summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Klocek <michal.klocek@qt.io>2018-12-19 15:12:30 +0100
committerMichal Klocek <michal.klocek@qt.io>2018-12-20 11:58:01 +0000
commit4010e56ec0c7929764779376d99c6b2eeb2cbe53 (patch)
tree6d19f194a9cd651482f75469969ea57888e1ff91
parentf97a65ce1568d842d9a3eeaedd32bf46b45d9538 (diff)
downloadqtwebengine-chromium-4010e56ec0c7929764779376d99c6b2eeb2cbe53.tar.gz
Minor. Remove old src version of sqlite
Remove old sqlite source code to avoid future misreference (src is using currently sqlite-src-3250200) Task-number: QTBUG-72632 Change-Id: I0300f4ff1b458d4e35e5eb01cc10603fbcc042f8 Reviewed-by: Kai Koehne <kai.koehne@qt.io>
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/Makefile.in1402
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/Makefile.linux-gcc123
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/Makefile.msc2482
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/README.md302
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/VERSION1
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/aclocal.m47972
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.eps5333
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.icobin2238 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.jpgbin80726 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/INSTALL370
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.am21
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.fallback19
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.msc1010
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/README.first11
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/README.txt113
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/configure.ac212
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/Makefile.in440
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/README36
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/aclocal.m49
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/configure.ac201
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/doc/sqlite3.n15
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/license.terms6
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/pkgIndex.tcl.in7
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/tclconfig/install-sh528
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/tclconfig/tcl.m44168
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/makefile.vc414
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/nmakehlp.c694
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/rules.vc711
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/config.guess1535
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/config.h.in131
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/config.sub1644
-rwxr-xr-xchromium/third_party/sqlite/sqlite-src-3240000/configure13923
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/configure.ac757
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/contrib/sqlitecon.tcl679
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/doc/lemon.html1061
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/doc/pager-invariants.txt76
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/doc/vfs-shm.txt130
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/README.md8
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/async/README.txt170
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/async/sqlite3async.c1707
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/async/sqlite3async.h223
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/README.md83
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/expert.c156
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/expert1.test382
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/sqlite3expert.c1952
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/sqlite3expert.h168
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/test_expert.c220
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/README.txt2
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/ft_hash.c404
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/ft_hash.h111
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1.c3348
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1.h11
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_hash.c369
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_hash.h112
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_porter.c643
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_tokenizer.h90
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_tokenizer1.c221
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fulltext.c1511
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fulltext.h11
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/simple_tokenizer.c174
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/tokenizer.h89
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/README.tokenizers133
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/README.txt4
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2.c6860
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2.h26
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_hash.c376
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_hash.h110
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_icu.c260
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_porter.c644
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer.c375
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer.h145
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer1.c233
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/mkfts2amal.tcl116
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.content178
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.syntax209
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.tokenizers133
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.txt4
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3.c5959
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3.h26
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3Int.h619
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_aux.c550
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_expr.c1292
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_hash.c383
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_hash.h112
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_icu.c262
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_porter.c662
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_snippet.c1706
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_term.c373
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_test.c592
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenize_vtab.c454
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer.c516
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer.h161
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer1.c234
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_unicode.c393
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_unicode2.c364
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_write.c5685
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3speed.tcl122
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/mkfts3amal.tcl115
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/tool/fts3cov.sh16
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/tool/fts3view.c875
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/CaseFolding.txt1224
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/UnicodeData.txt24428
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/mkunicode.tcl694
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/parseunicode.tcl146
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/extract_api_docs.tcl252
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5.h579
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5Int.h794
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_aux.c714
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_buffer.c394
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_config.c961
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_expr.c2842
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_hash.c537
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_index.c6505
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_main.c2752
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_storage.c1132
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_tcl.c1154
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_test_mi.c421
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_test_tok.c482
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_tokenize.c1242
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_unicode2.c360
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_varint.c345
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_vocab.c764
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5parse.y197
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/mkportersteps.tcl222
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/fts5speed.tcl64
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/fts5txt2db.tcl229
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/loadfts5.tcl172
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/mkfts5c.tcl113
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/showfts5.tcl97
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/README.txt169
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/icu.c553
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/sqliteicu.h27
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/Makefile56
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/Makefile.msc102
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/README40
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest.h303
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest1.c654
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest2.c488
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest3.c238
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest4.c127
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest5.c633
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest6.c661
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest7.c206
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest8.c326
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest9.c143
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_bt.c75
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_datasource.c96
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_func.c177
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_io.c248
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_main.c1548
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_mem.c409
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb.c846
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb.h174
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb2.cc370
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb3.c1402
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb4.c982
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_util.c223
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_win32.c30
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm.h684
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsmInt.h993
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_ckpt.c1239
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_file.c3312
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_log.c1156
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_main.c1008
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_mem.c104
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_mutex.c88
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_shared.c1976
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_sorted.c6187
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_str.c148
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_tree.c2465
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_unix.c746
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_varint.c196
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_vtab.c1079
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_win32.c1063
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/tool/mklsm1c.tcl88
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/README.md60
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/amatch.c1499
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/anycollseq.c58
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/appendvfs.c565
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/btreeinfo.c428
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/carray.c406
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/closure.c964
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/completion.c500
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/compress.c129
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/csv.c887
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/dbdump.c716
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/eval.c123
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/fileio.c926
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/fuzzer.c1185
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/ieee754.c131
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/json1.c2427
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/memvfs.c574
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/mmapwarm.c108
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/nextchar.c311
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/normalize.c707
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/percentile.c219
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/regexp.c760
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/remember.c72
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/rot13.c114
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/scrub.c610
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/series.c423
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/sha1.c407
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/shathree.c714
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/showauth.c103
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/spellfix.c3058
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/sqlar.c121
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/stmt.c298
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/templatevtab.c267
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/totype.c512
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/unionvtab.c1381
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vfslog.c759
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vfsstat.c816
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vtablog.c509
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vtshim.c553
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/wholenumber.c274
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/zipfile.c2177
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/zorder.c102
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu.c188
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu1.test673
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu10.test188
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu11.test198
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu12.test235
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu13.test65
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu14.test95
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu3.test207
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu5.test306
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu6.test103
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu7.test110
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu8.test75
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu9.test128
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuA.test83
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuB.test62
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuC.test142
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu_common.tcl109
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucollate.test63
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucrash.test148
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucrash2.test106
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbudiff.test303
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbudor.test59
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault.test237
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault2.test58
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault3.test98
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault4.test66
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufts.test134
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbumulti.test175
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuprogress.test419
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rburesume.test254
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbusave.test105
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbusplit.test95
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbutemplimit.test129
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuvacuum.test400
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuvacuum2.test235
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/sqlite3rbu.c4888
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/sqlite3rbu.h601
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/test_rbu.c390
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/README.md16
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/checkfreelist.c299
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/checkindex.c927
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/sqlite3_checker.c.in86
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/sqlite3_checker.tcl264
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/README120
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree.c4394
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree.h30
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree1.test651
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree2.test146
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree3.test266
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree4.test254
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree5.test83
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree6.test168
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree7.test73
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree8.test207
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree9.test129
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeA.test261
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeB.test50
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeC.test378
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeD.test55
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeE.test143
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeF.test84
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeG.test69
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeH.test80
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree_perf.tcl74
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree_util.tcl197
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreecheck.test158
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeconnect.test56
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/sqlite3rtree.h117
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/tkt3363.test50
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/viewrtree.tcl188
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/changeset.c416
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session1.test662
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session2.test591
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session3.test214
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session4.test146
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session5.test408
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session6.test90
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session8.test91
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session9.test287
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionA.test106
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionB.test508
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionC.test198
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionD.test258
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionE.test115
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionF.test295
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionG.test251
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionH.test39
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session_common.tcl198
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session_speed_test.c360
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionat.test249
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessiondiff.test114
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionfault.test589
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionfault2.test285
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionrebase.test477
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionstat1.test311
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionwor.test57
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sqlite3session.c5377
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sqlite3session.h1583
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/session/test_session.c1231
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/sqlite3userauth.h96
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/user-auth.txt164
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/userauth.c355
-rwxr-xr-xchromium/third_party/sqlite/sqlite-src-3240000/install-sh251
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/ltmain.sh8461
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/magic.txt32
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/main.mk1080
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/manifest1740
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/manifest.uuid1
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/mkso.sh32
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/mptest/config01.test46
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/mptest/config02.test123
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/mptest/crash01.test106
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/mptest/crash02.subtest53
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/mptest/mptest.c1470
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/mptest/multiwrite01.test415
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/spec.template67
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/sqlite.pc.in13
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/sqlite3.1286
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/sqlite3.pc.in13
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/alter.c808
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/analyze.c1936
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/attach.c624
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/auth.c271
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/backup.c800
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/bitvec.c411
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/btmutex.c308
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/btree.c10143
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/btree.h390
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/btreeInt.h704
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/build.c4495
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/callback.c488
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/complete.c290
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/ctime.c755
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/date.c1249
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/dbpage.c411
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/dbstat.c705
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/delete.c950
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/expr.c5519
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/fault.c87
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/fkey.c1428
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/func.c1910
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/global.c304
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/hash.c269
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/hash.h96
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/hwtime.h85
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/in-operator.md107
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/insert.c2450
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/legacy.c142
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/loadext.c816
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/main.c4258
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/malloc.c715
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mem0.c59
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mem1.c291
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mem2.c528
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mem3.c687
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mem5.c576
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/memdb.c589
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/memjournal.c434
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/msvc.h36
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mutex.c360
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mutex.h70
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_noop.c215
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_unix.c394
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_w32.c399
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/notify.c332
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/os.c420
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/os.h212
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/os_common.h105
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/os_setup.h57
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/os_unix.c7788
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/os_win.c6105
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/os_win.h88
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/pager.c7660
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/pager.h245
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/parse.y1572
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/pcache.c871
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/pcache.h186
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/pcache1.c1258
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/pragma.c2488
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/pragma.h649
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/prepare.c906
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/printf.c1242
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/random.c134
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/resolve.c1583
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/rowset.c498
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/select.c6352
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/shell.c.in8787
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite.h.in9148
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite3.rc83
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite3ext.h615
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/sqliteInt.h4491
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/sqliteLimit.h211
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/status.c380
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/table.c198
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/tclsqlite.c3776
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test1.c7892
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test2.c752
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test3.c690
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test4.c726
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test5.c220
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test6.c1103
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test7.c718
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test8.c1444
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test9.c204
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_async.c248
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_autoext.c228
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_backup.c157
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_bestindex.c620
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_blob.c330
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_btree.c66
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_config.c820
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_delete.c156
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_demovfs.c686
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_devsym.c524
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_fs.c925
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_func.c933
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_hexio.c392
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_init.c295
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_intarray.c389
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_intarray.h128
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_journal.c869
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_loadext.c128
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_malloc.c1546
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_md5.c450
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_multiplex.c1320
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_multiplex.h99
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_mutex.c510
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_onefile.c830
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_osinst.c1224
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_pcache.c467
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_quota.c1979
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_quota.h268
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_rtree.c511
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_schema.c366
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_server.c516
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_sqllog.c556
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_superlock.c363
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_syscall.c765
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_tclsh.c201
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_tclvar.c562
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_thread.c651
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_vfs.c1545
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_vfstrace.c892
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_windirent.c191
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_windirent.h159
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/test_wsd.c84
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/threads.c274
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/tokenize.c616
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/treeview.c573
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/trigger.c1144
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/update.c946
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/upsert.c250
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/utf.c532
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/util.c1624
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vacuum.c377
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbe.c7375
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbe.h345
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeInt.h566
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeapi.c1958
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeaux.c4848
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeblob.c507
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbemem.c1840
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbesort.c2750
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vdbetrace.c194
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vtab.c1246
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/vxworks.h32
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/wal.c3795
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/wal.h148
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/walker.c159
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/where.c5217
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/whereInt.h557
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/wherecode.c2234
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/src/whereexpr.c1531
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/GetFile.cs450
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/GetTclKit.bat299
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/Replace.cs223
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/addopcodes.tcl64
-rwxr-xr-xchromium/third_party/sqlite/sqlite-src-3240000/tool/build-all-msvc.bat859
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/build-shell.sh22
-rwxr-xr-xchromium/third_party/sqlite/sqlite-src-3240000/tool/cg_anno.tcl77
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/checkSpacing.c84
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/dbhash.c506
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/extract.c46
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/fast_vacuum.c234
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/fragck.tcl149
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/fuzzershell.c1262
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/genfkey.README137
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/genfkey.test354
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/getlock.c134
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/kvtest-speed.sh35
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/lemon.c5618
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/lempar.c1059
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/libvers.c15
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/loadfts.c242
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/logest.c170
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/max-limits.c41
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkautoconfamal.sh92
-rwxr-xr-xchromium/third_party/sqlite/sqlite-src-3240000/tool/mkccode.tcl93
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkctimec.tcl311
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkkeywordhash.c632
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkmsvcmin.tcl112
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopcodec.tcl50
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopcodeh.tcl270
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopts.tcl51
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkpragmatab.tcl589
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkshellc.tcl66
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mksourceid.c853
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkspeedsql.tcl237
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3c-noext.tcl366
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3c.tcl438
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3h.tcl155
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3internalh.tcl148
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/mkvsix.tcl840
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/offsets.c329
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/omittest.tcl307
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/opcodesum.tcl34
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/pagesig.c92
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/replace.tcl23
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/restore_jrnl.tcl233
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/rollback-test.c155
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/run-speed-test.sh90
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/showdb.c1179
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/showjournal.c138
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/showlocks.c64
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/showshm.c158
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/showstat4.c163
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/showwal.c608
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/soak1.tcl103
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/spaceanal.tcl891
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/speed-check.sh188
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest.tcl275
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest16.c171
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest2.tcl207
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest8.c260
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest8inst1.c218
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/split-sqlite3c.tcl84
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/sqldiff.c2006
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/sqlite3_analyzer.c.in29
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/sqltclsh.c.in51
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/sqltclsh.tcl71
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/srcck1.c158
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/stack_usage.tcl98
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/symbols-mingw.sh33
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/symbols.sh34
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/varint.c123
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/vdbe-compress.tcl143
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/vdbe_profile.tcl90
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/warnings-clang.sh14
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/warnings.sh60
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/tool/win/sqlite.vsixbin32825 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml8
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml.cpp120
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml.h27
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/LockScreenLogo.scale-200.pngbin1430 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/SplashScreen.scale-200.pngbin7700 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square150x150Logo.scale-200.pngbin2937 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square44x44Logo.scale-200.pngbin1647 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.pngbin1255 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/StoreLogo.pngbin1451 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Wide310x150Logo.scale-200.pngbin3204 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml13
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml.cpp53
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml.h22
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Package.appxmanifest49
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/pch.cpp6
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/pch.h11
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.sln39
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.tcl373
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.vcxproj.data198
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.vcxproj.filters57
-rw-r--r--chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest_TemporaryKey.pfxbin2520 -> 0 bytes
588 files changed, 0 insertions, 476475 deletions
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.in b/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.in
deleted file mode 100644
index ac84fe832cb..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.in
+++ /dev/null
@@ -1,1402 +0,0 @@
-#!/usr/make
-#
-# Makefile for SQLITE
-#
-# This makefile is suppose to be configured automatically using the
-# autoconf. But if that does not work for you, you can configure
-# the makefile manually. Just set the parameters below to values that
-# work well for your system.
-#
-# If the configure script does not work out-of-the-box, you might
-# be able to get it to work by giving it some hints. See the comment
-# at the beginning of configure.in for additional information.
-#
-
-# The toplevel directory of the source tree. This is the directory
-# that contains this "Makefile.in" and the "configure.in" script.
-#
-TOP = @abs_srcdir@
-
-# C Compiler and options for use in building executables that
-# will run on the platform that is doing the build.
-#
-BCC = @BUILD_CC@ @BUILD_CFLAGS@
-
-# TCC is the C Compile and options for use in building executables that
-# will run on the target platform. (BCC and TCC are usually the
-# same unless your are cross-compiling.) Separate CC and CFLAGS macros
-# are provide so that these aspects of the build process can be changed
-# on the "make" command-line. Ex: "make CC=clang CFLAGS=-fsanitize=undefined"
-#
-CC = @CC@
-CFLAGS = @CPPFLAGS@ @CFLAGS@
-TCC = ${CC} ${CFLAGS} -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/icu
-TCC += -I${TOP}/ext/fts3 -I${TOP}/ext/async -I${TOP}/ext/session
-
-# Define this for the autoconf-based build, so that the code knows it can
-# include the generated config.h
-#
-TCC += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite
-
-# Define -DNDEBUG to compile without debugging (i.e., for production usage)
-# Omitting the define will cause extra debugging code to be inserted and
-# includes extra comments when "EXPLAIN stmt" is used.
-#
-TCC += @TARGET_DEBUG@
-
-# Compiler options needed for programs that use the TCL library.
-#
-TCC += @TCL_INCLUDE_SPEC@
-
-# The library that programs using TCL must link against.
-#
-LIBTCL = @TCL_LIB_SPEC@
-
-# Compiler options needed for programs that use the readline() library.
-#
-READLINE_FLAGS = -DHAVE_READLINE=@TARGET_HAVE_READLINE@ @TARGET_READLINE_INC@
-READLINE_FLAGS += -DHAVE_EDITLINE=@TARGET_HAVE_EDITLINE@
-
-# The library that programs using readline() must link against.
-#
-LIBREADLINE = @TARGET_READLINE_LIBS@
-
-# Should the database engine be compiled threadsafe
-#
-TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@
-
-# Any target libraries which libsqlite must be linked against
-#
-TLIBS = @LIBS@ $(LIBS)
-
-# Flags controlling use of the in memory btree implementation
-#
-# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
-# default to file, 2 to default to memory, and 3 to force temporary
-# tables to always be in memory.
-#
-TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@
-
-# Enable/disable loadable extensions, and other optional features
-# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
-# The same set of OMIT and ENABLE flags should be passed to the
-# LEMON parser generator and the mkkeywordhash tool as well.
-OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
-
-TCC += $(OPT_FEATURE_FLAGS)
-
-# Add in any optional parameters specified on the make commane line
-# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
-TCC += $(OPTS)
-
-# Add in compile-time options for some libraries used by extensions
-TCC += @HAVE_ZLIB@
-
-# Version numbers and release number for the SQLite being compiled.
-#
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-RELEASE = @RELEASE@
-
-# Filename extensions
-#
-BEXE = @BUILD_EXEEXT@
-TEXE = @TARGET_EXEEXT@
-
-# The following variable is "1" if the configure script was able to locate
-# the tclConfig.sh file. It is an empty string otherwise. When this
-# variable is "1", the TCL extension library (libtclsqlite3.so) is built
-# and installed.
-#
-HAVE_TCL = @HAVE_TCL@
-
-# This is the command to use for tclsh - normally just "tclsh", but we may
-# know the specific version we want to use
-#
-TCLSH_CMD = @TCLSH_CMD@
-
-# Where do we want to install the tcl plugin
-#
-TCLLIBDIR = @TCLLIBDIR@
-
-# The suffix used on shared libraries. Ex: ".dll", ".so", ".dylib"
-#
-SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
-
-# If gcov support was enabled by the configure script, add the appropriate
-# flags here. It's not always as easy as just having the user add the right
-# CFLAGS / LDFLAGS, because libtool wants to use CFLAGS when linking, which
-# causes build errors with -fprofile-arcs -ftest-coverage with some GCCs.
-# Supposedly GCC does the right thing if you use --coverage, but in
-# practice it still fails. See:
-#
-# http://www.mail-archive.com/debian-gcc@lists.debian.org/msg26197.html
-#
-# for more info.
-#
-GCOV_CFLAGS1 = -DSQLITE_COVERAGE_TEST=1 -fprofile-arcs -ftest-coverage
-GCOV_LDFLAGS1 = -lgcov
-USE_GCOV = @USE_GCOV@
-LTCOMPILE_EXTRAS += $(GCOV_CFLAGS$(USE_GCOV))
-LTLINK_EXTRAS += $(GCOV_LDFLAGS$(USE_GCOV))
-
-
-# The directory into which to store package information for
-
-# Some standard variables and programs
-#
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-libdir = @libdir@
-pkgconfigdir = $(libdir)/pkgconfig
-bindir = @bindir@
-includedir = @includedir@
-INSTALL = @INSTALL@
-LIBTOOL = ./libtool
-ALLOWRELEASE = @ALLOWRELEASE@
-
-# libtool compile/link/install
-LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(TCC) $(LTCOMPILE_EXTRAS)
-LTLINK = $(LIBTOOL) --mode=link $(TCC) $(LTCOMPILE_EXTRAS) @LDFLAGS@ $(LTLINK_EXTRAS)
-LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL)
-
-# You should not have to change anything below this line
-###############################################################################
-
-USE_AMALGAMATION = @USE_AMALGAMATION@
-
-# Object files for the SQLite library (non-amalgamation).
-#
-LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
- backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
- callback.lo complete.lo ctime.lo \
- date.lo dbpage.lo dbstat.lo delete.lo \
- expr.lo fault.lo fkey.lo \
- fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
- fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
- fts3_tokenize_vtab.lo \
- fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
- fts5.lo \
- func.lo global.lo hash.lo \
- icu.lo insert.lo json1.lo legacy.lo loadext.lo \
- main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
- memdb.lo memjournal.lo \
- mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
- notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
- pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
- random.lo resolve.lo rowset.lo rtree.lo \
- sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
- table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
- update.lo upsert.lo util.lo vacuum.lo \
- vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
- vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
- utf.lo vtab.lo
-
-# Object files for the amalgamation.
-#
-LIBOBJS1 = sqlite3.lo
-
-# Determine the real value of LIBOBJ based on the 'configure' script
-#
-LIBOBJ = $(LIBOBJS$(USE_AMALGAMATION))
-
-
-# All of the source code files.
-#
-SRC = \
- $(TOP)/src/alter.c \
- $(TOP)/src/analyze.c \
- $(TOP)/src/attach.c \
- $(TOP)/src/auth.c \
- $(TOP)/src/backup.c \
- $(TOP)/src/bitvec.c \
- $(TOP)/src/btmutex.c \
- $(TOP)/src/btree.c \
- $(TOP)/src/btree.h \
- $(TOP)/src/btreeInt.h \
- $(TOP)/src/build.c \
- $(TOP)/src/callback.c \
- $(TOP)/src/complete.c \
- $(TOP)/src/ctime.c \
- $(TOP)/src/date.c \
- $(TOP)/src/dbpage.c \
- $(TOP)/src/dbstat.c \
- $(TOP)/src/delete.c \
- $(TOP)/src/expr.c \
- $(TOP)/src/fault.c \
- $(TOP)/src/fkey.c \
- $(TOP)/src/func.c \
- $(TOP)/src/global.c \
- $(TOP)/src/hash.c \
- $(TOP)/src/hash.h \
- $(TOP)/src/hwtime.h \
- $(TOP)/src/insert.c \
- $(TOP)/src/legacy.c \
- $(TOP)/src/loadext.c \
- $(TOP)/src/main.c \
- $(TOP)/src/malloc.c \
- $(TOP)/src/mem0.c \
- $(TOP)/src/mem1.c \
- $(TOP)/src/mem2.c \
- $(TOP)/src/mem3.c \
- $(TOP)/src/mem5.c \
- $(TOP)/src/memdb.c \
- $(TOP)/src/memjournal.c \
- $(TOP)/src/msvc.h \
- $(TOP)/src/mutex.c \
- $(TOP)/src/mutex.h \
- $(TOP)/src/mutex_noop.c \
- $(TOP)/src/mutex_unix.c \
- $(TOP)/src/mutex_w32.c \
- $(TOP)/src/notify.c \
- $(TOP)/src/os.c \
- $(TOP)/src/os.h \
- $(TOP)/src/os_common.h \
- $(TOP)/src/os_setup.h \
- $(TOP)/src/os_unix.c \
- $(TOP)/src/os_win.c \
- $(TOP)/src/os_win.h \
- $(TOP)/src/pager.c \
- $(TOP)/src/pager.h \
- $(TOP)/src/parse.y \
- $(TOP)/src/pcache.c \
- $(TOP)/src/pcache.h \
- $(TOP)/src/pcache1.c \
- $(TOP)/src/pragma.c \
- $(TOP)/src/pragma.h \
- $(TOP)/src/prepare.c \
- $(TOP)/src/printf.c \
- $(TOP)/src/random.c \
- $(TOP)/src/resolve.c \
- $(TOP)/src/rowset.c \
- $(TOP)/src/select.c \
- $(TOP)/src/status.c \
- $(TOP)/src/shell.c.in \
- $(TOP)/src/sqlite.h.in \
- $(TOP)/src/sqlite3ext.h \
- $(TOP)/src/sqliteInt.h \
- $(TOP)/src/sqliteLimit.h \
- $(TOP)/src/table.c \
- $(TOP)/src/tclsqlite.c \
- $(TOP)/src/threads.c \
- $(TOP)/src/tokenize.c \
- $(TOP)/src/treeview.c \
- $(TOP)/src/trigger.c \
- $(TOP)/src/utf.c \
- $(TOP)/src/update.c \
- $(TOP)/src/upsert.c \
- $(TOP)/src/util.c \
- $(TOP)/src/vacuum.c \
- $(TOP)/src/vdbe.c \
- $(TOP)/src/vdbe.h \
- $(TOP)/src/vdbeapi.c \
- $(TOP)/src/vdbeaux.c \
- $(TOP)/src/vdbeblob.c \
- $(TOP)/src/vdbemem.c \
- $(TOP)/src/vdbesort.c \
- $(TOP)/src/vdbetrace.c \
- $(TOP)/src/vdbeInt.h \
- $(TOP)/src/vtab.c \
- $(TOP)/src/vxworks.h \
- $(TOP)/src/wal.c \
- $(TOP)/src/wal.h \
- $(TOP)/src/walker.c \
- $(TOP)/src/where.c \
- $(TOP)/src/wherecode.c \
- $(TOP)/src/whereexpr.c \
- $(TOP)/src/whereInt.h
-
-# Source code for extensions
-#
-SRC += \
- $(TOP)/ext/fts1/fts1.c \
- $(TOP)/ext/fts1/fts1.h \
- $(TOP)/ext/fts1/fts1_hash.c \
- $(TOP)/ext/fts1/fts1_hash.h \
- $(TOP)/ext/fts1/fts1_porter.c \
- $(TOP)/ext/fts1/fts1_tokenizer.h \
- $(TOP)/ext/fts1/fts1_tokenizer1.c
-SRC += \
- $(TOP)/ext/fts2/fts2.c \
- $(TOP)/ext/fts2/fts2.h \
- $(TOP)/ext/fts2/fts2_hash.c \
- $(TOP)/ext/fts2/fts2_hash.h \
- $(TOP)/ext/fts2/fts2_icu.c \
- $(TOP)/ext/fts2/fts2_porter.c \
- $(TOP)/ext/fts2/fts2_tokenizer.h \
- $(TOP)/ext/fts2/fts2_tokenizer.c \
- $(TOP)/ext/fts2/fts2_tokenizer1.c
-SRC += \
- $(TOP)/ext/fts3/fts3.c \
- $(TOP)/ext/fts3/fts3.h \
- $(TOP)/ext/fts3/fts3Int.h \
- $(TOP)/ext/fts3/fts3_aux.c \
- $(TOP)/ext/fts3/fts3_expr.c \
- $(TOP)/ext/fts3/fts3_hash.c \
- $(TOP)/ext/fts3/fts3_hash.h \
- $(TOP)/ext/fts3/fts3_icu.c \
- $(TOP)/ext/fts3/fts3_porter.c \
- $(TOP)/ext/fts3/fts3_snippet.c \
- $(TOP)/ext/fts3/fts3_tokenizer.h \
- $(TOP)/ext/fts3/fts3_tokenizer.c \
- $(TOP)/ext/fts3/fts3_tokenizer1.c \
- $(TOP)/ext/fts3/fts3_tokenize_vtab.c \
- $(TOP)/ext/fts3/fts3_unicode.c \
- $(TOP)/ext/fts3/fts3_unicode2.c \
- $(TOP)/ext/fts3/fts3_write.c
-SRC += \
- $(TOP)/ext/icu/sqliteicu.h \
- $(TOP)/ext/icu/icu.c
-SRC += \
- $(TOP)/ext/rtree/rtree.h \
- $(TOP)/ext/rtree/rtree.c
-SRC += \
- $(TOP)/ext/session/sqlite3session.c \
- $(TOP)/ext/session/sqlite3session.h
-SRC += \
- $(TOP)/ext/rbu/sqlite3rbu.h \
- $(TOP)/ext/rbu/sqlite3rbu.c
-SRC += \
- $(TOP)/ext/misc/json1.c \
- $(TOP)/ext/misc/stmt.c
-
-# Generated source code files
-#
-SRC += \
- keywordhash.h \
- opcodes.c \
- opcodes.h \
- parse.c \
- parse.h \
- config.h \
- shell.c \
- sqlite3.h
-
-# Source code to the test files.
-#
-TESTSRC = \
- $(TOP)/src/test1.c \
- $(TOP)/src/test2.c \
- $(TOP)/src/test3.c \
- $(TOP)/src/test4.c \
- $(TOP)/src/test5.c \
- $(TOP)/src/test6.c \
- $(TOP)/src/test7.c \
- $(TOP)/src/test8.c \
- $(TOP)/src/test9.c \
- $(TOP)/src/test_autoext.c \
- $(TOP)/src/test_async.c \
- $(TOP)/src/test_backup.c \
- $(TOP)/src/test_bestindex.c \
- $(TOP)/src/test_blob.c \
- $(TOP)/src/test_btree.c \
- $(TOP)/src/test_config.c \
- $(TOP)/src/test_delete.c \
- $(TOP)/src/test_demovfs.c \
- $(TOP)/src/test_devsym.c \
- $(TOP)/src/test_fs.c \
- $(TOP)/src/test_func.c \
- $(TOP)/src/test_hexio.c \
- $(TOP)/src/test_init.c \
- $(TOP)/src/test_intarray.c \
- $(TOP)/src/test_journal.c \
- $(TOP)/src/test_malloc.c \
- $(TOP)/src/test_md5.c \
- $(TOP)/src/test_multiplex.c \
- $(TOP)/src/test_mutex.c \
- $(TOP)/src/test_onefile.c \
- $(TOP)/src/test_osinst.c \
- $(TOP)/src/test_pcache.c \
- $(TOP)/src/test_quota.c \
- $(TOP)/src/test_rtree.c \
- $(TOP)/src/test_schema.c \
- $(TOP)/src/test_server.c \
- $(TOP)/src/test_superlock.c \
- $(TOP)/src/test_syscall.c \
- $(TOP)/src/test_tclsh.c \
- $(TOP)/src/test_tclvar.c \
- $(TOP)/src/test_thread.c \
- $(TOP)/src/test_vfs.c \
- $(TOP)/src/test_windirent.c \
- $(TOP)/src/test_wsd.c \
- $(TOP)/ext/fts3/fts3_term.c \
- $(TOP)/ext/fts3/fts3_test.c \
- $(TOP)/ext/session/test_session.c \
- $(TOP)/ext/rbu/test_rbu.c
-
-# Statically linked extensions
-#
-TESTSRC += \
- $(TOP)/ext/expert/sqlite3expert.c \
- $(TOP)/ext/expert/test_expert.c \
- $(TOP)/ext/misc/amatch.c \
- $(TOP)/ext/misc/carray.c \
- $(TOP)/ext/misc/closure.c \
- $(TOP)/ext/misc/csv.c \
- $(TOP)/ext/misc/eval.c \
- $(TOP)/ext/misc/fileio.c \
- $(TOP)/ext/misc/fuzzer.c \
- $(TOP)/ext/fts5/fts5_tcl.c \
- $(TOP)/ext/fts5/fts5_test_mi.c \
- $(TOP)/ext/fts5/fts5_test_tok.c \
- $(TOP)/ext/misc/ieee754.c \
- $(TOP)/ext/misc/mmapwarm.c \
- $(TOP)/ext/misc/nextchar.c \
- $(TOP)/ext/misc/normalize.c \
- $(TOP)/ext/misc/percentile.c \
- $(TOP)/ext/misc/regexp.c \
- $(TOP)/ext/misc/remember.c \
- $(TOP)/ext/misc/series.c \
- $(TOP)/ext/misc/spellfix.c \
- $(TOP)/ext/misc/totype.c \
- $(TOP)/ext/misc/unionvtab.c \
- $(TOP)/ext/misc/wholenumber.c \
- $(TOP)/ext/misc/zipfile.c
-
-# Source code to the library files needed by the test fixture
-#
-TESTSRC2 = \
- $(TOP)/src/attach.c \
- $(TOP)/src/backup.c \
- $(TOP)/src/bitvec.c \
- $(TOP)/src/btree.c \
- $(TOP)/src/build.c \
- $(TOP)/src/ctime.c \
- $(TOP)/src/date.c \
- $(TOP)/src/dbpage.c \
- $(TOP)/src/dbstat.c \
- $(TOP)/src/expr.c \
- $(TOP)/src/func.c \
- $(TOP)/src/insert.c \
- $(TOP)/src/wal.c \
- $(TOP)/src/main.c \
- $(TOP)/src/mem5.c \
- $(TOP)/src/os.c \
- $(TOP)/src/os_unix.c \
- $(TOP)/src/os_win.c \
- $(TOP)/src/pager.c \
- $(TOP)/src/pragma.c \
- $(TOP)/src/prepare.c \
- $(TOP)/src/printf.c \
- $(TOP)/src/random.c \
- $(TOP)/src/pcache.c \
- $(TOP)/src/pcache1.c \
- $(TOP)/src/select.c \
- $(TOP)/src/tokenize.c \
- $(TOP)/src/utf.c \
- $(TOP)/src/util.c \
- $(TOP)/src/vdbeapi.c \
- $(TOP)/src/vdbeaux.c \
- $(TOP)/src/vdbe.c \
- $(TOP)/src/vdbemem.c \
- $(TOP)/src/vdbetrace.c \
- $(TOP)/src/where.c \
- $(TOP)/src/wherecode.c \
- $(TOP)/src/whereexpr.c \
- parse.c \
- $(TOP)/ext/fts3/fts3.c \
- $(TOP)/ext/fts3/fts3_aux.c \
- $(TOP)/ext/fts3/fts3_expr.c \
- $(TOP)/ext/fts3/fts3_term.c \
- $(TOP)/ext/fts3/fts3_tokenizer.c \
- $(TOP)/ext/fts3/fts3_write.c \
- $(TOP)/ext/async/sqlite3async.c \
- $(TOP)/ext/session/sqlite3session.c \
- $(TOP)/ext/misc/stmt.c
-
-# Header files used by all library source files.
-#
-HDR = \
- $(TOP)/src/btree.h \
- $(TOP)/src/btreeInt.h \
- $(TOP)/src/hash.h \
- $(TOP)/src/hwtime.h \
- keywordhash.h \
- $(TOP)/src/msvc.h \
- $(TOP)/src/mutex.h \
- opcodes.h \
- $(TOP)/src/os.h \
- $(TOP)/src/os_common.h \
- $(TOP)/src/os_setup.h \
- $(TOP)/src/os_win.h \
- $(TOP)/src/pager.h \
- $(TOP)/src/pcache.h \
- parse.h \
- $(TOP)/src/pragma.h \
- sqlite3.h \
- $(TOP)/src/sqlite3ext.h \
- $(TOP)/src/sqliteInt.h \
- $(TOP)/src/sqliteLimit.h \
- $(TOP)/src/vdbe.h \
- $(TOP)/src/vdbeInt.h \
- $(TOP)/src/vxworks.h \
- $(TOP)/src/whereInt.h \
- config.h
-
-# Header files used by extensions
-#
-EXTHDR += \
- $(TOP)/ext/fts1/fts1.h \
- $(TOP)/ext/fts1/fts1_hash.h \
- $(TOP)/ext/fts1/fts1_tokenizer.h
-EXTHDR += \
- $(TOP)/ext/fts2/fts2.h \
- $(TOP)/ext/fts2/fts2_hash.h \
- $(TOP)/ext/fts2/fts2_tokenizer.h
-EXTHDR += \
- $(TOP)/ext/fts3/fts3.h \
- $(TOP)/ext/fts3/fts3Int.h \
- $(TOP)/ext/fts3/fts3_hash.h \
- $(TOP)/ext/fts3/fts3_tokenizer.h
-EXTHDR += \
- $(TOP)/ext/rtree/rtree.h
-EXTHDR += \
- $(TOP)/ext/icu/sqliteicu.h
-EXTHDR += \
- $(TOP)/ext/rtree/sqlite3rtree.h
-
-# executables needed for testing
-#
-TESTPROGS = \
- testfixture$(TEXE) \
- sqlite3$(TEXE) \
- sqlite3_analyzer$(TEXE) \
- sqldiff$(TEXE) \
- dbhash$(TEXE) \
- sqltclsh$(TEXE)
-
-# Databases containing fuzzer test cases
-#
-FUZZDATA = \
- $(TOP)/test/fuzzdata1.db \
- $(TOP)/test/fuzzdata2.db \
- $(TOP)/test/fuzzdata3.db \
- $(TOP)/test/fuzzdata4.db \
- $(TOP)/test/fuzzdata5.db \
- $(TOP)/test/fuzzdata6.db
-
-# Standard options to testfixture
-#
-TESTOPTS = --verbose=file --output=test-out.txt
-
-# Extra compiler options for various shell tools
-#
-SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
-#SHELL_OPT += -DSQLITE_ENABLE_FTS5
-SHELL_OPT += -DSQLITE_ENABLE_RTREE
-SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
-SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
-SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
-SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
-SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
-SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
-SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
-FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
-FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
-FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
-FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
-DBFUZZ_OPT =
-
-# This is the default Makefile target. The objects listed here
-# are what get build when you type just "make" with no arguments.
-#
-all: sqlite3.h libsqlite3.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la)
-
-Makefile: $(TOP)/Makefile.in
- ./config.status
-
-sqlite3.pc: $(TOP)/sqlite3.pc.in
- ./config.status
-
-libsqlite3.la: $(LIBOBJ)
- $(LTLINK) -no-undefined -o $@ $(LIBOBJ) $(TLIBS) \
- ${ALLOWRELEASE} -rpath "$(libdir)" -version-info "8:6:8"
-
-libtclsqlite3.la: tclsqlite.lo libsqlite3.la
- $(LTLINK) -no-undefined -o $@ tclsqlite.lo \
- libsqlite3.la @TCL_STUB_LIB_SPEC@ $(TLIBS) \
- -rpath "$(TCLLIBDIR)" \
- -version-info "8:6:8" \
- -avoid-version
-
-sqlite3$(TEXE): shell.c sqlite3.c
- $(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \
- shell.c sqlite3.c \
- $(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
-
-sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.lo sqlite3.h
- $(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.lo $(TLIBS)
-
-dbhash$(TEXE): $(TOP)/tool/dbhash.c sqlite3.lo sqlite3.h
- $(LTLINK) -o $@ $(TOP)/tool/dbhash.c sqlite3.lo $(TLIBS)
-
-scrub$(TEXE): $(TOP)/ext/misc/scrub.c sqlite3.lo
- $(LTLINK) -o $@ -I. -DSCRUB_STANDALONE \
- $(TOP)/ext/misc/scrub.c sqlite3.lo $(TLIBS)
-
-srcck1$(BEXE): $(TOP)/tool/srcck1.c
- $(BCC) -o srcck1$(BEXE) $(TOP)/tool/srcck1.c
-
-sourcetest: srcck1$(BEXE) sqlite3.c
- ./srcck1 sqlite3.c
-
-fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
- $(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
- $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
-
-fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h
- $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS)
-
-ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
- $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \
- $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
-
-sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
- $(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
-
-dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
- $(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
-
-mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c
- $(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
- $(TLIBS) -rpath "$(libdir)"
-
-MPTEST1=./mptester$(TEXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
-MPTEST2=./mptester$(TEXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
-mptest: mptester$(TEXE)
- rm -f mptest.db
- $(MPTEST1) --journalmode DELETE
- $(MPTEST2) --journalmode WAL
- $(MPTEST1) --journalmode WAL
- $(MPTEST2) --journalmode PERSIST
- $(MPTEST1) --journalmode PERSIST
- $(MPTEST2) --journalmode TRUNCATE
- $(MPTEST1) --journalmode TRUNCATE
- $(MPTEST2) --journalmode DELETE
-
-
-# This target creates a directory named "tsrc" and fills it with
-# copies of all of the C source code and header files needed to
-# build on the target system. Some of the C source code and header
-# files are automatically generated. This target takes care of
-# all that automatic generation.
-#
-.target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl fts5.c
- rm -rf tsrc
- mkdir tsrc
- cp -f $(SRC) tsrc
- rm tsrc/sqlite.h.in tsrc/parse.y
- $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
- mv vdbe.new tsrc/vdbe.c
- cp fts5.c fts5.h tsrc
- touch .target_source
-
-sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl
- $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
- cp tsrc/sqlite3ext.h .
- cp $(TOP)/ext/session/sqlite3session.h .
-
-sqlite3ext.h: .target_source
- cp tsrc/sqlite3ext.h .
-
-tclsqlite3.c: sqlite3.c
- echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
- cat sqlite3.c >>tclsqlite3.c
- echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
- cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
-
-sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl
- $(TCLSH_CMD) $(TOP)/tool/split-sqlite3c.tcl
-
-# Rule to build the amalgamation
-#
-sqlite3.lo: sqlite3.c
- $(LTCOMPILE) $(TEMP_STORE) -c sqlite3.c
-
-# Rules to build the LEMON compiler generator
-#
-lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
- $(BCC) -o $@ $(TOP)/tool/lemon.c
- cp $(TOP)/tool/lempar.c .
-
-# Rules to build the program that generates the source-id
-#
-mksourceid$(BEXE): $(TOP)/tool/mksourceid.c
- $(BCC) -o $@ $(TOP)/tool/mksourceid.c
-
-# Rules to build individual *.o files from generated *.c files. This
-# applies to:
-#
-# parse.o
-# opcodes.o
-#
-parse.lo: parse.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c parse.c
-
-opcodes.lo: opcodes.c
- $(LTCOMPILE) $(TEMP_STORE) -c opcodes.c
-
-# Rules to build individual *.o files from files in the src directory.
-#
-alter.lo: $(TOP)/src/alter.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/alter.c
-
-analyze.lo: $(TOP)/src/analyze.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/analyze.c
-
-attach.lo: $(TOP)/src/attach.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/attach.c
-
-auth.lo: $(TOP)/src/auth.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/auth.c
-
-backup.lo: $(TOP)/src/backup.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/backup.c
-
-bitvec.lo: $(TOP)/src/bitvec.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/bitvec.c
-
-btmutex.lo: $(TOP)/src/btmutex.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/btmutex.c
-
-btree.lo: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/btree.c
-
-build.lo: $(TOP)/src/build.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/build.c
-
-callback.lo: $(TOP)/src/callback.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/callback.c
-
-complete.lo: $(TOP)/src/complete.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/complete.c
-
-ctime.lo: $(TOP)/src/ctime.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/ctime.c
-
-date.lo: $(TOP)/src/date.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/date.c
-
-dbpage.lo: $(TOP)/src/dbpage.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbpage.c
-
-dbstat.lo: $(TOP)/src/dbstat.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbstat.c
-
-delete.lo: $(TOP)/src/delete.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/delete.c
-
-expr.lo: $(TOP)/src/expr.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/expr.c
-
-fault.lo: $(TOP)/src/fault.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/fault.c
-
-fkey.lo: $(TOP)/src/fkey.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/fkey.c
-
-func.lo: $(TOP)/src/func.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/func.c
-
-global.lo: $(TOP)/src/global.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/global.c
-
-hash.lo: $(TOP)/src/hash.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/hash.c
-
-insert.lo: $(TOP)/src/insert.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/insert.c
-
-legacy.lo: $(TOP)/src/legacy.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/legacy.c
-
-loadext.lo: $(TOP)/src/loadext.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/loadext.c
-
-main.lo: $(TOP)/src/main.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c
-
-malloc.lo: $(TOP)/src/malloc.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/malloc.c
-
-mem0.lo: $(TOP)/src/mem0.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem0.c
-
-mem1.lo: $(TOP)/src/mem1.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem1.c
-
-mem2.lo: $(TOP)/src/mem2.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem2.c
-
-mem3.lo: $(TOP)/src/mem3.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem3.c
-
-mem5.lo: $(TOP)/src/mem5.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem5.c
-
-memdb.lo: $(TOP)/src/memdb.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memdb.c
-
-memjournal.lo: $(TOP)/src/memjournal.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memjournal.c
-
-mutex.lo: $(TOP)/src/mutex.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c
-
-mutex_noop.lo: $(TOP)/src/mutex_noop.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_noop.c
-
-mutex_unix.lo: $(TOP)/src/mutex_unix.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_unix.c
-
-mutex_w32.lo: $(TOP)/src/mutex_w32.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_w32.c
-
-notify.lo: $(TOP)/src/notify.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/notify.c
-
-pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pager.c
-
-pcache.lo: $(TOP)/src/pcache.c $(HDR) $(TOP)/src/pcache.h
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pcache.c
-
-pcache1.lo: $(TOP)/src/pcache1.c $(HDR) $(TOP)/src/pcache.h
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pcache1.c
-
-os.lo: $(TOP)/src/os.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os.c
-
-os_unix.lo: $(TOP)/src/os_unix.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_unix.c
-
-os_win.lo: $(TOP)/src/os_win.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_win.c
-
-pragma.lo: $(TOP)/src/pragma.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pragma.c
-
-prepare.lo: $(TOP)/src/prepare.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/prepare.c
-
-printf.lo: $(TOP)/src/printf.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/printf.c
-
-random.lo: $(TOP)/src/random.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/random.c
-
-resolve.lo: $(TOP)/src/resolve.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/resolve.c
-
-rowset.lo: $(TOP)/src/rowset.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/rowset.c
-
-select.lo: $(TOP)/src/select.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/select.c
-
-status.lo: $(TOP)/src/status.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/status.c
-
-table.lo: $(TOP)/src/table.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/table.c
-
-threads.lo: $(TOP)/src/threads.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/threads.c
-
-tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c
-
-treeview.lo: $(TOP)/src/treeview.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/treeview.c
-
-trigger.lo: $(TOP)/src/trigger.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/trigger.c
-
-update.lo: $(TOP)/src/update.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/update.c
-
-upsert.lo: $(TOP)/src/upsert.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/upsert.c
-
-utf.lo: $(TOP)/src/utf.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/utf.c
-
-util.lo: $(TOP)/src/util.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/util.c
-
-vacuum.lo: $(TOP)/src/vacuum.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vacuum.c
-
-vdbe.lo: $(TOP)/src/vdbe.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbe.c
-
-vdbeapi.lo: $(TOP)/src/vdbeapi.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbeapi.c
-
-vdbeaux.lo: $(TOP)/src/vdbeaux.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbeaux.c
-
-vdbeblob.lo: $(TOP)/src/vdbeblob.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbeblob.c
-
-vdbemem.lo: $(TOP)/src/vdbemem.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbemem.c
-
-vdbesort.lo: $(TOP)/src/vdbesort.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbesort.c
-
-vdbetrace.lo: $(TOP)/src/vdbetrace.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbetrace.c
-
-vtab.lo: $(TOP)/src/vtab.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vtab.c
-
-wal.lo: $(TOP)/src/wal.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wal.c
-
-walker.lo: $(TOP)/src/walker.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/walker.c
-
-where.lo: $(TOP)/src/where.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/where.c
-
-wherecode.lo: $(TOP)/src/wherecode.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wherecode.c
-
-whereexpr.lo: $(TOP)/src/whereexpr.c $(HDR)
- $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/whereexpr.c
-
-tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR)
- $(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c
-
-tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR)
- $(LTCOMPILE) -DTCLSH -o $@ -c $(TOP)/src/tclsqlite.c
-
-tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR)
- $(LTCOMPILE) -DUSE_TCL_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c
-
-tclsqlite3$(TEXE): tclsqlite-shell.lo libsqlite3.la
- $(LTLINK) -o $@ tclsqlite-shell.lo \
- libsqlite3.la $(LIBTCL)
-
-# Rules to build opcodes.c and opcodes.h
-#
-opcodes.c: opcodes.h $(TOP)/tool/mkopcodec.tcl
- $(TCLSH_CMD) $(TOP)/tool/mkopcodec.tcl opcodes.h >opcodes.c
-
-opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl
- cat parse.h $(TOP)/src/vdbe.c | $(TCLSH_CMD) $(TOP)/tool/mkopcodeh.tcl >opcodes.h
-
-# Rules to build parse.c and parse.h - the outputs of lemon.
-#
-parse.h: parse.c
-
-parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl
- cp $(TOP)/src/parse.y .
- rm -f parse.h
- ./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
- mv parse.h parse.h.temp
- $(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
-
-sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
- $(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
-
-keywordhash.h: $(TOP)/tool/mkkeywordhash.c
- $(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
- ./mkkeywordhash$(BEXE) >keywordhash.h
-
-# Source files that go into making shell.c
-SHELL_SRC = \
- $(TOP)/src/shell.c.in \
- $(TOP)/ext/misc/appendvfs.c \
- $(TOP)/ext/misc/shathree.c \
- $(TOP)/ext/misc/fileio.c \
- $(TOP)/ext/misc/completion.c \
- $(TOP)/ext/misc/sqlar.c \
- $(TOP)/ext/expert/sqlite3expert.c \
- $(TOP)/ext/expert/sqlite3expert.h \
- $(TOP)/ext/misc/zipfile.c \
- $(TOP)/src/test_windirent.c
-
-shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
- $(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
-
-
-
-
-# Rules to build the extension objects.
-#
-icu.lo: $(TOP)/ext/icu/icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/icu/icu.c
-
-fts2.lo: $(TOP)/ext/fts2/fts2.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2.c
-
-fts2_hash.lo: $(TOP)/ext/fts2/fts2_hash.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_hash.c
-
-fts2_icu.lo: $(TOP)/ext/fts2/fts2_icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_icu.c
-
-fts2_porter.lo: $(TOP)/ext/fts2/fts2_porter.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_porter.c
-
-fts2_tokenizer.lo: $(TOP)/ext/fts2/fts2_tokenizer.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer.c
-
-fts2_tokenizer1.lo: $(TOP)/ext/fts2/fts2_tokenizer1.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer1.c
-
-fts3.lo: $(TOP)/ext/fts3/fts3.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3.c
-
-fts3_aux.lo: $(TOP)/ext/fts3/fts3_aux.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_aux.c
-
-fts3_expr.lo: $(TOP)/ext/fts3/fts3_expr.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_expr.c
-
-fts3_hash.lo: $(TOP)/ext/fts3/fts3_hash.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_hash.c
-
-fts3_icu.lo: $(TOP)/ext/fts3/fts3_icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_icu.c
-
-fts3_porter.lo: $(TOP)/ext/fts3/fts3_porter.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c
-
-fts3_snippet.lo: $(TOP)/ext/fts3/fts3_snippet.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_snippet.c
-
-fts3_tokenizer.lo: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c
-
-fts3_tokenizer1.lo: $(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c
-
-fts3_tokenize_vtab.lo: $(TOP)/ext/fts3/fts3_tokenize_vtab.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenize_vtab.c
-
-fts3_unicode.lo: $(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c
-
-fts3_unicode2.lo: $(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c
-
-fts3_write.lo: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
-
-rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
-
-sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
-
-json1.lo: $(TOP)/ext/misc/json1.c
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
-
-stmt.lo: $(TOP)/ext/misc/stmt.c
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
-
-# FTS5 things
-#
-FTS5_SRC = \
- $(TOP)/ext/fts5/fts5.h \
- $(TOP)/ext/fts5/fts5Int.h \
- $(TOP)/ext/fts5/fts5_aux.c \
- $(TOP)/ext/fts5/fts5_buffer.c \
- $(TOP)/ext/fts5/fts5_main.c \
- $(TOP)/ext/fts5/fts5_config.c \
- $(TOP)/ext/fts5/fts5_expr.c \
- $(TOP)/ext/fts5/fts5_hash.c \
- $(TOP)/ext/fts5/fts5_index.c \
- fts5parse.c fts5parse.h \
- $(TOP)/ext/fts5/fts5_storage.c \
- $(TOP)/ext/fts5/fts5_tokenize.c \
- $(TOP)/ext/fts5/fts5_unicode2.c \
- $(TOP)/ext/fts5/fts5_varint.c \
- $(TOP)/ext/fts5/fts5_vocab.c \
-
-fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
- cp $(TOP)/ext/fts5/fts5parse.y .
- rm -f fts5parse.h
- ./lemon$(BEXE) $(OPTS) fts5parse.y
-
-fts5parse.h: fts5parse.c
-
-fts5.c: $(FTS5_SRC)
- $(TCLSH_CMD) $(TOP)/ext/fts5/tool/mkfts5c.tcl
- cp $(TOP)/ext/fts5/fts5.h .
-
-fts5.lo: fts5.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c fts5.c
-
-sqlite3rbu.lo: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rbu/sqlite3rbu.c
-
-
-# Rules to build the 'testfixture' application.
-#
-# If using the amalgamation, use sqlite3.c directly to build the test
-# fixture. Otherwise link against libsqlite3.la. (This distinction is
-# necessary because the test fixture requires non-API symbols which are
-# hidden when the library is built via the amalgamation).
-#
-TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
-TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
-TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
-TESTFIXTURE_FLAGS += -DBUILD_sqlite
-TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
-TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
-TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
-TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
-
-TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
-TESTFIXTURE_SRC1 = sqlite3.c
-TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c
-TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION))
-
-testfixture$(TEXE): $(TESTFIXTURE_SRC)
- $(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
- -o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
-
-# A very detailed test running most or all test cases
-fulltest: $(TESTPROGS) fuzztest
- ./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS)
-
-# Really really long testing
-soaktest: $(TESTPROGS)
- ./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)
-
-# Do extra testing but not everything.
-fulltestonly: $(TESTPROGS) fuzztest
- ./testfixture$(TEXE) $(TOP)/test/full.test
-
-# Fuzz testing
-fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
- ./fuzzcheck$(TEXE) $(FUZZDATA)
- ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
-
-fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
- ./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)
- ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
-
-valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
- valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
- valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
-
-# The veryquick.test TCL tests.
-#
-tcltest: ./testfixture$(TEXE)
- ./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
-
-# Minimal testing that runs in less than 3 minutes
-#
-quicktest: ./testfixture$(TEXE)
- ./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)
-
-# This is the common case. Run many tests that do not take too long,
-# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
-#
-test: fastfuzztest sourcetest $(TESTPROGS) tcltest
-
-# Run a test using valgrind. This can take a really long time
-# because valgrind is so much slower than a native machine.
-#
-valgrindtest: $(TESTPROGS) valgrindfuzz
- OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)
-
-# A very fast test that checks basic sanity. The name comes from
-# the 60s-era electronics testing: "Turn it on and see if smoke
-# comes out."
-#
-smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
- ./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
-
-sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
- $(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
-
-sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
- $(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
-
-sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in
- $(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in >sqltclsh.c
-
-sqltclsh$(TEXE): sqltclsh.c
- $(LTLINK) sqltclsh.c -o $@ $(LIBTCL) $(TLIBS)
-
-sqlite3_expert$(TEXE): $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c
- $(LTLINK) $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c -o sqlite3_expert $(TLIBS)
-
-CHECKER_DEPS =\
- $(TOP)/tool/mkccode.tcl \
- sqlite3.c \
- $(TOP)/src/tclsqlite.c \
- $(TOP)/ext/repair/sqlite3_checker.tcl \
- $(TOP)/ext/repair/checkindex.c \
- $(TOP)/ext/repair/checkfreelist.c \
- $(TOP)/ext/misc/btreeinfo.c \
- $(TOP)/ext/repair/sqlite3_checker.c.in
-
-sqlite3_checker.c: $(CHECKER_DEPS)
- $(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
-
-sqlite3_checker$(TEXE): sqlite3_checker.c
- $(LTLINK) sqlite3_checker.c -o $@ $(LIBTCL) $(TLIBS)
-
-dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
- $(LTLINK) -DDBDUMP_STANDALONE -o $@ \
- $(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
-
-showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
- $(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
-
-showstat4$(TEXE): $(TOP)/tool/showstat4.c sqlite3.lo
- $(LTLINK) -o $@ $(TOP)/tool/showstat4.c sqlite3.lo $(TLIBS)
-
-showjournal$(TEXE): $(TOP)/tool/showjournal.c sqlite3.lo
- $(LTLINK) -o $@ $(TOP)/tool/showjournal.c sqlite3.lo $(TLIBS)
-
-showwal$(TEXE): $(TOP)/tool/showwal.c sqlite3.lo
- $(LTLINK) -o $@ $(TOP)/tool/showwal.c sqlite3.lo $(TLIBS)
-
-showshm$(TEXE): $(TOP)/tool/showshm.c
- $(LTLINK) -o $@ $(TOP)/tool/showshm.c
-
-changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
- $(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
-
-rollback-test$(TEXE): $(TOP)/tool/rollback-test.c sqlite3.lo
- $(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS)
-
-LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h
- $(LTLINK) -I. -o $@ $(TOP)/tool/logest.c
-
-wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
- $(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)
-
-speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.c
- $(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)
-
-KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ
-
-kvtest$(TEXE): $(TOP)/test/kvtest.c sqlite3.c
- $(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)
-
-rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo
- $(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)
-
-loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
- $(LTLINK) $(TOP)/tool/loadfts.c libsqlite3.la -o $@ $(TLIBS)
-
-# This target will fail if the SQLite amalgamation contains any exported
-# symbols that do not begin with "sqlite3_". It is run as part of the
-# releasetest.tcl script.
-#
-VALIDIDS=' sqlite3(changeset|changegroup|session)?_'
-checksymbols: sqlite3.lo
- nm -g --defined-only sqlite3.lo | egrep -v $(VALIDIDS); test $$? -ne 0
- echo '0 errors out of 1 tests'
-
-# Build the amalgamation-autoconf package. The amalamgation-tarball target builds
-# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz.
-# The snapshot-tarball target builds a tarball named by the SHA1 hash
-#
-amalgamation-tarball: sqlite3.c
- TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal
-
-snapshot-tarball: sqlite3.c
- TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot
-
-# The next two rules are used to support the "threadtest" target. Building
-# threadtest runs a few thread-safety tests that are implemented in C. This
-# target is invoked by the releasetest.tcl script.
-#
-THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
- $(TOP)/test/tt3_checkpoint.c \
- $(TOP)/test/tt3_index.c \
- $(TOP)/test/tt3_vacuum.c \
- $(TOP)/test/tt3_stress.c \
- $(TOP)/test/tt3_lookaside1.c
-
-threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
- $(LTLINK) $(TOP)/test/threadtest3.c $(TOP)/src/test_multiplex.c sqlite3.lo -o $@ $(TLIBS)
-
-threadtest: threadtest3$(TEXE)
- ./threadtest3$(TEXE)
-
-releasetest:
- $(TCLSH_CMD) $(TOP)/test/releasetest.tcl
-
-# Standard install and cleanup targets
-#
-lib_install: libsqlite3.la
- $(INSTALL) -d $(DESTDIR)$(libdir)
- $(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
-
-install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install}
- $(INSTALL) -d $(DESTDIR)$(bindir)
- $(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir)
- $(INSTALL) -d $(DESTDIR)$(includedir)
- $(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(includedir)
- $(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(includedir)
- $(INSTALL) -d $(DESTDIR)$(pkgconfigdir)
- $(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir)
-
-pkgIndex.tcl:
- echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@
-tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
- $(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
- $(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
- rm -f $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.a
- $(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)
-
-clean:
- rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
- rm -f sqlite3.h opcodes.*
- rm -rf .libs .deps
- rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
- rm -f mkkeywordhash$(BEXE) keywordhash.h
- rm -f *.da *.bb *.bbg gmon.out
- rm -rf tsrc .target_source
- rm -f tclsqlite3$(TEXE)
- rm -f testfixture$(TEXE) test.db
- rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
- rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
- rm -f wordcount$(TEXE) changeset$(TEXE)
- rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
- rm -f sqlite3.c
- rm -f sqlite3rc.h
- rm -f shell.c sqlite3ext.h
- rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
- rm -f sqlite-*-output.vsix
- rm -f mptester mptester.exe
- rm -f rbu rbu.exe
- rm -f srcck1 srcck1.exe
- rm -f fuzzershell fuzzershell.exe
- rm -f fuzzcheck fuzzcheck.exe
- rm -f sqldiff sqldiff.exe
- rm -f dbhash dbhash.exe
- rm -f fts5.* fts5parse.*
-
-distclean: clean
- rm -f config.h config.log config.status libtool Makefile sqlite3.pc
-
-#
-# Windows section
-#
-dll: sqlite3.dll
-
-REAL_LIBOBJ = $(LIBOBJ:%.lo=.libs/%.o)
-
-$(REAL_LIBOBJ): $(LIBOBJ)
-
-sqlite3.def: $(REAL_LIBOBJ)
- echo 'EXPORTS' >sqlite3.def
- nm $(REAL_LIBOBJ) | grep ' T ' | grep ' _sqlite3_' \
- | sed 's/^.* _//' >>sqlite3.def
-
-sqlite3.dll: $(REAL_LIBOBJ) sqlite3.def
- $(TCC) -shared -o $@ sqlite3.def \
- -Wl,"--strip-all" $(REAL_LIBOBJ)
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.linux-gcc b/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.linux-gcc
deleted file mode 100644
index 1491a4b02a8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.linux-gcc
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/make
-#
-# Makefile for SQLITE
-#
-# This is a template makefile for SQLite. Most people prefer to
-# use the autoconf generated "configure" script to generate the
-# makefile automatically. But that does not work for everybody
-# and in every situation. If you are having problems with the
-# "configure" script, you might want to try this makefile as an
-# alternative. Create a copy of this file, edit the parameters
-# below and type "make".
-#
-
-#### The toplevel directory of the source tree. This is the directory
-# that contains this "Makefile.in" and the "configure.in" script.
-#
-TOP = ../sqlite
-
-#### C Compiler and options for use in building executables that
-# will run on the platform that is doing the build.
-#
-BCC = gcc -g -O2
-#BCC = /opt/ancic/bin/c89 -0
-
-#### If the target operating system supports the "usleep()" system
-# call, then define the HAVE_USLEEP macro for all C modules.
-#
-#USLEEP =
-USLEEP = -DHAVE_USLEEP=1
-
-#### If you want the SQLite library to be safe for use within a
-# multi-threaded program, then define the following macro
-# appropriately:
-#
-#THREADSAFE = -DTHREADSAFE=1
-THREADSAFE = -DTHREADSAFE=0
-
-#### Specify any extra linker options needed to make the library
-# thread safe
-#
-#THREADLIB = -lpthread
-THREADLIB =
-
-#### Specify any extra libraries needed to access required functions.
-#
-#TLIBS = -lrt # fdatasync on Solaris 8
-TLIBS =
-
-#### Leave SQLITE_DEBUG undefined for maximum speed. Use SQLITE_DEBUG=1
-# to check for memory leaks. Use SQLITE_DEBUG=2 to print a log of all
-# malloc()s and free()s in order to track down memory leaks.
-#
-# SQLite uses some expensive assert() statements in the inner loop.
-# You can make the library go almost twice as fast if you compile
-# with -DNDEBUG=1
-#
-#OPTS = -DSQLITE_DEBUG=2
-#OPTS = -DSQLITE_DEBUG=1
-#OPTS =
-OPTS = -DNDEBUG=1
-OPTS += -DHAVE_FDATASYNC=1
-
-#### The suffix to add to executable files. ".exe" for windows.
-# Nothing for unix.
-#
-#EXE = .exe
-EXE =
-
-#### C Compile and options for use in building executables that
-# will run on the target platform. This is usually the same
-# as BCC, unless you are cross-compiling.
-#
-TCC = gcc -O6
-#TCC = gcc -g -O0 -Wall
-#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
-#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6
-#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive
-
-#### Tools used to build a static library.
-#
-AR = ar cr
-#AR = /opt/mingw/bin/i386-mingw32-ar cr
-RANLIB = ranlib
-#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib
-
-MKSHLIB = gcc -shared
-SO = so
-SHPREFIX = lib
-# SO = dll
-# SHPREFIX =
-
-#### Extra compiler options needed for programs that use the TCL library.
-#
-#TCL_FLAGS =
-#TCL_FLAGS = -DSTATIC_BUILD=1
-TCL_FLAGS = -I/home/drh/tcltk/8.5linux
-#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
-#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux
-
-#### Linker options needed to link against the TCL library.
-#
-#LIBTCL = -ltcl -lm -ldl
-LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
-#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
-#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
-
-#### Additional objects for SQLite library when TCL support is enabled.
-#TCLOBJ =
-TCLOBJ = tclsqlite.o
-
-#### Compiler options needed for programs that use the readline() library.
-#
-READLINE_FLAGS =
-#READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline
-
-#### Linker options needed by programs using readline() must link against.
-#
-LIBREADLINE =
-#LIBREADLINE = -static -lreadline -ltermcap
-
-# You should not have to change anything below this line
-###############################################################################
-include $(TOP)/main.mk
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.msc b/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.msc
deleted file mode 100644
index 8513996b6a0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/Makefile.msc
+++ /dev/null
@@ -1,2482 +0,0 @@
-#
-# nmake Makefile for SQLite
-#
-###############################################################################
-############################## START OF OPTIONS ###############################
-###############################################################################
-
-# The toplevel directory of the source tree. This is the directory
-# that contains this "Makefile.msc".
-#
-TOP = .
-
-# <<mark>>
-# Set this non-0 to create and use the SQLite amalgamation file.
-#
-!IFNDEF USE_AMALGAMATION
-USE_AMALGAMATION = 1
-!ENDIF
-# <</mark>>
-
-# Set this non-0 to enable full warnings (-W4, etc) when compiling.
-#
-!IFNDEF USE_FULLWARN
-USE_FULLWARN = 1
-!ENDIF
-
-# Set this non-0 to enable treating warnings as errors (-WX, etc) when
-# compiling.
-#
-!IFNDEF USE_FATAL_WARN
-USE_FATAL_WARN = 0
-!ENDIF
-
-# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
-# has no effect if (any) optimizations are enabled.
-#
-!IFNDEF USE_RUNTIME_CHECKS
-USE_RUNTIME_CHECKS = 0
-!ENDIF
-
-# Set this non-0 to create a SQLite amalgamation file that excludes the
-# various built-in extensions.
-#
-!IFNDEF MINIMAL_AMALGAMATION
-MINIMAL_AMALGAMATION = 0
-!ENDIF
-
-# Set this non-0 to use "stdcall" calling convention for the core library
-# and shell executable.
-#
-!IFNDEF USE_STDCALL
-USE_STDCALL = 0
-!ENDIF
-
-# Set this non-0 to have the shell executable link against the core dynamic
-# link library.
-#
-!IFNDEF DYNAMIC_SHELL
-DYNAMIC_SHELL = 0
-!ENDIF
-
-# Set this non-0 to enable extra code that attempts to detect misuse of the
-# SQLite API.
-#
-!IFNDEF API_ARMOR
-API_ARMOR = 0
-!ENDIF
-
-# If necessary, create a list of harmless compiler warnings to disable when
-# compiling the various tools. For the SQLite source code itself, warnings,
-# if any, will be disabled from within it.
-#
-!IFNDEF NO_WARN
-!IF $(USE_FULLWARN)!=0
-NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
-NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
-!ENDIF
-!ENDIF
-
-# Set this non-0 to use the library paths and other options necessary for
-# Windows Phone 8.1.
-#
-!IFNDEF USE_WP81_OPTS
-USE_WP81_OPTS = 0
-!ENDIF
-
-# Set this non-0 to split the SQLite amalgamation file into chunks to
-# be used for debugging with Visual Studio.
-#
-!IFNDEF SPLIT_AMALGAMATION
-SPLIT_AMALGAMATION = 0
-!ENDIF
-
-# <<mark>>
-# Set this non-0 to have this makefile assume the Tcl shell executable
-# (tclsh*.exe) is available in the PATH. By default, this is disabled
-# for compatibility with older build environments. This setting only
-# applies if TCLSH_CMD is not set manually.
-#
-!IFNDEF USE_TCLSH_IN_PATH
-USE_TCLSH_IN_PATH = 0
-!ENDIF
-
-# Set this non-0 to use zlib, possibly compiling it from source code.
-#
-!IFNDEF USE_ZLIB
-USE_ZLIB = 0
-!ENDIF
-
-# Set this non-0 to build zlib from source code. This is enabled by
-# default and in that case it will be assumed that the ZLIBDIR macro
-# points to the top-level source code directory for zlib.
-#
-!IFNDEF BUILD_ZLIB
-BUILD_ZLIB = 1
-!ENDIF
-
-# Set this non-0 to use the International Components for Unicode (ICU).
-#
-!IFNDEF USE_ICU
-USE_ICU = 0
-!ENDIF
-# <</mark>>
-
-# Set this non-0 to dynamically link to the MSVC runtime library.
-#
-!IFNDEF USE_CRT_DLL
-USE_CRT_DLL = 0
-!ENDIF
-
-# Set this non-0 to link to the RPCRT4 library.
-#
-!IFNDEF USE_RPCRT4_LIB
-USE_RPCRT4_LIB = 0
-!ENDIF
-
-# Set this non-0 to generate assembly code listings for the source code
-# files.
-#
-!IFNDEF USE_LISTINGS
-USE_LISTINGS = 0
-!ENDIF
-
-# Set this non-0 to attempt setting the native compiler automatically
-# for cross-compiling the command line tools needed during the compilation
-# process.
-#
-!IFNDEF XCOMPILE
-XCOMPILE = 0
-!ENDIF
-
-# Set this non-0 to use the native libraries paths for cross-compiling
-# the command line tools needed during the compilation process.
-#
-!IFNDEF USE_NATIVE_LIBPATHS
-USE_NATIVE_LIBPATHS = 0
-!ENDIF
-
-# Set this 0 to skip the compiling and embedding of version resources.
-#
-!IFNDEF USE_RC
-USE_RC = 1
-!ENDIF
-
-# Set this non-0 to compile binaries suitable for the WinRT environment.
-# This setting does not apply to any binaries that require Tcl to operate
-# properly (i.e. the text fixture, etc).
-#
-!IFNDEF FOR_WINRT
-FOR_WINRT = 0
-!ENDIF
-
-# Set this non-0 to compile binaries suitable for the UWP environment.
-# This setting does not apply to any binaries that require Tcl to operate
-# properly (i.e. the text fixture, etc).
-#
-!IFNDEF FOR_UWP
-FOR_UWP = 0
-!ENDIF
-
-# Set this non-0 to compile binaries suitable for the Windows 10 platform.
-#
-!IFNDEF FOR_WIN10
-FOR_WIN10 = 0
-!ENDIF
-
-# <<mark>>
-# Set this non-0 to skip attempting to look for and/or link with the Tcl
-# runtime library.
-#
-!IFNDEF NO_TCL
-NO_TCL = 0
-!ENDIF
-# <</mark>>
-
-# Set this to non-0 to create and use PDBs.
-#
-!IFNDEF SYMBOLS
-SYMBOLS = 1
-!ENDIF
-
-# Set this to non-0 to use the SQLite debugging heap subsystem.
-#
-!IFNDEF MEMDEBUG
-MEMDEBUG = 0
-!ENDIF
-
-# Set this to non-0 to use the Win32 native heap subsystem.
-#
-!IFNDEF WIN32HEAP
-WIN32HEAP = 0
-!ENDIF
-
-# Set this to non-0 to enable OSTRACE() macros, which can be useful when
-# debugging.
-#
-!IFNDEF OSTRACE
-OSTRACE = 0
-!ENDIF
-
-# Set this to one of the following values to enable various debugging
-# features. Each level includes the debugging options from the previous
-# levels. Currently, the recognized values for DEBUG are:
-#
-# 0 == NDEBUG: Disables assert() and other runtime diagnostics.
-# 1 == SQLITE_ENABLE_API_ARMOR: extra attempts to detect misuse of the API.
-# 2 == Disables NDEBUG and all optimizations and then enables PDBs.
-# 3 == SQLITE_DEBUG: Enables various diagnostics messages and code.
-# 4 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
-# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
-# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
-#
-!IFNDEF DEBUG
-DEBUG = 0
-!ENDIF
-
-# Enable use of available compiler optimizations? Normally, this should be
-# non-zero. Setting this to zero, thus disabling all compiler optimizations,
-# can be useful for testing.
-#
-!IFNDEF OPTIMIZATIONS
-OPTIMIZATIONS = 2
-!ENDIF
-
-# Set this to non-0 to enable support for the session extension.
-#
-!IFNDEF SESSION
-SESSION = 0
-!ENDIF
-
-# Set the source code file to be used by executables and libraries when
-# they need the amalgamation.
-#
-!IFNDEF SQLITE3C
-!IF $(SPLIT_AMALGAMATION)!=0
-SQLITE3C = sqlite3-all.c
-!ELSE
-SQLITE3C = sqlite3.c
-!ENDIF
-!ENDIF
-
-# Set the include code file to be used by executables and libraries when
-# they need SQLite.
-#
-!IFNDEF SQLITE3H
-SQLITE3H = sqlite3.h
-!ENDIF
-
-# This is the name to use for the SQLite dynamic link library (DLL).
-#
-!IFNDEF SQLITE3DLL
-!IF $(FOR_WIN10)!=0
-SQLITE3DLL = winsqlite3.dll
-!ELSE
-SQLITE3DLL = sqlite3.dll
-!ENDIF
-!ENDIF
-
-# This is the name to use for the SQLite import library (LIB).
-#
-!IFNDEF SQLITE3LIB
-!IF $(FOR_WIN10)!=0
-SQLITE3LIB = winsqlite3.lib
-!ELSE
-SQLITE3LIB = sqlite3.lib
-!ENDIF
-!ENDIF
-
-# This is the name to use for the SQLite shell executable (EXE).
-#
-!IFNDEF SQLITE3EXE
-!IF $(FOR_WIN10)!=0
-SQLITE3EXE = winsqlite3shell.exe
-!ELSE
-SQLITE3EXE = sqlite3.exe
-!ENDIF
-!ENDIF
-
-# This is the argument used to set the program database (PDB) file for the
-# SQLite shell executable (EXE).
-#
-!IFNDEF SQLITE3EXEPDB
-!IF $(FOR_WIN10)!=0
-SQLITE3EXEPDB =
-!ELSE
-SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
-!ENDIF
-!ENDIF
-
-# <<mark>>
-# These are the names of the customized Tcl header files used by various parts
-# of this makefile when the stdcall calling convention is in use. It is not
-# used for any other purpose.
-#
-!IFNDEF SQLITETCLH
-SQLITETCLH = sqlite_tcl.h
-!ENDIF
-
-!IFNDEF SQLITETCLDECLSH
-SQLITETCLDECLSH = sqlite_tclDecls.h
-!ENDIF
-
-# These are the additional targets that the targets that integrate with the
-# Tcl library should depend on when compiling, etc.
-#
-!IFNDEF SQLITE_TCL_DEP
-!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
-SQLITE_TCL_DEP = $(SQLITETCLDECLSH) $(SQLITETCLH)
-!ELSE
-SQLITE_TCL_DEP =
-!ENDIF
-!ENDIF
-# <</mark>>
-
-# These are the "standard" SQLite compilation options used when compiling for
-# the Windows platform.
-#
-!IFNDEF OPT_FEATURE_FLAGS
-!IF $(MINIMAL_AMALGAMATION)==0
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
-!ENDIF
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
-!ENDIF
-
-# Should the session extension be enabled? If so, add compilation options
-# to enable it.
-#
-!IF $(SESSION)!=0
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
-!ENDIF
-
-# These are the "extended" SQLite compilation options used when compiling for
-# the Windows 10 platform.
-#
-!IFNDEF EXT_FEATURE_FLAGS
-!IF $(FOR_WIN10)!=0
-EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1
-EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_SYSTEM_MALLOC=1
-EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_OMIT_LOCALTIME=1
-!ELSE
-EXT_FEATURE_FLAGS =
-!ENDIF
-!ENDIF
-
-###############################################################################
-############################### END OF OPTIONS ################################
-###############################################################################
-
-# When compiling for the Windows 10 platform, the PLATFORM macro must be set
-# to an appropriate value (e.g. x86, x64, arm, arm64, etc).
-#
-!IF $(FOR_WIN10)!=0
-!IFNDEF PLATFORM
-!ERROR Using the FOR_WIN10 option requires a value for PLATFORM.
-!ENDIF
-!ENDIF
-
-# This assumes that MSVC is always installed in 32-bit Program Files directory
-# and sets the variable for use in locating other 32-bit installs accordingly.
-#
-PROGRAMFILES_X86 = $(VCINSTALLDIR)\..\..
-PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\)
-
-# Check for the predefined command macro CC. This should point to the compiler
-# binary for the target platform. If it is not defined, simply define it to
-# the legacy default value 'cl.exe'.
-#
-!IFNDEF CC
-CC = cl.exe
-!ENDIF
-
-# Check for the predefined command macro CSC. This should point to a working
-# C Sharp compiler binary. If it is not defined, simply define it to the
-# legacy default value 'csc.exe'.
-#
-!IFNDEF CSC
-CSC = csc.exe
-!ENDIF
-
-# Check for the command macro LD. This should point to the linker binary for
-# the target platform. If it is not defined, simply define it to the legacy
-# default value 'link.exe'.
-#
-!IFNDEF LD
-LD = link.exe
-!ENDIF
-
-# Check for the predefined command macro RC. This should point to the resource
-# compiler binary for the target platform. If it is not defined, simply define
-# it to the legacy default value 'rc.exe'.
-#
-!IFNDEF RC
-RC = rc.exe
-!ENDIF
-
-# Check for the MSVC runtime library path macro. Otherwise, this value will
-# default to the 'lib' directory underneath the MSVC installation directory.
-#
-!IFNDEF CRTLIBPATH
-CRTLIBPATH = $(VCINSTALLDIR)\lib
-!ENDIF
-
-CRTLIBPATH = $(CRTLIBPATH:\\=\)
-
-# Check for the command macro NCC. This should point to the compiler binary
-# for the platform the compilation process is taking place on. If it is not
-# defined, simply define it to have the same value as the CC macro. When
-# cross-compiling, it is suggested that this macro be modified via the command
-# line (since nmake itself does not provide a built-in method to guess it).
-# For example, to use the x86 compiler when cross-compiling for x64, a command
-# line similar to the following could be used (all on one line):
-#
-# nmake /f Makefile.msc sqlite3.dll
-# XCOMPILE=1 USE_NATIVE_LIBPATHS=1
-#
-# Alternatively, the full path and file name to the compiler binary for the
-# platform the compilation process is taking place may be specified (all on
-# one line):
-#
-# nmake /f Makefile.msc sqlite3.dll
-# "NCC=""%VCINSTALLDIR%\bin\cl.exe"""
-# USE_NATIVE_LIBPATHS=1
-#
-!IFDEF NCC
-NCC = $(NCC:\\=\)
-!ELSEIF $(XCOMPILE)!=0
-NCC = "$(VCINSTALLDIR)\bin\$(CC)"
-NCC = $(NCC:\\=\)
-!ELSE
-NCC = $(CC)
-!ENDIF
-
-# Check for the MSVC native runtime library path macro. Otherwise,
-# this value will default to the 'lib' directory underneath the MSVC
-# installation directory.
-#
-!IFNDEF NCRTLIBPATH
-NCRTLIBPATH = $(VCINSTALLDIR)\lib
-!ENDIF
-
-NCRTLIBPATH = $(NCRTLIBPATH:\\=\)
-
-# Check for the Platform SDK library path macro. Otherwise, this
-# value will default to the 'lib' directory underneath the Windows
-# SDK installation directory (the environment variable used appears
-# to be available when using Visual C++ 2008 or later via the
-# command line).
-#
-!IFNDEF NSDKLIBPATH
-NSDKLIBPATH = $(WINDOWSSDKDIR)\lib
-!ENDIF
-
-NSDKLIBPATH = $(NSDKLIBPATH:\\=\)
-
-# Check for the UCRT library path macro. Otherwise, this value will
-# default to the version-specific, platform-specific 'lib' directory
-# underneath the Windows SDK installation directory.
-#
-!IFNDEF UCRTLIBPATH
-UCRTLIBPATH = $(WINDOWSSDKDIR)\lib\$(WINDOWSSDKLIBVERSION)\ucrt\$(PLATFORM)
-!ENDIF
-
-UCRTLIBPATH = $(UCRTLIBPATH:\\=\)
-
-# C compiler and options for use in building executables that
-# will run on the platform that is doing the build.
-#
-!IF $(USE_FULLWARN)!=0
-BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
-!ELSE
-BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
-!ENDIF
-
-# Check if assembly code listings should be generated for the source
-# code files to be compiled.
-#
-!IF $(USE_LISTINGS)!=0
-BCC = $(BCC) -FAcs
-!ENDIF
-
-# Check if the native library paths should be used when compiling
-# the command line tools used during the compilation process. If
-# so, set the necessary macro now.
-#
-!IF $(USE_NATIVE_LIBPATHS)!=0
-NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
-
-!IFDEF NUCRTLIBPATH
-NUCRTLIBPATH = $(NUCRTLIBPATH:\\=\)
-NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)"
-!ENDIF
-!ENDIF
-
-# C compiler and options for use in building executables that
-# will run on the target platform. (BCC and TCC are usually the
-# same unless your are cross-compiling.)
-#
-!IF $(USE_FULLWARN)!=0
-TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
-!ELSE
-TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
-!ENDIF
-
-# Check if warnings should be treated as errors when compiling.
-#
-!IF $(USE_FATAL_WARN)!=0
-TCC = $(TCC) -WX
-!ENDIF
-
-TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
-RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
-
-# Check if we want to use the "stdcall" calling convention when compiling.
-# This is not supported by the compilers for non-x86 platforms. It should
-# also be noted here that building any target with these "stdcall" options
-# will most likely fail if the Tcl library is also required. This is due
-# to how the Tcl library functions are declared and exported (i.e. without
-# an explicit calling convention, which results in "cdecl").
-#
-!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
-!IF "$(PLATFORM)"=="x86"
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-# <<mark>>
-TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
-# <</mark>>
-!ELSE
-!IFNDEF PLATFORM
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-# <<mark>>
-TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
-# <</mark>>
-!ELSE
-CORE_CCONV_OPTS =
-SHELL_CCONV_OPTS =
-# <<mark>>
-TEST_CCONV_OPTS =
-# <</mark>>
-!ENDIF
-!ENDIF
-!ELSE
-CORE_CCONV_OPTS =
-SHELL_CCONV_OPTS =
-# <<mark>>
-TEST_CCONV_OPTS =
-# <</mark>>
-!ENDIF
-
-# These are additional compiler options used for the core library.
-#
-!IFNDEF CORE_COMPILE_OPTS
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport)
-!ELSE
-CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
-!ENDIF
-!ENDIF
-
-# These are the additional targets that the core library should depend on
-# when linking.
-#
-!IFNDEF CORE_LINK_DEP
-!IF $(DYNAMIC_SHELL)!=0
-CORE_LINK_DEP =
-!ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86"
-CORE_LINK_DEP = sqlite3.def
-!ELSE
-CORE_LINK_DEP =
-!ENDIF
-!ENDIF
-
-# These are additional linker options used for the core library.
-#
-!IFNDEF CORE_LINK_OPTS
-!IF $(DYNAMIC_SHELL)!=0
-CORE_LINK_OPTS =
-!ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86"
-CORE_LINK_OPTS = /DEF:sqlite3.def
-!ELSE
-CORE_LINK_OPTS =
-!ENDIF
-!ENDIF
-
-# These are additional compiler options used for the shell executable.
-#
-!IFNDEF SHELL_COMPILE_OPTS
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
-!ELSE
-SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS)
-!ENDIF
-!ENDIF
-
-# This is the source code that the shell executable should be compiled
-# with.
-#
-!IFNDEF SHELL_CORE_SRC
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-SHELL_CORE_SRC =
-!ELSE
-SHELL_CORE_SRC = $(SQLITE3C)
-!ENDIF
-!ENDIF
-
-# This is the core library that the shell executable should depend on.
-#
-!IFNDEF SHELL_CORE_DEP
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-SHELL_CORE_DEP = $(SQLITE3DLL)
-!ELSE
-SHELL_CORE_DEP =
-!ENDIF
-!ENDIF
-
-# <<mark>>
-# If zlib support is enabled, add the dependencies for it.
-#
-!IF $(USE_ZLIB)!=0 && $(BUILD_ZLIB)!=0
-SHELL_CORE_DEP = zlib $(SHELL_CORE_DEP)
-TESTFIXTURE_DEP = zlib $(TESTFIXTURE_DEP)
-!ENDIF
-# <</mark>>
-
-# This is the core library that the shell executable should link with.
-#
-!IFNDEF SHELL_CORE_LIB
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-SHELL_CORE_LIB = $(SQLITE3LIB)
-!ELSE
-SHELL_CORE_LIB =
-!ENDIF
-!ENDIF
-
-# These are additional linker options used for the shell executable.
-#
-!IFNDEF SHELL_LINK_OPTS
-SHELL_LINK_OPTS = $(SHELL_CORE_LIB)
-!ENDIF
-
-# Check if assembly code listings should be generated for the source
-# code files to be compiled.
-#
-!IF $(USE_LISTINGS)!=0
-TCC = $(TCC) -FAcs
-!ENDIF
-
-# When compiling the library for use in the WinRT environment,
-# the following compile-time options must be used as well to
-# disable use of Win32 APIs that are not available and to enable
-# use of Win32 APIs that are specific to Windows 8 and/or WinRT.
-#
-!IF $(FOR_WINRT)!=0
-TCC = $(TCC) -DSQLITE_OS_WINRT=1
-RCC = $(RCC) -DSQLITE_OS_WINRT=1
-TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
-RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
-!ENDIF
-
-# C compiler options for the Windows 10 platform (needs MSVC 2015).
-#
-!IF $(FOR_WIN10)!=0
-TCC = $(TCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
-BCC = $(BCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
-!ENDIF
-
-# Also, we need to dynamically link to the correct MSVC runtime
-# when compiling for WinRT (e.g. debug or release) OR if the
-# USE_CRT_DLL option is set to force dynamically linking to the
-# MSVC runtime library.
-#
-!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0
-!IF $(DEBUG)>1
-TCC = $(TCC) -MDd
-BCC = $(BCC) -MDd
-!ELSE
-TCC = $(TCC) -MD
-BCC = $(BCC) -MD
-!ENDIF
-!ELSE
-!IF $(DEBUG)>1
-TCC = $(TCC) -MTd
-BCC = $(BCC) -MTd
-!ELSE
-TCC = $(TCC) -MT
-BCC = $(BCC) -MT
-!ENDIF
-!ENDIF
-
-# <<mark>>
-# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in
-# any extension header files by default. For non-amalgamation
-# builds, we need to make sure the compiler can find these.
-#
-!IF $(USE_AMALGAMATION)==0
-TCC = $(TCC) -I$(TOP)\ext\fts3
-RCC = $(RCC) -I$(TOP)\ext\fts3
-TCC = $(TCC) -I$(TOP)\ext\rtree
-RCC = $(RCC) -I$(TOP)\ext\rtree
-TCC = $(TCC) -I$(TOP)\ext\session
-RCC = $(RCC) -I$(TOP)\ext\session
-!ENDIF
-
-# The mksqlite3c.tcl script accepts some options on the command
-# line. When compiling with debugging enabled, some of these
-# options are necessary in order to allow debugging symbols to
-# work correctly with Visual Studio when using the amalgamation.
-#
-!IFNDEF MKSQLITE3C_TOOL
-!IF $(MINIMAL_AMALGAMATION)!=0
-MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c-noext.tcl
-!ELSE
-MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c.tcl
-!ENDIF
-!ENDIF
-
-!IFNDEF MKSQLITE3C_ARGS
-!IF $(DEBUG)>1
-MKSQLITE3C_ARGS = --linemacros
-!ELSE
-MKSQLITE3C_ARGS =
-!ENDIF
-!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
-MKSQLITE3C_ARGS = $(MKSQLITE3C_ARGS) --useapicall
-!ENDIF
-!ENDIF
-
-# The mksqlite3h.tcl script accepts some options on the command line.
-# When compiling with stdcall support, some of these options are
-# necessary.
-#
-!IFNDEF MKSQLITE3H_ARGS
-!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
-MKSQLITE3H_ARGS = --useapicall
-!ELSE
-MKSQLITE3H_ARGS =
-!ENDIF
-!ENDIF
-# <</mark>>
-
-# Define -DNDEBUG to compile without debugging (i.e., for production usage)
-# Omitting the define will cause extra debugging code to be inserted and
-# includes extra comments when "EXPLAIN stmt" is used.
-#
-!IF $(DEBUG)==0
-TCC = $(TCC) -DNDEBUG
-BCC = $(BCC) -DNDEBUG
-RCC = $(RCC) -DNDEBUG
-!ENDIF
-
-!IF $(DEBUG)>0 || $(API_ARMOR)!=0 || $(FOR_WIN10)!=0
-TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1
-RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
-!ENDIF
-
-!IF $(DEBUG)>2
-TCC = $(TCC) -DSQLITE_DEBUG=1
-RCC = $(RCC) -DSQLITE_DEBUG=1
-!IF $(DYNAMIC_SHELL)==0
-TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
-RCC = $(RCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
-!ENDIF
-!ENDIF
-
-!IF $(DEBUG)>4 || $(OSTRACE)!=0
-TCC = $(TCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
-RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
-!ENDIF
-
-!IF $(DEBUG)>5
-TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1
-RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1
-!ENDIF
-
-# Prevent warnings about "insecure" MSVC runtime library functions
-# being used.
-#
-TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
-BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
-RCC = $(RCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
-
-# Prevent warnings about "deprecated" POSIX functions being used.
-#
-TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
-BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
-RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
-
-# Use the SQLite debugging heap subsystem?
-#
-!IF $(MEMDEBUG)!=0
-TCC = $(TCC) -DSQLITE_MEMDEBUG=1
-RCC = $(RCC) -DSQLITE_MEMDEBUG=1
-
-# Use native Win32 heap subsystem instead of malloc/free?
-#
-!ELSEIF $(WIN32HEAP)!=0
-TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
-RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
-
-# Validate the heap on every call into the native Win32 heap subsystem?
-#
-!IF $(DEBUG)>3
-TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
-RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
-!ENDIF
-!ENDIF
-
-# <<mark>>
-# The locations of the Tcl header and library files. Also, the library that
-# non-stubs enabled programs using Tcl must link against. These variables
-# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
-# prior to running nmake in order to match the actual installed location and
-# version on this machine.
-#
-!IFNDEF TCLDIR
-TCLDIR = $(TOP)\compat\tcl
-!ENDIF
-
-!IFNDEF TCLINCDIR
-TCLINCDIR = $(TCLDIR)\include
-!ENDIF
-
-!IFNDEF TCLLIBDIR
-TCLLIBDIR = $(TCLDIR)\lib
-!ENDIF
-
-!IFNDEF LIBTCL
-LIBTCL = tcl86.lib
-!ENDIF
-
-!IFNDEF LIBTCLSTUB
-LIBTCLSTUB = tclstub86.lib
-!ENDIF
-
-!IFNDEF LIBTCLPATH
-LIBTCLPATH = $(TCLDIR)\bin
-!ENDIF
-
-# The locations of the zlib header and library files. These variables
-# (ZLIBINCDIR, ZLIBLIBDIR, and ZLIBLIB) may be overridden via the environment
-# prior to running nmake in order to match the actual installed (or source
-# code) location on this machine.
-#
-!IFNDEF ZLIBDIR
-ZLIBDIR = $(TOP)\compat\zlib
-!ENDIF
-
-!IFNDEF ZLIBINCDIR
-ZLIBINCDIR = $(ZLIBDIR)
-!ENDIF
-
-!IFNDEF ZLIBLIBDIR
-ZLIBLIBDIR = $(ZLIBDIR)
-!ENDIF
-
-!IFNDEF ZLIBLIB
-!IF $(DYNAMIC_SHELL)!=0
-ZLIBLIB = zdll.lib
-!ELSE
-ZLIBLIB = zlib.lib
-!ENDIF
-!ENDIF
-
-# The locations of the ICU header and library files. These variables
-# (ICUINCDIR, ICULIBDIR, and LIBICU) may be overridden via the environment
-# prior to running nmake in order to match the actual installed location on
-# this machine.
-#
-!IFNDEF ICUDIR
-ICUDIR = $(TOP)\compat\icu
-!ENDIF
-
-!IFNDEF ICUINCDIR
-ICUINCDIR = $(ICUDIR)\include
-!ENDIF
-
-!IFNDEF ICULIBDIR
-ICULIBDIR = $(ICUDIR)\lib
-!ENDIF
-
-!IFNDEF LIBICU
-LIBICU = icuuc.lib icuin.lib
-!ENDIF
-
-# This is the command to use for tclsh - normally just "tclsh", but we may
-# know the specific version we want to use. This variable (TCLSH_CMD) may be
-# overridden via the environment prior to running nmake in order to select a
-# specific Tcl shell to use.
-#
-!IFNDEF TCLSH_CMD
-!IF $(USE_TCLSH_IN_PATH)!=0 || !EXIST("$(TCLDIR)\bin\tclsh.exe")
-TCLSH_CMD = tclsh
-!ELSE
-TCLSH_CMD = $(TCLDIR)\bin\tclsh.exe
-!ENDIF
-!ENDIF
-# <</mark>>
-
-# Compiler options needed for programs that use the readline() library.
-#
-!IFNDEF READLINE_FLAGS
-READLINE_FLAGS = -DHAVE_READLINE=0
-!ENDIF
-
-# The library that programs using readline() must link against.
-#
-!IFNDEF LIBREADLINE
-LIBREADLINE =
-!ENDIF
-
-# Should the database engine be compiled threadsafe
-#
-TCC = $(TCC) -DSQLITE_THREADSAFE=1
-RCC = $(RCC) -DSQLITE_THREADSAFE=1
-
-# Do threads override each others locks by default (1), or do we test (-1)
-#
-TCC = $(TCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
-RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
-
-# Any target libraries which libsqlite must be linked against
-#
-!IFNDEF TLIBS
-TLIBS =
-!ENDIF
-
-# Flags controlling use of the in memory btree implementation
-#
-# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
-# default to file, 2 to default to memory, and 3 to force temporary
-# tables to always be in memory.
-#
-TCC = $(TCC) -DSQLITE_TEMP_STORE=1
-RCC = $(RCC) -DSQLITE_TEMP_STORE=1
-
-# Enable/disable loadable extensions, and other optional features
-# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
-# The same set of OMIT and ENABLE flags should be passed to the
-# LEMON parser generator and the mkkeywordhash tool as well.
-
-# These are the required SQLite compilation options used when compiling for
-# the Windows platform.
-#
-REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
-
-# If we are linking to the RPCRT4 library, enable features that need it.
-#
-!IF $(USE_RPCRT4_LIB)!=0
-REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_WIN32_USE_UUID=1
-!ENDIF
-
-# Add the required and optional SQLite compilation options into the command
-# lines used to invoke the MSVC code and resource compilers.
-#
-TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS)
-RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS)
-
-# Add in any optional parameters specified on the commane line, e.g.
-# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
-#
-TCC = $(TCC) $(OPTS)
-RCC = $(RCC) $(OPTS)
-
-# If compiling for debugging, add some defines.
-#
-!IF $(DEBUG)>1
-TCC = $(TCC) -D_DEBUG
-BCC = $(BCC) -D_DEBUG
-RCC = $(RCC) -D_DEBUG
-!ENDIF
-
-# If optimizations are enabled or disabled (either implicitly or
-# explicitly), add the necessary flags.
-#
-!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0
-TCC = $(TCC) -Od
-BCC = $(BCC) -Od
-!IF $(USE_RUNTIME_CHECKS)!=0
-TCC = $(TCC) -RTC1
-BCC = $(BCC) -RTC1
-!ENDIF
-!ELSEIF $(OPTIMIZATIONS)>=3
-TCC = $(TCC) -Ox
-BCC = $(BCC) -Ox
-!ELSEIF $(OPTIMIZATIONS)==2
-TCC = $(TCC) -O2
-BCC = $(BCC) -O2
-!ELSEIF $(OPTIMIZATIONS)==1
-TCC = $(TCC) -O1
-BCC = $(BCC) -O1
-!ENDIF
-
-# If symbols are enabled (or compiling for debugging), enable PDBs.
-#
-!IF $(DEBUG)>1 || $(SYMBOLS)!=0
-TCC = $(TCC) -Zi
-BCC = $(BCC) -Zi
-!ENDIF
-
-# <<mark>>
-# If zlib support is enabled, add the compiler options for it.
-#
-!IF $(USE_ZLIB)!=0
-TCC = $(TCC) -DSQLITE_HAVE_ZLIB=1
-RCC = $(RCC) -DSQLITE_HAVE_ZLIB=1
-TCC = $(TCC) -I$(ZLIBINCDIR)
-RCC = $(RCC) -I$(ZLIBINCDIR)
-!ENDIF
-
-# If ICU support is enabled, add the compiler options for it.
-#
-!IF $(USE_ICU)!=0
-TCC = $(TCC) -DSQLITE_ENABLE_ICU=1
-RCC = $(RCC) -DSQLITE_ENABLE_ICU=1
-TCC = $(TCC) -I$(TOP)\ext\icu
-RCC = $(RCC) -I$(TOP)\ext\icu
-TCC = $(TCC) -I$(ICUINCDIR)
-RCC = $(RCC) -I$(ICUINCDIR)
-!ENDIF
-# <</mark>>
-
-# Command line prefixes for compiling code, compiling resources,
-# linking, etc.
-#
-LTCOMPILE = $(TCC) -Fo$@
-LTRCOMPILE = $(RCC) -r
-LTLIB = lib.exe
-LTLINK = $(TCC) -Fe$@
-
-# If requested, link to the RPCRT4 library.
-#
-!IF $(USE_RPCRT4_LIB)!=0
-LTLIBS = $(LTLIBS) rpcrt4.lib
-!ENDIF
-
-# If a platform was set, force the linker to target that.
-# Note that the vcvars*.bat family of batch files typically
-# set this for you. Otherwise, the linker will attempt
-# to deduce the binary type based on the object files.
-!IFDEF PLATFORM
-LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
-LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
-!ELSE
-LTLINKOPTS = /NOLOGO
-LTLIBOPTS = /NOLOGO
-!ENDIF
-
-# When compiling for use in the WinRT environment, the following
-# linker option must be used to mark the executable as runnable
-# only in the context of an application container.
-#
-!IF $(FOR_WINRT)!=0
-LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
-!IF "$(VISUALSTUDIOVERSION)"=="12.0" || "$(VISUALSTUDIOVERSION)"=="14.0"
-!IFNDEF STORELIBPATH
-!IF "$(PLATFORM)"=="x86"
-STORELIBPATH = $(CRTLIBPATH)\store
-!ELSEIF "$(PLATFORM)"=="x64"
-STORELIBPATH = $(CRTLIBPATH)\store\amd64
-!ELSEIF "$(PLATFORM)"=="ARM"
-STORELIBPATH = $(CRTLIBPATH)\store\arm
-!ELSE
-STORELIBPATH = $(CRTLIBPATH)\store
-!ENDIF
-!ENDIF
-STORELIBPATH = $(STORELIBPATH:\\=\)
-LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(STORELIBPATH)"
-!ENDIF
-!ENDIF
-
-# When compiling for Windows Phone 8.1, an extra library path is
-# required.
-#
-!IF $(USE_WP81_OPTS)!=0
-!IFNDEF WP81LIBPATH
-!IF "$(PLATFORM)"=="x86"
-WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
-!ELSEIF "$(PLATFORM)"=="ARM"
-WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\ARM
-!ELSE
-WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
-!ENDIF
-!ENDIF
-!ENDIF
-
-# When compiling for Windows Phone 8.1, some extra linker options
-# are also required.
-#
-!IF $(USE_WP81_OPTS)!=0
-!IFDEF WP81LIBPATH
-LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(WP81LIBPATH)"
-!ENDIF
-LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE
-LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib
-LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
-!ENDIF
-
-# When compiling for UWP or the Windows 10 platform, some extra linker
-# options are also required.
-#
-!IF $(FOR_UWP)!=0 || $(FOR_WIN10)!=0
-LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib
-LTLINKOPTS = $(LTLINKOPTS) mincore.lib
-!IFDEF PSDKLIBPATH
-LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)"
-!ENDIF
-!ENDIF
-
-!IF $(FOR_WIN10)!=0
-LTLINKOPTS = $(LTLINKOPTS) /guard:cf "/LIBPATH:$(UCRTLIBPATH)"
-!IF $(DEBUG)>1
-LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrtd.lib /DEFAULTLIB:ucrtd.lib
-!ELSE
-LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib
-!ENDIF
-!ENDIF
-
-# If either debugging or symbols are enabled, enable PDBs.
-#
-!IF $(DEBUG)>1 || $(SYMBOLS)!=0
-LDFLAGS = /DEBUG $(LDOPTS)
-!ELSE
-LDFLAGS = $(LDOPTS)
-!ENDIF
-
-# <<mark>>
-# Start with the Tcl related linker options.
-#
-!IF $(NO_TCL)==0
-TCLLIBPATHS = $(TCLLIBPATHS) /LIBPATH:$(TCLLIBDIR)
-TCLLIBS = $(TCLLIBS) $(LIBTCL)
-!ENDIF
-
-# If zlib support is enabled, add the linker options for it.
-#
-!IF $(USE_ZLIB)!=0
-LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ZLIBLIBDIR)
-LTLIBS = $(LTLIBS) $(ZLIBLIB)
-!ENDIF
-
-# If ICU support is enabled, add the linker options for it.
-#
-!IF $(USE_ICU)!=0
-LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR)
-LTLIBS = $(LTLIBS) $(LIBICU)
-!ENDIF
-# <</mark>>
-
-# You should not have to change anything below this line
-###############################################################################
-
-# <<mark>>
-# Object files for the SQLite library (non-amalgamation).
-#
-LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
- backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
- callback.lo complete.lo ctime.lo \
- date.lo dbpage.lo dbstat.lo delete.lo \
- expr.lo fault.lo fkey.lo \
- fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
- fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
- fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
- fts5.lo \
- func.lo global.lo hash.lo \
- icu.lo insert.lo legacy.lo loadext.lo \
- main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
- memdb.lo memjournal.lo \
- mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
- notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
- pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
- random.lo resolve.lo rowset.lo rtree.lo \
- sqlite3session.lo select.lo sqlite3rbu.lo status.lo \
- table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
- update.lo upsert.lo util.lo vacuum.lo \
- vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
- vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
- utf.lo vtab.lo
-# <</mark>>
-
-# Object files for the amalgamation.
-#
-LIBOBJS1 = sqlite3.lo
-
-# Determine the real value of LIBOBJ based on the 'configure' script
-#
-# <<mark>>
-!IF $(USE_AMALGAMATION)==0
-LIBOBJ = $(LIBOBJS0)
-!ELSE
-# <</mark>>
-LIBOBJ = $(LIBOBJS1)
-# <<mark>>
-!ENDIF
-# <</mark>>
-
-# Determine if embedded resource compilation and usage are enabled.
-#
-!IF $(USE_RC)!=0
-LIBRESOBJS = sqlite3res.lo
-!ELSE
-LIBRESOBJS =
-!ENDIF
-
-# <<mark>>
-# Core source code files, part 1.
-#
-SRC00 = \
- $(TOP)\src\alter.c \
- $(TOP)\src\analyze.c \
- $(TOP)\src\attach.c \
- $(TOP)\src\auth.c \
- $(TOP)\src\backup.c \
- $(TOP)\src\bitvec.c \
- $(TOP)\src\btmutex.c \
- $(TOP)\src\btree.c \
- $(TOP)\src\build.c \
- $(TOP)\src\callback.c \
- $(TOP)\src\complete.c \
- $(TOP)\src\ctime.c \
- $(TOP)\src\date.c \
- $(TOP)\src\dbpage.c \
- $(TOP)\src\dbstat.c \
- $(TOP)\src\delete.c \
- $(TOP)\src\expr.c \
- $(TOP)\src\fault.c \
- $(TOP)\src\fkey.c \
- $(TOP)\src\func.c \
- $(TOP)\src\global.c \
- $(TOP)\src\hash.c \
- $(TOP)\src\insert.c \
- $(TOP)\src\legacy.c \
- $(TOP)\src\loadext.c \
- $(TOP)\src\main.c \
- $(TOP)\src\malloc.c \
- $(TOP)\src\mem0.c \
- $(TOP)\src\mem1.c \
- $(TOP)\src\mem2.c \
- $(TOP)\src\mem3.c \
- $(TOP)\src\mem5.c \
- $(TOP)\src\memdb.c \
- $(TOP)\src\memjournal.c \
- $(TOP)\src\mutex.c \
- $(TOP)\src\mutex_noop.c \
- $(TOP)\src\mutex_unix.c \
- $(TOP)\src\mutex_w32.c \
- $(TOP)\src\notify.c \
- $(TOP)\src\os.c \
- $(TOP)\src\os_unix.c \
- $(TOP)\src\os_win.c
-
-# Core source code files, part 2.
-#
-SRC01 = \
- $(TOP)\src\pager.c \
- $(TOP)\src\pcache.c \
- $(TOP)\src\pcache1.c \
- $(TOP)\src\pragma.c \
- $(TOP)\src\prepare.c \
- $(TOP)\src\printf.c \
- $(TOP)\src\random.c \
- $(TOP)\src\resolve.c \
- $(TOP)\src\rowset.c \
- $(TOP)\src\select.c \
- $(TOP)\src\status.c \
- $(TOP)\src\table.c \
- $(TOP)\src\threads.c \
- $(TOP)\src\tclsqlite.c \
- $(TOP)\src\tokenize.c \
- $(TOP)\src\treeview.c \
- $(TOP)\src\trigger.c \
- $(TOP)\src\utf.c \
- $(TOP)\src\update.c \
- $(TOP)\src\upsert.c \
- $(TOP)\src\util.c \
- $(TOP)\src\vacuum.c \
- $(TOP)\src\vdbe.c \
- $(TOP)\src\vdbeapi.c \
- $(TOP)\src\vdbeaux.c \
- $(TOP)\src\vdbeblob.c \
- $(TOP)\src\vdbemem.c \
- $(TOP)\src\vdbesort.c \
- $(TOP)\src\vdbetrace.c \
- $(TOP)\src\vtab.c \
- $(TOP)\src\wal.c \
- $(TOP)\src\walker.c \
- $(TOP)\src\where.c \
- $(TOP)\src\wherecode.c \
- $(TOP)\src\whereexpr.c
-
-# Core miscellaneous files.
-#
-SRC03 = \
- $(TOP)\src\parse.y
-
-# Core header files, part 1.
-#
-SRC04 = \
- $(TOP)\src\btree.h \
- $(TOP)\src\btreeInt.h \
- $(TOP)\src\hash.h \
- $(TOP)\src\hwtime.h \
- $(TOP)\src\msvc.h \
- $(TOP)\src\mutex.h \
- $(TOP)\src\os.h \
- $(TOP)\src\os_common.h \
- $(TOP)\src\os_setup.h \
- $(TOP)\src\os_win.h
-
-# Core header files, part 2.
-#
-SRC05 = \
- $(TOP)\src\pager.h \
- $(TOP)\src\pcache.h \
- $(TOP)\src\pragma.h \
- $(TOP)\src\sqlite.h.in \
- $(TOP)\src\sqlite3ext.h \
- $(TOP)\src\sqliteInt.h \
- $(TOP)\src\sqliteLimit.h \
- $(TOP)\src\vdbe.h \
- $(TOP)\src\vdbeInt.h \
- $(TOP)\src\vxworks.h \
- $(TOP)\src\wal.h \
- $(TOP)\src\whereInt.h
-
-# Extension source code files, part 1.
-#
-SRC06 = \
- $(TOP)\ext\fts1\fts1.c \
- $(TOP)\ext\fts1\fts1_hash.c \
- $(TOP)\ext\fts1\fts1_porter.c \
- $(TOP)\ext\fts1\fts1_tokenizer1.c \
- $(TOP)\ext\fts2\fts2.c \
- $(TOP)\ext\fts2\fts2_hash.c \
- $(TOP)\ext\fts2\fts2_icu.c \
- $(TOP)\ext\fts2\fts2_porter.c \
- $(TOP)\ext\fts2\fts2_tokenizer.c \
- $(TOP)\ext\fts2\fts2_tokenizer1.c
-
-# Extension source code files, part 2.
-#
-SRC07 = \
- $(TOP)\ext\fts3\fts3.c \
- $(TOP)\ext\fts3\fts3_aux.c \
- $(TOP)\ext\fts3\fts3_expr.c \
- $(TOP)\ext\fts3\fts3_hash.c \
- $(TOP)\ext\fts3\fts3_icu.c \
- $(TOP)\ext\fts3\fts3_porter.c \
- $(TOP)\ext\fts3\fts3_snippet.c \
- $(TOP)\ext\fts3\fts3_tokenizer.c \
- $(TOP)\ext\fts3\fts3_tokenizer1.c \
- $(TOP)\ext\fts3\fts3_tokenize_vtab.c \
- $(TOP)\ext\fts3\fts3_unicode.c \
- $(TOP)\ext\fts3\fts3_unicode2.c \
- $(TOP)\ext\fts3\fts3_write.c \
- $(TOP)\ext\icu\icu.c \
- $(TOP)\ext\rtree\rtree.c \
- $(TOP)\ext\session\sqlite3session.c \
- $(TOP)\ext\rbu\sqlite3rbu.c \
- $(TOP)\ext\misc\json1.c \
- $(TOP)\ext\misc\stmt.c
-
-# Extension header files, part 1.
-#
-SRC08 = \
- $(TOP)\ext\fts1\fts1.h \
- $(TOP)\ext\fts1\fts1_hash.h \
- $(TOP)\ext\fts1\fts1_tokenizer.h \
- $(TOP)\ext\fts2\fts2.h \
- $(TOP)\ext\fts2\fts2_hash.h \
- $(TOP)\ext\fts2\fts2_tokenizer.h
-
-# Extension header files, part 2.
-#
-SRC09 = \
- $(TOP)\ext\fts3\fts3.h \
- $(TOP)\ext\fts3\fts3Int.h \
- $(TOP)\ext\fts3\fts3_hash.h \
- $(TOP)\ext\fts3\fts3_tokenizer.h \
- $(TOP)\ext\icu\sqliteicu.h \
- $(TOP)\ext\rtree\rtree.h \
- $(TOP)\ext\rbu\sqlite3rbu.h \
- $(TOP)\ext\session\sqlite3session.h
-
-# Generated source code files
-#
-SRC10 = \
- opcodes.c \
- parse.c
-
-# Generated header files
-#
-SRC11 = \
- keywordhash.h \
- opcodes.h \
- parse.h \
- shell.c \
- $(SQLITE3H)
-
-# Generated Tcl header files
-#
-!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
-SRC12 = \
- $(SQLITETCLH) \
- $(SQLITETCLDECLSH)
-!ELSE
-SRC12 =
-!ENDIF
-
-# All source code files.
-#
-SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
-
-# Source code to the test files.
-#
-TESTSRC = \
- $(TOP)\src\test1.c \
- $(TOP)\src\test2.c \
- $(TOP)\src\test3.c \
- $(TOP)\src\test4.c \
- $(TOP)\src\test5.c \
- $(TOP)\src\test6.c \
- $(TOP)\src\test7.c \
- $(TOP)\src\test8.c \
- $(TOP)\src\test9.c \
- $(TOP)\src\test_autoext.c \
- $(TOP)\src\test_async.c \
- $(TOP)\src\test_backup.c \
- $(TOP)\src\test_bestindex.c \
- $(TOP)\src\test_blob.c \
- $(TOP)\src\test_btree.c \
- $(TOP)\src\test_config.c \
- $(TOP)\src\test_delete.c \
- $(TOP)\src\test_demovfs.c \
- $(TOP)\src\test_devsym.c \
- $(TOP)\src\test_fs.c \
- $(TOP)\src\test_func.c \
- $(TOP)\src\test_hexio.c \
- $(TOP)\src\test_init.c \
- $(TOP)\src\test_intarray.c \
- $(TOP)\src\test_journal.c \
- $(TOP)\src\test_malloc.c \
- $(TOP)\src\test_md5.c \
- $(TOP)\src\test_multiplex.c \
- $(TOP)\src\test_mutex.c \
- $(TOP)\src\test_onefile.c \
- $(TOP)\src\test_osinst.c \
- $(TOP)\src\test_pcache.c \
- $(TOP)\src\test_quota.c \
- $(TOP)\src\test_rtree.c \
- $(TOP)\src\test_schema.c \
- $(TOP)\src\test_server.c \
- $(TOP)\src\test_superlock.c \
- $(TOP)\src\test_syscall.c \
- $(TOP)\src\test_tclsh.c \
- $(TOP)\src\test_tclvar.c \
- $(TOP)\src\test_thread.c \
- $(TOP)\src\test_vfs.c \
- $(TOP)\src\test_windirent.c \
- $(TOP)\src\test_wsd.c \
- $(TOP)\ext\fts3\fts3_term.c \
- $(TOP)\ext\fts3\fts3_test.c \
- $(TOP)\ext\rbu\test_rbu.c \
- $(TOP)\ext\session\test_session.c
-
-# Statically linked extensions.
-#
-TESTEXT = \
- $(TOP)\ext\expert\sqlite3expert.c \
- $(TOP)\ext\expert\test_expert.c \
- $(TOP)\ext\misc\amatch.c \
- $(TOP)\ext\misc\carray.c \
- $(TOP)\ext\misc\closure.c \
- $(TOP)\ext\misc\csv.c \
- $(TOP)\ext\misc\eval.c \
- $(TOP)\ext\misc\fileio.c \
- $(TOP)\ext\misc\fuzzer.c \
- $(TOP)\ext\fts5\fts5_tcl.c \
- $(TOP)\ext\fts5\fts5_test_mi.c \
- $(TOP)\ext\fts5\fts5_test_tok.c \
- $(TOP)\ext\misc\ieee754.c \
- $(TOP)\ext\misc\mmapwarm.c \
- $(TOP)\ext\misc\nextchar.c \
- $(TOP)\ext\misc\normalize.c \
- $(TOP)\ext\misc\percentile.c \
- $(TOP)\ext\misc\regexp.c \
- $(TOP)\ext\misc\remember.c \
- $(TOP)\ext\misc\series.c \
- $(TOP)\ext\misc\spellfix.c \
- $(TOP)\ext\misc\totype.c \
- $(TOP)\ext\misc\unionvtab.c \
- $(TOP)\ext\misc\wholenumber.c
-
-# If use of zlib is enabled, add the "zipfile.c" source file.
-#
-!IF $(USE_ZLIB)!=0
-TESTEXT = $(TESTEXT) $(TOP)\ext\misc\zipfile.c
-!ENDIF
-
-# Source code to the library files needed by the test fixture
-# (non-amalgamation)
-#
-TESTSRC2 = \
- $(SRC00) \
- $(SRC01) \
- $(SRC06) \
- $(SRC07) \
- $(SRC10) \
- $(TOP)\ext\async\sqlite3async.c
-
-# Header files used by all library source files.
-#
-HDR = \
- $(TOP)\src\btree.h \
- $(TOP)\src\btreeInt.h \
- $(TOP)\src\hash.h \
- $(TOP)\src\hwtime.h \
- keywordhash.h \
- $(TOP)\src\msvc.h \
- $(TOP)\src\mutex.h \
- opcodes.h \
- $(TOP)\src\os.h \
- $(TOP)\src\os_common.h \
- $(TOP)\src\os_setup.h \
- $(TOP)\src\os_win.h \
- $(TOP)\src\pager.h \
- $(TOP)\src\pcache.h \
- parse.h \
- $(TOP)\src\pragma.h \
- $(SQLITE3H) \
- sqlite3ext.h \
- $(TOP)\src\sqliteInt.h \
- $(TOP)\src\sqliteLimit.h \
- $(TOP)\src\vdbe.h \
- $(TOP)\src\vdbeInt.h \
- $(TOP)\src\vxworks.h \
- $(TOP)\src\whereInt.h
-
-# Header files used by extensions
-#
-EXTHDR = $(EXTHDR) \
- $(TOP)\ext\fts1\fts1.h \
- $(TOP)\ext\fts1\fts1_hash.h \
- $(TOP)\ext\fts1\fts1_tokenizer.h
-EXTHDR = $(EXTHDR) \
- $(TOP)\ext\fts2\fts2.h \
- $(TOP)\ext\fts2\fts2_hash.h \
- $(TOP)\ext\fts2\fts2_tokenizer.h
-EXTHDR = $(EXTHDR) \
- $(TOP)\ext\fts3\fts3.h \
- $(TOP)\ext\fts3\fts3Int.h \
- $(TOP)\ext\fts3\fts3_hash.h \
- $(TOP)\ext\fts3\fts3_tokenizer.h
-EXTHDR = $(EXTHDR) \
- $(TOP)\ext\rtree\rtree.h
-EXTHDR = $(EXTHDR) \
- $(TOP)\ext\icu\sqliteicu.h
-EXTHDR = $(EXTHDR) \
- $(TOP)\ext\rtree\sqlite3rtree.h
-EXTHDR = $(EXTHDR) \
- $(TOP)\ext\session\sqlite3session.h
-
-# executables needed for testing
-#
-TESTPROGS = \
- testfixture.exe \
- $(SQLITE3EXE) \
- sqlite3_analyzer.exe \
- sqlite3_checker.exe \
- sqldiff.exe \
- dbhash.exe \
- sqltclsh.exe
-
-# Databases containing fuzzer test cases
-#
-FUZZDATA = \
- $(TOP)\test\fuzzdata1.db \
- $(TOP)\test\fuzzdata2.db \
- $(TOP)\test\fuzzdata3.db \
- $(TOP)\test\fuzzdata4.db \
- $(TOP)\test\fuzzdata5.db \
- $(TOP)\test\fuzzdata6.db
-# <</mark>>
-
-# Additional compiler options for the shell. These are only effective
-# when the shell is not being dynamically linked.
-#
-!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_INTROSPECTION_PRAGMAS
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_RTREE
-!ENDIF
-
-# <<mark>>
-# Extra compiler options for various test tools.
-#
-MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
-FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
-FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
-OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
-DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
-KV_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
-ST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0
-
-# Standard options to testfixture.
-#
-TESTOPTS = --verbose=file --output=test-out.txt
-
-# Extra targets for the "all" target that require Tcl.
-#
-!IF $(NO_TCL)==0
-ALL_TCL_TARGETS = libtclsqlite3.lib
-!ELSE
-ALL_TCL_TARGETS =
-!ENDIF
-# <</mark>>
-
-# This is the default Makefile target. The objects listed here
-# are what get build when you type just "make" with no arguments.
-#
-core: dll libsqlite3.lib shell
-
-# Targets that require the Tcl library.
-#
-tcl: $(ALL_TCL_TARGETS)
-
-# This Makefile target builds all of the standard binaries.
-#
-all: core tcl
-
-# Dynamic link library section.
-#
-dll: $(SQLITE3DLL)
-
-# Shell executable.
-#
-shell: $(SQLITE3EXE)
-
-# <<mark>>
-libsqlite3.lib: $(LIBOBJ)
- $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)
-
-libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
- $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS)
-# <</mark>>
-
-$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
- $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
-
-# <<block2>>
-sqlite3.def: libsqlite3.lib
- echo EXPORTS > sqlite3.def
- dumpbin /all libsqlite3.lib \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@]*)(?:@\d+)?$$" \1 \
- | sort >> sqlite3.def
-# <</block2>>
-
-$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
- $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
- /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
-
-# <<mark>>
-sqldiff.exe: $(TOP)\tool\sqldiff.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-srcck1.exe: $(TOP)\tool\srcck1.c
- $(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\srcck1.c
-
-sourcetest: srcck1.exe sqlite3.c
- srcck1.exe sqlite3.c
-
-fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-sessionfuzz.exe: zlib $(TOP)\test\sessionfuzz.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -I$(ZLIBINCDIR) $(TOP)\test\sessionfuzz.c /link $(LDFLAGS) $(LTLINKOPTS) /LIBPATH:$(ZLIBLIBDIR) $(ZLIBLIB)
-
-mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20
-MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20
-
-mptest: mptester.exe
- del /Q mptest.db 2>NUL
- $(MPTEST1) --journalmode DELETE
- $(MPTEST2) --journalmode WAL
- $(MPTEST1) --journalmode WAL
- $(MPTEST2) --journalmode PERSIST
- $(MPTEST1) --journalmode PERSIST
- $(MPTEST2) --journalmode TRUNCATE
- $(MPTEST1) --journalmode TRUNCATE
- $(MPTEST2) --journalmode DELETE
-
-# This target creates a directory named "tsrc" and fills it with
-# copies of all of the C source code and header files needed to
-# build on the target system. Some of the C source code and header
-# files are automatically generated. This target takes care of
-# all that automatic generation.
-#
-.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c $(SQLITE_TCL_DEP)
- -rmdir /Q/S tsrc 2>NUL
- -mkdir tsrc
- for %i in ($(SRC00)) do copy /Y %i tsrc
- for %i in ($(SRC01)) do copy /Y %i tsrc
- for %i in ($(SRC03)) do copy /Y %i tsrc
- for %i in ($(SRC04)) do copy /Y %i tsrc
- for %i in ($(SRC05)) do copy /Y %i tsrc
- for %i in ($(SRC06)) do copy /Y %i tsrc
- for %i in ($(SRC07)) do copy /Y %i tsrc
- for %i in ($(SRC08)) do copy /Y %i tsrc
- for %i in ($(SRC09)) do copy /Y %i tsrc
- for %i in ($(SRC10)) do copy /Y %i tsrc
- for %i in ($(SRC11)) do copy /Y %i tsrc
- for %i in ($(SRC12)) do copy /Y %i tsrc
- copy /Y fts5.c tsrc
- copy /Y fts5.h tsrc
- del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
- $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
- move vdbe.new tsrc\vdbe.c
- echo > .target_source
-
-sqlite3.c: .target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
- $(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
- copy $(TOP)\ext\session\sqlite3session.h .
-
-sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
- $(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
-# <</mark>>
-
-# Rule to build the amalgamation
-#
-sqlite3.lo: $(SQLITE3C)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C)
-
-# <<mark>>
-# Rules to build the LEMON compiler generator
-#
-lempar.c: $(TOP)\tool\lempar.c
- copy $(TOP)\tool\lempar.c .
-
-lemon.exe: $(TOP)\tool\lemon.c lempar.c
- $(BCC) $(NO_WARN) -Daccess=_access \
- -Fe$@ $(TOP)\tool\lemon.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
-
-# <<mark>>
-# Rules to build the source-id generator tool
-#
-mksourceid.exe: $(TOP)\tool\mksourceid.c
- $(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\mksourceid.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
-
-# Rules to build individual *.lo files from generated *.c files. This
-# applies to:
-#
-# parse.lo
-# opcodes.lo
-#
-parse.lo: parse.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c parse.c
-
-opcodes.lo: opcodes.c
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c opcodes.c
-# <</mark>>
-
-# Rule to build the Win32 resources object file.
-#
-!IF $(USE_RC)!=0
-# <<block1>>
-$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H)
- echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
- for /F %%V in ('type "$(TOP)\VERSION"') do ( \
- echo #define SQLITE_RESOURCE_VERSION %%V \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact . ^, >> sqlite3rc.h \
- )
- echo #endif >> sqlite3rc.h
- $(LTRCOMPILE) -fo $(LIBRESOBJS) $(TOP)\src\sqlite3.rc
-# <</block1>>
-!ENDIF
-
-# <<mark>>
-# Rules to build individual *.lo files from files in the src directory.
-#
-alter.lo: $(TOP)\src\alter.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\alter.c
-
-analyze.lo: $(TOP)\src\analyze.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\analyze.c
-
-attach.lo: $(TOP)\src\attach.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\attach.c
-
-auth.lo: $(TOP)\src\auth.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\auth.c
-
-backup.lo: $(TOP)\src\backup.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\backup.c
-
-bitvec.lo: $(TOP)\src\bitvec.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\bitvec.c
-
-btmutex.lo: $(TOP)\src\btmutex.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\btmutex.c
-
-btree.lo: $(TOP)\src\btree.c $(HDR) $(TOP)\src\pager.h
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\btree.c
-
-build.lo: $(TOP)\src\build.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\build.c
-
-callback.lo: $(TOP)\src\callback.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\callback.c
-
-complete.lo: $(TOP)\src\complete.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\complete.c
-
-ctime.lo: $(TOP)\src\ctime.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\ctime.c
-
-date.lo: $(TOP)\src\date.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
-
-dbpage.lo: $(TOP)\src\dbpage.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbpage.c
-
-dbstat.lo: $(TOP)\src\dbstat.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbstat.c
-
-delete.lo: $(TOP)\src\delete.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\delete.c
-
-expr.lo: $(TOP)\src\expr.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\expr.c
-
-fault.lo: $(TOP)\src\fault.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\fault.c
-
-fkey.lo: $(TOP)\src\fkey.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\fkey.c
-
-func.lo: $(TOP)\src\func.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\func.c
-
-global.lo: $(TOP)\src\global.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\global.c
-
-hash.lo: $(TOP)\src\hash.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\hash.c
-
-insert.lo: $(TOP)\src\insert.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\insert.c
-
-legacy.lo: $(TOP)\src\legacy.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\legacy.c
-
-loadext.lo: $(TOP)\src\loadext.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\loadext.c
-
-main.lo: $(TOP)\src\main.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\main.c
-
-malloc.lo: $(TOP)\src\malloc.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\malloc.c
-
-mem0.lo: $(TOP)\src\mem0.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem0.c
-
-mem1.lo: $(TOP)\src\mem1.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem1.c
-
-mem2.lo: $(TOP)\src\mem2.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem2.c
-
-mem3.lo: $(TOP)\src\mem3.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem3.c
-
-mem5.lo: $(TOP)\src\mem5.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem5.c
-
-memdb.lo: $(TOP)\src\memdb.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memdb.c
-
-memjournal.lo: $(TOP)\src\memjournal.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memjournal.c
-
-mutex.lo: $(TOP)\src\mutex.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex.c
-
-mutex_noop.lo: $(TOP)\src\mutex_noop.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_noop.c
-
-mutex_unix.lo: $(TOP)\src\mutex_unix.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_unix.c
-
-mutex_w32.lo: $(TOP)\src\mutex_w32.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_w32.c
-
-notify.lo: $(TOP)\src\notify.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\notify.c
-
-pager.lo: $(TOP)\src\pager.c $(HDR) $(TOP)\src\pager.h
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pager.c
-
-pcache.lo: $(TOP)\src\pcache.c $(HDR) $(TOP)\src\pcache.h
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pcache.c
-
-pcache1.lo: $(TOP)\src\pcache1.c $(HDR) $(TOP)\src\pcache.h
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pcache1.c
-
-os.lo: $(TOP)\src\os.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os.c
-
-os_unix.lo: $(TOP)\src\os_unix.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_unix.c
-
-os_win.lo: $(TOP)\src\os_win.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_win.c
-
-pragma.lo: $(TOP)\src\pragma.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pragma.c
-
-prepare.lo: $(TOP)\src\prepare.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\prepare.c
-
-printf.lo: $(TOP)\src\printf.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\printf.c
-
-random.lo: $(TOP)\src\random.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\random.c
-
-resolve.lo: $(TOP)\src\resolve.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\resolve.c
-
-rowset.lo: $(TOP)\src\rowset.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\rowset.c
-
-select.lo: $(TOP)\src\select.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\select.c
-
-status.lo: $(TOP)\src\status.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\status.c
-
-table.lo: $(TOP)\src\table.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\table.c
-
-threads.lo: $(TOP)\src\threads.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\threads.c
-
-tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\tokenize.c
-
-treeview.lo: $(TOP)\src\treeview.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\treeview.c
-
-trigger.lo: $(TOP)\src\trigger.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c
-
-update.lo: $(TOP)\src\update.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\update.c
-
-upsert.lo: $(TOP)\src\upsert.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\upsert.c
-
-utf.lo: $(TOP)\src\utf.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\utf.c
-
-util.lo: $(TOP)\src\util.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\util.c
-
-vacuum.lo: $(TOP)\src\vacuum.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vacuum.c
-
-vdbe.lo: $(TOP)\src\vdbe.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbe.c
-
-vdbeapi.lo: $(TOP)\src\vdbeapi.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeapi.c
-
-vdbeaux.lo: $(TOP)\src\vdbeaux.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeaux.c
-
-vdbeblob.lo: $(TOP)\src\vdbeblob.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeblob.c
-
-vdbemem.lo: $(TOP)\src\vdbemem.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbemem.c
-
-vdbesort.lo: $(TOP)\src\vdbesort.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbesort.c
-
-vdbetrace.lo: $(TOP)\src\vdbetrace.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbetrace.c
-
-vtab.lo: $(TOP)\src\vtab.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vtab.c
-
-wal.lo: $(TOP)\src\wal.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wal.c
-
-walker.lo: $(TOP)\src\walker.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\walker.c
-
-where.lo: $(TOP)\src\where.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\where.c
-
-wherecode.lo: $(TOP)\src\wherecode.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wherecode.c
-
-whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c
-
-tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
- $(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
-
-tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
- $(LTCOMPILE) $(NO_WARN) -DTCLSH -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
-
-tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
- $(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
-
-# Rules to build opcodes.c and opcodes.h
-#
-opcodes.c: opcodes.h $(TOP)\tool\mkopcodec.tcl
- $(TCLSH_CMD) $(TOP)\tool\mkopcodec.tcl opcodes.h > opcodes.c
-
-opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\tool\mkopcodeh.tcl
- type parse.h $(TOP)\src\vdbe.c | $(TCLSH_CMD) $(TOP)\tool\mkopcodeh.tcl > opcodes.h
-
-# Rules to build parse.c and parse.h - the outputs of lemon.
-#
-parse.h: parse.c
-
-parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
- del /Q parse.y parse.h parse.h.temp 2>NUL
- copy $(TOP)\src\parse.y .
- .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) parse.y
- move parse.h parse.h.temp
- $(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
-
-$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
- $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
-
-sqlite3ext.h: .target_source
-!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
- type tsrc\sqlite3ext.h | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*\)" "(SQLITE_CALLBACK *)" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_APICALL *" > sqlite3ext.h
- copy /Y sqlite3ext.h tsrc\sqlite3ext.h
-!ELSE
- copy /Y tsrc\sqlite3ext.h sqlite3ext.h
-!ENDIF
-
-mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
- $(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
- $(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
-
-keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
- .\mkkeywordhash.exe > keywordhash.h
-
-# Source files that go into making shell.c
-SHELL_SRC = \
- $(TOP)\src\shell.c.in \
- $(TOP)\ext\misc\appendvfs.c \
- $(TOP)\ext\misc\shathree.c \
- $(TOP)\ext\misc\fileio.c \
- $(TOP)\ext\misc\completion.c \
- $(TOP)\ext\expert\sqlite3expert.c \
- $(TOP)\ext\expert\sqlite3expert.h \
- $(TOP)\src\test_windirent.c
-
-# If use of zlib is enabled, add the "zipfile.c" source file.
-#
-!IF $(USE_ZLIB)!=0
-SHELL_SRC = $(SHELL_SRC) $(TOP)\ext\misc\sqlar.c
-SHELL_SRC = $(SHELL_SRC) $(TOP)\ext\misc\zipfile.c
-!ENDIF
-
-shell.c: $(SHELL_SRC) $(TOP)\tool\mkshellc.tcl
- $(TCLSH_CMD) $(TOP)\tool\mkshellc.tcl > shell.c
-
-zlib:
- pushd $(ZLIBDIR) && $(MAKE) /f win32\Makefile.msc clean $(ZLIBLIB) && popd
-
-# Rules to build the extension objects.
-#
-icu.lo: $(TOP)\ext\icu\icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\icu\icu.c
-
-fts2.lo: $(TOP)\ext\fts2\fts2.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2.c
-
-fts2_hash.lo: $(TOP)\ext\fts2\fts2_hash.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_hash.c
-
-fts2_icu.lo: $(TOP)\ext\fts2\fts2_icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_icu.c
-
-fts2_porter.lo: $(TOP)\ext\fts2\fts2_porter.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_porter.c
-
-fts2_tokenizer.lo: $(TOP)\ext\fts2\fts2_tokenizer.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer.c
-
-fts2_tokenizer1.lo: $(TOP)\ext\fts2\fts2_tokenizer1.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer1.c
-
-fts3.lo: $(TOP)\ext\fts3\fts3.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3.c
-
-fts3_aux.lo: $(TOP)\ext\fts3\fts3_aux.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_aux.c
-
-fts3_expr.lo: $(TOP)\ext\fts3\fts3_expr.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_expr.c
-
-fts3_hash.lo: $(TOP)\ext\fts3\fts3_hash.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_hash.c
-
-fts3_icu.lo: $(TOP)\ext\fts3\fts3_icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_icu.c
-
-fts3_snippet.lo: $(TOP)\ext\fts3\fts3_snippet.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_snippet.c
-
-fts3_porter.lo: $(TOP)\ext\fts3\fts3_porter.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_porter.c
-
-fts3_tokenizer.lo: $(TOP)\ext\fts3\fts3_tokenizer.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer.c
-
-fts3_tokenizer1.lo: $(TOP)\ext\fts3\fts3_tokenizer1.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c
-
-fts3_tokenize_vtab.lo: $(TOP)\ext\fts3\fts3_tokenize_vtab.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenize_vtab.c
-
-fts3_unicode.lo: $(TOP)\ext\fts3\fts3_unicode.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c
-
-fts3_unicode2.lo: $(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c
-
-fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c
-
-rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c
-
-sqlite3session.lo: $(TOP)\ext\session\sqlite3session.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\session\sqlite3session.c
-
-# FTS5 things
-#
-FTS5_SRC = \
- $(TOP)\ext\fts5\fts5.h \
- $(TOP)\ext\fts5\fts5Int.h \
- $(TOP)\ext\fts5\fts5_aux.c \
- $(TOP)\ext\fts5\fts5_buffer.c \
- $(TOP)\ext\fts5\fts5_main.c \
- $(TOP)\ext\fts5\fts5_config.c \
- $(TOP)\ext\fts5\fts5_expr.c \
- $(TOP)\ext\fts5\fts5_hash.c \
- $(TOP)\ext\fts5\fts5_index.c \
- fts5parse.c fts5parse.h \
- $(TOP)\ext\fts5\fts5_storage.c \
- $(TOP)\ext\fts5\fts5_tokenize.c \
- $(TOP)\ext\fts5\fts5_unicode2.c \
- $(TOP)\ext\fts5\fts5_varint.c \
- $(TOP)\ext\fts5\fts5_vocab.c
-
-LSM1_SRC = \
- $(TOP)\ext\lsm1\lsm.h \
- $(TOP)\ext\lsm1\lsmInt.h \
- $(TOP)\ext\lsm1\lsm_ckpt.c \
- $(TOP)\ext\lsm1\lsm_file.c \
- $(TOP)\ext\lsm1\lsm_log.c \
- $(TOP)\ext\lsm1\lsm_main.c \
- $(TOP)\ext\lsm1\lsm_mem.c \
- $(TOP)\ext\lsm1\lsm_mutex.c \
- $(TOP)\ext\lsm1\lsm_shared.c \
- $(TOP)\ext\lsm1\lsm_sorted.c \
- $(TOP)\ext\lsm1\lsm_str.c \
- $(TOP)\ext\lsm1\lsm_tree.c \
- $(TOP)\ext\lsm1\lsm_unix.c \
- $(TOP)\ext\lsm1\lsm_varint.c \
- $(TOP)\ext\lsm1\lsm_vtab.c \
- $(TOP)\ext\lsm1\lsm_win32.c
-
-fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
- copy $(TOP)\ext\fts5\fts5parse.y .
- del /Q fts5parse.h 2>NUL
- .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) fts5parse.y
-
-fts5parse.h: fts5parse.c
-
-fts5.c: $(FTS5_SRC)
- $(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl
- copy $(TOP)\ext\fts5\fts5.h .
-
-lsm1.c: $(LSM1_SRC)
- $(TCLSH_CMD) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
- copy $(TOP)\ext\lsm1\lsm.h .
-
-fts5.lo: fts5.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c
-
-fts5_ext.lo: fts5.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) $(NO_WARN) -c fts5.c
-
-fts5.dll: fts5_ext.lo
- $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ fts5_ext.lo
-
-sqlite3rbu.lo: $(TOP)\ext\rbu\sqlite3rbu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\rbu\sqlite3rbu.c
-
-# Rules to build the 'testfixture' application.
-#
-# If using the amalgamation, use sqlite3.c directly to build the test
-# fixture. Otherwise link against libsqlite3.lib. (This distinction is
-# necessary because the test fixture requires non-API symbols which are
-# hidden when the library is built via the amalgamation).
-#
-TESTFIXTURE_FLAGS = -DTCLSH_INIT_PROC=sqlite3TestInit -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
-
-TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
-TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
-!IF $(USE_AMALGAMATION)==0
-TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
-!ELSE
-TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1)
-!ENDIF
-
-!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
-sqlite_tclDecls.h:
- echo #ifndef SQLITE_TCLAPI > $(SQLITETCLDECLSH)
- echo # define SQLITE_TCLAPI >> $(SQLITETCLDECLSH)
- echo #endif >> $(SQLITETCLDECLSH)
- type "$(TCLINCDIR)\tclDecls.h" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "^(EXTERN(?: CONST\d+?)?\s+?[^\(]*?\s+?)Tcl_" "\1 SQLITE_TCLAPI Tcl_" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "^(EXTERN\s+?(?:void|VOID)\s+?)TclFreeObj" "\1 SQLITE_TCLAPI TclFreeObj" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*tcl_" "(SQLITE_TCLAPI *tcl_" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*tclFreeObj" "(SQLITE_TCLAPI *tclFreeObj" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_TCLAPI *" >> $(SQLITETCLDECLSH)
-
-sqlite_tcl.h:
- type "$(TCLINCDIR)\tcl.h" | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact tclDecls.h sqlite_tclDecls.h \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "typedef (.*?)\(Tcl_" "typedef \1 (SQLITE_TCLAPI Tcl_" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "void (*freeProc)" "void (SQLITE_TCLAPI *freeProc)" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*findProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *findProc)" \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*createProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *createProc)" >> $(SQLITETCLH)
-!ENDIF
-
-testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
- $(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
- -DBUILD_sqlite -I$(TCLINCDIR) \
- $(TESTFIXTURE_SRC) \
- /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
-
-extensiontest: testfixture.exe testloadext.dll
- @set PATH=$(LIBTCLPATH);$(PATH)
- .\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
-
-fulltest: $(TESTPROGS) fuzztest
- @set PATH=$(LIBTCLPATH);$(PATH)
- .\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)
-
-soaktest: $(TESTPROGS)
- @set PATH=$(LIBTCLPATH);$(PATH)
- .\testfixture.exe $(TOP)\test\all.test -soak=1 $(TESTOPTS)
-
-fulltestonly: $(TESTPROGS) fuzztest
- @set PATH=$(LIBTCLPATH);$(PATH)
- .\testfixture.exe $(TOP)\test\full.test
-
-queryplantest: testfixture.exe shell
- @set PATH=$(LIBTCLPATH);$(PATH)
- .\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS)
-
-fuzztest: fuzzcheck.exe
- .\fuzzcheck.exe $(FUZZDATA)
-
-fastfuzztest: fuzzcheck.exe
- .\fuzzcheck.exe --limit-mem 100M $(FUZZDATA)
-
-# Minimal testing that runs in less than 3 minutes (on a fast machine)
-#
-quicktest: testfixture.exe sourcetest
- @set PATH=$(LIBTCLPATH);$(PATH)
- .\testfixture.exe $(TOP)\test\extraquick.test $(TESTOPTS)
-
-# This is the common case. Run many tests that do not take too long,
-# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
-#
-test: $(TESTPROGS) sourcetest fastfuzztest
- @set PATH=$(LIBTCLPATH);$(PATH)
- .\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
-
-smoketest: $(TESTPROGS)
- @set PATH=$(LIBTCLPATH);$(PATH)
- .\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
-
-sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
- $(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
-
-sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
- $(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
- /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
-
-sqltclsh.c: sqlite3.c $(TOP)\src\tclsqlite.c $(TOP)\tool\sqltclsh.tcl $(TOP)\ext\misc\appendvfs.c $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqltclsh.c.in
- $(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqltclsh.c.in >sqltclsh.c
-
-sqltclsh.exe: sqltclsh.c $(SHELL_CORE_DEP) $(LIBRESOBJS)
- $(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqltclsh.c \
- /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
-
-sqlite3_expert.exe: $(SQLITE3C) $(TOP)\ext\expert\sqlite3expert.h $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c
- $(LTLINK) $(NO_WARN) $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c $(SQLITE3C) $(TLIBS)
-
-CHECKER_DEPS =\
- $(TOP)/tool/mkccode.tcl \
- sqlite3.c \
- $(TOP)/src/tclsqlite.c \
- $(TOP)/ext/repair/sqlite3_checker.tcl \
- $(TOP)/ext/repair/checkindex.c \
- $(TOP)/ext/repair/checkfreelist.c \
- $(TOP)/ext/misc/btreeinfo.c \
- $(TOP)/ext/repair/sqlite3_checker.c.in
-
-sqlite3_checker.c: $(CHECKER_DEPS)
- $(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\ext\repair\sqlite3_checker.c.in > $@
-
-sqlite3_checker.exe: sqlite3_checker.c $(LIBRESOBJS)
- $(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
- /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
-
-dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
- $(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
- /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
-
-testloadext.lo: $(TOP)\src\test_loadext.c $(SQLITE3H)
- $(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
-
-testloadext.dll: testloadext.lo
- $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
-
-showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-showshm.exe: $(TOP)\tool\showshm.c
- $(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS)
-
-changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
- $(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-LogEst.exe: $(TOP)\tool\logest.c $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
-
-wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(ST_COMPILE_OPTS) -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-kvtest.exe: $(TOP)\test\kvtest.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(KV_COMPILE_OPTS) \
- $(TOP)\test\kvtest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
- $(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
-LSMDIR=$(TOP)\ext\lsm1
-!INCLUDE $(LSMDIR)\Makefile.msc
-
-moreclean: clean
- del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
-# <</mark>>
-
-clean:
- del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
- del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
- del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
-# <<mark>>
- del /Q sqlite3.c sqlite3.h 2>NUL
- del /Q opcodes.c opcodes.h 2>NUL
- del /Q lemon.* lempar.c parse.* 2>NUL
- del /Q mksourceid.* mkkeywordhash.* keywordhash.h 2>NUL
- del /Q notasharedlib.* 2>NUL
- -rmdir /Q/S .deps 2>NUL
- -rmdir /Q/S .libs 2>NUL
- -rmdir /Q/S tsrc 2>NUL
- del /Q .target_source 2>NUL
- del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
- del /Q lsm.dll lsmtest.exe 2>NUL
- del /Q testloadext.dll 2>NUL
- del /Q testfixture.exe test.db 2>NUL
- del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
- del /Q changeset.exe 2>NUL
- del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
- del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL
- del /Q sqlite3.c sqlite3-*.c 2>NUL
- del /Q sqlite3rc.h 2>NUL
- del /Q shell.c sqlite3ext.h sqlite3session.h 2>NUL
- del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
- del /Q sqlite-*-output.vsix 2>NUL
- del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
- del /Q sqltclsh.* 2>NUL
- del /Q dbfuzz.exe sessionfuzz.exe 2>NUL
- del /Q kvtest.exe ossshell.exe scrub.exe 2>NUL
- del /Q showshm.exe sqlite3_checker.* sqlite3_expert.exe 2>NUL
- del /Q fts5.* fts5parse.* 2>NUL
- del /Q lsm.h lsm1.c 2>NUL
-# <</mark>>
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/README.md b/chromium/third_party/sqlite/sqlite-src-3240000/README.md
deleted file mode 100644
index 8c8cc95c74c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/README.md
+++ /dev/null
@@ -1,302 +0,0 @@
-<h1 align="center">SQLite Source Repository</h1>
-
-This repository contains the complete source code for the SQLite database
-engine. Some test scripts are also included. However, many other test scripts
-and most of the documentation are managed separately.
-
-SQLite [does not use Git](https://sqlite.org/whynotgit.html).
-If you are reading this on GitHub, then you are looking at an
-unofficial mirror. See <https://sqlite.org/src> for the official
-repository.
-
-## Obtaining The Code
-
-SQLite sources are managed using the
-[Fossil](https://www.fossil-scm.org/), a distributed version control system
-that was specifically designed to support SQLite development.
-If you do not want to use Fossil, you can download tarballs or ZIP
-archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
-
- * Lastest trunk check-in as
- [Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz),
- [ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip), or
- [SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar).
-
- * Latest release as
- [Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release),
- [ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip?r=release), or
- [SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar?r=release).
-
- * For other check-ins, substitute an appropriate branch name or
- tag or hash prefix for "release" in the URLs of the previous
- bullet. Or browse the [timeline](https://www.sqlite.org/src/timeline)
- to locate the check-in desired, click on its information page link,
- then click on the "Tarball" or "ZIP Archive" links on the information
- page.
-
-If you do want to use Fossil to check out the source tree,
-first install Fossil version 2.0 or later.
-(Source tarballs and precompiled binaries available
-[here](https://www.fossil-scm.org/fossil/uv/download.html). Fossil is
-a stand-alone program. To install, simply download or build the single
-executable file and put that file someplace on your $PATH.)
-Then run commands like this:
-
- mkdir ~/sqlite
- cd ~/sqlite
- fossil clone https://www.sqlite.org/src sqlite.fossil
- fossil open sqlite.fossil
-
-After setting up a repository using the steps above, you can always
-update to the lastest version using:
-
- fossil update trunk ;# latest trunk check-in
- fossil update release ;# latest official release
-
-Or type "fossil ui" to get a web-based user interface.
-
-## Compiling
-
-First create a directory in which to place
-the build products. It is recommended, but not required, that the
-build directory be separate from the source directory. Cd into the
-build directory and then from the build directory run the configure
-script found at the root of the source tree. Then run "make".
-
-For example:
-
- tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
- mkdir bld ;# Build will occur in a sibling directory
- cd bld ;# Change to the build directory
- ../sqlite/configure ;# Run the configure script
- make ;# Run the makefile.
- make sqlite3.c ;# Build the "amalgamation" source file
- make test ;# Run some tests (requires Tcl)
-
-See the makefile for additional targets.
-
-The configure script uses autoconf 2.61 and libtool. If the configure
-script does not work out for you, there is a generic makefile named
-"Makefile.linux-gcc" in the top directory of the source tree that you
-can copy and edit to suit your needs. Comments on the generic makefile
-show what changes are needed.
-
-## Using MSVC
-
-On Windows, all applicable build products can be compiled with MSVC.
-First open the command prompt window associated with the desired compiler
-version (e.g. "Developer Command Prompt for VS2013"). Next, use NMAKE
-with the provided "Makefile.msc" to build one of the supported targets.
-
-For example:
-
- mkdir bld
- cd bld
- nmake /f Makefile.msc TOP=..\sqlite
- nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
- nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
- nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
- nmake /f Makefile.msc test TOP=..\sqlite
-
-There are several build options that can be set via the NMAKE command
-line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
-to the "sqlite3.dll" command line above. When debugging into the SQLite
-code, adding the "DEBUG=1" argument to one of the above command lines is
-recommended.
-
-SQLite does not require [Tcl](http://www.tcl.tk/) to run, but a Tcl installation
-is required by the makefiles (including those for MSVC). SQLite contains
-a lot of generated code and Tcl is used to do much of that code generation.
-
-## Source Code Tour
-
-Most of the core source files are in the **src/** subdirectory. The
-**src/** folder also contains files used to build the "testfixture" test
-harness. The names of the source files used by "testfixture" all begin
-with "test".
-The **src/** also contains the "shell.c" file
-which is the main program for the "sqlite3.exe"
-[command-line shell](https://sqlite.org/cli.html) and
-the "tclsqlite.c" file which implements the
-[Tcl bindings](https://sqlite.org/tclsqlite.html) for SQLite.
-(Historical note: SQLite began as a Tcl
-extension and only later escaped to the wild as an independent library.)
-
-Test scripts and programs are found in the **test/** subdirectory.
-Addtional test code is found in other source repositories.
-See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
-additional information.
-
-The **ext/** subdirectory contains code for extensions. The
-Full-text search engine is in **ext/fts3**. The R-Tree engine is in
-**ext/rtree**. The **ext/misc** subdirectory contains a number of
-smaller, single-file extensions, such as a REGEXP operator.
-
-The **tool/** subdirectory contains various scripts and programs used
-for building generated source code files or for testing or for generating
-accessory programs such as "sqlite3_analyzer(.exe)".
-
-### Generated Source Code Files
-
-Several of the C-language source files used by SQLite are generated from
-other sources rather than being typed in manually by a programmer. This
-section will summarize those automatically-generated files. To create all
-of the automatically-generated files, simply run "make target&#95;source".
-The "target&#95;source" make target will create a subdirectory "tsrc/" and
-fill it with all the source files needed to build SQLite, both
-manually-edited files and automatically-generated files.
-
-The SQLite interface is defined by the **sqlite3.h** header file, which is
-generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The
-[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
-The manifest.uuid file contains the SHA3 hash of the particular check-in
-and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file
-contains the current SQLite version number. The sqlite3.h header is really
-just a copy of src/sqlite.h.in with the source-id and version number inserted
-at just the right spots. Note that comment text in the sqlite3.h file is
-used to generate much of the SQLite API documentation. The Tcl scripts
-used to generate that documentation are in a separate source repository.
-
-The SQL language parser is **parse.c** which is generate from a grammar in
-the src/parse.y file. The conversion of "parse.y" into "parse.c" is done
-by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
-for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a
-template for generating its parser.
-
-Lemon also generates the **parse.h** header file, at the same time it
-generates parse.c. But the parse.h header file is
-modified further (to add additional symbols) using the ./addopcodes.tcl
-Tcl script.
-
-The **opcodes.h** header file contains macros that define the numbers
-corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h
-file is generated by the scanning the src/vdbe.c source file. The
-Tcl script at ./mkopcodeh.tcl does this scan and generates opcodes.h.
-A second Tcl script, ./mkopcodec.tcl, then scans opcodes.h to generate
-the **opcodes.c** source file, which contains a reverse mapping from
-opcode-number to opcode-name that is used for EXPLAIN output.
-
-The **keywordhash.h** header file contains the definition of a hash table
-that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into
-the numeric codes used by the parse.c parser. The keywordhash.h file is
-generated by a C-language program at tool mkkeywordhash.c.
-
-The **pragma.h** header file contains various definitions used to parse
-and implement the PRAGMA statements. The header is generated by a
-script **tool/mkpragmatab.tcl**. If you want to add a new PRAGMA, edit
-the **tool/mkpragmatab.tcl** file to insert the information needed by the
-parser for your new PRAGMA, then run the script to regenerate the
-**pragma.h** header file.
-
-### The Amalgamation
-
-All of the individual C source code and header files (both manually-edited
-and automatically-generated) can be combined into a single big source file
-**sqlite3.c** called "the amalgamation". The amalgamation is the recommended
-way of using SQLite in a larger application. Combining all individual
-source code files into a single big source code file allows the C compiler
-to perform more cross-procedure analysis and generate better code. SQLite
-runs about 5% faster when compiled from the amalgamation versus when compiled
-from individual source files.
-
-The amalgamation is generated from the tool/mksqlite3c.tcl Tcl script.
-First, all of the individual source files must be gathered into the tsrc/
-subdirectory (using the equivalent of "make target_source") then the
-tool/mksqlite3c.tcl script is run to copy them all together in just the
-right order while resolving internal "#include" references.
-
-The amalgamation source file is more than 200K lines long. Some symbolic
-debuggers (most notably MSVC) are unable to deal with files longer than 64K
-lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl,
-can be run on the amalgamation to break it up into a single small C file
-called **sqlite3-all.c** that does #include on about seven other files
-named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-7.c**. In this way,
-all of the source code is contained within a single translation unit so
-that the compiler can do extra cross-procedure optimization, but no
-individual source file exceeds 32K lines in length.
-
-## How It All Fits Together
-
-SQLite is modular in design.
-See the [architectural description](http://www.sqlite.org/arch.html)
-for details. Other documents that are useful in
-(helping to understand how SQLite works include the
-[file format](http://www.sqlite.org/fileformat2.html) description,
-the [virtual machine](http://www.sqlite.org/opcode.html) that runs
-prepared statements, the description of
-[how transactions work](http://www.sqlite.org/atomiccommit.html), and
-the [overview of the query planner](http://www.sqlite.org/optoverview.html).
-
-Years of effort have gone into optimizating SQLite, both
-for small size and high performance. And optimizations tend to result in
-complex code. So there is a lot of complexity in the current SQLite
-implementation. It will not be the easiest library in the world to hack.
-
-Key files:
-
- * **sqlite.h.in** - This file defines the public interface to the SQLite
- library. Readers will need to be familiar with this interface before
- trying to understand how the library works internally.
-
- * **sqliteInt.h** - this header file defines many of the data objects
- used internally by SQLite. In addition to "sqliteInt.h", some
- subsystems have their own header files.
-
- * **parse.y** - This file describes the LALR(1) grammar that SQLite uses
- to parse SQL statements, and the actions that are taken at each step
- in the parsing process.
-
- * **vdbe.c** - This file implements the virtual machine that runs
- prepared statements. There are various helper files whose names
- begin with "vdbe". The VDBE has access to the vdbeInt.h header file
- which defines internal data objects. The rest of SQLite interacts
- with the VDBE through an interface defined by vdbe.h.
-
- * **where.c** - This file (together with its helper files named
- by "where*.c") analyzes the WHERE clause and generates
- virtual machine code to run queries efficiently. This file is
- sometimes called the "query optimizer". It has its own private
- header file, whereInt.h, that defines data objects used internally.
-
- * **btree.c** - This file contains the implementation of the B-Tree
- storage engine used by SQLite. The interface to the rest of the system
- is defined by "btree.h". The "btreeInt.h" header defines objects
- used internally by btree.c and not published to the rest of the system.
-
- * **pager.c** - This file contains the "pager" implementation, the
- module that implements transactions. The "pager.h" header file
- defines the interface between pager.c and the rest of the system.
-
- * **os_unix.c** and **os_win.c** - These two files implement the interface
- between SQLite and the underlying operating system using the run-time
- pluggable VFS interface.
-
- * **shell.c.in** - This file is not part of the core SQLite library. This
- is the file that, when linked against sqlite3.a, generates the
- "sqlite3.exe" command-line shell. The "shell.c.in" file is transformed
- into "shell.c" as part of the build process.
-
- * **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It
- is not part of the core SQLite library. But as most of the tests in this
- repository are written in Tcl, the Tcl language bindings are important.
-
- * **test*.c** - Files in the src/ folder that begin with "test" go into
- building the "testfixture.exe" program. The testfixture.exe program is
- an enhanced Tcl shell. The testfixture.exe program runs scripts in the
- test/ folder to validate the core SQLite code. The testfixture program
- (and some other test programs too) is build and run when you type
- "make test".
-
- * **ext/misc/json1.c** - This file implements the various JSON functions
- that are build into SQLite.
-
-There are many other source files. Each has a succinct header comment that
-describes its purpose and role within the larger system.
-
-
-## Contacts
-
-The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/)
-with geographically distributed backups at
-[http://www2.sqlite.org/](http://www2.sqlite.org) and
-[http://www3.sqlite.org/](http://www3.sqlite.org).
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/VERSION b/chromium/third_party/sqlite/sqlite-src-3240000/VERSION
deleted file mode 100644
index 954e2288218..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-3.24.0
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/aclocal.m4 b/chromium/third_party/sqlite/sqlite-src-3240000/aclocal.m4
deleted file mode 100644
index 8e5151ebade..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/aclocal.m4
+++ /dev/null
@@ -1,7972 +0,0 @@
-# generated automatically by aclocal 1.10.2 -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-# 2006, 2007, 2008 Free Software Foundation, Inc.
-# Written by Gordon Matzigkeit, 1996
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-m4_define([_LT_COPYING], [dnl
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-# 2006, 2007, 2008 Free Software Foundation, Inc.
-# Written by Gordon Matzigkeit, 1996
-#
-# This file is part of GNU Libtool.
-#
-# GNU Libtool is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# As a special exception to the GNU General Public License,
-# if you distribute this file as part of a program or library that
-# is built using GNU Libtool, you may include this file under the
-# same distribution terms that you use for the rest of that program.
-#
-# GNU Libtool is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Libtool; see the file COPYING. If not, a copy
-# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
-# obtained by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-])
-
-# serial 56 LT_INIT
-
-
-# LT_PREREQ(VERSION)
-# ------------------
-# Complain and exit if this libtool version is less that VERSION.
-m4_defun([LT_PREREQ],
-[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
- [m4_default([$3],
- [m4_fatal([Libtool version $1 or higher is required],
- 63)])],
- [$2])])
-
-
-# _LT_CHECK_BUILDDIR
-# ------------------
-# Complain if the absolute build directory name contains unusual characters
-m4_defun([_LT_CHECK_BUILDDIR],
-[case `pwd` in
- *\ * | *\ *)
- AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
-esac
-])
-
-
-# LT_INIT([OPTIONS])
-# ------------------
-AC_DEFUN([LT_INIT],
-[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
-AC_BEFORE([$0], [LT_LANG])dnl
-AC_BEFORE([$0], [LT_OUTPUT])dnl
-AC_BEFORE([$0], [LTDL_INIT])dnl
-m4_require([_LT_CHECK_BUILDDIR])dnl
-
-dnl Autoconf doesn't catch unexpanded LT_ macros by default:
-m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
-m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
-dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
-dnl unless we require an AC_DEFUNed macro:
-AC_REQUIRE([LTOPTIONS_VERSION])dnl
-AC_REQUIRE([LTSUGAR_VERSION])dnl
-AC_REQUIRE([LTVERSION_VERSION])dnl
-AC_REQUIRE([LTOBSOLETE_VERSION])dnl
-m4_require([_LT_PROG_LTMAIN])dnl
-
-dnl Parse OPTIONS
-_LT_SET_OPTIONS([$0], [$1])
-
-# This can be used to rebuild libtool when needed
-LIBTOOL_DEPS="$ltmain"
-
-# Always use our own libtool.
-LIBTOOL='$(SHELL) $(top_builddir)/libtool'
-AC_SUBST(LIBTOOL)dnl
-
-_LT_SETUP
-
-# Only expand once:
-m4_define([LT_INIT])
-])# LT_INIT
-
-# Old names:
-AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
-AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
-dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
-
-
-# _LT_CC_BASENAME(CC)
-# -------------------
-# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
-m4_defun([_LT_CC_BASENAME],
-[for cc_temp in $1""; do
- case $cc_temp in
- compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
- distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-])
-
-
-# _LT_FILEUTILS_DEFAULTS
-# ----------------------
-# It is okay to use these file commands and assume they have been set
-# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
-m4_defun([_LT_FILEUTILS_DEFAULTS],
-[: ${CP="cp -f"}
-: ${MV="mv -f"}
-: ${RM="rm -f"}
-])# _LT_FILEUTILS_DEFAULTS
-
-
-# _LT_SETUP
-# ---------
-m4_defun([_LT_SETUP],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-_LT_DECL([], [host_alias], [0], [The host system])dnl
-_LT_DECL([], [host], [0])dnl
-_LT_DECL([], [host_os], [0])dnl
-dnl
-_LT_DECL([], [build_alias], [0], [The build system])dnl
-_LT_DECL([], [build], [0])dnl
-_LT_DECL([], [build_os], [0])dnl
-dnl
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([LT_PATH_LD])dnl
-AC_REQUIRE([LT_PATH_NM])dnl
-dnl
-AC_REQUIRE([AC_PROG_LN_S])dnl
-test -z "$LN_S" && LN_S="ln -s"
-_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
-dnl
-AC_REQUIRE([LT_CMD_MAX_LEN])dnl
-_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
-_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
-dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_CHECK_SHELL_FEATURES])dnl
-m4_require([_LT_CMD_RELOAD])dnl
-m4_require([_LT_CHECK_MAGIC_METHOD])dnl
-m4_require([_LT_CMD_OLD_ARCHIVE])dnl
-m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
-
-_LT_CONFIG_LIBTOOL_INIT([
-# See if we are running on zsh, and set the options which allow our
-# commands through without removal of \ escapes INIT.
-if test -n "\${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
-fi
-])
-if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
-fi
-
-_LT_CHECK_OBJDIR
-
-m4_require([_LT_TAG_COMPILER])dnl
-_LT_PROG_ECHO_BACKSLASH
-
-case $host_os in
-aix3*)
- # AIX sometimes has problems with the GCC collect2 program. For some
- # reason, if we set the COLLECT_NAMES environment variable, the problems
- # vanish in a puff of smoke.
- if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
- fi
- ;;
-esac
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([["`\\]]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to delay expansion of an escaped single quote.
-delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-
-# Global variables:
-ofile=libtool
-can_build_shared=yes
-
-# All known linkers require a `.a' archive for static linking (except MSVC,
-# which needs '.lib').
-libext=a
-
-with_gnu_ld="$lt_cv_prog_gnu_ld"
-
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-
-# Set sane defaults for various variables
-test -z "$CC" && CC=cc
-test -z "$LTCC" && LTCC=$CC
-test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
-test -z "$LD" && LD=ld
-test -z "$ac_objext" && ac_objext=o
-
-_LT_CC_BASENAME([$compiler])
-
-# Only perform the check for file, if the check method requires it
-test -z "$MAGIC_CMD" && MAGIC_CMD=file
-case $deplibs_check_method in
-file_magic*)
- if test "$file_magic_cmd" = '$MAGIC_CMD'; then
- _LT_PATH_MAGIC
- fi
- ;;
-esac
-
-# Use C for the default configuration in the libtool script
-LT_SUPPORTED_TAG([CC])
-_LT_LANG_C_CONFIG
-_LT_LANG_DEFAULT_CONFIG
-_LT_CONFIG_COMMANDS
-])# _LT_SETUP
-
-
-# _LT_PROG_LTMAIN
-# ---------------
-# Note that this code is called both from `configure', and `config.status'
-# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
-# `config.status' has no value for ac_aux_dir unless we are using Automake,
-# so we pass a copy along to make sure it has a sensible value anyway.
-m4_defun([_LT_PROG_LTMAIN],
-[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
-_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
-ltmain="$ac_aux_dir/ltmain.sh"
-])# _LT_PROG_LTMAIN
-
-
-
-# So that we can recreate a full libtool script including additional
-# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
-# in macros and then make a single call at the end using the `libtool'
-# label.
-
-
-# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
-# ----------------------------------------
-# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
-m4_define([_LT_CONFIG_LIBTOOL_INIT],
-[m4_ifval([$1],
- [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
- [$1
-])])])
-
-# Initialize.
-m4_define([_LT_OUTPUT_LIBTOOL_INIT])
-
-
-# _LT_CONFIG_LIBTOOL([COMMANDS])
-# ------------------------------
-# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
-m4_define([_LT_CONFIG_LIBTOOL],
-[m4_ifval([$1],
- [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
- [$1
-])])])
-
-# Initialize.
-m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
-
-
-# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
-# -----------------------------------------------------
-m4_defun([_LT_CONFIG_SAVE_COMMANDS],
-[_LT_CONFIG_LIBTOOL([$1])
-_LT_CONFIG_LIBTOOL_INIT([$2])
-])
-
-
-# _LT_FORMAT_COMMENT([COMMENT])
-# -----------------------------
-# Add leading comment marks to the start of each line, and a trailing
-# full-stop to the whole comment if one is not present already.
-m4_define([_LT_FORMAT_COMMENT],
-[m4_ifval([$1], [
-m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
- [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
-)])
-
-
-
-
-
-# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
-# -------------------------------------------------------------------
-# CONFIGNAME is the name given to the value in the libtool script.
-# VARNAME is the (base) name used in the configure script.
-# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
-# VARNAME. Any other value will be used directly.
-m4_define([_LT_DECL],
-[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
- [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
- [m4_ifval([$1], [$1], [$2])])
- lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
- m4_ifval([$4],
- [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
- lt_dict_add_subkey([lt_decl_dict], [$2],
- [tagged?], [m4_ifval([$5], [yes], [no])])])
-])
-
-
-# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
-# --------------------------------------------------------
-m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
-
-
-# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
-# ------------------------------------------------
-m4_define([lt_decl_tag_varnames],
-[_lt_decl_filter([tagged?], [yes], $@)])
-
-
-# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
-# ---------------------------------------------------------
-m4_define([_lt_decl_filter],
-[m4_case([$#],
- [0], [m4_fatal([$0: too few arguments: $#])],
- [1], [m4_fatal([$0: too few arguments: $#: $1])],
- [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
- [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
- [lt_dict_filter([lt_decl_dict], $@)])[]dnl
-])
-
-
-# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
-# --------------------------------------------------
-m4_define([lt_decl_quote_varnames],
-[_lt_decl_filter([value], [1], $@)])
-
-
-# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
-# ---------------------------------------------------
-m4_define([lt_decl_dquote_varnames],
-[_lt_decl_filter([value], [2], $@)])
-
-
-# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
-# ---------------------------------------------------
-m4_define([lt_decl_varnames_tagged],
-[m4_assert([$# <= 2])dnl
-_$0(m4_quote(m4_default([$1], [[, ]])),
- m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
- m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
-m4_define([_lt_decl_varnames_tagged],
-[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
-
-
-# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
-# ------------------------------------------------
-m4_define([lt_decl_all_varnames],
-[_$0(m4_quote(m4_default([$1], [[, ]])),
- m4_if([$2], [],
- m4_quote(lt_decl_varnames),
- m4_quote(m4_shift($@))))[]dnl
-])
-m4_define([_lt_decl_all_varnames],
-[lt_join($@, lt_decl_varnames_tagged([$1],
- lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
-])
-
-
-# _LT_CONFIG_STATUS_DECLARE([VARNAME])
-# ------------------------------------
-# Quote a variable value, and forward it to `config.status' so that its
-# declaration there will have the same value as in `configure'. VARNAME
-# must have a single quote delimited value for this to work.
-m4_define([_LT_CONFIG_STATUS_DECLARE],
-[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`'])
-
-
-# _LT_CONFIG_STATUS_DECLARATIONS
-# ------------------------------
-# We delimit libtool config variables with single quotes, so when
-# we write them to config.status, we have to be sure to quote all
-# embedded single quotes properly. In configure, this macro expands
-# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
-#
-# <var>='`$ECHO "X$<var>" | $Xsed -e "$delay_single_quote_subst"`'
-m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
-[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
- [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
-
-
-# _LT_LIBTOOL_TAGS
-# ----------------
-# Output comment and list of tags supported by the script
-m4_defun([_LT_LIBTOOL_TAGS],
-[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
-available_tags="_LT_TAGS"dnl
-])
-
-
-# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
-# -----------------------------------
-# Extract the dictionary values for VARNAME (optionally with TAG) and
-# expand to a commented shell variable setting:
-#
-# # Some comment about what VAR is for.
-# visible_name=$lt_internal_name
-m4_define([_LT_LIBTOOL_DECLARE],
-[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
- [description])))[]dnl
-m4_pushdef([_libtool_name],
- m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
-m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
- [0], [_libtool_name=[$]$1],
- [1], [_libtool_name=$lt_[]$1],
- [2], [_libtool_name=$lt_[]$1],
- [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
-m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
-])
-
-
-# _LT_LIBTOOL_CONFIG_VARS
-# -----------------------
-# Produce commented declarations of non-tagged libtool config variables
-# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
-# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
-# section) are produced by _LT_LIBTOOL_TAG_VARS.
-m4_defun([_LT_LIBTOOL_CONFIG_VARS],
-[m4_foreach([_lt_var],
- m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
- [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
-
-
-# _LT_LIBTOOL_TAG_VARS(TAG)
-# -------------------------
-m4_define([_LT_LIBTOOL_TAG_VARS],
-[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
- [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
-
-
-# _LT_TAGVAR(VARNAME, [TAGNAME])
-# ------------------------------
-m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
-
-
-# _LT_CONFIG_COMMANDS
-# -------------------
-# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
-# variables for single and double quote escaping we saved from calls
-# to _LT_DECL, we can put quote escaped variables declarations
-# into `config.status', and then the shell code to quote escape them in
-# for loops in `config.status'. Finally, any additional code accumulated
-# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
-m4_defun([_LT_CONFIG_COMMANDS],
-[AC_PROVIDE_IFELSE([LT_OUTPUT],
- dnl If the libtool generation code has been placed in $CONFIG_LT,
- dnl instead of duplicating it all over again into config.status,
- dnl then we will have config.status run $CONFIG_LT later, so it
- dnl needs to know what name is stored there:
- [AC_CONFIG_COMMANDS([libtool],
- [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
- dnl If the libtool generation code is destined for config.status,
- dnl expand the accumulated commands and init code now:
- [AC_CONFIG_COMMANDS([libtool],
- [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
-])#_LT_CONFIG_COMMANDS
-
-
-# Initialize.
-m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
-[
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-sed_quote_subst='$sed_quote_subst'
-double_quote_subst='$double_quote_subst'
-delay_variable_subst='$delay_variable_subst'
-_LT_CONFIG_STATUS_DECLARATIONS
-LTCC='$LTCC'
-LTCFLAGS='$LTCFLAGS'
-compiler='$compiler_DEFAULT'
-
-# Quote evaled strings.
-for var in lt_decl_all_varnames([[ \
-]], lt_decl_quote_varnames); do
- case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
- *[[\\\\\\\`\\"\\\$]]*)
- eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
- ;;
- *)
- eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
- ;;
- esac
-done
-
-# Double-quote double-evaled strings.
-for var in lt_decl_all_varnames([[ \
-]], lt_decl_dquote_varnames); do
- case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
- *[[\\\\\\\`\\"\\\$]]*)
- eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
- ;;
- *)
- eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
- ;;
- esac
-done
-
-# Fix-up fallback echo if it was mangled by the above quoting rules.
-case \$lt_ECHO in
-*'\\\[$]0 --fallback-echo"')dnl "
- lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
- ;;
-esac
-
-_LT_OUTPUT_LIBTOOL_INIT
-])
-
-
-# LT_OUTPUT
-# ---------
-# This macro allows early generation of the libtool script (before
-# AC_OUTPUT is called), incase it is used in configure for compilation
-# tests.
-AC_DEFUN([LT_OUTPUT],
-[: ${CONFIG_LT=./config.lt}
-AC_MSG_NOTICE([creating $CONFIG_LT])
-cat >"$CONFIG_LT" <<_LTEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate a libtool stub with the current configuration.
-
-lt_cl_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_LTEOF
-
-cat >>"$CONFIG_LT" <<\_LTEOF
-AS_SHELL_SANITIZE
-_AS_PREPARE
-
-exec AS_MESSAGE_FD>&1
-exec AS_MESSAGE_LOG_FD>>config.log
-{
- echo
- AS_BOX([Running $as_me.])
-} >&AS_MESSAGE_LOG_FD
-
-lt_cl_help="\
-\`$as_me' creates a local libtool stub from the current configuration,
-for use in further configure time tests before the real libtool is
-generated.
-
-Usage: $[0] [[OPTIONS]]
-
- -h, --help print this help, then exit
- -V, --version print version number, then exit
- -q, --quiet do not print progress messages
- -d, --debug don't remove temporary files
-
-Report bugs to <bug-libtool@gnu.org>."
-
-lt_cl_version="\
-m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
-m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
-configured by $[0], generated by m4_PACKAGE_STRING.
-
-Copyright (C) 2008 Free Software Foundation, Inc.
-This config.lt script is free software; the Free Software Foundation
-gives unlimited permision to copy, distribute and modify it."
-
-while test $[#] != 0
-do
- case $[1] in
- --version | --v* | -V )
- echo "$lt_cl_version"; exit 0 ;;
- --help | --h* | -h )
- echo "$lt_cl_help"; exit 0 ;;
- --debug | --d* | -d )
- debug=: ;;
- --quiet | --q* | --silent | --s* | -q )
- lt_cl_silent=: ;;
-
- -*) AC_MSG_ERROR([unrecognized option: $[1]
-Try \`$[0] --help' for more information.]) ;;
-
- *) AC_MSG_ERROR([unrecognized argument: $[1]
-Try \`$[0] --help' for more information.]) ;;
- esac
- shift
-done
-
-if $lt_cl_silent; then
- exec AS_MESSAGE_FD>/dev/null
-fi
-_LTEOF
-
-cat >>"$CONFIG_LT" <<_LTEOF
-_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
-_LTEOF
-
-cat >>"$CONFIG_LT" <<\_LTEOF
-AC_MSG_NOTICE([creating $ofile])
-_LT_OUTPUT_LIBTOOL_COMMANDS
-AS_EXIT(0)
-_LTEOF
-chmod +x "$CONFIG_LT"
-
-# configure is writing to config.log, but config.lt does its own redirection,
-# appending to config.log, which fails on DOS, as config.log is still kept
-# open by configure. Here we exec the FD to /dev/null, effectively closing
-# config.log, so it can be properly (re)opened and appended to by config.lt.
-if test "$no_create" != yes; then
- lt_cl_success=:
- test "$silent" = yes &&
- lt_config_lt_args="$lt_config_lt_args --quiet"
- exec AS_MESSAGE_LOG_FD>/dev/null
- $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
- exec AS_MESSAGE_LOG_FD>>config.log
- $lt_cl_success || AS_EXIT(1)
-fi
-])# LT_OUTPUT
-
-
-# _LT_CONFIG(TAG)
-# ---------------
-# If TAG is the built-in tag, create an initial libtool script with a
-# default configuration from the untagged config vars. Otherwise add code
-# to config.status for appending the configuration named by TAG from the
-# matching tagged config vars.
-m4_defun([_LT_CONFIG],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-_LT_CONFIG_SAVE_COMMANDS([
- m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
- m4_if(_LT_TAG, [C], [
- # See if we are running on zsh, and set the options which allow our
- # commands through without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
-
- cfgfile="${ofile}T"
- trap "$RM \"$cfgfile\"; exit 1" 1 2 15
- $RM "$cfgfile"
-
- cat <<_LT_EOF >> "$cfgfile"
-#! $SHELL
-
-# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-# NOTE: Changes made to this file will be lost: look at ltmain.sh.
-#
-_LT_COPYING
-_LT_LIBTOOL_TAGS
-
-# ### BEGIN LIBTOOL CONFIG
-_LT_LIBTOOL_CONFIG_VARS
-_LT_LIBTOOL_TAG_VARS
-# ### END LIBTOOL CONFIG
-
-_LT_EOF
-
- case $host_os in
- aix3*)
- cat <<\_LT_EOF >> "$cfgfile"
-# AIX sometimes has problems with the GCC collect2 program. For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
-fi
-_LT_EOF
- ;;
- esac
-
- _LT_PROG_LTMAIN
-
- # We use sed instead of cat because bash on DJGPP gets confused if
- # if finds mixed CR/LF and LF-only lines. Since sed operates in
- # text mode, it properly converts lines to CR/LF. This bash problem
- # is reportedly fixed, but why not run on old versions too?
- sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
- || (rm -f "$cfgfile"; exit 1)
-
- _LT_PROG_XSI_SHELLFNS
-
- sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
- || (rm -f "$cfgfile"; exit 1)
-
- mv -f "$cfgfile" "$ofile" ||
- (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
- chmod +x "$ofile"
-],
-[cat <<_LT_EOF >> "$ofile"
-
-dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
-dnl in a comment (ie after a #).
-# ### BEGIN LIBTOOL TAG CONFIG: $1
-_LT_LIBTOOL_TAG_VARS(_LT_TAG)
-# ### END LIBTOOL TAG CONFIG: $1
-_LT_EOF
-])dnl /m4_if
-],
-[m4_if([$1], [], [
- PACKAGE='$PACKAGE'
- VERSION='$VERSION'
- TIMESTAMP='$TIMESTAMP'
- RM='$RM'
- ofile='$ofile'], [])
-])dnl /_LT_CONFIG_SAVE_COMMANDS
-])# _LT_CONFIG
-
-
-# LT_SUPPORTED_TAG(TAG)
-# ---------------------
-# Trace this macro to discover what tags are supported by the libtool
-# --tag option, using:
-# autoconf --trace 'LT_SUPPORTED_TAG:$1'
-AC_DEFUN([LT_SUPPORTED_TAG], [])
-
-
-# C support is built-in for now
-m4_define([_LT_LANG_C_enabled], [])
-m4_define([_LT_TAGS], [])
-
-
-# LT_LANG(LANG)
-# -------------
-# Enable libtool support for the given language if not already enabled.
-AC_DEFUN([LT_LANG],
-[AC_BEFORE([$0], [LT_OUTPUT])dnl
-m4_case([$1],
- [C], [_LT_LANG(C)],
- [C++], [_LT_LANG(CXX)],
- [Java], [_LT_LANG(GCJ)],
- [Fortran 77], [_LT_LANG(F77)],
- [Fortran], [_LT_LANG(FC)],
- [Windows Resource], [_LT_LANG(RC)],
- [m4_ifdef([_LT_LANG_]$1[_CONFIG],
- [_LT_LANG($1)],
- [m4_fatal([$0: unsupported language: "$1"])])])dnl
-])# LT_LANG
-
-
-# _LT_LANG(LANGNAME)
-# ------------------
-m4_defun([_LT_LANG],
-[m4_ifdef([_LT_LANG_]$1[_enabled], [],
- [LT_SUPPORTED_TAG([$1])dnl
- m4_append([_LT_TAGS], [$1 ])dnl
- m4_define([_LT_LANG_]$1[_enabled], [])dnl
- _LT_LANG_$1_CONFIG($1)])dnl
-])# _LT_LANG
-
-
-# _LT_LANG_DEFAULT_CONFIG
-# -----------------------
-m4_defun([_LT_LANG_DEFAULT_CONFIG],
-[AC_PROVIDE_IFELSE([AC_PROG_CXX],
- [LT_LANG(CXX)],
- [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
-
-AC_PROVIDE_IFELSE([AC_PROG_F77],
- [LT_LANG(F77)],
- [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
-
-AC_PROVIDE_IFELSE([AC_PROG_FC],
- [LT_LANG(FC)],
- [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
-
-dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
-dnl pulling things in needlessly.
-AC_PROVIDE_IFELSE([AC_PROG_GCJ],
- [LT_LANG(GCJ)],
- [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
- [LT_LANG(GCJ)],
- [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
- [LT_LANG(GCJ)],
- [m4_ifdef([AC_PROG_GCJ],
- [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
- m4_ifdef([A][M_PROG_GCJ],
- [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
- m4_ifdef([LT_PROG_GCJ],
- [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
-
-AC_PROVIDE_IFELSE([LT_PROG_RC],
- [LT_LANG(RC)],
- [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
-])# _LT_LANG_DEFAULT_CONFIG
-
-# Obsolete macros:
-AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
-AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
-AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
-AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
-dnl AC_DEFUN([AC_LIBTOOL_F77], [])
-dnl AC_DEFUN([AC_LIBTOOL_FC], [])
-dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
-
-
-# _LT_TAG_COMPILER
-# ----------------
-m4_defun([_LT_TAG_COMPILER],
-[AC_REQUIRE([AC_PROG_CC])dnl
-
-_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
-_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
-_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
-_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-])# _LT_TAG_COMPILER
-
-
-# _LT_COMPILER_BOILERPLATE
-# ------------------------
-# Check for compiler boilerplate output or warnings with
-# the simple compiler test code.
-m4_defun([_LT_COMPILER_BOILERPLATE],
-[m4_require([_LT_DECL_SED])dnl
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$RM conftest*
-])# _LT_COMPILER_BOILERPLATE
-
-
-# _LT_LINKER_BOILERPLATE
-# ----------------------
-# Check for linker boilerplate output or warnings with
-# the simple link test code.
-m4_defun([_LT_LINKER_BOILERPLATE],
-[m4_require([_LT_DECL_SED])dnl
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$RM -r conftest*
-])# _LT_LINKER_BOILERPLATE
-
-# _LT_REQUIRED_DARWIN_CHECKS
-# -------------------------
-m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
- case $host_os in
- rhapsody* | darwin*)
- AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
- AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
- AC_CHECK_TOOL([LIPO], [lipo], [:])
- AC_CHECK_TOOL([OTOOL], [otool], [:])
- AC_CHECK_TOOL([OTOOL64], [otool64], [:])
- _LT_DECL([], [DSYMUTIL], [1],
- [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
- _LT_DECL([], [NMEDIT], [1],
- [Tool to change global to local symbols on Mac OS X])
- _LT_DECL([], [LIPO], [1],
- [Tool to manipulate fat objects and archives on Mac OS X])
- _LT_DECL([], [OTOOL], [1],
- [ldd/readelf like tool for Mach-O binaries on Mac OS X])
- _LT_DECL([], [OTOOL64], [1],
- [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
-
- AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
- [lt_cv_apple_cc_single_mod=no
- if test -z "${LT_MULTI_MODULE}"; then
- # By default we will add the -single_module flag. You can override
- # by either setting the environment variable LT_MULTI_MODULE
- # non-empty at configure time, or by adding -multi_module to the
- # link flags.
- rm -rf libconftest.dylib*
- echo "int foo(void){return 1;}" > conftest.c
- echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
--dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
- $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
- -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
- _lt_result=$?
- if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
- lt_cv_apple_cc_single_mod=yes
- else
- cat conftest.err >&AS_MESSAGE_LOG_FD
- fi
- rm -rf libconftest.dylib*
- rm -f conftest.*
- fi])
- AC_CACHE_CHECK([for -exported_symbols_list linker flag],
- [lt_cv_ld_exported_symbols_list],
- [lt_cv_ld_exported_symbols_list=no
- save_LDFLAGS=$LDFLAGS
- echo "_main" > conftest.sym
- LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
- AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
- [lt_cv_ld_exported_symbols_list=yes],
- [lt_cv_ld_exported_symbols_list=no])
- LDFLAGS="$save_LDFLAGS"
- ])
- case $host_os in
- rhapsody* | darwin1.[[012]])
- _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
- darwin1.*)
- _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- darwin*) # darwin 5.x on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- 10.[[012]]*)
- _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- 10.*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- esac
- ;;
- esac
- if test "$lt_cv_apple_cc_single_mod" = "yes"; then
- _lt_dar_single_mod='$single_module'
- fi
- if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
- _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
- else
- _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
- fi
- if test "$DSYMUTIL" != ":"; then
- _lt_dsymutil='~$DSYMUTIL $lib || :'
- else
- _lt_dsymutil=
- fi
- ;;
- esac
-])
-
-
-# _LT_DARWIN_LINKER_FEATURES
-# --------------------------
-# Checks for linker and compiler features on darwin
-m4_defun([_LT_DARWIN_LINKER_FEATURES],
-[
- m4_require([_LT_REQUIRED_DARWIN_CHECKS])
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_automatic, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
- _LT_TAGVAR(whole_archive_flag_spec, $1)=''
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
- case $cc_basename in
- ifort*) _lt_dar_can_shared=yes ;;
- *) _lt_dar_can_shared=$GCC ;;
- esac
- if test "$_lt_dar_can_shared" = "yes"; then
- output_verbose_link_cmd=echo
- _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
- _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
- _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
- _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
- m4_if([$1], [CXX],
-[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
- _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
- _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
- fi
-],[])
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
-])
-
-# _LT_SYS_MODULE_PATH_AIX
-# -----------------------
-# Links a minimal program and checks the executable
-# for the system default hardcoded library path. In most cases,
-# this is /usr/lib:/lib, but when the MPI compilers are used
-# the location of the communication and MPI libs are included too.
-# If we don't find anything, use the default library path according
-# to the aix ld manual.
-m4_defun([_LT_SYS_MODULE_PATH_AIX],
-[m4_require([_LT_DECL_SED])dnl
-AC_LINK_IFELSE(AC_LANG_PROGRAM,[
-lt_aix_libpath_sed='
- /Import File Strings/,/^$/ {
- /^0/ {
- s/^0 *\(.*\)$/\1/
- p
- }
- }'
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then
- aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-fi],[])
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-])# _LT_SYS_MODULE_PATH_AIX
-
-
-# _LT_SHELL_INIT(ARG)
-# -------------------
-m4_define([_LT_SHELL_INIT],
-[ifdef([AC_DIVERSION_NOTICE],
- [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
- [AC_DIVERT_PUSH(NOTICE)])
-$1
-AC_DIVERT_POP
-])# _LT_SHELL_INIT
-
-
-# _LT_PROG_ECHO_BACKSLASH
-# -----------------------
-# Add some code to the start of the generated configure script which
-# will find an echo command which doesn't interpret backslashes.
-m4_defun([_LT_PROG_ECHO_BACKSLASH],
-[_LT_SHELL_INIT([
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-case X$lt_ECHO in
-X*--fallback-echo)
- # Remove one level of quotation (which was required for Make).
- ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
- ;;
-esac
-
-ECHO=${lt_ECHO-echo}
-if test "X[$]1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X[$]1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
- # Yippee, $ECHO works!
- :
-else
- # Restart under the correct shell.
- exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
-fi
-
-if test "X[$]1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<_LT_EOF
-[$]*
-_LT_EOF
- exit 0
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-if test -z "$lt_ECHO"; then
- if test "X${echo_test_string+set}" != Xset; then
- # find a string as large as possible, as long as the shell can cope with it
- for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
- # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
- if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
- { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
- then
- break
- fi
- done
- fi
-
- if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- :
- else
- # The Solaris, AIX, and Digital Unix default echo programs unquote
- # backslashes. This makes it impossible to quote backslashes using
- # echo "$something" | sed 's/\\/\\\\/g'
- #
- # So, first we look for a working echo in the user's PATH.
-
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for dir in $PATH /usr/ucb; do
- IFS="$lt_save_ifs"
- if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
- test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- ECHO="$dir/echo"
- break
- fi
- done
- IFS="$lt_save_ifs"
-
- if test "X$ECHO" = Xecho; then
- # We didn't find a better echo, so look for alternatives.
- if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- # This shell has a builtin print -r that does the trick.
- ECHO='print -r'
- elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
- test "X$CONFIG_SHELL" != X/bin/ksh; then
- # If we have ksh, try running configure again with it.
- ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
- export ORIGINAL_CONFIG_SHELL
- CONFIG_SHELL=/bin/ksh
- export CONFIG_SHELL
- exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
- else
- # Try using printf.
- ECHO='printf %s\n'
- if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- # Cool, printf works
- :
- elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
- test "X$echo_testing_string" = 'X\t' &&
- echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
- export CONFIG_SHELL
- SHELL="$CONFIG_SHELL"
- export SHELL
- ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
- elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
- test "X$echo_testing_string" = 'X\t' &&
- echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
- else
- # maybe with a smaller string...
- prev=:
-
- for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
- if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
- then
- break
- fi
- prev="$cmd"
- done
-
- if test "$prev" != 'sed 50q "[$]0"'; then
- echo_test_string=`eval $prev`
- export echo_test_string
- exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
- else
- # Oops. We lost completely, so just stick with echo.
- ECHO=echo
- fi
- fi
- fi
- fi
- fi
-fi
-
-# Copy echo and quote the copy suitably for passing to libtool from
-# the Makefile, instead of quoting the original, which is used later.
-lt_ECHO=$ECHO
-if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
- lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
-fi
-
-AC_SUBST(lt_ECHO)
-])
-_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
-_LT_DECL([], [ECHO], [1],
- [An echo program that does not interpret backslashes])
-])# _LT_PROG_ECHO_BACKSLASH
-
-
-# _LT_ENABLE_LOCK
-# ---------------
-m4_defun([_LT_ENABLE_LOCK],
-[AC_ARG_ENABLE([libtool-lock],
- [AS_HELP_STRING([--disable-libtool-lock],
- [avoid locking (might break parallel builds)])])
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
-
-# Some flags need to be propagated to the compiler or linker for good
-# libtool support.
-case $host in
-ia64-*-hpux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.$ac_objext` in
- *ELF-32*)
- HPUX_IA64_MODE="32"
- ;;
- *ELF-64*)
- HPUX_IA64_MODE="64"
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-*-*-irix6*)
- # Find out which ABI we are using.
- echo '[#]line __oline__ "configure"' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- if test "$lt_cv_prog_gnu_ld" = yes; then
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -melf32bsmip"
- ;;
- *N32*)
- LD="${LD-ld} -melf32bmipn32"
- ;;
- *64-bit*)
- LD="${LD-ld} -melf64bmip"
- ;;
- esac
- else
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -32"
- ;;
- *N32*)
- LD="${LD-ld} -n32"
- ;;
- *64-bit*)
- LD="${LD-ld} -64"
- ;;
- esac
- fi
- fi
- rm -rf conftest*
- ;;
-
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
-s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.o` in
- *32-bit*)
- case $host in
- x86_64-*kfreebsd*-gnu)
- LD="${LD-ld} -m elf_i386_fbsd"
- ;;
- x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
- ;;
- ppc64-*linux*|powerpc64-*linux*)
- LD="${LD-ld} -m elf32ppclinux"
- ;;
- s390x-*linux*)
- LD="${LD-ld} -m elf_s390"
- ;;
- sparc64-*linux*)
- LD="${LD-ld} -m elf32_sparc"
- ;;
- esac
- ;;
- *64-bit*)
- case $host in
- x86_64-*kfreebsd*-gnu)
- LD="${LD-ld} -m elf_x86_64_fbsd"
- ;;
- x86_64-*linux*)
- LD="${LD-ld} -m elf_x86_64"
- ;;
- ppc*-*linux*|powerpc*-*linux*)
- LD="${LD-ld} -m elf64ppc"
- ;;
- s390*-*linux*|s390*-*tpf*)
- LD="${LD-ld} -m elf64_s390"
- ;;
- sparc*-*linux*)
- LD="${LD-ld} -m elf64_sparc"
- ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-
-*-*-sco3.2v5*)
- # On SCO OpenServer 5, we need -belf to get full-featured binaries.
- SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -belf"
- AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
- [AC_LANG_PUSH(C)
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
- AC_LANG_POP])
- if test x"$lt_cv_cc_needs_belf" != x"yes"; then
- # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
- CFLAGS="$SAVE_CFLAGS"
- fi
- ;;
-sparc*-*solaris*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.o` in
- *64-bit*)
- case $lt_cv_prog_gnu_ld in
- yes*) LD="${LD-ld} -m elf64_sparc" ;;
- *)
- if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
- LD="${LD-ld} -64"
- fi
- ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-esac
-
-need_locks="$enable_libtool_lock"
-])# _LT_ENABLE_LOCK
-
-
-# _LT_CMD_OLD_ARCHIVE
-# -------------------
-m4_defun([_LT_CMD_OLD_ARCHIVE],
-[AC_CHECK_TOOL(AR, ar, false)
-test -z "$AR" && AR=ar
-test -z "$AR_FLAGS" && AR_FLAGS=cru
-_LT_DECL([], [AR], [1], [The archiver])
-_LT_DECL([], [AR_FLAGS], [1])
-
-AC_CHECK_TOOL(STRIP, strip, :)
-test -z "$STRIP" && STRIP=:
-_LT_DECL([], [STRIP], [1], [A symbol stripping program])
-
-AC_CHECK_TOOL(RANLIB, ranlib, :)
-test -z "$RANLIB" && RANLIB=:
-_LT_DECL([], [RANLIB], [1],
- [Commands used to install an old-style archive])
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-if test -n "$RANLIB"; then
- case $host_os in
- openbsd*)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
- ;;
- *)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
- ;;
- esac
- old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
-fi
-_LT_DECL([], [old_postinstall_cmds], [2])
-_LT_DECL([], [old_postuninstall_cmds], [2])
-_LT_TAGDECL([], [old_archive_cmds], [2],
- [Commands used to build an old-style archive])
-])# _LT_CMD_OLD_ARCHIVE
-
-
-# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
-# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
-# ----------------------------------------------------------------
-# Check whether the given compiler option works
-AC_DEFUN([_LT_COMPILER_OPTION],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_SED])dnl
-AC_CACHE_CHECK([$1], [$2],
- [$2=no
- m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="$3"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&AS_MESSAGE_LOG_FD
- echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- $2=yes
- fi
- fi
- $RM conftest*
-])
-
-if test x"[$]$2" = xyes; then
- m4_if([$5], , :, [$5])
-else
- m4_if([$6], , :, [$6])
-fi
-])# _LT_COMPILER_OPTION
-
-# Old name:
-AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
-
-
-# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
-# [ACTION-SUCCESS], [ACTION-FAILURE])
-# ----------------------------------------------------
-# Check whether the given linker option works
-AC_DEFUN([_LT_LINKER_OPTION],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_SED])dnl
-AC_CACHE_CHECK([$1], [$2],
- [$2=no
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $3"
- echo "$lt_simple_link_test_code" > conftest.$ac_ext
- if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
- # The linker can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- # Append any errors to the config.log.
- cat conftest.err 1>&AS_MESSAGE_LOG_FD
- $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if diff conftest.exp conftest.er2 >/dev/null; then
- $2=yes
- fi
- else
- $2=yes
- fi
- fi
- $RM -r conftest*
- LDFLAGS="$save_LDFLAGS"
-])
-
-if test x"[$]$2" = xyes; then
- m4_if([$4], , :, [$4])
-else
- m4_if([$5], , :, [$5])
-fi
-])# _LT_LINKER_OPTION
-
-# Old name:
-AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
-
-
-# LT_CMD_MAX_LEN
-#---------------
-AC_DEFUN([LT_CMD_MAX_LEN],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-# find the maximum length of command line arguments
-AC_MSG_CHECKING([the maximum length of command line arguments])
-AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
- i=0
- teststring="ABCD"
-
- case $build_os in
- msdosdjgpp*)
- # On DJGPP, this test can blow up pretty badly due to problems in libc
- # (any single argument exceeding 2000 bytes causes a buffer overrun
- # during glob expansion). Even if it were fixed, the result of this
- # check would be larger than it should be.
- lt_cv_sys_max_cmd_len=12288; # 12K is about right
- ;;
-
- gnu*)
- # Under GNU Hurd, this test is not required because there is
- # no limit to the length of command line arguments.
- # Libtool will interpret -1 as no limit whatsoever
- lt_cv_sys_max_cmd_len=-1;
- ;;
-
- cygwin* | mingw* | cegcc*)
- # On Win9x/ME, this test blows up -- it succeeds, but takes
- # about 5 minutes as the teststring grows exponentially.
- # Worse, since 9x/ME are not pre-emptively multitasking,
- # you end up with a "frozen" computer, even though with patience
- # the test eventually succeeds (with a max line length of 256k).
- # Instead, let's just punt: use the minimum linelength reported by
- # all of the supported platforms: 8192 (on NT/2K/XP).
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- amigaos*)
- # On AmigaOS with pdksh, this test takes hours, literally.
- # So we just punt and use a minimum line length of 8192.
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
- # This has been around since 386BSD, at least. Likely further.
- if test -x /sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
- elif test -x /usr/sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
- else
- lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
- fi
- # And add a safety zone
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
- ;;
-
- interix*)
- # We know the value 262144 and hardcode it with a safety zone (like BSD)
- lt_cv_sys_max_cmd_len=196608
- ;;
-
- osf*)
- # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
- # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
- # nice to cause kernel panics so lets avoid the loop below.
- # First set a reasonable default.
- lt_cv_sys_max_cmd_len=16384
- #
- if test -x /sbin/sysconfig; then
- case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
- *1*) lt_cv_sys_max_cmd_len=-1 ;;
- esac
- fi
- ;;
- sco3.2v5*)
- lt_cv_sys_max_cmd_len=102400
- ;;
- sysv5* | sco5v6* | sysv4.2uw2*)
- kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
- if test -n "$kargmax"; then
- lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
- else
- lt_cv_sys_max_cmd_len=32768
- fi
- ;;
- *)
- lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
- if test -n "$lt_cv_sys_max_cmd_len"; then
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
- else
- # Make teststring a little bigger before we do anything with it.
- # a 1K string should be a reasonable start.
- for i in 1 2 3 4 5 6 7 8 ; do
- teststring=$teststring$teststring
- done
- SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
- # If test is not a shell built-in, we'll probably end up computing a
- # maximum length that is only half of the actual maximum length, but
- # we can't tell.
- while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
- = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
- test $i != 17 # 1/2 MB should be enough
- do
- i=`expr $i + 1`
- teststring=$teststring$teststring
- done
- # Only check the string length outside the loop.
- lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
- teststring=
- # Add a significant safety factor because C++ compilers can tack on
- # massive amounts of additional arguments before passing them to the
- # linker. It appears as though 1/2 is a usable value.
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
- fi
- ;;
- esac
-])
-if test -n $lt_cv_sys_max_cmd_len ; then
- AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
-else
- AC_MSG_RESULT(none)
-fi
-max_cmd_len=$lt_cv_sys_max_cmd_len
-_LT_DECL([], [max_cmd_len], [0],
- [What is the maximum length of a command?])
-])# LT_CMD_MAX_LEN
-
-# Old name:
-AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
-
-
-# _LT_HEADER_DLFCN
-# ----------------
-m4_defun([_LT_HEADER_DLFCN],
-[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
-])# _LT_HEADER_DLFCN
-
-
-# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
-# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
-# ----------------------------------------------------------------
-m4_defun([_LT_TRY_DLOPEN_SELF],
-[m4_require([_LT_HEADER_DLFCN])dnl
-if test "$cross_compiling" = yes; then :
- [$4]
-else
- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
- lt_status=$lt_dlunknown
- cat > conftest.$ac_ext <<_LT_EOF
-[#line __oline__ "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LT_DLGLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LT_DLGLOBAL DL_GLOBAL
-# else
-# define LT_DLGLOBAL 0
-# endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LT_DLLAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LT_DLLAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LT_DLLAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LT_DLLAZY_OR_NOW DL_NOW
-# else
-# define LT_DLLAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-void fnord() { int i=42;}
-int main ()
-{
- void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
- int status = $lt_dlunknown;
-
- if (self)
- {
- if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
- else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
- /* dlclose (self); */
- }
- else
- puts (dlerror ());
-
- return status;
-}]
-_LT_EOF
- if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
- (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
- lt_status=$?
- case x$lt_status in
- x$lt_dlno_uscore) $1 ;;
- x$lt_dlneed_uscore) $2 ;;
- x$lt_dlunknown|x*) $3 ;;
- esac
- else :
- # compilation failed
- $3
- fi
-fi
-rm -fr conftest*
-])# _LT_TRY_DLOPEN_SELF
-
-
-# LT_SYS_DLOPEN_SELF
-# ------------------
-AC_DEFUN([LT_SYS_DLOPEN_SELF],
-[m4_require([_LT_HEADER_DLFCN])dnl
-if test "x$enable_dlopen" != xyes; then
- enable_dlopen=unknown
- enable_dlopen_self=unknown
- enable_dlopen_self_static=unknown
-else
- lt_cv_dlopen=no
- lt_cv_dlopen_libs=
-
- case $host_os in
- beos*)
- lt_cv_dlopen="load_add_on"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ;;
-
- mingw* | pw32* | cegcc*)
- lt_cv_dlopen="LoadLibrary"
- lt_cv_dlopen_libs=
- ;;
-
- cygwin*)
- lt_cv_dlopen="dlopen"
- lt_cv_dlopen_libs=
- ;;
-
- darwin*)
- # if libdl is installed we need to link against it
- AC_CHECK_LIB([dl], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
- lt_cv_dlopen="dyld"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ])
- ;;
-
- *)
- AC_CHECK_FUNC([shl_load],
- [lt_cv_dlopen="shl_load"],
- [AC_CHECK_LIB([dld], [shl_load],
- [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
- [AC_CHECK_FUNC([dlopen],
- [lt_cv_dlopen="dlopen"],
- [AC_CHECK_LIB([dl], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
- [AC_CHECK_LIB([svld], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
- [AC_CHECK_LIB([dld], [dld_link],
- [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
- ])
- ])
- ])
- ])
- ])
- ;;
- esac
-
- if test "x$lt_cv_dlopen" != xno; then
- enable_dlopen=yes
- else
- enable_dlopen=no
- fi
-
- case $lt_cv_dlopen in
- dlopen)
- save_CPPFLAGS="$CPPFLAGS"
- test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-
- save_LDFLAGS="$LDFLAGS"
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-
- save_LIBS="$LIBS"
- LIBS="$lt_cv_dlopen_libs $LIBS"
-
- AC_CACHE_CHECK([whether a program can dlopen itself],
- lt_cv_dlopen_self, [dnl
- _LT_TRY_DLOPEN_SELF(
- lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
- lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
- ])
-
- if test "x$lt_cv_dlopen_self" = xyes; then
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
- AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
- lt_cv_dlopen_self_static, [dnl
- _LT_TRY_DLOPEN_SELF(
- lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
- lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
- ])
- fi
-
- CPPFLAGS="$save_CPPFLAGS"
- LDFLAGS="$save_LDFLAGS"
- LIBS="$save_LIBS"
- ;;
- esac
-
- case $lt_cv_dlopen_self in
- yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
- *) enable_dlopen_self=unknown ;;
- esac
-
- case $lt_cv_dlopen_self_static in
- yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
- *) enable_dlopen_self_static=unknown ;;
- esac
-fi
-_LT_DECL([dlopen_support], [enable_dlopen], [0],
- [Whether dlopen is supported])
-_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
- [Whether dlopen of programs is supported])
-_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
- [Whether dlopen of statically linked programs is supported])
-])# LT_SYS_DLOPEN_SELF
-
-# Old name:
-AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
-
-
-# _LT_COMPILER_C_O([TAGNAME])
-# ---------------------------
-# Check to see if options -c and -o are simultaneously supported by compiler.
-# This macro does not hard code the compiler like AC_PROG_CC_C_O.
-m4_defun([_LT_COMPILER_C_O],
-[m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_TAG_COMPILER])dnl
-AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
- [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
- [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
- $RM -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&AS_MESSAGE_LOG_FD
- echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
- fi
- fi
- chmod u+w . 2>&AS_MESSAGE_LOG_FD
- $RM conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
- $RM out/* && rmdir out
- cd ..
- $RM -r conftest
- $RM conftest*
-])
-_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
- [Does compiler simultaneously support -c and -o options?])
-])# _LT_COMPILER_C_O
-
-
-# _LT_COMPILER_FILE_LOCKS([TAGNAME])
-# ----------------------------------
-# Check to see if we can do hard links to lock some files if needed
-m4_defun([_LT_COMPILER_FILE_LOCKS],
-[m4_require([_LT_ENABLE_LOCK])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-_LT_COMPILER_C_O([$1])
-
-hard_links="nottested"
-if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- AC_MSG_CHECKING([if we can lock with hard links])
- hard_links=yes
- $RM conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- AC_MSG_RESULT([$hard_links])
- if test "$hard_links" = no; then
- AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
-])# _LT_COMPILER_FILE_LOCKS
-
-
-# _LT_CHECK_OBJDIR
-# ----------------
-m4_defun([_LT_CHECK_OBJDIR],
-[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
-[rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
- lt_cv_objdir=.libs
-else
- # MS-DOS does not allow filenames that begin with a dot.
- lt_cv_objdir=_libs
-fi
-rmdir .libs 2>/dev/null])
-objdir=$lt_cv_objdir
-_LT_DECL([], [objdir], [0],
- [The name of the directory that contains temporary libtool files])dnl
-m4_pattern_allow([LT_OBJDIR])dnl
-AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
- [Define to the sub-directory in which libtool stores uninstalled libraries.])
-])# _LT_CHECK_OBJDIR
-
-
-# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
-# --------------------------------------
-# Check hardcoding attributes.
-m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
-[AC_MSG_CHECKING([how to hardcode library paths into programs])
-_LT_TAGVAR(hardcode_action, $1)=
-if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
- test -n "$_LT_TAGVAR(runpath_var, $1)" ||
- test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
-
- # We can hardcode non-existent directories.
- if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
- test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
- # Linking always hardcodes the temporary library directory.
- _LT_TAGVAR(hardcode_action, $1)=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- _LT_TAGVAR(hardcode_action, $1)=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- _LT_TAGVAR(hardcode_action, $1)=unsupported
-fi
-AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
-
-if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
- test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-_LT_TAGDECL([], [hardcode_action], [0],
- [How to hardcode a shared library path into an executable])
-])# _LT_LINKER_HARDCODE_LIBPATH
-
-
-# _LT_CMD_STRIPLIB
-# ----------------
-m4_defun([_LT_CMD_STRIPLIB],
-[m4_require([_LT_DECL_EGREP])
-striplib=
-old_striplib=
-AC_MSG_CHECKING([whether stripping libraries is possible])
-if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
- test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
- test -z "$striplib" && striplib="$STRIP --strip-unneeded"
- AC_MSG_RESULT([yes])
-else
-# FIXME - insert some real tests, host_os isn't really good enough
- case $host_os in
- darwin*)
- if test -n "$STRIP" ; then
- striplib="$STRIP -x"
- old_striplib="$STRIP -S"
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
- fi
- ;;
- *)
- AC_MSG_RESULT([no])
- ;;
- esac
-fi
-_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
-_LT_DECL([], [striplib], [1])
-])# _LT_CMD_STRIPLIB
-
-
-# _LT_SYS_DYNAMIC_LINKER([TAG])
-# -----------------------------
-# PORTME Fill in your ld.so characteristics
-m4_defun([_LT_SYS_DYNAMIC_LINKER],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-m4_require([_LT_DECL_EGREP])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_OBJDUMP])dnl
-m4_require([_LT_DECL_SED])dnl
-AC_MSG_CHECKING([dynamic linker characteristics])
-m4_if([$1],
- [], [
-if test "$GCC" = yes; then
- case $host_os in
- darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
- *) lt_awk_arg="/^libraries:/" ;;
- esac
- lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
- # if the path contains ";" then we assume it to be the separator
- # otherwise default to the standard path separator (i.e. ":") - it is
- # assumed that no part of a normal pathname contains ";" but that should
- # okay in the real world where ";" in dirpaths is itself problematic.
- lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
- else
- lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- # Ok, now we have the path, separated by spaces, we can step through it
- # and add multilib dir if necessary.
- lt_tmp_lt_search_path_spec=
- lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
- for lt_sys_path in $lt_search_path_spec; do
- if test -d "$lt_sys_path/$lt_multi_os_dir"; then
- lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
- else
- test -d "$lt_sys_path" && \
- lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
- fi
- done
- lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
-BEGIN {RS=" "; FS="/|\n";} {
- lt_foo="";
- lt_count=0;
- for (lt_i = NF; lt_i > 0; lt_i--) {
- if ($lt_i != "" && $lt_i != ".") {
- if ($lt_i == "..") {
- lt_count++;
- } else {
- if (lt_count == 0) {
- lt_foo="/" $lt_i lt_foo;
- } else {
- lt_count--;
- }
- }
- }
- }
- if (lt_foo != "") { lt_freq[[lt_foo]]++; }
- if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
-}'`
- sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
-else
- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi])
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX 3 has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
-
-aix[[4-9]]*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- hardcode_into_libs=yes
- if test "$host_cpu" = ia64; then
- # AIX 5 supports IA64
- library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- else
- # With GCC up to 2.95.x, collect2 would create an import file
- # for dependence libraries. The import file would start with
- # the line `#! .'. This would cause the generated library to
- # depend on `.', always an invalid library. This was fixed in
- # development snapshots of GCC prior to 3.0.
- case $host_os in
- aix4 | aix4.[[01]] | aix4.[[01]].*)
- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
- echo ' yes '
- echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
- :
- else
- can_build_shared=no
- fi
- ;;
- esac
- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- if test "$aix_use_runtimelinking" = yes; then
- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
- # instead of lib<name>.a to let people know that these are not
- # typical AIX shared libraries.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- else
- # We preserve .a as extension for shared libraries through AIX4.2
- # and later when we are not doing run time linking.
- library_names_spec='${libname}${release}.a $libname.a'
- soname_spec='${libname}${release}${shared_ext}$major'
- fi
- shlibpath_var=LIBPATH
- fi
- ;;
-
-amigaos*)
- case $host_cpu in
- powerpc)
- # Since July 2007 AmigaOS4 officially supports .so libraries.
- # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- ;;
- m68k)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
- ;;
- esac
- ;;
-
-beos*)
- library_names_spec='${libname}${shared_ext}'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- ;;
-
-bsdi[[45]]*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw* | pw32* | cegcc*)
- version_type=windows
- shrext_cmds=".dll"
- need_version=no
- need_lib_prefix=no
-
- case $GCC,$host_os in
- yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
- library_names_spec='$libname.dll.a'
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname~
- chmod a+x \$dldir/$dlname~
- if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
- eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
- fi'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $RM \$dlpath'
- shlibpath_overrides_runpath=yes
-
- case $host_os in
- cygwin*)
- # Cygwin DLLs use 'cyg' prefix rather than 'lib'
- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
- ;;
- mingw* | cegcc*)
- # MinGW DLLs use traditional 'lib' prefix
- soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
- # It is most probably a Windows format PATH printed by
- # mingw gcc, but we are running on Cygwin. Gcc prints its search
- # path with ; separators, and with drive letters. We can handle the
- # drive letters (cygwin fileutils understands them), so leave them,
- # especially as we might pass files found there to a mingw objdump,
- # which wouldn't understand a cygwinified path. Ahh.
- sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- ;;
- pw32*)
- # pw32 DLLs use 'pw' prefix rather than 'lib'
- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- ;;
- esac
- ;;
-
- *)
- library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
- ;;
- esac
- dynamic_linker='Win32 ld.exe'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- ;;
-
-darwin* | rhapsody*)
- dynamic_linker="$host_os dyld"
- version_type=darwin
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
- soname_spec='${libname}${release}${major}$shared_ext'
- shlibpath_overrides_runpath=yes
- shlibpath_var=DYLD_LIBRARY_PATH
- shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
-m4_if([$1], [],[
- sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
- sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-freebsd* | dragonfly*)
- # DragonFly does not have aout. When/if they implement a new
- # versioning mechanism, adjust this.
- if test -x /usr/bin/objformat; then
- objformat=`/usr/bin/objformat`
- else
- case $host_os in
- freebsd[[123]]*) objformat=aout ;;
- *) objformat=elf ;;
- esac
- fi
- # Handle Gentoo/FreeBSD as it was Linux
- case $host_vendor in
- gentoo)
- version_type=linux ;;
- *)
- version_type=freebsd-$objformat ;;
- esac
-
- case $version_type in
- freebsd-elf*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
- need_version=yes
- ;;
- linux)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- need_lib_prefix=no
- need_version=no
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case $host_os in
- freebsd2*)
- shlibpath_overrides_runpath=yes
- ;;
- freebsd3.[[01]]* | freebsdelf3.[[01]]*)
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
- freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
- *) # from 4.6 on, and DragonFly
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- case $host_cpu in
- ia64*)
- shrext_cmds='.so'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.so"
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- if test "X$HPUX_IA64_MODE" = X32; then
- sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
- else
- sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
- fi
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- hppa*64*)
- shrext_cmds='.sl'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- *)
- shrext_cmds='.sl'
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
- esac
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
- ;;
-
-interix[[3-9]]*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $host_os in
- nonstopux*) version_type=nonstopux ;;
- *)
- if test "$lt_cv_prog_gnu_ld" = yes; then
- version_type=linux
- else
- version_type=irix
- fi ;;
- esac
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
- case $host_os in
- irix5* | nonstopux*)
- libsuff= shlibsuff=
- ;;
- *)
- case $LD in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
- libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
- libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
- libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- hardcode_into_libs=yes
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux* | k*bsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- # Some binutils ld are patched to set DT_RUNPATH
- save_LDFLAGS=$LDFLAGS
- save_libdir=$libdir
- eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
- LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
- AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
- [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
- [shlibpath_overrides_runpath=yes])])
- LDFLAGS=$save_LDFLAGS
- libdir=$save_libdir
-
- # This implies no fast_install, which is unacceptable.
- # Some rework will be needed to allow for fast_install
- # before this can be enabled.
- hardcode_into_libs=yes
-
- # Append ld.so.conf contents to the search path
- if test -f /etc/ld.so.conf; then
- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
- sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
- fi
-
- # We used to test for /lib/ld.so.1 and disable shared libraries on
- # powerpc, because MkLinux only supported shared libraries with the
- # GNU dynamic linker. Since this was broken with cross compilers,
- # most powerpc-linux boxes support dynamic linking these days and
- # people can always --disable-shared, the test was removed, and we
- # assume the GNU/Linux dynamic linker is in use.
- dynamic_linker='GNU/Linux ld.so'
- ;;
-
-netbsd*)
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
-
-newsos6)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-*nto* | *qnx*)
- version_type=qnx
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='ldqnx.so'
- ;;
-
-openbsd*)
- version_type=sunos
- sys_lib_dlsearch_path_spec="/usr/lib"
- need_lib_prefix=no
- # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
- case $host_os in
- openbsd3.3 | openbsd3.3.*) need_version=yes ;;
- *) need_version=no ;;
- esac
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- case $host_os in
- openbsd2.[[89]] | openbsd2.[[89]].*)
- shlibpath_overrides_runpath=no
- ;;
- *)
- shlibpath_overrides_runpath=yes
- ;;
- esac
- else
- shlibpath_overrides_runpath=yes
- fi
- ;;
-
-os2*)
- libname_spec='$name'
- shrext_cmds=".dll"
- need_lib_prefix=no
- library_names_spec='$libname${shared_ext} $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-rdos*)
- dynamic_linker=no
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- case $host_vendor in
- sni)
- shlibpath_overrides_runpath=no
- need_lib_prefix=no
- runpath_var=LD_RUN_PATH
- ;;
- siemens)
- need_lib_prefix=no
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- ;;
- esac
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
- soname_spec='$libname${shared_ext}.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- version_type=freebsd-elf
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- if test "$with_gnu_ld" = yes; then
- sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
- else
- sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
- case $host_os in
- sco3.2v5*)
- sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
- ;;
- esac
- fi
- sys_lib_dlsearch_path_spec='/usr/lib'
- ;;
-
-tpf*)
- # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-AC_MSG_RESULT([$dynamic_linker])
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-
-if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
- sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
-fi
-if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
- sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
-fi
-
-_LT_DECL([], [variables_saved_for_relink], [1],
- [Variables whose values should be saved in libtool wrapper scripts and
- restored at link time])
-_LT_DECL([], [need_lib_prefix], [0],
- [Do we need the "lib" prefix for modules?])
-_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
-_LT_DECL([], [version_type], [0], [Library versioning type])
-_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
-_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
-_LT_DECL([], [shlibpath_overrides_runpath], [0],
- [Is shlibpath searched before the hard-coded library search path?])
-_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
-_LT_DECL([], [library_names_spec], [1],
- [[List of archive names. First name is the real one, the rest are links.
- The last name is the one that the linker finds with -lNAME]])
-_LT_DECL([], [soname_spec], [1],
- [[The coded name of the library, if different from the real name]])
-_LT_DECL([], [postinstall_cmds], [2],
- [Command to use after installation of a shared archive])
-_LT_DECL([], [postuninstall_cmds], [2],
- [Command to use after uninstallation of a shared archive])
-_LT_DECL([], [finish_cmds], [2],
- [Commands used to finish a libtool library installation in a directory])
-_LT_DECL([], [finish_eval], [1],
- [[As "finish_cmds", except a single script fragment to be evaled but
- not shown]])
-_LT_DECL([], [hardcode_into_libs], [0],
- [Whether we should hardcode library paths into libraries])
-_LT_DECL([], [sys_lib_search_path_spec], [2],
- [Compile-time system search path for libraries])
-_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
- [Run-time system search path for libraries])
-])# _LT_SYS_DYNAMIC_LINKER
-
-
-# _LT_PATH_TOOL_PREFIX(TOOL)
-# --------------------------
-# find a file program which can recognize shared library
-AC_DEFUN([_LT_PATH_TOOL_PREFIX],
-[m4_require([_LT_DECL_EGREP])dnl
-AC_MSG_CHECKING([for $1])
-AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
-[case $MAGIC_CMD in
-[[\\/*] | ?:[\\/]*])
- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
- ;;
-*)
- lt_save_MAGIC_CMD="$MAGIC_CMD"
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-dnl $ac_dummy forces splitting on constant user-supplied paths.
-dnl POSIX.2 word splitting is done only on the output of word expansions,
-dnl not every word. This closes a longstanding sh security hole.
- ac_dummy="m4_if([$2], , $PATH, [$2])"
- for ac_dir in $ac_dummy; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$1; then
- lt_cv_path_MAGIC_CMD="$ac_dir/$1"
- if test -n "$file_magic_test_file"; then
- case $deplibs_check_method in
- "file_magic "*)
- file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
- MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- $EGREP "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<_LT_EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-_LT_EOF
- fi ;;
- esac
- fi
- break
- fi
- done
- IFS="$lt_save_ifs"
- MAGIC_CMD="$lt_save_MAGIC_CMD"
- ;;
-esac])
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
- AC_MSG_RESULT($MAGIC_CMD)
-else
- AC_MSG_RESULT(no)
-fi
-_LT_DECL([], [MAGIC_CMD], [0],
- [Used to examine libraries when file_magic_cmd begins with "file"])dnl
-])# _LT_PATH_TOOL_PREFIX
-
-# Old name:
-AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
-
-
-# _LT_PATH_MAGIC
-# --------------
-# find a file program which can recognize a shared library
-m4_defun([_LT_PATH_MAGIC],
-[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
-if test -z "$lt_cv_path_MAGIC_CMD"; then
- if test -n "$ac_tool_prefix"; then
- _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
- else
- MAGIC_CMD=:
- fi
-fi
-])# _LT_PATH_MAGIC
-
-
-# LT_PATH_LD
-# ----------
-# find the pathname to the GNU or non-GNU linker
-AC_DEFUN([LT_PATH_LD],
-[AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_DECL_EGREP])dnl
-
-AC_ARG_WITH([gnu-ld],
- [AS_HELP_STRING([--with-gnu-ld],
- [assume the C compiler uses GNU ld @<:@default=no@:>@])],
- [test "$withval" = no || with_gnu_ld=yes],
- [with_gnu_ld=no])dnl
-
-ac_prog=ld
-if test "$GCC" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
- AC_MSG_CHECKING([for ld used by $CC])
- case $host in
- *-*-mingw*)
- # gcc leaves a trailing carriage return which upsets mingw
- ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
- *)
- ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
- esac
- case $ac_prog in
- # Accept absolute paths.
- [[\\/]]* | ?:[[\\/]]*)
- re_direlt='/[[^/]][[^/]]*/\.\./'
- # Canonicalize the pathname of ld
- ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
- while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we aren't using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
-elif test "$with_gnu_ld" = yes; then
- AC_MSG_CHECKING([for GNU ld])
-else
- AC_MSG_CHECKING([for non-GNU ld])
-fi
-AC_CACHE_VAL(lt_cv_path_LD,
-[if test -z "$LD"; then
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- lt_cv_path_LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some variants of GNU ld only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
- *GNU* | *'with BFD'*)
- test "$with_gnu_ld" != no && break
- ;;
- *)
- test "$with_gnu_ld" != yes && break
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
-else
- lt_cv_path_LD="$LD" # Let the user override the test with a path.
-fi])
-LD="$lt_cv_path_LD"
-if test -n "$LD"; then
- AC_MSG_RESULT($LD)
-else
- AC_MSG_RESULT(no)
-fi
-test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
-_LT_PATH_LD_GNU
-AC_SUBST([LD])
-
-_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
-])# LT_PATH_LD
-
-# Old names:
-AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
-AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AM_PROG_LD], [])
-dnl AC_DEFUN([AC_PROG_LD], [])
-
-
-# _LT_PATH_LD_GNU
-#- --------------
-m4_defun([_LT_PATH_LD_GNU],
-[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
-[# I'd rather use --version here, but apparently some GNU lds only accept -v.
-case `$LD -v 2>&1 </dev/null` in
-*GNU* | *'with BFD'*)
- lt_cv_prog_gnu_ld=yes
- ;;
-*)
- lt_cv_prog_gnu_ld=no
- ;;
-esac])
-with_gnu_ld=$lt_cv_prog_gnu_ld
-])# _LT_PATH_LD_GNU
-
-
-# _LT_CMD_RELOAD
-# --------------
-# find reload flag for linker
-# -- PORTME Some linkers may need a different reload flag.
-m4_defun([_LT_CMD_RELOAD],
-[AC_CACHE_CHECK([for $LD option to reload object files],
- lt_cv_ld_reload_flag,
- [lt_cv_ld_reload_flag='-r'])
-reload_flag=$lt_cv_ld_reload_flag
-case $reload_flag in
-"" | " "*) ;;
-*) reload_flag=" $reload_flag" ;;
-esac
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-case $host_os in
- darwin*)
- if test "$GCC" = yes; then
- reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
- else
- reload_cmds='$LD$reload_flag -o $output$reload_objs'
- fi
- ;;
-esac
-_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
-_LT_DECL([], [reload_cmds], [2])dnl
-])# _LT_CMD_RELOAD
-
-
-# _LT_CHECK_MAGIC_METHOD
-# ----------------------
-# how to check for library dependencies
-# -- PORTME fill in with the dynamic library characteristics
-m4_defun([_LT_CHECK_MAGIC_METHOD],
-[m4_require([_LT_DECL_EGREP])
-m4_require([_LT_DECL_OBJDUMP])
-AC_CACHE_CHECK([how to recognize dependent libraries],
-lt_cv_deplibs_check_method,
-[lt_cv_file_magic_cmd='$MAGIC_CMD'
-lt_cv_file_magic_test_file=
-lt_cv_deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [[regex]]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given extended regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-
-case $host_os in
-aix[[4-9]]*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-beos*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-bsdi[[45]]*)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
- lt_cv_file_magic_cmd='/usr/bin/file -L'
- lt_cv_file_magic_test_file=/shlib/libc.so
- ;;
-
-cygwin*)
- # func_win32_libid is a shell function defined in ltmain.sh
- lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
- lt_cv_file_magic_cmd='func_win32_libid'
- ;;
-
-mingw* | pw32*)
- # Base MSYS/MinGW do not provide the 'file' command needed by
- # func_win32_libid shell function, so use a weaker test based on 'objdump',
- # unless we find 'file', for example because we are cross-compiling.
- if ( file / ) >/dev/null 2>&1; then
- lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
- lt_cv_file_magic_cmd='func_win32_libid'
- else
- lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
- lt_cv_file_magic_cmd='$OBJDUMP -f'
- fi
- ;;
-
-cegcc)
- # use the weaker test based on 'objdump'. See mingw*.
- lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
- lt_cv_file_magic_cmd='$OBJDUMP -f'
- ;;
-
-darwin* | rhapsody*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-freebsd* | dragonfly*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
- case $host_cpu in
- i*86 )
- # Not sure whether the presence of OpenBSD here was a mistake.
- # Let's accept both of them until this is cleared up.
- lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
- ;;
- esac
- else
- lt_cv_deplibs_check_method=pass_all
- fi
- ;;
-
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-hpux10.20* | hpux11*)
- lt_cv_file_magic_cmd=/usr/bin/file
- case $host_cpu in
- ia64*)
- lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
- lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
- ;;
- hppa*64*)
- [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
- lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
- ;;
- *)
- lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
- lt_cv_file_magic_test_file=/usr/lib/libc.sl
- ;;
- esac
- ;;
-
-interix[[3-9]]*)
- # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $LD in
- *-32|*"-32 ") libmagic=32-bit;;
- *-n32|*"-n32 ") libmagic=N32;;
- *-64|*"-64 ") libmagic=64-bit;;
- *) libmagic=never-match;;
- esac
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-# This must be Linux ELF.
-linux* | k*bsd*-gnu)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
- fi
- ;;
-
-newos6*)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=/usr/lib/libnls.so
- ;;
-
-*nto* | *qnx*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-openbsd*)
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
- fi
- ;;
-
-osf3* | osf4* | osf5*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-rdos*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-solaris*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-sysv4 | sysv4.3*)
- case $host_vendor in
- motorola)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
- ;;
- ncr)
- lt_cv_deplibs_check_method=pass_all
- ;;
- sequent)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
- ;;
- sni)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
- lt_cv_file_magic_test_file=/lib/libc.so
- ;;
- siemens)
- lt_cv_deplibs_check_method=pass_all
- ;;
- pc)
- lt_cv_deplibs_check_method=pass_all
- ;;
- esac
- ;;
-
-tpf*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-esac
-])
-file_magic_cmd=$lt_cv_file_magic_cmd
-deplibs_check_method=$lt_cv_deplibs_check_method
-test -z "$deplibs_check_method" && deplibs_check_method=unknown
-
-_LT_DECL([], [deplibs_check_method], [1],
- [Method to check whether dependent libraries are shared objects])
-_LT_DECL([], [file_magic_cmd], [1],
- [Command to use when deplibs_check_method == "file_magic"])
-])# _LT_CHECK_MAGIC_METHOD
-
-
-# LT_PATH_NM
-# ----------
-# find the pathname to a BSD- or MS-compatible name lister
-AC_DEFUN([LT_PATH_NM],
-[AC_REQUIRE([AC_PROG_CC])dnl
-AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
-[if test -n "$NM"; then
- # Let the user override the test.
- lt_cv_path_NM="$NM"
-else
- lt_nm_to_check="${ac_tool_prefix}nm"
- if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
- lt_nm_to_check="$lt_nm_to_check nm"
- fi
- for lt_tmp_nm in $lt_nm_to_check; do
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- tmp_nm="$ac_dir/$lt_tmp_nm"
- if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
- # Check to see if the nm accepts a BSD-compat flag.
- # Adding the `sed 1q' prevents false positives on HP-UX, which says:
- # nm: unknown option "B" ignored
- # Tru64's nm complains that /dev/null is an invalid object file
- case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
- */dev/null* | *'Invalid file or object type'*)
- lt_cv_path_NM="$tmp_nm -B"
- break
- ;;
- *)
- case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
- */dev/null*)
- lt_cv_path_NM="$tmp_nm -p"
- break
- ;;
- *)
- lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
- continue # so that we can try to find one that supports BSD flags
- ;;
- esac
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
- done
- : ${lt_cv_path_NM=no}
-fi])
-if test "$lt_cv_path_NM" != "no"; then
- NM="$lt_cv_path_NM"
-else
- # Didn't find any BSD compatible name lister, look for dumpbin.
- AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
- AC_SUBST([DUMPBIN])
- if test "$DUMPBIN" != ":"; then
- NM="$DUMPBIN"
- fi
-fi
-test -z "$NM" && NM=nm
-AC_SUBST([NM])
-_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
-
-AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
- [lt_cv_nm_interface="BSD nm"
- echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
- (eval "$ac_compile" 2>conftest.err)
- cat conftest.err >&AS_MESSAGE_LOG_FD
- (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
- (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
- cat conftest.err >&AS_MESSAGE_LOG_FD
- (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD)
- cat conftest.out >&AS_MESSAGE_LOG_FD
- if $GREP 'External.*some_variable' conftest.out > /dev/null; then
- lt_cv_nm_interface="MS dumpbin"
- fi
- rm -f conftest*])
-])# LT_PATH_NM
-
-# Old names:
-AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
-AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AM_PROG_NM], [])
-dnl AC_DEFUN([AC_PROG_NM], [])
-
-
-# LT_LIB_M
-# --------
-# check for math library
-AC_DEFUN([LT_LIB_M],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-LIBM=
-case $host in
-*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
- # These system don't have libm, or don't need it
- ;;
-*-ncr-sysv4.3*)
- AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
- AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
- ;;
-*)
- AC_CHECK_LIB(m, cos, LIBM="-lm")
- ;;
-esac
-AC_SUBST([LIBM])
-])# LT_LIB_M
-
-# Old name:
-AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_CHECK_LIBM], [])
-
-
-# _LT_COMPILER_NO_RTTI([TAGNAME])
-# -------------------------------
-m4_defun([_LT_COMPILER_NO_RTTI],
-[m4_require([_LT_TAG_COMPILER])dnl
-
-_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
-
-if test "$GCC" = yes; then
- _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
-
- _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
- lt_cv_prog_compiler_rtti_exceptions,
- [-fno-rtti -fno-exceptions], [],
- [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
-fi
-_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
- [Compiler flag to turn off builtin functions])
-])# _LT_COMPILER_NO_RTTI
-
-
-# _LT_CMD_GLOBAL_SYMBOLS
-# ----------------------
-m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([LT_PATH_NM])dnl
-AC_REQUIRE([LT_PATH_LD])dnl
-m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_DECL_EGREP])dnl
-m4_require([_LT_TAG_COMPILER])dnl
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-AC_MSG_CHECKING([command to parse $NM output from $compiler object])
-AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
-[
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix. What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[[BCDEGRST]]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
-
-# Define system-specific variables.
-case $host_os in
-aix*)
- symcode='[[BCDT]]'
- ;;
-cygwin* | mingw* | pw32* | cegcc*)
- symcode='[[ABCDGISTW]]'
- ;;
-hpux*)
- if test "$host_cpu" = ia64; then
- symcode='[[ABCDEGRST]]'
- fi
- ;;
-irix* | nonstopux*)
- symcode='[[BCDEGRST]]'
- ;;
-osf*)
- symcode='[[BCDEGQRST]]'
- ;;
-solaris*)
- symcode='[[BDRT]]'
- ;;
-sco3.2v5*)
- symcode='[[DT]]'
- ;;
-sysv4.2uw2*)
- symcode='[[DT]]'
- ;;
-sysv5* | sco5v6* | unixware* | OpenUNIX*)
- symcode='[[ABDT]]'
- ;;
-sysv4)
- symcode='[[DFNSTU]]'
- ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-case `$NM -V 2>&1` in
-*GNU* | *'with BFD'*)
- symcode='[[ABCDGIRSTW]]' ;;
-esac
-
-# Transform an extracted symbol line into a proper C declaration.
-# Some systems (esp. on ia64) link data and code symbols differently,
-# so use this general approach.
-lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
-
-# Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
-
-# Handle CRLF in mingw tool chain
-opt_cr=
-case $build_os in
-mingw*)
- opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
- ;;
-esac
-
-# Try without a prefix underscore, then with it.
-for ac_symprfx in "" "_"; do
-
- # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
- symxfrm="\\1 $ac_symprfx\\2 \\2"
-
- # Write the raw and C identifiers.
- if test "$lt_cv_nm_interface" = "MS dumpbin"; then
- # Fake it for dumpbin and say T for any non-static function
- # and D for any global variable.
- # Also find C++ and __fastcall symbols from MSVC++,
- # which start with @ or ?.
- lt_cv_sys_global_symbol_pipe="$AWK ['"\
-" {last_section=section; section=\$ 3};"\
-" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
-" \$ 0!~/External *\|/{next};"\
-" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
-" {if(hide[section]) next};"\
-" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
-" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
-" s[1]~/^[@?]/{print s[1], s[1]; next};"\
-" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
-" ' prfx=^$ac_symprfx]"
- else
- lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
- fi
-
- # Check to see that the pipe works correctly.
- pipe_works=no
-
- rm -f conftest*
- cat > conftest.$ac_ext <<_LT_EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(void);
-void nm_test_func(void){}
-#ifdef __cplusplus
-}
-#endif
-int main(){nm_test_var='a';nm_test_func();return(0);}
-_LT_EOF
-
- if AC_TRY_EVAL(ac_compile); then
- # Now try to grab the symbols.
- nlist=conftest.nm
- if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
- # Try sorting and uniquifying the output.
- if sort "$nlist" | uniq > "$nlist"T; then
- mv -f "$nlist"T "$nlist"
- else
- rm -f "$nlist"T
- fi
-
- # Make sure that we snagged all the symbols we need.
- if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
- if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
- cat <<_LT_EOF > conftest.$ac_ext
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-_LT_EOF
- # Now generate the symbol file.
- eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
-
- cat <<_LT_EOF >> conftest.$ac_ext
-
-/* The mapping between symbol names and symbols. */
-const struct {
- const char *name;
- void *address;
-}
-lt__PROGRAM__LTX_preloaded_symbols[[]] =
-{
- { "@PROGRAM@", (void *) 0 },
-_LT_EOF
- $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
- cat <<\_LT_EOF >> conftest.$ac_ext
- {0, (void *) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
- return lt__PROGRAM__LTX_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-_LT_EOF
- # Now try linking the two files.
- mv conftest.$ac_objext conftstm.$ac_objext
- lt_save_LIBS="$LIBS"
- lt_save_CFLAGS="$CFLAGS"
- LIBS="conftstm.$ac_objext"
- CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
- if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
- pipe_works=yes
- fi
- LIBS="$lt_save_LIBS"
- CFLAGS="$lt_save_CFLAGS"
- else
- echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
- cat conftest.$ac_ext >&5
- fi
- rm -rf conftest* conftst*
-
- # Do not use the global_symbol_pipe unless it works.
- if test "$pipe_works" = yes; then
- break
- else
- lt_cv_sys_global_symbol_pipe=
- fi
-done
-])
-if test -z "$lt_cv_sys_global_symbol_pipe"; then
- lt_cv_sys_global_symbol_to_cdecl=
-fi
-if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
- AC_MSG_RESULT(failed)
-else
- AC_MSG_RESULT(ok)
-fi
-
-_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
- [Take the output of nm and produce a listing of raw symbols and C names])
-_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
- [Transform the output of nm in a proper C declaration])
-_LT_DECL([global_symbol_to_c_name_address],
- [lt_cv_sys_global_symbol_to_c_name_address], [1],
- [Transform the output of nm in a C name address pair])
-_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
- [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
- [Transform the output of nm in a C name address pair when lib prefix is needed])
-]) # _LT_CMD_GLOBAL_SYMBOLS
-
-
-# _LT_COMPILER_PIC([TAGNAME])
-# ---------------------------
-m4_defun([_LT_COMPILER_PIC],
-[m4_require([_LT_TAG_COMPILER])dnl
-_LT_TAGVAR(lt_prog_compiler_wl, $1)=
-_LT_TAGVAR(lt_prog_compiler_pic, $1)=
-_LT_TAGVAR(lt_prog_compiler_static, $1)=
-
-AC_MSG_CHECKING([for $compiler option to produce PIC])
-m4_if([$1], [CXX], [
- # C++ specific cases for pic, static, wl, etc.
- if test "$GXX" = yes; then
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- m68k)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
- ;;
- esac
- ;;
-
- beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
- mingw* | cygwin* | os2* | pw32* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- # Although the cygwin gcc ignores -fPIC, still need this for old-style
- # (--disable-auto-import) libraries
- m4_if([$1], [GCJ], [],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
- ;;
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
- ;;
- *djgpp*)
- # DJGPP does not support shared libraries at all
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=
- ;;
- interix[[3-9]]*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
- fi
- ;;
- hpux*)
- # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
- # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
- # sets the default TLS model and affects inlining.
- case $host_cpu in
- hppa*64*)
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- ;;
- *qnx* | *nto*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- else
- case $host_os in
- aix[[4-9]]*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- else
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
- chorus*)
- case $cc_basename in
- cxch68*)
- # Green Hills C++ Compiler
- # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
- ;;
- esac
- ;;
- dgux*)
- case $cc_basename in
- ec++*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- ;;
- ghcx*)
- # Green Hills C++ Compiler
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- *)
- ;;
- esac
- ;;
- freebsd* | dragonfly*)
- # FreeBSD uses GNU C++
- ;;
- hpux9* | hpux10* | hpux11*)
- case $cc_basename in
- CC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- if test "$host_cpu" != ia64; then
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- fi
- ;;
- aCC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- ;;
- esac
- ;;
- *)
- ;;
- esac
- ;;
- interix*)
- # This is c89, which is MS Visual C++ (no shared libs)
- # Anyone wants to do a port?
- ;;
- irix5* | irix6* | nonstopux*)
- case $cc_basename in
- CC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- # CC pic flag -KPIC is the default.
- ;;
- *)
- ;;
- esac
- ;;
- linux* | k*bsd*-gnu)
- case $cc_basename in
- KCC*)
- # KAI C++ Compiler
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- ecpc* )
- # old Intel C++ for x86_64 which still supported -KPIC.
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- icpc* )
- # Intel C++, used to be incompatible with GCC.
- # ICC 10 doesn't accept -KPIC any more.
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- pgCC* | pgcpp*)
- # Portland Group C++ compiler
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- cxx*)
- # Compaq C++
- # Make sure the PIC flag is empty. It appears that all Alpha
- # Linux and Compaq Tru64 Unix objects are PIC.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- xlc* | xlC*)
- # IBM XL 8.0 on PPC
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
- ;;
- *)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*)
- # Sun C++ 5.9
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
- ;;
- esac
- ;;
- esac
- ;;
- lynxos*)
- ;;
- m88k*)
- ;;
- mvs*)
- case $cc_basename in
- cxx*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
- ;;
- *)
- ;;
- esac
- ;;
- netbsd*)
- ;;
- *qnx* | *nto*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
- ;;
- osf3* | osf4* | osf5*)
- case $cc_basename in
- KCC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
- ;;
- RCC*)
- # Rational C++ 2.4.1
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- cxx*)
- # Digital/Compaq C++
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # Make sure the PIC flag is empty. It appears that all Alpha
- # Linux and Compaq Tru64 Unix objects are PIC.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- *)
- ;;
- esac
- ;;
- psos*)
- ;;
- solaris*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.2, 5.x and Centerline C++
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
- ;;
- gcx*)
- # Green Hills C++ Compiler
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
- ;;
- *)
- ;;
- esac
- ;;
- sunos4*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.x
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- lcc*)
- # Lucid
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- *)
- ;;
- esac
- ;;
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- case $cc_basename in
- CC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- esac
- ;;
- tandem*)
- case $cc_basename in
- NCC*)
- # NonStop-UX NCC 3.20
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- ;;
- *)
- ;;
- esac
- ;;
- vxworks*)
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
- esac
- fi
-],
-[
- if test "$GCC" = yes; then
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- m68k)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
- ;;
- esac
- ;;
-
- beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
-
- mingw* | cygwin* | pw32* | os2* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- # Although the cygwin gcc ignores -fPIC, still need this for old-style
- # (--disable-auto-import) libraries
- m4_if([$1], [GCJ], [],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
- ;;
-
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
- ;;
-
- hpux*)
- # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
- # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
- # sets the default TLS model and affects inlining.
- case $host_cpu in
- hppa*64*)
- # +Z the default
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- ;;
-
- interix[[3-9]]*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
-
- msdosdjgpp*)
- # Just because we use GCC doesn't mean we suddenly get shared libraries
- # on systems that don't support them.
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- enable_shared=no
- ;;
-
- *nto* | *qnx*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
- fi
- ;;
-
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- else
- # PORTME Check for flag to pass linker flags through the system compiler.
- case $host_os in
- aix*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- else
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
-
- mingw* | cygwin* | pw32* | os2* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- m4_if([$1], [GCJ], [],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
- ;;
-
- hpux9* | hpux10* | hpux11*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- ;;
- esac
- # Is there a better lt_prog_compiler_static that works with the bundled CC?
- _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- ;;
-
- irix5* | irix6* | nonstopux*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # PIC (with -KPIC) is the default.
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
-
- linux* | k*bsd*-gnu)
- case $cc_basename in
- # old Intel for x86_64 which still supported -KPIC.
- ecc*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- # icc used to be incompatible with GCC.
- # ICC 10 doesn't accept -KPIC any more.
- icc* | ifort*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- # Lahey Fortran 8.1.
- lf95*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
- ;;
- pgcc* | pgf77* | pgf90* | pgf95*)
- # Portland Group compilers (*not* the Pentium gcc compiler,
- # which looks to be a dead project)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- ccc*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # All Alpha code is PIC.
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- xl*)
- # IBM XL C 8.0/Fortran 10.1 on PPC
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
- ;;
- *)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*)
- # Sun C 5.9
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- ;;
- *Sun\ F*)
- # Sun Fortran 8.3 passes all unrecognized flags to the linker
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
- ;;
- esac
- ;;
- esac
- ;;
-
- newsos6)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- *nto* | *qnx*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
- ;;
-
- osf3* | osf4* | osf5*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # All OSF/1 code is PIC.
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
-
- rdos*)
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
-
- solaris*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- case $cc_basename in
- f77* | f90* | f95*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
- *)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
- esac
- ;;
-
- sunos4*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec ;then
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
-
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- unicos*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
-
- uts4*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- *)
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
- esac
- fi
-])
-case $host_os in
- # For platforms which do not support PIC, -DPIC is meaningless:
- *djgpp*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
- ;;
-esac
-AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
-_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
- [How to pass a linker flag through the compiler])
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
- _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
- [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
- [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
- [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
- "" | " "*) ;;
- *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
- esac],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
-fi
-_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
- [Additional compiler flags for building library objects])
-
-#
-# Check to make sure the static flag actually works.
-#
-wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
-_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
- _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
- $lt_tmp_static_flag,
- [],
- [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
-_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
- [Compiler flag to prevent dynamic linking])
-])# _LT_COMPILER_PIC
-
-
-# _LT_LINKER_SHLIBS([TAGNAME])
-# ----------------------------
-# See if the linker supports building shared libraries.
-m4_defun([_LT_LINKER_SHLIBS],
-[AC_REQUIRE([LT_PATH_LD])dnl
-AC_REQUIRE([LT_PATH_NM])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_EGREP])dnl
-m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
-m4_require([_LT_TAG_COMPILER])dnl
-AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
-m4_if([$1], [CXX], [
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- case $host_os in
- aix[[4-9]]*)
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- else
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- fi
- ;;
- pw32*)
- _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
- ;;
- cygwin* | mingw* | cegcc*)
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
- ;;
- *)
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- ;;
- esac
- _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
-], [
- runpath_var=
- _LT_TAGVAR(allow_undefined_flag, $1)=
- _LT_TAGVAR(always_export_symbols, $1)=no
- _LT_TAGVAR(archive_cmds, $1)=
- _LT_TAGVAR(archive_expsym_cmds, $1)=
- _LT_TAGVAR(compiler_needs_object, $1)=no
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
- _LT_TAGVAR(export_dynamic_flag_spec, $1)=
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- _LT_TAGVAR(hardcode_automatic, $1)=no
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_direct_absolute, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
- _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
- _LT_TAGVAR(hardcode_libdir_separator, $1)=
- _LT_TAGVAR(hardcode_minus_L, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
- _LT_TAGVAR(inherit_rpath, $1)=no
- _LT_TAGVAR(link_all_deplibs, $1)=unknown
- _LT_TAGVAR(module_cmds, $1)=
- _LT_TAGVAR(module_expsym_cmds, $1)=
- _LT_TAGVAR(old_archive_from_new_cmds, $1)=
- _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
- _LT_TAGVAR(thread_safe_flag_spec, $1)=
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- # include_expsyms should be a list of space-separated symbols to be *always*
- # included in the symbol list
- _LT_TAGVAR(include_expsyms, $1)=
- # exclude_expsyms can be an extended regexp of symbols to exclude
- # it will be wrapped by ` (' and `)$', so one must not match beginning or
- # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
- # as well as any symbol that contains `d'.
- _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
- # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
- # platforms (ab)use it in PIC code, but their linkers get confused if
- # the symbol is explicitly referenced. Since portable code cannot
- # rely on this symbol name, it's probably fine to never include it in
- # preloaded symbol tables.
- # Exclude shared library initialization/finalization symbols.
-dnl Note also adjust exclude_expsyms for C++ above.
- extract_expsyms_cmds=
-
- case $host_os in
- cygwin* | mingw* | pw32* | cegcc*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$GCC" != yes; then
- with_gnu_ld=no
- fi
- ;;
- interix*)
- # we just hope/assume this is gcc and not c89 (= MSVC++)
- with_gnu_ld=yes
- ;;
- openbsd*)
- with_gnu_ld=no
- ;;
- esac
-
- _LT_TAGVAR(ld_shlibs, $1)=yes
- if test "$with_gnu_ld" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # Set some defaults for GNU ld with shared library support. These
- # are reset later if shared libraries are not supported. Putting them
- # here allows them to be overridden if necessary.
- runpath_var=LD_RUN_PATH
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
- _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- supports_anon_versioning=no
- case `$LD -v 2>&1` in
- *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
- *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
- *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
- *\ 2.11.*) ;; # other 2.11 versions
- *) supports_anon_versioning=yes ;;
- esac
-
- # See if GNU ld supports shared libraries.
- case $host_os in
- aix[[3-9]]*)
- # On AIX/PPC, the GNU linker is very broken
- if test "$host_cpu" != ia64; then
- _LT_TAGVAR(ld_shlibs, $1)=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-_LT_EOF
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)=''
- ;;
- m68k)
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- ;;
- esac
- ;;
-
- beos*)
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- cygwin* | mingw* | pw32* | cegcc*)
- # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
- # as there is no search path for DLLs.
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(always_export_symbols, $1)=no
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
-
- if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- interix[[3-9]]*)
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
-
- gnu* | linux* | tpf* | k*bsd*-gnu)
- tmp_diet=no
- if test "$host_os" = linux-dietlibc; then
- case $cc_basename in
- diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
- esac
- fi
- if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
- && test "$tmp_diet" = no
- then
- tmp_addflag=
- tmp_sharedflag='-shared'
- case $cc_basename,$host_cpu in
- pgcc*) # Portland Group C compiler
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag'
- ;;
- pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag -Mnomain' ;;
- ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
- tmp_addflag=' -i_dynamic' ;;
- efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
- tmp_addflag=' -i_dynamic -nofor_main' ;;
- ifc* | ifort*) # Intel Fortran compiler
- tmp_addflag=' -nofor_main' ;;
- lf95*) # Lahey Fortran 8.1
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- tmp_sharedflag='--shared' ;;
- xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
- tmp_sharedflag='-qmkshrobj'
- tmp_addflag= ;;
- esac
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*) # Sun C 5.9
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
- _LT_TAGVAR(compiler_needs_object, $1)=yes
- tmp_sharedflag='-G' ;;
- *Sun\ F*) # Sun Fortran 8.3
- tmp_sharedflag='-G' ;;
- esac
- _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-
- if test "x$supports_anon_versioning" = xyes; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
-
- case $cc_basename in
- xlf*)
- # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
- _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
- _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
- _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
- if test "x$supports_anon_versioning" = xyes; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- echo "local: *; };" >> $output_objdir/$libname.ver~
- $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
- fi
- ;;
- esac
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
- wlarc=
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- fi
- ;;
-
- solaris*)
- if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
- _LT_TAGVAR(ld_shlibs, $1)=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
- case `$LD -v 2>&1` in
- *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
- _LT_TAGVAR(ld_shlibs, $1)=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
-*** reliably create shared libraries on SCO systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- ;;
- *)
- # For security reasons, it is highly recommended that you always
- # use absolute paths for naming shared libraries, and exclude the
- # DT_RUNPATH tag from executables and libraries. But doing so
- # requires that you compile everything twice, which is a pain.
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- sunos4*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- wlarc=
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- *)
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
-
- if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
- runpath_var=
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
- _LT_TAGVAR(export_dynamic_flag_spec, $1)=
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case $host_os in
- aix3*)
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(always_export_symbols, $1)=yes
- _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- _LT_TAGVAR(hardcode_direct, $1)=unsupported
- fi
- ;;
-
- aix[[4-9]]*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- else
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- fi
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
- for ld_flag in $LDFLAGS; do
- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
- aix_use_runtimelinking=yes
- break
- fi
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- _LT_TAGVAR(archive_cmds, $1)=''
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
-
- if test "$GCC" = yes; then
- case $host_os in aix4.[[012]]|aix4.[[012]].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" &&
- strings "$collect2name" | $GREP resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- :
- else
- # We have old collect2
- _LT_TAGVAR(hardcode_direct, $1)=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- _LT_TAGVAR(always_export_symbols, $1)=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
- # Determine the default libpath from the value encoded in an
- # empty executable.
- _LT_SYS_MODULE_PATH_AIX
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
- _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
- _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an
- # empty executable.
- _LT_SYS_MODULE_PATH_AIX
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)=''
- ;;
- m68k)
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- ;;
- esac
- ;;
-
- bsdi[[45]]*)
- _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
- ;;
-
- cygwin* | mingw* | pw32* | cegcc*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
- # FIXME: Should let the user specify the lib program.
- _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
- _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
- ;;
-
- darwin* | rhapsody*)
- _LT_DARWIN_LINKER_FEATURES($1)
- ;;
-
- dgux*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- freebsd1*)
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd* | dragonfly*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- hpux9*)
- if test "$GCC" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- fi
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(hardcode_direct, $1)=yes
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- ;;
-
- hpux10*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
- fi
- if test "$with_gnu_ld" = no; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- fi
- ;;
-
- hpux11*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- case $host_cpu in
- hppa*64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- else
- case $host_cpu in
- hppa*64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- fi
- if test "$with_gnu_ld" = no; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
- *)
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- ;;
- esac
- fi
- ;;
-
- irix5* | irix6* | nonstopux*)
- if test "$GCC" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- # Try to use the -exported_symbol ld option, if it does not
- # work, assume that -exports_file does not work either and
- # implicitly export all symbols.
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
- AC_LINK_IFELSE(int foo(void) {},
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
- )
- LDFLAGS="$save_LDFLAGS"
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
- fi
- _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(inherit_rpath, $1)=yes
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
- else
- _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
- fi
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- newsos6)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- *nto* | *qnx*)
- ;;
-
- openbsd*)
- if test -f /usr/libexec/ld.so; then
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- else
- case $host_os in
- openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- ;;
- esac
- fi
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- os2*)
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
- _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$GCC" = yes; then
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
- fi
- _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- ;;
-
- osf4* | osf5*) # as osf3* with the addition of -msym flag
- if test "$GCC" = yes; then
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- else
- _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
- $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
-
- # Both c and cxx compiler support -rpath directly
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- fi
- _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- ;;
-
- solaris*)
- _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
- if test "$GCC" = yes; then
- wlarc='${wl}'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
- else
- case `$CC -V 2>&1` in
- *"Compilers 5.0"*)
- wlarc=''
- _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
- ;;
- *)
- wlarc='${wl}'
- _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
- ;;
- esac
- fi
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- case $host_os in
- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
- *)
- # The compiler driver will combine and reorder linker options,
- # but understands `-z linker_flag'. GCC discards it without `$wl',
- # but is careful enough not to reorder.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- if test "$GCC" = yes; then
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
- else
- _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
- fi
- ;;
- esac
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- ;;
-
- sunos4*)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
- fi
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- sysv4)
- case $host_vendor in
- sni)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
- ;;
- siemens)
- ## LD is ld it makes a PLAMLIB
- ## CC just makes a GrossModule.
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
- _LT_TAGVAR(hardcode_direct, $1)=no
- ;;
- motorola)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
- ;;
- esac
- runpath_var='LD_RUN_PATH'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- sysv4.3*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- _LT_TAGVAR(ld_shlibs, $1)=yes
- fi
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
- _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- uts4*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- *)
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
-
- if test x$host_vendor = xsni; then
- case $host in
- sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
- ;;
- esac
- fi
- fi
-])
-AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
-test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
-
-_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
-
-_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
-_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
-_LT_DECL([], [extract_expsyms_cmds], [2],
- [The commands to extract the exported symbol list from a shared archive])
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
-x|xyes)
- # Assume -lc should be added
- _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
-
- if test "$enable_shared" = yes && test "$GCC" = yes; then
- case $_LT_TAGVAR(archive_cmds, $1) in
- *'~'*)
- # FIXME: we may have to deal with multi-command sequences.
- ;;
- '$CC '*)
- # Test whether the compiler implicitly links with -lc since on some
- # systems, -lgcc has to come before -lc. If gcc already passes -lc
- # to ld, don't add -lc before -lgcc.
- AC_MSG_CHECKING([whether -lc should be explicitly linked in])
- $RM conftest*
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
- soname=conftest
- lib=conftest
- libobjs=conftest.$ac_objext
- deplibs=
- wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
- pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
- compiler_flags=-v
- linker_flags=-v
- verstring=
- output_objdir=.
- libname=conftest
- lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
- _LT_TAGVAR(allow_undefined_flag, $1)=
- if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
- then
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- else
- _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
- fi
- _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
- else
- cat conftest.err 1>&5
- fi
- $RM conftest*
- AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)])
- ;;
- esac
- fi
- ;;
-esac
-
-_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
- [Whether or not to add -lc for building shared libraries])
-_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
- [enable_shared_with_static_runtimes], [0],
- [Whether or not to disallow shared libs when runtime libs are static])
-_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
- [Compiler flag to allow reflexive dlopens])
-_LT_TAGDECL([], [whole_archive_flag_spec], [1],
- [Compiler flag to generate shared objects directly from archives])
-_LT_TAGDECL([], [compiler_needs_object], [1],
- [Whether the compiler copes with passing no objects directly])
-_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
- [Create an old-style archive from a shared archive])
-_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
- [Create a temporary old-style archive to link instead of a shared archive])
-_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
-_LT_TAGDECL([], [archive_expsym_cmds], [2])
-_LT_TAGDECL([], [module_cmds], [2],
- [Commands used to build a loadable module if different from building
- a shared archive.])
-_LT_TAGDECL([], [module_expsym_cmds], [2])
-_LT_TAGDECL([], [with_gnu_ld], [1],
- [Whether we are building with GNU ld or not])
-_LT_TAGDECL([], [allow_undefined_flag], [1],
- [Flag that allows shared libraries with undefined symbols to be built])
-_LT_TAGDECL([], [no_undefined_flag], [1],
- [Flag that enforces no undefined symbols])
-_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
- [Flag to hardcode $libdir into a binary during linking.
- This must work even if $libdir does not exist])
-_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
- [[If ld is used when linking, flag to hardcode $libdir into a binary
- during linking. This must work even if $libdir does not exist]])
-_LT_TAGDECL([], [hardcode_libdir_separator], [1],
- [Whether we need a single "-rpath" flag with a separated argument])
-_LT_TAGDECL([], [hardcode_direct], [0],
- [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
- DIR into the resulting binary])
-_LT_TAGDECL([], [hardcode_direct_absolute], [0],
- [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
- DIR into the resulting binary and the resulting library dependency is
- "absolute", i.e impossible to change by setting ${shlibpath_var} if the
- library is relocated])
-_LT_TAGDECL([], [hardcode_minus_L], [0],
- [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
- into the resulting binary])
-_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
- [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
- into the resulting binary])
-_LT_TAGDECL([], [hardcode_automatic], [0],
- [Set to "yes" if building a shared library automatically hardcodes DIR
- into the library and all subsequent libraries and executables linked
- against it])
-_LT_TAGDECL([], [inherit_rpath], [0],
- [Set to yes if linker adds runtime paths of dependent libraries
- to runtime path list])
-_LT_TAGDECL([], [link_all_deplibs], [0],
- [Whether libtool must link a program against all its dependency libraries])
-_LT_TAGDECL([], [fix_srcfile_path], [1],
- [Fix the shell variable $srcfile for the compiler])
-_LT_TAGDECL([], [always_export_symbols], [0],
- [Set to "yes" if exported symbols are required])
-_LT_TAGDECL([], [export_symbols_cmds], [2],
- [The commands to list exported symbols])
-_LT_TAGDECL([], [exclude_expsyms], [1],
- [Symbols that should not be listed in the preloaded symbols])
-_LT_TAGDECL([], [include_expsyms], [1],
- [Symbols that must always be exported])
-_LT_TAGDECL([], [prelink_cmds], [2],
- [Commands necessary for linking programs (against libraries) with templates])
-_LT_TAGDECL([], [file_list_spec], [1],
- [Specify filename containing input files])
-dnl FIXME: Not yet implemented
-dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
-dnl [Compiler flag to generate thread safe objects])
-])# _LT_LINKER_SHLIBS
-
-
-# _LT_LANG_C_CONFIG([TAG])
-# ------------------------
-# Ensure that the configuration variables for a C compiler are suitably
-# defined. These variables are subsequently used by _LT_CONFIG to write
-# the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_C_CONFIG],
-[m4_require([_LT_DECL_EGREP])dnl
-lt_save_CC="$CC"
-AC_LANG_PUSH(C)
-
-# Source file extension for C test sources.
-ac_ext=c
-
-# Object file extension for compiled C test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="int some_variable = 0;"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='int main(){return(0);}'
-
-_LT_TAG_COMPILER
-# Save the default compiler, since it gets overwritten when the other
-# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
-compiler_DEFAULT=$CC
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-if test -n "$compiler"; then
- _LT_COMPILER_NO_RTTI($1)
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_SYS_DYNAMIC_LINKER($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
- LT_SYS_DLOPEN_SELF
- _LT_CMD_STRIPLIB
-
- # Report which library types will actually be built
- AC_MSG_CHECKING([if libtool supports shared libraries])
- AC_MSG_RESULT([$can_build_shared])
-
- AC_MSG_CHECKING([whether to build shared libraries])
- test "$can_build_shared" = "no" && enable_shared=no
-
- # On AIX, shared libraries and static libraries use the same namespace, and
- # are all built from PIC.
- case $host_os in
- aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-
- aix[[4-9]]*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
- esac
- AC_MSG_RESULT([$enable_shared])
-
- AC_MSG_CHECKING([whether to build static libraries])
- # Make sure either enable_shared or enable_static is yes.
- test "$enable_shared" = yes || enable_static=yes
- AC_MSG_RESULT([$enable_static])
-
- _LT_CONFIG($1)
-fi
-AC_LANG_POP
-CC="$lt_save_CC"
-])# _LT_LANG_C_CONFIG
-
-
-# _LT_PROG_CXX
-# ------------
-# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
-# compiler, we have our own version here.
-m4_defun([_LT_PROG_CXX],
-[
-pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
-AC_PROG_CXX
-if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
- ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
- (test "X$CXX" != "Xg++"))) ; then
- AC_PROG_CXXCPP
-else
- _lt_caught_CXX_error=yes
-fi
-popdef([AC_MSG_ERROR])
-])# _LT_PROG_CXX
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([_LT_PROG_CXX], [])
-
-
-# _LT_LANG_CXX_CONFIG([TAG])
-# --------------------------
-# Ensure that the configuration variables for a C++ compiler are suitably
-# defined. These variables are subsequently used by _LT_CONFIG to write
-# the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_CXX_CONFIG],
-[AC_REQUIRE([_LT_PROG_CXX])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_EGREP])dnl
-
-AC_LANG_PUSH(C++)
-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
-_LT_TAGVAR(allow_undefined_flag, $1)=
-_LT_TAGVAR(always_export_symbols, $1)=no
-_LT_TAGVAR(archive_expsym_cmds, $1)=
-_LT_TAGVAR(compiler_needs_object, $1)=no
-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
-_LT_TAGVAR(hardcode_direct, $1)=no
-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
-_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
-_LT_TAGVAR(hardcode_libdir_separator, $1)=
-_LT_TAGVAR(hardcode_minus_L, $1)=no
-_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
-_LT_TAGVAR(hardcode_automatic, $1)=no
-_LT_TAGVAR(inherit_rpath, $1)=no
-_LT_TAGVAR(module_cmds, $1)=
-_LT_TAGVAR(module_expsym_cmds, $1)=
-_LT_TAGVAR(link_all_deplibs, $1)=unknown
-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_TAGVAR(no_undefined_flag, $1)=
-_LT_TAGVAR(whole_archive_flag_spec, $1)=
-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
-
-# Source file extension for C++ test sources.
-ac_ext=cpp
-
-# Object file extension for compiled C++ test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# No sense in running all these tests if we already determined that
-# the CXX compiler isn't working. Some variables (like enable_shared)
-# are currently assumed to apply to all compilers on this platform,
-# and will be corrupted by setting them based on a non-working compiler.
-if test "$_lt_caught_CXX_error" != yes; then
- # Code to be used in simple compile tests
- lt_simple_compile_test_code="int some_variable = 0;"
-
- # Code to be used in simple link tests
- lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
-
- # ltmain only uses $CC for tagged configurations so make sure $CC is set.
- _LT_TAG_COMPILER
-
- # save warnings/boilerplate of simple test code
- _LT_COMPILER_BOILERPLATE
- _LT_LINKER_BOILERPLATE
-
- # Allow CC to be a program name with arguments.
- lt_save_CC=$CC
- lt_save_LD=$LD
- lt_save_GCC=$GCC
- GCC=$GXX
- lt_save_with_gnu_ld=$with_gnu_ld
- lt_save_path_LD=$lt_cv_path_LD
- if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
- lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
- else
- $as_unset lt_cv_prog_gnu_ld
- fi
- if test -n "${lt_cv_path_LDCXX+set}"; then
- lt_cv_path_LD=$lt_cv_path_LDCXX
- else
- $as_unset lt_cv_path_LD
- fi
- test -z "${LDCXX+set}" || LD=$LDCXX
- CC=${CXX-"c++"}
- compiler=$CC
- _LT_TAGVAR(compiler, $1)=$CC
- _LT_CC_BASENAME([$compiler])
-
- if test -n "$compiler"; then
- # We don't want -fno-exception when compiling C++ code, so set the
- # no_builtin_flag separately
- if test "$GXX" = yes; then
- _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
- else
- _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
- fi
-
- if test "$GXX" = yes; then
- # Set up default GNU C++ configuration
-
- LT_PATH_LD
-
- # Check if GNU C++ uses GNU ld as the underlying linker, since the
- # archiving commands below assume that GNU ld is being used.
- if test "$with_gnu_ld" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-
- # If archive_cmds runs LD, not CC, wlarc should be empty
- # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
- # investigate it a little bit more. (MM)
- wlarc='${wl}'
-
- # ancient GNU ld didn't support --whole-archive et. al.
- if eval "`$CC -print-prog-name=ld` --help 2>&1" |
- $GREP 'no-whole-archive' > /dev/null; then
- _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- else
- with_gnu_ld=no
- wlarc=
-
- # A generic and very simple default shared library creation
- # command for GNU C++ for the case where it uses the native
- # linker, instead of GNU ld. If possible, this setting should
- # overridden to take advantage of the native linker features on
- # the platform it is being used on.
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
- fi
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
-
- else
- GXX=no
- with_gnu_ld=no
- wlarc=
- fi
-
- # PORTME: fill in a description of your system's C++ link characteristics
- AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
- _LT_TAGVAR(ld_shlibs, $1)=yes
- case $host_os in
- aix3*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- aix[[4-9]]*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
- for ld_flag in $LDFLAGS; do
- case $ld_flag in
- *-brtl*)
- aix_use_runtimelinking=yes
- break
- ;;
- esac
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- _LT_TAGVAR(archive_cmds, $1)=''
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
-
- if test "$GXX" = yes; then
- case $host_os in aix4.[[012]]|aix4.[[012]].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" &&
- strings "$collect2name" | $GREP resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- :
- else
- # We have old collect2
- _LT_TAGVAR(hardcode_direct, $1)=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=
- fi
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to
- # export.
- _LT_TAGVAR(always_export_symbols, $1)=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
- # Determine the default libpath from the value encoded in an empty
- # executable.
- _LT_SYS_MODULE_PATH_AIX
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
-
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
- _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
- _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an
- # empty executable.
- _LT_SYS_MODULE_PATH_AIX
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
- # This is similar to how AIX traditionally builds its shared
- # libraries.
- _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- beos*)
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- chorus*)
- case $cc_basename in
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- cygwin* | mingw* | pw32* | cegcc*)
- # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
- # as there is no search path for DLLs.
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(always_export_symbols, $1)=no
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
-
- if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- darwin* | rhapsody*)
- _LT_DARWIN_LINKER_FEATURES($1)
- ;;
-
- dgux*)
- case $cc_basename in
- ec++*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- ghcx*)
- # Green Hills C++ Compiler
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- freebsd[[12]]*)
- # C++ shared libraries reported to be fairly broken before
- # switch to ELF
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- freebsd-elf*)
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- ;;
-
- freebsd* | dragonfly*)
- # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
- # conventions
- _LT_TAGVAR(ld_shlibs, $1)=yes
- ;;
-
- gnu*)
- ;;
-
- hpux9*)
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
- # but as the default
- # location of the library.
-
- case $cc_basename in
- CC*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- aCC*)
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
- ;;
- *)
- if test "$GXX" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- hpux10*|hpux11*)
- if test $with_gnu_ld = no; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- ;;
- *)
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- ;;
- esac
- fi
- case $host_cpu in
- hppa*64*|ia64*)
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
- *)
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
- # but as the default
- # location of the library.
- ;;
- esac
-
- case $cc_basename in
- CC*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- aCC*)
- case $host_cpu in
- hppa*64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- ia64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- esac
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
- ;;
- *)
- if test "$GXX" = yes; then
- if test $with_gnu_ld = no; then
- case $host_cpu in
- hppa*64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- ia64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- esac
- fi
- else
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- interix[[3-9]]*)
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
- irix5* | irix6*)
- case $cc_basename in
- CC*)
- # SGI C++
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
-
- # Archives containing C++ object files must be created using
- # "CC -ar", where "CC" is the IRIX C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
- ;;
- *)
- if test "$GXX" = yes; then
- if test "$with_gnu_ld" = no; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
- fi
- fi
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- ;;
- esac
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(inherit_rpath, $1)=yes
- ;;
-
- linux* | k*bsd*-gnu)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-
- # Archives containing C++ object files must be created using
- # "CC -Bstatic", where "CC" is the KAI C++ compiler.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
- ;;
- icpc* | ecpc* )
- # Intel C++
- with_gnu_ld=yes
- # version 8.0 and above of icpc choke on multiply defined symbols
- # if we add $predep_objects and $postdep_objects, however 7.1 and
- # earlier do not add the objects themselves.
- case `$CC -V 2>&1` in
- *"Version 7."*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- ;;
- *) # Version 8.0 or newer
- tmp_idyn=
- case $host_cpu in
- ia64*) tmp_idyn=' -i_dynamic';;
- esac
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- ;;
- esac
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
- ;;
- pgCC* | pgcpp*)
- # Portland Group C++ compiler
- case `$CC -V` in
- *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*)
- _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
- rm -rf $tpldir~
- $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
- compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
- _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
- rm -rf $tpldir~
- $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
- $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
- $RANLIB $oldlib'
- _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
- rm -rf $tpldir~
- $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
- $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
- rm -rf $tpldir~
- $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
- $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
- ;;
- *) # Version 6 will use weak symbols
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
- ;;
- esac
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
- ;;
- cxx*)
- # Compaq C++
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
-
- runpath_var=LD_RUN_PATH
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
- ;;
- xl*)
- # IBM XL 8.0 on PPC, with GNU ld
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- if test "x$supports_anon_versioning" = xyes; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
- ;;
- *)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*)
- # Sun C++ 5.9
- _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
- _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
- _LT_TAGVAR(compiler_needs_object, $1)=yes
-
- # Not sure whether something based on
- # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
- # would be better.
- output_verbose_link_cmd='echo'
-
- # Archives containing C++ object files must be created using
- # "CC -xar", where "CC" is the Sun C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
- ;;
- esac
- ;;
- esac
- ;;
-
- lynxos*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- m88k*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- mvs*)
- case $cc_basename in
- cxx*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
- wlarc=
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- fi
- # Workaround some broken pre-1.5 toolchains
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
- ;;
-
- *nto* | *qnx*)
- _LT_TAGVAR(ld_shlibs, $1)=yes
- ;;
-
- openbsd2*)
- # C++ shared libraries are fairly broken
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- openbsd*)
- if test -f /usr/libexec/ld.so; then
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- fi
- output_verbose_link_cmd=echo
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- osf3* | osf4* | osf5*)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Archives containing C++ object files must be created using
- # the KAI C++ compiler.
- case $host in
- osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
- *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
- esac
- ;;
- RCC*)
- # Rational C++ 2.4.1
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- cxx*)
- case $host in
- osf3*)
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- ;;
- *)
- _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
- echo "-hidden">> $lib.exp~
- $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
- $RM $lib.exp'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- ;;
- esac
-
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
- ;;
- *)
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- case $host in
- osf3*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- ;;
- esac
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
-
- else
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- psos*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- sunos4*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.x
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- lcc*)
- # Lucid
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- solaris*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.2, 5.x and Centerline C++
- _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
- _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
- _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- case $host_os in
- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
- *)
- # The compiler driver will combine and reorder linker options,
- # but understands `-z linker_flag'.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
- ;;
- esac
- _LT_TAGVAR(link_all_deplibs, $1)=yes
-
- output_verbose_link_cmd='echo'
-
- # Archives containing C++ object files must be created using
- # "CC -xar", where "CC" is the Sun C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
- ;;
- gcx*)
- # Green Hills C++ Compiler
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
-
- # The C++ compiler must be used to create the archive.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
- ;;
- *)
- # GNU C++ compiler with Solaris linker
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
- if $CC --version | $GREP -v '^2\.7' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
- else
- # g++ 2.7 appears to require `-G' NOT `-shared' on this
- # platform.
- _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
- fi
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
- case $host_os in
- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
- *)
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
- ;;
- esac
- fi
- ;;
- esac
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
- _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var='LD_RUN_PATH'
-
- case $cc_basename in
- CC*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- case $cc_basename in
- CC*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- ;;
-
- tandem*)
- case $cc_basename in
- NCC*)
- # NonStop-UX NCC 3.20
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- vxworks*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
-
- AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
- test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
-
- _LT_TAGVAR(GCC, $1)="$GXX"
- _LT_TAGVAR(LD, $1)="$LD"
-
- ## CAVEAT EMPTOR:
- ## There is no encapsulation within the following macros, do not change
- ## the running order or otherwise move them around unless you know exactly
- ## what you are doing...
- _LT_SYS_HIDDEN_LIBDEPS($1)
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_SYS_DYNAMIC_LINKER($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
-
- _LT_CONFIG($1)
- fi # test -n "$compiler"
-
- CC=$lt_save_CC
- LDCXX=$LD
- LD=$lt_save_LD
- GCC=$lt_save_GCC
- with_gnu_ld=$lt_save_with_gnu_ld
- lt_cv_path_LDCXX=$lt_cv_path_LD
- lt_cv_path_LD=$lt_save_path_LD
- lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
- lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
-fi # test "$_lt_caught_CXX_error" != yes
-
-AC_LANG_POP
-])# _LT_LANG_CXX_CONFIG
-
-
-# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
-# ---------------------------------
-# Figure out "hidden" library dependencies from verbose
-# compiler output when linking a shared library.
-# Parse the compiler output and extract the necessary
-# objects, libraries and library flags.
-m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-# Dependencies to place before and after the object being linked:
-_LT_TAGVAR(predep_objects, $1)=
-_LT_TAGVAR(postdep_objects, $1)=
-_LT_TAGVAR(predeps, $1)=
-_LT_TAGVAR(postdeps, $1)=
-_LT_TAGVAR(compiler_lib_search_path, $1)=
-
-dnl we can't use the lt_simple_compile_test_code here,
-dnl because it contains code intended for an executable,
-dnl not a library. It's possible we should let each
-dnl tag define a new lt_????_link_test_code variable,
-dnl but it's only used here...
-m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
-int a;
-void foo (void) { a = 0; }
-_LT_EOF
-], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
-class Foo
-{
-public:
- Foo (void) { a = 0; }
-private:
- int a;
-};
-_LT_EOF
-], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
- subroutine foo
- implicit none
- integer*4 a
- a=0
- return
- end
-_LT_EOF
-], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
- subroutine foo
- implicit none
- integer a
- a=0
- return
- end
-_LT_EOF
-], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
-public class foo {
- private int a;
- public void bar (void) {
- a = 0;
- }
-};
-_LT_EOF
-])
-dnl Parse the compiler output and extract the necessary
-dnl objects, libraries and library flags.
-if AC_TRY_EVAL(ac_compile); then
- # Parse the compiler output and extract the necessary
- # objects, libraries and library flags.
-
- # Sentinel used to keep track of whether or not we are before
- # the conftest object file.
- pre_test_object_deps_done=no
-
- for p in `eval "$output_verbose_link_cmd"`; do
- case $p in
-
- -L* | -R* | -l*)
- # Some compilers place space between "-{L,R}" and the path.
- # Remove the space.
- if test $p = "-L" ||
- test $p = "-R"; then
- prev=$p
- continue
- else
- prev=
- fi
-
- if test "$pre_test_object_deps_done" = no; then
- case $p in
- -L* | -R*)
- # Internal compiler library paths should come after those
- # provided the user. The postdeps already come after the
- # user supplied libs so there is no need to process them.
- if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
- _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
- else
- _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
- fi
- ;;
- # The "-l" case would never come before the object being
- # linked, so don't bother handling this case.
- esac
- else
- if test -z "$_LT_TAGVAR(postdeps, $1)"; then
- _LT_TAGVAR(postdeps, $1)="${prev}${p}"
- else
- _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
- fi
- fi
- ;;
-
- *.$objext)
- # This assumes that the test object file only shows up
- # once in the compiler output.
- if test "$p" = "conftest.$objext"; then
- pre_test_object_deps_done=yes
- continue
- fi
-
- if test "$pre_test_object_deps_done" = no; then
- if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
- _LT_TAGVAR(predep_objects, $1)="$p"
- else
- _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
- fi
- else
- if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
- _LT_TAGVAR(postdep_objects, $1)="$p"
- else
- _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
- fi
- fi
- ;;
-
- *) ;; # Ignore the rest.
-
- esac
- done
-
- # Clean up.
- rm -f a.out a.exe
-else
- echo "libtool.m4: error: problem compiling $1 test program"
-fi
-
-$RM -f confest.$objext
-
-# PORTME: override above test on systems where it is broken
-m4_if([$1], [CXX],
-[case $host_os in
-interix[[3-9]]*)
- # Interix 3.5 installs completely hosed .la files for C++, so rather than
- # hack all around it, let's just trust "g++" to DTRT.
- _LT_TAGVAR(predep_objects,$1)=
- _LT_TAGVAR(postdep_objects,$1)=
- _LT_TAGVAR(postdeps,$1)=
- ;;
-
-linux*)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*)
- # Sun C++ 5.9
-
- # The more standards-conforming stlport4 library is
- # incompatible with the Cstd library. Avoid specifying
- # it if it's in CXXFLAGS. Ignore libCrun as
- # -library=stlport4 depends on it.
- case " $CXX $CXXFLAGS " in
- *" -library=stlport4 "*)
- solaris_use_stlport4=yes
- ;;
- esac
-
- if test "$solaris_use_stlport4" != yes; then
- _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
- fi
- ;;
- esac
- ;;
-
-solaris*)
- case $cc_basename in
- CC*)
- # The more standards-conforming stlport4 library is
- # incompatible with the Cstd library. Avoid specifying
- # it if it's in CXXFLAGS. Ignore libCrun as
- # -library=stlport4 depends on it.
- case " $CXX $CXXFLAGS " in
- *" -library=stlport4 "*)
- solaris_use_stlport4=yes
- ;;
- esac
-
- # Adding this requires a known-good setup of shared libraries for
- # Sun compiler versions before 5.6, else PIC objects from an old
- # archive will be linked into the output, leading to subtle bugs.
- if test "$solaris_use_stlport4" != yes; then
- _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
- fi
- ;;
- esac
- ;;
-esac
-])
-
-case " $_LT_TAGVAR(postdeps, $1) " in
-*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
-esac
- _LT_TAGVAR(compiler_lib_search_dirs, $1)=
-if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
- _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
-fi
-_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
- [The directories searched by this compiler when creating a shared library])
-_LT_TAGDECL([], [predep_objects], [1],
- [Dependencies to place before and after the objects being linked to
- create a shared library])
-_LT_TAGDECL([], [postdep_objects], [1])
-_LT_TAGDECL([], [predeps], [1])
-_LT_TAGDECL([], [postdeps], [1])
-_LT_TAGDECL([], [compiler_lib_search_path], [1],
- [The library search path used internally by the compiler when linking
- a shared library])
-])# _LT_SYS_HIDDEN_LIBDEPS
-
-
-# _LT_PROG_F77
-# ------------
-# Since AC_PROG_F77 is broken, in that it returns the empty string
-# if there is no fortran compiler, we have our own version here.
-m4_defun([_LT_PROG_F77],
-[
-pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
-AC_PROG_F77
-if test -z "$F77" || test "X$F77" = "Xno"; then
- _lt_disable_F77=yes
-fi
-popdef([AC_MSG_ERROR])
-])# _LT_PROG_F77
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([_LT_PROG_F77], [])
-
-
-# _LT_LANG_F77_CONFIG([TAG])
-# --------------------------
-# Ensure that the configuration variables for a Fortran 77 compiler are
-# suitably defined. These variables are subsequently used by _LT_CONFIG
-# to write the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_F77_CONFIG],
-[AC_REQUIRE([_LT_PROG_F77])dnl
-AC_LANG_PUSH(Fortran 77)
-
-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
-_LT_TAGVAR(allow_undefined_flag, $1)=
-_LT_TAGVAR(always_export_symbols, $1)=no
-_LT_TAGVAR(archive_expsym_cmds, $1)=
-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
-_LT_TAGVAR(hardcode_direct, $1)=no
-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
-_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
-_LT_TAGVAR(hardcode_libdir_separator, $1)=
-_LT_TAGVAR(hardcode_minus_L, $1)=no
-_LT_TAGVAR(hardcode_automatic, $1)=no
-_LT_TAGVAR(inherit_rpath, $1)=no
-_LT_TAGVAR(module_cmds, $1)=
-_LT_TAGVAR(module_expsym_cmds, $1)=
-_LT_TAGVAR(link_all_deplibs, $1)=unknown
-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_TAGVAR(no_undefined_flag, $1)=
-_LT_TAGVAR(whole_archive_flag_spec, $1)=
-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
-
-# Source file extension for f77 test sources.
-ac_ext=f
-
-# Object file extension for compiled f77 test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# No sense in running all these tests if we already determined that
-# the F77 compiler isn't working. Some variables (like enable_shared)
-# are currently assumed to apply to all compilers on this platform,
-# and will be corrupted by setting them based on a non-working compiler.
-if test "$_lt_disable_F77" != yes; then
- # Code to be used in simple compile tests
- lt_simple_compile_test_code="\
- subroutine t
- return
- end
-"
-
- # Code to be used in simple link tests
- lt_simple_link_test_code="\
- program t
- end
-"
-
- # ltmain only uses $CC for tagged configurations so make sure $CC is set.
- _LT_TAG_COMPILER
-
- # save warnings/boilerplate of simple test code
- _LT_COMPILER_BOILERPLATE
- _LT_LINKER_BOILERPLATE
-
- # Allow CC to be a program name with arguments.
- lt_save_CC="$CC"
- lt_save_GCC=$GCC
- CC=${F77-"f77"}
- compiler=$CC
- _LT_TAGVAR(compiler, $1)=$CC
- _LT_CC_BASENAME([$compiler])
- GCC=$G77
- if test -n "$compiler"; then
- AC_MSG_CHECKING([if libtool supports shared libraries])
- AC_MSG_RESULT([$can_build_shared])
-
- AC_MSG_CHECKING([whether to build shared libraries])
- test "$can_build_shared" = "no" && enable_shared=no
-
- # On AIX, shared libraries and static libraries use the same namespace, and
- # are all built from PIC.
- case $host_os in
- aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
- aix[[4-9]]*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
- esac
- AC_MSG_RESULT([$enable_shared])
-
- AC_MSG_CHECKING([whether to build static libraries])
- # Make sure either enable_shared or enable_static is yes.
- test "$enable_shared" = yes || enable_static=yes
- AC_MSG_RESULT([$enable_static])
-
- _LT_TAGVAR(GCC, $1)="$G77"
- _LT_TAGVAR(LD, $1)="$LD"
-
- ## CAVEAT EMPTOR:
- ## There is no encapsulation within the following macros, do not change
- ## the running order or otherwise move them around unless you know exactly
- ## what you are doing...
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_SYS_DYNAMIC_LINKER($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
-
- _LT_CONFIG($1)
- fi # test -n "$compiler"
-
- GCC=$lt_save_GCC
- CC="$lt_save_CC"
-fi # test "$_lt_disable_F77" != yes
-
-AC_LANG_POP
-])# _LT_LANG_F77_CONFIG
-
-
-# _LT_PROG_FC
-# -----------
-# Since AC_PROG_FC is broken, in that it returns the empty string
-# if there is no fortran compiler, we have our own version here.
-m4_defun([_LT_PROG_FC],
-[
-pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
-AC_PROG_FC
-if test -z "$FC" || test "X$FC" = "Xno"; then
- _lt_disable_FC=yes
-fi
-popdef([AC_MSG_ERROR])
-])# _LT_PROG_FC
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([_LT_PROG_FC], [])
-
-
-# _LT_LANG_FC_CONFIG([TAG])
-# -------------------------
-# Ensure that the configuration variables for a Fortran compiler are
-# suitably defined. These variables are subsequently used by _LT_CONFIG
-# to write the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_FC_CONFIG],
-[AC_REQUIRE([_LT_PROG_FC])dnl
-AC_LANG_PUSH(Fortran)
-
-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
-_LT_TAGVAR(allow_undefined_flag, $1)=
-_LT_TAGVAR(always_export_symbols, $1)=no
-_LT_TAGVAR(archive_expsym_cmds, $1)=
-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
-_LT_TAGVAR(hardcode_direct, $1)=no
-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
-_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
-_LT_TAGVAR(hardcode_libdir_separator, $1)=
-_LT_TAGVAR(hardcode_minus_L, $1)=no
-_LT_TAGVAR(hardcode_automatic, $1)=no
-_LT_TAGVAR(inherit_rpath, $1)=no
-_LT_TAGVAR(module_cmds, $1)=
-_LT_TAGVAR(module_expsym_cmds, $1)=
-_LT_TAGVAR(link_all_deplibs, $1)=unknown
-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_TAGVAR(no_undefined_flag, $1)=
-_LT_TAGVAR(whole_archive_flag_spec, $1)=
-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
-
-# Source file extension for fc test sources.
-ac_ext=${ac_fc_srcext-f}
-
-# Object file extension for compiled fc test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# No sense in running all these tests if we already determined that
-# the FC compiler isn't working. Some variables (like enable_shared)
-# are currently assumed to apply to all compilers on this platform,
-# and will be corrupted by setting them based on a non-working compiler.
-if test "$_lt_disable_FC" != yes; then
- # Code to be used in simple compile tests
- lt_simple_compile_test_code="\
- subroutine t
- return
- end
-"
-
- # Code to be used in simple link tests
- lt_simple_link_test_code="\
- program t
- end
-"
-
- # ltmain only uses $CC for tagged configurations so make sure $CC is set.
- _LT_TAG_COMPILER
-
- # save warnings/boilerplate of simple test code
- _LT_COMPILER_BOILERPLATE
- _LT_LINKER_BOILERPLATE
-
- # Allow CC to be a program name with arguments.
- lt_save_CC="$CC"
- lt_save_GCC=$GCC
- CC=${FC-"f95"}
- compiler=$CC
- GCC=$ac_cv_fc_compiler_gnu
-
- _LT_TAGVAR(compiler, $1)=$CC
- _LT_CC_BASENAME([$compiler])
-
- if test -n "$compiler"; then
- AC_MSG_CHECKING([if libtool supports shared libraries])
- AC_MSG_RESULT([$can_build_shared])
-
- AC_MSG_CHECKING([whether to build shared libraries])
- test "$can_build_shared" = "no" && enable_shared=no
-
- # On AIX, shared libraries and static libraries use the same namespace, and
- # are all built from PIC.
- case $host_os in
- aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
- aix[[4-9]]*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
- esac
- AC_MSG_RESULT([$enable_shared])
-
- AC_MSG_CHECKING([whether to build static libraries])
- # Make sure either enable_shared or enable_static is yes.
- test "$enable_shared" = yes || enable_static=yes
- AC_MSG_RESULT([$enable_static])
-
- _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
- _LT_TAGVAR(LD, $1)="$LD"
-
- ## CAVEAT EMPTOR:
- ## There is no encapsulation within the following macros, do not change
- ## the running order or otherwise move them around unless you know exactly
- ## what you are doing...
- _LT_SYS_HIDDEN_LIBDEPS($1)
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_SYS_DYNAMIC_LINKER($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
-
- _LT_CONFIG($1)
- fi # test -n "$compiler"
-
- GCC=$lt_save_GCC
- CC="$lt_save_CC"
-fi # test "$_lt_disable_FC" != yes
-
-AC_LANG_POP
-])# _LT_LANG_FC_CONFIG
-
-
-# _LT_LANG_GCJ_CONFIG([TAG])
-# --------------------------
-# Ensure that the configuration variables for the GNU Java Compiler compiler
-# are suitably defined. These variables are subsequently used by _LT_CONFIG
-# to write the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_GCJ_CONFIG],
-[AC_REQUIRE([LT_PROG_GCJ])dnl
-AC_LANG_SAVE
-
-# Source file extension for Java test sources.
-ac_ext=java
-
-# Object file extension for compiled Java test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="class foo {}"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-_LT_TAG_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-lt_save_GCC=$GCC
-GCC=yes
-CC=${GCJ-"gcj"}
-compiler=$CC
-_LT_TAGVAR(compiler, $1)=$CC
-_LT_TAGVAR(LD, $1)="$LD"
-_LT_CC_BASENAME([$compiler])
-
-# GCJ did not exist at the time GCC didn't implicitly link libc in.
-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
-
-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-
-if test -n "$compiler"; then
- _LT_COMPILER_NO_RTTI($1)
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
-
- _LT_CONFIG($1)
-fi
-
-AC_LANG_RESTORE
-
-GCC=$lt_save_GCC
-CC="$lt_save_CC"
-])# _LT_LANG_GCJ_CONFIG
-
-
-# _LT_LANG_RC_CONFIG([TAG])
-# -------------------------
-# Ensure that the configuration variables for the Windows resource compiler
-# are suitably defined. These variables are subsequently used by _LT_CONFIG
-# to write the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_RC_CONFIG],
-[AC_REQUIRE([LT_PROG_RC])dnl
-AC_LANG_SAVE
-
-# Source file extension for RC test sources.
-ac_ext=rc
-
-# Object file extension for compiled RC test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
-
-# Code to be used in simple link tests
-lt_simple_link_test_code="$lt_simple_compile_test_code"
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-_LT_TAG_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-lt_save_GCC=$GCC
-GCC=
-CC=${RC-"windres"}
-compiler=$CC
-_LT_TAGVAR(compiler, $1)=$CC
-_LT_CC_BASENAME([$compiler])
-_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
-
-if test -n "$compiler"; then
- :
- _LT_CONFIG($1)
-fi
-
-GCC=$lt_save_GCC
-AC_LANG_RESTORE
-CC="$lt_save_CC"
-])# _LT_LANG_RC_CONFIG
-
-
-# LT_PROG_GCJ
-# -----------
-AC_DEFUN([LT_PROG_GCJ],
-[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
- [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
- [AC_CHECK_TOOL(GCJ, gcj,)
- test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
- AC_SUBST(GCJFLAGS)])])[]dnl
-])
-
-# Old name:
-AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
-
-
-# LT_PROG_RC
-# ----------
-AC_DEFUN([LT_PROG_RC],
-[AC_CHECK_TOOL(RC, windres,)
-])
-
-# Old name:
-AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([LT_AC_PROG_RC], [])
-
-
-# _LT_DECL_EGREP
-# --------------
-# If we don't have a new enough Autoconf to choose the best grep
-# available, choose the one first in the user's PATH.
-m4_defun([_LT_DECL_EGREP],
-[AC_REQUIRE([AC_PROG_EGREP])dnl
-AC_REQUIRE([AC_PROG_FGREP])dnl
-test -z "$GREP" && GREP=grep
-_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
-_LT_DECL([], [EGREP], [1], [An ERE matcher])
-_LT_DECL([], [FGREP], [1], [A literal string matcher])
-dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
-AC_SUBST([GREP])
-])
-
-
-# _LT_DECL_OBJDUMP
-# --------------
-# If we don't have a new enough Autoconf to choose the best objdump
-# available, choose the one first in the user's PATH.
-m4_defun([_LT_DECL_OBJDUMP],
-[AC_CHECK_TOOL(OBJDUMP, objdump, false)
-test -z "$OBJDUMP" && OBJDUMP=objdump
-_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
-AC_SUBST([OBJDUMP])
-])
-
-
-# _LT_DECL_SED
-# ------------
-# Check for a fully-functional sed program, that truncates
-# as few characters as possible. Prefer GNU sed if found.
-m4_defun([_LT_DECL_SED],
-[AC_PROG_SED
-test -z "$SED" && SED=sed
-Xsed="$SED -e 1s/^X//"
-_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
-_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
- [Sed that helps us avoid accidentally triggering echo(1) options like -n])
-])# _LT_DECL_SED
-
-m4_ifndef([AC_PROG_SED], [
-# NOTE: This macro has been submitted for inclusion into #
-# GNU Autoconf as AC_PROG_SED. When it is available in #
-# a released version of Autoconf we should remove this #
-# macro and use it instead. #
-
-m4_defun([AC_PROG_SED],
-[AC_MSG_CHECKING([for a sed that does not truncate output])
-AC_CACHE_VAL(lt_cv_path_SED,
-[# Loop through the user's path and test for sed and gsed.
-# Then use that list of sed's as ones to test for truncation.
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for lt_ac_prog in sed gsed; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
- lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
- fi
- done
- done
-done
-IFS=$as_save_IFS
-lt_ac_max=0
-lt_ac_count=0
-# Add /usr/xpg4/bin/sed as it is typically found on Solaris
-# along with /bin/sed that truncates output.
-for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
- test ! -f $lt_ac_sed && continue
- cat /dev/null > conftest.in
- lt_ac_count=0
- echo $ECHO_N "0123456789$ECHO_C" >conftest.in
- # Check for GNU sed and select it if it is found.
- if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
- lt_cv_path_SED=$lt_ac_sed
- break
- fi
- while true; do
- cat conftest.in conftest.in >conftest.tmp
- mv conftest.tmp conftest.in
- cp conftest.in conftest.nl
- echo >>conftest.nl
- $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
- cmp -s conftest.out conftest.nl || break
- # 10000 chars as input seems more than enough
- test $lt_ac_count -gt 10 && break
- lt_ac_count=`expr $lt_ac_count + 1`
- if test $lt_ac_count -gt $lt_ac_max; then
- lt_ac_max=$lt_ac_count
- lt_cv_path_SED=$lt_ac_sed
- fi
- done
-done
-])
-SED=$lt_cv_path_SED
-AC_SUBST([SED])
-AC_MSG_RESULT([$SED])
-])#AC_PROG_SED
-])#m4_ifndef
-
-# Old name:
-AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([LT_AC_PROG_SED], [])
-
-
-# _LT_CHECK_SHELL_FEATURES
-# ------------------------
-# Find out whether the shell is Bourne or XSI compatible,
-# or has some other useful features.
-m4_defun([_LT_CHECK_SHELL_FEATURES],
-[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
-# Try some XSI features
-xsi_shell=no
-( _lt_dummy="a/b/c"
- test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
- = c,a/b,, \
- && eval 'test $(( 1 + 1 )) -eq 2 \
- && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
- && xsi_shell=yes
-AC_MSG_RESULT([$xsi_shell])
-_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
-
-AC_MSG_CHECKING([whether the shell understands "+="])
-lt_shell_append=no
-( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
- >/dev/null 2>&1 \
- && lt_shell_append=yes
-AC_MSG_RESULT([$lt_shell_append])
-_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
-
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- lt_unset=unset
-else
- lt_unset=false
-fi
-_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
-
-# test EBCDIC or ASCII
-case `echo X|tr X '\101'` in
- A) # ASCII based system
- # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
- lt_SP2NL='tr \040 \012'
- lt_NL2SP='tr \015\012 \040\040'
- ;;
- *) # EBCDIC based system
- lt_SP2NL='tr \100 \n'
- lt_NL2SP='tr \r\n \100\100'
- ;;
-esac
-_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
-_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
-])# _LT_CHECK_SHELL_FEATURES
-
-
-# _LT_PROG_XSI_SHELLFNS
-# ---------------------
-# Bourne and XSI compatible variants of some useful shell functions.
-m4_defun([_LT_PROG_XSI_SHELLFNS],
-[case $xsi_shell in
- yes)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE. If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
- case ${1} in
- */*) func_dirname_result="${1%/*}${2}" ;;
- * ) func_dirname_result="${3}" ;;
- esac
-}
-
-# func_basename file
-func_basename ()
-{
- func_basename_result="${1##*/}"
-}
-
-# func_dirname_and_basename file append nondir_replacement
-# perform func_basename and func_dirname in a single function
-# call:
-# dirname: Compute the dirname of FILE. If nonempty,
-# add APPEND to the result, otherwise set result
-# to NONDIR_REPLACEMENT.
-# value returned in "$func_dirname_result"
-# basename: Compute filename of FILE.
-# value retuned in "$func_basename_result"
-# Implementation must be kept synchronized with func_dirname
-# and func_basename. For efficiency, we do not delegate to
-# those functions but instead duplicate the functionality here.
-func_dirname_and_basename ()
-{
- case ${1} in
- */*) func_dirname_result="${1%/*}${2}" ;;
- * ) func_dirname_result="${3}" ;;
- esac
- func_basename_result="${1##*/}"
-}
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-func_stripname ()
-{
- # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
- # positional parameters, so assign one to ordinary parameter first.
- func_stripname_result=${3}
- func_stripname_result=${func_stripname_result#"${1}"}
- func_stripname_result=${func_stripname_result%"${2}"}
-}
-
-# func_opt_split
-func_opt_split ()
-{
- func_opt_split_opt=${1%%=*}
- func_opt_split_arg=${1#*=}
-}
-
-# func_lo2o object
-func_lo2o ()
-{
- case ${1} in
- *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
- *) func_lo2o_result=${1} ;;
- esac
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
- func_xform_result=${1%.*}.lo
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
- func_arith_result=$(( $[*] ))
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
- func_len_result=${#1}
-}
-
-_LT_EOF
- ;;
- *) # Bourne compatible functions.
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE. If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
- # Extract subdirectory from the argument.
- func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
- if test "X$func_dirname_result" = "X${1}"; then
- func_dirname_result="${3}"
- else
- func_dirname_result="$func_dirname_result${2}"
- fi
-}
-
-# func_basename file
-func_basename ()
-{
- func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
-}
-
-dnl func_dirname_and_basename
-dnl A portable version of this function is already defined in general.m4sh
-dnl so there is no need for it here.
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-# func_strip_suffix prefix name
-func_stripname ()
-{
- case ${2} in
- .*) func_stripname_result=`$ECHO "X${3}" \
- | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
- *) func_stripname_result=`$ECHO "X${3}" \
- | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
- esac
-}
-
-# sed scripts:
-my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
-my_sed_long_arg='1s/^-[[^=]]*=//'
-
-# func_opt_split
-func_opt_split ()
-{
- func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
- func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
-}
-
-# func_lo2o object
-func_lo2o ()
-{
- func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
- func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
- func_arith_result=`expr "$[@]"`
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
- func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
-}
-
-_LT_EOF
-esac
-
-case $lt_shell_append in
- yes)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
- eval "$[1]+=\$[2]"
-}
-_LT_EOF
- ;;
- *)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
- eval "$[1]=\$$[1]\$[2]"
-}
-
-_LT_EOF
- ;;
- esac
-])
-
-# Helper functions for option handling. -*- Autoconf -*-
-#
-# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
-# Written by Gary V. Vaughan, 2004
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# serial 6 ltoptions.m4
-
-# This is to help aclocal find these macros, as it can't see m4_define.
-AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
-
-
-# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
-# ------------------------------------------
-m4_define([_LT_MANGLE_OPTION],
-[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
-
-
-# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
-# ---------------------------------------
-# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
-# matching handler defined, dispatch to it. Other OPTION-NAMEs are
-# saved as a flag.
-m4_define([_LT_SET_OPTION],
-[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
-m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
- _LT_MANGLE_DEFUN([$1], [$2]),
- [m4_warning([Unknown $1 option `$2'])])[]dnl
-])
-
-
-# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
-# ------------------------------------------------------------
-# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
-m4_define([_LT_IF_OPTION],
-[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
-
-
-# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
-# -------------------------------------------------------
-# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
-# are set.
-m4_define([_LT_UNLESS_OPTIONS],
-[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
- [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
- [m4_define([$0_found])])])[]dnl
-m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
-])[]dnl
-])
-
-
-# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
-# ----------------------------------------
-# OPTION-LIST is a space-separated list of Libtool options associated
-# with MACRO-NAME. If any OPTION has a matching handler declared with
-# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
-# the unknown option and exit.
-m4_defun([_LT_SET_OPTIONS],
-[# Set options
-m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
- [_LT_SET_OPTION([$1], _LT_Option)])
-
-m4_if([$1],[LT_INIT],[
- dnl
- dnl Simply set some default values (i.e off) if boolean options were not
- dnl specified:
- _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
- ])
- _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
- ])
- dnl
- dnl If no reference was made to various pairs of opposing options, then
- dnl we run the default mode handler for the pair. For example, if neither
- dnl `shared' nor `disable-shared' was passed, we enable building of shared
- dnl archives by default:
- _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
- _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
- _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
- _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
- [_LT_ENABLE_FAST_INSTALL])
- ])
-])# _LT_SET_OPTIONS
-
-
-
-# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
-# -----------------------------------------
-m4_define([_LT_MANGLE_DEFUN],
-[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
-
-
-# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
-# -----------------------------------------------
-m4_define([LT_OPTION_DEFINE],
-[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
-])# LT_OPTION_DEFINE
-
-
-# dlopen
-# ------
-LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
-])
-
-AU_DEFUN([AC_LIBTOOL_DLOPEN],
-[_LT_SET_OPTION([LT_INIT], [dlopen])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you
-put the `dlopen' option into LT_INIT's first parameter.])
-])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
-
-
-# win32-dll
-# ---------
-# Declare package support for building win32 dll's.
-LT_OPTION_DEFINE([LT_INIT], [win32-dll],
-[enable_win32_dll=yes
-
-case $host in
-*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
- AC_CHECK_TOOL(AS, as, false)
- AC_CHECK_TOOL(DLLTOOL, dlltool, false)
- AC_CHECK_TOOL(OBJDUMP, objdump, false)
- ;;
-esac
-
-test -z "$AS" && AS=as
-_LT_DECL([], [AS], [0], [Assembler program])dnl
-
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
-
-test -z "$OBJDUMP" && OBJDUMP=objdump
-_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
-])# win32-dll
-
-AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-_LT_SET_OPTION([LT_INIT], [win32-dll])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you
-put the `win32-dll' option into LT_INIT's first parameter.])
-])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
-
-
-# _LT_ENABLE_SHARED([DEFAULT])
-# ----------------------------
-# implement the --enable-shared flag, and supports the `shared' and
-# `disable-shared' LT_INIT options.
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-m4_define([_LT_ENABLE_SHARED],
-[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
-AC_ARG_ENABLE([shared],
- [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
- [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_shared=yes ;;
- no) enable_shared=no ;;
- *)
- enable_shared=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_shared=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
-
- _LT_DECL([build_libtool_libs], [enable_shared], [0],
- [Whether or not to build shared libraries])
-])# _LT_ENABLE_SHARED
-
-LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
-LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
-
-# Old names:
-AC_DEFUN([AC_ENABLE_SHARED],
-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
-])
-
-AC_DEFUN([AC_DISABLE_SHARED],
-[_LT_SET_OPTION([LT_INIT], [disable-shared])
-])
-
-AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
-AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AM_ENABLE_SHARED], [])
-dnl AC_DEFUN([AM_DISABLE_SHARED], [])
-
-
-
-# _LT_ENABLE_STATIC([DEFAULT])
-# ----------------------------
-# implement the --enable-static flag, and support the `static' and
-# `disable-static' LT_INIT options.
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-m4_define([_LT_ENABLE_STATIC],
-[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
-AC_ARG_ENABLE([static],
- [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
- [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_static=yes ;;
- no) enable_static=no ;;
- *)
- enable_static=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_static=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
-
- _LT_DECL([build_old_libs], [enable_static], [0],
- [Whether or not to build static libraries])
-])# _LT_ENABLE_STATIC
-
-LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
-LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
-
-# Old names:
-AC_DEFUN([AC_ENABLE_STATIC],
-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
-])
-
-AC_DEFUN([AC_DISABLE_STATIC],
-[_LT_SET_OPTION([LT_INIT], [disable-static])
-])
-
-AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
-AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AM_ENABLE_STATIC], [])
-dnl AC_DEFUN([AM_DISABLE_STATIC], [])
-
-
-
-# _LT_ENABLE_FAST_INSTALL([DEFAULT])
-# ----------------------------------
-# implement the --enable-fast-install flag, and support the `fast-install'
-# and `disable-fast-install' LT_INIT options.
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-m4_define([_LT_ENABLE_FAST_INSTALL],
-[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
-AC_ARG_ENABLE([fast-install],
- [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
- [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_fast_install=yes ;;
- no) enable_fast_install=no ;;
- *)
- enable_fast_install=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_fast_install=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
-
-_LT_DECL([fast_install], [enable_fast_install], [0],
- [Whether or not to optimize for fast installation])dnl
-])# _LT_ENABLE_FAST_INSTALL
-
-LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
-LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
-
-# Old names:
-AU_DEFUN([AC_ENABLE_FAST_INSTALL],
-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you put
-the `fast-install' option into LT_INIT's first parameter.])
-])
-
-AU_DEFUN([AC_DISABLE_FAST_INSTALL],
-[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you put
-the `disable-fast-install' option into LT_INIT's first parameter.])
-])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
-dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
-
-
-# _LT_WITH_PIC([MODE])
-# --------------------
-# implement the --with-pic flag, and support the `pic-only' and `no-pic'
-# LT_INIT options.
-# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
-m4_define([_LT_WITH_PIC],
-[AC_ARG_WITH([pic],
- [AS_HELP_STRING([--with-pic],
- [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
- [pic_mode="$withval"],
- [pic_mode=default])
-
-test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
-
-_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
-])# _LT_WITH_PIC
-
-LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
-LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
-
-# Old name:
-AU_DEFUN([AC_LIBTOOL_PICMODE],
-[_LT_SET_OPTION([LT_INIT], [pic-only])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you
-put the `pic-only' option into LT_INIT's first parameter.])
-])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
-
-
-m4_define([_LTDL_MODE], [])
-LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
- [m4_define([_LTDL_MODE], [nonrecursive])])
-LT_OPTION_DEFINE([LTDL_INIT], [recursive],
- [m4_define([_LTDL_MODE], [recursive])])
-LT_OPTION_DEFINE([LTDL_INIT], [subproject],
- [m4_define([_LTDL_MODE], [subproject])])
-
-m4_define([_LTDL_TYPE], [])
-LT_OPTION_DEFINE([LTDL_INIT], [installable],
- [m4_define([_LTDL_TYPE], [installable])])
-LT_OPTION_DEFINE([LTDL_INIT], [convenience],
- [m4_define([_LTDL_TYPE], [convenience])])
-
-# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
-#
-# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
-# Written by Gary V. Vaughan, 2004
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# serial 6 ltsugar.m4
-
-# This is to help aclocal find these macros, as it can't see m4_define.
-AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
-
-
-# lt_join(SEP, ARG1, [ARG2...])
-# -----------------------------
-# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
-# associated separator.
-# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
-# versions in m4sugar had bugs.
-m4_define([lt_join],
-[m4_if([$#], [1], [],
- [$#], [2], [[$2]],
- [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
-m4_define([_lt_join],
-[m4_if([$#$2], [2], [],
- [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
-
-
-# lt_car(LIST)
-# lt_cdr(LIST)
-# ------------
-# Manipulate m4 lists.
-# These macros are necessary as long as will still need to support
-# Autoconf-2.59 which quotes differently.
-m4_define([lt_car], [[$1]])
-m4_define([lt_cdr],
-[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
- [$#], 1, [],
- [m4_dquote(m4_shift($@))])])
-m4_define([lt_unquote], $1)
-
-
-# lt_append(MACRO-NAME, STRING, [SEPARATOR])
-# ------------------------------------------
-# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
-# Note that neither SEPARATOR nor STRING are expanded; they are appended
-# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
-# No SEPARATOR is output if MACRO-NAME was previously undefined (different
-# than defined and empty).
-#
-# This macro is needed until we can rely on Autoconf 2.62, since earlier
-# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
-m4_define([lt_append],
-[m4_define([$1],
- m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
-
-
-
-# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
-# ----------------------------------------------------------
-# Produce a SEP delimited list of all paired combinations of elements of
-# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
-# has the form PREFIXmINFIXSUFFIXn.
-# Needed until we can rely on m4_combine added in Autoconf 2.62.
-m4_define([lt_combine],
-[m4_if(m4_eval([$# > 3]), [1],
- [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
-[[m4_foreach([_Lt_prefix], [$2],
- [m4_foreach([_Lt_suffix],
- ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
- [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
-
-
-# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
-# -----------------------------------------------------------------------
-# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
-# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
-m4_define([lt_if_append_uniq],
-[m4_ifdef([$1],
- [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
- [lt_append([$1], [$2], [$3])$4],
- [$5])],
- [lt_append([$1], [$2], [$3])$4])])
-
-
-# lt_dict_add(DICT, KEY, VALUE)
-# -----------------------------
-m4_define([lt_dict_add],
-[m4_define([$1($2)], [$3])])
-
-
-# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
-# --------------------------------------------
-m4_define([lt_dict_add_subkey],
-[m4_define([$1($2:$3)], [$4])])
-
-
-# lt_dict_fetch(DICT, KEY, [SUBKEY])
-# ----------------------------------
-m4_define([lt_dict_fetch],
-[m4_ifval([$3],
- m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
- m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
-
-
-# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
-# -----------------------------------------------------------------
-m4_define([lt_if_dict_fetch],
-[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
- [$5],
- [$6])])
-
-
-# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
-# --------------------------------------------------------------
-m4_define([lt_dict_filter],
-[m4_if([$5], [], [],
- [lt_join(m4_quote(m4_default([$4], [[, ]])),
- lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
- [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
-])
-
-# ltversion.m4 -- version numbers -*- Autoconf -*-
-#
-# Copyright (C) 2004 Free Software Foundation, Inc.
-# Written by Scott James Remnant, 2004
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# Generated from ltversion.in.
-
-# serial 3012 ltversion.m4
-# This file is part of GNU Libtool
-
-m4_define([LT_PACKAGE_VERSION], [2.2.6])
-m4_define([LT_PACKAGE_REVISION], [1.3012])
-
-AC_DEFUN([LTVERSION_VERSION],
-[macro_version='2.2.6'
-macro_revision='1.3012'
-_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
-_LT_DECL(, macro_revision, 0)
-])
-
-# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
-#
-# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
-# Written by Scott James Remnant, 2004.
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# serial 4 lt~obsolete.m4
-
-# These exist entirely to fool aclocal when bootstrapping libtool.
-#
-# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
-# which have later been changed to m4_define as they aren't part of the
-# exported API, or moved to Autoconf or Automake where they belong.
-#
-# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
-# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
-# using a macro with the same name in our local m4/libtool.m4 it'll
-# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
-# and doesn't know about Autoconf macros at all.)
-#
-# So we provide this file, which has a silly filename so it's always
-# included after everything else. This provides aclocal with the
-# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
-# because those macros already exist, or will be overwritten later.
-# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
-#
-# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
-# Yes, that means every name once taken will need to remain here until
-# we give up compatibility with versions before 1.7, at which point
-# we need to keep only those names which we still refer to.
-
-# This is to help aclocal find these macros, as it can't see m4_define.
-AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
-
-m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
-m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
-m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
-m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
-m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
-m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
-m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
-m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
-m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
-m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
-m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
-m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
-m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
-m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
-m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
-m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
-m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
-m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
-m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
-m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
-m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
-m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
-m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
-m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
-m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
-m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
-m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
-m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
-m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
-m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
-m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
-m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
-m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
-m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
-m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
-m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
-m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
-m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
-m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
-m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
-m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
-m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
-m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
-m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
-m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
-m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
-m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
-m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
-m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
-m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
-m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.eps b/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.eps
deleted file mode 100644
index c2670a0bc77..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.eps
+++ /dev/null
@@ -1,5333 +0,0 @@
-%!PS-Adobe-3.1 EPSF-3.0
-%ADO_DSC_Encoding: MacOS Roman
-%%Title: logo_color_eps.eps
-%%Creator: Adobe Illustrator(R) 13.0
-%%For: Mary Diarte
-%%CreationDate: 5/25/10
-%%BoundingBox: 0 0 372 212
-%%HiResBoundingBox: 0 0 372 211.3042
-%%CropBox: 0 0 372 211.3042
-%%LanguageLevel: 2
-%%DocumentData: Clean7Bit
-%ADOBeginClientInjection: DocumentHeader "AI11EPS"
-%%AI8_CreatorVersion: 13.0.2 %AI9_PrintingDataBegin %AI3_Cropmarks: 36.0000 36.0000 336.0000 175.3042
-%ADO_BuildNumber: Adobe Illustrator(R) 13.0.2 x434 R agm 4.4379 ct 5.1039 %ADO_ContainsXMP: MainFirst %AI7_Thumbnail: 128 76 8 %%BeginData: 6312 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD4AFFA90C0D %0C35A8FD79FF3505060506050CA8FD5AFF84360E0E0D140E0E0D140E0E0D %140E0E0D140E0E0D140E0E0D140E0E0D0D0506050C05060535FD59FF7E0E %3685608560856085608560856085608560856085608560856085600D0506 %05060506050605FD59FF365A856085618560856185608561856085618560 %856185608561856035050605060506050605067EFD58FF0D615A615A615A %615A615A615A615A615A615A615A615A615A615A5A050605060506050605 %060584FD58FF146185608561856085618560856185608561856085618560 %856161060C0506050C0606050C05067EFD58FF0D615A615A615A615A615A %615A615A615A615A615A615A615A610D0605060506060C050605060584FD %58FF0E5A855A615A855A615A855A615A855A615A855A615A855A61360605 %060506062F050605060506A8FD58FF0D5A5A615A5A5A615A5A5A615A5A5A %615A5A5A615A5A5A615A0C05060506055905060506050605FD59FF0E5A61 %5A615A615A615A615A615A615A615A615A615A615A5A050C0506052F0C06 %050C05060535FD59FF0D5A365B5A5A365B5A5A365B5A5A365B5A5A365B5A %5A365B0C0605060506590605060506050659FD59FF145A5B5A615A5B5A61 %5A5B5A615A5B5A615A5B5A615A5B360605060506350C05060506050606FD %5AFF0D5A365A365A365A365A365A365A365A365A365A365A360D05060506 %05840506050605060535FD5AFF14365B365B365B365B365B365B365B365B %365B365B365B050C0506055A0C06050C0506050CA8FD5AFF0D5A3636365A %3636365A3636365A3636365A3636365A0D060506050C5906050605060506 %0CFD5BFF0E365A365A365A365A365A365A365A365A365A365A360D050605 %06590C05060506050605A9FD5BFF0D363036303630363036303630363036 %3036303630360506050605A90506050605060535FD5CFF0EFD14360D0C05 %06055A2F06050C0506050CAFFD5CFF0D360E3630360E3630360E3630360E %3630360E36300D0506050684060506050605062FFD5DFF1436360E363636 %0E3636360E3636360E3636360E360C0605060C5905060506050606FD5EFF %0D360E360D360E360D360E360D360E360D360E360D0C0506058406060506 %05060CA9FD5EFF140E360E360E360E360E360E360E360E360E360E0D0506 %050CA806050C062F2FA9FFFF2F0C050C06350C84FD07FF5A0C0C060D050C %2FFD06FF0D0506050C0CFD3AFF0D360E140D360E140D360E140D360E140D %360E14060605062E3505060506050CFFFF0C0659FFFFA806065AFD05FF7E %0C0535A8FFFFFF590C0559FD05FF7E05062EFD3BFF0E0E360E140E360E14 %0E360E140E360E140E360E0C0506058406060506050684FF84062FFD05FF %0584FD04FF590605A9FD06FFA80C052FFD04FF84060584FD3BFF0D0E0D14 %0D0E0D140D0E0D140D0E0D140D0E0D0D050605067E06050605062FFFFF35 %055AFD05FF2F59FFFFFF7E060559FD08FF84060535FD04FF05065AFD09FF %060CFD30FF0E0E140E140E140E140E140E140E140E140E140D06050C0C5A %050C05060CFFFFFF2F0C0CFD05FFA8FD04FF0D050CFD0AFF2F0605AFFFFF %FF0C0584FD09FF0D05AFFD05FFA9FD29FF0D0E0D140D0E0D140D0E0D140D %0E0D140D0E0D0D050605590606050605AFFFFFFF5905062FFD08FF840506 %2FFD0AFFA905062EFFFFFF05065AFD0AFFA9FD05FF5A06FD29FF140E140D %140E140D140E140D140E140D140E140D0C05065906050606A9FD04FFA80C %05060CFD07FF2F060584FD0BFF0C050CFFFFFF060584FD10FF060CFD29FF %0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0606055A05062FFD07FF %2F0605060559FD05FF0C0506FD0CFF060605FFFFFF050659FD07FFA85A2E %0C06FFFF350506050C0684FD04FF0C06050C59FD1DFF140E140D140E140D %140E140D140E0E0D140E0E0D0E050C2F0C84FD09FF350C0506050DAFFFFF %FF0C0605FD0CFF0D0506FFFFFF060584FD07FFA92F0C050DFFFF7E5A050C %7E84AFFFFFFF060C2F0C050CA9FD1CFF0D0E0D0E0D0E0D0E0D0E0D0E0D0E %0D0E0D0E0D0E0D060C0C59FD0BFF840C0506050CA8FFFF0C0506FD0CFF06 %0605FFFFA9050659FD09FF840606FFFFFF590606FD05FF060C84FF59060C %FD1DFF0E0D140E0E0D140E0E0D140E0E0D140E0E0D140E0E06590CFD0EFF %5A0606050DFFFF0C060584FD0BFF0C050CFFFF7E060584FD0AFF050CFFFF %FF84050DFD04FF840635FFFF2F05FD1EFF0D0E0D0E0D0E0D0E0D0E0D0E0D %0E0D0E0D0E0D0E0D0C2E84FD0FFF84050605FFFF59050659FD0BFF05060C %FFFF8405065AFD09FF590606FFFFFF5A0606FD04FF59055A590C0584FD1E %FF0E0D140E0E0D140E0E0D140E0E0D140E0E0D140E0E0684FD0AFF59FD06 %FF5A050C7EFFFF0C052FFD0AFF59060584FFFF7E0C0584FD09FF84050DFF %FFFF84050DFD04FF2F0606355AFD20FF0D0E0D0E0D0E0D0E0D0E0D0E0D0E %0D0E0D0E0D0E0D0C59FD0AFF0C59FD05FFA80605A9FFFF59060584FD09FF %0C050CFFFFFF8405065AFD09FF590606FFFFFF5A062EFD04FF350559FD05 %FFA9FD1CFF140E0E0D140E0E0D140E0E0D140E0E0D140E0E0D140684FD0A %FF0C2FFD05FF84050CFD04FF2F0606FD08FF35050CAFFFFFFF7E060584FD %05FF8459FFFF84050DFFFFFF840535FFFF84847E0606FD04FF8406FD1CFF %5A0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0C84FD0AFF0C0559FD %04FF060659FD05FF2E0606A8FD04FFA82F050CA8FD04FF5A05062EFD05FF %0559FFFF5A0605FFFFFF590605842F0C7EFF0506065A592F055AFD1DFF5A %0E0D140E0E0D140E0E0D140E0E0D140E0E0D140CA8FD0AFF0C0C060D2F2F %050C59FD07FF7E0D052F2F590C0C065AFD05FF350506050C060D0C0C0506 %7EFF2F0C050C0C5AFFFF0C06050C84FFFFA90C06050C0635FD1FFFA98584 %A9848584A9848584A9848584A9848584355AFD0AFF84A8FF7E5A2F5AA8FD %0AFFA80C0605062EFD07FF7E845A8459845A8459845AAFFD0AFF5A84FD06 %FFA88484FD34FF3584FD1EFF0C06050659FD5BFF842FFD1FFF0C0605067E %FD5AFFA935FD20FF2F06050C59FD5AFF06FD21FF59060506062F2F5AFD7A %FF8435592F5984FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFC %FFFDD1FFFF %%EndData
-%ADOEndClientInjection: DocumentHeader "AI11EPS"
-%%Pages: 1
-%%DocumentNeededResources:
-%%DocumentSuppliedResources: procset Adobe_AGM_Image 1.0 0
-%%+ procset Adobe_CoolType_Utility_T42 1.0 0
-%%+ procset Adobe_CoolType_Utility_MAKEOCF 1.23 0
-%%+ procset Adobe_CoolType_Core 2.31 0
-%%+ procset Adobe_AGM_Core 2.0 0
-%%+ procset Adobe_AGM_Utils 1.0 0
-%%DocumentFonts:
-%%DocumentNeededFonts:
-%%DocumentNeededFeatures:
-%%DocumentSuppliedFeatures:
-%%DocumentProcessColors:
-%%DocumentCustomColors: (PANTONE 2905 U)
-%%+ (PANTONE 309 U)
-%%+ (PANTONE 3005 U)
-%%CMYKCustomColor: 0.4100 0.0200 0 0 (PANTONE 2905 U)
-%%+ 1 0 0.0900 0.7200 (PANTONE 309 U)
-%%+ 1 0.3400 0 0.0200 (PANTONE 3005 U)
-%%RGBCustomColor:
-%%EndComments
-
-
-
-
-
-
-%%BeginDefaults
-%%ViewingOrientation: 1 0 0 1
-%%EndDefaults
-%%BeginProlog
-%%BeginResource: procset Adobe_AGM_Utils 1.0 0
-%%Version: 1.0 0
-%%Copyright: Copyright(C)2000-2006 Adobe Systems, Inc. All Rights Reserved.
-systemdict/setpacking known
-{currentpacking true setpacking}if
-userdict/Adobe_AGM_Utils 73 dict dup begin put
-/bdf
-{bind def}bind def
-/nd{null def}bdf
-/xdf
-{exch def}bdf
-/ldf
-{load def}bdf
-/ddf
-{put}bdf
-/xddf
-{3 -1 roll put}bdf
-/xpt
-{exch put}bdf
-/ndf
-{
- exch dup where{
- pop pop pop
- }{
- xdf
- }ifelse
-}def
-/cdndf
-{
- exch dup currentdict exch known{
- pop pop
- }{
- exch def
- }ifelse
-}def
-/gx
-{get exec}bdf
-/ps_level
- /languagelevel where{
- pop systemdict/languagelevel gx
- }{
- 1
- }ifelse
-def
-/level2
- ps_level 2 ge
-def
-/level3
- ps_level 3 ge
-def
-/ps_version
- {version cvr}stopped{-1}if
-def
-/set_gvm
-{currentglobal exch setglobal}bdf
-/reset_gvm
-{setglobal}bdf
-/makereadonlyarray
-{
- /packedarray where{pop packedarray
- }{
- array astore readonly}ifelse
-}bdf
-/map_reserved_ink_name
-{
- dup type/stringtype eq{
- dup/Red eq{
- pop(_Red_)
- }{
- dup/Green eq{
- pop(_Green_)
- }{
- dup/Blue eq{
- pop(_Blue_)
- }{
- dup()cvn eq{
- pop(Process)
- }if
- }ifelse
- }ifelse
- }ifelse
- }if
-}bdf
-/AGMUTIL_GSTATE 22 dict def
-/get_gstate
-{
- AGMUTIL_GSTATE begin
- /AGMUTIL_GSTATE_clr_spc currentcolorspace def
- /AGMUTIL_GSTATE_clr_indx 0 def
- /AGMUTIL_GSTATE_clr_comps 12 array def
- mark currentcolor counttomark
- {AGMUTIL_GSTATE_clr_comps AGMUTIL_GSTATE_clr_indx 3 -1 roll put
- /AGMUTIL_GSTATE_clr_indx AGMUTIL_GSTATE_clr_indx 1 add def}repeat pop
- /AGMUTIL_GSTATE_fnt rootfont def
- /AGMUTIL_GSTATE_lw currentlinewidth def
- /AGMUTIL_GSTATE_lc currentlinecap def
- /AGMUTIL_GSTATE_lj currentlinejoin def
- /AGMUTIL_GSTATE_ml currentmiterlimit def
- currentdash/AGMUTIL_GSTATE_do xdf/AGMUTIL_GSTATE_da xdf
- /AGMUTIL_GSTATE_sa currentstrokeadjust def
- /AGMUTIL_GSTATE_clr_rnd currentcolorrendering def
- /AGMUTIL_GSTATE_op currentoverprint def
- /AGMUTIL_GSTATE_bg currentblackgeneration cvlit def
- /AGMUTIL_GSTATE_ucr currentundercolorremoval cvlit def
- currentcolortransfer cvlit/AGMUTIL_GSTATE_gy_xfer xdf cvlit/AGMUTIL_GSTATE_b_xfer xdf
- cvlit/AGMUTIL_GSTATE_g_xfer xdf cvlit/AGMUTIL_GSTATE_r_xfer xdf
- /AGMUTIL_GSTATE_ht currenthalftone def
- /AGMUTIL_GSTATE_flt currentflat def
- end
-}def
-/set_gstate
-{
- AGMUTIL_GSTATE begin
- AGMUTIL_GSTATE_clr_spc setcolorspace
- AGMUTIL_GSTATE_clr_indx{AGMUTIL_GSTATE_clr_comps AGMUTIL_GSTATE_clr_indx 1 sub get
- /AGMUTIL_GSTATE_clr_indx AGMUTIL_GSTATE_clr_indx 1 sub def}repeat setcolor
- AGMUTIL_GSTATE_fnt setfont
- AGMUTIL_GSTATE_lw setlinewidth
- AGMUTIL_GSTATE_lc setlinecap
- AGMUTIL_GSTATE_lj setlinejoin
- AGMUTIL_GSTATE_ml setmiterlimit
- AGMUTIL_GSTATE_da AGMUTIL_GSTATE_do setdash
- AGMUTIL_GSTATE_sa setstrokeadjust
- AGMUTIL_GSTATE_clr_rnd setcolorrendering
- AGMUTIL_GSTATE_op setoverprint
- AGMUTIL_GSTATE_bg cvx setblackgeneration
- AGMUTIL_GSTATE_ucr cvx setundercolorremoval
- AGMUTIL_GSTATE_r_xfer cvx AGMUTIL_GSTATE_g_xfer cvx AGMUTIL_GSTATE_b_xfer cvx
- AGMUTIL_GSTATE_gy_xfer cvx setcolortransfer
- AGMUTIL_GSTATE_ht/HalftoneType get dup 9 eq exch 100 eq or
- {
- currenthalftone/HalftoneType get AGMUTIL_GSTATE_ht/HalftoneType get ne
- {
- mark AGMUTIL_GSTATE_ht{sethalftone}stopped cleartomark
- }if
- }{
- AGMUTIL_GSTATE_ht sethalftone
- }ifelse
- AGMUTIL_GSTATE_flt setflat
- end
-}def
-/get_gstate_and_matrix
-{
- AGMUTIL_GSTATE begin
- /AGMUTIL_GSTATE_ctm matrix currentmatrix def
- end
- get_gstate
-}def
-/set_gstate_and_matrix
-{
- set_gstate
- AGMUTIL_GSTATE begin
- AGMUTIL_GSTATE_ctm setmatrix
- end
-}def
-/AGMUTIL_str256 256 string def
-/AGMUTIL_src256 256 string def
-/AGMUTIL_dst64 64 string def
-/AGMUTIL_srcLen nd
-/AGMUTIL_ndx nd
-/AGMUTIL_cpd nd
-/capture_cpd{
- //Adobe_AGM_Utils/AGMUTIL_cpd currentpagedevice ddf
-}def
-/thold_halftone
-{
- level3
- {sethalftone currenthalftone}
- {
- dup/HalftoneType get 3 eq
- {
- sethalftone currenthalftone
- }{
- begin
- Width Height mul{
- Thresholds read{pop}if
- }repeat
- end
- currenthalftone
- }ifelse
- }ifelse
-}def
-/rdcmntline
-{
- currentfile AGMUTIL_str256 readline pop
- (%)anchorsearch{pop}if
-}bdf
-/filter_cmyk
-{
- dup type/filetype ne{
- exch()/SubFileDecode filter
- }{
- exch pop
- }
- ifelse
- [
- exch
- {
- AGMUTIL_src256 readstring pop
- dup length/AGMUTIL_srcLen exch def
- /AGMUTIL_ndx 0 def
- AGMCORE_plate_ndx 4 AGMUTIL_srcLen 1 sub{
- 1 index exch get
- AGMUTIL_dst64 AGMUTIL_ndx 3 -1 roll put
- /AGMUTIL_ndx AGMUTIL_ndx 1 add def
- }for
- pop
- AGMUTIL_dst64 0 AGMUTIL_ndx getinterval
- }
- bind
- /exec cvx
- ]cvx
-}bdf
-/filter_indexed_devn
-{
- cvi Names length mul names_index add Lookup exch get
-}bdf
-/filter_devn
-{
- 4 dict begin
- /srcStr xdf
- /dstStr xdf
- dup type/filetype ne{
- 0()/SubFileDecode filter
- }if
- [
- exch
- [
- /devicen_colorspace_dict/AGMCORE_gget cvx/begin cvx
- currentdict/srcStr get/readstring cvx/pop cvx
- /dup cvx/length cvx 0/gt cvx[
- Adobe_AGM_Utils/AGMUTIL_ndx 0/ddf cvx
- names_index Names length currentdict/srcStr get length 1 sub{
- 1/index cvx/exch cvx/get cvx
- currentdict/dstStr get/AGMUTIL_ndx/load cvx 3 -1/roll cvx/put cvx
- Adobe_AGM_Utils/AGMUTIL_ndx/AGMUTIL_ndx/load cvx 1/add cvx/ddf cvx
- }for
- currentdict/dstStr get 0/AGMUTIL_ndx/load cvx/getinterval cvx
- ]cvx/if cvx
- /end cvx
- ]cvx
- bind
- /exec cvx
- ]cvx
- end
-}bdf
-/AGMUTIL_imagefile nd
-/read_image_file
-{
- AGMUTIL_imagefile 0 setfileposition
- 10 dict begin
- /imageDict xdf
- /imbufLen Width BitsPerComponent mul 7 add 8 idiv def
- /imbufIdx 0 def
- /origDataSource imageDict/DataSource get def
- /origMultipleDataSources imageDict/MultipleDataSources get def
- /origDecode imageDict/Decode get def
- /dstDataStr imageDict/Width get colorSpaceElemCnt mul string def
- imageDict/MultipleDataSources known{MultipleDataSources}{false}ifelse
- {
- /imbufCnt imageDict/DataSource get length def
- /imbufs imbufCnt array def
- 0 1 imbufCnt 1 sub{
- /imbufIdx xdf
- imbufs imbufIdx imbufLen string put
- imageDict/DataSource get imbufIdx[AGMUTIL_imagefile imbufs imbufIdx get/readstring cvx/pop cvx]cvx put
- }for
- DeviceN_PS2{
- imageDict begin
- /DataSource[DataSource/devn_sep_datasource cvx]cvx def
- /MultipleDataSources false def
- /Decode[0 1]def
- end
- }if
- }{
- /imbuf imbufLen string def
- Indexed_DeviceN level3 not and DeviceN_NoneName or{
- /srcDataStrs[imageDict begin
- currentdict/MultipleDataSources known{MultipleDataSources{DataSource length}{1}ifelse}{1}ifelse
- {
- Width Decode length 2 div mul cvi string
- }repeat
- end]def
- imageDict begin
- /DataSource[AGMUTIL_imagefile Decode BitsPerComponent false 1/filter_indexed_devn load dstDataStr srcDataStrs devn_alt_datasource/exec cvx]cvx def
- /Decode[0 1]def
- end
- }{
- imageDict/DataSource[1 string dup 0 AGMUTIL_imagefile Decode length 2 idiv string/readstring cvx/pop cvx names_index/get cvx/put cvx]cvx put
- imageDict/Decode[0 1]put
- }ifelse
- }ifelse
- imageDict exch
- load exec
- imageDict/DataSource origDataSource put
- imageDict/MultipleDataSources origMultipleDataSources put
- imageDict/Decode origDecode put
- end
-}bdf
-/write_image_file
-{
- begin
- {(AGMUTIL_imagefile)(w+)file}stopped{
- false
- }{
- Adobe_AGM_Utils/AGMUTIL_imagefile xddf
- 2 dict begin
- /imbufLen Width BitsPerComponent mul 7 add 8 idiv def
- MultipleDataSources{DataSource 0 get}{DataSource}ifelse type/filetype eq{
- /imbuf imbufLen string def
- }if
- 1 1 Height MultipleDataSources not{Decode length 2 idiv mul}if{
- pop
- MultipleDataSources{
- 0 1 DataSource length 1 sub{
- DataSource type dup
- /arraytype eq{
- pop DataSource exch gx
- }{
- /filetype eq{
- DataSource exch get imbuf readstring pop
- }{
- DataSource exch get
- }ifelse
- }ifelse
- AGMUTIL_imagefile exch writestring
- }for
- }{
- DataSource type dup
- /arraytype eq{
- pop DataSource exec
- }{
- /filetype eq{
- DataSource imbuf readstring pop
- }{
- DataSource
- }ifelse
- }ifelse
- AGMUTIL_imagefile exch writestring
- }ifelse
- }for
- end
- true
- }ifelse
- end
-}bdf
-/close_image_file
-{
- AGMUTIL_imagefile closefile(AGMUTIL_imagefile)deletefile
-}def
-statusdict/product known userdict/AGMP_current_show known not and{
- /pstr statusdict/product get def
- pstr(HP LaserJet 2200)eq
- pstr(HP LaserJet 4000 Series)eq or
- pstr(HP LaserJet 4050 Series )eq or
- pstr(HP LaserJet 8000 Series)eq or
- pstr(HP LaserJet 8100 Series)eq or
- pstr(HP LaserJet 8150 Series)eq or
- pstr(HP LaserJet 5000 Series)eq or
- pstr(HP LaserJet 5100 Series)eq or
- pstr(HP Color LaserJet 4500)eq or
- pstr(HP Color LaserJet 4600)eq or
- pstr(HP LaserJet 5Si)eq or
- pstr(HP LaserJet 1200 Series)eq or
- pstr(HP LaserJet 1300 Series)eq or
- pstr(HP LaserJet 4100 Series)eq or
- {
- userdict/AGMP_current_show/show load put
- userdict/show{
- currentcolorspace 0 get
- /Pattern eq
- {false charpath f}
- {AGMP_current_show}ifelse
- }put
- }if
- currentdict/pstr undef
-}if
-/consumeimagedata
-{
- begin
- AGMIMG_init_common
- currentdict/MultipleDataSources known not
- {/MultipleDataSources false def}if
- MultipleDataSources
- {
- DataSource 0 get type
- dup/filetype eq
- {
- 1 dict begin
- /flushbuffer Width cvi string def
- 1 1 Height cvi
- {
- pop
- 0 1 DataSource length 1 sub
- {
- DataSource exch get
- flushbuffer readstring pop pop
- }for
- }for
- end
- }if
- dup/arraytype eq exch/packedarraytype eq or DataSource 0 get xcheck and
- {
- Width Height mul cvi
- {
- 0 1 DataSource length 1 sub
- {dup DataSource exch gx length exch 0 ne{pop}if}for
- dup 0 eq
- {pop exit}if
- sub dup 0 le
- {exit}if
- }loop
- pop
- }if
- }
- {
- /DataSource load type
- dup/filetype eq
- {
- 1 dict begin
- /flushbuffer Width Decode length 2 idiv mul cvi string def
- 1 1 Height{pop DataSource flushbuffer readstring pop pop}for
- end
- }if
- dup/arraytype eq exch/packedarraytype eq or/DataSource load xcheck and
- {
- Height Width BitsPerComponent mul 8 BitsPerComponent sub add 8 idiv Decode length 2 idiv mul mul
- {
- DataSource length dup 0 eq
- {pop exit}if
- sub dup 0 le
- {exit}if
- }loop
- pop
- }if
- }ifelse
- end
-}bdf
-/addprocs
-{
- 2{/exec load}repeat
- 3 1 roll
- [5 1 roll]bind cvx
-}def
-/modify_halftone_xfer
-{
- currenthalftone dup length dict copy begin
- currentdict 2 index known{
- 1 index load dup length dict copy begin
- currentdict/TransferFunction known{
- /TransferFunction load
- }{
- currenttransfer
- }ifelse
- addprocs/TransferFunction xdf
- currentdict end def
- currentdict end sethalftone
- }{
- currentdict/TransferFunction known{
- /TransferFunction load
- }{
- currenttransfer
- }ifelse
- addprocs/TransferFunction xdf
- currentdict end sethalftone
- pop
- }ifelse
-}def
-/clonearray
-{
- dup xcheck exch
- dup length array exch
- Adobe_AGM_Core/AGMCORE_tmp -1 ddf
- {
- Adobe_AGM_Core/AGMCORE_tmp 2 copy get 1 add ddf
- dup type/dicttype eq
- {
- Adobe_AGM_Core/AGMCORE_tmp get
- exch
- clonedict
- Adobe_AGM_Core/AGMCORE_tmp 4 -1 roll ddf
- }if
- dup type/arraytype eq
- {
- Adobe_AGM_Core/AGMCORE_tmp get exch
- clonearray
- Adobe_AGM_Core/AGMCORE_tmp 4 -1 roll ddf
- }if
- exch dup
- Adobe_AGM_Core/AGMCORE_tmp get 4 -1 roll put
- }forall
- exch{cvx}if
-}bdf
-/clonedict
-{
- dup length dict
- begin
- {
- dup type/dicttype eq
- {clonedict}if
- dup type/arraytype eq
- {clonearray}if
- def
- }forall
- currentdict
- end
-}bdf
-/DeviceN_PS2
-{
- /currentcolorspace AGMCORE_gget 0 get/DeviceN eq level3 not and
-}bdf
-/Indexed_DeviceN
-{
- /indexed_colorspace_dict AGMCORE_gget dup null ne{
- dup/CSDBase known{
- /CSDBase get/CSD get_res/Names known
- }{
- pop false
- }ifelse
- }{
- pop false
- }ifelse
-}bdf
-/DeviceN_NoneName
-{
- /Names where{
- pop
- false Names
- {
- (None)eq or
- }forall
- }{
- false
- }ifelse
-}bdf
-/DeviceN_PS2_inRip_seps
-{
- /AGMCORE_in_rip_sep where
- {
- pop dup type dup/arraytype eq exch/packedarraytype eq or
- {
- dup 0 get/DeviceN eq level3 not and AGMCORE_in_rip_sep and
- {
- /currentcolorspace exch AGMCORE_gput
- false
- }{
- true
- }ifelse
- }{
- true
- }ifelse
- }{
- true
- }ifelse
-}bdf
-/base_colorspace_type
-{
- dup type/arraytype eq{0 get}if
-}bdf
-/currentdistillerparams where{pop currentdistillerparams/CoreDistVersion get 5000 lt}{true}ifelse
-{
- /pdfmark_5{cleartomark}bind def
-}{
- /pdfmark_5{pdfmark}bind def
-}ifelse
-/ReadBypdfmark_5
-{
- currentfile exch 0 exch/SubFileDecode filter
- /currentdistillerparams where
- {pop currentdistillerparams/CoreDistVersion get 5000 lt}{true}ifelse
- {flushfile cleartomark}
- {/PUT pdfmark}ifelse
-}bdf
-/xpdfm
-{
- {
- dup 0 get/Label eq
- {
- aload length[exch 1 add 1 roll/PAGELABEL
- }{
- aload pop
- [{ThisPage}<<5 -2 roll>>/PUT
- }ifelse
- pdfmark_5
- }forall
-}bdf
-/ds{
- Adobe_AGM_Utils begin
-}bdf
-/dt{
- currentdict Adobe_AGM_Utils eq{
- end
- }if
-}bdf
-systemdict/setpacking known
-{setpacking}if
-%%EndResource
-%%BeginResource: procset Adobe_AGM_Core 2.0 0
-%%Version: 2.0 0
-%%Copyright: Copyright(C)1997-2007 Adobe Systems, Inc. All Rights Reserved.
-systemdict/setpacking known
-{
- currentpacking
- true setpacking
-}if
-userdict/Adobe_AGM_Core 209 dict dup begin put
-/Adobe_AGM_Core_Id/Adobe_AGM_Core_2.0_0 def
-/AGMCORE_str256 256 string def
-/AGMCORE_save nd
-/AGMCORE_graphicsave nd
-/AGMCORE_c 0 def
-/AGMCORE_m 0 def
-/AGMCORE_y 0 def
-/AGMCORE_k 0 def
-/AGMCORE_cmykbuf 4 array def
-/AGMCORE_screen[currentscreen]cvx def
-/AGMCORE_tmp 0 def
-/AGMCORE_&setgray nd
-/AGMCORE_&setcolor nd
-/AGMCORE_&setcolorspace nd
-/AGMCORE_&setcmykcolor nd
-/AGMCORE_cyan_plate nd
-/AGMCORE_magenta_plate nd
-/AGMCORE_yellow_plate nd
-/AGMCORE_black_plate nd
-/AGMCORE_plate_ndx nd
-/AGMCORE_get_ink_data nd
-/AGMCORE_is_cmyk_sep nd
-/AGMCORE_host_sep nd
-/AGMCORE_avoid_L2_sep_space nd
-/AGMCORE_distilling nd
-/AGMCORE_composite_job nd
-/AGMCORE_producing_seps nd
-/AGMCORE_ps_level -1 def
-/AGMCORE_ps_version -1 def
-/AGMCORE_environ_ok nd
-/AGMCORE_CSD_cache 0 dict def
-/AGMCORE_currentoverprint false def
-/AGMCORE_deltaX nd
-/AGMCORE_deltaY nd
-/AGMCORE_name nd
-/AGMCORE_sep_special nd
-/AGMCORE_err_strings 4 dict def
-/AGMCORE_cur_err nd
-/AGMCORE_current_spot_alias false def
-/AGMCORE_inverting false def
-/AGMCORE_feature_dictCount nd
-/AGMCORE_feature_opCount nd
-/AGMCORE_feature_ctm nd
-/AGMCORE_ConvertToProcess false def
-/AGMCORE_Default_CTM matrix def
-/AGMCORE_Default_PageSize nd
-/AGMCORE_Default_flatness nd
-/AGMCORE_currentbg nd
-/AGMCORE_currentucr nd
-/AGMCORE_pattern_paint_type 0 def
-/knockout_unitsq nd
-currentglobal true setglobal
-[/CSA/Gradient/Procedure]
-{
- /Generic/Category findresource dup length dict copy/Category defineresource pop
-}forall
-setglobal
-/AGMCORE_key_known
-{
- where{
- /Adobe_AGM_Core_Id known
- }{
- false
- }ifelse
-}ndf
-/flushinput
-{
- save
- 2 dict begin
- /CompareBuffer 3 -1 roll def
- /readbuffer 256 string def
- mark
- {
- currentfile readbuffer{readline}stopped
- {cleartomark mark}
- {
- not
- {pop exit}
- if
- CompareBuffer eq
- {exit}
- if
- }ifelse
- }loop
- cleartomark
- end
- restore
-}bdf
-/getspotfunction
-{
- AGMCORE_screen exch pop exch pop
- dup type/dicttype eq{
- dup/HalftoneType get 1 eq{
- /SpotFunction get
- }{
- dup/HalftoneType get 2 eq{
- /GraySpotFunction get
- }{
- pop
- {
- abs exch abs 2 copy add 1 gt{
- 1 sub dup mul exch 1 sub dup mul add 1 sub
- }{
- dup mul exch dup mul add 1 exch sub
- }ifelse
- }bind
- }ifelse
- }ifelse
- }if
-}def
-/np
-{newpath}bdf
-/clp_npth
-{clip np}def
-/eoclp_npth
-{eoclip np}def
-/npth_clp
-{np clip}def
-/graphic_setup
-{
- /AGMCORE_graphicsave save store
- concat
- 0 setgray
- 0 setlinecap
- 0 setlinejoin
- 1 setlinewidth
- []0 setdash
- 10 setmiterlimit
- np
- false setoverprint
- false setstrokeadjust
- //Adobe_AGM_Core/spot_alias gx
- /Adobe_AGM_Image where{
- pop
- Adobe_AGM_Image/spot_alias 2 copy known{
- gx
- }{
- pop pop
- }ifelse
- }if
- /sep_colorspace_dict null AGMCORE_gput
- 100 dict begin
- /dictstackcount countdictstack def
- /showpage{}def
- mark
-}def
-/graphic_cleanup
-{
- cleartomark
- dictstackcount 1 countdictstack 1 sub{end}for
- end
- AGMCORE_graphicsave restore
-}def
-/compose_error_msg
-{
- grestoreall initgraphics
- /Helvetica findfont 10 scalefont setfont
- /AGMCORE_deltaY 100 def
- /AGMCORE_deltaX 310 def
- clippath pathbbox np pop pop 36 add exch 36 add exch moveto
- 0 AGMCORE_deltaY rlineto AGMCORE_deltaX 0 rlineto
- 0 AGMCORE_deltaY neg rlineto AGMCORE_deltaX neg 0 rlineto closepath
- 0 AGMCORE_&setgray
- gsave 1 AGMCORE_&setgray fill grestore
- 1 setlinewidth gsave stroke grestore
- currentpoint AGMCORE_deltaY 15 sub add exch 8 add exch moveto
- /AGMCORE_deltaY 12 def
- /AGMCORE_tmp 0 def
- AGMCORE_err_strings exch get
- {
- dup 32 eq
- {
- pop
- AGMCORE_str256 0 AGMCORE_tmp getinterval
- stringwidth pop currentpoint pop add AGMCORE_deltaX 28 add gt
- {
- currentpoint AGMCORE_deltaY sub exch pop
- clippath pathbbox pop pop pop 44 add exch moveto
- }if
- AGMCORE_str256 0 AGMCORE_tmp getinterval show( )show
- 0 1 AGMCORE_str256 length 1 sub
- {
- AGMCORE_str256 exch 0 put
- }for
- /AGMCORE_tmp 0 def
- }{
- AGMCORE_str256 exch AGMCORE_tmp xpt
- /AGMCORE_tmp AGMCORE_tmp 1 add def
- }ifelse
- }forall
-}bdf
-/AGMCORE_CMYKDeviceNColorspaces[
- [/Separation/None/DeviceCMYK{0 0 0}]
- [/Separation(Black)/DeviceCMYK{0 0 0 4 -1 roll}bind]
- [/Separation(Yellow)/DeviceCMYK{0 0 3 -1 roll 0}bind]
- [/DeviceN[(Yellow)(Black)]/DeviceCMYK{0 0 4 2 roll}bind]
- [/Separation(Magenta)/DeviceCMYK{0 exch 0 0}bind]
- [/DeviceN[(Magenta)(Black)]/DeviceCMYK{0 3 1 roll 0 exch}bind]
- [/DeviceN[(Magenta)(Yellow)]/DeviceCMYK{0 3 1 roll 0}bind]
- [/DeviceN[(Magenta)(Yellow)(Black)]/DeviceCMYK{0 4 1 roll}bind]
- [/Separation(Cyan)/DeviceCMYK{0 0 0}]
- [/DeviceN[(Cyan)(Black)]/DeviceCMYK{0 0 3 -1 roll}bind]
- [/DeviceN[(Cyan)(Yellow)]/DeviceCMYK{0 exch 0}bind]
- [/DeviceN[(Cyan)(Yellow)(Black)]/DeviceCMYK{0 3 1 roll}bind]
- [/DeviceN[(Cyan)(Magenta)]/DeviceCMYK{0 0}]
- [/DeviceN[(Cyan)(Magenta)(Black)]/DeviceCMYK{0 exch}bind]
- [/DeviceN[(Cyan)(Magenta)(Yellow)]/DeviceCMYK{0}]
- [/DeviceCMYK]
-]def
-/ds{
- Adobe_AGM_Core begin
- /currentdistillerparams where
- {
- pop currentdistillerparams/CoreDistVersion get 5000 lt
- {<</DetectBlends false>>setdistillerparams}if
- }if
- /AGMCORE_ps_version xdf
- /AGMCORE_ps_level xdf
- errordict/AGM_handleerror known not{
- errordict/AGM_handleerror errordict/handleerror get put
- errordict/handleerror{
- Adobe_AGM_Core begin
- $error/newerror get AGMCORE_cur_err null ne and{
- $error/newerror false put
- AGMCORE_cur_err compose_error_msg
- }if
- $error/newerror true put
- end
- errordict/AGM_handleerror get exec
- }bind put
- }if
- /AGMCORE_environ_ok
- ps_level AGMCORE_ps_level ge
- ps_version AGMCORE_ps_version ge and
- AGMCORE_ps_level -1 eq or
- def
- AGMCORE_environ_ok not
- {/AGMCORE_cur_err/AGMCORE_bad_environ def}if
- /AGMCORE_&setgray systemdict/setgray get def
- level2{
- /AGMCORE_&setcolor systemdict/setcolor get def
- /AGMCORE_&setcolorspace systemdict/setcolorspace get def
- }if
- /AGMCORE_currentbg currentblackgeneration def
- /AGMCORE_currentucr currentundercolorremoval def
- /AGMCORE_Default_flatness currentflat def
- /AGMCORE_distilling
- /product where{
- pop systemdict/setdistillerparams known product(Adobe PostScript Parser)ne and
- }{
- false
- }ifelse
- def
- /AGMCORE_GSTATE AGMCORE_key_known not{
- /AGMCORE_GSTATE 21 dict def
- /AGMCORE_tmpmatrix matrix def
- /AGMCORE_gstack 32 array def
- /AGMCORE_gstackptr 0 def
- /AGMCORE_gstacksaveptr 0 def
- /AGMCORE_gstackframekeys 14 def
- /AGMCORE_&gsave/gsave ldf
- /AGMCORE_&grestore/grestore ldf
- /AGMCORE_&grestoreall/grestoreall ldf
- /AGMCORE_&save/save ldf
- /AGMCORE_&setoverprint/setoverprint ldf
- /AGMCORE_gdictcopy{
- begin
- {def}forall
- end
- }def
- /AGMCORE_gput{
- AGMCORE_gstack AGMCORE_gstackptr get
- 3 1 roll
- put
- }def
- /AGMCORE_gget{
- AGMCORE_gstack AGMCORE_gstackptr get
- exch
- get
- }def
- /gsave{
- AGMCORE_&gsave
- AGMCORE_gstack AGMCORE_gstackptr get
- AGMCORE_gstackptr 1 add
- dup 32 ge{limitcheck}if
- /AGMCORE_gstackptr exch store
- AGMCORE_gstack AGMCORE_gstackptr get
- AGMCORE_gdictcopy
- }def
- /grestore{
- AGMCORE_&grestore
- AGMCORE_gstackptr 1 sub
- dup AGMCORE_gstacksaveptr lt{1 add}if
- dup AGMCORE_gstack exch get dup/AGMCORE_currentoverprint known
- {/AGMCORE_currentoverprint get setoverprint}{pop}ifelse
- /AGMCORE_gstackptr exch store
- }def
- /grestoreall{
- AGMCORE_&grestoreall
- /AGMCORE_gstackptr AGMCORE_gstacksaveptr store
- }def
- /save{
- AGMCORE_&save
- AGMCORE_gstack AGMCORE_gstackptr get
- AGMCORE_gstackptr 1 add
- dup 32 ge{limitcheck}if
- /AGMCORE_gstackptr exch store
- /AGMCORE_gstacksaveptr AGMCORE_gstackptr store
- AGMCORE_gstack AGMCORE_gstackptr get
- AGMCORE_gdictcopy
- }def
- /setoverprint{
- dup/AGMCORE_currentoverprint exch AGMCORE_gput AGMCORE_&setoverprint
- }def
- 0 1 AGMCORE_gstack length 1 sub{
- AGMCORE_gstack exch AGMCORE_gstackframekeys dict put
- }for
- }if
- level3/AGMCORE_&sysshfill AGMCORE_key_known not and
- {
- /AGMCORE_&sysshfill systemdict/shfill get def
- /AGMCORE_&sysmakepattern systemdict/makepattern get def
- /AGMCORE_&usrmakepattern/makepattern load def
- }if
- /currentcmykcolor[0 0 0 0]AGMCORE_gput
- /currentstrokeadjust false AGMCORE_gput
- /currentcolorspace[/DeviceGray]AGMCORE_gput
- /sep_tint 0 AGMCORE_gput
- /devicen_tints[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]AGMCORE_gput
- /sep_colorspace_dict null AGMCORE_gput
- /devicen_colorspace_dict null AGMCORE_gput
- /indexed_colorspace_dict null AGMCORE_gput
- /currentcolor_intent()AGMCORE_gput
- /customcolor_tint 1 AGMCORE_gput
- /absolute_colorimetric_crd null AGMCORE_gput
- /relative_colorimetric_crd null AGMCORE_gput
- /saturation_crd null AGMCORE_gput
- /perceptual_crd null AGMCORE_gput
- currentcolortransfer cvlit/AGMCore_gray_xfer xdf cvlit/AGMCore_b_xfer xdf
- cvlit/AGMCore_g_xfer xdf cvlit/AGMCore_r_xfer xdf
- <<
- /MaxPatternItem currentsystemparams/MaxPatternCache get
- >>
- setuserparams
- end
-}def
-/ps
-{
- /setcmykcolor where{
- pop
- Adobe_AGM_Core/AGMCORE_&setcmykcolor/setcmykcolor load put
- }if
- Adobe_AGM_Core begin
- /setcmykcolor
- {
- 4 copy AGMCORE_cmykbuf astore/currentcmykcolor exch AGMCORE_gput
- 1 sub 4 1 roll
- 3{
- 3 index add neg dup 0 lt{
- pop 0
- }if
- 3 1 roll
- }repeat
- setrgbcolor pop
- }ndf
- /currentcmykcolor
- {
- /currentcmykcolor AGMCORE_gget aload pop
- }ndf
- /setoverprint
- {pop}ndf
- /currentoverprint
- {false}ndf
- /AGMCORE_cyan_plate 1 0 0 0 test_cmyk_color_plate def
- /AGMCORE_magenta_plate 0 1 0 0 test_cmyk_color_plate def
- /AGMCORE_yellow_plate 0 0 1 0 test_cmyk_color_plate def
- /AGMCORE_black_plate 0 0 0 1 test_cmyk_color_plate def
- /AGMCORE_plate_ndx
- AGMCORE_cyan_plate{
- 0
- }{
- AGMCORE_magenta_plate{
- 1
- }{
- AGMCORE_yellow_plate{
- 2
- }{
- AGMCORE_black_plate{
- 3
- }{
- 4
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- def
- /AGMCORE_have_reported_unsupported_color_space false def
- /AGMCORE_report_unsupported_color_space
- {
- AGMCORE_have_reported_unsupported_color_space false eq
- {
- (Warning: Job contains content that cannot be separated with on-host methods. This content appears on the black plate, and knocks out all other plates.)==
- Adobe_AGM_Core/AGMCORE_have_reported_unsupported_color_space true ddf
- }if
- }def
- /AGMCORE_composite_job
- AGMCORE_cyan_plate AGMCORE_magenta_plate and AGMCORE_yellow_plate and AGMCORE_black_plate and def
- /AGMCORE_in_rip_sep
- /AGMCORE_in_rip_sep where{
- pop AGMCORE_in_rip_sep
- }{
- AGMCORE_distilling
- {
- false
- }{
- userdict/Adobe_AGM_OnHost_Seps known{
- false
- }{
- level2{
- currentpagedevice/Separations 2 copy known{
- get
- }{
- pop pop false
- }ifelse
- }{
- false
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- def
- /AGMCORE_producing_seps AGMCORE_composite_job not AGMCORE_in_rip_sep or def
- /AGMCORE_host_sep AGMCORE_producing_seps AGMCORE_in_rip_sep not and def
- /AGM_preserve_spots
- /AGM_preserve_spots where{
- pop AGM_preserve_spots
- }{
- AGMCORE_distilling AGMCORE_producing_seps or
- }ifelse
- def
- /AGM_is_distiller_preserving_spotimages
- {
- currentdistillerparams/PreserveOverprintSettings known
- {
- currentdistillerparams/PreserveOverprintSettings get
- {
- currentdistillerparams/ColorConversionStrategy known
- {
- currentdistillerparams/ColorConversionStrategy get
- /sRGB ne
- }{
- true
- }ifelse
- }{
- false
- }ifelse
- }{
- false
- }ifelse
- }def
- /convert_spot_to_process where{pop}{
- /convert_spot_to_process
- {
- //Adobe_AGM_Core begin
- dup map_alias{
- /Name get exch pop
- }if
- dup dup(None)eq exch(All)eq or
- {
- pop false
- }{
- AGMCORE_host_sep
- {
- gsave
- 1 0 0 0 setcmykcolor currentgray 1 exch sub
- 0 1 0 0 setcmykcolor currentgray 1 exch sub
- 0 0 1 0 setcmykcolor currentgray 1 exch sub
- 0 0 0 1 setcmykcolor currentgray 1 exch sub
- add add add 0 eq
- {
- pop false
- }{
- false setoverprint
- current_spot_alias false set_spot_alias
- 1 1 1 1 6 -1 roll findcmykcustomcolor 1 setcustomcolor
- set_spot_alias
- currentgray 1 ne
- }ifelse
- grestore
- }{
- AGMCORE_distilling
- {
- pop AGM_is_distiller_preserving_spotimages not
- }{
- //Adobe_AGM_Core/AGMCORE_name xddf
- false
- //Adobe_AGM_Core/AGMCORE_pattern_paint_type get 0 eq
- AGMUTIL_cpd/OverrideSeparations known and
- {
- AGMUTIL_cpd/OverrideSeparations get
- {
- /HqnSpots/ProcSet resourcestatus
- {
- pop pop pop true
- }if
- }if
- }if
- {
- AGMCORE_name/HqnSpots/ProcSet findresource/TestSpot gx not
- }{
- gsave
- [/Separation AGMCORE_name/DeviceGray{}]AGMCORE_&setcolorspace
- false
- AGMUTIL_cpd/SeparationColorNames 2 copy known
- {
- get
- {AGMCORE_name eq or}forall
- not
- }{
- pop pop pop true
- }ifelse
- grestore
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- end
- }def
- }ifelse
- /convert_to_process where{pop}{
- /convert_to_process
- {
- dup length 0 eq
- {
- pop false
- }{
- AGMCORE_host_sep
- {
- dup true exch
- {
- dup(Cyan)eq exch
- dup(Magenta)eq 3 -1 roll or exch
- dup(Yellow)eq 3 -1 roll or exch
- dup(Black)eq 3 -1 roll or
- {pop}
- {convert_spot_to_process and}ifelse
- }
- forall
- {
- true exch
- {
- dup(Cyan)eq exch
- dup(Magenta)eq 3 -1 roll or exch
- dup(Yellow)eq 3 -1 roll or exch
- (Black)eq or and
- }forall
- not
- }{pop false}ifelse
- }{
- false exch
- {
- /PhotoshopDuotoneList where{pop false}{true}ifelse
- {
- dup(Cyan)eq exch
- dup(Magenta)eq 3 -1 roll or exch
- dup(Yellow)eq 3 -1 roll or exch
- dup(Black)eq 3 -1 roll or
- {pop}
- {convert_spot_to_process or}ifelse
- }
- {
- convert_spot_to_process or
- }
- ifelse
- }
- forall
- }ifelse
- }ifelse
- }def
- }ifelse
- /AGMCORE_avoid_L2_sep_space
- version cvr 2012 lt
- level2 and
- AGMCORE_producing_seps not and
- def
- /AGMCORE_is_cmyk_sep
- AGMCORE_cyan_plate AGMCORE_magenta_plate or AGMCORE_yellow_plate or AGMCORE_black_plate or
- def
- /AGM_avoid_0_cmyk where{
- pop AGM_avoid_0_cmyk
- }{
- AGM_preserve_spots
- userdict/Adobe_AGM_OnHost_Seps known
- userdict/Adobe_AGM_InRip_Seps known or
- not and
- }ifelse
- {
- /setcmykcolor[
- {
- 4 copy add add add 0 eq currentoverprint and{
- pop 0.0005
- }if
- }/exec cvx
- /AGMCORE_&setcmykcolor load dup type/operatortype ne{
- /exec cvx
- }if
- ]cvx def
- }if
- /AGMCORE_IsSeparationAProcessColor
- {
- dup(Cyan)eq exch dup(Magenta)eq exch dup(Yellow)eq exch(Black)eq or or or
- }def
- AGMCORE_host_sep{
- /setcolortransfer
- {
- AGMCORE_cyan_plate{
- pop pop pop
- }{
- AGMCORE_magenta_plate{
- 4 3 roll pop pop pop
- }{
- AGMCORE_yellow_plate{
- 4 2 roll pop pop pop
- }{
- 4 1 roll pop pop pop
- }ifelse
- }ifelse
- }ifelse
- settransfer
- }
- def
- /AGMCORE_get_ink_data
- AGMCORE_cyan_plate{
- {pop pop pop}
- }{
- AGMCORE_magenta_plate{
- {4 3 roll pop pop pop}
- }{
- AGMCORE_yellow_plate{
- {4 2 roll pop pop pop}
- }{
- {4 1 roll pop pop pop}
- }ifelse
- }ifelse
- }ifelse
- def
- /AGMCORE_RemoveProcessColorNames
- {
- 1 dict begin
- /filtername
- {
- dup/Cyan eq 1 index(Cyan)eq or
- {pop(_cyan_)}if
- dup/Magenta eq 1 index(Magenta)eq or
- {pop(_magenta_)}if
- dup/Yellow eq 1 index(Yellow)eq or
- {pop(_yellow_)}if
- dup/Black eq 1 index(Black)eq or
- {pop(_black_)}if
- }def
- dup type/arraytype eq
- {[exch{filtername}forall]}
- {filtername}ifelse
- end
- }def
- level3{
- /AGMCORE_IsCurrentColor
- {
- dup AGMCORE_IsSeparationAProcessColor
- {
- AGMCORE_plate_ndx 0 eq
- {dup(Cyan)eq exch/Cyan eq or}if
- AGMCORE_plate_ndx 1 eq
- {dup(Magenta)eq exch/Magenta eq or}if
- AGMCORE_plate_ndx 2 eq
- {dup(Yellow)eq exch/Yellow eq or}if
- AGMCORE_plate_ndx 3 eq
- {dup(Black)eq exch/Black eq or}if
- AGMCORE_plate_ndx 4 eq
- {pop false}if
- }{
- gsave
- false setoverprint
- current_spot_alias false set_spot_alias
- 1 1 1 1 6 -1 roll findcmykcustomcolor 1 setcustomcolor
- set_spot_alias
- currentgray 1 ne
- grestore
- }ifelse
- }def
- /AGMCORE_filter_functiondatasource
- {
- 5 dict begin
- /data_in xdf
- data_in type/stringtype eq
- {
- /ncomp xdf
- /comp xdf
- /string_out data_in length ncomp idiv string def
- 0 ncomp data_in length 1 sub
- {
- string_out exch dup ncomp idiv exch data_in exch ncomp getinterval comp get 255 exch sub put
- }for
- string_out
- }{
- string/string_in xdf
- /string_out 1 string def
- /component xdf
- [
- data_in string_in/readstring cvx
- [component/get cvx 255/exch cvx/sub cvx string_out/exch cvx 0/exch cvx/put cvx string_out]cvx
- [/pop cvx()]cvx/ifelse cvx
- ]cvx/ReusableStreamDecode filter
- }ifelse
- end
- }def
- /AGMCORE_separateShadingFunction
- {
- 2 dict begin
- /paint? xdf
- /channel xdf
- dup type/dicttype eq
- {
- begin
- FunctionType 0 eq
- {
- /DataSource channel Range length 2 idiv DataSource AGMCORE_filter_functiondatasource def
- currentdict/Decode known
- {/Decode Decode channel 2 mul 2 getinterval def}if
- paint? not
- {/Decode[1 1]def}if
- }if
- FunctionType 2 eq
- {
- paint?
- {
- /C0[C0 channel get 1 exch sub]def
- /C1[C1 channel get 1 exch sub]def
- }{
- /C0[1]def
- /C1[1]def
- }ifelse
- }if
- FunctionType 3 eq
- {
- /Functions[Functions{channel paint? AGMCORE_separateShadingFunction}forall]def
- }if
- currentdict/Range known
- {/Range[0 1]def}if
- currentdict
- end}{
- channel get 0 paint? AGMCORE_separateShadingFunction
- }ifelse
- end
- }def
- /AGMCORE_separateShading
- {
- 3 -1 roll begin
- currentdict/Function known
- {
- currentdict/Background known
- {[1 index{Background 3 index get 1 exch sub}{1}ifelse]/Background xdf}if
- Function 3 1 roll AGMCORE_separateShadingFunction/Function xdf
- /ColorSpace[/DeviceGray]def
- }{
- ColorSpace dup type/arraytype eq{0 get}if/DeviceCMYK eq
- {
- /ColorSpace[/DeviceN[/_cyan_/_magenta_/_yellow_/_black_]/DeviceCMYK{}]def
- }{
- ColorSpace dup 1 get AGMCORE_RemoveProcessColorNames 1 exch put
- }ifelse
- ColorSpace 0 get/Separation eq
- {
- {
- [1/exch cvx/sub cvx]cvx
- }{
- [/pop cvx 1]cvx
- }ifelse
- ColorSpace 3 3 -1 roll put
- pop
- }{
- {
- [exch ColorSpace 1 get length 1 sub exch sub/index cvx 1/exch cvx/sub cvx ColorSpace 1 get length 1 add 1/roll cvx ColorSpace 1 get length{/pop cvx}repeat]cvx
- }{
- pop[ColorSpace 1 get length{/pop cvx}repeat cvx 1]cvx
- }ifelse
- ColorSpace 3 3 -1 roll bind put
- }ifelse
- ColorSpace 2/DeviceGray put
- }ifelse
- end
- }def
- /AGMCORE_separateShadingDict
- {
- dup/ColorSpace get
- dup type/arraytype ne
- {[exch]}if
- dup 0 get/DeviceCMYK eq
- {
- exch begin
- currentdict
- AGMCORE_cyan_plate
- {0 true}if
- AGMCORE_magenta_plate
- {1 true}if
- AGMCORE_yellow_plate
- {2 true}if
- AGMCORE_black_plate
- {3 true}if
- AGMCORE_plate_ndx 4 eq
- {0 false}if
- dup not currentoverprint and
- {/AGMCORE_ignoreshade true def}if
- AGMCORE_separateShading
- currentdict
- end exch
- }if
- dup 0 get/Separation eq
- {
- exch begin
- ColorSpace 1 get dup/None ne exch/All ne and
- {
- ColorSpace 1 get AGMCORE_IsCurrentColor AGMCORE_plate_ndx 4 lt and ColorSpace 1 get AGMCORE_IsSeparationAProcessColor not and
- {
- ColorSpace 2 get dup type/arraytype eq{0 get}if/DeviceCMYK eq
- {
- /ColorSpace
- [
- /Separation
- ColorSpace 1 get
- /DeviceGray
- [
- ColorSpace 3 get/exec cvx
- 4 AGMCORE_plate_ndx sub -1/roll cvx
- 4 1/roll cvx
- 3[/pop cvx]cvx/repeat cvx
- 1/exch cvx/sub cvx
- ]cvx
- ]def
- }{
- AGMCORE_report_unsupported_color_space
- AGMCORE_black_plate not
- {
- currentdict 0 false AGMCORE_separateShading
- }if
- }ifelse
- }{
- currentdict ColorSpace 1 get AGMCORE_IsCurrentColor
- 0 exch
- dup not currentoverprint and
- {/AGMCORE_ignoreshade true def}if
- AGMCORE_separateShading
- }ifelse
- }if
- currentdict
- end exch
- }if
- dup 0 get/DeviceN eq
- {
- exch begin
- ColorSpace 1 get convert_to_process
- {
- ColorSpace 2 get dup type/arraytype eq{0 get}if/DeviceCMYK eq
- {
- /ColorSpace
- [
- /DeviceN
- ColorSpace 1 get
- /DeviceGray
- [
- ColorSpace 3 get/exec cvx
- 4 AGMCORE_plate_ndx sub -1/roll cvx
- 4 1/roll cvx
- 3[/pop cvx]cvx/repeat cvx
- 1/exch cvx/sub cvx
- ]cvx
- ]def
- }{
- AGMCORE_report_unsupported_color_space
- AGMCORE_black_plate not
- {
- currentdict 0 false AGMCORE_separateShading
- /ColorSpace[/DeviceGray]def
- }if
- }ifelse
- }{
- currentdict
- false -1 ColorSpace 1 get
- {
- AGMCORE_IsCurrentColor
- {
- 1 add
- exch pop true exch exit
- }if
- 1 add
- }forall
- exch
- dup not currentoverprint and
- {/AGMCORE_ignoreshade true def}if
- AGMCORE_separateShading
- }ifelse
- currentdict
- end exch
- }if
- dup 0 get dup/DeviceCMYK eq exch dup/Separation eq exch/DeviceN eq or or not
- {
- exch begin
- ColorSpace dup type/arraytype eq
- {0 get}if
- /DeviceGray ne
- {
- AGMCORE_report_unsupported_color_space
- AGMCORE_black_plate not
- {
- ColorSpace 0 get/CIEBasedA eq
- {
- /ColorSpace[/Separation/_ciebaseda_/DeviceGray{}]def
- }if
- ColorSpace 0 get dup/CIEBasedABC eq exch dup/CIEBasedDEF eq exch/DeviceRGB eq or or
- {
- /ColorSpace[/DeviceN[/_red_/_green_/_blue_]/DeviceRGB{}]def
- }if
- ColorSpace 0 get/CIEBasedDEFG eq
- {
- /ColorSpace[/DeviceN[/_cyan_/_magenta_/_yellow_/_black_]/DeviceCMYK{}]def
- }if
- currentdict 0 false AGMCORE_separateShading
- }if
- }if
- currentdict
- end exch
- }if
- pop
- dup/AGMCORE_ignoreshade known
- {
- begin
- /ColorSpace[/Separation(None)/DeviceGray{}]def
- currentdict end
- }if
- }def
- /shfill
- {
- AGMCORE_separateShadingDict
- dup/AGMCORE_ignoreshade known
- {pop}
- {AGMCORE_&sysshfill}ifelse
- }def
- /makepattern
- {
- exch
- dup/PatternType get 2 eq
- {
- clonedict
- begin
- /Shading Shading AGMCORE_separateShadingDict def
- Shading/AGMCORE_ignoreshade known
- currentdict end exch
- {pop<</PatternType 1/PaintProc{pop}/BBox[0 0 1 1]/XStep 1/YStep 1/PaintType 1/TilingType 3>>}if
- exch AGMCORE_&sysmakepattern
- }{
- exch AGMCORE_&usrmakepattern
- }ifelse
- }def
- }if
- }if
- AGMCORE_in_rip_sep{
- /setcustomcolor
- {
- exch aload pop
- dup 7 1 roll inRip_spot_has_ink not {
- 4{4 index mul 4 1 roll}
- repeat
- /DeviceCMYK setcolorspace
- 6 -2 roll pop pop
- }{
- //Adobe_AGM_Core begin
- /AGMCORE_k xdf/AGMCORE_y xdf/AGMCORE_m xdf/AGMCORE_c xdf
- end
- [/Separation 4 -1 roll/DeviceCMYK
- {dup AGMCORE_c mul exch dup AGMCORE_m mul exch dup AGMCORE_y mul exch AGMCORE_k mul}
- ]
- setcolorspace
- }ifelse
- setcolor
- }ndf
- /setseparationgray
- {
- [/Separation(All)/DeviceGray{}]setcolorspace_opt
- 1 exch sub setcolor
- }ndf
- }{
- /setseparationgray
- {
- AGMCORE_&setgray
- }ndf
- }ifelse
- /findcmykcustomcolor
- {
- 5 makereadonlyarray
- }ndf
- /setcustomcolor
- {
- exch aload pop pop
- 4{4 index mul 4 1 roll}repeat
- setcmykcolor pop
- }ndf
- /has_color
- /colorimage where{
- AGMCORE_producing_seps{
- pop true
- }{
- systemdict eq
- }ifelse
- }{
- false
- }ifelse
- def
- /map_index
- {
- 1 index mul exch getinterval{255 div}forall
- }bdf
- /map_indexed_devn
- {
- Lookup Names length 3 -1 roll cvi map_index
- }bdf
- /n_color_components
- {
- base_colorspace_type
- dup/DeviceGray eq{
- pop 1
- }{
- /DeviceCMYK eq{
- 4
- }{
- 3
- }ifelse
- }ifelse
- }bdf
- level2{
- /mo/moveto ldf
- /li/lineto ldf
- /cv/curveto ldf
- /knockout_unitsq
- {
- 1 setgray
- 0 0 1 1 rectfill
- }def
- level2/setcolorspace AGMCORE_key_known not and{
- /AGMCORE_&&&setcolorspace/setcolorspace ldf
- /AGMCORE_ReplaceMappedColor
- {
- dup type dup/arraytype eq exch/packedarraytype eq or
- {
- /AGMCORE_SpotAliasAry2 where{
- begin
- dup 0 get dup/Separation eq
- {
- pop
- dup length array copy
- dup dup 1 get
- current_spot_alias
- {
- dup map_alias
- {
- false set_spot_alias
- dup 1 exch setsepcolorspace
- true set_spot_alias
- begin
- /sep_colorspace_dict currentdict AGMCORE_gput
- pop pop pop
- [
- /Separation Name
- CSA map_csa
- MappedCSA
- /sep_colorspace_proc load
- ]
- dup Name
- end
- }if
- }if
- map_reserved_ink_name 1 xpt
- }{
- /DeviceN eq
- {
- dup length array copy
- dup dup 1 get[
- exch{
- current_spot_alias{
- dup map_alias{
- /Name get exch pop
- }if
- }if
- map_reserved_ink_name
- }forall
- ]1 xpt
- }if
- }ifelse
- end
- }if
- }if
- }def
- /setcolorspace
- {
- dup type dup/arraytype eq exch/packedarraytype eq or
- {
- dup 0 get/Indexed eq
- {
- AGMCORE_distilling
- {
- /PhotoshopDuotoneList where
- {
- pop false
- }{
- true
- }ifelse
- }{
- true
- }ifelse
- {
- aload pop 3 -1 roll
- AGMCORE_ReplaceMappedColor
- 3 1 roll 4 array astore
- }if
- }{
- AGMCORE_ReplaceMappedColor
- }ifelse
- }if
- DeviceN_PS2_inRip_seps{AGMCORE_&&&setcolorspace}if
- }def
- }if
- }{
- /adj
- {
- currentstrokeadjust{
- transform
- 0.25 sub round 0.25 add exch
- 0.25 sub round 0.25 add exch
- itransform
- }if
- }def
- /mo{
- adj moveto
- }def
- /li{
- adj lineto
- }def
- /cv{
- 6 2 roll adj
- 6 2 roll adj
- 6 2 roll adj curveto
- }def
- /knockout_unitsq
- {
- 1 setgray
- 8 8 1[8 0 0 8 0 0]{<ffffffffffffffff>}image
- }def
- /currentstrokeadjust{
- /currentstrokeadjust AGMCORE_gget
- }def
- /setstrokeadjust{
- /currentstrokeadjust exch AGMCORE_gput
- }def
- /setcolorspace
- {
- /currentcolorspace exch AGMCORE_gput
- }def
- /currentcolorspace
- {
- /currentcolorspace AGMCORE_gget
- }def
- /setcolor_devicecolor
- {
- base_colorspace_type
- dup/DeviceGray eq{
- pop setgray
- }{
- /DeviceCMYK eq{
- setcmykcolor
- }{
- setrgbcolor
- }ifelse
- }ifelse
- }def
- /setcolor
- {
- currentcolorspace 0 get
- dup/DeviceGray ne{
- dup/DeviceCMYK ne{
- dup/DeviceRGB ne{
- dup/Separation eq{
- pop
- currentcolorspace 3 gx
- currentcolorspace 2 get
- }{
- dup/Indexed eq{
- pop
- currentcolorspace 3 get dup type/stringtype eq{
- currentcolorspace 1 get n_color_components
- 3 -1 roll map_index
- }{
- exec
- }ifelse
- currentcolorspace 1 get
- }{
- /AGMCORE_cur_err/AGMCORE_invalid_color_space def
- AGMCORE_invalid_color_space
- }ifelse
- }ifelse
- }if
- }if
- }if
- setcolor_devicecolor
- }def
- }ifelse
- /sop/setoverprint ldf
- /lw/setlinewidth ldf
- /lc/setlinecap ldf
- /lj/setlinejoin ldf
- /ml/setmiterlimit ldf
- /dsh/setdash ldf
- /sadj/setstrokeadjust ldf
- /gry/setgray ldf
- /rgb/setrgbcolor ldf
- /cmyk[
- /currentcolorspace[/DeviceCMYK]/AGMCORE_gput cvx
- /setcmykcolor load dup type/operatortype ne{/exec cvx}if
- ]cvx bdf
- level3 AGMCORE_host_sep not and{
- /nzopmsc{
- 6 dict begin
- /kk exch def
- /yy exch def
- /mm exch def
- /cc exch def
- /sum 0 def
- cc 0 ne{/sum sum 2#1000 or def cc}if
- mm 0 ne{/sum sum 2#0100 or def mm}if
- yy 0 ne{/sum sum 2#0010 or def yy}if
- kk 0 ne{/sum sum 2#0001 or def kk}if
- AGMCORE_CMYKDeviceNColorspaces sum get setcolorspace
- sum 0 eq{0}if
- end
- setcolor
- }bdf
- }{
- /nzopmsc/cmyk ldf
- }ifelse
- /sep/setsepcolor ldf
- /devn/setdevicencolor ldf
- /idx/setindexedcolor ldf
- /colr/setcolor ldf
- /csacrd/set_csa_crd ldf
- /sepcs/setsepcolorspace ldf
- /devncs/setdevicencolorspace ldf
- /idxcs/setindexedcolorspace ldf
- /cp/closepath ldf
- /clp/clp_npth ldf
- /eclp/eoclp_npth ldf
- /f/fill ldf
- /ef/eofill ldf
- /@/stroke ldf
- /nclp/npth_clp ldf
- /gset/graphic_setup ldf
- /gcln/graphic_cleanup ldf
- /ct/concat ldf
- /cf/currentfile ldf
- /fl/filter ldf
- /rs/readstring ldf
- /AGMCORE_def_ht currenthalftone def
- /clonedict Adobe_AGM_Utils begin/clonedict load end def
- /clonearray Adobe_AGM_Utils begin/clonearray load end def
- currentdict{
- dup xcheck 1 index type dup/arraytype eq exch/packedarraytype eq or and{
- bind
- }if
- def
- }forall
- /getrampcolor
- {
- /indx exch def
- 0 1 NumComp 1 sub
- {
- dup
- Samples exch get
- dup type/stringtype eq{indx get}if
- exch
- Scaling exch get aload pop
- 3 1 roll
- mul add
- }for
- ColorSpaceFamily/Separation eq
- {sep}
- {
- ColorSpaceFamily/DeviceN eq
- {devn}{setcolor}ifelse
- }ifelse
- }bdf
- /sssetbackground{
- aload pop
- ColorSpaceFamily/Separation eq
- {sep}
- {
- ColorSpaceFamily/DeviceN eq
- {devn}{setcolor}ifelse
- }ifelse
- }bdf
- /RadialShade
- {
- 40 dict begin
- /ColorSpaceFamily xdf
- /background xdf
- /ext1 xdf
- /ext0 xdf
- /BBox xdf
- /r2 xdf
- /c2y xdf
- /c2x xdf
- /r1 xdf
- /c1y xdf
- /c1x xdf
- /rampdict xdf
- /setinkoverprint where{pop/setinkoverprint{pop}def}if
- gsave
- BBox length 0 gt
- {
- np
- BBox 0 get BBox 1 get moveto
- BBox 2 get BBox 0 get sub 0 rlineto
- 0 BBox 3 get BBox 1 get sub rlineto
- BBox 2 get BBox 0 get sub neg 0 rlineto
- closepath
- clip
- np
- }if
- c1x c2x eq
- {
- c1y c2y lt{/theta 90 def}{/theta 270 def}ifelse
- }{
- /slope c2y c1y sub c2x c1x sub div def
- /theta slope 1 atan def
- c2x c1x lt c2y c1y ge and{/theta theta 180 sub def}if
- c2x c1x lt c2y c1y lt and{/theta theta 180 add def}if
- }ifelse
- gsave
- clippath
- c1x c1y translate
- theta rotate
- -90 rotate
- {pathbbox}stopped
- {0 0 0 0}if
- /yMax xdf
- /xMax xdf
- /yMin xdf
- /xMin xdf
- grestore
- xMax xMin eq yMax yMin eq or
- {
- grestore
- end
- }{
- /max{2 copy gt{pop}{exch pop}ifelse}bdf
- /min{2 copy lt{pop}{exch pop}ifelse}bdf
- rampdict begin
- 40 dict begin
- background length 0 gt{background sssetbackground gsave clippath fill grestore}if
- gsave
- c1x c1y translate
- theta rotate
- -90 rotate
- /c2y c1x c2x sub dup mul c1y c2y sub dup mul add sqrt def
- /c1y 0 def
- /c1x 0 def
- /c2x 0 def
- ext0
- {
- 0 getrampcolor
- c2y r2 add r1 sub 0.0001 lt
- {
- c1x c1y r1 360 0 arcn
- pathbbox
- /aymax exch def
- /axmax exch def
- /aymin exch def
- /axmin exch def
- /bxMin xMin axmin min def
- /byMin yMin aymin min def
- /bxMax xMax axmax max def
- /byMax yMax aymax max def
- bxMin byMin moveto
- bxMax byMin lineto
- bxMax byMax lineto
- bxMin byMax lineto
- bxMin byMin lineto
- eofill
- }{
- c2y r1 add r2 le
- {
- c1x c1y r1 0 360 arc
- fill
- }
- {
- c2x c2y r2 0 360 arc fill
- r1 r2 eq
- {
- /p1x r1 neg def
- /p1y c1y def
- /p2x r1 def
- /p2y c1y def
- p1x p1y moveto p2x p2y lineto p2x yMin lineto p1x yMin lineto
- fill
- }{
- /AA r2 r1 sub c2y div def
- AA -1 eq
- {/theta 89.99 def}
- {/theta AA 1 AA dup mul sub sqrt div 1 atan def}
- ifelse
- /SS1 90 theta add dup sin exch cos div def
- /p1x r1 SS1 SS1 mul SS1 SS1 mul 1 add div sqrt mul neg def
- /p1y p1x SS1 div neg def
- /SS2 90 theta sub dup sin exch cos div def
- /p2x r1 SS2 SS2 mul SS2 SS2 mul 1 add div sqrt mul def
- /p2y p2x SS2 div neg def
- r1 r2 gt
- {
- /L1maxX p1x yMin p1y sub SS1 div add def
- /L2maxX p2x yMin p2y sub SS2 div add def
- }{
- /L1maxX 0 def
- /L2maxX 0 def
- }ifelse
- p1x p1y moveto p2x p2y lineto L2maxX L2maxX p2x sub SS2 mul p2y add lineto
- L1maxX L1maxX p1x sub SS1 mul p1y add lineto
- fill
- }ifelse
- }ifelse
- }ifelse
- }if
- c1x c2x sub dup mul
- c1y c2y sub dup mul
- add 0.5 exp
- 0 dtransform
- dup mul exch dup mul add 0.5 exp 72 div
- 0 72 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt
- 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt
- 1 index 1 index lt{exch}if pop
- /hires xdf
- hires mul
- /numpix xdf
- /numsteps NumSamples def
- /rampIndxInc 1 def
- /subsampling false def
- numpix 0 ne
- {
- NumSamples numpix div 0.5 gt
- {
- /numsteps numpix 2 div round cvi dup 1 le{pop 2}if def
- /rampIndxInc NumSamples 1 sub numsteps div def
- /subsampling true def
- }if
- }if
- /xInc c2x c1x sub numsteps div def
- /yInc c2y c1y sub numsteps div def
- /rInc r2 r1 sub numsteps div def
- /cx c1x def
- /cy c1y def
- /radius r1 def
- np
- xInc 0 eq yInc 0 eq rInc 0 eq and and
- {
- 0 getrampcolor
- cx cy radius 0 360 arc
- stroke
- NumSamples 1 sub getrampcolor
- cx cy radius 72 hires div add 0 360 arc
- 0 setlinewidth
- stroke
- }{
- 0
- numsteps
- {
- dup
- subsampling{round cvi}if
- getrampcolor
- cx cy radius 0 360 arc
- /cx cx xInc add def
- /cy cy yInc add def
- /radius radius rInc add def
- cx cy radius 360 0 arcn
- eofill
- rampIndxInc add
- }repeat
- pop
- }ifelse
- ext1
- {
- c2y r2 add r1 lt
- {
- c2x c2y r2 0 360 arc
- fill
- }{
- c2y r1 add r2 sub 0.0001 le
- {
- c2x c2y r2 360 0 arcn
- pathbbox
- /aymax exch def
- /axmax exch def
- /aymin exch def
- /axmin exch def
- /bxMin xMin axmin min def
- /byMin yMin aymin min def
- /bxMax xMax axmax max def
- /byMax yMax aymax max def
- bxMin byMin moveto
- bxMax byMin lineto
- bxMax byMax lineto
- bxMin byMax lineto
- bxMin byMin lineto
- eofill
- }{
- c2x c2y r2 0 360 arc fill
- r1 r2 eq
- {
- /p1x r2 neg def
- /p1y c2y def
- /p2x r2 def
- /p2y c2y def
- p1x p1y moveto p2x p2y lineto p2x yMax lineto p1x yMax lineto
- fill
- }{
- /AA r2 r1 sub c2y div def
- AA -1 eq
- {/theta 89.99 def}
- {/theta AA 1 AA dup mul sub sqrt div 1 atan def}
- ifelse
- /SS1 90 theta add dup sin exch cos div def
- /p1x r2 SS1 SS1 mul SS1 SS1 mul 1 add div sqrt mul neg def
- /p1y c2y p1x SS1 div sub def
- /SS2 90 theta sub dup sin exch cos div def
- /p2x r2 SS2 SS2 mul SS2 SS2 mul 1 add div sqrt mul def
- /p2y c2y p2x SS2 div sub def
- r1 r2 lt
- {
- /L1maxX p1x yMax p1y sub SS1 div add def
- /L2maxX p2x yMax p2y sub SS2 div add def
- }{
- /L1maxX 0 def
- /L2maxX 0 def
- }ifelse
- p1x p1y moveto p2x p2y lineto L2maxX L2maxX p2x sub SS2 mul p2y add lineto
- L1maxX L1maxX p1x sub SS1 mul p1y add lineto
- fill
- }ifelse
- }ifelse
- }ifelse
- }if
- grestore
- grestore
- end
- end
- end
- }ifelse
- }bdf
- /GenStrips
- {
- 40 dict begin
- /ColorSpaceFamily xdf
- /background xdf
- /ext1 xdf
- /ext0 xdf
- /BBox xdf
- /y2 xdf
- /x2 xdf
- /y1 xdf
- /x1 xdf
- /rampdict xdf
- /setinkoverprint where{pop/setinkoverprint{pop}def}if
- gsave
- BBox length 0 gt
- {
- np
- BBox 0 get BBox 1 get moveto
- BBox 2 get BBox 0 get sub 0 rlineto
- 0 BBox 3 get BBox 1 get sub rlineto
- BBox 2 get BBox 0 get sub neg 0 rlineto
- closepath
- clip
- np
- }if
- x1 x2 eq
- {
- y1 y2 lt{/theta 90 def}{/theta 270 def}ifelse
- }{
- /slope y2 y1 sub x2 x1 sub div def
- /theta slope 1 atan def
- x2 x1 lt y2 y1 ge and{/theta theta 180 sub def}if
- x2 x1 lt y2 y1 lt and{/theta theta 180 add def}if
- }
- ifelse
- gsave
- clippath
- x1 y1 translate
- theta rotate
- {pathbbox}stopped
- {0 0 0 0}if
- /yMax exch def
- /xMax exch def
- /yMin exch def
- /xMin exch def
- grestore
- xMax xMin eq yMax yMin eq or
- {
- grestore
- end
- }{
- rampdict begin
- 20 dict begin
- background length 0 gt{background sssetbackground gsave clippath fill grestore}if
- gsave
- x1 y1 translate
- theta rotate
- /xStart 0 def
- /xEnd x2 x1 sub dup mul y2 y1 sub dup mul add 0.5 exp def
- /ySpan yMax yMin sub def
- /numsteps NumSamples def
- /rampIndxInc 1 def
- /subsampling false def
- xStart 0 transform
- xEnd 0 transform
- 3 -1 roll
- sub dup mul
- 3 1 roll
- sub dup mul
- add 0.5 exp 72 div
- 0 72 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt
- 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt
- 1 index 1 index lt{exch}if pop
- mul
- /numpix xdf
- numpix 0 ne
- {
- NumSamples numpix div 0.5 gt
- {
- /numsteps numpix 2 div round cvi dup 1 le{pop 2}if def
- /rampIndxInc NumSamples 1 sub numsteps div def
- /subsampling true def
- }if
- }if
- ext0
- {
- 0 getrampcolor
- xMin xStart lt
- {
- xMin yMin xMin neg ySpan rectfill
- }if
- }if
- /xInc xEnd xStart sub numsteps div def
- /x xStart def
- 0
- numsteps
- {
- dup
- subsampling{round cvi}if
- getrampcolor
- x yMin xInc ySpan rectfill
- /x x xInc add def
- rampIndxInc add
- }repeat
- pop
- ext1{
- xMax xEnd gt
- {
- xEnd yMin xMax xEnd sub ySpan rectfill
- }if
- }if
- grestore
- grestore
- end
- end
- end
- }ifelse
- }bdf
-}def
-/pt
-{
- end
-}def
-/dt{
-}def
-/pgsv{
- //Adobe_AGM_Core/AGMCORE_save save put
-}def
-/pgrs{
- //Adobe_AGM_Core/AGMCORE_save get restore
-}def
-systemdict/findcolorrendering known{
- /findcolorrendering systemdict/findcolorrendering get def
-}if
-systemdict/setcolorrendering known{
- /setcolorrendering systemdict/setcolorrendering get def
-}if
-/test_cmyk_color_plate
-{
- gsave
- setcmykcolor currentgray 1 ne
- grestore
-}def
-/inRip_spot_has_ink
-{
- dup//Adobe_AGM_Core/AGMCORE_name xddf
- convert_spot_to_process not
-}def
-/map255_to_range
-{
- 1 index sub
- 3 -1 roll 255 div mul add
-}def
-/set_csa_crd
-{
- /sep_colorspace_dict null AGMCORE_gput
- begin
- CSA get_csa_by_name setcolorspace_opt
- set_crd
- end
-}
-def
-/map_csa
-{
- currentdict/MappedCSA known{MappedCSA null ne}{false}ifelse
- {pop}{get_csa_by_name/MappedCSA xdf}ifelse
-}def
-/setsepcolor
-{
- /sep_colorspace_dict AGMCORE_gget begin
- dup/sep_tint exch AGMCORE_gput
- TintProc
- end
-}def
-/setdevicencolor
-{
- /devicen_colorspace_dict AGMCORE_gget begin
- Names length copy
- Names length 1 sub -1 0
- {
- /devicen_tints AGMCORE_gget 3 1 roll xpt
- }for
- TintProc
- end
-}def
-/sep_colorspace_proc
-{
- /AGMCORE_tmp exch store
- /sep_colorspace_dict AGMCORE_gget begin
- currentdict/Components known{
- Components aload pop
- TintMethod/Lab eq{
- 2{AGMCORE_tmp mul NComponents 1 roll}repeat
- LMax sub AGMCORE_tmp mul LMax add NComponents 1 roll
- }{
- TintMethod/Subtractive eq{
- NComponents{
- AGMCORE_tmp mul NComponents 1 roll
- }repeat
- }{
- NComponents{
- 1 sub AGMCORE_tmp mul 1 add NComponents 1 roll
- }repeat
- }ifelse
- }ifelse
- }{
- ColorLookup AGMCORE_tmp ColorLookup length 1 sub mul round cvi get
- aload pop
- }ifelse
- end
-}def
-/sep_colorspace_gray_proc
-{
- /AGMCORE_tmp exch store
- /sep_colorspace_dict AGMCORE_gget begin
- GrayLookup AGMCORE_tmp GrayLookup length 1 sub mul round cvi get
- end
-}def
-/sep_proc_name
-{
- dup 0 get
- dup/DeviceRGB eq exch/DeviceCMYK eq or level2 not and has_color not and{
- pop[/DeviceGray]
- /sep_colorspace_gray_proc
- }{
- /sep_colorspace_proc
- }ifelse
-}def
-/setsepcolorspace
-{
- current_spot_alias{
- dup begin
- Name map_alias{
- exch pop
- }if
- end
- }if
- dup/sep_colorspace_dict exch AGMCORE_gput
- begin
- CSA map_csa
- /AGMCORE_sep_special Name dup()eq exch(All)eq or store
- AGMCORE_avoid_L2_sep_space{
- [/Indexed MappedCSA sep_proc_name 255 exch
- {255 div}/exec cvx 3 -1 roll[4 1 roll load/exec cvx]cvx
- ]setcolorspace_opt
- /TintProc{
- 255 mul round cvi setcolor
- }bdf
- }{
- MappedCSA 0 get/DeviceCMYK eq
- currentdict/Components known and
- AGMCORE_sep_special not and{
- /TintProc[
- Components aload pop Name findcmykcustomcolor
- /exch cvx/setcustomcolor cvx
- ]cvx bdf
- }{
- AGMCORE_host_sep Name(All)eq and{
- /TintProc{
- 1 exch sub setseparationgray
- }bdf
- }{
- AGMCORE_in_rip_sep MappedCSA 0 get/DeviceCMYK eq and
- AGMCORE_host_sep or
- Name()eq and{
- /TintProc[
- MappedCSA sep_proc_name exch 0 get/DeviceCMYK eq{
- cvx/setcmykcolor cvx
- }{
- cvx/setgray cvx
- }ifelse
- ]cvx bdf
- }{
- AGMCORE_producing_seps MappedCSA 0 get dup/DeviceCMYK eq exch/DeviceGray eq or and AGMCORE_sep_special not and{
- /TintProc[
- /dup cvx
- MappedCSA sep_proc_name cvx exch
- 0 get/DeviceGray eq{
- 1/exch cvx/sub cvx 0 0 0 4 -1/roll cvx
- }if
- /Name cvx/findcmykcustomcolor cvx/exch cvx
- AGMCORE_host_sep{
- AGMCORE_is_cmyk_sep
- /Name cvx
- /AGMCORE_IsSeparationAProcessColor load/exec cvx
- /not cvx/and cvx
- }{
- Name inRip_spot_has_ink not
- }ifelse
- [
- /pop cvx 1
- ]cvx/if cvx
- /setcustomcolor cvx
- ]cvx bdf
- }{
- /TintProc{setcolor}bdf
- [/Separation Name MappedCSA sep_proc_name load]setcolorspace_opt
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- set_crd
- setsepcolor
- end
-}def
-/additive_blend
-{
- 3 dict begin
- /numarrays xdf
- /numcolors xdf
- 0 1 numcolors 1 sub
- {
- /c1 xdf
- 1
- 0 1 numarrays 1 sub
- {
- 1 exch add/index cvx
- c1/get cvx/mul cvx
- }for
- numarrays 1 add 1/roll cvx
- }for
- numarrays[/pop cvx]cvx/repeat cvx
- end
-}def
-/subtractive_blend
-{
- 3 dict begin
- /numarrays xdf
- /numcolors xdf
- 0 1 numcolors 1 sub
- {
- /c1 xdf
- 1 1
- 0 1 numarrays 1 sub
- {
- 1 3 3 -1 roll add/index cvx
- c1/get cvx/sub cvx/mul cvx
- }for
- /sub cvx
- numarrays 1 add 1/roll cvx
- }for
- numarrays[/pop cvx]cvx/repeat cvx
- end
-}def
-/exec_tint_transform
-{
- /TintProc[
- /TintTransform cvx/setcolor cvx
- ]cvx bdf
- MappedCSA setcolorspace_opt
-}bdf
-/devn_makecustomcolor
-{
- 2 dict begin
- /names_index xdf
- /Names xdf
- 1 1 1 1 Names names_index get findcmykcustomcolor
- /devicen_tints AGMCORE_gget names_index get setcustomcolor
- Names length{pop}repeat
- end
-}bdf
-/setdevicencolorspace
-{
- dup/AliasedColorants known{false}{true}ifelse
- current_spot_alias and{
- 7 dict begin
- /names_index 0 def
- dup/names_len exch/Names get length def
- /new_names names_len array def
- /new_LookupTables names_len array def
- /alias_cnt 0 def
- dup/Names get
- {
- dup map_alias{
- exch pop
- dup/ColorLookup known{
- dup begin
- new_LookupTables names_index ColorLookup put
- end
- }{
- dup/Components known{
- dup begin
- new_LookupTables names_index Components put
- end
- }{
- dup begin
- new_LookupTables names_index[null null null null]put
- end
- }ifelse
- }ifelse
- new_names names_index 3 -1 roll/Name get put
- /alias_cnt alias_cnt 1 add def
- }{
- /name xdf
- new_names names_index name put
- dup/LookupTables known{
- dup begin
- new_LookupTables names_index LookupTables names_index get put
- end
- }{
- dup begin
- new_LookupTables names_index[null null null null]put
- end
- }ifelse
- }ifelse
- /names_index names_index 1 add def
- }forall
- alias_cnt 0 gt{
- /AliasedColorants true def
- /lut_entry_len new_LookupTables 0 get dup length 256 ge{0 get length}{length}ifelse def
- 0 1 names_len 1 sub{
- /names_index xdf
- new_LookupTables names_index get dup length 256 ge{0 get length}{length}ifelse lut_entry_len ne{
- /AliasedColorants false def
- exit
- }{
- new_LookupTables names_index get 0 get null eq{
- dup/Names get names_index get/name xdf
- name(Cyan)eq name(Magenta)eq name(Yellow)eq name(Black)eq
- or or or not{
- /AliasedColorants false def
- exit
- }if
- }if
- }ifelse
- }for
- lut_entry_len 1 eq{
- /AliasedColorants false def
- }if
- AliasedColorants{
- dup begin
- /Names new_names def
- /LookupTables new_LookupTables def
- /AliasedColorants true def
- /NComponents lut_entry_len def
- /TintMethod NComponents 4 eq{/Subtractive}{/Additive}ifelse def
- /MappedCSA TintMethod/Additive eq{/DeviceRGB}{/DeviceCMYK}ifelse def
- currentdict/TTTablesIdx known not{
- /TTTablesIdx -1 def
- }if
- end
- }if
- }if
- end
- }if
- dup/devicen_colorspace_dict exch AGMCORE_gput
- begin
- currentdict/AliasedColorants known{
- AliasedColorants
- }{
- false
- }ifelse
- dup not{
- CSA map_csa
- }if
- /TintTransform load type/nulltype eq or{
- /TintTransform[
- 0 1 Names length 1 sub
- {
- /TTTablesIdx TTTablesIdx 1 add def
- dup LookupTables exch get dup 0 get null eq
- {
- 1 index
- Names exch get
- dup(Cyan)eq
- {
- pop exch
- LookupTables length exch sub
- /index cvx
- 0 0 0
- }
- {
- dup(Magenta)eq
- {
- pop exch
- LookupTables length exch sub
- /index cvx
- 0/exch cvx 0 0
- }{
- (Yellow)eq
- {
- exch
- LookupTables length exch sub
- /index cvx
- 0 0 3 -1/roll cvx 0
- }{
- exch
- LookupTables length exch sub
- /index cvx
- 0 0 0 4 -1/roll cvx
- }ifelse
- }ifelse
- }ifelse
- 5 -1/roll cvx/astore cvx
- }{
- dup length 1 sub
- LookupTables length 4 -1 roll sub 1 add
- /index cvx/mul cvx/round cvx/cvi cvx/get cvx
- }ifelse
- Names length TTTablesIdx add 1 add 1/roll cvx
- }for
- Names length[/pop cvx]cvx/repeat cvx
- NComponents Names length
- TintMethod/Subtractive eq
- {
- subtractive_blend
- }{
- additive_blend
- }ifelse
- ]cvx bdf
- }if
- AGMCORE_host_sep{
- Names convert_to_process{
- exec_tint_transform
- }
- {
- currentdict/AliasedColorants known{
- AliasedColorants not
- }{
- false
- }ifelse
- 5 dict begin
- /AvoidAliasedColorants xdf
- /painted? false def
- /names_index 0 def
- /names_len Names length def
- AvoidAliasedColorants{
- /currentspotalias current_spot_alias def
- false set_spot_alias
- }if
- Names{
- AGMCORE_is_cmyk_sep{
- dup(Cyan)eq AGMCORE_cyan_plate and exch
- dup(Magenta)eq AGMCORE_magenta_plate and exch
- dup(Yellow)eq AGMCORE_yellow_plate and exch
- (Black)eq AGMCORE_black_plate and or or or{
- /devicen_colorspace_dict AGMCORE_gget/TintProc[
- Names names_index/devn_makecustomcolor cvx
- ]cvx ddf
- /painted? true def
- }if
- painted?{exit}if
- }{
- 0 0 0 0 5 -1 roll findcmykcustomcolor 1 setcustomcolor currentgray 0 eq{
- /devicen_colorspace_dict AGMCORE_gget/TintProc[
- Names names_index/devn_makecustomcolor cvx
- ]cvx ddf
- /painted? true def
- exit
- }if
- }ifelse
- /names_index names_index 1 add def
- }forall
- AvoidAliasedColorants{
- currentspotalias set_spot_alias
- }if
- painted?{
- /devicen_colorspace_dict AGMCORE_gget/names_index names_index put
- }{
- /devicen_colorspace_dict AGMCORE_gget/TintProc[
- names_len[/pop cvx]cvx/repeat cvx 1/setseparationgray cvx
- 0 0 0 0/setcmykcolor cvx
- ]cvx ddf
- }ifelse
- end
- }ifelse
- }
- {
- AGMCORE_in_rip_sep{
- Names convert_to_process not
- }{
- level3
- }ifelse
- {
- [/DeviceN Names MappedCSA/TintTransform load]setcolorspace_opt
- /TintProc level3 not AGMCORE_in_rip_sep and{
- [
- Names/length cvx[/pop cvx]cvx/repeat cvx
- ]cvx bdf
- }{
- {setcolor}bdf
- }ifelse
- }{
- exec_tint_transform
- }ifelse
- }ifelse
- set_crd
- /AliasedColorants false def
- end
-}def
-/setindexedcolorspace
-{
- dup/indexed_colorspace_dict exch AGMCORE_gput
- begin
- currentdict/CSDBase known{
- CSDBase/CSD get_res begin
- currentdict/Names known{
- currentdict devncs
- }{
- 1 currentdict sepcs
- }ifelse
- AGMCORE_host_sep{
- 4 dict begin
- /compCnt/Names where{pop Names length}{1}ifelse def
- /NewLookup HiVal 1 add string def
- 0 1 HiVal{
- /tableIndex xdf
- Lookup dup type/stringtype eq{
- compCnt tableIndex map_index
- }{
- exec
- }ifelse
- /Names where{
- pop setdevicencolor
- }{
- setsepcolor
- }ifelse
- currentgray
- tableIndex exch
- 255 mul cvi
- NewLookup 3 1 roll put
- }for
- [/Indexed currentcolorspace HiVal NewLookup]setcolorspace_opt
- end
- }{
- level3
- {
- currentdict/Names known{
- [/Indexed[/DeviceN Names MappedCSA/TintTransform load]HiVal Lookup]setcolorspace_opt
- }{
- [/Indexed[/Separation Name MappedCSA sep_proc_name load]HiVal Lookup]setcolorspace_opt
- }ifelse
- }{
- [/Indexed MappedCSA HiVal
- [
- currentdict/Names known{
- Lookup dup type/stringtype eq
- {/exch cvx CSDBase/CSD get_res/Names get length dup/mul cvx exch/getinterval cvx{255 div}/forall cvx}
- {/exec cvx}ifelse
- /TintTransform load/exec cvx
- }{
- Lookup dup type/stringtype eq
- {/exch cvx/get cvx 255/div cvx}
- {/exec cvx}ifelse
- CSDBase/CSD get_res/MappedCSA get sep_proc_name exch pop/load cvx/exec cvx
- }ifelse
- ]cvx
- ]setcolorspace_opt
- }ifelse
- }ifelse
- end
- set_crd
- }
- {
- CSA map_csa
- AGMCORE_host_sep level2 not and{
- 0 0 0 0 setcmykcolor
- }{
- [/Indexed MappedCSA
- level2 not has_color not and{
- dup 0 get dup/DeviceRGB eq exch/DeviceCMYK eq or{
- pop[/DeviceGray]
- }if
- HiVal GrayLookup
- }{
- HiVal
- currentdict/RangeArray known{
- {
- /indexed_colorspace_dict AGMCORE_gget begin
- Lookup exch
- dup HiVal gt{
- pop HiVal
- }if
- NComponents mul NComponents getinterval{}forall
- NComponents 1 sub -1 0{
- RangeArray exch 2 mul 2 getinterval aload pop map255_to_range
- NComponents 1 roll
- }for
- end
- }bind
- }{
- Lookup
- }ifelse
- }ifelse
- ]setcolorspace_opt
- set_crd
- }ifelse
- }ifelse
- end
-}def
-/setindexedcolor
-{
- AGMCORE_host_sep{
- /indexed_colorspace_dict AGMCORE_gget
- begin
- currentdict/CSDBase known{
- CSDBase/CSD get_res begin
- currentdict/Names known{
- map_indexed_devn
- devn
- }
- {
- Lookup 1 3 -1 roll map_index
- sep
- }ifelse
- end
- }{
- Lookup MappedCSA/DeviceCMYK eq{4}{1}ifelse 3 -1 roll
- map_index
- MappedCSA/DeviceCMYK eq{setcmykcolor}{setgray}ifelse
- }ifelse
- end
- }{
- level3 not AGMCORE_in_rip_sep and/indexed_colorspace_dict AGMCORE_gget/CSDBase known and{
- /indexed_colorspace_dict AGMCORE_gget/CSDBase get/CSD get_res begin
- map_indexed_devn
- devn
- end
- }
- {
- setcolor
- }ifelse
- }ifelse
-}def
-/ignoreimagedata
-{
- currentoverprint not{
- gsave
- dup clonedict begin
- 1 setgray
- /Decode[0 1]def
- /DataSource<FF>def
- /MultipleDataSources false def
- /BitsPerComponent 8 def
- currentdict end
- systemdict/image gx
- grestore
- }if
- consumeimagedata
-}def
-/add_res
-{
- dup/CSD eq{
- pop
- //Adobe_AGM_Core begin
- /AGMCORE_CSD_cache load 3 1 roll put
- end
- }{
- defineresource pop
- }ifelse
-}def
-/del_res
-{
- {
- aload pop exch
- dup/CSD eq{
- pop
- {//Adobe_AGM_Core/AGMCORE_CSD_cache get exch undef}forall
- }{
- exch
- {1 index undefineresource}forall
- pop
- }ifelse
- }forall
-}def
-/get_res
-{
- dup/CSD eq{
- pop
- dup type dup/nametype eq exch/stringtype eq or{
- AGMCORE_CSD_cache exch get
- }if
- }{
- findresource
- }ifelse
-}def
-/get_csa_by_name
-{
- dup type dup/nametype eq exch/stringtype eq or{
- /CSA get_res
- }if
-}def
-/paintproc_buf_init
-{
- /count get 0 0 put
-}def
-/paintproc_buf_next
-{
- dup/count get dup 0 get
- dup 3 1 roll
- 1 add 0 xpt
- get
-}def
-/cachepaintproc_compress
-{
- 5 dict begin
- currentfile exch 0 exch/SubFileDecode filter/ReadFilter exch def
- /ppdict 20 dict def
- /string_size 16000 def
- /readbuffer string_size string def
- currentglobal true setglobal
- ppdict 1 array dup 0 1 put/count xpt
- setglobal
- /LZWFilter
- {
- exch
- dup length 0 eq{
- pop
- }{
- ppdict dup length 1 sub 3 -1 roll put
- }ifelse
- {string_size}{0}ifelse string
- }/LZWEncode filter def
- {
- ReadFilter readbuffer readstring
- exch LZWFilter exch writestring
- not{exit}if
- }loop
- LZWFilter closefile
- ppdict
- end
-}def
-/cachepaintproc
-{
- 2 dict begin
- currentfile exch 0 exch/SubFileDecode filter/ReadFilter exch def
- /ppdict 20 dict def
- currentglobal true setglobal
- ppdict 1 array dup 0 1 put/count xpt
- setglobal
- {
- ReadFilter 16000 string readstring exch
- ppdict dup length 1 sub 3 -1 roll put
- not{exit}if
- }loop
- ppdict dup dup length 1 sub()put
- end
-}def
-/make_pattern
-{
- exch clonedict exch
- dup matrix currentmatrix matrix concatmatrix 0 0 3 2 roll itransform
- exch 3 index/XStep get 1 index exch 2 copy div cvi mul sub sub
- exch 3 index/YStep get 1 index exch 2 copy div cvi mul sub sub
- matrix translate exch matrix concatmatrix
- 1 index begin
- BBox 0 get XStep div cvi XStep mul/xshift exch neg def
- BBox 1 get YStep div cvi YStep mul/yshift exch neg def
- BBox 0 get xshift add
- BBox 1 get yshift add
- BBox 2 get xshift add
- BBox 3 get yshift add
- 4 array astore
- /BBox exch def
- [xshift yshift/translate load null/exec load]dup
- 3/PaintProc load put cvx/PaintProc exch def
- end
- gsave 0 setgray
- makepattern
- grestore
-}def
-/set_pattern
-{
- dup/PatternType get 1 eq{
- dup/PaintType get 1 eq{
- currentoverprint sop[/DeviceGray]setcolorspace 0 setgray
- }if
- }if
- setpattern
-}def
-/setcolorspace_opt
-{
- dup currentcolorspace eq{pop}{setcolorspace}ifelse
-}def
-/updatecolorrendering
-{
- currentcolorrendering/RenderingIntent known{
- currentcolorrendering/RenderingIntent get
- }
- {
- Intent/AbsoluteColorimetric eq
- {
- /absolute_colorimetric_crd AGMCORE_gget dup null eq
- }
- {
- Intent/RelativeColorimetric eq
- {
- /relative_colorimetric_crd AGMCORE_gget dup null eq
- }
- {
- Intent/Saturation eq
- {
- /saturation_crd AGMCORE_gget dup null eq
- }
- {
- /perceptual_crd AGMCORE_gget dup null eq
- }ifelse
- }ifelse
- }ifelse
- {
- pop null
- }
- {
- /RenderingIntent known{null}{Intent}ifelse
- }ifelse
- }ifelse
- Intent ne{
- Intent/ColorRendering{findresource}stopped
- {
- pop pop systemdict/findcolorrendering known
- {
- Intent findcolorrendering
- {
- /ColorRendering findresource true exch
- }
- {
- /ColorRendering findresource
- product(Xerox Phaser 5400)ne
- exch
- }ifelse
- dup Intent/AbsoluteColorimetric eq
- {
- /absolute_colorimetric_crd exch AGMCORE_gput
- }
- {
- Intent/RelativeColorimetric eq
- {
- /relative_colorimetric_crd exch AGMCORE_gput
- }
- {
- Intent/Saturation eq
- {
- /saturation_crd exch AGMCORE_gput
- }
- {
- Intent/Perceptual eq
- {
- /perceptual_crd exch AGMCORE_gput
- }
- {
- pop
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- 1 index{exch}{pop}ifelse
- }
- {false}ifelse
- }
- {true}ifelse
- {
- dup begin
- currentdict/TransformPQR known{
- currentdict/TransformPQR get aload pop
- 3{{}eq 3 1 roll}repeat or or
- }
- {true}ifelse
- currentdict/MatrixPQR known{
- currentdict/MatrixPQR get aload pop
- 1.0 eq 9 1 roll 0.0 eq 9 1 roll 0.0 eq 9 1 roll
- 0.0 eq 9 1 roll 1.0 eq 9 1 roll 0.0 eq 9 1 roll
- 0.0 eq 9 1 roll 0.0 eq 9 1 roll 1.0 eq
- and and and and and and and and
- }
- {true}ifelse
- end
- or
- {
- clonedict begin
- /TransformPQR[
- {4 -1 roll 3 get dup 3 1 roll sub 5 -1 roll 3 get 3 -1 roll sub div
- 3 -1 roll 3 get 3 -1 roll 3 get dup 4 1 roll sub mul add}bind
- {4 -1 roll 4 get dup 3 1 roll sub 5 -1 roll 4 get 3 -1 roll sub div
- 3 -1 roll 4 get 3 -1 roll 4 get dup 4 1 roll sub mul add}bind
- {4 -1 roll 5 get dup 3 1 roll sub 5 -1 roll 5 get 3 -1 roll sub div
- 3 -1 roll 5 get 3 -1 roll 5 get dup 4 1 roll sub mul add}bind
- ]def
- /MatrixPQR[0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296]def
- /RangePQR[-0.3227950745 2.3229645538 -1.5003771057 3.5003465881 -0.1369979095 2.136967392]def
- currentdict end
- }if
- setcolorrendering_opt
- }if
- }if
-}def
-/set_crd
-{
- AGMCORE_host_sep not level2 and{
- currentdict/ColorRendering known{
- ColorRendering/ColorRendering{findresource}stopped not{setcolorrendering_opt}if
- }{
- currentdict/Intent known{
- updatecolorrendering
- }if
- }ifelse
- currentcolorspace dup type/arraytype eq
- {0 get}if
- /DeviceRGB eq
- {
- currentdict/UCR known
- {/UCR}{/AGMCORE_currentucr}ifelse
- load setundercolorremoval
- currentdict/BG known
- {/BG}{/AGMCORE_currentbg}ifelse
- load setblackgeneration
- }if
- }if
-}def
-/set_ucrbg
-{
- dup null eq{pop/AGMCORE_currentbg load}{/Procedure get_res}ifelse setblackgeneration
- dup null eq{pop/AGMCORE_currentucr load}{/Procedure get_res}ifelse setundercolorremoval
-}def
-/setcolorrendering_opt
-{
- dup currentcolorrendering eq{
- pop
- }{
- clonedict
- begin
- /Intent Intent def
- currentdict
- end
- setcolorrendering
- }ifelse
-}def
-/cpaint_gcomp
-{
- convert_to_process//Adobe_AGM_Core/AGMCORE_ConvertToProcess xddf
- //Adobe_AGM_Core/AGMCORE_ConvertToProcess get not
- {
- (%end_cpaint_gcomp)flushinput
- }if
-}def
-/cpaint_gsep
-{
- //Adobe_AGM_Core/AGMCORE_ConvertToProcess get
- {
- (%end_cpaint_gsep)flushinput
- }if
-}def
-/cpaint_gend
-{np}def
-/T1_path
-{
- currentfile token pop currentfile token pop mo
- {
- currentfile token pop dup type/stringtype eq
- {pop exit}if
- 0 exch rlineto
- currentfile token pop dup type/stringtype eq
- {pop exit}if
- 0 rlineto
- }loop
-}def
-/T1_gsave
- level3
- {/clipsave}
- {/gsave}ifelse
- load def
-/T1_grestore
- level3
- {/cliprestore}
- {/grestore}ifelse
- load def
-/set_spot_alias_ary
-{
- dup inherit_aliases
- //Adobe_AGM_Core/AGMCORE_SpotAliasAry xddf
-}def
-/set_spot_normalization_ary
-{
- dup inherit_aliases
- dup length
- /AGMCORE_SpotAliasAry where{pop AGMCORE_SpotAliasAry length add}if
- array
- //Adobe_AGM_Core/AGMCORE_SpotAliasAry2 xddf
- /AGMCORE_SpotAliasAry where{
- pop
- AGMCORE_SpotAliasAry2 0 AGMCORE_SpotAliasAry putinterval
- AGMCORE_SpotAliasAry length
- }{0}ifelse
- AGMCORE_SpotAliasAry2 3 1 roll exch putinterval
- true set_spot_alias
-}def
-/inherit_aliases
-{
- {dup/Name get map_alias{/CSD put}{pop}ifelse}forall
-}def
-/set_spot_alias
-{
- /AGMCORE_SpotAliasAry2 where{
- /AGMCORE_current_spot_alias 3 -1 roll put
- }{
- pop
- }ifelse
-}def
-/current_spot_alias
-{
- /AGMCORE_SpotAliasAry2 where{
- /AGMCORE_current_spot_alias get
- }{
- false
- }ifelse
-}def
-/map_alias
-{
- /AGMCORE_SpotAliasAry2 where{
- begin
- /AGMCORE_name xdf
- false
- AGMCORE_SpotAliasAry2{
- dup/Name get AGMCORE_name eq{
- /CSD get/CSD get_res
- exch pop true
- exit
- }{
- pop
- }ifelse
- }forall
- end
- }{
- pop false
- }ifelse
-}bdf
-/spot_alias
-{
- true set_spot_alias
- /AGMCORE_&setcustomcolor AGMCORE_key_known not{
- //Adobe_AGM_Core/AGMCORE_&setcustomcolor/setcustomcolor load put
- }if
- /customcolor_tint 1 AGMCORE_gput
- //Adobe_AGM_Core begin
- /setcustomcolor
- {
- //Adobe_AGM_Core begin
- dup/customcolor_tint exch AGMCORE_gput
- 1 index aload pop pop 1 eq exch 1 eq and exch 1 eq and exch 1 eq and not
- current_spot_alias and{1 index 4 get map_alias}{false}ifelse
- {
- false set_spot_alias
- /sep_colorspace_dict AGMCORE_gget null ne
- 3 1 roll 2 index{
- exch pop/sep_tint AGMCORE_gget exch
- }if
- mark 3 1 roll
- setsepcolorspace
- counttomark 0 ne{
- setsepcolor
- }if
- pop
- not{/sep_tint 1.0 AGMCORE_gput}if
- pop
- true set_spot_alias
- }{
- AGMCORE_&setcustomcolor
- }ifelse
- end
- }bdf
- end
-}def
-/begin_feature
-{
- Adobe_AGM_Core/AGMCORE_feature_dictCount countdictstack put
- count Adobe_AGM_Core/AGMCORE_feature_opCount 3 -1 roll put
- {Adobe_AGM_Core/AGMCORE_feature_ctm matrix currentmatrix put}if
-}def
-/end_feature
-{
- 2 dict begin
- /spd/setpagedevice load def
- /setpagedevice{get_gstate spd set_gstate}def
- stopped{$error/newerror false put}if
- end
- count Adobe_AGM_Core/AGMCORE_feature_opCount get sub dup 0 gt{{pop}repeat}{pop}ifelse
- countdictstack Adobe_AGM_Core/AGMCORE_feature_dictCount get sub dup 0 gt{{end}repeat}{pop}ifelse
- {Adobe_AGM_Core/AGMCORE_feature_ctm get setmatrix}if
-}def
-/set_negative
-{
- //Adobe_AGM_Core begin
- /AGMCORE_inverting exch def
- level2{
- currentpagedevice/NegativePrint known AGMCORE_distilling not and{
- currentpagedevice/NegativePrint get//Adobe_AGM_Core/AGMCORE_inverting get ne{
- true begin_feature true{
- <</NegativePrint//Adobe_AGM_Core/AGMCORE_inverting get>>setpagedevice
- }end_feature
- }if
- /AGMCORE_inverting false def
- }if
- }if
- AGMCORE_inverting{
- [{1 exch sub}/exec load dup currenttransfer exch]cvx bind settransfer
- AGMCORE_distilling{
- erasepage
- }{
- gsave np clippath 1/setseparationgray where{pop setseparationgray}{setgray}ifelse
- /AGMIRS_&fill where{pop AGMIRS_&fill}{fill}ifelse grestore
- }ifelse
- }if
- end
-}def
-/lw_save_restore_override{
- /md where{
- pop
- md begin
- initializepage
- /initializepage{}def
- /pmSVsetup{}def
- /endp{}def
- /pse{}def
- /psb{}def
- /orig_showpage where
- {pop}
- {/orig_showpage/showpage load def}
- ifelse
- /showpage{orig_showpage gR}def
- end
- }if
-}def
-/pscript_showpage_override{
- /NTPSOct95 where
- {
- begin
- showpage
- save
- /showpage/restore load def
- /restore{exch pop}def
- end
- }if
-}def
-/driver_media_override
-{
- /md where{
- pop
- md/initializepage known{
- md/initializepage{}put
- }if
- md/rC known{
- md/rC{4{pop}repeat}put
- }if
- }if
- /mysetup where{
- /mysetup[1 0 0 1 0 0]put
- }if
- Adobe_AGM_Core/AGMCORE_Default_CTM matrix currentmatrix put
- level2
- {Adobe_AGM_Core/AGMCORE_Default_PageSize currentpagedevice/PageSize get put}if
-}def
-/driver_check_media_override
-{
- /PrepsDict where
- {pop}
- {
- Adobe_AGM_Core/AGMCORE_Default_CTM get matrix currentmatrix ne
- Adobe_AGM_Core/AGMCORE_Default_PageSize get type/arraytype eq
- {
- Adobe_AGM_Core/AGMCORE_Default_PageSize get 0 get currentpagedevice/PageSize get 0 get eq and
- Adobe_AGM_Core/AGMCORE_Default_PageSize get 1 get currentpagedevice/PageSize get 1 get eq and
- }if
- {
- Adobe_AGM_Core/AGMCORE_Default_CTM get setmatrix
- }if
- }ifelse
-}def
-AGMCORE_err_strings begin
- /AGMCORE_bad_environ(Environment not satisfactory for this job. Ensure that the PPD is correct or that the PostScript level requested is supported by this printer. )def
- /AGMCORE_color_space_onhost_seps(This job contains colors that will not separate with on-host methods. )def
- /AGMCORE_invalid_color_space(This job contains an invalid color space. )def
-end
-/set_def_ht
-{AGMCORE_def_ht sethalftone}def
-/set_def_flat
-{AGMCORE_Default_flatness setflat}def
-end
-systemdict/setpacking known
-{setpacking}if
-%%EndResource
-%%BeginResource: procset Adobe_CoolType_Core 2.31 0 %%Copyright: Copyright 1997-2006 Adobe Systems Incorporated. All Rights Reserved. %%Version: 2.31 0 10 dict begin /Adobe_CoolType_Passthru currentdict def /Adobe_CoolType_Core_Defined userdict/Adobe_CoolType_Core known def Adobe_CoolType_Core_Defined {/Adobe_CoolType_Core userdict/Adobe_CoolType_Core get def} if userdict/Adobe_CoolType_Core 70 dict dup begin put /Adobe_CoolType_Version 2.31 def /Level2? systemdict/languagelevel known dup {pop systemdict/languagelevel get 2 ge} if def Level2? not { /currentglobal false def /setglobal/pop load def /gcheck{pop false}bind def /currentpacking false def /setpacking/pop load def /SharedFontDirectory 0 dict def } if currentpacking true setpacking currentglobal false setglobal userdict/Adobe_CoolType_Data 2 copy known not {2 copy 10 dict put} if get begin /@opStackCountByLevel 32 dict def /@opStackLevel 0 def /@dictStackCountByLevel 32 dict def /@dictStackLevel 0 def end setglobal currentglobal true setglobal userdict/Adobe_CoolType_GVMFonts known not {userdict/Adobe_CoolType_GVMFonts 10 dict put} if setglobal currentglobal false setglobal userdict/Adobe_CoolType_LVMFonts known not {userdict/Adobe_CoolType_LVMFonts 10 dict put} if setglobal /ct_VMDictPut { dup gcheck{Adobe_CoolType_GVMFonts}{Adobe_CoolType_LVMFonts}ifelse 3 1 roll put }bind def /ct_VMDictUndef { dup Adobe_CoolType_GVMFonts exch known {Adobe_CoolType_GVMFonts exch undef} { dup Adobe_CoolType_LVMFonts exch known {Adobe_CoolType_LVMFonts exch undef} {pop} ifelse }ifelse }bind def /ct_str1 1 string def /ct_xshow { /_ct_na exch def /_ct_i 0 def currentpoint /_ct_y exch def /_ct_x exch def { pop pop ct_str1 exch 0 exch put ct_str1 show {_ct_na _ct_i get}stopped {pop pop} { _ct_x _ct_y moveto 0 rmoveto } ifelse /_ct_i _ct_i 1 add def currentpoint /_ct_y exch def /_ct_x exch def } exch @cshow }bind def /ct_yshow { /_ct_na exch def /_ct_i 0 def currentpoint /_ct_y exch def /_ct_x exch def { pop pop ct_str1 exch 0 exch put ct_str1 show {_ct_na _ct_i get}stopped {pop pop} { _ct_x _ct_y moveto 0 exch rmoveto } ifelse /_ct_i _ct_i 1 add def currentpoint /_ct_y exch def /_ct_x exch def } exch @cshow }bind def /ct_xyshow { /_ct_na exch def /_ct_i 0 def currentpoint /_ct_y exch def /_ct_x exch def { pop pop ct_str1 exch 0 exch put ct_str1 show {_ct_na _ct_i get}stopped {pop pop} { {_ct_na _ct_i 1 add get}stopped {pop pop pop} { _ct_x _ct_y moveto rmoveto } ifelse } ifelse /_ct_i _ct_i 2 add def currentpoint /_ct_y exch def /_ct_x exch def } exch @cshow }bind def /xsh{{@xshow}stopped{Adobe_CoolType_Data begin ct_xshow end}if}bind def /ysh{{@yshow}stopped{Adobe_CoolType_Data begin ct_yshow end}if}bind def /xysh{{@xyshow}stopped{Adobe_CoolType_Data begin ct_xyshow end}if}bind def currentglobal true setglobal /ct_T3Defs { /BuildChar { 1 index/Encoding get exch get 1 index/BuildGlyph get exec }bind def /BuildGlyph { exch begin GlyphProcs exch get exec end }bind def }bind def setglobal /@_SaveStackLevels { Adobe_CoolType_Data begin /@vmState currentglobal def false setglobal @opStackCountByLevel @opStackLevel 2 copy known not { 2 copy 3 dict dup/args 7 index 5 add array put put get } { get dup/args get dup length 3 index lt { dup length 5 add array exch 1 index exch 0 exch putinterval 1 index exch/args exch put } {pop} ifelse } ifelse begin count 1 sub 1 index lt {pop count} if dup/argCount exch def dup 0 gt { args exch 0 exch getinterval astore pop } {pop} ifelse count /restCount exch def end /@opStackLevel @opStackLevel 1 add def countdictstack 1 sub @dictStackCountByLevel exch @dictStackLevel exch put /@dictStackLevel @dictStackLevel 1 add def @vmState setglobal end }bind def /@_RestoreStackLevels { Adobe_CoolType_Data begin /@opStackLevel @opStackLevel 1 sub def @opStackCountByLevel @opStackLevel get begin count restCount sub dup 0 gt {{pop}repeat} {pop} ifelse args 0 argCount getinterval{}forall end /@dictStackLevel @dictStackLevel 1 sub def @dictStackCountByLevel @dictStackLevel get end countdictstack exch sub dup 0 gt {{end}repeat} {pop} ifelse }bind def /@_PopStackLevels { Adobe_CoolType_Data begin /@opStackLevel @opStackLevel 1 sub def /@dictStackLevel @dictStackLevel 1 sub def end }bind def /@Raise { exch cvx exch errordict exch get exec stop }bind def /@ReRaise { cvx $error/errorname get errordict exch get exec stop }bind def /@Stopped { 0 @#Stopped }bind def /@#Stopped { @_SaveStackLevels stopped {@_RestoreStackLevels true} {@_PopStackLevels false} ifelse }bind def /@Arg { Adobe_CoolType_Data begin @opStackCountByLevel @opStackLevel 1 sub get begin args exch argCount 1 sub exch sub get end end }bind def currentglobal true setglobal /CTHasResourceForAllBug Level2? { 1 dict dup /@shouldNotDisappearDictValue true def Adobe_CoolType_Data exch/@shouldNotDisappearDict exch put begin count @_SaveStackLevels {(*){pop stop}128 string/Category resourceforall} stopped pop @_RestoreStackLevels currentdict Adobe_CoolType_Data/@shouldNotDisappearDict get dup 3 1 roll ne dup 3 1 roll { /@shouldNotDisappearDictValue known { { end currentdict 1 index eq {pop exit} if } loop } if } { pop end } ifelse } {false} ifelse def true setglobal /CTHasResourceStatusBug Level2? { mark {/steveamerige/Category resourcestatus} stopped {cleartomark true} {cleartomark currentglobal not} ifelse } {false} ifelse def setglobal /CTResourceStatus { mark 3 1 roll /Category findresource begin ({ResourceStatus}stopped)0()/SubFileDecode filter cvx exec {cleartomark false} {{3 2 roll pop true}{cleartomark false}ifelse} ifelse end }bind def /CTWorkAroundBugs { Level2? { /cid_PreLoad/ProcSet resourcestatus { pop pop currentglobal mark { (*) { dup/CMap CTHasResourceStatusBug {CTResourceStatus} {resourcestatus} ifelse { pop dup 0 eq exch 1 eq or { dup/CMap findresource gcheck setglobal /CMap undefineresource } { pop CTHasResourceForAllBug {exit} {stop} ifelse } ifelse } {pop} ifelse } 128 string/CMap resourceforall } stopped {cleartomark} stopped pop setglobal } if } if }bind def /ds { Adobe_CoolType_Core begin CTWorkAroundBugs /mo/moveto load def /nf/newencodedfont load def /msf{makefont setfont}bind def /uf{dup undefinefont ct_VMDictUndef}bind def /ur/undefineresource load def /chp/charpath load def /awsh/awidthshow load def /wsh/widthshow load def /ash/ashow load def /@xshow/xshow load def /@yshow/yshow load def /@xyshow/xyshow load def /@cshow/cshow load def /sh/show load def /rp/repeat load def /.n/.notdef def end currentglobal false setglobal userdict/Adobe_CoolType_Data 2 copy known not {2 copy 10 dict put} if get begin /AddWidths? false def /CC 0 def /charcode 2 string def /@opStackCountByLevel 32 dict def /@opStackLevel 0 def /@dictStackCountByLevel 32 dict def /@dictStackLevel 0 def /InVMFontsByCMap 10 dict def /InVMDeepCopiedFonts 10 dict def end setglobal }bind def /dt { currentdict Adobe_CoolType_Core eq {end} if }bind def /ps { Adobe_CoolType_Core begin Adobe_CoolType_GVMFonts begin Adobe_CoolType_LVMFonts begin SharedFontDirectory begin }bind def /pt { end end end end }bind def /unload { systemdict/languagelevel known { systemdict/languagelevel get 2 ge { userdict/Adobe_CoolType_Core 2 copy known {undef} {pop pop} ifelse } if } if }bind def /ndf { 1 index where {pop pop pop} {dup xcheck{bind}if def} ifelse }def /findfont systemdict begin userdict begin /globaldict where{/globaldict get begin}if dup where pop exch get /globaldict where{pop end}if end end Adobe_CoolType_Core_Defined {/systemfindfont exch def} { /findfont 1 index def /systemfindfont exch def } ifelse /undefinefont {pop}ndf /copyfont { currentglobal 3 1 roll 1 index gcheck setglobal dup null eq{0}{dup length}ifelse 2 index length add 1 add dict begin exch { 1 index/FID eq {pop pop} {def} ifelse } forall dup null eq {pop} {{def}forall} ifelse currentdict end exch setglobal }bind def /copyarray { currentglobal exch dup gcheck setglobal dup length array copy exch setglobal }bind def /newencodedfont { currentglobal { SharedFontDirectory 3 index known {SharedFontDirectory 3 index get/FontReferenced known} {false} ifelse } { FontDirectory 3 index known {FontDirectory 3 index get/FontReferenced known} { SharedFontDirectory 3 index known {SharedFontDirectory 3 index get/FontReferenced known} {false} ifelse } ifelse } ifelse dup { 3 index findfont/FontReferenced get 2 index dup type/nametype eq {findfont} if ne {pop false} if } if dup { 1 index dup type/nametype eq {findfont} if dup/CharStrings known { /CharStrings get length 4 index findfont/CharStrings get length ne { pop false } if } {pop} ifelse } if { pop 1 index findfont /Encoding get exch 0 1 255 {2 copy get 3 index 3 1 roll put} for pop pop pop } { currentglobal 4 1 roll dup type/nametype eq {findfont} if dup gcheck setglobal dup dup maxlength 2 add dict begin exch { 1 index/FID ne 2 index/Encoding ne and {def} {pop pop} ifelse } forall /FontReferenced exch def /Encoding exch dup length array copy def /FontName 1 index dup type/stringtype eq{cvn}if def dup currentdict end definefont ct_VMDictPut setglobal } ifelse }bind def /SetSubstituteStrategy { $SubstituteFont begin dup type/dicttype ne {0 dict} if currentdict/$Strategies known { exch $Strategies exch 2 copy known { get 2 copy maxlength exch maxlength add dict begin {def}forall {def}forall currentdict dup/$Init known {dup/$Init get exec} if end /$Strategy exch def } {pop pop pop} ifelse } {pop pop} ifelse end }bind def /scff { $SubstituteFont begin dup type/stringtype eq {dup length exch} {null} ifelse /$sname exch def /$slen exch def /$inVMIndex $sname null eq { 1 index $str cvs dup length $slen sub $slen getinterval cvn } {$sname} ifelse def end {findfont} @Stopped { dup length 8 add string exch 1 index 0(BadFont:)putinterval 1 index exch 8 exch dup length string cvs putinterval cvn {findfont} @Stopped {pop/Courier findfont} if } if $SubstituteFont begin /$sname null def /$slen 0 def /$inVMIndex null def end }bind def /isWidthsOnlyFont { dup/WidthsOnly known {pop pop true} { dup/FDepVector known {/FDepVector get{isWidthsOnlyFont dup{exit}if}forall} { dup/FDArray known {/FDArray get{isWidthsOnlyFont dup{exit}if}forall} {pop} ifelse } ifelse } ifelse }bind def /ct_StyleDicts 4 dict dup begin /Adobe-Japan1 4 dict dup begin Level2? { /Serif /HeiseiMin-W3-83pv-RKSJ-H/Font resourcestatus {pop pop/HeiseiMin-W3} { /CIDFont/Category resourcestatus { pop pop /HeiseiMin-W3/CIDFont resourcestatus {pop pop/HeiseiMin-W3} {/Ryumin-Light} ifelse } {/Ryumin-Light} ifelse } ifelse def /SansSerif /HeiseiKakuGo-W5-83pv-RKSJ-H/Font resourcestatus {pop pop/HeiseiKakuGo-W5} { /CIDFont/Category resourcestatus { pop pop /HeiseiKakuGo-W5/CIDFont resourcestatus {pop pop/HeiseiKakuGo-W5} {/GothicBBB-Medium} ifelse } {/GothicBBB-Medium} ifelse } ifelse def /HeiseiMaruGo-W4-83pv-RKSJ-H/Font resourcestatus {pop pop/HeiseiMaruGo-W4} { /CIDFont/Category resourcestatus { pop pop /HeiseiMaruGo-W4/CIDFont resourcestatus {pop pop/HeiseiMaruGo-W4} { /Jun101-Light-RKSJ-H/Font resourcestatus {pop pop/Jun101-Light} {SansSerif} ifelse } ifelse } { /Jun101-Light-RKSJ-H/Font resourcestatus {pop pop/Jun101-Light} {SansSerif} ifelse } ifelse } ifelse /RoundSansSerif exch def /Default Serif def } { /Serif/Ryumin-Light def /SansSerif/GothicBBB-Medium def { (fonts/Jun101-Light-83pv-RKSJ-H)status }stopped {pop}{ {pop pop pop pop/Jun101-Light} {SansSerif} ifelse /RoundSansSerif exch def }ifelse /Default Serif def } ifelse end def /Adobe-Korea1 4 dict dup begin /Serif/HYSMyeongJo-Medium def /SansSerif/HYGoThic-Medium def /RoundSansSerif SansSerif def /Default Serif def end def /Adobe-GB1 4 dict dup begin /Serif/STSong-Light def /SansSerif/STHeiti-Regular def /RoundSansSerif SansSerif def /Default Serif def end def /Adobe-CNS1 4 dict dup begin /Serif/MKai-Medium def /SansSerif/MHei-Medium def /RoundSansSerif SansSerif def /Default Serif def end def end def Level2?{currentglobal true setglobal}if /ct_BoldRomanWidthProc { stringwidth 1 index 0 ne{exch .03 add exch}if setcharwidth 0 0 }bind def /ct_Type0WidthProc { dup stringwidth 0 0 moveto 2 index true charpath pathbbox 0 -1 7 index 2 div .88 setcachedevice2 pop 0 0 }bind def /ct_Type0WMode1WidthProc { dup stringwidth pop 2 div neg -0.88 2 copy moveto 0 -1 5 -1 roll true charpath pathbbox setcachedevice }bind def /cHexEncoding [/c00/c01/c02/c03/c04/c05/c06/c07/c08/c09/c0A/c0B/c0C/c0D/c0E/c0F/c10/c11/c12 /c13/c14/c15/c16/c17/c18/c19/c1A/c1B/c1C/c1D/c1E/c1F/c20/c21/c22/c23/c24/c25 /c26/c27/c28/c29/c2A/c2B/c2C/c2D/c2E/c2F/c30/c31/c32/c33/c34/c35/c36/c37/c38 /c39/c3A/c3B/c3C/c3D/c3E/c3F/c40/c41/c42/c43/c44/c45/c46/c47/c48/c49/c4A/c4B /c4C/c4D/c4E/c4F/c50/c51/c52/c53/c54/c55/c56/c57/c58/c59/c5A/c5B/c5C/c5D/c5E /c5F/c60/c61/c62/c63/c64/c65/c66/c67/c68/c69/c6A/c6B/c6C/c6D/c6E/c6F/c70/c71 /c72/c73/c74/c75/c76/c77/c78/c79/c7A/c7B/c7C/c7D/c7E/c7F/c80/c81/c82/c83/c84 /c85/c86/c87/c88/c89/c8A/c8B/c8C/c8D/c8E/c8F/c90/c91/c92/c93/c94/c95/c96/c97 /c98/c99/c9A/c9B/c9C/c9D/c9E/c9F/cA0/cA1/cA2/cA3/cA4/cA5/cA6/cA7/cA8/cA9/cAA /cAB/cAC/cAD/cAE/cAF/cB0/cB1/cB2/cB3/cB4/cB5/cB6/cB7/cB8/cB9/cBA/cBB/cBC/cBD /cBE/cBF/cC0/cC1/cC2/cC3/cC4/cC5/cC6/cC7/cC8/cC9/cCA/cCB/cCC/cCD/cCE/cCF/cD0 /cD1/cD2/cD3/cD4/cD5/cD6/cD7/cD8/cD9/cDA/cDB/cDC/cDD/cDE/cDF/cE0/cE1/cE2/cE3 /cE4/cE5/cE6/cE7/cE8/cE9/cEA/cEB/cEC/cED/cEE/cEF/cF0/cF1/cF2/cF3/cF4/cF5/cF6 /cF7/cF8/cF9/cFA/cFB/cFC/cFD/cFE/cFF]def /ct_BoldBaseFont 11 dict begin /FontType 3 def /FontMatrix[1 0 0 1 0 0]def /FontBBox[0 0 1 1]def /Encoding cHexEncoding def /_setwidthProc/ct_BoldRomanWidthProc load def /_bcstr1 1 string def /BuildChar { exch begin _basefont setfont _bcstr1 dup 0 4 -1 roll put dup _setwidthProc 3 copy moveto show _basefonto setfont moveto show end }bind def currentdict end def systemdict/composefont known { /ct_DefineIdentity-H { /Identity-H/CMap resourcestatus { pop pop } { /CIDInit/ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo 3 dict dup begin /Registry(Adobe)def /Ordering(Identity)def /Supplement 0 def end def /CMapName/Identity-H def /CMapVersion 1.000 def /CMapType 1 def 1 begincodespacerange <0000><FFFF> endcodespacerange 1 begincidrange <0000><FFFF>0 endcidrange endcmap CMapName currentdict/CMap defineresource pop end end } ifelse } def /ct_BoldBaseCIDFont 11 dict begin /CIDFontType 1 def /CIDFontName/ct_BoldBaseCIDFont def /FontMatrix[1 0 0 1 0 0]def /FontBBox[0 0 1 1]def /_setwidthProc/ct_Type0WidthProc load def /_bcstr2 2 string def /BuildGlyph { exch begin _basefont setfont _bcstr2 1 2 index 256 mod put _bcstr2 0 3 -1 roll 256 idiv put _bcstr2 dup _setwidthProc 3 copy moveto show _basefonto setfont moveto show end }bind def currentdict end def }if Level2?{setglobal}if /ct_CopyFont{ { 1 index/FID ne 2 index/UniqueID ne and {def}{pop pop}ifelse }forall }bind def /ct_Type0CopyFont { exch dup length dict begin ct_CopyFont [ exch FDepVector { dup/FontType get 0 eq { 1 index ct_Type0CopyFont /_ctType0 exch definefont } { /_ctBaseFont exch 2 index exec } ifelse exch } forall pop ] /FDepVector exch def currentdict end }bind def /ct_MakeBoldFont { dup/ct_SyntheticBold known { dup length 3 add dict begin ct_CopyFont /ct_StrokeWidth .03 0 FontMatrix idtransform pop def /ct_SyntheticBold true def currentdict end definefont } { dup dup length 3 add dict begin ct_CopyFont /PaintType 2 def /StrokeWidth .03 0 FontMatrix idtransform pop def /dummybold currentdict end definefont dup/FontType get dup 9 ge exch 11 le and { ct_BoldBaseCIDFont dup length 3 add dict copy begin dup/CIDSystemInfo get/CIDSystemInfo exch def ct_DefineIdentity-H /_Type0Identity/Identity-H 3 -1 roll[exch]composefont /_basefont exch def /_Type0Identity/Identity-H 3 -1 roll[exch]composefont /_basefonto exch def currentdict end /CIDFont defineresource } { ct_BoldBaseFont dup length 3 add dict copy begin /_basefont exch def /_basefonto exch def currentdict end definefont } ifelse } ifelse }bind def /ct_MakeBold{ 1 index 1 index findfont currentglobal 5 1 roll dup gcheck setglobal dup /FontType get 0 eq { dup/WMode known{dup/WMode get 1 eq}{false}ifelse version length 4 ge and {version 0 4 getinterval cvi 2015 ge} {true} ifelse {/ct_Type0WidthProc} {/ct_Type0WMode1WidthProc} ifelse ct_BoldBaseFont/_setwidthProc 3 -1 roll load put {ct_MakeBoldFont}ct_Type0CopyFont definefont } { dup/_fauxfont known not 1 index/SubstMaster known not and { ct_BoldBaseFont/_setwidthProc /ct_BoldRomanWidthProc load put ct_MakeBoldFont } { 2 index 2 index eq {exch pop } { dup length dict begin ct_CopyFont currentdict end definefont } ifelse } ifelse } ifelse pop pop pop setglobal }bind def /?str1 256 string def /?set { $SubstituteFont begin /$substituteFound false def /$fontname 1 index def /$doSmartSub false def end dup findfont $SubstituteFont begin $substituteFound {false} { dup/FontName known { dup/FontName get $fontname eq 1 index/DistillerFauxFont known not and /currentdistillerparams where {pop false 2 index isWidthsOnlyFont not and} if } {false} ifelse } ifelse exch pop /$doSmartSub true def end { 5 1 roll pop pop pop pop findfont } { 1 index findfont dup/FontType get 3 eq { 6 1 roll pop pop pop pop pop false } {pop true} ifelse { $SubstituteFont begin pop pop /$styleArray 1 index def /$regOrdering 2 index def pop pop 0 1 $styleArray length 1 sub { $styleArray exch get ct_StyleDicts $regOrdering 2 copy known { get exch 2 copy known not {pop/Default} if get dup type/nametype eq { ?str1 cvs length dup 1 add exch ?str1 exch(-)putinterval exch dup length exch ?str1 exch 3 index exch putinterval add ?str1 exch 0 exch getinterval cvn } { pop pop/Unknown } ifelse } { pop pop pop pop/Unknown } ifelse } for end findfont }if } ifelse currentglobal false setglobal 3 1 roll null copyfont definefont pop setglobal }bind def setpacking userdict/$SubstituteFont 25 dict put 1 dict begin /SubstituteFont dup $error exch 2 copy known {get} {pop pop{pop/Courier}bind} ifelse def /currentdistillerparams where dup { pop pop currentdistillerparams/CannotEmbedFontPolicy 2 copy known {get/Error eq} {pop pop false} ifelse } if not { countdictstack array dictstack 0 get begin userdict begin $SubstituteFont begin /$str 128 string def /$fontpat 128 string def /$slen 0 def /$sname null def /$match false def /$fontname null def /$substituteFound false def /$inVMIndex null def /$doSmartSub true def /$depth 0 def /$fontname null def /$italicangle 26.5 def /$dstack null def /$Strategies 10 dict dup begin /$Type3Underprint { currentglobal exch false setglobal 11 dict begin /UseFont exch $WMode 0 ne { dup length dict copy dup/WMode $WMode put /UseFont exch definefont } if def /FontName $fontname dup type/stringtype eq{cvn}if def /FontType 3 def /FontMatrix[.001 0 0 .001 0 0]def /Encoding 256 array dup 0 1 255{/.notdef put dup}for pop def /FontBBox[0 0 0 0]def /CCInfo 7 dict dup begin /cc null def /x 0 def /y 0 def end def /BuildChar { exch begin CCInfo begin 1 string dup 0 3 index put exch pop /cc exch def UseFont 1000 scalefont setfont cc stringwidth/y exch def/x exch def x y setcharwidth $SubstituteFont/$Strategy get/$Underprint get exec 0 0 moveto cc show x y moveto end end }bind def currentdict end exch setglobal }bind def /$GetaTint 2 dict dup begin /$BuildFont { dup/WMode known {dup/WMode get} {0} ifelse /$WMode exch def $fontname exch dup/FontName known { dup/FontName get dup type/stringtype eq{cvn}if } {/unnamedfont} ifelse exch Adobe_CoolType_Data/InVMDeepCopiedFonts get 1 index/FontName get known { pop Adobe_CoolType_Data/InVMDeepCopiedFonts get 1 index get null copyfont } {$deepcopyfont} ifelse exch 1 index exch/FontBasedOn exch put dup/FontName $fontname dup type/stringtype eq{cvn}if put definefont Adobe_CoolType_Data/InVMDeepCopiedFonts get begin dup/FontBasedOn get 1 index def end }bind def /$Underprint { gsave x abs y abs gt {/y 1000 def} {/x -1000 def 500 120 translate} ifelse Level2? { [/Separation(All)/DeviceCMYK{0 0 0 1 pop}] setcolorspace } {0 setgray} ifelse 10 setlinewidth x .8 mul [7 3] { y mul 8 div 120 sub x 10 div exch moveto 0 y 4 div neg rlineto dup 0 rlineto 0 y 4 div rlineto closepath gsave Level2? {.2 setcolor} {.8 setgray} ifelse fill grestore stroke } forall pop grestore }bind def end def /$Oblique 1 dict dup begin /$BuildFont { currentglobal exch dup gcheck setglobal null copyfont begin /FontBasedOn currentdict/FontName known { FontName dup type/stringtype eq{cvn}if } {/unnamedfont} ifelse def /FontName $fontname dup type/stringtype eq{cvn}if def /currentdistillerparams where {pop} { /FontInfo currentdict/FontInfo known {FontInfo null copyfont} {2 dict} ifelse dup begin /ItalicAngle $italicangle def /FontMatrix FontMatrix [1 0 ItalicAngle dup sin exch cos div 1 0 0] matrix concatmatrix readonly end 4 2 roll def def } ifelse FontName currentdict end definefont exch setglobal }bind def end def /$None 1 dict dup begin /$BuildFont{}bind def end def end def /$Oblique SetSubstituteStrategy /$findfontByEnum { dup type/stringtype eq{cvn}if dup/$fontname exch def $sname null eq {$str cvs dup length $slen sub $slen getinterval} {pop $sname} ifelse $fontpat dup 0(fonts/*)putinterval exch 7 exch putinterval /$match false def $SubstituteFont/$dstack countdictstack array dictstack put mark { $fontpat 0 $slen 7 add getinterval {/$match exch def exit} $str filenameforall } stopped { cleardictstack currentdict true $SubstituteFont/$dstack get { exch { 1 index eq {pop false} {true} ifelse } {begin false} ifelse } forall pop } if cleartomark /$slen 0 def $match false ne {$match(fonts/)anchorsearch pop pop cvn} {/Courier} ifelse }bind def /$ROS 1 dict dup begin /Adobe 4 dict dup begin /Japan1 [/Ryumin-Light/HeiseiMin-W3 /GothicBBB-Medium/HeiseiKakuGo-W5 /HeiseiMaruGo-W4/Jun101-Light]def /Korea1 [/HYSMyeongJo-Medium/HYGoThic-Medium]def /GB1 [/STSong-Light/STHeiti-Regular]def /CNS1 [/MKai-Medium/MHei-Medium]def end def end def /$cmapname null def /$deepcopyfont { dup/FontType get 0 eq { 1 dict dup/FontName/copied put copyfont begin /FDepVector FDepVector copyarray 0 1 2 index length 1 sub { 2 copy get $deepcopyfont dup/FontName/copied put /copied exch definefont 3 copy put pop pop } for def currentdict end } {$Strategies/$Type3Underprint get exec} ifelse }bind def /$buildfontname { dup/CIDFont findresource/CIDSystemInfo get begin Registry length Ordering length Supplement 8 string cvs 3 copy length 2 add add add string dup 5 1 roll dup 0 Registry putinterval dup 4 index(-)putinterval dup 4 index 1 add Ordering putinterval 4 2 roll add 1 add 2 copy(-)putinterval end 1 add 2 copy 0 exch getinterval $cmapname $fontpat cvs exch anchorsearch {pop pop 3 2 roll putinterval cvn/$cmapname exch def} {pop pop pop pop pop} ifelse length $str 1 index(-)putinterval 1 add $str 1 index $cmapname $fontpat cvs putinterval $cmapname length add $str exch 0 exch getinterval cvn }bind def /$findfontByROS { /$fontname exch def $ROS Registry 2 copy known { get Ordering 2 copy known {get} {pop pop[]} ifelse } {pop pop[]} ifelse false exch { dup/CIDFont resourcestatus { pop pop save 1 index/CIDFont findresource dup/WidthsOnly known {dup/WidthsOnly get} {false} ifelse exch pop exch restore {pop} {exch pop true exit} ifelse } {pop} ifelse } forall {$str cvs $buildfontname} { false(*) { save exch dup/CIDFont findresource dup/WidthsOnly known {dup/WidthsOnly get not} {true} ifelse exch/CIDSystemInfo get dup/Registry get Registry eq exch/Ordering get Ordering eq and and {exch restore exch pop true exit} {pop restore} ifelse } $str/CIDFont resourceforall {$buildfontname} {$fontname $findfontByEnum} ifelse } ifelse }bind def end end currentdict/$error known currentdict/languagelevel known and dup {pop $error/SubstituteFont known} if dup {$error} {Adobe_CoolType_Core} ifelse begin { /SubstituteFont /CMap/Category resourcestatus { pop pop { $SubstituteFont begin /$substituteFound true def dup length $slen gt $sname null ne or $slen 0 gt and { $sname null eq {dup $str cvs dup length $slen sub $slen getinterval cvn} {$sname} ifelse Adobe_CoolType_Data/InVMFontsByCMap get 1 index 2 copy known { get false exch { pop currentglobal { GlobalFontDirectory 1 index known {exch pop true exit} {pop} ifelse } { FontDirectory 1 index known {exch pop true exit} { GlobalFontDirectory 1 index known {exch pop true exit} {pop} ifelse } ifelse } ifelse } forall } {pop pop false} ifelse { exch pop exch pop } { dup/CMap resourcestatus { pop pop dup/$cmapname exch def /CMap findresource/CIDSystemInfo get{def}forall $findfontByROS } { 128 string cvs dup(-)search { 3 1 roll search { 3 1 roll pop {dup cvi} stopped {pop pop pop pop pop $findfontByEnum} { 4 2 roll pop pop exch length exch 2 index length 2 index sub exch 1 sub -1 0 { $str cvs dup length 4 index 0 4 index 4 3 roll add getinterval exch 1 index exch 3 index exch putinterval dup/CMap resourcestatus { pop pop 4 1 roll pop pop pop dup/$cmapname exch def /CMap findresource/CIDSystemInfo get{def}forall $findfontByROS true exit } {pop} ifelse } for dup type/booleantype eq {pop} {pop pop pop $findfontByEnum} ifelse } ifelse } {pop pop pop $findfontByEnum} ifelse } {pop pop $findfontByEnum} ifelse } ifelse } ifelse } {//SubstituteFont exec} ifelse /$slen 0 def end } } { { $SubstituteFont begin /$substituteFound true def dup length $slen gt $sname null ne or $slen 0 gt and {$findfontByEnum} {//SubstituteFont exec} ifelse end } } ifelse bind readonly def Adobe_CoolType_Core/scfindfont/systemfindfont load put } { /scfindfont { $SubstituteFont begin dup systemfindfont dup/FontName known {dup/FontName get dup 3 index ne} {/noname true} ifelse dup { /$origfontnamefound 2 index def /$origfontname 4 index def/$substituteFound true def } if exch pop { $slen 0 gt $sname null ne 3 index length $slen gt or and { pop dup $findfontByEnum findfont dup maxlength 1 add dict begin {1 index/FID eq{pop pop}{def}ifelse} forall currentdict end definefont dup/FontName known{dup/FontName get}{null}ifelse $origfontnamefound ne { $origfontname $str cvs print ( substitution revised, using )print dup/FontName known {dup/FontName get}{(unspecified font)} ifelse $str cvs print(.\n)print } if } {exch pop} ifelse } {exch pop} ifelse end }bind def } ifelse end end Adobe_CoolType_Core_Defined not { Adobe_CoolType_Core/findfont { $SubstituteFont begin $depth 0 eq { /$fontname 1 index dup type/stringtype ne{$str cvs}if def /$substituteFound false def } if /$depth $depth 1 add def end scfindfont $SubstituteFont begin /$depth $depth 1 sub def $substituteFound $depth 0 eq and { $inVMIndex null ne {dup $inVMIndex $AddInVMFont} if $doSmartSub { currentdict/$Strategy known {$Strategy/$BuildFont get exec} if } if } if end }bind put } if } if end /$AddInVMFont { exch/FontName 2 copy known { get 1 dict dup begin exch 1 index gcheck def end exch Adobe_CoolType_Data/InVMFontsByCMap get exch $DictAdd } {pop pop pop} ifelse }bind def /$DictAdd { 2 copy known not {2 copy 4 index length dict put} if Level2? not { 2 copy get dup maxlength exch length 4 index length add lt 2 copy get dup length 4 index length add exch maxlength 1 index lt { 2 mul dict begin 2 copy get{forall}def 2 copy currentdict put end } {pop} ifelse } if get begin {def} forall end }bind def end end %%EndResource currentglobal true setglobal %%BeginResource: procset Adobe_CoolType_Utility_MAKEOCF 1.23 0 %%Copyright: Copyright 1987-2006 Adobe Systems Incorporated. %%Version: 1.23 0 systemdict/languagelevel known dup {currentglobal false setglobal} {false} ifelse exch userdict/Adobe_CoolType_Utility 2 copy known {2 copy get dup maxlength 27 add dict copy} {27 dict} ifelse put Adobe_CoolType_Utility begin /@eexecStartData <BAB431EA07F209EB8C4348311481D9D3F76E3D15246555577D87BC510ED54E 118C39697FA9F6DB58128E60EB8A12FA24D7CDD2FA94D221FA9EC8DA3E5E6A1C 4ACECC8C2D39C54E7C946031DD156C3A6B4A09AD29E1867A>def /@recognizeCIDFont null def /ct_Level2? exch def /ct_Clone? 1183615869 internaldict dup /CCRun known not exch/eCCRun known not ct_Level2? and or def ct_Level2? {globaldict begin currentglobal true setglobal} if /ct_AddStdCIDMap ct_Level2? {{ mark Adobe_CoolType_Utility/@recognizeCIDFont currentdict put { ((Hex)57 StartData 0615 1e27 2c39 1c60 d8a8 cc31 fe2b f6e0 7aa3 e541 e21c 60d8 a8c9 c3d0 6d9e 1c60 d8a8 c9c2 02d7 9a1c 60d8 a849 1c60 d8a8 cc36 74f4 1144 b13b 77)0()/SubFileDecode filter cvx exec } stopped { cleartomark Adobe_CoolType_Utility/@recognizeCIDFont get countdictstack dup array dictstack exch 1 sub -1 0 { 2 copy get 3 index eq {1 index length exch sub 1 sub{end}repeat exit} {pop} ifelse } for pop pop Adobe_CoolType_Utility/@eexecStartData get eexec } {cleartomark} ifelse }} {{ Adobe_CoolType_Utility/@eexecStartData get eexec }} ifelse bind def userdict/cid_extensions known dup{cid_extensions/cid_UpdateDB known and}if { cid_extensions begin /cid_GetCIDSystemInfo { 1 index type/stringtype eq {exch cvn exch} if cid_extensions begin dup load 2 index known { 2 copy cid_GetStatusInfo dup null ne { 1 index load 3 index get dup null eq {pop pop cid_UpdateDB} { exch 1 index/Created get eq {exch pop exch pop} {pop cid_UpdateDB} ifelse } ifelse } {pop cid_UpdateDB} ifelse } {cid_UpdateDB} ifelse end }bind def end } if ct_Level2? {end setglobal} if /ct_UseNativeCapability? systemdict/composefont known def /ct_MakeOCF 35 dict def /ct_Vars 25 dict def /ct_GlyphDirProcs 6 dict def /ct_BuildCharDict 15 dict dup begin /charcode 2 string def /dst_string 1500 string def /nullstring()def /usewidths? true def end def ct_Level2?{setglobal}{pop}ifelse ct_GlyphDirProcs begin /GetGlyphDirectory { systemdict/languagelevel known {pop/CIDFont findresource/GlyphDirectory get} { 1 index/CIDFont findresource/GlyphDirectory get dup type/dicttype eq { dup dup maxlength exch length sub 2 index lt { dup length 2 index add dict copy 2 index /CIDFont findresource/GlyphDirectory 2 index put } if } if exch pop exch pop } ifelse + }def /+ { systemdict/languagelevel known { currentglobal false setglobal 3 dict begin /vm exch def } {1 dict begin} ifelse /$ exch def systemdict/languagelevel known { vm setglobal /gvm currentglobal def $ gcheck setglobal } if ?{$ begin}if }def /?{$ type/dicttype eq}def /|{ userdict/Adobe_CoolType_Data known { Adobe_CoolType_Data/AddWidths? known { currentdict Adobe_CoolType_Data begin begin AddWidths? { Adobe_CoolType_Data/CC 3 index put ?{def}{$ 3 1 roll put}ifelse CC charcode exch 1 index 0 2 index 256 idiv put 1 index exch 1 exch 256 mod put stringwidth 2 array astore currentfont/Widths get exch CC exch put } {?{def}{$ 3 1 roll put}ifelse} ifelse end end } {?{def}{$ 3 1 roll put}ifelse} ifelse } {?{def}{$ 3 1 roll put}ifelse} ifelse }def /! { ?{end}if systemdict/languagelevel known {gvm setglobal} if end }def /:{string currentfile exch readstring pop}executeonly def end ct_MakeOCF begin /ct_cHexEncoding [/c00/c01/c02/c03/c04/c05/c06/c07/c08/c09/c0A/c0B/c0C/c0D/c0E/c0F/c10/c11/c12 /c13/c14/c15/c16/c17/c18/c19/c1A/c1B/c1C/c1D/c1E/c1F/c20/c21/c22/c23/c24/c25 /c26/c27/c28/c29/c2A/c2B/c2C/c2D/c2E/c2F/c30/c31/c32/c33/c34/c35/c36/c37/c38 /c39/c3A/c3B/c3C/c3D/c3E/c3F/c40/c41/c42/c43/c44/c45/c46/c47/c48/c49/c4A/c4B /c4C/c4D/c4E/c4F/c50/c51/c52/c53/c54/c55/c56/c57/c58/c59/c5A/c5B/c5C/c5D/c5E /c5F/c60/c61/c62/c63/c64/c65/c66/c67/c68/c69/c6A/c6B/c6C/c6D/c6E/c6F/c70/c71 /c72/c73/c74/c75/c76/c77/c78/c79/c7A/c7B/c7C/c7D/c7E/c7F/c80/c81/c82/c83/c84 /c85/c86/c87/c88/c89/c8A/c8B/c8C/c8D/c8E/c8F/c90/c91/c92/c93/c94/c95/c96/c97 /c98/c99/c9A/c9B/c9C/c9D/c9E/c9F/cA0/cA1/cA2/cA3/cA4/cA5/cA6/cA7/cA8/cA9/cAA /cAB/cAC/cAD/cAE/cAF/cB0/cB1/cB2/cB3/cB4/cB5/cB6/cB7/cB8/cB9/cBA/cBB/cBC/cBD /cBE/cBF/cC0/cC1/cC2/cC3/cC4/cC5/cC6/cC7/cC8/cC9/cCA/cCB/cCC/cCD/cCE/cCF/cD0 /cD1/cD2/cD3/cD4/cD5/cD6/cD7/cD8/cD9/cDA/cDB/cDC/cDD/cDE/cDF/cE0/cE1/cE2/cE3 /cE4/cE5/cE6/cE7/cE8/cE9/cEA/cEB/cEC/cED/cEE/cEF/cF0/cF1/cF2/cF3/cF4/cF5/cF6 /cF7/cF8/cF9/cFA/cFB/cFC/cFD/cFE/cFF]def /ct_CID_STR_SIZE 8000 def /ct_mkocfStr100 100 string def /ct_defaultFontMtx[.001 0 0 .001 0 0]def /ct_1000Mtx[1000 0 0 1000 0 0]def /ct_raise{exch cvx exch errordict exch get exec stop}bind def /ct_reraise {cvx $error/errorname get(Error: )print dup( )cvs print errordict exch get exec stop }bind def /ct_cvnsi { 1 index add 1 sub 1 exch 0 4 1 roll { 2 index exch get exch 8 bitshift add } for exch pop }bind def /ct_GetInterval { Adobe_CoolType_Utility/ct_BuildCharDict get begin /dst_index 0 def dup dst_string length gt {dup string/dst_string exch def} if 1 index ct_CID_STR_SIZE idiv /arrayIndex exch def 2 index arrayIndex get 2 index arrayIndex ct_CID_STR_SIZE mul sub { dup 3 index add 2 index length le { 2 index getinterval dst_string dst_index 2 index putinterval length dst_index add/dst_index exch def exit } { 1 index length 1 index sub dup 4 1 roll getinterval dst_string dst_index 2 index putinterval pop dup dst_index add/dst_index exch def sub /arrayIndex arrayIndex 1 add def 2 index dup length arrayIndex gt {arrayIndex get} { pop exit } ifelse 0 } ifelse } loop pop pop pop dst_string 0 dst_index getinterval end }bind def ct_Level2? { /ct_resourcestatus currentglobal mark true setglobal {/unknowninstancename/Category resourcestatus} stopped {cleartomark setglobal true} {cleartomark currentglobal not exch setglobal} ifelse { { mark 3 1 roll/Category findresource begin ct_Vars/vm currentglobal put ({ResourceStatus}stopped)0()/SubFileDecode filter cvx exec {cleartomark false} {{3 2 roll pop true}{cleartomark false}ifelse} ifelse ct_Vars/vm get setglobal end } } {{resourcestatus}} ifelse bind def /CIDFont/Category ct_resourcestatus {pop pop} { currentglobal true setglobal /Generic/Category findresource dup length dict copy dup/InstanceType/dicttype put /CIDFont exch/Category defineresource pop setglobal } ifelse ct_UseNativeCapability? { /CIDInit/ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo 3 dict dup begin /Registry(Adobe)def /Ordering(Identity)def /Supplement 0 def end def /CMapName/Identity-H def /CMapVersion 1.000 def /CMapType 1 def 1 begincodespacerange <0000><FFFF> endcodespacerange 1 begincidrange <0000><FFFF>0 endcidrange endcmap CMapName currentdict/CMap defineresource pop end end } if } { /ct_Category 2 dict begin /CIDFont 10 dict def /ProcSet 2 dict def currentdict end def /defineresource { ct_Category 1 index 2 copy known { get dup dup maxlength exch length eq { dup length 10 add dict copy ct_Category 2 index 2 index put } if 3 index 3 index put pop exch pop } {pop pop/defineresource/undefined ct_raise} ifelse }bind def /findresource { ct_Category 1 index 2 copy known { get 2 index 2 copy known {get 3 1 roll pop pop} {pop pop/findresource/undefinedresource ct_raise} ifelse } {pop pop/findresource/undefined ct_raise} ifelse }bind def /resourcestatus { ct_Category 1 index 2 copy known { get 2 index known exch pop exch pop { 0 -1 true } { false } ifelse } {pop pop/findresource/undefined ct_raise} ifelse }bind def /ct_resourcestatus/resourcestatus load def } ifelse /ct_CIDInit 2 dict begin /ct_cidfont_stream_init { { dup(Binary)eq { pop null currentfile ct_Level2? { {cid_BYTE_COUNT()/SubFileDecode filter} stopped {pop pop pop} if } if /readstring load exit } if dup(Hex)eq { pop currentfile ct_Level2? { {null exch/ASCIIHexDecode filter/readstring} stopped {pop exch pop(>)exch/readhexstring} if } {(>)exch/readhexstring} ifelse load exit } if /StartData/typecheck ct_raise } loop cid_BYTE_COUNT ct_CID_STR_SIZE le { 2 copy cid_BYTE_COUNT string exch exec pop 1 array dup 3 -1 roll 0 exch put } { cid_BYTE_COUNT ct_CID_STR_SIZE div ceiling cvi dup array exch 2 sub 0 exch 1 exch { 2 copy 5 index ct_CID_STR_SIZE string 6 index exec pop put pop } for 2 index cid_BYTE_COUNT ct_CID_STR_SIZE mod string 3 index exec pop 1 index exch 1 index length 1 sub exch put } ifelse cid_CIDFONT exch/GlyphData exch put 2 index null eq { pop pop pop } { pop/readstring load 1 string exch { 3 copy exec pop dup length 0 eq { pop pop pop pop pop true exit } if 4 index eq { pop pop pop pop false exit } if } loop pop } ifelse }bind def /StartData { mark { currentdict dup/FDArray get 0 get/FontMatrix get 0 get 0.001 eq { dup/CDevProc known not { /CDevProc 1183615869 internaldict/stdCDevProc 2 copy known {get} { pop pop {pop pop pop pop pop 0 -1000 7 index 2 div 880} } ifelse def } if } { /CDevProc { pop pop pop pop pop 0 1 cid_temp/cid_CIDFONT get /FDArray get 0 get /FontMatrix get 0 get div 7 index 2 div 1 index 0.88 mul }def } ifelse /cid_temp 15 dict def cid_temp begin /cid_CIDFONT exch def 3 copy pop dup/cid_BYTE_COUNT exch def 0 gt { ct_cidfont_stream_init FDArray { /Private get dup/SubrMapOffset known { begin /Subrs SubrCount array def Subrs SubrMapOffset SubrCount SDBytes ct_Level2? { currentdict dup/SubrMapOffset undef dup/SubrCount undef /SDBytes undef } if end /cid_SD_BYTES exch def /cid_SUBR_COUNT exch def /cid_SUBR_MAP_OFFSET exch def /cid_SUBRS exch def cid_SUBR_COUNT 0 gt { GlyphData cid_SUBR_MAP_OFFSET cid_SD_BYTES ct_GetInterval 0 cid_SD_BYTES ct_cvnsi 0 1 cid_SUBR_COUNT 1 sub { exch 1 index 1 add cid_SD_BYTES mul cid_SUBR_MAP_OFFSET add GlyphData exch cid_SD_BYTES ct_GetInterval 0 cid_SD_BYTES ct_cvnsi cid_SUBRS 4 2 roll GlyphData exch 4 index 1 index sub ct_GetInterval dup length string copy put } for pop } if } {pop} ifelse } forall } if cleartomark pop pop end CIDFontName currentdict/CIDFont defineresource pop end end } stopped {cleartomark/StartData ct_reraise} if }bind def currentdict end def /ct_saveCIDInit { /CIDInit/ProcSet ct_resourcestatus {true} {/CIDInitC/ProcSet ct_resourcestatus} ifelse { pop pop /CIDInit/ProcSet findresource ct_UseNativeCapability? {pop null} {/CIDInit ct_CIDInit/ProcSet defineresource pop} ifelse } {/CIDInit ct_CIDInit/ProcSet defineresource pop null} ifelse ct_Vars exch/ct_oldCIDInit exch put }bind def /ct_restoreCIDInit { ct_Vars/ct_oldCIDInit get dup null ne {/CIDInit exch/ProcSet defineresource pop} {pop} ifelse }bind def /ct_BuildCharSetUp { 1 index begin CIDFont begin Adobe_CoolType_Utility/ct_BuildCharDict get begin /ct_dfCharCode exch def /ct_dfDict exch def CIDFirstByte ct_dfCharCode add dup CIDCount ge {pop 0} if /cid exch def { GlyphDirectory cid 2 copy known {get} {pop pop nullstring} ifelse dup length FDBytes sub 0 gt { dup FDBytes 0 ne {0 FDBytes ct_cvnsi} {pop 0} ifelse /fdIndex exch def dup length FDBytes sub FDBytes exch getinterval /charstring exch def exit } { pop cid 0 eq {/charstring nullstring def exit} if /cid 0 def } ifelse } loop }def /ct_SetCacheDevice { 0 0 moveto dup stringwidth 3 -1 roll true charpath pathbbox 0 -1000 7 index 2 div 880 setcachedevice2 0 0 moveto }def /ct_CloneSetCacheProc { 1 eq { stringwidth pop -2 div -880 0 -1000 setcharwidth moveto } { usewidths? { currentfont/Widths get cid 2 copy known {get exch pop aload pop} {pop pop stringwidth} ifelse } {stringwidth} ifelse setcharwidth 0 0 moveto } ifelse }def /ct_Type3ShowCharString { ct_FDDict fdIndex 2 copy known {get} { currentglobal 3 1 roll 1 index gcheck setglobal ct_Type1FontTemplate dup maxlength dict copy begin FDArray fdIndex get dup/FontMatrix 2 copy known {get} {pop pop ct_defaultFontMtx} ifelse /FontMatrix exch dup length array copy def /Private get /Private exch def /Widths rootfont/Widths get def /CharStrings 1 dict dup/.notdef <d841272cf18f54fc13>dup length string copy put def currentdict end /ct_Type1Font exch definefont dup 5 1 roll put setglobal } ifelse dup/CharStrings get 1 index/Encoding get ct_dfCharCode get charstring put rootfont/WMode 2 copy known {get} {pop pop 0} ifelse exch 1000 scalefont setfont ct_str1 0 ct_dfCharCode put ct_str1 exch ct_dfSetCacheProc ct_SyntheticBold { currentpoint ct_str1 show newpath moveto ct_str1 true charpath ct_StrokeWidth setlinewidth stroke } {ct_str1 show} ifelse }def /ct_Type4ShowCharString { ct_dfDict ct_dfCharCode charstring FDArray fdIndex get dup/FontMatrix get dup ct_defaultFontMtx ct_matrixeq not {ct_1000Mtx matrix concatmatrix concat} {pop} ifelse /Private get Adobe_CoolType_Utility/ct_Level2? get not { ct_dfDict/Private 3 -1 roll {put} 1183615869 internaldict/superexec get exec } if 1183615869 internaldict Adobe_CoolType_Utility/ct_Level2? get {1 index} {3 index/Private get mark 6 1 roll} ifelse dup/RunInt known {/RunInt get} {pop/CCRun} ifelse get exec Adobe_CoolType_Utility/ct_Level2? get not {cleartomark} if }bind def /ct_BuildCharIncremental { { Adobe_CoolType_Utility/ct_MakeOCF get begin ct_BuildCharSetUp ct_ShowCharString } stopped {stop} if end end end end }bind def /BaseFontNameStr(BF00)def /ct_Type1FontTemplate 14 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0]def /FontBBox [-250 -250 1250 1250]def /Encoding ct_cHexEncoding def /PaintType 0 def currentdict end def /BaseFontTemplate 11 dict begin /FontMatrix [0.001 0 0 0.001 0 0]def /FontBBox [-250 -250 1250 1250]def /Encoding ct_cHexEncoding def /BuildChar/ct_BuildCharIncremental load def ct_Clone? { /FontType 3 def /ct_ShowCharString/ct_Type3ShowCharString load def /ct_dfSetCacheProc/ct_CloneSetCacheProc load def /ct_SyntheticBold false def /ct_StrokeWidth 1 def } { /FontType 4 def /Private 1 dict dup/lenIV 4 put def /CharStrings 1 dict dup/.notdef<d841272cf18f54fc13>put def /PaintType 0 def /ct_ShowCharString/ct_Type4ShowCharString load def } ifelse /ct_str1 1 string def currentdict end def /BaseFontDictSize BaseFontTemplate length 5 add def /ct_matrixeq { true 0 1 5 { dup 4 index exch get exch 3 index exch get eq and dup not {exit} if } for exch pop exch pop }bind def /ct_makeocf { 15 dict begin exch/WMode exch def exch/FontName exch def /FontType 0 def /FMapType 2 def dup/FontMatrix known {dup/FontMatrix get/FontMatrix exch def} {/FontMatrix matrix def} ifelse /bfCount 1 index/CIDCount get 256 idiv 1 add dup 256 gt{pop 256}if def /Encoding 256 array 0 1 bfCount 1 sub{2 copy dup put pop}for bfCount 1 255{2 copy bfCount put pop}for def /FDepVector bfCount dup 256 lt{1 add}if array def BaseFontTemplate BaseFontDictSize dict copy begin /CIDFont exch def CIDFont/FontBBox known {CIDFont/FontBBox get/FontBBox exch def} if CIDFont/CDevProc known {CIDFont/CDevProc get/CDevProc exch def} if currentdict end BaseFontNameStr 3(0)putinterval 0 1 bfCount dup 256 eq{1 sub}if { FDepVector exch 2 index BaseFontDictSize dict copy begin dup/CIDFirstByte exch 256 mul def FontType 3 eq {/ct_FDDict 2 dict def} if currentdict end 1 index 16 BaseFontNameStr 2 2 getinterval cvrs pop BaseFontNameStr exch definefont put } for ct_Clone? {/Widths 1 index/CIDFont get/GlyphDirectory get length dict def} if FontName currentdict end definefont ct_Clone? { gsave dup 1000 scalefont setfont ct_BuildCharDict begin /usewidths? false def currentfont/Widths get begin exch/CIDFont get/GlyphDirectory get { pop dup charcode exch 1 index 0 2 index 256 idiv put 1 index exch 1 exch 256 mod put stringwidth 2 array astore def } forall end /usewidths? true def end grestore } {exch pop} ifelse }bind def currentglobal true setglobal /ct_ComposeFont { ct_UseNativeCapability? { 2 index/CMap ct_resourcestatus {pop pop exch pop} { /CIDInit/ProcSet findresource begin 12 dict begin begincmap /CMapName 3 index def /CMapVersion 1.000 def /CMapType 1 def exch/WMode exch def /CIDSystemInfo 3 dict dup begin /Registry(Adobe)def /Ordering CMapName ct_mkocfStr100 cvs (Adobe-)search { pop pop (-)search { dup length string copy exch pop exch pop } {pop(Identity)} ifelse } {pop (Identity)} ifelse def /Supplement 0 def end def 1 begincodespacerange <0000><FFFF> endcodespacerange 1 begincidrange <0000><FFFF>0 endcidrange endcmap CMapName currentdict/CMap defineresource pop end end } ifelse composefont } { 3 2 roll pop 0 get/CIDFont findresource ct_makeocf } ifelse }bind def setglobal /ct_MakeIdentity { ct_UseNativeCapability? { 1 index/CMap ct_resourcestatus {pop pop} { /CIDInit/ProcSet findresource begin 12 dict begin begincmap /CMapName 2 index def /CMapVersion 1.000 def /CMapType 1 def /CIDSystemInfo 3 dict dup begin /Registry(Adobe)def /Ordering CMapName ct_mkocfStr100 cvs (Adobe-)search { pop pop (-)search {dup length string copy exch pop exch pop} {pop(Identity)} ifelse } {pop(Identity)} ifelse def /Supplement 0 def end def 1 begincodespacerange <0000><FFFF> endcodespacerange 1 begincidrange <0000><FFFF>0 endcidrange endcmap CMapName currentdict/CMap defineresource pop end end } ifelse composefont } { exch pop 0 get/CIDFont findresource ct_makeocf } ifelse }bind def currentdict readonly pop end end %%EndResource setglobal %%BeginResource: procset Adobe_CoolType_Utility_T42 1.0 0 %%Copyright: Copyright 1987-2004 Adobe Systems Incorporated. %%Version: 1.0 0 userdict/ct_T42Dict 15 dict put ct_T42Dict begin /Is2015? { version cvi 2015 ge }bind def /AllocGlyphStorage { Is2015? { pop } { {string}forall }ifelse }bind def /Type42DictBegin { 25 dict begin /FontName exch def /CharStrings 256 dict begin /.notdef 0 def currentdict end def /Encoding exch def /PaintType 0 def /FontType 42 def /FontMatrix[1 0 0 1 0 0]def 4 array astore cvx/FontBBox exch def /sfnts }bind def /Type42DictEnd { currentdict dup/FontName get exch definefont end ct_T42Dict exch dup/FontName get exch put }bind def /RD{string currentfile exch readstring pop}executeonly def /PrepFor2015 { Is2015? { /GlyphDirectory 16 dict def sfnts 0 get dup 2 index (glyx) putinterval 2 index (locx) putinterval pop pop } { pop pop }ifelse }bind def /AddT42Char { Is2015? { /GlyphDirectory get begin def end pop pop } { /sfnts get 4 index get 3 index 2 index putinterval pop pop pop pop }ifelse }bind def /T0AddT42Mtx2 { /CIDFont findresource/Metrics2 get begin def end }bind def end %%EndResource currentglobal true setglobal %%BeginFile: MMFauxFont.prc %%Copyright: Copyright 1987-2001 Adobe Systems Incorporated. %%All Rights Reserved. userdict /ct_EuroDict 10 dict put ct_EuroDict begin /ct_CopyFont { { 1 index /FID ne {def} {pop pop} ifelse} forall } def /ct_GetGlyphOutline { gsave initmatrix newpath exch findfont dup length 1 add dict begin ct_CopyFont /Encoding Encoding dup length array copy dup 4 -1 roll 0 exch put def currentdict end /ct_EuroFont exch definefont 1000 scalefont setfont 0 0 moveto [ <00> stringwidth <00> false charpath pathbbox [ {/m cvx} {/l cvx} {/c cvx} {/cp cvx} pathforall grestore counttomark 8 add } def /ct_MakeGlyphProc { ] cvx /ct_PSBuildGlyph cvx ] cvx } def /ct_PSBuildGlyph { gsave 8 -1 roll pop 7 1 roll 6 -2 roll ct_FontMatrix transform 6 2 roll 4 -2 roll ct_FontMatrix transform 4 2 roll ct_FontMatrix transform currentdict /PaintType 2 copy known {get 2 eq}{pop pop false} ifelse dup 9 1 roll { currentdict /StrokeWidth 2 copy known { get 2 div 0 ct_FontMatrix dtransform pop 5 1 roll 4 -1 roll 4 index sub 4 1 roll 3 -1 roll 4 index sub 3 1 roll exch 4 index add exch 4 index add 5 -1 roll pop } { pop pop } ifelse } if setcachedevice ct_FontMatrix concat ct_PSPathOps begin exec end { currentdict /StrokeWidth 2 copy known { get } { pop pop 0 } ifelse setlinewidth stroke } { fill } ifelse grestore } def /ct_PSPathOps 4 dict dup begin /m {moveto} def /l {lineto} def /c {curveto} def /cp {closepath} def end def /ct_matrix1000 [1000 0 0 1000 0 0] def /ct_AddGlyphProc { 2 index findfont dup length 4 add dict begin ct_CopyFont /CharStrings CharStrings dup length 1 add dict copy begin 3 1 roll def currentdict end def /ct_FontMatrix ct_matrix1000 FontMatrix matrix concatmatrix def /ct_PSBuildGlyph /ct_PSBuildGlyph load def /ct_PSPathOps /ct_PSPathOps load def currentdict end definefont pop } def systemdict /languagelevel known { /ct_AddGlyphToPrinterFont { 2 copy ct_GetGlyphOutline 3 add -1 roll restore ct_MakeGlyphProc ct_AddGlyphProc } def } { /ct_AddGlyphToPrinterFont { pop pop restore Adobe_CTFauxDict /$$$FONTNAME get /Euro Adobe_CTFauxDict /$$$SUBSTITUTEBASE get ct_EuroDict exch get ct_AddGlyphProc } def } ifelse /AdobeSansMM { 556 0 24 -19 541 703 { 541 628 m 510 669 442 703 354 703 c 201 703 117 607 101 444 c 50 444 l 25 372 l 97 372 l 97 301 l 49 301 l 24 229 l 103 229 l 124 67 209 -19 350 -19 c 435 -19 501 25 509 32 c 509 131 l 492 105 417 60 343 60 c 267 60 204 127 197 229 c 406 229 l 430 301 l 191 301 l 191 372 l 455 372 l 479 444 l 194 444 l 201 531 245 624 348 624 c 433 624 484 583 509 534 c cp 556 0 m } ct_PSBuildGlyph } def /AdobeSerifMM { 500 0 10 -12 484 692 { 347 298 m 171 298 l 170 310 170 322 170 335 c 170 362 l 362 362 l 374 403 l 172 403 l 184 580 244 642 308 642 c 380 642 434 574 457 457 c 481 462 l 474 691 l 449 691 l 433 670 429 657 410 657 c 394 657 360 692 299 692 c 204 692 94 604 73 403 c 22 403 l 10 362 l 70 362 l 69 352 69 341 69 330 c 69 319 69 308 70 298 c 22 298 l 10 257 l 73 257 l 97 57 216 -12 295 -12 c 364 -12 427 25 484 123 c 458 142 l 425 101 384 37 316 37 c 256 37 189 84 173 257 c 335 257 l cp 500 0 m } ct_PSBuildGlyph } def end %%EndFile setglobal Adobe_CoolType_Core begin /$Oblique SetSubstituteStrategy end %%BeginResource: procset Adobe_AGM_Image 1.0 0
-%%Version: 1.0 0
-%%Copyright: Copyright(C)2000-2006 Adobe Systems, Inc. All Rights Reserved.
-systemdict/setpacking known
-{
- currentpacking
- true setpacking
-}if
-userdict/Adobe_AGM_Image 71 dict dup begin put
-/Adobe_AGM_Image_Id/Adobe_AGM_Image_1.0_0 def
-/nd{
- null def
-}bind def
-/AGMIMG_&image nd
-/AGMIMG_&colorimage nd
-/AGMIMG_&imagemask nd
-/AGMIMG_mbuf()def
-/AGMIMG_ybuf()def
-/AGMIMG_kbuf()def
-/AGMIMG_c 0 def
-/AGMIMG_m 0 def
-/AGMIMG_y 0 def
-/AGMIMG_k 0 def
-/AGMIMG_tmp nd
-/AGMIMG_imagestring0 nd
-/AGMIMG_imagestring1 nd
-/AGMIMG_imagestring2 nd
-/AGMIMG_imagestring3 nd
-/AGMIMG_imagestring4 nd
-/AGMIMG_imagestring5 nd
-/AGMIMG_cnt nd
-/AGMIMG_fsave nd
-/AGMIMG_colorAry nd
-/AGMIMG_override nd
-/AGMIMG_name nd
-/AGMIMG_maskSource nd
-/AGMIMG_flushfilters nd
-/invert_image_samples nd
-/knockout_image_samples nd
-/img nd
-/sepimg nd
-/devnimg nd
-/idximg nd
-/ds
-{
- Adobe_AGM_Core begin
- Adobe_AGM_Image begin
- /AGMIMG_&image systemdict/image get def
- /AGMIMG_&imagemask systemdict/imagemask get def
- /colorimage where{
- pop
- /AGMIMG_&colorimage/colorimage ldf
- }if
- end
- end
-}def
-/ps
-{
- Adobe_AGM_Image begin
- /AGMIMG_ccimage_exists{/customcolorimage where
- {
- pop
- /Adobe_AGM_OnHost_Seps where
- {
- pop false
- }{
- /Adobe_AGM_InRip_Seps where
- {
- pop false
- }{
- true
- }ifelse
- }ifelse
- }{
- false
- }ifelse
- }bdf
- level2{
- /invert_image_samples
- {
- Adobe_AGM_Image/AGMIMG_tmp Decode length ddf
- /Decode[Decode 1 get Decode 0 get]def
- }def
- /knockout_image_samples
- {
- Operator/imagemask ne{
- /Decode[1 1]def
- }if
- }def
- }{
- /invert_image_samples
- {
- {1 exch sub}currenttransfer addprocs settransfer
- }def
- /knockout_image_samples
- {
- {pop 1}currenttransfer addprocs settransfer
- }def
- }ifelse
- /img/imageormask ldf
- /sepimg/sep_imageormask ldf
- /devnimg/devn_imageormask ldf
- /idximg/indexed_imageormask ldf
- /_ctype 7 def
- currentdict{
- dup xcheck 1 index type dup/arraytype eq exch/packedarraytype eq or and{
- bind
- }if
- def
- }forall
-}def
-/pt
-{
- end
-}def
-/dt
-{
-}def
-/AGMIMG_flushfilters
-{
- dup type/arraytype ne
- {1 array astore}if
- dup 0 get currentfile ne
- {dup 0 get flushfile}if
- {
- dup type/filetype eq
- {
- dup status 1 index currentfile ne and
- {closefile}
- {pop}
- ifelse
- }{pop}ifelse
- }forall
-}def
-/AGMIMG_init_common
-{
- currentdict/T known{/ImageType/T ldf currentdict/T undef}if
- currentdict/W known{/Width/W ldf currentdict/W undef}if
- currentdict/H known{/Height/H ldf currentdict/H undef}if
- currentdict/M known{/ImageMatrix/M ldf currentdict/M undef}if
- currentdict/BC known{/BitsPerComponent/BC ldf currentdict/BC undef}if
- currentdict/D known{/Decode/D ldf currentdict/D undef}if
- currentdict/DS known{/DataSource/DS ldf currentdict/DS undef}if
- currentdict/O known{
- /Operator/O load 1 eq{
- /imagemask
- }{
- /O load 2 eq{
- /image
- }{
- /colorimage
- }ifelse
- }ifelse
- def
- currentdict/O undef
- }if
- currentdict/HSCI known{/HostSepColorImage/HSCI ldf currentdict/HSCI undef}if
- currentdict/MD known{/MultipleDataSources/MD ldf currentdict/MD undef}if
- currentdict/I known{/Interpolate/I ldf currentdict/I undef}if
- currentdict/SI known{/SkipImageProc/SI ldf currentdict/SI undef}if
- /DataSource load xcheck not{
- DataSource type/arraytype eq{
- DataSource 0 get type/filetype eq{
- /_Filters DataSource def
- currentdict/MultipleDataSources known not{
- /DataSource DataSource dup length 1 sub get def
- }if
- }if
- }if
- currentdict/MultipleDataSources known not{
- /MultipleDataSources DataSource type/arraytype eq{
- DataSource length 1 gt
- }
- {false}ifelse def
- }if
- }if
- /NComponents Decode length 2 div def
- currentdict/SkipImageProc known not{/SkipImageProc{false}def}if
-}bdf
-/imageormask_sys
-{
- begin
- AGMIMG_init_common
- save mark
- level2{
- currentdict
- Operator/imagemask eq{
- AGMIMG_&imagemask
- }{
- use_mask{
- process_mask AGMIMG_&image
- }{
- AGMIMG_&image
- }ifelse
- }ifelse
- }{
- Width Height
- Operator/imagemask eq{
- Decode 0 get 1 eq Decode 1 get 0 eq and
- ImageMatrix/DataSource load
- AGMIMG_&imagemask
- }{
- BitsPerComponent ImageMatrix/DataSource load
- AGMIMG_&image
- }ifelse
- }ifelse
- currentdict/_Filters known{_Filters AGMIMG_flushfilters}if
- cleartomark restore
- end
-}def
-/overprint_plate
-{
- currentoverprint{
- 0 get dup type/nametype eq{
- dup/DeviceGray eq{
- pop AGMCORE_black_plate not
- }{
- /DeviceCMYK eq{
- AGMCORE_is_cmyk_sep not
- }if
- }ifelse
- }{
- false exch
- {
- AGMOHS_sepink eq or
- }forall
- not
- }ifelse
- }{
- pop false
- }ifelse
-}def
-/process_mask
-{
- level3{
- dup begin
- /ImageType 1 def
- end
- 4 dict begin
- /DataDict exch def
- /ImageType 3 def
- /InterleaveType 3 def
- /MaskDict 9 dict begin
- /ImageType 1 def
- /Width DataDict dup/MaskWidth known{/MaskWidth}{/Width}ifelse get def
- /Height DataDict dup/MaskHeight known{/MaskHeight}{/Height}ifelse get def
- /ImageMatrix[Width 0 0 Height neg 0 Height]def
- /NComponents 1 def
- /BitsPerComponent 1 def
- /Decode DataDict dup/MaskD known{/MaskD}{[1 0]}ifelse get def
- /DataSource Adobe_AGM_Core/AGMIMG_maskSource get def
- currentdict end def
- currentdict end
- }if
-}def
-/use_mask
-{
- dup/Mask known {dup/Mask get}{false}ifelse
-}def
-/imageormask
-{
- begin
- AGMIMG_init_common
- SkipImageProc{
- currentdict consumeimagedata
- }
- {
- save mark
- level2 AGMCORE_host_sep not and{
- currentdict
- Operator/imagemask eq DeviceN_PS2 not and{
- imagemask
- }{
- AGMCORE_in_rip_sep currentoverprint and currentcolorspace 0 get/DeviceGray eq and{
- [/Separation/Black/DeviceGray{}]setcolorspace
- /Decode[Decode 1 get Decode 0 get]def
- }if
- use_mask{
- process_mask image
- }{
- DeviceN_NoneName DeviceN_PS2 Indexed_DeviceN level3 not and or or AGMCORE_in_rip_sep and
- {
- Names convert_to_process not{
- 2 dict begin
- /imageDict xdf
- /names_index 0 def
- gsave
- imageDict write_image_file{
- Names{
- dup(None)ne{
- [/Separation 3 -1 roll/DeviceGray{1 exch sub}]setcolorspace
- Operator imageDict read_image_file
- names_index 0 eq{true setoverprint}if
- /names_index names_index 1 add def
- }{
- pop
- }ifelse
- }forall
- close_image_file
- }if
- grestore
- end
- }{
- Operator/imagemask eq{
- imagemask
- }{
- image
- }ifelse
- }ifelse
- }{
- Operator/imagemask eq{
- imagemask
- }{
- image
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- }{
- Width Height
- Operator/imagemask eq{
- Decode 0 get 1 eq Decode 1 get 0 eq and
- ImageMatrix/DataSource load
- /Adobe_AGM_OnHost_Seps where{
- pop imagemask
- }{
- currentgray 1 ne{
- currentdict imageormask_sys
- }{
- currentoverprint not{
- 1 AGMCORE_&setgray
- currentdict imageormask_sys
- }{
- currentdict ignoreimagedata
- }ifelse
- }ifelse
- }ifelse
- }{
- BitsPerComponent ImageMatrix
- MultipleDataSources{
- 0 1 NComponents 1 sub{
- DataSource exch get
- }for
- }{
- /DataSource load
- }ifelse
- Operator/colorimage eq{
- AGMCORE_host_sep{
- MultipleDataSources level2 or NComponents 4 eq and{
- AGMCORE_is_cmyk_sep{
- MultipleDataSources{
- /DataSource DataSource 0 get xcheck
- {
- [
- DataSource 0 get/exec cvx
- DataSource 1 get/exec cvx
- DataSource 2 get/exec cvx
- DataSource 3 get/exec cvx
- /AGMCORE_get_ink_data cvx
- ]cvx
- }{
- DataSource aload pop AGMCORE_get_ink_data
- }ifelse def
- }{
- /DataSource
- Width BitsPerComponent mul 7 add 8 idiv Height mul 4 mul
- /DataSource load
- filter_cmyk 0()/SubFileDecode filter def
- }ifelse
- /Decode[Decode 0 get Decode 1 get]def
- /MultipleDataSources false def
- /NComponents 1 def
- /Operator/image def
- invert_image_samples
- 1 AGMCORE_&setgray
- currentdict imageormask_sys
- }{
- currentoverprint not Operator/imagemask eq and{
- 1 AGMCORE_&setgray
- currentdict imageormask_sys
- }{
- currentdict ignoreimagedata
- }ifelse
- }ifelse
- }{
- MultipleDataSources NComponents AGMIMG_&colorimage
- }ifelse
- }{
- true NComponents colorimage
- }ifelse
- }{
- Operator/image eq{
- AGMCORE_host_sep{
- /DoImage true def
- currentdict/HostSepColorImage known{HostSepColorImage not}{false}ifelse
- {
- AGMCORE_black_plate not Operator/imagemask ne and{
- /DoImage false def
- currentdict ignoreimagedata
- }if
- }if
- 1 AGMCORE_&setgray
- DoImage
- {currentdict imageormask_sys}if
- }{
- use_mask{
- process_mask image
- }{
- image
- }ifelse
- }ifelse
- }{
- Operator/knockout eq{
- pop pop pop pop pop
- currentcolorspace overprint_plate not{
- knockout_unitsq
- }if
- }if
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- cleartomark restore
- }ifelse
- currentdict/_Filters known{_Filters AGMIMG_flushfilters}if
- end
-}def
-/sep_imageormask
-{
- /sep_colorspace_dict AGMCORE_gget begin
- CSA map_csa
- begin
- AGMIMG_init_common
- SkipImageProc{
- currentdict consumeimagedata
- }{
- save mark
- AGMCORE_avoid_L2_sep_space{
- /Decode[Decode 0 get 255 mul Decode 1 get 255 mul]def
- }if
- AGMIMG_ccimage_exists
- MappedCSA 0 get/DeviceCMYK eq and
- currentdict/Components known and
- Name()ne and
- Name(All)ne and
- Operator/image eq and
- AGMCORE_producing_seps not and
- level2 not and
- {
- Width Height BitsPerComponent ImageMatrix
- [
- /DataSource load/exec cvx
- {
- 0 1 2 index length 1 sub{
- 1 index exch
- 2 copy get 255 xor put
- }for
- }/exec cvx
- ]cvx bind
- MappedCSA 0 get/DeviceCMYK eq{
- Components aload pop
- }{
- 0 0 0 Components aload pop 1 exch sub
- }ifelse
- Name findcmykcustomcolor
- customcolorimage
- }{
- AGMCORE_producing_seps not{
- level2{
- //Adobe_AGM_Core/AGMCORE_pattern_paint_type get 2 ne AGMCORE_avoid_L2_sep_space not and currentcolorspace 0 get/Separation ne and{
- [/Separation Name MappedCSA sep_proc_name exch dup 0 get 15 string cvs(/Device)anchorsearch{pop pop 0 get}{pop}ifelse exch load]setcolorspace_opt
- /sep_tint AGMCORE_gget setcolor
- }if
- currentdict imageormask
- }{
- currentdict
- Operator/imagemask eq{
- imageormask
- }{
- sep_imageormask_lev1
- }ifelse
- }ifelse
- }{
- AGMCORE_host_sep{
- Operator/knockout eq{
- currentdict/ImageMatrix get concat
- knockout_unitsq
- }{
- currentgray 1 ne{
- AGMCORE_is_cmyk_sep Name(All)ne and{
- level2{
- Name AGMCORE_IsSeparationAProcessColor
- {
- Operator/imagemask eq{
- //Adobe_AGM_Core/AGMCORE_pattern_paint_type get 2 ne{
- /sep_tint AGMCORE_gget 1 exch sub AGMCORE_&setcolor
- }if
- }{
- invert_image_samples
- }ifelse
- }{
- //Adobe_AGM_Core/AGMCORE_pattern_paint_type get 2 ne{
- [/Separation Name[/DeviceGray]
- {
- sep_colorspace_proc AGMCORE_get_ink_data
- 1 exch sub
- }bind
- ]AGMCORE_&setcolorspace
- /sep_tint AGMCORE_gget AGMCORE_&setcolor
- }if
- }ifelse
- currentdict imageormask_sys
- }{
- currentdict
- Operator/imagemask eq{
- imageormask_sys
- }{
- sep_image_lev1_sep
- }ifelse
- }ifelse
- }{
- Operator/imagemask ne{
- invert_image_samples
- }if
- currentdict imageormask_sys
- }ifelse
- }{
- currentoverprint not Name(All)eq or Operator/imagemask eq and{
- currentdict imageormask_sys
- }{
- currentoverprint not
- {
- gsave
- knockout_unitsq
- grestore
- }if
- currentdict consumeimagedata
- }ifelse
- }ifelse
- }ifelse
- }{
- //Adobe_AGM_Core/AGMCORE_pattern_paint_type get 2 ne{
- currentcolorspace 0 get/Separation ne{
- [/Separation Name MappedCSA sep_proc_name exch 0 get exch load]setcolorspace_opt
- /sep_tint AGMCORE_gget setcolor
- }if
- }if
- currentoverprint
- MappedCSA 0 get/DeviceCMYK eq and
- Name AGMCORE_IsSeparationAProcessColor not and
- //Adobe_AGM_Core/AGMCORE_pattern_paint_type get 2 ne{Name inRip_spot_has_ink not and}{false}ifelse
- Name(All)ne and{
- imageormask_l2_overprint
- }{
- currentdict imageormask
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- cleartomark restore
- }ifelse
- currentdict/_Filters known{_Filters AGMIMG_flushfilters}if
- end
- end
-}def
-/colorSpaceElemCnt
-{
- mark currentcolor counttomark dup 2 add 1 roll cleartomark
-}bdf
-/devn_sep_datasource
-{
- 1 dict begin
- /dataSource xdf
- [
- 0 1 dataSource length 1 sub{
- dup currentdict/dataSource get/exch cvx/get cvx/exec cvx
- /exch cvx names_index/ne cvx[/pop cvx]cvx/if cvx
- }for
- ]cvx bind
- end
-}bdf
-/devn_alt_datasource
-{
- 11 dict begin
- /convProc xdf
- /origcolorSpaceElemCnt xdf
- /origMultipleDataSources xdf
- /origBitsPerComponent xdf
- /origDecode xdf
- /origDataSource xdf
- /dsCnt origMultipleDataSources{origDataSource length}{1}ifelse def
- /DataSource origMultipleDataSources
- {
- [
- BitsPerComponent 8 idiv origDecode length 2 idiv mul string
- 0 1 origDecode length 2 idiv 1 sub
- {
- dup 7 mul 1 add index exch dup BitsPerComponent 8 idiv mul exch
- origDataSource exch get 0()/SubFileDecode filter
- BitsPerComponent 8 idiv string/readstring cvx/pop cvx/putinterval cvx
- }for
- ]bind cvx
- }{origDataSource}ifelse 0()/SubFileDecode filter def
- [
- origcolorSpaceElemCnt string
- 0 2 origDecode length 2 sub
- {
- dup origDecode exch get dup 3 -1 roll 1 add origDecode exch get exch sub 2 BitsPerComponent exp 1 sub div
- 1 BitsPerComponent 8 idiv{DataSource/read cvx/not cvx{0}/if cvx/mul cvx}repeat/mul cvx/add cvx
- }for
- /convProc load/exec cvx
- origcolorSpaceElemCnt 1 sub -1 0
- {
- /dup cvx 2/add cvx/index cvx
- 3 1/roll cvx/exch cvx 255/mul cvx/cvi cvx/put cvx
- }for
- ]bind cvx 0()/SubFileDecode filter
- end
-}bdf
-/devn_imageormask
-{
- /devicen_colorspace_dict AGMCORE_gget begin
- CSA map_csa
- 2 dict begin
- dup
- /srcDataStrs[3 -1 roll begin
- AGMIMG_init_common
- currentdict/MultipleDataSources known{MultipleDataSources{DataSource length}{1}ifelse}{1}ifelse
- {
- Width Decode length 2 div mul cvi
- {
- dup 65535 gt{1 add 2 div cvi}{exit}ifelse
- }loop
- string
- }repeat
- end]def
- /dstDataStr srcDataStrs 0 get length string def
- begin
- AGMIMG_init_common
- SkipImageProc{
- currentdict consumeimagedata
- }{
- save mark
- AGMCORE_producing_seps not{
- level3 not{
- Operator/imagemask ne{
- /DataSource[[
- DataSource Decode BitsPerComponent currentdict/MultipleDataSources known{MultipleDataSources}{false}ifelse
- colorSpaceElemCnt/devicen_colorspace_dict AGMCORE_gget/TintTransform get
- devn_alt_datasource 1/string cvx/readstring cvx/pop cvx]cvx colorSpaceElemCnt 1 sub{dup}repeat]def
- /MultipleDataSources true def
- /Decode colorSpaceElemCnt[exch{0 1}repeat]def
- }if
- }if
- currentdict imageormask
- }{
- AGMCORE_host_sep{
- Names convert_to_process{
- CSA get_csa_by_name 0 get/DeviceCMYK eq{
- /DataSource
- Width BitsPerComponent mul 7 add 8 idiv Height mul 4 mul
- DataSource Decode BitsPerComponent currentdict/MultipleDataSources known{MultipleDataSources}{false}ifelse
- 4/devicen_colorspace_dict AGMCORE_gget/TintTransform get
- devn_alt_datasource
- filter_cmyk 0()/SubFileDecode filter def
- /MultipleDataSources false def
- /Decode[1 0]def
- /DeviceGray setcolorspace
- currentdict imageormask_sys
- }{
- AGMCORE_report_unsupported_color_space
- AGMCORE_black_plate{
- /DataSource
- DataSource Decode BitsPerComponent currentdict/MultipleDataSources known{MultipleDataSources}{false}ifelse
- CSA get_csa_by_name 0 get/DeviceRGB eq{3}{1}ifelse/devicen_colorspace_dict AGMCORE_gget/TintTransform get
- devn_alt_datasource
- /MultipleDataSources false def
- /Decode colorSpaceElemCnt[exch{0 1}repeat]def
- currentdict imageormask_sys
- }{
- gsave
- knockout_unitsq
- grestore
- currentdict consumeimagedata
- }ifelse
- }ifelse
- }
- {
- /devicen_colorspace_dict AGMCORE_gget/names_index known{
- Operator/imagemask ne{
- MultipleDataSources{
- /DataSource[DataSource devn_sep_datasource/exec cvx]cvx def
- /MultipleDataSources false def
- }{
- /DataSource/DataSource load dstDataStr srcDataStrs 0 get filter_devn def
- }ifelse
- invert_image_samples
- }if
- currentdict imageormask_sys
- }{
- currentoverprint not Operator/imagemask eq and{
- currentdict imageormask_sys
- }{
- currentoverprint not
- {
- gsave
- knockout_unitsq
- grestore
- }if
- currentdict consumeimagedata
- }ifelse
- }ifelse
- }ifelse
- }{
- currentdict imageormask
- }ifelse
- }ifelse
- cleartomark restore
- }ifelse
- currentdict/_Filters known{_Filters AGMIMG_flushfilters}if
- end
- end
- end
-}def
-/imageormask_l2_overprint
-{
- currentdict
- currentcmykcolor add add add 0 eq{
- currentdict consumeimagedata
- }{
- level3{
- currentcmykcolor
- /AGMIMG_k xdf
- /AGMIMG_y xdf
- /AGMIMG_m xdf
- /AGMIMG_c xdf
- Operator/imagemask eq{
- [/DeviceN[
- AGMIMG_c 0 ne{/Cyan}if
- AGMIMG_m 0 ne{/Magenta}if
- AGMIMG_y 0 ne{/Yellow}if
- AGMIMG_k 0 ne{/Black}if
- ]/DeviceCMYK{}]setcolorspace
- AGMIMG_c 0 ne{AGMIMG_c}if
- AGMIMG_m 0 ne{AGMIMG_m}if
- AGMIMG_y 0 ne{AGMIMG_y}if
- AGMIMG_k 0 ne{AGMIMG_k}if
- setcolor
- }{
- /Decode[Decode 0 get 255 mul Decode 1 get 255 mul]def
- [/Indexed
- [
- /DeviceN[
- AGMIMG_c 0 ne{/Cyan}if
- AGMIMG_m 0 ne{/Magenta}if
- AGMIMG_y 0 ne{/Yellow}if
- AGMIMG_k 0 ne{/Black}if
- ]
- /DeviceCMYK{
- AGMIMG_k 0 eq{0}if
- AGMIMG_y 0 eq{0 exch}if
- AGMIMG_m 0 eq{0 3 1 roll}if
- AGMIMG_c 0 eq{0 4 1 roll}if
- }
- ]
- 255
- {
- 255 div
- mark exch
- dup dup dup
- AGMIMG_k 0 ne{
- /sep_tint AGMCORE_gget mul MappedCSA sep_proc_name exch pop load exec 4 1 roll pop pop pop
- counttomark 1 roll
- }{
- pop
- }ifelse
- AGMIMG_y 0 ne{
- /sep_tint AGMCORE_gget mul MappedCSA sep_proc_name exch pop load exec 4 2 roll pop pop pop
- counttomark 1 roll
- }{
- pop
- }ifelse
- AGMIMG_m 0 ne{
- /sep_tint AGMCORE_gget mul MappedCSA sep_proc_name exch pop load exec 4 3 roll pop pop pop
- counttomark 1 roll
- }{
- pop
- }ifelse
- AGMIMG_c 0 ne{
- /sep_tint AGMCORE_gget mul MappedCSA sep_proc_name exch pop load exec pop pop pop
- counttomark 1 roll
- }{
- pop
- }ifelse
- counttomark 1 add -1 roll pop
- }
- ]setcolorspace
- }ifelse
- imageormask_sys
- }{
- write_image_file{
- currentcmykcolor
- 0 ne{
- [/Separation/Black/DeviceGray{}]setcolorspace
- gsave
- /Black
- [{1 exch sub/sep_tint AGMCORE_gget mul}/exec cvx MappedCSA sep_proc_name cvx exch pop{4 1 roll pop pop pop 1 exch sub}/exec cvx]
- cvx modify_halftone_xfer
- Operator currentdict read_image_file
- grestore
- }if
- 0 ne{
- [/Separation/Yellow/DeviceGray{}]setcolorspace
- gsave
- /Yellow
- [{1 exch sub/sep_tint AGMCORE_gget mul}/exec cvx MappedCSA sep_proc_name cvx exch pop{4 2 roll pop pop pop 1 exch sub}/exec cvx]
- cvx modify_halftone_xfer
- Operator currentdict read_image_file
- grestore
- }if
- 0 ne{
- [/Separation/Magenta/DeviceGray{}]setcolorspace
- gsave
- /Magenta
- [{1 exch sub/sep_tint AGMCORE_gget mul}/exec cvx MappedCSA sep_proc_name cvx exch pop{4 3 roll pop pop pop 1 exch sub}/exec cvx]
- cvx modify_halftone_xfer
- Operator currentdict read_image_file
- grestore
- }if
- 0 ne{
- [/Separation/Cyan/DeviceGray{}]setcolorspace
- gsave
- /Cyan
- [{1 exch sub/sep_tint AGMCORE_gget mul}/exec cvx MappedCSA sep_proc_name cvx exch pop{pop pop pop 1 exch sub}/exec cvx]
- cvx modify_halftone_xfer
- Operator currentdict read_image_file
- grestore
- }if
- close_image_file
- }{
- imageormask
- }ifelse
- }ifelse
- }ifelse
-}def
-/indexed_imageormask
-{
- begin
- AGMIMG_init_common
- save mark
- currentdict
- AGMCORE_host_sep{
- Operator/knockout eq{
- /indexed_colorspace_dict AGMCORE_gget dup/CSA known{
- /CSA get get_csa_by_name
- }{
- /Names get
- }ifelse
- overprint_plate not{
- knockout_unitsq
- }if
- }{
- Indexed_DeviceN{
- /devicen_colorspace_dict AGMCORE_gget dup/names_index known exch/Names get convert_to_process or{
- indexed_image_lev2_sep
- }{
- currentoverprint not{
- knockout_unitsq
- }if
- currentdict consumeimagedata
- }ifelse
- }{
- AGMCORE_is_cmyk_sep{
- Operator/imagemask eq{
- imageormask_sys
- }{
- level2{
- indexed_image_lev2_sep
- }{
- indexed_image_lev1_sep
- }ifelse
- }ifelse
- }{
- currentoverprint not{
- knockout_unitsq
- }if
- currentdict consumeimagedata
- }ifelse
- }ifelse
- }ifelse
- }{
- level2{
- Indexed_DeviceN{
- /indexed_colorspace_dict AGMCORE_gget begin
- }{
- /indexed_colorspace_dict AGMCORE_gget dup null ne
- {
- begin
- currentdict/CSDBase known{CSDBase/CSD get_res/MappedCSA get}{CSA}ifelse
- get_csa_by_name 0 get/DeviceCMYK eq ps_level 3 ge and ps_version 3015.007 lt and
- AGMCORE_in_rip_sep and{
- [/Indexed[/DeviceN[/Cyan/Magenta/Yellow/Black]/DeviceCMYK{}]HiVal Lookup]
- setcolorspace
- }if
- end
- }
- {pop}ifelse
- }ifelse
- imageormask
- Indexed_DeviceN{
- end
- }if
- }{
- Operator/imagemask eq{
- imageormask
- }{
- indexed_imageormask_lev1
- }ifelse
- }ifelse
- }ifelse
- cleartomark restore
- currentdict/_Filters known{_Filters AGMIMG_flushfilters}if
- end
-}def
-/indexed_image_lev2_sep
-{
- /indexed_colorspace_dict AGMCORE_gget begin
- begin
- Indexed_DeviceN not{
- currentcolorspace
- dup 1/DeviceGray put
- dup 3
- currentcolorspace 2 get 1 add string
- 0 1 2 3 AGMCORE_get_ink_data 4 currentcolorspace 3 get length 1 sub
- {
- dup 4 idiv exch currentcolorspace 3 get exch get 255 exch sub 2 index 3 1 roll put
- }for
- put setcolorspace
- }if
- currentdict
- Operator/imagemask eq{
- AGMIMG_&imagemask
- }{
- use_mask{
- process_mask AGMIMG_&image
- }{
- AGMIMG_&image
- }ifelse
- }ifelse
- end end
-}def
- /OPIimage
- {
- dup type/dicttype ne{
- 10 dict begin
- /DataSource xdf
- /ImageMatrix xdf
- /BitsPerComponent xdf
- /Height xdf
- /Width xdf
- /ImageType 1 def
- /Decode[0 1 def]
- currentdict
- end
- }if
- dup begin
- /NComponents 1 cdndf
- /MultipleDataSources false cdndf
- /SkipImageProc{false}cdndf
- /Decode[
- 0
- currentcolorspace 0 get/Indexed eq{
- 2 BitsPerComponent exp 1 sub
- }{
- 1
- }ifelse
- ]cdndf
- /Operator/image cdndf
- end
- /sep_colorspace_dict AGMCORE_gget null eq{
- imageormask
- }{
- gsave
- dup begin invert_image_samples end
- sep_imageormask
- grestore
- }ifelse
- }def
-/cachemask_level2
-{
- 3 dict begin
- /LZWEncode filter/WriteFilter xdf
- /readBuffer 256 string def
- /ReadFilter
- currentfile
- 0(%EndMask)/SubFileDecode filter
- /ASCII85Decode filter
- /RunLengthDecode filter
- def
- {
- ReadFilter readBuffer readstring exch
- WriteFilter exch writestring
- not{exit}if
- }loop
- WriteFilter closefile
- end
-}def
-/spot_alias
-{
- /mapto_sep_imageormask
- {
- dup type/dicttype ne{
- 12 dict begin
- /ImageType 1 def
- /DataSource xdf
- /ImageMatrix xdf
- /BitsPerComponent xdf
- /Height xdf
- /Width xdf
- /MultipleDataSources false def
- }{
- begin
- }ifelse
- /Decode[/customcolor_tint AGMCORE_gget 0]def
- /Operator/image def
- /SkipImageProc{false}def
- currentdict
- end
- sep_imageormask
- }bdf
- /customcolorimage
- {
- Adobe_AGM_Image/AGMIMG_colorAry xddf
- /customcolor_tint AGMCORE_gget
- <<
- /Name AGMIMG_colorAry 4 get
- /CSA[/DeviceCMYK]
- /TintMethod/Subtractive
- /TintProc null
- /MappedCSA null
- /NComponents 4
- /Components[AGMIMG_colorAry aload pop pop]
- >>
- setsepcolorspace
- mapto_sep_imageormask
- }ndf
- Adobe_AGM_Image/AGMIMG_&customcolorimage/customcolorimage load put
- /customcolorimage
- {
- Adobe_AGM_Image/AGMIMG_override false put
- current_spot_alias{dup 4 get map_alias}{false}ifelse
- {
- false set_spot_alias
- /customcolor_tint AGMCORE_gget exch setsepcolorspace
- pop
- mapto_sep_imageormask
- true set_spot_alias
- }{
- //Adobe_AGM_Image/AGMIMG_&customcolorimage get exec
- }ifelse
- }bdf
-}def
-/snap_to_device
-{
- 6 dict begin
- matrix currentmatrix
- dup 0 get 0 eq 1 index 3 get 0 eq and
- 1 index 1 get 0 eq 2 index 2 get 0 eq and or exch pop
- {
- 1 1 dtransform 0 gt exch 0 gt/AGMIMG_xSign? exch def/AGMIMG_ySign? exch def
- 0 0 transform
- AGMIMG_ySign?{floor 0.1 sub}{ceiling 0.1 add}ifelse exch
- AGMIMG_xSign?{floor 0.1 sub}{ceiling 0.1 add}ifelse exch
- itransform/AGMIMG_llY exch def/AGMIMG_llX exch def
- 1 1 transform
- AGMIMG_ySign?{ceiling 0.1 add}{floor 0.1 sub}ifelse exch
- AGMIMG_xSign?{ceiling 0.1 add}{floor 0.1 sub}ifelse exch
- itransform/AGMIMG_urY exch def/AGMIMG_urX exch def
- [AGMIMG_urX AGMIMG_llX sub 0 0 AGMIMG_urY AGMIMG_llY sub AGMIMG_llX AGMIMG_llY]concat
- }{
- }ifelse
- end
-}def
-level2 not{
- /colorbuf
- {
- 0 1 2 index length 1 sub{
- dup 2 index exch get
- 255 exch sub
- 2 index
- 3 1 roll
- put
- }for
- }def
- /tint_image_to_color
- {
- begin
- Width Height BitsPerComponent ImageMatrix
- /DataSource load
- end
- Adobe_AGM_Image begin
- /AGMIMG_mbuf 0 string def
- /AGMIMG_ybuf 0 string def
- /AGMIMG_kbuf 0 string def
- {
- colorbuf dup length AGMIMG_mbuf length ne
- {
- dup length dup dup
- /AGMIMG_mbuf exch string def
- /AGMIMG_ybuf exch string def
- /AGMIMG_kbuf exch string def
- }if
- dup AGMIMG_mbuf copy AGMIMG_ybuf copy AGMIMG_kbuf copy pop
- }
- addprocs
- {AGMIMG_mbuf}{AGMIMG_ybuf}{AGMIMG_kbuf}true 4 colorimage
- end
- }def
- /sep_imageormask_lev1
- {
- begin
- MappedCSA 0 get dup/DeviceRGB eq exch/DeviceCMYK eq or has_color not and{
- {
- 255 mul round cvi GrayLookup exch get
- }currenttransfer addprocs settransfer
- currentdict imageormask
- }{
- /sep_colorspace_dict AGMCORE_gget/Components known{
- MappedCSA 0 get/DeviceCMYK eq{
- Components aload pop
- }{
- 0 0 0 Components aload pop 1 exch sub
- }ifelse
- Adobe_AGM_Image/AGMIMG_k xddf
- Adobe_AGM_Image/AGMIMG_y xddf
- Adobe_AGM_Image/AGMIMG_m xddf
- Adobe_AGM_Image/AGMIMG_c xddf
- AGMIMG_y 0.0 eq AGMIMG_m 0.0 eq and AGMIMG_c 0.0 eq and{
- {AGMIMG_k mul 1 exch sub}currenttransfer addprocs settransfer
- currentdict imageormask
- }{
- currentcolortransfer
- {AGMIMG_k mul 1 exch sub}exch addprocs 4 1 roll
- {AGMIMG_y mul 1 exch sub}exch addprocs 4 1 roll
- {AGMIMG_m mul 1 exch sub}exch addprocs 4 1 roll
- {AGMIMG_c mul 1 exch sub}exch addprocs 4 1 roll
- setcolortransfer
- currentdict tint_image_to_color
- }ifelse
- }{
- MappedCSA 0 get/DeviceGray eq{
- {255 mul round cvi ColorLookup exch get 0 get}currenttransfer addprocs settransfer
- currentdict imageormask
- }{
- MappedCSA 0 get/DeviceCMYK eq{
- currentcolortransfer
- {255 mul round cvi ColorLookup exch get 3 get 1 exch sub}exch addprocs 4 1 roll
- {255 mul round cvi ColorLookup exch get 2 get 1 exch sub}exch addprocs 4 1 roll
- {255 mul round cvi ColorLookup exch get 1 get 1 exch sub}exch addprocs 4 1 roll
- {255 mul round cvi ColorLookup exch get 0 get 1 exch sub}exch addprocs 4 1 roll
- setcolortransfer
- currentdict tint_image_to_color
- }{
- currentcolortransfer
- {pop 1}exch addprocs 4 1 roll
- {255 mul round cvi ColorLookup exch get 2 get}exch addprocs 4 1 roll
- {255 mul round cvi ColorLookup exch get 1 get}exch addprocs 4 1 roll
- {255 mul round cvi ColorLookup exch get 0 get}exch addprocs 4 1 roll
- setcolortransfer
- currentdict tint_image_to_color
- }ifelse
- }ifelse
- }ifelse
- }ifelse
- end
- }def
- /sep_image_lev1_sep
- {
- begin
- /sep_colorspace_dict AGMCORE_gget/Components known{
- Components aload pop
- Adobe_AGM_Image/AGMIMG_k xddf
- Adobe_AGM_Image/AGMIMG_y xddf
- Adobe_AGM_Image/AGMIMG_m xddf
- Adobe_AGM_Image/AGMIMG_c xddf
- {AGMIMG_c mul 1 exch sub}
- {AGMIMG_m mul 1 exch sub}
- {AGMIMG_y mul 1 exch sub}
- {AGMIMG_k mul 1 exch sub}
- }{
- {255 mul round cvi ColorLookup exch get 0 get 1 exch sub}
- {255 mul round cvi ColorLookup exch get 1 get 1 exch sub}
- {255 mul round cvi ColorLookup exch get 2 get 1 exch sub}
- {255 mul round cvi ColorLookup exch get 3 get 1 exch sub}
- }ifelse
- AGMCORE_get_ink_data currenttransfer addprocs settransfer
- currentdict imageormask_sys
- end
- }def
- /indexed_imageormask_lev1
- {
- /indexed_colorspace_dict AGMCORE_gget begin
- begin
- currentdict
- MappedCSA 0 get dup/DeviceRGB eq exch/DeviceCMYK eq or has_color not and{
- {HiVal mul round cvi GrayLookup exch get HiVal div}currenttransfer addprocs settransfer
- imageormask
- }{
- MappedCSA 0 get/DeviceGray eq{
- {HiVal mul round cvi Lookup exch get HiVal div}currenttransfer addprocs settransfer
- imageormask
- }{
- MappedCSA 0 get/DeviceCMYK eq{
- currentcolortransfer
- {4 mul HiVal mul round cvi 3 add Lookup exch get HiVal div 1 exch sub}exch addprocs 4 1 roll
- {4 mul HiVal mul round cvi 2 add Lookup exch get HiVal div 1 exch sub}exch addprocs 4 1 roll
- {4 mul HiVal mul round cvi 1 add Lookup exch get HiVal div 1 exch sub}exch addprocs 4 1 roll
- {4 mul HiVal mul round cvi Lookup exch get HiVal div 1 exch sub}exch addprocs 4 1 roll
- setcolortransfer
- tint_image_to_color
- }{
- currentcolortransfer
- {pop 1}exch addprocs 4 1 roll
- {3 mul HiVal mul round cvi 2 add Lookup exch get HiVal div}exch addprocs 4 1 roll
- {3 mul HiVal mul round cvi 1 add Lookup exch get HiVal div}exch addprocs 4 1 roll
- {3 mul HiVal mul round cvi Lookup exch get HiVal div}exch addprocs 4 1 roll
- setcolortransfer
- tint_image_to_color
- }ifelse
- }ifelse
- }ifelse
- end end
- }def
- /indexed_image_lev1_sep
- {
- /indexed_colorspace_dict AGMCORE_gget begin
- begin
- {4 mul HiVal mul round cvi Lookup exch get HiVal div 1 exch sub}
- {4 mul HiVal mul round cvi 1 add Lookup exch get HiVal div 1 exch sub}
- {4 mul HiVal mul round cvi 2 add Lookup exch get HiVal div 1 exch sub}
- {4 mul HiVal mul round cvi 3 add Lookup exch get HiVal div 1 exch sub}
- AGMCORE_get_ink_data currenttransfer addprocs settransfer
- currentdict imageormask_sys
- end end
- }def
-}if
-end
-systemdict/setpacking known
-{setpacking}if
-%%EndResource
-currentdict Adobe_AGM_Utils eq {end} if
-%%EndProlog
-%%BeginSetup
-Adobe_AGM_Utils begin
-2 2010 Adobe_AGM_Core/ds gx
-Adobe_CoolType_Core/ds get exec Adobe_AGM_Image/ds gx
-currentdict Adobe_AGM_Utils eq {end} if
-%%EndSetup
-%%Page: (Page 1) 1
-%%EndPageComments
-%%BeginPageSetup
-%ADOBeginClientInjection: PageSetup Start "AI11EPS"
-%AI12_RMC_Transparency: Balance=75 RasterRes=300 GradRes=150 Text=0 Stroke=1 Clip=1 OP=0
-%ADOEndClientInjection: PageSetup Start "AI11EPS"
-Adobe_AGM_Utils begin
-Adobe_AGM_Core/ps gx
-Adobe_AGM_Utils/capture_cpd gx
-Adobe_CoolType_Core/ps get exec Adobe_AGM_Image/ps gx
-%ADOBeginClientInjection: PageSetup End "AI11EPS"
-/currentdistillerparams where {pop currentdistillerparams /CoreDistVersion get 5000 lt} {true} ifelse { userdict /AI11_PDFMark5 /cleartomark load put userdict /AI11_ReadMetadata_PDFMark5 {flushfile cleartomark } bind put} { userdict /AI11_PDFMark5 /pdfmark load put userdict /AI11_ReadMetadata_PDFMark5 {/PUT pdfmark} bind put } ifelse [/NamespacePush AI11_PDFMark5 [/_objdef {ai_metadata_stream_123} /type /stream /OBJ AI11_PDFMark5 [{ai_metadata_stream_123} currentfile 0 (% &&end XMP packet marker&&) /SubFileDecode filter AI11_ReadMetadata_PDFMark5 <?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
-<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.1-c036 46.277092, Fri Feb 23 2007 14:16:18 ">
- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <rdf:Description rdf:about=""
- xmlns:dc="http://purl.org/dc/elements/1.1/">
- <dc:format>application/postscript</dc:format>
- <dc:title>
- <rdf:Alt>
- <rdf:li xml:lang="x-default">Print</rdf:li>
- </rdf:Alt>
- </dc:title>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xap="http://ns.adobe.com/xap/1.0/"
- xmlns:xapGImg="http://ns.adobe.com/xap/1.0/g/img/">
- <xap:CreatorTool>Adobe Illustrator CS3</xap:CreatorTool>
- <xap:CreateDate>2010-05-25T11:06:31-06:00</xap:CreateDate>
- <xap:ModifyDate>2010-05-25T11:06:31-06:00</xap:ModifyDate>
- <xap:MetadataDate>2010-05-25T11:06:31-06:00</xap:MetadataDate>
- <xap:Thumbnails>
- <rdf:Alt>
- <rdf:li rdf:parseType="Resource">
- <xapGImg:width>256</xapGImg:width>
- <xapGImg:height>116</xapGImg:height>
- <xapGImg:format>JPEG</xapGImg:format>
- <xapGImg:image>/9j/4AAQSkZJRgABAgEAlgCWAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAAlgAAAAEA&#xA;AQCWAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAdAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A735w/NHyr5VuVs715bnU&#xA;WAb6jaIJJVVtwX5FFWvgWr7Zm6bs/JmFjaPeXB1XaOLAalvLuDGv+V92H/Uu6p/wC/1zM/kaX8+L&#xA;hfy3D+bJ3/K+7D/qXdU/4Bf64/yNL+fFf5bh/Nk7/lfdh/1Luqf8Av8AXH+Rpfz4r/LcP5snf8r7&#xA;sP8AqXdU/wCAX+uP8jS/nxX+W4fzZO/5X3Yf9S7qn/AL/XH+Rpfz4r/LcP5snf8AK+7D/qXdU/4B&#xA;f64/yNL+fFf5bh/Nk7/lfdh/1Luqf8Av9cf5Gl/Piv8ALcP5snf8r7sP+pd1T/gF/rj/ACNL+fFf&#xA;5bh/Nkl+s/8AOSuiaVbGSfQr5JWB+rxSlIg7DtU1oPE0NMry9lmAsyDOHa8ZmhGT5289fmr5z853&#xA;cj6pevHYk/utMgZktkHb4AfjP+U9TghjEeTTlyymd0k8ueaNf8t6lHqWiXstldxkHlG3wuAa8ZE+&#xA;y6nurCmSIBFFhGRibGxfa/5VfmFbee/KUOsLGIL2Nzb6jbLUqk6AE8K78GVgy/OlajNdlx8Jp3Wn&#xA;zeJG+rMMqb3Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXzf5Hk+uxXuu3f73VL+4k&#xA;ae4brQkNxHgKnt/DOvzjhqA+kB4rCeMmcvqJZT62YzfTvWxWnetitO9bFad62K071sVp3rYrSC1n&#xA;XbLSNMuNRvH429uvJqbsx6KqjxY7DEmlp82+ZvMmoeYdXl1G9b4n+GGIGqxRg/Ci+w/E75hTlxFy&#xA;YQ4QgLS0nupxDCvJyCxPZVUFmdj2VVBJPYZFkSpOEDkIaqOhO1ffFQ+gv+cRNSkTVvMWmdY5oILk&#xA;exhdkPfv63h2zF1Q2Bc/QS9RHl+PvfTGYTtHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX&#xA;Yq7FXzJ5Cl46DT/i5/4Z2OpHqeJ0v0/Fknr++Y9OS71/fGld6/vjSu9f3xpXev740rvX98aV3r++&#xA;NK8Z/NjzY2paoNItnrZWDH1aE0efo1f9T7I965iZ5702449WAgEmg3J6DKG1l/mbTx5T0uPy8wpr&#xA;98kdxr53BgjakkFj8x8Ms3+VwX9g1jE3uzlHh2PP8fj+xiGSYPov/nEPS2MnmTVWUhQLa1iegoST&#xA;JJIK+1EzF1R2AdhoBuS+kMwnZuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvljyZL&#xA;x0an/Fr/AMM7PUD1PEaX6finvr++UU5Nu9f3xpbd6/vjS271/fGlt3r++NLbvX98aW0n82+Yv0No&#xA;Vxdqf9II9K2H/Fr7A/7HdvoyGSXCLSBZp4OzMzFmNWJqSepJzWuUBT0T8rtGsdOsdR/MPW4RLpfl&#xA;6i6ZayfZu9UcfuI+oqsRIkeh8Oorlcz/AAjr9zdiAFyPIff+NywLUL+81G/uL+9lM15dyvPcTN1e&#xA;SRizMfmTljUh8UPtP/nHzyu+gflhpwmUrc6qzalMp7fWAoi/5Ion05r9RK5e53Ojhw4/fu9Iyhyn&#xA;Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXyb5Wl46XT/ixv4Z2ucep4fTH0pv9Yyq&#xA;m+3fWMaW3fWMaW3fWMaW3fWMaW3fWMaW3mX5m6ybnU4dPQ/u7ReTjxkkAP4LT7zmBqpb034R1Yvp&#xA;GlXur6raaXYx+reXsyQW8fSryMFFT2G+5zEJpyALNB6P+deoWGkLpP5caNJz03yzGDfyrsLjUZhy&#xA;lkYVb7Ibb+Usy9srxb+o9fub85AqA5R+/q8ty1x2Vflh5Ml84edtN0QKxtZJPVv3X9i2i+KU17VH&#xA;wg/zEZCc+EW2YsfHIB93xxxxRrFEoSNAFRFACqoFAAB0AzVu/ApdirsVdirsVdirsVdirsVdirsV&#xA;dirsVdirsVdirsVdirsVdir5A0CXjYU/y2/hnc5Ru8HhOyZfWMqpt4nfWMaXid9YxpeJ31jGl4nf&#xA;WMaXiWyXaxo0jtREBZj4AbnGl4njV/dveXs90/2p5Gc+3I1p9GaScuIkuyhGgA9X/I2xt9B0zzD+&#xA;Zuoxh7fy9A1vpSOPhkvp1CgVHgJFU/69e2Y+Xeo9/wBzl6f0gz/m8ve8ovr27v724vryVpru6kea&#xA;4mbdnkkYszH3JOXOPahih9a/84z/AJenQfKzeYr6LhqmuhWhDD4o7IbxjcbeqfjPiOOYOpyWa7na&#xA;6LFUeI9fu/a9mzGc52KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvjTS5StrT/KO&#xA;d5MbvnsJUjPXOQpnxO9c40vE71zjS8TvXONLxO9c40vEgNcum/RdxGrhZJkaKOv7TMp+Ee5FaZVm&#xA;HoPmzxy9QeZqrMwVQSzGgA6knNE7l7H+cjL5T8keVPy3gIW4hhGq65TiSbqbkFUsP5WMnX9njlOL&#xA;1Ey+DlZ/TGMPife8by5xXqf5R/kn5i8za9Y3msabPaeWI2E9zcTqYhOi/EscQbi7CToWXYCu9aZV&#xA;lyiI83IwaczI29L7HjjSNFjjUJGgCoiigAGwAA7ZrXdgN4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXY&#xA;q7FXYq7FXYq7FXYq7FXxVaScYqe5zvyHzi6VvWOCl4nescaXid6xxpeJ3rHGl4nescaXiY75undo&#xA;oRG9DCwd1H2hyqEb8Dmu152FdPwHYaGiTfX8FMPyV8tr5j/M7RrWVOVrBMb66FKrwtgZQrD+VnVU&#xA;+nNNmnUSXc6fHxTASz8y/NH+KPPes60GL29xcMtoaAf6PFSKHYd/TQV98MI8IARlnxSMu9vyjr2t&#xA;Wuo2ll5X062/TdzIsVtdvAl1dGRyOPA3AeKIg9GRFIHVsMgOvJjAkHbm+wBez/l9+W02peYr+bWL&#xA;3ToDPfXMjsxmuJGAWOMsPhQyMqJtsNyOua6uOdDZ3IPhY7kbLz3yF5LvvzV0/wDxl+YF9Pd6feSy&#xA;fony/byvBZxRRu0bFlQhq8loNw1BVmau12TJ4fpi4uHCc3rmb7gyHWf+cdvJRgM/lZ7ryzrMQ5Wt&#xA;9Z3M5AcfZ5q7saf6hU5COpl13DbPQw/h2ISL/nHUeaIvM3nu08z3M11rNnJp9vcSzu0rH0xcqpDN&#xA;uVKgFT3GS1NUK5MNECDK+e36XuOYrsHjX5tfn6nl/UD5Z8pwLqnmRmEMslDJFBK54iJUXeWap+z0&#xA;U7GpquZOLBe8uTgajV8J4Y81PQfyP1/zFEmp/mhr17qN5N+9/QsE5jtoeW5RuHw18REFA7E5KWcR&#xA;2gER0hnvkJ934/QyC4/5x2/KWSAxwaO9pLSkdzBdXXqofFecjrX/AFlOVjUz7206HEen2sH812X5&#xA;qflCo1fQ9Xm8x+TkZVnsdSJme2UnigZtmVd6B4yor1XxtiYZNiKLjzjkw7g3H8fjZ6n+W/5maB58&#xA;0Y32mkw3cHFdQ0+Q1kgdq0FaAOrUPFh19jUDHyYjAuZgzjIPNGecfy+8pecYIYfMNiLz6sJBayc5&#xA;I3iMvHmUZGXrwXr4YIZDHkyy4Yz+p8XweUIG/M9fJ8kzfVxrX6Ke4FOfpi69AuNqcuO+bLi9N+Vu&#xA;lMKnw+dfbT7a8q+UPL3lTSv0XoNoLOy5mVo+TuWkYBWdmcsxJCjNbOZkbLu8eKMBUU4yDY7FXYq7&#xA;FXYq7FXYq7FXYq+Io2ouegPm0gv54op3PFadzxWnc8Vp3PFaYr5haZNScn7EsYA91/sYVzSa6xkP&#xA;mPx9rutEAcY7wWd/lVMNB8hefPNleFwLKPRrA1oTJfPSQr/lRhUfNZk3IHx+TtMW0ZHyr5vLctaH&#xA;1P8A843flKdGsV84a1DTVb6OmlwOPigtnG8u/R5QfoT/AFiBhajLfpDs9Hgr1n4Ml/5yRt7ib8pd&#xA;UaIErDLbSTAfyeui/TuwyGm+pt1o/dsP/wCcaPzT0c6JB5I1OZbbULaR/wBFM/wrPHM5kMQY/wC7&#xA;FdmoO4Ip0yzUYjfEGnRZwBwH4Pf8xHYpVp/lnS9P1/V9dtw4v9bFst8S1UP1NGjiKrTb4X3yRmSA&#xA;O5rjjAkZd7Gfzq89v5M8h3d/bNx1S7IstNPXjNKCTJ/zzRWYe4AyzBDik1arLwQ25l4n/wA4teUI&#xA;9X806h5ov19YaQqrbGSpJurnlWTfqURW692B65k6mdRrvcLRY+KVno+p8wHbOxVRvbK0vrOeyvIl&#xA;ntLmNop4XFVdHHFlI8CDhBo2iUQRRfFtnqOqflJ+bdykDSNDpt01vcxH4Tc2EhDgMOlXiKuvg1D2&#xA;zZECcfe6ME4p+77f7X2pa3NvdW0V1buJbedFlhlXcMjjkrD2IOa0ineAgiw+Mof/AFo4/wDgWv8A&#xA;91E5sR/d/wCb+h0k/wC9/wA8f7p9o5rXeOxV2KvJPy0/KDzR5Q8/6vrc+treaNfrKFgLO08rySB0&#xA;acMqxhkA+0p39gcycuYSjVbuDp9LLHMm9vxzet5jOcxrV/POn6d520HyiYzNf64lzLyVgBBHbxNI&#xA;Gdab+oY2VfkcsGO4mXc0yzATEO9kuVtzsVdirsVfD6mgz0F84Ib5YrTuWK01zxWnc8C01zOKaSbz&#xA;LFyt4pu6NxPyYf2Zre0oekSc/QSqRDL7qy1Fvyi8n+WNLiN1qHmjVLzU/qsYq5MFLOIHtRuLN4bV&#xA;OaT+InuH7Xd0eCIG9kn9H63tf5Xf847eXPLcEOoeYo49Y14gMUkHK1tzT7McZ2dh/O30Ad8XJqCd&#xA;hyc7BowN5bn7HsGYznIXVdLsNW0260zUIRPZXkTQ3ELdGRxQio3HsR0wxJBsMZREhR5PjL81PyY8&#xA;x+Rb2S5RHvfLrv8A6LqaCvAE7JOF+w46V+y3bwGxx5RL3ulz6c4zvyZJ+WX/ADkn5h0BodN8z+pr&#xA;Ojr8K3JNbyEV6h2P75R4Oa/5VBTI5NOJcti24dXKOx3H2vqPQdf0fX9Kg1XR7pLywuRWKZK9tiCD&#xA;QqwOxB3GYMomJou0hMSFjk8F/wCcv5pBB5VgDfuna+dl7FkFuFP0czmVpergdofw/H9DIf8AnE+G&#xA;Nfy7v5QoEkmqzB3oKkLbwUFfAVOR1X1D3M+z/pPv/QHtOYrnuxV2Kvjn/nJm1WH817yQdbm2tpW+&#xA;YjEf6o82OA+gOl1YrIfx0fSn5N30t7+V3lqeU1dbKOGpp0grCvSn7KDMPOKmXZaWV4w+YIf/AFo4&#xA;/wDgWv8A91E5mj+7/wA39Dq5/wB7/nj/AHT7RzWu8diqR+cdS812GlLL5Y0ePWtSeVYzby3CWyRx&#xA;lWJlZnpyoVC8Qa717ZOAiTuaDVllID0iy8Gb86/zdX80dI8ra1Fa6OW1Oytb+ytolk5xXEqV/eyN&#xA;P9uOT7SEZlnDDhJG7rxqcpmInbcX+N3vPnC484waUreUrWzu9UaUKyX7ukKxcWLP8FCx5BRSo65i&#xA;QEb9TsMpmB6Ob5V0TUPzOl/PdHL2l/52t5rmBVuy31MGO2lV0HpmMhFj5caU3zOkI8H9F1WOU/F7&#xA;5bvpPyTdfm5NqUy+c7PSLfTRCTA+mmYymfmtA3qSSDjw5dutMw5iFek7uyxHKT6gKTrzf5t0byno&#xA;Fzrmry+naW4ACLQySyNskUakjkzH+poATkYQMjQbMuUQjZeNX3mv/nI7zFobeavL1lbaTozIZrLT&#xA;VWGa8lt6FhJSdX57DagUttxU1zJEMUTR3LgHJnnHiGw+H6fx5Ib8kvz981eYPNdt5Z8yLFd/Xlk+&#xA;rX0cYikSSKNpaOqUQqyoRsoNfbHNgiBYTptVIyEZb28kztHjHYq7FXYq7FXYqgtYj9TTZh/KAw/2&#xA;JrmLrY3iLfpZVkD6k/KfyNb2tnofmC5iX1rfQrGy0wNQlBMhurqWn7LPLPw8eK/5W/I5snOPm9jp&#xA;cI2n/RFfefvel5jua7FXYqtmhimieGZFkhkUpJG4DKysKFWB2IIxBQRb5+/N3/nG2zngn1zyRF6F&#xA;0gaS40RamOUAEk23Xi//ABX9k/s06HMxajpJ12o0dbw+X6v1MI/5xn853+kefIvL7yt+i9aEkckD&#xA;V4pcRoXjkA7MeHA/PfoMs1ELj5ho0eQiYHQvRf8AnLLy9cXnlbSNbhUumk3MkVwACeMd2FHMnsA8&#xA;Kr82GU6WW5Dk6+BoHuU/+cSNYjl8sa3o+3q2l6t37lLmIJ+Btz9+HVDcFdBLYj4/j5PecxHYOxV2&#xA;Kviz/nIDUk1b83NXS0JmFu0NlGFqSZIolV0A8RKWXNlhFQDo9TK8hL658laI2heUNG0dwBLYWUEE&#xA;9DyHqpGBIQd+r1OYGSVyJdxhhwwA8nyRD/60cf8AwLX/AO6iczx/d/5v6HTz/vf88f7p9o5rXeOx&#xA;V2Kvln8ywB/zk/o1B11DRif+DhzPh/dfAupy/wCMfEfofU2YDtny15V/9axn/wC2hqX/AFCT5n5P&#xA;7r4B1OH+/wDjL9L6lzAds+cP+cktXi1H8wvKvlK9u1ttEBguL+UuFRDdXBhZ5STRfTiTkCegY5m6&#xA;cVEnq6vWnimI3t+tn2q/nZo8sDaT+Xmnz+ZtYCelbR2cDrZW5+yjTSsEURr/AJO3bkvXKxgPOWwb&#xA;5asfTjFlB/kv+Ry+UJT5h190uvM8wbgqHlHarIDzCn9qRgaM3TsNty5s/FsOSNLpODeXP7nz/dWs&#xA;9pdTWtwhjuIHaKaNtiroeLA/IjO2jIEWOReJlExJB5hSwodirsVdirsVQup/8c+4/wBQ5j6v+7k2&#xA;6f6x73235ciSHy9pcUYokdpAijrssSgZxM/qL3mIege5Mci2OxV5h/zkLq8+jeTNO1aDeWw1mxuk&#xA;X+Yws0gB+ZXMjTCyR5OFriREEfzv1vQdD1vTdc0i01fTJhPY3sYlgkHgeoPgynZh2O2UyiYmi5UJ&#xA;iQBHJHEgAkmgG5JyLN8qflVosXmH/nIPUtY0pOehadfX1968Y4x8JGkS347ADmzhlX+UHwzYZTWP&#xA;fm6fTx4stjlZP6n07rui6drmj3mkalF61jfRNDOnfiw6qezKd1PY5gxkQbDtpwEhRfKenQa/+Rf5&#xA;oRy6jG9zoN3ygN1Gvw3Nk7A8l7CWIhWKV6ileLAnPNZI7OnHFgyb/wBofWGl6pp2q6fBqOnXCXVj&#xA;coJILiI8kZT4H8D4ZryCDRdxGQkLHJFYGTCvzU/M3SvInl6S7mdJdWuFZNLsK/FJJSgdlrX00O7H&#xA;6Opy3FiMj5OPqM4xjzeM/kB+VGp61ro8++aI5Pq6Sm609JxR7q5cl/rLV34Kx5Kf2m36DfJz5aHC&#xA;HC0unMjxS5fe+m8wXaviu3ngb/nIcTiRfRbzWzrJUcSp1AkGvhmzA9H+b+h0UjeX/P8A98+1M1jv&#xA;UHrWrWWj6TearfOI7SyheeZyQPhQVoK9z0Hvkoxs0xnMRBJ6KHljXYvMHl7T9bhhe3i1GBLiOGWn&#xA;NVkFRWm3TGceE0jHPiiC+ZfzEYn/AJyk08E1A1XRQPYUtjmbD+6+B/S6qf8AjH+cPuD6tzAdw+Wf&#xA;KzKv/OWExYgD9I6iKnbc2k4H45nz/uvgHU4v7/4n9L6H84eefL3lKyiuNWmb1blxFZ2MC+rdXEjE&#xA;DjDEDVqV37fhmHDGZcnY5c0YDd8+/wDOUNjPpvn3QPMyW4e1ntox+8FVea0mLsrq3SqSIKEfxzM0&#xA;x9NOu10amD3j8fofRHlDX/L+veXrPUtBeM6dKg4RRBV9JqAtEyLsjrXdcw5xIO7ssU4yjceSQfmJ&#xA;+aemeVTb6ZZIuq+ar+WKDT9Ejf4y0rABpSK+mtG+GvU9NqkTxYTLc7Bq1GpENhvLuQ3nv8l/L3mm&#xA;8bUYpn0zU5KetNEqvHJT9p4yVq3+UGHvXM3SdqTwjhI4ouJrOyseY8V8MmH/APQsv/fyf9OX/Zxm&#xA;b/Lv9D/ZfscD+QP6f+x/a7/oWX/v5P8Apy/7OMf5d/of7L9i/wAgf0/9j+13/Qsv/fyf9OX/AGcY&#xA;/wAu/wBD/ZfsX+QP6f8Asf2u/wChZf8Av5P+nL/s4x/l3+h/sv2L/IH9P/Y/td/0LL/38n/Tl/2c&#xA;Y/y7/Q/2X7F/kD+n/sf2pR5v/wCcdn0zyrrGppr31hrCyuLr0DacOfoxtJx5es9K8fDIy7Y8QcPB&#xA;z8/2L/Inh+vj+nfl+17x5dkSXy/pkkZ5I9pAyN4gxqQc0c/qLv8AEfSPcmGRbHYqxT8yvIEHnry/&#xA;FolxeNZQLdw3M0iIJGZIuQaNasoUsG2bengcsxZOA20Z8PiCrrdi9h+S+reVjKfIHmu70eGYlptO&#xA;voo761d9hyVWCGM0Aqwq3vTLDnEvqDSNLKH0SpD6t+Xf5x+ZoZNO8w+cbWz0acUuYNKtiryKRRoy&#xA;zem3FhWvxEeIOSGTHHcDdjLBmntKQr8e5nnkryN5d8maMulaHAY4a85ppCGmmkpTnK4AqfkAB2GU&#xA;TyGRsuVixRgKCf5BtS7X/Luh+YdMk0zWrOO+sZd2hlFaMNgysKMrCuzKQRkoyMTYYTxxmKLy2T8l&#xA;PNHlNLq7/LPzPc2BblIuh3oSe2lc/shnHFTQUDMhPi3fMgZ4y2kHDOklCzjl8Pxt9jyDWv8AnIX8&#xA;5LaafS7u6i069tmaC5C2sQlV1NGrzDgEewy8YIdziS1WXlf3PV/yt/K/yB5lsrbztqOoXHm/UbkD&#xA;1X1JqpDMlOUUlvVviTpxdmWlCBShynLllE0NnJ0+nhMcRPEXtYAAAAoBsAMxHYpB5z0LzFrWmLZ6&#xA;Hr7+XpS5M91FbpcO8ZUjgvNkMe+/JTXLMcgDuLac0JSFRPC8VP8AziFEWLnzY5cmpY2IrXxr9YzJ&#xA;/Nju+39jg/ycf5w+X7WZ235T/mZbQJBF+Z98Y4xRedmkjU93eZmP0nK/Gh/N/HybRpco/j+z/jyV&#xA;+YP+cf8Azd5ih9DWvzEvb22qG+rSWtIeSigb0luAlR40yQ1ERyj+Pkxlopy5zv4f8eenW3l29sfJ&#xA;tp5e0vUmsrqxs7ezt9UWGORl+roqc/Rk5IeQToa9cx+IGVkOYIEQEQdwObyrV/8AnGSTWNYl1rUv&#xA;OF5c6pMyu921vGH5IAEI4uOPEKAKdMyBqQBQDhy0JJsy3937XqnlLQ/MGkWssGseYJdfZivoSzQQ&#xA;wNGqggisQq/LxYk5jzkDyFOZihKP1HieX+f/APnHS417znN5o0LXf0Rc3MiTyRmNy0c6AD1YpUdW&#xA;BYry9j38L8eooUQ4uXRmUuIFlXkb8mdI8u6n+ndW1C58y+ZqUGrX7MxjFKfukZpCp47VZmPhTITz&#xA;kihsG3FpRE8RPFJk3nTyVoHnHQ5NG1qEyWzsHjljIWWKRQQskTENRhUjoR2O2VwmYmw3ZcQmKLw9&#xA;v+cUtbs7qQ6R5t9C3kBBJhkjk4mo4t6clG2PtXwzKGqHc686A3sWefll+QegeSdTOsz3smsa0Ayw&#xA;3UqCKOIOKMyR8pDzIJBYudsqy5zIU5ODSCBu7L1HMdy3Yq7FXYq7FXYqhdW06LUtKvNOmNIr2CW3&#xA;kNK0WVCh2+TYYmjbGceKJHex/wDKu+ku/wAvdC9ZDHc2lsthdRt9pZrEm1lB9+cJyzMKmWrSyvGP&#xA;l8tmVZU3uxV2KuxV2KuxV2KuxV2KvI/zw/JGHzpbnWtFVIfM9ugUqSES7jXokhOwkUbI5/1W2oVy&#xA;MObh2PJwtVpeP1R+r73gX5e+fvNP5V+aJoby0mS2chNV0e4DRMwHSRQw+F1/ZboR7ZlzgJhwMWWW&#xA;OX3h9WeXPzX/AC+8wael7Za3axBh8dtdSpbzxnuHjkYH6RUHsTmDLDIHk7WGpxyF3XvZFpmr6Tqt&#xA;u1zpl7Bf26uY2mtpUmQOtKqWQsKivTKzEjm2xmJCwbReBk7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq&#xA;7FXYq7FXYq7FVsXpcT6XHjyavGlOXI8+nflWvviUBdil2KuxV2KuxV2KuxV2KuxV2KsV8+/8q1+p&#xA;L/jb9G+jQ+h9f9P1KVHL0eX7yvjwy3Hx/wALRm8P+OnlUP8A0KN9cHD6t6vI/b/SXpV/2f7un4Zk&#xA;fvvxThD8tfX/AGT2fyp/hL9Dx/4U+pfojkeH6O9L0OdBy/uvh5dK138cxZ8V+p2GLgr01XknGQbH&#xA;Yq7FXYq7FXYq7FXYq7FXYq7FX//Z</xapGImg:image>
- </rdf:li>
- </rdf:Alt>
- </xap:Thumbnails>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xapMM="http://ns.adobe.com/xap/1.0/mm/"
- xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#">
- <xapMM:DocumentID>uuid:EB89571B7F69DF11AF0CB9E432C5A167</xapMM:DocumentID>
- <xapMM:InstanceID>uuid:EC89571B7F69DF11AF0CB9E432C5A167</xapMM:InstanceID>
- <xapMM:DerivedFrom rdf:parseType="Resource">
- <stRef:instanceID>uuid:EA89571B7F69DF11AF0CB9E432C5A167</stRef:instanceID>
- <stRef:documentID>uuid:E989571B7F69DF11AF0CB9E432C5A167</stRef:documentID>
- </xapMM:DerivedFrom>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/">
- <illustrator:StartupProfile>Print</illustrator:StartupProfile>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xapTPg="http://ns.adobe.com/xap/1.0/t/pg/"
- xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
- xmlns:xapG="http://ns.adobe.com/xap/1.0/g/">
- <xapTPg:MaxPageSize rdf:parseType="Resource">
- <stDim:w>300.000000</stDim:w>
- <stDim:h>200.000000</stDim:h>
- <stDim:unit>Points</stDim:unit>
- </xapTPg:MaxPageSize>
- <xapTPg:NPages>1</xapTPg:NPages>
- <xapTPg:HasVisibleTransparency>False</xapTPg:HasVisibleTransparency>
- <xapTPg:HasVisibleOverprint>False</xapTPg:HasVisibleOverprint>
- <xapTPg:PlateNames>
- <rdf:Seq>
- <rdf:li>PANTONE 3005 U</rdf:li>
- <rdf:li>PANTONE 309 U</rdf:li>
- <rdf:li>PANTONE 2905 U</rdf:li>
- </rdf:Seq>
- </xapTPg:PlateNames>
- <xapTPg:SwatchGroups>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:groupName>Default Swatch Group</xapG:groupName>
- <xapG:groupType>0</xapG:groupType>
- <xapG:Colorants>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>PANTONE 3005 U</xapG:swatchName>
- <xapG:type>SPOT</xapG:type>
- <xapG:tint>100.000000</xapG:tint>
- <xapG:mode>CMYK</xapG:mode>
- <xapG:cyan>100.000000</xapG:cyan>
- <xapG:magenta>34.000000</xapG:magenta>
- <xapG:yellow>0.000000</xapG:yellow>
- <xapG:black>2.000000</xapG:black>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>PANTONE 2905 U</xapG:swatchName>
- <xapG:type>SPOT</xapG:type>
- <xapG:tint>100.000000</xapG:tint>
- <xapG:mode>CMYK</xapG:mode>
- <xapG:cyan>41.000000</xapG:cyan>
- <xapG:magenta>2.000000</xapG:magenta>
- <xapG:yellow>0.000000</xapG:yellow>
- <xapG:black>0.000000</xapG:black>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>PANTONE 309 U</xapG:swatchName>
- <xapG:type>SPOT</xapG:type>
- <xapG:tint>100.000000</xapG:tint>
- <xapG:mode>CMYK</xapG:mode>
- <xapG:cyan>100.000000</xapG:cyan>
- <xapG:magenta>0.000000</xapG:magenta>
- <xapG:yellow>9.000000</xapG:yellow>
- <xapG:black>72.000000</xapG:black>
- </rdf:li>
- </rdf:Seq>
- </xapG:Colorants>
- </rdf:li>
- </rdf:Seq>
- </xapTPg:SwatchGroups>
- </rdf:Description>
- </rdf:RDF>
-</x:xmpmeta>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<?xpacket end="w"?> % &&end XMP packet marker&& [{ai_metadata_stream_123} <</Type /Metadata /Subtype /XML>> /PUT AI11_PDFMark5 [/Document 1 dict begin /Metadata {ai_metadata_stream_123} def currentdict end /BDC AI11_PDFMark5
-%ADOEndClientInjection: PageSetup End "AI11EPS"
-%%EndPageSetup
-1 -1 scale 0 -211.304 translate
-pgsv
-[1 0 0 1 0 0 ]ct
-gsave
-np
-gsave
-0 0 mo
-0 211.304 li
-372 211.304 li
-372 0 li
-cp
-clp
-[1 0 0 1 0 0 ]ct
-103.096 139.708 mo
-103.039 138.986 103.005 138.517 103.005 138.517 cv
-103.005 138.517 100.816 123.759 98.21 119.355 cv
-97.7979 118.657 98.2549 115.79 99.4053 111.543 cv
-100.078 112.706 102.917 117.68 103.487 119.283 cv
-104.129 121.095 104.264 121.614 104.264 121.614 cv
-104.264 121.614 102.707 113.603 100.152 108.928 cv
-100.712 107.038 101.381 104.949 102.138 102.716 cv
-103.106 104.414 105.423 108.525 105.933 109.951 cv
-106.036 110.244 106.123 110.493 106.201 110.721 cv
-106.226 110.584 106.251 110.447 106.276 110.31 cv
-105.691 107.828 104.542 103.509 102.969 100.318 cv
-106.459 82.1528 118.362 57.8726 130.565 47.0405 cv
-50.96 47.0405 li
-45.625 47.0405 41.2598 51.4063 41.2598 56.7407 cv
-41.2598 144.53 li
-41.2598 149.865 45.625 154.23 50.96 154.23 cv
-103.39 154.23 li
-103.012 149.654 102.886 144.591 103.096 139.708 cv
-cp
-false sop
-/0
-<<
-/Name (PANTONE 3005 U)
-/0
-[/DeviceCMYK] /CSA add_res
-/CSA /0 get_csa_by_name
-/MappedCSA /0 /CSA get_res
-/TintMethod /Subtractive
-/TintProc null
-/NComponents 4
-/Components [ 1 0.34 0 0.02 ]
->>
-/CSD add_res
-1 /0 /CSD get_res sepcs
-1 sep
-f
-161.875 105.281 mo
-163.221 105.281 li
-163.221 116.492 li
-161.795 116.492 li
-161.469 113.393 160.348 110.974 158.432 109.234 cv
-156.514 107.497 154.104 106.626 151.196 106.626 cv
-148.612 106.626 146.534 107.279 144.958 108.583 cv
-143.382 109.886 142.594 111.626 142.594 113.801 cv
-142.594 115.812 143.246 117.646 144.551 119.303 cv
-145.854 120.962 148.682 123.093 153.031 125.706 cv
-158.085 128.722 161.482 131.355 163.221 133.613 cv
-164.96 135.868 165.829 138.45 165.829 141.358 cv
-165.829 145.108 164.502 148.315 161.844 150.978 cv
-159.182 153.642 155.979 154.973 152.236 154.973 cv
-150.064 154.973 147.297 154.375 143.932 153.178 cv
-142.549 152.689 141.666 152.447 141.287 152.447 cv
-140.499 152.447 139.89 153.057 139.455 154.281 cv
-138.028 154.281 li
-138.028 141.358 li
-139.455 141.358 li
-139.481 144.919 140.642 147.772 142.934 149.92 cv
-145.226 152.065 147.904 153.138 150.968 153.138 cv
-153.873 153.138 156.196 152.366 157.948 150.814 cv
-159.697 149.263 160.572 147.197 160.572 144.612 cv
-160.572 142.681 159.852 140.832 158.415 139.065 cv
-156.979 137.296 153.972 135.018 149.4 132.227 cv
-145.674 129.923 143.186 128.11 141.937 126.776 cv
-140.688 125.443 139.765 123.982 139.168 122.39 cv
-138.571 120.801 138.272 119.052 138.272 117.15 cv
-138.272 113.48 139.476 110.502 141.881 108.217 cv
-144.286 105.934 147.418 104.792 151.276 104.792 cv
-153.396 104.792 155.707 105.213 158.207 106.055 cv
-159.374 106.436 160.19 106.626 160.651 106.626 cv
-161.034 106.626 161.291 106.545 161.425 106.382 cv
-161.563 106.218 161.713 105.852 161.875 105.281 cv
-cp
-/1
-<<
-/Name (PANTONE 309 U)
-/CSA /0 get_csa_by_name
-/MappedCSA /0 /CSA get_res
-/TintMethod /Subtractive
-/TintProc null
-/NComponents 4
-/Components [ 1 0 0.09 0.72 ]
->>
-/CSD add_res
-1 /1 /CSD get_res sepcs
-1 sep
-f
-216.34 130.229 mo
-216.34 122.917 214.667 117.157 211.324 112.944 cv
-207.98 108.732 203.66 106.626 198.358 106.626 cv
-192.733 106.626 188.244 108.741 184.888 112.964 cv
-181.53 117.192 179.855 122.837 179.855 129.903 cv
-179.855 136.779 181.519 142.372 184.847 146.679 cv
-188.178 150.986 192.518 153.138 197.871 153.138 cv
-203.443 153.138 207.913 151.053 211.282 146.881 cv
-214.651 142.708 216.34 137.158 216.34 130.229 cv
-cp
-224.653 166.999 mo
-225.182 168.304 li
-222.846 169.364 220.197 169.894 217.235 169.894 cv
-214.789 169.894 212.518 169.573 210.426 168.936 cv
-208.336 168.296 206.369 167.319 204.537 166 cv
-202.703 164.682 200.466 162.487 197.83 159.418 cv
-195.491 156.699 193.698 155.012 192.449 154.361 cv
-186.986 153.249 182.294 150.365 178.365 145.721 cv
-174.438 141.074 172.474 135.772 172.474 129.821 cv
-172.474 125.391 173.602 121.221 175.857 117.307 cv
-178.113 113.393 181.171 110.329 185.033 108.116 cv
-188.889 105.899 193.17 104.792 197.871 104.792 cv
-205.128 104.792 211.242 107.205 216.217 112.028 cv
-221.188 116.85 223.674 122.783 223.674 129.821 cv
-223.674 135.748 221.76 141.023 217.928 145.657 cv
-214.095 150.293 209.189 153.194 203.212 154.361 cv
-203.784 154.819 204.806 155.976 206.272 157.826 cv
-209.391 161.687 212 164.306 214.091 165.678 cv
-216.185 167.046 218.264 167.734 220.331 167.734 cv
-221.854 167.734 223.297 167.488 224.653 166.999 cv
-cp
-f
-259.776 146.473 mo
-258.979 154.111 li
-227.787 154.111 li
-227.853 152.591 li
-229.544 152.418 230.729 151.984 231.42 151.291 cv
-232.11 150.593 232.459 148.992 232.485 146.473 cv
-232.521 112.728 li
-232.509 110.965 232.423 109.75 232.277 109.087 cv
-231.885 107.234 230.135 106.309 227.005 106.309 cv
-226.938 104.792 li
-243.22 104.792 li
-243.282 106.309 li
-241.546 106.427 240.358 106.895 239.693 107.717 cv
-239.035 108.542 238.709 110.213 238.71 112.728 cv
-238.585 146.826 li
-238.59 147.406 238.639 147.937 238.747 148.429 cv
-239.27 150.917 241.243 152.158 244.665 152.158 cv
-247.604 152.158 li
-251.407 152.158 254.046 151.73 255.535 150.876 cv
-257.02 150.028 257.964 148.557 258.371 146.473 cv
-259.776 146.473 li
-cp
-f
-270.119 113.882 mo
-270.855 113.882 271.533 114.14 272.159 114.658 cv
-272.778 115.174 273.181 115.812 273.336 116.571 cv
-273.487 117.307 273.362 117.946 272.959 118.489 cv
-272.556 119.032 271.992 119.303 271.256 119.303 cv
-270.495 119.303 269.786 119.032 269.13 118.489 cv
-268.47 117.946 268.066 117.307 267.916 116.571 cv
-267.761 115.812 267.886 115.174 268.33 114.658 cv
-268.764 114.14 269.358 113.882 270.119 113.882 cv
-cp
-275.101 125.583 mo
-275.051 146.943 li
-275.06 148.436 275.136 149.497 275.269 150.124 cv
-275.441 150.994 275.827 151.583 276.406 151.895 cv
-276.995 152.209 278.309 152.366 280.348 152.366 cv
-280.395 153.792 li
-265.72 153.792 li
-265.755 152.366 li
-267.767 152.366 269.003 152.18 269.474 151.814 cv
-269.941 151.449 270.181 150.218 270.207 148.125 cv
-270.299 133.002 li
-270.282 132.177 270.23 131.532 270.133 131.064 cv
-269.845 129.666 268.923 128.965 267.373 128.965 cv
-264.189 129.372 li
-264.174 127.701 li
-273.424 125.583 li
-275.101 125.583 li
-cp
-f
-299.717 126.315 mo
-299.787 128.597 li
-292.118 128.597 li
-292.063 147.671 li
-292.063 148.191 292.094 148.638 292.183 149.021 cv
-292.508 150.597 293.372 151.387 294.761 151.387 cv
-297.021 151.387 299.6 149.906 302.527 146.943 cv
-303.758 147.981 li
-299.704 152.48 295.83 154.728 292.135 154.728 cv
-289.581 154.728 288.058 153.559 287.563 151.222 cv
-287.359 150.246 287.257 148.315 287.249 145.434 cv
-287.354 128.597 li
-282.338 128.597 li
-282.28 127.172 li
-286.584 126.738 289.38 124.034 290.673 119.06 cv
-292.14 119.06 li
-292.127 126.315 li
-299.717 126.315 li
-cp
-f
-311.427 140.01 mo
-319.449 138.461 323.033 135.679 322.196 131.658 cv
-322.025 130.839 321.502 130.092 320.645 129.414 cv
-319.776 128.734 318.904 128.394 318.011 128.394 cv
-315.972 128.394 314.303 129.597 313.017 132.001 cv
-311.721 134.407 311.198 137.078 311.427 140.01 cv
-cp
-311.381 141.522 mo
-311.449 142.227 311.544 142.894 311.677 143.518 cv
-312.7 148.409 315.455 150.855 319.937 150.855 cv
-323.197 150.855 327.513 148.887 329.655 144.946 cv
-330.741 146.066 li
-329.398 149.104 327.935 151.306 326.357 152.675 cv
-324.783 154.045 321.037 154.728 318.351 154.728 cv
-315.466 154.728 313.074 153.92 311.172 152.303 cv
-309.267 150.685 308.014 148.396 307.389 145.434 cv
-306.327 140.378 307.15 135.782 309.851 131.634 cv
-312.566 127.493 316.063 125.417 320.356 125.417 cv
-322.045 125.417 325.076 125.848 326.24 126.703 cv
-327.389 127.558 328.122 128.707 328.426 130.146 cv
-328.937 132.567 326.205 134.854 323.48 137.016 cv
-320.753 139.177 316.713 140.678 311.381 141.522 cv
-cp
-f
-99.4053 111.543 mo
-100.078 112.706 102.917 117.68 103.487 119.283 cv
-104.129 121.095 104.264 121.614 104.264 121.614 cv
-104.264 121.614 102.707 113.603 100.152 108.928 cv
-100.712 107.038 101.381 104.949 102.138 102.716 cv
-103.023 104.269 105.034 107.836 105.761 109.526 cv
-105.788 109.207 105.815 108.888 105.843 108.572 cv
-105.199 106.097 104.221 102.857 102.969 100.318 cv
-106.183 83.5933 116.528 61.6929 127.673 49.8696 cv
-50.96 49.8696 li
-47.1719 49.8696 44.0889 52.9521 44.0889 56.7407 cv
-44.0889 138.125 li
-61.4629 131.457 82.4121 125.362 100.442 125.623 cv
-99.7725 123.042 99.0107 120.708 98.21 119.355 cv
-97.7979 118.657 98.2549 115.79 99.4053 111.543 cv
-cp
-/2
-<<
-/Names [
-(PANTONE 2905 U)
-(PANTONE 3005 U)
-]
-/CSA /0 get_csa_by_name
-/TintMethod /Subtractive
-/TintProc null
-/MappedCSA null
-/TintTransform
-/0 {
-1 3 1 roll 1 3 1 roll 1 3 1 roll 1 3 1
-roll 6 -1 roll 2 index 0.41 mul 1 cvr exch sub mul 1 index
-1 mul 1 cvr exch sub mul 1 cvr exch sub 6 1 roll 5
--1 roll 2 index 0.02 mul 1 cvr exch sub mul 1 index 0.34 mul
-1 cvr exch sub mul 1 cvr exch sub 5 1 roll 4 -1 roll
-2 index 0 mul 1 cvr exch sub mul 1 index 0 mul 1 cvr
-exch sub mul 1 cvr exch sub 4 1 roll 3 -1 roll 2 index
-0 mul 1 cvr exch sub mul 1 index 0.02 mul 1 cvr exch sub
-mul 1 cvr exch sub 3 1 roll pop pop
-} bind /Procedure add_res
-/0 /Procedure get_res
->>
-/CSD add_res
-/2 /CSD get_res devncs
-level3{
-gsave
-clp
-[-4.01667e-06 91.8907 -91.8907 -4.01667e-06 85.8809 49.8696 ]ct
-/0
-<<
-/ShadingType 2
-/ColorSpace [/DeviceN /devicen_colorspace_dict AGMCORE_gget begin /Names load /MappedCSA load /TintTransform load end]
-/Coords [0 0 1 0 ]
-/Domain [0 1 ]
-/Extend[ true true]
-/Function
-<<
-/Domain[0 1 ]
-/FunctionType 3
-/Functions [
-<<
-/Domain[0 1 ]
-/FunctionType 2
-/C0 [0 1 ]
-/C1 [1 0 ]
-/N 1.3901
->>
-<<
-/Domain[0 1 ]
-/FunctionType 2
-/C0 [0 1 ]
-/C1 [0 1 ]
-/N 1
->>
-]
-/Bounds [0.920245 ]
-/Encode [1 0 0 1 ]
->>
->>/Gradient add_res /0 /Gradient get_res clonedict shfill grestore
-}if
-level3 not{
-gsave
-[-4.01667e-06 91.8907 -91.8907 -4.01667e-06 85.8809 49.8696 ]ct
-clp
-/0 {
-<<
-/NumSamples 256
-/NumComp 2
-/Scaling[[0.00392157 0 ][0.00392157 0 ]]
-/Samples[
-<~s8Dikq=jUToC;><mHa'$kN1daiSWMJgY1<3e^W'qd*BnZb/q]D`5BI-^V.:l\[],V['Hs@Y-"e*WMl\j
-UnXQUSt2C?R@';*P`q5kO,]*VMMR%BKnFu.J:;ooH[0j[G'.kHEH#i5Chmd"BP(gd@q&kR?<pf?>$4p-
-<E)mp;,C%`9hS)M84Q-<6pj:,5X.Fq4?GSa3&``Q1c$mA0J>%1/1`;$.4?Pj,pX][+sA'N*Zc=A)]BS3
-(`*r''bh;p&eP]e%h9'Y$k*LO$4."E#R:P<"U,#3!s8T+!W`<&zzzzz!!!!!~>
-<~!!*0)"U>;?$OmRW&JGio(E",2*?QCI,:"T`.4Qi"/hf"91c73O3]fGf5=%V'77Kd=8k_rS:f1+i<E<4)
->$P?>?t!MTAS,UiC27[(DfKf=FEVkQH$apeIXm!$K8#&8Ll%%KNK0'^P*;,qQC+)/S"-%ATV8*TUnsuf
-WN*##Xfek3Z*UgF[^WcW]">Vg^;%J"_Sa=2`lH0Bb0/#RcHjkbdaHUoe^i@)g"P38gtgiEi8ESRj5f=`
-k3(sll0@U#m-X3.n*oi:o()DDo_%nNp@n@Wq>'m`qtp<hr;HTmrr2ors8W-!s8W-!s8W-!s8W-!s8W-!
-~>
-]
->>
-0 0 1 0 []true true []
-/DeviceN
-GenStrips
-} /Gradient add_res /0 /Gradient get_res exec grestore
-}if
-np
-149.133 44.167 mo
-143.681 39.3052 137.08 41.2583 130.565 47.0405 cv
-129.598 47.8994 128.633 48.8516 127.673 49.8696 cv
-116.528 61.6929 106.183 83.5933 102.969 100.318 cv
-104.221 102.857 105.199 106.097 105.843 108.572 cv
-106.008 109.207 106.157 109.803 106.276 110.31 cv
-106.559 111.51 106.711 112.288 106.711 112.288 cv
-106.711 112.288 106.611 111.91 106.201 110.721 cv
-106.123 110.493 106.036 110.244 105.933 109.951 cv
-105.889 109.83 105.828 109.683 105.761 109.526 cv
-105.034 107.836 103.023 104.269 102.138 102.716 cv
-101.381 104.949 100.712 107.038 100.152 108.928 cv
-102.707 113.603 104.264 121.614 104.264 121.614 cv
-104.264 121.614 104.129 121.095 103.487 119.283 cv
-102.917 117.68 100.078 112.706 99.4053 111.543 cv
-98.2549 115.79 97.7979 118.657 98.21 119.355 cv
-99.0107 120.708 99.7725 123.042 100.442 125.623 cv
-101.954 131.438 103.005 138.517 103.005 138.517 cv
-103.005 138.517 103.039 138.986 103.096 139.708 cv
-102.886 144.591 103.012 149.654 103.39 154.23 cv
-103.891 160.288 104.834 165.492 106.036 168.277 cv
-106.852 167.832 li
-105.087 162.345 104.37 155.154 104.684 146.861 cv
-105.159 134.185 108.076 118.898 113.466 102.965 cv
-122.572 78.9131 135.206 59.6152 146.769 50.3994 cv
-136.23 59.917 121.966 90.7261 117.696 102.135 cv
-112.915 114.911 109.527 126.9 107.485 138.387 cv
-111.008 127.618 122.399 122.989 122.399 122.989 cv
-122.399 122.989 127.986 116.099 134.515 106.255 cv
-130.604 107.147 124.182 108.674 122.031 109.578 cv
-118.858 110.909 118.003 111.363 118.003 111.363 cv
-118.003 111.363 128.281 105.104 137.099 102.27 cv
-149.226 83.1704 162.438 56.0361 149.133 44.167 cv
-cp
-1 /1 /CSD get_res sepcs
-1 sep
-f
-0.5 lw
-0 lc
-0 lj
-4 ml
-[] 0 dsh
-true sadj
-27 175.304 mo
-0 175.304 li
-/3
-<<
-/Name (All)
-/CSA /0 get_csa_by_name
-/MappedCSA /0 /CSA get_res
-/TintMethod /Subtractive
-/TintProc null
-/NComponents 4
-/Components [ 1 1 1 1 ]
->>
-/CSD add_res
-1 /3 /CSD get_res sepcs
-1 sep
-@
-36 184.304 mo
-36 211.304 li
-@
-27 36 mo
-0 36 li
-@
-36 27 mo
-36 0 li
-@
-345 36 mo
-372 36 li
-@
-336 27 mo
-336 0 li
-@
-345 175.304 mo
-372 175.304 li
-@
-336 184.304 mo
-336 211.304 li
-@
-%ADOBeginClientInjection: EndPageContent "AI11EPS"
-userdict /annotatepage 2 copy known {get exec}{pop pop} ifelse
-%ADOEndClientInjection: EndPageContent "AI11EPS"
-grestore
-grestore
-pgrs
-%%PageTrailer
-%ADOBeginClientInjection: PageTrailer Start "AI11EPS"
-[/EMC AI11_PDFMark5 [/NamespacePop AI11_PDFMark5
-%ADOEndClientInjection: PageTrailer Start "AI11EPS"
-[
-[/CSA [/0 ]]
-[/CSD [/0 /1 /2 /3 ]]
-[/Gradient [/0 ]]
-[/Procedure [/0 ]]
-] del_res
-Adobe_AGM_Image/pt gx
-Adobe_CoolType_Core/pt get exec Adobe_AGM_Core/pt gx
-currentdict Adobe_AGM_Utils eq {end} if
-%%Trailer
-Adobe_AGM_Image/dt get exec
-Adobe_CoolType_Core/dt get exec Adobe_AGM_Core/dt get exec
-%%EOF
-%AI9_PrintingDataEnd userdict /AI9_read_buffer 256 string put userdict begin /ai9_skip_data { mark { currentfile AI9_read_buffer { readline } stopped { } { not { exit } if (%AI9_PrivateDataEnd) eq { exit } if } ifelse } loop cleartomark } def end userdict /ai9_skip_data get exec %AI9_PrivateDataBegin %!PS-Adobe-3.0 EPSF-3.0 %%Creator: Adobe Illustrator(R) 11.0 %%AI8_CreatorVersion: 13.0.2 %%For: (Mary Diarte) () %%Title: (logo_color_eps.eps) %%CreationDate: 5/25/10 11:06 AM %AI9_DataStream %Gb"-6Bp2f2Pp#o2n/pqR,4,%FCG'cqcS6#7\b,MND(@139M]b(.+f4cF,#U)U>4f'lQ=CZga0;4=HqR+.hQ;lS]&LdEc>u@I.>23 %q]F^Dqtf,mGOPRXQT*6<^3Q#^]MCJ(9'2$brlaWb^%u/7-/D=Fni+nSD+m-X<]f0h<-*C3hW?NRp>"X*b9,WUHM?s1&+<l>qVd5. %q`!t.r:$QY@eYrRS($[^Y>4ON]RB>?-JqPuoA<r0J,\EGGH\`n_;>RsO7-Dhq=33@?bLaTo$t5LppPVL"+66G_;E"Vp$lPXedl-E %f\r+m++O(\r[knTjqhClIe3HoroSIcl4e19q3S5Cs4r6Tg&tH.m=5(!rb6'5bF@`Sf_44`DPgGmRtgB[JFB2ck)1d=>MFY\SU'T^ %Df'`(IdsVVHhH4\+$P-unaZ;LGQ79$4Ehn(J,f5]L]?1"qeUklES7hPDM(`iorZ[%fMm-9i0iK;HMdZ1(E[#CP1hnO`g^!`%_m%t %[T9d%ee_Y:(Ya7?CN"gNe98q#]2C+Ae(=TLT3f;/pFgH6rSlr)G9>`Bn4-[EY?nsh7+cq_q"<tQYH<&=SVB6?6%AXhRo^^2q;(@t %D*/:nPofhqqeoiT@1YVLHLh3hI_oRks&@tO00XdXl=7`gpMYM6g%t9:a;]U"j4i`Mrqu$`+V)0C\)4rHp\X^b%=@urg3?h"[5U:F %>ALpeZ*uU"Q+,&*S(`=2$/\^"6K$I!"B]C\>(a9E-*SQ,CA@Y[&$N`prU*>H@fGL35.pm'j)Dni6N7XLPi5u7J(3:4nrFl"^#SNb %pW`]h]q&lKrUne7K&?Uua1)*Bm`"KMD:Z,7dnOO^\SF1smdT5rM_B"3\*iCn]_XiOGCTSt>AIsqn)=;2i;[!>s8?8shS[Z/*YSA] %hg/)USkec34d?Z08dYJh$#6:>[8K&VUs3)::9@?j[LYK+/(CR6C;FiX5LeEUU"4Z':[[uHc$g1G:+,i1F@lk25+UX/dtsZi*`IQf %5P.GA(7pcZ]f0<6s%j*C"TLh@(mBoC^4R$6s%iqi"TQBLAL?VD(_cfXJ&-s!IqX]$M->WG_>c3,p^'b6'>0N@PMQhX?sN1ce2a'" %-L1asV`CVWUfi<Lkt)dRoq)"TIA=8=cXi*3#(<-[N">oCQ=pG9eFXc`)#T%j0KrWJRMC,a`WuO]?SFNEJ,#X^%M8CWC;K]'Ip,:X %&t2mJ5J0j4!.$9m,ATdIUKN@U1iG-&1ihkEoUPbHn"l=]]r6[5TFQoU0G?n\:Xc9,>8SI[&%)\X@=0mZoITnNF^T=R$c-Z44#D$N %#/Y8o@DN\p2X!/0$K6U'$X$DsGNp3n3k^mB%=0WW,%IC^6S3RF[8,&sp[k/Ne'94TVDY9^Tb^Du+oL`>SXqQCaDUB,9BN565%1qY %IE+Qs]&Sn=oY/I'bC(D(7l$:tFIs$,X7TKM9C:/kekZ!kT0sDGJ"39PqG6s@5_&O#oJ'^k8<Eh74uq*Lr?m"cTta6_G8L8FG4\N/ %8Y<UVqRcd'O87dS+@uN(TAu(5mQ]qll%eI_X<%47lUlZM?hC[ac\6e'Vo&i'o;_i.mW@15Bg3Wl48(l+b3=ug&)n;$`;fN2NNHf, %I*?\Kj^?"(Vtjd.=oN5k>GIh)oeX$8jn<Pd]W&h+4nKi(fm;NPgAXs]NT8`44aZFkq-jYuNEuSG@r&Q\ffgZ#GOhrbcJbs"s5IqP %C?p0B^BA<)L<Da9mWl+?NP3VSl>sVoj(j"uk-k#k^Oc::E",u7_Aq#<fDY?@NuQeqVf>0;c`kGD?SlQaT@EJo2e*A.h80H]D/*n@ %FmGl>`pL4+mMXUl(_")pfQIMm0E6]L_f*%[gq2.h)-4*[YuMasF*HE#46cP\1B+);V11[hZN9ZV/%3p@?MRCk/<7>qq5iTNGL08* %e"qPu^\_Ad#'&/tRa<Jmob.\VRf%?skCBW1ja7,8CMhqEqEKAgJ>oe+Ai&j)[s2TTT?dIP4WjYATAQ#-376K@L"U9\hodX/]7tV& %3BD0I"&NKFHhA%b9d+p2gFCM2a$FJG>",TbT]bn#eka9BrF2Z^4Gu]lYIJNFs-.M3^D,:mD4K]4oF,NlqenG')BK2JF=5[83&i"" %#9sZN#>hZST2(2p0HPJMnO>2S'C\Zn]P@6%G;A'X2eRWWSE"NM&pKk<UNfu2EK@R>p9A%1HXDGI&24i<U$VmY&DdFNT^Sl!eec89 %)RIYI%CBRhKP+jR^Ouc0Ra^Ohla4F]mfD=h3"GQ,HFX:G8)FpP5Y^UaJPLGlDa*JGIs10oUDP]rGWrq7.'qi,1cIDN`1o!V?J$XP %$`'!U7)b`F>bR!d"ibu:^OrU<ckbG?b_%+*m&;p/NUV@P)t!A?ILid&*#Gb*c!7)k4.]<:5?I_%Xae3FXlft&?g,F"0nFNucNW;g %r_<;0@0U_(1,h;["8&GKGbX'9$kU/X^Rb6nZ_Gr+@9\<P6$=[D+IWn4K=_fc1%#Fem=`7CW=OS4=8Y^=9$$3P4O*LPot<Y>D85Q0 %4`KET\Z#.*@mG3tp/iNOlTCA=^77[^N'6gdg7G\iG72$(&%Ejo0V#t7)7CYPJj%'fT?e5FZneI=corR)`-d].,mZuUC^N=XQ*G\P %[-`@D3DYJ2Q.E$Fe9D%eQ8;,\&^mb\F'<ij-H/iXs0s*VkCI"`DrPS>Oq&6ln]YieiE6679CjS(Esp`Y?6FWN/&.E2a8L&BoZKb] %kA;7+n^>(t%\<RQ]-G&M,l<\c-2)Vp,J:p6CFu5\4A.M@4.\0qWJ9S(nSuSh&R-;1@kr)k6\;3BDt6cV;s4DPBilII[=Nes9V$p0 %o=X%RCGQ4UE74o/NUR?WAM6-2c=]2)[6I"(#7>Ksp>@c\hSENqQD*KI+0M+oprTj44&jKnI.r(05LEi6*.-@q*UeM._GbQ.a^!!W %KQST*J5;u$O47CPoBW@7JZ6kReeL[2hAqFGaUC7YMk"1eJs+\kraqUFm&*)@)K@MB41^C[kR:i2SHFD=ck`\hltSXMYFB*L47sLP %0&Y"<";WJXOc+;%#>d#2$q>Q&Vph5460O_WG'c8*KoQh,UOFEokLY$>YgQ!Q^1]_5r-%KU@Jkei&"nkHNEb:`0Tt#Y*V2cmB+r>4 %E*roq0`KkLmb?^Si==ZY^k]qA+:cl7fA;]:Lt!:rde7Z,i"\gYg/St%lq!6On0s`73:X,Pifo64L=,'&;8kH%$M+\p]j>2j,._s5 %%^jjaiqVqGY[GgrqtG$FhXlHQ2ST%Wrlt?/kWA_`^\R`V`ui&D,7XYNc#;IJg99Cbl,<K(^FA&fp#a<geN\G+s5WkRq!J[]bqF7t %^AkZD2da8nprAl92m;(dqnk(*(e0#3ck?lbr:Q[g&a]51lgK=KZ+]%E!41=%2o#=#s7P[=a7_1hqJTa@q"j$Oq]#D.-!5d`gt[>Q %nV9?cr;QZl2ql%B=5$@Q,8BGCFhH`bI,Nh!hpG-$ho$7qDq]X7pfI3U<r;e6g6[<6Xm]W0H1UmE%kkZsj6N%90A-&+haH?bi+8fF %00[&6cf:Ygo*Vl&o@nbAs5rtbD`]ieOKVu<q"X^IRo`tsq1k$7hVR/DiRK%,Is=%K)a]VSrq,L#qsT;8.ceR\Df>XPM\"]PC)WE& %&$Ol=gNEkjk<=mohgQ)r'fTM"n\t7+Ye)"WGf#nV?\-48?G(XTi<J8p,`nXQ^Q"i08J8kHdJ-E\N$IS6p<;0Y]6=?cr.be9^4"gN %lBaHEpucki?G(^ZmEKh`\uEG$>JQ`m`nfEuC];l^b,!b6Y*HV"p?BrHZ'A7Z>-Y3><dYCZ`)[Kg5$Fqfm.+F4qc43/*:kVO9UT(h %XghCo*+80,N$Yk5c]qC4fsPkPb.a-.3OWrXV`M4p>B-e?<^Md')X&<V%%]gbhl`6V<qc45b-@414mf+ICb)Y'hb%PcQ+sH.Nkuao %_;3Ce*N#*M.u./cXdjR4];ZP"MJL2?&mC-o^s'SRTu6A+Hl/tDqc42N#BP**j`G\JVIOOKEEIT=Tp=8&_?*X>@r>T0j85MR1tisR %3FZ^CVu^VIEDKD9.iq>s-+8D@"S7$i=C;n`+:%*=[R?E+/12k.LoLt:%Z>6O@#8!)d>r,NO16)uSCSq1bn5_$SYJ*(7tW^u'9pta %`F<gh4I:REE_0LkQboT$T/kjSEk0Z)f5__NEE7gTq9KMH-Xm7Q+;Rb/OqXSA[,Zb]NGRSqPq*)M6]X9q#n)3@F]^bmJ0eYr>]?`G %`-Y_!+?E]E.D+bpCMGE("]*giL#+$rO!Sb%=;$tE"ZMjM`o3M/4"c?,NmZ2o\F@p.=ec:]%#a#`IMV<Xi"ERG/t#Ak;Ru/$gi;"g %Buk'$LQ>UA5:.sEX[,H.mgo@1[3QCuQ`R#sWEOIKmY8%!EfabaJ&e7QHAU*Im&[^"nRF:./B[gQcB^#XU%AIYr@&h8^6hQ#IR8$d %EhBhrhk5I$0b8]jRKg[m/EZO^2aoOAcW`S3K1)U<5on6Z6s<lX52RMP4sCHE89P(Jg5MhMLW&gMZkI/N6Rpc&UHsK6OoFa1hOTbB %&PWX(_D2b**>0`m7jk/r%d?YTE`/!81brL$4rf[b=PVc?Md^gq`gVF''i+Kj4$c[0\?V#MHR)3<V3DqB,HTE:frC6EY)51gi2.-- %;k9+=/rEf1c9<ObS-h#HSS;gIP<k5N+g2%(;GoEPZUi.[+`g&QOg%9m'NO]s&RNO,,=H@0YX$,,&c3f3%rshWo+8Z(g^\<b`96Iq %1-(oEJWkI"31J4D#Y.g+]Z`[O(hR3H)7ULA>_I#-SjiDhjAh"5=g0:VF(1@ikr_NXfTA0=Z=ZBlet`1+U*es(4]koU\MY>\>C:dq %"TrZ.c(XgsY4]*/*p;,OfLFlTW%9F8:9E!#2Xn=:$.ZEYaDGg(RjHtSbC[aINU20OHIq;f[V=$(_IK']h\O&rVq,.@JO<Y;]=(tP %/R30d(uaC/D,";?h5QD#f]II?h!D2;6##PE)I`h3_d,WrWQi8a+j_9-C"JHH2"XDUPW*.E%IIuL5b,&g>I])KboLj!V4hZ+oiN`Y %Ts60_147-N`-XoE>snF>U-rbN+<X&1g;]N6*bd-ECtiN^'$7:nT`WuED5`7pbI:1M/D&B2as1:hgOSKTdCKLE7W-ro5+ugp30UJ$ %'<^s>chW!Y"Q0J6nd-0oLtK."0H(Em_1\o3&K-ltnhE5eD[LMJa[af.8O/^Gr/uc/TV3'=<e/YGjLns)<FjC*9hWPK!)iu\3+VV! %j[4,P!^Copjq&@u?l=N@"@a#+8f0't)ULA"e)4C(1t%5Nl;?B8?mcRg]/,G*'"\OIKUC]9<Y?g&3lj<.a([c^q9r0ohgFt=h1m=+ %?M9\'E.8P!S*J_:+i6TRRkML$fL'jIR*0CEpjfQWNQRR\429iBca7mQJP@D*Oe"/h)?"Zj\8A^nD$sVT,&YkI7U"1d*7k*R)_3[: %J3R_a>Kqi/lq(u/I='cEp0ZQ2(3$S`J+Ro9:>TE`_dmgMCYQ$HkN0.CX/XG([1D1>Q$+>fW*u6X[8>sCT'WCrEjrFsgdCC/5/=9r %m7=%qek4cZ\Z3>[`$:=[?W3M!p=4Jjg.7D"4NJ/2nheY4I9#`)V2M9]b9jMO0Oh,V$P@i;:a$=8?&<\lK&$c)$+I-O^$WRVCn[&Y %n.$=dG4]-f"Au*0W]&Sq2MGNZ9Eiu2^YhL:C,*rdp!<,ZUdeL\5&,m3lT9UNpppOQNS+)hkNH4'p$L_5Gr.!eWp'N=RZ<%.D2Dq; %f"\TR4au8YeDR+F_&ONjfe87dK<X-:/A&6bnWn;tb!sL2P%H$66I`"O586$jX(@HgC-GZSda/F%O:Or(X>\n.$FM)P>EAs4a9<sP %KHkNT!BFVM>d6ZAfG\.YO[2/cPC1;_g*<YGL[=RAV&[u[UXYKhF[kL2[9=(9B8_/gaY4Z^^eP1d>uB:F;=toA/2]04`)[O]]jo'N %=_fh_er@:Rf"*Zh"dS;i>^+bf)!h.9=;+op=D@q#[5-7K:.Jlk-Y/s.Kbieg(h_UUOX'G?`%)Lfgc/hsbjcb-@UP%D(N'I2EkoKf %<oeIUe$[9QmZF3faMPMXpjlS]CRf*.51CaBq(&6*^X#lN)Z6(An,`A;F+4pSH:TdgbOMTQ\>M13@oNau06_'ODPP^d(m[UW,qhlZ %Q+:KfN5bS^j+a94O&>-jecV4_7I!%?m+[E6+*Uu.,Z2)d/n2X>H\Q4\7JH7R:kk#g+tp"@Ht)[R*?uahhm(.sc33>`6E:Z7#!$u^ %8KVQ-oT$n(&Y_^E(?&DLk"0YZTCqg*i:&aU=tpi.5!5bdIprV?jLX-;/\B9%L<j2KU?"a7ZP&&1egc;:3_AWVenPdIkG3/B+(8Q2 %&Shf<6"M>W1(+mN)%2jmac%39Q0D/:ktn3j=[@0s`MTr\STdM/PZ^dj0-bP$_DsBTa;j2*eXrW;XbJjO`-TeG4J+<S_W2#M-]FTM %FeTFIQ)IP<Y3SKB)UVD(WnL;1f1''u&YEZs;%ro+Y\4'FT#@65GLh$qiQQs.",1@Ib1bPn:M(MDQC0%O1[`'V=@17XE+9+u^'/d: %LUnhj`(HeY5Q`T-IdAENZgD"bo:NKS2>BaSp+btkJ,VeS[+?"5>r=69fTOJpd%7Bma(6u@O?Hhsqm1tnQTHG,B\@6g\gh8kOR"XF %r,`^QQ\>sfJcQtg^2]U$*C$=(i&$[nQ9i%4Ei3J=7LCkK#aa)d'k4C<C,AtOIV-#*9GXB-*"oU%Q'2=2mK`POf@uN;^SiARY33qZ %&DNZgDggk2o<#4k$"%Sd>'gq:f9<W&'?dRM24:!=oqIAD9GM]pf#O:jqmGLQ9(K]bO&JKYD%hZ1F05(`VHqnR*\EXHRgLE%F&",M %m.%TcB+/Askr?/maUk2j4CR*f`n*rWRNpMLTeI<f(@H@@_qj-WcfUbF(Lc]gcj`-pS^JuLU@#qY!F-Z]At36Ve8rt'-8(!(jnfdX %$/JL[&YNTI':c%2no"$]eEp=$+NC+5h0;2G+-"Qc)kH#^=hi)iAa,%,qP(2Q$@D8&?i^<RJY5;?T=d=6iLSKiY5>(aG-2LF\t-FZ %U%96cc)Ib6366q\S9Vnnml0c^l[Ea:fOid6D=h6]h8&6Q2KqPV0A]gAOR;:mbMJ?/<E6k*/`QW[pKBe;ge^I_72q*rn%OK_h#*?P %V6!:S@f!:pQ*XKY/scH<bl#e\*'U>A9fda[nur<opD7mFV2(;-6%e1=k)aoM7QKmeC,CeKoHGKUfHH56+a!e%!(:7N`./iWJ,mC9 %VbQ(B]"q,/e0BtNdCLis=#VsU65s4Wk3cmGHtM$-hp.b<`:[ru?-gmnN*O[k]:Pk8CS-"JgF6gcA`'cq)S>=A\,O9mp&-M1KtDeX %fG>&Un_)g+"cN?QeTZLPcC#B-hQTU0W$B&:o8>tc<k!NtmB;.p^Gu&HM6"D%@h[A9_KMH7L"9m$XieHU)u\<X.;+mc>f*e62+Rf\ %5,jnQi%3!^[[>)on[!"MU`cZ,*ft>okXT<A,Z0VtRuhdn6W"eK'BO1*2h4ab,1-CN+GBmn+ZT=L@_`9\oE*<WU)$-Ii6W326$,GL %`(2#<3#Hg4[7V8+i/l+LW#NILF&,cgqJFt+NmLojU@)T600E+p^8O13L]()0\>2;2&8)l<F2t_$2EttF%Q^`cTH),Z&$bb_`EW*Z %3Rk[bK<g+I"GeZuN2"8H&Ao`(q,qtpD!7m[e![M8[ht#`\uX"S-8KXJ[:?_TR-UgPh)*b5LdqcK+;Y+-b=VL@OBP1a+_aAU<=r*> %b<-(W_6C]Pg09$L=+9B^mq7[OaJB`>%tme_HHTr5fB8i`Vh&bh"<s:;,iUQp;4*b+(t!DPckqimT(T3&N(_q\7mLtc#EDSBZ=CDC %X/nc?9!k>ETHfS^P$rV\CFNNbB/c(#K^=IL:^k68<%k.\fhJNQX\2'gXP(-afec%A8iU2%$5=R`bU3+d"F#>MO*UM5g0iMn?#VV' %KbSdR>>WdZ8;8$+l#dFNI'7HeD#7[70D0j.=FY)a9shB.gF&c]FF\DFA8aaOIH/4^Z8%<'QXB7r\MXp=jNPC3Y3,82j]>_\][S)h %=tQ#JeP^+YAS!.o-`k0O.[:*+4m^R5Mi)<ZTfn*fL(VF9#!L-(RE$`P<H2Z/2+p$JV\_J3e@4oGEd(54f2]GsI)ZB4@q6J;]Iqeq %-=#g&YZ3m?+62=_*ACkXNK<Tqm(t_A0p2oSG@HMI--,3l[Zqqs2qY#iK1>GQ*jS5pKG*9(`<pm4F*&BX1uD"T<Dk=,DJ&J-h+"sO %i#3%1%oBWnC=]Os*OVrM_aY?@UIpgFcss;#A#F0]at7h8:[t`YTt8qJUqo!,W4;bkP"WdG[>&H*XgFrKh+E?kgKf3EPQ3(2XpplA %0EIClCn5Lr<(>&e#?DNL_WjJ/E(`T5VuVq3qWmGbo?.6.UNbPCW<`(qdDoPL548!LnI9,IiLaAH)Z88IfOQeEi@OMtnrO(-?5X^$ %gfl'hXI'H0O%\S@`m!5uXR4?"D.akNpEJ;[-JA#@=o+Em4sjl\1c[+Om<=ID$H7-g8hWXs"I<?qETN&j7`X_6EO6F%pR+6A%K9<9 %ek[rRIjkmVq,/pe7'p7.q9CRoN,!6hrjl)*bj"<#;+Bs$W-M9p'SS;6&Ihd5(ASXrU(&@7QjBgm4>Z1pld;Dl$;jdVVC0YIE9+7% %""Eb;?Ukc53<MQUj^'\jC.-YNGn`7Y;V-a/NtZ79%iRfXLN?gX'Eo\:TI=8G(;X5Z.ZJsU5su:t7+*VpJ`DCe-]YX0GUjEVZU'.) %E5hr@Uar*K"Vh[cA5-#'BaQ1^;6]6U"GK_eT_GWG*0)n&<@.:8_W1f`F9$_"/"SI-.Chg?HUPHU6V",/"R[_Qi@iR9;gcJ]I)Am1 %_bV<1n<ZpJp=/#!K22q?UqnPp%Y!jDKg1!<O8f(E`]%#0KFp&".5c]O@1-#/c$2>=4M]qTWfL+KDWfhqo=R/C+CB>1&b/h'A6J5t %+s^Fs(Pr-:n8bjn\i?YocC]o1;</8lc;8^tg7N/h!J22*;D%9L^U]`WkF0Q'^ltm>_=DI:i#fu3Cce]DBXFtE:Mo"<M$N\IdE&Yb %WQ/;8WTSlMm$#RjK7>N`4t%]I^1&/@6s&VNMX8[`5tYcRjiH9))/Cs.W0=^5iES+,.d+t^k\X<V(UMO^DeQ%M;3K\6C+S[U]o1Ag %MfPC")c+)\S5//6Ye_\Ed$#C38Ib;jX+C7jqt]]b_']lh7)GNdfMAZlrX#a5G\Z`I_5@K%XhhaU?2Ito2?'r6A5>3Fcmr!TGZQU) %cWl*N^<5K#O+(%%k_JI-1lFGM(=:S5bKTBaSc-5ZmP\k)oZ4GOafe^HWs]-7I:05LKmS(9Wp]/$JLg%>gTJAqlRqWB\?c+>m51)I %Q*0t"eOQ@W[#H`fgsE=_RDUU7bUMFb=QnX6>RNrrS/0GA0grApCFF2!+lYh"=b,L`m(UU<I+AF??d0<0DS>fGI=1C5DW`d4:R;4^ %#;u8oo)#'&l$lu^s,F,ZAk9sc.Bic:)>t)^>g2?Fb2g=.a'Y&*Et$keL]9,^s"])=B('*&mcVOeAsKiTT!c>rm%4L0EP2+IZ5YDD %lSn/N46Gg8?@fL",nK?t\sp[J@<@uA"Lf,ZoZ@Wbq<+aQa^#Tc7Hn,/8]qXYTa/J<q8"?k*'u6Tj9J1O8]X,is!OZ'NuNZsV;c.( %dL;<#OT+CKPeWgpeb.T(ab1^>d'_P?QD2PKhbu@qR9?=DgBr'3X0TrM5Pd;-XVar*;qIs=;uMrDX<(Cj'<0:QFl?,gH(0i>n"YO4 %kfM[Ef@a6]Ya9\1:9T!67b1:.?KgBt/pD9)eDXXjq$s]!N7W&;FY:.]qsKb)XaTf!(\r'0B!(D`5$lWV)D:9QH;-n+Dt3@l%Nu1* %<QBY>6X^4>Vr$C.FqXWof6*0V\1!tE9I92FNfd(AP4(Tro@2\sK22sUX;ZJ\'2K'$2>G\ZI1?2CWe3sQTg1g8gmH(E2K+CV-?-`j %M8q''[Sned`e>\L^XJs\W]nWZWWo#G3HJ'jV/**?/u_l-YL+l#QPWV.DrR<nSS-7'S@?-i:G8JL?(AC^bKUpEgb2e$]7DuW(rU-7 %'W8EfYOjq;rXd/-G?@BakDk0TPD4-^n;&pb_alMQQ(pAb3raaskVN(Q>j]`)fptJo_,\E9d%fZc)SG-\Ec8MT^@I@0WH9cf]L\oj %+hd'tEti]hX0X790,J\Pe[t.)\[LLlCnse$@a9JrJ5U_KiuangR+XWMX$VWH29rIlZF\,\?fj;^dLS#%0RC'43.'-%R6,i*0B+^! %YLbdYLX*Hs/8%nZCu:=13p*X$i&<dNcaoX=93\^h-!mKa2Z:J\:KA+S3IRC'h>n"elrRf?2a5OkSqg:fKbaIMFNU+M\`ZmLRS\:` %8>nXHV`[bOI-)%WUM5q4,fr`9B=X)dabqU#0"JpB<=%e>B@q9cr9-Oa8SR$q*:sa:i7Z$69ZS^/I,s)'hL9bm"r;4njNOom^QgS. %&"*H@(jHb3p3^7'hD#c6AhGt4l,hF/YO4H@g+"?B4<Jgo#*-702%_gE!PdY/i$V;"mI,WE!o59b2^J8a@@D+i\/>kt$f^%a@b_QX %bT^3o7&5d?ZbnkO&4oWQ((Lp"imJWJm5nS1,Hdua2%7!.)&I%C9-YeO[N(Y&D`r0*l`0/[Y3(W=>qb%-\h)71Z[-Lr#.l?t5&tB( %V/,EMa##CGVp*AQl?':9a@S!&VbYBf]_0j0&pF-(WMWM?:1':UG$6HH\^PAgAY$C?-0RLScObQUVaF4GIcAEte?aMDJ^of93SK5B %j5^p@B;6H7HAE&!?V[g(d9@%VGqFer5MG5/mnA89"eAd=mV9C&COTF=q&AKMh`%_SC,7eJ0?X,Ljs:DH\tdTQK=k7/oPmm^2LGCi %fu<WN&oH3".BCmQY2SDa]^:/!lPhsP2hC2S+[ifB9[8-)H!#^nh4B%fMm#<[q.jkemX"PoZn_hEctCkNR-o>$H*f>=R1/kq=rDD4 %>l%j1$nfY).:Sk2ELDo.1Y\Y7inhqVFKq&aAgnD<7dTI&0\4EeWdHVc\Qk!7GgsoVW-"He-cVf3I?k[IM-e6S0B87spb#mlki'rA %a7o#LSU5V)KmE/F(\_n"k*+4-s3:,bh;1*]??<hrjLF?b<ZThoJ\a)LmV:g`PbT.aWKE;]=X[jRbeQ<"9[fM?)Hio!8J:`?i/Ps> %/Xj"6"#IlQ.:GJt@jMGDAr$ZL+Fg$DM]k6iiDD7a9[*$b>Yt7%a;nV)H,g0&*%Sr?cU?=ZB2aY52N45q8@,fLH(.b,RjDkc1CK;& %$TWK<QGIa>,`TbOJ#k:pl%8W7Co^(P.V-$=_.P*;#bRVi`g9O:EtYu.O`LRb?<OlOAk%>`/_K\If?9]NhjMI"0L%C[bjt\I=lR[M %X2FKa5O+P)iV]@=jX2*\V7"N(DZ$p?1s/XVJU55+rQGUcYLJ8+1M<$BbYla/.^9(%GM$*UEsmDFagEZ1rO';M0'De3bS"Gk_NG9D %ZPK7d3C1r=c=\XfS#BmC]/;>(:I`b[,O)(foM^a2pDEZX=m<AU/2#-@oZPYIQQk%lR*@nio3q%PZ9%'e5I\1UALRIWZ00c$=iC5= %\S+$A+*30.ic+cBLUO)bl0G[LCpnq:O,Y:2>oV17cSOd!<,3_:'\R/N#XaJ;RnANo.[Hdq/*^T5\P[)=deQB(*W@fO$;LVANAu!4 %j3[GkO-"ijoEBsP`7TD$dH&+%$EJm.1$[Vq*.V8,9r$HBohA[dMg9BMJD=o^=bQ_'O<ok3[U\Dc`8?uOO7V>ac;[qqfih0ai]!M) %e0dHQM,/QZ;kNj7-U.40n3J;Fo@2^U>_>i'Osb%ePI9Jn>4Q2UH*Wb6K[u;6hl\?aXs`,092.SFG!5YE4o'7a^piVYioDQJj=0*L %.H9D;ioDQJj:`b5SkL>(-BY5(#+qeUjYqG,Dt'"Ki$lE,QVW*#q$m>rZ[;ZK-2`uk^MhXumgo+jGd6qpqPh-r52D";D7OVriQ?m^ %)'g+ErQlp$8QZn?L(oQR**pUicu0mNcF1K!WgufO,EIe?I4:"*B"i+E>X:P+oD>L?oV"IWraLrVc1X<ca&O)(^"hNacgm$cAK6'B %f">nDlZPD;Z^c!I'9:`UF"Hp`ZcaSr##uP6bTL5#VSo+-pm7VLQ!eJui(5\="I#,I<5\T@GG",/9NT6XBq&nm`rWW82A;[j<-r$u %l=]PM\FosYIkDLt2g/hq:l$7J-7n*Rb?L<U>l+N/?JFg7m#&!'.f3q[GW#9IFWK't5cqYt7*NYPD4isMX:)S'("L(.k2Y[Dk%,PC %n*4kEYGYsF69lOmkm]*l#Y6C`6j3PsrLP#n7[K1`l!lINqMbb?T\p4b7l21t;+Z])*@AA6;*-c&#=f53f+F$H_O3p8W$r^.KemT) %W%T,JL83&@QXEd0W/<rAmrlt7W&l!,LSOifcledF&ogkqWZn^5Y"9UUM9!5,f,g'o.'RkCZR0A+C*-@Gbh#nNH";':V<;5sJU)Zt %^rQijO]ei,-T-f^<_jf#6\OkY='@GsZIY`Z?ECS4V=7s15rFVe]j>^+&'LE"NYkjR%*Qqr@U44U(GAj]f)DU`07%,5I5<FhW/oO9 %+A-1\!)Y!`7]i=n%H)WSmW`#KcVD-Ub?ZX$>'jFSn^iqp.n@X#n&bYT]6CuplG9m`_P5kQ4Y.NNjY!.nA'srcZe3Epnn4f6qKL39 %G.F56s5-l/i0G-'^iEA3.=d?X@LeKJ9riW0mqdV:rlHi:Rp1gRo@4QhJa@=1iT#CS<4LE8:4YM*^";5gI)<^Ld0sNf\&2H`L,%<7 %@BME(R-X,nf9p'kolc]S1X)@rb&Kc9-fpeSa'Y^P?m%'q2MDTcip%oR'$Js8cH;[O4n1Ka`,9T=G.;#H=6?1W+SS<SR"klrX?<]S %n\_pj'P,rkCEl+*Hsk%/+X0h.b#EG3\bIliN\@r@Qqd'5"uc%C]P'Xb[%L[2TpSP1b/07GnlluK.AJc^#ku.$p&:<>APQ]8l%Tp- %Xd"f\?7)t^(cAUXpUlTeKo@VD>q]`/+f!4$*e@^D.<m6fA9NT6$]MueF5m((NlWg>d26q[GMc@Xaad58i@u>!1ultGj,j3@mF]OR %S`Ya:RKNCcgo9(YXjlfB]nq]G!C<:LD;A:d*XAoBVO3.l9-.p5pa!Ji7<??=_(Xqk1sGZ!j-RpMpmLHCBf;N35IG;3j?0A'`N20Z %Gj1oI,g06!Hot[sm4Nl@SBD]Zp^LTDo6u$:s5^GPMb\]DEeus-.,&O`l<H=:Q8@I#R'YT*dTWt0iCU-I3Jpi2`R:99Vn!L?@sV8% %7QKqTFZ,!'CkpZeHmc+YZq6TZ^[oM/q%NZ-#B?==3R?Sf@%&^L`VEo3ch)Ktn3=G!g$uZ/<l_8a3q<LJd;.\>l>j?dAdc+fLU^<L %NrC$Z\5ejR;!5tF3l%i6"jR8]S1gXe`Xl7V<L1`LfEH5C(MUXD[*,HI7a`ogU2/[l<]04g#f:=V@?l3D")@54A^rE4(6qir:,VB* %a?h@SgEZS.mTDF_\MU?T)H73S/:*2P\Mrd]?.F3\WOK-6pY\XAGn910[8W-YXI_SkW;hlX0:el4m[`?7d5?p+KKA'1R/o^!c7!I/ %Q((D2^>d[5Kj5BPfUPG8Cn$263nNj]jro]/211F0#buGMT48qZkZl$gR.L17\Jp$&6.*jc!A.A4"@'gHfWb)7JiiJ>]Re?+m_BA) %"uc4f"$b!K\=H=Q`[S>JZ!3*6H>_cC/*E#S@)c0T&2Wnb&Z_80K-3lLLg>)+CcYP'"gro\Kp1k2@L3]0k7JS%Z#tr3;_6^5([IAA %Z&Q.CA^iur9k7`,(*fb[b.=]kNr_pE[>&joR;YRu:8MXr(<X;#&s'n%kM[cZ!"t7t0hc_:S;3^?DTkF%(=<klkH+MmR[IsRk`RrM %`120]c93dmI[4TcWm&#43J0"MgZO@_TQ)Zaq-Ir`oI8"UY'>%P8$W?,rEA!2QeC:"GkEk'9<pS3%.5aUTq3!C`&@/Q=!)A8$/siL %bad_OK(GY5*obK_j))*`_*3kV(quuOfMnP248pT!qO=dKGrYsMgt(D==$?%5np$,%O\#!'.F,m4diMGiX4aYbG.8%S_9Y9e.d+:" %EdmL$<7Lf1=\/;JD7;pXYs'-mGl6?$'A@<*DUt:;ct:nTMgD_:9s1#1Y'j\q1/1#Wii;Rlam@^dk,mf9S#3Ko]Q>p@p46f49CcLk %H-=K[[d)mLC""0S]=EK:C=El<E#J=eHdo`3A4V7lXiQ;")[]7eYb8d^!rGR5-_/8rG`mAi0<q:hEXK]EZC;A&WgOU.3O5,YIUL$7 %DE.i2#ZE+SOjS)84@d!OM"h0C1`9nJ+V>M6nIfUGWZc9njAREi<#g7MOP^W=XlNbSr^.Q_QK2[FSjY[6-j-&aDpSrY_N-!"=L:>! %nLK31O5oGDU-T0--&-lA.CGL).qMcHWpI`7pm6&oND(3n%U6ng!0<0i#5J2D=j6&GmUt+DkQsPM&,L\#k2.UFE@B[qE4]%p19jZF %PbN[n/)i,.'Z4,OV'p\]+M4L'7l(\nJ&X_?Yj%bqArO4)h.GTWk?KsXTIT27ihJ\Q45O[uogqS%A=*d"XHF3*7-'.0&s4F`8jntu %1_F^?!ej%bE#oohe&)Is#*lM3MajOGO-:LBbE8#,VJ&BHH:a$X(Str6elB&W)s,N2mW(&YlRG'D!t/al0_3EM.SgL[XEk%%8Z4$^ %,oN]']Q,Bm*p^s'<fIu.;9hX1S=q9F?3TSM=njbEo66bSPL5k&rL&M:Qn:o//4J6h.6F@TNN/@@<X/7eW6,l]R8]D6UF_D5Qj%K? %dk"RU'n+c00InV_AoXPo9l,Os2p.<GTS*64o\;riB&mW3[Y`IUA8:^GY-*$\Q!72!cW#?o%<bnfOHQ8ie"h)@ndY(5N>k/iKK,*O %Oq#fuJ@\0Y5E<g2O?eGl=$S-`8cXhNq>f#r3"6u<6kY:qM"i0_Em^']>&ogfTAU,3f922@Ec8DAg%e0#c9bQXcq7i2TWn-;Vjom? %k=9![d3HW)3o+N$-HXlhZShDL9k+aj&Ar003,ZgaF=B^Ye;StM4ADXc*]'</?&0=Bp#_n,XNYPABZDh`s.(_DkkR=qRq_H;+tM/c %-(ZdPd[(bCg+MOC(S=l[<Xj5Q\M_jH?[hj-Jl_?[qO;/:Va^``N<PR4-$p$>aVu=>PDs"P]_mYZaK:$WdZ'`6]rQF+@ega'1$Z.< %n&Hl[C>.0B2/o#k\'Tb6pgm*,H1i&$;_mQp_)h4m=H)4LLI?N+a/InqbbO;YCs?d``MbG!X,icYY/aV-qA@,rmgW6fKqEQZo9GO8 %bTt``;6;AFZ?pX(D42GW;<264kajN?bRB;;Y39#A3R<7VA"n^nZ9_?7qPYh2%:d)>M^=:+n&B_X5S&h.c8epL0$sL0RM7((H<-3Y %Z8PM;>\Nk[26"9*6`F>6gQKheF5L&_g&oAma0i!E2QsH1>c@7mh%R8@:RpgD=XN4sm)QGCa2js[P^$`:_F\=XV=Bm``\G&6)(2\J %B[B!HI#-J$X'JP7M4`U_7@Q)J@@"kmXVeK/9+B.:koNI/_+R?DC(_%;Yd]ej/(p?:&sW)2nits2#HE$6MPI,G<u6?]ERC#@R)n'g %cf@r%00V3?gWBh4E5@o9AS41'VmECoJaH.uG-5\R>]Ut&2DT"<3YL^P)RSfiU#Y@60KL]5%;,i5>P8K7AoLn?4"\\4(+Lps.m,jV %c`qbUbO^7PGppi5iYTn05JOX<FqY7uB6KCE#U\2f:Nc2.R;T:?bbmFFc`);+7nNo2GO%jddrWDTCEZ2:>H4.<dJO558%F@XIf_go %;@8Xf,NL1,T?HbEm/tkLF'nuc2%"F3HK8Q$&obOm(/+e:FZMYS3I4bE.f]d#TA*dI<bL;jeZY$mql;pGjOiO,e,89gNChPPB<=[W %gia/H*DtB?BWLdG?76^@$IkX7Sn>Jc#BEh?*l.Y+4baeh)b635FW*9!k;_0Q`]i`L`i0d_TL=[bc94uVq@,RV3I4b:s"a8N`p#%P %^;f&c4icTO$K?GJN+'t4`/\4'`8e(I1P8Dj[Tj3Og.g?0Q>/?u-ieGmO(u/@H)sQ(!+%WPcDDV&_/#lO,M#DcM,4;B*`[)GTS5M7 %>:L1s_lV1S1k2MmC'E_%qP;E2Do//P'@kg.D;:j_F6oP<#$kCeX@=/XJ/qX2VAl#X0O_VIfod?;>nM66A+&nR[5FtdQ5Rln'#EhT %<sd'pOKj2:9[+d>B73@s/:(rPs,G]ja16T8c,BZ%oACR)KGD-IB_Z"-<BjDKfF+rF6e'CoaFO/3hr'7Ni5!'(&NunBLk4qjr1`mY %`k(hNLS?pl6j84-XK\78Zl^R%0(,!l3TW;g('GanZ)9o4,Js*SKknO`"r3/1KL]/WfP/F2)*pB2Y-B.O/I7"-_"8n.([lQMhsN2- %)5sgU/8PK*$c0\8YV6?a'`VcDc$rjuT3%l]@YR,4RBjG,(@G&^XP_OI`CSSpZT%q+?-MJIlL23u1O7(fgj71(GG%>^R[^BkSa1Ra %$:W94Gg]pis.;+MS^f:k5r/sB`\PY*2r=@cBsmWF^YuI_\%(Vigb"!pGPmF-m$S2bQ.Rl=mOBAq:Wgh:6]FQmj<9:liOG#Md3C`4 %+d"NdfemGP%#:2AZ4'0.7a8-S!,!a[%KE_^#=gaXc@-3%9NRL,Ik`HMH!E(ni;2]W4QbV##(N?O2fhD=ZUKiK,0!I%AM>Ec;ta1h %A#da-V;e("+dI/;Fqo1da07@@-L,E=Njr#R75EjGpl*,:bSYo.jM9%bdJRekcaVn]1[H@lkFKVk8Xu6fWc>\?`iMn7()GH))\g5^ %P-t!=;M4M'LJh`\0$;Hj>e09'A`KB#oo5,?.;d@tnLr`=5%q6'`G>N-7"4$#b]qmXk9uC0E,k?1\U6!Y_opqIK@dYn:pca`5^2BY %XTb!RTp@.1g]aj\qfh!KOuAM+-;7n58J)75q1XoO=]RRb#&28N'uN5?Cc,<9;p5FO9j?A/(rfM`@krcn7GsKh`afj&)`-**+d.)_ %\o-P#\paaPiEnJrR_-->GKcKJ[<!#jIK*;JUFSos?^D&lSmMODR14qWD^LjuB]U;7gnU+sfi0drfrPgW>fp&e`IY@XVdq&J^RF%O %H!RtjA^"^K"C5ot;cSm0r,[U-c;)W&Fq@-#fVgm<%,k:=#oP,5[rH=IZ%r/BR*/Vj7S>@sm`)4A$mV?Q^qf<9PRuD`@FnL+id+g7 %j,1[ejBYFh_NghDGTo+sgI>0#J[+=;*g"r+G2iTdIO)bU>P()iG#ZCi^YtBgp>8k]*_@7Dje>tTBVC4,hbLq31]:dt4mnX(dC0rK %AN]`O]lVfidF`WC7"NOnR?i%P/MI.cH(!L;Gj_$S9,H-%Hd(94,'s*DVQaoIfO8=t'4%b7k=Y)gCl1R(V0;h!U$"$<e_JeMg/>_u %K<BT:_AKcq:H#)52N@+U5JU6kP`h-oU]I,cfi`I2R%)^2Im@2@;omUVLj,u.b.\=.gEGYS#O!e?QsB]de.sK-_pqQT93PQJYC>JN %oP?<S5J,TS0WR9k*r5Vr#+*p_c&0(0ou"u5)VhPnT[ejA@%HGHkZki:A[mmj2;P"g7Knr8IjN/#Z5)==MC'iO%Ysj!p*r7Uh9,Xn %NZOe5QZC$(4#r7+b-ATu74a@Dn`(R?'`0aLo)oF8YEViS%,[DT/`"(WF5`akq6M_#[9d&9kF.lcf$5sn-O>W8T_",9o-B-M1o00Y %bht?<q@<3S8%d$.VhfeOV)`N3&[CKiB#G_7f:O?6mVXcs<]]uFS5O\6'I5O>T92G40k6GBRu$=1kN'OPUC9NJ,>@9^LLa#IC!"rV %l#L^ea.4]&o2M]A=p/lqEBYqOL3V%a.a\idSi%%PI:Y+YMhrL5fsj._I=9u&B?KKN+SWhq`Zc4@+f=!6,$Np;hW\F1@m0A,%S(Wg %5&e7__21SX<l=_HqBle"Xie>3.C8d_3o0#i.OX1!/"u#M/F)jM'=@K-Eos*c_rtfABB<sR]ik8i4SAF(kPaNQ\\!K3n";bh:IsUX %R.tW]SfcnX#-K)fi65iJd3FK*6B.g)Hd2,1i\LmKc/R&8aM<Yen)[#2^5Wa5+Te>nN?R:@!ft=lG+bs'U>_J'BXi3M^AL:%9(jCP %*CM]1l$ek4Dj\ReP([*WPC,S?qrNu[K!#Y)`SHaud(L'UGFW7qqQ^^Qp4-d8-(@\t=tMTm=FeJ)CFK9jJ[6hEC+gY+*')JSf=-Nr %k)mTnCrYP$Y]QbUO#L0]#:"^P>QdV\6B>!5?PL$4?K\cCY,Rm<gcUsN/>)6D=M*<UGEk.dB*@($F'@3Z[k+.k_t#goI7eNTF4'i0 %*1TaT(=9T,e;4XAa3/;R6KcqH[7taO))W4)Uk>rESt\,AZXH>:hl(jpQj;8OY:A[SO$>M3h;CZk?:<%bETFbKd>R0;V=NY7IWX[* %\_pC%5Ohr(&`C$8_QUiQ%ugN>5I>\Idso2L<Ld*LHKC&lrchH+dVmZVc9-*n+7ijDS%e,90K-UGh1BA/luH6RYqfs.AutIfenD`+ %AtBOND$4&QTpB:momACGnfem[8@rLMBeu&mZ0T_!IYd,pNq+tZgWa3qX74JFc6W2[jC1;kF+9S^n+1d:We%]G4gGP\E/4"#`?B?d %.(;U"Q-['Q!)5i3SF6%[oOG$dR&LS>`?b%J3\jTrc)Z>02G?relX<;X,0;sf1nIjV77j@'8Jg"BM]!.M>'5o#K8Y+)2L3BQ\^R?9 %GOne%L:'N\$CR+]FYY65HRD<hMN>YhNIm3oM=[K-583<@AbqZkDpA^]Qef[-#2,C&&t=6NcFTo-0f>GePrtd'22IpM>^Zk<20p$H %b56Ig@if($[ad/?CSj:7!U4pPo+tMfH2>ge,uHC2L+N6=D]D!*V/K=a1ZNLMNkT(Z^7P(?5KiqL>3>cGQ_3_UG.r6B5-rDVG<%J: %G4s6*.A+-p-f8)A\WDQl>aL$1qNQ?i;X=;#'%bs/:t.Tg,O*OJ_5m0@"]nO.;bA8\W7l5i6[R1oAA=O&lfoks/t=00B"FEDB3'QA %ihda^9T!07PZ`tXoto\`V8M:bB]])!YRsUr=a3jE67K6_,dZErISK@<m*(XX>Z'e^6>"D`,k:[<qC[O30CBFd0/WIHaBipO\G)2> %=Z$\9*e1;Sf,L;A9Ac8mjHp>HZ?[,BI8dD2K7<`kY=R/!hNoMPHK<AII^(ifSE.o\DK!)AHU#.$]+2;tB@Zn,<Y@"C&4eP@'pn[3 %?+afmX3C.:/`TGK#jm"IM-Hr\]5j0(Y"$)S.TEm?;9bX3[Z1=A[p[ObWEpJ=Q\g=^9+s..%EuKg#+#=rn,Zpd^SFBrZkPc<9\O)_ %]sUDqef$j7![aV_NNpbJLY]pQB^tSsdbQl?"h<RtU'B>.#k_\Fb]u0X?$Y@LPa:]ADm&?pjb']:^A6%NG@,cCrU/_3GMbQ12Oo9W %(Zm[6_`*:`\bkmV%tFNB`Q+%C5.p4%TUUD`=H$P_pFlPaIV`SIc=$I75IWlVC]!4C2:0+qKUZ?+r9OBQDSCh9^GF3)-rY$D9aJ2_ %2DN2-]J\#_NStXtn,`H7!@E!k!;@8;@/BZ1p;5]*lBApWhd`3r$O8>t3S;t*.#m2!i-[Vs<,VbMD]=FOHYnK<k3HlUVEDNO,s:YE %D3N0NJY?Pjo\3@2=Rj]kQC;!H2JGTeMdKN_'3&e,9suY_0D>p,^hk9T]q!=WO(`IoFkuH7g:`n5$<FY"(EMG5I(AGiUpk)kRu`Hm %rcp5GXZK8mfDUo$c`6VG2ZM4[eO&ZJ+3Zs=HLm&%hYbQHDndH=2KYPLk'\Y9d$k6RZ#5</=/0YI'(en4-QukmY/0#,&/k%d%`tqJ %K**el[>*0C9>>7q$f6Go`(&cjKp!R,A"^<=Gq(FWBZ[YbRG-^Z&t)p/&&@HREle?dg=tmJ!)$h%;Za%6d)OYkL+M`fGT1LHVu]Q$ %c*9"sE.$PtPR@OsqiG9de]dEONK(s_TSBA<Ug)FR!j!?qqR.;E2g8Z:0%6lL1iX$+gY2;H#b$,^E!1#[2);D0:IJT.W79l:HkiRk %W.B]@hHI#8qV;VnW8"O>B+K+uc4E`:S#fk.Z63"DG18e$[k;536CT2@DQ=.g?i^%-nE[f^R`S]*Y6ltQe,U+g!2k-IX2C8-gSQT2 %DsM6ZGJ2[776oic^A1R:%j)=c?[dD$rnWJCJ%k`aJU[+t%H>[2?f(^YY<Oopr8#UNmd>6O?iKioGOIc1J@`M.q0uSms0qsEREU=W %Xmt2lPU6OHAMBlMBnTtG3'Zg'Jdmu!J/a<I'!UnK4?r3Dml]400mQ6deBV(p`\pc7,-[bF42M8C0\V)>XDIr.o`dqZD.s+WlSakX %+l]j5/Go^f6u??73!<uhTp@@'^_SQq"(8e7NFsAeLAr*X1(=90eJ,EBiho2&iDZESg;J[2W,@G5OfUG\ab9O#8";\KBsmI+Ot9<n %D+G@'!?I7`"p1'+^sZgCGb"omOq%4[%_;kdds;&dK>?_06V]pP/NZN/?o1e180;pXg-.)#G=cqd"YNU*`.A@Ff(O2)\.)N5(`hg. %NnUNQs6ODf')_Hhk@q6so!Ut18E-M/2)csb5X_G#!;$TK+Z%JG4Cf?:FLSE0&-?aeLUq>NCPiN'dK;a"lQcorp:`ER)^V!#`V.dq %*T9M%kG!.I2Kk8WE1?h8NO:"=1)4RLLb\K?VMJp?Q4bg4K;G4W-__"Y(G^-1X`]hQW&(uH('M(:Q'(LD%O?9H4V)e"r;`]agMR?" %9EK$o.1JZu*GAC7K>+E1$NT._am>j*V'7Snop$*h@A3t[cA@j2_plCJ=Bj8t<MSYE8iGf4pl\.oW,EA(Y%LtKC2&Z2?Q59k)/+Xn %14\``q8PGi!DJ,WMN&&J]0-6LGlWgmOI%tr!/Mq_/NUGndcL\ro/.mu=g$M89KVs&jkdoV)$.f"!fknu,OW8PZeR)"au0l?!tOO^ %SApYY)<stgG!$h8P8qU00XoP^VhKP5kVT[\Y!Lg":#\SC%SK"mq/f?*]%PjD0=SF2Rfu$1][+&6I4b_>c<o7oh=hFgZCFuCCZL_E %On/,L<h''($l)VmI-6Iga0hl(mtNV<J@4h6&4h:J!J]/[A9d_TG^OrJr.jr5s%$F37kKU=&E'n_W<6J\;,8-k`<#[[KJhlt%Yj*B %c[a%O[_V'Q9602b2j&p2j\6Bnf^f]p1;LJjS)CQ*/au4g5<h4+^K,IMT7k=8)`#<<rs7-I9<8SGM/gA7:t'>MApET*"\&A&4+ggJ %Q?6b)6,*ksiM6FrULO"/aVCm;*mk=(ntO40m0!m/%cHMkE'':^Nk?XNOYbqPa@c>]eP[UZYeU8Z`oSVk0*XsAD$'g6-Q[5OF/oVu %WP,st;a6tt.<=77nSeZO)HcXVQNOQf,+VGrCP0c\`GGtq;BSiX9dI)6-S.L3oc?ob#`&)k/QWLf85p"Wi?IfdJYTPLQPm@m[Y\PF %`aFS=j%V!.`(56+A2.&LTNGrGE`BO+KV8Ab>6UFa`aS4:@F4(XmOYXLcPbMaS&a2r5[^Ap:N'al49JaA"s@R^W*KCMR4r"r#`'r2 %!_u<*BS[jR%a;XF^t_j3r=/io6QcgP!ENF##:Mrl`"16ZP>l*:*.WGM)Y,Z1-Gcl4UH!)j`<^4OZ04##$1K:H:i*%eU0D@`PFEE, %Jr;VKagE22^iGCHj8`e0(H?mt%Fbpm(d\pEQ&bNg[0'/Y^Lig8^YruA4IRU3Zlt2<jHr@-Cf&.SBN5/Z+TT2t.Ke]%o8Hp&cfjtl %UeF0Z/'k+ccNB??a?\gk#mbQ62#sAD1lt"#6GQE3A_P#=/b0#q+c3(ipnS?UN0GWmU/t!I8^<o7(E>B]p&[lg0Nt(8glNn(Dc$\D %k6>BF]UPfG"_tZK9VNK*Zl]qedt1.;AHEWF%Int4?r@)^^gf_dq)O(U#i&c'8I^i5]G-d?83DA(-LYN440Qo+q:hiNk^*`UU_1s( %#t3dr5_jY8kQ"IA!]R.)h//m*i\&_P(>)*r)N^Ne8k'k?7a$LLoqALW6#R^C%#gDa\M4W6b7LC]+WD80?Ks-+V$NIK,VoqKSUmSO %K-$iD)lR'K:%?_acph6LC4VpM^^u3C<*3@N^4G[iH_1F-"La0YWs4_#10%;me\Kg+g,ar/?Ug<m'g*UJTA.Y\-9'.,2%X12A\n-Q %!FV"k>Po`UaEk<EJ36i[JG4BJ5[FEl2YfDW`%&!G/:1HrTL"ukl!sj[<F-0[C8FiTaIuh>?kFf7P)cRU(,]KtP=Q;mQthc*L;QP# %LfO)3`,_Tt\"0fklQ+A%;#du!Ms&Wgbh?JrN?Y.g1+clNO[7B7$)$Jb=gGn*m;@N_54)ME"E,Isdt"jp(T)VkD/N_GcmNQ.!a)dF %:.pI3!'8ddOQb`eIrJ]C"Ro"#m/d:oMQheCN?HDn"%krLWXu'S4"fdh&LM"2qW./L7<OkP:a[oC*YfNjGtcL4,==!mW8)FU=*Yle %8X[86^h%gnA!^JDM^`JXaIEEt_EI31I&aJ\JC"r@bso'FP:AH,1crIJJ`I0!2MPB@Mr8_8M@.!3l'SYSAnJ@&DH;e:b3"4tXe;bc %pVeRCgt<oK:q)i,p.2%rbTp%&9o/i-\sXGlW[dKb?eHPMkB)'G5.h0LJJj.+66^K=)IiW;!@OBS`0.*j,mQT`^aSiF_2W==3$i9* %Gic*uDnrC9%,)#`h+$UQ1SS(C)6/Ii,\S8N;*N>EHX#Q9FY^E8>]LfF7_g!SC*G<5;!f%agZA5tg.44>$.t;^)k?O-%.$<,F_r=! %6.n1T-FQrLXEK4#-3:EG#D$>i!3i3m"BeTn1H8p74$,nc[%6k],[bYuj8fa+Bf8^E/sZ\M*5WW$AI]+WV%d@8Cs`HM'flqp[qNS2 %A5`Q,[NSeqkU&<h\n.soXdt&#TVeKmTLl^`B1`8$79CVlj/%;<.SkW"\HRpH_Tl^165Ce["/8e*0/fqgF3oT][Rd"U:/si5oLpT^ %Jie7Cf6rj6<\h/sBGs2Tc3e!ZO^\Sj945B)#24gXEnJ;s'H#r=apeV8L`9ZD6F"DB,DhZiJ;<-q)=CY%<neTKY`WM]JJ[o%Srut? %JGE&Q$jE$PKJCj(&7fC,3Pgj$`l"cgTU-[^R)).`;K`>UVe?2"GA]Z>XE>G;29IKRlmtpo+iO:9.<>O@$(UJ<%YfM'WPUNE$M<!X %d.%ME<"I1So_UY$;&.(+ZI2&L,(ro>M#^3>I!45F'9TOph"c,,$.UM?ka\Xq:f_`Gb]$"<!5o$B``fqI;^-;gTTa5_Q#8p\Pf@J$ %>E<T`#+--D5So-</g/))mqiZ:+]:N]&7tKbR2]s-O\JuR##8277<#I3I8#4n9HKk(Sk7#Z8d!$=6-d8h58UQEblNHaM!:sHb\f0D %"Is/G?qm'C#%]#>miqm':Hf4d2Z\90j%'DAZJ%Q?"uiLWWe']--ZCD%U&hU+j15YJT[F""L9um1be'J0"qFHuD,r@k0F&V80"lgn %<k^U,_0q&mE#1QUP-[OcZJu(OW.CTs&KpfnL2[s/cq'J0)DLB86c0g"&-j)YZ9kC>8\,%M),GK$OepMtZ(s=P7sa+([n.<'IEsd< %'hg/RKNNK5b)qk>h#m'AZLJ:6-o@U#Jha)-5mM?A,tG5Q`tBXL(hko0;8^BYQ#8_2&6(Y)@;@Z\D#$UG).so89?de[fLZ0/l*3kD %3qs>4d?qL54@Cc?;TbDnjA]u(8:;VUAN\3%F&Qe0#Um+jGa$\@D7-C+EoOP>S,c4Ar;ffBP%-YT1BL)KMHiDXShmlJTQ5?XnSrO) %$c^&?69qTo++.VX,_61%,A/$A)rsHp(eNA6%Y3.Tl><H-ZV*hV#9'\+hr#?^;.i0[&_HnG8`6VdX]ZR`b/5J=((ggI_h(;,CBMt0 %kniPA\^_tT"Ir;r#K!)Klf-7nX%;\"f8W]ED?GT3!a=h=`#WOoGnQVnV$@(\,.3R$ck*L%XYCF.e\LPP.)K6b^qFST`AG]9RVcUY %CGI@d8oiWNR_3OM-k3!1V$EUi3Z8PUAOZbTF3r!Pj\qFX`H)4gi]H+AT[b0X33*%E,#(3#Q(>pi;q_[1BLFsf&Lbp=^nJ?`^g&3N %i#FTS\p*86S_,A<0?9@G4KR9pHP(r="?J2P:gt;lX6t$0.lO.dR=N!Yq'7ON!okP,"a"aJG!"kY#6XWBM,8b90#(!nNd)gB"4#*N %<)9)4ciZG7W[1.Em"'&qd%:h?'GA?p,-XbXB+sTh^ogQb/:]QrCfFCK$Fs,^<s/;l7iSXW"P'>&51/KKJBET]j_b3U(o/dRJgSim %LV,snFuH3QmSe#2ME86k,="NU%Zl3U"*U[P%#"nCScDd&jb-`o?4OfVMG@C,.geWR>GRG^8H\*HGs@C*jS>U,8BjRaORs7,Z]X/+ %Kd"c7e%3,nhQjhMTZZC?SPa>jF1&>Cq>=Y.]@m84:gSl^S.j7m@d?%5U)a8;1Pkt!N]+9c'UVLSglB1Q%&f#RAJ/N%9nM.XC',c) %oWFGaf(Fh$-8sfqk)#ptaKXSPo9kf#Z5<+O]HYKhZXRH\i)mODJOcb,?H#MDP\[)$Kq.6!n]Wk+P_0!n,?8h\V%%#A&M2\#oM5`* %Fe+>s#\4N8QtL]WWe*S#[>Kh_"?^e,6suQr(C2BV@,asiZD7`0;e:G;.2sYR:;YH^&F>>-J;)KN3nqFU!72A-Nkg0;>6M5H$q5lo %'ZNHX>$5[1C8dOg)1k<b#%lBq`54<<gVN)$4i/sl6i\Qr@07F\&Ep3/13@R<<&Jp+f"EOCMX8sQ`nogDm&DrT>[`"uP>,Q[_G8F. %?!Qe[;Zif]bS*X0K2C/[#!,r>#"-QMXXi/AW2cGSQ/*;s0P7?j8!QPb<E5!@B^:Mef69Ajk^XOig(QGrJ>0\BV>1=g8Bl^/6%c_< %V:?j')o+nB$K5ed5:JItFB/Jtf^Y2g#%FU\/t]+$#Ut<7T]rrej"R`O(o@MQbbDsk@%Wto%:ma)2M)+T/UQ=X7ZJlXMe06=HWNnN %9FW8`:=PAe6X^(ScBn>_C7kkp<S4>plWD(0f79fY-K$T3<!8<jSU0'Ga$*!/1n(__[Lhu;Ca>d!1XQI9.T%_`js1458Yi/*4Y[Na %7"l`d$$HD0i0/,9PLJ\laiLOe0sh^`]c[S%UHFUoY^HZ&!4/Xa#pDkBUt%b!WfDYOeM6%Q5oX3,H^I5\M7jCF5dH9:L&nOW*hgmA %,4f+%EEqVY!!#QaMJ0r(J\H3q^j=:60i&:K[$$i:KbZ-*2G20"9/QD8\gk^%FMs8ad6kX0`@8mfMUdunan0fj>>'fOlFgId%Xn#e %L'@.]_2=E`\"WO'm5Z`?7sR3H4[UA*JPB[?m:EsnDrj[3%4YAAU8FS&]Z;O?l$`#M<Ma/6b^`/Mf8u*\d=C(H:]$iA*QT_c')@<o %PF(+E;O+Qj/I9M93%L+'8?&ut5s`]>d88.mfpZ5BKQE2A?n&k5AU-MpT)`6q$:$S)&8>Ra*LpKU%XfXrZdLF)SaP/WPDu/inO\&B %H88LY;$4]Mg>7A)<DH!/];s&HGu?sQcSoH)3ab>&kEuXVGZT6TkPO[ZBuiTiPVCogch.LfWqOe!"tq;HGZb_W&S,r4Bf]4:$H;4h %MRV"]f`E;\b!Ah31BdP?8Q`Alp9?krO<.EAC(qU)'SN^C,SMpiLOY1r%B1G+]IqPSeQ5IO>c[?7aV-Hb]\%3(JfFN9Y*58:m_-94 %&O]q3dAT=&S7$F+.fnhC;#9UL)?qfWnYtTb2'_[j7$%YH^.XD?"Ld<[LmAYX#+65M4[G%t8CMY1k98u=S(6!925VP<g'LK.\jam_ %e6>epL7nYOR7Z,7.ET+sKl:_6dF!JWOcPDkNWq;R#MR_Wc5*6*&1f,s-VU=&EaYQinL!X*oWerq)3b?NjN7]P_gjHE-JK'Da=u0U %_"2BETOq1(Lg_-&QV7I=iqP.@i:7kDQ:ZX-qNV7CNI23Ik_guQR^T`#kClUio.J.p190CI(q^h?,$@4,Wo=I3_),gq3\nuXUK*[L %M<8NfW'k&ZnCE,aN9DW.Yd;[:;@8U[[Wpq?;t%OFZbt0`1YX23Ur"^&G0d"n]%@>T"td<\jtfg0S&n$U22QXl[(9Bsjc5Tm%Hu>0 %&#g?GK3++dNoCp5PX=u*P6QmZG0102DN_AdV(X&V?UQ7uY#lQD*7VD00Il<+:e"IHYaI$ak(VfQR!;;UJSYaI%QG'TTrp!cl6Q1: %;0FrP*WbRP;JT?t?is$#-Dp["rQVX\]#WLcV$e'e5k.n#*=P*,<kF[,GjSO.`<0=dWGW%N2$)47U1Y8?3P7tlq?Wl$lC^hqE^\Nq %4Z`13!PTJH(98G`^jfOu2fE9A0kQXB+XD=pp5@u6/F2oDlLQl4Y1c#VX&)uA#8"V#XVD+RpE,V8][ZU?%P`&e@@3-ZZ/nih<Xr;4 %b!0MmL/9RlM&jgCYt.`Dp5Eh/UlY)1f[_O!bi>2j,]:/;/9-Rh-:87SOfP.o.WQrD-m062kD/mZBiO4_:2kHkWrptjmk/YYU!?QJ %jFeK%OA:mJ-9\.O*E,s(VpmmWVof,cg\A(U8fE`*Rj9VjZ:[t4@"f*K2:Hfr-e<)=phAA2igPHbV,!jU3L.8mot6gg"ADrF26$9X %^p]jtA=<"]446,?dO5?Z,-$FT!R-Z[U[d1N`fn1V/O.@cJ12nSBEM0JQ$6]f:TN7FHrZh_TGeZY5m1dH:24/b;5[(R5Km^AXAl@T %W=\^&W"XEO:g3'_&Y5eT.LjIsFQ'_9)$)OF79mU+JaUCjl9>7QEFJ'1aBP)n[`D.J?JSD9]N&oZ3X:@6$.M4EYGg%L66lqh<[;Gm %+$<(j.MoCK'\;@K$AE[[!NTB/'p0Y%<$kXAZNfg;1eL"9*-CnBc4]T$;l=Cr)ji4>!3X76HOr(,LauLEkUNj9.PYV0#Tejp$L3e8 %<pfH-!3<,?J0[\gh3s6,#ktdW"Y#4HW>6J1[e:i$m`Hl%T!aPH>QP1E`QXC??@"es'mlhMn6Xp?CSrjo!n@"9//fQ?)T8S!a>)L# %3Ku"+JWJf_,ITpb*gCu&"J.1b51*]-0i\Z"P'BT@4Z!:FX$'W97PDBhp8;sCJ!W`e;@fclogc/'?f./OSKF!pX)8`W]X]+E80h#R %_W69GC?utc5R-"DIq0#;:/u/YU:GoV3K'B8Q2!hIXI_[UO]K*[Z5BM@Qt0I#B96`;j4#>23g7sP]#?3<e-t@8?)mBX&8SI5^53:5 %*\8iTH\5)X";I%U]8okm7:Vmu[h?m<4jSMSe3kUl7B4Q,$inD6L$mHpJq[Id#5TU%jR%2JMA$/o9/8p9+g;+BU$m74.Yj\7-kpBH %]ZZObG,dp6N=qWn=gJF^`#8rJP)Lqo$/-drF>)"BqG'b$3VR)]Wf`2k"jpt>-:.*3Bn.Wi\oq`$QpuqOTWYS%!_9:^"6(EO7N`DM %W)X,UA<Kc^#>p*>:b%e('o0sVWZ(($+$bOEb7%'F/(WFHf4YdR?8-Q@bT1Z\X%#@_]*#8ZbQ[Qg86fZSc3>dOjJ`"g%$`fkfX[aY %L6T2o=cXH,P+nXeL.R\XkQ/UeaihW+U&cRSXAHD0dhGATiqh,I8mst:!k&j)4saFpopc^%S^mC,b!V+1b-VRNZ>\-KPDL",eZbq< %3ARW+ZJ9I%KC#XI!'LocN"S)5<+C[T2n3:1T/5-)1N2M7E<Ib78(*q@Yk(Oc%Uk_YTl`SKo4L<N+pln)*jCUF<^]g^\X\3jrg6^` %`.M'!2ai_\J5us]Rc]9c)<N)%AR1/k02,a[(otk4H8,ac(or<_M1Z=0+''>Z?.R<#870=;"d3I3qM1JASu\e>]2@<oCn]t\K<-R( %)4oYBWNPYOZ)tPlbV#MSTNU2O3)_)]-nM[D,E!ELe0+*YQ9hcM^na(_-GE2S4R<B=.><PU@PBbZ_<aPkW\6t2!`cq6o[l$_k>4!M %:1#?.+eTL=,WlO\1XAUk(kk^WfE/*C]sMR5kY!ps$ikR6JATka)4*BJJ]a=e5.R_s]Z-Y]Tq4\[N4p"]WYd>(-GYR1-92`i4Tc<j %@TA%&LDXWDCfTL<#<l\XeB)B,eDhg<$2#0=8BG]S@KOL"!7K_K*eO7(=\(oF\I5@k&1ar[W6+C98I",d,`@j'BcBF,X>Huh1U&;u %R7B*I5""XW7iL@Y^eR&7(("^mBjgI9K")"GL]PSj!*N!X@$ONEkGsehF<YZ4p6FEK^tldu#CL`IBGGfok^t#W$5-F(a_ppE_)QNX %0AGss=L_Y!$_Z<*4m4dOn<m[]/e]&n%%T<Q^.DcJ[i2'.]7H_C>o!PV8^^A.`e@ArXGrjf6S:/5GVob#S2H.lAW+D.@^1$jZ@[J( %UansnPUEXDfLZtm'B-k\'VcI+#Se'_1-%Ws"%?c7:pI=0>Bg"52_YES/tm@M@jG0;p>!!V!c='"7'AOa+DFYu;JP*>rEp6(5d*0# %G>;Gg]UE`Enct@'(5V.8*4eD-+T"F7L8bE7AFduicJZL#f81LJd"@_Y`IJld!tBXc,ZL8_?+PnAMo<D(RPs\<cR;Ai>Otet\%Bh2 %dDItCncngHc@SJu_'!shL89\oRX>UdNGK)oZT+J5>9?A:1GIuC]2k\>\fZ5Ff-p3-(CdP*-99n'YY$6.F>$D`;>(E%rn-I!aqOsg %\uoc"8'sn5-+"Vfh/#)t,AIWc-9k990^s,@CCYt(Tkm/kPN;"eTqa>d+KGG[\CjNDaVm"o2"t+;7_"%d,]^,_\=28)%E(\FQ7Q.b %YTO6?DC6iQe.epI"Grj"0`^^=ankL7-(o<7!fee54Tm78OoiIV[&Z/?%NCcl7'Ii!T[>Tt6'#kOm:?nC-dbMLHN*%JXon(l6?po+ %^#pdrn`n9+*$1%[DK5fB[l4@78P)Bc:EH.LOs',.F!FP#--7$"@JV[M<bQ$L)PJO=oXSTlJ4Rp9]*$m9T2EfckP[ri]KO1-BXRo, %1dke=i&ShD2/jkkJ4'M#6O<M:3&W_i;!(/3*dc1^:cTmger\%-iA%VQi=I-)"SZMcYa,LKUa1s6FB"71ar5ef'pDI-k+&DR;Aqp; %BQleKLFT5k+oq^)Zo8GF(QcZ]dp\m$2N(-_fK03@93X#;M4t'EdgR6o3S^E]9`S_#Y:ri'5Z(uOBb)D`,aOW0PS)4F*(XI2AH*4F %Rq*Nr7n7A@7f&U4Ps2GF5Z/!W3@,$D\076l(eb<iM-an93"--lj)C5NdP-R`:1=qg/?1nOgcD0s9!!oh4?R;PjLLOC,s#$<A;tnq %(79$3SBTZ;L87C7,PIX#8M$__Tl4K_qJVIU#kJb@6$_B6Kbh;];>hr#;PFAP5Y([g28(8ek`.Cu:0,=2Um[BNE@`5YN^6hB?r()" %i!Q3Md6L+W$92e=#^`MFr`>YS\SD2(iYXJNOVJeuNnC(l<rHn&Na)QXi_2>2Mh]i.FYoX9d6Q;53_<(P\K6;1c&!9g4_k>t<kqk^ %1"lpmpd[;e0F'[i';#@kM8ar"mW3j91e\'f-JpR<X#k6[@Zni1>_b"bM1Cu`Q%@r-%Ues)c0RWL2B=MZM4`P6"+0DQ$YA=a,!BEg %VQ(FXkQ02(f1RGgE/kKNXi0362GAsqJW6&dXs,Jc;,(GVpN+Bjae4GW0<W)p!F+ejT#A[b"gOGPER/4d@O-l28Gq;,WIeua:_39e %$0%\`GeN`bFB@E8Er^8aN51WLr,km[1X4iG'>$c?(cjoDT[##a4HuRP!M5Z7TiO&).MXi<c[5>TP+?%JTP0^T`k>r&X;X\3%#9KB %p='GJ+aC`W#e(9h3_D"1jItF&DLnf"QW@#eF<<>2R?0gR=iX?@BJt]UH"*)FN'XLTcJ.Ua-[C>dW>\inN;6ZY=3V`dYmSe\>XWXg %)P?3INDS'<8#Gp:J#1gErM9E%<[k_,Z&46*+cnO0"g]]:qlWZWp^HH,!CD%cZO8GXX>5%E;q_%m#-8i96QVK=')W!ea33bY^nKiC %^-[R2kV*BB\==Ul\")f*Qj>e+>2>QXH(Mm<_6YDkg;c!WmH>O1>n0SJJ1*G'B)pCec=VSMZPhu28Sed#P"lb:Y;r)'<72["QJ#\h %#)<&]FsH1OeHf58jr!9t!3kTC;#$2neB^&rJ!#\^nT"3;#5+SHV<\]&-j4)/:+k*/)>^ET9(.TWq43(8\*[uo5!f2TScKEUAg;eY %G2W=_Z"O^IpOOlXSUAg.!P^?r)fV^f+U>[hGL>No:*F*4'6k;jP;WWg#i`Xo0`b3_?l]YpQ!J3b8qM4aYh3e7dF@Y]#4KtX4.1r- %>]u:HfIi>GHe\PWD;"oZ[FcJkQj`"%HHT^A(RWm;9u'.7>&pJo=?ukBrl.&506'((7kbub=g`,Y77"YrOOf@.1Xri\^=ECGln;Kt %5EREG-VXgVOU^@u$G`W3BLF8/DrncU?Q*;g7g*T9!D-Raer:P$-](e&#l9jR]Ur\#YmCUW7N8l"_"!ABrphKo&7t9rCn0Eo0$o.D %\:]ukiR-@nOp2hoiu&,2*\Z2/d\kHK+iSF^q96=E'_4\R>Rul/H(=heE`U4'E5R\k"50_f1G]ek>=q8\QY[^0(C^FMooisr7f[RC %+P<uWX<FI8I49n,k6*=Z#FnMSf/niP.!o.AOT6u51';\tb8\Em_/NZmbF..hOib5))F27GY5u5d5%>tbM=66cmf+.d0%+#DXKR`j %$I;#%s/.CXR5$$9W1g>6O;7in*)s0s_%:u0$&'V0i6E87ScoG>it2\bR+[hK,'_+;cUK['TG65gK0[Bq:'76>Xu*rV9ABeR4o.^] %PZ&B9X]Whh)WH#B*+`k1EA<?(<Ef'A>ZnXl!d_X`"jl4'ne?V<'o0@Ii<1$"\*T:H*WRA-;&\B)?3$LrGhEBQ-dFl1^a9Q]\>k`8 %&9)cf./[L0UDRkDAJfAZ5h8G;c3a)?N75=Pa.b=`:.U%a^8\Yo$(lP.O\R1bmQ9B_b=^:)!?uh^'oWeg!i%bijoN\l+;!uhg%cI* %7DP(%'o_a4"RUGidKAlQXg2pkG`pFSS/&np;PNe+AC#DK7h*[iPn?m%39W0n:eHsZ9tfV0%WbY+$O,i&nKf=A]pQrG+_Uj&NPd^W %aF5BDLaP9saji-H?ZHD(D$oN)'otJ;T>6)V0J$!keo9%I5k6-I'OCW<![VEQ??,lH?Mbm:J<IW'_!.29GYY>hML'\Mf%<<.kT`5] %*pd*M`sN!._8M00#i%im<#.8Q0X(mk0Y=fipIgc0M:.[[]X"CcM)I3R+\:340uW*cfrHl"`$=oI]B+!LK?TYOQeXjH,5$piAEok+ %Kqc@*#6cFZO9T0OHr%scA-B3BHo2peMTK0J)l:aY7u??ELFRhq<"6<cM;)8LK/.%-NC=p*Y+V_3!7[!n)e^U=?^AhldEu/:QpTbT %d>s%OU@E+0/98L%JFf&p^;34PJjVMe"J49/3JcB?QgT&=L*<5MOu0rj_W8Oc-qKA;\=[M6IpL>UMt]m//sHGISGA[=SgU+0os]ND %^kl\(F/SbLS@De>3Dn"@MB[;[c-ekp$GK@BO#A;<bQYjTY%6#Eb\3-+Z%AEEjqY@[-t_03%<]XteVTJb*aHN=71fOMn(ihP&YR+" %j#q;P6J&>2RrW'\R!(hr;B3am&8hh)<IDM$06\]NB-=r:\q-#cPXafB@U,*ZF60,>!m4YDaA=;*Bsk7"]%u<*PjoR`b^_L8FA&$S %f_%M-N:$\3PFH]"KI^;c4-0(=H$%2p?_dB\O]s480rTeVElAWgJeWAt8=634,TsYkjf5sOWbeN/"\0eKW-D4?`W60/jW+HRK,^$% %Q0%oG9,H]a-grA&KsS,'9M:=mQ"q*iqpW^Z*N:GM+YfgX4oqQSUO`KC-d8)`>oIBm0A!%BGn_Rcj@6)<2'.W2:#ff(g4M0IiP\<* %J?Q,%WKu//17?$Hg%LZ:-dSnGq9g-_KT:*J%6Df]D?,)fZiR!tPf&bTK+rur<8m0I07gS+%WDnuJ?l)/bG%]5K#a9p0XPfA6?&\n %6./20iqSHpg61#uAfX"fX:,Jfe:>3PWb@]N>h%lSd4gYK]FRq/1VD8$k?k!>=Tt*O&)K)T%JaP5FNB>UaXK%H>:,A/o>?=!0gB.s %<44YRDb:+kPGpm#,aOs!dfW8Fgq?=MPcJ)Cj%_m"m1=rfPApV<L*@6hB+N=Y#$HZO8bVJ3+ooSB!kKN&4`]+I06I$BA40g,,te@' %prQN'Z2ba&`9tYoJo-aI+c;JUd%Nf%2kFk87p^W[rHe;K$8g?,^7@V(.tn`G1j<8WVE3b*!psF=.Ha^i!ii3aLMdF9LLAJ*dDf_C %7i=UJb`u]L;WQf]eV(/uib19XGlZuEJ/%2mY5uRO^7@V!l]J>Nr]+kGhI)+jTc6*2hCol!.c03W1Fn(6D5qtT/'<0f_BEG5O!X9) %%1$LY#Nr2HXj/GF@fo*us"D0o"02[qRoRuKJe'bbN9<aorjOCs^F.JZW!X?&a^(EF?(qjY=Yh>qDM<EfU'C%*1("')oA7K0?,nF^ %d&m0ca9hQ$$_q*Q\+H3m--G`UB<q`)"5a8)3CX?P?5Ap2bj'687V88.k(GiOk6r&rV(s8LX4t&r"%>.+#J*2)_i>b1C)HS+$I#Z0 %.">FNPuMl^+HfS+;HdZ5lH?'7XNP3`"M18R]qS).TX&6qTQX2aHIaReM*2(Z2`.18E<c\s0T!)F;FOcE\_%uGTH)^7()Xmo<1R65 %lae6to!lH,o8#(o*_1Ki;:DS?"/g>H**D8&g-]hk7NaJ<3<tl(=l_kq@'*ed*J$6u"DS$"XJ%6N#O5PMN9.c^rgfqZlSS^?9(F.^ %^&u%u*+rZ<-D4GJNefY7e?*3\(6qceYg44Z0)[GNVZ[#f*J)BGoX[fd7fcA:Gn,o?.&p<udQgb9GGr^a]ccH1_Nc"C9Nqt!%da!0 %S0[XB!0^qOFjRH;:n)UEq[Ra/Ql^N[9dens1]gZ'5DfAKW7ukLk7t)h[BVMA8&Q!YZ:R#?Ni3(0L\qA\W59(ag<T#-NkDUh'nDNJ %<e/VK:X60/H<WghiN&>'*32-cT[&9GT.9SYCY_[UPJkjlCC=cH(#V_sP_@SUea5K,Gi-ht(ko""3,&?rmcS@>#Hc7>(kAm8JC6&s %=j?8QA8A=d$guN@>_"#a<H@(:lNY^9(1P9O2$7hbJXhtlBXA*Z+qEH=PmqOMkVPfk%#F2dAHT#S?NM7'[A#CYZBke;1+HIi`)>O& %.OI=c1\;AJrN$E!^>Q:5n%3P(fO6RZ3R2@N5a9dZ+>?f93$js5<\,rNC.`";kNF5M7*3FP.$B_J"?t<=G<U%ML`Gie!+K\PBgBIj %o&A'?\gOZAP(ocOHkd%lAHHnJGo>m6<c<!(Q0Yh$cPbV=(N6qIdu2$LDnnr5lHE<6.c'WXge31GJ1o$HlAC'olm1DF/Q#h#%7gub %7!V0,?R//70WZ\"LA;N/$N$:DL%q+\o-/bKY%Tq1,W@WT0t@R-Lh-h`8UQ_3*,.(;a"HKS1TZ8K)uq\7`!C8)J;T(;BFU.RW?f>- %p$FmD]=hn_:0r3*M7Dd@db1JM*-PA-XD:7U%s,h3hZ4!cd<q8m"<9l`7W-Z]U,g$m3TRD<0H#E9Uh`[aW-HJieM'8@W)LNMP$@3W %&ZGfHU/NTmmfh85!mntK!;2l@'H"0f!q]tfC^6[\IbB87>:o&8@up=Qe7)12DD=s*C%gWUFh>0e#d9TID"42i7!7a>9nj+d"%lC0 %<\%;=k2`UU&I(i0\WgZ2<fiJp_l4%Li/A=KE9W2r0sLk8O4g\O:R&T'"3"Rmg&5Q+RHXf];ELBK-b?0@)X-*'GsIN^B1s:dJj>1K %S]KhYk!6'bR8d6K9R*BJfLm?a,EN*j=LIH5$kI`Qdq.TA#uHAl+d6ElDTM,]^b@pn0\Q$,,`2RLD(B5I-MMT;be>5ADO&I/fk=#Y %P8>Sp_2F]1cqa%J\1&kj#@J[(E%s?Z3/TZ(&!U"Gk`aQlJBIU\1/RA@*+D"ZKnpAR+Qnh]J7GDMTN+*d\$DZh^R,3n3ic.j&KQf1 %W<(A%<k##3.4>1I.MIiXCkZF?^p3'+daVrT1L8<UU&5;`Sn&+i^F59*"Ta<H/$h"Hd_N?<^lgtrnkA7p.uc3N]kDR1<&&b1FWmi^ %lC#en3<00;(5*,*?q8e4q%Pg=7)K`.ah^4c-J"$7W7K3;644mXBYYd\NYI7`^#hcQ4WQl=CCLAQ]333,_8cST/eB!&1TTht8=fpX %n!,`V_(&W@;-W05ZVT2S>Ij4A-lMIB3lO\U7QW?UMs4XS7"JW<n-[GrM1+DSYt,)\Q4P=tQb1VOSsN-N,GW_=,6eQaY?AJGcNhL( %0aUb]f3^tD7#cst.mdVm8M*lXP5-q2h]@`1jp!NqQg=c;kMT*4mj&DQ18IGK3=T_Yc1D@1j2[(q:2uF&L[d.?Sj!Kl:Wl8+<H#1E %R]T-3(-W6Z).!@J!%iamFJXNu*YQ(A?4haS66qt,&ChPhCna2D4k;4M9m-_C<5QO01]VX_6`M8)\Ng+)k!7<:p/_db<5L%KRHRbM %`LMTQP5+*'rpWQ'-D:uce%s0d<&M`Y$D1K'0a:].[Xun(NIb)aDcpc_Y=^QI)""*jNcM[Cp&cG1\&9Xs]&[9+`#E]l!<GuBDcFM_ %l%+A,qrV_!%$VokTt8kKh9p/^+@e]B7QKc8;!1N@A?/f)o^a6\mf/@D=3CSCA>,5,o=B>&B^Q2LB0Z_mdKV`LYK<46;l*EPJCU>( %%c#1_h-I%j>f!i9m+KgJU6I&Ffb,.7f\0tGagKf'!J$jKBi59E!D3mt[cX9d`rpXDJ12okk)!MP(@C/d0;_hAi/*\qI_f%1RKNm0 %m#$SD[cc@<l<aua,sd&Y0mTF<E4pQ3;DMtU&)TjK"6Is6!PS3BJTEI4jtK5D+<?!j.IsB:>qmqWg-p&-5ZU=.OiBJnOE"T.>WHCZ %R-6(8TEq^[(HU(5L:GSN'h;Y-R_C]U]eP!je'3Hi0[;eF3QL.6q9^["!_uGVI@!mFUce_#Q:aAH'.&)H$(_BZ<rRUBhR,A(j&cuo %"oJo&`=_[\!j;F^kS!u[%e%Q,Y\Y>PG[l@,JY7Z2/m8g^bk(/Xb$0#]9JsC)P/%J_El`bDe_PAObcE1a>T4q=KGGbr(N=oc>1kBA %hV&6@UZRIOls6ks"kK=so3=B#65ZATSGRY4P'-[.\IRVrX;]h<EN\1B`?<mW<"6W8L?,R8*bQ7?EEUR9#"#6,n1%(/KW<EO=Z(c( %ntL`p9GroU`qZ0HN,I0+Mf+*!R[4t&,sf,F@WhSKGH7N*,*ZNp*0>#?bQoV9Gqi]d,[c:P^X+M[=cm)Q<,A1<$r%Q]fqt@//<gsl %l5c-Ag7_b,VUuJ]Vf3mSjORM,n23,>$b)-%ATTp0]e*Fp]\7Mb$C`"+60o-$;">>j'Ijn\Ht`TK%a\Wgq'Zs=ff<_a[(rnXI0Q\# %SSs23[81e^iije=TGSJam5':nYhq7=YAP$u&9B`p4cjePJo<0Vi9C^6r_J4<!_s+Y/h?a*ooPQ:(&I-L-8a^eWU`dN!u-3GO)ZpR %6O+?-N9Jp1IUJd[,BO'3W6J?%X;*sK/&P?B#O"M:^_%1$7>@[4U:./*N6;]qTX5j^/oaBjCcB%-Qt@<3TbBtn#c._oB1j1Tq.r[E %V6D*^XK@W;,qfuE0=n3+B:-npbUOCV$Xil&HDBgL/8N1@#cl:HOkN0BQ[<38,G-ASN;uG0TTA$o[%]NG#B9GgA3%!EfN;Wm.reoH %7/Z<G$d=]@V%pQga+kF=%Jg&R?OiGAKbjknhKUkO'U[^to7i2-,DR6F4d1mUigi1SB/R"iZ;;OVi[GnjJm[=?p9NO!kR(:j0KW<H %Ort(2hoZ3`1WF6e;SfH:/?;8G,mYES'H':>RLL.gGjCDL5Q\G$ZA_ODX6/HKYrE1&ZJgm:A1"Ge#BOZ+%^i5<6k.c88G*R!TfesS %gqq[K6[VQP"Q-(Eb@(dYF2UWq8d1NiVme5:c''2J!6tB!!#/kM^roHWY8D*WlEIkE6AGN!FE#cT%[s\Tb&N]oE8ZutTtEWe<26bY %AT7<A6+2!^6:@frA/**#[u?!aIL(7`XiMp\*M>qEkNioCP3g#$osOl.2q%63';X4P5qPZ#`bulNW0YU7#-lXb.%:4=N(m08aTV3o %Z5?1pnsGM#J8sn-EYgL9/^""NUp4>.p^U4/afU-t?u_i=a:qc$^*@f]LK&2PZG]ju-9ACH,&pl\afsD.^7X[&$_@Wo8B=OH&]tL6 %1)lQkf6SsKmKBIh:kSY*!ti@epS)Uqb/>"B&B-U#!"3QY<`?RY/,_L?QB$X.26W'lE/fk6)CZG</.@c3[(a>4fFRLF_6/&#7RB4B %jEV?T%8MnL96??u>mNC[j"I[Ag@B?H0J:O1>2X'HSsr#_c@TeBKMX["+Y&>Ig7_YEiXgB*B:1lb.0.(2BnY<BSH?T49TP7s:q]jM %QfX];W0=5)3J0!oiBr7-M#oMSZ!;t42-FcA&_>\f3\&mi<YXdB9QF$6\9YP/6kk$VeB*4OZ18/d&(6/>(q=.NYDlM^fnliHT%gRD %6ERB@8/U.oasl?"Z=WOM1cWi3_NFS?QIU=r3]0AQK2_?`=S%j*8JDdlk>c=#_+((q"1jQ(csX4+hS(266n!q(b\JN@4&H7%o/d1c %VB\gb\j7n"5Z]0^JD83.9d*mQWbF/Cfd?h$)\)lO%5J6+7q-dH81sts/UB]]<_5Usn8%e.Of<O),I)K)+WVqcA#kn9JuOi"82$od %VRES/EQ_(W>%+QIYRqC`>l[94+KQoF_7J"FNHd!LC(4%j\/@TRJUtB=7L#4qZSmcbArbmk:/`F:+LOWq+C0f4To>Eo2e(mHn8`Eh %@;9NkA4T,O.HVX<dU3Mt.EXXk?k_HL#9tCTNQLdE=:U;kOO\0m"!VThOi&^m>(EJ$&8F9e2>DE1A<Dt;q#!Z63u6tNc.lF;ou!,\ %$&u17@^;*9AM__j^frhTmmu(rPQil6H1Kb_E^&"'4`nMR+4(Y?1bQt]<UlfEKhR4M0,VV?5;Ej@B$qce(T:;`\X$"OglS2/Yt>-^ %CG[[__4$F<WHr+o0gs/DksS&:2n5_'VEpmA`$1Fkb]C3ECLo:S65?NbDnK[85.]uh2e++HEutNQEs-W$FNn:k19!t*YVYgVY^[6c %NN[dSFr#d:]p=X3OW/5`YllRN;A*$F&5oKBE<("6U'TjCi9W18g$8PB6PcW:c50o3'G/];>de>CFu?j?)$pQ(]Fh%R0aq,6P5B6H %Up6"f:iY0*fdmH@L,3rtX&hD..H9#PR&h^PQ!(=8d&!VfKc%p(m>="6N20C1QKaB!_FSkl1(OV0jS/_r%rAo*'gs?$.-mcGb$'ah %S>VYnG5k[d"\(fuR!PW/ED=plk,!#d=Rk$Xadaq.3q<@@2=nu?1n)!RCkN]Zh["X?+-+9[]0GXfE1^_-Fs7/I$gVsKj@2eb2I",X %^E3c%c)bh2"6**d8kfNVa]cUklDbTA$Y&5K;+"f7JY7A3/D0/*,a0h9%oHK;A>E1e+Hs>r#i![d`-;A=C/e)rj^]VVaDr3h!-TGZ %2=TY:H;a;'28TWM\8oSH);)K'%<Q;0N0W^@,d(iAC;2%PPc^?/R!Jmg_)H"add6ZA06bkta8r!d4/R/uNl7MVM46\:O=o'K0s85Z %mLBL$\Ek?>\GAMTL`'b%"d#OU2HRPbi8CP4$Z/FT;?r[M3mggIHPRM#jAnIF!A4nVX'o[.WefAt[(0qB&98nkR\<CI@;KL>j/=#< %'8ul48uVDRLbehSnW^quT5+[QK:4Vd6E=;K!0,S>e>GUK2e>?^b>%o[+A>>W-HGBo9aj\3eB5WXidD:U_SN!.(/'g^HABoQ+Ot8' %ENi?SM&M]i<m"IfSa!rqTtFbUEG<Q*_AZ"m$6)pC'h\`BkSU1$M1_YR$3qC@88KTKCk,JVQ!1=#K!_S<AV:uc\65+NoAH^6dlp<_ %=V8e&K!K:-Ca;Vh&df(Q.r6c-<pZ2o#4b;4#p%"CeW8&-`?EaFQ.gt][0D:j[DMUj2J$Ak4Qn(0K9L2X9HLYiD3X*5!bp'KL((+i %+0XZXUnQq!Vn)(6#n_9mG%1WpP#lA"Wh.]krfg$WYh$Ujc*Du:^W&)2-98P%H%GI@N62M!<?SDb?&0<\nq'?T$qCMc/onUJk+o(' %i;i]rMraqSKlKX&/p2#rO<MuJ/Xn#>P_9s=:p:LJr:(>_1G11tK0q3,8/S'>JeSHp"FO_%YWRfQ+,LoZFsK!=9=i8V.iKnk7`Qb< %MSrdWA]5HB?l1#TP4,,mCD#Zc0kne=_Fc60$8FT@^-Gb!V0BM*Y;Tj0d1!3tjGs*cAc5.n64"_S]g*N&CusXNW#iVQ1''[(>4b2( %h:VqM[R'X!g<8iHUU!J7gi?gje3kLh@O3Y(+bk5,OH,!HQZXikGR+SWYUi`f7@(k`,7#dKJ.bA5bHdr[h2hpVo*D.hYJj?g+k$lF %K9?A0cn6=bZE3D/V@hB@5J@IEPo]8tV%6$^`"aBg0-a[HS#4q9EhNMDdH-,8%iL@*`@Hh@Uq'+=@u<(9@VNtG,2+"SW$C8/#nGsn %-j]/^[2:)Tq$T]8'k+f>isfBq<c7cXOHZsb,-"E+q@'W^2q[#M&CHabf#fJR?T`!T,bc20P6YJ>o'b)Nb!emEB9.fpfAu".j2K*G %-4WugHKgSM=Ct>A0aSl*g-OYYi'5#:D-EX3^`:6U0$?AC9gD`(e3rRJ05/:uW=9`e"q:N&3:]ZM@Tc!LK+Hs4L1"C8-DG4+JL0fp %Q3<MK-j9$"qQM<B'H^e?Z*]MRXqje`K[>M$$J1gu9j(Q$d5*(Y,b`bk'oH@UnODQE/m/Z)PM&)3,)ikB?kBBG=]U\a,:f+bcsbdT %Glbs7,MQD@i!:>1VnH@Pl<sr'nGo:':2$'<#GZ(63kl2/Ld50F6iM!nbQgF$%)NU4I1R>)a;ggIG&T6)e;2V^M'dtYim)J,jflB% %gH-0/KH?+P%^P&Y1'3m3nrhpLj^C/TLIdATG%5J0O+[U>66k'Gh22\)?R$U[%7nDo4p\2M8Z?%NZ@bTmFQjq/5SA@Y+I:M>NM:;6 %3g""52CFnT/d)SMadRdcFdb[@=ksFc1<?,L;-Dkd0LW'>64U+1TtGo$#0(5:I?B1hMi,[qa@.L1&B]u0fqM>_A!M#$[mIadXY6V^ %-`L\_*SCmIGmDmU;18j,@eiEX?mH<[b"p<):Ldh/36(5iY2[Yaefa%C\Uc)>,`FURIun9"WhGu7^%O%jY1!*):Qg#KP4V"#4qJGc %#Md=-#cHb`puc;JXG_GN\qQYsF$t#?LTsV3buQc!SB$&nI!'bI\E`M.;n!OcEk*?2ia+YX1)&%l'9P60(nHM.So3mj2bIa8U.AV; %NBUO(<;O,pYo3boNIRCQQ(!N0l:,0(UU@[q?/6@%M0Q:FBUJueDT8>D`2cVO[e6ERjs&q5\um!-2\iYX&`7e6,iEdo?kZu$NCB@n %>O99fG,$3.,:C*#QCIE3'="$*ELu!Bd$a+F;5@nb-FFZ)g5U6GN/F0aTTs3FDHuUm(uFPWkX>\O71j_gNdH?!U\JDG[M.i:((pN8 %ft+\MT'jO":W-d>`,BiE]k=+WRgAS&XEcHM]c4fENHLkRMr+f6n&F'W`8u2Qpq+rQ'?gG^(4e*q^aqE1_dh'P46Z5ZFSHLrGSXmO %)&iL/0%7]@.n#.YU<>F!J=!"hYirAuFI=kp//hg.N<sK_/rrMhnRI.kUrOb/jW']O-Q0Ef\u[8X$n5I?PqMOJ/4W?+kL/=;RG`nc %o#XQZcciWCN#6Cmgc#m/3F,CN0)Nos;brb1Vp#)r_%kJ]($ZABc#OOV]LH02U^=K*0!eHBK5#q>WQXVW@=XeSMje%>l>f_Gnl7R& %<ZMsW$-'%QG-*q=fA2s&,CZgK'3LSYXNN<KjW^2S/SdAl\nl&Db\:@K[4WP*Qb0@io@DrSS)B<rigK*fd`o)LFdVT_nE4r)p:@>Q %>mA%rgL#^OYYQCoV&J]@'$g%a2I)#C<l@Q6`D*e[/hc5t%S,K)lnUp\+H^L9-9%;@-WhqsN0dgfbR#?80'?i5STBD)Zci3ujTh@; %'(,7MFr<n"fM&p$Vd5>45+QGDH*tiC3l1"5jaQU&`6L-\Nn@u+4LGim[M/SJ4eg^qV=#]+DO72DK$h'NrnHN@T&:<Si#f[sWHa$F %\BBCbi_#g#<UOf[GM/E4R%5U,TY#U!'AV#A*pPq!opFS3GiJsPl$'BUDL&R8%,2G3g`>PF0$!]3+*a,6]ZW&o_+<Eo0CSJ%G<+'_ %r94kglSGX/I00.g<qn;"I$\VtMO2'#@=L5h4h*h>jnUWhrl(bE@GL<ko2"lNG<,[^ZNEm3&t$g&d*5??S'+(f*cs1`/BOd9AmSS8 %dEk\O0Tl(&Ric)hQc/H*'Q_qYR`lT(*#WTSNBms;B&;aJka4p'd7O5_bmuRl9B7/987n$Q%,^O98"%VudcOj"An^FAF6R4al/mei %c6q)c4`bh5RK6FCc[N3_.Hf`t%IoN[Vji16S#`HVf4Q90cpY=8H__T!k:;]3FE8D'j[&aI<d']`WLI1-+qmm6CJun";a1jn04e*9 %ZdbA(:7be(o)#<C+kbd6]4>oJ'<THL2SlcOAS(23\'=KV23`&#lF7nW>`Xn_9Nr=bA.oAq'5Vpb*.(sT^-6UFO6*Rg#h\5Km-r5= %&+hjG2Tb8G4EnY@[mkjg.1YuEWgk]@c6NEdQ`R+*l8)'5A-WHr%^"(^"d'3gQ`b"]g??FD=lhQ!np_%Fd_K??bY&#dm*IO_;E8l5 %T6^W;'4b!hii*6AW\0iBQhm`&OYt+TeKs(@U$.r<oBK/%2'cTDKOPVU@m--`]D9YtW6aT3e[jgW;`&?4P\pU#>F-[SJl8a=5M%3] %><lq)$1PN*Gn[Q2>me<X\b[XdrC.KO?*_7'@R59*Q\9=;Yjg[BfnS:d97o2iRFnE=lk2&H8K58ENu]^k$/3HA`FP<oEf.B496/]q %_ji$uCqqu83mJ&sc7[@SQOn8)4ENtJg8-'cU+bn2ST[S%-O<[5A?0!>ed2]80&>h-1$gs/gq("lU$E<AD33K]&K_rh,*s8.:.33e %30eAT9/l^D(FdgmWgSaZR>BDXa7XO!JEES[R`M4@%+8t);N5MX7R0[996DJ[H6HBhd9=6)Y&4[#>.iM!'5[SuE?*\Vcc30HW3qNm %EAtaO/oGPN`i^8?2\EUPNUlCh"3s@Geel;B/E1L$@N4@[Mh[aXSErXHG2k;)@lO:)Sp*\X:.1.$Of$s%eCjWI-J#RD'g!!ngPrZ/ %`oTt6n93i?qiS^9;8c2IEAoe$2NG<SH1$>TpOfDkiRXR0m"lSIM0SK,AGB=B\Q#48EP<$UraDR<)p,f3o0*a.57pQGNOka<d-jHq %pZ)893!(!^JM-Q0/5&9qd9rOnU!'F^ARCg6C?Vo`FSR"j\KVquM(SnLh..8FD+U&p@tH;-bH*G7_(idXdH1)cZ@I$76b;V.>oo/# %cB9fp8XB`pJi0CJYgV]D\XU()bOI@2*7JJeRGt!0iN='ggh\b*9X*\R1$s'CH"Ql!)Qo\b.o;9mW67(U`Ci&*@5RHoFd\BS=d2C7 %90I$e5)I_mh,BXVC77Mib;[s_VOD)$C)F-4\ZmK+[/-:s'C8s[9O8spY:`&l"IE5WGHAta2To^`0V<JIdO+b=-Fh[=/8[2%D@QJI %QR?[&;f72:Y00d'7qt!0hfX27-91\0r-M_H^0+LO0`tgE.r^)AYercZALj9Y2On/@m.)IJE%?rn(qY`d?$=7@'4dFcEe7Z(b=1)q %Xdie/m'0uBGr+VD2Fi.bS'7E:/>%>[croe`0$ia;PI/M>3l,pl@7BSSVp9=bNd+^=%'Db%f.JlG'Sl#`h^mO_b-AP"@6;GPgZ?GG %@*tNVge@l4Di_oIbP9h'#O^%HG8Z1Jm)0Q"`Y4l_I=C60PO]^ZEl68Zj`6sOI3*ArGM&]=R&;<6Wk3Z0ZeX/t-+h'l4i+eeAa/XR %Gq\.U*dGPKK]4fCisee0LX1@"q7Ob2hW7\.k$IN([.ie>Hc5A9MYJfjr%.=7LcW;gAj=Cbhdspuo'&qhmrs'R4,j.Pm/Pm8!Ss7I %ZhXhq\I,oN%D!Dg]%I^BBbdKX0_A7#FE0E9jF<Q<("(8U0p.$]S#rESf4$'3`[G1`Roj/`0unSMNc)RkDJ"s?/0JfLOBugeDB=sY %cB<0fP<8B/FE=<QA652?`6uoad`q59P7+80)q.G61QdT-,&^1?_bE?7:+(,.35pn/XYq'CJ8&fJp.3:`^!EQl+qme:25m!OBHe6i %2fDPP_bi?/;E&Ah2nr6L(K382dmSqgM/6#EbYd19;cELjHF^)f=g$=HkirPqQ]WkGD4N0DEkH\,XD/FHCMR0loe(NRf56-Bmc1Wr %EQ]0MA!ZGdcug5l]%hIM4ErGj?C+r9P)6B[g=PH\lYt$aL`7DH%Un0S[@L.CXjQrLMIjLnrR3&!Rc>&";\+"BMXDfJC<2II1eA@F %8mV:i$)4;";Q#f\W^dd]5qCK^T^%\?9b:NO8[,dJ=VK:g*?))HY=iurJ_+ZC/0"B!Uf<[-Ckbi(6pK6G.[qP<lOff_R*t+geXDeJ %R+g+Nh1i.i0)Jk.,]8W:Xs'D&;:J=efkjXEF\2/d$2$dKHQAQh5,DVQri]*33(k_\+s?5M'i**op*gRA-;0jO<bt>EHZY5\e;bOf %a=^o^"M&'(LpBZV3QH$j&7P8L1FK^j2d&,PFI`f<4W><d/n*rP\`ej*ZqFO_6#YJR6LBl3Fu\SSguY0o1=^6Gg3k#?\h5AdMu3"l %i?9Q/B-X96\jNdI4`/gNKB_RU$N]'jT@"JJlDIf4R0kZA[U,MT6fFN>(jK]/9GftKO]Wfq>(:W\*6@U?9j8K30`e?[h/et,^J\3b %%Toli"imoJ><I1fVT:]+0q^Zq-YP!?.5:rR>CU`]$l?*uqkpEZ-"a#mGjk.MSo3YpRAGls$%<N-'5a*j!TDc3P/X!m@Nm.mXDAAP %jpI9f#cefFf8nZ5UL_kbX3E=Dnn9Ok5%?'T:fF'=\#H>h$`a=C]O*/s6)I3Rl"WRD*'c(&%B6;=DU]J<r<<Z(T?m)nX5C,[oq-H0 %?Ot$*J%<;igWfQEmJ59C#6uNoA_m@EfjB2_^M$&cqY%Nc^,j"WYBfhsqWmE2T)IVTJ,\R`f5Jsmf,*VJ\*)@E-T<.9qSUpcYPrrq %EE3![:o\YZrr)`KZZj/krQf,+G^a^TZ<#uWa7G3J2eQ4]GI..`T<<'e^VTs+If0!Mrq;WRh="EpppRj'lA'A9%jr1^WQ<,:'!QRG %Jb%KT=HBSbq7l*.rpN@U\Q0+'rlb,,gE5VEcc*?!%6pGTs7#(9Hm>HBK=Bk9T3aasq"_sof6XkWkATM;!G*=b%G0M;hm:edU[.YU %DbAiGY,<WFd$2#L$2sJ\r:\roRmr,3kCPU.bKb;.roX+P(M?gIB<rUFccl'8]_N/n1#%;LZZkjk(9B>Ap[Ge;0fWfMnbpSAZWB(u %s6k@R[0<JR>4Di9PF6:7ebdP)T&-&d3*WW6g9M7GPcO+gDpN>tV[f5j7IRJ55L(pJ1hfp6akeaLFaZd1B/dH/J';a46]LQupMF1. %k>tS\YW\5Dd">,mDm/'US=]]Lk2b\IcVG?6A4\j(Tc'%/)sVnNo@_C1mIe_O$\jh*[MFn,07U]bGCI/7.=?sZTJA8!m6A6CHb9-# %D_UPfVS0gQV$<.<)ba&P@![0@;Y8:n^KdDGgRCl@@5?)S-$ILARbp!r(=V,Lg076tMeR)a4W01B_!J5K[&EEIC,NOL?o9NM__,%c %7qWph0#%;SjN[?NTCoL(GK^FUhp?])h:(cgMt^/>nIA\;o4n'4gG^e25+J619pTIpD<XPPWrI>7rnY3XPH1JC6/"fIFjZ`5g(c>, %Qej8Q+5]3#!I=Y;mCT^Z4(c[">1.=)W*!t%52u/3.h9UKiBC**hu.qGqUbI?rOkQsrrTPg5ieJB?X2Lda"KYP)f+gAp[M^D"-\X+ %]\Ya-J22N@02?DFYHQg=Sm3iaTZni*]NOh;OE^/3hO^7/I=$:GBR!"C+5ot-nM%ZSpWqGmBD3:@iJCjgndi)Ws6Qhtn!@"&9C;Z[ %Z`*3iHbT4RrJ4Xmhlb;/DSK=bd!lpggY''K!5IK6AVW+*qq9V+lO%"!Rd>0t]f5t?C\p<Pr,#Tdo=EjU$WcgogV&]XFt]:K:k+q> %^"_CfO&5KsEhg-P"K%JU3s'^Yc+'D4Ju[QqZ)VaBG&fc\YjB^SG&hYQqr?ekm=I4bgH3T%a0N@5[s%RJp..RFkHgX"cCjWL8.A_7 %+Zua\s)Jk,j%4^%T480S?u$cVo2X[GpQF*S36Bae8WL!X090qqcMi1iVIP\)h_?,MP5rbh_tiNKS!,eomh^qYP^@Yui<^>c]=U;? %3PROVE0In42VXk-Dgq]UqVq@,H2V9#2#mM4oXNZ&'8U4'&=Kf\LA'BKVp:uQh1iY9G6Dja'&I&WUk:fmo&83ddtoGY1A/,"lWKk\ %D>i$AhhJ8hHIN!*FN:,ck>@cH..2KtpQo+LgC"eMjb%"LLsW5SKqRd&6=YL0hh(5[l/pa)[3sf%q+J9Y+&B&Bc7Zgo]/VlXA1MR^ %n_h[gqtu0(]plG*`1rk90@&JRHuX1QG'S7Rqra08GNc!84=RJ&^GOY^b@8;6hpqlsXlOu4NF2ABf@`(AD[R70.JN>l2"*]^rj1^- %Eje-ZDKQ@2IXf(IiG[aO[A;upFd7G@Ds_EAbb&gkenS1m,!ist=2VJJU:8>8/oT&h/f(-J/fnFX:G.)Vq)ENDNE4Qraj%+;70Oe4 %oUg'@pQ5DcJNJdID4qp7p3M;LGl8IZTC;\:$TLt]ck^M5Df;d3(T_$roa!b!X8-&bjRi*Cjnh,WNgk4!AKO*(C]<s>=s`))$eBd8 %@H6>XhR8n01i;EFp#aNpmJ2M`/ZL*=+X#t5lsr<RiUl3joZu+sYjG0,7oJMGY0J\e/<DN<_V\A)W84j-:7hLp@R1sAes89dHPj[B %#4Y-[rmksM:B1U(TFG,;ofU4k?OQ(ip-=Es&E:kbp?`#Mm.+".Y9[sF&E<<g!$N,b@;F3#4V2'5KQtRhGmZfm-0ot`%u_Cu_ik-g %S3?rr`.Bo6JImmno@pk!:S.Uu@R1sA<i^Oo+N.=<6L52BA'$!$]Ep^KW9kd[f+JeI^>D/)^OK#TKH9:M03<]pqY9J7VEOt.lPIWO %nG73P<HdQDGp5Yd$f$'_:1a!c-e$^d:j6hS@D>+qmKPO5Gl%qb^Hq8N#5.Pa#keVT0(2S35_1tK=h*@\p=iMqHePMr41m^>!VL0A %4mf_Vme5.:F1ctSqq#]LKmhPFr<c]=6K2p(L!7#P^I!Ce/*(X3s$"'igVq:Tf/jt)orqRP*]boZXo(<&NU$<5,riB2kUp^_2eSK/ %PMsH,WeuR$%^#BT7]j$Ns0#Jbhlk5ljlb7W&$+NAAF;VpLL/>\/`sBa>(dH.]CVU'@N3rBhYdk1&@66LF_hU"gm7Q42eR'TYGO+D %[\qBrB.(/AQL"cLdB2T@fG;0^8YdF)IS#FLXbUXEC;nb-3I=DJqj-pGqiRui.pfY4[WQ(@Q%[tCIK'GuW_[g0No'ATQ?;Cr(DHDh %K!kO*@k?a=W>]!Q,L(SII[[kBBh,sUqf]?SS*GS+Qs(g'!9cqOqL[6ZKii)jDBF/l498?hPFM0u+"trX(MH=R]eaMLh!Xp+Q2@M\ %72=J4=FQ8Lb8mHtgYZ-$D_1WAQ4H21iQflMYF!M\r@R.1Q?%IJfko1:QL\a1f'dN+pU?C!laPU*;Ehg+ZbN?lVIdHqQ[<YrhnFNR %JDl"DQh8^\D!e6oVn%-JroS(FZ+aL7j#eg)Ksq1I@`R)%`Ep5]0Xiq]fYU,*r*MEOUV[PuR#bkr(Y?FG[cl`KLECHXh[`J5]5t\` %lfIm/UqJkS;^U_[5MVd"?%$"=fs@l?0m!?3p"(;2Y:n1=^V2^ToC_e$ajm2nJ+%#raLuT&ZTC?&5LZ?$Hgbe)4.GrhVBs7HmQ$bY %R_O51q=!pupU=)3PM4P1"Wr+YL&"c>?'P@kk3-K95+7hu`AnhihnTHp=9+0oA4V-dLVsZsleQ`m]_hNkZtKS$:BF)#+H;nuGI`RF %q8=NAYtrRUZ_0J:lS&;:F4#U.1JYh$O.ZVNH1L[CMnST=Z$dGTW?C(%4#50:Z1hPjI2ANfqKq,=hKQ7!?0ltUHf)e#q(=;f0_'AF %5'l[Dq%@iFQ49`4oY!ALd+A.S@J6:gI7XA9fD$tQj=c<ZhU[ed`Q57Mh33"A*<1kWfImMFhq!&M"d<S'j7+eJDuY!$53[%CTegL, %MSD;efacKSgeTrdT4a4p-#N$H[\oF:bbJuM/+^-oZJE&&?9TV.PVS.Hn44XN&sP0/rcn"rqNlU7N6*u[n]C.C2R<p0hO9(DSul]K %(qaF$C26nhI+l%g;`eBFL\^[Sm*ot2^,rr\flD0-B%b22oh0YJE6K\U`%mC^N;ndQo%VO)J&N+L;G-_mN5M!nS_/K:f\8\rB*TGj %s1?rU\6p9Up]q,OU:N#)#Tc>Vcq_j;rKm+79CQIsm,?],(UW/AZUNND>40420mEcnbd)Rk^c'n0:W!hWp7?dddR&04'9MpZJ8JKD %$\i0[$.th:EUO4dNcE]u!kpo'p7?e1Y_-ghQ67aP<mZk06#U[::2`o\rc3G$!0^/Rc1Qe'qghslqDjZ_%pepTs2*?&H4/H2[C_&P %S>RD'roDngX.-Hqp\sOEFFhTG<rCo>E:^lfX7qs1/W9YH'"Wh+m";e/lMB8io@q_CIqS'oJ7AO<^KAp[;;kg7ZhN6(h/2VC\5Uo9 %4N%-bon$]Fq@P3lgIrea[dCO_f9ZkG!LA%bNU8/lTe&2IpIlu^-Buj2Q9>o((\*mjj8I6smk;gUhEA@$cBCFC0r;>/Pl32_,OE+! %>qPGf]8@e9;"JPC&?.%-+^3<K?,.!\8*T?=GgIK#OmP<qrI2;J;j;IDIh(kuI4qrg<):f)4--)fHZJT<ak^/p:X!9O[!D%UVS16] %\!\;Pk'NS3D_p4eAt%?7p,:B[fh>0HFnAY7VYQ&8*Aa/H)mhPmp.!NfB\FD"H_]h^(ek6]GKm!RFl-6;aZfgDBh97e_/T7slg$Jo %gmfqJ*VWU`N`f(PKY7:u`2kVMP2=b92K'W',OW$X/oBp#hK/.&e])]Z=1J*jfU@6kMuaFu3*hc\FR,k(Z=[q?b^Xt:FEbkPq]F^& %S=KTNonl/h5G+I;hgYKa-#VF\[iZE_H)G,4[R=Ff_ff^Ir$l07XnDTD>U\@,EBM3Mq]-<o*Ui\3p0774DTbe_gW%1[oS?_dSepR8 %gt&kq&%d)\roWUil.NPD-]9gA;<`j[nBRL<1h+MW=."5XJW6r6^_Shck5W:A)AR_j`r,DfOr2IP:.9SMQO_KOBtaEs3IJ6*?\H%S %>(27[@DY4;r"l=7m[cM->(3q<X='9lIJs52jt8mL2kSag?D!*I?9Cn7s8DQ^e_,A*Bm=*jYrqm6plmV$]u%'V=P>f`b8\_:C+N-` %Y^4'3j*U`?n*p9-3.)NQ:g^H$IsR%W^">of]mJ1ZhOhBdD0t/'6Ih\6SoENjr+W0%3s'^i-dNK:9NuZ:-n7"6CZ#(Hm,[=,p;b@_ %-1pp.Zg@56o!Y-$pJXi]kLh(t8R$P+/a3+L4j"PAh#1*Y5KY&;.,,aql95U-G)X<T3)FdkpV0r:G%g*3%R\@%aE'F9'<so[oFkc6 %ga=&0]rg.tXo-lR\ND=ERZ@L,l:q$pqq'Ee_0VsQJ%aa>A@@'agO^^rjW;(.Ik6Yp])u1,.;-o#),M.$2h/PW+`68^IhJd)dgB%- %'*i@&!r5/8JqrJPg0k2:^HTJ1`.N@4A06E<"VYU.Dip?d:g:O^J^53giu_'KiH5[\HMf(<Y8O_]lf&5H/_:ANaR3'^rQ0'*(%SQ; %B/d$>D]ZrQYUs@1Hh.,eESP<LSQX4L[]u7X/bEe;$9oU1cMOZk^[KOPn-!@O@9fe^;k6R2gs;f%SP/hDDG*K\"]7OK![:59EH?0n %md1'2o^/'qpP&0VXlJ>G]$j\qJ2ANY8-dps%t8TV"%5sK^UX&5>86g:=F4<0kJH>/M3$OEj2g\\s%09C0<a6^bTe8$+F3pPl`7dc %=!24o!Jul_IQ5)Ws7#A.5P$u+:Z$W6r;QQPfiRmll>Ib_:+jlMXT!ZhIeE[40>E"6<mSt(s8(j1qsltZqWkHgkO>[9jZi`Gq;qVl %d4[#ZqXa"Pq`eig#0QuEfg/Lg*U7%M.TmJrST/@dM.1UpF%!8r[,1T.2^m748nhYNg)gN7'8neUo$+M9mn7;Cp!5/PQoD&fDGK&Y %(KG%CmI.;hcBen&#*X'!_mAp"jF)<#rL'E]H?Cq>U:`Mq8o+3$3_[BBe\<`/BmZ5,1Fr:SHSDtIdL<TW-G.03P@#?$54aQPVc$gr %\a55EQd=0TauW&)Wk\0IFoK`L$bZ]Y;]2/`LT14-XlSZ`F3^fl&%Y-)9nWb<1t%dZmk$^?%^T1?)YpfMp<cajVpqDYk/F)(^7s#9 %C30#?ZWmcEV:B!peua&i>dSd!:qFH.iSh&gV7Ytr+_LnP*tF8bANY)d@hEk`_,<.h\k*c/1I/_=dVm^j1AK/YO;<9V7Uj2dV,rUN %#s-6LC/a9@dB]4P;TO.Ic;Mfsob!.D4+JYrf)V806Q$-0N&SobYcMNAHtfNCN%((c1,X["(`G]:pd$!<;Xg?'=o&&LnM"XIB\CFj %2*I@lYn#?u;9nhb>FmDGAf;e-A,Zn#k'+#dQ[dQNn*p@R*D0JJ]&T.WNMW+m!Zpr!#7h&q?N%D?W2_0lbPg_#0/J[g!*p6nmp3(q %oUFtR(.Z6,%DHXshb:]jrp[)gqp4hO?@DMDe\D(s%_84dP7GpL"mu-M?Dh49'pUm7V_T)\><2etf@8pUcin4q%#?P-Iba_hk>\na %j(BQ24<m0`=iu'069O^)8<]'\YJ.e^%Ed[fhD[+'C;j);P\LZ5D0gK+60->#+dlNbZ`mCOY1A@W\l'>j!Ap.o;*!-Xo.0&Bjf#f6 %OW%<]4tOH_IQWoZ->*tVE^k%?k7k*o%0PK,K%"Am0DVn)D-W(djN<raDia3kqRWd,T`ZKu@1c^DHa&G[GF$]d&;I%e:ZVa<LJDb< %^H!p,[TOZhqLU3J[e=l@SqXo.D/C%KqXZBD1ul`@@T-Nkk@WBaUJ&9D39;<&7JWX;c-aU?BqmMGT_>NM"NP(0q<'P:M-iDqF8c'j %lM0H"iqs&Pi2hrVhS8r-ooJG)@d_'I.kgbNhk'dAQ0qSI"j4Q<mb#5^c5ud_p4[s5?MPE2=H3<"U]2f>YPiNAp.b@rS8.09AU_?E %gM$r65t>""MdlY?Nm,)l]cQfgXS6M3lIhZYIlegRY2?oFb5,m9>[;5+MXofPZbVROWu')i'5]XpS=G5lY2)1[Hd,u"3L(=IqrX5- %YM[Gchc;DA1<J+Vp2Xh7=-V-?Gk:=PM#Pc#PO.<K[@2?jZ@2YiqHgm=oD<CaD*;^gT'J!MUZ3Arr$h+N;V&FQ`GUj8IBdY#nR\[A %fASED`BhIH2Fobeh[r34S^q4ET!sfeQ>>1?koB6!Kp?8Z4ad*B6gShFX0j*ZYp[t7I>FUH23A?dVA*_H#sOfCFA$S[JbTrNC:t"u %JJYg#7@YB:$n`k[AYG.6h/]l=MuhJ%r("coY+2;tZ[o>sE[Ej$6rW0qZ.MRc,brgcqm*\0%89p#b4%u;_J1n[A\0L^q7<ePQHF)n %$t6nN@D0:q(9<$m':L[^Hs@bHdTtEL4WZt(Xg`a:*pqDE;%DSO$Mp5NFi1Un%RT@U@rNu/:s9CbQi0@qVC30u.eUj?oMbMSkP@Uq %VsCB.@pZ1%p6G0q(U`sJ]1YA<gjNFYR@>PtnUL7>*n`4=m<=&-rU#Xn5G.n,SO3"OHLd?9HOYbJ_sF7%rTaDkk.f*N.MI:(LVKIP %>cbYcEF,`XgU!Ba?bN-[.a\1[TDoCX/?d@U]kdVM@=e",T3qP9EE<,5p$+%t^MSG,N3^1XUW!B-GC<F*/SXdN\c:'f8R3\U=*el^ %>e`t]mn[$#n9B9QqSgSDam21)Gl?fhT@\r_s&4CFo&")Xn"G?n#H6_=XOGO6!+hEu7MZN\(b_=/:*i$ZCb[,3h4&,mE+t*=gfT?a %Gfcc+n&XKQQo+W^eoj;:5PtT6.@`_<S^Lh^4W(q2XAa5oq4_!R;LnphB-h'b:R5Qj9#2^URbW,+YUr@qKeqX0*6*$m\V2+OY?b"R %>WEp77dDo(B^(\1-Q4nDfR)iS.G@#a^%?BNbU4kKO6S9NRa1-->Llg_mL7"Q<(cZ14+2;`4:RJ2[Wt,U\FOk9_bCVQB-&UOZ?2qb %HL/LQ4I4*Ef'.:C'CVVbEpHa_3QFJ^(jX0mI?l^7j9uG?]&]_1*H^JmBmFY"_Iq7,kfguOY&$)6O8X?8$<_<T*h`*:oZ2k<'PSa" %5/^6g6/p:=nO<A%7AroG^1.VlJi?5Bh!1`"-bSd?oep.LG^d?".dWLs-'jFgLfJA@Gd]F^6pLD=NET+1O`dW2.W6"qA.(6"_'asZ %8tr]!pC+):f)9E%(H4N<&6lX+^B:2'CS!`ZD.LE?'cb/O:CDhih5:ECe6g6[/JN!o<5giHJ9IjtiTLHaL08_:_I9q4fE@m+)fE3K %=Bp*.XOFG\Ds5-j1"^UCi'_C9AoK\Hb^i]\"'U_%Xc/3_a?EH/F>54kPMl)dGd\(\]4PA-T"]A.2-rRKbYZ?(Kf2R#".=eGA*KB3 %T'&!#al]6jV<Z#>Hk&6,ZEITJb3J3PfGrZ]\"538(ALcG7Q2,.HJY:gV2ju[T4a/3b(3VF]/%`84Vsf5qYn-&NG/@[e>YX:?E8oa %h9V^;8'UM3H+3H3GFWL++W*@ch3I)4U30rnhl,f+#[q_3=i='m7dn=.6N3\+o7Jt1^Ld>qF,%)#B$JBIG&cQ'.q6)(=S(@r"jWR' %D\.pkJoh)Onf;a`2*OJ@iiUY]+5)Op*hl`2G>8Ib0.:H:msQY^Ts9Hc"n"M)HCuZETi>uU60(1#V;_6kqcl,s)Bl`a4LiXrT<4"\ %+!3B_`aIIiQkJeX74=6)f_kkQ^rE[FW^-7*.QLNFUK=Mt6q]BcP9?oPf*,G&.Y&C3H_k8R<S8Y_Y3'J;R)V*@[0r_l5p53PKI69u %MKTjq?GLIC:Y``m^-'\P3k[Qamc[*H0:dFW?G%36bP\79H!bkVrUp0&<2R^CCTS#dh6+/k9A\Qu=3TWJQP2*<fmCb0D(M1$hOf#" %Z:U%(HJZPF63(sCW.m>lpO]W[QjgSpR6BGD?5JpPXLT.3Zc`C)m$n!d-TqQU@.T8%DSTg]IhjUW0$Xsl0BGj3CqLh(Pj.B5CgJ_) %PQS2iloZ*egm;_?pQVYX_)af/(-o&TL7\<Jp-gh([4\@Tfe_]Um\?5XIFJu#eu1\<G=pfWOe39t=qdWt!<ghRdRmRj>P:HG(o(.- %D?o'bbR&.71ut\o/gCYE'J"'t':?&gQjm2^mSlZ3X=j:2MT+j1F!>)f`g&!<G3*B*_;OS++dk)I1cU9;orGn":j,n"?2qI[%jL4X %r].c!ie_GYR..@,p%7@qeu8'QA\hQHn+?9ic(N(Y)H8D[4npVOaglXmMih5`'`;LEFN27dZH6;TeL/V&GsKgn]e:-9Xo"JIKF5"X %^m:<#JBsMk0`^-)G<BT0OhH<.Pb1!n^8SZI<4HV9gp*f+b(XCX;\,.,"kp1`KCO6Pe"!]arIMteN(L;Mj:@a;GVhWm;jF)Z7s4u\ %;s[EO@_jKkL(=^tY68R4FD3+Tb7]'T">L-nLd8"OB*Y?*(*K*l/lC<_=GICef8/daK<$;E!J&W.400V_lN#l^b0jfM^BNN1gUR,$ %31^A&+$$fffr<eX,E"*H9!8="H2NC5JAhP;?uj3kU=EmsBiZ;EJZ-W?@;_Z,Z"YaLqEE!I/0@Y$6U&t/7cu&#"2XR@DF%d*_1]he %64h67F@*CoR"s6rfcm`&AV1=PhO0A(NCeXfd!X$#H9A?q/I&?aX7_<eD.kVlYV2*jV4fI7Q*7VY!=<NH2Y]VPg"A9;NDZsf47N:\ %cc]Hgk"RG.":XOs1M]q1d\*3r)c&CO)"YY``(a+4:#^2,#++U)O9tA[J>"NRZJQtsf9T8oP'o*.#\;&BhH&_7Y)CaY7CDO.JQ&-B %!F5pQNkUf:Yhu0O*4-Z+i0-n"@iLq`DNBk=dIVC;]o(-Qcq!f[0)@p#*ZK,,TF9NWiqUk=:'^SsC)tbSo!)9D!NWP-eIICj.Q_$\ %euCh%NF*!KghbF;cFpY-\nko)n0phrj.6K-V*-J$T4uWPrk"k"b&?D1%@k^U&Z7AQ%Jt(R_J4b/3WKDi#JALcVj$`)plML0[%0Fo %@";F8TshQ/eFHE<)83?"#"5/ER?-tEOB:_apGYQU_)-HWGUl_$DE<[QI^En<Y3.Ao*&fH*BVWHf%#@4]_pL_j"KY`=)R*I\^c]/I %2b3D*eX+K6qJq<:)?_$`/&#:2#=P6/;[^4J^cH$k%qW@s::-)@@SQGWU8\_,p+V,m/q$iVPu!X?EYscqp:%>N6`>'[FUhkZRUF$H %c@H1sUJ5Mj\?fm^!DUmL.<r"Gk$UFBWY6=+!2+ViEi?&_3`0s\K<kt96@`ITlEU`f$T),7UC^M5]H@7;'?/i!.OmTHPEqtN<OB"U %'u@\>;m$?Q#5d>96fcPo\J_LAU(<WJ.<I+>8C<"i,\b=t(>Oj*>>33<.J1`KJF:Kk)sjUF?bLc^m)rjW4Z@)&nGSZ$aH(Pjr+bD8 %eAgA,>V:YMQ_1a#FQ*5EA\9S,_mp2fr*:BJh"KU8%*iFt#oH*!8=aC<pm\"=@fUO*B+F-;_]"qQ3qi2&fZq4q^O">iAF9GgJ]GmL %-4N]t(Wlc5:6KY7P*70OhIQ[%JKY'P,V]=07j1&7Teh5WE<uU04DG>L&%kibLGhOfIOALr8dbg/LC!@&?Y(@Z#La-5U]IiSrkea< %b6&bn@%AH]bW3<e#5FMdI:MP6:"C0R#s+K@[FI7HL_4bRKm=O"j%k]`LKc`$b2F!7i"lgS`QMo7Z6t9X"/<]dk^/;nb:^0Ycl%)m %2N7-2pu072@<Cc!8?gPGTp>B*!IQ@H,ck<so44+2U"\.2(`_-[,.87Da#(1-'FcX/-Z3T2G]"rN&U3MtiKGT9QXd(pluMGGs7FG+ %V3.\$P8-t()Xmh<aA\o\E"=/f=Qq:56h]0RY:OV_U3ehjkflmc-6dT29!J\3"Z>CLo%<,@9Cnn,A+-YpjnKB\W3tX(/"OWrC%OH5 %5qYcW=g99#'NA$LBJ$r7Z,cs39gDGBHa?:^1:mS/6VaEZ:&g+^D1,BB>;&RW+WJ;7Nsia9[ZLcdYD'2?ZFgD1E&5]_:GRa.(9b&c %[B):GSdlLbl>k[!AV2t12,>b/UD6S+XYRFC`9C5eYq-r*']Jr::W_00pW7?$a_/@kV4cNMQhigd#)T#R$fPQIS^TU#f%8%%aDO&n %<b&c[QGG_u0`t0r"us&,6H*:LM*Au-ju\mR.6oQ-e`f3+I%,Cq#Ft08LV],>D-[934Cq&ei4$!Ib0gSVY,rmDdIdPKP8+=?Dn<]% %en3qb+4d\C[!79NB."`KN)iOReKph]RBXfE[28=%nEI+><rr0W<DMuWaP3'DfNE^:S$$F1VNlm12F\WBHU)'j$KEm`mK72f%;*(C %Fbc7-7DU,)X0ZAk9gX$TX%<P$VkOoS[T:pbPc5Qr`(kID"m):kd(PRS>RgBN?ODnG\1mV9>M\Y_igV"^#eR9BN.)@ZFV,E*$B6#n %H1UjJ"^<gr'G]L[Brbg_;'F'LmKEo56KJ(lQ4:+e2atIr&88)!Xq*hN9eoS;=M.Ip%1>!ufl*[f43X-'86`P&AAeR3`)3mJD!Mue %VHian.[3d5\rT"J&eF9=]6tMGE6L6^<9#m,pk-)h4>\#\b"i@'D?8gCe(U9g7A3mGW'Mj"IKR"7]EJSd80Et`_nMB.H=HrF+Ls'h %8VFr'/('E`XT@(Ga2CMfN.S*A3V"_;5(PB;"TVAZ0rsCKTI;Q]$j&\HPZFXOrKujY(0(KhL7CrgUoUhgAu,ObKZ"[njc#?<'H>KK %o<,$Jgf?D!<?S+c2pgQq($O!e\W,BDC[\:054JWM2-,Cm*p=85.t.?d8/qHk7=%u1e%UW.aZb3^k7hSaaH(@(r+bu2#C<\f_Ysf( %EYg&2HKP12afngD5AK-ik`1^uU:b[lKDX;[h8]Q)4Q)G\.D[iDUF\/TQ'3odSmE,*CG,%]SAg?fT/POgm6/#_QjcGj3Sj#IN$6-? %KDGsrIqCsli3%d=]`5QjB$fgc/,@kF0P.Mc6890R3Q$nQT1*]('fB<H0)HgnPAMk?[/B8RkTfW,i;%n-14!i\k$=!Aq)Ru<;.TAI %\k,+iej^0D4$c,p.a@GmCrLKMqC_QCEL,6"K?l(.JL.$1?5`G:Q[*ZcZ8<8:$Ogg<%M5\:9=`JN&M1fUF0TP_%KURGXs'6-Ic=7r %#V;3Zpb)IeHL_h6=$DgX,0eb*[iR-%Bn0LA7ol4']UOI[/&kQG5qVs&A#^`'*3"<j4Ji,.aiH!$N@l500rDqde*LBI67a%t+,[A% %d?9pm,$Z\/bU-3H#?*?tMXCm,(/Vl[%i/Bl-MGMKM!=dFe*)]NK1h2V5rH-q)e3^'-'r=(5XOF'DpcUfD31^E8<*tPQk.AQN;R,U %$]jEXDQ4>mn694K6';2<3,^q\BRGD99*V6rV@)nqY7bPA"kt/XOE)-"98Zj`+?nL-r`)E'=_+,^R2&n!X>9_1UeSfc8'<"jE@*cf %"LRAb<-l?Eg0cM%$\ffei;=52:hCW)'B<X(f/(d>"te/&#`rY3'5=ME@\(2h<)Vg)6C,Te&(+$VKnb?=%p3D/7F7Wq`t@[.quD>K %YioU%?rP$?_`S%ai#8[X.Itk-+Mo`EhE2ZtAt]c,3L(a2U17mCO9YpO7QJ@BA((Ob5SPBugpko2KT8VjA;f*HbgqC-l^jO`%3a:\ %kF`r4aU!XI7s7@gojSN&QLll0m5e1]5sD/O7<&S8!ZK+j#g3>h@*JscObGin>r;qeQ0\K%=53kRL/E)&R_fOgYc\n,H?!G>'mU6+ %5CfIQ)o/tW$L]O6;Rfj[W]r$B9s1JD4b+fRT#/$'HYaBuFr;dIL,o*T*,hl97YXXk9^[e_nN5k&9A8qJ,)\-nk[)AIAV\7e&:Up% %DI+1YU=eJqk`mSdj&%eYcX0-<@M_2La^uB3*'7Ar^ti0]i:jl3q*>ak_2k,/WElS9^mHD7(l)B4Cme'^7rkMnA%TLTB?0G<RLXSJ %EF&HK\=X`9NqV8s^`9?db?.2a1OETl`6Bdbcqp-Fg8uR:CI^N#JC8P`%SC1p5ZU8>4l$dKedmUp<nYCpaZ4T);],+iWj_6F_5Km3 %2)mb\Skf0/$FP>qH@&bSG>3jfV/q_V/7h3]ONT]r2B`:\6>R'4\[#YS,TBc%),VNa6XP."7WHOd9SRlS#"'5:&i2$MPXY"T*&0rH %]/bhjXS8MYLMj7Rcp#p]9Gb4_b#E36!;p-4&Sj[SQPM!7p]fD2!cN]F88*gc8mpAh7b39T)HYE0)\'h3A\#I3KEK5SodL7T4RrS` %XZCE5nrfHO)GMhD@CTLY.$i.FORCgZ5eWq\F."DB@RT_T.6(_11[?nHo+Sa%kCt:j!Fkm#i%&!(``qL,1JTbK?OuQ-Z&.Q?0)\Kf %6;T6B$LCN?@p,R(PUm:MK;kPafti4)fUi;=N(?-YnZo)Sp>rQ-@De4Uq80dh):\H2qCR&Y+6f<jec'+Hr*@BOcqNlg\gSKlrVaj` %qR["k'L2um,g99;+8p'PPO0&(=_8NmhE";cGF^JoI#4?fB%Mij<TiU;_:j;,UpK<'/7LWQ'[\Z?K[99Q,Go/4`[:57:^F];GbB\0 %\nLbKilPY#0t._6je047(lYSM7>(m0Z;34g3?ga#hHWE[SF49UEKh+.=k8m1/3Nu/%iiP?9fs6*j\m[];LGjUS[pW^PnpSn4Lrb( %i/f%!<lDXfdm>!@*2A&(bP.A>b8pg<XO>Y49TLeH>TGVmg?AH>KKt"!Z*eer+$B>NU>H_lEp1%+;c!,=4?/6T6B?b['._\-?^:R% %/lhYQ8$"Ib9i!XR$r$AJ`rSE2A__:Y#80_/=C+.ub5d(2$$;8WgRgO#*X6a<?DHJ"4n1[?^l2Fu3X4==0bphF=C1(]C;\H3nV,$( %*2>G-85fY?V#eA,7mf$5^Ih)&\V'Vr#DC^Q0%.['E^Ko3J2*/<onAbYR^p6_2Asna)u!Z];6>$l7b4^MS^s:I_9$E,^J1jaVIQAJ %:i7(g#=ogi?t(lO1c=h$#QUpXH'ZAq1?Dkp*/]=7-$C?a9S'Cc<Me\_E7$6eLl:N+"u$6O-NdKX?6&c>aptQVkKkZGJB([U=uIYk %0;O@7ThiRZ)P`<!iEKRu">QJZY!#Rbj4:,3EQ>3U[Gm4eT%]&`DS<UrGMN%EgSH\#MLd<?-lrK\/!h]?0_j3"]fD!GAJS.]/;P/s %#=;/F;C2fB@W0O9H9n+-NE`iZgu,so&7)URb2um-?Es+-BYZ?=.s@JMfAJu5QK$!A/?iOs=#*?6%7@74/Gd@ara]AS.0&L=?QHnc %8*Zq!q==;_Pn)\Ce8S#<+S@9n.@<&fC^i*OjRdjSD.W50`X&.aKfK0l71Fhc,5m*@dG<1.Ts"0G:2MLnCg>jTbC@dPn(%4t*oGXO %rC[!l\8<bPZ:2cj`l3l"38BN4B5l<Oe_*?"N`\Q]'KQ(f)!"LcG.#`"e`@+;<heWP4HqfbU7=eY!\l"c,K+\l+@p(r$tSB@``WG[ %)EFe>=NeG;m$cs\m.DBD3#W=tQu^)eKT4l7[HX:6l]1>_4l/037pbe_fDOB%_DSMWFh]!G8.IsZ0cHh@Qb#M0Yi5E!(Zfhu\\^#X %%N2@3_])J1FF+L3'nj\3<1U<4&Gk!t[Q)p^*J_XG-EG2aoIQU><A@W?+U#Msi(?0gJVQ1kl^'%tF;#^-81d0S>>C'10O=D&ReAX< %3&rg#/LU'(K0rtB0@@bf@]-!U0_6uAQ!k<c@Yb/u\P.NdZZ9pm8-<)A31bW6?F"<:5o[l9U5U5?M`(8`Lngq+/r@VP.*XXcn0];^ %ahKqng:i/,A?VTZQTi1T3UbqES+,AA4X,?_ZT#[Bq]4H*AZ=Jl*``A%`H#UpLMR:G+4ZH,k)PMbkbe_?ITt*([g!lXj:^_WXYMcX %R/f)@0!?d#=;n=0"27KKEbtq@rAX\!:O7N-*Va&5QcAUF^e_2Kl7Z_DJbq>Q-CZH:%JXAA#u)rGZ2'cA!*Y:^cQ5eXA33N$<slu/ %s'57\64Xn(.YB4o^[rQV5h`Eo=t"`n,cusCDVuTMO-LB/9cnc!d=N,8)GR3L-_f.&7.8,*DoZ\@qG'XmRu=r`Gk,k^fTcU]/F[k7 %5Vm!dZEdjlClG09!mrlm]#Bb]#T\`/krf=!/rp,#1>-^/jt1nV=TLegOA.A)+usp]+"Z6bmLI<S5n(7rC)S9!'ZhX``&?EX+Pr94 %oij>W(uu'n(0n:$*nSiPVW`IH@)NAGU8J2R&^8+XTh:ga/XQg0YD--2IObNqitR+aUPV<US1RtR)2Ok['9`L/^p#m-6fL;ID#1Fs %i\G)N&U4GW`g?@Qg)@lmD;=p<q2JgoU$o\n"+$+3n?l9)Y0Ba)*ftWF8cm<`j.ZV;+iC8\TpQP:$Lm^*H2]esqNbI03g1Yn_@NCR %do[74qo#Q_0S><1Y8db>3/3=eMF@!U+i%L;8q[E]SVBF5baIZWA]hl=FO`9h5[0t-q$Tb#A;<q@CJ8Tn'K2]/>0>\1k,Afq`6d0b %K:0Y=)2NEl_Do!^;3Jj0WA3'`JN3Q;>"EW)F9=;6L[c!#g;1"qR,V4sj.p`AKT`Rq!EX]%5A%1KE@?adRK37;0s1h6E[G\^T>Nnq %=G.1K0gV2FeI3E1k\_ee"mU-mIEEf>'r[e%8GU.q$PWa[*$Aq;6imAS(5![HK,oMu<t"LJB[ep_o)mHuN7O*r=SFPrkn'A8Kf*#r %7@5ZPOAel*]fGth#+05C;%:19rq<QpU)1R$+Um>SZGHXZWu;Cj7&MSl,tE?jcU3[E+3CU$Lm]9+MrOCcE'9O;@6Q(Ob,L19c^<<% %`?A9`1\lB*;+QGSG3;2QM6KY4Ka+\;+[ZFY:j/X:)L#N=Ht=B<MU_\X%"j2R$.p*iO2uY>8cXFJHba1Pp,<p"ZZ2&8,iE1c(dOYn %V`Y%u/ft,3n)YerQ?.'lYciOt!dm$/](G9M[P&f_H$X13^+-aFg/Y&\dG=qk0O3#Ym[6*@K772cY<bLAH/cW5?h@X63hB.RecF0h %qQBWFL)Te/E5TA-YLXBE\0iVL[Uo23!SZfI/ok(3$GD"p$0Ee.T_F8jMjPG^%Yp`nnCi#87f+`GZc8pO_ONMpfX5KY?MIQ=a=ItU %9&`t(T[b8TCDGHj:uZaI\)Wk<R:NR?Jr97kfE?K;KW(f5q8sFQqhgCAD:(c\Yr,i1]g4II.dB;h$_C?1fGa/i.EuN+Dm!>6B-Wf' %i6.PQpc?8O]&G?_KRdkrj>$A/oar0KXJ,K>60nmU$UPO&*/KoG\;_q&#AO&ib<'<?.qGYbDaAKF#t,r<1Gm\10j&`P"VS\7=[S=H %;X@sioc/N.-csNOpc8ImOi5rs#-3k5W4_&QnbQ?_6?^Jk4=2Bkr3KcAR`X^.2kN"jTGtPn=otkcFE^^ud,)!G^aV7aNf>;lTK!+0 %A]&#&'am&@pL.bP1L$./NgqRV)T^<`Z^#2.N_N:fDQ(p5buo!:ZbV;Vj/j"ASe1P$;iK2f,ktnPp%&U+?gt/3GZbO>=%,JQO>LqF %Bn,Kuk#XY!%=E6Nn!sKWEeiQ,h$%hjFLE!,mB2Kgd,sckBK<?k=Tlk"m\c/s1=$6:!,VDLNonR%qH\?r_q*s\fEc42k3s(Dp.hE[ %c"Mf_F!s:5/@pbt0L9mpR=a.DLPhjMd9VDnYMOMMdc#=dpIVGB';+9uNfLWJ>m,7,+Ir#ND_embK3&Q1eNSN^gO31F?3CZCL*M;s %eK2$D*0`BP%GJqBUB35*lp>(3<g=iS&Kh"k^g2c"Iakn?o_(uhSHJ'ri'dn:J,/G5pa@tRrG:JE?TPn$=^&(K3%P595OJNPD&ZmT %Cb&>ldBsG%h"OqN7D6_=c0/!U;aUsM#I/lIN?5b-$5oRZK%#*^H8'CZHK14PRH9T$$Lt2?Q1*eXd[i+9j9jh/Vq(sdXjP6*;M.G( %2pR.B?3AM\>^*BpX3b'.p;_*#@LE1fd*89De\LG4)-:(%!5\s1kn,/VDi>E\.eqYi\6r:"Ft=DQ\q/XZoeM.n]@*BAEQ=+G9F.20 %m.1mO^\63\*UX-#5-L!RF`D]`XObE^kHlZXI(9ej@*&cgLa;#2nKrKH!)u))m;0TCeXGj&Ca@PkFV7.PT''K"PVr?UX#G/47^<ER %\=KCt.HUhPB5km$+l\HYQ>*]1ZUR3d*_:hI*8M=3^VGcR"4t-jaYF#QEK0^(SFsso>[c3Cj11nc>7^D25$Dk_T].E1\ab%d8Dpin %H,qr-^a[S1*>Kg4*7K4ccs,oPFA-oA!53n-cjAgYN[,(](6P<eL+HF9NrLM0^T7[AV9Xg(96dp3WrdX-(4]HO.jttl27#rZ7UGOq %2<pJgFkB);(trd#C_63W`;n8>HRGBTg'`/iJ$L_2*LUrD'tZOLPo4+>Bh4nD4LW"K`>;gG1u'#n$lG_'IYBTSTbSVg7RJ3>cl9'f %$$c?!2^Dt7h2Tf'l:E@-Vl&e$]Wq.eX6goKL8@Z/]3=hWn_)n`^>pk92Vl3q$jTpApIL@VKY:D;-@e%4amFdK\aDf\k4KN!c;RR- %@V3b,bKgF9bX\-g+<%/`kofjTm2;#99b=`M2i!kt`H!Iq@,ipeflW/uNZ5Ni%BqO^)N1D&kK2T%cGPV5C]<YT1.''A?eTIkVb55k %P,1u._,ou62aY>+TM=(edK%V5X`a!ADoFWti<A6'mg=EUs%r@5h"^-5U@tf4jG`+gotZMa4S&GXZ/c55%6))57N7IB!^u#VAQQfk %-g5m#PDf9;4Ye2a-a5P`Ec,1c*<)A03brn)UZc`M:)?)P%.V^9Pd!9"gZ_Y/f8r^W5Ze0dVMQ4#k*%(E3i/6&!<u\"8r[k%QB)/0 %97kH04I3m8FX_FN;5H5^%WD[bSOa1iW`!"bVPY];,RKl.`GOQ4@0CYrZ<?_R+AT0O(V@cMqn:1J:H\;V6uB6708jQP./T?.gDAiE %5/#l$^AFUbQV[*3qn(8a)Mk0$$Z3$EY<[?MA]s^)'2\5VnP/';f`g'n*:B9F=B8K"n"0PNX4K#.hL,4jo)%_\rpQVg+3q&lo$seI %ZBWXPIc%.Ommm-4#*]aY\-;m!*\'b*!*_e^M_-;Gfg!je04Hs>D)jD6`ufs7nj:3BLjaj<Y4&m%a3Dq6M'PGsG0'FhGlj)'$=A<T %ekq7a>0"r[C^^pV?kOEF\LcRj=c7B#HM%lnZ=R=#\=uqfLslOB,,<\%NF]rBZ5BZDKT7em97;p>'ZCdY96J%FZ'[#*NT(&T2[2t% %DLbb\;-=<I`YUn=LV^Df+Q*AS!&CM3jreN!P\LHK*cIhrclIgO*O's#gEPR:YfXZi;GIX:)B;>1@AcWu)eDGD.=/4F_*J*:e:1n0 %b7%EP4!l5lDSV`SHi`*M;HZHQS?].)i0Yq0U2g:E%62T,)BLl`,_NF(j?P\Y(B@^^AOk`hYMcW.ASL4Y5o:>=A;2io'Np_Y84<k< %%+#lo2Q."6XL&O[4i8[UEX6u]#_?D2i-2D<1Im5\X<C4UKgf(YmUg@DO'L7Epq"FP1mPU&`p'-mJU\T9#8!&6XB/7k*>1,l[_eG_ %fa'0gZd(,?<-]mN'IAaeU0(NtQUNO:,(t5pad!u9"rP?^0*kKT39#\a1JugnBok$3TF=!7$`n`uTj],G&?%.W]:sU#(7)r*q,<EK %OuQX8Jcf%&5gqu#Zlna\l!h42.`pqXXf#Pulu0*:%*fXp#DA.e_d\[Q*kiGI&;j;HIS-fJeDHD?"UZP59+`O\kX7/BAjI7N5%cIR %j3S-QS/haN\8Z-0#G2G3EBSg0FlRQ$ZGt<l/5'%_Of=5o4n+i*UC&uI+Fk55M>/gb%*$s4PYCr3.D8;eA+mJ,=GerQ@kece?+FY5 %^oT=]`I893h:t.Z^,gf"g;\KqS9ROocVI?o?iL$#p&rOH=qWB,6qu&>"0oga7aOiJa=LT36]O;3Tdk:3'=<"81i+u/Is.-\`ChQp %UFoLA`$.s0qn57QK!,I&.hMY3b@U'^+21]!ksnm[d`rPGou$b4FdI8l7Y"m6jqaE-F:-<VeKW6hRW,!5@L/tj1M1_e#=Y/kh627@ %B%hpR6jFmqg#AtAe=[$\[,B<Q(-#G%[^"%b3ds=FfU8Ok1D.kPB?B!5Dl6UpA1oi075Y6hSO9hJ`^5#+EYMHZ,=CO9CKU@"$%i^9 %"=e*q51WjC`H'Xbq,2DBe.&"$`mHolL(&P"/#\9q?r9IS-#R<7]r6OUHIdE$ZhM-l6f46fIj14.&7]DMCpDStSRC[N:WDS?:/^]i %jH.3`*6MT(<Ql>@Z<WS7.0+ip'-1Z9\6rrBU;Z^*o"kSdfAR,cB=O]=$ASaD6`f:Q3+`C4\K%\^e9oqEKlpW4jr.W2;4(iEKI<E3 %.e'l3c36]Z#8hL,@CabjGA^ghH3`TE7:"g"ECkd3l@:*j"ZPX<<eAI^^tfj#LpSWV*2QeZ$8QR*d37Iamb1LK/L3NY-lFA/%eZWO %^nNQP;]]BX2*+d'k]b0iC9o*8qh`TqZ<<?lW53`75T()24X(lFW6,PF<]q$<B-OkbkjSs;?P]0(6/"aE<QrAeC9eh.0iRdVE+>]^ %.Oon!P,EoK,>)HBdKJ7B!(rh3AXfR&e6!6d@?_"WM.Nn'kY+;U/j-gLhoM,Te+"P'`Jiu!aM@-NU`WbaI0`N]>D/(Y/2M"'i]@gp %orU#_#:k9=<>&\lOW1/@8&YYHQaL6=F([p/U]b+nXV_9:K@GG\#R,;MhQ=@&luR"koL3<j`JVI%'M_uU+6tA^VBuX!BJuY6,BDZE %N`I.\,*p:RbatEI`J2p@XN3hOJhEe'T!*jL[cB':ZK3nSK-Sjb$?JCo%^'Jh\6uRnWE@;pkEnJgpPk2dSr&YrV0$DG<n+s"2_/s; %1:DhMcP#7AjRtLam;SWXM>+NeL@]J;bnLe/76('UP6-bq(lFS&eW+Gb=@jUF-j@T*)^IA5!Wu-&/I,s&l57kd:k&Xs+Hu>`1F9k+ %,n3d8i(D+Jed#sP@V'!]=67LA9Z\OqP1?Le-B0PlUe48O3)3EK'R?1p"@2`N&NZZI5d_XLat]AZackfnPUU,uQ/e"NQ(i/PagX"6 %5+alm$7#]D,MZ'T91L,k&fH,%V3>kfP3K(4OqOn,W-KnXD4pO('gG$Z4p.@mBrAK\,sR,-qu`?]O;fr0kpH4,aUecAOjS]E5]84] %#4?BuhWS[/:QX>Xo6i$L<MM.bCld[:%)ij+/mGo@@*Ujf7D+Kt,>'sKBQtqB!C@E^YD-dK')3hDD1[I8@=K?9ak0.CM-l-#J</AS %7+a?T&o]Vd\&s7E(^Y@p^g*P!@b;>kQIAlL1%$I\9egJj?>&ehHeo;hD2G3A\[ln!,O.g*jJs$"Y3EY)T&tE\E61GoJ8E5hG?trr %$>G2*AAR"4Ba^#`0bQ$cEt3W$BhNag'&VXr+Q(<fn"B_2TSdFFiDI$1L.O47^>h?jpGgrHd09Xq?c5fV;G5UEjfOOP*DG'V)^'h1 %iC9La(C"0@K)nEd1X/d6+8JN]1T'/##i-PpX%1B-N)fWqAWr<GS:"076=(k8hOWmr"pl@#G[WnURs8-<0l$27k#s3Rg+\h"7h.&% %C11qUi)]&F#JETX!"qiIM'iesYpkP'X2nXF\d4ogjhX7:/+OTu*2hc-(d->gZI96sFZ7mZne6W,O0mNE"si+AG1e,q.?YfsEuo_K %]b.YN0G&i<H7HoHdD1B3M>3T6%X-dk4g%@F:hlHhh@&<UJO1Eu(d^]*jLjX2O_chbGCue1X91?p"YKO<0t#&2Rg$`7pjm2-B<h7T %$ro%hJ7aMDHa15J1.0oN8GGDflVS1LPql\93fgA<h:CH9_#Vp1k0r^)bD/0d&,hsH`tc5gSY^"FHS(EbCeL]Mp9Dg-4+nA1@c&h> %OWc4gLP+e&nJW,Q[IOS;4;OPZ`#^OZ_&tNEk:f%/%X#A&/TjYl>q$gOP+#&oMEqV!W,O0$hXQ??f?t_Ng!73V(XPqO1UB!:0,gJH %!q>RI]&\)b-I@?NjJ\Rk-^a'aqub^H*:O(_Ag]ojD'4(Rb;IHV(n%=MJtiLu=<-qr3ep22b@FE],n$D.bBO6`Y2N$!BHVO/eBJn; %VJ)g9Rc^VL[a["Xlk`^Qc,SVn^D:q!q!#-:*?nCM^'_41Z;(^o]s?q:Q:rA33G^Z:(8,4."`W^gQ)SiQ"nKPW\oKc<MV#orI8O8Q %)A"\"%kQiZ'B1sHkeIO-V'O$c+gMF`f1LEo8.<!Oeb5BXQk:oFK1n78`#/gdo=Y!Sn.RqJ4@K[P&Pfk;SBe:]#Npf::,\J-SmU]3 %,T$m0\PRi/YgeMhT[X]+a*T@r5.?Ekq_j5fmY+Ya2OcpV@24,Tjr1%CWsahPa#t7J4B^e,Kc,jK$Z`eoM,%9C4X:M&+?eY"bRq^H %KOfJH@e!XqXH:D`#C?rek_6sH%bPq=LSA\;ooAG@-^IBP/_/,(M\LRY1gS"]o<L\#K.#f4"8$7^Y7'KS<P3TIE*[]((V>:A!dHfu %$`#('b4L[4Z,eC'TO`kP-4F^T0sYg(ohpX#kYU5kR!9X*1C\G9U.ti@Uoe.3f!(2GiK)c9R9oG:b+Y>f`H3"%Nk^C7p5KPL^i:5m %W0#NkigD><-](J]ca\3HK;.&9W/AM_/O#ZuV!"m+.%R@P'8GpD@<5=o:P\EJE+"*%I2r'?#m)^T\0BZ>N?*"nj[^=B!O&",O+nI( %>iZht6M3h'0dAKePE$];A-/rJ[BQL)5f'J'L=R+Df.!ER5V#G,EgheR,&#%Up+<G.rP#i;dcS:PPa7j/kV*$nq7mYD2qFGcp96+% %'+!3IE0SJ'ZX299,$S-A"`UaufROS`AZi<b,oT)N@6(WBZ]T;8c:)mn#5%^f#?e#AR)VhsD%dl,k]mP`VZ@$![VSI!ZSD"W,e9^\ %jUQuK`ZU+*n`o>*O&2IqSHe>RRJ%S;70>Q6I3g\YR]]91Bqq3C'p($pP9[-s!5WBF=J@`7OF:f%f_Jo>qb!Ff;*%%Jc+t'UI)U4- %K%J[X.>5XuCl1(sHZNjbf50GbP26762fRGF2^^lkH/R3b`mtUBm5lr$@UMYi6!B`$GPgHL:."cF[:]_*kWQrpr_rSD1c#jMBY]T\ %qL['Icg7a&Q2U9_[((JYXOmd?M5';9)&n`)ES6O90L]b:$HOt'F2d<(Y:nk?M7$f3GZ`WMf08p_=(ji.9WOf9T1ap)$B^USc6Ec9 %(Hd`\jrKQ^]^0db].\QWi2Ikl@A#YhfL%9<8JY\gSnH+'H`,_QHj5FN&F^3G-V4g+(nh&*/6WOJ^`G^P?S\*"acbDGC>^UF-/hG: %7o&#%V'ItsR%&VJ%/;R1D,d7a*dg7]N[dHF#[msE/04>ITqZY3i%&?fWCi,<+SoR<'0o,!NcTmCOr"PF7hY1i_O@<Ofs<UBln^]g %']=Y$E]T:BEQKp-JO^[lmpoq\/9*@'R'\FFJ-[M/A9$Ne,1loiioH)bD'sRZVY`$lE*dAtQ2&cr2K!"-#(ame[A6G\kRE58_GD9E %gdP+>+t2X?E2.(I;TjZSX;u[c%+Q7YVnfO>30.tL22+^HWteM^#)V[,HZK0U5nqBpqt6=G$a/^re$]?!Q'%ULXGd*f%(9/mh='(G %6*&2&9r`(P1/>W,e;@I<M<4Wbk8JSaQnf!l@:gk[de]DL7e7'6>s=AY*)j'i2MlraG$o9u=u83l>E`tIa]SmtAIMM1@k,f7#(YYV %iB#?9-f2pH^+ga;)r:fS`Z-aK!0#m(YDMHM%YH#8I11!8#V,uGX@+ujE&HQ0?TFc@[,1D50+ncAVsK&qQ-%WbS)*bVSXBbqU`H<L %68f<6"uJ(%5YX!oT`M>5Ksj5:pfLA<,Z?/\:tF45"Ac]%h(O35*<lh(R&rjm&%o)ir6<GE9Ai+F_Q&Z<s#Vh@c:\f1^-OQ?.@21, %H.[Z!55+f,C"fNh_4\0gJaj5^V3jeud>Au5'=?O'TV6o(+7okha+!jB`@L$%"V5GE61A<'-?"A"ZT#.e2E3!kdB)54ZI7%g:g(FT %`Af87jN8$OT0KP+@!lAA<EcD9[BP2`C_b`?#Br(_8XFDDS[,A_4[flMJi?S1SKrrT!6lp&6Q6"A?pmW*/\B*^at8:8[5LG8jHR7i %+C1]M]9oq5iD1`g"&qr"+9B1<12A)EAm7U/&7$r(2'dBR>!r@^!cj9HO=lV,IA(Gtn$o\gpT:_:ZP!B+(koiJ@n%qR11[b6=lr@5 %[+pS$_$5]K^aPk:%+%;POY@92JLI&2(LI0!Oh[A<WgH*]OOe*@J!=a1Lc=re<<!5])="=!FD^P&E:J^PfE[/U+EmjDFg?Se``X/[ %"Lf$1&"FMN>f$phSk^*W5>hkV2sGu/1._!B:_,srI)hdIp,1jC%@rD2P>DdDqI9$cNsppr2C1`1nIg[B#H+($,f[rT_5LW0R7"`7 %_B:'u(82@%d0f[l(a`LUf^[m=rh_p*hg@ndN@%h5]SJsRj%DSu1!l#:$Ep,mjJ<gL8<2(.N8).^V:qUtLdEjo!Oq##!JV^=+MqPQ %QiTQtbkNHt9*O)V+mh!OS<4<0JX$YL@,UoKmDlFARM-Ys8IuDQ1g*MpQitjOf$q<uW/#KDTAGVK:'(=7-`2G;-B;6Eln0Bi+k[EY %#AaTGNA3fQHsf*/dQ5W-)A#A7<O6`,C5diHB)lt[;BQ!D_D"(d]gi>F95?-]<u=<T5gf1Fh$t87_K<[hn;6W"1%"\JHdXrG')m_N %R53Y"_J65M*[O?@fma..7V@t)HhJ-W5_?!NF:V^@r"fH+Ju0Si"P+A@fCN6?XJ;)A0Ua@-L4fg6`l6.`7qSt56ptS)0P?%WgqVHg %Z$5cugW?&MnZDj="B/a9!j8*sN4Z>/49S`q&BOF5`#hF*QjB3(#[bAu7b4t58OUo+63OM`OH6dT(G!XF@YI%N.>OTF]]e=g7H6:D %L0X3r-B/@O?%UW99P9<RL:9!SaDVjtJHiMCk,9]&UkH5q"T2.*E8mXSW#tO5$nT5F-I"DuWtse6EgO,J7Fr`P,]5#L;,'&B\SRFs %V`BhBib%]^!/-0HP]-*91P0rrW22gsWbJ2i!'Z#92?9QX7J)hVMm-!-c6IpZ'Ome&lpK%p+l)S>bT31hGprXYPN<@Jbk_F%(\T#j %6R.8;_TgI-KEH+?XSo7]^'-8]`B)p#F*rnS>cgm:fsNQG"aics/1aZO:cf9WBK=Eg17n)1L5'ZF_._lPnIGLq!n$Km'uY>EFF]H^ %L/1ulrKOYe4$NQW9kc-UTVt(/!#i^u9U^e%3G,+>!NWG&[AmnU3\^ZOSnR\57N`_0.Ycdn-n>SK(s1l+_+)(MiU%*>09A:kd3UN) %2=6Hjd5TPXdc%H7MG=mOOWtnZCB.Fga,H\"5d3M+*%BC9oG>Le@TdWJ?'r/lJs,X&m$'RO_];QIn`)TS3KV0KU6b2,fGF3HHSVoM %E>q1T?)5P;Yd6/7SHQ0;!:If67BQC#!?+8lB@(1k@r\T+@e?6OG#iqoI;OGto=:J@:(Wf/o`>-&SkIX+3NPmlJch-h5iIFT=&sp] %7uh`nclj><.=F_kO+*+"Zp:,4+HE8L`/8:3EBX+hKu(EIfKTM>VjRStr+%f''1+NIM1RWFg,d%0XYg4X&N8K_mI=i]Wdlg.IAYqL %]4?=[Yl()TI,o^n-mWI4HEb0EZ6#^kKY;K%:GND+ZR`WaZ%m<Z^fUc[%q#bNX(0'W*F_`tm(N2!-0Y,6`UtW&(2$/FJL-0J35u=& %_k7_'X'e-lP2@b_6l78>G#n$o!SWqV"/hY*>S&7&<K`i&c<>m)96LHi^iXQ44lt65n)[/oS-*(hg5a+:4^\KaReMHpA+92RY=bRb %^fM.@.V'j<i1&R!&3_jfjiS8I?g&R4?Eo\7Z;i\K$BUT2$%]YB._]RE@k>QSC^2$n9=fsR1a8=Bc&[:mV)O,(nDqI+M'^qoJMBDH %K<hZ=H^MT\KEt'^SE2e1OC[NQT51A0-Bs!4A-oe*Tu+eAc2!jZGA!h_f/KbFSXf\dU-FVc(B+PX/Ek6]&2FH.KDWh2q?<B5aNk#e %;YQo:.VH7'eH51,U5?6MH8$duZH$GF<n'GU+='5&FT>+/?t%tg7ifIoAK@<A:6$h0E#2QM>iscf&CP]$q2R^F:ma$\+g@sI"GpS] %YsZCh!gc>kJqSfbEu=\U3R"/Gh][u@"#"t4Hc(a<%.9d/21m;8b^pQ:2mo@o([DgcW6CJ=+B4lDeH,V7TL]@t<WuLOJYs4-_c*up %#USkGMdr(`&/h4W)h\j//ZFG#8660E77J_P5&&F)k`uLh`BFORj"RJJKP8WO$a>V%^QC#I&d#[;&Xl)P<qm5HEtulh?t77:f;'8^ %cu:'N5(Us4$G21Y-Pqh=@Gc]bMD7LNHaR(?mSs`o`l/NV>6@ukDN\DMEHG&l/V)B51(*A']("4*Guu@%=agZXYJE=f\gEsVV67Y< %K@kag$K@c^7k'@D&g4"/7j/`O-tMmAOMXSgiJJKt`fi<$)6G'$`Sc0U#1/QdU!r3q%g9o#&/0fFj)X'Eei)<s^e*_IdLFo]6llSh %e0Buu%6u?i!5@_%d%JT$06$7*E<_)V4]])';`L@lltS]F*LMX-ZqGKdOBOmM:f&_[3ILr3b<[8<#1P!(O<4!r9<]\$aA"iK4f=Rl %#]-@4ku)L/&>c0G^)j/1\FQa',s[*NcU:mNhhWb47^s1s>CedC7[Jl!UMNh^gKL9#.cOE91M&-@N?<er=&Z:^@K`$OL5Sc^h)ONf %<(FUt<,+rdV:eqH1F$fK#]C*QJk.ofL&c0$#"!<(Hc1\5&UFf8@3Nks&8JaM_0d#Tl\^5G+p<utE&caj<CM-"i6+UT%1THF=>odQ %\Rj=TdSKu_oc=N;'%1KS63%2?P#?pAi]q"9$d)'[6PZi9!Qii+$B+7J#b.V4rP7sa+n_-*+DK>WCF@"5b"As\aO-?Y?NX5McklcO %Vo;fs/"mu:lm"2^UU)D+OQ*ci^)1a=7lF20g*,N!bmG/>8Cpf^frc;$1&%2kMI>Kpoh6J<?3h:^0KSQ=^64)<Gj$NJ61DMu5T<b^ %E(@/X(^u/77!V',*8'QHH@a%%4pQ%PbUa,g8W&:K6uXT,)5!/cGM*))9=-m%>NN"f39$$/7<9P9hS"k7LcEbY2O>UIBg3kj%\VI6 %kDdgA,bZpnh:M-FN7g7'j<Iq2l7u.Ml6.q=1jFnR#97R,N[=crSPsH8DP0[4UQ\e$KE?p3K[_kY;``'Cd$2J;)N[B]g7Ir&__YK6 %;d)ar1<c/E3u"Rk4(Y(.<]H;V+YI"2#)87UY9b>(G];"W8d,AI!sg/GW=A`5#W000R>jcP@H4-Hm373CK8;/aRN8Y2P,-b31%%N8 %q5`4QQuS?R-t@]8hDrucK.hcP#)o7.25=j>J4g</]/7N,i:hd*").lp\86\YJKBU9$s^+=g=9@j<@fLbVcQ^%m@`2SpIu>+"rh,c %6pWP*Vm)8K-d57J:uFNfC)%tu<1i^h1(0"+jghNRnOU_7)n&0<3.T@KBJi>s%O7r!3to7:&J'@Fh(kB.`O\auIh8'BW;`H9OT/Aa %4IH[T'F%GL2!#sX\)Muj_FtZZVsIjOSKD`88:(=[E#QT2Xt!*[,6-'T"@=('r!+t5_P,V'3)NEjC5#!p%A9XA&/k6So`3ot,CdiQ %7-SD3KP.fN1%_p\JUu%g+mX41*_;5jd7C:rS<W+U3`FN<$&a5W?&8DRp]@S6N>\_-Mk6ukR0K!'W)Q4-AI0Z.D*t(@@-paW`XKY< %.?bqc!@l4rXpun"$D:(77K^F7p,8>V`hS_%=Ya\#_OE5q"D!rL<'b$0H#56I?^)(/M,f?iK?HnWZNIcN0A>C^9Yh'.?UQ<-p,"o( %4QHc6\.<!2=\hUig]q5f,RWic'dt"'=Q^5#$Y`4I(Q#5@6O-.I(c]n_lFMl;nYrLZ0V-qE]t3h9XrS3H9n!CNnH?seC2)BAiHETk %QqK5HL?p+SQX%.G(WiV+"3E0(8eF-u\K%>=jDe"G=UY:1&6_A:J<5NdJDA(f$IAeeAJY@PK4;+F4Z<HZ&,I&AA\j)DB*&JSf)gHZ %oCX1RDj$"mmqcu^`tqlmJ0AJC2Mn)O%H<Z_Pc5S<obAMFE)r^^*J?CUF>sh0((?*H:_p^]5pZWA""s\#7Jh]TTGW5I6=roG<<LO@ %A+j;@]VpM"k%HL!ER<=2,$tJW9ndR_R$gEk<T&5$iR8Osl0tu'Z&j%RJPaael>"+4A:pd+(s,9<6D>'E#"[eZW6Z0g!@q--/cp]( %Qn&Vh5rNrf#A97\4hu<f99A7OJG](K#:eO@n:63;M3KR,Fp6Zh?iU7FKBSNFXM5-C!!3LaBHFXK7'd'Q":,30L13mg0W^m!=:Gjs %a:$/+-Zi+`+^Nl2KYf(T=mVdc#3cmg)#Z_^WsL,L,2j_BL1G3NX0Lkp[LpL:b>Wl(F?I;RdgE<5A=`p5=2=7a**3j]%]'5SM:&cI %F64/JH:JH$m012&)"#/i6<sfY.m$h?n;0C@Ag9%\AQ)%3AeZ30bQ&HX'WqK2%bq%,V+`_P/S805KJDg!R&(\R=ZF2;.*V096@#Hr %,Ut:n4L#"RKJcNq"IHe&".`"SfF*=upse%&mm'!P`!C4Hq3KAY0UOfU%UBY@"dq13;B@2;a-.'Q/*&J0e?K:W4MY0aW">R3S-f=b %J_NE]3of4[Q%')A!dMo;Hqaj[BZ0oO,mtrB+aK_J5%e9k;au-uYj(+o6OH5mRfM7Q>rDnM(CVr^[hoEmnFcJdY:39V(eUq2XVgOF %!U1U2fp.GT,UH3d8:d`g(B0\gA/0WEM'5k9QPi>++B+7ZNAr)ZbnRNO_GY5@6B$Qr^h&@Ub(+ua>62WU)D3/6A>fWE@0'"&3HgEf %=hotDgeEpd9M*H5;'Q.-'jCo&WbC:t/I;XJ,r@FYQ1.Y6X>"o;i%bq!8-"%oUH8hXb.sEbb.)mW?VtX,(`_ZmV9ZFMLV'O*c4J56 %D4U6f`u@L1pCa,]N$S$h$V>?\7W[p9QA")`<^J*BDGJW;&TZf`&\rH5?fYF5U'Zo%&n&sbZe0;_$,SuI*C8t7?3Uu4(MLStq+[dk %8U0o*m%c0gjkrRbOXMVPBP'3YGG@,Dig=]8fWYeHTY"EOdQj6=Mk,hKV^RX(7imj</gi9LRB\H%(a0:tUKFK.!qPN+d#5a)&FA@I %MQ]0N*%Q.j0^s+S&M"]J\B0Ucc\NCs$A]V]1HG!M3.s7Idt236:'`=>Yb*mG=94.L]-rVkc9s#35['0MiYY'2'CZdq<[o./o)-i? %lC+64W!C.OT9Q,mohgAJ)C?O<f*89/IQG-p7@hYl$7?&\L17t>_bA%uMs)YW(=#IGJUe4>',Xaq<<Q_A;Bm#Ec)7XtJ-n=t!5M:u %K-8,"T#`Q6cq#[!FiCi@3<UG1M<8$(UC4(jUsI[G+34RN-H8HeKa;@<!SgT"E%)s>!95hZk)%1)Llh/K?B[J9PRTO?#f[?1bApJ? %,KlhE/d)M2]QNiBY\'oWJqF+R`WVF.kkk9??HfX864%'5.1$MOED@_OSCALZ.#Rs/i+ZT&Kb]##$qE'<@5H;lVTPot/l:paJWd,V %9XmS&R;_WbrM5+0V\,+:H/Z>b`Kc6:15Q&9CX]'X!>c-C`fTb>+#k1P)0/8N$9eJ,&Dq,p&5V@`6_-M4)+jtfL=#Ob^_(u[(8Dbi %-9Aej;h,N,=Ni8>liX]Y6&%)E@:]<JlHI0fWcBa1a=KV'RG(IqaDrD8&o/;;SI4=n<0g*/@4uf6P/03jAr^]T_'p-E&K;&"E><&* %da8:G8I:)FVih''im.rNKiN.7P^S+n./;BK@']:;r;s'ce,iH@1K,u`d0KSkc>d"-m&1-dn<l?R0:G]4PiDa4&1<o#`eabL_B;?] %Z)a9\aAq@6j!<d+LDo^g7O@_XX*I;[M\KS;^u\]^q*m=0/s`(%3Y@Q;mNn5\RhS6HA=XlU,#Jc:PR7m)%Xq?:1jqP_8<6hAP);4U %5"&BW_FXa**,%J?#WBt*o+%N?;aM\*`lKtLS0D(4cLZQb1,T\BrYi:Y;PCf^7@o8I=[BQ;\kr!7V36p_G0b^Y,\6TTA9UUm,n#97 %dIRamD0S=!JYXc?DD%nrj?/$f_;*qGK#]%P$W%2I=9dBhZp4`6eDjan[g^VQ=h.Oe?.RKe$+;kG2F4\co;=9d?*5'f^pRu/ophAn %'0PP"I1,X7$Wg#634gA](I*S^#H%tnes7_+;l*0@].&eu1m5Fh0OMbGP13GkX,0f;!c=X?QsLAVm>1*50BJo^no7nQW)_LWDgIRH %Me@/95<It/g[_B8>:7S8k?.[IA]VEAB]6`=%\?<+7R\gN+<)lRarVWn<i;W,!sOt"b!3rbjd[F4YiZN!Xe:6XPK+H7ki3p3d>WZR %bU2hEA]6;kYEFhF3b2)]7O%L*L>X3/Q1H16IFD+&kQR9T0X,'N!fmCN-n#tA\4k:'0o<4fEq6/-$!e^F*RYiU0;0o[PbpiscH$B@ %%\--A7EJL/N]#fU!V<'u.L84X<-7LoNl3(p%gR8VGB9]iXOA"[bK/&1`/&!oHdRZQ^(tQ3ZFim,827HpSpl30$\j$o=eIbhbWop* %"H8pmi.H*:`Br&bL^Jq*^?d>2)M:J7"N$;GJ'+7KMM]Mk$%-\3G(VFR*5gb]0-biO&eN2X[WGJ\4+q<uc&U'biS*Cq^f'5NHSo=i %$dj#LZ")l*p+;Q?XE)45:3KEF==J*!!*15TT-JR*!Kjm*bfQ'D7$@ZY^J2oaW+qJBD(ERYTK>,-'`0Nq8qC+fa^#Qn2pJn\q[n=? %=Y/u(+N_$Y1D0?'5l)D'c6cNM5UEhtgVU7I#pf2*-4Q#1@V'.d(l1aR^C$'O@%=p#WoY@5Z:PBai]qY,AL!BCJ5?pV,&;SHr.8I9 %rRb18G[i!;%VRl9'o.jX_D[BrV&C13G=g#+RD>`d&/G^nop*7rC^@mO%F>F/9LA4gD(d`]^u5<#Yn=;h(tFF(J>#8:pbD)8"Q(nY %?nqjUM3f(Y9%2eqXL8fV5/]O;,Z<4kJ\2.LE?L43ZpPc_M70:^Hr7+rTIspIQ^XZn?lfXW&m316$%2OtPJC<r<C9WJ=qDj_5pX:g %.,nTUoM15`TW;Wrm03i!^8?DgA)mT=p>3HUWFXa&I_Pm?+V#n+JNXNo8-XYg#Qg_[@7UGf1789W]mi/:rN.s-*\n;=l#-1Tp-%Rq %/%'0EY$oj!InR4$4$O:palCY5l$@=\4E'^AoJnq^k-D*CIo<kD;H%jR#,]0WJ^9!hQlW3-RO-0iK.>2L/7.A!%iE.3O!<+@PhHuW %'L.M38pW@O89(@pZiTW]cpF9gi4aX5[NadIaLOs*alr728>qT#GFp0s/b6Ru-<;7IM?BNTL9LmmAd>&>m69u>2q4A=E%n4"hSm'Z %+Y"+"Tif,N/n9Yg25UkB)aV[REl&JX?HWW9A=.t490R$^+Y1G^!+b^8+PC6!>i<u;%]F!dCI\Ba?si\@oEAt6Gn3cP.o)#c#)qn6 %FnAK3oLMkG^ks8aCVZmi"@140//o]3O?EjQW0iK0KKb57'u=*%HZCN38T`4G"p5^!]F1)FY/-7Fkh%Hm/@/u082u0h&2DO"8Uh*O %k!lj@$Ytc2bBY8q!KEZd+!U2=M>Y8O8J%'4bYPWr/4\^h>u/C*dr_!kCCq7#/0V?$QRZDEC,CARiqjX9*CEOhgUAHS:(h*Q?]#U" %9\eah7?C2Q;H0=.<^[:;AB\A_$<<5LY0c35"(T+q"j.R1,DrG_j=iS139_/LD^.[m*:f7c#ElX>gs+uu#<neK&dB*g#7ODka&p!0 %Cbd?$iE`2)*M%?9C\S#tN!RBlmu_K^O<^8:!VR1nU`V7qZ$Ta<!JbEG,)'Qofdl3O&<UrXi=+(N7Dlmd"U;1ZJNP#6-Kf$OSDW@b %aVG_^,rE1i.4%:R.Zd5m8$XF)!lmUi:WVWSLa^kG5eL)"@.s=]oE0#4=B1U$7Ii`C^1S=2.O-#?Gi:+0'1><Kje6N_20psqPUeju %*$0_l.H'2#!?,H2#\1p'ku`U$O"_q4!2I$TjBA-W`Bp(7'L@MN'=l0tlp9B9=?Y(>+M*Ou&jcYq`5a$Gb`W>&Ak4DLX+<YM%>ZnR %";"FR+pL_6BJLsPPB^J41(QXd"sROhjGb@p'[)8%#]jTg!1:WUM6.hcEWRLteBHhZL)a>);.a(paGkG#V_8k8eN<t3D*9LX?ijR8 %&[?i._0%"n%8>1)J]HkSM+E?l9Ma.NTXd+=2mdf1+L9E=_ulXKGI*ZU8:E><S45:LV.X6LE3,V'PrQ_>Z8fa#<*lt'"<!!ZW"(1' %OXgPj[k0&VJZR8ZZ<+mrJK&Q"1UR7";fiAHV>qHKU"5jW&-<0-Q7Es-6raWcCSf$Qi)*?:,\#u@Cd/7XJD<mk:K>%3ohOl'$TPBF %i=J/"5G;-l)%HO8Q@`.n"H%dRAG]#[+d>m%!b!^8&PE?E/IOP`GccN68CFQ+W/t[q6F;E$30O2qAirRQX/$7j_kdbjU#*7=kT@uA %^ireG$$/-NO?H+@E)%"_OqaFECJ1on+M+/H\MtZT=DZU>0-a.R^t+)?!N@M83Zr8J:2#=I5<IqT+`dI5gJZl.Td,4G"to.LERZ3F %%1N0NJrZueB>]o=H1Yq#^b?^/Z6osmMpeLXT?7@GaA=E-GX3O&4UC5E+j%c0q@QCH5"V/e_;PYbMDh9Y)e=/<.$:7AMUZ^gVkH4c %#UnjD%dgg*W.<\lVq<5!2N#7W4(@U2eN)#jo;3+M9TSqN%J^d:aCC6#AcY=)K9[b9,FnN>6(fbRJT].*lq*6i2\f*f+E1F%Eh5:@ %`9!Zj^rFk26hi9T(pL8aoFd<Y,.%q0P4M1[:11EE7q'jm#9SkD['h)LarDO?-BTlapc37<>S#uP)Fjjr'jS)pJLfmq@eiCFFKR9U %#=*sQc6NT'U\G#l&6!KmMZ>XMfo?oT7oiZZ09`_?!]dgLA-kZ(og6YIZQ[G@GnL6b;q4h(k6S(r3C'?\_8*aepp;bY[TfWMZ".MT %^h?%c37\eL'6"@:*`j]BL'2E5^4^b,-H:HWi,$3C'l7Z@dK/#d6M;K5d<0T8PYV<J94E;S#<!LcjbH$iY)^l5`RX0M&Nh8Lkb<UW %.F4>rL10)W3tKJ9(:>'W8_ZX$P@K0/*O`+<#B5iMRB/T->IuFd@_WsGL[iA(3j:\LD*#1kiTFSLP)sb[OW6&8#W5,GrJ<q.,*;$` %9Jf+KpF]Oo,;LCWmKsil+-9/fab_&eTO?E^mcp8J\MTu/$'2+c1c7;?A4NXJ+BC!+an:HX9HPEKBW3dq&<nZ.eTJJSAFpd;(SiX0 %be'650_U,$]=X+.bAKlH$T<^N1cb&.E>jU=WRIFMQORI!"7W-2`Zlo$L`qa\6ZR?U\CF<r*`+>]&?Wb.E-V".(1r_?S"aAu*&WV9 %gJDC59DO,7LS:d\ORLi]Q37^%6MNm)'S;6Rd1L8)nJ;j+37p<1Z>=BPUJ;4F5XpqSOsLbH&p#dc`+9bu-=VfZ,_cs2"!so9;Dqh; %!a3\:E\*j2&gU?rdV+":7KnR1[[c!C5uF#XW?%H<`a3.OHU('c/0tlQMoT?X7j?eT5UX:%3E?j,!WXhoV8V&/ZXbLN.%leBNd39K %PUo.:6!1h:W?#ql;pp[=^c?lS62OrF?O$]7KBE6;f8u_#+mGI)ktihY2`WSm<Q>aZ<C%/t#_A<B57`\@@77+c8@hq6e28fR0$ght %"E;gK32K9#l'Yf/Jo];(P]b-G;%!-9kZ+d^jDmO.$l-5(lO7-Th?ZdV!$;D^%u1]*EF8k&%#HBs*s3jFBR`n(5mY>OFTaMM8MFsE %9SQ4c@W]e-0FTBp6BF8oj9qI^7Li'b^>_C1a=4rQCEV>.#+Lbt9hm\LO\\"D>`\b>pcQF:I%Q6tnEsgVqSgF)@O`"tj@PdR,`Mtn %"=!BSGV%(]EDjAlaJ8D63u_-AT6M1uPOKI]=C-Q;.WnXcl2b"!0Ppm=9$!B[7*4^\,-EPodNe=9M$:jYPu[H.bg8%LW<2,.e:9=^ %5VriG\IKqc.'as9H4hk>7%Z'!*eu"NFs*e7'oifK:_5>.N^W:KO@IXYA>6WgP,q=6_Fl+aLBh[.-s()OP)uES)I4$Zi06h,'4auZ %%\GI'Wb:=2fMj=<;^pc.m6q>BL(GoRB=<]>58B#P7hHJ<]?\b3(^A@*Jjr94gPUP-LKr*b4"qPr*AXa=C*#W:;sLGU*g8-T.73q_ %bbm<b8N$qnAdOh^Jh^me=,_#[%!1GGIF*i@fDu?[<#rMYaXI<4G[\7FPYWO>Q^on,EW\qU`QEIjr;h&S"-88:!+dkcbX",9`-?\\ %8ui:c4LpKUSH9u205ML,NAfjj8(cNnURkrHkfSVU26K;L5uDM@)I^P-d*)7Q0)iXurWA;/-7&CGR;?nQ8'"er3'1pW2`Po3Ld$B^ %+qhOA#r@kajU<\,aWYKY/Op`eF[>f*n1kf^NUS]`'F0G5!_eB#_'pr)^h>Ha9U@kh"$s'lNIhh!I+THs`NJE\QkF'>a?i/>Yt-2p %%q5rDeScCA15"G-_LMgnecTG3pBcV/F[V:*92JhkC<_(5`X]s98@6=.>X9\QOM/`mX7i>6;;@NoN]%[^+ekio/d@6-GbIRp6>*": %j0D!+$W-LN)tIN.pGL$Vk-A#giK<-S-")]aTc!cF4+YoHKrP2bfPqI(?Yd`AZK=+b,QcsA&HN%e-">`?[J;),ThGHSXBV>(R1/8O %X"?;979WA`BGLZD/_Fp%@#5%+D+^c$(dSko*,2pVY4W07F7QdB\-4GF.9lBQZ>a7Y2kato#o3Z9J4`bu()D-Nca0#j=Pgd0_+HsL %3N*2lFEhfC]&F&4G[OJe#l?JGD>X(S&dB?V'0Khr$i)f!-mfaD;Zg/T/Ibg=f.%Xe_7$"foh94^%4L/)LcdC'ltCDhJOP$:!Z\QV %eoMGg!ccF,G+D>e5VrV6ctDQa,SCAjT^*C*Xp*($)OSK-"X&*oJS1&XQ9*r=^lSf:21>jSNSsA8/(nItL"dZDj1pn7a68bI_M3mo %D*&m8E3]h+)S44',f9VXCRW1l,0gN8<'rAp#k8[N9FR_@L(*H^ES<'VdL[BI,Vq^86U<if+n?J>_3(ZpN'OZtAl`<A^_D^0Ctls? %Jh/3H:jdh2CQgeMac=JFP%ah@LM]T568FgIGWD/^/.(+Icn,m*"'soT97mjS>fJB"-;2l0e$@V;BJXNf<HDXmA@/(DdHrTkN<TF1 %<&dX:_^V77-O8"K#Fo08_(P-(JHhIGla$1!O!qOt>qu4Z>aC#eb/>PKOAmcN0's?pD&B'R1RY`hO<GI4$l'qr\e#ucS-o<kJ8cLt %\J-3I<s=@lKA4un\#HDq@)7Um[QN0*0LZ6MZcK05o&W;*oq&uc?Z%9K3IsQkAK2NUIu5G%CY>S04G]ZMlN:pMYV-?34rtqq9<pRo %C/SVc5DFXS8U\+aL]Sk3_*J<ZHJei>cC&-t2,FYu&!dRU1XTV>]0PD<"#dYB`b)/f+&L<aPhlQ=],Y6k&b6rbi7K[&CcT3EASkS7 %=p%+'Pe@<nkA`=^(ht7'@T$3=WMtheMCO]+L.l\L`_B.Z4t^P?6o=-BGQ\k!7AKMm`AH(11km.GppsE5H![m3"n`7*6\uiaU`uF= %j.49:C[1DEOP#->UZeXAT>'8'!`)D,Wi-oL3d.F,^Bn2sFL:cX1LMep+>Ga:XiH!pnLF7*qpEXm$,F!&76n?G.`\K<J9\ILrc`=R %U01"_jg,J9PN1j7/?ls(o5][:I9bd4]Ki7VdN&=t0^JfF:">C\3uEkM;CInNK.&^O%;nYUj?Od1]d"`]WZ+gr38*G27)jt$0bQ%m %U5kIPQ9%9e>!h!E>Y(!X:?EL)i(UgE)(6L4ObEkf0%K8nWYV;sQ-a/cq1&l9"r8C*"E-8tV\7']3/iWp$c4ua)$iWfm3+T.cX>=Z %V=!rF>`Sp=-+"tO)Q889XtAC9_m4LiBL+%;E%jTg@9]ld%O'.8Y(8R^i,h*?88'l?2Nbo(Q2B-Q;"c[iQO-((JB%YH!pd]_e2F)P %>N2h4HRT"cF6Xq0IKpie(^`Sa:i-OO"Sb!HOlHP"SHq2g$8^VGPU`[@>)+X7Jb=h^j0>2:3/p7`/Wh/;N_I5:$\P3H*Ce<_6X;R0 %nS9WpA'["R&];JJ\5nb$/A1X$7#oGn6MJ3Io3ii-<9fc_qG7E^##TVg^]l#5mq)qd(TrN*XHj>@(5/oR;E[cd^N^5`U//'=&K0rm %L`tG=o!6C-UCluMCehn.<NpbW*K#cq;\Vl]nBi.f@qMu*TgM+k7/V2Y]qK8Q6%%#-d$`g)VZ?cG]/H;^,T)tmiPY/&,+GZDCC]Nk %>mK;D"-^V2d:lP;oH]bA@Xur\Rro]LU]QU81AP+aKo:T,F2QZ<CbFE)Qm/)T*pHp+#r4k+H&T;Q$B/@(A%R:dWQG2c/s76L[^gs^ %.<6c,c*7_6g.(R!-K6+T^_$8i>t]]<*6DuNMTG!r`t$TNj:`+jVG=Y#AX]-KJV>e7ka<:*NV<7"S-:TMQ]e[;T/H]&qH_l@OE)\9 %h3d,.EYsiDBnKrCJRE"&Bg;\)a\i6SZU6`_5$a+X)?fJ=E7b]@S<IqJn0f&$LsdijHL>jm3CY3T<QUD/IN;flE"J]KE+k+V,+1PJ %lqD'75cnn+oB8S5X,sk3Ya?We%iFsQYaC#.6.c4+'.b:3Jf#fQ[Ku#IBFZ<r+\bXg?uN@tS1S-d%B-e6c,#b#eR29m)@">tS5tI6 %#X&L71Bk;u_fk:>(qTp,L;sB2M$h@Bi(Mo,f<0bu>f(/>U*7O'[1TKBY8%P*k)+8rBr*Gi+[sXa#'F%Q(Q(WC9?N_;?N<cI@+2-2 %k6g!DL+2gs_kBsllt[or.]eQO4O[il![-1)L_paTNnHW?0hbM4l[`=ar!eK'Cmg!_X[J>2"TT1r-s[+Cir*MJ>F]/@agG_Jr@CSo %!D@)'\Q!b`7V"6$&17-s67.h`b131=)5J<9jB7AUpK\7XNmcV^:J2nq;:Heac!cMR3@h(-FZ)5qde0F.TOh&MH]!R=!s"#W>a*&K %--k/Koh,%u0Ii6lB\P)$9B)rdE:m/bQF7:SVl?QQ63=t+.@qAX@M(qh'FQieQ_C0/1/EdV>&M.'Va_g)rY1N28Nn1/"%Q*j-r>h( %B0eGV@#kC*Vlc![f>*#Z=b1+STQ+:!OCT'(\A0m&LuoC#Cf8X.$."Q`2+J3AT\"oriXiNm'?T_LHk(96DZl="#X"\4L1Z=c*l9A1 %-++d:72uWCVQa;t>bS7>OD?]d;6aUH-]ejH#Ct96]"D\&CRN/k)%,lKB^%4N'P\I/pk5oj9uWBnF;.6/J0Dc?Qp2g)#g($M5%>VW %$6sg'+U)=I(gNt<0cl#h6dgo)!"R`e3fXNM.,s]m[`sLEoDtVW]U53_ZXUmB*)*TrWdk^r$#OP-UNKj<JVU!mD][(<+QYU_=r5bD %1mO0!!$l#J7U<%@Ur%-b5`!i"a.NR<hM%'>A7:WPfH!Y*(;a;])(pqc8f@bD=+W..1,eAs!S)h!l@B`@(VjkGHCD9s]eDI##N(Tm %mL#-M&QjuQmW7&@9I$2A@#O`t2jUEl_ZVi*96:5/:IY_I+gLu0o.g\H91c]8<`?rK&1Y5:L?)uV)&>j("(Ua*Ru\+l#H]-^k8/)H %.Dg#H)Z%Y[0fKZkJLbP/#QfX"%Ln3c<@gFqN6c!EI3S6E"eRM?KG=e'a-],Tb8>RJOAp3=!WZ4c=r_cf/>#jb,P6Je$gVh"Y%[3) %#V9@+!N^Hlb,,tuc<q9qb=suAb%35*(?9?G=VfnKaNa9.B!M\^)+kqmGMmK.'O<YRJ:PGon(:NgJAOiC1e!t#1^flSj@??_`+,I\ %EOnnjF#`A"KU*,"=[B\SMYf<r'2F5t&5X<Jf,9eUGR;p:o/pK[Vju2p;6$kH2-/sp;,.RB@$'Ie%n#7o>ThiY),Ek^SmYjB:sL9( %raGN)?nHu!A9aU]/oXc4L(bU23$9'e"Hn4#K7hAZ)5k8;V:_"l"H:/g^Y#U'(lWuU7oooq#r>O9%Y13=+T7Z.\WH=mW![TpiA#R\ %0msm;]Qmc#:r0\P\<8=PH\&O\_b`-Gob^'#"B&PVAG+57GVbt13`I"[c3fjt1e!.?**l&NZ_:VN,!&jqntIPXhpKsY!8WQaBfK^k %(<c8'`tT_@"&gs3FVtA'',X=E&gD:e=EkB&6;mdn5VQt5.M.WeVa*aL$Tsr?$G#\s*+r\jX"?_:6nAZ:#I;RT"d)fl[,DW6@B_`U %QtW@-G(I_i.,%)O],l3e_aN!F8-4pI#*_e,;A?=/)\Y8PRks\ia'c%cpdJ$k"A?4gX#DGi&_#s/KGCd$`0EjnV8=Cn,a'%>!Sao! %LY,Y==$o%<$-(B#A&Y<^P:I@lTS+sX6kg)j^_<k'3GL@3%j-T7J#e2C"[iuB\SNgmSeK``S69$4$po/k-IEAik";K_(_r`L+?Y4W %,G$SES[bpF7oEf%&Qt5Lph@/^$Xl46BDFlU]?)?P&@#GO5k8b#NL1"7T3)CZ"/+X#\TQCIql!6mN#S*Pdfm^.^fBX'7W&;0.1nj^ %(EEP7#qbBATj>!(i5)*DGZ0VB7cYfKP'W*&%``N>\gbH89>SMr)FD_up]=7VH_<W\%1PC`i"IpORPZPr\akicEEe:%KH_fK&]s\i %Q4fKA4Ib`<!0G?4$+S/L`A')e`Fdb#6qYA[6/j3C,uA"YNr\`6Wg9<6Ta&cNa?W95A$,g=@R-U.O/o\FSY<J+8-[FN\8d<U`>emW %$lu.lR]FP?i@n5o9GF9/^!*6U'L"Dh*t),!iWrQ"B]?'29,rV:o#dA&&2iO;@VW0h)ZmZS:i[$9]HN_t_`@?3&J>Kq`:PbO-2<c3 %'EpcA*/PL7h_lX^p_mTJgt<ro6H0&h[0)Mq.n!I_%"VAg,FgO@joO+hcc?t>HRNh=K&GX(U_BA9g#6QeMB5o^9W;b8N_Z5:TKjn[ %"`FSj53gab,0pfX@65)il<=t3D.(?<;\"m&+@!gg6;"9_3RRK/>7<g=;?3R_:g\%=-u_GF>Z;c^]l<2-bCCF]T8"d"Jg"cXKJ&!. %asSFP)?r)%`b.(mOlRFm?k78qeO4.M?mHS#S3Xi@r<1_9kn=O3!+`&q0`qhF3]dO?95MfT,89+^3BGI,Yp+ZSGVM@9kJ=PT86@6j %5@N<F7^?`JY9Fu2mkY:/-UJ84Skj\s+SgPV>&mV'S6SNjM`t.p*h:q)@CSAbG:SL<S%tM`.-T4oOEW`YL=kH5,SI!tlG/a<)ZX.h %J?b40L!1?p\0)DT.SV_1M]Hbj/i6?Y4L4?pBE[%PaNY/G;6:KF'311q84UgR`;>1\ODRQT5U-(`+cO>OODi(H,i3%sr,>aM9$JZ0 %.fg^LZJSKTcBGajaRF2.'R$7h[HWe#@8Q(mmlJIW!\$FX@@?Ir5buLu7ir@A"n[\+!GHAe?%]a,/p*RX*nKm<(rI"Or.Jq`N6r&F %*lUs2[37+GC)f!i;Ge.UMh0.tg!sUG)Jlj_+;#cRR-<Q/"@F5chB4faWHO.HQ?=H^1^nP8k[%[LRAaP0Tmf&R'S.pT/!lRW-JTLN %i7K[`Z;?)F>EGj93Fi[BKW0J;R^"t@=JI\X*0qb"S)m9(1cn=h6&8_Hli^60Rsh5AWeJ8Z54`_,'R7La1b#d^9:AHq(S9lJ9#JA# %YjL\D@W7B<HjVF,`c$Cs'8pd1XA22R!u%H5@/OJKVL3"5Q#CdsEV*2b1CVjC"Yu?])aL7[8iPDP_))93X"J(DBY-/3+9m[5>D-o6 %;"g7n-sRFn#7-U"3*=&V3Y7TglHMm)M?*#Z+I7!//XV(pC<:!:0_H@Z3%n+Zgm;+JaKDCW"QcOa[>(VhnkN<r;0Tlo!uEU&5_?EI %Q%8e@!0Jc;[p\;A0*Jdu2>Wtr)%bZ9,FU2WLo)%)hZJ+:Rh=!LL`7OLdH8eD6rpc`Z'8[S%CS\KpQW'fh]oXRRrZcZB]r>q.jB&H %PQ>gI>K6=B1#6:q38?8Q\[+tq^;UY68>4ZhL$[cC=g'S,gE,nK/G`P.90eC]RmKUsK]/U8#,AS%_[<orLlIGDO=!UE'H-M,6=$jB %OP#k)`)_XIF[;\/\0r0QS\+as-5KoQEiA)A^q^GUZ46p?B*gqpN5,E2&dgQ!]PX*?_^*cogU]ANL-D7aa$,d^@E^NQT$3HH,%aXS %0M&RR$igCs:Ui!5/^P8-;adu%$K)FKR[Q>2LrM/,oI^DX0_f-t_6\e=N_)-b:CjVr'=L34PmE:T\sc26^)HX%[iKm!kYn:l'8rS@ %3B3P/(,;a1C^;NR'Lp.uYTZ>o'*+aN;;e>AW?+F*]i5]6a]SWGcjl1mVSaYJI+]KAl4b7J7T<q+,TtO=Yt>*;^VF)`e"2>B=7V,3 %=CcqqEi&ts+d(/4_+q(ar;hS20\T2fMrbF]_,:Lh<27ZhN#F/fBY:>ZR<151,52>:6X\.K+''`bd0SA3C'&J+PpX1pTYs"9.&SM% %Vk+dG]_*[6>0JA!TJ$m3m%+P\G\lSqVB-c*OR_8->J;QEdP6HSUh>`J4h:VC,&r^NdpfGI,X8gSp]R4pGiSQ%Nu_mr;ioc0\r5&\ %OA-aY$p[a7U-oDB'`dtk+(qP5K-aC"=%EW16.[LV&$04\8msHN@P^mN9O3\(_YXrqCXB[=*>#/i6GU6EUZpTDIH?]1"Obla,](VX %0he!(Mi3d.!kTt*5f@.@aa>EOr/dqf%c0W,1Ncpmci=fE[!XYr[0=/]k+TWjjFWS/,='3NbAE&Ij4iR!LB.Oh\f4(fJJb0M%G'PZ %&W%Y<g*]-dh[h&-E0.o,5Zq*\5T?,oc6Dob:X)5-%k#^A.YKiO,GX0=Y`k0-BVH)F?:H*icn!u9"n$p!,-X08F!L`BF?Mh`QoUJo %/4W4&Hoo[q+=7X09O`-!Vi<%NU$X:9`o^DdV4>a73WdI<:eS^$b6%<BMK:WleP<JST1<:oD%dUg;BSYn)k^:.jDDk;;%Oc0%?f"L %)S-1lj?-jr2^hC.CY]?7#c$GpY34hjH4FbC?_Ea2!cJJJCRe8Dl8I)C/d:3rVSc;"FBq3^3^WE@ZttY;?j<A^R\<Jc_7B[Xk;$ea %'%e88TT;>jB!E,/AK%)*B!S*TPR)]I(JTJPVYk`)2l*:p@R^sIc\(gRTG^-&Z6L1"/_U:d4[Z6'&Oh0lr%,"0TjuHbO6Oj!@MiT@ %#%7=5j@'+R!aTFU+sK:j,>3qBjaYY;5l$cY*:&>a,"0XAR$:%I*?5,T.<#M#NbFMQ,tmJkUb3R/N:T?3*t!p\gQEj+5]7*F@N8!E %U&ct;'7aop_I=(ELe=#t\mBs-7Q.buYC%/HN+94ZJ!Wt-!Gr9h5X?M<RJa:V"rD6q@S'g>aO@),!M[Xp7&2H1l53joVLu)CBXPKd %#/Q[F821eI`Lb-`OCS?V9=QH_TE>6(:]!`1#U_Acik#oWZ:9[B-r)S]"nsA$b9iKs4d!00?IR=X'1@/o2$%_HV',X@7F1]oj?Gu$ %F(3uIeUjW]"9J(pPCTe2KIq6G+cV$e^^UnF9/1=>Nnc(Q+Y=%iK.EIs4FMma_@,-C"#b?g(/KJ!FN(nC):]ecM&,8Z@PB_FS(e-9 %:=76ASg[\G\@NYF*tdO&J/VdlO:&L$(o8JV3^TD!O"bhd!_-83$eT*MAH4g?AtqfUQ@])EOoV`M"g41`2]4DH%^6$S2`V9i3Sa=E %0ms904cHB$2M0a7U4h$b=L?MPiio$""1QC6Wf>m:OZ`d8,We*M#NNueW5-=Q*Bk9a6Ottr!0Vt-8\mRs;ImIBTB0"O0ufkrS>%I2 %l6ZS4350d.97S:r6t8NdjG-F)aQ#c%faS(G"9U7'#mEnt=;'PF]aEi%J4*I]B2MlcO"FtY657Bf\)j]2X>(:iACZHSc-YXT>2.up %EM4Z"HR@jh;E4s5Ulp1g:ru9c5c.A(+CjA%-=W)fr*ZMd^_J8Gp0\U0E>s+RM-5%RY5EgE1M3H:49kl1M!;Mo&VZpsTXq_mVQMb3 %d@piA[-Hj0e%j=KO73.RbafdUL/+.i&k+I+Z;":*Q%QhHj^g(+U5*dF@[RN*VM,qU>c/Q/><U\^/k-@D^anq(5[ZhZ/eQnN<GBNi %#[Ei(MeI`B!Rd2V='3&MiY=sg41]=3&:kuin)?`WaH%LS$-/cj0c>ONUMf8IA2rZK)$oF1<d(8p8hr0G2b%?<Ht2+:T+;#?2M>hc %K_u$38*,ie#.m5sbb4X>"15Jq4pk*lk,'Q/&hWa'-;seZ+F8JZ[@TZ=1YG*FeTl\$.KS8[4jFFEYR!TM/M0ViZlBC=FDMCL(C14F %B]p]gXPeuT_LZiDE.%`!^g"VUrl_.H4ne(BNo<Uc&53YXr\d)]C]%%nZcb)\QMh=*'(/]DWD,AM=gXN);,g4h7-TZs%PIX5+=GM\ %o<Jk"J:(XeV,,`?`RqQU;kRU*&87*4-V2e+&h[^AZD]$+VUl0..POA7ZiaDE$5'0UMF1M)OPLj0Y`oYiA!d]1SBE:L(+31o)TBkm %H"o=D#>R6hs.6N=;k6@I)P>qg-qMGi0utF\b2G%H1,'aQD8OY)!N"hX)Ka%]P2]+Wo]hC`2CpP$>"Gl/JJ@=Dge^s:D$5h(q,O@A %?neXmjE+^h,@H-)"JQI==25Rt)oQ;i\dG@q;;$:8,;')7,/`EKi*i8eS1J83gPe7*'=):;&t`$eEt!4D+jIn1D[52E/OfuO">Yp4 %M:q*N-#576&<]@>E65L5M[JL5/BJLeA8\\fHhn*U)cMkUA1Bhd\25e-0:9^XZ2b8D^pI3),8%^ncu01_'0<"l(MA*k*'05$S6J[C %_WAd6\-hD20f1"@C`'=N5Gg3t:[\dlaUpmHaB6ha+hJ@!91dN!$u?-$[CL;eij608^M@U!+.!T>.&,;Q4H@7eh%@*Jl^9F_2kPBm %B#Z*@[D<-*-Bg1U)p,VEanB,*CDudh=P\M)(7M;.WQmN_N)'RF@Z/6fBT0Q,*t.,O0eh0$"!)gq<-tGa5N(T8MTnUY$FjYQaMMao %MhpT5/?kh5KBY^^AW;CM>Y_+`0>T(VF^6K.'SKZY6DL]Bb9A/Wg)!))^Sg%PcrTLPd\a27M""7bFc$J^oWE^Qc7q_WrN5Qp<'M^? %Ls.Ehdp"HfR:,,_$2>Z8O!_l1n8,6L"%H^_B5:memqC7C]H5pfO]gOYoeU["D:?R*g<ECiVH(n5Y0*;=VV/-'W/DbRpHr;AKhTuS %2^&pR<ED5[0J;!VHn7#3A.8.WnmSZUfIO"hr2H:(J_::iI_XHNKh%,KV05fe2q.i9](P?Hg37kF)1@2q5-/&@Hi5RWmJ)$`5=G1: %Dmp[BQCG#IH)%fj;m4bu,J2_.Zd\@9UQ4h2j`o+gm%&"%W^ks9kNrKRSQ@%L0kG7'>H>.e\SenTa8CmYaf5<QrF=tZr<(E)7V6$+ %a2A9\5C?O^m&5F0U.BcESBP=%rC8)2KkClUg`^2FFAR4OCfcl'!C1EGBjO3Vj^%qJJnR&nkJg[3-0blT"/n1Z37o%CAhkqq[c+Uk %\RLD:Y?S,LZW>=UG0AE^9hi-9c/SpTl+uH6T`<;Ec9R11-p.9T_'9FZC&K\qdA,]7i4XfUp2+jT$C66m<;q*_K;c<U<*"auXSE49 %d=p!nqL9l=@t(.263IHlD2)S&[--N/UoR;9X)/$>p<dLI9ig'-0?RW2?$mq*WRV4s%]Y*n#(`3n[08g8ZU6_ol<8hLbJ$4PO4%Lr %cR`1hc,c)\=aVZ-hP46lT&A;.)rq0XnD?jh1I/buo.Mc$FmO@i@nIL66dbVW+3@+J#ZdbC5<)U[KEBcaRbpj<J/Pj.h^^no*7@"> %6T"TC)+40("9KIl'bi'9N$2Kk*sP1ln/_!c:]1O.\hH7c^cHHfLAYh=M7ig"/sdC^+r\k;a)D)"\uYAVi&FR:"71"k@M")[=gp<R %=5%(QAq/^hmK?c'QSSpn5r_?@A(?KIA5>_\`eYdJKu]%3=on[XW=H^AlT/ph/``5&+&N^EqB\3gZ=IW0>Z!JP9UOIC;O[^?7)1*H %@VpP1d3Q(%c6\1hBM2"MdWq/j>3U'fU!)\(O8rZe6F=^>+GAgsi"@rALrh#(N$!\Dj"/+/;3#0P:eU%9DtukeGA;,l3#D$+(1rt6 %1';8Y3)X-B0F4m,rdNU5CJK8Y2WMb&^'Y@:kD/:>!1Y-_4,D.Im>387T$S?>K[C\\fsZXBQ/keFfd+s9F<F_l@aC*k+>.^ap)"B> %`9e]'!Tm0VA9Npql(l!0dFNh!$*m"`=%"=d9$5Yg2-?R:aAIiSf)eNq6:2Q'4qN06N\sMJ@Sd"(1FNNiTR-mM*1ru>iSnmF8>2EU %a5MbpU?l7*Ohpd=>aX4T1fB@99;s9UVWl5"JP=`.5!sBId2&$DV,pP_jLBLCR1.6KD^X9@.%[(!2;mKLW=D2TE2%3f7$ff[Or.", %Fg;*#CW*(4D=h'&k*/u@`&/4iNW>Jdc&up`i3^*&M]g\=lm-gt>4LA\^'(S?\`pB+;]#os"$^6!L;5U5;Kn\AR3`g[D'eGI29$+P %bUPeYBM3NjfOlKkLo(/%98Bs>C('Q2;DCfk<YL[T&0j[Q(*c:A)\Eb<+@_C"9LOhVXr&n-&JJ^.Zp;P4p%\5U82S^k^iBTRQom97 %!-^-t,'Lak*(Iu)R6e>/S7G7VN#h@1XPb:7CmiIHgZPt<U"j>2Q#t]iW`LtOmS3."F0&?UGn`NnNUujOB%?rT[AThN:l1R*>q4qo %MjnuR%uI#QFsn5bs)Sg&WM`\pQZjEBrnV`Le[=jJRo&b,.sRr[$s/?3N>ficL-r(Cc]mF7("5#lOF4sUm%jWY3oaq2lu3.:nu.8Y %Wl>T($'LXS/jFJ=]gt_$Onec7BGWfDl.+(49,Xf^(qg:V@K7Z,7-oNEmfeQY"(+a=Du,r%<%h!@IlGL"aY-H:idD;aI9OFq,3ltq %NhT8qV;F0u5:!#E7KF[%Z?JXO]43=1:;s<),gBh#ZHu!!V/e*VQ@Mfun19Hu'-fgT73pUpe`"Z]$)/<RN+aC<Ck2MWl6'I[PQ]BX %F]a,]`:Zkg%>]A.$ktkl<*YtmLLT"q5-lBcM;`J=ZKk&iL$)(r1KQ)dD*L,UZq9d^7.gUQ5&c>aSl:abAY[9%%5`rYM[e.d;'XK_ %,\Rc&$I`Gt'G4hR)'d/!4X.q4-q9.21Id>*H]/l+HU\-YgIplZcj22[9^Om&k8=IXC'cV&:5TgXh"]BejN^E-1^"ae,")%`8Ji>\ %>RsqXEEj(m]o_N@#*RFL@h:O^/b0F'/g8s\=Xb%d-Ur0@r1f<gip@<0@$t9e;)359K#*\W[3eD1%30So%%:;5#-20ij?WSZEO;8. %kfq&;-,<3I$?W:b1!Bn<A7NSdeC7!ie-aYV6NZ3d1@t,p7kSSWXG60kBj>!r"o^mb_<H-7Y^>-1#)TU?M$?617d=]H.nc!56FB?I %%eu)_\i(aaY3Q9@U(Jot)j-iB&=Ys>pBVoP0LXG(jU\,)d5Kuu]d)IF",(Q"4YnAQ)16qtVAYYgfWlZeiHE=<7hVUf+=JA#9$fF# %D$0)3SB(]IkQ"`T_j:r+d+.>!U,OETJYZ[DAD]_LZR!ejg.P"H8DlV0k7N?c9+:kF,Irh&N0q+",+<@;D_dKf:>ZY?I2=t`;9P%9 %d26`=BfA#>/_-$DeKacFE7QOh=3AgXq3#$f9>6fE'_:sp;_6VQAl?dsrO5\5OYXVJV!J\bXZ;3D0RPQ^:K2,Q*;P3D=#b%+T=X,g %r\c/Z(VPEg\RN8-XS$Ab_cE'$Gn=!haNoY"]PQ,E^"DcpT]kn6\^k>eVLMgpbW5<6K.dZS0-'R]"2Z5$]JP;[[8ARdLVNJi"/U2W %%sm7/Tmee7rU!Xh?Z&kYB>no+I(!<CgFIJG9lf"Ig#ep7apeb5q#J2-LN^>0qX%>5EQb!oFPKa)@o'7MpRYVI*4;jq[7\3iboDru %f9q#seZ*cTe#J_%\XZ'Q1/X=RO<2Vj@.T-qEp3mk1==1s&U72c!TSiq8B@,3!C]Pa&A8JiN!2]&8,!h9OE%X-i,Ar;R#+fj%KiSJ %E&,A()j[/q6M4cNEQj"?>E'b!JB#CG&0^9DE-T0;@gTG:=;PZq,B5)ELhE'#5'1nFOsUgKZf.a:!LC5d4qCVZX,86[+QK8R@14Vl %Ik6a+!B31m5U:HBfF/tOE?uFQd9,uEeL.5:EN%qOAAoHd>o!de&@<>549iBsT$J]G/BmKl!-sW`>bW[0X(o.Ad;+Q.P9;bS7CW)A %2e]8mb!X:hTbn#KA!*jJQ*;QU)'[6@D:lbs`"[mF7@19p)_EQUr?fTJ8=+B$SQjN*@CoC,/p/'F$lgUrpcJOG!:Y7dAHE\k$,R&R %PTNW8,QVu:LquGX(k/n9`%+L"C^>M*C8I:;a93(O^4n^Z3(-:Z[sSD.`>AV"$=^.Q_fJ.T?NMr<"BQ6:>H#msZt6aNLjNcn5HKGK %Eb)PrO_?$7;LJZ]8g>#?+k-gp,"Ou[paYd7fUTV[AE"+2</B6/o]]lE#U!SY-P:2s0QY17JmnD4Un^eG+hjP!Rq*-<Z%b(7+=Pai %U%H&a-UMtZAbfc<J]VkaOuWMLl5P>kCR`]SKSD`V&fs/aPjS6D!'iSa#p"[nkF=:8A?%&;=J$@i!8qCqPEilj,"a8e+3SLT1]f4p %Ra$p^I$=.W!D1`uH-Zi)D6sTlR6SjOcl32Y%&L)_=pT-cki,RK$\@Mu=!9kQ)!E\?e;7-:OTE<s*Vc3qCkrZ4apLn8".N1n$3S<N %K<3NiW`Ut9+:ULFe6NL!+PS%`OG9i&U'k"Zc'j=@L/e?sabpfD.8-QX_Ue;!4(+2WZndgfH_J`%N"NVaH%KX<\0*r;?\Plt-l4`Z %'H#%V8h_:`!,t=g;7Ac?PQNfW(fqm3)?SY\$c?.q`rpdul^?hRiEA^q,h_oK)GQ0(@"rEZqq+ki.a<Aa=PO7Nq^@0EVRE#g)Ws:" %'o8`n@rUBl"O`G9T9*M)I9lB^K[;$/TXeN'R+O<YYQmLQ,]kW)crb]Z.*EA/'t>m3nJ3-.65Xiu;oOfh`F\4fc!XtW,iQ0C6'!(1 %35K8S&FOGH5!u.Rem.QH])%\shLY:>Y"g[%J@neM0tRL-*risQ.XR%3+mK1A4ima54^nJW$,Y:;@,MCqSr"=r'I_-^D5^Mg3eF<` %Nc7LC%RUq[G*rC^VW:Z,d6\DtOKCqT[:"aNJjRD(QVl^XfCX/s(KGh&gD;M]lkSS9g*D^#T7CSg+l+H))r4:R+^Fi%#"tSbNYYu+ %=KR.O!2D/[1I`/`,_1Pgpd6i[6(5]0=H)n&H]6:'V+\uXmVS-Z&uU[#>(jAAOC2hal=b):d3l<7BHI:V^*<s&0sX5%]4muR7Z%dp %!j51=i(%?q@mikJ90FBLF>QqB_nD=,T,>N!*dWdn:GWlUqifVKcjI>p$,3oY\:%ctRp:;l;hP_igt#TLZHoAE8]WbtJ;?c,Q'ioN %VS^MJU7j*j77?&oQ7lB+ng[QLIpsXCFSY<T_>b'j:WW)-AbP-8_^9C0JK!HNW"ufX*E1o<R/>l^^&j3@"YRW$:uNjZ!,tMPJaGqj %F<F881`U4_C+Q(.c:Vc'FNb@9@Aj3d@iD%:&cJF80f`cq-`R!1'I/hf#(WV?eqX6NK^3?koHCafL<ZFSmo4h!A633"9s3HRjCi]I %&\_F8=ULo\*9eKW$uQp,O,P?[o]N"[BBg[`$%4Ic'mPZ/`B^HHKTs2=7)ZtfKPuP/_MN5j87RY#P$\nJ"rnPI,"fDq";qF0-ehOr %$q$7p@R+?[aldZ!0Fi5Wk]$'m(t#06)sP0#X2Kp_U5=g5U;\I<%T3NWYoTMJM\foe)qU(tVP6fQ;+3B?q8@117YTV?A(fePLg1'^ %Z&MAVq4.Idi,+,q:3;nDOX!]+/XHQ;&C?&o;iD4*A*,aKPn<52GTh^;HT#H'@@^1,4ou@QZ<4bsb5PjQ0e)MsP'ABt6jR_"MN5!n %m]qn>^6KQ><,VH*.:C54i1DWkNa+ng7&%r1hh*;U0`6GUMndY5?E@3.)_X;_68tB-F<+/u[NU06BQ$K35IbS:H3B%U4_Ru]r!,6J %lm6[>)3bqGf0UB].&&]4?F2!EMYd[Q/$kTYcOe/]U/!Deo(;Mli@d[/\ZfV%a:?5nbm!O'H6,]40nrG^k\El4Le,!RlL?RFX@NnF %FlJ5@OuH6!i(q>OGa+d>9aVFLbr(qT+DUPhBX.XRQ,.L8A[-''H&8_tD2*^#VHH'b2NeM:GU`"f+Gp073s\E<n<"P"0Ba\'ia])^ %!MQ)3+16pHa%0<66F1e@5`)R:0qr*&?7*4tIBNO;hXZA/k@"#hA-PEH;LBtaJo@O-(4iJ3L^&G@LT/`*1:o0i&jK+m7i/9]jBS0T %Qo[ucXH\$!%Lc4/@l+26+BNAg2ds\soPQF+^i=0L5u&MuZ49Vqm,!LcFV?:0Jl9_TTfD^Iduh^JO"dih!&fmt^JXH%PZ5GN@O#m6 %Pa3;qV;it5hrfl!,0,ZeZ<^c'!d4Vk'gac%/fu0Me<^a4ORi!_Wl1.BL^kZoVhhcuV4WOdgpU*T"%,/>,GNM.;lTpR-8HoFN+`OE %FHVG\,ae]4=>\l2JpfI-TU'S6C2Ae/lE<H=`jg?qO_J6EMZB1Gkb-$lmSVfc6L)kdGR\+d",R3u+d?hs$FcerC...Hek?W<0'aE# %##m<9f`B[U%GX?MO<-cgP8Y$cfX2_ELK[GG&>dhLi'Ab"59G8i^E/=PjkR`[%9B^uT%*)AC(j<JFe9duHn3op+AY&"TEgG;"o"8' %2lEcr.EIeIfO3m(g2CAq>`(9-W$2\Mf*kl\KHjRe3],npI5i0eV27\#'PO?8`.ZIUImE$P`(12bc;_j&Of4PlQ;W`n53DGW3Ul]q %iKJl="fee98BESC!&p;c&@<#h$oHi!%Q+PC3Y\5+Jnt#f^.pB*V',Uj_+T@B`R&`WW?a`B;GIBeiJ;MBO`g`VVB',N'?B9\0bVb\ %h?u$6>XrlsW]C[-3<jmJ\C_B0*=30\(^V\Z+F!m$Wre>D0Em0h1UE"U-,]>/&WbJa!7XRG+FF[?'Pb5\#S[tfs,GK^&)3B8>!J9, %XRkg%BNMGOE&%Ape1O,lL?sT/;A=A7!BYt/2?HB91P0%d^m)[,"?/'P3._aq$9/)[E&5>A7/3&NcQ-UOH.?uGION4CndVCZVLX3* %IE(UJ`^@Yj9Xkehj+5ST53E#n!MaXDGl]OK&V94Ud/]5%cghBpTDMp]2A"">P7rq<]>8s5Jd=8d8c'RH)V@rZ*fQ\F`eP^A.E4,0 %iL\NW1V:gb<sCtu@J+Ll2!f7QZq49W!]CJTc4'Y0,b*`''cdVR5p@8<G6-*XKQ'7C4,@'/iigjgK??THN+^jDhC2)7g^#D5eQ#2] %1-o-<19*OsSDif9ll28@7cBiajoE8]9'cWI0pa1)SBA]>*.oeAQVbhq3Ec!=RQhaMISfjY#.PcX0m+U=(p4`\Z%$"Q_1e[(;m8.g %"IX=EZlVTPJnGiDJml$H:MQV-=&&r&?YU_F82.st_aqV9b2l<)%NHoq:\B[%cb[]u)EP4B=(00r%:@_<4b2u+Y\cer`#)rZl:bD/ %K"1lQ-s'f^W9,)6`Y%*^@5+>qQJL*Gbp>Vt4<bQ9q[P0mBIJc\gB&Lh"<a`^qWJD!Q<)aB1:_@CW3%Wpf.b$`#oHPGWu5C&?bh#o %`Ihnr[0Ro@RThu-?a-f,,6MM<fIk(Mf$I,NA@b7Um*IU,Z<h`2hbh`J49df7(8_kH&&2_*-+*ug_Hg*Wb&+CjTtX7C4&C?eFC^lf %qiL.nhJQ!B?5N*g-mcsp@_,[W)rP'KT?%@E%[ctj/ZLOQ,`OmSK.Nm.+D_@0;'84?5L]=KAdF%/cj0Xeajm]"C*4s)-C(ii%u,EE %aUlGMgRReJ5g<[["+1q)#!m<F$m3SsIAR<"6UT-8Q2%WK!lN/N9dYXM`AOP[`lH,W14^Pa8`g"<WZ#]M`U`SqmL>8%RB32VmXh-X %WP4on+3br`=>5ET7mZAGU'b<1mLrK\U0T)Z9I;&rE,%1n_lu/.MTSO6Oit:gN!`>Y%Zkn&9W7EEJKR*Dkt\rC2)m"Ze3^]Lf2*NU %gX5dp5Bp7-!Z:lWNPWlJ'uLbP<<-If/?TN;j;SH2&CD[H0WAH8Z*]c*XQ88`LY;dkgdCl;[]iqc_a1BF+CE05hR67COA7tDg,)p7 %;1+FO`pY!)Y]"_D,t_E75c`N<]50c^_Mic^J+P>*OTAu*7Rc+UV(s:VGmCsUYUPMA^o`;sp]`CR;BnmKfhdlI%"I@ZZ7-%sTITF2 %%0pK3P%$T57tFAqRkRat$okC72F9dR5CkoDQ`l/W5ZCDu_Ogng`e1J-X7(nJSf:FE<D#D^mr'NFSZ,Kh8ki++dSu;'VtHG6?(KKE %L@XqM.!N/1;iP>?qV9?n7b>LQYC>9[LAJI2O1Y3]<'R8F`kSZogs,,X]('Pb'mFg^IhF?mcG&Hhd3A#D\cB.aE_!"_NWdC^rqREO %9L#&la>fO`PdHlu(C_KjN_lG5LImaZCd#$A7BIq;Uh#:2=d>^<k"1i;fs;'S^pp!B3uOo(i=?Uf=<lst;)j?q=Z#suR[/?PJ?D=. %*MRDu&!Q9_f_Y&M>kGVBV/t$nr-_=*&5fq6O6E&<oeW?B/IbEdj)=-peA^=ndc<dpZCXN+r!cA[3qteJg>-V'[)JNS2FN1m+9%Q9 %Vu-JZ>+D,?^TPW)+T@ZRGB^A8a"2iF3oFK\%QC'C#o=UYo]V&RWZGG+6^0`[`t3Ah?nqp#^(I,Tgu6J9;#:C4GsLnp+,6_CJe^&6 %r6_W(7/`;k"r+ibUUnXp7Q#/'W>qcRaq&th3M[*?6p6bVrj%,(O=C>^UAXL>PXOeGLmf_Vr+/<:`*Dcfj\8FL*;QN%h\.%\22Yi- %UtgH`.?q-%-W;I*HOhNi,#(e+<o2p`-2^cMY![;*3T("n-LK\6qPGsZ!KC$DIR*'9na\bRGf)@6qI,3J.Em'&qih1:TRR;VrdY26 %ioPC[FoR\p\bpVhp[r\aZ]a9t_)(t)5-mj]?-^q-eW9a064*]XX`c4iQLD<6[g*!r?24$XA\3)X[RX\a2k)*KL3^dgR!IA9?NU)c %TQ-b+HiO":XjS#e2*uN@/%<Zf[;KTk>6WBIZ+jki@RMe\XA#P,PhH(;<rYA9F?Ymg?,YL0A(qN.MHuGbjo2CLD/>8@>045*`K1?& %;%F)DV%5<:_'d_Rgi!2t>b^Q$<Ol=J7j"^6@2D;"*g\srDQT@)a1m%.)qus(U=<k#bDj_C-e=g^er];1<S(>0LoAtFm8%T,qe?>b %$^YNsW@aLi:NsH)7mW6]bf-J"re*.Zs#1A_&,sNqIb\W:d`\E1NN]eK+"sCl%=,)OO1a%=IBp!SOUmKNF6E"gWJ7a6YB;WXZQ]>J %5Pn>Aa7)t??^UNAN(oLPrWDW^;j6RKIsu@"n+$Si47?oh_FJR$b8DaS6u>opN3f%:Ipf.>1H8Z4-.%p\rp&!m(f?h#N#\*s%3LlW %P^0`j9(L?YYUnh#_>J),4Gr$r!>E?k3MET;Pj50GaPQG7O$;2bj.u-(@&7sN&)dJ\A?#m2<cKIF8S@%dI9?@F)>/^Wcjq*AiYN+' %V4SWm%Nnq3$&/KFBJ)s\FqOW+0`8_;7,T/VO!!3r+oS//n5944UXko;IaMp1dDA,4oSN^QdK<gU%oAGJE_]37heM`JEe-k6QKeo: %f?dhYLO(I<%>[Wqn!:N+iin2uq>`K8p7ZlE=0KPKdr&0(lMV<s=(a;3#N]iQptI,4@d7eDJ-&4OcVZc?!5C1PlQ%j8Zr3o(NTY>" %YWp\)\DD/>Y86iaf^BIMJ3h0)$FM)FraDqW<[)N`r>6FZ?riBKQabJQ336D9rY2t51UeR0`qL1G><Fam,E7CY5=:Qk\enTV5U(Y( %;.+9Tp(gbtI)iLk;F`j+b9[,LE`%gB2)CGaMnKZ++D!\>]=(i-e6:DZIZ&\L6.a*u_.cKMa'Wr[Tt_5cD,&9Fg@rX)paIqe>!jpn %H_!Y%48fK1gbdGs@ZWo=.<k)]V&oPfiBQ@q&jNL1E-l-T4$U-0o*tA8j1"us*O^pQ7r+_dPTH6\(Th<!_h]Is)*K'oEPqgm,BMUW %Fr\htBK(]9#iJ]I]UO\Yg"gYKrJQS?Xe-a^n.^YPhr(DpbUN(lk"9,2<!-#W)tbP*?l#sQ>`C`!^?G7QBq=a,I;/@9'CO[*".k#D %O"']]@ct=o$)Yc#Rh&`<1ER[>T68b5pb"N=*2L@K`S.?f\l[Ya<bq)(&To.UB64h70/X4+eF(VSX0"*YYh-6K)P(dTQ>=K$]?s%3 %&c>^'mn[$a%ThLFI[uaJ-i;o8&\`^r<?,:]r<F//h\2meJ]4-^etk"g#CL]^G+Z#AA#eK`"jE)1VJR3J!PqE;kh)2R3g&GiAYQ/Y %s8,ES^T3*-H@bPTh#KEH!'<5AmAHu_ccCC0Wr5o)T.5)0VA]RI%5.N..!S\@r[q:/rIn:$WnNM9`B-2rs"g[g3E>IE!p8kOVABGc %0Ql5J<Vp-+[?'cg-lXm`hG6$,?\JMV2>jG.5LoB)^@U4]F^2FT%KB1)5598$I]D@f=N.9.reD59CT?;gjic&cHRF?nGpj_L>NGBT %aue+LRd0X^X^(\6lM"lj<P)Wpq_j[(6S6E8U=iKDI]D<*Pl,a*hbWqBWKqa`>2HIDaIOgUGImG'0=:@M%=c;O>#QOB&$,L!<5kJe %Qm5&D^qo$HJ:JK(%XU>j$`a)!Fo:,t[esERr4if-8e8Pe%%sOVmUd+?D,5<PWK.!71>o-l5Lo;%MVd/<HKI$bs*o.P/b@Rsq5K*5 %C)*X1r#\r.SZ.3*PqPYMQbF!\C]Gp5#XT'XT>'L;^BDilo]<'@s/V'E^TEqH?qCt::b`#H4L"r`D<Rsf5?7<)8iAe3o;?@&<8"mq %:u=A,"A[MF?YSX#n/#:(WL?%\(%3gfkC5tIGGfcd<59L@aL;5o!M.='/AniE7)5<BqS0Ulq:dCqQKc7ep=0(`IV;MQebuJY5?7H- %>&HH&pSUX@O*Cia?cTQ9eb8HPiQZ(Gri`NmHW-jAO"1%`<8!n$QQsFAO<R'8[8<C#][.$?j>h2GE2r"!^1-3mWoSr$Ba66oUaY>; %Wo[$ar*P$b:UU,"Q9Wpjmnuk6INd>2<6`2$PrF2dQ(P)PUI$c6:Al9ao9BUN1[+XY_/B6(A\g54e&lK$]Oh,#.e$5LEL-KkEKEc& %7qsK%Pa,$\JGOKCL\5#YO)F&O%;;eHX0mB\(,@`^rhMTTmhuriUn/ZS!QJ%4L1OM$4>B!3["bTJeF0N1:5stBTWq>\@KcJ1*7$<$ %bks2Tcj]Af,QI`I6?C8;=pKOXlel^-H`*1GWI8H5A\m<uq5`JB59WE./=DN6RZPL)gMRjY"E#geQ4\@+Zh5aE[kHj8FcD/[O0!&[ %aMd@NU"sC+1XF7(Mgi9<q[""QImG(PMaiID\,ZB<b3Z<RAkauT0%h<0PF8N</t'E]Sp].uIV(c[RfC=BrSQ63[p75jYF/DM:Z.W8 %^EMqP;sat]kM?gN#V5r4fF^K%RLS$V/h#k>1YCYa)#Br[#eh8We0:>1?U#:P#1f$0[/[(Kn),Tq/U,\dB,ss[cO,["o0G`16Msu\ %VSc+7BgHGWF3/I:/jJEW$JX<d>?!gfiORWglMp:UDL]4.rkCeuWBCK9LYd[>[CZA7IK4kIM>hD/hbj:JO5TIro_co4\$"k-Y$17[ %@EM8Hf1XVm",HPdq#./jJ,bYglG&L)GEkF_3NQLC_!:K6.dR'ZZL72AB"Z[.H/(!\H5GsdF+=ke?Uia)A'[oiHh:;0jiN-q?bNTg %-9M'(rE*nqR2MC9+Bg_K6G$1"ob&%FDS'9Df?T8]bAJp);mZG)pAF9M5=dpLWm,s9lE,\^^")<?;9N:Bge^^<j\!;D*VRoKFa93M %6cXt*lRa$5Ap.H@ibo'/n3$CGdkF\7*RqZc)NQEAj%9/=,P@e[s"--dB%'GIh/1]R4V2j"rB'/<6dJNe[0,RsIiWfX;U8*]I`uI5 %WkEW*S(sPjjnr'&s1=iuUT8FCrPqlNqFQ^mY@Im2J$+9#Hi32e4C&fCDS)*pD4A*hi&CLHjIMEXI'O^/Q4)`Qh>KR&'UF+e*7F8> %.rc0e][7WV@HQI8Y[40RNPDOBlf,N^IAKreh<Xn3OMB>WrIbm8.G(g8:Kj8IDS!<`^YbXs^/rhT9r%_C`XIpnbt^V^_t:B%e8%+^ %;*QnmPh,IlSa(Z?0XJ=Wn8,F2c#rpY\fO[QTU`]3[gp!LFhMpcbn<$D;nMlk$*[%ka$C]8A'aYjh"sJ3CJSXLn@]oP/`-25daX\; %$Kd3!@"3fl:78YFgrnaVQ^\lI0\jlfGj`nG1_CcbQE]MX@H$D7(03EU0dcJGi$n/8qMD\86XCQ!6O.m"&+[9Y"N4qbk%0>1&:]gF %gf7]$?Whg7%2X3nC^C4;Ti>F]^p;o,DdBms"#g\cl0*Kc]\S*Ur]_60jgkZ6.b2]?.s8!/WHP6Nm7@c:S]h+>Wqg\9Kg1jP8F+gE %Dq(9Qc)tXg^3@app%tH:H07-jp^NWr[gR]5(t>ME,8gA*4OM,kjef$LVdd2DSs_`GQG:saJ\P[7*r^W#\,-f>AA`k$c-6.>Cp_^< %=f'DelfU3Tdf39F28o(#e&<@"+)=leW]-s6>)V**plt[`s4./+WR7njO'96'DrkkT2&6uADu-Tk\<43bmu:uc<`s1W,O$NRqF,%p %7Fp/H-DgekVE2iC8B]!Pp:JW9Xf<;<3Pi2(c#H_K^Vl2CrVPTVmqDOsk"M.PB4@V(YF!QS[7N:UXfM:K*V>V8'-D@1qB,0>pq4aD %YMX6s\")fWgP7;m15LX'kG][al$!!Fc\3:\:Ge<niKX$grqM=gj8\lkoG[DFYKi&CG:@Jn?W>u]TDEu!`VodCF'a(4Z9n;oDu"IK %NV["3M\Un<:1-,lIE`l,.OI12qF03/^\oY2$Ii-[_/3P%<NBJ59u>+sbQ%@L`4.YhK?i5",nK@n0)GJ$3e_%uqItT.quh4.1;0IV %9t+$DK)sq+ptma,R2JA@NR(_AgqBf^Ps>>XKALckP,07Jk!,/GG7HO?9'pN&4R,b_^\FP[W/YYapss]U?X?Gss8(C8nF`[6W:q[N %:j(7eG4CRHQs6\<?E7r[$4#BF/ES4M2Xne;re]Yg,k)E,RYp&u[&)fbs76a?^NQ/cqm'Glp$1E]>.6okTDZuOGPZH<s-^qH(2Ngi %Ze>X1r4`R5C_O[Wcos\9(WK\ZjI<I*hYX!B9=Fj,Unh4ubC@bZOd%-jld>2N6PnP(18`pI+92!FR^IU46C\#335WEjNX&SX?;5J( %@ZBnddoeGlN7a?G\a@g>UEL\`P?PF#bMMD,C3k%GTp*$(BiQRj^6O$X_``>NE<b4:1bojV39RDI2q'AQqR(57)u9?UbDgPCP%HAH %8(op#7_MgFoP8sM;ch%rQ9>Xul&BUdC",548fJ25IqH:"9D+:R4OI"bBW_06Q>(iLFZ\M]lj]!1bfK]olFjWP[[&oY7mH0lX59VE %LYR'?frOeK15@h>I)%Lm2>,me,^GI;rjpX_>cUZG>^"j\*OZ=nM9bj6qAn*oI.rq5WA&su\Xg%[R?d6@hg.0/dnAu:Y3j6_QFm+e %G.CgWP6e=';gmiRUeNKKh?U/IQ32kq;/NF;\$n9oO`%cT1Yb#nh9ntJ`.;`[A$n$IS(2i"HsVj:Ij6uSAk'D!(&,B*A9Q.ubFA'6 %/T];,aO3)R+d?Zd_/Xikb!]jNp8up(,Puqn<it79@k7@0G(,4[YbX34Nk1j>r+g!Y_U\`GST;-,g4@LhmlE<B]hZ23C8FDTMsX#, %n`\JhG\&-+W838IrS2QCGLLKrXZFN:_G$l_;'4/c2fBVrB`"5CQYuTm-09rX>2sn=Y@_RZ>q%^?<dOQ<0UY;;<UZu2[u9dBnXklY %P5oMqDM1?ch8seTAI;BVGeon<kWi=FJc>tCAqk/)^7@!lE63;4hm,%=(bUMKkZe$K4I373--,^abDu8rO%@#?)J<jo+-k\n$GZe* %gR0$Wgk[Dkj_lBsl#s,U\5<=mgV&6u05YpIBCb0,2))2aLj*%MH%9Of^jZGa=uG*H)2pLj_$3,)(M2`]@CYQ32o0"J!.XW@2D^B8 %*p[C3CGEhl-@;$N(Ph5Db_JFXS/FDNj1gIs;8&t(=>.L>E";q/F*)JPd;Dq6WK$[IC,<Nje^BH+k8Kd(D`VVYE19=,ak*]<hs-u^ %H$[V4;`24MhsMj\Z.g=W05>frDg<#b*m=>PVg)W$l\D&=L2W\gT(;m/;sr"2EQ^_pYf4?D+X8SK9_+:1hV"[UG5-eaEB3tk\Y%QM %:tgKF*H1P\<W@-u;G/rp;f>[jJ+QW+NO>_*71@uP5Cu*Jda*Z\lhU)-Y&48QYAeS?C^$!hNf.hk$hZXEZZ3uA5O+I`8niP,<qgjN %eLrj.IRNE=I<E[O_q$dB!4%QsEX/c7KVX"M.lNlfrqAa]d?nHr[b;9o.5Tk[:%/pWJW8F'c#GDpX&?X)=c9<o[sn(V<Y&8e2B9Gb %:!`Q^bB*tr&7*>EQoQM<e^I6LE>)[5LeX-%=NureihP[#\drhp!?klo<7f7<f$32PnE<6Eq.HV]m=Q7O:P75mnr6hT$GO0:8Dd2A %Ghh_Gr9Y%*9^GjJjPFXYQ0s!$leF=Cn_G.22NMaofYacZZ]74F/T*U/4o(6%Dmd9J7_c*J?'4a`Fknb#C.G:@VVXZ,\D=4/Eo!mB %=;`F*O3oiE$5Bp;q6Rk/pgID6NuJY7.;9"0*$q,9>7M8q27;;(jSlI=*Md2CeD>kY9FjGS-A]P6&8H@PLF,m32@kfpSHEUhH4gG: %m^%c1-uS%#cP8=,Gd=:DO3SM(Fo-::Z:0IQ/4[/*jj%H/HKcCZ5l9PMl)%N\B,JsI#b:F,#FY=2#>4ZA+F*S1`1.@NW7Pr=<N.M( %n?i:gQYt'm,&>o"VO_J.?*,tf'+^d8]rb(f:"0VH*K?2K^.rkY7Im:0@Tnu'm'kXNiJ,YQQJG(3n6KgW>7-!REONeP6/+WXM"u=# %Z`@'3JZ8Rq5$(\9X'`<XK9iW]6X7]R%YGVM,;tL+3leZZpWi+'B"9_3.CJCMReR(j<uTnk9"P7`:gdcN1K8%e)>ADD?&N4HG,n8. %0N3aTLtn54GbI*\jGlZ`Rrg0n,6i(kJ[_Wk2ThSeWsRO/)a-)i'"&M-=iML%Ce*Y8>/W-ieH5CeZ&[]ME2CJG3&FXu()V$B4DX"C %46efT>8Q[2RWW+c::E&Ko@A2tgD_r68OaV<K*`H3L+kpJ(e^6hFdsn*,F^X8h<SBfe.X[iURn,qCt'-*:9h*U27[DnQ`?$?pS'en %_^@M4/V-<DIe^0@gfm[h%f?fgB,`e*``rGq=mDke$/Y-g>$at@FAt?a3=0oQR!.P,);Sf3g?g34W]=n8Z'kAjHG.^EXu)K`&Q<Cm %+33W?L2BUN)a30FL*80(qR+\)mqU]<k/[oa`YA>iA?0q\jI?it'K<"'cG+"L?);Uc7n>T.?mJ^1\Q9GlC"07g9,ug))2(KC&fSeN %iDrS[C$>Kuim;P$^O(8'je1>s`=TpT8[h$F'^=r7G%3-CC=Hrs^5ps/fV[*^NLNMiVI+7T-f@P@hNN?F0l<#AhKD8.Kc:L@1,5lK %Opl3V]/c4]ZA1697c]jR_91%8EGTHT<pd14q*[]Xc5%RoNG6iq.qkt$crnf`or;9!F^lKPTrjItfH2I>-oRI^@?4l_NVXKs:c2p1 %.V$C!CsX-ml.DYT1Qd]dH>`Z&-*DXEWf1EffVmS?M'$\1X4t.cin;_^S9qqk[$5i74'0RE\Z_C\LUj0=qZe5*1Z,92arg-NR(tmZ %"&Ni"O/oaa^fC*kK%V@r%5WVX]LcD>`^mN9Gi2JZR\YNB#&GSQ<WBh,@7LYtUG7'@iiU?pS'gG8!$kim?!NCM%FD2#?101!V)@E+ %L1X`1>IqKdI*GdL*88OH@rEI>/Jnc##r9'd472WV-)`2XIeYB$>tJdn>"IN]NHc-0P0A@[(+nrB\n*&JhJY=k2lIe)]9t`9J\[To %'ME(PQn:_#l)T%/o=,&"g9#P[WnVFBMX<W3P[4'Y0%SaMP-mDE[6@4Jfj)#d8%X+r(s*u^?7A_f3H`61Qi"DVmkmsp/8H)\Q3Xn1 %jmUSFdDVP:Dp,!K@q3d('S><7p@,O$K\hY.0eUZ5+ci*=GjWQU*BW3/9@G+,n^:X:YagPn;/F='FW2?^PC)6cd3c^l!kg8VZ@d=q %/gB-XWF=e*Wo6HGhFq3?!(j6;UPR3oja+D<bcuKP-lsEck+JBTE_e-ha+FEa_k)[p*H(>;/_nCOJ?diN3ptRg0Ha5U7i5@Vc/6Gs %V;j)F!&Ei!)5Yho==)/_`'O+;<NVPNOXmfoaoL&30H";i0]SRA%t5a*-M8Q';n%GJV`qhgLQ<amrSG91FO\!h;9Q+1/GKAR6%*&@ %hGq6X5rgZ;]pM[#e^(_S*,#+bkbh>%eBuT?c8<]=fQRVa.sEDk!B+$JVK)j8h/3tT\/Fs.n"mLmq7BKKDI5f,WV8/,X_Y]Y=rMBP %aGs4?=1\(MX[enAS(qj8eS8XT,GdQ%Z`3$Z6hm*ANe\O3Rapss=',6Lp`U\5/:9i;0qOBb>P'XuO;-I*f&jSQH;J]M#@-o]Y?g.2 %\aC<Z;&UP-0&n>B2Em8T`keq3">FX<$QWU11s]CfH=MP>;AVa>Vf1`M]5](VB[3@)WtP8)lErkK"Yf10pEQH\2oR$^)j'RS\"40: %[j4&:`d[1I!9`kg!IStZ*Z0)fNr%j<<JU;(-8Z-8fQ#6a]%1Acr%57(38W^AUK7+]V_d2>023<+m/(>!Y/lYY#/*U0]MS#m!,oP/ %rYUU+aQ#tXf#rI)`r2Ue\6W+<Y@#dJ6#sufFs(IXQ7%0tDNGJ4eF2J\NgAVDKXQ[k`4XQ5l"blAq/He^1Cc>/[)b1W:cg^B@(9cs %S;*7Loh`i[jEVD2KiN&c"Xn'/O1!+bGlQ'qrC?;mf%rN;]NTcr\77bWcfR0t>Ks46bLX@td_3W1a+\hbWV=bdrI!(@Yd3eFCOONS %[^,ehn_Qb0VW*q#XhA,nFIWSjd49Yp?7m-,2c`-p4kWqAm.<2^0<F9'fo=P<HX1?me'DAbJ$lnnk1#Cuor%,@imQ98bCNa^<_q9C %r*jA``IGAI07N_aGMZmIF3XDr0=QAZ^KOb6*o*!;cGMU:09+"jAnHr;`m4D,c5ui@Kn&[YrJ00J@Hh=p9B5D?5&RH-QTf;goTkpR %`PpN"dbImr@V-B'X7TO8_W&PT2h&KGd<N9DOh^/tY5EKU@QH\;.TXdLY8_9'*l"Cte<#$2:R@^-lJEY2/T+Y!n)^mlQ\W,Hm"6(5 %iGH,O1G]u!R9QV+<npbtKe)>&FY,Of5?c.C>l;7=;0`#M<2eV8=[1SbE4&lKPcs''l3j't]3"W:do\7"h>5%8/+l\"eU1m#g#Hmm %iPSB-pZU"+)#sNRlHYYX1[D07I,)fN.Z^&,:\RnVrT8m5Fl-Qo?.c]*A_UJ"?86S`Q/YR-6qs0N\E:Q2NTs-LYZt5pC[O?Vb:_B: %%KE(m?Z<S<]2@3eHgkWg0m%bW?+/X;&(^\GqpWF98bN%>FoL;DG.ZV"<?JU94a@$#o%n`R]kYAGXllnN]e"*HPNo;ZIXJA$>V<3C %.c"<Rf7g\YnA?X?"e3`[)X$k(*W5Ycp!OcYgY/.A(Y$+%\G;ORZVIW>[<:@F$g[,JMcTB$j\tU1c-s)NlBdj0E$b1-<IamkQf"MU %j`g=s5"5W.kFN_]URHflpKkRYL/Y4-dq=^8cMLM]*>cIA'JGbZI,-??+$[trkHA6p4YND/kDl_qrS56,b$OMgZIS7'r/[`de2,X! %Rr:MU]?sPF]/Hog5@$dM"c]AHF'5`rG4FR*Z\n@R\h25]X?Tg86Rr:&ccg9uR0tBfkNu#YUYEJ.mB#ZfH%mg`\Fm#&(@TB)6G=Ih %8l'$h_rL>@o0`ro?-UTr/j-h8.hs"8hUlgLe:2<QFm<Vq4)]&=*r#-dNd(=YK2\1Aak48L_S>Kp"5:$>@pbSf\b&#?*/:lLgnW/B %iQ=60[s;km4Xnsnh*n)^n8qY@KVh+4`pQmqCraKM[[-ksJs6%?WOVoG0@SUP"V$L+2IGP=5NVW3Ko;M;0OL>O98.-P'Ue-G2;$&1 %]Vf\B^:jO6ds(WN`t+c=`\93L7T%nnDI(T>e>loX!Jdq>Mj66g_9o.7<Rec8p:!*Wcbj^1eTmROOk&i*qk?pUeNMiVg%Pa&r.FD" %d9!I$<ZX-K8NrZ"mBsFmFQ_J?]_(cIia]FnFa!N$<r]8TbT2,g.5'5EcBY>\MoX/Wh!n_JEoZ5*]3O%u?G2nt?!B!@5Nq@qCbE/' %>,=aGb$2:92rSB1qWfAO!?R=lR2GOjpQ'M5H[PZLGM)+AM77h3I]h>\A&ggHHErc^EI--'R>nIjq>G-ifRL88f_p,4-E`:TO,=aa %a.Eug^gX3a2Lk0&5==tr<_XS`pH8+!Y<Ml5S[`BC:Hq^CkZ3%On[S-hc/Pc_l<qAT\?Pt^ZglZ&dGdWr:p7X6_Pc4B-HF(A0:lfL %CRa`SrX.P'q4pI(O7tPEo8Oc#$.eBiF?]Z]=oF2`EH8e[+$AFB1s\D"cIn9H4l!F,++>],>D:lBppYCR`Qb;Mm<n#`\N!Z8VJ5?P %ZcQjY-.:_t4>=_U5)=]78%[>&q"6("X^=m)>+W=JX^t/>Rk5[bBC@mNct#l@A7uI+U4-)`)SM++Tsqi7P$Mnf_6</P<j;sijoC0i %@o2'WqT7,]i%sVM@8JX>a$<kJcD%dU([3B#+V/oKrlHr#4WYms';&E]?h#qD78ld;@;n&]Xio6rH4#[O54r.2@c%eMhYPm$STl;U %b:k`A=pTEY-7e@#56L't3?:ocX.hh`/,eV4BFH]'agG@q[cPL]#n7dP9n*nk2#<F0f[,U4_7"m6]DAS&XchPIoIV:8lR@62SfF/Y %VpRFjj8EDMRQ@E(Z[)tNVERr)a\&jsB?AO8U1a#Je4Y'mU2q.*0o8n9O*3*5L7-*l3@_(UKEmrkcmGT-.H*Bu\!'R0C^ahJ$Vn69 %I@*O\p\HQJLnCQ*k)X@H>S*@/2>mRrj.R9VoDA<$2#[8DIIC_268@s_2W&jiY*D)]\9t!gaqpVuKonG\H-n*YR-+(cm+1OSR@4e5 %cATdk2m6iF8n\+_-QB,+_7bQIPIJm".a(#7M%_VC+KZs/gSp_PM?/Pel3^jRWFfb@'UBP\n$*N(k226LVYntg];;$GrGW#7JE-qe %TRnjR)mjetIl"]]i=oW]qs),WP!?#/%U2H,F%?2rk2sPKnm(b;7VO*;m>+Y[3$0SVoRcK)a'WobL&:tm0J$Ke',.,t:lrPW?Q'S9 %r7/sU_jpa8kHMJFII_Yc#<DPSa6hZ?2m8I9bThHtHbItaYB="?g\(.&gA\=PFbcg`]#/d;!Mg+N*M>4GJ,QYGU3Q4.GI1U>Gd#'J %c*%;6[r(I1qshhU86'>82QdHW3tsl<2!h]^rDN1/S$PH[Mmp?Fd@@mLo'I)hc,ofph`n3N@;smj5%68?W:;V-9'p0Wm!$l/]I2DS %Y[4udc9J'?]X$-R.m\%PET(Zk['3eBJ%EL4Q(4b*/on)&rDG(BKG>SeYJJ%rS::-/qZ.NEG%o:ok)9a[PZ%$bSb@>N!"PSZP\(NL %s%2H>2ULs)p7e3DW4Gh%I't(3[ncl0V2fItL:-.0V7V.uDuN*r8YJ;U.Bi^JWd+&[@8$.T;ULr:DUJhZ9bm)HO;QTI[7AiDcBVc5 %o^U%UdUqh-ZS`[["((r6`J;Y*"2D.RPCI_ZTt]Wqq2uKjS($'GX-Z=(V;cl&IY]n/qiTiEhjbc*]._GkOcGs?3EYaQe[cHt529@F %=Pl/$PF_Ad8Zgq!Mu<8)JeIG]/tt/6!g]-Jq.o<\^$#]<#V];Zc%Z7ca@hofGEK:#Bm`;)IFiBa8a0gak]W7u/Nc*DJ!Cfiq\uRh %:@B_+n`jGdn,;%h<qVASQ`",)j7U(sf)Sn1l.h7uK.V:u5:A_hm&G8^M]BH/9NAdf;d"6_gtOsWR-,EhY9,F:N+A7/\A*?0F7:K" %r479U?Ehj38fos-24E]2c(3;fN1&A';/0Hsg+fIBGq>jPhV!R[f8a&La.H_VnoBeKk>(F.f$bQW#b9aE[?F8T#E@83d=#XZXIjrh %1>(Ui>(3R-h:Uu:n"*hDI&_<lpNCG398D'a`lcIXfD:@cp?n8N"Z?gic'RgFD:a]hDc\l.4s/CBYA0[n_gM0&E*L;ZbX(,KFlAdu %o$.,UFc.OKO-`Ujs2KMcVY[O+\a[PLLtu1\^4WQK4ac`VfN<Fj[D$tWr;:SFj_ZI''le'<h8AiP=hM#k(/MX,fQZ]Mk*F#WdaS(. %[=7RFMm^k0/rC>!K3dX@d&c5bj1Y?;li!$em]j@eSitjk1KklY(WXLQRG#j(p>/Nhh8m:eX;j(Z;rSEo-80#8'giH!qn;*X-b89n %%60)NG&ZqdEuWqOG`t3K>lM62rtJ_:'n>gCX\2@#U$Lq,ZJ%%F:R$D#iH=C$okHMc;JZ5H;_@S%]oB5A.^eIF=K@orE8J-117t0i %1/0@*P/iS)Ia+2@g>RGE-hD_0gPWShpF?[JAN&FZ)Ad/'>efm]=8#EK<]d!8phALnej["=K3.Ff,9('TQ"p!ilX5p#fqK(mHX&&M %]^+?mZ#&PA_1TP-(;JEZ<q]lXE5?!'AmcFKJ)Y2(m<`thML2nOj,L6pHfIDq:k-(.gK5oLQG$qfgTA?9_T=Sc*I<+JphTQFqr2e\ %n0%24Z2+P1s67?_Fa4h-8om)?G/NJb8pqJ,GnHCm7XO*r^3H$W-sf+4kkH[!V1K>8l;+.W;!N\Y/o#7UFRRiD+3pIomU"X1?[gTu %9&;D1i:t^;UXIhJ7n;kA(-ZP`qU2R?%<?DO\,)TWq'U5>ZR^A1pA<Y8nY:Gfc15[TGIu%!.c(rQ`.[6u%jO!Ro*;*Ym\:C,2n%Tn %5#toNG.#SV7N5[s2NMp.G^()eTCYeMOa1GI'=\=jTIS3!>DpO*4B#G9n]A-'NOAH))g,4?>/m<\?.AGsO8D"akOec>k>+<%O!jd% %(@r0PbUn6n[p3jd<9hM94+?V1NAfRH4(.ARTBk2AP`"r_N4N+GK6o7Eo;;ilgl#+;)LL_t(GDi.C,9+Rq^g7<jqO0>^V5[%0/;GZ %k:8K7;RQ7N)",8ap6Xc-\C2jt5H2t`]:Z]NV-Kd<+3gLYrM!=7>^7hQ$d0WL04(_3PGi*,3m*aHc&9-\9()2_/EiQ``VGR]]r.^^ %HJY.Y\AdiU@s3D&1_/ZugjD3e?Fj*`Z$jB[\7P42XY&BLS<c'lrg?s]ep6N:P=8ELYcm#Rcr)73riD.=ZQRi$rFBf;PY;&/s!5=Z %NS1-%N@//B1q2;bKi]@&4t%-Vp5VbO*ChiN2mpg<49*T_c6A04lJEcd$[m7[s6)`lVuH:8@kG;L5P-PSkg:._Ma+.0S+bbXHZ5Ns %k45]7kBc;5JWZ>aaYJ1#mr/H[_9JR3I*9oThO;2=*nl>DGc(luo8?lNCB$k1EuK7#ESHDk2g44sj842q!l.uB`U_F-LTT73O+H"< %f/KtSrS>ml[JCgQ;%u;<--43b`a3Y!s(X-oCY-8=G3R-HU8PpPB3(uE)\$mIY1CJ4$+o-.S_*BbNLM&^=f'ZfqiLqEYfGbTG,KX` %RX;:S`YTNelDkF+i.jeike(t&g7m]b^W\Y*#@Cr'd`1n(=#lPnrISs5A$;0reQ;VQ\YGYGf&28AG)P,"H;@gNq5,'=_^g/lRghk\ %!;e9^LMFj&Wk/dr0=T":6.fMHCnA,.B5_L.r92DGc1:&bqt]BkUY#`%HRpLl4F?m)X`Q_g[nh,^4*Ld6$5^k(R9IPl:VJ<@Hi'Yp %aN-Q[F<A7L4hBn-o$0s9Bf\l8Np5WWUcB5>%_B%#aFF#+YYj2Y^?QMYk2o:o#2LW@;6Ec6U1gpeJ$aW"hRmp)V"$b0Fa'2Ub@5;^ %5o'+L@d_d11Nc&cRV&'1n(dPpmIsh#WUmp_U'-_'n]K$Nk;T6`T<'C+0j?`gho3(QdonrTro'Br4Nn_qn($OhG-6)[W:Rgj^Z[m6 %SMc_!'5sk">.dh8d<jlVHs/K2J'^N.?0qBQXTS^'S9#`9DMRAD(X'?sX4N-2!@?*0Qeu]Qk25#K^=`8V[9-Z1F?`q_PkdO*lAE=> %./*1>fipJoIl-E=n8,%fX67f%BDmnEd`1>$ERG`fiB\Us,Ds<g\sbR`=+P\Timu\mi:t4Pq/Pgsn^;hb:N8&4\:eMZ>FP=$0?GQD %`QTmE+:D9>f=mPk#905!^"uIFBc?WVY@`#]X;&h/`@(??MSEbAei)DkCi=([,W7Y\-iU%IG>gL<A=)_:/S#7B(=(RK49,*IoArm? %-AQK\=%_IsS1U%1\NP(b*ma#Q=4a`/TVQnH<"/3Yk-u<5D@ebf:1)i']CVk1`Q+u/`QK+-jPQ"?n1=1d^!7Y,G<^H??g"WQ.Po:g %rpe_1k2OFode>o*)&[(,ZII_-Trr!DrTfZ<iq_?_TfR&VcaQZq3hMO)lJj[0k4R`<Sa`Ufi7ZN\YP[V\1F;l[;_7daf/sO7XJ=@I %\N]AX2=L3(F]k9bf8HJ.F&(uEY7;A,481@dp_QceNp3*^]u]/t:n$55=&OJ4`bLR"*kf1%'ee8_(XR7\e:,ZD4s,;tpiu+:WUhS5 %in\tnXZhC<4Pm0ph#A)T5IZ\@HZ<]+FLHG"P55sMcgbU/F_rN'q-:GB.Qn!>GE<ZIm\&TWjk='gb7NL7?i4"jI1Z-R7grd:VgPcd %I=FSCI\l,_^!brCg!]Jh<f<2oo]G+1EG+6])h2q(s)>;b^0$(;JiD7:VDdm-JqZDkH#5-Al2KmbXFA=KjGjWIRF4-s9#Fu\Q?2Fu %XV;5)HElXRWuJ)]?g%C=p9@cuGko`bqYj?%@p(ikr8OBLc<kuoI;hLeh(8O)jh6LOnk?MFH3N)VL^5D:H4j2Q#6c%L"]SGdlkQ=! %c.M'XCHll@&e[MD'$.]Z53&_o/AIO'<&8=`24r$/WB/JMOlH@GkuJA@52Lr^XF8,'r3>V)qsR1%7s\s2@BO1Ss!UP'55b-uOI,pZ %ra28NM>\(YcMM[01rKM]gYhMWoLbK2%FXVCUukd^7=\C0>gH*d)ms^9\Q02YHPjmi1YuT:n%n"\<7;5AQE'^DI_WTEds,5HVgo+6 %48o-3_KV:1Y\*a$9FWDf;>4.GfcDc,XM'=3n[55ROSl[g7'!<Eq+,M"^;[HAOIRAk-DLNDN7=4gqCh^_L4+;AOn53_5r/4.5*G8Q %n[U[g(&e%(PbAOqp"f^)-kC<5Z&qeA3gfjD\aotrSIOfl`]K]`Rha6Hp>..=1RRU/1^em)37[sZIG]MIZHq^A9Er/QrB`<Lh)Zrs %mOFX1E0;_0::O@$@!XXqk"]?VXor?Ob5-_*23Ae9@4(._cr&A7dP#W2[H%e86K=Va[/5&?C1d$hEHYC85Hcsg]^aUmlWNWq]TSJL %9I'.UK25aK%i_oZr*[C.q<qYK07R'ab<YJNT+'jXp>>>FcPK8<;+[BJiF>)aR#a!A/p`NWb"CR1rduJ\,(6+U[<r[*a%k&Q63RLr %&T$HO%<PX]6?df!KRLrP-Pm/mG9K:k&qKBl?OQ=B[ON;/l<ccZKmrWhO$>7I[`[uiJ)\50:Y+[AO=/$Yh0TVRA+ihIs/n#R''iSO %AVqdGepd&'a%1l0fkoo;c$:A-a5b'/CYXd-cRCpKR3_*^G<^GF)o.[7GMG*?g_4FT]mX/RV)G8*3:>Q-H#6[$TR;at)I![I4RW,A %D_)+;on;XKN$3hr]<</s4;"'ieY$JK$>.#r#<getSV20@,I9[E/[OX8::RcSrF!(br?J1S[8J.Z\@oN4bm3@aG>p:I>`qBEJ?lE1 %mGb%Ro?/1]R12b'?i+EX6$F3L>qd33ecNb':o2UMD,0$Kh[PcboR\c1/8?GK-hNU%#/(@t%"$-WD\(^HTY;P^Qg#5#GP-F?akpF` %TSL_&b&t4.r$H#>kbrl@2Q/9"L(u>>_Z1S*AC1>N;5@FYK3f8c!e8)Rghb>/@$E7+5uCi=XgNPnr6ffOK6!+Jro*UrL"W-78B6k+ %FE=X$(_fH%G?$,g/-md0G3ZQs6]47b*NIa@?^n3?]/VeZIN@4pIAXVKQ(kSmb<\LJ\+HNmTL]!6nRQaLK7b4ZKDL0,JSW6<P=4,c %"K#YJ6*#iY>8adg$QB9blIE(BH-jFG=)hZFGA4('?f:HnF^\B`Xl[;hi[[h=9F!`<)h1s"Rf7WUAIO4..*Adg&ZVEB9[!aD`#^B] %KBUg,d/)55U#hp`&*:,KZ,gNm^!BQbTpB@UBJhKE^\(o$dm7oQo[#9?)+>G:VK>Z2[MlM>h2^-p`LnT@gW/Gt`cTSi8T,-8dV>m[ %:RPqG@aG@?l<H4kk(?uF^4!H\7sis_@)]K]44AH!EmUGZrS<diTLJ.Fp31%2k[b\)f_@WdadK<>n/2lj"r5>\jonbM#OQD)98c,X %17gAl3?7ZnnR;&nkq[2pH(=gq_4\YrER<m^lQ'Q`055?5;#Ym03`djA'2!u%MhB#X/X*ZM!"O@]X<=N_s$K%"_OqOLA5aS)P!%r" %\.CNZf:OKuL?(W^e)VBM0tf'Lffq#0TAcH2AQ<tB`tHqY:Di_W0b-8D3/K&9->W.jQ%D5DP7?q$O^Zq,Rqd(SXb$?Uhn(8%-G-AO %V;:Oi[!%<bF\+ZU1VM\8r?-GT^0S%cj)J*.[;W&UB;SJN])Er>oO35anSK[CG:-Gm_mcYSgb'A;ra9msO5HG*[GJ*K..5IWmIBbV %mj$dM,d8'Arf2EC`+>jj>C8Z+MKJ,9@K,ZYY!7?f/CZ5bSK:g,cN4dNXbdQeTfUa&I=>f-F@CGc8>g&CMf1,L=38Btbjb#T^0KI@ %OmpJ@#JX%dCFX(3^6d"_?PRa&](^oC`OA?G?goste4a(oTA=;NN'FT`hj1$53MGtNrp>!.pj!if,NN&BMHsK%InlRBqrU[]Zp&ul %aT5oAmEaZDp,*Bjhp-MKh78u$cc]+.p?q,!^&79HhlWmf9tp#'^f*;NN[BYGh[`m,`Td*X_#2qgWq.;.4P_po2V>+EgkPbD-fu*^ %O,ooJCq:Alj7hg"DjftVAM*e3h_$@OETZLuipVQkg:+%YjCk?JJm)lA#9K(<Ucf3SVGEuEi_f6"2FbN^j&+/SloWq!KW@d`n).&? %;>n^VrcJpK8I=-V>L$G'XiOHjl*u+*)NU<NNZW@kc6#-3gA^=5B*81PZ*!5Nk-&k$VeHn\jp-6eG.q0V<O!6L>Xf[B'.W.Z@b\l" %klXFVE"q&:r0aU+j/T=J@<]*Z?TA&OSJHOVFRe;L\/-=9X'uP%i-;E+o9jpsCBk4sS%^!Y3ke5FYX(;'K%Nmt(&.,lAse)'fhVe( %&;e=]M7[\l`*G(mf-?[nFGPFb"*=1o>l5$S[,as,&4$..e([L<ks6lo<\p6%_W2gh],?%S>>>[%>%DpjTfJJ]7V]<M=dG8(R-gWN %9b,Wg(=V$7c^t!6BErOIDK=6[q8Ot?EDX%>ao0>/fN`%`G8"-9#_0l\B9Q/$GAPhFnL_/:7G854gHRas\R%-HY-%!s]Q(!tW++lP %C3=/a(($`MLQ0==cFOKHUIqr0h.hguKBAu9_Spq;ohIuI;63U(.@Q)#*<jJWfPYcnKtI?AMu6FN!40B!"2eWaa\EmfF-QRl^unF( %F?[J"#PXG"BgGeX.%1i+9>BNG%2lm9ALI:?s/I6@)9fQmU#-oun2M=jeKe=Pi77O"`S%`gZrm;#)ZQ'iDu:<o`)e[;P,sklRCf8Y %rD^-8ec!V/p2[lTo(h`J<76Ke:(:F2<J`pIB+g:)3!A%7EUGte*g+p(PZ6N8`'Ygo-'doie4Z`ETP02^9XEtFZr4ME`NhA"([?qi %#-g-%rdu0I,S)@JOCHlqk:=V`jBl.s6!h<X<$A4;K.DKJ?R<hl0r'OTOFM`,s+AU?s2^7SBp_qq++!)r0DkJt?M<<*O:U?C!#%De %:@YSfI0*EGK<eCd]+ZZ(]Pk8[k:9il/)<gGl7s0!bICU]/"J\*.J\$Z-9'83R8!(&Y#O$.#fG`abgj.W)aOqE:H+$Mkp!iqks`pR %WDWG%U4gQtAu^PY5*%'S+Mm$N;qh%he?di^dOc@/%Ac-/)e7hX>9f7TXPi5u.R3A+WUeMSc]!&=[4#6@U^N_baXb(U4oCGaq1<BW %cS.A)_lP2_aM*Ssod9*@2a;es;IP97<6@O]4Vj>`=<M-D?Cuib'Tg^72G.(]bu/+SRHjoUU/"1l/3I04%@#d@#L\m/&l5hF\8:?U %\^6QlK]]PTFCs3`[Ram%c'M$$-pg96YpMe9G\D$!RN-,Wm!eajZ:gIpXh6Xr[:964n55t$S;Hb&b+`OS5$q.C`auR9Nq2J`nhII" %WOY3JPEMj9)Z"6[RaTuK/PYM<@lc&;8qufUmT[7/fs&=ma6*]-N7AFjp+JI9Z?O`bRJ:1&&"Ie3528A':"`blpXk;1;A/=GWqS+? %S[f%Hf<N\O4&c1QO,F23qER8YO3uX'<EiXgA$nVe(7/%RP%:6P#EhsT7p,jQmkWRsme2hXfhhZuADlOkB'77XoZ3=Ygb;G;S67H\ %V"-AZ^Yc+_--:,*G>>okOli2!cB3rq/0Vt>X*b8P%aUJ$;*7r2Z^jQU4?EL`:Y)_>6S>A*P)7oL`#njh*Va+F_rP34XJ]^o/o&+\ %AtU]e_R3'5c>5OGNYCb[.P3)g>cCJ&]%dQ=Su4V0?Z>]1K'kS70KFD1F!eWt=ll;92Tma"C@F6n--Prb4V<T,]pJ[KY4BW'.Pk2H %/`e]7Wt+@5"=/.48@Y`B2^4p2Se52;jDWcdd);O3f\!NEC>s<MV@N"H>M1c<:b8p"-+E4G,@8E1a1N4j[R]T&5"'A1OP/4BNl1X' %ftNn,P2/."<*dEqQMm?/2U:+l903egqD!nGD.6_dBM2f8"p3A*%:TOMdOpb>FbbP):C\(hN\qV^Ysg!`(WT\kRX1g>gI;]s4VBo; %m5:"Z\/]?hH,?f"AP[P^S;ue'$`?+.nr&L`d!;V\0RBSZm),;tofPGVOZ00oGr*HrQ<UHDb&b[H"Xi8\hmF(Pb*BugT;V,,#9ejk %53gYUs!Tn[FgX?5e;:d0)&$W5drV$3dfLXL[+:ip._@at&%Tr9=RKmP8p$`\]VY9jfHn"_7<U[SpW5#Q]]H+;n&!c=E*m"!%W%I> %g+=V[<p8V@l'Wg+fH'3,B9D!G3?uWt_sX#WI9%`)cKpa!o-e<aP(h^`L3M3BDOJJb5A,`CegAKjQlI.;"eCA:G0)=4$=Wh-ND@CD %VJT][2b7g8Vq&rLUd)kW9G1$50tAUrj>A]13$ll7Pgg,Soq^qq-"`Tj+Vgj"_;`ZALGK;t:6V1nYGNR>Jg^"[Vg&r?1s*lT=Ia64 %-TCo':H1@;>;DRXS@g&-eh%M.E5g3KFluE\P(df\dp!u/c?OY7+\oZpD+P2>ik&7*A]62p@%dDP[p2@Is)LNrHqM!*"\u'\nq7nY %#1q/g1gq,iQ@*ZC.4oeK(-X_'bVC,Smt5Bs\DA<+IIP:>:%SoWmIUNq_2#9LZ8l$+gur4LYt[22XG0oHg3+B\UBr\=KJ5P,ESrb8 %8rm&FEN(J]"mspQ*.P0.O?*-TaqJX?Wgc#lA:7&Z]W8a<l7<7N0sVdfX[=Y0F_j'Zjj$12.CS:]>>`To-9#q,1!:KDXIB5@FZa!Q %.BS*Pg1o90[m`N,_8'4?If7m/?_d<bC4!%F'r4@s1Eb-a/eM:1p!$&kq2/:;)H9#NR;T>phq'OAetb35*DV?7'dp%F-0HguA'"d- %QH._"Z!?O6U=*YM\/+D<ef>f.g?YQh+^U;s`M#@Kc+^$DZ]qk(\X/)K-i!BBgaoU]D)=g4X@XtlPP<%K2`E,QUrObnc7eb@l5n3W %-!6U!CCr0]j@62XV:,bqE(TFc=J(.OZ1/ctba@htm@%I@j[sqe=$g`4dYEA78f+gQ/,6D5>#U*@ns7?Td7n)8L%XQfbNJb<H""/l %7+bWn7Yp0eYgFZ0?r!sa%h1(N%"(>L=Jg6BbJTtLJAi)&ki0`)bid^0Blg="+8u]-MKrIk3+.$.[oirj^i>qf=5(!H48Y9q<cu8_ %]a7eK9'9'lePPt6d^0Eb%-q,'f7uKN3aa\g_VmDm]Eq]%=L<W(0\`p12ae+P2[9\NR>[T/a/+0`8Up@.0kWh3,!<1FiMWrK#gY6< %/ee+B0T#P4VXq*j<Uoj9>)(@d0[Sk?b\<,MrTS4MR.o8)Hfq*3LiKo+KQLk`T>m2:h4j=H'`ifTV/B9db<FnfNcAn!D2uk^"CZLi %?]F>GL9NlUWH?miM$uQCm:<.S_)eD%%A@YWg")'1a(r5D<BS%Oj1?n`]9gZVlYC(uB.$'$g7D@">8Oh/+Yr-P][D,:mHn27I^4S= %&"&r8):DN//8iCH?-NR/"B#Ohg7R^lQ6Aura_c*e6mk.=TDk@fn.P.dkAXS#)K3::h-ZFl]mic;mu"UIoYE@g/W:d4T8jld005F_ %3,@XYK<on'AA?t4A,b:%r2Ttk!l#0*MQMZnMtE:.0$'TXnlbt/rDahR>p*!lI_+5^mP-.[?8Lp)(A%'"n[oG#>T@:..'p%CjTXQn %o%4pC.pe`NC[/eM3]dZ'[P`<-'s:UhVinUf[T3oK$(['_SAC5L.r`2nH[D^)o9Ic<!]u8)87sf_pVAODHt@jXm!-H0TH.#>gtarW %S1b^?mD[u4kllOWrStm``J\P<2s;60BgdH[hQ)ED>qPJn/Ub=<1]AD5H2+h?(Z)73kWN%+c@c2Sq=Ln#Ok[i6C?<*i@R9E+s1GYD %$0Rtfh<NqsAL5=(92s=?q1G"UkM;EpWeMKi9J#3MA5=^;45DdW78S:K#$LK9(\h_<io%YLa"@GrbJtAqc\i<O?QT+#O#NXnI0FaC %3[Jlk6!N3[2J-toW;2._T>+\6CPV@=\`;c*<TUZ[,@N=HGda\*e.+p'ku8jb7IT9j"=.H"!T=)NjD+G0.^t3^:.HE=4j_#.R+OS) %D[gi2!%&1hM,rVq>B_uKeX8S3G'C5H`^*,'AV\PD?0f;&]*^PH.[=*#>J18:E5X9JL:aWu=69#B'ntnm]s&_XZ3oZsX\a/cD*rXm %LCTI3BR7kD(rpZ.N5Y=")-%=Ya.>Znotb[GG<KArn]807<8Cg_(1]5M=mbFVQ-LkHeSCSoM^+eS%QuAdM\V-"/+g&tY4]$7dL88I %4LR`!fI_DO(Q0m(@_G,>40FCl#X.Oeg3+/%YT_k)nA@/+=pmK0'CU:(*hI0H"oPS>3LhOg*b,>!)DbHtXDcL#3lU:+qSGkl/&2qA %WrXT4%5YOn"adU.Z*WoHm*HX=\U*ngdG7T&e?QcQ*8E>[IkIP#Jqft&[b"3SG&8$lSD"9-GiK`1ge9Kd-Fb<;+B(f*42!qe4qi^s %D!e:387sH$?`m2]A0WYAI/48aMs2g)i9d5<ZA,VOq`;OdXTUB'p"5UEEXK/[hs&VdWXlFb-rD`M38TUX$22\.!NkY-&FJd(2H;pY %=ZUPG90e\^N1YY:Vu)'8'O\BB\FRobBAU.AKOKeAeN1$i<qb1OK4r03!p]#`F08\'q.$rqauQa3*W@G%@4RkXW`RG*E-ehU-DIoH %l,DG-gf6R>]ss$?2Sfe,LqKhQa*96#IPqrh,AXF(>.3PI:.uYJc/?HsB)-6tIPJ_UL%AfT8G1JHDU%>Qb\23/MJ:GLfTiUkkgZTG %q#:XufOC\s4No5U?I$5.RgN8<W;5f^I&8]F?Qlqni3K:t"qk5V($ka]5#7_0&PgIA1q*-dh3!\@Y@0Q/#Ht;?F-:,43HJA_n$B4H %3a6`jWB3<^6uL,f>,4A&M"$fuKK$][-Fp>skbf*jCpokU?DB^PN1@XBWW691I6O-'15!2brj+ITn<\243%5)W3/>I!B1`>i>;XO' %l?i6#1!LZU<P)7@<,ka>j@ifK'uLMuJDtYoXt/u-!i$Ob=BlY]YKJhJ*H=6Q3KA?H[76C\.rhu:nl377=-sUE;E]P.<U@]T"ZCq) %H.N^2e!d=p-+IngEE2RqR+)FFK+#lKi>"n&qrh:W\&=u+/h:6ERqgq1Y@1s!J?"58,+mmO,$_*qI@T=R$Wu`#T=bq1Xnrg["BWe= %Xp^fVF,WgqNAKE"fK[\1&tJKTGJ#Q5*2,B_eoKd2QZ=(3'Q\^D#Jn8\<l#2.#H!+l1%.kYU'N[&3Q/SR3/\MsW)gh3*=DYUesWqY %1n6'gM]U+KXn\2?Un2roctuOY41p7OYI==75_IZMj)YS;[_<p'95(QgW+53CaW;Ae0!8Fq)JiFdiB9#Bhl_^P1MF"d5@"cM95(Qs %m1%@d,&eqXqVFM\#@]s381;\4m_IV(=:^$72.i.KWsB]=?/>9:2AJU_S*ERG+\1t30u$\;NV-HM3puH95r>cL?cV/$'a!Ih/@D-I %be_tfCL?8`cfQL8+>(:,N.I[Y!T*`4/Hf4bCpAXGc]MF+DsnbmBO5V-rS?kWNYaX_Oe&p4BldTF-3J5="84CA3"[k1af?ru>1qtB %2X:ukF^:JQ.ik'dm*V4-2Y=KD>rF[iW20fTc>HYe"7f`4:/#U^liNu['hI!4G`W=eWAQUtRe4W[WOHshT95QfVtS(qSH.Z.SYdLN %g$@o,Dg3Si_Ca"d^"$1!3k-OWk7or>Lo#@R5qT">7pFV1l-C0Qn'RploSUc!g)5enYu]W&MJd3/YY*bp0YG\._9S/8S"bMZ0YneS %lP3C'B?5C'<3U^[rAplbF0Eo*<3TNebM($`92mTSJre/5N!H<>j5KUD5Z#:/QsfSM]\]?6bqQu7hY-7V'teJ^[U647_.K'BS%&@! %M$c/1S1j(`.bG.CljJ-!$9#d)X1Rg@.bLgQTBE.\1JI9n`AU-gRpgp9.CK^9fTK^8U4UWD_0QXC)cX&pA)tnRSt^h]0YtJrf;N'j %hr@lV-$b.N2QL%ef,o).MI?aG<0sQA'o5hM:r-b2@,jCOS"kQo34!RT$8u+fi=3==TRtEB_7!I;[8=\OAFl46_OI6NbpI(($+Up' %GY,&1%tC`4+]kCi>ua4oN=%QgS)n>cP-)ki3%!D&;c1$f@eVr0;p68nfKH[qGfmA\]8>q$;LBP!S(KnP8G:#TG8&_@MbS)`=R4e] %p/<`1rH6skCl^1)pnh(^fO?d"=M&bjgZP@(V`^H]S(R]CA[Q`eN%T:Gg=2\^4%:$u`tk.G6TMsa)g\mI0WaY]M_916/RIV"T=QM$ %LY1TH-bDV[]8%de^Kk_7]%B0SGh(R1bg=>+SZTE6_`bT`4gs"kmb=Cmf>NQX6l3JU(7R`ac<l7j'O.[*M^rnSV42A%b`#\?-g5%6 %f](HM'm9*p@4V-<RV6f0fOEs,`tc2<4gruZFH8%tO"Jpc0urKepXnK%qi`%nMqqm$*E70aH7cB(CpEo0GB`7[pXis(=DS/Pf_oV% %md>%M/p<:-2U@Jdm`-?VfG_Tn7(SpuMt&@?/\9St(G4\'`V@DT`9SJ>]JA+%#tA(FQ8Y:ZJPh`p`J@FKaO6G`PYF0kF,[C\SG8ru %j[G^7EijpP(hK2k:-?HC)t3+!;ZE4pPa?CLX5A$e*i&)e^-3LA/LQ$an*@<@o3>^pc)V,_`]@l=EMfZkO0HnJdb40XF),0Sf?RX3 %_E+m;n9T_0etA3G<Y*nnSX6U"rrVM&L3`M7lYM%iYZFq><Ph3?7rN$B'C0Heqd*d'20$$QF7JBpB5M[f@K%"mH#3uYRc8(h@U<N7 %c0joh*p]n%C$#5T2S_ACH:jc=SMd4L0DP"?cMIIk^V`*:=YXj"cH]4e2ShEn;/-%7lb)Kl;r1oQSKPI$a#\"*#eU,_Yg,0#`C$`5 %<okpfrI9HBeco-Yec,d<XQ@C%GCO\8ZVb'.%G"ZL3r=O/%dU3i4[$Bg_\DEQ@e]m'elb(S,dl5'#j\Rq[JkAPkI%'1='4W#EMZ0- %B+=+l%4]U:l`A9G&2_El_E&Xmc1-k!cKh!Z\ApXGHY'k'_+Ul9L3.Tni`m#[XK>HGRc$3W=d(o<p[EK]Fk00,]QnSg.UU6@Ru>nm %FVaBf1<2GfHYKa9@^M>Xi^R$_blI(e.dJtCH1SYtS7%mF",p4_rsJ(.<Gh%Rf%FJ,Bg\un@X[g^_E&W3H2\9(H.-u7Qt)\h%Am1& %juq:@J]Ia-elafEE`M;;_)cB1br*^0^cF-@=T&W/Z^H73*p[WKDn3C9c*>RJjG<1&,HUK7]`1d3c<>_[3,rl@cAUQS^VW$Ir!BX\ %5JoN8l/[>GFk-h3HdC5s=QcNeUjmu=[XJ%6B38fKMT=FHhAkitN%DWX3iA:35s[R/JnA+tpUFi2K\d'dljJ,lCR.Jq6K\,rhVaji %;9_aie2;6jp8DRT7c"R*Cl`<8:A+hBCl`>>Gse_b>dM'E.o`i.kRF]J*n@pu:>tkcc1\)JS$t)`_DU)m9.]slhVaji;9]<&Xc7,) %J'8`$#1m[PC0'6/]IC#:*nBTbH@p"A7l@&rnH.<Y?fOTCL%>;rCnK%8h^Q2uY1XlH]QAeoR^hK;C>d^Z2;:32)M3;l>k>g)QVbpW %lB<7KRdKElFZH:XE6\+3AjC==NGCGCg`4uQSrtJ2B!2aWp:+`34Z2cLf>9E"OKHYgf]$6PME*-("F?qC(/a7)_8FEua+?gH>m5-s %]7:'N<5JEr>m7D]]3nteXA_;8._?6tlVV4p_5#.*S<?C->m8P(]*Jbsq($^71I_03(Xnj^f=TFgFK0XWDgeuG(B+n.?!U#3Vj1Pj %N]:(:@(Je5@P!EuV:>g8R'V!1hF6M#7</ocZqa:Sa92>3:@LSjYH`!T7/mmj>UJL`;_"ni0^"nPl+:`/S"N'6-FX!#g$l+n?jN:4 %EJD*SXZNl(SgJ<?_6h+nY&IO7D8^gB4-%Z-N]4fjm\Am-?(d:MpoOpe6h:0++Bg-G8p.@C3MT\3ZX'&oO;G(]fU.lAnaa5B.5&_& %$J>aBd>WUQF\3sd!k_55LfL#>fCLO"aL1CAb)MgPSa3Opb"4k`-qKi)N445:M+Co519j>PS*ir&)+:_qbC<QsiUgYn)4.]o7'UP7 %;-])O>sqhfgc!I6UT>9,='u',_6r*gTV307pQ2KCa&O[-'u+-@DVhs>h$`Kik;S&rp>_h.aG@%,K/D=!/=9rR/FQ@=;(2s5Fj>n( %NSM$68)m=GlbC?j.6?2!I2<ATZU75eS0L+CLU0neBSE^3p't`5k\/F9Hu6/l\P!]aC^&MIU8(;WGO9T64,*JS`R]Noo<S"WUSBcX %-,9[FH52adrZ09ZaYlY/Y/Eg\'O,_d9H9It_3%m)@L*hDW#QGg6Po8pf.!i)Hi#gE!/biH#8+S3N&rPEYc)_#e6;mBGu=roB$^Su %]MVl/Ess>c"mmb"@"d[^q*n^&-Y6TRm>;c49:0"[dA=T(+^JAUAr00tR4Yr_:?p][`"bE]7:9?NkoBncDBc6AZCe4DEms-KiolAo %:1I#lj<bIZRY,`ZSiE`poUa!Y2]taq?dRjDU@fr'8mH5iqhC<o]O;#Jn<GsZlT.ieAn6$1-kOS0\0<<(/@ED/X[B-ebIW>,I!q#J %/RbUQ\jn*%HN'reVaf6gb[P^foD;o9ptN=,@quXTRhI;Sl#OGOhHS3CW3B@]FH>i5O^HtXnkrhe'9ON$B)@0jkAQX)GrnG=3iM)A %CDk%?'Q\E/_<2qW<ii&q%^2rGE`Y9Vn@EYMrk%IpA;f4)/TDf`UJjUld,2uifR^;b=@4V51<Gfmc1*m^@&T&mYe#%Th09=0]H(al %h9+2]#LH(FWVniPK&:bTq;&j(=[3?=UtHu+j^.('l:kMT+O,qLO][%G:B8HT\iD6L#`3,bk&^hY+oTY9KZr=diLi[s?cTIf8%r'` %esdHlW!LdLUZ,Pmqpo(NMdc*tk1Le+D[4MR$B]DflR]]"h35;aOHg`3Sb3SoKnm>$Mg4Tp$A9un..pHo_<oJt$j`NZbh$"\XrAXP %KA1,-Df.:-D"[Vf8mb*3>g8t-o_-#,$!sgl`sTjWDgM\@"TuF6c'")]nACm[9hrm^K2-;CTXW_\cdm<r1d/Fl#m&<9NRJq6[a2)E %WGm'.6Z^MASBOfD#XJ+E-7:(iW](j+7!<%#<^jUFZ(e,::7ISROSAT$#$=q1]rhZrU$cc9Ek8?on#geb`)M(gH4RuL=OGK8cPA%r %4?esWR$OYR9.<#`%I$A%MsLT8B_)-..hC4R1+Z1='4e#tLG=5-_^<H"kg/=E&.`M^TDW:=p3CKcU0YI4;b*eZ_JS?\n\5!gK]q\h %8DE4Ph<',Wc?f,i"s+'6lD?srl\bN!>hm49!SV-4f&Rh(mbgR<l>uItVfl+S45G3-<qsd_p#tI"n*QATmAkRj]k(h1[Ab+c;S3aR %C</nEb::IZY.c"cCr#m</6."gfo,0R_fF:'`n$AN@l)`SF>s)fW;IY&;u+JQW"&Wa:5Y2-3*_n9NIHdU`>;]!l?"e//O!6K5b6r_ %h!`h-%/WkN"-rlKK^kCXI]T#K9#q5.Q0^;2lnG'Hb3Jklh>HRe6>%3Le!\eL$d,T:<b)OJT$?irbP.e%R$kU>hYT?dXh*.f+BBe; %q"e9B.ioG6RIU'>aeir:mBAhMS)F4<,ZXL*%I5l9PH:DF++>TDYeG)qeoF]7%oJ%=&PEk86CKBI3b><*SR#1E7/!4PhV\"*o=[_c %WZQt?Wr@+'V/AJD0@Xk&pRSmtdXTd6k\Q#hT(MSQkOPZ?Ff+[EolM,LV4RFaK@KM?A&K0'O"Xt9nKcQq`foBLl$/MahG43Jlt`,n %9#pbqi2TP6fD`ImiDiJUq9Nub5pd33L'C_1gUfpikBD;Mgh"!nMpQN..;h)iqQ]ugnLBd'*=W.IX<2Gc#JCd=X#Ka5%q89"4-;_n %4FZJ>_I<A:?)%b9M5Tn)m4;Xc2o+CX6nc4Wh&"T/"us8r5"V/kD.JH:Y4DO%pSH5d/mR@OgA=B1Z(rh.#o/"d]@?Ft\>BiD-tYoB %rPLf(>u2mtWn:u#WD[,K24fWKQUtk'322eUf5"eB<f`;Sci.'h`*GLCjMYL+D!ug#)\\_9G43nIJ,I\SOAX?UacFJU.oVM;L7.Ab %?3Pd7^06I\5lloc41Vip``)SXO?$@T<?64Fk!Dr9n*89-fu)F6_jsJ<:V=t0DE].n=!-GuI^5#CPJ3$#18KS2DO/$f%U/\DbH-fk %Pce6K?!QGs[aPK1UU0U/jQ3To"hq,Hbr#;'g[psbIG_IS11e;ZK>*bgo[-6g6]o""^<?=RWh%!?^a&d/?hWY<`Ih*P(@fF0`GUY7 %b.[9$"`X4:rit0\fhNVi>-Ii!BQ-u\QVUD2SV6Vb>m4Fm:d)5b@Y$P[/dg@tA1RS/P^Ppj[NgYO(Jj/Bb<mn1GkM;6X&PrAHD=T> %%J!E@oDEOpp%\J8pWbq`aYQH7=h^:c:Z$g&*tQ,>j5OE+pO;"l*=a"F9d"$,"'6UV0<[heC#GW>_ob`d%pe!GMA[+O6H/lclZ8c7 %LMrE3#'Mq43>:\3Qp5bhIUoX?i<g=DT76bSe@%HsP$IulkmW<%SI?!Le\@TE6=5Q<g%4C]\*Wj-.$i1[Df7$^nf,Y,ni&Y'a%jBR %:W;hmREiRemOt9SB+F"jAW#3PQ2*$#rQQ^^c$iYWa2R65h8Fd$[T1UPRa#:7qrK,eC#$-@q:!f.7_1X=SJ;Oq[pm`,%>SsGh#ghM %f)HJ+YFX_5@jc;8da*.*j&7pf/t+T&/h!Te)p/"\C"Ijr2S([B"B$"&q9$f$VsXHeP7aRbO5.e9';N"l*N"mN]h%9u=Im6PXZ[d3 %[0N]Z&lsLf(W`4s#6"lC'2A2!Wuq=fH3Dt_JPi^[Ti)KR;PAY9_a09qOr(Z.7krQc#O+kX%9=DF/f+F-"L:$1d:^5if>^nmG4oiI %?^\bRq\<P7o?$fJ/Y1$dD.l\&\ZC9B4oXY8eCcb!FGl$peW7<a$<qn!kCqbYG;oDirar-rh.T6kdR<'!40]c]#="*lTh5RAEdf"L %e7T4#9JE)o6(\5Cj<QY%m7sPiLTR1Bj1J492CEJ`gHNX]8`WD`gAIS2g;W#<p?f#+WtFAO*/cugmHTZ6UAufEo<6&OMP0[NYODo2 %YFec(B(d,loWE]/`=?,I"r>;:#_Cdm;nd;;Imu$::*7GAeSOVZ(oQ]1au/C^a=58=L'a]nAKif!/t14(rb]Eu2&Z%bcqeccq;Q;! %<IBfPo=49_V=2%D7r^0pNG$#Cf=uuh9P;eS$-f)/>aSei"2+)spf)kfM)<Kd;.:',j+iQJEA>pllXt"@bDR?egdi#@+PR>4kH-$5 %BW?>s?N7ms'UmE#2p9cmkJt=t=g-2i5L=G1Wrs%m%oV(D41e'+T$4'QNAetncVBt?O5j2;f&In4?g5K)oEl;akC3+drjJ0(lG$A> %??P4%Ge#?[]punYKMJPO?]ARbd1>D(-:]nLrH'DfQ=j94&q[GpFng*ik/b90g"6d((/d*H7><jl9aK>P:Z%.gZUiIKJ]Z==c/De( %#q2jY*$o/0\$c*&iqBuf;Y<X4!a>S"bZm>4$JAO%0UbYrGOB#^]drO<?BtutY<PTr)[s9+iG%rT$#A5VkK6.Co_E.Hr5jl+_[hi9 %n[3U@U;Mk+LkVapbNr#%fkt2'EHkOJBHN;Q1M2_#2Zf&M^L2J=7T&s?U]mbUpEQ_>&;>1);.(o6>$([fXO+^s#Y;b)\uXYZr98Xi %&+*L=9^q^CrcU$%!(Z\ZY7MErE>Z(V5n_Vg*>'FM03k24^'hbR=#oqA\_9Rr7:4mZh<.W8%+t/o1%X6"Z1j+"4C[q7RH^k=Ecf.n %@gA]3oT&PBS\03CprTM='E$k6+8m-aiYV)=_nPo@kH2%>mk6ALI6$aEemP[&K>(,0K927[`5#7Dqa!isjN"3Ra="7;ZKId-90Wtf %-\mS$[eIN.]CJ64F"'gYa:1T/n!NRQ=o'd75/LR^l^=\6/UdC%U#4ZE9T$Q^W6+XK^3BBpJVIfnRF&1`Z!]cUJ&$td<TSGPpeUU( %(A]HAqXpZ$I#j[4Bu<dP1Jh>9b^_Z6Gfa3ud#5XI$Mto`!M[fbg.t+NGjq0$O)I[smAa^'ro3NJ.\4-JMtE^Ln1N\8e8@GFZ(GbA %j%-"G3H/8]UYQ/d0!r3>B>h0ANur9heKL(m1)-*7/sn<"e%NuoM15ei-3VD,9ZN:XrWaS^nY7eRD9:I<p_/dJd@'4N02q5<YeMQ5 %U6@f"bNgIoD##<&Z2<'Hs1Q/FcIKh8:+:\r`kY%2:WUW:.*>5h?hr&1R3AXX>CF8akg'!NQB);]K>VmIRLC$<H6uQ$]\V`UKiSJX %URBm!&%KME(@9oOHhO4tT#c8tltf$#HM*Co?=[\Ccsq8Q_)AZdJFibLDoM4Hpm<-cc[+8JE3uMP.e*aA00f4o4/2LVjTHo;NocY! %j6(f;2JJ:XG181DBVnYZrD;ijW!o1)<]lSm]TdNDE6uhDApYo(HI#GFb7G)X_#sOIp<nq9Z!PXE?><.tG/"PmR<_OLQ#gra;aOX: %W<+q`^g*M<Lgb`ocsE\mQiBD^;pR9=_'URk[nH9*)"d'ppb_BVMO?4jf_+QWBO5PVI0Jm<*384n.`BbY-IGAsbI_,p)n+70,;;uC %X3a<'1HXX5'r,+/;oRGaEVTG#"#SSu5Q-oLpB4IFMp,[`o\kV_Q?eE;,kg_U#JR_+d`ID#S^T12YrdY0*b6ui"t00U`d<!3Oj8c5 %P9>SuD"@mHR/'@J&+_T7+Xb#3mE0>nS\30p(@M#$C-4\[1`,>'AfP`u0376"STa]VJ%]-H['.8[jC0Q7ZDZH%8Q1@Wb=Mh(8kS]b %QGu"8f&\m8BJNr7Hg9a-Y@(H]<d$'rPmL*#<a2W\8n7%b<dMfVl*AmkCW1PuC?8(b]CmaTF>?ugX*'[V$%ZWf?Kan?@S>`9PIc,P %SSI2f6-4::\^sep-hf5u[R!&Mp5&mKI'J+m!(u54*IX:cl?WC-C%42DjGIA;L_O=G^eae$J\>S<5M61Yr+naYRf<d3HAtN`+-f:< %qcMKJ/O$lajDPP6O&tf>`<AWCJ@3V914(\sNscWNfGq.(#9T;Iqa]cGdlDeq)Ejlk?N"8oB9I(-R.&(8U#2Vgnuo5umgu,9,U2?g %:X2c,BD[%,/D"E1(b\aSqW,*q_]R+`I^JDB;aP#\J*ic6^m2V62t*[D#%m0^LT-IImN6Zs(W/G8Yj6/n>NB>j>!e&Ha"b1:CQ1LZ %Pttb+5!39!Kkp1";`_1QdP7Lk$+"S'-:P4'm\^2n&!KUi:MQDZ<,Cd:b\5`[a].g7?.17_IS)"A/gf\+8m*nq`)iCF?CJ:`V[(s* %h&3'm'O.),\@6PXAMU6T*C$ZpOtZ$6;@]Uh2b_=0oSfF9FtBQPP:rS>n%WSaA5WSL;uqjM4lWB6jciTZGTh;);poE-FH\2"XU=2g %\\?5)/4KrXD-4oFWaUS62;9s0]9dF'Fd!WkpQH=*57$Z(rF;_5GPI9]o<I'01R$d_N;*(k`SA#7+IO`;M1i'X+l-<3.X-5B/`2+h %HrJL:HZ]%(9ekbQ=hZ^e$k.c?'uOH/R^sCQ_e2l66jF).9?/pA6+X^W].?-0%#8jl$gG*eanM,+A_q/oVl/>dZ,gPN#BtZ$HrqFH %*h2WtRt^N40>_:pKC>n'DZ53qX>E#PIq"0lZ7dRBH<.,7WhXR6[_$48SM:ihg2Y87HBu-6*ag&/S>jX_s6u[ha]*_,EkcD3<;VIL %bB&Z>?nID,lKVeg_c6G'?"9mG4f7SL,u\dg[S54,@k)`s\Z<!")(2VlHqp'O^f($b[pggLPeK17B.@NU2e+=SG<>?^cPpHic'XA_ %f>:s3VE2it%F(8tNfJ.EJYa,Aq0pQ]f$m[mHA_(',u]f4/X_JGkNb9(VOD=f.QMnd]Y<.o_pH!L@O#*`l*gB)=D1_*c:<Y9FVCll %l<TeB<Re%0CMHj0IT]#@S7pHuUfSiD?lHdBfS[H_VAa"&M-bU()b%Q-<`O?n[9e!L<H!?r/@D\t>J7V)<n3pG;n`%78Na8p:L5iK %8CQD^d]&X8Q.PT:#ua95G;#$NVHSc7>gTO4M7Btn(Hh7Q]@*^;S@gIQIEh-O'KN;h5Z?A%.?kVh;tZcr@4Er%0Gt*]"mOMQr5V), %@4@!`#ZI!0j&'Th>%+GY%U&+sg&:#[pJ%%_p=GP.g@#\JVXh'Mb:`rj)<1Vg^"5ORZIB9(p&3(,6J6cg9P#/B=R.C^G<qJ5g6r@J %L8gaoa,71m1Z`.#K*nor$bL>ZWS0.Ds3H8dS+"(X5t1hPT4P0mab-F]P'=[b:#e0&AnacZaqrhhQ%>b_3-e5qlFlTRS*;A5/XnGZ %5EpYr=mN&,MJ)U)Y^323]oP*\.K`<]3-e5qHL9JQ.Dj2u7]L'Hb'5\)[IgGg7]L'H9$P2T)6*=`gjoQgaqn;1;K_;&@9,[+WgVal %[cP]>RCKOaa]q7prVrOn8D0eZ)E'b3a0W=&U">q=q:!fV>E"_ekB,\3260+3CI:DZHVtl!?Q4kbk!aEkI;Pq/UZt\Qg<eqBV=giU %m;#'\G1;00;#AsC4;7I`3n1l%'_]M0l;7B3:nkumW"-5=%E1HE(Y,5Q[@oR;(Y,5Q[@t=-2q=Vq[@n0#HVtl!?Q6!hlSkpU[BIqV %l7Frt%^dD3qG%cLeY2]ETkGsiW"-5=%957b`mpdV[@o?NgduW:W6F"%/=1uh%=[3>\>6+SI&_2q8lu9eO"t_%Hm_#?dH'p9/[B1' %Qs$,4G<ElJ>j"miNlL[YSUsmO=[RaOiiq<t)1Er7)Q@YX44OZmEF5Zl3EGUiXhsE0@f'4#Y<f2)%/(T-KaWN;q:?uOQq+FEi_VPA %pcG<SE]TY#.X)K0p_:9BO>a1?^t.i/YD5G_GOGirH*Em@`i=0GTeL3^OMJp(02aq>B(DWES#u25B,Cn1Um(ml2&989"hHdA5aQ[Y %;l$"J<"P1Lb0V$ic+dQR)VX/op%N.G;#a,R$Y"SQ^]^REYnU!P,Eln@&ZRL\N8BS+oe<mJ*%?#Ydadd5CSm5@HqPh?\)2b7o/e9a %cqdPA[nsooW[X88W&Fd.;60/[MthfI589`.gW,`>?MBlG?dP"(VZ+NP8ZkCkR%'jhnfh)-q/q6pIFb$)co6S.G=Tnc-\m&Kd"K8i %DDs8oEr=Z_gT,Vej;1Xo\(ao97OX,^\SCg!07/tZmrHXtbrsI0RRt_PMgd^2ERV&Oc]3_o`<_n!m/'5bTD^`25=\)&Q+ru5_8!i[ %1'Nj29j[uM+*7mIKpd(,du?>K)B>f\>iqCdU-fd_D-"m)mTZ^$7c%^ZS5uN-`M`2"9X`n.03Z'Ns.k#d`R.m6,LK^#f<aq^pi?<& %p@5a0oc<l=18csWoD:9oNX(3Vi4l/b@=Ru,pml:K[gk1dh!(fZk6LtEb5d!Op,TRFSjZc:i7.F,2,G(9];/-kE0(M-)IQkiDH$l> %P%1`b.A+.g'H7=]P<_#*h"cP41R+>$iGaBMR"So*h^6K%WP9N4auo*'U8*XQF@DXo`:?b]?6%gA[tX@i*L4Ai[N!3Gb]."Ggei%T %)Cl'aEA<sNDs@/mZ^6)(Y@TK:?Q._%_\;lI,Ug$IY5HX$Ru1D..XO@Ofun)RieiV\aOOmBOpE@XLC@6tB)cbt#LgBa^;T[SZ3@+q %L:6][o]o63,#]8K0D6^kpnT>*>ef>\B7Y*gDs+%0Uj"=r;c&b$#>@eM^GFc^gN]sq,jWpKa'r+@NUAGVf8?qlNJD=+qm@s"I0:0G %HutWUk3t&r<1p*Pl0-l+MXZuIL=khP-srqnKan>2i<mW;8$,eqQ1P^n'0op`T:SsP/T_VuD8HD)9;Mf)ZO>W;^.]t%o2NFkl7ikX %R_'YlJWTS]+d(lBW,qAeefib<m(&kW5m>=Ok@'S*QE8F<#7E6nH39/%!33#3LG(if1>qG?RL.[/Kk1gC[@d)$#`Od9hl1dm2_<!) %=*MQ'=@Pk[:]RciNuE5B-'j@e!!dZ%NtZ_`9%41rZsW;ZWPc8eC4\B?h8N$XLN#"-W*eB)qq5%07orPlf>Ttci&#`9Xe!N?7bd1i %q<4&:IN]?8"_F&\q9uhOKL<^ts'ZrYFMO8Nh&Y]b*\_1C2Z=\7j'(.RE_G+_,dtjE&$g<RkAjO#MMY]dV7?d?@aXSGI,U2G_qSA& %"hklIKu-:6=)`i.>8i+:e.2g%hqp\@3/K7QgG7geC%6(FrHK#(Z+>BMrP)`S[.>,5-6J,XAa96@/9=r/C74D>\$>:o+99.Y`d[d" %WF-2Ee:d)e4T%`%bMUmJkagK]f>OO/IbnjlJNn!WcSt#,[*qBupaP\GC'TeFMSZG64Z%J+El?IP`;`46bu-5=IrS^Gm)7bM'RL+o %(.4n8f@^lGAE>@ld&JB_;>_WF9oXX%d;1qernP-oZqo#EUJ\P54QtW<p`Xk1H0fXRoaLE^+M:B*0+SA6/&s?79&Uom((9jlU6#B3 %BfDdM^thr5oIrWVR)?7H^KE[ePciA1aN-=[FAOddfZq#CbFl<1=!ngkh.6DtZU[$Po)&-r(4*A(-Aj9miC%@EEeS:HWqXQ'd:WBc %2L3/Yn"s3[a#j*1pCCn](BZ1:[$uI?%Geh4pb;(6?uj+5:]N^-TaElZ=Je,25"0CRWkU@)O']N[>"+cZRgNs_QbB[EPW03M@5f46 %R!VV.7L!(Q4GMGVjuAdPh!?(GP96K"gr*jNZJWJf,PUminZ*NX,p&1Y*PF"5r)<LW6?mNX,3kf-OgkQON%o@($02=5_u!?9o^E/: %[D;)^/gLL:F[rq4.&<FVZm+l7j)apP3VKKhU)_$2r>.TeNaM8DVg=m>VUfoF+]0YB#:H(dnGRB'9gd.>GknuW2j'G)dO?u:M0`LB %rCW,D5Mu:CaC>Y\krqJK?+>R@%4Y]W!,C7rSSiVd4o]4XE!*nf0Y/q2D?/!'WVH58$1S2iZgQA?]c3VNRBdZ[Go_A0Jn>%NfAW&7 %C+TWt?ADlC(sj+MGo_?r$Z_R80X&AIO;F)\bj4aknbEUpR+L:5Q;]C@?s\UqMS/0A9HkZ%IX)#I+Ah<tYKI/ElPqGV=.=D6m;a1, %aY^&([n*MO=a^RHVoQ,m6BQ]`/'np@5BuT1;'`P*Gg.KpXbmV$-K!(C6X`^C^raQ^q9d0l),?(aajo]DZu^4P=D9YNX1Wpe0>,qh %TPD&*3(1k##aGQgDEF3<[`?KE\OMX$J/uNoPbXH=rX/:"oV:=E-\j+*;Of7MILI_1hf</-2hn_DYLJ'Wr`QMS3D*'?a/mlRfe+%m %X&d@RMtS[?h3XH_$`q:gI=rD1=X@ASms7KRT1^D2dCoUI-!SP"_'4i$^"BIEW8HK(L&K1+"#3Mj=,f'V:[IN.4am+f%t5;jm:RdC %I<P+ZKiA:!d:A+sRr6f/g\C/sJl#+r'Z_*K_l-q14\12dm[f#>No.rT]$@*qNJEStn6='<E^U5js)jH+NPjB3ppld&Vu=Ti+T&Zn %\X`(e)'QZmTH9A_m&jKS"7DiTPjiL4"6]b+?P@bTI,V)IaaN+\`aUPnQS.)iM6,gr<E$S;OX\+M4=Qf)0:RL"3%CHnW;U()+S:)! %;mO"Q5BW#>lq;NrJejOgf"FoaArr*3q.\WgS<>PhNSN2_BmpqpDGme[Y>p-'Q0YJEgM1N#L/HMUs0+D;jG.^KkBOVU6`TJ[)We=[ %ee_R1)F\S6(7^dm>D#BD\$\Mt15K0^s(#2MjomBU]m].t(7aV4jsJI>IfM2N/B.$J?fuZ1k\\/(=gbXW=#sb>3\!j@+Iomjf!,%P %l`Jd<[_@(95r_RuH%k?aVhAEdqc6D`Cr93^$Y/;SG6dEAKlj4!;]/\0\!G9X+gu\hJ`rOX<G^i_[U:R.@#k\mb3/0+3S]uSAcEs? %h<t3HLKE'_(-CVn;lr+E5)$'=Ve_r-49:u3$`)A&W[*&`*lX(Aok!"rE9\1r^`DA*KKX$C0E)RAe3/[XdAio7n-4ElosLe<]pe9; %[P]hi<JY/)am5[gXb$"Q/K:CN=.nr^YCK0uU0,usE9_XsD5MV@?;V[0$[SSIm.HSDDZ$jo1u:E6hBWW\mlC_(f"GO+%CD[R`DFQ4 %W,R])Z,ElF]C-*G;L7A4Y&M2bn\/dPPVZ^sfC])0Y^(_+a&FsC8d9"@]DT_n/i[>K2YT,.E"4e(b<jb%s)V`KCr,7L"r2?5^q\#s %NDg(hV4Ni'rHknD4*lPfp(D257GL/U$>dEo;jFoRoA%'VT(7YShs2%coA5;s&f84%a_NY3n&lUcr-o2mrq`p?UhU2o?T1m-g>!)- %^C+k<7q]\FVB0E!Ta)P4H'G?A/F)?caGI67aej]B9t]n:_id_!"e-&JDd'I2TO?4bgpgnD6,=o!.;`1ml(DDtD<6KuRgoc`nOfqn %9/[e)Cr5UY>-dCc?k[<G2_<X(:p>e%b7.*&*>E=QQXXc3ZK\#i'6NfB-(>AO2LWE$9/[e)Ck>F=Zt.WOmA)DFEQP)16#g6i/D5,A %YR.VMC!!6)Jk]Tkj-!+A"e35#8iF#tMql,n;1D07GOU_Y4R6#0KpYk/H9jVCQk@6tmkS>i\8>L+$V*Bg%_60ud:ihB6n?iMF;Cnu %&+c^tj4hQ1Oh)Y<"4j5S4'4[eVh:ma\%-Rms8<D]P-A$&h=TYsU<sViMpG1cIk]:KB/HOJK9,E#h78f".L3,;&+Qn-rpE:+rVdc` %4d#%KYq73)%j)\gKm?T,dq]JFKq&'W<,jQJSnTh[&FP4tB@*;YOmLEnDHlP/E\`eb+Z)k:(;-a(%mM^gbe:Z?ZSa2uk2%34BSK.( %&r)QCZmpJX"<TuRIrm"f/l4\;/CT!sl5T89H`_!e#&/NSPP\Hu2p=+I4*uZo@FUq,l>Q7-DIEdni;WAI2WZLl]CWMRk-W<\mp?F8 %i(MB%_TfOCH1aU8)I=ArVlsdu\G;RdbO=8E4EfVtFu:V#]>8Sj[6q.6oF_-!Ja0]($dNrHUQdSn$blg39%q)#1Mf,*Xo;qiT?eUb %+.7msd":YqPuccbf6g=NZJXEO7HqG:Iuo=]UjoaI&bY&(@k7gk-'"G2'>EDm"*IYH&8f'$k[qiYddMsphgZ=8`dHmJIH>p-m-IO\ %=67C28bKIkN@D-fZFl^.7?E`58bijI]2*/;WUTeZ#FkO@6"m5.VR$m6J:G]OhEHChh>\OTIIrj'577CFIhU6Gc%oR4cbfu/>H9no %R/D,cNbh_3Fa?*iN2QK4rq'^qgE$=g<YCm*kLH'Nr)Ri2rp:Bsp2DMjZ_<uKfC2cC&T1D:ej4I=r5N[?`TC4[^IH-2FA)&91#0q% %l`5MZq_@p1I1I*B%kE/#;-Oq5s42\rB(2Ec=;hoe3F#^W@^a-TR>])H7:D+N.":J/!q$$LUQh%];u[:KcJTe:d.Er7gt);PI>?O& %_%*Ys?stL8kI(L:%`X.SqB7GT-t5i$k9Tu/Pi.3HBP//_fP:9d/tNUXH:t'oP"<Ks9UnjKM(MS\ZQc$oq@B2``tLd+fFjl2Oo0`< %TF4VS90CI8$#H,+n66MAVkjO.Q,=Xl%Q6je@2:tX@u=[l[mUg?#E+2=3M$Ypn`!U,-U>9h6AJfNi*\q21W'8_i%rV'E/Ht%`YZ*0 %Ql;GbC^Kk?6Z5QC1!T2l[lC0+d__:q`Y0%ZD[Cf]jXFVrVPn`+U3W729dMc4J4VI\L`@R46=?Gm6:iL)%nUbA@\=C-%1P+GcP"4$ %>7qHp^cW:75nl!2B24'9j(A[c&3_n?L`bja7D?c#0#@nH,4VH2RMT*("iF.CnpnYNj>.%:`su6cLH.qG6(hq^JjeW[`&LQA$()qK %SYbHHK5H/DGQtTB*ee)lp^P-\GnFX<13&V6F`E8J.#8<"%$18cCBEc$O6(aG(RGukjEX\S-cL@fKDh8u_'Bm)-q3_IoZ-K*"!O<5 %$+PV]@G01V$dZj^?l-4<Sq],<lI7Q=cX[8_ps$IJME=P"O9Yt*"gVBq8!]h.0IjPCAFQ,X'r5O*gRJ"P=b7poP?8A@8X1K-Q+4nT %$,RDs%pSZ.D$ei>MUU:Z=rVE?Z:^BER1No#f31/h#iJ:?9-EnY8i1K(:cfg+^j6D&k9sF?E%/"81-3[q(a<oWYURJ0T[.:Zr<2JP %,fOI9B1<!(^r,GMG_Tg<=7s>$TK?O&kQ?&7G(UEYXtTt9)4H>W__Vu>(<$:ib]CiW0F*/oKp:_%>m!V\$`h:&PU;W1_G?C?#:R%o %+WGAF!s4FEM^"2m8TBmO(mNQ=6A1A-\cNDC"st$Dp^M0q8.DL68lc-e"X["7csHjgTgbakd#nWZ:2mM]R;Y?B5n+s!LI@PW5XIm" %;FU_]7)]@oP\Alcm":G"XYs$rJV>H;K1g_OnXtCL?6fW21b>'84_"c.6&93E5L7DCM5GhDS-7h:a]ae'KfDGNe>`tf8"fBS:B)7E %$=j4rCfWgK"'S<]gat05F*cm;H-f+O%jKFerrb4komdJ[&"KCQi'SLN\gZim_nm0^Ugl]$"k(2[3eF%c1-&0LP,*Q0c9J@__A;5F %6PE>b'^RK4$j.E6L493j,b+j0?_UYg8392D$8W6A#Eof687*KlR#pK#0us`q!g%EO"sb3;.8XC*Da6cg!dNCucj\,6Lr6"Y:kT+# %#AXAj!p#@hK#],'JN5`dM"2E`"s_:'UU2/;-%RI:Z7&hY"<*ed.P#PX8s5%SU+1.*GG'LI%OD<+.WM\F$.LU:$6mb,3'..U(X/%/ %!.fbs80D7OCP+AK'EM5N:_VfR8ed]q?tY$(Pq<_IDF$U>_<!7CYT/E6)($Sk#%I<p<jlc<&F^:Kq)MT*M1#ANJ>*@^UMg.<8<g&8 %6^g8O0`ih8ggj0g:CN/u9;0(mL]uiWcr9]NW%&jJ*lo@eTZNe2@R=+i6nhGM&Ml=`Oge>!r;!NAfna,GcQknFFde\?p]e+<ZF;B` %<GZ+n:=cF%n:db=TKuu46>@DOUmN>EEW-n`?D'^];3l9(!^2@qnd81^?kaL,0b7lSr!&*+;8&\Pb.T?0M`quI]c1ErJ>rZq"tZ-6 %Nqca6BMG3[=O8Y(Eg.^Zh%MJC/9k&`0_B".EEVX0^sAZ!5k=(I0IpN=ZK:]8,_4'8ha&>@&eA!<"LNd,+selaPU&nQg;&gWVZMXZ %/?BIra"_6Nd#1-s`.C>:.'c'jdp^oL%5NKL%V1-#TjnQH$]ebM?6AG=%V?6S,!Nq<TL+0e3=-ZfoI#0i;*CU@+O?`P![3BNK4i:N %Yl-[69/))5K2)_d:B@6pe-:i"P!`l97m050-?oZk9qgWf7*]LK.P-K&mMO>6C'."p7*EKH9d70s.,mK#4oli;2!;,NRRKRIr!PU, %Yq2"\(n(N/T3H7ECbJ9jX3#qL5sGSk$]"rFT]g2oL<+uXN(h*^=p,I'f7K%/JSl[UImFu\lBJXu1GF%2@Ud<%(1d__%Lg7Me!pE] %KhmQh2MsnU71#MfE57<V!S^6!>5bNIK\D*tP0aMg:10]>UaDHmO`6j>-"MmkSAKB4JGpRjRs9Gi["2o]:rs!a$a<6FYB:cl9aTko %ggHDh5TOpe*5kjOM0B>3cClmaW!E:,!gn*?bU(R^#SeTcN&ko$llJ?cKErPk:*DV1"r'.>ZQLE<Mi8Vs5Qc^FNH,3=OuRBA8LH9t %I-ij!fc[W"c;<:*&ra+jDro)[TVr/kM<Fi428R)(;k0]"aoMr,"5-@)`kY.P=:\OaQn9BPQ4eZj]`^gQ.4GOt^aWD_A0=)^HC=d; %2?<(X1*A7qDul%!,n'hX-4C<(,a7/*":hOPW*JBn1sGOqZpq.`7B&u_RNL<BkQ2f;8J!8B+,.U_1=uY2#:E#QH5^'LoTFG3&1C.b %DR3?7f@b9Tnh>Z`rrskqU3".\W.oI7WQ#U`9cP"<&W(Bq6]J[&:3ffHBV16QUM/^-*smp6I)8oDZIN]aMPac;Q0<N_=9-JQGQ;k# %3;;XMrBM#@>CU%*Z>6,X-+([DBP8#U21i"uU(_?@S,m_=n1,D>DF).2=SZr57USGh%6t/YQ^+h/d11C64>.?d)b<MT%"SQ%cTJDU %:k"._OMQHJ(aW8FVM%L1Hm4F"+:#7rB)#SH@))laO@8#0U=7X(5uMM%:)I4K@OjGS[@fq0.0HsY++bh=d;s_:oeG[qLr:$2BYuE& %T>VN#3M(?4K!f.)q2qKR\,_]oi(8OOB1W1O]-,`o;&iHN1m4"&7n-%*,`W()JlN^S85s'V6_M%Fa8kp#m8I"gOROI!39274J=sbJ %MG91e"<(EV?tmLS3&JNF/8c40F)_*eWb7nL*6D$U$91o]%$,pg"CfNP/MJm''DnssJh\@1!;`KFl36P]UrTt_"p*hFSY5^+9#S7e %epp%F(sNiM)g(\66WkURF-]qfj6GE,JMf]_#u3NYV?q?H8.u2K)"+0R=]Ln9io:^@$QHl/jH0sE]S[0:;hTE&1l4)pM$'Z;BF!TM %C`lmm)Mn2u5aeCHL\6i_L1d05GeZc^(<e1g2U5_*W-J7pQlJdMTCEM,6/mFiWSGIchZt42fTa2,Pk#fs$,i,E[%:E^li\R%#$Mp! %-*lh:%8);)9p2e-#5SK]KU%)DifW+8?>`<TS0EJ--dTSH"`U9Q)b[F+^1.hV?WN2fa_+;K,k/R3g^C,Ope3e[H"7M/neS``<.\c( %F@?mPBHT'ilX;MS;B'T47G1p5'@Gc=\VYP8^hXpX$Z)eqY(ORkhoe-5m"09[F!Y7$J2fSSUl!_4[>=qIPUC>\BL8r+clgE'(,Sjn %&?r+C^l8S#?P)^hKM4Zh[m9).:+Np#!q@\CM51:i#EAWaX=[QB"D3q':\(S8.i!=DScKacBK%4m0k/\_quepnIL3T="g3SIf$f)# %MOBg<:-aS*P+Wm$Hrg`^[$cI)LeaEt<O?UteKEaH]Pb]qSBB8n!^)MR[Z5+D4.%(X':)Y*j.,armEn65E2l2B^k#0MEcU2q1_H2Z %d3mlWhuf-E")0\N+ea2R]d.dX"9o_<)[np-fqAFl(tB/&/2i#c^_.#D915`/J=K^rU^F+6:6+.5*X)OD%FRX]J;:oJPpDgGINtMm %aI5mMT*77.Wi@Lq#53U>ONAbm$.BW"nK<!#/V9*,_b5%B!kNqb">XCBCMErH(l%$!rGQ(N);22:mOj-K8O==j:=\8iQn4PZXl^l_ %ak4B_JhTtMOTnua40b$C4TmZ/7s,6@.+!j09rJN:&.9Zo>4AY>oTKq\*.fsni=0B'a=8oSc3SI?:T:rk;\D$-;KbtO&p)@n?=jtD %WCSG:EsNW(14Db-M<b;`\RC<o"oeQEQ@u6i!'WV#T+/lk"`5NX/F]q^1LqnoE!)4;7V(U[LtVjTJ:q?a4T>_l3I"sX*@qik!!A9j %JO%>?#`kXbKB["idgI.("po]\FL_P-9uh,sMBa@.0S9BD,T2)*]a:tW'f#8k8F.g6%LW>A3HUX0#H$$+dA>kG>S@=doA<qJ'9c6T %/LSN!0Jl95K;<7T"Srf6iGc$'p^j%0Yf%,^1#[Wl/5!C3K.rZZUP]9q(q8FABSI^d((t:6m$3Ns5bgZ_"5Eni>:)aY5/E<p/41%E %/B0CQ##:,M2'<ce=(k@Ur<?b[(]]jo$k^nt;mjurMDWueA[X9$/WsIKlBEW1LL`iYJKuh/D'TbZ@$@)c"4nCo(V?LWngOo+/4*Yc %r\;EX%*<&>HqETt:bpS2,*K85WfV1>M0[XUNdMunKCZ;T!j2b,PIVSGI6qDbLd]JV>R*V<,R1+i':c(q7<G>NP,K_\>\kN#A]"JG %T^`Eu'C9CjOi.$+*9*8-3KTqrOYA;S_!NI!`VkQPW=:UmaiR$F2n4VLL,]CCE_YI`M+k\fHDl7t7Y,*pBfrS]Gn7ms!YUQ?M$Ak- %R/,fVa`*:7oDb5"4@)P]:pdkQQu+#B^k=94n<p?oUE>;1j^Y_%T+K,l%!!bF(=C)e4bNT"Osbnp#Ip/l'BEM`P2V,&.E=o^R3I;^ %jp,tG7Zp.e`c])"BME29,qLXKDjm2`J]"HOQrBFrY+oPC12dd[A]IFh4cg5;i+`@fL\_<5%e(-@!AOKsN!p-;OHc=B!fB=95RHB0 %KGSrd+MtWn<_eS2.?4P6-0TKgU8Sc'Kbt>WqlUHdZTSlDnBLE?pLj!$oeu6PI,KFZ;M6$2a!>C-F=ID/U@-C#g<./*@X&4fs2Vs: %0U2f"/d?s&#+C$oAn$=qXWQXb(:8K`Ua/u9FIPM:i]Xi>a'sRgZ@2\5QqmjE\U)2qWtB>mBK<Pa7BqN2At>H*d]Der@0VH^YU!KX %6+;BY2Wf7@F[Ep;#ijl5UHMmD&aoNME?Uu_@5s4F9hA(7T^`39^W`g.T95h638R%QQ6jR"=pEsOU[Uk==fUJ=__<A6-`9PU@ru`h %cSLsB"boOh:Je>Q,iP^<lu&<j6H!@:fG4bdQO`Ka_mb$)^Mrsd/.THuPKY^6a,[)rcsOcI%\F;uPRr+L;,&Y,0b[j%U^rFle"BT[ %b=ZtM.i[%4Jm/0bhic\PRY@U7&#8JEW<T-c0PVE!p+bd/512`+^hpmI&5)X%N+FT\_A>T$^o_OS[_Q!l@&QiaA"Ose?h6#l!Tcl7 %LndL@JBB&Qa9o!o>6&]ja<ou#`[]Y`#ljC]Kt'MP-DMi,L;K-?76*/Z=]%3.NoGW+2<Y8dh8KLA4(NTI6kTM,<Q[$NbS(@,ORl59 %&b+"3XsP:SYoEu5pfj2MZP4h2/4r!+*agF[T"pl##gkSKLI?HcH,V38%3W_^bQ:3Clk7AYEhG(knl_nr)C*B2@@/lC>S:5GUaCh[ %AJr0M&0Fck=hn'J^8('_?QBZ97+;Dr@tS8[:0]ajp@$RfapSl!R'?eUJp^-bhD!K?JMk$C'TiA6h&ap@R((*a)SuhT.*uu=#X3i& %82qqM/2*W&$>`%p5RM!TE^H4fO^!XA`P;Ir)io7X,VM[Hcd>]gG^QclN_u/#p`q.;D?$eS<j$a!r4\6oZ<.N"ZZ6dcDEJn5I'^q& %r:87-DB7XO^I)g#muG.0>@5._s8:^L*DX*CQbL0B4hL$*nQbkg)Z#mra'Gd'l_"]$e]j#qJ/t!"b@9]-UU[RnI)lUPN^\3pC8aj, %?_&#tQ:0.04oaKR/]OR[:-uA"DYZ)jHTWrS!,;-)ceB3?+=F&/:UO'9g<>&I++_C7)*DldNPMj4TadW',Y;_##+2m%mU%3c]R)em %[%?FPR5\918,Lp<Zh<i<Es?T@bSS+R<VL@W(jA3Y#@lZGV#)6dXmRi]6[(R._)L:Z%49Q_Gd'&N+9!Xr^a&-jK>GE9dJ*YB\[:?g~> %AI9_PrivateDataEnd \ No newline at end of file
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.ico b/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.ico
deleted file mode 100644
index 0e8139434b2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.ico
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.jpg b/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.jpg
deleted file mode 100644
index 840afa92bc1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/art/sqlite370.jpg
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/INSTALL b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/INSTALL
deleted file mode 100644
index a1e89e18ad2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/INSTALL
+++ /dev/null
@@ -1,370 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
-Inc.
-
- Copying and distribution of this file, with or without modification,
-are permitted in any medium without royalty provided the copyright
-notice and this notice are preserved. This file is offered as-is,
-without warranty of any kind.
-
-Basic Installation
-==================
-
- Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package. The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package. Some packages provide this
-`INSTALL' file but do not implement all of the features documented
-below. The lack of an optional feature in a given package is not
-necessarily a bug. More recommendations for GNU packages can be found
-in *note Makefile Conventions: (standards)Makefile Conventions.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
- It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring. Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
- The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'. You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
- The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system.
-
- Running `configure' might take a while. While running, it prints
- some messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package, generally using the just-built uninstalled binaries.
-
- 4. Type `make install' to install the programs and any data files and
- documentation. When installing into a prefix owned by root, it is
- recommended that the package be configured and built as a regular
- user, and only the `make install' phase executed with root
- privileges.
-
- 5. Optionally, type `make installcheck' to repeat any self-tests, but
- this time using the binaries in their final installed location.
- This target does not install anything. Running this target as a
- regular user, particularly if the prior `make install' required
- root privileges, verifies that the installation completed
- correctly.
-
- 6. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
- 7. Often, you can also type `make uninstall' to remove the installed
- files again. In practice, not all packages have tested that
- uninstallation works correctly, even though it is required by the
- GNU Coding Standards.
-
- 8. Some packages, particularly those that use Automake, provide `make
- distcheck', which can by used by developers to test that all other
- targets like `make install' and `make uninstall' work correctly.
- This target is generally not run by end users.
-
-Compilers and Options
-=====================
-
- Some systems require unusual options for compilation or linking that
-the `configure' script does not know about. Run `./configure --help'
-for details on some of the pertinent environment variables.
-
- You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment. Here
-is an example:
-
- ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
- *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
- You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you can use GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'. This
-is known as a "VPATH" build.
-
- With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory. After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
- On MacOS X 10.5 and later systems, you can create libraries and
-executables that work on multiple system types--known as "fat" or
-"universal" binaries--by specifying multiple `-arch' options to the
-compiler but only a single `-arch' option to the preprocessor. Like
-this:
-
- ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
- CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
- CPP="gcc -E" CXXCPP="g++ -E"
-
- This is not guaranteed to produce working output in all cases, you
-may have to build one architecture at a time and combine the results
-using the `lipo' tool if you have problems.
-
-Installation Names
-==================
-
- By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc. You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX', where PREFIX must be an
-absolute file name.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them. In general, the
-default for these options is expressed in terms of `${prefix}', so that
-specifying just `--prefix' will affect all of the other directory
-specifications that were not explicitly provided.
-
- The most portable way to affect installation locations is to pass the
-correct locations to `configure'; however, many packages provide one or
-both of the following shortcuts of passing variable assignments to the
-`make install' command line to change installation locations without
-having to reconfigure or recompile.
-
- The first method involves providing an override variable for each
-affected directory. For example, `make install
-prefix=/alternate/directory' will choose an alternate location for all
-directory configuration variables that were expressed in terms of
-`${prefix}'. Any directories that were specified during `configure',
-but not in terms of `${prefix}', must each be overridden at install
-time for the entire installation to be relocated. The approach of
-makefile variable overrides for each directory variable is required by
-the GNU Coding Standards, and ideally causes no recompilation.
-However, some platforms have known limitations with the semantics of
-shared libraries that end up requiring recompilation when using this
-method, particularly noticeable in packages that use GNU Libtool.
-
- The second method involves providing the `DESTDIR' variable. For
-example, `make install DESTDIR=/alternate/directory' will prepend
-`/alternate/directory' before all installation names. The approach of
-`DESTDIR' overrides is not required by the GNU Coding Standards, and
-does not work on platforms that have drive letters. On the other hand,
-it does better at avoiding recompilation issues, and works well even
-when some directory options were not specified in terms of `${prefix}'
-at `configure' time.
-
-Optional Features
-=================
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
- Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
- Some packages offer the ability to configure how verbose the
-execution of `make' will be. For these packages, running `./configure
---enable-silent-rules' sets the default to minimal output, which can be
-overridden with `make V=1'; while running `./configure
---disable-silent-rules' sets the default to verbose, which can be
-overridden with `make V=0'.
-
-Particular systems
-==================
-
- On HP-UX, the default C compiler is not ANSI C compatible. If GNU
-CC is not installed, it is recommended to use the following options in
-order to use an ANSI C compiler:
-
- ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
-
-and if that doesn't work, install pre-built binaries of GCC for HP-UX.
-
- HP-UX `make' updates targets which have the same time stamps as
-their prerequisites, which makes it generally unusable when shipped
-generated files such as `configure' are involved. Use GNU `make'
-instead.
-
- On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
-parse its `<wchar.h>' header file. The option `-nodtk' can be used as
-a workaround. If GNU CC is not installed, it is therefore recommended
-to try
-
- ./configure CC="cc"
-
-and if that doesn't work, try
-
- ./configure CC="cc -nodtk"
-
- On Solaris, don't put `/usr/ucb' early in your `PATH'. This
-directory contains several dysfunctional programs; working variants of
-these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
-in your `PATH', put it _after_ `/usr/bin'.
-
- On Haiku, software installed for all users goes in `/boot/common',
-not `/usr/local'. It is recommended to use the following options:
-
- ./configure --prefix=/boot/common
-
-Specifying the System Type
-==========================
-
- There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on. Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
- CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
- OS
- KERNEL-OS
-
- See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
- If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
- If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
- If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
- Variables not defined in a site shell script can be set in the
-environment passed to `configure'. However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost. In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'. For example:
-
- ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug. Until the bug is fixed you can use this workaround:
-
- CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
- `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
- Print a summary of all of the options to `configure', and exit.
-
-`--help=short'
-`--help=recursive'
- Print a summary of the options unique to this package's
- `configure', and exit. The `short' variant lists options used
- only in the top level, while the `recursive' variant lists options
- also present in any nested packages.
-
-`--version'
-`-V'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--cache-file=FILE'
- Enable the cache: use and save the results of the tests in FILE,
- traditionally `config.cache'. FILE defaults to `/dev/null' to
- disable caching.
-
-`--config-cache'
-`-C'
- Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`--prefix=DIR'
- Use DIR as the installation prefix. *note Installation Names::
- for more details, including other options available for fine-tuning
- the installation locations.
-
-`--no-create'
-`-n'
- Run the configure checks, but stop before creating any output
- files.
-
-`configure' also accepts some other, not widely useful, options. Run
-`configure --help' for more details.
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.am b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.am
deleted file mode 100644
index a9a8d803dc7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-
-AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE @DEBUG_FLAGS@
-
-lib_LTLIBRARIES = libsqlite3.la
-libsqlite3_la_SOURCES = sqlite3.c
-libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
-
-bin_PROGRAMS = sqlite3
-sqlite3_SOURCES = shell.c sqlite3.h
-EXTRA_sqlite3_SOURCES = sqlite3.c
-sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
-sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
-sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS)
-
-include_HEADERS = sqlite3.h sqlite3ext.h
-
-EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback
-pkgconfigdir = ${libdir}/pkgconfig
-pkgconfig_DATA = sqlite3.pc
-
-man_MANS = sqlite3.1
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.fallback b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.fallback
deleted file mode 100644
index 9355b147a8f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.fallback
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/make
-#
-# If the configure script does not work, then this Makefile is available
-# as a backup. Manually configure the variables below.
-#
-# Note: This makefile works out-of-the-box on MacOS 10.2 (Jaguar)
-#
-CC = gcc
-CFLAGS = -O0 -I.
-LIBS = -lz
-COPTS += -D_BSD_SOURCE
-COPTS += -DSQLITE_ENABLE_LOCKING_STYLE=0
-COPTS += -DSQLITE_THREADSAFE=0
-COPTS += -DSQLITE_OMIT_LOAD_EXTENSION
-COPTS += -DSQLITE_WITHOUT_ZONEMALLOC
-COPTS += -DSQLITE_ENABLE_RTREE
-
-sqlite3: shell.c sqlite3.c
- $(CC) $(CFLAGS) $(COPTS) -o sqlite3 shell.c sqlite3.c $(LIBS)
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.msc b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.msc
deleted file mode 100644
index dbcb8c98803..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/Makefile.msc
+++ /dev/null
@@ -1,1010 +0,0 @@
-#### DO NOT EDIT ####
-# This makefile is automatically generated from the Makefile.msc at
-# the root of the canonical SQLite source tree (not the
-# amalgamation tarball) using the tool/mkmsvcmin.tcl
-# script.
-#
-
-#
-# nmake Makefile for SQLite
-#
-###############################################################################
-############################## START OF OPTIONS ###############################
-###############################################################################
-
-# The toplevel directory of the source tree. This is the directory
-# that contains this "Makefile.msc".
-#
-TOP = .
-
-
-# Set this non-0 to enable full warnings (-W4, etc) when compiling.
-#
-!IFNDEF USE_FULLWARN
-USE_FULLWARN = 1
-!ENDIF
-
-# Set this non-0 to enable treating warnings as errors (-WX, etc) when
-# compiling.
-#
-!IFNDEF USE_FATAL_WARN
-USE_FATAL_WARN = 0
-!ENDIF
-
-# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
-# has no effect if (any) optimizations are enabled.
-#
-!IFNDEF USE_RUNTIME_CHECKS
-USE_RUNTIME_CHECKS = 0
-!ENDIF
-
-# Set this non-0 to create a SQLite amalgamation file that excludes the
-# various built-in extensions.
-#
-!IFNDEF MINIMAL_AMALGAMATION
-MINIMAL_AMALGAMATION = 0
-!ENDIF
-
-# Set this non-0 to use "stdcall" calling convention for the core library
-# and shell executable.
-#
-!IFNDEF USE_STDCALL
-USE_STDCALL = 0
-!ENDIF
-
-# Set this non-0 to have the shell executable link against the core dynamic
-# link library.
-#
-!IFNDEF DYNAMIC_SHELL
-DYNAMIC_SHELL = 0
-!ENDIF
-
-# Set this non-0 to enable extra code that attempts to detect misuse of the
-# SQLite API.
-#
-!IFNDEF API_ARMOR
-API_ARMOR = 0
-!ENDIF
-
-# If necessary, create a list of harmless compiler warnings to disable when
-# compiling the various tools. For the SQLite source code itself, warnings,
-# if any, will be disabled from within it.
-#
-!IFNDEF NO_WARN
-!IF $(USE_FULLWARN)!=0
-NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
-NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
-!ENDIF
-!ENDIF
-
-# Set this non-0 to use the library paths and other options necessary for
-# Windows Phone 8.1.
-#
-!IFNDEF USE_WP81_OPTS
-USE_WP81_OPTS = 0
-!ENDIF
-
-# Set this non-0 to split the SQLite amalgamation file into chunks to
-# be used for debugging with Visual Studio.
-#
-!IFNDEF SPLIT_AMALGAMATION
-SPLIT_AMALGAMATION = 0
-!ENDIF
-
-
-# Set this non-0 to dynamically link to the MSVC runtime library.
-#
-!IFNDEF USE_CRT_DLL
-USE_CRT_DLL = 0
-!ENDIF
-
-# Set this non-0 to link to the RPCRT4 library.
-#
-!IFNDEF USE_RPCRT4_LIB
-USE_RPCRT4_LIB = 0
-!ENDIF
-
-# Set this non-0 to generate assembly code listings for the source code
-# files.
-#
-!IFNDEF USE_LISTINGS
-USE_LISTINGS = 0
-!ENDIF
-
-# Set this non-0 to attempt setting the native compiler automatically
-# for cross-compiling the command line tools needed during the compilation
-# process.
-#
-!IFNDEF XCOMPILE
-XCOMPILE = 0
-!ENDIF
-
-# Set this non-0 to use the native libraries paths for cross-compiling
-# the command line tools needed during the compilation process.
-#
-!IFNDEF USE_NATIVE_LIBPATHS
-USE_NATIVE_LIBPATHS = 0
-!ENDIF
-
-# Set this 0 to skip the compiling and embedding of version resources.
-#
-!IFNDEF USE_RC
-USE_RC = 1
-!ENDIF
-
-# Set this non-0 to compile binaries suitable for the WinRT environment.
-# This setting does not apply to any binaries that require Tcl to operate
-# properly (i.e. the text fixture, etc).
-#
-!IFNDEF FOR_WINRT
-FOR_WINRT = 0
-!ENDIF
-
-# Set this non-0 to compile binaries suitable for the UWP environment.
-# This setting does not apply to any binaries that require Tcl to operate
-# properly (i.e. the text fixture, etc).
-#
-!IFNDEF FOR_UWP
-FOR_UWP = 0
-!ENDIF
-
-# Set this non-0 to compile binaries suitable for the Windows 10 platform.
-#
-!IFNDEF FOR_WIN10
-FOR_WIN10 = 0
-!ENDIF
-
-
-# Set this to non-0 to create and use PDBs.
-#
-!IFNDEF SYMBOLS
-SYMBOLS = 1
-!ENDIF
-
-# Set this to non-0 to use the SQLite debugging heap subsystem.
-#
-!IFNDEF MEMDEBUG
-MEMDEBUG = 0
-!ENDIF
-
-# Set this to non-0 to use the Win32 native heap subsystem.
-#
-!IFNDEF WIN32HEAP
-WIN32HEAP = 0
-!ENDIF
-
-# Set this to non-0 to enable OSTRACE() macros, which can be useful when
-# debugging.
-#
-!IFNDEF OSTRACE
-OSTRACE = 0
-!ENDIF
-
-# Set this to one of the following values to enable various debugging
-# features. Each level includes the debugging options from the previous
-# levels. Currently, the recognized values for DEBUG are:
-#
-# 0 == NDEBUG: Disables assert() and other runtime diagnostics.
-# 1 == SQLITE_ENABLE_API_ARMOR: extra attempts to detect misuse of the API.
-# 2 == Disables NDEBUG and all optimizations and then enables PDBs.
-# 3 == SQLITE_DEBUG: Enables various diagnostics messages and code.
-# 4 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
-# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
-# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
-#
-!IFNDEF DEBUG
-DEBUG = 0
-!ENDIF
-
-# Enable use of available compiler optimizations? Normally, this should be
-# non-zero. Setting this to zero, thus disabling all compiler optimizations,
-# can be useful for testing.
-#
-!IFNDEF OPTIMIZATIONS
-OPTIMIZATIONS = 2
-!ENDIF
-
-# Set this to non-0 to enable support for the session extension.
-#
-!IFNDEF SESSION
-SESSION = 0
-!ENDIF
-
-# Set the source code file to be used by executables and libraries when
-# they need the amalgamation.
-#
-!IFNDEF SQLITE3C
-!IF $(SPLIT_AMALGAMATION)!=0
-SQLITE3C = sqlite3-all.c
-!ELSE
-SQLITE3C = sqlite3.c
-!ENDIF
-!ENDIF
-
-# Set the include code file to be used by executables and libraries when
-# they need SQLite.
-#
-!IFNDEF SQLITE3H
-SQLITE3H = sqlite3.h
-!ENDIF
-
-# This is the name to use for the SQLite dynamic link library (DLL).
-#
-!IFNDEF SQLITE3DLL
-!IF $(FOR_WIN10)!=0
-SQLITE3DLL = winsqlite3.dll
-!ELSE
-SQLITE3DLL = sqlite3.dll
-!ENDIF
-!ENDIF
-
-# This is the name to use for the SQLite import library (LIB).
-#
-!IFNDEF SQLITE3LIB
-!IF $(FOR_WIN10)!=0
-SQLITE3LIB = winsqlite3.lib
-!ELSE
-SQLITE3LIB = sqlite3.lib
-!ENDIF
-!ENDIF
-
-# This is the name to use for the SQLite shell executable (EXE).
-#
-!IFNDEF SQLITE3EXE
-!IF $(FOR_WIN10)!=0
-SQLITE3EXE = winsqlite3shell.exe
-!ELSE
-SQLITE3EXE = sqlite3.exe
-!ENDIF
-!ENDIF
-
-# This is the argument used to set the program database (PDB) file for the
-# SQLite shell executable (EXE).
-#
-!IFNDEF SQLITE3EXEPDB
-!IF $(FOR_WIN10)!=0
-SQLITE3EXEPDB =
-!ELSE
-SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
-!ENDIF
-!ENDIF
-
-
-# These are the "standard" SQLite compilation options used when compiling for
-# the Windows platform.
-#
-!IFNDEF OPT_FEATURE_FLAGS
-!IF $(MINIMAL_AMALGAMATION)==0
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
-!ENDIF
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
-!ENDIF
-
-# Should the session extension be enabled? If so, add compilation options
-# to enable it.
-#
-!IF $(SESSION)!=0
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
-!ENDIF
-
-# These are the "extended" SQLite compilation options used when compiling for
-# the Windows 10 platform.
-#
-!IFNDEF EXT_FEATURE_FLAGS
-!IF $(FOR_WIN10)!=0
-EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1
-EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_SYSTEM_MALLOC=1
-EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_OMIT_LOCALTIME=1
-!ELSE
-EXT_FEATURE_FLAGS =
-!ENDIF
-!ENDIF
-
-###############################################################################
-############################### END OF OPTIONS ################################
-###############################################################################
-
-# When compiling for the Windows 10 platform, the PLATFORM macro must be set
-# to an appropriate value (e.g. x86, x64, arm, arm64, etc).
-#
-!IF $(FOR_WIN10)!=0
-!IFNDEF PLATFORM
-!ERROR Using the FOR_WIN10 option requires a value for PLATFORM.
-!ENDIF
-!ENDIF
-
-# This assumes that MSVC is always installed in 32-bit Program Files directory
-# and sets the variable for use in locating other 32-bit installs accordingly.
-#
-PROGRAMFILES_X86 = $(VCINSTALLDIR)\..\..
-PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\)
-
-# Check for the predefined command macro CC. This should point to the compiler
-# binary for the target platform. If it is not defined, simply define it to
-# the legacy default value 'cl.exe'.
-#
-!IFNDEF CC
-CC = cl.exe
-!ENDIF
-
-# Check for the predefined command macro CSC. This should point to a working
-# C Sharp compiler binary. If it is not defined, simply define it to the
-# legacy default value 'csc.exe'.
-#
-!IFNDEF CSC
-CSC = csc.exe
-!ENDIF
-
-# Check for the command macro LD. This should point to the linker binary for
-# the target platform. If it is not defined, simply define it to the legacy
-# default value 'link.exe'.
-#
-!IFNDEF LD
-LD = link.exe
-!ENDIF
-
-# Check for the predefined command macro RC. This should point to the resource
-# compiler binary for the target platform. If it is not defined, simply define
-# it to the legacy default value 'rc.exe'.
-#
-!IFNDEF RC
-RC = rc.exe
-!ENDIF
-
-# Check for the MSVC runtime library path macro. Otherwise, this value will
-# default to the 'lib' directory underneath the MSVC installation directory.
-#
-!IFNDEF CRTLIBPATH
-CRTLIBPATH = $(VCINSTALLDIR)\lib
-!ENDIF
-
-CRTLIBPATH = $(CRTLIBPATH:\\=\)
-
-# Check for the command macro NCC. This should point to the compiler binary
-# for the platform the compilation process is taking place on. If it is not
-# defined, simply define it to have the same value as the CC macro. When
-# cross-compiling, it is suggested that this macro be modified via the command
-# line (since nmake itself does not provide a built-in method to guess it).
-# For example, to use the x86 compiler when cross-compiling for x64, a command
-# line similar to the following could be used (all on one line):
-#
-# nmake /f Makefile.msc sqlite3.dll
-# XCOMPILE=1 USE_NATIVE_LIBPATHS=1
-#
-# Alternatively, the full path and file name to the compiler binary for the
-# platform the compilation process is taking place may be specified (all on
-# one line):
-#
-# nmake /f Makefile.msc sqlite3.dll
-# "NCC=""%VCINSTALLDIR%\bin\cl.exe"""
-# USE_NATIVE_LIBPATHS=1
-#
-!IFDEF NCC
-NCC = $(NCC:\\=\)
-!ELSEIF $(XCOMPILE)!=0
-NCC = "$(VCINSTALLDIR)\bin\$(CC)"
-NCC = $(NCC:\\=\)
-!ELSE
-NCC = $(CC)
-!ENDIF
-
-# Check for the MSVC native runtime library path macro. Otherwise,
-# this value will default to the 'lib' directory underneath the MSVC
-# installation directory.
-#
-!IFNDEF NCRTLIBPATH
-NCRTLIBPATH = $(VCINSTALLDIR)\lib
-!ENDIF
-
-NCRTLIBPATH = $(NCRTLIBPATH:\\=\)
-
-# Check for the Platform SDK library path macro. Otherwise, this
-# value will default to the 'lib' directory underneath the Windows
-# SDK installation directory (the environment variable used appears
-# to be available when using Visual C++ 2008 or later via the
-# command line).
-#
-!IFNDEF NSDKLIBPATH
-NSDKLIBPATH = $(WINDOWSSDKDIR)\lib
-!ENDIF
-
-NSDKLIBPATH = $(NSDKLIBPATH:\\=\)
-
-# Check for the UCRT library path macro. Otherwise, this value will
-# default to the version-specific, platform-specific 'lib' directory
-# underneath the Windows SDK installation directory.
-#
-!IFNDEF UCRTLIBPATH
-UCRTLIBPATH = $(WINDOWSSDKDIR)\lib\$(WINDOWSSDKLIBVERSION)\ucrt\$(PLATFORM)
-!ENDIF
-
-UCRTLIBPATH = $(UCRTLIBPATH:\\=\)
-
-# C compiler and options for use in building executables that
-# will run on the platform that is doing the build.
-#
-!IF $(USE_FULLWARN)!=0
-BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
-!ELSE
-BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
-!ENDIF
-
-# Check if assembly code listings should be generated for the source
-# code files to be compiled.
-#
-!IF $(USE_LISTINGS)!=0
-BCC = $(BCC) -FAcs
-!ENDIF
-
-# Check if the native library paths should be used when compiling
-# the command line tools used during the compilation process. If
-# so, set the necessary macro now.
-#
-!IF $(USE_NATIVE_LIBPATHS)!=0
-NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
-
-!IFDEF NUCRTLIBPATH
-NUCRTLIBPATH = $(NUCRTLIBPATH:\\=\)
-NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)"
-!ENDIF
-!ENDIF
-
-# C compiler and options for use in building executables that
-# will run on the target platform. (BCC and TCC are usually the
-# same unless your are cross-compiling.)
-#
-!IF $(USE_FULLWARN)!=0
-TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
-!ELSE
-TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
-!ENDIF
-
-# Check if warnings should be treated as errors when compiling.
-#
-!IF $(USE_FATAL_WARN)!=0
-TCC = $(TCC) -WX
-!ENDIF
-
-TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise
-RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
-
-# Check if we want to use the "stdcall" calling convention when compiling.
-# This is not supported by the compilers for non-x86 platforms. It should
-# also be noted here that building any target with these "stdcall" options
-# will most likely fail if the Tcl library is also required. This is due
-# to how the Tcl library functions are declared and exported (i.e. without
-# an explicit calling convention, which results in "cdecl").
-#
-!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
-!IF "$(PLATFORM)"=="x86"
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-!ELSE
-!IFNDEF PLATFORM
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-!ELSE
-CORE_CCONV_OPTS =
-SHELL_CCONV_OPTS =
-!ENDIF
-!ENDIF
-!ELSE
-CORE_CCONV_OPTS =
-SHELL_CCONV_OPTS =
-!ENDIF
-
-# These are additional compiler options used for the core library.
-#
-!IFNDEF CORE_COMPILE_OPTS
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport)
-!ELSE
-CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
-!ENDIF
-!ENDIF
-
-# These are the additional targets that the core library should depend on
-# when linking.
-#
-!IFNDEF CORE_LINK_DEP
-!IF $(DYNAMIC_SHELL)!=0
-CORE_LINK_DEP =
-!ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86"
-CORE_LINK_DEP = sqlite3.def
-!ELSE
-CORE_LINK_DEP =
-!ENDIF
-!ENDIF
-
-# These are additional linker options used for the core library.
-#
-!IFNDEF CORE_LINK_OPTS
-!IF $(DYNAMIC_SHELL)!=0
-CORE_LINK_OPTS =
-!ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86"
-CORE_LINK_OPTS = /DEF:sqlite3.def
-!ELSE
-CORE_LINK_OPTS =
-!ENDIF
-!ENDIF
-
-# These are additional compiler options used for the shell executable.
-#
-!IFNDEF SHELL_COMPILE_OPTS
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
-!ELSE
-SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS)
-!ENDIF
-!ENDIF
-
-# This is the source code that the shell executable should be compiled
-# with.
-#
-!IFNDEF SHELL_CORE_SRC
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-SHELL_CORE_SRC =
-!ELSE
-SHELL_CORE_SRC = $(SQLITE3C)
-!ENDIF
-!ENDIF
-
-# This is the core library that the shell executable should depend on.
-#
-!IFNDEF SHELL_CORE_DEP
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-SHELL_CORE_DEP = $(SQLITE3DLL)
-!ELSE
-SHELL_CORE_DEP =
-!ENDIF
-!ENDIF
-
-
-# This is the core library that the shell executable should link with.
-#
-!IFNDEF SHELL_CORE_LIB
-!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
-SHELL_CORE_LIB = $(SQLITE3LIB)
-!ELSE
-SHELL_CORE_LIB =
-!ENDIF
-!ENDIF
-
-# These are additional linker options used for the shell executable.
-#
-!IFNDEF SHELL_LINK_OPTS
-SHELL_LINK_OPTS = $(SHELL_CORE_LIB)
-!ENDIF
-
-# Check if assembly code listings should be generated for the source
-# code files to be compiled.
-#
-!IF $(USE_LISTINGS)!=0
-TCC = $(TCC) -FAcs
-!ENDIF
-
-# When compiling the library for use in the WinRT environment,
-# the following compile-time options must be used as well to
-# disable use of Win32 APIs that are not available and to enable
-# use of Win32 APIs that are specific to Windows 8 and/or WinRT.
-#
-!IF $(FOR_WINRT)!=0
-TCC = $(TCC) -DSQLITE_OS_WINRT=1
-RCC = $(RCC) -DSQLITE_OS_WINRT=1
-TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
-RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
-!ENDIF
-
-# C compiler options for the Windows 10 platform (needs MSVC 2015).
-#
-!IF $(FOR_WIN10)!=0
-TCC = $(TCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
-BCC = $(BCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
-!ENDIF
-
-# Also, we need to dynamically link to the correct MSVC runtime
-# when compiling for WinRT (e.g. debug or release) OR if the
-# USE_CRT_DLL option is set to force dynamically linking to the
-# MSVC runtime library.
-#
-!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0
-!IF $(DEBUG)>1
-TCC = $(TCC) -MDd
-BCC = $(BCC) -MDd
-!ELSE
-TCC = $(TCC) -MD
-BCC = $(BCC) -MD
-!ENDIF
-!ELSE
-!IF $(DEBUG)>1
-TCC = $(TCC) -MTd
-BCC = $(BCC) -MTd
-!ELSE
-TCC = $(TCC) -MT
-BCC = $(BCC) -MT
-!ENDIF
-!ENDIF
-
-
-# Define -DNDEBUG to compile without debugging (i.e., for production usage)
-# Omitting the define will cause extra debugging code to be inserted and
-# includes extra comments when "EXPLAIN stmt" is used.
-#
-!IF $(DEBUG)==0
-TCC = $(TCC) -DNDEBUG
-BCC = $(BCC) -DNDEBUG
-RCC = $(RCC) -DNDEBUG
-!ENDIF
-
-!IF $(DEBUG)>0 || $(API_ARMOR)!=0 || $(FOR_WIN10)!=0
-TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1
-RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
-!ENDIF
-
-!IF $(DEBUG)>2
-TCC = $(TCC) -DSQLITE_DEBUG=1
-RCC = $(RCC) -DSQLITE_DEBUG=1
-!IF $(DYNAMIC_SHELL)==0
-TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
-RCC = $(RCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
-!ENDIF
-!ENDIF
-
-!IF $(DEBUG)>4 || $(OSTRACE)!=0
-TCC = $(TCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
-RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
-!ENDIF
-
-!IF $(DEBUG)>5
-TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1
-RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1
-!ENDIF
-
-# Prevent warnings about "insecure" MSVC runtime library functions
-# being used.
-#
-TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
-BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
-RCC = $(RCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
-
-# Prevent warnings about "deprecated" POSIX functions being used.
-#
-TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
-BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
-RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
-
-# Use the SQLite debugging heap subsystem?
-#
-!IF $(MEMDEBUG)!=0
-TCC = $(TCC) -DSQLITE_MEMDEBUG=1
-RCC = $(RCC) -DSQLITE_MEMDEBUG=1
-
-# Use native Win32 heap subsystem instead of malloc/free?
-#
-!ELSEIF $(WIN32HEAP)!=0
-TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
-RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
-
-# Validate the heap on every call into the native Win32 heap subsystem?
-#
-!IF $(DEBUG)>3
-TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
-RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
-!ENDIF
-!ENDIF
-
-
-# Compiler options needed for programs that use the readline() library.
-#
-!IFNDEF READLINE_FLAGS
-READLINE_FLAGS = -DHAVE_READLINE=0
-!ENDIF
-
-# The library that programs using readline() must link against.
-#
-!IFNDEF LIBREADLINE
-LIBREADLINE =
-!ENDIF
-
-# Should the database engine be compiled threadsafe
-#
-TCC = $(TCC) -DSQLITE_THREADSAFE=1
-RCC = $(RCC) -DSQLITE_THREADSAFE=1
-
-# Do threads override each others locks by default (1), or do we test (-1)
-#
-TCC = $(TCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
-RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
-
-# Any target libraries which libsqlite must be linked against
-#
-!IFNDEF TLIBS
-TLIBS =
-!ENDIF
-
-# Flags controlling use of the in memory btree implementation
-#
-# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
-# default to file, 2 to default to memory, and 3 to force temporary
-# tables to always be in memory.
-#
-TCC = $(TCC) -DSQLITE_TEMP_STORE=1
-RCC = $(RCC) -DSQLITE_TEMP_STORE=1
-
-# Enable/disable loadable extensions, and other optional features
-# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
-# The same set of OMIT and ENABLE flags should be passed to the
-# LEMON parser generator and the mkkeywordhash tool as well.
-
-# These are the required SQLite compilation options used when compiling for
-# the Windows platform.
-#
-REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
-
-# If we are linking to the RPCRT4 library, enable features that need it.
-#
-!IF $(USE_RPCRT4_LIB)!=0
-REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_WIN32_USE_UUID=1
-!ENDIF
-
-# Add the required and optional SQLite compilation options into the command
-# lines used to invoke the MSVC code and resource compilers.
-#
-TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS)
-RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS)
-
-# Add in any optional parameters specified on the commane line, e.g.
-# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
-#
-TCC = $(TCC) $(OPTS)
-RCC = $(RCC) $(OPTS)
-
-# If compiling for debugging, add some defines.
-#
-!IF $(DEBUG)>1
-TCC = $(TCC) -D_DEBUG
-BCC = $(BCC) -D_DEBUG
-RCC = $(RCC) -D_DEBUG
-!ENDIF
-
-# If optimizations are enabled or disabled (either implicitly or
-# explicitly), add the necessary flags.
-#
-!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0
-TCC = $(TCC) -Od
-BCC = $(BCC) -Od
-!IF $(USE_RUNTIME_CHECKS)!=0
-TCC = $(TCC) -RTC1
-BCC = $(BCC) -RTC1
-!ENDIF
-!ELSEIF $(OPTIMIZATIONS)>=3
-TCC = $(TCC) -Ox
-BCC = $(BCC) -Ox
-!ELSEIF $(OPTIMIZATIONS)==2
-TCC = $(TCC) -O2
-BCC = $(BCC) -O2
-!ELSEIF $(OPTIMIZATIONS)==1
-TCC = $(TCC) -O1
-BCC = $(BCC) -O1
-!ENDIF
-
-# If symbols are enabled (or compiling for debugging), enable PDBs.
-#
-!IF $(DEBUG)>1 || $(SYMBOLS)!=0
-TCC = $(TCC) -Zi
-BCC = $(BCC) -Zi
-!ENDIF
-
-
-# Command line prefixes for compiling code, compiling resources,
-# linking, etc.
-#
-LTCOMPILE = $(TCC) -Fo$@
-LTRCOMPILE = $(RCC) -r
-LTLIB = lib.exe
-LTLINK = $(TCC) -Fe$@
-
-# If requested, link to the RPCRT4 library.
-#
-!IF $(USE_RPCRT4_LIB)!=0
-LTLIBS = $(LTLIBS) rpcrt4.lib
-!ENDIF
-
-# If a platform was set, force the linker to target that.
-# Note that the vcvars*.bat family of batch files typically
-# set this for you. Otherwise, the linker will attempt
-# to deduce the binary type based on the object files.
-!IFDEF PLATFORM
-LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
-LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
-!ELSE
-LTLINKOPTS = /NOLOGO
-LTLIBOPTS = /NOLOGO
-!ENDIF
-
-# When compiling for use in the WinRT environment, the following
-# linker option must be used to mark the executable as runnable
-# only in the context of an application container.
-#
-!IF $(FOR_WINRT)!=0
-LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
-!IF "$(VISUALSTUDIOVERSION)"=="12.0" || "$(VISUALSTUDIOVERSION)"=="14.0"
-!IFNDEF STORELIBPATH
-!IF "$(PLATFORM)"=="x86"
-STORELIBPATH = $(CRTLIBPATH)\store
-!ELSEIF "$(PLATFORM)"=="x64"
-STORELIBPATH = $(CRTLIBPATH)\store\amd64
-!ELSEIF "$(PLATFORM)"=="ARM"
-STORELIBPATH = $(CRTLIBPATH)\store\arm
-!ELSE
-STORELIBPATH = $(CRTLIBPATH)\store
-!ENDIF
-!ENDIF
-STORELIBPATH = $(STORELIBPATH:\\=\)
-LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(STORELIBPATH)"
-!ENDIF
-!ENDIF
-
-# When compiling for Windows Phone 8.1, an extra library path is
-# required.
-#
-!IF $(USE_WP81_OPTS)!=0
-!IFNDEF WP81LIBPATH
-!IF "$(PLATFORM)"=="x86"
-WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
-!ELSEIF "$(PLATFORM)"=="ARM"
-WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\ARM
-!ELSE
-WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
-!ENDIF
-!ENDIF
-!ENDIF
-
-# When compiling for Windows Phone 8.1, some extra linker options
-# are also required.
-#
-!IF $(USE_WP81_OPTS)!=0
-!IFDEF WP81LIBPATH
-LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(WP81LIBPATH)"
-!ENDIF
-LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE
-LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib
-LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
-!ENDIF
-
-# When compiling for UWP or the Windows 10 platform, some extra linker
-# options are also required.
-#
-!IF $(FOR_UWP)!=0 || $(FOR_WIN10)!=0
-LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib
-LTLINKOPTS = $(LTLINKOPTS) mincore.lib
-!IFDEF PSDKLIBPATH
-LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)"
-!ENDIF
-!ENDIF
-
-!IF $(FOR_WIN10)!=0
-LTLINKOPTS = $(LTLINKOPTS) /guard:cf "/LIBPATH:$(UCRTLIBPATH)"
-!IF $(DEBUG)>1
-LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrtd.lib /DEFAULTLIB:ucrtd.lib
-!ELSE
-LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib
-!ENDIF
-!ENDIF
-
-# If either debugging or symbols are enabled, enable PDBs.
-#
-!IF $(DEBUG)>1 || $(SYMBOLS)!=0
-LDFLAGS = /DEBUG $(LDOPTS)
-!ELSE
-LDFLAGS = $(LDOPTS)
-!ENDIF
-
-
-# You should not have to change anything below this line
-###############################################################################
-
-
-# Object files for the amalgamation.
-#
-LIBOBJS1 = sqlite3.lo
-
-# Determine the real value of LIBOBJ based on the 'configure' script
-#
-LIBOBJ = $(LIBOBJS1)
-
-# Determine if embedded resource compilation and usage are enabled.
-#
-!IF $(USE_RC)!=0
-LIBRESOBJS = sqlite3res.lo
-!ELSE
-LIBRESOBJS =
-!ENDIF
-
-
-# Additional compiler options for the shell. These are only effective
-# when the shell is not being dynamically linked.
-#
-!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_INTROSPECTION_PRAGMAS
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_RTREE
-!ENDIF
-
-
-# This is the default Makefile target. The objects listed here
-# are what get build when you type just "make" with no arguments.
-#
-core: dll shell
-
-# Targets that require the Tcl library.
-#
-tcl: $(ALL_TCL_TARGETS)
-
-# This Makefile target builds all of the standard binaries.
-#
-all: core tcl
-
-# Dynamic link library section.
-#
-dll: $(SQLITE3DLL)
-
-# Shell executable.
-#
-shell: $(SQLITE3EXE)
-
-
-$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
- $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
-
-Replace.exe:
- $(CSC) /target:exe $(TOP)\Replace.cs
-
-sqlite3.def: Replace.exe $(LIBOBJ)
- echo EXPORTS > sqlite3.def
- dumpbin /all $(LIBOBJ) \
- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
- | sort >> sqlite3.def
-
-$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
- $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
- /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
-
-
-# Rule to build the amalgamation
-#
-sqlite3.lo: $(SQLITE3C)
- $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C)
-
-
-# Rule to build the Win32 resources object file.
-#
-!IF $(USE_RC)!=0
-_HASHCHAR=^#
-!IF ![echo !IFNDEF VERSION > rcver.vc] && \
- ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| "%SystemRoot%\System32\find.exe" "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \
- ![echo !ENDIF >> rcver.vc]
-!INCLUDE rcver.vc
-!ENDIF
-
-RESOURCE_VERSION = $(VERSION:^#=)
-RESOURCE_VERSION = $(RESOURCE_VERSION:define=)
-RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=)
-RESOURCE_VERSION = $(RESOURCE_VERSION:"=)
-RESOURCE_VERSION = $(RESOURCE_VERSION:.=,)
-
-$(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H)
- echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
- echo #define SQLITE_RESOURCE_VERSION $(RESOURCE_VERSION) >> sqlite3rc.h
- echo #endif >> sqlite3rc.h
- $(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc
-!ENDIF
-
-
-clean:
- del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
- del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
- del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/README.first b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/README.first
deleted file mode 100644
index 5c2ea0a70f2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/README.first
+++ /dev/null
@@ -1,11 +0,0 @@
-This directory contains components use to build an autoconf-ready package
-of the SQLite amalgamation: sqlite-autoconf-30XXXXXX.tar.gz
-
-To build the autoconf amalgamation, run from the top-level:
-
- ./configure
- make amalgamation-tarball
-
-The amalgamation-tarball target (also available in "main.mk") runs the
-script tool/mkautoconfamal.sh which does the work. Refer to that script
-for details.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/README.txt b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/README.txt
deleted file mode 100644
index 6e62a4e1385..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/README.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-This package contains:
-
- * the SQLite library amalgamation source code file: sqlite3.c
- * the sqlite3.h and sqlite3ext.h header files that define the C-language
- interface to the sqlite3.c library file
- * the shell.c file used to build the sqlite3 command-line shell program
- * autoconf/automake installation infrastucture for building on POSIX
- compliant systems
- * a Makefile.msc, sqlite3.rc, and Replace.cs for building with Microsoft
- Visual C++ on Windows
-
-SUMMARY OF HOW TO BUILD
-=======================
-
- Unix: ./configure; make
- Windows: nmake /f Makefile.msc
-
-BUILDING ON POSIX
-=================
-
-The generic installation instructions for autoconf/automake are found
-in the INSTALL file.
-
-The following SQLite specific boolean options are supported:
-
- --enable-readline use readline in shell tool [default=yes]
- --enable-threadsafe build a thread-safe library [default=yes]
- --enable-dynamic-extensions support loadable extensions [default=yes]
-
-The default value for the CFLAGS variable (options passed to the C
-compiler) includes debugging symbols in the build, resulting in larger
-binaries than are necessary. Override it on the configure command
-line like this:
-
- $ CFLAGS="-Os" ./configure
-
-to produce a smaller installation footprint.
-
-Other SQLite compilation parameters can also be set using CFLAGS. For
-example:
-
- $ CFLAGS="-Os -DSQLITE_THREADSAFE=0" ./configure
-
-
-BUILDING WITH MICROSOFT VISUAL C++
-==================================
-
-To compile for Windows using Microsoft Visual C++:
-
- $ nmake /f Makefile.msc
-
-Using Microsoft Visual C++ 2005 (or later) is recommended. Several Windows
-platform variants may be built by adding additional macros to the NMAKE
-command line.
-
-Building for WinRT 8.0
-----------------------
-
- FOR_WINRT=1
-
-Using Microsoft Visual C++ 2012 (or later) is required. When using the
-above, something like the following macro will need to be added to the
-NMAKE command line as well:
-
- "NSDKLIBPATH=%WindowsSdkDir%\..\8.0\lib\win8\um\x86"
-
-Building for WinRT 8.1
-----------------------
-
- FOR_WINRT=1
-
-Using Microsoft Visual C++ 2013 (or later) is required. When using the
-above, something like the following macro will need to be added to the
-NMAKE command line as well:
-
- "NSDKLIBPATH=%WindowsSdkDir%\..\8.1\lib\winv6.3\um\x86"
-
-Building for UWP 10.0
----------------------
-
- FOR_WINRT=1 FOR_UWP=1
-
-Using Microsoft Visual C++ 2015 (or later) is required. When using the
-above, something like the following macros will need to be added to the
-NMAKE command line as well:
-
- "NSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86"
- "PSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86"
- "NUCRTLIBPATH=%UniversalCRTSdkDir%\..\10\lib\10.0.10586.0\ucrt\x86"
-
-Building for the Windows 10 SDK
--------------------------------
-
- FOR_WIN10=1
-
-Using Microsoft Visual C++ 2015 (or later) is required. When using the
-above, no other macros should be needed on the NMAKE command line.
-
-Other preprocessor defines
---------------------------
-
-Additionally, preprocessor defines may be specified by using the OPTS macro
-on the NMAKE command line. However, not all possible preprocessor defines
-may be specified in this manner as some require the amalgamation to be built
-with them enabled (see http://www.sqlite.org/compile.html). For example, the
-following will work:
-
- "OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1"
-
-However, the following will not compile unless the amalgamation was built
-with it enabled:
-
- "OPTS=-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1"
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/configure.ac b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/configure.ac
deleted file mode 100644
index 8ba221891a9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/configure.ac
+++ /dev/null
@@ -1,212 +0,0 @@
-
-#-----------------------------------------------------------------------
-# Supports the following non-standard switches.
-#
-# --enable-threadsafe
-# --enable-readline
-# --enable-editline
-# --enable-static-shell
-# --enable-dynamic-extensions
-#
-
-AC_PREREQ(2.61)
-AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org)
-AC_CONFIG_SRCDIR([sqlite3.c])
-AC_CONFIG_AUX_DIR([.])
-
-# Use automake.
-AM_INIT_AUTOMAKE([foreign])
-
-AC_SYS_LARGEFILE
-
-# Check for required programs.
-AC_PROG_CC
-AC_PROG_LIBTOOL
-AC_PROG_MKDIR_P
-
-# Check for library functions that SQLite can optionally use.
-AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r])
-AC_FUNC_STRERROR_R
-
-AC_CONFIG_FILES([Makefile sqlite3.pc])
-AC_SUBST(BUILD_CFLAGS)
-
-#-------------------------------------------------------------------------
-# Two options to enable readline compatible libraries:
-#
-# --enable-editline
-# --enable-readline
-#
-# Both are enabled by default. If, after command line processing both are
-# still enabled, the script searches for editline first and automatically
-# disables readline if it is found. So, to use readline explicitly, the
-# user must pass "--disable-editline". To disable command line editing
-# support altogether, "--disable-editline --disable-readline".
-#
-# When searching for either library, check for headers before libraries
-# as some distros supply packages that contain libraries but not header
-# files, which come as a separate development package.
-#
-AC_ARG_ENABLE(editline, [AS_HELP_STRING([--enable-editline],[use BSD libedit])])
-AC_ARG_ENABLE(readline, [AS_HELP_STRING([--enable-readline],[use readline])])
-
-AS_IF([ test x"$enable_editline" != xno ],[
- AC_CHECK_HEADERS([editline/readline.h],[
- sLIBS=$LIBS
- LIBS=""
- AC_SEARCH_LIBS([readline],[edit],[
- AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
- READLINE_LIBS="$LIBS -ltinfo"
- enable_readline=no
- ],[],[-ltinfo])
- AS_UNSET(ac_cv_search_readline)
- LIBS=$sLIBS
- ])
-])
-
-AS_IF([ test x"$enable_readline" != xno ],[
- AC_CHECK_HEADERS([readline/readline.h],[
- sLIBS=$LIBS
- LIBS=""
- AC_SEARCH_LIBS(tgetent, termcap curses ncurses ncursesw, [], [])
- AC_SEARCH_LIBS(readline,[readline edit], [
- AC_DEFINE([HAVE_READLINE],1,Define to use readline or wrapper)
- READLINE_LIBS=$LIBS
- ])
- LIBS=$sLIBS
- ])
-])
-
-AC_SUBST(READLINE_LIBS)
-#-----------------------------------------------------------------------
-
-#-----------------------------------------------------------------------
-# --enable-threadsafe
-#
-AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING(
- [--enable-threadsafe], [build a thread-safe library [default=yes]])],
- [], [enable_threadsafe=yes])
-THREADSAFE_FLAGS=-DSQLITE_THREADSAFE=0
-if test x"$enable_threadsafe" != "xno"; then
- THREADSAFE_FLAGS="-D_REENTRANT=1 -DSQLITE_THREADSAFE=1"
- AC_SEARCH_LIBS(pthread_create, pthread)
- AC_SEARCH_LIBS(pthread_mutexattr_init, pthread)
-fi
-AC_SUBST(THREADSAFE_FLAGS)
-#-----------------------------------------------------------------------
-
-#-----------------------------------------------------------------------
-# --enable-dynamic-extensions
-#
-AC_ARG_ENABLE(dynamic-extensions, [AS_HELP_STRING(
- [--enable-dynamic-extensions], [support loadable extensions [default=yes]])],
- [], [enable_dynamic_extensions=yes])
-if test x"$enable_dynamic_extensions" != "xno"; then
- AC_SEARCH_LIBS(dlopen, dl)
-else
- DYNAMIC_EXTENSION_FLAGS=-DSQLITE_OMIT_LOAD_EXTENSION=1
-fi
-AC_MSG_CHECKING([for whether to support dynamic extensions])
-AC_MSG_RESULT($enable_dynamic_extensions)
-AC_SUBST(DYNAMIC_EXTENSION_FLAGS)
-#-----------------------------------------------------------------------
-
-#-----------------------------------------------------------------------
-# --enable-fts5
-#
-AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
- [--enable-fts5], [include fts5 support [default=yes]])],
- [], [enable_fts5=yes])
-if test x"$enable_fts5" = "xyes"; then
- AC_SEARCH_LIBS(log, m)
- FTS5_FLAGS=-DSQLITE_ENABLE_FTS5
-fi
-AC_SUBST(FTS5_FLAGS)
-#-----------------------------------------------------------------------
-
-#-----------------------------------------------------------------------
-# --enable-json1
-#
-AC_ARG_ENABLE(json1, [AS_HELP_STRING(
- [--enable-json1], [include json1 support [default=yes]])],
- [], [enable_json1=yes])
-if test x"$enable_json1" = "xyes"; then
- JSON1_FLAGS=-DSQLITE_ENABLE_JSON1
-fi
-AC_SUBST(JSON1_FLAGS)
-#-----------------------------------------------------------------------
-
-#-----------------------------------------------------------------------
-# --enable-session
-#
-AC_ARG_ENABLE(session, [AS_HELP_STRING(
- [--enable-session], [enable the session extension [default=no]])],
- [], [enable_session=no])
-if test x"$enable_session" = "xyes"; then
- SESSION_FLAGS="-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
-fi
-AC_SUBST(SESSION_FLAGS)
-#-----------------------------------------------------------------------
-
-#-----------------------------------------------------------------------
-# --enable-debug
-#
-AC_ARG_ENABLE(debug, [AS_HELP_STRING(
- [--enable-debug], [build with debugging features enabled [default=no]])],
- [], [enable_session=no])
-if test x"$enable_debug" = "xyes"; then
- DEBUG_FLAGS="-DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
-fi
-AC_SUBST(DEBUG_FLAGS)
-#-----------------------------------------------------------------------
-
-#-----------------------------------------------------------------------
-# --enable-static-shell
-#
-AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(
- [--enable-static-shell],
- [statically link libsqlite3 into shell tool [default=yes]])],
- [], [enable_static_shell=yes])
-if test x"$enable_static_shell" = "xyes"; then
- EXTRA_SHELL_OBJ=sqlite3-sqlite3.$OBJEXT
-else
- EXTRA_SHELL_OBJ=libsqlite3.la
-fi
-AC_SUBST(EXTRA_SHELL_OBJ)
-#-----------------------------------------------------------------------
-
-AC_CHECK_FUNCS(posix_fallocate)
-AC_CHECK_HEADERS(zlib.h,[
- AC_SEARCH_LIBS(deflate,z,[ZLIB_FLAGS="-DSQLITE_HAVE_ZLIB"])
-])
-AC_SUBST(ZLIB_FLAGS)
-
-AC_SEARCH_LIBS(system,,,[SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM"])
-AC_SUBST(SHELL_CFLAGS)
-
-#-----------------------------------------------------------------------
-# UPDATE: Maybe it's better if users just set CFLAGS before invoking
-# configure. This option doesn't really add much...
-#
-# --enable-tempstore
-#
-# AC_ARG_ENABLE(tempstore, [AS_HELP_STRING(
-# [--enable-tempstore],
-# [in-memory temporary tables (never, no, yes, always) [default=no]])],
-# [], [enable_tempstore=no])
-# AC_MSG_CHECKING([for whether or not to store temp tables in-memory])
-# case "$enable_tempstore" in
-# never ) TEMP_STORE=0 ;;
-# no ) TEMP_STORE=1 ;;
-# always ) TEMP_STORE=3 ;;
-# yes ) TEMP_STORE=3 ;;
-# * )
-# TEMP_STORE=1
-# enable_tempstore=yes
-# ;;
-# esac
-# AC_MSG_RESULT($enable_tempstore)
-# AC_SUBST(TEMP_STORE)
-#-----------------------------------------------------------------------
-
-AC_OUTPUT
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/Makefile.in b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/Makefile.in
deleted file mode 100644
index 3e481dadfe8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/Makefile.in
+++ /dev/null
@@ -1,440 +0,0 @@
-# Makefile.in --
-#
-# This file is a Makefile for Sample TEA Extension. If it has the name
-# "Makefile.in" then it is a template for a Makefile; to generate the
-# actual Makefile, run "./configure", which is a configuration script
-# generated by the "autoconf" program (constructs like "@foo@" will get
-# replaced in the actual Makefile.
-#
-# Copyright (c) 1999 Scriptics Corporation.
-# Copyright (c) 2002-2005 ActiveState Corporation.
-#
-# See the file "license.terms" for information on usage and redistribution
-# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-#
-# RCS: @(#) $Id: Makefile.in,v 1.59 2005/07/26 19:17:02 mdejong Exp $
-
-#========================================================================
-# Add additional lines to handle any additional AC_SUBST cases that
-# have been added in a customized configure script.
-#========================================================================
-
-#SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@
-
-#========================================================================
-# Nothing of the variables below this line should need to be changed.
-# Please check the TARGETS section below to make sure the make targets
-# are correct.
-#========================================================================
-
-#========================================================================
-# The names of the source files is defined in the configure script.
-# The object files are used for linking into the final library.
-# This will be used when a dist target is added to the Makefile.
-# It is not important to specify the directory, as long as it is the
-# $(srcdir) or in the generic, win or unix subdirectory.
-#========================================================================
-
-PKG_SOURCES = @PKG_SOURCES@
-PKG_OBJECTS = @PKG_OBJECTS@
-
-PKG_STUB_SOURCES = @PKG_STUB_SOURCES@
-PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@
-
-#========================================================================
-# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with
-# this package that need to be installed, if any.
-#========================================================================
-
-PKG_TCL_SOURCES = @PKG_TCL_SOURCES@
-
-#========================================================================
-# This is a list of public header files to be installed, if any.
-#========================================================================
-
-PKG_HEADERS = @PKG_HEADERS@
-
-#========================================================================
-# "PKG_LIB_FILE" refers to the library (dynamic or static as per
-# configuration options) composed of the named objects.
-#========================================================================
-
-PKG_LIB_FILE = @PKG_LIB_FILE@
-PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@
-
-lib_BINARIES = $(PKG_LIB_FILE)
-BINARIES = $(lib_BINARIES)
-
-SHELL = @SHELL@
-
-srcdir = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-libdir = @libdir@
-datarootdir = @datarootdir@
-datadir = @datadir@
-mandir = @mandir@
-includedir = @includedir@
-
-DESTDIR =
-
-PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION)
-pkgdatadir = $(datadir)/$(PKG_DIR)
-pkglibdir = $(libdir)/$(PKG_DIR)
-pkgincludedir = $(includedir)/$(PKG_DIR)
-
-top_builddir = .
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-CC = @CC@
-CFLAGS_DEFAULT = @CFLAGS_DEFAULT@
-CFLAGS_WARNING = @CFLAGS_WARNING@
-CLEANFILES = @CLEANFILES@
-EXEEXT = @EXEEXT@
-LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
-MAKE_LIB = @MAKE_LIB@
-MAKE_SHARED_LIB = @MAKE_SHARED_LIB@
-MAKE_STATIC_LIB = @MAKE_STATIC_LIB@
-MAKE_STUB_LIB = @MAKE_STUB_LIB@
-OBJEXT = @OBJEXT@
-RANLIB = @RANLIB@
-RANLIB_STUB = @RANLIB_STUB@
-SHLIB_CFLAGS = @SHLIB_CFLAGS@
-SHLIB_LD = @SHLIB_LD@
-SHLIB_LD_LIBS = @SHLIB_LD_LIBS@
-STLIB_LD = @STLIB_LD@
-#TCL_DEFS = @TCL_DEFS@
-TCL_BIN_DIR = @TCL_BIN_DIR@
-TCL_SRC_DIR = @TCL_SRC_DIR@
-#TK_BIN_DIR = @TK_BIN_DIR@
-#TK_SRC_DIR = @TK_SRC_DIR@
-
-# This is no longer necessary even for packages that use private Tcl headers
-#TCL_TOP_DIR_NATIVE = @TCL_TOP_DIR_NATIVE@
-# Not used, but retained for reference of what libs Tcl required
-#TCL_LIBS = @TCL_LIBS@
-
-#========================================================================
-# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
-# package without installing. The other environment variables allow us
-# to test against an uninstalled Tcl. Add special env vars that you
-# require for testing here (like TCLX_LIBRARY).
-#========================================================================
-
-EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR)
-#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
-TCLLIBPATH = $(top_builddir)
-TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \
- @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
- PATH="$(EXTRA_PATH):$(PATH)" \
- TCLLIBPATH="$(TCLLIBPATH)"
-# TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
-
-TCLSH_PROG = @TCLSH_PROG@
-TCLSH = $(TCLSH_ENV) $(TCLSH_PROG)
-
-#WISH_PROG = @WISH_PROG@
-#WISH = $(TCLSH_ENV) $(WISH_PROG)
-
-
-SHARED_BUILD = @SHARED_BUILD@
-
-INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I$(srcdir)/..
-#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@
-
-PKG_CFLAGS = @PKG_CFLAGS@
-
-# TCL_DEFS is not strictly need here, but if you remove it, then you
-# must make sure that configure.in checks for the necessary components
-# that your library may use. TCL_DEFS can actually be a problem if
-# you do not compile with a similar machine setup as the Tcl core was
-# compiled with.
-#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
-DEFS = @DEFS@ $(PKG_CFLAGS)
-
-CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
-
-CPPFLAGS = @CPPFLAGS@
-LIBS = @PKG_LIBS@ @LIBS@
-AR = @AR@
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-
-#========================================================================
-# Start of user-definable TARGETS section
-#========================================================================
-
-#========================================================================
-# TEA TARGETS. Please note that the "libraries:" target refers to platform
-# independent files, and the "binaries:" target inclues executable programs and
-# platform-dependent libraries. Modify these targets so that they install
-# the various pieces of your package. The make and install rules
-# for the BINARIES that you specified above have already been done.
-#========================================================================
-
-all: binaries libraries doc
-
-#========================================================================
-# The binaries target builds executable programs, Windows .dll's, unix
-# shared/static libraries, and any other platform-dependent files.
-# The list of targets to build for "binaries:" is specified at the top
-# of the Makefile, in the "BINARIES" variable.
-#========================================================================
-
-binaries: $(BINARIES)
-
-libraries:
-
-
-#========================================================================
-# Your doc target should differentiate from doc builds (by the developer)
-# and doc installs (see install-doc), which just install the docs on the
-# end user machine when building from source.
-#========================================================================
-
-doc:
- @echo "If you have documentation to create, place the commands to"
- @echo "build the docs in the 'doc:' target. For example:"
- @echo " xml2nroff sample.xml > sample.n"
- @echo " xml2html sample.xml > sample.html"
-
-install: all install-binaries install-libraries install-doc
-
-install-binaries: binaries install-lib-binaries install-bin-binaries
-
-#========================================================================
-# This rule installs platform-independent files, such as header files.
-# The list=...; for p in $$list handles the empty list case x-platform.
-#========================================================================
-
-install-libraries: libraries
- @mkdir -p $(DESTDIR)$(includedir)
- @echo "Installing header files in $(DESTDIR)$(includedir)"
- @list='$(PKG_HEADERS)'; for i in $$list; do \
- echo "Installing $(srcdir)/$$i" ; \
- $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
- done;
-
-#========================================================================
-# Install documentation. Unix manpages should go in the $(mandir)
-# directory.
-#========================================================================
-
-install-doc: doc
- @mkdir -p $(DESTDIR)$(mandir)/mann
- @echo "Installing documentation in $(DESTDIR)$(mandir)"
- @list='$(srcdir)/doc/*.n'; for i in $$list; do \
- echo "Installing $$i"; \
- rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \
- $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
- done
-
-test: binaries libraries
- @echo "SQLite TEA distribution does not include tests"
-
-shell: binaries libraries
- @$(TCLSH) $(SCRIPT)
-
-gdb:
- $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)
-
-depend:
-
-#========================================================================
-# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
-# mentioned above. That will ensure that this target is built when you
-# run "make binaries".
-#
-# The $(PKG_OBJECTS) objects are created and linked into the final
-# library. In most cases these object files will correspond to the
-# source files above.
-#========================================================================
-
-$(PKG_LIB_FILE): $(PKG_OBJECTS)
- -rm -f $(PKG_LIB_FILE)
- ${MAKE_LIB}
- $(RANLIB) $(PKG_LIB_FILE)
-
-$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
- -rm -f $(PKG_STUB_LIB_FILE)
- ${MAKE_STUB_LIB}
- $(RANLIB_STUB) $(PKG_STUB_LIB_FILE)
-
-#========================================================================
-# We need to enumerate the list of .c to .o lines here.
-#
-# In the following lines, $(srcdir) refers to the toplevel directory
-# containing your extension. If your sources are in a subdirectory,
-# you will have to modify the paths to reflect this:
-#
-# sample.$(OBJEXT): $(srcdir)/generic/sample.c
-# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
-#
-# Setting the VPATH variable to a list of paths will cause the makefile
-# to look into these paths when resolving .c to .obj dependencies.
-# As necessary, add $(srcdir):$(srcdir)/compat:....
-#========================================================================
-
-VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win
-
-.c.@OBJEXT@:
- $(COMPILE) -c `@CYGPATH@ $<` -o $@
-
-#========================================================================
-# Distribution creation
-# You may need to tweak this target to make it work correctly.
-#========================================================================
-
-#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
-COMPRESS = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
-DIST_ROOT = /tmp/dist
-DIST_DIR = $(DIST_ROOT)/$(PKG_DIR)
-
-dist-clean:
- rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*
-
-dist: dist-clean
- mkdir -p $(DIST_DIR)
- cp -p $(srcdir)/README* $(srcdir)/license* \
- $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
- $(DIST_DIR)/
- chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
- chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in
-
- for i in $(srcdir)/*.[ch]; do \
- if [ -f $$i ]; then \
- cp -p $$i $(DIST_DIR)/ ; \
- fi; \
- done;
-
- mkdir $(DIST_DIR)/tclconfig
- cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
- $(DIST_DIR)/tclconfig/
- chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
- chmod +x $(DIST_DIR)/tclconfig/install-sh
-
- list='demos doc generic library mac tests unix win'; \
- for p in $$list; do \
- if test -d $(srcdir)/$$p ; then \
- mkdir $(DIST_DIR)/$$p; \
- cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \
- fi; \
- done
-
- (cd $(DIST_ROOT); $(COMPRESS);)
-
-#========================================================================
-# End of user-definable section
-#========================================================================
-
-#========================================================================
-# Don't modify the file to clean here. Instead, set the "CLEANFILES"
-# variable in configure.in
-#========================================================================
-
-clean:
- -test -z "$(BINARIES)" || rm -f $(BINARIES)
- -rm -f *.$(OBJEXT) core *.core
- -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean: clean
- -rm -f *.tab.c
- -rm -f $(CONFIG_CLEAN_FILES)
- -rm -f config.h config.cache config.log config.status
-
-#========================================================================
-# Install binary object libraries. On Windows this includes both .dll and
-# .lib files. Because the .lib files are not explicitly listed anywhere,
-# we need to deduce their existence from the .dll file of the same name.
-# Library files go into the lib directory.
-# In addition, this will generate the pkgIndex.tcl
-# file in the install location (assuming it can find a usable tclsh shell)
-#
-# You should not have to modify this target.
-#========================================================================
-
-install-lib-binaries: binaries
- @mkdir -p $(DESTDIR)$(pkglibdir)
- @list='$(lib_BINARIES)'; for p in $$list; do \
- if test -f $$p; then \
- echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
- $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \
- stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
- if test "x$$stub" = "xstub"; then \
- echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
- $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
- else \
- echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
- $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
- fi; \
- ext=`echo $$p|sed -e "s/.*\.//"`; \
- if test "x$$ext" = "xdll"; then \
- lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
- if test -f $$lib; then \
- echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
- $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
- fi; \
- fi; \
- fi; \
- done
- @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
- if test -f $(srcdir)/$$p; then \
- destp=`basename $$p`; \
- echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
- $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
- fi; \
- done
- @if test "x$(SHARED_BUILD)" = "x1"; then \
- echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
- $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
- fi
-
-#========================================================================
-# Install binary executables (e.g. .exe files and dependent .dll files)
-# This is for files that must go in the bin directory (located next to
-# wish and tclsh), like dependent .dll files on Windows.
-#
-# You should not have to modify this target, except to define bin_BINARIES
-# above if necessary.
-#========================================================================
-
-install-bin-binaries: binaries
- @mkdir -p $(DESTDIR)$(bindir)
- @list='$(bin_BINARIES)'; for p in $$list; do \
- if test -f $$p; then \
- echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
- $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
- fi; \
- done
-
-.SUFFIXES: .c .$(OBJEXT)
-
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- cd $(top_builddir) \
- && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-uninstall-binaries:
- list='$(lib_BINARIES)'; for p in $$list; do \
- rm -f $(DESTDIR)$(pkglibdir)/$$p; \
- done
- list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
- p=`basename $$p`; \
- rm -f $(DESTDIR)$(pkglibdir)/$$p; \
- done
- list='$(bin_BINARIES)'; for p in $$list; do \
- rm -f $(DESTDIR)$(bindir)/$$p; \
- done
-
-.PHONY: all binaries clean depend distclean doc install libraries test
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/README b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/README
deleted file mode 100644
index 99dc8b8f03c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/README
+++ /dev/null
@@ -1,36 +0,0 @@
-This is the SQLite extension for Tcl using the Tcl Extension
-Architecture (TEA). For additional information on SQLite see
-
- http://www.sqlite.org/
-
-
-UNIX BUILD
-==========
-
-Building under most UNIX systems is easy, just run the configure script
-and then run make. For more information about the build process, see
-the tcl/unix/README file in the Tcl src dist. The following minimal
-example will install the extension in the /opt/tcl directory.
-
- $ cd sqlite-*-tea
- $ ./configure --prefix=/opt/tcl
- $ make
- $ make install
-
-WINDOWS BUILD
-=============
-
-The recommended method to build extensions under windows is to use the
-Msys + Mingw build process. This provides a Unix-style build while
-generating native Windows binaries. Using the Msys + Mingw build tools
-means that you can use the same configure script as per the Unix build
-to create a Makefile. See the tcl/win/README file for the URL of
-the Msys + Mingw download.
-
-If you have VC++ then you may wish to use the files in the win
-subdirectory and build the extension using just VC++. These files have
-been designed to be as generic as possible but will require some
-additional maintenance by the project developer to synchronise with
-the TEA configure.in and Makefile.in files. Instructions for using the
-VC++ makefile are written in the first part of the Makefile.vc
-file.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/aclocal.m4 b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/aclocal.m4
deleted file mode 100644
index 0b057391d29..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/aclocal.m4
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Include the TEA standard macro set
-#
-
-builtin(include,tclconfig/tcl.m4)
-
-#
-# Add here whatever m4 macros you want to define for your package
-#
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/configure.ac b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/configure.ac
deleted file mode 100644
index 7fca05b2e74..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/configure.ac
+++ /dev/null
@@ -1,201 +0,0 @@
-#!/bin/bash -norc
-dnl This file is an input file used by the GNU "autoconf" program to
-dnl generate the file "configure", which is run during Tcl installation
-dnl to configure the system for the local environment.
-#
-# RCS: @(#) $Id: configure.in,v 1.43 2005/07/26 19:17:05 mdejong Exp $
-
-#-----------------------------------------------------------------------
-# Sample configure.in for Tcl Extensions. The only places you should
-# need to modify this file are marked by the string __CHANGE__
-#-----------------------------------------------------------------------
-
-#-----------------------------------------------------------------------
-# __CHANGE__
-# Set your package name and version numbers here.
-#
-# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
-# set as provided. These will also be added as -D defs in your Makefile
-# so you can encode the package version directly into the source files.
-#-----------------------------------------------------------------------
-
-AC_INIT([sqlite], [3.7.4])
-
-#--------------------------------------------------------------------
-# Call TEA_INIT as the first TEA_ macro to set up initial vars.
-# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
-# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
-#--------------------------------------------------------------------
-
-TEA_INIT([3.9])
-
-AC_CONFIG_AUX_DIR(tclconfig)
-
-#--------------------------------------------------------------------
-# Load the tclConfig.sh file
-#--------------------------------------------------------------------
-
-TEA_PATH_TCLCONFIG
-TEA_LOAD_TCLCONFIG
-
-#--------------------------------------------------------------------
-# Load the tkConfig.sh file if necessary (Tk extension)
-#--------------------------------------------------------------------
-
-#TEA_PATH_TKCONFIG
-#TEA_LOAD_TKCONFIG
-
-#-----------------------------------------------------------------------
-# Handle the --prefix=... option by defaulting to what Tcl gave.
-# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
-#-----------------------------------------------------------------------
-
-TEA_PREFIX
-
-#-----------------------------------------------------------------------
-# Standard compiler checks.
-# This sets up CC by using the CC env var, or looks for gcc otherwise.
-# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create
-# the basic setup necessary to compile executables.
-#-----------------------------------------------------------------------
-
-TEA_SETUP_COMPILER
-
-#-----------------------------------------------------------------------
-# __CHANGE__
-# Specify the C source files to compile in TEA_ADD_SOURCES,
-# public headers that need to be installed in TEA_ADD_HEADERS,
-# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
-# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
-# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
-# and PKG_TCL_SOURCES.
-#-----------------------------------------------------------------------
-
-TEA_ADD_SOURCES([tclsqlite3.c])
-TEA_ADD_HEADERS([])
-TEA_ADD_INCLUDES([-I\"`\${CYGPATH} \${srcdir}/generic`\"])
-TEA_ADD_LIBS([])
-TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS3=1])
-TEA_ADD_CFLAGS([-DSQLITE_3_SUFFIX_ONLY=1])
-TEA_ADD_CFLAGS([-DSQLITE_ENABLE_RTREE=1])
-TEA_ADD_STUB_SOURCES([])
-TEA_ADD_TCL_SOURCES([])
-
-#--------------------------------------------------------------------
-# The --with-system-sqlite causes the TCL bindings to SQLite to use
-# the system shared library for SQLite rather than statically linking
-# against its own private copy. This is dangerous and leads to
-# undersirable dependences and is not recommended.
-# Patchs from rmax.
-#--------------------------------------------------------------------
-AC_ARG_WITH([system-sqlite],
- [AC_HELP_STRING([--with-system-sqlite],
- [use a system-supplied libsqlite3 instead of the bundled one])],
- [], [with_system_sqlite=no])
-if test x$with_system_sqlite != xno; then
- AC_CHECK_HEADER([sqlite3.h],
- [AC_CHECK_LIB([sqlite3],[sqlite3_initialize],
- [AC_DEFINE(USE_SYSTEM_SQLITE)
- LIBS="$LIBS -lsqlite3"])])
-fi
-
-#--------------------------------------------------------------------
-# __CHANGE__
-# Choose which headers you need. Extension authors should try very
-# hard to only rely on the Tcl public header files. Internal headers
-# contain private data structures and are subject to change without
-# notice.
-# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
-#--------------------------------------------------------------------
-
-TEA_PUBLIC_TCL_HEADERS
-#TEA_PRIVATE_TCL_HEADERS
-
-#TEA_PUBLIC_TK_HEADERS
-#TEA_PRIVATE_TK_HEADERS
-#TEA_PATH_X
-
-#--------------------------------------------------------------------
-# Check whether --enable-threads or --disable-threads was given.
-# This auto-enables if Tcl was compiled threaded.
-#--------------------------------------------------------------------
-
-TEA_ENABLE_THREADS
-if test "${TCL_THREADS}" = "1" ; then
- AC_DEFINE(SQLITE_THREADSAFE, 1, [Trigger sqlite threadsafe build])
- # Not automatically added by Tcl because its assumed Tcl links to them,
- # but it may not if it isn't really a threaded build.
- TEA_ADD_LIBS([$THREADS_LIBS])
-else
- AC_DEFINE(SQLITE_THREADSAFE, 0, [Trigger sqlite non-threadsafe build])
-fi
-
-#--------------------------------------------------------------------
-# The statement below defines a collection of symbols related to
-# building as a shared library instead of a static library.
-#--------------------------------------------------------------------
-
-TEA_ENABLE_SHARED
-
-#--------------------------------------------------------------------
-# This macro figures out what flags to use with the compiler/linker
-# when building shared/static debug/optimized objects. This information
-# can be taken from the tclConfig.sh file, but this figures it all out.
-#--------------------------------------------------------------------
-
-TEA_CONFIG_CFLAGS
-
-#--------------------------------------------------------------------
-# Set the default compiler switches based on the --enable-symbols option.
-#--------------------------------------------------------------------
-
-TEA_ENABLE_SYMBOLS
-
-#--------------------------------------------------------------------
-# Everyone should be linking against the Tcl stub library. If you
-# can't for some reason, remove this definition. If you aren't using
-# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
-# link against the non-stubbed Tcl library. Add Tk too if necessary.
-#--------------------------------------------------------------------
-
-AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
-#AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])
-
-
-#--------------------------------------------------------------------
-# Redefine fdatasync as fsync on systems that lack fdatasync
-#--------------------------------------------------------------------
-#
-#AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync))
-# Check for library functions that SQLite can optionally use.
-AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r])
-
-AC_FUNC_STRERROR_R
-
-
-#--------------------------------------------------------------------
-# This macro generates a line to use when building a library. It
-# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
-# and TEA_LOAD_TCLCONFIG macros above.
-#--------------------------------------------------------------------
-
-TEA_MAKE_LIB
-
-#--------------------------------------------------------------------
-# Determine the name of the tclsh and/or wish executables in the
-# Tcl and Tk build directories or the location they were installed
-# into. These paths are used to support running test cases only,
-# the Makefile should not be making use of these paths to generate
-# a pkgIndex.tcl file or anything else at extension build time.
-#--------------------------------------------------------------------
-
-TEA_PROG_TCLSH
-#TEA_PROG_WISH
-
-#--------------------------------------------------------------------
-# Finally, substitute all of the various values into the Makefile.
-# You may alternatively have a special pkgIndex.tcl.in or other files
-# which require substituting th AC variables in. Include these here.
-#--------------------------------------------------------------------
-
-AC_OUTPUT([Makefile pkgIndex.tcl])
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/doc/sqlite3.n b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/doc/sqlite3.n
deleted file mode 100644
index 13913e5583d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/doc/sqlite3.n
+++ /dev/null
@@ -1,15 +0,0 @@
-.TH sqlite3 n 4.1 "Tcl-Extensions"
-.HS sqlite3 tcl
-.BS
-.SH NAME
-sqlite3 \- an interface to the SQLite3 database engine
-.SH SYNOPSIS
-\fBsqlite3\fI command_name ?filename?\fR
-.br
-.SH DESCRIPTION
-SQLite3 is a self-contains, zero-configuration, transactional SQL database
-engine. This extension provides an easy to use interface for accessing
-SQLite database files from Tcl.
-.PP
-For full documentation see \fIhttp://www.sqlite.org/\fR and
-in particular \fIhttp://www.sqlite.org/tclsqlite.html\fR.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/license.terms b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/license.terms
deleted file mode 100644
index 723c4cd3c6e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/license.terms
+++ /dev/null
@@ -1,6 +0,0 @@
-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.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/pkgIndex.tcl.in b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/pkgIndex.tcl.in
deleted file mode 100644
index bc585f73b30..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/pkgIndex.tcl.in
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Tcl package index file
-#
-# Note sqlite*3* init specifically
-#
-package ifneeded sqlite3 @PACKAGE_VERSION@ \
- [list load [file join $dir @PKG_LIB_FILE@] Sqlite3]
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/tclconfig/install-sh b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/tclconfig/install-sh
deleted file mode 100644
index 7c34c3f9260..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/tclconfig/install-sh
+++ /dev/null
@@ -1,528 +0,0 @@
-#!/bin/sh
-# install - install a program, script, or datafile
-
-scriptversion=2011-04-20.01; # UTC
-
-# This originates from X11R5 (mit/util/scripts/install.sh), which was
-# later released in X11R6 (xc/config/util/install.sh) with the
-# following copyright and license.
-#
-# Copyright (C) 1994 X Consortium
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
-# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the name of the X Consortium shall not
-# be used in advertising or otherwise to promote the sale, use or other deal-
-# ings in this Software without prior written authorization from the X Consor-
-# tium.
-#
-#
-# FSF changes to this file are in the public domain.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.
-
-nl='
-'
-IFS=" "" $nl"
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit=${DOITPROG-}
-if test -z "$doit"; then
- doit_exec=exec
-else
- doit_exec=$doit
-fi
-
-# Put in absolute file names if you don't have them in your path;
-# or use environment vars.
-
-chgrpprog=${CHGRPPROG-chgrp}
-chmodprog=${CHMODPROG-chmod}
-chownprog=${CHOWNPROG-chown}
-cmpprog=${CMPPROG-cmp}
-cpprog=${CPPROG-cp}
-mkdirprog=${MKDIRPROG-mkdir}
-mvprog=${MVPROG-mv}
-rmprog=${RMPROG-rm}
-stripprog=${STRIPPROG-strip}
-
-posix_glob='?'
-initialize_posix_glob='
- test "$posix_glob" != "?" || {
- if (set -f) 2>/dev/null; then
- posix_glob=
- else
- posix_glob=:
- fi
- }
-'
-
-posix_mkdir=
-
-# Desired mode of installed file.
-mode=0755
-
-chgrpcmd=
-chmodcmd=$chmodprog
-chowncmd=
-mvcmd=$mvprog
-rmcmd="$rmprog -f"
-stripcmd=
-
-src=
-dst=
-dir_arg=
-dst_arg=
-
-copy_on_change=false
-no_target_directory=
-
-usage="\
-Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
- or: $0 [OPTION]... SRCFILES... DIRECTORY
- or: $0 [OPTION]... -t DIRECTORY SRCFILES...
- or: $0 [OPTION]... -d DIRECTORIES...
-
-In the 1st form, copy SRCFILE to DSTFILE.
-In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
-In the 4th, create DIRECTORIES.
-
-Options:
- --help display this help and exit.
- --version display version info and exit.
-
- -c (ignored)
- -C install only if different (preserve the last data modification time)
- -d create directories instead of installing files.
- -g GROUP $chgrpprog installed files to GROUP.
- -m MODE $chmodprog installed files to MODE.
- -o USER $chownprog installed files to USER.
- -s $stripprog installed files.
- -S $stripprog installed files.
- -t DIRECTORY install into DIRECTORY.
- -T report an error if DSTFILE is a directory.
-
-Environment variables override the default commands:
- CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
- RMPROG STRIPPROG
-"
-
-while test $# -ne 0; do
- case $1 in
- -c) ;;
-
- -C) copy_on_change=true;;
-
- -d) dir_arg=true;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift;;
-
- --help) echo "$usage"; exit $?;;
-
- -m) mode=$2
- case $mode in
- *' '* | *' '* | *'
-'* | *'*'* | *'?'* | *'['*)
- echo "$0: invalid mode: $mode" >&2
- exit 1;;
- esac
- shift;;
-
- -o) chowncmd="$chownprog $2"
- shift;;
-
- -s) stripcmd=$stripprog;;
-
- -S) stripcmd="$stripprog $2"
- shift;;
-
- -t) dst_arg=$2
- shift;;
-
- -T) no_target_directory=true;;
-
- --version) echo "$0 $scriptversion"; exit $?;;
-
- --) shift
- break;;
-
- -*) echo "$0: invalid option: $1" >&2
- exit 1;;
-
- *) break;;
- esac
- shift
-done
-
-if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
- # When -d is used, all remaining arguments are directories to create.
- # When -t is used, the destination is already specified.
- # Otherwise, the last argument is the destination. Remove it from $@.
- for arg
- do
- if test -n "$dst_arg"; then
- # $@ is not empty: it contains at least $arg.
- set fnord "$@" "$dst_arg"
- shift # fnord
- fi
- shift # arg
- dst_arg=$arg
- done
-fi
-
-if test $# -eq 0; then
- if test -z "$dir_arg"; then
- echo "$0: no input file specified." >&2
- exit 1
- fi
- # It's OK to call `install-sh -d' without argument.
- # This can happen when creating conditional directories.
- exit 0
-fi
-
-if test -z "$dir_arg"; then
- do_exit='(exit $ret); exit $ret'
- trap "ret=129; $do_exit" 1
- trap "ret=130; $do_exit" 2
- trap "ret=141; $do_exit" 13
- trap "ret=143; $do_exit" 15
-
- # Set umask so as not to create temps with too-generous modes.
- # However, 'strip' requires both read and write access to temps.
- case $mode in
- # Optimize common cases.
- *644) cp_umask=133;;
- *755) cp_umask=22;;
-
- *[0-7])
- if test -z "$stripcmd"; then
- u_plus_rw=
- else
- u_plus_rw='% 200'
- fi
- cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
- *)
- if test -z "$stripcmd"; then
- u_plus_rw=
- else
- u_plus_rw=,u+rw
- fi
- cp_umask=$mode$u_plus_rw;;
- esac
-fi
-
-for src
-do
- # Protect names starting with `-'.
- case $src in
- -*) src=./$src;;
- esac
-
- if test -n "$dir_arg"; then
- dst=$src
- dstdir=$dst
- test -d "$dstdir"
- dstdir_status=$?
- else
-
- # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
- # might cause directories to be created, which would be especially bad
- # if $src (and thus $dsttmp) contains '*'.
- if test ! -f "$src" && test ! -d "$src"; then
- echo "$0: $src does not exist." >&2
- exit 1
- fi
-
- if test -z "$dst_arg"; then
- echo "$0: no destination specified." >&2
- exit 1
- fi
-
- dst=$dst_arg
- # Protect names starting with `-'.
- case $dst in
- -*) dst=./$dst;;
- esac
-
- # If destination is a directory, append the input filename; won't work
- # if double slashes aren't ignored.
- if test -d "$dst"; then
- if test -n "$no_target_directory"; then
- echo "$0: $dst_arg: Is a directory" >&2
- exit 1
- fi
- dstdir=$dst
- dst=$dstdir/`basename "$src"`
- dstdir_status=0
- else
- # Prefer dirname, but fall back on a substitute if dirname fails.
- dstdir=`
- (dirname "$dst") 2>/dev/null ||
- expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$dst" : 'X\(//\)[^/]' \| \
- X"$dst" : 'X\(//\)$' \| \
- X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
- echo X"$dst" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'
- `
-
- test -d "$dstdir"
- dstdir_status=$?
- fi
- fi
-
- obsolete_mkdir_used=false
-
- if test $dstdir_status != 0; then
- case $posix_mkdir in
- '')
- # Create intermediate dirs using mode 755 as modified by the umask.
- # This is like FreeBSD 'install' as of 1997-10-28.
- umask=`umask`
- case $stripcmd.$umask in
- # Optimize common cases.
- *[2367][2367]) mkdir_umask=$umask;;
- .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
-
- *[0-7])
- mkdir_umask=`expr $umask + 22 \
- - $umask % 100 % 40 + $umask % 20 \
- - $umask % 10 % 4 + $umask % 2
- `;;
- *) mkdir_umask=$umask,go-w;;
- esac
-
- # With -d, create the new directory with the user-specified mode.
- # Otherwise, rely on $mkdir_umask.
- if test -n "$dir_arg"; then
- mkdir_mode=-m$mode
- else
- mkdir_mode=
- fi
-
- posix_mkdir=false
- case $umask in
- *[123567][0-7][0-7])
- # POSIX mkdir -p sets u+wx bits regardless of umask, which
- # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
- ;;
- *)
- tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
- trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
-
- if (umask $mkdir_umask &&
- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
- then
- if test -z "$dir_arg" || {
- # Check for POSIX incompatibilities with -m.
- # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
- # other-writeable bit of parent directory when it shouldn't.
- # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
- ls_ld_tmpdir=`ls -ld "$tmpdir"`
- case $ls_ld_tmpdir in
- d????-?r-*) different_mode=700;;
- d????-?--*) different_mode=755;;
- *) false;;
- esac &&
- $mkdirprog -m$different_mode -p -- "$tmpdir" && {
- ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
- test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
- }
- }
- then posix_mkdir=:
- fi
- rmdir "$tmpdir/d" "$tmpdir"
- else
- # Remove any dirs left behind by ancient mkdir implementations.
- rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
- fi
- trap '' 0;;
- esac;;
- esac
-
- if
- $posix_mkdir && (
- umask $mkdir_umask &&
- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
- )
- then :
- else
-
- # The umask is ridiculous, or mkdir does not conform to POSIX,
- # or it failed possibly due to a race condition. Create the
- # directory the slow way, step by step, checking for races as we go.
-
- case $dstdir in
- /*) prefix='/';;
- -*) prefix='./';;
- *) prefix='';;
- esac
-
- eval "$initialize_posix_glob"
-
- oIFS=$IFS
- IFS=/
- $posix_glob set -f
- set fnord $dstdir
- shift
- $posix_glob set +f
- IFS=$oIFS
-
- prefixes=
-
- for d
- do
- test -z "$d" && continue
-
- prefix=$prefix$d
- if test -d "$prefix"; then
- prefixes=
- else
- if $posix_mkdir; then
- (umask=$mkdir_umask &&
- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
- # Don't fail if two instances are running concurrently.
- test -d "$prefix" || exit 1
- else
- case $prefix in
- *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
- *) qprefix=$prefix;;
- esac
- prefixes="$prefixes '$qprefix'"
- fi
- fi
- prefix=$prefix/
- done
-
- if test -n "$prefixes"; then
- # Don't fail if two instances are running concurrently.
- (umask $mkdir_umask &&
- eval "\$doit_exec \$mkdirprog $prefixes") ||
- test -d "$dstdir" || exit 1
- obsolete_mkdir_used=true
- fi
- fi
- fi
-
- if test -n "$dir_arg"; then
- { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
- { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
- { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
- test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
- else
-
- # Make a couple of temp file names in the proper directory.
- dsttmp=$dstdir/_inst.$$_
- rmtmp=$dstdir/_rm.$$_
-
- # Trap to clean up those temp files at exit.
- trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
-
- # Copy the file name to the temp name.
- (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
-
- # and set any options; do chmod last to preserve setuid bits.
- #
- # If any of these fail, we abort the whole thing. If we want to
- # ignore errors from any of these, just make sure not to ignore
- # errors from the above "$doit $cpprog $src $dsttmp" command.
- #
- { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
- { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
- { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
- { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
-
- # If -C, don't bother to copy if it wouldn't change the file.
- if $copy_on_change &&
- old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
- new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
-
- eval "$initialize_posix_glob" &&
- $posix_glob set -f &&
- set X $old && old=:$2:$4:$5:$6 &&
- set X $new && new=:$2:$4:$5:$6 &&
- $posix_glob set +f &&
-
- test "$old" = "$new" &&
- $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
- then
- rm -f "$dsttmp"
- else
- # Rename the file to the real destination.
- $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
-
- # The rename failed, perhaps because mv can't rename something else
- # to itself, or perhaps because mv is so ancient that it does not
- # support -f.
- {
- # Now remove or move aside any old file at destination location.
- # We try this two ways since rm can't unlink itself on some
- # systems and the destination file might be busy for other
- # reasons. In this case, the final cleanup might fail but the new
- # file should still install successfully.
- {
- test ! -f "$dst" ||
- $doit $rmcmd -f "$dst" 2>/dev/null ||
- { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
- { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
- } ||
- { echo "$0: cannot unlink or rename $dst" >&2
- (exit 1); exit 1
- }
- } &&
-
- # Now rename the file to the real destination.
- $doit $mvcmd "$dsttmp" "$dst"
- }
- fi || exit 1
-
- trap '' 0
- fi
-done
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-time-zone: "UTC"
-# time-stamp-end: "; # UTC"
-# End:
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/tclconfig/tcl.m4 b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/tclconfig/tcl.m4
deleted file mode 100644
index 4b4bd1e8889..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/tclconfig/tcl.m4
+++ /dev/null
@@ -1,4168 +0,0 @@
-# tcl.m4 --
-#
-# This file provides a set of autoconf macros to help TEA-enable
-# a Tcl extension.
-#
-# Copyright (c) 1999-2000 Ajuba Solutions.
-# Copyright (c) 2002-2005 ActiveState Corporation.
-#
-# See the file "license.terms" for information on usage and redistribution
-# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-
-AC_PREREQ(2.57)
-
-dnl TEA extensions pass us the version of TEA they think they
-dnl are compatible with (must be set in TEA_INIT below)
-dnl TEA_VERSION="3.9"
-
-# Possible values for key variables defined:
-#
-# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem')
-# TEA_PLATFORM - windows unix
-#
-
-#------------------------------------------------------------------------
-# TEA_PATH_TCLCONFIG --
-#
-# Locate the tclConfig.sh file and perform a sanity check on
-# the Tcl compile flags
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Adds the following arguments to configure:
-# --with-tcl=...
-#
-# Defines the following vars:
-# TCL_BIN_DIR Full path to the directory containing
-# the tclConfig.sh file
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PATH_TCLCONFIG], [
- dnl TEA specific: Make sure we are initialized
- AC_REQUIRE([TEA_INIT])
- #
- # Ok, lets find the tcl configuration
- # First, look for one uninstalled.
- # the alternative search directory is invoked by --with-tcl
- #
-
- if test x"${no_tcl}" = x ; then
- # we reset no_tcl in case something fails here
- no_tcl=true
- AC_ARG_WITH(tcl,
- AC_HELP_STRING([--with-tcl],
- [directory containing tcl configuration (tclConfig.sh)]),
- with_tclconfig="${withval}")
- AC_MSG_CHECKING([for Tcl configuration])
- AC_CACHE_VAL(ac_cv_c_tclconfig,[
-
- # First check to see if --with-tcl was specified.
- if test x"${with_tclconfig}" != x ; then
- case "${with_tclconfig}" in
- */tclConfig.sh )
- if test -f "${with_tclconfig}"; then
- AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])
- with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`"
- fi ;;
- esac
- if test -f "${with_tclconfig}/tclConfig.sh" ; then
- ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`"
- else
- AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
- fi
- fi
-
- # then check for a private Tcl installation
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in \
- ../tcl \
- `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
- ../../tcl \
- `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
- ../../../tcl \
- `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
- if test "${TEA_PLATFORM}" = "windows" \
- -a -f "$i/win/tclConfig.sh" ; then
- ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
- break
- fi
- if test -f "$i/unix/tclConfig.sh" ; then
- ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
- break
- fi
- done
- fi
-
- # on Darwin, check in Framework installation locations
- if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
- for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
- `ls -d /Library/Frameworks 2>/dev/null` \
- `ls -d /Network/Library/Frameworks 2>/dev/null` \
- `ls -d /System/Library/Frameworks 2>/dev/null` \
- ; do
- if test -f "$i/Tcl.framework/tclConfig.sh" ; then
- ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
- break
- fi
- done
- fi
-
- # TEA specific: on Windows, check in common installation locations
- if test "${TEA_PLATFORM}" = "windows" \
- -a x"${ac_cv_c_tclconfig}" = x ; then
- for i in `ls -d C:/Tcl/lib 2>/dev/null` \
- `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
- ; do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig="`(cd $i; pwd)`"
- break
- fi
- done
- fi
-
- # check in a few common install locations
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in `ls -d ${libdir} 2>/dev/null` \
- `ls -d ${exec_prefix}/lib 2>/dev/null` \
- `ls -d ${prefix}/lib 2>/dev/null` \
- `ls -d /usr/local/lib 2>/dev/null` \
- `ls -d /usr/contrib/lib 2>/dev/null` \
- `ls -d /usr/lib 2>/dev/null` \
- `ls -d /usr/lib64 2>/dev/null` \
- `ls -d /usr/lib/tcl8.6 2>/dev/null` \
- `ls -d /usr/lib/tcl8.5 2>/dev/null` \
- ; do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig="`(cd $i; pwd)`"
- break
- fi
- done
- fi
-
- # check in a few other private locations
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in \
- ${srcdir}/../tcl \
- `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
- if test "${TEA_PLATFORM}" = "windows" \
- -a -f "$i/win/tclConfig.sh" ; then
- ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
- break
- fi
- if test -f "$i/unix/tclConfig.sh" ; then
- ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
- break
- fi
- done
- fi
- ])
-
- if test x"${ac_cv_c_tclconfig}" = x ; then
- TCL_BIN_DIR="# no Tcl configs found"
- AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh])
- else
- no_tcl=
- TCL_BIN_DIR="${ac_cv_c_tclconfig}"
- AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])
- fi
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_PATH_TKCONFIG --
-#
-# Locate the tkConfig.sh file
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Adds the following arguments to configure:
-# --with-tk=...
-#
-# Defines the following vars:
-# TK_BIN_DIR Full path to the directory containing
-# the tkConfig.sh file
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PATH_TKCONFIG], [
- #
- # Ok, lets find the tk configuration
- # First, look for one uninstalled.
- # the alternative search directory is invoked by --with-tk
- #
-
- if test x"${no_tk}" = x ; then
- # we reset no_tk in case something fails here
- no_tk=true
- AC_ARG_WITH(tk,
- AC_HELP_STRING([--with-tk],
- [directory containing tk configuration (tkConfig.sh)]),
- with_tkconfig="${withval}")
- AC_MSG_CHECKING([for Tk configuration])
- AC_CACHE_VAL(ac_cv_c_tkconfig,[
-
- # First check to see if --with-tkconfig was specified.
- if test x"${with_tkconfig}" != x ; then
- case "${with_tkconfig}" in
- */tkConfig.sh )
- if test -f "${with_tkconfig}"; then
- AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])
- with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`"
- fi ;;
- esac
- if test -f "${with_tkconfig}/tkConfig.sh" ; then
- ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`"
- else
- AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
- fi
- fi
-
- # then check for a private Tk library
- if test x"${ac_cv_c_tkconfig}" = x ; then
- for i in \
- ../tk \
- `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \
- ../../tk \
- `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \
- ../../../tk \
- `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
- if test "${TEA_PLATFORM}" = "windows" \
- -a -f "$i/win/tkConfig.sh" ; then
- ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
- break
- fi
- if test -f "$i/unix/tkConfig.sh" ; then
- ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
- break
- fi
- done
- fi
-
- # on Darwin, check in Framework installation locations
- if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then
- for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
- `ls -d /Library/Frameworks 2>/dev/null` \
- `ls -d /Network/Library/Frameworks 2>/dev/null` \
- `ls -d /System/Library/Frameworks 2>/dev/null` \
- ; do
- if test -f "$i/Tk.framework/tkConfig.sh" ; then
- ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
- break
- fi
- done
- fi
-
- # check in a few common install locations
- if test x"${ac_cv_c_tkconfig}" = x ; then
- for i in `ls -d ${libdir} 2>/dev/null` \
- `ls -d ${exec_prefix}/lib 2>/dev/null` \
- `ls -d ${prefix}/lib 2>/dev/null` \
- `ls -d /usr/local/lib 2>/dev/null` \
- `ls -d /usr/contrib/lib 2>/dev/null` \
- `ls -d /usr/lib 2>/dev/null` \
- `ls -d /usr/lib64 2>/dev/null` \
- ; do
- if test -f "$i/tkConfig.sh" ; then
- ac_cv_c_tkconfig="`(cd $i; pwd)`"
- break
- fi
- done
- fi
-
- # TEA specific: on Windows, check in common installation locations
- if test "${TEA_PLATFORM}" = "windows" \
- -a x"${ac_cv_c_tkconfig}" = x ; then
- for i in `ls -d C:/Tcl/lib 2>/dev/null` \
- `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
- ; do
- if test -f "$i/tkConfig.sh" ; then
- ac_cv_c_tkconfig="`(cd $i; pwd)`"
- break
- fi
- done
- fi
-
- # check in a few other private locations
- if test x"${ac_cv_c_tkconfig}" = x ; then
- for i in \
- ${srcdir}/../tk \
- `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
- if test "${TEA_PLATFORM}" = "windows" \
- -a -f "$i/win/tkConfig.sh" ; then
- ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
- break
- fi
- if test -f "$i/unix/tkConfig.sh" ; then
- ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
- break
- fi
- done
- fi
- ])
-
- if test x"${ac_cv_c_tkconfig}" = x ; then
- TK_BIN_DIR="# no Tk configs found"
- AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])
- else
- no_tk=
- TK_BIN_DIR="${ac_cv_c_tkconfig}"
- AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])
- fi
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_LOAD_TCLCONFIG --
-#
-# Load the tclConfig.sh file
-#
-# Arguments:
-#
-# Requires the following vars to be set:
-# TCL_BIN_DIR
-#
-# Results:
-#
-# Substitutes the following vars:
-# TCL_BIN_DIR
-# TCL_SRC_DIR
-# TCL_LIB_FILE
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_LOAD_TCLCONFIG], [
- AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])
-
- if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
- AC_MSG_RESULT([loading])
- . "${TCL_BIN_DIR}/tclConfig.sh"
- else
- AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
- fi
-
- # eval is required to do the TCL_DBGX substitution
- eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
- eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
-
- # If the TCL_BIN_DIR is the build directory (not the install directory),
- # then set the common variable name to the value of the build variables.
- # For example, the variable TCL_LIB_SPEC will be set to the value
- # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
- # instead of TCL_BUILD_LIB_SPEC since it will work with both an
- # installed and uninstalled version of Tcl.
- if test -f "${TCL_BIN_DIR}/Makefile" ; then
- TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
- TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
- TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
- elif test "`uname -s`" = "Darwin"; then
- # If Tcl was built as a framework, attempt to use the libraries
- # from the framework at the given location so that linking works
- # against Tcl.framework installed in an arbitrary location.
- case ${TCL_DEFS} in
- *TCL_FRAMEWORK*)
- if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
- for i in "`cd "${TCL_BIN_DIR}"; pwd`" \
- "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do
- if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then
- TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}"
- break
- fi
- done
- fi
- if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then
- TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
- TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
- fi
- ;;
- esac
- fi
-
- # eval is required to do the TCL_DBGX substitution
- eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
- eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
- eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
- eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
-
- AC_SUBST(TCL_VERSION)
- AC_SUBST(TCL_PATCH_LEVEL)
- AC_SUBST(TCL_BIN_DIR)
- AC_SUBST(TCL_SRC_DIR)
-
- AC_SUBST(TCL_LIB_FILE)
- AC_SUBST(TCL_LIB_FLAG)
- AC_SUBST(TCL_LIB_SPEC)
-
- AC_SUBST(TCL_STUB_LIB_FILE)
- AC_SUBST(TCL_STUB_LIB_FLAG)
- AC_SUBST(TCL_STUB_LIB_SPEC)
-
- AC_MSG_CHECKING([platform])
- hold_cc=$CC; CC="$TCL_CC"
- AC_TRY_COMPILE(,[
- #ifdef _WIN32
- #error win32
- #endif
- ], TEA_PLATFORM="unix",
- TEA_PLATFORM="windows"
- )
- CC=$hold_cc
- AC_MSG_RESULT($TEA_PLATFORM)
-
- # The BUILD_$pkg is to define the correct extern storage class
- # handling when making this package
- AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [],
- [Building extension source?])
- # Do this here as we have fully defined TEA_PLATFORM now
- if test "${TEA_PLATFORM}" = "windows" ; then
- EXEEXT=".exe"
- CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp"
- fi
-
- # TEA specific:
- AC_SUBST(CLEANFILES)
- AC_SUBST(TCL_LIBS)
- AC_SUBST(TCL_DEFS)
- AC_SUBST(TCL_EXTRA_CFLAGS)
- AC_SUBST(TCL_LD_FLAGS)
- AC_SUBST(TCL_SHLIB_LD_LIBS)
-])
-
-#------------------------------------------------------------------------
-# TEA_LOAD_TKCONFIG --
-#
-# Load the tkConfig.sh file
-#
-# Arguments:
-#
-# Requires the following vars to be set:
-# TK_BIN_DIR
-#
-# Results:
-#
-# Sets the following vars that should be in tkConfig.sh:
-# TK_BIN_DIR
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_LOAD_TKCONFIG], [
- AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])
-
- if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
- AC_MSG_RESULT([loading])
- . "${TK_BIN_DIR}/tkConfig.sh"
- else
- AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
- fi
-
- # eval is required to do the TK_DBGX substitution
- eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
- eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""
-
- # If the TK_BIN_DIR is the build directory (not the install directory),
- # then set the common variable name to the value of the build variables.
- # For example, the variable TK_LIB_SPEC will be set to the value
- # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
- # instead of TK_BUILD_LIB_SPEC since it will work with both an
- # installed and uninstalled version of Tcl.
- if test -f "${TK_BIN_DIR}/Makefile" ; then
- TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}"
- TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}"
- TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}"
- elif test "`uname -s`" = "Darwin"; then
- # If Tk was built as a framework, attempt to use the libraries
- # from the framework at the given location so that linking works
- # against Tk.framework installed in an arbitrary location.
- case ${TK_DEFS} in
- *TK_FRAMEWORK*)
- if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then
- for i in "`cd "${TK_BIN_DIR}"; pwd`" \
- "`cd "${TK_BIN_DIR}"/../..; pwd`"; do
- if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then
- TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}"
- break
- fi
- done
- fi
- if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then
- TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
- TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"
- fi
- ;;
- esac
- fi
-
- # eval is required to do the TK_DBGX substitution
- eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
- eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
- eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\""
- eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""
-
- # TEA specific: Ensure windowingsystem is defined
- if test "${TEA_PLATFORM}" = "unix" ; then
- case ${TK_DEFS} in
- *MAC_OSX_TK*)
- AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?])
- TEA_WINDOWINGSYSTEM="aqua"
- ;;
- *)
- TEA_WINDOWINGSYSTEM="x11"
- ;;
- esac
- elif test "${TEA_PLATFORM}" = "windows" ; then
- TEA_WINDOWINGSYSTEM="win32"
- fi
-
- AC_SUBST(TK_VERSION)
- AC_SUBST(TK_BIN_DIR)
- AC_SUBST(TK_SRC_DIR)
-
- AC_SUBST(TK_LIB_FILE)
- AC_SUBST(TK_LIB_FLAG)
- AC_SUBST(TK_LIB_SPEC)
-
- AC_SUBST(TK_STUB_LIB_FILE)
- AC_SUBST(TK_STUB_LIB_FLAG)
- AC_SUBST(TK_STUB_LIB_SPEC)
-
- # TEA specific:
- AC_SUBST(TK_LIBS)
- AC_SUBST(TK_XINCLUDES)
-])
-
-#------------------------------------------------------------------------
-# TEA_PROG_TCLSH
-# Determine the fully qualified path name of the tclsh executable
-# in the Tcl build directory or the tclsh installed in a bin
-# directory. This macro will correctly determine the name
-# of the tclsh executable even if tclsh has not yet been
-# built in the build directory. The tclsh found is always
-# associated with a tclConfig.sh file. This tclsh should be used
-# only for running extension test cases. It should never be
-# or generation of files (like pkgIndex.tcl) at build time.
-#
-# Arguments:
-# none
-#
-# Results:
-# Substitutes the following vars:
-# TCLSH_PROG
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PROG_TCLSH], [
- AC_MSG_CHECKING([for tclsh])
- if test -f "${TCL_BIN_DIR}/Makefile" ; then
- # tclConfig.sh is in Tcl build directory
- if test "${TEA_PLATFORM}" = "windows"; then
- TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
- else
- TCLSH_PROG="${TCL_BIN_DIR}/tclsh"
- fi
- else
- # tclConfig.sh is in install location
- if test "${TEA_PLATFORM}" = "windows"; then
- TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
- else
- TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}"
- fi
- list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \
- `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \
- `ls -d ${TCL_PREFIX}/bin 2>/dev/null`"
- for i in $list ; do
- if test -f "$i/${TCLSH_PROG}" ; then
- REAL_TCL_BIN_DIR="`cd "$i"; pwd`/"
- break
- fi
- done
- TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}"
- fi
- AC_MSG_RESULT([${TCLSH_PROG}])
- AC_SUBST(TCLSH_PROG)
-])
-
-#------------------------------------------------------------------------
-# TEA_PROG_WISH
-# Determine the fully qualified path name of the wish executable
-# in the Tk build directory or the wish installed in a bin
-# directory. This macro will correctly determine the name
-# of the wish executable even if wish has not yet been
-# built in the build directory. The wish found is always
-# associated with a tkConfig.sh file. This wish should be used
-# only for running extension test cases. It should never be
-# or generation of files (like pkgIndex.tcl) at build time.
-#
-# Arguments:
-# none
-#
-# Results:
-# Substitutes the following vars:
-# WISH_PROG
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PROG_WISH], [
- AC_MSG_CHECKING([for wish])
- if test -f "${TK_BIN_DIR}/Makefile" ; then
- # tkConfig.sh is in Tk build directory
- if test "${TEA_PLATFORM}" = "windows"; then
- WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
- else
- WISH_PROG="${TK_BIN_DIR}/wish"
- fi
- else
- # tkConfig.sh is in install location
- if test "${TEA_PLATFORM}" = "windows"; then
- WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
- else
- WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}"
- fi
- list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \
- `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \
- `ls -d ${TK_PREFIX}/bin 2>/dev/null`"
- for i in $list ; do
- if test -f "$i/${WISH_PROG}" ; then
- REAL_TK_BIN_DIR="`cd "$i"; pwd`/"
- break
- fi
- done
- WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}"
- fi
- AC_MSG_RESULT([${WISH_PROG}])
- AC_SUBST(WISH_PROG)
-])
-
-#------------------------------------------------------------------------
-# TEA_ENABLE_SHARED --
-#
-# Allows the building of shared libraries
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Adds the following arguments to configure:
-# --enable-shared=yes|no
-#
-# Defines the following vars:
-# STATIC_BUILD Used for building import/export libraries
-# on Windows.
-#
-# Sets the following vars:
-# SHARED_BUILD Value of 1 or 0
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_ENABLE_SHARED], [
- AC_MSG_CHECKING([how to build libraries])
- AC_ARG_ENABLE(shared,
- AC_HELP_STRING([--enable-shared],
- [build and link with shared libraries (default: on)]),
- [tcl_ok=$enableval], [tcl_ok=yes])
-
- if test "${enable_shared+set}" = set; then
- enableval="$enable_shared"
- tcl_ok=$enableval
- else
- tcl_ok=yes
- fi
-
- if test "$tcl_ok" = "yes" ; then
- AC_MSG_RESULT([shared])
- SHARED_BUILD=1
- else
- AC_MSG_RESULT([static])
- SHARED_BUILD=0
- AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
- fi
- AC_SUBST(SHARED_BUILD)
-])
-
-#------------------------------------------------------------------------
-# TEA_ENABLE_THREADS --
-#
-# Specify if thread support should be enabled. If "yes" is specified
-# as an arg (optional), threads are enabled by default, "no" means
-# threads are disabled. "yes" is the default.
-#
-# TCL_THREADS is checked so that if you are compiling an extension
-# against a threaded core, your extension must be compiled threaded
-# as well.
-#
-# Note that it is legal to have a thread enabled extension run in a
-# threaded or non-threaded Tcl core, but a non-threaded extension may
-# only run in a non-threaded Tcl core.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Adds the following arguments to configure:
-# --enable-threads
-#
-# Sets the following vars:
-# THREADS_LIBS Thread library(s)
-#
-# Defines the following vars:
-# TCL_THREADS
-# _REENTRANT
-# _THREAD_SAFE
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_ENABLE_THREADS], [
- AC_ARG_ENABLE(threads,
- AC_HELP_STRING([--enable-threads],
- [build with threads]),
- [tcl_ok=$enableval], [tcl_ok=yes])
-
- if test "${enable_threads+set}" = set; then
- enableval="$enable_threads"
- tcl_ok=$enableval
- else
- tcl_ok=yes
- fi
-
- if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
- TCL_THREADS=1
-
- if test "${TEA_PLATFORM}" != "windows" ; then
- # We are always OK on Windows, so check what this platform wants:
-
- # USE_THREAD_ALLOC tells us to try the special thread-based
- # allocator that significantly reduces lock contention
- AC_DEFINE(USE_THREAD_ALLOC, 1,
- [Do we want to use the threaded memory allocator?])
- AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
- if test "`uname -s`" = "SunOS" ; then
- AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
- [Do we really want to follow the standard? Yes we do!])
- fi
- AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
- AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
- if test "$tcl_ok" = "no"; then
- # Check a little harder for __pthread_mutex_init in the same
- # library, as some systems hide it there until pthread.h is
- # defined. We could alternatively do an AC_TRY_COMPILE with
- # pthread.h, but that will work with libpthread really doesn't
- # exist, like AIX 4.2. [Bug: 4359]
- AC_CHECK_LIB(pthread, __pthread_mutex_init,
- tcl_ok=yes, tcl_ok=no)
- fi
-
- if test "$tcl_ok" = "yes"; then
- # The space is needed
- THREADS_LIBS=" -lpthread"
- else
- AC_CHECK_LIB(pthreads, pthread_mutex_init,
- tcl_ok=yes, tcl_ok=no)
- if test "$tcl_ok" = "yes"; then
- # The space is needed
- THREADS_LIBS=" -lpthreads"
- else
- AC_CHECK_LIB(c, pthread_mutex_init,
- tcl_ok=yes, tcl_ok=no)
- if test "$tcl_ok" = "no"; then
- AC_CHECK_LIB(c_r, pthread_mutex_init,
- tcl_ok=yes, tcl_ok=no)
- if test "$tcl_ok" = "yes"; then
- # The space is needed
- THREADS_LIBS=" -pthread"
- else
- TCL_THREADS=0
- AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled])
- fi
- fi
- fi
- fi
- fi
- else
- TCL_THREADS=0
- fi
- # Do checking message here to not mess up interleaved configure output
- AC_MSG_CHECKING([for building with threads])
- if test "${TCL_THREADS}" = 1; then
- AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])
- AC_MSG_RESULT([yes (default)])
- else
- AC_MSG_RESULT([no])
- fi
- # TCL_THREADS sanity checking. See if our request for building with
- # threads is the same as the way Tcl was built. If not, warn the user.
- case ${TCL_DEFS} in
- *THREADS=1*)
- if test "${TCL_THREADS}" = "0"; then
- AC_MSG_WARN([
- Building ${PACKAGE_NAME} without threads enabled, but building against Tcl
- that IS thread-enabled. It is recommended to use --enable-threads.])
- fi
- ;;
- *)
- if test "${TCL_THREADS}" = "1"; then
- AC_MSG_WARN([
- --enable-threads requested, but building against a Tcl that is NOT
- thread-enabled. This is an OK configuration that will also run in
- a thread-enabled core.])
- fi
- ;;
- esac
- AC_SUBST(TCL_THREADS)
-])
-
-#------------------------------------------------------------------------
-# TEA_ENABLE_SYMBOLS --
-#
-# Specify if debugging symbols should be used.
-# Memory (TCL_MEM_DEBUG) debugging can also be enabled.
-#
-# Arguments:
-# none
-#
-# TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives
-# the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted.
-# Requires the following vars to be set in the Makefile:
-# CFLAGS_DEFAULT
-# LDFLAGS_DEFAULT
-#
-# Results:
-#
-# Adds the following arguments to configure:
-# --enable-symbols
-#
-# Defines the following vars:
-# CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true
-# Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false
-# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true
-# Sets to $(LDFLAGS_OPTIMIZE) if false
-# DBGX Formerly used as debug library extension;
-# always blank now.
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_ENABLE_SYMBOLS], [
- dnl TEA specific: Make sure we are initialized
- AC_REQUIRE([TEA_CONFIG_CFLAGS])
- AC_MSG_CHECKING([for build with symbols])
- AC_ARG_ENABLE(symbols,
- AC_HELP_STRING([--enable-symbols],
- [build with debugging symbols (default: off)]),
- [tcl_ok=$enableval], [tcl_ok=no])
- DBGX=""
- if test "$tcl_ok" = "no"; then
- CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG"
- LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}"
- AC_MSG_RESULT([no])
- else
- CFLAGS_DEFAULT="${CFLAGS_DEBUG}"
- LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}"
- if test "$tcl_ok" = "yes"; then
- AC_MSG_RESULT([yes (standard debugging)])
- fi
- fi
- # TEA specific:
- if test "${TEA_PLATFORM}" != "windows" ; then
- LDFLAGS_DEFAULT="${LDFLAGS}"
- fi
- AC_SUBST(CFLAGS_DEFAULT)
- AC_SUBST(LDFLAGS_DEFAULT)
- AC_SUBST(TCL_DBGX)
-
- if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
- AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])
- fi
-
- if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
- if test "$tcl_ok" = "all"; then
- AC_MSG_RESULT([enabled symbols mem debugging])
- else
- AC_MSG_RESULT([enabled $tcl_ok debugging])
- fi
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_ENABLE_LANGINFO --
-#
-# Allows use of modern nl_langinfo check for better l10n.
-# This is only relevant for Unix.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Adds the following arguments to configure:
-# --enable-langinfo=yes|no (default is yes)
-#
-# Defines the following vars:
-# HAVE_LANGINFO Triggers use of nl_langinfo if defined.
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_ENABLE_LANGINFO], [
- AC_ARG_ENABLE(langinfo,
- AC_HELP_STRING([--enable-langinfo],
- [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
- [langinfo_ok=$enableval], [langinfo_ok=yes])
-
- HAVE_LANGINFO=0
- if test "$langinfo_ok" = "yes"; then
- AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
- fi
- AC_MSG_CHECKING([whether to use nl_langinfo])
- if test "$langinfo_ok" = "yes"; then
- AC_CACHE_VAL(tcl_cv_langinfo_h, [
- AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
- [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
- AC_MSG_RESULT([$tcl_cv_langinfo_h])
- if test $tcl_cv_langinfo_h = yes; then
- AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
- fi
- else
- AC_MSG_RESULT([$langinfo_ok])
- fi
-])
-
-#--------------------------------------------------------------------
-# TEA_CONFIG_SYSTEM
-#
-# Determine what the system is (some things cannot be easily checked
-# on a feature-driven basis, alas). This can usually be done via the
-# "uname" command.
-#
-# Arguments:
-# none
-#
-# Results:
-# Defines the following var:
-#
-# system - System/platform/version identification code.
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_CONFIG_SYSTEM], [
- AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
- # TEA specific:
- if test "${TEA_PLATFORM}" = "windows" ; then
- tcl_cv_sys_version=windows
- else
- tcl_cv_sys_version=`uname -s`-`uname -r`
- if test "$?" -ne 0 ; then
- AC_MSG_WARN([can't find uname command])
- tcl_cv_sys_version=unknown
- else
- if test "`uname -s`" = "AIX" ; then
- tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
- fi
- fi
- fi
- ])
- system=$tcl_cv_sys_version
-])
-
-#--------------------------------------------------------------------
-# TEA_CONFIG_CFLAGS
-#
-# Try to determine the proper flags to pass to the compiler
-# for building shared libraries and other such nonsense.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Defines and substitutes the following vars:
-#
-# DL_OBJS, DL_LIBS - removed for TEA, only needed by core.
-# LDFLAGS - Flags to pass to the compiler when linking object
-# files into an executable application binary such
-# as tclsh.
-# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib",
-# that tell the run-time dynamic linker where to look
-# for shared libraries such as libtcl.so. Depends on
-# the variable LIB_RUNTIME_DIR in the Makefile. Could
-# be the same as CC_SEARCH_FLAGS if ${CC} is used to link.
-# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib",
-# that tell the run-time dynamic linker where to look
-# for shared libraries such as libtcl.so. Depends on
-# the variable LIB_RUNTIME_DIR in the Makefile.
-# SHLIB_CFLAGS - Flags to pass to cc when compiling the components
-# of a shared library (may request position-independent
-# code, among other things).
-# SHLIB_LD - Base command to use for combining object files
-# into a shared library.
-# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when
-# creating shared libraries. This symbol typically
-# goes at the end of the "ld" commands that build
-# shared libraries. The value of the symbol defaults to
-# "${LIBS}" if all of the dependent libraries should
-# be specified when creating a shared library. If
-# dependent libraries should not be specified (as on
-# SunOS 4.x, where they cause the link to fail, or in
-# general if Tcl and Tk aren't themselves shared
-# libraries), then this symbol has an empty string
-# as its value.
-# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable
-# extensions. An empty string means we don't know how
-# to use shared libraries on this platform.
-# LIB_SUFFIX - Specifies everything that comes after the "libfoo"
-# in a static or shared library name, using the $PACKAGE_VERSION variable
-# to put the version in the right place. This is used
-# by platforms that need non-standard library names.
-# Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs
-# to have a version after the .so, and ${PACKAGE_VERSION}.a
-# on AIX, since a shared library needs to have
-# a .a extension whereas shared objects for loadable
-# extensions have a .so extension. Defaults to
-# ${PACKAGE_VERSION}${SHLIB_SUFFIX}.
-# CFLAGS_DEBUG -
-# Flags used when running the compiler in debug mode
-# CFLAGS_OPTIMIZE -
-# Flags used when running the compiler in optimize mode
-# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit)
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_CONFIG_CFLAGS], [
- dnl TEA specific: Make sure we are initialized
- AC_REQUIRE([TEA_INIT])
-
- # Step 0.a: Enable 64 bit support?
-
- AC_MSG_CHECKING([if 64bit support is requested])
- AC_ARG_ENABLE(64bit,
- AC_HELP_STRING([--enable-64bit],
- [enable 64bit support (default: off)]),
- [do64bit=$enableval], [do64bit=no])
- AC_MSG_RESULT([$do64bit])
-
- # Step 0.b: Enable Solaris 64 bit VIS support?
-
- AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
- AC_ARG_ENABLE(64bit-vis,
- AC_HELP_STRING([--enable-64bit-vis],
- [enable 64bit Sparc VIS support (default: off)]),
- [do64bitVIS=$enableval], [do64bitVIS=no])
- AC_MSG_RESULT([$do64bitVIS])
- # Force 64bit on with VIS
- AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])
-
- # Step 0.c: Check if visibility support is available. Do this here so
- # that platform specific alternatives can be used below if this fails.
-
- AC_CACHE_CHECK([if compiler supports visibility "hidden"],
- tcl_cv_cc_visibility_hidden, [
- hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
- AC_TRY_LINK([
- extern __attribute__((__visibility__("hidden"))) void f(void);
- void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
- tcl_cv_cc_visibility_hidden=no)
- CFLAGS=$hold_cflags])
- AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
- AC_DEFINE(MODULE_SCOPE,
- [extern __attribute__((__visibility__("hidden")))],
- [Compiler support for module scope symbols])
- AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
- ])
-
- # Step 0.d: Disable -rpath support?
-
- AC_MSG_CHECKING([if rpath support is requested])
- AC_ARG_ENABLE(rpath,
- AC_HELP_STRING([--disable-rpath],
- [disable rpath support (default: on)]),
- [doRpath=$enableval], [doRpath=yes])
- AC_MSG_RESULT([$doRpath])
-
- # TEA specific: Cross-compiling options for Windows/CE builds?
-
- AS_IF([test "${TEA_PLATFORM}" = windows], [
- AC_MSG_CHECKING([if Windows/CE build is requested])
- AC_ARG_ENABLE(wince,
- AC_HELP_STRING([--enable-wince],
- [enable Win/CE support (where applicable)]),
- [doWince=$enableval], [doWince=no])
- AC_MSG_RESULT([$doWince])
- ])
-
- # Set the variable "system" to hold the name and version number
- # for the system.
-
- TEA_CONFIG_SYSTEM
-
- # Require ranlib early so we can override it in special cases below.
-
- AC_REQUIRE([AC_PROG_RANLIB])
-
- # Set configuration options based on system name and version.
- # This is similar to Tcl's unix/tcl.m4 except that we've added a
- # "windows" case and removed some core-only vars.
-
- do64bit_ok=no
- # default to '{$LIBS}' and set to "" on per-platform necessary basis
- SHLIB_LD_LIBS='${LIBS}'
- # When ld needs options to work in 64-bit mode, put them in
- # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
- # is disabled by the user. [Bug 1016796]
- LDFLAGS_ARCH=""
- UNSHARED_LIB_SUFFIX=""
- # TEA specific: use PACKAGE_VERSION instead of VERSION
- TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`'
- ECHO_VERSION='`echo ${PACKAGE_VERSION}`'
- TCL_LIB_VERSIONS_OK=ok
- CFLAGS_DEBUG=-g
- AS_IF([test "$GCC" = yes], [
- CFLAGS_OPTIMIZE=-O2
- CFLAGS_WARNING="-Wall"
- ], [
- CFLAGS_OPTIMIZE=-O
- CFLAGS_WARNING=""
- ])
- AC_CHECK_TOOL(AR, ar)
- STLIB_LD='${AR} cr'
- LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
- AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"])
- case $system in
- # TEA specific:
- windows)
- # This is a 2-stage check to make sure we have the 64-bit SDK
- # We have to know where the SDK is installed.
- # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs
- # MACHINE is IX86 for LINK, but this is used by the manifest,
- # which requires x86|amd64|ia64.
- MACHINE="X86"
- if test "$do64bit" != "no" ; then
- if test "x${MSSDK}x" = "xx" ; then
- MSSDK="C:/Progra~1/Microsoft Platform SDK"
- fi
- MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'`
- PATH64=""
- case "$do64bit" in
- amd64|x64|yes)
- MACHINE="AMD64" ; # default to AMD64 64-bit build
- PATH64="${MSSDK}/Bin/Win64/x86/AMD64"
- ;;
- ia64)
- MACHINE="IA64"
- PATH64="${MSSDK}/Bin/Win64"
- ;;
- esac
- if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then
- AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode])
- AC_MSG_WARN([Ensure latest Platform SDK is installed])
- do64bit="no"
- else
- AC_MSG_RESULT([ Using 64-bit $MACHINE mode])
- do64bit_ok="yes"
- fi
- fi
-
- if test "$doWince" != "no" ; then
- if test "$do64bit" != "no" ; then
- AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible])
- fi
- if test "$GCC" = "yes" ; then
- AC_MSG_ERROR([Windows/CE and GCC builds incompatible])
- fi
- TEA_PATH_CELIB
- # Set defaults for common evc4/PPC2003 setup
- # Currently Tcl requires 300+, possibly 420+ for sockets
- CEVERSION=420; # could be 211 300 301 400 420 ...
- TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ...
- ARCH=ARM; # could be ARM MIPS X86EM ...
- PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
- if test "$doWince" != "yes"; then
- # If !yes then the user specified something
- # Reset ARCH to allow user to skip specifying it
- ARCH=
- eval `echo $doWince | awk -F, '{ \
- if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \
- if ([$]1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
- if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \
- if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \
- if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \
- }'`
- if test "x${ARCH}" = "x" ; then
- ARCH=$TARGETCPU;
- fi
- fi
- OSVERSION=WCE$CEVERSION;
- if test "x${WCEROOT}" = "x" ; then
- WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
- if test ! -d "${WCEROOT}" ; then
- WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
- fi
- fi
- if test "x${SDKROOT}" = "x" ; then
- SDKROOT="C:/Program Files/Windows CE Tools"
- if test ! -d "${SDKROOT}" ; then
- SDKROOT="C:/Windows CE Tools"
- fi
- fi
- WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'`
- SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
- if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \
- -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
- AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]])
- doWince="no"
- else
- # We could PATH_NOSPACE these, but that's not important,
- # as long as we quote them when used.
- CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
- if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
- CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
- fi
- CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
- fi
- fi
-
- if test "$GCC" != "yes" ; then
- if test "${SHARED_BUILD}" = "0" ; then
- runtime=-MT
- else
- runtime=-MD
- fi
-
- if test "$do64bit" != "no" ; then
- # All this magic is necessary for the Win64 SDK RC1 - hobbs
- CC="\"${PATH64}/cl.exe\""
- CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\""
- RC="\"${MSSDK}/bin/rc.exe\""
- lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
- LINKBIN="\"${PATH64}/link.exe\""
- CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d"
- CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
- # Avoid 'unresolved external symbol __security_cookie'
- # errors, c.f. http://support.microsoft.com/?id=894573
- TEA_ADD_LIBS([bufferoverflowU.lib])
- elif test "$doWince" != "no" ; then
- CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
- if test "${TARGETCPU}" = "X86"; then
- CC="\"${CEBINROOT}/cl.exe\""
- else
- CC="\"${CEBINROOT}/cl${ARCH}.exe\""
- fi
- CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
- RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\""
- arch=`echo ${ARCH} | awk '{print tolower([$]0)}'`
- defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS"
- if test "${SHARED_BUILD}" = "1" ; then
- # Static CE builds require static celib as well
- defs="${defs} _DLL"
- fi
- for i in $defs ; do
- AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i)
- done
- AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version])
- AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version])
- CFLAGS_DEBUG="-nologo -Zi -Od"
- CFLAGS_OPTIMIZE="-nologo -Ox"
- lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
- lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
- LINKBIN="\"${CEBINROOT}/link.exe\""
- AC_SUBST(CELIB_DIR)
- else
- RC="rc"
- lflags="-nologo"
- LINKBIN="link"
- CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d"
- CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
- fi
- fi
-
- if test "$GCC" = "yes"; then
- # mingw gcc mode
- AC_CHECK_TOOL(RC, windres)
- CFLAGS_DEBUG="-g"
- CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
- SHLIB_LD='${CC} -shared'
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
- LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}"
- LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}"
-
- AC_CACHE_CHECK(for cross-compile version of gcc,
- ac_cv_cross,
- AC_TRY_COMPILE([
- #ifdef _WIN32
- #error cross-compiler
- #endif
- ], [],
- ac_cv_cross=yes,
- ac_cv_cross=no)
- )
- if test "$ac_cv_cross" = "yes"; then
- case "$do64bit" in
- amd64|x64|yes)
- CC="x86_64-w64-mingw32-gcc"
- LD="x86_64-w64-mingw32-ld"
- AR="x86_64-w64-mingw32-ar"
- RANLIB="x86_64-w64-mingw32-ranlib"
- RC="x86_64-w64-mingw32-windres"
- ;;
- *)
- CC="i686-w64-mingw32-gcc"
- LD="i686-w64-mingw32-ld"
- AR="i686-w64-mingw32-ar"
- RANLIB="i686-w64-mingw32-ranlib"
- RC="i686-w64-mingw32-windres"
- ;;
- esac
- fi
-
- else
- SHLIB_LD="${LINKBIN} -dll ${lflags}"
- # link -lib only works when -lib is the first arg
- STLIB_LD="${LINKBIN} -lib ${lflags}"
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib'
- PATHTYPE=-w
- # For information on what debugtype is most useful, see:
- # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
- # and also
- # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx
- # This essentially turns it all on.
- LDFLAGS_DEBUG="-debug -debugtype:cv"
- LDFLAGS_OPTIMIZE="-release"
- if test "$doWince" != "no" ; then
- LDFLAGS_CONSOLE="-link ${lflags}"
- LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
- else
- LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
- LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
- fi
- fi
-
- SHLIB_SUFFIX=".dll"
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'
-
- TCL_LIB_VERSIONS_OK=nodots
- ;;
- AIX-*)
- AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
- # AIX requires the _r compiler when gcc isn't being used
- case "${CC}" in
- *_r|*_r\ *)
- # ok ...
- ;;
- *)
- # Make sure only first arg gets _r
- CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'`
- ;;
- esac
- AC_MSG_RESULT([Using $CC for compiling with threads])
- ])
- LIBS="$LIBS -lc"
- SHLIB_CFLAGS=""
- SHLIB_SUFFIX=".so"
-
- LD_LIBRARY_PATH_VAR="LIBPATH"
-
- # Check to enable 64-bit flags for compiler/linker
- AS_IF([test "$do64bit" = yes], [
- AS_IF([test "$GCC" = yes], [
- AC_MSG_WARN([64bit mode not supported with GCC on $system])
- ], [
- do64bit_ok=yes
- CFLAGS="$CFLAGS -q64"
- LDFLAGS_ARCH="-q64"
- RANLIB="${RANLIB} -X64"
- AR="${AR} -X64"
- SHLIB_LD_FLAGS="-b64"
- ])
- ])
-
- AS_IF([test "`uname -m`" = ia64], [
- # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
- SHLIB_LD="/usr/ccs/bin/ld -G -z text"
- AS_IF([test "$GCC" = yes], [
- CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
- ], [
- CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
- ])
- LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
- ], [
- AS_IF([test "$GCC" = yes], [
- SHLIB_LD='${CC} -shared -Wl,-bexpall'
- ], [
- SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
- LDFLAGS="$LDFLAGS -brtl"
- ])
- SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- ])
- ;;
- BeOS*)
- SHLIB_CFLAGS="-fPIC"
- SHLIB_LD='${CC} -nostart'
- SHLIB_SUFFIX=".so"
-
- #-----------------------------------------------------------
- # Check for inet_ntoa in -lbind, for BeOS (which also needs
- # -lsocket, even if the network functions are in -lnet which
- # is always linked to, for compatibility.
- #-----------------------------------------------------------
- AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"])
- ;;
- BSD/OS-4.*)
- SHLIB_CFLAGS="-export-dynamic -fPIC"
- SHLIB_LD='${CC} -shared'
- SHLIB_SUFFIX=".so"
- LDFLAGS="$LDFLAGS -export-dynamic"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
- ;;
- CYGWIN_*)
- SHLIB_CFLAGS=""
- SHLIB_LD='${CC} -shared'
- SHLIB_SUFFIX=".dll"
- EXEEXT=".exe"
- do64bit_ok=yes
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
- ;;
- Haiku*)
- LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
- SHLIB_CFLAGS="-fPIC"
- SHLIB_SUFFIX=".so"
- SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
- AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
- ;;
- HP-UX-*.11.*)
- # Use updated header definitions where possible
- AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
- # TEA specific: Needed by Tcl, but not most extensions
- #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
- #LIBS="$LIBS -lxnet" # Use the XOPEN network library
-
- AS_IF([test "`uname -m`" = ia64], [
- SHLIB_SUFFIX=".so"
- # Use newer C++ library for C++ extensions
- #if test "$GCC" != "yes" ; then
- # CPPFLAGS="-AA"
- #fi
- ], [
- SHLIB_SUFFIX=".sl"
- ])
- AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
- AS_IF([test "$tcl_ok" = yes], [
- LDFLAGS="$LDFLAGS -Wl,-E"
- CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
- LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
- LD_LIBRARY_PATH_VAR="SHLIB_PATH"
- ])
- AS_IF([test "$GCC" = yes], [
- SHLIB_LD='${CC} -shared'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- ], [
- CFLAGS="$CFLAGS -z"
- # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
- #CFLAGS="$CFLAGS +DAportable"
- SHLIB_CFLAGS="+z"
- SHLIB_LD="ld -b"
- ])
-
- # Check to enable 64-bit flags for compiler/linker
- AS_IF([test "$do64bit" = "yes"], [
- AS_IF([test "$GCC" = yes], [
- case `${CC} -dumpmachine` in
- hppa64*)
- # 64-bit gcc in use. Fix flags for GNU ld.
- do64bit_ok=yes
- SHLIB_LD='${CC} -shared'
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- ;;
- *)
- AC_MSG_WARN([64bit mode not supported with GCC on $system])
- ;;
- esac
- ], [
- do64bit_ok=yes
- CFLAGS="$CFLAGS +DD64"
- LDFLAGS_ARCH="+DD64"
- ])
- ]) ;;
- IRIX-6.*)
- SHLIB_CFLAGS=""
- SHLIB_LD="ld -n32 -shared -rdata_shared"
- SHLIB_SUFFIX=".so"
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
- AS_IF([test "$GCC" = yes], [
- CFLAGS="$CFLAGS -mabi=n32"
- LDFLAGS="$LDFLAGS -mabi=n32"
- ], [
- case $system in
- IRIX-6.3)
- # Use to build 6.2 compatible binaries on 6.3.
- CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS"
- ;;
- *)
- CFLAGS="$CFLAGS -n32"
- ;;
- esac
- LDFLAGS="$LDFLAGS -n32"
- ])
- ;;
- IRIX64-6.*)
- SHLIB_CFLAGS=""
- SHLIB_LD="ld -n32 -shared -rdata_shared"
- SHLIB_SUFFIX=".so"
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
-
- # Check to enable 64-bit flags for compiler/linker
-
- AS_IF([test "$do64bit" = yes], [
- AS_IF([test "$GCC" = yes], [
- AC_MSG_WARN([64bit mode not supported by gcc])
- ], [
- do64bit_ok=yes
- SHLIB_LD="ld -64 -shared -rdata_shared"
- CFLAGS="$CFLAGS -64"
- LDFLAGS_ARCH="-64"
- ])
- ])
- ;;
- Linux*|GNU*|NetBSD-Debian)
- SHLIB_CFLAGS="-fPIC"
- SHLIB_SUFFIX=".so"
-
- # TEA specific:
- CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
-
- # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
- SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}'
- LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
- AS_IF([test $do64bit = yes], [
- AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
- hold_cflags=$CFLAGS
- CFLAGS="$CFLAGS -m64"
- AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
- CFLAGS=$hold_cflags])
- AS_IF([test $tcl_cv_cc_m64 = yes], [
- CFLAGS="$CFLAGS -m64"
- do64bit_ok=yes
- ])
- ])
-
- # The combo of gcc + glibc has a bug related to inlining of
- # functions like strtod(). The -fno-builtin flag should address
- # this problem but it does not work. The -fno-inline flag is kind
- # of overkill but it works. Disable inlining only when one of the
- # files in compat/*.c is being linked in.
-
- AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"])
- ;;
- Lynx*)
- SHLIB_CFLAGS="-fPIC"
- SHLIB_SUFFIX=".so"
- CFLAGS_OPTIMIZE=-02
- SHLIB_LD='${CC} -shared'
- LD_FLAGS="-Wl,--export-dynamic"
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
- ;;
- OpenBSD-*)
- arch=`arch -s`
- case "$arch" in
- vax)
- SHLIB_SUFFIX=""
- SHARED_LIB_SUFFIX=""
- LDFLAGS=""
- ;;
- *)
- SHLIB_CFLAGS="-fPIC"
- SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
- SHLIB_SUFFIX=".so"
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
- LDFLAGS="-Wl,-export-dynamic"
- ;;
- esac
- case "$arch" in
- vax)
- CFLAGS_OPTIMIZE="-O1"
- ;;
- *)
- CFLAGS_OPTIMIZE="-O2"
- ;;
- esac
- AS_IF([test "${TCL_THREADS}" = "1"], [
- # On OpenBSD: Compile with -pthread
- # Don't link with -lpthread
- LIBS=`echo $LIBS | sed s/-lpthread//`
- CFLAGS="$CFLAGS -pthread"
- ])
- # OpenBSD doesn't do version numbers with dots.
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
- TCL_LIB_VERSIONS_OK=nodots
- ;;
- NetBSD-*)
- # NetBSD has ELF and can use 'cc -shared' to build shared libs
- SHLIB_CFLAGS="-fPIC"
- SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
- SHLIB_SUFFIX=".so"
- LDFLAGS="$LDFLAGS -export-dynamic"
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- AS_IF([test "${TCL_THREADS}" = "1"], [
- # The -pthread needs to go in the CFLAGS, not LIBS
- LIBS=`echo $LIBS | sed s/-pthread//`
- CFLAGS="$CFLAGS -pthread"
- LDFLAGS="$LDFLAGS -pthread"
- ])
- ;;
- FreeBSD-*)
- # This configuration from FreeBSD Ports.
- SHLIB_CFLAGS="-fPIC"
- SHLIB_LD="${CC} -shared"
- TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]"
- TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$[@]"
- SHLIB_SUFFIX=".so"
- LDFLAGS=""
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
- AS_IF([test "${TCL_THREADS}" = "1"], [
- # The -pthread needs to go in the LDFLAGS, not LIBS
- LIBS=`echo $LIBS | sed s/-pthread//`
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
- LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
- case $system in
- FreeBSD-3.*)
- # Version numbers are dot-stripped by system policy.
- TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
- TCL_LIB_VERSIONS_OK=nodots
- ;;
- esac
- ;;
- Darwin-*)
- CFLAGS_OPTIMIZE="-Os"
- SHLIB_CFLAGS="-fno-common"
- # To avoid discrepancies between what headers configure sees during
- # preprocessing tests and compiling tests, move any -isysroot and
- # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
- CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
- awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
- if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`"
- CFLAGS="`echo " ${CFLAGS}" | \
- awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
- if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
- AS_IF([test $do64bit = yes], [
- case `arch` in
- ppc)
- AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
- tcl_cv_cc_arch_ppc64, [
- hold_cflags=$CFLAGS
- CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
- AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
- tcl_cv_cc_arch_ppc64=no)
- CFLAGS=$hold_cflags])
- AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
- CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
- do64bit_ok=yes
- ]);;
- i386)
- AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
- tcl_cv_cc_arch_x86_64, [
- hold_cflags=$CFLAGS
- CFLAGS="$CFLAGS -arch x86_64"
- AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
- tcl_cv_cc_arch_x86_64=no)
- CFLAGS=$hold_cflags])
- AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
- CFLAGS="$CFLAGS -arch x86_64"
- do64bit_ok=yes
- ]);;
- *)
- AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
- esac
- ], [
- # Check for combined 32-bit and 64-bit fat build
- AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
- && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
- fat_32_64=yes])
- ])
- # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
- SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}'
- AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
- hold_ldflags=$LDFLAGS
- LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
- AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
- LDFLAGS=$hold_ldflags])
- AS_IF([test $tcl_cv_ld_single_module = yes], [
- SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
- ])
- # TEA specific: link shlib with current and compatibility version flags
- vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d`
- SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}"
- SHLIB_SUFFIX=".dylib"
- # Don't use -prebind when building for Mac OS X 10.4 or later only:
- AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
- "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
- LDFLAGS="$LDFLAGS -prebind"])
- LDFLAGS="$LDFLAGS -headerpad_max_install_names"
- AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
- tcl_cv_ld_search_paths_first, [
- hold_ldflags=$LDFLAGS
- LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
- AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
- tcl_cv_ld_search_paths_first=no)
- LDFLAGS=$hold_ldflags])
- AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
- LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
- ])
- AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
- AC_DEFINE(MODULE_SCOPE, [__private_extern__],
- [Compiler support for module scope symbols])
- tcl_cv_cc_visibility_hidden=yes
- ])
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
- LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
- # TEA specific: for combined 32 & 64 bit fat builds of Tk
- # extensions, verify that 64-bit build is possible.
- AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [
- AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [
- AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [
- for v in CFLAGS CPPFLAGS LDFLAGS; do
- eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
- done
- CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include"
- LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11"
- AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();],
- tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no)
- for v in CFLAGS CPPFLAGS LDFLAGS; do
- eval $v'="$hold_'$v'"'
- done])
- ])
- AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [
- AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [
- for v in CFLAGS CPPFLAGS LDFLAGS; do
- eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
- done
- CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}"
- LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}"
- AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);],
- tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no)
- for v in CFLAGS CPPFLAGS LDFLAGS; do
- eval $v'="$hold_'$v'"'
- done])
- ])
- # remove 64-bit arch flags from CFLAGS et al. if configuration
- # does not support 64-bit.
- AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [
- AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags])
- for v in CFLAGS CPPFLAGS LDFLAGS; do
- eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
- done])
- ])
- ;;
- OS/390-*)
- CFLAGS_OPTIMIZE="" # Optimizer is buggy
- AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h
- [Should OS/390 do the right thing with sockets?])
- ;;
- OSF1-V*)
- # Digital OSF/1
- SHLIB_CFLAGS=""
- AS_IF([test "$SHARED_BUILD" = 1], [
- SHLIB_LD='ld -shared -expect_unresolved "*"'
- ], [
- SHLIB_LD='ld -non_shared -expect_unresolved "*"'
- ])
- SHLIB_SUFFIX=".so"
- AS_IF([test $doRpath = yes], [
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
- AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
- CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
- # see pthread_intro(3) for pthread support on osf1, k.furukawa
- AS_IF([test "${TCL_THREADS}" = 1], [
- CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
- CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
- LIBS=`echo $LIBS | sed s/-lpthreads//`
- AS_IF([test "$GCC" = yes], [
- LIBS="$LIBS -lpthread -lmach -lexc"
- ], [
- CFLAGS="$CFLAGS -pthread"
- LDFLAGS="$LDFLAGS -pthread"
- ])
- ])
- ;;
- QNX-6*)
- # QNX RTP
- # This may work for all QNX, but it was only reported for v6.
- SHLIB_CFLAGS="-fPIC"
- SHLIB_LD="ld -Bshareable -x"
- SHLIB_LD_LIBS=""
- SHLIB_SUFFIX=".so"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
- ;;
- SCO_SV-3.2*)
- AS_IF([test "$GCC" = yes], [
- SHLIB_CFLAGS="-fPIC -melf"
- LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
- ], [
- SHLIB_CFLAGS="-Kpic -belf"
- LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
- ])
- SHLIB_LD="ld -G"
- SHLIB_LD_LIBS=""
- SHLIB_SUFFIX=".so"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
- ;;
- SunOS-5.[[0-6]])
- # Careful to not let 5.10+ fall into this case
-
- # Note: If _REENTRANT isn't defined, then Solaris
- # won't define thread-safe library routines.
-
- AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
- AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
- [Do we really want to follow the standard? Yes we do!])
-
- SHLIB_CFLAGS="-KPIC"
- SHLIB_SUFFIX=".so"
- AS_IF([test "$GCC" = yes], [
- SHLIB_LD='${CC} -shared'
- CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- ], [
- SHLIB_LD="/usr/ccs/bin/ld -G -z text"
- CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- ])
- ;;
- SunOS-5*)
- # Note: If _REENTRANT isn't defined, then Solaris
- # won't define thread-safe library routines.
-
- AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
- AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
- [Do we really want to follow the standard? Yes we do!])
-
- SHLIB_CFLAGS="-KPIC"
-
- # Check to enable 64-bit flags for compiler/linker
- AS_IF([test "$do64bit" = yes], [
- arch=`isainfo`
- AS_IF([test "$arch" = "sparcv9 sparc"], [
- AS_IF([test "$GCC" = yes], [
- AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [
- AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
- ], [
- do64bit_ok=yes
- CFLAGS="$CFLAGS -m64 -mcpu=v9"
- LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
- SHLIB_CFLAGS="-fPIC"
- ])
- ], [
- do64bit_ok=yes
- AS_IF([test "$do64bitVIS" = yes], [
- CFLAGS="$CFLAGS -xarch=v9a"
- LDFLAGS_ARCH="-xarch=v9a"
- ], [
- CFLAGS="$CFLAGS -xarch=v9"
- LDFLAGS_ARCH="-xarch=v9"
- ])
- # Solaris 64 uses this as well
- #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
- ])
- ], [AS_IF([test "$arch" = "amd64 i386"], [
- AS_IF([test "$GCC" = yes], [
- case $system in
- SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
- do64bit_ok=yes
- CFLAGS="$CFLAGS -m64"
- LDFLAGS="$LDFLAGS -m64";;
- *)
- AC_MSG_WARN([64bit mode not supported with GCC on $system]);;
- esac
- ], [
- do64bit_ok=yes
- case $system in
- SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
- CFLAGS="$CFLAGS -m64"
- LDFLAGS="$LDFLAGS -m64";;
- *)
- CFLAGS="$CFLAGS -xarch=amd64"
- LDFLAGS="$LDFLAGS -xarch=amd64";;
- esac
- ])
- ], [AC_MSG_WARN([64bit mode not supported for $arch])])])
- ])
-
- SHLIB_SUFFIX=".so"
- AS_IF([test "$GCC" = yes], [
- SHLIB_LD='${CC} -shared'
- CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- AS_IF([test "$do64bit_ok" = yes], [
- AS_IF([test "$arch" = "sparcv9 sparc"], [
- # We need to specify -static-libgcc or we need to
- # add the path to the sparv9 libgcc.
- # JH: static-libgcc is necessary for core Tcl, but may
- # not be necessary for extensions.
- SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
- # for finding sparcv9 libgcc, get the regular libgcc
- # path, remove so name and append 'sparcv9'
- #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
- #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
- ], [AS_IF([test "$arch" = "amd64 i386"], [
- # JH: static-libgcc is necessary for core Tcl, but may
- # not be necessary for extensions.
- SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
- ])])
- ])
- ], [
- case $system in
- SunOS-5.[[1-9]][[0-9]]*)
- # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
- SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';;
- *)
- SHLIB_LD='/usr/ccs/bin/ld -G -z text';;
- esac
- CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
- ])
- ;;
- UNIX_SV* | UnixWare-5*)
- SHLIB_CFLAGS="-KPIC"
- SHLIB_LD='${CC} -G'
- SHLIB_LD_LIBS=""
- SHLIB_SUFFIX=".so"
- # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
- # that don't grok the -Bexport option. Test that it does.
- AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
- hold_ldflags=$LDFLAGS
- LDFLAGS="$LDFLAGS -Wl,-Bexport"
- AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
- LDFLAGS=$hold_ldflags])
- AS_IF([test $tcl_cv_ld_Bexport = yes], [
- LDFLAGS="$LDFLAGS -Wl,-Bexport"
- ])
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
- ;;
- esac
-
- AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [
- AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])
- ])
-
-dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so
-dnl # until the end of configure, as configure's compile and link tests use
-dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
-dnl # preprocessing tests use only CPPFLAGS.
- AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])
-
- # Add in the arch flags late to ensure it wasn't removed.
- # Not necessary in TEA, but this is aligned with core
- LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"
-
- # If we're running gcc, then change the C flags for compiling shared
- # libraries to the right flags for gcc, instead of those for the
- # standard manufacturer compiler.
-
- AS_IF([test "$GCC" = yes], [
- case $system in
- AIX-*) ;;
- BSD/OS*) ;;
- CYGWIN_*|MINGW32_*) ;;
- IRIX*) ;;
- NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
- Darwin-*) ;;
- SCO_SV-3.2*) ;;
- windows) ;;
- *) SHLIB_CFLAGS="-fPIC" ;;
- esac])
-
- AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
- AC_DEFINE(MODULE_SCOPE, [extern],
- [No Compiler support for module scope symbols])
- ])
-
- AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
- # TEA specific: use PACKAGE_VERSION instead of VERSION
- SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'])
- AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
- # TEA specific: use PACKAGE_VERSION instead of VERSION
- UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'])
-
- if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then
- AC_CACHE_CHECK(for SEH support in compiler,
- tcl_cv_seh,
- AC_TRY_RUN([
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-
- int main(int argc, char** argv) {
- int a, b = 0;
- __try {
- a = 666 / b;
- }
- __except (EXCEPTION_EXECUTE_HANDLER) {
- return 0;
- }
- return 1;
- }
- ],
- tcl_cv_seh=yes,
- tcl_cv_seh=no,
- tcl_cv_seh=no)
- )
- if test "$tcl_cv_seh" = "no" ; then
- AC_DEFINE(HAVE_NO_SEH, 1,
- [Defined when mingw does not support SEH])
- fi
-
- #
- # Check to see if the excpt.h include file provided contains the
- # definition for EXCEPTION_DISPOSITION; if not, which is the case
- # with Cygwin's version as of 2002-04-10, define it to be int,
- # sufficient for getting the current code to work.
- #
- AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
- tcl_cv_eh_disposition,
- AC_TRY_COMPILE([
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# undef WIN32_LEAN_AND_MEAN
- ],[
- EXCEPTION_DISPOSITION x;
- ],
- tcl_cv_eh_disposition=yes,
- tcl_cv_eh_disposition=no)
- )
- if test "$tcl_cv_eh_disposition" = "no" ; then
- AC_DEFINE(EXCEPTION_DISPOSITION, int,
- [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
- fi
-
- # Check to see if winnt.h defines CHAR, SHORT, and LONG
- # even if VOID has already been #defined. The win32api
- # used by mingw and cygwin is known to do this.
-
- AC_CACHE_CHECK(for winnt.h that ignores VOID define,
- tcl_cv_winnt_ignore_void,
- AC_TRY_COMPILE([
-#define VOID void
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
- ], [
- CHAR c;
- SHORT s;
- LONG l;
- ],
- tcl_cv_winnt_ignore_void=yes,
- tcl_cv_winnt_ignore_void=no)
- )
- if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
- AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
- [Defined when cygwin/mingw ignores VOID define in winnt.h])
- fi
- fi
-
- # See if the compiler supports casting to a union type.
- # This is used to stop gcc from printing a compiler
- # warning when initializing a union member.
-
- AC_CACHE_CHECK(for cast to union support,
- tcl_cv_cast_to_union,
- AC_TRY_COMPILE([],
- [
- union foo { int i; double d; };
- union foo f = (union foo) (int) 0;
- ],
- tcl_cv_cast_to_union=yes,
- tcl_cv_cast_to_union=no)
- )
- if test "$tcl_cv_cast_to_union" = "yes"; then
- AC_DEFINE(HAVE_CAST_TO_UNION, 1,
- [Defined when compiler supports casting to union type.])
- fi
-
- AC_SUBST(CFLAGS_DEBUG)
- AC_SUBST(CFLAGS_OPTIMIZE)
- AC_SUBST(CFLAGS_WARNING)
-
- AC_SUBST(STLIB_LD)
- AC_SUBST(SHLIB_LD)
-
- AC_SUBST(SHLIB_LD_LIBS)
- AC_SUBST(SHLIB_CFLAGS)
-
- AC_SUBST(LD_LIBRARY_PATH_VAR)
-
- # These must be called after we do the basic CFLAGS checks and
- # verify any possible 64-bit or similar switches are necessary
- TEA_TCL_EARLY_FLAGS
- TEA_TCL_64BIT_FLAGS
-])
-
-#--------------------------------------------------------------------
-# TEA_SERIAL_PORT
-#
-# Determine which interface to use to talk to the serial port.
-# Note that #include lines must begin in leftmost column for
-# some compilers to recognize them as preprocessor directives,
-# and some build environments have stdin not pointing at a
-# pseudo-terminal (usually /dev/null instead.)
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Defines only one of the following vars:
-# HAVE_SYS_MODEM_H
-# USE_TERMIOS
-# USE_TERMIO
-# USE_SGTTY
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_SERIAL_PORT], [
- AC_CHECK_HEADERS(sys/modem.h)
- AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [
- AC_TRY_RUN([
-#include <termios.h>
-
-int main() {
- struct termios t;
- if (tcgetattr(0, &t) == 0) {
- cfsetospeed(&t, 0);
- t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
- return 0;
- }
- return 1;
-}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
- if test $tcl_cv_api_serial = no ; then
- AC_TRY_RUN([
-#include <termio.h>
-
-int main() {
- struct termio t;
- if (ioctl(0, TCGETA, &t) == 0) {
- t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
- return 0;
- }
- return 1;
-}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
- fi
- if test $tcl_cv_api_serial = no ; then
- AC_TRY_RUN([
-#include <sgtty.h>
-
-int main() {
- struct sgttyb t;
- if (ioctl(0, TIOCGETP, &t) == 0) {
- t.sg_ospeed = 0;
- t.sg_flags |= ODDP | EVENP | RAW;
- return 0;
- }
- return 1;
-}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
- fi
- if test $tcl_cv_api_serial = no ; then
- AC_TRY_RUN([
-#include <termios.h>
-#include <errno.h>
-
-int main() {
- struct termios t;
- if (tcgetattr(0, &t) == 0
- || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
- cfsetospeed(&t, 0);
- t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
- return 0;
- }
- return 1;
-}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
- fi
- if test $tcl_cv_api_serial = no; then
- AC_TRY_RUN([
-#include <termio.h>
-#include <errno.h>
-
-int main() {
- struct termio t;
- if (ioctl(0, TCGETA, &t) == 0
- || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
- t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
- return 0;
- }
- return 1;
- }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
- fi
- if test $tcl_cv_api_serial = no; then
- AC_TRY_RUN([
-#include <sgtty.h>
-#include <errno.h>
-
-int main() {
- struct sgttyb t;
- if (ioctl(0, TIOCGETP, &t) == 0
- || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
- t.sg_ospeed = 0;
- t.sg_flags |= ODDP | EVENP | RAW;
- return 0;
- }
- return 1;
-}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)
- fi])
- case $tcl_cv_api_serial in
- termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;
- termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;
- sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;
- esac
-])
-
-#--------------------------------------------------------------------
-# TEA_MISSING_POSIX_HEADERS
-#
-# Supply substitutes for missing POSIX header files. Special
-# notes:
-# - stdlib.h doesn't define strtol, strtoul, or
-# strtod in some versions of SunOS
-# - some versions of string.h don't declare procedures such
-# as strstr
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Defines some of the following vars:
-# NO_DIRENT_H
-# NO_ERRNO_H
-# NO_VALUES_H
-# HAVE_LIMITS_H or NO_LIMITS_H
-# NO_STDLIB_H
-# NO_STRING_H
-# NO_SYS_WAIT_H
-# NO_DLFCN_H
-# HAVE_SYS_PARAM_H
-#
-# HAVE_STRING_H ?
-#
-# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and
-# CHECK on limits.h
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [
- AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
- AC_TRY_LINK([#include <sys/types.h>
-#include <dirent.h>], [
-#ifndef _POSIX_SOURCE
-# ifdef __Lynx__
- /*
- * Generate compilation error to make the test fail: Lynx headers
- * are only valid if really in the POSIX environment.
- */
-
- missing_procedure();
-# endif
-#endif
-DIR *d;
-struct dirent *entryPtr;
-char *p;
-d = opendir("foobar");
-entryPtr = readdir(d);
-p = entryPtr->d_name;
-closedir(d);
-], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])
-
- if test $tcl_cv_dirent_h = no; then
- AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
- fi
-
- # TEA specific:
- AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])
- AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
- AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
- AC_CHECK_HEADER(limits.h,
- [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])],
- [AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])])
- AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
- AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
- AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
- AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)
- if test $tcl_ok = 0; then
- AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
- fi
- AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
- AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
- AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)
-
- # See also memmove check below for a place where NO_STRING_H can be
- # set and why.
-
- if test $tcl_ok = 0; then
- AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
- fi
-
- AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
- AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])
-
- # OS/390 lacks sys/param.h (and doesn't need it, by chance).
- AC_HAVE_HEADERS(sys/param.h)
-])
-
-#--------------------------------------------------------------------
-# TEA_PATH_X
-#
-# Locate the X11 header files and the X11 library archive. Try
-# the ac_path_x macro first, but if it doesn't find the X stuff
-# (e.g. because there's no xmkmf program) then check through
-# a list of possible directories. Under some conditions the
-# autoconf macro will return an include directory that contains
-# no include files, so double-check its result just to be safe.
-#
-# This should be called after TEA_CONFIG_CFLAGS as setting the
-# LIBS line can confuse some configure macro magic.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Sets the following vars:
-# XINCLUDES
-# XLIBSW
-# PKG_LIBS (appends to)
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_PATH_X], [
- if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then
- TEA_PATH_UNIX_X
- fi
-])
-
-AC_DEFUN([TEA_PATH_UNIX_X], [
- AC_PATH_X
- not_really_there=""
- if test "$no_x" = ""; then
- if test "$x_includes" = ""; then
- AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes")
- else
- if test ! -r $x_includes/X11/Xlib.h; then
- not_really_there="yes"
- fi
- fi
- fi
- if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
- AC_MSG_CHECKING([for X11 header files])
- found_xincludes="no"
- AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no")
- if test "$found_xincludes" = "no"; then
- dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
- for i in $dirs ; do
- if test -r $i/X11/Xlib.h; then
- AC_MSG_RESULT([$i])
- XINCLUDES=" -I$i"
- found_xincludes="yes"
- break
- fi
- done
- fi
- else
- if test "$x_includes" != ""; then
- XINCLUDES="-I$x_includes"
- found_xincludes="yes"
- fi
- fi
- if test "$found_xincludes" = "no"; then
- AC_MSG_RESULT([couldn't find any!])
- fi
-
- if test "$no_x" = yes; then
- AC_MSG_CHECKING([for X11 libraries])
- XLIBSW=nope
- dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib"
- for i in $dirs ; do
- if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then
- AC_MSG_RESULT([$i])
- XLIBSW="-L$i -lX11"
- x_libraries="$i"
- break
- fi
- done
- else
- if test "$x_libraries" = ""; then
- XLIBSW=-lX11
- else
- XLIBSW="-L$x_libraries -lX11"
- fi
- fi
- if test "$XLIBSW" = nope ; then
- AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)
- fi
- if test "$XLIBSW" = nope ; then
- AC_MSG_RESULT([could not find any! Using -lX11.])
- XLIBSW=-lX11
- fi
- # TEA specific:
- if test x"${XLIBSW}" != x ; then
- PKG_LIBS="${PKG_LIBS} ${XLIBSW}"
- fi
-])
-
-#--------------------------------------------------------------------
-# TEA_BLOCKING_STYLE
-#
-# The statements below check for systems where POSIX-style
-# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
-# On these systems (mostly older ones), use the old BSD-style
-# FIONBIO approach instead.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Defines some of the following vars:
-# HAVE_SYS_IOCTL_H
-# HAVE_SYS_FILIO_H
-# USE_FIONBIO
-# O_NONBLOCK
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_BLOCKING_STYLE], [
- AC_CHECK_HEADERS(sys/ioctl.h)
- AC_CHECK_HEADERS(sys/filio.h)
- TEA_CONFIG_SYSTEM
- AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])
- case $system in
- OSF*)
- AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
- AC_MSG_RESULT([FIONBIO])
- ;;
- *)
- AC_MSG_RESULT([O_NONBLOCK])
- ;;
- esac
-])
-
-#--------------------------------------------------------------------
-# TEA_TIME_HANDLER
-#
-# Checks how the system deals with time.h, what time structures
-# are used on the system, and what fields the structures have.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Defines some of the following vars:
-# USE_DELTA_FOR_TZ
-# HAVE_TM_GMTOFF
-# HAVE_TM_TZADJ
-# HAVE_TIMEZONE_VAR
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_TIME_HANDLER], [
- AC_CHECK_HEADERS(sys/time.h)
- AC_HEADER_TIME
- AC_STRUCT_TIMEZONE
-
- AC_CHECK_FUNCS(gmtime_r localtime_r)
-
- AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
- AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
- tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])
- if test $tcl_cv_member_tm_tzadj = yes ; then
- AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
- fi
-
- AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
- AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
- tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])
- if test $tcl_cv_member_tm_gmtoff = yes ; then
- AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
- fi
-
- #
- # Its important to include time.h in this check, as some systems
- # (like convex) have timezone functions, etc.
- #
- AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
- AC_TRY_COMPILE([#include <time.h>],
- [extern long timezone;
- timezone += 1;
- exit (0);],
- tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
- if test $tcl_cv_timezone_long = yes ; then
- AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
- else
- #
- # On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
- #
- AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
- AC_TRY_COMPILE([#include <time.h>],
- [extern time_t timezone;
- timezone += 1;
- exit (0);],
- tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])
- if test $tcl_cv_timezone_time = yes ; then
- AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
- fi
- fi
-])
-
-#--------------------------------------------------------------------
-# TEA_BUGGY_STRTOD
-#
-# Under Solaris 2.4, strtod returns the wrong value for the
-# terminating character under some conditions. Check for this
-# and if the problem exists use a substitute procedure
-# "fixstrtod" (provided by Tcl) that corrects the error.
-# Also, on Compaq's Tru64 Unix 5.0,
-# strtod(" ") returns 0.0 instead of a failure to convert.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Might defines some of the following vars:
-# strtod (=fixstrtod)
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_BUGGY_STRTOD], [
- AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
- if test "$tcl_strtod" = 1; then
- AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[
- AC_TRY_RUN([
- extern double strtod();
- int main() {
- char *infString="Inf", *nanString="NaN", *spaceString=" ";
- char *term;
- double value;
- value = strtod(infString, &term);
- if ((term != infString) && (term[-1] == 0)) {
- exit(1);
- }
- value = strtod(nanString, &term);
- if ((term != nanString) && (term[-1] == 0)) {
- exit(1);
- }
- value = strtod(spaceString, &term);
- if (term == (spaceString+1)) {
- exit(1);
- }
- exit(0);
- }], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,
- tcl_cv_strtod_buggy=buggy)])
- if test "$tcl_cv_strtod_buggy" = buggy; then
- AC_LIBOBJ([fixstrtod])
- USE_COMPAT=1
- AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
- fi
- fi
-])
-
-#--------------------------------------------------------------------
-# TEA_TCL_LINK_LIBS
-#
-# Search for the libraries needed to link the Tcl shell.
-# Things like the math library (-lm) and socket stuff (-lsocket vs.
-# -lnsl) are dealt with here.
-#
-# Arguments:
-# Requires the following vars to be set in the Makefile:
-# DL_LIBS (not in TEA, only needed in core)
-# LIBS
-# MATH_LIBS
-#
-# Results:
-#
-# Substitutes the following vars:
-# TCL_LIBS
-# MATH_LIBS
-#
-# Might append to the following vars:
-# LIBS
-#
-# Might define the following vars:
-# HAVE_NET_ERRNO_H
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_TCL_LINK_LIBS], [
- #--------------------------------------------------------------------
- # On a few very rare systems, all of the libm.a stuff is
- # already in libc.a. Set compiler flags accordingly.
- # Also, Linux requires the "ieee" library for math to work
- # right (and it must appear before "-lm").
- #--------------------------------------------------------------------
-
- AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm")
- AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"])
-
- #--------------------------------------------------------------------
- # Interactive UNIX requires -linet instead of -lsocket, plus it
- # needs net/errno.h to define the socket-related error codes.
- #--------------------------------------------------------------------
-
- AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"])
- AC_CHECK_HEADER(net/errno.h, [
- AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])])
-
- #--------------------------------------------------------------------
- # Check for the existence of the -lsocket and -lnsl libraries.
- # The order here is important, so that they end up in the right
- # order in the command line generated by make. Here are some
- # special considerations:
- # 1. Use "connect" and "accept" to check for -lsocket, and
- # "gethostbyname" to check for -lnsl.
- # 2. Use each function name only once: can't redo a check because
- # autoconf caches the results of the last check and won't redo it.
- # 3. Use -lnsl and -lsocket only if they supply procedures that
- # aren't already present in the normal libraries. This is because
- # IRIX 5.2 has libraries, but they aren't needed and they're
- # bogus: they goof up name resolution if used.
- # 4. On some SVR4 systems, can't use -lsocket without -lnsl too.
- # To get around this problem, check for both libraries together
- # if -lsocket doesn't work by itself.
- #--------------------------------------------------------------------
-
- tcl_checkBoth=0
- AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1)
- if test "$tcl_checkSocket" = 1; then
- AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt,
- LIBS="$LIBS -lsocket", tcl_checkBoth=1)])
- fi
- if test "$tcl_checkBoth" = 1; then
- tk_oldLibs=$LIBS
- LIBS="$LIBS -lsocket -lnsl"
- AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
- fi
- AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
- [LIBS="$LIBS -lnsl"])])
-
- # TEA specific: Don't perform the eval of the libraries here because
- # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS
-
- TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
- AC_SUBST(TCL_LIBS)
- AC_SUBST(MATH_LIBS)
-])
-
-#--------------------------------------------------------------------
-# TEA_TCL_EARLY_FLAGS
-#
-# Check for what flags are needed to be passed so the correct OS
-# features are available.
-#
-# Arguments:
-# None
-#
-# Results:
-#
-# Might define the following vars:
-# _ISOC99_SOURCE
-# _LARGEFILE64_SOURCE
-# _LARGEFILE_SOURCE64
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_TCL_EARLY_FLAG],[
- AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
- AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
- AC_TRY_COMPILE([[#define ]$1[ 1
-]$2], $3,
- [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
- [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
- if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
- AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
- tcl_flags="$tcl_flags $1"
- fi
-])
-
-AC_DEFUN([TEA_TCL_EARLY_FLAGS],[
- AC_MSG_CHECKING([for required early compiler flags])
- tcl_flags=""
- TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],
- [char *p = (char *)strtoll; char *q = (char *)strtoull;])
- TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
- [struct stat64 buf; int i = stat64("/", &buf);])
- TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],
- [char *p = (char *)open64;])
- if test "x${tcl_flags}" = "x" ; then
- AC_MSG_RESULT([none])
- else
- AC_MSG_RESULT([${tcl_flags}])
- fi
-])
-
-#--------------------------------------------------------------------
-# TEA_TCL_64BIT_FLAGS
-#
-# Check for what is defined in the way of 64-bit features.
-#
-# Arguments:
-# None
-#
-# Results:
-#
-# Might define the following vars:
-# TCL_WIDE_INT_IS_LONG
-# TCL_WIDE_INT_TYPE
-# HAVE_STRUCT_DIRENT64
-# HAVE_STRUCT_STAT64
-# HAVE_TYPE_OFF64_T
-#--------------------------------------------------------------------
-
-AC_DEFUN([TEA_TCL_64BIT_FLAGS], [
- AC_MSG_CHECKING([for 64-bit integer type])
- AC_CACHE_VAL(tcl_cv_type_64bit,[
- tcl_cv_type_64bit=none
- # See if the compiler knows natively about __int64
- AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
- tcl_type_64bit=__int64, tcl_type_64bit="long long")
- # See if we should use long anyway Note that we substitute in the
- # type that is our current guess for a 64-bit type inside this check
- # program, so it should be modified only carefully...
- AC_TRY_COMPILE(,[switch (0) {
- case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
- }],tcl_cv_type_64bit=${tcl_type_64bit})])
- if test "${tcl_cv_type_64bit}" = none ; then
- AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
- AC_MSG_RESULT([using long])
- elif test "${tcl_cv_type_64bit}" = "__int64" \
- -a "${TEA_PLATFORM}" = "windows" ; then
- # TEA specific: We actually want to use the default tcl.h checks in
- # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*
- AC_MSG_RESULT([using Tcl header defaults])
- else
- AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
- [What type should be used to define wide integers?])
- AC_MSG_RESULT([${tcl_cv_type_64bit}])
-
- # Now check for auxiliary declarations
- AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
- AC_TRY_COMPILE([#include <sys/types.h>
-#include <dirent.h>],[struct dirent64 p;],
- tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
- if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
- AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
- fi
-
- AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
- AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
-],
- tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
- if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
- AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
- fi
-
- AC_CHECK_FUNCS(open64 lseek64)
- AC_MSG_CHECKING([for off64_t])
- AC_CACHE_VAL(tcl_cv_type_off64_t,[
- AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
-],
- tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
- dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
- dnl functions lseek64 and open64 are defined.
- if test "x${tcl_cv_type_off64_t}" = "xyes" && \
- test "x${ac_cv_func_lseek64}" = "xyes" && \
- test "x${ac_cv_func_open64}" = "xyes" ; then
- AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
- fi
- fi
-])
-
-##
-## Here ends the standard Tcl configuration bits and starts the
-## TEA specific functions
-##
-
-#------------------------------------------------------------------------
-# TEA_INIT --
-#
-# Init various Tcl Extension Architecture (TEA) variables.
-# This should be the first called TEA_* macro.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Defines and substs the following vars:
-# CYGPATH
-# EXEEXT
-# Defines only:
-# TEA_VERSION
-# TEA_INITED
-# TEA_PLATFORM (windows or unix)
-#
-# "cygpath" is used on windows to generate native path names for include
-# files. These variables should only be used with the compiler and linker
-# since they generate native path names.
-#
-# EXEEXT
-# Select the executable extension based on the host type. This
-# is a lightweight replacement for AC_EXEEXT that doesn't require
-# a compiler.
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_INIT], [
- # TEA extensions pass this us the version of TEA they think they
- # are compatible with.
- TEA_VERSION="3.9"
-
- AC_MSG_CHECKING([for correct TEA configuration])
- if test x"${PACKAGE_NAME}" = x ; then
- AC_MSG_ERROR([
-The PACKAGE_NAME variable must be defined by your TEA configure.in])
- fi
- if test x"$1" = x ; then
- AC_MSG_ERROR([
-TEA version not specified.])
- elif test "$1" != "${TEA_VERSION}" ; then
- AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"])
- else
- AC_MSG_RESULT([ok (TEA ${TEA_VERSION})])
- fi
-
- # If the user did not set CFLAGS, set it now to keep macros
- # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
- if test "${CFLAGS+set}" != "set" ; then
- CFLAGS=""
- fi
-
- case "`uname -s`" in
- *win32*|*WIN32*|*MINGW32_*)
- AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
- EXEEXT=".exe"
- TEA_PLATFORM="windows"
- ;;
- *CYGWIN_*)
- CYGPATH=echo
- EXEEXT=".exe"
- # TEA_PLATFORM is determined later in LOAD_TCLCONFIG
- ;;
- *)
- CYGPATH=echo
- # Maybe we are cross-compiling....
- case ${host_alias} in
- *mingw32*)
- EXEEXT=".exe"
- TEA_PLATFORM="windows"
- ;;
- *)
- EXEEXT=""
- TEA_PLATFORM="unix"
- ;;
- esac
- ;;
- esac
-
- # Check if exec_prefix is set. If not use fall back to prefix.
- # Note when adjusted, so that TEA_PREFIX can correct for this.
- # This is needed for recursive configures, since autoconf propagates
- # $prefix, but not $exec_prefix (doh!).
- if test x$exec_prefix = xNONE ; then
- exec_prefix_default=yes
- exec_prefix=$prefix
- fi
-
- AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}])
-
- AC_SUBST(EXEEXT)
- AC_SUBST(CYGPATH)
-
- # This package name must be replaced statically for AC_SUBST to work
- AC_SUBST(PKG_LIB_FILE)
- # Substitute STUB_LIB_FILE in case package creates a stub library too.
- AC_SUBST(PKG_STUB_LIB_FILE)
-
- # We AC_SUBST these here to ensure they are subst'ed,
- # in case the user doesn't call TEA_ADD_...
- AC_SUBST(PKG_STUB_SOURCES)
- AC_SUBST(PKG_STUB_OBJECTS)
- AC_SUBST(PKG_TCL_SOURCES)
- AC_SUBST(PKG_HEADERS)
- AC_SUBST(PKG_INCLUDES)
- AC_SUBST(PKG_LIBS)
- AC_SUBST(PKG_CFLAGS)
-])
-
-#------------------------------------------------------------------------
-# TEA_ADD_SOURCES --
-#
-# Specify one or more source files. Users should check for
-# the right platform before adding to their list.
-# It is not important to specify the directory, as long as it is
-# in the generic, win or unix subdirectory of $(srcdir).
-#
-# Arguments:
-# one or more file names
-#
-# Results:
-#
-# Defines and substs the following vars:
-# PKG_SOURCES
-# PKG_OBJECTS
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_ADD_SOURCES], [
- vars="$@"
- for i in $vars; do
- case $i in
- [\$]*)
- # allow $-var names
- PKG_SOURCES="$PKG_SOURCES $i"
- PKG_OBJECTS="$PKG_OBJECTS $i"
- ;;
- *)
- # check for existence - allows for generic/win/unix VPATH
- # To add more dirs here (like 'src'), you have to update VPATH
- # in Makefile.in as well
- if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
- -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
- -a ! -f "${srcdir}/macosx/$i" \
- ; then
- AC_MSG_ERROR([could not find source file '$i'])
- fi
- PKG_SOURCES="$PKG_SOURCES $i"
- # this assumes it is in a VPATH dir
- i=`basename $i`
- # handle user calling this before or after TEA_SETUP_COMPILER
- if test x"${OBJEXT}" != x ; then
- j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
- else
- j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
- fi
- PKG_OBJECTS="$PKG_OBJECTS $j"
- ;;
- esac
- done
- AC_SUBST(PKG_SOURCES)
- AC_SUBST(PKG_OBJECTS)
-])
-
-#------------------------------------------------------------------------
-# TEA_ADD_STUB_SOURCES --
-#
-# Specify one or more source files. Users should check for
-# the right platform before adding to their list.
-# It is not important to specify the directory, as long as it is
-# in the generic, win or unix subdirectory of $(srcdir).
-#
-# Arguments:
-# one or more file names
-#
-# Results:
-#
-# Defines and substs the following vars:
-# PKG_STUB_SOURCES
-# PKG_STUB_OBJECTS
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_ADD_STUB_SOURCES], [
- vars="$@"
- for i in $vars; do
- # check for existence - allows for generic/win/unix VPATH
- if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
- -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
- -a ! -f "${srcdir}/macosx/$i" \
- ; then
- AC_MSG_ERROR([could not find stub source file '$i'])
- fi
- PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i"
- # this assumes it is in a VPATH dir
- i=`basename $i`
- # handle user calling this before or after TEA_SETUP_COMPILER
- if test x"${OBJEXT}" != x ; then
- j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
- else
- j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
- fi
- PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j"
- done
- AC_SUBST(PKG_STUB_SOURCES)
- AC_SUBST(PKG_STUB_OBJECTS)
-])
-
-#------------------------------------------------------------------------
-# TEA_ADD_TCL_SOURCES --
-#
-# Specify one or more Tcl source files. These should be platform
-# independent runtime files.
-#
-# Arguments:
-# one or more file names
-#
-# Results:
-#
-# Defines and substs the following vars:
-# PKG_TCL_SOURCES
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_ADD_TCL_SOURCES], [
- vars="$@"
- for i in $vars; do
- # check for existence, be strict because it is installed
- if test ! -f "${srcdir}/$i" ; then
- AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i'])
- fi
- PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i"
- done
- AC_SUBST(PKG_TCL_SOURCES)
-])
-
-#------------------------------------------------------------------------
-# TEA_ADD_HEADERS --
-#
-# Specify one or more source headers. Users should check for
-# the right platform before adding to their list.
-#
-# Arguments:
-# one or more file names
-#
-# Results:
-#
-# Defines and substs the following vars:
-# PKG_HEADERS
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_ADD_HEADERS], [
- vars="$@"
- for i in $vars; do
- # check for existence, be strict because it is installed
- if test ! -f "${srcdir}/$i" ; then
- AC_MSG_ERROR([could not find header file '${srcdir}/$i'])
- fi
- PKG_HEADERS="$PKG_HEADERS $i"
- done
- AC_SUBST(PKG_HEADERS)
-])
-
-#------------------------------------------------------------------------
-# TEA_ADD_INCLUDES --
-#
-# Specify one or more include dirs. Users should check for
-# the right platform before adding to their list.
-#
-# Arguments:
-# one or more file names
-#
-# Results:
-#
-# Defines and substs the following vars:
-# PKG_INCLUDES
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_ADD_INCLUDES], [
- vars="$@"
- for i in $vars; do
- PKG_INCLUDES="$PKG_INCLUDES $i"
- done
- AC_SUBST(PKG_INCLUDES)
-])
-
-#------------------------------------------------------------------------
-# TEA_ADD_LIBS --
-#
-# Specify one or more libraries. Users should check for
-# the right platform before adding to their list. For Windows,
-# libraries provided in "foo.lib" format will be converted to
-# "-lfoo" when using GCC (mingw).
-#
-# Arguments:
-# one or more file names
-#
-# Results:
-#
-# Defines and substs the following vars:
-# PKG_LIBS
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_ADD_LIBS], [
- vars="$@"
- for i in $vars; do
- if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
- # Convert foo.lib to -lfoo for GCC. No-op if not *.lib
- i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'`
- fi
- PKG_LIBS="$PKG_LIBS $i"
- done
- AC_SUBST(PKG_LIBS)
-])
-
-#------------------------------------------------------------------------
-# TEA_ADD_CFLAGS --
-#
-# Specify one or more CFLAGS. Users should check for
-# the right platform before adding to their list.
-#
-# Arguments:
-# one or more file names
-#
-# Results:
-#
-# Defines and substs the following vars:
-# PKG_CFLAGS
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_ADD_CFLAGS], [
- PKG_CFLAGS="$PKG_CFLAGS $@"
- AC_SUBST(PKG_CFLAGS)
-])
-
-#------------------------------------------------------------------------
-# TEA_ADD_CLEANFILES --
-#
-# Specify one or more CLEANFILES.
-#
-# Arguments:
-# one or more file names to clean target
-#
-# Results:
-#
-# Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_ADD_CLEANFILES], [
- CLEANFILES="$CLEANFILES $@"
-])
-
-#------------------------------------------------------------------------
-# TEA_PREFIX --
-#
-# Handle the --prefix=... option by defaulting to what Tcl gave
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# If --prefix or --exec-prefix was not specified, $prefix and
-# $exec_prefix will be set to the values given to Tcl when it was
-# configured.
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_PREFIX], [
- if test "${prefix}" = "NONE"; then
- prefix_default=yes
- if test x"${TCL_PREFIX}" != x; then
- AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}])
- prefix=${TCL_PREFIX}
- else
- AC_MSG_NOTICE([--prefix defaulting to /usr/local])
- prefix=/usr/local
- fi
- fi
- if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \
- -o x"${exec_prefix_default}" = x"yes" ; then
- if test x"${TCL_EXEC_PREFIX}" != x; then
- AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}])
- exec_prefix=${TCL_EXEC_PREFIX}
- else
- AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}])
- exec_prefix=$prefix
- fi
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_SETUP_COMPILER_CC --
-#
-# Do compiler checks the way we want. This is just a replacement
-# for AC_PROG_CC in TEA configure.in files to make them cleaner.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Sets up CC var and other standard bits we need to make executables.
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_SETUP_COMPILER_CC], [
- # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)
- # in this macro, they need to go into TEA_SETUP_COMPILER instead.
-
- AC_PROG_CC
- AC_PROG_CPP
-
- INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c"
- AC_SUBST(INSTALL)
- INSTALL_DATA="\${INSTALL} -m 644"
- AC_SUBST(INSTALL_DATA)
- INSTALL_PROGRAM="\${INSTALL}"
- AC_SUBST(INSTALL_PROGRAM)
- INSTALL_SCRIPT="\${INSTALL}"
- AC_SUBST(INSTALL_SCRIPT)
-
- #--------------------------------------------------------------------
- # Checks to see if the make program sets the $MAKE variable.
- #--------------------------------------------------------------------
-
- AC_PROG_MAKE_SET
-
- #--------------------------------------------------------------------
- # Find ranlib
- #--------------------------------------------------------------------
-
- AC_CHECK_TOOL(RANLIB, ranlib)
-
- #--------------------------------------------------------------------
- # Determines the correct binary file extension (.o, .obj, .exe etc.)
- #--------------------------------------------------------------------
-
- AC_OBJEXT
- AC_EXEEXT
-])
-
-#------------------------------------------------------------------------
-# TEA_SETUP_COMPILER --
-#
-# Do compiler checks that use the compiler. This must go after
-# TEA_SETUP_COMPILER_CC, which does the actual compiler check.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Sets up CC var and other standard bits we need to make executables.
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_SETUP_COMPILER], [
- # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here.
- AC_REQUIRE([TEA_SETUP_COMPILER_CC])
-
- #------------------------------------------------------------------------
- # If we're using GCC, see if the compiler understands -pipe. If so, use it.
- # It makes compiling go faster. (This is only a performance feature.)
- #------------------------------------------------------------------------
-
- if test -z "$no_pipe" -a -n "$GCC"; then
- AC_CACHE_CHECK([if the compiler understands -pipe],
- tcl_cv_cc_pipe, [
- hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
- AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
- CFLAGS=$hold_cflags])
- if test $tcl_cv_cc_pipe = yes; then
- CFLAGS="$CFLAGS -pipe"
- fi
- fi
-
- #--------------------------------------------------------------------
- # Common compiler flag setup
- #--------------------------------------------------------------------
-
- AC_C_BIGENDIAN
- if test "${TEA_PLATFORM}" = "unix" ; then
- TEA_TCL_LINK_LIBS
- TEA_MISSING_POSIX_HEADERS
- # Let the user call this, because if it triggers, they will
- # need a compat/strtod.c that is correct. Users can also
- # use Tcl_GetDouble(FromObj) instead.
- #TEA_BUGGY_STRTOD
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_MAKE_LIB --
-#
-# Generate a line that can be used to build a shared/unshared library
-# in a platform independent manner.
-#
-# Arguments:
-# none
-#
-# Requires:
-#
-# Results:
-#
-# Defines the following vars:
-# CFLAGS - Done late here to note disturb other AC macros
-# MAKE_LIB - Command to execute to build the Tcl library;
-# differs depending on whether or not Tcl is being
-# compiled as a shared library.
-# MAKE_SHARED_LIB Makefile rule for building a shared library
-# MAKE_STATIC_LIB Makefile rule for building a static library
-# MAKE_STUB_LIB Makefile rule for building a stub library
-# VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL
-# VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_MAKE_LIB], [
- if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
- MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)"
- MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)"
- AC_EGREP_CPP([manifest needed], [
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-print("manifest needed")
-#endif
- ], [
- # Could do a CHECK_PROG for mt, but should always be with MSVC8+
- VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi"
- VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi"
- MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}"
- TEA_ADD_CLEANFILES([*.manifest])
- ])
- MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)"
- else
- MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)"
- MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
- MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)"
- fi
-
- if test "${SHARED_BUILD}" = "1" ; then
- MAKE_LIB="${MAKE_SHARED_LIB} "
- else
- MAKE_LIB="${MAKE_STATIC_LIB} "
- fi
-
- #--------------------------------------------------------------------
- # Shared libraries and static libraries have different names.
- # Use the double eval to make sure any variables in the suffix is
- # substituted. (@@@ Might not be necessary anymore)
- #--------------------------------------------------------------------
-
- if test "${TEA_PLATFORM}" = "windows" ; then
- if test "${SHARED_BUILD}" = "1" ; then
- # We force the unresolved linking of symbols that are really in
- # the private libraries of Tcl and Tk.
- if test x"${TK_BIN_DIR}" != x ; then
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\""
- fi
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\""
- if test "$GCC" = "yes"; then
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc"
- fi
- eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
- else
- eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
- if test "$GCC" = "yes"; then
- PKG_LIB_FILE=lib${PKG_LIB_FILE}
- fi
- fi
- # Some packages build their own stubs libraries
- eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
- if test "$GCC" = "yes"; then
- PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}
- fi
- # These aren't needed on Windows (either MSVC or gcc)
- RANLIB=:
- RANLIB_STUB=:
- else
- RANLIB_STUB="${RANLIB}"
- if test "${SHARED_BUILD}" = "1" ; then
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}"
- if test x"${TK_BIN_DIR}" != x ; then
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
- fi
- eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
- RANLIB=:
- else
- eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
- fi
- # Some packages build their own stubs libraries
- eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
- fi
-
- # These are escaped so that only CFLAGS is picked up at configure time.
- # The other values will be substituted at make time.
- CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
- if test "${SHARED_BUILD}" = "1" ; then
- CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
- fi
-
- AC_SUBST(MAKE_LIB)
- AC_SUBST(MAKE_SHARED_LIB)
- AC_SUBST(MAKE_STATIC_LIB)
- AC_SUBST(MAKE_STUB_LIB)
- AC_SUBST(RANLIB_STUB)
- AC_SUBST(VC_MANIFEST_EMBED_DLL)
- AC_SUBST(VC_MANIFEST_EMBED_EXE)
-])
-
-#------------------------------------------------------------------------
-# TEA_LIB_SPEC --
-#
-# Compute the name of an existing object library located in libdir
-# from the given base name and produce the appropriate linker flags.
-#
-# Arguments:
-# basename The base name of the library without version
-# numbers, extensions, or "lib" prefixes.
-# extra_dir Extra directory in which to search for the
-# library. This location is used first, then
-# $prefix/$exec-prefix, then some defaults.
-#
-# Requires:
-# TEA_INIT and TEA_PREFIX must be called first.
-#
-# Results:
-#
-# Defines the following vars:
-# ${basename}_LIB_NAME The computed library name.
-# ${basename}_LIB_SPEC The computed linker flags.
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_LIB_SPEC], [
- AC_MSG_CHECKING([for $1 library])
-
- # Look in exec-prefix for the library (defined by TEA_PREFIX).
-
- tea_lib_name_dir="${exec_prefix}/lib"
-
- # Or in a user-specified location.
-
- if test x"$2" != x ; then
- tea_extra_lib_dir=$2
- else
- tea_extra_lib_dir=NONE
- fi
-
- for i in \
- `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
- `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \
- `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
- `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \
- `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \
- `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \
- `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \
- `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \
- `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \
- `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do
- if test -f "$i" ; then
- tea_lib_name_dir=`dirname $i`
- $1_LIB_NAME=`basename $i`
- $1_LIB_PATH_NAME=$i
- break
- fi
- done
-
- if test "${TEA_PLATFORM}" = "windows"; then
- $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\"
- else
- # Strip off the leading "lib" and trailing ".a" or ".so"
-
- tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'`
- $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}"
- fi
-
- if test "x${$1_LIB_NAME}" = x ; then
- AC_MSG_ERROR([not found])
- else
- AC_MSG_RESULT([${$1_LIB_SPEC}])
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_PRIVATE_TCL_HEADERS --
-#
-# Locate the private Tcl include files
-#
-# Arguments:
-#
-# Requires:
-# TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has
-# already been called.
-#
-# Results:
-#
-# Substitutes the following vars:
-# TCL_TOP_DIR_NATIVE
-# TCL_INCLUDES
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [
- # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh}
- AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS])
- AC_MSG_CHECKING([for Tcl private include files])
-
- TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}`
- TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\"
-
- # Check to see if tcl<Plat>Port.h isn't already with the public headers
- # Don't look for tclInt.h because that resides with tcl.h in the core
- # sources, but the <plat>Port headers are in a different directory
- if test "${TEA_PLATFORM}" = "windows" -a \
- -f "${ac_cv_c_tclh}/tclWinPort.h"; then
- result="private headers found with public headers"
- elif test "${TEA_PLATFORM}" = "unix" -a \
- -f "${ac_cv_c_tclh}/tclUnixPort.h"; then
- result="private headers found with public headers"
- else
- TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\"
- if test "${TEA_PLATFORM}" = "windows"; then
- TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\"
- else
- TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\"
- fi
- # Overwrite the previous TCL_INCLUDES as this should capture both
- # public and private headers in the same set.
- # We want to ensure these are substituted so as not to require
- # any *_NATIVE vars be defined in the Makefile
- TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}"
- if test "`uname -s`" = "Darwin"; then
- # If Tcl was built as a framework, attempt to use
- # the framework's Headers and PrivateHeaders directories
- case ${TCL_DEFS} in
- *TCL_FRAMEWORK*)
- if test -d "${TCL_BIN_DIR}/Headers" -a \
- -d "${TCL_BIN_DIR}/PrivateHeaders"; then
- TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}"
- else
- TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
- fi
- ;;
- esac
- result="Using ${TCL_INCLUDES}"
- else
- if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then
- AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}])
- fi
- result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}"
- fi
- fi
-
- AC_SUBST(TCL_TOP_DIR_NATIVE)
-
- AC_SUBST(TCL_INCLUDES)
- AC_MSG_RESULT([${result}])
-])
-
-#------------------------------------------------------------------------
-# TEA_PUBLIC_TCL_HEADERS --
-#
-# Locate the installed public Tcl header files
-#
-# Arguments:
-# None.
-#
-# Requires:
-# CYGPATH must be set
-#
-# Results:
-#
-# Adds a --with-tclinclude switch to configure.
-# Result is cached.
-#
-# Substitutes the following vars:
-# TCL_INCLUDES
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [
- AC_MSG_CHECKING([for Tcl public headers])
-
- AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval})
-
- AC_CACHE_VAL(ac_cv_c_tclh, [
- # Use the value from --with-tclinclude, if it was given
-
- if test x"${with_tclinclude}" != x ; then
- if test -f "${with_tclinclude}/tcl.h" ; then
- ac_cv_c_tclh=${with_tclinclude}
- else
- AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h])
- fi
- else
- list=""
- if test "`uname -s`" = "Darwin"; then
- # If Tcl was built as a framework, attempt to use
- # the framework's Headers directory
- case ${TCL_DEFS} in
- *TCL_FRAMEWORK*)
- list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`"
- ;;
- esac
- fi
-
- # Look in the source dir only if Tcl is not installed,
- # and in that situation, look there before installed locations.
- if test -f "${TCL_BIN_DIR}/Makefile" ; then
- list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`"
- fi
-
- # Check order: pkg --prefix location, Tcl's --prefix location,
- # relative to directory of tclConfig.sh.
-
- eval "temp_includedir=${includedir}"
- list="$list \
- `ls -d ${temp_includedir} 2>/dev/null` \
- `ls -d ${TCL_PREFIX}/include 2>/dev/null` \
- `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
- if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
- list="$list /usr/local/include /usr/include"
- if test x"${TCL_INCLUDE_SPEC}" != x ; then
- d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'`
- list="$list `ls -d ${d} 2>/dev/null`"
- fi
- fi
- for i in $list ; do
- if test -f "$i/tcl.h" ; then
- ac_cv_c_tclh=$i
- break
- fi
- done
- fi
- ])
-
- # Print a message based on how we determined the include path
-
- if test x"${ac_cv_c_tclh}" = x ; then
- AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude])
- else
- AC_MSG_RESULT([${ac_cv_c_tclh}])
- fi
-
- # Convert to a native path and substitute into the output files.
-
- INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}`
-
- TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
-
- AC_SUBST(TCL_INCLUDES)
-])
-
-#------------------------------------------------------------------------
-# TEA_PRIVATE_TK_HEADERS --
-#
-# Locate the private Tk include files
-#
-# Arguments:
-#
-# Requires:
-# TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has
-# already been called.
-#
-# Results:
-#
-# Substitutes the following vars:
-# TK_INCLUDES
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [
- # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh}
- AC_REQUIRE([TEA_PUBLIC_TK_HEADERS])
- AC_MSG_CHECKING([for Tk private include files])
-
- TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}`
- TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\"
-
- # Check to see if tk<Plat>Port.h isn't already with the public headers
- # Don't look for tkInt.h because that resides with tk.h in the core
- # sources, but the <plat>Port headers are in a different directory
- if test "${TEA_PLATFORM}" = "windows" -a \
- -f "${ac_cv_c_tkh}/tkWinPort.h"; then
- result="private headers found with public headers"
- elif test "${TEA_PLATFORM}" = "unix" -a \
- -f "${ac_cv_c_tkh}/tkUnixPort.h"; then
- result="private headers found with public headers"
- else
- TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\"
- TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\"
- if test "${TEA_PLATFORM}" = "windows"; then
- TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\"
- else
- TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\"
- fi
- # Overwrite the previous TK_INCLUDES as this should capture both
- # public and private headers in the same set.
- # We want to ensure these are substituted so as not to require
- # any *_NATIVE vars be defined in the Makefile
- TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}"
- # Detect and add ttk subdir
- if test -d "${TK_SRC_DIR}/generic/ttk"; then
- TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\""
- fi
- if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
- TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\""
- fi
- if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then
- TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\""
- fi
- if test "`uname -s`" = "Darwin"; then
- # If Tk was built as a framework, attempt to use
- # the framework's Headers and PrivateHeaders directories
- case ${TK_DEFS} in
- *TK_FRAMEWORK*)
- if test -d "${TK_BIN_DIR}/Headers" -a \
- -d "${TK_BIN_DIR}/PrivateHeaders"; then
- TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}"
- else
- TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
- fi
- ;;
- esac
- result="Using ${TK_INCLUDES}"
- else
- if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then
- AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}])
- fi
- result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}"
- fi
- fi
-
- AC_SUBST(TK_TOP_DIR_NATIVE)
- AC_SUBST(TK_XLIB_DIR_NATIVE)
-
- AC_SUBST(TK_INCLUDES)
- AC_MSG_RESULT([${result}])
-])
-
-#------------------------------------------------------------------------
-# TEA_PUBLIC_TK_HEADERS --
-#
-# Locate the installed public Tk header files
-#
-# Arguments:
-# None.
-#
-# Requires:
-# CYGPATH must be set
-#
-# Results:
-#
-# Adds a --with-tkinclude switch to configure.
-# Result is cached.
-#
-# Substitutes the following vars:
-# TK_INCLUDES
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [
- AC_MSG_CHECKING([for Tk public headers])
-
- AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval})
-
- AC_CACHE_VAL(ac_cv_c_tkh, [
- # Use the value from --with-tkinclude, if it was given
-
- if test x"${with_tkinclude}" != x ; then
- if test -f "${with_tkinclude}/tk.h" ; then
- ac_cv_c_tkh=${with_tkinclude}
- else
- AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h])
- fi
- else
- list=""
- if test "`uname -s`" = "Darwin"; then
- # If Tk was built as a framework, attempt to use
- # the framework's Headers directory.
- case ${TK_DEFS} in
- *TK_FRAMEWORK*)
- list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`"
- ;;
- esac
- fi
-
- # Look in the source dir only if Tk is not installed,
- # and in that situation, look there before installed locations.
- if test -f "${TK_BIN_DIR}/Makefile" ; then
- list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`"
- fi
-
- # Check order: pkg --prefix location, Tk's --prefix location,
- # relative to directory of tkConfig.sh, Tcl's --prefix location,
- # relative to directory of tclConfig.sh.
-
- eval "temp_includedir=${includedir}"
- list="$list \
- `ls -d ${temp_includedir} 2>/dev/null` \
- `ls -d ${TK_PREFIX}/include 2>/dev/null` \
- `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \
- `ls -d ${TCL_PREFIX}/include 2>/dev/null` \
- `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
- if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
- list="$list /usr/local/include /usr/include"
- if test x"${TK_INCLUDE_SPEC}" != x ; then
- d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'`
- list="$list `ls -d ${d} 2>/dev/null`"
- fi
- fi
- for i in $list ; do
- if test -f "$i/tk.h" ; then
- ac_cv_c_tkh=$i
- break
- fi
- done
- fi
- ])
-
- # Print a message based on how we determined the include path
-
- if test x"${ac_cv_c_tkh}" = x ; then
- AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude])
- else
- AC_MSG_RESULT([${ac_cv_c_tkh}])
- fi
-
- # Convert to a native path and substitute into the output files.
-
- INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}`
-
- TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
-
- AC_SUBST(TK_INCLUDES)
-
- if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
- # On Windows and Aqua, we need the X compat headers
- AC_MSG_CHECKING([for X11 header files])
- if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then
- INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`"
- TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
- AC_SUBST(TK_XINCLUDES)
- fi
- AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}])
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_PATH_CONFIG --
-#
-# Locate the ${1}Config.sh file and perform a sanity check on
-# the ${1} compile flags. These are used by packages like
-# [incr Tk] that load *Config.sh files from more than Tcl and Tk.
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Adds the following arguments to configure:
-# --with-$1=...
-#
-# Defines the following vars:
-# $1_BIN_DIR Full path to the directory containing
-# the $1Config.sh file
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PATH_CONFIG], [
- #
- # Ok, lets find the $1 configuration
- # First, look for one uninstalled.
- # the alternative search directory is invoked by --with-$1
- #
-
- if test x"${no_$1}" = x ; then
- # we reset no_$1 in case something fails here
- no_$1=true
- AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval})
- AC_MSG_CHECKING([for $1 configuration])
- AC_CACHE_VAL(ac_cv_c_$1config,[
-
- # First check to see if --with-$1 was specified.
- if test x"${with_$1config}" != x ; then
- case ${with_$1config} in
- */$1Config.sh )
- if test -f ${with_$1config}; then
- AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself])
- with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'`
- fi;;
- esac
- if test -f "${with_$1config}/$1Config.sh" ; then
- ac_cv_c_$1config=`(cd ${with_$1config}; pwd)`
- else
- AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh])
- fi
- fi
-
- # then check for a private $1 installation
- if test x"${ac_cv_c_$1config}" = x ; then
- for i in \
- ../$1 \
- `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
- `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
- `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
- ../../$1 \
- `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
- `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
- `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
- ../../../$1 \
- `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
- `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
- `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
- ${srcdir}/../$1 \
- `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
- `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
- `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
- ; do
- if test -f "$i/$1Config.sh" ; then
- ac_cv_c_$1config=`(cd $i; pwd)`
- break
- fi
- if test -f "$i/unix/$1Config.sh" ; then
- ac_cv_c_$1config=`(cd $i/unix; pwd)`
- break
- fi
- done
- fi
-
- # check in a few common install locations
- if test x"${ac_cv_c_$1config}" = x ; then
- for i in `ls -d ${libdir} 2>/dev/null` \
- `ls -d ${exec_prefix}/lib 2>/dev/null` \
- `ls -d ${prefix}/lib 2>/dev/null` \
- `ls -d /usr/local/lib 2>/dev/null` \
- `ls -d /usr/contrib/lib 2>/dev/null` \
- `ls -d /usr/lib 2>/dev/null` \
- `ls -d /usr/lib64 2>/dev/null` \
- ; do
- if test -f "$i/$1Config.sh" ; then
- ac_cv_c_$1config=`(cd $i; pwd)`
- break
- fi
- done
- fi
- ])
-
- if test x"${ac_cv_c_$1config}" = x ; then
- $1_BIN_DIR="# no $1 configs found"
- AC_MSG_WARN([Cannot find $1 configuration definitions])
- exit 0
- else
- no_$1=
- $1_BIN_DIR=${ac_cv_c_$1config}
- AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh])
- fi
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_LOAD_CONFIG --
-#
-# Load the $1Config.sh file
-#
-# Arguments:
-#
-# Requires the following vars to be set:
-# $1_BIN_DIR
-#
-# Results:
-#
-# Substitutes the following vars:
-# $1_SRC_DIR
-# $1_LIB_FILE
-# $1_LIB_SPEC
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_LOAD_CONFIG], [
- AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh])
-
- if test -f "${$1_BIN_DIR}/$1Config.sh" ; then
- AC_MSG_RESULT([loading])
- . "${$1_BIN_DIR}/$1Config.sh"
- else
- AC_MSG_RESULT([file not found])
- fi
-
- #
- # If the $1_BIN_DIR is the build directory (not the install directory),
- # then set the common variable name to the value of the build variables.
- # For example, the variable $1_LIB_SPEC will be set to the value
- # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC
- # instead of $1_BUILD_LIB_SPEC since it will work with both an
- # installed and uninstalled version of Tcl.
- #
-
- if test -f "${$1_BIN_DIR}/Makefile" ; then
- AC_MSG_WARN([Found Makefile - using build library specs for $1])
- $1_LIB_SPEC=${$1_BUILD_LIB_SPEC}
- $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC}
- $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH}
- $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC}
- $1_LIBRARY_PATH=${$1_LIBRARY_PATH}
- fi
-
- AC_SUBST($1_VERSION)
- AC_SUBST($1_BIN_DIR)
- AC_SUBST($1_SRC_DIR)
-
- AC_SUBST($1_LIB_FILE)
- AC_SUBST($1_LIB_SPEC)
-
- AC_SUBST($1_STUB_LIB_FILE)
- AC_SUBST($1_STUB_LIB_SPEC)
- AC_SUBST($1_STUB_LIB_PATH)
-
- # Allow the caller to prevent this auto-check by specifying any 2nd arg
- AS_IF([test "x$2" = x], [
- # Check both upper and lower-case variants
- # If a dev wanted non-stubs libs, this function could take an option
- # to not use _STUB in the paths below
- AS_IF([test "x${$1_STUB_LIB_SPEC}" = x],
- [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)],
- [TEA_LOAD_CONFIG_LIB($1_STUB)])
- ])
-])
-
-#------------------------------------------------------------------------
-# TEA_LOAD_CONFIG_LIB --
-#
-# Helper function to load correct library from another extension's
-# ${PACKAGE}Config.sh.
-#
-# Results:
-# Adds to LIBS the appropriate extension library
-#------------------------------------------------------------------------
-AC_DEFUN([TEA_LOAD_CONFIG_LIB], [
- AC_MSG_CHECKING([For $1 library for LIBS])
- # This simplifies the use of stub libraries by automatically adding
- # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS,
- # but this is called before CONFIG_CFLAGS. More importantly, this adds
- # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD.
- if test "x${$1_LIB_SPEC}" != "x" ; then
- if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then
- TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"])
- AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}])
- else
- TEA_ADD_LIBS([${$1_LIB_SPEC}])
- AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}])
- fi
- else
- AC_MSG_RESULT([file not found])
- fi
-])
-
-#------------------------------------------------------------------------
-# TEA_EXPORT_CONFIG --
-#
-# Define the data to insert into the ${PACKAGE}Config.sh file
-#
-# Arguments:
-#
-# Requires the following vars to be set:
-# $1
-#
-# Results:
-# Substitutes the following vars:
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_EXPORT_CONFIG], [
- #--------------------------------------------------------------------
- # These are for $1Config.sh
- #--------------------------------------------------------------------
-
- # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib)
- eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}"
- if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
- eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}"
- eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}"
- else
- eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
- eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
- fi
- $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}"
- $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}"
- $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}"
- $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}"
- $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}"
- $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}"
-
- AC_SUBST($1_BUILD_LIB_SPEC)
- AC_SUBST($1_LIB_SPEC)
- AC_SUBST($1_BUILD_STUB_LIB_SPEC)
- AC_SUBST($1_STUB_LIB_SPEC)
- AC_SUBST($1_BUILD_STUB_LIB_PATH)
- AC_SUBST($1_STUB_LIB_PATH)
-
- AC_SUBST(MAJOR_VERSION)
- AC_SUBST(MINOR_VERSION)
- AC_SUBST(PATCHLEVEL)
-])
-
-
-#------------------------------------------------------------------------
-# TEA_PATH_CELIB --
-#
-# Locate Keuchel's celib emulation layer for targeting Win/CE
-#
-# Arguments:
-# none
-#
-# Results:
-#
-# Adds the following arguments to configure:
-# --with-celib=...
-#
-# Defines the following vars:
-# CELIB_DIR Full path to the directory containing
-# the include and platform lib files
-#------------------------------------------------------------------------
-
-AC_DEFUN([TEA_PATH_CELIB], [
- # First, look for one uninstalled.
- # the alternative search directory is invoked by --with-celib
-
- if test x"${no_celib}" = x ; then
- # we reset no_celib in case something fails here
- no_celib=true
- AC_ARG_WITH(celib,[ --with-celib=DIR use Windows/CE support library from DIR], with_celibconfig=${withval})
- AC_MSG_CHECKING([for Windows/CE celib directory])
- AC_CACHE_VAL(ac_cv_c_celibconfig,[
- # First check to see if --with-celibconfig was specified.
- if test x"${with_celibconfig}" != x ; then
- if test -d "${with_celibconfig}/inc" ; then
- ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`
- else
- AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory])
- fi
- fi
-
- # then check for a celib library
- if test x"${ac_cv_c_celibconfig}" = x ; then
- for i in \
- ../celib-palm-3.0 \
- ../celib \
- ../../celib-palm-3.0 \
- ../../celib \
- `ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \
- ${srcdir}/../celib-palm-3.0 \
- ${srcdir}/../celib \
- `ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \
- ; do
- if test -d "$i/inc" ; then
- ac_cv_c_celibconfig=`(cd $i; pwd)`
- break
- fi
- done
- fi
- ])
- if test x"${ac_cv_c_celibconfig}" = x ; then
- AC_MSG_ERROR([Cannot find celib support library directory])
- else
- no_celib=
- CELIB_DIR=${ac_cv_c_celibconfig}
- CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
- AC_MSG_RESULT([found $CELIB_DIR])
- fi
- fi
-])
-# Local Variables:
-# mode: autoconf
-# End:
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/makefile.vc b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/makefile.vc
deleted file mode 100644
index a5e46277072..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/makefile.vc
+++ /dev/null
@@ -1,414 +0,0 @@
-# makefile.vc -- -*- Makefile -*-
-#
-# Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+)
-#
-# This makefile is based upon the Tcl 8.4 Makefile.vc and modified to
-# make it suitable as a general package makefile. Look for the word EDIT
-# which marks sections that may need modification. As a minumum you will
-# need to change the PROJECT, DOTVERSION and DLLOBJS variables to values
-# relevant to your package.
-#
-# See the file "license.terms" for information on usage and redistribution
-# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-#
-# Copyright (c) 1995-1996 Sun Microsystems, Inc.
-# Copyright (c) 1998-2000 Ajuba Solutions.
-# Copyright (c) 2001 ActiveState Corporation.
-# Copyright (c) 2001-2002 David Gravereaux.
-# Copyright (c) 2003 Pat Thoyts
-#
-#-------------------------------------------------------------------------
-# RCS: @(#)$Id: makefile.vc,v 1.4 2004/07/26 08:22:05 patthoyts Exp $
-#-------------------------------------------------------------------------
-
-!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCINSTALLDIR) && !defined(MSSDK) && !defined(WINDOWSSDKDIR)
-MSG = ^
-You will need to run vcvars32.bat from Developer Studio, first, to setup^
-the environment. Jump to this line to read the new instructions.
-!error $(MSG)
-!endif
-
-#------------------------------------------------------------------------------
-# HOW TO USE this makefile:
-#
-# 1) It is now necessary to have %MSVCDir% set in the environment. This is
-# used as a check to see if vcvars32.bat had been run prior to running
-# nmake or during the installation of Microsoft Visual C++, MSVCDir had
-# been set globally and the PATH adjusted. Either way is valid.
-#
-# You'll need to run vcvars32.bat contained in the MsDev's vc(98)/bin
-# directory to setup the proper environment, if needed, for your current
-# setup. This is a needed bootstrap requirement and allows the swapping of
-# different environments to be easier.
-#
-# 2) To use the Platform SDK (not expressly needed), run setenv.bat after
-# vcvars32.bat according to the instructions for it. This can also turn on
-# the 64-bit compiler, if your SDK has it.
-#
-# 3) Targets are:
-# all -- Builds everything.
-# <project> -- Builds the project (eg: nmake sample)
-# test -- Builds and runs the test suite.
-# install -- Installs the built binaries and libraries to $(INSTALLDIR)
-# in an appropriate subdirectory.
-# clean/realclean/distclean -- varying levels of cleaning.
-#
-# 4) Macros usable on the commandline:
-# INSTALLDIR=<path>
-# Sets where to install Tcl from the built binaries.
-# C:\Progra~1\Tcl is assumed when not specified.
-#
-# OPTS=static,msvcrt,staticpkg,threads,symbols,profile,loimpact,none
-# Sets special options for the core. The default is for none.
-# Any combination of the above may be used (comma separated).
-# 'none' will over-ride everything to nothing.
-#
-# static = Builds a static library of the core instead of a
-# dll. The shell will be static (and large), as well.
-# msvcrt = Effects the static option only to switch it from
-# using libcmt(d) as the C runtime [by default] to
-# msvcrt(d). This is useful for static embedding
-# support.
-# staticpkg = Effects the static option only to switch
-# tclshXX.exe to have the dde and reg extension linked
-# inside it.
-# threads = Turns on full multithreading support.
-# thrdalloc = Use the thread allocator (shared global free pool).
-# symbols = Adds symbols for step debugging.
-# profile = Adds profiling hooks. Map file is assumed.
-# loimpact = Adds a flag for how NT treats the heap to keep memory
-# in use, low. This is said to impact alloc performance.
-#
-# STATS=memdbg,compdbg,none
-# Sets optional memory and bytecode compiler debugging code added
-# to the core. The default is for none. Any combination of the
-# above may be used (comma separated). 'none' will over-ride
-# everything to nothing.
-#
-# memdbg = Enables the debugging memory allocator.
-# compdbg = Enables byte compilation logging.
-#
-# MACHINE=(IX86|IA64|ALPHA)
-# Set the machine type used for the compiler, linker, and
-# resource compiler. This hook is needed to tell the tools
-# when alternate platforms are requested. IX86 is the default
-# when not specified.
-#
-# TMP_DIR=<path>
-# OUT_DIR=<path>
-# Hooks to allow the intermediate and output directories to be
-# changed. $(OUT_DIR) is assumed to be
-# $(BINROOT)\(Release|Debug) based on if symbols are requested.
-# $(TMP_DIR) will de $(OUT_DIR)\<buildtype> by default.
-#
-# TESTPAT=<file>
-# Reads the tests requested to be run from this file.
-#
-# CFG_ENCODING=encoding
-# name of encoding for configuration information. Defaults
-# to cp1252
-#
-# 5) Examples:
-#
-# Basic syntax of calling nmake looks like this:
-# nmake [-nologo] -f makefile.vc [target|macrodef [target|macrodef] [...]]
-#
-# Standard (no frills)
-# c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat
-# Setting environment for using Microsoft Visual C++ tools.
-# c:\tcl_src\win\>nmake -f makefile.vc all
-# c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl
-#
-# Building for Win64
-# c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat
-# Setting environment for using Microsoft Visual C++ tools.
-# c:\tcl_src\win\>c:\progra~1\platfo~1\setenv.bat /pre64 /RETAIL
-# Targeting Windows pre64 RETAIL
-# c:\tcl_src\win\>nmake -f makefile.vc MACHINE=IA64
-#
-#------------------------------------------------------------------------------
-#==============================================================================
-###############################################################################
-#------------------------------------------------------------------------------
-
-!if !exist("makefile.vc")
-MSG = ^
-You must run this makefile only from the directory it is in.^
-Please `cd` to its location first.
-!error $(MSG)
-!endif
-
-#-------------------------------------------------------------------------
-# Project specific information (EDIT)
-#
-# You should edit this with the name and version of your project. This
-# information is used to generate the name of the package library and
-# it's install location.
-#
-# For example, the sample extension is going to build sample04.dll and
-# would install it into $(INSTALLDIR)\lib\sample04
-#
-# You need to specify the object files that need to be linked into your
-# binary here.
-#
-#-------------------------------------------------------------------------
-
-PROJECT = sqlite3
-!include "rules.vc"
-
-# nmakehelp -V <file> <tag> will search the file for tag, skips until a
-# number and returns all character until a character not in [0-9.ab]
-# is read.
-
-!if [echo REM = This file is generated from Makefile.vc > versions.vc]
-!endif
-# get project version from row "AC_INIT([sqlite], [3.7.14])"
-!if [echo DOTVERSION = \>> versions.vc] \
- && [nmakehlp -V ..\configure.in AC_INIT >> versions.vc]
-!endif
-!include "versions.vc"
-
-VERSION = $(DOTVERSION:.=)
-STUBPREFIX = $(PROJECT)stub
-
-DLLOBJS = \
- $(TMP_DIR)\tclsqlite3.obj
-
-#-------------------------------------------------------------------------
-# Target names and paths ( shouldn't need changing )
-#-------------------------------------------------------------------------
-
-BINROOT = .
-ROOT = ..
-
-PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
-PRJLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT)
-PRJLIB = $(OUT_DIR)\$(PRJLIBNAME)
-
-PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib
-PRJSTUBLIB = $(OUT_DIR)\$(PRJSTUBLIBNAME)
-
-### Make sure we use backslash only.
-PRJ_INSTALL_DIR = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION)
-LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR)
-BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR)
-DOC_INSTALL_DIR = $(PRJ_INSTALL_DIR)
-SCRIPT_INSTALL_DIR = $(PRJ_INSTALL_DIR)
-INCLUDE_INSTALL_DIR = $(_TCLDIR)\include
-
-### The following paths CANNOT have spaces in them.
-GENERICDIR = $(ROOT)\generic
-WINDIR = $(ROOT)\win
-LIBDIR = $(ROOT)\library
-DOCDIR = $(ROOT)\doc
-TOOLSDIR = $(ROOT)\tools
-COMPATDIR = $(ROOT)\compat
-
-#---------------------------------------------------------------------
-# Compile flags
-#---------------------------------------------------------------------
-
-!if !$(DEBUG)
-!if $(OPTIMIZING)
-### This cranks the optimization level to maximize speed
-cdebug = -O2 -Op -Gs
-!else
-cdebug =
-!endif
-!else if "$(MACHINE)" == "IA64"
-### Warnings are too many, can't support warnings into errors.
-cdebug = -Z7 -Od -GZ
-!else
-cdebug = -Z7 -WX -Od -GZ
-!endif
-
-### Declarations common to all compiler options
-cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\
-
-!if $(MSVCRT)
-!if $(DEBUG)
-crt = -MDd
-!else
-crt = -MD
-!endif
-!else
-!if $(DEBUG)
-crt = -MTd
-!else
-crt = -MT
-!endif
-!endif
-
-INCLUDES = $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)" \
- -I"$(ROOT)\.."
-BASE_CLFAGS = $(cflags) $(cdebug) $(crt) $(INCLUDES) \
- -DSQLITE_3_SUFFIX_ONLY=1 -DSQLITE_ENABLE_RTREE=1 \
- -DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1
-CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE -DSQLITE_ENABLE_FTS3=1
-TCL_CFLAGS = -DBUILD_sqlite -DUSE_TCL_STUBS \
- -DPACKAGE_VERSION="\"$(DOTVERSION)\"" $(BASE_CLFAGS) \
- $(OPTDEFINES)
-
-#---------------------------------------------------------------------
-# Link flags
-#---------------------------------------------------------------------
-
-!if $(DEBUG)
-ldebug = -debug:full -debugtype:cv
-!else
-ldebug = -release -opt:ref -opt:icf,3
-!endif
-
-### Declarations common to all linker options
-lflags = -nologo -machine:$(MACHINE) $(ldebug)
-
-!if $(PROFILE)
-lflags = $(lflags) -profile
-!endif
-
-!if $(ALIGN98_HACK) && !$(STATIC_BUILD)
-### Align sections for PE size savings.
-lflags = $(lflags) -opt:nowin98
-!else if !$(ALIGN98_HACK) && $(STATIC_BUILD)
-### Align sections for speed in loading by choosing the virtual page size.
-lflags = $(lflags) -align:4096
-!endif
-
-!if $(LOIMPACT)
-lflags = $(lflags) -ws:aggressive
-!endif
-
-dlllflags = $(lflags) -dll
-conlflags = $(lflags) -subsystem:console
-guilflags = $(lflags) -subsystem:windows
-baselibs = $(TCLSTUBLIB)
-
-#---------------------------------------------------------------------
-# TclTest flags
-#---------------------------------------------------------------------
-
-!IF "$(TESTPAT)" != ""
-TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)
-!ENDIF
-
-#---------------------------------------------------------------------
-# Project specific targets (EDIT)
-#---------------------------------------------------------------------
-
-all: setup $(PROJECT)
-$(PROJECT): setup $(PRJLIB)
-install: install-binaries install-libraries install-docs
-
-# Tests need to ensure we load the right dll file we
-# have to handle the output differently on Win9x.
-#
-!if "$(OS)" == "Windows_NT" || "$(MSVCDIR)" == "IDE"
-test: setup $(PROJECT)
- set TCL_LIBRARY=$(ROOT)/library
- $(TCLSH) <<
-load $(PRJLIB:\=/)
-cd "$(ROOT)/tests"
-set argv "$(TESTFLAGS)"
-source all.tcl
-<<
-!else
-test: setup $(PROJECT)
- echo Please wait while the test results are collected
- set TCL_LIBRARY=$(ROOT)/library
- $(TCLSH) << >tests.log
-load $(PRJLIB:\=/)
-cd "$(ROOT)/tests"
-set argv "$(TESTFLAGS)"
-source all.tcl
-<<
- type tests.log | more
-!endif
-
-setup:
- @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)
- @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
-
-$(PRJLIB): $(DLLOBJS)
- $(link32) $(dlllflags) -out:$@ $(baselibs) @<<
-$**
-<<
- -@del $*.exp
-
-$(PRJSTUBLIB): $(PRJSTUBOBJS)
- $(lib32) -nologo -out:$@ $(PRJSTUBOBJS)
-
-#---------------------------------------------------------------------
-# Implicit rules
-#---------------------------------------------------------------------
-
-{$(WINDIR)}.c{$(TMP_DIR)}.obj::
- $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
-$<
-<<
-
-{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
- $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
-$<
-<<
-
-{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
- $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
-$<
-<<
-
-{$(WINDIR)}.rc{$(TMP_DIR)}.res:
- $(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \
-!if $(DEBUG)
- -d DEBUG \
-!endif
-!if $(TCL_THREADS)
- -d TCL_THREADS \
-!endif
-!if $(STATIC_BUILD)
- -d STATIC_BUILD \
-!endif
- $<
-
-.SUFFIXES:
-.SUFFIXES:.c .rc
-
-#---------------------------------------------------------------------
-# Installation. (EDIT)
-#
-# You may need to modify this section to reflect the final distribution
-# of your files and possibly to generate documentation.
-#
-#---------------------------------------------------------------------
-
-install-binaries:
- @echo Installing binaries to '$(SCRIPT_INSTALL_DIR)'
- @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
- @$(CPY) $(PRJLIB) "$(SCRIPT_INSTALL_DIR)" >NUL
-
-install-libraries:
- @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)'
- @if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)"
- @echo Installing package index in '$(SCRIPT_INSTALL_DIR)'
- @type << >"$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
-package ifneeded $(PROJECT) $(DOTVERSION) \
- [list load [file join $$dir $(PRJLIBNAME)] sqlite3]
-<<
-
-install-docs:
- @echo Installing documentation files to '$(DOC_INSTALL_DIR)'
- @if exist $(DOCDIR) $(CPY) $(DOCDIR)\*.n "$(DOC_INSTALL_DIR)"
-
-#---------------------------------------------------------------------
-# Clean up
-#---------------------------------------------------------------------
-
-clean:
- @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
- @if exist $(WINDIR)\version.vc del $(WINDIR)\version.vc
-
-realclean: clean
- @if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR)
-
-distclean: realclean
- @if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe
- @if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/nmakehlp.c b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/nmakehlp.c
deleted file mode 100644
index e00f1b49965..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/nmakehlp.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * ----------------------------------------------------------------------------
- * nmakehlp.c --
- *
- * This is used to fix limitations within nmake and the environment.
- *
- * Copyright (c) 2002 by David Gravereaux.
- * Copyright (c) 2006 by Pat Thoyts
- *
- * See the file "license.terms" for information on usage and redistribution of
- * this file, and for a DISCLAIMER OF ALL WARRANTIES.
- * ----------------------------------------------------------------------------
- */
-
-#define _CRT_SECURE_NO_DEPRECATE
-#include <windows.h>
-#define NO_SHLWAPI_GDI
-#define NO_SHLWAPI_STREAM
-#define NO_SHLWAPI_REG
-#include <shlwapi.h>
-#pragma comment (lib, "user32.lib")
-#pragma comment (lib, "kernel32.lib")
-#pragma comment (lib, "shlwapi.lib")
-#include <stdio.h>
-#include <math.h>
-
-/*
- * This library is required for x64 builds with _some_ versions of MSVC
- */
-#if defined(_M_IA64) || defined(_M_AMD64)
-#if _MSC_VER >= 1400 && _MSC_VER < 1500
-#pragma comment(lib, "bufferoverflowU")
-#endif
-#endif
-
-/* ISO hack for dumb VC++ */
-#ifdef _MSC_VER
-#define snprintf _snprintf
-#endif
-
-
-
-/* protos */
-
-static int CheckForCompilerFeature(const char *option);
-static int CheckForLinkerFeature(const char *option);
-static int IsIn(const char *string, const char *substring);
-static int SubstituteFile(const char *substs, const char *filename);
-static int QualifyPath(const char *path);
-static const char *GetVersionFromFile(const char *filename, const char *match);
-static DWORD WINAPI ReadFromPipe(LPVOID args);
-
-/* globals */
-
-#define CHUNK 25
-#define STATICBUFFERSIZE 1000
-typedef struct {
- HANDLE pipe;
- char buffer[STATICBUFFERSIZE];
-} pipeinfo;
-
-pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
-pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
-
-/*
- * exitcodes: 0 == no, 1 == yes, 2 == error
- */
-
-int
-main(
- int argc,
- char *argv[])
-{
- char msg[300];
- DWORD dwWritten;
- int chars;
-
- /*
- * Make sure children (cl.exe and link.exe) are kept quiet.
- */
-
- SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
-
- /*
- * Make sure the compiler and linker aren't effected by the outside world.
- */
-
- SetEnvironmentVariable("CL", "");
- SetEnvironmentVariable("LINK", "");
-
- if (argc > 1 && *argv[1] == '-') {
- switch (*(argv[1]+1)) {
- case 'c':
- if (argc != 3) {
- chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -c <compiler option>\n"
- "Tests for whether cl.exe supports an option\n"
- "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
- &dwWritten, NULL);
- return 2;
- }
- return CheckForCompilerFeature(argv[2]);
- case 'l':
- if (argc != 3) {
- chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -l <linker option>\n"
- "Tests for whether link.exe supports an option\n"
- "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
- &dwWritten, NULL);
- return 2;
- }
- return CheckForLinkerFeature(argv[2]);
- case 'f':
- if (argc == 2) {
- chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -f <string> <substring>\n"
- "Find a substring within another\n"
- "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
- &dwWritten, NULL);
- return 2;
- } else if (argc == 3) {
- /*
- * If the string is blank, there is no match.
- */
-
- return 0;
- } else {
- return IsIn(argv[2], argv[3]);
- }
- case 's':
- if (argc == 2) {
- chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -s <substitutions file> <file>\n"
- "Perform a set of string map type substutitions on a file\n"
- "exitcodes: 0\n",
- argv[0]);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
- &dwWritten, NULL);
- return 2;
- }
- return SubstituteFile(argv[2], argv[3]);
- case 'V':
- if (argc != 4) {
- chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -V filename matchstring\n"
- "Extract a version from a file:\n"
- "eg: pkgIndex.tcl \"package ifneeded http\"",
- argv[0]);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
- &dwWritten, NULL);
- return 0;
- }
- printf("%s\n", GetVersionFromFile(argv[2], argv[3]));
- return 0;
- case 'Q':
- if (argc != 3) {
- chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -Q path\n"
- "Emit the fully qualified path\n"
- "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
- &dwWritten, NULL);
- return 2;
- }
- return QualifyPath(argv[2]);
- }
- }
- chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -c|-f|-l|-Q|-s|-V ...\n"
- "This is a little helper app to equalize shell differences between WinNT and\n"
- "Win9x and get nmake.exe to accomplish its job.\n",
- argv[0]);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
- return 2;
-}
-
-static int
-CheckForCompilerFeature(
- const char *option)
-{
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- SECURITY_ATTRIBUTES sa;
- DWORD threadID;
- char msg[300];
- BOOL ok;
- HANDLE hProcess, h, pipeThreads[2];
- char cmdline[100];
-
- hProcess = GetCurrentProcess();
-
- ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
- ZeroMemory(&si, sizeof(STARTUPINFO));
- si.cb = sizeof(STARTUPINFO);
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = INVALID_HANDLE_VALUE;
-
- ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.lpSecurityDescriptor = NULL;
- sa.bInheritHandle = FALSE;
-
- /*
- * Create a non-inheritible pipe.
- */
-
- CreatePipe(&Out.pipe, &h, &sa, 0);
-
- /*
- * Dupe the write side, make it inheritible, and close the original.
- */
-
- DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
-
- /*
- * Same as above, but for the error side.
- */
-
- CreatePipe(&Err.pipe, &h, &sa, 0);
- DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
-
- /*
- * Base command line.
- */
-
- lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch ");
-
- /*
- * Append our option for testing
- */
-
- lstrcat(cmdline, option);
-
- /*
- * Filename to compile, which exists, but is nothing and empty.
- */
-
- lstrcat(cmdline, " .\\nul");
-
- ok = CreateProcess(
- NULL, /* Module name. */
- cmdline, /* Command line. */
- NULL, /* Process handle not inheritable. */
- NULL, /* Thread handle not inheritable. */
- TRUE, /* yes, inherit handles. */
- DETACHED_PROCESS, /* No console for you. */
- NULL, /* Use parent's environment block. */
- NULL, /* Use parent's starting directory. */
- &si, /* Pointer to STARTUPINFO structure. */
- &pi); /* Pointer to PROCESS_INFORMATION structure. */
-
- if (!ok) {
- DWORD err = GetLastError();
- int chars = snprintf(msg, sizeof(msg) - 1,
- "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
-
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
- FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
- (300-chars), 0);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
- return 2;
- }
-
- /*
- * Close our references to the write handles that have now been inherited.
- */
-
- CloseHandle(si.hStdOutput);
- CloseHandle(si.hStdError);
-
- WaitForInputIdle(pi.hProcess, 5000);
- CloseHandle(pi.hThread);
-
- /*
- * Start the pipe reader threads.
- */
-
- pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
- pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
-
- /*
- * Block waiting for the process to end.
- */
-
- WaitForSingleObject(pi.hProcess, INFINITE);
- CloseHandle(pi.hProcess);
-
- /*
- * Wait for our pipe to get done reading, should it be a little slow.
- */
-
- WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
- CloseHandle(pipeThreads[0]);
- CloseHandle(pipeThreads[1]);
-
- /*
- * Look for the commandline warning code in both streams.
- * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
- */
-
- return !(strstr(Out.buffer, "D4002") != NULL
- || strstr(Err.buffer, "D4002") != NULL
- || strstr(Out.buffer, "D9002") != NULL
- || strstr(Err.buffer, "D9002") != NULL
- || strstr(Out.buffer, "D2021") != NULL
- || strstr(Err.buffer, "D2021") != NULL);
-}
-
-static int
-CheckForLinkerFeature(
- const char *option)
-{
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- SECURITY_ATTRIBUTES sa;
- DWORD threadID;
- char msg[300];
- BOOL ok;
- HANDLE hProcess, h, pipeThreads[2];
- char cmdline[100];
-
- hProcess = GetCurrentProcess();
-
- ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
- ZeroMemory(&si, sizeof(STARTUPINFO));
- si.cb = sizeof(STARTUPINFO);
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = INVALID_HANDLE_VALUE;
-
- ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.lpSecurityDescriptor = NULL;
- sa.bInheritHandle = TRUE;
-
- /*
- * Create a non-inheritible pipe.
- */
-
- CreatePipe(&Out.pipe, &h, &sa, 0);
-
- /*
- * Dupe the write side, make it inheritible, and close the original.
- */
-
- DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
-
- /*
- * Same as above, but for the error side.
- */
-
- CreatePipe(&Err.pipe, &h, &sa, 0);
- DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
-
- /*
- * Base command line.
- */
-
- lstrcpy(cmdline, "link.exe -nologo ");
-
- /*
- * Append our option for testing.
- */
-
- lstrcat(cmdline, option);
-
- ok = CreateProcess(
- NULL, /* Module name. */
- cmdline, /* Command line. */
- NULL, /* Process handle not inheritable. */
- NULL, /* Thread handle not inheritable. */
- TRUE, /* yes, inherit handles. */
- DETACHED_PROCESS, /* No console for you. */
- NULL, /* Use parent's environment block. */
- NULL, /* Use parent's starting directory. */
- &si, /* Pointer to STARTUPINFO structure. */
- &pi); /* Pointer to PROCESS_INFORMATION structure. */
-
- if (!ok) {
- DWORD err = GetLastError();
- int chars = snprintf(msg, sizeof(msg) - 1,
- "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
-
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
- FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
- (300-chars), 0);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
- return 2;
- }
-
- /*
- * Close our references to the write handles that have now been inherited.
- */
-
- CloseHandle(si.hStdOutput);
- CloseHandle(si.hStdError);
-
- WaitForInputIdle(pi.hProcess, 5000);
- CloseHandle(pi.hThread);
-
- /*
- * Start the pipe reader threads.
- */
-
- pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
- pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
-
- /*
- * Block waiting for the process to end.
- */
-
- WaitForSingleObject(pi.hProcess, INFINITE);
- CloseHandle(pi.hProcess);
-
- /*
- * Wait for our pipe to get done reading, should it be a little slow.
- */
-
- WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
- CloseHandle(pipeThreads[0]);
- CloseHandle(pipeThreads[1]);
-
- /*
- * Look for the commandline warning code in the stderr stream.
- */
-
- return !(strstr(Out.buffer, "LNK1117") != NULL ||
- strstr(Err.buffer, "LNK1117") != NULL ||
- strstr(Out.buffer, "LNK4044") != NULL ||
- strstr(Err.buffer, "LNK4044") != NULL);
-}
-
-static DWORD WINAPI
-ReadFromPipe(
- LPVOID args)
-{
- pipeinfo *pi = (pipeinfo *) args;
- char *lastBuf = pi->buffer;
- DWORD dwRead;
- BOOL ok;
-
- again:
- if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
- CloseHandle(pi->pipe);
- return (DWORD)-1;
- }
- ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
- if (!ok || dwRead == 0) {
- CloseHandle(pi->pipe);
- return 0;
- }
- lastBuf += dwRead;
- goto again;
-
- return 0; /* makes the compiler happy */
-}
-
-static int
-IsIn(
- const char *string,
- const char *substring)
-{
- return (strstr(string, substring) != NULL);
-}
-
-/*
- * GetVersionFromFile --
- * Looks for a match string in a file and then returns the version
- * following the match where a version is anything acceptable to
- * package provide or package ifneeded.
- */
-
-static const char *
-GetVersionFromFile(
- const char *filename,
- const char *match)
-{
- size_t cbBuffer = 100;
- static char szBuffer[100];
- char *szResult = NULL;
- FILE *fp = fopen(filename, "rt");
-
- if (fp != NULL) {
- /*
- * Read data until we see our match string.
- */
-
- while (fgets(szBuffer, cbBuffer, fp) != NULL) {
- LPSTR p, q;
-
- p = strstr(szBuffer, match);
- if (p != NULL) {
- /*
- * Skip to first digit.
- */
-
- while (*p && !isdigit(*p)) {
- ++p;
- }
-
- /*
- * Find ending whitespace.
- */
-
- q = p;
- while (*q && (isalnum(*q) || *q == '.')) {
- ++q;
- }
-
- memcpy(szBuffer, p, q - p);
- szBuffer[q-p] = 0;
- szResult = szBuffer;
- break;
- }
- }
- fclose(fp);
- }
- return szResult;
-}
-
-/*
- * List helpers for the SubstituteFile function
- */
-
-typedef struct list_item_t {
- struct list_item_t *nextPtr;
- char * key;
- char * value;
-} list_item_t;
-
-/* insert a list item into the list (list may be null) */
-static list_item_t *
-list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
-{
- list_item_t *itemPtr = malloc(sizeof(list_item_t));
- if (itemPtr) {
- itemPtr->key = strdup(key);
- itemPtr->value = strdup(value);
- itemPtr->nextPtr = NULL;
-
- while(*listPtrPtr) {
- listPtrPtr = &(*listPtrPtr)->nextPtr;
- }
- *listPtrPtr = itemPtr;
- }
- return itemPtr;
-}
-
-static void
-list_free(list_item_t **listPtrPtr)
-{
- list_item_t *tmpPtr, *listPtr = *listPtrPtr;
- while (listPtr) {
- tmpPtr = listPtr;
- listPtr = listPtr->nextPtr;
- free(tmpPtr->key);
- free(tmpPtr->value);
- free(tmpPtr);
- }
-}
-
-/*
- * SubstituteFile --
- * As windows doesn't provide anything useful like sed and it's unreliable
- * to use the tclsh you are building against (consider x-platform builds -
- * eg compiling AMD64 target from IX86) we provide a simple substitution
- * option here to handle autoconf style substitutions.
- * The substitution file is whitespace and line delimited. The file should
- * consist of lines matching the regular expression:
- * \s*\S+\s+\S*$
- *
- * Usage is something like:
- * nmakehlp -S << $** > $@
- * @PACKAGE_NAME@ $(PACKAGE_NAME)
- * @PACKAGE_VERSION@ $(PACKAGE_VERSION)
- * <<
- */
-
-static int
-SubstituteFile(
- const char *substitutions,
- const char *filename)
-{
- size_t cbBuffer = 1024;
- static char szBuffer[1024], szCopy[1024];
- char *szResult = NULL;
- list_item_t *substPtr = NULL;
- FILE *fp, *sp;
-
- fp = fopen(filename, "rt");
- if (fp != NULL) {
-
- /*
- * Build a list of substutitions from the first filename
- */
-
- sp = fopen(substitutions, "rt");
- if (sp != NULL) {
- while (fgets(szBuffer, cbBuffer, sp) != NULL) {
- unsigned char *ks, *ke, *vs, *ve;
- ks = (unsigned char*)szBuffer;
- while (ks && *ks && isspace(*ks)) ++ks;
- ke = ks;
- while (ke && *ke && !isspace(*ke)) ++ke;
- vs = ke;
- while (vs && *vs && isspace(*vs)) ++vs;
- ve = vs;
- while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
- *ke = 0, *ve = 0;
- list_insert(&substPtr, (char*)ks, (char*)vs);
- }
- fclose(sp);
- }
-
- /* debug: dump the list */
-#ifdef _DEBUG
- {
- int n = 0;
- list_item_t *p = NULL;
- for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
- fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
- }
- }
-#endif
-
- /*
- * Run the substitutions over each line of the input
- */
-
- while (fgets(szBuffer, cbBuffer, fp) != NULL) {
- list_item_t *p = NULL;
- for (p = substPtr; p != NULL; p = p->nextPtr) {
- char *m = strstr(szBuffer, p->key);
- if (m) {
- char *cp, *op, *sp;
- cp = szCopy;
- op = szBuffer;
- while (op != m) *cp++ = *op++;
- sp = p->value;
- while (sp && *sp) *cp++ = *sp++;
- op += strlen(p->key);
- while (*op) *cp++ = *op++;
- *cp = 0;
- memcpy(szBuffer, szCopy, sizeof(szCopy));
- }
- }
- printf(szBuffer);
- }
-
- list_free(&substPtr);
- }
- fclose(fp);
- return 0;
-}
-
-/*
- * QualifyPath --
- *
- * This composes the current working directory with a provided path
- * and returns the fully qualified and normalized path.
- * Mostly needed to setup paths for testing.
- */
-
-static int
-QualifyPath(
- const char *szPath)
-{
- char szCwd[MAX_PATH + 1];
- char szTmp[MAX_PATH + 1];
- char *p;
- GetCurrentDirectory(MAX_PATH, szCwd);
- while ((p = strchr(szPath, '/')) && *p)
- *p = '\\';
- PathCombine(szTmp, szCwd, szPath);
- PathCanonicalize(szCwd, szTmp);
- printf("%s\n", szCwd);
- return 0;
-}
-
-/*
- * Local variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * indent-tabs-mode: t
- * tab-width: 8
- * End:
- */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/rules.vc b/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/rules.vc
deleted file mode 100644
index 99471053c8c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/autoconf/tea/win/rules.vc
+++ /dev/null
@@ -1,711 +0,0 @@
-#------------------------------------------------------------------------------
-# rules.vc --
-#
-# Microsoft Visual C++ makefile include for decoding the commandline
-# macros. This file does not need editing to build Tcl.
-#
-# See the file "license.terms" for information on usage and redistribution
-# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-#
-# Copyright (c) 2001-2003 David Gravereaux.
-# Copyright (c) 2003-2008 Patrick Thoyts
-#------------------------------------------------------------------------------
-
-!ifndef _RULES_VC
-_RULES_VC = 1
-
-cc32 = $(CC) # built-in default.
-link32 = link
-lib32 = lib
-rc32 = $(RC) # built-in default.
-
-!ifndef INSTALLDIR
-### Assume the normal default.
-_INSTALLDIR = C:\Program Files\Tcl
-!else
-### Fix the path separators.
-_INSTALLDIR = $(INSTALLDIR:/=\)
-!endif
-
-#----------------------------------------------------------
-# Set the proper copy method to avoid overwrite questions
-# to the user when copying files and selecting the right
-# "delete all" method.
-#----------------------------------------------------------
-
-!if "$(OS)" == "Windows_NT"
-RMDIR = rmdir /S /Q
-ERRNULL = 2>NUL
-!if ![ver | find "4.0" > nul]
-CPY = echo y | xcopy /i >NUL
-COPY = copy >NUL
-!else
-CPY = xcopy /i /y >NUL
-COPY = copy /y >NUL
-!endif
-!else # "$(OS)" != "Windows_NT"
-CPY = xcopy /i >_JUNK.OUT # On Win98 NUL does not work here.
-COPY = copy >_JUNK.OUT # On Win98 NUL does not work here.
-RMDIR = deltree /Y
-NULL = \NUL # Used in testing directory existence
-ERRNULL = >NUL # Win9x shell cannot redirect stderr
-!endif
-MKDIR = mkdir
-
-#------------------------------------------------------------------------------
-# Determine the host and target architectures and compiler version.
-#------------------------------------------------------------------------------
-
-_HASH=^#
-_VC_MANIFEST_EMBED_EXE=
-_VC_MANIFEST_EMBED_DLL=
-VCVER=0
-!if ![echo VCVERSION=_MSC_VER > vercl.x] \
- && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \
- && ![echo ARCH=IX86 >> vercl.x] \
- && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \
- && ![echo ARCH=AMD64 >> vercl.x] \
- && ![echo $(_HASH)endif >> vercl.x] \
- && ![cl -nologo -TC -P vercl.x $(ERRNULL)]
-!include vercl.i
-!if ![echo VCVER= ^\> vercl.vc] \
- && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc]
-!include vercl.vc
-!endif
-!endif
-!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc]
-!endif
-
-!if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86]
-NATIVE_ARCH=IX86
-!else
-NATIVE_ARCH=AMD64
-!endif
-
-# Since MSVC8 we must deal with manifest resources.
-!if $(VCVERSION) >= 1400
-_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
-_VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
-!endif
-
-!ifndef MACHINE
-MACHINE=$(ARCH)
-!endif
-
-!ifndef CFG_ENCODING
-CFG_ENCODING = \"cp1252\"
-!endif
-
-!message ===============================================================================
-
-#----------------------------------------------------------
-# build the helper app we need to overcome nmake's limiting
-# environment.
-#----------------------------------------------------------
-
-!if !exist(nmakehlp.exe)
-!if [$(cc32) -nologo nmakehlp.c -link -subsystem:console > nul]
-!endif
-!endif
-
-#----------------------------------------------------------
-# Test for compiler features
-#----------------------------------------------------------
-
-### test for optimizations
-!if [nmakehlp -c -Ot]
-!message *** Compiler has 'Optimizations'
-OPTIMIZING = 1
-!else
-!message *** Compiler does not have 'Optimizations'
-OPTIMIZING = 0
-!endif
-
-OPTIMIZATIONS =
-
-!if [nmakehlp -c -Ot]
-OPTIMIZATIONS = $(OPTIMIZATIONS) -Ot
-!endif
-
-!if [nmakehlp -c -Oi]
-OPTIMIZATIONS = $(OPTIMIZATIONS) -Oi
-!endif
-
-!if [nmakehlp -c -Op]
-OPTIMIZATIONS = $(OPTIMIZATIONS) -Op
-!endif
-
-!if [nmakehlp -c -fp:strict]
-OPTIMIZATIONS = $(OPTIMIZATIONS) -fp:strict
-!endif
-
-!if [nmakehlp -c -Gs]
-OPTIMIZATIONS = $(OPTIMIZATIONS) -Gs
-!endif
-
-!if [nmakehlp -c -GS]
-OPTIMIZATIONS = $(OPTIMIZATIONS) -GS
-!endif
-
-!if [nmakehlp -c -GL]
-OPTIMIZATIONS = $(OPTIMIZATIONS) -GL
-!endif
-
-DEBUGFLAGS =
-
-!if [nmakehlp -c -RTC1]
-DEBUGFLAGS = $(DEBUGFLAGS) -RTC1
-!elseif [nmakehlp -c -GZ]
-DEBUGFLAGS = $(DEBUGFLAGS) -GZ
-!endif
-
-COMPILERFLAGS =-W3 -DUNICODE -D_UNICODE
-
-# In v13 -GL and -YX are incompatible.
-!if [nmakehlp -c -YX]
-!if ![nmakehlp -c -GL]
-OPTIMIZATIONS = $(OPTIMIZATIONS) -YX
-!endif
-!endif
-
-!if "$(MACHINE)" == "IX86"
-### test for pentium errata
-!if [nmakehlp -c -QI0f]
-!message *** Compiler has 'Pentium 0x0f fix'
-COMPILERFLAGS = $(COMPILERFLAGS) -QI0f
-!else
-!message *** Compiler does not have 'Pentium 0x0f fix'
-!endif
-!endif
-
-!if "$(MACHINE)" == "IA64"
-### test for Itanium errata
-!if [nmakehlp -c -QIA64_Bx]
-!message *** Compiler has 'B-stepping errata workarounds'
-COMPILERFLAGS = $(COMPILERFLAGS) -QIA64_Bx
-!else
-!message *** Compiler does not have 'B-stepping errata workarounds'
-!endif
-!endif
-
-!if "$(MACHINE)" == "IX86"
-### test for -align:4096, when align:512 will do.
-!if [nmakehlp -l -opt:nowin98]
-!message *** Linker has 'Win98 alignment problem'
-ALIGN98_HACK = 1
-!else
-!message *** Linker does not have 'Win98 alignment problem'
-ALIGN98_HACK = 0
-!endif
-!else
-ALIGN98_HACK = 0
-!endif
-
-LINKERFLAGS =
-
-!if [nmakehlp -l -ltcg]
-LINKERFLAGS =-ltcg
-!endif
-
-#----------------------------------------------------------
-# Decode the options requested.
-#----------------------------------------------------------
-
-!if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"]
-STATIC_BUILD = 0
-TCL_THREADS = 1
-DEBUG = 0
-SYMBOLS = 0
-PROFILE = 0
-PGO = 0
-MSVCRT = 0
-LOIMPACT = 0
-TCL_USE_STATIC_PACKAGES = 0
-USE_THREAD_ALLOC = 1
-UNCHECKED = 0
-!else
-!if [nmakehlp -f $(OPTS) "static"]
-!message *** Doing static
-STATIC_BUILD = 1
-!else
-STATIC_BUILD = 0
-!endif
-!if [nmakehlp -f $(OPTS) "msvcrt"]
-!message *** Doing msvcrt
-MSVCRT = 1
-!else
-MSVCRT = 0
-!endif
-!if [nmakehlp -f $(OPTS) "staticpkg"]
-!message *** Doing staticpkg
-TCL_USE_STATIC_PACKAGES = 1
-!else
-TCL_USE_STATIC_PACKAGES = 0
-!endif
-!if [nmakehlp -f $(OPTS) "nothreads"]
-!message *** Compile explicitly for non-threaded tcl
-TCL_THREADS = 0
-!else
-TCL_THREADS = 1
-USE_THREAD_ALLOC= 1
-!endif
-!if [nmakehlp -f $(OPTS) "symbols"]
-!message *** Doing symbols
-DEBUG = 1
-!else
-DEBUG = 0
-!endif
-!if [nmakehlp -f $(OPTS) "pdbs"]
-!message *** Doing pdbs
-SYMBOLS = 1
-!else
-SYMBOLS = 0
-!endif
-!if [nmakehlp -f $(OPTS) "profile"]
-!message *** Doing profile
-PROFILE = 1
-!else
-PROFILE = 0
-!endif
-!if [nmakehlp -f $(OPTS) "pgi"]
-!message *** Doing profile guided optimization instrumentation
-PGO = 1
-!elseif [nmakehlp -f $(OPTS) "pgo"]
-!message *** Doing profile guided optimization
-PGO = 2
-!else
-PGO = 0
-!endif
-!if [nmakehlp -f $(OPTS) "loimpact"]
-!message *** Doing loimpact
-LOIMPACT = 1
-!else
-LOIMPACT = 0
-!endif
-!if [nmakehlp -f $(OPTS) "thrdalloc"]
-!message *** Doing thrdalloc
-USE_THREAD_ALLOC = 1
-!endif
-!if [nmakehlp -f $(OPTS) "tclalloc"]
-!message *** Doing tclalloc
-USE_THREAD_ALLOC = 0
-!endif
-!if [nmakehlp -f $(OPTS) "unchecked"]
-!message *** Doing unchecked
-UNCHECKED = 1
-!else
-UNCHECKED = 0
-!endif
-!endif
-
-
-!if !$(STATIC_BUILD)
-# Make sure we don't build overly fat DLLs.
-MSVCRT = 1
-# We shouldn't statically put the extensions inside the shell when dynamic.
-TCL_USE_STATIC_PACKAGES = 0
-!endif
-
-
-#----------------------------------------------------------
-# Figure-out how to name our intermediate and output directories.
-# We wouldn't want different builds to use the same .obj files
-# by accident.
-#----------------------------------------------------------
-
-#----------------------------------------
-# Naming convention:
-# t = full thread support.
-# s = static library (as opposed to an
-# import library)
-# g = linked to the debug enabled C
-# run-time.
-# x = special static build when it
-# links to the dynamic C run-time.
-#----------------------------------------
-SUFX = tsgx
-
-!if $(DEBUG)
-BUILDDIRTOP = Debug
-!else
-BUILDDIRTOP = Release
-!endif
-
-!if "$(MACHINE)" != "IX86"
-BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE)
-!endif
-!if $(VCVER) > 6
-BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER)
-!endif
-
-!if !$(DEBUG) || $(DEBUG) && $(UNCHECKED)
-SUFX = $(SUFX:g=)
-!endif
-
-TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX
-
-!if !$(STATIC_BUILD)
-TMP_DIRFULL = $(TMP_DIRFULL:Static=)
-SUFX = $(SUFX:s=)
-EXT = dll
-!if $(MSVCRT)
-TMP_DIRFULL = $(TMP_DIRFULL:X=)
-SUFX = $(SUFX:x=)
-!endif
-!else
-TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)
-EXT = lib
-!if !$(MSVCRT)
-TMP_DIRFULL = $(TMP_DIRFULL:X=)
-SUFX = $(SUFX:x=)
-!endif
-!endif
-
-!if !$(TCL_THREADS)
-TMP_DIRFULL = $(TMP_DIRFULL:Threaded=)
-SUFX = $(SUFX:t=)
-!endif
-
-!ifndef TMP_DIR
-TMP_DIR = $(TMP_DIRFULL)
-!ifndef OUT_DIR
-OUT_DIR = .\$(BUILDDIRTOP)
-!endif
-!else
-!ifndef OUT_DIR
-OUT_DIR = $(TMP_DIR)
-!endif
-!endif
-
-
-#----------------------------------------------------------
-# Decode the statistics requested.
-#----------------------------------------------------------
-
-!if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"]
-TCL_MEM_DEBUG = 0
-TCL_COMPILE_DEBUG = 0
-!else
-!if [nmakehlp -f $(STATS) "memdbg"]
-!message *** Doing memdbg
-TCL_MEM_DEBUG = 1
-!else
-TCL_MEM_DEBUG = 0
-!endif
-!if [nmakehlp -f $(STATS) "compdbg"]
-!message *** Doing compdbg
-TCL_COMPILE_DEBUG = 1
-!else
-TCL_COMPILE_DEBUG = 0
-!endif
-!endif
-
-
-#----------------------------------------------------------
-# Decode the checks requested.
-#----------------------------------------------------------
-
-!if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"]
-TCL_NO_DEPRECATED = 0
-WARNINGS = -W3
-!else
-!if [nmakehlp -f $(CHECKS) "nodep"]
-!message *** Doing nodep check
-TCL_NO_DEPRECATED = 1
-!else
-TCL_NO_DEPRECATED = 0
-!endif
-!if [nmakehlp -f $(CHECKS) "fullwarn"]
-!message *** Doing full warnings check
-WARNINGS = -W4
-!if [nmakehlp -l -warn:3]
-LINKERFLAGS = $(LINKERFLAGS) -warn:3
-!endif
-!else
-WARNINGS = -W3
-!endif
-!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64]
-!message *** Doing 64bit portability warnings
-WARNINGS = $(WARNINGS) -Wp64
-!endif
-!endif
-
-!if $(PGO) > 1
-!if [nmakehlp -l -ltcg:pgoptimize]
-LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize
-!else
-MSG=^
-This compiler does not support profile guided optimization.
-!error $(MSG)
-!endif
-!elseif $(PGO) > 0
-!if [nmakehlp -l -ltcg:pginstrument]
-LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument
-!else
-MSG=^
-This compiler does not support profile guided optimization.
-!error $(MSG)
-!endif
-!endif
-
-#----------------------------------------------------------
-# Set our defines now armed with our options.
-#----------------------------------------------------------
-
-OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS
-
-!if $(TCL_MEM_DEBUG)
-OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG
-!endif
-!if $(TCL_COMPILE_DEBUG)
-OPTDEFINES = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
-!endif
-!if $(TCL_THREADS)
-OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1
-!if $(USE_THREAD_ALLOC)
-OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1
-!endif
-!endif
-!if $(STATIC_BUILD)
-OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD
-!endif
-!if $(TCL_NO_DEPRECATED)
-OPTDEFINES = $(OPTDEFINES) -DTCL_NO_DEPRECATED
-!endif
-
-!if !$(DEBUG)
-OPTDEFINES = $(OPTDEFINES) -DNDEBUG
-!if $(OPTIMIZING)
-OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED
-!endif
-!endif
-!if $(PROFILE)
-OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_PROFILED
-!endif
-!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
-OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DO64BIT
-!endif
-!if $(VCVERSION) < 1300
-OPTDEFINES = $(OPTDEFINES) -DNO_STRTOI64
-!endif
-
-#----------------------------------------------------------
-# Locate the Tcl headers to build against
-#----------------------------------------------------------
-
-!if "$(PROJECT)" == "tcl"
-
-_TCL_H = ..\generic\tcl.h
-
-!else
-
-# If INSTALLDIR set to tcl root dir then reset to the lib dir.
-!if exist("$(_INSTALLDIR)\include\tcl.h")
-_INSTALLDIR=$(_INSTALLDIR)\lib
-!endif
-
-!if !defined(TCLDIR)
-!if exist("$(_INSTALLDIR)\..\include\tcl.h")
-TCLINSTALL = 1
-_TCLDIR = $(_INSTALLDIR)\..
-_TCL_H = $(_INSTALLDIR)\..\include\tcl.h
-TCLDIR = $(_INSTALLDIR)\..
-!else
-MSG=^
-Failed to find tcl.h. Set the TCLDIR macro.
-!error $(MSG)
-!endif
-!else
-_TCLDIR = $(TCLDIR:/=\)
-!if exist("$(_TCLDIR)\include\tcl.h")
-TCLINSTALL = 1
-_TCL_H = $(_TCLDIR)\include\tcl.h
-!elseif exist("$(_TCLDIR)\generic\tcl.h")
-TCLINSTALL = 0
-_TCL_H = $(_TCLDIR)\generic\tcl.h
-!else
-MSG =^
-Failed to find tcl.h. The TCLDIR macro does not appear correct.
-!error $(MSG)
-!endif
-!endif
-!endif
-
-#--------------------------------------------------------------
-# Extract various version numbers from tcl headers
-# The generated file is then included in the makefile.
-#--------------------------------------------------------------
-
-!if [echo REM = This file is generated from rules.vc > versions.vc]
-!endif
-!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \
- && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc]
-!endif
-!if [echo TCL_MINOR_VERSION = \>> versions.vc] \
- && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc]
-!endif
-!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \
- && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc]
-!endif
-
-# If building the tcl core then we need additional package versions
-!if "$(PROJECT)" == "tcl"
-!if [echo PKG_HTTP_VER = \>> versions.vc] \
- && [nmakehlp -V ..\library\http\pkgIndex.tcl http >> versions.vc]
-!endif
-!if [echo PKG_TCLTEST_VER = \>> versions.vc] \
- && [nmakehlp -V ..\library\tcltest\pkgIndex.tcl tcltest >> versions.vc]
-!endif
-!if [echo PKG_MSGCAT_VER = \>> versions.vc] \
- && [nmakehlp -V ..\library\msgcat\pkgIndex.tcl msgcat >> versions.vc]
-!endif
-!if [echo PKG_PLATFORM_VER = \>> versions.vc] \
- && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform " >> versions.vc]
-!endif
-!if [echo PKG_SHELL_VER = \>> versions.vc] \
- && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform::shell" >> versions.vc]
-!endif
-!if [echo PKG_DDE_VER = \>> versions.vc] \
- && [nmakehlp -V ..\library\dde\pkgIndex.tcl "dde " >> versions.vc]
-!endif
-!if [echo PKG_REG_VER =\>> versions.vc] \
- && [nmakehlp -V ..\library\reg\pkgIndex.tcl registry >> versions.vc]
-!endif
-!endif
-
-!include versions.vc
-
-#--------------------------------------------------------------
-# Setup tcl version dependent stuff headers
-#--------------------------------------------------------------
-
-!if "$(PROJECT)" != "tcl"
-
-TCL_VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
-
-!if $(TCL_VERSION) < 81
-TCL_DOES_STUBS = 0
-!else
-TCL_DOES_STUBS = 1
-!endif
-
-!if $(TCLINSTALL)
-TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe"
-!if !exist($(TCLSH)) && $(TCL_THREADS)
-TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe"
-!endif
-TCLSTUBLIB = "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib"
-TCLIMPLIB = "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
-TCL_LIBRARY = $(_TCLDIR)\lib
-TCLREGLIB = "$(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib"
-TCLDDELIB = "$(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib"
-COFFBASE = \must\have\tcl\sources\to\build\this\target
-TCLTOOLSDIR = \must\have\tcl\sources\to\build\this\target
-TCL_INCLUDES = -I"$(_TCLDIR)\include"
-!else
-TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
-!if !exist($(TCLSH)) && $(TCL_THREADS)
-TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe"
-!endif
-TCLSTUBLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib"
-TCLIMPLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
-TCL_LIBRARY = $(_TCLDIR)\library
-TCLREGLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib"
-TCLDDELIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib"
-COFFBASE = "$(_TCLDIR)\win\coffbase.txt"
-TCLTOOLSDIR = $(_TCLDIR)\tools
-TCL_INCLUDES = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
-!endif
-
-!endif
-
-#-------------------------------------------------------------------------
-# Locate the Tk headers to build against
-#-------------------------------------------------------------------------
-
-!if "$(PROJECT)" == "tk"
-_TK_H = ..\generic\tk.h
-_INSTALLDIR = $(_INSTALLDIR)\..
-!endif
-
-!ifdef PROJECT_REQUIRES_TK
-!if !defined(TKDIR)
-!if exist("$(_INSTALLDIR)\..\include\tk.h")
-TKINSTALL = 1
-_TKDIR = $(_INSTALLDIR)\..
-_TK_H = $(_TKDIR)\include\tk.h
-TKDIR = $(_TKDIR)
-!elseif exist("$(_TCLDIR)\include\tk.h")
-TKINSTALL = 1
-_TKDIR = $(_TCLDIR)
-_TK_H = $(_TKDIR)\include\tk.h
-TKDIR = $(_TKDIR)
-!endif
-!else
-_TKDIR = $(TKDIR:/=\)
-!if exist("$(_TKDIR)\include\tk.h")
-TKINSTALL = 1
-_TK_H = $(_TKDIR)\include\tk.h
-!elseif exist("$(_TKDIR)\generic\tk.h")
-TKINSTALL = 0
-_TK_H = $(_TKDIR)\generic\tk.h
-!else
-MSG =^
-Failed to find tk.h. The TKDIR macro does not appear correct.
-!error $(MSG)
-!endif
-!endif
-!endif
-
-#-------------------------------------------------------------------------
-# Extract Tk version numbers
-#-------------------------------------------------------------------------
-
-!if defined(PROJECT_REQUIRES_TK) || "$(PROJECT)" == "tk"
-
-!if [echo TK_MAJOR_VERSION = \>> versions.vc] \
- && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc]
-!endif
-!if [echo TK_MINOR_VERSION = \>> versions.vc] \
- && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]
-!endif
-!if [echo TK_PATCH_LEVEL = \>> versions.vc] \
- && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]
-!endif
-
-!include versions.vc
-
-TK_DOTVERSION = $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
-TK_VERSION = $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)
-
-!if "$(PROJECT)" != "tk"
-!if $(TKINSTALL)
-WISH = "$(_TKDIR)\bin\wish$(TK_VERSION)$(SUFX).exe"
-TKSTUBLIB = "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib"
-TKIMPLIB = "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib"
-TK_INCLUDES = -I"$(_TKDIR)\include"
-!else
-WISH = "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(SUFX).exe"
-TKSTUBLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib"
-TKIMPLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib"
-TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
-!endif
-!endif
-
-!endif
-
-#----------------------------------------------------------
-# Display stats being used.
-#----------------------------------------------------------
-
-!message *** Intermediate directory will be '$(TMP_DIR)'
-!message *** Output directory will be '$(OUT_DIR)'
-!message *** Suffix for binaries will be '$(SUFX)'
-!message *** Optional defines are '$(OPTDEFINES)'
-!message *** Compiler version $(VCVER). Target machine is $(MACHINE)
-!message *** Host architecture is $(NATIVE_ARCH)
-!message *** Compiler options '$(COMPILERFLAGS) $(OPTIMIZATIONS) $(DEBUGFLAGS) $(WARNINGS)'
-!message *** Link options '$(LINKERFLAGS)'
-
-!endif
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/config.guess b/chromium/third_party/sqlite/sqlite-src-3240000/config.guess
deleted file mode 100644
index 34093cc6bb5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/config.guess
+++ /dev/null
@@ -1,1535 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-# Inc.
-
-timestamp='2007-07-22'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner <per@bothner.com>.
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
-#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit build system type.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
- --version | -v )
- echo "$version" ; exit ;;
- --help | --h* | -h )
- echo "$usage"; exit ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help" >&2
- exit 1 ;;
- * )
- break ;;
- esac
-done
-
-if test $# != 0; then
- echo "$me: too many arguments$help" >&2
- exit 1
-fi
-
-trap 'exit 1' 1 2 15
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
- PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-if [ "${UNAME_SYSTEM}" = "Linux" ] ; then
- eval $set_cc_for_build
- cat << EOF > $dummy.c
- #include <features.h>
- #ifdef __UCLIBC__
- # ifdef __UCLIBC_CONFIG_VERSION__
- LIBC=uclibc __UCLIBC_CONFIG_VERSION__
- # else
- LIBC=uclibc
- # endif
- #else
- LIBC=gnu
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep LIBC= | sed -e 's: ::g'`
-fi
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- *:NetBSD:*:*)
- # NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
- # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
- # switched to ELF, *-*-netbsd* would select the old
- # object file format. This provides both forward
- # compatibility and a consistent mechanism for selecting the
- # object file format.
- #
- # Note: NetBSD doesn't particularly care about the vendor
- # portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
- armeb) machine=armeb-unknown ;;
- arm*) machine=arm-unknown ;;
- sh3el) machine=shl-unknown ;;
- sh3eb) machine=sh-unknown ;;
- sh5el) machine=sh5le-unknown ;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
- esac
- # The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
- case "${UNAME_MACHINE_ARCH}" in
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep __ELF__ >/dev/null
- then
- # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
- # Return netbsd for either. FIX?
- os=netbsd
- else
- os=netbsdelf
- fi
- ;;
- *)
- os=netbsd
- ;;
- esac
- # The OS release
- # Debian GNU/NetBSD machines have a different userland, and
- # thus, need a distinct triplet. However, they do not need
- # kernel version information, so it can be replaced with a
- # suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
- Debian*)
- release='-gnu'
- ;;
- *)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
- ;;
- esac
- # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
- # contains redundant information, the shorter form:
- # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
- exit ;;
- *:OpenBSD:*:*)
- UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
- exit ;;
- *:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
- exit ;;
- *:SolidBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
- exit ;;
- macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- *:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- alpha:OSF1:*:*)
- case $UNAME_RELEASE in
- *4.0)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- ;;
- *5.*)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
- ;;
- esac
- # According to Compaq, /usr/sbin/psrinfo has been available on
- # OSF/1 and Tru64 systems produced since 1995. I hope that
- # covers most systems running today. This code pipes the CPU
- # types through head -n 1, so we only detect the type of CPU 0.
- ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
- case "$ALPHA_CPU_TYPE" in
- "EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
- "EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
- "LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
- "EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
- "EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
- "EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
- "EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
- "EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
- "EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
- "EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
- "EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
- "EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
- esac
- # A Pn.n version is a patched version.
- # A Vn.n version is a released version.
- # A Tn.n version is a released field test version.
- # A Xn.n version is an unreleased experimental baselevel.
- # 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit ;;
- Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit ;;
- *:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
- exit ;;
- *:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
- exit ;;
- *:OS/390:*:*)
- echo i370-ibm-openedition
- exit ;;
- *:z/VM:*:*)
- echo s390-ibm-zvmoe
- exit ;;
- *:OS400:*:*)
- echo powerpc-ibm-os400
- exit ;;
- arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
- exit ;;
- arm:riscos:*:*|arm:RISCOS:*:*)
- echo arm-unknown-riscos
- exit ;;
- SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit ;;
- Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
- # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "`(/bin/universe) 2>/dev/null`" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit ;;
- NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit ;;
- DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit ;;
- DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
- case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7; exit ;;
- esac ;;
- sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:6*:*)
- # According to config.sub, this is the proper way to canonicalize
- # SunOS6. Hard to guess exactly what SunOS6 will be like, but
- # it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:*:*)
- case "`/usr/bin/arch -k`" in
- Series*|S4*)
- UNAME_RELEASE=`uname -v`
- ;;
- esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit ;;
- sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
- exit ;;
- sun*:*:4.2BSD:*)
- UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
- case "`/bin/arch`" in
- sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
- ;;
- sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
- ;;
- esac
- exit ;;
- aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
- exit ;;
- # The situation for MiNT is a little confusing. The machine name
- # can be virtually everything (everything which is not
- # "atarist" or "atariste" at least should have a processor
- # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
- # to the lowercase version "mint" (or "freemint"). Finally
- # the system name "TOS" denotes a system which is actually not
- # MiNT. But MiNT is downward compatible to TOS, so this should
- # be no problem.
- atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
- hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
- *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
- m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
- exit ;;
- powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
- exit ;;
- RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit ;;
- RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
- exit ;;
- VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
- exit ;;
- 2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
- exit ;;
- mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-#ifdef __cplusplus
-#include <stdio.h> /* for printf() prototype */
- int main (int argc, char *argv[]) {
-#else
- int main (argc, argv) int argc; char *argv[]; {
-#endif
- #if defined (host_mips) && defined (MIPSEB)
- #if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
- #endif
- #endif
- exit (-1);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
- { echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos${UNAME_RELEASE}
- exit ;;
- Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit ;;
- Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit ;;
- Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit ;;
- Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit ;;
- m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit ;;
- m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit ;;
- m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit ;;
- AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
- then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
- then
- echo m88k-dg-dgux${UNAME_RELEASE}
- else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
- fi
- else
- echo i586-dg-dgux${UNAME_RELEASE}
- fi
- exit ;;
- M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit ;;
- M88*:*:R3*:*)
- # Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit ;;
- XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit ;;
- Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit ;;
- *:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit ;;
- ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
- i*86:AIX:*:*)
- echo i386-ibm-aix
- exit ;;
- ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit ;;
- *:AIX:2:3)
- if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <sys/systemcfg.h>
-
- main()
- {
- if (!__power_pc())
- exit(1);
- puts("powerpc-ibm-aix3.2.5");
- exit(0);
- }
-EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
- then
- echo "$SYSTEM_NAME"
- else
- echo rs6000-ibm-aix3.2.5
- fi
- elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
- else
- echo rs6000-ibm-aix3.2
- fi
- exit ;;
- *:AIX:*:[45])
- IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
- IBM_ARCH=rs6000
- else
- IBM_ARCH=powerpc
- fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit ;;
- *:AIX:*:*)
- echo rs6000-ibm-aix
- exit ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
- echo romp-ibm-bsd4.4
- exit ;;
- ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit ;; # report: romp-ibm BSD 4.3
- *:BOSX:*:*)
- echo rs6000-bull-bosx
- exit ;;
- DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit ;;
- 9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit ;;
- hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit ;;
- 9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
- sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
- fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-
- #define _HPUX_SOURCE
- #include <stdlib.h>
- #include <unistd.h>
-
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
-
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
-EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
- test -z "$HP_ARCH" && HP_ARCH=hppa
- fi ;;
- esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
- then
- eval $set_cc_for_build
-
- # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
- # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
- # generating 64-bit code. GNU and HP use different nomenclature:
- #
- # $ CC_FOR_BUILD=cc ./config.guess
- # => hppa2.0w-hp-hpux11.23
- # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
- # => hppa64-hp-hpux11.23
-
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
- grep __LP64__ >/dev/null
- then
- HP_ARCH="hppa2.0w"
- else
- HP_ARCH="hppa64"
- fi
- fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit ;;
- ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
- exit ;;
- 3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <unistd.h>
- int
- main ()
- {
- long cpu = sysconf (_SC_CPU_VERSION);
- /* The order matters, because CPU_IS_HP_MC68K erroneously returns
- true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
- results, however. */
- if (CPU_IS_PA_RISC (cpu))
- {
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
- default: puts ("hppa-hitachi-hiuxwe2"); break;
- }
- }
- else if (CPU_IS_HP_MC68K (cpu))
- puts ("m68k-hitachi-hiuxwe2");
- else puts ("unknown-hitachi-hiuxwe2");
- exit (0);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
- echo unknown-hitachi-hiuxwe2
- exit ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
- echo hppa1.1-hp-bsd
- exit ;;
- 9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit ;;
- *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
- echo hppa1.1-hp-osf
- exit ;;
- hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit ;;
- i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
- else
- echo ${UNAME_MACHINE}-unknown-osf1
- fi
- exit ;;
- parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit ;;
- C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit ;;
- C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit ;;
- C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit ;;
- C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit ;;
- CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
- | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
- -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
- -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- *:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- 5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit ;;
- sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:FreeBSD:*:*)
- case ${UNAME_MACHINE} in
- pc98)
- echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- esac
- exit ;;
- i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
- exit ;;
- *:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
- exit ;;
- i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
- exit ;;
- *:Interix*:[3456]*)
- case ${UNAME_MACHINE} in
- x86)
- echo i586-pc-interix${UNAME_RELEASE}
- exit ;;
- EM64T | authenticamd)
- echo x86_64-unknown-interix${UNAME_RELEASE}
- exit ;;
- esac ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit ;;
- i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
- exit ;;
- amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
- exit ;;
- prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- *:GNU:*:*)
- # the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit ;;
- *:GNU/*:*:*)
- # other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
- exit ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
- exit ;;
- arm*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- cris:Linux:*:*)
- echo cris-axis-linux-${LIBC}
- exit ;;
- crisv32:Linux:*:*)
- echo crisv32-axis-linux-${LIBC}
- exit ;;
- frv:Linux:*:*)
- echo frv-unknown-linux-${LIBC}
- exit ;;
- ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- mips:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips
- #undef mipsel
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mipsel
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips
- #else
- CPU=
- #endif
- #endif
-EOF
- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
- /^CPU/{
- s: ::g
- p
- }'`"
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
- ;;
- mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips64
- #undef mips64el
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mips64el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips64
- #else
- CPU=
- #endif
- #endif
-EOF
- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
- /^CPU/{
- s: ::g
- p
- }'`"
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
- ;;
- or32:Linux:*:*)
- echo or32-unknown-linux-${LIBC}
- exit ;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-${LIBC}
- exit ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-${LIBC}
- exit ;;
- alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- EV5) UNAME_MACHINE=alphaev5 ;;
- EV56) UNAME_MACHINE=alphaev56 ;;
- PCA56) UNAME_MACHINE=alphapca56 ;;
- PCA57) UNAME_MACHINE=alphapca56 ;;
- EV6) UNAME_MACHINE=alphaev6 ;;
- EV67) UNAME_MACHINE=alphaev67 ;;
- EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
- objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
- if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- parisc:Linux:*:* | hppa:Linux:*:*)
- # Look for CPU level
- case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
- PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
- *) echo hppa-unknown-linux-${LIBC} ;;
- esac
- exit ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-${LIBC}
- exit ;;
- s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
- exit ;;
- sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-${LIBC}
- exit ;;
- x86_64:Linux:*:*)
- echo x86_64-unknown-linux-${LIBC}
- exit ;;
- xtensa:Linux:*:*)
- echo xtensa-unknown-linux-${LIBC}
- exit ;;
- i*86:Linux:*:*)
- # The BFD linker knows what the default object file format is, so
- # first see if it will tell us. cd to the root directory to prevent
- # problems with other programs or directories called `ld' in the path.
- # Set LC_ALL=C to ensure ld outputs messages in English.
- ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
- | sed -ne '/supported targets:/!d
- s/[ ][ ]*/ /g
- s/.*supported targets: *//
- s/ .*//
- p'`
- case "$ld_supported_targets" in
- elf32-i386)
- TENTATIVE="${UNAME_MACHINE}-pc-linux-${LIBC}"
- ;;
- a.out-i386-linux)
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}aout"
- exit ;;
- coff-i386)
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}coff"
- exit ;;
- "")
- # Either a pre-BFD a.out linker (linux-gnuoldld) or
- # one that does not give us useful --help.
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}oldld"
- exit ;;
- esac
- # This should get integrated into the C code below, but now we hack
- if [ "$LIBC" != "gnu" ] ; then echo "$TENTATIVE" && exit 0 ; fi
- # Determine whether the default compiler is a.out or elf
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <features.h>
- #ifdef __ELF__
- # ifdef __GLIBC__
- # if __GLIBC__ >= 2
- LIBC=gnu
- # else
- LIBC=gnulibc1
- # endif
- # else
- LIBC=gnulibc1
- # endif
- #else
- #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
- LIBC=gnu
- #else
- LIBC=gnuaout
- #endif
- #endif
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
- /^LIBC/{
- s: ::g
- p
- }'`"
- test x"${LIBC}" != x && {
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
- exit
- }
- test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
- ;;
- i*86:DYNIX/ptx:4*:*)
- # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
- # earlier versions are messed up and put the nodename in both
- # sysname and nodename.
- echo i386-sequent-sysv4
- exit ;;
- i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
- # I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit ;;
- i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
- # is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
- exit ;;
- i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
- exit ;;
- i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
- exit ;;
- i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
- exit ;;
- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
- if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
- else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
- fi
- exit ;;
- i*86:*:5:[678]*)
- # UnixWare 7.x, OpenUNIX and OpenServer 6.
- case `/bin/uname -X | grep "^Machine"` in
- *486*) UNAME_MACHINE=i486 ;;
- *Pentium) UNAME_MACHINE=i586 ;;
- *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
- esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit ;;
- i*86:*:3.2:*)
- if test -f /usr/options/cb.name; then
- UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
- elif /bin/uname -X 2>/dev/null >/dev/null ; then
- UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
- (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
- (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
- && UNAME_MACHINE=i586
- (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
- && UNAME_MACHINE=i686
- (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
- && UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
- else
- echo ${UNAME_MACHINE}-pc-sysv32
- fi
- exit ;;
- pc:*:*:*)
- # Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i386.
- echo i386-pc-msdosdjgpp
- exit ;;
- Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit ;;
- paragon:*:*:*)
- echo i860-intel-osf1
- exit ;;
- i860:*:4.*:*) # i860-SVR4
- if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
- else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
- fi
- exit ;;
- mini*:CTIX:SYS*5:*)
- # "miniframe"
- echo m68010-convergent-sysv
- exit ;;
- mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit ;;
- M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit ;;
- M68*:*:R3V[5678]*:*)
- test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
- 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
- OS_REL=''
- test -r /etc/.relid \
- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
- 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4; exit; } ;;
- m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit ;;
- TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
- exit ;;
- RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
- RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
- *:SINIX-*:*:*)
- if uname -p 2>/dev/null >/dev/null ; then
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
- else
- echo ns32k-sni-sysv
- fi
- exit ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
- *:UNIX_System_V:4*:FTX*)
- # From Gerald Hewes <hewes@openmarket.com>.
- # How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
- *:*:*:FTX*)
- # From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
- i*86:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
- exit ;;
- *:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit ;;
- mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
- exit ;;
- news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit ;;
- R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
- else
- echo mips-unknown-sysv${UNAME_RELEASE}
- fi
- exit ;;
- BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit ;;
- BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit ;;
- BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit ;;
- SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux${UNAME_RELEASE}
- exit ;;
- Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit ;;
- *:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit ;;
- *:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- case $UNAME_PROCESSOR in
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit ;;
- *:procnto*:*:* | *:QNX:[0123456789]*:*)
- UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
- UNAME_PROCESSOR=i386
- UNAME_MACHINE=pc
- fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit ;;
- *:QNX:*:4*)
- echo i386-pc-qnx
- exit ;;
- NSE-?:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
- exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
- exit ;;
- *:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit ;;
- BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit ;;
- DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit ;;
- *:Plan9:*:*)
- # "uname -m" is not consistent, so use $cputype instead. 386
- # is converted to i386 for consistency with other x86
- # operating systems.
- if test "$cputype" = "386"; then
- UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
- fi
- echo ${UNAME_MACHINE}-unknown-plan9
- exit ;;
- *:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit ;;
- *:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit ;;
- KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit ;;
- XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit ;;
- *:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit ;;
- *:ITS:*:*)
- echo pdp10-unknown-its
- exit ;;
- SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit ;;
- *:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
- *:*VMS:*:*)
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
- A*) echo alpha-dec-vms ; exit ;;
- I*) echo ia64-dec-vms ; exit ;;
- V*) echo vax-dec-vms ; exit ;;
- esac ;;
- *:XENIX:*:SysV)
- echo i386-pc-xenix
- exit ;;
- i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
- exit ;;
- i*86:rdos:*:*)
- echo ${UNAME_MACHINE}-pc-rdos
- exit ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
- I don't know.... */
- printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
- printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
- "4"
-#else
- ""
-#endif
- ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
- int version;
- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- if (version < 4)
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
- else
- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
- exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
- printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
- printf ("ns32k-encore-mach\n"); exit (0);
-#else
- printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
- printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
- printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
- printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-# include <sys/param.h>
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
- printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
- exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- c34*)
- echo c34-convex-bsd
- exit ;;
- c38*)
- echo c38-convex-bsd
- exit ;;
- c4*)
- echo c4-convex-bsd
- exit ;;
- esac
-fi
-
-cat >&2 <<EOF
-$0: unable to guess system type
-
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
-
- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
-and
- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
-
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
-
-hostinfo = `(hostinfo) 2>/dev/null`
-/bin/universe = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
-EOF
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/config.h.in b/chromium/third_party/sqlite/sqlite-src-3240000/config.h.in
deleted file mode 100644
index f2ba7d4fc4c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/config.h.in
+++ /dev/null
@@ -1,131 +0,0 @@
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you have the `fdatasync' function. */
-#undef HAVE_FDATASYNC
-
-/* Define to 1 if you have the `gmtime_r' function. */
-#undef HAVE_GMTIME_R
-
-/* Define to 1 if the system has the type `int16_t'. */
-#undef HAVE_INT16_T
-
-/* Define to 1 if the system has the type `int32_t'. */
-#undef HAVE_INT32_T
-
-/* Define to 1 if the system has the type `int64_t'. */
-#undef HAVE_INT64_T
-
-/* Define to 1 if the system has the type `int8_t'. */
-#undef HAVE_INT8_T
-
-/* Define to 1 if the system has the type `intptr_t'. */
-#undef HAVE_INTPTR_T
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the `isnan' function. */
-#undef HAVE_ISNAN
-
-/* Define to 1 if you have the `localtime_r' function. */
-#undef HAVE_LOCALTIME_R
-
-/* Define to 1 if you have the `localtime_s' function. */
-#undef HAVE_LOCALTIME_S
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
-
-/* Define to 1 if you have the `malloc_usable_size' function. */
-#undef HAVE_MALLOC_USABLE_SIZE
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the pread() function. */
-#undef HAVE_PREAD
-
-/* Define to 1 if you have the pread64() function. */
-#undef HAVE_PREAD64
-
-/* Define to 1 if you have the pwrite() function. */
-#undef HAVE_PWRITE
-
-/* Define to 1 if you have the pwrite64() function. */
-#undef HAVE_PWRITE64
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the strchrnul() function */
-#undef HAVE_STRCHRNUL
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if the system has the type `uint16_t'. */
-#undef HAVE_UINT16_T
-
-/* Define to 1 if the system has the type `uint32_t'. */
-#undef HAVE_UINT32_T
-
-/* Define to 1 if the system has the type `uint64_t'. */
-#undef HAVE_UINT64_T
-
-/* Define to 1 if the system has the type `uint8_t'. */
-#undef HAVE_UINT8_T
-
-/* Define to 1 if the system has the type `uintptr_t'. */
-#undef HAVE_UINTPTR_T
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the `usleep' function. */
-#undef HAVE_USLEEP
-
-/* Define to 1 if you have the utime() library function. */
-#undef HAVE_UTIME
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#undef LT_OBJDIR
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
-/* Define for large files, on AIX-style hosts. */
-#undef _LARGE_FILES
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/config.sub b/chromium/third_party/sqlite/sqlite-src-3240000/config.sub
deleted file mode 100644
index 63cdd0a35d5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/config.sub
+++ /dev/null
@@ -1,1644 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-# Inc.
-
-timestamp='2007-06-28'
-
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
-#
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support. The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
-
-Canonicalize a configuration name.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
- --version | -v )
- echo "$version" ; exit ;;
- --help | --h* | -h )
- echo "$usage"; exit ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help"
- exit 1 ;;
-
- *local*)
- # First pass through any local machine types.
- echo $1
- exit ;;
-
- * )
- break ;;
- esac
-done
-
-case $# in
- 0) echo "$me: missing argument$help" >&2
- exit 1;;
- 1) ;;
- *) echo "$me: too many arguments$help" >&2
- exit 1;;
-esac
-
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
- uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
- storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
-
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray)
- os=
- basic_machine=$1
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco6)
- os=-sco5v6
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*)
- os=-lynxos
- ;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
- ;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
- ;;
- -psos*)
- os=-psos
- ;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
-esac
-
-# Decode aliases for certain CPU-COMPANY combinations.
-case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
- | bfin \
- | c4x | clipper \
- | d10v | d30v | dlx | dsp16xx | dvp \
- | fido | fr30 | frv \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | i370 | i860 | i960 | ia64 \
- | ip2k | iq2000 \
- | m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | mcore | mep \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64el \
- | mips64vr | mips64vrel \
- | mips64orion | mips64orionel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipstx39 | mipstx39el \
- | mn10200 | mn10300 \
- | mt \
- | msp430 \
- | nios | nios2 \
- | ns16k | ns32k \
- | or32 \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
- | pyramid \
- | score \
- | sh | sh[1234] | sh[24]a | sh[24]a*eb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
- | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu | strongarm \
- | tahoe | thumb | tic4x | tic80 | tron \
- | v850 | v850e \
- | we32k \
- | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
- | z8k)
- basic_machine=$basic_machine-unknown
- ;;
- m6811 | m68hc11 | m6812 | m68hc12)
- # Motorola 68HC11/12.
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
- ;;
- ms1)
- basic_machine=mt-unknown
- ;;
-
- # We use `pc' rather than `unknown'
- # because (1) that's what they normally are, and
- # (2) the word "unknown" tends to confuse beginning users.
- i*86 | x86_64)
- basic_machine=$basic_machine-pc
- ;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* | avr32-* \
- | bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
- | clipper-* | craynv-* | cydra-* \
- | d10v-* | d30v-* | dlx-* \
- | elxsi-* \
- | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* | iq2000-* \
- | m32c-* | m32r-* | m32rle-* \
- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* \
- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- | mips16-* \
- | mips64-* | mips64el-* \
- | mips64vr-* | mips64vrel-* \
- | mips64orion-* | mips64orionel-* \
- | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* \
- | mips64vr5000-* | mips64vr5000el-* \
- | mips64vr5900-* | mips64vr5900el-* \
- | mipsisa32-* | mipsisa32el-* \
- | mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa64-* | mipsisa64el-* \
- | mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64sb1-* | mipsisa64sb1el-* \
- | mipsisa64sr71k-* | mipsisa64sr71kel-* \
- | mipstx39-* | mipstx39el-* \
- | mmix-* \
- | mt-* \
- | msp430-* \
- | nios-* | nios2-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
- | pyramid-* \
- | romp-* | rs6000-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[24]a*eb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
- | sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
- | tron-* \
- | v850-* | v850e-* | vax-* \
- | we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
- | xstormy16-* | xtensa-* \
- | ymp-* \
- | z8k-*)
- ;;
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
- ;;
- 3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- abacus)
- basic_machine=abacus-unknown
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amd64)
- basic_machine=x86_64-pc
- ;;
- amd64-*)
- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- c90)
- basic_machine=c90-cray
- os=-unicos
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
- ;;
- cr16)
- basic_machine=cr16-unknown
- os=-elf
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- crisv32 | crisv32-* | etraxfs*)
- basic_machine=crisv32-axis
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- crx)
- basic_machine=crx-unknown
- os=-elf
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
- ;;
- decsystem10* | dec10*)
- basic_machine=pdp10-dec
- os=-tops10
- ;;
- decsystem20* | dec20*)
- basic_machine=pdp10-dec
- os=-tops20
- ;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
- ;;
- encore | umax | mmax)
- basic_machine=ns32k-encore
- ;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
- ;;
- fx2800)
- basic_machine=i860-alliant
- ;;
- genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
- ;;
- h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
- ;;
- hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
- ;;
- hp9k3[2-9][0-9])
- basic_machine=m68k-hp
- ;;
- hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
- ;;
- hp9k78[0-9] | hp78[0-9])
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
- ;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
- i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
- ;;
- i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
- ;;
- i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
- ;;
- i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
- ;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
- ;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
- ;;
- iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- -irix*)
- ;;
- *)
- os=-irix4
- ;;
- esac
- ;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- mingw32)
- basic_machine=i386-pc
- os=-mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- os=-mingw32ce
- ;;
- miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mipsEE* | ee | ps2)
- basic_machine=mips64r5900el-scei
- case $os in
- -linux*)
- ;;
- *)
- os=-elf
- ;;
- esac
- ;;
- iop)
- basic_machine=mipsel-scei
- os=-irx
- ;;
- dvp)
- basic_machine=dvp-scei
- os=-elf
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
- ;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- ms1-*)
- basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
- ;;
- news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
- ;;
- next | m*-next )
- basic_machine=m68k-next
- case $os in
- -nextstep* )
- ;;
- -ns2*)
- os=-nextstep2
- ;;
- *)
- os=-nextstep3
- ;;
- esac
- ;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
- np1)
- basic_machine=np1-gould
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
- ;;
- op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- openrisc | openrisc-*)
- basic_machine=or32-unknown
- ;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
- ;;
- pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- pbd)
- basic_machine=sparc-tti
- ;;
- pbb)
- basic_machine=m68k-tti
- ;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
- ;;
- pc98)
- basic_machine=i386-pc
- ;;
- pc98-*)
- basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium | p5 | k5 | k6 | nexgen | viac3)
- basic_machine=i586-pc
- ;;
- pentiumpro | p6 | 6x86 | athlon | athlon_*)
- basic_machine=i686-pc
- ;;
- pentiumii | pentium2 | pentiumiii | pentium3)
- basic_machine=i686-pc
- ;;
- pentium4)
- basic_machine=i786-pc
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium4-*)
- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pn)
- basic_machine=pn-gould
- ;;
- power) basic_machine=power-ibm
- ;;
- ppc) basic_machine=powerpc-unknown
- ;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppcle | powerpclittle | ppc-le | powerpc-little)
- basic_machine=powerpcle-unknown
- ;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little | ppc64-le | powerpc64-little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rdos)
- basic_machine=i386-pc
- os=-rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- rm[46]00)
- basic_machine=mips-siemens
- ;;
- rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- s390 | s390-*)
- basic_machine=s390-ibm
- ;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
- ;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
- ;;
- sb1)
- basic_machine=mipsisa64sb1-unknown
- ;;
- sb1el)
- basic_machine=mipsisa64sb1el-unknown
- ;;
- sde)
- basic_machine=mipsisa32-sde
- os=-elf
- ;;
- sei)
- basic_machine=mips-sei
- os=-seiux
- ;;
- sequent)
- basic_machine=i386-sequent
- ;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
- ;;
- sh5el)
- basic_machine=sh5le-unknown
- ;;
- sh64)
- basic_machine=sh64-unknown
- ;;
- sparclite-wrs | simso-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
- ;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
- ;;
- spur)
- basic_machine=spur-unknown
- ;;
- st2000)
- basic_machine=m68k-tandem
- ;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
- ;;
- sun2)
- basic_machine=m68000-sun
- ;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
- ;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
- ;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
- ;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
- ;;
- sun4)
- basic_machine=sparc-sun
- ;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
- ;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
- ;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
- ;;
- t90)
- basic_machine=t90-cray
- os=-unicos
- ;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tic55x | c55x*)
- basic_machine=tic55x-unknown
- os=-coff
- ;;
- tic6x | c6x*)
- basic_machine=tic6x-unknown
- os=-coff
- ;;
- tx39)
- basic_machine=mipstx39-unknown
- ;;
- tx39el)
- basic_machine=mipstx39el-unknown
- ;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
- ;;
- tower | tower-32)
- basic_machine=m68k-ncr
- ;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
- ;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
- ;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
- ;;
- vms)
- basic_machine=vax-dec
- os=-vms
- ;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
- ;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
- ;;
- w65*)
- basic_machine=w65-wdc
- os=-none
- ;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
- ;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
- ;;
- xps | xps100)
- basic_machine=xps100-honeywell
- ;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
- ;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
- ;;
- none)
- basic_machine=none-none
- os=-none
- ;;
-
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
- ;;
- op50n)
- basic_machine=hppa1.1-oki
- ;;
- op60c)
- basic_machine=hppa1.1-oki
- ;;
- romp)
- basic_machine=romp-ibm
- ;;
- mmix)
- basic_machine=mmix-knuth
- ;;
- rs6000)
- basic_machine=rs6000-ibm
- ;;
- vax)
- basic_machine=vax-dec
- ;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
- ;;
- pdp11)
- basic_machine=pdp11-dec
- ;;
- we32k)
- basic_machine=we32k-att
- ;;
- sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
- basic_machine=sh-unknown
- ;;
- sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
- basic_machine=sparc-sun
- ;;
- cydra)
- basic_machine=cydra-cydrome
- ;;
- orion)
- basic_machine=orion-highlevel
- ;;
- orion105)
- basic_machine=clipper-highlevel
- ;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
- ;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
- ;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
- ;;
- *)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
- ;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
- ;;
- *)
- ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if [ x"$os" != x"" ]
-then
-case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
- ;;
- -solaris)
- os=-solaris2
- ;;
- -svr4*)
- os=-sysv4
- ;;
- -unixware*)
- os=-sysv4.2uw
- ;;
- -gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
- ;;
- # First accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST END IN A *, to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -openbsd* | -solidbsd* \
- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* \
- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
- | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -irx*)
- # Remember, each alternative MUST END IN *, to match a version number.
- ;;
- -qnx*)
- case $basic_machine in
- x86-* | i*86-*)
- ;;
- *)
- os=-nto$os
- ;;
- esac
- ;;
- -nto-qnx*)
- ;;
- -nto*)
- os=`echo $os | sed -e 's|nto|nto-qnx|'`
- ;;
- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
- ;;
- -mac*)
- os=`echo $os | sed -e 's|mac|macos|'`
- ;;
- -linux-dietlibc)
- os=-linux-dietlibc
- ;;
- -linux*)
- os=`echo $os | sed -e 's|linux|linux-gnu|'`
- ;;
- -sunos5*)
- os=`echo $os | sed -e 's|sunos5|solaris2|'`
- ;;
- -sunos6*)
- os=`echo $os | sed -e 's|sunos6|solaris3|'`
- ;;
- -opened*)
- os=-openedition
- ;;
- -os400*)
- os=-os400
- ;;
- -wince*)
- os=-wince
- ;;
- -osfrose*)
- os=-osfrose
- ;;
- -osf*)
- os=-osf
- ;;
- -utek*)
- os=-bsd
- ;;
- -dynix*)
- os=-bsd
- ;;
- -acis*)
- os=-aos
- ;;
- -atheos*)
- os=-atheos
- ;;
- -syllable*)
- os=-syllable
- ;;
- -386bsd)
- os=-bsd
- ;;
- -ctix* | -uts*)
- os=-sysv
- ;;
- -nova*)
- os=-rtmk-nova
- ;;
- -ns2 )
- os=-nextstep2
- ;;
- -nsk*)
- os=-nsk
- ;;
- # Preserve the version number of sinix5.
- -sinix5.*)
- os=`echo $os | sed -e 's|sinix|sysv|'`
- ;;
- -sinix*)
- os=-sysv4
- ;;
- -tpf*)
- os=-tpf
- ;;
- -triton*)
- os=-sysv3
- ;;
- -oss*)
- os=-sysv3
- ;;
- -svr4)
- os=-sysv4
- ;;
- -svr3)
- os=-sysv3
- ;;
- -sysvr4)
- os=-sysv4
- ;;
- # This must come after -sysvr4.
- -sysv*)
- ;;
- -ose*)
- os=-ose
- ;;
- -es1800*)
- os=-ose
- ;;
- -xenix)
- os=-xenix
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
- ;;
- -aros*)
- os=-aros
- ;;
- -kaos*)
- os=-kaos
- ;;
- -zvmoe)
- os=-zvmoe
- ;;
- -none)
- ;;
- *)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
- exit 1
- ;;
-esac
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system. Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-case $basic_machine in
- score-*)
- os=-elf
- ;;
- spu-*)
- os=-elf
- ;;
- *-acorn)
- os=-riscix1.2
- ;;
- arm*-rebel)
- os=-linux
- ;;
- arm*-semi)
- os=-aout
- ;;
- c4x-* | tic4x-*)
- os=-coff
- ;;
- # This must come before the *-dec entry.
- pdp10-*)
- os=-tops20
- ;;
- pdp11-*)
- os=-none
- ;;
- *-dec | vax-*)
- os=-ultrix4.2
- ;;
- m68*-apollo)
- os=-domain
- ;;
- i386-sun)
- os=-sunos4.0.2
- ;;
- m68000-sun)
- os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
- ;;
- m68*-cisco)
- os=-aout
- ;;
- mep-*)
- os=-elf
- ;;
- mips*-cisco)
- os=-elf
- ;;
- mips*-*)
- os=-elf
- ;;
- or32-*)
- os=-coff
- ;;
- *-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
- ;;
- sparc-* | *-sun)
- os=-sunos4.1.1
- ;;
- *-be)
- os=-beos
- ;;
- *-haiku)
- os=-haiku
- ;;
- *-ibm)
- os=-aix
- ;;
- *-knuth)
- os=-mmixware
- ;;
- *-wec)
- os=-proelf
- ;;
- *-winbond)
- os=-proelf
- ;;
- *-oki)
- os=-proelf
- ;;
- *-hp)
- os=-hpux
- ;;
- *-hitachi)
- os=-hiux
- ;;
- i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
- ;;
- *-cbm)
- os=-amigaos
- ;;
- *-dg)
- os=-dgux
- ;;
- *-dolphin)
- os=-sysv3
- ;;
- m68k-ccur)
- os=-rtu
- ;;
- m88k-omron*)
- os=-luna
- ;;
- *-next )
- os=-nextstep
- ;;
- *-sequent)
- os=-ptx
- ;;
- *-crds)
- os=-unos
- ;;
- *-ns)
- os=-genix
- ;;
- i370-*)
- os=-mvs
- ;;
- *-next)
- os=-nextstep3
- ;;
- *-gould)
- os=-sysv
- ;;
- *-highlevel)
- os=-bsd
- ;;
- *-encore)
- os=-bsd
- ;;
- *-sgi)
- os=-irix
- ;;
- *-siemens)
- os=-sysv4
- ;;
- *-masscomp)
- os=-rtu
- ;;
- f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
- ;;
- *-rom68k)
- os=-coff
- ;;
- *-*bug)
- os=-coff
- ;;
- *-apple)
- os=-macos
- ;;
- *-atari*)
- os=-mint
- ;;
- *)
- os=-none
- ;;
-esac
-fi
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
- case $os in
- -riscix*)
- vendor=acorn
- ;;
- -sunos*)
- vendor=sun
- ;;
- -aix*)
- vendor=ibm
- ;;
- -beos*)
- vendor=be
- ;;
- -hpux*)
- vendor=hp
- ;;
- -mpeix*)
- vendor=hp
- ;;
- -hiux*)
- vendor=hitachi
- ;;
- -unos*)
- vendor=crds
- ;;
- -dgux*)
- vendor=dg
- ;;
- -luna*)
- vendor=omron
- ;;
- -genix*)
- vendor=ns
- ;;
- -mvs* | -opened*)
- vendor=ibm
- ;;
- -os400*)
- vendor=ibm
- ;;
- -ptx*)
- vendor=sequent
- ;;
- -tpf*)
- vendor=ibm
- ;;
- -vxsim* | -vxworks* | -windiss*)
- vendor=wrs
- ;;
- -aux*)
- vendor=apple
- ;;
- -hms*)
- vendor=hitachi
- ;;
- -mpw* | -macos*)
- vendor=apple
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- vendor=atari
- ;;
- -vos*)
- vendor=stratus
- ;;
- esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
- ;;
-esac
-
-echo $basic_machine$os
-exit
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/configure b/chromium/third_party/sqlite/sqlite-src-3240000/configure
deleted file mode 100755
index ea1160120f9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/configure
+++ /dev/null
@@ -1,13923 +0,0 @@
-#! /bin/sh
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sqlite 3.24.0.
-#
-#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
-#
-#
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## -------------------- ##
-## M4sh Initialization. ##
-## -------------------- ##
-
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
- emulate sh
- NULLCMD=:
- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in #(
- *posix*) :
- set -o posix ;; #(
- *) :
- ;;
-esac
-fi
-
-
-as_nl='
-'
-export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- PATH_SEPARATOR=:
- (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
- (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
- PATH_SEPARATOR=';'
- }
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
-# Find who we are. Look in the path if we contain no directory separator.
-as_myself=
-case $0 in #((
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
- done
-IFS=$as_save_IFS
-
- ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
- as_myself=$0
-fi
-if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- exit 1
-fi
-
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-# Use a proper internal environment variable to ensure we don't fall
- # into an infinite loop, continuously re-executing ourselves.
- if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
- _as_can_reexec=no; export _as_can_reexec;
- # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
- *v*x* | *x*v* ) as_opts=-vx ;;
- *v* ) as_opts=-v ;;
- *x* ) as_opts=-x ;;
- * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
- fi
- # We don't want this to propagate to other subprocesses.
- { _as_can_reexec=; unset _as_can_reexec;}
-if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
- emulate sh
- NULLCMD=:
- # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '\${1+\"\$@\"}'='\"\$@\"'
- setopt NO_GLOB_SUBST
-else
- case \`(set -o) 2>/dev/null\` in #(
- *posix*) :
- set -o posix ;; #(
- *) :
- ;;
-esac
-fi
-"
- as_required="as_fn_return () { (exit \$1); }
-as_fn_success () { as_fn_return 0; }
-as_fn_failure () { as_fn_return 1; }
-as_fn_ret_success () { return 0; }
-as_fn_ret_failure () { return 1; }
-
-exitcode=0
-as_fn_success || { exitcode=1; echo as_fn_success failed.; }
-as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
-as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
-as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
-
-else
- exitcode=1; echo positional parameters were not saved.
-fi
-test x\$exitcode = x0 || exit 1
-test -x / || exit 1"
- as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
- as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
- eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
- test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
-test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
- as_have_required=yes
-else
- as_have_required=no
-fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
-
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-as_found=false
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- as_found=:
- case $as_dir in #(
- /*)
- for as_base in sh bash ksh sh5; do
- # Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
- if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
- CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
- break 2
-fi
-fi
- done;;
- esac
- as_found=false
-done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
-IFS=$as_save_IFS
-
-
- if test "x$CONFIG_SHELL" != x; then :
- export CONFIG_SHELL
- # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
- *v*x* | *x*v* ) as_opts=-vx ;;
- *v* ) as_opts=-v ;;
- *x* ) as_opts=-x ;;
- * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-exit 255
-fi
-
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
- else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
-$0: including any error possibly output before this
-$0: message. Then install a modern shell, or manually run
-$0: the script under such a shell if you do have one."
- fi
- exit 1
-fi
-fi
-fi
-SHELL=${CONFIG_SHELL-/bin/sh}
-export SHELL
-# Unset more variables known to interfere with behavior of common tools.
-CLICOLOR_FORCE= GREP_OPTIONS=
-unset CLICOLOR_FORCE GREP_OPTIONS
-
-## --------------------- ##
-## M4sh Shell Functions. ##
-## --------------------- ##
-# as_fn_unset VAR
-# ---------------
-# Portably unset VAR.
-as_fn_unset ()
-{
- { eval $1=; unset $1;}
-}
-as_unset=as_fn_unset
-
-# as_fn_set_status STATUS
-# -----------------------
-# Set $? to STATUS, without forking.
-as_fn_set_status ()
-{
- return $1
-} # as_fn_set_status
-
-# as_fn_exit STATUS
-# -----------------
-# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
-as_fn_exit ()
-{
- set +e
- as_fn_set_status $1
- exit $1
-} # as_fn_exit
-
-# as_fn_mkdir_p
-# -------------
-# Create "$as_dir" as a directory, including parents if necessary.
-as_fn_mkdir_p ()
-{
-
- case $as_dir in #(
- -*) as_dir=./$as_dir;;
- esac
- test -d "$as_dir" || eval $as_mkdir_p || {
- as_dirs=
- while :; do
- case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
- *) as_qdir=$as_dir;;
- esac
- as_dirs="'$as_qdir' $as_dirs"
- as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- test -d "$as_dir" && break
- done
- test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
-
-
-} # as_fn_mkdir_p
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
- test -f "$1" && test -x "$1"
-} # as_fn_executable_p
-# as_fn_append VAR VALUE
-# ----------------------
-# Append the text in VALUE to the end of the definition contained in VAR. Take
-# advantage of any shell optimizations that allow amortized linear growth over
-# repeated appends, instead of the typical quadratic growth present in naive
-# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
- eval 'as_fn_append ()
- {
- eval $1+=\$2
- }'
-else
- as_fn_append ()
- {
- eval $1=\$$1\$2
- }
-fi # as_fn_append
-
-# as_fn_arith ARG...
-# ------------------
-# Perform arithmetic evaluation on the ARGs, and store the result in the
-# global $as_val. Take advantage of shells that can avoid forks. The arguments
-# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
- eval 'as_fn_arith ()
- {
- as_val=$(( $* ))
- }'
-else
- as_fn_arith ()
- {
- as_val=`expr "$@" || test $? -eq 1`
- }
-fi # as_fn_arith
-
-
-# as_fn_error STATUS ERROR [LINENO LOG_FD]
-# ----------------------------------------
-# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with STATUS, using 1 if that was 0.
-as_fn_error ()
-{
- as_status=$1; test $as_status -eq 0 && as_status=1
- if test "$4"; then
- as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
- fi
- $as_echo "$as_me: error: $2" >&2
- as_fn_exit $as_status
-} # as_fn_error
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
-
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-
- as_lineno_1=$LINENO as_lineno_1a=$LINENO
- as_lineno_2=$LINENO as_lineno_2a=$LINENO
- eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
- test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
- # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
- sed -n '
- p
- /[$]LINENO/=
- ' <$as_myself |
- sed '
- s/[$]LINENO.*/&-/
- t lineno
- b
- :lineno
- N
- :loop
- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
- t loop
- s/-\n.*//
- ' >$as_me.lineno &&
- chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
-
- # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
- # already done that, so ensure we don't try to do so again and fall
- # in an infinite loop. This has already happened in practice.
- _as_can_reexec=no; export _as_can_reexec
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensitive to this).
- . "./$as_me.lineno"
- # Exit status is that of the last command.
- exit
-}
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in #(((((
--n*)
- case `echo 'xy\c'` in
- *c*) ECHO_T=' ';; # ECHO_T is single tab character.
- xy) ECHO_C='\c';;
- *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
- ECHO_T=' ';;
- esac;;
-*)
- ECHO_N='-n';;
-esac
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
- rm -f conf$$.dir/conf$$.file
-else
- rm -f conf$$.dir
- mkdir conf$$.dir 2>/dev/null
-fi
-if (echo >conf$$.file) 2>/dev/null; then
- if ln -s conf$$.file conf$$ 2>/dev/null; then
- as_ln_s='ln -s'
- # ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -pR'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -pR'
- elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
- else
- as_ln_s='cp -pR'
- fi
-else
- as_ln_s='cp -pR'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p='mkdir -p "$as_dir"'
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-case X$lt_ECHO in
-X*--fallback-echo)
- # Remove one level of quotation (which was required for Make).
- ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','`
- ;;
-esac
-
-ECHO=${lt_ECHO-echo}
-if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X$1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
- # Yippee, $ECHO works!
- :
-else
- # Restart under the correct shell.
- exec $SHELL "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<_LT_EOF
-$*
-_LT_EOF
- exit 0
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-if test -z "$lt_ECHO"; then
- if test "X${echo_test_string+set}" != Xset; then
- # find a string as large as possible, as long as the shell can cope with it
- for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
- # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
- if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
- { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
- then
- break
- fi
- done
- fi
-
- if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- :
- else
- # The Solaris, AIX, and Digital Unix default echo programs unquote
- # backslashes. This makes it impossible to quote backslashes using
- # echo "$something" | sed 's/\\/\\\\/g'
- #
- # So, first we look for a working echo in the user's PATH.
-
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for dir in $PATH /usr/ucb; do
- IFS="$lt_save_ifs"
- if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
- test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- ECHO="$dir/echo"
- break
- fi
- done
- IFS="$lt_save_ifs"
-
- if test "X$ECHO" = Xecho; then
- # We didn't find a better echo, so look for alternatives.
- if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- # This shell has a builtin print -r that does the trick.
- ECHO='print -r'
- elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
- test "X$CONFIG_SHELL" != X/bin/ksh; then
- # If we have ksh, try running configure again with it.
- ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
- export ORIGINAL_CONFIG_SHELL
- CONFIG_SHELL=/bin/ksh
- export CONFIG_SHELL
- exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
- else
- # Try using printf.
- ECHO='printf %s\n'
- if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- # Cool, printf works
- :
- elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
- test "X$echo_testing_string" = 'X\t' &&
- echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
- export CONFIG_SHELL
- SHELL="$CONFIG_SHELL"
- export SHELL
- ECHO="$CONFIG_SHELL $0 --fallback-echo"
- elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
- test "X$echo_testing_string" = 'X\t' &&
- echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- ECHO="$CONFIG_SHELL $0 --fallback-echo"
- else
- # maybe with a smaller string...
- prev=:
-
- for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
- if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
- then
- break
- fi
- prev="$cmd"
- done
-
- if test "$prev" != 'sed 50q "$0"'; then
- echo_test_string=`eval $prev`
- export echo_test_string
- exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
- else
- # Oops. We lost completely, so just stick with echo.
- ECHO=echo
- fi
- fi
- fi
- fi
- fi
-fi
-
-# Copy echo and quote the copy suitably for passing to libtool from
-# the Makefile, instead of quoting the original, which is used later.
-lt_ECHO=$ECHO
-if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
- lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
-fi
-
-
-
-
-test -n "$DJDIR" || exec 7<&0 </dev/null
-exec 6>&1
-
-# Name of the host.
-# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_clean_files=
-ac_config_libobj_dir=.
-LIBOBJS=
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-
-# Identity of this package.
-PACKAGE_NAME='sqlite'
-PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.24.0'
-PACKAGE_STRING='sqlite 3.24.0'
-PACKAGE_BUGREPORT=''
-PACKAGE_URL=''
-
-# Factoring default headers for most tests.
-ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
-# include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif"
-
-ac_subst_vars='LTLIBOBJS
-LIBOBJS
-BUILD_CFLAGS
-USE_GCOV
-OPT_FEATURE_FLAGS
-HAVE_ZLIB
-USE_AMALGAMATION
-TARGET_DEBUG
-TARGET_HAVE_EDITLINE
-TARGET_HAVE_READLINE
-TARGET_READLINE_INC
-TARGET_READLINE_LIBS
-HAVE_TCL
-TCL_SHLIB_SUFFIX
-TCL_STUB_LIB_SPEC
-TCL_STUB_LIB_FLAG
-TCL_STUB_LIB_FILE
-TCL_LIB_SPEC
-TCL_LIB_FLAG
-TCL_LIB_FILE
-TCL_INCLUDE_SPEC
-TCL_SRC_DIR
-TCL_BIN_DIR
-TCL_VERSION
-TARGET_EXEEXT
-SQLITE_OS_WIN
-SQLITE_OS_UNIX
-BUILD_EXEEXT
-TEMP_STORE
-ALLOWRELEASE
-SQLITE_THREADSAFE
-BUILD_CC
-VERSION_NUMBER
-RELEASE
-VERSION
-program_prefix
-TCLLIBDIR
-TCLSH_CMD
-INSTALL_DATA
-INSTALL_SCRIPT
-INSTALL_PROGRAM
-CPP
-OTOOL64
-OTOOL
-LIPO
-NMEDIT
-DSYMUTIL
-lt_ECHO
-RANLIB
-STRIP
-AR
-OBJDUMP
-LN_S
-NM
-ac_ct_DUMPBIN
-DUMPBIN
-LD
-FGREP
-EGREP
-GREP
-SED
-OBJEXT
-EXEEXT
-ac_ct_CC
-CPPFLAGS
-LDFLAGS
-CFLAGS
-CC
-host_os
-host_vendor
-host_cpu
-host
-build_os
-build_vendor
-build_cpu
-build
-LIBTOOL
-target_alias
-host_alias
-build_alias
-LIBS
-ECHO_T
-ECHO_N
-ECHO_C
-DEFS
-mandir
-localedir
-libdir
-psdir
-pdfdir
-dvidir
-htmldir
-infodir
-docdir
-oldincludedir
-includedir
-localstatedir
-sharedstatedir
-sysconfdir
-datadir
-datarootdir
-libexecdir
-sbindir
-bindir
-program_transform_name
-prefix
-exec_prefix
-PACKAGE_URL
-PACKAGE_BUGREPORT
-PACKAGE_STRING
-PACKAGE_VERSION
-PACKAGE_TARNAME
-PACKAGE_NAME
-PATH_SEPARATOR
-SHELL'
-ac_subst_files=''
-ac_user_opts='
-enable_option_checking
-enable_shared
-enable_static
-with_pic
-enable_fast_install
-with_gnu_ld
-enable_libtool_lock
-enable_largefile
-enable_threadsafe
-enable_releasemode
-enable_tempstore
-enable_tcl
-with_tcl
-enable_editline
-enable_readline
-with_readline_lib
-with_readline_inc
-enable_debug
-enable_amalgamation
-enable_load_extension
-enable_memsys5
-enable_memsys3
-enable_fts3
-enable_fts4
-enable_fts5
-enable_json1
-enable_update_limit
-enable_rtree
-enable_session
-enable_gcov
-'
- ac_precious_vars='build_alias
-host_alias
-target_alias
-CC
-CFLAGS
-LDFLAGS
-LIBS
-CPPFLAGS
-CPP
-TCLLIBDIR'
-
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-ac_unrecognized_opts=
-ac_unrecognized_sep=
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-# (The list follows the same order as the GNU Coding Standards.)
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datarootdir='${prefix}/share'
-datadir='${datarootdir}'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
-infodir='${datarootdir}/info'
-htmldir='${docdir}'
-dvidir='${docdir}'
-pdfdir='${docdir}'
-psdir='${docdir}'
-libdir='${exec_prefix}/lib'
-localedir='${datarootdir}/locale'
-mandir='${datarootdir}/man'
-
-ac_prev=
-ac_dashdash=
-for ac_option
-do
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval $ac_prev=\$ac_option
- ac_prev=
- continue
- fi
-
- case $ac_option in
- *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
- *=) ac_optarg= ;;
- *) ac_optarg=yes ;;
- esac
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case $ac_dashdash$ac_option in
- --)
- ac_dashdash=yes ;;
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir=$ac_optarg ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build_alias ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build_alias=$ac_optarg ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file=$ac_optarg ;;
-
- --config-cache | -C)
- cache_file=config.cache ;;
-
- -datadir | --datadir | --datadi | --datad)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=*)
- datadir=$ac_optarg ;;
-
- -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
- | --dataroo | --dataro | --datar)
- ac_prev=datarootdir ;;
- -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
- | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
- datarootdir=$ac_optarg ;;
-
- -disable-* | --disable-*)
- ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
- ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
- case $ac_user_opts in
- *"
-"enable_$ac_useropt"
-"*) ;;
- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
- ac_unrecognized_sep=', ';;
- esac
- eval enable_$ac_useropt=no ;;
-
- -docdir | --docdir | --docdi | --doc | --do)
- ac_prev=docdir ;;
- -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
- docdir=$ac_optarg ;;
-
- -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
- ac_prev=dvidir ;;
- -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
- dvidir=$ac_optarg ;;
-
- -enable-* | --enable-*)
- ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
- ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
- case $ac_user_opts in
- *"
-"enable_$ac_useropt"
-"*) ;;
- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
- ac_unrecognized_sep=', ';;
- esac
- eval enable_$ac_useropt=\$ac_optarg ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix=$ac_optarg ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he | -h)
- ac_init_help=long ;;
- -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
- ac_init_help=recursive ;;
- -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
- ac_init_help=short ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host_alias ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host_alias=$ac_optarg ;;
-
- -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
- ac_prev=htmldir ;;
- -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
- | --ht=*)
- htmldir=$ac_optarg ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir=$ac_optarg ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir=$ac_optarg ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir=$ac_optarg ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir=$ac_optarg ;;
-
- -localedir | --localedir | --localedi | --localed | --locale)
- ac_prev=localedir ;;
- -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
- localedir=$ac_optarg ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst | --locals)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
- localstatedir=$ac_optarg ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir=$ac_optarg ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c | -n)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir=$ac_optarg ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix=$ac_optarg ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix=$ac_optarg ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix=$ac_optarg ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name=$ac_optarg ;;
-
- -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
- ac_prev=pdfdir ;;
- -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
- pdfdir=$ac_optarg ;;
-
- -psdir | --psdir | --psdi | --psd | --ps)
- ac_prev=psdir ;;
- -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
- psdir=$ac_optarg ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir=$ac_optarg ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir=$ac_optarg ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site=$ac_optarg ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir=$ac_optarg ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir=$ac_optarg ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target_alias ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target_alias=$ac_optarg ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers | -V)
- ac_init_version=: ;;
-
- -with-* | --with-*)
- ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
- ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
- case $ac_user_opts in
- *"
-"with_$ac_useropt"
-"*) ;;
- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
- ac_unrecognized_sep=', ';;
- esac
- eval with_$ac_useropt=\$ac_optarg ;;
-
- -without-* | --without-*)
- ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
- ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
- case $ac_user_opts in
- *"
-"with_$ac_useropt"
-"*) ;;
- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
- ac_unrecognized_sep=', ';;
- esac
- eval with_$ac_useropt=no ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes=$ac_optarg ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries=$ac_optarg ;;
-
- -*) as_fn_error $? "unrecognized option: \`$ac_option'
-Try \`$0 --help' for more information"
- ;;
-
- *=*)
- ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
- # Reject names that are not valid shell variable names.
- case $ac_envvar in #(
- '' | [0-9]* | *[!_$as_cr_alnum]* )
- as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
- esac
- eval $ac_envvar=\$ac_optarg
- export $ac_envvar ;;
-
- *)
- # FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
- expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
- : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- as_fn_error $? "missing argument to $ac_option"
-fi
-
-if test -n "$ac_unrecognized_opts"; then
- case $enable_option_checking in
- no) ;;
- fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
- esac
-fi
-
-# Check all directory arguments for consistency.
-for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
- datadir sysconfdir sharedstatedir localstatedir includedir \
- oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir
-do
- eval ac_val=\$$ac_var
- # Remove trailing slashes.
- case $ac_val in
- */ )
- ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
- eval $ac_var=\$ac_val;;
- esac
- # Be sure to have absolute directory names.
- case $ac_val in
- [\\/$]* | ?:[\\/]* ) continue;;
- NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
- esac
- as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
- if test "x$build_alias" = x; then
- cross_compiling=maybe
- elif test "x$build_alias" != "x$host_alias"; then
- cross_compiling=yes
- fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-ac_pwd=`pwd` && test -n "$ac_pwd" &&
-ac_ls_di=`ls -di .` &&
-ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
- as_fn_error $? "working directory cannot be determined"
-test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
- as_fn_error $? "pwd does not report name of working directory"
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then the parent directory.
- ac_confdir=`$as_dirname -- "$as_myself" ||
-$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_myself" : 'X\(//\)[^/]' \| \
- X"$as_myself" : 'X\(//\)$' \| \
- X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- srcdir=$ac_confdir
- if test ! -r "$srcdir/$ac_unique_file"; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r "$srcdir/$ac_unique_file"; then
- test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
- as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
-fi
-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
-ac_abs_confdir=`(
- cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
- pwd)`
-# When building in place, set srcdir=.
-if test "$ac_abs_confdir" = "$ac_pwd"; then
- srcdir=.
-fi
-# Remove unnecessary trailing slashes from srcdir.
-# Double slashes in file names in object file debugging info
-# mess up M-x gdb in Emacs.
-case $srcdir in
-*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
-esac
-for ac_var in $ac_precious_vars; do
- eval ac_env_${ac_var}_set=\${${ac_var}+set}
- eval ac_env_${ac_var}_value=\$${ac_var}
- eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
- eval ac_cv_env_${ac_var}_value=\$${ac_var}
-done
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat <<_ACEOF
-\`configure' configures sqlite 3.24.0 to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE. See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
- -h, --help display this help and exit
- --help=short display options specific to this package
- --help=recursive display the short help of all the included packages
- -V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking ...' messages
- --cache-file=FILE cache test results in FILE [disabled]
- -C, --config-cache alias for \`--cache-file=config.cache'
- -n, --no-create do not create output files
- --srcdir=DIR find the sources in DIR [configure dir or \`..']
-
-Installation directories:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
- --bindir=DIR user executables [EPREFIX/bin]
- --sbindir=DIR system admin executables [EPREFIX/sbin]
- --libexecdir=DIR program executables [EPREFIX/libexec]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --libdir=DIR object code libraries [EPREFIX/lib]
- --includedir=DIR C header files [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc [/usr/include]
- --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
- --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
- --infodir=DIR info documentation [DATAROOTDIR/info]
- --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
- --mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/sqlite]
- --htmldir=DIR html documentation [DOCDIR]
- --dvidir=DIR dvi documentation [DOCDIR]
- --pdfdir=DIR pdf documentation [DOCDIR]
- --psdir=DIR ps documentation [DOCDIR]
-_ACEOF
-
- cat <<\_ACEOF
-
-System types:
- --build=BUILD configure for building on BUILD [guessed]
- --host=HOST cross-compile to build programs to run on HOST [BUILD]
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.24.0:";;
- esac
- cat <<\_ACEOF
-
-Optional Features:
- --disable-option-checking ignore unrecognized --enable/--with options
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --enable-shared[=PKGS] build shared libraries [default=yes]
- --enable-static[=PKGS] build static libraries [default=yes]
- --enable-fast-install[=PKGS]
- optimize for fast installation [default=yes]
- --disable-libtool-lock avoid locking (might break parallel builds)
- --disable-largefile omit support for large files
- --disable-threadsafe Disable mutexing
- --enable-releasemode Support libtool link to release mode
- --enable-tempstore Use an in-ram database for temporary tables
- (never,no,yes,always)
- --disable-tcl do not build TCL extension
- --enable-editline enable BSD editline support
- --disable-readline disable readline support
- --enable-debug enable debugging & verbose explain
- --disable-amalgamation Disable the amalgamation and instead build all files
- separately
- --disable-load-extension
- Disable loading of external extensions
- --enable-memsys5 Enable MEMSYS5
- --enable-memsys3 Enable MEMSYS3
- --enable-fts3 Enable the FTS3 extension
- --enable-fts4 Enable the FTS4 extension
- --enable-fts5 Enable the FTS5 extension
- --enable-json1 Enable the JSON1 extension
- --enable-update-limit Enable the UPDATE/DELETE LIMIT clause
- --enable-rtree Enable the RTREE extension
- --enable-session Enable the SESSION extension
- --enable-gcov Enable coverage testing using gcov
-
-Optional Packages:
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --with-pic try to use only PIC/non-PIC objects [default=use
- both]
- --with-gnu-ld assume the C compiler uses GNU ld [default=no]
- --with-tcl=DIR directory containing tcl configuration
- (tclConfig.sh)
- --with-readline-lib specify readline library
- --with-readline-inc specify readline include paths
-
-Some influential environment variables:
- CC C compiler command
- CFLAGS C compiler flags
- LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
- nonstandard directory <lib dir>
- LIBS libraries to pass to the linker, e.g. -l<library>
- CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
- you have headers in a nonstandard directory <include dir>
- CPP C preprocessor
- TCLLIBDIR Where to install tcl plugin
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-Report bugs to the package provider.
-_ACEOF
-ac_status=$?
-fi
-
-if test "$ac_init_help" = "recursive"; then
- # If there are subdirs, report their specific --help.
- for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
- test -d "$ac_dir" ||
- { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
- continue
- ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
- # A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
- case $ac_top_builddir_sub in
- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
- esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
- .) # We are building in place.
- ac_srcdir=.
- ac_top_srcdir=$ac_top_builddir_sub
- ac_abs_top_srcdir=$ac_pwd ;;
- [\\/]* | ?:[\\/]* ) # Absolute name.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir
- ac_abs_top_srcdir=$srcdir ;;
- *) # Relative name.
- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_build_prefix$srcdir
- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
- cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
- if test -f "$ac_srcdir/configure.gnu"; then
- echo &&
- $SHELL "$ac_srcdir/configure.gnu" --help=recursive
- elif test -f "$ac_srcdir/configure"; then
- echo &&
- $SHELL "$ac_srcdir/configure" --help=recursive
- else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
- fi || ac_status=$?
- cd "$ac_pwd" || { ac_status=$?; break; }
- done
-fi
-
-test -n "$ac_init_help" && exit $ac_status
-if $ac_init_version; then
- cat <<\_ACEOF
-sqlite configure 3.24.0
-generated by GNU Autoconf 2.69
-
-Copyright (C) 2012 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
- exit
-fi
-
-## ------------------------ ##
-## Autoconf initialization. ##
-## ------------------------ ##
-
-# ac_fn_c_try_compile LINENO
-# --------------------------
-# Try to compile conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_compile ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
- if { { ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compile") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_compile
-
-# ac_fn_c_try_link LINENO
-# -----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_link ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- test -x conftest$ac_exeext
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
- # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
- # interfere with the next link command; also delete a directory that is
- # left behind by Apple's compiler. We do this before executing the actions.
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_link
-
-# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists and can be compiled using the include files in
-# INCLUDES, setting the cache variable VAR accordingly.
-ac_fn_c_check_header_compile ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_compile
-
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_try_run LINENO
-# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
-ac_fn_c_try_run ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
- ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=$ac_status
-fi
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_run
-
-# ac_fn_c_check_func LINENO FUNC VAR
-# ----------------------------------
-# Tests whether FUNC exists, setting the cache variable VAR accordingly
-ac_fn_c_check_func ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $2 innocuous_$2
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $2
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $2 ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$2 || defined __stub___$2
-choke me
-#endif
-
-int
-main ()
-{
-return $2 ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_func
-
-# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
-# -------------------------------------------
-# Tests whether TYPE exists after having included INCLUDES, setting cache
-# variable VAR accordingly.
-ac_fn_c_check_type ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=no"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-if (sizeof ($2))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-if (sizeof (($2)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
- eval "$3=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_type
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-cat >config.log <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by sqlite $as_me 3.24.0, which was
-generated by GNU Autoconf 2.69. Invocation command line was
-
- $ $0 $@
-
-_ACEOF
-exec 5>>config.log
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
-
-/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
-/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
-/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
- done
-IFS=$as_save_IFS
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
- for ac_arg
- do
- case $ac_arg in
- -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- continue ;;
- *\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
- esac
- case $ac_pass in
- 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
- 2)
- as_fn_append ac_configure_args1 " '$ac_arg'"
- if test $ac_must_keep_next = true; then
- ac_must_keep_next=false # Got value, back to normal.
- else
- case $ac_arg in
- *=* | --config-cache | -C | -disable-* | --disable-* \
- | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
- | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
- | -with-* | --with-* | -without-* | --without-* | --x)
- case "$ac_configure_args0 " in
- "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
- esac
- ;;
- -* ) ac_must_keep_next=true ;;
- esac
- fi
- as_fn_append ac_configure_args " '$ac_arg'"
- ;;
- esac
- done
-done
-{ ac_configure_args0=; unset ac_configure_args0;}
-{ ac_configure_args1=; unset ac_configure_args1;}
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log. We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Use '\'' to represent an apostrophe within the trap.
-# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
-trap 'exit_status=$?
- # Save into config.log some information that might help in debugging.
- {
- echo
-
- $as_echo "## ---------------- ##
-## Cache variables. ##
-## ---------------- ##"
- echo
- # The following way of writing the cache mishandles newlines in values,
-(
- for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
- eval ac_val=\$$ac_var
- case $ac_val in #(
- *${as_nl}*)
- case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
- esac
- case $ac_var in #(
- _ | IFS | as_nl) ;; #(
- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
- *) { eval $ac_var=; unset $ac_var;} ;;
- esac ;;
- esac
- done
- (set) 2>&1 |
- case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
- *${as_nl}ac_space=\ *)
- sed -n \
- "s/'\''/'\''\\\\'\'''\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
- ;; #(
- *)
- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
- ;;
- esac |
- sort
-)
- echo
-
- $as_echo "## ----------------- ##
-## Output variables. ##
-## ----------------- ##"
- echo
- for ac_var in $ac_subst_vars
- do
- eval ac_val=\$$ac_var
- case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
- esac
- $as_echo "$ac_var='\''$ac_val'\''"
- done | sort
- echo
-
- if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
-## File substitutions. ##
-## ------------------- ##"
- echo
- for ac_var in $ac_subst_files
- do
- eval ac_val=\$$ac_var
- case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
- esac
- $as_echo "$ac_var='\''$ac_val'\''"
- done | sort
- echo
- fi
-
- if test -s confdefs.h; then
- $as_echo "## ----------- ##
-## confdefs.h. ##
-## ----------- ##"
- echo
- cat confdefs.h
- echo
- fi
- test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
- } >&5
- rm -f core *.core core.conftest.* &&
- rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
- exit $exit_status
-' 0
-for ac_signal in 1 2 13 15; do
- trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -f -r conftest* confdefs.h
-
-$as_echo "/* confdefs.h */" > confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
-if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
-elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
-else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
-fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
-do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
- sed 's/^/| /' "$ac_site_file" >&5
- . "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5; }
- fi
-done
-
-if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special files
- # actually), so we avoid doing that. DJGPP emulates it as a regular file.
- if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
- case $cache_file in
- [\\/]* | ?:[\\/]* ) . "$cache_file";;
- *) . "./$cache_file";;
- esac
- fi
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
- >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in $ac_precious_vars; do
- eval ac_old_set=\$ac_cv_env_${ac_var}_set
- eval ac_new_set=\$ac_env_${ac_var}_set
- eval ac_old_val=\$ac_cv_env_${ac_var}_value
- eval ac_new_val=\$ac_env_${ac_var}_value
- case $ac_old_set,$ac_new_set in
- set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,);;
- *)
- if test "x$ac_old_val" != "x$ac_new_val"; then
- # differences in whitespace do not lead to failure.
- ac_old_val_w=`echo x $ac_old_val`
- ac_new_val_w=`echo x $ac_new_val`
- if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
- ac_cache_corrupted=:
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
- eval $ac_var=\$ac_old_val
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
- fi;;
- esac
- # Pass precious variables to config.status.
- if test "$ac_new_set" = set; then
- case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
- *) ac_arg=$ac_var=$ac_new_val ;;
- esac
- case " $ac_configure_args " in
- *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
- *) as_fn_append ac_configure_args " '$ac_arg'" ;;
- esac
- fi
-done
-if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
-fi
-## -------------------- ##
-## Main body of script. ##
-## -------------------- ##
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-sqlite_version_sanity_check=`cat $srcdir/VERSION | tr -d '\n'`
-if test "$PACKAGE_VERSION" != "$sqlite_version_sanity_check" ; then
-as_fn_error $? "configure script is out of date:
- configure \$PACKAGE_VERSION = $PACKAGE_VERSION
- top level VERSION file = $sqlite_version_sanity_check
-please regen with autoconf" "$LINENO" 5
-fi
-
-#########
-# Programs needed
-#
-case `pwd` in
- *\ * | *\ *)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
-$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
-esac
-
-
-
-macro_version='2.2.6'
-macro_revision='1.3012'
-
-
-
-
-
-
-
-
-
-
-
-
-
-ltmain="$ac_aux_dir/ltmain.sh"
-
-ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
-fi
-
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-
-
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
- as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
-esac
-build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "x$host_alias" = x; then
- ac_cv_host=$ac_cv_build
-else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-else
- CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- fi
-fi
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# != 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
- fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- for ac_prog in cl.exe
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$CC" && break
- done
-fi
-if test -z "$CC"; then
- ac_ct_CC=$CC
- for ac_prog in cl.exe
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$ac_ct_CC" && break
-done
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-fi
-
-fi
-
-
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
-
-# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
-set X $ac_compile
-ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
- { { ac_try="$ac_compiler $ac_option >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compiler $ac_option >&5") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- sed '10a\
-... rest of stderr output deleted ...
- 10q' conftest.err >conftest.er1
- cat conftest.er1 >&5
- fi
- rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }
-done
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-
-# The possible output files:
-ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
-
-ac_rmfiles=
-for ac_file in $ac_files
-do
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
- * ) ac_rmfiles="$ac_rmfiles $ac_file";;
- esac
-done
-rm -f $ac_rmfiles
-
-if { { ac_try="$ac_link_default"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link_default") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
-# in a Makefile. We should not override ac_cv_exeext if it was cached,
-# so that the user can short-circuit this test for compilers unknown to
-# Autoconf.
-for ac_file in $ac_files ''
-do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
- ;;
- [ab].out )
- # We found the default executable, but exeext='' is most
- # certainly right.
- break;;
- *.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
- then :; else
- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- fi
- # We set ac_cv_exeext here because the later test for it is not
- # safe: cross compilers may not add the suffix if given an `-o'
- # argument, so we may need to know it at that point already.
- # Even if this section looks crufty: it has the advantage of
- # actually working.
- break;;
- * )
- break;;
- esac
-done
-test "$ac_cv_exeext" = no && ac_cv_exeext=
-
-else
- ac_file=''
-fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
-ac_exeext=$ac_cv_exeext
-
-rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
-if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- break;;
- * ) break;;
- esac
-done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdio.h>
-int
-main ()
-{
-FILE *f = fopen ("conftest.out", "w");
- return ferror (f) || fclose (f) != 0;
-
- ;
- return 0;
-}
-_ACEOF
-ac_clean_files="$ac_clean_files conftest.out"
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
-if test "$cross_compiling" != yes; then
- { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }
- if { ac_try='./conftest$ac_cv_exeext'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5; }
- fi
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
-
-rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
-ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { { ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compile") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- for ac_file in conftest.o conftest.obj conftest.*; do
- test -f "$ac_file" || continue;
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
- *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
- break;;
- esac
-done
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_compiler_gnu=yes
-else
- ac_compiler_gnu=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
-if test $ac_compiler_gnu = yes; then
- GCC=yes
-else
- GCC=
-fi
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_save_c_werror_flag=$ac_c_werror_flag
- ac_c_werror_flag=yes
- ac_cv_prog_cc_g=no
- CFLAGS="-g"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_g=yes
-else
- CFLAGS=""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
- ac_c_werror_flag=$ac_save_c_werror_flag
- CFLAGS="-g"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_g=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_c_werror_flag=$ac_save_c_werror_flag
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
-_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
- CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_c89=$ac_arg
-fi
-rm -f core conftest.err conftest.$ac_objext
- test "x$ac_cv_prog_cc_c89" != "xno" && break
-done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
-
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
-$as_echo_n "checking for a sed that does not truncate output... " >&6; }
-if ${ac_cv_path_SED+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
- for ac_i in 1 2 3 4 5 6 7; do
- ac_script="$ac_script$as_nl$ac_script"
- done
- echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
- { ac_script=; unset ac_script;}
- if test -z "$SED"; then
- ac_path_SED_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in sed gsed; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_SED" || continue
-# Check for GNU ac_path_SED and select it if it is found.
- # Check for GNU $ac_path_SED
-case `"$ac_path_SED" --version 2>&1` in
-*GNU*)
- ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo '' >> "conftest.nl"
- "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_SED_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_SED="$ac_path_SED"
- ac_path_SED_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_SED_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_SED"; then
- as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
- fi
-else
- ac_cv_path_SED=$SED
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
-$as_echo "$ac_cv_path_SED" >&6; }
- SED="$ac_cv_path_SED"
- rm -f conftest.sed
-
-test -z "$SED" && SED=sed
-Xsed="$SED -e 1s/^X//"
-
-
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
-$as_echo_n "checking for fgrep... " >&6; }
-if ${ac_cv_path_FGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
- then ac_cv_path_FGREP="$GREP -F"
- else
- if test -z "$FGREP"; then
- ac_path_FGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in fgrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_FGREP" || continue
-# Check for GNU ac_path_FGREP and select it if it is found.
- # Check for GNU $ac_path_FGREP
-case `"$ac_path_FGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'FGREP' >> "conftest.nl"
- "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_FGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_FGREP="$ac_path_FGREP"
- ac_path_FGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_FGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_FGREP"; then
- as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_FGREP=$FGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
-$as_echo "$ac_cv_path_FGREP" >&6; }
- FGREP="$ac_cv_path_FGREP"
-
-
-test -z "$GREP" && GREP=grep
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Check whether --with-gnu-ld was given.
-if test "${with_gnu_ld+set}" = set; then :
- withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
-else
- with_gnu_ld=no
-fi
-
-ac_prog=ld
-if test "$GCC" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
-$as_echo_n "checking for ld used by $CC... " >&6; }
- case $host in
- *-*-mingw*)
- # gcc leaves a trailing carriage return which upsets mingw
- ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
- *)
- ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
- esac
- case $ac_prog in
- # Accept absolute paths.
- [\\/]* | ?:[\\/]*)
- re_direlt='/[^/][^/]*/\.\./'
- # Canonicalize the pathname of ld
- ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
- while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we aren't using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
-elif test "$with_gnu_ld" = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
-$as_echo_n "checking for GNU ld... " >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
-$as_echo_n "checking for non-GNU ld... " >&6; }
-fi
-if ${lt_cv_path_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$LD"; then
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- lt_cv_path_LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some variants of GNU ld only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
- *GNU* | *'with BFD'*)
- test "$with_gnu_ld" != no && break
- ;;
- *)
- test "$with_gnu_ld" != yes && break
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
-else
- lt_cv_path_LD="$LD" # Let the user override the test with a path.
-fi
-fi
-
-LD="$lt_cv_path_LD"
-if test -n "$LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
-$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
-if ${lt_cv_prog_gnu_ld+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # I'd rather use --version here, but apparently some GNU lds only accept -v.
-case `$LD -v 2>&1 </dev/null` in
-*GNU* | *'with BFD'*)
- lt_cv_prog_gnu_ld=yes
- ;;
-*)
- lt_cv_prog_gnu_ld=no
- ;;
-esac
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
-$as_echo "$lt_cv_prog_gnu_ld" >&6; }
-with_gnu_ld=$lt_cv_prog_gnu_ld
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
-$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
-if ${lt_cv_path_NM+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$NM"; then
- # Let the user override the test.
- lt_cv_path_NM="$NM"
-else
- lt_nm_to_check="${ac_tool_prefix}nm"
- if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
- lt_nm_to_check="$lt_nm_to_check nm"
- fi
- for lt_tmp_nm in $lt_nm_to_check; do
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- tmp_nm="$ac_dir/$lt_tmp_nm"
- if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
- # Check to see if the nm accepts a BSD-compat flag.
- # Adding the `sed 1q' prevents false positives on HP-UX, which says:
- # nm: unknown option "B" ignored
- # Tru64's nm complains that /dev/null is an invalid object file
- case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
- */dev/null* | *'Invalid file or object type'*)
- lt_cv_path_NM="$tmp_nm -B"
- break
- ;;
- *)
- case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
- */dev/null*)
- lt_cv_path_NM="$tmp_nm -p"
- break
- ;;
- *)
- lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
- continue # so that we can try to find one that supports BSD flags
- ;;
- esac
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
- done
- : ${lt_cv_path_NM=no}
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
-$as_echo "$lt_cv_path_NM" >&6; }
-if test "$lt_cv_path_NM" != "no"; then
- NM="$lt_cv_path_NM"
-else
- # Didn't find any BSD compatible name lister, look for dumpbin.
- if test -n "$ac_tool_prefix"; then
- for ac_prog in "dumpbin -symbols" "link -dump -symbols"
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DUMPBIN+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$DUMPBIN"; then
- ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-DUMPBIN=$ac_cv_prog_DUMPBIN
-if test -n "$DUMPBIN"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
-$as_echo "$DUMPBIN" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$DUMPBIN" && break
- done
-fi
-if test -z "$DUMPBIN"; then
- ac_ct_DUMPBIN=$DUMPBIN
- for ac_prog in "dumpbin -symbols" "link -dump -symbols"
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_DUMPBIN"; then
- ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
-if test -n "$ac_ct_DUMPBIN"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
-$as_echo "$ac_ct_DUMPBIN" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$ac_ct_DUMPBIN" && break
-done
-
- if test "x$ac_ct_DUMPBIN" = x; then
- DUMPBIN=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- DUMPBIN=$ac_ct_DUMPBIN
- fi
-fi
-
-
- if test "$DUMPBIN" != ":"; then
- NM="$DUMPBIN"
- fi
-fi
-test -z "$NM" && NM=nm
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
-$as_echo_n "checking the name lister ($NM) interface... " >&6; }
-if ${lt_cv_nm_interface+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_nm_interface="BSD nm"
- echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:3935: $ac_compile\"" >&5)
- (eval "$ac_compile" 2>conftest.err)
- cat conftest.err >&5
- (eval echo "\"\$as_me:3938: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
- (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
- cat conftest.err >&5
- (eval echo "\"\$as_me:3941: output\"" >&5)
- cat conftest.out >&5
- if $GREP 'External.*some_variable' conftest.out > /dev/null; then
- lt_cv_nm_interface="MS dumpbin"
- fi
- rm -f conftest*
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
-$as_echo "$lt_cv_nm_interface" >&6; }
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
-$as_echo_n "checking whether ln -s works... " >&6; }
-LN_S=$as_ln_s
-if test "$LN_S" = "ln -s"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
-$as_echo "no, using $LN_S" >&6; }
-fi
-
-# find the maximum length of command line arguments
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
-$as_echo_n "checking the maximum length of command line arguments... " >&6; }
-if ${lt_cv_sys_max_cmd_len+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- i=0
- teststring="ABCD"
-
- case $build_os in
- msdosdjgpp*)
- # On DJGPP, this test can blow up pretty badly due to problems in libc
- # (any single argument exceeding 2000 bytes causes a buffer overrun
- # during glob expansion). Even if it were fixed, the result of this
- # check would be larger than it should be.
- lt_cv_sys_max_cmd_len=12288; # 12K is about right
- ;;
-
- gnu*)
- # Under GNU Hurd, this test is not required because there is
- # no limit to the length of command line arguments.
- # Libtool will interpret -1 as no limit whatsoever
- lt_cv_sys_max_cmd_len=-1;
- ;;
-
- cygwin* | mingw* | cegcc*)
- # On Win9x/ME, this test blows up -- it succeeds, but takes
- # about 5 minutes as the teststring grows exponentially.
- # Worse, since 9x/ME are not pre-emptively multitasking,
- # you end up with a "frozen" computer, even though with patience
- # the test eventually succeeds (with a max line length of 256k).
- # Instead, let's just punt: use the minimum linelength reported by
- # all of the supported platforms: 8192 (on NT/2K/XP).
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- amigaos*)
- # On AmigaOS with pdksh, this test takes hours, literally.
- # So we just punt and use a minimum line length of 8192.
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
- # This has been around since 386BSD, at least. Likely further.
- if test -x /sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
- elif test -x /usr/sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
- else
- lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
- fi
- # And add a safety zone
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
- ;;
-
- interix*)
- # We know the value 262144 and hardcode it with a safety zone (like BSD)
- lt_cv_sys_max_cmd_len=196608
- ;;
-
- osf*)
- # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
- # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
- # nice to cause kernel panics so lets avoid the loop below.
- # First set a reasonable default.
- lt_cv_sys_max_cmd_len=16384
- #
- if test -x /sbin/sysconfig; then
- case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
- *1*) lt_cv_sys_max_cmd_len=-1 ;;
- esac
- fi
- ;;
- sco3.2v5*)
- lt_cv_sys_max_cmd_len=102400
- ;;
- sysv5* | sco5v6* | sysv4.2uw2*)
- kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
- if test -n "$kargmax"; then
- lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
- else
- lt_cv_sys_max_cmd_len=32768
- fi
- ;;
- *)
- lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
- if test -n "$lt_cv_sys_max_cmd_len"; then
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
- else
- # Make teststring a little bigger before we do anything with it.
- # a 1K string should be a reasonable start.
- for i in 1 2 3 4 5 6 7 8 ; do
- teststring=$teststring$teststring
- done
- SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
- # If test is not a shell built-in, we'll probably end up computing a
- # maximum length that is only half of the actual maximum length, but
- # we can't tell.
- while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
- = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
- test $i != 17 # 1/2 MB should be enough
- do
- i=`expr $i + 1`
- teststring=$teststring$teststring
- done
- # Only check the string length outside the loop.
- lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
- teststring=
- # Add a significant safety factor because C++ compilers can tack on
- # massive amounts of additional arguments before passing them to the
- # linker. It appears as though 1/2 is a usable value.
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
- fi
- ;;
- esac
-
-fi
-
-if test -n $lt_cv_sys_max_cmd_len ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
-$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
-$as_echo "none" >&6; }
-fi
-max_cmd_len=$lt_cv_sys_max_cmd_len
-
-
-
-
-
-
-: ${CP="cp -f"}
-: ${MV="mv -f"}
-: ${RM="rm -f"}
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
-$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
-# Try some XSI features
-xsi_shell=no
-( _lt_dummy="a/b/c"
- test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
- = c,a/b,, \
- && eval 'test $(( 1 + 1 )) -eq 2 \
- && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
- && xsi_shell=yes
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
-$as_echo "$xsi_shell" >&6; }
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
-$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
-lt_shell_append=no
-( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
- >/dev/null 2>&1 \
- && lt_shell_append=yes
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
-$as_echo "$lt_shell_append" >&6; }
-
-
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- lt_unset=unset
-else
- lt_unset=false
-fi
-
-
-
-
-
-# test EBCDIC or ASCII
-case `echo X|tr X '\101'` in
- A) # ASCII based system
- # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
- lt_SP2NL='tr \040 \012'
- lt_NL2SP='tr \015\012 \040\040'
- ;;
- *) # EBCDIC based system
- lt_SP2NL='tr \100 \n'
- lt_NL2SP='tr \r\n \100\100'
- ;;
-esac
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
-$as_echo_n "checking for $LD option to reload object files... " >&6; }
-if ${lt_cv_ld_reload_flag+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_ld_reload_flag='-r'
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
-$as_echo "$lt_cv_ld_reload_flag" >&6; }
-reload_flag=$lt_cv_ld_reload_flag
-case $reload_flag in
-"" | " "*) ;;
-*) reload_flag=" $reload_flag" ;;
-esac
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-case $host_os in
- darwin*)
- if test "$GCC" = yes; then
- reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
- else
- reload_cmds='$LD$reload_flag -o $output$reload_objs'
- fi
- ;;
-esac
-
-
-
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
-set dummy ${ac_tool_prefix}objdump; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_OBJDUMP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$OBJDUMP"; then
- ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-OBJDUMP=$ac_cv_prog_OBJDUMP
-if test -n "$OBJDUMP"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
-$as_echo "$OBJDUMP" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_OBJDUMP"; then
- ac_ct_OBJDUMP=$OBJDUMP
- # Extract the first word of "objdump", so it can be a program name with args.
-set dummy objdump; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_OBJDUMP"; then
- ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_OBJDUMP="objdump"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
-if test -n "$ac_ct_OBJDUMP"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
-$as_echo "$ac_ct_OBJDUMP" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_OBJDUMP" = x; then
- OBJDUMP="false"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- OBJDUMP=$ac_ct_OBJDUMP
- fi
-else
- OBJDUMP="$ac_cv_prog_OBJDUMP"
-fi
-
-test -z "$OBJDUMP" && OBJDUMP=objdump
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
-$as_echo_n "checking how to recognize dependent libraries... " >&6; }
-if ${lt_cv_deplibs_check_method+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_file_magic_cmd='$MAGIC_CMD'
-lt_cv_file_magic_test_file=
-lt_cv_deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [[regex]]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given extended regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-
-case $host_os in
-aix[4-9]*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-beos*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-bsdi[45]*)
- lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
- lt_cv_file_magic_cmd='/usr/bin/file -L'
- lt_cv_file_magic_test_file=/shlib/libc.so
- ;;
-
-cygwin*)
- # func_win32_libid is a shell function defined in ltmain.sh
- lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
- lt_cv_file_magic_cmd='func_win32_libid'
- ;;
-
-mingw* | pw32*)
- # Base MSYS/MinGW do not provide the 'file' command needed by
- # func_win32_libid shell function, so use a weaker test based on 'objdump',
- # unless we find 'file', for example because we are cross-compiling.
- if ( file / ) >/dev/null 2>&1; then
- lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
- lt_cv_file_magic_cmd='func_win32_libid'
- else
- lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
- lt_cv_file_magic_cmd='$OBJDUMP -f'
- fi
- ;;
-
-cegcc)
- # use the weaker test based on 'objdump'. See mingw*.
- lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
- lt_cv_file_magic_cmd='$OBJDUMP -f'
- ;;
-
-darwin* | rhapsody*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-freebsd* | dragonfly*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
- case $host_cpu in
- i*86 )
- # Not sure whether the presence of OpenBSD here was a mistake.
- # Let's accept both of them until this is cleared up.
- lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
- ;;
- esac
- else
- lt_cv_deplibs_check_method=pass_all
- fi
- ;;
-
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-hpux10.20* | hpux11*)
- lt_cv_file_magic_cmd=/usr/bin/file
- case $host_cpu in
- ia64*)
- lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
- lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
- ;;
- hppa*64*)
- lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
- lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
- ;;
- *)
- lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
- lt_cv_file_magic_test_file=/usr/lib/libc.sl
- ;;
- esac
- ;;
-
-interix[3-9]*)
- # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $LD in
- *-32|*"-32 ") libmagic=32-bit;;
- *-n32|*"-n32 ") libmagic=N32;;
- *-64|*"-64 ") libmagic=64-bit;;
- *) libmagic=never-match;;
- esac
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-# This must be Linux ELF.
-linux* | k*bsd*-gnu)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
- fi
- ;;
-
-newos6*)
- lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=/usr/lib/libnls.so
- ;;
-
-*nto* | *qnx*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-openbsd*)
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
- fi
- ;;
-
-osf3* | osf4* | osf5*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-rdos*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-solaris*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-sysv4 | sysv4.3*)
- case $host_vendor in
- motorola)
- lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
- ;;
- ncr)
- lt_cv_deplibs_check_method=pass_all
- ;;
- sequent)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
- ;;
- sni)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
- lt_cv_file_magic_test_file=/lib/libc.so
- ;;
- siemens)
- lt_cv_deplibs_check_method=pass_all
- ;;
- pc)
- lt_cv_deplibs_check_method=pass_all
- ;;
- esac
- ;;
-
-tpf*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-esac
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
-$as_echo "$lt_cv_deplibs_check_method" >&6; }
-file_magic_cmd=$lt_cv_file_magic_cmd
-deplibs_check_method=$lt_cv_deplibs_check_method
-test -z "$deplibs_check_method" && deplibs_check_method=unknown
-
-
-
-
-
-
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$AR"; then
- ac_cv_prog_AR="$AR" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_AR="${ac_tool_prefix}ar"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-AR=$ac_cv_prog_AR
-if test -n "$AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_AR"; then
- ac_ct_AR=$AR
- # Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_AR"; then
- ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_AR="ar"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_AR=$ac_cv_prog_ac_ct_AR
-if test -n "$ac_ct_AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
-$as_echo "$ac_ct_AR" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_AR" = x; then
- AR="false"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- AR=$ac_ct_AR
- fi
-else
- AR="$ac_cv_prog_AR"
-fi
-
-test -z "$AR" && AR=ar
-test -z "$AR_FLAGS" && AR_FLAGS=cru
-
-
-
-
-
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
-set dummy ${ac_tool_prefix}strip; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_STRIP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$STRIP"; then
- ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_STRIP="${ac_tool_prefix}strip"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-STRIP=$ac_cv_prog_STRIP
-if test -n "$STRIP"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
-$as_echo "$STRIP" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_STRIP"; then
- ac_ct_STRIP=$STRIP
- # Extract the first word of "strip", so it can be a program name with args.
-set dummy strip; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_STRIP"; then
- ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_STRIP="strip"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
-if test -n "$ac_ct_STRIP"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
-$as_echo "$ac_ct_STRIP" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_STRIP" = x; then
- STRIP=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- STRIP=$ac_ct_STRIP
- fi
-else
- STRIP="$ac_cv_prog_STRIP"
-fi
-
-test -z "$STRIP" && STRIP=:
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
- ac_ct_RANLIB=$RANLIB
- # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_RANLIB"; then
- ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_RANLIB" = x; then
- RANLIB=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- RANLIB=$ac_ct_RANLIB
- fi
-else
- RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-test -z "$RANLIB" && RANLIB=:
-
-
-
-
-
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-if test -n "$RANLIB"; then
- case $host_os in
- openbsd*)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
- ;;
- *)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
- ;;
- esac
- old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
-$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
-if ${lt_cv_sys_global_symbol_pipe+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix. What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[BCDEGRST]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
-
-# Define system-specific variables.
-case $host_os in
-aix*)
- symcode='[BCDT]'
- ;;
-cygwin* | mingw* | pw32* | cegcc*)
- symcode='[ABCDGISTW]'
- ;;
-hpux*)
- if test "$host_cpu" = ia64; then
- symcode='[ABCDEGRST]'
- fi
- ;;
-irix* | nonstopux*)
- symcode='[BCDEGRST]'
- ;;
-osf*)
- symcode='[BCDEGQRST]'
- ;;
-solaris*)
- symcode='[BDRT]'
- ;;
-sco3.2v5*)
- symcode='[DT]'
- ;;
-sysv4.2uw2*)
- symcode='[DT]'
- ;;
-sysv5* | sco5v6* | unixware* | OpenUNIX*)
- symcode='[ABDT]'
- ;;
-sysv4)
- symcode='[DFNSTU]'
- ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-case `$NM -V 2>&1` in
-*GNU* | *'with BFD'*)
- symcode='[ABCDGIRSTW]' ;;
-esac
-
-# Transform an extracted symbol line into a proper C declaration.
-# Some systems (esp. on ia64) link data and code symbols differently,
-# so use this general approach.
-lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
-
-# Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'"
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
-
-# Handle CRLF in mingw tool chain
-opt_cr=
-case $build_os in
-mingw*)
- opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
- ;;
-esac
-
-# Try without a prefix underscore, then with it.
-for ac_symprfx in "" "_"; do
-
- # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
- symxfrm="\\1 $ac_symprfx\\2 \\2"
-
- # Write the raw and C identifiers.
- if test "$lt_cv_nm_interface" = "MS dumpbin"; then
- # Fake it for dumpbin and say T for any non-static function
- # and D for any global variable.
- # Also find C++ and __fastcall symbols from MSVC++,
- # which start with @ or ?.
- lt_cv_sys_global_symbol_pipe="$AWK '"\
-" {last_section=section; section=\$ 3};"\
-" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
-" \$ 0!~/External *\|/{next};"\
-" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
-" {if(hide[section]) next};"\
-" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
-" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
-" s[1]~/^[@?]/{print s[1], s[1]; next};"\
-" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
-" ' prfx=^$ac_symprfx"
- else
- lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
- fi
-
- # Check to see that the pipe works correctly.
- pipe_works=no
-
- rm -f conftest*
- cat > conftest.$ac_ext <<_LT_EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(void);
-void nm_test_func(void){}
-#ifdef __cplusplus
-}
-#endif
-int main(){nm_test_var='a';nm_test_func();return(0);}
-_LT_EOF
-
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- # Now try to grab the symbols.
- nlist=conftest.nm
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5
- (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && test -s "$nlist"; then
- # Try sorting and uniquifying the output.
- if sort "$nlist" | uniq > "$nlist"T; then
- mv -f "$nlist"T "$nlist"
- else
- rm -f "$nlist"T
- fi
-
- # Make sure that we snagged all the symbols we need.
- if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
- if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
- cat <<_LT_EOF > conftest.$ac_ext
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-_LT_EOF
- # Now generate the symbol file.
- eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
-
- cat <<_LT_EOF >> conftest.$ac_ext
-
-/* The mapping between symbol names and symbols. */
-const struct {
- const char *name;
- void *address;
-}
-lt__PROGRAM__LTX_preloaded_symbols[] =
-{
- { "@PROGRAM@", (void *) 0 },
-_LT_EOF
- $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
- cat <<\_LT_EOF >> conftest.$ac_ext
- {0, (void *) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
- return lt__PROGRAM__LTX_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-_LT_EOF
- # Now try linking the two files.
- mv conftest.$ac_objext conftstm.$ac_objext
- lt_save_LIBS="$LIBS"
- lt_save_CFLAGS="$CFLAGS"
- LIBS="conftstm.$ac_objext"
- CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && test -s conftest${ac_exeext}; then
- pipe_works=yes
- fi
- LIBS="$lt_save_LIBS"
- CFLAGS="$lt_save_CFLAGS"
- else
- echo "cannot find nm_test_func in $nlist" >&5
- fi
- else
- echo "cannot find nm_test_var in $nlist" >&5
- fi
- else
- echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
- fi
- else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- fi
- rm -rf conftest* conftst*
-
- # Do not use the global_symbol_pipe unless it works.
- if test "$pipe_works" = yes; then
- break
- else
- lt_cv_sys_global_symbol_pipe=
- fi
-done
-
-fi
-
-if test -z "$lt_cv_sys_global_symbol_pipe"; then
- lt_cv_sys_global_symbol_to_cdecl=
-fi
-if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
-$as_echo "failed" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
-$as_echo "ok" >&6; }
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Check whether --enable-libtool-lock was given.
-if test "${enable_libtool_lock+set}" = set; then :
- enableval=$enable_libtool_lock;
-fi
-
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
-
-# Some flags need to be propagated to the compiler or linker for good
-# libtool support.
-case $host in
-ia64-*-hpux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- case `/usr/bin/file conftest.$ac_objext` in
- *ELF-32*)
- HPUX_IA64_MODE="32"
- ;;
- *ELF-64*)
- HPUX_IA64_MODE="64"
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-*-*-irix6*)
- # Find out which ABI we are using.
- echo '#line 5147 "configure"' > conftest.$ac_ext
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- if test "$lt_cv_prog_gnu_ld" = yes; then
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -melf32bsmip"
- ;;
- *N32*)
- LD="${LD-ld} -melf32bmipn32"
- ;;
- *64-bit*)
- LD="${LD-ld} -melf64bmip"
- ;;
- esac
- else
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -32"
- ;;
- *N32*)
- LD="${LD-ld} -n32"
- ;;
- *64-bit*)
- LD="${LD-ld} -64"
- ;;
- esac
- fi
- fi
- rm -rf conftest*
- ;;
-
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
-s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- case `/usr/bin/file conftest.o` in
- *32-bit*)
- case $host in
- x86_64-*kfreebsd*-gnu)
- LD="${LD-ld} -m elf_i386_fbsd"
- ;;
- x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
- ;;
- ppc64-*linux*|powerpc64-*linux*)
- LD="${LD-ld} -m elf32ppclinux"
- ;;
- s390x-*linux*)
- LD="${LD-ld} -m elf_s390"
- ;;
- sparc64-*linux*)
- LD="${LD-ld} -m elf32_sparc"
- ;;
- esac
- ;;
- *64-bit*)
- case $host in
- x86_64-*kfreebsd*-gnu)
- LD="${LD-ld} -m elf_x86_64_fbsd"
- ;;
- x86_64-*linux*)
- LD="${LD-ld} -m elf_x86_64"
- ;;
- ppc*-*linux*|powerpc*-*linux*)
- LD="${LD-ld} -m elf64ppc"
- ;;
- s390*-*linux*|s390*-*tpf*)
- LD="${LD-ld} -m elf64_s390"
- ;;
- sparc*-*linux*)
- LD="${LD-ld} -m elf64_sparc"
- ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-
-*-*-sco3.2v5*)
- # On SCO OpenServer 5, we need -belf to get full-featured binaries.
- SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -belf"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
-$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
-if ${lt_cv_cc_needs_belf+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- lt_cv_cc_needs_belf=yes
-else
- lt_cv_cc_needs_belf=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
-$as_echo "$lt_cv_cc_needs_belf" >&6; }
- if test x"$lt_cv_cc_needs_belf" != x"yes"; then
- # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
- CFLAGS="$SAVE_CFLAGS"
- fi
- ;;
-sparc*-*solaris*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- case `/usr/bin/file conftest.o` in
- *64-bit*)
- case $lt_cv_prog_gnu_ld in
- yes*) LD="${LD-ld} -m elf64_sparc" ;;
- *)
- if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
- LD="${LD-ld} -64"
- fi
- ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-esac
-
-need_locks="$enable_libtool_lock"
-
-
- case $host_os in
- rhapsody* | darwin*)
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
-set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DSYMUTIL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$DSYMUTIL"; then
- ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-DSYMUTIL=$ac_cv_prog_DSYMUTIL
-if test -n "$DSYMUTIL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
-$as_echo "$DSYMUTIL" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_DSYMUTIL"; then
- ac_ct_DSYMUTIL=$DSYMUTIL
- # Extract the first word of "dsymutil", so it can be a program name with args.
-set dummy dsymutil; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_DSYMUTIL"; then
- ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
-if test -n "$ac_ct_DSYMUTIL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
-$as_echo "$ac_ct_DSYMUTIL" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_DSYMUTIL" = x; then
- DSYMUTIL=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- DSYMUTIL=$ac_ct_DSYMUTIL
- fi
-else
- DSYMUTIL="$ac_cv_prog_DSYMUTIL"
-fi
-
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
-set dummy ${ac_tool_prefix}nmedit; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_NMEDIT+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$NMEDIT"; then
- ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-NMEDIT=$ac_cv_prog_NMEDIT
-if test -n "$NMEDIT"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
-$as_echo "$NMEDIT" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_NMEDIT"; then
- ac_ct_NMEDIT=$NMEDIT
- # Extract the first word of "nmedit", so it can be a program name with args.
-set dummy nmedit; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_NMEDIT"; then
- ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_NMEDIT="nmedit"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
-if test -n "$ac_ct_NMEDIT"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
-$as_echo "$ac_ct_NMEDIT" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_NMEDIT" = x; then
- NMEDIT=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- NMEDIT=$ac_ct_NMEDIT
- fi
-else
- NMEDIT="$ac_cv_prog_NMEDIT"
-fi
-
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
-set dummy ${ac_tool_prefix}lipo; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LIPO+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$LIPO"; then
- ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-LIPO=$ac_cv_prog_LIPO
-if test -n "$LIPO"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
-$as_echo "$LIPO" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_LIPO"; then
- ac_ct_LIPO=$LIPO
- # Extract the first word of "lipo", so it can be a program name with args.
-set dummy lipo; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_LIPO"; then
- ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_LIPO="lipo"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
-if test -n "$ac_ct_LIPO"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
-$as_echo "$ac_ct_LIPO" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_LIPO" = x; then
- LIPO=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- LIPO=$ac_ct_LIPO
- fi
-else
- LIPO="$ac_cv_prog_LIPO"
-fi
-
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
-set dummy ${ac_tool_prefix}otool; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_OTOOL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$OTOOL"; then
- ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-OTOOL=$ac_cv_prog_OTOOL
-if test -n "$OTOOL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
-$as_echo "$OTOOL" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_OTOOL"; then
- ac_ct_OTOOL=$OTOOL
- # Extract the first word of "otool", so it can be a program name with args.
-set dummy otool; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_OTOOL"; then
- ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_OTOOL="otool"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
-if test -n "$ac_ct_OTOOL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
-$as_echo "$ac_ct_OTOOL" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_OTOOL" = x; then
- OTOOL=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- OTOOL=$ac_ct_OTOOL
- fi
-else
- OTOOL="$ac_cv_prog_OTOOL"
-fi
-
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
-set dummy ${ac_tool_prefix}otool64; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_OTOOL64+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$OTOOL64"; then
- ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-OTOOL64=$ac_cv_prog_OTOOL64
-if test -n "$OTOOL64"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
-$as_echo "$OTOOL64" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_OTOOL64"; then
- ac_ct_OTOOL64=$OTOOL64
- # Extract the first word of "otool64", so it can be a program name with args.
-set dummy otool64; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_OTOOL64"; then
- ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_OTOOL64="otool64"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
-if test -n "$ac_ct_OTOOL64"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
-$as_echo "$ac_ct_OTOOL64" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_OTOOL64" = x; then
- OTOOL64=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- OTOOL64=$ac_ct_OTOOL64
- fi
-else
- OTOOL64="$ac_cv_prog_OTOOL64"
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
-$as_echo_n "checking for -single_module linker flag... " >&6; }
-if ${lt_cv_apple_cc_single_mod+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_apple_cc_single_mod=no
- if test -z "${LT_MULTI_MODULE}"; then
- # By default we will add the -single_module flag. You can override
- # by either setting the environment variable LT_MULTI_MODULE
- # non-empty at configure time, or by adding -multi_module to the
- # link flags.
- rm -rf libconftest.dylib*
- echo "int foo(void){return 1;}" > conftest.c
- echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
--dynamiclib -Wl,-single_module conftest.c" >&5
- $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
- -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
- _lt_result=$?
- if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
- lt_cv_apple_cc_single_mod=yes
- else
- cat conftest.err >&5
- fi
- rm -rf libconftest.dylib*
- rm -f conftest.*
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
-$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
-$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
-if ${lt_cv_ld_exported_symbols_list+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_ld_exported_symbols_list=no
- save_LDFLAGS=$LDFLAGS
- echo "_main" > conftest.sym
- LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- lt_cv_ld_exported_symbols_list=yes
-else
- lt_cv_ld_exported_symbols_list=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- LDFLAGS="$save_LDFLAGS"
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
-$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
- case $host_os in
- rhapsody* | darwin1.[012])
- _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
- darwin1.*)
- _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- darwin*) # darwin 5.x on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- 10.[012]*)
- _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- 10.*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- esac
- ;;
- esac
- if test "$lt_cv_apple_cc_single_mod" = "yes"; then
- _lt_dar_single_mod='$single_module'
- fi
- if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
- _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
- else
- _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
- fi
- if test "$DSYMUTIL" != ":"; then
- _lt_dsymutil='~$DSYMUTIL $lib || :'
- else
- _lt_dsymutil=
- fi
- ;;
- esac
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-for ac_header in dlfcn.h
-do :
- ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
-"
-if test "x$ac_cv_header_dlfcn_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DLFCN_H 1
-_ACEOF
-
-fi
-
-done
-
-
-
-# Set options
-
-
-
- enable_dlopen=no
-
-
- enable_win32_dll=no
-
-
- # Check whether --enable-shared was given.
-if test "${enable_shared+set}" = set; then :
- enableval=$enable_shared; p=${PACKAGE-default}
- case $enableval in
- yes) enable_shared=yes ;;
- no) enable_shared=no ;;
- *)
- enable_shared=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_shared=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac
-else
- enable_shared=yes
-fi
-
-
-
-
-
-
-
-
-
- # Check whether --enable-static was given.
-if test "${enable_static+set}" = set; then :
- enableval=$enable_static; p=${PACKAGE-default}
- case $enableval in
- yes) enable_static=yes ;;
- no) enable_static=no ;;
- *)
- enable_static=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_static=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac
-else
- enable_static=yes
-fi
-
-
-
-
-
-
-
-
-
-
-# Check whether --with-pic was given.
-if test "${with_pic+set}" = set; then :
- withval=$with_pic; pic_mode="$withval"
-else
- pic_mode=default
-fi
-
-
-test -z "$pic_mode" && pic_mode=default
-
-
-
-
-
-
-
- # Check whether --enable-fast-install was given.
-if test "${enable_fast_install+set}" = set; then :
- enableval=$enable_fast_install; p=${PACKAGE-default}
- case $enableval in
- yes) enable_fast_install=yes ;;
- no) enable_fast_install=no ;;
- *)
- enable_fast_install=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_fast_install=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac
-else
- enable_fast_install=yes
-fi
-
-
-
-
-
-
-
-
-
-
-
-# This can be used to rebuild libtool when needed
-LIBTOOL_DEPS="$ltmain"
-
-# Always use our own libtool.
-LIBTOOL='$(SHELL) $(top_builddir)/libtool'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-test -z "$LN_S" && LN_S="ln -s"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
-$as_echo_n "checking for objdir... " >&6; }
-if ${lt_cv_objdir+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
- lt_cv_objdir=.libs
-else
- # MS-DOS does not allow filenames that begin with a dot.
- lt_cv_objdir=_libs
-fi
-rmdir .libs 2>/dev/null
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
-$as_echo "$lt_cv_objdir" >&6; }
-objdir=$lt_cv_objdir
-
-
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define LT_OBJDIR "$lt_cv_objdir/"
-_ACEOF
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-case $host_os in
-aix3*)
- # AIX sometimes has problems with the GCC collect2 program. For some
- # reason, if we set the COLLECT_NAMES environment variable, the problems
- # vanish in a puff of smoke.
- if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
- fi
- ;;
-esac
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\(["`\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to delay expansion of an escaped single quote.
-delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-
-# Global variables:
-ofile=libtool
-can_build_shared=yes
-
-# All known linkers require a `.a' archive for static linking (except MSVC,
-# which needs '.lib').
-libext=a
-
-with_gnu_ld="$lt_cv_prog_gnu_ld"
-
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-
-# Set sane defaults for various variables
-test -z "$CC" && CC=cc
-test -z "$LTCC" && LTCC=$CC
-test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
-test -z "$LD" && LD=ld
-test -z "$ac_objext" && ac_objext=o
-
-for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
-
-# Only perform the check for file, if the check method requires it
-test -z "$MAGIC_CMD" && MAGIC_CMD=file
-case $deplibs_check_method in
-file_magic*)
- if test "$file_magic_cmd" = '$MAGIC_CMD'; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
-$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
-if ${lt_cv_path_MAGIC_CMD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $MAGIC_CMD in
-[\\/*] | ?:[\\/]*)
- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
- ;;
-*)
- lt_save_MAGIC_CMD="$MAGIC_CMD"
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
- for ac_dir in $ac_dummy; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/${ac_tool_prefix}file; then
- lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
- if test -n "$file_magic_test_file"; then
- case $deplibs_check_method in
- "file_magic "*)
- file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
- MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- $EGREP "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<_LT_EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-_LT_EOF
- fi ;;
- esac
- fi
- break
- fi
- done
- IFS="$lt_save_ifs"
- MAGIC_CMD="$lt_save_MAGIC_CMD"
- ;;
-esac
-fi
-
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
-$as_echo "$MAGIC_CMD" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-
-
-
-if test -z "$lt_cv_path_MAGIC_CMD"; then
- if test -n "$ac_tool_prefix"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
-$as_echo_n "checking for file... " >&6; }
-if ${lt_cv_path_MAGIC_CMD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $MAGIC_CMD in
-[\\/*] | ?:[\\/]*)
- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
- ;;
-*)
- lt_save_MAGIC_CMD="$MAGIC_CMD"
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
- for ac_dir in $ac_dummy; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/file; then
- lt_cv_path_MAGIC_CMD="$ac_dir/file"
- if test -n "$file_magic_test_file"; then
- case $deplibs_check_method in
- "file_magic "*)
- file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
- MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- $EGREP "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<_LT_EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-_LT_EOF
- fi ;;
- esac
- fi
- break
- fi
- done
- IFS="$lt_save_ifs"
- MAGIC_CMD="$lt_save_MAGIC_CMD"
- ;;
-esac
-fi
-
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
-$as_echo "$MAGIC_CMD" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- else
- MAGIC_CMD=:
- fi
-fi
-
- fi
- ;;
-esac
-
-# Use C for the default configuration in the libtool script
-
-lt_save_CC="$CC"
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-# Source file extension for C test sources.
-ac_ext=c
-
-# Object file extension for compiled C test sources.
-objext=o
-objext=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="int some_variable = 0;"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='int main(){return(0);}'
-
-
-
-
-
-
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-# Save the default compiler, since it gets overwritten when the other
-# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
-compiler_DEFAULT=$CC
-
-# save warnings/boilerplate of simple test code
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$RM conftest*
-
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$RM -r conftest*
-
-
-if test -n "$compiler"; then
-
-lt_prog_compiler_no_builtin_flag=
-
-if test "$GCC" = yes; then
- lt_prog_compiler_no_builtin_flag=' -fno-builtin'
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
-if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_prog_compiler_rtti_exceptions=no
- ac_outfile=conftest.$ac_objext
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="-fno-rtti -fno-exceptions"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6672: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&5
- echo "$as_me:6676: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_rtti_exceptions=yes
- fi
- fi
- $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
-$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
-
-if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
- lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
-else
- :
-fi
-
-fi
-
-
-
-
-
-
- lt_prog_compiler_wl=
-lt_prog_compiler_pic=
-lt_prog_compiler_static=
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
-$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
-
- if test "$GCC" = yes; then
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_static='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static='-Bstatic'
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- lt_prog_compiler_pic='-fPIC'
- ;;
- m68k)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
- ;;
- esac
- ;;
-
- beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
-
- mingw* | cygwin* | pw32* | os2* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- # Although the cygwin gcc ignores -fPIC, still need this for old-style
- # (--disable-auto-import) libraries
- lt_prog_compiler_pic='-DDLL_EXPORT'
- ;;
-
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- lt_prog_compiler_pic='-fno-common'
- ;;
-
- hpux*)
- # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
- # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
- # sets the default TLS model and affects inlining.
- case $host_cpu in
- hppa*64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic='-fPIC'
- ;;
- esac
- ;;
-
- interix[3-9]*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
-
- msdosdjgpp*)
- # Just because we use GCC doesn't mean we suddenly get shared libraries
- # on systems that don't support them.
- lt_prog_compiler_can_build_shared=no
- enable_shared=no
- ;;
-
- *nto* | *qnx*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- lt_prog_compiler_pic='-fPIC -shared'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- lt_prog_compiler_pic=-Kconform_pic
- fi
- ;;
-
- *)
- lt_prog_compiler_pic='-fPIC'
- ;;
- esac
- else
- # PORTME Check for flag to pass linker flags through the system compiler.
- case $host_os in
- aix*)
- lt_prog_compiler_wl='-Wl,'
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static='-Bstatic'
- else
- lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
-
- mingw* | cygwin* | pw32* | os2* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- lt_prog_compiler_pic='-DDLL_EXPORT'
- ;;
-
- hpux9* | hpux10* | hpux11*)
- lt_prog_compiler_wl='-Wl,'
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic='+Z'
- ;;
- esac
- # Is there a better lt_prog_compiler_static that works with the bundled CC?
- lt_prog_compiler_static='${wl}-a ${wl}archive'
- ;;
-
- irix5* | irix6* | nonstopux*)
- lt_prog_compiler_wl='-Wl,'
- # PIC (with -KPIC) is the default.
- lt_prog_compiler_static='-non_shared'
- ;;
-
- linux* | k*bsd*-gnu)
- case $cc_basename in
- # old Intel for x86_64 which still supported -KPIC.
- ecc*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-static'
- ;;
- # icc used to be incompatible with GCC.
- # ICC 10 doesn't accept -KPIC any more.
- icc* | ifort*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-fPIC'
- lt_prog_compiler_static='-static'
- ;;
- # Lahey Fortran 8.1.
- lf95*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='--shared'
- lt_prog_compiler_static='--static'
- ;;
- pgcc* | pgf77* | pgf90* | pgf95*)
- # Portland Group compilers (*not* the Pentium gcc compiler,
- # which looks to be a dead project)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-fpic'
- lt_prog_compiler_static='-Bstatic'
- ;;
- ccc*)
- lt_prog_compiler_wl='-Wl,'
- # All Alpha code is PIC.
- lt_prog_compiler_static='-non_shared'
- ;;
- xl*)
- # IBM XL C 8.0/Fortran 10.1 on PPC
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-qpic'
- lt_prog_compiler_static='-qstaticlink'
- ;;
- *)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*)
- # Sun C 5.9
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- lt_prog_compiler_wl='-Wl,'
- ;;
- *Sun\ F*)
- # Sun Fortran 8.3 passes all unrecognized flags to the linker
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- lt_prog_compiler_wl=''
- ;;
- esac
- ;;
- esac
- ;;
-
- newsos6)
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- *nto* | *qnx*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- lt_prog_compiler_pic='-fPIC -shared'
- ;;
-
- osf3* | osf4* | osf5*)
- lt_prog_compiler_wl='-Wl,'
- # All OSF/1 code is PIC.
- lt_prog_compiler_static='-non_shared'
- ;;
-
- rdos*)
- lt_prog_compiler_static='-non_shared'
- ;;
-
- solaris*)
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- case $cc_basename in
- f77* | f90* | f95*)
- lt_prog_compiler_wl='-Qoption ld ';;
- *)
- lt_prog_compiler_wl='-Wl,';;
- esac
- ;;
-
- sunos4*)
- lt_prog_compiler_wl='-Qoption ld '
- lt_prog_compiler_pic='-PIC'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec ;then
- lt_prog_compiler_pic='-Kconform_pic'
- lt_prog_compiler_static='-Bstatic'
- fi
- ;;
-
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- unicos*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_can_build_shared=no
- ;;
-
- uts4*)
- lt_prog_compiler_pic='-pic'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- *)
- lt_prog_compiler_can_build_shared=no
- ;;
- esac
- fi
-
-case $host_os in
- # For platforms which do not support PIC, -DPIC is meaningless:
- *djgpp*)
- lt_prog_compiler_pic=
- ;;
- *)
- lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
- ;;
-esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
-$as_echo "$lt_prog_compiler_pic" >&6; }
-
-
-
-
-
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$lt_prog_compiler_pic"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
-$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
-if ${lt_cv_prog_compiler_pic_works+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_prog_compiler_pic_works=no
- ac_outfile=conftest.$ac_objext
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7011: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&5
- echo "$as_me:7015: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_pic_works=yes
- fi
- fi
- $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
-$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
-
-if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
- case $lt_prog_compiler_pic in
- "" | " "*) ;;
- *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
- esac
-else
- lt_prog_compiler_pic=
- lt_prog_compiler_can_build_shared=no
-fi
-
-fi
-
-
-
-
-
-
-#
-# Check to make sure the static flag actually works.
-#
-wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
-if ${lt_cv_prog_compiler_static_works+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_prog_compiler_static_works=no
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
- echo "$lt_simple_link_test_code" > conftest.$ac_ext
- if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
- # The linker can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if diff conftest.exp conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_static_works=yes
- fi
- else
- lt_cv_prog_compiler_static_works=yes
- fi
- fi
- $RM -r conftest*
- LDFLAGS="$save_LDFLAGS"
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
-$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
-
-if test x"$lt_cv_prog_compiler_static_works" = xyes; then
- :
-else
- lt_prog_compiler_static=
-fi
-
-
-
-
-
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
-$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if ${lt_cv_prog_compiler_c_o+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_prog_compiler_c_o=no
- $RM -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7116: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&5
- echo "$as_me:7120: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_c_o=yes
- fi
- fi
- chmod u+w . 2>&5
- $RM conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
- $RM out/* && rmdir out
- cd ..
- $RM -r conftest
- $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
-$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
-
-
-
-
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
-$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if ${lt_cv_prog_compiler_c_o+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- lt_cv_prog_compiler_c_o=no
- $RM -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7171: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&5
- echo "$as_me:7175: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_c_o=yes
- fi
- fi
- chmod u+w . 2>&5
- $RM conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
- $RM out/* && rmdir out
- cd ..
- $RM -r conftest
- $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
-$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
-
-
-
-
-hard_links="nottested"
-if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
-$as_echo_n "checking if we can lock with hard links... " >&6; }
- hard_links=yes
- $RM conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
-$as_echo "$hard_links" >&6; }
- if test "$hard_links" = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
-$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-
-
-
-
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
-
- runpath_var=
- allow_undefined_flag=
- always_export_symbols=no
- archive_cmds=
- archive_expsym_cmds=
- compiler_needs_object=no
- enable_shared_with_static_runtimes=no
- export_dynamic_flag_spec=
- export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- hardcode_automatic=no
- hardcode_direct=no
- hardcode_direct_absolute=no
- hardcode_libdir_flag_spec=
- hardcode_libdir_flag_spec_ld=
- hardcode_libdir_separator=
- hardcode_minus_L=no
- hardcode_shlibpath_var=unsupported
- inherit_rpath=no
- link_all_deplibs=unknown
- module_cmds=
- module_expsym_cmds=
- old_archive_from_new_cmds=
- old_archive_from_expsyms_cmds=
- thread_safe_flag_spec=
- whole_archive_flag_spec=
- # include_expsyms should be a list of space-separated symbols to be *always*
- # included in the symbol list
- include_expsyms=
- # exclude_expsyms can be an extended regexp of symbols to exclude
- # it will be wrapped by ` (' and `)$', so one must not match beginning or
- # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
- # as well as any symbol that contains `d'.
- exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
- # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
- # platforms (ab)use it in PIC code, but their linkers get confused if
- # the symbol is explicitly referenced. Since portable code cannot
- # rely on this symbol name, it's probably fine to never include it in
- # preloaded symbol tables.
- # Exclude shared library initialization/finalization symbols.
- extract_expsyms_cmds=
-
- case $host_os in
- cygwin* | mingw* | pw32* | cegcc*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$GCC" != yes; then
- with_gnu_ld=no
- fi
- ;;
- interix*)
- # we just hope/assume this is gcc and not c89 (= MSVC++)
- with_gnu_ld=yes
- ;;
- openbsd*)
- with_gnu_ld=no
- ;;
- esac
-
- ld_shlibs=yes
- if test "$with_gnu_ld" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # Set some defaults for GNU ld with shared library support. These
- # are reset later if shared libraries are not supported. Putting them
- # here allows them to be overridden if necessary.
- runpath_var=LD_RUN_PATH
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- export_dynamic_flag_spec='${wl}--export-dynamic'
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
- whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- whole_archive_flag_spec=
- fi
- supports_anon_versioning=no
- case `$LD -v 2>&1` in
- *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
- *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
- *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
- *\ 2.11.*) ;; # other 2.11 versions
- *) supports_anon_versioning=yes ;;
- esac
-
- # See if GNU ld supports shared libraries.
- case $host_os in
- aix[3-9]*)
- # On AIX/PPC, the GNU linker is very broken
- if test "$host_cpu" != ia64; then
- ld_shlibs=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-_LT_EOF
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds=''
- ;;
- m68k)
- archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- ;;
- esac
- ;;
-
- beos*)
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- allow_undefined_flag=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- cygwin* | mingw* | pw32* | cegcc*)
- # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
- # as there is no search path for DLLs.
- hardcode_libdir_flag_spec='-L$libdir'
- allow_undefined_flag=unsupported
- always_export_symbols=no
- enable_shared_with_static_runtimes=yes
- export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
-
- if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- interix[3-9]*)
- hardcode_direct=no
- hardcode_shlibpath_var=no
- hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
- export_dynamic_flag_spec='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
-
- gnu* | linux* | tpf* | k*bsd*-gnu)
- tmp_diet=no
- if test "$host_os" = linux-dietlibc; then
- case $cc_basename in
- diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
- esac
- fi
- if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
- && test "$tmp_diet" = no
- then
- tmp_addflag=
- tmp_sharedflag='-shared'
- case $cc_basename,$host_cpu in
- pgcc*) # Portland Group C compiler
- whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag'
- ;;
- pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
- whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag -Mnomain' ;;
- ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
- tmp_addflag=' -i_dynamic' ;;
- efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
- tmp_addflag=' -i_dynamic -nofor_main' ;;
- ifc* | ifort*) # Intel Fortran compiler
- tmp_addflag=' -nofor_main' ;;
- lf95*) # Lahey Fortran 8.1
- whole_archive_flag_spec=
- tmp_sharedflag='--shared' ;;
- xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
- tmp_sharedflag='-qmkshrobj'
- tmp_addflag= ;;
- esac
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*) # Sun C 5.9
- whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
- compiler_needs_object=yes
- tmp_sharedflag='-G' ;;
- *Sun\ F*) # Sun Fortran 8.3
- tmp_sharedflag='-G' ;;
- esac
- archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-
- if test "x$supports_anon_versioning" = xyes; then
- archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
-
- case $cc_basename in
- xlf*)
- # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
- whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
- hardcode_libdir_flag_spec=
- hardcode_libdir_flag_spec_ld='-rpath $libdir'
- archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
- if test "x$supports_anon_versioning" = xyes; then
- archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- echo "local: *; };" >> $output_objdir/$libname.ver~
- $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
- fi
- ;;
- esac
- else
- ld_shlibs=no
- fi
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
- wlarc=
- else
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- fi
- ;;
-
- solaris*)
- if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
- ld_shlibs=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
- case `$LD -v 2>&1` in
- *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
- ld_shlibs=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
-*** reliably create shared libraries on SCO systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- ;;
- *)
- # For security reasons, it is highly recommended that you always
- # use absolute paths for naming shared libraries, and exclude the
- # DT_RUNPATH tag from executables and libraries. But doing so
- # requires that you compile everything twice, which is a pain.
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
- esac
- ;;
-
- sunos4*)
- archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- wlarc=
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- *)
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
- esac
-
- if test "$ld_shlibs" = no; then
- runpath_var=
- hardcode_libdir_flag_spec=
- export_dynamic_flag_spec=
- whole_archive_flag_spec=
- fi
- else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case $host_os in
- aix3*)
- allow_undefined_flag=unsupported
- always_export_symbols=yes
- archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- hardcode_minus_L=yes
- if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- hardcode_direct=unsupported
- fi
- ;;
-
- aix[4-9]*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
- export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- else
- export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- fi
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
- for ld_flag in $LDFLAGS; do
- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
- aix_use_runtimelinking=yes
- break
- fi
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- archive_cmds=''
- hardcode_direct=yes
- hardcode_direct_absolute=yes
- hardcode_libdir_separator=':'
- link_all_deplibs=yes
- file_list_spec='${wl}-f,'
-
- if test "$GCC" = yes; then
- case $host_os in aix4.[012]|aix4.[012].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" &&
- strings "$collect2name" | $GREP resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- :
- else
- # We have old collect2
- hardcode_direct=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- hardcode_minus_L=yes
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_libdir_separator=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- export_dynamic_flag_spec='${wl}-bexpall'
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- always_export_symbols=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- allow_undefined_flag='-berok'
- # Determine the default libpath from the value encoded in an
- # empty executable.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-
-lt_aix_libpath_sed='
- /Import File Strings/,/^$/ {
- /^0/ {
- s/^0 *\(.*\)$/\1/
- p
- }
- }'
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then
- aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-fi
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
- archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
- allow_undefined_flag="-z nodefs"
- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an
- # empty executable.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-
-lt_aix_libpath_sed='
- /Import File Strings/,/^$/ {
- /^0/ {
- s/^0 *\(.*\)$/\1/
- p
- }
- }'
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then
- aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-fi
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- no_undefined_flag=' ${wl}-bernotok'
- allow_undefined_flag=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- whole_archive_flag_spec='$convenience'
- archive_cmds_need_lc=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds=''
- ;;
- m68k)
- archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- ;;
- esac
- ;;
-
- bsdi[45]*)
- export_dynamic_flag_spec=-rdynamic
- ;;
-
- cygwin* | mingw* | pw32* | cegcc*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- hardcode_libdir_flag_spec=' '
- allow_undefined_flag=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- old_archive_from_new_cmds='true'
- # FIXME: Should let the user specify the lib program.
- old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
- fix_srcfile_path='`cygpath -w "$srcfile"`'
- enable_shared_with_static_runtimes=yes
- ;;
-
- darwin* | rhapsody*)
-
-
- archive_cmds_need_lc=no
- hardcode_direct=no
- hardcode_automatic=yes
- hardcode_shlibpath_var=unsupported
- whole_archive_flag_spec=''
- link_all_deplibs=yes
- allow_undefined_flag="$_lt_dar_allow_undefined"
- case $cc_basename in
- ifort*) _lt_dar_can_shared=yes ;;
- *) _lt_dar_can_shared=$GCC ;;
- esac
- if test "$_lt_dar_can_shared" = "yes"; then
- output_verbose_link_cmd=echo
- archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
- module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
- archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
- module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
-
- else
- ld_shlibs=no
- fi
-
- ;;
-
- dgux*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_shlibpath_var=no
- ;;
-
- freebsd1*)
- ld_shlibs=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct=yes
- hardcode_minus_L=yes
- hardcode_shlibpath_var=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd* | dragonfly*)
- archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- hpux9*)
- if test "$GCC" = yes; then
- archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- fi
- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator=:
- hardcode_direct=yes
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L=yes
- export_dynamic_flag_spec='${wl}-E'
- ;;
-
- hpux10*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
- fi
- if test "$with_gnu_ld" = no; then
- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
- hardcode_libdir_flag_spec_ld='+b $libdir'
- hardcode_libdir_separator=:
- hardcode_direct=yes
- hardcode_direct_absolute=yes
- export_dynamic_flag_spec='${wl}-E'
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L=yes
- fi
- ;;
-
- hpux11*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- case $host_cpu in
- hppa*64*)
- archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- else
- case $host_cpu in
- hppa*64*)
- archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- fi
- if test "$with_gnu_ld" = no; then
- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- hardcode_direct=no
- hardcode_shlibpath_var=no
- ;;
- *)
- hardcode_direct=yes
- hardcode_direct_absolute=yes
- export_dynamic_flag_spec='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L=yes
- ;;
- esac
- fi
- ;;
-
- irix5* | irix6* | nonstopux*)
- if test "$GCC" = yes; then
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- # Try to use the -exported_symbol ld option, if it does not
- # work, assume that -exports_file does not work either and
- # implicitly export all symbols.
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-int foo(void) {}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
-
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- LDFLAGS="$save_LDFLAGS"
- else
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
- fi
- archive_cmds_need_lc='no'
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- inherit_rpath=yes
- link_all_deplibs=yes
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
- else
- archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
- fi
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- newsos6)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct=yes
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- hardcode_shlibpath_var=no
- ;;
-
- *nto* | *qnx*)
- ;;
-
- openbsd*)
- if test -f /usr/libexec/ld.so; then
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- hardcode_direct_absolute=yes
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
- hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
- export_dynamic_flag_spec='${wl}-E'
- else
- case $host_os in
- openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec='-R$libdir'
- ;;
- *)
- archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
- ;;
- esac
- fi
- else
- ld_shlibs=no
- fi
- ;;
-
- os2*)
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- allow_undefined_flag=unsupported
- archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
- old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$GCC" = yes; then
- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- allow_undefined_flag=' -expect_unresolved \*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
- fi
- archive_cmds_need_lc='no'
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- ;;
-
- osf4* | osf5*) # as osf3* with the addition of -msym flag
- if test "$GCC" = yes; then
- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- else
- allow_undefined_flag=' -expect_unresolved \*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
- archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
- $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
-
- # Both c and cxx compiler support -rpath directly
- hardcode_libdir_flag_spec='-rpath $libdir'
- fi
- archive_cmds_need_lc='no'
- hardcode_libdir_separator=:
- ;;
-
- solaris*)
- no_undefined_flag=' -z defs'
- if test "$GCC" = yes; then
- wlarc='${wl}'
- archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
- else
- case `$CC -V 2>&1` in
- *"Compilers 5.0"*)
- wlarc=''
- archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
- archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
- ;;
- *)
- wlarc='${wl}'
- archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
- ;;
- esac
- fi
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_shlibpath_var=no
- case $host_os in
- solaris2.[0-5] | solaris2.[0-5].*) ;;
- *)
- # The compiler driver will combine and reorder linker options,
- # but understands `-z linker_flag'. GCC discards it without `$wl',
- # but is careful enough not to reorder.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- if test "$GCC" = yes; then
- whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
- else
- whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
- fi
- ;;
- esac
- link_all_deplibs=yes
- ;;
-
- sunos4*)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
- fi
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_direct=yes
- hardcode_minus_L=yes
- hardcode_shlibpath_var=no
- ;;
-
- sysv4)
- case $host_vendor in
- sni)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct=yes # is this really true???
- ;;
- siemens)
- ## LD is ld it makes a PLAMLIB
- ## CC just makes a GrossModule.
- archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
- reload_cmds='$CC -r -o $output$reload_objs'
- hardcode_direct=no
- ;;
- motorola)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct=no #Motorola manual says yes, but my tests say they lie
- ;;
- esac
- runpath_var='LD_RUN_PATH'
- hardcode_shlibpath_var=no
- ;;
-
- sysv4.3*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_shlibpath_var=no
- export_dynamic_flag_spec='-Bexport'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_shlibpath_var=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- ld_shlibs=yes
- fi
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
- no_undefined_flag='${wl}-z,text'
- archive_cmds_need_lc=no
- hardcode_shlibpath_var=no
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- no_undefined_flag='${wl}-z,text'
- allow_undefined_flag='${wl}-z,nodefs'
- archive_cmds_need_lc=no
- hardcode_shlibpath_var=no
- hardcode_libdir_flag_spec='${wl}-R,$libdir'
- hardcode_libdir_separator=':'
- link_all_deplibs=yes
- export_dynamic_flag_spec='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- uts4*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_shlibpath_var=no
- ;;
-
- *)
- ld_shlibs=no
- ;;
- esac
-
- if test x$host_vendor = xsni; then
- case $host in
- sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
- export_dynamic_flag_spec='${wl}-Blargedynsym'
- ;;
- esac
- fi
- fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
-$as_echo "$ld_shlibs" >&6; }
-test "$ld_shlibs" = no && can_build_shared=no
-
-with_gnu_ld=$with_gnu_ld
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$archive_cmds_need_lc" in
-x|xyes)
- # Assume -lc should be added
- archive_cmds_need_lc=yes
-
- if test "$enable_shared" = yes && test "$GCC" = yes; then
- case $archive_cmds in
- *'~'*)
- # FIXME: we may have to deal with multi-command sequences.
- ;;
- '$CC '*)
- # Test whether the compiler implicitly links with -lc since on some
- # systems, -lgcc has to come before -lc. If gcc already passes -lc
- # to ld, don't add -lc before -lgcc.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
-$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
- $RM conftest*
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } 2>conftest.err; then
- soname=conftest
- lib=conftest
- libobjs=conftest.$ac_objext
- deplibs=
- wl=$lt_prog_compiler_wl
- pic_flag=$lt_prog_compiler_pic
- compiler_flags=-v
- linker_flags=-v
- verstring=
- output_objdir=.
- libname=conftest
- lt_save_allow_undefined_flag=$allow_undefined_flag
- allow_undefined_flag=
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
- (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }
- then
- archive_cmds_need_lc=no
- else
- archive_cmds_need_lc=yes
- fi
- allow_undefined_flag=$lt_save_allow_undefined_flag
- else
- cat conftest.err 1>&5
- fi
- $RM conftest*
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5
-$as_echo "$archive_cmds_need_lc" >&6; }
- ;;
- esac
- fi
- ;;
-esac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
-$as_echo_n "checking dynamic linker characteristics... " >&6; }
-
-if test "$GCC" = yes; then
- case $host_os in
- darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
- *) lt_awk_arg="/^libraries:/" ;;
- esac
- lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
- # if the path contains ";" then we assume it to be the separator
- # otherwise default to the standard path separator (i.e. ":") - it is
- # assumed that no part of a normal pathname contains ";" but that should
- # okay in the real world where ";" in dirpaths is itself problematic.
- lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
- else
- lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- # Ok, now we have the path, separated by spaces, we can step through it
- # and add multilib dir if necessary.
- lt_tmp_lt_search_path_spec=
- lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
- for lt_sys_path in $lt_search_path_spec; do
- if test -d "$lt_sys_path/$lt_multi_os_dir"; then
- lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
- else
- test -d "$lt_sys_path" && \
- lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
- fi
- done
- lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
-BEGIN {RS=" "; FS="/|\n";} {
- lt_foo="";
- lt_count=0;
- for (lt_i = NF; lt_i > 0; lt_i--) {
- if ($lt_i != "" && $lt_i != ".") {
- if ($lt_i == "..") {
- lt_count++;
- } else {
- if (lt_count == 0) {
- lt_foo="/" $lt_i lt_foo;
- } else {
- lt_count--;
- }
- }
- }
- }
- if (lt_foo != "") { lt_freq[lt_foo]++; }
- if (lt_freq[lt_foo] == 1) { print lt_foo; }
-}'`
- sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
-else
- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX 3 has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
-
-aix[4-9]*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- hardcode_into_libs=yes
- if test "$host_cpu" = ia64; then
- # AIX 5 supports IA64
- library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- else
- # With GCC up to 2.95.x, collect2 would create an import file
- # for dependence libraries. The import file would start with
- # the line `#! .'. This would cause the generated library to
- # depend on `.', always an invalid library. This was fixed in
- # development snapshots of GCC prior to 3.0.
- case $host_os in
- aix4 | aix4.[01] | aix4.[01].*)
- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
- echo ' yes '
- echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
- :
- else
- can_build_shared=no
- fi
- ;;
- esac
- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- if test "$aix_use_runtimelinking" = yes; then
- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
- # instead of lib<name>.a to let people know that these are not
- # typical AIX shared libraries.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- else
- # We preserve .a as extension for shared libraries through AIX4.2
- # and later when we are not doing run time linking.
- library_names_spec='${libname}${release}.a $libname.a'
- soname_spec='${libname}${release}${shared_ext}$major'
- fi
- shlibpath_var=LIBPATH
- fi
- ;;
-
-amigaos*)
- case $host_cpu in
- powerpc)
- # Since July 2007 AmigaOS4 officially supports .so libraries.
- # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- ;;
- m68k)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
- ;;
- esac
- ;;
-
-beos*)
- library_names_spec='${libname}${shared_ext}'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- ;;
-
-bsdi[45]*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw* | pw32* | cegcc*)
- version_type=windows
- shrext_cmds=".dll"
- need_version=no
- need_lib_prefix=no
-
- case $GCC,$host_os in
- yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
- library_names_spec='$libname.dll.a'
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname~
- chmod a+x \$dldir/$dlname~
- if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
- eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
- fi'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $RM \$dlpath'
- shlibpath_overrides_runpath=yes
-
- case $host_os in
- cygwin*)
- # Cygwin DLLs use 'cyg' prefix rather than 'lib'
- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
- ;;
- mingw* | cegcc*)
- # MinGW DLLs use traditional 'lib' prefix
- soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
- # It is most probably a Windows format PATH printed by
- # mingw gcc, but we are running on Cygwin. Gcc prints its search
- # path with ; separators, and with drive letters. We can handle the
- # drive letters (cygwin fileutils understands them), so leave them,
- # especially as we might pass files found there to a mingw objdump,
- # which wouldn't understand a cygwinified path. Ahh.
- sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- ;;
- pw32*)
- # pw32 DLLs use 'pw' prefix rather than 'lib'
- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- ;;
- esac
- ;;
-
- *)
- library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
- ;;
- esac
- dynamic_linker='Win32 ld.exe'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- ;;
-
-darwin* | rhapsody*)
- dynamic_linker="$host_os dyld"
- version_type=darwin
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
- soname_spec='${libname}${release}${major}$shared_ext'
- shlibpath_overrides_runpath=yes
- shlibpath_var=DYLD_LIBRARY_PATH
- shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
-
- sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
- sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-freebsd* | dragonfly*)
- # DragonFly does not have aout. When/if they implement a new
- # versioning mechanism, adjust this.
- if test -x /usr/bin/objformat; then
- objformat=`/usr/bin/objformat`
- else
- case $host_os in
- freebsd[123]*) objformat=aout ;;
- *) objformat=elf ;;
- esac
- fi
- # Handle Gentoo/FreeBSD as it was Linux
- case $host_vendor in
- gentoo)
- version_type=linux ;;
- *)
- version_type=freebsd-$objformat ;;
- esac
-
- case $version_type in
- freebsd-elf*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
- need_version=yes
- ;;
- linux)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- need_lib_prefix=no
- need_version=no
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case $host_os in
- freebsd2*)
- shlibpath_overrides_runpath=yes
- ;;
- freebsd3.[01]* | freebsdelf3.[01]*)
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
- freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
- *) # from 4.6 on, and DragonFly
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- case $host_cpu in
- ia64*)
- shrext_cmds='.so'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.so"
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- if test "X$HPUX_IA64_MODE" = X32; then
- sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
- else
- sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
- fi
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- hppa*64*)
- shrext_cmds='.sl'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- *)
- shrext_cmds='.sl'
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
- esac
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
- ;;
-
-interix[3-9]*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $host_os in
- nonstopux*) version_type=nonstopux ;;
- *)
- if test "$lt_cv_prog_gnu_ld" = yes; then
- version_type=linux
- else
- version_type=irix
- fi ;;
- esac
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
- case $host_os in
- irix5* | nonstopux*)
- libsuff= shlibsuff=
- ;;
- *)
- case $LD in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
- libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
- libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
- libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- hardcode_into_libs=yes
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux* | k*bsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- # Some binutils ld are patched to set DT_RUNPATH
- save_LDFLAGS=$LDFLAGS
- save_libdir=$libdir
- eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
- LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
- shlibpath_overrides_runpath=yes
-fi
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- LDFLAGS=$save_LDFLAGS
- libdir=$save_libdir
-
- # This implies no fast_install, which is unacceptable.
- # Some rework will be needed to allow for fast_install
- # before this can be enabled.
- hardcode_into_libs=yes
-
- # Append ld.so.conf contents to the search path
- if test -f /etc/ld.so.conf; then
- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
- sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
- fi
-
- # We used to test for /lib/ld.so.1 and disable shared libraries on
- # powerpc, because MkLinux only supported shared libraries with the
- # GNU dynamic linker. Since this was broken with cross compilers,
- # most powerpc-linux boxes support dynamic linking these days and
- # people can always --disable-shared, the test was removed, and we
- # assume the GNU/Linux dynamic linker is in use.
- dynamic_linker='GNU/Linux ld.so'
- ;;
-
-netbsd*)
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
-
-newsos6)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-*nto* | *qnx*)
- version_type=qnx
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='ldqnx.so'
- ;;
-
-openbsd*)
- version_type=sunos
- sys_lib_dlsearch_path_spec="/usr/lib"
- need_lib_prefix=no
- # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
- case $host_os in
- openbsd3.3 | openbsd3.3.*) need_version=yes ;;
- *) need_version=no ;;
- esac
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- case $host_os in
- openbsd2.[89] | openbsd2.[89].*)
- shlibpath_overrides_runpath=no
- ;;
- *)
- shlibpath_overrides_runpath=yes
- ;;
- esac
- else
- shlibpath_overrides_runpath=yes
- fi
- ;;
-
-os2*)
- libname_spec='$name'
- shrext_cmds=".dll"
- need_lib_prefix=no
- library_names_spec='$libname${shared_ext} $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-rdos*)
- dynamic_linker=no
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- case $host_vendor in
- sni)
- shlibpath_overrides_runpath=no
- need_lib_prefix=no
- runpath_var=LD_RUN_PATH
- ;;
- siemens)
- need_lib_prefix=no
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- ;;
- esac
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
- soname_spec='$libname${shared_ext}.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- version_type=freebsd-elf
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- if test "$with_gnu_ld" = yes; then
- sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
- else
- sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
- case $host_os in
- sco3.2v5*)
- sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
- ;;
- esac
- fi
- sys_lib_dlsearch_path_spec='/usr/lib'
- ;;
-
-tpf*)
- # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
-$as_echo "$dynamic_linker" >&6; }
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-
-if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
- sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
-fi
-if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
- sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
-$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" ||
- test -n "$runpath_var" ||
- test "X$hardcode_automatic" = "Xyes" ; then
-
- # We can hardcode non-existent directories.
- if test "$hardcode_direct" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
- test "$hardcode_minus_L" != no; then
- # Linking always hardcodes the temporary library directory.
- hardcode_action=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- hardcode_action=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- hardcode_action=unsupported
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
-$as_echo "$hardcode_action" >&6; }
-
-if test "$hardcode_action" = relink ||
- test "$inherit_rpath" = yes; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-
-
-
-
-
-
- if test "x$enable_dlopen" != xyes; then
- enable_dlopen=unknown
- enable_dlopen_self=unknown
- enable_dlopen_self_static=unknown
-else
- lt_cv_dlopen=no
- lt_cv_dlopen_libs=
-
- case $host_os in
- beos*)
- lt_cv_dlopen="load_add_on"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ;;
-
- mingw* | pw32* | cegcc*)
- lt_cv_dlopen="LoadLibrary"
- lt_cv_dlopen_libs=
- ;;
-
- cygwin*)
- lt_cv_dlopen="dlopen"
- lt_cv_dlopen_libs=
- ;;
-
- darwin*)
- # if libdl is installed we need to link against it
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
-$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if ${ac_cv_lib_dl_dlopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_dl_dlopen=yes
-else
- ac_cv_lib_dl_dlopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
-$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
-
- lt_cv_dlopen="dyld"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
-
-fi
-
- ;;
-
- *)
- ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
-if test "x$ac_cv_func_shl_load" = xyes; then :
- lt_cv_dlopen="shl_load"
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
-$as_echo_n "checking for shl_load in -ldld... " >&6; }
-if ${ac_cv_lib_dld_shl_load+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldld $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load ();
-int
-main ()
-{
-return shl_load ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_dld_shl_load=yes
-else
- ac_cv_lib_dld_shl_load=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
-$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
-if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
- lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
-else
- ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
-if test "x$ac_cv_func_dlopen" = xyes; then :
- lt_cv_dlopen="dlopen"
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
-$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if ${ac_cv_lib_dl_dlopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_dl_dlopen=yes
-else
- ac_cv_lib_dl_dlopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
-$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
-$as_echo_n "checking for dlopen in -lsvld... " >&6; }
-if ${ac_cv_lib_svld_dlopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsvld $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_svld_dlopen=yes
-else
- ac_cv_lib_svld_dlopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
-$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
-if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
-$as_echo_n "checking for dld_link in -ldld... " >&6; }
-if ${ac_cv_lib_dld_dld_link+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldld $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dld_link ();
-int
-main ()
-{
-return dld_link ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_dld_dld_link=yes
-else
- ac_cv_lib_dld_dld_link=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
-$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
-if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
- lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
- ;;
- esac
-
- if test "x$lt_cv_dlopen" != xno; then
- enable_dlopen=yes
- else
- enable_dlopen=no
- fi
-
- case $lt_cv_dlopen in
- dlopen)
- save_CPPFLAGS="$CPPFLAGS"
- test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-
- save_LDFLAGS="$LDFLAGS"
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-
- save_LIBS="$LIBS"
- LIBS="$lt_cv_dlopen_libs $LIBS"
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
-$as_echo_n "checking whether a program can dlopen itself... " >&6; }
-if ${lt_cv_dlopen_self+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
- lt_cv_dlopen_self=cross
-else
- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
- lt_status=$lt_dlunknown
- cat > conftest.$ac_ext <<_LT_EOF
-#line 9551 "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LT_DLGLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LT_DLGLOBAL DL_GLOBAL
-# else
-# define LT_DLGLOBAL 0
-# endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LT_DLLAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LT_DLLAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LT_DLLAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LT_DLLAZY_OR_NOW DL_NOW
-# else
-# define LT_DLLAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-void fnord() { int i=42;}
-int main ()
-{
- void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
- int status = $lt_dlunknown;
-
- if (self)
- {
- if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
- else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
- /* dlclose (self); */
- }
- else
- puts (dlerror ());
-
- return status;
-}
-_LT_EOF
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
- (./conftest; exit; ) >&5 2>/dev/null
- lt_status=$?
- case x$lt_status in
- x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
- x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
- x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
- esac
- else :
- # compilation failed
- lt_cv_dlopen_self=no
- fi
-fi
-rm -fr conftest*
-
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
-$as_echo "$lt_cv_dlopen_self" >&6; }
-
- if test "x$lt_cv_dlopen_self" = xyes; then
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
-$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
-if ${lt_cv_dlopen_self_static+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
- lt_cv_dlopen_self_static=cross
-else
- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
- lt_status=$lt_dlunknown
- cat > conftest.$ac_ext <<_LT_EOF
-#line 9647 "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LT_DLGLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LT_DLGLOBAL DL_GLOBAL
-# else
-# define LT_DLGLOBAL 0
-# endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LT_DLLAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LT_DLLAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LT_DLLAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LT_DLLAZY_OR_NOW DL_NOW
-# else
-# define LT_DLLAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-void fnord() { int i=42;}
-int main ()
-{
- void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
- int status = $lt_dlunknown;
-
- if (self)
- {
- if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
- else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
- /* dlclose (self); */
- }
- else
- puts (dlerror ());
-
- return status;
-}
-_LT_EOF
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
- (./conftest; exit; ) >&5 2>/dev/null
- lt_status=$?
- case x$lt_status in
- x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
- x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
- x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
- esac
- else :
- # compilation failed
- lt_cv_dlopen_self_static=no
- fi
-fi
-rm -fr conftest*
-
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
-$as_echo "$lt_cv_dlopen_self_static" >&6; }
- fi
-
- CPPFLAGS="$save_CPPFLAGS"
- LDFLAGS="$save_LDFLAGS"
- LIBS="$save_LIBS"
- ;;
- esac
-
- case $lt_cv_dlopen_self in
- yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
- *) enable_dlopen_self=unknown ;;
- esac
-
- case $lt_cv_dlopen_self_static in
- yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
- *) enable_dlopen_self_static=unknown ;;
- esac
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-striplib=
-old_striplib=
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
-$as_echo_n "checking whether stripping libraries is possible... " >&6; }
-if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
- test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
- test -z "$striplib" && striplib="$STRIP --strip-unneeded"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
-# FIXME - insert some real tests, host_os isn't really good enough
- case $host_os in
- darwin*)
- if test -n "$STRIP" ; then
- striplib="$STRIP -x"
- old_striplib="$STRIP -S"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
- ;;
- *)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- ;;
- esac
-fi
-
-
-
-
-
-
-
-
-
-
-
-
- # Report which library types will actually be built
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
-$as_echo_n "checking if libtool supports shared libraries... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
-$as_echo "$can_build_shared" >&6; }
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
-$as_echo_n "checking whether to build shared libraries... " >&6; }
- test "$can_build_shared" = "no" && enable_shared=no
-
- # On AIX, shared libraries and static libraries use the same namespace, and
- # are all built from PIC.
- case $host_os in
- aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-
- aix[4-9]*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
- esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
-$as_echo "$enable_shared" >&6; }
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
-$as_echo_n "checking whether to build static libraries... " >&6; }
- # Make sure either enable_shared or enable_static is yes.
- test "$enable_shared" = yes || enable_static=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
-$as_echo "$enable_static" >&6; }
-
-
-
-
-fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-CC="$lt_save_CC"
-
-
-
-
-
-
-
-
-
-
-
-
-
- ac_config_commands="$ac_config_commands libtool"
-
-
-
-
-# Only expand once:
-
-
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
-if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- rm -rf conftest.one conftest.two conftest.dir
- echo one > conftest.one
- echo two > conftest.two
- mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
- test -s conftest.one && test -s conftest.two &&
- test -s conftest.dir/conftest.one &&
- test -s conftest.dir/conftest.two
- then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- fi
- done
- done
- ;;
-esac
-
- done
-IFS=$as_save_IFS
-
-rm -rf conftest.one conftest.two conftest.dir
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL=$ac_cv_path_install
- else
- # As a last resort, use the slow shell script. Don't cache a
- # value for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the value is a relative name.
- INSTALL=$ac_install_sh
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-
-#########
-# Enable large file support (if special flags are necessary)
-#
-# Check whether --enable-largefile was given.
-if test "${enable_largefile+set}" = set; then :
- enableval=$enable_largefile;
-fi
-
-if test "$enable_largefile" != no; then
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
-$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
-if ${ac_cv_sys_largefile_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_sys_largefile_CC=no
- if test "$GCC" != yes; then
- ac_save_CC=$CC
- while :; do
- # IRIX 6.2 and later do not support large files by default,
- # so use the C compiler's -n32 option if that helps.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
- if ac_fn_c_try_compile "$LINENO"; then :
- break
-fi
-rm -f core conftest.err conftest.$ac_objext
- CC="$CC -n32"
- if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_sys_largefile_CC=' -n32'; break
-fi
-rm -f core conftest.err conftest.$ac_objext
- break
- done
- CC=$ac_save_CC
- rm -f conftest.$ac_ext
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
-$as_echo "$ac_cv_sys_largefile_CC" >&6; }
- if test "$ac_cv_sys_largefile_CC" != no; then
- CC=$CC$ac_cv_sys_largefile_CC
- fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
-$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
-if ${ac_cv_sys_file_offset_bits+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- while :; do
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_sys_file_offset_bits=no; break
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#define _FILE_OFFSET_BITS 64
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_sys_file_offset_bits=64; break
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_cv_sys_file_offset_bits=unknown
- break
-done
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
-$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
-case $ac_cv_sys_file_offset_bits in #(
- no | unknown) ;;
- *)
-cat >>confdefs.h <<_ACEOF
-#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
-_ACEOF
-;;
-esac
-rm -rf conftest*
- if test $ac_cv_sys_file_offset_bits = unknown; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
-$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
-if ${ac_cv_sys_large_files+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- while :; do
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_sys_large_files=no; break
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#define _LARGE_FILES 1
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_sys_large_files=1; break
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_cv_sys_large_files=unknown
- break
-done
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
-$as_echo "$ac_cv_sys_large_files" >&6; }
-case $ac_cv_sys_large_files in #(
- no | unknown) ;;
- *)
-cat >>confdefs.h <<_ACEOF
-#define _LARGE_FILES $ac_cv_sys_large_files
-_ACEOF
-;;
-esac
-rm -rf conftest*
- fi
-
-
-fi
-
-
-#########
-# Check for needed/wanted data types
-ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default"
-if test "x$ac_cv_type_int8_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT8_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default"
-if test "x$ac_cv_type_int16_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT16_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default"
-if test "x$ac_cv_type_int32_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT32_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default"
-if test "x$ac_cv_type_int64_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT64_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default"
-if test "x$ac_cv_type_intptr_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INTPTR_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default"
-if test "x$ac_cv_type_uint8_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT8_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default"
-if test "x$ac_cv_type_uint16_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT16_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default"
-if test "x$ac_cv_type_uint32_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT32_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default"
-if test "x$ac_cv_type_uint64_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT64_T 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
-if test "x$ac_cv_type_uintptr_t" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINTPTR_T 1
-_ACEOF
-
-
-fi
-
-
-#########
-# Check for needed/wanted headers
-for ac_header in sys/types.h stdlib.h stdint.h inttypes.h malloc.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-#########
-# Figure out whether or not we have these functions
-#
-for ac_func in fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-#########
-# By default, we use the amalgamation (this may be changed below...)
-#
-USE_AMALGAMATION=1
-
-#########
-# See whether we can run specific tclsh versions known to work well;
-# if not, then we fall back to plain tclsh.
-# TODO: try other versions before falling back?
-#
-for ac_prog in tclsh8.7 tclsh8.6 tclsh8.5 tclsh
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_TCLSH_CMD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$TCLSH_CMD"; then
- ac_cv_prog_TCLSH_CMD="$TCLSH_CMD" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_TCLSH_CMD="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-TCLSH_CMD=$ac_cv_prog_TCLSH_CMD
-if test -n "$TCLSH_CMD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_CMD" >&5
-$as_echo "$TCLSH_CMD" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$TCLSH_CMD" && break
-done
-test -n "$TCLSH_CMD" || TCLSH_CMD="none"
-
-if test "$TCLSH_CMD" = "none"; then
- # If we can't find a local tclsh, then building the amalgamation will fail.
- # We act as though --disable-amalgamation has been used.
- echo "Warning: can't find tclsh - defaulting to non-amalgamation build."
- USE_AMALGAMATION=0
- TCLSH_CMD="tclsh"
-fi
-
-
-
-if test "x${TCLLIBDIR+set}" != "xset" ; then
- TCLLIBDIR='$(libdir)'
- for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
- TCLLIBDIR=$i
- break
- done
- TCLLIBDIR="${TCLLIBDIR}/sqlite3"
-fi
-
-
-#########
-# Set up an appropriate program prefix
-#
-if test "$program_prefix" = "NONE"; then
- program_prefix=""
-fi
-
-
-VERSION=`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: Version set to $VERSION" >&5
-$as_echo "$as_me: Version set to $VERSION" >&6;}
-
-RELEASE=`cat $srcdir/VERSION`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: Release set to $RELEASE" >&5
-$as_echo "$as_me: Release set to $RELEASE" >&6;}
-
-VERSION_NUMBER=`cat $srcdir/VERSION \
- | sed 's/[^0-9]/ /g' \
- | awk '{printf "%d%03d%03d",$1,$2,$3}'`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: Version number set to $VERSION_NUMBER" >&5
-$as_echo "$as_me: Version number set to $VERSION_NUMBER" >&6;}
-
-
-#########
-# Locate a compiler for the build machine. This compiler should
-# generate command-line programs that run on the build machine.
-#
-if test x"$cross_compiling" = xno; then
- BUILD_CC=$CC
- BUILD_CFLAGS=$CFLAGS
-else
- if test "${BUILD_CC+set}" != set; then
- for ac_prog in gcc cc cl
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_BUILD_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$BUILD_CC"; then
- ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_BUILD_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-BUILD_CC=$ac_cv_prog_BUILD_CC
-if test -n "$BUILD_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5
-$as_echo "$BUILD_CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$BUILD_CC" && break
-done
-
- fi
- if test "${BUILD_CFLAGS+set}" != set; then
- BUILD_CFLAGS="-g"
- fi
-fi
-
-
-##########
-# Do we want to support multithreaded use of sqlite
-#
-# Check whether --enable-threadsafe was given.
-if test "${enable_threadsafe+set}" = set; then :
- enableval=$enable_threadsafe;
-else
- enable_threadsafe=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support threadsafe operation" >&5
-$as_echo_n "checking whether to support threadsafe operation... " >&6; }
-if test "$enable_threadsafe" = "no"; then
- SQLITE_THREADSAFE=0
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-else
- SQLITE_THREADSAFE=1
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-
-
-if test "$SQLITE_THREADSAFE" = "1"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
-$as_echo_n "checking for library containing pthread_create... " >&6; }
-if ${ac_cv_search_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pthread_create ();
-int
-main ()
-{
-return pthread_create ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' pthread; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_pthread_create=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_pthread_create+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_pthread_create+:} false; then :
-
-else
- ac_cv_search_pthread_create=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5
-$as_echo "$ac_cv_search_pthread_create" >&6; }
-ac_res=$ac_cv_search_pthread_create
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_mutexattr_init" >&5
-$as_echo_n "checking for library containing pthread_mutexattr_init... " >&6; }
-if ${ac_cv_search_pthread_mutexattr_init+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pthread_mutexattr_init ();
-int
-main ()
-{
-return pthread_mutexattr_init ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' pthread; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_pthread_mutexattr_init=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_pthread_mutexattr_init+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_pthread_mutexattr_init+:} false; then :
-
-else
- ac_cv_search_pthread_mutexattr_init=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_mutexattr_init" >&5
-$as_echo "$ac_cv_search_pthread_mutexattr_init" >&6; }
-ac_res=$ac_cv_search_pthread_mutexattr_init
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-fi
-
-##########
-# Do we want to support release
-#
-# Check whether --enable-releasemode was given.
-if test "${enable_releasemode+set}" = set; then :
- enableval=$enable_releasemode;
-else
- enable_releasemode=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support shared library linked as release mode or not" >&5
-$as_echo_n "checking whether to support shared library linked as release mode or not... " >&6; }
-if test "$enable_releasemode" = "no"; then
- ALLOWRELEASE=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-else
- ALLOWRELEASE="-release `cat $srcdir/VERSION`"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-
-
-##########
-# Do we want temporary databases in memory
-#
-# Check whether --enable-tempstore was given.
-if test "${enable_tempstore+set}" = set; then :
- enableval=$enable_tempstore;
-else
- enable_tempstore=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use an in-ram database for temporary tables" >&5
-$as_echo_n "checking whether to use an in-ram database for temporary tables... " >&6; }
-case "$enable_tempstore" in
- never )
- TEMP_STORE=0
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: never" >&5
-$as_echo "never" >&6; }
- ;;
- no )
- TEMP_STORE=1
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- ;;
- yes )
- TEMP_STORE=2
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- ;;
- always )
- TEMP_STORE=3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: always" >&5
-$as_echo "always" >&6; }
- ;;
- * )
- TEMP_STORE=1
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- ;;
-esac
-
-
-
-###########
-# Lots of things are different if we are compiling for Windows using
-# the CYGWIN environment. So check for that special case and handle
-# things accordingly.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if executables have the .exe suffix" >&5
-$as_echo_n "checking if executables have the .exe suffix... " >&6; }
-if test "$config_BUILD_EXEEXT" = ".exe"; then
- CYGWIN=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5
-$as_echo "unknown" >&6; }
-fi
-if test "$CYGWIN" != "yes"; then
-
-case $host_os in
- *cygwin* ) CYGWIN=yes;;
- * ) CYGWIN=no;;
-esac
-
-fi
-if test "$CYGWIN" = "yes"; then
- BUILD_EXEEXT=.exe
-else
- BUILD_EXEEXT=$EXEEXT
-fi
-if test x"$cross_compiling" = xno; then
- TARGET_EXEEXT=$BUILD_EXEEXT
-else
- TARGET_EXEEXT=$config_TARGET_EXEEXT
-fi
-if test "$TARGET_EXEEXT" = ".exe"; then
- SQLITE_OS_UNIX=0
- SQLITE_OS_WIN=1
- CFLAGS="$CFLAGS -DSQLITE_OS_WIN=1"
-else
- SQLITE_OS_UNIX=1
- SQLITE_OS_WIN=0
- CFLAGS="$CFLAGS -DSQLITE_OS_UNIX=1"
-fi
-
-
-
-
-
-
-##########
-# Figure out all the parameters needed to compile against Tcl.
-#
-# This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG
-# macros in the in the tcl.m4 file of the standard TCL distribution.
-# Those macros could not be used directly since we have to make some
-# minor changes to accomodate systems that do not have TCL installed.
-#
-# Check whether --enable-tcl was given.
-if test "${enable_tcl+set}" = set; then :
- enableval=$enable_tcl; use_tcl=$enableval
-else
- use_tcl=yes
-fi
-
-if test "${use_tcl}" = "yes" ; then
-
-# Check whether --with-tcl was given.
-if test "${with_tcl+set}" = set; then :
- withval=$with_tcl; with_tclconfig=${withval}
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5
-$as_echo_n "checking for Tcl configuration... " >&6; }
- if ${ac_cv_c_tclconfig+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- # First check to see if --with-tcl was specified.
- if test x"${with_tclconfig}" != x ; then
- if test -f "${with_tclconfig}/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
- else
- as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5
- fi
- fi
-
- # Start autosearch by asking tclsh
- if test x"${ac_cv_c_tclconfig}" = x ; then
- if test x"$cross_compiling" = xno; then
- for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}`
- do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig="$i"
- break
- fi
- done
- fi
- fi
-
- # On ubuntu 14.10, $auto_path on tclsh is not quite correct.
- # So try again after applying corrections.
- if test x"${ac_cv_c_tclconfig}" = x ; then
- if test x"$cross_compiling" = xno; then
- for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'`
- do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig="$i"
- break
- fi
- done
- fi
- fi
-
- # Recent versions of Xcode on Macs hid the tclConfig.sh file
- # in a strange place.
- if test x"${ac_cv_c_tclconfig}" = x ; then
- if test x"$cross_compiling" = xno; then
- for i in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX*.sdk/usr/lib
- do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig="$i"
- break
- fi
- done
- fi
- fi
-
- # then check for a private Tcl installation
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in \
- ../tcl \
- `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
- `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \
- `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \
- ../../tcl \
- `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
- `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \
- `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \
- ../../../tcl \
- `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
- `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \
- `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null`
- do
- if test -f "$i/unix/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
- break
- fi
- done
- fi
-
- # check in a few common install locations
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in \
- `ls -d ${libdir} 2>/dev/null` \
- `ls -d /usr/local/lib 2>/dev/null` \
- `ls -d /usr/contrib/lib 2>/dev/null` \
- `ls -d /usr/lib 2>/dev/null`
- do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd $i; pwd)`
- break
- fi
- done
- fi
-
- # check in a few other private locations
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in \
- ${srcdir}/../tcl \
- `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
- `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \
- `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null`
- do
- if test -f "$i/unix/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
- break
- fi
- done
- fi
-
-fi
-
-
- if test x"${ac_cv_c_tclconfig}" = x ; then
- use_tcl=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find Tcl configuration definitions" >&5
-$as_echo "$as_me: WARNING: Can't find Tcl configuration definitions" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&5
-$as_echo "$as_me: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&5
-$as_echo "$as_me: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&2;}
- else
- TCL_BIN_DIR=${ac_cv_c_tclconfig}
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $TCL_BIN_DIR/tclConfig.sh" >&5
-$as_echo "found $TCL_BIN_DIR/tclConfig.sh" >&6; }
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5
-$as_echo_n "checking for existence of $TCL_BIN_DIR/tclConfig.sh... " >&6; }
- if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5
-$as_echo "loading" >&6; }
- . $TCL_BIN_DIR/tclConfig.sh
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: file not found" >&5
-$as_echo "file not found" >&6; }
- fi
-
- #
- # If the TCL_BIN_DIR is the build directory (not the install directory),
- # then set the common variable name to the value of the build variables.
- # For example, the variable TCL_LIB_SPEC will be set to the value
- # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
- # instead of TCL_BUILD_LIB_SPEC since it will work with both an
- # installed and uninstalled version of Tcl.
- #
-
- if test -f $TCL_BIN_DIR/Makefile ; then
- TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
- TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
- TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
- fi
-
- #
- # eval is required to do the TCL_DBGX substitution
- #
-
- eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
- eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
- eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
-
- eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
- eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
- eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- fi
-fi
-if test "${use_tcl}" = "no" ; then
- HAVE_TCL=""
-else
- HAVE_TCL=1
-fi
-
-
-##########
-# Figure out what C libraries are required to compile programs
-# that use "readline()" library.
-#
-TARGET_READLINE_LIBS=""
-TARGET_READLINE_INC=""
-TARGET_HAVE_READLINE=0
-TARGET_HAVE_EDITLINE=0
-# Check whether --enable-editline was given.
-if test "${enable_editline+set}" = set; then :
- enableval=$enable_editline; with_editline=$enableval
-else
- with_editline=auto
-fi
-
-# Check whether --enable-readline was given.
-if test "${enable_readline+set}" = set; then :
- enableval=$enable_readline; with_readline=$enableval
-else
- with_readline=auto
-fi
-
-
-if test x"$with_editline" != xno; then
- sLIBS=$LIBS
- LIBS=""
- TARGET_HAVE_EDITLINE=1
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing readline" >&5
-$as_echo_n "checking for library containing readline... " >&6; }
-if ${ac_cv_search_readline+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char readline ();
-int
-main ()
-{
-return readline ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' edit; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_readline=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_readline+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_readline+:} false; then :
-
-else
- ac_cv_search_readline=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_readline" >&5
-$as_echo "$ac_cv_search_readline" >&6; }
-ac_res=$ac_cv_search_readline
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
- with_readline=no
-else
- TARGET_HAVE_EDITLINE=0
-fi
-
- TARGET_READLINE_LIBS=$LIBS
- LIBS=$sLIBS
-fi
-if test x"$with_readline" != xno; then
- found="yes"
-
-
-# Check whether --with-readline-lib was given.
-if test "${with_readline_lib+set}" = set; then :
- withval=$with_readline_lib; with_readline_lib=$withval
-else
- with_readline_lib="auto"
-fi
-
- if test "x$with_readline_lib" = xauto; then
- save_LIBS="$LIBS"
- LIBS=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tgetent" >&5
-$as_echo_n "checking for library containing tgetent... " >&6; }
-if ${ac_cv_search_tgetent+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char tgetent ();
-int
-main ()
-{
-return tgetent ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' readline ncurses curses termcap; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_tgetent=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_tgetent+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_tgetent+:} false; then :
-
-else
- ac_cv_search_tgetent=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_tgetent" >&5
-$as_echo "$ac_cv_search_tgetent" >&6; }
-ac_res=$ac_cv_search_tgetent
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
- term_LIBS="$LIBS"
-else
- term_LIBS=""
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5
-$as_echo_n "checking for readline in -lreadline... " >&6; }
-if ${ac_cv_lib_readline_readline+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lreadline $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char readline ();
-int
-main ()
-{
-return readline ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_readline_readline=yes
-else
- ac_cv_lib_readline_readline=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5
-$as_echo "$ac_cv_lib_readline_readline" >&6; }
-if test "x$ac_cv_lib_readline_readline" = xyes; then :
- TARGET_READLINE_LIBS="-lreadline"
-else
- found="no"
-fi
-
- TARGET_READLINE_LIBS="$TARGET_READLINE_LIBS $term_LIBS"
- LIBS="$save_LIBS"
- else
- TARGET_READLINE_LIBS="$with_readline_lib"
- fi
-
-
-# Check whether --with-readline-inc was given.
-if test "${with_readline_inc+set}" = set; then :
- withval=$with_readline_inc; with_readline_inc=$withval
-else
- with_readline_inc="auto"
-fi
-
- if test "x$with_readline_inc" = xauto; then
- ac_fn_c_check_header_mongrel "$LINENO" "readline.h" "ac_cv_header_readline_h" "$ac_includes_default"
-if test "x$ac_cv_header_readline_h" = xyes; then :
- found="yes"
-else
-
- found="no"
- if test "$cross_compiling" != yes; then
- for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do
- for subdir in include include/readline; do
- as_ac_File=`$as_echo "ac_cv_file_$dir/$subdir/readline.h" | $as_tr_sh`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $dir/$subdir/readline.h" >&5
-$as_echo_n "checking for $dir/$subdir/readline.h... " >&6; }
-if eval \${$as_ac_File+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- test "$cross_compiling" = yes &&
- as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
-if test -r "$dir/$subdir/readline.h"; then
- eval "$as_ac_File=yes"
-else
- eval "$as_ac_File=no"
-fi
-fi
-eval ac_res=\$$as_ac_File
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
- found=yes
-fi
-
- if test "$found" = "yes"; then
- TARGET_READLINE_INC="-I$dir/$subdir"
- break
- fi
- done
- test "$found" = "yes" && break
- done
- fi
-
-fi
-
-
- else
- TARGET_READLINE_INC="$with_readline_inc"
- fi
-
- if test x"$found" = xno; then
- TARGET_READLINE_LIBS=""
- TARGET_READLINE_INC=""
- TARGET_HAVE_READLINE=0
- else
- TARGET_HAVE_READLINE=1
- fi
-fi
-
-
-
-
-
-
-##########
-# Figure out what C libraries are required to compile programs
-# that use "fdatasync()" function.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5
-$as_echo_n "checking for library containing fdatasync... " >&6; }
-if ${ac_cv_search_fdatasync+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char fdatasync ();
-int
-main ()
-{
-return fdatasync ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' rt; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_fdatasync=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_fdatasync+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_fdatasync+:} false; then :
-
-else
- ac_cv_search_fdatasync=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fdatasync" >&5
-$as_echo "$ac_cv_search_fdatasync" >&6; }
-ac_res=$ac_cv_search_fdatasync
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-
-#########
-# check for debug enabled
-# Check whether --enable-debug was given.
-if test "${enable_debug+set}" = set; then :
- enableval=$enable_debug; use_debug=$enableval
-else
- use_debug=no
-fi
-
-if test "${use_debug}" = "yes" ; then
- TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
-else
- TARGET_DEBUG="-DNDEBUG"
-fi
-
-
-#########
-# See whether we should use the amalgamation to build
-# Check whether --enable-amalgamation was given.
-if test "${enable_amalgamation+set}" = set; then :
- enableval=$enable_amalgamation; use_amalgamation=$enableval
-else
- use_amalgamation=yes
-fi
-
-if test "${use_amalgamation}" != "yes" ; then
- USE_AMALGAMATION=0
-fi
-
-
-#########
-# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
-for ac_header in zlib.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_zlib_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_ZLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
-$as_echo_n "checking for library containing deflate... " >&6; }
-if ${ac_cv_search_deflate+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' z; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_deflate=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_deflate+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_deflate+:} false; then :
-
-else
- ac_cv_search_deflate=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
-$as_echo "$ac_cv_search_deflate" >&6; }
-ac_res=$ac_cv_search_deflate
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
- HAVE_ZLIB="-DSQLITE_HAVE_ZLIB=1"
-else
- HAVE_ZLIB=""
-fi
-
-
-
-#########
-# See whether we should allow loadable extensions
-# Check whether --enable-load-extension was given.
-if test "${enable_load_extension+set}" = set; then :
- enableval=$enable_load_extension; use_loadextension=$enableval
-else
- use_loadextension=yes
-fi
-
-if test "${use_loadextension}" = "yes" ; then
- OPT_FEATURE_FLAGS=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
-$as_echo_n "checking for library containing dlopen... " >&6; }
-if ${ac_cv_search_dlopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' dl; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_dlopen=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_dlopen+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_dlopen+:} false; then :
-
-else
- ac_cv_search_dlopen=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
-$as_echo "$ac_cv_search_dlopen" >&6; }
-ac_res=$ac_cv_search_dlopen
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-else
- OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
-fi
-
-##########
-# Do we want to support memsys3 and/or memsys5
-#
-# Check whether --enable-memsys5 was given.
-if test "${enable_memsys5+set}" = set; then :
- enableval=$enable_memsys5; enable_memsys5=yes
-else
- enable_memsys5=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS5" >&5
-$as_echo_n "checking whether to support MEMSYS5... " >&6; }
-if test "${enable_memsys5}" = "yes"; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-# Check whether --enable-memsys3 was given.
-if test "${enable_memsys3+set}" = set; then :
- enableval=$enable_memsys3; enable_memsys3=yes
-else
- enable_memsys3=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS3" >&5
-$as_echo_n "checking whether to support MEMSYS3... " >&6; }
-if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-#########
-# See whether we should enable Full Text Search extensions
-# Check whether --enable-fts3 was given.
-if test "${enable_fts3+set}" = set; then :
- enableval=$enable_fts3; enable_fts3=yes
-else
- enable_fts3=no
-fi
-
-if test "${enable_fts3}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
-fi
-# Check whether --enable-fts4 was given.
-if test "${enable_fts4+set}" = set; then :
- enableval=$enable_fts4; enable_fts4=yes
-else
- enable_fts4=no
-fi
-
-if test "${enable_fts4}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
-$as_echo_n "checking for library containing log... " >&6; }
-if ${ac_cv_search_log+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char log ();
-int
-main ()
-{
-return log ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' m; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_log=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_log+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_log+:} false; then :
-
-else
- ac_cv_search_log=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log" >&5
-$as_echo "$ac_cv_search_log" >&6; }
-ac_res=$ac_cv_search_log
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-fi
-# Check whether --enable-fts5 was given.
-if test "${enable_fts5+set}" = set; then :
- enableval=$enable_fts5; enable_fts5=yes
-else
- enable_fts5=no
-fi
-
-if test "${enable_fts5}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
-$as_echo_n "checking for library containing log... " >&6; }
-if ${ac_cv_search_log+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char log ();
-int
-main ()
-{
-return log ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' m; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_log=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_log+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_log+:} false; then :
-
-else
- ac_cv_search_log=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log" >&5
-$as_echo "$ac_cv_search_log" >&6; }
-ac_res=$ac_cv_search_log
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-fi
-
-#########
-# See whether we should enable JSON1
-# Check whether --enable-json1 was given.
-if test "${enable_json1+set}" = set; then :
- enableval=$enable_json1; enable_json1=yes
-else
- enable_json1=no
-fi
-
-if test "${enable_json1}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
-fi
-
-#########
-# See whether we should enable the LIMIT clause on UPDATE and DELETE
-# statements.
-# Check whether --enable-update-limit was given.
-if test "${enable_update_limit+set}" = set; then :
- enableval=$enable_update_limit; enable_udlimit=yes
-else
- enable_udlimit=no
-fi
-
-if test "${enable_udlimit}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
-fi
-
-#########
-# See whether we should enable RTREE
-# Check whether --enable-rtree was given.
-if test "${enable_rtree+set}" = set; then :
- enableval=$enable_rtree; enable_rtree=yes
-else
- enable_rtree=no
-fi
-
-if test "${enable_rtree}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
-fi
-
-#########
-# See whether we should enable the SESSION extension
-# Check whether --enable-session was given.
-if test "${enable_session+set}" = set; then :
- enableval=$enable_session; enable_session=yes
-else
- enable_session=no
-fi
-
-if test "${enable_session}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
-fi
-
-#########
-# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
-for option in $CFLAGS $CPPFLAGS
-do
- case $option in
- -DSQLITE_OMIT*) OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS $option";;
- -DSQLITE_ENABLE*) OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS $option";;
- esac
-done
-
-
-
-# attempt to remove any OMITS and ENABLES from the $(CFLAGS) parameter
-ac_temp_CFLAGS=""
-for option in $CFLAGS
-do
- case $option in
- -DSQLITE_OMIT*) ;;
- -DSQLITE_ENABLE*) ;;
- *) ac_temp_CFLAGS="$ac_temp_CFLAGS $option";;
- esac
-done
-CFLAGS=$ac_temp_CFLAGS
-
-
-# attempt to remove any OMITS and ENABLES from the $(CPPFLAGS) parameter
-ac_temp_CPPFLAGS=""
-for option in $CPPFLAGS
-do
- case $option in
- -DSQLITE_OMIT*) ;;
- -DSQLITE_ENABLE*) ;;
- *) ac_temp_CPPFLAGS="$ac_temp_CPPFLAGS $option";;
- esac
-done
-CPPFLAGS=$ac_temp_CPPFLAGS
-
-
-# attempt to remove any OMITS and ENABLES from the $(BUILD_CFLAGS) parameter
-ac_temp_BUILD_CFLAGS=""
-for option in $BUILD_CFLAGS
-do
- case $option in
- -DSQLITE_OMIT*) ;;
- -DSQLITE_ENABLE*) ;;
- *) ac_temp_BUILD_CFLAGS="$ac_temp_BUILD_CFLAGS $option";;
- esac
-done
-BUILD_CFLAGS=$ac_temp_BUILD_CFLAGS
-
-
-#########
-# See whether we should use GCOV
-# Check whether --enable-gcov was given.
-if test "${enable_gcov+set}" = set; then :
- enableval=$enable_gcov; use_gcov=$enableval
-else
- use_gcov=no
-fi
-
-if test "${use_gcov}" = "yes" ; then
- USE_GCOV=1
-else
- USE_GCOV=0
-fi
-
-
-
-#########
-# Output the config header
-ac_config_headers="$ac_config_headers config.h"
-
-
-#########
-# Generate the output files.
-#
-
-ac_config_files="$ac_config_files Makefile sqlite3.pc"
-
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems. If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, we kill variables containing newlines.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(
- for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
- eval ac_val=\$$ac_var
- case $ac_val in #(
- *${as_nl}*)
- case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
- esac
- case $ac_var in #(
- _ | IFS | as_nl) ;; #(
- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
- *) { eval $ac_var=; unset $ac_var;} ;;
- esac ;;
- esac
- done
-
- (set) 2>&1 |
- case $as_nl`(ac_space=' '; set) 2>&1` in #(
- *${as_nl}ac_space=\ *)
- # `set' does not quote correctly, so add quotes: double-quote
- # substitution turns \\\\ into \\, and sed turns \\ into \.
- sed -n \
- "s/'/'\\\\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
- ;; #(
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
- ;;
- esac |
- sort
-) |
- sed '
- /^ac_cv_env_/b end
- t clear
- :clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
- t end
- s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
- :end' >>confcache
-if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
- if test -w "$cache_file"; then
- if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
- if test ! -f "$cache_file" || test -h "$cache_file"; then
- cat confcache >"$cache_file"
- else
- case $cache_file in #(
- */* | ?:*)
- mv -f confcache "$cache_file"$$ &&
- mv -f "$cache_file"$$ "$cache_file" ;; #(
- *)
- mv -f confcache "$cache_file" ;;
- esac
- fi
- fi
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
- fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-DEFS=-DHAVE_CONFIG_H
-
-ac_libobjs=
-ac_ltlibobjs=
-U=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
- # 1. Remove the extension, and $U if already installed.
- ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
- # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
- # will be set to the directory where LIBOBJS objects are built.
- as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
- as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: "${CONFIG_STATUS=./config.status}"
-ac_write_fail=0
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
-as_write_fail=0
-cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-
-SHELL=\${CONFIG_SHELL-$SHELL}
-export SHELL
-_ASEOF
-cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
-## -------------------- ##
-## M4sh Initialization. ##
-## -------------------- ##
-
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
- emulate sh
- NULLCMD=:
- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in #(
- *posix*) :
- set -o posix ;; #(
- *) :
- ;;
-esac
-fi
-
-
-as_nl='
-'
-export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- PATH_SEPARATOR=:
- (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
- (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
- PATH_SEPARATOR=';'
- }
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
-# Find who we are. Look in the path if we contain no directory separator.
-as_myself=
-case $0 in #((
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
- done
-IFS=$as_save_IFS
-
- ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
- as_myself=$0
-fi
-if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- exit 1
-fi
-
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-
-# as_fn_error STATUS ERROR [LINENO LOG_FD]
-# ----------------------------------------
-# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with STATUS, using 1 if that was 0.
-as_fn_error ()
-{
- as_status=$1; test $as_status -eq 0 && as_status=1
- if test "$4"; then
- as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
- fi
- $as_echo "$as_me: error: $2" >&2
- as_fn_exit $as_status
-} # as_fn_error
-
-
-# as_fn_set_status STATUS
-# -----------------------
-# Set $? to STATUS, without forking.
-as_fn_set_status ()
-{
- return $1
-} # as_fn_set_status
-
-# as_fn_exit STATUS
-# -----------------
-# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
-as_fn_exit ()
-{
- set +e
- as_fn_set_status $1
- exit $1
-} # as_fn_exit
-
-# as_fn_unset VAR
-# ---------------
-# Portably unset VAR.
-as_fn_unset ()
-{
- { eval $1=; unset $1;}
-}
-as_unset=as_fn_unset
-# as_fn_append VAR VALUE
-# ----------------------
-# Append the text in VALUE to the end of the definition contained in VAR. Take
-# advantage of any shell optimizations that allow amortized linear growth over
-# repeated appends, instead of the typical quadratic growth present in naive
-# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
- eval 'as_fn_append ()
- {
- eval $1+=\$2
- }'
-else
- as_fn_append ()
- {
- eval $1=\$$1\$2
- }
-fi # as_fn_append
-
-# as_fn_arith ARG...
-# ------------------
-# Perform arithmetic evaluation on the ARGs, and store the result in the
-# global $as_val. Take advantage of shells that can avoid forks. The arguments
-# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
- eval 'as_fn_arith ()
- {
- as_val=$(( $* ))
- }'
-else
- as_fn_arith ()
- {
- as_val=`expr "$@" || test $? -eq 1`
- }
-fi # as_fn_arith
-
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
-
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in #(((((
--n*)
- case `echo 'xy\c'` in
- *c*) ECHO_T=' ';; # ECHO_T is single tab character.
- xy) ECHO_C='\c';;
- *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
- ECHO_T=' ';;
- esac;;
-*)
- ECHO_N='-n';;
-esac
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
- rm -f conf$$.dir/conf$$.file
-else
- rm -f conf$$.dir
- mkdir conf$$.dir 2>/dev/null
-fi
-if (echo >conf$$.file) 2>/dev/null; then
- if ln -s conf$$.file conf$$ 2>/dev/null; then
- as_ln_s='ln -s'
- # ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -pR'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -pR'
- elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
- else
- as_ln_s='cp -pR'
- fi
-else
- as_ln_s='cp -pR'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-
-# as_fn_mkdir_p
-# -------------
-# Create "$as_dir" as a directory, including parents if necessary.
-as_fn_mkdir_p ()
-{
-
- case $as_dir in #(
- -*) as_dir=./$as_dir;;
- esac
- test -d "$as_dir" || eval $as_mkdir_p || {
- as_dirs=
- while :; do
- case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
- *) as_qdir=$as_dir;;
- esac
- as_dirs="'$as_qdir' $as_dirs"
- as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- test -d "$as_dir" && break
- done
- test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
-
-
-} # as_fn_mkdir_p
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p='mkdir -p "$as_dir"'
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
- test -f "$1" && test -x "$1"
-} # as_fn_executable_p
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-exec 6>&1
-## ----------------------------------- ##
-## Main body of $CONFIG_STATUS script. ##
-## ----------------------------------- ##
-_ASEOF
-test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# Save the log message, to keep $0 and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.
-ac_log="
-This file was extended by sqlite $as_me 3.24.0, which was
-generated by GNU Autoconf 2.69. Invocation command line was
-
- CONFIG_FILES = $CONFIG_FILES
- CONFIG_HEADERS = $CONFIG_HEADERS
- CONFIG_LINKS = $CONFIG_LINKS
- CONFIG_COMMANDS = $CONFIG_COMMANDS
- $ $0 $@
-
-on `(hostname || uname -n) 2>/dev/null | sed 1q`
-"
-
-_ACEOF
-
-case $ac_config_files in *"
-"*) set x $ac_config_files; shift; ac_config_files=$*;;
-esac
-
-case $ac_config_headers in *"
-"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
-esac
-
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-# Files that config.status was made for.
-config_files="$ac_config_files"
-config_headers="$ac_config_headers"
-config_commands="$ac_config_commands"
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-ac_cs_usage="\
-\`$as_me' instantiates files and other configuration actions
-from templates according to the current configuration. Unless the files
-and actions are specified as TAGs, all are instantiated by default.
-
-Usage: $0 [OPTION]... [TAG]...
-
- -h, --help print this help, then exit
- -V, --version print version number and configuration settings, then exit
- --config print configuration, then exit
- -q, --quiet, --silent
- do not print progress messages
- -d, --debug don't remove temporary files
- --recheck update $as_me by reconfiguring in the same conditions
- --file=FILE[:TEMPLATE]
- instantiate the configuration file FILE
- --header=FILE[:TEMPLATE]
- instantiate the configuration header FILE
-
-Configuration files:
-$config_files
-
-Configuration headers:
-$config_headers
-
-Configuration commands:
-$config_commands
-
-Report bugs to the package provider."
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
-ac_cs_version="\\
-sqlite config.status 3.24.0
-configured by $0, generated by GNU Autoconf 2.69,
- with options \\"\$ac_cs_config\\"
-
-Copyright (C) 2012 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-
-ac_pwd='$ac_pwd'
-srcdir='$srcdir'
-INSTALL='$INSTALL'
-test -n "\$AWK" || AWK=awk
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# The default lists apply if the user does not specify any file.
-ac_need_defaults=:
-while test $# != 0
-do
- case $1 in
- --*=?*)
- ac_option=`expr "X$1" : 'X\([^=]*\)='`
- ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
- ac_shift=:
- ;;
- --*=)
- ac_option=`expr "X$1" : 'X\([^=]*\)='`
- ac_optarg=
- ac_shift=:
- ;;
- *)
- ac_option=$1
- ac_optarg=$2
- ac_shift=shift
- ;;
- esac
-
- case $ac_option in
- # Handling of the options.
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- ac_cs_recheck=: ;;
- --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
- --config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
- --debug | --debu | --deb | --de | --d | -d )
- debug=: ;;
- --file | --fil | --fi | --f )
- $ac_shift
- case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
- '') as_fn_error $? "missing file argument" ;;
- esac
- as_fn_append CONFIG_FILES " '$ac_optarg'"
- ac_need_defaults=false;;
- --header | --heade | --head | --hea )
- $ac_shift
- case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
- esac
- as_fn_append CONFIG_HEADERS " '$ac_optarg'"
- ac_need_defaults=false;;
- --he | --h)
- # Conflict between --help and --header
- as_fn_error $? "ambiguous option: \`$1'
-Try \`$0 --help' for more information.";;
- --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil | --si | --s)
- ac_cs_silent=: ;;
-
- # This is an error.
- -*) as_fn_error $? "unrecognized option: \`$1'
-Try \`$0 --help' for more information." ;;
-
- *) as_fn_append ac_config_targets " $1"
- ac_need_defaults=false ;;
-
- esac
- shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
- exec 6>/dev/null
- ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-if \$ac_cs_recheck; then
- set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
- shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
- CONFIG_SHELL='$SHELL'
- export CONFIG_SHELL
- exec "\$@"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-exec 5>>config.log
-{
- echo
- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
- $as_echo "$ac_log"
-} >&5
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-#
-# INIT-COMMANDS
-#
-
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-sed_quote_subst='$sed_quote_subst'
-double_quote_subst='$double_quote_subst'
-delay_variable_subst='$delay_variable_subst'
-macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`'
-macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`'
-enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`'
-enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`'
-pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`'
-enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`'
-host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`'
-host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`'
-host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`'
-build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`'
-build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`'
-build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`'
-SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`'
-Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`'
-GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`'
-EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`'
-FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`'
-LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`'
-NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`'
-LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`'
-max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`'
-ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`'
-exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`'
-lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`'
-lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`'
-lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`'
-reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`'
-reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`'
-deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`'
-file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`'
-AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`'
-AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`'
-STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`'
-RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`'
-old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`'
-CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`'
-compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`'
-GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
-objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`'
-SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`'
-ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`'
-MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`'
-need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`'
-DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`'
-NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`'
-LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`'
-OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`'
-OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`'
-libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`'
-shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`'
-enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`'
-export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
-whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
-compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`'
-allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
-no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`'
-inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`'
-link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`'
-fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`'
-always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`'
-export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
-include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
-prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`'
-variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`'
-need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
-need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`'
-version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`'
-runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`'
-shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
-shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`'
-libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`'
-library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`'
-soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`'
-postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`'
-sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
-sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`'
-enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`'
-enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`'
-enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`'
-old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`'
-striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`'
-
-LTCC='$LTCC'
-LTCFLAGS='$LTCFLAGS'
-compiler='$compiler_DEFAULT'
-
-# Quote evaled strings.
-for var in SED \
-GREP \
-EGREP \
-FGREP \
-LD \
-NM \
-LN_S \
-lt_SP2NL \
-lt_NL2SP \
-reload_flag \
-OBJDUMP \
-deplibs_check_method \
-file_magic_cmd \
-AR \
-AR_FLAGS \
-STRIP \
-RANLIB \
-CC \
-CFLAGS \
-compiler \
-lt_cv_sys_global_symbol_pipe \
-lt_cv_sys_global_symbol_to_cdecl \
-lt_cv_sys_global_symbol_to_c_name_address \
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
-SHELL \
-ECHO \
-lt_prog_compiler_no_builtin_flag \
-lt_prog_compiler_wl \
-lt_prog_compiler_pic \
-lt_prog_compiler_static \
-lt_cv_prog_compiler_c_o \
-need_locks \
-DSYMUTIL \
-NMEDIT \
-LIPO \
-OTOOL \
-OTOOL64 \
-shrext_cmds \
-export_dynamic_flag_spec \
-whole_archive_flag_spec \
-compiler_needs_object \
-with_gnu_ld \
-allow_undefined_flag \
-no_undefined_flag \
-hardcode_libdir_flag_spec \
-hardcode_libdir_flag_spec_ld \
-hardcode_libdir_separator \
-fix_srcfile_path \
-exclude_expsyms \
-include_expsyms \
-file_list_spec \
-variables_saved_for_relink \
-libname_spec \
-library_names_spec \
-soname_spec \
-finish_eval \
-old_striplib \
-striplib; do
- case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
- *[\\\\\\\`\\"\\\$]*)
- eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
- ;;
- *)
- eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
- ;;
- esac
-done
-
-# Double-quote double-evaled strings.
-for var in reload_cmds \
-old_postinstall_cmds \
-old_postuninstall_cmds \
-old_archive_cmds \
-extract_expsyms_cmds \
-old_archive_from_new_cmds \
-old_archive_from_expsyms_cmds \
-archive_cmds \
-archive_expsym_cmds \
-module_cmds \
-module_expsym_cmds \
-export_symbols_cmds \
-prelink_cmds \
-postinstall_cmds \
-postuninstall_cmds \
-finish_cmds \
-sys_lib_search_path_spec \
-sys_lib_dlsearch_path_spec; do
- case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
- *[\\\\\\\`\\"\\\$]*)
- eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
- ;;
- *)
- eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
- ;;
- esac
-done
-
-# Fix-up fallback echo if it was mangled by the above quoting rules.
-case \$lt_ECHO in
-*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\`
- ;;
-esac
-
-ac_aux_dir='$ac_aux_dir'
-xsi_shell='$xsi_shell'
-lt_shell_append='$lt_shell_append'
-
-# See if we are running on zsh, and set the options which allow our
-# commands through without removal of \ escapes INIT.
-if test -n "\${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
-fi
-
-
- PACKAGE='$PACKAGE'
- VERSION='$VERSION'
- TIMESTAMP='$TIMESTAMP'
- RM='$RM'
- ofile='$ofile'
-
-
-
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-
-# Handling of arguments.
-for ac_config_target in $ac_config_targets
-do
- case $ac_config_target in
- "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
- "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
- "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- "sqlite3.pc") CONFIG_FILES="$CONFIG_FILES sqlite3.pc" ;;
-
- *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
- esac
-done
-
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used. Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
- test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
-fi
-
-# Have a temporary directory for convenience. Make it in the build tree
-# simply because there is no reason against having it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Hook for its removal unless debugging.
-# Note that there is a small window in which the directory will not be cleaned:
-# after its creation but before its name has been assigned to `$tmp'.
-$debug ||
-{
- tmp= ac_tmp=
- trap 'exit_status=$?
- : "${ac_tmp:=$tmp}"
- { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
-' 0
- trap 'as_fn_exit 1' 1 2 13 15
-}
-# Create a (secure) tmp directory for tmp files.
-
-{
- tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
- test -d "$tmp"
-} ||
-{
- tmp=./conf$$-$RANDOM
- (umask 077 && mkdir "$tmp")
-} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
-ac_tmp=$tmp
-
-# Set up the scripts for CONFIG_FILES section.
-# No need to generate them if there are no CONFIG_FILES.
-# This happens for instance with `./config.status config.h'.
-if test -n "$CONFIG_FILES"; then
-
-
-ac_cr=`echo X | tr X '\015'`
-# On cygwin, bash can eat \r inside `` if the user requested igncr.
-# But we know of no other shell where ac_cr would be empty at this
-# point, so we can use a bashism as a fallback.
-if test "x$ac_cr" = x; then
- eval ac_cr=\$\'\\r\'
-fi
-ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
-if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
- ac_cs_awk_cr='\\r'
-else
- ac_cs_awk_cr=$ac_cr
-fi
-
-echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
-_ACEOF
-
-
-{
- echo "cat >conf$$subs.awk <<_ACEOF" &&
- echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
- echo "_ACEOF"
-} >conf$$subs.sh ||
- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
-ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
- . ./conf$$subs.sh ||
- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
-
- ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
- if test $ac_delim_n = $ac_delim_num; then
- break
- elif $ac_last_try; then
- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
- else
- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
- fi
-done
-rm -f conf$$subs.sh
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
-_ACEOF
-sed -n '
-h
-s/^/S["/; s/!.*/"]=/
-p
-g
-s/^[^!]*!//
-:repl
-t repl
-s/'"$ac_delim"'$//
-t delim
-:nl
-h
-s/\(.\{148\}\)..*/\1/
-t more1
-s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
-p
-n
-b repl
-:more1
-s/["\\]/\\&/g; s/^/"/; s/$/"\\/
-p
-g
-s/.\{148\}//
-t nl
-:delim
-h
-s/\(.\{148\}\)..*/\1/
-t more2
-s/["\\]/\\&/g; s/^/"/; s/$/"/
-p
-b
-:more2
-s/["\\]/\\&/g; s/^/"/; s/$/"\\/
-p
-g
-s/.\{148\}//
-t delim
-' <conf$$subs.awk | sed '
-/^[^""]/{
- N
- s/\n//
-}
-' >>$CONFIG_STATUS || ac_write_fail=1
-rm -f conf$$subs.awk
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-_ACAWK
-cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
- for (key in S) S_is_set[key] = 1
- FS = ""
-
-}
-{
- line = $ 0
- nfields = split(line, field, "@")
- substed = 0
- len = length(field[1])
- for (i = 2; i < nfields; i++) {
- key = field[i]
- keylen = length(key)
- if (S_is_set[key]) {
- value = S[key]
- line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
- len += length(value) + length(field[++i])
- substed = 1
- } else
- len += 1 + keylen
- }
-
- print line
-}
-
-_ACAWK
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
- sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
-else
- cat
-fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
- || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
-_ACEOF
-
-# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
-# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
-h
-s///
-s/^/:/
-s/[ ]*$/:/
-s/:\$(srcdir):/:/g
-s/:\${srcdir}:/:/g
-s/:@srcdir@:/:/g
-s/^:*//
-s/:*$//
-x
-s/\(=[ ]*\).*/\1/
-G
-s/\n//
-s/^[^=]*=[ ]*$//
-}'
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-fi # test -n "$CONFIG_FILES"
-
-# Set up the scripts for CONFIG_HEADERS section.
-# No need to generate them if there are no CONFIG_HEADERS.
-# This happens for instance with `./config.status Makefile'.
-if test -n "$CONFIG_HEADERS"; then
-cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
-BEGIN {
-_ACEOF
-
-# Transform confdefs.h into an awk script `defines.awk', embedded as
-# here-document in config.status, that substitutes the proper values into
-# config.h.in to produce config.h.
-
-# Create a delimiter string that does not exist in confdefs.h, to ease
-# handling of long lines.
-ac_delim='%!_!# '
-for ac_last_try in false false :; do
- ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
- if test -z "$ac_tt"; then
- break
- elif $ac_last_try; then
- as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
- else
- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
- fi
-done
-
-# For the awk script, D is an array of macro values keyed by name,
-# likewise P contains macro parameters if any. Preserve backslash
-# newline sequences.
-
-ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
-sed -n '
-s/.\{148\}/&'"$ac_delim"'/g
-t rset
-:rset
-s/^[ ]*#[ ]*define[ ][ ]*/ /
-t def
-d
-:def
-s/\\$//
-t bsnl
-s/["\\]/\\&/g
-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
-D["\1"]=" \3"/p
-s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
-d
-:bsnl
-s/["\\]/\\&/g
-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
-D["\1"]=" \3\\\\\\n"\\/p
-t cont
-s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
-t cont
-d
-:cont
-n
-s/.\{148\}/&'"$ac_delim"'/g
-t clear
-:clear
-s/\\$//
-t bsnlc
-s/["\\]/\\&/g; s/^/"/; s/$/"/p
-d
-:bsnlc
-s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
-b cont
-' <confdefs.h | sed '
-s/'"$ac_delim"'/"\\\
-"/g' >>$CONFIG_STATUS || ac_write_fail=1
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
- for (key in D) D_is_set[key] = 1
- FS = ""
-}
-/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
- line = \$ 0
- split(line, arg, " ")
- if (arg[1] == "#") {
- defundef = arg[2]
- mac1 = arg[3]
- } else {
- defundef = substr(arg[1], 2)
- mac1 = arg[2]
- }
- split(mac1, mac2, "(") #)
- macro = mac2[1]
- prefix = substr(line, 1, index(line, defundef) - 1)
- if (D_is_set[macro]) {
- # Preserve the white space surrounding the "#".
- print prefix "define", macro P[macro] D[macro]
- next
- } else {
- # Replace #undef with comments. This is necessary, for example,
- # in the case of _POSIX_SOURCE, which is predefined and required
- # on some systems where configure will not decide to define it.
- if (defundef == "undef") {
- print "/*", prefix defundef, macro, "*/"
- next
- }
- }
-}
-{ print }
-_ACAWK
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
- as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
-fi # test -n "$CONFIG_HEADERS"
-
-
-eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
-shift
-for ac_tag
-do
- case $ac_tag in
- :[FHLC]) ac_mode=$ac_tag; continue;;
- esac
- case $ac_mode$ac_tag in
- :[FHL]*:*);;
- :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
- :[FH]-) ac_tag=-:-;;
- :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
- esac
- ac_save_IFS=$IFS
- IFS=:
- set x $ac_tag
- IFS=$ac_save_IFS
- shift
- ac_file=$1
- shift
-
- case $ac_mode in
- :L) ac_source=$1;;
- :[FH])
- ac_file_inputs=
- for ac_f
- do
- case $ac_f in
- -) ac_f="$ac_tmp/stdin";;
- *) # Look for the file first in the build tree, then in the source tree
- # (if the path is not absolute). The absolute path cannot be DOS-style,
- # because $ac_f cannot contain `:'.
- test -f "$ac_f" ||
- case $ac_f in
- [\\/$]*) false;;
- *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
- esac ||
- as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
- esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
- as_fn_append ac_file_inputs " '$ac_f'"
- done
-
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
- `' by configure.'
- if test x"$ac_file" != x-; then
- configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
- fi
- # Neutralize special characters interpreted by sed in replacement strings.
- case $configure_input in #(
- *\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
- sed 's/[\\\\&|]/\\\\&/g'`;; #(
- *) ac_sed_conf_input=$configure_input;;
- esac
-
- case $ac_tag in
- *:-:* | *:-) cat >"$ac_tmp/stdin" \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
- esac
- ;;
- esac
-
- ac_dir=`$as_dirname -- "$ac_file" ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_file" : 'X\(//\)[^/]' \| \
- X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- as_dir="$ac_dir"; as_fn_mkdir_p
- ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
- # A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
- case $ac_top_builddir_sub in
- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
- esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
- .) # We are building in place.
- ac_srcdir=.
- ac_top_srcdir=$ac_top_builddir_sub
- ac_abs_top_srcdir=$ac_pwd ;;
- [\\/]* | ?:[\\/]* ) # Absolute name.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir
- ac_abs_top_srcdir=$srcdir ;;
- *) # Relative name.
- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_build_prefix$srcdir
- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
-
- case $ac_mode in
- :F)
- #
- # CONFIG_FILE
- #
-
- case $INSTALL in
- [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
- *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
- esac
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# If the template does not know about datarootdir, expand it.
-# FIXME: This hack should be removed a few years after 2.60.
-ac_datarootdir_hack=; ac_datarootdir_seen=
-ac_sed_dataroot='
-/datarootdir/ {
- p
- q
-}
-/@datadir@/p
-/@docdir@/p
-/@infodir@/p
-/@localedir@/p
-/@mandir@/p'
-case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
-*datarootdir*) ac_datarootdir_seen=yes;;
-*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
- ac_datarootdir_hack='
- s&@datadir@&$datadir&g
- s&@docdir@&$docdir&g
- s&@infodir@&$infodir&g
- s&@localedir@&$localedir&g
- s&@mandir@&$mandir&g
- s&\\\${datarootdir}&$datarootdir&g' ;;
-esac
-_ACEOF
-
-# Neutralize VPATH when `$srcdir' = `.'.
-# Shell code in configure.ac might set extrasub.
-# FIXME: do we really want to maintain this feature?
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_sed_extra="$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s|@configure_input@|$ac_sed_conf_input|;t t
-s&@top_builddir@&$ac_top_builddir_sub&;t t
-s&@top_build_prefix@&$ac_top_build_prefix&;t t
-s&@srcdir@&$ac_srcdir&;t t
-s&@abs_srcdir@&$ac_abs_srcdir&;t t
-s&@top_srcdir@&$ac_top_srcdir&;t t
-s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
-s&@builddir@&$ac_builddir&;t t
-s&@abs_builddir@&$ac_abs_builddir&;t t
-s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
-s&@INSTALL@&$ac_INSTALL&;t t
-$ac_datarootdir_hack
-"
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
- >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
-
-test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
- { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
- { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
- "$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined" >&2;}
-
- rm -f "$ac_tmp/stdin"
- case $ac_file in
- -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
- *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
- esac \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5
- ;;
- :H)
- #
- # CONFIG_HEADER
- #
- if test x"$ac_file" != x-; then
- {
- $as_echo "/* $configure_input */" \
- && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
- } >"$ac_tmp/config.h" \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5
- if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
-$as_echo "$as_me: $ac_file is unchanged" >&6;}
- else
- rm -f "$ac_file"
- mv "$ac_tmp/config.h" "$ac_file" \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5
- fi
- else
- $as_echo "/* $configure_input */" \
- && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
- || as_fn_error $? "could not create -" "$LINENO" 5
- fi
- ;;
-
- :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
-$as_echo "$as_me: executing $ac_file commands" >&6;}
- ;;
- esac
-
-
- case $ac_file$ac_mode in
- "libtool":C)
-
- # See if we are running on zsh, and set the options which allow our
- # commands through without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
-
- cfgfile="${ofile}T"
- trap "$RM \"$cfgfile\"; exit 1" 1 2 15
- $RM "$cfgfile"
-
- cat <<_LT_EOF >> "$cfgfile"
-#! $SHELL
-
-# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-# NOTE: Changes made to this file will be lost: look at ltmain.sh.
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-# 2006, 2007, 2008 Free Software Foundation, Inc.
-# Written by Gordon Matzigkeit, 1996
-#
-# This file is part of GNU Libtool.
-#
-# GNU Libtool is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# As a special exception to the GNU General Public License,
-# if you distribute this file as part of a program or library that
-# is built using GNU Libtool, you may include this file under the
-# same distribution terms that you use for the rest of that program.
-#
-# GNU Libtool is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Libtool; see the file COPYING. If not, a copy
-# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
-# obtained by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
-# The names of the tagged configurations supported by this script.
-available_tags=""
-
-# ### BEGIN LIBTOOL CONFIG
-
-# Which release of libtool.m4 was used?
-macro_version=$macro_version
-macro_revision=$macro_revision
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# What type of objects to build.
-pic_mode=$pic_mode
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# A sed program that does not truncate output.
-SED=$lt_SED
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="\$SED -e 1s/^X//"
-
-# A grep program that handles long lines.
-GREP=$lt_GREP
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# A literal string matcher.
-FGREP=$lt_FGREP
-
-# A BSD- or MS-compatible name lister.
-NM=$lt_NM
-
-# Whether we need soft or hard links.
-LN_S=$lt_LN_S
-
-# What is the maximum length of a command?
-max_cmd_len=$max_cmd_len
-
-# Object file suffix (normally "o").
-objext=$ac_objext
-
-# Executable file suffix (normally "").
-exeext=$exeext
-
-# whether the shell understands "unset".
-lt_unset=$lt_unset
-
-# turn spaces into newlines.
-SP2NL=$lt_lt_SP2NL
-
-# turn newlines into spaces.
-NL2SP=$lt_lt_NL2SP
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# An object symbol dumper.
-OBJDUMP=$lt_OBJDUMP
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method == "file_magic".
-file_magic_cmd=$lt_file_magic_cmd
-
-# The archiver.
-AR=$lt_AR
-AR_FLAGS=$lt_AR_FLAGS
-
-# A symbol stripping program.
-STRIP=$lt_STRIP
-
-# Commands used to install an old-style archive.
-RANLIB=$lt_RANLIB
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# A C compiler.
-LTCC=$lt_CC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_CFLAGS
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration.
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair.
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# Transform the output of nm in a C name address pair when lib prefix is needed.
-global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# An echo program that does not interpret backslashes.
-ECHO=$lt_ECHO
-
-# Used to examine libraries when file_magic_cmd begins with "file".
-MAGIC_CMD=$MAGIC_CMD
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
-DSYMUTIL=$lt_DSYMUTIL
-
-# Tool to change global to local symbols on Mac OS X.
-NMEDIT=$lt_NMEDIT
-
-# Tool to manipulate fat objects and archives on Mac OS X.
-LIPO=$lt_LIPO
-
-# ldd/readelf like tool for Mach-O binaries on Mac OS X.
-OTOOL=$lt_OTOOL
-
-# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
-OTOOL64=$lt_OTOOL64
-
-# Old archive suffix (normally "a").
-libext=$libext
-
-# Shared library suffix (normally ".so").
-shrext_cmds=$lt_shrext_cmds
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at link time.
-variables_saved_for_relink=$lt_variables_saved_for_relink
-
-# Do we need the "lib" prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Library versioning type.
-version_type=$version_type
-
-# Shared library runtime path variable.
-runpath_var=$runpath_var
-
-# Shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Command to use after installation of a shared archive.
-postinstall_cmds=$lt_postinstall_cmds
-
-# Command to use after uninstallation of a shared archive.
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# As "finish_cmds", except a single script fragment to be evaled but
-# not shown.
-finish_eval=$lt_finish_eval
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Compile-time system search path for libraries.
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries.
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-
-# The linker used to build libraries.
-LD=$lt_LD
-
-# Commands used to build an old-style archive.
-old_archive_cmds=$lt_old_archive_cmds
-
-# A language specific compiler.
-CC=$lt_compiler
-
-# Is the compiler the GNU compiler?
-with_gcc=$GCC
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc
-
-# Whether or not to disallow shared libs when runtime libs are static.
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec
-
-# Whether the compiler copes with passing no objects directly.
-compiler_needs_object=$lt_compiler_needs_object
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
-
-# Commands used to build a shared archive.
-archive_cmds=$lt_archive_cmds
-archive_expsym_cmds=$lt_archive_expsym_cmds
-
-# Commands used to build a loadable module if different from building
-# a shared archive.
-module_cmds=$lt_module_cmds
-module_expsym_cmds=$lt_module_expsym_cmds
-
-# Whether we are building with GNU ld or not.
-with_gnu_ld=$lt_with_gnu_ld
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag
-
-# Flag that enforces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
-
-# If ld is used when linking, flag to hardcode \$libdir into a binary
-# during linking. This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
-
-# Whether we need a single "-rpath" flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator
-
-# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
-# DIR into the resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
-# DIR into the resulting binary and the resulting library dependency is
-# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
-# library is relocated.
-hardcode_direct_absolute=$hardcode_direct_absolute
-
-# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
-# into the resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
-# into the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Set to "yes" if building a shared library automatically hardcodes DIR
-# into the library and all subsequent libraries and executables linked
-# against it.
-hardcode_automatic=$hardcode_automatic
-
-# Set to yes if linker adds runtime paths of dependent libraries
-# to runtime path list.
-inherit_rpath=$inherit_rpath
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path=$lt_fix_srcfile_path
-
-# Set to "yes" if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms
-
-# Commands necessary for linking programs (against libraries) with templates.
-prelink_cmds=$lt_prelink_cmds
-
-# Specify filename containing input files.
-file_list_spec=$lt_file_list_spec
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# ### END LIBTOOL CONFIG
-
-_LT_EOF
-
- case $host_os in
- aix3*)
- cat <<\_LT_EOF >> "$cfgfile"
-# AIX sometimes has problems with the GCC collect2 program. For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
-fi
-_LT_EOF
- ;;
- esac
-
-
-ltmain="$ac_aux_dir/ltmain.sh"
-
-
- # We use sed instead of cat because bash on DJGPP gets confused if
- # if finds mixed CR/LF and LF-only lines. Since sed operates in
- # text mode, it properly converts lines to CR/LF. This bash problem
- # is reportedly fixed, but why not run on old versions too?
- sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
- || (rm -f "$cfgfile"; exit 1)
-
- case $xsi_shell in
- yes)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE. If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
- case ${1} in
- */*) func_dirname_result="${1%/*}${2}" ;;
- * ) func_dirname_result="${3}" ;;
- esac
-}
-
-# func_basename file
-func_basename ()
-{
- func_basename_result="${1##*/}"
-}
-
-# func_dirname_and_basename file append nondir_replacement
-# perform func_basename and func_dirname in a single function
-# call:
-# dirname: Compute the dirname of FILE. If nonempty,
-# add APPEND to the result, otherwise set result
-# to NONDIR_REPLACEMENT.
-# value returned in "$func_dirname_result"
-# basename: Compute filename of FILE.
-# value retuned in "$func_basename_result"
-# Implementation must be kept synchronized with func_dirname
-# and func_basename. For efficiency, we do not delegate to
-# those functions but instead duplicate the functionality here.
-func_dirname_and_basename ()
-{
- case ${1} in
- */*) func_dirname_result="${1%/*}${2}" ;;
- * ) func_dirname_result="${3}" ;;
- esac
- func_basename_result="${1##*/}"
-}
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-func_stripname ()
-{
- # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
- # positional parameters, so assign one to ordinary parameter first.
- func_stripname_result=${3}
- func_stripname_result=${func_stripname_result#"${1}"}
- func_stripname_result=${func_stripname_result%"${2}"}
-}
-
-# func_opt_split
-func_opt_split ()
-{
- func_opt_split_opt=${1%%=*}
- func_opt_split_arg=${1#*=}
-}
-
-# func_lo2o object
-func_lo2o ()
-{
- case ${1} in
- *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
- *) func_lo2o_result=${1} ;;
- esac
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
- func_xform_result=${1%.*}.lo
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
- func_arith_result=$(( $* ))
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
- func_len_result=${#1}
-}
-
-_LT_EOF
- ;;
- *) # Bourne compatible functions.
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE. If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
- # Extract subdirectory from the argument.
- func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
- if test "X$func_dirname_result" = "X${1}"; then
- func_dirname_result="${3}"
- else
- func_dirname_result="$func_dirname_result${2}"
- fi
-}
-
-# func_basename file
-func_basename ()
-{
- func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
-}
-
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-# func_strip_suffix prefix name
-func_stripname ()
-{
- case ${2} in
- .*) func_stripname_result=`$ECHO "X${3}" \
- | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
- *) func_stripname_result=`$ECHO "X${3}" \
- | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
- esac
-}
-
-# sed scripts:
-my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
-my_sed_long_arg='1s/^-[^=]*=//'
-
-# func_opt_split
-func_opt_split ()
-{
- func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
- func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
-}
-
-# func_lo2o object
-func_lo2o ()
-{
- func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
- func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'`
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
- func_arith_result=`expr "$@"`
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
- func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
-}
-
-_LT_EOF
-esac
-
-case $lt_shell_append in
- yes)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
- eval "$1+=\$2"
-}
-_LT_EOF
- ;;
- *)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
- eval "$1=\$$1\$2"
-}
-
-_LT_EOF
- ;;
- esac
-
-
- sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
- || (rm -f "$cfgfile"; exit 1)
-
- mv -f "$cfgfile" "$ofile" ||
- (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
- chmod +x "$ofile"
-
- ;;
-
- esac
-done # for ac_tag
-
-
-as_fn_exit 0
-_ACEOF
-ac_clean_files=$ac_clean_files_save
-
-test $ac_write_fail = 0 ||
- as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded. So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status. When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
- ac_cs_success=:
- ac_config_status_args=
- test "$silent" = yes &&
- ac_config_status_args="$ac_config_status_args --quiet"
- exec 5>/dev/null
- $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
- exec 5>>config.log
- # Use ||, not &&, to avoid exiting from the if with $? = 1, which
- # would make configure fail if this is the last instruction.
- $ac_cs_success || as_fn_exit 1
-fi
-if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
-fi
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/configure.ac b/chromium/third_party/sqlite/sqlite-src-3240000/configure.ac
deleted file mode 100644
index 7089772d197..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/configure.ac
+++ /dev/null
@@ -1,757 +0,0 @@
-#
-# The build process allows for using a cross-compiler. But the default
-# action is to target the same platform that we are running on. The
-# configure script needs to discover the following properties of the
-# build and target systems:
-#
-# srcdir
-#
-# The is the name of the directory that contains the
-# "configure" shell script. All source files are
-# located relative to this directory.
-#
-# bindir
-#
-# The name of the directory where executables should be
-# written by the "install" target of the makefile.
-#
-# program_prefix
-#
-# Add this prefix to the names of all executables that run
-# on the target machine. Default: ""
-#
-# ENABLE_SHARED
-#
-# True if shared libraries should be generated.
-#
-# BUILD_CC
-#
-# The name of a command that is used to convert C
-# source files into executables that run on the build
-# platform.
-#
-# BUILD_CFLAGS
-#
-# Switches that the build compiler needs in order to construct
-# command-line programs.
-#
-# BUILD_LIBS
-#
-# Libraries that the build compiler needs in order to construct
-# command-line programs.
-#
-# BUILD_EXEEXT
-#
-# The filename extension for executables on the build
-# platform. "" for Unix and ".exe" for Windows.
-#
-# TCL_*
-#
-# Lots of values are read in from the tclConfig.sh script,
-# if that script is available. This values are used for
-# constructing and installing the TCL extension.
-#
-# TARGET_READLINE_LIBS
-#
-# This is the library directives passed to the target linker
-# that cause the executable to link against the readline library.
-# This might be a switch like "-lreadline" or pathnames of library
-# file like "../../src/libreadline.a".
-#
-# TARGET_READLINE_INC
-#
-# This variables define the directory that contain header
-# files for the readline library. If the compiler is able
-# to find <readline.h> on its own, then this can be blank.
-#
-# TARGET_EXEEXT
-#
-# The filename extension for executables on the
-# target platform. "" for Unix and ".exe" for windows.
-#
-# This configure.in file is easy to reuse on other projects. Just
-# change the argument to AC_INIT(). And disable any features that
-# you don't need (for example BLT) by erasing or commenting out
-# the corresponding code.
-#
-AC_INIT(sqlite, m4_esyscmd([cat VERSION | tr -d '\n']))
-
-dnl Make sure the local VERSION file matches this configure script
-sqlite_version_sanity_check=`cat $srcdir/VERSION | tr -d '\n'`
-if test "$PACKAGE_VERSION" != "$sqlite_version_sanity_check" ; then
-AC_MSG_ERROR([configure script is out of date:
- configure \$PACKAGE_VERSION = $PACKAGE_VERSION
- top level VERSION file = $sqlite_version_sanity_check
-please regen with autoconf])
-fi
-
-#########
-# Programs needed
-#
-AC_PROG_LIBTOOL
-AC_PROG_INSTALL
-
-#########
-# Enable large file support (if special flags are necessary)
-#
-AC_SYS_LARGEFILE
-
-#########
-# Check for needed/wanted data types
-AC_CHECK_TYPES([int8_t, int16_t, int32_t, int64_t, intptr_t, uint8_t,
- uint16_t, uint32_t, uint64_t, uintptr_t])
-
-#########
-# Check for needed/wanted headers
-AC_CHECK_HEADERS([sys/types.h stdlib.h stdint.h inttypes.h malloc.h])
-
-#########
-# Figure out whether or not we have these functions
-#
-AC_CHECK_FUNCS([fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64])
-
-#########
-# By default, we use the amalgamation (this may be changed below...)
-#
-USE_AMALGAMATION=1
-
-#########
-# See whether we can run specific tclsh versions known to work well;
-# if not, then we fall back to plain tclsh.
-# TODO: try other versions before falling back?
-#
-AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.7 tclsh8.6 tclsh8.5 tclsh], none)
-if test "$TCLSH_CMD" = "none"; then
- # If we can't find a local tclsh, then building the amalgamation will fail.
- # We act as though --disable-amalgamation has been used.
- echo "Warning: can't find tclsh - defaulting to non-amalgamation build."
- USE_AMALGAMATION=0
- TCLSH_CMD="tclsh"
-fi
-AC_SUBST(TCLSH_CMD)
-
-AC_ARG_VAR([TCLLIBDIR], [Where to install tcl plugin])
-if test "x${TCLLIBDIR+set}" != "xset" ; then
- TCLLIBDIR='$(libdir)'
- for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
- TCLLIBDIR=$i
- break
- done
- TCLLIBDIR="${TCLLIBDIR}/sqlite3"
-fi
-
-
-#########
-# Set up an appropriate program prefix
-#
-if test "$program_prefix" = "NONE"; then
- program_prefix=""
-fi
-AC_SUBST(program_prefix)
-
-VERSION=[`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`]
-AC_MSG_NOTICE(Version set to $VERSION)
-AC_SUBST(VERSION)
-RELEASE=`cat $srcdir/VERSION`
-AC_MSG_NOTICE(Release set to $RELEASE)
-AC_SUBST(RELEASE)
-VERSION_NUMBER=[`cat $srcdir/VERSION \
- | sed 's/[^0-9]/ /g' \
- | awk '{printf "%d%03d%03d",$1,$2,$3}'`]
-AC_MSG_NOTICE(Version number set to $VERSION_NUMBER)
-AC_SUBST(VERSION_NUMBER)
-
-#########
-# Locate a compiler for the build machine. This compiler should
-# generate command-line programs that run on the build machine.
-#
-if test x"$cross_compiling" = xno; then
- BUILD_CC=$CC
- BUILD_CFLAGS=$CFLAGS
-else
- if test "${BUILD_CC+set}" != set; then
- AC_CHECK_PROGS(BUILD_CC, gcc cc cl)
- fi
- if test "${BUILD_CFLAGS+set}" != set; then
- BUILD_CFLAGS="-g"
- fi
-fi
-AC_SUBST(BUILD_CC)
-
-##########
-# Do we want to support multithreaded use of sqlite
-#
-AC_ARG_ENABLE(threadsafe,
-AC_HELP_STRING([--disable-threadsafe],[Disable mutexing]),,enable_threadsafe=yes)
-AC_MSG_CHECKING([whether to support threadsafe operation])
-if test "$enable_threadsafe" = "no"; then
- SQLITE_THREADSAFE=0
- AC_MSG_RESULT([no])
-else
- SQLITE_THREADSAFE=1
- AC_MSG_RESULT([yes])
-fi
-AC_SUBST(SQLITE_THREADSAFE)
-
-if test "$SQLITE_THREADSAFE" = "1"; then
- AC_SEARCH_LIBS(pthread_create, pthread)
- AC_SEARCH_LIBS(pthread_mutexattr_init, pthread)
-fi
-
-##########
-# Do we want to support release
-#
-AC_ARG_ENABLE(releasemode,
-AC_HELP_STRING([--enable-releasemode],[Support libtool link to release mode]),,enable_releasemode=no)
-AC_MSG_CHECKING([whether to support shared library linked as release mode or not])
-if test "$enable_releasemode" = "no"; then
- ALLOWRELEASE=""
- AC_MSG_RESULT([no])
-else
- ALLOWRELEASE="-release `cat $srcdir/VERSION`"
- AC_MSG_RESULT([yes])
-fi
-AC_SUBST(ALLOWRELEASE)
-
-##########
-# Do we want temporary databases in memory
-#
-AC_ARG_ENABLE(tempstore,
-AC_HELP_STRING([--enable-tempstore],[Use an in-ram database for temporary tables (never,no,yes,always)]),,enable_tempstore=no)
-AC_MSG_CHECKING([whether to use an in-ram database for temporary tables])
-case "$enable_tempstore" in
- never )
- TEMP_STORE=0
- AC_MSG_RESULT([never])
- ;;
- no )
- TEMP_STORE=1
- AC_MSG_RESULT([no])
- ;;
- yes )
- TEMP_STORE=2
- AC_MSG_RESULT([yes])
- ;;
- always )
- TEMP_STORE=3
- AC_MSG_RESULT([always])
- ;;
- * )
- TEMP_STORE=1
- AC_MSG_RESULT([no])
- ;;
-esac
-
-AC_SUBST(TEMP_STORE)
-
-###########
-# Lots of things are different if we are compiling for Windows using
-# the CYGWIN environment. So check for that special case and handle
-# things accordingly.
-#
-AC_MSG_CHECKING([if executables have the .exe suffix])
-if test "$config_BUILD_EXEEXT" = ".exe"; then
- CYGWIN=yes
- AC_MSG_RESULT(yes)
-else
- AC_MSG_RESULT(unknown)
-fi
-if test "$CYGWIN" != "yes"; then
- AC_CYGWIN
-fi
-if test "$CYGWIN" = "yes"; then
- BUILD_EXEEXT=.exe
-else
- BUILD_EXEEXT=$EXEEXT
-fi
-if test x"$cross_compiling" = xno; then
- TARGET_EXEEXT=$BUILD_EXEEXT
-else
- TARGET_EXEEXT=$config_TARGET_EXEEXT
-fi
-if test "$TARGET_EXEEXT" = ".exe"; then
- SQLITE_OS_UNIX=0
- SQLITE_OS_WIN=1
- CFLAGS="$CFLAGS -DSQLITE_OS_WIN=1"
-else
- SQLITE_OS_UNIX=1
- SQLITE_OS_WIN=0
- CFLAGS="$CFLAGS -DSQLITE_OS_UNIX=1"
-fi
-
-AC_SUBST(BUILD_EXEEXT)
-AC_SUBST(SQLITE_OS_UNIX)
-AC_SUBST(SQLITE_OS_WIN)
-AC_SUBST(TARGET_EXEEXT)
-
-##########
-# Figure out all the parameters needed to compile against Tcl.
-#
-# This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG
-# macros in the in the tcl.m4 file of the standard TCL distribution.
-# Those macros could not be used directly since we have to make some
-# minor changes to accomodate systems that do not have TCL installed.
-#
-AC_ARG_ENABLE(tcl, AC_HELP_STRING([--disable-tcl],[do not build TCL extension]),
- [use_tcl=$enableval],[use_tcl=yes])
-if test "${use_tcl}" = "yes" ; then
- AC_ARG_WITH(tcl, AC_HELP_STRING([--with-tcl=DIR],[directory containing tcl configuration (tclConfig.sh)]), with_tclconfig=${withval})
- AC_MSG_CHECKING([for Tcl configuration])
- AC_CACHE_VAL(ac_cv_c_tclconfig,[
- # First check to see if --with-tcl was specified.
- if test x"${with_tclconfig}" != x ; then
- if test -f "${with_tclconfig}/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
- else
- AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
- fi
- fi
-
- # Start autosearch by asking tclsh
- if test x"${ac_cv_c_tclconfig}" = x ; then
- if test x"$cross_compiling" = xno; then
- for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}`
- do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig="$i"
- break
- fi
- done
- fi
- fi
-
- # On ubuntu 14.10, $auto_path on tclsh is not quite correct.
- # So try again after applying corrections.
- if test x"${ac_cv_c_tclconfig}" = x ; then
- if test x"$cross_compiling" = xno; then
- for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'`
- do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig="$i"
- break
- fi
- done
- fi
- fi
-
- # Recent versions of Xcode on Macs hid the tclConfig.sh file
- # in a strange place.
- if test x"${ac_cv_c_tclconfig}" = x ; then
- if test x"$cross_compiling" = xno; then
- for i in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX*.sdk/usr/lib
- do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig="$i"
- break
- fi
- done
- fi
- fi
-
- # then check for a private Tcl installation
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in \
- ../tcl \
- `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
- ../../tcl \
- `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
- ../../../tcl \
- `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null`
- do
- if test -f "$i/unix/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
- break
- fi
- done
- fi
-
- # check in a few common install locations
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in \
- `ls -d ${libdir} 2>/dev/null` \
- `ls -d /usr/local/lib 2>/dev/null` \
- `ls -d /usr/contrib/lib 2>/dev/null` \
- `ls -d /usr/lib 2>/dev/null`
- do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd $i; pwd)`
- break
- fi
- done
- fi
-
- # check in a few other private locations
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in \
- ${srcdir}/../tcl \
- `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
- `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
- `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null`
- do
- if test -f "$i/unix/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
- break
- fi
- done
- fi
- ])
-
- if test x"${ac_cv_c_tclconfig}" = x ; then
- use_tcl=no
- AC_MSG_WARN(Can't find Tcl configuration definitions)
- AC_MSG_WARN(*** Without Tcl the regression tests cannot be executed ***)
- AC_MSG_WARN(*** Consider using --with-tcl=... to define location of Tcl ***)
- else
- TCL_BIN_DIR=${ac_cv_c_tclconfig}
- AC_MSG_RESULT(found $TCL_BIN_DIR/tclConfig.sh)
-
- AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh])
- if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
- AC_MSG_RESULT([loading])
- . $TCL_BIN_DIR/tclConfig.sh
- else
- AC_MSG_RESULT([file not found])
- fi
-
- #
- # If the TCL_BIN_DIR is the build directory (not the install directory),
- # then set the common variable name to the value of the build variables.
- # For example, the variable TCL_LIB_SPEC will be set to the value
- # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
- # instead of TCL_BUILD_LIB_SPEC since it will work with both an
- # installed and uninstalled version of Tcl.
- #
-
- if test -f $TCL_BIN_DIR/Makefile ; then
- TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
- TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
- TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
- fi
-
- #
- # eval is required to do the TCL_DBGX substitution
- #
-
- eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
- eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
- eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
-
- eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
- eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
- eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
-
- AC_SUBST(TCL_VERSION)
- AC_SUBST(TCL_BIN_DIR)
- AC_SUBST(TCL_SRC_DIR)
- AC_SUBST(TCL_INCLUDE_SPEC)
-
- AC_SUBST(TCL_LIB_FILE)
- AC_SUBST(TCL_LIB_FLAG)
- AC_SUBST(TCL_LIB_SPEC)
-
- AC_SUBST(TCL_STUB_LIB_FILE)
- AC_SUBST(TCL_STUB_LIB_FLAG)
- AC_SUBST(TCL_STUB_LIB_SPEC)
- AC_SUBST(TCL_SHLIB_SUFFIX)
- fi
-fi
-if test "${use_tcl}" = "no" ; then
- HAVE_TCL=""
-else
- HAVE_TCL=1
-fi
-AC_SUBST(HAVE_TCL)
-
-##########
-# Figure out what C libraries are required to compile programs
-# that use "readline()" library.
-#
-TARGET_READLINE_LIBS=""
-TARGET_READLINE_INC=""
-TARGET_HAVE_READLINE=0
-TARGET_HAVE_EDITLINE=0
-AC_ARG_ENABLE([editline],
- [AC_HELP_STRING([--enable-editline],[enable BSD editline support])],
- [with_editline=$enableval],
- [with_editline=auto])
-AC_ARG_ENABLE([readline],
- [AC_HELP_STRING([--disable-readline],[disable readline support])],
- [with_readline=$enableval],
- [with_readline=auto])
-
-if test x"$with_editline" != xno; then
- sLIBS=$LIBS
- LIBS=""
- TARGET_HAVE_EDITLINE=1
- AC_SEARCH_LIBS(readline,edit,[with_readline=no],[TARGET_HAVE_EDITLINE=0])
- TARGET_READLINE_LIBS=$LIBS
- LIBS=$sLIBS
-fi
-if test x"$with_readline" != xno; then
- found="yes"
-
- AC_ARG_WITH([readline-lib],
- [AC_HELP_STRING([--with-readline-lib],[specify readline library])],
- [with_readline_lib=$withval],
- [with_readline_lib="auto"])
- if test "x$with_readline_lib" = xauto; then
- save_LIBS="$LIBS"
- LIBS=""
- AC_SEARCH_LIBS(tgetent, [readline ncurses curses termcap], [term_LIBS="$LIBS"], [term_LIBS=""])
- AC_CHECK_LIB([readline], [readline], [TARGET_READLINE_LIBS="-lreadline"], [found="no"])
- TARGET_READLINE_LIBS="$TARGET_READLINE_LIBS $term_LIBS"
- LIBS="$save_LIBS"
- else
- TARGET_READLINE_LIBS="$with_readline_lib"
- fi
-
- AC_ARG_WITH([readline-inc],
- [AC_HELP_STRING([--with-readline-inc],[specify readline include paths])],
- [with_readline_inc=$withval],
- [with_readline_inc="auto"])
- if test "x$with_readline_inc" = xauto; then
- AC_CHECK_HEADER(readline.h, [found="yes"], [
- found="no"
- if test "$cross_compiling" != yes; then
- for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do
- for subdir in include include/readline; do
- AC_CHECK_FILE($dir/$subdir/readline.h, found=yes)
- if test "$found" = "yes"; then
- TARGET_READLINE_INC="-I$dir/$subdir"
- break
- fi
- done
- test "$found" = "yes" && break
- done
- fi
- ])
- else
- TARGET_READLINE_INC="$with_readline_inc"
- fi
-
- if test x"$found" = xno; then
- TARGET_READLINE_LIBS=""
- TARGET_READLINE_INC=""
- TARGET_HAVE_READLINE=0
- else
- TARGET_HAVE_READLINE=1
- fi
-fi
-
-AC_SUBST(TARGET_READLINE_LIBS)
-AC_SUBST(TARGET_READLINE_INC)
-AC_SUBST(TARGET_HAVE_READLINE)
-AC_SUBST(TARGET_HAVE_EDITLINE)
-
-##########
-# Figure out what C libraries are required to compile programs
-# that use "fdatasync()" function.
-#
-AC_SEARCH_LIBS(fdatasync, [rt])
-
-#########
-# check for debug enabled
-AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]),
- [use_debug=$enableval],[use_debug=no])
-if test "${use_debug}" = "yes" ; then
- TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
-else
- TARGET_DEBUG="-DNDEBUG"
-fi
-AC_SUBST(TARGET_DEBUG)
-
-#########
-# See whether we should use the amalgamation to build
-AC_ARG_ENABLE(amalgamation, AC_HELP_STRING([--disable-amalgamation],
- [Disable the amalgamation and instead build all files separately]),
- [use_amalgamation=$enableval],[use_amalgamation=yes])
-if test "${use_amalgamation}" != "yes" ; then
- USE_AMALGAMATION=0
-fi
-AC_SUBST(USE_AMALGAMATION)
-
-#########
-# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
-AC_CHECK_HEADERS(zlib.h)
-AC_SEARCH_LIBS(deflate, z, [HAVE_ZLIB="-DSQLITE_HAVE_ZLIB=1"], [HAVE_ZLIB=""])
-AC_SUBST(HAVE_ZLIB)
-
-#########
-# See whether we should allow loadable extensions
-AC_ARG_ENABLE(load-extension, AC_HELP_STRING([--disable-load-extension],
- [Disable loading of external extensions]),
- [use_loadextension=$enableval],[use_loadextension=yes])
-if test "${use_loadextension}" = "yes" ; then
- OPT_FEATURE_FLAGS=""
- AC_SEARCH_LIBS(dlopen, dl)
-else
- OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
-fi
-
-##########
-# Do we want to support memsys3 and/or memsys5
-#
-AC_ARG_ENABLE(memsys5,
- AC_HELP_STRING([--enable-memsys5],[Enable MEMSYS5]),
- [enable_memsys5=yes],[enable_memsys5=no])
-AC_MSG_CHECKING([whether to support MEMSYS5])
-if test "${enable_memsys5}" = "yes"; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
- AC_MSG_RESULT([yes])
-else
- AC_MSG_RESULT([no])
-fi
-AC_ARG_ENABLE(memsys3,
- AC_HELP_STRING([--enable-memsys3],[Enable MEMSYS3]),
- [enable_memsys3=yes],[enable_memsys3=no])
-AC_MSG_CHECKING([whether to support MEMSYS3])
-if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
- AC_MSG_RESULT([yes])
-else
- AC_MSG_RESULT([no])
-fi
-
-#########
-# See whether we should enable Full Text Search extensions
-AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
- [Enable the FTS3 extension]),
- [enable_fts3=yes],[enable_fts3=no])
-if test "${enable_fts3}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
-fi
-AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
- [Enable the FTS4 extension]),
- [enable_fts4=yes],[enable_fts4=no])
-if test "${enable_fts4}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
- AC_SEARCH_LIBS([log],[m])
-fi
-AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
- [Enable the FTS5 extension]),
- [enable_fts5=yes],[enable_fts5=no])
-if test "${enable_fts5}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
- AC_SEARCH_LIBS([log],[m])
-fi
-
-#########
-# See whether we should enable JSON1
-AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],
- [Enable the JSON1 extension]),
- [enable_json1=yes],[enable_json1=no])
-if test "${enable_json1}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
-fi
-
-#########
-# See whether we should enable the LIMIT clause on UPDATE and DELETE
-# statements.
-AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
- [Enable the UPDATE/DELETE LIMIT clause]),
- [enable_udlimit=yes],[enable_udlimit=no])
-if test "${enable_udlimit}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
-fi
-
-#########
-# See whether we should enable RTREE
-AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
- [Enable the RTREE extension]),
- [enable_rtree=yes],[enable_rtree=no])
-if test "${enable_rtree}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
-fi
-
-#########
-# See whether we should enable the SESSION extension
-AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
- [Enable the SESSION extension]),
- [enable_session=yes],[enable_session=no])
-if test "${enable_session}" = "yes" ; then
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
- OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
-fi
-
-#########
-# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
-for option in $CFLAGS $CPPFLAGS
-do
- case $option in
- -DSQLITE_OMIT*) OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS $option";;
- -DSQLITE_ENABLE*) OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS $option";;
- esac
-done
-AC_SUBST(OPT_FEATURE_FLAGS)
-
-
-# attempt to remove any OMITS and ENABLES from the $(CFLAGS) parameter
-ac_temp_CFLAGS=""
-for option in $CFLAGS
-do
- case $option in
- -DSQLITE_OMIT*) ;;
- -DSQLITE_ENABLE*) ;;
- *) ac_temp_CFLAGS="$ac_temp_CFLAGS $option";;
- esac
-done
-CFLAGS=$ac_temp_CFLAGS
-
-
-# attempt to remove any OMITS and ENABLES from the $(CPPFLAGS) parameter
-ac_temp_CPPFLAGS=""
-for option in $CPPFLAGS
-do
- case $option in
- -DSQLITE_OMIT*) ;;
- -DSQLITE_ENABLE*) ;;
- *) ac_temp_CPPFLAGS="$ac_temp_CPPFLAGS $option";;
- esac
-done
-CPPFLAGS=$ac_temp_CPPFLAGS
-
-
-# attempt to remove any OMITS and ENABLES from the $(BUILD_CFLAGS) parameter
-ac_temp_BUILD_CFLAGS=""
-for option in $BUILD_CFLAGS
-do
- case $option in
- -DSQLITE_OMIT*) ;;
- -DSQLITE_ENABLE*) ;;
- *) ac_temp_BUILD_CFLAGS="$ac_temp_BUILD_CFLAGS $option";;
- esac
-done
-BUILD_CFLAGS=$ac_temp_BUILD_CFLAGS
-
-
-#########
-# See whether we should use GCOV
-AC_ARG_ENABLE(gcov, AC_HELP_STRING([--enable-gcov],
- [Enable coverage testing using gcov]),
- [use_gcov=$enableval],[use_gcov=no])
-if test "${use_gcov}" = "yes" ; then
- USE_GCOV=1
-else
- USE_GCOV=0
-fi
-AC_SUBST(USE_GCOV)
-
-
-#########
-# Output the config header
-AC_CONFIG_HEADERS(config.h)
-
-#########
-# Generate the output files.
-#
-AC_SUBST(BUILD_CFLAGS)
-AC_OUTPUT([
-Makefile
-sqlite3.pc
-])
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/contrib/sqlitecon.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/contrib/sqlitecon.tcl
deleted file mode 100644
index b5dbcafc2a5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/contrib/sqlitecon.tcl
+++ /dev/null
@@ -1,679 +0,0 @@
-# A Tk console widget for SQLite. Invoke sqlitecon::create with a window name,
-# a prompt string, a title to set a new top-level window, and the SQLite
-# database handle. For example:
-#
-# sqlitecon::create .sqlcon {sql:- } {SQL Console} db
-#
-# A toplevel window is created that allows you to type in SQL commands to
-# be processed on the spot.
-#
-# A limited set of dot-commands are supported:
-#
-# .table
-# .schema ?TABLE?
-# .mode list|column|multicolumn|line
-# .exit
-#
-# In addition, a new SQL function named "edit()" is created. This function
-# takes a single text argument and returns a text result. Whenever the
-# the function is called, it pops up a new toplevel window containing a
-# text editor screen initialized to the argument. When the "OK" button
-# is pressed, whatever revised text is in the text editor is returned as
-# the result of the edit() function. This allows text fields of SQL tables
-# to be edited quickly and easily as follows:
-#
-# UPDATE table1 SET dscr = edit(dscr) WHERE rowid=15;
-#
-
-
-# Create a namespace to work in
-#
-namespace eval ::sqlitecon {
- # do nothing
-}
-
-# Create a console widget named $w. The prompt string is $prompt.
-# The title at the top of the window is $title. The database connection
-# object is $db
-#
-proc sqlitecon::create {w prompt title db} {
- upvar #0 $w.t v
- if {[winfo exists $w]} {destroy $w}
- if {[info exists v]} {unset v}
- toplevel $w
- wm title $w $title
- wm iconname $w $title
- frame $w.mb -bd 2 -relief raised
- pack $w.mb -side top -fill x
- menubutton $w.mb.file -text File -menu $w.mb.file.m
- menubutton $w.mb.edit -text Edit -menu $w.mb.edit.m
- pack $w.mb.file $w.mb.edit -side left -padx 8 -pady 1
- set m [menu $w.mb.file.m -tearoff 0]
- $m add command -label {Close} -command "destroy $w"
- sqlitecon::create_child $w $prompt $w.mb.edit.m
- set v(db) $db
- $db function edit ::sqlitecon::_edit
-}
-
-# This routine creates a console as a child window within a larger
-# window. It also creates an edit menu named "$editmenu" if $editmenu!="".
-# The calling function is responsible for posting the edit menu.
-#
-proc sqlitecon::create_child {w prompt editmenu} {
- upvar #0 $w.t v
- if {$editmenu!=""} {
- set m [menu $editmenu -tearoff 0]
- $m add command -label Cut -command "sqlitecon::Cut $w.t"
- $m add command -label Copy -command "sqlitecon::Copy $w.t"
- $m add command -label Paste -command "sqlitecon::Paste $w.t"
- $m add command -label {Clear Screen} -command "sqlitecon::Clear $w.t"
- $m add separator
- $m add command -label {Save As...} -command "sqlitecon::SaveFile $w.t"
- catch {$editmenu config -postcommand "sqlitecon::EnableEditMenu $w"}
- }
- scrollbar $w.sb -orient vertical -command "$w.t yview"
- pack $w.sb -side right -fill y
- text $w.t -font fixed -yscrollcommand "$w.sb set"
- pack $w.t -side right -fill both -expand 1
- bindtags $w.t Sqlitecon
- set v(editmenu) $editmenu
- set v(history) 0
- set v(historycnt) 0
- set v(current) -1
- set v(prompt) $prompt
- set v(prior) {}
- set v(plength) [string length $v(prompt)]
- set v(x) 0
- set v(y) 0
- set v(mode) column
- set v(header) on
- $w.t mark set insert end
- $w.t tag config ok -foreground blue
- $w.t tag config err -foreground red
- $w.t insert end $v(prompt)
- $w.t mark set out 1.0
- after idle "focus $w.t"
-}
-
-bind Sqlitecon <1> {sqlitecon::Button1 %W %x %y}
-bind Sqlitecon <B1-Motion> {sqlitecon::B1Motion %W %x %y}
-bind Sqlitecon <B1-Leave> {sqlitecon::B1Leave %W %x %y}
-bind Sqlitecon <B1-Enter> {sqlitecon::cancelMotor %W}
-bind Sqlitecon <ButtonRelease-1> {sqlitecon::cancelMotor %W}
-bind Sqlitecon <KeyPress> {sqlitecon::Insert %W %A}
-bind Sqlitecon <Left> {sqlitecon::Left %W}
-bind Sqlitecon <Control-b> {sqlitecon::Left %W}
-bind Sqlitecon <Right> {sqlitecon::Right %W}
-bind Sqlitecon <Control-f> {sqlitecon::Right %W}
-bind Sqlitecon <BackSpace> {sqlitecon::Backspace %W}
-bind Sqlitecon <Control-h> {sqlitecon::Backspace %W}
-bind Sqlitecon <Delete> {sqlitecon::Delete %W}
-bind Sqlitecon <Control-d> {sqlitecon::Delete %W}
-bind Sqlitecon <Home> {sqlitecon::Home %W}
-bind Sqlitecon <Control-a> {sqlitecon::Home %W}
-bind Sqlitecon <End> {sqlitecon::End %W}
-bind Sqlitecon <Control-e> {sqlitecon::End %W}
-bind Sqlitecon <Return> {sqlitecon::Enter %W}
-bind Sqlitecon <KP_Enter> {sqlitecon::Enter %W}
-bind Sqlitecon <Up> {sqlitecon::Prior %W}
-bind Sqlitecon <Control-p> {sqlitecon::Prior %W}
-bind Sqlitecon <Down> {sqlitecon::Next %W}
-bind Sqlitecon <Control-n> {sqlitecon::Next %W}
-bind Sqlitecon <Control-k> {sqlitecon::EraseEOL %W}
-bind Sqlitecon <<Cut>> {sqlitecon::Cut %W}
-bind Sqlitecon <<Copy>> {sqlitecon::Copy %W}
-bind Sqlitecon <<Paste>> {sqlitecon::Paste %W}
-bind Sqlitecon <<Clear>> {sqlitecon::Clear %W}
-
-# Insert a single character at the insertion cursor
-#
-proc sqlitecon::Insert {w a} {
- $w insert insert $a
- $w yview insert
-}
-
-# Move the cursor one character to the left
-#
-proc sqlitecon::Left {w} {
- upvar #0 $w v
- scan [$w index insert] %d.%d row col
- if {$col>$v(plength)} {
- $w mark set insert "insert -1c"
- }
-}
-
-# Erase the character to the left of the cursor
-#
-proc sqlitecon::Backspace {w} {
- upvar #0 $w v
- scan [$w index insert] %d.%d row col
- if {$col>$v(plength)} {
- $w delete {insert -1c}
- }
-}
-
-# Erase to the end of the line
-#
-proc sqlitecon::EraseEOL {w} {
- upvar #0 $w v
- scan [$w index insert] %d.%d row col
- if {$col>=$v(plength)} {
- $w delete insert {insert lineend}
- }
-}
-
-# Move the cursor one character to the right
-#
-proc sqlitecon::Right {w} {
- $w mark set insert "insert +1c"
-}
-
-# Erase the character to the right of the cursor
-#
-proc sqlitecon::Delete w {
- $w delete insert
-}
-
-# Move the cursor to the beginning of the current line
-#
-proc sqlitecon::Home w {
- upvar #0 $w v
- scan [$w index insert] %d.%d row col
- $w mark set insert $row.$v(plength)
-}
-
-# Move the cursor to the end of the current line
-#
-proc sqlitecon::End w {
- $w mark set insert {insert lineend}
-}
-
-# Add a line to the history
-#
-proc sqlitecon::addHistory {w line} {
- upvar #0 $w v
- if {$v(historycnt)>0} {
- set last [lindex $v(history) [expr $v(historycnt)-1]]
- if {[string compare $last $line]} {
- lappend v(history) $line
- incr v(historycnt)
- }
- } else {
- set v(history) [list $line]
- set v(historycnt) 1
- }
- set v(current) $v(historycnt)
-}
-
-# Called when "Enter" is pressed. Do something with the line
-# of text that was entered.
-#
-proc sqlitecon::Enter w {
- upvar #0 $w v
- scan [$w index insert] %d.%d row col
- set start $row.$v(plength)
- set line [$w get $start "$start lineend"]
- $w insert end \n
- $w mark set out end
- if {$v(prior)==""} {
- set cmd $line
- } else {
- set cmd $v(prior)\n$line
- }
- if {[string index $cmd 0]=="." || [$v(db) complete $cmd]} {
- regsub -all {\n} [string trim $cmd] { } cmd2
- addHistory $w $cmd2
- set rc [catch {DoCommand $w $cmd} res]
- if {![winfo exists $w]} return
- if {$rc} {
- $w insert end $res\n err
- } elseif {[string length $res]>0} {
- $w insert end $res\n ok
- }
- set v(prior) {}
- $w insert end $v(prompt)
- } else {
- set v(prior) $cmd
- regsub -all {[^ ]} $v(prompt) . x
- $w insert end $x
- }
- $w mark set insert end
- $w mark set out {insert linestart}
- $w yview insert
-}
-
-# Execute a single SQL command. Pay special attention to control
-# directives that begin with "."
-#
-# The return value is the text output from the command, properly
-# formatted.
-#
-proc sqlitecon::DoCommand {w cmd} {
- upvar #0 $w v
- set mode $v(mode)
- set header $v(header)
- if {[regexp {^(\.[a-z]+)} $cmd all word]} {
- if {$word==".mode"} {
- regexp {^.[a-z]+ +([a-z]+)} $cmd all v(mode)
- return {}
- } elseif {$word==".exit"} {
- destroy [winfo toplevel $w]
- return {}
- } elseif {$word==".header"} {
- regexp {^.[a-z]+ +([a-z]+)} $cmd all v(header)
- return {}
- } elseif {$word==".tables"} {
- set mode multicolumn
- set cmd {SELECT name FROM sqlite_master WHERE type='table'
- UNION ALL
- SELECT name FROM sqlite_temp_master WHERE type='table'}
- $v(db) eval {PRAGMA database_list} {
- if {$name!="temp" && $name!="main"} {
- append cmd "UNION ALL SELECT name FROM $name.sqlite_master\
- WHERE type='table'"
- }
- }
- append cmd { ORDER BY 1}
- } elseif {$word==".fullschema"} {
- set pattern %
- regexp {^.[a-z]+ +([^ ]+)} $cmd all pattern
- set mode list
- set header 0
- set cmd "SELECT sql FROM sqlite_master WHERE tbl_name LIKE '$pattern'
- AND sql NOT NULL UNION ALL SELECT sql FROM sqlite_temp_master
- WHERE tbl_name LIKE '$pattern' AND sql NOT NULL"
- $v(db) eval {PRAGMA database_list} {
- if {$name!="temp" && $name!="main"} {
- append cmd " UNION ALL SELECT sql FROM $name.sqlite_master\
- WHERE tbl_name LIKE '$pattern' AND sql NOT NULL"
- }
- }
- } elseif {$word==".schema"} {
- set pattern %
- regexp {^.[a-z]+ +([^ ]+)} $cmd all pattern
- set mode list
- set header 0
- set cmd "SELECT sql FROM sqlite_master WHERE name LIKE '$pattern'
- AND sql NOT NULL UNION ALL SELECT sql FROM sqlite_temp_master
- WHERE name LIKE '$pattern' AND sql NOT NULL"
- $v(db) eval {PRAGMA database_list} {
- if {$name!="temp" && $name!="main"} {
- append cmd " UNION ALL SELECT sql FROM $name.sqlite_master\
- WHERE name LIKE '$pattern' AND sql NOT NULL"
- }
- }
- } else {
- return \
- ".exit\n.mode line|list|column\n.schema ?TABLENAME?\n.tables"
- }
- }
- set res {}
- if {$mode=="list"} {
- $v(db) eval $cmd x {
- set sep {}
- foreach col $x(*) {
- append res $sep$x($col)
- set sep |
- }
- append res \n
- }
- if {[info exists x(*)] && $header} {
- set sep {}
- set hdr {}
- foreach col $x(*) {
- append hdr $sep$col
- set sep |
- }
- set res $hdr\n$res
- }
- } elseif {[string range $mode 0 2]=="col"} {
- set y {}
- $v(db) eval $cmd x {
- foreach col $x(*) {
- if {![info exists cw($col)] || $cw($col)<[string length $x($col)]} {
- set cw($col) [string length $x($col)]
- }
- lappend y $x($col)
- }
- }
- if {[info exists x(*)] && $header} {
- set hdr {}
- set ln {}
- set dash ---------------------------------------------------------------
- append dash ------------------------------------------------------------
- foreach col $x(*) {
- if {![info exists cw($col)] || $cw($col)<[string length $col]} {
- set cw($col) [string length $col]
- }
- lappend hdr $col
- lappend ln [string range $dash 1 $cw($col)]
- }
- set y [concat $hdr $ln $y]
- }
- if {[info exists x(*)]} {
- set format {}
- set arglist {}
- set arglist2 {}
- set i 0
- foreach col $x(*) {
- lappend arglist x$i
- append arglist2 " \$x$i"
- incr i
- append format " %-$cw($col)s"
- }
- set format [string trimleft $format]\n
- if {[llength $arglist]>0} {
- foreach $arglist $y "append res \[format [list $format] $arglist2\]"
- }
- }
- } elseif {$mode=="multicolumn"} {
- set y [$v(db) eval $cmd]
- set max 0
- foreach e $y {
- if {$max<[string length $e]} {set max [string length $e]}
- }
- set ncol [expr {int(80/($max+2))}]
- if {$ncol<1} {set ncol 1}
- set nelem [llength $y]
- set nrow [expr {($nelem+$ncol-1)/$ncol}]
- set format "%-${max}s"
- for {set i 0} {$i<$nrow} {incr i} {
- set j $i
- while 1 {
- append res [format $format [lindex $y $j]]
- incr j $nrow
- if {$j>=$nelem} break
- append res { }
- }
- append res \n
- }
- } else {
- $v(db) eval $cmd x {
- foreach col $x(*) {append res "$col = $x($col)\n"}
- append res \n
- }
- }
- return [string trimright $res]
-}
-
-# Change the line to the previous line
-#
-proc sqlitecon::Prior w {
- upvar #0 $w v
- if {$v(current)<=0} return
- incr v(current) -1
- set line [lindex $v(history) $v(current)]
- sqlitecon::SetLine $w $line
-}
-
-# Change the line to the next line
-#
-proc sqlitecon::Next w {
- upvar #0 $w v
- if {$v(current)>=$v(historycnt)} return
- incr v(current) 1
- set line [lindex $v(history) $v(current)]
- sqlitecon::SetLine $w $line
-}
-
-# Change the contents of the entry line
-#
-proc sqlitecon::SetLine {w line} {
- upvar #0 $w v
- scan [$w index insert] %d.%d row col
- set start $row.$v(plength)
- $w delete $start end
- $w insert end $line
- $w mark set insert end
- $w yview insert
-}
-
-# Called when the mouse button is pressed at position $x,$y on
-# the console widget.
-#
-proc sqlitecon::Button1 {w x y} {
- global tkPriv
- upvar #0 $w v
- set v(mouseMoved) 0
- set v(pressX) $x
- set p [sqlitecon::nearestBoundry $w $x $y]
- scan [$w index insert] %d.%d ix iy
- scan $p %d.%d px py
- if {$px==$ix} {
- $w mark set insert $p
- }
- $w mark set anchor $p
- focus $w
-}
-
-# Find the boundry between characters that is nearest
-# to $x,$y
-#
-proc sqlitecon::nearestBoundry {w x y} {
- set p [$w index @$x,$y]
- set bb [$w bbox $p]
- if {![string compare $bb ""]} {return $p}
- if {($x-[lindex $bb 0])<([lindex $bb 2]/2)} {return $p}
- $w index "$p + 1 char"
-}
-
-# This routine extends the selection to the point specified by $x,$y
-#
-proc sqlitecon::SelectTo {w x y} {
- upvar #0 $w v
- set cur [sqlitecon::nearestBoundry $w $x $y]
- if {[catch {$w index anchor}]} {
- $w mark set anchor $cur
- }
- set anchor [$w index anchor]
- if {[$w compare $cur != $anchor] || (abs($v(pressX) - $x) >= 3)} {
- if {$v(mouseMoved)==0} {
- $w tag remove sel 0.0 end
- }
- set v(mouseMoved) 1
- }
- if {[$w compare $cur < anchor]} {
- set first $cur
- set last anchor
- } else {
- set first anchor
- set last $cur
- }
- if {$v(mouseMoved)} {
- $w tag remove sel 0.0 $first
- $w tag add sel $first $last
- $w tag remove sel $last end
- update idletasks
- }
-}
-
-# Called whenever the mouse moves while button-1 is held down.
-#
-proc sqlitecon::B1Motion {w x y} {
- upvar #0 $w v
- set v(y) $y
- set v(x) $x
- sqlitecon::SelectTo $w $x $y
-}
-
-# Called whenever the mouse leaves the boundries of the widget
-# while button 1 is held down.
-#
-proc sqlitecon::B1Leave {w x y} {
- upvar #0 $w v
- set v(y) $y
- set v(x) $x
- sqlitecon::motor $w
-}
-
-# This routine is called to automatically scroll the window when
-# the mouse drags offscreen.
-#
-proc sqlitecon::motor w {
- upvar #0 $w v
- if {![winfo exists $w]} return
- if {$v(y)>=[winfo height $w]} {
- $w yview scroll 1 units
- } elseif {$v(y)<0} {
- $w yview scroll -1 units
- } else {
- return
- }
- sqlitecon::SelectTo $w $v(x) $v(y)
- set v(timer) [after 50 sqlitecon::motor $w]
-}
-
-# This routine cancels the scrolling motor if it is active
-#
-proc sqlitecon::cancelMotor w {
- upvar #0 $w v
- catch {after cancel $v(timer)}
- catch {unset v(timer)}
-}
-
-# Do a Copy operation on the stuff currently selected.
-#
-proc sqlitecon::Copy w {
- if {![catch {set text [$w get sel.first sel.last]}]} {
- clipboard clear -displayof $w
- clipboard append -displayof $w $text
- }
-}
-
-# Return 1 if the selection exists and is contained
-# entirely on the input line. Return 2 if the selection
-# exists but is not entirely on the input line. Return 0
-# if the selection does not exist.
-#
-proc sqlitecon::canCut w {
- set r [catch {
- scan [$w index sel.first] %d.%d s1x s1y
- scan [$w index sel.last] %d.%d s2x s2y
- scan [$w index insert] %d.%d ix iy
- }]
- if {$r==1} {return 0}
- if {$s1x==$ix && $s2x==$ix} {return 1}
- return 2
-}
-
-# Do a Cut operation if possible. Cuts are only allowed
-# if the current selection is entirely contained on the
-# current input line.
-#
-proc sqlitecon::Cut w {
- if {[sqlitecon::canCut $w]==1} {
- sqlitecon::Copy $w
- $w delete sel.first sel.last
- }
-}
-
-# Do a paste opeation.
-#
-proc sqlitecon::Paste w {
- if {[sqlitecon::canCut $w]==1} {
- $w delete sel.first sel.last
- }
- if {[catch {selection get -displayof $w -selection CLIPBOARD} topaste]
- && [catch {selection get -displayof $w -selection PRIMARY} topaste]} {
- return
- }
- if {[info exists ::$w]} {
- set prior 0
- foreach line [split $topaste \n] {
- if {$prior} {
- sqlitecon::Enter $w
- update
- }
- set prior 1
- $w insert insert $line
- }
- } else {
- $w insert insert $topaste
- }
-}
-
-# Enable or disable entries in the Edit menu
-#
-proc sqlitecon::EnableEditMenu w {
- upvar #0 $w.t v
- set m $v(editmenu)
- if {$m=="" || ![winfo exists $m]} return
- switch [sqlitecon::canCut $w.t] {
- 0 {
- $m entryconf Copy -state disabled
- $m entryconf Cut -state disabled
- }
- 1 {
- $m entryconf Copy -state normal
- $m entryconf Cut -state normal
- }
- 2 {
- $m entryconf Copy -state normal
- $m entryconf Cut -state disabled
- }
- }
-}
-
-# Prompt the user for the name of a writable file. Then write the
-# entire contents of the console screen to that file.
-#
-proc sqlitecon::SaveFile w {
- set types {
- {{Text Files} {.txt}}
- {{All Files} *}
- }
- set f [tk_getSaveFile -filetypes $types -title "Write Screen To..."]
- if {$f!=""} {
- if {[catch {open $f w} fd]} {
- tk_messageBox -type ok -icon error -message $fd
- } else {
- puts $fd [string trimright [$w get 1.0 end] \n]
- close $fd
- }
- }
-}
-
-# Erase everything from the console above the insertion line.
-#
-proc sqlitecon::Clear w {
- $w delete 1.0 {insert linestart}
-}
-
-# An in-line editor for SQL
-#
-proc sqlitecon::_edit {origtxt {title {}}} {
- for {set i 0} {[winfo exists .ed$i]} {incr i} continue
- set w .ed$i
- toplevel $w
- wm protocol $w WM_DELETE_WINDOW "$w.b.can invoke"
- wm title $w {Inline SQL Editor}
- frame $w.b
- pack $w.b -side bottom -fill x
- button $w.b.can -text Cancel -width 6 -command [list set ::$w 0]
- button $w.b.ok -text OK -width 6 -command [list set ::$w 1]
- button $w.b.cut -text Cut -width 6 -command [list ::sqlitecon::Cut $w.t]
- button $w.b.copy -text Copy -width 6 -command [list ::sqlitecon::Copy $w.t]
- button $w.b.paste -text Paste -width 6 -command [list ::sqlitecon::Paste $w.t]
- set ::$w {}
- pack $w.b.cut $w.b.copy $w.b.paste $w.b.can $w.b.ok\
- -side left -padx 5 -pady 5 -expand 1
- if {$title!=""} {
- label $w.title -text $title
- pack $w.title -side top -padx 5 -pady 5
- }
- text $w.t -bg white -fg black -yscrollcommand [list $w.sb set]
- pack $w.t -side left -fill both -expand 1
- scrollbar $w.sb -orient vertical -command [list $w.t yview]
- pack $w.sb -side left -fill y
- $w.t insert end $origtxt
-
- vwait ::$w
-
- if {[set ::$w]} {
- set txt [string trimright [$w.t get 1.0 end]]
- } else {
- set txt $origtxt
- }
- destroy $w
- return $txt
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/doc/lemon.html b/chromium/third_party/sqlite/sqlite-src-3240000/doc/lemon.html
deleted file mode 100644
index 4f0849e6d6e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/doc/lemon.html
+++ /dev/null
@@ -1,1061 +0,0 @@
-<html>
-<head>
-<title>The Lemon Parser Generator</title>
-</head>
-<body bgcolor='white'>
-<h1 align='center'>The Lemon Parser Generator</h1>
-
-<p>Lemon is an LALR(1) parser generator for C.
-It does the same job as "bison" and "yacc".
-But Lemon is not a bison or yacc clone. Lemon
-uses a different grammar syntax which is designed to
-reduce the number of coding errors. Lemon also uses a
-parsing engine that is faster than yacc and
-bison and which is both reentrant and threadsafe.
-(Update: Since the previous sentence was written, bison
-has also been updated so that it too can generate a
-reentrant and threadsafe parser.)
-Lemon also implements features that can be used
-to eliminate resource leaks, making it suitable for use
-in long-running programs such as graphical user interfaces
-or embedded controllers.</p>
-
-<p>This document is an introduction to the Lemon
-parser generator.</p>
-
-<h2>Security Note</h2>
-
-<p>The language parser code created by Lemon is very robust and
-is well-suited for use in internet-facing applications that need to
-safely process maliciously crafted inputs.
-
-<p>The "lemon.exe" command-line tool itself works great when given a valid
-input grammar file and almost always gives helpful
-error messages for malformed inputs. However, it is possible for
-a malicious user to craft a grammar file that will cause
-lemon.exe to crash.
-We do not see this as a problem, as lemon.exe is not intended to be used
-with hostile inputs.
-To summarize:</p>
-
-<ul>
-<li>Parser code generated by lemon &rarr; Robust and secure
-<li>The "lemon.exe" command line tool itself &rarr; Not so much
-</ul>
-
-<h2>Theory of Operation</h2>
-
-<p>The main goal of Lemon is to translate a context free grammar (CFG)
-for a particular language into C code that implements a parser for
-that language.
-The program has two inputs:
-<ul>
-<li>The grammar specification.
-<li>A parser template file.
-</ul>
-Typically, only the grammar specification is supplied by the programmer.
-Lemon comes with a default parser template which works fine for most
-applications. But the user is free to substitute a different parser
-template if desired.</p>
-
-<p>Depending on command-line options, Lemon will generate up to
-three output files.
-<ul>
-<li>C code to implement the parser.
-<li>A header file defining an integer ID for each terminal symbol.
-<li>An information file that describes the states of the generated parser
- automaton.
-</ul>
-By default, all three of these output files are generated.
-The header file is suppressed if the "-m" command-line option is
-used and the report file is omitted when "-q" is selected.</p>
-
-<p>The grammar specification file uses a ".y" suffix, by convention.
-In the examples used in this document, we'll assume the name of the
-grammar file is "gram.y". A typical use of Lemon would be the
-following command:
-<pre>
- lemon gram.y
-</pre>
-This command will generate three output files named "gram.c",
-"gram.h" and "gram.out".
-The first is C code to implement the parser. The second
-is the header file that defines numerical values for all
-terminal symbols, and the last is the report that explains
-the states used by the parser automaton.</p>
-
-<h3>Command Line Options</h3>
-
-<p>The behavior of Lemon can be modified using command-line options.
-You can obtain a list of the available command-line options together
-with a brief explanation of what each does by typing
-<pre>
- lemon "-?"
-</pre>
-As of this writing, the following command-line options are supported:
-<ul>
-<li><b>-b</b>
-Show only the basis for each parser state in the report file.
-<li><b>-c</b>
-Do not compress the generated action tables. The parser will be a
-little larger and slower, but it will detect syntax errors sooner.
-<li><b>-d</b><i>directory</i>
-Write all output files into <i>directory</i>. Normally, output files
-are written into the directory that contains the input grammar file.
-<li><b>-D<i>name</i></b>
-Define C preprocessor macro <i>name</i>. This macro is usable by
-"<tt><a href='#pifdef'>%ifdef</a></tt>" and
-"<tt><a href='#pifdef'>%ifndef</a></tt>" lines
-in the grammar file.
-<li><b>-g</b>
-Do not generate a parser. Instead write the input grammar to standard
-output with all comments, actions, and other extraneous text removed.
-<li><b>-l</b>
-Omit "#line" directives in the generated parser C code.
-<li><b>-m</b>
-Cause the output C source code to be compatible with the "makeheaders"
-program.
-<li><b>-p</b>
-Display all conflicts that are resolved by
-<a href='#precrules'>precedence rules</a>.
-<li><b>-q</b>
-Suppress generation of the report file.
-<li><b>-r</b>
-Do not sort or renumber the parser states as part of optimization.
-<li><b>-s</b>
-Show parser statistics before existing.
-<li><b>-T<i>file</i></b>
-Use <i>file</i> as the template for the generated C-code parser implementation.
-<li><b>-x</b>
-Print the Lemon version number.
-</ul>
-
-<h3>The Parser Interface</h3>
-
-<p>Lemon doesn't generate a complete, working program. It only generates
-a few subroutines that implement a parser. This section describes
-the interface to those subroutines. It is up to the programmer to
-call these subroutines in an appropriate way in order to produce a
-complete system.</p>
-
-<p>Before a program begins using a Lemon-generated parser, the program
-must first create the parser.
-A new parser is created as follows:
-<pre>
- void *pParser = ParseAlloc( malloc );
-</pre>
-The ParseAlloc() routine allocates and initializes a new parser and
-returns a pointer to it.
-The actual data structure used to represent a parser is opaque &mdash;
-its internal structure is not visible or usable by the calling routine.
-For this reason, the ParseAlloc() routine returns a pointer to void
-rather than a pointer to some particular structure.
-The sole argument to the ParseAlloc() routine is a pointer to the
-subroutine used to allocate memory. Typically this means malloc().</p>
-
-<p>After a program is finished using a parser, it can reclaim all
-memory allocated by that parser by calling
-<pre>
- ParseFree(pParser, free);
-</pre>
-The first argument is the same pointer returned by ParseAlloc(). The
-second argument is a pointer to the function used to release bulk
-memory back to the system.</p>
-
-<p>After a parser has been allocated using ParseAlloc(), the programmer
-must supply the parser with a sequence of tokens (terminal symbols) to
-be parsed. This is accomplished by calling the following function
-once for each token:
-<pre>
- Parse(pParser, hTokenID, sTokenData, pArg);
-</pre>
-The first argument to the Parse() routine is the pointer returned by
-ParseAlloc().
-The second argument is a small positive integer that tells the parser the
-type of the next token in the data stream.
-There is one token type for each terminal symbol in the grammar.
-The gram.h file generated by Lemon contains #define statements that
-map symbolic terminal symbol names into appropriate integer values.
-A value of 0 for the second argument is a special flag to the
-parser to indicate that the end of input has been reached.
-The third argument is the value of the given token. By default,
-the type of the third argument is "void*", but the grammar will
-usually redefine this type to be some kind of structure.
-Typically the second argument will be a broad category of tokens
-such as "identifier" or "number" and the third argument will
-be the name of the identifier or the value of the number.</p>
-
-<p>The Parse() function may have either three or four arguments,
-depending on the grammar. If the grammar specification file requests
-it (via the <tt><a href='#extraarg'>%extra_argument</a></tt> directive),
-the Parse() function will have a fourth parameter that can be
-of any type chosen by the programmer. The parser doesn't do anything
-with this argument except to pass it through to action routines.
-This is a convenient mechanism for passing state information down
-to the action routines without having to use global variables.</p>
-
-<p>A typical use of a Lemon parser might look something like the
-following:
-<pre>
- 1 ParseTree *ParseFile(const char *zFilename){
- 2 Tokenizer *pTokenizer;
- 3 void *pParser;
- 4 Token sToken;
- 5 int hTokenId;
- 6 ParserState sState;
- 7
- 8 pTokenizer = TokenizerCreate(zFilename);
- 9 pParser = ParseAlloc( malloc );
- 10 InitParserState(&amp;sState);
- 11 while( GetNextToken(pTokenizer, &amp;hTokenId, &amp;sToken) ){
- 12 Parse(pParser, hTokenId, sToken, &amp;sState);
- 13 }
- 14 Parse(pParser, 0, sToken, &amp;sState);
- 15 ParseFree(pParser, free );
- 16 TokenizerFree(pTokenizer);
- 17 return sState.treeRoot;
- 18 }
-</pre>
-This example shows a user-written routine that parses a file of
-text and returns a pointer to the parse tree.
-(All error-handling code is omitted from this example to keep it
-simple.)
-We assume the existence of some kind of tokenizer which is created
-using TokenizerCreate() on line 8 and deleted by TokenizerFree()
-on line 16. The GetNextToken() function on line 11 retrieves the
-next token from the input file and puts its type in the
-integer variable hTokenId. The sToken variable is assumed to be
-some kind of structure that contains details about each token,
-such as its complete text, what line it occurs on, etc.</p>
-
-<p>This example also assumes the existence of structure of type
-ParserState that holds state information about a particular parse.
-An instance of such a structure is created on line 6 and initialized
-on line 10. A pointer to this structure is passed into the Parse()
-routine as the optional 4th argument.
-The action routine specified by the grammar for the parser can use
-the ParserState structure to hold whatever information is useful and
-appropriate. In the example, we note that the treeRoot field of
-the ParserState structure is left pointing to the root of the parse
-tree.</p>
-
-<p>The core of this example as it relates to Lemon is as follows:
-<pre>
- ParseFile(){
- pParser = ParseAlloc( malloc );
- while( GetNextToken(pTokenizer,&amp;hTokenId, &amp;sToken) ){
- Parse(pParser, hTokenId, sToken);
- }
- Parse(pParser, 0, sToken);
- ParseFree(pParser, free );
- }
-</pre>
-Basically, what a program has to do to use a Lemon-generated parser
-is first create the parser, then send it lots of tokens obtained by
-tokenizing an input source. When the end of input is reached, the
-Parse() routine should be called one last time with a token type
-of 0. This step is necessary to inform the parser that the end of
-input has been reached. Finally, we reclaim memory used by the
-parser by calling ParseFree().</p>
-
-<p>There is one other interface routine that should be mentioned
-before we move on.
-The ParseTrace() function can be used to generate debugging output
-from the parser. A prototype for this routine is as follows:
-<pre>
- ParseTrace(FILE *stream, char *zPrefix);
-</pre>
-After this routine is called, a short (one-line) message is written
-to the designated output stream every time the parser changes states
-or calls an action routine. Each such message is prefaced using
-the text given by zPrefix. This debugging output can be turned off
-by calling ParseTrace() again with a first argument of NULL (0).</p>
-
-<h3>Differences With YACC and BISON</h3>
-
-<p>Programmers who have previously used the yacc or bison parser
-generator will notice several important differences between yacc and/or
-bison and Lemon.
-<ul>
-<li>In yacc and bison, the parser calls the tokenizer. In Lemon,
- the tokenizer calls the parser.
-<li>Lemon uses no global variables. Yacc and bison use global variables
- to pass information between the tokenizer and parser.
-<li>Lemon allows multiple parsers to be running simultaneously. Yacc
- and bison do not.
-</ul>
-These differences may cause some initial confusion for programmers
-with prior yacc and bison experience.
-But after years of experience using Lemon, I firmly
-believe that the Lemon way of doing things is better.</p>
-
-<p><i>Updated as of 2016-02-16:</i>
-The text above was written in the 1990s.
-We are told that Bison has lately been enhanced to support the
-tokenizer-calls-parser paradigm used by Lemon, and to obviate the
-need for global variables.</p>
-
-<h2>Input File Syntax</h2>
-
-<p>The main purpose of the grammar specification file for Lemon is
-to define the grammar for the parser. But the input file also
-specifies additional information Lemon requires to do its job.
-Most of the work in using Lemon is in writing an appropriate
-grammar file.</p>
-
-<p>The grammar file for Lemon is, for the most part, free format.
-It does not have sections or divisions like yacc or bison. Any
-declaration can occur at any point in the file.
-Lemon ignores whitespace (except where it is needed to separate
-tokens), and it honors the same commenting conventions as C and C++.</p>
-
-<h3>Terminals and Nonterminals</h3>
-
-<p>A terminal symbol (token) is any string of alphanumeric
-and/or underscore characters
-that begins with an uppercase letter.
-A terminal can contain lowercase letters after the first character,
-but the usual convention is to make terminals all uppercase.
-A nonterminal, on the other hand, is any string of alphanumeric
-and underscore characters than begins with a lowercase letter.
-Again, the usual convention is to make nonterminals use all lowercase
-letters.</p>
-
-<p>In Lemon, terminal and nonterminal symbols do not need to
-be declared or identified in a separate section of the grammar file.
-Lemon is able to generate a list of all terminals and nonterminals
-by examining the grammar rules, and it can always distinguish a
-terminal from a nonterminal by checking the case of the first
-character of the name.</p>
-
-<p>Yacc and bison allow terminal symbols to have either alphanumeric
-names or to be individual characters included in single quotes, like
-this: ')' or '$'. Lemon does not allow this alternative form for
-terminal symbols. With Lemon, all symbols, terminals and nonterminals,
-must have alphanumeric names.</p>
-
-<h3>Grammar Rules</h3>
-
-<p>The main component of a Lemon grammar file is a sequence of grammar
-rules.
-Each grammar rule consists of a nonterminal symbol followed by
-the special symbol "::=" and then a list of terminals and/or nonterminals.
-The rule is terminated by a period.
-The list of terminals and nonterminals on the right-hand side of the
-rule can be empty.
-Rules can occur in any order, except that the left-hand side of the
-first rule is assumed to be the start symbol for the grammar (unless
-specified otherwise using the <tt><a href='#start_symbol'>%start_symbol</a></tt>
-directive described below.)
-A typical sequence of grammar rules might look something like this:
-<pre>
- expr ::= expr PLUS expr.
- expr ::= expr TIMES expr.
- expr ::= LPAREN expr RPAREN.
- expr ::= VALUE.
-</pre>
-</p>
-
-<p>There is one non-terminal in this example, "expr", and five
-terminal symbols or tokens: "PLUS", "TIMES", "LPAREN",
-"RPAREN" and "VALUE".</p>
-
-<p>Like yacc and bison, Lemon allows the grammar to specify a block
-of C code that will be executed whenever a grammar rule is reduced
-by the parser.
-In Lemon, this action is specified by putting the C code (contained
-within curly braces <tt>{...}</tt>) immediately after the
-period that closes the rule.
-For example:
-<pre>
- expr ::= expr PLUS expr. { printf("Doing an addition...\n"); }
-</pre>
-</p>
-
-<p>In order to be useful, grammar actions must normally be linked to
-their associated grammar rules.
-In yacc and bison, this is accomplished by embedding a "$$" in the
-action to stand for the value of the left-hand side of the rule and
-symbols "$1", "$2", and so forth to stand for the value of
-the terminal or nonterminal at position 1, 2 and so forth on the
-right-hand side of the rule.
-This idea is very powerful, but it is also very error-prone. The
-single most common source of errors in a yacc or bison grammar is
-to miscount the number of symbols on the right-hand side of a grammar
-rule and say "$7" when you really mean "$8".</p>
-
-<p>Lemon avoids the need to count grammar symbols by assigning symbolic
-names to each symbol in a grammar rule and then using those symbolic
-names in the action.
-In yacc or bison, one would write this:
-<pre>
- expr -&gt; expr PLUS expr { $$ = $1 + $3; };
-</pre>
-But in Lemon, the same rule becomes the following:
-<pre>
- expr(A) ::= expr(B) PLUS expr(C). { A = B+C; }
-</pre>
-In the Lemon rule, any symbol in parentheses after a grammar rule
-symbol becomes a place holder for that symbol in the grammar rule.
-This place holder can then be used in the associated C action to
-stand for the value of that symbol.<p>
-
-<p>The Lemon notation for linking a grammar rule with its reduce
-action is superior to yacc/bison on several counts.
-First, as mentioned above, the Lemon method avoids the need to
-count grammar symbols.
-Secondly, if a terminal or nonterminal in a Lemon grammar rule
-includes a linking symbol in parentheses but that linking symbol
-is not actually used in the reduce action, then an error message
-is generated.
-For example, the rule
-<pre>
- expr(A) ::= expr(B) PLUS expr(C). { A = B; }
-</pre>
-will generate an error because the linking symbol "C" is used
-in the grammar rule but not in the reduce action.</p>
-
-<p>The Lemon notation for linking grammar rules to reduce actions
-also facilitates the use of destructors for reclaiming memory
-allocated by the values of terminals and nonterminals on the
-right-hand side of a rule.</p>
-
-<a name='precrules'></a>
-<h3>Precedence Rules</h3>
-
-<p>Lemon resolves parsing ambiguities in exactly the same way as
-yacc and bison. A shift-reduce conflict is resolved in favor
-of the shift, and a reduce-reduce conflict is resolved by reducing
-whichever rule comes first in the grammar file.</p>
-
-<p>Just like in
-yacc and bison, Lemon allows a measure of control
-over the resolution of parsing conflicts using precedence rules.
-A precedence value can be assigned to any terminal symbol
-using the
-<tt><a href='#pleft'>%left</a></tt>,
-<tt><a href='#pright'>%right</a></tt> or
-<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives. Terminal symbols
-mentioned in earlier directives have a lower precedence than
-terminal symbols mentioned in later directives. For example:</p>
-
-<p><pre>
- %left AND.
- %left OR.
- %nonassoc EQ NE GT GE LT LE.
- %left PLUS MINUS.
- %left TIMES DIVIDE MOD.
- %right EXP NOT.
-</pre></p>
-
-<p>In the preceding sequence of directives, the AND operator is
-defined to have the lowest precedence. The OR operator is one
-precedence level higher. And so forth. Hence, the grammar would
-attempt to group the ambiguous expression
-<pre>
- a AND b OR c
-</pre>
-like this
-<pre>
- a AND (b OR c).
-</pre>
-The associativity (left, right or nonassoc) is used to determine
-the grouping when the precedence is the same. AND is left-associative
-in our example, so
-<pre>
- a AND b AND c
-</pre>
-is parsed like this
-<pre>
- (a AND b) AND c.
-</pre>
-The EXP operator is right-associative, though, so
-<pre>
- a EXP b EXP c
-</pre>
-is parsed like this
-<pre>
- a EXP (b EXP c).
-</pre>
-The nonassoc precedence is used for non-associative operators.
-So
-<pre>
- a EQ b EQ c
-</pre>
-is an error.</p>
-
-<p>The precedence of non-terminals is transferred to rules as follows:
-The precedence of a grammar rule is equal to the precedence of the
-left-most terminal symbol in the rule for which a precedence is
-defined. This is normally what you want, but in those cases where
-you want to precedence of a grammar rule to be something different,
-you can specify an alternative precedence symbol by putting the
-symbol in square braces after the period at the end of the rule and
-before any C-code. For example:</p>
-
-<p><pre>
- expr = MINUS expr. [NOT]
-</pre></p>
-
-<p>This rule has a precedence equal to that of the NOT symbol, not the
-MINUS symbol as would have been the case by default.</p>
-
-<p>With the knowledge of how precedence is assigned to terminal
-symbols and individual
-grammar rules, we can now explain precisely how parsing conflicts
-are resolved in Lemon. Shift-reduce conflicts are resolved
-as follows:
-<ul>
-<li> If either the token to be shifted or the rule to be reduced
- lacks precedence information, then resolve in favor of the
- shift, but report a parsing conflict.
-<li> If the precedence of the token to be shifted is greater than
- the precedence of the rule to reduce, then resolve in favor
- of the shift. No parsing conflict is reported.
-<li> If the precedence of the token to be shifted is less than the
- precedence of the rule to reduce, then resolve in favor of the
- reduce action. No parsing conflict is reported.
-<li> If the precedences are the same and the shift token is
- right-associative, then resolve in favor of the shift.
- No parsing conflict is reported.
-<li> If the precedences are the same and the shift token is
- left-associative, then resolve in favor of the reduce.
- No parsing conflict is reported.
-<li> Otherwise, resolve the conflict by doing the shift, and
- report a parsing conflict.
-</ul>
-Reduce-reduce conflicts are resolved this way:
-<ul>
-<li> If either reduce rule
- lacks precedence information, then resolve in favor of the
- rule that appears first in the grammar, and report a parsing
- conflict.
-<li> If both rules have precedence and the precedence is different,
- then resolve the dispute in favor of the rule with the highest
- precedence, and do not report a conflict.
-<li> Otherwise, resolve the conflict by reducing by the rule that
- appears first in the grammar, and report a parsing conflict.
-</ul>
-
-<h3>Special Directives</h3>
-
-<p>The input grammar to Lemon consists of grammar rules and special
-directives. We've described all the grammar rules, so now we'll
-talk about the special directives.</p>
-
-<p>Directives in Lemon can occur in any order. You can put them before
-the grammar rules, or after the grammar rules, or in the midst of the
-grammar rules. It doesn't matter. The relative order of
-directives used to assign precedence to terminals is important, but
-other than that, the order of directives in Lemon is arbitrary.</p>
-
-<p>Lemon supports the following special directives:
-<ul>
-<li><tt><a href='#pcode'>%code</a></tt>
-<li><tt><a href='#default_destructor'>%default_destructor</a></tt>
-<li><tt><a href='#default_type'>%default_type</a></tt>
-<li><tt><a href='#destructor'>%destructor</a></tt>
-<li><tt><a href='#pifdef'>%endif</a></tt>
-<li><tt><a href='#extraarg'>%extra_argument</a></tt>
-<li><tt><a href='#pfallback'>%fallback</a></tt>
-<li><tt><a href='#pifdef'>%ifdef</a></tt>
-<li><tt><a href='#pifdef'>%ifndef</a></tt>
-<li><tt><a href='#pinclude'>%include</a></tt>
-<li><tt><a href='#pleft'>%left</a></tt>
-<li><tt><a href='#pname'>%name</a></tt>
-<li><tt><a href='#pnonassoc'>%nonassoc</a></tt>
-<li><tt><a href='#parse_accept'>%parse_accept</a></tt>
-<li><tt><a href='#parse_failure'>%parse_failure</a></tt>
-<li><tt><a href='#pright'>%right</a></tt>
-<li><tt><a href='#stack_overflow'>%stack_overflow</a></tt>
-<li><tt><a href='#stack_size'>%stack_size</a></tt>
-<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
-<li><tt><a href='#syntax_error'>%syntax_error</a></tt>
-<li><tt><a href='#token_class'>%token_class</a></tt>
-<li><tt><a href='#token_destructor'>%token_destructor</a></tt>
-<li><tt><a href='#token_prefix'>%token_prefix</a></tt>
-<li><tt><a href='#token_type'>%token_type</a></tt>
-<li><tt><a href='#ptype'>%type</a></tt>
-<li><tt><a href='#pwildcard'>%wildcard</a></tt>
-</ul>
-Each of these directives will be described separately in the
-following sections:</p>
-
-<a name='pcode'></a>
-<h4>The <tt>%code</tt> directive</h4>
-
-<p>The <tt>%code</tt> directive is used to specify additional C code that
-is added to the end of the main output file. This is similar to
-the <tt><a href='#pinclude'>%include</a></tt> directive except that
-<tt>%include</tt> is inserted at the beginning of the main output file.</p>
-
-<p><tt>%code</tt> is typically used to include some action routines or perhaps
-a tokenizer or even the "main()" function
-as part of the output file.</p>
-
-<a name='default_destructor'></a>
-<h4>The <tt>%default_destructor</tt> directive</h4>
-
-<p>The <tt>%default_destructor</tt> directive specifies a destructor to
-use for non-terminals that do not have their own destructor
-specified by a separate <tt>%destructor</tt> directive. See the documentation
-on the <tt><a name='#destructor'>%destructor</a></tt> directive below for
-additional information.</p>
-
-<p>In some grammars, many different non-terminal symbols have the
-same data type and hence the same destructor. This directive is
-a convenient way to specify the same destructor for all those
-non-terminals using a single statement.</p>
-
-<a name='default_type'></a>
-<h4>The <tt>%default_type</tt> directive</h4>
-
-<p>The <tt>%default_type</tt> directive specifies the data type of non-terminal
-symbols that do not have their own data type defined using a separate
-<tt><a href='#ptype'>%type</a></tt> directive.</p>
-
-<a name='destructor'></a>
-<h4>The <tt>%destructor</tt> directive</h4>
-
-<p>The <tt>%destructor</tt> directive is used to specify a destructor for
-a non-terminal symbol.
-(See also the <tt><a href='#token_destructor'>%token_destructor</a></tt>
-directive which is used to specify a destructor for terminal symbols.)</p>
-
-<p>A non-terminal's destructor is called to dispose of the
-non-terminal's value whenever the non-terminal is popped from
-the stack. This includes all of the following circumstances:
-<ul>
-<li> When a rule reduces and the value of a non-terminal on
- the right-hand side is not linked to C code.
-<li> When the stack is popped during error processing.
-<li> When the ParseFree() function runs.
-</ul>
-The destructor can do whatever it wants with the value of
-the non-terminal, but its design is to deallocate memory
-or other resources held by that non-terminal.</p>
-
-<p>Consider an example:
-<pre>
- %type nt {void*}
- %destructor nt { free($$); }
- nt(A) ::= ID NUM. { A = malloc( 100 ); }
-</pre>
-This example is a bit contrived, but it serves to illustrate how
-destructors work. The example shows a non-terminal named
-"nt" that holds values of type "void*". When the rule for
-an "nt" reduces, it sets the value of the non-terminal to
-space obtained from malloc(). Later, when the nt non-terminal
-is popped from the stack, the destructor will fire and call
-free() on this malloced space, thus avoiding a memory leak.
-(Note that the symbol "$$" in the destructor code is replaced
-by the value of the non-terminal.)</p>
-
-<p>It is important to note that the value of a non-terminal is passed
-to the destructor whenever the non-terminal is removed from the
-stack, unless the non-terminal is used in a C-code action. If
-the non-terminal is used by C-code, then it is assumed that the
-C-code will take care of destroying it.
-More commonly, the value is used to build some
-larger structure, and we don't want to destroy it, which is why
-the destructor is not called in this circumstance.</p>
-
-<p>Destructors help avoid memory leaks by automatically freeing
-allocated objects when they go out of scope.
-To do the same using yacc or bison is much more difficult.</p>
-
-<a name='extraarg'></a>
-<h4>The <tt>%extra_argument</tt> directive</h4>
-
-The <tt>%extra_argument</tt> directive instructs Lemon to add a 4th parameter
-to the parameter list of the Parse() function it generates. Lemon
-doesn't do anything itself with this extra argument, but it does
-make the argument available to C-code action routines, destructors,
-and so forth. For example, if the grammar file contains:</p>
-
-<p><pre>
- %extra_argument { MyStruct *pAbc }
-</pre></p>
-
-<p>Then the Parse() function generated will have an 4th parameter
-of type "MyStruct*" and all action routines will have access to
-a variable named "pAbc" that is the value of the 4th parameter
-in the most recent call to Parse().</p>
-
-<p>The <tt>%extra_context</tt> directive works the same except that it
-is passed in on the ParseAlloc() or ParseInit() routines instead of
-on Parse().
-
-<a name='extractx'></a>
-<h4>The <tt>%extra_context</tt> directive</h4>
-
-The <tt>%extra_context</tt> directive instructs Lemon to add a 2th parameter
-to the parameter list of the ParseAlloc() and ParseInif() functions. Lemon
-doesn't do anything itself with these extra argument, but it does
-store the value make it available to C-code action routines, destructors,
-and so forth. For example, if the grammar file contains:</p>
-
-<p><pre>
- %extra_context { MyStruct *pAbc }
-</pre></p>
-
-<p>Then the ParseAlloc() and ParseInit() functions will have an 2th parameter
-of type "MyStruct*" and all action routines will have access to
-a variable named "pAbc" that is the value of that 2th parameter.</p>
-
-<p>The <tt>%extra_argument</tt> directive works the same except that it
-is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().
-
-<a name='pfallback'></a>
-<h4>The <tt>%fallback</tt> directive</h4>
-
-<p>The <tt>%fallback</tt> directive specifies an alternative meaning for one
-or more tokens. The alternative meaning is tried if the original token
-would have generated a syntax error.</p>
-
-<p>The <tt>%fallback</tt> directive was added to support robust parsing of SQL
-syntax in <a href='https://www.sqlite.org/'>SQLite</a>.
-The SQL language contains a large assortment of keywords, each of which
-appears as a different token to the language parser. SQL contains so
-many keywords that it can be difficult for programmers to keep up with
-them all. Programmers will, therefore, sometimes mistakenly use an
-obscure language keyword for an identifier. The <tt>%fallback</tt> directive
-provides a mechanism to tell the parser: "If you are unable to parse
-this keyword, try treating it as an identifier instead."</p>
-
-<p>The syntax of <tt>%fallback</tt> is as follows:
-
-<blockquote>
-<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
-</blockquote></p>
-
-<p>In words, the <tt>%fallback</tt> directive is followed by a list of token
-names terminated by a period.
-The first token name is the fallback token &mdash; the
-token to which all the other tokens fall back to. The second and subsequent
-arguments are tokens which fall back to the token identified by the first
-argument.</p>
-
-<a name='pifdef'></a>
-<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives</h4>
-
-<p>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives
-are similar to #ifdef, #ifndef, and #endif in the C-preprocessor,
-just not as general.
-Each of these directives must begin at the left margin. No whitespace
-is allowed between the "%" and the directive name.</p>
-
-<p>Grammar text in between "<tt>%ifdef MACRO</tt>" and the next nested
-"<tt>%endif</tt>" is
-ignored unless the "-DMACRO" command-line option is used. Grammar text
-betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
-included except when the "-DMACRO" command-line option is used.</p>
-
-<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> must
-be a single preprocessor symbol name, not a general expression.
-There is no "<tt>%else</tt>" directive.</p>
-
-
-<a name='pinclude'></a>
-<h4>The <tt>%include</tt> directive</h4>
-
-<p>The <tt>%include</tt> directive specifies C code that is included at the
-top of the generated parser. You can include any text you want &mdash;
-the Lemon parser generator copies it blindly. If you have multiple
-<tt>%include</tt> directives in your grammar file, their values are concatenated
-so that all <tt>%include</tt> code ultimately appears near the top of the
-generated parser, in the same order as it appeared in the grammar.</p>
-
-<p>The <tt>%include</tt> directive is very handy for getting some extra #include
-preprocessor statements at the beginning of the generated parser.
-For example:</p>
-
-<p><pre>
- %include {#include &lt;unistd.h&gt;}
-</pre></p>
-
-<p>This might be needed, for example, if some of the C actions in the
-grammar call functions that are prototyped in unistd.h.</p>
-
-<a name='pleft'></a>
-<h4>The <tt>%left</tt> directive</h4>
-
-The <tt>%left</tt> directive is used (along with the
-<tt><a href='#pright'>%right</a></tt> and
-<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives) to declare
-precedences of terminal symbols.
-Every terminal symbol whose name appears after
-a <tt>%left</tt> directive but before the next period (".") is
-given the same left-associative precedence value. Subsequent
-<tt>%left</tt> directives have higher precedence. For example:</p>
-
-<p><pre>
- %left AND.
- %left OR.
- %nonassoc EQ NE GT GE LT LE.
- %left PLUS MINUS.
- %left TIMES DIVIDE MOD.
- %right EXP NOT.
-</pre></p>
-
-<p>Note the period that terminates each <tt>%left</tt>,
-<tt>%right</tt> or <tt>%nonassoc</tt>
-directive.</p>
-
-<p>LALR(1) grammars can get into a situation where they require
-a large amount of stack space if you make heavy use or right-associative
-operators. For this reason, it is recommended that you use <tt>%left</tt>
-rather than <tt>%right</tt> whenever possible.</p>
-
-<a name='pname'></a>
-<h4>The <tt>%name</tt> directive</h4>
-
-<p>By default, the functions generated by Lemon all begin with the
-five-character string "Parse". You can change this string to something
-different using the <tt>%name</tt> directive. For instance:</p>
-
-<p><pre>
- %name Abcde
-</pre></p>
-
-<p>Putting this directive in the grammar file will cause Lemon to generate
-functions named
-<ul>
-<li> AbcdeAlloc(),
-<li> AbcdeFree(),
-<li> AbcdeTrace(), and
-<li> Abcde().
-</ul>
-The <tt>%name</tt> directive allows you to generate two or more different
-parsers and link them all into the same executable.</p>
-
-<a name='pnonassoc'></a>
-<h4>The <tt>%nonassoc</tt> directive</h4>
-
-<p>This directive is used to assign non-associative precedence to
-one or more terminal symbols. See the section on
-<a href='#precrules'>precedence rules</a>
-or on the <tt><a href='#pleft'>%left</a></tt> directive
-for additional information.</p>
-
-<a name='parse_accept'></a>
-<h4>The <tt>%parse_accept</tt> directive</h4>
-
-<p>The <tt>%parse_accept</tt> directive specifies a block of C code that is
-executed whenever the parser accepts its input string. To "accept"
-an input string means that the parser was able to process all tokens
-without error.</p>
-
-<p>For example:</p>
-
-<p><pre>
- %parse_accept {
- printf("parsing complete!\n");
- }
-</pre></p>
-
-<a name='parse_failure'></a>
-<h4>The <tt>%parse_failure</tt> directive</h4>
-
-<p>The <tt>%parse_failure</tt> directive specifies a block of C code that
-is executed whenever the parser fails complete. This code is not
-executed until the parser has tried and failed to resolve an input
-error using is usual error recovery strategy. The routine is
-only invoked when parsing is unable to continue.</p>
-
-<p><pre>
- %parse_failure {
- fprintf(stderr,"Giving up. Parser is hopelessly lost...\n");
- }
-</pre></p>
-
-<a name='pright'></a>
-<h4>The <tt>%right</tt> directive</h4>
-
-<p>This directive is used to assign right-associative precedence to
-one or more terminal symbols. See the section on
-<a href='#precrules'>precedence rules</a>
-or on the <a href='#pleft'>%left</a> directive for additional information.</p>
-
-<a name='stack_overflow'></a>
-<h4>The <tt>%stack_overflow</tt> directive</h4>
-
-<p>The <tt>%stack_overflow</tt> directive specifies a block of C code that
-is executed if the parser's internal stack ever overflows. Typically
-this just prints an error message. After a stack overflow, the parser
-will be unable to continue and must be reset.</p>
-
-<p><pre>
- %stack_overflow {
- fprintf(stderr,"Giving up. Parser stack overflow\n");
- }
-</pre></p>
-
-<p>You can help prevent parser stack overflows by avoiding the use
-of right recursion and right-precedence operators in your grammar.
-Use left recursion and and left-precedence operators instead to
-encourage rules to reduce sooner and keep the stack size down.
-For example, do rules like this:
-<pre>
- list ::= list element. // left-recursion. Good!
- list ::= .
-</pre>
-Not like this:
-<pre>
- list ::= element list. // right-recursion. Bad!
- list ::= .
-</pre></p>
-
-<a name='stack_size'></a>
-<h4>The <tt>%stack_size</tt> directive</h4>
-
-<p>If stack overflow is a problem and you can't resolve the trouble
-by using left-recursion, then you might want to increase the size
-of the parser's stack using this directive. Put an positive integer
-after the <tt>%stack_size</tt> directive and Lemon will generate a parse
-with a stack of the requested size. The default value is 100.</p>
-
-<p><pre>
- %stack_size 2000
-</pre></p>
-
-<a name='start_symbol'></a>
-<h4>The <tt>%start_symbol</tt> directive</h4>
-
-<p>By default, the start symbol for the grammar that Lemon generates
-is the first non-terminal that appears in the grammar file. But you
-can choose a different start symbol using the
-<tt>%start_symbol</tt> directive.</p>
-
-<p><pre>
- %start_symbol prog
-</pre></p>
-
-<a name='syntax_error'></a>
-<h4>The <tt>%syntax_error</tt> directive</h4>
-
-<p>See <a href='#error_processing'>Error Processing</a>.</p>
-
-<a name='token_class'></a>
-<h4>The <tt>%token_class</tt> directive</h4>
-
-<p>Undocumented. Appears to be related to the MULTITERMINAL concept.
-<a href='http://sqlite.org/src/fdiff?v1=796930d5fc2036c7&v2=624b24c5dc048e09&sbs=0'>Implementation</a>.</p>
-
-<a name='token_destructor'></a>
-<h4>The <tt>%token_destructor</tt> directive</h4>
-
-<p>The <tt>%destructor</tt> directive assigns a destructor to a non-terminal
-symbol. (See the description of the
-<tt><a href='%destructor'>%destructor</a></tt> directive above.)
-The <tt>%token_destructor</tt> directive does the same thing
-for all terminal symbols.</p>
-
-<p>Unlike non-terminal symbols which may each have a different data type
-for their values, terminals all use the same data type (defined by
-the <tt><a href='#token_type'>%token_type</a></tt> directive)
-and so they use a common destructor.
-Other than that, the token destructor works just like the non-terminal
-destructors.</p>
-
-<a name='token_prefix'></a>
-<h4>The <tt>%token_prefix</tt> directive</h4>
-
-<p>Lemon generates #defines that assign small integer constants
-to each terminal symbol in the grammar. If desired, Lemon will
-add a prefix specified by this directive
-to each of the #defines it generates.</p>
-
-<p>So if the default output of Lemon looked like this:
-<pre>
- #define AND 1
- #define MINUS 2
- #define OR 3
- #define PLUS 4
-</pre>
-You can insert a statement into the grammar like this:
-<pre>
- %token_prefix TOKEN_
-</pre>
-to cause Lemon to produce these symbols instead:
-<pre>
- #define TOKEN_AND 1
- #define TOKEN_MINUS 2
- #define TOKEN_OR 3
- #define TOKEN_PLUS 4
-</pre></p>
-
-<a name='token_type'></a><a name='ptype'></a>
-<h4>The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
-
-<p>These directives are used to specify the data types for values
-on the parser's stack associated with terminal and non-terminal
-symbols. The values of all terminal symbols must be of the same
-type. This turns out to be the same data type as the 3rd parameter
-to the Parse() function generated by Lemon. Typically, you will
-make the value of a terminal symbol by a pointer to some kind of
-token structure. Like this:</p>
-
-<p><pre>
- %token_type {Token*}
-</pre></p>
-
-<p>If the data type of terminals is not specified, the default value
-is "void*".</p>
-
-<p>Non-terminal symbols can each have their own data types. Typically
-the data type of a non-terminal is a pointer to the root of a parse tree
-structure that contains all information about that non-terminal.
-For example:</p>
-
-<p><pre>
- %type expr {Expr*}
-</pre></p>
-
-<p>Each entry on the parser's stack is actually a union containing
-instances of all data types for every non-terminal and terminal symbol.
-Lemon will automatically use the correct element of this union depending
-on what the corresponding non-terminal or terminal symbol is. But
-the grammar designer should keep in mind that the size of the union
-will be the size of its largest element. So if you have a single
-non-terminal whose data type requires 1K of storage, then your 100
-entry parser stack will require 100K of heap space. If you are willing
-and able to pay that price, fine. You just need to know.</p>
-
-<a name='pwildcard'></a>
-<h4>The <tt>%wildcard</tt> directive</h4>
-
-<p>The <tt>%wildcard</tt> directive is followed by a single token name and a
-period. This directive specifies that the identified token should
-match any input token.</p>
-
-<p>When the generated parser has the choice of matching an input against
-the wildcard token and some other token, the other token is always used.
-The wildcard token is only matched if there are no alternatives.</p>
-
-<a name='error_processing'></a>
-<h3>Error Processing</h3>
-
-<p>After extensive experimentation over several years, it has been
-discovered that the error recovery strategy used by yacc is about
-as good as it gets. And so that is what Lemon uses.</p>
-
-<p>When a Lemon-generated parser encounters a syntax error, it
-first invokes the code specified by the <tt>%syntax_error</tt> directive, if
-any. It then enters its error recovery strategy. The error recovery
-strategy is to begin popping the parsers stack until it enters a
-state where it is permitted to shift a special non-terminal symbol
-named "error". It then shifts this non-terminal and continues
-parsing. The <tt>%syntax_error</tt> routine will not be called again
-until at least three new tokens have been successfully shifted.</p>
-
-<p>If the parser pops its stack until the stack is empty, and it still
-is unable to shift the error symbol, then the
-<tt><a href='#parse_failure'>%parse_failure</a></tt> routine
-is invoked and the parser resets itself to its start state, ready
-to begin parsing a new file. This is what will happen at the very
-first syntax error, of course, if there are no instances of the
-"error" non-terminal in your grammar.</p>
-
-</body>
-</html>
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/doc/pager-invariants.txt b/chromium/third_party/sqlite/sqlite-src-3240000/doc/pager-invariants.txt
deleted file mode 100644
index 44444dad54b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/doc/pager-invariants.txt
+++ /dev/null
@@ -1,76 +0,0 @@
- *** Throughout this document, a page is deemed to have been synced
- automatically as soon as it is written when PRAGMA synchronous=OFF.
- Otherwise, the page is not synced until the xSync method of the VFS
- is called successfully on the file containing the page.
-
- *** Definition: A page of the database file is said to be "overwriteable" if
- one or more of the following are true about the page:
-
- (a) The original content of the page as it was at the beginning of
- the transaction has been written into the rollback journal and
- synced.
-
- (b) The page was a freelist leaf page at the start of the transaction.
-
- (c) The page number is greater than the largest page that existed in
- the database file at the start of the transaction.
-
- (1) A page of the database file is never overwritten unless one of the
- following are true:
-
- (a) The page and all other pages on the same sector are overwriteable.
-
- (b) The atomic page write optimization is enabled, and the entire
- transaction other than the update of the transaction sequence
- number consists of a single page change.
-
- (2) The content of a page written into the rollback journal exactly matches
- both the content in the database when the rollback journal was written
- and the content in the database at the beginning of the current
- transaction.
-
- (3) Writes to the database file are an integer multiple of the page size
- in length and are aligned to a page boundary.
-
- (4) Reads from the database file are either aligned on a page boundary and
- an integer multiple of the page size in length or are taken from the
- first 100 bytes of the database file.
-
- (5) All writes to the database file are synced prior to the rollback journal
- being deleted, truncated, or zeroed.
-
- (6) If a master journal file is used, then all writes to the database file
- are synced prior to the master journal being deleted.
-
- *** Definition: Two databases (or the same database at two points it time)
- are said to be "logically equivalent" if they give the same answer to
- all queries. Note in particular the content of freelist leaf
- pages can be changed arbitarily without effecting the logical equivalence
- of the database.
-
- (7) At any time, if any subset, including the empty set and the total set,
- of the unsynced changes to a rollback journal are removed and the
- journal is rolled back, the resulting database file will be logical
- equivalent to the database file at the beginning of the transaction.
-
- (8) When a transaction is rolled back, the xTruncate method of the VFS
- is called to restore the database file to the same size it was at
- the beginning of the transaction. (In some VFSes, the xTruncate
- method is a no-op, but that does not change the fact the SQLite will
- invoke it.)
-
- (9) Whenever the database file is modified, at least one bit in the range
- of bytes from 24 through 39 inclusive will be changed prior to releasing
- the EXCLUSIVE lock.
-
-(10) The pattern of bits in bytes 24 through 39 shall not repeat in less
- than one billion transactions.
-
-(11) A database file is well-formed at the beginning and at the conclusion
- of every transaction.
-
-(12) An EXCLUSIVE lock must be held on the database file before making
- any changes to the database file.
-
-(13) A SHARED lock must be held on the database file before reading any
- content out of the database file.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/doc/vfs-shm.txt b/chromium/third_party/sqlite/sqlite-src-3240000/doc/vfs-shm.txt
deleted file mode 100644
index c1f125a1203..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/doc/vfs-shm.txt
+++ /dev/null
@@ -1,130 +0,0 @@
-The 5 states of an historical rollback lock as implemented by the
-xLock, xUnlock, and xCheckReservedLock methods of the sqlite3_io_methods
-objec are:
-
- UNLOCKED
- SHARED
- RESERVED
- PENDING
- EXCLUSIVE
-
-The wal-index file has a similar locking hierarchy implemented using
-the xShmLock method of the sqlite3_vfs object, but with 7
-states. Each connection to a wal-index file must be in one of
-the following 7 states:
-
- UNLOCKED
- READ
- READ_FULL
- WRITE
- PENDING
- CHECKPOINT
- RECOVER
-
-These roughly correspond to the 5 states of a rollback lock except
-that SHARED is split out into 2 states: READ and READ_FULL and
-there is an extra RECOVER state used for wal-index reconstruction.
-
-The meanings of the various wal-index locking states is as follows:
-
- UNLOCKED - The wal-index is not in use.
-
- READ - Some prefix of the wal-index is being read. Additional
- wal-index information can be appended at any time. The
- newly appended content will be ignored by the holder of
- the READ lock.
-
- READ_FULL - The entire wal-index is being read. No new information
- can be added to the wal-index. The holder of a READ_FULL
- lock promises never to read pages from the database file
- that are available anywhere in the wal-index.
-
- WRITE - It is OK to append to the wal-index file and to adjust
- the header to indicate the new "last valid frame".
-
- PENDING - Waiting on all READ locks to clear so that a
- CHECKPOINT lock can be acquired.
-
- CHECKPOINT - It is OK to write any WAL data into the database file
- and zero the last valid frame field of the wal-index
- header. The wal-index file itself may not be changed
- other than to zero the last valid frame field in the
- header.
-
- RECOVER - Held during wal-index recovery. Used to prevent a
- race if multiple clients try to recover a wal-index at
- the same time.
-
-
-A particular lock manager implementation may coalesce one or more of
-the wal-index locking states, though with a reduction in concurrency.
-For example, an implemention might implement only exclusive locking,
-in which case all states would be equivalent to CHECKPOINT, meaning that
-only one reader or one writer or one checkpointer could be active at a
-time. Or, an implementation might combine READ and READ_FULL into
-a single state equivalent to READ, meaning that a writer could
-coexist with a reader, but no reader or writers could coexist with a
-checkpointer.
-
-The lock manager must obey the following rules:
-
-(1) A READ cannot coexist with CHECKPOINT.
-(2) A READ_FULL cannot coexist with WRITE.
-(3) None of WRITE, PENDING, CHECKPOINT, or RECOVER can coexist.
-
-The SQLite core will obey the next set of rules. These rules are
-assertions on the behavior of the SQLite core which might be verified
-during testing using an instrumented lock manager.
-
-(5) No part of the wal-index will be read without holding either some
- kind of SHM lock or an EXCLUSIVE lock on the original database.
- The original database is the file named in the 2nd parameter to
- the xShmOpen method.
-
-(6) A holder of a READ_FULL will never read any page of the database
- file that is contained anywhere in the wal-index.
-
-(7) No part of the wal-index other than the header will be written nor
- will the size of the wal-index grow without holding a WRITE or
- an EXCLUSIVE on the original database file.
-
-(8) The wal-index header will not be written without holding one of
- WRITE, CHECKPOINT, or RECOVER on the wal-index or an EXCLUSIVE on
- the original database files.
-
-(9) A CHECKPOINT or RECOVER must be held on the wal-index, or an
- EXCLUSIVE on the original database file, in order to reset the
- last valid frame counter in the header of the wal-index back to zero.
-
-(10) A WRITE can only increase the last valid frame pointer in the header.
-
-The SQLite core will only ever send requests for UNLOCK, READ, WRITE,
-CHECKPOINT, or RECOVER to the lock manager. The SQLite core will never
-request a READ_FULL or PENDING lock though the lock manager may deliver
-those locking states in response to READ and CHECKPOINT requests,
-respectively, if and only if the requested READ or CHECKPOINT cannot
-be delivered.
-
-The following are the allowed lock transitions:
-
- Original-State Request New-State
- -------------- ---------- ----------
-(11a) UNLOCK READ READ
-(11b) UNLOCK READ READ_FULL
-(11c) UNLOCK CHECKPOINT PENDING
-(11d) UNLOCK CHECKPOINT CHECKPOINT
-(11e) READ UNLOCK UNLOCK
-(11f) READ WRITE WRITE
-(11g) READ RECOVER RECOVER
-(11h) READ_FULL UNLOCK UNLOCK
-(11i) READ_FULL WRITE WRITE
-(11j) READ_FULL RECOVER RECOVER
-(11k) WRITE READ READ
-(11l) PENDING UNLOCK UNLOCK
-(11m) PENDING CHECKPOINT CHECKPOINT
-(11n) CHECKPOINT UNLOCK UNLOCK
-(11o) RECOVER READ READ
-
-These 15 transitions are all that needs to be supported. The lock
-manager implementation can assert that fact. The other 27 possible
-transitions among the 7 locking states will never occur.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/README.md b/chromium/third_party/sqlite/sqlite-src-3240000/ext/README.md
deleted file mode 100644
index 933a33d053b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-## Loadable Extensions
-
-Various [loadable extensions](https://www.sqlite.org/loadext.html) for
-SQLite are found in subfolders.
-
-Most subfolders are dedicated to a single loadable extension (for
-example FTS5, or RTREE). But the misc/ subfolder contains a collection
-of smaller single-file extensions.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/README.txt b/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/README.txt
deleted file mode 100644
index f62fa2fc17e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/README.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-NOTE (2012-11-29):
-
-The functionality implemented by this extension has been superseded
-by WAL-mode. This module is no longer supported or maintained. The
-code is retained for historical reference only.
-
-------------------------------------------------------------------------------
-
-Normally, when SQLite writes to a database file, it waits until the write
-operation is finished before returning control to the calling application.
-Since writing to the file-system is usually very slow compared with CPU
-bound operations, this can be a performance bottleneck. This directory
-contains an extension that causes SQLite to perform all write requests
-using a separate thread running in the background. Although this does not
-reduce the overall system resources (CPU, disk bandwidth etc.) at all, it
-allows SQLite to return control to the caller quickly even when writing to
-the database, eliminating the bottleneck.
-
- 1. Functionality
-
- 1.1 How it Works
- 1.2 Limitations
- 1.3 Locking and Concurrency
-
- 2. Compilation and Usage
-
- 3. Porting
-
-
-
-1. FUNCTIONALITY
-
- With asynchronous I/O, write requests are handled by a separate thread
- running in the background. This means that the thread that initiates
- a database write does not have to wait for (sometimes slow) disk I/O
- to occur. The write seems to happen very quickly, though in reality
- it is happening at its usual slow pace in the background.
-
- Asynchronous I/O appears to give better responsiveness, but at a price.
- You lose the Durable property. With the default I/O backend of SQLite,
- once a write completes, you know that the information you wrote is
- safely on disk. With the asynchronous I/O, this is not the case. If
- your program crashes or if a power loss occurs after the database
- write but before the asynchronous write thread has completed, then the
- database change might never make it to disk and the next user of the
- database might not see your change.
-
- You lose Durability with asynchronous I/O, but you still retain the
- other parts of ACID: Atomic, Consistent, and Isolated. Many
- appliations get along fine without the Durablity.
-
- 1.1 How it Works
-
- Asynchronous I/O works by creating a special SQLite "vfs" structure
- and registering it with sqlite3_vfs_register(). When files opened via
- this vfs are written to (using the vfs xWrite() method), the data is not
- written directly to disk, but is placed in the "write-queue" to be
- handled by the background thread.
-
- When files opened with the asynchronous vfs are read from
- (using the vfs xRead() method), the data is read from the file on
- disk and the write-queue, so that from the point of view of
- the vfs reader the xWrite() appears to have already completed.
-
- The special vfs is registered (and unregistered) by calls to the
- API functions sqlite3async_initialize() and sqlite3async_shutdown().
- See section "Compilation and Usage" below for details.
-
- 1.2 Limitations
-
- In order to gain experience with the main ideas surrounding asynchronous
- IO, this implementation is deliberately kept simple. Additional
- capabilities may be added in the future.
-
- For example, as currently implemented, if writes are happening at a
- steady stream that exceeds the I/O capability of the background writer
- thread, the queue of pending write operations will grow without bound.
- If this goes on for long enough, the host system could run out of memory.
- A more sophisticated module could to keep track of the quantity of
- pending writes and stop accepting new write requests when the queue of
- pending writes grows too large.
-
- 1.3 Locking and Concurrency
-
- Multiple connections from within a single process that use this
- implementation of asynchronous IO may access a single database
- file concurrently. From the point of view of the user, if all
- connections are from within a single process, there is no difference
- between the concurrency offered by "normal" SQLite and SQLite
- using the asynchronous backend.
-
- If file-locking is enabled (it is enabled by default), then connections
- from multiple processes may also read and write the database file.
- However concurrency is reduced as follows:
-
- * When a connection using asynchronous IO begins a database
- transaction, the database is locked immediately. However the
- lock is not released until after all relevant operations
- in the write-queue have been flushed to disk. This means
- (for example) that the database may remain locked for some
- time after a "COMMIT" or "ROLLBACK" is issued.
-
- * If an application using asynchronous IO executes transactions
- in quick succession, other database users may be effectively
- locked out of the database. This is because when a BEGIN
- is executed, a database lock is established immediately. But
- when the corresponding COMMIT or ROLLBACK occurs, the lock
- is not released until the relevant part of the write-queue
- has been flushed through. As a result, if a COMMIT is followed
- by a BEGIN before the write-queue is flushed through, the database
- is never unlocked,preventing other processes from accessing
- the database.
-
- File-locking may be disabled at runtime using the sqlite3async_control()
- API (see below). This may improve performance when an NFS or other
- network file-system, as the synchronous round-trips to the server be
- required to establish file locks are avoided. However, if multiple
- connections attempt to access the same database file when file-locking
- is disabled, application crashes and database corruption is a likely
- outcome.
-
-
-2. COMPILATION AND USAGE
-
- The asynchronous IO extension consists of a single file of C code
- (sqlite3async.c), and a header file (sqlite3async.h) that defines the
- C API used by applications to activate and control the modules
- functionality.
-
- To use the asynchronous IO extension, compile sqlite3async.c as
- part of the application that uses SQLite. Then use the API defined
- in sqlite3async.h to initialize and configure the module.
-
- The asynchronous IO VFS API is described in detail in comments in
- sqlite3async.h. Using the API usually consists of the following steps:
-
- 1. Register the asynchronous IO VFS with SQLite by calling the
- sqlite3async_initialize() function.
-
- 2. Create a background thread to perform write operations and call
- sqlite3async_run().
-
- 3. Use the normal SQLite API to read and write to databases via
- the asynchronous IO VFS.
-
- Refer to sqlite3async.h for details.
-
-
-3. PORTING
-
- Currently the asynchronous IO extension is compatible with win32 systems
- and systems that support the pthreads interface, including Mac OSX, Linux,
- and other varieties of Unix.
-
- To port the asynchronous IO extension to another platform, the user must
- implement mutex and condition variable primitives for the new platform.
- Currently there is no externally available interface to allow this, but
- modifying the code within sqlite3async.c to include the new platforms
- concurrency primitives is relatively easy. Search within sqlite3async.c
- for the comment string "PORTING FUNCTIONS" for details. Then implement
- new versions of each of the following:
-
- static void async_mutex_enter(int eMutex);
- static void async_mutex_leave(int eMutex);
- static void async_cond_wait(int eCond, int eMutex);
- static void async_cond_signal(int eCond);
- static void async_sched_yield(void);
-
- The functionality required of each of the above functions is described
- in comments in sqlite3async.c.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/sqlite3async.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/sqlite3async.c
deleted file mode 100644
index b6f4a4bd36b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/sqlite3async.c
+++ /dev/null
@@ -1,1707 +0,0 @@
-/*
-** 2005 December 14
-**
-** 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.
-**
-*************************************************************************
-**
-** $Id: sqlite3async.c,v 1.7 2009/07/18 11:52:04 danielk1977 Exp $
-**
-** This file contains the implementation of an asynchronous IO backend
-** for SQLite.
-*/
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO)
-
-#include "sqlite3async.h"
-#include "sqlite3.h"
-#include <stdarg.h>
-#include <string.h>
-#include <assert.h>
-
-/* Useful macros used in several places */
-#define MIN(x,y) ((x)<(y)?(x):(y))
-#define MAX(x,y) ((x)>(y)?(x):(y))
-
-#ifndef SQLITE_AMALGAMATION
-/* Macro to mark parameters as unused and silence compiler warnings. */
-#define UNUSED_PARAMETER(x) (void)(x)
-#endif
-
-/* Forward references */
-typedef struct AsyncWrite AsyncWrite;
-typedef struct AsyncFile AsyncFile;
-typedef struct AsyncFileData AsyncFileData;
-typedef struct AsyncFileLock AsyncFileLock;
-typedef struct AsyncLock AsyncLock;
-
-/* Enable for debugging */
-#ifndef NDEBUG
-#include <stdio.h>
-static int sqlite3async_trace = 0;
-# define ASYNC_TRACE(X) if( sqlite3async_trace ) asyncTrace X
-static void asyncTrace(const char *zFormat, ...){
- char *z;
- va_list ap;
- va_start(ap, zFormat);
- z = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- fprintf(stderr, "[%d] %s", 0 /* (int)pthread_self() */, z);
- sqlite3_free(z);
-}
-#else
-# define ASYNC_TRACE(X)
-#endif
-
-/*
-** THREAD SAFETY NOTES
-**
-** Basic rules:
-**
-** * Both read and write access to the global write-op queue must be
-** protected by the async.queueMutex. As are the async.ioError and
-** async.nFile variables.
-**
-** * The async.pLock list and all AsyncLock and AsyncFileLock
-** structures must be protected by the async.lockMutex mutex.
-**
-** * The file handles from the underlying system are not assumed to
-** be thread safe.
-**
-** * See the last two paragraphs under "The Writer Thread" for
-** an assumption to do with file-handle synchronization by the Os.
-**
-** Deadlock prevention:
-**
-** There are three mutex used by the system: the "writer" mutex,
-** the "queue" mutex and the "lock" mutex. Rules are:
-**
-** * It is illegal to block on the writer mutex when any other mutex
-** are held, and
-**
-** * It is illegal to block on the queue mutex when the lock mutex
-** is held.
-**
-** i.e. mutex's must be grabbed in the order "writer", "queue", "lock".
-**
-** File system operations (invoked by SQLite thread):
-**
-** xOpen
-** xDelete
-** xFileExists
-**
-** File handle operations (invoked by SQLite thread):
-**
-** asyncWrite, asyncClose, asyncTruncate, asyncSync
-**
-** The operations above add an entry to the global write-op list. They
-** prepare the entry, acquire the async.queueMutex momentarily while
-** list pointers are manipulated to insert the new entry, then release
-** the mutex and signal the writer thread to wake up in case it happens
-** to be asleep.
-**
-**
-** asyncRead, asyncFileSize.
-**
-** Read operations. Both of these read from both the underlying file
-** first then adjust their result based on pending writes in the
-** write-op queue. So async.queueMutex is held for the duration
-** of these operations to prevent other threads from changing the
-** queue in mid operation.
-**
-**
-** asyncLock, asyncUnlock, asyncCheckReservedLock
-**
-** These primitives implement in-process locking using a hash table
-** on the file name. Files are locked correctly for connections coming
-** from the same process. But other processes cannot see these locks
-** and will therefore not honor them.
-**
-**
-** The writer thread:
-**
-** The async.writerMutex is used to make sure only there is only
-** a single writer thread running at a time.
-**
-** Inside the writer thread is a loop that works like this:
-**
-** WHILE (write-op list is not empty)
-** Do IO operation at head of write-op list
-** Remove entry from head of write-op list
-** END WHILE
-**
-** The async.queueMutex is always held during the <write-op list is
-** not empty> test, and when the entry is removed from the head
-** of the write-op list. Sometimes it is held for the interim
-** period (while the IO is performed), and sometimes it is
-** relinquished. It is relinquished if (a) the IO op is an
-** ASYNC_CLOSE or (b) when the file handle was opened, two of
-** the underlying systems handles were opened on the same
-** file-system entry.
-**
-** If condition (b) above is true, then one file-handle
-** (AsyncFile.pBaseRead) is used exclusively by sqlite threads to read the
-** file, the other (AsyncFile.pBaseWrite) by sqlite3_async_flush()
-** threads to perform write() operations. This means that read
-** operations are not blocked by asynchronous writes (although
-** asynchronous writes may still be blocked by reads).
-**
-** This assumes that the OS keeps two handles open on the same file
-** properly in sync. That is, any read operation that starts after a
-** write operation on the same file system entry has completed returns
-** data consistent with the write. We also assume that if one thread
-** reads a file while another is writing it all bytes other than the
-** ones actually being written contain valid data.
-**
-** If the above assumptions are not true, set the preprocessor symbol
-** SQLITE_ASYNC_TWO_FILEHANDLES to 0.
-*/
-
-
-#ifndef NDEBUG
-# define TESTONLY( X ) X
-#else
-# define TESTONLY( X )
-#endif
-
-/*
-** PORTING FUNCTIONS
-**
-** There are two definitions of the following functions. One for pthreads
-** compatible systems and one for Win32. These functions isolate the OS
-** specific code required by each platform.
-**
-** The system uses three mutexes and a single condition variable. To
-** block on a mutex, async_mutex_enter() is called. The parameter passed
-** to async_mutex_enter(), which must be one of ASYNC_MUTEX_LOCK,
-** ASYNC_MUTEX_QUEUE or ASYNC_MUTEX_WRITER, identifies which of the three
-** mutexes to lock. Similarly, to unlock a mutex, async_mutex_leave() is
-** called with a parameter identifying the mutex being unlocked. Mutexes
-** are not recursive - it is an error to call async_mutex_enter() to
-** lock a mutex that is already locked, or to call async_mutex_leave()
-** to unlock a mutex that is not currently locked.
-**
-** The async_cond_wait() and async_cond_signal() functions are modelled
-** on the pthreads functions with similar names. The first parameter to
-** both functions is always ASYNC_COND_QUEUE. When async_cond_wait()
-** is called the mutex identified by the second parameter must be held.
-** The mutex is unlocked, and the calling thread simultaneously begins
-** waiting for the condition variable to be signalled by another thread.
-** After another thread signals the condition variable, the calling
-** thread stops waiting, locks mutex eMutex and returns. The
-** async_cond_signal() function is used to signal the condition variable.
-** It is assumed that the mutex used by the thread calling async_cond_wait()
-** is held by the caller of async_cond_signal() (otherwise there would be
-** a race condition).
-**
-** It is guaranteed that no other thread will call async_cond_wait() when
-** there is already a thread waiting on the condition variable.
-**
-** The async_sched_yield() function is called to suggest to the operating
-** system that it would be a good time to shift the current thread off the
-** CPU. The system will still work if this function is not implemented
-** (it is not currently implemented for win32), but it might be marginally
-** more efficient if it is.
-*/
-static void async_mutex_enter(int eMutex);
-static void async_mutex_leave(int eMutex);
-static void async_cond_wait(int eCond, int eMutex);
-static void async_cond_signal(int eCond);
-static void async_sched_yield(void);
-
-/*
-** There are also two definitions of the following. async_os_initialize()
-** is called when the asynchronous VFS is first installed, and os_shutdown()
-** is called when it is uninstalled (from within sqlite3async_shutdown()).
-**
-** For pthreads builds, both of these functions are no-ops. For win32,
-** they provide an opportunity to initialize and finalize the required
-** mutex and condition variables.
-**
-** If async_os_initialize() returns other than zero, then the initialization
-** fails and SQLITE_ERROR is returned to the user.
-*/
-static int async_os_initialize(void);
-static void async_os_shutdown(void);
-
-/* Values for use as the 'eMutex' argument of the above functions. The
-** integer values assigned to these constants are important for assert()
-** statements that verify that mutexes are locked in the correct order.
-** Specifically, it is unsafe to try to lock mutex N while holding a lock
-** on mutex M if (M<=N).
-*/
-#define ASYNC_MUTEX_LOCK 0
-#define ASYNC_MUTEX_QUEUE 1
-#define ASYNC_MUTEX_WRITER 2
-
-/* Values for use as the 'eCond' argument of the above functions. */
-#define ASYNC_COND_QUEUE 0
-
-/*************************************************************************
-** Start of OS specific code.
-*/
-#if SQLITE_OS_WIN || defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
-
-#include <windows.h>
-
-/* The following block contains the win32 specific code. */
-
-#define mutex_held(X) (GetCurrentThreadId()==primitives.aHolder[X])
-
-static struct AsyncPrimitives {
- int isInit;
- DWORD aHolder[3];
- CRITICAL_SECTION aMutex[3];
- HANDLE aCond[1];
-} primitives = { 0 };
-
-static int async_os_initialize(void){
- if( !primitives.isInit ){
- primitives.aCond[0] = CreateEvent(NULL, TRUE, FALSE, 0);
- if( primitives.aCond[0]==NULL ){
- return 1;
- }
- InitializeCriticalSection(&primitives.aMutex[0]);
- InitializeCriticalSection(&primitives.aMutex[1]);
- InitializeCriticalSection(&primitives.aMutex[2]);
- primitives.isInit = 1;
- }
- return 0;
-}
-static void async_os_shutdown(void){
- if( primitives.isInit ){
- DeleteCriticalSection(&primitives.aMutex[0]);
- DeleteCriticalSection(&primitives.aMutex[1]);
- DeleteCriticalSection(&primitives.aMutex[2]);
- CloseHandle(primitives.aCond[0]);
- primitives.isInit = 0;
- }
-}
-
-/* The following block contains the Win32 specific code. */
-static void async_mutex_enter(int eMutex){
- assert( eMutex==0 || eMutex==1 || eMutex==2 );
- assert( eMutex!=2 || (!mutex_held(0) && !mutex_held(1) && !mutex_held(2)) );
- assert( eMutex!=1 || (!mutex_held(0) && !mutex_held(1)) );
- assert( eMutex!=0 || (!mutex_held(0)) );
- EnterCriticalSection(&primitives.aMutex[eMutex]);
- TESTONLY( primitives.aHolder[eMutex] = GetCurrentThreadId(); )
-}
-static void async_mutex_leave(int eMutex){
- assert( eMutex==0 || eMutex==1 || eMutex==2 );
- assert( mutex_held(eMutex) );
- TESTONLY( primitives.aHolder[eMutex] = 0; )
- LeaveCriticalSection(&primitives.aMutex[eMutex]);
-}
-static void async_cond_wait(int eCond, int eMutex){
- ResetEvent(primitives.aCond[eCond]);
- async_mutex_leave(eMutex);
- WaitForSingleObject(primitives.aCond[eCond], INFINITE);
- async_mutex_enter(eMutex);
-}
-static void async_cond_signal(int eCond){
- assert( mutex_held(ASYNC_MUTEX_QUEUE) );
- SetEvent(primitives.aCond[eCond]);
-}
-static void async_sched_yield(void){
- Sleep(0);
-}
-#else
-
-/* The following block contains the pthreads specific code. */
-#include <pthread.h>
-#include <sched.h>
-
-#define mutex_held(X) pthread_equal(primitives.aHolder[X], pthread_self())
-
-static int async_os_initialize(void) {return 0;}
-static void async_os_shutdown(void) {}
-
-static struct AsyncPrimitives {
- pthread_mutex_t aMutex[3];
- pthread_cond_t aCond[1];
- pthread_t aHolder[3];
-} primitives = {
- { PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_MUTEX_INITIALIZER
- } , {
- PTHREAD_COND_INITIALIZER
- } , { 0, 0, 0 }
-};
-
-static void async_mutex_enter(int eMutex){
- assert( eMutex==0 || eMutex==1 || eMutex==2 );
- assert( eMutex!=2 || (!mutex_held(0) && !mutex_held(1) && !mutex_held(2)) );
- assert( eMutex!=1 || (!mutex_held(0) && !mutex_held(1)) );
- assert( eMutex!=0 || (!mutex_held(0)) );
- pthread_mutex_lock(&primitives.aMutex[eMutex]);
- TESTONLY( primitives.aHolder[eMutex] = pthread_self(); )
-}
-static void async_mutex_leave(int eMutex){
- assert( eMutex==0 || eMutex==1 || eMutex==2 );
- assert( mutex_held(eMutex) );
- TESTONLY( primitives.aHolder[eMutex] = 0; )
- pthread_mutex_unlock(&primitives.aMutex[eMutex]);
-}
-static void async_cond_wait(int eCond, int eMutex){
- assert( eMutex==0 || eMutex==1 || eMutex==2 );
- assert( mutex_held(eMutex) );
- TESTONLY( primitives.aHolder[eMutex] = 0; )
- pthread_cond_wait(&primitives.aCond[eCond], &primitives.aMutex[eMutex]);
- TESTONLY( primitives.aHolder[eMutex] = pthread_self(); )
-}
-static void async_cond_signal(int eCond){
- assert( mutex_held(ASYNC_MUTEX_QUEUE) );
- pthread_cond_signal(&primitives.aCond[eCond]);
-}
-static void async_sched_yield(void){
- sched_yield();
-}
-#endif
-/*
-** End of OS specific code.
-*************************************************************************/
-
-#define assert_mutex_is_held(X) assert( mutex_held(X) )
-
-
-#ifndef SQLITE_ASYNC_TWO_FILEHANDLES
-/* #define SQLITE_ASYNC_TWO_FILEHANDLES 0 */
-#define SQLITE_ASYNC_TWO_FILEHANDLES 1
-#endif
-
-/*
-** State information is held in the static variable "async" defined
-** as the following structure.
-**
-** Both async.ioError and async.nFile are protected by async.queueMutex.
-*/
-static struct TestAsyncStaticData {
- AsyncWrite *pQueueFirst; /* Next write operation to be processed */
- AsyncWrite *pQueueLast; /* Last write operation on the list */
- AsyncLock *pLock; /* Linked list of all AsyncLock structures */
- volatile int ioDelay; /* Extra delay between write operations */
- volatile int eHalt; /* One of the SQLITEASYNC_HALT_XXX values */
- volatile int bLockFiles; /* Current value of "lockfiles" parameter */
- int ioError; /* True if an IO error has occurred */
- int nFile; /* Number of open files (from sqlite pov) */
-} async = { 0,0,0,0,0,1,0,0 };
-
-/* Possible values of AsyncWrite.op */
-#define ASYNC_NOOP 0
-#define ASYNC_WRITE 1
-#define ASYNC_SYNC 2
-#define ASYNC_TRUNCATE 3
-#define ASYNC_CLOSE 4
-#define ASYNC_DELETE 5
-#define ASYNC_OPENEXCLUSIVE 6
-#define ASYNC_UNLOCK 7
-
-/* Names of opcodes. Used for debugging only.
-** Make sure these stay in sync with the macros above!
-*/
-static const char *azOpcodeName[] = {
- "NOOP", "WRITE", "SYNC", "TRUNCATE", "CLOSE", "DELETE", "OPENEX", "UNLOCK"
-};
-
-/*
-** Entries on the write-op queue are instances of the AsyncWrite
-** structure, defined here.
-**
-** The interpretation of the iOffset and nByte variables varies depending
-** on the value of AsyncWrite.op:
-**
-** ASYNC_NOOP:
-** No values used.
-**
-** ASYNC_WRITE:
-** iOffset -> Offset in file to write to.
-** nByte -> Number of bytes of data to write (pointed to by zBuf).
-**
-** ASYNC_SYNC:
-** nByte -> flags to pass to sqlite3OsSync().
-**
-** ASYNC_TRUNCATE:
-** iOffset -> Size to truncate file to.
-** nByte -> Unused.
-**
-** ASYNC_CLOSE:
-** iOffset -> Unused.
-** nByte -> Unused.
-**
-** ASYNC_DELETE:
-** iOffset -> Contains the "syncDir" flag.
-** nByte -> Number of bytes of zBuf points to (file name).
-**
-** ASYNC_OPENEXCLUSIVE:
-** iOffset -> Value of "delflag".
-** nByte -> Number of bytes of zBuf points to (file name).
-**
-** ASYNC_UNLOCK:
-** nByte -> Argument to sqlite3OsUnlock().
-**
-**
-** For an ASYNC_WRITE operation, zBuf points to the data to write to the file.
-** This space is sqlite3_malloc()d along with the AsyncWrite structure in a
-** single blob, so is deleted when sqlite3_free() is called on the parent
-** structure.
-*/
-struct AsyncWrite {
- AsyncFileData *pFileData; /* File to write data to or sync */
- int op; /* One of ASYNC_xxx etc. */
- sqlite_int64 iOffset; /* See above */
- int nByte; /* See above */
- char *zBuf; /* Data to write to file (or NULL if op!=ASYNC_WRITE) */
- AsyncWrite *pNext; /* Next write operation (to any file) */
-};
-
-/*
-** An instance of this structure is created for each distinct open file
-** (i.e. if two handles are opened on the one file, only one of these
-** structures is allocated) and stored in the async.aLock hash table. The
-** keys for async.aLock are the full pathnames of the opened files.
-**
-** AsyncLock.pList points to the head of a linked list of AsyncFileLock
-** structures, one for each handle currently open on the file.
-**
-** If the opened file is not a main-database (the SQLITE_OPEN_MAIN_DB is
-** not passed to the sqlite3OsOpen() call), or if async.bLockFiles is
-** false, variables AsyncLock.pFile and AsyncLock.eLock are never used.
-** Otherwise, pFile is a file handle opened on the file in question and
-** used to obtain the file-system locks required by database connections
-** within this process.
-**
-** See comments above the asyncLock() function for more details on
-** the implementation of database locking used by this backend.
-*/
-struct AsyncLock {
- char *zFile;
- int nFile;
- sqlite3_file *pFile;
- int eLock;
- AsyncFileLock *pList;
- AsyncLock *pNext; /* Next in linked list headed by async.pLock */
-};
-
-/*
-** An instance of the following structure is allocated along with each
-** AsyncFileData structure (see AsyncFileData.lock), but is only used if the
-** file was opened with the SQLITE_OPEN_MAIN_DB.
-*/
-struct AsyncFileLock {
- int eLock; /* Internally visible lock state (sqlite pov) */
- int eAsyncLock; /* Lock-state with write-queue unlock */
- AsyncFileLock *pNext;
-};
-
-/*
-** The AsyncFile structure is a subclass of sqlite3_file used for
-** asynchronous IO.
-**
-** All of the actual data for the structure is stored in the structure
-** pointed to by AsyncFile.pData, which is allocated as part of the
-** sqlite3OsOpen() using sqlite3_malloc(). The reason for this is that the
-** lifetime of the AsyncFile structure is ended by the caller after OsClose()
-** is called, but the data in AsyncFileData may be required by the
-** writer thread after that point.
-*/
-struct AsyncFile {
- sqlite3_io_methods *pMethod;
- AsyncFileData *pData;
-};
-struct AsyncFileData {
- char *zName; /* Underlying OS filename - used for debugging */
- int nName; /* Number of characters in zName */
- sqlite3_file *pBaseRead; /* Read handle to the underlying Os file */
- sqlite3_file *pBaseWrite; /* Write handle to the underlying Os file */
- AsyncFileLock lock; /* Lock state for this handle */
- AsyncLock *pLock; /* AsyncLock object for this file system entry */
- AsyncWrite closeOp; /* Preallocated close operation */
-};
-
-/*
-** Add an entry to the end of the global write-op list. pWrite should point
-** to an AsyncWrite structure allocated using sqlite3_malloc(). The writer
-** thread will call sqlite3_free() to free the structure after the specified
-** operation has been completed.
-**
-** Once an AsyncWrite structure has been added to the list, it becomes the
-** property of the writer thread and must not be read or modified by the
-** caller.
-*/
-static void addAsyncWrite(AsyncWrite *pWrite){
- /* We must hold the queue mutex in order to modify the queue pointers */
- if( pWrite->op!=ASYNC_UNLOCK ){
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- }
-
- /* Add the record to the end of the write-op queue */
- assert( !pWrite->pNext );
- if( async.pQueueLast ){
- assert( async.pQueueFirst );
- async.pQueueLast->pNext = pWrite;
- }else{
- async.pQueueFirst = pWrite;
- }
- async.pQueueLast = pWrite;
- ASYNC_TRACE(("PUSH %p (%s %s %d)\n", pWrite, azOpcodeName[pWrite->op],
- pWrite->pFileData ? pWrite->pFileData->zName : "-", pWrite->iOffset));
-
- if( pWrite->op==ASYNC_CLOSE ){
- async.nFile--;
- }
-
- /* The writer thread might have been idle because there was nothing
- ** on the write-op queue for it to do. So wake it up. */
- async_cond_signal(ASYNC_COND_QUEUE);
-
- /* Drop the queue mutex */
- if( pWrite->op!=ASYNC_UNLOCK ){
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- }
-}
-
-/*
-** Increment async.nFile in a thread-safe manner.
-*/
-static void incrOpenFileCount(void){
- /* We must hold the queue mutex in order to modify async.nFile */
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- if( async.nFile==0 ){
- async.ioError = SQLITE_OK;
- }
- async.nFile++;
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
-}
-
-/*
-** This is a utility function to allocate and populate a new AsyncWrite
-** structure and insert it (via addAsyncWrite() ) into the global list.
-*/
-static int addNewAsyncWrite(
- AsyncFileData *pFileData,
- int op,
- sqlite3_int64 iOffset,
- int nByte,
- const char *zByte
-){
- AsyncWrite *p;
- if( op!=ASYNC_CLOSE && async.ioError ){
- return async.ioError;
- }
- p = sqlite3_malloc(sizeof(AsyncWrite) + (zByte?nByte:0));
- if( !p ){
- /* The upper layer does not expect operations like OsWrite() to
- ** return SQLITE_NOMEM. This is partly because under normal conditions
- ** SQLite is required to do rollback without calling malloc(). So
- ** if malloc() fails here, treat it as an I/O error. The above
- ** layer knows how to handle that.
- */
- return SQLITE_IOERR;
- }
- p->op = op;
- p->iOffset = iOffset;
- p->nByte = nByte;
- p->pFileData = pFileData;
- p->pNext = 0;
- if( zByte ){
- p->zBuf = (char *)&p[1];
- memcpy(p->zBuf, zByte, nByte);
- }else{
- p->zBuf = 0;
- }
- addAsyncWrite(p);
- return SQLITE_OK;
-}
-
-/*
-** Close the file. This just adds an entry to the write-op list, the file is
-** not actually closed.
-*/
-static int asyncClose(sqlite3_file *pFile){
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
-
- /* Unlock the file, if it is locked */
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- p->lock.eLock = 0;
- async_mutex_leave(ASYNC_MUTEX_LOCK);
-
- addAsyncWrite(&p->closeOp);
- return SQLITE_OK;
-}
-
-/*
-** Implementation of sqlite3OsWrite() for asynchronous files. Instead of
-** writing to the underlying file, this function adds an entry to the end of
-** the global AsyncWrite list. Either SQLITE_OK or SQLITE_NOMEM may be
-** returned.
-*/
-static int asyncWrite(
- sqlite3_file *pFile,
- const void *pBuf,
- int amt,
- sqlite3_int64 iOff
-){
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
- return addNewAsyncWrite(p, ASYNC_WRITE, iOff, amt, pBuf);
-}
-
-/*
-** Read data from the file. First we read from the filesystem, then adjust
-** the contents of the buffer based on ASYNC_WRITE operations in the
-** write-op queue.
-**
-** This method holds the mutex from start to finish.
-*/
-static int asyncRead(
- sqlite3_file *pFile,
- void *zOut,
- int iAmt,
- sqlite3_int64 iOffset
-){
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
- int rc = SQLITE_OK;
- sqlite3_int64 filesize = 0;
- sqlite3_file *pBase = p->pBaseRead;
- sqlite3_int64 iAmt64 = (sqlite3_int64)iAmt;
-
- /* Grab the write queue mutex for the duration of the call */
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
-
- /* If an I/O error has previously occurred in this virtual file
- ** system, then all subsequent operations fail.
- */
- if( async.ioError!=SQLITE_OK ){
- rc = async.ioError;
- goto asyncread_out;
- }
-
- if( pBase->pMethods ){
- sqlite3_int64 nRead;
- rc = pBase->pMethods->xFileSize(pBase, &filesize);
- if( rc!=SQLITE_OK ){
- goto asyncread_out;
- }
- nRead = MIN(filesize - iOffset, iAmt64);
- if( nRead>0 ){
- rc = pBase->pMethods->xRead(pBase, zOut, (int)nRead, iOffset);
- ASYNC_TRACE(("READ %s %d bytes at %d\n", p->zName, nRead, iOffset));
- }
- }
-
- if( rc==SQLITE_OK ){
- AsyncWrite *pWrite;
- char *zName = p->zName;
-
- for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
- if( pWrite->op==ASYNC_WRITE && (
- (pWrite->pFileData==p) ||
- (zName && pWrite->pFileData->zName==zName)
- )){
- sqlite3_int64 nCopy;
- sqlite3_int64 nByte64 = (sqlite3_int64)pWrite->nByte;
-
- /* Set variable iBeginIn to the offset in buffer pWrite->zBuf[] from
- ** which data should be copied. Set iBeginOut to the offset within
- ** the output buffer to which data should be copied. If either of
- ** these offsets is a negative number, set them to 0.
- */
- sqlite3_int64 iBeginOut = (pWrite->iOffset-iOffset);
- sqlite3_int64 iBeginIn = -iBeginOut;
- if( iBeginIn<0 ) iBeginIn = 0;
- if( iBeginOut<0 ) iBeginOut = 0;
-
- filesize = MAX(filesize, pWrite->iOffset+nByte64);
-
- nCopy = MIN(nByte64-iBeginIn, iAmt64-iBeginOut);
- if( nCopy>0 ){
- memcpy(&((char *)zOut)[iBeginOut], &pWrite->zBuf[iBeginIn], (size_t)nCopy);
- ASYNC_TRACE(("OVERREAD %d bytes at %d\n", nCopy, iBeginOut+iOffset));
- }
- }
- }
- }
-
-asyncread_out:
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- if( rc==SQLITE_OK && filesize<(iOffset+iAmt) ){
- rc = SQLITE_IOERR_SHORT_READ;
- }
- return rc;
-}
-
-/*
-** Truncate the file to nByte bytes in length. This just adds an entry to
-** the write-op list, no IO actually takes place.
-*/
-static int asyncTruncate(sqlite3_file *pFile, sqlite3_int64 nByte){
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
- return addNewAsyncWrite(p, ASYNC_TRUNCATE, nByte, 0, 0);
-}
-
-/*
-** Sync the file. This just adds an entry to the write-op list, the
-** sync() is done later by sqlite3_async_flush().
-*/
-static int asyncSync(sqlite3_file *pFile, int flags){
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
- return addNewAsyncWrite(p, ASYNC_SYNC, 0, flags, 0);
-}
-
-/*
-** Read the size of the file. First we read the size of the file system
-** entry, then adjust for any ASYNC_WRITE or ASYNC_TRUNCATE operations
-** currently in the write-op list.
-**
-** This method holds the mutex from start to finish.
-*/
-int asyncFileSize(sqlite3_file *pFile, sqlite3_int64 *piSize){
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
- int rc = SQLITE_OK;
- sqlite3_int64 s = 0;
- sqlite3_file *pBase;
-
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
-
- /* Read the filesystem size from the base file. If pMethods is NULL, this
- ** means the file hasn't been opened yet. In this case all relevant data
- ** must be in the write-op queue anyway, so we can omit reading from the
- ** file-system.
- */
- pBase = p->pBaseRead;
- if( pBase->pMethods ){
- rc = pBase->pMethods->xFileSize(pBase, &s);
- }
-
- if( rc==SQLITE_OK ){
- AsyncWrite *pWrite;
- for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
- if( pWrite->op==ASYNC_DELETE
- && p->zName
- && strcmp(p->zName, pWrite->zBuf)==0
- ){
- s = 0;
- }else if( pWrite->pFileData && (
- (pWrite->pFileData==p)
- || (p->zName && pWrite->pFileData->zName==p->zName)
- )){
- switch( pWrite->op ){
- case ASYNC_WRITE:
- s = MAX(pWrite->iOffset + (sqlite3_int64)(pWrite->nByte), s);
- break;
- case ASYNC_TRUNCATE:
- s = MIN(s, pWrite->iOffset);
- break;
- }
- }
- }
- *piSize = s;
- }
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- return rc;
-}
-
-/*
-** Lock or unlock the actual file-system entry.
-*/
-static int getFileLock(AsyncLock *pLock){
- int rc = SQLITE_OK;
- AsyncFileLock *pIter;
- int eRequired = 0;
-
- if( pLock->pFile ){
- for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
- assert(pIter->eAsyncLock>=pIter->eLock);
- if( pIter->eAsyncLock>eRequired ){
- eRequired = pIter->eAsyncLock;
- assert(eRequired>=0 && eRequired<=SQLITE_LOCK_EXCLUSIVE);
- }
- }
-
- if( eRequired>pLock->eLock ){
- rc = pLock->pFile->pMethods->xLock(pLock->pFile, eRequired);
- if( rc==SQLITE_OK ){
- pLock->eLock = eRequired;
- }
- }
- else if( eRequired<pLock->eLock && eRequired<=SQLITE_LOCK_SHARED ){
- rc = pLock->pFile->pMethods->xUnlock(pLock->pFile, eRequired);
- if( rc==SQLITE_OK ){
- pLock->eLock = eRequired;
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Return the AsyncLock structure from the global async.pLock list
-** associated with the file-system entry identified by path zName
-** (a string of nName bytes). If no such structure exists, return 0.
-*/
-static AsyncLock *findLock(const char *zName, int nName){
- AsyncLock *p = async.pLock;
- while( p && (p->nFile!=nName || memcmp(p->zFile, zName, nName)) ){
- p = p->pNext;
- }
- return p;
-}
-
-/*
-** The following two methods - asyncLock() and asyncUnlock() - are used
-** to obtain and release locks on database files opened with the
-** asynchronous backend.
-*/
-static int asyncLock(sqlite3_file *pFile, int eLock){
- int rc = SQLITE_OK;
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
-
- if( p->zName ){
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- if( p->lock.eLock<eLock ){
- AsyncLock *pLock = p->pLock;
- AsyncFileLock *pIter;
- assert(pLock && pLock->pList);
- for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
- if( pIter!=&p->lock && (
- (eLock==SQLITE_LOCK_EXCLUSIVE && pIter->eLock>=SQLITE_LOCK_SHARED) ||
- (eLock==SQLITE_LOCK_PENDING && pIter->eLock>=SQLITE_LOCK_RESERVED) ||
- (eLock==SQLITE_LOCK_RESERVED && pIter->eLock>=SQLITE_LOCK_RESERVED) ||
- (eLock==SQLITE_LOCK_SHARED && pIter->eLock>=SQLITE_LOCK_PENDING)
- )){
- rc = SQLITE_BUSY;
- }
- }
- if( rc==SQLITE_OK ){
- p->lock.eLock = eLock;
- p->lock.eAsyncLock = MAX(p->lock.eAsyncLock, eLock);
- }
- assert(p->lock.eAsyncLock>=p->lock.eLock);
- if( rc==SQLITE_OK ){
- rc = getFileLock(pLock);
- }
- }
- async_mutex_leave(ASYNC_MUTEX_LOCK);
- }
-
- ASYNC_TRACE(("LOCK %d (%s) rc=%d\n", eLock, p->zName, rc));
- return rc;
-}
-static int asyncUnlock(sqlite3_file *pFile, int eLock){
- int rc = SQLITE_OK;
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
- if( p->zName ){
- AsyncFileLock *pLock = &p->lock;
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- pLock->eLock = MIN(pLock->eLock, eLock);
- rc = addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0);
- async_mutex_leave(ASYNC_MUTEX_LOCK);
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- }
- return rc;
-}
-
-/*
-** This function is called when the pager layer first opens a database file
-** and is checking for a hot-journal.
-*/
-static int asyncCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- int ret = 0;
- AsyncFileLock *pIter;
- AsyncFileData *p = ((AsyncFile *)pFile)->pData;
-
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- for(pIter=p->pLock->pList; pIter; pIter=pIter->pNext){
- if( pIter->eLock>=SQLITE_LOCK_RESERVED ){
- ret = 1;
- break;
- }
- }
- async_mutex_leave(ASYNC_MUTEX_LOCK);
-
- ASYNC_TRACE(("CHECK-LOCK %d (%s)\n", ret, p->zName));
- *pResOut = ret;
- return SQLITE_OK;
-}
-
-/*
-** sqlite3_file_control() implementation.
-*/
-static int asyncFileControl(sqlite3_file *id, int op, void *pArg){
- switch( op ){
- case SQLITE_FCNTL_LOCKSTATE: {
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- *(int*)pArg = ((AsyncFile*)id)->pData->lock.eLock;
- async_mutex_leave(ASYNC_MUTEX_LOCK);
- return SQLITE_OK;
- }
- }
- return SQLITE_NOTFOUND;
-}
-
-/*
-** Return the device characteristics and sector-size of the device. It
-** is tricky to implement these correctly, as this backend might
-** not have an open file handle at this point.
-*/
-static int asyncSectorSize(sqlite3_file *pFile){
- UNUSED_PARAMETER(pFile);
- return 512;
-}
-static int asyncDeviceCharacteristics(sqlite3_file *pFile){
- UNUSED_PARAMETER(pFile);
- return 0;
-}
-
-static int unlinkAsyncFile(AsyncFileData *pData){
- AsyncFileLock **ppIter;
- int rc = SQLITE_OK;
-
- if( pData->zName ){
- AsyncLock *pLock = pData->pLock;
- for(ppIter=&pLock->pList; *ppIter; ppIter=&((*ppIter)->pNext)){
- if( (*ppIter)==&pData->lock ){
- *ppIter = pData->lock.pNext;
- break;
- }
- }
- if( !pLock->pList ){
- AsyncLock **pp;
- if( pLock->pFile ){
- pLock->pFile->pMethods->xClose(pLock->pFile);
- }
- for(pp=&async.pLock; *pp!=pLock; pp=&((*pp)->pNext));
- *pp = pLock->pNext;
- sqlite3_free(pLock);
- }else{
- rc = getFileLock(pLock);
- }
- }
-
- return rc;
-}
-
-/*
-** The parameter passed to this function is a copy of a 'flags' parameter
-** passed to this modules xOpen() method. This function returns true
-** if the file should be opened asynchronously, or false if it should
-** be opened immediately.
-**
-** If the file is to be opened asynchronously, then asyncOpen() will add
-** an entry to the event queue and the file will not actually be opened
-** until the event is processed. Otherwise, the file is opened directly
-** by the caller.
-*/
-static int doAsynchronousOpen(int flags){
- return (flags&SQLITE_OPEN_CREATE) && (
- (flags&SQLITE_OPEN_MAIN_JOURNAL) ||
- (flags&SQLITE_OPEN_TEMP_JOURNAL) ||
- (flags&SQLITE_OPEN_DELETEONCLOSE)
- );
-}
-
-/*
-** Open a file.
-*/
-static int asyncOpen(
- sqlite3_vfs *pAsyncVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- static sqlite3_io_methods async_methods = {
- 1, /* iVersion */
- asyncClose, /* xClose */
- asyncRead, /* xRead */
- asyncWrite, /* xWrite */
- asyncTruncate, /* xTruncate */
- asyncSync, /* xSync */
- asyncFileSize, /* xFileSize */
- asyncLock, /* xLock */
- asyncUnlock, /* xUnlock */
- asyncCheckReservedLock, /* xCheckReservedLock */
- asyncFileControl, /* xFileControl */
- asyncSectorSize, /* xSectorSize */
- asyncDeviceCharacteristics /* xDeviceCharacteristics */
- };
-
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- AsyncFile *p = (AsyncFile *)pFile;
- int nName = 0;
- int rc = SQLITE_OK;
- int nByte;
- AsyncFileData *pData;
- AsyncLock *pLock = 0;
- char *z;
- int isAsyncOpen = doAsynchronousOpen(flags);
-
- /* If zName is NULL, then the upper layer is requesting an anonymous file.
- ** Otherwise, allocate enough space to make a copy of the file name (along
- ** with the second nul-terminator byte required by xOpen).
- */
- if( zName ){
- nName = (int)strlen(zName);
- }
-
- nByte = (
- sizeof(AsyncFileData) + /* AsyncFileData structure */
- 2 * pVfs->szOsFile + /* AsyncFileData.pBaseRead and pBaseWrite */
- nName + 2 /* AsyncFileData.zName */
- );
- z = sqlite3_malloc(nByte);
- if( !z ){
- return SQLITE_NOMEM;
- }
- memset(z, 0, nByte);
- pData = (AsyncFileData*)z;
- z += sizeof(pData[0]);
- pData->pBaseRead = (sqlite3_file*)z;
- z += pVfs->szOsFile;
- pData->pBaseWrite = (sqlite3_file*)z;
- pData->closeOp.pFileData = pData;
- pData->closeOp.op = ASYNC_CLOSE;
-
- if( zName ){
- z += pVfs->szOsFile;
- pData->zName = z;
- pData->nName = nName;
- memcpy(pData->zName, zName, nName);
- }
-
- if( !isAsyncOpen ){
- int flagsout;
- rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseRead, flags, &flagsout);
- if( rc==SQLITE_OK
- && (flagsout&SQLITE_OPEN_READWRITE)
- && (flags&SQLITE_OPEN_EXCLUSIVE)==0
- ){
- rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseWrite, flags, 0);
- }
- if( pOutFlags ){
- *pOutFlags = flagsout;
- }
- }
-
- async_mutex_enter(ASYNC_MUTEX_LOCK);
-
- if( zName && rc==SQLITE_OK ){
- pLock = findLock(pData->zName, pData->nName);
- if( !pLock ){
- int nByte = pVfs->szOsFile + sizeof(AsyncLock) + pData->nName + 1;
- pLock = (AsyncLock *)sqlite3_malloc(nByte);
- if( pLock ){
- memset(pLock, 0, nByte);
- if( async.bLockFiles && (flags&SQLITE_OPEN_MAIN_DB) ){
- pLock->pFile = (sqlite3_file *)&pLock[1];
- rc = pVfs->xOpen(pVfs, pData->zName, pLock->pFile, flags, 0);
- if( rc!=SQLITE_OK ){
- sqlite3_free(pLock);
- pLock = 0;
- }
- }
- if( pLock ){
- pLock->nFile = pData->nName;
- pLock->zFile = &((char *)(&pLock[1]))[pVfs->szOsFile];
- memcpy(pLock->zFile, pData->zName, pLock->nFile);
- pLock->pNext = async.pLock;
- async.pLock = pLock;
- }
- }else{
- rc = SQLITE_NOMEM;
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- p->pMethod = &async_methods;
- p->pData = pData;
-
- /* Link AsyncFileData.lock into the linked list of
- ** AsyncFileLock structures for this file.
- */
- if( zName ){
- pData->lock.pNext = pLock->pList;
- pLock->pList = &pData->lock;
- pData->zName = pLock->zFile;
- }
- }else{
- if( pData->pBaseRead->pMethods ){
- pData->pBaseRead->pMethods->xClose(pData->pBaseRead);
- }
- if( pData->pBaseWrite->pMethods ){
- pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite);
- }
- sqlite3_free(pData);
- }
-
- async_mutex_leave(ASYNC_MUTEX_LOCK);
-
- if( rc==SQLITE_OK ){
- pData->pLock = pLock;
- }
-
- if( rc==SQLITE_OK && isAsyncOpen ){
- rc = addNewAsyncWrite(pData, ASYNC_OPENEXCLUSIVE, (sqlite3_int64)flags,0,0);
- if( rc==SQLITE_OK ){
- if( pOutFlags ) *pOutFlags = flags;
- }else{
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- unlinkAsyncFile(pData);
- async_mutex_leave(ASYNC_MUTEX_LOCK);
- sqlite3_free(pData);
- }
- }
- if( rc!=SQLITE_OK ){
- p->pMethod = 0;
- }else{
- incrOpenFileCount();
- }
-
- return rc;
-}
-
-/*
-** Implementation of sqlite3OsDelete. Add an entry to the end of the
-** write-op queue to perform the delete.
-*/
-static int asyncDelete(sqlite3_vfs *pAsyncVfs, const char *z, int syncDir){
- UNUSED_PARAMETER(pAsyncVfs);
- return addNewAsyncWrite(0, ASYNC_DELETE, syncDir, (int)strlen(z)+1, z);
-}
-
-/*
-** Implementation of sqlite3OsAccess. This method holds the mutex from
-** start to finish.
-*/
-static int asyncAccess(
- sqlite3_vfs *pAsyncVfs,
- const char *zName,
- int flags,
- int *pResOut
-){
- int rc;
- int ret;
- AsyncWrite *p;
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
-
- assert(flags==SQLITE_ACCESS_READWRITE
- || flags==SQLITE_ACCESS_READ
- || flags==SQLITE_ACCESS_EXISTS
- );
-
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- rc = pVfs->xAccess(pVfs, zName, flags, &ret);
- if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
- for(p=async.pQueueFirst; p; p = p->pNext){
- if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, zName) ){
- ret = 0;
- }else if( p->op==ASYNC_OPENEXCLUSIVE
- && p->pFileData->zName
- && 0==strcmp(p->pFileData->zName, zName)
- ){
- ret = 1;
- }
- }
- }
- ASYNC_TRACE(("ACCESS(%s): %s = %d\n",
- flags==SQLITE_ACCESS_READWRITE?"read-write":
- flags==SQLITE_ACCESS_READ?"read":"exists"
- , zName, ret)
- );
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- *pResOut = ret;
- return rc;
-}
-
-/*
-** Fill in zPathOut with the full path to the file identified by zPath.
-*/
-static int asyncFullPathname(
- sqlite3_vfs *pAsyncVfs,
- const char *zPath,
- int nPathOut,
- char *zPathOut
-){
- int rc;
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- rc = pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
-
- /* Because of the way intra-process file locking works, this backend
- ** needs to return a canonical path. The following block assumes the
- ** file-system uses unix style paths.
- */
- if( rc==SQLITE_OK ){
- int i, j;
- char *z = zPathOut;
- int n = (int)strlen(z);
- while( n>1 && z[n-1]=='/' ){ n--; }
- for(i=j=0; i<n; i++){
- if( z[i]=='/' ){
- if( z[i+1]=='/' ) continue;
- if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
- i += 1;
- continue;
- }
- if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
- while( j>0 && z[j-1]!='/' ){ j--; }
- if( j>0 ){ j--; }
- i += 2;
- continue;
- }
- }
- z[j++] = z[i];
- }
- z[j] = 0;
- }
-
- return rc;
-}
-static void *asyncDlOpen(sqlite3_vfs *pAsyncVfs, const char *zPath){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- return pVfs->xDlOpen(pVfs, zPath);
-}
-static void asyncDlError(sqlite3_vfs *pAsyncVfs, int nByte, char *zErrMsg){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- pVfs->xDlError(pVfs, nByte, zErrMsg);
-}
-static void (*asyncDlSym(
- sqlite3_vfs *pAsyncVfs,
- void *pHandle,
- const char *zSymbol
-))(void){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- return pVfs->xDlSym(pVfs, pHandle, zSymbol);
-}
-static void asyncDlClose(sqlite3_vfs *pAsyncVfs, void *pHandle){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- pVfs->xDlClose(pVfs, pHandle);
-}
-static int asyncRandomness(sqlite3_vfs *pAsyncVfs, int nByte, char *zBufOut){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- return pVfs->xRandomness(pVfs, nByte, zBufOut);
-}
-static int asyncSleep(sqlite3_vfs *pAsyncVfs, int nMicro){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- return pVfs->xSleep(pVfs, nMicro);
-}
-static int asyncCurrentTime(sqlite3_vfs *pAsyncVfs, double *pTimeOut){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
- return pVfs->xCurrentTime(pVfs, pTimeOut);
-}
-
-static sqlite3_vfs async_vfs = {
- 1, /* iVersion */
- sizeof(AsyncFile), /* szOsFile */
- 0, /* mxPathname */
- 0, /* pNext */
- SQLITEASYNC_VFSNAME, /* zName */
- 0, /* pAppData */
- asyncOpen, /* xOpen */
- asyncDelete, /* xDelete */
- asyncAccess, /* xAccess */
- asyncFullPathname, /* xFullPathname */
- asyncDlOpen, /* xDlOpen */
- asyncDlError, /* xDlError */
- asyncDlSym, /* xDlSym */
- asyncDlClose, /* xDlClose */
- asyncRandomness, /* xDlError */
- asyncSleep, /* xDlSym */
- asyncCurrentTime /* xDlClose */
-};
-
-/*
-** This procedure runs in a separate thread, reading messages off of the
-** write queue and processing them one by one.
-**
-** If async.writerHaltNow is true, then this procedure exits
-** after processing a single message.
-**
-** If async.writerHaltWhenIdle is true, then this procedure exits when
-** the write queue is empty.
-**
-** If both of the above variables are false, this procedure runs
-** indefinately, waiting for operations to be added to the write queue
-** and processing them in the order in which they arrive.
-**
-** An artifical delay of async.ioDelay milliseconds is inserted before
-** each write operation in order to simulate the effect of a slow disk.
-**
-** Only one instance of this procedure may be running at a time.
-*/
-static void asyncWriterThread(void){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)(async_vfs.pAppData);
- AsyncWrite *p = 0;
- int rc = SQLITE_OK;
- int holdingMutex = 0;
-
- async_mutex_enter(ASYNC_MUTEX_WRITER);
-
- while( async.eHalt!=SQLITEASYNC_HALT_NOW ){
- int doNotFree = 0;
- sqlite3_file *pBase = 0;
-
- if( !holdingMutex ){
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- }
- while( (p = async.pQueueFirst)==0 ){
- if( async.eHalt!=SQLITEASYNC_HALT_NEVER ){
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- break;
- }else{
- ASYNC_TRACE(("IDLE\n"));
- async_cond_wait(ASYNC_COND_QUEUE, ASYNC_MUTEX_QUEUE);
- ASYNC_TRACE(("WAKEUP\n"));
- }
- }
- if( p==0 ) break;
- holdingMutex = 1;
-
- /* Right now this thread is holding the mutex on the write-op queue.
- ** Variable 'p' points to the first entry in the write-op queue. In
- ** the general case, we hold on to the mutex for the entire body of
- ** the loop.
- **
- ** However in the cases enumerated below, we relinquish the mutex,
- ** perform the IO, and then re-request the mutex before removing 'p' from
- ** the head of the write-op queue. The idea is to increase concurrency with
- ** sqlite threads.
- **
- ** * An ASYNC_CLOSE operation.
- ** * An ASYNC_OPENEXCLUSIVE operation. For this one, we relinquish
- ** the mutex, call the underlying xOpenExclusive() function, then
- ** re-aquire the mutex before seting the AsyncFile.pBaseRead
- ** variable.
- ** * ASYNC_SYNC and ASYNC_WRITE operations, if
- ** SQLITE_ASYNC_TWO_FILEHANDLES was set at compile time and two
- ** file-handles are open for the particular file being "synced".
- */
- if( async.ioError!=SQLITE_OK && p->op!=ASYNC_CLOSE ){
- p->op = ASYNC_NOOP;
- }
- if( p->pFileData ){
- pBase = p->pFileData->pBaseWrite;
- if(
- p->op==ASYNC_CLOSE ||
- p->op==ASYNC_OPENEXCLUSIVE ||
- (pBase->pMethods && (p->op==ASYNC_SYNC || p->op==ASYNC_WRITE) )
- ){
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- holdingMutex = 0;
- }
- if( !pBase->pMethods ){
- pBase = p->pFileData->pBaseRead;
- }
- }
-
- switch( p->op ){
- case ASYNC_NOOP:
- break;
-
- case ASYNC_WRITE:
- assert( pBase );
- ASYNC_TRACE(("WRITE %s %d bytes at %d\n",
- p->pFileData->zName, p->nByte, p->iOffset));
- rc = pBase->pMethods->xWrite(pBase, (void *)(p->zBuf), p->nByte, p->iOffset);
- break;
-
- case ASYNC_SYNC:
- assert( pBase );
- ASYNC_TRACE(("SYNC %s\n", p->pFileData->zName));
- rc = pBase->pMethods->xSync(pBase, p->nByte);
- break;
-
- case ASYNC_TRUNCATE:
- assert( pBase );
- ASYNC_TRACE(("TRUNCATE %s to %d bytes\n",
- p->pFileData->zName, p->iOffset));
- rc = pBase->pMethods->xTruncate(pBase, p->iOffset);
- break;
-
- case ASYNC_CLOSE: {
- AsyncFileData *pData = p->pFileData;
- ASYNC_TRACE(("CLOSE %s\n", p->pFileData->zName));
- if( pData->pBaseWrite->pMethods ){
- pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite);
- }
- if( pData->pBaseRead->pMethods ){
- pData->pBaseRead->pMethods->xClose(pData->pBaseRead);
- }
-
- /* Unlink AsyncFileData.lock from the linked list of AsyncFileLock
- ** structures for this file. Obtain the async.lockMutex mutex
- ** before doing so.
- */
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- rc = unlinkAsyncFile(pData);
- async_mutex_leave(ASYNC_MUTEX_LOCK);
-
- if( !holdingMutex ){
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- holdingMutex = 1;
- }
- assert_mutex_is_held(ASYNC_MUTEX_QUEUE);
- async.pQueueFirst = p->pNext;
- sqlite3_free(pData);
- doNotFree = 1;
- break;
- }
-
- case ASYNC_UNLOCK: {
- AsyncWrite *pIter;
- AsyncFileData *pData = p->pFileData;
- int eLock = p->nByte;
-
- /* When a file is locked by SQLite using the async backend, it is
- ** locked within the 'real' file-system synchronously. When it is
- ** unlocked, an ASYNC_UNLOCK event is added to the write-queue to
- ** unlock the file asynchronously. The design of the async backend
- ** requires that the 'real' file-system file be locked from the
- ** time that SQLite first locks it (and probably reads from it)
- ** until all asynchronous write events that were scheduled before
- ** SQLite unlocked the file have been processed.
- **
- ** This is more complex if SQLite locks and unlocks the file multiple
- ** times in quick succession. For example, if SQLite does:
- **
- ** lock, write, unlock, lock, write, unlock
- **
- ** Each "lock" operation locks the file immediately. Each "write"
- ** and "unlock" operation adds an event to the event queue. If the
- ** second "lock" operation is performed before the first "unlock"
- ** operation has been processed asynchronously, then the first
- ** "unlock" cannot be safely processed as is, since this would mean
- ** the file was unlocked when the second "write" operation is
- ** processed. To work around this, when processing an ASYNC_UNLOCK
- ** operation, SQLite:
- **
- ** 1) Unlocks the file to the minimum of the argument passed to
- ** the xUnlock() call and the current lock from SQLite's point
- ** of view, and
- **
- ** 2) Only unlocks the file at all if this event is the last
- ** ASYNC_UNLOCK event on this file in the write-queue.
- */
- assert( holdingMutex==1 );
- assert( async.pQueueFirst==p );
- for(pIter=async.pQueueFirst->pNext; pIter; pIter=pIter->pNext){
- if( pIter->pFileData==pData && pIter->op==ASYNC_UNLOCK ) break;
- }
- if( !pIter ){
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- pData->lock.eAsyncLock = MIN(
- pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock)
- );
- assert(pData->lock.eAsyncLock>=pData->lock.eLock);
- rc = getFileLock(pData->pLock);
- async_mutex_leave(ASYNC_MUTEX_LOCK);
- }
- break;
- }
-
- case ASYNC_DELETE:
- ASYNC_TRACE(("DELETE %s\n", p->zBuf));
- rc = pVfs->xDelete(pVfs, p->zBuf, (int)p->iOffset);
- if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
- break;
-
- case ASYNC_OPENEXCLUSIVE: {
- int flags = (int)p->iOffset;
- AsyncFileData *pData = p->pFileData;
- ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset));
- assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0);
- rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseRead, flags, 0);
- assert( holdingMutex==0 );
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- holdingMutex = 1;
- break;
- }
-
- default: assert(!"Illegal value for AsyncWrite.op");
- }
-
- /* If we didn't hang on to the mutex during the IO op, obtain it now
- ** so that the AsyncWrite structure can be safely removed from the
- ** global write-op queue.
- */
- if( !holdingMutex ){
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- holdingMutex = 1;
- }
- /* ASYNC_TRACE(("UNLINK %p\n", p)); */
- if( p==async.pQueueLast ){
- async.pQueueLast = 0;
- }
- if( !doNotFree ){
- assert_mutex_is_held(ASYNC_MUTEX_QUEUE);
- async.pQueueFirst = p->pNext;
- sqlite3_free(p);
- }
- assert( holdingMutex );
-
- /* An IO error has occurred. We cannot report the error back to the
- ** connection that requested the I/O since the error happened
- ** asynchronously. The connection has already moved on. There
- ** really is nobody to report the error to.
- **
- ** The file for which the error occurred may have been a database or
- ** journal file. Regardless, none of the currently queued operations
- ** associated with the same database should now be performed. Nor should
- ** any subsequently requested IO on either a database or journal file
- ** handle for the same database be accepted until the main database
- ** file handle has been closed and reopened.
- **
- ** Furthermore, no further IO should be queued or performed on any file
- ** handle associated with a database that may have been part of a
- ** multi-file transaction that included the database associated with
- ** the IO error (i.e. a database ATTACHed to the same handle at some
- ** point in time).
- */
- if( rc!=SQLITE_OK ){
- async.ioError = rc;
- }
-
- if( async.ioError && !async.pQueueFirst ){
- async_mutex_enter(ASYNC_MUTEX_LOCK);
- if( 0==async.pLock ){
- async.ioError = SQLITE_OK;
- }
- async_mutex_leave(ASYNC_MUTEX_LOCK);
- }
-
- /* Drop the queue mutex before continuing to the next write operation
- ** in order to give other threads a chance to work with the write queue.
- */
- if( !async.pQueueFirst || !async.ioError ){
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- holdingMutex = 0;
- if( async.ioDelay>0 ){
- pVfs->xSleep(pVfs, async.ioDelay*1000);
- }else{
- async_sched_yield();
- }
- }
- }
-
- async_mutex_leave(ASYNC_MUTEX_WRITER);
- return;
-}
-
-/*
-** Install the asynchronous VFS.
-*/
-int sqlite3async_initialize(const char *zParent, int isDefault){
- int rc = SQLITE_OK;
- if( async_vfs.pAppData==0 ){
- sqlite3_vfs *pParent = sqlite3_vfs_find(zParent);
- if( !pParent || async_os_initialize() ){
- rc = SQLITE_ERROR;
- }else if( SQLITE_OK!=(rc = sqlite3_vfs_register(&async_vfs, isDefault)) ){
- async_os_shutdown();
- }else{
- async_vfs.pAppData = (void *)pParent;
- async_vfs.mxPathname = ((sqlite3_vfs *)async_vfs.pAppData)->mxPathname;
- }
- }
- return rc;
-}
-
-/*
-** Uninstall the asynchronous VFS.
-*/
-void sqlite3async_shutdown(void){
- if( async_vfs.pAppData ){
- async_os_shutdown();
- sqlite3_vfs_unregister((sqlite3_vfs *)&async_vfs);
- async_vfs.pAppData = 0;
- }
-}
-
-/*
-** Process events on the write-queue.
-*/
-void sqlite3async_run(void){
- asyncWriterThread();
-}
-
-/*
-** Control/configure the asynchronous IO system.
-*/
-int sqlite3async_control(int op, ...){
- int rc = SQLITE_OK;
- va_list ap;
- va_start(ap, op);
- switch( op ){
- case SQLITEASYNC_HALT: {
- int eWhen = va_arg(ap, int);
- if( eWhen!=SQLITEASYNC_HALT_NEVER
- && eWhen!=SQLITEASYNC_HALT_NOW
- && eWhen!=SQLITEASYNC_HALT_IDLE
- ){
- rc = SQLITE_MISUSE;
- break;
- }
- async.eHalt = eWhen;
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- async_cond_signal(ASYNC_COND_QUEUE);
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- break;
- }
-
- case SQLITEASYNC_DELAY: {
- int iDelay = va_arg(ap, int);
- if( iDelay<0 ){
- rc = SQLITE_MISUSE;
- break;
- }
- async.ioDelay = iDelay;
- break;
- }
-
- case SQLITEASYNC_LOCKFILES: {
- int bLock = va_arg(ap, int);
- async_mutex_enter(ASYNC_MUTEX_QUEUE);
- if( async.nFile || async.pQueueFirst ){
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- rc = SQLITE_MISUSE;
- break;
- }
- async.bLockFiles = bLock;
- async_mutex_leave(ASYNC_MUTEX_QUEUE);
- break;
- }
-
- case SQLITEASYNC_GET_HALT: {
- int *peWhen = va_arg(ap, int *);
- *peWhen = async.eHalt;
- break;
- }
- case SQLITEASYNC_GET_DELAY: {
- int *piDelay = va_arg(ap, int *);
- *piDelay = async.ioDelay;
- break;
- }
- case SQLITEASYNC_GET_LOCKFILES: {
- int *piDelay = va_arg(ap, int *);
- *piDelay = async.bLockFiles;
- break;
- }
-
- default:
- rc = SQLITE_ERROR;
- break;
- }
- va_end(ap);
- return rc;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO) */
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/sqlite3async.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/sqlite3async.h
deleted file mode 100644
index 5b20d7189a0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/async/sqlite3async.h
+++ /dev/null
@@ -1,223 +0,0 @@
-
-#ifndef __SQLITEASYNC_H_
-#define __SQLITEASYNC_H_ 1
-
-/*
-** Make sure we can call this stuff from C++.
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SQLITEASYNC_VFSNAME "sqlite3async"
-
-/*
-** THREAD SAFETY NOTES:
-**
-** Of the four API functions in this file, the following are not threadsafe:
-**
-** sqlite3async_initialize()
-** sqlite3async_shutdown()
-**
-** Care must be taken that neither of these functions is called while
-** another thread may be calling either any sqlite3async_XXX() function
-** or an sqlite3_XXX() API function related to a database handle that
-** is using the asynchronous IO VFS.
-**
-** These functions:
-**
-** sqlite3async_run()
-** sqlite3async_control()
-**
-** are threadsafe. It is quite safe to call either of these functions even
-** if another thread may also be calling one of them or an sqlite3_XXX()
-** function related to a database handle that uses the asynchronous IO VFS.
-*/
-
-/*
-** Initialize the asynchronous IO VFS and register it with SQLite using
-** sqlite3_vfs_register(). If the asynchronous VFS is already initialized
-** and registered, this function is a no-op. The asynchronous IO VFS
-** is registered as "sqlite3async".
-**
-** The asynchronous IO VFS does not make operating system IO requests
-** directly. Instead, it uses an existing VFS implementation for all
-** required file-system operations. If the first parameter to this function
-** is NULL, then the current default VFS is used for IO. If it is not
-** NULL, then it must be the name of an existing VFS. In other words, the
-** first argument to this function is passed to sqlite3_vfs_find() to
-** locate the VFS to use for all real IO operations. This VFS is known
-** as the "parent VFS".
-**
-** If the second parameter to this function is non-zero, then the
-** asynchronous IO VFS is registered as the default VFS for all SQLite
-** database connections within the process. Otherwise, the asynchronous IO
-** VFS is only used by connections opened using sqlite3_open_v2() that
-** specifically request VFS "sqlite3async".
-**
-** If a parent VFS cannot be located, then SQLITE_ERROR is returned.
-** In the unlikely event that operating system specific initialization
-** fails (win32 systems create the required critical section and event
-** objects within this function), then SQLITE_ERROR is also returned.
-** Finally, if the call to sqlite3_vfs_register() returns an error, then
-** the error code is returned to the user by this function. In all three
-** of these cases, intialization has failed and the asynchronous IO VFS
-** is not registered with SQLite.
-**
-** Otherwise, if no error occurs, SQLITE_OK is returned.
-*/
-int sqlite3async_initialize(const char *zParent, int isDefault);
-
-/*
-** This function unregisters the asynchronous IO VFS using
-** sqlite3_vfs_unregister().
-**
-** On win32 platforms, this function also releases the small number of
-** critical section and event objects created by sqlite3async_initialize().
-*/
-void sqlite3async_shutdown(void);
-
-/*
-** This function may only be called when the asynchronous IO VFS is
-** installed (after a call to sqlite3async_initialize()). It processes
-** zero or more queued write operations before returning. It is expected
-** (but not required) that this function will be called by a different
-** thread than those threads that use SQLite. The "background thread"
-** that performs IO.
-**
-** How many queued write operations are performed before returning
-** depends on the global setting configured by passing the SQLITEASYNC_HALT
-** verb to sqlite3async_control() (see below for details). By default
-** this function never returns - it processes all pending operations and
-** then blocks waiting for new ones.
-**
-** If multiple simultaneous calls are made to sqlite3async_run() from two
-** or more threads, then the calls are serialized internally.
-*/
-void sqlite3async_run(void);
-
-/*
-** This function may only be called when the asynchronous IO VFS is
-** installed (after a call to sqlite3async_initialize()). It is used
-** to query or configure various parameters that affect the operation
-** of the asynchronous IO VFS. At present there are three parameters
-** supported:
-**
-** * The "halt" parameter, which configures the circumstances under
-** which the sqlite3async_run() parameter is configured.
-**
-** * The "delay" parameter. Setting the delay parameter to a non-zero
-** value causes the sqlite3async_run() function to sleep for the
-** configured number of milliseconds between each queued write
-** operation.
-**
-** * The "lockfiles" parameter. This parameter determines whether or
-** not the asynchronous IO VFS locks the database files it operates
-** on. Disabling file locking can improve throughput.
-**
-** This function is always passed two arguments. When setting the value
-** of a parameter, the first argument must be one of SQLITEASYNC_HALT,
-** SQLITEASYNC_DELAY or SQLITEASYNC_LOCKFILES. The second argument must
-** be passed the new value for the parameter as type "int".
-**
-** When querying the current value of a paramter, the first argument must
-** be one of SQLITEASYNC_GET_HALT, GET_DELAY or GET_LOCKFILES. The second
-** argument to this function must be of type (int *). The current value
-** of the queried parameter is copied to the memory pointed to by the
-** second argument. For example:
-**
-** int eCurrentHalt;
-** int eNewHalt = SQLITEASYNC_HALT_IDLE;
-**
-** sqlite3async_control(SQLITEASYNC_HALT, eNewHalt);
-** sqlite3async_control(SQLITEASYNC_GET_HALT, &eCurrentHalt);
-** assert( eNewHalt==eCurrentHalt );
-**
-** See below for more detail on each configuration parameter.
-**
-** SQLITEASYNC_HALT:
-**
-** This is used to set the value of the "halt" parameter. The second
-** argument must be one of the SQLITEASYNC_HALT_XXX symbols defined
-** below (either NEVER, IDLE and NOW).
-**
-** If the parameter is set to NEVER, then calls to sqlite3async_run()
-** never return. This is the default setting. If the parameter is set
-** to IDLE, then calls to sqlite3async_run() return as soon as the
-** queue of pending write operations is empty. If the parameter is set
-** to NOW, then calls to sqlite3async_run() return as quickly as
-** possible, without processing any pending write requests.
-**
-** If an attempt is made to set this parameter to an integer value other
-** than SQLITEASYNC_HALT_NEVER, IDLE or NOW, then sqlite3async_control()
-** returns SQLITE_MISUSE and the current value of the parameter is not
-** modified.
-**
-** Modifying the "halt" parameter affects calls to sqlite3async_run()
-** made by other threads that are currently in progress.
-**
-** SQLITEASYNC_DELAY:
-**
-** This is used to set the value of the "delay" parameter. If set to
-** a non-zero value, then after completing a pending write request, the
-** sqlite3async_run() function sleeps for the configured number of
-** milliseconds.
-**
-** If an attempt is made to set this parameter to a negative value,
-** sqlite3async_control() returns SQLITE_MISUSE and the current value
-** of the parameter is not modified.
-**
-** Modifying the "delay" parameter affects calls to sqlite3async_run()
-** made by other threads that are currently in progress.
-**
-** SQLITEASYNC_LOCKFILES:
-**
-** This is used to set the value of the "lockfiles" parameter. This
-** parameter must be set to either 0 or 1. If set to 1, then the
-** asynchronous IO VFS uses the xLock() and xUnlock() methods of the
-** parent VFS to lock database files being read and/or written. If
-** the parameter is set to 0, then these locks are omitted.
-**
-** This parameter may only be set when there are no open database
-** connections using the VFS and the queue of pending write requests
-** is empty. Attempting to set it when this is not true, or to set it
-** to a value other than 0 or 1 causes sqlite3async_control() to return
-** SQLITE_MISUSE and the value of the parameter to remain unchanged.
-**
-** If this parameter is set to zero, then it is only safe to access the
-** database via the asynchronous IO VFS from within a single process. If
-** while writing to the database via the asynchronous IO VFS the database
-** is also read or written from within another process, or via another
-** connection that does not use the asynchronous IO VFS within the same
-** process, the results are undefined (and may include crashes or database
-** corruption).
-**
-** Alternatively, if this parameter is set to 1, then it is safe to access
-** the database from multiple connections within multiple processes using
-** either the asynchronous IO VFS or the parent VFS directly.
-*/
-int sqlite3async_control(int op, ...);
-
-/*
-** Values that can be used as the first argument to sqlite3async_control().
-*/
-#define SQLITEASYNC_HALT 1
-#define SQLITEASYNC_GET_HALT 2
-#define SQLITEASYNC_DELAY 3
-#define SQLITEASYNC_GET_DELAY 4
-#define SQLITEASYNC_LOCKFILES 5
-#define SQLITEASYNC_GET_LOCKFILES 6
-
-/*
-** If the first argument to sqlite3async_control() is SQLITEASYNC_HALT,
-** the second argument should be one of the following.
-*/
-#define SQLITEASYNC_HALT_NEVER 0 /* Never halt (default value) */
-#define SQLITEASYNC_HALT_NOW 1 /* Halt as soon as possible */
-#define SQLITEASYNC_HALT_IDLE 2 /* Halt when write-queue is empty */
-
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-#endif /* ifndef __SQLITEASYNC_H_ */
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/README.md b/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/README.md
deleted file mode 100644
index 28886fd1f2d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/README.md
+++ /dev/null
@@ -1,83 +0,0 @@
-## SQLite Expert Extension
-
-This folder contains code for a simple system to propose useful indexes
-given a database and a set of SQL queries. It works as follows:
-
- 1. The user database schema is copied to a temporary database.
-
- 1. All SQL queries are prepared against the temporary database.
- Information regarding the WHERE and ORDER BY clauses, and other query
- features that affect index selection are recorded.
-
- 1. The information gathered in step 2 is used to create candidate
- indexes - indexes that the planner might have made use of in the previous
- step, had they been available.
-
- 1. A subset of the data in the user database is used to generate statistics
- for all existing indexes and the candidate indexes generated in step 3
- above.
-
- 1. The SQL queries are prepared a second time. If the planner uses any
- of the indexes created in step 3, they are recommended to the user.
-
-# C API
-
-The SQLite expert C API is defined in sqlite3expert.h. Most uses will proceed
-as follows:
-
- 1. An sqlite3expert object is created by calling **sqlite3\_expert\_new()**.
- A database handle opened by the user is passed as an argument.
-
- 1. The sqlite3expert object is configured with one or more SQL statements
- by making one or more calls to **sqlite3\_expert\_sql()**. Each call may
- specify a single SQL statement, or multiple statements separated by
- semi-colons.
-
- 1. Optionally, the **sqlite3\_expert\_config()** API may be used to
- configure the size of the data subset used to generate index statistics.
- Using a smaller subset of the data can speed up the analysis.
-
- 1. **sqlite3\_expert\_analyze()** is called to run the analysis.
-
- 1. One or more calls are made to **sqlite3\_expert\_report()** to extract
- components of the results of the analysis.
-
- 1. **sqlite3\_expert\_destroy()** is called to free all resources.
-
-Refer to comments in sqlite3expert.h for further details.
-
-# sqlite3_expert application
-
-The file "expert.c" contains the code for a command line application that
-uses the API described above. It can be compiled with (for example):
-
-<pre>
- gcc -O2 sqlite3.c expert.c sqlite3expert.c -o sqlite3_expert
-</pre>
-
-Assuming the database is named "test.db", it can then be run to analyze a
-single query:
-
-<pre>
- ./sqlite3_expert -sql &lt;sql-query&gt; test.db
-</pre>
-
-Or an entire text file worth of queries with:
-
-<pre>
- ./sqlite3_expert -file &lt;text-file&gt; test.db
-</pre>
-
-By default, sqlite3\_expert generates index statistics using all the data in
-the user database. For a large database, this may be prohibitively time
-consuming. The "-sample" option may be used to configure sqlite3\_expert to
-generate statistics based on an integer percentage of the user database as
-follows:
-
-<pre>
- # Generate statistics based on 25% of the user database rows:
- ./sqlite3_expert -sample 25 -sql &lt;sql-query&gt; test.db
-
- # Do not generate any statistics at all:
- ./sqlite3_expert -sample 0 -sql &lt;sql-query&gt; test.db
-</pre>
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/expert.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/expert.c
deleted file mode 100644
index 051480f8960..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/expert.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-** 2017 April 07
-**
-** 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.
-**
-*************************************************************************
-*/
-
-
-#include <sqlite3.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sqlite3expert.h"
-
-
-static void option_requires_argument(const char *zOpt){
- fprintf(stderr, "Option requires an argument: %s\n", zOpt);
- exit(-3);
-}
-
-static int option_integer_arg(const char *zVal){
- return atoi(zVal);
-}
-
-static void usage(char **argv){
- fprintf(stderr, "\n");
- fprintf(stderr, "Usage %s ?OPTIONS? DATABASE\n", argv[0]);
- fprintf(stderr, "\n");
- fprintf(stderr, "Options are:\n");
- fprintf(stderr, " -sql SQL (analyze SQL statements passed as argument)\n");
- fprintf(stderr, " -file FILE (read SQL statements from file FILE)\n");
- fprintf(stderr, " -verbose LEVEL (integer verbosity level. default 1)\n");
- fprintf(stderr, " -sample PERCENT (percent of db to sample. default 100)\n");
- exit(-1);
-}
-
-static int readSqlFromFile(sqlite3expert *p, const char *zFile, char **pzErr){
- FILE *in = fopen(zFile, "rb");
- long nIn;
- size_t nRead;
- char *pBuf;
- int rc;
- if( in==0 ){
- *pzErr = sqlite3_mprintf("failed to open file %s\n", zFile);
- return SQLITE_ERROR;
- }
- fseek(in, 0, SEEK_END);
- nIn = ftell(in);
- rewind(in);
- pBuf = sqlite3_malloc64( nIn+1 );
- nRead = fread(pBuf, nIn, 1, in);
- fclose(in);
- if( nRead!=1 ){
- sqlite3_free(pBuf);
- *pzErr = sqlite3_mprintf("failed to read file %s\n", zFile);
- return SQLITE_ERROR;
- }
- pBuf[nIn] = 0;
- rc = sqlite3_expert_sql(p, pBuf, pzErr);
- sqlite3_free(pBuf);
- return rc;
-}
-
-int main(int argc, char **argv){
- const char *zDb;
- int rc = 0;
- char *zErr = 0;
- int i;
- int iVerbose = 1; /* -verbose option */
-
- sqlite3 *db = 0;
- sqlite3expert *p = 0;
-
- if( argc<2 ) usage(argv);
- zDb = argv[argc-1];
- if( zDb[0]=='-' ) usage(argv);
- rc = sqlite3_open(zDb, &db);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "Cannot open db file: %s - %s\n", zDb, sqlite3_errmsg(db));
- exit(-2);
- }
-
- p = sqlite3_expert_new(db, &zErr);
- if( p==0 ){
- fprintf(stderr, "Cannot run analysis: %s\n", zErr);
- rc = 1;
- }else{
- for(i=1; i<(argc-1); i++){
- char *zArg = argv[i];
- int nArg;
- if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++;
- nArg = (int)strlen(zArg);
- if( nArg>=2 && 0==sqlite3_strnicmp(zArg, "-file", nArg) ){
- if( ++i==(argc-1) ) option_requires_argument("-file");
- rc = readSqlFromFile(p, argv[i], &zErr);
- }
-
- else if( nArg>=3 && 0==sqlite3_strnicmp(zArg, "-sql", nArg) ){
- if( ++i==(argc-1) ) option_requires_argument("-sql");
- rc = sqlite3_expert_sql(p, argv[i], &zErr);
- }
-
- else if( nArg>=3 && 0==sqlite3_strnicmp(zArg, "-sample", nArg) ){
- int iSample;
- if( ++i==(argc-1) ) option_requires_argument("-sample");
- iSample = option_integer_arg(argv[i]);
- sqlite3_expert_config(p, EXPERT_CONFIG_SAMPLE, iSample);
- }
-
- else if( nArg>=2 && 0==sqlite3_strnicmp(zArg, "-verbose", nArg) ){
- if( ++i==(argc-1) ) option_requires_argument("-verbose");
- iVerbose = option_integer_arg(argv[i]);
- }
-
- else{
- usage(argv);
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_expert_analyze(p, &zErr);
- }
-
- if( rc==SQLITE_OK ){
- int nQuery = sqlite3_expert_count(p);
- if( iVerbose>0 ){
- const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
- fprintf(stdout, "-- Candidates -------------------------------\n");
- fprintf(stdout, "%s\n", zCand);
- }
- for(i=0; i<nQuery; i++){
- const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
- const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
- const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
- if( zIdx==0 ) zIdx = "(no new indexes)\n";
- if( iVerbose>0 ){
- fprintf(stdout, "-- Query %d ----------------------------------\n",i+1);
- fprintf(stdout, "%s\n\n", zSql);
- }
- fprintf(stdout, "%s\n%s\n", zIdx, zEQP);
- }
- }else{
- fprintf(stderr, "Error: %s\n", zErr ? zErr : "?");
- }
-
- sqlite3_expert_destroy(p);
- sqlite3_free(zErr);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/expert1.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/expert1.test
deleted file mode 100644
index d1564c513f7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/expert1.test
+++ /dev/null
@@ -1,382 +0,0 @@
-# 2009 Nov 11
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the CLI shell tool. Specifically,
-# the ".recommend" command.
-#
-#
-
-# Test plan:
-#
-#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set testprefix expert1
-
-if {[info commands sqlite3_expert_new]==""} {
- finish_test
- return
-}
-
-set CLI [test_binary_name sqlite3]
-set CMD [test_binary_name sqlite3_expert]
-
-proc squish {txt} {
- regsub -all {[[:space:]]+} $txt { }
-}
-
-proc do_setup_rec_test {tn setup sql res} {
- reset_db
- db eval $setup
- uplevel [list do_rec_test $tn $sql $res]
-}
-
-foreach {tn setup} {
- 1 {
- if {![file executable $CMD]} { continue }
-
- proc do_rec_test {tn sql res} {
- set res [squish [string trim $res]]
- set tst [subst -nocommands {
- squish [string trim [exec $::CMD -verbose 0 -sql {$sql;} test.db]]
- }]
- uplevel [list do_test $tn $tst $res]
- }
- }
- 2 {
- if {[info commands sqlite3_expert_new]==""} { continue }
-
- proc do_rec_test {tn sql res} {
- set expert [sqlite3_expert_new db]
- $expert sql $sql
- $expert analyze
-
- set result [list]
- for {set i 0} {$i < [$expert count]} {incr i} {
- set idx [string trim [$expert report $i indexes]]
- if {$idx==""} {set idx "(no new indexes)"}
- lappend result $idx
- lappend result [string trim [$expert report $i plan]]
- }
-
- $expert destroy
-
- set tst [subst -nocommands {set {} [squish [join {$result}]]}]
- uplevel [list do_test $tn $tst [string trim [squish $res]]]
- }
- }
- 3 {
- if {![file executable $CLI]} { continue }
-
- proc do_rec_test {tn sql res} {
- set res [squish [string trim $res]]
- set tst [subst -nocommands {
- squish [string trim [exec $::CLI test.db ".expert" {$sql;}]]
- }]
- uplevel [list do_test $tn $tst $res]
- }
- }
-} {
-
- eval $setup
-
-
-do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
- SELECT * FROM t1
-} {
- (no new indexes)
- SCAN TABLE t1
-}
-
-do_setup_rec_test $tn.2 {
- CREATE TABLE t1(a, b, c);
-} {
- SELECT * FROM t1 WHERE b>?;
-} {
- CREATE INDEX t1_idx_00000062 ON t1(b);
- SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
-}
-
-do_setup_rec_test $tn.3 {
- CREATE TABLE t1(a, b, c);
-} {
- SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
-} {
- CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE);
- SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
-}
-
-do_setup_rec_test $tn.4 {
- CREATE TABLE t1(a, b, c);
-} {
- SELECT a FROM t1 ORDER BY b;
-} {
- CREATE INDEX t1_idx_00000062 ON t1(b);
- SCAN TABLE t1 USING INDEX t1_idx_00000062
-}
-
-do_setup_rec_test $tn.5 {
- CREATE TABLE t1(a, b, c);
-} {
- SELECT a FROM t1 WHERE a=? ORDER BY b;
-} {
- CREATE INDEX t1_idx_000123a7 ON t1(a, b);
- SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
-}
-
-do_setup_rec_test $tn.6 {
- CREATE TABLE t1(a, b, c);
-} {
- SELECT min(a) FROM t1
-} {
- CREATE INDEX t1_idx_00000061 ON t1(a);
- SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
-}
-
-do_setup_rec_test $tn.7 {
- CREATE TABLE t1(a, b, c);
-} {
- SELECT * FROM t1 ORDER BY a, b, c;
-} {
- CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
- SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
-}
-
-#do_setup_rec_test $tn.1.8 {
-# CREATE TABLE t1(a, b, c);
-#} {
-# SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
-#} {
-# CREATE INDEX t1_idx_5be6e222 ON t1(a, b COLLATE NOCASE DESC, c);
-# 0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5be6e222
-#}
-
-do_setup_rec_test $tn.8.1 {
- CREATE TABLE t1(a COLLATE NOCase, b, c);
-} {
- SELECT * FROM t1 WHERE a=?
-} {
- CREATE INDEX t1_idx_00000061 ON t1(a);
- SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
-}
-do_setup_rec_test $tn.8.2 {
- CREATE TABLE t1(a, b COLLATE nocase, c);
-} {
- SELECT * FROM t1 ORDER BY a ASC, b DESC, c ASC;
-} {
- CREATE INDEX t1_idx_5cb97285 ON t1(a, b DESC, c);
- SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
-}
-
-
-# Tables with names that require quotes.
-#
-do_setup_rec_test $tn.9.1 {
- CREATE TABLE "t t"(a, b, c);
-} {
- SELECT * FROM "t t" WHERE a=?
-} {
- CREATE INDEX 't t_idx_00000061' ON 't t'(a);
- SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?)
-}
-
-do_setup_rec_test $tn.9.2 {
- CREATE TABLE "t t"(a, b, c);
-} {
- SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
-} {
- CREATE INDEX 't t_idx_00000062' ON 't t'(b);
- SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
-}
-
-# Columns with names that require quotes.
-#
-do_setup_rec_test $tn.10.1 {
- CREATE TABLE t3(a, "b b", c);
-} {
- SELECT * FROM t3 WHERE "b b" = ?
-} {
- CREATE INDEX t3_idx_00050c52 ON t3('b b');
- SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
-}
-
-do_setup_rec_test $tn.10.2 {
- CREATE TABLE t3(a, "b b", c);
-} {
- SELECT * FROM t3 ORDER BY "b b"
-} {
- CREATE INDEX t3_idx_00050c52 ON t3('b b');
- SCAN TABLE t3 USING INDEX t3_idx_00050c52
-}
-
-# Transitive constraints
-#
-do_setup_rec_test $tn.11.1 {
- CREATE TABLE t5(a, b);
- CREATE TABLE t6(c, d);
-} {
- SELECT * FROM t5, t6 WHERE a=? AND b=c AND c=?
-} {
- CREATE INDEX t5_idx_000123a7 ON t5(a, b);
- CREATE INDEX t6_idx_00000063 ON t6(c);
- SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?)
- SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
-}
-
-# OR terms.
-#
-do_setup_rec_test $tn.12.1 {
- CREATE TABLE t7(a, b);
-} {
- SELECT * FROM t7 WHERE a=? OR b=?
-} {
- CREATE INDEX t7_idx_00000062 ON t7(b);
- CREATE INDEX t7_idx_00000061 ON t7(a);
- MULTI-INDEX OR
- SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
- SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
-}
-
-# rowid terms.
-#
-do_setup_rec_test $tn.13.1 {
- CREATE TABLE t8(a, b);
-} {
- SELECT * FROM t8 WHERE rowid=?
-} {
- (no new indexes)
- SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
-}
-do_setup_rec_test $tn.13.2 {
- CREATE TABLE t8(a, b);
-} {
- SELECT * FROM t8 ORDER BY rowid
-} {
- (no new indexes)
- SCAN TABLE t8
-}
-do_setup_rec_test $tn.13.3 {
- CREATE TABLE t8(a, b);
-} {
- SELECT * FROM t8 WHERE a=? ORDER BY rowid
-} {
- CREATE INDEX t8_idx_00000061 ON t8(a);
- SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
-}
-
-# Triggers
-#
-do_setup_rec_test $tn.14 {
- CREATE TABLE t9(a, b, c);
- CREATE TABLE t10(a, b, c);
- CREATE TRIGGER t9t AFTER INSERT ON t9 BEGIN
- UPDATE t10 SET a=new.a WHERE b = new.b;
- END;
-} {
- INSERT INTO t9 VALUES(?, ?, ?);
-} {
- CREATE INDEX t10_idx_00000062 ON t10(b);
- SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
-}
-
-do_setup_rec_test $tn.15 {
- CREATE TABLE t1(a, b);
- CREATE TABLE t2(c, d);
-
- WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
- INSERT INTO t1 SELECT (i-1)/50, (i-1)/20 FROM s;
-
- WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
- INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
-} {
- SELECT * FROM t2, t1 WHERE b=? AND d=? AND t2.rowid=t1.rowid
-} {
- CREATE INDEX t2_idx_00000064 ON t2(d);
- SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?)
- SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
-}
-
-do_setup_rec_test $tn.16 {
- CREATE TABLE t1(a, b);
-} {
- SELECT * FROM t1 WHERE b IS NOT NULL;
-} {
- (no new indexes)
- SCAN TABLE t1
-}
-
-}
-
-proc do_candidates_test {tn sql res} {
- set res [squish [string trim $res]]
-
- set expert [sqlite3_expert_new db]
- $expert sql $sql
- $expert analyze
-
- set candidates [squish [string trim [$expert report 0 candidates]]]
- $expert destroy
-
- uplevel [list do_test $tn [list set {} $candidates] $res]
-}
-
-
-reset_db
-do_execsql_test 3.0 {
- CREATE TABLE t1(a, b);
- CREATE TABLE t2(c, d);
-
- WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
- INSERT INTO t1 SELECT (i-1)/50, (i-1)/20 FROM s;
-
- WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
- INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
-}
-do_candidates_test 3.1 {
- SELECT * FROM t1,t2 WHERE (b=? OR a=?) AND (c=? OR d=?)
-} {
- CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20
- CREATE INDEX t1_idx_00000061 ON t1(a); -- stat1: 100 50
- CREATE INDEX t2_idx_00000063 ON t2(c); -- stat1: 100 20
- CREATE INDEX t2_idx_00000064 ON t2(d); -- stat1: 100 5
-}
-
-do_candidates_test 3.2 {
- SELECT * FROM t1,t2 WHERE a=? AND b=? AND c=? AND d=?
-} {
- CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 17
- CREATE INDEX t2_idx_0001295b ON t2(c, d); -- stat1: 100 20 5
-}
-
-do_execsql_test 3.2 {
- CREATE INDEX t1_idx_00000061 ON t1(a); -- stat1: 100 50
- CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20
- CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 16
-
- CREATE INDEX t2_idx_00000063 ON t2(c); -- stat1: 100 20
- CREATE INDEX t2_idx_00000064 ON t2(d); -- stat1: 100 5
- CREATE INDEX t2_idx_0001295b ON t2(c, d); -- stat1: 100 20 5
-
- ANALYZE;
- SELECT * FROM sqlite_stat1 ORDER BY 1, 2;
-} {
- t1 t1_idx_00000061 {100 50}
- t1 t1_idx_00000062 {100 20}
- t1 t1_idx_000123a7 {100 50 17}
- t2 t2_idx_00000063 {100 20}
- t2 t2_idx_00000064 {100 5}
- t2 t2_idx_0001295b {100 20 5}
-}
-
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/sqlite3expert.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/sqlite3expert.c
deleted file mode 100644
index 695aaece8c9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/sqlite3expert.c
+++ /dev/null
@@ -1,1952 +0,0 @@
-/*
-** 2017 April 09
-**
-** 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.
-**
-*************************************************************************
-*/
-#include "sqlite3expert.h"
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-typedef sqlite3_int64 i64;
-typedef sqlite3_uint64 u64;
-
-typedef struct IdxColumn IdxColumn;
-typedef struct IdxConstraint IdxConstraint;
-typedef struct IdxScan IdxScan;
-typedef struct IdxStatement IdxStatement;
-typedef struct IdxTable IdxTable;
-typedef struct IdxWrite IdxWrite;
-
-#define STRLEN (int)strlen
-
-/*
-** A temp table name that we assume no user database will actually use.
-** If this assumption proves incorrect triggers on the table with the
-** conflicting name will be ignored.
-*/
-#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
-
-/*
-** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
-** any other type of single-ended range constraint on a column).
-**
-** pLink:
-** Used to temporarily link IdxConstraint objects into lists while
-** creating candidate indexes.
-*/
-struct IdxConstraint {
- char *zColl; /* Collation sequence */
- int bRange; /* True for range, false for eq */
- int iCol; /* Constrained table column */
- int bFlag; /* Used by idxFindCompatible() */
- int bDesc; /* True if ORDER BY <expr> DESC */
- IdxConstraint *pNext; /* Next constraint in pEq or pRange list */
- IdxConstraint *pLink; /* See above */
-};
-
-/*
-** A single scan of a single table.
-*/
-struct IdxScan {
- IdxTable *pTab; /* Associated table object */
- int iDb; /* Database containing table zTable */
- i64 covering; /* Mask of columns required for cov. index */
- IdxConstraint *pOrder; /* ORDER BY columns */
- IdxConstraint *pEq; /* List of == constraints */
- IdxConstraint *pRange; /* List of < constraints */
- IdxScan *pNextScan; /* Next IdxScan object for same analysis */
-};
-
-/*
-** Information regarding a single database table. Extracted from
-** "PRAGMA table_info" by function idxGetTableInfo().
-*/
-struct IdxColumn {
- char *zName;
- char *zColl;
- int iPk;
-};
-struct IdxTable {
- int nCol;
- char *zName; /* Table name */
- IdxColumn *aCol;
- IdxTable *pNext; /* Next table in linked list of all tables */
-};
-
-/*
-** An object of the following type is created for each unique table/write-op
-** seen. The objects are stored in a singly-linked list beginning at
-** sqlite3expert.pWrite.
-*/
-struct IdxWrite {
- IdxTable *pTab;
- int eOp; /* SQLITE_UPDATE, DELETE or INSERT */
- IdxWrite *pNext;
-};
-
-/*
-** Each statement being analyzed is represented by an instance of this
-** structure.
-*/
-struct IdxStatement {
- int iId; /* Statement number */
- char *zSql; /* SQL statement */
- char *zIdx; /* Indexes */
- char *zEQP; /* Plan */
- IdxStatement *pNext;
-};
-
-
-/*
-** A hash table for storing strings. With space for a payload string
-** with each entry. Methods are:
-**
-** idxHashInit()
-** idxHashClear()
-** idxHashAdd()
-** idxHashSearch()
-*/
-#define IDX_HASH_SIZE 1023
-typedef struct IdxHashEntry IdxHashEntry;
-typedef struct IdxHash IdxHash;
-struct IdxHashEntry {
- char *zKey; /* nul-terminated key */
- char *zVal; /* nul-terminated value string */
- char *zVal2; /* nul-terminated value string 2 */
- IdxHashEntry *pHashNext; /* Next entry in same hash bucket */
- IdxHashEntry *pNext; /* Next entry in hash */
-};
-struct IdxHash {
- IdxHashEntry *pFirst;
- IdxHashEntry *aHash[IDX_HASH_SIZE];
-};
-
-/*
-** sqlite3expert object.
-*/
-struct sqlite3expert {
- int iSample; /* Percentage of tables to sample for stat1 */
- sqlite3 *db; /* User database */
- sqlite3 *dbm; /* In-memory db for this analysis */
- sqlite3 *dbv; /* Vtab schema for this analysis */
- IdxTable *pTable; /* List of all IdxTable objects */
- IdxScan *pScan; /* List of scan objects */
- IdxWrite *pWrite; /* List of write objects */
- IdxStatement *pStatement; /* List of IdxStatement objects */
- int bRun; /* True once analysis has run */
- char **pzErrmsg;
- int rc; /* Error code from whereinfo hook */
- IdxHash hIdx; /* Hash containing all candidate indexes */
- char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */
-};
-
-
-/*
-** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
-** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
-*/
-static void *idxMalloc(int *pRc, int nByte){
- void *pRet;
- assert( *pRc==SQLITE_OK );
- assert( nByte>0 );
- pRet = sqlite3_malloc(nByte);
- if( pRet ){
- memset(pRet, 0, nByte);
- }else{
- *pRc = SQLITE_NOMEM;
- }
- return pRet;
-}
-
-/*
-** Initialize an IdxHash hash table.
-*/
-static void idxHashInit(IdxHash *pHash){
- memset(pHash, 0, sizeof(IdxHash));
-}
-
-/*
-** Reset an IdxHash hash table.
-*/
-static void idxHashClear(IdxHash *pHash){
- int i;
- for(i=0; i<IDX_HASH_SIZE; i++){
- IdxHashEntry *pEntry;
- IdxHashEntry *pNext;
- for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){
- pNext = pEntry->pHashNext;
- sqlite3_free(pEntry->zVal2);
- sqlite3_free(pEntry);
- }
- }
- memset(pHash, 0, sizeof(IdxHash));
-}
-
-/*
-** Return the index of the hash bucket that the string specified by the
-** arguments to this function belongs.
-*/
-static int idxHashString(const char *z, int n){
- unsigned int ret = 0;
- int i;
- for(i=0; i<n; i++){
- ret += (ret<<3) + (unsigned char)(z[i]);
- }
- return (int)(ret % IDX_HASH_SIZE);
-}
-
-/*
-** If zKey is already present in the hash table, return non-zero and do
-** nothing. Otherwise, add an entry with key zKey and payload string zVal to
-** the hash table passed as the second argument.
-*/
-static int idxHashAdd(
- int *pRc,
- IdxHash *pHash,
- const char *zKey,
- const char *zVal
-){
- int nKey = STRLEN(zKey);
- int iHash = idxHashString(zKey, nKey);
- int nVal = (zVal ? STRLEN(zVal) : 0);
- IdxHashEntry *pEntry;
- assert( iHash>=0 );
- for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
- if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
- return 1;
- }
- }
- pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
- if( pEntry ){
- pEntry->zKey = (char*)&pEntry[1];
- memcpy(pEntry->zKey, zKey, nKey);
- if( zVal ){
- pEntry->zVal = &pEntry->zKey[nKey+1];
- memcpy(pEntry->zVal, zVal, nVal);
- }
- pEntry->pHashNext = pHash->aHash[iHash];
- pHash->aHash[iHash] = pEntry;
-
- pEntry->pNext = pHash->pFirst;
- pHash->pFirst = pEntry;
- }
- return 0;
-}
-
-/*
-** If zKey/nKey is present in the hash table, return a pointer to the
-** hash-entry object.
-*/
-static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
- int iHash;
- IdxHashEntry *pEntry;
- if( nKey<0 ) nKey = STRLEN(zKey);
- iHash = idxHashString(zKey, nKey);
- assert( iHash>=0 );
- for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
- if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
- return pEntry;
- }
- }
- return 0;
-}
-
-/*
-** If the hash table contains an entry with a key equal to the string
-** passed as the final two arguments to this function, return a pointer
-** to the payload string. Otherwise, if zKey/nKey is not present in the
-** hash table, return NULL.
-*/
-static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){
- IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey);
- if( pEntry ) return pEntry->zVal;
- return 0;
-}
-
-/*
-** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl
-** variable to point to a copy of nul-terminated string zColl.
-*/
-static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
- IdxConstraint *pNew;
- int nColl = STRLEN(zColl);
-
- assert( *pRc==SQLITE_OK );
- pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
- if( pNew ){
- pNew->zColl = (char*)&pNew[1];
- memcpy(pNew->zColl, zColl, nColl+1);
- }
- return pNew;
-}
-
-/*
-** An error associated with database handle db has just occurred. Pass
-** the error message to callback function xOut.
-*/
-static void idxDatabaseError(
- sqlite3 *db, /* Database handle */
- char **pzErrmsg /* Write error here */
-){
- *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
-}
-
-/*
-** Prepare an SQL statement.
-*/
-static int idxPrepareStmt(
- sqlite3 *db, /* Database handle to compile against */
- sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */
- char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */
- const char *zSql /* SQL statement to compile */
-){
- int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
- if( rc!=SQLITE_OK ){
- *ppStmt = 0;
- idxDatabaseError(db, pzErrmsg);
- }
- return rc;
-}
-
-/*
-** Prepare an SQL statement using the results of a printf() formatting.
-*/
-static int idxPrintfPrepareStmt(
- sqlite3 *db, /* Database handle to compile against */
- sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */
- char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */
- const char *zFmt, /* printf() format of SQL statement */
- ... /* Trailing printf() arguments */
-){
- va_list ap;
- int rc;
- char *zSql;
- va_start(ap, zFmt);
- zSql = sqlite3_vmprintf(zFmt, ap);
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql);
- sqlite3_free(zSql);
- }
- va_end(ap);
- return rc;
-}
-
-
-/*************************************************************************
-** Beginning of virtual table implementation.
-*/
-typedef struct ExpertVtab ExpertVtab;
-struct ExpertVtab {
- sqlite3_vtab base;
- IdxTable *pTab;
- sqlite3expert *pExpert;
-};
-
-typedef struct ExpertCsr ExpertCsr;
-struct ExpertCsr {
- sqlite3_vtab_cursor base;
- sqlite3_stmt *pData;
-};
-
-static char *expertDequote(const char *zIn){
- int n = STRLEN(zIn);
- char *zRet = sqlite3_malloc(n);
-
- assert( zIn[0]=='\'' );
- assert( zIn[n-1]=='\'' );
-
- if( zRet ){
- int iOut = 0;
- int iIn = 0;
- for(iIn=1; iIn<(n-1); iIn++){
- if( zIn[iIn]=='\'' ){
- assert( zIn[iIn+1]=='\'' );
- iIn++;
- }
- zRet[iOut++] = zIn[iIn];
- }
- zRet[iOut] = '\0';
- }
-
- return zRet;
-}
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the r-tree virtual table.
-**
-** argv[0] -> module name
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> column names...
-*/
-static int expertConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3expert *pExpert = (sqlite3expert*)pAux;
- ExpertVtab *p = 0;
- int rc;
-
- if( argc!=4 ){
- *pzErr = sqlite3_mprintf("internal error!");
- rc = SQLITE_ERROR;
- }else{
- char *zCreateTable = expertDequote(argv[3]);
- if( zCreateTable ){
- rc = sqlite3_declare_vtab(db, zCreateTable);
- if( rc==SQLITE_OK ){
- p = idxMalloc(&rc, sizeof(ExpertVtab));
- }
- if( rc==SQLITE_OK ){
- p->pExpert = pExpert;
- p->pTab = pExpert->pTable;
- assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 );
- }
- sqlite3_free(zCreateTable);
- }else{
- rc = SQLITE_NOMEM;
- }
- }
-
- *ppVtab = (sqlite3_vtab*)p;
- return rc;
-}
-
-static int expertDisconnect(sqlite3_vtab *pVtab){
- ExpertVtab *p = (ExpertVtab*)pVtab;
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
- ExpertVtab *p = (ExpertVtab*)pVtab;
- int rc = SQLITE_OK;
- int n = 0;
- IdxScan *pScan;
- const int opmask =
- SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT |
- SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE |
- SQLITE_INDEX_CONSTRAINT_LE;
-
- pScan = idxMalloc(&rc, sizeof(IdxScan));
- if( pScan ){
- int i;
-
- /* Link the new scan object into the list */
- pScan->pTab = p->pTab;
- pScan->pNextScan = p->pExpert->pScan;
- p->pExpert->pScan = pScan;
-
- /* Add the constraints to the IdxScan object */
- for(i=0; i<pIdxInfo->nConstraint; i++){
- struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
- if( pCons->usable
- && pCons->iColumn>=0
- && p->pTab->aCol[pCons->iColumn].iPk==0
- && (pCons->op & opmask)
- ){
- IdxConstraint *pNew;
- const char *zColl = sqlite3_vtab_collation(pIdxInfo, i);
- pNew = idxNewConstraint(&rc, zColl);
- if( pNew ){
- pNew->iCol = pCons->iColumn;
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
- pNew->pNext = pScan->pEq;
- pScan->pEq = pNew;
- }else{
- pNew->bRange = 1;
- pNew->pNext = pScan->pRange;
- pScan->pRange = pNew;
- }
- }
- n++;
- pIdxInfo->aConstraintUsage[i].argvIndex = n;
- }
- }
-
- /* Add the ORDER BY to the IdxScan object */
- for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
- int iCol = pIdxInfo->aOrderBy[i].iColumn;
- if( iCol>=0 ){
- IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
- if( pNew ){
- pNew->iCol = iCol;
- pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
- pNew->pNext = pScan->pOrder;
- pNew->pLink = pScan->pOrder;
- pScan->pOrder = pNew;
- n++;
- }
- }
- }
- }
-
- pIdxInfo->estimatedCost = 1000000.0 / (n+1);
- return rc;
-}
-
-static int expertUpdate(
- sqlite3_vtab *pVtab,
- int nData,
- sqlite3_value **azData,
- sqlite_int64 *pRowid
-){
- (void)pVtab;
- (void)nData;
- (void)azData;
- (void)pRowid;
- return SQLITE_OK;
-}
-
-/*
-** Virtual table module xOpen method.
-*/
-static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- int rc = SQLITE_OK;
- ExpertCsr *pCsr;
- (void)pVTab;
- pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
- *ppCursor = (sqlite3_vtab_cursor*)pCsr;
- return rc;
-}
-
-/*
-** Virtual table module xClose method.
-*/
-static int expertClose(sqlite3_vtab_cursor *cur){
- ExpertCsr *pCsr = (ExpertCsr*)cur;
- sqlite3_finalize(pCsr->pData);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Virtual table module xEof method.
-**
-** Return non-zero if the cursor does not currently point to a valid
-** record (i.e if the scan has finished), or zero otherwise.
-*/
-static int expertEof(sqlite3_vtab_cursor *cur){
- ExpertCsr *pCsr = (ExpertCsr*)cur;
- return pCsr->pData==0;
-}
-
-/*
-** Virtual table module xNext method.
-*/
-static int expertNext(sqlite3_vtab_cursor *cur){
- ExpertCsr *pCsr = (ExpertCsr*)cur;
- int rc = SQLITE_OK;
-
- assert( pCsr->pData );
- rc = sqlite3_step(pCsr->pData);
- if( rc!=SQLITE_ROW ){
- rc = sqlite3_finalize(pCsr->pData);
- pCsr->pData = 0;
- }else{
- rc = SQLITE_OK;
- }
-
- return rc;
-}
-
-/*
-** Virtual table module xRowid method.
-*/
-static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- (void)cur;
- *pRowid = 0;
- return SQLITE_OK;
-}
-
-/*
-** Virtual table module xColumn method.
-*/
-static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- ExpertCsr *pCsr = (ExpertCsr*)cur;
- sqlite3_value *pVal;
- pVal = sqlite3_column_value(pCsr->pData, i);
- if( pVal ){
- sqlite3_result_value(ctx, pVal);
- }
- return SQLITE_OK;
-}
-
-/*
-** Virtual table module xFilter method.
-*/
-static int expertFilter(
- sqlite3_vtab_cursor *cur,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- ExpertCsr *pCsr = (ExpertCsr*)cur;
- ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab);
- sqlite3expert *pExpert = pVtab->pExpert;
- int rc;
-
- (void)idxNum;
- (void)idxStr;
- (void)argc;
- (void)argv;
- rc = sqlite3_finalize(pCsr->pData);
- pCsr->pData = 0;
- if( rc==SQLITE_OK ){
- rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
- "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
- );
- }
-
- if( rc==SQLITE_OK ){
- rc = expertNext(cur);
- }
- return rc;
-}
-
-static int idxRegisterVtab(sqlite3expert *p){
- static sqlite3_module expertModule = {
- 2, /* iVersion */
- expertConnect, /* xCreate - create a table */
- expertConnect, /* xConnect - connect to an existing table */
- expertBestIndex, /* xBestIndex - Determine search strategy */
- expertDisconnect, /* xDisconnect - Disconnect from a table */
- expertDisconnect, /* xDestroy - Drop a table */
- expertOpen, /* xOpen - open a cursor */
- expertClose, /* xClose - close a cursor */
- expertFilter, /* xFilter - configure scan constraints */
- expertNext, /* xNext - advance a cursor */
- expertEof, /* xEof */
- expertColumn, /* xColumn - read data */
- expertRowid, /* xRowid - read data */
- expertUpdate, /* xUpdate - write data */
- 0, /* xBegin - begin transaction */
- 0, /* xSync - sync transaction */
- 0, /* xCommit - commit transaction */
- 0, /* xRollback - rollback transaction */
- 0, /* xFindFunction - function overloading */
- 0, /* xRename - rename the table */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
- };
-
- return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
-}
-/*
-** End of virtual table implementation.
-*************************************************************************/
-/*
-** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function
-** is called, set it to the return value of sqlite3_finalize() before
-** returning. Otherwise, discard the sqlite3_finalize() return value.
-*/
-static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){
- int rc = sqlite3_finalize(pStmt);
- if( *pRc==SQLITE_OK ) *pRc = rc;
-}
-
-/*
-** Attempt to allocate an IdxTable structure corresponding to table zTab
-** in the main database of connection db. If successful, set (*ppOut) to
-** point to the new object and return SQLITE_OK. Otherwise, return an
-** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be
-** set to point to an error string.
-**
-** It is the responsibility of the caller to eventually free either the
-** IdxTable object or error message using sqlite3_free().
-*/
-static int idxGetTableInfo(
- sqlite3 *db, /* Database connection to read details from */
- const char *zTab, /* Table name */
- IdxTable **ppOut, /* OUT: New object (if successful) */
- char **pzErrmsg /* OUT: Error message (if not) */
-){
- sqlite3_stmt *p1 = 0;
- int nCol = 0;
- int nTab = STRLEN(zTab);
- int nByte = sizeof(IdxTable) + nTab + 1;
- IdxTable *pNew = 0;
- int rc, rc2;
- char *pCsr = 0;
-
- rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
- const char *zCol = (const char*)sqlite3_column_text(p1, 1);
- nByte += 1 + STRLEN(zCol);
- rc = sqlite3_table_column_metadata(
- db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
- );
- nByte += 1 + STRLEN(zCol);
- nCol++;
- }
- rc2 = sqlite3_reset(p1);
- if( rc==SQLITE_OK ) rc = rc2;
-
- nByte += sizeof(IdxColumn) * nCol;
- if( rc==SQLITE_OK ){
- pNew = idxMalloc(&rc, nByte);
- }
- if( rc==SQLITE_OK ){
- pNew->aCol = (IdxColumn*)&pNew[1];
- pNew->nCol = nCol;
- pCsr = (char*)&pNew->aCol[nCol];
- }
-
- nCol = 0;
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
- const char *zCol = (const char*)sqlite3_column_text(p1, 1);
- int nCopy = STRLEN(zCol) + 1;
- pNew->aCol[nCol].zName = pCsr;
- pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
- memcpy(pCsr, zCol, nCopy);
- pCsr += nCopy;
-
- rc = sqlite3_table_column_metadata(
- db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
- );
- if( rc==SQLITE_OK ){
- nCopy = STRLEN(zCol) + 1;
- pNew->aCol[nCol].zColl = pCsr;
- memcpy(pCsr, zCol, nCopy);
- pCsr += nCopy;
- }
-
- nCol++;
- }
- idxFinalize(&rc, p1);
-
- if( rc!=SQLITE_OK ){
- sqlite3_free(pNew);
- pNew = 0;
- }else{
- pNew->zName = pCsr;
- memcpy(pNew->zName, zTab, nTab+1);
- }
-
- *ppOut = pNew;
- return rc;
-}
-
-/*
-** This function is a no-op if *pRc is set to anything other than
-** SQLITE_OK when it is called.
-**
-** If *pRc is initially set to SQLITE_OK, then the text specified by
-** the printf() style arguments is appended to zIn and the result returned
-** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on
-** zIn before returning.
-*/
-static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
- va_list ap;
- char *zAppend = 0;
- char *zRet = 0;
- int nIn = zIn ? STRLEN(zIn) : 0;
- int nAppend = 0;
- va_start(ap, zFmt);
- if( *pRc==SQLITE_OK ){
- zAppend = sqlite3_vmprintf(zFmt, ap);
- if( zAppend ){
- nAppend = STRLEN(zAppend);
- zRet = (char*)sqlite3_malloc(nIn + nAppend + 1);
- }
- if( zAppend && zRet ){
- if( nIn ) memcpy(zRet, zIn, nIn);
- memcpy(&zRet[nIn], zAppend, nAppend+1);
- }else{
- sqlite3_free(zRet);
- zRet = 0;
- *pRc = SQLITE_NOMEM;
- }
- sqlite3_free(zAppend);
- sqlite3_free(zIn);
- }
- va_end(ap);
- return zRet;
-}
-
-/*
-** Return true if zId must be quoted in order to use it as an SQL
-** identifier, or false otherwise.
-*/
-static int idxIdentifierRequiresQuotes(const char *zId){
- int i;
- for(i=0; zId[i]; i++){
- if( !(zId[i]=='_')
- && !(zId[i]>='0' && zId[i]<='9')
- && !(zId[i]>='a' && zId[i]<='z')
- && !(zId[i]>='A' && zId[i]<='Z')
- ){
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** This function appends an index column definition suitable for constraint
-** pCons to the string passed as zIn and returns the result.
-*/
-static char *idxAppendColDefn(
- int *pRc, /* IN/OUT: Error code */
- char *zIn, /* Column defn accumulated so far */
- IdxTable *pTab, /* Table index will be created on */
- IdxConstraint *pCons
-){
- char *zRet = zIn;
- IdxColumn *p = &pTab->aCol[pCons->iCol];
- if( zRet ) zRet = idxAppendText(pRc, zRet, ", ");
-
- if( idxIdentifierRequiresQuotes(p->zName) ){
- zRet = idxAppendText(pRc, zRet, "%Q", p->zName);
- }else{
- zRet = idxAppendText(pRc, zRet, "%s", p->zName);
- }
-
- if( sqlite3_stricmp(p->zColl, pCons->zColl) ){
- if( idxIdentifierRequiresQuotes(pCons->zColl) ){
- zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl);
- }else{
- zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl);
- }
- }
-
- if( pCons->bDesc ){
- zRet = idxAppendText(pRc, zRet, " DESC");
- }
- return zRet;
-}
-
-/*
-** Search database dbm for an index compatible with the one idxCreateFromCons()
-** would create from arguments pScan, pEq and pTail. If no error occurs and
-** such an index is found, return non-zero. Or, if no such index is found,
-** return zero.
-**
-** If an error occurs, set *pRc to an SQLite error code and return zero.
-*/
-static int idxFindCompatible(
- int *pRc, /* OUT: Error code */
- sqlite3* dbm, /* Database to search */
- IdxScan *pScan, /* Scan for table to search for index on */
- IdxConstraint *pEq, /* List of == constraints */
- IdxConstraint *pTail /* List of range constraints */
-){
- const char *zTbl = pScan->pTab->zName;
- sqlite3_stmt *pIdxList = 0;
- IdxConstraint *pIter;
- int nEq = 0; /* Number of elements in pEq */
- int rc;
-
- /* Count the elements in list pEq */
- for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++;
-
- rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
- while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
- int bMatch = 1;
- IdxConstraint *pT = pTail;
- sqlite3_stmt *pInfo = 0;
- const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
-
- /* Zero the IdxConstraint.bFlag values in the pEq list */
- for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
-
- rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
- while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
- int iIdx = sqlite3_column_int(pInfo, 0);
- int iCol = sqlite3_column_int(pInfo, 1);
- const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
-
- if( iIdx<nEq ){
- for(pIter=pEq; pIter; pIter=pIter->pLink){
- if( pIter->bFlag ) continue;
- if( pIter->iCol!=iCol ) continue;
- if( sqlite3_stricmp(pIter->zColl, zColl) ) continue;
- pIter->bFlag = 1;
- break;
- }
- if( pIter==0 ){
- bMatch = 0;
- break;
- }
- }else{
- if( pT ){
- if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){
- bMatch = 0;
- break;
- }
- pT = pT->pLink;
- }
- }
- }
- idxFinalize(&rc, pInfo);
-
- if( rc==SQLITE_OK && bMatch ){
- sqlite3_finalize(pIdxList);
- return 1;
- }
- }
- idxFinalize(&rc, pIdxList);
-
- *pRc = rc;
- return 0;
-}
-
-static int idxCreateFromCons(
- sqlite3expert *p,
- IdxScan *pScan,
- IdxConstraint *pEq,
- IdxConstraint *pTail
-){
- sqlite3 *dbm = p->dbm;
- int rc = SQLITE_OK;
- if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
- IdxTable *pTab = pScan->pTab;
- char *zCols = 0;
- char *zIdx = 0;
- IdxConstraint *pCons;
- unsigned int h = 0;
- const char *zFmt;
-
- for(pCons=pEq; pCons; pCons=pCons->pLink){
- zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
- }
- for(pCons=pTail; pCons; pCons=pCons->pLink){
- zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
- }
-
- if( rc==SQLITE_OK ){
- /* Hash the list of columns to come up with a name for the index */
- const char *zTable = pScan->pTab->zName;
- char *zName; /* Index name */
- int i;
- for(i=0; zCols[i]; i++){
- h += ((h<<3) + zCols[i]);
- }
- zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
- if( zName==0 ){
- rc = SQLITE_NOMEM;
- }else{
- if( idxIdentifierRequiresQuotes(zTable) ){
- zFmt = "CREATE INDEX '%q' ON %Q(%s)";
- }else{
- zFmt = "CREATE INDEX %s ON %s(%s)";
- }
- zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
- if( !zIdx ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
- idxHashAdd(&rc, &p->hIdx, zName, zIdx);
- }
- sqlite3_free(zName);
- sqlite3_free(zIdx);
- }
- }
-
- sqlite3_free(zCols);
- }
- return rc;
-}
-
-/*
-** Return true if list pList (linked by IdxConstraint.pLink) contains
-** a constraint compatible with *p. Otherwise return false.
-*/
-static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
- IdxConstraint *pCmp;
- for(pCmp=pList; pCmp; pCmp=pCmp->pLink){
- if( p->iCol==pCmp->iCol ) return 1;
- }
- return 0;
-}
-
-static int idxCreateFromWhere(
- sqlite3expert *p,
- IdxScan *pScan, /* Create indexes for this scan */
- IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */
-){
- IdxConstraint *p1 = 0;
- IdxConstraint *pCon;
- int rc;
-
- /* Gather up all the == constraints. */
- for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
- if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
- pCon->pLink = p1;
- p1 = pCon;
- }
- }
-
- /* Create an index using the == constraints collected above. And the
- ** range constraint/ORDER BY terms passed in by the caller, if any. */
- rc = idxCreateFromCons(p, pScan, p1, pTail);
-
- /* If no range/ORDER BY passed by the caller, create a version of the
- ** index for each range constraint. */
- if( pTail==0 ){
- for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
- assert( pCon->pLink==0 );
- if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
- rc = idxCreateFromCons(p, pScan, p1, pCon);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Create candidate indexes in database [dbm] based on the data in
-** linked-list pScan.
-*/
-static int idxCreateCandidates(sqlite3expert *p){
- int rc = SQLITE_OK;
- IdxScan *pIter;
-
- for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
- rc = idxCreateFromWhere(p, pIter, 0);
- if( rc==SQLITE_OK && pIter->pOrder ){
- rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
- }
- }
-
- return rc;
-}
-
-/*
-** Free all elements of the linked list starting at pConstraint.
-*/
-static void idxConstraintFree(IdxConstraint *pConstraint){
- IdxConstraint *pNext;
- IdxConstraint *p;
-
- for(p=pConstraint; p; p=pNext){
- pNext = p->pNext;
- sqlite3_free(p);
- }
-}
-
-/*
-** Free all elements of the linked list starting from pScan up until pLast
-** (pLast is not freed).
-*/
-static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
- IdxScan *p;
- IdxScan *pNext;
- for(p=pScan; p!=pLast; p=pNext){
- pNext = p->pNextScan;
- idxConstraintFree(p->pOrder);
- idxConstraintFree(p->pEq);
- idxConstraintFree(p->pRange);
- sqlite3_free(p);
- }
-}
-
-/*
-** Free all elements of the linked list starting from pStatement up
-** until pLast (pLast is not freed).
-*/
-static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
- IdxStatement *p;
- IdxStatement *pNext;
- for(p=pStatement; p!=pLast; p=pNext){
- pNext = p->pNext;
- sqlite3_free(p->zEQP);
- sqlite3_free(p->zIdx);
- sqlite3_free(p);
- }
-}
-
-/*
-** Free the linked list of IdxTable objects starting at pTab.
-*/
-static void idxTableFree(IdxTable *pTab){
- IdxTable *pIter;
- IdxTable *pNext;
- for(pIter=pTab; pIter; pIter=pNext){
- pNext = pIter->pNext;
- sqlite3_free(pIter);
- }
-}
-
-/*
-** Free the linked list of IdxWrite objects starting at pTab.
-*/
-static void idxWriteFree(IdxWrite *pTab){
- IdxWrite *pIter;
- IdxWrite *pNext;
- for(pIter=pTab; pIter; pIter=pNext){
- pNext = pIter->pNext;
- sqlite3_free(pIter);
- }
-}
-
-
-
-/*
-** This function is called after candidate indexes have been created. It
-** runs all the queries to see which indexes they prefer, and populates
-** IdxStatement.zIdx and IdxStatement.zEQP with the results.
-*/
-int idxFindIndexes(
- sqlite3expert *p,
- char **pzErr /* OUT: Error message (sqlite3_malloc) */
-){
- IdxStatement *pStmt;
- sqlite3 *dbm = p->dbm;
- int rc = SQLITE_OK;
-
- IdxHash hIdx;
- idxHashInit(&hIdx);
-
- for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
- IdxHashEntry *pEntry;
- sqlite3_stmt *pExplain = 0;
- idxHashClear(&hIdx);
- rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
- "EXPLAIN QUERY PLAN %s", pStmt->zSql
- );
- while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
- /* int iId = sqlite3_column_int(pExplain, 0); */
- /* int iParent = sqlite3_column_int(pExplain, 1); */
- /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
- const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
- int nDetail = STRLEN(zDetail);
- int i;
-
- for(i=0; i<nDetail; i++){
- const char *zIdx = 0;
- if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
- zIdx = &zDetail[i+13];
- }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
- zIdx = &zDetail[i+22];
- }
- if( zIdx ){
- const char *zSql;
- int nIdx = 0;
- while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
- nIdx++;
- }
- zSql = idxHashSearch(&p->hIdx, zIdx, nIdx);
- if( zSql ){
- idxHashAdd(&rc, &hIdx, zSql, 0);
- if( rc ) goto find_indexes_out;
- }
- break;
- }
- }
-
- if( zDetail[0]!='-' ){
- pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
- }
- }
-
- for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
- pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
- }
-
- idxFinalize(&rc, pExplain);
- }
-
- find_indexes_out:
- idxHashClear(&hIdx);
- return rc;
-}
-
-static int idxAuthCallback(
- void *pCtx,
- int eOp,
- const char *z3,
- const char *z4,
- const char *zDb,
- const char *zTrigger
-){
- int rc = SQLITE_OK;
- (void)z4;
- (void)zTrigger;
- if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
- if( sqlite3_stricmp(zDb, "main")==0 ){
- sqlite3expert *p = (sqlite3expert*)pCtx;
- IdxTable *pTab;
- for(pTab=p->pTable; pTab; pTab=pTab->pNext){
- if( 0==sqlite3_stricmp(z3, pTab->zName) ) break;
- }
- if( pTab ){
- IdxWrite *pWrite;
- for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){
- if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break;
- }
- if( pWrite==0 ){
- pWrite = idxMalloc(&rc, sizeof(IdxWrite));
- if( rc==SQLITE_OK ){
- pWrite->pTab = pTab;
- pWrite->eOp = eOp;
- pWrite->pNext = p->pWrite;
- p->pWrite = pWrite;
- }
- }
- }
- }
- }
- return rc;
-}
-
-static int idxProcessOneTrigger(
- sqlite3expert *p,
- IdxWrite *pWrite,
- char **pzErr
-){
- static const char *zInt = UNIQUE_TABLE_NAME;
- static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
- IdxTable *pTab = pWrite->pTab;
- const char *zTab = pTab->zName;
- const char *zSql =
- "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master "
- "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
- "ORDER BY type;";
- sqlite3_stmt *pSelect = 0;
- int rc = SQLITE_OK;
- char *zWrite = 0;
-
- /* Create the table and its triggers in the temp schema */
- rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
- const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
- rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
- }
- idxFinalize(&rc, pSelect);
-
- /* Rename the table in the temp schema to zInt */
- if( rc==SQLITE_OK ){
- char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
- if( z==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr);
- sqlite3_free(z);
- }
- }
-
- switch( pWrite->eOp ){
- case SQLITE_INSERT: {
- int i;
- zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt);
- for(i=0; i<pTab->nCol; i++){
- zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", ");
- }
- zWrite = idxAppendText(&rc, zWrite, ")");
- break;
- }
- case SQLITE_UPDATE: {
- int i;
- zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt);
- for(i=0; i<pTab->nCol; i++){
- zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ",
- pTab->aCol[i].zName
- );
- }
- break;
- }
- default: {
- assert( pWrite->eOp==SQLITE_DELETE );
- if( rc==SQLITE_OK ){
- zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt);
- if( zWrite==0 ) rc = SQLITE_NOMEM;
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- sqlite3_stmt *pX = 0;
- rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0);
- idxFinalize(&rc, pX);
- if( rc!=SQLITE_OK ){
- idxDatabaseError(p->dbv, pzErr);
- }
- }
- sqlite3_free(zWrite);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr);
- }
-
- return rc;
-}
-
-static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
- int rc = SQLITE_OK;
- IdxWrite *pEnd = 0;
- IdxWrite *pFirst = p->pWrite;
-
- while( rc==SQLITE_OK && pFirst!=pEnd ){
- IdxWrite *pIter;
- for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){
- rc = idxProcessOneTrigger(p, pIter, pzErr);
- }
- pEnd = pFirst;
- pFirst = p->pWrite;
- }
-
- return rc;
-}
-
-
-static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
- int rc = idxRegisterVtab(p);
- sqlite3_stmt *pSchema = 0;
-
- /* For each table in the main db schema:
- **
- ** 1) Add an entry to the p->pTable list, and
- ** 2) Create the equivalent virtual table in dbv.
- */
- rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
- "SELECT type, name, sql, 1 FROM sqlite_master "
- "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
- " UNION ALL "
- "SELECT type, name, sql, 2 FROM sqlite_master "
- "WHERE type = 'trigger'"
- " AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') "
- "ORDER BY 4, 1"
- );
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
- const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
- const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
- const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
-
- if( zType[0]=='v' || zType[1]=='r' ){
- rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
- }else{
- IdxTable *pTab;
- rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
- if( rc==SQLITE_OK ){
- int i;
- char *zInner = 0;
- char *zOuter = 0;
- pTab->pNext = p->pTable;
- p->pTable = pTab;
-
- /* The statement the vtab will pass to sqlite3_declare_vtab() */
- zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
- for(i=0; i<pTab->nCol; i++){
- zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
- (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
- );
- }
- zInner = idxAppendText(&rc, zInner, ")");
-
- /* The CVT statement to create the vtab */
- zOuter = idxAppendText(&rc, 0,
- "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
- }
- sqlite3_free(zInner);
- sqlite3_free(zOuter);
- }
- }
- }
- idxFinalize(&rc, pSchema);
- return rc;
-}
-
-struct IdxSampleCtx {
- int iTarget;
- double target; /* Target nRet/nRow value */
- double nRow; /* Number of rows seen */
- double nRet; /* Number of rows returned */
-};
-
-static void idxSampleFunc(
- sqlite3_context *pCtx,
- int argc,
- sqlite3_value **argv
-){
- struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
- int bRet;
-
- (void)argv;
- assert( argc==0 );
- if( p->nRow==0.0 ){
- bRet = 1;
- }else{
- bRet = (p->nRet / p->nRow) <= p->target;
- if( bRet==0 ){
- unsigned short rnd;
- sqlite3_randomness(2, (void*)&rnd);
- bRet = ((int)rnd % 100) <= p->iTarget;
- }
- }
-
- sqlite3_result_int(pCtx, bRet);
- p->nRow += 1.0;
- p->nRet += (double)bRet;
-}
-
-struct IdxRemCtx {
- int nSlot;
- struct IdxRemSlot {
- int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
- i64 iVal; /* SQLITE_INTEGER value */
- double rVal; /* SQLITE_FLOAT value */
- int nByte; /* Bytes of space allocated at z */
- int n; /* Size of buffer z */
- char *z; /* SQLITE_TEXT/BLOB value */
- } aSlot[1];
-};
-
-/*
-** Implementation of scalar function rem().
-*/
-static void idxRemFunc(
- sqlite3_context *pCtx,
- int argc,
- sqlite3_value **argv
-){
- struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx);
- struct IdxRemSlot *pSlot;
- int iSlot;
- assert( argc==2 );
-
- iSlot = sqlite3_value_int(argv[0]);
- assert( iSlot<=p->nSlot );
- pSlot = &p->aSlot[iSlot];
-
- switch( pSlot->eType ){
- case SQLITE_NULL:
- /* no-op */
- break;
-
- case SQLITE_INTEGER:
- sqlite3_result_int64(pCtx, pSlot->iVal);
- break;
-
- case SQLITE_FLOAT:
- sqlite3_result_double(pCtx, pSlot->rVal);
- break;
-
- case SQLITE_BLOB:
- sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
- break;
-
- case SQLITE_TEXT:
- sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
- break;
- }
-
- pSlot->eType = sqlite3_value_type(argv[1]);
- switch( pSlot->eType ){
- case SQLITE_NULL:
- /* no-op */
- break;
-
- case SQLITE_INTEGER:
- pSlot->iVal = sqlite3_value_int64(argv[1]);
- break;
-
- case SQLITE_FLOAT:
- pSlot->rVal = sqlite3_value_double(argv[1]);
- break;
-
- case SQLITE_BLOB:
- case SQLITE_TEXT: {
- int nByte = sqlite3_value_bytes(argv[1]);
- if( nByte>pSlot->nByte ){
- char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
- if( zNew==0 ){
- sqlite3_result_error_nomem(pCtx);
- return;
- }
- pSlot->nByte = nByte*2;
- pSlot->z = zNew;
- }
- pSlot->n = nByte;
- if( pSlot->eType==SQLITE_BLOB ){
- memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
- }else{
- memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
- }
- break;
- }
- }
-}
-
-static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
- int rc = SQLITE_OK;
- const char *zMax =
- "SELECT max(i.seqno) FROM "
- " sqlite_master AS s, "
- " pragma_index_list(s.name) AS l, "
- " pragma_index_info(l.name) AS i "
- "WHERE s.type = 'table'";
- sqlite3_stmt *pMax = 0;
-
- *pnMax = 0;
- rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
- if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
- *pnMax = sqlite3_column_int(pMax, 0) + 1;
- }
- idxFinalize(&rc, pMax);
-
- return rc;
-}
-
-static int idxPopulateOneStat1(
- sqlite3expert *p,
- sqlite3_stmt *pIndexXInfo,
- sqlite3_stmt *pWriteStat,
- const char *zTab,
- const char *zIdx,
- char **pzErr
-){
- char *zCols = 0;
- char *zOrder = 0;
- char *zQuery = 0;
- int nCol = 0;
- int i;
- sqlite3_stmt *pQuery = 0;
- int *aStat = 0;
- int rc = SQLITE_OK;
-
- assert( p->iSample>0 );
-
- /* Formulate the query text */
- sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC);
- while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){
- const char *zComma = zCols==0 ? "" : ", ";
- const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
- const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
- zCols = idxAppendText(&rc, zCols,
- "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
- );
- zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
- }
- sqlite3_reset(pIndexXInfo);
- if( rc==SQLITE_OK ){
- if( p->iSample==100 ){
- zQuery = sqlite3_mprintf(
- "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder
- );
- }else{
- zQuery = sqlite3_mprintf(
- "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder
- );
- }
- }
- sqlite3_free(zCols);
- sqlite3_free(zOrder);
-
- /* Formulate the query text */
- if( rc==SQLITE_OK ){
- sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
- rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery);
- }
- sqlite3_free(zQuery);
-
- if( rc==SQLITE_OK ){
- aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1));
- }
- if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
- IdxHashEntry *pEntry;
- char *zStat = 0;
- for(i=0; i<=nCol; i++) aStat[i] = 1;
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
- aStat[0]++;
- for(i=0; i<nCol; i++){
- if( sqlite3_column_int(pQuery, i)==0 ) break;
- }
- for(/*no-op*/; i<nCol; i++){
- aStat[i+1]++;
- }
- }
-
- if( rc==SQLITE_OK ){
- int s0 = aStat[0];
- zStat = sqlite3_mprintf("%d", s0);
- if( zStat==0 ) rc = SQLITE_NOMEM;
- for(i=1; rc==SQLITE_OK && i<=nCol; i++){
- zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]);
- }
- }
-
- if( rc==SQLITE_OK ){
- sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC);
- sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC);
- sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC);
- sqlite3_step(pWriteStat);
- rc = sqlite3_reset(pWriteStat);
- }
-
- pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx));
- if( pEntry ){
- assert( pEntry->zVal2==0 );
- pEntry->zVal2 = zStat;
- }else{
- sqlite3_free(zStat);
- }
- }
- sqlite3_free(aStat);
- idxFinalize(&rc, pQuery);
-
- return rc;
-}
-
-static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){
- int rc;
- char *zSql;
-
- rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
- if( rc!=SQLITE_OK ) return rc;
-
- zSql = sqlite3_mprintf(
- "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab
- );
- if( zSql==0 ) return SQLITE_NOMEM;
- rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0);
- sqlite3_free(zSql);
-
- return rc;
-}
-
-/*
-** This function is called as part of sqlite3_expert_analyze(). Candidate
-** indexes have already been created in database sqlite3expert.dbm, this
-** function populates sqlite_stat1 table in the same database.
-**
-** The stat1 data is generated by querying the
-*/
-static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
- int rc = SQLITE_OK;
- int nMax =0;
- struct IdxRemCtx *pCtx = 0;
- struct IdxSampleCtx samplectx;
- int i;
- i64 iPrev = -100000;
- sqlite3_stmt *pAllIndex = 0;
- sqlite3_stmt *pIndexXInfo = 0;
- sqlite3_stmt *pWrite = 0;
-
- const char *zAllIndex =
- "SELECT s.rowid, s.name, l.name FROM "
- " sqlite_master AS s, "
- " pragma_index_list(s.name) AS l "
- "WHERE s.type = 'table'";
- const char *zIndexXInfo =
- "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
- const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";
-
- /* If iSample==0, no sqlite_stat1 data is required. */
- if( p->iSample==0 ) return SQLITE_OK;
-
- rc = idxLargestIndex(p->dbm, &nMax, pzErr);
- if( nMax<=0 || rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
-
- if( rc==SQLITE_OK ){
- int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
- pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
- }
-
- if( rc==SQLITE_OK ){
- sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
- rc = sqlite3_create_function(
- dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
- );
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(
- p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
- );
- }
-
- if( rc==SQLITE_OK ){
- pCtx->nSlot = nMax+1;
- rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
- }
- if( rc==SQLITE_OK ){
- rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo);
- }
- if( rc==SQLITE_OK ){
- rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
- }
-
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
- i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
- const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
- const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
- if( p->iSample<100 && iPrev!=iRowid ){
- samplectx.target = (double)p->iSample / 100.0;
- samplectx.iTarget = p->iSample;
- samplectx.nRow = 0.0;
- samplectx.nRet = 0.0;
- rc = idxBuildSampleTable(p, zTab);
- if( rc!=SQLITE_OK ) break;
- }
- rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr);
- iPrev = iRowid;
- }
- if( rc==SQLITE_OK && p->iSample<100 ){
- rc = sqlite3_exec(p->dbv,
- "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0
- );
- }
-
- idxFinalize(&rc, pAllIndex);
- idxFinalize(&rc, pIndexXInfo);
- idxFinalize(&rc, pWrite);
-
- for(i=0; i<pCtx->nSlot; i++){
- sqlite3_free(pCtx->aSlot[i].z);
- }
- sqlite3_free(pCtx);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0);
- }
-
- sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
- return rc;
-}
-
-/*
-** Allocate a new sqlite3expert object.
-*/
-sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
- int rc = SQLITE_OK;
- sqlite3expert *pNew;
-
- pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert));
-
- /* Open two in-memory databases to work with. The "vtab database" (dbv)
- ** will contain a virtual table corresponding to each real table in
- ** the user database schema, and a copy of each view. It is used to
- ** collect information regarding the WHERE, ORDER BY and other clauses
- ** of the user's query.
- */
- if( rc==SQLITE_OK ){
- pNew->db = db;
- pNew->iSample = 100;
- rc = sqlite3_open(":memory:", &pNew->dbv);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_open(":memory:", &pNew->dbm);
- if( rc==SQLITE_OK ){
- sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
- }
- }
-
-
- /* Copy the entire schema of database [db] into [dbm]. */
- if( rc==SQLITE_OK ){
- sqlite3_stmt *pSql;
- rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
- "SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'"
- " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
- );
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
- const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
- rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
- }
- idxFinalize(&rc, pSql);
- }
-
- /* Create the vtab schema */
- if( rc==SQLITE_OK ){
- rc = idxCreateVtabSchema(pNew, pzErrmsg);
- }
-
- /* Register the auth callback with dbv */
- if( rc==SQLITE_OK ){
- sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
- }
-
- /* If an error has occurred, free the new object and reutrn NULL. Otherwise,
- ** return the new sqlite3expert handle. */
- if( rc!=SQLITE_OK ){
- sqlite3_expert_destroy(pNew);
- pNew = 0;
- }
- return pNew;
-}
-
-/*
-** Configure an sqlite3expert object.
-*/
-int sqlite3_expert_config(sqlite3expert *p, int op, ...){
- int rc = SQLITE_OK;
- va_list ap;
- va_start(ap, op);
- switch( op ){
- case EXPERT_CONFIG_SAMPLE: {
- int iVal = va_arg(ap, int);
- if( iVal<0 ) iVal = 0;
- if( iVal>100 ) iVal = 100;
- p->iSample = iVal;
- break;
- }
- default:
- rc = SQLITE_NOTFOUND;
- break;
- }
-
- va_end(ap);
- return rc;
-}
-
-/*
-** Add an SQL statement to the analysis.
-*/
-int sqlite3_expert_sql(
- sqlite3expert *p, /* From sqlite3_expert_new() */
- const char *zSql, /* SQL statement to add */
- char **pzErr /* OUT: Error message (if any) */
-){
- IdxScan *pScanOrig = p->pScan;
- IdxStatement *pStmtOrig = p->pStatement;
- int rc = SQLITE_OK;
- const char *zStmt = zSql;
-
- if( p->bRun ) return SQLITE_MISUSE;
-
- while( rc==SQLITE_OK && zStmt && zStmt[0] ){
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
- if( rc==SQLITE_OK ){
- if( pStmt ){
- IdxStatement *pNew;
- const char *z = sqlite3_sql(pStmt);
- int n = STRLEN(z);
- pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
- if( rc==SQLITE_OK ){
- pNew->zSql = (char*)&pNew[1];
- memcpy(pNew->zSql, z, n+1);
- pNew->pNext = p->pStatement;
- if( p->pStatement ) pNew->iId = p->pStatement->iId+1;
- p->pStatement = pNew;
- }
- sqlite3_finalize(pStmt);
- }
- }else{
- idxDatabaseError(p->dbv, pzErr);
- }
- }
-
- if( rc!=SQLITE_OK ){
- idxScanFree(p->pScan, pScanOrig);
- idxStatementFree(p->pStatement, pStmtOrig);
- p->pScan = pScanOrig;
- p->pStatement = pStmtOrig;
- }
-
- return rc;
-}
-
-int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
- int rc;
- IdxHashEntry *pEntry;
-
- /* Do trigger processing to collect any extra IdxScan structures */
- rc = idxProcessTriggers(p, pzErr);
-
- /* Create candidate indexes within the in-memory database file */
- if( rc==SQLITE_OK ){
- rc = idxCreateCandidates(p);
- }
-
- /* Generate the stat1 data */
- if( rc==SQLITE_OK ){
- rc = idxPopulateStat1(p, pzErr);
- }
-
- /* Formulate the EXPERT_REPORT_CANDIDATES text */
- for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
- p->zCandidates = idxAppendText(&rc, p->zCandidates,
- "%s;%s%s\n", pEntry->zVal,
- pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2
- );
- }
-
- /* Figure out which of the candidate indexes are preferred by the query
- ** planner and report the results to the user. */
- if( rc==SQLITE_OK ){
- rc = idxFindIndexes(p, pzErr);
- }
-
- if( rc==SQLITE_OK ){
- p->bRun = 1;
- }
- return rc;
-}
-
-/*
-** Return the total number of statements that have been added to this
-** sqlite3expert using sqlite3_expert_sql().
-*/
-int sqlite3_expert_count(sqlite3expert *p){
- int nRet = 0;
- if( p->pStatement ) nRet = p->pStatement->iId+1;
- return nRet;
-}
-
-/*
-** Return a component of the report.
-*/
-const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
- const char *zRet = 0;
- IdxStatement *pStmt;
-
- if( p->bRun==0 ) return 0;
- for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
- switch( eReport ){
- case EXPERT_REPORT_SQL:
- if( pStmt ) zRet = pStmt->zSql;
- break;
- case EXPERT_REPORT_INDEXES:
- if( pStmt ) zRet = pStmt->zIdx;
- break;
- case EXPERT_REPORT_PLAN:
- if( pStmt ) zRet = pStmt->zEQP;
- break;
- case EXPERT_REPORT_CANDIDATES:
- zRet = p->zCandidates;
- break;
- }
- return zRet;
-}
-
-/*
-** Free an sqlite3expert object.
-*/
-void sqlite3_expert_destroy(sqlite3expert *p){
- if( p ){
- sqlite3_close(p->dbm);
- sqlite3_close(p->dbv);
- idxScanFree(p->pScan, 0);
- idxStatementFree(p->pStatement, 0);
- idxTableFree(p->pTable);
- idxWriteFree(p->pWrite);
- idxHashClear(&p->hIdx);
- sqlite3_free(p->zCandidates);
- sqlite3_free(p);
- }
-}
-
-#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/sqlite3expert.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/sqlite3expert.h
deleted file mode 100644
index 39135dc274d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/sqlite3expert.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-** 2017 April 07
-**
-** 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.
-**
-*************************************************************************
-*/
-
-
-#include "sqlite3.h"
-
-typedef struct sqlite3expert sqlite3expert;
-
-/*
-** Create a new sqlite3expert object.
-**
-** If successful, a pointer to the new object is returned and (*pzErr) set
-** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
-** an English-language error message. In this case it is the responsibility
-** of the caller to eventually free the error message buffer using
-** sqlite3_free().
-*/
-sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
-
-/*
-** Configure an sqlite3expert object.
-**
-** EXPERT_CONFIG_SAMPLE:
-** By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
-** each candidate index. This involves scanning and sorting the entire
-** contents of each user database table once for each candidate index
-** associated with the table. For large databases, this can be
-** prohibitively slow. This option allows the sqlite3expert object to
-** be configured so that sqlite_stat1 data is instead generated based on a
-** subset of each table, or so that no sqlite_stat1 data is used at all.
-**
-** A single integer argument is passed to this option. If the value is less
-** than or equal to zero, then no sqlite_stat1 data is generated or used by
-** the analysis - indexes are recommended based on the database schema only.
-** Or, if the value is 100 or greater, complete sqlite_stat1 data is
-** generated for each candidate index (this is the default). Finally, if the
-** value falls between 0 and 100, then it represents the percentage of user
-** table rows that should be considered when generating sqlite_stat1 data.
-**
-** Examples:
-**
-** // Do not generate any sqlite_stat1 data
-** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
-**
-** // Generate sqlite_stat1 data based on 10% of the rows in each table.
-** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
-*/
-int sqlite3_expert_config(sqlite3expert *p, int op, ...);
-
-#define EXPERT_CONFIG_SAMPLE 1 /* int */
-
-/*
-** Specify zero or more SQL statements to be included in the analysis.
-**
-** Buffer zSql must contain zero or more complete SQL statements. This
-** function parses all statements contained in the buffer and adds them
-** to the internal list of statements to analyze. If successful, SQLITE_OK
-** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
-** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
-** may be set to point to an English language error message. In this case
-** the caller is responsible for eventually freeing the error message buffer
-** using sqlite3_free().
-**
-** If an error does occur while processing one of the statements in the
-** buffer passed as the second argument, none of the statements in the
-** buffer are added to the analysis.
-**
-** This function must be called before sqlite3_expert_analyze(). If a call
-** to this function is made on an sqlite3expert object that has already
-** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
-** immediately and no statements are added to the analysis.
-*/
-int sqlite3_expert_sql(
- sqlite3expert *p, /* From a successful sqlite3_expert_new() */
- const char *zSql, /* SQL statement(s) to add */
- char **pzErr /* OUT: Error message (if any) */
-);
-
-
-/*
-** This function is called after the sqlite3expert object has been configured
-** with all SQL statements using sqlite3_expert_sql() to actually perform
-** the analysis. Once this function has been called, it is not possible to
-** add further SQL statements to the analysis.
-**
-** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
-** an error occurs, an SQLite error code is returned and (*pzErr) set to
-** point to a buffer containing an English language error message. In this
-** case it is the responsibility of the caller to eventually free the buffer
-** using sqlite3_free().
-**
-** If an error does occur within this function, the sqlite3expert object
-** is no longer useful for any purpose. At that point it is no longer
-** possible to add further SQL statements to the object or to re-attempt
-** the analysis. The sqlite3expert object must still be freed using a call
-** sqlite3_expert_destroy().
-*/
-int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
-
-/*
-** Return the total number of statements loaded using sqlite3_expert_sql().
-** The total number of SQL statements may be different from the total number
-** to calls to sqlite3_expert_sql().
-*/
-int sqlite3_expert_count(sqlite3expert*);
-
-/*
-** Return a component of the report.
-**
-** This function is called after sqlite3_expert_analyze() to extract the
-** results of the analysis. Each call to this function returns either a
-** NULL pointer or a pointer to a buffer containing a nul-terminated string.
-** The value passed as the third argument must be one of the EXPERT_REPORT_*
-** #define constants defined below.
-**
-** For some EXPERT_REPORT_* parameters, the buffer returned contains
-** information relating to a specific SQL statement. In these cases that
-** SQL statement is identified by the value passed as the second argument.
-** SQL statements are numbered from 0 in the order in which they are parsed.
-** If an out-of-range value (less than zero or equal to or greater than the
-** value returned by sqlite3_expert_count()) is passed as the second argument
-** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
-**
-** EXPERT_REPORT_SQL:
-** Return the text of SQL statement iStmt.
-**
-** EXPERT_REPORT_INDEXES:
-** Return a buffer containing the CREATE INDEX statements for all recommended
-** indexes for statement iStmt. If there are no new recommeded indexes, NULL
-** is returned.
-**
-** EXPERT_REPORT_PLAN:
-** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
-** iStmt after the proposed indexes have been added to the database schema.
-**
-** EXPERT_REPORT_CANDIDATES:
-** Return a pointer to a buffer containing the CREATE INDEX statements
-** for all indexes that were tested (for all SQL statements). The iStmt
-** parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
-*/
-const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
-
-/*
-** Values for the third argument passed to sqlite3_expert_report().
-*/
-#define EXPERT_REPORT_SQL 1
-#define EXPERT_REPORT_INDEXES 2
-#define EXPERT_REPORT_PLAN 3
-#define EXPERT_REPORT_CANDIDATES 4
-
-/*
-** Free an (sqlite3expert*) handle and all associated resources. There
-** should be one call to this function for each successful call to
-** sqlite3-expert_new().
-*/
-void sqlite3_expert_destroy(sqlite3expert*);
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/test_expert.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/test_expert.c
deleted file mode 100644
index 064c1908a96..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/expert/test_expert.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
-** 2017 April 07
-**
-** 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.
-**
-*************************************************************************
-*/
-
-#if defined(SQLITE_TEST)
-
-#include "sqlite3expert.h"
-#include <assert.h>
-#include <string.h>
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Extract an sqlite3* db handle from the object passed as the second
-** argument. If successful, set *pDb to point to the db handle and return
-** TCL_OK. Otherwise, return TCL_ERROR.
-*/
-static int dbHandleFromObj(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
- Tcl_CmdInfo info;
- if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(pObj), &info) ){
- Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
- return TCL_ERROR;
- }
-
- *pDb = *(sqlite3 **)info.objClientData;
- return TCL_OK;
-}
-
-
-/*
-** Tclcmd: $expert sql SQL
-** $expert analyze
-** $expert count
-** $expert report STMT EREPORT
-** $expert destroy
-*/
-static int SQLITE_TCLAPI testExpertCmd(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3expert *pExpert = (sqlite3expert*)clientData;
- struct Subcmd {
- const char *zSub;
- int nArg;
- const char *zMsg;
- } aSub[] = {
- { "sql", 1, "TABLE", }, /* 0 */
- { "analyze", 0, "", }, /* 1 */
- { "count", 0, "", }, /* 2 */
- { "report", 2, "STMT EREPORT", }, /* 3 */
- { "destroy", 0, "", }, /* 4 */
- { 0 }
- };
- int iSub;
- int rc = TCL_OK;
- char *zErr = 0;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
- return TCL_ERROR;
- }
- rc = Tcl_GetIndexFromObjStruct(interp,
- objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
- );
- if( rc!=TCL_OK ) return rc;
- if( objc!=2+aSub[iSub].nArg ){
- Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg);
- return TCL_ERROR;
- }
-
- switch( iSub ){
- case 0: { /* sql */
- char *zArg = Tcl_GetString(objv[2]);
- rc = sqlite3_expert_sql(pExpert, zArg, &zErr);
- break;
- }
-
- case 1: { /* analyze */
- rc = sqlite3_expert_analyze(pExpert, &zErr);
- break;
- }
-
- case 2: { /* count */
- int n = sqlite3_expert_count(pExpert);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
- break;
- }
-
- case 3: { /* report */
- const char *aEnum[] = {
- "sql", "indexes", "plan", "candidates", 0
- };
- int iEnum;
- int iStmt;
- const char *zReport;
-
- if( Tcl_GetIntFromObj(interp, objv[2], &iStmt)
- || Tcl_GetIndexFromObj(interp, objv[3], aEnum, "report", 0, &iEnum)
- ){
- return TCL_ERROR;
- }
-
- assert( EXPERT_REPORT_SQL==1 );
- assert( EXPERT_REPORT_INDEXES==2 );
- assert( EXPERT_REPORT_PLAN==3 );
- assert( EXPERT_REPORT_CANDIDATES==4 );
- zReport = sqlite3_expert_report(pExpert, iStmt, 1+iEnum);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zReport, -1));
- break;
- }
-
- default: /* destroy */
- assert( iSub==4 );
- Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
- break;
- }
-
- if( rc!=TCL_OK ){
- if( zErr ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
- }else{
- extern const char *sqlite3ErrName(int);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- }
- }
- sqlite3_free(zErr);
- return rc;
-}
-
-static void SQLITE_TCLAPI testExpertDel(void *clientData){
- sqlite3expert *pExpert = (sqlite3expert*)clientData;
- sqlite3_expert_destroy(pExpert);
-}
-
-/*
-** sqlite3_expert_new DB
-*/
-static int SQLITE_TCLAPI test_sqlite3_expert_new(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- static int iCmd = 0;
- sqlite3 *db;
- char *zCmd = 0;
- char *zErr = 0;
- sqlite3expert *pExpert;
- int rc = TCL_OK;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( dbHandleFromObj(interp, objv[1], &db) ){
- return TCL_ERROR;
- }
-
- zCmd = sqlite3_mprintf("sqlite3expert%d", ++iCmd);
- if( zCmd==0 ){
- Tcl_AppendResult(interp, "out of memory", (char*)0);
- return TCL_ERROR;
- }
-
- pExpert = sqlite3_expert_new(db, &zErr);
- if( pExpert==0 ){
- Tcl_AppendResult(interp, zErr, (char*)0);
- rc = TCL_ERROR;
- }else{
- void *p = (void*)pExpert;
- Tcl_CreateObjCommand(interp, zCmd, testExpertCmd, p, testExpertDel);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zCmd, -1));
- }
-
- sqlite3_free(zCmd);
- sqlite3_free(zErr);
- return rc;
-}
-
-#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
-
-int TestExpert_Init(Tcl_Interp *interp){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- struct Cmd {
- const char *zCmd;
- Tcl_ObjCmdProc *xProc;
- } aCmd[] = {
- { "sqlite3_expert_new", test_sqlite3_expert_new },
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){
- struct Cmd *p = &aCmd[i];
- Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, 0, 0);
- }
-#endif
- return TCL_OK;
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/README.txt b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/README.txt
deleted file mode 100644
index 292b7daa0b0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This folder contains source code to the first full-text search
-extension for SQLite.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/ft_hash.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/ft_hash.c
deleted file mode 100644
index 8b3a7064eeb..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/ft_hash.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the implementation of generic hash-tables used in SQLite.
-** We've modified it slightly to serve as a standalone hash table
-** implementation for the full-text indexing module.
-*/
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "ft_hash.h"
-
-void *malloc_and_zero(int n){
- void *p = malloc(n);
- if( p ){
- memset(p, 0, n);
- }
- return p;
-}
-
-/* Turn bulk memory into a hash table object by initializing the
-** fields of the Hash structure.
-**
-** "pNew" is a pointer to the hash table that is to be initialized.
-** keyClass is one of the constants HASH_INT, HASH_POINTER,
-** HASH_BINARY, or HASH_STRING. The value of keyClass
-** determines what kind of key the hash table will use. "copyKey" is
-** true if the hash table should make its own private copy of keys and
-** false if it should just use the supplied pointer. CopyKey only makes
-** sense for HASH_STRING and HASH_BINARY and is ignored
-** for other key classes.
-*/
-void HashInit(Hash *pNew, int keyClass, int copyKey){
- assert( pNew!=0 );
- assert( keyClass>=HASH_STRING && keyClass<=HASH_BINARY );
- pNew->keyClass = keyClass;
-#if 0
- if( keyClass==HASH_POINTER || keyClass==HASH_INT ) copyKey = 0;
-#endif
- pNew->copyKey = copyKey;
- pNew->first = 0;
- pNew->count = 0;
- pNew->htsize = 0;
- pNew->ht = 0;
- pNew->xMalloc = malloc_and_zero;
- pNew->xFree = free;
-}
-
-/* Remove all entries from a hash table. Reclaim all memory.
-** Call this routine to delete a hash table or to reset a hash table
-** to the empty state.
-*/
-void HashClear(Hash *pH){
- HashElem *elem; /* For looping over all elements of the table */
-
- assert( pH!=0 );
- elem = pH->first;
- pH->first = 0;
- if( pH->ht ) pH->xFree(pH->ht);
- pH->ht = 0;
- pH->htsize = 0;
- while( elem ){
- HashElem *next_elem = elem->next;
- if( pH->copyKey && elem->pKey ){
- pH->xFree(elem->pKey);
- }
- pH->xFree(elem);
- elem = next_elem;
- }
- pH->count = 0;
-}
-
-#if 0 /* NOT USED */
-/*
-** Hash and comparison functions when the mode is HASH_INT
-*/
-static int intHash(const void *pKey, int nKey){
- return nKey ^ (nKey<<8) ^ (nKey>>8);
-}
-static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- return n2 - n1;
-}
-#endif
-
-#if 0 /* NOT USED */
-/*
-** Hash and comparison functions when the mode is HASH_POINTER
-*/
-static int ptrHash(const void *pKey, int nKey){
- uptr x = Addr(pKey);
- return x ^ (x<<8) ^ (x>>8);
-}
-static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( pKey1==pKey2 ) return 0;
- if( pKey1<pKey2 ) return -1;
- return 1;
-}
-#endif
-
-/*
-** Hash and comparison functions when the mode is HASH_STRING
-*/
-static int strHash(const void *pKey, int nKey){
- const char *z = (const char *)pKey;
- int h = 0;
- if( nKey<=0 ) nKey = (int) strlen(z);
- while( nKey > 0 ){
- h = (h<<3) ^ h ^ *z++;
- nKey--;
- }
- return h & 0x7fffffff;
-}
-static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return strncmp((const char*)pKey1,(const char*)pKey2,n1);
-}
-
-/*
-** Hash and comparison functions when the mode is HASH_BINARY
-*/
-static int binHash(const void *pKey, int nKey){
- int h = 0;
- const char *z = (const char *)pKey;
- while( nKey-- > 0 ){
- h = (h<<3) ^ h ^ *(z++);
- }
- return h & 0x7fffffff;
-}
-static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return memcmp(pKey1,pKey2,n1);
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** The C syntax in this function definition may be unfamilar to some
-** programmers, so we provide the following additional explanation:
-**
-** The name of the function is "hashFunction". The function takes a
-** single parameter "keyClass". The return value of hashFunction()
-** is a pointer to another function. Specifically, the return value
-** of hashFunction() is a pointer to a function that takes two parameters
-** with types "const void*" and "int" and returns an "int".
-*/
-static int (*hashFunction(int keyClass))(const void*,int){
-#if 0 /* HASH_INT and HASH_POINTER are never used */
- switch( keyClass ){
- case HASH_INT: return &intHash;
- case HASH_POINTER: return &ptrHash;
- case HASH_STRING: return &strHash;
- case HASH_BINARY: return &binHash;;
- default: break;
- }
- return 0;
-#else
- if( keyClass==HASH_STRING ){
- return &strHash;
- }else{
- assert( keyClass==HASH_BINARY );
- return &binHash;
- }
-#endif
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** For help in interpreted the obscure C code in the function definition,
-** see the header comment on the previous function.
-*/
-static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
-#if 0 /* HASH_INT and HASH_POINTER are never used */
- switch( keyClass ){
- case HASH_INT: return &intCompare;
- case HASH_POINTER: return &ptrCompare;
- case HASH_STRING: return &strCompare;
- case HASH_BINARY: return &binCompare;
- default: break;
- }
- return 0;
-#else
- if( keyClass==HASH_STRING ){
- return &strCompare;
- }else{
- assert( keyClass==HASH_BINARY );
- return &binCompare;
- }
-#endif
-}
-
-/* Link an element into the hash table
-*/
-static void insertElement(
- Hash *pH, /* The complete hash table */
- struct _ht *pEntry, /* The entry into which pNew is inserted */
- HashElem *pNew /* The element to be inserted */
-){
- HashElem *pHead; /* First element already in pEntry */
- pHead = pEntry->chain;
- if( pHead ){
- pNew->next = pHead;
- pNew->prev = pHead->prev;
- if( pHead->prev ){ pHead->prev->next = pNew; }
- else { pH->first = pNew; }
- pHead->prev = pNew;
- }else{
- pNew->next = pH->first;
- if( pH->first ){ pH->first->prev = pNew; }
- pNew->prev = 0;
- pH->first = pNew;
- }
- pEntry->count++;
- pEntry->chain = pNew;
-}
-
-
-/* Resize the hash table so that it cantains "new_size" buckets.
-** "new_size" must be a power of 2. The hash table might fail
-** to resize if sqliteMalloc() fails.
-*/
-static void rehash(Hash *pH, int new_size){
- struct _ht *new_ht; /* The new hash table */
- HashElem *elem, *next_elem; /* For looping over existing elements */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( (new_size & (new_size-1))==0 );
- new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) );
- if( new_ht==0 ) return;
- if( pH->ht ) pH->xFree(pH->ht);
- pH->ht = new_ht;
- pH->htsize = new_size;
- xHash = hashFunction(pH->keyClass);
- for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
- next_elem = elem->next;
- insertElement(pH, &new_ht[h], elem);
- }
-}
-
-/* This function (for internal use only) locates an element in an
-** hash table that matches the given key. The hash for this key has
-** already been computed and is passed as the 4th parameter.
-*/
-static HashElem *findElementGivenHash(
- const Hash *pH, /* The pH to be searched */
- const void *pKey, /* The key we are searching for */
- int nKey,
- int h /* The hash for this key. */
-){
- HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- int (*xCompare)(const void*,int,const void*,int); /* comparison function */
-
- if( pH->ht ){
- struct _ht *pEntry = &pH->ht[h];
- elem = pEntry->chain;
- count = pEntry->count;
- xCompare = compareFunction(pH->keyClass);
- while( count-- && elem ){
- if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- }
- return 0;
-}
-
-/* Remove a single entry from the hash table given a pointer to that
-** element and a hash on the element's key.
-*/
-static void removeElementGivenHash(
- Hash *pH, /* The pH containing "elem" */
- HashElem* elem, /* The element to be removed from the pH */
- int h /* Hash value for the element */
-){
- struct _ht *pEntry;
- if( elem->prev ){
- elem->prev->next = elem->next;
- }else{
- pH->first = elem->next;
- }
- if( elem->next ){
- elem->next->prev = elem->prev;
- }
- pEntry = &pH->ht[h];
- if( pEntry->chain==elem ){
- pEntry->chain = elem->next;
- }
- pEntry->count--;
- if( pEntry->count<=0 ){
- pEntry->chain = 0;
- }
- if( pH->copyKey && elem->pKey ){
- pH->xFree(elem->pKey);
- }
- pH->xFree( elem );
- pH->count--;
- if( pH->count<=0 ){
- assert( pH->first==0 );
- assert( pH->count==0 );
- HashClear(pH);
- }
-}
-
-/* Attempt to locate an element of the hash table pH with a key
-** that matches pKey,nKey. Return the data for this element if it is
-** found, or NULL if there is no match.
-*/
-void *HashFind(const Hash *pH, const void *pKey, int nKey){
- int h; /* A hash on key */
- HashElem *elem; /* The element that matches key */
- int (*xHash)(const void*,int); /* The hash function */
-
- if( pH==0 || pH->ht==0 ) return 0;
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- h = (*xHash)(pKey,nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
- return elem ? elem->data : 0;
-}
-
-/* Insert an element into the hash table pH. The key is pKey,nKey
-** and the data is "data".
-**
-** If no element exists with a matching key, then a new
-** element is created. A copy of the key is made if the copyKey
-** flag is set. NULL is returned.
-**
-** If another element already exists with the same key, then the
-** new data replaces the old data and the old data is returned.
-** The key is not copied in this instance. If a malloc fails, then
-** the new data is returned and the hash table is unchanged.
-**
-** If the "data" parameter to this function is NULL, then the
-** element corresponding to "key" is removed from the hash table.
-*/
-void *HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
- int hraw; /* Raw hash value of the key */
- int h; /* the hash of the key modulo hash table size */
- HashElem *elem; /* Used to loop thru the element list */
- HashElem *new_elem; /* New element added to the pH */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( pH!=0 );
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- hraw = (*xHash)(pKey, nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = findElementGivenHash(pH,pKey,nKey,h);
- if( elem ){
- void *old_data = elem->data;
- if( data==0 ){
- removeElementGivenHash(pH,elem,h);
- }else{
- elem->data = data;
- }
- return old_data;
- }
- if( data==0 ) return 0;
- new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) );
- if( new_elem==0 ) return data;
- if( pH->copyKey && pKey!=0 ){
- new_elem->pKey = pH->xMalloc( nKey );
- if( new_elem->pKey==0 ){
- pH->xFree(new_elem);
- return data;
- }
- memcpy((void*)new_elem->pKey, pKey, nKey);
- }else{
- new_elem->pKey = (void*)pKey;
- }
- new_elem->nKey = nKey;
- pH->count++;
- if( pH->htsize==0 ){
- rehash(pH,8);
- if( pH->htsize==0 ){
- pH->count = 0;
- pH->xFree(new_elem);
- return data;
- }
- }
- if( pH->count > pH->htsize ){
- rehash(pH,pH->htsize*2);
- }
- assert( pH->htsize>0 );
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- insertElement(pH, &pH->ht[h], new_elem);
- new_elem->data = data;
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/ft_hash.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/ft_hash.h
deleted file mode 100644
index 95871a4590c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/ft_hash.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the header file for the generic hash-table implementation
-** used in SQLite. We've modified it slightly to serve as a standalone
-** hash table implementation for the full-text indexing module.
-**
-*/
-#ifndef _HASH_H_
-#define _HASH_H_
-
-/* Forward declarations of structures. */
-typedef struct Hash Hash;
-typedef struct HashElem HashElem;
-
-/* A complete hash table is an instance of the following structure.
-** The internals of this structure are intended to be opaque -- client
-** code should not attempt to access or modify the fields of this structure
-** directly. Change this structure only by using the routines below.
-** However, many of the "procedures" and "functions" for modifying and
-** accessing this structure are really macros, so we can't really make
-** this structure opaque.
-*/
-struct Hash {
- char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */
- char copyKey; /* True if copy of key made on insert */
- int count; /* Number of entries in this table */
- HashElem *first; /* The first element of the array */
- void *(*xMalloc)(int); /* malloc() function to use */
- void (*xFree)(void *); /* free() function to use */
- int htsize; /* Number of buckets in the hash table */
- struct _ht { /* the hash table */
- int count; /* Number of entries with this hash */
- HashElem *chain; /* Pointer to first entry with this hash */
- } *ht;
-};
-
-/* Each element in the hash table is an instance of the following
-** structure. All elements are stored on a single doubly-linked list.
-**
-** Again, this structure is intended to be opaque, but it can't really
-** be opaque because it is used by macros.
-*/
-struct HashElem {
- HashElem *next, *prev; /* Next and previous elements in the table */
- void *data; /* Data associated with this element */
- void *pKey; int nKey; /* Key associated with this element */
-};
-
-/*
-** There are 4 different modes of operation for a hash table:
-**
-** HASH_INT nKey is used as the key and pKey is ignored.
-**
-** HASH_POINTER pKey is used as the key and nKey is ignored.
-**
-** HASH_STRING pKey points to a string that is nKey bytes long
-** (including the null-terminator, if any). Case
-** is respected in comparisons.
-**
-** HASH_BINARY pKey points to binary data nKey bytes long.
-** memcmp() is used to compare keys.
-**
-** A copy of the key is made for HASH_STRING and HASH_BINARY
-** if the copyKey parameter to HashInit is 1.
-*/
-/* #define HASH_INT 1 // NOT USED */
-/* #define HASH_POINTER 2 // NOT USED */
-#define HASH_STRING 3
-#define HASH_BINARY 4
-
-/*
-** Access routines. To delete, insert a NULL pointer.
-*/
-void HashInit(Hash*, int keytype, int copyKey);
-void *HashInsert(Hash*, const void *pKey, int nKey, void *pData);
-void *HashFind(const Hash*, const void *pKey, int nKey);
-void HashClear(Hash*);
-
-/*
-** Macros for looping over all elements of a hash table. The idiom is
-** like this:
-**
-** Hash h;
-** HashElem *p;
-** ...
-** for(p=HashFirst(&h); p; p=HashNext(p)){
-** SomeStructure *pData = HashData(p);
-** // do something with pData
-** }
-*/
-#define HashFirst(H) ((H)->first)
-#define HashNext(E) ((E)->next)
-#define HashData(E) ((E)->data)
-#define HashKey(E) ((E)->pKey)
-#define HashKeysize(E) ((E)->nKey)
-
-/*
-** Number of entries in a hash table
-*/
-#define HashCount(H) ((H)->count)
-
-#endif /* _HASH_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1.c
deleted file mode 100644
index 77fa9e23f59..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1.c
+++ /dev/null
@@ -1,3348 +0,0 @@
-/* fts1 has a design flaw which can lead to database corruption (see
-** below). It is recommended not to use it any longer, instead use
-** fts3 (or higher). If you believe that your use of fts1 is safe,
-** add -DSQLITE_ENABLE_BROKEN_FTS1=1 to your CFLAGS.
-*/
-#if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)) \
- && !defined(SQLITE_ENABLE_BROKEN_FTS1)
-#error fts1 has a design flaw and has been deprecated.
-#endif
-/* The flaw is that fts1 uses the content table's unaliased rowid as
-** the unique docid. fts1 embeds the rowid in the index it builds,
-** and expects the rowid to not change. The SQLite VACUUM operation
-** will renumber such rowids, thereby breaking fts1. If you are using
-** fts1 in a system which has disabled VACUUM, then you can continue
-** to use it safely. Note that PRAGMA auto_vacuum does NOT disable
-** VACUUM, though systems using auto_vacuum are unlikely to invoke
-** VACUUM.
-**
-** fts1 should be safe even across VACUUM if you only insert documents
-** and never delete.
-*/
-
-/* The author disclaims copyright to this source code.
- *
- * This is an SQLite module implementing full-text search.
- */
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS1 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS1 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)
-
-#if defined(SQLITE_ENABLE_FTS1) && !defined(SQLITE_CORE)
-# define SQLITE_CORE 1
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "fts1.h"
-#include "fts1_hash.h"
-#include "fts1_tokenizer.h"
-#include "sqlite3.h"
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-
-#if 0
-# define TRACE(A) printf A; fflush(stdout)
-#else
-# define TRACE(A)
-#endif
-
-/* utility functions */
-
-typedef struct StringBuffer {
- int len; /* length, not including null terminator */
- int alloced; /* Space allocated for s[] */
- char *s; /* Content of the string */
-} StringBuffer;
-
-static void initStringBuffer(StringBuffer *sb){
- sb->len = 0;
- sb->alloced = 100;
- sb->s = malloc(100);
- sb->s[0] = '\0';
-}
-
-static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){
- if( sb->len + nFrom >= sb->alloced ){
- sb->alloced = sb->len + nFrom + 100;
- sb->s = realloc(sb->s, sb->alloced+1);
- if( sb->s==0 ){
- initStringBuffer(sb);
- return;
- }
- }
- memcpy(sb->s + sb->len, zFrom, nFrom);
- sb->len += nFrom;
- sb->s[sb->len] = 0;
-}
-static void append(StringBuffer *sb, const char *zFrom){
- nappend(sb, zFrom, strlen(zFrom));
-}
-
-/* We encode variable-length integers in little-endian order using seven bits
- * per byte as follows:
-**
-** KEY:
-** A = 0xxxxxxx 7 bits of data and one flag bit
-** B = 1xxxxxxx 7 bits of data and one flag bit
-**
-** 7 bits - A
-** 14 bits - BA
-** 21 bits - BBA
-** and so on.
-*/
-
-/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */
-#define VARINT_MAX 10
-
-/* Write a 64-bit variable-length integer to memory starting at p[0].
- * The length of data written will be between 1 and VARINT_MAX bytes.
- * The number of bytes written is returned. */
-static int putVarint(char *p, sqlite_int64 v){
- unsigned char *q = (unsigned char *) p;
- sqlite_uint64 vu = v;
- do{
- *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
- vu >>= 7;
- }while( vu!=0 );
- q[-1] &= 0x7f; /* turn off high bit in final byte */
- assert( q - (unsigned char *)p <= VARINT_MAX );
- return (int) (q - (unsigned char *)p);
-}
-
-/* Read a 64-bit variable-length integer from memory starting at p[0].
- * Return the number of bytes read, or 0 on error.
- * The value is stored in *v. */
-static int getVarint(const char *p, sqlite_int64 *v){
- const unsigned char *q = (const unsigned char *) p;
- sqlite_uint64 x = 0, y = 1;
- while( (*q & 0x80) == 0x80 ){
- x += y * (*q++ & 0x7f);
- y <<= 7;
- if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */
- assert( 0 );
- return 0;
- }
- }
- x += y * (*q++);
- *v = (sqlite_int64) x;
- return (int) (q - (unsigned char *)p);
-}
-
-static int getVarint32(const char *p, int *pi){
- sqlite_int64 i;
- int ret = getVarint(p, &i);
- *pi = (int) i;
- assert( *pi==i );
- return ret;
-}
-
-/*** Document lists ***
- *
- * A document list holds a sorted list of varint-encoded document IDs.
- *
- * A doclist with type DL_POSITIONS_OFFSETS is stored like this:
- *
- * array {
- * varint docid;
- * array {
- * varint position; (delta from previous position plus POS_BASE)
- * varint startOffset; (delta from previous startOffset)
- * varint endOffset; (delta from startOffset)
- * }
- * }
- *
- * Here, array { X } means zero or more occurrences of X, adjacent in memory.
- *
- * A position list may hold positions for text in multiple columns. A position
- * POS_COLUMN is followed by a varint containing the index of the column for
- * following positions in the list. Any positions appearing before any
- * occurrences of POS_COLUMN are for column 0.
- *
- * A doclist with type DL_POSITIONS is like the above, but holds only docids
- * and positions without offset information.
- *
- * A doclist with type DL_DOCIDS is like the above, but holds only docids
- * without positions or offset information.
- *
- * On disk, every document list has positions and offsets, so we don't bother
- * to serialize a doclist's type.
- *
- * We don't yet delta-encode document IDs; doing so will probably be a
- * modest win.
- *
- * NOTE(shess) I've thought of a slightly (1%) better offset encoding.
- * After the first offset, estimate the next offset by using the
- * current token position and the previous token position and offset,
- * offset to handle some variance. So the estimate would be
- * (iPosition*w->iStartOffset/w->iPosition-64), which is delta-encoded
- * as normal. Offsets more than 64 chars from the estimate are
- * encoded as the delta to the previous start offset + 128. An
- * additional tiny increment can be gained by using the end offset of
- * the previous token to make the estimate a tiny bit more precise.
-*/
-
-/* It is not safe to call isspace(), tolower(), or isalnum() on
-** hi-bit-set characters. This is the same solution used in the
-** tokenizer.
-*/
-/* TODO(shess) The snippet-generation code should be using the
-** tokenizer-generated tokens rather than doing its own local
-** tokenization.
-*/
-/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */
-static int safe_isspace(char c){
- return (c&0x80)==0 ? isspace((unsigned char)c) : 0;
-}
-static int safe_tolower(char c){
- return (c&0x80)==0 ? tolower((unsigned char)c) : c;
-}
-static int safe_isalnum(char c){
- return (c&0x80)==0 ? isalnum((unsigned char)c) : 0;
-}
-
-typedef enum DocListType {
- DL_DOCIDS, /* docids only */
- DL_POSITIONS, /* docids + positions */
- DL_POSITIONS_OFFSETS /* docids + positions + offsets */
-} DocListType;
-
-/*
-** By default, only positions and not offsets are stored in the doclists.
-** To change this so that offsets are stored too, compile with
-**
-** -DDL_DEFAULT=DL_POSITIONS_OFFSETS
-**
-*/
-#ifndef DL_DEFAULT
-# define DL_DEFAULT DL_POSITIONS
-#endif
-
-typedef struct DocList {
- char *pData;
- int nData;
- DocListType iType;
- int iLastColumn; /* the last column written */
- int iLastPos; /* the last position written */
- int iLastOffset; /* the last start offset written */
-} DocList;
-
-enum {
- POS_END = 0, /* end of this position list */
- POS_COLUMN, /* followed by new column number */
- POS_BASE
-};
-
-/* Initialize a new DocList to hold the given data. */
-static void docListInit(DocList *d, DocListType iType,
- const char *pData, int nData){
- d->nData = nData;
- if( nData>0 ){
- d->pData = malloc(nData);
- memcpy(d->pData, pData, nData);
- } else {
- d->pData = NULL;
- }
- d->iType = iType;
- d->iLastColumn = 0;
- d->iLastPos = d->iLastOffset = 0;
-}
-
-/* Create a new dynamically-allocated DocList. */
-static DocList *docListNew(DocListType iType){
- DocList *d = (DocList *) malloc(sizeof(DocList));
- docListInit(d, iType, 0, 0);
- return d;
-}
-
-static void docListDestroy(DocList *d){
- free(d->pData);
-#ifndef NDEBUG
- memset(d, 0x55, sizeof(*d));
-#endif
-}
-
-static void docListDelete(DocList *d){
- docListDestroy(d);
- free(d);
-}
-
-static char *docListEnd(DocList *d){
- return d->pData + d->nData;
-}
-
-/* Append a varint to a DocList's data. */
-static void appendVarint(DocList *d, sqlite_int64 i){
- char c[VARINT_MAX];
- int n = putVarint(c, i);
- d->pData = realloc(d->pData, d->nData + n);
- memcpy(d->pData + d->nData, c, n);
- d->nData += n;
-}
-
-static void docListAddDocid(DocList *d, sqlite_int64 iDocid){
- appendVarint(d, iDocid);
- if( d->iType>=DL_POSITIONS ){
- appendVarint(d, POS_END); /* initially empty position list */
- d->iLastColumn = 0;
- d->iLastPos = d->iLastOffset = 0;
- }
-}
-
-/* helper function for docListAddPos and docListAddPosOffset */
-static void addPos(DocList *d, int iColumn, int iPos){
- assert( d->nData>0 );
- --d->nData; /* remove previous terminator */
- if( iColumn!=d->iLastColumn ){
- assert( iColumn>d->iLastColumn );
- appendVarint(d, POS_COLUMN);
- appendVarint(d, iColumn);
- d->iLastColumn = iColumn;
- d->iLastPos = d->iLastOffset = 0;
- }
- assert( iPos>=d->iLastPos );
- appendVarint(d, iPos-d->iLastPos+POS_BASE);
- d->iLastPos = iPos;
-}
-
-/* Add a position to the last position list in a doclist. */
-static void docListAddPos(DocList *d, int iColumn, int iPos){
- assert( d->iType==DL_POSITIONS );
- addPos(d, iColumn, iPos);
- appendVarint(d, POS_END); /* add new terminator */
-}
-
-/*
-** Add a position and starting and ending offsets to a doclist.
-**
-** If the doclist is setup to handle only positions, then insert
-** the position only and ignore the offsets.
-*/
-static void docListAddPosOffset(
- DocList *d, /* Doclist under construction */
- int iColumn, /* Column the inserted term is part of */
- int iPos, /* Position of the inserted term */
- int iStartOffset, /* Starting offset of inserted term */
- int iEndOffset /* Ending offset of inserted term */
-){
- assert( d->iType>=DL_POSITIONS );
- addPos(d, iColumn, iPos);
- if( d->iType==DL_POSITIONS_OFFSETS ){
- assert( iStartOffset>=d->iLastOffset );
- appendVarint(d, iStartOffset-d->iLastOffset);
- d->iLastOffset = iStartOffset;
- assert( iEndOffset>=iStartOffset );
- appendVarint(d, iEndOffset-iStartOffset);
- }
- appendVarint(d, POS_END); /* add new terminator */
-}
-
-/*
-** A DocListReader object is a cursor into a doclist. Initialize
-** the cursor to the beginning of the doclist by calling readerInit().
-** Then use routines
-**
-** peekDocid()
-** readDocid()
-** readPosition()
-** skipPositionList()
-** and so forth...
-**
-** to read information out of the doclist. When we reach the end
-** of the doclist, atEnd() returns TRUE.
-*/
-typedef struct DocListReader {
- DocList *pDoclist; /* The document list we are stepping through */
- char *p; /* Pointer to next unread byte in the doclist */
- int iLastColumn;
- int iLastPos; /* the last position read, or -1 when not in a position list */
-} DocListReader;
-
-/*
-** Initialize the DocListReader r to point to the beginning of pDoclist.
-*/
-static void readerInit(DocListReader *r, DocList *pDoclist){
- r->pDoclist = pDoclist;
- if( pDoclist!=NULL ){
- r->p = pDoclist->pData;
- }
- r->iLastColumn = -1;
- r->iLastPos = -1;
-}
-
-/*
-** Return TRUE if we have reached then end of pReader and there is
-** nothing else left to read.
-*/
-static int atEnd(DocListReader *pReader){
- return pReader->pDoclist==0 || (pReader->p >= docListEnd(pReader->pDoclist));
-}
-
-/* Peek at the next docid without advancing the read pointer.
-*/
-static sqlite_int64 peekDocid(DocListReader *pReader){
- sqlite_int64 ret;
- assert( !atEnd(pReader) );
- assert( pReader->iLastPos==-1 );
- getVarint(pReader->p, &ret);
- return ret;
-}
-
-/* Read the next docid. See also nextDocid().
-*/
-static sqlite_int64 readDocid(DocListReader *pReader){
- sqlite_int64 ret;
- assert( !atEnd(pReader) );
- assert( pReader->iLastPos==-1 );
- pReader->p += getVarint(pReader->p, &ret);
- if( pReader->pDoclist->iType>=DL_POSITIONS ){
- pReader->iLastColumn = 0;
- pReader->iLastPos = 0;
- }
- return ret;
-}
-
-/* Read the next position and column index from a position list.
- * Returns the position, or -1 at the end of the list. */
-static int readPosition(DocListReader *pReader, int *iColumn){
- int i;
- int iType = pReader->pDoclist->iType;
-
- if( pReader->iLastPos==-1 ){
- return -1;
- }
- assert( !atEnd(pReader) );
-
- if( iType<DL_POSITIONS ){
- return -1;
- }
- pReader->p += getVarint32(pReader->p, &i);
- if( i==POS_END ){
- pReader->iLastColumn = pReader->iLastPos = -1;
- *iColumn = -1;
- return -1;
- }
- if( i==POS_COLUMN ){
- pReader->p += getVarint32(pReader->p, &pReader->iLastColumn);
- pReader->iLastPos = 0;
- pReader->p += getVarint32(pReader->p, &i);
- assert( i>=POS_BASE );
- }
- pReader->iLastPos += ((int) i)-POS_BASE;
- if( iType>=DL_POSITIONS_OFFSETS ){
- /* Skip over offsets, ignoring them for now. */
- int iStart, iEnd;
- pReader->p += getVarint32(pReader->p, &iStart);
- pReader->p += getVarint32(pReader->p, &iEnd);
- }
- *iColumn = pReader->iLastColumn;
- return pReader->iLastPos;
-}
-
-/* Skip past the end of a position list. */
-static void skipPositionList(DocListReader *pReader){
- DocList *p = pReader->pDoclist;
- if( p && p->iType>=DL_POSITIONS ){
- int iColumn;
- while( readPosition(pReader, &iColumn)!=-1 ){}
- }
-}
-
-/* Skip over a docid, including its position list if the doclist has
- * positions. */
-static void skipDocument(DocListReader *pReader){
- readDocid(pReader);
- skipPositionList(pReader);
-}
-
-/* Skip past all docids which are less than [iDocid]. Returns 1 if a docid
- * matching [iDocid] was found. */
-static int skipToDocid(DocListReader *pReader, sqlite_int64 iDocid){
- sqlite_int64 d = 0;
- while( !atEnd(pReader) && (d=peekDocid(pReader))<iDocid ){
- skipDocument(pReader);
- }
- return !atEnd(pReader) && d==iDocid;
-}
-
-/* Return the first document in a document list.
-*/
-static sqlite_int64 firstDocid(DocList *d){
- DocListReader r;
- readerInit(&r, d);
- return readDocid(&r);
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** This routine is used for debugging purpose only.
-**
-** Write the content of a doclist to standard output.
-*/
-static void printDoclist(DocList *p){
- DocListReader r;
- const char *zSep = "";
-
- readerInit(&r, p);
- while( !atEnd(&r) ){
- sqlite_int64 docid = readDocid(&r);
- if( docid==0 ){
- skipPositionList(&r);
- continue;
- }
- printf("%s%lld", zSep, docid);
- zSep = ",";
- if( p->iType>=DL_POSITIONS ){
- int iPos, iCol;
- const char *zDiv = "";
- printf("(");
- while( (iPos = readPosition(&r, &iCol))>=0 ){
- printf("%s%d:%d", zDiv, iCol, iPos);
- zDiv = ":";
- }
- printf(")");
- }
- }
- printf("\n");
- fflush(stdout);
-}
-#endif /* SQLITE_DEBUG */
-
-/* Trim the given doclist to contain only positions in column
- * [iRestrictColumn]. */
-static void docListRestrictColumn(DocList *in, int iRestrictColumn){
- DocListReader r;
- DocList out;
-
- assert( in->iType>=DL_POSITIONS );
- readerInit(&r, in);
- docListInit(&out, DL_POSITIONS, NULL, 0);
-
- while( !atEnd(&r) ){
- sqlite_int64 iDocid = readDocid(&r);
- int iPos, iColumn;
-
- docListAddDocid(&out, iDocid);
- while( (iPos = readPosition(&r, &iColumn)) != -1 ){
- if( iColumn==iRestrictColumn ){
- docListAddPos(&out, iColumn, iPos);
- }
- }
- }
-
- docListDestroy(in);
- *in = out;
-}
-
-/* Trim the given doclist by discarding any docids without any remaining
- * positions. */
-static void docListDiscardEmpty(DocList *in) {
- DocListReader r;
- DocList out;
-
- /* TODO: It would be nice to implement this operation in place; that
- * could save a significant amount of memory in queries with long doclists. */
- assert( in->iType>=DL_POSITIONS );
- readerInit(&r, in);
- docListInit(&out, DL_POSITIONS, NULL, 0);
-
- while( !atEnd(&r) ){
- sqlite_int64 iDocid = readDocid(&r);
- int match = 0;
- int iPos, iColumn;
- while( (iPos = readPosition(&r, &iColumn)) != -1 ){
- if( !match ){
- docListAddDocid(&out, iDocid);
- match = 1;
- }
- docListAddPos(&out, iColumn, iPos);
- }
- }
-
- docListDestroy(in);
- *in = out;
-}
-
-/* Helper function for docListUpdate() and docListAccumulate().
-** Splices a doclist element into the doclist represented by r,
-** leaving r pointing after the newly spliced element.
-*/
-static void docListSpliceElement(DocListReader *r, sqlite_int64 iDocid,
- const char *pSource, int nSource){
- DocList *d = r->pDoclist;
- char *pTarget;
- int nTarget, found;
-
- found = skipToDocid(r, iDocid);
-
- /* Describe slice in d to place pSource/nSource. */
- pTarget = r->p;
- if( found ){
- skipDocument(r);
- nTarget = r->p-pTarget;
- }else{
- nTarget = 0;
- }
-
- /* The sense of the following is that there are three possibilities.
- ** If nTarget==nSource, we should not move any memory nor realloc.
- ** If nTarget>nSource, trim target and realloc.
- ** If nTarget<nSource, realloc then expand target.
- */
- if( nTarget>nSource ){
- memmove(pTarget+nSource, pTarget+nTarget, docListEnd(d)-(pTarget+nTarget));
- }
- if( nTarget!=nSource ){
- int iDoclist = pTarget-d->pData;
- d->pData = realloc(d->pData, d->nData+nSource-nTarget);
- pTarget = d->pData+iDoclist;
- }
- if( nTarget<nSource ){
- memmove(pTarget+nSource, pTarget+nTarget, docListEnd(d)-(pTarget+nTarget));
- }
-
- memcpy(pTarget, pSource, nSource);
- d->nData += nSource-nTarget;
- r->p = pTarget+nSource;
-}
-
-/* Insert/update pUpdate into the doclist. */
-static void docListUpdate(DocList *d, DocList *pUpdate){
- DocListReader reader;
-
- assert( d!=NULL && pUpdate!=NULL );
- assert( d->iType==pUpdate->iType);
-
- readerInit(&reader, d);
- docListSpliceElement(&reader, firstDocid(pUpdate),
- pUpdate->pData, pUpdate->nData);
-}
-
-/* Propagate elements from pUpdate to pAcc, overwriting elements with
-** matching docids.
-*/
-static void docListAccumulate(DocList *pAcc, DocList *pUpdate){
- DocListReader accReader, updateReader;
-
- /* Handle edge cases where one doclist is empty. */
- assert( pAcc!=NULL );
- if( pUpdate==NULL || pUpdate->nData==0 ) return;
- if( pAcc->nData==0 ){
- pAcc->pData = malloc(pUpdate->nData);
- memcpy(pAcc->pData, pUpdate->pData, pUpdate->nData);
- pAcc->nData = pUpdate->nData;
- return;
- }
-
- readerInit(&accReader, pAcc);
- readerInit(&updateReader, pUpdate);
-
- while( !atEnd(&updateReader) ){
- char *pSource = updateReader.p;
- sqlite_int64 iDocid = readDocid(&updateReader);
- skipPositionList(&updateReader);
- docListSpliceElement(&accReader, iDocid, pSource, updateReader.p-pSource);
- }
-}
-
-/*
-** Read the next docid off of pIn. Return 0 if we reach the end.
-*
-* TODO: This assumes that docids are never 0, but they may actually be 0 since
-* users can choose docids when inserting into a full-text table. Fix this.
-*/
-static sqlite_int64 nextDocid(DocListReader *pIn){
- skipPositionList(pIn);
- return atEnd(pIn) ? 0 : readDocid(pIn);
-}
-
-/*
-** pLeft and pRight are two DocListReaders that are pointing to
-** positions lists of the same document: iDocid.
-**
-** If there are no instances in pLeft or pRight where the position
-** of pLeft is one less than the position of pRight, then this
-** routine adds nothing to pOut.
-**
-** If there are one or more instances where positions from pLeft
-** are exactly one less than positions from pRight, then add a new
-** document record to pOut. If pOut wants to hold positions, then
-** include the positions from pRight that are one more than a
-** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1.
-**
-** pLeft and pRight are left pointing at the next document record.
-*/
-static void mergePosList(
- DocListReader *pLeft, /* Left position list */
- DocListReader *pRight, /* Right position list */
- sqlite_int64 iDocid, /* The docid from pLeft and pRight */
- DocList *pOut /* Write the merged document record here */
-){
- int iLeftCol, iLeftPos = readPosition(pLeft, &iLeftCol);
- int iRightCol, iRightPos = readPosition(pRight, &iRightCol);
- int match = 0;
-
- /* Loop until we've reached the end of both position lists. */
- while( iLeftPos!=-1 && iRightPos!=-1 ){
- if( iLeftCol==iRightCol && iLeftPos+1==iRightPos ){
- if( !match ){
- docListAddDocid(pOut, iDocid);
- match = 1;
- }
- if( pOut->iType>=DL_POSITIONS ){
- docListAddPos(pOut, iRightCol, iRightPos);
- }
- iLeftPos = readPosition(pLeft, &iLeftCol);
- iRightPos = readPosition(pRight, &iRightCol);
- }else if( iRightCol<iLeftCol ||
- (iRightCol==iLeftCol && iRightPos<iLeftPos+1) ){
- iRightPos = readPosition(pRight, &iRightCol);
- }else{
- iLeftPos = readPosition(pLeft, &iLeftCol);
- }
- }
- if( iLeftPos>=0 ) skipPositionList(pLeft);
- if( iRightPos>=0 ) skipPositionList(pRight);
-}
-
-/* We have two doclists: pLeft and pRight.
-** Write the phrase intersection of these two doclists into pOut.
-**
-** A phrase intersection means that two documents only match
-** if pLeft.iPos+1==pRight.iPos.
-**
-** The output pOut may or may not contain positions. If pOut
-** does contain positions, they are the positions of pRight.
-*/
-static void docListPhraseMerge(
- DocList *pLeft, /* Doclist resulting from the words on the left */
- DocList *pRight, /* Doclist for the next word to the right */
- DocList *pOut /* Write the combined doclist here */
-){
- DocListReader left, right;
- sqlite_int64 docidLeft, docidRight;
-
- readerInit(&left, pLeft);
- readerInit(&right, pRight);
- docidLeft = nextDocid(&left);
- docidRight = nextDocid(&right);
-
- while( docidLeft>0 && docidRight>0 ){
- if( docidLeft<docidRight ){
- docidLeft = nextDocid(&left);
- }else if( docidRight<docidLeft ){
- docidRight = nextDocid(&right);
- }else{
- mergePosList(&left, &right, docidLeft, pOut);
- docidLeft = nextDocid(&left);
- docidRight = nextDocid(&right);
- }
- }
-}
-
-/* We have two doclists: pLeft and pRight.
-** Write the intersection of these two doclists into pOut.
-** Only docids are matched. Position information is ignored.
-**
-** The output pOut never holds positions.
-*/
-static void docListAndMerge(
- DocList *pLeft, /* Doclist resulting from the words on the left */
- DocList *pRight, /* Doclist for the next word to the right */
- DocList *pOut /* Write the combined doclist here */
-){
- DocListReader left, right;
- sqlite_int64 docidLeft, docidRight;
-
- assert( pOut->iType<DL_POSITIONS );
-
- readerInit(&left, pLeft);
- readerInit(&right, pRight);
- docidLeft = nextDocid(&left);
- docidRight = nextDocid(&right);
-
- while( docidLeft>0 && docidRight>0 ){
- if( docidLeft<docidRight ){
- docidLeft = nextDocid(&left);
- }else if( docidRight<docidLeft ){
- docidRight = nextDocid(&right);
- }else{
- docListAddDocid(pOut, docidLeft);
- docidLeft = nextDocid(&left);
- docidRight = nextDocid(&right);
- }
- }
-}
-
-/* We have two doclists: pLeft and pRight.
-** Write the union of these two doclists into pOut.
-** Only docids are matched. Position information is ignored.
-**
-** The output pOut never holds positions.
-*/
-static void docListOrMerge(
- DocList *pLeft, /* Doclist resulting from the words on the left */
- DocList *pRight, /* Doclist for the next word to the right */
- DocList *pOut /* Write the combined doclist here */
-){
- DocListReader left, right;
- sqlite_int64 docidLeft, docidRight, priorLeft;
-
- readerInit(&left, pLeft);
- readerInit(&right, pRight);
- docidLeft = nextDocid(&left);
- docidRight = nextDocid(&right);
-
- while( docidLeft>0 && docidRight>0 ){
- if( docidLeft<=docidRight ){
- docListAddDocid(pOut, docidLeft);
- }else{
- docListAddDocid(pOut, docidRight);
- }
- priorLeft = docidLeft;
- if( docidLeft<=docidRight ){
- docidLeft = nextDocid(&left);
- }
- if( docidRight>0 && docidRight<=priorLeft ){
- docidRight = nextDocid(&right);
- }
- }
- while( docidLeft>0 ){
- docListAddDocid(pOut, docidLeft);
- docidLeft = nextDocid(&left);
- }
- while( docidRight>0 ){
- docListAddDocid(pOut, docidRight);
- docidRight = nextDocid(&right);
- }
-}
-
-/* We have two doclists: pLeft and pRight.
-** Write into pOut all documents that occur in pLeft but not
-** in pRight.
-**
-** Only docids are matched. Position information is ignored.
-**
-** The output pOut never holds positions.
-*/
-static void docListExceptMerge(
- DocList *pLeft, /* Doclist resulting from the words on the left */
- DocList *pRight, /* Doclist for the next word to the right */
- DocList *pOut /* Write the combined doclist here */
-){
- DocListReader left, right;
- sqlite_int64 docidLeft, docidRight, priorLeft;
-
- readerInit(&left, pLeft);
- readerInit(&right, pRight);
- docidLeft = nextDocid(&left);
- docidRight = nextDocid(&right);
-
- while( docidLeft>0 && docidRight>0 ){
- priorLeft = docidLeft;
- if( docidLeft<docidRight ){
- docListAddDocid(pOut, docidLeft);
- }
- if( docidLeft<=docidRight ){
- docidLeft = nextDocid(&left);
- }
- if( docidRight>0 && docidRight<=priorLeft ){
- docidRight = nextDocid(&right);
- }
- }
- while( docidLeft>0 ){
- docListAddDocid(pOut, docidLeft);
- docidLeft = nextDocid(&left);
- }
-}
-
-static char *string_dup_n(const char *s, int n){
- char *str = malloc(n + 1);
- memcpy(str, s, n);
- str[n] = '\0';
- return str;
-}
-
-/* Duplicate a string; the caller must free() the returned string.
- * (We don't use strdup() since it is not part of the standard C library and
- * may not be available everywhere.) */
-static char *string_dup(const char *s){
- return string_dup_n(s, strlen(s));
-}
-
-/* Format a string, replacing each occurrence of the % character with
- * zDb.zName. This may be more convenient than sqlite_mprintf()
- * when one string is used repeatedly in a format string.
- * The caller must free() the returned string. */
-static char *string_format(const char *zFormat,
- const char *zDb, const char *zName){
- const char *p;
- size_t len = 0;
- size_t nDb = strlen(zDb);
- size_t nName = strlen(zName);
- size_t nFullTableName = nDb+1+nName;
- char *result;
- char *r;
-
- /* first compute length needed */
- for(p = zFormat ; *p ; ++p){
- len += (*p=='%' ? nFullTableName : 1);
- }
- len += 1; /* for null terminator */
-
- r = result = malloc(len);
- for(p = zFormat; *p; ++p){
- if( *p=='%' ){
- memcpy(r, zDb, nDb);
- r += nDb;
- *r++ = '.';
- memcpy(r, zName, nName);
- r += nName;
- } else {
- *r++ = *p;
- }
- }
- *r++ = '\0';
- assert( r == result + len );
- return result;
-}
-
-static int sql_exec(sqlite3 *db, const char *zDb, const char *zName,
- const char *zFormat){
- char *zCommand = string_format(zFormat, zDb, zName);
- int rc;
- TRACE(("FTS1 sql: %s\n", zCommand));
- rc = sqlite3_exec(db, zCommand, NULL, 0, NULL);
- free(zCommand);
- return rc;
-}
-
-static int sql_prepare(sqlite3 *db, const char *zDb, const char *zName,
- sqlite3_stmt **ppStmt, const char *zFormat){
- char *zCommand = string_format(zFormat, zDb, zName);
- int rc;
- TRACE(("FTS1 prepare: %s\n", zCommand));
- rc = sqlite3_prepare(db, zCommand, -1, ppStmt, NULL);
- free(zCommand);
- return rc;
-}
-
-/* end utility functions */
-
-/* Forward reference */
-typedef struct fulltext_vtab fulltext_vtab;
-
-/* A single term in a query is represented by an instances of
-** the following structure.
-*/
-typedef struct QueryTerm {
- short int nPhrase; /* How many following terms are part of the same phrase */
- short int iPhrase; /* This is the i-th term of a phrase. */
- short int iColumn; /* Column of the index that must match this term */
- signed char isOr; /* this term is preceded by "OR" */
- signed char isNot; /* this term is preceded by "-" */
- char *pTerm; /* text of the term. '\000' terminated. malloced */
- int nTerm; /* Number of bytes in pTerm[] */
-} QueryTerm;
-
-
-/* A query string is parsed into a Query structure.
- *
- * We could, in theory, allow query strings to be complicated
- * nested expressions with precedence determined by parentheses.
- * But none of the major search engines do this. (Perhaps the
- * feeling is that an parenthesized expression is two complex of
- * an idea for the average user to grasp.) Taking our lead from
- * the major search engines, we will allow queries to be a list
- * of terms (with an implied AND operator) or phrases in double-quotes,
- * with a single optional "-" before each non-phrase term to designate
- * negation and an optional OR connector.
- *
- * OR binds more tightly than the implied AND, which is what the
- * major search engines seem to do. So, for example:
- *
- * [one two OR three] ==> one AND (two OR three)
- * [one OR two three] ==> (one OR two) AND three
- *
- * A "-" before a term matches all entries that lack that term.
- * The "-" must occur immediately before the term with in intervening
- * space. This is how the search engines do it.
- *
- * A NOT term cannot be the right-hand operand of an OR. If this
- * occurs in the query string, the NOT is ignored:
- *
- * [one OR -two] ==> one OR two
- *
- */
-typedef struct Query {
- fulltext_vtab *pFts; /* The full text index */
- int nTerms; /* Number of terms in the query */
- QueryTerm *pTerms; /* Array of terms. Space obtained from malloc() */
- int nextIsOr; /* Set the isOr flag on the next inserted term */
- int nextColumn; /* Next word parsed must be in this column */
- int dfltColumn; /* The default column */
-} Query;
-
-
-/*
-** An instance of the following structure keeps track of generated
-** matching-word offset information and snippets.
-*/
-typedef struct Snippet {
- int nMatch; /* Total number of matches */
- int nAlloc; /* Space allocated for aMatch[] */
- struct snippetMatch { /* One entry for each matching term */
- char snStatus; /* Status flag for use while constructing snippets */
- short int iCol; /* The column that contains the match */
- short int iTerm; /* The index in Query.pTerms[] of the matching term */
- short int nByte; /* Number of bytes in the term */
- int iStart; /* The offset to the first character of the term */
- } *aMatch; /* Points to space obtained from malloc */
- char *zOffset; /* Text rendering of aMatch[] */
- int nOffset; /* strlen(zOffset) */
- char *zSnippet; /* Snippet text */
- int nSnippet; /* strlen(zSnippet) */
-} Snippet;
-
-
-typedef enum QueryType {
- QUERY_GENERIC, /* table scan */
- QUERY_ROWID, /* lookup by rowid */
- QUERY_FULLTEXT /* QUERY_FULLTEXT + [i] is a full-text search for column i*/
-} QueryType;
-
-/* TODO(shess) CHUNK_MAX controls how much data we allow in segment 0
-** before we start aggregating into larger segments. Lower CHUNK_MAX
-** means that for a given input we have more individual segments per
-** term, which means more rows in the table and a bigger index (due to
-** both more rows and bigger rowids). But it also reduces the average
-** cost of adding new elements to the segment 0 doclist, and it seems
-** to reduce the number of pages read and written during inserts. 256
-** was chosen by measuring insertion times for a certain input (first
-** 10k documents of Enron corpus), though including query performance
-** in the decision may argue for a larger value.
-*/
-#define CHUNK_MAX 256
-
-typedef enum fulltext_statement {
- CONTENT_INSERT_STMT,
- CONTENT_SELECT_STMT,
- CONTENT_UPDATE_STMT,
- CONTENT_DELETE_STMT,
-
- TERM_SELECT_STMT,
- TERM_SELECT_ALL_STMT,
- TERM_INSERT_STMT,
- TERM_UPDATE_STMT,
- TERM_DELETE_STMT,
-
- MAX_STMT /* Always at end! */
-} fulltext_statement;
-
-/* These must exactly match the enum above. */
-/* TODO(adam): Is there some risk that a statement (in particular,
-** pTermSelectStmt) will be used in two cursors at once, e.g. if a
-** query joins a virtual table to itself? If so perhaps we should
-** move some of these to the cursor object.
-*/
-static const char *const fulltext_zStatement[MAX_STMT] = {
- /* CONTENT_INSERT */ NULL, /* generated in contentInsertStatement() */
- /* CONTENT_SELECT */ "select * from %_content where rowid = ?",
- /* CONTENT_UPDATE */ NULL, /* generated in contentUpdateStatement() */
- /* CONTENT_DELETE */ "delete from %_content where rowid = ?",
-
- /* TERM_SELECT */
- "select rowid, doclist from %_term where term = ? and segment = ?",
- /* TERM_SELECT_ALL */
- "select doclist from %_term where term = ? order by segment",
- /* TERM_INSERT */
- "insert into %_term (rowid, term, segment, doclist) values (?, ?, ?, ?)",
- /* TERM_UPDATE */ "update %_term set doclist = ? where rowid = ?",
- /* TERM_DELETE */ "delete from %_term where rowid = ?",
-};
-
-/*
-** A connection to a fulltext index is an instance of the following
-** structure. The xCreate and xConnect methods create an instance
-** of this structure and xDestroy and xDisconnect free that instance.
-** All other methods receive a pointer to the structure as one of their
-** arguments.
-*/
-struct fulltext_vtab {
- sqlite3_vtab base; /* Base class used by SQLite core */
- sqlite3 *db; /* The database connection */
- const char *zDb; /* logical database name */
- const char *zName; /* virtual table name */
- int nColumn; /* number of columns in virtual table */
- char **azColumn; /* column names. malloced */
- char **azContentColumn; /* column names in content table; malloced */
- sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
-
- /* Precompiled statements which we keep as long as the table is
- ** open.
- */
- sqlite3_stmt *pFulltextStatements[MAX_STMT];
-};
-
-/*
-** When the core wants to do a query, it create a cursor using a
-** call to xOpen. This structure is an instance of a cursor. It
-** is destroyed by xClose.
-*/
-typedef struct fulltext_cursor {
- sqlite3_vtab_cursor base; /* Base class used by SQLite core */
- QueryType iCursorType; /* Copy of sqlite3_index_info.idxNum */
- sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
- int eof; /* True if at End Of Results */
- Query q; /* Parsed query string */
- Snippet snippet; /* Cached snippet for the current row */
- int iColumn; /* Column being searched */
- DocListReader result; /* used when iCursorType == QUERY_FULLTEXT */
-} fulltext_cursor;
-
-static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){
- return (fulltext_vtab *) c->base.pVtab;
-}
-
-static const sqlite3_module fulltextModule; /* forward declaration */
-
-/* Append a list of strings separated by commas to a StringBuffer. */
-static void appendList(StringBuffer *sb, int nString, char **azString){
- int i;
- for(i=0; i<nString; ++i){
- if( i>0 ) append(sb, ", ");
- append(sb, azString[i]);
- }
-}
-
-/* Return a dynamically generated statement of the form
- * insert into %_content (rowid, ...) values (?, ...)
- */
-static const char *contentInsertStatement(fulltext_vtab *v){
- StringBuffer sb;
- int i;
-
- initStringBuffer(&sb);
- append(&sb, "insert into %_content (rowid, ");
- appendList(&sb, v->nColumn, v->azContentColumn);
- append(&sb, ") values (?");
- for(i=0; i<v->nColumn; ++i)
- append(&sb, ", ?");
- append(&sb, ")");
- return sb.s;
-}
-
-/* Return a dynamically generated statement of the form
- * update %_content set [col_0] = ?, [col_1] = ?, ...
- * where rowid = ?
- */
-static const char *contentUpdateStatement(fulltext_vtab *v){
- StringBuffer sb;
- int i;
-
- initStringBuffer(&sb);
- append(&sb, "update %_content set ");
- for(i=0; i<v->nColumn; ++i) {
- if( i>0 ){
- append(&sb, ", ");
- }
- append(&sb, v->azContentColumn[i]);
- append(&sb, " = ?");
- }
- append(&sb, " where rowid = ?");
- return sb.s;
-}
-
-/* Puts a freshly-prepared statement determined by iStmt in *ppStmt.
-** If the indicated statement has never been prepared, it is prepared
-** and cached, otherwise the cached version is reset.
-*/
-static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt,
- sqlite3_stmt **ppStmt){
- assert( iStmt<MAX_STMT );
- if( v->pFulltextStatements[iStmt]==NULL ){
- const char *zStmt;
- int rc;
- switch( iStmt ){
- case CONTENT_INSERT_STMT:
- zStmt = contentInsertStatement(v); break;
- case CONTENT_UPDATE_STMT:
- zStmt = contentUpdateStatement(v); break;
- default:
- zStmt = fulltext_zStatement[iStmt];
- }
- rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt],
- zStmt);
- if( zStmt != fulltext_zStatement[iStmt]) free((void *) zStmt);
- if( rc!=SQLITE_OK ) return rc;
- } else {
- int rc = sqlite3_reset(v->pFulltextStatements[iStmt]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- *ppStmt = v->pFulltextStatements[iStmt];
- return SQLITE_OK;
-}
-
-/* Step the indicated statement, handling errors SQLITE_BUSY (by
-** retrying) and SQLITE_SCHEMA (by re-preparing and transferring
-** bindings to the new statement).
-** TODO(adam): We should extend this function so that it can work with
-** statements declared locally, not only globally cached statements.
-*/
-static int sql_step_statement(fulltext_vtab *v, fulltext_statement iStmt,
- sqlite3_stmt **ppStmt){
- int rc;
- sqlite3_stmt *s = *ppStmt;
- assert( iStmt<MAX_STMT );
- assert( s==v->pFulltextStatements[iStmt] );
-
- while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){
- if( rc==SQLITE_BUSY ) continue;
- if( rc!=SQLITE_ERROR ) return rc;
-
- /* If an SQLITE_SCHEMA error has occurred, then finalizing this
- * statement is going to delete the fulltext_vtab structure. If
- * the statement just executed is in the pFulltextStatements[]
- * array, it will be finalized twice. So remove it before
- * calling sqlite3_finalize().
- */
- v->pFulltextStatements[iStmt] = NULL;
- rc = sqlite3_finalize(s);
- break;
- }
- return rc;
-
- err:
- sqlite3_finalize(s);
- return rc;
-}
-
-/* Like sql_step_statement(), but convert SQLITE_DONE to SQLITE_OK.
-** Useful for statements like UPDATE, where we expect no results.
-*/
-static int sql_single_step_statement(fulltext_vtab *v,
- fulltext_statement iStmt,
- sqlite3_stmt **ppStmt){
- int rc = sql_step_statement(v, iStmt, ppStmt);
- return (rc==SQLITE_DONE) ? SQLITE_OK : rc;
-}
-
-/* insert into %_content (rowid, ...) values ([rowid], [pValues]) */
-static int content_insert(fulltext_vtab *v, sqlite3_value *rowid,
- sqlite3_value **pValues){
- sqlite3_stmt *s;
- int i;
- int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_value(s, 1, rowid);
- if( rc!=SQLITE_OK ) return rc;
-
- for(i=0; i<v->nColumn; ++i){
- rc = sqlite3_bind_value(s, 2+i, pValues[i]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- return sql_single_step_statement(v, CONTENT_INSERT_STMT, &s);
-}
-
-/* update %_content set col0 = pValues[0], col1 = pValues[1], ...
- * where rowid = [iRowid] */
-static int content_update(fulltext_vtab *v, sqlite3_value **pValues,
- sqlite_int64 iRowid){
- sqlite3_stmt *s;
- int i;
- int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- for(i=0; i<v->nColumn; ++i){
- rc = sqlite3_bind_value(s, 1+i, pValues[i]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- rc = sqlite3_bind_int64(s, 1+v->nColumn, iRowid);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, CONTENT_UPDATE_STMT, &s);
-}
-
-static void freeStringArray(int nString, const char **pString){
- int i;
-
- for (i=0 ; i < nString ; ++i) {
- if( pString[i]!=NULL ) free((void *) pString[i]);
- }
- free((void *) pString);
-}
-
-/* select * from %_content where rowid = [iRow]
- * The caller must delete the returned array and all strings in it.
- * null fields will be NULL in the returned array.
- *
- * TODO: Perhaps we should return pointer/length strings here for consistency
- * with other code which uses pointer/length. */
-static int content_select(fulltext_vtab *v, sqlite_int64 iRow,
- const char ***pValues){
- sqlite3_stmt *s;
- const char **values;
- int i;
- int rc;
-
- *pValues = NULL;
-
- rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s);
- if( rc!=SQLITE_ROW ) return rc;
-
- values = (const char **) malloc(v->nColumn * sizeof(const char *));
- for(i=0; i<v->nColumn; ++i){
- if( sqlite3_column_type(s, i)==SQLITE_NULL ){
- values[i] = NULL;
- }else{
- values[i] = string_dup((char*)sqlite3_column_text(s, i));
- }
- }
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- if( rc==SQLITE_DONE ){
- *pValues = values;
- return SQLITE_OK;
- }
-
- freeStringArray(v->nColumn, values);
- return rc;
-}
-
-/* delete from %_content where rowid = [iRow ] */
-static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, CONTENT_DELETE_STMT, &s);
-}
-
-/* select rowid, doclist from %_term
- * where term = [pTerm] and segment = [iSegment]
- * If found, returns SQLITE_ROW; the caller must free the
- * returned doclist. If no rows found, returns SQLITE_DONE. */
-static int term_select(fulltext_vtab *v, const char *pTerm, int nTerm,
- int iSegment,
- sqlite_int64 *rowid, DocList *out){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_SELECT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_text(s, 1, pTerm, nTerm, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int(s, 2, iSegment);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sql_step_statement(v, TERM_SELECT_STMT, &s);
- if( rc!=SQLITE_ROW ) return rc;
-
- *rowid = sqlite3_column_int64(s, 0);
- docListInit(out, DL_DEFAULT,
- sqlite3_column_blob(s, 1), sqlite3_column_bytes(s, 1));
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- return rc==SQLITE_DONE ? SQLITE_ROW : rc;
-}
-
-/* Load the segment doclists for term pTerm and merge them in
-** appropriate order into out. Returns SQLITE_OK if successful. If
-** there are no segments for pTerm, successfully returns an empty
-** doclist in out.
-**
-** Each document consists of 1 or more "columns". The number of
-** columns is v->nColumn. If iColumn==v->nColumn, then return
-** position information about all columns. If iColumn<v->nColumn,
-** then only return position information about the iColumn-th column
-** (where the first column is 0).
-*/
-static int term_select_all(
- fulltext_vtab *v, /* The fulltext index we are querying against */
- int iColumn, /* If <nColumn, only look at the iColumn-th column */
- const char *pTerm, /* The term whose posting lists we want */
- int nTerm, /* Number of bytes in pTerm */
- DocList *out /* Write the resulting doclist here */
-){
- DocList doclist;
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_SELECT_ALL_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_text(s, 1, pTerm, nTerm, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- docListInit(&doclist, DL_DEFAULT, 0, 0);
-
- /* TODO(shess) Handle schema and busy errors. */
- while( (rc=sql_step_statement(v, TERM_SELECT_ALL_STMT, &s))==SQLITE_ROW ){
- DocList old;
-
- /* TODO(shess) If we processed doclists from oldest to newest, we
- ** could skip the malloc() involved with the following call. For
- ** now, I'd rather keep this logic similar to index_insert_term().
- ** We could additionally drop elements when we see deletes, but
- ** that would require a distinct version of docListAccumulate().
- */
- docListInit(&old, DL_DEFAULT,
- sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0));
-
- if( iColumn<v->nColumn ){ /* querying a single column */
- docListRestrictColumn(&old, iColumn);
- }
-
- /* doclist contains the newer data, so write it over old. Then
- ** steal accumulated result for doclist.
- */
- docListAccumulate(&old, &doclist);
- docListDestroy(&doclist);
- doclist = old;
- }
- if( rc!=SQLITE_DONE ){
- docListDestroy(&doclist);
- return rc;
- }
-
- docListDiscardEmpty(&doclist);
- *out = doclist;
- return SQLITE_OK;
-}
-
-/* insert into %_term (rowid, term, segment, doclist)
- values ([piRowid], [pTerm], [iSegment], [doclist])
-** Lets sqlite select rowid if piRowid is NULL, else uses *piRowid.
-**
-** NOTE(shess) piRowid is IN, with values of "space of int64" plus
-** null, it is not used to pass data back to the caller.
-*/
-static int term_insert(fulltext_vtab *v, sqlite_int64 *piRowid,
- const char *pTerm, int nTerm,
- int iSegment, DocList *doclist){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_INSERT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- if( piRowid==NULL ){
- rc = sqlite3_bind_null(s, 1);
- }else{
- rc = sqlite3_bind_int64(s, 1, *piRowid);
- }
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_text(s, 2, pTerm, nTerm, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int(s, 3, iSegment);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_blob(s, 4, doclist->pData, doclist->nData, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, TERM_INSERT_STMT, &s);
-}
-
-/* update %_term set doclist = [doclist] where rowid = [rowid] */
-static int term_update(fulltext_vtab *v, sqlite_int64 rowid,
- DocList *doclist){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_UPDATE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_blob(s, 1, doclist->pData, doclist->nData, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 2, rowid);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, TERM_UPDATE_STMT, &s);
-}
-
-static int term_delete(fulltext_vtab *v, sqlite_int64 rowid){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_DELETE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, rowid);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, TERM_DELETE_STMT, &s);
-}
-
-/*
-** Free the memory used to contain a fulltext_vtab structure.
-*/
-static void fulltext_vtab_destroy(fulltext_vtab *v){
- int iStmt, i;
-
- TRACE(("FTS1 Destroy %p\n", v));
- for( iStmt=0; iStmt<MAX_STMT; iStmt++ ){
- if( v->pFulltextStatements[iStmt]!=NULL ){
- sqlite3_finalize(v->pFulltextStatements[iStmt]);
- v->pFulltextStatements[iStmt] = NULL;
- }
- }
-
- if( v->pTokenizer!=NULL ){
- v->pTokenizer->pModule->xDestroy(v->pTokenizer);
- v->pTokenizer = NULL;
- }
-
- free(v->azColumn);
- for(i = 0; i < v->nColumn; ++i) {
- sqlite3_free(v->azContentColumn[i]);
- }
- free(v->azContentColumn);
- free(v);
-}
-
-/*
-** Token types for parsing the arguments to xConnect or xCreate.
-*/
-#define TOKEN_EOF 0 /* End of file */
-#define TOKEN_SPACE 1 /* Any kind of whitespace */
-#define TOKEN_ID 2 /* An identifier */
-#define TOKEN_STRING 3 /* A string literal */
-#define TOKEN_PUNCT 4 /* A single punctuation character */
-
-/*
-** If X is a character that can be used in an identifier then
-** IdChar(X) will be true. Otherwise it is false.
-**
-** For ASCII, any character with the high-order bit set is
-** allowed in an identifier. For 7-bit characters,
-** sqlite3IsIdChar[X] must be 1.
-**
-** Ticket #1066. the SQL standard does not allow '$' in the
-** middle of identfiers. But many SQL implementations do.
-** SQLite will allow '$' in identifiers for compatibility.
-** But the feature is undocumented.
-*/
-static const char isIdChar[] = {
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
- 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
-};
-#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20]))
-
-
-/*
-** Return the length of the token that begins at z[0].
-** Store the token type in *tokenType before returning.
-*/
-static int getToken(const char *z, int *tokenType){
- int i, c;
- switch( *z ){
- case 0: {
- *tokenType = TOKEN_EOF;
- return 0;
- }
- case ' ': case '\t': case '\n': case '\f': case '\r': {
- for(i=1; safe_isspace(z[i]); i++){}
- *tokenType = TOKEN_SPACE;
- return i;
- }
- case '`':
- case '\'':
- case '"': {
- int delim = z[0];
- for(i=1; (c=z[i])!=0; i++){
- if( c==delim ){
- if( z[i+1]==delim ){
- i++;
- }else{
- break;
- }
- }
- }
- *tokenType = TOKEN_STRING;
- return i + (c!=0);
- }
- case '[': {
- for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
- *tokenType = TOKEN_ID;
- return i;
- }
- default: {
- if( !IdChar(*z) ){
- break;
- }
- for(i=1; IdChar(z[i]); i++){}
- *tokenType = TOKEN_ID;
- return i;
- }
- }
- *tokenType = TOKEN_PUNCT;
- return 1;
-}
-
-/*
-** A token extracted from a string is an instance of the following
-** structure.
-*/
-typedef struct Token {
- const char *z; /* Pointer to token text. Not '\000' terminated */
- short int n; /* Length of the token text in bytes. */
-} Token;
-
-/*
-** Given a input string (which is really one of the argv[] parameters
-** passed into xConnect or xCreate) split the string up into tokens.
-** Return an array of pointers to '\000' terminated strings, one string
-** for each non-whitespace token.
-**
-** The returned array is terminated by a single NULL pointer.
-**
-** Space to hold the returned array is obtained from a single
-** malloc and should be freed by passing the return value to free().
-** The individual strings within the token list are all a part of
-** the single memory allocation and will all be freed at once.
-*/
-static char **tokenizeString(const char *z, int *pnToken){
- int nToken = 0;
- Token *aToken = malloc( strlen(z) * sizeof(aToken[0]) );
- int n = 1;
- int e, i;
- int totalSize = 0;
- char **azToken;
- char *zCopy;
- while( n>0 ){
- n = getToken(z, &e);
- if( e!=TOKEN_SPACE ){
- aToken[nToken].z = z;
- aToken[nToken].n = n;
- nToken++;
- totalSize += n+1;
- }
- z += n;
- }
- azToken = (char**)malloc( nToken*sizeof(char*) + totalSize );
- zCopy = (char*)&azToken[nToken];
- nToken--;
- for(i=0; i<nToken; i++){
- azToken[i] = zCopy;
- n = aToken[i].n;
- memcpy(zCopy, aToken[i].z, n);
- zCopy[n] = 0;
- zCopy += n+1;
- }
- azToken[nToken] = 0;
- free(aToken);
- *pnToken = nToken;
- return azToken;
-}
-
-/*
-** Convert an SQL-style quoted string into a normal string by removing
-** the quote characters. The conversion is done in-place. If the
-** input does not begin with a quote character, then this routine
-** is a no-op.
-**
-** Examples:
-**
-** "abc" becomes abc
-** 'xyz' becomes xyz
-** [pqr] becomes pqr
-** `mno` becomes mno
-*/
-static void dequoteString(char *z){
- int quote;
- int i, j;
- if( z==0 ) return;
- quote = z[0];
- switch( quote ){
- case '\'': break;
- case '"': break;
- case '`': break; /* For MySQL compatibility */
- case '[': quote = ']'; break; /* For MS SqlServer compatibility */
- default: return;
- }
- for(i=1, j=0; z[i]; i++){
- if( z[i]==quote ){
- if( z[i+1]==quote ){
- z[j++] = quote;
- i++;
- }else{
- z[j++] = 0;
- break;
- }
- }else{
- z[j++] = z[i];
- }
- }
-}
-
-/*
-** The input azIn is a NULL-terminated list of tokens. Remove the first
-** token and all punctuation tokens. Remove the quotes from
-** around string literal tokens.
-**
-** Example:
-**
-** input: tokenize chinese ( 'simplifed' , 'mixed' )
-** output: chinese simplifed mixed
-**
-** Another example:
-**
-** input: delimiters ( '[' , ']' , '...' )
-** output: [ ] ...
-*/
-static void tokenListToIdList(char **azIn){
- int i, j;
- if( azIn ){
- for(i=0, j=-1; azIn[i]; i++){
- if( safe_isalnum(azIn[i][0]) || azIn[i][1] ){
- dequoteString(azIn[i]);
- if( j>=0 ){
- azIn[j] = azIn[i];
- }
- j++;
- }
- }
- azIn[j] = 0;
- }
-}
-
-
-/*
-** Find the first alphanumeric token in the string zIn. Null-terminate
-** this token. Remove any quotation marks. And return a pointer to
-** the result.
-*/
-static char *firstToken(char *zIn, char **pzTail){
- int n, ttype;
- while(1){
- n = getToken(zIn, &ttype);
- if( ttype==TOKEN_SPACE ){
- zIn += n;
- }else if( ttype==TOKEN_EOF ){
- *pzTail = zIn;
- return 0;
- }else{
- zIn[n] = 0;
- *pzTail = &zIn[1];
- dequoteString(zIn);
- return zIn;
- }
- }
- /*NOTREACHED*/
-}
-
-/* Return true if...
-**
-** * s begins with the string t, ignoring case
-** * s is longer than t
-** * The first character of s beyond t is not a alphanumeric
-**
-** Ignore leading space in *s.
-**
-** To put it another way, return true if the first token of
-** s[] is t[].
-*/
-static int startsWith(const char *s, const char *t){
- while( safe_isspace(*s) ){ s++; }
- while( *t ){
- if( safe_tolower(*s++)!=safe_tolower(*t++) ) return 0;
- }
- return *s!='_' && !safe_isalnum(*s);
-}
-
-/*
-** An instance of this structure defines the "spec" of a
-** full text index. This structure is populated by parseSpec
-** and use by fulltextConnect and fulltextCreate.
-*/
-typedef struct TableSpec {
- const char *zDb; /* Logical database name */
- const char *zName; /* Name of the full-text index */
- int nColumn; /* Number of columns to be indexed */
- char **azColumn; /* Original names of columns to be indexed */
- char **azContentColumn; /* Column names for %_content */
- char **azTokenizer; /* Name of tokenizer and its arguments */
-} TableSpec;
-
-/*
-** Reclaim all of the memory used by a TableSpec
-*/
-static void clearTableSpec(TableSpec *p) {
- free(p->azColumn);
- free(p->azContentColumn);
- free(p->azTokenizer);
-}
-
-/* Parse a CREATE VIRTUAL TABLE statement, which looks like this:
- *
- * CREATE VIRTUAL TABLE email
- * USING fts1(subject, body, tokenize mytokenizer(myarg))
- *
- * We return parsed information in a TableSpec structure.
- *
- */
-static int parseSpec(TableSpec *pSpec, int argc, const char *const*argv,
- char**pzErr){
- int i, n;
- char *z, *zDummy;
- char **azArg;
- const char *zTokenizer = 0; /* argv[] entry describing the tokenizer */
-
- assert( argc>=3 );
- /* Current interface:
- ** argv[0] - module name
- ** argv[1] - database name
- ** argv[2] - table name
- ** argv[3..] - columns, optionally followed by tokenizer specification
- ** and snippet delimiters specification.
- */
-
- /* Make a copy of the complete argv[][] array in a single allocation.
- ** The argv[][] array is read-only and transient. We can write to the
- ** copy in order to modify things and the copy is persistent.
- */
- memset(pSpec, 0, sizeof(*pSpec));
- for(i=n=0; i<argc; i++){
- n += strlen(argv[i]) + 1;
- }
- azArg = malloc( sizeof(char*)*argc + n );
- if( azArg==0 ){
- return SQLITE_NOMEM;
- }
- z = (char*)&azArg[argc];
- for(i=0; i<argc; i++){
- azArg[i] = z;
- strcpy(z, argv[i]);
- z += strlen(z)+1;
- }
-
- /* Identify the column names and the tokenizer and delimiter arguments
- ** in the argv[][] array.
- */
- pSpec->zDb = azArg[1];
- pSpec->zName = azArg[2];
- pSpec->nColumn = 0;
- pSpec->azColumn = azArg;
- zTokenizer = "tokenize simple";
- for(i=3; i<argc; ++i){
- if( startsWith(azArg[i],"tokenize") ){
- zTokenizer = azArg[i];
- }else{
- z = azArg[pSpec->nColumn] = firstToken(azArg[i], &zDummy);
- pSpec->nColumn++;
- }
- }
- if( pSpec->nColumn==0 ){
- azArg[0] = "content";
- pSpec->nColumn = 1;
- }
-
- /*
- ** Construct the list of content column names.
- **
- ** Each content column name will be of the form cNNAAAA
- ** where NN is the column number and AAAA is the sanitized
- ** column name. "sanitized" means that special characters are
- ** converted to "_". The cNN prefix guarantees that all column
- ** names are unique.
- **
- ** The AAAA suffix is not strictly necessary. It is included
- ** for the convenience of people who might examine the generated
- ** %_content table and wonder what the columns are used for.
- */
- pSpec->azContentColumn = malloc( pSpec->nColumn * sizeof(char *) );
- if( pSpec->azContentColumn==0 ){
- clearTableSpec(pSpec);
- return SQLITE_NOMEM;
- }
- for(i=0; i<pSpec->nColumn; i++){
- char *p;
- pSpec->azContentColumn[i] = sqlite3_mprintf("c%d%s", i, azArg[i]);
- for (p = pSpec->azContentColumn[i]; *p ; ++p) {
- if( !safe_isalnum(*p) ) *p = '_';
- }
- }
-
- /*
- ** Parse the tokenizer specification string.
- */
- pSpec->azTokenizer = tokenizeString(zTokenizer, &n);
- tokenListToIdList(pSpec->azTokenizer);
-
- return SQLITE_OK;
-}
-
-/*
-** Generate a CREATE TABLE statement that describes the schema of
-** the virtual table. Return a pointer to this schema string.
-**
-** Space is obtained from sqlite3_mprintf() and should be freed
-** using sqlite3_free().
-*/
-static char *fulltextSchema(
- int nColumn, /* Number of columns */
- const char *const* azColumn, /* List of columns */
- const char *zTableName /* Name of the table */
-){
- int i;
- char *zSchema, *zNext;
- const char *zSep = "(";
- zSchema = sqlite3_mprintf("CREATE TABLE x");
- for(i=0; i<nColumn; i++){
- zNext = sqlite3_mprintf("%s%s%Q", zSchema, zSep, azColumn[i]);
- sqlite3_free(zSchema);
- zSchema = zNext;
- zSep = ",";
- }
- zNext = sqlite3_mprintf("%s,%Q)", zSchema, zTableName);
- sqlite3_free(zSchema);
- return zNext;
-}
-
-/*
-** Build a new sqlite3_vtab structure that will describe the
-** fulltext index defined by spec.
-*/
-static int constructVtab(
- sqlite3 *db, /* The SQLite database connection */
- TableSpec *spec, /* Parsed spec information from parseSpec() */
- sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
- char **pzErr /* Write any error message here */
-){
- int rc;
- int n;
- fulltext_vtab *v = 0;
- const sqlite3_tokenizer_module *m = NULL;
- char *schema;
-
- v = (fulltext_vtab *) malloc(sizeof(fulltext_vtab));
- if( v==0 ) return SQLITE_NOMEM;
- memset(v, 0, sizeof(*v));
- /* sqlite will initialize v->base */
- v->db = db;
- v->zDb = spec->zDb; /* Freed when azColumn is freed */
- v->zName = spec->zName; /* Freed when azColumn is freed */
- v->nColumn = spec->nColumn;
- v->azContentColumn = spec->azContentColumn;
- spec->azContentColumn = 0;
- v->azColumn = spec->azColumn;
- spec->azColumn = 0;
-
- if( spec->azTokenizer==0 ){
- return SQLITE_NOMEM;
- }
- /* TODO(shess) For now, add new tokenizers as else if clauses. */
- if( spec->azTokenizer[0]==0 || startsWith(spec->azTokenizer[0], "simple") ){
- sqlite3Fts1SimpleTokenizerModule(&m);
- }else if( startsWith(spec->azTokenizer[0], "porter") ){
- sqlite3Fts1PorterTokenizerModule(&m);
- }else{
- *pzErr = sqlite3_mprintf("unknown tokenizer: %s", spec->azTokenizer[0]);
- rc = SQLITE_ERROR;
- goto err;
- }
- for(n=0; spec->azTokenizer[n]; n++){}
- if( n ){
- rc = m->xCreate(n-1, (const char*const*)&spec->azTokenizer[1],
- &v->pTokenizer);
- }else{
- rc = m->xCreate(0, 0, &v->pTokenizer);
- }
- if( rc!=SQLITE_OK ) goto err;
- v->pTokenizer->pModule = m;
-
- /* TODO: verify the existence of backing tables foo_content, foo_term */
-
- schema = fulltextSchema(v->nColumn, (const char*const*)v->azColumn,
- spec->zName);
- rc = sqlite3_declare_vtab(db, schema);
- sqlite3_free(schema);
- if( rc!=SQLITE_OK ) goto err;
-
- memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements));
-
- *ppVTab = &v->base;
- TRACE(("FTS1 Connect %p\n", v));
-
- return rc;
-
-err:
- fulltext_vtab_destroy(v);
- return rc;
-}
-
-static int fulltextConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab,
- char **pzErr
-){
- TableSpec spec;
- int rc = parseSpec(&spec, argc, argv, pzErr);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = constructVtab(db, &spec, ppVTab, pzErr);
- clearTableSpec(&spec);
- return rc;
-}
-
- /* The %_content table holds the text of each document, with
- ** the rowid used as the docid.
- **
- ** The %_term table maps each term to a document list blob
- ** containing elements sorted by ascending docid, each element
- ** encoded as:
- **
- ** docid varint-encoded
- ** token elements:
- ** position+1 varint-encoded as delta from previous position
- ** start offset varint-encoded as delta from previous start offset
- ** end offset varint-encoded as delta from start offset
- **
- ** The sentinel position of 0 indicates the end of the token list.
- **
- ** Additionally, doclist blobs are chunked into multiple segments,
- ** using segment to order the segments. New elements are added to
- ** the segment at segment 0, until it exceeds CHUNK_MAX. Then
- ** segment 0 is deleted, and the doclist is inserted at segment 1.
- ** If there is already a doclist at segment 1, the segment 0 doclist
- ** is merged with it, the segment 1 doclist is deleted, and the
- ** merged doclist is inserted at segment 2, repeating those
- ** operations until an insert succeeds.
- **
- ** Since this structure doesn't allow us to update elements in place
- ** in case of deletion or update, these are simply written to
- ** segment 0 (with an empty token list in case of deletion), with
- ** docListAccumulate() taking care to retain lower-segment
- ** information in preference to higher-segment information.
- */
- /* TODO(shess) Provide a VACUUM type operation which both removes
- ** deleted elements which are no longer necessary, and duplicated
- ** elements. I suspect this will probably not be necessary in
- ** practice, though.
- */
-static int fulltextCreate(sqlite3 *db, void *pAux,
- int argc, const char * const *argv,
- sqlite3_vtab **ppVTab, char **pzErr){
- int rc;
- TableSpec spec;
- StringBuffer schema;
- TRACE(("FTS1 Create\n"));
-
- rc = parseSpec(&spec, argc, argv, pzErr);
- if( rc!=SQLITE_OK ) return rc;
-
- initStringBuffer(&schema);
- append(&schema, "CREATE TABLE %_content(");
- appendList(&schema, spec.nColumn, spec.azContentColumn);
- append(&schema, ")");
- rc = sql_exec(db, spec.zDb, spec.zName, schema.s);
- free(schema.s);
- if( rc!=SQLITE_OK ) goto out;
-
- rc = sql_exec(db, spec.zDb, spec.zName,
- "create table %_term(term text, segment integer, doclist blob, "
- "primary key(term, segment));");
- if( rc!=SQLITE_OK ) goto out;
-
- rc = constructVtab(db, &spec, ppVTab, pzErr);
-
-out:
- clearTableSpec(&spec);
- return rc;
-}
-
-/* Decide how to handle an SQL query. */
-static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
- int i;
- TRACE(("FTS1 BestIndex\n"));
-
- for(i=0; i<pInfo->nConstraint; ++i){
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = &pInfo->aConstraint[i];
- if( pConstraint->usable ) {
- if( pConstraint->iColumn==-1 &&
- pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
- pInfo->idxNum = QUERY_ROWID; /* lookup by rowid */
- TRACE(("FTS1 QUERY_ROWID\n"));
- } else if( pConstraint->iColumn>=0 &&
- pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
- /* full-text search */
- pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn;
- TRACE(("FTS1 QUERY_FULLTEXT %d\n", pConstraint->iColumn));
- } else continue;
-
- pInfo->aConstraintUsage[i].argvIndex = 1;
- pInfo->aConstraintUsage[i].omit = 1;
-
- /* An arbitrary value for now.
- * TODO: Perhaps rowid matches should be considered cheaper than
- * full-text searches. */
- pInfo->estimatedCost = 1.0;
-
- return SQLITE_OK;
- }
- }
- pInfo->idxNum = QUERY_GENERIC;
- return SQLITE_OK;
-}
-
-static int fulltextDisconnect(sqlite3_vtab *pVTab){
- TRACE(("FTS1 Disconnect %p\n", pVTab));
- fulltext_vtab_destroy((fulltext_vtab *)pVTab);
- return SQLITE_OK;
-}
-
-static int fulltextDestroy(sqlite3_vtab *pVTab){
- fulltext_vtab *v = (fulltext_vtab *)pVTab;
- int rc;
-
- TRACE(("FTS1 Destroy %p\n", pVTab));
- rc = sql_exec(v->db, v->zDb, v->zName,
- "drop table if exists %_content;"
- "drop table if exists %_term;"
- );
- if( rc!=SQLITE_OK ) return rc;
-
- fulltext_vtab_destroy((fulltext_vtab *)pVTab);
- return SQLITE_OK;
-}
-
-static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- fulltext_cursor *c;
-
- c = (fulltext_cursor *) calloc(sizeof(fulltext_cursor), 1);
- /* sqlite will initialize c->base */
- *ppCursor = &c->base;
- TRACE(("FTS1 Open %p: %p\n", pVTab, c));
-
- return SQLITE_OK;
-}
-
-
-/* Free all of the dynamically allocated memory held by *q
-*/
-static void queryClear(Query *q){
- int i;
- for(i = 0; i < q->nTerms; ++i){
- free(q->pTerms[i].pTerm);
- }
- free(q->pTerms);
- memset(q, 0, sizeof(*q));
-}
-
-/* Free all of the dynamically allocated memory held by the
-** Snippet
-*/
-static void snippetClear(Snippet *p){
- free(p->aMatch);
- free(p->zOffset);
- free(p->zSnippet);
- memset(p, 0, sizeof(*p));
-}
-/*
-** Append a single entry to the p->aMatch[] log.
-*/
-static void snippetAppendMatch(
- Snippet *p, /* Append the entry to this snippet */
- int iCol, int iTerm, /* The column and query term */
- int iStart, int nByte /* Offset and size of the match */
-){
- int i;
- struct snippetMatch *pMatch;
- if( p->nMatch+1>=p->nAlloc ){
- p->nAlloc = p->nAlloc*2 + 10;
- p->aMatch = realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) );
- if( p->aMatch==0 ){
- p->nMatch = 0;
- p->nAlloc = 0;
- return;
- }
- }
- i = p->nMatch++;
- pMatch = &p->aMatch[i];
- pMatch->iCol = iCol;
- pMatch->iTerm = iTerm;
- pMatch->iStart = iStart;
- pMatch->nByte = nByte;
-}
-
-/*
-** Sizing information for the circular buffer used in snippetOffsetsOfColumn()
-*/
-#define FTS1_ROTOR_SZ (32)
-#define FTS1_ROTOR_MASK (FTS1_ROTOR_SZ-1)
-
-/*
-** Add entries to pSnippet->aMatch[] for every match that occurs against
-** document zDoc[0..nDoc-1] which is stored in column iColumn.
-*/
-static void snippetOffsetsOfColumn(
- Query *pQuery,
- Snippet *pSnippet,
- int iColumn,
- const char *zDoc,
- int nDoc
-){
- const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */
- sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */
- sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */
- fulltext_vtab *pVtab; /* The full text index */
- int nColumn; /* Number of columns in the index */
- const QueryTerm *aTerm; /* Query string terms */
- int nTerm; /* Number of query string terms */
- int i, j; /* Loop counters */
- int rc; /* Return code */
- unsigned int match, prevMatch; /* Phrase search bitmasks */
- const char *zToken; /* Next token from the tokenizer */
- int nToken; /* Size of zToken */
- int iBegin, iEnd, iPos; /* Offsets of beginning and end */
-
- /* The following variables keep a circular buffer of the last
- ** few tokens */
- unsigned int iRotor = 0; /* Index of current token */
- int iRotorBegin[FTS1_ROTOR_SZ]; /* Beginning offset of token */
- int iRotorLen[FTS1_ROTOR_SZ]; /* Length of token */
-
- pVtab = pQuery->pFts;
- nColumn = pVtab->nColumn;
- pTokenizer = pVtab->pTokenizer;
- pTModule = pTokenizer->pModule;
- rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor);
- if( rc ) return;
- pTCursor->pTokenizer = pTokenizer;
- aTerm = pQuery->pTerms;
- nTerm = pQuery->nTerms;
- if( nTerm>=FTS1_ROTOR_SZ ){
- nTerm = FTS1_ROTOR_SZ - 1;
- }
- prevMatch = 0;
- while(1){
- rc = pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
- if( rc ) break;
- iRotorBegin[iRotor&FTS1_ROTOR_MASK] = iBegin;
- iRotorLen[iRotor&FTS1_ROTOR_MASK] = iEnd-iBegin;
- match = 0;
- for(i=0; i<nTerm; i++){
- int iCol;
- iCol = aTerm[i].iColumn;
- if( iCol>=0 && iCol<nColumn && iCol!=iColumn ) continue;
- if( aTerm[i].nTerm!=nToken ) continue;
- if( memcmp(aTerm[i].pTerm, zToken, nToken) ) continue;
- if( aTerm[i].iPhrase>1 && (prevMatch & (1<<i))==0 ) continue;
- match |= 1<<i;
- if( i==nTerm-1 || aTerm[i+1].iPhrase==1 ){
- for(j=aTerm[i].iPhrase-1; j>=0; j--){
- int k = (iRotor-j) & FTS1_ROTOR_MASK;
- snippetAppendMatch(pSnippet, iColumn, i-j,
- iRotorBegin[k], iRotorLen[k]);
- }
- }
- }
- prevMatch = match<<1;
- iRotor++;
- }
- pTModule->xClose(pTCursor);
-}
-
-
-/*
-** Compute all offsets for the current row of the query.
-** If the offsets have already been computed, this routine is a no-op.
-*/
-static void snippetAllOffsets(fulltext_cursor *p){
- int nColumn;
- int iColumn, i;
- int iFirst, iLast;
- fulltext_vtab *pFts;
-
- if( p->snippet.nMatch ) return;
- if( p->q.nTerms==0 ) return;
- pFts = p->q.pFts;
- nColumn = pFts->nColumn;
- iColumn = p->iCursorType - QUERY_FULLTEXT;
- if( iColumn<0 || iColumn>=nColumn ){
- iFirst = 0;
- iLast = nColumn-1;
- }else{
- iFirst = iColumn;
- iLast = iColumn;
- }
- for(i=iFirst; i<=iLast; i++){
- const char *zDoc;
- int nDoc;
- zDoc = (const char*)sqlite3_column_text(p->pStmt, i+1);
- nDoc = sqlite3_column_bytes(p->pStmt, i+1);
- snippetOffsetsOfColumn(&p->q, &p->snippet, i, zDoc, nDoc);
- }
-}
-
-/*
-** Convert the information in the aMatch[] array of the snippet
-** into the string zOffset[0..nOffset-1].
-*/
-static void snippetOffsetText(Snippet *p){
- int i;
- int cnt = 0;
- StringBuffer sb;
- char zBuf[200];
- if( p->zOffset ) return;
- initStringBuffer(&sb);
- for(i=0; i<p->nMatch; i++){
- struct snippetMatch *pMatch = &p->aMatch[i];
- zBuf[0] = ' ';
- sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d",
- pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte);
- append(&sb, zBuf);
- cnt++;
- }
- p->zOffset = sb.s;
- p->nOffset = sb.len;
-}
-
-/*
-** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set
-** of matching words some of which might be in zDoc. zDoc is column
-** number iCol.
-**
-** iBreak is suggested spot in zDoc where we could begin or end an
-** excerpt. Return a value similar to iBreak but possibly adjusted
-** to be a little left or right so that the break point is better.
-*/
-static int wordBoundary(
- int iBreak, /* The suggested break point */
- const char *zDoc, /* Document text */
- int nDoc, /* Number of bytes in zDoc[] */
- struct snippetMatch *aMatch, /* Matching words */
- int nMatch, /* Number of entries in aMatch[] */
- int iCol /* The column number for zDoc[] */
-){
- int i;
- if( iBreak<=10 ){
- return 0;
- }
- if( iBreak>=nDoc-10 ){
- return nDoc;
- }
- for(i=0; i<nMatch && aMatch[i].iCol<iCol; i++){}
- while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; }
- if( i<nMatch ){
- if( aMatch[i].iStart<iBreak+10 ){
- return aMatch[i].iStart;
- }
- if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){
- return aMatch[i-1].iStart;
- }
- }
- for(i=1; i<=10; i++){
- if( safe_isspace(zDoc[iBreak-i]) ){
- return iBreak - i + 1;
- }
- if( safe_isspace(zDoc[iBreak+i]) ){
- return iBreak + i + 1;
- }
- }
- return iBreak;
-}
-
-/*
-** If the StringBuffer does not end in white space, add a single
-** space character to the end.
-*/
-static void appendWhiteSpace(StringBuffer *p){
- if( p->len==0 ) return;
- if( safe_isspace(p->s[p->len-1]) ) return;
- append(p, " ");
-}
-
-/*
-** Remove white space from teh end of the StringBuffer
-*/
-static void trimWhiteSpace(StringBuffer *p){
- while( p->len>0 && safe_isspace(p->s[p->len-1]) ){
- p->len--;
- }
-}
-
-
-
-/*
-** Allowed values for Snippet.aMatch[].snStatus
-*/
-#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */
-#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */
-
-/*
-** Generate the text of a snippet.
-*/
-static void snippetText(
- fulltext_cursor *pCursor, /* The cursor we need the snippet for */
- const char *zStartMark, /* Markup to appear before each match */
- const char *zEndMark, /* Markup to appear after each match */
- const char *zEllipsis /* Ellipsis mark */
-){
- int i, j;
- struct snippetMatch *aMatch;
- int nMatch;
- int nDesired;
- StringBuffer sb;
- int tailCol;
- int tailOffset;
- int iCol;
- int nDoc;
- const char *zDoc;
- int iStart, iEnd;
- int tailEllipsis = 0;
- int iMatch;
-
-
- free(pCursor->snippet.zSnippet);
- pCursor->snippet.zSnippet = 0;
- aMatch = pCursor->snippet.aMatch;
- nMatch = pCursor->snippet.nMatch;
- initStringBuffer(&sb);
-
- for(i=0; i<nMatch; i++){
- aMatch[i].snStatus = SNIPPET_IGNORE;
- }
- nDesired = 0;
- for(i=0; i<pCursor->q.nTerms; i++){
- for(j=0; j<nMatch; j++){
- if( aMatch[j].iTerm==i ){
- aMatch[j].snStatus = SNIPPET_DESIRED;
- nDesired++;
- break;
- }
- }
- }
-
- iMatch = 0;
- tailCol = -1;
- tailOffset = 0;
- for(i=0; i<nMatch && nDesired>0; i++){
- if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue;
- nDesired--;
- iCol = aMatch[i].iCol;
- zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1);
- nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1);
- iStart = aMatch[i].iStart - 40;
- iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol);
- if( iStart<=10 ){
- iStart = 0;
- }
- if( iCol==tailCol && iStart<=tailOffset+20 ){
- iStart = tailOffset;
- }
- if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){
- trimWhiteSpace(&sb);
- appendWhiteSpace(&sb);
- append(&sb, zEllipsis);
- appendWhiteSpace(&sb);
- }
- iEnd = aMatch[i].iStart + aMatch[i].nByte + 40;
- iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol);
- if( iEnd>=nDoc-10 ){
- iEnd = nDoc;
- tailEllipsis = 0;
- }else{
- tailEllipsis = 1;
- }
- while( iMatch<nMatch && aMatch[iMatch].iCol<iCol ){ iMatch++; }
- while( iStart<iEnd ){
- while( iMatch<nMatch && aMatch[iMatch].iStart<iStart
- && aMatch[iMatch].iCol<=iCol ){
- iMatch++;
- }
- if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd
- && aMatch[iMatch].iCol==iCol ){
- nappend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart);
- iStart = aMatch[iMatch].iStart;
- append(&sb, zStartMark);
- nappend(&sb, &zDoc[iStart], aMatch[iMatch].nByte);
- append(&sb, zEndMark);
- iStart += aMatch[iMatch].nByte;
- for(j=iMatch+1; j<nMatch; j++){
- if( aMatch[j].iTerm==aMatch[iMatch].iTerm
- && aMatch[j].snStatus==SNIPPET_DESIRED ){
- nDesired--;
- aMatch[j].snStatus = SNIPPET_IGNORE;
- }
- }
- }else{
- nappend(&sb, &zDoc[iStart], iEnd - iStart);
- iStart = iEnd;
- }
- }
- tailCol = iCol;
- tailOffset = iEnd;
- }
- trimWhiteSpace(&sb);
- if( tailEllipsis ){
- appendWhiteSpace(&sb);
- append(&sb, zEllipsis);
- }
- pCursor->snippet.zSnippet = sb.s;
- pCursor->snippet.nSnippet = sb.len;
-}
-
-
-/*
-** Close the cursor. For additional information see the documentation
-** on the xClose method of the virtual table interface.
-*/
-static int fulltextClose(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- TRACE(("FTS1 Close %p\n", c));
- sqlite3_finalize(c->pStmt);
- queryClear(&c->q);
- snippetClear(&c->snippet);
- if( c->result.pDoclist!=NULL ){
- docListDelete(c->result.pDoclist);
- }
- free(c);
- return SQLITE_OK;
-}
-
-static int fulltextNext(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- sqlite_int64 iDocid;
- int rc;
-
- TRACE(("FTS1 Next %p\n", pCursor));
- snippetClear(&c->snippet);
- if( c->iCursorType < QUERY_FULLTEXT ){
- /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
- rc = sqlite3_step(c->pStmt);
- switch( rc ){
- case SQLITE_ROW:
- c->eof = 0;
- return SQLITE_OK;
- case SQLITE_DONE:
- c->eof = 1;
- return SQLITE_OK;
- default:
- c->eof = 1;
- return rc;
- }
- } else { /* full-text query */
- rc = sqlite3_reset(c->pStmt);
- if( rc!=SQLITE_OK ) return rc;
-
- iDocid = nextDocid(&c->result);
- if( iDocid==0 ){
- c->eof = 1;
- return SQLITE_OK;
- }
- rc = sqlite3_bind_int64(c->pStmt, 1, iDocid);
- if( rc!=SQLITE_OK ) return rc;
- /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
- rc = sqlite3_step(c->pStmt);
- if( rc==SQLITE_ROW ){ /* the case we expect */
- c->eof = 0;
- return SQLITE_OK;
- }
- /* an error occurred; abort */
- return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
- }
-}
-
-
-/* Return a DocList corresponding to the query term *pTerm. If *pTerm
-** is the first term of a phrase query, go ahead and evaluate the phrase
-** query and return the doclist for the entire phrase query.
-**
-** The result is stored in pTerm->doclist.
-*/
-static int docListOfTerm(
- fulltext_vtab *v, /* The full text index */
- int iColumn, /* column to restrict to. No restrition if >=nColumn */
- QueryTerm *pQTerm, /* Term we are looking for, or 1st term of a phrase */
- DocList **ppResult /* Write the result here */
-){
- DocList *pLeft, *pRight, *pNew;
- int i, rc;
-
- pLeft = docListNew(DL_POSITIONS);
- rc = term_select_all(v, iColumn, pQTerm->pTerm, pQTerm->nTerm, pLeft);
- if( rc ){
- docListDelete(pLeft);
- return rc;
- }
- for(i=1; i<=pQTerm->nPhrase; i++){
- pRight = docListNew(DL_POSITIONS);
- rc = term_select_all(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm, pRight);
- if( rc ){
- docListDelete(pLeft);
- return rc;
- }
- pNew = docListNew(i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS);
- docListPhraseMerge(pLeft, pRight, pNew);
- docListDelete(pLeft);
- docListDelete(pRight);
- pLeft = pNew;
- }
- *ppResult = pLeft;
- return SQLITE_OK;
-}
-
-/* Add a new term pTerm[0..nTerm-1] to the query *q.
-*/
-static void queryAdd(Query *q, const char *pTerm, int nTerm){
- QueryTerm *t;
- ++q->nTerms;
- q->pTerms = realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0]));
- if( q->pTerms==0 ){
- q->nTerms = 0;
- return;
- }
- t = &q->pTerms[q->nTerms - 1];
- memset(t, 0, sizeof(*t));
- t->pTerm = malloc(nTerm+1);
- memcpy(t->pTerm, pTerm, nTerm);
- t->pTerm[nTerm] = 0;
- t->nTerm = nTerm;
- t->isOr = q->nextIsOr;
- q->nextIsOr = 0;
- t->iColumn = q->nextColumn;
- q->nextColumn = q->dfltColumn;
-}
-
-/*
-** Check to see if the string zToken[0...nToken-1] matches any
-** column name in the virtual table. If it does,
-** return the zero-indexed column number. If not, return -1.
-*/
-static int checkColumnSpecifier(
- fulltext_vtab *pVtab, /* The virtual table */
- const char *zToken, /* Text of the token */
- int nToken /* Number of characters in the token */
-){
- int i;
- for(i=0; i<pVtab->nColumn; i++){
- if( memcmp(pVtab->azColumn[i], zToken, nToken)==0
- && pVtab->azColumn[i][nToken]==0 ){
- return i;
- }
- }
- return -1;
-}
-
-/*
-** Parse the text at pSegment[0..nSegment-1]. Add additional terms
-** to the query being assemblied in pQuery.
-**
-** inPhrase is true if pSegment[0..nSegement-1] is contained within
-** double-quotes. If inPhrase is true, then the first term
-** is marked with the number of terms in the phrase less one and
-** OR and "-" syntax is ignored. If inPhrase is false, then every
-** term found is marked with nPhrase=0 and OR and "-" syntax is significant.
-*/
-static int tokenizeSegment(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */
- const char *pSegment, int nSegment, /* Query expression being parsed */
- int inPhrase, /* True if within "..." */
- Query *pQuery /* Append results here */
-){
- const sqlite3_tokenizer_module *pModule = pTokenizer->pModule;
- sqlite3_tokenizer_cursor *pCursor;
- int firstIndex = pQuery->nTerms;
- int iCol;
- int nTerm = 1;
-
- int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
- if( rc!=SQLITE_OK ) return rc;
- pCursor->pTokenizer = pTokenizer;
-
- while( 1 ){
- const char *pToken;
- int nToken, iBegin, iEnd, iPos;
-
- rc = pModule->xNext(pCursor,
- &pToken, &nToken,
- &iBegin, &iEnd, &iPos);
- if( rc!=SQLITE_OK ) break;
- if( !inPhrase &&
- pSegment[iEnd]==':' &&
- (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){
- pQuery->nextColumn = iCol;
- continue;
- }
- if( !inPhrase && pQuery->nTerms>0 && nToken==2
- && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){
- pQuery->nextIsOr = 1;
- continue;
- }
- queryAdd(pQuery, pToken, nToken);
- if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
- pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
- }
- pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm;
- if( inPhrase ){
- nTerm++;
- }
- }
-
- if( inPhrase && pQuery->nTerms>firstIndex ){
- pQuery->pTerms[firstIndex].nPhrase = pQuery->nTerms - firstIndex - 1;
- }
-
- return pModule->xClose(pCursor);
-}
-
-/* Parse a query string, yielding a Query object pQuery.
-**
-** The calling function will need to queryClear() to clean up
-** the dynamically allocated memory held by pQuery.
-*/
-static int parseQuery(
- fulltext_vtab *v, /* The fulltext index */
- const char *zInput, /* Input text of the query string */
- int nInput, /* Size of the input text */
- int dfltColumn, /* Default column of the index to match against */
- Query *pQuery /* Write the parse results here. */
-){
- int iInput, inPhrase = 0;
-
- if( zInput==0 ) nInput = 0;
- if( nInput<0 ) nInput = strlen(zInput);
- pQuery->nTerms = 0;
- pQuery->pTerms = NULL;
- pQuery->nextIsOr = 0;
- pQuery->nextColumn = dfltColumn;
- pQuery->dfltColumn = dfltColumn;
- pQuery->pFts = v;
-
- for(iInput=0; iInput<nInput; ++iInput){
- int i;
- for(i=iInput; i<nInput && zInput[i]!='"'; ++i){}
- if( i>iInput ){
- tokenizeSegment(v->pTokenizer, zInput+iInput, i-iInput, inPhrase,
- pQuery);
- }
- iInput = i;
- if( i<nInput ){
- assert( zInput[i]=='"' );
- inPhrase = !inPhrase;
- }
- }
-
- if( inPhrase ){
- /* unmatched quote */
- queryClear(pQuery);
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-
-/* Perform a full-text query using the search expression in
-** zInput[0..nInput-1]. Return a list of matching documents
-** in pResult.
-**
-** Queries must match column iColumn. Or if iColumn>=nColumn
-** they are allowed to match against any column.
-*/
-static int fulltextQuery(
- fulltext_vtab *v, /* The full text index */
- int iColumn, /* Match against this column by default */
- const char *zInput, /* The query string */
- int nInput, /* Number of bytes in zInput[] */
- DocList **pResult, /* Write the result doclist here */
- Query *pQuery /* Put parsed query string here */
-){
- int i, iNext, rc;
- DocList *pLeft = NULL;
- DocList *pRight, *pNew, *pOr;
- int nNot = 0;
- QueryTerm *aTerm;
-
- rc = parseQuery(v, zInput, nInput, iColumn, pQuery);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Merge AND terms. */
- aTerm = pQuery->pTerms;
- for(i = 0; i<pQuery->nTerms; i=iNext){
- if( aTerm[i].isNot ){
- /* Handle all NOT terms in a separate pass */
- nNot++;
- iNext = i + aTerm[i].nPhrase+1;
- continue;
- }
- iNext = i + aTerm[i].nPhrase + 1;
- rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &pRight);
- if( rc ){
- queryClear(pQuery);
- return rc;
- }
- while( iNext<pQuery->nTerms && aTerm[iNext].isOr ){
- rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &pOr);
- iNext += aTerm[iNext].nPhrase + 1;
- if( rc ){
- queryClear(pQuery);
- return rc;
- }
- pNew = docListNew(DL_DOCIDS);
- docListOrMerge(pRight, pOr, pNew);
- docListDelete(pRight);
- docListDelete(pOr);
- pRight = pNew;
- }
- if( pLeft==0 ){
- pLeft = pRight;
- }else{
- pNew = docListNew(DL_DOCIDS);
- docListAndMerge(pLeft, pRight, pNew);
- docListDelete(pRight);
- docListDelete(pLeft);
- pLeft = pNew;
- }
- }
-
- if( nNot && pLeft==0 ){
- /* We do not yet know how to handle a query of only NOT terms */
- return SQLITE_ERROR;
- }
-
- /* Do the EXCEPT terms */
- for(i=0; i<pQuery->nTerms; i += aTerm[i].nPhrase + 1){
- if( !aTerm[i].isNot ) continue;
- rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &pRight);
- if( rc ){
- queryClear(pQuery);
- docListDelete(pLeft);
- return rc;
- }
- pNew = docListNew(DL_DOCIDS);
- docListExceptMerge(pLeft, pRight, pNew);
- docListDelete(pRight);
- docListDelete(pLeft);
- pLeft = pNew;
- }
-
- *pResult = pLeft;
- return rc;
-}
-
-/*
-** This is the xFilter interface for the virtual table. See
-** the virtual table xFilter method documentation for additional
-** information.
-**
-** If idxNum==QUERY_GENERIC then do a full table scan against
-** the %_content table.
-**
-** If idxNum==QUERY_ROWID then do a rowid lookup for a single entry
-** in the %_content table.
-**
-** If idxNum>=QUERY_FULLTEXT then use the full text index. The
-** column on the left-hand side of the MATCH operator is column
-** number idxNum-QUERY_FULLTEXT, 0 indexed. argv[0] is the right-hand
-** side of the MATCH operator.
-*/
-/* TODO(shess) Upgrade the cursor initialization and destruction to
-** account for fulltextFilter() being called multiple times on the
-** same cursor. The current solution is very fragile. Apply fix to
-** fts2 as appropriate.
-*/
-static int fulltextFilter(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, const char *idxStr, /* Which indexing scheme to use */
- int argc, sqlite3_value **argv /* Arguments for the indexing scheme */
-){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- fulltext_vtab *v = cursor_vtab(c);
- int rc;
- char *zSql;
-
- TRACE(("FTS1 Filter %p\n",pCursor));
-
- zSql = sqlite3_mprintf("select rowid, * from %%_content %s",
- idxNum==QUERY_GENERIC ? "" : "where rowid=?");
- sqlite3_finalize(c->pStmt);
- rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, zSql);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK ) return rc;
-
- c->iCursorType = idxNum;
- switch( idxNum ){
- case QUERY_GENERIC:
- break;
-
- case QUERY_ROWID:
- rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0]));
- if( rc!=SQLITE_OK ) return rc;
- break;
-
- default: /* full-text search */
- {
- const char *zQuery = (const char *)sqlite3_value_text(argv[0]);
- DocList *pResult;
- assert( idxNum<=QUERY_FULLTEXT+v->nColumn);
- assert( argc==1 );
- queryClear(&c->q);
- rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &pResult, &c->q);
- if( rc!=SQLITE_OK ) return rc;
- if( c->result.pDoclist!=NULL ) docListDelete(c->result.pDoclist);
- readerInit(&c->result, pResult);
- break;
- }
- }
-
- return fulltextNext(pCursor);
-}
-
-/* This is the xEof method of the virtual table. The SQLite core
-** calls this routine to find out if it has reached the end of
-** a query's results set.
-*/
-static int fulltextEof(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- return c->eof;
-}
-
-/* This is the xColumn method of the virtual table. The SQLite
-** core calls this method during a query when it needs the value
-** of a column from the virtual table. This method needs to use
-** one of the sqlite3_result_*() routines to store the requested
-** value back in the pContext.
-*/
-static int fulltextColumn(sqlite3_vtab_cursor *pCursor,
- sqlite3_context *pContext, int idxCol){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- fulltext_vtab *v = cursor_vtab(c);
-
- if( idxCol<v->nColumn ){
- sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1);
- sqlite3_result_value(pContext, pVal);
- }else if( idxCol==v->nColumn ){
- /* The extra column whose name is the same as the table.
- ** Return a blob which is a pointer to the cursor
- */
- sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT);
- }
- return SQLITE_OK;
-}
-
-/* This is the xRowid method. The SQLite core calls this routine to
-** retrive the rowid for the current row of the result set. The
-** rowid should be written to *pRowid.
-*/
-static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
-
- *pRowid = sqlite3_column_int64(c->pStmt, 0);
- return SQLITE_OK;
-}
-
-/* Add all terms in [zText] to the given hash table. If [iColumn] > 0,
- * we also store positions and offsets in the hash table using the given
- * column number. */
-static int buildTerms(fulltext_vtab *v, fts1Hash *terms, sqlite_int64 iDocid,
- const char *zText, int iColumn){
- sqlite3_tokenizer *pTokenizer = v->pTokenizer;
- sqlite3_tokenizer_cursor *pCursor;
- const char *pToken;
- int nTokenBytes;
- int iStartOffset, iEndOffset, iPosition;
- int rc;
-
- rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor);
- if( rc!=SQLITE_OK ) return rc;
-
- pCursor->pTokenizer = pTokenizer;
- while( SQLITE_OK==pTokenizer->pModule->xNext(pCursor,
- &pToken, &nTokenBytes,
- &iStartOffset, &iEndOffset,
- &iPosition) ){
- DocList *p;
-
- /* Positions can't be negative; we use -1 as a terminator internally. */
- if( iPosition<0 ){
- pTokenizer->pModule->xClose(pCursor);
- return SQLITE_ERROR;
- }
-
- p = fts1HashFind(terms, pToken, nTokenBytes);
- if( p==NULL ){
- p = docListNew(DL_DEFAULT);
- docListAddDocid(p, iDocid);
- fts1HashInsert(terms, pToken, nTokenBytes, p);
- }
- if( iColumn>=0 ){
- docListAddPosOffset(p, iColumn, iPosition, iStartOffset, iEndOffset);
- }
- }
-
- /* TODO(shess) Check return? Should this be able to cause errors at
- ** this point? Actually, same question about sqlite3_finalize(),
- ** though one could argue that failure there means that the data is
- ** not durable. *ponder*
- */
- pTokenizer->pModule->xClose(pCursor);
- return rc;
-}
-
-/* Update the %_terms table to map the term [pTerm] to the given rowid. */
-static int index_insert_term(fulltext_vtab *v, const char *pTerm, int nTerm,
- DocList *d){
- sqlite_int64 iIndexRow;
- DocList doclist;
- int iSegment = 0, rc;
-
- rc = term_select(v, pTerm, nTerm, iSegment, &iIndexRow, &doclist);
- if( rc==SQLITE_DONE ){
- docListInit(&doclist, DL_DEFAULT, 0, 0);
- docListUpdate(&doclist, d);
- /* TODO(shess) Consider length(doclist)>CHUNK_MAX? */
- rc = term_insert(v, NULL, pTerm, nTerm, iSegment, &doclist);
- goto err;
- }
- if( rc!=SQLITE_ROW ) return SQLITE_ERROR;
-
- docListUpdate(&doclist, d);
- if( doclist.nData<=CHUNK_MAX ){
- rc = term_update(v, iIndexRow, &doclist);
- goto err;
- }
-
- /* Doclist doesn't fit, delete what's there, and accumulate
- ** forward.
- */
- rc = term_delete(v, iIndexRow);
- if( rc!=SQLITE_OK ) goto err;
-
- /* Try to insert the doclist into a higher segment bucket. On
- ** failure, accumulate existing doclist with the doclist from that
- ** bucket, and put results in the next bucket.
- */
- iSegment++;
- while( (rc=term_insert(v, &iIndexRow, pTerm, nTerm, iSegment,
- &doclist))!=SQLITE_OK ){
- sqlite_int64 iSegmentRow;
- DocList old;
- int rc2;
-
- /* Retain old error in case the term_insert() error was really an
- ** error rather than a bounced insert.
- */
- rc2 = term_select(v, pTerm, nTerm, iSegment, &iSegmentRow, &old);
- if( rc2!=SQLITE_ROW ) goto err;
-
- rc = term_delete(v, iSegmentRow);
- if( rc!=SQLITE_OK ) goto err;
-
- /* Reusing lowest-number deleted row keeps the index smaller. */
- if( iSegmentRow<iIndexRow ) iIndexRow = iSegmentRow;
-
- /* doclist contains the newer data, so accumulate it over old.
- ** Then steal accumulated data for doclist.
- */
- docListAccumulate(&old, &doclist);
- docListDestroy(&doclist);
- doclist = old;
-
- iSegment++;
- }
-
- err:
- docListDestroy(&doclist);
- return rc;
-}
-
-/* Add doclists for all terms in [pValues] to the hash table [terms]. */
-static int insertTerms(fulltext_vtab *v, fts1Hash *terms, sqlite_int64 iRowid,
- sqlite3_value **pValues){
- int i;
- for(i = 0; i < v->nColumn ; ++i){
- char *zText = (char*)sqlite3_value_text(pValues[i]);
- int rc = buildTerms(v, terms, iRowid, zText, i);
- if( rc!=SQLITE_OK ) return rc;
- }
- return SQLITE_OK;
-}
-
-/* Add empty doclists for all terms in the given row's content to the hash
- * table [pTerms]. */
-static int deleteTerms(fulltext_vtab *v, fts1Hash *pTerms, sqlite_int64 iRowid){
- const char **pValues;
- int i;
-
- int rc = content_select(v, iRowid, &pValues);
- if( rc!=SQLITE_OK ) return rc;
-
- for(i = 0 ; i < v->nColumn; ++i) {
- rc = buildTerms(v, pTerms, iRowid, pValues[i], -1);
- if( rc!=SQLITE_OK ) break;
- }
-
- freeStringArray(v->nColumn, pValues);
- return SQLITE_OK;
-}
-
-/* Insert a row into the %_content table; set *piRowid to be the ID of the
- * new row. Fill [pTerms] with new doclists for the %_term table. */
-static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestRowid,
- sqlite3_value **pValues,
- sqlite_int64 *piRowid, fts1Hash *pTerms){
- int rc;
-
- rc = content_insert(v, pRequestRowid, pValues); /* execute an SQL INSERT */
- if( rc!=SQLITE_OK ) return rc;
- *piRowid = sqlite3_last_insert_rowid(v->db);
- return insertTerms(v, pTerms, *piRowid, pValues);
-}
-
-/* Delete a row from the %_content table; fill [pTerms] with empty doclists
- * to be written to the %_term table. */
-static int index_delete(fulltext_vtab *v, sqlite_int64 iRow, fts1Hash *pTerms){
- int rc = deleteTerms(v, pTerms, iRow);
- if( rc!=SQLITE_OK ) return rc;
- return content_delete(v, iRow); /* execute an SQL DELETE */
-}
-
-/* Update a row in the %_content table; fill [pTerms] with new doclists for the
- * %_term table. */
-static int index_update(fulltext_vtab *v, sqlite_int64 iRow,
- sqlite3_value **pValues, fts1Hash *pTerms){
- /* Generate an empty doclist for each term that previously appeared in this
- * row. */
- int rc = deleteTerms(v, pTerms, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = content_update(v, pValues, iRow); /* execute an SQL UPDATE */
- if( rc!=SQLITE_OK ) return rc;
-
- /* Now add positions for terms which appear in the updated row. */
- return insertTerms(v, pTerms, iRow, pValues);
-}
-
-/* This function implements the xUpdate callback; it is the top-level entry
- * point for inserting, deleting or updating a row in a full-text table. */
-static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg,
- sqlite_int64 *pRowid){
- fulltext_vtab *v = (fulltext_vtab *) pVtab;
- fts1Hash terms; /* maps term string -> PosList */
- int rc;
- fts1HashElem *e;
-
- TRACE(("FTS1 Update %p\n", pVtab));
-
- fts1HashInit(&terms, FTS1_HASH_STRING, 1);
-
- if( nArg<2 ){
- rc = index_delete(v, sqlite3_value_int64(ppArg[0]), &terms);
- } else if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){
- /* An update:
- * ppArg[0] = old rowid
- * ppArg[1] = new rowid
- * ppArg[2..2+v->nColumn-1] = values
- * ppArg[2+v->nColumn] = value for magic column (we ignore this)
- */
- sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]);
- if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER ||
- sqlite3_value_int64(ppArg[1]) != rowid ){
- rc = SQLITE_ERROR; /* we don't allow changing the rowid */
- } else {
- assert( nArg==2+v->nColumn+1);
- rc = index_update(v, rowid, &ppArg[2], &terms);
- }
- } else {
- /* An insert:
- * ppArg[1] = requested rowid
- * ppArg[2..2+v->nColumn-1] = values
- * ppArg[2+v->nColumn] = value for magic column (we ignore this)
- */
- assert( nArg==2+v->nColumn+1);
- rc = index_insert(v, ppArg[1], &ppArg[2], pRowid, &terms);
- }
-
- if( rc==SQLITE_OK ){
- /* Write updated doclists to disk. */
- for(e=fts1HashFirst(&terms); e; e=fts1HashNext(e)){
- DocList *p = fts1HashData(e);
- rc = index_insert_term(v, fts1HashKey(e), fts1HashKeysize(e), p);
- if( rc!=SQLITE_OK ) break;
- }
- }
-
- /* clean up */
- for(e=fts1HashFirst(&terms); e; e=fts1HashNext(e)){
- DocList *p = fts1HashData(e);
- docListDelete(p);
- }
- fts1HashClear(&terms);
-
- return rc;
-}
-
-/*
-** Implementation of the snippet() function for FTS1
-*/
-static void snippetFunc(
- sqlite3_context *pContext,
- int argc,
- sqlite3_value **argv
-){
- fulltext_cursor *pCursor;
- if( argc<1 ) return;
- if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
- sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
- sqlite3_result_error(pContext, "illegal first argument to html_snippet",-1);
- }else{
- const char *zStart = "<b>";
- const char *zEnd = "</b>";
- const char *zEllipsis = "<b>...</b>";
- memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
- if( argc>=2 ){
- zStart = (const char*)sqlite3_value_text(argv[1]);
- if( argc>=3 ){
- zEnd = (const char*)sqlite3_value_text(argv[2]);
- if( argc>=4 ){
- zEllipsis = (const char*)sqlite3_value_text(argv[3]);
- }
- }
- }
- snippetAllOffsets(pCursor);
- snippetText(pCursor, zStart, zEnd, zEllipsis);
- sqlite3_result_text(pContext, pCursor->snippet.zSnippet,
- pCursor->snippet.nSnippet, SQLITE_STATIC);
- }
-}
-
-/*
-** Implementation of the offsets() function for FTS1
-*/
-static void snippetOffsetsFunc(
- sqlite3_context *pContext,
- int argc,
- sqlite3_value **argv
-){
- fulltext_cursor *pCursor;
- if( argc<1 ) return;
- if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
- sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
- sqlite3_result_error(pContext, "illegal first argument to offsets",-1);
- }else{
- memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
- snippetAllOffsets(pCursor);
- snippetOffsetText(&pCursor->snippet);
- sqlite3_result_text(pContext,
- pCursor->snippet.zOffset, pCursor->snippet.nOffset,
- SQLITE_STATIC);
- }
-}
-
-/*
-** This routine implements the xFindFunction method for the FTS1
-** virtual table.
-*/
-static int fulltextFindFunction(
- sqlite3_vtab *pVtab,
- int nArg,
- const char *zName,
- void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
- void **ppArg
-){
- if( strcmp(zName,"snippet")==0 ){
- *pxFunc = snippetFunc;
- return 1;
- }else if( strcmp(zName,"offsets")==0 ){
- *pxFunc = snippetOffsetsFunc;
- return 1;
- }
- return 0;
-}
-
-/*
-** Rename an fts1 table.
-*/
-static int fulltextRename(
- sqlite3_vtab *pVtab,
- const char *zName
-){
- fulltext_vtab *p = (fulltext_vtab *)pVtab;
- int rc = SQLITE_NOMEM;
- char *zSql = sqlite3_mprintf(
- "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';"
- "ALTER TABLE %Q.'%q_term' RENAME TO '%q_term';"
- , p->zDb, p->zName, zName
- , p->zDb, p->zName, zName
- );
- if( zSql ){
- rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
- return rc;
-}
-
-static const sqlite3_module fulltextModule = {
- /* iVersion */ 0,
- /* xCreate */ fulltextCreate,
- /* xConnect */ fulltextConnect,
- /* xBestIndex */ fulltextBestIndex,
- /* xDisconnect */ fulltextDisconnect,
- /* xDestroy */ fulltextDestroy,
- /* xOpen */ fulltextOpen,
- /* xClose */ fulltextClose,
- /* xFilter */ fulltextFilter,
- /* xNext */ fulltextNext,
- /* xEof */ fulltextEof,
- /* xColumn */ fulltextColumn,
- /* xRowid */ fulltextRowid,
- /* xUpdate */ fulltextUpdate,
- /* xBegin */ 0,
- /* xSync */ 0,
- /* xCommit */ 0,
- /* xRollback */ 0,
- /* xFindFunction */ fulltextFindFunction,
- /* xRename */ fulltextRename,
-};
-
-int sqlite3Fts1Init(sqlite3 *db){
- sqlite3_overload_function(db, "snippet", -1);
- sqlite3_overload_function(db, "offsets", -1);
- return sqlite3_create_module(db, "fts1", &fulltextModule, 0);
-}
-
-#if !SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fts1_init(sqlite3 *db, char **pzErrMsg,
- const sqlite3_api_routines *pApi){
- SQLITE_EXTENSION_INIT2(pApi)
- return sqlite3Fts1Init(db);
-}
-#endif
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1.h
deleted file mode 100644
index d55e6897332..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "sqlite3.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int sqlite3Fts1Init(sqlite3 *db);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_hash.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_hash.c
deleted file mode 100644
index 463a52b6455..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_hash.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the implementation of generic hash-tables used in SQLite.
-** We've modified it slightly to serve as a standalone hash table
-** implementation for the full-text indexing module.
-*/
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS1 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS1 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)
-
-
-#include "fts1_hash.h"
-
-static void *malloc_and_zero(int n){
- void *p = malloc(n);
- if( p ){
- memset(p, 0, n);
- }
- return p;
-}
-
-/* Turn bulk memory into a hash table object by initializing the
-** fields of the Hash structure.
-**
-** "pNew" is a pointer to the hash table that is to be initialized.
-** keyClass is one of the constants
-** FTS1_HASH_BINARY or FTS1_HASH_STRING. The value of keyClass
-** determines what kind of key the hash table will use. "copyKey" is
-** true if the hash table should make its own private copy of keys and
-** false if it should just use the supplied pointer.
-*/
-void sqlite3Fts1HashInit(fts1Hash *pNew, int keyClass, int copyKey){
- assert( pNew!=0 );
- assert( keyClass>=FTS1_HASH_STRING && keyClass<=FTS1_HASH_BINARY );
- pNew->keyClass = keyClass;
- pNew->copyKey = copyKey;
- pNew->first = 0;
- pNew->count = 0;
- pNew->htsize = 0;
- pNew->ht = 0;
- pNew->xMalloc = malloc_and_zero;
- pNew->xFree = free;
-}
-
-/* Remove all entries from a hash table. Reclaim all memory.
-** Call this routine to delete a hash table or to reset a hash table
-** to the empty state.
-*/
-void sqlite3Fts1HashClear(fts1Hash *pH){
- fts1HashElem *elem; /* For looping over all elements of the table */
-
- assert( pH!=0 );
- elem = pH->first;
- pH->first = 0;
- if( pH->ht ) pH->xFree(pH->ht);
- pH->ht = 0;
- pH->htsize = 0;
- while( elem ){
- fts1HashElem *next_elem = elem->next;
- if( pH->copyKey && elem->pKey ){
- pH->xFree(elem->pKey);
- }
- pH->xFree(elem);
- elem = next_elem;
- }
- pH->count = 0;
-}
-
-/*
-** Hash and comparison functions when the mode is FTS1_HASH_STRING
-*/
-static int strHash(const void *pKey, int nKey){
- const char *z = (const char *)pKey;
- int h = 0;
- if( nKey<=0 ) nKey = (int) strlen(z);
- while( nKey > 0 ){
- h = (h<<3) ^ h ^ *z++;
- nKey--;
- }
- return h & 0x7fffffff;
-}
-static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return strncmp((const char*)pKey1,(const char*)pKey2,n1);
-}
-
-/*
-** Hash and comparison functions when the mode is FTS1_HASH_BINARY
-*/
-static int binHash(const void *pKey, int nKey){
- int h = 0;
- const char *z = (const char *)pKey;
- while( nKey-- > 0 ){
- h = (h<<3) ^ h ^ *(z++);
- }
- return h & 0x7fffffff;
-}
-static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return memcmp(pKey1,pKey2,n1);
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** The C syntax in this function definition may be unfamilar to some
-** programmers, so we provide the following additional explanation:
-**
-** The name of the function is "hashFunction". The function takes a
-** single parameter "keyClass". The return value of hashFunction()
-** is a pointer to another function. Specifically, the return value
-** of hashFunction() is a pointer to a function that takes two parameters
-** with types "const void*" and "int" and returns an "int".
-*/
-static int (*hashFunction(int keyClass))(const void*,int){
- if( keyClass==FTS1_HASH_STRING ){
- return &strHash;
- }else{
- assert( keyClass==FTS1_HASH_BINARY );
- return &binHash;
- }
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** For help in interpreted the obscure C code in the function definition,
-** see the header comment on the previous function.
-*/
-static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
- if( keyClass==FTS1_HASH_STRING ){
- return &strCompare;
- }else{
- assert( keyClass==FTS1_HASH_BINARY );
- return &binCompare;
- }
-}
-
-/* Link an element into the hash table
-*/
-static void insertElement(
- fts1Hash *pH, /* The complete hash table */
- struct _fts1ht *pEntry, /* The entry into which pNew is inserted */
- fts1HashElem *pNew /* The element to be inserted */
-){
- fts1HashElem *pHead; /* First element already in pEntry */
- pHead = pEntry->chain;
- if( pHead ){
- pNew->next = pHead;
- pNew->prev = pHead->prev;
- if( pHead->prev ){ pHead->prev->next = pNew; }
- else { pH->first = pNew; }
- pHead->prev = pNew;
- }else{
- pNew->next = pH->first;
- if( pH->first ){ pH->first->prev = pNew; }
- pNew->prev = 0;
- pH->first = pNew;
- }
- pEntry->count++;
- pEntry->chain = pNew;
-}
-
-
-/* Resize the hash table so that it cantains "new_size" buckets.
-** "new_size" must be a power of 2. The hash table might fail
-** to resize if sqliteMalloc() fails.
-*/
-static void rehash(fts1Hash *pH, int new_size){
- struct _fts1ht *new_ht; /* The new hash table */
- fts1HashElem *elem, *next_elem; /* For looping over existing elements */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( (new_size & (new_size-1))==0 );
- new_ht = (struct _fts1ht *)pH->xMalloc( new_size*sizeof(struct _fts1ht) );
- if( new_ht==0 ) return;
- if( pH->ht ) pH->xFree(pH->ht);
- pH->ht = new_ht;
- pH->htsize = new_size;
- xHash = hashFunction(pH->keyClass);
- for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
- next_elem = elem->next;
- insertElement(pH, &new_ht[h], elem);
- }
-}
-
-/* This function (for internal use only) locates an element in an
-** hash table that matches the given key. The hash for this key has
-** already been computed and is passed as the 4th parameter.
-*/
-static fts1HashElem *findElementGivenHash(
- const fts1Hash *pH, /* The pH to be searched */
- const void *pKey, /* The key we are searching for */
- int nKey,
- int h /* The hash for this key. */
-){
- fts1HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- int (*xCompare)(const void*,int,const void*,int); /* comparison function */
-
- if( pH->ht ){
- struct _fts1ht *pEntry = &pH->ht[h];
- elem = pEntry->chain;
- count = pEntry->count;
- xCompare = compareFunction(pH->keyClass);
- while( count-- && elem ){
- if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- }
- return 0;
-}
-
-/* Remove a single entry from the hash table given a pointer to that
-** element and a hash on the element's key.
-*/
-static void removeElementGivenHash(
- fts1Hash *pH, /* The pH containing "elem" */
- fts1HashElem* elem, /* The element to be removed from the pH */
- int h /* Hash value for the element */
-){
- struct _fts1ht *pEntry;
- if( elem->prev ){
- elem->prev->next = elem->next;
- }else{
- pH->first = elem->next;
- }
- if( elem->next ){
- elem->next->prev = elem->prev;
- }
- pEntry = &pH->ht[h];
- if( pEntry->chain==elem ){
- pEntry->chain = elem->next;
- }
- pEntry->count--;
- if( pEntry->count<=0 ){
- pEntry->chain = 0;
- }
- if( pH->copyKey && elem->pKey ){
- pH->xFree(elem->pKey);
- }
- pH->xFree( elem );
- pH->count--;
- if( pH->count<=0 ){
- assert( pH->first==0 );
- assert( pH->count==0 );
- fts1HashClear(pH);
- }
-}
-
-/* Attempt to locate an element of the hash table pH with a key
-** that matches pKey,nKey. Return the data for this element if it is
-** found, or NULL if there is no match.
-*/
-void *sqlite3Fts1HashFind(const fts1Hash *pH, const void *pKey, int nKey){
- int h; /* A hash on key */
- fts1HashElem *elem; /* The element that matches key */
- int (*xHash)(const void*,int); /* The hash function */
-
- if( pH==0 || pH->ht==0 ) return 0;
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- h = (*xHash)(pKey,nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
- return elem ? elem->data : 0;
-}
-
-/* Insert an element into the hash table pH. The key is pKey,nKey
-** and the data is "data".
-**
-** If no element exists with a matching key, then a new
-** element is created. A copy of the key is made if the copyKey
-** flag is set. NULL is returned.
-**
-** If another element already exists with the same key, then the
-** new data replaces the old data and the old data is returned.
-** The key is not copied in this instance. If a malloc fails, then
-** the new data is returned and the hash table is unchanged.
-**
-** If the "data" parameter to this function is NULL, then the
-** element corresponding to "key" is removed from the hash table.
-*/
-void *sqlite3Fts1HashInsert(
- fts1Hash *pH, /* The hash table to insert into */
- const void *pKey, /* The key */
- int nKey, /* Number of bytes in the key */
- void *data /* The data */
-){
- int hraw; /* Raw hash value of the key */
- int h; /* the hash of the key modulo hash table size */
- fts1HashElem *elem; /* Used to loop thru the element list */
- fts1HashElem *new_elem; /* New element added to the pH */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( pH!=0 );
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- hraw = (*xHash)(pKey, nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = findElementGivenHash(pH,pKey,nKey,h);
- if( elem ){
- void *old_data = elem->data;
- if( data==0 ){
- removeElementGivenHash(pH,elem,h);
- }else{
- elem->data = data;
- }
- return old_data;
- }
- if( data==0 ) return 0;
- new_elem = (fts1HashElem*)pH->xMalloc( sizeof(fts1HashElem) );
- if( new_elem==0 ) return data;
- if( pH->copyKey && pKey!=0 ){
- new_elem->pKey = pH->xMalloc( nKey );
- if( new_elem->pKey==0 ){
- pH->xFree(new_elem);
- return data;
- }
- memcpy((void*)new_elem->pKey, pKey, nKey);
- }else{
- new_elem->pKey = (void*)pKey;
- }
- new_elem->nKey = nKey;
- pH->count++;
- if( pH->htsize==0 ){
- rehash(pH,8);
- if( pH->htsize==0 ){
- pH->count = 0;
- pH->xFree(new_elem);
- return data;
- }
- }
- if( pH->count > pH->htsize ){
- rehash(pH,pH->htsize*2);
- }
- assert( pH->htsize>0 );
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- insertElement(pH, &pH->ht[h], new_elem);
- new_elem->data = data;
- return 0;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_hash.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_hash.h
deleted file mode 100644
index 9001152931c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_hash.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the header file for the generic hash-table implementation
-** used in SQLite. We've modified it slightly to serve as a standalone
-** hash table implementation for the full-text indexing module.
-**
-*/
-#ifndef _FTS1_HASH_H_
-#define _FTS1_HASH_H_
-
-/* Forward declarations of structures. */
-typedef struct fts1Hash fts1Hash;
-typedef struct fts1HashElem fts1HashElem;
-
-/* A complete hash table is an instance of the following structure.
-** The internals of this structure are intended to be opaque -- client
-** code should not attempt to access or modify the fields of this structure
-** directly. Change this structure only by using the routines below.
-** However, many of the "procedures" and "functions" for modifying and
-** accessing this structure are really macros, so we can't really make
-** this structure opaque.
-*/
-struct fts1Hash {
- char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */
- char copyKey; /* True if copy of key made on insert */
- int count; /* Number of entries in this table */
- fts1HashElem *first; /* The first element of the array */
- void *(*xMalloc)(int); /* malloc() function to use */
- void (*xFree)(void *); /* free() function to use */
- int htsize; /* Number of buckets in the hash table */
- struct _fts1ht { /* the hash table */
- int count; /* Number of entries with this hash */
- fts1HashElem *chain; /* Pointer to first entry with this hash */
- } *ht;
-};
-
-/* Each element in the hash table is an instance of the following
-** structure. All elements are stored on a single doubly-linked list.
-**
-** Again, this structure is intended to be opaque, but it can't really
-** be opaque because it is used by macros.
-*/
-struct fts1HashElem {
- fts1HashElem *next, *prev; /* Next and previous elements in the table */
- void *data; /* Data associated with this element */
- void *pKey; int nKey; /* Key associated with this element */
-};
-
-/*
-** There are 2 different modes of operation for a hash table:
-**
-** FTS1_HASH_STRING pKey points to a string that is nKey bytes long
-** (including the null-terminator, if any). Case
-** is respected in comparisons.
-**
-** FTS1_HASH_BINARY pKey points to binary data nKey bytes long.
-** memcmp() is used to compare keys.
-**
-** A copy of the key is made if the copyKey parameter to fts1HashInit is 1.
-*/
-#define FTS1_HASH_STRING 1
-#define FTS1_HASH_BINARY 2
-
-/*
-** Access routines. To delete, insert a NULL pointer.
-*/
-void sqlite3Fts1HashInit(fts1Hash*, int keytype, int copyKey);
-void *sqlite3Fts1HashInsert(fts1Hash*, const void *pKey, int nKey, void *pData);
-void *sqlite3Fts1HashFind(const fts1Hash*, const void *pKey, int nKey);
-void sqlite3Fts1HashClear(fts1Hash*);
-
-/*
-** Shorthand for the functions above
-*/
-#define fts1HashInit sqlite3Fts1HashInit
-#define fts1HashInsert sqlite3Fts1HashInsert
-#define fts1HashFind sqlite3Fts1HashFind
-#define fts1HashClear sqlite3Fts1HashClear
-
-/*
-** Macros for looping over all elements of a hash table. The idiom is
-** like this:
-**
-** fts1Hash h;
-** fts1HashElem *p;
-** ...
-** for(p=fts1HashFirst(&h); p; p=fts1HashNext(p)){
-** SomeStructure *pData = fts1HashData(p);
-** // do something with pData
-** }
-*/
-#define fts1HashFirst(H) ((H)->first)
-#define fts1HashNext(E) ((E)->next)
-#define fts1HashData(E) ((E)->data)
-#define fts1HashKey(E) ((E)->pKey)
-#define fts1HashKeysize(E) ((E)->nKey)
-
-/*
-** Number of entries in a hash table
-*/
-#define fts1HashCount(H) ((H)->count)
-
-#endif /* _FTS1_HASH_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_porter.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_porter.c
deleted file mode 100644
index 1d26236681a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_porter.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
-** 2006 September 30
-**
-** 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.
-**
-*************************************************************************
-** Implementation of the full-text-search tokenizer that implements
-** a Porter stemmer.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS1 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS1 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)
-
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "fts1_tokenizer.h"
-
-/*
-** Class derived from sqlite3_tokenizer
-*/
-typedef struct porter_tokenizer {
- sqlite3_tokenizer base; /* Base class */
-} porter_tokenizer;
-
-/*
-** Class derived from sqlit3_tokenizer_cursor
-*/
-typedef struct porter_tokenizer_cursor {
- sqlite3_tokenizer_cursor base;
- const char *zInput; /* input we are tokenizing */
- int nInput; /* size of the input */
- int iOffset; /* current position in zInput */
- int iToken; /* index of next token to be returned */
- char *zToken; /* storage for current token */
- int nAllocated; /* space allocated to zToken buffer */
-} porter_tokenizer_cursor;
-
-
-/* Forward declaration */
-static const sqlite3_tokenizer_module porterTokenizerModule;
-
-
-/*
-** Create a new tokenizer instance.
-*/
-static int porterCreate(
- int argc, const char * const *argv,
- sqlite3_tokenizer **ppTokenizer
-){
- porter_tokenizer *t;
- t = (porter_tokenizer *) calloc(sizeof(*t), 1);
- if( t==NULL ) return SQLITE_NOMEM;
-
- *ppTokenizer = &t->base;
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int porterDestroy(sqlite3_tokenizer *pTokenizer){
- free(pTokenizer);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is zInput[0..nInput-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int porterOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *zInput, int nInput, /* String to be tokenized */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- porter_tokenizer_cursor *c;
-
- c = (porter_tokenizer_cursor *) malloc(sizeof(*c));
- if( c==NULL ) return SQLITE_NOMEM;
-
- c->zInput = zInput;
- if( zInput==0 ){
- c->nInput = 0;
- }else if( nInput<0 ){
- c->nInput = (int)strlen(zInput);
- }else{
- c->nInput = nInput;
- }
- c->iOffset = 0; /* start tokenizing at the beginning */
- c->iToken = 0;
- c->zToken = NULL; /* no space allocated, yet. */
- c->nAllocated = 0;
-
- *ppCursor = &c->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to
-** porterOpen() above.
-*/
-static int porterClose(sqlite3_tokenizer_cursor *pCursor){
- porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
- free(c->zToken);
- free(c);
- return SQLITE_OK;
-}
-/*
-** Vowel or consonant
-*/
-static const char cType[] = {
- 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
- 1, 1, 1, 2, 1
-};
-
-/*
-** isConsonant() and isVowel() determine if their first character in
-** the string they point to is a consonant or a vowel, according
-** to Porter ruls.
-**
-** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
-** 'Y' is a consonant unless it follows another consonant,
-** in which case it is a vowel.
-**
-** In these routine, the letters are in reverse order. So the 'y' rule
-** is that 'y' is a consonant unless it is followed by another
-** consonent.
-*/
-static int isVowel(const char*);
-static int isConsonant(const char *z){
- int j;
- char x = *z;
- if( x==0 ) return 0;
- assert( x>='a' && x<='z' );
- j = cType[x-'a'];
- if( j<2 ) return j;
- return z[1]==0 || isVowel(z + 1);
-}
-static int isVowel(const char *z){
- int j;
- char x = *z;
- if( x==0 ) return 0;
- assert( x>='a' && x<='z' );
- j = cType[x-'a'];
- if( j<2 ) return 1-j;
- return isConsonant(z + 1);
-}
-
-/*
-** Let any sequence of one or more vowels be represented by V and let
-** C be sequence of one or more consonants. Then every word can be
-** represented as:
-**
-** [C] (VC){m} [V]
-**
-** In prose: A word is an optional consonant followed by zero or
-** vowel-consonant pairs followed by an optional vowel. "m" is the
-** number of vowel consonant pairs. This routine computes the value
-** of m for the first i bytes of a word.
-**
-** Return true if the m-value for z is 1 or more. In other words,
-** return true if z contains at least one vowel that is followed
-** by a consonant.
-**
-** In this routine z[] is in reverse order. So we are really looking
-** for an instance of of a consonant followed by a vowel.
-*/
-static int m_gt_0(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/* Like mgt0 above except we are looking for a value of m which is
-** exactly 1
-*/
-static int m_eq_1(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 1;
- while( isConsonant(z) ){ z++; }
- return *z==0;
-}
-
-/* Like mgt0 above except we are looking for a value of m>1 instead
-** or m>0
-*/
-static int m_gt_1(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/*
-** Return TRUE if there is a vowel anywhere within z[0..n-1]
-*/
-static int hasVowel(const char *z){
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/*
-** Return TRUE if the word ends in a double consonant.
-**
-** The text is reversed here. So we are really looking at
-** the first two characters of z[].
-*/
-static int doubleConsonant(const char *z){
- return isConsonant(z) && z[0]==z[1] && isConsonant(z+1);
-}
-
-/*
-** Return TRUE if the word ends with three letters which
-** are consonant-vowel-consonent and where the final consonant
-** is not 'w', 'x', or 'y'.
-**
-** The word is reversed here. So we are really checking the
-** first three letters and the first one cannot be in [wxy].
-*/
-static int star_oh(const char *z){
- return
- z[0]!=0 && isConsonant(z) &&
- z[0]!='w' && z[0]!='x' && z[0]!='y' &&
- z[1]!=0 && isVowel(z+1) &&
- z[2]!=0 && isConsonant(z+2);
-}
-
-/*
-** If the word ends with zFrom and xCond() is true for the stem
-** of the word that preceeds the zFrom ending, then change the
-** ending to zTo.
-**
-** The input word *pz and zFrom are both in reverse order. zTo
-** is in normal order.
-**
-** Return TRUE if zFrom matches. Return FALSE if zFrom does not
-** match. Not that TRUE is returned even if xCond() fails and
-** no substitution occurs.
-*/
-static int stem(
- char **pz, /* The word being stemmed (Reversed) */
- const char *zFrom, /* If the ending matches this... (Reversed) */
- const char *zTo, /* ... change the ending to this (not reversed) */
- int (*xCond)(const char*) /* Condition that must be true */
-){
- char *z = *pz;
- while( *zFrom && *zFrom==*z ){ z++; zFrom++; }
- if( *zFrom!=0 ) return 0;
- if( xCond && !xCond(z) ) return 1;
- while( *zTo ){
- *(--z) = *(zTo++);
- }
- *pz = z;
- return 1;
-}
-
-/*
-** This is the fallback stemmer used when the porter stemmer is
-** inappropriate. The input word is copied into the output with
-** US-ASCII case folding. If the input word is too long (more
-** than 20 bytes if it contains no digits or more than 6 bytes if
-** it contains digits) then word is truncated to 20 or 6 bytes
-** by taking 10 or 3 bytes from the beginning and end.
-*/
-static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
- int i, mx, j;
- int hasDigit = 0;
- for(i=0; i<nIn; i++){
- int c = zIn[i];
- if( c>='A' && c<='Z' ){
- zOut[i] = c - 'A' + 'a';
- }else{
- if( c>='0' && c<='9' ) hasDigit = 1;
- zOut[i] = c;
- }
- }
- mx = hasDigit ? 3 : 10;
- if( nIn>mx*2 ){
- for(j=mx, i=nIn-mx; i<nIn; i++, j++){
- zOut[j] = zOut[i];
- }
- i = j;
- }
- zOut[i] = 0;
- *pnOut = i;
-}
-
-
-/*
-** Stem the input word zIn[0..nIn-1]. Store the output in zOut.
-** zOut is at least big enough to hold nIn bytes. Write the actual
-** size of the output word (exclusive of the '\0' terminator) into *pnOut.
-**
-** Any upper-case characters in the US-ASCII character set ([A-Z])
-** are converted to lower case. Upper-case UTF characters are
-** unchanged.
-**
-** Words that are longer than about 20 bytes are stemmed by retaining
-** a few bytes from the beginning and the end of the word. If the
-** word contains digits, 3 bytes are taken from the beginning and
-** 3 bytes from the end. For long words without digits, 10 bytes
-** are taken from each end. US-ASCII case folding still applies.
-**
-** If the input word contains not digits but does characters not
-** in [a-zA-Z] then no stemming is attempted and this routine just
-** copies the input into the input into the output with US-ASCII
-** case folding.
-**
-** Stemming never increases the length of the word. So there is
-** no chance of overflowing the zOut buffer.
-*/
-static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
- int i, j, c;
- char zReverse[28];
- char *z, *z2;
- if( nIn<3 || nIn>=sizeof(zReverse)-7 ){
- /* The word is too big or too small for the porter stemmer.
- ** Fallback to the copy stemmer */
- copy_stemmer(zIn, nIn, zOut, pnOut);
- return;
- }
- for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){
- c = zIn[i];
- if( c>='A' && c<='Z' ){
- zReverse[j] = c + 'a' - 'A';
- }else if( c>='a' && c<='z' ){
- zReverse[j] = c;
- }else{
- /* The use of a character not in [a-zA-Z] means that we fallback
- ** to the copy stemmer */
- copy_stemmer(zIn, nIn, zOut, pnOut);
- return;
- }
- }
- memset(&zReverse[sizeof(zReverse)-5], 0, 5);
- z = &zReverse[j+1];
-
-
- /* Step 1a */
- if( z[0]=='s' ){
- if(
- !stem(&z, "sess", "ss", 0) &&
- !stem(&z, "sei", "i", 0) &&
- !stem(&z, "ss", "ss", 0)
- ){
- z++;
- }
- }
-
- /* Step 1b */
- z2 = z;
- if( stem(&z, "dee", "ee", m_gt_0) ){
- /* Do nothing. The work was all in the test */
- }else if(
- (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel))
- && z!=z2
- ){
- if( stem(&z, "ta", "ate", 0) ||
- stem(&z, "lb", "ble", 0) ||
- stem(&z, "zi", "ize", 0) ){
- /* Do nothing. The work was all in the test */
- }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){
- z++;
- }else if( m_eq_1(z) && star_oh(z) ){
- *(--z) = 'e';
- }
- }
-
- /* Step 1c */
- if( z[0]=='y' && hasVowel(z+1) ){
- z[0] = 'i';
- }
-
- /* Step 2 */
- switch( z[1] ){
- case 'a':
- stem(&z, "lanoita", "ate", m_gt_0) ||
- stem(&z, "lanoit", "tion", m_gt_0);
- break;
- case 'c':
- stem(&z, "icne", "ence", m_gt_0) ||
- stem(&z, "icna", "ance", m_gt_0);
- break;
- case 'e':
- stem(&z, "rezi", "ize", m_gt_0);
- break;
- case 'g':
- stem(&z, "igol", "log", m_gt_0);
- break;
- case 'l':
- stem(&z, "ilb", "ble", m_gt_0) ||
- stem(&z, "illa", "al", m_gt_0) ||
- stem(&z, "iltne", "ent", m_gt_0) ||
- stem(&z, "ile", "e", m_gt_0) ||
- stem(&z, "ilsuo", "ous", m_gt_0);
- break;
- case 'o':
- stem(&z, "noitazi", "ize", m_gt_0) ||
- stem(&z, "noita", "ate", m_gt_0) ||
- stem(&z, "rota", "ate", m_gt_0);
- break;
- case 's':
- stem(&z, "msila", "al", m_gt_0) ||
- stem(&z, "ssenevi", "ive", m_gt_0) ||
- stem(&z, "ssenluf", "ful", m_gt_0) ||
- stem(&z, "ssensuo", "ous", m_gt_0);
- break;
- case 't':
- stem(&z, "itila", "al", m_gt_0) ||
- stem(&z, "itivi", "ive", m_gt_0) ||
- stem(&z, "itilib", "ble", m_gt_0);
- break;
- }
-
- /* Step 3 */
- switch( z[0] ){
- case 'e':
- stem(&z, "etaci", "ic", m_gt_0) ||
- stem(&z, "evita", "", m_gt_0) ||
- stem(&z, "ezila", "al", m_gt_0);
- break;
- case 'i':
- stem(&z, "itici", "ic", m_gt_0);
- break;
- case 'l':
- stem(&z, "laci", "ic", m_gt_0) ||
- stem(&z, "luf", "", m_gt_0);
- break;
- case 's':
- stem(&z, "ssen", "", m_gt_0);
- break;
- }
-
- /* Step 4 */
- switch( z[1] ){
- case 'a':
- if( z[0]=='l' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'c':
- if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){
- z += 4;
- }
- break;
- case 'e':
- if( z[0]=='r' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'i':
- if( z[0]=='c' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'l':
- if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){
- z += 4;
- }
- break;
- case 'n':
- if( z[0]=='t' ){
- if( z[2]=='a' ){
- if( m_gt_1(z+3) ){
- z += 3;
- }
- }else if( z[2]=='e' ){
- stem(&z, "tneme", "", m_gt_1) ||
- stem(&z, "tnem", "", m_gt_1) ||
- stem(&z, "tne", "", m_gt_1);
- }
- }
- break;
- case 'o':
- if( z[0]=='u' ){
- if( m_gt_1(z+2) ){
- z += 2;
- }
- }else if( z[3]=='s' || z[3]=='t' ){
- stem(&z, "noi", "", m_gt_1);
- }
- break;
- case 's':
- if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- case 't':
- stem(&z, "eta", "", m_gt_1) ||
- stem(&z, "iti", "", m_gt_1);
- break;
- case 'u':
- if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- case 'v':
- case 'z':
- if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- }
-
- /* Step 5a */
- if( z[0]=='e' ){
- if( m_gt_1(z+1) ){
- z++;
- }else if( m_eq_1(z+1) && !star_oh(z+1) ){
- z++;
- }
- }
-
- /* Step 5b */
- if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){
- z++;
- }
-
- /* z[] is now the stemmed word in reverse order. Flip it back
- ** around into forward order and return.
- */
- *pnOut = i = strlen(z);
- zOut[i] = 0;
- while( *z ){
- zOut[--i] = *(z++);
- }
-}
-
-/*
-** Characters that can be part of a token. We assume any character
-** whose value is greater than 0x80 (any UTF character) can be
-** part of a token. In other words, delimiters all must have
-** values of 0x7f or lower.
-*/
-static const char isIdChar[] = {
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
-};
-#define idChar(C) (((ch=C)&0x80)!=0 || (ch>0x2f && isIdChar[ch-0x30]))
-#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !isIdChar[ch-0x30]))
-
-/*
-** Extract the next token from a tokenization cursor. The cursor must
-** have been opened by a prior call to porterOpen().
-*/
-static int porterNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */
- const char **pzToken, /* OUT: *pzToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
- const char *z = c->zInput;
-
- while( c->iOffset<c->nInput ){
- int iStartOffset, ch;
-
- /* Scan past delimiter characters */
- while( c->iOffset<c->nInput && isDelim(z[c->iOffset]) ){
- c->iOffset++;
- }
-
- /* Count non-delimiter characters. */
- iStartOffset = c->iOffset;
- while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
- c->iOffset++;
- }
-
- if( c->iOffset>iStartOffset ){
- int n = c->iOffset-iStartOffset;
- if( n>c->nAllocated ){
- c->nAllocated = n+20;
- c->zToken = realloc(c->zToken, c->nAllocated);
- if( c->zToken==NULL ) return SQLITE_NOMEM;
- }
- porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
- *pzToken = c->zToken;
- *piStartOffset = iStartOffset;
- *piEndOffset = c->iOffset;
- *piPosition = c->iToken++;
- return SQLITE_OK;
- }
- }
- return SQLITE_DONE;
-}
-
-/*
-** The set of routines that implement the porter-stemmer tokenizer
-*/
-static const sqlite3_tokenizer_module porterTokenizerModule = {
- 0,
- porterCreate,
- porterDestroy,
- porterOpen,
- porterClose,
- porterNext,
-};
-
-/*
-** Allocate a new porter tokenizer. Return a pointer to the new
-** tokenizer in *ppModule
-*/
-void sqlite3Fts1PorterTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &porterTokenizerModule;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_tokenizer.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_tokenizer.h
deleted file mode 100644
index a48cb745193..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_tokenizer.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-** 2006 July 10
-**
-** The author disclaims copyright to this source code.
-**
-*************************************************************************
-** Defines the interface to tokenizers used by fulltext-search. There
-** are three basic components:
-**
-** sqlite3_tokenizer_module is a singleton defining the tokenizer
-** interface functions. This is essentially the class structure for
-** tokenizers.
-**
-** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
-** including customization information defined at creation time.
-**
-** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
-** tokens from a particular input.
-*/
-#ifndef _FTS1_TOKENIZER_H_
-#define _FTS1_TOKENIZER_H_
-
-/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
-** If tokenizers are to be allowed to call sqlite3_*() functions, then
-** we will need a way to register the API consistently.
-*/
-#include "sqlite3.h"
-
-/*
-** Structures used by the tokenizer interface.
-*/
-typedef struct sqlite3_tokenizer sqlite3_tokenizer;
-typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
-typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
-
-struct sqlite3_tokenizer_module {
- int iVersion; /* currently 0 */
-
- /*
- ** Create and destroy a tokenizer. argc/argv are passed down from
- ** the fulltext virtual table creation to allow customization.
- */
- int (*xCreate)(int argc, const char *const*argv,
- sqlite3_tokenizer **ppTokenizer);
- int (*xDestroy)(sqlite3_tokenizer *pTokenizer);
-
- /*
- ** Tokenize a particular input. Call xOpen() to prepare to
- ** tokenize, xNext() repeatedly until it returns SQLITE_DONE, then
- ** xClose() to free any internal state. The pInput passed to
- ** xOpen() must exist until the cursor is closed. The ppToken
- ** result from xNext() is only valid until the next call to xNext()
- ** or until xClose() is called.
- */
- /* TODO(shess) current implementation requires pInput to be
- ** nul-terminated. This should either be fixed, or pInput/nBytes
- ** should be converted to zInput.
- */
- int (*xOpen)(sqlite3_tokenizer *pTokenizer,
- const char *pInput, int nBytes,
- sqlite3_tokenizer_cursor **ppCursor);
- int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
- int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
- const char **ppToken, int *pnBytes,
- int *piStartOffset, int *piEndOffset, int *piPosition);
-};
-
-struct sqlite3_tokenizer {
- const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
- /* Tokenizer implementations will typically add additional fields */
-};
-
-struct sqlite3_tokenizer_cursor {
- sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */
- /* Tokenizer implementations will typically add additional fields */
-};
-
-/*
-** Get the module for a tokenizer which generates tokens based on a
-** set of non-token characters. The default is to break tokens at any
-** non-alnum character, though the set of delimiters can also be
-** specified by the first argv argument to xCreate().
-*/
-/* TODO(shess) This doesn't belong here. Need some sort of
-** registration process.
-*/
-void sqlite3Fts1SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-void sqlite3Fts1PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-
-#endif /* _FTS1_TOKENIZER_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_tokenizer1.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_tokenizer1.c
deleted file mode 100644
index f58fba8f8e6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fts1_tokenizer1.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
-** The author disclaims copyright to this source code.
-**
-*************************************************************************
-** Implementation of the "simple" full-text-search tokenizer.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS1 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS1 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)
-
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "fts1_tokenizer.h"
-
-typedef struct simple_tokenizer {
- sqlite3_tokenizer base;
- char delim[128]; /* flag ASCII delimiters */
-} simple_tokenizer;
-
-typedef struct simple_tokenizer_cursor {
- sqlite3_tokenizer_cursor base;
- const char *pInput; /* input we are tokenizing */
- int nBytes; /* size of the input */
- int iOffset; /* current position in pInput */
- int iToken; /* index of next token to be returned */
- char *pToken; /* storage for current token */
- int nTokenAllocated; /* space allocated to zToken buffer */
-} simple_tokenizer_cursor;
-
-
-/* Forward declaration */
-static const sqlite3_tokenizer_module simpleTokenizerModule;
-
-static int isDelim(simple_tokenizer *t, unsigned char c){
- return c<0x80 && t->delim[c];
-}
-
-/*
-** Create a new tokenizer instance.
-*/
-static int simpleCreate(
- int argc, const char * const *argv,
- sqlite3_tokenizer **ppTokenizer
-){
- simple_tokenizer *t;
-
- t = (simple_tokenizer *) calloc(sizeof(*t), 1);
- if( t==NULL ) return SQLITE_NOMEM;
-
- /* TODO(shess) Delimiters need to remain the same from run to run,
- ** else we need to reindex. One solution would be a meta-table to
- ** track such information in the database, then we'd only want this
- ** information on the initial create.
- */
- if( argc>1 ){
- int i, n = strlen(argv[1]);
- for(i=0; i<n; i++){
- unsigned char ch = argv[1][i];
- /* We explicitly don't support UTF-8 delimiters for now. */
- if( ch>=0x80 ){
- free(t);
- return SQLITE_ERROR;
- }
- t->delim[ch] = 1;
- }
- } else {
- /* Mark non-alphanumeric ASCII characters as delimiters */
- int i;
- for(i=1; i<0x80; i++){
- t->delim[i] = !isalnum(i);
- }
- }
-
- *ppTokenizer = &t->base;
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
- free(pTokenizer);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int simpleOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *pInput, int nBytes, /* String to be tokenized */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- simple_tokenizer_cursor *c;
-
- c = (simple_tokenizer_cursor *) malloc(sizeof(*c));
- if( c==NULL ) return SQLITE_NOMEM;
-
- c->pInput = pInput;
- if( pInput==0 ){
- c->nBytes = 0;
- }else if( nBytes<0 ){
- c->nBytes = (int)strlen(pInput);
- }else{
- c->nBytes = nBytes;
- }
- c->iOffset = 0; /* start tokenizing at the beginning */
- c->iToken = 0;
- c->pToken = NULL; /* no space allocated, yet. */
- c->nTokenAllocated = 0;
-
- *ppCursor = &c->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to
-** simpleOpen() above.
-*/
-static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
- simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
- free(c->pToken);
- free(c);
- return SQLITE_OK;
-}
-
-/*
-** Extract the next token from a tokenization cursor. The cursor must
-** have been opened by a prior call to simpleOpen().
-*/
-static int simpleNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
- const char **ppToken, /* OUT: *ppToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
- simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
- unsigned char *p = (unsigned char *)c->pInput;
-
- while( c->iOffset<c->nBytes ){
- int iStartOffset;
-
- /* Scan past delimiter characters */
- while( c->iOffset<c->nBytes && isDelim(t, p[c->iOffset]) ){
- c->iOffset++;
- }
-
- /* Count non-delimiter characters. */
- iStartOffset = c->iOffset;
- while( c->iOffset<c->nBytes && !isDelim(t, p[c->iOffset]) ){
- c->iOffset++;
- }
-
- if( c->iOffset>iStartOffset ){
- int i, n = c->iOffset-iStartOffset;
- if( n>c->nTokenAllocated ){
- c->nTokenAllocated = n+20;
- c->pToken = realloc(c->pToken, c->nTokenAllocated);
- if( c->pToken==NULL ) return SQLITE_NOMEM;
- }
- for(i=0; i<n; i++){
- /* TODO(shess) This needs expansion to handle UTF-8
- ** case-insensitivity.
- */
- unsigned char ch = p[iStartOffset+i];
- c->pToken[i] = ch<0x80 ? tolower(ch) : ch;
- }
- *ppToken = c->pToken;
- *pnBytes = n;
- *piStartOffset = iStartOffset;
- *piEndOffset = c->iOffset;
- *piPosition = c->iToken++;
-
- return SQLITE_OK;
- }
- }
- return SQLITE_DONE;
-}
-
-/*
-** The set of routines that implement the simple tokenizer
-*/
-static const sqlite3_tokenizer_module simpleTokenizerModule = {
- 0,
- simpleCreate,
- simpleDestroy,
- simpleOpen,
- simpleClose,
- simpleNext,
-};
-
-/*
-** Allocate a new simple tokenizer. Return a pointer to the new
-** tokenizer in *ppModule
-*/
-void sqlite3Fts1SimpleTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &simpleTokenizerModule;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fulltext.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fulltext.c
deleted file mode 100644
index 313ff303e1a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fulltext.c
+++ /dev/null
@@ -1,1511 +0,0 @@
-/* The author disclaims copyright to this source code.
- *
- * This is an SQLite module implementing full-text search.
- */
-
-#include <assert.h>
-#if !defined(__APPLE__)
-#include <malloc.h>
-#else
-#include <stdlib.h>
-#endif
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "fulltext.h"
-#include "ft_hash.h"
-#include "tokenizer.h"
-#include "sqlite3.h"
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-/* utility functions */
-
-/* We encode variable-length integers in little-endian order using seven bits
- * per byte as follows:
-**
-** KEY:
-** A = 0xxxxxxx 7 bits of data and one flag bit
-** B = 1xxxxxxx 7 bits of data and one flag bit
-**
-** 7 bits - A
-** 14 bits - BA
-** 21 bits - BBA
-** and so on.
-*/
-
-/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */
-#define VARINT_MAX 10
-
-/* Write a 64-bit variable-length integer to memory starting at p[0].
- * The length of data written will be between 1 and VARINT_MAX bytes.
- * The number of bytes written is returned. */
-static int putVarint(char *p, sqlite_int64 v){
- unsigned char *q = (unsigned char *) p;
- sqlite_uint64 vu = v;
- do{
- *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
- vu >>= 7;
- }while( vu!=0 );
- q[-1] &= 0x7f; /* turn off high bit in final byte */
- assert( q - (unsigned char *)p <= VARINT_MAX );
- return (int) (q - (unsigned char *)p);
-}
-
-/* Read a 64-bit variable-length integer from memory starting at p[0].
- * Return the number of bytes read, or 0 on error.
- * The value is stored in *v. */
-static int getVarint(const char *p, sqlite_int64 *v){
- const unsigned char *q = (const unsigned char *) p;
- sqlite_uint64 x = 0, y = 1;
- while( (*q & 0x80) == 0x80 ){
- x += y * (*q++ & 0x7f);
- y <<= 7;
- if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */
- assert( 0 );
- return 0;
- }
- }
- x += y * (*q++);
- *v = (sqlite_int64) x;
- return (int) (q - (unsigned char *)p);
-}
-
-static int getVarint32(const char *p, int *pi){
- sqlite_int64 i;
- int ret = getVarint(p, &i);
- *pi = (int) i;
- assert( *pi==i );
- return ret;
-}
-
-/*** Document lists ***
- *
- * A document list holds a sorted list of varint-encoded document IDs.
- *
- * A doclist with type DL_POSITIONS_OFFSETS is stored like this:
- *
- * array {
- * varint docid;
- * array {
- * varint position; (delta from previous position plus 1, or 0 for end)
- * varint startOffset; (delta from previous startOffset)
- * varint endOffset; (delta from startOffset)
- * }
- * }
- *
- * Here, array { X } means zero or more occurrences of X, adjacent in memory.
- *
- * A doclist with type DL_POSITIONS is like the above, but holds only docids
- * and positions without offset information.
- *
- * A doclist with type DL_DOCIDS is like the above, but holds only docids
- * without positions or offset information.
- *
- * On disk, every document list has positions and offsets, so we don't bother
- * to serialize a doclist's type.
- *
- * We don't yet delta-encode document IDs; doing so will probably be a
- * modest win.
- *
- * NOTE(shess) I've thought of a slightly (1%) better offset encoding.
- * After the first offset, estimate the next offset by using the
- * current token position and the previous token position and offset,
- * offset to handle some variance. So the estimate would be
- * (iPosition*w->iStartOffset/w->iPosition-64), which is delta-encoded
- * as normal. Offsets more than 64 chars from the estimate are
- * encoded as the delta to the previous start offset + 128. An
- * additional tiny increment can be gained by using the end offset of
- * the previous token to make the estimate a tiny bit more precise.
-*/
-
-typedef enum DocListType {
- DL_DOCIDS, /* docids only */
- DL_POSITIONS, /* docids + positions */
- DL_POSITIONS_OFFSETS /* docids + positions + offsets */
-} DocListType;
-
-typedef struct DocList {
- char *pData;
- int nData;
- DocListType iType;
- int iLastPos; /* the last position written */
- int iLastOffset; /* the last start offset written */
-} DocList;
-
-/* Initialize a new DocList to hold the given data. */
-static void docListInit(DocList *d, DocListType iType,
- const char *pData, int nData){
- d->nData = nData;
- if( nData>0 ){
- d->pData = malloc(nData);
- memcpy(d->pData, pData, nData);
- } else {
- d->pData = NULL;
- }
- d->iType = iType;
- d->iLastPos = 0;
- d->iLastOffset = 0;
-}
-
-/* Create a new dynamically-allocated DocList. */
-static DocList *docListNew(DocListType iType){
- DocList *d = (DocList *) malloc(sizeof(DocList));
- docListInit(d, iType, 0, 0);
- return d;
-}
-
-static void docListDestroy(DocList *d){
- free(d->pData);
-#ifndef NDEBUG
- memset(d, 0x55, sizeof(*d));
-#endif
-}
-
-static void docListDelete(DocList *d){
- docListDestroy(d);
- free(d);
-}
-
-static char *docListEnd(DocList *d){
- return d->pData + d->nData;
-}
-
-/* Append a varint to a DocList's data. */
-static void appendVarint(DocList *d, sqlite_int64 i){
- char c[VARINT_MAX];
- int n = putVarint(c, i);
- d->pData = realloc(d->pData, d->nData + n);
- memcpy(d->pData + d->nData, c, n);
- d->nData += n;
-}
-
-static void docListAddDocid(DocList *d, sqlite_int64 iDocid){
- appendVarint(d, iDocid);
- d->iLastPos = 0;
-}
-
-/* Add a position to the last position list in a doclist. */
-static void docListAddPos(DocList *d, int iPos){
- assert( d->iType>=DL_POSITIONS );
- appendVarint(d, iPos-d->iLastPos+1);
- d->iLastPos = iPos;
-}
-
-static void docListAddPosOffset(DocList *d, int iPos,
- int iStartOffset, int iEndOffset){
- assert( d->iType==DL_POSITIONS_OFFSETS );
- docListAddPos(d, iPos);
- appendVarint(d, iStartOffset-d->iLastOffset);
- d->iLastOffset = iStartOffset;
- appendVarint(d, iEndOffset-iStartOffset);
-}
-
-/* Terminate the last position list in the given doclist. */
-static void docListAddEndPos(DocList *d){
- appendVarint(d, 0);
-}
-
-typedef struct DocListReader {
- DocList *pDoclist;
- char *p;
- int iLastPos; /* the last position read */
-} DocListReader;
-
-static void readerInit(DocListReader *r, DocList *pDoclist){
- r->pDoclist = pDoclist;
- if( pDoclist!=NULL ){
- r->p = pDoclist->pData;
- }
- r->iLastPos = 0;
-}
-
-static int readerAtEnd(DocListReader *pReader){
- return pReader->p >= docListEnd(pReader->pDoclist);
-}
-
-/* Peek at the next docid without advancing the read pointer. */
-static sqlite_int64 peekDocid(DocListReader *pReader){
- sqlite_int64 ret;
- assert( !readerAtEnd(pReader) );
- getVarint(pReader->p, &ret);
- return ret;
-}
-
-/* Read the next docid. */
-static sqlite_int64 readDocid(DocListReader *pReader){
- sqlite_int64 ret;
- assert( !readerAtEnd(pReader) );
- pReader->p += getVarint(pReader->p, &ret);
- pReader->iLastPos = 0;
- return ret;
-}
-
-/* Read the next position from a position list.
- * Returns the position, or -1 at the end of the list. */
-static int readPosition(DocListReader *pReader){
- int i;
- int iType = pReader->pDoclist->iType;
- assert( iType>=DL_POSITIONS );
- assert( !readerAtEnd(pReader) );
-
- pReader->p += getVarint32(pReader->p, &i);
- if( i==0 ){
- pReader->iLastPos = -1;
- return -1;
- }
- pReader->iLastPos += ((int) i)-1;
- if( iType>=DL_POSITIONS_OFFSETS ){
- /* Skip over offsets, ignoring them for now. */
- int iStart, iEnd;
- pReader->p += getVarint32(pReader->p, &iStart);
- pReader->p += getVarint32(pReader->p, &iEnd);
- }
- return pReader->iLastPos;
-}
-
-/* Skip past the end of a position list. */
-static void skipPositionList(DocListReader *pReader){
- while( readPosition(pReader)!=-1 )
- ;
-}
-
-/* Skip over a docid, including its position list if the doclist has
- * positions. */
-static void skipDocument(DocListReader *pReader){
- readDocid(pReader);
- if( pReader->pDoclist->iType >= DL_POSITIONS ){
- skipPositionList(pReader);
- }
-}
-
-static sqlite_int64 firstDocid(DocList *d){
- DocListReader r;
- readerInit(&r, d);
- return readDocid(&r);
-}
-
-/* Doclist multi-tool. Pass pUpdate==NULL to delete the indicated docid;
- * otherwise pUpdate, which must contain only the single docid [iDocid], is
- * inserted (if not present) or updated (if already present). */
-static int docListUpdate(DocList *d, sqlite_int64 iDocid, DocList *pUpdate){
- int modified = 0;
- DocListReader reader;
- char *p;
-
- if( pUpdate!=NULL ){
- assert( d->iType==pUpdate->iType);
- assert( iDocid==firstDocid(pUpdate) );
- }
-
- readerInit(&reader, d);
- while( !readerAtEnd(&reader) && peekDocid(&reader)<iDocid ){
- skipDocument(&reader);
- }
-
- p = reader.p;
- /* Delete if there is a matching element. */
- if( !readerAtEnd(&reader) && iDocid==peekDocid(&reader) ){
- skipDocument(&reader);
- memmove(p, reader.p, docListEnd(d) - reader.p);
- d->nData -= (reader.p - p);
- modified = 1;
- }
-
- /* Insert if indicated. */
- if( pUpdate!=NULL ){
- int iDoclist = p-d->pData;
- docListAddEndPos(pUpdate);
-
- d->pData = realloc(d->pData, d->nData+pUpdate->nData);
- p = d->pData + iDoclist;
-
- memmove(p+pUpdate->nData, p, docListEnd(d) - p);
- memcpy(p, pUpdate->pData, pUpdate->nData);
- d->nData += pUpdate->nData;
- modified = 1;
- }
-
- return modified;
-}
-
-/* Split the second half of doclist d into a separate doclist d2. Returns 1
- * if successful, or 0 if d contains a single document and hence can't be
- * split. */
-static int docListSplit(DocList *d, DocList *d2){
- const char *pSplitPoint = d->pData + d->nData / 2;
- DocListReader reader;
-
- readerInit(&reader, d);
- while( reader.p<pSplitPoint ){
- skipDocument(&reader);
- }
- if( readerAtEnd(&reader) ) return 0;
- docListInit(d2, d->iType, reader.p, docListEnd(d) - reader.p);
- d->nData = reader.p - d->pData;
- d->pData = realloc(d->pData, d->nData);
- return 1;
-}
-
-/* A DocListMerge computes the AND of an in-memory DocList [in] and a chunked
- * on-disk doclist, resulting in another in-memory DocList [out]. [in]
- * and [out] may or may not store position information according to the
- * caller's wishes. The on-disk doclist always comes with positions.
- *
- * The caller must read each chunk of the on-disk doclist in succession and
- * pass it to mergeBlock().
- *
- * If [in] has positions, then the merge output contains only documents with
- * matching positions in the two input doclists. If [in] does not have
- * positions, then the merge output contains all documents common to the two
- * input doclists.
- *
- * If [in] is NULL, then the on-disk doclist is copied to [out] directly.
- *
- * A merge is performed using an integer [iOffset] provided by the caller.
- * [iOffset] is subtracted from each position in the on-disk doclist for the
- * purpose of position comparison; this is helpful in implementing phrase
- * searches.
- *
- * A DocListMerge is not yet able to propagate offsets through query
- * processing; we should add that capability soon.
-*/
-typedef struct DocListMerge {
- DocListReader in;
- DocList *pOut;
- int iOffset;
-} DocListMerge;
-
-static void mergeInit(DocListMerge *m,
- DocList *pIn, int iOffset, DocList *pOut){
- readerInit(&m->in, pIn);
- m->pOut = pOut;
- m->iOffset = iOffset;
-
- /* can't handle offsets yet */
- assert( pIn==NULL || pIn->iType <= DL_POSITIONS );
- assert( pOut->iType <= DL_POSITIONS );
-}
-
-/* A helper function for mergeBlock(), below. Merge the position lists
- * pointed to by m->in and pBlockReader.
- * If the merge matches, write [iDocid] to m->pOut; if m->pOut
- * has positions then write all matching positions as well. */
-static void mergePosList(DocListMerge *m, sqlite_int64 iDocid,
- DocListReader *pBlockReader){
- int block_pos = readPosition(pBlockReader);
- int in_pos = readPosition(&m->in);
- int match = 0;
- while( block_pos!=-1 || in_pos!=-1 ){
- if( block_pos-m->iOffset==in_pos ){
- if( !match ){
- docListAddDocid(m->pOut, iDocid);
- match = 1;
- }
- if( m->pOut->iType >= DL_POSITIONS ){
- docListAddPos(m->pOut, in_pos);
- }
- block_pos = readPosition(pBlockReader);
- in_pos = readPosition(&m->in);
- } else if( in_pos==-1 || (block_pos!=-1 && block_pos-m->iOffset<in_pos) ){
- block_pos = readPosition(pBlockReader);
- } else {
- in_pos = readPosition(&m->in);
- }
- }
- if( m->pOut->iType >= DL_POSITIONS && match ){
- docListAddEndPos(m->pOut);
- }
-}
-
-/* Merge one block of an on-disk doclist into a DocListMerge. */
-static void mergeBlock(DocListMerge *m, DocList *pBlock){
- DocListReader blockReader;
- assert( pBlock->iType >= DL_POSITIONS );
- readerInit(&blockReader, pBlock);
- while( !readerAtEnd(&blockReader) ){
- sqlite_int64 iDocid = readDocid(&blockReader);
- if( m->in.pDoclist!=NULL ){
- while( 1 ){
- if( readerAtEnd(&m->in) ) return; /* nothing more to merge */
- if( peekDocid(&m->in)>=iDocid ) break;
- skipDocument(&m->in);
- }
- if( peekDocid(&m->in)>iDocid ){ /* [pIn] has no match with iDocid */
- skipPositionList(&blockReader); /* skip this docid in the block */
- continue;
- }
- readDocid(&m->in);
- }
- /* We have a document match. */
- if( m->in.pDoclist==NULL || m->in.pDoclist->iType < DL_POSITIONS ){
- /* We don't need to do a poslist merge. */
- docListAddDocid(m->pOut, iDocid);
- if( m->pOut->iType >= DL_POSITIONS ){
- /* Copy all positions to the output doclist. */
- while( 1 ){
- int pos = readPosition(&blockReader);
- if( pos==-1 ) break;
- docListAddPos(m->pOut, pos);
- }
- docListAddEndPos(m->pOut);
- } else skipPositionList(&blockReader);
- continue;
- }
- mergePosList(m, iDocid, &blockReader);
- }
-}
-
-static char *string_dup_n(const char *s, int n){
- char *str = malloc(n + 1);
- memcpy(str, s, n);
- str[n] = '\0';
- return str;
-}
-
-/* Duplicate a string; the caller must free() the returned string.
- * (We don't use strdup() since it's not part of the standard C library and
- * may not be available everywhere.) */
-static char *string_dup(const char *s){
- return string_dup_n(s, strlen(s));
-}
-
-/* Format a string, replacing each occurrence of the % character with
- * zName. This may be more convenient than sqlite_mprintf()
- * when one string is used repeatedly in a format string.
- * The caller must free() the returned string. */
-static char *string_format(const char *zFormat, const char *zName){
- const char *p;
- size_t len = 0;
- size_t nName = strlen(zName);
- char *result;
- char *r;
-
- /* first compute length needed */
- for(p = zFormat ; *p ; ++p){
- len += (*p=='%' ? nName : 1);
- }
- len += 1; /* for null terminator */
-
- r = result = malloc(len);
- for(p = zFormat; *p; ++p){
- if( *p=='%' ){
- memcpy(r, zName, nName);
- r += nName;
- } else {
- *r++ = *p;
- }
- }
- *r++ = '\0';
- assert( r == result + len );
- return result;
-}
-
-static int sql_exec(sqlite3 *db, const char *zName, const char *zFormat){
- char *zCommand = string_format(zFormat, zName);
- int rc = sqlite3_exec(db, zCommand, NULL, 0, NULL);
- free(zCommand);
- return rc;
-}
-
-static int sql_prepare(sqlite3 *db, const char *zName, sqlite3_stmt **ppStmt,
- const char *zFormat){
- char *zCommand = string_format(zFormat, zName);
- int rc = sqlite3_prepare(db, zCommand, -1, ppStmt, NULL);
- free(zCommand);
- return rc;
-}
-
-/* end utility functions */
-
-#define QUERY_GENERIC 0
-#define QUERY_FULLTEXT 1
-
-#define CHUNK_MAX 1024
-
-typedef enum fulltext_statement {
- CONTENT_INSERT_STMT,
- CONTENT_SELECT_STMT,
- CONTENT_DELETE_STMT,
-
- TERM_SELECT_STMT,
- TERM_CHUNK_SELECT_STMT,
- TERM_INSERT_STMT,
- TERM_UPDATE_STMT,
- TERM_DELETE_STMT,
-
- MAX_STMT /* Always at end! */
-} fulltext_statement;
-
-/* These must exactly match the enum above. */
-/* TODO(adam): Is there some risk that a statement (in particular,
-** pTermSelectStmt) will be used in two cursors at once, e.g. if a
-** query joins a virtual table to itself? If so perhaps we should
-** move some of these to the cursor object.
-*/
-static const char *fulltext_zStatement[MAX_STMT] = {
- /* CONTENT_INSERT */ "insert into %_content (rowid, content) values (?, ?)",
- /* CONTENT_SELECT */ "select content from %_content where rowid = ?",
- /* CONTENT_DELETE */ "delete from %_content where rowid = ?",
-
- /* TERM_SELECT */
- "select rowid, doclist from %_term where term = ? and first = ?",
- /* TERM_CHUNK_SELECT */
- "select max(first) from %_term where term = ? and first <= ?",
- /* TERM_INSERT */
- "insert into %_term (term, first, doclist) values (?, ?, ?)",
- /* TERM_UPDATE */ "update %_term set doclist = ? where rowid = ?",
- /* TERM_DELETE */ "delete from %_term where rowid = ?",
-};
-
-typedef struct fulltext_vtab {
- sqlite3_vtab base;
- sqlite3 *db;
- const char *zName; /* virtual table name */
- sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
-
- /* Precompiled statements which we keep as long as the table is
- ** open.
- */
- sqlite3_stmt *pFulltextStatements[MAX_STMT];
-} fulltext_vtab;
-
-typedef struct fulltext_cursor {
- sqlite3_vtab_cursor base;
- int iCursorType; /* QUERY_GENERIC or QUERY_FULLTEXT */
-
- sqlite3_stmt *pStmt;
-
- int eof;
-
- /* The following is used only when iCursorType == QUERY_FULLTEXT. */
- DocListReader result;
-} fulltext_cursor;
-
-static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){
- return (fulltext_vtab *) c->base.pVtab;
-}
-
-static sqlite3_module fulltextModule; /* forward declaration */
-
-/* Puts a freshly-prepared statement determined by iStmt in *ppStmt.
-** If the indicated statement has never been prepared, it is prepared
-** and cached, otherwise the cached version is reset.
-*/
-static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt,
- sqlite3_stmt **ppStmt){
- assert( iStmt<MAX_STMT );
- if( v->pFulltextStatements[iStmt]==NULL ){
- int rc = sql_prepare(v->db, v->zName, &v->pFulltextStatements[iStmt],
- fulltext_zStatement[iStmt]);
- if( rc!=SQLITE_OK ) return rc;
- } else {
- int rc = sqlite3_reset(v->pFulltextStatements[iStmt]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- *ppStmt = v->pFulltextStatements[iStmt];
- return SQLITE_OK;
-}
-
-/* Step the indicated statement, handling errors SQLITE_BUSY (by
-** retrying) and SQLITE_SCHEMA (by re-preparing and transferring
-** bindings to the new statement).
-** TODO(adam): We should extend this function so that it can work with
-** statements declared locally, not only globally cached statements.
-*/
-static int sql_step_statement(fulltext_vtab *v, fulltext_statement iStmt,
- sqlite3_stmt **ppStmt){
- int rc;
- sqlite3_stmt *s = *ppStmt;
- assert( iStmt<MAX_STMT );
- assert( s==v->pFulltextStatements[iStmt] );
-
- while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){
- sqlite3_stmt *pNewStmt;
-
- if( rc==SQLITE_BUSY ) continue;
- if( rc!=SQLITE_ERROR ) return rc;
-
- rc = sqlite3_reset(s);
- if( rc!=SQLITE_SCHEMA ) return SQLITE_ERROR;
-
- v->pFulltextStatements[iStmt] = NULL; /* Still in s */
- rc = sql_get_statement(v, iStmt, &pNewStmt);
- if( rc!=SQLITE_OK ) goto err;
- *ppStmt = pNewStmt;
-
- rc = sqlite3_transfer_bindings(s, pNewStmt);
- if( rc!=SQLITE_OK ) goto err;
-
- rc = sqlite3_finalize(s);
- if( rc!=SQLITE_OK ) return rc;
- s = pNewStmt;
- }
- return rc;
-
- err:
- sqlite3_finalize(s);
- return rc;
-}
-
-/* Like sql_step_statement(), but convert SQLITE_DONE to SQLITE_OK.
-** Useful for statements like UPDATE, where we expect no results.
-*/
-static int sql_single_step_statement(fulltext_vtab *v,
- fulltext_statement iStmt,
- sqlite3_stmt **ppStmt){
- int rc = sql_step_statement(v, iStmt, ppStmt);
- return (rc==SQLITE_DONE) ? SQLITE_OK : rc;
-}
-
-/* insert into %_content (rowid, content) values ([rowid], [zContent]) */
-static int content_insert(fulltext_vtab *v, sqlite3_value *rowid,
- const char *zContent, int nContent){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_value(s, 1, rowid);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_text(s, 2, zContent, nContent, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, CONTENT_INSERT_STMT, &s);
-}
-
-/* select content from %_content where rowid = [iRow]
- * The caller must delete the returned string. */
-static int content_select(fulltext_vtab *v, sqlite_int64 iRow,
- char **pzContent){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s);
- if( rc!=SQLITE_ROW ) return rc;
-
- *pzContent = string_dup((const char *)sqlite3_column_text(s, 0));
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- if( rc==SQLITE_DONE ) return SQLITE_OK;
-
- free(*pzContent);
- return rc;
-}
-
-/* delete from %_content where rowid = [iRow ] */
-static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, CONTENT_DELETE_STMT, &s);
-}
-
-/* select rowid, doclist from %_term where term = [zTerm] and first = [iFirst]
- * If found, returns SQLITE_OK; the caller must free the returned doclist.
- * If no rows found, returns SQLITE_ERROR. */
-static int term_select(fulltext_vtab *v, const char *zTerm, int nTerm,
- sqlite_int64 iFirst,
- sqlite_int64 *rowid,
- DocList *out){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_SELECT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_TRANSIENT);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 2, iFirst);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sql_step_statement(v, TERM_SELECT_STMT, &s);
- if( rc!=SQLITE_ROW ) return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
-
- *rowid = sqlite3_column_int64(s, 0);
- docListInit(out, DL_POSITIONS_OFFSETS,
- sqlite3_column_blob(s, 1), sqlite3_column_bytes(s, 1));
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- return rc==SQLITE_DONE ? SQLITE_OK : rc;
-}
-
-/* select max(first) from %_term where term = [zTerm] and first <= [iFirst]
- * If found, returns SQLITE_ROW and result in *piResult; if the query returns
- * NULL (meaning no row found) returns SQLITE_DONE.
- */
-static int term_chunk_select(fulltext_vtab *v, const char *zTerm, int nTerm,
- sqlite_int64 iFirst, sqlite_int64 *piResult){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_CHUNK_SELECT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 2, iFirst);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sql_step_statement(v, TERM_CHUNK_SELECT_STMT, &s);
- if( rc!=SQLITE_ROW ) return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
-
- switch( sqlite3_column_type(s, 0) ){
- case SQLITE_NULL:
- rc = SQLITE_DONE;
- break;
- case SQLITE_INTEGER:
- *piResult = sqlite3_column_int64(s, 0);
- break;
- default:
- return SQLITE_ERROR;
- }
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- if( sqlite3_step(s) != SQLITE_DONE ) return SQLITE_ERROR;
- return rc;
-}
-
-/* insert into %_term (term, first, doclist)
- values ([zTerm], [iFirst], [doclist]) */
-static int term_insert(fulltext_vtab *v, const char *zTerm, int nTerm,
- sqlite_int64 iFirst, DocList *doclist){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_INSERT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 2, iFirst);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_blob(s, 3, doclist->pData, doclist->nData, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, TERM_INSERT_STMT, &s);
-}
-
-/* update %_term set doclist = [doclist] where rowid = [rowid] */
-static int term_update(fulltext_vtab *v, sqlite_int64 rowid,
- DocList *doclist){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_UPDATE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_blob(s, 1, doclist->pData, doclist->nData,
- SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 2, rowid);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, TERM_UPDATE_STMT, &s);
-}
-
-static int term_delete(fulltext_vtab *v, sqlite_int64 rowid){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, TERM_DELETE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, rowid);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step_statement(v, TERM_DELETE_STMT, &s);
-}
-
-static void fulltext_vtab_destroy(fulltext_vtab *v){
- int iStmt;
-
- for( iStmt=0; iStmt<MAX_STMT; iStmt++ ){
- if( v->pFulltextStatements[iStmt]!=NULL ){
- sqlite3_finalize(v->pFulltextStatements[iStmt]);
- v->pFulltextStatements[iStmt] = NULL;
- }
- }
-
- if( v->pTokenizer!=NULL ){
- v->pTokenizer->pModule->xDestroy(v->pTokenizer);
- v->pTokenizer = NULL;
- }
-
- free((void *) v->zName);
- free(v);
-}
-
-/* Current interface:
-** argv[0] - module name
-** argv[1] - database name
-** argv[2] - table name
-** argv[3] - tokenizer name (optional, a sensible default is provided)
-** argv[4..] - passed to tokenizer (optional based on tokenizer)
-**/
-static int fulltextConnect(
- sqlite3 *db,
- void *pAux,
- int argc,
- const char * const *argv,
- sqlite3_vtab **ppVTab,
- char **pzErr
-){
- int rc;
- fulltext_vtab *v;
- sqlite3_tokenizer_module *m = NULL;
-
- assert( argc>=3 );
- v = (fulltext_vtab *) malloc(sizeof(fulltext_vtab));
- /* sqlite will initialize v->base */
- v->db = db;
- v->zName = string_dup(argv[2]);
- v->pTokenizer = NULL;
-
- if( argc==3 ){
- get_simple_tokenizer_module(&m);
- } else {
- /* TODO(shess) For now, add new tokenizers as else if clauses. */
- if( !strcmp(argv[3], "simple") ){
- get_simple_tokenizer_module(&m);
- } else {
- assert( "unrecognized tokenizer"==NULL );
- }
- }
-
- /* TODO(shess) Since tokenization impacts the index, the parameters
- ** to the tokenizer need to be identical when a persistent virtual
- ** table is re-created. One solution would be a meta-table to track
- ** such information in the database. Then we could verify that the
- ** information is identical on subsequent creates.
- */
- /* TODO(shess) Why isn't argv already (const char **)? */
- rc = m->xCreate(argc-3, (const char **) (argv+3), &v->pTokenizer);
- if( rc!=SQLITE_OK ) return rc;
- v->pTokenizer->pModule = m;
-
- /* TODO: verify the existence of backing tables foo_content, foo_term */
-
- rc = sqlite3_declare_vtab(db, "create table x(content text)");
- if( rc!=SQLITE_OK ) return rc;
-
- memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements));
-
- *ppVTab = &v->base;
- return SQLITE_OK;
-}
-
-static int fulltextCreate(
- sqlite3 *db,
- void *pAux,
- int argc,
- const char * const *argv,
- sqlite3_vtab **ppVTab,
- char **pzErr
-){
- int rc;
- assert( argc>=3 );
-
- /* The %_content table holds the text of each full-text item, with
- ** the rowid used as the docid.
- **
- ** The %_term table maps each term to a document list blob
- ** containing elements sorted by ascending docid, each element
- ** encoded as:
- **
- ** docid varint-encoded
- ** token count varint-encoded
- ** "count" token elements (poslist):
- ** position varint-encoded as delta from previous position
- ** start offset varint-encoded as delta from previous start offset
- ** end offset varint-encoded as delta from start offset
- **
- ** Additionally, doclist blobs can be chunked into multiple rows,
- ** using "first" to order the blobs. "first" is simply the first
- ** docid in the blob.
- */
- /*
- ** NOTE(shess) That last sentence is incorrect in the face of
- ** deletion, which can leave a doclist that doesn't contain the
- ** first from that row. I _believe_ this does not matter to the
- ** operation of the system, but it might be reasonable to update
- ** appropriately in case this assumption becomes more important.
- */
- rc = sql_exec(db, argv[2],
- "create table %_content(content text);"
- "create table %_term(term text, first integer, doclist blob);"
- "create index %_index on %_term(term, first)");
- if( rc!=SQLITE_OK ) return rc;
-
- return fulltextConnect(db, pAux, argc, argv, ppVTab, pzErr);
-}
-
-/* Decide how to handle an SQL query.
- * At the moment, MATCH queries can include implicit boolean ANDs; we
- * haven't implemented phrase searches or OR yet. */
-static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
- int i;
-
- for(i=0; i<pInfo->nConstraint; ++i){
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = &pInfo->aConstraint[i];
- if( pConstraint->iColumn==0 &&
- pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH &&
- pConstraint->usable ){ /* a full-text search */
- pInfo->aConstraintUsage[i].argvIndex = 1;
- pInfo->aConstraintUsage[i].omit = 1;
- pInfo->idxNum = QUERY_FULLTEXT;
- pInfo->estimatedCost = 1.0; /* an arbitrary value for now */
- return SQLITE_OK;
- }
- }
- pInfo->idxNum = QUERY_GENERIC;
- return SQLITE_OK;
-}
-
-static int fulltextDisconnect(sqlite3_vtab *pVTab){
- fulltext_vtab_destroy((fulltext_vtab *)pVTab);
- return SQLITE_OK;
-}
-
-static int fulltextDestroy(sqlite3_vtab *pVTab){
- fulltext_vtab *v = (fulltext_vtab *)pVTab;
-
- int rc = sql_exec(v->db, v->zName,
- "drop table %_content; drop table %_term");
- if( rc!=SQLITE_OK ) return rc;
-
- fulltext_vtab_destroy((fulltext_vtab *)pVTab);
- return SQLITE_OK;
-}
-
-static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- fulltext_cursor *c;
-
- c = (fulltext_cursor *) calloc(sizeof(fulltext_cursor), 1);
- /* sqlite will initialize c->base */
- *ppCursor = &c->base;
-
- return SQLITE_OK;
-}
-
-static int fulltextClose(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- sqlite3_finalize(c->pStmt);
- if( c->result.pDoclist!=NULL ){
- docListDelete(c->result.pDoclist);
- }
- free(c);
- return SQLITE_OK;
-}
-
-static int fulltextNext(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- sqlite_int64 iDocid;
- int rc;
-
- switch( c->iCursorType ){
- case QUERY_GENERIC:
- /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
- rc = sqlite3_step(c->pStmt);
- switch( rc ){
- case SQLITE_ROW:
- c->eof = 0;
- return SQLITE_OK;
- case SQLITE_DONE:
- c->eof = 1;
- return SQLITE_OK;
- default:
- c->eof = 1;
- return rc;
- }
- case QUERY_FULLTEXT:
- rc = sqlite3_reset(c->pStmt);
- if( rc!=SQLITE_OK ) return rc;
-
- if( readerAtEnd(&c->result)){
- c->eof = 1;
- return SQLITE_OK;
- }
- iDocid = readDocid(&c->result);
- rc = sqlite3_bind_int64(c->pStmt, 1, iDocid);
- if( rc!=SQLITE_OK ) return rc;
- /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
- rc = sqlite3_step(c->pStmt);
- if( rc==SQLITE_ROW ){ /* the case we expect */
- c->eof = 0;
- return SQLITE_OK;
- }
- /* an error occurred; abort */
- return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
- default:
- assert( 0 );
- return SQLITE_ERROR; /* not reached */
- }
-}
-
-static int term_select_doclist(fulltext_vtab *v, const char *pTerm, int nTerm,
- sqlite3_stmt **ppStmt){
- int rc;
- if( *ppStmt ){
- rc = sqlite3_reset(*ppStmt);
- } else {
- rc = sql_prepare(v->db, v->zName, ppStmt,
- "select doclist from %_term where term = ? order by first");
- }
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_text(*ppStmt, 1, pTerm, nTerm, SQLITE_TRANSIENT);
- if( rc!=SQLITE_OK ) return rc;
-
- return sqlite3_step(*ppStmt); /* TODO(adamd): handle schema error */
-}
-
-/* Read the posting list for [zTerm]; AND it with the doclist [in] to
- * produce the doclist [out], using the given offset [iOffset] for phrase
- * matching.
- * (*pSelect) is used to hold an SQLite statement used inside this function;
- * the caller should initialize *pSelect to NULL before the first call.
- */
-static int query_merge(fulltext_vtab *v, sqlite3_stmt **pSelect,
- const char *zTerm,
- DocList *pIn, int iOffset, DocList *out){
- int rc;
- DocListMerge merge;
-
- if( pIn!=NULL && !pIn->nData ){
- /* If [pIn] is already empty, there's no point in reading the
- * posting list to AND it in; return immediately. */
- return SQLITE_OK;
- }
-
- rc = term_select_doclist(v, zTerm, -1, pSelect);
- if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc;
-
- mergeInit(&merge, pIn, iOffset, out);
- while( rc==SQLITE_ROW ){
- DocList block;
- docListInit(&block, DL_POSITIONS_OFFSETS,
- sqlite3_column_blob(*pSelect, 0),
- sqlite3_column_bytes(*pSelect, 0));
- mergeBlock(&merge, &block);
- docListDestroy(&block);
-
- rc = sqlite3_step(*pSelect);
- if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
- return rc;
- }
- }
-
- return SQLITE_OK;
-}
-
-typedef struct QueryTerm {
- int is_phrase; /* true if this term begins a new phrase */
- const char *zTerm;
-} QueryTerm;
-
-/* A parsed query.
- *
- * As an example, parsing the query ["four score" years "new nation"] will
- * yield a Query with 5 terms:
- * "four", is_phrase = 1
- * "score", is_phrase = 0
- * "years", is_phrase = 1
- * "new", is_phrase = 1
- * "nation", is_phrase = 0
- */
-typedef struct Query {
- int nTerms;
- QueryTerm *pTerm;
-} Query;
-
-static void query_add(Query *q, int is_phrase, const char *zTerm){
- QueryTerm *t;
- ++q->nTerms;
- q->pTerm = realloc(q->pTerm, q->nTerms * sizeof(q->pTerm[0]));
- t = &q->pTerm[q->nTerms - 1];
- t->is_phrase = is_phrase;
- t->zTerm = zTerm;
-}
-
-static void query_free(Query *q){
- int i;
- for(i = 0; i < q->nTerms; ++i){
- free((void *) q->pTerm[i].zTerm);
- }
- free(q->pTerm);
-}
-
-static int tokenize_segment(sqlite3_tokenizer *pTokenizer,
- const char *zQuery, int in_phrase,
- Query *pQuery){
- sqlite3_tokenizer_module *pModule = pTokenizer->pModule;
- sqlite3_tokenizer_cursor *pCursor;
- int is_first = 1;
-
- int rc = pModule->xOpen(pTokenizer, zQuery, -1, &pCursor);
- if( rc!=SQLITE_OK ) return rc;
- pCursor->pTokenizer = pTokenizer;
-
- while( 1 ){
- const char *zToken;
- int nToken, iStartOffset, iEndOffset, dummy_pos;
-
- rc = pModule->xNext(pCursor,
- &zToken, &nToken,
- &iStartOffset, &iEndOffset,
- &dummy_pos);
- if( rc!=SQLITE_OK ) break;
- query_add(pQuery, !in_phrase || is_first, string_dup_n(zToken, nToken));
- is_first = 0;
- }
-
- return pModule->xClose(pCursor);
-}
-
-/* Parse a query string, yielding a Query object. */
-static int parse_query(fulltext_vtab *v, const char *zQuery, Query *pQuery){
- char *zQuery1 = string_dup(zQuery);
- int in_phrase = 0;
- char *s = zQuery1;
- pQuery->nTerms = 0;
- pQuery->pTerm = NULL;
-
- while( *s ){
- char *t = s;
- while( *t ){
- if( *t=='"' ){
- *t++ = '\0';
- break;
- }
- ++t;
- }
- if( *s ){
- tokenize_segment(v->pTokenizer, s, in_phrase, pQuery);
- }
- s = t;
- in_phrase = !in_phrase;
- }
-
- free(zQuery1);
- return SQLITE_OK;
-}
-
-/* Perform a full-text query; return a list of documents in [pResult]. */
-static int fulltext_query(fulltext_vtab *v, const char *zQuery,
- DocList **pResult){
- Query q;
- int phrase_start = -1;
- int i;
- sqlite3_stmt *pSelect = NULL;
- DocList *d = NULL;
-
- int rc = parse_query(v, zQuery, &q);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Merge terms. */
- for(i = 0 ; i < q.nTerms ; ++i){
- /* In each merge step, we need to generate positions whenever we're
- * processing a phrase which hasn't ended yet. */
- int need_positions = i<q.nTerms-1 && !q.pTerm[i+1].is_phrase;
- DocList *next = docListNew(need_positions ? DL_POSITIONS : DL_DOCIDS);
- if( q.pTerm[i].is_phrase ){
- phrase_start = i;
- }
- rc = query_merge(v, &pSelect, q.pTerm[i].zTerm, d, i - phrase_start, next);
- if( rc!=SQLITE_OK ) break;
- if( d!=NULL ){
- docListDelete(d);
- }
- d = next;
- }
-
- sqlite3_finalize(pSelect);
- query_free(&q);
- *pResult = d;
- return rc;
-}
-
-static int fulltextFilter(sqlite3_vtab_cursor *pCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- fulltext_vtab *v = cursor_vtab(c);
- int rc;
- const char *zStatement;
-
- c->iCursorType = idxNum;
- switch( idxNum ){
- case QUERY_GENERIC:
- zStatement = "select rowid, content from %_content";
- break;
-
- case QUERY_FULLTEXT: /* full-text search */
- {
- const char *zQuery = (const char *)sqlite3_value_text(argv[0]);
- DocList *pResult;
- assert( argc==1 );
- rc = fulltext_query(v, zQuery, &pResult);
- if( rc!=SQLITE_OK ) return rc;
- readerInit(&c->result, pResult);
- zStatement = "select rowid, content from %_content where rowid = ?";
- break;
- }
-
- default:
- assert( 0 );
- }
-
- rc = sql_prepare(v->db, v->zName, &c->pStmt, zStatement);
- if( rc!=SQLITE_OK ) return rc;
-
- return fulltextNext(pCursor);
-}
-
-static int fulltextEof(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- return c->eof;
-}
-
-static int fulltextColumn(sqlite3_vtab_cursor *pCursor,
- sqlite3_context *pContext, int idxCol){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- const char *s;
-
- assert( idxCol==0 );
- s = (const char *) sqlite3_column_text(c->pStmt, 1);
- sqlite3_result_text(pContext, s, -1, SQLITE_TRANSIENT);
-
- return SQLITE_OK;
-}
-
-static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
-
- *pRowid = sqlite3_column_int64(c->pStmt, 0);
- return SQLITE_OK;
-}
-
-/* Build a hash table containing all terms in zText. */
-static int build_terms(Hash *terms, sqlite3_tokenizer *pTokenizer,
- const char *zText, sqlite_int64 iDocid){
- sqlite3_tokenizer_cursor *pCursor;
- const char *pToken;
- int nTokenBytes;
- int iStartOffset, iEndOffset, iPosition;
-
- int rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor);
- if( rc!=SQLITE_OK ) return rc;
-
- pCursor->pTokenizer = pTokenizer;
- HashInit(terms, HASH_STRING, 1);
- while( SQLITE_OK==pTokenizer->pModule->xNext(pCursor,
- &pToken, &nTokenBytes,
- &iStartOffset, &iEndOffset,
- &iPosition) ){
- DocList *p;
-
- /* Positions can't be negative; we use -1 as a terminator internally. */
- if( iPosition<0 ) {
- rc = SQLITE_ERROR;
- goto err;
- }
-
- p = HashFind(terms, pToken, nTokenBytes);
- if( p==NULL ){
- p = docListNew(DL_POSITIONS_OFFSETS);
- docListAddDocid(p, iDocid);
- HashInsert(terms, pToken, nTokenBytes, p);
- }
- docListAddPosOffset(p, iPosition, iStartOffset, iEndOffset);
- }
-
-err:
- /* TODO(shess) Check return? Should this be able to cause errors at
- ** this point? Actually, same question about sqlite3_finalize(),
- ** though one could argue that failure there means that the data is
- ** not durable. *ponder*
- */
- pTokenizer->pModule->xClose(pCursor);
- return rc;
-}
-/* Update the %_terms table to map the term [zTerm] to the given rowid. */
-static int index_insert_term(fulltext_vtab *v, const char *zTerm, int nTerm,
- sqlite_int64 iDocid, DocList *p){
- sqlite_int64 iFirst;
- sqlite_int64 iIndexRow;
- DocList doclist;
-
- int rc = term_chunk_select(v, zTerm, nTerm, iDocid, &iFirst);
- if( rc==SQLITE_DONE ){
- docListInit(&doclist, DL_POSITIONS_OFFSETS, 0, 0);
- if( docListUpdate(&doclist, iDocid, p) ){
- rc = term_insert(v, zTerm, nTerm, iDocid, &doclist);
- docListDestroy(&doclist);
- return rc;
- }
- return SQLITE_OK;
- }
- if( rc!=SQLITE_ROW ) return SQLITE_ERROR;
-
- /* This word is in the index; add this document ID to its blob. */
-
- rc = term_select(v, zTerm, nTerm, iFirst, &iIndexRow, &doclist);
- if( rc!=SQLITE_OK ) return rc;
-
- if( docListUpdate(&doclist, iDocid, p) ){
- /* If the blob is too big, split it in half. */
- if( doclist.nData>CHUNK_MAX ){
- DocList half;
- if( docListSplit(&doclist, &half) ){
- rc = term_insert(v, zTerm, nTerm, firstDocid(&half), &half);
- docListDestroy(&half);
- if( rc!=SQLITE_OK ) goto err;
- }
- }
- rc = term_update(v, iIndexRow, &doclist);
- }
-
-err:
- docListDestroy(&doclist);
- return rc;
-}
-
-/* Insert a row into the full-text index; set *piRowid to be the ID of the
- * new row. */
-static int index_insert(fulltext_vtab *v,
- sqlite3_value *pRequestRowid, const char *zText,
- sqlite_int64 *piRowid){
- Hash terms; /* maps term string -> PosList */
- HashElem *e;
-
- int rc = content_insert(v, pRequestRowid, zText, -1);
- if( rc!=SQLITE_OK ) return rc;
- *piRowid = sqlite3_last_insert_rowid(v->db);
-
- if( !zText ) return SQLITE_OK; /* nothing to index */
-
- rc = build_terms(&terms, v->pTokenizer, zText, *piRowid);
- if( rc!=SQLITE_OK ) return rc;
-
- for(e=HashFirst(&terms); e; e=HashNext(e)){
- DocList *p = HashData(e);
- rc = index_insert_term(v, HashKey(e), HashKeysize(e), *piRowid, p);
- if( rc!=SQLITE_OK ) break;
- }
-
- for(e=HashFirst(&terms); e; e=HashNext(e)){
- DocList *p = HashData(e);
- docListDelete(p);
- }
- HashClear(&terms);
- return rc;
-}
-
-static int index_delete_term(fulltext_vtab *v, const char *zTerm, int nTerm,
- sqlite_int64 iDocid){
- sqlite_int64 iFirst;
- sqlite_int64 iIndexRow;
- DocList doclist;
-
- int rc = term_chunk_select(v, zTerm, nTerm, iDocid, &iFirst);
- if( rc!=SQLITE_ROW ) return SQLITE_ERROR;
-
- rc = term_select(v, zTerm, nTerm, iFirst, &iIndexRow, &doclist);
- if( rc!=SQLITE_OK ) return rc;
-
- if( docListUpdate(&doclist, iDocid, NULL) ){
- if( doclist.nData>0 ){
- rc = term_update(v, iIndexRow, &doclist);
- } else { /* empty posting list */
- rc = term_delete(v, iIndexRow);
- }
- }
- docListDestroy(&doclist);
- return rc;
-}
-
-/* Delete a row from the full-text index. */
-static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){
- char *zText;
- Hash terms;
- HashElem *e;
-
- int rc = content_select(v, iRow, &zText);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = build_terms(&terms, v->pTokenizer, zText, iRow);
- free(zText);
- if( rc!=SQLITE_OK ) return rc;
-
- for(e=HashFirst(&terms); e; e=HashNext(e)){
- rc = index_delete_term(v, HashKey(e), HashKeysize(e), iRow);
- if( rc!=SQLITE_OK ) break;
- }
- for(e=HashFirst(&terms); e; e=HashNext(e)){
- DocList *p = HashData(e);
- docListDelete(p);
- }
- HashClear(&terms);
-
- return content_delete(v, iRow);
-}
-
-static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg,
- sqlite_int64 *pRowid){
- fulltext_vtab *v = (fulltext_vtab *) pVtab;
-
- if( nArg<2 ){
- return index_delete(v, sqlite3_value_int64(ppArg[0]));
- }
-
- if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){
- return SQLITE_ERROR; /* an update; not yet supported */
- }
-
- assert( nArg==3 ); /* ppArg[1] = rowid, ppArg[2] = content */
- return index_insert(v, ppArg[1],
- (const char *)sqlite3_value_text(ppArg[2]), pRowid);
-}
-
-static sqlite3_module fulltextModule = {
- 0,
- fulltextCreate,
- fulltextConnect,
- fulltextBestIndex,
- fulltextDisconnect,
- fulltextDestroy,
- fulltextOpen,
- fulltextClose,
- fulltextFilter,
- fulltextNext,
- fulltextEof,
- fulltextColumn,
- fulltextRowid,
- fulltextUpdate
-};
-
-int fulltext_init(sqlite3 *db){
- return sqlite3_create_module(db, "fulltext", &fulltextModule, 0);
-}
-
-#if !SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fulltext_init(sqlite3 *db, char **pzErrMsg,
- const sqlite3_api_routines *pApi){
- SQLITE_EXTENSION_INIT2(pApi)
- return fulltext_init(db);
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fulltext.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fulltext.h
deleted file mode 100644
index 477dcab2ade..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/fulltext.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "sqlite3.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int fulltext_init(sqlite3 *db);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/simple_tokenizer.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/simple_tokenizer.c
deleted file mode 100644
index 0ddc7055af7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/simple_tokenizer.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-** The author disclaims copyright to this source code.
-**
-*************************************************************************
-** Implementation of the "simple" full-text-search tokenizer.
-*/
-
-#include <assert.h>
-#if !defined(__APPLE__)
-#include <malloc.h>
-#else
-#include <stdlib.h>
-#endif
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "tokenizer.h"
-
-/* Duplicate a string; the caller must free() the returned string.
- * (We don't use strdup() since it's not part of the standard C library and
- * may not be available everywhere.) */
-/* TODO(shess) Copied from fulltext.c, consider util.c for such
-** things. */
-static char *string_dup(const char *s){
- char *str = malloc(strlen(s) + 1);
- strcpy(str, s);
- return str;
-}
-
-typedef struct simple_tokenizer {
- sqlite3_tokenizer base;
- const char *zDelim; /* token delimiters */
-} simple_tokenizer;
-
-typedef struct simple_tokenizer_cursor {
- sqlite3_tokenizer_cursor base;
- const char *pInput; /* input we are tokenizing */
- int nBytes; /* size of the input */
- const char *pCurrent; /* current position in pInput */
- int iToken; /* index of next token to be returned */
- char *zToken; /* storage for current token */
- int nTokenBytes; /* actual size of current token */
- int nTokenAllocated; /* space allocated to zToken buffer */
-} simple_tokenizer_cursor;
-
-static sqlite3_tokenizer_module simpleTokenizerModule;/* forward declaration */
-
-static int simpleCreate(
- int argc, const char **argv,
- sqlite3_tokenizer **ppTokenizer
-){
- simple_tokenizer *t;
-
- t = (simple_tokenizer *) malloc(sizeof(simple_tokenizer));
- /* TODO(shess) Delimiters need to remain the same from run to run,
- ** else we need to reindex. One solution would be a meta-table to
- ** track such information in the database, then we'd only want this
- ** information on the initial create.
- */
- if( argc>1 ){
- t->zDelim = string_dup(argv[1]);
- } else {
- /* Build a string excluding alphanumeric ASCII characters */
- char zDelim[0x80]; /* nul-terminated, so nul not a member */
- int i, j;
- for(i=1, j=0; i<0x80; i++){
- if( !isalnum(i) ){
- zDelim[j++] = i;
- }
- }
- zDelim[j++] = '\0';
- assert( j<=sizeof(zDelim) );
- t->zDelim = string_dup(zDelim);
- }
-
- *ppTokenizer = &t->base;
- return SQLITE_OK;
-}
-
-static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
- simple_tokenizer *t = (simple_tokenizer *) pTokenizer;
-
- free((void *) t->zDelim);
- free(t);
-
- return SQLITE_OK;
-}
-
-static int simpleOpen(
- sqlite3_tokenizer *pTokenizer,
- const char *pInput, int nBytes,
- sqlite3_tokenizer_cursor **ppCursor
-){
- simple_tokenizer_cursor *c;
-
- c = (simple_tokenizer_cursor *) malloc(sizeof(simple_tokenizer_cursor));
- c->pInput = pInput;
- c->nBytes = nBytes<0 ? (int) strlen(pInput) : nBytes;
- c->pCurrent = c->pInput; /* start tokenizing at the beginning */
- c->iToken = 0;
- c->zToken = NULL; /* no space allocated, yet. */
- c->nTokenBytes = 0;
- c->nTokenAllocated = 0;
-
- *ppCursor = &c->base;
- return SQLITE_OK;
-}
-
-static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
- simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
-
- if( NULL!=c->zToken ){
- free(c->zToken);
- }
- free(c);
-
- return SQLITE_OK;
-}
-
-static int simpleNext(
- sqlite3_tokenizer_cursor *pCursor,
- const char **ppToken, int *pnBytes,
- int *piStartOffset, int *piEndOffset, int *piPosition
-){
- simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
- simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
- int ii;
-
- while( c->pCurrent-c->pInput<c->nBytes ){
- int n = (int) strcspn(c->pCurrent, t->zDelim);
- if( n>0 ){
- if( n+1>c->nTokenAllocated ){
- c->zToken = realloc(c->zToken, n+1);
- }
- for(ii=0; ii<n; ii++){
- /* TODO(shess) This needs expansion to handle UTF-8
- ** case-insensitivity.
- */
- char ch = c->pCurrent[ii];
- c->zToken[ii] = (unsigned char)ch<0x80 ? tolower((unsigned char)ch):ch;
- }
- c->zToken[n] = '\0';
- *ppToken = c->zToken;
- *pnBytes = n;
- *piStartOffset = (int) (c->pCurrent-c->pInput);
- *piEndOffset = *piStartOffset+n;
- *piPosition = c->iToken++;
- c->pCurrent += n + 1;
-
- return SQLITE_OK;
- }
- c->pCurrent += n + 1;
- /* TODO(shess) could strspn() to skip delimiters en masse. Needs
- ** to happen in two places, though, which is annoying.
- */
- }
- return SQLITE_DONE;
-}
-
-static sqlite3_tokenizer_module simpleTokenizerModule = {
- 0,
- simpleCreate,
- simpleDestroy,
- simpleOpen,
- simpleClose,
- simpleNext,
-};
-
-void get_simple_tokenizer_module(
- sqlite3_tokenizer_module **ppModule
-){
- *ppModule = &simpleTokenizerModule;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/tokenizer.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/tokenizer.h
deleted file mode 100644
index 1d7bd1f6703..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts1/tokenizer.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-** 2006 July 10
-**
-** The author disclaims copyright to this source code.
-**
-*************************************************************************
-** Defines the interface to tokenizers used by fulltext-search. There
-** are three basic components:
-**
-** sqlite3_tokenizer_module is a singleton defining the tokenizer
-** interface functions. This is essentially the class structure for
-** tokenizers.
-**
-** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
-** including customization information defined at creation time.
-**
-** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
-** tokens from a particular input.
-*/
-#ifndef _TOKENIZER_H_
-#define _TOKENIZER_H_
-
-/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
-** If tokenizers are to be allowed to call sqlite3_*() functions, then
-** we will need a way to register the API consistently.
-*/
-#include "sqlite3.h"
-
-/*
-** Structures used by the tokenizer interface.
-*/
-typedef struct sqlite3_tokenizer sqlite3_tokenizer;
-typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
-typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
-
-struct sqlite3_tokenizer_module {
- int iVersion; /* currently 0 */
-
- /*
- ** Create and destroy a tokenizer. argc/argv are passed down from
- ** the fulltext virtual table creation to allow customization.
- */
- int (*xCreate)(int argc, const char **argv,
- sqlite3_tokenizer **ppTokenizer);
- int (*xDestroy)(sqlite3_tokenizer *pTokenizer);
-
- /*
- ** Tokenize a particular input. Call xOpen() to prepare to
- ** tokenize, xNext() repeatedly until it returns SQLITE_DONE, then
- ** xClose() to free any internal state. The pInput passed to
- ** xOpen() must exist until the cursor is closed. The ppToken
- ** result from xNext() is only valid until the next call to xNext()
- ** or until xClose() is called.
- */
- /* TODO(shess) current implementation requires pInput to be
- ** nul-terminated. This should either be fixed, or pInput/nBytes
- ** should be converted to zInput.
- */
- int (*xOpen)(sqlite3_tokenizer *pTokenizer,
- const char *pInput, int nBytes,
- sqlite3_tokenizer_cursor **ppCursor);
- int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
- int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
- const char **ppToken, int *pnBytes,
- int *piStartOffset, int *piEndOffset, int *piPosition);
-};
-
-struct sqlite3_tokenizer {
- sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
- /* Tokenizer implementations will typically add additional fields */
-};
-
-struct sqlite3_tokenizer_cursor {
- sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */
- /* Tokenizer implementations will typically add additional fields */
-};
-
-/*
-** Get the module for a tokenizer which generates tokens based on a
-** set of non-token characters. The default is to break tokens at any
-** non-alnum character, though the set of delimiters can also be
-** specified by the first argv argument to xCreate().
-*/
-/* TODO(shess) This doesn't belong here. Need some sort of
-** registration process.
-*/
-void get_simple_tokenizer_module(sqlite3_tokenizer_module **ppModule);
-
-#endif /* _TOKENIZER_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/README.tokenizers b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/README.tokenizers
deleted file mode 100644
index 98d2021ba1d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/README.tokenizers
+++ /dev/null
@@ -1,133 +0,0 @@
-
-1. FTS2 Tokenizers
-
- When creating a new full-text table, FTS2 allows the user to select
- the text tokenizer implementation to be used when indexing text
- by specifying a "tokenizer" clause as part of the CREATE VIRTUAL TABLE
- statement:
-
- CREATE VIRTUAL TABLE <table-name> USING fts2(
- <columns ...> [, tokenizer <tokenizer-name> [<tokenizer-args>]]
- );
-
- The built-in tokenizers (valid values to pass as <tokenizer name>) are
- "simple" and "porter".
-
- <tokenizer-args> should consist of zero or more white-space separated
- arguments to pass to the selected tokenizer implementation. The
- interpretation of the arguments, if any, depends on the individual
- tokenizer.
-
-2. Custom Tokenizers
-
- FTS2 allows users to provide custom tokenizer implementations. The
- interface used to create a new tokenizer is defined and described in
- the fts2_tokenizer.h source file.
-
- Registering a new FTS2 tokenizer is similar to registering a new
- virtual table module with SQLite. The user passes a pointer to a
- structure containing pointers to various callback functions that
- make up the implementation of the new tokenizer type. For tokenizers,
- the structure (defined in fts2_tokenizer.h) is called
- "sqlite3_tokenizer_module".
-
- FTS2 does not expose a C-function that users call to register new
- tokenizer types with a database handle. Instead, the pointer must
- be encoded as an SQL blob value and passed to FTS2 through the SQL
- engine by evaluating a special scalar function, "fts2_tokenizer()".
- The fts2_tokenizer() function may be called with one or two arguments,
- as follows:
-
- SELECT fts2_tokenizer(<tokenizer-name>);
- SELECT fts2_tokenizer(<tokenizer-name>, <sqlite3_tokenizer_module ptr>);
-
- Where <tokenizer-name> is a string identifying the tokenizer and
- <sqlite3_tokenizer_module ptr> is a pointer to an sqlite3_tokenizer_module
- structure encoded as an SQL blob. If the second argument is present,
- it is registered as tokenizer <tokenizer-name> and a copy of it
- returned. If only one argument is passed, a pointer to the tokenizer
- implementation currently registered as <tokenizer-name> is returned,
- encoded as a blob. Or, if no such tokenizer exists, an SQL exception
- (error) is raised.
-
- SECURITY: If the fts2 extension is used in an environment where potentially
- malicious users may execute arbitrary SQL (i.e. gears), they should be
- prevented from invoking the fts2_tokenizer() function, possibly using the
- authorisation callback.
-
- See "Sample code" below for an example of calling the fts2_tokenizer()
- function from C code.
-
-3. ICU Library Tokenizers
-
- If this extension is compiled with the SQLITE_ENABLE_ICU pre-processor
- symbol defined, then there exists a built-in tokenizer named "icu"
- implemented using the ICU library. The first argument passed to the
- xCreate() method (see fts2_tokenizer.h) of this tokenizer may be
- an ICU locale identifier. For example "tr_TR" for Turkish as used
- in Turkey, or "en_AU" for English as used in Australia. For example:
-
- "CREATE VIRTUAL TABLE thai_text USING fts2(text, tokenizer icu th_TH)"
-
- The ICU tokenizer implementation is very simple. It splits the input
- text according to the ICU rules for finding word boundaries and discards
- any tokens that consist entirely of white-space. This may be suitable
- for some applications in some locales, but not all. If more complex
- processing is required, for example to implement stemming or
- discard punctuation, this can be done by creating a tokenizer
- implementation that uses the ICU tokenizer as part of its implementation.
-
- When using the ICU tokenizer this way, it is safe to overwrite the
- contents of the strings returned by the xNext() method (see
- fts2_tokenizer.h).
-
-4. Sample code.
-
- The following two code samples illustrate the way C code should invoke
- the fts2_tokenizer() scalar function:
-
- int registerTokenizer(
- sqlite3 *db,
- char *zName,
- const sqlite3_tokenizer_module *p
- ){
- int rc;
- sqlite3_stmt *pStmt;
- const char zSql[] = "SELECT fts2_tokenizer(?, ?)";
-
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
- sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC);
- sqlite3_step(pStmt);
-
- return sqlite3_finalize(pStmt);
- }
-
- int queryTokenizer(
- sqlite3 *db,
- char *zName,
- const sqlite3_tokenizer_module **pp
- ){
- int rc;
- sqlite3_stmt *pStmt;
- const char zSql[] = "SELECT fts2_tokenizer(?)";
-
- *pp = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
- memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
- }
- }
-
- return sqlite3_finalize(pStmt);
- }
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/README.txt b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/README.txt
deleted file mode 100644
index 517a2a04346..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/README.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This folder contains source code to the second full-text search
-extension for SQLite. While the API is the same, this version uses a
-substantially different storage schema from fts1, so tables will need
-to be rebuilt.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2.c
deleted file mode 100644
index 0405fb7b1e5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2.c
+++ /dev/null
@@ -1,6860 +0,0 @@
-/* fts2 has a design flaw which can lead to database corruption (see
-** below). It is recommended not to use it any longer, instead use
-** fts3 (or higher). If you believe that your use of fts2 is safe,
-** add -DSQLITE_ENABLE_BROKEN_FTS2=1 to your CFLAGS.
-*/
-#if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)) \
- && !defined(SQLITE_ENABLE_BROKEN_FTS2)
-#error fts2 has a design flaw and has been deprecated.
-#endif
-/* The flaw is that fts2 uses the content table's unaliased rowid as
-** the unique docid. fts2 embeds the rowid in the index it builds,
-** and expects the rowid to not change. The SQLite VACUUM operation
-** will renumber such rowids, thereby breaking fts2. If you are using
-** fts2 in a system which has disabled VACUUM, then you can continue
-** to use it safely. Note that PRAGMA auto_vacuum does NOT disable
-** VACUUM, though systems using auto_vacuum are unlikely to invoke
-** VACUUM.
-**
-** Unlike fts1, which is safe across VACUUM if you never delete
-** documents, fts2 has a second exposure to this flaw, in the segments
-** table. So fts2 should be considered unsafe across VACUUM in all
-** cases.
-*/
-
-/*
-** 2006 Oct 10
-**
-** 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 is an SQLite module implementing full-text search.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS2 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS2 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
-*/
-
-/* TODO(shess) Consider exporting this comment to an HTML file or the
-** wiki.
-*/
-/* The full-text index is stored in a series of b+tree (-like)
-** structures called segments which map terms to doclists. The
-** structures are like b+trees in layout, but are constructed from the
-** bottom up in optimal fashion and are not updatable. Since trees
-** are built from the bottom up, things will be described from the
-** bottom up.
-**
-**
-**** Varints ****
-** The basic unit of encoding is a variable-length integer called a
-** varint. We encode variable-length integers in little-endian order
-** using seven bits * per byte as follows:
-**
-** KEY:
-** A = 0xxxxxxx 7 bits of data and one flag bit
-** B = 1xxxxxxx 7 bits of data and one flag bit
-**
-** 7 bits - A
-** 14 bits - BA
-** 21 bits - BBA
-** and so on.
-**
-** This is identical to how sqlite encodes varints (see util.c).
-**
-**
-**** Document lists ****
-** A doclist (document list) holds a docid-sorted list of hits for a
-** given term. Doclists hold docids, and can optionally associate
-** token positions and offsets with docids.
-**
-** A DL_POSITIONS_OFFSETS doclist is stored like this:
-**
-** array {
-** varint docid;
-** array { (position list for column 0)
-** varint position; (delta from previous position plus POS_BASE)
-** varint startOffset; (delta from previous startOffset)
-** varint endOffset; (delta from startOffset)
-** }
-** array {
-** varint POS_COLUMN; (marks start of position list for new column)
-** varint column; (index of new column)
-** array {
-** varint position; (delta from previous position plus POS_BASE)
-** varint startOffset;(delta from previous startOffset)
-** varint endOffset; (delta from startOffset)
-** }
-** }
-** varint POS_END; (marks end of positions for this document.
-** }
-**
-** Here, array { X } means zero or more occurrences of X, adjacent in
-** memory. A "position" is an index of a token in the token stream
-** generated by the tokenizer, while an "offset" is a byte offset,
-** both based at 0. Note that POS_END and POS_COLUMN occur in the
-** same logical place as the position element, and act as sentinals
-** ending a position list array.
-**
-** A DL_POSITIONS doclist omits the startOffset and endOffset
-** information. A DL_DOCIDS doclist omits both the position and
-** offset information, becoming an array of varint-encoded docids.
-**
-** On-disk data is stored as type DL_DEFAULT, so we don't serialize
-** the type. Due to how deletion is implemented in the segmentation
-** system, on-disk doclists MUST store at least positions.
-**
-**
-**** Segment leaf nodes ****
-** Segment leaf nodes store terms and doclists, ordered by term. Leaf
-** nodes are written using LeafWriter, and read using LeafReader (to
-** iterate through a single leaf node's data) and LeavesReader (to
-** iterate through a segment's entire leaf layer). Leaf nodes have
-** the format:
-**
-** varint iHeight; (height from leaf level, always 0)
-** varint nTerm; (length of first term)
-** char pTerm[nTerm]; (content of first term)
-** varint nDoclist; (length of term's associated doclist)
-** char pDoclist[nDoclist]; (content of doclist)
-** array {
-** (further terms are delta-encoded)
-** varint nPrefix; (length of prefix shared with previous term)
-** varint nSuffix; (length of unshared suffix)
-** char pTermSuffix[nSuffix];(unshared suffix of next term)
-** varint nDoclist; (length of term's associated doclist)
-** char pDoclist[nDoclist]; (content of doclist)
-** }
-**
-** Here, array { X } means zero or more occurrences of X, adjacent in
-** memory.
-**
-** Leaf nodes are broken into blocks which are stored contiguously in
-** the %_segments table in sorted order. This means that when the end
-** of a node is reached, the next term is in the node with the next
-** greater node id.
-**
-** New data is spilled to a new leaf node when the current node
-** exceeds LEAF_MAX bytes (default 2048). New data which itself is
-** larger than STANDALONE_MIN (default 1024) is placed in a standalone
-** node (a leaf node with a single term and doclist). The goal of
-** these settings is to pack together groups of small doclists while
-** making it efficient to directly access large doclists. The
-** assumption is that large doclists represent terms which are more
-** likely to be query targets.
-**
-** TODO(shess) It may be useful for blocking decisions to be more
-** dynamic. For instance, it may make more sense to have a 2.5k leaf
-** node rather than splitting into 2k and .5k nodes. My intuition is
-** that this might extend through 2x or 4x the pagesize.
-**
-**
-**** Segment interior nodes ****
-** Segment interior nodes store blockids for subtree nodes and terms
-** to describe what data is stored by the each subtree. Interior
-** nodes are written using InteriorWriter, and read using
-** InteriorReader. InteriorWriters are created as needed when
-** SegmentWriter creates new leaf nodes, or when an interior node
-** itself grows too big and must be split. The format of interior
-** nodes:
-**
-** varint iHeight; (height from leaf level, always >0)
-** varint iBlockid; (block id of node's leftmost subtree)
-** optional {
-** varint nTerm; (length of first term)
-** char pTerm[nTerm]; (content of first term)
-** array {
-** (further terms are delta-encoded)
-** varint nPrefix; (length of shared prefix with previous term)
-** varint nSuffix; (length of unshared suffix)
-** char pTermSuffix[nSuffix]; (unshared suffix of next term)
-** }
-** }
-**
-** Here, optional { X } means an optional element, while array { X }
-** means zero or more occurrences of X, adjacent in memory.
-**
-** An interior node encodes n terms separating n+1 subtrees. The
-** subtree blocks are contiguous, so only the first subtree's blockid
-** is encoded. The subtree at iBlockid will contain all terms less
-** than the first term encoded (or all terms if no term is encoded).
-** Otherwise, for terms greater than or equal to pTerm[i] but less
-** than pTerm[i+1], the subtree for that term will be rooted at
-** iBlockid+i. Interior nodes only store enough term data to
-** distinguish adjacent children (if the rightmost term of the left
-** child is "something", and the leftmost term of the right child is
-** "wicked", only "w" is stored).
-**
-** New data is spilled to a new interior node at the same height when
-** the current node exceeds INTERIOR_MAX bytes (default 2048).
-** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing
-** interior nodes and making the tree too skinny. The interior nodes
-** at a given height are naturally tracked by interior nodes at
-** height+1, and so on.
-**
-**
-**** Segment directory ****
-** The segment directory in table %_segdir stores meta-information for
-** merging and deleting segments, and also the root node of the
-** segment's tree.
-**
-** The root node is the top node of the segment's tree after encoding
-** the entire segment, restricted to ROOT_MAX bytes (default 1024).
-** This could be either a leaf node or an interior node. If the top
-** node requires more than ROOT_MAX bytes, it is flushed to %_segments
-** and a new root interior node is generated (which should always fit
-** within ROOT_MAX because it only needs space for 2 varints, the
-** height and the blockid of the previous root).
-**
-** The meta-information in the segment directory is:
-** level - segment level (see below)
-** idx - index within level
-** - (level,idx uniquely identify a segment)
-** start_block - first leaf node
-** leaves_end_block - last leaf node
-** end_block - last block (including interior nodes)
-** root - contents of root node
-**
-** If the root node is a leaf node, then start_block,
-** leaves_end_block, and end_block are all 0.
-**
-**
-**** Segment merging ****
-** To amortize update costs, segments are groups into levels and
-** merged in matches. Each increase in level represents exponentially
-** more documents.
-**
-** New documents (actually, document updates) are tokenized and
-** written individually (using LeafWriter) to a level 0 segment, with
-** incrementing idx. When idx reaches MERGE_COUNT (default 16), all
-** level 0 segments are merged into a single level 1 segment. Level 1
-** is populated like level 0, and eventually MERGE_COUNT level 1
-** segments are merged to a single level 2 segment (representing
-** MERGE_COUNT^2 updates), and so on.
-**
-** A segment merge traverses all segments at a given level in
-** parallel, performing a straightforward sorted merge. Since segment
-** leaf nodes are written in to the %_segments table in order, this
-** merge traverses the underlying sqlite disk structures efficiently.
-** After the merge, all segment blocks from the merged level are
-** deleted.
-**
-** MERGE_COUNT controls how often we merge segments. 16 seems to be
-** somewhat of a sweet spot for insertion performance. 32 and 64 show
-** very similar performance numbers to 16 on insertion, though they're
-** a tiny bit slower (perhaps due to more overhead in merge-time
-** sorting). 8 is about 20% slower than 16, 4 about 50% slower than
-** 16, 2 about 66% slower than 16.
-**
-** At query time, high MERGE_COUNT increases the number of segments
-** which need to be scanned and merged. For instance, with 100k docs
-** inserted:
-**
-** MERGE_COUNT segments
-** 16 25
-** 8 12
-** 4 10
-** 2 6
-**
-** This appears to have only a moderate impact on queries for very
-** frequent terms (which are somewhat dominated by segment merge
-** costs), and infrequent and non-existent terms still seem to be fast
-** even with many segments.
-**
-** TODO(shess) That said, it would be nice to have a better query-side
-** argument for MERGE_COUNT of 16. Also, it is possible/likely that
-** optimizations to things like doclist merging will swing the sweet
-** spot around.
-**
-**
-**
-**** Handling of deletions and updates ****
-** Since we're using a segmented structure, with no docid-oriented
-** index into the term index, we clearly cannot simply update the term
-** index when a document is deleted or updated. For deletions, we
-** write an empty doclist (varint(docid) varint(POS_END)), for updates
-** we simply write the new doclist. Segment merges overwrite older
-** data for a particular docid with newer data, so deletes or updates
-** will eventually overtake the earlier data and knock it out. The
-** query logic likewise merges doclists so that newer data knocks out
-** older data.
-**
-** TODO(shess) Provide a VACUUM type operation to clear out all
-** deletions and duplications. This would basically be a forced merge
-** into a single segment.
-*/
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)
-
-#if defined(SQLITE_ENABLE_FTS2) && !defined(SQLITE_CORE)
-# define SQLITE_CORE 1
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "fts2.h"
-#include "fts2_hash.h"
-#include "fts2_tokenizer.h"
-#include "sqlite3.h"
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-
-/* TODO(shess) MAN, this thing needs some refactoring. At minimum, it
-** would be nice to order the file better, perhaps something along the
-** lines of:
-**
-** - utility functions
-** - table setup functions
-** - table update functions
-** - table query functions
-**
-** Put the query functions last because they're likely to reference
-** typedefs or functions from the table update section.
-*/
-
-#if 0
-# define TRACE(A) printf A; fflush(stdout)
-#else
-# define TRACE(A)
-#endif
-
-/* It is not safe to call isspace(), tolower(), or isalnum() on
-** hi-bit-set characters. This is the same solution used in the
-** tokenizer.
-*/
-/* TODO(shess) The snippet-generation code should be using the
-** tokenizer-generated tokens rather than doing its own local
-** tokenization.
-*/
-/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */
-static int safe_isspace(char c){
- return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
-}
-static int safe_tolower(char c){
- return (c>='A' && c<='Z') ? (c - 'A' + 'a') : c;
-}
-static int safe_isalnum(char c){
- return (c>='0' && c<='9') || (c>='A' && c<='Z') || (c>='a' && c<='z');
-}
-
-typedef enum DocListType {
- DL_DOCIDS, /* docids only */
- DL_POSITIONS, /* docids + positions */
- DL_POSITIONS_OFFSETS /* docids + positions + offsets */
-} DocListType;
-
-/*
-** By default, only positions and not offsets are stored in the doclists.
-** To change this so that offsets are stored too, compile with
-**
-** -DDL_DEFAULT=DL_POSITIONS_OFFSETS
-**
-** If DL_DEFAULT is set to DL_DOCIDS, your table can only be inserted
-** into (no deletes or updates).
-*/
-#ifndef DL_DEFAULT
-# define DL_DEFAULT DL_POSITIONS
-#endif
-
-enum {
- POS_END = 0, /* end of this position list */
- POS_COLUMN, /* followed by new column number */
- POS_BASE
-};
-
-/* MERGE_COUNT controls how often we merge segments (see comment at
-** top of file).
-*/
-#define MERGE_COUNT 16
-
-/* utility functions */
-
-/* CLEAR() and SCRAMBLE() abstract memset() on a pointer to a single
-** record to prevent errors of the form:
-**
-** my_function(SomeType *b){
-** memset(b, '\0', sizeof(b)); // sizeof(b)!=sizeof(*b)
-** }
-*/
-/* TODO(shess) Obvious candidates for a header file. */
-#define CLEAR(b) memset(b, '\0', sizeof(*(b)))
-
-#ifndef NDEBUG
-# define SCRAMBLE(b) memset(b, 0x55, sizeof(*(b)))
-#else
-# define SCRAMBLE(b)
-#endif
-
-/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */
-#define VARINT_MAX 10
-
-/* Write a 64-bit variable-length integer to memory starting at p[0].
- * The length of data written will be between 1 and VARINT_MAX bytes.
- * The number of bytes written is returned. */
-static int putVarint(char *p, sqlite_int64 v){
- unsigned char *q = (unsigned char *) p;
- sqlite_uint64 vu = v;
- do{
- *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
- vu >>= 7;
- }while( vu!=0 );
- q[-1] &= 0x7f; /* turn off high bit in final byte */
- assert( q - (unsigned char *)p <= VARINT_MAX );
- return (int) (q - (unsigned char *)p);
-}
-
-/* Read a 64-bit variable-length integer from memory starting at p[0].
- * Return the number of bytes read, or 0 on error.
- * The value is stored in *v. */
-static int getVarint(const char *p, sqlite_int64 *v){
- const unsigned char *q = (const unsigned char *) p;
- sqlite_uint64 x = 0, y = 1;
- while( (*q & 0x80) == 0x80 ){
- x += y * (*q++ & 0x7f);
- y <<= 7;
- if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */
- assert( 0 );
- return 0;
- }
- }
- x += y * (*q++);
- *v = (sqlite_int64) x;
- return (int) (q - (unsigned char *)p);
-}
-
-static int getVarint32(const char *p, int *pi){
- sqlite_int64 i;
- int ret = getVarint(p, &i);
- *pi = (int) i;
- assert( *pi==i );
- return ret;
-}
-
-/*******************************************************************/
-/* DataBuffer is used to collect data into a buffer in piecemeal
-** fashion. It implements the usual distinction between amount of
-** data currently stored (nData) and buffer capacity (nCapacity).
-**
-** dataBufferInit - create a buffer with given initial capacity.
-** dataBufferReset - forget buffer's data, retaining capacity.
-** dataBufferDestroy - free buffer's data.
-** dataBufferSwap - swap contents of two buffers.
-** dataBufferExpand - expand capacity without adding data.
-** dataBufferAppend - append data.
-** dataBufferAppend2 - append two pieces of data at once.
-** dataBufferReplace - replace buffer's data.
-*/
-typedef struct DataBuffer {
- char *pData; /* Pointer to malloc'ed buffer. */
- int nCapacity; /* Size of pData buffer. */
- int nData; /* End of data loaded into pData. */
-} DataBuffer;
-
-static void dataBufferInit(DataBuffer *pBuffer, int nCapacity){
- assert( nCapacity>=0 );
- pBuffer->nData = 0;
- pBuffer->nCapacity = nCapacity;
- pBuffer->pData = nCapacity==0 ? NULL : sqlite3_malloc(nCapacity);
-}
-static void dataBufferReset(DataBuffer *pBuffer){
- pBuffer->nData = 0;
-}
-static void dataBufferDestroy(DataBuffer *pBuffer){
- if( pBuffer->pData!=NULL ) sqlite3_free(pBuffer->pData);
- SCRAMBLE(pBuffer);
-}
-static void dataBufferSwap(DataBuffer *pBuffer1, DataBuffer *pBuffer2){
- DataBuffer tmp = *pBuffer1;
- *pBuffer1 = *pBuffer2;
- *pBuffer2 = tmp;
-}
-static void dataBufferExpand(DataBuffer *pBuffer, int nAddCapacity){
- assert( nAddCapacity>0 );
- /* TODO(shess) Consider expanding more aggressively. Note that the
- ** underlying malloc implementation may take care of such things for
- ** us already.
- */
- if( pBuffer->nData+nAddCapacity>pBuffer->nCapacity ){
- pBuffer->nCapacity = pBuffer->nData+nAddCapacity;
- pBuffer->pData = sqlite3_realloc(pBuffer->pData, pBuffer->nCapacity);
- }
-}
-static void dataBufferAppend(DataBuffer *pBuffer,
- const char *pSource, int nSource){
- assert( nSource>0 && pSource!=NULL );
- dataBufferExpand(pBuffer, nSource);
- memcpy(pBuffer->pData+pBuffer->nData, pSource, nSource);
- pBuffer->nData += nSource;
-}
-static void dataBufferAppend2(DataBuffer *pBuffer,
- const char *pSource1, int nSource1,
- const char *pSource2, int nSource2){
- assert( nSource1>0 && pSource1!=NULL );
- assert( nSource2>0 && pSource2!=NULL );
- dataBufferExpand(pBuffer, nSource1+nSource2);
- memcpy(pBuffer->pData+pBuffer->nData, pSource1, nSource1);
- memcpy(pBuffer->pData+pBuffer->nData+nSource1, pSource2, nSource2);
- pBuffer->nData += nSource1+nSource2;
-}
-static void dataBufferReplace(DataBuffer *pBuffer,
- const char *pSource, int nSource){
- dataBufferReset(pBuffer);
- dataBufferAppend(pBuffer, pSource, nSource);
-}
-
-/* StringBuffer is a null-terminated version of DataBuffer. */
-typedef struct StringBuffer {
- DataBuffer b; /* Includes null terminator. */
-} StringBuffer;
-
-static void initStringBuffer(StringBuffer *sb){
- dataBufferInit(&sb->b, 100);
- dataBufferReplace(&sb->b, "", 1);
-}
-static int stringBufferLength(StringBuffer *sb){
- return sb->b.nData-1;
-}
-static char *stringBufferData(StringBuffer *sb){
- return sb->b.pData;
-}
-static void stringBufferDestroy(StringBuffer *sb){
- dataBufferDestroy(&sb->b);
-}
-
-static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){
- assert( sb->b.nData>0 );
- if( nFrom>0 ){
- sb->b.nData--;
- dataBufferAppend2(&sb->b, zFrom, nFrom, "", 1);
- }
-}
-static void append(StringBuffer *sb, const char *zFrom){
- nappend(sb, zFrom, strlen(zFrom));
-}
-
-/* Append a list of strings separated by commas. */
-static void appendList(StringBuffer *sb, int nString, char **azString){
- int i;
- for(i=0; i<nString; ++i){
- if( i>0 ) append(sb, ", ");
- append(sb, azString[i]);
- }
-}
-
-static int endsInWhiteSpace(StringBuffer *p){
- return stringBufferLength(p)>0 &&
- safe_isspace(stringBufferData(p)[stringBufferLength(p)-1]);
-}
-
-/* If the StringBuffer ends in something other than white space, add a
-** single space character to the end.
-*/
-static void appendWhiteSpace(StringBuffer *p){
- if( stringBufferLength(p)==0 ) return;
- if( !endsInWhiteSpace(p) ) append(p, " ");
-}
-
-/* Remove white space from the end of the StringBuffer */
-static void trimWhiteSpace(StringBuffer *p){
- while( endsInWhiteSpace(p) ){
- p->b.pData[--p->b.nData-1] = '\0';
- }
-}
-
-/*******************************************************************/
-/* DLReader is used to read document elements from a doclist. The
-** current docid is cached, so dlrDocid() is fast. DLReader does not
-** own the doclist buffer.
-**
-** dlrAtEnd - true if there's no more data to read.
-** dlrDocid - docid of current document.
-** dlrDocData - doclist data for current document (including docid).
-** dlrDocDataBytes - length of same.
-** dlrAllDataBytes - length of all remaining data.
-** dlrPosData - position data for current document.
-** dlrPosDataLen - length of pos data for current document (incl POS_END).
-** dlrStep - step to current document.
-** dlrInit - initial for doclist of given type against given data.
-** dlrDestroy - clean up.
-**
-** Expected usage is something like:
-**
-** DLReader reader;
-** dlrInit(&reader, pData, nData);
-** while( !dlrAtEnd(&reader) ){
-** // calls to dlrDocid() and kin.
-** dlrStep(&reader);
-** }
-** dlrDestroy(&reader);
-*/
-typedef struct DLReader {
- DocListType iType;
- const char *pData;
- int nData;
-
- sqlite_int64 iDocid;
- int nElement;
-} DLReader;
-
-static int dlrAtEnd(DLReader *pReader){
- assert( pReader->nData>=0 );
- return pReader->nData==0;
-}
-static sqlite_int64 dlrDocid(DLReader *pReader){
- assert( !dlrAtEnd(pReader) );
- return pReader->iDocid;
-}
-static const char *dlrDocData(DLReader *pReader){
- assert( !dlrAtEnd(pReader) );
- return pReader->pData;
-}
-static int dlrDocDataBytes(DLReader *pReader){
- assert( !dlrAtEnd(pReader) );
- return pReader->nElement;
-}
-static int dlrAllDataBytes(DLReader *pReader){
- assert( !dlrAtEnd(pReader) );
- return pReader->nData;
-}
-/* TODO(shess) Consider adding a field to track iDocid varint length
-** to make these two functions faster. This might matter (a tiny bit)
-** for queries.
-*/
-static const char *dlrPosData(DLReader *pReader){
- sqlite_int64 iDummy;
- int n = getVarint(pReader->pData, &iDummy);
- assert( !dlrAtEnd(pReader) );
- return pReader->pData+n;
-}
-static int dlrPosDataLen(DLReader *pReader){
- sqlite_int64 iDummy;
- int n = getVarint(pReader->pData, &iDummy);
- assert( !dlrAtEnd(pReader) );
- return pReader->nElement-n;
-}
-static void dlrStep(DLReader *pReader){
- assert( !dlrAtEnd(pReader) );
-
- /* Skip past current doclist element. */
- assert( pReader->nElement<=pReader->nData );
- pReader->pData += pReader->nElement;
- pReader->nData -= pReader->nElement;
-
- /* If there is more data, read the next doclist element. */
- if( pReader->nData!=0 ){
- sqlite_int64 iDocidDelta;
- int iDummy, n = getVarint(pReader->pData, &iDocidDelta);
- pReader->iDocid += iDocidDelta;
- if( pReader->iType>=DL_POSITIONS ){
- assert( n<pReader->nData );
- while( 1 ){
- n += getVarint32(pReader->pData+n, &iDummy);
- assert( n<=pReader->nData );
- if( iDummy==POS_END ) break;
- if( iDummy==POS_COLUMN ){
- n += getVarint32(pReader->pData+n, &iDummy);
- assert( n<pReader->nData );
- }else if( pReader->iType==DL_POSITIONS_OFFSETS ){
- n += getVarint32(pReader->pData+n, &iDummy);
- n += getVarint32(pReader->pData+n, &iDummy);
- assert( n<pReader->nData );
- }
- }
- }
- pReader->nElement = n;
- assert( pReader->nElement<=pReader->nData );
- }
-}
-static void dlrInit(DLReader *pReader, DocListType iType,
- const char *pData, int nData){
- assert( pData!=NULL && nData!=0 );
- pReader->iType = iType;
- pReader->pData = pData;
- pReader->nData = nData;
- pReader->nElement = 0;
- pReader->iDocid = 0;
-
- /* Load the first element's data. There must be a first element. */
- dlrStep(pReader);
-}
-static void dlrDestroy(DLReader *pReader){
- SCRAMBLE(pReader);
-}
-
-#ifndef NDEBUG
-/* Verify that the doclist can be validly decoded. Also returns the
-** last docid found because it is convenient in other assertions for
-** DLWriter.
-*/
-static void docListValidate(DocListType iType, const char *pData, int nData,
- sqlite_int64 *pLastDocid){
- sqlite_int64 iPrevDocid = 0;
- assert( nData>0 );
- assert( pData!=0 );
- assert( pData+nData>pData );
- while( nData!=0 ){
- sqlite_int64 iDocidDelta;
- int n = getVarint(pData, &iDocidDelta);
- iPrevDocid += iDocidDelta;
- if( iType>DL_DOCIDS ){
- int iDummy;
- while( 1 ){
- n += getVarint32(pData+n, &iDummy);
- if( iDummy==POS_END ) break;
- if( iDummy==POS_COLUMN ){
- n += getVarint32(pData+n, &iDummy);
- }else if( iType>DL_POSITIONS ){
- n += getVarint32(pData+n, &iDummy);
- n += getVarint32(pData+n, &iDummy);
- }
- assert( n<=nData );
- }
- }
- assert( n<=nData );
- pData += n;
- nData -= n;
- }
- if( pLastDocid ) *pLastDocid = iPrevDocid;
-}
-#define ASSERT_VALID_DOCLIST(i, p, n, o) docListValidate(i, p, n, o)
-#else
-#define ASSERT_VALID_DOCLIST(i, p, n, o) assert( 1 )
-#endif
-
-/*******************************************************************/
-/* DLWriter is used to write doclist data to a DataBuffer. DLWriter
-** always appends to the buffer and does not own it.
-**
-** dlwInit - initialize to write a given type doclistto a buffer.
-** dlwDestroy - clear the writer's memory. Does not free buffer.
-** dlwAppend - append raw doclist data to buffer.
-** dlwCopy - copy next doclist from reader to writer.
-** dlwAdd - construct doclist element and append to buffer.
-** Only apply dlwAdd() to DL_DOCIDS doclists (else use PLWriter).
-*/
-typedef struct DLWriter {
- DocListType iType;
- DataBuffer *b;
- sqlite_int64 iPrevDocid;
-#ifndef NDEBUG
- int has_iPrevDocid;
-#endif
-} DLWriter;
-
-static void dlwInit(DLWriter *pWriter, DocListType iType, DataBuffer *b){
- pWriter->b = b;
- pWriter->iType = iType;
- pWriter->iPrevDocid = 0;
-#ifndef NDEBUG
- pWriter->has_iPrevDocid = 0;
-#endif
-}
-static void dlwDestroy(DLWriter *pWriter){
- SCRAMBLE(pWriter);
-}
-/* iFirstDocid is the first docid in the doclist in pData. It is
-** needed because pData may point within a larger doclist, in which
-** case the first item would be delta-encoded.
-**
-** iLastDocid is the final docid in the doclist in pData. It is
-** needed to create the new iPrevDocid for future delta-encoding. The
-** code could decode the passed doclist to recreate iLastDocid, but
-** the only current user (docListMerge) already has decoded this
-** information.
-*/
-/* TODO(shess) This has become just a helper for docListMerge.
-** Consider a refactor to make this cleaner.
-*/
-static void dlwAppend(DLWriter *pWriter,
- const char *pData, int nData,
- sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
- sqlite_int64 iDocid = 0;
- char c[VARINT_MAX];
- int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */
-#ifndef NDEBUG
- sqlite_int64 iLastDocidDelta;
-#endif
-
- /* Recode the initial docid as delta from iPrevDocid. */
- nFirstOld = getVarint(pData, &iDocid);
- assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) );
- nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid);
-
- /* Verify that the incoming doclist is valid AND that it ends with
- ** the expected docid. This is essential because we'll trust this
- ** docid in future delta-encoding.
- */
- ASSERT_VALID_DOCLIST(pWriter->iType, pData, nData, &iLastDocidDelta);
- assert( iLastDocid==iFirstDocid-iDocid+iLastDocidDelta );
-
- /* Append recoded initial docid and everything else. Rest of docids
- ** should have been delta-encoded from previous initial docid.
- */
- if( nFirstOld<nData ){
- dataBufferAppend2(pWriter->b, c, nFirstNew,
- pData+nFirstOld, nData-nFirstOld);
- }else{
- dataBufferAppend(pWriter->b, c, nFirstNew);
- }
- pWriter->iPrevDocid = iLastDocid;
-}
-static void dlwCopy(DLWriter *pWriter, DLReader *pReader){
- dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
- dlrDocid(pReader), dlrDocid(pReader));
-}
-static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){
- char c[VARINT_MAX];
- int n = putVarint(c, iDocid-pWriter->iPrevDocid);
-
- /* Docids must ascend. */
- assert( !pWriter->has_iPrevDocid || iDocid>pWriter->iPrevDocid );
- assert( pWriter->iType==DL_DOCIDS );
-
- dataBufferAppend(pWriter->b, c, n);
- pWriter->iPrevDocid = iDocid;
-#ifndef NDEBUG
- pWriter->has_iPrevDocid = 1;
-#endif
-}
-
-/*******************************************************************/
-/* PLReader is used to read data from a document's position list. As
-** the caller steps through the list, data is cached so that varints
-** only need to be decoded once.
-**
-** plrInit, plrDestroy - create/destroy a reader.
-** plrColumn, plrPosition, plrStartOffset, plrEndOffset - accessors
-** plrAtEnd - at end of stream, only call plrDestroy once true.
-** plrStep - step to the next element.
-*/
-typedef struct PLReader {
- /* These refer to the next position's data. nData will reach 0 when
- ** reading the last position, so plrStep() signals EOF by setting
- ** pData to NULL.
- */
- const char *pData;
- int nData;
-
- DocListType iType;
- int iColumn; /* the last column read */
- int iPosition; /* the last position read */
- int iStartOffset; /* the last start offset read */
- int iEndOffset; /* the last end offset read */
-} PLReader;
-
-static int plrAtEnd(PLReader *pReader){
- return pReader->pData==NULL;
-}
-static int plrColumn(PLReader *pReader){
- assert( !plrAtEnd(pReader) );
- return pReader->iColumn;
-}
-static int plrPosition(PLReader *pReader){
- assert( !plrAtEnd(pReader) );
- return pReader->iPosition;
-}
-static int plrStartOffset(PLReader *pReader){
- assert( !plrAtEnd(pReader) );
- return pReader->iStartOffset;
-}
-static int plrEndOffset(PLReader *pReader){
- assert( !plrAtEnd(pReader) );
- return pReader->iEndOffset;
-}
-static void plrStep(PLReader *pReader){
- int i, n;
-
- assert( !plrAtEnd(pReader) );
-
- if( pReader->nData==0 ){
- pReader->pData = NULL;
- return;
- }
-
- n = getVarint32(pReader->pData, &i);
- if( i==POS_COLUMN ){
- n += getVarint32(pReader->pData+n, &pReader->iColumn);
- pReader->iPosition = 0;
- pReader->iStartOffset = 0;
- n += getVarint32(pReader->pData+n, &i);
- }
- /* Should never see adjacent column changes. */
- assert( i!=POS_COLUMN );
-
- if( i==POS_END ){
- pReader->nData = 0;
- pReader->pData = NULL;
- return;
- }
-
- pReader->iPosition += i-POS_BASE;
- if( pReader->iType==DL_POSITIONS_OFFSETS ){
- n += getVarint32(pReader->pData+n, &i);
- pReader->iStartOffset += i;
- n += getVarint32(pReader->pData+n, &i);
- pReader->iEndOffset = pReader->iStartOffset+i;
- }
- assert( n<=pReader->nData );
- pReader->pData += n;
- pReader->nData -= n;
-}
-
-static void plrInit(PLReader *pReader, DLReader *pDLReader){
- pReader->pData = dlrPosData(pDLReader);
- pReader->nData = dlrPosDataLen(pDLReader);
- pReader->iType = pDLReader->iType;
- pReader->iColumn = 0;
- pReader->iPosition = 0;
- pReader->iStartOffset = 0;
- pReader->iEndOffset = 0;
- plrStep(pReader);
-}
-static void plrDestroy(PLReader *pReader){
- SCRAMBLE(pReader);
-}
-
-/*******************************************************************/
-/* PLWriter is used in constructing a document's position list. As a
-** convenience, if iType is DL_DOCIDS, PLWriter becomes a no-op.
-** PLWriter writes to the associated DLWriter's buffer.
-**
-** plwInit - init for writing a document's poslist.
-** plwDestroy - clear a writer.
-** plwAdd - append position and offset information.
-** plwCopy - copy next position's data from reader to writer.
-** plwTerminate - add any necessary doclist terminator.
-**
-** Calling plwAdd() after plwTerminate() may result in a corrupt
-** doclist.
-*/
-/* TODO(shess) Until we've written the second item, we can cache the
-** first item's information. Then we'd have three states:
-**
-** - initialized with docid, no positions.
-** - docid and one position.
-** - docid and multiple positions.
-**
-** Only the last state needs to actually write to dlw->b, which would
-** be an improvement in the DLCollector case.
-*/
-typedef struct PLWriter {
- DLWriter *dlw;
-
- int iColumn; /* the last column written */
- int iPos; /* the last position written */
- int iOffset; /* the last start offset written */
-} PLWriter;
-
-/* TODO(shess) In the case where the parent is reading these values
-** from a PLReader, we could optimize to a copy if that PLReader has
-** the same type as pWriter.
-*/
-static void plwAdd(PLWriter *pWriter, int iColumn, int iPos,
- int iStartOffset, int iEndOffset){
- /* Worst-case space for POS_COLUMN, iColumn, iPosDelta,
- ** iStartOffsetDelta, and iEndOffsetDelta.
- */
- char c[5*VARINT_MAX];
- int n = 0;
-
- /* Ban plwAdd() after plwTerminate(). */
- assert( pWriter->iPos!=-1 );
-
- if( pWriter->dlw->iType==DL_DOCIDS ) return;
-
- if( iColumn!=pWriter->iColumn ){
- n += putVarint(c+n, POS_COLUMN);
- n += putVarint(c+n, iColumn);
- pWriter->iColumn = iColumn;
- pWriter->iPos = 0;
- pWriter->iOffset = 0;
- }
- assert( iPos>=pWriter->iPos );
- n += putVarint(c+n, POS_BASE+(iPos-pWriter->iPos));
- pWriter->iPos = iPos;
- if( pWriter->dlw->iType==DL_POSITIONS_OFFSETS ){
- assert( iStartOffset>=pWriter->iOffset );
- n += putVarint(c+n, iStartOffset-pWriter->iOffset);
- pWriter->iOffset = iStartOffset;
- assert( iEndOffset>=iStartOffset );
- n += putVarint(c+n, iEndOffset-iStartOffset);
- }
- dataBufferAppend(pWriter->dlw->b, c, n);
-}
-static void plwCopy(PLWriter *pWriter, PLReader *pReader){
- plwAdd(pWriter, plrColumn(pReader), plrPosition(pReader),
- plrStartOffset(pReader), plrEndOffset(pReader));
-}
-static void plwInit(PLWriter *pWriter, DLWriter *dlw, sqlite_int64 iDocid){
- char c[VARINT_MAX];
- int n;
-
- pWriter->dlw = dlw;
-
- /* Docids must ascend. */
- assert( !pWriter->dlw->has_iPrevDocid || iDocid>pWriter->dlw->iPrevDocid );
- n = putVarint(c, iDocid-pWriter->dlw->iPrevDocid);
- dataBufferAppend(pWriter->dlw->b, c, n);
- pWriter->dlw->iPrevDocid = iDocid;
-#ifndef NDEBUG
- pWriter->dlw->has_iPrevDocid = 1;
-#endif
-
- pWriter->iColumn = 0;
- pWriter->iPos = 0;
- pWriter->iOffset = 0;
-}
-/* TODO(shess) Should plwDestroy() also terminate the doclist? But
-** then plwDestroy() would no longer be just a destructor, it would
-** also be doing work, which isn't consistent with the overall idiom.
-** Another option would be for plwAdd() to always append any necessary
-** terminator, so that the output is always correct. But that would
-** add incremental work to the common case with the only benefit being
-** API elegance. Punt for now.
-*/
-static void plwTerminate(PLWriter *pWriter){
- if( pWriter->dlw->iType>DL_DOCIDS ){
- char c[VARINT_MAX];
- int n = putVarint(c, POS_END);
- dataBufferAppend(pWriter->dlw->b, c, n);
- }
-#ifndef NDEBUG
- /* Mark as terminated for assert in plwAdd(). */
- pWriter->iPos = -1;
-#endif
-}
-static void plwDestroy(PLWriter *pWriter){
- SCRAMBLE(pWriter);
-}
-
-/*******************************************************************/
-/* DLCollector wraps PLWriter and DLWriter to provide a
-** dynamically-allocated doclist area to use during tokenization.
-**
-** dlcNew - malloc up and initialize a collector.
-** dlcDelete - destroy a collector and all contained items.
-** dlcAddPos - append position and offset information.
-** dlcAddDoclist - add the collected doclist to the given buffer.
-** dlcNext - terminate the current document and open another.
-*/
-typedef struct DLCollector {
- DataBuffer b;
- DLWriter dlw;
- PLWriter plw;
-} DLCollector;
-
-/* TODO(shess) This could also be done by calling plwTerminate() and
-** dataBufferAppend(). I tried that, expecting nominal performance
-** differences, but it seemed to pretty reliably be worth 1% to code
-** it this way. I suspect it is the incremental malloc overhead (some
-** percentage of the plwTerminate() calls will cause a realloc), so
-** this might be worth revisiting if the DataBuffer implementation
-** changes.
-*/
-static void dlcAddDoclist(DLCollector *pCollector, DataBuffer *b){
- if( pCollector->dlw.iType>DL_DOCIDS ){
- char c[VARINT_MAX];
- int n = putVarint(c, POS_END);
- dataBufferAppend2(b, pCollector->b.pData, pCollector->b.nData, c, n);
- }else{
- dataBufferAppend(b, pCollector->b.pData, pCollector->b.nData);
- }
-}
-static void dlcNext(DLCollector *pCollector, sqlite_int64 iDocid){
- plwTerminate(&pCollector->plw);
- plwDestroy(&pCollector->plw);
- plwInit(&pCollector->plw, &pCollector->dlw, iDocid);
-}
-static void dlcAddPos(DLCollector *pCollector, int iColumn, int iPos,
- int iStartOffset, int iEndOffset){
- plwAdd(&pCollector->plw, iColumn, iPos, iStartOffset, iEndOffset);
-}
-
-static DLCollector *dlcNew(sqlite_int64 iDocid, DocListType iType){
- DLCollector *pCollector = sqlite3_malloc(sizeof(DLCollector));
- dataBufferInit(&pCollector->b, 0);
- dlwInit(&pCollector->dlw, iType, &pCollector->b);
- plwInit(&pCollector->plw, &pCollector->dlw, iDocid);
- return pCollector;
-}
-static void dlcDelete(DLCollector *pCollector){
- plwDestroy(&pCollector->plw);
- dlwDestroy(&pCollector->dlw);
- dataBufferDestroy(&pCollector->b);
- SCRAMBLE(pCollector);
- sqlite3_free(pCollector);
-}
-
-
-/* Copy the doclist data of iType in pData/nData into *out, trimming
-** unnecessary data as we go. Only columns matching iColumn are
-** copied, all columns copied if iColumn is -1. Elements with no
-** matching columns are dropped. The output is an iOutType doclist.
-*/
-/* NOTE(shess) This code is only valid after all doclists are merged.
-** If this is run before merges, then doclist items which represent
-** deletion will be trimmed, and will thus not effect a deletion
-** during the merge.
-*/
-static void docListTrim(DocListType iType, const char *pData, int nData,
- int iColumn, DocListType iOutType, DataBuffer *out){
- DLReader dlReader;
- DLWriter dlWriter;
-
- assert( iOutType<=iType );
-
- dlrInit(&dlReader, iType, pData, nData);
- dlwInit(&dlWriter, iOutType, out);
-
- while( !dlrAtEnd(&dlReader) ){
- PLReader plReader;
- PLWriter plWriter;
- int match = 0;
-
- plrInit(&plReader, &dlReader);
-
- while( !plrAtEnd(&plReader) ){
- if( iColumn==-1 || plrColumn(&plReader)==iColumn ){
- if( !match ){
- plwInit(&plWriter, &dlWriter, dlrDocid(&dlReader));
- match = 1;
- }
- plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader),
- plrStartOffset(&plReader), plrEndOffset(&plReader));
- }
- plrStep(&plReader);
- }
- if( match ){
- plwTerminate(&plWriter);
- plwDestroy(&plWriter);
- }
-
- plrDestroy(&plReader);
- dlrStep(&dlReader);
- }
- dlwDestroy(&dlWriter);
- dlrDestroy(&dlReader);
-}
-
-/* Used by docListMerge() to keep doclists in the ascending order by
-** docid, then ascending order by age (so the newest comes first).
-*/
-typedef struct OrderedDLReader {
- DLReader *pReader;
-
- /* TODO(shess) If we assume that docListMerge pReaders is ordered by
- ** age (which we do), then we could use pReader comparisons to break
- ** ties.
- */
- int idx;
-} OrderedDLReader;
-
-/* Order eof to end, then by docid asc, idx desc. */
-static int orderedDLReaderCmp(OrderedDLReader *r1, OrderedDLReader *r2){
- if( dlrAtEnd(r1->pReader) ){
- if( dlrAtEnd(r2->pReader) ) return 0; /* Both atEnd(). */
- return 1; /* Only r1 atEnd(). */
- }
- if( dlrAtEnd(r2->pReader) ) return -1; /* Only r2 atEnd(). */
-
- if( dlrDocid(r1->pReader)<dlrDocid(r2->pReader) ) return -1;
- if( dlrDocid(r1->pReader)>dlrDocid(r2->pReader) ) return 1;
-
- /* Descending on idx. */
- return r2->idx-r1->idx;
-}
-
-/* Bubble p[0] to appropriate place in p[1..n-1]. Assumes that
-** p[1..n-1] is already sorted.
-*/
-/* TODO(shess) Is this frequent enough to warrant a binary search?
-** Before implementing that, instrument the code to check. In most
-** current usage, I expect that p[0] will be less than p[1] a very
-** high proportion of the time.
-*/
-static void orderedDLReaderReorder(OrderedDLReader *p, int n){
- while( n>1 && orderedDLReaderCmp(p, p+1)>0 ){
- OrderedDLReader tmp = p[0];
- p[0] = p[1];
- p[1] = tmp;
- n--;
- p++;
- }
-}
-
-/* Given an array of doclist readers, merge their doclist elements
-** into out in sorted order (by docid), dropping elements from older
-** readers when there is a duplicate docid. pReaders is assumed to be
-** ordered by age, oldest first.
-*/
-/* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably
-** be fixed.
-*/
-static void docListMerge(DataBuffer *out,
- DLReader *pReaders, int nReaders){
- OrderedDLReader readers[MERGE_COUNT];
- DLWriter writer;
- int i, n;
- const char *pStart = 0;
- int nStart = 0;
- sqlite_int64 iFirstDocid = 0, iLastDocid = 0;
-
- assert( nReaders>0 );
- if( nReaders==1 ){
- dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders));
- return;
- }
-
- assert( nReaders<=MERGE_COUNT );
- n = 0;
- for(i=0; i<nReaders; i++){
- assert( pReaders[i].iType==pReaders[0].iType );
- readers[i].pReader = pReaders+i;
- readers[i].idx = i;
- n += dlrAllDataBytes(&pReaders[i]);
- }
- /* Conservatively size output to sum of inputs. Output should end
- ** up strictly smaller than input.
- */
- dataBufferExpand(out, n);
-
- /* Get the readers into sorted order. */
- while( i-->0 ){
- orderedDLReaderReorder(readers+i, nReaders-i);
- }
-
- dlwInit(&writer, pReaders[0].iType, out);
- while( !dlrAtEnd(readers[0].pReader) ){
- sqlite_int64 iDocid = dlrDocid(readers[0].pReader);
-
- /* If this is a continuation of the current buffer to copy, extend
- ** that buffer. memcpy() seems to be more efficient if it has a
- ** lots of data to copy.
- */
- if( dlrDocData(readers[0].pReader)==pStart+nStart ){
- nStart += dlrDocDataBytes(readers[0].pReader);
- }else{
- if( pStart!=0 ){
- dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
- }
- pStart = dlrDocData(readers[0].pReader);
- nStart = dlrDocDataBytes(readers[0].pReader);
- iFirstDocid = iDocid;
- }
- iLastDocid = iDocid;
- dlrStep(readers[0].pReader);
-
- /* Drop all of the older elements with the same docid. */
- for(i=1; i<nReaders &&
- !dlrAtEnd(readers[i].pReader) &&
- dlrDocid(readers[i].pReader)==iDocid; i++){
- dlrStep(readers[i].pReader);
- }
-
- /* Get the readers back into order. */
- while( i-->0 ){
- orderedDLReaderReorder(readers+i, nReaders-i);
- }
- }
-
- /* Copy over any remaining elements. */
- if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
- dlwDestroy(&writer);
-}
-
-/* Helper function for posListUnion(). Compares the current position
-** between left and right, returning as standard C idiom of <0 if
-** left<right, >0 if left>right, and 0 if left==right. "End" always
-** compares greater.
-*/
-static int posListCmp(PLReader *pLeft, PLReader *pRight){
- assert( pLeft->iType==pRight->iType );
- if( pLeft->iType==DL_DOCIDS ) return 0;
-
- if( plrAtEnd(pLeft) ) return plrAtEnd(pRight) ? 0 : 1;
- if( plrAtEnd(pRight) ) return -1;
-
- if( plrColumn(pLeft)<plrColumn(pRight) ) return -1;
- if( plrColumn(pLeft)>plrColumn(pRight) ) return 1;
-
- if( plrPosition(pLeft)<plrPosition(pRight) ) return -1;
- if( plrPosition(pLeft)>plrPosition(pRight) ) return 1;
- if( pLeft->iType==DL_POSITIONS ) return 0;
-
- if( plrStartOffset(pLeft)<plrStartOffset(pRight) ) return -1;
- if( plrStartOffset(pLeft)>plrStartOffset(pRight) ) return 1;
-
- if( plrEndOffset(pLeft)<plrEndOffset(pRight) ) return -1;
- if( plrEndOffset(pLeft)>plrEndOffset(pRight) ) return 1;
-
- return 0;
-}
-
-/* Write the union of position lists in pLeft and pRight to pOut.
-** "Union" in this case meaning "All unique position tuples". Should
-** work with any doclist type, though both inputs and the output
-** should be the same type.
-*/
-static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
- PLReader left, right;
- PLWriter writer;
-
- assert( dlrDocid(pLeft)==dlrDocid(pRight) );
- assert( pLeft->iType==pRight->iType );
- assert( pLeft->iType==pOut->iType );
-
- plrInit(&left, pLeft);
- plrInit(&right, pRight);
- plwInit(&writer, pOut, dlrDocid(pLeft));
-
- while( !plrAtEnd(&left) || !plrAtEnd(&right) ){
- int c = posListCmp(&left, &right);
- if( c<0 ){
- plwCopy(&writer, &left);
- plrStep(&left);
- }else if( c>0 ){
- plwCopy(&writer, &right);
- plrStep(&right);
- }else{
- plwCopy(&writer, &left);
- plrStep(&left);
- plrStep(&right);
- }
- }
-
- plwTerminate(&writer);
- plwDestroy(&writer);
- plrDestroy(&left);
- plrDestroy(&right);
-}
-
-/* Write the union of doclists in pLeft and pRight to pOut. For
-** docids in common between the inputs, the union of the position
-** lists is written. Inputs and outputs are always type DL_DEFAULT.
-*/
-static void docListUnion(
- const char *pLeft, int nLeft,
- const char *pRight, int nRight,
- DataBuffer *pOut /* Write the combined doclist here */
-){
- DLReader left, right;
- DLWriter writer;
-
- if( nLeft==0 ){
- if( nRight!=0) dataBufferAppend(pOut, pRight, nRight);
- return;
- }
- if( nRight==0 ){
- dataBufferAppend(pOut, pLeft, nLeft);
- return;
- }
-
- dlrInit(&left, DL_DEFAULT, pLeft, nLeft);
- dlrInit(&right, DL_DEFAULT, pRight, nRight);
- dlwInit(&writer, DL_DEFAULT, pOut);
-
- while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){
- if( dlrAtEnd(&right) ){
- dlwCopy(&writer, &left);
- dlrStep(&left);
- }else if( dlrAtEnd(&left) ){
- dlwCopy(&writer, &right);
- dlrStep(&right);
- }else if( dlrDocid(&left)<dlrDocid(&right) ){
- dlwCopy(&writer, &left);
- dlrStep(&left);
- }else if( dlrDocid(&left)>dlrDocid(&right) ){
- dlwCopy(&writer, &right);
- dlrStep(&right);
- }else{
- posListUnion(&left, &right, &writer);
- dlrStep(&left);
- dlrStep(&right);
- }
- }
-
- dlrDestroy(&left);
- dlrDestroy(&right);
- dlwDestroy(&writer);
-}
-
-/* pLeft and pRight are DLReaders positioned to the same docid.
-**
-** If there are no instances in pLeft or pRight where the position
-** of pLeft is one less than the position of pRight, then this
-** routine adds nothing to pOut.
-**
-** If there are one or more instances where positions from pLeft
-** are exactly one less than positions from pRight, then add a new
-** document record to pOut. If pOut wants to hold positions, then
-** include the positions from pRight that are one more than a
-** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1.
-*/
-static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
- DLWriter *pOut){
- PLReader left, right;
- PLWriter writer;
- int match = 0;
-
- assert( dlrDocid(pLeft)==dlrDocid(pRight) );
- assert( pOut->iType!=DL_POSITIONS_OFFSETS );
-
- plrInit(&left, pLeft);
- plrInit(&right, pRight);
-
- while( !plrAtEnd(&left) && !plrAtEnd(&right) ){
- if( plrColumn(&left)<plrColumn(&right) ){
- plrStep(&left);
- }else if( plrColumn(&left)>plrColumn(&right) ){
- plrStep(&right);
- }else if( plrPosition(&left)+1<plrPosition(&right) ){
- plrStep(&left);
- }else if( plrPosition(&left)+1>plrPosition(&right) ){
- plrStep(&right);
- }else{
- if( !match ){
- plwInit(&writer, pOut, dlrDocid(pLeft));
- match = 1;
- }
- plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0);
- plrStep(&left);
- plrStep(&right);
- }
- }
-
- if( match ){
- plwTerminate(&writer);
- plwDestroy(&writer);
- }
-
- plrDestroy(&left);
- plrDestroy(&right);
-}
-
-/* We have two doclists with positions: pLeft and pRight.
-** Write the phrase intersection of these two doclists into pOut.
-**
-** A phrase intersection means that two documents only match
-** if pLeft.iPos+1==pRight.iPos.
-**
-** iType controls the type of data written to pOut. If iType is
-** DL_POSITIONS, the positions are those from pRight.
-*/
-static void docListPhraseMerge(
- const char *pLeft, int nLeft,
- const char *pRight, int nRight,
- DocListType iType,
- DataBuffer *pOut /* Write the combined doclist here */
-){
- DLReader left, right;
- DLWriter writer;
-
- if( nLeft==0 || nRight==0 ) return;
-
- assert( iType!=DL_POSITIONS_OFFSETS );
-
- dlrInit(&left, DL_POSITIONS, pLeft, nLeft);
- dlrInit(&right, DL_POSITIONS, pRight, nRight);
- dlwInit(&writer, iType, pOut);
-
- while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){
- if( dlrDocid(&left)<dlrDocid(&right) ){
- dlrStep(&left);
- }else if( dlrDocid(&right)<dlrDocid(&left) ){
- dlrStep(&right);
- }else{
- posListPhraseMerge(&left, &right, &writer);
- dlrStep(&left);
- dlrStep(&right);
- }
- }
-
- dlrDestroy(&left);
- dlrDestroy(&right);
- dlwDestroy(&writer);
-}
-
-/* We have two DL_DOCIDS doclists: pLeft and pRight.
-** Write the intersection of these two doclists into pOut as a
-** DL_DOCIDS doclist.
-*/
-static void docListAndMerge(
- const char *pLeft, int nLeft,
- const char *pRight, int nRight,
- DataBuffer *pOut /* Write the combined doclist here */
-){
- DLReader left, right;
- DLWriter writer;
-
- if( nLeft==0 || nRight==0 ) return;
-
- dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
- dlrInit(&right, DL_DOCIDS, pRight, nRight);
- dlwInit(&writer, DL_DOCIDS, pOut);
-
- while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){
- if( dlrDocid(&left)<dlrDocid(&right) ){
- dlrStep(&left);
- }else if( dlrDocid(&right)<dlrDocid(&left) ){
- dlrStep(&right);
- }else{
- dlwAdd(&writer, dlrDocid(&left));
- dlrStep(&left);
- dlrStep(&right);
- }
- }
-
- dlrDestroy(&left);
- dlrDestroy(&right);
- dlwDestroy(&writer);
-}
-
-/* We have two DL_DOCIDS doclists: pLeft and pRight.
-** Write the union of these two doclists into pOut as a
-** DL_DOCIDS doclist.
-*/
-static void docListOrMerge(
- const char *pLeft, int nLeft,
- const char *pRight, int nRight,
- DataBuffer *pOut /* Write the combined doclist here */
-){
- DLReader left, right;
- DLWriter writer;
-
- if( nLeft==0 ){
- if( nRight!=0 ) dataBufferAppend(pOut, pRight, nRight);
- return;
- }
- if( nRight==0 ){
- dataBufferAppend(pOut, pLeft, nLeft);
- return;
- }
-
- dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
- dlrInit(&right, DL_DOCIDS, pRight, nRight);
- dlwInit(&writer, DL_DOCIDS, pOut);
-
- while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){
- if( dlrAtEnd(&right) ){
- dlwAdd(&writer, dlrDocid(&left));
- dlrStep(&left);
- }else if( dlrAtEnd(&left) ){
- dlwAdd(&writer, dlrDocid(&right));
- dlrStep(&right);
- }else if( dlrDocid(&left)<dlrDocid(&right) ){
- dlwAdd(&writer, dlrDocid(&left));
- dlrStep(&left);
- }else if( dlrDocid(&right)<dlrDocid(&left) ){
- dlwAdd(&writer, dlrDocid(&right));
- dlrStep(&right);
- }else{
- dlwAdd(&writer, dlrDocid(&left));
- dlrStep(&left);
- dlrStep(&right);
- }
- }
-
- dlrDestroy(&left);
- dlrDestroy(&right);
- dlwDestroy(&writer);
-}
-
-/* We have two DL_DOCIDS doclists: pLeft and pRight.
-** Write into pOut as DL_DOCIDS doclist containing all documents that
-** occur in pLeft but not in pRight.
-*/
-static void docListExceptMerge(
- const char *pLeft, int nLeft,
- const char *pRight, int nRight,
- DataBuffer *pOut /* Write the combined doclist here */
-){
- DLReader left, right;
- DLWriter writer;
-
- if( nLeft==0 ) return;
- if( nRight==0 ){
- dataBufferAppend(pOut, pLeft, nLeft);
- return;
- }
-
- dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
- dlrInit(&right, DL_DOCIDS, pRight, nRight);
- dlwInit(&writer, DL_DOCIDS, pOut);
-
- while( !dlrAtEnd(&left) ){
- while( !dlrAtEnd(&right) && dlrDocid(&right)<dlrDocid(&left) ){
- dlrStep(&right);
- }
- if( dlrAtEnd(&right) || dlrDocid(&left)<dlrDocid(&right) ){
- dlwAdd(&writer, dlrDocid(&left));
- }
- dlrStep(&left);
- }
-
- dlrDestroy(&left);
- dlrDestroy(&right);
- dlwDestroy(&writer);
-}
-
-static char *string_dup_n(const char *s, int n){
- char *str = sqlite3_malloc(n + 1);
- memcpy(str, s, n);
- str[n] = '\0';
- return str;
-}
-
-/* Duplicate a string; the caller must free() the returned string.
- * (We don't use strdup() since it is not part of the standard C library and
- * may not be available everywhere.) */
-static char *string_dup(const char *s){
- return string_dup_n(s, strlen(s));
-}
-
-/* Format a string, replacing each occurrence of the % character with
- * zDb.zName. This may be more convenient than sqlite_mprintf()
- * when one string is used repeatedly in a format string.
- * The caller must free() the returned string. */
-static char *string_format(const char *zFormat,
- const char *zDb, const char *zName){
- const char *p;
- size_t len = 0;
- size_t nDb = strlen(zDb);
- size_t nName = strlen(zName);
- size_t nFullTableName = nDb+1+nName;
- char *result;
- char *r;
-
- /* first compute length needed */
- for(p = zFormat ; *p ; ++p){
- len += (*p=='%' ? nFullTableName : 1);
- }
- len += 1; /* for null terminator */
-
- r = result = sqlite3_malloc(len);
- for(p = zFormat; *p; ++p){
- if( *p=='%' ){
- memcpy(r, zDb, nDb);
- r += nDb;
- *r++ = '.';
- memcpy(r, zName, nName);
- r += nName;
- } else {
- *r++ = *p;
- }
- }
- *r++ = '\0';
- assert( r == result + len );
- return result;
-}
-
-static int sql_exec(sqlite3 *db, const char *zDb, const char *zName,
- const char *zFormat){
- char *zCommand = string_format(zFormat, zDb, zName);
- int rc;
- TRACE(("FTS2 sql: %s\n", zCommand));
- rc = sqlite3_exec(db, zCommand, NULL, 0, NULL);
- sqlite3_free(zCommand);
- return rc;
-}
-
-static int sql_prepare(sqlite3 *db, const char *zDb, const char *zName,
- sqlite3_stmt **ppStmt, const char *zFormat){
- char *zCommand = string_format(zFormat, zDb, zName);
- int rc;
- TRACE(("FTS2 prepare: %s\n", zCommand));
- rc = sqlite3_prepare_v2(db, zCommand, -1, ppStmt, NULL);
- sqlite3_free(zCommand);
- return rc;
-}
-
-/* end utility functions */
-
-/* Forward reference */
-typedef struct fulltext_vtab fulltext_vtab;
-
-/* A single term in a query is represented by an instances of
-** the following structure.
-*/
-typedef struct QueryTerm {
- short int nPhrase; /* How many following terms are part of the same phrase */
- short int iPhrase; /* This is the i-th term of a phrase. */
- short int iColumn; /* Column of the index that must match this term */
- signed char isOr; /* this term is preceded by "OR" */
- signed char isNot; /* this term is preceded by "-" */
- signed char isPrefix; /* this term is followed by "*" */
- char *pTerm; /* text of the term. '\000' terminated. malloced */
- int nTerm; /* Number of bytes in pTerm[] */
-} QueryTerm;
-
-
-/* A query string is parsed into a Query structure.
- *
- * We could, in theory, allow query strings to be complicated
- * nested expressions with precedence determined by parentheses.
- * But none of the major search engines do this. (Perhaps the
- * feeling is that an parenthesized expression is two complex of
- * an idea for the average user to grasp.) Taking our lead from
- * the major search engines, we will allow queries to be a list
- * of terms (with an implied AND operator) or phrases in double-quotes,
- * with a single optional "-" before each non-phrase term to designate
- * negation and an optional OR connector.
- *
- * OR binds more tightly than the implied AND, which is what the
- * major search engines seem to do. So, for example:
- *
- * [one two OR three] ==> one AND (two OR three)
- * [one OR two three] ==> (one OR two) AND three
- *
- * A "-" before a term matches all entries that lack that term.
- * The "-" must occur immediately before the term with in intervening
- * space. This is how the search engines do it.
- *
- * A NOT term cannot be the right-hand operand of an OR. If this
- * occurs in the query string, the NOT is ignored:
- *
- * [one OR -two] ==> one OR two
- *
- */
-typedef struct Query {
- fulltext_vtab *pFts; /* The full text index */
- int nTerms; /* Number of terms in the query */
- QueryTerm *pTerms; /* Array of terms. Space obtained from malloc() */
- int nextIsOr; /* Set the isOr flag on the next inserted term */
- int nextColumn; /* Next word parsed must be in this column */
- int dfltColumn; /* The default column */
-} Query;
-
-
-/*
-** An instance of the following structure keeps track of generated
-** matching-word offset information and snippets.
-*/
-typedef struct Snippet {
- int nMatch; /* Total number of matches */
- int nAlloc; /* Space allocated for aMatch[] */
- struct snippetMatch { /* One entry for each matching term */
- char snStatus; /* Status flag for use while constructing snippets */
- short int iCol; /* The column that contains the match */
- short int iTerm; /* The index in Query.pTerms[] of the matching term */
- short int nByte; /* Number of bytes in the term */
- int iStart; /* The offset to the first character of the term */
- } *aMatch; /* Points to space obtained from malloc */
- char *zOffset; /* Text rendering of aMatch[] */
- int nOffset; /* strlen(zOffset) */
- char *zSnippet; /* Snippet text */
- int nSnippet; /* strlen(zSnippet) */
-} Snippet;
-
-
-typedef enum QueryType {
- QUERY_GENERIC, /* table scan */
- QUERY_ROWID, /* lookup by rowid */
- QUERY_FULLTEXT /* QUERY_FULLTEXT + [i] is a full-text search for column i*/
-} QueryType;
-
-typedef enum fulltext_statement {
- CONTENT_INSERT_STMT,
- CONTENT_SELECT_STMT,
- CONTENT_UPDATE_STMT,
- CONTENT_DELETE_STMT,
- CONTENT_EXISTS_STMT,
-
- BLOCK_INSERT_STMT,
- BLOCK_SELECT_STMT,
- BLOCK_DELETE_STMT,
- BLOCK_DELETE_ALL_STMT,
-
- SEGDIR_MAX_INDEX_STMT,
- SEGDIR_SET_STMT,
- SEGDIR_SELECT_LEVEL_STMT,
- SEGDIR_SPAN_STMT,
- SEGDIR_DELETE_STMT,
- SEGDIR_SELECT_SEGMENT_STMT,
- SEGDIR_SELECT_ALL_STMT,
- SEGDIR_DELETE_ALL_STMT,
- SEGDIR_COUNT_STMT,
-
- MAX_STMT /* Always at end! */
-} fulltext_statement;
-
-/* These must exactly match the enum above. */
-/* TODO(shess): Is there some risk that a statement will be used in two
-** cursors at once, e.g. if a query joins a virtual table to itself?
-** If so perhaps we should move some of these to the cursor object.
-*/
-static const char *const fulltext_zStatement[MAX_STMT] = {
- /* CONTENT_INSERT */ NULL, /* generated in contentInsertStatement() */
- /* CONTENT_SELECT */ "select * from %_content where rowid = ?",
- /* CONTENT_UPDATE */ NULL, /* generated in contentUpdateStatement() */
- /* CONTENT_DELETE */ "delete from %_content where rowid = ?",
- /* CONTENT_EXISTS */ "select rowid from %_content limit 1",
-
- /* BLOCK_INSERT */ "insert into %_segments values (?)",
- /* BLOCK_SELECT */ "select block from %_segments where rowid = ?",
- /* BLOCK_DELETE */ "delete from %_segments where rowid between ? and ?",
- /* BLOCK_DELETE_ALL */ "delete from %_segments",
-
- /* SEGDIR_MAX_INDEX */ "select max(idx) from %_segdir where level = ?",
- /* SEGDIR_SET */ "insert into %_segdir values (?, ?, ?, ?, ?, ?)",
- /* SEGDIR_SELECT_LEVEL */
- "select start_block, leaves_end_block, root from %_segdir "
- " where level = ? order by idx",
- /* SEGDIR_SPAN */
- "select min(start_block), max(end_block) from %_segdir "
- " where level = ? and start_block <> 0",
- /* SEGDIR_DELETE */ "delete from %_segdir where level = ?",
-
- /* NOTE(shess): The first three results of the following two
- ** statements must match.
- */
- /* SEGDIR_SELECT_SEGMENT */
- "select start_block, leaves_end_block, root from %_segdir "
- " where level = ? and idx = ?",
- /* SEGDIR_SELECT_ALL */
- "select start_block, leaves_end_block, root from %_segdir "
- " order by level desc, idx asc",
- /* SEGDIR_DELETE_ALL */ "delete from %_segdir",
- /* SEGDIR_COUNT */ "select count(*), ifnull(max(level),0) from %_segdir",
-};
-
-/*
-** A connection to a fulltext index is an instance of the following
-** structure. The xCreate and xConnect methods create an instance
-** of this structure and xDestroy and xDisconnect free that instance.
-** All other methods receive a pointer to the structure as one of their
-** arguments.
-*/
-struct fulltext_vtab {
- sqlite3_vtab base; /* Base class used by SQLite core */
- sqlite3 *db; /* The database connection */
- const char *zDb; /* logical database name */
- const char *zName; /* virtual table name */
- int nColumn; /* number of columns in virtual table */
- char **azColumn; /* column names. malloced */
- char **azContentColumn; /* column names in content table; malloced */
- sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
-
- /* Precompiled statements which we keep as long as the table is
- ** open.
- */
- sqlite3_stmt *pFulltextStatements[MAX_STMT];
-
- /* Precompiled statements used for segment merges. We run a
- ** separate select across the leaf level of each tree being merged.
- */
- sqlite3_stmt *pLeafSelectStmts[MERGE_COUNT];
- /* The statement used to prepare pLeafSelectStmts. */
-#define LEAF_SELECT \
- "select block from %_segments where rowid between ? and ? order by rowid"
-
- /* These buffer pending index updates during transactions.
- ** nPendingData estimates the memory size of the pending data. It
- ** doesn't include the hash-bucket overhead, nor any malloc
- ** overhead. When nPendingData exceeds kPendingThreshold, the
- ** buffer is flushed even before the transaction closes.
- ** pendingTerms stores the data, and is only valid when nPendingData
- ** is >=0 (nPendingData<0 means pendingTerms has not been
- ** initialized). iPrevDocid is the last docid written, used to make
- ** certain we're inserting in sorted order.
- */
- int nPendingData;
-#define kPendingThreshold (1*1024*1024)
- sqlite_int64 iPrevDocid;
- fts2Hash pendingTerms;
-};
-
-/*
-** When the core wants to do a query, it create a cursor using a
-** call to xOpen. This structure is an instance of a cursor. It
-** is destroyed by xClose.
-*/
-typedef struct fulltext_cursor {
- sqlite3_vtab_cursor base; /* Base class used by SQLite core */
- QueryType iCursorType; /* Copy of sqlite3_index_info.idxNum */
- sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
- int eof; /* True if at End Of Results */
- Query q; /* Parsed query string */
- Snippet snippet; /* Cached snippet for the current row */
- int iColumn; /* Column being searched */
- DataBuffer result; /* Doclist results from fulltextQuery */
- DLReader reader; /* Result reader if result not empty */
-} fulltext_cursor;
-
-static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){
- return (fulltext_vtab *) c->base.pVtab;
-}
-
-static const sqlite3_module fts2Module; /* forward declaration */
-
-/* Return a dynamically generated statement of the form
- * insert into %_content (rowid, ...) values (?, ...)
- */
-static const char *contentInsertStatement(fulltext_vtab *v){
- StringBuffer sb;
- int i;
-
- initStringBuffer(&sb);
- append(&sb, "insert into %_content (rowid, ");
- appendList(&sb, v->nColumn, v->azContentColumn);
- append(&sb, ") values (?");
- for(i=0; i<v->nColumn; ++i)
- append(&sb, ", ?");
- append(&sb, ")");
- return stringBufferData(&sb);
-}
-
-/* Return a dynamically generated statement of the form
- * update %_content set [col_0] = ?, [col_1] = ?, ...
- * where rowid = ?
- */
-static const char *contentUpdateStatement(fulltext_vtab *v){
- StringBuffer sb;
- int i;
-
- initStringBuffer(&sb);
- append(&sb, "update %_content set ");
- for(i=0; i<v->nColumn; ++i) {
- if( i>0 ){
- append(&sb, ", ");
- }
- append(&sb, v->azContentColumn[i]);
- append(&sb, " = ?");
- }
- append(&sb, " where rowid = ?");
- return stringBufferData(&sb);
-}
-
-/* Puts a freshly-prepared statement determined by iStmt in *ppStmt.
-** If the indicated statement has never been prepared, it is prepared
-** and cached, otherwise the cached version is reset.
-*/
-static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt,
- sqlite3_stmt **ppStmt){
- assert( iStmt<MAX_STMT );
- if( v->pFulltextStatements[iStmt]==NULL ){
- const char *zStmt;
- int rc;
- switch( iStmt ){
- case CONTENT_INSERT_STMT:
- zStmt = contentInsertStatement(v); break;
- case CONTENT_UPDATE_STMT:
- zStmt = contentUpdateStatement(v); break;
- default:
- zStmt = fulltext_zStatement[iStmt];
- }
- rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt],
- zStmt);
- if( zStmt != fulltext_zStatement[iStmt]) sqlite3_free((void *) zStmt);
- if( rc!=SQLITE_OK ) return rc;
- } else {
- int rc = sqlite3_reset(v->pFulltextStatements[iStmt]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- *ppStmt = v->pFulltextStatements[iStmt];
- return SQLITE_OK;
-}
-
-/* Like sqlite3_step(), but convert SQLITE_DONE to SQLITE_OK and
-** SQLITE_ROW to SQLITE_ERROR. Useful for statements like UPDATE,
-** where we expect no results.
-*/
-static int sql_single_step(sqlite3_stmt *s){
- int rc = sqlite3_step(s);
- return (rc==SQLITE_DONE) ? SQLITE_OK : rc;
-}
-
-/* Like sql_get_statement(), but for special replicated LEAF_SELECT
-** statements. idx -1 is a special case for an uncached version of
-** the statement (used in the optimize implementation).
-*/
-/* TODO(shess) Write version for generic statements and then share
-** that between the cached-statement functions.
-*/
-static int sql_get_leaf_statement(fulltext_vtab *v, int idx,
- sqlite3_stmt **ppStmt){
- assert( idx>=-1 && idx<MERGE_COUNT );
- if( idx==-1 ){
- return sql_prepare(v->db, v->zDb, v->zName, ppStmt, LEAF_SELECT);
- }else if( v->pLeafSelectStmts[idx]==NULL ){
- int rc = sql_prepare(v->db, v->zDb, v->zName, &v->pLeafSelectStmts[idx],
- LEAF_SELECT);
- if( rc!=SQLITE_OK ) return rc;
- }else{
- int rc = sqlite3_reset(v->pLeafSelectStmts[idx]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- *ppStmt = v->pLeafSelectStmts[idx];
- return SQLITE_OK;
-}
-
-/* insert into %_content (rowid, ...) values ([rowid], [pValues]) */
-static int content_insert(fulltext_vtab *v, sqlite3_value *rowid,
- sqlite3_value **pValues){
- sqlite3_stmt *s;
- int i;
- int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_value(s, 1, rowid);
- if( rc!=SQLITE_OK ) return rc;
-
- for(i=0; i<v->nColumn; ++i){
- rc = sqlite3_bind_value(s, 2+i, pValues[i]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- return sql_single_step(s);
-}
-
-/* update %_content set col0 = pValues[0], col1 = pValues[1], ...
- * where rowid = [iRowid] */
-static int content_update(fulltext_vtab *v, sqlite3_value **pValues,
- sqlite_int64 iRowid){
- sqlite3_stmt *s;
- int i;
- int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- for(i=0; i<v->nColumn; ++i){
- rc = sqlite3_bind_value(s, 1+i, pValues[i]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- rc = sqlite3_bind_int64(s, 1+v->nColumn, iRowid);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step(s);
-}
-
-static void freeStringArray(int nString, const char **pString){
- int i;
-
- for (i=0 ; i < nString ; ++i) {
- if( pString[i]!=NULL ) sqlite3_free((void *) pString[i]);
- }
- sqlite3_free((void *) pString);
-}
-
-/* select * from %_content where rowid = [iRow]
- * The caller must delete the returned array and all strings in it.
- * null fields will be NULL in the returned array.
- *
- * TODO: Perhaps we should return pointer/length strings here for consistency
- * with other code which uses pointer/length. */
-static int content_select(fulltext_vtab *v, sqlite_int64 iRow,
- const char ***pValues){
- sqlite3_stmt *s;
- const char **values;
- int i;
- int rc;
-
- *pValues = NULL;
-
- rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_step(s);
- if( rc!=SQLITE_ROW ) return rc;
-
- values = (const char **) sqlite3_malloc(v->nColumn * sizeof(const char *));
- for(i=0; i<v->nColumn; ++i){
- if( sqlite3_column_type(s, i)==SQLITE_NULL ){
- values[i] = NULL;
- }else{
- values[i] = string_dup((char*)sqlite3_column_text(s, i));
- }
- }
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- if( rc==SQLITE_DONE ){
- *pValues = values;
- return SQLITE_OK;
- }
-
- freeStringArray(v->nColumn, values);
- return rc;
-}
-
-/* delete from %_content where rowid = [iRow ] */
-static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step(s);
-}
-
-/* Returns SQLITE_ROW if any rows exist in %_content, SQLITE_DONE if
-** no rows exist, and any error in case of failure.
-*/
-static int content_exists(fulltext_vtab *v){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, CONTENT_EXISTS_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_step(s);
- if( rc!=SQLITE_ROW ) return rc;
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- if( rc==SQLITE_DONE ) return SQLITE_ROW;
- if( rc==SQLITE_ROW ) return SQLITE_ERROR;
- return rc;
-}
-
-/* insert into %_segments values ([pData])
-** returns assigned rowid in *piBlockid
-*/
-static int block_insert(fulltext_vtab *v, const char *pData, int nData,
- sqlite_int64 *piBlockid){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, BLOCK_INSERT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_blob(s, 1, pData, nData, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_step(s);
- if( rc==SQLITE_ROW ) return SQLITE_ERROR;
- if( rc!=SQLITE_DONE ) return rc;
-
- *piBlockid = sqlite3_last_insert_rowid(v->db);
- return SQLITE_OK;
-}
-
-/* delete from %_segments
-** where rowid between [iStartBlockid] and [iEndBlockid]
-**
-** Deletes the range of blocks, inclusive, used to delete the blocks
-** which form a segment.
-*/
-static int block_delete(fulltext_vtab *v,
- sqlite_int64 iStartBlockid, sqlite_int64 iEndBlockid){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, BLOCK_DELETE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iStartBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 2, iEndBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step(s);
-}
-
-/* Returns SQLITE_ROW with *pidx set to the maximum segment idx found
-** at iLevel. Returns SQLITE_DONE if there are no segments at
-** iLevel. Otherwise returns an error.
-*/
-static int segdir_max_index(fulltext_vtab *v, int iLevel, int *pidx){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, SEGDIR_MAX_INDEX_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int(s, 1, iLevel);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_step(s);
- /* Should always get at least one row due to how max() works. */
- if( rc==SQLITE_DONE ) return SQLITE_DONE;
- if( rc!=SQLITE_ROW ) return rc;
-
- /* NULL means that there were no inputs to max(). */
- if( SQLITE_NULL==sqlite3_column_type(s, 0) ){
- rc = sqlite3_step(s);
- if( rc==SQLITE_ROW ) return SQLITE_ERROR;
- return rc;
- }
-
- *pidx = sqlite3_column_int(s, 0);
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- if( rc==SQLITE_ROW ) return SQLITE_ERROR;
- if( rc!=SQLITE_DONE ) return rc;
- return SQLITE_ROW;
-}
-
-/* insert into %_segdir values (
-** [iLevel], [idx],
-** [iStartBlockid], [iLeavesEndBlockid], [iEndBlockid],
-** [pRootData]
-** )
-*/
-static int segdir_set(fulltext_vtab *v, int iLevel, int idx,
- sqlite_int64 iStartBlockid,
- sqlite_int64 iLeavesEndBlockid,
- sqlite_int64 iEndBlockid,
- const char *pRootData, int nRootData){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, SEGDIR_SET_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int(s, 1, iLevel);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int(s, 2, idx);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 3, iStartBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 4, iLeavesEndBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 5, iEndBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_blob(s, 6, pRootData, nRootData, SQLITE_STATIC);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step(s);
-}
-
-/* Queries %_segdir for the block span of the segments in level
-** iLevel. Returns SQLITE_DONE if there are no blocks for iLevel,
-** SQLITE_ROW if there are blocks, else an error.
-*/
-static int segdir_span(fulltext_vtab *v, int iLevel,
- sqlite_int64 *piStartBlockid,
- sqlite_int64 *piEndBlockid){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, SEGDIR_SPAN_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int(s, 1, iLevel);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_step(s);
- if( rc==SQLITE_DONE ) return SQLITE_DONE; /* Should never happen */
- if( rc!=SQLITE_ROW ) return rc;
-
- /* This happens if all segments at this level are entirely inline. */
- if( SQLITE_NULL==sqlite3_column_type(s, 0) ){
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- int rc2 = sqlite3_step(s);
- if( rc2==SQLITE_ROW ) return SQLITE_ERROR;
- return rc2;
- }
-
- *piStartBlockid = sqlite3_column_int64(s, 0);
- *piEndBlockid = sqlite3_column_int64(s, 1);
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- if( rc==SQLITE_ROW ) return SQLITE_ERROR;
- if( rc!=SQLITE_DONE ) return rc;
- return SQLITE_ROW;
-}
-
-/* Delete the segment blocks and segment directory records for all
-** segments at iLevel.
-*/
-static int segdir_delete(fulltext_vtab *v, int iLevel){
- sqlite3_stmt *s;
- sqlite_int64 iStartBlockid, iEndBlockid;
- int rc = segdir_span(v, iLevel, &iStartBlockid, &iEndBlockid);
- if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc;
-
- if( rc==SQLITE_ROW ){
- rc = block_delete(v, iStartBlockid, iEndBlockid);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- /* Delete the segment directory itself. */
- rc = sql_get_statement(v, SEGDIR_DELETE_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iLevel);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step(s);
-}
-
-/* Delete entire fts index, SQLITE_OK on success, relevant error on
-** failure.
-*/
-static int segdir_delete_all(fulltext_vtab *v){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, SEGDIR_DELETE_ALL_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sql_single_step(s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sql_get_statement(v, BLOCK_DELETE_ALL_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- return sql_single_step(s);
-}
-
-/* Returns SQLITE_OK with *pnSegments set to the number of entries in
-** %_segdir and *piMaxLevel set to the highest level which has a
-** segment. Otherwise returns the SQLite error which caused failure.
-*/
-static int segdir_count(fulltext_vtab *v, int *pnSegments, int *piMaxLevel){
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, SEGDIR_COUNT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_step(s);
- /* TODO(shess): This case should not be possible? Should stronger
- ** measures be taken if it happens?
- */
- if( rc==SQLITE_DONE ){
- *pnSegments = 0;
- *piMaxLevel = 0;
- return SQLITE_OK;
- }
- if( rc!=SQLITE_ROW ) return rc;
-
- *pnSegments = sqlite3_column_int(s, 0);
- *piMaxLevel = sqlite3_column_int(s, 1);
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain locked. */
- rc = sqlite3_step(s);
- if( rc==SQLITE_DONE ) return SQLITE_OK;
- if( rc==SQLITE_ROW ) return SQLITE_ERROR;
- return rc;
-}
-
-/* TODO(shess) clearPendingTerms() is far down the file because
-** writeZeroSegment() is far down the file because LeafWriter is far
-** down the file. Consider refactoring the code to move the non-vtab
-** code above the vtab code so that we don't need this forward
-** reference.
-*/
-static int clearPendingTerms(fulltext_vtab *v);
-
-/*
-** Free the memory used to contain a fulltext_vtab structure.
-*/
-static void fulltext_vtab_destroy(fulltext_vtab *v){
- int iStmt, i;
-
- TRACE(("FTS2 Destroy %p\n", v));
- for( iStmt=0; iStmt<MAX_STMT; iStmt++ ){
- if( v->pFulltextStatements[iStmt]!=NULL ){
- sqlite3_finalize(v->pFulltextStatements[iStmt]);
- v->pFulltextStatements[iStmt] = NULL;
- }
- }
-
- for( i=0; i<MERGE_COUNT; i++ ){
- if( v->pLeafSelectStmts[i]!=NULL ){
- sqlite3_finalize(v->pLeafSelectStmts[i]);
- v->pLeafSelectStmts[i] = NULL;
- }
- }
-
- if( v->pTokenizer!=NULL ){
- v->pTokenizer->pModule->xDestroy(v->pTokenizer);
- v->pTokenizer = NULL;
- }
-
- clearPendingTerms(v);
-
- sqlite3_free(v->azColumn);
- for(i = 0; i < v->nColumn; ++i) {
- sqlite3_free(v->azContentColumn[i]);
- }
- sqlite3_free(v->azContentColumn);
- sqlite3_free(v);
-}
-
-/*
-** Token types for parsing the arguments to xConnect or xCreate.
-*/
-#define TOKEN_EOF 0 /* End of file */
-#define TOKEN_SPACE 1 /* Any kind of whitespace */
-#define TOKEN_ID 2 /* An identifier */
-#define TOKEN_STRING 3 /* A string literal */
-#define TOKEN_PUNCT 4 /* A single punctuation character */
-
-/*
-** If X is a character that can be used in an identifier then
-** IdChar(X) will be true. Otherwise it is false.
-**
-** For ASCII, any character with the high-order bit set is
-** allowed in an identifier. For 7-bit characters,
-** sqlite3IsIdChar[X] must be 1.
-**
-** Ticket #1066. the SQL standard does not allow '$' in the
-** middle of identfiers. But many SQL implementations do.
-** SQLite will allow '$' in identifiers for compatibility.
-** But the feature is undocumented.
-*/
-static const char isIdChar[] = {
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
- 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
-};
-#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20]))
-
-
-/*
-** Return the length of the token that begins at z[0].
-** Store the token type in *tokenType before returning.
-*/
-static int getToken(const char *z, int *tokenType){
- int i, c;
- switch( *z ){
- case 0: {
- *tokenType = TOKEN_EOF;
- return 0;
- }
- case ' ': case '\t': case '\n': case '\f': case '\r': {
- for(i=1; safe_isspace(z[i]); i++){}
- *tokenType = TOKEN_SPACE;
- return i;
- }
- case '`':
- case '\'':
- case '"': {
- int delim = z[0];
- for(i=1; (c=z[i])!=0; i++){
- if( c==delim ){
- if( z[i+1]==delim ){
- i++;
- }else{
- break;
- }
- }
- }
- *tokenType = TOKEN_STRING;
- return i + (c!=0);
- }
- case '[': {
- for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
- *tokenType = TOKEN_ID;
- return i;
- }
- default: {
- if( !IdChar(*z) ){
- break;
- }
- for(i=1; IdChar(z[i]); i++){}
- *tokenType = TOKEN_ID;
- return i;
- }
- }
- *tokenType = TOKEN_PUNCT;
- return 1;
-}
-
-/*
-** A token extracted from a string is an instance of the following
-** structure.
-*/
-typedef struct Token {
- const char *z; /* Pointer to token text. Not '\000' terminated */
- short int n; /* Length of the token text in bytes. */
-} Token;
-
-/*
-** Given a input string (which is really one of the argv[] parameters
-** passed into xConnect or xCreate) split the string up into tokens.
-** Return an array of pointers to '\000' terminated strings, one string
-** for each non-whitespace token.
-**
-** The returned array is terminated by a single NULL pointer.
-**
-** Space to hold the returned array is obtained from a single
-** malloc and should be freed by passing the return value to free().
-** The individual strings within the token list are all a part of
-** the single memory allocation and will all be freed at once.
-*/
-static char **tokenizeString(const char *z, int *pnToken){
- int nToken = 0;
- Token *aToken = sqlite3_malloc( strlen(z) * sizeof(aToken[0]) );
- int n = 1;
- int e, i;
- int totalSize = 0;
- char **azToken;
- char *zCopy;
- while( n>0 ){
- n = getToken(z, &e);
- if( e!=TOKEN_SPACE ){
- aToken[nToken].z = z;
- aToken[nToken].n = n;
- nToken++;
- totalSize += n+1;
- }
- z += n;
- }
- azToken = (char**)sqlite3_malloc( nToken*sizeof(char*) + totalSize );
- zCopy = (char*)&azToken[nToken];
- nToken--;
- for(i=0; i<nToken; i++){
- azToken[i] = zCopy;
- n = aToken[i].n;
- memcpy(zCopy, aToken[i].z, n);
- zCopy[n] = 0;
- zCopy += n+1;
- }
- azToken[nToken] = 0;
- sqlite3_free(aToken);
- *pnToken = nToken;
- return azToken;
-}
-
-/*
-** Convert an SQL-style quoted string into a normal string by removing
-** the quote characters. The conversion is done in-place. If the
-** input does not begin with a quote character, then this routine
-** is a no-op.
-**
-** Examples:
-**
-** "abc" becomes abc
-** 'xyz' becomes xyz
-** [pqr] becomes pqr
-** `mno` becomes mno
-*/
-static void dequoteString(char *z){
- int quote;
- int i, j;
- if( z==0 ) return;
- quote = z[0];
- switch( quote ){
- case '\'': break;
- case '"': break;
- case '`': break; /* For MySQL compatibility */
- case '[': quote = ']'; break; /* For MS SqlServer compatibility */
- default: return;
- }
- for(i=1, j=0; z[i]; i++){
- if( z[i]==quote ){
- if( z[i+1]==quote ){
- z[j++] = quote;
- i++;
- }else{
- z[j++] = 0;
- break;
- }
- }else{
- z[j++] = z[i];
- }
- }
-}
-
-/*
-** The input azIn is a NULL-terminated list of tokens. Remove the first
-** token and all punctuation tokens. Remove the quotes from
-** around string literal tokens.
-**
-** Example:
-**
-** input: tokenize chinese ( 'simplifed' , 'mixed' )
-** output: chinese simplifed mixed
-**
-** Another example:
-**
-** input: delimiters ( '[' , ']' , '...' )
-** output: [ ] ...
-*/
-static void tokenListToIdList(char **azIn){
- int i, j;
- if( azIn ){
- for(i=0, j=-1; azIn[i]; i++){
- if( safe_isalnum(azIn[i][0]) || azIn[i][1] ){
- dequoteString(azIn[i]);
- if( j>=0 ){
- azIn[j] = azIn[i];
- }
- j++;
- }
- }
- azIn[j] = 0;
- }
-}
-
-
-/*
-** Find the first alphanumeric token in the string zIn. Null-terminate
-** this token. Remove any quotation marks. And return a pointer to
-** the result.
-*/
-static char *firstToken(char *zIn, char **pzTail){
- int n, ttype;
- while(1){
- n = getToken(zIn, &ttype);
- if( ttype==TOKEN_SPACE ){
- zIn += n;
- }else if( ttype==TOKEN_EOF ){
- *pzTail = zIn;
- return 0;
- }else{
- zIn[n] = 0;
- *pzTail = &zIn[1];
- dequoteString(zIn);
- return zIn;
- }
- }
- /*NOTREACHED*/
-}
-
-/* Return true if...
-**
-** * s begins with the string t, ignoring case
-** * s is longer than t
-** * The first character of s beyond t is not a alphanumeric
-**
-** Ignore leading space in *s.
-**
-** To put it another way, return true if the first token of
-** s[] is t[].
-*/
-static int startsWith(const char *s, const char *t){
- while( safe_isspace(*s) ){ s++; }
- while( *t ){
- if( safe_tolower(*s++)!=safe_tolower(*t++) ) return 0;
- }
- return *s!='_' && !safe_isalnum(*s);
-}
-
-/*
-** An instance of this structure defines the "spec" of a
-** full text index. This structure is populated by parseSpec
-** and use by fulltextConnect and fulltextCreate.
-*/
-typedef struct TableSpec {
- const char *zDb; /* Logical database name */
- const char *zName; /* Name of the full-text index */
- int nColumn; /* Number of columns to be indexed */
- char **azColumn; /* Original names of columns to be indexed */
- char **azContentColumn; /* Column names for %_content */
- char **azTokenizer; /* Name of tokenizer and its arguments */
-} TableSpec;
-
-/*
-** Reclaim all of the memory used by a TableSpec
-*/
-static void clearTableSpec(TableSpec *p) {
- sqlite3_free(p->azColumn);
- sqlite3_free(p->azContentColumn);
- sqlite3_free(p->azTokenizer);
-}
-
-/* Parse a CREATE VIRTUAL TABLE statement, which looks like this:
- *
- * CREATE VIRTUAL TABLE email
- * USING fts2(subject, body, tokenize mytokenizer(myarg))
- *
- * We return parsed information in a TableSpec structure.
- *
- */
-static int parseSpec(TableSpec *pSpec, int argc, const char *const*argv,
- char**pzErr){
- int i, n;
- char *z, *zDummy;
- char **azArg;
- const char *zTokenizer = 0; /* argv[] entry describing the tokenizer */
-
- assert( argc>=3 );
- /* Current interface:
- ** argv[0] - module name
- ** argv[1] - database name
- ** argv[2] - table name
- ** argv[3..] - columns, optionally followed by tokenizer specification
- ** and snippet delimiters specification.
- */
-
- /* Make a copy of the complete argv[][] array in a single allocation.
- ** The argv[][] array is read-only and transient. We can write to the
- ** copy in order to modify things and the copy is persistent.
- */
- CLEAR(pSpec);
- for(i=n=0; i<argc; i++){
- n += strlen(argv[i]) + 1;
- }
- azArg = sqlite3_malloc( sizeof(char*)*argc + n );
- if( azArg==0 ){
- return SQLITE_NOMEM;
- }
- z = (char*)&azArg[argc];
- for(i=0; i<argc; i++){
- azArg[i] = z;
- strcpy(z, argv[i]);
- z += strlen(z)+1;
- }
-
- /* Identify the column names and the tokenizer and delimiter arguments
- ** in the argv[][] array.
- */
- pSpec->zDb = azArg[1];
- pSpec->zName = azArg[2];
- pSpec->nColumn = 0;
- pSpec->azColumn = azArg;
- zTokenizer = "tokenize simple";
- for(i=3; i<argc; ++i){
- if( startsWith(azArg[i],"tokenize") ){
- zTokenizer = azArg[i];
- }else{
- z = azArg[pSpec->nColumn] = firstToken(azArg[i], &zDummy);
- pSpec->nColumn++;
- }
- }
- if( pSpec->nColumn==0 ){
- azArg[0] = "content";
- pSpec->nColumn = 1;
- }
-
- /*
- ** Construct the list of content column names.
- **
- ** Each content column name will be of the form cNNAAAA
- ** where NN is the column number and AAAA is the sanitized
- ** column name. "sanitized" means that special characters are
- ** converted to "_". The cNN prefix guarantees that all column
- ** names are unique.
- **
- ** The AAAA suffix is not strictly necessary. It is included
- ** for the convenience of people who might examine the generated
- ** %_content table and wonder what the columns are used for.
- */
- pSpec->azContentColumn = sqlite3_malloc( pSpec->nColumn * sizeof(char *) );
- if( pSpec->azContentColumn==0 ){
- clearTableSpec(pSpec);
- return SQLITE_NOMEM;
- }
- for(i=0; i<pSpec->nColumn; i++){
- char *p;
- pSpec->azContentColumn[i] = sqlite3_mprintf("c%d%s", i, azArg[i]);
- for (p = pSpec->azContentColumn[i]; *p ; ++p) {
- if( !safe_isalnum(*p) ) *p = '_';
- }
- }
-
- /*
- ** Parse the tokenizer specification string.
- */
- pSpec->azTokenizer = tokenizeString(zTokenizer, &n);
- tokenListToIdList(pSpec->azTokenizer);
-
- return SQLITE_OK;
-}
-
-/*
-** Generate a CREATE TABLE statement that describes the schema of
-** the virtual table. Return a pointer to this schema string.
-**
-** Space is obtained from sqlite3_mprintf() and should be freed
-** using sqlite3_free().
-*/
-static char *fulltextSchema(
- int nColumn, /* Number of columns */
- const char *const* azColumn, /* List of columns */
- const char *zTableName /* Name of the table */
-){
- int i;
- char *zSchema, *zNext;
- const char *zSep = "(";
- zSchema = sqlite3_mprintf("CREATE TABLE x");
- for(i=0; i<nColumn; i++){
- zNext = sqlite3_mprintf("%s%s%Q", zSchema, zSep, azColumn[i]);
- sqlite3_free(zSchema);
- zSchema = zNext;
- zSep = ",";
- }
- zNext = sqlite3_mprintf("%s,%Q)", zSchema, zTableName);
- sqlite3_free(zSchema);
- return zNext;
-}
-
-/*
-** Build a new sqlite3_vtab structure that will describe the
-** fulltext index defined by spec.
-*/
-static int constructVtab(
- sqlite3 *db, /* The SQLite database connection */
- fts2Hash *pHash, /* Hash table containing tokenizers */
- TableSpec *spec, /* Parsed spec information from parseSpec() */
- sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
- char **pzErr /* Write any error message here */
-){
- int rc;
- int n;
- fulltext_vtab *v = 0;
- const sqlite3_tokenizer_module *m = NULL;
- char *schema;
-
- char const *zTok; /* Name of tokenizer to use for this fts table */
- int nTok; /* Length of zTok, including nul terminator */
-
- v = (fulltext_vtab *) sqlite3_malloc(sizeof(fulltext_vtab));
- if( v==0 ) return SQLITE_NOMEM;
- CLEAR(v);
- /* sqlite will initialize v->base */
- v->db = db;
- v->zDb = spec->zDb; /* Freed when azColumn is freed */
- v->zName = spec->zName; /* Freed when azColumn is freed */
- v->nColumn = spec->nColumn;
- v->azContentColumn = spec->azContentColumn;
- spec->azContentColumn = 0;
- v->azColumn = spec->azColumn;
- spec->azColumn = 0;
-
- if( spec->azTokenizer==0 ){
- return SQLITE_NOMEM;
- }
-
- zTok = spec->azTokenizer[0];
- if( !zTok ){
- zTok = "simple";
- }
- nTok = strlen(zTok)+1;
-
- m = (sqlite3_tokenizer_module *)sqlite3Fts2HashFind(pHash, zTok, nTok);
- if( !m ){
- *pzErr = sqlite3_mprintf("unknown tokenizer: %s", spec->azTokenizer[0]);
- rc = SQLITE_ERROR;
- goto err;
- }
-
- for(n=0; spec->azTokenizer[n]; n++){}
- if( n ){
- rc = m->xCreate(n-1, (const char*const*)&spec->azTokenizer[1],
- &v->pTokenizer);
- }else{
- rc = m->xCreate(0, 0, &v->pTokenizer);
- }
- if( rc!=SQLITE_OK ) goto err;
- v->pTokenizer->pModule = m;
-
- /* TODO: verify the existence of backing tables foo_content, foo_term */
-
- schema = fulltextSchema(v->nColumn, (const char*const*)v->azColumn,
- spec->zName);
- rc = sqlite3_declare_vtab(db, schema);
- sqlite3_free(schema);
- if( rc!=SQLITE_OK ) goto err;
-
- memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements));
-
- /* Indicate that the buffer is not live. */
- v->nPendingData = -1;
-
- *ppVTab = &v->base;
- TRACE(("FTS2 Connect %p\n", v));
-
- return rc;
-
-err:
- fulltext_vtab_destroy(v);
- return rc;
-}
-
-static int fulltextConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab,
- char **pzErr
-){
- TableSpec spec;
- int rc = parseSpec(&spec, argc, argv, pzErr);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = constructVtab(db, (fts2Hash *)pAux, &spec, ppVTab, pzErr);
- clearTableSpec(&spec);
- return rc;
-}
-
-/* The %_content table holds the text of each document, with
-** the rowid used as the docid.
-*/
-/* TODO(shess) This comment needs elaboration to match the updated
-** code. Work it into the top-of-file comment at that time.
-*/
-static int fulltextCreate(sqlite3 *db, void *pAux,
- int argc, const char * const *argv,
- sqlite3_vtab **ppVTab, char **pzErr){
- int rc;
- TableSpec spec;
- StringBuffer schema;
- TRACE(("FTS2 Create\n"));
-
- rc = parseSpec(&spec, argc, argv, pzErr);
- if( rc!=SQLITE_OK ) return rc;
-
- initStringBuffer(&schema);
- append(&schema, "CREATE TABLE %_content(");
- appendList(&schema, spec.nColumn, spec.azContentColumn);
- append(&schema, ")");
- rc = sql_exec(db, spec.zDb, spec.zName, stringBufferData(&schema));
- stringBufferDestroy(&schema);
- if( rc!=SQLITE_OK ) goto out;
-
- rc = sql_exec(db, spec.zDb, spec.zName,
- "create table %_segments(block blob);");
- if( rc!=SQLITE_OK ) goto out;
-
- rc = sql_exec(db, spec.zDb, spec.zName,
- "create table %_segdir("
- " level integer,"
- " idx integer,"
- " start_block integer,"
- " leaves_end_block integer,"
- " end_block integer,"
- " root blob,"
- " primary key(level, idx)"
- ");");
- if( rc!=SQLITE_OK ) goto out;
-
- rc = constructVtab(db, (fts2Hash *)pAux, &spec, ppVTab, pzErr);
-
-out:
- clearTableSpec(&spec);
- return rc;
-}
-
-/* Decide how to handle an SQL query. */
-static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
- int i;
- TRACE(("FTS2 BestIndex\n"));
-
- for(i=0; i<pInfo->nConstraint; ++i){
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = &pInfo->aConstraint[i];
- if( pConstraint->usable ) {
- if( pConstraint->iColumn==-1 &&
- pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
- pInfo->idxNum = QUERY_ROWID; /* lookup by rowid */
- TRACE(("FTS2 QUERY_ROWID\n"));
- } else if( pConstraint->iColumn>=0 &&
- pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
- /* full-text search */
- pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn;
- TRACE(("FTS2 QUERY_FULLTEXT %d\n", pConstraint->iColumn));
- } else continue;
-
- pInfo->aConstraintUsage[i].argvIndex = 1;
- pInfo->aConstraintUsage[i].omit = 1;
-
- /* An arbitrary value for now.
- * TODO: Perhaps rowid matches should be considered cheaper than
- * full-text searches. */
- pInfo->estimatedCost = 1.0;
-
- return SQLITE_OK;
- }
- }
- pInfo->idxNum = QUERY_GENERIC;
- return SQLITE_OK;
-}
-
-static int fulltextDisconnect(sqlite3_vtab *pVTab){
- TRACE(("FTS2 Disconnect %p\n", pVTab));
- fulltext_vtab_destroy((fulltext_vtab *)pVTab);
- return SQLITE_OK;
-}
-
-static int fulltextDestroy(sqlite3_vtab *pVTab){
- fulltext_vtab *v = (fulltext_vtab *)pVTab;
- int rc;
-
- TRACE(("FTS2 Destroy %p\n", pVTab));
- rc = sql_exec(v->db, v->zDb, v->zName,
- "drop table if exists %_content;"
- "drop table if exists %_segments;"
- "drop table if exists %_segdir;"
- );
- if( rc!=SQLITE_OK ) return rc;
-
- fulltext_vtab_destroy((fulltext_vtab *)pVTab);
- return SQLITE_OK;
-}
-
-static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- fulltext_cursor *c;
-
- c = (fulltext_cursor *) sqlite3_malloc(sizeof(fulltext_cursor));
- if( c ){
- memset(c, 0, sizeof(fulltext_cursor));
- /* sqlite will initialize c->base */
- *ppCursor = &c->base;
- TRACE(("FTS2 Open %p: %p\n", pVTab, c));
- return SQLITE_OK;
- }else{
- return SQLITE_NOMEM;
- }
-}
-
-
-/* Free all of the dynamically allocated memory held by *q
-*/
-static void queryClear(Query *q){
- int i;
- for(i = 0; i < q->nTerms; ++i){
- sqlite3_free(q->pTerms[i].pTerm);
- }
- sqlite3_free(q->pTerms);
- CLEAR(q);
-}
-
-/* Free all of the dynamically allocated memory held by the
-** Snippet
-*/
-static void snippetClear(Snippet *p){
- sqlite3_free(p->aMatch);
- sqlite3_free(p->zOffset);
- sqlite3_free(p->zSnippet);
- CLEAR(p);
-}
-/*
-** Append a single entry to the p->aMatch[] log.
-*/
-static void snippetAppendMatch(
- Snippet *p, /* Append the entry to this snippet */
- int iCol, int iTerm, /* The column and query term */
- int iStart, int nByte /* Offset and size of the match */
-){
- int i;
- struct snippetMatch *pMatch;
- if( p->nMatch+1>=p->nAlloc ){
- p->nAlloc = p->nAlloc*2 + 10;
- p->aMatch = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) );
- if( p->aMatch==0 ){
- p->nMatch = 0;
- p->nAlloc = 0;
- return;
- }
- }
- i = p->nMatch++;
- pMatch = &p->aMatch[i];
- pMatch->iCol = iCol;
- pMatch->iTerm = iTerm;
- pMatch->iStart = iStart;
- pMatch->nByte = nByte;
-}
-
-/*
-** Sizing information for the circular buffer used in snippetOffsetsOfColumn()
-*/
-#define FTS2_ROTOR_SZ (32)
-#define FTS2_ROTOR_MASK (FTS2_ROTOR_SZ-1)
-
-/*
-** Add entries to pSnippet->aMatch[] for every match that occurs against
-** document zDoc[0..nDoc-1] which is stored in column iColumn.
-*/
-static void snippetOffsetsOfColumn(
- Query *pQuery,
- Snippet *pSnippet,
- int iColumn,
- const char *zDoc,
- int nDoc
-){
- const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */
- sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */
- sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */
- fulltext_vtab *pVtab; /* The full text index */
- int nColumn; /* Number of columns in the index */
- const QueryTerm *aTerm; /* Query string terms */
- int nTerm; /* Number of query string terms */
- int i, j; /* Loop counters */
- int rc; /* Return code */
- unsigned int match, prevMatch; /* Phrase search bitmasks */
- const char *zToken; /* Next token from the tokenizer */
- int nToken; /* Size of zToken */
- int iBegin, iEnd, iPos; /* Offsets of beginning and end */
-
- /* The following variables keep a circular buffer of the last
- ** few tokens */
- unsigned int iRotor = 0; /* Index of current token */
- int iRotorBegin[FTS2_ROTOR_SZ]; /* Beginning offset of token */
- int iRotorLen[FTS2_ROTOR_SZ]; /* Length of token */
-
- pVtab = pQuery->pFts;
- nColumn = pVtab->nColumn;
- pTokenizer = pVtab->pTokenizer;
- pTModule = pTokenizer->pModule;
- rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor);
- if( rc ) return;
- pTCursor->pTokenizer = pTokenizer;
- aTerm = pQuery->pTerms;
- nTerm = pQuery->nTerms;
- if( nTerm>=FTS2_ROTOR_SZ ){
- nTerm = FTS2_ROTOR_SZ - 1;
- }
- prevMatch = 0;
- while(1){
- rc = pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
- if( rc ) break;
- iRotorBegin[iRotor&FTS2_ROTOR_MASK] = iBegin;
- iRotorLen[iRotor&FTS2_ROTOR_MASK] = iEnd-iBegin;
- match = 0;
- for(i=0; i<nTerm; i++){
- int iCol;
- iCol = aTerm[i].iColumn;
- if( iCol>=0 && iCol<nColumn && iCol!=iColumn ) continue;
- if( aTerm[i].nTerm>nToken ) continue;
- if( !aTerm[i].isPrefix && aTerm[i].nTerm<nToken ) continue;
- assert( aTerm[i].nTerm<=nToken );
- if( memcmp(aTerm[i].pTerm, zToken, aTerm[i].nTerm) ) continue;
- if( aTerm[i].iPhrase>1 && (prevMatch & (1<<i))==0 ) continue;
- match |= 1<<i;
- if( i==nTerm-1 || aTerm[i+1].iPhrase==1 ){
- for(j=aTerm[i].iPhrase-1; j>=0; j--){
- int k = (iRotor-j) & FTS2_ROTOR_MASK;
- snippetAppendMatch(pSnippet, iColumn, i-j,
- iRotorBegin[k], iRotorLen[k]);
- }
- }
- }
- prevMatch = match<<1;
- iRotor++;
- }
- pTModule->xClose(pTCursor);
-}
-
-
-/*
-** Compute all offsets for the current row of the query.
-** If the offsets have already been computed, this routine is a no-op.
-*/
-static void snippetAllOffsets(fulltext_cursor *p){
- int nColumn;
- int iColumn, i;
- int iFirst, iLast;
- fulltext_vtab *pFts;
-
- if( p->snippet.nMatch ) return;
- if( p->q.nTerms==0 ) return;
- pFts = p->q.pFts;
- nColumn = pFts->nColumn;
- iColumn = (p->iCursorType - QUERY_FULLTEXT);
- if( iColumn<0 || iColumn>=nColumn ){
- iFirst = 0;
- iLast = nColumn-1;
- }else{
- iFirst = iColumn;
- iLast = iColumn;
- }
- for(i=iFirst; i<=iLast; i++){
- const char *zDoc;
- int nDoc;
- zDoc = (const char*)sqlite3_column_text(p->pStmt, i+1);
- nDoc = sqlite3_column_bytes(p->pStmt, i+1);
- snippetOffsetsOfColumn(&p->q, &p->snippet, i, zDoc, nDoc);
- }
-}
-
-/*
-** Convert the information in the aMatch[] array of the snippet
-** into the string zOffset[0..nOffset-1].
-*/
-static void snippetOffsetText(Snippet *p){
- int i;
- int cnt = 0;
- StringBuffer sb;
- char zBuf[200];
- if( p->zOffset ) return;
- initStringBuffer(&sb);
- for(i=0; i<p->nMatch; i++){
- struct snippetMatch *pMatch = &p->aMatch[i];
- zBuf[0] = ' ';
- sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d",
- pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte);
- append(&sb, zBuf);
- cnt++;
- }
- p->zOffset = stringBufferData(&sb);
- p->nOffset = stringBufferLength(&sb);
-}
-
-/*
-** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set
-** of matching words some of which might be in zDoc. zDoc is column
-** number iCol.
-**
-** iBreak is suggested spot in zDoc where we could begin or end an
-** excerpt. Return a value similar to iBreak but possibly adjusted
-** to be a little left or right so that the break point is better.
-*/
-static int wordBoundary(
- int iBreak, /* The suggested break point */
- const char *zDoc, /* Document text */
- int nDoc, /* Number of bytes in zDoc[] */
- struct snippetMatch *aMatch, /* Matching words */
- int nMatch, /* Number of entries in aMatch[] */
- int iCol /* The column number for zDoc[] */
-){
- int i;
- if( iBreak<=10 ){
- return 0;
- }
- if( iBreak>=nDoc-10 ){
- return nDoc;
- }
- for(i=0; i<nMatch && aMatch[i].iCol<iCol; i++){}
- while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; }
- if( i<nMatch ){
- if( aMatch[i].iStart<iBreak+10 ){
- return aMatch[i].iStart;
- }
- if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){
- return aMatch[i-1].iStart;
- }
- }
- for(i=1; i<=10; i++){
- if( safe_isspace(zDoc[iBreak-i]) ){
- return iBreak - i + 1;
- }
- if( safe_isspace(zDoc[iBreak+i]) ){
- return iBreak + i + 1;
- }
- }
- return iBreak;
-}
-
-
-
-/*
-** Allowed values for Snippet.aMatch[].snStatus
-*/
-#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */
-#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */
-
-/*
-** Generate the text of a snippet.
-*/
-static void snippetText(
- fulltext_cursor *pCursor, /* The cursor we need the snippet for */
- const char *zStartMark, /* Markup to appear before each match */
- const char *zEndMark, /* Markup to appear after each match */
- const char *zEllipsis /* Ellipsis mark */
-){
- int i, j;
- struct snippetMatch *aMatch;
- int nMatch;
- int nDesired;
- StringBuffer sb;
- int tailCol;
- int tailOffset;
- int iCol;
- int nDoc;
- const char *zDoc;
- int iStart, iEnd;
- int tailEllipsis = 0;
- int iMatch;
-
-
- sqlite3_free(pCursor->snippet.zSnippet);
- pCursor->snippet.zSnippet = 0;
- aMatch = pCursor->snippet.aMatch;
- nMatch = pCursor->snippet.nMatch;
- initStringBuffer(&sb);
-
- for(i=0; i<nMatch; i++){
- aMatch[i].snStatus = SNIPPET_IGNORE;
- }
- nDesired = 0;
- for(i=0; i<pCursor->q.nTerms; i++){
- for(j=0; j<nMatch; j++){
- if( aMatch[j].iTerm==i ){
- aMatch[j].snStatus = SNIPPET_DESIRED;
- nDesired++;
- break;
- }
- }
- }
-
- iMatch = 0;
- tailCol = -1;
- tailOffset = 0;
- for(i=0; i<nMatch && nDesired>0; i++){
- if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue;
- nDesired--;
- iCol = aMatch[i].iCol;
- zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1);
- nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1);
- iStart = aMatch[i].iStart - 40;
- iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol);
- if( iStart<=10 ){
- iStart = 0;
- }
- if( iCol==tailCol && iStart<=tailOffset+20 ){
- iStart = tailOffset;
- }
- if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){
- trimWhiteSpace(&sb);
- appendWhiteSpace(&sb);
- append(&sb, zEllipsis);
- appendWhiteSpace(&sb);
- }
- iEnd = aMatch[i].iStart + aMatch[i].nByte + 40;
- iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol);
- if( iEnd>=nDoc-10 ){
- iEnd = nDoc;
- tailEllipsis = 0;
- }else{
- tailEllipsis = 1;
- }
- while( iMatch<nMatch && aMatch[iMatch].iCol<iCol ){ iMatch++; }
- while( iStart<iEnd ){
- while( iMatch<nMatch && aMatch[iMatch].iStart<iStart
- && aMatch[iMatch].iCol<=iCol ){
- iMatch++;
- }
- if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd
- && aMatch[iMatch].iCol==iCol ){
- nappend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart);
- iStart = aMatch[iMatch].iStart;
- append(&sb, zStartMark);
- nappend(&sb, &zDoc[iStart], aMatch[iMatch].nByte);
- append(&sb, zEndMark);
- iStart += aMatch[iMatch].nByte;
- for(j=iMatch+1; j<nMatch; j++){
- if( aMatch[j].iTerm==aMatch[iMatch].iTerm
- && aMatch[j].snStatus==SNIPPET_DESIRED ){
- nDesired--;
- aMatch[j].snStatus = SNIPPET_IGNORE;
- }
- }
- }else{
- nappend(&sb, &zDoc[iStart], iEnd - iStart);
- iStart = iEnd;
- }
- }
- tailCol = iCol;
- tailOffset = iEnd;
- }
- trimWhiteSpace(&sb);
- if( tailEllipsis ){
- appendWhiteSpace(&sb);
- append(&sb, zEllipsis);
- }
- pCursor->snippet.zSnippet = stringBufferData(&sb);
- pCursor->snippet.nSnippet = stringBufferLength(&sb);
-}
-
-
-/*
-** Close the cursor. For additional information see the documentation
-** on the xClose method of the virtual table interface.
-*/
-static int fulltextClose(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- TRACE(("FTS2 Close %p\n", c));
- sqlite3_finalize(c->pStmt);
- queryClear(&c->q);
- snippetClear(&c->snippet);
- if( c->result.nData!=0 ) dlrDestroy(&c->reader);
- dataBufferDestroy(&c->result);
- sqlite3_free(c);
- return SQLITE_OK;
-}
-
-static int fulltextNext(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- int rc;
-
- TRACE(("FTS2 Next %p\n", pCursor));
- snippetClear(&c->snippet);
- if( c->iCursorType < QUERY_FULLTEXT ){
- /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
- rc = sqlite3_step(c->pStmt);
- switch( rc ){
- case SQLITE_ROW:
- c->eof = 0;
- return SQLITE_OK;
- case SQLITE_DONE:
- c->eof = 1;
- return SQLITE_OK;
- default:
- c->eof = 1;
- return rc;
- }
- } else { /* full-text query */
- rc = sqlite3_reset(c->pStmt);
- if( rc!=SQLITE_OK ) return rc;
-
- if( c->result.nData==0 || dlrAtEnd(&c->reader) ){
- c->eof = 1;
- return SQLITE_OK;
- }
- rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader));
- dlrStep(&c->reader);
- if( rc!=SQLITE_OK ) return rc;
- /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
- rc = sqlite3_step(c->pStmt);
- if( rc==SQLITE_ROW ){ /* the case we expect */
- c->eof = 0;
- return SQLITE_OK;
- }
- /* an error occurred; abort */
- return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
- }
-}
-
-
-/* TODO(shess) If we pushed LeafReader to the top of the file, or to
-** another file, term_select() could be pushed above
-** docListOfTerm().
-*/
-static int termSelect(fulltext_vtab *v, int iColumn,
- const char *pTerm, int nTerm, int isPrefix,
- DocListType iType, DataBuffer *out);
-
-/* Return a DocList corresponding to the query term *pTerm. If *pTerm
-** is the first term of a phrase query, go ahead and evaluate the phrase
-** query and return the doclist for the entire phrase query.
-**
-** The resulting DL_DOCIDS doclist is stored in pResult, which is
-** overwritten.
-*/
-static int docListOfTerm(
- fulltext_vtab *v, /* The full text index */
- int iColumn, /* column to restrict to. No restriction if >=nColumn */
- QueryTerm *pQTerm, /* Term we are looking for, or 1st term of a phrase */
- DataBuffer *pResult /* Write the result here */
-){
- DataBuffer left, right, new;
- int i, rc;
-
- /* No phrase search if no position info. */
- assert( pQTerm->nPhrase==0 || DL_DEFAULT!=DL_DOCIDS );
-
- /* This code should never be called with buffered updates. */
- assert( v->nPendingData<0 );
-
- dataBufferInit(&left, 0);
- rc = termSelect(v, iColumn, pQTerm->pTerm, pQTerm->nTerm, pQTerm->isPrefix,
- 0<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &left);
- if( rc ) return rc;
- for(i=1; i<=pQTerm->nPhrase && left.nData>0; i++){
- dataBufferInit(&right, 0);
- rc = termSelect(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm,
- pQTerm[i].isPrefix, DL_POSITIONS, &right);
- if( rc ){
- dataBufferDestroy(&left);
- return rc;
- }
- dataBufferInit(&new, 0);
- docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
- i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new);
- dataBufferDestroy(&left);
- dataBufferDestroy(&right);
- left = new;
- }
- *pResult = left;
- return SQLITE_OK;
-}
-
-/* Add a new term pTerm[0..nTerm-1] to the query *q.
-*/
-static void queryAdd(Query *q, const char *pTerm, int nTerm){
- QueryTerm *t;
- ++q->nTerms;
- q->pTerms = sqlite3_realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0]));
- if( q->pTerms==0 ){
- q->nTerms = 0;
- return;
- }
- t = &q->pTerms[q->nTerms - 1];
- CLEAR(t);
- t->pTerm = sqlite3_malloc(nTerm+1);
- memcpy(t->pTerm, pTerm, nTerm);
- t->pTerm[nTerm] = 0;
- t->nTerm = nTerm;
- t->isOr = q->nextIsOr;
- t->isPrefix = 0;
- q->nextIsOr = 0;
- t->iColumn = q->nextColumn;
- q->nextColumn = q->dfltColumn;
-}
-
-/*
-** Check to see if the string zToken[0...nToken-1] matches any
-** column name in the virtual table. If it does,
-** return the zero-indexed column number. If not, return -1.
-*/
-static int checkColumnSpecifier(
- fulltext_vtab *pVtab, /* The virtual table */
- const char *zToken, /* Text of the token */
- int nToken /* Number of characters in the token */
-){
- int i;
- for(i=0; i<pVtab->nColumn; i++){
- if( memcmp(pVtab->azColumn[i], zToken, nToken)==0
- && pVtab->azColumn[i][nToken]==0 ){
- return i;
- }
- }
- return -1;
-}
-
-/*
-** Parse the text at pSegment[0..nSegment-1]. Add additional terms
-** to the query being assemblied in pQuery.
-**
-** inPhrase is true if pSegment[0..nSegement-1] is contained within
-** double-quotes. If inPhrase is true, then the first term
-** is marked with the number of terms in the phrase less one and
-** OR and "-" syntax is ignored. If inPhrase is false, then every
-** term found is marked with nPhrase=0 and OR and "-" syntax is significant.
-*/
-static int tokenizeSegment(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */
- const char *pSegment, int nSegment, /* Query expression being parsed */
- int inPhrase, /* True if within "..." */
- Query *pQuery /* Append results here */
-){
- const sqlite3_tokenizer_module *pModule = pTokenizer->pModule;
- sqlite3_tokenizer_cursor *pCursor;
- int firstIndex = pQuery->nTerms;
- int iCol;
- int nTerm = 1;
-
- int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
- if( rc!=SQLITE_OK ) return rc;
- pCursor->pTokenizer = pTokenizer;
-
- while( 1 ){
- const char *pToken;
- int nToken, iBegin, iEnd, iPos;
-
- rc = pModule->xNext(pCursor,
- &pToken, &nToken,
- &iBegin, &iEnd, &iPos);
- if( rc!=SQLITE_OK ) break;
- if( !inPhrase &&
- pSegment[iEnd]==':' &&
- (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){
- pQuery->nextColumn = iCol;
- continue;
- }
- if( !inPhrase && pQuery->nTerms>0 && nToken==2
- && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){
- pQuery->nextIsOr = 1;
- continue;
- }
- queryAdd(pQuery, pToken, nToken);
- if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
- pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
- }
- if( iEnd<nSegment && pSegment[iEnd]=='*' ){
- pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1;
- }
- pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm;
- if( inPhrase ){
- nTerm++;
- }
- }
-
- if( inPhrase && pQuery->nTerms>firstIndex ){
- pQuery->pTerms[firstIndex].nPhrase = pQuery->nTerms - firstIndex - 1;
- }
-
- return pModule->xClose(pCursor);
-}
-
-/* Parse a query string, yielding a Query object pQuery.
-**
-** The calling function will need to queryClear() to clean up
-** the dynamically allocated memory held by pQuery.
-*/
-static int parseQuery(
- fulltext_vtab *v, /* The fulltext index */
- const char *zInput, /* Input text of the query string */
- int nInput, /* Size of the input text */
- int dfltColumn, /* Default column of the index to match against */
- Query *pQuery /* Write the parse results here. */
-){
- int iInput, inPhrase = 0;
-
- if( zInput==0 ) nInput = 0;
- if( nInput<0 ) nInput = strlen(zInput);
- pQuery->nTerms = 0;
- pQuery->pTerms = NULL;
- pQuery->nextIsOr = 0;
- pQuery->nextColumn = dfltColumn;
- pQuery->dfltColumn = dfltColumn;
- pQuery->pFts = v;
-
- for(iInput=0; iInput<nInput; ++iInput){
- int i;
- for(i=iInput; i<nInput && zInput[i]!='"'; ++i){}
- if( i>iInput ){
- tokenizeSegment(v->pTokenizer, zInput+iInput, i-iInput, inPhrase,
- pQuery);
- }
- iInput = i;
- if( i<nInput ){
- assert( zInput[i]=='"' );
- inPhrase = !inPhrase;
- }
- }
-
- if( inPhrase ){
- /* unmatched quote */
- queryClear(pQuery);
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-
-/* TODO(shess) Refactor the code to remove this forward decl. */
-static int flushPendingTerms(fulltext_vtab *v);
-
-/* Perform a full-text query using the search expression in
-** zInput[0..nInput-1]. Return a list of matching documents
-** in pResult.
-**
-** Queries must match column iColumn. Or if iColumn>=nColumn
-** they are allowed to match against any column.
-*/
-static int fulltextQuery(
- fulltext_vtab *v, /* The full text index */
- int iColumn, /* Match against this column by default */
- const char *zInput, /* The query string */
- int nInput, /* Number of bytes in zInput[] */
- DataBuffer *pResult, /* Write the result doclist here */
- Query *pQuery /* Put parsed query string here */
-){
- int i, iNext, rc;
- DataBuffer left, right, or, new;
- int nNot = 0;
- QueryTerm *aTerm;
-
- /* TODO(shess) Instead of flushing pendingTerms, we could query for
- ** the relevant term and merge the doclist into what we receive from
- ** the database. Wait and see if this is a common issue, first.
- **
- ** A good reason not to flush is to not generate update-related
- ** error codes from here.
- */
-
- /* Flush any buffered updates before executing the query. */
- rc = flushPendingTerms(v);
- if( rc!=SQLITE_OK ) return rc;
-
- /* TODO(shess) I think that the queryClear() calls below are not
- ** necessary, because fulltextClose() already clears the query.
- */
- rc = parseQuery(v, zInput, nInput, iColumn, pQuery);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Empty or NULL queries return no results. */
- if( pQuery->nTerms==0 ){
- dataBufferInit(pResult, 0);
- return SQLITE_OK;
- }
-
- /* Merge AND terms. */
- /* TODO(shess) I think we can early-exit if( i>nNot && left.nData==0 ). */
- aTerm = pQuery->pTerms;
- for(i = 0; i<pQuery->nTerms; i=iNext){
- if( aTerm[i].isNot ){
- /* Handle all NOT terms in a separate pass */
- nNot++;
- iNext = i + aTerm[i].nPhrase+1;
- continue;
- }
- iNext = i + aTerm[i].nPhrase + 1;
- rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right);
- if( rc ){
- if( i!=nNot ) dataBufferDestroy(&left);
- queryClear(pQuery);
- return rc;
- }
- while( iNext<pQuery->nTerms && aTerm[iNext].isOr ){
- rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &or);
- iNext += aTerm[iNext].nPhrase + 1;
- if( rc ){
- if( i!=nNot ) dataBufferDestroy(&left);
- dataBufferDestroy(&right);
- queryClear(pQuery);
- return rc;
- }
- dataBufferInit(&new, 0);
- docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
- dataBufferDestroy(&right);
- dataBufferDestroy(&or);
- right = new;
- }
- if( i==nNot ){ /* first term processed. */
- left = right;
- }else{
- dataBufferInit(&new, 0);
- docListAndMerge(left.pData, left.nData, right.pData, right.nData, &new);
- dataBufferDestroy(&right);
- dataBufferDestroy(&left);
- left = new;
- }
- }
-
- if( nNot==pQuery->nTerms ){
- /* We do not yet know how to handle a query of only NOT terms */
- return SQLITE_ERROR;
- }
-
- /* Do the EXCEPT terms */
- for(i=0; i<pQuery->nTerms; i += aTerm[i].nPhrase + 1){
- if( !aTerm[i].isNot ) continue;
- rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right);
- if( rc ){
- queryClear(pQuery);
- dataBufferDestroy(&left);
- return rc;
- }
- dataBufferInit(&new, 0);
- docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new);
- dataBufferDestroy(&right);
- dataBufferDestroy(&left);
- left = new;
- }
-
- *pResult = left;
- return rc;
-}
-
-/*
-** This is the xFilter interface for the virtual table. See
-** the virtual table xFilter method documentation for additional
-** information.
-**
-** If idxNum==QUERY_GENERIC then do a full table scan against
-** the %_content table.
-**
-** If idxNum==QUERY_ROWID then do a rowid lookup for a single entry
-** in the %_content table.
-**
-** If idxNum>=QUERY_FULLTEXT then use the full text index. The
-** column on the left-hand side of the MATCH operator is column
-** number idxNum-QUERY_FULLTEXT, 0 indexed. argv[0] is the right-hand
-** side of the MATCH operator.
-*/
-/* TODO(shess) Upgrade the cursor initialization and destruction to
-** account for fulltextFilter() being called multiple times on the
-** same cursor. The current solution is very fragile. Apply fix to
-** fts2 as appropriate.
-*/
-static int fulltextFilter(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, const char *idxStr, /* Which indexing scheme to use */
- int argc, sqlite3_value **argv /* Arguments for the indexing scheme */
-){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- fulltext_vtab *v = cursor_vtab(c);
- int rc;
-
- TRACE(("FTS2 Filter %p\n",pCursor));
-
- /* If the cursor has a statement that was not prepared according to
- ** idxNum, clear it. I believe all calls to fulltextFilter with a
- ** given cursor will have the same idxNum , but in this case it's
- ** easy to be safe.
- */
- if( c->pStmt && c->iCursorType!=idxNum ){
- sqlite3_finalize(c->pStmt);
- c->pStmt = NULL;
- }
-
- /* Get a fresh statement appropriate to idxNum. */
- /* TODO(shess): Add a prepared-statement cache in the vt structure.
- ** The cache must handle multiple open cursors. Easier to cache the
- ** statement variants at the vt to reduce malloc/realloc/free here.
- ** Or we could have a StringBuffer variant which allowed stack
- ** construction for small values.
- */
- if( !c->pStmt ){
- char *zSql = sqlite3_mprintf("select rowid, * from %%_content %s",
- idxNum==QUERY_GENERIC ? "" : "where rowid=?");
- rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, zSql);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK ) return rc;
- c->iCursorType = idxNum;
- }else{
- sqlite3_reset(c->pStmt);
- assert( c->iCursorType==idxNum );
- }
-
- switch( idxNum ){
- case QUERY_GENERIC:
- break;
-
- case QUERY_ROWID:
- rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0]));
- if( rc!=SQLITE_OK ) return rc;
- break;
-
- default: /* full-text search */
- {
- const char *zQuery = (const char *)sqlite3_value_text(argv[0]);
- assert( idxNum<=QUERY_FULLTEXT+v->nColumn);
- assert( argc==1 );
- queryClear(&c->q);
- if( c->result.nData!=0 ){
- /* This case happens if the same cursor is used repeatedly. */
- dlrDestroy(&c->reader);
- dataBufferReset(&c->result);
- }else{
- dataBufferInit(&c->result, 0);
- }
- rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q);
- if( rc!=SQLITE_OK ) return rc;
- if( c->result.nData!=0 ){
- dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
- }
- break;
- }
- }
-
- return fulltextNext(pCursor);
-}
-
-/* This is the xEof method of the virtual table. The SQLite core
-** calls this routine to find out if it has reached the end of
-** a query's results set.
-*/
-static int fulltextEof(sqlite3_vtab_cursor *pCursor){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- return c->eof;
-}
-
-/* This is the xColumn method of the virtual table. The SQLite
-** core calls this method during a query when it needs the value
-** of a column from the virtual table. This method needs to use
-** one of the sqlite3_result_*() routines to store the requested
-** value back in the pContext.
-*/
-static int fulltextColumn(sqlite3_vtab_cursor *pCursor,
- sqlite3_context *pContext, int idxCol){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
- fulltext_vtab *v = cursor_vtab(c);
-
- if( idxCol<v->nColumn ){
- sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1);
- sqlite3_result_value(pContext, pVal);
- }else if( idxCol==v->nColumn ){
- /* The extra column whose name is the same as the table.
- ** Return a blob which is a pointer to the cursor
- */
- sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT);
- }
- return SQLITE_OK;
-}
-
-/* This is the xRowid method. The SQLite core calls this routine to
-** retrive the rowid for the current row of the result set. The
-** rowid should be written to *pRowid.
-*/
-static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- fulltext_cursor *c = (fulltext_cursor *) pCursor;
-
- *pRowid = sqlite3_column_int64(c->pStmt, 0);
- return SQLITE_OK;
-}
-
-/* Add all terms in [zText] to pendingTerms table. If [iColumn] > 0,
-** we also store positions and offsets in the hash table using that
-** column number.
-*/
-static int buildTerms(fulltext_vtab *v, sqlite_int64 iDocid,
- const char *zText, int iColumn){
- sqlite3_tokenizer *pTokenizer = v->pTokenizer;
- sqlite3_tokenizer_cursor *pCursor;
- const char *pToken;
- int nTokenBytes;
- int iStartOffset, iEndOffset, iPosition;
- int rc;
-
- rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor);
- if( rc!=SQLITE_OK ) return rc;
-
- pCursor->pTokenizer = pTokenizer;
- while( SQLITE_OK==(rc=pTokenizer->pModule->xNext(pCursor,
- &pToken, &nTokenBytes,
- &iStartOffset, &iEndOffset,
- &iPosition)) ){
- DLCollector *p;
- int nData; /* Size of doclist before our update. */
-
- /* Positions can't be negative; we use -1 as a terminator
- * internally. Token can't be NULL or empty. */
- if( iPosition<0 || pToken == NULL || nTokenBytes == 0 ){
- rc = SQLITE_ERROR;
- break;
- }
-
- p = fts2HashFind(&v->pendingTerms, pToken, nTokenBytes);
- if( p==NULL ){
- nData = 0;
- p = dlcNew(iDocid, DL_DEFAULT);
- fts2HashInsert(&v->pendingTerms, pToken, nTokenBytes, p);
-
- /* Overhead for our hash table entry, the key, and the value. */
- v->nPendingData += sizeof(struct fts2HashElem)+sizeof(*p)+nTokenBytes;
- }else{
- nData = p->b.nData;
- if( p->dlw.iPrevDocid!=iDocid ) dlcNext(p, iDocid);
- }
- if( iColumn>=0 ){
- dlcAddPos(p, iColumn, iPosition, iStartOffset, iEndOffset);
- }
-
- /* Accumulate data added by dlcNew or dlcNext, and dlcAddPos. */
- v->nPendingData += p->b.nData-nData;
- }
-
- /* TODO(shess) Check return? Should this be able to cause errors at
- ** this point? Actually, same question about sqlite3_finalize(),
- ** though one could argue that failure there means that the data is
- ** not durable. *ponder*
- */
- pTokenizer->pModule->xClose(pCursor);
- if( SQLITE_DONE == rc ) return SQLITE_OK;
- return rc;
-}
-
-/* Add doclists for all terms in [pValues] to pendingTerms table. */
-static int insertTerms(fulltext_vtab *v, sqlite_int64 iRowid,
- sqlite3_value **pValues){
- int i;
- for(i = 0; i < v->nColumn ; ++i){
- char *zText = (char*)sqlite3_value_text(pValues[i]);
- int rc = buildTerms(v, iRowid, zText, i);
- if( rc!=SQLITE_OK ) return rc;
- }
- return SQLITE_OK;
-}
-
-/* Add empty doclists for all terms in the given row's content to
-** pendingTerms.
-*/
-static int deleteTerms(fulltext_vtab *v, sqlite_int64 iRowid){
- const char **pValues;
- int i, rc;
-
- /* TODO(shess) Should we allow such tables at all? */
- if( DL_DEFAULT==DL_DOCIDS ) return SQLITE_ERROR;
-
- rc = content_select(v, iRowid, &pValues);
- if( rc!=SQLITE_OK ) return rc;
-
- for(i = 0 ; i < v->nColumn; ++i) {
- rc = buildTerms(v, iRowid, pValues[i], -1);
- if( rc!=SQLITE_OK ) break;
- }
-
- freeStringArray(v->nColumn, pValues);
- return SQLITE_OK;
-}
-
-/* TODO(shess) Refactor the code to remove this forward decl. */
-static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid);
-
-/* Insert a row into the %_content table; set *piRowid to be the ID of the
-** new row. Add doclists for terms to pendingTerms.
-*/
-static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestRowid,
- sqlite3_value **pValues, sqlite_int64 *piRowid){
- int rc;
-
- rc = content_insert(v, pRequestRowid, pValues); /* execute an SQL INSERT */
- if( rc!=SQLITE_OK ) return rc;
-
- *piRowid = sqlite3_last_insert_rowid(v->db);
- rc = initPendingTerms(v, *piRowid);
- if( rc!=SQLITE_OK ) return rc;
-
- return insertTerms(v, *piRowid, pValues);
-}
-
-/* Delete a row from the %_content table; add empty doclists for terms
-** to pendingTerms.
-*/
-static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){
- int rc = initPendingTerms(v, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = deleteTerms(v, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- return content_delete(v, iRow); /* execute an SQL DELETE */
-}
-
-/* Update a row in the %_content table; add delete doclists to
-** pendingTerms for old terms not in the new data, add insert doclists
-** to pendingTerms for terms in the new data.
-*/
-static int index_update(fulltext_vtab *v, sqlite_int64 iRow,
- sqlite3_value **pValues){
- int rc = initPendingTerms(v, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Generate an empty doclist for each term that previously appeared in this
- * row. */
- rc = deleteTerms(v, iRow);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = content_update(v, pValues, iRow); /* execute an SQL UPDATE */
- if( rc!=SQLITE_OK ) return rc;
-
- /* Now add positions for terms which appear in the updated row. */
- return insertTerms(v, iRow, pValues);
-}
-
-/*******************************************************************/
-/* InteriorWriter is used to collect terms and block references into
-** interior nodes in %_segments. See commentary at top of file for
-** format.
-*/
-
-/* How large interior nodes can grow. */
-#define INTERIOR_MAX 2048
-
-/* Minimum number of terms per interior node (except the root). This
-** prevents large terms from making the tree too skinny - must be >0
-** so that the tree always makes progress. Note that the min tree
-** fanout will be INTERIOR_MIN_TERMS+1.
-*/
-#define INTERIOR_MIN_TERMS 7
-#if INTERIOR_MIN_TERMS<1
-# error INTERIOR_MIN_TERMS must be greater than 0.
-#endif
-
-/* ROOT_MAX controls how much data is stored inline in the segment
-** directory.
-*/
-/* TODO(shess) Push ROOT_MAX down to whoever is writing things. It's
-** only here so that interiorWriterRootInfo() and leafWriterRootInfo()
-** can both see it, but if the caller passed it in, we wouldn't even
-** need a define.
-*/
-#define ROOT_MAX 1024
-#if ROOT_MAX<VARINT_MAX*2
-# error ROOT_MAX must have enough space for a header.
-#endif
-
-/* InteriorBlock stores a linked-list of interior blocks while a lower
-** layer is being constructed.
-*/
-typedef struct InteriorBlock {
- DataBuffer term; /* Leftmost term in block's subtree. */
- DataBuffer data; /* Accumulated data for the block. */
- struct InteriorBlock *next;
-} InteriorBlock;
-
-static InteriorBlock *interiorBlockNew(int iHeight, sqlite_int64 iChildBlock,
- const char *pTerm, int nTerm){
- InteriorBlock *block = sqlite3_malloc(sizeof(InteriorBlock));
- char c[VARINT_MAX+VARINT_MAX];
- int n;
-
- if( block ){
- memset(block, 0, sizeof(*block));
- dataBufferInit(&block->term, 0);
- dataBufferReplace(&block->term, pTerm, nTerm);
-
- n = putVarint(c, iHeight);
- n += putVarint(c+n, iChildBlock);
- dataBufferInit(&block->data, INTERIOR_MAX);
- dataBufferReplace(&block->data, c, n);
- }
- return block;
-}
-
-#ifndef NDEBUG
-/* Verify that the data is readable as an interior node. */
-static void interiorBlockValidate(InteriorBlock *pBlock){
- const char *pData = pBlock->data.pData;
- int nData = pBlock->data.nData;
- int n, iDummy;
- sqlite_int64 iBlockid;
-
- assert( nData>0 );
- assert( pData!=0 );
- assert( pData+nData>pData );
-
- /* Must lead with height of node as a varint(n), n>0 */
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>0 );
- assert( n<nData );
- pData += n;
- nData -= n;
-
- /* Must contain iBlockid. */
- n = getVarint(pData, &iBlockid);
- assert( n>0 );
- assert( n<=nData );
- pData += n;
- nData -= n;
-
- /* Zero or more terms of positive length */
- if( nData!=0 ){
- /* First term is not delta-encoded. */
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>0 );
- assert( n+iDummy>0);
- assert( n+iDummy<=nData );
- pData += n+iDummy;
- nData -= n+iDummy;
-
- /* Following terms delta-encoded. */
- while( nData!=0 ){
- /* Length of shared prefix. */
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>=0 );
- assert( n<nData );
- pData += n;
- nData -= n;
-
- /* Length and data of distinct suffix. */
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>0 );
- assert( n+iDummy>0);
- assert( n+iDummy<=nData );
- pData += n+iDummy;
- nData -= n+iDummy;
- }
- }
-}
-#define ASSERT_VALID_INTERIOR_BLOCK(x) interiorBlockValidate(x)
-#else
-#define ASSERT_VALID_INTERIOR_BLOCK(x) assert( 1 )
-#endif
-
-typedef struct InteriorWriter {
- int iHeight; /* from 0 at leaves. */
- InteriorBlock *first, *last;
- struct InteriorWriter *parentWriter;
-
- DataBuffer term; /* Last term written to block "last". */
- sqlite_int64 iOpeningChildBlock; /* First child block in block "last". */
-#ifndef NDEBUG
- sqlite_int64 iLastChildBlock; /* for consistency checks. */
-#endif
-} InteriorWriter;
-
-/* Initialize an interior node where pTerm[nTerm] marks the leftmost
-** term in the tree. iChildBlock is the leftmost child block at the
-** next level down the tree.
-*/
-static void interiorWriterInit(int iHeight, const char *pTerm, int nTerm,
- sqlite_int64 iChildBlock,
- InteriorWriter *pWriter){
- InteriorBlock *block;
- assert( iHeight>0 );
- CLEAR(pWriter);
-
- pWriter->iHeight = iHeight;
- pWriter->iOpeningChildBlock = iChildBlock;
-#ifndef NDEBUG
- pWriter->iLastChildBlock = iChildBlock;
-#endif
- block = interiorBlockNew(iHeight, iChildBlock, pTerm, nTerm);
- pWriter->last = pWriter->first = block;
- ASSERT_VALID_INTERIOR_BLOCK(pWriter->last);
- dataBufferInit(&pWriter->term, 0);
-}
-
-/* Append the child node rooted at iChildBlock to the interior node,
-** with pTerm[nTerm] as the leftmost term in iChildBlock's subtree.
-*/
-static void interiorWriterAppend(InteriorWriter *pWriter,
- const char *pTerm, int nTerm,
- sqlite_int64 iChildBlock){
- char c[VARINT_MAX+VARINT_MAX];
- int n, nPrefix = 0;
-
- ASSERT_VALID_INTERIOR_BLOCK(pWriter->last);
-
- /* The first term written into an interior node is actually
- ** associated with the second child added (the first child was added
- ** in interiorWriterInit, or in the if clause at the bottom of this
- ** function). That term gets encoded straight up, with nPrefix left
- ** at 0.
- */
- if( pWriter->term.nData==0 ){
- n = putVarint(c, nTerm);
- }else{
- while( nPrefix<pWriter->term.nData &&
- pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){
- nPrefix++;
- }
-
- n = putVarint(c, nPrefix);
- n += putVarint(c+n, nTerm-nPrefix);
- }
-
-#ifndef NDEBUG
- pWriter->iLastChildBlock++;
-#endif
- assert( pWriter->iLastChildBlock==iChildBlock );
-
- /* Overflow to a new block if the new term makes the current block
- ** too big, and the current block already has enough terms.
- */
- if( pWriter->last->data.nData+n+nTerm-nPrefix>INTERIOR_MAX &&
- iChildBlock-pWriter->iOpeningChildBlock>INTERIOR_MIN_TERMS ){
- pWriter->last->next = interiorBlockNew(pWriter->iHeight, iChildBlock,
- pTerm, nTerm);
- pWriter->last = pWriter->last->next;
- pWriter->iOpeningChildBlock = iChildBlock;
- dataBufferReset(&pWriter->term);
- }else{
- dataBufferAppend2(&pWriter->last->data, c, n,
- pTerm+nPrefix, nTerm-nPrefix);
- dataBufferReplace(&pWriter->term, pTerm, nTerm);
- }
- ASSERT_VALID_INTERIOR_BLOCK(pWriter->last);
-}
-
-/* Free the space used by pWriter, including the linked-list of
-** InteriorBlocks, and parentWriter, if present.
-*/
-static int interiorWriterDestroy(InteriorWriter *pWriter){
- InteriorBlock *block = pWriter->first;
-
- while( block!=NULL ){
- InteriorBlock *b = block;
- block = block->next;
- dataBufferDestroy(&b->term);
- dataBufferDestroy(&b->data);
- sqlite3_free(b);
- }
- if( pWriter->parentWriter!=NULL ){
- interiorWriterDestroy(pWriter->parentWriter);
- sqlite3_free(pWriter->parentWriter);
- }
- dataBufferDestroy(&pWriter->term);
- SCRAMBLE(pWriter);
- return SQLITE_OK;
-}
-
-/* If pWriter can fit entirely in ROOT_MAX, return it as the root info
-** directly, leaving *piEndBlockid unchanged. Otherwise, flush
-** pWriter to %_segments, building a new layer of interior nodes, and
-** recursively ask for their root into.
-*/
-static int interiorWriterRootInfo(fulltext_vtab *v, InteriorWriter *pWriter,
- char **ppRootInfo, int *pnRootInfo,
- sqlite_int64 *piEndBlockid){
- InteriorBlock *block = pWriter->first;
- sqlite_int64 iBlockid = 0;
- int rc;
-
- /* If we can fit the segment inline */
- if( block==pWriter->last && block->data.nData<ROOT_MAX ){
- *ppRootInfo = block->data.pData;
- *pnRootInfo = block->data.nData;
- return SQLITE_OK;
- }
-
- /* Flush the first block to %_segments, and create a new level of
- ** interior node.
- */
- ASSERT_VALID_INTERIOR_BLOCK(block);
- rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid);
- if( rc!=SQLITE_OK ) return rc;
- *piEndBlockid = iBlockid;
-
- pWriter->parentWriter = sqlite3_malloc(sizeof(*pWriter->parentWriter));
- interiorWriterInit(pWriter->iHeight+1,
- block->term.pData, block->term.nData,
- iBlockid, pWriter->parentWriter);
-
- /* Flush additional blocks and append to the higher interior
- ** node.
- */
- for(block=block->next; block!=NULL; block=block->next){
- ASSERT_VALID_INTERIOR_BLOCK(block);
- rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid);
- if( rc!=SQLITE_OK ) return rc;
- *piEndBlockid = iBlockid;
-
- interiorWriterAppend(pWriter->parentWriter,
- block->term.pData, block->term.nData, iBlockid);
- }
-
- /* Parent node gets the chance to be the root. */
- return interiorWriterRootInfo(v, pWriter->parentWriter,
- ppRootInfo, pnRootInfo, piEndBlockid);
-}
-
-/****************************************************************/
-/* InteriorReader is used to read off the data from an interior node
-** (see comment at top of file for the format).
-*/
-typedef struct InteriorReader {
- const char *pData;
- int nData;
-
- DataBuffer term; /* previous term, for decoding term delta. */
-
- sqlite_int64 iBlockid;
-} InteriorReader;
-
-static void interiorReaderDestroy(InteriorReader *pReader){
- dataBufferDestroy(&pReader->term);
- SCRAMBLE(pReader);
-}
-
-/* TODO(shess) The assertions are great, but what if we're in NDEBUG
-** and the blob is empty or otherwise contains suspect data?
-*/
-static void interiorReaderInit(const char *pData, int nData,
- InteriorReader *pReader){
- int n, nTerm;
-
- /* Require at least the leading flag byte */
- assert( nData>0 );
- assert( pData[0]!='\0' );
-
- CLEAR(pReader);
-
- /* Decode the base blockid, and set the cursor to the first term. */
- n = getVarint(pData+1, &pReader->iBlockid);
- assert( 1+n<=nData );
- pReader->pData = pData+1+n;
- pReader->nData = nData-(1+n);
-
- /* A single-child interior node (such as when a leaf node was too
- ** large for the segment directory) won't have any terms.
- ** Otherwise, decode the first term.
- */
- if( pReader->nData==0 ){
- dataBufferInit(&pReader->term, 0);
- }else{
- n = getVarint32(pReader->pData, &nTerm);
- dataBufferInit(&pReader->term, nTerm);
- dataBufferReplace(&pReader->term, pReader->pData+n, nTerm);
- assert( n+nTerm<=pReader->nData );
- pReader->pData += n+nTerm;
- pReader->nData -= n+nTerm;
- }
-}
-
-static int interiorReaderAtEnd(InteriorReader *pReader){
- return pReader->term.nData==0;
-}
-
-static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){
- return pReader->iBlockid;
-}
-
-static int interiorReaderTermBytes(InteriorReader *pReader){
- assert( !interiorReaderAtEnd(pReader) );
- return pReader->term.nData;
-}
-static const char *interiorReaderTerm(InteriorReader *pReader){
- assert( !interiorReaderAtEnd(pReader) );
- return pReader->term.pData;
-}
-
-/* Step forward to the next term in the node. */
-static void interiorReaderStep(InteriorReader *pReader){
- assert( !interiorReaderAtEnd(pReader) );
-
- /* If the last term has been read, signal eof, else construct the
- ** next term.
- */
- if( pReader->nData==0 ){
- dataBufferReset(&pReader->term);
- }else{
- int n, nPrefix, nSuffix;
-
- n = getVarint32(pReader->pData, &nPrefix);
- n += getVarint32(pReader->pData+n, &nSuffix);
-
- /* Truncate the current term and append suffix data. */
- pReader->term.nData = nPrefix;
- dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);
-
- assert( n+nSuffix<=pReader->nData );
- pReader->pData += n+nSuffix;
- pReader->nData -= n+nSuffix;
- }
- pReader->iBlockid++;
-}
-
-/* Compare the current term to pTerm[nTerm], returning strcmp-style
-** results. If isPrefix, equality means equal through nTerm bytes.
-*/
-static int interiorReaderTermCmp(InteriorReader *pReader,
- const char *pTerm, int nTerm, int isPrefix){
- const char *pReaderTerm = interiorReaderTerm(pReader);
- int nReaderTerm = interiorReaderTermBytes(pReader);
- int c, n = nReaderTerm<nTerm ? nReaderTerm : nTerm;
-
- if( n==0 ){
- if( nReaderTerm>0 ) return -1;
- if( nTerm>0 ) return 1;
- return 0;
- }
-
- c = memcmp(pReaderTerm, pTerm, n);
- if( c!=0 ) return c;
- if( isPrefix && n==nTerm ) return 0;
- return nReaderTerm - nTerm;
-}
-
-/****************************************************************/
-/* LeafWriter is used to collect terms and associated doclist data
-** into leaf blocks in %_segments (see top of file for format info).
-** Expected usage is:
-**
-** LeafWriter writer;
-** leafWriterInit(0, 0, &writer);
-** while( sorted_terms_left_to_process ){
-** // data is doclist data for that term.
-** rc = leafWriterStep(v, &writer, pTerm, nTerm, pData, nData);
-** if( rc!=SQLITE_OK ) goto err;
-** }
-** rc = leafWriterFinalize(v, &writer);
-**err:
-** leafWriterDestroy(&writer);
-** return rc;
-**
-** leafWriterStep() may write a collected leaf out to %_segments.
-** leafWriterFinalize() finishes writing any buffered data and stores
-** a root node in %_segdir. leafWriterDestroy() frees all buffers and
-** InteriorWriters allocated as part of writing this segment.
-**
-** TODO(shess) Document leafWriterStepMerge().
-*/
-
-/* Put terms with data this big in their own block. */
-#define STANDALONE_MIN 1024
-
-/* Keep leaf blocks below this size. */
-#define LEAF_MAX 2048
-
-typedef struct LeafWriter {
- int iLevel;
- int idx;
- sqlite_int64 iStartBlockid; /* needed to create the root info */
- sqlite_int64 iEndBlockid; /* when we're done writing. */
-
- DataBuffer term; /* previous encoded term */
- DataBuffer data; /* encoding buffer */
-
- /* bytes of first term in the current node which distinguishes that
- ** term from the last term of the previous node.
- */
- int nTermDistinct;
-
- InteriorWriter parentWriter; /* if we overflow */
- int has_parent;
-} LeafWriter;
-
-static void leafWriterInit(int iLevel, int idx, LeafWriter *pWriter){
- CLEAR(pWriter);
- pWriter->iLevel = iLevel;
- pWriter->idx = idx;
-
- dataBufferInit(&pWriter->term, 32);
-
- /* Start out with a reasonably sized block, though it can grow. */
- dataBufferInit(&pWriter->data, LEAF_MAX);
-}
-
-#ifndef NDEBUG
-/* Verify that the data is readable as a leaf node. */
-static void leafNodeValidate(const char *pData, int nData){
- int n, iDummy;
-
- if( nData==0 ) return;
- assert( nData>0 );
- assert( pData!=0 );
- assert( pData+nData>pData );
-
- /* Must lead with a varint(0) */
- n = getVarint32(pData, &iDummy);
- assert( iDummy==0 );
- assert( n>0 );
- assert( n<nData );
- pData += n;
- nData -= n;
-
- /* Leading term length and data must fit in buffer. */
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>0 );
- assert( n+iDummy>0 );
- assert( n+iDummy<nData );
- pData += n+iDummy;
- nData -= n+iDummy;
-
- /* Leading term's doclist length and data must fit. */
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>0 );
- assert( n+iDummy>0 );
- assert( n+iDummy<=nData );
- ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL);
- pData += n+iDummy;
- nData -= n+iDummy;
-
- /* Verify that trailing terms and doclists also are readable. */
- while( nData!=0 ){
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>=0 );
- assert( n<nData );
- pData += n;
- nData -= n;
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>0 );
- assert( n+iDummy>0 );
- assert( n+iDummy<nData );
- pData += n+iDummy;
- nData -= n+iDummy;
-
- n = getVarint32(pData, &iDummy);
- assert( n>0 );
- assert( iDummy>0 );
- assert( n+iDummy>0 );
- assert( n+iDummy<=nData );
- ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL);
- pData += n+iDummy;
- nData -= n+iDummy;
- }
-}
-#define ASSERT_VALID_LEAF_NODE(p, n) leafNodeValidate(p, n)
-#else
-#define ASSERT_VALID_LEAF_NODE(p, n) assert( 1 )
-#endif
-
-/* Flush the current leaf node to %_segments, and adding the resulting
-** blockid and the starting term to the interior node which will
-** contain it.
-*/
-static int leafWriterInternalFlush(fulltext_vtab *v, LeafWriter *pWriter,
- int iData, int nData){
- sqlite_int64 iBlockid = 0;
- const char *pStartingTerm;
- int nStartingTerm, rc, n;
-
- /* Must have the leading varint(0) flag, plus at least some
- ** valid-looking data.
- */
- assert( nData>2 );
- assert( iData>=0 );
- assert( iData+nData<=pWriter->data.nData );
- ASSERT_VALID_LEAF_NODE(pWriter->data.pData+iData, nData);
-
- rc = block_insert(v, pWriter->data.pData+iData, nData, &iBlockid);
- if( rc!=SQLITE_OK ) return rc;
- assert( iBlockid!=0 );
-
- /* Reconstruct the first term in the leaf for purposes of building
- ** the interior node.
- */
- n = getVarint32(pWriter->data.pData+iData+1, &nStartingTerm);
- pStartingTerm = pWriter->data.pData+iData+1+n;
- assert( pWriter->data.nData>iData+1+n+nStartingTerm );
- assert( pWriter->nTermDistinct>0 );
- assert( pWriter->nTermDistinct<=nStartingTerm );
- nStartingTerm = pWriter->nTermDistinct;
-
- if( pWriter->has_parent ){
- interiorWriterAppend(&pWriter->parentWriter,
- pStartingTerm, nStartingTerm, iBlockid);
- }else{
- interiorWriterInit(1, pStartingTerm, nStartingTerm, iBlockid,
- &pWriter->parentWriter);
- pWriter->has_parent = 1;
- }
-
- /* Track the span of this segment's leaf nodes. */
- if( pWriter->iEndBlockid==0 ){
- pWriter->iEndBlockid = pWriter->iStartBlockid = iBlockid;
- }else{
- pWriter->iEndBlockid++;
- assert( iBlockid==pWriter->iEndBlockid );
- }
-
- return SQLITE_OK;
-}
-static int leafWriterFlush(fulltext_vtab *v, LeafWriter *pWriter){
- int rc = leafWriterInternalFlush(v, pWriter, 0, pWriter->data.nData);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Re-initialize the output buffer. */
- dataBufferReset(&pWriter->data);
-
- return SQLITE_OK;
-}
-
-/* Fetch the root info for the segment. If the entire leaf fits
-** within ROOT_MAX, then it will be returned directly, otherwise it
-** will be flushed and the root info will be returned from the
-** interior node. *piEndBlockid is set to the blockid of the last
-** interior or leaf node written to disk (0 if none are written at
-** all).
-*/
-static int leafWriterRootInfo(fulltext_vtab *v, LeafWriter *pWriter,
- char **ppRootInfo, int *pnRootInfo,
- sqlite_int64 *piEndBlockid){
- /* we can fit the segment entirely inline */
- if( !pWriter->has_parent && pWriter->data.nData<ROOT_MAX ){
- *ppRootInfo = pWriter->data.pData;
- *pnRootInfo = pWriter->data.nData;
- *piEndBlockid = 0;
- return SQLITE_OK;
- }
-
- /* Flush remaining leaf data. */
- if( pWriter->data.nData>0 ){
- int rc = leafWriterFlush(v, pWriter);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- /* We must have flushed a leaf at some point. */
- assert( pWriter->has_parent );
-
- /* Tenatively set the end leaf blockid as the end blockid. If the
- ** interior node can be returned inline, this will be the final
- ** blockid, otherwise it will be overwritten by
- ** interiorWriterRootInfo().
- */
- *piEndBlockid = pWriter->iEndBlockid;
-
- return interiorWriterRootInfo(v, &pWriter->parentWriter,
- ppRootInfo, pnRootInfo, piEndBlockid);
-}
-
-/* Collect the rootInfo data and store it into the segment directory.
-** This has the effect of flushing the segment's leaf data to
-** %_segments, and also flushing any interior nodes to %_segments.
-*/
-static int leafWriterFinalize(fulltext_vtab *v, LeafWriter *pWriter){
- sqlite_int64 iEndBlockid;
- char *pRootInfo;
- int rc, nRootInfo;
-
- rc = leafWriterRootInfo(v, pWriter, &pRootInfo, &nRootInfo, &iEndBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Don't bother storing an entirely empty segment. */
- if( iEndBlockid==0 && nRootInfo==0 ) return SQLITE_OK;
-
- return segdir_set(v, pWriter->iLevel, pWriter->idx,
- pWriter->iStartBlockid, pWriter->iEndBlockid,
- iEndBlockid, pRootInfo, nRootInfo);
-}
-
-static void leafWriterDestroy(LeafWriter *pWriter){
- if( pWriter->has_parent ) interiorWriterDestroy(&pWriter->parentWriter);
- dataBufferDestroy(&pWriter->term);
- dataBufferDestroy(&pWriter->data);
-}
-
-/* Encode a term into the leafWriter, delta-encoding as appropriate.
-** Returns the length of the new term which distinguishes it from the
-** previous term, which can be used to set nTermDistinct when a node
-** boundary is crossed.
-*/
-static int leafWriterEncodeTerm(LeafWriter *pWriter,
- const char *pTerm, int nTerm){
- char c[VARINT_MAX+VARINT_MAX];
- int n, nPrefix = 0;
-
- assert( nTerm>0 );
- while( nPrefix<pWriter->term.nData &&
- pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){
- nPrefix++;
- /* Failing this implies that the terms weren't in order. */
- assert( nPrefix<nTerm );
- }
-
- if( pWriter->data.nData==0 ){
- /* Encode the node header and leading term as:
- ** varint(0)
- ** varint(nTerm)
- ** char pTerm[nTerm]
- */
- n = putVarint(c, '\0');
- n += putVarint(c+n, nTerm);
- dataBufferAppend2(&pWriter->data, c, n, pTerm, nTerm);
- }else{
- /* Delta-encode the term as:
- ** varint(nPrefix)
- ** varint(nSuffix)
- ** char pTermSuffix[nSuffix]
- */
- n = putVarint(c, nPrefix);
- n += putVarint(c+n, nTerm-nPrefix);
- dataBufferAppend2(&pWriter->data, c, n, pTerm+nPrefix, nTerm-nPrefix);
- }
- dataBufferReplace(&pWriter->term, pTerm, nTerm);
-
- return nPrefix+1;
-}
-
-/* Used to avoid a memmove when a large amount of doclist data is in
-** the buffer. This constructs a node and term header before
-** iDoclistData and flushes the resulting complete node using
-** leafWriterInternalFlush().
-*/
-static int leafWriterInlineFlush(fulltext_vtab *v, LeafWriter *pWriter,
- const char *pTerm, int nTerm,
- int iDoclistData){
- char c[VARINT_MAX+VARINT_MAX];
- int iData, n = putVarint(c, 0);
- n += putVarint(c+n, nTerm);
-
- /* There should always be room for the header. Even if pTerm shared
- ** a substantial prefix with the previous term, the entire prefix
- ** could be constructed from earlier data in the doclist, so there
- ** should be room.
- */
- assert( iDoclistData>=n+nTerm );
-
- iData = iDoclistData-(n+nTerm);
- memcpy(pWriter->data.pData+iData, c, n);
- memcpy(pWriter->data.pData+iData+n, pTerm, nTerm);
-
- return leafWriterInternalFlush(v, pWriter, iData, pWriter->data.nData-iData);
-}
-
-/* Push pTerm[nTerm] along with the doclist data to the leaf layer of
-** %_segments.
-*/
-static int leafWriterStepMerge(fulltext_vtab *v, LeafWriter *pWriter,
- const char *pTerm, int nTerm,
- DLReader *pReaders, int nReaders){
- char c[VARINT_MAX+VARINT_MAX];
- int iTermData = pWriter->data.nData, iDoclistData;
- int i, nData, n, nActualData, nActual, rc, nTermDistinct;
-
- ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData);
- nTermDistinct = leafWriterEncodeTerm(pWriter, pTerm, nTerm);
-
- /* Remember nTermDistinct if opening a new node. */
- if( iTermData==0 ) pWriter->nTermDistinct = nTermDistinct;
-
- iDoclistData = pWriter->data.nData;
-
- /* Estimate the length of the merged doclist so we can leave space
- ** to encode it.
- */
- for(i=0, nData=0; i<nReaders; i++){
- nData += dlrAllDataBytes(&pReaders[i]);
- }
- n = putVarint(c, nData);
- dataBufferAppend(&pWriter->data, c, n);
-
- docListMerge(&pWriter->data, pReaders, nReaders);
- ASSERT_VALID_DOCLIST(DL_DEFAULT,
- pWriter->data.pData+iDoclistData+n,
- pWriter->data.nData-iDoclistData-n, NULL);
-
- /* The actual amount of doclist data at this point could be smaller
- ** than the length we encoded. Additionally, the space required to
- ** encode this length could be smaller. For small doclists, this is
- ** not a big deal, we can just use memmove() to adjust things.
- */
- nActualData = pWriter->data.nData-(iDoclistData+n);
- nActual = putVarint(c, nActualData);
- assert( nActualData<=nData );
- assert( nActual<=n );
-
- /* If the new doclist is big enough for force a standalone leaf
- ** node, we can immediately flush it inline without doing the
- ** memmove().
- */
- /* TODO(shess) This test matches leafWriterStep(), which does this
- ** test before it knows the cost to varint-encode the term and
- ** doclist lengths. At some point, change to
- ** pWriter->data.nData-iTermData>STANDALONE_MIN.
- */
- if( nTerm+nActualData>STANDALONE_MIN ){
- /* Push leaf node from before this term. */
- if( iTermData>0 ){
- rc = leafWriterInternalFlush(v, pWriter, 0, iTermData);
- if( rc!=SQLITE_OK ) return rc;
-
- pWriter->nTermDistinct = nTermDistinct;
- }
-
- /* Fix the encoded doclist length. */
- iDoclistData += n - nActual;
- memcpy(pWriter->data.pData+iDoclistData, c, nActual);
-
- /* Push the standalone leaf node. */
- rc = leafWriterInlineFlush(v, pWriter, pTerm, nTerm, iDoclistData);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Leave the node empty. */
- dataBufferReset(&pWriter->data);
-
- return rc;
- }
-
- /* At this point, we know that the doclist was small, so do the
- ** memmove if indicated.
- */
- if( nActual<n ){
- memmove(pWriter->data.pData+iDoclistData+nActual,
- pWriter->data.pData+iDoclistData+n,
- pWriter->data.nData-(iDoclistData+n));
- pWriter->data.nData -= n-nActual;
- }
-
- /* Replace written length with actual length. */
- memcpy(pWriter->data.pData+iDoclistData, c, nActual);
-
- /* If the node is too large, break things up. */
- /* TODO(shess) This test matches leafWriterStep(), which does this
- ** test before it knows the cost to varint-encode the term and
- ** doclist lengths. At some point, change to
- ** pWriter->data.nData>LEAF_MAX.
- */
- if( iTermData+nTerm+nActualData>LEAF_MAX ){
- /* Flush out the leading data as a node */
- rc = leafWriterInternalFlush(v, pWriter, 0, iTermData);
- if( rc!=SQLITE_OK ) return rc;
-
- pWriter->nTermDistinct = nTermDistinct;
-
- /* Rebuild header using the current term */
- n = putVarint(pWriter->data.pData, 0);
- n += putVarint(pWriter->data.pData+n, nTerm);
- memcpy(pWriter->data.pData+n, pTerm, nTerm);
- n += nTerm;
-
- /* There should always be room, because the previous encoding
- ** included all data necessary to construct the term.
- */
- assert( n<iDoclistData );
- /* So long as STANDALONE_MIN is half or less of LEAF_MAX, the
- ** following memcpy() is safe (as opposed to needing a memmove).
- */
- assert( 2*STANDALONE_MIN<=LEAF_MAX );
- assert( n+pWriter->data.nData-iDoclistData<iDoclistData );
- memcpy(pWriter->data.pData+n,
- pWriter->data.pData+iDoclistData,
- pWriter->data.nData-iDoclistData);
- pWriter->data.nData -= iDoclistData-n;
- }
- ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData);
-
- return SQLITE_OK;
-}
-
-/* Push pTerm[nTerm] along with the doclist data to the leaf layer of
-** %_segments.
-*/
-/* TODO(shess) Revise writeZeroSegment() so that doclists are
-** constructed directly in pWriter->data.
-*/
-static int leafWriterStep(fulltext_vtab *v, LeafWriter *pWriter,
- const char *pTerm, int nTerm,
- const char *pData, int nData){
- int rc;
- DLReader reader;
-
- dlrInit(&reader, DL_DEFAULT, pData, nData);
- rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1);
- dlrDestroy(&reader);
-
- return rc;
-}
-
-
-/****************************************************************/
-/* LeafReader is used to iterate over an individual leaf node. */
-typedef struct LeafReader {
- DataBuffer term; /* copy of current term. */
-
- const char *pData; /* data for current term. */
- int nData;
-} LeafReader;
-
-static void leafReaderDestroy(LeafReader *pReader){
- dataBufferDestroy(&pReader->term);
- SCRAMBLE(pReader);
-}
-
-static int leafReaderAtEnd(LeafReader *pReader){
- return pReader->nData<=0;
-}
-
-/* Access the current term. */
-static int leafReaderTermBytes(LeafReader *pReader){
- return pReader->term.nData;
-}
-static const char *leafReaderTerm(LeafReader *pReader){
- assert( pReader->term.nData>0 );
- return pReader->term.pData;
-}
-
-/* Access the doclist data for the current term. */
-static int leafReaderDataBytes(LeafReader *pReader){
- int nData;
- assert( pReader->term.nData>0 );
- getVarint32(pReader->pData, &nData);
- return nData;
-}
-static const char *leafReaderData(LeafReader *pReader){
- int n, nData;
- assert( pReader->term.nData>0 );
- n = getVarint32(pReader->pData, &nData);
- return pReader->pData+n;
-}
-
-static void leafReaderInit(const char *pData, int nData,
- LeafReader *pReader){
- int nTerm, n;
-
- assert( nData>0 );
- assert( pData[0]=='\0' );
-
- CLEAR(pReader);
-
- /* Read the first term, skipping the header byte. */
- n = getVarint32(pData+1, &nTerm);
- dataBufferInit(&pReader->term, nTerm);
- dataBufferReplace(&pReader->term, pData+1+n, nTerm);
-
- /* Position after the first term. */
- assert( 1+n+nTerm<nData );
- pReader->pData = pData+1+n+nTerm;
- pReader->nData = nData-1-n-nTerm;
-}
-
-/* Step the reader forward to the next term. */
-static void leafReaderStep(LeafReader *pReader){
- int n, nData, nPrefix, nSuffix;
- assert( !leafReaderAtEnd(pReader) );
-
- /* Skip previous entry's data block. */
- n = getVarint32(pReader->pData, &nData);
- assert( n+nData<=pReader->nData );
- pReader->pData += n+nData;
- pReader->nData -= n+nData;
-
- if( !leafReaderAtEnd(pReader) ){
- /* Construct the new term using a prefix from the old term plus a
- ** suffix from the leaf data.
- */
- n = getVarint32(pReader->pData, &nPrefix);
- n += getVarint32(pReader->pData+n, &nSuffix);
- assert( n+nSuffix<pReader->nData );
- pReader->term.nData = nPrefix;
- dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);
-
- pReader->pData += n+nSuffix;
- pReader->nData -= n+nSuffix;
- }
-}
-
-/* strcmp-style comparison of pReader's current term against pTerm.
-** If isPrefix, equality means equal through nTerm bytes.
-*/
-static int leafReaderTermCmp(LeafReader *pReader,
- const char *pTerm, int nTerm, int isPrefix){
- int c, n = pReader->term.nData<nTerm ? pReader->term.nData : nTerm;
- if( n==0 ){
- if( pReader->term.nData>0 ) return -1;
- if(nTerm>0 ) return 1;
- return 0;
- }
-
- c = memcmp(pReader->term.pData, pTerm, n);
- if( c!=0 ) return c;
- if( isPrefix && n==nTerm ) return 0;
- return pReader->term.nData - nTerm;
-}
-
-
-/****************************************************************/
-/* LeavesReader wraps LeafReader to allow iterating over the entire
-** leaf layer of the tree.
-*/
-typedef struct LeavesReader {
- int idx; /* Index within the segment. */
-
- sqlite3_stmt *pStmt; /* Statement we're streaming leaves from. */
- int eof; /* we've seen SQLITE_DONE from pStmt. */
-
- LeafReader leafReader; /* reader for the current leaf. */
- DataBuffer rootData; /* root data for inline. */
-} LeavesReader;
-
-/* Access the current term. */
-static int leavesReaderTermBytes(LeavesReader *pReader){
- assert( !pReader->eof );
- return leafReaderTermBytes(&pReader->leafReader);
-}
-static const char *leavesReaderTerm(LeavesReader *pReader){
- assert( !pReader->eof );
- return leafReaderTerm(&pReader->leafReader);
-}
-
-/* Access the doclist data for the current term. */
-static int leavesReaderDataBytes(LeavesReader *pReader){
- assert( !pReader->eof );
- return leafReaderDataBytes(&pReader->leafReader);
-}
-static const char *leavesReaderData(LeavesReader *pReader){
- assert( !pReader->eof );
- return leafReaderData(&pReader->leafReader);
-}
-
-static int leavesReaderAtEnd(LeavesReader *pReader){
- return pReader->eof;
-}
-
-/* loadSegmentLeaves() may not read all the way to SQLITE_DONE, thus
-** leaving the statement handle open, which locks the table.
-*/
-/* TODO(shess) This "solution" is not satisfactory. Really, there
-** should be check-in function for all statement handles which
-** arranges to call sqlite3_reset(). This most likely will require
-** modification to control flow all over the place, though, so for now
-** just punt.
-**
-** Note the current system assumes that segment merges will run to
-** completion, which is why this particular probably hasn't arisen in
-** this case. Probably a brittle assumption.
-*/
-static int leavesReaderReset(LeavesReader *pReader){
- return sqlite3_reset(pReader->pStmt);
-}
-
-static void leavesReaderDestroy(LeavesReader *pReader){
- /* If idx is -1, that means we're using a non-cached statement
- ** handle in the optimize() case, so we need to release it.
- */
- if( pReader->pStmt!=NULL && pReader->idx==-1 ){
- sqlite3_finalize(pReader->pStmt);
- }
- leafReaderDestroy(&pReader->leafReader);
- dataBufferDestroy(&pReader->rootData);
- SCRAMBLE(pReader);
-}
-
-/* Initialize pReader with the given root data (if iStartBlockid==0
-** the leaf data was entirely contained in the root), or from the
-** stream of blocks between iStartBlockid and iEndBlockid, inclusive.
-*/
-static int leavesReaderInit(fulltext_vtab *v,
- int idx,
- sqlite_int64 iStartBlockid,
- sqlite_int64 iEndBlockid,
- const char *pRootData, int nRootData,
- LeavesReader *pReader){
- CLEAR(pReader);
- pReader->idx = idx;
-
- dataBufferInit(&pReader->rootData, 0);
- if( iStartBlockid==0 ){
- /* Entire leaf level fit in root data. */
- dataBufferReplace(&pReader->rootData, pRootData, nRootData);
- leafReaderInit(pReader->rootData.pData, pReader->rootData.nData,
- &pReader->leafReader);
- }else{
- sqlite3_stmt *s;
- int rc = sql_get_leaf_statement(v, idx, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iStartBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 2, iEndBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_step(s);
- if( rc==SQLITE_DONE ){
- pReader->eof = 1;
- return SQLITE_OK;
- }
- if( rc!=SQLITE_ROW ) return rc;
-
- pReader->pStmt = s;
- leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
- sqlite3_column_bytes(pReader->pStmt, 0),
- &pReader->leafReader);
- }
- return SQLITE_OK;
-}
-
-/* Step the current leaf forward to the next term. If we reach the
-** end of the current leaf, step forward to the next leaf block.
-*/
-static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
- assert( !leavesReaderAtEnd(pReader) );
- leafReaderStep(&pReader->leafReader);
-
- if( leafReaderAtEnd(&pReader->leafReader) ){
- int rc;
- if( pReader->rootData.pData ){
- pReader->eof = 1;
- return SQLITE_OK;
- }
- rc = sqlite3_step(pReader->pStmt);
- if( rc!=SQLITE_ROW ){
- pReader->eof = 1;
- return rc==SQLITE_DONE ? SQLITE_OK : rc;
- }
- leafReaderDestroy(&pReader->leafReader);
- leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
- sqlite3_column_bytes(pReader->pStmt, 0),
- &pReader->leafReader);
- }
- return SQLITE_OK;
-}
-
-/* Order LeavesReaders by their term, ignoring idx. Readers at eof
-** always sort to the end.
-*/
-static int leavesReaderTermCmp(LeavesReader *lr1, LeavesReader *lr2){
- if( leavesReaderAtEnd(lr1) ){
- if( leavesReaderAtEnd(lr2) ) return 0;
- return 1;
- }
- if( leavesReaderAtEnd(lr2) ) return -1;
-
- return leafReaderTermCmp(&lr1->leafReader,
- leavesReaderTerm(lr2), leavesReaderTermBytes(lr2),
- 0);
-}
-
-/* Similar to leavesReaderTermCmp(), with additional ordering by idx
-** so that older segments sort before newer segments.
-*/
-static int leavesReaderCmp(LeavesReader *lr1, LeavesReader *lr2){
- int c = leavesReaderTermCmp(lr1, lr2);
- if( c!=0 ) return c;
- return lr1->idx-lr2->idx;
-}
-
-/* Assume that pLr[1]..pLr[nLr] are sorted. Bubble pLr[0] into its
-** sorted position.
-*/
-static void leavesReaderReorder(LeavesReader *pLr, int nLr){
- while( nLr>1 && leavesReaderCmp(pLr, pLr+1)>0 ){
- LeavesReader tmp = pLr[0];
- pLr[0] = pLr[1];
- pLr[1] = tmp;
- nLr--;
- pLr++;
- }
-}
-
-/* Initializes pReaders with the segments from level iLevel, returning
-** the number of segments in *piReaders. Leaves pReaders in sorted
-** order.
-*/
-static int leavesReadersInit(fulltext_vtab *v, int iLevel,
- LeavesReader *pReaders, int *piReaders){
- sqlite3_stmt *s;
- int i, rc = sql_get_statement(v, SEGDIR_SELECT_LEVEL_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int(s, 1, iLevel);
- if( rc!=SQLITE_OK ) return rc;
-
- i = 0;
- while( (rc = sqlite3_step(s))==SQLITE_ROW ){
- sqlite_int64 iStart = sqlite3_column_int64(s, 0);
- sqlite_int64 iEnd = sqlite3_column_int64(s, 1);
- const char *pRootData = sqlite3_column_blob(s, 2);
- int nRootData = sqlite3_column_bytes(s, 2);
-
- assert( i<MERGE_COUNT );
- rc = leavesReaderInit(v, i, iStart, iEnd, pRootData, nRootData,
- &pReaders[i]);
- if( rc!=SQLITE_OK ) break;
-
- i++;
- }
- if( rc!=SQLITE_DONE ){
- while( i-->0 ){
- leavesReaderDestroy(&pReaders[i]);
- }
- return rc;
- }
-
- *piReaders = i;
-
- /* Leave our results sorted by term, then age. */
- while( i-- ){
- leavesReaderReorder(pReaders+i, *piReaders-i);
- }
- return SQLITE_OK;
-}
-
-/* Merge doclists from pReaders[nReaders] into a single doclist, which
-** is written to pWriter. Assumes pReaders is ordered oldest to
-** newest.
-*/
-/* TODO(shess) Consider putting this inline in segmentMerge(). */
-static int leavesReadersMerge(fulltext_vtab *v,
- LeavesReader *pReaders, int nReaders,
- LeafWriter *pWriter){
- DLReader dlReaders[MERGE_COUNT];
- const char *pTerm = leavesReaderTerm(pReaders);
- int i, nTerm = leavesReaderTermBytes(pReaders);
-
- assert( nReaders<=MERGE_COUNT );
-
- for(i=0; i<nReaders; i++){
- dlrInit(&dlReaders[i], DL_DEFAULT,
- leavesReaderData(pReaders+i),
- leavesReaderDataBytes(pReaders+i));
- }
-
- return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders);
-}
-
-/* Forward ref due to mutual recursion with segdirNextIndex(). */
-static int segmentMerge(fulltext_vtab *v, int iLevel);
-
-/* Put the next available index at iLevel into *pidx. If iLevel
-** already has MERGE_COUNT segments, they are merged to a higher
-** level to make room.
-*/
-static int segdirNextIndex(fulltext_vtab *v, int iLevel, int *pidx){
- int rc = segdir_max_index(v, iLevel, pidx);
- if( rc==SQLITE_DONE ){ /* No segments at iLevel. */
- *pidx = 0;
- }else if( rc==SQLITE_ROW ){
- if( *pidx==(MERGE_COUNT-1) ){
- rc = segmentMerge(v, iLevel);
- if( rc!=SQLITE_OK ) return rc;
- *pidx = 0;
- }else{
- (*pidx)++;
- }
- }else{
- return rc;
- }
- return SQLITE_OK;
-}
-
-/* Merge MERGE_COUNT segments at iLevel into a new segment at
-** iLevel+1. If iLevel+1 is already full of segments, those will be
-** merged to make room.
-*/
-static int segmentMerge(fulltext_vtab *v, int iLevel){
- LeafWriter writer;
- LeavesReader lrs[MERGE_COUNT];
- int i, rc, idx = 0;
-
- /* Determine the next available segment index at the next level,
- ** merging as necessary.
- */
- rc = segdirNextIndex(v, iLevel+1, &idx);
- if( rc!=SQLITE_OK ) return rc;
-
- /* TODO(shess) This assumes that we'll always see exactly
- ** MERGE_COUNT segments to merge at a given level. That will be
- ** broken if we allow the developer to request preemptive or
- ** deferred merging.
- */
- memset(&lrs, '\0', sizeof(lrs));
- rc = leavesReadersInit(v, iLevel, lrs, &i);
- if( rc!=SQLITE_OK ) return rc;
- assert( i==MERGE_COUNT );
-
- leafWriterInit(iLevel+1, idx, &writer);
-
- /* Since leavesReaderReorder() pushes readers at eof to the end,
- ** when the first reader is empty, all will be empty.
- */
- while( !leavesReaderAtEnd(lrs) ){
- /* Figure out how many readers share their next term. */
- for(i=1; i<MERGE_COUNT && !leavesReaderAtEnd(lrs+i); i++){
- if( 0!=leavesReaderTermCmp(lrs, lrs+i) ) break;
- }
-
- rc = leavesReadersMerge(v, lrs, i, &writer);
- if( rc!=SQLITE_OK ) goto err;
-
- /* Step forward those that were merged. */
- while( i-->0 ){
- rc = leavesReaderStep(v, lrs+i);
- if( rc!=SQLITE_OK ) goto err;
-
- /* Reorder by term, then by age. */
- leavesReaderReorder(lrs+i, MERGE_COUNT-i);
- }
- }
-
- for(i=0; i<MERGE_COUNT; i++){
- leavesReaderDestroy(&lrs[i]);
- }
-
- rc = leafWriterFinalize(v, &writer);
- leafWriterDestroy(&writer);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Delete the merged segment data. */
- return segdir_delete(v, iLevel);
-
- err:
- for(i=0; i<MERGE_COUNT; i++){
- leavesReaderDestroy(&lrs[i]);
- }
- leafWriterDestroy(&writer);
- return rc;
-}
-
-/* Accumulate the union of *acc and *pData into *acc. */
-static void docListAccumulateUnion(DataBuffer *acc,
- const char *pData, int nData) {
- DataBuffer tmp = *acc;
- dataBufferInit(acc, tmp.nData+nData);
- docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
- dataBufferDestroy(&tmp);
-}
-
-/* TODO(shess) It might be interesting to explore different merge
-** strategies, here. For instance, since this is a sorted merge, we
-** could easily merge many doclists in parallel. With some
-** comprehension of the storage format, we could merge all of the
-** doclists within a leaf node directly from the leaf node's storage.
-** It may be worthwhile to merge smaller doclists before larger
-** doclists, since they can be traversed more quickly - but the
-** results may have less overlap, making them more expensive in a
-** different way.
-*/
-
-/* Scan pReader for pTerm/nTerm, and merge the term's doclist over
-** *out (any doclists with duplicate docids overwrite those in *out).
-** Internal function for loadSegmentLeaf().
-*/
-static int loadSegmentLeavesInt(fulltext_vtab *v, LeavesReader *pReader,
- const char *pTerm, int nTerm, int isPrefix,
- DataBuffer *out){
- /* doclist data is accumulated into pBuffers similar to how one does
- ** increment in binary arithmetic. If index 0 is empty, the data is
- ** stored there. If there is data there, it is merged and the
- ** results carried into position 1, with further merge-and-carry
- ** until an empty position is found.
- */
- DataBuffer *pBuffers = NULL;
- int nBuffers = 0, nMaxBuffers = 0, rc;
-
- assert( nTerm>0 );
-
- for(rc=SQLITE_OK; rc==SQLITE_OK && !leavesReaderAtEnd(pReader);
- rc=leavesReaderStep(v, pReader)){
- /* TODO(shess) Really want leavesReaderTermCmp(), but that name is
- ** already taken to compare the terms of two LeavesReaders. Think
- ** on a better name. [Meanwhile, break encapsulation rather than
- ** use a confusing name.]
- */
- int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix);
- if( c>0 ) break; /* Past any possible matches. */
- if( c==0 ){
- const char *pData = leavesReaderData(pReader);
- int iBuffer, nData = leavesReaderDataBytes(pReader);
-
- /* Find the first empty buffer. */
- for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
- if( 0==pBuffers[iBuffer].nData ) break;
- }
-
- /* Out of buffers, add an empty one. */
- if( iBuffer==nBuffers ){
- if( nBuffers==nMaxBuffers ){
- DataBuffer *p;
- nMaxBuffers += 20;
-
- /* Manual realloc so we can handle NULL appropriately. */
- p = sqlite3_malloc(nMaxBuffers*sizeof(*pBuffers));
- if( p==NULL ){
- rc = SQLITE_NOMEM;
- break;
- }
-
- if( nBuffers>0 ){
- assert(pBuffers!=NULL);
- memcpy(p, pBuffers, nBuffers*sizeof(*pBuffers));
- sqlite3_free(pBuffers);
- }
- pBuffers = p;
- }
- dataBufferInit(&(pBuffers[nBuffers]), 0);
- nBuffers++;
- }
-
- /* At this point, must have an empty at iBuffer. */
- assert(iBuffer<nBuffers && pBuffers[iBuffer].nData==0);
-
- /* If empty was first buffer, no need for merge logic. */
- if( iBuffer==0 ){
- dataBufferReplace(&(pBuffers[0]), pData, nData);
- }else{
- /* pAcc is the empty buffer the merged data will end up in. */
- DataBuffer *pAcc = &(pBuffers[iBuffer]);
- DataBuffer *p = &(pBuffers[0]);
-
- /* Handle position 0 specially to avoid need to prime pAcc
- ** with pData/nData.
- */
- dataBufferSwap(p, pAcc);
- docListAccumulateUnion(pAcc, pData, nData);
-
- /* Accumulate remaining doclists into pAcc. */
- for(++p; p<pAcc; ++p){
- docListAccumulateUnion(pAcc, p->pData, p->nData);
-
- /* dataBufferReset() could allow a large doclist to blow up
- ** our memory requirements.
- */
- if( p->nCapacity<1024 ){
- dataBufferReset(p);
- }else{
- dataBufferDestroy(p);
- dataBufferInit(p, 0);
- }
- }
- }
- }
- }
-
- /* Union all the doclists together into *out. */
- /* TODO(shess) What if *out is big? Sigh. */
- if( rc==SQLITE_OK && nBuffers>0 ){
- int iBuffer;
- for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
- if( pBuffers[iBuffer].nData>0 ){
- if( out->nData==0 ){
- dataBufferSwap(out, &(pBuffers[iBuffer]));
- }else{
- docListAccumulateUnion(out, pBuffers[iBuffer].pData,
- pBuffers[iBuffer].nData);
- }
- }
- }
- }
-
- while( nBuffers-- ){
- dataBufferDestroy(&(pBuffers[nBuffers]));
- }
- if( pBuffers!=NULL ) sqlite3_free(pBuffers);
-
- return rc;
-}
-
-/* Call loadSegmentLeavesInt() with pData/nData as input. */
-static int loadSegmentLeaf(fulltext_vtab *v, const char *pData, int nData,
- const char *pTerm, int nTerm, int isPrefix,
- DataBuffer *out){
- LeavesReader reader;
- int rc;
-
- assert( nData>1 );
- assert( *pData=='\0' );
- rc = leavesReaderInit(v, 0, 0, 0, pData, nData, &reader);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out);
- leavesReaderReset(&reader);
- leavesReaderDestroy(&reader);
- return rc;
-}
-
-/* Call loadSegmentLeavesInt() with the leaf nodes from iStartLeaf to
-** iEndLeaf (inclusive) as input, and merge the resulting doclist into
-** out.
-*/
-static int loadSegmentLeaves(fulltext_vtab *v,
- sqlite_int64 iStartLeaf, sqlite_int64 iEndLeaf,
- const char *pTerm, int nTerm, int isPrefix,
- DataBuffer *out){
- int rc;
- LeavesReader reader;
-
- assert( iStartLeaf<=iEndLeaf );
- rc = leavesReaderInit(v, 0, iStartLeaf, iEndLeaf, NULL, 0, &reader);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out);
- leavesReaderReset(&reader);
- leavesReaderDestroy(&reader);
- return rc;
-}
-
-/* Taking pData/nData as an interior node, find the sequence of child
-** nodes which could include pTerm/nTerm/isPrefix. Note that the
-** interior node terms logically come between the blocks, so there is
-** one more blockid than there are terms (that block contains terms >=
-** the last interior-node term).
-*/
-/* TODO(shess) The calling code may already know that the end child is
-** not worth calculating, because the end may be in a later sibling
-** node. Consider whether breaking symmetry is worthwhile. I suspect
-** it is not worthwhile.
-*/
-static void getChildrenContaining(const char *pData, int nData,
- const char *pTerm, int nTerm, int isPrefix,
- sqlite_int64 *piStartChild,
- sqlite_int64 *piEndChild){
- InteriorReader reader;
-
- assert( nData>1 );
- assert( *pData!='\0' );
- interiorReaderInit(pData, nData, &reader);
-
- /* Scan for the first child which could contain pTerm/nTerm. */
- while( !interiorReaderAtEnd(&reader) ){
- if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break;
- interiorReaderStep(&reader);
- }
- *piStartChild = interiorReaderCurrentBlockid(&reader);
-
- /* Keep scanning to find a term greater than our term, using prefix
- ** comparison if indicated. If isPrefix is false, this will be the
- ** same blockid as the starting block.
- */
- while( !interiorReaderAtEnd(&reader) ){
- if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break;
- interiorReaderStep(&reader);
- }
- *piEndChild = interiorReaderCurrentBlockid(&reader);
-
- interiorReaderDestroy(&reader);
-
- /* Children must ascend, and if !prefix, both must be the same. */
- assert( *piEndChild>=*piStartChild );
- assert( isPrefix || *piStartChild==*piEndChild );
-}
-
-/* Read block at iBlockid and pass it with other params to
-** getChildrenContaining().
-*/
-static int loadAndGetChildrenContaining(
- fulltext_vtab *v,
- sqlite_int64 iBlockid,
- const char *pTerm, int nTerm, int isPrefix,
- sqlite_int64 *piStartChild, sqlite_int64 *piEndChild
-){
- sqlite3_stmt *s = NULL;
- int rc;
-
- assert( iBlockid!=0 );
- assert( pTerm!=NULL );
- assert( nTerm!=0 ); /* TODO(shess) Why not allow this? */
- assert( piStartChild!=NULL );
- assert( piEndChild!=NULL );
-
- rc = sql_get_statement(v, BLOCK_SELECT_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_bind_int64(s, 1, iBlockid);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_step(s);
- if( rc==SQLITE_DONE ) return SQLITE_ERROR;
- if( rc!=SQLITE_ROW ) return rc;
-
- getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0),
- pTerm, nTerm, isPrefix, piStartChild, piEndChild);
-
- /* We expect only one row. We must execute another sqlite3_step()
- * to complete the iteration; otherwise the table will remain
- * locked. */
- rc = sqlite3_step(s);
- if( rc==SQLITE_ROW ) return SQLITE_ERROR;
- if( rc!=SQLITE_DONE ) return rc;
-
- return SQLITE_OK;
-}
-
-/* Traverse the tree represented by pData[nData] looking for
-** pTerm[nTerm], placing its doclist into *out. This is internal to
-** loadSegment() to make error-handling cleaner.
-*/
-static int loadSegmentInt(fulltext_vtab *v, const char *pData, int nData,
- sqlite_int64 iLeavesEnd,
- const char *pTerm, int nTerm, int isPrefix,
- DataBuffer *out){
- /* Special case where root is a leaf. */
- if( *pData=='\0' ){
- return loadSegmentLeaf(v, pData, nData, pTerm, nTerm, isPrefix, out);
- }else{
- int rc;
- sqlite_int64 iStartChild, iEndChild;
-
- /* Process pData as an interior node, then loop down the tree
- ** until we find the set of leaf nodes to scan for the term.
- */
- getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
- &iStartChild, &iEndChild);
- while( iStartChild>iLeavesEnd ){
- sqlite_int64 iNextStart, iNextEnd;
- rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix,
- &iNextStart, &iNextEnd);
- if( rc!=SQLITE_OK ) return rc;
-
- /* If we've branched, follow the end branch, too. */
- if( iStartChild!=iEndChild ){
- sqlite_int64 iDummy;
- rc = loadAndGetChildrenContaining(v, iEndChild, pTerm, nTerm, isPrefix,
- &iDummy, &iNextEnd);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- assert( iNextStart<=iNextEnd );
- iStartChild = iNextStart;
- iEndChild = iNextEnd;
- }
- assert( iStartChild<=iLeavesEnd );
- assert( iEndChild<=iLeavesEnd );
-
- /* Scan through the leaf segments for doclists. */
- return loadSegmentLeaves(v, iStartChild, iEndChild,
- pTerm, nTerm, isPrefix, out);
- }
-}
-
-/* Call loadSegmentInt() to collect the doclist for pTerm/nTerm, then
-** merge its doclist over *out (any duplicate doclists read from the
-** segment rooted at pData will overwrite those in *out).
-*/
-/* TODO(shess) Consider changing this to determine the depth of the
-** leaves using either the first characters of interior nodes (when
-** ==1, we're one level above the leaves), or the first character of
-** the root (which will describe the height of the tree directly).
-** Either feels somewhat tricky to me.
-*/
-/* TODO(shess) The current merge is likely to be slow for large
-** doclists (though it should process from newest/smallest to
-** oldest/largest, so it may not be that bad). It might be useful to
-** modify things to allow for N-way merging. This could either be
-** within a segment, with pairwise merges across segments, or across
-** all segments at once.
-*/
-static int loadSegment(fulltext_vtab *v, const char *pData, int nData,
- sqlite_int64 iLeavesEnd,
- const char *pTerm, int nTerm, int isPrefix,
- DataBuffer *out){
- DataBuffer result;
- int rc;
-
- assert( nData>1 );
-
- /* This code should never be called with buffered updates. */
- assert( v->nPendingData<0 );
-
- dataBufferInit(&result, 0);
- rc = loadSegmentInt(v, pData, nData, iLeavesEnd,
- pTerm, nTerm, isPrefix, &result);
- if( rc==SQLITE_OK && result.nData>0 ){
- if( out->nData==0 ){
- DataBuffer tmp = *out;
- *out = result;
- result = tmp;
- }else{
- DataBuffer merged;
- DLReader readers[2];
-
- dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
- dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
- dataBufferInit(&merged, out->nData+result.nData);
- docListMerge(&merged, readers, 2);
- dataBufferDestroy(out);
- *out = merged;
- dlrDestroy(&readers[0]);
- dlrDestroy(&readers[1]);
- }
- }
- dataBufferDestroy(&result);
- return rc;
-}
-
-/* Scan the database and merge together the posting lists for the term
-** into *out.
-*/
-static int termSelect(fulltext_vtab *v, int iColumn,
- const char *pTerm, int nTerm, int isPrefix,
- DocListType iType, DataBuffer *out){
- DataBuffer doclist;
- sqlite3_stmt *s;
- int rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s);
- if( rc!=SQLITE_OK ) return rc;
-
- /* This code should never be called with buffered updates. */
- assert( v->nPendingData<0 );
-
- dataBufferInit(&doclist, 0);
-
- /* Traverse the segments from oldest to newest so that newer doclist
- ** elements for given docids overwrite older elements.
- */
- while( (rc = sqlite3_step(s))==SQLITE_ROW ){
- const char *pData = sqlite3_column_blob(s, 2);
- const int nData = sqlite3_column_bytes(s, 2);
- const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1);
- rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix,
- &doclist);
- if( rc!=SQLITE_OK ) goto err;
- }
- if( rc==SQLITE_DONE ){
- if( doclist.nData!=0 ){
- /* TODO(shess) The old term_select_all() code applied the column
- ** restrict as we merged segments, leading to smaller buffers.
- ** This is probably worthwhile to bring back, once the new storage
- ** system is checked in.
- */
- if( iColumn==v->nColumn) iColumn = -1;
- docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
- iColumn, iType, out);
- }
- rc = SQLITE_OK;
- }
-
- err:
- dataBufferDestroy(&doclist);
- return rc;
-}
-
-/****************************************************************/
-/* Used to hold hashtable data for sorting. */
-typedef struct TermData {
- const char *pTerm;
- int nTerm;
- DLCollector *pCollector;
-} TermData;
-
-/* Orders TermData elements in strcmp fashion ( <0 for less-than, 0
-** for equal, >0 for greater-than).
-*/
-static int termDataCmp(const void *av, const void *bv){
- const TermData *a = (const TermData *)av;
- const TermData *b = (const TermData *)bv;
- int n = a->nTerm<b->nTerm ? a->nTerm : b->nTerm;
- int c = memcmp(a->pTerm, b->pTerm, n);
- if( c!=0 ) return c;
- return a->nTerm-b->nTerm;
-}
-
-/* Order pTerms data by term, then write a new level 0 segment using
-** LeafWriter.
-*/
-static int writeZeroSegment(fulltext_vtab *v, fts2Hash *pTerms){
- fts2HashElem *e;
- int idx, rc, i, n;
- TermData *pData;
- LeafWriter writer;
- DataBuffer dl;
-
- /* Determine the next index at level 0, merging as necessary. */
- rc = segdirNextIndex(v, 0, &idx);
- if( rc!=SQLITE_OK ) return rc;
-
- n = fts2HashCount(pTerms);
- pData = sqlite3_malloc(n*sizeof(TermData));
-
- for(i = 0, e = fts2HashFirst(pTerms); e; i++, e = fts2HashNext(e)){
- assert( i<n );
- pData[i].pTerm = fts2HashKey(e);
- pData[i].nTerm = fts2HashKeysize(e);
- pData[i].pCollector = fts2HashData(e);
- }
- assert( i==n );
-
- /* TODO(shess) Should we allow user-defined collation sequences,
- ** here? I think we only need that once we support prefix searches.
- */
- if( n>1 ) qsort(pData, n, sizeof(*pData), termDataCmp);
-
- /* TODO(shess) Refactor so that we can write directly to the segment
- ** DataBuffer, as happens for segment merges.
- */
- leafWriterInit(0, idx, &writer);
- dataBufferInit(&dl, 0);
- for(i=0; i<n; i++){
- dataBufferReset(&dl);
- dlcAddDoclist(pData[i].pCollector, &dl);
- rc = leafWriterStep(v, &writer,
- pData[i].pTerm, pData[i].nTerm, dl.pData, dl.nData);
- if( rc!=SQLITE_OK ) goto err;
- }
- rc = leafWriterFinalize(v, &writer);
-
- err:
- dataBufferDestroy(&dl);
- sqlite3_free(pData);
- leafWriterDestroy(&writer);
- return rc;
-}
-
-/* If pendingTerms has data, free it. */
-static int clearPendingTerms(fulltext_vtab *v){
- if( v->nPendingData>=0 ){
- fts2HashElem *e;
- for(e=fts2HashFirst(&v->pendingTerms); e; e=fts2HashNext(e)){
- dlcDelete(fts2HashData(e));
- }
- fts2HashClear(&v->pendingTerms);
- v->nPendingData = -1;
- }
- return SQLITE_OK;
-}
-
-/* If pendingTerms has data, flush it to a level-zero segment, and
-** free it.
-*/
-static int flushPendingTerms(fulltext_vtab *v){
- if( v->nPendingData>=0 ){
- int rc = writeZeroSegment(v, &v->pendingTerms);
- if( rc==SQLITE_OK ) clearPendingTerms(v);
- return rc;
- }
- return SQLITE_OK;
-}
-
-/* If pendingTerms is "too big", or docid is out of order, flush it.
-** Regardless, be certain that pendingTerms is initialized for use.
-*/
-static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid){
- /* TODO(shess) Explore whether partially flushing the buffer on
- ** forced-flush would provide better performance. I suspect that if
- ** we ordered the doclists by size and flushed the largest until the
- ** buffer was half empty, that would let the less frequent terms
- ** generate longer doclists.
- */
- if( iDocid<=v->iPrevDocid || v->nPendingData>kPendingThreshold ){
- int rc = flushPendingTerms(v);
- if( rc!=SQLITE_OK ) return rc;
- }
- if( v->nPendingData<0 ){
- fts2HashInit(&v->pendingTerms, FTS2_HASH_STRING, 1);
- v->nPendingData = 0;
- }
- v->iPrevDocid = iDocid;
- return SQLITE_OK;
-}
-
-/* This function implements the xUpdate callback; it is the top-level entry
- * point for inserting, deleting or updating a row in a full-text table. */
-static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg,
- sqlite_int64 *pRowid){
- fulltext_vtab *v = (fulltext_vtab *) pVtab;
- int rc;
-
- TRACE(("FTS2 Update %p\n", pVtab));
-
- if( nArg<2 ){
- rc = index_delete(v, sqlite3_value_int64(ppArg[0]));
- if( rc==SQLITE_OK ){
- /* If we just deleted the last row in the table, clear out the
- ** index data.
- */
- rc = content_exists(v);
- if( rc==SQLITE_ROW ){
- rc = SQLITE_OK;
- }else if( rc==SQLITE_DONE ){
- /* Clear the pending terms so we don't flush a useless level-0
- ** segment when the transaction closes.
- */
- rc = clearPendingTerms(v);
- if( rc==SQLITE_OK ){
- rc = segdir_delete_all(v);
- }
- }
- }
- } else if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){
- /* An update:
- * ppArg[0] = old rowid
- * ppArg[1] = new rowid
- * ppArg[2..2+v->nColumn-1] = values
- * ppArg[2+v->nColumn] = value for magic column (we ignore this)
- */
- sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]);
- if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER ||
- sqlite3_value_int64(ppArg[1]) != rowid ){
- rc = SQLITE_ERROR; /* we don't allow changing the rowid */
- } else {
- assert( nArg==2+v->nColumn+1);
- rc = index_update(v, rowid, &ppArg[2]);
- }
- } else {
- /* An insert:
- * ppArg[1] = requested rowid
- * ppArg[2..2+v->nColumn-1] = values
- * ppArg[2+v->nColumn] = value for magic column (we ignore this)
- */
- assert( nArg==2+v->nColumn+1);
- rc = index_insert(v, ppArg[1], &ppArg[2], pRowid);
- }
-
- return rc;
-}
-
-static int fulltextSync(sqlite3_vtab *pVtab){
- TRACE(("FTS2 xSync()\n"));
- return flushPendingTerms((fulltext_vtab *)pVtab);
-}
-
-static int fulltextBegin(sqlite3_vtab *pVtab){
- fulltext_vtab *v = (fulltext_vtab *) pVtab;
- TRACE(("FTS2 xBegin()\n"));
-
- /* Any buffered updates should have been cleared by the previous
- ** transaction.
- */
- assert( v->nPendingData<0 );
- return clearPendingTerms(v);
-}
-
-static int fulltextCommit(sqlite3_vtab *pVtab){
- fulltext_vtab *v = (fulltext_vtab *) pVtab;
- TRACE(("FTS2 xCommit()\n"));
-
- /* Buffered updates should have been cleared by fulltextSync(). */
- assert( v->nPendingData<0 );
- return clearPendingTerms(v);
-}
-
-static int fulltextRollback(sqlite3_vtab *pVtab){
- TRACE(("FTS2 xRollback()\n"));
- return clearPendingTerms((fulltext_vtab *)pVtab);
-}
-
-/*
-** Implementation of the snippet() function for FTS2
-*/
-static void snippetFunc(
- sqlite3_context *pContext,
- int argc,
- sqlite3_value **argv
-){
- fulltext_cursor *pCursor;
- if( argc<1 ) return;
- if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
- sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
- sqlite3_result_error(pContext, "illegal first argument to html_snippet",-1);
- }else{
- const char *zStart = "<b>";
- const char *zEnd = "</b>";
- const char *zEllipsis = "<b>...</b>";
- memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
- if( argc>=2 ){
- zStart = (const char*)sqlite3_value_text(argv[1]);
- if( argc>=3 ){
- zEnd = (const char*)sqlite3_value_text(argv[2]);
- if( argc>=4 ){
- zEllipsis = (const char*)sqlite3_value_text(argv[3]);
- }
- }
- }
- snippetAllOffsets(pCursor);
- snippetText(pCursor, zStart, zEnd, zEllipsis);
- sqlite3_result_text(pContext, pCursor->snippet.zSnippet,
- pCursor->snippet.nSnippet, SQLITE_STATIC);
- }
-}
-
-/*
-** Implementation of the offsets() function for FTS2
-*/
-static void snippetOffsetsFunc(
- sqlite3_context *pContext,
- int argc,
- sqlite3_value **argv
-){
- fulltext_cursor *pCursor;
- if( argc<1 ) return;
- if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
- sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
- sqlite3_result_error(pContext, "illegal first argument to offsets",-1);
- }else{
- memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
- snippetAllOffsets(pCursor);
- snippetOffsetText(&pCursor->snippet);
- sqlite3_result_text(pContext,
- pCursor->snippet.zOffset, pCursor->snippet.nOffset,
- SQLITE_STATIC);
- }
-}
-
-/* OptLeavesReader is nearly identical to LeavesReader, except that
-** where LeavesReader is geared towards the merging of complete
-** segment levels (with exactly MERGE_COUNT segments), OptLeavesReader
-** is geared towards implementation of the optimize() function, and
-** can merge all segments simultaneously. This version may be
-** somewhat less efficient than LeavesReader because it merges into an
-** accumulator rather than doing an N-way merge, but since segment
-** size grows exponentially (so segment count logrithmically) this is
-** probably not an immediate problem.
-*/
-/* TODO(shess): Prove that assertion, or extend the merge code to
-** merge tree fashion (like the prefix-searching code does).
-*/
-/* TODO(shess): OptLeavesReader and LeavesReader could probably be
-** merged with little or no loss of performance for LeavesReader. The
-** merged code would need to handle >MERGE_COUNT segments, and would
-** also need to be able to optionally optimize away deletes.
-*/
-typedef struct OptLeavesReader {
- /* Segment number, to order readers by age. */
- int segment;
- LeavesReader reader;
-} OptLeavesReader;
-
-static int optLeavesReaderAtEnd(OptLeavesReader *pReader){
- return leavesReaderAtEnd(&pReader->reader);
-}
-static int optLeavesReaderTermBytes(OptLeavesReader *pReader){
- return leavesReaderTermBytes(&pReader->reader);
-}
-static const char *optLeavesReaderData(OptLeavesReader *pReader){
- return leavesReaderData(&pReader->reader);
-}
-static int optLeavesReaderDataBytes(OptLeavesReader *pReader){
- return leavesReaderDataBytes(&pReader->reader);
-}
-static const char *optLeavesReaderTerm(OptLeavesReader *pReader){
- return leavesReaderTerm(&pReader->reader);
-}
-static int optLeavesReaderStep(fulltext_vtab *v, OptLeavesReader *pReader){
- return leavesReaderStep(v, &pReader->reader);
-}
-static int optLeavesReaderTermCmp(OptLeavesReader *lr1, OptLeavesReader *lr2){
- return leavesReaderTermCmp(&lr1->reader, &lr2->reader);
-}
-/* Order by term ascending, segment ascending (oldest to newest), with
-** exhausted readers to the end.
-*/
-static int optLeavesReaderCmp(OptLeavesReader *lr1, OptLeavesReader *lr2){
- int c = optLeavesReaderTermCmp(lr1, lr2);
- if( c!=0 ) return c;
- return lr1->segment-lr2->segment;
-}
-/* Bubble pLr[0] to appropriate place in pLr[1..nLr-1]. Assumes that
-** pLr[1..nLr-1] is already sorted.
-*/
-static void optLeavesReaderReorder(OptLeavesReader *pLr, int nLr){
- while( nLr>1 && optLeavesReaderCmp(pLr, pLr+1)>0 ){
- OptLeavesReader tmp = pLr[0];
- pLr[0] = pLr[1];
- pLr[1] = tmp;
- nLr--;
- pLr++;
- }
-}
-
-/* optimize() helper function. Put the readers in order and iterate
-** through them, merging doclists for matching terms into pWriter.
-** Returns SQLITE_OK on success, or the SQLite error code which
-** prevented success.
-*/
-static int optimizeInternal(fulltext_vtab *v,
- OptLeavesReader *readers, int nReaders,
- LeafWriter *pWriter){
- int i, rc = SQLITE_OK;
- DataBuffer doclist, merged, tmp;
-
- /* Order the readers. */
- i = nReaders;
- while( i-- > 0 ){
- optLeavesReaderReorder(&readers[i], nReaders-i);
- }
-
- dataBufferInit(&doclist, LEAF_MAX);
- dataBufferInit(&merged, LEAF_MAX);
-
- /* Exhausted readers bubble to the end, so when the first reader is
- ** at eof, all are at eof.
- */
- while( !optLeavesReaderAtEnd(&readers[0]) ){
-
- /* Figure out how many readers share the next term. */
- for(i=1; i<nReaders && !optLeavesReaderAtEnd(&readers[i]); i++){
- if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break;
- }
-
- /* Special-case for no merge. */
- if( i==1 ){
- /* Trim deletions from the doclist. */
- dataBufferReset(&merged);
- docListTrim(DL_DEFAULT,
- optLeavesReaderData(&readers[0]),
- optLeavesReaderDataBytes(&readers[0]),
- -1, DL_DEFAULT, &merged);
- }else{
- DLReader dlReaders[MERGE_COUNT];
- int iReader, nReaders;
-
- /* Prime the pipeline with the first reader's doclist. After
- ** one pass index 0 will reference the accumulated doclist.
- */
- dlrInit(&dlReaders[0], DL_DEFAULT,
- optLeavesReaderData(&readers[0]),
- optLeavesReaderDataBytes(&readers[0]));
- iReader = 1;
-
- assert( iReader<i ); /* Must execute the loop at least once. */
- while( iReader<i ){
- /* Merge 16 inputs per pass. */
- for( nReaders=1; iReader<i && nReaders<MERGE_COUNT;
- iReader++, nReaders++ ){
- dlrInit(&dlReaders[nReaders], DL_DEFAULT,
- optLeavesReaderData(&readers[iReader]),
- optLeavesReaderDataBytes(&readers[iReader]));
- }
-
- /* Merge doclists and swap result into accumulator. */
- dataBufferReset(&merged);
- docListMerge(&merged, dlReaders, nReaders);
- tmp = merged;
- merged = doclist;
- doclist = tmp;
-
- while( nReaders-- > 0 ){
- dlrDestroy(&dlReaders[nReaders]);
- }
-
- /* Accumulated doclist to reader 0 for next pass. */
- dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
- }
-
- /* Destroy reader that was left in the pipeline. */
- dlrDestroy(&dlReaders[0]);
-
- /* Trim deletions from the doclist. */
- dataBufferReset(&merged);
- docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
- -1, DL_DEFAULT, &merged);
- }
-
- /* Only pass doclists with hits (skip if all hits deleted). */
- if( merged.nData>0 ){
- rc = leafWriterStep(v, pWriter,
- optLeavesReaderTerm(&readers[0]),
- optLeavesReaderTermBytes(&readers[0]),
- merged.pData, merged.nData);
- if( rc!=SQLITE_OK ) goto err;
- }
-
- /* Step merged readers to next term and reorder. */
- while( i-- > 0 ){
- rc = optLeavesReaderStep(v, &readers[i]);
- if( rc!=SQLITE_OK ) goto err;
-
- optLeavesReaderReorder(&readers[i], nReaders-i);
- }
- }
-
- err:
- dataBufferDestroy(&doclist);
- dataBufferDestroy(&merged);
- return rc;
-}
-
-/* Implement optimize() function for FTS3. optimize(t) merges all
-** segments in the fts index into a single segment. 't' is the magic
-** table-named column.
-*/
-static void optimizeFunc(sqlite3_context *pContext,
- int argc, sqlite3_value **argv){
- fulltext_cursor *pCursor;
- if( argc>1 ){
- sqlite3_result_error(pContext, "excess arguments to optimize()",-1);
- }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
- sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
- sqlite3_result_error(pContext, "illegal first argument to optimize",-1);
- }else{
- fulltext_vtab *v;
- int i, rc, iMaxLevel;
- OptLeavesReader *readers;
- int nReaders;
- LeafWriter writer;
- sqlite3_stmt *s;
-
- memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
- v = cursor_vtab(pCursor);
-
- /* Flush any buffered updates before optimizing. */
- rc = flushPendingTerms(v);
- if( rc!=SQLITE_OK ) goto err;
-
- rc = segdir_count(v, &nReaders, &iMaxLevel);
- if( rc!=SQLITE_OK ) goto err;
- if( nReaders==0 || nReaders==1 ){
- sqlite3_result_text(pContext, "Index already optimal", -1,
- SQLITE_STATIC);
- return;
- }
-
- rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s);
- if( rc!=SQLITE_OK ) goto err;
-
- readers = sqlite3_malloc(nReaders*sizeof(readers[0]));
- if( readers==NULL ) goto err;
-
- /* Note that there will already be a segment at this position
- ** until we call segdir_delete() on iMaxLevel.
- */
- leafWriterInit(iMaxLevel, 0, &writer);
-
- i = 0;
- while( (rc = sqlite3_step(s))==SQLITE_ROW ){
- sqlite_int64 iStart = sqlite3_column_int64(s, 0);
- sqlite_int64 iEnd = sqlite3_column_int64(s, 1);
- const char *pRootData = sqlite3_column_blob(s, 2);
- int nRootData = sqlite3_column_bytes(s, 2);
-
- assert( i<nReaders );
- rc = leavesReaderInit(v, -1, iStart, iEnd, pRootData, nRootData,
- &readers[i].reader);
- if( rc!=SQLITE_OK ) break;
-
- readers[i].segment = i;
- i++;
- }
-
- /* If we managed to successfully read them all, optimize them. */
- if( rc==SQLITE_DONE ){
- assert( i==nReaders );
- rc = optimizeInternal(v, readers, nReaders, &writer);
- }
-
- while( i-- > 0 ){
- leavesReaderDestroy(&readers[i].reader);
- }
- sqlite3_free(readers);
-
- /* If we've successfully gotten to here, delete the old segments
- ** and flush the interior structure of the new segment.
- */
- if( rc==SQLITE_OK ){
- for( i=0; i<=iMaxLevel; i++ ){
- rc = segdir_delete(v, i);
- if( rc!=SQLITE_OK ) break;
- }
-
- if( rc==SQLITE_OK ) rc = leafWriterFinalize(v, &writer);
- }
-
- leafWriterDestroy(&writer);
-
- if( rc!=SQLITE_OK ) goto err;
-
- sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC);
- return;
-
- /* TODO(shess): Error-handling needs to be improved along the
- ** lines of the dump_ functions.
- */
- err:
- {
- char buf[512];
- sqlite3_snprintf(sizeof(buf), buf, "Error in optimize: %s",
- sqlite3_errmsg(sqlite3_context_db_handle(pContext)));
- sqlite3_result_error(pContext, buf, -1);
- }
- }
-}
-
-#ifdef SQLITE_TEST
-/* Generate an error of the form "<prefix>: <msg>". If msg is NULL,
-** pull the error from the context's db handle.
-*/
-static void generateError(sqlite3_context *pContext,
- const char *prefix, const char *msg){
- char buf[512];
- if( msg==NULL ) msg = sqlite3_errmsg(sqlite3_context_db_handle(pContext));
- sqlite3_snprintf(sizeof(buf), buf, "%s: %s", prefix, msg);
- sqlite3_result_error(pContext, buf, -1);
-}
-
-/* Helper function to collect the set of terms in the segment into
-** pTerms. The segment is defined by the leaf nodes between
-** iStartBlockid and iEndBlockid, inclusive, or by the contents of
-** pRootData if iStartBlockid is 0 (in which case the entire segment
-** fit in a leaf).
-*/
-static int collectSegmentTerms(fulltext_vtab *v, sqlite3_stmt *s,
- fts2Hash *pTerms){
- const sqlite_int64 iStartBlockid = sqlite3_column_int64(s, 0);
- const sqlite_int64 iEndBlockid = sqlite3_column_int64(s, 1);
- const char *pRootData = sqlite3_column_blob(s, 2);
- const int nRootData = sqlite3_column_bytes(s, 2);
- LeavesReader reader;
- int rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid,
- pRootData, nRootData, &reader);
- if( rc!=SQLITE_OK ) return rc;
-
- while( rc==SQLITE_OK && !leavesReaderAtEnd(&reader) ){
- const char *pTerm = leavesReaderTerm(&reader);
- const int nTerm = leavesReaderTermBytes(&reader);
- void *oldValue = sqlite3Fts2HashFind(pTerms, pTerm, nTerm);
- void *newValue = (void *)((char *)oldValue+1);
-
- /* From the comment before sqlite3Fts2HashInsert in fts2_hash.c,
- ** the data value passed is returned in case of malloc failure.
- */
- if( newValue==sqlite3Fts2HashInsert(pTerms, pTerm, nTerm, newValue) ){
- rc = SQLITE_NOMEM;
- }else{
- rc = leavesReaderStep(v, &reader);
- }
- }
-
- leavesReaderDestroy(&reader);
- return rc;
-}
-
-/* Helper function to build the result string for dump_terms(). */
-static int generateTermsResult(sqlite3_context *pContext, fts2Hash *pTerms){
- int iTerm, nTerms, nResultBytes, iByte;
- char *result;
- TermData *pData;
- fts2HashElem *e;
-
- /* Iterate pTerms to generate an array of terms in pData for
- ** sorting.
- */
- nTerms = fts2HashCount(pTerms);
- assert( nTerms>0 );
- pData = sqlite3_malloc(nTerms*sizeof(TermData));
- if( pData==NULL ) return SQLITE_NOMEM;
-
- nResultBytes = 0;
- for(iTerm = 0, e = fts2HashFirst(pTerms); e; iTerm++, e = fts2HashNext(e)){
- nResultBytes += fts2HashKeysize(e)+1; /* Term plus trailing space */
- assert( iTerm<nTerms );
- pData[iTerm].pTerm = fts2HashKey(e);
- pData[iTerm].nTerm = fts2HashKeysize(e);
- pData[iTerm].pCollector = fts2HashData(e); /* unused */
- }
- assert( iTerm==nTerms );
-
- assert( nResultBytes>0 ); /* nTerms>0, nResultsBytes must be, too. */
- result = sqlite3_malloc(nResultBytes);
- if( result==NULL ){
- sqlite3_free(pData);
- return SQLITE_NOMEM;
- }
-
- if( nTerms>1 ) qsort(pData, nTerms, sizeof(*pData), termDataCmp);
-
- /* Read the terms in order to build the result. */
- iByte = 0;
- for(iTerm=0; iTerm<nTerms; ++iTerm){
- memcpy(result+iByte, pData[iTerm].pTerm, pData[iTerm].nTerm);
- iByte += pData[iTerm].nTerm;
- result[iByte++] = ' ';
- }
- assert( iByte==nResultBytes );
- assert( result[nResultBytes-1]==' ' );
- result[nResultBytes-1] = '\0';
-
- /* Passes away ownership of result. */
- sqlite3_result_text(pContext, result, nResultBytes-1, sqlite3_free);
- sqlite3_free(pData);
- return SQLITE_OK;
-}
-
-/* Implements dump_terms() for use in inspecting the fts2 index from
-** tests. TEXT result containing the ordered list of terms joined by
-** spaces. dump_terms(t, level, idx) dumps the terms for the segment
-** specified by level, idx (in %_segdir), while dump_terms(t) dumps
-** all terms in the index. In both cases t is the fts table's magic
-** table-named column.
-*/
-static void dumpTermsFunc(
- sqlite3_context *pContext,
- int argc, sqlite3_value **argv
-){
- fulltext_cursor *pCursor;
- if( argc!=3 && argc!=1 ){
- generateError(pContext, "dump_terms", "incorrect arguments");
- }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
- sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
- generateError(pContext, "dump_terms", "illegal first argument");
- }else{
- fulltext_vtab *v;
- fts2Hash terms;
- sqlite3_stmt *s = NULL;
- int rc;
-
- memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
- v = cursor_vtab(pCursor);
-
- /* If passed only the cursor column, get all segments. Otherwise
- ** get the segment described by the following two arguments.
- */
- if( argc==1 ){
- rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s);
- }else{
- rc = sql_get_statement(v, SEGDIR_SELECT_SEGMENT_STMT, &s);
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_int(s, 1, sqlite3_value_int(argv[1]));
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_int(s, 2, sqlite3_value_int(argv[2]));
- }
- }
- }
-
- if( rc!=SQLITE_OK ){
- generateError(pContext, "dump_terms", NULL);
- return;
- }
-
- /* Collect the terms for each segment. */
- sqlite3Fts2HashInit(&terms, FTS2_HASH_STRING, 1);
- while( (rc = sqlite3_step(s))==SQLITE_ROW ){
- rc = collectSegmentTerms(v, s, &terms);
- if( rc!=SQLITE_OK ) break;
- }
-
- if( rc!=SQLITE_DONE ){
- sqlite3_reset(s);
- generateError(pContext, "dump_terms", NULL);
- }else{
- const int nTerms = fts2HashCount(&terms);
- if( nTerms>0 ){
- rc = generateTermsResult(pContext, &terms);
- if( rc==SQLITE_NOMEM ){
- generateError(pContext, "dump_terms", "out of memory");
- }else{
- assert( rc==SQLITE_OK );
- }
- }else if( argc==3 ){
- /* The specific segment asked for could not be found. */
- generateError(pContext, "dump_terms", "segment not found");
- }else{
- /* No segments found. */
- /* TODO(shess): It should be impossible to reach this. This
- ** case can only happen for an empty table, in which case
- ** SQLite has no rows to call this function on.
- */
- sqlite3_result_null(pContext);
- }
- }
- sqlite3Fts2HashClear(&terms);
- }
-}
-
-/* Expand the DL_DEFAULT doclist in pData into a text result in
-** pContext.
-*/
-static void createDoclistResult(sqlite3_context *pContext,
- const char *pData, int nData){
- DataBuffer dump;
- DLReader dlReader;
-
- assert( pData!=NULL && nData>0 );
-
- dataBufferInit(&dump, 0);
- dlrInit(&dlReader, DL_DEFAULT, pData, nData);
- for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){
- char buf[256];
- PLReader plReader;
-
- plrInit(&plReader, &dlReader);
- if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){
- sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader));
- dataBufferAppend(&dump, buf, strlen(buf));
- }else{
- int iColumn = plrColumn(&plReader);
-
- sqlite3_snprintf(sizeof(buf), buf, "[%lld %d[",
- dlrDocid(&dlReader), iColumn);
- dataBufferAppend(&dump, buf, strlen(buf));
-
- for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){
- if( plrColumn(&plReader)!=iColumn ){
- iColumn = plrColumn(&plReader);
- sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn);
- assert( dump.nData>0 );
- dump.nData--; /* Overwrite trailing space. */
- assert( dump.pData[dump.nData]==' ');
- dataBufferAppend(&dump, buf, strlen(buf));
- }
- if( DL_DEFAULT==DL_POSITIONS_OFFSETS ){
- sqlite3_snprintf(sizeof(buf), buf, "%d,%d,%d ",
- plrPosition(&plReader),
- plrStartOffset(&plReader), plrEndOffset(&plReader));
- }else if( DL_DEFAULT==DL_POSITIONS ){
- sqlite3_snprintf(sizeof(buf), buf, "%d ", plrPosition(&plReader));
- }else{
- assert( NULL=="Unhandled DL_DEFAULT value");
- }
- dataBufferAppend(&dump, buf, strlen(buf));
- }
- plrDestroy(&plReader);
-
- assert( dump.nData>0 );
- dump.nData--; /* Overwrite trailing space. */
- assert( dump.pData[dump.nData]==' ');
- dataBufferAppend(&dump, "]] ", 3);
- }
- }
- dlrDestroy(&dlReader);
-
- assert( dump.nData>0 );
- dump.nData--; /* Overwrite trailing space. */
- assert( dump.pData[dump.nData]==' ');
- dump.pData[dump.nData] = '\0';
- assert( dump.nData>0 );
-
- /* Passes ownership of dump's buffer to pContext. */
- sqlite3_result_text(pContext, dump.pData, dump.nData, sqlite3_free);
- dump.pData = NULL;
- dump.nData = dump.nCapacity = 0;
-}
-
-/* Implements dump_doclist() for use in inspecting the fts2 index from
-** tests. TEXT result containing a string representation of the
-** doclist for the indicated term. dump_doclist(t, term, level, idx)
-** dumps the doclist for term from the segment specified by level, idx
-** (in %_segdir), while dump_doclist(t, term) dumps the logical
-** doclist for the term across all segments. The per-segment doclist
-** can contain deletions, while the full-index doclist will not
-** (deletions are omitted).
-**
-** Result formats differ with the setting of DL_DEFAULTS. Examples:
-**
-** DL_DOCIDS: [1] [3] [7]
-** DL_POSITIONS: [1 0[0 4] 1[17]] [3 1[5]]
-** DL_POSITIONS_OFFSETS: [1 0[0,0,3 4,23,26] 1[17,102,105]] [3 1[5,20,23]]
-**
-** In each case the number after the outer '[' is the docid. In the
-** latter two cases, the number before the inner '[' is the column
-** associated with the values within. For DL_POSITIONS the numbers
-** within are the positions, for DL_POSITIONS_OFFSETS they are the
-** position, the start offset, and the end offset.
-*/
-static void dumpDoclistFunc(
- sqlite3_context *pContext,
- int argc, sqlite3_value **argv
-){
- fulltext_cursor *pCursor;
- if( argc!=2 && argc!=4 ){
- generateError(pContext, "dump_doclist", "incorrect arguments");
- }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
- sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
- generateError(pContext, "dump_doclist", "illegal first argument");
- }else if( sqlite3_value_text(argv[1])==NULL ||
- sqlite3_value_text(argv[1])[0]=='\0' ){
- generateError(pContext, "dump_doclist", "empty second argument");
- }else{
- const char *pTerm = (const char *)sqlite3_value_text(argv[1]);
- const int nTerm = strlen(pTerm);
- fulltext_vtab *v;
- int rc;
- DataBuffer doclist;
-
- memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
- v = cursor_vtab(pCursor);
-
- dataBufferInit(&doclist, 0);
-
- /* termSelect() yields the same logical doclist that queries are
- ** run against.
- */
- if( argc==2 ){
- rc = termSelect(v, v->nColumn, pTerm, nTerm, 0, DL_DEFAULT, &doclist);
- }else{
- sqlite3_stmt *s = NULL;
-
- /* Get our specific segment's information. */
- rc = sql_get_statement(v, SEGDIR_SELECT_SEGMENT_STMT, &s);
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_int(s, 1, sqlite3_value_int(argv[2]));
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_int(s, 2, sqlite3_value_int(argv[3]));
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_step(s);
-
- if( rc==SQLITE_DONE ){
- dataBufferDestroy(&doclist);
- generateError(pContext, "dump_doclist", "segment not found");
- return;
- }
-
- /* Found a segment, load it into doclist. */
- if( rc==SQLITE_ROW ){
- const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1);
- const char *pData = sqlite3_column_blob(s, 2);
- const int nData = sqlite3_column_bytes(s, 2);
-
- /* loadSegment() is used by termSelect() to load each
- ** segment's data.
- */
- rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, 0,
- &doclist);
- if( rc==SQLITE_OK ){
- rc = sqlite3_step(s);
-
- /* Should not have more than one matching segment. */
- if( rc!=SQLITE_DONE ){
- sqlite3_reset(s);
- dataBufferDestroy(&doclist);
- generateError(pContext, "dump_doclist", "invalid segdir");
- return;
- }
- rc = SQLITE_OK;
- }
- }
- }
-
- sqlite3_reset(s);
- }
-
- if( rc==SQLITE_OK ){
- if( doclist.nData>0 ){
- createDoclistResult(pContext, doclist.pData, doclist.nData);
- }else{
- /* TODO(shess): This can happen if the term is not present, or
- ** if all instances of the term have been deleted and this is
- ** an all-index dump. It may be interesting to distinguish
- ** these cases.
- */
- sqlite3_result_text(pContext, "", 0, SQLITE_STATIC);
- }
- }else if( rc==SQLITE_NOMEM ){
- /* Handle out-of-memory cases specially because if they are
- ** generated in fts2 code they may not be reflected in the db
- ** handle.
- */
- /* TODO(shess): Handle this more comprehensively.
- ** sqlite3ErrStr() has what I need, but is internal.
- */
- generateError(pContext, "dump_doclist", "out of memory");
- }else{
- generateError(pContext, "dump_doclist", NULL);
- }
-
- dataBufferDestroy(&doclist);
- }
-}
-#endif
-
-/*
-** This routine implements the xFindFunction method for the FTS2
-** virtual table.
-*/
-static int fulltextFindFunction(
- sqlite3_vtab *pVtab,
- int nArg,
- const char *zName,
- void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
- void **ppArg
-){
- if( strcmp(zName,"snippet")==0 ){
- *pxFunc = snippetFunc;
- return 1;
- }else if( strcmp(zName,"offsets")==0 ){
- *pxFunc = snippetOffsetsFunc;
- return 1;
- }else if( strcmp(zName,"optimize")==0 ){
- *pxFunc = optimizeFunc;
- return 1;
-#ifdef SQLITE_TEST
- /* NOTE(shess): These functions are present only for testing
- ** purposes. No particular effort is made to optimize their
- ** execution or how they build their results.
- */
- }else if( strcmp(zName,"dump_terms")==0 ){
- /* fprintf(stderr, "Found dump_terms\n"); */
- *pxFunc = dumpTermsFunc;
- return 1;
- }else if( strcmp(zName,"dump_doclist")==0 ){
- /* fprintf(stderr, "Found dump_doclist\n"); */
- *pxFunc = dumpDoclistFunc;
- return 1;
-#endif
- }
- return 0;
-}
-
-/*
-** Rename an fts2 table.
-*/
-static int fulltextRename(
- sqlite3_vtab *pVtab,
- const char *zName
-){
- fulltext_vtab *p = (fulltext_vtab *)pVtab;
- int rc = SQLITE_NOMEM;
- char *zSql = sqlite3_mprintf(
- "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';"
- "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';"
- "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';"
- , p->zDb, p->zName, zName
- , p->zDb, p->zName, zName
- , p->zDb, p->zName, zName
- );
- if( zSql ){
- rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
- return rc;
-}
-
-static const sqlite3_module fts2Module = {
- /* iVersion */ 0,
- /* xCreate */ fulltextCreate,
- /* xConnect */ fulltextConnect,
- /* xBestIndex */ fulltextBestIndex,
- /* xDisconnect */ fulltextDisconnect,
- /* xDestroy */ fulltextDestroy,
- /* xOpen */ fulltextOpen,
- /* xClose */ fulltextClose,
- /* xFilter */ fulltextFilter,
- /* xNext */ fulltextNext,
- /* xEof */ fulltextEof,
- /* xColumn */ fulltextColumn,
- /* xRowid */ fulltextRowid,
- /* xUpdate */ fulltextUpdate,
- /* xBegin */ fulltextBegin,
- /* xSync */ fulltextSync,
- /* xCommit */ fulltextCommit,
- /* xRollback */ fulltextRollback,
- /* xFindFunction */ fulltextFindFunction,
- /* xRename */ fulltextRename,
-};
-
-static void hashDestroy(void *p){
- fts2Hash *pHash = (fts2Hash *)p;
- sqlite3Fts2HashClear(pHash);
- sqlite3_free(pHash);
-}
-
-/*
-** The fts2 built-in tokenizers - "simple" and "porter" - are implemented
-** in files fts2_tokenizer1.c and fts2_porter.c respectively. The following
-** two forward declarations are for functions declared in these files
-** used to retrieve the respective implementations.
-**
-** Calling sqlite3Fts2SimpleTokenizerModule() sets the value pointed
-** to by the argument to point a the "simple" tokenizer implementation.
-** Function ...PorterTokenizerModule() sets *pModule to point to the
-** porter tokenizer/stemmer implementation.
-*/
-void sqlite3Fts2SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-void sqlite3Fts2PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-void sqlite3Fts2IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-
-int sqlite3Fts2InitHashTable(sqlite3 *, fts2Hash *, const char *);
-
-/*
-** Initialize the fts2 extension. If this extension is built as part
-** of the sqlite library, then this function is called directly by
-** SQLite. If fts2 is built as a dynamically loadable extension, this
-** function is called by the sqlite3_extension_init() entry point.
-*/
-int sqlite3Fts2Init(sqlite3 *db){
- int rc = SQLITE_OK;
- fts2Hash *pHash = 0;
- const sqlite3_tokenizer_module *pSimple = 0;
- const sqlite3_tokenizer_module *pPorter = 0;
- const sqlite3_tokenizer_module *pIcu = 0;
-
- sqlite3Fts2SimpleTokenizerModule(&pSimple);
- sqlite3Fts2PorterTokenizerModule(&pPorter);
-#ifdef SQLITE_ENABLE_ICU
- sqlite3Fts2IcuTokenizerModule(&pIcu);
-#endif
-
- /* Allocate and initialize the hash-table used to store tokenizers. */
- pHash = sqlite3_malloc(sizeof(fts2Hash));
- if( !pHash ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3Fts2HashInit(pHash, FTS2_HASH_STRING, 1);
- }
-
- /* Load the built-in tokenizers into the hash table */
- if( rc==SQLITE_OK ){
- if( sqlite3Fts2HashInsert(pHash, "simple", 7, (void *)pSimple)
- || sqlite3Fts2HashInsert(pHash, "porter", 7, (void *)pPorter)
- || (pIcu && sqlite3Fts2HashInsert(pHash, "icu", 4, (void *)pIcu))
- ){
- rc = SQLITE_NOMEM;
- }
- }
-
- /* Create the virtual table wrapper around the hash-table and overload
- ** the two scalar functions. If this is successful, register the
- ** module with sqlite.
- */
- if( SQLITE_OK==rc
- && SQLITE_OK==(rc = sqlite3Fts2InitHashTable(db, pHash, "fts2_tokenizer"))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", -1))
-#ifdef SQLITE_TEST
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "dump_terms", -1))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "dump_doclist", -1))
-#endif
- ){
- return sqlite3_create_module_v2(
- db, "fts2", &fts2Module, (void *)pHash, hashDestroy
- );
- }
-
- /* An error has occurred. Delete the hash table and return the error code. */
- assert( rc!=SQLITE_OK );
- if( pHash ){
- sqlite3Fts2HashClear(pHash);
- sqlite3_free(pHash);
- }
- return rc;
-}
-
-#if !SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fts2_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi)
- return sqlite3Fts2Init(db);
-}
-#endif
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2.h
deleted file mode 100644
index 4da4c3877b0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-** 2006 Oct 10
-**
-** 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 header file is used by programs that want to link against the
-** FTS2 library. All it does is declare the sqlite3Fts2Init() interface.
-*/
-#include "sqlite3.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int sqlite3Fts2Init(sqlite3 *db);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_hash.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_hash.c
deleted file mode 100644
index 3596dcf0b80..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_hash.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the implementation of generic hash-tables used in SQLite.
-** We've modified it slightly to serve as a standalone hash table
-** implementation for the full-text indexing module.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS2 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS2 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "sqlite3.h"
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT3
-#include "fts2_hash.h"
-
-/*
-** Malloc and Free functions
-*/
-static void *fts2HashMalloc(int n){
- void *p = sqlite3_malloc(n);
- if( p ){
- memset(p, 0, n);
- }
- return p;
-}
-static void fts2HashFree(void *p){
- sqlite3_free(p);
-}
-
-/* Turn bulk memory into a hash table object by initializing the
-** fields of the Hash structure.
-**
-** "pNew" is a pointer to the hash table that is to be initialized.
-** keyClass is one of the constants
-** FTS2_HASH_BINARY or FTS2_HASH_STRING. The value of keyClass
-** determines what kind of key the hash table will use. "copyKey" is
-** true if the hash table should make its own private copy of keys and
-** false if it should just use the supplied pointer.
-*/
-void sqlite3Fts2HashInit(fts2Hash *pNew, int keyClass, int copyKey){
- assert( pNew!=0 );
- assert( keyClass>=FTS2_HASH_STRING && keyClass<=FTS2_HASH_BINARY );
- pNew->keyClass = keyClass;
- pNew->copyKey = copyKey;
- pNew->first = 0;
- pNew->count = 0;
- pNew->htsize = 0;
- pNew->ht = 0;
-}
-
-/* Remove all entries from a hash table. Reclaim all memory.
-** Call this routine to delete a hash table or to reset a hash table
-** to the empty state.
-*/
-void sqlite3Fts2HashClear(fts2Hash *pH){
- fts2HashElem *elem; /* For looping over all elements of the table */
-
- assert( pH!=0 );
- elem = pH->first;
- pH->first = 0;
- fts2HashFree(pH->ht);
- pH->ht = 0;
- pH->htsize = 0;
- while( elem ){
- fts2HashElem *next_elem = elem->next;
- if( pH->copyKey && elem->pKey ){
- fts2HashFree(elem->pKey);
- }
- fts2HashFree(elem);
- elem = next_elem;
- }
- pH->count = 0;
-}
-
-/*
-** Hash and comparison functions when the mode is FTS2_HASH_STRING
-*/
-static int strHash(const void *pKey, int nKey){
- const char *z = (const char *)pKey;
- int h = 0;
- if( nKey<=0 ) nKey = (int) strlen(z);
- while( nKey > 0 ){
- h = (h<<3) ^ h ^ *z++;
- nKey--;
- }
- return h & 0x7fffffff;
-}
-static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return strncmp((const char*)pKey1,(const char*)pKey2,n1);
-}
-
-/*
-** Hash and comparison functions when the mode is FTS2_HASH_BINARY
-*/
-static int binHash(const void *pKey, int nKey){
- int h = 0;
- const char *z = (const char *)pKey;
- while( nKey-- > 0 ){
- h = (h<<3) ^ h ^ *(z++);
- }
- return h & 0x7fffffff;
-}
-static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return memcmp(pKey1,pKey2,n1);
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** The C syntax in this function definition may be unfamilar to some
-** programmers, so we provide the following additional explanation:
-**
-** The name of the function is "hashFunction". The function takes a
-** single parameter "keyClass". The return value of hashFunction()
-** is a pointer to another function. Specifically, the return value
-** of hashFunction() is a pointer to a function that takes two parameters
-** with types "const void*" and "int" and returns an "int".
-*/
-static int (*hashFunction(int keyClass))(const void*,int){
- if( keyClass==FTS2_HASH_STRING ){
- return &strHash;
- }else{
- assert( keyClass==FTS2_HASH_BINARY );
- return &binHash;
- }
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** For help in interpreted the obscure C code in the function definition,
-** see the header comment on the previous function.
-*/
-static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
- if( keyClass==FTS2_HASH_STRING ){
- return &strCompare;
- }else{
- assert( keyClass==FTS2_HASH_BINARY );
- return &binCompare;
- }
-}
-
-/* Link an element into the hash table
-*/
-static void insertElement(
- fts2Hash *pH, /* The complete hash table */
- struct _fts2ht *pEntry, /* The entry into which pNew is inserted */
- fts2HashElem *pNew /* The element to be inserted */
-){
- fts2HashElem *pHead; /* First element already in pEntry */
- pHead = pEntry->chain;
- if( pHead ){
- pNew->next = pHead;
- pNew->prev = pHead->prev;
- if( pHead->prev ){ pHead->prev->next = pNew; }
- else { pH->first = pNew; }
- pHead->prev = pNew;
- }else{
- pNew->next = pH->first;
- if( pH->first ){ pH->first->prev = pNew; }
- pNew->prev = 0;
- pH->first = pNew;
- }
- pEntry->count++;
- pEntry->chain = pNew;
-}
-
-
-/* Resize the hash table so that it cantains "new_size" buckets.
-** "new_size" must be a power of 2. The hash table might fail
-** to resize if sqliteMalloc() fails.
-*/
-static void rehash(fts2Hash *pH, int new_size){
- struct _fts2ht *new_ht; /* The new hash table */
- fts2HashElem *elem, *next_elem; /* For looping over existing elements */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( (new_size & (new_size-1))==0 );
- new_ht = (struct _fts2ht *)fts2HashMalloc( new_size*sizeof(struct _fts2ht) );
- if( new_ht==0 ) return;
- fts2HashFree(pH->ht);
- pH->ht = new_ht;
- pH->htsize = new_size;
- xHash = hashFunction(pH->keyClass);
- for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
- next_elem = elem->next;
- insertElement(pH, &new_ht[h], elem);
- }
-}
-
-/* This function (for internal use only) locates an element in an
-** hash table that matches the given key. The hash for this key has
-** already been computed and is passed as the 4th parameter.
-*/
-static fts2HashElem *findElementGivenHash(
- const fts2Hash *pH, /* The pH to be searched */
- const void *pKey, /* The key we are searching for */
- int nKey,
- int h /* The hash for this key. */
-){
- fts2HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- int (*xCompare)(const void*,int,const void*,int); /* comparison function */
-
- if( pH->ht ){
- struct _fts2ht *pEntry = &pH->ht[h];
- elem = pEntry->chain;
- count = pEntry->count;
- xCompare = compareFunction(pH->keyClass);
- while( count-- && elem ){
- if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- }
- return 0;
-}
-
-/* Remove a single entry from the hash table given a pointer to that
-** element and a hash on the element's key.
-*/
-static void removeElementGivenHash(
- fts2Hash *pH, /* The pH containing "elem" */
- fts2HashElem* elem, /* The element to be removed from the pH */
- int h /* Hash value for the element */
-){
- struct _fts2ht *pEntry;
- if( elem->prev ){
- elem->prev->next = elem->next;
- }else{
- pH->first = elem->next;
- }
- if( elem->next ){
- elem->next->prev = elem->prev;
- }
- pEntry = &pH->ht[h];
- if( pEntry->chain==elem ){
- pEntry->chain = elem->next;
- }
- pEntry->count--;
- if( pEntry->count<=0 ){
- pEntry->chain = 0;
- }
- if( pH->copyKey && elem->pKey ){
- fts2HashFree(elem->pKey);
- }
- fts2HashFree( elem );
- pH->count--;
- if( pH->count<=0 ){
- assert( pH->first==0 );
- assert( pH->count==0 );
- fts2HashClear(pH);
- }
-}
-
-/* Attempt to locate an element of the hash table pH with a key
-** that matches pKey,nKey. Return the data for this element if it is
-** found, or NULL if there is no match.
-*/
-void *sqlite3Fts2HashFind(const fts2Hash *pH, const void *pKey, int nKey){
- int h; /* A hash on key */
- fts2HashElem *elem; /* The element that matches key */
- int (*xHash)(const void*,int); /* The hash function */
-
- if( pH==0 || pH->ht==0 ) return 0;
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- h = (*xHash)(pKey,nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
- return elem ? elem->data : 0;
-}
-
-/* Insert an element into the hash table pH. The key is pKey,nKey
-** and the data is "data".
-**
-** If no element exists with a matching key, then a new
-** element is created. A copy of the key is made if the copyKey
-** flag is set. NULL is returned.
-**
-** If another element already exists with the same key, then the
-** new data replaces the old data and the old data is returned.
-** The key is not copied in this instance. If a malloc fails, then
-** the new data is returned and the hash table is unchanged.
-**
-** If the "data" parameter to this function is NULL, then the
-** element corresponding to "key" is removed from the hash table.
-*/
-void *sqlite3Fts2HashInsert(
- fts2Hash *pH, /* The hash table to insert into */
- const void *pKey, /* The key */
- int nKey, /* Number of bytes in the key */
- void *data /* The data */
-){
- int hraw; /* Raw hash value of the key */
- int h; /* the hash of the key modulo hash table size */
- fts2HashElem *elem; /* Used to loop thru the element list */
- fts2HashElem *new_elem; /* New element added to the pH */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( pH!=0 );
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- hraw = (*xHash)(pKey, nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = findElementGivenHash(pH,pKey,nKey,h);
- if( elem ){
- void *old_data = elem->data;
- if( data==0 ){
- removeElementGivenHash(pH,elem,h);
- }else{
- elem->data = data;
- }
- return old_data;
- }
- if( data==0 ) return 0;
- new_elem = (fts2HashElem*)fts2HashMalloc( sizeof(fts2HashElem) );
- if( new_elem==0 ) return data;
- if( pH->copyKey && pKey!=0 ){
- new_elem->pKey = fts2HashMalloc( nKey );
- if( new_elem->pKey==0 ){
- fts2HashFree(new_elem);
- return data;
- }
- memcpy((void*)new_elem->pKey, pKey, nKey);
- }else{
- new_elem->pKey = (void*)pKey;
- }
- new_elem->nKey = nKey;
- pH->count++;
- if( pH->htsize==0 ){
- rehash(pH,8);
- if( pH->htsize==0 ){
- pH->count = 0;
- fts2HashFree(new_elem);
- return data;
- }
- }
- if( pH->count > pH->htsize ){
- rehash(pH,pH->htsize*2);
- }
- assert( pH->htsize>0 );
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- insertElement(pH, &pH->ht[h], new_elem);
- new_elem->data = data;
- return 0;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_hash.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_hash.h
deleted file mode 100644
index 02936f18bba..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_hash.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the header file for the generic hash-table implementation
-** used in SQLite. We've modified it slightly to serve as a standalone
-** hash table implementation for the full-text indexing module.
-**
-*/
-#ifndef _FTS2_HASH_H_
-#define _FTS2_HASH_H_
-
-/* Forward declarations of structures. */
-typedef struct fts2Hash fts2Hash;
-typedef struct fts2HashElem fts2HashElem;
-
-/* A complete hash table is an instance of the following structure.
-** The internals of this structure are intended to be opaque -- client
-** code should not attempt to access or modify the fields of this structure
-** directly. Change this structure only by using the routines below.
-** However, many of the "procedures" and "functions" for modifying and
-** accessing this structure are really macros, so we can't really make
-** this structure opaque.
-*/
-struct fts2Hash {
- char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */
- char copyKey; /* True if copy of key made on insert */
- int count; /* Number of entries in this table */
- fts2HashElem *first; /* The first element of the array */
- int htsize; /* Number of buckets in the hash table */
- struct _fts2ht { /* the hash table */
- int count; /* Number of entries with this hash */
- fts2HashElem *chain; /* Pointer to first entry with this hash */
- } *ht;
-};
-
-/* Each element in the hash table is an instance of the following
-** structure. All elements are stored on a single doubly-linked list.
-**
-** Again, this structure is intended to be opaque, but it can't really
-** be opaque because it is used by macros.
-*/
-struct fts2HashElem {
- fts2HashElem *next, *prev; /* Next and previous elements in the table */
- void *data; /* Data associated with this element */
- void *pKey; int nKey; /* Key associated with this element */
-};
-
-/*
-** There are 2 different modes of operation for a hash table:
-**
-** FTS2_HASH_STRING pKey points to a string that is nKey bytes long
-** (including the null-terminator, if any). Case
-** is respected in comparisons.
-**
-** FTS2_HASH_BINARY pKey points to binary data nKey bytes long.
-** memcmp() is used to compare keys.
-**
-** A copy of the key is made if the copyKey parameter to fts2HashInit is 1.
-*/
-#define FTS2_HASH_STRING 1
-#define FTS2_HASH_BINARY 2
-
-/*
-** Access routines. To delete, insert a NULL pointer.
-*/
-void sqlite3Fts2HashInit(fts2Hash*, int keytype, int copyKey);
-void *sqlite3Fts2HashInsert(fts2Hash*, const void *pKey, int nKey, void *pData);
-void *sqlite3Fts2HashFind(const fts2Hash*, const void *pKey, int nKey);
-void sqlite3Fts2HashClear(fts2Hash*);
-
-/*
-** Shorthand for the functions above
-*/
-#define fts2HashInit sqlite3Fts2HashInit
-#define fts2HashInsert sqlite3Fts2HashInsert
-#define fts2HashFind sqlite3Fts2HashFind
-#define fts2HashClear sqlite3Fts2HashClear
-
-/*
-** Macros for looping over all elements of a hash table. The idiom is
-** like this:
-**
-** fts2Hash h;
-** fts2HashElem *p;
-** ...
-** for(p=fts2HashFirst(&h); p; p=fts2HashNext(p)){
-** SomeStructure *pData = fts2HashData(p);
-** // do something with pData
-** }
-*/
-#define fts2HashFirst(H) ((H)->first)
-#define fts2HashNext(E) ((E)->next)
-#define fts2HashData(E) ((E)->data)
-#define fts2HashKey(E) ((E)->pKey)
-#define fts2HashKeysize(E) ((E)->nKey)
-
-/*
-** Number of entries in a hash table
-*/
-#define fts2HashCount(H) ((H)->count)
-
-#endif /* _FTS2_HASH_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_icu.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_icu.c
deleted file mode 100644
index 2670301f519..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_icu.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
-** 2007 June 22
-**
-** 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 a tokenizer for fts2 based on the ICU library.
-**
-** $Id: fts2_icu.c,v 1.3 2008/12/18 05:30:26 danielk1977 Exp $
-*/
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)
-#ifdef SQLITE_ENABLE_ICU
-
-#include <assert.h>
-#include <string.h>
-#include "fts2_tokenizer.h"
-
-#include <unicode/ubrk.h>
-#include <unicode/ucol.h>
-#include <unicode/ustring.h>
-#include <unicode/utf16.h>
-
-typedef struct IcuTokenizer IcuTokenizer;
-typedef struct IcuCursor IcuCursor;
-
-struct IcuTokenizer {
- sqlite3_tokenizer base;
- char *zLocale;
-};
-
-struct IcuCursor {
- sqlite3_tokenizer_cursor base;
-
- UBreakIterator *pIter; /* ICU break-iterator object */
- int nChar; /* Number of UChar elements in pInput */
- UChar *aChar; /* Copy of input using utf-16 encoding */
- int *aOffset; /* Offsets of each character in utf-8 input */
-
- int nBuffer;
- char *zBuffer;
-
- int iToken;
-};
-
-/*
-** Create a new tokenizer instance.
-*/
-static int icuCreate(
- int argc, /* Number of entries in argv[] */
- const char * const *argv, /* Tokenizer creation arguments */
- sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
-){
- IcuTokenizer *p;
- int n = 0;
-
- if( argc>0 ){
- n = strlen(argv[0])+1;
- }
- p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
- if( !p ){
- return SQLITE_NOMEM;
- }
- memset(p, 0, sizeof(IcuTokenizer));
-
- if( n ){
- p->zLocale = (char *)&p[1];
- memcpy(p->zLocale, argv[0], n);
- }
-
- *ppTokenizer = (sqlite3_tokenizer *)p;
-
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int icuDestroy(sqlite3_tokenizer *pTokenizer){
- IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int icuOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *zInput, /* Input string */
- int nInput, /* Length of zInput in bytes */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
- IcuCursor *pCsr;
-
- const int32_t opt = U_FOLD_CASE_DEFAULT;
- UErrorCode status = U_ZERO_ERROR;
- int nChar;
-
- UChar32 c;
- int iInput = 0;
- int iOut = 0;
-
- *ppCursor = 0;
-
- if( nInput<0 ){
- nInput = strlen(zInput);
- }
- nChar = nInput+1;
- pCsr = (IcuCursor *)sqlite3_malloc(
- sizeof(IcuCursor) + /* IcuCursor */
- ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
- (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
- );
- if( !pCsr ){
- return SQLITE_NOMEM;
- }
- memset(pCsr, 0, sizeof(IcuCursor));
- pCsr->aChar = (UChar *)&pCsr[1];
- pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
-
- pCsr->aOffset[iOut] = iInput;
- U8_NEXT(zInput, iInput, nInput, c);
- while( c>0 ){
- int isError = 0;
- c = u_foldCase(c, opt);
- U16_APPEND(pCsr->aChar, iOut, nChar, c, isError);
- if( isError ){
- sqlite3_free(pCsr);
- return SQLITE_ERROR;
- }
- pCsr->aOffset[iOut] = iInput;
-
- if( iInput<nInput ){
- U8_NEXT(zInput, iInput, nInput, c);
- }else{
- c = 0;
- }
- }
-
- pCsr->pIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status);
- if( !U_SUCCESS(status) ){
- sqlite3_free(pCsr);
- return SQLITE_ERROR;
- }
- pCsr->nChar = iOut;
-
- ubrk_first(pCsr->pIter);
- *ppCursor = (sqlite3_tokenizer_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to icuOpen().
-*/
-static int icuClose(sqlite3_tokenizer_cursor *pCursor){
- IcuCursor *pCsr = (IcuCursor *)pCursor;
- ubrk_close(pCsr->pIter);
- sqlite3_free(pCsr->zBuffer);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Extract the next token from a tokenization cursor.
-*/
-static int icuNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
- const char **ppToken, /* OUT: *ppToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- IcuCursor *pCsr = (IcuCursor *)pCursor;
-
- int iStart = 0;
- int iEnd = 0;
- int nByte = 0;
-
- while( iStart==iEnd ){
- UChar32 c;
-
- iStart = ubrk_current(pCsr->pIter);
- iEnd = ubrk_next(pCsr->pIter);
- if( iEnd==UBRK_DONE ){
- return SQLITE_DONE;
- }
-
- while( iStart<iEnd ){
- int iWhite = iStart;
- U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
- if( u_isspace(c) ){
- iStart = iWhite;
- }else{
- break;
- }
- }
- assert(iStart<=iEnd);
- }
-
- do {
- UErrorCode status = U_ZERO_ERROR;
- if( nByte ){
- char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- pCsr->zBuffer = zNew;
- pCsr->nBuffer = nByte;
- }
-
- u_strToUTF8(
- pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */
- &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */
- &status /* Output success/failure */
- );
- } while( nByte>pCsr->nBuffer );
-
- *ppToken = pCsr->zBuffer;
- *pnBytes = nByte;
- *piStartOffset = pCsr->aOffset[iStart];
- *piEndOffset = pCsr->aOffset[iEnd];
- *piPosition = pCsr->iToken++;
-
- return SQLITE_OK;
-}
-
-/*
-** The set of routines that implement the simple tokenizer
-*/
-static const sqlite3_tokenizer_module icuTokenizerModule = {
- 0, /* iVersion */
- icuCreate, /* xCreate */
- icuDestroy, /* xCreate */
- icuOpen, /* xOpen */
- icuClose, /* xClose */
- icuNext, /* xNext */
-};
-
-/*
-** Set *ppModule to point at the implementation of the ICU tokenizer.
-*/
-void sqlite3Fts2IcuTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &icuTokenizerModule;
-}
-
-#endif /* defined(SQLITE_ENABLE_ICU) */
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_porter.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_porter.c
deleted file mode 100644
index 881baf7100f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_porter.c
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
-** 2006 September 30
-**
-** 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.
-**
-*************************************************************************
-** Implementation of the full-text-search tokenizer that implements
-** a Porter stemmer.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS2 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS2 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)
-
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "sqlite3.h"
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT3
-#include "fts2_tokenizer.h"
-
-/*
-** Class derived from sqlite3_tokenizer
-*/
-typedef struct porter_tokenizer {
- sqlite3_tokenizer base; /* Base class */
-} porter_tokenizer;
-
-/*
-** Class derived from sqlit3_tokenizer_cursor
-*/
-typedef struct porter_tokenizer_cursor {
- sqlite3_tokenizer_cursor base;
- const char *zInput; /* input we are tokenizing */
- int nInput; /* size of the input */
- int iOffset; /* current position in zInput */
- int iToken; /* index of next token to be returned */
- char *zToken; /* storage for current token */
- int nAllocated; /* space allocated to zToken buffer */
-} porter_tokenizer_cursor;
-
-
-/* Forward declaration */
-static const sqlite3_tokenizer_module porterTokenizerModule;
-
-
-/*
-** Create a new tokenizer instance.
-*/
-static int porterCreate(
- int argc, const char * const *argv,
- sqlite3_tokenizer **ppTokenizer
-){
- porter_tokenizer *t;
- t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t));
- if( t==NULL ) return SQLITE_NOMEM;
- memset(t, 0, sizeof(*t));
- *ppTokenizer = &t->base;
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int porterDestroy(sqlite3_tokenizer *pTokenizer){
- sqlite3_free(pTokenizer);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is zInput[0..nInput-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int porterOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *zInput, int nInput, /* String to be tokenized */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- porter_tokenizer_cursor *c;
-
- c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
- if( c==NULL ) return SQLITE_NOMEM;
-
- c->zInput = zInput;
- if( zInput==0 ){
- c->nInput = 0;
- }else if( nInput<0 ){
- c->nInput = (int)strlen(zInput);
- }else{
- c->nInput = nInput;
- }
- c->iOffset = 0; /* start tokenizing at the beginning */
- c->iToken = 0;
- c->zToken = NULL; /* no space allocated, yet. */
- c->nAllocated = 0;
-
- *ppCursor = &c->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to
-** porterOpen() above.
-*/
-static int porterClose(sqlite3_tokenizer_cursor *pCursor){
- porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
- sqlite3_free(c->zToken);
- sqlite3_free(c);
- return SQLITE_OK;
-}
-/*
-** Vowel or consonant
-*/
-static const char cType[] = {
- 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
- 1, 1, 1, 2, 1
-};
-
-/*
-** isConsonant() and isVowel() determine if their first character in
-** the string they point to is a consonant or a vowel, according
-** to Porter ruls.
-**
-** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
-** 'Y' is a consonant unless it follows another consonant,
-** in which case it is a vowel.
-**
-** In these routine, the letters are in reverse order. So the 'y' rule
-** is that 'y' is a consonant unless it is followed by another
-** consonent.
-*/
-static int isVowel(const char*);
-static int isConsonant(const char *z){
- int j;
- char x = *z;
- if( x==0 ) return 0;
- assert( x>='a' && x<='z' );
- j = cType[x-'a'];
- if( j<2 ) return j;
- return z[1]==0 || isVowel(z + 1);
-}
-static int isVowel(const char *z){
- int j;
- char x = *z;
- if( x==0 ) return 0;
- assert( x>='a' && x<='z' );
- j = cType[x-'a'];
- if( j<2 ) return 1-j;
- return isConsonant(z + 1);
-}
-
-/*
-** Let any sequence of one or more vowels be represented by V and let
-** C be sequence of one or more consonants. Then every word can be
-** represented as:
-**
-** [C] (VC){m} [V]
-**
-** In prose: A word is an optional consonant followed by zero or
-** vowel-consonant pairs followed by an optional vowel. "m" is the
-** number of vowel consonant pairs. This routine computes the value
-** of m for the first i bytes of a word.
-**
-** Return true if the m-value for z is 1 or more. In other words,
-** return true if z contains at least one vowel that is followed
-** by a consonant.
-**
-** In this routine z[] is in reverse order. So we are really looking
-** for an instance of of a consonant followed by a vowel.
-*/
-static int m_gt_0(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/* Like mgt0 above except we are looking for a value of m which is
-** exactly 1
-*/
-static int m_eq_1(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 1;
- while( isConsonant(z) ){ z++; }
- return *z==0;
-}
-
-/* Like mgt0 above except we are looking for a value of m>1 instead
-** or m>0
-*/
-static int m_gt_1(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/*
-** Return TRUE if there is a vowel anywhere within z[0..n-1]
-*/
-static int hasVowel(const char *z){
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/*
-** Return TRUE if the word ends in a double consonant.
-**
-** The text is reversed here. So we are really looking at
-** the first two characters of z[].
-*/
-static int doubleConsonant(const char *z){
- return isConsonant(z) && z[0]==z[1] && isConsonant(z+1);
-}
-
-/*
-** Return TRUE if the word ends with three letters which
-** are consonant-vowel-consonent and where the final consonant
-** is not 'w', 'x', or 'y'.
-**
-** The word is reversed here. So we are really checking the
-** first three letters and the first one cannot be in [wxy].
-*/
-static int star_oh(const char *z){
- return
- z[0]!=0 && isConsonant(z) &&
- z[0]!='w' && z[0]!='x' && z[0]!='y' &&
- z[1]!=0 && isVowel(z+1) &&
- z[2]!=0 && isConsonant(z+2);
-}
-
-/*
-** If the word ends with zFrom and xCond() is true for the stem
-** of the word that preceeds the zFrom ending, then change the
-** ending to zTo.
-**
-** The input word *pz and zFrom are both in reverse order. zTo
-** is in normal order.
-**
-** Return TRUE if zFrom matches. Return FALSE if zFrom does not
-** match. Not that TRUE is returned even if xCond() fails and
-** no substitution occurs.
-*/
-static int stem(
- char **pz, /* The word being stemmed (Reversed) */
- const char *zFrom, /* If the ending matches this... (Reversed) */
- const char *zTo, /* ... change the ending to this (not reversed) */
- int (*xCond)(const char*) /* Condition that must be true */
-){
- char *z = *pz;
- while( *zFrom && *zFrom==*z ){ z++; zFrom++; }
- if( *zFrom!=0 ) return 0;
- if( xCond && !xCond(z) ) return 1;
- while( *zTo ){
- *(--z) = *(zTo++);
- }
- *pz = z;
- return 1;
-}
-
-/*
-** This is the fallback stemmer used when the porter stemmer is
-** inappropriate. The input word is copied into the output with
-** US-ASCII case folding. If the input word is too long (more
-** than 20 bytes if it contains no digits or more than 6 bytes if
-** it contains digits) then word is truncated to 20 or 6 bytes
-** by taking 10 or 3 bytes from the beginning and end.
-*/
-static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
- int i, mx, j;
- int hasDigit = 0;
- for(i=0; i<nIn; i++){
- int c = zIn[i];
- if( c>='A' && c<='Z' ){
- zOut[i] = c - 'A' + 'a';
- }else{
- if( c>='0' && c<='9' ) hasDigit = 1;
- zOut[i] = c;
- }
- }
- mx = hasDigit ? 3 : 10;
- if( nIn>mx*2 ){
- for(j=mx, i=nIn-mx; i<nIn; i++, j++){
- zOut[j] = zOut[i];
- }
- i = j;
- }
- zOut[i] = 0;
- *pnOut = i;
-}
-
-
-/*
-** Stem the input word zIn[0..nIn-1]. Store the output in zOut.
-** zOut is at least big enough to hold nIn bytes. Write the actual
-** size of the output word (exclusive of the '\0' terminator) into *pnOut.
-**
-** Any upper-case characters in the US-ASCII character set ([A-Z])
-** are converted to lower case. Upper-case UTF characters are
-** unchanged.
-**
-** Words that are longer than about 20 bytes are stemmed by retaining
-** a few bytes from the beginning and the end of the word. If the
-** word contains digits, 3 bytes are taken from the beginning and
-** 3 bytes from the end. For long words without digits, 10 bytes
-** are taken from each end. US-ASCII case folding still applies.
-**
-** If the input word contains not digits but does characters not
-** in [a-zA-Z] then no stemming is attempted and this routine just
-** copies the input into the input into the output with US-ASCII
-** case folding.
-**
-** Stemming never increases the length of the word. So there is
-** no chance of overflowing the zOut buffer.
-*/
-static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
- int i, j, c;
- char zReverse[28];
- char *z, *z2;
- if( nIn<3 || nIn>=sizeof(zReverse)-7 ){
- /* The word is too big or too small for the porter stemmer.
- ** Fallback to the copy stemmer */
- copy_stemmer(zIn, nIn, zOut, pnOut);
- return;
- }
- for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){
- c = zIn[i];
- if( c>='A' && c<='Z' ){
- zReverse[j] = c + 'a' - 'A';
- }else if( c>='a' && c<='z' ){
- zReverse[j] = c;
- }else{
- /* The use of a character not in [a-zA-Z] means that we fallback
- ** to the copy stemmer */
- copy_stemmer(zIn, nIn, zOut, pnOut);
- return;
- }
- }
- memset(&zReverse[sizeof(zReverse)-5], 0, 5);
- z = &zReverse[j+1];
-
-
- /* Step 1a */
- if( z[0]=='s' ){
- if(
- !stem(&z, "sess", "ss", 0) &&
- !stem(&z, "sei", "i", 0) &&
- !stem(&z, "ss", "ss", 0)
- ){
- z++;
- }
- }
-
- /* Step 1b */
- z2 = z;
- if( stem(&z, "dee", "ee", m_gt_0) ){
- /* Do nothing. The work was all in the test */
- }else if(
- (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel))
- && z!=z2
- ){
- if( stem(&z, "ta", "ate", 0) ||
- stem(&z, "lb", "ble", 0) ||
- stem(&z, "zi", "ize", 0) ){
- /* Do nothing. The work was all in the test */
- }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){
- z++;
- }else if( m_eq_1(z) && star_oh(z) ){
- *(--z) = 'e';
- }
- }
-
- /* Step 1c */
- if( z[0]=='y' && hasVowel(z+1) ){
- z[0] = 'i';
- }
-
- /* Step 2 */
- switch( z[1] ){
- case 'a':
- stem(&z, "lanoita", "ate", m_gt_0) ||
- stem(&z, "lanoit", "tion", m_gt_0);
- break;
- case 'c':
- stem(&z, "icne", "ence", m_gt_0) ||
- stem(&z, "icna", "ance", m_gt_0);
- break;
- case 'e':
- stem(&z, "rezi", "ize", m_gt_0);
- break;
- case 'g':
- stem(&z, "igol", "log", m_gt_0);
- break;
- case 'l':
- stem(&z, "ilb", "ble", m_gt_0) ||
- stem(&z, "illa", "al", m_gt_0) ||
- stem(&z, "iltne", "ent", m_gt_0) ||
- stem(&z, "ile", "e", m_gt_0) ||
- stem(&z, "ilsuo", "ous", m_gt_0);
- break;
- case 'o':
- stem(&z, "noitazi", "ize", m_gt_0) ||
- stem(&z, "noita", "ate", m_gt_0) ||
- stem(&z, "rota", "ate", m_gt_0);
- break;
- case 's':
- stem(&z, "msila", "al", m_gt_0) ||
- stem(&z, "ssenevi", "ive", m_gt_0) ||
- stem(&z, "ssenluf", "ful", m_gt_0) ||
- stem(&z, "ssensuo", "ous", m_gt_0);
- break;
- case 't':
- stem(&z, "itila", "al", m_gt_0) ||
- stem(&z, "itivi", "ive", m_gt_0) ||
- stem(&z, "itilib", "ble", m_gt_0);
- break;
- }
-
- /* Step 3 */
- switch( z[0] ){
- case 'e':
- stem(&z, "etaci", "ic", m_gt_0) ||
- stem(&z, "evita", "", m_gt_0) ||
- stem(&z, "ezila", "al", m_gt_0);
- break;
- case 'i':
- stem(&z, "itici", "ic", m_gt_0);
- break;
- case 'l':
- stem(&z, "laci", "ic", m_gt_0) ||
- stem(&z, "luf", "", m_gt_0);
- break;
- case 's':
- stem(&z, "ssen", "", m_gt_0);
- break;
- }
-
- /* Step 4 */
- switch( z[1] ){
- case 'a':
- if( z[0]=='l' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'c':
- if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){
- z += 4;
- }
- break;
- case 'e':
- if( z[0]=='r' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'i':
- if( z[0]=='c' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'l':
- if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){
- z += 4;
- }
- break;
- case 'n':
- if( z[0]=='t' ){
- if( z[2]=='a' ){
- if( m_gt_1(z+3) ){
- z += 3;
- }
- }else if( z[2]=='e' ){
- stem(&z, "tneme", "", m_gt_1) ||
- stem(&z, "tnem", "", m_gt_1) ||
- stem(&z, "tne", "", m_gt_1);
- }
- }
- break;
- case 'o':
- if( z[0]=='u' ){
- if( m_gt_1(z+2) ){
- z += 2;
- }
- }else if( z[3]=='s' || z[3]=='t' ){
- stem(&z, "noi", "", m_gt_1);
- }
- break;
- case 's':
- if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- case 't':
- stem(&z, "eta", "", m_gt_1) ||
- stem(&z, "iti", "", m_gt_1);
- break;
- case 'u':
- if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- case 'v':
- case 'z':
- if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- }
-
- /* Step 5a */
- if( z[0]=='e' ){
- if( m_gt_1(z+1) ){
- z++;
- }else if( m_eq_1(z+1) && !star_oh(z+1) ){
- z++;
- }
- }
-
- /* Step 5b */
- if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){
- z++;
- }
-
- /* z[] is now the stemmed word in reverse order. Flip it back
- ** around into forward order and return.
- */
- *pnOut = i = strlen(z);
- zOut[i] = 0;
- while( *z ){
- zOut[--i] = *(z++);
- }
-}
-
-/*
-** Characters that can be part of a token. We assume any character
-** whose value is greater than 0x80 (any UTF character) can be
-** part of a token. In other words, delimiters all must have
-** values of 0x7f or lower.
-*/
-static const char porterIdChar[] = {
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
-};
-#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30]))
-
-/*
-** Extract the next token from a tokenization cursor. The cursor must
-** have been opened by a prior call to porterOpen().
-*/
-static int porterNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */
- const char **pzToken, /* OUT: *pzToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
- const char *z = c->zInput;
-
- while( c->iOffset<c->nInput ){
- int iStartOffset, ch;
-
- /* Scan past delimiter characters */
- while( c->iOffset<c->nInput && isDelim(z[c->iOffset]) ){
- c->iOffset++;
- }
-
- /* Count non-delimiter characters. */
- iStartOffset = c->iOffset;
- while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
- c->iOffset++;
- }
-
- if( c->iOffset>iStartOffset ){
- int n = c->iOffset-iStartOffset;
- if( n>c->nAllocated ){
- c->nAllocated = n+20;
- c->zToken = sqlite3_realloc(c->zToken, c->nAllocated);
- if( c->zToken==NULL ) return SQLITE_NOMEM;
- }
- porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
- *pzToken = c->zToken;
- *piStartOffset = iStartOffset;
- *piEndOffset = c->iOffset;
- *piPosition = c->iToken++;
- return SQLITE_OK;
- }
- }
- return SQLITE_DONE;
-}
-
-/*
-** The set of routines that implement the porter-stemmer tokenizer
-*/
-static const sqlite3_tokenizer_module porterTokenizerModule = {
- 0,
- porterCreate,
- porterDestroy,
- porterOpen,
- porterClose,
- porterNext,
-};
-
-/*
-** Allocate a new porter tokenizer. Return a pointer to the new
-** tokenizer in *ppModule
-*/
-void sqlite3Fts2PorterTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &porterTokenizerModule;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer.c
deleted file mode 100644
index dda33a72d26..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
-** 2007 June 22
-**
-** 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 is part of an SQLite module implementing full-text search.
-** This particular file implements the generic tokenizer interface.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS2 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS2 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)
-
-
-#include "sqlite3.h"
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT3
-
-#include "fts2_hash.h"
-#include "fts2_tokenizer.h"
-#include <assert.h>
-
-/*
-** Implementation of the SQL scalar function for accessing the underlying
-** hash table. This function may be called as follows:
-**
-** SELECT <function-name>(<key-name>);
-** SELECT <function-name>(<key-name>, <pointer>);
-**
-** where <function-name> is the name passed as the second argument
-** to the sqlite3Fts2InitHashTable() function (e.g. 'fts2_tokenizer').
-**
-** If the <pointer> argument is specified, it must be a blob value
-** containing a pointer to be stored as the hash data corresponding
-** to the string <key-name>. If <pointer> is not specified, then
-** the string <key-name> must already exist in the has table. Otherwise,
-** an error is returned.
-**
-** Whether or not the <pointer> argument is specified, the value returned
-** is a blob containing the pointer stored as the hash data corresponding
-** to string <key-name> (after the hash-table is updated, if applicable).
-*/
-static void scalarFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- fts2Hash *pHash;
- void *pPtr = 0;
- const unsigned char *zName;
- int nName;
-
- assert( argc==1 || argc==2 );
-
- pHash = (fts2Hash *)sqlite3_user_data(context);
-
- zName = sqlite3_value_text(argv[0]);
- nName = sqlite3_value_bytes(argv[0])+1;
-
- if( argc==2 ){
- void *pOld;
- int n = sqlite3_value_bytes(argv[1]);
- if( n!=sizeof(pPtr) ){
- sqlite3_result_error(context, "argument type mismatch", -1);
- return;
- }
- pPtr = *(void **)sqlite3_value_blob(argv[1]);
- pOld = sqlite3Fts2HashInsert(pHash, (void *)zName, nName, pPtr);
- if( pOld==pPtr ){
- sqlite3_result_error(context, "out of memory", -1);
- return;
- }
- }else{
- pPtr = sqlite3Fts2HashFind(pHash, zName, nName);
- if( !pPtr ){
- char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- return;
- }
- }
-
- sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
-}
-
-#ifdef SQLITE_TEST
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <string.h>
-
-/*
-** Implementation of a special SQL scalar function for testing tokenizers
-** designed to be used in concert with the Tcl testing framework. This
-** function must be called with two arguments:
-**
-** SELECT <function-name>(<key-name>, <input-string>);
-** SELECT <function-name>(<key-name>, <pointer>);
-**
-** where <function-name> is the name passed as the second argument
-** to the sqlite3Fts2InitHashTable() function (e.g. 'fts2_tokenizer')
-** concatenated with the string '_test' (e.g. 'fts2_tokenizer_test').
-**
-** The return value is a string that may be interpreted as a Tcl
-** list. For each token in the <input-string>, three elements are
-** added to the returned list. The first is the token position, the
-** second is the token text (folded, stemmed, etc.) and the third is the
-** substring of <input-string> associated with the token. For example,
-** using the built-in "simple" tokenizer:
-**
-** SELECT fts_tokenizer_test('simple', 'I don't see how');
-**
-** will return the string:
-**
-** "{0 i I 1 dont don't 2 see see 3 how how}"
-**
-*/
-static void testFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- fts2Hash *pHash;
- sqlite3_tokenizer_module *p;
- sqlite3_tokenizer *pTokenizer = 0;
- sqlite3_tokenizer_cursor *pCsr = 0;
-
- const char *zErr = 0;
-
- const char *zName;
- int nName;
- const char *zInput;
- int nInput;
-
- const char *zArg = 0;
-
- const char *zToken;
- int nToken;
- int iStart;
- int iEnd;
- int iPos;
-
- Tcl_Obj *pRet;
-
- assert( argc==2 || argc==3 );
-
- nName = sqlite3_value_bytes(argv[0]);
- zName = (const char *)sqlite3_value_text(argv[0]);
- nInput = sqlite3_value_bytes(argv[argc-1]);
- zInput = (const char *)sqlite3_value_text(argv[argc-1]);
-
- if( argc==3 ){
- zArg = (const char *)sqlite3_value_text(argv[1]);
- }
-
- pHash = (fts2Hash *)sqlite3_user_data(context);
- p = (sqlite3_tokenizer_module *)sqlite3Fts2HashFind(pHash, zName, nName+1);
-
- if( !p ){
- char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- return;
- }
-
- pRet = Tcl_NewObj();
- Tcl_IncrRefCount(pRet);
-
- if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){
- zErr = "error in xCreate()";
- goto finish;
- }
- pTokenizer->pModule = p;
- if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){
- zErr = "error in xOpen()";
- goto finish;
- }
- pCsr->pTokenizer = pTokenizer;
-
- while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
- zToken = &zInput[iStart];
- nToken = iEnd-iStart;
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
- }
-
- if( SQLITE_OK!=p->xClose(pCsr) ){
- zErr = "error in xClose()";
- goto finish;
- }
- if( SQLITE_OK!=p->xDestroy(pTokenizer) ){
- zErr = "error in xDestroy()";
- goto finish;
- }
-
-finish:
- if( zErr ){
- sqlite3_result_error(context, zErr, -1);
- }else{
- sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT);
- }
- Tcl_DecrRefCount(pRet);
-}
-
-static
-int registerTokenizer(
- sqlite3 *db,
- char *zName,
- const sqlite3_tokenizer_module *p
-){
- int rc;
- sqlite3_stmt *pStmt;
- const char zSql[] = "SELECT fts2_tokenizer(?, ?)";
-
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
- sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC);
- sqlite3_step(pStmt);
-
- return sqlite3_finalize(pStmt);
-}
-
-static
-int queryFts2Tokenizer(
- sqlite3 *db,
- char *zName,
- const sqlite3_tokenizer_module **pp
-){
- int rc;
- sqlite3_stmt *pStmt;
- const char zSql[] = "SELECT fts2_tokenizer(?)";
-
- *pp = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
- memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
- }
- }
-
- return sqlite3_finalize(pStmt);
-}
-
-void sqlite3Fts2SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-
-/*
-** Implementation of the scalar function fts2_tokenizer_internal_test().
-** This function is used for testing only, it is not included in the
-** build unless SQLITE_TEST is defined.
-**
-** The purpose of this is to test that the fts2_tokenizer() function
-** can be used as designed by the C-code in the queryFts2Tokenizer and
-** registerTokenizer() functions above. These two functions are repeated
-** in the README.tokenizer file as an example, so it is important to
-** test them.
-**
-** To run the tests, evaluate the fts2_tokenizer_internal_test() scalar
-** function with no arguments. An assert() will fail if a problem is
-** detected. i.e.:
-**
-** SELECT fts2_tokenizer_internal_test();
-**
-*/
-static void intTestFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int rc;
- const sqlite3_tokenizer_module *p1;
- const sqlite3_tokenizer_module *p2;
- sqlite3 *db = (sqlite3 *)sqlite3_user_data(context);
-
- /* Test the query function */
- sqlite3Fts2SimpleTokenizerModule(&p1);
- rc = queryFts2Tokenizer(db, "simple", &p2);
- assert( rc==SQLITE_OK );
- assert( p1==p2 );
- rc = queryFts2Tokenizer(db, "nosuchtokenizer", &p2);
- assert( rc==SQLITE_ERROR );
- assert( p2==0 );
- assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") );
-
- /* Test the storage function */
- rc = registerTokenizer(db, "nosuchtokenizer", p1);
- assert( rc==SQLITE_OK );
- rc = queryFts2Tokenizer(db, "nosuchtokenizer", &p2);
- assert( rc==SQLITE_OK );
- assert( p2==p1 );
-
- sqlite3_result_text(context, "ok", -1, SQLITE_STATIC);
-}
-
-#endif
-
-/*
-** Set up SQL objects in database db used to access the contents of
-** the hash table pointed to by argument pHash. The hash table must
-** been initialized to use string keys, and to take a private copy
-** of the key when a value is inserted. i.e. by a call similar to:
-**
-** sqlite3Fts2HashInit(pHash, FTS2_HASH_STRING, 1);
-**
-** This function adds a scalar function (see header comment above
-** scalarFunc() in this file for details) and, if ENABLE_TABLE is
-** defined at compilation time, a temporary virtual table (see header
-** comment above struct HashTableVtab) to the database schema. Both
-** provide read/write access to the contents of *pHash.
-**
-** The third argument to this function, zName, is used as the name
-** of both the scalar and, if created, the virtual table.
-*/
-int sqlite3Fts2InitHashTable(
- sqlite3 *db,
- fts2Hash *pHash,
- const char *zName
-){
- int rc = SQLITE_OK;
- void *p = (void *)pHash;
- const int any = SQLITE_ANY;
- char *zTest = 0;
- char *zTest2 = 0;
-
-#ifdef SQLITE_TEST
- void *pdb = (void *)db;
- zTest = sqlite3_mprintf("%s_test", zName);
- zTest2 = sqlite3_mprintf("%s_internal_test", zName);
- if( !zTest || !zTest2 ){
- rc = SQLITE_NOMEM;
- }
-#endif
-
- if( rc!=SQLITE_OK
- || (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0))
- || (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0))
-#ifdef SQLITE_TEST
- || (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0))
- || (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0))
- || (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0))
-#endif
- );
-
- sqlite3_free(zTest);
- sqlite3_free(zTest2);
- return rc;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer.h
deleted file mode 100644
index 8db2048d6bf..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
-** 2006 July 10
-**
-** The author disclaims copyright to this source code.
-**
-*************************************************************************
-** Defines the interface to tokenizers used by fulltext-search. There
-** are three basic components:
-**
-** sqlite3_tokenizer_module is a singleton defining the tokenizer
-** interface functions. This is essentially the class structure for
-** tokenizers.
-**
-** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
-** including customization information defined at creation time.
-**
-** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
-** tokens from a particular input.
-*/
-#ifndef _FTS2_TOKENIZER_H_
-#define _FTS2_TOKENIZER_H_
-
-/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
-** If tokenizers are to be allowed to call sqlite3_*() functions, then
-** we will need a way to register the API consistently.
-*/
-#include "sqlite3.h"
-
-/*
-** Structures used by the tokenizer interface. When a new tokenizer
-** implementation is registered, the caller provides a pointer to
-** an sqlite3_tokenizer_module containing pointers to the callback
-** functions that make up an implementation.
-**
-** When an fts2 table is created, it passes any arguments passed to
-** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the
-** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer
-** implementation. The xCreate() function in turn returns an
-** sqlite3_tokenizer structure representing the specific tokenizer to
-** be used for the fts2 table (customized by the tokenizer clause arguments).
-**
-** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen()
-** method is called. It returns an sqlite3_tokenizer_cursor object
-** that may be used to tokenize a specific input buffer based on
-** the tokenization rules supplied by a specific sqlite3_tokenizer
-** object.
-*/
-typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
-typedef struct sqlite3_tokenizer sqlite3_tokenizer;
-typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
-
-struct sqlite3_tokenizer_module {
-
- /*
- ** Structure version. Should always be set to 0.
- */
- int iVersion;
-
- /*
- ** Create a new tokenizer. The values in the argv[] array are the
- ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL
- ** TABLE statement that created the fts2 table. For example, if
- ** the following SQL is executed:
- **
- ** CREATE .. USING fts2( ... , tokenizer <tokenizer-name> arg1 arg2)
- **
- ** then argc is set to 2, and the argv[] array contains pointers
- ** to the strings "arg1" and "arg2".
- **
- ** This method should return either SQLITE_OK (0), or an SQLite error
- ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
- ** to point at the newly created tokenizer structure. The generic
- ** sqlite3_tokenizer.pModule variable should not be initialized by
- ** this callback. The caller will do so.
- */
- int (*xCreate)(
- int argc, /* Size of argv array */
- const char *const*argv, /* Tokenizer argument strings */
- sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
- );
-
- /*
- ** Destroy an existing tokenizer. The fts2 module calls this method
- ** exactly once for each successful call to xCreate().
- */
- int (*xDestroy)(sqlite3_tokenizer *pTokenizer);
-
- /*
- ** Create a tokenizer cursor to tokenize an input buffer. The caller
- ** is responsible for ensuring that the input buffer remains valid
- ** until the cursor is closed (using the xClose() method).
- */
- int (*xOpen)(
- sqlite3_tokenizer *pTokenizer, /* Tokenizer object */
- const char *pInput, int nBytes, /* Input buffer */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */
- );
-
- /*
- ** Destroy an existing tokenizer cursor. The fts2 module calls this
- ** method exactly once for each successful call to xOpen().
- */
- int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
-
- /*
- ** Retrieve the next token from the tokenizer cursor pCursor. This
- ** method should either return SQLITE_OK and set the values of the
- ** "OUT" variables identified below, or SQLITE_DONE to indicate that
- ** the end of the buffer has been reached, or an SQLite error code.
- **
- ** *ppToken should be set to point at a buffer containing the
- ** normalized version of the token (i.e. after any case-folding and/or
- ** stemming has been performed). *pnBytes should be set to the length
- ** of this buffer in bytes. The input text that generated the token is
- ** identified by the byte offsets returned in *piStartOffset and
- ** *piEndOffset.
- **
- ** The buffer *ppToken is set to point at is managed by the tokenizer
- ** implementation. It is only required to be valid until the next call
- ** to xNext() or xClose().
- */
- /* TODO(shess) current implementation requires pInput to be
- ** nul-terminated. This should either be fixed, or pInput/nBytes
- ** should be converted to zInput.
- */
- int (*xNext)(
- sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */
- const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */
- int *piStartOffset, /* OUT: Byte offset of token in input buffer */
- int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */
- int *piPosition /* OUT: Number of tokens returned before this one */
- );
-};
-
-struct sqlite3_tokenizer {
- const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
- /* Tokenizer implementations will typically add additional fields */
-};
-
-struct sqlite3_tokenizer_cursor {
- sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */
- /* Tokenizer implementations will typically add additional fields */
-};
-
-#endif /* _FTS2_TOKENIZER_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer1.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer1.c
deleted file mode 100644
index fe4f9eb4b56..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/fts2_tokenizer1.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
-** 2006 Oct 10
-**
-** 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.
-**
-******************************************************************************
-**
-** Implementation of the "simple" full-text-search tokenizer.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS2 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS2 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)
-
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "sqlite3.h"
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT3
-#include "fts2_tokenizer.h"
-
-typedef struct simple_tokenizer {
- sqlite3_tokenizer base;
- char delim[128]; /* flag ASCII delimiters */
-} simple_tokenizer;
-
-typedef struct simple_tokenizer_cursor {
- sqlite3_tokenizer_cursor base;
- const char *pInput; /* input we are tokenizing */
- int nBytes; /* size of the input */
- int iOffset; /* current position in pInput */
- int iToken; /* index of next token to be returned */
- char *pToken; /* storage for current token */
- int nTokenAllocated; /* space allocated to zToken buffer */
-} simple_tokenizer_cursor;
-
-
-/* Forward declaration */
-static const sqlite3_tokenizer_module simpleTokenizerModule;
-
-static int simpleDelim(simple_tokenizer *t, unsigned char c){
- return c<0x80 && t->delim[c];
-}
-
-/*
-** Create a new tokenizer instance.
-*/
-static int simpleCreate(
- int argc, const char * const *argv,
- sqlite3_tokenizer **ppTokenizer
-){
- simple_tokenizer *t;
-
- t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t));
- if( t==NULL ) return SQLITE_NOMEM;
- memset(t, 0, sizeof(*t));
-
- /* TODO(shess) Delimiters need to remain the same from run to run,
- ** else we need to reindex. One solution would be a meta-table to
- ** track such information in the database, then we'd only want this
- ** information on the initial create.
- */
- if( argc>1 ){
- int i, n = strlen(argv[1]);
- for(i=0; i<n; i++){
- unsigned char ch = argv[1][i];
- /* We explicitly don't support UTF-8 delimiters for now. */
- if( ch>=0x80 ){
- sqlite3_free(t);
- return SQLITE_ERROR;
- }
- t->delim[ch] = 1;
- }
- } else {
- /* Mark non-alphanumeric ASCII characters as delimiters */
- int i;
- for(i=1; i<0x80; i++){
- t->delim[i] = !((i>='0' && i<='9') || (i>='A' && i<='Z') ||
- (i>='a' && i<='z'));
- }
- }
-
- *ppTokenizer = &t->base;
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
- sqlite3_free(pTokenizer);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int simpleOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *pInput, int nBytes, /* String to be tokenized */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- simple_tokenizer_cursor *c;
-
- c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
- if( c==NULL ) return SQLITE_NOMEM;
-
- c->pInput = pInput;
- if( pInput==0 ){
- c->nBytes = 0;
- }else if( nBytes<0 ){
- c->nBytes = (int)strlen(pInput);
- }else{
- c->nBytes = nBytes;
- }
- c->iOffset = 0; /* start tokenizing at the beginning */
- c->iToken = 0;
- c->pToken = NULL; /* no space allocated, yet. */
- c->nTokenAllocated = 0;
-
- *ppCursor = &c->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to
-** simpleOpen() above.
-*/
-static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
- simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
- sqlite3_free(c->pToken);
- sqlite3_free(c);
- return SQLITE_OK;
-}
-
-/*
-** Extract the next token from a tokenization cursor. The cursor must
-** have been opened by a prior call to simpleOpen().
-*/
-static int simpleNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
- const char **ppToken, /* OUT: *ppToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
- simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
- unsigned char *p = (unsigned char *)c->pInput;
-
- while( c->iOffset<c->nBytes ){
- int iStartOffset;
-
- /* Scan past delimiter characters */
- while( c->iOffset<c->nBytes && simpleDelim(t, p[c->iOffset]) ){
- c->iOffset++;
- }
-
- /* Count non-delimiter characters. */
- iStartOffset = c->iOffset;
- while( c->iOffset<c->nBytes && !simpleDelim(t, p[c->iOffset]) ){
- c->iOffset++;
- }
-
- if( c->iOffset>iStartOffset ){
- int i, n = c->iOffset-iStartOffset;
- if( n>c->nTokenAllocated ){
- c->nTokenAllocated = n+20;
- c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated);
- if( c->pToken==NULL ) return SQLITE_NOMEM;
- }
- for(i=0; i<n; i++){
- /* TODO(shess) This needs expansion to handle UTF-8
- ** case-insensitivity.
- */
- unsigned char ch = p[iStartOffset+i];
- c->pToken[i] = (ch>='A' && ch<='Z') ? (ch - 'A' + 'a') : ch;
- }
- *ppToken = c->pToken;
- *pnBytes = n;
- *piStartOffset = iStartOffset;
- *piEndOffset = c->iOffset;
- *piPosition = c->iToken++;
-
- return SQLITE_OK;
- }
- }
- return SQLITE_DONE;
-}
-
-/*
-** The set of routines that implement the simple tokenizer
-*/
-static const sqlite3_tokenizer_module simpleTokenizerModule = {
- 0,
- simpleCreate,
- simpleDestroy,
- simpleOpen,
- simpleClose,
- simpleNext,
-};
-
-/*
-** Allocate a new simple tokenizer. Return a pointer to the new
-** tokenizer in *ppModule
-*/
-void sqlite3Fts2SimpleTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &simpleTokenizerModule;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/mkfts2amal.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/mkfts2amal.tcl
deleted file mode 100644
index 5c8d1e93d78..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts2/mkfts2amal.tcl
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script builds a single C code file holding all of FTS2 code.
-# The name of the output file is fts2amal.c. To build this file,
-# first do:
-#
-# make target_source
-#
-# The make target above moves all of the source code files into
-# a subdirectory named "tsrc". (This script expects to find the files
-# there and will not work if they are not found.)
-#
-# After the "tsrc" directory has been created and populated, run
-# this script:
-#
-# tclsh mkfts2amal.tcl
-#
-# The amalgamated FTS2 code will be written into fts2amal.c
-#
-
-# Open the output file and write a header comment at the beginning
-# of the file.
-#
-set out [open fts2amal.c w]
-set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
-puts $out [subst \
-{/******************************************************************************
-** This file is an amalgamation of separate C source files from the SQLite
-** Full Text Search extension 2 (fts2). By combining all the individual C
-** code files into this single large file, the entire code can be compiled
-** as a one translation unit. This allows many compilers to do optimizations
-** that would not be possible if the files were compiled separately. It also
-** makes the code easier to import into other projects.
-**
-** This amalgamation was generated on $today.
-*/}]
-
-# These are the header files used by FTS2. The first time any of these
-# files are seen in a #include statement in the C code, include the complete
-# text of the file in-line. The file only needs to be included once.
-#
-foreach hdr {
- fts2.h
- fts2_hash.h
- fts2_tokenizer.h
- sqlite3.h
- sqlite3ext.h
-} {
- set available_hdr($hdr) 1
-}
-
-# 78 stars used for comment formatting.
-set s78 \
-{*****************************************************************************}
-
-# Insert a comment into the code
-#
-proc section_comment {text} {
- global out s78
- set n [string length $text]
- set nstar [expr {60 - $n}]
- set stars [string range $s78 0 $nstar]
- puts $out "/************** $text $stars/"
-}
-
-# Read the source file named $filename and write it into the
-# sqlite3.c output file. If any #include statements are seen,
-# process them approprately.
-#
-proc copy_file {filename} {
- global seen_hdr available_hdr out
- set tail [file tail $filename]
- section_comment "Begin file $tail"
- set in [open $filename r]
- while {![eof $in]} {
- set line [gets $in]
- if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
- if {[info exists available_hdr($hdr)]} {
- if {$available_hdr($hdr)} {
- section_comment "Include $hdr in the middle of $tail"
- copy_file tsrc/$hdr
- section_comment "Continuing where we left off in $tail"
- }
- } elseif {![info exists seen_hdr($hdr)]} {
- set seen_hdr($hdr) 1
- puts $out $line
- }
- } elseif {[regexp {^#ifdef __cplusplus} $line]} {
- puts $out "#if 0"
- } elseif {[regexp {^#line} $line]} {
- # Skip #line directives.
- } else {
- puts $out $line
- }
- }
- close $in
- section_comment "End of $tail"
-}
-
-
-# Process the source files. Process files containing commonly
-# used subroutines first in order to help the compiler find
-# inlining opportunities.
-#
-foreach file {
- fts2.c
- fts2_hash.c
- fts2_porter.c
- fts2_tokenizer.c
- fts2_tokenizer1.c
- fts2_icu.c
-} {
- copy_file tsrc/$file
-}
-
-close $out
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.content b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.content
deleted file mode 100644
index ab986754df2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.content
+++ /dev/null
@@ -1,178 +0,0 @@
-
-FTS4 CONTENT OPTION
-
- Normally, in order to create a full-text index on a dataset, the FTS4
- module stores a copy of all indexed documents in a specially created
- database table.
-
- As of SQLite version 3.7.9, FTS4 supports a new option - "content" -
- designed to extend FTS4 to support the creation of full-text indexes where:
-
- * The indexed documents are not stored within the SQLite database
- at all (a "contentless" FTS4 table), or
-
- * The indexed documents are stored in a database table created and
- managed by the user (an "external content" FTS4 table).
-
- Because the indexed documents themselves are usually much larger than
- the full-text index, the content option can sometimes be used to achieve
- significant space savings.
-
-CONTENTLESS FTS4 TABLES
-
- In order to create an FTS4 table that does not store a copy of the indexed
- documents at all, the content option should be set to an empty string.
- For example, the following SQL creates such an FTS4 table with three
- columns - "a", "b", and "c":
-
- CREATE VIRTUAL TABLE t1 USING fts4(content="", a, b, c);
-
- Data can be inserted into such an FTS4 table using an INSERT statements.
- However, unlike ordinary FTS4 tables, the user must supply an explicit
- integer docid value. For example:
-
- -- This statement is Ok:
- INSERT INTO t1(docid, a, b, c) VALUES(1, 'a b c', 'd e f', 'g h i');
-
- -- This statement causes an error, as no docid value has been provided:
- INSERT INTO t1(a, b, c) VALUES('j k l', 'm n o', 'p q r');
-
- It is not possible to UPDATE or DELETE a row stored in a contentless FTS4
- table. Attempting to do so is an error.
-
- Contentless FTS4 tables also support SELECT statements. However, it is
- an error to attempt to retrieve the value of any table column other than
- the docid column. The auxiliary function matchinfo() may be used, but
- snippet() and offsets() may not. For example:
-
- -- The following statements are Ok:
- SELECT docid FROM t1 WHERE t1 MATCH 'xxx';
- SELECT docid FROM t1 WHERE a MATCH 'xxx';
- SELECT matchinfo(t1) FROM t1 WHERE t1 MATCH 'xxx';
-
- -- The following statements all cause errors, as the value of columns
- -- other than docid are required to evaluate them.
- SELECT * FROM t1;
- SELECT a, b FROM t1 WHERE t1 MATCH 'xxx';
- SELECT docid FROM t1 WHERE a LIKE 'xxx%';
- SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'xxx';
-
- Errors related to attempting to retrieve column values other than docid
- are runtime errors that occur within sqlite3_step(). In some cases, for
- example if the MATCH expression in a SELECT query matches zero rows, there
- may be no error at all even if a statement does refer to column values
- other than docid.
-
-EXTERNAL CONTENT FTS4 TABLES
-
- An "external content" FTS4 table is similar to a contentless table, except
- that if evaluation of a query requires the value of a column other than
- docid, FTS4 attempts to retrieve that value from a table (or view, or
- virtual table) nominated by the user (hereafter referred to as the "content
- table"). The FTS4 module never writes to the content table, and writing
- to the content table does not affect the full-text index. It is the
- responsibility of the user to ensure that the content table and the
- full-text index are consistent.
-
- An external content FTS4 table is created by setting the content option
- to the name of a table (or view, or virtual table) that may be queried by
- FTS4 to retrieve column values when required. If the nominated table does
- not exist, then an external content table behaves in the same way as
- a contentless table. For example:
-
- CREATE TABLE t2(id INTEGER PRIMARY KEY, a, b, c);
- CREATE VIRTUAL TABLE t3 USING fts4(content="t2", a, c);
-
- Assuming the nominated table does exist, then its columns must be the same
- as or a superset of those defined for the FTS table.
-
- When a users query on the FTS table requires a column value other than
- docid, FTS attempts to read this value from the corresponding column of
- the row in the content table with a rowid value equal to the current FTS
- docid. Or, if such a row cannot be found in the content table, a NULL
- value is used instead. For example:
-
- CREATE TABLE t2(id INTEGER PRIMARY KEY, a, b, c, d);
- CREATE VIRTUAL TABLE t3 USING fts4(content="t2", b, c);
-
- INSERT INTO t2 VALUES(2, 'a b', 'c d', 'e f');
- INSERT INTO t2 VALUES(3, 'g h', 'i j', 'k l');
- INSERT INTO t3(docid, b, c) SELECT id, b, c FROM t2;
-
- -- The following query returns a single row with two columns containing
- -- the text values "i j" and "k l".
- --
- -- The query uses the full-text index to discover that the MATCH
- -- term matches the row with docid=3. It then retrieves the values
- -- of columns b and c from the row with rowid=3 in the content table
- -- to return.
- --
- SELECT * FROM t3 WHERE t3 MATCH 'k';
-
- -- Following the UPDATE, the query still returns a single row, this
- -- time containing the text values "xxx" and "yyy". This is because the
- -- full-text index still indicates that the row with docid=3 matches
- -- the FTS4 query 'k', even though the documents stored in the content
- -- table have been modified.
- --
- UPDATE t2 SET b = 'xxx', c = 'yyy' WHERE rowid = 3;
- SELECT * FROM t3 WHERE t3 MATCH 'k';
-
- -- Following the DELETE below, the query returns one row containing two
- -- NULL values. NULL values are returned because FTS is unable to find
- -- a row with rowid=3 within the content table.
- --
- DELETE FROM t2;
- SELECT * FROM t3 WHERE t3 MATCH 'k';
-
- When a row is deleted from an external content FTS4 table, FTS4 needs to
- retrieve the column values of the row being deleted from the content table.
- This is so that FTS4 can update the full-text index entries for each token
- that occurs within the deleted row to indicate that that row has been
- deleted. If the content table row cannot be found, or if it contains values
- inconsistent with the contents of the FTS index, the results can be difficult
- to predict. The FTS index may be left containing entries corresponding to the
- deleted row, which can lead to seemingly nonsensical results being returned
- by subsequent SELECT queries. The same applies when a row is updated, as
- internally an UPDATE is the same as a DELETE followed by an INSERT.
-
- Instead of writing separately to the full-text index and the content table,
- some users may wish to use database triggers to keep the full-text index
- up to date with respect to the set of documents stored in the content table.
- For example, using the tables from earlier examples:
-
- CREATE TRIGGER t2_bu BEFORE UPDATE ON t2 BEGIN
- DELETE FROM t3 WHERE docid=old.rowid;
- END;
- CREATE TRIGGER t2_bd BEFORE DELETE ON t2 BEGIN
- DELETE FROM t3 WHERE docid=old.rowid;
- END;
-
- CREATE TRIGGER t2_bu AFTER UPDATE ON t2 BEGIN
- INSERT INTO t3(docid, b, c) VALUES(new.rowid, new.b, new.c);
- END;
- CREATE TRIGGER t2_bd AFTER INSERT ON t2 BEGIN
- INSERT INTO t3(docid, b, c) VALUES(new.rowid, new.b, new.c);
- END;
-
- The DELETE trigger must be fired before the actual delete takes place
- on the content table. This is so that FTS4 can still retrieve the original
- values in order to update the full-text index. And the INSERT trigger must
- be fired after the new row is inserted, so as to handle the case where the
- rowid is assigned automatically within the system. The UPDATE trigger must
- be split into two parts, one fired before and one after the update of the
- content table, for the same reasons.
-
- FTS4 features a special command similar to the 'optimize' command that
- deletes the entire full-text index and rebuilds it based on the current
- set of documents in the content table. Assuming again that "t3" is the
- name of the external content FTS4 table, the command is:
-
- INSERT INTO t3(t3) VALUES('rebuild');
-
- This command may also be used with ordinary FTS4 tables, although it may
- only be useful if the full-text index has somehow become corrupt. It is an
- error to attempt to rebuild the full-text index maintained by a contentless
- FTS4 table.
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.syntax b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.syntax
deleted file mode 100644
index 01bc80c5fbe..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.syntax
+++ /dev/null
@@ -1,209 +0,0 @@
-
-1. OVERVIEW
-
- This README file describes the syntax of the arguments that may be passed to
- the FTS3 MATCH operator used for full-text queries. For example, if table
- "t1" is an Fts3 virtual table, the following SQL query:
-
- SELECT * FROM t1 WHERE <col> MATCH <full-text query>
-
- may be used to retrieve all rows that match a specified for full-text query.
- The text "<col>" should be replaced by either the name of the fts3 table
- (in this case "t1"), or by the name of one of the columns of the fts3
- table. <full-text-query> should be replaced by an SQL expression that
- computes to a string containing an Fts3 query.
-
- If the left-hand-side of the MATCH operator is set to the name of the
- fts3 table, then by default the query may be matched against any column
- of the table. If it is set to a column name, then by default the query
- may only match the specified column. In both cases this may be overriden
- as part of the query text (see sections 2 and 3 below).
-
- As of SQLite version 3.6.8, Fts3 supports two slightly different query
- formats; the standard syntax, which is used by default, and the enhanced
- query syntax which can be selected by compiling with the pre-processor
- symbol SQLITE_ENABLE_FTS3_PARENTHESIS defined.
-
- -DSQLITE_ENABLE_FTS3_PARENTHESIS
-
-2. STANDARD QUERY SYNTAX
-
- When using the standard Fts3 query syntax, a query usually consists of a
- list of terms (words) separated by white-space characters. To match a
- query, a row (or column) of an Fts3 table must contain each of the specified
- terms. For example, the following query:
-
- <col> MATCH 'hello world'
-
- matches rows (or columns, if <col> is the name of a column name) that
- contain at least one instance of the token "hello", and at least one
- instance of the token "world". Tokens may be grouped into phrases using
- quotation marks. In this case, a matching row or column must contain each
- of the tokens in the phrase in the order specified, with no intervening
- tokens. For example, the query:
-
- <col> MATCH '"hello world" joe"
-
- matches the first of the following two documents, but not the second or
- third:
-
- "'Hello world', said Joe."
- "One should always greet the world with a cheery hello, thought Joe."
- "How many hello world programs could their be?"
-
- As well as grouping tokens together by phrase, the binary NEAR operator
- may be used to search for rows that contain two or more specified tokens
- or phrases within a specified proximity of each other. The NEAR operator
- must always be specified in upper case. The word "near" in lower or mixed
- case is treated as an ordinary token. For example, the following query:
-
- <col> MATCH 'engineering NEAR consultancy'
-
- matches rows that contain both the "engineering" and "consultancy" tokens
- in the same column with not more than 10 other words between them. It does
- not matter which of the two terms occurs first in the document, only that
- they be seperated by only 10 tokens or less. The user may also specify
- a different required proximity by adding "/N" immediately after the NEAR
- operator, where N is an integer. For example:
-
- <col> MATCH 'engineering NEAR/5 consultancy'
-
- searches for a row containing an instance of each specified token seperated
- by not more than 5 other tokens. More than one NEAR operator can be used
- in as sequence. For example this query:
-
- <col> MATCH 'reliable NEAR/2 engineering NEAR/5 consultancy'
-
- searches for a row that contains an instance of the token "reliable"
- seperated by not more than two tokens from an instance of "engineering",
- which is in turn separated by not more than 5 other tokens from an
- instance of the term "consultancy". Phrases enclosed in quotes may
- also be used as arguments to the NEAR operator.
-
- Similar to the NEAR operator, one or more tokens or phrases may be
- separated by OR operators. In this case, only one of the specified tokens
- or phrases must appear in the document. For example, the query:
-
- <col> MATCH 'hello OR world'
-
- matches rows that contain either the term "hello", or the term "world",
- or both. Note that unlike in many programming languages, the OR operator
- has a higher precedence than the AND operators implied between white-space
- separated tokens. The following query matches documents that contain the
- term 'sqlite' and at least one of the terms 'fantastic' or 'impressive',
- not those that contain both 'sqlite' and 'fantastic' or 'impressive':
-
- <col> MATCH 'sqlite fantastic OR impressive'
-
- Any token that is part of an Fts3 query expression, whether or not it is
- part of a phrase enclosed in quotes, may have a '*' character appended to
- it. In this case, the token matches all terms that begin with the characters
- of the token, not just those that exactly match it. For example, the
- following query:
-
- <col> MATCH 'sql*'
-
- matches all rows that contain the term "SQLite", as well as those that
- contain "SQL".
-
- A token that is not part of a quoted phrase may be preceded by a '-'
- character, which indicates that matching rows must not contain the
- specified term. For example, the following:
-
- <col> MATCH '"database engine" -sqlite'
-
- matches rows that contain the phrase "database engine" but do not contain
- the term "sqlite". If the '-' character occurs inside a quoted phrase,
- it is ignored. It is possible to use both the '-' prefix and the '*' postfix
- on a single term. At this time, all Fts3 queries must contain at least
- one term or phrase that is not preceded by the '-' prefix.
-
- Regardless of whether or not a table name or column name is used on the
- left hand side of the MATCH operator, a specific column of the fts3 table
- may be associated with each token in a query by preceding a token with
- a column name followed by a ':' character. For example, regardless of what
- is specified for <col>, the following query requires that column "col1"
- of the table contains the term "hello", and that column "col2" of the
- table contains the term "world". If the table does not contain columns
- named "col1" and "col2", then an error is returned and the query is
- not run.
-
- <col> MATCH 'col1:hello col2:world'
-
- It is not possible to associate a specific table column with a quoted
- phrase or a term preceded by a '-' operator. A '*' character may be
- appended to a term associated with a specific column for prefix matching.
-
-3. ENHANCED QUERY SYNTAX
-
- The enhanced query syntax is quite similar to the standard query syntax,
- with the following four differences:
-
- 1) Parenthesis are supported. When using the enhanced query syntax,
- parenthesis may be used to overcome the built-in precedence of the
- supplied binary operators. For example, the following query:
-
- <col> MATCH '(hello world) OR (simple example)'
-
- matches documents that contain both "hello" and "world", and documents
- that contain both "simple" and "example". It is not possible to forumlate
- such a query using the standard syntax.
-
- 2) Instead of separating tokens and phrases by whitespace, an AND operator
- may be explicitly specified. This does not change query processing at
- all, but may be used to improve readability. For example, the following
- query is handled identically to the one above:
-
- <col> MATCH '(hello AND world) OR (simple AND example)'
-
- As with the OR and NEAR operators, the AND operator must be specified
- in upper case. The word "and" specified in lower or mixed case is
- handled as a regular token.
-
- 3) The '-' token prefix is not supported. Instead, a new binary operator,
- NOT, is included. The NOT operator requires that the query specified
- as its left-hand operator matches, but that the query specified as the
- right-hand operator does not. For example, to query for all rows that
- contain the term "example" but not the term "simple", the following
- query could be used:
-
- <col> MATCH 'example NOT simple'
-
- As for all other operators, the NOT operator must be specified in
- upper case. Otherwise it will be treated as a regular token.
-
- 4) Unlike in the standard syntax, where the OR operator has a higher
- precedence than the implicit AND operator, when using the enhanced
- syntax implicit and explict AND operators have a higher precedence
- than OR operators. Using the enhanced syntax, the following two
- queries are equivalent:
-
- <col> MATCH 'sqlite fantastic OR impressive'
- <col> MATCH '(sqlite AND fantastic) OR impressive'
-
- however, when using the standard syntax, the query:
-
- <col> MATCH 'sqlite fantastic OR impressive'
-
- is equivalent to the enhanced syntax query:
-
- <col> MATCH 'sqlite AND (fantastic OR impressive)'
-
- The precedence of all enhanced syntax operators, in order from highest
- to lowest, is:
-
- NEAR (highest precedence, tightest grouping)
- NOT
- AND
- OR (lowest precedence, loosest grouping)
-
- Using the advanced syntax, it is possible to specify expressions enclosed
- in parenthesis as operands to the NOT, AND and OR operators. However both
- the left and right hand side operands of NEAR operators must be either
- tokens or phrases. Attempting the following query will return an error:
-
- <col> MATCH 'sqlite NEAR (fantastic OR impressive)'
-
- Queries of this form must be re-written as:
-
- <col> MATCH 'sqlite NEAR fantastic OR sqlite NEAR impressive'
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.tokenizers b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.tokenizers
deleted file mode 100644
index 7f2345a81fd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.tokenizers
+++ /dev/null
@@ -1,133 +0,0 @@
-
-1. FTS3 Tokenizers
-
- When creating a new full-text table, FTS3 allows the user to select
- the text tokenizer implementation to be used when indexing text
- by specifying a "tokenize" clause as part of the CREATE VIRTUAL TABLE
- statement:
-
- CREATE VIRTUAL TABLE <table-name> USING fts3(
- <columns ...> [, tokenize <tokenizer-name> [<tokenizer-args>]]
- );
-
- The built-in tokenizers (valid values to pass as <tokenizer name>) are
- "simple", "porter" and "unicode".
-
- <tokenizer-args> should consist of zero or more white-space separated
- arguments to pass to the selected tokenizer implementation. The
- interpretation of the arguments, if any, depends on the individual
- tokenizer.
-
-2. Custom Tokenizers
-
- FTS3 allows users to provide custom tokenizer implementations. The
- interface used to create a new tokenizer is defined and described in
- the fts3_tokenizer.h source file.
-
- Registering a new FTS3 tokenizer is similar to registering a new
- virtual table module with SQLite. The user passes a pointer to a
- structure containing pointers to various callback functions that
- make up the implementation of the new tokenizer type. For tokenizers,
- the structure (defined in fts3_tokenizer.h) is called
- "sqlite3_tokenizer_module".
-
- FTS3 does not expose a C-function that users call to register new
- tokenizer types with a database handle. Instead, the pointer must
- be encoded as an SQL blob value and passed to FTS3 through the SQL
- engine by evaluating a special scalar function, "fts3_tokenizer()".
- The fts3_tokenizer() function may be called with one or two arguments,
- as follows:
-
- SELECT fts3_tokenizer(<tokenizer-name>);
- SELECT fts3_tokenizer(<tokenizer-name>, <sqlite3_tokenizer_module ptr>);
-
- Where <tokenizer-name> is a string identifying the tokenizer and
- <sqlite3_tokenizer_module ptr> is a pointer to an sqlite3_tokenizer_module
- structure encoded as an SQL blob. If the second argument is present,
- it is registered as tokenizer <tokenizer-name> and a copy of it
- returned. If only one argument is passed, a pointer to the tokenizer
- implementation currently registered as <tokenizer-name> is returned,
- encoded as a blob. Or, if no such tokenizer exists, an SQL exception
- (error) is raised.
-
- SECURITY: If the fts3 extension is used in an environment where potentially
- malicious users may execute arbitrary SQL (i.e. gears), they should be
- prevented from invoking the fts3_tokenizer() function, possibly using the
- authorisation callback.
-
- See "Sample code" below for an example of calling the fts3_tokenizer()
- function from C code.
-
-3. ICU Library Tokenizers
-
- If this extension is compiled with the SQLITE_ENABLE_ICU pre-processor
- symbol defined, then there exists a built-in tokenizer named "icu"
- implemented using the ICU library. The first argument passed to the
- xCreate() method (see fts3_tokenizer.h) of this tokenizer may be
- an ICU locale identifier. For example "tr_TR" for Turkish as used
- in Turkey, or "en_AU" for English as used in Australia. For example:
-
- "CREATE VIRTUAL TABLE thai_text USING fts3(text, tokenizer icu th_TH)"
-
- The ICU tokenizer implementation is very simple. It splits the input
- text according to the ICU rules for finding word boundaries and discards
- any tokens that consist entirely of white-space. This may be suitable
- for some applications in some locales, but not all. If more complex
- processing is required, for example to implement stemming or
- discard punctuation, this can be done by creating a tokenizer
- implementation that uses the ICU tokenizer as part of its implementation.
-
- When using the ICU tokenizer this way, it is safe to overwrite the
- contents of the strings returned by the xNext() method (see
- fts3_tokenizer.h).
-
-4. Sample code.
-
- The following two code samples illustrate the way C code should invoke
- the fts3_tokenizer() scalar function:
-
- int registerTokenizer(
- sqlite3 *db,
- char *zName,
- const sqlite3_tokenizer_module *p
- ){
- int rc;
- sqlite3_stmt *pStmt;
- const char zSql[] = "SELECT fts3_tokenizer(?, ?)";
-
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
- sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC);
- sqlite3_step(pStmt);
-
- return sqlite3_finalize(pStmt);
- }
-
- int queryTokenizer(
- sqlite3 *db,
- char *zName,
- const sqlite3_tokenizer_module **pp
- ){
- int rc;
- sqlite3_stmt *pStmt;
- const char zSql[] = "SELECT fts3_tokenizer(?)";
-
- *pp = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
- memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
- }
- }
-
- return sqlite3_finalize(pStmt);
- }
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.txt b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.txt
deleted file mode 100644
index 517a2a04346..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/README.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This folder contains source code to the second full-text search
-extension for SQLite. While the API is the same, this version uses a
-substantially different storage schema from fts1, so tables will need
-to be rebuilt.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3.c
deleted file mode 100644
index 93776d004fb..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3.c
+++ /dev/null
@@ -1,5959 +0,0 @@
-/*
-** 2006 Oct 10
-**
-** 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 is an SQLite module implementing full-text search.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS3 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS3 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
-*/
-
-/* The full-text index is stored in a series of b+tree (-like)
-** structures called segments which map terms to doclists. The
-** structures are like b+trees in layout, but are constructed from the
-** bottom up in optimal fashion and are not updatable. Since trees
-** are built from the bottom up, things will be described from the
-** bottom up.
-**
-**
-**** Varints ****
-** The basic unit of encoding is a variable-length integer called a
-** varint. We encode variable-length integers in little-endian order
-** using seven bits * per byte as follows:
-**
-** KEY:
-** A = 0xxxxxxx 7 bits of data and one flag bit
-** B = 1xxxxxxx 7 bits of data and one flag bit
-**
-** 7 bits - A
-** 14 bits - BA
-** 21 bits - BBA
-** and so on.
-**
-** This is similar in concept to how sqlite encodes "varints" but
-** the encoding is not the same. SQLite varints are big-endian
-** are are limited to 9 bytes in length whereas FTS3 varints are
-** little-endian and can be up to 10 bytes in length (in theory).
-**
-** Example encodings:
-**
-** 1: 0x01
-** 127: 0x7f
-** 128: 0x81 0x00
-**
-**
-**** Document lists ****
-** A doclist (document list) holds a docid-sorted list of hits for a
-** given term. Doclists hold docids and associated token positions.
-** A docid is the unique integer identifier for a single document.
-** A position is the index of a word within the document. The first
-** word of the document has a position of 0.
-**
-** FTS3 used to optionally store character offsets using a compile-time
-** option. But that functionality is no longer supported.
-**
-** A doclist is stored like this:
-**
-** array {
-** varint docid; (delta from previous doclist)
-** array { (position list for column 0)
-** varint position; (2 more than the delta from previous position)
-** }
-** array {
-** varint POS_COLUMN; (marks start of position list for new column)
-** varint column; (index of new column)
-** array {
-** varint position; (2 more than the delta from previous position)
-** }
-** }
-** varint POS_END; (marks end of positions for this document.
-** }
-**
-** Here, array { X } means zero or more occurrences of X, adjacent in
-** memory. A "position" is an index of a token in the token stream
-** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
-** in the same logical place as the position element, and act as sentinals
-** ending a position list array. POS_END is 0. POS_COLUMN is 1.
-** The positions numbers are not stored literally but rather as two more
-** than the difference from the prior position, or the just the position plus
-** 2 for the first position. Example:
-**
-** label: A B C D E F G H I J K
-** value: 123 5 9 1 1 14 35 0 234 72 0
-**
-** The 123 value is the first docid. For column zero in this document
-** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1
-** at D signals the start of a new column; the 1 at E indicates that the
-** new column is column number 1. There are two positions at 12 and 45
-** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The
-** 234 at I is the delta to next docid (357). It has one position 70
-** (72-2) and then terminates with the 0 at K.
-**
-** A "position-list" is the list of positions for multiple columns for
-** a single docid. A "column-list" is the set of positions for a single
-** column. Hence, a position-list consists of one or more column-lists,
-** a document record consists of a docid followed by a position-list and
-** a doclist consists of one or more document records.
-**
-** A bare doclist omits the position information, becoming an
-** array of varint-encoded docids.
-**
-**** Segment leaf nodes ****
-** Segment leaf nodes store terms and doclists, ordered by term. Leaf
-** nodes are written using LeafWriter, and read using LeafReader (to
-** iterate through a single leaf node's data) and LeavesReader (to
-** iterate through a segment's entire leaf layer). Leaf nodes have
-** the format:
-**
-** varint iHeight; (height from leaf level, always 0)
-** varint nTerm; (length of first term)
-** char pTerm[nTerm]; (content of first term)
-** varint nDoclist; (length of term's associated doclist)
-** char pDoclist[nDoclist]; (content of doclist)
-** array {
-** (further terms are delta-encoded)
-** varint nPrefix; (length of prefix shared with previous term)
-** varint nSuffix; (length of unshared suffix)
-** char pTermSuffix[nSuffix];(unshared suffix of next term)
-** varint nDoclist; (length of term's associated doclist)
-** char pDoclist[nDoclist]; (content of doclist)
-** }
-**
-** Here, array { X } means zero or more occurrences of X, adjacent in
-** memory.
-**
-** Leaf nodes are broken into blocks which are stored contiguously in
-** the %_segments table in sorted order. This means that when the end
-** of a node is reached, the next term is in the node with the next
-** greater node id.
-**
-** New data is spilled to a new leaf node when the current node
-** exceeds LEAF_MAX bytes (default 2048). New data which itself is
-** larger than STANDALONE_MIN (default 1024) is placed in a standalone
-** node (a leaf node with a single term and doclist). The goal of
-** these settings is to pack together groups of small doclists while
-** making it efficient to directly access large doclists. The
-** assumption is that large doclists represent terms which are more
-** likely to be query targets.
-**
-** TODO(shess) It may be useful for blocking decisions to be more
-** dynamic. For instance, it may make more sense to have a 2.5k leaf
-** node rather than splitting into 2k and .5k nodes. My intuition is
-** that this might extend through 2x or 4x the pagesize.
-**
-**
-**** Segment interior nodes ****
-** Segment interior nodes store blockids for subtree nodes and terms
-** to describe what data is stored by the each subtree. Interior
-** nodes are written using InteriorWriter, and read using
-** InteriorReader. InteriorWriters are created as needed when
-** SegmentWriter creates new leaf nodes, or when an interior node
-** itself grows too big and must be split. The format of interior
-** nodes:
-**
-** varint iHeight; (height from leaf level, always >0)
-** varint iBlockid; (block id of node's leftmost subtree)
-** optional {
-** varint nTerm; (length of first term)
-** char pTerm[nTerm]; (content of first term)
-** array {
-** (further terms are delta-encoded)
-** varint nPrefix; (length of shared prefix with previous term)
-** varint nSuffix; (length of unshared suffix)
-** char pTermSuffix[nSuffix]; (unshared suffix of next term)
-** }
-** }
-**
-** Here, optional { X } means an optional element, while array { X }
-** means zero or more occurrences of X, adjacent in memory.
-**
-** An interior node encodes n terms separating n+1 subtrees. The
-** subtree blocks are contiguous, so only the first subtree's blockid
-** is encoded. The subtree at iBlockid will contain all terms less
-** than the first term encoded (or all terms if no term is encoded).
-** Otherwise, for terms greater than or equal to pTerm[i] but less
-** than pTerm[i+1], the subtree for that term will be rooted at
-** iBlockid+i. Interior nodes only store enough term data to
-** distinguish adjacent children (if the rightmost term of the left
-** child is "something", and the leftmost term of the right child is
-** "wicked", only "w" is stored).
-**
-** New data is spilled to a new interior node at the same height when
-** the current node exceeds INTERIOR_MAX bytes (default 2048).
-** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing
-** interior nodes and making the tree too skinny. The interior nodes
-** at a given height are naturally tracked by interior nodes at
-** height+1, and so on.
-**
-**
-**** Segment directory ****
-** The segment directory in table %_segdir stores meta-information for
-** merging and deleting segments, and also the root node of the
-** segment's tree.
-**
-** The root node is the top node of the segment's tree after encoding
-** the entire segment, restricted to ROOT_MAX bytes (default 1024).
-** This could be either a leaf node or an interior node. If the top
-** node requires more than ROOT_MAX bytes, it is flushed to %_segments
-** and a new root interior node is generated (which should always fit
-** within ROOT_MAX because it only needs space for 2 varints, the
-** height and the blockid of the previous root).
-**
-** The meta-information in the segment directory is:
-** level - segment level (see below)
-** idx - index within level
-** - (level,idx uniquely identify a segment)
-** start_block - first leaf node
-** leaves_end_block - last leaf node
-** end_block - last block (including interior nodes)
-** root - contents of root node
-**
-** If the root node is a leaf node, then start_block,
-** leaves_end_block, and end_block are all 0.
-**
-**
-**** Segment merging ****
-** To amortize update costs, segments are grouped into levels and
-** merged in batches. Each increase in level represents exponentially
-** more documents.
-**
-** New documents (actually, document updates) are tokenized and
-** written individually (using LeafWriter) to a level 0 segment, with
-** incrementing idx. When idx reaches MERGE_COUNT (default 16), all
-** level 0 segments are merged into a single level 1 segment. Level 1
-** is populated like level 0, and eventually MERGE_COUNT level 1
-** segments are merged to a single level 2 segment (representing
-** MERGE_COUNT^2 updates), and so on.
-**
-** A segment merge traverses all segments at a given level in
-** parallel, performing a straightforward sorted merge. Since segment
-** leaf nodes are written in to the %_segments table in order, this
-** merge traverses the underlying sqlite disk structures efficiently.
-** After the merge, all segment blocks from the merged level are
-** deleted.
-**
-** MERGE_COUNT controls how often we merge segments. 16 seems to be
-** somewhat of a sweet spot for insertion performance. 32 and 64 show
-** very similar performance numbers to 16 on insertion, though they're
-** a tiny bit slower (perhaps due to more overhead in merge-time
-** sorting). 8 is about 20% slower than 16, 4 about 50% slower than
-** 16, 2 about 66% slower than 16.
-**
-** At query time, high MERGE_COUNT increases the number of segments
-** which need to be scanned and merged. For instance, with 100k docs
-** inserted:
-**
-** MERGE_COUNT segments
-** 16 25
-** 8 12
-** 4 10
-** 2 6
-**
-** This appears to have only a moderate impact on queries for very
-** frequent terms (which are somewhat dominated by segment merge
-** costs), and infrequent and non-existent terms still seem to be fast
-** even with many segments.
-**
-** TODO(shess) That said, it would be nice to have a better query-side
-** argument for MERGE_COUNT of 16. Also, it is possible/likely that
-** optimizations to things like doclist merging will swing the sweet
-** spot around.
-**
-**
-**
-**** Handling of deletions and updates ****
-** Since we're using a segmented structure, with no docid-oriented
-** index into the term index, we clearly cannot simply update the term
-** index when a document is deleted or updated. For deletions, we
-** write an empty doclist (varint(docid) varint(POS_END)), for updates
-** we simply write the new doclist. Segment merges overwrite older
-** data for a particular docid with newer data, so deletes or updates
-** will eventually overtake the earlier data and knock it out. The
-** query logic likewise merges doclists so that newer data knocks out
-** older data.
-*/
-
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
-# define SQLITE_CORE 1
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "fts3.h"
-#ifndef SQLITE_CORE
-# include "sqlite3ext.h"
- SQLITE_EXTENSION_INIT1
-#endif
-
-static int fts3EvalNext(Fts3Cursor *pCsr);
-static int fts3EvalStart(Fts3Cursor *pCsr);
-static int fts3TermSegReaderCursor(
- Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
-
-#ifndef SQLITE_AMALGAMATION
-# if defined(SQLITE_DEBUG)
-int sqlite3Fts3Always(int b) { assert( b ); return b; }
-int sqlite3Fts3Never(int b) { assert( !b ); return b; }
-# endif
-#endif
-
-/*
-** Write a 64-bit variable-length integer to memory starting at p[0].
-** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
-** The number of bytes written is returned.
-*/
-int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
- unsigned char *q = (unsigned char *) p;
- sqlite_uint64 vu = v;
- do{
- *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
- vu >>= 7;
- }while( vu!=0 );
- q[-1] &= 0x7f; /* turn off high bit in final byte */
- assert( q - (unsigned char *)p <= FTS3_VARINT_MAX );
- return (int) (q - (unsigned char *)p);
-}
-
-#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
- v = (v & mask1) | ( (*ptr++) << shift ); \
- if( (v & mask2)==0 ){ var = v; return ret; }
-#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
- v = (*ptr++); \
- if( (v & mask2)==0 ){ var = v; return ret; }
-
-/*
-** Read a 64-bit variable-length integer from memory starting at p[0].
-** Return the number of bytes read, or 0 on error.
-** The value is stored in *v.
-*/
-int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
- const unsigned char *p = (const unsigned char*)pBuf;
- const unsigned char *pStart = p;
- u32 a;
- u64 b;
- int shift;
-
- GETVARINT_INIT(a, p, 0, 0x00, 0x80, *v, 1);
- GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *v, 2);
- GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *v, 3);
- GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4);
- b = (a & 0x0FFFFFFF );
-
- for(shift=28; shift<=63; shift+=7){
- u64 c = *p++;
- b += (c&0x7F) << shift;
- if( (c & 0x80)==0 ) break;
- }
- *v = b;
- return (int)(p - pStart);
-}
-
-/*
-** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
-** a non-negative 32-bit integer before it is returned.
-*/
-int sqlite3Fts3GetVarint32(const char *p, int *pi){
- u32 a;
-
-#ifndef fts3GetVarint32
- GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
-#else
- a = (*p++);
- assert( a & 0x80 );
-#endif
-
- GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *pi, 2);
- GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
- GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
- a = (a & 0x0FFFFFFF );
- *pi = (int)(a | ((u32)(*p & 0x07) << 28));
- assert( 0==(a & 0x80000000) );
- assert( *pi>=0 );
- return 5;
-}
-
-/*
-** Return the number of bytes required to encode v as a varint
-*/
-int sqlite3Fts3VarintLen(sqlite3_uint64 v){
- int i = 0;
- do{
- i++;
- v >>= 7;
- }while( v!=0 );
- return i;
-}
-
-/*
-** Convert an SQL-style quoted string into a normal string by removing
-** the quote characters. The conversion is done in-place. If the
-** input does not begin with a quote character, then this routine
-** is a no-op.
-**
-** Examples:
-**
-** "abc" becomes abc
-** 'xyz' becomes xyz
-** [pqr] becomes pqr
-** `mno` becomes mno
-**
-*/
-void sqlite3Fts3Dequote(char *z){
- char quote; /* Quote character (if any ) */
-
- quote = z[0];
- if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
- int iIn = 1; /* Index of next byte to read from input */
- int iOut = 0; /* Index of next byte to write to output */
-
- /* If the first byte was a '[', then the close-quote character is a ']' */
- if( quote=='[' ) quote = ']';
-
- while( z[iIn] ){
- if( z[iIn]==quote ){
- if( z[iIn+1]!=quote ) break;
- z[iOut++] = quote;
- iIn += 2;
- }else{
- z[iOut++] = z[iIn++];
- }
- }
- z[iOut] = '\0';
- }
-}
-
-/*
-** Read a single varint from the doclist at *pp and advance *pp to point
-** to the first byte past the end of the varint. Add the value of the varint
-** to *pVal.
-*/
-static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
- sqlite3_int64 iVal;
- *pp += sqlite3Fts3GetVarint(*pp, &iVal);
- *pVal += iVal;
-}
-
-/*
-** When this function is called, *pp points to the first byte following a
-** varint that is part of a doclist (or position-list, or any other list
-** of varints). This function moves *pp to point to the start of that varint,
-** and sets *pVal by the varint value.
-**
-** Argument pStart points to the first byte of the doclist that the
-** varint is part of.
-*/
-static void fts3GetReverseVarint(
- char **pp,
- char *pStart,
- sqlite3_int64 *pVal
-){
- sqlite3_int64 iVal;
- char *p;
-
- /* Pointer p now points at the first byte past the varint we are
- ** interested in. So, unless the doclist is corrupt, the 0x80 bit is
- ** clear on character p[-1]. */
- for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
- p++;
- *pp = p;
-
- sqlite3Fts3GetVarint(p, &iVal);
- *pVal = iVal;
-}
-
-/*
-** The xDisconnect() virtual table method.
-*/
-static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
- Fts3Table *p = (Fts3Table *)pVtab;
- int i;
-
- assert( p->nPendingData==0 );
- assert( p->pSegments==0 );
-
- /* Free any prepared statements held */
- sqlite3_finalize(p->pSeekStmt);
- for(i=0; i<SizeofArray(p->aStmt); i++){
- sqlite3_finalize(p->aStmt[i]);
- }
- sqlite3_free(p->zSegmentsTbl);
- sqlite3_free(p->zReadExprlist);
- sqlite3_free(p->zWriteExprlist);
- sqlite3_free(p->zContentTbl);
- sqlite3_free(p->zLanguageid);
-
- /* Invoke the tokenizer destructor to free the tokenizer. */
- p->pTokenizer->pModule->xDestroy(p->pTokenizer);
-
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Write an error message into *pzErr
-*/
-void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){
- va_list ap;
- sqlite3_free(*pzErr);
- va_start(ap, zFormat);
- *pzErr = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
-}
-
-/*
-** Construct one or more SQL statements from the format string given
-** and then evaluate those statements. The success code is written
-** into *pRc.
-**
-** If *pRc is initially non-zero then this routine is a no-op.
-*/
-static void fts3DbExec(
- int *pRc, /* Success code */
- sqlite3 *db, /* Database in which to run SQL */
- const char *zFormat, /* Format string for SQL */
- ... /* Arguments to the format string */
-){
- va_list ap;
- char *zSql;
- if( *pRc ) return;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- if( zSql==0 ){
- *pRc = SQLITE_NOMEM;
- }else{
- *pRc = sqlite3_exec(db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
-}
-
-/*
-** The xDestroy() virtual table method.
-*/
-static int fts3DestroyMethod(sqlite3_vtab *pVtab){
- Fts3Table *p = (Fts3Table *)pVtab;
- int rc = SQLITE_OK; /* Return code */
- const char *zDb = p->zDb; /* Name of database (e.g. "main", "temp") */
- sqlite3 *db = p->db; /* Database handle */
-
- /* Drop the shadow tables */
- if( p->zContentTbl==0 ){
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
- }
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
-
- /* If everything has worked, invoke fts3DisconnectMethod() to free the
- ** memory associated with the Fts3Table structure and return SQLITE_OK.
- ** Otherwise, return an SQLite error code.
- */
- return (rc==SQLITE_OK ? fts3DisconnectMethod(pVtab) : rc);
-}
-
-
-/*
-** Invoke sqlite3_declare_vtab() to declare the schema for the FTS3 table
-** passed as the first argument. This is done as part of the xConnect()
-** and xCreate() methods.
-**
-** If *pRc is non-zero when this function is called, it is a no-op.
-** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
-** before returning.
-*/
-static void fts3DeclareVtab(int *pRc, Fts3Table *p){
- if( *pRc==SQLITE_OK ){
- int i; /* Iterator variable */
- int rc; /* Return code */
- char *zSql; /* SQL statement passed to declare_vtab() */
- char *zCols; /* List of user defined columns */
- const char *zLanguageid;
-
- zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid");
- sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
-
- /* Create a list of user columns for the virtual table */
- zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
- for(i=1; zCols && i<p->nColumn; i++){
- zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
- }
-
- /* Create the whole "CREATE TABLE" statement to pass to SQLite */
- zSql = sqlite3_mprintf(
- "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)",
- zCols, p->zName, zLanguageid
- );
- if( !zCols || !zSql ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_declare_vtab(p->db, zSql);
- }
-
- sqlite3_free(zSql);
- sqlite3_free(zCols);
- *pRc = rc;
- }
-}
-
-/*
-** Create the %_stat table if it does not already exist.
-*/
-void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){
- fts3DbExec(pRc, p->db,
- "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'"
- "(id INTEGER PRIMARY KEY, value BLOB);",
- p->zDb, p->zName
- );
- if( (*pRc)==SQLITE_OK ) p->bHasStat = 1;
-}
-
-/*
-** Create the backing store tables (%_content, %_segments and %_segdir)
-** required by the FTS3 table passed as the only argument. This is done
-** as part of the vtab xCreate() method.
-**
-** If the p->bHasDocsize boolean is true (indicating that this is an
-** FTS4 table, not an FTS3 table) then also create the %_docsize and
-** %_stat tables required by FTS4.
-*/
-static int fts3CreateTables(Fts3Table *p){
- int rc = SQLITE_OK; /* Return code */
- int i; /* Iterator variable */
- sqlite3 *db = p->db; /* The database connection */
-
- if( p->zContentTbl==0 ){
- const char *zLanguageid = p->zLanguageid;
- char *zContentCols; /* Columns of %_content table */
-
- /* Create a list of user columns for the content table */
- zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
- for(i=0; zContentCols && i<p->nColumn; i++){
- char *z = p->azColumn[i];
- zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
- }
- if( zLanguageid && zContentCols ){
- zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid);
- }
- if( zContentCols==0 ) rc = SQLITE_NOMEM;
-
- /* Create the content table */
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_content'(%s)",
- p->zDb, p->zName, zContentCols
- );
- sqlite3_free(zContentCols);
- }
-
- /* Create other tables */
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);",
- p->zDb, p->zName
- );
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_segdir'("
- "level INTEGER,"
- "idx INTEGER,"
- "start_block INTEGER,"
- "leaves_end_block INTEGER,"
- "end_block INTEGER,"
- "root BLOB,"
- "PRIMARY KEY(level, idx)"
- ");",
- p->zDb, p->zName
- );
- if( p->bHasDocsize ){
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
- p->zDb, p->zName
- );
- }
- assert( p->bHasStat==p->bFts4 );
- if( p->bHasStat ){
- sqlite3Fts3CreateStatTable(&rc, p);
- }
- return rc;
-}
-
-/*
-** Store the current database page-size in bytes in p->nPgsz.
-**
-** If *pRc is non-zero when this function is called, it is a no-op.
-** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
-** before returning.
-*/
-static void fts3DatabasePageSize(int *pRc, Fts3Table *p){
- if( *pRc==SQLITE_OK ){
- int rc; /* Return code */
- char *zSql; /* SQL text "PRAGMA %Q.page_size" */
- sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */
-
- zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- 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 );
- sqlite3_free(zSql);
- *pRc = rc;
- }
-}
-
-/*
-** "Special" FTS4 arguments are column specifications of the following form:
-**
-** <key> = <value>
-**
-** There may not be whitespace surrounding the "=" character. The <value>
-** term may be quoted, but the <key> may not.
-*/
-static int fts3IsSpecialColumn(
- const char *z,
- int *pnKey,
- char **pzValue
-){
- char *zValue;
- const char *zCsr = z;
-
- while( *zCsr!='=' ){
- if( *zCsr=='\0' ) return 0;
- zCsr++;
- }
-
- *pnKey = (int)(zCsr-z);
- zValue = sqlite3_mprintf("%s", &zCsr[1]);
- if( zValue ){
- sqlite3Fts3Dequote(zValue);
- }
- *pzValue = zValue;
- return 1;
-}
-
-/*
-** Append the output of a printf() style formatting to an existing string.
-*/
-static void fts3Appendf(
- int *pRc, /* IN/OUT: Error code */
- char **pz, /* IN/OUT: Pointer to string buffer */
- const char *zFormat, /* Printf format string to append */
- ... /* Arguments for printf format string */
-){
- if( *pRc==SQLITE_OK ){
- va_list ap;
- char *z;
- va_start(ap, zFormat);
- z = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- if( z && *pz ){
- char *z2 = sqlite3_mprintf("%s%s", *pz, z);
- sqlite3_free(z);
- z = z2;
- }
- if( z==0 ) *pRc = SQLITE_NOMEM;
- sqlite3_free(*pz);
- *pz = z;
- }
-}
-
-/*
-** Return a copy of input string zInput enclosed in double-quotes (") and
-** with all double quote characters escaped. For example:
-**
-** fts3QuoteId("un \"zip\"") -> "un \"\"zip\"\""
-**
-** The pointer returned points to memory obtained from sqlite3_malloc(). It
-** is the callers responsibility to call sqlite3_free() to release this
-** memory.
-*/
-static char *fts3QuoteId(char const *zInput){
- int nRet;
- char *zRet;
- nRet = 2 + (int)strlen(zInput)*2 + 1;
- zRet = sqlite3_malloc(nRet);
- if( zRet ){
- int i;
- char *z = zRet;
- *(z++) = '"';
- for(i=0; zInput[i]; i++){
- if( zInput[i]=='"' ) *(z++) = '"';
- *(z++) = zInput[i];
- }
- *(z++) = '"';
- *(z++) = '\0';
- }
- return zRet;
-}
-
-/*
-** Return a list of comma separated SQL expressions and a FROM clause that
-** could be used in a SELECT statement such as the following:
-**
-** SELECT <list of expressions> FROM %_content AS x ...
-**
-** to return the docid, followed by each column of text data in order
-** from left to write. If parameter zFunc is not NULL, then instead of
-** being returned directly each column of text data is passed to an SQL
-** function named zFunc first. For example, if zFunc is "unzip" and the
-** table has the three user-defined columns "a", "b", and "c", the following
-** string is returned:
-**
-** "docid, unzip(x.'a'), unzip(x.'b'), unzip(x.'c') FROM %_content AS x"
-**
-** The pointer returned points to a buffer allocated by sqlite3_malloc(). It
-** is the responsibility of the caller to eventually free it.
-**
-** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and
-** a NULL pointer is returned). Otherwise, if an OOM error is encountered
-** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If
-** no error occurs, *pRc is left unmodified.
-*/
-static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){
- char *zRet = 0;
- char *zFree = 0;
- char *zFunction;
- int i;
-
- if( p->zContentTbl==0 ){
- if( !zFunc ){
- zFunction = "";
- }else{
- zFree = zFunction = fts3QuoteId(zFunc);
- }
- fts3Appendf(pRc, &zRet, "docid");
- for(i=0; i<p->nColumn; i++){
- fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]);
- }
- if( p->zLanguageid ){
- fts3Appendf(pRc, &zRet, ", x.%Q", "langid");
- }
- sqlite3_free(zFree);
- }else{
- fts3Appendf(pRc, &zRet, "rowid");
- for(i=0; i<p->nColumn; i++){
- fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]);
- }
- if( p->zLanguageid ){
- fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid);
- }
- }
- fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x",
- p->zDb,
- (p->zContentTbl ? p->zContentTbl : p->zName),
- (p->zContentTbl ? "" : "_content")
- );
- return zRet;
-}
-
-/*
-** Return a list of N comma separated question marks, where N is the number
-** of columns in the %_content table (one for the docid plus one for each
-** user-defined text column).
-**
-** If argument zFunc is not NULL, then all but the first question mark
-** is preceded by zFunc and an open bracket, and followed by a closed
-** bracket. For example, if zFunc is "zip" and the FTS3 table has three
-** user-defined text columns, the following string is returned:
-**
-** "?, zip(?), zip(?), zip(?)"
-**
-** The pointer returned points to a buffer allocated by sqlite3_malloc(). It
-** is the responsibility of the caller to eventually free it.
-**
-** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and
-** a NULL pointer is returned). Otherwise, if an OOM error is encountered
-** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If
-** no error occurs, *pRc is left unmodified.
-*/
-static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
- char *zRet = 0;
- char *zFree = 0;
- char *zFunction;
- int i;
-
- if( !zFunc ){
- zFunction = "";
- }else{
- zFree = zFunction = fts3QuoteId(zFunc);
- }
- fts3Appendf(pRc, &zRet, "?");
- for(i=0; i<p->nColumn; i++){
- fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
- }
- if( p->zLanguageid ){
- fts3Appendf(pRc, &zRet, ", ?");
- }
- sqlite3_free(zFree);
- return zRet;
-}
-
-/*
-** This function interprets the string at (*pp) as a non-negative integer
-** value. It reads the integer and sets *pnOut to the value read, then
-** sets *pp to point to the byte immediately following the last byte of
-** the integer value.
-**
-** Only decimal digits ('0'..'9') may be part of an integer value.
-**
-** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
-** the output value undefined. Otherwise SQLITE_OK is returned.
-**
-** This function is used when parsing the "prefix=" FTS4 parameter.
-*/
-static int fts3GobbleInt(const char **pp, int *pnOut){
- const int MAX_NPREFIX = 10000000;
- const char *p; /* Iterator pointer */
- int nInt = 0; /* Output value */
-
- for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
- nInt = nInt * 10 + (p[0] - '0');
- if( nInt>MAX_NPREFIX ){
- nInt = 0;
- break;
- }
- }
- if( p==*pp ) return SQLITE_ERROR;
- *pnOut = nInt;
- *pp = p;
- return SQLITE_OK;
-}
-
-/*
-** This function is called to allocate an array of Fts3Index structures
-** representing the indexes maintained by the current FTS table. FTS tables
-** always maintain the main "terms" index, but may also maintain one or
-** more "prefix" indexes, depending on the value of the "prefix=" parameter
-** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
-**
-** Argument zParam is passed the value of the "prefix=" option if one was
-** specified, or NULL otherwise.
-**
-** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
-** the allocated array. *pnIndex is set to the number of elements in the
-** array. If an error does occur, an SQLite error code is returned.
-**
-** Regardless of whether or not an error is returned, it is the responsibility
-** of the caller to call sqlite3_free() on the output array to free it.
-*/
-static int fts3PrefixParameter(
- const char *zParam, /* ABC in prefix=ABC parameter to parse */
- int *pnIndex, /* OUT: size of *apIndex[] array */
- struct Fts3Index **apIndex /* OUT: Array of indexes for this table */
-){
- struct Fts3Index *aIndex; /* Allocated array */
- int nIndex = 1; /* Number of entries in array */
-
- if( zParam && zParam[0] ){
- const char *p;
- nIndex++;
- for(p=zParam; *p; p++){
- if( *p==',' ) nIndex++;
- }
- }
-
- aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
- *apIndex = aIndex;
- if( !aIndex ){
- return SQLITE_NOMEM;
- }
-
- memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex);
- if( zParam ){
- const char *p = zParam;
- int i;
- for(i=1; i<nIndex; i++){
- int nPrefix = 0;
- if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR;
- assert( nPrefix>=0 );
- if( nPrefix==0 ){
- nIndex--;
- i--;
- }else{
- aIndex[i].nPrefix = nPrefix;
- }
- p++;
- }
- }
-
- *pnIndex = nIndex;
- return SQLITE_OK;
-}
-
-/*
-** This function is called when initializing an FTS4 table that uses the
-** content=xxx option. It determines the number of and names of the columns
-** of the new FTS4 table.
-**
-** The third argument passed to this function is the value passed to the
-** config=xxx option (i.e. "xxx"). This function queries the database for
-** a table of that name. If found, the output variables are populated
-** as follows:
-**
-** *pnCol: Set to the number of columns table xxx has,
-**
-** *pnStr: Set to the total amount of space required to store a copy
-** of each columns name, including the nul-terminator.
-**
-** *pazCol: Set to point to an array of *pnCol strings. Each string is
-** the name of the corresponding column in table xxx. The array
-** and its contents are allocated using a single allocation. It
-** is the responsibility of the caller to free this allocation
-** by eventually passing the *pazCol value to sqlite3_free().
-**
-** If the table cannot be found, an error code is returned and the output
-** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is
-** returned (and the output variables are undefined).
-*/
-static int fts3ContentColumns(
- sqlite3 *db, /* Database handle */
- const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */
- const char *zTbl, /* Name of content table */
- const char ***pazCol, /* OUT: Malloc'd array of column names */
- int *pnCol, /* OUT: Size of array *pazCol */
- int *pnStr, /* OUT: Bytes of string content */
- char **pzErr /* OUT: error message */
-){
- int rc = SQLITE_OK; /* Return code */
- char *zSql; /* "SELECT *" statement on zTbl */
- sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */
-
- zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db));
- }
- }
- sqlite3_free(zSql);
-
- if( rc==SQLITE_OK ){
- const char **azCol; /* Output array */
- int nStr = 0; /* Size of all column names (incl. 0x00) */
- int nCol; /* Number of table columns */
- int i; /* Used to iterate through columns */
-
- /* Loop through the returned columns. Set nStr to the number of bytes of
- ** space required to store a copy of each column name, including the
- ** nul-terminator byte. */
- nCol = sqlite3_column_count(pStmt);
- for(i=0; i<nCol; i++){
- const char *zCol = sqlite3_column_name(pStmt, i);
- nStr += (int)strlen(zCol) + 1;
- }
-
- /* Allocate and populate the array to return. */
- azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
- if( azCol==0 ){
- rc = SQLITE_NOMEM;
- }else{
- char *p = (char *)&azCol[nCol];
- for(i=0; i<nCol; i++){
- const char *zCol = sqlite3_column_name(pStmt, i);
- int n = (int)strlen(zCol)+1;
- memcpy(p, zCol, n);
- azCol[i] = p;
- p += n;
- }
- }
- sqlite3_finalize(pStmt);
-
- /* Set the output variables. */
- *pnCol = nCol;
- *pnStr = nStr;
- *pazCol = azCol;
- }
-
- return rc;
-}
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the FTS3 virtual table.
-**
-** The argv[] array contains the following:
-**
-** argv[0] -> module name ("fts3" or "fts4")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> "column name" and other module argument fields.
-*/
-static int fts3InitVtab(
- int isCreate, /* True for xCreate, false for xConnect */
- sqlite3 *db, /* The SQLite database connection */
- void *pAux, /* Hash table containing tokenizers */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
- char **pzErr /* Write any error message here */
-){
- Fts3Hash *pHash = (Fts3Hash *)pAux;
- Fts3Table *p = 0; /* Pointer to allocated vtab */
- int rc = SQLITE_OK; /* Return code */
- int i; /* Iterator variable */
- int nByte; /* Size of allocation used for *p */
- int iCol; /* Column index */
- int nString = 0; /* Bytes required to hold all column names */
- int nCol = 0; /* Number of columns in the FTS table */
- char *zCsr; /* Space for holding column names */
- int nDb; /* Bytes required to hold database name */
- int nName; /* Bytes required to hold table name */
- int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
- const char **aCol; /* Array of column names */
- sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
-
- int nIndex = 0; /* Size of aIndex[] array */
- struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
-
- /* The results of parsing supported FTS4 key=value options: */
- int bNoDocsize = 0; /* True to omit %_docsize table */
- int bDescIdx = 0; /* True to store descending indexes */
- char *zPrefix = 0; /* Prefix parameter value (or NULL) */
- char *zCompress = 0; /* compress=? parameter (or NULL) */
- char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
- char *zContent = 0; /* content=? parameter (or NULL) */
- char *zLanguageid = 0; /* languageid=? parameter (or NULL) */
- char **azNotindexed = 0; /* The set of notindexed= columns */
- int nNotindexed = 0; /* Size of azNotindexed[] array */
-
- assert( strlen(argv[0])==4 );
- assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
- || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
- );
-
- nDb = (int)strlen(argv[1]) + 1;
- nName = (int)strlen(argv[2]) + 1;
-
- nByte = sizeof(const char *) * (argc-2);
- aCol = (const char **)sqlite3_malloc(nByte);
- if( aCol ){
- memset((void*)aCol, 0, nByte);
- azNotindexed = (char **)sqlite3_malloc(nByte);
- }
- if( azNotindexed ){
- memset(azNotindexed, 0, nByte);
- }
- if( !aCol || !azNotindexed ){
- rc = SQLITE_NOMEM;
- goto fts3_init_out;
- }
-
- /* Loop through all of the arguments passed by the user to the FTS3/4
- ** module (i.e. all the column names and special arguments). This loop
- ** does the following:
- **
- ** + Figures out the number of columns the FTSX table will have, and
- ** the number of bytes of space that must be allocated to store copies
- ** of the column names.
- **
- ** + If there is a tokenizer specification included in the arguments,
- ** initializes the tokenizer pTokenizer.
- */
- for(i=3; rc==SQLITE_OK && i<argc; i++){
- char const *z = argv[i];
- int nKey;
- char *zVal;
-
- /* Check if this is a tokenizer specification */
- if( !pTokenizer
- && strlen(z)>8
- && 0==sqlite3_strnicmp(z, "tokenize", 8)
- && 0==sqlite3Fts3IsIdChar(z[8])
- ){
- rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr);
- }
-
- /* Check if it is an FTS4 special argument. */
- else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){
- struct Fts4Option {
- const char *zOpt;
- int nOpt;
- } aFts4Opt[] = {
- { "matchinfo", 9 }, /* 0 -> MATCHINFO */
- { "prefix", 6 }, /* 1 -> PREFIX */
- { "compress", 8 }, /* 2 -> COMPRESS */
- { "uncompress", 10 }, /* 3 -> UNCOMPRESS */
- { "order", 5 }, /* 4 -> ORDER */
- { "content", 7 }, /* 5 -> CONTENT */
- { "languageid", 10 }, /* 6 -> LANGUAGEID */
- { "notindexed", 10 } /* 7 -> NOTINDEXED */
- };
-
- int iOpt;
- if( !zVal ){
- rc = SQLITE_NOMEM;
- }else{
- for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){
- struct Fts4Option *pOp = &aFts4Opt[iOpt];
- if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){
- break;
- }
- }
- switch( iOpt ){
- case 0: /* MATCHINFO */
- if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
- sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
- rc = SQLITE_ERROR;
- }
- bNoDocsize = 1;
- break;
-
- case 1: /* PREFIX */
- sqlite3_free(zPrefix);
- zPrefix = zVal;
- zVal = 0;
- break;
-
- case 2: /* COMPRESS */
- sqlite3_free(zCompress);
- zCompress = zVal;
- zVal = 0;
- break;
-
- case 3: /* UNCOMPRESS */
- sqlite3_free(zUncompress);
- zUncompress = zVal;
- zVal = 0;
- break;
-
- case 4: /* ORDER */
- if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
- && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
- ){
- sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
- rc = SQLITE_ERROR;
- }
- bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
- break;
-
- case 5: /* CONTENT */
- sqlite3_free(zContent);
- zContent = zVal;
- zVal = 0;
- break;
-
- case 6: /* LANGUAGEID */
- assert( iOpt==6 );
- sqlite3_free(zLanguageid);
- zLanguageid = zVal;
- zVal = 0;
- break;
-
- case 7: /* NOTINDEXED */
- azNotindexed[nNotindexed++] = zVal;
- zVal = 0;
- break;
-
- default:
- assert( iOpt==SizeofArray(aFts4Opt) );
- sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
- rc = SQLITE_ERROR;
- break;
- }
- sqlite3_free(zVal);
- }
- }
-
- /* Otherwise, the argument is a column name. */
- else {
- nString += (int)(strlen(z) + 1);
- aCol[nCol++] = z;
- }
- }
-
- /* If a content=xxx option was specified, the following:
- **
- ** 1. Ignore any compress= and uncompress= options.
- **
- ** 2. If no column names were specified as part of the CREATE VIRTUAL
- ** TABLE statement, use all columns from the content table.
- */
- if( rc==SQLITE_OK && zContent ){
- sqlite3_free(zCompress);
- sqlite3_free(zUncompress);
- zCompress = 0;
- zUncompress = 0;
- if( nCol==0 ){
- sqlite3_free((void*)aCol);
- aCol = 0;
- rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr);
-
- /* If a languageid= option was specified, remove the language id
- ** column from the aCol[] array. */
- if( rc==SQLITE_OK && zLanguageid ){
- int j;
- for(j=0; j<nCol; j++){
- if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){
- int k;
- for(k=j; k<nCol; k++) aCol[k] = aCol[k+1];
- nCol--;
- break;
- }
- }
- }
- }
- }
- if( rc!=SQLITE_OK ) goto fts3_init_out;
-
- if( nCol==0 ){
- assert( nString==0 );
- aCol[0] = "content";
- nString = 8;
- nCol = 1;
- }
-
- if( pTokenizer==0 ){
- rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
- if( rc!=SQLITE_OK ) goto fts3_init_out;
- }
- assert( pTokenizer );
-
- rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
- if( rc==SQLITE_ERROR ){
- assert( zPrefix );
- sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix);
- }
- if( rc!=SQLITE_OK ) goto fts3_init_out;
-
- /* Allocate and populate the Fts3Table structure. */
- nByte = sizeof(Fts3Table) + /* Fts3Table */
- nCol * sizeof(char *) + /* azColumn */
- nIndex * sizeof(struct Fts3Index) + /* aIndex */
- nCol * sizeof(u8) + /* abNotindexed */
- nName + /* zName */
- nDb + /* zDb */
- nString; /* Space for azColumn strings */
- p = (Fts3Table*)sqlite3_malloc(nByte);
- if( p==0 ){
- rc = SQLITE_NOMEM;
- goto fts3_init_out;
- }
- memset(p, 0, nByte);
- p->db = db;
- p->nColumn = nCol;
- p->nPendingData = 0;
- p->azColumn = (char **)&p[1];
- p->pTokenizer = pTokenizer;
- p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
- p->bHasDocsize = (isFts4 && bNoDocsize==0);
- p->bHasStat = (u8)isFts4;
- p->bFts4 = (u8)isFts4;
- p->bDescIdx = (u8)bDescIdx;
- p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
- p->zContentTbl = zContent;
- p->zLanguageid = zLanguageid;
- zContent = 0;
- zLanguageid = 0;
- TESTONLY( p->inTransaction = -1 );
- TESTONLY( p->mxSavepoint = -1 );
-
- p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
- memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
- p->nIndex = nIndex;
- for(i=0; i<nIndex; i++){
- fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
- }
- p->abNotindexed = (u8 *)&p->aIndex[nIndex];
-
- /* Fill in the zName and zDb fields of the vtab structure. */
- zCsr = (char *)&p->abNotindexed[nCol];
- p->zName = zCsr;
- memcpy(zCsr, argv[2], nName);
- zCsr += nName;
- p->zDb = zCsr;
- memcpy(zCsr, argv[1], nDb);
- zCsr += nDb;
-
- /* Fill in the azColumn array */
- for(iCol=0; iCol<nCol; iCol++){
- char *z;
- int n = 0;
- z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
- if( n>0 ){
- memcpy(zCsr, z, n);
- }
- zCsr[n] = '\0';
- sqlite3Fts3Dequote(zCsr);
- p->azColumn[iCol] = zCsr;
- zCsr += n+1;
- assert( zCsr <= &((char *)p)[nByte] );
- }
-
- /* Fill in the abNotindexed array */
- for(iCol=0; iCol<nCol; iCol++){
- int n = (int)strlen(p->azColumn[iCol]);
- for(i=0; i<nNotindexed; i++){
- char *zNot = azNotindexed[i];
- if( zNot && n==(int)strlen(zNot)
- && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n)
- ){
- p->abNotindexed[iCol] = 1;
- sqlite3_free(zNot);
- azNotindexed[i] = 0;
- }
- }
- }
- for(i=0; i<nNotindexed; i++){
- if( azNotindexed[i] ){
- sqlite3Fts3ErrMsg(pzErr, "no such column: %s", azNotindexed[i]);
- rc = SQLITE_ERROR;
- }
- }
-
- if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){
- char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
- rc = SQLITE_ERROR;
- sqlite3Fts3ErrMsg(pzErr, "missing %s parameter in fts4 constructor", zMiss);
- }
- p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc);
- p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc);
- if( rc!=SQLITE_OK ) goto fts3_init_out;
-
- /* If this is an xCreate call, create the underlying tables in the
- ** database. TODO: For xConnect(), it could verify that said tables exist.
- */
- if( isCreate ){
- rc = fts3CreateTables(p);
- }
-
- /* Check to see if a legacy fts3 table has been "upgraded" by the
- ** addition of a %_stat table so that it can use incremental merge.
- */
- if( !isFts4 && !isCreate ){
- p->bHasStat = 2;
- }
-
- /* Figure out the page-size for the database. This is required in order to
- ** estimate the cost of loading large doclists from the database. */
- fts3DatabasePageSize(&rc, p);
- p->nNodeSize = p->nPgsz-35;
-
- /* Declare the table schema to SQLite. */
- fts3DeclareVtab(&rc, p);
-
-fts3_init_out:
- sqlite3_free(zPrefix);
- sqlite3_free(aIndex);
- sqlite3_free(zCompress);
- sqlite3_free(zUncompress);
- sqlite3_free(zContent);
- sqlite3_free(zLanguageid);
- for(i=0; i<nNotindexed; i++) sqlite3_free(azNotindexed[i]);
- sqlite3_free((void *)aCol);
- sqlite3_free((void *)azNotindexed);
- if( rc!=SQLITE_OK ){
- if( p ){
- fts3DisconnectMethod((sqlite3_vtab *)p);
- }else if( pTokenizer ){
- pTokenizer->pModule->xDestroy(pTokenizer);
- }
- }else{
- assert( p->pSegments==0 );
- *ppVTab = &p->base;
- }
- return rc;
-}
-
-/*
-** The xConnect() and xCreate() methods for the virtual table. All the
-** work is done in function fts3InitVtab().
-*/
-static int fts3ConnectMethod(
- sqlite3 *db, /* Database connection */
- void *pAux, /* Pointer to tokenizer hash table */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- return fts3InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr);
-}
-static int fts3CreateMethod(
- sqlite3 *db, /* Database connection */
- void *pAux, /* Pointer to tokenizer hash table */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
-}
-
-/*
-** Set the pIdxInfo->estimatedRows variable to nRow. Unless this
-** extension is currently being used by a version of SQLite too old to
-** support estimatedRows. In that case this function is a no-op.
-*/
-static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
-#if SQLITE_VERSION_NUMBER>=3008002
- if( sqlite3_libversion_number()>=3008002 ){
- pIdxInfo->estimatedRows = nRow;
- }
-#endif
-}
-
-/*
-** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
-** extension is currently being used by a version of SQLite too old to
-** support index-info flags. In that case this function is a no-op.
-*/
-static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){
-#if SQLITE_VERSION_NUMBER>=3008012
- if( sqlite3_libversion_number()>=3008012 ){
- pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
- }
-#endif
-}
-
-/*
-** Implementation of the xBestIndex method for FTS3 tables. There
-** are three possible strategies, in order of preference:
-**
-** 1. Direct lookup by rowid or docid.
-** 2. Full-text search using a MATCH operator on a non-docid column.
-** 3. Linear scan of %_content table.
-*/
-static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
- Fts3Table *p = (Fts3Table *)pVTab;
- int i; /* Iterator variable */
- int iCons = -1; /* Index of constraint to use */
-
- int iLangidCons = -1; /* Index of langid=x constraint, if present */
- int iDocidGe = -1; /* Index of docid>=x constraint, if present */
- int iDocidLe = -1; /* Index of docid<=x constraint, if present */
- int iIdx;
-
- /* By default use a full table scan. This is an expensive option,
- ** so search through the constraints to see if a more efficient
- ** strategy is possible.
- */
- pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
- pInfo->estimatedCost = 5000000;
- for(i=0; i<pInfo->nConstraint; i++){
- int bDocid; /* True if this constraint is on docid */
- struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
- if( pCons->usable==0 ){
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
- /* There exists an unusable MATCH constraint. This means that if
- ** the planner does elect to use the results of this call as part
- ** of the overall query plan the user will see an "unable to use
- ** function MATCH in the requested context" error. To discourage
- ** this, return a very high cost here. */
- pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
- pInfo->estimatedCost = 1e50;
- fts3SetEstimatedRows(pInfo, ((sqlite3_int64)1) << 50);
- return SQLITE_OK;
- }
- continue;
- }
-
- bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1);
-
- /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
- if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){
- pInfo->idxNum = FTS3_DOCID_SEARCH;
- pInfo->estimatedCost = 1.0;
- iCons = i;
- }
-
- /* A MATCH constraint. Use a full-text search.
- **
- ** If there is more than one MATCH constraint available, use the first
- ** one encountered. If there is both a MATCH constraint and a direct
- ** rowid/docid lookup, prefer the MATCH strategy. This is done even
- ** though the rowid/docid lookup is faster than a MATCH query, selecting
- ** it would lead to an "unable to use function MATCH in the requested
- ** context" error.
- */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH
- && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn
- ){
- pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn;
- pInfo->estimatedCost = 2.0;
- iCons = i;
- }
-
- /* Equality constraint on the langid column */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
- && pCons->iColumn==p->nColumn + 2
- ){
- iLangidCons = i;
- }
-
- if( bDocid ){
- switch( pCons->op ){
- case SQLITE_INDEX_CONSTRAINT_GE:
- case SQLITE_INDEX_CONSTRAINT_GT:
- iDocidGe = i;
- break;
-
- case SQLITE_INDEX_CONSTRAINT_LE:
- case SQLITE_INDEX_CONSTRAINT_LT:
- iDocidLe = i;
- break;
- }
- }
- }
-
- /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */
- if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo);
-
- iIdx = 1;
- if( iCons>=0 ){
- pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
- pInfo->aConstraintUsage[iCons].omit = 1;
- }
- if( iLangidCons>=0 ){
- pInfo->idxNum |= FTS3_HAVE_LANGID;
- pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
- }
- if( iDocidGe>=0 ){
- pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
- pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
- }
- if( iDocidLe>=0 ){
- pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
- pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
- }
-
- /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
- ** docid) order. Both ascending and descending are possible.
- */
- if( pInfo->nOrderBy==1 ){
- struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0];
- if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){
- if( pOrder->desc ){
- pInfo->idxStr = "DESC";
- }else{
- pInfo->idxStr = "ASC";
- }
- pInfo->orderByConsumed = 1;
- }
- }
-
- assert( p->pSegments==0 );
- return SQLITE_OK;
-}
-
-/*
-** Implementation of xOpen method.
-*/
-static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
- sqlite3_vtab_cursor *pCsr; /* Allocated cursor */
-
- UNUSED_PARAMETER(pVTab);
-
- /* Allocate a buffer large enough for an Fts3Cursor structure. If the
- ** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
- ** if the allocation fails, return SQLITE_NOMEM.
- */
- *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));
- if( !pCsr ){
- return SQLITE_NOMEM;
- }
- memset(pCsr, 0, sizeof(Fts3Cursor));
- return SQLITE_OK;
-}
-
-/*
-** Finalize the statement handle at pCsr->pStmt.
-**
-** Or, if that statement handle is one created by fts3CursorSeekStmt(),
-** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement
-** pointer there instead of finalizing it.
-*/
-static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
- if( pCsr->bSeekStmt ){
- Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
- if( p->pSeekStmt==0 ){
- p->pSeekStmt = pCsr->pStmt;
- sqlite3_reset(pCsr->pStmt);
- pCsr->pStmt = 0;
- }
- pCsr->bSeekStmt = 0;
- }
- sqlite3_finalize(pCsr->pStmt);
-}
-
-/*
-** Free all resources currently held by the cursor passed as the only
-** argument.
-*/
-static void fts3ClearCursor(Fts3Cursor *pCsr){
- fts3CursorFinalizeStmt(pCsr);
- sqlite3Fts3FreeDeferredTokens(pCsr);
- sqlite3_free(pCsr->aDoclist);
- sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
- sqlite3Fts3ExprFree(pCsr->pExpr);
- memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
-}
-
-/*
-** Close the cursor. For additional information see the documentation
-** on the xClose method of the virtual table interface.
-*/
-static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
- Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
- assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
- fts3ClearCursor(pCsr);
- assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then
-** compose and prepare an SQL statement of the form:
-**
-** "SELECT <columns> FROM %_content WHERE rowid = ?"
-**
-** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
-** it. If an error occurs, return an SQLite error code.
-*/
-static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
- int rc = SQLITE_OK;
- if( pCsr->pStmt==0 ){
- Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
- char *zSql;
- if( p->pSeekStmt ){
- pCsr->pStmt = p->pSeekStmt;
- p->pSeekStmt = 0;
- }else{
- zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
- if( !zSql ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
- sqlite3_free(zSql);
- }
- if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
- }
- return rc;
-}
-
-/*
-** Position the pCsr->pStmt statement so that it is on the row
-** of the %_content table that contains the last match. Return
-** SQLITE_OK on success.
-*/
-static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
- int rc = SQLITE_OK;
- if( pCsr->isRequireSeek ){
- rc = fts3CursorSeekStmt(pCsr);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
- pCsr->isRequireSeek = 0;
- if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
- return SQLITE_OK;
- }else{
- rc = sqlite3_reset(pCsr->pStmt);
- if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
- /* If no row was found and no error has occurred, then the %_content
- ** table is missing a row that is present in the full-text index.
- ** The data structures are corrupt. */
- rc = FTS_CORRUPT_VTAB;
- pCsr->isEof = 1;
- }
- }
- }
- }
-
- if( rc!=SQLITE_OK && pContext ){
- sqlite3_result_error_code(pContext, rc);
- }
- return rc;
-}
-
-/*
-** This function is used to process a single interior node when searching
-** a b-tree for a term or term prefix. The node data is passed to this
-** function via the zNode/nNode parameters. The term to search for is
-** passed in zTerm/nTerm.
-**
-** If piFirst is not NULL, then this function sets *piFirst to the blockid
-** of the child node that heads the sub-tree that may contain the term.
-**
-** If piLast is not NULL, then *piLast is set to the right-most child node
-** that heads a sub-tree that may contain a term for which zTerm/nTerm is
-** a prefix.
-**
-** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
-*/
-static int fts3ScanInteriorNode(
- const char *zTerm, /* Term to select leaves for */
- int nTerm, /* Size of term zTerm in bytes */
- const char *zNode, /* Buffer containing segment interior node */
- int nNode, /* Size of buffer at zNode */
- sqlite3_int64 *piFirst, /* OUT: Selected child node */
- sqlite3_int64 *piLast /* OUT: Selected child node */
-){
- int rc = SQLITE_OK; /* Return code */
- const char *zCsr = zNode; /* Cursor to iterate through node */
- const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
- char *zBuffer = 0; /* Buffer to load terms into */
- int nAlloc = 0; /* Size of allocated buffer */
- int isFirstTerm = 1; /* True when processing first term on page */
- sqlite3_int64 iChild; /* Block id of child node to descend to */
-
- /* Skip over the 'height' varint that occurs at the start of every
- ** interior node. Then load the blockid of the left-child of the b-tree
- ** node into variable iChild.
- **
- ** Even if the data structure on disk is corrupted, this (reading two
- ** varints from the buffer) does not risk an overread. If zNode is a
- ** root node, then the buffer comes from a SELECT statement. SQLite does
- ** not make this guarantee explicitly, but in practice there are always
- ** either more than 20 bytes of allocated space following the nNode bytes of
- ** contents, or two zero bytes. Or, if the node is read from the %_segments
- ** table, then there are always 20 bytes of zeroed padding following the
- ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
- */
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- if( zCsr>zEnd ){
- return FTS_CORRUPT_VTAB;
- }
-
- while( zCsr<zEnd && (piFirst || piLast) ){
- int cmp; /* memcmp() result */
- int nSuffix; /* Size of term suffix */
- int nPrefix = 0; /* Size of term prefix */
- int nBuffer; /* Total term size */
-
- /* Load the next term on the node into zBuffer. Use realloc() to expand
- ** the size of zBuffer if required. */
- if( !isFirstTerm ){
- zCsr += fts3GetVarint32(zCsr, &nPrefix);
- }
- isFirstTerm = 0;
- zCsr += fts3GetVarint32(zCsr, &nSuffix);
-
- assert( nPrefix>=0 && nSuffix>=0 );
- if( &zCsr[nSuffix]>zEnd ){
- rc = FTS_CORRUPT_VTAB;
- goto finish_scan;
- }
- if( nPrefix+nSuffix>nAlloc ){
- char *zNew;
- nAlloc = (nPrefix+nSuffix) * 2;
- zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
- if( !zNew ){
- rc = SQLITE_NOMEM;
- goto finish_scan;
- }
- zBuffer = zNew;
- }
- assert( zBuffer );
- memcpy(&zBuffer[nPrefix], zCsr, nSuffix);
- nBuffer = nPrefix + nSuffix;
- zCsr += nSuffix;
-
- /* Compare the term we are searching for with the term just loaded from
- ** the interior node. If the specified term is greater than or equal
- ** to the term from the interior node, then all terms on the sub-tree
- ** headed by node iChild are smaller than zTerm. No need to search
- ** iChild.
- **
- ** If the interior node term is larger than the specified term, then
- ** the tree headed by iChild may contain the specified term.
- */
- cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
- if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
- piFirst = 0;
- }
-
- if( piLast && cmp<0 ){
- *piLast = iChild;
- piLast = 0;
- }
-
- iChild++;
- };
-
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
-
- finish_scan:
- sqlite3_free(zBuffer);
- return rc;
-}
-
-
-/*
-** The buffer pointed to by argument zNode (size nNode bytes) contains an
-** interior node of a b-tree segment. The zTerm buffer (size nTerm bytes)
-** contains a term. This function searches the sub-tree headed by the zNode
-** node for the range of leaf nodes that may contain the specified term
-** or terms for which the specified term is a prefix.
-**
-** If piLeaf is not NULL, then *piLeaf is set to the blockid of the
-** left-most leaf node in the tree that may contain the specified term.
-** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the
-** right-most leaf node that may contain a term for which the specified
-** term is a prefix.
-**
-** It is possible that the range of returned leaf nodes does not contain
-** the specified term or any terms for which it is a prefix. However, if the
-** segment does contain any such terms, they are stored within the identified
-** range. Because this function only inspects interior segment nodes (and
-** never loads leaf nodes into memory), it is not possible to be sure.
-**
-** If an error occurs, an error code other than SQLITE_OK is returned.
-*/
-static int fts3SelectLeaf(
- Fts3Table *p, /* Virtual table handle */
- const char *zTerm, /* Term to select leaves for */
- int nTerm, /* Size of term zTerm in bytes */
- const char *zNode, /* Buffer containing segment interior node */
- int nNode, /* Size of buffer at zNode */
- sqlite3_int64 *piLeaf, /* Selected leaf node */
- sqlite3_int64 *piLeaf2 /* Selected leaf node */
-){
- int rc = SQLITE_OK; /* Return code */
- int iHeight; /* Height of this node in tree */
-
- assert( piLeaf || piLeaf2 );
-
- fts3GetVarint32(zNode, &iHeight);
- rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
- assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
-
- if( rc==SQLITE_OK && iHeight>1 ){
- char *zBlob = 0; /* Blob read from %_segments table */
- int nBlob = 0; /* Size of zBlob in bytes */
-
- if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
- rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0);
- if( rc==SQLITE_OK ){
- rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0);
- }
- sqlite3_free(zBlob);
- piLeaf = 0;
- zBlob = 0;
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
- }
- if( rc==SQLITE_OK ){
- rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
- }
- sqlite3_free(zBlob);
- }
-
- return rc;
-}
-
-/*
-** This function is used to create delta-encoded serialized lists of FTS3
-** varints. Each call to this function appends a single varint to a list.
-*/
-static void fts3PutDeltaVarint(
- char **pp, /* IN/OUT: Output pointer */
- sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
- sqlite3_int64 iVal /* Write this value to the list */
-){
- assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
- *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
- *piPrev = iVal;
-}
-
-/*
-** When this function is called, *ppPoslist is assumed to point to the
-** start of a position-list. After it returns, *ppPoslist points to the
-** first byte after the position-list.
-**
-** A position list is list of positions (delta encoded) and columns for
-** a single document record of a doclist. So, in other words, this
-** routine advances *ppPoslist so that it points to the next docid in
-** the doclist, or to the first byte past the end of the doclist.
-**
-** If pp is not NULL, then the contents of the position list are copied
-** to *pp. *pp is set to point to the first byte past the last byte copied
-** before this function returns.
-*/
-static void fts3PoslistCopy(char **pp, char **ppPoslist){
- char *pEnd = *ppPoslist;
- char c = 0;
-
- /* The end of a position list is marked by a zero encoded as an FTS3
- ** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by
- ** a byte with the 0x80 bit set, then it is not a varint 0, but the tail
- ** of some other, multi-byte, value.
- **
- ** The following while-loop moves pEnd to point to the first byte that is not
- ** immediately preceded by a byte with the 0x80 bit set. Then increments
- ** pEnd once more so that it points to the byte immediately following the
- ** last byte in the position-list.
- */
- while( *pEnd | c ){
- c = *pEnd++ & 0x80;
- testcase( c!=0 && (*pEnd)==0 );
- }
- pEnd++; /* Advance past the POS_END terminator byte */
-
- if( pp ){
- int n = (int)(pEnd - *ppPoslist);
- char *p = *pp;
- memcpy(p, *ppPoslist, n);
- p += n;
- *pp = p;
- }
- *ppPoslist = pEnd;
-}
-
-/*
-** When this function is called, *ppPoslist is assumed to point to the
-** start of a column-list. After it returns, *ppPoslist points to the
-** to the terminator (POS_COLUMN or POS_END) byte of the column-list.
-**
-** A column-list is list of delta-encoded positions for a single column
-** within a single document within a doclist.
-**
-** The column-list is terminated either by a POS_COLUMN varint (1) or
-** a POS_END varint (0). This routine leaves *ppPoslist pointing to
-** the POS_COLUMN or POS_END that terminates the column-list.
-**
-** If pp is not NULL, then the contents of the column-list are copied
-** to *pp. *pp is set to point to the first byte past the last byte copied
-** before this function returns. The POS_COLUMN or POS_END terminator
-** is not copied into *pp.
-*/
-static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
- char *pEnd = *ppPoslist;
- char c = 0;
-
- /* A column-list is terminated by either a 0x01 or 0x00 byte that is
- ** not part of a multi-byte varint.
- */
- while( 0xFE & (*pEnd | c) ){
- c = *pEnd++ & 0x80;
- testcase( c!=0 && ((*pEnd)&0xfe)==0 );
- }
- if( pp ){
- int n = (int)(pEnd - *ppPoslist);
- char *p = *pp;
- memcpy(p, *ppPoslist, n);
- p += n;
- *pp = p;
- }
- *ppPoslist = pEnd;
-}
-
-/*
-** Value used to signify the end of an position-list. This is safe because
-** it is not possible to have a document with 2^31 terms.
-*/
-#define POSITION_LIST_END 0x7fffffff
-
-/*
-** This function is used to help parse position-lists. When this function is
-** called, *pp may point to the start of the next varint in the position-list
-** being parsed, or it may point to 1 byte past the end of the position-list
-** (in which case **pp will be a terminator bytes POS_END (0) or
-** (1)).
-**
-** If *pp points past the end of the current position-list, set *pi to
-** POSITION_LIST_END and return. Otherwise, read the next varint from *pp,
-** increment the current value of *pi by the value read, and set *pp to
-** point to the next value before returning.
-**
-** Before calling this routine *pi must be initialized to the value of
-** the previous position, or zero if we are reading the first position
-** in the position-list. Because positions are delta-encoded, the value
-** of the previous position is needed in order to compute the value of
-** the next position.
-*/
-static void fts3ReadNextPos(
- char **pp, /* IN/OUT: Pointer into position-list buffer */
- sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
-){
- if( (**pp)&0xFE ){
- fts3GetDeltaVarint(pp, pi);
- *pi -= 2;
- }else{
- *pi = POSITION_LIST_END;
- }
-}
-
-/*
-** If parameter iCol is not 0, write an POS_COLUMN (1) byte followed by
-** the value of iCol encoded as a varint to *pp. This will start a new
-** column list.
-**
-** Set *pp to point to the byte just after the last byte written before
-** returning (do not modify it if iCol==0). Return the total number of bytes
-** written (0 if iCol==0).
-*/
-static int fts3PutColNumber(char **pp, int iCol){
- int n = 0; /* Number of bytes written */
- if( iCol ){
- char *p = *pp; /* Output pointer */
- n = 1 + sqlite3Fts3PutVarint(&p[1], iCol);
- *p = 0x01;
- *pp = &p[n];
- }
- return n;
-}
-
-/*
-** Compute the union of two position lists. The output written
-** into *pp contains all positions of both *pp1 and *pp2 in sorted
-** order and with any duplicates removed. All pointers are
-** updated appropriately. The caller is responsible for insuring
-** that there is enough space in *pp to hold the complete output.
-*/
-static void fts3PoslistMerge(
- char **pp, /* Output buffer */
- char **pp1, /* Left input list */
- char **pp2 /* Right input list */
-){
- char *p = *pp;
- char *p1 = *pp1;
- char *p2 = *pp2;
-
- while( *p1 || *p2 ){
- int iCol1; /* The current column index in pp1 */
- int iCol2; /* The current column index in pp2 */
-
- if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
- else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
- else iCol1 = 0;
-
- if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
- else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
- else iCol2 = 0;
-
- if( iCol1==iCol2 ){
- sqlite3_int64 i1 = 0; /* Last position from pp1 */
- sqlite3_int64 i2 = 0; /* Last position from pp2 */
- sqlite3_int64 iPrev = 0;
- int n = fts3PutColNumber(&p, iCol1);
- p1 += n;
- p2 += n;
-
- /* At this point, both p1 and p2 point to the start of column-lists
- ** for the same column (the column with index iCol1 and iCol2).
- ** A column-list is a list of non-negative delta-encoded varints, each
- ** incremented by 2 before being stored. Each list is terminated by a
- ** POS_END (0) or POS_COLUMN (1). The following block merges the two lists
- ** and writes the results to buffer p. p is left pointing to the byte
- ** after the list written. No terminator (POS_END or POS_COLUMN) is
- ** written to the output.
- */
- fts3GetDeltaVarint(&p1, &i1);
- fts3GetDeltaVarint(&p2, &i2);
- do {
- fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
- iPrev -= 2;
- if( i1==i2 ){
- fts3ReadNextPos(&p1, &i1);
- fts3ReadNextPos(&p2, &i2);
- }else if( i1<i2 ){
- fts3ReadNextPos(&p1, &i1);
- }else{
- fts3ReadNextPos(&p2, &i2);
- }
- }while( i1!=POSITION_LIST_END || i2!=POSITION_LIST_END );
- }else if( iCol1<iCol2 ){
- p1 += fts3PutColNumber(&p, iCol1);
- fts3ColumnlistCopy(&p, &p1);
- }else{
- p2 += fts3PutColNumber(&p, iCol2);
- fts3ColumnlistCopy(&p, &p2);
- }
- }
-
- *p++ = POS_END;
- *pp = p;
- *pp1 = p1 + 1;
- *pp2 = p2 + 1;
-}
-
-/*
-** This function is used to merge two position lists into one. When it is
-** called, *pp1 and *pp2 must both point to position lists. A position-list is
-** the part of a doclist that follows each document id. For example, if a row
-** contains:
-**
-** 'a b c'|'x y z'|'a b b a'
-**
-** Then the position list for this row for token 'b' would consist of:
-**
-** 0x02 0x01 0x02 0x03 0x03 0x00
-**
-** When this function returns, both *pp1 and *pp2 are left pointing to the
-** byte following the 0x00 terminator of their respective position lists.
-**
-** If isSaveLeft is 0, an entry is added to the output position list for
-** each position in *pp2 for which there exists one or more positions in
-** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
-** when the *pp1 token appears before the *pp2 token, but not more than nToken
-** slots before it.
-**
-** e.g. nToken==1 searches for adjacent positions.
-*/
-static int fts3PoslistPhraseMerge(
- char **pp, /* IN/OUT: Preallocated output buffer */
- int nToken, /* Maximum difference in token positions */
- int isSaveLeft, /* Save the left position */
- int isExact, /* If *pp1 is exactly nTokens before *pp2 */
- char **pp1, /* IN/OUT: Left input list */
- char **pp2 /* IN/OUT: Right input list */
-){
- char *p = *pp;
- char *p1 = *pp1;
- char *p2 = *pp2;
- int iCol1 = 0;
- int iCol2 = 0;
-
- /* Never set both isSaveLeft and isExact for the same invocation. */
- assert( isSaveLeft==0 || isExact==0 );
-
- assert( p!=0 && *p1!=0 && *p2!=0 );
- if( *p1==POS_COLUMN ){
- p1++;
- p1 += fts3GetVarint32(p1, &iCol1);
- }
- if( *p2==POS_COLUMN ){
- p2++;
- p2 += fts3GetVarint32(p2, &iCol2);
- }
-
- while( 1 ){
- if( iCol1==iCol2 ){
- char *pSave = p;
- sqlite3_int64 iPrev = 0;
- sqlite3_int64 iPos1 = 0;
- sqlite3_int64 iPos2 = 0;
-
- if( iCol1 ){
- *p++ = POS_COLUMN;
- p += sqlite3Fts3PutVarint(p, iCol1);
- }
-
- assert( *p1!=POS_END && *p1!=POS_COLUMN );
- assert( *p2!=POS_END && *p2!=POS_COLUMN );
- fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
- fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
-
- while( 1 ){
- if( iPos2==iPos1+nToken
- || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken)
- ){
- sqlite3_int64 iSave;
- iSave = isSaveLeft ? iPos1 : iPos2;
- fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2;
- pSave = 0;
- assert( p );
- }
- if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){
- if( (*p2&0xFE)==0 ) break;
- fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
- }else{
- if( (*p1&0xFE)==0 ) break;
- fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
- }
- }
-
- if( pSave ){
- assert( pp && p );
- p = pSave;
- }
-
- fts3ColumnlistCopy(0, &p1);
- fts3ColumnlistCopy(0, &p2);
- assert( (*p1&0xFE)==0 && (*p2&0xFE)==0 );
- if( 0==*p1 || 0==*p2 ) break;
-
- p1++;
- p1 += fts3GetVarint32(p1, &iCol1);
- p2++;
- p2 += fts3GetVarint32(p2, &iCol2);
- }
-
- /* Advance pointer p1 or p2 (whichever corresponds to the smaller of
- ** iCol1 and iCol2) so that it points to either the 0x00 that marks the
- ** end of the position list, or the 0x01 that precedes the next
- ** column-number in the position list.
- */
- else if( iCol1<iCol2 ){
- fts3ColumnlistCopy(0, &p1);
- if( 0==*p1 ) break;
- p1++;
- p1 += fts3GetVarint32(p1, &iCol1);
- }else{
- fts3ColumnlistCopy(0, &p2);
- if( 0==*p2 ) break;
- p2++;
- p2 += fts3GetVarint32(p2, &iCol2);
- }
- }
-
- fts3PoslistCopy(0, &p2);
- fts3PoslistCopy(0, &p1);
- *pp1 = p1;
- *pp2 = p2;
- if( *pp==p ){
- return 0;
- }
- *p++ = 0x00;
- *pp = p;
- return 1;
-}
-
-/*
-** Merge two position-lists as required by the NEAR operator. The argument
-** position lists correspond to the left and right phrases of an expression
-** like:
-**
-** "phrase 1" NEAR "phrase number 2"
-**
-** Position list *pp1 corresponds to the left-hand side of the NEAR
-** expression and *pp2 to the right. As usual, the indexes in the position
-** lists are the offsets of the last token in each phrase (tokens "1" and "2"
-** in the example above).
-**
-** The output position list - written to *pp - is a copy of *pp2 with those
-** entries that are not sufficiently NEAR entries in *pp1 removed.
-*/
-static int fts3PoslistNearMerge(
- char **pp, /* Output buffer */
- char *aTmp, /* Temporary buffer space */
- int nRight, /* Maximum difference in token positions */
- int nLeft, /* Maximum difference in token positions */
- char **pp1, /* IN/OUT: Left input list */
- char **pp2 /* IN/OUT: Right input list */
-){
- char *p1 = *pp1;
- char *p2 = *pp2;
-
- char *pTmp1 = aTmp;
- char *pTmp2;
- char *aTmp2;
- int res = 1;
-
- fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
- aTmp2 = pTmp2 = pTmp1;
- *pp1 = p1;
- *pp2 = p2;
- fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
- if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
- fts3PoslistMerge(pp, &aTmp, &aTmp2);
- }else if( pTmp1!=aTmp ){
- fts3PoslistCopy(pp, &aTmp);
- }else if( pTmp2!=aTmp2 ){
- fts3PoslistCopy(pp, &aTmp2);
- }else{
- res = 0;
- }
-
- return res;
-}
-
-/*
-** An instance of this function is used to merge together the (potentially
-** large number of) doclists for each term that matches a prefix query.
-** See function fts3TermSelectMerge() for details.
-*/
-typedef struct TermSelect TermSelect;
-struct TermSelect {
- char *aaOutput[16]; /* Malloc'd output buffers */
- int anOutput[16]; /* Size each output buffer in bytes */
-};
-
-/*
-** This function is used to read a single varint from a buffer. Parameter
-** pEnd points 1 byte past the end of the buffer. When this function is
-** called, if *pp points to pEnd or greater, then the end of the buffer
-** has been reached. In this case *pp is set to 0 and the function returns.
-**
-** If *pp does not point to or past pEnd, then a single varint is read
-** from *pp. *pp is then set to point 1 byte past the end of the read varint.
-**
-** If bDescIdx is false, the value read is added to *pVal before returning.
-** If it is true, the value read is subtracted from *pVal before this
-** function returns.
-*/
-static void fts3GetDeltaVarint3(
- char **pp, /* IN/OUT: Point to read varint from */
- char *pEnd, /* End of buffer */
- int bDescIdx, /* True if docids are descending */
- sqlite3_int64 *pVal /* IN/OUT: Integer value */
-){
- if( *pp>=pEnd ){
- *pp = 0;
- }else{
- sqlite3_int64 iVal;
- *pp += sqlite3Fts3GetVarint(*pp, &iVal);
- if( bDescIdx ){
- *pVal -= iVal;
- }else{
- *pVal += iVal;
- }
- }
-}
-
-/*
-** This function is used to write a single varint to a buffer. The varint
-** is written to *pp. Before returning, *pp is set to point 1 byte past the
-** end of the value written.
-**
-** If *pbFirst is zero when this function is called, the value written to
-** the buffer is that of parameter iVal.
-**
-** If *pbFirst is non-zero when this function is called, then the value
-** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
-** (if bDescIdx is non-zero).
-**
-** Before returning, this function always sets *pbFirst to 1 and *piPrev
-** to the value of parameter iVal.
-*/
-static void fts3PutDeltaVarint3(
- char **pp, /* IN/OUT: Output pointer */
- int bDescIdx, /* True for descending docids */
- sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
- int *pbFirst, /* IN/OUT: True after first int written */
- sqlite3_int64 iVal /* Write this value to the list */
-){
- sqlite3_int64 iWrite;
- if( bDescIdx==0 || *pbFirst==0 ){
- iWrite = iVal - *piPrev;
- }else{
- iWrite = *piPrev - iVal;
- }
- assert( *pbFirst || *piPrev==0 );
- assert( *pbFirst==0 || iWrite>0 );
- *pp += sqlite3Fts3PutVarint(*pp, iWrite);
- *piPrev = iVal;
- *pbFirst = 1;
-}
-
-
-/*
-** This macro is used by various functions that merge doclists. The two
-** arguments are 64-bit docid values. If the value of the stack variable
-** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
-** Otherwise, (i2-i1).
-**
-** Using this makes it easier to write code that can merge doclists that are
-** sorted in either ascending or descending order.
-*/
-#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
-
-/*
-** This function does an "OR" merge of two doclists (output contains all
-** positions contained in either argument doclist). If the docids in the
-** input doclists are sorted in ascending order, parameter bDescDoclist
-** should be false. If they are sorted in ascending order, it should be
-** passed a non-zero value.
-**
-** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
-** containing the output doclist and SQLITE_OK is returned. In this case
-** *pnOut is set to the number of bytes in the output doclist.
-**
-** If an error occurs, an SQLite error code is returned. The output values
-** are undefined in this case.
-*/
-static int fts3DoclistOrMerge(
- int bDescDoclist, /* True if arguments are desc */
- char *a1, int n1, /* First doclist */
- char *a2, int n2, /* Second doclist */
- char **paOut, int *pnOut /* OUT: Malloc'd doclist */
-){
- sqlite3_int64 i1 = 0;
- sqlite3_int64 i2 = 0;
- sqlite3_int64 iPrev = 0;
- char *pEnd1 = &a1[n1];
- char *pEnd2 = &a2[n2];
- char *p1 = a1;
- char *p2 = a2;
- char *p;
- char *aOut;
- int bFirstOut = 0;
-
- *paOut = 0;
- *pnOut = 0;
-
- /* Allocate space for the output. Both the input and output doclists
- ** are delta encoded. If they are in ascending order (bDescDoclist==0),
- ** then the first docid in each list is simply encoded as a varint. For
- ** each subsequent docid, the varint stored is the difference between the
- ** current and previous docid (a positive number - since the list is in
- ** ascending order).
- **
- ** The first docid written to the output is therefore encoded using the
- ** same number of bytes as it is in whichever of the input lists it is
- ** read from. And each subsequent docid read from the same input list
- ** consumes either the same or less bytes as it did in the input (since
- ** the difference between it and the previous value in the output must
- ** be a positive value less than or equal to the delta value read from
- ** the input list). The same argument applies to all but the first docid
- ** read from the 'other' list. And to the contents of all position lists
- ** that will be copied and merged from the input to the output.
- **
- ** However, if the first docid copied to the output is a negative number,
- ** then the encoding of the first docid from the 'other' input list may
- ** be larger in the output than it was in the input (since the delta value
- ** may be a larger positive integer than the actual docid).
- **
- ** The space required to store the output is therefore the sum of the
- ** sizes of the two inputs, plus enough space for exactly one of the input
- ** docids to grow.
- **
- ** A symetric argument may be made if the doclists are in descending
- ** order.
- */
- aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
- if( !aOut ) return SQLITE_NOMEM;
-
- p = aOut;
- fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
- fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
- while( p1 || p2 ){
- sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
-
- if( p2 && p1 && iDiff==0 ){
- fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
- fts3PoslistMerge(&p, &p1, &p2);
- fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
- fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
- }else if( !p2 || (p1 && iDiff<0) ){
- fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
- fts3PoslistCopy(&p, &p1);
- fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
- }else{
- fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
- fts3PoslistCopy(&p, &p2);
- fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
- }
- }
-
- *paOut = aOut;
- *pnOut = (int)(p-aOut);
- assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
- return SQLITE_OK;
-}
-
-/*
-** This function does a "phrase" merge of two doclists. In a phrase merge,
-** the output contains a copy of each position from the right-hand input
-** doclist for which there is a position in the left-hand input doclist
-** exactly nDist tokens before it.
-**
-** If the docids in the input doclists are sorted in ascending order,
-** parameter bDescDoclist should be false. If they are sorted in ascending
-** order, it should be passed a non-zero value.
-**
-** The right-hand input doclist is overwritten by this function.
-*/
-static int fts3DoclistPhraseMerge(
- int bDescDoclist, /* True if arguments are desc */
- int nDist, /* Distance from left to right (1=adjacent) */
- char *aLeft, int nLeft, /* Left doclist */
- char **paRight, int *pnRight /* IN/OUT: Right/output doclist */
-){
- sqlite3_int64 i1 = 0;
- sqlite3_int64 i2 = 0;
- sqlite3_int64 iPrev = 0;
- char *aRight = *paRight;
- char *pEnd1 = &aLeft[nLeft];
- char *pEnd2 = &aRight[*pnRight];
- char *p1 = aLeft;
- char *p2 = aRight;
- char *p;
- int bFirstOut = 0;
- char *aOut;
-
- assert( nDist>0 );
- if( bDescDoclist ){
- aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
- if( aOut==0 ) return SQLITE_NOMEM;
- }else{
- aOut = aRight;
- }
- p = aOut;
-
- fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
- fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
-
- while( p1 && p2 ){
- sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
- if( iDiff==0 ){
- char *pSave = p;
- sqlite3_int64 iPrevSave = iPrev;
- int bFirstOutSave = bFirstOut;
-
- fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
- if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
- p = pSave;
- iPrev = iPrevSave;
- bFirstOut = bFirstOutSave;
- }
- fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
- fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
- }else if( iDiff<0 ){
- fts3PoslistCopy(0, &p1);
- fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
- }else{
- fts3PoslistCopy(0, &p2);
- fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
- }
- }
-
- *pnRight = (int)(p - aOut);
- if( bDescDoclist ){
- sqlite3_free(aRight);
- *paRight = aOut;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Argument pList points to a position list nList bytes in size. This
-** function checks to see if the position list contains any entries for
-** a token in position 0 (of any column). If so, it writes argument iDelta
-** to the output buffer pOut, followed by a position list consisting only
-** of the entries from pList at position 0, and terminated by an 0x00 byte.
-** The value returned is the number of bytes written to pOut (if any).
-*/
-int sqlite3Fts3FirstFilter(
- sqlite3_int64 iDelta, /* Varint that may be written to pOut */
- char *pList, /* Position list (no 0x00 term) */
- int nList, /* Size of pList in bytes */
- char *pOut /* Write output here */
-){
- int nOut = 0;
- int bWritten = 0; /* True once iDelta has been written */
- char *p = pList;
- char *pEnd = &pList[nList];
-
- if( *p!=0x01 ){
- if( *p==0x02 ){
- nOut += sqlite3Fts3PutVarint(&pOut[nOut], iDelta);
- pOut[nOut++] = 0x02;
- bWritten = 1;
- }
- fts3ColumnlistCopy(0, &p);
- }
-
- while( p<pEnd ){
- sqlite3_int64 iCol;
- p++;
- p += sqlite3Fts3GetVarint(p, &iCol);
- if( *p==0x02 ){
- if( bWritten==0 ){
- nOut += sqlite3Fts3PutVarint(&pOut[nOut], iDelta);
- bWritten = 1;
- }
- pOut[nOut++] = 0x01;
- nOut += sqlite3Fts3PutVarint(&pOut[nOut], iCol);
- pOut[nOut++] = 0x02;
- }
- fts3ColumnlistCopy(0, &p);
- }
- if( bWritten ){
- pOut[nOut++] = 0x00;
- }
-
- return nOut;
-}
-
-
-/*
-** Merge all doclists in the TermSelect.aaOutput[] array into a single
-** doclist stored in TermSelect.aaOutput[0]. If successful, delete all
-** other doclists (except the aaOutput[0] one) and return SQLITE_OK.
-**
-** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
-** the responsibility of the caller to free any doclists left in the
-** TermSelect.aaOutput[] array.
-*/
-static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
- char *aOut = 0;
- int nOut = 0;
- int i;
-
- /* Loop through the doclists in the aaOutput[] array. Merge them all
- ** into a single doclist.
- */
- for(i=0; i<SizeofArray(pTS->aaOutput); i++){
- if( pTS->aaOutput[i] ){
- if( !aOut ){
- aOut = pTS->aaOutput[i];
- nOut = pTS->anOutput[i];
- pTS->aaOutput[i] = 0;
- }else{
- int nNew;
- char *aNew;
-
- int rc = fts3DoclistOrMerge(p->bDescIdx,
- pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew
- );
- if( rc!=SQLITE_OK ){
- sqlite3_free(aOut);
- return rc;
- }
-
- sqlite3_free(pTS->aaOutput[i]);
- sqlite3_free(aOut);
- pTS->aaOutput[i] = 0;
- aOut = aNew;
- nOut = nNew;
- }
- }
- }
-
- pTS->aaOutput[0] = aOut;
- pTS->anOutput[0] = nOut;
- return SQLITE_OK;
-}
-
-/*
-** Merge the doclist aDoclist/nDoclist into the TermSelect object passed
-** as the first argument. The merge is an "OR" merge (see function
-** fts3DoclistOrMerge() for details).
-**
-** This function is called with the doclist for each term that matches
-** a queried prefix. It merges all these doclists into one, the doclist
-** for the specified prefix. Since there can be a very large number of
-** doclists to merge, the merging is done pair-wise using the TermSelect
-** object.
-**
-** This function returns SQLITE_OK if the merge is successful, or an
-** SQLite error code (SQLITE_NOMEM) if an error occurs.
-*/
-static int fts3TermSelectMerge(
- Fts3Table *p, /* FTS table handle */
- TermSelect *pTS, /* TermSelect object to merge into */
- char *aDoclist, /* Pointer to doclist */
- int nDoclist /* Size of aDoclist in bytes */
-){
- if( pTS->aaOutput[0]==0 ){
- /* If this is the first term selected, copy the doclist to the output
- ** buffer using memcpy().
- **
- ** Add FTS3_VARINT_MAX bytes of unused space to the end of the
- ** allocation. This is so as to ensure that the buffer is big enough
- ** to hold the current doclist AND'd with any other doclist. If the
- ** doclists are stored in order=ASC order, this padding would not be
- ** required (since the size of [doclistA AND doclistB] is always less
- ** than or equal to the size of [doclistA] in that case). But this is
- ** not true for order=DESC. For example, a doclist containing (1, -1)
- ** may be smaller than (-1), as in the first example the -1 may be stored
- ** as a single-byte delta, whereas in the second it must be stored as a
- ** FTS3_VARINT_MAX byte varint.
- **
- ** Similar padding is added in the fts3DoclistOrMerge() function.
- */
- pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1);
- pTS->anOutput[0] = nDoclist;
- if( pTS->aaOutput[0] ){
- memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
- }else{
- return SQLITE_NOMEM;
- }
- }else{
- char *aMerge = aDoclist;
- int nMerge = nDoclist;
- int iOut;
-
- for(iOut=0; iOut<SizeofArray(pTS->aaOutput); iOut++){
- if( pTS->aaOutput[iOut]==0 ){
- assert( iOut>0 );
- pTS->aaOutput[iOut] = aMerge;
- pTS->anOutput[iOut] = nMerge;
- break;
- }else{
- char *aNew;
- int nNew;
-
- int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge,
- pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew
- );
- if( rc!=SQLITE_OK ){
- if( aMerge!=aDoclist ) sqlite3_free(aMerge);
- return rc;
- }
-
- if( aMerge!=aDoclist ) sqlite3_free(aMerge);
- sqlite3_free(pTS->aaOutput[iOut]);
- pTS->aaOutput[iOut] = 0;
-
- aMerge = aNew;
- nMerge = nNew;
- if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
- pTS->aaOutput[iOut] = aMerge;
- pTS->anOutput[iOut] = nMerge;
- }
- }
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Append SegReader object pNew to the end of the pCsr->apSegment[] array.
-*/
-static int fts3SegReaderCursorAppend(
- Fts3MultiSegReader *pCsr,
- Fts3SegReader *pNew
-){
- if( (pCsr->nSegment%16)==0 ){
- Fts3SegReader **apNew;
- int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
- apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
- if( !apNew ){
- sqlite3Fts3SegReaderFree(pNew);
- return SQLITE_NOMEM;
- }
- pCsr->apSegment = apNew;
- }
- pCsr->apSegment[pCsr->nSegment++] = pNew;
- return SQLITE_OK;
-}
-
-/*
-** Add seg-reader objects to the Fts3MultiSegReader object passed as the
-** 8th argument.
-**
-** This function returns SQLITE_OK if successful, or an SQLite error code
-** otherwise.
-*/
-static int fts3SegReaderCursor(
- Fts3Table *p, /* FTS3 table handle */
- int iLangid, /* Language id */
- int iIndex, /* Index to search (from 0 to p->nIndex-1) */
- int iLevel, /* Level of segments to scan */
- const char *zTerm, /* Term to query for */
- int nTerm, /* Size of zTerm in bytes */
- int isPrefix, /* True for a prefix search */
- int isScan, /* True to scan from zTerm to EOF */
- Fts3MultiSegReader *pCsr /* Cursor object to populate */
-){
- int rc = SQLITE_OK; /* Error code */
- sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
- int rc2; /* Result of sqlite3_reset() */
-
- /* If iLevel is less than 0 and this is not a scan, include a seg-reader
- ** for the pending-terms. If this is a scan, then this call must be being
- ** made by an fts4aux module, not an FTS table. In this case calling
- ** Fts3SegReaderPending might segfault, as the data structures used by
- ** fts4aux are not completely populated. So it's easiest to filter these
- ** calls out here. */
- if( iLevel<0 && p->aIndex ){
- Fts3SegReader *pSeg = 0;
- rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
- if( rc==SQLITE_OK && pSeg ){
- rc = fts3SegReaderCursorAppend(pCsr, pSeg);
- }
- }
-
- if( iLevel!=FTS3_SEGCURSOR_PENDING ){
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt);
- }
-
- while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
- Fts3SegReader *pSeg = 0;
-
- /* Read the values returned by the SELECT into local variables. */
- sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1);
- sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2);
- sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3);
- int nRoot = sqlite3_column_bytes(pStmt, 4);
- char const *zRoot = sqlite3_column_blob(pStmt, 4);
-
- /* If zTerm is not NULL, and this segment is not stored entirely on its
- ** root node, the range of leaves scanned can be reduced. Do this. */
- if( iStartBlock && zTerm ){
- sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
- rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
- if( rc!=SQLITE_OK ) goto finished;
- if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
- }
-
- rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
- (isPrefix==0 && isScan==0),
- iStartBlock, iLeavesEndBlock,
- iEndBlock, zRoot, nRoot, &pSeg
- );
- if( rc!=SQLITE_OK ) goto finished;
- rc = fts3SegReaderCursorAppend(pCsr, pSeg);
- }
- }
-
- finished:
- rc2 = sqlite3_reset(pStmt);
- if( rc==SQLITE_DONE ) rc = rc2;
-
- return rc;
-}
-
-/*
-** Set up a cursor object for iterating through a full-text index or a
-** single level therein.
-*/
-int sqlite3Fts3SegReaderCursor(
- Fts3Table *p, /* FTS3 table handle */
- int iLangid, /* Language-id to search */
- int iIndex, /* Index to search (from 0 to p->nIndex-1) */
- int iLevel, /* Level of segments to scan */
- const char *zTerm, /* Term to query for */
- int nTerm, /* Size of zTerm in bytes */
- int isPrefix, /* True for a prefix search */
- int isScan, /* True to scan from zTerm to EOF */
- Fts3MultiSegReader *pCsr /* Cursor object to populate */
-){
- assert( iIndex>=0 && iIndex<p->nIndex );
- assert( iLevel==FTS3_SEGCURSOR_ALL
- || iLevel==FTS3_SEGCURSOR_PENDING
- || iLevel>=0
- );
- assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
- assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
- assert( isPrefix==0 || isScan==0 );
-
- memset(pCsr, 0, sizeof(Fts3MultiSegReader));
- return fts3SegReaderCursor(
- p, iLangid, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
- );
-}
-
-/*
-** In addition to its current configuration, have the Fts3MultiSegReader
-** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
-**
-** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
-*/
-static int fts3SegReaderCursorAddZero(
- Fts3Table *p, /* FTS virtual table handle */
- int iLangid,
- const char *zTerm, /* Term to scan doclist of */
- int nTerm, /* Number of bytes in zTerm */
- Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
-){
- return fts3SegReaderCursor(p,
- iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr
- );
-}
-
-/*
-** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
-** if isPrefix is true, to scan the doclist for all terms for which
-** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
-** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
-** an SQLite error code.
-**
-** It is the responsibility of the caller to free this object by eventually
-** passing it to fts3SegReaderCursorFree()
-**
-** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
-** Output parameter *ppSegcsr is set to 0 if an error occurs.
-*/
-static int fts3TermSegReaderCursor(
- Fts3Cursor *pCsr, /* Virtual table cursor handle */
- const char *zTerm, /* Term to query for */
- int nTerm, /* Size of zTerm in bytes */
- int isPrefix, /* True for a prefix search */
- Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
-){
- Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
- int rc = SQLITE_NOMEM; /* Return code */
-
- pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
- if( pSegcsr ){
- int i;
- int bFound = 0; /* True once an index has been found */
- Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
-
- if( isPrefix ){
- for(i=1; bFound==0 && i<p->nIndex; i++){
- if( p->aIndex[i].nPrefix==nTerm ){
- bFound = 1;
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
- i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr
- );
- pSegcsr->bLookup = 1;
- }
- }
-
- for(i=1; bFound==0 && i<p->nIndex; i++){
- if( p->aIndex[i].nPrefix==nTerm+1 ){
- bFound = 1;
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
- i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
- );
- if( rc==SQLITE_OK ){
- rc = fts3SegReaderCursorAddZero(
- p, pCsr->iLangid, zTerm, nTerm, pSegcsr
- );
- }
- }
- }
- }
-
- if( bFound==0 ){
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
- 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
- );
- pSegcsr->bLookup = !isPrefix;
- }
- }
-
- *ppSegcsr = pSegcsr;
- return rc;
-}
-
-/*
-** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
-*/
-static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
- sqlite3Fts3SegReaderFinish(pSegcsr);
- sqlite3_free(pSegcsr);
-}
-
-/*
-** This function retrieves the doclist for the specified term (or term
-** prefix) from the database.
-*/
-static int fts3TermSelect(
- Fts3Table *p, /* Virtual table handle */
- Fts3PhraseToken *pTok, /* Token to query for */
- int iColumn, /* Column to query (or -ve for all columns) */
- int *pnOut, /* OUT: Size of buffer at *ppOut */
- char **ppOut /* OUT: Malloced result buffer */
-){
- int rc; /* Return code */
- Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
- TermSelect tsc; /* Object for pair-wise doclist merging */
- Fts3SegFilter filter; /* Segment term filter configuration */
-
- pSegcsr = pTok->pSegcsr;
- memset(&tsc, 0, sizeof(TermSelect));
-
- filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
- | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
- | (pTok->bFirst ? FTS3_SEGMENT_FIRST : 0)
- | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
- filter.iCol = iColumn;
- filter.zTerm = pTok->z;
- filter.nTerm = pTok->n;
-
- rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
- while( SQLITE_OK==rc
- && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
- ){
- rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
- }
-
- if( rc==SQLITE_OK ){
- rc = fts3TermSelectFinishMerge(p, &tsc);
- }
- if( rc==SQLITE_OK ){
- *ppOut = tsc.aaOutput[0];
- *pnOut = tsc.anOutput[0];
- }else{
- int i;
- for(i=0; i<SizeofArray(tsc.aaOutput); i++){
- sqlite3_free(tsc.aaOutput[i]);
- }
- }
-
- fts3SegReaderCursorFree(pSegcsr);
- pTok->pSegcsr = 0;
- return rc;
-}
-
-/*
-** This function counts the total number of docids in the doclist stored
-** in buffer aList[], size nList bytes.
-**
-** If the isPoslist argument is true, then it is assumed that the doclist
-** contains a position-list following each docid. Otherwise, it is assumed
-** that the doclist is simply a list of docids stored as delta encoded
-** varints.
-*/
-static int fts3DoclistCountDocids(char *aList, int nList){
- int nDoc = 0; /* Return value */
- if( aList ){
- char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
- char *p = aList; /* Cursor */
- while( p<aEnd ){
- nDoc++;
- while( (*p++)&0x80 ); /* Skip docid varint */
- fts3PoslistCopy(0, &p); /* Skip over position list */
- }
- }
-
- return nDoc;
-}
-
-/*
-** Advance the cursor to the next row in the %_content table that
-** matches the search criteria. For a MATCH search, this will be
-** the next row that matches. For a full-table scan, this will be
-** simply the next row in the %_content table. For a docid lookup,
-** this routine simply sets the EOF flag.
-**
-** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
-** even if we reach end-of-file. The fts3EofMethod() will be called
-** subsequently to determine whether or not an EOF was hit.
-*/
-static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
- int rc;
- Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
- if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
- if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
- pCsr->isEof = 1;
- rc = sqlite3_reset(pCsr->pStmt);
- }else{
- pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
- rc = SQLITE_OK;
- }
- }else{
- rc = fts3EvalNext((Fts3Cursor *)pCursor);
- }
- assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
- return rc;
-}
-
-/*
-** The following are copied from sqliteInt.h.
-**
-** Constants for the largest and smallest possible 64-bit signed integers.
-** These macros are designed to work correctly on both 32-bit and 64-bit
-** compilers.
-*/
-#ifndef SQLITE_AMALGAMATION
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
-/*
-** If the numeric type of argument pVal is "integer", then return it
-** converted to a 64-bit signed integer. Otherwise, return a copy of
-** the second parameter, iDefault.
-*/
-static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
- if( pVal ){
- int eType = sqlite3_value_numeric_type(pVal);
- if( eType==SQLITE_INTEGER ){
- return sqlite3_value_int64(pVal);
- }
- }
- return iDefault;
-}
-
-/*
-** This is the xFilter interface for the virtual table. See
-** the virtual table xFilter method documentation for additional
-** information.
-**
-** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against
-** the %_content table.
-**
-** If idxNum==FTS3_DOCID_SEARCH then do a docid lookup for a single entry
-** in the %_content table.
-**
-** If idxNum>=FTS3_FULLTEXT_SEARCH then use the full text index. The
-** column on the left-hand side of the MATCH operator is column
-** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand
-** side of the MATCH operator.
-*/
-static int fts3FilterMethod(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, /* Strategy index */
- const char *idxStr, /* Unused */
- int nVal, /* Number of elements in apVal */
- sqlite3_value **apVal /* Arguments for the indexing scheme */
-){
- int rc = SQLITE_OK;
- char *zSql; /* SQL statement used to access %_content */
- int eSearch;
- Fts3Table *p = (Fts3Table *)pCursor->pVtab;
- Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
-
- sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */
- sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */
- sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */
- sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */
- int iIdx;
-
- UNUSED_PARAMETER(idxStr);
- UNUSED_PARAMETER(nVal);
-
- eSearch = (idxNum & 0x0000FFFF);
- assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
- assert( p->pSegments==0 );
-
- /* Collect arguments into local variables */
- iIdx = 0;
- if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++];
- if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++];
- if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++];
- if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++];
- assert( iIdx==nVal );
-
- /* In case the cursor has been used before, clear it now. */
- fts3ClearCursor(pCsr);
-
- /* Set the lower and upper bounds on docids to return */
- pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
- pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64);
-
- if( idxStr ){
- pCsr->bDesc = (idxStr[0]=='D');
- }else{
- pCsr->bDesc = p->bDescIdx;
- }
- pCsr->eSearch = (i16)eSearch;
-
- if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){
- int iCol = eSearch-FTS3_FULLTEXT_SEARCH;
- const char *zQuery = (const char *)sqlite3_value_text(pCons);
-
- if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){
- return SQLITE_NOMEM;
- }
-
- pCsr->iLangid = 0;
- if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid);
-
- assert( p->base.zErrMsg==0 );
- rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
- p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
- &p->base.zErrMsg
- );
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- rc = fts3EvalStart(pCsr);
- sqlite3Fts3SegmentsClose(p);
- if( rc!=SQLITE_OK ) return rc;
- pCsr->pNextId = pCsr->aDoclist;
- pCsr->iPrevId = 0;
- }
-
- /* Compile a SELECT statement for this cursor. For a full-table-scan, the
- ** statement loops through all rows of the %_content table. For a
- ** full-text query or docid lookup, the statement retrieves a single
- ** row by docid.
- */
- if( eSearch==FTS3_FULLSCAN_SEARCH ){
- if( pDocidGe || pDocidLe ){
- zSql = sqlite3_mprintf(
- "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s",
- p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid,
- (pCsr->bDesc ? "DESC" : "ASC")
- );
- }else{
- zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s",
- p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
- );
- }
- if( zSql ){
- rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
- sqlite3_free(zSql);
- }else{
- rc = SQLITE_NOMEM;
- }
- }else if( eSearch==FTS3_DOCID_SEARCH ){
- rc = fts3CursorSeekStmt(pCsr);
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
- }
- }
- if( rc!=SQLITE_OK ) return rc;
-
- return fts3NextMethod(pCursor);
-}
-
-/*
-** This is the xEof method of the virtual table. SQLite calls this
-** routine to find out if it has reached the end of a result set.
-*/
-static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
- Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
- if( pCsr->isEof ){
- fts3ClearCursor(pCsr);
- pCsr->isEof = 1;
- }
- return pCsr->isEof;
-}
-
-/*
-** This is the xRowid method. The SQLite core calls this routine to
-** retrieve the rowid for the current row of the result set. fts3
-** exposes %_content.docid as the rowid for the virtual table. The
-** rowid should be written to *pRowid.
-*/
-static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
- *pRowid = pCsr->iPrevId;
- return SQLITE_OK;
-}
-
-/*
-** This is the xColumn method, called by SQLite to request a value from
-** the row that the supplied cursor currently points to.
-**
-** If:
-**
-** (iCol < p->nColumn) -> The value of the iCol'th user column.
-** (iCol == p->nColumn) -> Magic column with the same name as the table.
-** (iCol == p->nColumn+1) -> Docid column
-** (iCol == p->nColumn+2) -> Langid column
-*/
-static int fts3ColumnMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
- int iCol /* Index of column to read value from */
-){
- int rc = SQLITE_OK; /* Return Code */
- Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
- Fts3Table *p = (Fts3Table *)pCursor->pVtab;
-
- /* The column value supplied by SQLite must be in range. */
- assert( iCol>=0 && iCol<=p->nColumn+2 );
-
- switch( iCol-p->nColumn ){
- case 0:
- /* The special 'table-name' column */
- sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
- break;
-
- case 1:
- /* The docid column */
- sqlite3_result_int64(pCtx, pCsr->iPrevId);
- break;
-
- case 2:
- if( pCsr->pExpr ){
- sqlite3_result_int64(pCtx, pCsr->iLangid);
- break;
- }else if( p->zLanguageid==0 ){
- sqlite3_result_int(pCtx, 0);
- break;
- }else{
- iCol = p->nColumn;
- /* fall-through */
- }
-
- default:
- /* A user column. Or, if this is a full-table scan, possibly the
- ** language-id column. Seek the cursor. */
- rc = fts3CursorSeek(0, pCsr);
- if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){
- sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
- }
- break;
- }
-
- assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
- return rc;
-}
-
-/*
-** This function is the implementation of the xUpdate callback used by
-** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
-** inserted, updated or deleted.
-*/
-static int fts3UpdateMethod(
- sqlite3_vtab *pVtab, /* Virtual table handle */
- int nArg, /* Size of argument array */
- sqlite3_value **apVal, /* Array of arguments */
- sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
-){
- return sqlite3Fts3UpdateMethod(pVtab, nArg, apVal, pRowid);
-}
-
-/*
-** Implementation of xSync() method. Flush the contents of the pending-terms
-** hash-table to the database.
-*/
-static int fts3SyncMethod(sqlite3_vtab *pVtab){
-
- /* Following an incremental-merge operation, assuming that the input
- ** segments are not completely consumed (the usual case), they are updated
- ** in place to remove the entries that have already been merged. This
- ** involves updating the leaf block that contains the smallest unmerged
- ** entry and each block (if any) between the leaf and the root node. So
- ** if the height of the input segment b-trees is N, and input segments
- ** are merged eight at a time, updating the input segments at the end
- ** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually
- ** small - often between 0 and 2. So the overhead of the incremental
- ** merge is somewhere between 8 and 24 blocks. To avoid this overhead
- ** dwarfing the actual productive work accomplished, the incremental merge
- ** is only attempted if it will write at least 64 leaf blocks. Hence
- ** nMinMerge.
- **
- ** Of course, updating the input segments also involves deleting a bunch
- ** of blocks from the segments table. But this is not considered overhead
- ** as it would also be required by a crisis-merge that used the same input
- ** segments.
- */
- const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
-
- Fts3Table *p = (Fts3Table*)pVtab;
- int rc;
- i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
-
- rc = sqlite3Fts3PendingTermsFlush(p);
- if( rc==SQLITE_OK
- && p->nLeafAdd>(nMinMerge/16)
- && p->nAutoincrmerge && p->nAutoincrmerge!=0xff
- ){
- int mxLevel = 0; /* Maximum relative level value in db */
- int A; /* Incr-merge parameter A */
-
- rc = sqlite3Fts3MaxLevel(p, &mxLevel);
- assert( rc==SQLITE_OK || mxLevel==0 );
- A = p->nLeafAdd * mxLevel;
- A += (A/2);
- if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
- }
- sqlite3Fts3SegmentsClose(p);
- sqlite3_set_last_insert_rowid(p->db, iLastRowid);
- return rc;
-}
-
-/*
-** If it is currently unknown whether or not the FTS table has an %_stat
-** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat
-** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code
-** if an error occurs.
-*/
-static int fts3SetHasStat(Fts3Table *p){
- int rc = SQLITE_OK;
- if( p->bHasStat==2 ){
- char *zTbl = sqlite3_mprintf("%s_stat", p->zName);
- if( zTbl ){
- int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0);
- sqlite3_free(zTbl);
- p->bHasStat = (res==SQLITE_OK);
- }else{
- rc = SQLITE_NOMEM;
- }
- }
- return rc;
-}
-
-/*
-** Implementation of xBegin() method.
-*/
-static int fts3BeginMethod(sqlite3_vtab *pVtab){
- Fts3Table *p = (Fts3Table*)pVtab;
- UNUSED_PARAMETER(pVtab);
- assert( p->pSegments==0 );
- assert( p->nPendingData==0 );
- assert( p->inTransaction!=1 );
- TESTONLY( p->inTransaction = 1 );
- TESTONLY( p->mxSavepoint = -1; );
- p->nLeafAdd = 0;
- return fts3SetHasStat(p);
-}
-
-/*
-** Implementation of xCommit() method. This is a no-op. The contents of
-** the pending-terms hash-table have already been flushed into the database
-** by fts3SyncMethod().
-*/
-static int fts3CommitMethod(sqlite3_vtab *pVtab){
- TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
- UNUSED_PARAMETER(pVtab);
- assert( p->nPendingData==0 );
- assert( p->inTransaction!=0 );
- assert( p->pSegments==0 );
- TESTONLY( p->inTransaction = 0 );
- TESTONLY( p->mxSavepoint = -1; );
- return SQLITE_OK;
-}
-
-/*
-** Implementation of xRollback(). Discard the contents of the pending-terms
-** hash-table. Any changes made to the database are reverted by SQLite.
-*/
-static int fts3RollbackMethod(sqlite3_vtab *pVtab){
- Fts3Table *p = (Fts3Table*)pVtab;
- sqlite3Fts3PendingTermsClear(p);
- assert( p->inTransaction!=0 );
- TESTONLY( p->inTransaction = 0 );
- TESTONLY( p->mxSavepoint = -1; );
- return SQLITE_OK;
-}
-
-/*
-** When called, *ppPoslist must point to the byte immediately following the
-** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
-** moves *ppPoslist so that it instead points to the first byte of the
-** same position list.
-*/
-static void fts3ReversePoslist(char *pStart, char **ppPoslist){
- char *p = &(*ppPoslist)[-2];
- char c = 0;
-
- /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */
- while( p>pStart && (c=*p--)==0 );
-
- /* Search backwards for a varint with value zero (the end of the previous
- ** poslist). This is an 0x00 byte preceded by some byte that does not
- ** have the 0x80 bit set. */
- while( p>pStart && (*p & 0x80) | c ){
- c = *p--;
- }
- assert( p==pStart || c==0 );
-
- /* At this point p points to that preceding byte without the 0x80 bit
- ** set. So to find the start of the poslist, skip forward 2 bytes then
- ** over a varint.
- **
- ** Normally. The other case is that p==pStart and the poslist to return
- ** is the first in the doclist. In this case do not skip forward 2 bytes.
- ** The second part of the if condition (c==0 && *ppPoslist>&p[2])
- ** is required for cases where the first byte of a doclist and the
- ** doclist is empty. For example, if the first docid is 10, a doclist
- ** that begins with:
- **
- ** 0x0A 0x00 <next docid delta varint>
- */
- if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; }
- while( *p++&0x80 );
- *ppPoslist = p;
-}
-
-/*
-** Helper function used by the implementation of the overloaded snippet(),
-** offsets() and optimize() SQL functions.
-**
-** If the value passed as the third argument is a blob of size
-** sizeof(Fts3Cursor*), then the blob contents are copied to the
-** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error
-** message is written to context pContext and SQLITE_ERROR returned. The
-** string passed via zFunc is used as part of the error message.
-*/
-static int fts3FunctionArg(
- sqlite3_context *pContext, /* SQL function call context */
- const char *zFunc, /* Function name */
- sqlite3_value *pVal, /* argv[0] passed to function */
- Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
-){
- int rc;
- *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
- if( (*ppCsr)!=0 ){
- rc = SQLITE_OK;
- }else{
- char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
- sqlite3_result_error(pContext, zErr, -1);
- sqlite3_free(zErr);
- rc = SQLITE_ERROR;
- }
- return rc;
-}
-
-/*
-** Implementation of the snippet() function for FTS3
-*/
-static void fts3SnippetFunc(
- sqlite3_context *pContext, /* SQLite function call context */
- int nVal, /* Size of apVal[] array */
- sqlite3_value **apVal /* Array of arguments */
-){
- Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
- const char *zStart = "<b>";
- const char *zEnd = "</b>";
- const char *zEllipsis = "<b>...</b>";
- int iCol = -1;
- int nToken = 15; /* Default number of tokens in snippet */
-
- /* There must be at least one argument passed to this function (otherwise
- ** the non-overloaded version would have been called instead of this one).
- */
- assert( nVal>=1 );
-
- if( nVal>6 ){
- sqlite3_result_error(pContext,
- "wrong number of arguments to function snippet()", -1);
- return;
- }
- if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;
-
- switch( nVal ){
- case 6: nToken = sqlite3_value_int(apVal[5]);
- case 5: iCol = sqlite3_value_int(apVal[4]);
- case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
- case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
- case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
- }
- if( !zEllipsis || !zEnd || !zStart ){
- sqlite3_result_error_nomem(pContext);
- }else if( nToken==0 ){
- sqlite3_result_text(pContext, "", -1, SQLITE_STATIC);
- }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
- sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
- }
-}
-
-/*
-** Implementation of the offsets() function for FTS3
-*/
-static void fts3OffsetsFunc(
- sqlite3_context *pContext, /* SQLite function call context */
- int nVal, /* Size of argument array */
- sqlite3_value **apVal /* Array of arguments */
-){
- Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
-
- UNUSED_PARAMETER(nVal);
-
- assert( nVal==1 );
- if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return;
- assert( pCsr );
- if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
- sqlite3Fts3Offsets(pContext, pCsr);
- }
-}
-
-/*
-** Implementation of the special optimize() function for FTS3. This
-** function merges all segments in the database to a single segment.
-** Example usage is:
-**
-** SELECT optimize(t) FROM t LIMIT 1;
-**
-** where 't' is the name of an FTS3 table.
-*/
-static void fts3OptimizeFunc(
- sqlite3_context *pContext, /* SQLite function call context */
- int nVal, /* Size of argument array */
- sqlite3_value **apVal /* Array of arguments */
-){
- int rc; /* Return code */
- Fts3Table *p; /* Virtual table handle */
- Fts3Cursor *pCursor; /* Cursor handle passed through apVal[0] */
-
- UNUSED_PARAMETER(nVal);
-
- assert( nVal==1 );
- if( fts3FunctionArg(pContext, "optimize", apVal[0], &pCursor) ) return;
- p = (Fts3Table *)pCursor->base.pVtab;
- assert( p );
-
- rc = sqlite3Fts3Optimize(p);
-
- switch( rc ){
- case SQLITE_OK:
- sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC);
- break;
- case SQLITE_DONE:
- sqlite3_result_text(pContext, "Index already optimal", -1, SQLITE_STATIC);
- break;
- default:
- sqlite3_result_error_code(pContext, rc);
- break;
- }
-}
-
-/*
-** Implementation of the matchinfo() function for FTS3
-*/
-static void fts3MatchinfoFunc(
- sqlite3_context *pContext, /* SQLite function call context */
- int nVal, /* Size of argument array */
- sqlite3_value **apVal /* Array of arguments */
-){
- Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
- assert( nVal==1 || nVal==2 );
- if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){
- const char *zArg = 0;
- if( nVal>1 ){
- zArg = (const char *)sqlite3_value_text(apVal[1]);
- }
- sqlite3Fts3Matchinfo(pContext, pCsr, zArg);
- }
-}
-
-/*
-** This routine implements the xFindFunction method for the FTS3
-** virtual table.
-*/
-static int fts3FindFunctionMethod(
- sqlite3_vtab *pVtab, /* Virtual table handle */
- int nArg, /* Number of SQL function arguments */
- const char *zName, /* Name of SQL function */
- void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
- void **ppArg /* Unused */
-){
- struct Overloaded {
- const char *zName;
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
- } aOverload[] = {
- { "snippet", fts3SnippetFunc },
- { "offsets", fts3OffsetsFunc },
- { "optimize", fts3OptimizeFunc },
- { "matchinfo", fts3MatchinfoFunc },
- };
- int i; /* Iterator variable */
-
- UNUSED_PARAMETER(pVtab);
- UNUSED_PARAMETER(nArg);
- UNUSED_PARAMETER(ppArg);
-
- for(i=0; i<SizeofArray(aOverload); i++){
- if( strcmp(zName, aOverload[i].zName)==0 ){
- *pxFunc = aOverload[i].xFunc;
- return 1;
- }
- }
-
- /* No function of the specified name was found. Return 0. */
- return 0;
-}
-
-/*
-** Implementation of FTS3 xRename method. Rename an fts3 table.
-*/
-static int fts3RenameMethod(
- sqlite3_vtab *pVtab, /* Virtual table handle */
- const char *zName /* New name of table */
-){
- Fts3Table *p = (Fts3Table *)pVtab;
- sqlite3 *db = p->db; /* Database connection */
- int rc; /* Return Code */
-
- /* At this point it must be known if the %_stat table exists or not.
- ** So bHasStat may not be 2. */
- rc = fts3SetHasStat(p);
-
- /* As it happens, the pending terms table is always empty here. This is
- ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
- ** always opens a savepoint transaction. And the xSavepoint() method
- ** flushes the pending terms table. But leave the (no-op) call to
- ** PendingTermsFlush() in in case that changes.
- */
- assert( p->nPendingData==0 );
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3PendingTermsFlush(p);
- }
-
- if( p->zContentTbl==0 ){
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';",
- p->zDb, p->zName, zName
- );
- }
-
- if( p->bHasDocsize ){
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';",
- p->zDb, p->zName, zName
- );
- }
- if( p->bHasStat ){
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';",
- p->zDb, p->zName, zName
- );
- }
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';",
- p->zDb, p->zName, zName
- );
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';",
- p->zDb, p->zName, zName
- );
- return rc;
-}
-
-/*
-** The xSavepoint() method.
-**
-** Flush the contents of the pending-terms table to disk.
-*/
-static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
- int rc = SQLITE_OK;
- UNUSED_PARAMETER(iSavepoint);
- assert( ((Fts3Table *)pVtab)->inTransaction );
- assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
- TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
- if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){
- rc = fts3SyncMethod(pVtab);
- }
- return rc;
-}
-
-/*
-** The xRelease() method.
-**
-** This is a no-op.
-*/
-static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
- TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
- UNUSED_PARAMETER(iSavepoint);
- UNUSED_PARAMETER(pVtab);
- assert( p->inTransaction );
- assert( p->mxSavepoint >= iSavepoint );
- TESTONLY( p->mxSavepoint = iSavepoint-1 );
- return SQLITE_OK;
-}
-
-/*
-** The xRollbackTo() method.
-**
-** Discard the contents of the pending terms table.
-*/
-static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts3Table *p = (Fts3Table*)pVtab;
- UNUSED_PARAMETER(iSavepoint);
- assert( p->inTransaction );
- assert( p->mxSavepoint >= iSavepoint );
- TESTONLY( p->mxSavepoint = iSavepoint );
- sqlite3Fts3PendingTermsClear(p);
- return SQLITE_OK;
-}
-
-static const sqlite3_module fts3Module = {
- /* iVersion */ 2,
- /* xCreate */ fts3CreateMethod,
- /* xConnect */ fts3ConnectMethod,
- /* xBestIndex */ fts3BestIndexMethod,
- /* xDisconnect */ fts3DisconnectMethod,
- /* xDestroy */ fts3DestroyMethod,
- /* xOpen */ fts3OpenMethod,
- /* xClose */ fts3CloseMethod,
- /* xFilter */ fts3FilterMethod,
- /* xNext */ fts3NextMethod,
- /* xEof */ fts3EofMethod,
- /* xColumn */ fts3ColumnMethod,
- /* xRowid */ fts3RowidMethod,
- /* xUpdate */ fts3UpdateMethod,
- /* xBegin */ fts3BeginMethod,
- /* xSync */ fts3SyncMethod,
- /* xCommit */ fts3CommitMethod,
- /* xRollback */ fts3RollbackMethod,
- /* xFindFunction */ fts3FindFunctionMethod,
- /* xRename */ fts3RenameMethod,
- /* xSavepoint */ fts3SavepointMethod,
- /* xRelease */ fts3ReleaseMethod,
- /* xRollbackTo */ fts3RollbackToMethod,
-};
-
-/*
-** This function is registered as the module destructor (called when an
-** FTS3 enabled database connection is closed). It frees the memory
-** allocated for the tokenizer hash table.
-*/
-static void hashDestroy(void *p){
- Fts3Hash *pHash = (Fts3Hash *)p;
- sqlite3Fts3HashClear(pHash);
- sqlite3_free(pHash);
-}
-
-/*
-** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are
-** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c
-** respectively. The following three forward declarations are for functions
-** declared in these files used to retrieve the respective implementations.
-**
-** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed
-** to by the argument to point to the "simple" tokenizer implementation.
-** And so on.
-*/
-void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-#ifndef SQLITE_DISABLE_FTS3_UNICODE
-void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
-#endif
-#ifdef SQLITE_ENABLE_ICU
-void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-#endif
-
-/*
-** Initialize the fts3 extension. If this extension is built as part
-** of the sqlite library, then this function is called directly by
-** SQLite. If fts3 is built as a dynamically loadable extension, this
-** function is called by the sqlite3_extension_init() entry point.
-*/
-int sqlite3Fts3Init(sqlite3 *db){
- int rc = SQLITE_OK;
- Fts3Hash *pHash = 0;
- const sqlite3_tokenizer_module *pSimple = 0;
- const sqlite3_tokenizer_module *pPorter = 0;
-#ifndef SQLITE_DISABLE_FTS3_UNICODE
- const sqlite3_tokenizer_module *pUnicode = 0;
-#endif
-
-#ifdef SQLITE_ENABLE_ICU
- const sqlite3_tokenizer_module *pIcu = 0;
- sqlite3Fts3IcuTokenizerModule(&pIcu);
-#endif
-
-#ifndef SQLITE_DISABLE_FTS3_UNICODE
- sqlite3Fts3UnicodeTokenizer(&pUnicode);
-#endif
-
-#ifdef SQLITE_TEST
- rc = sqlite3Fts3InitTerm(db);
- if( rc!=SQLITE_OK ) return rc;
-#endif
-
- rc = sqlite3Fts3InitAux(db);
- if( rc!=SQLITE_OK ) return rc;
-
- sqlite3Fts3SimpleTokenizerModule(&pSimple);
- sqlite3Fts3PorterTokenizerModule(&pPorter);
-
- /* Allocate and initialize the hash-table used to store tokenizers. */
- pHash = sqlite3_malloc(sizeof(Fts3Hash));
- if( !pHash ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
- }
-
- /* Load the built-in tokenizers into the hash table */
- if( rc==SQLITE_OK ){
- if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
- || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
-
-#ifndef SQLITE_DISABLE_FTS3_UNICODE
- || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
-#endif
-#ifdef SQLITE_ENABLE_ICU
- || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
-#endif
- ){
- rc = SQLITE_NOMEM;
- }
- }
-
-#ifdef SQLITE_TEST
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3ExprInitTestInterface(db, pHash);
- }
-#endif
-
- /* Create the virtual table wrapper around the hash-table and overload
- ** the four scalar functions. If this is successful, register the
- ** module with sqlite.
- */
- if( SQLITE_OK==rc
- && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2))
- && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
- ){
- rc = sqlite3_create_module_v2(
- db, "fts3", &fts3Module, (void *)pHash, hashDestroy
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_module_v2(
- db, "fts4", &fts3Module, (void *)pHash, 0
- );
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3InitTok(db, (void *)pHash);
- }
- return rc;
- }
-
-
- /* An error has occurred. Delete the hash table and return the error code. */
- assert( rc!=SQLITE_OK );
- if( pHash ){
- sqlite3Fts3HashClear(pHash);
- sqlite3_free(pHash);
- }
- return rc;
-}
-
-/*
-** Allocate an Fts3MultiSegReader for each token in the expression headed
-** by pExpr.
-**
-** An Fts3SegReader object is a cursor that can seek or scan a range of
-** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
-** Fts3SegReader objects internally to provide an interface to seek or scan
-** within the union of all segments of a b-tree. Hence the name.
-**
-** If the allocated Fts3MultiSegReader just seeks to a single entry in a
-** segment b-tree (if the term is not a prefix or it is a prefix for which
-** there exists prefix b-tree of the right length) then it may be traversed
-** and merged incrementally. Otherwise, it has to be merged into an in-memory
-** doclist and then traversed.
-*/
-static void fts3EvalAllocateReaders(
- Fts3Cursor *pCsr, /* FTS cursor handle */
- Fts3Expr *pExpr, /* Allocate readers for this expression */
- int *pnToken, /* OUT: Total number of tokens in phrase. */
- int *pnOr, /* OUT: Total number of OR nodes in expr. */
- int *pRc /* IN/OUT: Error code */
-){
- if( pExpr && SQLITE_OK==*pRc ){
- if( pExpr->eType==FTSQUERY_PHRASE ){
- int i;
- int nToken = pExpr->pPhrase->nToken;
- *pnToken += nToken;
- for(i=0; i<nToken; i++){
- Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
- int rc = fts3TermSegReaderCursor(pCsr,
- pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
- );
- if( rc!=SQLITE_OK ){
- *pRc = rc;
- return;
- }
- }
- assert( pExpr->pPhrase->iDoclistToken==0 );
- pExpr->pPhrase->iDoclistToken = -1;
- }else{
- *pnOr += (pExpr->eType==FTSQUERY_OR);
- fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
- fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
- }
- }
-}
-
-/*
-** Arguments pList/nList contain the doclist for token iToken of phrase p.
-** It is merged into the main doclist stored in p->doclist.aAll/nAll.
-**
-** This function assumes that pList points to a buffer allocated using
-** sqlite3_malloc(). This function takes responsibility for eventually
-** freeing the buffer.
-**
-** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs.
-*/
-static int fts3EvalPhraseMergeToken(
- Fts3Table *pTab, /* FTS Table pointer */
- Fts3Phrase *p, /* Phrase to merge pList/nList into */
- int iToken, /* Token pList/nList corresponds to */
- char *pList, /* Pointer to doclist */
- int nList /* Number of bytes in pList */
-){
- int rc = SQLITE_OK;
- assert( iToken!=p->iDoclistToken );
-
- if( pList==0 ){
- sqlite3_free(p->doclist.aAll);
- p->doclist.aAll = 0;
- p->doclist.nAll = 0;
- }
-
- else if( p->iDoclistToken<0 ){
- p->doclist.aAll = pList;
- p->doclist.nAll = nList;
- }
-
- else if( p->doclist.aAll==0 ){
- sqlite3_free(pList);
- }
-
- else {
- char *pLeft;
- char *pRight;
- int nLeft;
- int nRight;
- int nDiff;
-
- if( p->iDoclistToken<iToken ){
- pLeft = p->doclist.aAll;
- nLeft = p->doclist.nAll;
- pRight = pList;
- nRight = nList;
- nDiff = iToken - p->iDoclistToken;
- }else{
- pRight = p->doclist.aAll;
- nRight = p->doclist.nAll;
- pLeft = pList;
- nLeft = nList;
- nDiff = p->iDoclistToken - iToken;
- }
-
- rc = fts3DoclistPhraseMerge(
- pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight
- );
- sqlite3_free(pLeft);
- p->doclist.aAll = pRight;
- p->doclist.nAll = nRight;
- }
-
- if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
- return rc;
-}
-
-/*
-** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
-** does not take deferred tokens into account.
-**
-** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
-*/
-static int fts3EvalPhraseLoad(
- Fts3Cursor *pCsr, /* FTS Cursor handle */
- Fts3Phrase *p /* Phrase object */
-){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int iToken;
- int rc = SQLITE_OK;
-
- for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
- Fts3PhraseToken *pToken = &p->aToken[iToken];
- assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );
-
- if( pToken->pSegcsr ){
- int nThis = 0;
- char *pThis = 0;
- rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
- if( rc==SQLITE_OK ){
- rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
- }
- }
- assert( pToken->pSegcsr==0 );
- }
-
- return rc;
-}
-
-/*
-** This function is called on each phrase after the position lists for
-** any deferred tokens have been loaded into memory. It updates the phrases
-** current position list to include only those positions that are really
-** instances of the phrase (after considering deferred tokens). If this
-** means that the phrase does not appear in the current row, doclist.pList
-** and doclist.nList are both zeroed.
-**
-** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
-*/
-static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
- int iToken; /* Used to iterate through phrase tokens */
- char *aPoslist = 0; /* Position list for deferred tokens */
- int nPoslist = 0; /* Number of bytes in aPoslist */
- int iPrev = -1; /* Token number of previous deferred token */
-
- assert( pPhrase->doclist.bFreeList==0 );
-
- for(iToken=0; iToken<pPhrase->nToken; iToken++){
- Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
- Fts3DeferredToken *pDeferred = pToken->pDeferred;
-
- if( pDeferred ){
- char *pList;
- int nList;
- int rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList);
- if( rc!=SQLITE_OK ) return rc;
-
- if( pList==0 ){
- sqlite3_free(aPoslist);
- pPhrase->doclist.pList = 0;
- pPhrase->doclist.nList = 0;
- return SQLITE_OK;
-
- }else if( aPoslist==0 ){
- aPoslist = pList;
- nPoslist = nList;
-
- }else{
- char *aOut = pList;
- char *p1 = aPoslist;
- char *p2 = aOut;
-
- assert( iPrev>=0 );
- fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
- sqlite3_free(aPoslist);
- aPoslist = pList;
- nPoslist = (int)(aOut - aPoslist);
- if( nPoslist==0 ){
- sqlite3_free(aPoslist);
- pPhrase->doclist.pList = 0;
- pPhrase->doclist.nList = 0;
- return SQLITE_OK;
- }
- }
- iPrev = iToken;
- }
- }
-
- if( iPrev>=0 ){
- int nMaxUndeferred = pPhrase->iDoclistToken;
- if( nMaxUndeferred<0 ){
- pPhrase->doclist.pList = aPoslist;
- pPhrase->doclist.nList = nPoslist;
- pPhrase->doclist.iDocid = pCsr->iPrevId;
- pPhrase->doclist.bFreeList = 1;
- }else{
- int nDistance;
- char *p1;
- char *p2;
- char *aOut;
-
- if( nMaxUndeferred>iPrev ){
- p1 = aPoslist;
- p2 = pPhrase->doclist.pList;
- nDistance = nMaxUndeferred - iPrev;
- }else{
- p1 = pPhrase->doclist.pList;
- p2 = aPoslist;
- nDistance = iPrev - nMaxUndeferred;
- }
-
- aOut = (char *)sqlite3_malloc(nPoslist+8);
- if( !aOut ){
- sqlite3_free(aPoslist);
- return SQLITE_NOMEM;
- }
-
- pPhrase->doclist.pList = aOut;
- if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
- pPhrase->doclist.bFreeList = 1;
- pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
- }else{
- sqlite3_free(aOut);
- pPhrase->doclist.pList = 0;
- pPhrase->doclist.nList = 0;
- }
- sqlite3_free(aPoslist);
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Maximum number of tokens a phrase may have to be considered for the
-** incremental doclists strategy.
-*/
-#define MAX_INCR_PHRASE_TOKENS 4
-
-/*
-** This function is called for each Fts3Phrase in a full-text query
-** expression to initialize the mechanism for returning rows. Once this
-** function has been called successfully on an Fts3Phrase, it may be
-** used with fts3EvalPhraseNext() to iterate through the matching docids.
-**
-** If parameter bOptOk is true, then the phrase may (or may not) use the
-** incremental loading strategy. Otherwise, the entire doclist is loaded into
-** memory within this call.
-**
-** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
-*/
-static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int rc = SQLITE_OK; /* Error code */
- int i;
-
- /* Determine if doclists may be loaded from disk incrementally. This is
- ** possible if the bOptOk argument is true, the FTS doclists will be
- ** scanned in forward order, and the phrase consists of
- ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
- ** tokens or prefix tokens that cannot use a prefix-index. */
- int bHaveIncr = 0;
- int bIncrOk = (bOptOk
- && pCsr->bDesc==pTab->bDescIdx
- && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
-#ifdef SQLITE_TEST
- && pTab->bNoIncrDoclist==0
-#endif
- );
- for(i=0; bIncrOk==1 && i<p->nToken; i++){
- Fts3PhraseToken *pToken = &p->aToken[i];
- if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){
- bIncrOk = 0;
- }
- if( pToken->pSegcsr ) bHaveIncr = 1;
- }
-
- if( bIncrOk && bHaveIncr ){
- /* Use the incremental approach. */
- int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
- for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
- Fts3PhraseToken *pToken = &p->aToken[i];
- Fts3MultiSegReader *pSegcsr = pToken->pSegcsr;
- if( pSegcsr ){
- rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n);
- }
- }
- p->bIncr = 1;
- }else{
- /* Load the full doclist for the phrase into memory. */
- rc = fts3EvalPhraseLoad(pCsr, p);
- p->bIncr = 0;
- }
-
- assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr );
- return rc;
-}
-
-/*
-** This function is used to iterate backwards (from the end to start)
-** through doclists. It is used by this module to iterate through phrase
-** doclists in reverse and by the fts3_write.c module to iterate through
-** pending-terms lists when writing to databases with "order=desc".
-**
-** The doclist may be sorted in ascending (parameter bDescIdx==0) or
-** descending (parameter bDescIdx==1) order of docid. Regardless, this
-** function iterates from the end of the doclist to the beginning.
-*/
-void sqlite3Fts3DoclistPrev(
- int bDescIdx, /* True if the doclist is desc */
- char *aDoclist, /* Pointer to entire doclist */
- int nDoclist, /* Length of aDoclist in bytes */
- char **ppIter, /* IN/OUT: Iterator pointer */
- sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */
- int *pnList, /* OUT: List length pointer */
- u8 *pbEof /* OUT: End-of-file flag */
-){
- char *p = *ppIter;
-
- assert( nDoclist>0 );
- assert( *pbEof==0 );
- assert( p || *piDocid==0 );
- assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
-
- if( p==0 ){
- sqlite3_int64 iDocid = 0;
- char *pNext = 0;
- char *pDocid = aDoclist;
- char *pEnd = &aDoclist[nDoclist];
- int iMul = 1;
-
- while( pDocid<pEnd ){
- sqlite3_int64 iDelta;
- pDocid += sqlite3Fts3GetVarint(pDocid, &iDelta);
- iDocid += (iMul * iDelta);
- pNext = pDocid;
- fts3PoslistCopy(0, &pDocid);
- while( pDocid<pEnd && *pDocid==0 ) pDocid++;
- iMul = (bDescIdx ? -1 : 1);
- }
-
- *pnList = (int)(pEnd - pNext);
- *ppIter = pNext;
- *piDocid = iDocid;
- }else{
- int iMul = (bDescIdx ? -1 : 1);
- sqlite3_int64 iDelta;
- fts3GetReverseVarint(&p, aDoclist, &iDelta);
- *piDocid -= (iMul * iDelta);
-
- if( p==aDoclist ){
- *pbEof = 1;
- }else{
- char *pSave = p;
- fts3ReversePoslist(aDoclist, &p);
- *pnList = (int)(pSave - p);
- }
- *ppIter = p;
- }
-}
-
-/*
-** Iterate forwards through a doclist.
-*/
-void sqlite3Fts3DoclistNext(
- int bDescIdx, /* True if the doclist is desc */
- char *aDoclist, /* Pointer to entire doclist */
- int nDoclist, /* Length of aDoclist in bytes */
- char **ppIter, /* IN/OUT: Iterator pointer */
- sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */
- u8 *pbEof /* OUT: End-of-file flag */
-){
- char *p = *ppIter;
-
- assert( nDoclist>0 );
- assert( *pbEof==0 );
- assert( p || *piDocid==0 );
- assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) );
-
- if( p==0 ){
- p = aDoclist;
- p += sqlite3Fts3GetVarint(p, piDocid);
- }else{
- fts3PoslistCopy(0, &p);
- while( p<&aDoclist[nDoclist] && *p==0 ) p++;
- if( p>=&aDoclist[nDoclist] ){
- *pbEof = 1;
- }else{
- sqlite3_int64 iVar;
- p += sqlite3Fts3GetVarint(p, &iVar);
- *piDocid += ((bDescIdx ? -1 : 1) * iVar);
- }
- }
-
- *ppIter = p;
-}
-
-/*
-** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof
-** to true if EOF is reached.
-*/
-static void fts3EvalDlPhraseNext(
- Fts3Table *pTab,
- Fts3Doclist *pDL,
- u8 *pbEof
-){
- char *pIter; /* Used to iterate through aAll */
- char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
-
- if( pDL->pNextDocid ){
- pIter = pDL->pNextDocid;
- }else{
- pIter = pDL->aAll;
- }
-
- if( pIter>=pEnd ){
- /* We have already reached the end of this doclist. EOF. */
- *pbEof = 1;
- }else{
- sqlite3_int64 iDelta;
- pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
- if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
- pDL->iDocid += iDelta;
- }else{
- pDL->iDocid -= iDelta;
- }
- pDL->pList = pIter;
- fts3PoslistCopy(0, &pIter);
- pDL->nList = (int)(pIter - pDL->pList);
-
- /* pIter now points just past the 0x00 that terminates the position-
- ** list for document pDL->iDocid. However, if this position-list was
- ** edited in place by fts3EvalNearTrim(), then pIter may not actually
- ** point to the start of the next docid value. The following line deals
- ** with this case by advancing pIter past the zero-padding added by
- ** fts3EvalNearTrim(). */
- while( pIter<pEnd && *pIter==0 ) pIter++;
-
- pDL->pNextDocid = pIter;
- assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
- *pbEof = 0;
- }
-}
-
-/*
-** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext().
-*/
-typedef struct TokenDoclist TokenDoclist;
-struct TokenDoclist {
- int bIgnore;
- sqlite3_int64 iDocid;
- char *pList;
- int nList;
-};
-
-/*
-** Token pToken is an incrementally loaded token that is part of a
-** multi-token phrase. Advance it to the next matching document in the
-** database and populate output variable *p with the details of the new
-** entry. Or, if the iterator has reached EOF, set *pbEof to true.
-**
-** If an error occurs, return an SQLite error code. Otherwise, return
-** SQLITE_OK.
-*/
-static int incrPhraseTokenNext(
- Fts3Table *pTab, /* Virtual table handle */
- Fts3Phrase *pPhrase, /* Phrase to advance token of */
- int iToken, /* Specific token to advance */
- TokenDoclist *p, /* OUT: Docid and doclist for new entry */
- u8 *pbEof /* OUT: True if iterator is at EOF */
-){
- int rc = SQLITE_OK;
-
- if( pPhrase->iDoclistToken==iToken ){
- assert( p->bIgnore==0 );
- assert( pPhrase->aToken[iToken].pSegcsr==0 );
- fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof);
- p->pList = pPhrase->doclist.pList;
- p->nList = pPhrase->doclist.nList;
- p->iDocid = pPhrase->doclist.iDocid;
- }else{
- Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
- assert( pToken->pDeferred==0 );
- assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 );
- if( pToken->pSegcsr ){
- assert( p->bIgnore==0 );
- rc = sqlite3Fts3MsrIncrNext(
- pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList
- );
- if( p->pList==0 ) *pbEof = 1;
- }else{
- p->bIgnore = 1;
- }
- }
-
- return rc;
-}
-
-
-/*
-** The phrase iterator passed as the second argument:
-**
-** * features at least one token that uses an incremental doclist, and
-**
-** * does not contain any deferred tokens.
-**
-** Advance it to the next matching documnent in the database and populate
-** the Fts3Doclist.pList and nList fields.
-**
-** If there is no "next" entry and no error occurs, then *pbEof is set to
-** 1 before returning. Otherwise, if no error occurs and the iterator is
-** successfully advanced, *pbEof is set to 0.
-**
-** If an error occurs, return an SQLite error code. Otherwise, return
-** SQLITE_OK.
-*/
-static int fts3EvalIncrPhraseNext(
- Fts3Cursor *pCsr, /* FTS Cursor handle */
- Fts3Phrase *p, /* Phrase object to advance to next docid */
- u8 *pbEof /* OUT: Set to 1 if EOF */
-){
- int rc = SQLITE_OK;
- Fts3Doclist *pDL = &p->doclist;
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- u8 bEof = 0;
-
- /* This is only called if it is guaranteed that the phrase has at least
- ** one incremental token. In which case the bIncr flag is set. */
- assert( p->bIncr==1 );
-
- if( p->nToken==1 ){
- rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
- &pDL->iDocid, &pDL->pList, &pDL->nList
- );
- if( pDL->pList==0 ) bEof = 1;
- }else{
- int bDescDoclist = pCsr->bDesc;
- struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS];
-
- memset(a, 0, sizeof(a));
- assert( p->nToken<=MAX_INCR_PHRASE_TOKENS );
- assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS );
-
- while( bEof==0 ){
- int bMaxSet = 0;
- sqlite3_int64 iMax = 0; /* Largest docid for all iterators */
- int i; /* Used to iterate through tokens */
-
- /* Advance the iterator for each token in the phrase once. */
- for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){
- rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
- if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
- iMax = a[i].iDocid;
- bMaxSet = 1;
- }
- }
- assert( rc!=SQLITE_OK || (p->nToken>=1 && a[p->nToken-1].bIgnore==0) );
- assert( rc!=SQLITE_OK || bMaxSet );
-
- /* Keep advancing iterators until they all point to the same document */
- for(i=0; i<p->nToken; i++){
- while( rc==SQLITE_OK && bEof==0
- && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
- ){
- rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
- if( DOCID_CMP(a[i].iDocid, iMax)>0 ){
- iMax = a[i].iDocid;
- i = 0;
- }
- }
- }
-
- /* Check if the current entries really are a phrase match */
- if( bEof==0 ){
- int nList = 0;
- int nByte = a[p->nToken-1].nList;
- char *aDoclist = sqlite3_malloc(nByte+1);
- if( !aDoclist ) return SQLITE_NOMEM;
- memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
-
- for(i=0; i<(p->nToken-1); i++){
- if( a[i].bIgnore==0 ){
- char *pL = a[i].pList;
- char *pR = aDoclist;
- char *pOut = aDoclist;
- int nDist = p->nToken-1-i;
- int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR);
- if( res==0 ) break;
- nList = (int)(pOut - aDoclist);
- }
- }
- if( i==(p->nToken-1) ){
- pDL->iDocid = iMax;
- pDL->pList = aDoclist;
- pDL->nList = nList;
- pDL->bFreeList = 1;
- break;
- }
- sqlite3_free(aDoclist);
- }
- }
- }
-
- *pbEof = bEof;
- return rc;
-}
-
-/*
-** Attempt to move the phrase iterator to point to the next matching docid.
-** If an error occurs, return an SQLite error code. Otherwise, return
-** SQLITE_OK.
-**
-** If there is no "next" entry and no error occurs, then *pbEof is set to
-** 1 before returning. Otherwise, if no error occurs and the iterator is
-** successfully advanced, *pbEof is set to 0.
-*/
-static int fts3EvalPhraseNext(
- Fts3Cursor *pCsr, /* FTS Cursor handle */
- Fts3Phrase *p, /* Phrase object to advance to next docid */
- u8 *pbEof /* OUT: Set to 1 if EOF */
-){
- int rc = SQLITE_OK;
- Fts3Doclist *pDL = &p->doclist;
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
-
- if( p->bIncr ){
- rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof);
- }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
- sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
- &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
- );
- pDL->pList = pDL->pNextDocid;
- }else{
- fts3EvalDlPhraseNext(pTab, pDL, pbEof);
- }
-
- return rc;
-}
-
-/*
-**
-** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
-** expression. Also the Fts3Expr.bDeferred variable is set to true for any
-** expressions for which all descendent tokens are deferred.
-**
-** If parameter bOptOk is zero, then it is guaranteed that the
-** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
-** each phrase in the expression (subject to deferred token processing).
-** Or, if bOptOk is non-zero, then one or more tokens within the expression
-** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
-**
-** If an error occurs within this function, *pRc is set to an SQLite error
-** code before returning.
-*/
-static void fts3EvalStartReaders(
- Fts3Cursor *pCsr, /* FTS Cursor handle */
- Fts3Expr *pExpr, /* Expression to initialize phrases in */
- int *pRc /* IN/OUT: Error code */
-){
- if( pExpr && SQLITE_OK==*pRc ){
- if( pExpr->eType==FTSQUERY_PHRASE ){
- int nToken = pExpr->pPhrase->nToken;
- if( nToken ){
- int i;
- for(i=0; i<nToken; i++){
- if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
- }
- pExpr->bDeferred = (i==nToken);
- }
- *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
- }else{
- fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
- fts3EvalStartReaders(pCsr, pExpr->pRight, pRc);
- pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
- }
- }
-}
-
-/*
-** An array of the following structures is assembled as part of the process
-** of selecting tokens to defer before the query starts executing (as part
-** of the xFilter() method). There is one element in the array for each
-** token in the FTS expression.
-**
-** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
-** to phrases that are connected only by AND and NEAR operators (not OR or
-** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
-** separately. The root of a tokens AND/NEAR cluster is stored in
-** Fts3TokenAndCost.pRoot.
-*/
-typedef struct Fts3TokenAndCost Fts3TokenAndCost;
-struct Fts3TokenAndCost {
- Fts3Phrase *pPhrase; /* The phrase the token belongs to */
- int iToken; /* Position of token in phrase */
- Fts3PhraseToken *pToken; /* The token itself */
- Fts3Expr *pRoot; /* Root of NEAR/AND cluster */
- int nOvfl; /* Number of overflow pages to load doclist */
- int iCol; /* The column the token must match */
-};
-
-/*
-** This function is used to populate an allocated Fts3TokenAndCost array.
-**
-** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-** Otherwise, if an error occurs during execution, *pRc is set to an
-** SQLite error code.
-*/
-static void fts3EvalTokenCosts(
- Fts3Cursor *pCsr, /* FTS Cursor handle */
- Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */
- Fts3Expr *pExpr, /* Expression to consider */
- Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */
- Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */
- int *pRc /* IN/OUT: Error code */
-){
- if( *pRc==SQLITE_OK ){
- if( pExpr->eType==FTSQUERY_PHRASE ){
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- int i;
- for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
- Fts3TokenAndCost *pTC = (*ppTC)++;
- pTC->pPhrase = pPhrase;
- pTC->iToken = i;
- pTC->pRoot = pRoot;
- pTC->pToken = &pPhrase->aToken[i];
- pTC->iCol = pPhrase->iColumn;
- *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
- }
- }else if( pExpr->eType!=FTSQUERY_NOT ){
- assert( pExpr->eType==FTSQUERY_OR
- || pExpr->eType==FTSQUERY_AND
- || pExpr->eType==FTSQUERY_NEAR
- );
- assert( pExpr->pLeft && pExpr->pRight );
- if( pExpr->eType==FTSQUERY_OR ){
- pRoot = pExpr->pLeft;
- **ppOr = pRoot;
- (*ppOr)++;
- }
- fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc);
- if( pExpr->eType==FTSQUERY_OR ){
- pRoot = pExpr->pRight;
- **ppOr = pRoot;
- (*ppOr)++;
- }
- fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
- }
- }
-}
-
-/*
-** Determine the average document (row) size in pages. If successful,
-** write this value to *pnPage and return SQLITE_OK. Otherwise, return
-** an SQLite error code.
-**
-** The average document size in pages is calculated by first calculating
-** determining the average size in bytes, B. If B is less than the amount
-** of data that will fit on a single leaf page of an intkey table in
-** this database, then the average docsize is 1. Otherwise, it is 1 plus
-** the number of overflow pages consumed by a record B bytes in size.
-*/
-static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
- int rc = SQLITE_OK;
- if( pCsr->nRowAvg==0 ){
- /* The average document size, which is required to calculate the cost
- ** of each doclist, has not yet been determined. Read the required
- ** data from the %_stat table to calculate it.
- **
- ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
- ** varints, where nCol is the number of columns in the FTS3 table.
- ** The first varint is the number of documents currently stored in
- ** the table. The following nCol varints contain the total amount of
- ** data stored in all rows of each column of the table, from left
- ** to right.
- */
- Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
- sqlite3_stmt *pStmt;
- sqlite3_int64 nDoc = 0;
- sqlite3_int64 nByte = 0;
- const char *pEnd;
- const char *a;
-
- rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
- if( rc!=SQLITE_OK ) return rc;
- a = sqlite3_column_blob(pStmt, 0);
- assert( a );
-
- pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
- a += sqlite3Fts3GetVarint(a, &nDoc);
- while( a<pEnd ){
- a += sqlite3Fts3GetVarint(a, &nByte);
- }
- if( nDoc==0 || nByte==0 ){
- sqlite3_reset(pStmt);
- return FTS_CORRUPT_VTAB;
- }
-
- pCsr->nDoc = nDoc;
- pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
- assert( pCsr->nRowAvg>0 );
- rc = sqlite3_reset(pStmt);
- }
-
- *pnPage = pCsr->nRowAvg;
- return rc;
-}
-
-/*
-** This function is called to select the tokens (if any) that will be
-** deferred. The array aTC[] has already been populated when this is
-** called.
-**
-** This function is called once for each AND/NEAR cluster in the
-** expression. Each invocation determines which tokens to defer within
-** the cluster with root node pRoot. See comments above the definition
-** of struct Fts3TokenAndCost for more details.
-**
-** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
-** called on each token to defer. Otherwise, an SQLite error code is
-** returned.
-*/
-static int fts3EvalSelectDeferred(
- Fts3Cursor *pCsr, /* FTS Cursor handle */
- Fts3Expr *pRoot, /* Consider tokens with this root node */
- Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */
- int nTC /* Number of entries in aTC[] */
-){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int nDocSize = 0; /* Number of pages per doc loaded */
- int rc = SQLITE_OK; /* Return code */
- int ii; /* Iterator variable for various purposes */
- int nOvfl = 0; /* Total overflow pages used by doclists */
- int nToken = 0; /* Total number of tokens in cluster */
-
- int nMinEst = 0; /* The minimum count for any phrase so far. */
- int nLoad4 = 1; /* (Phrases that will be loaded)^4. */
-
- /* Tokens are never deferred for FTS tables created using the content=xxx
- ** option. The reason being that it is not guaranteed that the content
- ** table actually contains the same data as the index. To prevent this from
- ** causing any problems, the deferred token optimization is completely
- ** disabled for content=xxx tables. */
- if( pTab->zContentTbl ){
- return SQLITE_OK;
- }
-
- /* Count the tokens in this AND/NEAR cluster. If none of the doclists
- ** associated with the tokens spill onto overflow pages, or if there is
- ** only 1 token, exit early. No tokens to defer in this case. */
- for(ii=0; ii<nTC; ii++){
- if( aTC[ii].pRoot==pRoot ){
- nOvfl += aTC[ii].nOvfl;
- nToken++;
- }
- }
- if( nOvfl==0 || nToken<2 ) return SQLITE_OK;
-
- /* Obtain the average docsize (in pages). */
- rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
- assert( rc!=SQLITE_OK || nDocSize>0 );
-
-
- /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
- ** of the number of overflow pages that will be loaded by the pager layer
- ** to retrieve the entire doclist for the token from the full-text index.
- ** Load the doclists for tokens that are either:
- **
- ** a. The cheapest token in the entire query (i.e. the one visited by the
- ** first iteration of this loop), or
- **
- ** b. Part of a multi-token phrase.
- **
- ** After each token doclist is loaded, merge it with the others from the
- ** same phrase and count the number of documents that the merged doclist
- ** contains. Set variable "nMinEst" to the smallest number of documents in
- ** any phrase doclist for which 1 or more token doclists have been loaded.
- ** Let nOther be the number of other phrases for which it is certain that
- ** one or more tokens will not be deferred.
- **
- ** Then, for each token, defer it if loading the doclist would result in
- ** loading N or more overflow pages into memory, where N is computed as:
- **
- ** (nMinEst + 4^nOther - 1) / (4^nOther)
- */
- for(ii=0; ii<nToken && rc==SQLITE_OK; ii++){
- int iTC; /* Used to iterate through aTC[] array. */
- Fts3TokenAndCost *pTC = 0; /* Set to cheapest remaining token. */
-
- /* Set pTC to point to the cheapest remaining token. */
- for(iTC=0; iTC<nTC; iTC++){
- if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
- && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
- ){
- pTC = &aTC[iTC];
- }
- }
- assert( pTC );
-
- if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
- /* The number of overflow pages to load for this (and therefore all
- ** subsequent) tokens is greater than the estimated number of pages
- ** that will be loaded if all subsequent tokens are deferred.
- */
- Fts3PhraseToken *pToken = pTC->pToken;
- rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
- fts3SegReaderCursorFree(pToken->pSegcsr);
- pToken->pSegcsr = 0;
- }else{
- /* Set nLoad4 to the value of (4^nOther) for the next iteration of the
- ** for-loop. Except, limit the value to 2^24 to prevent it from
- ** overflowing the 32-bit integer it is stored in. */
- if( ii<12 ) nLoad4 = nLoad4*4;
-
- if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){
- /* Either this is the cheapest token in the entire query, or it is
- ** part of a multi-token phrase. Either way, the entire doclist will
- ** (eventually) be loaded into memory. It may as well be now. */
- Fts3PhraseToken *pToken = pTC->pToken;
- int nList = 0;
- char *pList = 0;
- rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
- assert( rc==SQLITE_OK || pList==0 );
- if( rc==SQLITE_OK ){
- rc = fts3EvalPhraseMergeToken(
- pTab, pTC->pPhrase, pTC->iToken,pList,nList
- );
- }
- if( rc==SQLITE_OK ){
- int nCount;
- nCount = fts3DoclistCountDocids(
- pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
- );
- if( ii==0 || nCount<nMinEst ) nMinEst = nCount;
- }
- }
- }
- pTC->pToken = 0;
- }
-
- return rc;
-}
-
-/*
-** This function is called from within the xFilter method. It initializes
-** the full-text query currently stored in pCsr->pExpr. To iterate through
-** the results of a query, the caller does:
-**
-** fts3EvalStart(pCsr);
-** while( 1 ){
-** fts3EvalNext(pCsr);
-** if( pCsr->bEof ) break;
-** ... return row pCsr->iPrevId to the caller ...
-** }
-*/
-static int fts3EvalStart(Fts3Cursor *pCsr){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int rc = SQLITE_OK;
- int nToken = 0;
- int nOr = 0;
-
- /* Allocate a MultiSegReader for each token in the expression. */
- fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
-
- /* Determine which, if any, tokens in the expression should be deferred. */
-#ifndef SQLITE_DISABLE_FTS4_DEFERRED
- if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
- Fts3TokenAndCost *aTC;
- Fts3Expr **apOr;
- aTC = (Fts3TokenAndCost *)sqlite3_malloc(
- sizeof(Fts3TokenAndCost) * nToken
- + sizeof(Fts3Expr *) * nOr * 2
- );
- apOr = (Fts3Expr **)&aTC[nToken];
-
- if( !aTC ){
- rc = SQLITE_NOMEM;
- }else{
- int ii;
- Fts3TokenAndCost *pTC = aTC;
- Fts3Expr **ppOr = apOr;
-
- fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
- nToken = (int)(pTC-aTC);
- nOr = (int)(ppOr-apOr);
-
- if( rc==SQLITE_OK ){
- rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
- for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
- rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
- }
- }
-
- sqlite3_free(aTC);
- }
- }
-#endif
-
- fts3EvalStartReaders(pCsr, pCsr->pExpr, &rc);
- return rc;
-}
-
-/*
-** Invalidate the current position list for phrase pPhrase.
-*/
-static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
- if( pPhrase->doclist.bFreeList ){
- sqlite3_free(pPhrase->doclist.pList);
- }
- pPhrase->doclist.pList = 0;
- pPhrase->doclist.nList = 0;
- pPhrase->doclist.bFreeList = 0;
-}
-
-/*
-** This function is called to edit the position list associated with
-** the phrase object passed as the fifth argument according to a NEAR
-** condition. For example:
-**
-** abc NEAR/5 "def ghi"
-**
-** Parameter nNear is passed the NEAR distance of the expression (5 in
-** the example above). When this function is called, *paPoslist points to
-** the position list, and *pnToken is the number of phrase tokens in, the
-** phrase on the other side of the NEAR operator to pPhrase. For example,
-** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
-** the position list associated with phrase "abc".
-**
-** All positions in the pPhrase position list that are not sufficiently
-** close to a position in the *paPoslist position list are removed. If this
-** leaves 0 positions, zero is returned. Otherwise, non-zero.
-**
-** Before returning, *paPoslist is set to point to the position lsit
-** associated with pPhrase. And *pnToken is set to the number of tokens in
-** pPhrase.
-*/
-static int fts3EvalNearTrim(
- int nNear, /* NEAR distance. As in "NEAR/nNear". */
- char *aTmp, /* Temporary space to use */
- char **paPoslist, /* IN/OUT: Position list */
- int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
- Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
-){
- int nParam1 = nNear + pPhrase->nToken;
- int nParam2 = nNear + *pnToken;
- int nNew;
- char *p2;
- char *pOut;
- int res;
-
- assert( pPhrase->doclist.pList );
-
- p2 = pOut = pPhrase->doclist.pList;
- res = fts3PoslistNearMerge(
- &pOut, aTmp, nParam1, nParam2, paPoslist, &p2
- );
- if( res ){
- nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
- assert( pPhrase->doclist.pList[nNew]=='\0' );
- assert( nNew<=pPhrase->doclist.nList && nNew>0 );
- memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
- pPhrase->doclist.nList = nNew;
- *paPoslist = pPhrase->doclist.pList;
- *pnToken = pPhrase->nToken;
- }
-
- return res;
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
-** Otherwise, it advances the expression passed as the second argument to
-** point to the next matching row in the database. Expressions iterate through
-** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
-** or descending if it is non-zero.
-**
-** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
-** successful, the following variables in pExpr are set:
-**
-** Fts3Expr.bEof (non-zero if EOF - there is no next row)
-** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row)
-**
-** If the expression is of type FTSQUERY_PHRASE, and the expression is not
-** at EOF, then the following variables are populated with the position list
-** for the phrase for the visited row:
-**
-** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes)
-** FTs3Expr.pPhrase->doclist.pList (pointer to position list)
-**
-** It says above that this function advances the expression to the next
-** matching row. This is usually true, but there are the following exceptions:
-**
-** 1. Deferred tokens are not taken into account. If a phrase consists
-** entirely of deferred tokens, it is assumed to match every row in
-** the db. In this case the position-list is not populated at all.
-**
-** Or, if a phrase contains one or more deferred tokens and one or
-** more non-deferred tokens, then the expression is advanced to the
-** next possible match, considering only non-deferred tokens. In other
-** words, if the phrase is "A B C", and "B" is deferred, the expression
-** is advanced to the next row that contains an instance of "A * C",
-** where "*" may match any single token. The position list in this case
-** is populated as for "A * C" before returning.
-**
-** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
-** advanced to point to the next row that matches "x AND y".
-**
-** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is
-** really a match, taking into account deferred tokens and NEAR operators.
-*/
-static void fts3EvalNextRow(
- Fts3Cursor *pCsr, /* FTS Cursor handle */
- Fts3Expr *pExpr, /* Expr. to advance to next matching row */
- int *pRc /* IN/OUT: Error code */
-){
- if( *pRc==SQLITE_OK ){
- int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */
- assert( pExpr->bEof==0 );
- pExpr->bStart = 1;
-
- switch( pExpr->eType ){
- case FTSQUERY_NEAR:
- case FTSQUERY_AND: {
- Fts3Expr *pLeft = pExpr->pLeft;
- Fts3Expr *pRight = pExpr->pRight;
- assert( !pLeft->bDeferred || !pRight->bDeferred );
-
- if( pLeft->bDeferred ){
- /* LHS is entirely deferred. So we assume it matches every row.
- ** Advance the RHS iterator to find the next row visited. */
- fts3EvalNextRow(pCsr, pRight, pRc);
- pExpr->iDocid = pRight->iDocid;
- pExpr->bEof = pRight->bEof;
- }else if( pRight->bDeferred ){
- /* RHS is entirely deferred. So we assume it matches every row.
- ** Advance the LHS iterator to find the next row visited. */
- fts3EvalNextRow(pCsr, pLeft, pRc);
- pExpr->iDocid = pLeft->iDocid;
- pExpr->bEof = pLeft->bEof;
- }else{
- /* Neither the RHS or LHS are deferred. */
- fts3EvalNextRow(pCsr, pLeft, pRc);
- fts3EvalNextRow(pCsr, pRight, pRc);
- while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
- sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
- if( iDiff==0 ) break;
- if( iDiff<0 ){
- fts3EvalNextRow(pCsr, pLeft, pRc);
- }else{
- fts3EvalNextRow(pCsr, pRight, pRc);
- }
- }
- pExpr->iDocid = pLeft->iDocid;
- pExpr->bEof = (pLeft->bEof || pRight->bEof);
- if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
- assert( pRight->eType==FTSQUERY_PHRASE );
- if( pRight->pPhrase->doclist.aAll ){
- Fts3Doclist *pDl = &pRight->pPhrase->doclist;
- while( *pRc==SQLITE_OK && pRight->bEof==0 ){
- memset(pDl->pList, 0, pDl->nList);
- fts3EvalNextRow(pCsr, pRight, pRc);
- }
- }
- if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){
- Fts3Doclist *pDl = &pLeft->pPhrase->doclist;
- while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
- memset(pDl->pList, 0, pDl->nList);
- fts3EvalNextRow(pCsr, pLeft, pRc);
- }
- }
- }
- }
- break;
- }
-
- case FTSQUERY_OR: {
- Fts3Expr *pLeft = pExpr->pLeft;
- Fts3Expr *pRight = pExpr->pRight;
- sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
-
- assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
- assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
-
- if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
- fts3EvalNextRow(pCsr, pLeft, pRc);
- }else if( pLeft->bEof || iCmp>0 ){
- fts3EvalNextRow(pCsr, pRight, pRc);
- }else{
- fts3EvalNextRow(pCsr, pLeft, pRc);
- fts3EvalNextRow(pCsr, pRight, pRc);
- }
-
- pExpr->bEof = (pLeft->bEof && pRight->bEof);
- iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
- if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
- pExpr->iDocid = pLeft->iDocid;
- }else{
- pExpr->iDocid = pRight->iDocid;
- }
-
- break;
- }
-
- case FTSQUERY_NOT: {
- Fts3Expr *pLeft = pExpr->pLeft;
- Fts3Expr *pRight = pExpr->pRight;
-
- if( pRight->bStart==0 ){
- fts3EvalNextRow(pCsr, pRight, pRc);
- assert( *pRc!=SQLITE_OK || pRight->bStart );
- }
-
- fts3EvalNextRow(pCsr, pLeft, pRc);
- if( pLeft->bEof==0 ){
- while( !*pRc
- && !pRight->bEof
- && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
- ){
- fts3EvalNextRow(pCsr, pRight, pRc);
- }
- }
- pExpr->iDocid = pLeft->iDocid;
- pExpr->bEof = pLeft->bEof;
- break;
- }
-
- default: {
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- fts3EvalInvalidatePoslist(pPhrase);
- *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
- pExpr->iDocid = pPhrase->doclist.iDocid;
- break;
- }
- }
- }
-}
-
-/*
-** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
-** cluster, then this function returns 1 immediately.
-**
-** Otherwise, it checks if the current row really does match the NEAR
-** expression, using the data currently stored in the position lists
-** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
-**
-** If the current row is a match, the position list associated with each
-** phrase in the NEAR expression is edited in place to contain only those
-** phrase instances sufficiently close to their peers to satisfy all NEAR
-** constraints. In this case it returns 1. If the NEAR expression does not
-** match the current row, 0 is returned. The position lists may or may not
-** be edited if 0 is returned.
-*/
-static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
- int res = 1;
-
- /* The following block runs if pExpr is the root of a NEAR query.
- ** For example, the query:
- **
- ** "w" NEAR "x" NEAR "y" NEAR "z"
- **
- ** which is represented in tree form as:
- **
- ** |
- ** +--NEAR--+ <-- root of NEAR query
- ** | |
- ** +--NEAR--+ "z"
- ** | |
- ** +--NEAR--+ "y"
- ** | |
- ** "w" "x"
- **
- ** The right-hand child of a NEAR node is always a phrase. The
- ** left-hand child may be either a phrase or a NEAR node. There are
- ** no exceptions to this - it's the way the parser in fts3_expr.c works.
- */
- if( *pRc==SQLITE_OK
- && pExpr->eType==FTSQUERY_NEAR
- && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
- ){
- Fts3Expr *p;
- int nTmp = 0; /* Bytes of temp space */
- char *aTmp; /* Temp space for PoslistNearMerge() */
-
- /* Allocate temporary working space. */
- for(p=pExpr; p->pLeft; p=p->pLeft){
- assert( p->pRight->pPhrase->doclist.nList>0 );
- nTmp += p->pRight->pPhrase->doclist.nList;
- }
- nTmp += p->pPhrase->doclist.nList;
- aTmp = sqlite3_malloc(nTmp*2);
- if( !aTmp ){
- *pRc = SQLITE_NOMEM;
- res = 0;
- }else{
- char *aPoslist = p->pPhrase->doclist.pList;
- int nToken = p->pPhrase->nToken;
-
- for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
- Fts3Phrase *pPhrase = p->pRight->pPhrase;
- int nNear = p->nNear;
- res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
- }
-
- aPoslist = pExpr->pRight->pPhrase->doclist.pList;
- nToken = pExpr->pRight->pPhrase->nToken;
- for(p=pExpr->pLeft; p && res; p=p->pLeft){
- int nNear;
- Fts3Phrase *pPhrase;
- assert( p->pParent && p->pParent->pLeft==p );
- nNear = p->pParent->nNear;
- pPhrase = (
- p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
- );
- res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
- }
- }
-
- sqlite3_free(aTmp);
- }
-
- return res;
-}
-
-/*
-** This function is a helper function for sqlite3Fts3EvalTestDeferred().
-** Assuming no error occurs or has occurred, It returns non-zero if the
-** expression passed as the second argument matches the row that pCsr
-** currently points to, or zero if it does not.
-**
-** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-** If an error occurs during execution of this function, *pRc is set to
-** the appropriate SQLite error code. In this case the returned value is
-** undefined.
-*/
-static int fts3EvalTestExpr(
- Fts3Cursor *pCsr, /* FTS cursor handle */
- Fts3Expr *pExpr, /* Expr to test. May or may not be root. */
- int *pRc /* IN/OUT: Error code */
-){
- int bHit = 1; /* Return value */
- if( *pRc==SQLITE_OK ){
- switch( pExpr->eType ){
- case FTSQUERY_NEAR:
- case FTSQUERY_AND:
- bHit = (
- fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
- && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
- && fts3EvalNearTest(pExpr, pRc)
- );
-
- /* If the NEAR expression does not match any rows, zero the doclist for
- ** all phrases involved in the NEAR. This is because the snippet(),
- ** offsets() and matchinfo() functions are not supposed to recognize
- ** any instances of phrases that are part of unmatched NEAR queries.
- ** For example if this expression:
- **
- ** ... MATCH 'a OR (b NEAR c)'
- **
- ** is matched against a row containing:
- **
- ** 'a b d e'
- **
- ** then any snippet() should ony highlight the "a" term, not the "b"
- ** (as "b" is part of a non-matching NEAR clause).
- */
- if( bHit==0
- && pExpr->eType==FTSQUERY_NEAR
- && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
- ){
- Fts3Expr *p;
- for(p=pExpr; p->pPhrase==0; p=p->pLeft){
- if( p->pRight->iDocid==pCsr->iPrevId ){
- fts3EvalInvalidatePoslist(p->pRight->pPhrase);
- }
- }
- if( p->iDocid==pCsr->iPrevId ){
- fts3EvalInvalidatePoslist(p->pPhrase);
- }
- }
-
- break;
-
- case FTSQUERY_OR: {
- int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
- int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
- bHit = bHit1 || bHit2;
- break;
- }
-
- case FTSQUERY_NOT:
- bHit = (
- fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
- && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
- );
- break;
-
- default: {
-#ifndef SQLITE_DISABLE_FTS4_DEFERRED
- if( pCsr->pDeferred
- && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
- ){
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
- if( pExpr->bDeferred ){
- fts3EvalInvalidatePoslist(pPhrase);
- }
- *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
- bHit = (pPhrase->doclist.pList!=0);
- pExpr->iDocid = pCsr->iPrevId;
- }else
-#endif
- {
- bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
- }
- break;
- }
- }
- }
- return bHit;
-}
-
-/*
-** This function is called as the second part of each xNext operation when
-** iterating through the results of a full-text query. At this point the
-** cursor points to a row that matches the query expression, with the
-** following caveats:
-**
-** * Up until this point, "NEAR" operators in the expression have been
-** treated as "AND".
-**
-** * Deferred tokens have not yet been considered.
-**
-** If *pRc is not SQLITE_OK when this function is called, it immediately
-** returns 0. Otherwise, it tests whether or not after considering NEAR
-** operators and deferred tokens the current row is still a match for the
-** expression. It returns 1 if both of the following are true:
-**
-** 1. *pRc is SQLITE_OK when this function returns, and
-**
-** 2. After scanning the current FTS table row for the deferred tokens,
-** it is determined that the row does *not* match the query.
-**
-** Or, if no error occurs and it seems the current row does match the FTS
-** query, return 0.
-*/
-int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){
- int rc = *pRc;
- int bMiss = 0;
- if( rc==SQLITE_OK ){
-
- /* If there are one or more deferred tokens, load the current row into
- ** memory and scan it to determine the position list for each deferred
- ** token. Then, see if this row is really a match, considering deferred
- ** tokens and NEAR operators (neither of which were taken into account
- ** earlier, by fts3EvalNextRow()).
- */
- if( pCsr->pDeferred ){
- rc = fts3CursorSeek(0, pCsr);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
- }
- }
- bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
-
- /* Free the position-lists accumulated for each deferred token above. */
- sqlite3Fts3FreeDeferredDoclists(pCsr);
- *pRc = rc;
- }
- return (rc==SQLITE_OK && bMiss);
-}
-
-/*
-** Advance to the next document that matches the FTS expression in
-** Fts3Cursor.pExpr.
-*/
-static int fts3EvalNext(Fts3Cursor *pCsr){
- int rc = SQLITE_OK; /* Return Code */
- Fts3Expr *pExpr = pCsr->pExpr;
- assert( pCsr->isEof==0 );
- if( pExpr==0 ){
- pCsr->isEof = 1;
- }else{
- do {
- if( pCsr->isRequireSeek==0 ){
- sqlite3_reset(pCsr->pStmt);
- }
- assert( sqlite3_data_count(pCsr->pStmt)==0 );
- fts3EvalNextRow(pCsr, pExpr, &rc);
- pCsr->isEof = pExpr->bEof;
- pCsr->isRequireSeek = 1;
- pCsr->isMatchinfoNeeded = 1;
- pCsr->iPrevId = pExpr->iDocid;
- }while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) );
- }
-
- /* Check if the cursor is past the end of the docid range specified
- ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */
- if( rc==SQLITE_OK && (
- (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid)
- || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid)
- )){
- pCsr->isEof = 1;
- }
-
- return rc;
-}
-
-/*
-** Restart interation for expression pExpr so that the next call to
-** fts3EvalNext() visits the first row. Do not allow incremental
-** loading or merging of phrase doclists for this iteration.
-**
-** If *pRc is other than SQLITE_OK when this function is called, it is
-** a no-op. If an error occurs within this function, *pRc is set to an
-** SQLite error code before returning.
-*/
-static void fts3EvalRestart(
- Fts3Cursor *pCsr,
- Fts3Expr *pExpr,
- int *pRc
-){
- if( pExpr && *pRc==SQLITE_OK ){
- Fts3Phrase *pPhrase = pExpr->pPhrase;
-
- if( pPhrase ){
- fts3EvalInvalidatePoslist(pPhrase);
- if( pPhrase->bIncr ){
- int i;
- for(i=0; i<pPhrase->nToken; i++){
- Fts3PhraseToken *pToken = &pPhrase->aToken[i];
- assert( pToken->pDeferred==0 );
- if( pToken->pSegcsr ){
- sqlite3Fts3MsrIncrRestart(pToken->pSegcsr);
- }
- }
- *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
- }
- pPhrase->doclist.pNextDocid = 0;
- pPhrase->doclist.iDocid = 0;
- pPhrase->pOrPoslist = 0;
- }
-
- pExpr->iDocid = 0;
- pExpr->bEof = 0;
- pExpr->bStart = 0;
-
- fts3EvalRestart(pCsr, pExpr->pLeft, pRc);
- fts3EvalRestart(pCsr, pExpr->pRight, pRc);
- }
-}
-
-/*
-** After allocating the Fts3Expr.aMI[] array for each phrase in the
-** expression rooted at pExpr, the cursor iterates through all rows matched
-** by pExpr, calling this function for each row. This function increments
-** the values in Fts3Expr.aMI[] according to the position-list currently
-** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
-** expression nodes.
-*/
-static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
- if( pExpr ){
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- if( pPhrase && pPhrase->doclist.pList ){
- int iCol = 0;
- char *p = pPhrase->doclist.pList;
-
- assert( *p );
- while( 1 ){
- u8 c = 0;
- int iCnt = 0;
- while( 0xFE & (*p | c) ){
- if( (c&0x80)==0 ) iCnt++;
- c = *p++ & 0x80;
- }
-
- /* aMI[iCol*3 + 1] = Number of occurrences
- ** aMI[iCol*3 + 2] = Number of rows containing at least one instance
- */
- pExpr->aMI[iCol*3 + 1] += iCnt;
- pExpr->aMI[iCol*3 + 2] += (iCnt>0);
- if( *p==0x00 ) break;
- p++;
- p += fts3GetVarint32(p, &iCol);
- }
- }
-
- fts3EvalUpdateCounts(pExpr->pLeft);
- fts3EvalUpdateCounts(pExpr->pRight);
- }
-}
-
-/*
-** Expression pExpr must be of type FTSQUERY_PHRASE.
-**
-** If it is not already allocated and populated, this function allocates and
-** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part
-** of a NEAR expression, then it also allocates and populates the same array
-** for all other phrases that are part of the NEAR expression.
-**
-** SQLITE_OK is returned if the aMI[] array is successfully allocated and
-** populated. Otherwise, if an error occurs, an SQLite error code is returned.
-*/
-static int fts3EvalGatherStats(
- Fts3Cursor *pCsr, /* Cursor object */
- Fts3Expr *pExpr /* FTSQUERY_PHRASE expression */
-){
- int rc = SQLITE_OK; /* Return code */
-
- assert( pExpr->eType==FTSQUERY_PHRASE );
- if( pExpr->aMI==0 ){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- Fts3Expr *pRoot; /* Root of NEAR expression */
- Fts3Expr *p; /* Iterator used for several purposes */
-
- sqlite3_int64 iPrevId = pCsr->iPrevId;
- sqlite3_int64 iDocid;
- u8 bEof;
-
- /* Find the root of the NEAR expression */
- pRoot = pExpr;
- while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){
- pRoot = pRoot->pParent;
- }
- iDocid = pRoot->iDocid;
- bEof = pRoot->bEof;
- assert( pRoot->bStart );
-
- /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */
- for(p=pRoot; p; p=p->pLeft){
- Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
- assert( pE->aMI==0 );
- pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
- if( !pE->aMI ) return SQLITE_NOMEM;
- memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
- }
-
- fts3EvalRestart(pCsr, pRoot, &rc);
-
- while( pCsr->isEof==0 && rc==SQLITE_OK ){
-
- do {
- /* Ensure the %_content statement is reset. */
- if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
- assert( sqlite3_data_count(pCsr->pStmt)==0 );
-
- /* Advance to the next document */
- fts3EvalNextRow(pCsr, pRoot, &rc);
- pCsr->isEof = pRoot->bEof;
- pCsr->isRequireSeek = 1;
- pCsr->isMatchinfoNeeded = 1;
- pCsr->iPrevId = pRoot->iDocid;
- }while( pCsr->isEof==0
- && pRoot->eType==FTSQUERY_NEAR
- && sqlite3Fts3EvalTestDeferred(pCsr, &rc)
- );
-
- if( rc==SQLITE_OK && pCsr->isEof==0 ){
- fts3EvalUpdateCounts(pRoot);
- }
- }
-
- pCsr->isEof = 0;
- pCsr->iPrevId = iPrevId;
-
- if( bEof ){
- pRoot->bEof = bEof;
- }else{
- /* Caution: pRoot may iterate through docids in ascending or descending
- ** order. For this reason, even though it seems more defensive, the
- ** do loop can not be written:
- **
- ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
- */
- fts3EvalRestart(pCsr, pRoot, &rc);
- do {
- fts3EvalNextRow(pCsr, pRoot, &rc);
- assert( pRoot->bEof==0 );
- }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
- }
- }
- return rc;
-}
-
-/*
-** This function is used by the matchinfo() module to query a phrase
-** expression node for the following information:
-**
-** 1. The total number of occurrences of the phrase in each column of
-** the FTS table (considering all rows), and
-**
-** 2. For each column, the number of rows in the table for which the
-** column contains at least one instance of the phrase.
-**
-** If no error occurs, SQLITE_OK is returned and the values for each column
-** written into the array aiOut as follows:
-**
-** aiOut[iCol*3 + 1] = Number of occurrences
-** aiOut[iCol*3 + 2] = Number of rows containing at least one instance
-**
-** Caveats:
-**
-** * If a phrase consists entirely of deferred tokens, then all output
-** values are set to the number of documents in the table. In other
-** words we assume that very common tokens occur exactly once in each
-** column of each row of the table.
-**
-** * If a phrase contains some deferred tokens (and some non-deferred
-** tokens), count the potential occurrence identified by considering
-** the non-deferred tokens instead of actual phrase occurrences.
-**
-** * If the phrase is part of a NEAR expression, then only phrase instances
-** that meet the NEAR constraint are included in the counts.
-*/
-int sqlite3Fts3EvalPhraseStats(
- Fts3Cursor *pCsr, /* FTS cursor handle */
- Fts3Expr *pExpr, /* Phrase expression */
- u32 *aiOut /* Array to write results into (see above) */
-){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int rc = SQLITE_OK;
- int iCol;
-
- if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
- assert( pCsr->nDoc>0 );
- for(iCol=0; iCol<pTab->nColumn; iCol++){
- aiOut[iCol*3 + 1] = (u32)pCsr->nDoc;
- aiOut[iCol*3 + 2] = (u32)pCsr->nDoc;
- }
- }else{
- rc = fts3EvalGatherStats(pCsr, pExpr);
- if( rc==SQLITE_OK ){
- assert( pExpr->aMI );
- for(iCol=0; iCol<pTab->nColumn; iCol++){
- aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1];
- aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2];
- }
- }
- }
-
- return rc;
-}
-
-/*
-** The expression pExpr passed as the second argument to this function
-** must be of type FTSQUERY_PHRASE.
-**
-** The returned value is either NULL or a pointer to a buffer containing
-** a position-list indicating the occurrences of the phrase in column iCol
-** of the current row.
-**
-** More specifically, the returned buffer contains 1 varint for each
-** occurrence of the phrase in the column, stored using the normal (delta+2)
-** compression and is terminated by either an 0x01 or 0x00 byte. For example,
-** if the requested column contains "a b X c d X X" and the position-list
-** for 'X' is requested, the buffer returned may contain:
-**
-** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00
-**
-** This function works regardless of whether or not the phrase is deferred,
-** incremental, or neither.
-*/
-int sqlite3Fts3EvalPhrasePoslist(
- Fts3Cursor *pCsr, /* FTS3 cursor object */
- Fts3Expr *pExpr, /* Phrase to return doclist for */
- int iCol, /* Column to return position list for */
- char **ppOut /* OUT: Pointer to position list */
-){
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- char *pIter;
- int iThis;
- sqlite3_int64 iDocid;
-
- /* If this phrase is applies specifically to some column other than
- ** column iCol, return a NULL pointer. */
- *ppOut = 0;
- assert( iCol>=0 && iCol<pTab->nColumn );
- if( (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) ){
- return SQLITE_OK;
- }
-
- iDocid = pExpr->iDocid;
- pIter = pPhrase->doclist.pList;
- if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
- int rc = SQLITE_OK;
- int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
- int bOr = 0;
- u8 bTreeEof = 0;
- Fts3Expr *p; /* Used to iterate from pExpr to root */
- Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */
- int bMatch;
-
- /* Check if this phrase descends from an OR expression node. If not,
- ** return NULL. Otherwise, the entry that corresponds to docid
- ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
- ** tree that the node is part of has been marked as EOF, but the node
- ** itself is not EOF, then it may point to an earlier entry. */
- pNear = pExpr;
- for(p=pExpr->pParent; p; p=p->pParent){
- if( p->eType==FTSQUERY_OR ) bOr = 1;
- if( p->eType==FTSQUERY_NEAR ) pNear = p;
- if( p->bEof ) bTreeEof = 1;
- }
- if( bOr==0 ) return SQLITE_OK;
-
- /* This is the descendent of an OR node. In this case we cannot use
- ** an incremental phrase. Load the entire doclist for the phrase
- ** into memory in this case. */
- if( pPhrase->bIncr ){
- int bEofSave = pNear->bEof;
- fts3EvalRestart(pCsr, pNear, &rc);
- while( rc==SQLITE_OK && !pNear->bEof ){
- fts3EvalNextRow(pCsr, pNear, &rc);
- if( bEofSave==0 && pNear->iDocid==iDocid ) break;
- }
- assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
- }
- if( bTreeEof ){
- while( rc==SQLITE_OK && !pNear->bEof ){
- fts3EvalNextRow(pCsr, pNear, &rc);
- }
- }
- if( rc!=SQLITE_OK ) return rc;
-
- bMatch = 1;
- for(p=pNear; p; p=p->pLeft){
- u8 bEof = 0;
- Fts3Expr *pTest = p;
- Fts3Phrase *pPh;
- assert( pTest->eType==FTSQUERY_NEAR || pTest->eType==FTSQUERY_PHRASE );
- if( pTest->eType==FTSQUERY_NEAR ) pTest = pTest->pRight;
- assert( pTest->eType==FTSQUERY_PHRASE );
- pPh = pTest->pPhrase;
-
- pIter = pPh->pOrPoslist;
- iDocid = pPh->iOrDocid;
- if( pCsr->bDesc==bDescDoclist ){
- bEof = !pPh->doclist.nAll ||
- (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll));
- while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
- sqlite3Fts3DoclistNext(
- bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll,
- &pIter, &iDocid, &bEof
- );
- }
- }else{
- bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll);
- while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
- int dummy;
- sqlite3Fts3DoclistPrev(
- bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll,
- &pIter, &iDocid, &dummy, &bEof
- );
- }
- }
- pPh->pOrPoslist = pIter;
- pPh->iOrDocid = iDocid;
- if( bEof || iDocid!=pCsr->iPrevId ) bMatch = 0;
- }
-
- if( bMatch ){
- pIter = pPhrase->pOrPoslist;
- }else{
- pIter = 0;
- }
- }
- if( pIter==0 ) return SQLITE_OK;
-
- if( *pIter==0x01 ){
- pIter++;
- pIter += fts3GetVarint32(pIter, &iThis);
- }else{
- iThis = 0;
- }
- while( iThis<iCol ){
- fts3ColumnlistCopy(0, &pIter);
- if( *pIter==0x00 ) return SQLITE_OK;
- pIter++;
- pIter += fts3GetVarint32(pIter, &iThis);
- }
- if( *pIter==0x00 ){
- pIter = 0;
- }
-
- *ppOut = ((iCol==iThis)?pIter:0);
- return SQLITE_OK;
-}
-
-/*
-** Free all components of the Fts3Phrase structure that were allocated by
-** the eval module. Specifically, this means to free:
-**
-** * the contents of pPhrase->doclist, and
-** * any Fts3MultiSegReader objects held by phrase tokens.
-*/
-void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
- if( pPhrase ){
- int i;
- sqlite3_free(pPhrase->doclist.aAll);
- fts3EvalInvalidatePoslist(pPhrase);
- memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
- for(i=0; i<pPhrase->nToken; i++){
- fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
- pPhrase->aToken[i].pSegcsr = 0;
- }
- }
-}
-
-
-/*
-** Return SQLITE_CORRUPT_VTAB.
-*/
-#ifdef SQLITE_DEBUG
-int sqlite3Fts3Corrupt(){
- return SQLITE_CORRUPT_VTAB;
-}
-#endif
-
-#if !SQLITE_CORE
-/*
-** Initialize API pointer table, if required.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fts3_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi)
- return sqlite3Fts3Init(db);
-}
-#endif
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3.h
deleted file mode 100644
index c1aa8caf092..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-** 2006 Oct 10
-**
-** 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 header file is used by programs that want to link against the
-** FTS3 library. All it does is declare the sqlite3Fts3Init() interface.
-*/
-#include "sqlite3.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int sqlite3Fts3Init(sqlite3 *db);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3Int.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3Int.h
deleted file mode 100644
index 077bad7f54c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3Int.h
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
-** 2009 Nov 12
-**
-** 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.
-**
-******************************************************************************
-**
-*/
-#ifndef _FTSINT_H
-#define _FTSINT_H
-
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
-# define NDEBUG 1
-#endif
-
-/* FTS3/FTS4 require virtual tables */
-#ifdef SQLITE_OMIT_VIRTUALTABLE
-# undef SQLITE_ENABLE_FTS3
-# undef SQLITE_ENABLE_FTS4
-#endif
-
-/*
-** FTS4 is really an extension for FTS3. It is enabled using the
-** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
-** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
-*/
-#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
-# define SQLITE_ENABLE_FTS3
-#endif
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-/* If not building as part of the core, include sqlite3ext.h. */
-#ifndef SQLITE_CORE
-# include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT3
-#endif
-
-#include "sqlite3.h"
-#include "fts3_tokenizer.h"
-#include "fts3_hash.h"
-
-/*
-** This constant determines the maximum depth of an FTS expression tree
-** that the library will create and use. FTS uses recursion to perform
-** various operations on the query tree, so the disadvantage of a large
-** limit is that it may allow very large queries to use large amounts
-** of stack space (perhaps causing a stack overflow).
-*/
-#ifndef SQLITE_FTS3_MAX_EXPR_DEPTH
-# define SQLITE_FTS3_MAX_EXPR_DEPTH 12
-#endif
-
-
-/*
-** This constant controls how often segments are merged. Once there are
-** FTS3_MERGE_COUNT segments of level N, they are merged into a single
-** segment of level N+1.
-*/
-#define FTS3_MERGE_COUNT 16
-
-/*
-** This is the maximum amount of data (in bytes) to store in the
-** Fts3Table.pendingTerms hash table. Normally, the hash table is
-** populated as documents are inserted/updated/deleted in a transaction
-** and used to create a new segment when the transaction is committed.
-** However if this limit is reached midway through a transaction, a new
-** segment is created and the hash table cleared immediately.
-*/
-#define FTS3_MAX_PENDING_DATA (1*1024*1024)
-
-/*
-** Macro to return the number of elements in an array. SQLite has a
-** similar macro called ArraySize(). Use a different name to avoid
-** a collision when building an amalgamation with built-in FTS3.
-*/
-#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0])))
-
-
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-#ifndef MAX
-# define MAX(x,y) ((x)>(y)?(x):(y))
-#endif
-
-/*
-** Maximum length of a varint encoded integer. The varint format is different
-** from that used by SQLite, so the maximum length is 10, not 9.
-*/
-#define FTS3_VARINT_MAX 10
-
-/*
-** FTS4 virtual tables may maintain multiple indexes - one index of all terms
-** in the document set and zero or more prefix indexes. All indexes are stored
-** as one or more b+-trees in the %_segments and %_segdir tables.
-**
-** It is possible to determine which index a b+-tree belongs to based on the
-** value stored in the "%_segdir.level" column. Given this value L, the index
-** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with
-** level values between 0 and 1023 (inclusive) belong to index 0, all levels
-** between 1024 and 2047 to index 1, and so on.
-**
-** It is considered impossible for an index to use more than 1024 levels. In
-** theory though this may happen, but only after at least
-** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables.
-*/
-#define FTS3_SEGDIR_MAXLEVEL 1024
-#define FTS3_SEGDIR_MAXLEVEL_STR "1024"
-
-/*
-** The testcase() macro is only used by the amalgamation. If undefined,
-** make it a no-op.
-*/
-#ifndef testcase
-# define testcase(X)
-#endif
-
-/*
-** Terminator values for position-lists and column-lists.
-*/
-#define POS_COLUMN (1) /* Column-list terminator */
-#define POS_END (0) /* Position-list terminator */
-
-/*
-** This section provides definitions to allow the
-** FTS3 extension to be compiled outside of the
-** amalgamation.
-*/
-#ifndef SQLITE_AMALGAMATION
-/*
-** Macros indicating that conditional expressions are always true or
-** false.
-*/
-#ifdef SQLITE_COVERAGE_TEST
-# define ALWAYS(x) (1)
-# define NEVER(X) (0)
-#elif defined(SQLITE_DEBUG)
-# define ALWAYS(x) sqlite3Fts3Always((x)!=0)
-# define NEVER(x) sqlite3Fts3Never((x)!=0)
-int sqlite3Fts3Always(int b);
-int sqlite3Fts3Never(int b);
-#else
-# define ALWAYS(x) (x)
-# define NEVER(x) (x)
-#endif
-
-/*
-** Internal types used by SQLite.
-*/
-typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
-typedef short int i16; /* 2-byte (or larger) signed integer */
-typedef unsigned int u32; /* 4-byte unsigned integer */
-typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */
-typedef sqlite3_int64 i64; /* 8-byte signed integer */
-
-/*
-** Macro used to suppress compiler warnings for unused parameters.
-*/
-#define UNUSED_PARAMETER(x) (void)(x)
-
-/*
-** Activate assert() only if SQLITE_TEST is enabled.
-*/
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
-# define NDEBUG 1
-#endif
-
-/*
-** The TESTONLY macro is used to enclose variable declarations or
-** other bits of code that are needed to support the arguments
-** within testcase() and assert() macros.
-*/
-#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
-# define TESTONLY(X) X
-#else
-# define TESTONLY(X)
-#endif
-
-#endif /* SQLITE_AMALGAMATION */
-
-#ifdef SQLITE_DEBUG
-int sqlite3Fts3Corrupt(void);
-# define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt()
-#else
-# define FTS_CORRUPT_VTAB SQLITE_CORRUPT_VTAB
-#endif
-
-typedef struct Fts3Table Fts3Table;
-typedef struct Fts3Cursor Fts3Cursor;
-typedef struct Fts3Expr Fts3Expr;
-typedef struct Fts3Phrase Fts3Phrase;
-typedef struct Fts3PhraseToken Fts3PhraseToken;
-
-typedef struct Fts3Doclist Fts3Doclist;
-typedef struct Fts3SegFilter Fts3SegFilter;
-typedef struct Fts3DeferredToken Fts3DeferredToken;
-typedef struct Fts3SegReader Fts3SegReader;
-typedef struct Fts3MultiSegReader Fts3MultiSegReader;
-
-typedef struct MatchinfoBuffer MatchinfoBuffer;
-
-/*
-** A connection to a fulltext index is an instance of the following
-** structure. The xCreate and xConnect methods create an instance
-** of this structure and xDestroy and xDisconnect free that instance.
-** All other methods receive a pointer to the structure as one of their
-** arguments.
-*/
-struct Fts3Table {
- sqlite3_vtab base; /* Base class used by SQLite core */
- sqlite3 *db; /* The database connection */
- const char *zDb; /* logical database name */
- const char *zName; /* virtual table name */
- int nColumn; /* number of named columns in virtual table */
- char **azColumn; /* column names. malloced */
- u8 *abNotindexed; /* True for 'notindexed' columns */
- sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
- char *zContentTbl; /* content=xxx option, or NULL */
- char *zLanguageid; /* languageid=xxx option, or NULL */
- int nAutoincrmerge; /* Value configured by 'automerge' */
- u32 nLeafAdd; /* Number of leaf blocks added this trans */
-
- /* Precompiled statements used by the implementation. Each of these
- ** statements is run and reset within a single virtual table API call.
- */
- sqlite3_stmt *aStmt[40];
- sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */
-
- char *zReadExprlist;
- char *zWriteExprlist;
-
- int nNodeSize; /* Soft limit for node size */
- u8 bFts4; /* True for FTS4, false for FTS3 */
- u8 bHasStat; /* True if %_stat table exists (2==unknown) */
- u8 bHasDocsize; /* True if %_docsize table exists */
- u8 bDescIdx; /* True if doclists are in reverse order */
- u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */
- int nPgsz; /* Page size for host database */
- char *zSegmentsTbl; /* Name of %_segments table */
- sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
-
- /*
- ** The following array of hash tables is used to buffer pending index
- ** updates during transactions. All pending updates buffered at any one
- ** time must share a common language-id (see the FTS4 langid= feature).
- ** The current language id is stored in variable iPrevLangid.
- **
- ** A single FTS4 table may have multiple full-text indexes. For each index
- ** there is an entry in the aIndex[] array. Index 0 is an index of all the
- ** terms that appear in the document set. Each subsequent index in aIndex[]
- ** is an index of prefixes of a specific length.
- **
- ** Variable nPendingData contains an estimate the memory consumed by the
- ** pending data structures, including hash table overhead, but not including
- ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash
- ** tables are flushed to disk. Variable iPrevDocid is the docid of the most
- ** recently inserted record.
- */
- int nIndex; /* Size of aIndex[] */
- struct Fts3Index {
- int nPrefix; /* Prefix length (0 for main terms index) */
- Fts3Hash hPending; /* Pending terms table for this index */
- } *aIndex;
- int nMaxPendingData; /* Max pending data before flush to disk */
- int nPendingData; /* Current bytes of pending data */
- sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
- int iPrevLangid; /* Langid of recently inserted document */
- int bPrevDelete; /* True if last operation was a delete */
-
-#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
- /* State variables used for validating that the transaction control
- ** methods of the virtual table are called at appropriate times. These
- ** values do not contribute to FTS functionality; they are used for
- ** verifying the operation of the SQLite core.
- */
- int inTransaction; /* True after xBegin but before xCommit/xRollback */
- int mxSavepoint; /* Largest valid xSavepoint integer */
-#endif
-
-#ifdef SQLITE_TEST
- /* True to disable the incremental doclist optimization. This is controled
- ** by special insert command 'test-no-incr-doclist'. */
- int bNoIncrDoclist;
-#endif
-};
-
-/*
-** When the core wants to read from the virtual table, it creates a
-** virtual table cursor (an instance of the following structure) using
-** the xOpen method. Cursors are destroyed using the xClose method.
-*/
-struct Fts3Cursor {
- sqlite3_vtab_cursor base; /* Base class used by SQLite core */
- i16 eSearch; /* Search strategy (see below) */
- u8 isEof; /* True if at End Of Results */
- u8 isRequireSeek; /* True if must seek pStmt to %_content row */
- u8 bSeekStmt; /* True if pStmt is a seek */
- sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
- Fts3Expr *pExpr; /* Parsed MATCH query string */
- int iLangid; /* Language being queried for */
- int nPhrase; /* Number of matchable phrases in query */
- Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
- sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
- char *pNextId; /* Pointer into the body of aDoclist */
- char *aDoclist; /* List of docids for full-text queries */
- int nDoclist; /* Size of buffer at aDoclist */
- u8 bDesc; /* True to sort in descending order */
- int eEvalmode; /* An FTS3_EVAL_XX constant */
- int nRowAvg; /* Average size of database rows, in pages */
- sqlite3_int64 nDoc; /* Documents in table */
- i64 iMinDocid; /* Minimum docid to return */
- i64 iMaxDocid; /* Maximum docid to return */
- int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
- MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */
-};
-
-#define FTS3_EVAL_FILTER 0
-#define FTS3_EVAL_NEXT 1
-#define FTS3_EVAL_MATCHINFO 2
-
-/*
-** The Fts3Cursor.eSearch member is always set to one of the following.
-** Actualy, Fts3Cursor.eSearch can be greater than or equal to
-** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
-** of the column to be searched. For example, in
-**
-** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
-** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
-**
-** Because the LHS of the MATCH operator is 2nd column "b",
-** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a,
-** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1"
-** indicating that all columns should be searched,
-** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4.
-*/
-#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
-#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
-#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
-
-/*
-** The lower 16-bits of the sqlite3_index_info.idxNum value set by
-** the xBestIndex() method contains the Fts3Cursor.eSearch value described
-** above. The upper 16-bits contain a combination of the following
-** bits, used to describe extra constraints on full-text searches.
-*/
-#define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */
-#define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */
-#define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */
-
-struct Fts3Doclist {
- char *aAll; /* Array containing doclist (or NULL) */
- int nAll; /* Size of a[] in bytes */
- char *pNextDocid; /* Pointer to next docid */
-
- sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
- int bFreeList; /* True if pList should be sqlite3_free()d */
- char *pList; /* Pointer to position list following iDocid */
- int nList; /* Length of position list */
-};
-
-/*
-** A "phrase" is a sequence of one or more tokens that must match in
-** sequence. A single token is the base case and the most common case.
-** For a sequence of tokens contained in double-quotes (i.e. "one two three")
-** nToken will be the number of tokens in the string.
-*/
-struct Fts3PhraseToken {
- char *z; /* Text of the token */
- int n; /* Number of bytes in buffer z */
- int isPrefix; /* True if token ends with a "*" character */
- int bFirst; /* True if token must appear at position 0 */
-
- /* Variables above this point are populated when the expression is
- ** parsed (by code in fts3_expr.c). Below this point the variables are
- ** used when evaluating the expression. */
- Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
- Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */
-};
-
-struct Fts3Phrase {
- /* Cache of doclist for this phrase. */
- Fts3Doclist doclist;
- int bIncr; /* True if doclist is loaded incrementally */
- int iDoclistToken;
-
- /* Used by sqlite3Fts3EvalPhrasePoslist() if this is a descendent of an
- ** OR condition. */
- char *pOrPoslist;
- i64 iOrDocid;
-
- /* Variables below this point are populated by fts3_expr.c when parsing
- ** a MATCH expression. Everything above is part of the evaluation phase.
- */
- int nToken; /* Number of tokens in the phrase */
- int iColumn; /* Index of column this phrase must match */
- Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
-};
-
-/*
-** A tree of these objects forms the RHS of a MATCH operator.
-**
-** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
-** points to a malloced buffer, size nDoclist bytes, containing the results
-** of this phrase query in FTS3 doclist format. As usual, the initial
-** "Length" field found in doclists stored on disk is omitted from this
-** buffer.
-**
-** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global
-** matchinfo data. If it is not NULL, it points to an array of size nCol*3,
-** where nCol is the number of columns in the queried FTS table. The array
-** is populated as follows:
-**
-** aMI[iCol*3 + 0] = Undefined
-** aMI[iCol*3 + 1] = Number of occurrences
-** aMI[iCol*3 + 2] = Number of rows containing at least one instance
-**
-** The aMI array is allocated using sqlite3_malloc(). It should be freed
-** when the expression node is.
-*/
-struct Fts3Expr {
- int eType; /* One of the FTSQUERY_XXX values defined below */
- int nNear; /* Valid if eType==FTSQUERY_NEAR */
- Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */
- Fts3Expr *pLeft; /* Left operand */
- Fts3Expr *pRight; /* Right operand */
- Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
-
- /* The following are used by the fts3_eval.c module. */
- sqlite3_int64 iDocid; /* Current docid */
- u8 bEof; /* True this expression is at EOF already */
- u8 bStart; /* True if iDocid is valid */
- u8 bDeferred; /* True if this expression is entirely deferred */
-
- /* The following are used by the fts3_snippet.c module. */
- int iPhrase; /* Index of this phrase in matchinfo() results */
- u32 *aMI; /* See above */
-};
-
-/*
-** Candidate values for Fts3Query.eType. Note that the order of the first
-** four values is in order of precedence when parsing expressions. For
-** example, the following:
-**
-** "a OR b AND c NOT d NEAR e"
-**
-** is equivalent to:
-**
-** "a OR (b AND (c NOT (d NEAR e)))"
-*/
-#define FTSQUERY_NEAR 1
-#define FTSQUERY_NOT 2
-#define FTSQUERY_AND 3
-#define FTSQUERY_OR 4
-#define FTSQUERY_PHRASE 5
-
-
-/* fts3_write.c */
-int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
-int sqlite3Fts3PendingTermsFlush(Fts3Table *);
-void sqlite3Fts3PendingTermsClear(Fts3Table *);
-int sqlite3Fts3Optimize(Fts3Table *);
-int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
- sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
-int sqlite3Fts3SegReaderPending(
- Fts3Table*,int,const char*,int,int,Fts3SegReader**);
-void sqlite3Fts3SegReaderFree(Fts3SegReader *);
-int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **);
-int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
-
-int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
-int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
-
-#ifndef SQLITE_DISABLE_FTS4_DEFERRED
-void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
-int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
-int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
-void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
-int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
-#else
-# define sqlite3Fts3FreeDeferredTokens(x)
-# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK
-# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK
-# define sqlite3Fts3FreeDeferredDoclists(x)
-# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK
-#endif
-
-void sqlite3Fts3SegmentsClose(Fts3Table *);
-int sqlite3Fts3MaxLevel(Fts3Table *, int *);
-
-/* Special values interpreted by sqlite3SegReaderCursor() */
-#define FTS3_SEGCURSOR_PENDING -1
-#define FTS3_SEGCURSOR_ALL -2
-
-int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*);
-int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
-void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);
-
-int sqlite3Fts3SegReaderCursor(Fts3Table *,
- int, int, int, const char *, int, int, int, Fts3MultiSegReader *);
-
-/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
-#define FTS3_SEGMENT_REQUIRE_POS 0x00000001
-#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
-#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
-#define FTS3_SEGMENT_PREFIX 0x00000008
-#define FTS3_SEGMENT_SCAN 0x00000010
-#define FTS3_SEGMENT_FIRST 0x00000020
-
-/* Type passed as 4th argument to SegmentReaderIterate() */
-struct Fts3SegFilter {
- const char *zTerm;
- int nTerm;
- int iCol;
- int flags;
-};
-
-struct Fts3MultiSegReader {
- /* Used internally by sqlite3Fts3SegReaderXXX() calls */
- Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */
- int nSegment; /* Size of apSegment array */
- int nAdvance; /* How many seg-readers to advance */
- Fts3SegFilter *pFilter; /* Pointer to filter object */
- char *aBuffer; /* Buffer to merge doclists in */
- int nBuffer; /* Allocated size of aBuffer[] in bytes */
-
- int iColFilter; /* If >=0, filter for this column */
- int bRestart;
-
- /* Used by fts3.c only. */
- int nCost; /* Cost of running iterator */
- int bLookup; /* True if a lookup of a single entry. */
-
- /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */
- char *zTerm; /* Pointer to term buffer */
- int nTerm; /* Size of zTerm in bytes */
- char *aDoclist; /* Pointer to doclist buffer */
- int nDoclist; /* Size of aDoclist[] in bytes */
-};
-
-int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
-
-#define fts3GetVarint32(p, piVal) ( \
- (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
-)
-
-/* fts3.c */
-void sqlite3Fts3ErrMsg(char**,const char*,...);
-int sqlite3Fts3PutVarint(char *, sqlite3_int64);
-int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
-int sqlite3Fts3GetVarint32(const char *, int *);
-int sqlite3Fts3VarintLen(sqlite3_uint64);
-void sqlite3Fts3Dequote(char *);
-void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
-int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
-int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
-void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
-int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
-
-/* fts3_tokenizer.c */
-const char *sqlite3Fts3NextToken(const char *, int *);
-int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
-int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
- sqlite3_tokenizer **, char **
-);
-int sqlite3Fts3IsIdChar(char);
-
-/* fts3_snippet.c */
-void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*);
-void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
- const char *, const char *, int, int
-);
-void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
-void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p);
-
-/* fts3_expr.c */
-int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
- char **, int, int, int, const char *, int, Fts3Expr **, char **
-);
-void sqlite3Fts3ExprFree(Fts3Expr *);
-#ifdef SQLITE_TEST
-int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*);
-int sqlite3Fts3InitTerm(sqlite3 *db);
-#endif
-
-int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int,
- sqlite3_tokenizer_cursor **
-);
-
-/* fts3_aux.c */
-int sqlite3Fts3InitAux(sqlite3 *db);
-
-void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
-
-int sqlite3Fts3MsrIncrStart(
- Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
-int sqlite3Fts3MsrIncrNext(
- Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
-int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
-int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
-int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
-
-/* fts3_tokenize_vtab.c */
-int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
-
-/* fts3_unicode2.c (functions generated by parsing unicode text files) */
-#ifndef SQLITE_DISABLE_FTS3_UNICODE
-int sqlite3FtsUnicodeFold(int, int);
-int sqlite3FtsUnicodeIsalnum(int);
-int sqlite3FtsUnicodeIsdiacritic(int);
-#endif
-
-#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
-#endif /* _FTSINT_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_aux.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_aux.c
deleted file mode 100644
index f85a48ae020..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_aux.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
-** 2011 Jan 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.
-**
-******************************************************************************
-**
-*/
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <string.h>
-#include <assert.h>
-
-typedef struct Fts3auxTable Fts3auxTable;
-typedef struct Fts3auxCursor Fts3auxCursor;
-
-struct Fts3auxTable {
- sqlite3_vtab base; /* Base class used by SQLite core */
- Fts3Table *pFts3Tab;
-};
-
-struct Fts3auxCursor {
- sqlite3_vtab_cursor base; /* Base class used by SQLite core */
- Fts3MultiSegReader csr; /* Must be right after "base" */
- Fts3SegFilter filter;
- char *zStop;
- int nStop; /* Byte-length of string zStop */
- int iLangid; /* Language id to query */
- int isEof; /* True if cursor is at EOF */
- sqlite3_int64 iRowid; /* Current rowid */
-
- int iCol; /* Current value of 'col' column */
- int nStat; /* Size of aStat[] array */
- struct Fts3auxColstats {
- sqlite3_int64 nDoc; /* 'documents' values for current csr row */
- sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */
- } *aStat;
-};
-
-/*
-** Schema of the terms table.
-*/
-#define FTS3_AUX_SCHEMA \
- "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)"
-
-/*
-** This function does all the work for both the xConnect and xCreate methods.
-** These tables have no persistent representation of their own, so xConnect
-** and xCreate are identical operations.
-*/
-static int fts3auxConnectMethod(
- sqlite3 *db, /* Database connection */
- void *pUnused, /* Unused */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- char const *zDb; /* Name of database (e.g. "main") */
- char const *zFts3; /* Name of fts3 table */
- int nDb; /* Result of strlen(zDb) */
- int nFts3; /* Result of strlen(zFts3) */
- int nByte; /* Bytes of space to allocate here */
- int rc; /* value returned by declare_vtab() */
- Fts3auxTable *p; /* Virtual table object to return */
-
- UNUSED_PARAMETER(pUnused);
-
- /* The user should invoke this in one of two forms:
- **
- ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table);
- ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table);
- */
- if( argc!=4 && argc!=5 ) goto bad_args;
-
- zDb = argv[1];
- nDb = (int)strlen(zDb);
- if( argc==5 ){
- if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){
- zDb = argv[3];
- nDb = (int)strlen(zDb);
- zFts3 = argv[4];
- }else{
- goto bad_args;
- }
- }else{
- zFts3 = argv[3];
- }
- nFts3 = (int)strlen(zFts3);
-
- rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA);
- if( rc!=SQLITE_OK ) return rc;
-
- nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
- p = (Fts3auxTable *)sqlite3_malloc(nByte);
- if( !p ) return SQLITE_NOMEM;
- memset(p, 0, nByte);
-
- p->pFts3Tab = (Fts3Table *)&p[1];
- p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
- p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
- p->pFts3Tab->db = db;
- p->pFts3Tab->nIndex = 1;
-
- memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
- memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
- sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);
-
- *ppVtab = (sqlite3_vtab *)p;
- return SQLITE_OK;
-
- bad_args:
- sqlite3Fts3ErrMsg(pzErr, "invalid arguments to fts4aux constructor");
- return SQLITE_ERROR;
-}
-
-/*
-** This function does the work for both the xDisconnect and xDestroy methods.
-** These tables have no persistent representation of their own, so xDisconnect
-** and xDestroy are identical operations.
-*/
-static int fts3auxDisconnectMethod(sqlite3_vtab *pVtab){
- Fts3auxTable *p = (Fts3auxTable *)pVtab;
- Fts3Table *pFts3 = p->pFts3Tab;
- int i;
-
- /* Free any prepared statements held */
- for(i=0; i<SizeofArray(pFts3->aStmt); i++){
- sqlite3_finalize(pFts3->aStmt[i]);
- }
- sqlite3_free(pFts3->zSegmentsTbl);
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-#define FTS4AUX_EQ_CONSTRAINT 1
-#define FTS4AUX_GE_CONSTRAINT 2
-#define FTS4AUX_LE_CONSTRAINT 4
-
-/*
-** xBestIndex - Analyze a WHERE and ORDER BY clause.
-*/
-static int fts3auxBestIndexMethod(
- sqlite3_vtab *pVTab,
- sqlite3_index_info *pInfo
-){
- int i;
- int iEq = -1;
- int iGe = -1;
- int iLe = -1;
- int iLangid = -1;
- int iNext = 1; /* Next free argvIndex value */
-
- UNUSED_PARAMETER(pVTab);
-
- /* This vtab delivers always results in "ORDER BY term ASC" order. */
- if( pInfo->nOrderBy==1
- && pInfo->aOrderBy[0].iColumn==0
- && pInfo->aOrderBy[0].desc==0
- ){
- pInfo->orderByConsumed = 1;
- }
-
- /* Search for equality and range constraints on the "term" column.
- ** And equality constraints on the hidden "languageid" column. */
- for(i=0; i<pInfo->nConstraint; i++){
- if( pInfo->aConstraint[i].usable ){
- int op = pInfo->aConstraint[i].op;
- int iCol = pInfo->aConstraint[i].iColumn;
-
- if( iCol==0 ){
- if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
- if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
- if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
- if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
- if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
- }
- if( iCol==4 ){
- if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i;
- }
- }
- }
-
- if( iEq>=0 ){
- pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
- pInfo->aConstraintUsage[iEq].argvIndex = iNext++;
- pInfo->estimatedCost = 5;
- }else{
- pInfo->idxNum = 0;
- pInfo->estimatedCost = 20000;
- if( iGe>=0 ){
- pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
- pInfo->aConstraintUsage[iGe].argvIndex = iNext++;
- pInfo->estimatedCost /= 2;
- }
- if( iLe>=0 ){
- pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
- pInfo->aConstraintUsage[iLe].argvIndex = iNext++;
- pInfo->estimatedCost /= 2;
- }
- }
- if( iLangid>=0 ){
- pInfo->aConstraintUsage[iLangid].argvIndex = iNext++;
- pInfo->estimatedCost--;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** xOpen - Open a cursor.
-*/
-static int fts3auxOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
- Fts3auxCursor *pCsr; /* Pointer to cursor object to return */
-
- UNUSED_PARAMETER(pVTab);
-
- pCsr = (Fts3auxCursor *)sqlite3_malloc(sizeof(Fts3auxCursor));
- if( !pCsr ) return SQLITE_NOMEM;
- memset(pCsr, 0, sizeof(Fts3auxCursor));
-
- *ppCsr = (sqlite3_vtab_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** xClose - Close a cursor.
-*/
-static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){
- Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
- Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
-
- sqlite3Fts3SegmentsClose(pFts3);
- sqlite3Fts3SegReaderFinish(&pCsr->csr);
- sqlite3_free((void *)pCsr->filter.zTerm);
- sqlite3_free(pCsr->zStop);
- sqlite3_free(pCsr->aStat);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
- if( nSize>pCsr->nStat ){
- struct Fts3auxColstats *aNew;
- aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
- sizeof(struct Fts3auxColstats) * nSize
- );
- if( aNew==0 ) return SQLITE_NOMEM;
- memset(&aNew[pCsr->nStat], 0,
- sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat)
- );
- pCsr->aStat = aNew;
- pCsr->nStat = nSize;
- }
- return SQLITE_OK;
-}
-
-/*
-** xNext - Advance the cursor to the next row, if any.
-*/
-static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
- Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
- Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
- int rc;
-
- /* Increment our pretend rowid value. */
- pCsr->iRowid++;
-
- for(pCsr->iCol++; pCsr->iCol<pCsr->nStat; pCsr->iCol++){
- if( pCsr->aStat[pCsr->iCol].nDoc>0 ) return SQLITE_OK;
- }
-
- rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr);
- if( rc==SQLITE_ROW ){
- int i = 0;
- int nDoclist = pCsr->csr.nDoclist;
- char *aDoclist = pCsr->csr.aDoclist;
- int iCol;
-
- int eState = 0;
-
- if( pCsr->zStop ){
- int n = (pCsr->nStop<pCsr->csr.nTerm) ? pCsr->nStop : pCsr->csr.nTerm;
- int mc = memcmp(pCsr->zStop, pCsr->csr.zTerm, n);
- if( mc<0 || (mc==0 && pCsr->csr.nTerm>pCsr->nStop) ){
- pCsr->isEof = 1;
- return SQLITE_OK;
- }
- }
-
- if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
- memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
- iCol = 0;
-
- while( i<nDoclist ){
- sqlite3_int64 v = 0;
-
- i += sqlite3Fts3GetVarint(&aDoclist[i], &v);
- switch( eState ){
- /* State 0. In this state the integer just read was a docid. */
- case 0:
- pCsr->aStat[0].nDoc++;
- eState = 1;
- iCol = 0;
- break;
-
- /* State 1. In this state we are expecting either a 1, indicating
- ** that the following integer will be a column number, or the
- ** start of a position list for column 0.
- **
- ** The only difference between state 1 and state 2 is that if the
- ** integer encountered in state 1 is not 0 or 1, then we need to
- ** increment the column 0 "nDoc" count for this term.
- */
- case 1:
- assert( iCol==0 );
- if( v>1 ){
- pCsr->aStat[1].nDoc++;
- }
- eState = 2;
- /* fall through */
-
- case 2:
- if( v==0 ){ /* 0x00. Next integer will be a docid. */
- eState = 0;
- }else if( v==1 ){ /* 0x01. Next integer will be a column number. */
- eState = 3;
- }else{ /* 2 or greater. A position. */
- pCsr->aStat[iCol+1].nOcc++;
- pCsr->aStat[0].nOcc++;
- }
- break;
-
- /* State 3. The integer just read is a column number. */
- default: assert( eState==3 );
- iCol = (int)v;
- if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
- pCsr->aStat[iCol+1].nDoc++;
- eState = 2;
- break;
- }
- }
-
- pCsr->iCol = 0;
- rc = SQLITE_OK;
- }else{
- pCsr->isEof = 1;
- }
- return rc;
-}
-
-/*
-** xFilter - Initialize a cursor to point at the start of its data.
-*/
-static int fts3auxFilterMethod(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, /* Strategy index */
- const char *idxStr, /* Unused */
- int nVal, /* Number of elements in apVal */
- sqlite3_value **apVal /* Arguments for the indexing scheme */
-){
- Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
- Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
- int rc;
- int isScan = 0;
- int iLangVal = 0; /* Language id to query */
-
- int iEq = -1; /* Index of term=? value in apVal */
- int iGe = -1; /* Index of term>=? value in apVal */
- int iLe = -1; /* Index of term<=? value in apVal */
- int iLangid = -1; /* Index of languageid=? value in apVal */
- int iNext = 0;
-
- UNUSED_PARAMETER(nVal);
- UNUSED_PARAMETER(idxStr);
-
- assert( idxStr==0 );
- assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0
- || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
- || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
- );
-
- if( idxNum==FTS4AUX_EQ_CONSTRAINT ){
- iEq = iNext++;
- }else{
- isScan = 1;
- if( idxNum & FTS4AUX_GE_CONSTRAINT ){
- iGe = iNext++;
- }
- if( idxNum & FTS4AUX_LE_CONSTRAINT ){
- iLe = iNext++;
- }
- }
- if( iNext<nVal ){
- iLangid = iNext++;
- }
-
- /* In case this cursor is being reused, close and zero it. */
- testcase(pCsr->filter.zTerm);
- sqlite3Fts3SegReaderFinish(&pCsr->csr);
- sqlite3_free((void *)pCsr->filter.zTerm);
- sqlite3_free(pCsr->aStat);
- memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
-
- pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
- if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
-
- if( iEq>=0 || iGe>=0 ){
- const unsigned char *zStr = sqlite3_value_text(apVal[0]);
- assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
- if( zStr ){
- pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
- pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
- if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
- }
- }
-
- if( iLe>=0 ){
- pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
- pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
- if( pCsr->zStop==0 ) return SQLITE_NOMEM;
- }
-
- if( iLangid>=0 ){
- iLangVal = sqlite3_value_int(apVal[iLangid]);
-
- /* If the user specified a negative value for the languageid, use zero
- ** instead. This works, as the "languageid=?" constraint will also
- ** be tested by the VDBE layer. The test will always be false (since
- ** this module will not return a row with a negative languageid), and
- ** so the overall query will return zero rows. */
- if( iLangVal<0 ) iLangVal = 0;
- }
- pCsr->iLangid = iLangVal;
-
- rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL,
- pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
- }
-
- if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor);
- return rc;
-}
-
-/*
-** xEof - Return true if the cursor is at EOF, or false otherwise.
-*/
-static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){
- Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
- return pCsr->isEof;
-}
-
-/*
-** xColumn - Return a column value.
-*/
-static int fts3auxColumnMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
- int iCol /* Index of column to read value from */
-){
- Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
-
- assert( p->isEof==0 );
- switch( iCol ){
- case 0: /* term */
- sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
- break;
-
- case 1: /* col */
- if( p->iCol ){
- sqlite3_result_int(pCtx, p->iCol-1);
- }else{
- sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC);
- }
- break;
-
- case 2: /* documents */
- sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc);
- break;
-
- case 3: /* occurrences */
- sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc);
- break;
-
- default: /* languageid */
- assert( iCol==4 );
- sqlite3_result_int(pCtx, p->iLangid);
- break;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** xRowid - Return the current rowid for the cursor.
-*/
-static int fts3auxRowidMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite_int64 *pRowid /* OUT: Rowid value */
-){
- Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
- *pRowid = pCsr->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Register the fts3aux module with database connection db. Return SQLITE_OK
-** if successful or an error code if sqlite3_create_module() fails.
-*/
-int sqlite3Fts3InitAux(sqlite3 *db){
- static const sqlite3_module fts3aux_module = {
- 0, /* iVersion */
- fts3auxConnectMethod, /* xCreate */
- fts3auxConnectMethod, /* xConnect */
- fts3auxBestIndexMethod, /* xBestIndex */
- fts3auxDisconnectMethod, /* xDisconnect */
- fts3auxDisconnectMethod, /* xDestroy */
- fts3auxOpenMethod, /* xOpen */
- fts3auxCloseMethod, /* xClose */
- fts3auxFilterMethod, /* xFilter */
- fts3auxNextMethod, /* xNext */
- fts3auxEofMethod, /* xEof */
- fts3auxColumnMethod, /* xColumn */
- fts3auxRowidMethod, /* xRowid */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindFunction */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
- };
- int rc; /* Return code */
-
- rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0);
- return rc;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_expr.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_expr.c
deleted file mode 100644
index 9f42b44a71b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_expr.c
+++ /dev/null
@@ -1,1292 +0,0 @@
-/*
-** 2008 Nov 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 module contains code that implements a parser for fts3 query strings
-** (the right-hand argument to the MATCH operator). Because the supported
-** syntax is relatively simple, the whole tokenizer/parser system is
-** hand-coded.
-*/
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-/*
-** By default, this module parses the legacy syntax that has been
-** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS
-** is defined, then it uses the new syntax. The differences between
-** the new and the old syntaxes are:
-**
-** a) The new syntax supports parenthesis. The old does not.
-**
-** b) The new syntax supports the AND and NOT operators. The old does not.
-**
-** c) The old syntax supports the "-" token qualifier. This is not
-** supported by the new syntax (it is replaced by the NOT operator).
-**
-** d) When using the old syntax, the OR operator has a greater precedence
-** than an implicit AND. When using the new, both implicity and explicit
-** AND operators have a higher precedence than OR.
-**
-** If compiled with SQLITE_TEST defined, then this module exports the
-** symbol "int sqlite3_fts3_enable_parentheses". Setting this variable
-** to zero causes the module to use the old syntax. If it is set to
-** non-zero the new syntax is activated. This is so both syntaxes can
-** be tested using a single build of testfixture.
-**
-** The following describes the syntax supported by the fts3 MATCH
-** operator in a similar format to that used by the lemon parser
-** generator. This module does not use actually lemon, it uses a
-** custom parser.
-**
-** query ::= andexpr (OR andexpr)*.
-**
-** andexpr ::= notexpr (AND? notexpr)*.
-**
-** notexpr ::= nearexpr (NOT nearexpr|-TOKEN)*.
-** notexpr ::= LP query RP.
-**
-** nearexpr ::= phrase (NEAR distance_opt nearexpr)*.
-**
-** distance_opt ::= .
-** distance_opt ::= / INTEGER.
-**
-** phrase ::= TOKEN.
-** phrase ::= COLUMN:TOKEN.
-** phrase ::= "TOKEN TOKEN TOKEN...".
-*/
-
-#ifdef SQLITE_TEST
-int sqlite3_fts3_enable_parentheses = 0;
-#else
-# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
-# define sqlite3_fts3_enable_parentheses 1
-# else
-# define sqlite3_fts3_enable_parentheses 0
-# endif
-#endif
-
-/*
-** Default span for NEAR operators.
-*/
-#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
-
-#include <string.h>
-#include <assert.h>
-
-/*
-** isNot:
-** This variable is used by function getNextNode(). When getNextNode() is
-** called, it sets ParseContext.isNot to true if the 'next node' is a
-** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
-** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to
-** zero.
-*/
-typedef struct ParseContext ParseContext;
-struct ParseContext {
- sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
- int iLangid; /* Language id used with tokenizer */
- const char **azCol; /* Array of column names for fts3 table */
- int bFts4; /* True to allow FTS4-only syntax */
- int nCol; /* Number of entries in azCol[] */
- int iDefaultCol; /* Default column to query */
- int isNot; /* True if getNextNode() sees a unary - */
- sqlite3_context *pCtx; /* Write error message here */
- int nNest; /* Number of nested brackets */
-};
-
-/*
-** This function is equivalent to the standard isspace() function.
-**
-** The standard isspace() can be awkward to use safely, because although it
-** is defined to accept an argument of type int, its behavior when passed
-** an integer that falls outside of the range of the unsigned char type
-** is undefined (and sometimes, "undefined" means segfault). This wrapper
-** is defined to accept an argument of type char, and always returns 0 for
-** any values that fall outside of the range of the unsigned char type (i.e.
-** negative values).
-*/
-static int fts3isspace(char c){
- return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
-}
-
-/*
-** Allocate nByte bytes of memory using sqlite3_malloc(). If successful,
-** zero the memory before returning a pointer to it. If unsuccessful,
-** return NULL.
-*/
-static void *fts3MallocZero(int nByte){
- void *pRet = sqlite3_malloc(nByte);
- if( pRet ) memset(pRet, 0, nByte);
- return pRet;
-}
-
-int sqlite3Fts3OpenTokenizer(
- sqlite3_tokenizer *pTokenizer,
- int iLangid,
- const char *z,
- int n,
- sqlite3_tokenizer_cursor **ppCsr
-){
- sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
- sqlite3_tokenizer_cursor *pCsr = 0;
- int rc;
-
- rc = pModule->xOpen(pTokenizer, z, n, &pCsr);
- assert( rc==SQLITE_OK || pCsr==0 );
- if( rc==SQLITE_OK ){
- pCsr->pTokenizer = pTokenizer;
- if( pModule->iVersion>=1 ){
- rc = pModule->xLanguageid(pCsr, iLangid);
- if( rc!=SQLITE_OK ){
- pModule->xClose(pCsr);
- pCsr = 0;
- }
- }
- }
- *ppCsr = pCsr;
- return rc;
-}
-
-/*
-** Function getNextNode(), which is called by fts3ExprParse(), may itself
-** call fts3ExprParse(). So this forward declaration is required.
-*/
-static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
-
-/*
-** Extract the next token from buffer z (length n) using the tokenizer
-** and other information (column names etc.) in pParse. Create an Fts3Expr
-** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
-** single token and set *ppExpr to point to it. If the end of the buffer is
-** reached before a token is found, set *ppExpr to zero. It is the
-** responsibility of the caller to eventually deallocate the allocated
-** Fts3Expr structure (if any) by passing it to sqlite3_free().
-**
-** Return SQLITE_OK if successful, or SQLITE_NOMEM if a memory allocation
-** fails.
-*/
-static int getNextToken(
- ParseContext *pParse, /* fts3 query parse context */
- int iCol, /* Value for Fts3Phrase.iColumn */
- const char *z, int n, /* Input string */
- Fts3Expr **ppExpr, /* OUT: expression */
- int *pnConsumed /* OUT: Number of bytes consumed */
-){
- sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
- sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
- int rc;
- sqlite3_tokenizer_cursor *pCursor;
- Fts3Expr *pRet = 0;
- int i = 0;
-
- /* Set variable i to the maximum number of bytes of input to tokenize. */
- for(i=0; i<n; i++){
- if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
- if( z[i]=='"' ) break;
- }
-
- *pnConsumed = i;
- rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
- if( rc==SQLITE_OK ){
- const char *zToken;
- int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
- int nByte; /* total space to allocate */
-
- rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
- if( rc==SQLITE_OK ){
- nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
- pRet = (Fts3Expr *)fts3MallocZero(nByte);
- if( !pRet ){
- rc = SQLITE_NOMEM;
- }else{
- pRet->eType = FTSQUERY_PHRASE;
- pRet->pPhrase = (Fts3Phrase *)&pRet[1];
- pRet->pPhrase->nToken = 1;
- pRet->pPhrase->iColumn = iCol;
- pRet->pPhrase->aToken[0].n = nToken;
- pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
- memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
-
- if( iEnd<n && z[iEnd]=='*' ){
- pRet->pPhrase->aToken[0].isPrefix = 1;
- iEnd++;
- }
-
- while( 1 ){
- if( !sqlite3_fts3_enable_parentheses
- && iStart>0 && z[iStart-1]=='-'
- ){
- pParse->isNot = 1;
- iStart--;
- }else if( pParse->bFts4 && iStart>0 && z[iStart-1]=='^' ){
- pRet->pPhrase->aToken[0].bFirst = 1;
- iStart--;
- }else{
- break;
- }
- }
-
- }
- *pnConsumed = iEnd;
- }else if( i && rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- }
-
- pModule->xClose(pCursor);
- }
-
- *ppExpr = pRet;
- return rc;
-}
-
-
-/*
-** Enlarge a memory allocation. If an out-of-memory allocation occurs,
-** then free the old allocation.
-*/
-static void *fts3ReallocOrFree(void *pOrig, int nNew){
- void *pRet = sqlite3_realloc(pOrig, nNew);
- if( !pRet ){
- sqlite3_free(pOrig);
- }
- return pRet;
-}
-
-/*
-** Buffer zInput, length nInput, contains the contents of a quoted string
-** that appeared as part of an fts3 query expression. Neither quote character
-** is included in the buffer. This function attempts to tokenize the entire
-** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE
-** containing the results.
-**
-** If successful, SQLITE_OK is returned and *ppExpr set to point at the
-** allocated Fts3Expr structure. Otherwise, either SQLITE_NOMEM (out of memory
-** error) or SQLITE_ERROR (tokenization error) is returned and *ppExpr set
-** to 0.
-*/
-static int getNextString(
- ParseContext *pParse, /* fts3 query parse context */
- const char *zInput, int nInput, /* Input string */
- Fts3Expr **ppExpr /* OUT: expression */
-){
- sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
- sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
- int rc;
- Fts3Expr *p = 0;
- sqlite3_tokenizer_cursor *pCursor = 0;
- char *zTemp = 0;
- int nTemp = 0;
-
- const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
- int nToken = 0;
-
- /* The final Fts3Expr data structure, including the Fts3Phrase,
- ** Fts3PhraseToken structures token buffers are all stored as a single
- ** allocation so that the expression can be freed with a single call to
- ** sqlite3_free(). Setting this up requires a two pass approach.
- **
- ** The first pass, in the block below, uses a tokenizer cursor to iterate
- ** through the tokens in the expression. This pass uses fts3ReallocOrFree()
- ** to assemble data in two dynamic buffers:
- **
- ** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase
- ** structure, followed by the array of Fts3PhraseToken
- ** structures. This pass only populates the Fts3PhraseToken array.
- **
- ** Buffer zTemp: Contains copies of all tokens.
- **
- ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
- ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
- ** structures.
- */
- rc = sqlite3Fts3OpenTokenizer(
- pTokenizer, pParse->iLangid, zInput, nInput, &pCursor);
- if( rc==SQLITE_OK ){
- int ii;
- for(ii=0; rc==SQLITE_OK; ii++){
- const char *zByte;
- int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0;
- rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
- if( rc==SQLITE_OK ){
- Fts3PhraseToken *pToken;
-
- p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
- if( !p ) goto no_mem;
-
- zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
- if( !zTemp ) goto no_mem;
-
- assert( nToken==ii );
- pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
- memset(pToken, 0, sizeof(Fts3PhraseToken));
-
- memcpy(&zTemp[nTemp], zByte, nByte);
- nTemp += nByte;
-
- pToken->n = nByte;
- pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
- pToken->bFirst = (iBegin>0 && zInput[iBegin-1]=='^');
- nToken = ii+1;
- }
- }
-
- pModule->xClose(pCursor);
- pCursor = 0;
- }
-
- if( rc==SQLITE_DONE ){
- int jj;
- char *zBuf = 0;
-
- p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
- if( !p ) goto no_mem;
- memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
- p->eType = FTSQUERY_PHRASE;
- p->pPhrase = (Fts3Phrase *)&p[1];
- p->pPhrase->iColumn = pParse->iDefaultCol;
- p->pPhrase->nToken = nToken;
-
- zBuf = (char *)&p->pPhrase->aToken[nToken];
- if( zTemp ){
- memcpy(zBuf, zTemp, nTemp);
- sqlite3_free(zTemp);
- }else{
- assert( nTemp==0 );
- }
-
- for(jj=0; jj<p->pPhrase->nToken; jj++){
- p->pPhrase->aToken[jj].z = zBuf;
- zBuf += p->pPhrase->aToken[jj].n;
- }
- rc = SQLITE_OK;
- }
-
- *ppExpr = p;
- return rc;
-no_mem:
-
- if( pCursor ){
- pModule->xClose(pCursor);
- }
- sqlite3_free(zTemp);
- sqlite3_free(p);
- *ppExpr = 0;
- return SQLITE_NOMEM;
-}
-
-/*
-** The output variable *ppExpr is populated with an allocated Fts3Expr
-** structure, or set to 0 if the end of the input buffer is reached.
-**
-** Returns an SQLite error code. SQLITE_OK if everything works, SQLITE_NOMEM
-** if a malloc failure occurs, or SQLITE_ERROR if a parse error is encountered.
-** If SQLITE_ERROR is returned, pContext is populated with an error message.
-*/
-static int getNextNode(
- ParseContext *pParse, /* fts3 query parse context */
- const char *z, int n, /* Input string */
- Fts3Expr **ppExpr, /* OUT: expression */
- int *pnConsumed /* OUT: Number of bytes consumed */
-){
- static const struct Fts3Keyword {
- char *z; /* Keyword text */
- unsigned char n; /* Length of the keyword */
- unsigned char parenOnly; /* Only valid in paren mode */
- unsigned char eType; /* Keyword code */
- } aKeyword[] = {
- { "OR" , 2, 0, FTSQUERY_OR },
- { "AND", 3, 1, FTSQUERY_AND },
- { "NOT", 3, 1, FTSQUERY_NOT },
- { "NEAR", 4, 0, FTSQUERY_NEAR }
- };
- int ii;
- int iCol;
- int iColLen;
- int rc;
- Fts3Expr *pRet = 0;
-
- const char *zInput = z;
- int nInput = n;
-
- pParse->isNot = 0;
-
- /* Skip over any whitespace before checking for a keyword, an open or
- ** close bracket, or a quoted string.
- */
- while( nInput>0 && fts3isspace(*zInput) ){
- nInput--;
- zInput++;
- }
- if( nInput==0 ){
- return SQLITE_DONE;
- }
-
- /* See if we are dealing with a keyword. */
- for(ii=0; ii<(int)(sizeof(aKeyword)/sizeof(struct Fts3Keyword)); ii++){
- const struct Fts3Keyword *pKey = &aKeyword[ii];
-
- if( (pKey->parenOnly & ~sqlite3_fts3_enable_parentheses)!=0 ){
- continue;
- }
-
- if( nInput>=pKey->n && 0==memcmp(zInput, pKey->z, pKey->n) ){
- int nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM;
- int nKey = pKey->n;
- char cNext;
-
- /* If this is a "NEAR" keyword, check for an explicit nearness. */
- if( pKey->eType==FTSQUERY_NEAR ){
- assert( nKey==4 );
- if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
- nNear = 0;
- for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){
- nNear = nNear * 10 + (zInput[nKey] - '0');
- }
- }
- }
-
- /* At this point this is probably a keyword. But for that to be true,
- ** the next byte must contain either whitespace, an open or close
- ** parenthesis, a quote character, or EOF.
- */
- cNext = zInput[nKey];
- if( fts3isspace(cNext)
- || cNext=='"' || cNext=='(' || cNext==')' || cNext==0
- ){
- pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
- if( !pRet ){
- return SQLITE_NOMEM;
- }
- pRet->eType = pKey->eType;
- pRet->nNear = nNear;
- *ppExpr = pRet;
- *pnConsumed = (int)((zInput - z) + nKey);
- return SQLITE_OK;
- }
-
- /* Turns out that wasn't a keyword after all. This happens if the
- ** user has supplied a token such as "ORacle". Continue.
- */
- }
- }
-
- /* See if we are dealing with a quoted phrase. If this is the case, then
- ** search for the closing quote and pass the whole string to getNextString()
- ** for processing. This is easy to do, as fts3 has no syntax for escaping
- ** a quote character embedded in a string.
- */
- if( *zInput=='"' ){
- for(ii=1; ii<nInput && zInput[ii]!='"'; ii++);
- *pnConsumed = (int)((zInput - z) + ii + 1);
- if( ii==nInput ){
- return SQLITE_ERROR;
- }
- return getNextString(pParse, &zInput[1], ii-1, ppExpr);
- }
-
- if( sqlite3_fts3_enable_parentheses ){
- if( *zInput=='(' ){
- int nConsumed = 0;
- pParse->nNest++;
- rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
- if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
- *pnConsumed = (int)(zInput - z) + 1 + nConsumed;
- return rc;
- }else if( *zInput==')' ){
- pParse->nNest--;
- *pnConsumed = (int)((zInput - z) + 1);
- *ppExpr = 0;
- return SQLITE_DONE;
- }
- }
-
- /* If control flows to this point, this must be a regular token, or
- ** the end of the input. Read a regular token using the sqlite3_tokenizer
- ** interface. Before doing so, figure out if there is an explicit
- ** column specifier for the token.
- **
- ** TODO: Strangely, it is not possible to associate a column specifier
- ** with a quoted phrase, only with a single token. Not sure if this was
- ** an implementation artifact or an intentional decision when fts3 was
- ** first implemented. Whichever it was, this module duplicates the
- ** limitation.
- */
- iCol = pParse->iDefaultCol;
- iColLen = 0;
- for(ii=0; ii<pParse->nCol; ii++){
- const char *zStr = pParse->azCol[ii];
- int nStr = (int)strlen(zStr);
- if( nInput>nStr && zInput[nStr]==':'
- && sqlite3_strnicmp(zStr, zInput, nStr)==0
- ){
- iCol = ii;
- iColLen = (int)((zInput - z) + nStr + 1);
- break;
- }
- }
- rc = getNextToken(pParse, iCol, &z[iColLen], n-iColLen, ppExpr, pnConsumed);
- *pnConsumed += iColLen;
- return rc;
-}
-
-/*
-** The argument is an Fts3Expr structure for a binary operator (any type
-** except an FTSQUERY_PHRASE). Return an integer value representing the
-** precedence of the operator. Lower values have a higher precedence (i.e.
-** group more tightly). For example, in the C language, the == operator
-** groups more tightly than ||, and would therefore have a higher precedence.
-**
-** When using the new fts3 query syntax (when SQLITE_ENABLE_FTS3_PARENTHESIS
-** is defined), the order of the operators in precedence from highest to
-** lowest is:
-**
-** NEAR
-** NOT
-** AND (including implicit ANDs)
-** OR
-**
-** Note that when using the old query syntax, the OR operator has a higher
-** precedence than the AND operator.
-*/
-static int opPrecedence(Fts3Expr *p){
- assert( p->eType!=FTSQUERY_PHRASE );
- if( sqlite3_fts3_enable_parentheses ){
- return p->eType;
- }else if( p->eType==FTSQUERY_NEAR ){
- return 1;
- }else if( p->eType==FTSQUERY_OR ){
- return 2;
- }
- assert( p->eType==FTSQUERY_AND );
- return 3;
-}
-
-/*
-** Argument ppHead contains a pointer to the current head of a query
-** expression tree being parsed. pPrev is the expression node most recently
-** inserted into the tree. This function adds pNew, which is always a binary
-** operator node, into the expression tree based on the relative precedence
-** of pNew and the existing nodes of the tree. This may result in the head
-** of the tree changing, in which case *ppHead is set to the new root node.
-*/
-static void insertBinaryOperator(
- Fts3Expr **ppHead, /* Pointer to the root node of a tree */
- Fts3Expr *pPrev, /* Node most recently inserted into the tree */
- Fts3Expr *pNew /* New binary node to insert into expression tree */
-){
- Fts3Expr *pSplit = pPrev;
- while( pSplit->pParent && opPrecedence(pSplit->pParent)<=opPrecedence(pNew) ){
- pSplit = pSplit->pParent;
- }
-
- if( pSplit->pParent ){
- assert( pSplit->pParent->pRight==pSplit );
- pSplit->pParent->pRight = pNew;
- pNew->pParent = pSplit->pParent;
- }else{
- *ppHead = pNew;
- }
- pNew->pLeft = pSplit;
- pSplit->pParent = pNew;
-}
-
-/*
-** Parse the fts3 query expression found in buffer z, length n. This function
-** returns either when the end of the buffer is reached or an unmatched
-** closing bracket - ')' - is encountered.
-**
-** If successful, SQLITE_OK is returned, *ppExpr is set to point to the
-** parsed form of the expression and *pnConsumed is set to the number of
-** bytes read from buffer z. Otherwise, *ppExpr is set to 0 and SQLITE_NOMEM
-** (out of memory error) or SQLITE_ERROR (parse error) is returned.
-*/
-static int fts3ExprParse(
- ParseContext *pParse, /* fts3 query parse context */
- const char *z, int n, /* Text of MATCH query */
- Fts3Expr **ppExpr, /* OUT: Parsed query structure */
- int *pnConsumed /* OUT: Number of bytes consumed */
-){
- Fts3Expr *pRet = 0;
- Fts3Expr *pPrev = 0;
- Fts3Expr *pNotBranch = 0; /* Only used in legacy parse mode */
- int nIn = n;
- const char *zIn = z;
- int rc = SQLITE_OK;
- int isRequirePhrase = 1;
-
- while( rc==SQLITE_OK ){
- Fts3Expr *p = 0;
- int nByte = 0;
-
- rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
- assert( nByte>0 || (rc!=SQLITE_OK && p==0) );
- if( rc==SQLITE_OK ){
- if( p ){
- int isPhrase;
-
- if( !sqlite3_fts3_enable_parentheses
- && p->eType==FTSQUERY_PHRASE && pParse->isNot
- ){
- /* Create an implicit NOT operator. */
- Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
- if( !pNot ){
- sqlite3Fts3ExprFree(p);
- rc = SQLITE_NOMEM;
- goto exprparse_out;
- }
- pNot->eType = FTSQUERY_NOT;
- pNot->pRight = p;
- p->pParent = pNot;
- if( pNotBranch ){
- pNot->pLeft = pNotBranch;
- pNotBranch->pParent = pNot;
- }
- pNotBranch = pNot;
- p = pPrev;
- }else{
- int eType = p->eType;
- isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
-
- /* The isRequirePhrase variable is set to true if a phrase or
- ** an expression contained in parenthesis is required. If a
- ** binary operator (AND, OR, NOT or NEAR) is encounted when
- ** isRequirePhrase is set, this is a syntax error.
- */
- if( !isPhrase && isRequirePhrase ){
- sqlite3Fts3ExprFree(p);
- rc = SQLITE_ERROR;
- goto exprparse_out;
- }
-
- if( isPhrase && !isRequirePhrase ){
- /* Insert an implicit AND operator. */
- Fts3Expr *pAnd;
- assert( pRet && pPrev );
- pAnd = fts3MallocZero(sizeof(Fts3Expr));
- if( !pAnd ){
- sqlite3Fts3ExprFree(p);
- rc = SQLITE_NOMEM;
- goto exprparse_out;
- }
- pAnd->eType = FTSQUERY_AND;
- insertBinaryOperator(&pRet, pPrev, pAnd);
- pPrev = pAnd;
- }
-
- /* This test catches attempts to make either operand of a NEAR
- ** operator something other than a phrase. For example, either of
- ** the following:
- **
- ** (bracketed expression) NEAR phrase
- ** phrase NEAR (bracketed expression)
- **
- ** Return an error in either case.
- */
- if( pPrev && (
- (eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE)
- || (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR)
- )){
- sqlite3Fts3ExprFree(p);
- rc = SQLITE_ERROR;
- goto exprparse_out;
- }
-
- if( isPhrase ){
- if( pRet ){
- assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
- pPrev->pRight = p;
- p->pParent = pPrev;
- }else{
- pRet = p;
- }
- }else{
- insertBinaryOperator(&pRet, pPrev, p);
- }
- isRequirePhrase = !isPhrase;
- }
- pPrev = p;
- }
- assert( nByte>0 );
- }
- assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) );
- nIn -= nByte;
- zIn += nByte;
- }
-
- if( rc==SQLITE_DONE && pRet && isRequirePhrase ){
- rc = SQLITE_ERROR;
- }
-
- if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- if( !sqlite3_fts3_enable_parentheses && pNotBranch ){
- if( !pRet ){
- rc = SQLITE_ERROR;
- }else{
- Fts3Expr *pIter = pNotBranch;
- while( pIter->pLeft ){
- pIter = pIter->pLeft;
- }
- pIter->pLeft = pRet;
- pRet->pParent = pIter;
- pRet = pNotBranch;
- }
- }
- }
- *pnConsumed = n - nIn;
-
-exprparse_out:
- if( rc!=SQLITE_OK ){
- sqlite3Fts3ExprFree(pRet);
- sqlite3Fts3ExprFree(pNotBranch);
- pRet = 0;
- }
- *ppExpr = pRet;
- return rc;
-}
-
-/*
-** Return SQLITE_ERROR if the maximum depth of the expression tree passed
-** as the only argument is more than nMaxDepth.
-*/
-static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){
- int rc = SQLITE_OK;
- if( p ){
- if( nMaxDepth<0 ){
- rc = SQLITE_TOOBIG;
- }else{
- rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1);
- if( rc==SQLITE_OK ){
- rc = fts3ExprCheckDepth(p->pRight, nMaxDepth-1);
- }
- }
- }
- return rc;
-}
-
-/*
-** This function attempts to transform the expression tree at (*pp) to
-** an equivalent but more balanced form. The tree is modified in place.
-** If successful, SQLITE_OK is returned and (*pp) set to point to the
-** new root expression node.
-**
-** nMaxDepth is the maximum allowable depth of the balanced sub-tree.
-**
-** Otherwise, if an error occurs, an SQLite error code is returned and
-** expression (*pp) freed.
-*/
-static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
- int rc = SQLITE_OK; /* Return code */
- Fts3Expr *pRoot = *pp; /* Initial root node */
- Fts3Expr *pFree = 0; /* List of free nodes. Linked by pParent. */
- int eType = pRoot->eType; /* Type of node in this tree */
-
- if( nMaxDepth==0 ){
- rc = SQLITE_ERROR;
- }
-
- if( rc==SQLITE_OK ){
- if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
- Fts3Expr **apLeaf;
- apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
- if( 0==apLeaf ){
- rc = SQLITE_NOMEM;
- }else{
- memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth);
- }
-
- if( rc==SQLITE_OK ){
- int i;
- Fts3Expr *p;
-
- /* Set $p to point to the left-most leaf in the tree of eType nodes. */
- for(p=pRoot; p->eType==eType; p=p->pLeft){
- assert( p->pParent==0 || p->pParent->pLeft==p );
- assert( p->pLeft && p->pRight );
- }
-
- /* This loop runs once for each leaf in the tree of eType nodes. */
- while( 1 ){
- int iLvl;
- Fts3Expr *pParent = p->pParent; /* Current parent of p */
-
- assert( pParent==0 || pParent->pLeft==p );
- p->pParent = 0;
- if( pParent ){
- pParent->pLeft = 0;
- }else{
- pRoot = 0;
- }
- rc = fts3ExprBalance(&p, nMaxDepth-1);
- if( rc!=SQLITE_OK ) break;
-
- for(iLvl=0; p && iLvl<nMaxDepth; iLvl++){
- if( apLeaf[iLvl]==0 ){
- apLeaf[iLvl] = p;
- p = 0;
- }else{
- assert( pFree );
- pFree->pLeft = apLeaf[iLvl];
- pFree->pRight = p;
- pFree->pLeft->pParent = pFree;
- pFree->pRight->pParent = pFree;
-
- p = pFree;
- pFree = pFree->pParent;
- p->pParent = 0;
- apLeaf[iLvl] = 0;
- }
- }
- if( p ){
- sqlite3Fts3ExprFree(p);
- rc = SQLITE_TOOBIG;
- break;
- }
-
- /* If that was the last leaf node, break out of the loop */
- if( pParent==0 ) break;
-
- /* Set $p to point to the next leaf in the tree of eType nodes */
- for(p=pParent->pRight; p->eType==eType; p=p->pLeft);
-
- /* Remove pParent from the original tree. */
- assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent );
- pParent->pRight->pParent = pParent->pParent;
- if( pParent->pParent ){
- pParent->pParent->pLeft = pParent->pRight;
- }else{
- assert( pParent==pRoot );
- pRoot = pParent->pRight;
- }
-
- /* Link pParent into the free node list. It will be used as an
- ** internal node of the new tree. */
- pParent->pParent = pFree;
- pFree = pParent;
- }
-
- if( rc==SQLITE_OK ){
- p = 0;
- for(i=0; i<nMaxDepth; i++){
- if( apLeaf[i] ){
- if( p==0 ){
- p = apLeaf[i];
- p->pParent = 0;
- }else{
- assert( pFree!=0 );
- pFree->pRight = p;
- pFree->pLeft = apLeaf[i];
- pFree->pLeft->pParent = pFree;
- pFree->pRight->pParent = pFree;
-
- p = pFree;
- pFree = pFree->pParent;
- p->pParent = 0;
- }
- }
- }
- pRoot = p;
- }else{
- /* An error occurred. Delete the contents of the apLeaf[] array
- ** and pFree list. Everything else is cleaned up by the call to
- ** sqlite3Fts3ExprFree(pRoot) below. */
- Fts3Expr *pDel;
- for(i=0; i<nMaxDepth; i++){
- sqlite3Fts3ExprFree(apLeaf[i]);
- }
- while( (pDel=pFree)!=0 ){
- pFree = pDel->pParent;
- sqlite3_free(pDel);
- }
- }
-
- assert( pFree==0 );
- sqlite3_free( apLeaf );
- }
- }else if( eType==FTSQUERY_NOT ){
- Fts3Expr *pLeft = pRoot->pLeft;
- Fts3Expr *pRight = pRoot->pRight;
-
- pRoot->pLeft = 0;
- pRoot->pRight = 0;
- pLeft->pParent = 0;
- pRight->pParent = 0;
-
- rc = fts3ExprBalance(&pLeft, nMaxDepth-1);
- if( rc==SQLITE_OK ){
- rc = fts3ExprBalance(&pRight, nMaxDepth-1);
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3Fts3ExprFree(pRight);
- sqlite3Fts3ExprFree(pLeft);
- }else{
- assert( pLeft && pRight );
- pRoot->pLeft = pLeft;
- pLeft->pParent = pRoot;
- pRoot->pRight = pRight;
- pRight->pParent = pRoot;
- }
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3Fts3ExprFree(pRoot);
- pRoot = 0;
- }
- *pp = pRoot;
- return rc;
-}
-
-/*
-** This function is similar to sqlite3Fts3ExprParse(), with the following
-** differences:
-**
-** 1. It does not do expression rebalancing.
-** 2. It does not check that the expression does not exceed the
-** maximum allowable depth.
-** 3. Even if it fails, *ppExpr may still be set to point to an
-** expression tree. It should be deleted using sqlite3Fts3ExprFree()
-** in this case.
-*/
-static int fts3ExprParseUnbalanced(
- sqlite3_tokenizer *pTokenizer, /* Tokenizer module */
- int iLangid, /* Language id for tokenizer */
- char **azCol, /* Array of column names for fts3 table */
- int bFts4, /* True to allow FTS4-only syntax */
- int nCol, /* Number of entries in azCol[] */
- int iDefaultCol, /* Default column to query */
- const char *z, int n, /* Text of MATCH query */
- Fts3Expr **ppExpr /* OUT: Parsed query structure */
-){
- int nParsed;
- int rc;
- ParseContext sParse;
-
- memset(&sParse, 0, sizeof(ParseContext));
- sParse.pTokenizer = pTokenizer;
- sParse.iLangid = iLangid;
- sParse.azCol = (const char **)azCol;
- sParse.nCol = nCol;
- sParse.iDefaultCol = iDefaultCol;
- sParse.bFts4 = bFts4;
- if( z==0 ){
- *ppExpr = 0;
- return SQLITE_OK;
- }
- if( n<0 ){
- n = (int)strlen(z);
- }
- rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed);
- assert( rc==SQLITE_OK || *ppExpr==0 );
-
- /* Check for mismatched parenthesis */
- if( rc==SQLITE_OK && sParse.nNest ){
- rc = SQLITE_ERROR;
- }
-
- return rc;
-}
-
-/*
-** Parameters z and n contain a pointer to and length of a buffer containing
-** an fts3 query expression, respectively. This function attempts to parse the
-** query expression and create a tree of Fts3Expr structures representing the
-** parsed expression. If successful, *ppExpr is set to point to the head
-** of the parsed expression tree and SQLITE_OK is returned. If an error
-** occurs, either SQLITE_NOMEM (out-of-memory error) or SQLITE_ERROR (parse
-** error) is returned and *ppExpr is set to 0.
-**
-** If parameter n is a negative number, then z is assumed to point to a
-** nul-terminated string and the length is determined using strlen().
-**
-** The first parameter, pTokenizer, is passed the fts3 tokenizer module to
-** use to normalize query tokens while parsing the expression. The azCol[]
-** array, which is assumed to contain nCol entries, should contain the names
-** of each column in the target fts3 table, in order from left to right.
-** Column names must be nul-terminated strings.
-**
-** The iDefaultCol parameter should be passed the index of the table column
-** that appears on the left-hand-side of the MATCH operator (the default
-** column to match against for tokens for which a column name is not explicitly
-** specified as part of the query string), or -1 if tokens may by default
-** match any table column.
-*/
-int sqlite3Fts3ExprParse(
- sqlite3_tokenizer *pTokenizer, /* Tokenizer module */
- int iLangid, /* Language id for tokenizer */
- char **azCol, /* Array of column names for fts3 table */
- int bFts4, /* True to allow FTS4-only syntax */
- int nCol, /* Number of entries in azCol[] */
- int iDefaultCol, /* Default column to query */
- const char *z, int n, /* Text of MATCH query */
- Fts3Expr **ppExpr, /* OUT: Parsed query structure */
- char **pzErr /* OUT: Error message (sqlite3_malloc) */
-){
- int rc = fts3ExprParseUnbalanced(
- pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr
- );
-
- /* Rebalance the expression. And check that its depth does not exceed
- ** SQLITE_FTS3_MAX_EXPR_DEPTH. */
- if( rc==SQLITE_OK && *ppExpr ){
- rc = fts3ExprBalance(ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH);
- if( rc==SQLITE_OK ){
- rc = fts3ExprCheckDepth(*ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH);
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3Fts3ExprFree(*ppExpr);
- *ppExpr = 0;
- if( rc==SQLITE_TOOBIG ){
- sqlite3Fts3ErrMsg(pzErr,
- "FTS expression tree is too large (maximum depth %d)",
- SQLITE_FTS3_MAX_EXPR_DEPTH
- );
- rc = SQLITE_ERROR;
- }else if( rc==SQLITE_ERROR ){
- sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z);
- }
- }
-
- return rc;
-}
-
-/*
-** Free a single node of an expression tree.
-*/
-static void fts3FreeExprNode(Fts3Expr *p){
- assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
- sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
- sqlite3_free(p->aMI);
- sqlite3_free(p);
-}
-
-/*
-** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse().
-**
-** This function would be simpler if it recursively called itself. But
-** that would mean passing a sufficiently large expression to ExprParse()
-** could cause a stack overflow.
-*/
-void sqlite3Fts3ExprFree(Fts3Expr *pDel){
- Fts3Expr *p;
- assert( pDel==0 || pDel->pParent==0 );
- for(p=pDel; p && (p->pLeft||p->pRight); p=(p->pLeft ? p->pLeft : p->pRight)){
- assert( p->pParent==0 || p==p->pParent->pRight || p==p->pParent->pLeft );
- }
- while( p ){
- Fts3Expr *pParent = p->pParent;
- fts3FreeExprNode(p);
- if( pParent && p==pParent->pLeft && pParent->pRight ){
- p = pParent->pRight;
- while( p && (p->pLeft || p->pRight) ){
- assert( p==p->pParent->pRight || p==p->pParent->pLeft );
- p = (p->pLeft ? p->pLeft : p->pRight);
- }
- }else{
- p = pParent;
- }
- }
-}
-
-/****************************************************************************
-*****************************************************************************
-** Everything after this point is just test code.
-*/
-
-#ifdef SQLITE_TEST
-
-#include <stdio.h>
-
-/*
-** Return a pointer to a buffer containing a text representation of the
-** expression passed as the first argument. The buffer is obtained from
-** sqlite3_malloc(). It is the responsibility of the caller to use
-** sqlite3_free() to release the memory. If an OOM condition is encountered,
-** NULL is returned.
-**
-** If the second argument is not NULL, then its contents are prepended to
-** the returned expression text and then freed using sqlite3_free().
-*/
-static char *exprToString(Fts3Expr *pExpr, char *zBuf){
- if( pExpr==0 ){
- return sqlite3_mprintf("");
- }
- switch( pExpr->eType ){
- case FTSQUERY_PHRASE: {
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- int i;
- zBuf = sqlite3_mprintf(
- "%zPHRASE %d 0", zBuf, pPhrase->iColumn);
- for(i=0; zBuf && i<pPhrase->nToken; i++){
- zBuf = sqlite3_mprintf("%z %.*s%s", zBuf,
- pPhrase->aToken[i].n, pPhrase->aToken[i].z,
- (pPhrase->aToken[i].isPrefix?"+":"")
- );
- }
- return zBuf;
- }
-
- case FTSQUERY_NEAR:
- zBuf = sqlite3_mprintf("%zNEAR/%d ", zBuf, pExpr->nNear);
- break;
- case FTSQUERY_NOT:
- zBuf = sqlite3_mprintf("%zNOT ", zBuf);
- break;
- case FTSQUERY_AND:
- zBuf = sqlite3_mprintf("%zAND ", zBuf);
- break;
- case FTSQUERY_OR:
- zBuf = sqlite3_mprintf("%zOR ", zBuf);
- break;
- }
-
- if( zBuf ) zBuf = sqlite3_mprintf("%z{", zBuf);
- if( zBuf ) zBuf = exprToString(pExpr->pLeft, zBuf);
- if( zBuf ) zBuf = sqlite3_mprintf("%z} {", zBuf);
-
- if( zBuf ) zBuf = exprToString(pExpr->pRight, zBuf);
- if( zBuf ) zBuf = sqlite3_mprintf("%z}", zBuf);
-
- return zBuf;
-}
-
-/*
-** This is the implementation of a scalar SQL function used to test the
-** expression parser. It should be called as follows:
-**
-** fts3_exprtest(<tokenizer>, <expr>, <column 1>, ...);
-**
-** The first argument, <tokenizer>, is the name of the fts3 tokenizer used
-** to parse the query expression (see README.tokenizers). The second argument
-** is the query expression to parse. Each subsequent argument is the name
-** of a column of the fts3 table that the query expression may refer to.
-** For example:
-**
-** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2');
-*/
-static void fts3ExprTestCommon(
- int bRebalance,
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3_tokenizer *pTokenizer = 0;
- int rc;
- char **azCol = 0;
- const char *zExpr;
- int nExpr;
- int nCol;
- int ii;
- Fts3Expr *pExpr;
- char *zBuf = 0;
- Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context);
- const char *zTokenizer = 0;
- char *zErr = 0;
-
- if( argc<3 ){
- sqlite3_result_error(context,
- "Usage: fts3_exprtest(tokenizer, expr, col1, ...", -1
- );
- return;
- }
-
- zTokenizer = (const char*)sqlite3_value_text(argv[0]);
- rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ){
- sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_error(context, zErr, -1);
- }
- sqlite3_free(zErr);
- return;
- }
-
- zExpr = (const char *)sqlite3_value_text(argv[1]);
- nExpr = sqlite3_value_bytes(argv[1]);
- nCol = argc-2;
- azCol = (char **)sqlite3_malloc(nCol*sizeof(char *));
- if( !azCol ){
- sqlite3_result_error_nomem(context);
- goto exprtest_out;
- }
- for(ii=0; ii<nCol; ii++){
- azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
- }
-
- if( bRebalance ){
- char *zDummy = 0;
- rc = sqlite3Fts3ExprParse(
- pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy
- );
- assert( rc==SQLITE_OK || pExpr==0 );
- sqlite3_free(zDummy);
- }else{
- rc = fts3ExprParseUnbalanced(
- pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
- );
- }
-
- if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
- sqlite3Fts3ExprFree(pExpr);
- sqlite3_result_error(context, "Error parsing expression", -1);
- }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
- sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- sqlite3_free(zBuf);
- }
-
- sqlite3Fts3ExprFree(pExpr);
-
-exprtest_out:
- if( pTokenizer ){
- rc = pTokenizer->pModule->xDestroy(pTokenizer);
- }
- sqlite3_free(azCol);
-}
-
-static void fts3ExprTest(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- fts3ExprTestCommon(0, context, argc, argv);
-}
-static void fts3ExprTestRebalance(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- fts3ExprTestCommon(1, context, argc, argv);
-}
-
-/*
-** Register the query expression parser test function fts3_exprtest()
-** with database connection db.
-*/
-int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){
- int rc = sqlite3_create_function(
- db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "fts3_exprtest_rebalance",
- -1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0
- );
- }
- return rc;
-}
-
-#endif
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_hash.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_hash.c
deleted file mode 100644
index 1a32a537b40..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_hash.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the implementation of generic hash-tables used in SQLite.
-** We've modified it slightly to serve as a standalone hash table
-** implementation for the full-text indexing module.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS3 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS3 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
-*/
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "fts3_hash.h"
-
-/*
-** Malloc and Free functions
-*/
-static void *fts3HashMalloc(int n){
- void *p = sqlite3_malloc(n);
- if( p ){
- memset(p, 0, n);
- }
- return p;
-}
-static void fts3HashFree(void *p){
- sqlite3_free(p);
-}
-
-/* Turn bulk memory into a hash table object by initializing the
-** fields of the Hash structure.
-**
-** "pNew" is a pointer to the hash table that is to be initialized.
-** keyClass is one of the constants
-** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass
-** determines what kind of key the hash table will use. "copyKey" is
-** true if the hash table should make its own private copy of keys and
-** false if it should just use the supplied pointer.
-*/
-void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){
- assert( pNew!=0 );
- assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY );
- pNew->keyClass = keyClass;
- pNew->copyKey = copyKey;
- pNew->first = 0;
- pNew->count = 0;
- pNew->htsize = 0;
- pNew->ht = 0;
-}
-
-/* Remove all entries from a hash table. Reclaim all memory.
-** Call this routine to delete a hash table or to reset a hash table
-** to the empty state.
-*/
-void sqlite3Fts3HashClear(Fts3Hash *pH){
- Fts3HashElem *elem; /* For looping over all elements of the table */
-
- assert( pH!=0 );
- elem = pH->first;
- pH->first = 0;
- fts3HashFree(pH->ht);
- pH->ht = 0;
- pH->htsize = 0;
- while( elem ){
- Fts3HashElem *next_elem = elem->next;
- if( pH->copyKey && elem->pKey ){
- fts3HashFree(elem->pKey);
- }
- fts3HashFree(elem);
- elem = next_elem;
- }
- pH->count = 0;
-}
-
-/*
-** Hash and comparison functions when the mode is FTS3_HASH_STRING
-*/
-static int fts3StrHash(const void *pKey, int nKey){
- const char *z = (const char *)pKey;
- unsigned h = 0;
- if( nKey<=0 ) nKey = (int) strlen(z);
- while( nKey > 0 ){
- h = (h<<3) ^ h ^ *z++;
- nKey--;
- }
- return (int)(h & 0x7fffffff);
-}
-static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return strncmp((const char*)pKey1,(const char*)pKey2,n1);
-}
-
-/*
-** Hash and comparison functions when the mode is FTS3_HASH_BINARY
-*/
-static int fts3BinHash(const void *pKey, int nKey){
- int h = 0;
- const char *z = (const char *)pKey;
- while( nKey-- > 0 ){
- h = (h<<3) ^ h ^ *(z++);
- }
- return h & 0x7fffffff;
-}
-static int fts3BinCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return memcmp(pKey1,pKey2,n1);
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** The C syntax in this function definition may be unfamilar to some
-** programmers, so we provide the following additional explanation:
-**
-** The name of the function is "ftsHashFunction". The function takes a
-** single parameter "keyClass". The return value of ftsHashFunction()
-** is a pointer to another function. Specifically, the return value
-** of ftsHashFunction() is a pointer to a function that takes two parameters
-** with types "const void*" and "int" and returns an "int".
-*/
-static int (*ftsHashFunction(int keyClass))(const void*,int){
- if( keyClass==FTS3_HASH_STRING ){
- return &fts3StrHash;
- }else{
- assert( keyClass==FTS3_HASH_BINARY );
- return &fts3BinHash;
- }
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** For help in interpreted the obscure C code in the function definition,
-** see the header comment on the previous function.
-*/
-static int (*ftsCompareFunction(int keyClass))(const void*,int,const void*,int){
- if( keyClass==FTS3_HASH_STRING ){
- return &fts3StrCompare;
- }else{
- assert( keyClass==FTS3_HASH_BINARY );
- return &fts3BinCompare;
- }
-}
-
-/* Link an element into the hash table
-*/
-static void fts3HashInsertElement(
- Fts3Hash *pH, /* The complete hash table */
- struct _fts3ht *pEntry, /* The entry into which pNew is inserted */
- Fts3HashElem *pNew /* The element to be inserted */
-){
- Fts3HashElem *pHead; /* First element already in pEntry */
- pHead = pEntry->chain;
- if( pHead ){
- pNew->next = pHead;
- pNew->prev = pHead->prev;
- if( pHead->prev ){ pHead->prev->next = pNew; }
- else { pH->first = pNew; }
- pHead->prev = pNew;
- }else{
- pNew->next = pH->first;
- if( pH->first ){ pH->first->prev = pNew; }
- pNew->prev = 0;
- pH->first = pNew;
- }
- pEntry->count++;
- pEntry->chain = pNew;
-}
-
-
-/* Resize the hash table so that it cantains "new_size" buckets.
-** "new_size" must be a power of 2. The hash table might fail
-** to resize if sqliteMalloc() fails.
-**
-** Return non-zero if a memory allocation error occurs.
-*/
-static int fts3Rehash(Fts3Hash *pH, int new_size){
- struct _fts3ht *new_ht; /* The new hash table */
- Fts3HashElem *elem, *next_elem; /* For looping over existing elements */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( (new_size & (new_size-1))==0 );
- new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) );
- if( new_ht==0 ) return 1;
- fts3HashFree(pH->ht);
- pH->ht = new_ht;
- pH->htsize = new_size;
- xHash = ftsHashFunction(pH->keyClass);
- for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
- next_elem = elem->next;
- fts3HashInsertElement(pH, &new_ht[h], elem);
- }
- return 0;
-}
-
-/* This function (for internal use only) locates an element in an
-** hash table that matches the given key. The hash for this key has
-** already been computed and is passed as the 4th parameter.
-*/
-static Fts3HashElem *fts3FindElementByHash(
- const Fts3Hash *pH, /* The pH to be searched */
- const void *pKey, /* The key we are searching for */
- int nKey,
- int h /* The hash for this key. */
-){
- Fts3HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- int (*xCompare)(const void*,int,const void*,int); /* comparison function */
-
- if( pH->ht ){
- struct _fts3ht *pEntry = &pH->ht[h];
- elem = pEntry->chain;
- count = pEntry->count;
- xCompare = ftsCompareFunction(pH->keyClass);
- while( count-- && elem ){
- if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- }
- return 0;
-}
-
-/* Remove a single entry from the hash table given a pointer to that
-** element and a hash on the element's key.
-*/
-static void fts3RemoveElementByHash(
- Fts3Hash *pH, /* The pH containing "elem" */
- Fts3HashElem* elem, /* The element to be removed from the pH */
- int h /* Hash value for the element */
-){
- struct _fts3ht *pEntry;
- if( elem->prev ){
- elem->prev->next = elem->next;
- }else{
- pH->first = elem->next;
- }
- if( elem->next ){
- elem->next->prev = elem->prev;
- }
- pEntry = &pH->ht[h];
- if( pEntry->chain==elem ){
- pEntry->chain = elem->next;
- }
- pEntry->count--;
- if( pEntry->count<=0 ){
- pEntry->chain = 0;
- }
- if( pH->copyKey && elem->pKey ){
- fts3HashFree(elem->pKey);
- }
- fts3HashFree( elem );
- pH->count--;
- if( pH->count<=0 ){
- assert( pH->first==0 );
- assert( pH->count==0 );
- fts3HashClear(pH);
- }
-}
-
-Fts3HashElem *sqlite3Fts3HashFindElem(
- const Fts3Hash *pH,
- const void *pKey,
- int nKey
-){
- int h; /* A hash on key */
- int (*xHash)(const void*,int); /* The hash function */
-
- if( pH==0 || pH->ht==0 ) return 0;
- xHash = ftsHashFunction(pH->keyClass);
- assert( xHash!=0 );
- h = (*xHash)(pKey,nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1));
-}
-
-/*
-** Attempt to locate an element of the hash table pH with a key
-** that matches pKey,nKey. Return the data for this element if it is
-** found, or NULL if there is no match.
-*/
-void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
- Fts3HashElem *pElem; /* The element that matches key (if any) */
-
- pElem = sqlite3Fts3HashFindElem(pH, pKey, nKey);
- return pElem ? pElem->data : 0;
-}
-
-/* Insert an element into the hash table pH. The key is pKey,nKey
-** and the data is "data".
-**
-** If no element exists with a matching key, then a new
-** element is created. A copy of the key is made if the copyKey
-** flag is set. NULL is returned.
-**
-** If another element already exists with the same key, then the
-** new data replaces the old data and the old data is returned.
-** The key is not copied in this instance. If a malloc fails, then
-** the new data is returned and the hash table is unchanged.
-**
-** If the "data" parameter to this function is NULL, then the
-** element corresponding to "key" is removed from the hash table.
-*/
-void *sqlite3Fts3HashInsert(
- Fts3Hash *pH, /* The hash table to insert into */
- const void *pKey, /* The key */
- int nKey, /* Number of bytes in the key */
- void *data /* The data */
-){
- int hraw; /* Raw hash value of the key */
- int h; /* the hash of the key modulo hash table size */
- Fts3HashElem *elem; /* Used to loop thru the element list */
- Fts3HashElem *new_elem; /* New element added to the pH */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( pH!=0 );
- xHash = ftsHashFunction(pH->keyClass);
- assert( xHash!=0 );
- hraw = (*xHash)(pKey, nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = fts3FindElementByHash(pH,pKey,nKey,h);
- if( elem ){
- void *old_data = elem->data;
- if( data==0 ){
- fts3RemoveElementByHash(pH,elem,h);
- }else{
- elem->data = data;
- }
- return old_data;
- }
- if( data==0 ) return 0;
- if( (pH->htsize==0 && fts3Rehash(pH,8))
- || (pH->count>=pH->htsize && fts3Rehash(pH, pH->htsize*2))
- ){
- pH->count = 0;
- return data;
- }
- assert( pH->htsize>0 );
- new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) );
- if( new_elem==0 ) return data;
- if( pH->copyKey && pKey!=0 ){
- new_elem->pKey = fts3HashMalloc( nKey );
- if( new_elem->pKey==0 ){
- fts3HashFree(new_elem);
- return data;
- }
- memcpy((void*)new_elem->pKey, pKey, nKey);
- }else{
- new_elem->pKey = (void*)pKey;
- }
- new_elem->nKey = nKey;
- pH->count++;
- assert( pH->htsize>0 );
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- fts3HashInsertElement(pH, &pH->ht[h], new_elem);
- new_elem->data = data;
- return 0;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_hash.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_hash.h
deleted file mode 100644
index dc3fcf8334f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_hash.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the header file for the generic hash-table implementation
-** used in SQLite. We've modified it slightly to serve as a standalone
-** hash table implementation for the full-text indexing module.
-**
-*/
-#ifndef _FTS3_HASH_H_
-#define _FTS3_HASH_H_
-
-/* Forward declarations of structures. */
-typedef struct Fts3Hash Fts3Hash;
-typedef struct Fts3HashElem Fts3HashElem;
-
-/* A complete hash table is an instance of the following structure.
-** The internals of this structure are intended to be opaque -- client
-** code should not attempt to access or modify the fields of this structure
-** directly. Change this structure only by using the routines below.
-** However, many of the "procedures" and "functions" for modifying and
-** accessing this structure are really macros, so we can't really make
-** this structure opaque.
-*/
-struct Fts3Hash {
- char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */
- char copyKey; /* True if copy of key made on insert */
- int count; /* Number of entries in this table */
- Fts3HashElem *first; /* The first element of the array */
- int htsize; /* Number of buckets in the hash table */
- struct _fts3ht { /* the hash table */
- int count; /* Number of entries with this hash */
- Fts3HashElem *chain; /* Pointer to first entry with this hash */
- } *ht;
-};
-
-/* Each element in the hash table is an instance of the following
-** structure. All elements are stored on a single doubly-linked list.
-**
-** Again, this structure is intended to be opaque, but it can't really
-** be opaque because it is used by macros.
-*/
-struct Fts3HashElem {
- Fts3HashElem *next, *prev; /* Next and previous elements in the table */
- void *data; /* Data associated with this element */
- void *pKey; int nKey; /* Key associated with this element */
-};
-
-/*
-** There are 2 different modes of operation for a hash table:
-**
-** FTS3_HASH_STRING pKey points to a string that is nKey bytes long
-** (including the null-terminator, if any). Case
-** is respected in comparisons.
-**
-** FTS3_HASH_BINARY pKey points to binary data nKey bytes long.
-** memcmp() is used to compare keys.
-**
-** A copy of the key is made if the copyKey parameter to fts3HashInit is 1.
-*/
-#define FTS3_HASH_STRING 1
-#define FTS3_HASH_BINARY 2
-
-/*
-** Access routines. To delete, insert a NULL pointer.
-*/
-void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey);
-void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData);
-void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey);
-void sqlite3Fts3HashClear(Fts3Hash*);
-Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const void *, int);
-
-/*
-** Shorthand for the functions above
-*/
-#define fts3HashInit sqlite3Fts3HashInit
-#define fts3HashInsert sqlite3Fts3HashInsert
-#define fts3HashFind sqlite3Fts3HashFind
-#define fts3HashClear sqlite3Fts3HashClear
-#define fts3HashFindElem sqlite3Fts3HashFindElem
-
-/*
-** Macros for looping over all elements of a hash table. The idiom is
-** like this:
-**
-** Fts3Hash h;
-** Fts3HashElem *p;
-** ...
-** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){
-** SomeStructure *pData = fts3HashData(p);
-** // do something with pData
-** }
-*/
-#define fts3HashFirst(H) ((H)->first)
-#define fts3HashNext(E) ((E)->next)
-#define fts3HashData(E) ((E)->data)
-#define fts3HashKey(E) ((E)->pKey)
-#define fts3HashKeysize(E) ((E)->nKey)
-
-/*
-** Number of entries in a hash table
-*/
-#define fts3HashCount(H) ((H)->count)
-
-#endif /* _FTS3_HASH_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_icu.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_icu.c
deleted file mode 100644
index 6f90e1ebad0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_icu.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
-** 2007 June 22
-**
-** 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 a tokenizer for fts3 based on the ICU library.
-*/
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-#ifdef SQLITE_ENABLE_ICU
-
-#include <assert.h>
-#include <string.h>
-#include "fts3_tokenizer.h"
-
-#include <unicode/ubrk.h>
-#include <unicode/ucol.h>
-#include <unicode/ustring.h>
-#include <unicode/utf16.h>
-
-typedef struct IcuTokenizer IcuTokenizer;
-typedef struct IcuCursor IcuCursor;
-
-struct IcuTokenizer {
- sqlite3_tokenizer base;
- char *zLocale;
-};
-
-struct IcuCursor {
- sqlite3_tokenizer_cursor base;
-
- UBreakIterator *pIter; /* ICU break-iterator object */
- int nChar; /* Number of UChar elements in pInput */
- UChar *aChar; /* Copy of input using utf-16 encoding */
- int *aOffset; /* Offsets of each character in utf-8 input */
-
- int nBuffer;
- char *zBuffer;
-
- int iToken;
-};
-
-/*
-** Create a new tokenizer instance.
-*/
-static int icuCreate(
- int argc, /* Number of entries in argv[] */
- const char * const *argv, /* Tokenizer creation arguments */
- sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
-){
- IcuTokenizer *p;
- int n = 0;
-
- if( argc>0 ){
- n = strlen(argv[0])+1;
- }
- p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
- if( !p ){
- return SQLITE_NOMEM;
- }
- memset(p, 0, sizeof(IcuTokenizer));
-
- if( n ){
- p->zLocale = (char *)&p[1];
- memcpy(p->zLocale, argv[0], n);
- }
-
- *ppTokenizer = (sqlite3_tokenizer *)p;
-
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int icuDestroy(sqlite3_tokenizer *pTokenizer){
- IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int icuOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *zInput, /* Input string */
- int nInput, /* Length of zInput in bytes */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
- IcuCursor *pCsr;
-
- const int32_t opt = U_FOLD_CASE_DEFAULT;
- UErrorCode status = U_ZERO_ERROR;
- int nChar;
-
- UChar32 c;
- int iInput = 0;
- int iOut = 0;
-
- *ppCursor = 0;
-
- if( zInput==0 ){
- nInput = 0;
- zInput = "";
- }else if( nInput<0 ){
- nInput = strlen(zInput);
- }
- nChar = nInput+1;
- pCsr = (IcuCursor *)sqlite3_malloc(
- sizeof(IcuCursor) + /* IcuCursor */
- ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
- (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
- );
- if( !pCsr ){
- return SQLITE_NOMEM;
- }
- memset(pCsr, 0, sizeof(IcuCursor));
- pCsr->aChar = (UChar *)&pCsr[1];
- pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
-
- pCsr->aOffset[iOut] = iInput;
- U8_NEXT(zInput, iInput, nInput, c);
- while( c>0 ){
- int isError = 0;
- c = u_foldCase(c, opt);
- U16_APPEND(pCsr->aChar, iOut, nChar, c, isError);
- if( isError ){
- sqlite3_free(pCsr);
- return SQLITE_ERROR;
- }
- pCsr->aOffset[iOut] = iInput;
-
- if( iInput<nInput ){
- U8_NEXT(zInput, iInput, nInput, c);
- }else{
- c = 0;
- }
- }
-
- pCsr->pIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status);
- if( !U_SUCCESS(status) ){
- sqlite3_free(pCsr);
- return SQLITE_ERROR;
- }
- pCsr->nChar = iOut;
-
- ubrk_first(pCsr->pIter);
- *ppCursor = (sqlite3_tokenizer_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to icuOpen().
-*/
-static int icuClose(sqlite3_tokenizer_cursor *pCursor){
- IcuCursor *pCsr = (IcuCursor *)pCursor;
- ubrk_close(pCsr->pIter);
- sqlite3_free(pCsr->zBuffer);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Extract the next token from a tokenization cursor.
-*/
-static int icuNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
- const char **ppToken, /* OUT: *ppToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- IcuCursor *pCsr = (IcuCursor *)pCursor;
-
- int iStart = 0;
- int iEnd = 0;
- int nByte = 0;
-
- while( iStart==iEnd ){
- UChar32 c;
-
- iStart = ubrk_current(pCsr->pIter);
- iEnd = ubrk_next(pCsr->pIter);
- if( iEnd==UBRK_DONE ){
- return SQLITE_DONE;
- }
-
- while( iStart<iEnd ){
- int iWhite = iStart;
- U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
- if( u_isspace(c) ){
- iStart = iWhite;
- }else{
- break;
- }
- }
- assert(iStart<=iEnd);
- }
-
- do {
- UErrorCode status = U_ZERO_ERROR;
- if( nByte ){
- char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- pCsr->zBuffer = zNew;
- pCsr->nBuffer = nByte;
- }
-
- u_strToUTF8(
- pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */
- &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */
- &status /* Output success/failure */
- );
- } while( nByte>pCsr->nBuffer );
-
- *ppToken = pCsr->zBuffer;
- *pnBytes = nByte;
- *piStartOffset = pCsr->aOffset[iStart];
- *piEndOffset = pCsr->aOffset[iEnd];
- *piPosition = pCsr->iToken++;
-
- return SQLITE_OK;
-}
-
-/*
-** The set of routines that implement the simple tokenizer
-*/
-static const sqlite3_tokenizer_module icuTokenizerModule = {
- 0, /* iVersion */
- icuCreate, /* xCreate */
- icuDestroy, /* xCreate */
- icuOpen, /* xOpen */
- icuClose, /* xClose */
- icuNext, /* xNext */
- 0, /* xLanguageid */
-};
-
-/*
-** Set *ppModule to point at the implementation of the ICU tokenizer.
-*/
-void sqlite3Fts3IcuTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &icuTokenizerModule;
-}
-
-#endif /* defined(SQLITE_ENABLE_ICU) */
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_porter.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_porter.c
deleted file mode 100644
index 8fb4c25daa0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_porter.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
-** 2006 September 30
-**
-** 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.
-**
-*************************************************************************
-** Implementation of the full-text-search tokenizer that implements
-** a Porter stemmer.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS3 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS3 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
-*/
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "fts3_tokenizer.h"
-
-/*
-** Class derived from sqlite3_tokenizer
-*/
-typedef struct porter_tokenizer {
- sqlite3_tokenizer base; /* Base class */
-} porter_tokenizer;
-
-/*
-** Class derived from sqlite3_tokenizer_cursor
-*/
-typedef struct porter_tokenizer_cursor {
- sqlite3_tokenizer_cursor base;
- const char *zInput; /* input we are tokenizing */
- int nInput; /* size of the input */
- int iOffset; /* current position in zInput */
- int iToken; /* index of next token to be returned */
- char *zToken; /* storage for current token */
- int nAllocated; /* space allocated to zToken buffer */
-} porter_tokenizer_cursor;
-
-
-/*
-** Create a new tokenizer instance.
-*/
-static int porterCreate(
- int argc, const char * const *argv,
- sqlite3_tokenizer **ppTokenizer
-){
- porter_tokenizer *t;
-
- UNUSED_PARAMETER(argc);
- UNUSED_PARAMETER(argv);
-
- t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t));
- if( t==NULL ) return SQLITE_NOMEM;
- memset(t, 0, sizeof(*t));
- *ppTokenizer = &t->base;
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int porterDestroy(sqlite3_tokenizer *pTokenizer){
- sqlite3_free(pTokenizer);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is zInput[0..nInput-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int porterOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *zInput, int nInput, /* String to be tokenized */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- porter_tokenizer_cursor *c;
-
- UNUSED_PARAMETER(pTokenizer);
-
- c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
- if( c==NULL ) return SQLITE_NOMEM;
-
- c->zInput = zInput;
- if( zInput==0 ){
- c->nInput = 0;
- }else if( nInput<0 ){
- c->nInput = (int)strlen(zInput);
- }else{
- c->nInput = nInput;
- }
- c->iOffset = 0; /* start tokenizing at the beginning */
- c->iToken = 0;
- c->zToken = NULL; /* no space allocated, yet. */
- c->nAllocated = 0;
-
- *ppCursor = &c->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to
-** porterOpen() above.
-*/
-static int porterClose(sqlite3_tokenizer_cursor *pCursor){
- porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
- sqlite3_free(c->zToken);
- sqlite3_free(c);
- return SQLITE_OK;
-}
-/*
-** Vowel or consonant
-*/
-static const char cType[] = {
- 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
- 1, 1, 1, 2, 1
-};
-
-/*
-** isConsonant() and isVowel() determine if their first character in
-** the string they point to is a consonant or a vowel, according
-** to Porter ruls.
-**
-** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
-** 'Y' is a consonant unless it follows another consonant,
-** in which case it is a vowel.
-**
-** In these routine, the letters are in reverse order. So the 'y' rule
-** is that 'y' is a consonant unless it is followed by another
-** consonent.
-*/
-static int isVowel(const char*);
-static int isConsonant(const char *z){
- int j;
- char x = *z;
- if( x==0 ) return 0;
- assert( x>='a' && x<='z' );
- j = cType[x-'a'];
- if( j<2 ) return j;
- return z[1]==0 || isVowel(z + 1);
-}
-static int isVowel(const char *z){
- int j;
- char x = *z;
- if( x==0 ) return 0;
- assert( x>='a' && x<='z' );
- j = cType[x-'a'];
- if( j<2 ) return 1-j;
- return isConsonant(z + 1);
-}
-
-/*
-** Let any sequence of one or more vowels be represented by V and let
-** C be sequence of one or more consonants. Then every word can be
-** represented as:
-**
-** [C] (VC){m} [V]
-**
-** In prose: A word is an optional consonant followed by zero or
-** vowel-consonant pairs followed by an optional vowel. "m" is the
-** number of vowel consonant pairs. This routine computes the value
-** of m for the first i bytes of a word.
-**
-** Return true if the m-value for z is 1 or more. In other words,
-** return true if z contains at least one vowel that is followed
-** by a consonant.
-**
-** In this routine z[] is in reverse order. So we are really looking
-** for an instance of a consonant followed by a vowel.
-*/
-static int m_gt_0(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/* Like mgt0 above except we are looking for a value of m which is
-** exactly 1
-*/
-static int m_eq_1(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 1;
- while( isConsonant(z) ){ z++; }
- return *z==0;
-}
-
-/* Like mgt0 above except we are looking for a value of m>1 instead
-** or m>0
-*/
-static int m_gt_1(const char *z){
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isVowel(z) ){ z++; }
- if( *z==0 ) return 0;
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/*
-** Return TRUE if there is a vowel anywhere within z[0..n-1]
-*/
-static int hasVowel(const char *z){
- while( isConsonant(z) ){ z++; }
- return *z!=0;
-}
-
-/*
-** Return TRUE if the word ends in a double consonant.
-**
-** The text is reversed here. So we are really looking at
-** the first two characters of z[].
-*/
-static int doubleConsonant(const char *z){
- return isConsonant(z) && z[0]==z[1];
-}
-
-/*
-** Return TRUE if the word ends with three letters which
-** are consonant-vowel-consonent and where the final consonant
-** is not 'w', 'x', or 'y'.
-**
-** The word is reversed here. So we are really checking the
-** first three letters and the first one cannot be in [wxy].
-*/
-static int star_oh(const char *z){
- return
- isConsonant(z) &&
- z[0]!='w' && z[0]!='x' && z[0]!='y' &&
- isVowel(z+1) &&
- isConsonant(z+2);
-}
-
-/*
-** If the word ends with zFrom and xCond() is true for the stem
-** of the word that preceeds the zFrom ending, then change the
-** ending to zTo.
-**
-** The input word *pz and zFrom are both in reverse order. zTo
-** is in normal order.
-**
-** Return TRUE if zFrom matches. Return FALSE if zFrom does not
-** match. Not that TRUE is returned even if xCond() fails and
-** no substitution occurs.
-*/
-static int stem(
- char **pz, /* The word being stemmed (Reversed) */
- const char *zFrom, /* If the ending matches this... (Reversed) */
- const char *zTo, /* ... change the ending to this (not reversed) */
- int (*xCond)(const char*) /* Condition that must be true */
-){
- char *z = *pz;
- while( *zFrom && *zFrom==*z ){ z++; zFrom++; }
- if( *zFrom!=0 ) return 0;
- if( xCond && !xCond(z) ) return 1;
- while( *zTo ){
- *(--z) = *(zTo++);
- }
- *pz = z;
- return 1;
-}
-
-/*
-** This is the fallback stemmer used when the porter stemmer is
-** inappropriate. The input word is copied into the output with
-** US-ASCII case folding. If the input word is too long (more
-** than 20 bytes if it contains no digits or more than 6 bytes if
-** it contains digits) then word is truncated to 20 or 6 bytes
-** by taking 10 or 3 bytes from the beginning and end.
-*/
-static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
- int i, mx, j;
- int hasDigit = 0;
- for(i=0; i<nIn; i++){
- char c = zIn[i];
- if( c>='A' && c<='Z' ){
- zOut[i] = c - 'A' + 'a';
- }else{
- if( c>='0' && c<='9' ) hasDigit = 1;
- zOut[i] = c;
- }
- }
- mx = hasDigit ? 3 : 10;
- if( nIn>mx*2 ){
- for(j=mx, i=nIn-mx; i<nIn; i++, j++){
- zOut[j] = zOut[i];
- }
- i = j;
- }
- zOut[i] = 0;
- *pnOut = i;
-}
-
-
-/*
-** Stem the input word zIn[0..nIn-1]. Store the output in zOut.
-** zOut is at least big enough to hold nIn bytes. Write the actual
-** size of the output word (exclusive of the '\0' terminator) into *pnOut.
-**
-** Any upper-case characters in the US-ASCII character set ([A-Z])
-** are converted to lower case. Upper-case UTF characters are
-** unchanged.
-**
-** Words that are longer than about 20 bytes are stemmed by retaining
-** a few bytes from the beginning and the end of the word. If the
-** word contains digits, 3 bytes are taken from the beginning and
-** 3 bytes from the end. For long words without digits, 10 bytes
-** are taken from each end. US-ASCII case folding still applies.
-**
-** If the input word contains not digits but does characters not
-** in [a-zA-Z] then no stemming is attempted and this routine just
-** copies the input into the input into the output with US-ASCII
-** case folding.
-**
-** Stemming never increases the length of the word. So there is
-** no chance of overflowing the zOut buffer.
-*/
-static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
- int i, j;
- char zReverse[28];
- char *z, *z2;
- if( nIn<3 || nIn>=(int)sizeof(zReverse)-7 ){
- /* The word is too big or too small for the porter stemmer.
- ** Fallback to the copy stemmer */
- copy_stemmer(zIn, nIn, zOut, pnOut);
- return;
- }
- for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){
- char c = zIn[i];
- if( c>='A' && c<='Z' ){
- zReverse[j] = c + 'a' - 'A';
- }else if( c>='a' && c<='z' ){
- zReverse[j] = c;
- }else{
- /* The use of a character not in [a-zA-Z] means that we fallback
- ** to the copy stemmer */
- copy_stemmer(zIn, nIn, zOut, pnOut);
- return;
- }
- }
- memset(&zReverse[sizeof(zReverse)-5], 0, 5);
- z = &zReverse[j+1];
-
-
- /* Step 1a */
- if( z[0]=='s' ){
- if(
- !stem(&z, "sess", "ss", 0) &&
- !stem(&z, "sei", "i", 0) &&
- !stem(&z, "ss", "ss", 0)
- ){
- z++;
- }
- }
-
- /* Step 1b */
- z2 = z;
- if( stem(&z, "dee", "ee", m_gt_0) ){
- /* Do nothing. The work was all in the test */
- }else if(
- (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel))
- && z!=z2
- ){
- if( stem(&z, "ta", "ate", 0) ||
- stem(&z, "lb", "ble", 0) ||
- stem(&z, "zi", "ize", 0) ){
- /* Do nothing. The work was all in the test */
- }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){
- z++;
- }else if( m_eq_1(z) && star_oh(z) ){
- *(--z) = 'e';
- }
- }
-
- /* Step 1c */
- if( z[0]=='y' && hasVowel(z+1) ){
- z[0] = 'i';
- }
-
- /* Step 2 */
- switch( z[1] ){
- case 'a':
- if( !stem(&z, "lanoita", "ate", m_gt_0) ){
- stem(&z, "lanoit", "tion", m_gt_0);
- }
- break;
- case 'c':
- if( !stem(&z, "icne", "ence", m_gt_0) ){
- stem(&z, "icna", "ance", m_gt_0);
- }
- break;
- case 'e':
- stem(&z, "rezi", "ize", m_gt_0);
- break;
- case 'g':
- stem(&z, "igol", "log", m_gt_0);
- break;
- case 'l':
- if( !stem(&z, "ilb", "ble", m_gt_0)
- && !stem(&z, "illa", "al", m_gt_0)
- && !stem(&z, "iltne", "ent", m_gt_0)
- && !stem(&z, "ile", "e", m_gt_0)
- ){
- stem(&z, "ilsuo", "ous", m_gt_0);
- }
- break;
- case 'o':
- if( !stem(&z, "noitazi", "ize", m_gt_0)
- && !stem(&z, "noita", "ate", m_gt_0)
- ){
- stem(&z, "rota", "ate", m_gt_0);
- }
- break;
- case 's':
- if( !stem(&z, "msila", "al", m_gt_0)
- && !stem(&z, "ssenevi", "ive", m_gt_0)
- && !stem(&z, "ssenluf", "ful", m_gt_0)
- ){
- stem(&z, "ssensuo", "ous", m_gt_0);
- }
- break;
- case 't':
- if( !stem(&z, "itila", "al", m_gt_0)
- && !stem(&z, "itivi", "ive", m_gt_0)
- ){
- stem(&z, "itilib", "ble", m_gt_0);
- }
- break;
- }
-
- /* Step 3 */
- switch( z[0] ){
- case 'e':
- if( !stem(&z, "etaci", "ic", m_gt_0)
- && !stem(&z, "evita", "", m_gt_0)
- ){
- stem(&z, "ezila", "al", m_gt_0);
- }
- break;
- case 'i':
- stem(&z, "itici", "ic", m_gt_0);
- break;
- case 'l':
- if( !stem(&z, "laci", "ic", m_gt_0) ){
- stem(&z, "luf", "", m_gt_0);
- }
- break;
- case 's':
- stem(&z, "ssen", "", m_gt_0);
- break;
- }
-
- /* Step 4 */
- switch( z[1] ){
- case 'a':
- if( z[0]=='l' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'c':
- if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){
- z += 4;
- }
- break;
- case 'e':
- if( z[0]=='r' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'i':
- if( z[0]=='c' && m_gt_1(z+2) ){
- z += 2;
- }
- break;
- case 'l':
- if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){
- z += 4;
- }
- break;
- case 'n':
- if( z[0]=='t' ){
- if( z[2]=='a' ){
- if( m_gt_1(z+3) ){
- z += 3;
- }
- }else if( z[2]=='e' ){
- if( !stem(&z, "tneme", "", m_gt_1)
- && !stem(&z, "tnem", "", m_gt_1)
- ){
- stem(&z, "tne", "", m_gt_1);
- }
- }
- }
- break;
- case 'o':
- if( z[0]=='u' ){
- if( m_gt_1(z+2) ){
- z += 2;
- }
- }else if( z[3]=='s' || z[3]=='t' ){
- stem(&z, "noi", "", m_gt_1);
- }
- break;
- case 's':
- if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- case 't':
- if( !stem(&z, "eta", "", m_gt_1) ){
- stem(&z, "iti", "", m_gt_1);
- }
- break;
- case 'u':
- if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- case 'v':
- case 'z':
- if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){
- z += 3;
- }
- break;
- }
-
- /* Step 5a */
- if( z[0]=='e' ){
- if( m_gt_1(z+1) ){
- z++;
- }else if( m_eq_1(z+1) && !star_oh(z+1) ){
- z++;
- }
- }
-
- /* Step 5b */
- if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){
- z++;
- }
-
- /* z[] is now the stemmed word in reverse order. Flip it back
- ** around into forward order and return.
- */
- *pnOut = i = (int)strlen(z);
- zOut[i] = 0;
- while( *z ){
- zOut[--i] = *(z++);
- }
-}
-
-/*
-** Characters that can be part of a token. We assume any character
-** whose value is greater than 0x80 (any UTF character) can be
-** part of a token. In other words, delimiters all must have
-** values of 0x7f or lower.
-*/
-static const char porterIdChar[] = {
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
-};
-#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30]))
-
-/*
-** Extract the next token from a tokenization cursor. The cursor must
-** have been opened by a prior call to porterOpen().
-*/
-static int porterNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */
- const char **pzToken, /* OUT: *pzToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
- const char *z = c->zInput;
-
- while( c->iOffset<c->nInput ){
- int iStartOffset, ch;
-
- /* Scan past delimiter characters */
- while( c->iOffset<c->nInput && isDelim(z[c->iOffset]) ){
- c->iOffset++;
- }
-
- /* Count non-delimiter characters. */
- iStartOffset = c->iOffset;
- while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
- c->iOffset++;
- }
-
- if( c->iOffset>iStartOffset ){
- int n = c->iOffset-iStartOffset;
- if( n>c->nAllocated ){
- char *pNew;
- c->nAllocated = n+20;
- pNew = sqlite3_realloc(c->zToken, c->nAllocated);
- if( !pNew ) return SQLITE_NOMEM;
- c->zToken = pNew;
- }
- porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
- *pzToken = c->zToken;
- *piStartOffset = iStartOffset;
- *piEndOffset = c->iOffset;
- *piPosition = c->iToken++;
- return SQLITE_OK;
- }
- }
- return SQLITE_DONE;
-}
-
-/*
-** The set of routines that implement the porter-stemmer tokenizer
-*/
-static const sqlite3_tokenizer_module porterTokenizerModule = {
- 0,
- porterCreate,
- porterDestroy,
- porterOpen,
- porterClose,
- porterNext,
- 0
-};
-
-/*
-** Allocate a new porter tokenizer. Return a pointer to the new
-** tokenizer in *ppModule
-*/
-void sqlite3Fts3PorterTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &porterTokenizerModule;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_snippet.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_snippet.c
deleted file mode 100644
index a0771c0b305..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_snippet.c
+++ /dev/null
@@ -1,1706 +0,0 @@
-/*
-** 2009 Oct 23
-**
-** 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.
-**
-******************************************************************************
-*/
-
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <string.h>
-#include <assert.h>
-
-/*
-** Characters that may appear in the second argument to matchinfo().
-*/
-#define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */
-#define FTS3_MATCHINFO_NCOL 'c' /* 1 value */
-#define FTS3_MATCHINFO_NDOC 'n' /* 1 value */
-#define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */
-#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */
-#define FTS3_MATCHINFO_LCS 's' /* nCol values */
-#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */
-#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */
-#define FTS3_MATCHINFO_LHITS_BM 'b' /* nCol*nPhrase values */
-
-/*
-** The default value for the second argument to matchinfo().
-*/
-#define FTS3_MATCHINFO_DEFAULT "pcx"
-
-
-/*
-** Used as an fts3ExprIterate() context when loading phrase doclists to
-** Fts3Expr.aDoclist[]/nDoclist.
-*/
-typedef struct LoadDoclistCtx LoadDoclistCtx;
-struct LoadDoclistCtx {
- Fts3Cursor *pCsr; /* FTS3 Cursor */
- int nPhrase; /* Number of phrases seen so far */
- int nToken; /* Number of tokens seen so far */
-};
-
-/*
-** The following types are used as part of the implementation of the
-** fts3BestSnippet() routine.
-*/
-typedef struct SnippetIter SnippetIter;
-typedef struct SnippetPhrase SnippetPhrase;
-typedef struct SnippetFragment SnippetFragment;
-
-struct SnippetIter {
- Fts3Cursor *pCsr; /* Cursor snippet is being generated from */
- int iCol; /* Extract snippet from this column */
- int nSnippet; /* Requested snippet length (in tokens) */
- int nPhrase; /* Number of phrases in query */
- SnippetPhrase *aPhrase; /* Array of size nPhrase */
- int iCurrent; /* First token of current snippet */
-};
-
-struct SnippetPhrase {
- int nToken; /* Number of tokens in phrase */
- char *pList; /* Pointer to start of phrase position list */
- int iHead; /* Next value in position list */
- char *pHead; /* Position list data following iHead */
- int iTail; /* Next value in trailing position list */
- char *pTail; /* Position list data following iTail */
-};
-
-struct SnippetFragment {
- int iCol; /* Column snippet is extracted from */
- int iPos; /* Index of first token in snippet */
- u64 covered; /* Mask of query phrases covered */
- u64 hlmask; /* Mask of snippet terms to highlight */
-};
-
-/*
-** This type is used as an fts3ExprIterate() context object while
-** accumulating the data returned by the matchinfo() function.
-*/
-typedef struct MatchInfo MatchInfo;
-struct MatchInfo {
- Fts3Cursor *pCursor; /* FTS3 Cursor */
- int nCol; /* Number of columns in table */
- int nPhrase; /* Number of matchable phrases in query */
- sqlite3_int64 nDoc; /* Number of docs in database */
- char flag;
- u32 *aMatchinfo; /* Pre-allocated buffer */
-};
-
-/*
-** An instance of this structure is used to manage a pair of buffers, each
-** (nElem * sizeof(u32)) bytes in size. See the MatchinfoBuffer code below
-** for details.
-*/
-struct MatchinfoBuffer {
- u8 aRef[3];
- int nElem;
- int bGlobal; /* Set if global data is loaded */
- char *zMatchinfo;
- u32 aMatchinfo[1];
-};
-
-
-/*
-** The snippet() and offsets() functions both return text values. An instance
-** of the following structure is used to accumulate those values while the
-** functions are running. See fts3StringAppend() for details.
-*/
-typedef struct StrBuffer StrBuffer;
-struct StrBuffer {
- char *z; /* Pointer to buffer containing string */
- int n; /* Length of z in bytes (excl. nul-term) */
- int nAlloc; /* Allocated size of buffer z in bytes */
-};
-
-
-/*************************************************************************
-** Start of MatchinfoBuffer code.
-*/
-
-/*
-** Allocate a two-slot MatchinfoBuffer object.
-*/
-static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){
- MatchinfoBuffer *pRet;
- int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer);
- int nStr = (int)strlen(zMatchinfo);
-
- pRet = sqlite3_malloc(nByte + nStr+1);
- if( pRet ){
- memset(pRet, 0, nByte);
- pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
- pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1);
- pRet->nElem = nElem;
- pRet->zMatchinfo = ((char*)pRet) + nByte;
- memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
- pRet->aRef[0] = 1;
- }
-
- return pRet;
-}
-
-static void fts3MIBufferFree(void *p){
- MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
-
- assert( (u32*)p==&pBuf->aMatchinfo[1]
- || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
- );
- if( (u32*)p==&pBuf->aMatchinfo[1] ){
- pBuf->aRef[1] = 0;
- }else{
- pBuf->aRef[2] = 0;
- }
-
- if( pBuf->aRef[0]==0 && pBuf->aRef[1]==0 && pBuf->aRef[2]==0 ){
- sqlite3_free(pBuf);
- }
-}
-
-static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
- void (*xRet)(void*) = 0;
- u32 *aOut = 0;
-
- if( p->aRef[1]==0 ){
- p->aRef[1] = 1;
- aOut = &p->aMatchinfo[1];
- xRet = fts3MIBufferFree;
- }
- else if( p->aRef[2]==0 ){
- p->aRef[2] = 1;
- aOut = &p->aMatchinfo[p->nElem+2];
- xRet = fts3MIBufferFree;
- }else{
- aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32));
- if( aOut ){
- xRet = sqlite3_free;
- if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
- }
- }
-
- *paOut = aOut;
- return xRet;
-}
-
-static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
- p->bGlobal = 1;
- memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
-}
-
-/*
-** Free a MatchinfoBuffer object allocated using fts3MIBufferNew()
-*/
-void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){
- if( p ){
- assert( p->aRef[0]==1 );
- p->aRef[0] = 0;
- if( p->aRef[0]==0 && p->aRef[1]==0 && p->aRef[2]==0 ){
- sqlite3_free(p);
- }
- }
-}
-
-/*
-** End of MatchinfoBuffer code.
-*************************************************************************/
-
-
-/*
-** This function is used to help iterate through a position-list. A position
-** list is a list of unique integers, sorted from smallest to largest. Each
-** element of the list is represented by an FTS3 varint that takes the value
-** of the difference between the current element and the previous one plus
-** two. For example, to store the position-list:
-**
-** 4 9 113
-**
-** the three varints:
-**
-** 6 7 106
-**
-** are encoded.
-**
-** When this function is called, *pp points to the start of an element of
-** the list. *piPos contains the value of the previous entry in the list.
-** After it returns, *piPos contains the value of the next element of the
-** list and *pp is advanced to the following varint.
-*/
-static void fts3GetDeltaPosition(char **pp, int *piPos){
- int iVal;
- *pp += fts3GetVarint32(*pp, &iVal);
- *piPos += (iVal-2);
-}
-
-/*
-** Helper function for fts3ExprIterate() (see below).
-*/
-static int fts3ExprIterate2(
- Fts3Expr *pExpr, /* Expression to iterate phrases of */
- int *piPhrase, /* Pointer to phrase counter */
- int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
- void *pCtx /* Second argument to pass to callback */
-){
- int rc; /* Return code */
- int eType = pExpr->eType; /* Type of expression node pExpr */
-
- if( eType!=FTSQUERY_PHRASE ){
- assert( pExpr->pLeft && pExpr->pRight );
- rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx);
- if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){
- rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx);
- }
- }else{
- rc = x(pExpr, *piPhrase, pCtx);
- (*piPhrase)++;
- }
- return rc;
-}
-
-/*
-** Iterate through all phrase nodes in an FTS3 query, except those that
-** are part of a sub-tree that is the right-hand-side of a NOT operator.
-** For each phrase node found, the supplied callback function is invoked.
-**
-** If the callback function returns anything other than SQLITE_OK,
-** the iteration is abandoned and the error code returned immediately.
-** Otherwise, SQLITE_OK is returned after a callback has been made for
-** all eligible phrase nodes.
-*/
-static int fts3ExprIterate(
- Fts3Expr *pExpr, /* Expression to iterate phrases of */
- int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
- void *pCtx /* Second argument to pass to callback */
-){
- int iPhrase = 0; /* Variable used as the phrase counter */
- return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
-}
-
-
-/*
-** This is an fts3ExprIterate() callback used while loading the doclists
-** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
-** fts3ExprLoadDoclists().
-*/
-static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
- int rc = SQLITE_OK;
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
-
- UNUSED_PARAMETER(iPhrase);
-
- p->nPhrase++;
- p->nToken += pPhrase->nToken;
-
- return rc;
-}
-
-/*
-** Load the doclists for each phrase in the query associated with FTS3 cursor
-** pCsr.
-**
-** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable
-** phrases in the expression (all phrases except those directly or
-** indirectly descended from the right-hand-side of a NOT operator). If
-** pnToken is not NULL, then it is set to the number of tokens in all
-** matchable phrases of the expression.
-*/
-static int fts3ExprLoadDoclists(
- Fts3Cursor *pCsr, /* Fts3 cursor for current query */
- int *pnPhrase, /* OUT: Number of phrases in query */
- int *pnToken /* OUT: Number of tokens in query */
-){
- int rc; /* Return Code */
- LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */
- sCtx.pCsr = pCsr;
- rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx);
- if( pnPhrase ) *pnPhrase = sCtx.nPhrase;
- if( pnToken ) *pnToken = sCtx.nToken;
- return rc;
-}
-
-static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
- (*(int *)ctx)++;
- pExpr->iPhrase = iPhrase;
- return SQLITE_OK;
-}
-static int fts3ExprPhraseCount(Fts3Expr *pExpr){
- int nPhrase = 0;
- (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase);
- return nPhrase;
-}
-
-/*
-** Advance the position list iterator specified by the first two
-** arguments so that it points to the first element with a value greater
-** than or equal to parameter iNext.
-*/
-static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
- char *pIter = *ppIter;
- if( pIter ){
- int iIter = *piIter;
-
- while( iIter<iNext ){
- if( 0==(*pIter & 0xFE) ){
- iIter = -1;
- pIter = 0;
- break;
- }
- fts3GetDeltaPosition(&pIter, &iIter);
- }
-
- *piIter = iIter;
- *ppIter = pIter;
- }
-}
-
-/*
-** Advance the snippet iterator to the next candidate snippet.
-*/
-static int fts3SnippetNextCandidate(SnippetIter *pIter){
- int i; /* Loop counter */
-
- if( pIter->iCurrent<0 ){
- /* The SnippetIter object has just been initialized. The first snippet
- ** candidate always starts at offset 0 (even if this candidate has a
- ** score of 0.0).
- */
- pIter->iCurrent = 0;
-
- /* Advance the 'head' iterator of each phrase to the first offset that
- ** is greater than or equal to (iNext+nSnippet).
- */
- for(i=0; i<pIter->nPhrase; i++){
- SnippetPhrase *pPhrase = &pIter->aPhrase[i];
- fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet);
- }
- }else{
- int iStart;
- int iEnd = 0x7FFFFFFF;
-
- for(i=0; i<pIter->nPhrase; i++){
- SnippetPhrase *pPhrase = &pIter->aPhrase[i];
- if( pPhrase->pHead && pPhrase->iHead<iEnd ){
- iEnd = pPhrase->iHead;
- }
- }
- if( iEnd==0x7FFFFFFF ){
- return 1;
- }
-
- pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1;
- for(i=0; i<pIter->nPhrase; i++){
- SnippetPhrase *pPhrase = &pIter->aPhrase[i];
- fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1);
- fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart);
- }
- }
-
- return 0;
-}
-
-/*
-** Retrieve information about the current candidate snippet of snippet
-** iterator pIter.
-*/
-static void fts3SnippetDetails(
- SnippetIter *pIter, /* Snippet iterator */
- u64 mCovered, /* Bitmask of phrases already covered */
- int *piToken, /* OUT: First token of proposed snippet */
- int *piScore, /* OUT: "Score" for this snippet */
- u64 *pmCover, /* OUT: Bitmask of phrases covered */
- u64 *pmHighlight /* OUT: Bitmask of terms to highlight */
-){
- int iStart = pIter->iCurrent; /* First token of snippet */
- int iScore = 0; /* Score of this snippet */
- int i; /* Loop counter */
- u64 mCover = 0; /* Mask of phrases covered by this snippet */
- u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */
-
- for(i=0; i<pIter->nPhrase; i++){
- SnippetPhrase *pPhrase = &pIter->aPhrase[i];
- if( pPhrase->pTail ){
- char *pCsr = pPhrase->pTail;
- int iCsr = pPhrase->iTail;
-
- while( iCsr<(iStart+pIter->nSnippet) ){
- int j;
- u64 mPhrase = (u64)1 << i;
- u64 mPos = (u64)1 << (iCsr - iStart);
- assert( iCsr>=iStart );
- if( (mCover|mCovered)&mPhrase ){
- iScore++;
- }else{
- iScore += 1000;
- }
- mCover |= mPhrase;
-
- for(j=0; j<pPhrase->nToken; j++){
- mHighlight |= (mPos>>j);
- }
-
- if( 0==(*pCsr & 0x0FE) ) break;
- fts3GetDeltaPosition(&pCsr, &iCsr);
- }
- }
- }
-
- /* Set the output variables before returning. */
- *piToken = iStart;
- *piScore = iScore;
- *pmCover = mCover;
- *pmHighlight = mHighlight;
-}
-
-/*
-** This function is an fts3ExprIterate() callback used by fts3BestSnippet().
-** Each invocation populates an element of the SnippetIter.aPhrase[] array.
-*/
-static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
- SnippetIter *p = (SnippetIter *)ctx;
- SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
- char *pCsr;
- int rc;
-
- pPhrase->nToken = pExpr->pPhrase->nToken;
- rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
- assert( rc==SQLITE_OK || pCsr==0 );
- if( pCsr ){
- int iFirst = 0;
- pPhrase->pList = pCsr;
- fts3GetDeltaPosition(&pCsr, &iFirst);
- assert( iFirst>=0 );
- pPhrase->pHead = pCsr;
- pPhrase->pTail = pCsr;
- pPhrase->iHead = iFirst;
- pPhrase->iTail = iFirst;
- }else{
- assert( rc!=SQLITE_OK || (
- pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0
- ));
- }
-
- return rc;
-}
-
-/*
-** Select the fragment of text consisting of nFragment contiguous tokens
-** from column iCol that represent the "best" snippet. The best snippet
-** is the snippet with the highest score, where scores are calculated
-** by adding:
-**
-** (a) +1 point for each occurrence of a matchable phrase in the snippet.
-**
-** (b) +1000 points for the first occurrence of each matchable phrase in
-** the snippet for which the corresponding mCovered bit is not set.
-**
-** The selected snippet parameters are stored in structure *pFragment before
-** returning. The score of the selected snippet is stored in *piScore
-** before returning.
-*/
-static int fts3BestSnippet(
- int nSnippet, /* Desired snippet length */
- Fts3Cursor *pCsr, /* Cursor to create snippet for */
- int iCol, /* Index of column to create snippet from */
- u64 mCovered, /* Mask of phrases already covered */
- u64 *pmSeen, /* IN/OUT: Mask of phrases seen */
- SnippetFragment *pFragment, /* OUT: Best snippet found */
- int *piScore /* OUT: Score of snippet pFragment */
-){
- int rc; /* Return Code */
- int nList; /* Number of phrases in expression */
- SnippetIter sIter; /* Iterates through snippet candidates */
- int nByte; /* Number of bytes of space to allocate */
- int iBestScore = -1; /* Best snippet score found so far */
- int i; /* Loop counter */
-
- memset(&sIter, 0, sizeof(sIter));
-
- /* Iterate through the phrases in the expression to count them. The same
- ** callback makes sure the doclists are loaded for each phrase.
- */
- rc = fts3ExprLoadDoclists(pCsr, &nList, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Now that it is known how many phrases there are, allocate and zero
- ** the required space using malloc().
- */
- nByte = sizeof(SnippetPhrase) * nList;
- sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
- if( !sIter.aPhrase ){
- return SQLITE_NOMEM;
- }
- memset(sIter.aPhrase, 0, nByte);
-
- /* Initialize the contents of the SnippetIter object. Then iterate through
- ** the set of phrases in the expression to populate the aPhrase[] array.
- */
- sIter.pCsr = pCsr;
- sIter.iCol = iCol;
- sIter.nSnippet = nSnippet;
- sIter.nPhrase = nList;
- sIter.iCurrent = -1;
- rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter);
- if( rc==SQLITE_OK ){
-
- /* Set the *pmSeen output variable. */
- for(i=0; i<nList; i++){
- if( sIter.aPhrase[i].pHead ){
- *pmSeen |= (u64)1 << i;
- }
- }
-
- /* Loop through all candidate snippets. Store the best snippet in
- ** *pFragment. Store its associated 'score' in iBestScore.
- */
- pFragment->iCol = iCol;
- while( !fts3SnippetNextCandidate(&sIter) ){
- int iPos;
- int iScore;
- u64 mCover;
- u64 mHighlite;
- fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover,&mHighlite);
- assert( iScore>=0 );
- if( iScore>iBestScore ){
- pFragment->iPos = iPos;
- pFragment->hlmask = mHighlite;
- pFragment->covered = mCover;
- iBestScore = iScore;
- }
- }
-
- *piScore = iBestScore;
- }
- sqlite3_free(sIter.aPhrase);
- return rc;
-}
-
-
-/*
-** Append a string to the string-buffer passed as the first argument.
-**
-** If nAppend is negative, then the length of the string zAppend is
-** determined using strlen().
-*/
-static int fts3StringAppend(
- StrBuffer *pStr, /* Buffer to append to */
- const char *zAppend, /* Pointer to data to append to buffer */
- int nAppend /* Size of zAppend in bytes (or -1) */
-){
- if( nAppend<0 ){
- nAppend = (int)strlen(zAppend);
- }
-
- /* If there is insufficient space allocated at StrBuffer.z, use realloc()
- ** to grow the buffer until so that it is big enough to accomadate the
- ** appended data.
- */
- if( pStr->n+nAppend+1>=pStr->nAlloc ){
- int nAlloc = pStr->nAlloc+nAppend+100;
- char *zNew = sqlite3_realloc(pStr->z, nAlloc);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- pStr->z = zNew;
- pStr->nAlloc = nAlloc;
- }
- assert( pStr->z!=0 && (pStr->nAlloc >= pStr->n+nAppend+1) );
-
- /* Append the data to the string buffer. */
- memcpy(&pStr->z[pStr->n], zAppend, nAppend);
- pStr->n += nAppend;
- pStr->z[pStr->n] = '\0';
-
- return SQLITE_OK;
-}
-
-/*
-** The fts3BestSnippet() function often selects snippets that end with a
-** query term. That is, the final term of the snippet is always a term
-** that requires highlighting. For example, if 'X' is a highlighted term
-** and '.' is a non-highlighted term, BestSnippet() may select:
-**
-** ........X.....X
-**
-** This function "shifts" the beginning of the snippet forward in the
-** document so that there are approximately the same number of
-** non-highlighted terms to the right of the final highlighted term as there
-** are to the left of the first highlighted term. For example, to this:
-**
-** ....X.....X....
-**
-** This is done as part of extracting the snippet text, not when selecting
-** the snippet. Snippet selection is done based on doclists only, so there
-** is no way for fts3BestSnippet() to know whether or not the document
-** actually contains terms that follow the final highlighted term.
-*/
-static int fts3SnippetShift(
- Fts3Table *pTab, /* FTS3 table snippet comes from */
- int iLangid, /* Language id to use in tokenizing */
- int nSnippet, /* Number of tokens desired for snippet */
- const char *zDoc, /* Document text to extract snippet from */
- int nDoc, /* Size of buffer zDoc in bytes */
- int *piPos, /* IN/OUT: First token of snippet */
- u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */
-){
- u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */
-
- if( hlmask ){
- int nLeft; /* Tokens to the left of first highlight */
- int nRight; /* Tokens to the right of last highlight */
- int nDesired; /* Ideal number of tokens to shift forward */
-
- for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
- for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
- nDesired = (nLeft-nRight)/2;
-
- /* Ideally, the start of the snippet should be pushed forward in the
- ** document nDesired tokens. This block checks if there are actually
- ** nDesired tokens to the right of the snippet. If so, *piPos and
- ** *pHlMask are updated to shift the snippet nDesired tokens to the
- ** right. Otherwise, the snippet is shifted by the number of tokens
- ** available.
- */
- if( nDesired>0 ){
- int nShift; /* Number of tokens to shift snippet by */
- int iCurrent = 0; /* Token counter */
- int rc; /* Return Code */
- sqlite3_tokenizer_module *pMod;
- sqlite3_tokenizer_cursor *pC;
- pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
-
- /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired)
- ** or more tokens in zDoc/nDoc.
- */
- rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
- const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0;
- rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
- }
- pMod->xClose(pC);
- if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; }
-
- nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet;
- assert( nShift<=nDesired );
- if( nShift>0 ){
- *piPos += nShift;
- *pHlmask = hlmask >> nShift;
- }
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Extract the snippet text for fragment pFragment from cursor pCsr and
-** append it to string buffer pOut.
-*/
-static int fts3SnippetText(
- Fts3Cursor *pCsr, /* FTS3 Cursor */
- SnippetFragment *pFragment, /* Snippet to extract */
- int iFragment, /* Fragment number */
- int isLast, /* True for final fragment in snippet */
- int nSnippet, /* Number of tokens in extracted snippet */
- const char *zOpen, /* String inserted before highlighted term */
- const char *zClose, /* String inserted after highlighted term */
- const char *zEllipsis, /* String inserted between snippets */
- StrBuffer *pOut /* Write output here */
-){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int rc; /* Return code */
- const char *zDoc; /* Document text to extract snippet from */
- int nDoc; /* Size of zDoc in bytes */
- int iCurrent = 0; /* Current token number of document */
- int iEnd = 0; /* Byte offset of end of current token */
- int isShiftDone = 0; /* True after snippet is shifted */
- int iPos = pFragment->iPos; /* First token of snippet */
- u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */
- int iCol = pFragment->iCol+1; /* Query column to extract text from */
- sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
- sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */
-
- zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
- if( zDoc==0 ){
- if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){
- return SQLITE_NOMEM;
- }
- return SQLITE_OK;
- }
- nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);
-
- /* Open a token cursor on the document. */
- pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
- rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- while( rc==SQLITE_OK ){
- const char *ZDUMMY; /* Dummy argument used with tokenizer */
- int DUMMY1 = -1; /* Dummy argument used with tokenizer */
- int iBegin = 0; /* Offset in zDoc of start of token */
- int iFin = 0; /* Offset in zDoc of end of token */
- int isHighlight = 0; /* True for highlighted terms */
-
- /* Variable DUMMY1 is initialized to a negative value above. Elsewhere
- ** in the FTS code the variable that the third argument to xNext points to
- ** is initialized to zero before the first (*but not necessarily
- ** subsequent*) call to xNext(). This is done for a particular application
- ** that needs to know whether or not the tokenizer is being used for
- ** snippet generation or for some other purpose.
- **
- ** Extreme care is required when writing code to depend on this
- ** initialization. It is not a documented part of the tokenizer interface.
- ** If a tokenizer is used directly by any code outside of FTS, this
- ** convention might not be respected. */
- rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_DONE ){
- /* Special case - the last token of the snippet is also the last token
- ** of the column. Append any punctuation that occurred between the end
- ** of the previous token and the end of the document to the output.
- ** Then break out of the loop. */
- rc = fts3StringAppend(pOut, &zDoc[iEnd], -1);
- }
- break;
- }
- if( iCurrent<iPos ){ continue; }
-
- if( !isShiftDone ){
- int n = nDoc - iBegin;
- rc = fts3SnippetShift(
- pTab, pCsr->iLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask
- );
- isShiftDone = 1;
-
- /* Now that the shift has been done, check if the initial "..." are
- ** required. They are required if (a) this is not the first fragment,
- ** or (b) this fragment does not begin at position 0 of its column.
- */
- if( rc==SQLITE_OK ){
- if( iPos>0 || iFragment>0 ){
- rc = fts3StringAppend(pOut, zEllipsis, -1);
- }else if( iBegin ){
- rc = fts3StringAppend(pOut, zDoc, iBegin);
- }
- }
- if( rc!=SQLITE_OK || iCurrent<iPos ) continue;
- }
-
- if( iCurrent>=(iPos+nSnippet) ){
- if( isLast ){
- rc = fts3StringAppend(pOut, zEllipsis, -1);
- }
- break;
- }
-
- /* Set isHighlight to true if this term should be highlighted. */
- isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0;
-
- if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd);
- if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1);
- if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin);
- if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1);
-
- iEnd = iFin;
- }
-
- pMod->xClose(pC);
- return rc;
-}
-
-
-/*
-** This function is used to count the entries in a column-list (a
-** delta-encoded list of term offsets within a single column of a single
-** row). When this function is called, *ppCollist should point to the
-** beginning of the first varint in the column-list (the varint that
-** contains the position of the first matching term in the column data).
-** Before returning, *ppCollist is set to point to the first byte after
-** the last varint in the column-list (either the 0x00 signifying the end
-** of the position-list, or the 0x01 that precedes the column number of
-** the next column in the position-list).
-**
-** The number of elements in the column-list is returned.
-*/
-static int fts3ColumnlistCount(char **ppCollist){
- char *pEnd = *ppCollist;
- char c = 0;
- int nEntry = 0;
-
- /* A column-list is terminated by either a 0x01 or 0x00. */
- while( 0xFE & (*pEnd | c) ){
- c = *pEnd++ & 0x80;
- if( !c ) nEntry++;
- }
-
- *ppCollist = pEnd;
- return nEntry;
-}
-
-/*
-** This function gathers 'y' or 'b' data for a single phrase.
-*/
-static void fts3ExprLHits(
- Fts3Expr *pExpr, /* Phrase expression node */
- MatchInfo *p /* Matchinfo context */
-){
- Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab;
- int iStart;
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- char *pIter = pPhrase->doclist.pList;
- int iCol = 0;
-
- assert( p->flag==FTS3_MATCHINFO_LHITS_BM || p->flag==FTS3_MATCHINFO_LHITS );
- if( p->flag==FTS3_MATCHINFO_LHITS ){
- iStart = pExpr->iPhrase * p->nCol;
- }else{
- iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
- }
-
- while( 1 ){
- int nHit = fts3ColumnlistCount(&pIter);
- if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
- if( p->flag==FTS3_MATCHINFO_LHITS ){
- p->aMatchinfo[iStart + iCol] = (u32)nHit;
- }else if( nHit ){
- p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
- }
- }
- assert( *pIter==0x00 || *pIter==0x01 );
- if( *pIter!=0x01 ) break;
- pIter++;
- pIter += fts3GetVarint32(pIter, &iCol);
- }
-}
-
-/*
-** Gather the results for matchinfo directives 'y' and 'b'.
-*/
-static void fts3ExprLHitGather(
- Fts3Expr *pExpr,
- MatchInfo *p
-){
- assert( (pExpr->pLeft==0)==(pExpr->pRight==0) );
- if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
- if( pExpr->pLeft ){
- fts3ExprLHitGather(pExpr->pLeft, p);
- fts3ExprLHitGather(pExpr->pRight, p);
- }else{
- fts3ExprLHits(pExpr, p);
- }
- }
-}
-
-/*
-** fts3ExprIterate() callback used to collect the "global" matchinfo stats
-** for a single query.
-**
-** fts3ExprIterate() callback to load the 'global' elements of a
-** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements
-** of the matchinfo array that are constant for all rows returned by the
-** current query.
-**
-** Argument pCtx is actually a pointer to a struct of type MatchInfo. This
-** function populates Matchinfo.aMatchinfo[] as follows:
-**
-** for(iCol=0; iCol<nCol; iCol++){
-** aMatchinfo[3*iPhrase*nCol + 3*iCol + 1] = X;
-** aMatchinfo[3*iPhrase*nCol + 3*iCol + 2] = Y;
-** }
-**
-** where X is the number of matches for phrase iPhrase is column iCol of all
-** rows of the table. Y is the number of rows for which column iCol contains
-** at least one instance of phrase iPhrase.
-**
-** If the phrase pExpr consists entirely of deferred tokens, then all X and
-** Y values are set to nDoc, where nDoc is the number of documents in the
-** file system. This is done because the full-text index doclist is required
-** to calculate these values properly, and the full-text index doclist is
-** not available for deferred tokens.
-*/
-static int fts3ExprGlobalHitsCb(
- Fts3Expr *pExpr, /* Phrase expression node */
- int iPhrase, /* Phrase number (numbered from zero) */
- void *pCtx /* Pointer to MatchInfo structure */
-){
- MatchInfo *p = (MatchInfo *)pCtx;
- return sqlite3Fts3EvalPhraseStats(
- p->pCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol]
- );
-}
-
-/*
-** fts3ExprIterate() callback used to collect the "local" part of the
-** FTS3_MATCHINFO_HITS array. The local stats are those elements of the
-** array that are different for each row returned by the query.
-*/
-static int fts3ExprLocalHitsCb(
- Fts3Expr *pExpr, /* Phrase expression node */
- int iPhrase, /* Phrase number */
- void *pCtx /* Pointer to MatchInfo structure */
-){
- int rc = SQLITE_OK;
- MatchInfo *p = (MatchInfo *)pCtx;
- int iStart = iPhrase * p->nCol * 3;
- int i;
-
- for(i=0; i<p->nCol && rc==SQLITE_OK; i++){
- char *pCsr;
- rc = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i, &pCsr);
- if( pCsr ){
- p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr);
- }else{
- p->aMatchinfo[iStart+i*3] = 0;
- }
- }
-
- return rc;
-}
-
-static int fts3MatchinfoCheck(
- Fts3Table *pTab,
- char cArg,
- char **pzErr
-){
- if( (cArg==FTS3_MATCHINFO_NPHRASE)
- || (cArg==FTS3_MATCHINFO_NCOL)
- || (cArg==FTS3_MATCHINFO_NDOC && pTab->bFts4)
- || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bFts4)
- || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize)
- || (cArg==FTS3_MATCHINFO_LCS)
- || (cArg==FTS3_MATCHINFO_HITS)
- || (cArg==FTS3_MATCHINFO_LHITS)
- || (cArg==FTS3_MATCHINFO_LHITS_BM)
- ){
- return SQLITE_OK;
- }
- sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg);
- return SQLITE_ERROR;
-}
-
-static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
- int nVal; /* Number of integers output by cArg */
-
- switch( cArg ){
- case FTS3_MATCHINFO_NDOC:
- case FTS3_MATCHINFO_NPHRASE:
- case FTS3_MATCHINFO_NCOL:
- nVal = 1;
- break;
-
- case FTS3_MATCHINFO_AVGLENGTH:
- case FTS3_MATCHINFO_LENGTH:
- case FTS3_MATCHINFO_LCS:
- nVal = pInfo->nCol;
- break;
-
- case FTS3_MATCHINFO_LHITS:
- nVal = pInfo->nCol * pInfo->nPhrase;
- break;
-
- case FTS3_MATCHINFO_LHITS_BM:
- nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
- break;
-
- default:
- assert( cArg==FTS3_MATCHINFO_HITS );
- nVal = pInfo->nCol * pInfo->nPhrase * 3;
- break;
- }
-
- return nVal;
-}
-
-static int fts3MatchinfoSelectDoctotal(
- Fts3Table *pTab,
- sqlite3_stmt **ppStmt,
- sqlite3_int64 *pnDoc,
- const char **paLen
-){
- sqlite3_stmt *pStmt;
- const char *a;
- sqlite3_int64 nDoc;
-
- if( !*ppStmt ){
- int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt);
- if( rc!=SQLITE_OK ) return rc;
- }
- pStmt = *ppStmt;
- assert( sqlite3_data_count(pStmt)==1 );
-
- a = sqlite3_column_blob(pStmt, 0);
- a += sqlite3Fts3GetVarint(a, &nDoc);
- if( nDoc==0 ) return FTS_CORRUPT_VTAB;
- *pnDoc = (u32)nDoc;
-
- if( paLen ) *paLen = a;
- return SQLITE_OK;
-}
-
-/*
-** An instance of the following structure is used to store state while
-** iterating through a multi-column position-list corresponding to the
-** hits for a single phrase on a single row in order to calculate the
-** values for a matchinfo() FTS3_MATCHINFO_LCS request.
-*/
-typedef struct LcsIterator LcsIterator;
-struct LcsIterator {
- Fts3Expr *pExpr; /* Pointer to phrase expression */
- int iPosOffset; /* Tokens count up to end of this phrase */
- char *pRead; /* Cursor used to iterate through aDoclist */
- int iPos; /* Current position */
-};
-
-/*
-** If LcsIterator.iCol is set to the following value, the iterator has
-** finished iterating through all offsets for all columns.
-*/
-#define LCS_ITERATOR_FINISHED 0x7FFFFFFF;
-
-static int fts3MatchinfoLcsCb(
- Fts3Expr *pExpr, /* Phrase expression node */
- int iPhrase, /* Phrase number (numbered from zero) */
- void *pCtx /* Pointer to MatchInfo structure */
-){
- LcsIterator *aIter = (LcsIterator *)pCtx;
- aIter[iPhrase].pExpr = pExpr;
- return SQLITE_OK;
-}
-
-/*
-** Advance the iterator passed as an argument to the next position. Return
-** 1 if the iterator is at EOF or if it now points to the start of the
-** position list for the next column.
-*/
-static int fts3LcsIteratorAdvance(LcsIterator *pIter){
- char *pRead = pIter->pRead;
- sqlite3_int64 iRead;
- int rc = 0;
-
- pRead += sqlite3Fts3GetVarint(pRead, &iRead);
- if( iRead==0 || iRead==1 ){
- pRead = 0;
- rc = 1;
- }else{
- pIter->iPos += (int)(iRead-2);
- }
-
- pIter->pRead = pRead;
- return rc;
-}
-
-/*
-** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag.
-**
-** If the call is successful, the longest-common-substring lengths for each
-** column are written into the first nCol elements of the pInfo->aMatchinfo[]
-** array before returning. SQLITE_OK is returned in this case.
-**
-** Otherwise, if an error occurs, an SQLite error code is returned and the
-** data written to the first nCol elements of pInfo->aMatchinfo[] is
-** undefined.
-*/
-static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
- LcsIterator *aIter;
- int i;
- int iCol;
- int nToken = 0;
-
- /* Allocate and populate the array of LcsIterator objects. The array
- ** contains one element for each matchable phrase in the query.
- **/
- aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
- if( !aIter ) return SQLITE_NOMEM;
- memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
- (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
-
- for(i=0; i<pInfo->nPhrase; i++){
- LcsIterator *pIter = &aIter[i];
- nToken -= pIter->pExpr->pPhrase->nToken;
- pIter->iPosOffset = nToken;
- }
-
- for(iCol=0; iCol<pInfo->nCol; iCol++){
- int nLcs = 0; /* LCS value for this column */
- int nLive = 0; /* Number of iterators in aIter not at EOF */
-
- for(i=0; i<pInfo->nPhrase; i++){
- int rc;
- LcsIterator *pIt = &aIter[i];
- rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead);
- if( rc!=SQLITE_OK ) return rc;
- if( pIt->pRead ){
- pIt->iPos = pIt->iPosOffset;
- fts3LcsIteratorAdvance(&aIter[i]);
- nLive++;
- }
- }
-
- while( nLive>0 ){
- LcsIterator *pAdv = 0; /* The iterator to advance by one position */
- int nThisLcs = 0; /* LCS for the current iterator positions */
-
- for(i=0; i<pInfo->nPhrase; i++){
- LcsIterator *pIter = &aIter[i];
- if( pIter->pRead==0 ){
- /* This iterator is already at EOF for this column. */
- nThisLcs = 0;
- }else{
- if( pAdv==0 || pIter->iPos<pAdv->iPos ){
- pAdv = pIter;
- }
- if( nThisLcs==0 || pIter->iPos==pIter[-1].iPos ){
- nThisLcs++;
- }else{
- nThisLcs = 1;
- }
- if( nThisLcs>nLcs ) nLcs = nThisLcs;
- }
- }
- if( fts3LcsIteratorAdvance(pAdv) ) nLive--;
- }
-
- pInfo->aMatchinfo[iCol] = nLcs;
- }
-
- sqlite3_free(aIter);
- return SQLITE_OK;
-}
-
-/*
-** Populate the buffer pInfo->aMatchinfo[] with an array of integers to
-** be returned by the matchinfo() function. Argument zArg contains the
-** format string passed as the second argument to matchinfo (or the
-** default value "pcx" if no second argument was specified). The format
-** string has already been validated and the pInfo->aMatchinfo[] array
-** is guaranteed to be large enough for the output.
-**
-** If bGlobal is true, then populate all fields of the matchinfo() output.
-** If it is false, then assume that those fields that do not change between
-** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS)
-** have already been populated.
-**
-** Return SQLITE_OK if successful, or an SQLite error code if an error
-** occurs. If a value other than SQLITE_OK is returned, the state the
-** pInfo->aMatchinfo[] buffer is left in is undefined.
-*/
-static int fts3MatchinfoValues(
- Fts3Cursor *pCsr, /* FTS3 cursor object */
- int bGlobal, /* True to grab the global stats */
- MatchInfo *pInfo, /* Matchinfo context object */
- const char *zArg /* Matchinfo format string */
-){
- int rc = SQLITE_OK;
- int i;
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- sqlite3_stmt *pSelect = 0;
-
- for(i=0; rc==SQLITE_OK && zArg[i]; i++){
- pInfo->flag = zArg[i];
- switch( zArg[i] ){
- case FTS3_MATCHINFO_NPHRASE:
- if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase;
- break;
-
- case FTS3_MATCHINFO_NCOL:
- if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol;
- break;
-
- case FTS3_MATCHINFO_NDOC:
- if( bGlobal ){
- sqlite3_int64 nDoc = 0;
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
- pInfo->aMatchinfo[0] = (u32)nDoc;
- }
- break;
-
- case FTS3_MATCHINFO_AVGLENGTH:
- if( bGlobal ){
- sqlite3_int64 nDoc; /* Number of rows in table */
- const char *a; /* Aggregate column length array */
-
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a);
- if( rc==SQLITE_OK ){
- int iCol;
- for(iCol=0; iCol<pInfo->nCol; iCol++){
- u32 iVal;
- sqlite3_int64 nToken;
- a += sqlite3Fts3GetVarint(a, &nToken);
- iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
- pInfo->aMatchinfo[iCol] = iVal;
- }
- }
- }
- break;
-
- case FTS3_MATCHINFO_LENGTH: {
- sqlite3_stmt *pSelectDocsize = 0;
- rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize);
- if( rc==SQLITE_OK ){
- int iCol;
- const char *a = sqlite3_column_blob(pSelectDocsize, 0);
- for(iCol=0; iCol<pInfo->nCol; iCol++){
- sqlite3_int64 nToken;
- a += sqlite3Fts3GetVarint(a, &nToken);
- pInfo->aMatchinfo[iCol] = (u32)nToken;
- }
- }
- sqlite3_reset(pSelectDocsize);
- break;
- }
-
- case FTS3_MATCHINFO_LCS:
- rc = fts3ExprLoadDoclists(pCsr, 0, 0);
- if( rc==SQLITE_OK ){
- rc = fts3MatchinfoLcs(pCsr, pInfo);
- }
- break;
-
- case FTS3_MATCHINFO_LHITS_BM:
- case FTS3_MATCHINFO_LHITS: {
- int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
- memset(pInfo->aMatchinfo, 0, nZero);
- fts3ExprLHitGather(pCsr->pExpr, pInfo);
- break;
- }
-
- default: {
- Fts3Expr *pExpr;
- assert( zArg[i]==FTS3_MATCHINFO_HITS );
- pExpr = pCsr->pExpr;
- rc = fts3ExprLoadDoclists(pCsr, 0, 0);
- if( rc!=SQLITE_OK ) break;
- if( bGlobal ){
- if( pCsr->pDeferred ){
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0);
- if( rc!=SQLITE_OK ) break;
- }
- rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
- sqlite3Fts3EvalTestDeferred(pCsr, &rc);
- if( rc!=SQLITE_OK ) break;
- }
- (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo);
- break;
- }
- }
-
- pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]);
- }
-
- sqlite3_reset(pSelect);
- return rc;
-}
-
-
-/*
-** Populate pCsr->aMatchinfo[] with data for the current row. The
-** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32).
-*/
-static void fts3GetMatchinfo(
- sqlite3_context *pCtx, /* Return results here */
- Fts3Cursor *pCsr, /* FTS3 Cursor object */
- const char *zArg /* Second argument to matchinfo() function */
-){
- MatchInfo sInfo;
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int rc = SQLITE_OK;
- int bGlobal = 0; /* Collect 'global' stats as well as local */
-
- u32 *aOut = 0;
- void (*xDestroyOut)(void*) = 0;
-
- memset(&sInfo, 0, sizeof(MatchInfo));
- sInfo.pCursor = pCsr;
- sInfo.nCol = pTab->nColumn;
-
- /* If there is cached matchinfo() data, but the format string for the
- ** cache does not match the format string for this request, discard
- ** the cached data. */
- if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){
- sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
- pCsr->pMIBuffer = 0;
- }
-
- /* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the
- ** matchinfo function has been called for this query. In this case
- ** allocate the array used to accumulate the matchinfo data and
- ** initialize those elements that are constant for every row.
- */
- if( pCsr->pMIBuffer==0 ){
- int nMatchinfo = 0; /* Number of u32 elements in match-info */
- int i; /* Used to iterate through zArg */
-
- /* Determine the number of phrases in the query */
- pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr);
- sInfo.nPhrase = pCsr->nPhrase;
-
- /* Determine the number of integers in the buffer returned by this call. */
- for(i=0; zArg[i]; i++){
- char *zErr = 0;
- if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){
- sqlite3_result_error(pCtx, zErr, -1);
- sqlite3_free(zErr);
- return;
- }
- nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]);
- }
-
- /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */
- pCsr->pMIBuffer = fts3MIBufferNew(nMatchinfo, zArg);
- if( !pCsr->pMIBuffer ) rc = SQLITE_NOMEM;
-
- pCsr->isMatchinfoNeeded = 1;
- bGlobal = 1;
- }
-
- if( rc==SQLITE_OK ){
- xDestroyOut = fts3MIBufferAlloc(pCsr->pMIBuffer, &aOut);
- if( xDestroyOut==0 ){
- rc = SQLITE_NOMEM;
- }
- }
-
- if( rc==SQLITE_OK ){
- sInfo.aMatchinfo = aOut;
- sInfo.nPhrase = pCsr->nPhrase;
- rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg);
- if( bGlobal ){
- fts3MIBufferSetGlobal(pCsr->pMIBuffer);
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_result_error_code(pCtx, rc);
- if( xDestroyOut ) xDestroyOut(aOut);
- }else{
- int n = pCsr->pMIBuffer->nElem * sizeof(u32);
- sqlite3_result_blob(pCtx, aOut, n, xDestroyOut);
- }
-}
-
-/*
-** Implementation of snippet() function.
-*/
-void sqlite3Fts3Snippet(
- sqlite3_context *pCtx, /* SQLite function call context */
- Fts3Cursor *pCsr, /* Cursor object */
- const char *zStart, /* Snippet start text - "<b>" */
- const char *zEnd, /* Snippet end text - "</b>" */
- const char *zEllipsis, /* Snippet ellipsis text - "<b>...</b>" */
- int iCol, /* Extract snippet from this column */
- int nToken /* Approximate number of tokens in snippet */
-){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int rc = SQLITE_OK;
- int i;
- StrBuffer res = {0, 0, 0};
-
- /* The returned text includes up to four fragments of text extracted from
- ** the data in the current row. The first iteration of the for(...) loop
- ** below attempts to locate a single fragment of text nToken tokens in
- ** size that contains at least one instance of all phrases in the query
- ** expression that appear in the current row. If such a fragment of text
- ** cannot be found, the second iteration of the loop attempts to locate
- ** a pair of fragments, and so on.
- */
- int nSnippet = 0; /* Number of fragments in this snippet */
- SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */
- int nFToken = -1; /* Number of tokens in each fragment */
-
- if( !pCsr->pExpr ){
- sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
- return;
- }
-
- for(nSnippet=1; 1; nSnippet++){
-
- int iSnip; /* Loop counter 0..nSnippet-1 */
- u64 mCovered = 0; /* Bitmask of phrases covered by snippet */
- u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */
-
- if( nToken>=0 ){
- nFToken = (nToken+nSnippet-1) / nSnippet;
- }else{
- nFToken = -1 * nToken;
- }
-
- for(iSnip=0; iSnip<nSnippet; iSnip++){
- int iBestScore = -1; /* Best score of columns checked so far */
- int iRead; /* Used to iterate through columns */
- SnippetFragment *pFragment = &aSnippet[iSnip];
-
- memset(pFragment, 0, sizeof(*pFragment));
-
- /* Loop through all columns of the table being considered for snippets.
- ** If the iCol argument to this function was negative, this means all
- ** columns of the FTS3 table. Otherwise, only column iCol is considered.
- */
- for(iRead=0; iRead<pTab->nColumn; iRead++){
- SnippetFragment sF = {0, 0, 0, 0};
- int iS = 0;
- if( iCol>=0 && iRead!=iCol ) continue;
-
- /* Find the best snippet of nFToken tokens in column iRead. */
- rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS);
- if( rc!=SQLITE_OK ){
- goto snippet_out;
- }
- if( iS>iBestScore ){
- *pFragment = sF;
- iBestScore = iS;
- }
- }
-
- mCovered |= pFragment->covered;
- }
-
- /* If all query phrases seen by fts3BestSnippet() are present in at least
- ** one of the nSnippet snippet fragments, break out of the loop.
- */
- assert( (mCovered&mSeen)==mCovered );
- if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break;
- }
-
- assert( nFToken>0 );
-
- for(i=0; i<nSnippet && rc==SQLITE_OK; i++){
- rc = fts3SnippetText(pCsr, &aSnippet[i],
- i, (i==nSnippet-1), nFToken, zStart, zEnd, zEllipsis, &res
- );
- }
-
- snippet_out:
- sqlite3Fts3SegmentsClose(pTab);
- if( rc!=SQLITE_OK ){
- sqlite3_result_error_code(pCtx, rc);
- sqlite3_free(res.z);
- }else{
- sqlite3_result_text(pCtx, res.z, -1, sqlite3_free);
- }
-}
-
-
-typedef struct TermOffset TermOffset;
-typedef struct TermOffsetCtx TermOffsetCtx;
-
-struct TermOffset {
- char *pList; /* Position-list */
- int iPos; /* Position just read from pList */
- int iOff; /* Offset of this term from read positions */
-};
-
-struct TermOffsetCtx {
- Fts3Cursor *pCsr;
- int iCol; /* Column of table to populate aTerm for */
- int iTerm;
- sqlite3_int64 iDocid;
- TermOffset *aTerm;
-};
-
-/*
-** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets().
-*/
-static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
- TermOffsetCtx *p = (TermOffsetCtx *)ctx;
- int nTerm; /* Number of tokens in phrase */
- int iTerm; /* For looping through nTerm phrase terms */
- char *pList; /* Pointer to position list for phrase */
- int iPos = 0; /* First position in position-list */
- int rc;
-
- UNUSED_PARAMETER(iPhrase);
- rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pList);
- nTerm = pExpr->pPhrase->nToken;
- if( pList ){
- fts3GetDeltaPosition(&pList, &iPos);
- assert( iPos>=0 );
- }
-
- for(iTerm=0; iTerm<nTerm; iTerm++){
- TermOffset *pT = &p->aTerm[p->iTerm++];
- pT->iOff = nTerm-iTerm-1;
- pT->pList = pList;
- pT->iPos = iPos;
- }
-
- return rc;
-}
-
-/*
-** Implementation of offsets() function.
-*/
-void sqlite3Fts3Offsets(
- sqlite3_context *pCtx, /* SQLite function call context */
- Fts3Cursor *pCsr /* Cursor object */
-){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
- int rc; /* Return Code */
- int nToken; /* Number of tokens in query */
- int iCol; /* Column currently being processed */
- StrBuffer res = {0, 0, 0}; /* Result string */
- TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */
-
- if( !pCsr->pExpr ){
- sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
- return;
- }
-
- memset(&sCtx, 0, sizeof(sCtx));
- assert( pCsr->isRequireSeek==0 );
-
- /* Count the number of terms in the query */
- rc = fts3ExprLoadDoclists(pCsr, 0, &nToken);
- if( rc!=SQLITE_OK ) goto offsets_out;
-
- /* Allocate the array of TermOffset iterators. */
- sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
- if( 0==sCtx.aTerm ){
- rc = SQLITE_NOMEM;
- goto offsets_out;
- }
- sCtx.iDocid = pCsr->iPrevId;
- sCtx.pCsr = pCsr;
-
- /* Loop through the table columns, appending offset information to
- ** string-buffer res for each column.
- */
- for(iCol=0; iCol<pTab->nColumn; iCol++){
- sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
- const char *ZDUMMY; /* Dummy argument used with xNext() */
- int NDUMMY = 0; /* Dummy argument used with xNext() */
- int iStart = 0;
- int iEnd = 0;
- int iCurrent = 0;
- const char *zDoc;
- int nDoc;
-
- /* Initialize the contents of sCtx.aTerm[] for column iCol. There is
- ** no way that this operation can fail, so the return code from
- ** fts3ExprIterate() can be discarded.
- */
- sCtx.iCol = iCol;
- sCtx.iTerm = 0;
- (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
-
- /* Retreive the text stored in column iCol. If an SQL NULL is stored
- ** in column iCol, jump immediately to the next iteration of the loop.
- ** If an OOM occurs while retrieving the data (this can happen if SQLite
- ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM
- ** to the caller.
- */
- zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1);
- nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
- if( zDoc==0 ){
- if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){
- continue;
- }
- rc = SQLITE_NOMEM;
- goto offsets_out;
- }
-
- /* Initialize a tokenizer iterator to iterate through column iCol. */
- rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid,
- zDoc, nDoc, &pC
- );
- if( rc!=SQLITE_OK ) goto offsets_out;
-
- rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
- while( rc==SQLITE_OK ){
- int i; /* Used to loop through terms */
- int iMinPos = 0x7FFFFFFF; /* Position of next token */
- TermOffset *pTerm = 0; /* TermOffset associated with next token */
-
- for(i=0; i<nToken; i++){
- TermOffset *pT = &sCtx.aTerm[i];
- if( pT->pList && (pT->iPos-pT->iOff)<iMinPos ){
- iMinPos = pT->iPos-pT->iOff;
- pTerm = pT;
- }
- }
-
- if( !pTerm ){
- /* All offsets for this column have been gathered. */
- rc = SQLITE_DONE;
- }else{
- assert( iCurrent<=iMinPos );
- if( 0==(0xFE&*pTerm->pList) ){
- pTerm->pList = 0;
- }else{
- fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos);
- }
- while( rc==SQLITE_OK && iCurrent<iMinPos ){
- rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
- }
- if( rc==SQLITE_OK ){
- char aBuffer[64];
- sqlite3_snprintf(sizeof(aBuffer), aBuffer,
- "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
- );
- rc = fts3StringAppend(&res, aBuffer, -1);
- }else if( rc==SQLITE_DONE && pTab->zContentTbl==0 ){
- rc = FTS_CORRUPT_VTAB;
- }
- }
- }
- if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- }
-
- pMod->xClose(pC);
- if( rc!=SQLITE_OK ) goto offsets_out;
- }
-
- offsets_out:
- sqlite3_free(sCtx.aTerm);
- assert( rc!=SQLITE_DONE );
- sqlite3Fts3SegmentsClose(pTab);
- if( rc!=SQLITE_OK ){
- sqlite3_result_error_code(pCtx, rc);
- sqlite3_free(res.z);
- }else{
- sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free);
- }
- return;
-}
-
-/*
-** Implementation of matchinfo() function.
-*/
-void sqlite3Fts3Matchinfo(
- sqlite3_context *pContext, /* Function call context */
- Fts3Cursor *pCsr, /* FTS3 table cursor */
- const char *zArg /* Second arg to matchinfo() function */
-){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- const char *zFormat;
-
- if( zArg ){
- zFormat = zArg;
- }else{
- zFormat = FTS3_MATCHINFO_DEFAULT;
- }
-
- if( !pCsr->pExpr ){
- sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC);
- return;
- }else{
- /* Retrieve matchinfo() data. */
- fts3GetMatchinfo(pContext, pCsr, zFormat);
- sqlite3Fts3SegmentsClose(pTab);
- }
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_term.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_term.c
deleted file mode 100644
index 7edd0728925..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_term.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
-** 2011 Jan 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 is not part of the production FTS code. It is only used for
-** testing. It contains a virtual table implementation that provides direct
-** access to the full-text index of an FTS table.
-*/
-
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-#ifdef SQLITE_TEST
-
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-
-typedef struct Fts3termTable Fts3termTable;
-typedef struct Fts3termCursor Fts3termCursor;
-
-struct Fts3termTable {
- sqlite3_vtab base; /* Base class used by SQLite core */
- int iIndex; /* Index for Fts3Table.aIndex[] */
- Fts3Table *pFts3Tab;
-};
-
-struct Fts3termCursor {
- sqlite3_vtab_cursor base; /* Base class used by SQLite core */
- Fts3MultiSegReader csr; /* Must be right after "base" */
- Fts3SegFilter filter;
-
- int isEof; /* True if cursor is at EOF */
- char *pNext;
-
- sqlite3_int64 iRowid; /* Current 'rowid' value */
- sqlite3_int64 iDocid; /* Current 'docid' value */
- int iCol; /* Current 'col' value */
- int iPos; /* Current 'pos' value */
-};
-
-/*
-** Schema of the terms table.
-*/
-#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, docid, col, pos)"
-
-/*
-** This function does all the work for both the xConnect and xCreate methods.
-** These tables have no persistent representation of their own, so xConnect
-** and xCreate are identical operations.
-*/
-static int fts3termConnectMethod(
- sqlite3 *db, /* Database connection */
- void *pCtx, /* Non-zero for an fts4prefix table */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- char const *zDb; /* Name of database (e.g. "main") */
- char const *zFts3; /* Name of fts3 table */
- int nDb; /* Result of strlen(zDb) */
- int nFts3; /* Result of strlen(zFts3) */
- int nByte; /* Bytes of space to allocate here */
- int rc; /* value returned by declare_vtab() */
- Fts3termTable *p; /* Virtual table object to return */
- int iIndex = 0;
-
- UNUSED_PARAMETER(pCtx);
- if( argc==5 ){
- iIndex = atoi(argv[4]);
- argc--;
- }
-
- /* The user should specify a single argument - the name of an fts3 table. */
- if( argc!=4 ){
- sqlite3Fts3ErrMsg(pzErr,
- "wrong number of arguments to fts4term constructor"
- );
- return SQLITE_ERROR;
- }
-
- zDb = argv[1];
- nDb = (int)strlen(zDb);
- zFts3 = argv[3];
- nFts3 = (int)strlen(zFts3);
-
- rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
- if( rc!=SQLITE_OK ) return rc;
-
- nByte = sizeof(Fts3termTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
- p = (Fts3termTable *)sqlite3_malloc(nByte);
- if( !p ) return SQLITE_NOMEM;
- memset(p, 0, nByte);
-
- p->pFts3Tab = (Fts3Table *)&p[1];
- p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
- p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
- p->pFts3Tab->db = db;
- p->pFts3Tab->nIndex = iIndex+1;
- p->iIndex = iIndex;
-
- memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
- memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
- sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);
-
- *ppVtab = (sqlite3_vtab *)p;
- return SQLITE_OK;
-}
-
-/*
-** This function does the work for both the xDisconnect and xDestroy methods.
-** These tables have no persistent representation of their own, so xDisconnect
-** and xDestroy are identical operations.
-*/
-static int fts3termDisconnectMethod(sqlite3_vtab *pVtab){
- Fts3termTable *p = (Fts3termTable *)pVtab;
- Fts3Table *pFts3 = p->pFts3Tab;
- int i;
-
- /* Free any prepared statements held */
- for(i=0; i<SizeofArray(pFts3->aStmt); i++){
- sqlite3_finalize(pFts3->aStmt[i]);
- }
- sqlite3_free(pFts3->zSegmentsTbl);
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-#define FTS4AUX_EQ_CONSTRAINT 1
-#define FTS4AUX_GE_CONSTRAINT 2
-#define FTS4AUX_LE_CONSTRAINT 4
-
-/*
-** xBestIndex - Analyze a WHERE and ORDER BY clause.
-*/
-static int fts3termBestIndexMethod(
- sqlite3_vtab *pVTab,
- sqlite3_index_info *pInfo
-){
- UNUSED_PARAMETER(pVTab);
-
- /* This vtab naturally does "ORDER BY term, docid, col, pos". */
- if( pInfo->nOrderBy ){
- int i;
- for(i=0; i<pInfo->nOrderBy; i++){
- if( pInfo->aOrderBy[i].iColumn!=i || pInfo->aOrderBy[i].desc ) break;
- }
- if( i==pInfo->nOrderBy ){
- pInfo->orderByConsumed = 1;
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** xOpen - Open a cursor.
-*/
-static int fts3termOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
- Fts3termCursor *pCsr; /* Pointer to cursor object to return */
-
- UNUSED_PARAMETER(pVTab);
-
- pCsr = (Fts3termCursor *)sqlite3_malloc(sizeof(Fts3termCursor));
- if( !pCsr ) return SQLITE_NOMEM;
- memset(pCsr, 0, sizeof(Fts3termCursor));
-
- *ppCsr = (sqlite3_vtab_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** xClose - Close a cursor.
-*/
-static int fts3termCloseMethod(sqlite3_vtab_cursor *pCursor){
- Fts3Table *pFts3 = ((Fts3termTable *)pCursor->pVtab)->pFts3Tab;
- Fts3termCursor *pCsr = (Fts3termCursor *)pCursor;
-
- sqlite3Fts3SegmentsClose(pFts3);
- sqlite3Fts3SegReaderFinish(&pCsr->csr);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** xNext - Advance the cursor to the next row, if any.
-*/
-static int fts3termNextMethod(sqlite3_vtab_cursor *pCursor){
- Fts3termCursor *pCsr = (Fts3termCursor *)pCursor;
- Fts3Table *pFts3 = ((Fts3termTable *)pCursor->pVtab)->pFts3Tab;
- int rc;
- sqlite3_int64 v;
-
- /* Increment our pretend rowid value. */
- pCsr->iRowid++;
-
- /* Advance to the next term in the full-text index. */
- if( pCsr->csr.aDoclist==0
- || pCsr->pNext>=&pCsr->csr.aDoclist[pCsr->csr.nDoclist-1]
- ){
- rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr);
- if( rc!=SQLITE_ROW ){
- pCsr->isEof = 1;
- return rc;
- }
-
- pCsr->iCol = 0;
- pCsr->iPos = 0;
- pCsr->iDocid = 0;
- pCsr->pNext = pCsr->csr.aDoclist;
-
- /* Read docid */
- pCsr->pNext += sqlite3Fts3GetVarint(pCsr->pNext, &pCsr->iDocid);
- }
-
- pCsr->pNext += sqlite3Fts3GetVarint(pCsr->pNext, &v);
- if( v==0 ){
- pCsr->pNext += sqlite3Fts3GetVarint(pCsr->pNext, &v);
- pCsr->iDocid += v;
- pCsr->pNext += sqlite3Fts3GetVarint(pCsr->pNext, &v);
- pCsr->iCol = 0;
- pCsr->iPos = 0;
- }
-
- if( v==1 ){
- pCsr->pNext += sqlite3Fts3GetVarint(pCsr->pNext, &v);
- pCsr->iCol += (int)v;
- pCsr->iPos = 0;
- pCsr->pNext += sqlite3Fts3GetVarint(pCsr->pNext, &v);
- }
-
- pCsr->iPos += (int)(v - 2);
-
- return SQLITE_OK;
-}
-
-/*
-** xFilter - Initialize a cursor to point at the start of its data.
-*/
-static int fts3termFilterMethod(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, /* Strategy index */
- const char *idxStr, /* Unused */
- int nVal, /* Number of elements in apVal */
- sqlite3_value **apVal /* Arguments for the indexing scheme */
-){
- Fts3termCursor *pCsr = (Fts3termCursor *)pCursor;
- Fts3termTable *p = (Fts3termTable *)pCursor->pVtab;
- Fts3Table *pFts3 = p->pFts3Tab;
- int rc;
-
- UNUSED_PARAMETER(nVal);
- UNUSED_PARAMETER(idxNum);
- UNUSED_PARAMETER(idxStr);
- UNUSED_PARAMETER(apVal);
-
- assert( idxStr==0 && idxNum==0 );
-
- /* In case this cursor is being reused, close and zero it. */
- testcase(pCsr->filter.zTerm);
- sqlite3Fts3SegReaderFinish(&pCsr->csr);
- memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
-
- pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
- pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
-
- rc = sqlite3Fts3SegReaderCursor(pFts3, 0, p->iIndex, FTS3_SEGCURSOR_ALL,
- pCsr->filter.zTerm, pCsr->filter.nTerm, 0, 1, &pCsr->csr
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
- }
- if( rc==SQLITE_OK ){
- rc = fts3termNextMethod(pCursor);
- }
- return rc;
-}
-
-/*
-** xEof - Return true if the cursor is at EOF, or false otherwise.
-*/
-static int fts3termEofMethod(sqlite3_vtab_cursor *pCursor){
- Fts3termCursor *pCsr = (Fts3termCursor *)pCursor;
- return pCsr->isEof;
-}
-
-/*
-** xColumn - Return a column value.
-*/
-static int fts3termColumnMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
- int iCol /* Index of column to read value from */
-){
- Fts3termCursor *p = (Fts3termCursor *)pCursor;
-
- assert( iCol>=0 && iCol<=3 );
- switch( iCol ){
- case 0:
- sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
- break;
- case 1:
- sqlite3_result_int64(pCtx, p->iDocid);
- break;
- case 2:
- sqlite3_result_int64(pCtx, p->iCol);
- break;
- default:
- sqlite3_result_int64(pCtx, p->iPos);
- break;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** xRowid - Return the current rowid for the cursor.
-*/
-static int fts3termRowidMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite_int64 *pRowid /* OUT: Rowid value */
-){
- Fts3termCursor *pCsr = (Fts3termCursor *)pCursor;
- *pRowid = pCsr->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Register the fts3term module with database connection db. Return SQLITE_OK
-** if successful or an error code if sqlite3_create_module() fails.
-*/
-int sqlite3Fts3InitTerm(sqlite3 *db){
- static const sqlite3_module fts3term_module = {
- 0, /* iVersion */
- fts3termConnectMethod, /* xCreate */
- fts3termConnectMethod, /* xConnect */
- fts3termBestIndexMethod, /* xBestIndex */
- fts3termDisconnectMethod, /* xDisconnect */
- fts3termDisconnectMethod, /* xDestroy */
- fts3termOpenMethod, /* xOpen */
- fts3termCloseMethod, /* xClose */
- fts3termFilterMethod, /* xFilter */
- fts3termNextMethod, /* xNext */
- fts3termEofMethod, /* xEof */
- fts3termColumnMethod, /* xColumn */
- fts3termRowidMethod, /* xRowid */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindFunction */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
- };
- int rc; /* Return code */
-
- rc = sqlite3_create_module(db, "fts4term", &fts3term_module, 0);
- return rc;
-}
-
-#endif
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_test.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_test.c
deleted file mode 100644
index a48a556c98f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_test.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
-** 2011 Jun 13
-**
-** 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 is not part of the production FTS code. It is only used for
-** testing. It contains a Tcl command that can be used to test if a document
-** matches an FTS NEAR expression.
-**
-** As of March 2012, it also contains a version 1 tokenizer used for testing
-** that the sqlite3_tokenizer_module.xLanguage() method is invoked correctly.
-*/
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-#include <string.h>
-#include <assert.h>
-
-#if defined(SQLITE_TEST)
-#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
-
-/* Required so that the "ifdef SQLITE_ENABLE_FTS3" below works */
-#include "fts3Int.h"
-
-#define NM_MAX_TOKEN 12
-
-typedef struct NearPhrase NearPhrase;
-typedef struct NearDocument NearDocument;
-typedef struct NearToken NearToken;
-
-struct NearDocument {
- int nToken; /* Length of token in bytes */
- NearToken *aToken; /* Token array */
-};
-
-struct NearToken {
- int n; /* Length of token in bytes */
- const char *z; /* Pointer to token string */
-};
-
-struct NearPhrase {
- int nNear; /* Preceding NEAR value */
- int nToken; /* Number of tokens in this phrase */
- NearToken aToken[NM_MAX_TOKEN]; /* Array of tokens in this phrase */
-};
-
-static int nm_phrase_match(
- NearPhrase *p,
- NearToken *aToken
-){
- int ii;
-
- for(ii=0; ii<p->nToken; ii++){
- NearToken *pToken = &p->aToken[ii];
- if( pToken->n>0 && pToken->z[pToken->n-1]=='*' ){
- if( aToken[ii].n<(pToken->n-1) ) return 0;
- if( memcmp(aToken[ii].z, pToken->z, pToken->n-1) ) return 0;
- }else{
- if( aToken[ii].n!=pToken->n ) return 0;
- if( memcmp(aToken[ii].z, pToken->z, pToken->n) ) return 0;
- }
- }
-
- return 1;
-}
-
-static int nm_near_chain(
- int iDir, /* Direction to iterate through aPhrase[] */
- NearDocument *pDoc, /* Document to match against */
- int iPos, /* Position at which iPhrase was found */
- int nPhrase, /* Size of phrase array */
- NearPhrase *aPhrase, /* Phrase array */
- int iPhrase /* Index of phrase found */
-){
- int iStart;
- int iStop;
- int ii;
- int nNear;
- int iPhrase2;
- NearPhrase *p;
- NearPhrase *pPrev;
-
- assert( iDir==1 || iDir==-1 );
-
- if( iDir==1 ){
- if( (iPhrase+1)==nPhrase ) return 1;
- nNear = aPhrase[iPhrase+1].nNear;
- }else{
- if( iPhrase==0 ) return 1;
- nNear = aPhrase[iPhrase].nNear;
- }
- pPrev = &aPhrase[iPhrase];
- iPhrase2 = iPhrase+iDir;
- p = &aPhrase[iPhrase2];
-
- iStart = iPos - nNear - p->nToken;
- iStop = iPos + nNear + pPrev->nToken;
-
- if( iStart<0 ) iStart = 0;
- if( iStop > pDoc->nToken - p->nToken ) iStop = pDoc->nToken - p->nToken;
-
- for(ii=iStart; ii<=iStop; ii++){
- if( nm_phrase_match(p, &pDoc->aToken[ii]) ){
- if( nm_near_chain(iDir, pDoc, ii, nPhrase, aPhrase, iPhrase2) ) return 1;
- }
- }
-
- return 0;
-}
-
-static int nm_match_count(
- NearDocument *pDoc, /* Document to match against */
- int nPhrase, /* Size of phrase array */
- NearPhrase *aPhrase, /* Phrase array */
- int iPhrase /* Index of phrase to count matches for */
-){
- int nOcc = 0;
- int ii;
- NearPhrase *p = &aPhrase[iPhrase];
-
- for(ii=0; ii<(pDoc->nToken + 1 - p->nToken); ii++){
- if( nm_phrase_match(p, &pDoc->aToken[ii]) ){
- /* Test forward NEAR chain (i>iPhrase) */
- if( 0==nm_near_chain(1, pDoc, ii, nPhrase, aPhrase, iPhrase) ) continue;
-
- /* Test reverse NEAR chain (i<iPhrase) */
- if( 0==nm_near_chain(-1, pDoc, ii, nPhrase, aPhrase, iPhrase) ) continue;
-
- /* This is a real match. Increment the counter. */
- nOcc++;
- }
- }
-
- return nOcc;
-}
-
-/*
-** Tclcmd: fts3_near_match DOCUMENT EXPR ?OPTIONS?
-*/
-static int SQLITE_TCLAPI fts3_near_match_cmd(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int nTotal = 0;
- int rc;
- int ii;
- int nPhrase;
- NearPhrase *aPhrase = 0;
- NearDocument doc = {0, 0};
- Tcl_Obj **apDocToken;
- Tcl_Obj *pRet;
- Tcl_Obj *pPhrasecount = 0;
-
- Tcl_Obj **apExprToken;
- int nExprToken;
-
- UNUSED_PARAMETER(clientData);
-
- /* Must have 3 or more arguments. */
- if( objc<3 || (objc%2)==0 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DOCUMENT EXPR ?OPTION VALUE?...");
- rc = TCL_ERROR;
- goto near_match_out;
- }
-
- for(ii=3; ii<objc; ii+=2){
- enum NM_enum { NM_PHRASECOUNTS };
- struct TestnmSubcmd {
- char *zName;
- enum NM_enum eOpt;
- } aOpt[] = {
- { "-phrasecountvar", NM_PHRASECOUNTS },
- { 0, 0 }
- };
- int iOpt;
- if( Tcl_GetIndexFromObjStruct(
- interp, objv[ii], aOpt, sizeof(aOpt[0]), "option", 0, &iOpt)
- ){
- return TCL_ERROR;
- }
-
- switch( aOpt[iOpt].eOpt ){
- case NM_PHRASECOUNTS:
- pPhrasecount = objv[ii+1];
- break;
- }
- }
-
- rc = Tcl_ListObjGetElements(interp, objv[1], &doc.nToken, &apDocToken);
- if( rc!=TCL_OK ) goto near_match_out;
- doc.aToken = (NearToken *)ckalloc(doc.nToken*sizeof(NearToken));
- for(ii=0; ii<doc.nToken; ii++){
- doc.aToken[ii].z = Tcl_GetStringFromObj(apDocToken[ii], &doc.aToken[ii].n);
- }
-
- rc = Tcl_ListObjGetElements(interp, objv[2], &nExprToken, &apExprToken);
- if( rc!=TCL_OK ) goto near_match_out;
-
- nPhrase = (nExprToken + 1) / 2;
- aPhrase = (NearPhrase *)ckalloc(nPhrase * sizeof(NearPhrase));
- memset(aPhrase, 0, nPhrase * sizeof(NearPhrase));
- for(ii=0; ii<nPhrase; ii++){
- Tcl_Obj *pPhrase = apExprToken[ii*2];
- Tcl_Obj **apToken;
- int nToken;
- int jj;
-
- rc = Tcl_ListObjGetElements(interp, pPhrase, &nToken, &apToken);
- if( rc!=TCL_OK ) goto near_match_out;
- if( nToken>NM_MAX_TOKEN ){
- Tcl_AppendResult(interp, "Too many tokens in phrase", 0);
- rc = TCL_ERROR;
- goto near_match_out;
- }
- for(jj=0; jj<nToken; jj++){
- NearToken *pT = &aPhrase[ii].aToken[jj];
- pT->z = Tcl_GetStringFromObj(apToken[jj], &pT->n);
- }
- aPhrase[ii].nToken = nToken;
- }
- for(ii=1; ii<nPhrase; ii++){
- Tcl_Obj *pNear = apExprToken[2*ii-1];
- int nNear;
- rc = Tcl_GetIntFromObj(interp, pNear, &nNear);
- if( rc!=TCL_OK ) goto near_match_out;
- aPhrase[ii].nNear = nNear;
- }
-
- pRet = Tcl_NewObj();
- Tcl_IncrRefCount(pRet);
- for(ii=0; ii<nPhrase; ii++){
- int nOcc = nm_match_count(&doc, nPhrase, aPhrase, ii);
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nOcc));
- nTotal += nOcc;
- }
- if( pPhrasecount ){
- Tcl_ObjSetVar2(interp, pPhrasecount, 0, pRet, 0);
- }
- Tcl_DecrRefCount(pRet);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(nTotal>0));
-
- near_match_out:
- ckfree((char *)aPhrase);
- ckfree((char *)doc.aToken);
- return rc;
-}
-
-/*
-** Tclcmd: fts3_configure_incr_load ?CHUNKSIZE THRESHOLD?
-**
-** Normally, FTS uses hard-coded values to determine the minimum doclist
-** size eligible for incremental loading, and the size of the chunks loaded
-** when a doclist is incrementally loaded. This command allows the built-in
-** values to be overridden for testing purposes.
-**
-** If present, the first argument is the chunksize in bytes to load doclists
-** in. The second argument is the minimum doclist size in bytes to use
-** incremental loading with.
-**
-** Whether or not the arguments are present, this command returns a list of
-** two integers - the initial chunksize and threshold when the command is
-** invoked. This can be used to restore the default behavior after running
-** tests. For example:
-**
-** # Override incr-load settings for testing:
-** set cfg [fts3_configure_incr_load $new_chunksize $new_threshold]
-**
-** .... run tests ....
-**
-** # Restore initial incr-load settings:
-** eval fts3_configure_incr_load $cfg
-*/
-static int SQLITE_TCLAPI fts3_configure_incr_load_cmd(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifdef SQLITE_ENABLE_FTS3
- extern int test_fts3_node_chunksize;
- extern int test_fts3_node_chunk_threshold;
- Tcl_Obj *pRet;
-
- if( objc!=1 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?CHUNKSIZE THRESHOLD?");
- return TCL_ERROR;
- }
-
- pRet = Tcl_NewObj();
- Tcl_IncrRefCount(pRet);
- Tcl_ListObjAppendElement(
- interp, pRet, Tcl_NewIntObj(test_fts3_node_chunksize));
- Tcl_ListObjAppendElement(
- interp, pRet, Tcl_NewIntObj(test_fts3_node_chunk_threshold));
-
- if( objc==3 ){
- int iArg1;
- int iArg2;
- if( Tcl_GetIntFromObj(interp, objv[1], &iArg1)
- || Tcl_GetIntFromObj(interp, objv[2], &iArg2)
- ){
- Tcl_DecrRefCount(pRet);
- return TCL_ERROR;
- }
- test_fts3_node_chunksize = iArg1;
- test_fts3_node_chunk_threshold = iArg2;
- }
-
- Tcl_SetObjResult(interp, pRet);
- Tcl_DecrRefCount(pRet);
-#endif
- UNUSED_PARAMETER(clientData);
- return TCL_OK;
-}
-
-#ifdef SQLITE_ENABLE_FTS3
-/**************************************************************************
-** Beginning of test tokenizer code.
-**
-** For language 0, this tokenizer is similar to the default 'simple'
-** tokenizer. For other languages L, the following:
-**
-** * Odd numbered languages are case-sensitive. Even numbered
-** languages are not.
-**
-** * Language ids 100 or greater are considered an error.
-**
-** The implementation assumes that the input contains only ASCII characters
-** (i.e. those that may be encoded in UTF-8 using a single byte).
-*/
-typedef struct test_tokenizer {
- sqlite3_tokenizer base;
-} test_tokenizer;
-
-typedef struct test_tokenizer_cursor {
- sqlite3_tokenizer_cursor base;
- const char *aInput; /* Input being tokenized */
- int nInput; /* Size of the input in bytes */
- int iInput; /* Current offset in aInput */
- int iToken; /* Index of next token to be returned */
- char *aBuffer; /* Buffer containing current token */
- int nBuffer; /* Number of bytes allocated at pToken */
- int iLangid; /* Configured language id */
-} test_tokenizer_cursor;
-
-static int testTokenizerCreate(
- int argc, const char * const *argv,
- sqlite3_tokenizer **ppTokenizer
-){
- test_tokenizer *pNew;
- UNUSED_PARAMETER(argc);
- UNUSED_PARAMETER(argv);
-
- pNew = sqlite3_malloc(sizeof(test_tokenizer));
- if( !pNew ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(test_tokenizer));
-
- *ppTokenizer = (sqlite3_tokenizer *)pNew;
- return SQLITE_OK;
-}
-
-static int testTokenizerDestroy(sqlite3_tokenizer *pTokenizer){
- test_tokenizer *p = (test_tokenizer *)pTokenizer;
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-static int testTokenizerOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *pInput, int nBytes, /* String to be tokenized */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- int rc = SQLITE_OK; /* Return code */
- test_tokenizer_cursor *pCsr; /* New cursor object */
-
- UNUSED_PARAMETER(pTokenizer);
-
- pCsr = (test_tokenizer_cursor *)sqlite3_malloc(sizeof(test_tokenizer_cursor));
- if( pCsr==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pCsr, 0, sizeof(test_tokenizer_cursor));
- pCsr->aInput = pInput;
- if( nBytes<0 ){
- pCsr->nInput = (int)strlen(pInput);
- }else{
- pCsr->nInput = nBytes;
- }
- }
-
- *ppCursor = (sqlite3_tokenizer_cursor *)pCsr;
- return rc;
-}
-
-static int testTokenizerClose(sqlite3_tokenizer_cursor *pCursor){
- test_tokenizer_cursor *pCsr = (test_tokenizer_cursor *)pCursor;
- sqlite3_free(pCsr->aBuffer);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-static int testIsTokenChar(char c){
- return (c>='a' && c<='z') || (c>='A' && c<='Z');
-}
-static int testTolower(char c){
- char ret = c;
- if( ret>='A' && ret<='Z') ret = ret - ('A'-'a');
- return ret;
-}
-
-static int testTokenizerNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by testTokenizerOpen */
- const char **ppToken, /* OUT: *ppToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- test_tokenizer_cursor *pCsr = (test_tokenizer_cursor *)pCursor;
- int rc = SQLITE_OK;
- const char *p;
- const char *pEnd;
-
- p = &pCsr->aInput[pCsr->iInput];
- pEnd = &pCsr->aInput[pCsr->nInput];
-
- /* Skip past any white-space */
- assert( p<=pEnd );
- while( p<pEnd && testIsTokenChar(*p)==0 ) p++;
-
- if( p==pEnd ){
- rc = SQLITE_DONE;
- }else{
- /* Advance to the end of the token */
- const char *pToken = p;
- int nToken;
- while( p<pEnd && testIsTokenChar(*p) ) p++;
- nToken = (int)(p-pToken);
-
- /* Copy the token into the buffer */
- if( nToken>pCsr->nBuffer ){
- sqlite3_free(pCsr->aBuffer);
- pCsr->aBuffer = sqlite3_malloc(nToken);
- }
- if( pCsr->aBuffer==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int i;
-
- if( pCsr->iLangid & 0x00000001 ){
- for(i=0; i<nToken; i++) pCsr->aBuffer[i] = pToken[i];
- }else{
- for(i=0; i<nToken; i++) pCsr->aBuffer[i] = (char)testTolower(pToken[i]);
- }
- pCsr->iToken++;
- pCsr->iInput = (int)(p - pCsr->aInput);
-
- *ppToken = pCsr->aBuffer;
- *pnBytes = nToken;
- *piStartOffset = (int)(pToken - pCsr->aInput);
- *piEndOffset = (int)(p - pCsr->aInput);
- *piPosition = pCsr->iToken;
- }
- }
-
- return rc;
-}
-
-static int testTokenizerLanguage(
- sqlite3_tokenizer_cursor *pCursor,
- int iLangid
-){
- int rc = SQLITE_OK;
- test_tokenizer_cursor *pCsr = (test_tokenizer_cursor *)pCursor;
- pCsr->iLangid = iLangid;
- if( pCsr->iLangid>=100 ){
- rc = SQLITE_ERROR;
- }
- return rc;
-}
-#endif
-
-static int SQLITE_TCLAPI fts3_test_tokenizer_cmd(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifdef SQLITE_ENABLE_FTS3
- static const sqlite3_tokenizer_module testTokenizerModule = {
- 1,
- testTokenizerCreate,
- testTokenizerDestroy,
- testTokenizerOpen,
- testTokenizerClose,
- testTokenizerNext,
- testTokenizerLanguage
- };
- const sqlite3_tokenizer_module *pPtr = &testTokenizerModule;
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
- (const unsigned char *)&pPtr, sizeof(sqlite3_tokenizer_module *)
- ));
-#endif
- UNUSED_PARAMETER(clientData);
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI fts3_test_varint_cmd(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifdef SQLITE_ENABLE_FTS3
- char aBuf[24];
- int rc;
- Tcl_WideInt w;
- sqlite3_int64 w2;
- int nByte, nByte2;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "INTEGER");
- return TCL_ERROR;
- }
-
- rc = Tcl_GetWideIntFromObj(interp, objv[1], &w);
- if( rc!=TCL_OK ) return rc;
-
- nByte = sqlite3Fts3PutVarint(aBuf, w);
- nByte2 = sqlite3Fts3GetVarint(aBuf, &w2);
- if( w!=w2 || nByte!=nByte2 ){
- char *zErr = sqlite3_mprintf("error testing %lld", w);
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, zErr, 0);
- return TCL_ERROR;
- }
-
- if( w<=2147483647 && w>=0 ){
- int i;
- nByte2 = fts3GetVarint32(aBuf, &i);
- if( (int)w!=i || nByte!=nByte2 ){
- char *zErr = sqlite3_mprintf("error testing %lld (32-bit)", w);
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, zErr, 0);
- return TCL_ERROR;
- }
- }
-
-#endif
- UNUSED_PARAMETER(clientData);
- return TCL_OK;
-}
-
-/*
-** End of tokenizer code.
-**************************************************************************/
-
-int Sqlitetestfts3_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "fts3_near_match", fts3_near_match_cmd, 0, 0);
- Tcl_CreateObjCommand(interp,
- "fts3_configure_incr_load", fts3_configure_incr_load_cmd, 0, 0
- );
- Tcl_CreateObjCommand(
- interp, "fts3_test_tokenizer", fts3_test_tokenizer_cmd, 0, 0
- );
-
- Tcl_CreateObjCommand(
- interp, "fts3_test_varint", fts3_test_varint_cmd, 0, 0
- );
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_FTS3 || SQLITE_ENABLE_FTS4 */
-#endif /* ifdef SQLITE_TEST */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenize_vtab.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenize_vtab.c
deleted file mode 100644
index dfeddfeb963..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenize_vtab.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
-** 2013 Apr 22
-**
-** 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 contains code for the "fts3tokenize" virtual table module.
-** An fts3tokenize virtual table is created as follows:
-**
-** CREATE VIRTUAL TABLE <tbl> USING fts3tokenize(
-** <tokenizer-name>, <arg-1>, ...
-** );
-**
-** The table created has the following schema:
-**
-** CREATE TABLE <tbl>(input, token, start, end, position)
-**
-** When queried, the query must include a WHERE clause of type:
-**
-** input = <string>
-**
-** The virtual table module tokenizes this <string>, using the FTS3
-** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE
-** statement and returns one row for each token in the result. With
-** fields set as follows:
-**
-** input: Always set to a copy of <string>
-** token: A token from the input.
-** start: Byte offset of the token within the input <string>.
-** end: Byte offset of the byte immediately following the end of the
-** token within the input string.
-** pos: Token offset of token within input.
-**
-*/
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <string.h>
-#include <assert.h>
-
-typedef struct Fts3tokTable Fts3tokTable;
-typedef struct Fts3tokCursor Fts3tokCursor;
-
-/*
-** Virtual table structure.
-*/
-struct Fts3tokTable {
- sqlite3_vtab base; /* Base class used by SQLite core */
- const sqlite3_tokenizer_module *pMod;
- sqlite3_tokenizer *pTok;
-};
-
-/*
-** Virtual table cursor structure.
-*/
-struct Fts3tokCursor {
- sqlite3_vtab_cursor base; /* Base class used by SQLite core */
- char *zInput; /* Input string */
- sqlite3_tokenizer_cursor *pCsr; /* Cursor to iterate through zInput */
- int iRowid; /* Current 'rowid' value */
- const char *zToken; /* Current 'token' value */
- int nToken; /* Size of zToken in bytes */
- int iStart; /* Current 'start' value */
- int iEnd; /* Current 'end' value */
- int iPos; /* Current 'pos' value */
-};
-
-/*
-** Query FTS for the tokenizer implementation named zName.
-*/
-static int fts3tokQueryTokenizer(
- Fts3Hash *pHash,
- const char *zName,
- const sqlite3_tokenizer_module **pp,
- char **pzErr
-){
- sqlite3_tokenizer_module *p;
- int nName = (int)strlen(zName);
-
- p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
- if( !p ){
- sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName);
- return SQLITE_ERROR;
- }
-
- *pp = p;
- return SQLITE_OK;
-}
-
-/*
-** The second argument, argv[], is an array of pointers to nul-terminated
-** strings. This function makes a copy of the array and strings into a
-** single block of memory. It then dequotes any of the strings that appear
-** to be quoted.
-**
-** If successful, output parameter *pazDequote is set to point at the
-** array of dequoted strings and SQLITE_OK is returned. The caller is
-** responsible for eventually calling sqlite3_free() to free the array
-** in this case. Or, if an error occurs, an SQLite error code is returned.
-** The final value of *pazDequote is undefined in this case.
-*/
-static int fts3tokDequoteArray(
- int argc, /* Number of elements in argv[] */
- const char * const *argv, /* Input array */
- char ***pazDequote /* Output array */
-){
- int rc = SQLITE_OK; /* Return code */
- if( argc==0 ){
- *pazDequote = 0;
- }else{
- int i;
- int nByte = 0;
- char **azDequote;
-
- for(i=0; i<argc; i++){
- nByte += (int)(strlen(argv[i]) + 1);
- }
-
- *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
- if( azDequote==0 ){
- rc = SQLITE_NOMEM;
- }else{
- char *pSpace = (char *)&azDequote[argc];
- for(i=0; i<argc; i++){
- int n = (int)strlen(argv[i]);
- azDequote[i] = pSpace;
- memcpy(pSpace, argv[i], n+1);
- sqlite3Fts3Dequote(pSpace);
- pSpace += (n+1);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Schema of the tokenizer table.
-*/
-#define FTS3_TOK_SCHEMA "CREATE TABLE x(input, token, start, end, position)"
-
-/*
-** This function does all the work for both the xConnect and xCreate methods.
-** These tables have no persistent representation of their own, so xConnect
-** and xCreate are identical operations.
-**
-** argv[0]: module name
-** argv[1]: database name
-** argv[2]: table name
-** argv[3]: first argument (tokenizer name)
-*/
-static int fts3tokConnectMethod(
- sqlite3 *db, /* Database connection */
- void *pHash, /* Hash table of tokenizers */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- Fts3tokTable *pTab = 0;
- const sqlite3_tokenizer_module *pMod = 0;
- sqlite3_tokenizer *pTok = 0;
- int rc;
- char **azDequote = 0;
- int nDequote;
-
- rc = sqlite3_declare_vtab(db, FTS3_TOK_SCHEMA);
- if( rc!=SQLITE_OK ) return rc;
-
- nDequote = argc-3;
- rc = fts3tokDequoteArray(nDequote, &argv[3], &azDequote);
-
- if( rc==SQLITE_OK ){
- const char *zModule;
- if( nDequote<1 ){
- zModule = "simple";
- }else{
- zModule = azDequote[0];
- }
- rc = fts3tokQueryTokenizer((Fts3Hash*)pHash, zModule, &pMod, pzErr);
- }
-
- assert( (rc==SQLITE_OK)==(pMod!=0) );
- if( rc==SQLITE_OK ){
- const char * const *azArg = (const char * const *)&azDequote[1];
- rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok);
- }
-
- if( rc==SQLITE_OK ){
- pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable));
- if( pTab==0 ){
- rc = SQLITE_NOMEM;
- }
- }
-
- if( rc==SQLITE_OK ){
- memset(pTab, 0, sizeof(Fts3tokTable));
- pTab->pMod = pMod;
- pTab->pTok = pTok;
- *ppVtab = &pTab->base;
- }else{
- if( pTok ){
- pMod->xDestroy(pTok);
- }
- }
-
- sqlite3_free(azDequote);
- return rc;
-}
-
-/*
-** This function does the work for both the xDisconnect and xDestroy methods.
-** These tables have no persistent representation of their own, so xDisconnect
-** and xDestroy are identical operations.
-*/
-static int fts3tokDisconnectMethod(sqlite3_vtab *pVtab){
- Fts3tokTable *pTab = (Fts3tokTable *)pVtab;
-
- pTab->pMod->xDestroy(pTab->pTok);
- sqlite3_free(pTab);
- return SQLITE_OK;
-}
-
-/*
-** xBestIndex - Analyze a WHERE and ORDER BY clause.
-*/
-static int fts3tokBestIndexMethod(
- sqlite3_vtab *pVTab,
- sqlite3_index_info *pInfo
-){
- int i;
- UNUSED_PARAMETER(pVTab);
-
- for(i=0; i<pInfo->nConstraint; i++){
- if( pInfo->aConstraint[i].usable
- && pInfo->aConstraint[i].iColumn==0
- && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- pInfo->idxNum = 1;
- pInfo->aConstraintUsage[i].argvIndex = 1;
- pInfo->aConstraintUsage[i].omit = 1;
- pInfo->estimatedCost = 1;
- return SQLITE_OK;
- }
- }
-
- pInfo->idxNum = 0;
- assert( pInfo->estimatedCost>1000000.0 );
-
- return SQLITE_OK;
-}
-
-/*
-** xOpen - Open a cursor.
-*/
-static int fts3tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
- Fts3tokCursor *pCsr;
- UNUSED_PARAMETER(pVTab);
-
- pCsr = (Fts3tokCursor *)sqlite3_malloc(sizeof(Fts3tokCursor));
- if( pCsr==0 ){
- return SQLITE_NOMEM;
- }
- memset(pCsr, 0, sizeof(Fts3tokCursor));
-
- *ppCsr = (sqlite3_vtab_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** Reset the tokenizer cursor passed as the only argument. As if it had
-** just been returned by fts3tokOpenMethod().
-*/
-static void fts3tokResetCursor(Fts3tokCursor *pCsr){
- if( pCsr->pCsr ){
- Fts3tokTable *pTab = (Fts3tokTable *)(pCsr->base.pVtab);
- pTab->pMod->xClose(pCsr->pCsr);
- pCsr->pCsr = 0;
- }
- sqlite3_free(pCsr->zInput);
- pCsr->zInput = 0;
- pCsr->zToken = 0;
- pCsr->nToken = 0;
- pCsr->iStart = 0;
- pCsr->iEnd = 0;
- pCsr->iPos = 0;
- pCsr->iRowid = 0;
-}
-
-/*
-** xClose - Close a cursor.
-*/
-static int fts3tokCloseMethod(sqlite3_vtab_cursor *pCursor){
- Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
-
- fts3tokResetCursor(pCsr);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** xNext - Advance the cursor to the next row, if any.
-*/
-static int fts3tokNextMethod(sqlite3_vtab_cursor *pCursor){
- Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
- Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
- int rc; /* Return code */
-
- pCsr->iRowid++;
- rc = pTab->pMod->xNext(pCsr->pCsr,
- &pCsr->zToken, &pCsr->nToken,
- &pCsr->iStart, &pCsr->iEnd, &pCsr->iPos
- );
-
- if( rc!=SQLITE_OK ){
- fts3tokResetCursor(pCsr);
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- }
-
- return rc;
-}
-
-/*
-** xFilter - Initialize a cursor to point at the start of its data.
-*/
-static int fts3tokFilterMethod(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, /* Strategy index */
- const char *idxStr, /* Unused */
- int nVal, /* Number of elements in apVal */
- sqlite3_value **apVal /* Arguments for the indexing scheme */
-){
- int rc = SQLITE_ERROR;
- Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
- Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
- UNUSED_PARAMETER(idxStr);
- UNUSED_PARAMETER(nVal);
-
- fts3tokResetCursor(pCsr);
- if( idxNum==1 ){
- const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
- int nByte = sqlite3_value_bytes(apVal[0]);
- pCsr->zInput = sqlite3_malloc(nByte+1);
- if( pCsr->zInput==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memcpy(pCsr->zInput, zByte, nByte);
- pCsr->zInput[nByte] = 0;
- rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
- if( rc==SQLITE_OK ){
- pCsr->pCsr->pTokenizer = pTab->pTok;
- }
- }
- }
-
- if( rc!=SQLITE_OK ) return rc;
- return fts3tokNextMethod(pCursor);
-}
-
-/*
-** xEof - Return true if the cursor is at EOF, or false otherwise.
-*/
-static int fts3tokEofMethod(sqlite3_vtab_cursor *pCursor){
- Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
- return (pCsr->zToken==0);
-}
-
-/*
-** xColumn - Return a column value.
-*/
-static int fts3tokColumnMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
- int iCol /* Index of column to read value from */
-){
- Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
-
- /* CREATE TABLE x(input, token, start, end, position) */
- switch( iCol ){
- case 0:
- sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT);
- break;
- case 1:
- sqlite3_result_text(pCtx, pCsr->zToken, pCsr->nToken, SQLITE_TRANSIENT);
- break;
- case 2:
- sqlite3_result_int(pCtx, pCsr->iStart);
- break;
- case 3:
- sqlite3_result_int(pCtx, pCsr->iEnd);
- break;
- default:
- assert( iCol==4 );
- sqlite3_result_int(pCtx, pCsr->iPos);
- break;
- }
- return SQLITE_OK;
-}
-
-/*
-** xRowid - Return the current rowid for the cursor.
-*/
-static int fts3tokRowidMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite_int64 *pRowid /* OUT: Rowid value */
-){
- Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
- *pRowid = (sqlite3_int64)pCsr->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Register the fts3tok module with database connection db. Return SQLITE_OK
-** if successful or an error code if sqlite3_create_module() fails.
-*/
-int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
- static const sqlite3_module fts3tok_module = {
- 0, /* iVersion */
- fts3tokConnectMethod, /* xCreate */
- fts3tokConnectMethod, /* xConnect */
- fts3tokBestIndexMethod, /* xBestIndex */
- fts3tokDisconnectMethod, /* xDisconnect */
- fts3tokDisconnectMethod, /* xDestroy */
- fts3tokOpenMethod, /* xOpen */
- fts3tokCloseMethod, /* xClose */
- fts3tokFilterMethod, /* xFilter */
- fts3tokNextMethod, /* xNext */
- fts3tokEofMethod, /* xEof */
- fts3tokColumnMethod, /* xColumn */
- fts3tokRowidMethod, /* xRowid */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindFunction */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
- };
- int rc; /* Return code */
-
- rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash);
- return rc;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer.c
deleted file mode 100644
index bfc36af3e38..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
-** 2007 June 22
-**
-** 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 is part of an SQLite module implementing full-text search.
-** This particular file implements the generic tokenizer interface.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS3 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS3 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
-*/
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <assert.h>
-#include <string.h>
-
-/*
-** Return true if the two-argument version of fts3_tokenizer()
-** has been activated via a prior call to sqlite3_db_config(db,
-** SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, 0);
-*/
-static int fts3TokenizerEnabled(sqlite3_context *context){
- sqlite3 *db = sqlite3_context_db_handle(context);
- int isEnabled = 0;
- sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER,-1,&isEnabled);
- return isEnabled;
-}
-
-/*
-** Implementation of the SQL scalar function for accessing the underlying
-** hash table. This function may be called as follows:
-**
-** SELECT <function-name>(<key-name>);
-** SELECT <function-name>(<key-name>, <pointer>);
-**
-** where <function-name> is the name passed as the second argument
-** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer').
-**
-** If the <pointer> argument is specified, it must be a blob value
-** containing a pointer to be stored as the hash data corresponding
-** to the string <key-name>. If <pointer> is not specified, then
-** the string <key-name> must already exist in the has table. Otherwise,
-** an error is returned.
-**
-** Whether or not the <pointer> argument is specified, the value returned
-** is a blob containing the pointer stored as the hash data corresponding
-** to string <key-name> (after the hash-table is updated, if applicable).
-*/
-static void fts3TokenizerFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- Fts3Hash *pHash;
- void *pPtr = 0;
- const unsigned char *zName;
- int nName;
-
- assert( argc==1 || argc==2 );
-
- pHash = (Fts3Hash *)sqlite3_user_data(context);
-
- zName = sqlite3_value_text(argv[0]);
- nName = sqlite3_value_bytes(argv[0])+1;
-
- if( argc==2 ){
- if( fts3TokenizerEnabled(context) ){
- void *pOld;
- int n = sqlite3_value_bytes(argv[1]);
- if( zName==0 || n!=sizeof(pPtr) ){
- sqlite3_result_error(context, "argument type mismatch", -1);
- return;
- }
- pPtr = *(void **)sqlite3_value_blob(argv[1]);
- pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr);
- if( pOld==pPtr ){
- sqlite3_result_error(context, "out of memory", -1);
- }
- }else{
- sqlite3_result_error(context, "fts3tokenize disabled", -1);
- return;
- }
- }else{
- if( zName ){
- pPtr = sqlite3Fts3HashFind(pHash, zName, nName);
- }
- if( !pPtr ){
- char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- return;
- }
- }
- sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
-}
-
-int sqlite3Fts3IsIdChar(char c){
- static const char isFtsIdChar[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
- 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
- };
- return (c&0x80 || isFtsIdChar[(int)(c)]);
-}
-
-const char *sqlite3Fts3NextToken(const char *zStr, int *pn){
- const char *z1;
- const char *z2 = 0;
-
- /* Find the start of the next token. */
- z1 = zStr;
- while( z2==0 ){
- char c = *z1;
- switch( c ){
- case '\0': return 0; /* No more tokens here */
- case '\'':
- case '"':
- case '`': {
- z2 = z1;
- while( *++z2 && (*z2!=c || *++z2==c) );
- break;
- }
- case '[':
- z2 = &z1[1];
- while( *z2 && z2[0]!=']' ) z2++;
- if( *z2 ) z2++;
- break;
-
- default:
- if( sqlite3Fts3IsIdChar(*z1) ){
- z2 = &z1[1];
- while( sqlite3Fts3IsIdChar(*z2) ) z2++;
- }else{
- z1++;
- }
- }
- }
-
- *pn = (int)(z2-z1);
- return z1;
-}
-
-int sqlite3Fts3InitTokenizer(
- Fts3Hash *pHash, /* Tokenizer hash table */
- const char *zArg, /* Tokenizer name */
- sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */
- char **pzErr /* OUT: Set to malloced error message */
-){
- int rc;
- char *z = (char *)zArg;
- int n = 0;
- char *zCopy;
- char *zEnd; /* Pointer to nul-term of zCopy */
- sqlite3_tokenizer_module *m;
-
- zCopy = sqlite3_mprintf("%s", zArg);
- if( !zCopy ) return SQLITE_NOMEM;
- zEnd = &zCopy[strlen(zCopy)];
-
- z = (char *)sqlite3Fts3NextToken(zCopy, &n);
- if( z==0 ){
- assert( n==0 );
- z = zCopy;
- }
- z[n] = '\0';
- sqlite3Fts3Dequote(z);
-
- m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1);
- if( !m ){
- sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z);
- rc = SQLITE_ERROR;
- }else{
- char const **aArg = 0;
- int iArg = 0;
- z = &z[n+1];
- while( z<zEnd && (NULL!=(z = (char *)sqlite3Fts3NextToken(z, &n))) ){
- int nNew = sizeof(char *)*(iArg+1);
- char const **aNew = (const char **)sqlite3_realloc((void *)aArg, nNew);
- if( !aNew ){
- sqlite3_free(zCopy);
- sqlite3_free((void *)aArg);
- return SQLITE_NOMEM;
- }
- aArg = aNew;
- aArg[iArg++] = z;
- z[n] = '\0';
- sqlite3Fts3Dequote(z);
- z = &z[n+1];
- }
- rc = m->xCreate(iArg, aArg, ppTok);
- assert( rc!=SQLITE_OK || *ppTok );
- if( rc!=SQLITE_OK ){
- sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer");
- }else{
- (*ppTok)->pModule = m;
- }
- sqlite3_free((void *)aArg);
- }
-
- sqlite3_free(zCopy);
- return rc;
-}
-
-
-#ifdef SQLITE_TEST
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <string.h>
-
-/*
-** Implementation of a special SQL scalar function for testing tokenizers
-** designed to be used in concert with the Tcl testing framework. This
-** function must be called with two or more arguments:
-**
-** SELECT <function-name>(<key-name>, ..., <input-string>);
-**
-** where <function-name> is the name passed as the second argument
-** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer')
-** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test').
-**
-** The return value is a string that may be interpreted as a Tcl
-** list. For each token in the <input-string>, three elements are
-** added to the returned list. The first is the token position, the
-** second is the token text (folded, stemmed, etc.) and the third is the
-** substring of <input-string> associated with the token. For example,
-** using the built-in "simple" tokenizer:
-**
-** SELECT fts_tokenizer_test('simple', 'I don't see how');
-**
-** will return the string:
-**
-** "{0 i I 1 dont don't 2 see see 3 how how}"
-**
-*/
-static void testFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- Fts3Hash *pHash;
- sqlite3_tokenizer_module *p;
- sqlite3_tokenizer *pTokenizer = 0;
- sqlite3_tokenizer_cursor *pCsr = 0;
-
- const char *zErr = 0;
-
- const char *zName;
- int nName;
- const char *zInput;
- int nInput;
-
- const char *azArg[64];
-
- const char *zToken;
- int nToken = 0;
- int iStart = 0;
- int iEnd = 0;
- int iPos = 0;
- int i;
-
- Tcl_Obj *pRet;
-
- if( argc<2 ){
- sqlite3_result_error(context, "insufficient arguments", -1);
- return;
- }
-
- nName = sqlite3_value_bytes(argv[0]);
- zName = (const char *)sqlite3_value_text(argv[0]);
- nInput = sqlite3_value_bytes(argv[argc-1]);
- zInput = (const char *)sqlite3_value_text(argv[argc-1]);
-
- pHash = (Fts3Hash *)sqlite3_user_data(context);
- p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
-
- if( !p ){
- char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName);
- sqlite3_result_error(context, zErr2, -1);
- sqlite3_free(zErr2);
- return;
- }
-
- pRet = Tcl_NewObj();
- Tcl_IncrRefCount(pRet);
-
- for(i=1; i<argc-1; i++){
- azArg[i-1] = (const char *)sqlite3_value_text(argv[i]);
- }
-
- if( SQLITE_OK!=p->xCreate(argc-2, azArg, &pTokenizer) ){
- zErr = "error in xCreate()";
- goto finish;
- }
- pTokenizer->pModule = p;
- if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){
- zErr = "error in xOpen()";
- goto finish;
- }
-
- while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
- zToken = &zInput[iStart];
- nToken = iEnd-iStart;
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
- }
-
- if( SQLITE_OK!=p->xClose(pCsr) ){
- zErr = "error in xClose()";
- goto finish;
- }
- if( SQLITE_OK!=p->xDestroy(pTokenizer) ){
- zErr = "error in xDestroy()";
- goto finish;
- }
-
-finish:
- if( zErr ){
- sqlite3_result_error(context, zErr, -1);
- }else{
- sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT);
- }
- Tcl_DecrRefCount(pRet);
-}
-
-static
-int registerTokenizer(
- sqlite3 *db,
- char *zName,
- const sqlite3_tokenizer_module *p
-){
- int rc;
- sqlite3_stmt *pStmt;
- const char zSql[] = "SELECT fts3_tokenizer(?, ?)";
-
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
- sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC);
- sqlite3_step(pStmt);
-
- return sqlite3_finalize(pStmt);
-}
-
-
-static
-int queryTokenizer(
- sqlite3 *db,
- char *zName,
- const sqlite3_tokenizer_module **pp
-){
- int rc;
- sqlite3_stmt *pStmt;
- const char zSql[] = "SELECT fts3_tokenizer(?)";
-
- *pp = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
- memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
- }
- }
-
- return sqlite3_finalize(pStmt);
-}
-
-void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-
-/*
-** Implementation of the scalar function fts3_tokenizer_internal_test().
-** This function is used for testing only, it is not included in the
-** build unless SQLITE_TEST is defined.
-**
-** The purpose of this is to test that the fts3_tokenizer() function
-** can be used as designed by the C-code in the queryTokenizer and
-** registerTokenizer() functions above. These two functions are repeated
-** in the README.tokenizer file as an example, so it is important to
-** test them.
-**
-** To run the tests, evaluate the fts3_tokenizer_internal_test() scalar
-** function with no arguments. An assert() will fail if a problem is
-** detected. i.e.:
-**
-** SELECT fts3_tokenizer_internal_test();
-**
-*/
-static void intTestFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int rc;
- const sqlite3_tokenizer_module *p1;
- const sqlite3_tokenizer_module *p2;
- sqlite3 *db = (sqlite3 *)sqlite3_user_data(context);
-
- UNUSED_PARAMETER(argc);
- UNUSED_PARAMETER(argv);
-
- /* Test the query function */
- sqlite3Fts3SimpleTokenizerModule(&p1);
- rc = queryTokenizer(db, "simple", &p2);
- assert( rc==SQLITE_OK );
- assert( p1==p2 );
- rc = queryTokenizer(db, "nosuchtokenizer", &p2);
- assert( rc==SQLITE_ERROR );
- assert( p2==0 );
- assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") );
-
- /* Test the storage function */
- if( fts3TokenizerEnabled(context) ){
- rc = registerTokenizer(db, "nosuchtokenizer", p1);
- assert( rc==SQLITE_OK );
- rc = queryTokenizer(db, "nosuchtokenizer", &p2);
- assert( rc==SQLITE_OK );
- assert( p2==p1 );
- }
-
- sqlite3_result_text(context, "ok", -1, SQLITE_STATIC);
-}
-
-#endif
-
-/*
-** Set up SQL objects in database db used to access the contents of
-** the hash table pointed to by argument pHash. The hash table must
-** been initialized to use string keys, and to take a private copy
-** of the key when a value is inserted. i.e. by a call similar to:
-**
-** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
-**
-** This function adds a scalar function (see header comment above
-** fts3TokenizerFunc() in this file for details) and, if ENABLE_TABLE is
-** defined at compilation time, a temporary virtual table (see header
-** comment above struct HashTableVtab) to the database schema. Both
-** provide read/write access to the contents of *pHash.
-**
-** The third argument to this function, zName, is used as the name
-** of both the scalar and, if created, the virtual table.
-*/
-int sqlite3Fts3InitHashTable(
- sqlite3 *db,
- Fts3Hash *pHash,
- const char *zName
-){
- int rc = SQLITE_OK;
- void *p = (void *)pHash;
- const int any = SQLITE_ANY;
-
-#ifdef SQLITE_TEST
- char *zTest = 0;
- char *zTest2 = 0;
- void *pdb = (void *)db;
- zTest = sqlite3_mprintf("%s_test", zName);
- zTest2 = sqlite3_mprintf("%s_internal_test", zName);
- if( !zTest || !zTest2 ){
- rc = SQLITE_NOMEM;
- }
-#endif
-
- if( SQLITE_OK==rc ){
- rc = sqlite3_create_function(db, zName, 1, any, p, fts3TokenizerFunc, 0, 0);
- }
- if( SQLITE_OK==rc ){
- rc = sqlite3_create_function(db, zName, 2, any, p, fts3TokenizerFunc, 0, 0);
- }
-#ifdef SQLITE_TEST
- if( SQLITE_OK==rc ){
- rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0);
- }
- if( SQLITE_OK==rc ){
- rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0);
- }
-#endif
-
-#ifdef SQLITE_TEST
- sqlite3_free(zTest);
- sqlite3_free(zTest2);
-#endif
-
- return rc;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer.h
deleted file mode 100644
index 4a40b2b3850..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-** 2006 July 10
-**
-** The author disclaims copyright to this source code.
-**
-*************************************************************************
-** Defines the interface to tokenizers used by fulltext-search. There
-** are three basic components:
-**
-** sqlite3_tokenizer_module is a singleton defining the tokenizer
-** interface functions. This is essentially the class structure for
-** tokenizers.
-**
-** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
-** including customization information defined at creation time.
-**
-** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
-** tokens from a particular input.
-*/
-#ifndef _FTS3_TOKENIZER_H_
-#define _FTS3_TOKENIZER_H_
-
-/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
-** If tokenizers are to be allowed to call sqlite3_*() functions, then
-** we will need a way to register the API consistently.
-*/
-#include "sqlite3.h"
-
-/*
-** Structures used by the tokenizer interface. When a new tokenizer
-** implementation is registered, the caller provides a pointer to
-** an sqlite3_tokenizer_module containing pointers to the callback
-** functions that make up an implementation.
-**
-** When an fts3 table is created, it passes any arguments passed to
-** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the
-** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer
-** implementation. The xCreate() function in turn returns an
-** sqlite3_tokenizer structure representing the specific tokenizer to
-** be used for the fts3 table (customized by the tokenizer clause arguments).
-**
-** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen()
-** method is called. It returns an sqlite3_tokenizer_cursor object
-** that may be used to tokenize a specific input buffer based on
-** the tokenization rules supplied by a specific sqlite3_tokenizer
-** object.
-*/
-typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
-typedef struct sqlite3_tokenizer sqlite3_tokenizer;
-typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
-
-struct sqlite3_tokenizer_module {
-
- /*
- ** Structure version. Should always be set to 0 or 1.
- */
- int iVersion;
-
- /*
- ** Create a new tokenizer. The values in the argv[] array are the
- ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL
- ** TABLE statement that created the fts3 table. For example, if
- ** the following SQL is executed:
- **
- ** CREATE .. USING fts3( ... , tokenizer <tokenizer-name> arg1 arg2)
- **
- ** then argc is set to 2, and the argv[] array contains pointers
- ** to the strings "arg1" and "arg2".
- **
- ** This method should return either SQLITE_OK (0), or an SQLite error
- ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
- ** to point at the newly created tokenizer structure. The generic
- ** sqlite3_tokenizer.pModule variable should not be initialized by
- ** this callback. The caller will do so.
- */
- int (*xCreate)(
- int argc, /* Size of argv array */
- const char *const*argv, /* Tokenizer argument strings */
- sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
- );
-
- /*
- ** Destroy an existing tokenizer. The fts3 module calls this method
- ** exactly once for each successful call to xCreate().
- */
- int (*xDestroy)(sqlite3_tokenizer *pTokenizer);
-
- /*
- ** Create a tokenizer cursor to tokenize an input buffer. The caller
- ** is responsible for ensuring that the input buffer remains valid
- ** until the cursor is closed (using the xClose() method).
- */
- int (*xOpen)(
- sqlite3_tokenizer *pTokenizer, /* Tokenizer object */
- const char *pInput, int nBytes, /* Input buffer */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */
- );
-
- /*
- ** Destroy an existing tokenizer cursor. The fts3 module calls this
- ** method exactly once for each successful call to xOpen().
- */
- int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
-
- /*
- ** Retrieve the next token from the tokenizer cursor pCursor. This
- ** method should either return SQLITE_OK and set the values of the
- ** "OUT" variables identified below, or SQLITE_DONE to indicate that
- ** the end of the buffer has been reached, or an SQLite error code.
- **
- ** *ppToken should be set to point at a buffer containing the
- ** normalized version of the token (i.e. after any case-folding and/or
- ** stemming has been performed). *pnBytes should be set to the length
- ** of this buffer in bytes. The input text that generated the token is
- ** identified by the byte offsets returned in *piStartOffset and
- ** *piEndOffset. *piStartOffset should be set to the index of the first
- ** byte of the token in the input buffer. *piEndOffset should be set
- ** to the index of the first byte just past the end of the token in
- ** the input buffer.
- **
- ** The buffer *ppToken is set to point at is managed by the tokenizer
- ** implementation. It is only required to be valid until the next call
- ** to xNext() or xClose().
- */
- /* TODO(shess) current implementation requires pInput to be
- ** nul-terminated. This should either be fixed, or pInput/nBytes
- ** should be converted to zInput.
- */
- int (*xNext)(
- sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */
- const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */
- int *piStartOffset, /* OUT: Byte offset of token in input buffer */
- int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */
- int *piPosition /* OUT: Number of tokens returned before this one */
- );
-
- /***********************************************************************
- ** Methods below this point are only available if iVersion>=1.
- */
-
- /*
- ** Configure the language id of a tokenizer cursor.
- */
- int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid);
-};
-
-struct sqlite3_tokenizer {
- const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
- /* Tokenizer implementations will typically add additional fields */
-};
-
-struct sqlite3_tokenizer_cursor {
- sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */
- /* Tokenizer implementations will typically add additional fields */
-};
-
-int fts3_global_term_cnt(int iTerm, int iCol);
-int fts3_term_cnt(int iTerm, int iCol);
-
-
-#endif /* _FTS3_TOKENIZER_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer1.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer1.c
deleted file mode 100644
index deea06d92bf..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_tokenizer1.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
-** 2006 Oct 10
-**
-** 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.
-**
-******************************************************************************
-**
-** Implementation of the "simple" full-text-search tokenizer.
-*/
-
-/*
-** The code in this file is only compiled if:
-**
-** * The FTS3 module is being built as an extension
-** (in which case SQLITE_CORE is not defined), or
-**
-** * The FTS3 module is being built into the core of
-** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
-*/
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "fts3_tokenizer.h"
-
-typedef struct simple_tokenizer {
- sqlite3_tokenizer base;
- char delim[128]; /* flag ASCII delimiters */
-} simple_tokenizer;
-
-typedef struct simple_tokenizer_cursor {
- sqlite3_tokenizer_cursor base;
- const char *pInput; /* input we are tokenizing */
- int nBytes; /* size of the input */
- int iOffset; /* current position in pInput */
- int iToken; /* index of next token to be returned */
- char *pToken; /* storage for current token */
- int nTokenAllocated; /* space allocated to zToken buffer */
-} simple_tokenizer_cursor;
-
-
-static int simpleDelim(simple_tokenizer *t, unsigned char c){
- return c<0x80 && t->delim[c];
-}
-static int fts3_isalnum(int x){
- return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z');
-}
-
-/*
-** Create a new tokenizer instance.
-*/
-static int simpleCreate(
- int argc, const char * const *argv,
- sqlite3_tokenizer **ppTokenizer
-){
- simple_tokenizer *t;
-
- t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t));
- if( t==NULL ) return SQLITE_NOMEM;
- memset(t, 0, sizeof(*t));
-
- /* TODO(shess) Delimiters need to remain the same from run to run,
- ** else we need to reindex. One solution would be a meta-table to
- ** track such information in the database, then we'd only want this
- ** information on the initial create.
- */
- if( argc>1 ){
- int i, n = (int)strlen(argv[1]);
- for(i=0; i<n; i++){
- unsigned char ch = argv[1][i];
- /* We explicitly don't support UTF-8 delimiters for now. */
- if( ch>=0x80 ){
- sqlite3_free(t);
- return SQLITE_ERROR;
- }
- t->delim[ch] = 1;
- }
- } else {
- /* Mark non-alphanumeric ASCII characters as delimiters */
- int i;
- for(i=1; i<0x80; i++){
- t->delim[i] = !fts3_isalnum(i) ? -1 : 0;
- }
- }
-
- *ppTokenizer = &t->base;
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
- sqlite3_free(pTokenizer);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int simpleOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *pInput, int nBytes, /* String to be tokenized */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- simple_tokenizer_cursor *c;
-
- UNUSED_PARAMETER(pTokenizer);
-
- c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
- if( c==NULL ) return SQLITE_NOMEM;
-
- c->pInput = pInput;
- if( pInput==0 ){
- c->nBytes = 0;
- }else if( nBytes<0 ){
- c->nBytes = (int)strlen(pInput);
- }else{
- c->nBytes = nBytes;
- }
- c->iOffset = 0; /* start tokenizing at the beginning */
- c->iToken = 0;
- c->pToken = NULL; /* no space allocated, yet. */
- c->nTokenAllocated = 0;
-
- *ppCursor = &c->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to
-** simpleOpen() above.
-*/
-static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
- simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
- sqlite3_free(c->pToken);
- sqlite3_free(c);
- return SQLITE_OK;
-}
-
-/*
-** Extract the next token from a tokenization cursor. The cursor must
-** have been opened by a prior call to simpleOpen().
-*/
-static int simpleNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
- const char **ppToken, /* OUT: *ppToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
- simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
- unsigned char *p = (unsigned char *)c->pInput;
-
- while( c->iOffset<c->nBytes ){
- int iStartOffset;
-
- /* Scan past delimiter characters */
- while( c->iOffset<c->nBytes && simpleDelim(t, p[c->iOffset]) ){
- c->iOffset++;
- }
-
- /* Count non-delimiter characters. */
- iStartOffset = c->iOffset;
- while( c->iOffset<c->nBytes && !simpleDelim(t, p[c->iOffset]) ){
- c->iOffset++;
- }
-
- if( c->iOffset>iStartOffset ){
- int i, n = c->iOffset-iStartOffset;
- if( n>c->nTokenAllocated ){
- char *pNew;
- c->nTokenAllocated = n+20;
- pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated);
- if( !pNew ) return SQLITE_NOMEM;
- c->pToken = pNew;
- }
- for(i=0; i<n; i++){
- /* TODO(shess) This needs expansion to handle UTF-8
- ** case-insensitivity.
- */
- unsigned char ch = p[iStartOffset+i];
- c->pToken[i] = (char)((ch>='A' && ch<='Z') ? ch-'A'+'a' : ch);
- }
- *ppToken = c->pToken;
- *pnBytes = n;
- *piStartOffset = iStartOffset;
- *piEndOffset = c->iOffset;
- *piPosition = c->iToken++;
-
- return SQLITE_OK;
- }
- }
- return SQLITE_DONE;
-}
-
-/*
-** The set of routines that implement the simple tokenizer
-*/
-static const sqlite3_tokenizer_module simpleTokenizerModule = {
- 0,
- simpleCreate,
- simpleDestroy,
- simpleOpen,
- simpleClose,
- simpleNext,
- 0,
-};
-
-/*
-** Allocate a new simple tokenizer. Return a pointer to the new
-** tokenizer in *ppModule
-*/
-void sqlite3Fts3SimpleTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &simpleTokenizerModule;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_unicode.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_unicode.c
deleted file mode 100644
index dfb2680c505..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_unicode.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
-** 2012 May 24
-**
-** 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.
-**
-******************************************************************************
-**
-** Implementation of the "unicode" full-text-search tokenizer.
-*/
-
-#ifndef SQLITE_DISABLE_FTS3_UNICODE
-
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "fts3_tokenizer.h"
-
-/*
-** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
-** from the sqlite3 source file utf.c. If this file is compiled as part
-** of the amalgamation, they are not required.
-*/
-#ifndef SQLITE_AMALGAMATION
-
-static const unsigned char sqlite3Utf8Trans1[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
-};
-
-#define READ_UTF8(zIn, zTerm, c) \
- c = *(zIn++); \
- if( c>=0xc0 ){ \
- c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
- c = (c<<6) + (0x3f & *(zIn++)); \
- } \
- if( c<0x80 \
- || (c&0xFFFFF800)==0xD800 \
- || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
- }
-
-#define WRITE_UTF8(zOut, c) { \
- if( c<0x00080 ){ \
- *zOut++ = (u8)(c&0xFF); \
- } \
- else if( c<0x00800 ){ \
- *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- } \
- else if( c<0x10000 ){ \
- *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- }else{ \
- *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
- *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- } \
-}
-
-#endif /* ifndef SQLITE_AMALGAMATION */
-
-typedef struct unicode_tokenizer unicode_tokenizer;
-typedef struct unicode_cursor unicode_cursor;
-
-struct unicode_tokenizer {
- sqlite3_tokenizer base;
- int bRemoveDiacritic;
- int nException;
- int *aiException;
-};
-
-struct unicode_cursor {
- sqlite3_tokenizer_cursor base;
- const unsigned char *aInput; /* Input text being tokenized */
- int nInput; /* Size of aInput[] in bytes */
- int iOff; /* Current offset within aInput[] */
- int iToken; /* Index of next token to be returned */
- char *zToken; /* storage for current token */
- int nAlloc; /* space allocated at zToken */
-};
-
-
-/*
-** Destroy a tokenizer allocated by unicodeCreate().
-*/
-static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
- if( pTokenizer ){
- unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer;
- sqlite3_free(p->aiException);
- sqlite3_free(p);
- }
- return SQLITE_OK;
-}
-
-/*
-** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE
-** statement has specified that the tokenizer for this table shall consider
-** all characters in string zIn/nIn to be separators (if bAlnum==0) or
-** token characters (if bAlnum==1).
-**
-** For each codepoint in the zIn/nIn string, this function checks if the
-** sqlite3FtsUnicodeIsalnum() function already returns the desired result.
-** If so, no action is taken. Otherwise, the codepoint is added to the
-** unicode_tokenizer.aiException[] array. For the purposes of tokenization,
-** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all
-** codepoints in the aiException[] array.
-**
-** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
-** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
-** It is not possible to change the behavior of the tokenizer with respect
-** to these codepoints.
-*/
-static int unicodeAddExceptions(
- unicode_tokenizer *p, /* Tokenizer to add exceptions to */
- int bAlnum, /* Replace Isalnum() return value with this */
- const char *zIn, /* Array of characters to make exceptions */
- int nIn /* Length of z in bytes */
-){
- const unsigned char *z = (const unsigned char *)zIn;
- const unsigned char *zTerm = &z[nIn];
- unsigned int iCode;
- int nEntry = 0;
-
- assert( bAlnum==0 || bAlnum==1 );
-
- while( z<zTerm ){
- READ_UTF8(z, zTerm, iCode);
- assert( (sqlite3FtsUnicodeIsalnum((int)iCode) & 0xFFFFFFFE)==0 );
- if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
- && sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
- ){
- nEntry++;
- }
- }
-
- if( nEntry ){
- int *aNew; /* New aiException[] array */
- int nNew; /* Number of valid entries in array aNew[] */
-
- aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
- if( aNew==0 ) return SQLITE_NOMEM;
- nNew = p->nException;
-
- z = (const unsigned char *)zIn;
- while( z<zTerm ){
- READ_UTF8(z, zTerm, iCode);
- if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
- && sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
- ){
- int i, j;
- for(i=0; i<nNew && aNew[i]<(int)iCode; i++);
- for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
- aNew[i] = (int)iCode;
- nNew++;
- }
- }
- p->aiException = aNew;
- p->nException = nNew;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Return true if the p->aiException[] array contains the value iCode.
-*/
-static int unicodeIsException(unicode_tokenizer *p, int iCode){
- if( p->nException>0 ){
- int *a = p->aiException;
- int iLo = 0;
- int iHi = p->nException-1;
-
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( iCode==a[iTest] ){
- return 1;
- }else if( iCode>a[iTest] ){
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- }
-
- return 0;
-}
-
-/*
-** Return true if, for the purposes of tokenization, codepoint iCode is
-** considered a token character (not a separator).
-*/
-static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){
- assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
- return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode);
-}
-
-/*
-** Create a new tokenizer instance.
-*/
-static int unicodeCreate(
- int nArg, /* Size of array argv[] */
- const char * const *azArg, /* Tokenizer creation arguments */
- sqlite3_tokenizer **pp /* OUT: New tokenizer handle */
-){
- unicode_tokenizer *pNew; /* New tokenizer object */
- int i;
- int rc = SQLITE_OK;
-
- pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
- if( pNew==NULL ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(unicode_tokenizer));
- pNew->bRemoveDiacritic = 1;
-
- for(i=0; rc==SQLITE_OK && i<nArg; i++){
- const char *z = azArg[i];
- int n = (int)strlen(z);
-
- if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
- pNew->bRemoveDiacritic = 1;
- }
- else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
- pNew->bRemoveDiacritic = 0;
- }
- else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
- rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
- }
- else if( n>=11 && memcmp("separators=", z, 11)==0 ){
- rc = unicodeAddExceptions(pNew, 0, &z[11], n-11);
- }
- else{
- /* Unrecognized argument */
- rc = SQLITE_ERROR;
- }
- }
-
- if( rc!=SQLITE_OK ){
- unicodeDestroy((sqlite3_tokenizer *)pNew);
- pNew = 0;
- }
- *pp = (sqlite3_tokenizer *)pNew;
- return rc;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int unicodeOpen(
- sqlite3_tokenizer *p, /* The tokenizer */
- const char *aInput, /* Input string */
- int nInput, /* Size of string aInput in bytes */
- sqlite3_tokenizer_cursor **pp /* OUT: New cursor object */
-){
- unicode_cursor *pCsr;
-
- pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor));
- if( pCsr==0 ){
- return SQLITE_NOMEM;
- }
- memset(pCsr, 0, sizeof(unicode_cursor));
-
- pCsr->aInput = (const unsigned char *)aInput;
- if( aInput==0 ){
- pCsr->nInput = 0;
- }else if( nInput<0 ){
- pCsr->nInput = (int)strlen(aInput);
- }else{
- pCsr->nInput = nInput;
- }
-
- *pp = &pCsr->base;
- UNUSED_PARAMETER(p);
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to
-** simpleOpen() above.
-*/
-static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){
- unicode_cursor *pCsr = (unicode_cursor *) pCursor;
- sqlite3_free(pCsr->zToken);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Extract the next token from a tokenization cursor. The cursor must
-** have been opened by a prior call to simpleOpen().
-*/
-static int unicodeNext(
- sqlite3_tokenizer_cursor *pC, /* Cursor returned by simpleOpen */
- const char **paToken, /* OUT: Token text */
- int *pnToken, /* OUT: Number of bytes at *paToken */
- int *piStart, /* OUT: Starting offset of token */
- int *piEnd, /* OUT: Ending offset of token */
- int *piPos /* OUT: Position integer of token */
-){
- unicode_cursor *pCsr = (unicode_cursor *)pC;
- unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
- unsigned int iCode = 0;
- char *zOut;
- const unsigned char *z = &pCsr->aInput[pCsr->iOff];
- const unsigned char *zStart = z;
- const unsigned char *zEnd;
- const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
-
- /* Scan past any delimiter characters before the start of the next token.
- ** Return SQLITE_DONE early if this takes us all the way to the end of
- ** the input. */
- while( z<zTerm ){
- READ_UTF8(z, zTerm, iCode);
- if( unicodeIsAlnum(p, (int)iCode) ) break;
- zStart = z;
- }
- if( zStart>=zTerm ) return SQLITE_DONE;
-
- zOut = pCsr->zToken;
- do {
- int iOut;
-
- /* Grow the output buffer if required. */
- if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
- char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
- if( !zNew ) return SQLITE_NOMEM;
- zOut = &zNew[zOut - pCsr->zToken];
- pCsr->zToken = zNew;
- pCsr->nAlloc += 64;
- }
-
- /* Write the folded case of the last character read to the output */
- zEnd = z;
- iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
- if( iOut ){
- WRITE_UTF8(zOut, iOut);
- }
-
- /* If the cursor is not at EOF, read the next character */
- if( z>=zTerm ) break;
- READ_UTF8(z, zTerm, iCode);
- }while( unicodeIsAlnum(p, (int)iCode)
- || sqlite3FtsUnicodeIsdiacritic((int)iCode)
- );
-
- /* Set the output variables and return. */
- pCsr->iOff = (int)(z - pCsr->aInput);
- *paToken = pCsr->zToken;
- *pnToken = (int)(zOut - pCsr->zToken);
- *piStart = (int)(zStart - pCsr->aInput);
- *piEnd = (int)(zEnd - pCsr->aInput);
- *piPos = pCsr->iToken++;
- return SQLITE_OK;
-}
-
-/*
-** Set *ppModule to a pointer to the sqlite3_tokenizer_module
-** structure for the unicode tokenizer.
-*/
-void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){
- static const sqlite3_tokenizer_module module = {
- 0,
- unicodeCreate,
- unicodeDestroy,
- unicodeOpen,
- unicodeClose,
- unicodeNext,
- 0,
- };
- *ppModule = &module;
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
-#endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_unicode2.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_unicode2.c
deleted file mode 100644
index da7251ed0cb..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_unicode2.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
-** 2012 May 25
-**
-** 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.
-**
-******************************************************************************
-*/
-
-/*
-** DO NOT EDIT THIS MACHINE GENERATED FILE.
-*/
-
-#ifndef SQLITE_DISABLE_FTS3_UNICODE
-#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
-
-#include <assert.h>
-
-/*
-** Return true if the argument corresponds to a unicode codepoint
-** classified as either a letter or a number. Otherwise false.
-**
-** The results are undefined if the value passed to this function
-** is less than zero.
-*/
-int sqlite3FtsUnicodeIsalnum(int c){
- /* Each unsigned integer in the following array corresponds to a contiguous
- ** range of unicode codepoints that are not either letters or numbers (i.e.
- ** codepoints for which this function should return 0).
- **
- ** The most significant 22 bits in each 32-bit value contain the first
- ** codepoint in the range. The least significant 10 bits are used to store
- ** the size of the range (always at least 1). In other words, the value
- ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
- ** C. It is not possible to represent a range larger than 1023 codepoints
- ** using this format.
- */
- static const unsigned int aEntry[] = {
- 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
- 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
- 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
- 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
- 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
- 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
- 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
- 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401,
- 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804,
- 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403,
- 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812,
- 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001,
- 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802,
- 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805,
- 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401,
- 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
- 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807,
- 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001,
- 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01,
- 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804,
- 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001,
- 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802,
- 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01,
- 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06,
- 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007,
- 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006,
- 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417,
- 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14,
- 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07,
- 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01,
- 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001,
- 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802,
- 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F,
- 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
- 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802,
- 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006,
- 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D,
- 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802,
- 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027,
- 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
- 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805,
- 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04,
- 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
- 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
- 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B,
- 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A,
- 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
- 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59,
- 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
- 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
- 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
- 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
- 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
- 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
- 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
- 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012,
- 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
- 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002,
- 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
- 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
- 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
- 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802,
- 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013,
- 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06,
- 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003,
- 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01,
- 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403,
- 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009,
- 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003,
- 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003,
- 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E,
- 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046,
- 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401,
- 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401,
- 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F,
- 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C,
- 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002,
- 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025,
- 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6,
- 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46,
- 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060,
- 0x380400F0,
- };
- static const unsigned int aAscii[4] = {
- 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
- };
-
- if( (unsigned int)c<128 ){
- return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
- }else if( (unsigned int)c<(1<<22) ){
- unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
- int iRes = 0;
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
- int iLo = 0;
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( key >= aEntry[iTest] ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- assert( aEntry[0]<key );
- assert( key>=aEntry[iRes] );
- return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
- }
- return 1;
-}
-
-
-/*
-** If the argument is a codepoint corresponding to a lowercase letter
-** in the ASCII range with a diacritic added, return the codepoint
-** of the ASCII letter only. For example, if passed 235 - "LATIN
-** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
-** E"). The resuls of passing a codepoint that corresponds to an
-** uppercase letter are undefined.
-*/
-static int remove_diacritic(int c){
- unsigned short aDia[] = {
- 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
- 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
- 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
- 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
- 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
- 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
- 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
- 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
- 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
- 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
- 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
- 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
- 62924, 63050, 63082, 63274, 63390,
- };
- char aChar[] = {
- '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
- 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
- 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
- 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
- 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
- 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
- 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
- 'e', 'i', 'o', 'u', 'y',
- };
-
- unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
- int iRes = 0;
- int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
- int iLo = 0;
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( key >= aDia[iTest] ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- assert( key>=aDia[iRes] );
- return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
-}
-
-
-/*
-** Return true if the argument interpreted as a unicode codepoint
-** is a diacritical modifier character.
-*/
-int sqlite3FtsUnicodeIsdiacritic(int c){
- unsigned int mask0 = 0x08029FDF;
- unsigned int mask1 = 0x000361F8;
- if( c<768 || c>817 ) return 0;
- return (c < 768+32) ?
- (mask0 & (1 << (c-768))) :
- (mask1 & (1 << (c-768-32)));
-}
-
-
-/*
-** Interpret the argument as a unicode codepoint. If the codepoint
-** is an upper case character that has a lower case equivalent,
-** return the codepoint corresponding to the lower case version.
-** Otherwise, return a copy of the argument.
-**
-** The results are undefined if the value passed to this function
-** is less than zero.
-*/
-int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
- /* Each entry in the following array defines a rule for folding a range
- ** of codepoints to lower case. The rule applies to a range of nRange
- ** codepoints starting at codepoint iCode.
- **
- ** If the least significant bit in flags is clear, then the rule applies
- ** to all nRange codepoints (i.e. all nRange codepoints are upper case and
- ** need to be folded). Or, if it is set, then the rule only applies to
- ** every second codepoint in the range, starting with codepoint C.
- **
- ** The 7 most significant bits in flags are an index into the aiOff[]
- ** array. If a specific codepoint C does require folding, then its lower
- ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF).
- **
- ** The contents of this array are generated by parsing the CaseFolding.txt
- ** file distributed as part of the "Unicode Character Database". See
- ** http://www.unicode.org for details.
- */
- static const struct TableEntry {
- unsigned short iCode;
- unsigned char flags;
- unsigned char nRange;
- } aEntry[] = {
- {65, 14, 26}, {181, 64, 1}, {192, 14, 23},
- {216, 14, 7}, {256, 1, 48}, {306, 1, 6},
- {313, 1, 16}, {330, 1, 46}, {376, 116, 1},
- {377, 1, 6}, {383, 104, 1}, {385, 50, 1},
- {386, 1, 4}, {390, 44, 1}, {391, 0, 1},
- {393, 42, 2}, {395, 0, 1}, {398, 32, 1},
- {399, 38, 1}, {400, 40, 1}, {401, 0, 1},
- {403, 42, 1}, {404, 46, 1}, {406, 52, 1},
- {407, 48, 1}, {408, 0, 1}, {412, 52, 1},
- {413, 54, 1}, {415, 56, 1}, {416, 1, 6},
- {422, 60, 1}, {423, 0, 1}, {425, 60, 1},
- {428, 0, 1}, {430, 60, 1}, {431, 0, 1},
- {433, 58, 2}, {435, 1, 4}, {439, 62, 1},
- {440, 0, 1}, {444, 0, 1}, {452, 2, 1},
- {453, 0, 1}, {455, 2, 1}, {456, 0, 1},
- {458, 2, 1}, {459, 1, 18}, {478, 1, 18},
- {497, 2, 1}, {498, 1, 4}, {502, 122, 1},
- {503, 134, 1}, {504, 1, 40}, {544, 110, 1},
- {546, 1, 18}, {570, 70, 1}, {571, 0, 1},
- {573, 108, 1}, {574, 68, 1}, {577, 0, 1},
- {579, 106, 1}, {580, 28, 1}, {581, 30, 1},
- {582, 1, 10}, {837, 36, 1}, {880, 1, 4},
- {886, 0, 1}, {902, 18, 1}, {904, 16, 3},
- {908, 26, 1}, {910, 24, 2}, {913, 14, 17},
- {931, 14, 9}, {962, 0, 1}, {975, 4, 1},
- {976, 140, 1}, {977, 142, 1}, {981, 146, 1},
- {982, 144, 1}, {984, 1, 24}, {1008, 136, 1},
- {1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1},
- {1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1},
- {1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32},
- {1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1},
- {1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38},
- {4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1},
- {7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1},
- {7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6},
- {7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6},
- {8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8},
- {8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2},
- {8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1},
- {8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2},
- {8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2},
- {8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2},
- {8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1},
- {8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16},
- {8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47},
- {11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1},
- {11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1},
- {11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1},
- {11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2},
- {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1},
- {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14},
- {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1},
- {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1},
- {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1},
- {65313, 14, 26},
- };
- static const unsigned short aiOff[] = {
- 1, 2, 8, 15, 16, 26, 28, 32,
- 37, 38, 40, 48, 63, 64, 69, 71,
- 79, 80, 116, 202, 203, 205, 206, 207,
- 209, 210, 211, 213, 214, 217, 218, 219,
- 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721,
- 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274,
- 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406,
- 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462,
- 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511,
- 65514, 65521, 65527, 65528, 65529,
- };
-
- int ret = c;
-
- assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
-
- if( c<128 ){
- if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
- }else if( c<65536 ){
- const struct TableEntry *p;
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
- int iLo = 0;
- int iRes = -1;
-
- assert( c>aEntry[0].iCode );
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- int cmp = (c - aEntry[iTest].iCode);
- if( cmp>=0 ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
-
- assert( iRes>=0 && c>=aEntry[iRes].iCode );
- p = &aEntry[iRes];
- if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
- ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
- assert( ret>0 );
- }
-
- if( bRemoveDiacritic ) ret = remove_diacritic(ret);
- }
-
- else if( c>=66560 && c<66600 ){
- ret = c + 40;
- }
-
- return ret;
-}
-#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */
-#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_write.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_write.c
deleted file mode 100644
index 0baf82b76ec..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3_write.c
+++ /dev/null
@@ -1,5685 +0,0 @@
-/*
-** 2009 Oct 23
-**
-** 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 is part of the SQLite FTS3 extension module. Specifically,
-** this file contains code to insert, update and delete rows from FTS3
-** tables. It also contains code to merge FTS3 b-tree segments. Some
-** of the sub-routines used to merge segments are also used by the query
-** code in fts3.c.
-*/
-
-#include "fts3Int.h"
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-
-
-#define FTS_MAX_APPENDABLE_HEIGHT 16
-
-/*
-** When full-text index nodes are loaded from disk, the buffer that they
-** are loaded into has the following number of bytes of padding at the end
-** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
-** of 920 bytes is allocated for it.
-**
-** This means that if we have a pointer into a buffer containing node data,
-** it is always safe to read up to two varints from it without risking an
-** overread, even if the node data is corrupted.
-*/
-#define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2)
-
-/*
-** Under certain circumstances, b-tree nodes (doclists) can be loaded into
-** memory incrementally instead of all at once. This can be a big performance
-** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext()
-** method before retrieving all query results (as may happen, for example,
-** if a query has a LIMIT clause).
-**
-** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
-** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes.
-** The code is written so that the hard lower-limit for each of these values
-** is 1. Clearly such small values would be inefficient, but can be useful
-** for testing purposes.
-**
-** If this module is built with SQLITE_TEST defined, these constants may
-** be overridden at runtime for testing purposes. File fts3_test.c contains
-** a Tcl interface to read and write the values.
-*/
-#ifdef SQLITE_TEST
-int test_fts3_node_chunksize = (4*1024);
-int test_fts3_node_chunk_threshold = (4*1024)*4;
-# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize
-# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
-#else
-# define FTS3_NODE_CHUNKSIZE (4*1024)
-# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
-#endif
-
-/*
-** The two values that may be meaningfully bound to the :1 parameter in
-** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
-*/
-#define FTS_STAT_DOCTOTAL 0
-#define FTS_STAT_INCRMERGEHINT 1
-#define FTS_STAT_AUTOINCRMERGE 2
-
-/*
-** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic
-** and incremental merge operation that takes place. This is used for
-** debugging FTS only, it should not usually be turned on in production
-** systems.
-*/
-#ifdef FTS3_LOG_MERGES
-static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){
- sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel);
-}
-#else
-#define fts3LogMerge(x, y)
-#endif
-
-
-typedef struct PendingList PendingList;
-typedef struct SegmentNode SegmentNode;
-typedef struct SegmentWriter SegmentWriter;
-
-/*
-** An instance of the following data structure is used to build doclists
-** incrementally. See function fts3PendingListAppend() for details.
-*/
-struct PendingList {
- int nData;
- char *aData;
- int nSpace;
- sqlite3_int64 iLastDocid;
- sqlite3_int64 iLastCol;
- sqlite3_int64 iLastPos;
-};
-
-
-/*
-** Each cursor has a (possibly empty) linked list of the following objects.
-*/
-struct Fts3DeferredToken {
- Fts3PhraseToken *pToken; /* Pointer to corresponding expr token */
- int iCol; /* Column token must occur in */
- Fts3DeferredToken *pNext; /* Next in list of deferred tokens */
- PendingList *pList; /* Doclist is assembled here */
-};
-
-/*
-** An instance of this structure is used to iterate through the terms on
-** a contiguous set of segment b-tree leaf nodes. Although the details of
-** this structure are only manipulated by code in this file, opaque handles
-** of type Fts3SegReader* are also used by code in fts3.c to iterate through
-** terms when querying the full-text index. See functions:
-**
-** sqlite3Fts3SegReaderNew()
-** sqlite3Fts3SegReaderFree()
-** sqlite3Fts3SegReaderIterate()
-**
-** Methods used to manipulate Fts3SegReader structures:
-**
-** fts3SegReaderNext()
-** fts3SegReaderFirstDocid()
-** fts3SegReaderNextDocid()
-*/
-struct Fts3SegReader {
- int iIdx; /* Index within level, or 0x7FFFFFFF for PT */
- u8 bLookup; /* True for a lookup only */
- u8 rootOnly; /* True for a root-only reader */
-
- sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */
- sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */
- sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */
- sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */
-
- char *aNode; /* Pointer to node data (or NULL) */
- int nNode; /* Size of buffer at aNode (or 0) */
- int nPopulate; /* If >0, bytes of buffer aNode[] loaded */
- sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */
-
- Fts3HashElem **ppNextElem;
-
- /* Variables set by fts3SegReaderNext(). These may be read directly
- ** by the caller. They are valid from the time SegmentReaderNew() returns
- ** until SegmentReaderNext() returns something other than SQLITE_OK
- ** (i.e. SQLITE_DONE).
- */
- int nTerm; /* Number of bytes in current term */
- char *zTerm; /* Pointer to current term */
- int nTermAlloc; /* Allocated size of zTerm buffer */
- char *aDoclist; /* Pointer to doclist of current entry */
- int nDoclist; /* Size of doclist in current entry */
-
- /* The following variables are used by fts3SegReaderNextDocid() to iterate
- ** through the current doclist (aDoclist/nDoclist).
- */
- char *pOffsetList;
- int nOffsetList; /* For descending pending seg-readers only */
- sqlite3_int64 iDocid;
-};
-
-#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
-#define fts3SegReaderIsRootOnly(p) ((p)->rootOnly!=0)
-
-/*
-** An instance of this structure is used to create a segment b-tree in the
-** database. The internal details of this type are only accessed by the
-** following functions:
-**
-** fts3SegWriterAdd()
-** fts3SegWriterFlush()
-** fts3SegWriterFree()
-*/
-struct SegmentWriter {
- SegmentNode *pTree; /* Pointer to interior tree structure */
- sqlite3_int64 iFirst; /* First slot in %_segments written */
- sqlite3_int64 iFree; /* Next free slot in %_segments */
- char *zTerm; /* Pointer to previous term buffer */
- int nTerm; /* Number of bytes in zTerm */
- int nMalloc; /* Size of malloc'd buffer at zMalloc */
- char *zMalloc; /* Malloc'd space (possibly) used for zTerm */
- int nSize; /* Size of allocation at aData */
- int nData; /* Bytes of data in aData */
- char *aData; /* Pointer to block from malloc() */
- i64 nLeafData; /* Number of bytes of leaf data written */
-};
-
-/*
-** Type SegmentNode is used by the following three functions to create
-** the interior part of the segment b+-tree structures (everything except
-** the leaf nodes). These functions and type are only ever used by code
-** within the fts3SegWriterXXX() family of functions described above.
-**
-** fts3NodeAddTerm()
-** fts3NodeWrite()
-** fts3NodeFree()
-**
-** When a b+tree is written to the database (either as a result of a merge
-** or the pending-terms table being flushed), leaves are written into the
-** database file as soon as they are completely populated. The interior of
-** the tree is assembled in memory and written out only once all leaves have
-** been populated and stored. This is Ok, as the b+-tree fanout is usually
-** very large, meaning that the interior of the tree consumes relatively
-** little memory.
-*/
-struct SegmentNode {
- SegmentNode *pParent; /* Parent node (or NULL for root node) */
- SegmentNode *pRight; /* Pointer to right-sibling */
- SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */
- int nEntry; /* Number of terms written to node so far */
- char *zTerm; /* Pointer to previous term buffer */
- int nTerm; /* Number of bytes in zTerm */
- int nMalloc; /* Size of malloc'd buffer at zMalloc */
- char *zMalloc; /* Malloc'd space (possibly) used for zTerm */
- int nData; /* Bytes of valid data so far */
- char *aData; /* Node data */
-};
-
-/*
-** Valid values for the second argument to fts3SqlStmt().
-*/
-#define SQL_DELETE_CONTENT 0
-#define SQL_IS_EMPTY 1
-#define SQL_DELETE_ALL_CONTENT 2
-#define SQL_DELETE_ALL_SEGMENTS 3
-#define SQL_DELETE_ALL_SEGDIR 4
-#define SQL_DELETE_ALL_DOCSIZE 5
-#define SQL_DELETE_ALL_STAT 6
-#define SQL_SELECT_CONTENT_BY_ROWID 7
-#define SQL_NEXT_SEGMENT_INDEX 8
-#define SQL_INSERT_SEGMENTS 9
-#define SQL_NEXT_SEGMENTS_ID 10
-#define SQL_INSERT_SEGDIR 11
-#define SQL_SELECT_LEVEL 12
-#define SQL_SELECT_LEVEL_RANGE 13
-#define SQL_SELECT_LEVEL_COUNT 14
-#define SQL_SELECT_SEGDIR_MAX_LEVEL 15
-#define SQL_DELETE_SEGDIR_LEVEL 16
-#define SQL_DELETE_SEGMENTS_RANGE 17
-#define SQL_CONTENT_INSERT 18
-#define SQL_DELETE_DOCSIZE 19
-#define SQL_REPLACE_DOCSIZE 20
-#define SQL_SELECT_DOCSIZE 21
-#define SQL_SELECT_STAT 22
-#define SQL_REPLACE_STAT 23
-
-#define SQL_SELECT_ALL_PREFIX_LEVEL 24
-#define SQL_DELETE_ALL_TERMS_SEGDIR 25
-#define SQL_DELETE_SEGDIR_RANGE 26
-#define SQL_SELECT_ALL_LANGID 27
-#define SQL_FIND_MERGE_LEVEL 28
-#define SQL_MAX_LEAF_NODE_ESTIMATE 29
-#define SQL_DELETE_SEGDIR_ENTRY 30
-#define SQL_SHIFT_SEGDIR_ENTRY 31
-#define SQL_SELECT_SEGDIR 32
-#define SQL_CHOMP_SEGDIR 33
-#define SQL_SEGMENT_IS_APPENDABLE 34
-#define SQL_SELECT_INDEXES 35
-#define SQL_SELECT_MXLEVEL 36
-
-#define SQL_SELECT_LEVEL_RANGE2 37
-#define SQL_UPDATE_LEVEL_IDX 38
-#define SQL_UPDATE_LEVEL 39
-
-/*
-** This function is used to obtain an SQLite prepared statement handle
-** for the statement identified by the second argument. If successful,
-** *pp is set to the requested statement handle and SQLITE_OK returned.
-** Otherwise, an SQLite error code is returned and *pp is set to 0.
-**
-** If argument apVal is not NULL, then it must point to an array with
-** at least as many entries as the requested statement has bound
-** parameters. The values are bound to the statements parameters before
-** returning.
-*/
-static int fts3SqlStmt(
- Fts3Table *p, /* Virtual table handle */
- int eStmt, /* One of the SQL_XXX constants above */
- sqlite3_stmt **pp, /* OUT: Statement handle */
- sqlite3_value **apVal /* Values to bind to statement */
-){
- const char *azSql[] = {
-/* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?",
-/* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)",
-/* 2 */ "DELETE FROM %Q.'%q_content'",
-/* 3 */ "DELETE FROM %Q.'%q_segments'",
-/* 4 */ "DELETE FROM %Q.'%q_segdir'",
-/* 5 */ "DELETE FROM %Q.'%q_docsize'",
-/* 6 */ "DELETE FROM %Q.'%q_stat'",
-/* 7 */ "SELECT %s WHERE rowid=?",
-/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1",
-/* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
-/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
-/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
-
- /* Return segments in order from oldest to newest.*/
-/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
- "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
-/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
- "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?"
- "ORDER BY level DESC, idx ASC",
-
-/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
-/* 15 */ "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
-
-/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
-/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
-/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
-/* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
-/* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
-/* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
-/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?",
-/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)",
-/* 24 */ "",
-/* 25 */ "",
-
-/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
-/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'",
-
-/* This statement is used to determine which level to read the input from
-** when performing an incremental merge. It returns the absolute level number
-** of the oldest level in the db that contains at least ? segments. Or,
-** if no level in the FTS index contains more than ? segments, the statement
-** returns zero rows. */
-/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' "
- " GROUP BY level HAVING cnt>=?"
- " ORDER BY (level %% 1024) ASC LIMIT 1",
-
-/* Estimate the upper limit on the number of leaf nodes in a new segment
-** created by merging the oldest :2 segments from absolute level :1. See
-** function sqlite3Fts3Incrmerge() for details. */
-/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
- " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
-
-/* SQL_DELETE_SEGDIR_ENTRY
-** Delete the %_segdir entry on absolute level :1 with index :2. */
-/* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
-
-/* SQL_SHIFT_SEGDIR_ENTRY
-** Modify the idx value for the segment with idx=:3 on absolute level :2
-** to :1. */
-/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?",
-
-/* SQL_SELECT_SEGDIR
-** Read a single entry from the %_segdir table. The entry from absolute
-** level :1 with index value :2. */
-/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
- "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
-
-/* SQL_CHOMP_SEGDIR
-** Update the start_block (:1) and root (:2) fields of the %_segdir
-** entry located on absolute level :3 with index :4. */
-/* 33 */ "UPDATE %Q.'%q_segdir' SET start_block = ?, root = ?"
- "WHERE level = ? AND idx = ?",
-
-/* SQL_SEGMENT_IS_APPENDABLE
-** Return a single row if the segment with end_block=? is appendable. Or
-** no rows otherwise. */
-/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL",
-
-/* SQL_SELECT_INDEXES
-** Return the list of valid segment indexes for absolute level ? */
-/* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC",
-
-/* SQL_SELECT_MXLEVEL
-** Return the largest relative level in the FTS index or indexes. */
-/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'",
-
- /* Return segments in order from oldest to newest.*/
-/* 37 */ "SELECT level, idx, end_block "
- "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? "
- "ORDER BY level DESC, idx ASC",
-
- /* Update statements used while promoting segments */
-/* 38 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=-1,idx=? "
- "WHERE level=? AND idx=?",
-/* 39 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=? WHERE level=-1"
-
- };
- int rc = SQLITE_OK;
- sqlite3_stmt *pStmt;
-
- assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
- assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
-
- pStmt = p->aStmt[eStmt];
- if( !pStmt ){
- char *zSql;
- if( eStmt==SQL_CONTENT_INSERT ){
- zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
- }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
- zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
- }else{
- zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
- }
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
- &pStmt, NULL);
- sqlite3_free(zSql);
- assert( rc==SQLITE_OK || pStmt==0 );
- p->aStmt[eStmt] = pStmt;
- }
- }
- if( apVal ){
- int i;
- int nParam = sqlite3_bind_parameter_count(pStmt);
- for(i=0; rc==SQLITE_OK && i<nParam; i++){
- rc = sqlite3_bind_value(pStmt, i+1, apVal[i]);
- }
- }
- *pp = pStmt;
- return rc;
-}
-
-
-static int fts3SelectDocsize(
- Fts3Table *pTab, /* FTS3 table handle */
- sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */
- sqlite3_stmt **ppStmt /* OUT: Statement handle */
-){
- sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */
- int rc; /* Return code */
-
- rc = fts3SqlStmt(pTab, SQL_SELECT_DOCSIZE, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pStmt, 1, iDocid);
- rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
- rc = sqlite3_reset(pStmt);
- if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
- pStmt = 0;
- }else{
- rc = SQLITE_OK;
- }
- }
-
- *ppStmt = pStmt;
- return rc;
-}
-
-int sqlite3Fts3SelectDoctotal(
- Fts3Table *pTab, /* Fts3 table handle */
- sqlite3_stmt **ppStmt /* OUT: Statement handle */
-){
- sqlite3_stmt *pStmt = 0;
- int rc;
- rc = fts3SqlStmt(pTab, SQL_SELECT_STAT, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
- if( sqlite3_step(pStmt)!=SQLITE_ROW
- || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB
- ){
- rc = sqlite3_reset(pStmt);
- if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
- pStmt = 0;
- }
- }
- *ppStmt = pStmt;
- return rc;
-}
-
-int sqlite3Fts3SelectDocsize(
- Fts3Table *pTab, /* Fts3 table handle */
- sqlite3_int64 iDocid, /* Docid to read size data for */
- sqlite3_stmt **ppStmt /* OUT: Statement handle */
-){
- return fts3SelectDocsize(pTab, iDocid, ppStmt);
-}
-
-/*
-** Similar to fts3SqlStmt(). Except, after binding the parameters in
-** array apVal[] to the SQL statement identified by eStmt, the statement
-** is executed.
-**
-** Returns SQLITE_OK if the statement is successfully executed, or an
-** SQLite error code otherwise.
-*/
-static void fts3SqlExec(
- int *pRC, /* Result code */
- Fts3Table *p, /* The FTS3 table */
- int eStmt, /* Index of statement to evaluate */
- sqlite3_value **apVal /* Parameters to bind */
-){
- sqlite3_stmt *pStmt;
- int rc;
- if( *pRC ) return;
- rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
- if( rc==SQLITE_OK ){
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- }
- *pRC = rc;
-}
-
-
-/*
-** This function ensures that the caller has obtained an exclusive
-** shared-cache table-lock on the %_segdir table. This is required before
-** writing data to the fts3 table. If this lock is not acquired first, then
-** the caller may end up attempting to take this lock as part of committing
-** a transaction, causing SQLite to return SQLITE_LOCKED or
-** LOCKED_SHAREDCACHEto a COMMIT command.
-**
-** It is best to avoid this because if FTS3 returns any error when
-** committing a transaction, the whole transaction will be rolled back.
-** And this is not what users expect when they get SQLITE_LOCKED_SHAREDCACHE.
-** It can still happen if the user locks the underlying tables directly
-** instead of accessing them via FTS.
-*/
-static int fts3Writelock(Fts3Table *p){
- int rc = SQLITE_OK;
-
- if( p->nPendingData==0 ){
- sqlite3_stmt *pStmt;
- rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_null(pStmt, 1);
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- }
- }
-
- return rc;
-}
-
-/*
-** FTS maintains a separate indexes for each language-id (a 32-bit integer).
-** Within each language id, a separate index is maintained to store the
-** document terms, and each configured prefix size (configured the FTS
-** "prefix=" option). And each index consists of multiple levels ("relative
-** levels").
-**
-** All three of these values (the language id, the specific index and the
-** level within the index) are encoded in 64-bit integer values stored
-** in the %_segdir table on disk. This function is used to convert three
-** separate component values into the single 64-bit integer value that
-** can be used to query the %_segdir table.
-**
-** Specifically, each language-id/index combination is allocated 1024
-** 64-bit integer level values ("absolute levels"). The main terms index
-** for language-id 0 is allocate values 0-1023. The first prefix index
-** (if any) for language-id 0 is allocated values 1024-2047. And so on.
-** Language 1 indexes are allocated immediately following language 0.
-**
-** So, for a system with nPrefix prefix indexes configured, the block of
-** absolute levels that corresponds to language-id iLangid and index
-** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024).
-*/
-static sqlite3_int64 getAbsoluteLevel(
- Fts3Table *p, /* FTS3 table handle */
- int iLangid, /* Language id */
- int iIndex, /* Index in p->aIndex[] */
- int iLevel /* Level of segments */
-){
- sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
- assert( iLangid>=0 );
- assert( p->nIndex>0 );
- assert( iIndex>=0 && iIndex<p->nIndex );
-
- iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL;
- return iBase + iLevel;
-}
-
-/*
-** Set *ppStmt to a statement handle that may be used to iterate through
-** all rows in the %_segdir table, from oldest to newest. If successful,
-** return SQLITE_OK. If an error occurs while preparing the statement,
-** return an SQLite error code.
-**
-** There is only ever one instance of this SQL statement compiled for
-** each FTS3 table.
-**
-** The statement returns the following columns from the %_segdir table:
-**
-** 0: idx
-** 1: start_block
-** 2: leaves_end_block
-** 3: end_block
-** 4: root
-*/
-int sqlite3Fts3AllSegdirs(
- Fts3Table *p, /* FTS3 table */
- int iLangid, /* Language being queried */
- int iIndex, /* Index for p->aIndex[] */
- int iLevel, /* Level to select (relative level) */
- sqlite3_stmt **ppStmt /* OUT: Compiled statement */
-){
- int rc;
- sqlite3_stmt *pStmt = 0;
-
- assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 );
- assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
- assert( iIndex>=0 && iIndex<p->nIndex );
-
- if( iLevel<0 ){
- /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
- rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pStmt, 2,
- getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
- );
- }
- }else{
- /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
- rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel));
- }
- }
- *ppStmt = pStmt;
- return rc;
-}
-
-
-/*
-** Append a single varint to a PendingList buffer. SQLITE_OK is returned
-** if successful, or an SQLite error code otherwise.
-**
-** This function also serves to allocate the PendingList structure itself.
-** For example, to create a new PendingList structure containing two
-** varints:
-**
-** PendingList *p = 0;
-** fts3PendingListAppendVarint(&p, 1);
-** fts3PendingListAppendVarint(&p, 2);
-*/
-static int fts3PendingListAppendVarint(
- PendingList **pp, /* IN/OUT: Pointer to PendingList struct */
- sqlite3_int64 i /* Value to append to data */
-){
- PendingList *p = *pp;
-
- /* Allocate or grow the PendingList as required. */
- if( !p ){
- p = sqlite3_malloc(sizeof(*p) + 100);
- if( !p ){
- return SQLITE_NOMEM;
- }
- p->nSpace = 100;
- p->aData = (char *)&p[1];
- p->nData = 0;
- }
- else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){
- int nNew = p->nSpace * 2;
- p = sqlite3_realloc(p, sizeof(*p) + nNew);
- if( !p ){
- sqlite3_free(*pp);
- *pp = 0;
- return SQLITE_NOMEM;
- }
- p->nSpace = nNew;
- p->aData = (char *)&p[1];
- }
-
- /* Append the new serialized varint to the end of the list. */
- p->nData += sqlite3Fts3PutVarint(&p->aData[p->nData], i);
- p->aData[p->nData] = '\0';
- *pp = p;
- return SQLITE_OK;
-}
-
-/*
-** Add a docid/column/position entry to a PendingList structure. Non-zero
-** is returned if the structure is sqlite3_realloced as part of adding
-** the entry. Otherwise, zero.
-**
-** If an OOM error occurs, *pRc is set to SQLITE_NOMEM before returning.
-** Zero is always returned in this case. Otherwise, if no OOM error occurs,
-** it is set to SQLITE_OK.
-*/
-static int fts3PendingListAppend(
- PendingList **pp, /* IN/OUT: PendingList structure */
- sqlite3_int64 iDocid, /* Docid for entry to add */
- sqlite3_int64 iCol, /* Column for entry to add */
- sqlite3_int64 iPos, /* Position of term for entry to add */
- int *pRc /* OUT: Return code */
-){
- PendingList *p = *pp;
- int rc = SQLITE_OK;
-
- assert( !p || p->iLastDocid<=iDocid );
-
- if( !p || p->iLastDocid!=iDocid ){
- sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
- if( p ){
- assert( p->nData<p->nSpace );
- assert( p->aData[p->nData]==0 );
- p->nData++;
- }
- if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iDelta)) ){
- goto pendinglistappend_out;
- }
- p->iLastCol = -1;
- p->iLastPos = 0;
- p->iLastDocid = iDocid;
- }
- if( iCol>0 && p->iLastCol!=iCol ){
- if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, 1))
- || SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iCol))
- ){
- goto pendinglistappend_out;
- }
- p->iLastCol = iCol;
- p->iLastPos = 0;
- }
- if( iCol>=0 ){
- assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) );
- rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos);
- if( rc==SQLITE_OK ){
- p->iLastPos = iPos;
- }
- }
-
- pendinglistappend_out:
- *pRc = rc;
- if( p!=*pp ){
- *pp = p;
- return 1;
- }
- return 0;
-}
-
-/*
-** Free a PendingList object allocated by fts3PendingListAppend().
-*/
-static void fts3PendingListDelete(PendingList *pList){
- sqlite3_free(pList);
-}
-
-/*
-** Add an entry to one of the pending-terms hash tables.
-*/
-static int fts3PendingTermsAddOne(
- Fts3Table *p,
- int iCol,
- int iPos,
- Fts3Hash *pHash, /* Pending terms hash table to add entry to */
- const char *zToken,
- int nToken
-){
- PendingList *pList;
- int rc = SQLITE_OK;
-
- pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
- if( pList ){
- p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
- }
- if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
- if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
- /* Malloc failed while inserting the new entry. This can only
- ** happen if there was no previous entry for this token.
- */
- assert( 0==fts3HashFind(pHash, zToken, nToken) );
- sqlite3_free(pList);
- rc = SQLITE_NOMEM;
- }
- }
- if( rc==SQLITE_OK ){
- p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
- }
- return rc;
-}
-
-/*
-** Tokenize the nul-terminated string zText and add all tokens to the
-** pending-terms hash-table. The docid used is that currently stored in
-** p->iPrevDocid, and the column is specified by argument iCol.
-**
-** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
-*/
-static int fts3PendingTermsAdd(
- Fts3Table *p, /* Table into which text will be inserted */
- int iLangid, /* Language id to use */
- const char *zText, /* Text of document to be inserted */
- int iCol, /* Column into which text is being inserted */
- u32 *pnWord /* IN/OUT: Incr. by number tokens inserted */
-){
- int rc;
- int iStart = 0;
- int iEnd = 0;
- int iPos = 0;
- int nWord = 0;
-
- char const *zToken;
- int nToken = 0;
-
- sqlite3_tokenizer *pTokenizer = p->pTokenizer;
- sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
- sqlite3_tokenizer_cursor *pCsr;
- int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
- const char**,int*,int*,int*,int*);
-
- assert( pTokenizer && pModule );
-
- /* If the user has inserted a NULL value, this function may be called with
- ** zText==0. In this case, add zero token entries to the hash table and
- ** return early. */
- if( zText==0 ){
- *pnWord = 0;
- return SQLITE_OK;
- }
-
- rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- xNext = pModule->xNext;
- while( SQLITE_OK==rc
- && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
- ){
- int i;
- if( iPos>=nWord ) nWord = iPos+1;
-
- /* Positions cannot be negative; we use -1 as a terminator internally.
- ** Tokens must have a non-zero length.
- */
- if( iPos<0 || !zToken || nToken<=0 ){
- rc = SQLITE_ERROR;
- break;
- }
-
- /* Add the term to the terms index */
- rc = fts3PendingTermsAddOne(
- p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
- );
-
- /* Add the term to each of the prefix indexes that it is not too
- ** short for. */
- for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
- struct Fts3Index *pIndex = &p->aIndex[i];
- if( nToken<pIndex->nPrefix ) continue;
- rc = fts3PendingTermsAddOne(
- p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix
- );
- }
- }
-
- pModule->xClose(pCsr);
- *pnWord += nWord;
- return (rc==SQLITE_DONE ? SQLITE_OK : rc);
-}
-
-/*
-** Calling this function indicates that subsequent calls to
-** fts3PendingTermsAdd() are to add term/position-list pairs for the
-** contents of the document with docid iDocid.
-*/
-static int fts3PendingTermsDocid(
- Fts3Table *p, /* Full-text table handle */
- int bDelete, /* True if this op is a delete */
- int iLangid, /* Language id of row being written */
- sqlite_int64 iDocid /* Docid of row being written */
-){
- assert( iLangid>=0 );
- assert( bDelete==1 || bDelete==0 );
-
- /* TODO(shess) Explore whether partially flushing the buffer on
- ** forced-flush would provide better performance. I suspect that if
- ** we ordered the doclists by size and flushed the largest until the
- ** buffer was half empty, that would let the less frequent terms
- ** generate longer doclists.
- */
- if( iDocid<p->iPrevDocid
- || (iDocid==p->iPrevDocid && p->bPrevDelete==0)
- || p->iPrevLangid!=iLangid
- || p->nPendingData>p->nMaxPendingData
- ){
- int rc = sqlite3Fts3PendingTermsFlush(p);
- if( rc!=SQLITE_OK ) return rc;
- }
- p->iPrevDocid = iDocid;
- p->iPrevLangid = iLangid;
- p->bPrevDelete = bDelete;
- return SQLITE_OK;
-}
-
-/*
-** Discard the contents of the pending-terms hash tables.
-*/
-void sqlite3Fts3PendingTermsClear(Fts3Table *p){
- int i;
- for(i=0; i<p->nIndex; i++){
- Fts3HashElem *pElem;
- Fts3Hash *pHash = &p->aIndex[i].hPending;
- for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){
- PendingList *pList = (PendingList *)fts3HashData(pElem);
- fts3PendingListDelete(pList);
- }
- fts3HashClear(pHash);
- }
- p->nPendingData = 0;
-}
-
-/*
-** This function is called by the xUpdate() method as part of an INSERT
-** operation. It adds entries for each term in the new record to the
-** pendingTerms hash table.
-**
-** Argument apVal is the same as the similarly named argument passed to
-** fts3InsertData(). Parameter iDocid is the docid of the new row.
-*/
-static int fts3InsertTerms(
- Fts3Table *p,
- int iLangid,
- sqlite3_value **apVal,
- u32 *aSz
-){
- int i; /* Iterator variable */
- for(i=2; i<p->nColumn+2; i++){
- int iCol = i-2;
- if( p->abNotindexed[iCol]==0 ){
- const char *zText = (const char *)sqlite3_value_text(apVal[i]);
- int rc = fts3PendingTermsAdd(p, iLangid, zText, iCol, &aSz[iCol]);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** This function is called by the xUpdate() method for an INSERT operation.
-** The apVal parameter is passed a copy of the apVal argument passed by
-** SQLite to the xUpdate() method. i.e:
-**
-** apVal[0] Not used for INSERT.
-** apVal[1] rowid
-** apVal[2] Left-most user-defined column
-** ...
-** apVal[p->nColumn+1] Right-most user-defined column
-** apVal[p->nColumn+2] Hidden column with same name as table
-** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid)
-** apVal[p->nColumn+4] Hidden languageid column
-*/
-static int fts3InsertData(
- Fts3Table *p, /* Full-text table */
- sqlite3_value **apVal, /* Array of values to insert */
- sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */
-){
- int rc; /* Return code */
- sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */
-
- if( p->zContentTbl ){
- sqlite3_value *pRowid = apVal[p->nColumn+3];
- if( sqlite3_value_type(pRowid)==SQLITE_NULL ){
- pRowid = apVal[1];
- }
- if( sqlite3_value_type(pRowid)!=SQLITE_INTEGER ){
- return SQLITE_CONSTRAINT;
- }
- *piDocid = sqlite3_value_int64(pRowid);
- return SQLITE_OK;
- }
-
- /* Locate the statement handle used to insert data into the %_content
- ** table. The SQL for this statement is:
- **
- ** INSERT INTO %_content VALUES(?, ?, ?, ...)
- **
- ** The statement features N '?' variables, where N is the number of user
- ** defined columns in the FTS3 table, plus one for the docid field.
- */
- rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
- if( rc==SQLITE_OK && p->zLanguageid ){
- rc = sqlite3_bind_int(
- pContentInsert, p->nColumn+2,
- sqlite3_value_int(apVal[p->nColumn+4])
- );
- }
- if( rc!=SQLITE_OK ) return rc;
-
- /* There is a quirk here. The users INSERT statement may have specified
- ** a value for the "rowid" field, for the "docid" field, or for both.
- ** Which is a problem, since "rowid" and "docid" are aliases for the
- ** same value. For example:
- **
- ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2);
- **
- ** In FTS3, this is an error. It is an error to specify non-NULL values
- ** for both docid and some other rowid alias.
- */
- if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){
- if( SQLITE_NULL==sqlite3_value_type(apVal[0])
- && SQLITE_NULL!=sqlite3_value_type(apVal[1])
- ){
- /* A rowid/docid conflict. */
- return SQLITE_ERROR;
- }
- rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- /* Execute the statement to insert the record. Set *piDocid to the
- ** new docid value.
- */
- sqlite3_step(pContentInsert);
- rc = sqlite3_reset(pContentInsert);
-
- *piDocid = sqlite3_last_insert_rowid(p->db);
- return rc;
-}
-
-
-
-/*
-** Remove all data from the FTS3 table. Clear the hash table containing
-** pending terms.
-*/
-static int fts3DeleteAll(Fts3Table *p, int bContent){
- int rc = SQLITE_OK; /* Return code */
-
- /* Discard the contents of the pending-terms hash table. */
- sqlite3Fts3PendingTermsClear(p);
-
- /* Delete everything from the shadow tables. Except, leave %_content as
- ** is if bContent is false. */
- assert( p->zContentTbl==0 || bContent==0 );
- if( bContent ) fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0);
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0);
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
- if( p->bHasDocsize ){
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0);
- }
- if( p->bHasStat ){
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0);
- }
- return rc;
-}
-
-/*
-**
-*/
-static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){
- int iLangid = 0;
- if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1);
- return iLangid;
-}
-
-/*
-** The first element in the apVal[] array is assumed to contain the docid
-** (an integer) of a row about to be deleted. Remove all terms from the
-** full-text index.
-*/
-static void fts3DeleteTerms(
- int *pRC, /* Result code */
- Fts3Table *p, /* The FTS table to delete from */
- sqlite3_value *pRowid, /* The docid to be deleted */
- u32 *aSz, /* Sizes of deleted document written here */
- int *pbFound /* OUT: Set to true if row really does exist */
-){
- int rc;
- sqlite3_stmt *pSelect;
-
- assert( *pbFound==0 );
- if( *pRC ) return;
- rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pSelect) ){
- int i;
- int iLangid = langidFromSelect(p, pSelect);
- i64 iDocid = sqlite3_column_int64(pSelect, 0);
- rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid);
- for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
- int iCol = i-1;
- if( p->abNotindexed[iCol]==0 ){
- const char *zText = (const char *)sqlite3_column_text(pSelect, i);
- rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]);
- aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
- }
- }
- if( rc!=SQLITE_OK ){
- sqlite3_reset(pSelect);
- *pRC = rc;
- return;
- }
- *pbFound = 1;
- }
- rc = sqlite3_reset(pSelect);
- }else{
- sqlite3_reset(pSelect);
- }
- *pRC = rc;
-}
-
-/*
-** Forward declaration to account for the circular dependency between
-** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
-*/
-static int fts3SegmentMerge(Fts3Table *, int, int, int);
-
-/*
-** This function allocates a new level iLevel index in the segdir table.
-** Usually, indexes are allocated within a level sequentially starting
-** with 0, so the allocated index is one greater than the value returned
-** by:
-**
-** SELECT max(idx) FROM %_segdir WHERE level = :iLevel
-**
-** However, if there are already FTS3_MERGE_COUNT indexes at the requested
-** level, they are merged into a single level (iLevel+1) segment and the
-** allocated index is 0.
-**
-** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
-** returned. Otherwise, an SQLite error code is returned.
-*/
-static int fts3AllocateSegdirIdx(
- Fts3Table *p,
- int iLangid, /* Language id */
- int iIndex, /* Index for p->aIndex */
- int iLevel,
- int *piIdx
-){
- int rc; /* Return Code */
- sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
- int iNext = 0; /* Result of query pNextIdx */
-
- assert( iLangid>=0 );
- assert( p->nIndex>=1 );
-
- /* Set variable iNext to the next available segdir index at level iLevel. */
- rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(
- pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)
- );
- if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
- iNext = sqlite3_column_int(pNextIdx, 0);
- }
- rc = sqlite3_reset(pNextIdx);
- }
-
- if( rc==SQLITE_OK ){
- /* If iNext is FTS3_MERGE_COUNT, indicating that level iLevel is already
- ** full, merge all segments in level iLevel into a single iLevel+1
- ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
- ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
- */
- if( iNext>=FTS3_MERGE_COUNT ){
- fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
- rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
- *piIdx = 0;
- }else{
- *piIdx = iNext;
- }
- }
-
- return rc;
-}
-
-/*
-** The %_segments table is declared as follows:
-**
-** CREATE TABLE %_segments(blockid INTEGER PRIMARY KEY, block BLOB)
-**
-** This function reads data from a single row of the %_segments table. The
-** specific row is identified by the iBlockid parameter. If paBlob is not
-** NULL, then a buffer is allocated using sqlite3_malloc() and populated
-** with the contents of the blob stored in the "block" column of the
-** identified table row is. Whether or not paBlob is NULL, *pnBlob is set
-** to the size of the blob in bytes before returning.
-**
-** If an error occurs, or the table does not contain the specified row,
-** an SQLite error code is returned. Otherwise, SQLITE_OK is returned. If
-** paBlob is non-NULL, then it is the responsibility of the caller to
-** eventually free the returned buffer.
-**
-** This function may leave an open sqlite3_blob* handle in the
-** Fts3Table.pSegments variable. This handle is reused by subsequent calls
-** to this function. The handle may be closed by calling the
-** sqlite3Fts3SegmentsClose() function. Reusing a blob handle is a handy
-** performance improvement, but the blob handle should always be closed
-** before control is returned to the user (to prevent a lock being held
-** on the database file for longer than necessary). Thus, any virtual table
-** method (xFilter etc.) that may directly or indirectly call this function
-** must call sqlite3Fts3SegmentsClose() before returning.
-*/
-int sqlite3Fts3ReadBlock(
- Fts3Table *p, /* FTS3 table handle */
- sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */
- char **paBlob, /* OUT: Blob data in malloc'd buffer */
- int *pnBlob, /* OUT: Size of blob data */
- int *pnLoad /* OUT: Bytes actually loaded */
-){
- int rc; /* Return code */
-
- /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
- assert( pnBlob );
-
- if( p->pSegments ){
- rc = sqlite3_blob_reopen(p->pSegments, iBlockid);
- }else{
- if( 0==p->zSegmentsTbl ){
- p->zSegmentsTbl = sqlite3_mprintf("%s_segments", p->zName);
- if( 0==p->zSegmentsTbl ) return SQLITE_NOMEM;
- }
- rc = sqlite3_blob_open(
- p->db, p->zDb, p->zSegmentsTbl, "block", iBlockid, 0, &p->pSegments
- );
- }
-
- if( rc==SQLITE_OK ){
- int nByte = sqlite3_blob_bytes(p->pSegments);
- *pnBlob = nByte;
- if( paBlob ){
- char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
- if( !aByte ){
- rc = SQLITE_NOMEM;
- }else{
- if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){
- nByte = FTS3_NODE_CHUNKSIZE;
- *pnLoad = nByte;
- }
- rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
- memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
- if( rc!=SQLITE_OK ){
- sqlite3_free(aByte);
- aByte = 0;
- }
- }
- *paBlob = aByte;
- }
- }
-
- return rc;
-}
-
-/*
-** Close the blob handle at p->pSegments, if it is open. See comments above
-** the sqlite3Fts3ReadBlock() function for details.
-*/
-void sqlite3Fts3SegmentsClose(Fts3Table *p){
- sqlite3_blob_close(p->pSegments);
- p->pSegments = 0;
-}
-
-static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
- int nRead; /* Number of bytes to read */
- int rc; /* Return code */
-
- nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
- rc = sqlite3_blob_read(
- pReader->pBlob,
- &pReader->aNode[pReader->nPopulate],
- nRead,
- pReader->nPopulate
- );
-
- if( rc==SQLITE_OK ){
- pReader->nPopulate += nRead;
- memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING);
- if( pReader->nPopulate==pReader->nNode ){
- sqlite3_blob_close(pReader->pBlob);
- pReader->pBlob = 0;
- pReader->nPopulate = 0;
- }
- }
- return rc;
-}
-
-static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
- int rc = SQLITE_OK;
- assert( !pReader->pBlob
- || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
- );
- while( pReader->pBlob && rc==SQLITE_OK
- && (pFrom - pReader->aNode + nByte)>pReader->nPopulate
- ){
- rc = fts3SegReaderIncrRead(pReader);
- }
- return rc;
-}
-
-/*
-** Set an Fts3SegReader cursor to point at EOF.
-*/
-static void fts3SegReaderSetEof(Fts3SegReader *pSeg){
- if( !fts3SegReaderIsRootOnly(pSeg) ){
- sqlite3_free(pSeg->aNode);
- sqlite3_blob_close(pSeg->pBlob);
- pSeg->pBlob = 0;
- }
- pSeg->aNode = 0;
-}
-
-/*
-** Move the iterator passed as the first argument to the next term in the
-** segment. If successful, SQLITE_OK is returned. If there is no next term,
-** SQLITE_DONE. Otherwise, an SQLite error code.
-*/
-static int fts3SegReaderNext(
- Fts3Table *p,
- Fts3SegReader *pReader,
- int bIncr
-){
- int rc; /* Return code of various sub-routines */
- char *pNext; /* Cursor variable */
- int nPrefix; /* Number of bytes in term prefix */
- int nSuffix; /* Number of bytes in term suffix */
-
- if( !pReader->aDoclist ){
- pNext = pReader->aNode;
- }else{
- pNext = &pReader->aDoclist[pReader->nDoclist];
- }
-
- if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
-
- if( fts3SegReaderIsPending(pReader) ){
- Fts3HashElem *pElem = *(pReader->ppNextElem);
- sqlite3_free(pReader->aNode);
- pReader->aNode = 0;
- if( pElem ){
- char *aCopy;
- PendingList *pList = (PendingList *)fts3HashData(pElem);
- int nCopy = pList->nData+1;
- pReader->zTerm = (char *)fts3HashKey(pElem);
- pReader->nTerm = fts3HashKeysize(pElem);
- aCopy = (char*)sqlite3_malloc(nCopy);
- if( !aCopy ) return SQLITE_NOMEM;
- memcpy(aCopy, pList->aData, nCopy);
- pReader->nNode = pReader->nDoclist = nCopy;
- pReader->aNode = pReader->aDoclist = aCopy;
- pReader->ppNextElem++;
- assert( pReader->aNode );
- }
- return SQLITE_OK;
- }
-
- fts3SegReaderSetEof(pReader);
-
- /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
- ** blocks have already been traversed. */
- assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
- if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
- return SQLITE_OK;
- }
-
- rc = sqlite3Fts3ReadBlock(
- p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
- (bIncr ? &pReader->nPopulate : 0)
- );
- if( rc!=SQLITE_OK ) return rc;
- assert( pReader->pBlob==0 );
- if( bIncr && pReader->nPopulate<pReader->nNode ){
- pReader->pBlob = p->pSegments;
- p->pSegments = 0;
- }
- pNext = pReader->aNode;
- }
-
- assert( !fts3SegReaderIsPending(pReader) );
-
- rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
- ** safe (no risk of overread) even if the node data is corrupted. */
- pNext += fts3GetVarint32(pNext, &nPrefix);
- pNext += fts3GetVarint32(pNext, &nSuffix);
- if( nPrefix<0 || nSuffix<=0
- || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
- ){
- return FTS_CORRUPT_VTAB;
- }
-
- if( nPrefix+nSuffix>pReader->nTermAlloc ){
- int nNew = (nPrefix+nSuffix)*2;
- char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- pReader->zTerm = zNew;
- pReader->nTermAlloc = nNew;
- }
-
- rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX);
- if( rc!=SQLITE_OK ) return rc;
-
- memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
- pReader->nTerm = nPrefix+nSuffix;
- pNext += nSuffix;
- pNext += fts3GetVarint32(pNext, &pReader->nDoclist);
- pReader->aDoclist = pNext;
- pReader->pOffsetList = 0;
-
- /* Check that the doclist does not appear to extend past the end of the
- ** b-tree node. And that the final byte of the doclist is 0x00. If either
- ** of these statements is untrue, then the data structure is corrupt.
- */
- if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
- || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
- ){
- return FTS_CORRUPT_VTAB;
- }
- return SQLITE_OK;
-}
-
-/*
-** Set the SegReader to point to the first docid in the doclist associated
-** with the current term.
-*/
-static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){
- int rc = SQLITE_OK;
- assert( pReader->aDoclist );
- assert( !pReader->pOffsetList );
- if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
- u8 bEof = 0;
- pReader->iDocid = 0;
- pReader->nOffsetList = 0;
- sqlite3Fts3DoclistPrev(0,
- pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
- &pReader->iDocid, &pReader->nOffsetList, &bEof
- );
- }else{
- rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX);
- if( rc==SQLITE_OK ){
- int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
- pReader->pOffsetList = &pReader->aDoclist[n];
- }
- }
- return rc;
-}
-
-/*
-** Advance the SegReader to point to the next docid in the doclist
-** associated with the current term.
-**
-** If arguments ppOffsetList and pnOffsetList are not NULL, then
-** *ppOffsetList is set to point to the first column-offset list
-** in the doclist entry (i.e. immediately past the docid varint).
-** *pnOffsetList is set to the length of the set of column-offset
-** lists, not including the nul-terminator byte. For example:
-*/
-static int fts3SegReaderNextDocid(
- Fts3Table *pTab,
- Fts3SegReader *pReader, /* Reader to advance to next docid */
- char **ppOffsetList, /* OUT: Pointer to current position-list */
- int *pnOffsetList /* OUT: Length of *ppOffsetList in bytes */
-){
- int rc = SQLITE_OK;
- char *p = pReader->pOffsetList;
- char c = 0;
-
- assert( p );
-
- if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
- /* A pending-terms seg-reader for an FTS4 table that uses order=desc.
- ** Pending-terms doclists are always built up in ascending order, so
- ** we have to iterate through them backwards here. */
- u8 bEof = 0;
- if( ppOffsetList ){
- *ppOffsetList = pReader->pOffsetList;
- *pnOffsetList = pReader->nOffsetList - 1;
- }
- sqlite3Fts3DoclistPrev(0,
- pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid,
- &pReader->nOffsetList, &bEof
- );
- if( bEof ){
- pReader->pOffsetList = 0;
- }else{
- pReader->pOffsetList = p;
- }
- }else{
- char *pEnd = &pReader->aDoclist[pReader->nDoclist];
-
- /* Pointer p currently points at the first byte of an offset list. The
- ** following block advances it to point one byte past the end of
- ** the same offset list. */
- while( 1 ){
-
- /* The following line of code (and the "p++" below the while() loop) is
- ** normally all that is required to move pointer p to the desired
- ** position. The exception is if this node is being loaded from disk
- ** incrementally and pointer "p" now points to the first byte past
- ** the populated part of pReader->aNode[].
- */
- while( *p | c ) c = *p++ & 0x80;
- assert( *p==0 );
-
- if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
- rc = fts3SegReaderIncrRead(pReader);
- if( rc!=SQLITE_OK ) return rc;
- }
- p++;
-
- /* If required, populate the output variables with a pointer to and the
- ** size of the previous offset-list.
- */
- if( ppOffsetList ){
- *ppOffsetList = pReader->pOffsetList;
- *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
- }
-
- /* List may have been edited in place by fts3EvalNearTrim() */
- while( p<pEnd && *p==0 ) p++;
-
- /* If there are no more entries in the doclist, set pOffsetList to
- ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
- ** Fts3SegReader.pOffsetList to point to the next offset list before
- ** returning.
- */
- if( p>=pEnd ){
- pReader->pOffsetList = 0;
- }else{
- rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
- if( rc==SQLITE_OK ){
- sqlite3_int64 iDelta;
- pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
- if( pTab->bDescIdx ){
- pReader->iDocid -= iDelta;
- }else{
- pReader->iDocid += iDelta;
- }
- }
- }
- }
-
- return SQLITE_OK;
-}
-
-
-int sqlite3Fts3MsrOvfl(
- Fts3Cursor *pCsr,
- Fts3MultiSegReader *pMsr,
- int *pnOvfl
-){
- Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
- int nOvfl = 0;
- int ii;
- int rc = SQLITE_OK;
- int pgsz = p->nPgsz;
-
- assert( p->bFts4 );
- assert( pgsz>0 );
-
- for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
- Fts3SegReader *pReader = pMsr->apSegment[ii];
- if( !fts3SegReaderIsPending(pReader)
- && !fts3SegReaderIsRootOnly(pReader)
- ){
- sqlite3_int64 jj;
- for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
- int nBlob;
- rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
- if( rc!=SQLITE_OK ) break;
- if( (nBlob+35)>pgsz ){
- nOvfl += (nBlob + 34)/pgsz;
- }
- }
- }
- }
- *pnOvfl = nOvfl;
- return rc;
-}
-
-/*
-** Free all allocations associated with the iterator passed as the
-** second argument.
-*/
-void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
- if( pReader ){
- if( !fts3SegReaderIsPending(pReader) ){
- sqlite3_free(pReader->zTerm);
- }
- if( !fts3SegReaderIsRootOnly(pReader) ){
- sqlite3_free(pReader->aNode);
- }
- sqlite3_blob_close(pReader->pBlob);
- }
- sqlite3_free(pReader);
-}
-
-/*
-** Allocate a new SegReader object.
-*/
-int sqlite3Fts3SegReaderNew(
- int iAge, /* Segment "age". */
- int bLookup, /* True for a lookup only */
- sqlite3_int64 iStartLeaf, /* First leaf to traverse */
- sqlite3_int64 iEndLeaf, /* Final leaf to traverse */
- sqlite3_int64 iEndBlock, /* Final block of segment */
- const char *zRoot, /* Buffer containing root node */
- int nRoot, /* Size of buffer containing root node */
- Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */
-){
- Fts3SegReader *pReader; /* Newly allocated SegReader object */
- int nExtra = 0; /* Bytes to allocate segment root node */
-
- assert( iStartLeaf<=iEndLeaf );
- if( iStartLeaf==0 ){
- nExtra = nRoot + FTS3_NODE_PADDING;
- }
-
- pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
- if( !pReader ){
- return SQLITE_NOMEM;
- }
- memset(pReader, 0, sizeof(Fts3SegReader));
- pReader->iIdx = iAge;
- pReader->bLookup = bLookup!=0;
- pReader->iStartBlock = iStartLeaf;
- pReader->iLeafEndBlock = iEndLeaf;
- pReader->iEndBlock = iEndBlock;
-
- if( nExtra ){
- /* The entire segment is stored in the root node. */
- pReader->aNode = (char *)&pReader[1];
- pReader->rootOnly = 1;
- pReader->nNode = nRoot;
- memcpy(pReader->aNode, zRoot, nRoot);
- memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
- }else{
- pReader->iCurrentBlock = iStartLeaf-1;
- }
- *ppReader = pReader;
- return SQLITE_OK;
-}
-
-/*
-** This is a comparison function used as a qsort() callback when sorting
-** an array of pending terms by term. This occurs as part of flushing
-** the contents of the pending-terms hash table to the database.
-*/
-static int SQLITE_CDECL fts3CompareElemByTerm(
- const void *lhs,
- const void *rhs
-){
- char *z1 = fts3HashKey(*(Fts3HashElem **)lhs);
- char *z2 = fts3HashKey(*(Fts3HashElem **)rhs);
- int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs);
- int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs);
-
- int n = (n1<n2 ? n1 : n2);
- int c = memcmp(z1, z2, n);
- if( c==0 ){
- c = n1 - n2;
- }
- return c;
-}
-
-/*
-** This function is used to allocate an Fts3SegReader that iterates through
-** a subset of the terms stored in the Fts3Table.pendingTerms array.
-**
-** If the isPrefixIter parameter is zero, then the returned SegReader iterates
-** through each term in the pending-terms table. Or, if isPrefixIter is
-** non-zero, it iterates through each term and its prefixes. For example, if
-** the pending terms hash table contains the terms "sqlite", "mysql" and
-** "firebird", then the iterator visits the following 'terms' (in the order
-** shown):
-**
-** f fi fir fire fireb firebi firebir firebird
-** m my mys mysq mysql
-** s sq sql sqli sqlit sqlite
-**
-** Whereas if isPrefixIter is zero, the terms visited are:
-**
-** firebird mysql sqlite
-*/
-int sqlite3Fts3SegReaderPending(
- Fts3Table *p, /* Virtual table handle */
- int iIndex, /* Index for p->aIndex */
- const char *zTerm, /* Term to search for */
- int nTerm, /* Size of buffer zTerm */
- int bPrefix, /* True for a prefix iterator */
- Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */
-){
- Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */
- Fts3HashElem *pE; /* Iterator variable */
- Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */
- int nElem = 0; /* Size of array at aElem */
- int rc = SQLITE_OK; /* Return Code */
- Fts3Hash *pHash;
-
- pHash = &p->aIndex[iIndex].hPending;
- if( bPrefix ){
- int nAlloc = 0; /* Size of allocated array at aElem */
-
- for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){
- char *zKey = (char *)fts3HashKey(pE);
- int nKey = fts3HashKeysize(pE);
- if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){
- if( nElem==nAlloc ){
- Fts3HashElem **aElem2;
- nAlloc += 16;
- aElem2 = (Fts3HashElem **)sqlite3_realloc(
- aElem, nAlloc*sizeof(Fts3HashElem *)
- );
- if( !aElem2 ){
- rc = SQLITE_NOMEM;
- nElem = 0;
- break;
- }
- aElem = aElem2;
- }
-
- aElem[nElem++] = pE;
- }
- }
-
- /* If more than one term matches the prefix, sort the Fts3HashElem
- ** objects in term order using qsort(). This uses the same comparison
- ** callback as is used when flushing terms to disk.
- */
- if( nElem>1 ){
- qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm);
- }
-
- }else{
- /* The query is a simple term lookup that matches at most one term in
- ** the index. All that is required is a straight hash-lookup.
- **
- ** Because the stack address of pE may be accessed via the aElem pointer
- ** below, the "Fts3HashElem *pE" must be declared so that it is valid
- ** within this entire function, not just this "else{...}" block.
- */
- pE = fts3HashFindElem(pHash, zTerm, nTerm);
- if( pE ){
- aElem = &pE;
- nElem = 1;
- }
- }
-
- if( nElem>0 ){
- int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
- pReader = (Fts3SegReader *)sqlite3_malloc(nByte);
- if( !pReader ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pReader, 0, nByte);
- pReader->iIdx = 0x7FFFFFFF;
- pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
- memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
- }
- }
-
- if( bPrefix ){
- sqlite3_free(aElem);
- }
- *ppReader = pReader;
- return rc;
-}
-
-/*
-** Compare the entries pointed to by two Fts3SegReader structures.
-** Comparison is as follows:
-**
-** 1) EOF is greater than not EOF.
-**
-** 2) The current terms (if any) are compared using memcmp(). If one
-** term is a prefix of another, the longer term is considered the
-** larger.
-**
-** 3) By segment age. An older segment is considered larger.
-*/
-static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
- int rc;
- if( pLhs->aNode && pRhs->aNode ){
- int rc2 = pLhs->nTerm - pRhs->nTerm;
- if( rc2<0 ){
- rc = memcmp(pLhs->zTerm, pRhs->zTerm, pLhs->nTerm);
- }else{
- rc = memcmp(pLhs->zTerm, pRhs->zTerm, pRhs->nTerm);
- }
- if( rc==0 ){
- rc = rc2;
- }
- }else{
- rc = (pLhs->aNode==0) - (pRhs->aNode==0);
- }
- if( rc==0 ){
- rc = pRhs->iIdx - pLhs->iIdx;
- }
- assert( rc!=0 );
- return rc;
-}
-
-/*
-** A different comparison function for SegReader structures. In this
-** version, it is assumed that each SegReader points to an entry in
-** a doclist for identical terms. Comparison is made as follows:
-**
-** 1) EOF (end of doclist in this case) is greater than not EOF.
-**
-** 2) By current docid.
-**
-** 3) By segment age. An older segment is considered larger.
-*/
-static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
- int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
- if( rc==0 ){
- if( pLhs->iDocid==pRhs->iDocid ){
- rc = pRhs->iIdx - pLhs->iIdx;
- }else{
- rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1;
- }
- }
- assert( pLhs->aNode && pRhs->aNode );
- return rc;
-}
-static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
- int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
- if( rc==0 ){
- if( pLhs->iDocid==pRhs->iDocid ){
- rc = pRhs->iIdx - pLhs->iIdx;
- }else{
- rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1;
- }
- }
- assert( pLhs->aNode && pRhs->aNode );
- return rc;
-}
-
-/*
-** Compare the term that the Fts3SegReader object passed as the first argument
-** points to with the term specified by arguments zTerm and nTerm.
-**
-** If the pSeg iterator is already at EOF, return 0. Otherwise, return
-** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are
-** equal, or +ve if the pSeg term is greater than zTerm/nTerm.
-*/
-static int fts3SegReaderTermCmp(
- Fts3SegReader *pSeg, /* Segment reader object */
- const char *zTerm, /* Term to compare to */
- int nTerm /* Size of term zTerm in bytes */
-){
- int res = 0;
- if( pSeg->aNode ){
- if( pSeg->nTerm>nTerm ){
- res = memcmp(pSeg->zTerm, zTerm, nTerm);
- }else{
- res = memcmp(pSeg->zTerm, zTerm, pSeg->nTerm);
- }
- if( res==0 ){
- res = pSeg->nTerm-nTerm;
- }
- }
- return res;
-}
-
-/*
-** Argument apSegment is an array of nSegment elements. It is known that
-** the final (nSegment-nSuspect) members are already in sorted order
-** (according to the comparison function provided). This function shuffles
-** the array around until all entries are in sorted order.
-*/
-static void fts3SegReaderSort(
- Fts3SegReader **apSegment, /* Array to sort entries of */
- int nSegment, /* Size of apSegment array */
- int nSuspect, /* Unsorted entry count */
- int (*xCmp)(Fts3SegReader *, Fts3SegReader *) /* Comparison function */
-){
- int i; /* Iterator variable */
-
- assert( nSuspect<=nSegment );
-
- if( nSuspect==nSegment ) nSuspect--;
- for(i=nSuspect-1; i>=0; i--){
- int j;
- for(j=i; j<(nSegment-1); j++){
- Fts3SegReader *pTmp;
- if( xCmp(apSegment[j], apSegment[j+1])<0 ) break;
- pTmp = apSegment[j+1];
- apSegment[j+1] = apSegment[j];
- apSegment[j] = pTmp;
- }
- }
-
-#ifndef NDEBUG
- /* Check that the list really is sorted now. */
- for(i=0; i<(nSuspect-1); i++){
- assert( xCmp(apSegment[i], apSegment[i+1])<0 );
- }
-#endif
-}
-
-/*
-** Insert a record into the %_segments table.
-*/
-static int fts3WriteSegment(
- Fts3Table *p, /* Virtual table handle */
- sqlite3_int64 iBlock, /* Block id for new block */
- char *z, /* Pointer to buffer containing block data */
- int n /* Size of buffer z in bytes */
-){
- sqlite3_stmt *pStmt;
- int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pStmt, 1, iBlock);
- sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC);
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- sqlite3_bind_null(pStmt, 2);
- }
- return rc;
-}
-
-/*
-** Find the largest relative level number in the table. If successful, set
-** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs,
-** set *pnMax to zero and return an SQLite error code.
-*/
-int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){
- int rc;
- int mxLevel = 0;
- sqlite3_stmt *pStmt = 0;
-
- rc = fts3SqlStmt(p, SQL_SELECT_MXLEVEL, &pStmt, 0);
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- mxLevel = sqlite3_column_int(pStmt, 0);
- }
- rc = sqlite3_reset(pStmt);
- }
- *pnMax = mxLevel;
- return rc;
-}
-
-/*
-** Insert a record into the %_segdir table.
-*/
-static int fts3WriteSegdir(
- Fts3Table *p, /* Virtual table handle */
- sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */
- int iIdx, /* Value for "idx" field */
- sqlite3_int64 iStartBlock, /* Value for "start_block" field */
- sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
- sqlite3_int64 iEndBlock, /* Value for "end_block" field */
- sqlite3_int64 nLeafData, /* Bytes of leaf data in segment */
- char *zRoot, /* Blob value for "root" field */
- int nRoot /* Number of bytes in buffer zRoot */
-){
- sqlite3_stmt *pStmt;
- int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pStmt, 1, iLevel);
- sqlite3_bind_int(pStmt, 2, iIdx);
- sqlite3_bind_int64(pStmt, 3, iStartBlock);
- sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
- if( nLeafData==0 ){
- sqlite3_bind_int64(pStmt, 5, iEndBlock);
- }else{
- char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData);
- if( !zEnd ) return SQLITE_NOMEM;
- sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free);
- }
- sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- sqlite3_bind_null(pStmt, 6);
- }
- return rc;
-}
-
-/*
-** Return the size of the common prefix (if any) shared by zPrev and
-** zNext, in bytes. For example,
-**
-** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3
-** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2
-** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0
-*/
-static int fts3PrefixCompress(
- const char *zPrev, /* Buffer containing previous term */
- int nPrev, /* Size of buffer zPrev in bytes */
- const char *zNext, /* Buffer containing next term */
- int nNext /* Size of buffer zNext in bytes */
-){
- int n;
- UNUSED_PARAMETER(nNext);
- for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
- return n;
-}
-
-/*
-** Add term zTerm to the SegmentNode. It is guaranteed that zTerm is larger
-** (according to memcmp) than the previous term.
-*/
-static int fts3NodeAddTerm(
- Fts3Table *p, /* Virtual table handle */
- SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
- int isCopyTerm, /* True if zTerm/nTerm is transient */
- const char *zTerm, /* Pointer to buffer containing term */
- int nTerm /* Size of term in bytes */
-){
- SegmentNode *pTree = *ppTree;
- int rc;
- SegmentNode *pNew;
-
- /* First try to append the term to the current node. Return early if
- ** this is possible.
- */
- if( pTree ){
- int nData = pTree->nData; /* Current size of node in bytes */
- int nReq = nData; /* Required space after adding zTerm */
- int nPrefix; /* Number of bytes of prefix compression */
- int nSuffix; /* Suffix length */
-
- nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
- nSuffix = nTerm-nPrefix;
-
- nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
- if( nReq<=p->nNodeSize || !pTree->zTerm ){
-
- if( nReq>p->nNodeSize ){
- /* An unusual case: this is the first term to be added to the node
- ** and the static node buffer (p->nNodeSize bytes) is not large
- ** enough. Use a separately malloced buffer instead This wastes
- ** p->nNodeSize bytes, but since this scenario only comes about when
- ** the database contain two terms that share a prefix of almost 2KB,
- ** this is not expected to be a serious problem.
- */
- assert( pTree->aData==(char *)&pTree[1] );
- pTree->aData = (char *)sqlite3_malloc(nReq);
- if( !pTree->aData ){
- return SQLITE_NOMEM;
- }
- }
-
- if( pTree->zTerm ){
- /* There is no prefix-length field for first term in a node */
- nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nPrefix);
- }
-
- nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nSuffix);
- memcpy(&pTree->aData[nData], &zTerm[nPrefix], nSuffix);
- pTree->nData = nData + nSuffix;
- pTree->nEntry++;
-
- if( isCopyTerm ){
- if( pTree->nMalloc<nTerm ){
- char *zNew = sqlite3_realloc(pTree->zMalloc, nTerm*2);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- pTree->nMalloc = nTerm*2;
- pTree->zMalloc = zNew;
- }
- pTree->zTerm = pTree->zMalloc;
- memcpy(pTree->zTerm, zTerm, nTerm);
- pTree->nTerm = nTerm;
- }else{
- pTree->zTerm = (char *)zTerm;
- pTree->nTerm = nTerm;
- }
- return SQLITE_OK;
- }
- }
-
- /* If control flows to here, it was not possible to append zTerm to the
- ** current node. Create a new node (a right-sibling of the current node).
- ** If this is the first node in the tree, the term is added to it.
- **
- ** Otherwise, the term is not added to the new node, it is left empty for
- ** now. Instead, the term is inserted into the parent of pTree. If pTree
- ** has no parent, one is created here.
- */
- pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
- if( !pNew ){
- return SQLITE_NOMEM;
- }
- memset(pNew, 0, sizeof(SegmentNode));
- pNew->nData = 1 + FTS3_VARINT_MAX;
- pNew->aData = (char *)&pNew[1];
-
- if( pTree ){
- SegmentNode *pParent = pTree->pParent;
- rc = fts3NodeAddTerm(p, &pParent, isCopyTerm, zTerm, nTerm);
- if( pTree->pParent==0 ){
- pTree->pParent = pParent;
- }
- pTree->pRight = pNew;
- pNew->pLeftmost = pTree->pLeftmost;
- pNew->pParent = pParent;
- pNew->zMalloc = pTree->zMalloc;
- pNew->nMalloc = pTree->nMalloc;
- pTree->zMalloc = 0;
- }else{
- pNew->pLeftmost = pNew;
- rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
- }
-
- *ppTree = pNew;
- return rc;
-}
-
-/*
-** Helper function for fts3NodeWrite().
-*/
-static int fts3TreeFinishNode(
- SegmentNode *pTree,
- int iHeight,
- sqlite3_int64 iLeftChild
-){
- int nStart;
- assert( iHeight>=1 && iHeight<128 );
- nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild);
- pTree->aData[nStart] = (char)iHeight;
- sqlite3Fts3PutVarint(&pTree->aData[nStart+1], iLeftChild);
- return nStart;
-}
-
-/*
-** Write the buffer for the segment node pTree and all of its peers to the
-** database. Then call this function recursively to write the parent of
-** pTree and its peers to the database.
-**
-** Except, if pTree is a root node, do not write it to the database. Instead,
-** set output variables *paRoot and *pnRoot to contain the root node.
-**
-** If successful, SQLITE_OK is returned and output variable *piLast is
-** set to the largest blockid written to the database (or zero if no
-** blocks were written to the db). Otherwise, an SQLite error code is
-** returned.
-*/
-static int fts3NodeWrite(
- Fts3Table *p, /* Virtual table handle */
- SegmentNode *pTree, /* SegmentNode handle */
- int iHeight, /* Height of this node in tree */
- sqlite3_int64 iLeaf, /* Block id of first leaf node */
- sqlite3_int64 iFree, /* Block id of next free slot in %_segments */
- sqlite3_int64 *piLast, /* OUT: Block id of last entry written */
- char **paRoot, /* OUT: Data for root node */
- int *pnRoot /* OUT: Size of root node in bytes */
-){
- int rc = SQLITE_OK;
-
- if( !pTree->pParent ){
- /* Root node of the tree. */
- int nStart = fts3TreeFinishNode(pTree, iHeight, iLeaf);
- *piLast = iFree-1;
- *pnRoot = pTree->nData - nStart;
- *paRoot = &pTree->aData[nStart];
- }else{
- SegmentNode *pIter;
- sqlite3_int64 iNextFree = iFree;
- sqlite3_int64 iNextLeaf = iLeaf;
- for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){
- int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf);
- int nWrite = pIter->nData - nStart;
-
- rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite);
- iNextFree++;
- iNextLeaf += (pIter->nEntry+1);
- }
- if( rc==SQLITE_OK ){
- assert( iNextLeaf==iFree );
- rc = fts3NodeWrite(
- p, pTree->pParent, iHeight+1, iFree, iNextFree, piLast, paRoot, pnRoot
- );
- }
- }
-
- return rc;
-}
-
-/*
-** Free all memory allocations associated with the tree pTree.
-*/
-static void fts3NodeFree(SegmentNode *pTree){
- if( pTree ){
- SegmentNode *p = pTree->pLeftmost;
- fts3NodeFree(p->pParent);
- while( p ){
- SegmentNode *pRight = p->pRight;
- if( p->aData!=(char *)&p[1] ){
- sqlite3_free(p->aData);
- }
- assert( pRight==0 || p->zMalloc==0 );
- sqlite3_free(p->zMalloc);
- sqlite3_free(p);
- p = pRight;
- }
- }
-}
-
-/*
-** Add a term to the segment being constructed by the SegmentWriter object
-** *ppWriter. When adding the first term to a segment, *ppWriter should
-** be passed NULL. This function will allocate a new SegmentWriter object
-** and return it via the input/output variable *ppWriter in this case.
-**
-** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
-*/
-static int fts3SegWriterAdd(
- Fts3Table *p, /* Virtual table handle */
- SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
- int isCopyTerm, /* True if buffer zTerm must be copied */
- const char *zTerm, /* Pointer to buffer containing term */
- int nTerm, /* Size of term in bytes */
- const char *aDoclist, /* Pointer to buffer containing doclist */
- int nDoclist /* Size of doclist in bytes */
-){
- int nPrefix; /* Size of term prefix in bytes */
- int nSuffix; /* Size of term suffix in bytes */
- int nReq; /* Number of bytes required on leaf page */
- int nData;
- SegmentWriter *pWriter = *ppWriter;
-
- if( !pWriter ){
- int rc;
- sqlite3_stmt *pStmt;
-
- /* Allocate the SegmentWriter structure */
- pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter));
- if( !pWriter ) return SQLITE_NOMEM;
- memset(pWriter, 0, sizeof(SegmentWriter));
- *ppWriter = pWriter;
-
- /* Allocate a buffer in which to accumulate data */
- pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize);
- if( !pWriter->aData ) return SQLITE_NOMEM;
- pWriter->nSize = p->nNodeSize;
-
- /* Find the next free blockid in the %_segments table */
- rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0);
- if( rc!=SQLITE_OK ) return rc;
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- pWriter->iFree = sqlite3_column_int64(pStmt, 0);
- pWriter->iFirst = pWriter->iFree;
- }
- rc = sqlite3_reset(pStmt);
- if( rc!=SQLITE_OK ) return rc;
- }
- nData = pWriter->nData;
-
- nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
- nSuffix = nTerm-nPrefix;
-
- /* Figure out how many bytes are required by this new entry */
- nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */
- sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */
- nSuffix + /* Term suffix */
- sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */
- nDoclist; /* Doclist data */
-
- if( nData>0 && nData+nReq>p->nNodeSize ){
- int rc;
-
- /* The current leaf node is full. Write it out to the database. */
- rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
- if( rc!=SQLITE_OK ) return rc;
- p->nLeafAdd++;
-
- /* Add the current term to the interior node tree. The term added to
- ** the interior tree must:
- **
- ** a) be greater than the largest term on the leaf node just written
- ** to the database (still available in pWriter->zTerm), and
- **
- ** b) be less than or equal to the term about to be added to the new
- ** leaf node (zTerm/nTerm).
- **
- ** In other words, it must be the prefix of zTerm 1 byte longer than
- ** the common prefix (if any) of zTerm and pWriter->zTerm.
- */
- assert( nPrefix<nTerm );
- rc = fts3NodeAddTerm(p, &pWriter->pTree, isCopyTerm, zTerm, nPrefix+1);
- if( rc!=SQLITE_OK ) return rc;
-
- nData = 0;
- pWriter->nTerm = 0;
-
- nPrefix = 0;
- nSuffix = nTerm;
- nReq = 1 + /* varint containing prefix size */
- sqlite3Fts3VarintLen(nTerm) + /* varint containing suffix size */
- nTerm + /* Term suffix */
- sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */
- nDoclist; /* Doclist data */
- }
-
- /* Increase the total number of bytes written to account for the new entry. */
- pWriter->nLeafData += nReq;
-
- /* If the buffer currently allocated is too small for this entry, realloc
- ** the buffer to make it large enough.
- */
- if( nReq>pWriter->nSize ){
- char *aNew = sqlite3_realloc(pWriter->aData, nReq);
- if( !aNew ) return SQLITE_NOMEM;
- pWriter->aData = aNew;
- pWriter->nSize = nReq;
- }
- assert( nData+nReq<=pWriter->nSize );
-
- /* Append the prefix-compressed term and doclist to the buffer. */
- nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
- nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
- memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
- nData += nSuffix;
- nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
- memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
- pWriter->nData = nData + nDoclist;
-
- /* Save the current term so that it can be used to prefix-compress the next.
- ** If the isCopyTerm parameter is true, then the buffer pointed to by
- ** zTerm is transient, so take a copy of the term data. Otherwise, just
- ** store a copy of the pointer.
- */
- if( isCopyTerm ){
- if( nTerm>pWriter->nMalloc ){
- char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- pWriter->nMalloc = nTerm*2;
- pWriter->zMalloc = zNew;
- pWriter->zTerm = zNew;
- }
- assert( pWriter->zTerm==pWriter->zMalloc );
- memcpy(pWriter->zTerm, zTerm, nTerm);
- }else{
- pWriter->zTerm = (char *)zTerm;
- }
- pWriter->nTerm = nTerm;
-
- return SQLITE_OK;
-}
-
-/*
-** Flush all data associated with the SegmentWriter object pWriter to the
-** database. This function must be called after all terms have been added
-** to the segment using fts3SegWriterAdd(). If successful, SQLITE_OK is
-** returned. Otherwise, an SQLite error code.
-*/
-static int fts3SegWriterFlush(
- Fts3Table *p, /* Virtual table handle */
- SegmentWriter *pWriter, /* SegmentWriter to flush to the db */
- sqlite3_int64 iLevel, /* Value for 'level' column of %_segdir */
- int iIdx /* Value for 'idx' column of %_segdir */
-){
- int rc; /* Return code */
- if( pWriter->pTree ){
- sqlite3_int64 iLast = 0; /* Largest block id written to database */
- sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */
- char *zRoot = NULL; /* Pointer to buffer containing root node */
- int nRoot = 0; /* Size of buffer zRoot */
-
- iLastLeaf = pWriter->iFree;
- rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData);
- if( rc==SQLITE_OK ){
- rc = fts3NodeWrite(p, pWriter->pTree, 1,
- pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot);
- }
- if( rc==SQLITE_OK ){
- rc = fts3WriteSegdir(p, iLevel, iIdx,
- pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot);
- }
- }else{
- /* The entire tree fits on the root node. Write it to the segdir table. */
- rc = fts3WriteSegdir(p, iLevel, iIdx,
- 0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData);
- }
- p->nLeafAdd++;
- return rc;
-}
-
-/*
-** Release all memory held by the SegmentWriter object passed as the
-** first argument.
-*/
-static void fts3SegWriterFree(SegmentWriter *pWriter){
- if( pWriter ){
- sqlite3_free(pWriter->aData);
- sqlite3_free(pWriter->zMalloc);
- fts3NodeFree(pWriter->pTree);
- sqlite3_free(pWriter);
- }
-}
-
-/*
-** The first value in the apVal[] array is assumed to contain an integer.
-** This function tests if there exist any documents with docid values that
-** are different from that integer. i.e. if deleting the document with docid
-** pRowid would mean the FTS3 table were empty.
-**
-** If successful, *pisEmpty is set to true if the table is empty except for
-** document pRowid, or false otherwise, and SQLITE_OK is returned. If an
-** error occurs, an SQLite error code is returned.
-*/
-static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){
- sqlite3_stmt *pStmt;
- int rc;
- if( p->zContentTbl ){
- /* If using the content=xxx option, assume the table is never empty */
- *pisEmpty = 0;
- rc = SQLITE_OK;
- }else{
- rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid);
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- *pisEmpty = sqlite3_column_int(pStmt, 0);
- }
- rc = sqlite3_reset(pStmt);
- }
- }
- return rc;
-}
-
-/*
-** Set *pnMax to the largest segment level in the database for the index
-** iIndex.
-**
-** Segment levels are stored in the 'level' column of the %_segdir table.
-**
-** Return SQLITE_OK if successful, or an SQLite error code if not.
-*/
-static int fts3SegmentMaxLevel(
- Fts3Table *p,
- int iLangid,
- int iIndex,
- sqlite3_int64 *pnMax
-){
- sqlite3_stmt *pStmt;
- int rc;
- assert( iIndex>=0 && iIndex<p->nIndex );
-
- /* Set pStmt to the compiled version of:
- **
- ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
- **
- ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
- */
- rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
- if( rc!=SQLITE_OK ) return rc;
- sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pStmt, 2,
- getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
- );
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- *pnMax = sqlite3_column_int64(pStmt, 0);
- }
- return sqlite3_reset(pStmt);
-}
-
-/*
-** iAbsLevel is an absolute level that may be assumed to exist within
-** the database. This function checks if it is the largest level number
-** within its index. Assuming no error occurs, *pbMax is set to 1 if
-** iAbsLevel is indeed the largest level, or 0 otherwise, and SQLITE_OK
-** is returned. If an error occurs, an error code is returned and the
-** final value of *pbMax is undefined.
-*/
-static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){
-
- /* Set pStmt to the compiled version of:
- **
- ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
- **
- ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
- */
- sqlite3_stmt *pStmt;
- int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
- if( rc!=SQLITE_OK ) return rc;
- sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
- sqlite3_bind_int64(pStmt, 2,
- ((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
- );
-
- *pbMax = 0;
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- *pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL;
- }
- return sqlite3_reset(pStmt);
-}
-
-/*
-** Delete all entries in the %_segments table associated with the segment
-** opened with seg-reader pSeg. This function does not affect the contents
-** of the %_segdir table.
-*/
-static int fts3DeleteSegment(
- Fts3Table *p, /* FTS table handle */
- Fts3SegReader *pSeg /* Segment to delete */
-){
- int rc = SQLITE_OK; /* Return code */
- if( pSeg->iStartBlock ){
- sqlite3_stmt *pDelete; /* SQL statement to delete rows */
- rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pDelete, 1, pSeg->iStartBlock);
- sqlite3_bind_int64(pDelete, 2, pSeg->iEndBlock);
- sqlite3_step(pDelete);
- rc = sqlite3_reset(pDelete);
- }
- }
- return rc;
-}
-
-/*
-** This function is used after merging multiple segments into a single large
-** segment to delete the old, now redundant, segment b-trees. Specifically,
-** it:
-**
-** 1) Deletes all %_segments entries for the segments associated with
-** each of the SegReader objects in the array passed as the third
-** argument, and
-**
-** 2) deletes all %_segdir entries with level iLevel, or all %_segdir
-** entries regardless of level if (iLevel<0).
-**
-** SQLITE_OK is returned if successful, otherwise an SQLite error code.
-*/
-static int fts3DeleteSegdir(
- Fts3Table *p, /* Virtual table handle */
- int iLangid, /* Language id */
- int iIndex, /* Index for p->aIndex */
- int iLevel, /* Level of %_segdir entries to delete */
- Fts3SegReader **apSegment, /* Array of SegReader objects */
- int nReader /* Size of array apSegment */
-){
- int rc = SQLITE_OK; /* Return Code */
- int i; /* Iterator variable */
- sqlite3_stmt *pDelete = 0; /* SQL statement to delete rows */
-
- for(i=0; rc==SQLITE_OK && i<nReader; i++){
- rc = fts3DeleteSegment(p, apSegment[i]);
- }
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
- if( iLevel==FTS3_SEGCURSOR_ALL ){
- rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pDelete, 2,
- getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
- );
- }
- }else{
- rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(
- pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)
- );
- }
- }
-
- if( rc==SQLITE_OK ){
- sqlite3_step(pDelete);
- rc = sqlite3_reset(pDelete);
- }
-
- return rc;
-}
-
-/*
-** When this function is called, buffer *ppList (size *pnList bytes) contains
-** a position list that may (or may not) feature multiple columns. This
-** function adjusts the pointer *ppList and the length *pnList so that they
-** identify the subset of the position list that corresponds to column iCol.
-**
-** If there are no entries in the input position list for column iCol, then
-** *pnList is set to zero before returning.
-**
-** If parameter bZero is non-zero, then any part of the input list following
-** the end of the output list is zeroed before returning.
-*/
-static void fts3ColumnFilter(
- int iCol, /* Column to filter on */
- int bZero, /* Zero out anything following *ppList */
- char **ppList, /* IN/OUT: Pointer to position list */
- int *pnList /* IN/OUT: Size of buffer *ppList in bytes */
-){
- char *pList = *ppList;
- int nList = *pnList;
- char *pEnd = &pList[nList];
- int iCurrent = 0;
- char *p = pList;
-
- assert( iCol>=0 );
- while( 1 ){
- char c = 0;
- while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80;
-
- if( iCol==iCurrent ){
- nList = (int)(p - pList);
- break;
- }
-
- nList -= (int)(p - pList);
- pList = p;
- if( nList==0 ){
- break;
- }
- p = &pList[1];
- p += fts3GetVarint32(p, &iCurrent);
- }
-
- if( bZero && &pList[nList]!=pEnd ){
- memset(&pList[nList], 0, pEnd - &pList[nList]);
- }
- *ppList = pList;
- *pnList = nList;
-}
-
-/*
-** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any
-** existing data). Grow the buffer if required.
-**
-** If successful, return SQLITE_OK. Otherwise, if an OOM error is encountered
-** trying to resize the buffer, return SQLITE_NOMEM.
-*/
-static int fts3MsrBufferData(
- Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
- char *pList,
- int nList
-){
- if( nList>pMsr->nBuffer ){
- char *pNew;
- pMsr->nBuffer = nList*2;
- pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
- if( !pNew ) return SQLITE_NOMEM;
- pMsr->aBuffer = pNew;
- }
-
- memcpy(pMsr->aBuffer, pList, nList);
- return SQLITE_OK;
-}
-
-int sqlite3Fts3MsrIncrNext(
- Fts3Table *p, /* Virtual table handle */
- Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
- sqlite3_int64 *piDocid, /* OUT: Docid value */
- char **paPoslist, /* OUT: Pointer to position list */
- int *pnPoslist /* OUT: Size of position list in bytes */
-){
- int nMerge = pMsr->nAdvance;
- Fts3SegReader **apSegment = pMsr->apSegment;
- int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
- p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
- );
-
- if( nMerge==0 ){
- *paPoslist = 0;
- return SQLITE_OK;
- }
-
- while( 1 ){
- Fts3SegReader *pSeg;
- pSeg = pMsr->apSegment[0];
-
- if( pSeg->pOffsetList==0 ){
- *paPoslist = 0;
- break;
- }else{
- int rc;
- char *pList;
- int nList;
- int j;
- sqlite3_int64 iDocid = apSegment[0]->iDocid;
-
- rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
- j = 1;
- while( rc==SQLITE_OK
- && j<nMerge
- && apSegment[j]->pOffsetList
- && apSegment[j]->iDocid==iDocid
- ){
- rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
- j++;
- }
- if( rc!=SQLITE_OK ) return rc;
- fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
-
- if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
- rc = fts3MsrBufferData(pMsr, pList, nList+1);
- if( rc!=SQLITE_OK ) return rc;
- assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
- pList = pMsr->aBuffer;
- }
-
- if( pMsr->iColFilter>=0 ){
- fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList);
- }
-
- if( nList>0 ){
- *paPoslist = pList;
- *piDocid = iDocid;
- *pnPoslist = nList;
- break;
- }
- }
- }
-
- return SQLITE_OK;
-}
-
-static int fts3SegReaderStart(
- Fts3Table *p, /* Virtual table handle */
- Fts3MultiSegReader *pCsr, /* Cursor object */
- const char *zTerm, /* Term searched for (or NULL) */
- int nTerm /* Length of zTerm in bytes */
-){
- int i;
- int nSeg = pCsr->nSegment;
-
- /* If the Fts3SegFilter defines a specific term (or term prefix) to search
- ** for, then advance each segment iterator until it points to a term of
- ** equal or greater value than the specified term. This prevents many
- ** unnecessary merge/sort operations for the case where single segment
- ** b-tree leaf nodes contain more than one term.
- */
- for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
- int res = 0;
- Fts3SegReader *pSeg = pCsr->apSegment[i];
- do {
- int rc = fts3SegReaderNext(p, pSeg, 0);
- if( rc!=SQLITE_OK ) return rc;
- }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 );
-
- if( pSeg->bLookup && res!=0 ){
- fts3SegReaderSetEof(pSeg);
- }
- }
- fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);
-
- return SQLITE_OK;
-}
-
-int sqlite3Fts3SegReaderStart(
- Fts3Table *p, /* Virtual table handle */
- Fts3MultiSegReader *pCsr, /* Cursor object */
- Fts3SegFilter *pFilter /* Restrictions on range of iteration */
-){
- pCsr->pFilter = pFilter;
- return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm);
-}
-
-int sqlite3Fts3MsrIncrStart(
- Fts3Table *p, /* Virtual table handle */
- Fts3MultiSegReader *pCsr, /* Cursor object */
- int iCol, /* Column to match on. */
- const char *zTerm, /* Term to iterate through a doclist for */
- int nTerm /* Number of bytes in zTerm */
-){
- int i;
- int rc;
- int nSegment = pCsr->nSegment;
- int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
- p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
- );
-
- assert( pCsr->pFilter==0 );
- assert( zTerm && nTerm>0 );
-
- /* Advance each segment iterator until it points to the term zTerm/nTerm. */
- rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Determine how many of the segments actually point to zTerm/nTerm. */
- for(i=0; i<nSegment; i++){
- Fts3SegReader *pSeg = pCsr->apSegment[i];
- if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
- break;
- }
- }
- pCsr->nAdvance = i;
-
- /* Advance each of the segments to point to the first docid. */
- for(i=0; i<pCsr->nAdvance; i++){
- rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
- if( rc!=SQLITE_OK ) return rc;
- }
- fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
-
- assert( iCol<0 || iCol<p->nColumn );
- pCsr->iColFilter = iCol;
-
- return SQLITE_OK;
-}
-
-/*
-** This function is called on a MultiSegReader that has been started using
-** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also
-** have been made. Calling this function puts the MultiSegReader in such
-** a state that if the next two calls are:
-**
-** sqlite3Fts3SegReaderStart()
-** sqlite3Fts3SegReaderStep()
-**
-** then the entire doclist for the term is available in
-** MultiSegReader.aDoclist/nDoclist.
-*/
-int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
- int i; /* Used to iterate through segment-readers */
-
- assert( pCsr->zTerm==0 );
- assert( pCsr->nTerm==0 );
- assert( pCsr->aDoclist==0 );
- assert( pCsr->nDoclist==0 );
-
- pCsr->nAdvance = 0;
- pCsr->bRestart = 1;
- for(i=0; i<pCsr->nSegment; i++){
- pCsr->apSegment[i]->pOffsetList = 0;
- pCsr->apSegment[i]->nOffsetList = 0;
- pCsr->apSegment[i]->iDocid = 0;
- }
-
- return SQLITE_OK;
-}
-
-
-int sqlite3Fts3SegReaderStep(
- Fts3Table *p, /* Virtual table handle */
- Fts3MultiSegReader *pCsr /* Cursor object */
-){
- int rc = SQLITE_OK;
-
- int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY);
- int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS);
- int isColFilter = (pCsr->pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER);
- int isPrefix = (pCsr->pFilter->flags & FTS3_SEGMENT_PREFIX);
- int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN);
- int isFirst = (pCsr->pFilter->flags & FTS3_SEGMENT_FIRST);
-
- Fts3SegReader **apSegment = pCsr->apSegment;
- int nSegment = pCsr->nSegment;
- Fts3SegFilter *pFilter = pCsr->pFilter;
- int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
- p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
- );
-
- if( pCsr->nSegment==0 ) return SQLITE_OK;
-
- do {
- int nMerge;
- int i;
-
- /* Advance the first pCsr->nAdvance entries in the apSegment[] array
- ** forward. Then sort the list in order of current term again.
- */
- for(i=0; i<pCsr->nAdvance; i++){
- Fts3SegReader *pSeg = apSegment[i];
- if( pSeg->bLookup ){
- fts3SegReaderSetEof(pSeg);
- }else{
- rc = fts3SegReaderNext(p, pSeg, 0);
- }
- if( rc!=SQLITE_OK ) return rc;
- }
- fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
- pCsr->nAdvance = 0;
-
- /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */
- assert( rc==SQLITE_OK );
- if( apSegment[0]->aNode==0 ) break;
-
- pCsr->nTerm = apSegment[0]->nTerm;
- pCsr->zTerm = apSegment[0]->zTerm;
-
- /* If this is a prefix-search, and if the term that apSegment[0] points
- ** to does not share a suffix with pFilter->zTerm/nTerm, then all
- ** required callbacks have been made. In this case exit early.
- **
- ** Similarly, if this is a search for an exact match, and the first term
- ** of segment apSegment[0] is not a match, exit early.
- */
- if( pFilter->zTerm && !isScan ){
- if( pCsr->nTerm<pFilter->nTerm
- || (!isPrefix && pCsr->nTerm>pFilter->nTerm)
- || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm)
- ){
- break;
- }
- }
-
- nMerge = 1;
- while( nMerge<nSegment
- && apSegment[nMerge]->aNode
- && apSegment[nMerge]->nTerm==pCsr->nTerm
- && 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm)
- ){
- nMerge++;
- }
-
- assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
- if( nMerge==1
- && !isIgnoreEmpty
- && !isFirst
- && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
- ){
- pCsr->nDoclist = apSegment[0]->nDoclist;
- if( fts3SegReaderIsPending(apSegment[0]) ){
- rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
- pCsr->aDoclist = pCsr->aBuffer;
- }else{
- pCsr->aDoclist = apSegment[0]->aDoclist;
- }
- if( rc==SQLITE_OK ) rc = SQLITE_ROW;
- }else{
- int nDoclist = 0; /* Size of doclist */
- sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */
-
- /* The current term of the first nMerge entries in the array
- ** of Fts3SegReader objects is the same. The doclists must be merged
- ** and a single term returned with the merged doclist.
- */
- for(i=0; i<nMerge; i++){
- fts3SegReaderFirstDocid(p, apSegment[i]);
- }
- fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
- while( apSegment[0]->pOffsetList ){
- int j; /* Number of segments that share a docid */
- char *pList = 0;
- int nList = 0;
- int nByte;
- sqlite3_int64 iDocid = apSegment[0]->iDocid;
- fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
- j = 1;
- while( j<nMerge
- && apSegment[j]->pOffsetList
- && apSegment[j]->iDocid==iDocid
- ){
- fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
- j++;
- }
-
- if( isColFilter ){
- fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList);
- }
-
- if( !isIgnoreEmpty || nList>0 ){
-
- /* Calculate the 'docid' delta value to write into the merged
- ** doclist. */
- sqlite3_int64 iDelta;
- if( p->bDescIdx && nDoclist>0 ){
- iDelta = iPrev - iDocid;
- }else{
- iDelta = iDocid - iPrev;
- }
- assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
- assert( nDoclist>0 || iDelta==iDocid );
-
- nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
- if( nDoclist+nByte>pCsr->nBuffer ){
- char *aNew;
- pCsr->nBuffer = (nDoclist+nByte)*2;
- aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
- if( !aNew ){
- return SQLITE_NOMEM;
- }
- pCsr->aBuffer = aNew;
- }
-
- if( isFirst ){
- char *a = &pCsr->aBuffer[nDoclist];
- int nWrite;
-
- nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a);
- if( nWrite ){
- iPrev = iDocid;
- nDoclist += nWrite;
- }
- }else{
- nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta);
- iPrev = iDocid;
- if( isRequirePos ){
- memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
- nDoclist += nList;
- pCsr->aBuffer[nDoclist++] = '\0';
- }
- }
- }
-
- fts3SegReaderSort(apSegment, nMerge, j, xCmp);
- }
- if( nDoclist>0 ){
- pCsr->aDoclist = pCsr->aBuffer;
- pCsr->nDoclist = nDoclist;
- rc = SQLITE_ROW;
- }
- }
- pCsr->nAdvance = nMerge;
- }while( rc==SQLITE_OK );
-
- return rc;
-}
-
-
-void sqlite3Fts3SegReaderFinish(
- Fts3MultiSegReader *pCsr /* Cursor object */
-){
- if( pCsr ){
- int i;
- for(i=0; i<pCsr->nSegment; i++){
- sqlite3Fts3SegReaderFree(pCsr->apSegment[i]);
- }
- sqlite3_free(pCsr->apSegment);
- sqlite3_free(pCsr->aBuffer);
-
- pCsr->nSegment = 0;
- pCsr->apSegment = 0;
- pCsr->aBuffer = 0;
- }
-}
-
-/*
-** Decode the "end_block" field, selected by column iCol of the SELECT
-** statement passed as the first argument.
-**
-** The "end_block" field may contain either an integer, or a text field
-** containing the text representation of two non-negative integers separated
-** by one or more space (0x20) characters. In the first case, set *piEndBlock
-** to the integer value and *pnByte to zero before returning. In the second,
-** set *piEndBlock to the first value and *pnByte to the second.
-*/
-static void fts3ReadEndBlockField(
- sqlite3_stmt *pStmt,
- int iCol,
- i64 *piEndBlock,
- i64 *pnByte
-){
- const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
- if( zText ){
- int i;
- int iMul = 1;
- i64 iVal = 0;
- for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
- iVal = iVal*10 + (zText[i] - '0');
- }
- *piEndBlock = iVal;
- while( zText[i]==' ' ) i++;
- iVal = 0;
- if( zText[i]=='-' ){
- i++;
- iMul = -1;
- }
- for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
- iVal = iVal*10 + (zText[i] - '0');
- }
- *pnByte = (iVal * (i64)iMul);
- }
-}
-
-
-/*
-** A segment of size nByte bytes has just been written to absolute level
-** iAbsLevel. Promote any segments that should be promoted as a result.
-*/
-static int fts3PromoteSegments(
- Fts3Table *p, /* FTS table handle */
- sqlite3_int64 iAbsLevel, /* Absolute level just updated */
- sqlite3_int64 nByte /* Size of new segment at iAbsLevel */
-){
- int rc = SQLITE_OK;
- sqlite3_stmt *pRange;
-
- rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE2, &pRange, 0);
-
- if( rc==SQLITE_OK ){
- int bOk = 0;
- i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1;
- i64 nLimit = (nByte*3)/2;
-
- /* Loop through all entries in the %_segdir table corresponding to
- ** segments in this index on levels greater than iAbsLevel. If there is
- ** at least one such segment, and it is possible to determine that all
- ** such segments are smaller than nLimit bytes in size, they will be
- ** promoted to level iAbsLevel. */
- sqlite3_bind_int64(pRange, 1, iAbsLevel+1);
- sqlite3_bind_int64(pRange, 2, iLast);
- while( SQLITE_ROW==sqlite3_step(pRange) ){
- i64 nSize = 0, dummy;
- fts3ReadEndBlockField(pRange, 2, &dummy, &nSize);
- if( nSize<=0 || nSize>nLimit ){
- /* If nSize==0, then the %_segdir.end_block field does not not
- ** contain a size value. This happens if it was written by an
- ** old version of FTS. In this case it is not possible to determine
- ** the size of the segment, and so segment promotion does not
- ** take place. */
- bOk = 0;
- break;
- }
- bOk = 1;
- }
- rc = sqlite3_reset(pRange);
-
- if( bOk ){
- int iIdx = 0;
- sqlite3_stmt *pUpdate1 = 0;
- sqlite3_stmt *pUpdate2 = 0;
-
- if( rc==SQLITE_OK ){
- rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0);
- }
- if( rc==SQLITE_OK ){
- rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0);
- }
-
- if( rc==SQLITE_OK ){
-
- /* Loop through all %_segdir entries for segments in this index with
- ** levels equal to or greater than iAbsLevel. As each entry is visited,
- ** updated it to set (level = -1) and (idx = N), where N is 0 for the
- ** oldest segment in the range, 1 for the next oldest, and so on.
- **
- ** In other words, move all segments being promoted to level -1,
- ** setting the "idx" fields as appropriate to keep them in the same
- ** order. The contents of level -1 (which is never used, except
- ** transiently here), will be moved back to level iAbsLevel below. */
- sqlite3_bind_int64(pRange, 1, iAbsLevel);
- while( SQLITE_ROW==sqlite3_step(pRange) ){
- sqlite3_bind_int(pUpdate1, 1, iIdx++);
- sqlite3_bind_int(pUpdate1, 2, sqlite3_column_int(pRange, 0));
- sqlite3_bind_int(pUpdate1, 3, sqlite3_column_int(pRange, 1));
- sqlite3_step(pUpdate1);
- rc = sqlite3_reset(pUpdate1);
- if( rc!=SQLITE_OK ){
- sqlite3_reset(pRange);
- break;
- }
- }
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_reset(pRange);
- }
-
- /* Move level -1 to level iAbsLevel */
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pUpdate2, 1, iAbsLevel);
- sqlite3_step(pUpdate2);
- rc = sqlite3_reset(pUpdate2);
- }
- }
- }
-
-
- return rc;
-}
-
-/*
-** Merge all level iLevel segments in the database into a single
-** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
-** single segment with a level equal to the numerically largest level
-** currently present in the database.
-**
-** If this function is called with iLevel<0, but there is only one
-** segment in the database, SQLITE_DONE is returned immediately.
-** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
-** an SQLite error code is returned.
-*/
-static int fts3SegmentMerge(
- Fts3Table *p,
- int iLangid, /* Language id to merge */
- int iIndex, /* Index in p->aIndex[] to merge */
- int iLevel /* Level to merge */
-){
- int rc; /* Return code */
- int iIdx = 0; /* Index of new segment */
- sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */
- SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
- Fts3SegFilter filter; /* Segment term filter condition */
- Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
- int bIgnoreEmpty = 0; /* True to ignore empty segments */
- i64 iMaxLevel = 0; /* Max level number for this index/langid */
-
- assert( iLevel==FTS3_SEGCURSOR_ALL
- || iLevel==FTS3_SEGCURSOR_PENDING
- || iLevel>=0
- );
- assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
- assert( iIndex>=0 && iIndex<p->nIndex );
-
- rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr);
- if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
-
- if( iLevel!=FTS3_SEGCURSOR_PENDING ){
- rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iMaxLevel);
- if( rc!=SQLITE_OK ) goto finished;
- }
-
- if( iLevel==FTS3_SEGCURSOR_ALL ){
- /* This call is to merge all segments in the database to a single
- ** segment. The level of the new segment is equal to the numerically
- ** greatest segment level currently present in the database for this
- ** index. The idx of the new segment is always 0. */
- if( csr.nSegment==1 && 0==fts3SegReaderIsPending(csr.apSegment[0]) ){
- rc = SQLITE_DONE;
- goto finished;
- }
- iNewLevel = iMaxLevel;
- bIgnoreEmpty = 1;
-
- }else{
- /* This call is to merge all segments at level iLevel. find the next
- ** available segment index at level iLevel+1. The call to
- ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
- ** a single iLevel+2 segment if necessary. */
- assert( FTS3_SEGCURSOR_PENDING==-1 );
- iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
- rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
- bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel);
- }
- if( rc!=SQLITE_OK ) goto finished;
-
- assert( csr.nSegment>0 );
- assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
- assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
-
- memset(&filter, 0, sizeof(Fts3SegFilter));
- filter.flags = FTS3_SEGMENT_REQUIRE_POS;
- filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
-
- rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
- while( SQLITE_OK==rc ){
- rc = sqlite3Fts3SegReaderStep(p, &csr);
- if( rc!=SQLITE_ROW ) break;
- rc = fts3SegWriterAdd(p, &pWriter, 1,
- csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
- }
- if( rc!=SQLITE_OK ) goto finished;
- assert( pWriter || bIgnoreEmpty );
-
- if( iLevel!=FTS3_SEGCURSOR_PENDING ){
- rc = fts3DeleteSegdir(
- p, iLangid, iIndex, iLevel, csr.apSegment, csr.nSegment
- );
- if( rc!=SQLITE_OK ) goto finished;
- }
- if( pWriter ){
- rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
- if( rc==SQLITE_OK ){
- if( iLevel==FTS3_SEGCURSOR_PENDING || iNewLevel<iMaxLevel ){
- rc = fts3PromoteSegments(p, iNewLevel, pWriter->nLeafData);
- }
- }
- }
-
- finished:
- fts3SegWriterFree(pWriter);
- sqlite3Fts3SegReaderFinish(&csr);
- return rc;
-}
-
-
-/*
-** Flush the contents of pendingTerms to level 0 segments.
-*/
-int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
- int rc = SQLITE_OK;
- int i;
-
- for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
- rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING);
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- }
- sqlite3Fts3PendingTermsClear(p);
-
- /* Determine the auto-incr-merge setting if unknown. If enabled,
- ** estimate the number of leaf blocks of content to be written
- */
- if( rc==SQLITE_OK && p->bHasStat
- && p->nAutoincrmerge==0xff && p->nLeafAdd>0
- ){
- sqlite3_stmt *pStmt = 0;
- rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
- rc = sqlite3_step(pStmt);
- if( rc==SQLITE_ROW ){
- p->nAutoincrmerge = sqlite3_column_int(pStmt, 0);
- if( p->nAutoincrmerge==1 ) p->nAutoincrmerge = 8;
- }else if( rc==SQLITE_DONE ){
- p->nAutoincrmerge = 0;
- }
- rc = sqlite3_reset(pStmt);
- }
- }
- return rc;
-}
-
-/*
-** Encode N integers as varints into a blob.
-*/
-static void fts3EncodeIntArray(
- int N, /* The number of integers to encode */
- u32 *a, /* The integer values */
- char *zBuf, /* Write the BLOB here */
- int *pNBuf /* Write number of bytes if zBuf[] used here */
-){
- int i, j;
- for(i=j=0; i<N; i++){
- j += sqlite3Fts3PutVarint(&zBuf[j], (sqlite3_int64)a[i]);
- }
- *pNBuf = j;
-}
-
-/*
-** Decode a blob of varints into N integers
-*/
-static void fts3DecodeIntArray(
- int N, /* The number of integers to decode */
- u32 *a, /* Write the integer values */
- const char *zBuf, /* The BLOB containing the varints */
- int nBuf /* size of the BLOB */
-){
- int i, j;
- UNUSED_PARAMETER(nBuf);
- for(i=j=0; i<N; i++){
- sqlite3_int64 x;
- j += sqlite3Fts3GetVarint(&zBuf[j], &x);
- assert(j<=nBuf);
- a[i] = (u32)(x & 0xffffffff);
- }
-}
-
-/*
-** Insert the sizes (in tokens) for each column of the document
-** with docid equal to p->iPrevDocid. The sizes are encoded as
-** a blob of varints.
-*/
-static void fts3InsertDocsize(
- int *pRC, /* Result code */
- Fts3Table *p, /* Table into which to insert */
- u32 *aSz /* Sizes of each column, in tokens */
-){
- char *pBlob; /* The BLOB encoding of the document size */
- int nBlob; /* Number of bytes in the BLOB */
- sqlite3_stmt *pStmt; /* Statement used to insert the encoding */
- int rc; /* Result code from subfunctions */
-
- if( *pRC ) return;
- pBlob = sqlite3_malloc( 10*p->nColumn );
- if( pBlob==0 ){
- *pRC = SQLITE_NOMEM;
- return;
- }
- fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob);
- rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0);
- if( rc ){
- sqlite3_free(pBlob);
- *pRC = rc;
- return;
- }
- sqlite3_bind_int64(pStmt, 1, p->iPrevDocid);
- sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free);
- sqlite3_step(pStmt);
- *pRC = sqlite3_reset(pStmt);
-}
-
-/*
-** Record 0 of the %_stat table contains a blob consisting of N varints,
-** where N is the number of user defined columns in the fts3 table plus
-** two. If nCol is the number of user defined columns, then values of the
-** varints are set as follows:
-**
-** Varint 0: Total number of rows in the table.
-**
-** Varint 1..nCol: For each column, the total number of tokens stored in
-** the column for all rows of the table.
-**
-** Varint 1+nCol: The total size, in bytes, of all text values in all
-** columns of all rows of the table.
-**
-*/
-static void fts3UpdateDocTotals(
- int *pRC, /* The result code */
- Fts3Table *p, /* Table being updated */
- u32 *aSzIns, /* Size increases */
- u32 *aSzDel, /* Size decreases */
- int nChng /* Change in the number of documents */
-){
- char *pBlob; /* Storage for BLOB written into %_stat */
- int nBlob; /* Size of BLOB written into %_stat */
- u32 *a; /* Array of integers that becomes the BLOB */
- sqlite3_stmt *pStmt; /* Statement for reading and writing */
- int i; /* Loop counter */
- int rc; /* Result code from subfunctions */
-
- const int nStat = p->nColumn+2;
-
- if( *pRC ) return;
- a = sqlite3_malloc( (sizeof(u32)+10)*nStat );
- if( a==0 ){
- *pRC = SQLITE_NOMEM;
- return;
- }
- pBlob = (char*)&a[nStat];
- rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
- if( rc ){
- sqlite3_free(a);
- *pRC = rc;
- return;
- }
- sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- fts3DecodeIntArray(nStat, a,
- sqlite3_column_blob(pStmt, 0),
- sqlite3_column_bytes(pStmt, 0));
- }else{
- memset(a, 0, sizeof(u32)*(nStat) );
- }
- rc = sqlite3_reset(pStmt);
- if( rc!=SQLITE_OK ){
- sqlite3_free(a);
- *pRC = rc;
- return;
- }
- if( nChng<0 && a[0]<(u32)(-nChng) ){
- a[0] = 0;
- }else{
- a[0] += nChng;
- }
- for(i=0; i<p->nColumn+1; i++){
- u32 x = a[i+1];
- if( x+aSzIns[i] < aSzDel[i] ){
- x = 0;
- }else{
- x = x + aSzIns[i] - aSzDel[i];
- }
- a[i+1] = x;
- }
- fts3EncodeIntArray(nStat, a, pBlob, &nBlob);
- rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
- if( rc ){
- sqlite3_free(a);
- *pRC = rc;
- return;
- }
- sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
- sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC);
- sqlite3_step(pStmt);
- *pRC = sqlite3_reset(pStmt);
- sqlite3_bind_null(pStmt, 2);
- sqlite3_free(a);
-}
-
-/*
-** Merge the entire database so that there is one segment for each
-** iIndex/iLangid combination.
-*/
-static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
- int bSeenDone = 0;
- int rc;
- sqlite3_stmt *pAllLangid = 0;
-
- rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
- if( rc==SQLITE_OK ){
- int rc2;
- sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
- sqlite3_bind_int(pAllLangid, 2, p->nIndex);
- while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
- int i;
- int iLangid = sqlite3_column_int(pAllLangid, 0);
- for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
- rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL);
- if( rc==SQLITE_DONE ){
- bSeenDone = 1;
- rc = SQLITE_OK;
- }
- }
- }
- rc2 = sqlite3_reset(pAllLangid);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- sqlite3Fts3SegmentsClose(p);
- sqlite3Fts3PendingTermsClear(p);
-
- return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
-}
-
-/*
-** This function is called when the user executes the following statement:
-**
-** INSERT INTO <tbl>(<tbl>) VALUES('rebuild');
-**
-** The entire FTS index is discarded and rebuilt. If the table is one
-** created using the content=xxx option, then the new index is based on
-** the current contents of the xxx table. Otherwise, it is rebuilt based
-** on the contents of the %_content table.
-*/
-static int fts3DoRebuild(Fts3Table *p){
- int rc; /* Return Code */
-
- rc = fts3DeleteAll(p, 0);
- if( rc==SQLITE_OK ){
- u32 *aSz = 0;
- u32 *aSzIns = 0;
- u32 *aSzDel = 0;
- sqlite3_stmt *pStmt = 0;
- int nEntry = 0;
-
- /* Compose and prepare an SQL statement to loop through the content table */
- char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- }
-
- if( rc==SQLITE_OK ){
- int nByte = sizeof(u32) * (p->nColumn+1)*3;
- aSz = (u32 *)sqlite3_malloc(nByte);
- if( aSz==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(aSz, 0, nByte);
- aSzIns = &aSz[p->nColumn+1];
- aSzDel = &aSzIns[p->nColumn+1];
- }
- }
-
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- int iCol;
- int iLangid = langidFromSelect(p, pStmt);
- rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0));
- memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
- for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
- if( p->abNotindexed[iCol]==0 ){
- const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
- rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
- aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
- }
- }
- if( p->bHasDocsize ){
- fts3InsertDocsize(&rc, p, aSz);
- }
- if( rc!=SQLITE_OK ){
- sqlite3_finalize(pStmt);
- pStmt = 0;
- }else{
- nEntry++;
- for(iCol=0; iCol<=p->nColumn; iCol++){
- aSzIns[iCol] += aSz[iCol];
- }
- }
- }
- if( p->bFts4 ){
- fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry);
- }
- sqlite3_free(aSz);
-
- if( pStmt ){
- int rc2 = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
- }
-
- return rc;
-}
-
-
-/*
-** This function opens a cursor used to read the input data for an
-** incremental merge operation. Specifically, it opens a cursor to scan
-** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
-** level iAbsLevel.
-*/
-static int fts3IncrmergeCsr(
- Fts3Table *p, /* FTS3 table handle */
- sqlite3_int64 iAbsLevel, /* Absolute level to open */
- int nSeg, /* Number of segments to merge */
- Fts3MultiSegReader *pCsr /* Cursor object to populate */
-){
- int rc; /* Return Code */
- sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
- int nByte; /* Bytes allocated at pCsr->apSegment[] */
-
- /* Allocate space for the Fts3MultiSegReader.aCsr[] array */
- memset(pCsr, 0, sizeof(*pCsr));
- nByte = sizeof(Fts3SegReader *) * nSeg;
- pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
-
- if( pCsr->apSegment==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pCsr->apSegment, 0, nByte);
- rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
- }
- if( rc==SQLITE_OK ){
- int i;
- int rc2;
- sqlite3_bind_int64(pStmt, 1, iAbsLevel);
- assert( pCsr->nSegment==0 );
- for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && i<nSeg; i++){
- rc = sqlite3Fts3SegReaderNew(i, 0,
- sqlite3_column_int64(pStmt, 1), /* segdir.start_block */
- sqlite3_column_int64(pStmt, 2), /* segdir.leaves_end_block */
- sqlite3_column_int64(pStmt, 3), /* segdir.end_block */
- sqlite3_column_blob(pStmt, 4), /* segdir.root */
- sqlite3_column_bytes(pStmt, 4), /* segdir.root */
- &pCsr->apSegment[i]
- );
- pCsr->nSegment++;
- }
- rc2 = sqlite3_reset(pStmt);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- return rc;
-}
-
-typedef struct IncrmergeWriter IncrmergeWriter;
-typedef struct NodeWriter NodeWriter;
-typedef struct Blob Blob;
-typedef struct NodeReader NodeReader;
-
-/*
-** An instance of the following structure is used as a dynamic buffer
-** to build up nodes or other blobs of data in.
-**
-** The function blobGrowBuffer() is used to extend the allocation.
-*/
-struct Blob {
- char *a; /* Pointer to allocation */
- int n; /* Number of valid bytes of data in a[] */
- int nAlloc; /* Allocated size of a[] (nAlloc>=n) */
-};
-
-/*
-** This structure is used to build up buffers containing segment b-tree
-** nodes (blocks).
-*/
-struct NodeWriter {
- sqlite3_int64 iBlock; /* Current block id */
- Blob key; /* Last key written to the current block */
- Blob block; /* Current block image */
-};
-
-/*
-** An object of this type contains the state required to create or append
-** to an appendable b-tree segment.
-*/
-struct IncrmergeWriter {
- int nLeafEst; /* Space allocated for leaf blocks */
- int nWork; /* Number of leaf pages flushed */
- sqlite3_int64 iAbsLevel; /* Absolute level of input segments */
- int iIdx; /* Index of *output* segment in iAbsLevel+1 */
- sqlite3_int64 iStart; /* Block number of first allocated block */
- sqlite3_int64 iEnd; /* Block number of last allocated block */
- sqlite3_int64 nLeafData; /* Bytes of leaf page data so far */
- u8 bNoLeafData; /* If true, store 0 for segment size */
- NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
-};
-
-/*
-** An object of the following type is used to read data from a single
-** FTS segment node. See the following functions:
-**
-** nodeReaderInit()
-** nodeReaderNext()
-** nodeReaderRelease()
-*/
-struct NodeReader {
- const char *aNode;
- int nNode;
- int iOff; /* Current offset within aNode[] */
-
- /* Output variables. Containing the current node entry. */
- sqlite3_int64 iChild; /* Pointer to child node */
- Blob term; /* Current term */
- const char *aDoclist; /* Pointer to doclist */
- int nDoclist; /* Size of doclist in bytes */
-};
-
-/*
-** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-** Otherwise, if the allocation at pBlob->a is not already at least nMin
-** bytes in size, extend (realloc) it to be so.
-**
-** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a
-** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc
-** to reflect the new size of the pBlob->a[] buffer.
-*/
-static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
- if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){
- int nAlloc = nMin;
- char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc);
- if( a ){
- pBlob->nAlloc = nAlloc;
- pBlob->a = a;
- }else{
- *pRc = SQLITE_NOMEM;
- }
- }
-}
-
-/*
-** Attempt to advance the node-reader object passed as the first argument to
-** the next entry on the node.
-**
-** Return an error code if an error occurs (SQLITE_NOMEM is possible).
-** Otherwise return SQLITE_OK. If there is no next entry on the node
-** (e.g. because the current entry is the last) set NodeReader->aNode to
-** NULL to indicate EOF. Otherwise, populate the NodeReader structure output
-** variables for the new entry.
-*/
-static int nodeReaderNext(NodeReader *p){
- int bFirst = (p->term.n==0); /* True for first term on the node */
- int nPrefix = 0; /* Bytes to copy from previous term */
- int nSuffix = 0; /* Bytes to append to the prefix */
- int rc = SQLITE_OK; /* Return code */
-
- assert( p->aNode );
- if( p->iChild && bFirst==0 ) p->iChild++;
- if( p->iOff>=p->nNode ){
- /* EOF */
- p->aNode = 0;
- }else{
- if( bFirst==0 ){
- p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
- }
- p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
-
- blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
- if( rc==SQLITE_OK ){
- memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
- p->term.n = nPrefix+nSuffix;
- p->iOff += nSuffix;
- if( p->iChild==0 ){
- p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
- p->aDoclist = &p->aNode[p->iOff];
- p->iOff += p->nDoclist;
- }
- }
- }
-
- assert( p->iOff<=p->nNode );
-
- return rc;
-}
-
-/*
-** Release all dynamic resources held by node-reader object *p.
-*/
-static void nodeReaderRelease(NodeReader *p){
- sqlite3_free(p->term.a);
-}
-
-/*
-** Initialize a node-reader object to read the node in buffer aNode/nNode.
-**
-** If successful, SQLITE_OK is returned and the NodeReader object set to
-** point to the first entry on the node (if any). Otherwise, an SQLite
-** error code is returned.
-*/
-static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
- memset(p, 0, sizeof(NodeReader));
- p->aNode = aNode;
- p->nNode = nNode;
-
- /* Figure out if this is a leaf or an internal node. */
- if( p->aNode[0] ){
- /* An internal node. */
- p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
- }else{
- p->iOff = 1;
- }
-
- return nodeReaderNext(p);
-}
-
-/*
-** This function is called while writing an FTS segment each time a leaf o
-** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed
-** to be greater than the largest key on the node just written, but smaller
-** than or equal to the first key that will be written to the next leaf
-** node.
-**
-** The block id of the leaf node just written to disk may be found in
-** (pWriter->aNodeWriter[0].iBlock) when this function is called.
-*/
-static int fts3IncrmergePush(
- Fts3Table *p, /* Fts3 table handle */
- IncrmergeWriter *pWriter, /* Writer object */
- const char *zTerm, /* Term to write to internal node */
- int nTerm /* Bytes at zTerm */
-){
- sqlite3_int64 iPtr = pWriter->aNodeWriter[0].iBlock;
- int iLayer;
-
- assert( nTerm>0 );
- for(iLayer=1; ALWAYS(iLayer<FTS_MAX_APPENDABLE_HEIGHT); iLayer++){
- sqlite3_int64 iNextPtr = 0;
- NodeWriter *pNode = &pWriter->aNodeWriter[iLayer];
- int rc = SQLITE_OK;
- int nPrefix;
- int nSuffix;
- int nSpace;
-
- /* Figure out how much space the key will consume if it is written to
- ** the current node of layer iLayer. Due to the prefix compression,
- ** the space required changes depending on which node the key is to
- ** be added to. */
- nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
- nSuffix = nTerm - nPrefix;
- nSpace = sqlite3Fts3VarintLen(nPrefix);
- nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
-
- if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){
- /* If the current node of layer iLayer contains zero keys, or if adding
- ** the key to it will not cause it to grow to larger than nNodeSize
- ** bytes in size, write the key here. */
-
- Blob *pBlk = &pNode->block;
- if( pBlk->n==0 ){
- blobGrowBuffer(pBlk, p->nNodeSize, &rc);
- if( rc==SQLITE_OK ){
- pBlk->a[0] = (char)iLayer;
- pBlk->n = 1 + sqlite3Fts3PutVarint(&pBlk->a[1], iPtr);
- }
- }
- blobGrowBuffer(pBlk, pBlk->n + nSpace, &rc);
- blobGrowBuffer(&pNode->key, nTerm, &rc);
-
- if( rc==SQLITE_OK ){
- if( pNode->key.n ){
- pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
- }
- pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
- memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
- pBlk->n += nSuffix;
-
- memcpy(pNode->key.a, zTerm, nTerm);
- pNode->key.n = nTerm;
- }
- }else{
- /* Otherwise, flush the current node of layer iLayer to disk.
- ** Then allocate a new, empty sibling node. The key will be written
- ** into the parent of this node. */
- rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
-
- assert( pNode->block.nAlloc>=p->nNodeSize );
- pNode->block.a[0] = (char)iLayer;
- pNode->block.n = 1 + sqlite3Fts3PutVarint(&pNode->block.a[1], iPtr+1);
-
- iNextPtr = pNode->iBlock;
- pNode->iBlock++;
- pNode->key.n = 0;
- }
-
- if( rc!=SQLITE_OK || iNextPtr==0 ) return rc;
- iPtr = iNextPtr;
- }
-
- assert( 0 );
- return 0;
-}
-
-/*
-** Append a term and (optionally) doclist to the FTS segment node currently
-** stored in blob *pNode. The node need not contain any terms, but the
-** header must be written before this function is called.
-**
-** A node header is a single 0x00 byte for a leaf node, or a height varint
-** followed by the left-hand-child varint for an internal node.
-**
-** The term to be appended is passed via arguments zTerm/nTerm. For a
-** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal
-** node, both aDoclist and nDoclist must be passed 0.
-**
-** If the size of the value in blob pPrev is zero, then this is the first
-** term written to the node. Otherwise, pPrev contains a copy of the
-** previous term. Before this function returns, it is updated to contain a
-** copy of zTerm/nTerm.
-**
-** It is assumed that the buffer associated with pNode is already large
-** enough to accommodate the new entry. The buffer associated with pPrev
-** is extended by this function if requrired.
-**
-** If an error (i.e. OOM condition) occurs, an SQLite error code is
-** returned. Otherwise, SQLITE_OK.
-*/
-static int fts3AppendToNode(
- Blob *pNode, /* Current node image to append to */
- Blob *pPrev, /* Buffer containing previous term written */
- const char *zTerm, /* New term to write */
- int nTerm, /* Size of zTerm in bytes */
- const char *aDoclist, /* Doclist (or NULL) to write */
- int nDoclist /* Size of aDoclist in bytes */
-){
- int rc = SQLITE_OK; /* Return code */
- int bFirst = (pPrev->n==0); /* True if this is the first term written */
- int nPrefix; /* Size of term prefix in bytes */
- int nSuffix; /* Size of term suffix in bytes */
-
- /* Node must have already been started. There must be a doclist for a
- ** leaf node, and there must not be a doclist for an internal node. */
- assert( pNode->n>0 );
- assert( (pNode->a[0]=='\0')==(aDoclist!=0) );
-
- blobGrowBuffer(pPrev, nTerm, &rc);
- if( rc!=SQLITE_OK ) return rc;
-
- nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
- nSuffix = nTerm - nPrefix;
- memcpy(pPrev->a, zTerm, nTerm);
- pPrev->n = nTerm;
-
- if( bFirst==0 ){
- pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix);
- }
- pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix);
- memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix);
- pNode->n += nSuffix;
-
- if( aDoclist ){
- pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist);
- memcpy(&pNode->a[pNode->n], aDoclist, nDoclist);
- pNode->n += nDoclist;
- }
-
- assert( pNode->n<=pNode->nAlloc );
-
- return SQLITE_OK;
-}
-
-/*
-** Append the current term and doclist pointed to by cursor pCsr to the
-** appendable b-tree segment opened for writing by pWriter.
-**
-** Return SQLITE_OK if successful, or an SQLite error code otherwise.
-*/
-static int fts3IncrmergeAppend(
- Fts3Table *p, /* Fts3 table handle */
- IncrmergeWriter *pWriter, /* Writer object */
- Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */
-){
- const char *zTerm = pCsr->zTerm;
- int nTerm = pCsr->nTerm;
- const char *aDoclist = pCsr->aDoclist;
- int nDoclist = pCsr->nDoclist;
- int rc = SQLITE_OK; /* Return code */
- int nSpace; /* Total space in bytes required on leaf */
- int nPrefix; /* Size of prefix shared with previous term */
- int nSuffix; /* Size of suffix (nTerm - nPrefix) */
- NodeWriter *pLeaf; /* Object used to write leaf nodes */
-
- pLeaf = &pWriter->aNodeWriter[0];
- nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
- nSuffix = nTerm - nPrefix;
-
- nSpace = sqlite3Fts3VarintLen(nPrefix);
- nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
- nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
-
- /* If the current block is not empty, and if adding this term/doclist
- ** to the current block would make it larger than Fts3Table.nNodeSize
- ** bytes, write this block out to the database. */
- if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){
- rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n);
- pWriter->nWork++;
-
- /* Add the current term to the parent node. The term added to the
- ** parent must:
- **
- ** a) be greater than the largest term on the leaf node just written
- ** to the database (still available in pLeaf->key), and
- **
- ** b) be less than or equal to the term about to be added to the new
- ** leaf node (zTerm/nTerm).
- **
- ** In other words, it must be the prefix of zTerm 1 byte longer than
- ** the common prefix (if any) of zTerm and pWriter->zTerm.
- */
- if( rc==SQLITE_OK ){
- rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1);
- }
-
- /* Advance to the next output block */
- pLeaf->iBlock++;
- pLeaf->key.n = 0;
- pLeaf->block.n = 0;
-
- nSuffix = nTerm;
- nSpace = 1;
- nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
- nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
- }
-
- pWriter->nLeafData += nSpace;
- blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc);
- if( rc==SQLITE_OK ){
- if( pLeaf->block.n==0 ){
- pLeaf->block.n = 1;
- pLeaf->block.a[0] = '\0';
- }
- rc = fts3AppendToNode(
- &pLeaf->block, &pLeaf->key, zTerm, nTerm, aDoclist, nDoclist
- );
- }
-
- return rc;
-}
-
-/*
-** This function is called to release all dynamic resources held by the
-** merge-writer object pWriter, and if no error has occurred, to flush
-** all outstanding node buffers held by pWriter to disk.
-**
-** If *pRc is not SQLITE_OK when this function is called, then no attempt
-** is made to write any data to disk. Instead, this function serves only
-** to release outstanding resources.
-**
-** Otherwise, if *pRc is initially SQLITE_OK and an error occurs while
-** flushing buffers to disk, *pRc is set to an SQLite error code before
-** returning.
-*/
-static void fts3IncrmergeRelease(
- Fts3Table *p, /* FTS3 table handle */
- IncrmergeWriter *pWriter, /* Merge-writer object */
- int *pRc /* IN/OUT: Error code */
-){
- int i; /* Used to iterate through non-root layers */
- int iRoot; /* Index of root in pWriter->aNodeWriter */
- NodeWriter *pRoot; /* NodeWriter for root node */
- int rc = *pRc; /* Error code */
-
- /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment
- ** root node. If the segment fits entirely on a single leaf node, iRoot
- ** will be set to 0. If the root node is the parent of the leaves, iRoot
- ** will be 1. And so on. */
- for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){
- NodeWriter *pNode = &pWriter->aNodeWriter[iRoot];
- if( pNode->block.n>0 ) break;
- assert( *pRc || pNode->block.nAlloc==0 );
- assert( *pRc || pNode->key.nAlloc==0 );
- sqlite3_free(pNode->block.a);
- sqlite3_free(pNode->key.a);
- }
-
- /* Empty output segment. This is a no-op. */
- if( iRoot<0 ) return;
-
- /* The entire output segment fits on a single node. Normally, this means
- ** the node would be stored as a blob in the "root" column of the %_segdir
- ** table. However, this is not permitted in this case. The problem is that
- ** space has already been reserved in the %_segments table, and so the
- ** start_block and end_block fields of the %_segdir table must be populated.
- ** And, by design or by accident, released versions of FTS cannot handle
- ** segments that fit entirely on the root node with start_block!=0.
- **
- ** Instead, create a synthetic root node that contains nothing but a
- ** pointer to the single content node. So that the segment consists of a
- ** single leaf and a single interior (root) node.
- **
- ** Todo: Better might be to defer allocating space in the %_segments
- ** table until we are sure it is needed.
- */
- if( iRoot==0 ){
- Blob *pBlock = &pWriter->aNodeWriter[1].block;
- blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc);
- if( rc==SQLITE_OK ){
- pBlock->a[0] = 0x01;
- pBlock->n = 1 + sqlite3Fts3PutVarint(
- &pBlock->a[1], pWriter->aNodeWriter[0].iBlock
- );
- }
- iRoot = 1;
- }
- pRoot = &pWriter->aNodeWriter[iRoot];
-
- /* Flush all currently outstanding nodes to disk. */
- for(i=0; i<iRoot; i++){
- NodeWriter *pNode = &pWriter->aNodeWriter[i];
- if( pNode->block.n>0 && rc==SQLITE_OK ){
- rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
- }
- sqlite3_free(pNode->block.a);
- sqlite3_free(pNode->key.a);
- }
-
- /* Write the %_segdir record. */
- if( rc==SQLITE_OK ){
- rc = fts3WriteSegdir(p,
- pWriter->iAbsLevel+1, /* level */
- pWriter->iIdx, /* idx */
- pWriter->iStart, /* start_block */
- pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */
- pWriter->iEnd, /* end_block */
- (pWriter->bNoLeafData==0 ? pWriter->nLeafData : 0), /* end_block */
- pRoot->block.a, pRoot->block.n /* root */
- );
- }
- sqlite3_free(pRoot->block.a);
- sqlite3_free(pRoot->key.a);
-
- *pRc = rc;
-}
-
-/*
-** Compare the term in buffer zLhs (size in bytes nLhs) with that in
-** zRhs (size in bytes nRhs) using memcmp. If one term is a prefix of
-** the other, it is considered to be smaller than the other.
-**
-** Return -ve if zLhs is smaller than zRhs, 0 if it is equal, or +ve
-** if it is greater.
-*/
-static int fts3TermCmp(
- const char *zLhs, int nLhs, /* LHS of comparison */
- const char *zRhs, int nRhs /* RHS of comparison */
-){
- int nCmp = MIN(nLhs, nRhs);
- int res;
-
- res = memcmp(zLhs, zRhs, nCmp);
- if( res==0 ) res = nLhs - nRhs;
-
- return res;
-}
-
-
-/*
-** Query to see if the entry in the %_segments table with blockid iEnd is
-** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before
-** returning. Otherwise, set *pbRes to 0.
-**
-** Or, if an error occurs while querying the database, return an SQLite
-** error code. The final value of *pbRes is undefined in this case.
-**
-** This is used to test if a segment is an "appendable" segment. If it
-** is, then a NULL entry has been inserted into the %_segments table
-** with blockid %_segdir.end_block.
-*/
-static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){
- int bRes = 0; /* Result to set *pbRes to */
- sqlite3_stmt *pCheck = 0; /* Statement to query database with */
- int rc; /* Return code */
-
- rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pCheck, 1, iEnd);
- if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1;
- rc = sqlite3_reset(pCheck);
- }
-
- *pbRes = bRes;
- return rc;
-}
-
-/*
-** This function is called when initializing an incremental-merge operation.
-** It checks if the existing segment with index value iIdx at absolute level
-** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the
-** merge-writer object *pWriter is initialized to write to it.
-**
-** An existing segment can be appended to by an incremental merge if:
-**
-** * It was initially created as an appendable segment (with all required
-** space pre-allocated), and
-**
-** * The first key read from the input (arguments zKey and nKey) is
-** greater than the largest key currently stored in the potential
-** output segment.
-*/
-static int fts3IncrmergeLoad(
- Fts3Table *p, /* Fts3 table handle */
- sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
- int iIdx, /* Index of candidate output segment */
- const char *zKey, /* First key to write */
- int nKey, /* Number of bytes in nKey */
- IncrmergeWriter *pWriter /* Populate this object */
-){
- int rc; /* Return code */
- sqlite3_stmt *pSelect = 0; /* SELECT to read %_segdir entry */
-
- rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pSelect, 0);
- if( rc==SQLITE_OK ){
- sqlite3_int64 iStart = 0; /* Value of %_segdir.start_block */
- sqlite3_int64 iLeafEnd = 0; /* Value of %_segdir.leaves_end_block */
- sqlite3_int64 iEnd = 0; /* Value of %_segdir.end_block */
- const char *aRoot = 0; /* Pointer to %_segdir.root buffer */
- int nRoot = 0; /* Size of aRoot[] in bytes */
- int rc2; /* Return code from sqlite3_reset() */
- int bAppendable = 0; /* Set to true if segment is appendable */
-
- /* Read the %_segdir entry for index iIdx absolute level (iAbsLevel+1) */
- sqlite3_bind_int64(pSelect, 1, iAbsLevel+1);
- sqlite3_bind_int(pSelect, 2, iIdx);
- if( sqlite3_step(pSelect)==SQLITE_ROW ){
- iStart = sqlite3_column_int64(pSelect, 1);
- iLeafEnd = sqlite3_column_int64(pSelect, 2);
- fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData);
- if( pWriter->nLeafData<0 ){
- pWriter->nLeafData = pWriter->nLeafData * -1;
- }
- pWriter->bNoLeafData = (pWriter->nLeafData==0);
- nRoot = sqlite3_column_bytes(pSelect, 4);
- aRoot = sqlite3_column_blob(pSelect, 4);
- }else{
- return sqlite3_reset(pSelect);
- }
-
- /* Check for the zero-length marker in the %_segments table */
- rc = fts3IsAppendable(p, iEnd, &bAppendable);
-
- /* Check that zKey/nKey is larger than the largest key the candidate */
- if( rc==SQLITE_OK && bAppendable ){
- char *aLeaf = 0;
- int nLeaf = 0;
-
- rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0);
- if( rc==SQLITE_OK ){
- NodeReader reader;
- for(rc = nodeReaderInit(&reader, aLeaf, nLeaf);
- rc==SQLITE_OK && reader.aNode;
- rc = nodeReaderNext(&reader)
- ){
- assert( reader.aNode );
- }
- if( fts3TermCmp(zKey, nKey, reader.term.a, reader.term.n)<=0 ){
- bAppendable = 0;
- }
- nodeReaderRelease(&reader);
- }
- sqlite3_free(aLeaf);
- }
-
- if( rc==SQLITE_OK && bAppendable ){
- /* It is possible to append to this segment. Set up the IncrmergeWriter
- ** object to do so. */
- int i;
- int nHeight = (int)aRoot[0];
- NodeWriter *pNode;
-
- pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
- pWriter->iStart = iStart;
- pWriter->iEnd = iEnd;
- pWriter->iAbsLevel = iAbsLevel;
- pWriter->iIdx = iIdx;
-
- for(i=nHeight+1; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
- pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
- }
-
- pNode = &pWriter->aNodeWriter[nHeight];
- pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight;
- blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc);
- if( rc==SQLITE_OK ){
- memcpy(pNode->block.a, aRoot, nRoot);
- pNode->block.n = nRoot;
- }
-
- for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){
- NodeReader reader;
- pNode = &pWriter->aNodeWriter[i];
-
- rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
- while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
- blobGrowBuffer(&pNode->key, reader.term.n, &rc);
- if( rc==SQLITE_OK ){
- memcpy(pNode->key.a, reader.term.a, reader.term.n);
- pNode->key.n = reader.term.n;
- if( i>0 ){
- char *aBlock = 0;
- int nBlock = 0;
- pNode = &pWriter->aNodeWriter[i-1];
- pNode->iBlock = reader.iChild;
- rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
- blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc);
- if( rc==SQLITE_OK ){
- memcpy(pNode->block.a, aBlock, nBlock);
- pNode->block.n = nBlock;
- }
- sqlite3_free(aBlock);
- }
- }
- nodeReaderRelease(&reader);
- }
- }
-
- rc2 = sqlite3_reset(pSelect);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- return rc;
-}
-
-/*
-** Determine the largest segment index value that exists within absolute
-** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus
-** one before returning SQLITE_OK. Or, if there are no segments at all
-** within level iAbsLevel, set *piIdx to zero.
-**
-** If an error occurs, return an SQLite error code. The final value of
-** *piIdx is undefined in this case.
-*/
-static int fts3IncrmergeOutputIdx(
- Fts3Table *p, /* FTS Table handle */
- sqlite3_int64 iAbsLevel, /* Absolute index of input segments */
- int *piIdx /* OUT: Next free index at iAbsLevel+1 */
-){
- int rc;
- sqlite3_stmt *pOutputIdx = 0; /* SQL used to find output index */
-
- rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pOutputIdx, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pOutputIdx, 1, iAbsLevel+1);
- sqlite3_step(pOutputIdx);
- *piIdx = sqlite3_column_int(pOutputIdx, 0);
- rc = sqlite3_reset(pOutputIdx);
- }
-
- return rc;
-}
-
-/*
-** Allocate an appendable output segment on absolute level iAbsLevel+1
-** with idx value iIdx.
-**
-** In the %_segdir table, a segment is defined by the values in three
-** columns:
-**
-** start_block
-** leaves_end_block
-** end_block
-**
-** When an appendable segment is allocated, it is estimated that the
-** maximum number of leaf blocks that may be required is the sum of the
-** number of leaf blocks consumed by the input segments, plus the number
-** of input segments, multiplied by two. This value is stored in stack
-** variable nLeafEst.
-**
-** A total of 16*nLeafEst blocks are allocated when an appendable segment
-** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous
-** array of leaf nodes starts at the first block allocated. The array
-** of interior nodes that are parents of the leaf nodes start at block
-** (start_block + (1 + end_block - start_block) / 16). And so on.
-**
-** In the actual code below, the value "16" is replaced with the
-** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT.
-*/
-static int fts3IncrmergeWriter(
- Fts3Table *p, /* Fts3 table handle */
- sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
- int iIdx, /* Index of new output segment */
- Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */
- IncrmergeWriter *pWriter /* Populate this object */
-){
- int rc; /* Return Code */
- int i; /* Iterator variable */
- int nLeafEst = 0; /* Blocks allocated for leaf nodes */
- sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */
- sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */
-
- /* Calculate nLeafEst. */
- rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pLeafEst, 1, iAbsLevel);
- sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment);
- if( SQLITE_ROW==sqlite3_step(pLeafEst) ){
- nLeafEst = sqlite3_column_int(pLeafEst, 0);
- }
- rc = sqlite3_reset(pLeafEst);
- }
- if( rc!=SQLITE_OK ) return rc;
-
- /* Calculate the first block to use in the output segment */
- rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0);
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pFirstBlock) ){
- pWriter->iStart = sqlite3_column_int64(pFirstBlock, 0);
- pWriter->iEnd = pWriter->iStart - 1;
- pWriter->iEnd += nLeafEst * FTS_MAX_APPENDABLE_HEIGHT;
- }
- rc = sqlite3_reset(pFirstBlock);
- }
- if( rc!=SQLITE_OK ) return rc;
-
- /* Insert the marker in the %_segments table to make sure nobody tries
- ** to steal the space just allocated. This is also used to identify
- ** appendable segments. */
- rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0);
- if( rc!=SQLITE_OK ) return rc;
-
- pWriter->iAbsLevel = iAbsLevel;
- pWriter->nLeafEst = nLeafEst;
- pWriter->iIdx = iIdx;
-
- /* Set up the array of NodeWriter objects */
- for(i=0; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
- pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
- }
- return SQLITE_OK;
-}
-
-/*
-** Remove an entry from the %_segdir table. This involves running the
-** following two statements:
-**
-** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx
-** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx
-**
-** The DELETE statement removes the specific %_segdir level. The UPDATE
-** statement ensures that the remaining segments have contiguously allocated
-** idx values.
-*/
-static int fts3RemoveSegdirEntry(
- Fts3Table *p, /* FTS3 table handle */
- sqlite3_int64 iAbsLevel, /* Absolute level to delete from */
- int iIdx /* Index of %_segdir entry to delete */
-){
- int rc; /* Return code */
- sqlite3_stmt *pDelete = 0; /* DELETE statement */
-
- rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pDelete, 1, iAbsLevel);
- sqlite3_bind_int(pDelete, 2, iIdx);
- sqlite3_step(pDelete);
- rc = sqlite3_reset(pDelete);
- }
-
- return rc;
-}
-
-/*
-** One or more segments have just been removed from absolute level iAbsLevel.
-** Update the 'idx' values of the remaining segments in the level so that
-** the idx values are a contiguous sequence starting from 0.
-*/
-static int fts3RepackSegdirLevel(
- Fts3Table *p, /* FTS3 table handle */
- sqlite3_int64 iAbsLevel /* Absolute level to repack */
-){
- int rc; /* Return code */
- int *aIdx = 0; /* Array of remaining idx values */
- int nIdx = 0; /* Valid entries in aIdx[] */
- int nAlloc = 0; /* Allocated size of aIdx[] */
- int i; /* Iterator variable */
- sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */
- sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */
-
- rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0);
- if( rc==SQLITE_OK ){
- int rc2;
- sqlite3_bind_int64(pSelect, 1, iAbsLevel);
- while( SQLITE_ROW==sqlite3_step(pSelect) ){
- if( nIdx>=nAlloc ){
- int *aNew;
- nAlloc += 16;
- aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int));
- if( !aNew ){
- rc = SQLITE_NOMEM;
- break;
- }
- aIdx = aNew;
- }
- aIdx[nIdx++] = sqlite3_column_int(pSelect, 0);
- }
- rc2 = sqlite3_reset(pSelect);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- if( rc==SQLITE_OK ){
- rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0);
- }
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pUpdate, 2, iAbsLevel);
- }
-
- assert( p->bIgnoreSavepoint==0 );
- p->bIgnoreSavepoint = 1;
- for(i=0; rc==SQLITE_OK && i<nIdx; i++){
- if( aIdx[i]!=i ){
- sqlite3_bind_int(pUpdate, 3, aIdx[i]);
- sqlite3_bind_int(pUpdate, 1, i);
- sqlite3_step(pUpdate);
- rc = sqlite3_reset(pUpdate);
- }
- }
- p->bIgnoreSavepoint = 0;
-
- sqlite3_free(aIdx);
- return rc;
-}
-
-static void fts3StartNode(Blob *pNode, int iHeight, sqlite3_int64 iChild){
- pNode->a[0] = (char)iHeight;
- if( iChild ){
- assert( pNode->nAlloc>=1+sqlite3Fts3VarintLen(iChild) );
- pNode->n = 1 + sqlite3Fts3PutVarint(&pNode->a[1], iChild);
- }else{
- assert( pNode->nAlloc>=1 );
- pNode->n = 1;
- }
-}
-
-/*
-** The first two arguments are a pointer to and the size of a segment b-tree
-** node. The node may be a leaf or an internal node.
-**
-** This function creates a new node image in blob object *pNew by copying
-** all terms that are greater than or equal to zTerm/nTerm (for leaf nodes)
-** or greater than zTerm/nTerm (for internal nodes) from aNode/nNode.
-*/
-static int fts3TruncateNode(
- const char *aNode, /* Current node image */
- int nNode, /* Size of aNode in bytes */
- Blob *pNew, /* OUT: Write new node image here */
- const char *zTerm, /* Omit all terms smaller than this */
- int nTerm, /* Size of zTerm in bytes */
- sqlite3_int64 *piBlock /* OUT: Block number in next layer down */
-){
- NodeReader reader; /* Reader object */
- Blob prev = {0, 0, 0}; /* Previous term written to new node */
- int rc = SQLITE_OK; /* Return code */
- int bLeaf = aNode[0]=='\0'; /* True for a leaf node */
-
- /* Allocate required output space */
- blobGrowBuffer(pNew, nNode, &rc);
- if( rc!=SQLITE_OK ) return rc;
- pNew->n = 0;
-
- /* Populate new node buffer */
- for(rc = nodeReaderInit(&reader, aNode, nNode);
- rc==SQLITE_OK && reader.aNode;
- rc = nodeReaderNext(&reader)
- ){
- if( pNew->n==0 ){
- int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm);
- if( res<0 || (bLeaf==0 && res==0) ) continue;
- fts3StartNode(pNew, (int)aNode[0], reader.iChild);
- *piBlock = reader.iChild;
- }
- rc = fts3AppendToNode(
- pNew, &prev, reader.term.a, reader.term.n,
- reader.aDoclist, reader.nDoclist
- );
- if( rc!=SQLITE_OK ) break;
- }
- if( pNew->n==0 ){
- fts3StartNode(pNew, (int)aNode[0], reader.iChild);
- *piBlock = reader.iChild;
- }
- assert( pNew->n<=pNew->nAlloc );
-
- nodeReaderRelease(&reader);
- sqlite3_free(prev.a);
- return rc;
-}
-
-/*
-** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute
-** level iAbsLevel. This may involve deleting entries from the %_segments
-** table, and modifying existing entries in both the %_segments and %_segdir
-** tables.
-**
-** SQLITE_OK is returned if the segment is updated successfully. Or an
-** SQLite error code otherwise.
-*/
-static int fts3TruncateSegment(
- Fts3Table *p, /* FTS3 table handle */
- sqlite3_int64 iAbsLevel, /* Absolute level of segment to modify */
- int iIdx, /* Index within level of segment to modify */
- const char *zTerm, /* Remove terms smaller than this */
- int nTerm /* Number of bytes in buffer zTerm */
-){
- int rc = SQLITE_OK; /* Return code */
- Blob root = {0,0,0}; /* New root page image */
- Blob block = {0,0,0}; /* Buffer used for any other block */
- sqlite3_int64 iBlock = 0; /* Block id */
- sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */
- sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */
- sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */
-
- rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0);
- if( rc==SQLITE_OK ){
- int rc2; /* sqlite3_reset() return code */
- sqlite3_bind_int64(pFetch, 1, iAbsLevel);
- sqlite3_bind_int(pFetch, 2, iIdx);
- if( SQLITE_ROW==sqlite3_step(pFetch) ){
- const char *aRoot = sqlite3_column_blob(pFetch, 4);
- int nRoot = sqlite3_column_bytes(pFetch, 4);
- iOldStart = sqlite3_column_int64(pFetch, 1);
- rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock);
- }
- rc2 = sqlite3_reset(pFetch);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- while( rc==SQLITE_OK && iBlock ){
- char *aBlock = 0;
- int nBlock = 0;
- iNewStart = iBlock;
-
- rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0);
- if( rc==SQLITE_OK ){
- rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock);
- }
- if( rc==SQLITE_OK ){
- rc = fts3WriteSegment(p, iNewStart, block.a, block.n);
- }
- sqlite3_free(aBlock);
- }
-
- /* Variable iNewStart now contains the first valid leaf node. */
- if( rc==SQLITE_OK && iNewStart ){
- sqlite3_stmt *pDel = 0;
- rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pDel, 1, iOldStart);
- sqlite3_bind_int64(pDel, 2, iNewStart-1);
- sqlite3_step(pDel);
- rc = sqlite3_reset(pDel);
- }
- }
-
- if( rc==SQLITE_OK ){
- sqlite3_stmt *pChomp = 0;
- rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pChomp, 1, iNewStart);
- sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC);
- sqlite3_bind_int64(pChomp, 3, iAbsLevel);
- sqlite3_bind_int(pChomp, 4, iIdx);
- sqlite3_step(pChomp);
- rc = sqlite3_reset(pChomp);
- sqlite3_bind_null(pChomp, 2);
- }
- }
-
- sqlite3_free(root.a);
- sqlite3_free(block.a);
- return rc;
-}
-
-/*
-** This function is called after an incrmental-merge operation has run to
-** merge (or partially merge) two or more segments from absolute level
-** iAbsLevel.
-**
-** Each input segment is either removed from the db completely (if all of
-** its data was copied to the output segment by the incrmerge operation)
-** or modified in place so that it no longer contains those entries that
-** have been duplicated in the output segment.
-*/
-static int fts3IncrmergeChomp(
- Fts3Table *p, /* FTS table handle */
- sqlite3_int64 iAbsLevel, /* Absolute level containing segments */
- Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */
- int *pnRem /* Number of segments not deleted */
-){
- int i;
- int nRem = 0;
- int rc = SQLITE_OK;
-
- for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){
- Fts3SegReader *pSeg = 0;
- int j;
-
- /* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding
- ** somewhere in the pCsr->apSegment[] array. */
- for(j=0; ALWAYS(j<pCsr->nSegment); j++){
- pSeg = pCsr->apSegment[j];
- if( pSeg->iIdx==i ) break;
- }
- assert( j<pCsr->nSegment && pSeg->iIdx==i );
-
- if( pSeg->aNode==0 ){
- /* Seg-reader is at EOF. Remove the entire input segment. */
- rc = fts3DeleteSegment(p, pSeg);
- if( rc==SQLITE_OK ){
- rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx);
- }
- *pnRem = 0;
- }else{
- /* The incremental merge did not copy all the data from this
- ** segment to the upper level. The segment is modified in place
- ** so that it contains no keys smaller than zTerm/nTerm. */
- const char *zTerm = pSeg->zTerm;
- int nTerm = pSeg->nTerm;
- rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm);
- nRem++;
- }
- }
-
- if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){
- rc = fts3RepackSegdirLevel(p, iAbsLevel);
- }
-
- *pnRem = nRem;
- return rc;
-}
-
-/*
-** Store an incr-merge hint in the database.
-*/
-static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
- sqlite3_stmt *pReplace = 0;
- int rc; /* Return code */
-
- rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT);
- sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
- sqlite3_step(pReplace);
- rc = sqlite3_reset(pReplace);
- sqlite3_bind_null(pReplace, 2);
- }
-
- return rc;
-}
-
-/*
-** Load an incr-merge hint from the database. The incr-merge hint, if one
-** exists, is stored in the rowid==1 row of the %_stat table.
-**
-** If successful, populate blob *pHint with the value read from the %_stat
-** table and return SQLITE_OK. Otherwise, if an error occurs, return an
-** SQLite error code.
-*/
-static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){
- sqlite3_stmt *pSelect = 0;
- int rc;
-
- pHint->n = 0;
- rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pSelect, 0);
- if( rc==SQLITE_OK ){
- int rc2;
- sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT);
- if( SQLITE_ROW==sqlite3_step(pSelect) ){
- const char *aHint = sqlite3_column_blob(pSelect, 0);
- int nHint = sqlite3_column_bytes(pSelect, 0);
- if( aHint ){
- blobGrowBuffer(pHint, nHint, &rc);
- if( rc==SQLITE_OK ){
- memcpy(pHint->a, aHint, nHint);
- pHint->n = nHint;
- }
- }
- }
- rc2 = sqlite3_reset(pSelect);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- return rc;
-}
-
-/*
-** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-** Otherwise, append an entry to the hint stored in blob *pHint. Each entry
-** consists of two varints, the absolute level number of the input segments
-** and the number of input segments.
-**
-** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs,
-** set *pRc to an SQLite error code before returning.
-*/
-static void fts3IncrmergeHintPush(
- Blob *pHint, /* Hint blob to append to */
- i64 iAbsLevel, /* First varint to store in hint */
- int nInput, /* Second varint to store in hint */
- int *pRc /* IN/OUT: Error code */
-){
- blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc);
- if( *pRc==SQLITE_OK ){
- pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel);
- pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput);
- }
-}
-
-/*
-** Read the last entry (most recently pushed) from the hint blob *pHint
-** and then remove the entry. Write the two values read to *piAbsLevel and
-** *pnInput before returning.
-**
-** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does
-** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB.
-*/
-static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
- const int nHint = pHint->n;
- int i;
-
- i = pHint->n-2;
- while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
- while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
-
- pHint->n = i;
- i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
- i += fts3GetVarint32(&pHint->a[i], pnInput);
- if( i!=nHint ) return FTS_CORRUPT_VTAB;
-
- return SQLITE_OK;
-}
-
-
-/*
-** Attempt an incremental merge that writes nMerge leaf blocks.
-**
-** Incremental merges happen nMin segments at a time. The segments
-** to be merged are the nMin oldest segments (the ones with the smallest
-** values for the _segdir.idx field) in the highest level that contains
-** at least nMin segments. Multiple merges might occur in an attempt to
-** write the quota of nMerge leaf blocks.
-*/
-int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
- int rc; /* Return code */
- int nRem = nMerge; /* Number of leaf pages yet to be written */
- Fts3MultiSegReader *pCsr; /* Cursor used to read input data */
- Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */
- IncrmergeWriter *pWriter; /* Writer object */
- int nSeg = 0; /* Number of input segments */
- sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */
- Blob hint = {0, 0, 0}; /* Hint read from %_stat table */
- int bDirtyHint = 0; /* True if blob 'hint' has been modified */
-
- /* Allocate space for the cursor, filter and writer objects */
- const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
- pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc);
- if( !pWriter ) return SQLITE_NOMEM;
- pFilter = (Fts3SegFilter *)&pWriter[1];
- pCsr = (Fts3MultiSegReader *)&pFilter[1];
-
- rc = fts3IncrmergeHintLoad(p, &hint);
- while( rc==SQLITE_OK && nRem>0 ){
- const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
- sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
- int bUseHint = 0; /* True if attempting to append */
- int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
-
- /* Search the %_segdir table for the absolute level with the smallest
- ** relative level number that contains at least nMin segments, if any.
- ** If one is found, set iAbsLevel to the absolute level number and
- ** nSeg to nMin. If no level with at least nMin segments can be found,
- ** set nSeg to -1.
- */
- rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0);
- sqlite3_bind_int(pFindLevel, 1, MAX(2, nMin));
- if( sqlite3_step(pFindLevel)==SQLITE_ROW ){
- iAbsLevel = sqlite3_column_int64(pFindLevel, 0);
- nSeg = sqlite3_column_int(pFindLevel, 1);
- assert( nSeg>=2 );
- }else{
- nSeg = -1;
- }
- rc = sqlite3_reset(pFindLevel);
-
- /* If the hint read from the %_stat table is not empty, check if the
- ** last entry in it specifies a relative level smaller than or equal
- ** to the level identified by the block above (if any). If so, this
- ** iteration of the loop will work on merging at the hinted level.
- */
- if( rc==SQLITE_OK && hint.n ){
- int nHint = hint.n;
- sqlite3_int64 iHintAbsLevel = 0; /* Hint level */
- int nHintSeg = 0; /* Hint number of segments */
-
- rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
- if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
- iAbsLevel = iHintAbsLevel;
- nSeg = nHintSeg;
- bUseHint = 1;
- bDirtyHint = 1;
- }else{
- /* This undoes the effect of the HintPop() above - so that no entry
- ** is removed from the hint blob. */
- hint.n = nHint;
- }
- }
-
- /* If nSeg is less that zero, then there is no level with at least
- ** nMin segments and no hint in the %_stat table. No work to do.
- ** Exit early in this case. */
- if( nSeg<0 ) break;
-
- /* Open a cursor to iterate through the contents of the oldest nSeg
- ** indexes of absolute level iAbsLevel. If this cursor is opened using
- ** the 'hint' parameters, it is possible that there are less than nSeg
- ** segments available in level iAbsLevel. In this case, no work is
- ** done on iAbsLevel - fall through to the next iteration of the loop
- ** to start work on some other level. */
- memset(pWriter, 0, nAlloc);
- pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
-
- if( rc==SQLITE_OK ){
- rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
- assert( bUseHint==1 || bUseHint==0 );
- if( iIdx==0 || (bUseHint && iIdx==1) ){
- int bIgnore = 0;
- rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore);
- if( bIgnore ){
- pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY;
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
- }
- if( SQLITE_OK==rc && pCsr->nSegment==nSeg
- && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
- && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
- ){
- if( bUseHint && iIdx>0 ){
- const char *zKey = pCsr->zTerm;
- int nKey = pCsr->nTerm;
- rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
- }else{
- rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
- }
-
- if( rc==SQLITE_OK && pWriter->nLeafEst ){
- fts3LogMerge(nSeg, iAbsLevel);
- do {
- rc = fts3IncrmergeAppend(p, pWriter, pCsr);
- if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
- if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
- }while( rc==SQLITE_ROW );
-
- /* Update or delete the input segments */
- if( rc==SQLITE_OK ){
- nRem -= (1 + pWriter->nWork);
- rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg);
- if( nSeg!=0 ){
- bDirtyHint = 1;
- fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc);
- }
- }
- }
-
- if( nSeg!=0 ){
- pWriter->nLeafData = pWriter->nLeafData * -1;
- }
- fts3IncrmergeRelease(p, pWriter, &rc);
- if( nSeg==0 && pWriter->bNoLeafData==0 ){
- fts3PromoteSegments(p, iAbsLevel+1, pWriter->nLeafData);
- }
- }
-
- sqlite3Fts3SegReaderFinish(pCsr);
- }
-
- /* Write the hint values into the %_stat table for the next incr-merger */
- if( bDirtyHint && rc==SQLITE_OK ){
- rc = fts3IncrmergeHintStore(p, &hint);
- }
-
- sqlite3_free(pWriter);
- sqlite3_free(hint.a);
- return rc;
-}
-
-/*
-** Convert the text beginning at *pz into an integer and return
-** its value. Advance *pz to point to the first character past
-** the integer.
-**
-** This function used for parameters to merge= and incrmerge=
-** commands.
-*/
-static int fts3Getint(const char **pz){
- const char *z = *pz;
- int i = 0;
- while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0';
- *pz = z;
- return i;
-}
-
-/*
-** Process statements of the form:
-**
-** INSERT INTO table(table) VALUES('merge=A,B');
-**
-** A and B are integers that decode to be the number of leaf pages
-** written for the merge, and the minimum number of segments on a level
-** before it will be selected for a merge, respectively.
-*/
-static int fts3DoIncrmerge(
- Fts3Table *p, /* FTS3 table handle */
- const char *zParam /* Nul-terminated string containing "A,B" */
-){
- int rc;
- int nMin = (FTS3_MERGE_COUNT / 2);
- int nMerge = 0;
- const char *z = zParam;
-
- /* Read the first integer value */
- nMerge = fts3Getint(&z);
-
- /* If the first integer value is followed by a ',', read the second
- ** integer value. */
- if( z[0]==',' && z[1]!='\0' ){
- z++;
- nMin = fts3Getint(&z);
- }
-
- if( z[0]!='\0' || nMin<2 ){
- rc = SQLITE_ERROR;
- }else{
- rc = SQLITE_OK;
- if( !p->bHasStat ){
- assert( p->bFts4==0 );
- sqlite3Fts3CreateStatTable(&rc, p);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3Incrmerge(p, nMerge, nMin);
- }
- sqlite3Fts3SegmentsClose(p);
- }
- return rc;
-}
-
-/*
-** Process statements of the form:
-**
-** INSERT INTO table(table) VALUES('automerge=X');
-**
-** where X is an integer. X==0 means to turn automerge off. X!=0 means
-** turn it on. The setting is persistent.
-*/
-static int fts3DoAutoincrmerge(
- Fts3Table *p, /* FTS3 table handle */
- const char *zParam /* Nul-terminated string containing boolean */
-){
- int rc = SQLITE_OK;
- sqlite3_stmt *pStmt = 0;
- p->nAutoincrmerge = fts3Getint(&zParam);
- if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
- p->nAutoincrmerge = 8;
- }
- if( !p->bHasStat ){
- assert( p->bFts4==0 );
- sqlite3Fts3CreateStatTable(&rc, p);
- if( rc ) return rc;
- }
- rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
- if( rc ) return rc;
- sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
- sqlite3_bind_int(pStmt, 2, p->nAutoincrmerge);
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- return rc;
-}
-
-/*
-** Return a 64-bit checksum for the FTS index entry specified by the
-** arguments to this function.
-*/
-static u64 fts3ChecksumEntry(
- const char *zTerm, /* Pointer to buffer containing term */
- int nTerm, /* Size of zTerm in bytes */
- int iLangid, /* Language id for current row */
- int iIndex, /* Index (0..Fts3Table.nIndex-1) */
- i64 iDocid, /* Docid for current row. */
- int iCol, /* Column number */
- int iPos /* Position */
-){
- int i;
- u64 ret = (u64)iDocid;
-
- ret += (ret<<3) + iLangid;
- ret += (ret<<3) + iIndex;
- ret += (ret<<3) + iCol;
- ret += (ret<<3) + iPos;
- for(i=0; i<nTerm; i++) ret += (ret<<3) + zTerm[i];
-
- return ret;
-}
-
-/*
-** Return a checksum of all entries in the FTS index that correspond to
-** language id iLangid. The checksum is calculated by XORing the checksums
-** of each individual entry (see fts3ChecksumEntry()) together.
-**
-** If successful, the checksum value is returned and *pRc set to SQLITE_OK.
-** Otherwise, if an error occurs, *pRc is set to an SQLite error code. The
-** return value is undefined in this case.
-*/
-static u64 fts3ChecksumIndex(
- Fts3Table *p, /* FTS3 table handle */
- int iLangid, /* Language id to return cksum for */
- int iIndex, /* Index to cksum (0..p->nIndex-1) */
- int *pRc /* OUT: Return code */
-){
- Fts3SegFilter filter;
- Fts3MultiSegReader csr;
- int rc;
- u64 cksum = 0;
-
- assert( *pRc==SQLITE_OK );
-
- memset(&filter, 0, sizeof(filter));
- memset(&csr, 0, sizeof(csr));
- filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
- filter.flags |= FTS3_SEGMENT_SCAN;
-
- rc = sqlite3Fts3SegReaderCursor(
- p, iLangid, iIndex, FTS3_SEGCURSOR_ALL, 0, 0, 0, 1,&csr
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
- }
-
- if( rc==SQLITE_OK ){
- while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){
- char *pCsr = csr.aDoclist;
- char *pEnd = &pCsr[csr.nDoclist];
-
- i64 iDocid = 0;
- i64 iCol = 0;
- i64 iPos = 0;
-
- pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
- while( pCsr<pEnd ){
- i64 iVal = 0;
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
- if( pCsr<pEnd ){
- if( iVal==0 || iVal==1 ){
- iCol = 0;
- iPos = 0;
- if( iVal ){
- pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
- }else{
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
- iDocid += iVal;
- }
- }else{
- iPos += (iVal - 2);
- cksum = cksum ^ fts3ChecksumEntry(
- csr.zTerm, csr.nTerm, iLangid, iIndex, iDocid,
- (int)iCol, (int)iPos
- );
- }
- }
- }
- }
- }
- sqlite3Fts3SegReaderFinish(&csr);
-
- *pRc = rc;
- return cksum;
-}
-
-/*
-** Check if the contents of the FTS index match the current contents of the
-** content table. If no error occurs and the contents do match, set *pbOk
-** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk
-** to false before returning.
-**
-** If an error occurs (e.g. an OOM or IO error), return an SQLite error
-** code. The final value of *pbOk is undefined in this case.
-*/
-static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
- int rc = SQLITE_OK; /* Return code */
- u64 cksum1 = 0; /* Checksum based on FTS index contents */
- u64 cksum2 = 0; /* Checksum based on %_content contents */
- sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */
-
- /* This block calculates the checksum according to the FTS index. */
- rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
- if( rc==SQLITE_OK ){
- int rc2;
- sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
- sqlite3_bind_int(pAllLangid, 2, p->nIndex);
- while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
- int iLangid = sqlite3_column_int(pAllLangid, 0);
- int i;
- for(i=0; i<p->nIndex; i++){
- cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc);
- }
- }
- rc2 = sqlite3_reset(pAllLangid);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- /* This block calculates the checksum according to the %_content table */
- if( rc==SQLITE_OK ){
- sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
- sqlite3_stmt *pStmt = 0;
- char *zSql;
-
- zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- }
-
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- i64 iDocid = sqlite3_column_int64(pStmt, 0);
- int iLang = langidFromSelect(p, pStmt);
- int iCol;
-
- for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
- if( p->abNotindexed[iCol]==0 ){
- const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
- int nText = sqlite3_column_bytes(pStmt, iCol+1);
- sqlite3_tokenizer_cursor *pT = 0;
-
- rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
- while( rc==SQLITE_OK ){
- char const *zToken; /* Buffer containing token */
- int nToken = 0; /* Number of bytes in token */
- int iDum1 = 0, iDum2 = 0; /* Dummy variables */
- int iPos = 0; /* Position of token in zText */
-
- rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
- if( rc==SQLITE_OK ){
- int i;
- cksum2 = cksum2 ^ fts3ChecksumEntry(
- zToken, nToken, iLang, 0, iDocid, iCol, iPos
- );
- for(i=1; i<p->nIndex; i++){
- if( p->aIndex[i].nPrefix<=nToken ){
- cksum2 = cksum2 ^ fts3ChecksumEntry(
- zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
- );
- }
- }
- }
- }
- if( pT ) pModule->xClose(pT);
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- }
- }
- }
-
- sqlite3_finalize(pStmt);
- }
-
- *pbOk = (cksum1==cksum2);
- return rc;
-}
-
-/*
-** Run the integrity-check. If no error occurs and the current contents of
-** the FTS index are correct, return SQLITE_OK. Or, if the contents of the
-** FTS index are incorrect, return SQLITE_CORRUPT_VTAB.
-**
-** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
-** error code.
-**
-** The integrity-check works as follows. For each token and indexed token
-** prefix in the document set, a 64-bit checksum is calculated (by code
-** in fts3ChecksumEntry()) based on the following:
-**
-** + The index number (0 for the main index, 1 for the first prefix
-** index etc.),
-** + The token (or token prefix) text itself,
-** + The language-id of the row it appears in,
-** + The docid of the row it appears in,
-** + The column it appears in, and
-** + The tokens position within that column.
-**
-** The checksums for all entries in the index are XORed together to create
-** a single checksum for the entire index.
-**
-** The integrity-check code calculates the same checksum in two ways:
-**
-** 1. By scanning the contents of the FTS index, and
-** 2. By scanning and tokenizing the content table.
-**
-** If the two checksums are identical, the integrity-check is deemed to have
-** passed.
-*/
-static int fts3DoIntegrityCheck(
- Fts3Table *p /* FTS3 table handle */
-){
- int rc;
- int bOk = 0;
- rc = fts3IntegrityCheck(p, &bOk);
- if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
- return rc;
-}
-
-/*
-** Handle a 'special' INSERT of the form:
-**
-** "INSERT INTO tbl(tbl) VALUES(<expr>)"
-**
-** Argument pVal contains the result of <expr>. Currently the only
-** meaningful value to insert is the text 'optimize'.
-*/
-static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
- int rc; /* Return Code */
- const char *zVal = (const char *)sqlite3_value_text(pVal);
- int nVal = sqlite3_value_bytes(pVal);
-
- if( !zVal ){
- return SQLITE_NOMEM;
- }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
- rc = fts3DoOptimize(p, 0);
- }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){
- rc = fts3DoRebuild(p);
- }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){
- rc = fts3DoIntegrityCheck(p);
- }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){
- rc = fts3DoIncrmerge(p, &zVal[6]);
- }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
- rc = fts3DoAutoincrmerge(p, &zVal[10]);
-#ifdef SQLITE_TEST
- }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
- p->nNodeSize = atoi(&zVal[9]);
- rc = SQLITE_OK;
- }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
- p->nMaxPendingData = atoi(&zVal[11]);
- rc = SQLITE_OK;
- }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
- p->bNoIncrDoclist = atoi(&zVal[21]);
- rc = SQLITE_OK;
-#endif
- }else{
- rc = SQLITE_ERROR;
- }
-
- return rc;
-}
-
-#ifndef SQLITE_DISABLE_FTS4_DEFERRED
-/*
-** Delete all cached deferred doclists. Deferred doclists are cached
-** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
-*/
-void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
- Fts3DeferredToken *pDef;
- for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
- fts3PendingListDelete(pDef->pList);
- pDef->pList = 0;
- }
-}
-
-/*
-** Free all entries in the pCsr->pDeffered list. Entries are added to
-** this list using sqlite3Fts3DeferToken().
-*/
-void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
- Fts3DeferredToken *pDef;
- Fts3DeferredToken *pNext;
- for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
- pNext = pDef->pNext;
- fts3PendingListDelete(pDef->pList);
- sqlite3_free(pDef);
- }
- pCsr->pDeferred = 0;
-}
-
-/*
-** Generate deferred-doclists for all tokens in the pCsr->pDeferred list
-** based on the row that pCsr currently points to.
-**
-** A deferred-doclist is like any other doclist with position information
-** included, except that it only contains entries for a single row of the
-** table, not for all rows.
-*/
-int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
- int rc = SQLITE_OK; /* Return code */
- if( pCsr->pDeferred ){
- int i; /* Used to iterate through table columns */
- sqlite3_int64 iDocid; /* Docid of the row pCsr points to */
- Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */
-
- Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
- sqlite3_tokenizer *pT = p->pTokenizer;
- sqlite3_tokenizer_module const *pModule = pT->pModule;
-
- assert( pCsr->isRequireSeek==0 );
- iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
-
- for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
- if( p->abNotindexed[i]==0 ){
- const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
- sqlite3_tokenizer_cursor *pTC = 0;
-
- rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
- while( rc==SQLITE_OK ){
- char const *zToken; /* Buffer containing token */
- int nToken = 0; /* Number of bytes in token */
- int iDum1 = 0, iDum2 = 0; /* Dummy variables */
- int iPos = 0; /* Position of token in zText */
-
- rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
- for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
- Fts3PhraseToken *pPT = pDef->pToken;
- if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
- && (pPT->bFirst==0 || iPos==0)
- && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
- && (0==memcmp(zToken, pPT->z, pPT->n))
- ){
- fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
- }
- }
- }
- if( pTC ) pModule->xClose(pTC);
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- }
- }
-
- for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
- if( pDef->pList ){
- rc = fts3PendingListAppendVarint(&pDef->pList, 0);
- }
- }
- }
-
- return rc;
-}
-
-int sqlite3Fts3DeferredTokenList(
- Fts3DeferredToken *p,
- char **ppData,
- int *pnData
-){
- char *pRet;
- int nSkip;
- sqlite3_int64 dummy;
-
- *ppData = 0;
- *pnData = 0;
-
- if( p->pList==0 ){
- return SQLITE_OK;
- }
-
- pRet = (char *)sqlite3_malloc(p->pList->nData);
- if( !pRet ) return SQLITE_NOMEM;
-
- nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
- *pnData = p->pList->nData - nSkip;
- *ppData = pRet;
-
- memcpy(pRet, &p->pList->aData[nSkip], *pnData);
- return SQLITE_OK;
-}
-
-/*
-** Add an entry for token pToken to the pCsr->pDeferred list.
-*/
-int sqlite3Fts3DeferToken(
- Fts3Cursor *pCsr, /* Fts3 table cursor */
- Fts3PhraseToken *pToken, /* Token to defer */
- int iCol /* Column that token must appear in (or -1) */
-){
- Fts3DeferredToken *pDeferred;
- pDeferred = sqlite3_malloc(sizeof(*pDeferred));
- if( !pDeferred ){
- return SQLITE_NOMEM;
- }
- memset(pDeferred, 0, sizeof(*pDeferred));
- pDeferred->pToken = pToken;
- pDeferred->pNext = pCsr->pDeferred;
- pDeferred->iCol = iCol;
- pCsr->pDeferred = pDeferred;
-
- assert( pToken->pDeferred==0 );
- pToken->pDeferred = pDeferred;
-
- return SQLITE_OK;
-}
-#endif
-
-/*
-** SQLite value pRowid contains the rowid of a row that may or may not be
-** present in the FTS3 table. If it is, delete it and adjust the contents
-** of subsiduary data structures accordingly.
-*/
-static int fts3DeleteByRowid(
- Fts3Table *p,
- sqlite3_value *pRowid,
- int *pnChng, /* IN/OUT: Decrement if row is deleted */
- u32 *aSzDel
-){
- int rc = SQLITE_OK; /* Return code */
- int bFound = 0; /* True if *pRowid really is in the table */
-
- fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound);
- if( bFound && rc==SQLITE_OK ){
- int isEmpty = 0; /* Deleting *pRowid leaves the table empty */
- rc = fts3IsEmpty(p, pRowid, &isEmpty);
- if( rc==SQLITE_OK ){
- if( isEmpty ){
- /* Deleting this row means the whole table is empty. In this case
- ** delete the contents of all three tables and throw away any
- ** data in the pendingTerms hash table. */
- rc = fts3DeleteAll(p, 1);
- *pnChng = 0;
- memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2);
- }else{
- *pnChng = *pnChng - 1;
- if( p->zContentTbl==0 ){
- fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
- }
- if( p->bHasDocsize ){
- fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
- }
- }
- }
- }
-
- return rc;
-}
-
-/*
-** This function does the work for the xUpdate method of FTS3 virtual
-** tables. The schema of the virtual table being:
-**
-** CREATE TABLE <table name>(
-** <user columns>,
-** <table name> HIDDEN,
-** docid HIDDEN,
-** <langid> HIDDEN
-** );
-**
-**
-*/
-int sqlite3Fts3UpdateMethod(
- sqlite3_vtab *pVtab, /* FTS3 vtab object */
- int nArg, /* Size of argument array */
- sqlite3_value **apVal, /* Array of arguments */
- sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
-){
- Fts3Table *p = (Fts3Table *)pVtab;
- int rc = SQLITE_OK; /* Return Code */
- u32 *aSzIns = 0; /* Sizes of inserted documents */
- u32 *aSzDel = 0; /* Sizes of deleted documents */
- int nChng = 0; /* Net change in number of documents */
- int bInsertDone = 0;
-
- /* At this point it must be known if the %_stat table exists or not.
- ** So bHasStat may not be 2. */
- assert( p->bHasStat==0 || p->bHasStat==1 );
-
- assert( p->pSegments==0 );
- assert(
- nArg==1 /* DELETE operations */
- || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */
- );
-
- /* Check for a "special" INSERT operation. One of the form:
- **
- ** INSERT INTO xyz(xyz) VALUES('command');
- */
- if( nArg>1
- && sqlite3_value_type(apVal[0])==SQLITE_NULL
- && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
- ){
- rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
- goto update_out;
- }
-
- if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){
- rc = SQLITE_CONSTRAINT;
- goto update_out;
- }
-
- /* Allocate space to hold the change in document sizes */
- aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
- if( aSzDel==0 ){
- rc = SQLITE_NOMEM;
- goto update_out;
- }
- aSzIns = &aSzDel[p->nColumn+1];
- memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
-
- rc = fts3Writelock(p);
- if( rc!=SQLITE_OK ) goto update_out;
-
- /* If this is an INSERT operation, or an UPDATE that modifies the rowid
- ** value, then this operation requires constraint handling.
- **
- ** If the on-conflict mode is REPLACE, this means that the existing row
- ** should be deleted from the database before inserting the new row. Or,
- ** if the on-conflict mode is other than REPLACE, then this method must
- ** detect the conflict and return SQLITE_CONSTRAINT before beginning to
- ** modify the database file.
- */
- if( nArg>1 && p->zContentTbl==0 ){
- /* Find the value object that holds the new rowid value. */
- sqlite3_value *pNewRowid = apVal[3+p->nColumn];
- if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){
- pNewRowid = apVal[1];
- }
-
- if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
- sqlite3_value_type(apVal[0])==SQLITE_NULL
- || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid)
- )){
- /* The new rowid is not NULL (in this case the rowid will be
- ** automatically assigned and there is no chance of a conflict), and
- ** the statement is either an INSERT or an UPDATE that modifies the
- ** rowid column. So if the conflict mode is REPLACE, then delete any
- ** existing row with rowid=pNewRowid.
- **
- ** Or, if the conflict mode is not REPLACE, insert the new record into
- ** the %_content table. If we hit the duplicate rowid constraint (or any
- ** other error) while doing so, return immediately.
- **
- ** This branch may also run if pNewRowid contains a value that cannot
- ** be losslessly converted to an integer. In this case, the eventual
- ** call to fts3InsertData() (either just below or further on in this
- ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
- ** invoked, it will delete zero rows (since no row will have
- ** docid=$pNewRowid if $pNewRowid is not an integer value).
- */
- if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){
- rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel);
- }else{
- rc = fts3InsertData(p, apVal, pRowid);
- bInsertDone = 1;
- }
- }
- }
- if( rc!=SQLITE_OK ){
- goto update_out;
- }
-
- /* If this is a DELETE or UPDATE operation, remove the old record. */
- if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
- assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
- rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
- }
-
- /* If this is an INSERT or UPDATE operation, insert the new record. */
- if( nArg>1 && rc==SQLITE_OK ){
- int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]);
- if( bInsertDone==0 ){
- rc = fts3InsertData(p, apVal, pRowid);
- if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){
- rc = FTS_CORRUPT_VTAB;
- }
- }
- if( rc==SQLITE_OK ){
- rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid);
- }
- if( rc==SQLITE_OK ){
- assert( p->iPrevDocid==*pRowid );
- rc = fts3InsertTerms(p, iLangid, apVal, aSzIns);
- }
- if( p->bHasDocsize ){
- fts3InsertDocsize(&rc, p, aSzIns);
- }
- nChng++;
- }
-
- if( p->bFts4 ){
- fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
- }
-
- update_out:
- sqlite3_free(aSzDel);
- sqlite3Fts3SegmentsClose(p);
- return rc;
-}
-
-/*
-** Flush any data in the pending-terms hash table to disk. If successful,
-** merge all segments in the database (including the new segment, if
-** there was any data to flush) into a single segment.
-*/
-int sqlite3Fts3Optimize(Fts3Table *p){
- int rc;
- rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0);
- if( rc==SQLITE_OK ){
- rc = fts3DoOptimize(p, 1);
- if( rc==SQLITE_OK || rc==SQLITE_DONE ){
- int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
- if( rc2!=SQLITE_OK ) rc = rc2;
- }else{
- sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0);
- sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
- }
- }
- sqlite3Fts3SegmentsClose(p);
- return rc;
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3speed.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3speed.tcl
deleted file mode 100644
index 377cb196065..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/fts3speed.tcl
+++ /dev/null
@@ -1,122 +0,0 @@
-
-
-#--------------------------------------------------------------------------
-# This script contains several sub-programs used to test FTS3/FTS4
-# performance. It does not run the queries directly, but generates SQL
-# scripts that can be run using the shell tool.
-#
-# The following cases are tested:
-#
-# 1. Inserting documents into an FTS3 table.
-# 2. Optimizing an FTS3 table (i.e. "INSERT INTO t1 VALUES('optimize')").
-# 3. Deleting documents from an FTS3 table.
-# 4. Querying FTS3 tables.
-#
-
-# Number of tokens in vocabulary. And number of tokens in each document.
-#
-set VOCAB_SIZE 2000
-set DOC_SIZE 100
-
-set NUM_INSERTS 100000
-set NUM_SELECTS 1000
-
-# Force everything in this script to be deterministic.
-#
-expr {srand(0)}
-
-proc usage {} {
- puts stderr "Usage: $::argv0 <rows> <selects>"
- exit -1
-}
-
-proc sql {sql} {
- puts $::fd $sql
-}
-
-
-# Return a list of $nWord randomly generated tokens each between 2 and 10
-# characters in length.
-#
-proc build_vocab {nWord} {
- set ret [list]
- set chars [list a b c d e f g h i j k l m n o p q r s t u v w x y z]
- for {set i 0} {$i<$nWord} {incr i} {
- set len [expr {int((rand()*9.0)+2)}]
- set term ""
- for {set j 0} {$j<$len} {incr j} {
- append term [lindex $chars [expr {int(rand()*[llength $chars])}]]
- }
- lappend ret $term
- }
- set ret
-}
-
-proc select_term {} {
- set n [llength $::vocab]
- set t [expr int(rand()*$n*3)]
- if {$t>=2*$n} { set t [expr {($t-2*$n)/100}] }
- if {$t>=$n} { set t [expr {($t-$n)/10}] }
- lindex $::vocab $t
-}
-
-proc select_doc {nTerm} {
- set ret [list]
- for {set i 0} {$i<$nTerm} {incr i} {
- lappend ret [select_term]
- }
- set ret
-}
-
-proc test_1 {nInsert} {
- sql "PRAGMA synchronous = OFF;"
- sql "DROP TABLE IF EXISTS t1;"
- sql "CREATE VIRTUAL TABLE t1 USING fts4;"
- for {set i 0} {$i < $nInsert} {incr i} {
- set doc [select_doc $::DOC_SIZE]
- sql "INSERT INTO t1 VALUES('$doc');"
- }
-}
-
-proc test_2 {} {
- sql "INSERT INTO t1(t1) VALUES('optimize');"
-}
-
-proc test_3 {nSelect} {
- for {set i 0} {$i < $nSelect} {incr i} {
- sql "SELECT count(*) FROM t1 WHERE t1 MATCH '[select_term]';"
- }
-}
-
-proc test_4 {nSelect} {
- for {set i 0} {$i < $nSelect} {incr i} {
- sql "SELECT count(*) FROM t1 WHERE t1 MATCH '[select_term] [select_term]';"
- }
-}
-
-if {[llength $argv]!=0} usage
-
-set ::vocab [build_vocab $::VOCAB_SIZE]
-
-set ::fd [open fts3speed_insert.sql w]
-test_1 $NUM_INSERTS
-close $::fd
-
-set ::fd [open fts3speed_select.sql w]
-test_3 $NUM_SELECTS
-close $::fd
-
-set ::fd [open fts3speed_select2.sql w]
-test_4 $NUM_SELECTS
-close $::fd
-
-set ::fd [open fts3speed_optimize.sql w]
-test_2
-close $::fd
-
-puts "Success. Created files:"
-puts " fts3speed_insert.sql"
-puts " fts3speed_select.sql"
-puts " fts3speed_select2.sql"
-puts " fts3speed_optimize.sql"
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/mkfts3amal.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/mkfts3amal.tcl
deleted file mode 100644
index 059048717f9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/mkfts3amal.tcl
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script builds a single C code file holding all of FTS3 code.
-# The name of the output file is fts3amal.c. To build this file,
-# first do:
-#
-# make target_source
-#
-# The make target above moves all of the source code files into
-# a subdirectory named "tsrc". (This script expects to find the files
-# there and will not work if they are not found.)
-#
-# After the "tsrc" directory has been created and populated, run
-# this script:
-#
-# tclsh mkfts3amal.tcl
-#
-# The amalgamated FTS3 code will be written into fts3amal.c
-#
-
-# Open the output file and write a header comment at the beginning
-# of the file.
-#
-set out [open fts3amal.c w]
-set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
-puts $out [subst \
-{/******************************************************************************
-** This file is an amalgamation of separate C source files from the SQLite
-** Full Text Search extension 2 (fts3). By combining all the individual C
-** code files into this single large file, the entire code can be compiled
-** as a one translation unit. This allows many compilers to do optimizations
-** that would not be possible if the files were compiled separately. It also
-** makes the code easier to import into other projects.
-**
-** This amalgamation was generated on $today.
-*/}]
-
-# These are the header files used by FTS3. The first time any of these
-# files are seen in a #include statement in the C code, include the complete
-# text of the file in-line. The file only needs to be included once.
-#
-foreach hdr {
- fts3.h
- fts3_hash.h
- fts3_tokenizer.h
- sqlite3.h
- sqlite3ext.h
-} {
- set available_hdr($hdr) 1
-}
-
-# 78 stars used for comment formatting.
-set s78 \
-{*****************************************************************************}
-
-# Insert a comment into the code
-#
-proc section_comment {text} {
- global out s78
- set n [string length $text]
- set nstar [expr {60 - $n}]
- set stars [string range $s78 0 $nstar]
- puts $out "/************** $text $stars/"
-}
-
-# Read the source file named $filename and write it into the
-# sqlite3.c output file. If any #include statements are seen,
-# process them approprately.
-#
-proc copy_file {filename} {
- global seen_hdr available_hdr out
- set tail [file tail $filename]
- section_comment "Begin file $tail"
- set in [open $filename r]
- while {![eof $in]} {
- set line [gets $in]
- if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
- if {[info exists available_hdr($hdr)]} {
- if {$available_hdr($hdr)} {
- section_comment "Include $hdr in the middle of $tail"
- copy_file tsrc/$hdr
- section_comment "Continuing where we left off in $tail"
- }
- } elseif {![info exists seen_hdr($hdr)]} {
- set seen_hdr($hdr) 1
- puts $out $line
- }
- } elseif {[regexp {^#ifdef __cplusplus} $line]} {
- puts $out "#if 0"
- } elseif {[regexp {^#line} $line]} {
- # Skip #line directives.
- } else {
- puts $out $line
- }
- }
- close $in
- section_comment "End of $tail"
-}
-
-
-# Process the source files. Process files containing commonly
-# used subroutines first in order to help the compiler find
-# inlining opportunities.
-#
-foreach file {
- fts3.c
- fts3_hash.c
- fts3_porter.c
- fts3_tokenizer.c
- fts3_tokenizer1.c
-} {
- copy_file tsrc/$file
-}
-
-close $out
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/tool/fts3cov.sh b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/tool/fts3cov.sh
deleted file mode 100644
index b1f34dce76b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/tool/fts3cov.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-set -e
-
-srcdir=`dirname $(dirname $(dirname $(dirname $0)))`
-./testfixture $srcdir/test/fts3.test --output=fts3cov-out.txt
-
-echo ""
-
-for f in `ls $srcdir/ext/fts3/*.c`
-do
- f=`basename $f`
- echo -ne "$f: "
- gcov -b $f | grep Taken | sed 's/Taken at least once://'
-done
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/tool/fts3view.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/tool/fts3view.c
deleted file mode 100644
index 37f9b7396dc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/tool/fts3view.c
+++ /dev/null
@@ -1,875 +0,0 @@
-/*
-** This program is a debugging and analysis utility that displays
-** information about an FTS3 or FTS4 index.
-**
-** Link this program against the SQLite3 amalgamation with the
-** SQLITE_ENABLE_FTS4 compile-time option. Then run it as:
-**
-** fts3view DATABASE
-**
-** to get a list of all FTS3/4 tables in DATABASE, or do
-**
-** fts3view DATABASE TABLE COMMAND ....
-**
-** to see various aspects of the TABLE table. Type fts3view with no
-** arguments for a list of available COMMANDs.
-*/
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "sqlite3.h"
-
-/*
-** Extra command-line arguments:
-*/
-int nExtra;
-char **azExtra;
-
-/*
-** Look for a command-line argument.
-*/
-const char *findOption(const char *zName, int hasArg, const char *zDefault){
- int i;
- const char *zResult = zDefault;
- for(i=0; i<nExtra; i++){
- const char *z = azExtra[i];
- while( z[0]=='-' ) z++;
- if( strcmp(z, zName)==0 ){
- int j = 1;
- if( hasArg==0 || i==nExtra-1 ) j = 0;
- zResult = azExtra[i+j];
- while( i+j<nExtra ){
- azExtra[i] = azExtra[i+j+1];
- i++;
- }
- break;
- }
- }
- return zResult;
-}
-
-
-/*
-** Prepare an SQL query
-*/
-static sqlite3_stmt *prepare(sqlite3 *db, const char *zFormat, ...){
- va_list ap;
- char *zSql;
- sqlite3_stmt *pStmt;
- int rc;
-
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc ){
- fprintf(stderr, "Error: %s\nSQL: %s\n", sqlite3_errmsg(db), zSql);
- exit(1);
- }
- sqlite3_free(zSql);
- return pStmt;
-}
-
-/*
-** Run an SQL statement
-*/
-static int runSql(sqlite3 *db, const char *zFormat, ...){
- va_list ap;
- char *zSql;
- int rc;
-
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
- va_end(ap);
- return rc;
-}
-
-/*
-** Show the table schema
-*/
-static void showSchema(sqlite3 *db, const char *zTab){
- sqlite3_stmt *pStmt;
- pStmt = prepare(db,
- "SELECT sql FROM sqlite_master"
- " WHERE name LIKE '%q%%'"
- " ORDER BY 1",
- zTab);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- printf("%s;\n", sqlite3_column_text(pStmt, 0));
- }
- sqlite3_finalize(pStmt);
- pStmt = prepare(db, "PRAGMA page_size");
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- printf("PRAGMA page_size=%s;\n", sqlite3_column_text(pStmt, 0));
- }
- sqlite3_finalize(pStmt);
- pStmt = prepare(db, "PRAGMA journal_mode");
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- printf("PRAGMA journal_mode=%s;\n", sqlite3_column_text(pStmt, 0));
- }
- sqlite3_finalize(pStmt);
- pStmt = prepare(db, "PRAGMA auto_vacuum");
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zType = "???";
- switch( sqlite3_column_int(pStmt, 0) ){
- case 0: zType = "OFF"; break;
- case 1: zType = "FULL"; break;
- case 2: zType = "INCREMENTAL"; break;
- }
- printf("PRAGMA auto_vacuum=%s;\n", zType);
- }
- sqlite3_finalize(pStmt);
- pStmt = prepare(db, "PRAGMA encoding");
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- printf("PRAGMA encoding=%s;\n", sqlite3_column_text(pStmt, 0));
- }
- sqlite3_finalize(pStmt);
-}
-
-/*
-** Read a 64-bit variable-length integer from memory starting at p[0].
-** Return the number of bytes read, or 0 on error.
-** The value is stored in *v.
-*/
-int getVarint(const unsigned char *p, sqlite_int64 *v){
- const unsigned char *q = p;
- sqlite_uint64 x = 0, y = 1;
- while( (*q&0x80)==0x80 && q-(unsigned char *)p<9 ){
- x += y * (*q++ & 0x7f);
- y <<= 7;
- }
- x += y * (*q++);
- *v = (sqlite_int64) x;
- return (int) (q - (unsigned char *)p);
-}
-
-
-/* Show the content of the %_stat table
-*/
-static void showStat(sqlite3 *db, const char *zTab){
- sqlite3_stmt *pStmt;
- pStmt = prepare(db, "SELECT id, value FROM '%q_stat'", zTab);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- printf("stat[%d] =", sqlite3_column_int(pStmt, 0));
- switch( sqlite3_column_type(pStmt, 1) ){
- case SQLITE_INTEGER: {
- printf(" %d\n", sqlite3_column_int(pStmt, 1));
- break;
- }
- case SQLITE_BLOB: {
- unsigned char *x = (unsigned char*)sqlite3_column_blob(pStmt, 1);
- int len = sqlite3_column_bytes(pStmt, 1);
- int i = 0;
- sqlite3_int64 v;
- while( i<len ){
- i += getVarint(x, &v);
- printf(" %lld", v);
- }
- printf("\n");
- break;
- }
- }
- }
- sqlite3_finalize(pStmt);
-}
-
-/*
-** Report on the vocabulary. This creates an fts4aux table with a random
-** name, but deletes it in the end.
-*/
-static void showVocabulary(sqlite3 *db, const char *zTab){
- char *zAux;
- sqlite3_uint64 r;
- sqlite3_stmt *pStmt;
- int nDoc = 0;
- int nToken = 0;
- int nOccurrence = 0;
- int nTop;
- int n, i;
-
- sqlite3_randomness(sizeof(r), &r);
- zAux = sqlite3_mprintf("viewer_%llx", zTab, r);
- runSql(db, "BEGIN");
- pStmt = prepare(db, "SELECT count(*) FROM %Q", zTab);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- nDoc = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- printf("Number of documents...................... %9d\n", nDoc);
-
- runSql(db, "CREATE VIRTUAL TABLE %s USING fts4aux(%Q)", zAux, zTab);
- pStmt = prepare(db,
- "SELECT count(*), sum(occurrences) FROM %s WHERE col='*'",
- zAux);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- nToken = sqlite3_column_int(pStmt, 0);
- nOccurrence = sqlite3_column_int(pStmt, 1);
- }
- sqlite3_finalize(pStmt);
- printf("Total tokens in all documents............ %9d\n", nOccurrence);
- printf("Total number of distinct tokens.......... %9d\n", nToken);
- if( nToken==0 ) goto end_vocab;
-
- n = 0;
- pStmt = prepare(db, "SELECT count(*) FROM %s"
- " WHERE col='*' AND occurrences==1", zAux);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- n = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- printf("Tokens used exactly once................. %9d %5.2f%%\n",
- n, n*100.0/nToken);
-
- n = 0;
- pStmt = prepare(db, "SELECT count(*) FROM %s"
- " WHERE col='*' AND documents==1", zAux);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- n = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- printf("Tokens used in only one document......... %9d %5.2f%%\n",
- n, n*100.0/nToken);
-
- if( nDoc>=2000 ){
- n = 0;
- pStmt = prepare(db, "SELECT count(*) FROM %s"
- " WHERE col='*' AND occurrences<=%d", zAux, nDoc/1000);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- n = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- printf("Tokens used in 0.1%% or less of docs...... %9d %5.2f%%\n",
- n, n*100.0/nToken);
- }
-
- if( nDoc>=200 ){
- n = 0;
- pStmt = prepare(db, "SELECT count(*) FROM %s"
- " WHERE col='*' AND occurrences<=%d", zAux, nDoc/100);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- n = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- printf("Tokens used in 1%% or less of docs........ %9d %5.2f%%\n",
- n, n*100.0/nToken);
- }
-
- nTop = atoi(findOption("top", 1, "25"));
- printf("The %d most common tokens:\n", nTop);
- pStmt = prepare(db,
- "SELECT term, documents FROM %s"
- " WHERE col='*'"
- " ORDER BY documents DESC, term"
- " LIMIT %d", zAux, nTop);
- i = 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- i++;
- n = sqlite3_column_int(pStmt, 1);
- printf(" %2d. %-30s %9d docs %5.2f%%\n", i,
- sqlite3_column_text(pStmt, 0), n, n*100.0/nDoc);
- }
- sqlite3_finalize(pStmt);
-
-end_vocab:
- runSql(db, "ROLLBACK");
- sqlite3_free(zAux);
-}
-
-/*
-** Report on the number and sizes of segments
-*/
-static void showSegmentStats(sqlite3 *db, const char *zTab){
- sqlite3_stmt *pStmt;
- int nSeg = 0;
- sqlite3_int64 szSeg = 0, mxSeg = 0;
- int nIdx = 0;
- sqlite3_int64 szIdx = 0, mxIdx = 0;
- int nRoot = 0;
- sqlite3_int64 szRoot = 0, mxRoot = 0;
- sqlite3_int64 mx;
- int nLeaf;
- int n;
- int pgsz;
- int mxLevel;
- int i;
-
- pStmt = prepare(db,
- "SELECT count(*), sum(length(block)), max(length(block))"
- " FROM '%q_segments'",
- zTab);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- nSeg = sqlite3_column_int(pStmt, 0);
- szSeg = sqlite3_column_int64(pStmt, 1);
- mxSeg = sqlite3_column_int64(pStmt, 2);
- }
- sqlite3_finalize(pStmt);
- pStmt = prepare(db,
- "SELECT count(*), sum(length(block)), max(length(block))"
- " FROM '%q_segments' a JOIN '%q_segdir' b"
- " WHERE a.blockid BETWEEN b.leaves_end_block+1 AND b.end_block",
- zTab, zTab);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- nIdx = sqlite3_column_int(pStmt, 0);
- szIdx = sqlite3_column_int64(pStmt, 1);
- mxIdx = sqlite3_column_int64(pStmt, 2);
- }
- sqlite3_finalize(pStmt);
- pStmt = prepare(db,
- "SELECT count(*), sum(length(root)), max(length(root))"
- " FROM '%q_segdir'",
- zTab);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- nRoot = sqlite3_column_int(pStmt, 0);
- szRoot = sqlite3_column_int64(pStmt, 1);
- mxRoot = sqlite3_column_int64(pStmt, 2);
- }
- sqlite3_finalize(pStmt);
-
- printf("Number of segments....................... %9d\n", nSeg+nRoot);
- printf("Number of leaf segments.................. %9d\n", nSeg-nIdx);
- printf("Number of index segments................. %9d\n", nIdx);
- printf("Number of root segments.................. %9d\n", nRoot);
- printf("Total size of all segments............... %9lld\n", szSeg+szRoot);
- printf("Total size of all leaf segments.......... %9lld\n", szSeg-szIdx);
- printf("Total size of all index segments......... %9lld\n", szIdx);
- printf("Total size of all root segments.......... %9lld\n", szRoot);
- if( nSeg>0 ){
- printf("Average size of all segments............. %11.1f\n",
- (double)(szSeg+szRoot)/(double)(nSeg+nRoot));
- printf("Average size of leaf segments............ %11.1f\n",
- (double)(szSeg-szIdx)/(double)(nSeg-nIdx));
- }
- if( nIdx>0 ){
- printf("Average size of index segments........... %11.1f\n",
- (double)szIdx/(double)nIdx);
- }
- if( nRoot>0 ){
- printf("Average size of root segments............ %11.1f\n",
- (double)szRoot/(double)nRoot);
- }
- mx = mxSeg;
- if( mx<mxRoot ) mx = mxRoot;
- printf("Maximum segment size..................... %9lld\n", mx);
- printf("Maximum index segment size............... %9lld\n", mxIdx);
- printf("Maximum root segment size................ %9lld\n", mxRoot);
-
- pStmt = prepare(db, "PRAGMA page_size");
- pgsz = 1024;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- pgsz = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- printf("Database page size....................... %9d\n", pgsz);
- pStmt = prepare(db,
- "SELECT count(*)"
- " FROM '%q_segments' a JOIN '%q_segdir' b"
- " WHERE a.blockid BETWEEN b.start_block AND b.leaves_end_block"
- " AND length(a.block)>%d",
- zTab, zTab, pgsz-45);
- n = 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- n = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- nLeaf = nSeg - nIdx;
- printf("Leaf segments larger than %5d bytes.... %9d %5.2f%%\n",
- pgsz-45, n, nLeaf>0 ? n*100.0/nLeaf : 0.0);
-
- pStmt = prepare(db, "SELECT max(level%%1024) FROM '%q_segdir'", zTab);
- mxLevel = 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- mxLevel = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
-
- for(i=0; i<=mxLevel; i++){
- pStmt = prepare(db,
- "SELECT count(*), sum(len), avg(len), max(len), sum(len>%d),"
- " count(distinct idx)"
- " FROM (SELECT length(a.block) AS len, idx"
- " FROM '%q_segments' a JOIN '%q_segdir' b"
- " WHERE (a.blockid BETWEEN b.start_block"
- " AND b.leaves_end_block)"
- " AND (b.level%%1024)==%d)",
- pgsz-45, zTab, zTab, i);
- if( sqlite3_step(pStmt)==SQLITE_ROW
- && (nLeaf = sqlite3_column_int(pStmt, 0))>0
- ){
- sqlite3_int64 sz;
- nIdx = sqlite3_column_int(pStmt, 5);
- printf("For level %d:\n", i);
- printf(" Number of indexes...................... %9d\n", nIdx);
- printf(" Number of leaf segments................ %9d\n", nLeaf);
- if( nIdx>1 ){
- printf(" Average leaf segments per index........ %11.1f\n",
- (double)nLeaf/(double)nIdx);
- }
- printf(" Total size of all leaf segments........ %9lld\n",
- (sz = sqlite3_column_int64(pStmt, 1)));
- printf(" Average size of leaf segments.......... %11.1f\n",
- sqlite3_column_double(pStmt, 2));
- if( nIdx>1 ){
- printf(" Average leaf segment size per index.... %11.1f\n",
- (double)sz/(double)nIdx);
- }
- printf(" Maximum leaf segment size.............. %9lld\n",
- sqlite3_column_int64(pStmt, 3));
- n = sqlite3_column_int(pStmt, 4);
- printf(" Leaf segments larger than %5d bytes.. %9d %5.2f%%\n",
- pgsz-45, n, n*100.0/nLeaf);
- }
- sqlite3_finalize(pStmt);
- }
-}
-
-/*
-** Print a single "tree" line of the segdir map output.
-*/
-static void printTreeLine(sqlite3_int64 iLower, sqlite3_int64 iUpper){
- printf(" tree %9lld", iLower);
- if( iUpper>iLower ){
- printf(" thru %9lld (%lld blocks)", iUpper, iUpper-iLower+1);
- }
- printf("\n");
-}
-
-/*
-** Check to see if the block of a %_segments entry is NULL.
-*/
-static int isNullSegment(sqlite3 *db, const char *zTab, sqlite3_int64 iBlockId){
- sqlite3_stmt *pStmt;
- int rc = 1;
-
- pStmt = prepare(db, "SELECT block IS NULL FROM '%q_segments'"
- " WHERE blockid=%lld", zTab, iBlockId);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- rc = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- return rc;
-}
-
-/*
-** Show a map of segments derived from the %_segdir table.
-*/
-static void showSegdirMap(sqlite3 *db, const char *zTab){
- int mxIndex, iIndex;
- sqlite3_stmt *pStmt = 0;
- sqlite3_stmt *pStmt2 = 0;
- int prevLevel;
-
- pStmt = prepare(db, "SELECT max(level/1024) FROM '%q_segdir'", zTab);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- mxIndex = sqlite3_column_int(pStmt, 0);
- }else{
- mxIndex = 0;
- }
- sqlite3_finalize(pStmt);
-
- printf("Number of inverted indices............... %3d\n", mxIndex+1);
- pStmt = prepare(db,
- "SELECT level, idx, start_block, leaves_end_block, end_block, rowid"
- " FROM '%q_segdir'"
- " WHERE level/1024==?"
- " ORDER BY level DESC, idx",
- zTab);
- pStmt2 = prepare(db,
- "SELECT blockid FROM '%q_segments'"
- " WHERE blockid BETWEEN ? AND ? ORDER BY blockid",
- zTab);
- for(iIndex=0; iIndex<=mxIndex; iIndex++){
- if( mxIndex>0 ){
- printf("**************************** Index %d "
- "****************************\n", iIndex);
- }
- sqlite3_bind_int(pStmt, 1, iIndex);
- prevLevel = -1;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- int iLevel = sqlite3_column_int(pStmt, 0)%1024;
- int iIdx = sqlite3_column_int(pStmt, 1);
- sqlite3_int64 iStart = sqlite3_column_int64(pStmt, 2);
- sqlite3_int64 iLEnd = sqlite3_column_int64(pStmt, 3);
- sqlite3_int64 iEnd = sqlite3_column_int64(pStmt, 4);
- char rtag[20];
- if( iLevel!=prevLevel ){
- printf("level %2d idx %2d", iLevel, iIdx);
- prevLevel = iLevel;
- }else{
- printf(" idx %2d", iIdx);
- }
- sqlite3_snprintf(sizeof(rtag), rtag, "r%lld",
- sqlite3_column_int64(pStmt,5));
- printf(" root %9s\n", rtag);
- if( iLEnd>iStart ){
- sqlite3_int64 iLower, iPrev = 0, iX;
- if( iLEnd+1<=iEnd ){
- sqlite3_bind_int64(pStmt2, 1, iLEnd+1);
- sqlite3_bind_int64(pStmt2, 2, iEnd);
- iLower = -1;
- while( sqlite3_step(pStmt2)==SQLITE_ROW ){
- iX = sqlite3_column_int64(pStmt2, 0);
- if( iLower<0 ){
- iLower = iPrev = iX;
- }else if( iX==iPrev+1 ){
- iPrev = iX;
- }else{
- printTreeLine(iLower, iPrev);
- iLower = iPrev = iX;
- }
- }
- sqlite3_reset(pStmt2);
- if( iLower>=0 ){
- if( iLower==iPrev && iLower==iEnd
- && isNullSegment(db,zTab,iLower)
- ){
- printf(" null %9lld\n", iLower);
- }else{
- printTreeLine(iLower, iPrev);
- }
- }
- }
- printf(" leaves %9lld thru %9lld (%lld blocks)\n",
- iStart, iLEnd, iLEnd - iStart + 1);
- }
- }
- sqlite3_reset(pStmt);
- }
- sqlite3_finalize(pStmt);
- sqlite3_finalize(pStmt2);
-}
-
-/*
-** Decode a single segment block and display the results on stdout.
-*/
-static void decodeSegment(
- const unsigned char *aData, /* Content to print */
- int nData /* Number of bytes of content */
-){
- sqlite3_int64 iChild = 0;
- sqlite3_int64 iPrefix;
- sqlite3_int64 nTerm;
- sqlite3_int64 n;
- sqlite3_int64 iDocsz;
- int iHeight;
- sqlite3_int64 i = 0;
- int cnt = 0;
- char zTerm[1000];
-
- i += getVarint(aData, &n);
- iHeight = (int)n;
- printf("height: %d\n", iHeight);
- if( iHeight>0 ){
- i += getVarint(aData+i, &iChild);
- printf("left-child: %lld\n", iChild);
- }
- while( i<nData ){
- if( (cnt++)>0 ){
- i += getVarint(aData+i, &iPrefix);
- }else{
- iPrefix = 0;
- }
- i += getVarint(aData+i, &nTerm);
- if( iPrefix+nTerm+1 >= sizeof(zTerm) ){
- fprintf(stderr, "term to long\n");
- exit(1);
- }
- memcpy(zTerm+iPrefix, aData+i, (size_t)nTerm);
- zTerm[iPrefix+nTerm] = 0;
- i += nTerm;
- if( iHeight==0 ){
- i += getVarint(aData+i, &iDocsz);
- printf("term: %-25s doclist %7lld bytes offset %lld\n", zTerm, iDocsz, i);
- i += iDocsz;
- }else{
- printf("term: %-25s child %lld\n", zTerm, ++iChild);
- }
- }
-}
-
-
-/*
-** Print a a blob as hex and ascii.
-*/
-static void printBlob(
- const unsigned char *aData, /* Content to print */
- int nData /* Number of bytes of content */
-){
- int i, j;
- const char *zOfstFmt;
- const int perLine = 16;
-
- if( (nData&~0xfff)==0 ){
- zOfstFmt = " %03x: ";
- }else if( (nData&~0xffff)==0 ){
- zOfstFmt = " %04x: ";
- }else if( (nData&~0xfffff)==0 ){
- zOfstFmt = " %05x: ";
- }else if( (nData&~0xffffff)==0 ){
- zOfstFmt = " %06x: ";
- }else{
- zOfstFmt = " %08x: ";
- }
-
- for(i=0; i<nData; i += perLine){
- fprintf(stdout, zOfstFmt, i);
- for(j=0; j<perLine; j++){
- if( i+j>nData ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%02x ", aData[i+j]);
- }
- }
- for(j=0; j<perLine; j++){
- if( i+j>nData ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%c", isprint(aData[i+j]) ? aData[i+j] : '.');
- }
- }
- fprintf(stdout,"\n");
- }
-}
-
-/*
-** Convert text to a 64-bit integer
-*/
-static sqlite3_int64 atoi64(const char *z){
- sqlite3_int64 v = 0;
- while( z[0]>='0' && z[0]<='9' ){
- v = v*10 + z[0] - '0';
- z++;
- }
- return v;
-}
-
-/*
-** Return a prepared statement which, when stepped, will return in its
-** first column the blob associated with segment zId. If zId begins with
-** 'r' then it is a rowid of a %_segdir entry. Otherwise it is a
-** %_segment entry.
-*/
-static sqlite3_stmt *prepareToGetSegment(
- sqlite3 *db, /* The database */
- const char *zTab, /* The FTS3/4 table name */
- const char *zId /* ID of the segment to open */
-){
- sqlite3_stmt *pStmt;
- if( zId[0]=='r' ){
- pStmt = prepare(db, "SELECT root FROM '%q_segdir' WHERE rowid=%lld",
- zTab, atoi64(zId+1));
- }else{
- pStmt = prepare(db, "SELECT block FROM '%q_segments' WHERE blockid=%lld",
- zTab, atoi64(zId));
- }
- return pStmt;
-}
-
-/*
-** Print the content of a segment or of the root of a segdir. The segment
-** or root is identified by azExtra[0]. If the first character of azExtra[0]
-** is 'r' then the remainder is the integer rowid of the %_segdir entry.
-** If the first character of azExtra[0] is not 'r' then, then all of
-** azExtra[0] is an integer which is the block number.
-**
-** If the --raw option is present in azExtra, then a hex dump is provided.
-** Otherwise a decoding is shown.
-*/
-static void showSegment(sqlite3 *db, const char *zTab){
- const unsigned char *aData;
- int nData;
- sqlite3_stmt *pStmt;
-
- pStmt = prepareToGetSegment(db, zTab, azExtra[0]);
- if( sqlite3_step(pStmt)!=SQLITE_ROW ){
- sqlite3_finalize(pStmt);
- return;
- }
- nData = sqlite3_column_bytes(pStmt, 0);
- aData = sqlite3_column_blob(pStmt, 0);
- printf("Segment %s of size %d bytes:\n", azExtra[0], nData);
- if( findOption("raw", 0, 0)!=0 ){
- printBlob(aData, nData);
- }else{
- decodeSegment(aData, nData);
- }
- sqlite3_finalize(pStmt);
-}
-
-/*
-** Decode a single doclist and display the results on stdout.
-*/
-static void decodeDoclist(
- const unsigned char *aData, /* Content to print */
- int nData /* Number of bytes of content */
-){
- sqlite3_int64 iPrevDocid = 0;
- sqlite3_int64 iDocid;
- sqlite3_int64 iPos;
- sqlite3_int64 iPrevPos = 0;
- sqlite3_int64 iCol;
- int i = 0;
-
- while( i<nData ){
- i += getVarint(aData+i, &iDocid);
- printf("docid %lld col0", iDocid+iPrevDocid);
- iPrevDocid += iDocid;
- iPrevPos = 0;
- while( 1 ){
- i += getVarint(aData+i, &iPos);
- if( iPos==1 ){
- i += getVarint(aData+i, &iCol);
- printf(" col%lld", iCol);
- iPrevPos = 0;
- }else if( iPos==0 ){
- printf("\n");
- break;
- }else{
- iPrevPos += iPos - 2;
- printf(" %lld", iPrevPos);
- }
- }
- }
-}
-
-
-/*
-** Print the content of a doclist. The segment or segdir-root is
-** identified by azExtra[0]. If the first character of azExtra[0]
-** is 'r' then the remainder is the integer rowid of the %_segdir entry.
-** If the first character of azExtra[0] is not 'r' then, then all of
-** azExtra[0] is an integer which is the block number. The offset
-** into the segment is identified by azExtra[1]. The size of the doclist
-** is azExtra[2].
-**
-** If the --raw option is present in azExtra, then a hex dump is provided.
-** Otherwise a decoding is shown.
-*/
-static void showDoclist(sqlite3 *db, const char *zTab){
- const unsigned char *aData;
- sqlite3_int64 offset;
- int nData;
- sqlite3_stmt *pStmt;
-
- offset = atoi64(azExtra[1]);
- nData = atoi(azExtra[2]);
- pStmt = prepareToGetSegment(db, zTab, azExtra[0]);
- if( sqlite3_step(pStmt)!=SQLITE_ROW ){
- sqlite3_finalize(pStmt);
- return;
- }
- aData = sqlite3_column_blob(pStmt, 0);
- printf("Doclist at %s offset %lld of size %d bytes:\n",
- azExtra[0], offset, nData);
- if( findOption("raw", 0, 0)!=0 ){
- printBlob(aData+offset, nData);
- }else{
- decodeDoclist(aData+offset, nData);
- }
- sqlite3_finalize(pStmt);
-}
-
-/*
-** Show the top N largest segments
-*/
-static void listBigSegments(sqlite3 *db, const char *zTab){
- int nTop, i;
- sqlite3_stmt *pStmt;
- sqlite3_int64 sz;
- sqlite3_int64 id;
-
- nTop = atoi(findOption("top", 1, "25"));
- printf("The %d largest segments:\n", nTop);
- pStmt = prepare(db,
- "SELECT blockid, length(block) AS len FROM '%q_segments'"
- " ORDER BY 2 DESC, 1"
- " LIMIT %d", zTab, nTop);
- i = 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- i++;
- id = sqlite3_column_int64(pStmt, 0);
- sz = sqlite3_column_int64(pStmt, 1);
- printf(" %2d. %9lld size %lld\n", i, id, sz);
- }
- sqlite3_finalize(pStmt);
-}
-
-
-
-static void usage(const char *argv0){
- fprintf(stderr, "Usage: %s DATABASE\n"
- " or: %s DATABASE FTS3TABLE ARGS...\n", argv0, argv0);
- fprintf(stderr,
- "ARGS:\n"
- " big-segments [--top N] show the largest segments\n"
- " doclist BLOCKID OFFSET SIZE [--raw] Decode a doclist\n"
- " schema FTS table schema\n"
- " segdir directory of segments\n"
- " segment BLOCKID [--raw] content of a segment\n"
- " segment-stats info on segment sizes\n"
- " stat the %%_stat table\n"
- " vocabulary [--top N] document vocabulary\n"
- );
- exit(1);
-}
-
-int main(int argc, char **argv){
- sqlite3 *db;
- int rc;
- const char *zTab;
- const char *zCmd;
-
- if( argc<2 ) usage(argv[0]);
- rc = sqlite3_open(argv[1], &db);
- if( rc ){
- fprintf(stderr, "Cannot open %s\n", argv[1]);
- exit(1);
- }
- if( argc==2 ){
- sqlite3_stmt *pStmt;
- int cnt = 0;
- pStmt = prepare(db, "SELECT b.sql"
- " FROM sqlite_master a, sqlite_master b"
- " WHERE a.name GLOB '*_segdir'"
- " AND b.name=substr(a.name,1,length(a.name)-7)"
- " ORDER BY 1");
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- cnt++;
- printf("%s;\n", sqlite3_column_text(pStmt, 0));
- }
- sqlite3_finalize(pStmt);
- if( cnt==0 ){
- printf("/* No FTS3/4 tables found in database %s */\n", argv[1]);
- }
- return 0;
- }
- if( argc<4 ) usage(argv[0]);
- zTab = argv[2];
- zCmd = argv[3];
- nExtra = argc-4;
- azExtra = argv+4;
- if( strcmp(zCmd,"big-segments")==0 ){
- listBigSegments(db, zTab);
- }else if( strcmp(zCmd,"doclist")==0 ){
- if( argc<7 ) usage(argv[0]);
- showDoclist(db, zTab);
- }else if( strcmp(zCmd,"schema")==0 ){
- showSchema(db, zTab);
- }else if( strcmp(zCmd,"segdir")==0 ){
- showSegdirMap(db, zTab);
- }else if( strcmp(zCmd,"segment")==0 ){
- if( argc<5 ) usage(argv[0]);
- showSegment(db, zTab);
- }else if( strcmp(zCmd,"segment-stats")==0 ){
- showSegmentStats(db, zTab);
- }else if( strcmp(zCmd,"stat")==0 ){
- showStat(db, zTab);
- }else if( strcmp(zCmd,"vocabulary")==0 ){
- showVocabulary(db, zTab);
- }else{
- usage(argv[0]);
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/CaseFolding.txt b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/CaseFolding.txt
deleted file mode 100644
index 0d9a4090cde..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/CaseFolding.txt
+++ /dev/null
@@ -1,1224 +0,0 @@
-# CaseFolding-6.1.0.txt
-# Date: 2011-07-25, 21:21:56 GMT [MD]
-#
-# Unicode Character Database
-# Copyright (c) 1991-2011 Unicode, Inc.
-# For terms of use, see http://www.unicode.org/terms_of_use.html
-# For documentation, see http://www.unicode.org/reports/tr44/
-#
-# Case Folding Properties
-#
-# This file is a supplement to the UnicodeData file.
-# It provides a case folding mapping generated from the Unicode Character Database.
-# If all characters are mapped according to the full mapping below, then
-# case differences (according to UnicodeData.txt and SpecialCasing.txt)
-# are eliminated.
-#
-# The data supports both implementations that require simple case foldings
-# (where string lengths don't change), and implementations that allow full case folding
-# (where string lengths may grow). Note that where they can be supported, the
-# full case foldings are superior: for example, they allow "MASSE" and "Maße" to match.
-#
-# All code points not listed in this file map to themselves.
-#
-# NOTE: case folding does not preserve normalization formats!
-#
-# For information on case folding, including how to have case folding
-# preserve normalization formats, see Section 3.13 Default Case Algorithms in
-# The Unicode Standard, Version 5.0.
-#
-# ================================================================================
-# Format
-# ================================================================================
-# The entries in this file are in the following machine-readable format:
-#
-# <code>; <status>; <mapping>; # <name>
-#
-# The status field is:
-# C: common case folding, common mappings shared by both simple and full mappings.
-# F: full case folding, mappings that cause strings to grow in length. Multiple characters are separated by spaces.
-# S: simple case folding, mappings to single characters where different from F.
-# T: special case for uppercase I and dotted uppercase I
-# - For non-Turkic languages, this mapping is normally not used.
-# - For Turkic languages (tr, az), this mapping can be used instead of the normal mapping for these characters.
-# Note that the Turkic mappings do not maintain canonical equivalence without additional processing.
-# See the discussions of case mapping in the Unicode Standard for more information.
-#
-# Usage:
-# A. To do a simple case folding, use the mappings with status C + S.
-# B. To do a full case folding, use the mappings with status C + F.
-#
-# The mappings with status T can be used or omitted depending on the desired case-folding
-# behavior. (The default option is to exclude them.)
-#
-# =================================================================
-
-# Property: Case_Folding
-
-# All code points not explicitly listed for Case_Folding
-# have the value C for the status field, and the code point itself for the mapping field.
-
-# @missing: 0000..10FFFF; C; <code point>
-
-# =================================================================
-0041; C; 0061; # LATIN CAPITAL LETTER A
-0042; C; 0062; # LATIN CAPITAL LETTER B
-0043; C; 0063; # LATIN CAPITAL LETTER C
-0044; C; 0064; # LATIN CAPITAL LETTER D
-0045; C; 0065; # LATIN CAPITAL LETTER E
-0046; C; 0066; # LATIN CAPITAL LETTER F
-0047; C; 0067; # LATIN CAPITAL LETTER G
-0048; C; 0068; # LATIN CAPITAL LETTER H
-0049; C; 0069; # LATIN CAPITAL LETTER I
-0049; T; 0131; # LATIN CAPITAL LETTER I
-004A; C; 006A; # LATIN CAPITAL LETTER J
-004B; C; 006B; # LATIN CAPITAL LETTER K
-004C; C; 006C; # LATIN CAPITAL LETTER L
-004D; C; 006D; # LATIN CAPITAL LETTER M
-004E; C; 006E; # LATIN CAPITAL LETTER N
-004F; C; 006F; # LATIN CAPITAL LETTER O
-0050; C; 0070; # LATIN CAPITAL LETTER P
-0051; C; 0071; # LATIN CAPITAL LETTER Q
-0052; C; 0072; # LATIN CAPITAL LETTER R
-0053; C; 0073; # LATIN CAPITAL LETTER S
-0054; C; 0074; # LATIN CAPITAL LETTER T
-0055; C; 0075; # LATIN CAPITAL LETTER U
-0056; C; 0076; # LATIN CAPITAL LETTER V
-0057; C; 0077; # LATIN CAPITAL LETTER W
-0058; C; 0078; # LATIN CAPITAL LETTER X
-0059; C; 0079; # LATIN CAPITAL LETTER Y
-005A; C; 007A; # LATIN CAPITAL LETTER Z
-00B5; C; 03BC; # MICRO SIGN
-00C0; C; 00E0; # LATIN CAPITAL LETTER A WITH GRAVE
-00C1; C; 00E1; # LATIN CAPITAL LETTER A WITH ACUTE
-00C2; C; 00E2; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
-00C3; C; 00E3; # LATIN CAPITAL LETTER A WITH TILDE
-00C4; C; 00E4; # LATIN CAPITAL LETTER A WITH DIAERESIS
-00C5; C; 00E5; # LATIN CAPITAL LETTER A WITH RING ABOVE
-00C6; C; 00E6; # LATIN CAPITAL LETTER AE
-00C7; C; 00E7; # LATIN CAPITAL LETTER C WITH CEDILLA
-00C8; C; 00E8; # LATIN CAPITAL LETTER E WITH GRAVE
-00C9; C; 00E9; # LATIN CAPITAL LETTER E WITH ACUTE
-00CA; C; 00EA; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
-00CB; C; 00EB; # LATIN CAPITAL LETTER E WITH DIAERESIS
-00CC; C; 00EC; # LATIN CAPITAL LETTER I WITH GRAVE
-00CD; C; 00ED; # LATIN CAPITAL LETTER I WITH ACUTE
-00CE; C; 00EE; # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
-00CF; C; 00EF; # LATIN CAPITAL LETTER I WITH DIAERESIS
-00D0; C; 00F0; # LATIN CAPITAL LETTER ETH
-00D1; C; 00F1; # LATIN CAPITAL LETTER N WITH TILDE
-00D2; C; 00F2; # LATIN CAPITAL LETTER O WITH GRAVE
-00D3; C; 00F3; # LATIN CAPITAL LETTER O WITH ACUTE
-00D4; C; 00F4; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
-00D5; C; 00F5; # LATIN CAPITAL LETTER O WITH TILDE
-00D6; C; 00F6; # LATIN CAPITAL LETTER O WITH DIAERESIS
-00D8; C; 00F8; # LATIN CAPITAL LETTER O WITH STROKE
-00D9; C; 00F9; # LATIN CAPITAL LETTER U WITH GRAVE
-00DA; C; 00FA; # LATIN CAPITAL LETTER U WITH ACUTE
-00DB; C; 00FB; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
-00DC; C; 00FC; # LATIN CAPITAL LETTER U WITH DIAERESIS
-00DD; C; 00FD; # LATIN CAPITAL LETTER Y WITH ACUTE
-00DE; C; 00FE; # LATIN CAPITAL LETTER THORN
-00DF; F; 0073 0073; # LATIN SMALL LETTER SHARP S
-0100; C; 0101; # LATIN CAPITAL LETTER A WITH MACRON
-0102; C; 0103; # LATIN CAPITAL LETTER A WITH BREVE
-0104; C; 0105; # LATIN CAPITAL LETTER A WITH OGONEK
-0106; C; 0107; # LATIN CAPITAL LETTER C WITH ACUTE
-0108; C; 0109; # LATIN CAPITAL LETTER C WITH CIRCUMFLEX
-010A; C; 010B; # LATIN CAPITAL LETTER C WITH DOT ABOVE
-010C; C; 010D; # LATIN CAPITAL LETTER C WITH CARON
-010E; C; 010F; # LATIN CAPITAL LETTER D WITH CARON
-0110; C; 0111; # LATIN CAPITAL LETTER D WITH STROKE
-0112; C; 0113; # LATIN CAPITAL LETTER E WITH MACRON
-0114; C; 0115; # LATIN CAPITAL LETTER E WITH BREVE
-0116; C; 0117; # LATIN CAPITAL LETTER E WITH DOT ABOVE
-0118; C; 0119; # LATIN CAPITAL LETTER E WITH OGONEK
-011A; C; 011B; # LATIN CAPITAL LETTER E WITH CARON
-011C; C; 011D; # LATIN CAPITAL LETTER G WITH CIRCUMFLEX
-011E; C; 011F; # LATIN CAPITAL LETTER G WITH BREVE
-0120; C; 0121; # LATIN CAPITAL LETTER G WITH DOT ABOVE
-0122; C; 0123; # LATIN CAPITAL LETTER G WITH CEDILLA
-0124; C; 0125; # LATIN CAPITAL LETTER H WITH CIRCUMFLEX
-0126; C; 0127; # LATIN CAPITAL LETTER H WITH STROKE
-0128; C; 0129; # LATIN CAPITAL LETTER I WITH TILDE
-012A; C; 012B; # LATIN CAPITAL LETTER I WITH MACRON
-012C; C; 012D; # LATIN CAPITAL LETTER I WITH BREVE
-012E; C; 012F; # LATIN CAPITAL LETTER I WITH OGONEK
-0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE
-0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE
-0132; C; 0133; # LATIN CAPITAL LIGATURE IJ
-0134; C; 0135; # LATIN CAPITAL LETTER J WITH CIRCUMFLEX
-0136; C; 0137; # LATIN CAPITAL LETTER K WITH CEDILLA
-0139; C; 013A; # LATIN CAPITAL LETTER L WITH ACUTE
-013B; C; 013C; # LATIN CAPITAL LETTER L WITH CEDILLA
-013D; C; 013E; # LATIN CAPITAL LETTER L WITH CARON
-013F; C; 0140; # LATIN CAPITAL LETTER L WITH MIDDLE DOT
-0141; C; 0142; # LATIN CAPITAL LETTER L WITH STROKE
-0143; C; 0144; # LATIN CAPITAL LETTER N WITH ACUTE
-0145; C; 0146; # LATIN CAPITAL LETTER N WITH CEDILLA
-0147; C; 0148; # LATIN CAPITAL LETTER N WITH CARON
-0149; F; 02BC 006E; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
-014A; C; 014B; # LATIN CAPITAL LETTER ENG
-014C; C; 014D; # LATIN CAPITAL LETTER O WITH MACRON
-014E; C; 014F; # LATIN CAPITAL LETTER O WITH BREVE
-0150; C; 0151; # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
-0152; C; 0153; # LATIN CAPITAL LIGATURE OE
-0154; C; 0155; # LATIN CAPITAL LETTER R WITH ACUTE
-0156; C; 0157; # LATIN CAPITAL LETTER R WITH CEDILLA
-0158; C; 0159; # LATIN CAPITAL LETTER R WITH CARON
-015A; C; 015B; # LATIN CAPITAL LETTER S WITH ACUTE
-015C; C; 015D; # LATIN CAPITAL LETTER S WITH CIRCUMFLEX
-015E; C; 015F; # LATIN CAPITAL LETTER S WITH CEDILLA
-0160; C; 0161; # LATIN CAPITAL LETTER S WITH CARON
-0162; C; 0163; # LATIN CAPITAL LETTER T WITH CEDILLA
-0164; C; 0165; # LATIN CAPITAL LETTER T WITH CARON
-0166; C; 0167; # LATIN CAPITAL LETTER T WITH STROKE
-0168; C; 0169; # LATIN CAPITAL LETTER U WITH TILDE
-016A; C; 016B; # LATIN CAPITAL LETTER U WITH MACRON
-016C; C; 016D; # LATIN CAPITAL LETTER U WITH BREVE
-016E; C; 016F; # LATIN CAPITAL LETTER U WITH RING ABOVE
-0170; C; 0171; # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
-0172; C; 0173; # LATIN CAPITAL LETTER U WITH OGONEK
-0174; C; 0175; # LATIN CAPITAL LETTER W WITH CIRCUMFLEX
-0176; C; 0177; # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
-0178; C; 00FF; # LATIN CAPITAL LETTER Y WITH DIAERESIS
-0179; C; 017A; # LATIN CAPITAL LETTER Z WITH ACUTE
-017B; C; 017C; # LATIN CAPITAL LETTER Z WITH DOT ABOVE
-017D; C; 017E; # LATIN CAPITAL LETTER Z WITH CARON
-017F; C; 0073; # LATIN SMALL LETTER LONG S
-0181; C; 0253; # LATIN CAPITAL LETTER B WITH HOOK
-0182; C; 0183; # LATIN CAPITAL LETTER B WITH TOPBAR
-0184; C; 0185; # LATIN CAPITAL LETTER TONE SIX
-0186; C; 0254; # LATIN CAPITAL LETTER OPEN O
-0187; C; 0188; # LATIN CAPITAL LETTER C WITH HOOK
-0189; C; 0256; # LATIN CAPITAL LETTER AFRICAN D
-018A; C; 0257; # LATIN CAPITAL LETTER D WITH HOOK
-018B; C; 018C; # LATIN CAPITAL LETTER D WITH TOPBAR
-018E; C; 01DD; # LATIN CAPITAL LETTER REVERSED E
-018F; C; 0259; # LATIN CAPITAL LETTER SCHWA
-0190; C; 025B; # LATIN CAPITAL LETTER OPEN E
-0191; C; 0192; # LATIN CAPITAL LETTER F WITH HOOK
-0193; C; 0260; # LATIN CAPITAL LETTER G WITH HOOK
-0194; C; 0263; # LATIN CAPITAL LETTER GAMMA
-0196; C; 0269; # LATIN CAPITAL LETTER IOTA
-0197; C; 0268; # LATIN CAPITAL LETTER I WITH STROKE
-0198; C; 0199; # LATIN CAPITAL LETTER K WITH HOOK
-019C; C; 026F; # LATIN CAPITAL LETTER TURNED M
-019D; C; 0272; # LATIN CAPITAL LETTER N WITH LEFT HOOK
-019F; C; 0275; # LATIN CAPITAL LETTER O WITH MIDDLE TILDE
-01A0; C; 01A1; # LATIN CAPITAL LETTER O WITH HORN
-01A2; C; 01A3; # LATIN CAPITAL LETTER OI
-01A4; C; 01A5; # LATIN CAPITAL LETTER P WITH HOOK
-01A6; C; 0280; # LATIN LETTER YR
-01A7; C; 01A8; # LATIN CAPITAL LETTER TONE TWO
-01A9; C; 0283; # LATIN CAPITAL LETTER ESH
-01AC; C; 01AD; # LATIN CAPITAL LETTER T WITH HOOK
-01AE; C; 0288; # LATIN CAPITAL LETTER T WITH RETROFLEX HOOK
-01AF; C; 01B0; # LATIN CAPITAL LETTER U WITH HORN
-01B1; C; 028A; # LATIN CAPITAL LETTER UPSILON
-01B2; C; 028B; # LATIN CAPITAL LETTER V WITH HOOK
-01B3; C; 01B4; # LATIN CAPITAL LETTER Y WITH HOOK
-01B5; C; 01B6; # LATIN CAPITAL LETTER Z WITH STROKE
-01B7; C; 0292; # LATIN CAPITAL LETTER EZH
-01B8; C; 01B9; # LATIN CAPITAL LETTER EZH REVERSED
-01BC; C; 01BD; # LATIN CAPITAL LETTER TONE FIVE
-01C4; C; 01C6; # LATIN CAPITAL LETTER DZ WITH CARON
-01C5; C; 01C6; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
-01C7; C; 01C9; # LATIN CAPITAL LETTER LJ
-01C8; C; 01C9; # LATIN CAPITAL LETTER L WITH SMALL LETTER J
-01CA; C; 01CC; # LATIN CAPITAL LETTER NJ
-01CB; C; 01CC; # LATIN CAPITAL LETTER N WITH SMALL LETTER J
-01CD; C; 01CE; # LATIN CAPITAL LETTER A WITH CARON
-01CF; C; 01D0; # LATIN CAPITAL LETTER I WITH CARON
-01D1; C; 01D2; # LATIN CAPITAL LETTER O WITH CARON
-01D3; C; 01D4; # LATIN CAPITAL LETTER U WITH CARON
-01D5; C; 01D6; # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
-01D7; C; 01D8; # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
-01D9; C; 01DA; # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
-01DB; C; 01DC; # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
-01DE; C; 01DF; # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
-01E0; C; 01E1; # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
-01E2; C; 01E3; # LATIN CAPITAL LETTER AE WITH MACRON
-01E4; C; 01E5; # LATIN CAPITAL LETTER G WITH STROKE
-01E6; C; 01E7; # LATIN CAPITAL LETTER G WITH CARON
-01E8; C; 01E9; # LATIN CAPITAL LETTER K WITH CARON
-01EA; C; 01EB; # LATIN CAPITAL LETTER O WITH OGONEK
-01EC; C; 01ED; # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
-01EE; C; 01EF; # LATIN CAPITAL LETTER EZH WITH CARON
-01F0; F; 006A 030C; # LATIN SMALL LETTER J WITH CARON
-01F1; C; 01F3; # LATIN CAPITAL LETTER DZ
-01F2; C; 01F3; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z
-01F4; C; 01F5; # LATIN CAPITAL LETTER G WITH ACUTE
-01F6; C; 0195; # LATIN CAPITAL LETTER HWAIR
-01F7; C; 01BF; # LATIN CAPITAL LETTER WYNN
-01F8; C; 01F9; # LATIN CAPITAL LETTER N WITH GRAVE
-01FA; C; 01FB; # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
-01FC; C; 01FD; # LATIN CAPITAL LETTER AE WITH ACUTE
-01FE; C; 01FF; # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
-0200; C; 0201; # LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
-0202; C; 0203; # LATIN CAPITAL LETTER A WITH INVERTED BREVE
-0204; C; 0205; # LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
-0206; C; 0207; # LATIN CAPITAL LETTER E WITH INVERTED BREVE
-0208; C; 0209; # LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
-020A; C; 020B; # LATIN CAPITAL LETTER I WITH INVERTED BREVE
-020C; C; 020D; # LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
-020E; C; 020F; # LATIN CAPITAL LETTER O WITH INVERTED BREVE
-0210; C; 0211; # LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
-0212; C; 0213; # LATIN CAPITAL LETTER R WITH INVERTED BREVE
-0214; C; 0215; # LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
-0216; C; 0217; # LATIN CAPITAL LETTER U WITH INVERTED BREVE
-0218; C; 0219; # LATIN CAPITAL LETTER S WITH COMMA BELOW
-021A; C; 021B; # LATIN CAPITAL LETTER T WITH COMMA BELOW
-021C; C; 021D; # LATIN CAPITAL LETTER YOGH
-021E; C; 021F; # LATIN CAPITAL LETTER H WITH CARON
-0220; C; 019E; # LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
-0222; C; 0223; # LATIN CAPITAL LETTER OU
-0224; C; 0225; # LATIN CAPITAL LETTER Z WITH HOOK
-0226; C; 0227; # LATIN CAPITAL LETTER A WITH DOT ABOVE
-0228; C; 0229; # LATIN CAPITAL LETTER E WITH CEDILLA
-022A; C; 022B; # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
-022C; C; 022D; # LATIN CAPITAL LETTER O WITH TILDE AND MACRON
-022E; C; 022F; # LATIN CAPITAL LETTER O WITH DOT ABOVE
-0230; C; 0231; # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
-0232; C; 0233; # LATIN CAPITAL LETTER Y WITH MACRON
-023A; C; 2C65; # LATIN CAPITAL LETTER A WITH STROKE
-023B; C; 023C; # LATIN CAPITAL LETTER C WITH STROKE
-023D; C; 019A; # LATIN CAPITAL LETTER L WITH BAR
-023E; C; 2C66; # LATIN CAPITAL LETTER T WITH DIAGONAL STROKE
-0241; C; 0242; # LATIN CAPITAL LETTER GLOTTAL STOP
-0243; C; 0180; # LATIN CAPITAL LETTER B WITH STROKE
-0244; C; 0289; # LATIN CAPITAL LETTER U BAR
-0245; C; 028C; # LATIN CAPITAL LETTER TURNED V
-0246; C; 0247; # LATIN CAPITAL LETTER E WITH STROKE
-0248; C; 0249; # LATIN CAPITAL LETTER J WITH STROKE
-024A; C; 024B; # LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL
-024C; C; 024D; # LATIN CAPITAL LETTER R WITH STROKE
-024E; C; 024F; # LATIN CAPITAL LETTER Y WITH STROKE
-0345; C; 03B9; # COMBINING GREEK YPOGEGRAMMENI
-0370; C; 0371; # GREEK CAPITAL LETTER HETA
-0372; C; 0373; # GREEK CAPITAL LETTER ARCHAIC SAMPI
-0376; C; 0377; # GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
-0386; C; 03AC; # GREEK CAPITAL LETTER ALPHA WITH TONOS
-0388; C; 03AD; # GREEK CAPITAL LETTER EPSILON WITH TONOS
-0389; C; 03AE; # GREEK CAPITAL LETTER ETA WITH TONOS
-038A; C; 03AF; # GREEK CAPITAL LETTER IOTA WITH TONOS
-038C; C; 03CC; # GREEK CAPITAL LETTER OMICRON WITH TONOS
-038E; C; 03CD; # GREEK CAPITAL LETTER UPSILON WITH TONOS
-038F; C; 03CE; # GREEK CAPITAL LETTER OMEGA WITH TONOS
-0390; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
-0391; C; 03B1; # GREEK CAPITAL LETTER ALPHA
-0392; C; 03B2; # GREEK CAPITAL LETTER BETA
-0393; C; 03B3; # GREEK CAPITAL LETTER GAMMA
-0394; C; 03B4; # GREEK CAPITAL LETTER DELTA
-0395; C; 03B5; # GREEK CAPITAL LETTER EPSILON
-0396; C; 03B6; # GREEK CAPITAL LETTER ZETA
-0397; C; 03B7; # GREEK CAPITAL LETTER ETA
-0398; C; 03B8; # GREEK CAPITAL LETTER THETA
-0399; C; 03B9; # GREEK CAPITAL LETTER IOTA
-039A; C; 03BA; # GREEK CAPITAL LETTER KAPPA
-039B; C; 03BB; # GREEK CAPITAL LETTER LAMDA
-039C; C; 03BC; # GREEK CAPITAL LETTER MU
-039D; C; 03BD; # GREEK CAPITAL LETTER NU
-039E; C; 03BE; # GREEK CAPITAL LETTER XI
-039F; C; 03BF; # GREEK CAPITAL LETTER OMICRON
-03A0; C; 03C0; # GREEK CAPITAL LETTER PI
-03A1; C; 03C1; # GREEK CAPITAL LETTER RHO
-03A3; C; 03C3; # GREEK CAPITAL LETTER SIGMA
-03A4; C; 03C4; # GREEK CAPITAL LETTER TAU
-03A5; C; 03C5; # GREEK CAPITAL LETTER UPSILON
-03A6; C; 03C6; # GREEK CAPITAL LETTER PHI
-03A7; C; 03C7; # GREEK CAPITAL LETTER CHI
-03A8; C; 03C8; # GREEK CAPITAL LETTER PSI
-03A9; C; 03C9; # GREEK CAPITAL LETTER OMEGA
-03AA; C; 03CA; # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
-03AB; C; 03CB; # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
-03B0; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
-03C2; C; 03C3; # GREEK SMALL LETTER FINAL SIGMA
-03CF; C; 03D7; # GREEK CAPITAL KAI SYMBOL
-03D0; C; 03B2; # GREEK BETA SYMBOL
-03D1; C; 03B8; # GREEK THETA SYMBOL
-03D5; C; 03C6; # GREEK PHI SYMBOL
-03D6; C; 03C0; # GREEK PI SYMBOL
-03D8; C; 03D9; # GREEK LETTER ARCHAIC KOPPA
-03DA; C; 03DB; # GREEK LETTER STIGMA
-03DC; C; 03DD; # GREEK LETTER DIGAMMA
-03DE; C; 03DF; # GREEK LETTER KOPPA
-03E0; C; 03E1; # GREEK LETTER SAMPI
-03E2; C; 03E3; # COPTIC CAPITAL LETTER SHEI
-03E4; C; 03E5; # COPTIC CAPITAL LETTER FEI
-03E6; C; 03E7; # COPTIC CAPITAL LETTER KHEI
-03E8; C; 03E9; # COPTIC CAPITAL LETTER HORI
-03EA; C; 03EB; # COPTIC CAPITAL LETTER GANGIA
-03EC; C; 03ED; # COPTIC CAPITAL LETTER SHIMA
-03EE; C; 03EF; # COPTIC CAPITAL LETTER DEI
-03F0; C; 03BA; # GREEK KAPPA SYMBOL
-03F1; C; 03C1; # GREEK RHO SYMBOL
-03F4; C; 03B8; # GREEK CAPITAL THETA SYMBOL
-03F5; C; 03B5; # GREEK LUNATE EPSILON SYMBOL
-03F7; C; 03F8; # GREEK CAPITAL LETTER SHO
-03F9; C; 03F2; # GREEK CAPITAL LUNATE SIGMA SYMBOL
-03FA; C; 03FB; # GREEK CAPITAL LETTER SAN
-03FD; C; 037B; # GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL
-03FE; C; 037C; # GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL
-03FF; C; 037D; # GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
-0400; C; 0450; # CYRILLIC CAPITAL LETTER IE WITH GRAVE
-0401; C; 0451; # CYRILLIC CAPITAL LETTER IO
-0402; C; 0452; # CYRILLIC CAPITAL LETTER DJE
-0403; C; 0453; # CYRILLIC CAPITAL LETTER GJE
-0404; C; 0454; # CYRILLIC CAPITAL LETTER UKRAINIAN IE
-0405; C; 0455; # CYRILLIC CAPITAL LETTER DZE
-0406; C; 0456; # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
-0407; C; 0457; # CYRILLIC CAPITAL LETTER YI
-0408; C; 0458; # CYRILLIC CAPITAL LETTER JE
-0409; C; 0459; # CYRILLIC CAPITAL LETTER LJE
-040A; C; 045A; # CYRILLIC CAPITAL LETTER NJE
-040B; C; 045B; # CYRILLIC CAPITAL LETTER TSHE
-040C; C; 045C; # CYRILLIC CAPITAL LETTER KJE
-040D; C; 045D; # CYRILLIC CAPITAL LETTER I WITH GRAVE
-040E; C; 045E; # CYRILLIC CAPITAL LETTER SHORT U
-040F; C; 045F; # CYRILLIC CAPITAL LETTER DZHE
-0410; C; 0430; # CYRILLIC CAPITAL LETTER A
-0411; C; 0431; # CYRILLIC CAPITAL LETTER BE
-0412; C; 0432; # CYRILLIC CAPITAL LETTER VE
-0413; C; 0433; # CYRILLIC CAPITAL LETTER GHE
-0414; C; 0434; # CYRILLIC CAPITAL LETTER DE
-0415; C; 0435; # CYRILLIC CAPITAL LETTER IE
-0416; C; 0436; # CYRILLIC CAPITAL LETTER ZHE
-0417; C; 0437; # CYRILLIC CAPITAL LETTER ZE
-0418; C; 0438; # CYRILLIC CAPITAL LETTER I
-0419; C; 0439; # CYRILLIC CAPITAL LETTER SHORT I
-041A; C; 043A; # CYRILLIC CAPITAL LETTER KA
-041B; C; 043B; # CYRILLIC CAPITAL LETTER EL
-041C; C; 043C; # CYRILLIC CAPITAL LETTER EM
-041D; C; 043D; # CYRILLIC CAPITAL LETTER EN
-041E; C; 043E; # CYRILLIC CAPITAL LETTER O
-041F; C; 043F; # CYRILLIC CAPITAL LETTER PE
-0420; C; 0440; # CYRILLIC CAPITAL LETTER ER
-0421; C; 0441; # CYRILLIC CAPITAL LETTER ES
-0422; C; 0442; # CYRILLIC CAPITAL LETTER TE
-0423; C; 0443; # CYRILLIC CAPITAL LETTER U
-0424; C; 0444; # CYRILLIC CAPITAL LETTER EF
-0425; C; 0445; # CYRILLIC CAPITAL LETTER HA
-0426; C; 0446; # CYRILLIC CAPITAL LETTER TSE
-0427; C; 0447; # CYRILLIC CAPITAL LETTER CHE
-0428; C; 0448; # CYRILLIC CAPITAL LETTER SHA
-0429; C; 0449; # CYRILLIC CAPITAL LETTER SHCHA
-042A; C; 044A; # CYRILLIC CAPITAL LETTER HARD SIGN
-042B; C; 044B; # CYRILLIC CAPITAL LETTER YERU
-042C; C; 044C; # CYRILLIC CAPITAL LETTER SOFT SIGN
-042D; C; 044D; # CYRILLIC CAPITAL LETTER E
-042E; C; 044E; # CYRILLIC CAPITAL LETTER YU
-042F; C; 044F; # CYRILLIC CAPITAL LETTER YA
-0460; C; 0461; # CYRILLIC CAPITAL LETTER OMEGA
-0462; C; 0463; # CYRILLIC CAPITAL LETTER YAT
-0464; C; 0465; # CYRILLIC CAPITAL LETTER IOTIFIED E
-0466; C; 0467; # CYRILLIC CAPITAL LETTER LITTLE YUS
-0468; C; 0469; # CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
-046A; C; 046B; # CYRILLIC CAPITAL LETTER BIG YUS
-046C; C; 046D; # CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
-046E; C; 046F; # CYRILLIC CAPITAL LETTER KSI
-0470; C; 0471; # CYRILLIC CAPITAL LETTER PSI
-0472; C; 0473; # CYRILLIC CAPITAL LETTER FITA
-0474; C; 0475; # CYRILLIC CAPITAL LETTER IZHITSA
-0476; C; 0477; # CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
-0478; C; 0479; # CYRILLIC CAPITAL LETTER UK
-047A; C; 047B; # CYRILLIC CAPITAL LETTER ROUND OMEGA
-047C; C; 047D; # CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
-047E; C; 047F; # CYRILLIC CAPITAL LETTER OT
-0480; C; 0481; # CYRILLIC CAPITAL LETTER KOPPA
-048A; C; 048B; # CYRILLIC CAPITAL LETTER SHORT I WITH TAIL
-048C; C; 048D; # CYRILLIC CAPITAL LETTER SEMISOFT SIGN
-048E; C; 048F; # CYRILLIC CAPITAL LETTER ER WITH TICK
-0490; C; 0491; # CYRILLIC CAPITAL LETTER GHE WITH UPTURN
-0492; C; 0493; # CYRILLIC CAPITAL LETTER GHE WITH STROKE
-0494; C; 0495; # CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
-0496; C; 0497; # CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
-0498; C; 0499; # CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
-049A; C; 049B; # CYRILLIC CAPITAL LETTER KA WITH DESCENDER
-049C; C; 049D; # CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
-049E; C; 049F; # CYRILLIC CAPITAL LETTER KA WITH STROKE
-04A0; C; 04A1; # CYRILLIC CAPITAL LETTER BASHKIR KA
-04A2; C; 04A3; # CYRILLIC CAPITAL LETTER EN WITH DESCENDER
-04A4; C; 04A5; # CYRILLIC CAPITAL LIGATURE EN GHE
-04A6; C; 04A7; # CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
-04A8; C; 04A9; # CYRILLIC CAPITAL LETTER ABKHASIAN HA
-04AA; C; 04AB; # CYRILLIC CAPITAL LETTER ES WITH DESCENDER
-04AC; C; 04AD; # CYRILLIC CAPITAL LETTER TE WITH DESCENDER
-04AE; C; 04AF; # CYRILLIC CAPITAL LETTER STRAIGHT U
-04B0; C; 04B1; # CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
-04B2; C; 04B3; # CYRILLIC CAPITAL LETTER HA WITH DESCENDER
-04B4; C; 04B5; # CYRILLIC CAPITAL LIGATURE TE TSE
-04B6; C; 04B7; # CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
-04B8; C; 04B9; # CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
-04BA; C; 04BB; # CYRILLIC CAPITAL LETTER SHHA
-04BC; C; 04BD; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE
-04BE; C; 04BF; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
-04C0; C; 04CF; # CYRILLIC LETTER PALOCHKA
-04C1; C; 04C2; # CYRILLIC CAPITAL LETTER ZHE WITH BREVE
-04C3; C; 04C4; # CYRILLIC CAPITAL LETTER KA WITH HOOK
-04C5; C; 04C6; # CYRILLIC CAPITAL LETTER EL WITH TAIL
-04C7; C; 04C8; # CYRILLIC CAPITAL LETTER EN WITH HOOK
-04C9; C; 04CA; # CYRILLIC CAPITAL LETTER EN WITH TAIL
-04CB; C; 04CC; # CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
-04CD; C; 04CE; # CYRILLIC CAPITAL LETTER EM WITH TAIL
-04D0; C; 04D1; # CYRILLIC CAPITAL LETTER A WITH BREVE
-04D2; C; 04D3; # CYRILLIC CAPITAL LETTER A WITH DIAERESIS
-04D4; C; 04D5; # CYRILLIC CAPITAL LIGATURE A IE
-04D6; C; 04D7; # CYRILLIC CAPITAL LETTER IE WITH BREVE
-04D8; C; 04D9; # CYRILLIC CAPITAL LETTER SCHWA
-04DA; C; 04DB; # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
-04DC; C; 04DD; # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
-04DE; C; 04DF; # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
-04E0; C; 04E1; # CYRILLIC CAPITAL LETTER ABKHASIAN DZE
-04E2; C; 04E3; # CYRILLIC CAPITAL LETTER I WITH MACRON
-04E4; C; 04E5; # CYRILLIC CAPITAL LETTER I WITH DIAERESIS
-04E6; C; 04E7; # CYRILLIC CAPITAL LETTER O WITH DIAERESIS
-04E8; C; 04E9; # CYRILLIC CAPITAL LETTER BARRED O
-04EA; C; 04EB; # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
-04EC; C; 04ED; # CYRILLIC CAPITAL LETTER E WITH DIAERESIS
-04EE; C; 04EF; # CYRILLIC CAPITAL LETTER U WITH MACRON
-04F0; C; 04F1; # CYRILLIC CAPITAL LETTER U WITH DIAERESIS
-04F2; C; 04F3; # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
-04F4; C; 04F5; # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
-04F6; C; 04F7; # CYRILLIC CAPITAL LETTER GHE WITH DESCENDER
-04F8; C; 04F9; # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
-04FA; C; 04FB; # CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK
-04FC; C; 04FD; # CYRILLIC CAPITAL LETTER HA WITH HOOK
-04FE; C; 04FF; # CYRILLIC CAPITAL LETTER HA WITH STROKE
-0500; C; 0501; # CYRILLIC CAPITAL LETTER KOMI DE
-0502; C; 0503; # CYRILLIC CAPITAL LETTER KOMI DJE
-0504; C; 0505; # CYRILLIC CAPITAL LETTER KOMI ZJE
-0506; C; 0507; # CYRILLIC CAPITAL LETTER KOMI DZJE
-0508; C; 0509; # CYRILLIC CAPITAL LETTER KOMI LJE
-050A; C; 050B; # CYRILLIC CAPITAL LETTER KOMI NJE
-050C; C; 050D; # CYRILLIC CAPITAL LETTER KOMI SJE
-050E; C; 050F; # CYRILLIC CAPITAL LETTER KOMI TJE
-0510; C; 0511; # CYRILLIC CAPITAL LETTER REVERSED ZE
-0512; C; 0513; # CYRILLIC CAPITAL LETTER EL WITH HOOK
-0514; C; 0515; # CYRILLIC CAPITAL LETTER LHA
-0516; C; 0517; # CYRILLIC CAPITAL LETTER RHA
-0518; C; 0519; # CYRILLIC CAPITAL LETTER YAE
-051A; C; 051B; # CYRILLIC CAPITAL LETTER QA
-051C; C; 051D; # CYRILLIC CAPITAL LETTER WE
-051E; C; 051F; # CYRILLIC CAPITAL LETTER ALEUT KA
-0520; C; 0521; # CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
-0522; C; 0523; # CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
-0524; C; 0525; # CYRILLIC CAPITAL LETTER PE WITH DESCENDER
-0526; C; 0527; # CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER
-0531; C; 0561; # ARMENIAN CAPITAL LETTER AYB
-0532; C; 0562; # ARMENIAN CAPITAL LETTER BEN
-0533; C; 0563; # ARMENIAN CAPITAL LETTER GIM
-0534; C; 0564; # ARMENIAN CAPITAL LETTER DA
-0535; C; 0565; # ARMENIAN CAPITAL LETTER ECH
-0536; C; 0566; # ARMENIAN CAPITAL LETTER ZA
-0537; C; 0567; # ARMENIAN CAPITAL LETTER EH
-0538; C; 0568; # ARMENIAN CAPITAL LETTER ET
-0539; C; 0569; # ARMENIAN CAPITAL LETTER TO
-053A; C; 056A; # ARMENIAN CAPITAL LETTER ZHE
-053B; C; 056B; # ARMENIAN CAPITAL LETTER INI
-053C; C; 056C; # ARMENIAN CAPITAL LETTER LIWN
-053D; C; 056D; # ARMENIAN CAPITAL LETTER XEH
-053E; C; 056E; # ARMENIAN CAPITAL LETTER CA
-053F; C; 056F; # ARMENIAN CAPITAL LETTER KEN
-0540; C; 0570; # ARMENIAN CAPITAL LETTER HO
-0541; C; 0571; # ARMENIAN CAPITAL LETTER JA
-0542; C; 0572; # ARMENIAN CAPITAL LETTER GHAD
-0543; C; 0573; # ARMENIAN CAPITAL LETTER CHEH
-0544; C; 0574; # ARMENIAN CAPITAL LETTER MEN
-0545; C; 0575; # ARMENIAN CAPITAL LETTER YI
-0546; C; 0576; # ARMENIAN CAPITAL LETTER NOW
-0547; C; 0577; # ARMENIAN CAPITAL LETTER SHA
-0548; C; 0578; # ARMENIAN CAPITAL LETTER VO
-0549; C; 0579; # ARMENIAN CAPITAL LETTER CHA
-054A; C; 057A; # ARMENIAN CAPITAL LETTER PEH
-054B; C; 057B; # ARMENIAN CAPITAL LETTER JHEH
-054C; C; 057C; # ARMENIAN CAPITAL LETTER RA
-054D; C; 057D; # ARMENIAN CAPITAL LETTER SEH
-054E; C; 057E; # ARMENIAN CAPITAL LETTER VEW
-054F; C; 057F; # ARMENIAN CAPITAL LETTER TIWN
-0550; C; 0580; # ARMENIAN CAPITAL LETTER REH
-0551; C; 0581; # ARMENIAN CAPITAL LETTER CO
-0552; C; 0582; # ARMENIAN CAPITAL LETTER YIWN
-0553; C; 0583; # ARMENIAN CAPITAL LETTER PIWR
-0554; C; 0584; # ARMENIAN CAPITAL LETTER KEH
-0555; C; 0585; # ARMENIAN CAPITAL LETTER OH
-0556; C; 0586; # ARMENIAN CAPITAL LETTER FEH
-0587; F; 0565 0582; # ARMENIAN SMALL LIGATURE ECH YIWN
-10A0; C; 2D00; # GEORGIAN CAPITAL LETTER AN
-10A1; C; 2D01; # GEORGIAN CAPITAL LETTER BAN
-10A2; C; 2D02; # GEORGIAN CAPITAL LETTER GAN
-10A3; C; 2D03; # GEORGIAN CAPITAL LETTER DON
-10A4; C; 2D04; # GEORGIAN CAPITAL LETTER EN
-10A5; C; 2D05; # GEORGIAN CAPITAL LETTER VIN
-10A6; C; 2D06; # GEORGIAN CAPITAL LETTER ZEN
-10A7; C; 2D07; # GEORGIAN CAPITAL LETTER TAN
-10A8; C; 2D08; # GEORGIAN CAPITAL LETTER IN
-10A9; C; 2D09; # GEORGIAN CAPITAL LETTER KAN
-10AA; C; 2D0A; # GEORGIAN CAPITAL LETTER LAS
-10AB; C; 2D0B; # GEORGIAN CAPITAL LETTER MAN
-10AC; C; 2D0C; # GEORGIAN CAPITAL LETTER NAR
-10AD; C; 2D0D; # GEORGIAN CAPITAL LETTER ON
-10AE; C; 2D0E; # GEORGIAN CAPITAL LETTER PAR
-10AF; C; 2D0F; # GEORGIAN CAPITAL LETTER ZHAR
-10B0; C; 2D10; # GEORGIAN CAPITAL LETTER RAE
-10B1; C; 2D11; # GEORGIAN CAPITAL LETTER SAN
-10B2; C; 2D12; # GEORGIAN CAPITAL LETTER TAR
-10B3; C; 2D13; # GEORGIAN CAPITAL LETTER UN
-10B4; C; 2D14; # GEORGIAN CAPITAL LETTER PHAR
-10B5; C; 2D15; # GEORGIAN CAPITAL LETTER KHAR
-10B6; C; 2D16; # GEORGIAN CAPITAL LETTER GHAN
-10B7; C; 2D17; # GEORGIAN CAPITAL LETTER QAR
-10B8; C; 2D18; # GEORGIAN CAPITAL LETTER SHIN
-10B9; C; 2D19; # GEORGIAN CAPITAL LETTER CHIN
-10BA; C; 2D1A; # GEORGIAN CAPITAL LETTER CAN
-10BB; C; 2D1B; # GEORGIAN CAPITAL LETTER JIL
-10BC; C; 2D1C; # GEORGIAN CAPITAL LETTER CIL
-10BD; C; 2D1D; # GEORGIAN CAPITAL LETTER CHAR
-10BE; C; 2D1E; # GEORGIAN CAPITAL LETTER XAN
-10BF; C; 2D1F; # GEORGIAN CAPITAL LETTER JHAN
-10C0; C; 2D20; # GEORGIAN CAPITAL LETTER HAE
-10C1; C; 2D21; # GEORGIAN CAPITAL LETTER HE
-10C2; C; 2D22; # GEORGIAN CAPITAL LETTER HIE
-10C3; C; 2D23; # GEORGIAN CAPITAL LETTER WE
-10C4; C; 2D24; # GEORGIAN CAPITAL LETTER HAR
-10C5; C; 2D25; # GEORGIAN CAPITAL LETTER HOE
-10C7; C; 2D27; # GEORGIAN CAPITAL LETTER YN
-10CD; C; 2D2D; # GEORGIAN CAPITAL LETTER AEN
-1E00; C; 1E01; # LATIN CAPITAL LETTER A WITH RING BELOW
-1E02; C; 1E03; # LATIN CAPITAL LETTER B WITH DOT ABOVE
-1E04; C; 1E05; # LATIN CAPITAL LETTER B WITH DOT BELOW
-1E06; C; 1E07; # LATIN CAPITAL LETTER B WITH LINE BELOW
-1E08; C; 1E09; # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE
-1E0A; C; 1E0B; # LATIN CAPITAL LETTER D WITH DOT ABOVE
-1E0C; C; 1E0D; # LATIN CAPITAL LETTER D WITH DOT BELOW
-1E0E; C; 1E0F; # LATIN CAPITAL LETTER D WITH LINE BELOW
-1E10; C; 1E11; # LATIN CAPITAL LETTER D WITH CEDILLA
-1E12; C; 1E13; # LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW
-1E14; C; 1E15; # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE
-1E16; C; 1E17; # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE
-1E18; C; 1E19; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW
-1E1A; C; 1E1B; # LATIN CAPITAL LETTER E WITH TILDE BELOW
-1E1C; C; 1E1D; # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE
-1E1E; C; 1E1F; # LATIN CAPITAL LETTER F WITH DOT ABOVE
-1E20; C; 1E21; # LATIN CAPITAL LETTER G WITH MACRON
-1E22; C; 1E23; # LATIN CAPITAL LETTER H WITH DOT ABOVE
-1E24; C; 1E25; # LATIN CAPITAL LETTER H WITH DOT BELOW
-1E26; C; 1E27; # LATIN CAPITAL LETTER H WITH DIAERESIS
-1E28; C; 1E29; # LATIN CAPITAL LETTER H WITH CEDILLA
-1E2A; C; 1E2B; # LATIN CAPITAL LETTER H WITH BREVE BELOW
-1E2C; C; 1E2D; # LATIN CAPITAL LETTER I WITH TILDE BELOW
-1E2E; C; 1E2F; # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE
-1E30; C; 1E31; # LATIN CAPITAL LETTER K WITH ACUTE
-1E32; C; 1E33; # LATIN CAPITAL LETTER K WITH DOT BELOW
-1E34; C; 1E35; # LATIN CAPITAL LETTER K WITH LINE BELOW
-1E36; C; 1E37; # LATIN CAPITAL LETTER L WITH DOT BELOW
-1E38; C; 1E39; # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON
-1E3A; C; 1E3B; # LATIN CAPITAL LETTER L WITH LINE BELOW
-1E3C; C; 1E3D; # LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW
-1E3E; C; 1E3F; # LATIN CAPITAL LETTER M WITH ACUTE
-1E40; C; 1E41; # LATIN CAPITAL LETTER M WITH DOT ABOVE
-1E42; C; 1E43; # LATIN CAPITAL LETTER M WITH DOT BELOW
-1E44; C; 1E45; # LATIN CAPITAL LETTER N WITH DOT ABOVE
-1E46; C; 1E47; # LATIN CAPITAL LETTER N WITH DOT BELOW
-1E48; C; 1E49; # LATIN CAPITAL LETTER N WITH LINE BELOW
-1E4A; C; 1E4B; # LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW
-1E4C; C; 1E4D; # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE
-1E4E; C; 1E4F; # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS
-1E50; C; 1E51; # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE
-1E52; C; 1E53; # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE
-1E54; C; 1E55; # LATIN CAPITAL LETTER P WITH ACUTE
-1E56; C; 1E57; # LATIN CAPITAL LETTER P WITH DOT ABOVE
-1E58; C; 1E59; # LATIN CAPITAL LETTER R WITH DOT ABOVE
-1E5A; C; 1E5B; # LATIN CAPITAL LETTER R WITH DOT BELOW
-1E5C; C; 1E5D; # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON
-1E5E; C; 1E5F; # LATIN CAPITAL LETTER R WITH LINE BELOW
-1E60; C; 1E61; # LATIN CAPITAL LETTER S WITH DOT ABOVE
-1E62; C; 1E63; # LATIN CAPITAL LETTER S WITH DOT BELOW
-1E64; C; 1E65; # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE
-1E66; C; 1E67; # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE
-1E68; C; 1E69; # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE
-1E6A; C; 1E6B; # LATIN CAPITAL LETTER T WITH DOT ABOVE
-1E6C; C; 1E6D; # LATIN CAPITAL LETTER T WITH DOT BELOW
-1E6E; C; 1E6F; # LATIN CAPITAL LETTER T WITH LINE BELOW
-1E70; C; 1E71; # LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW
-1E72; C; 1E73; # LATIN CAPITAL LETTER U WITH DIAERESIS BELOW
-1E74; C; 1E75; # LATIN CAPITAL LETTER U WITH TILDE BELOW
-1E76; C; 1E77; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW
-1E78; C; 1E79; # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE
-1E7A; C; 1E7B; # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS
-1E7C; C; 1E7D; # LATIN CAPITAL LETTER V WITH TILDE
-1E7E; C; 1E7F; # LATIN CAPITAL LETTER V WITH DOT BELOW
-1E80; C; 1E81; # LATIN CAPITAL LETTER W WITH GRAVE
-1E82; C; 1E83; # LATIN CAPITAL LETTER W WITH ACUTE
-1E84; C; 1E85; # LATIN CAPITAL LETTER W WITH DIAERESIS
-1E86; C; 1E87; # LATIN CAPITAL LETTER W WITH DOT ABOVE
-1E88; C; 1E89; # LATIN CAPITAL LETTER W WITH DOT BELOW
-1E8A; C; 1E8B; # LATIN CAPITAL LETTER X WITH DOT ABOVE
-1E8C; C; 1E8D; # LATIN CAPITAL LETTER X WITH DIAERESIS
-1E8E; C; 1E8F; # LATIN CAPITAL LETTER Y WITH DOT ABOVE
-1E90; C; 1E91; # LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
-1E92; C; 1E93; # LATIN CAPITAL LETTER Z WITH DOT BELOW
-1E94; C; 1E95; # LATIN CAPITAL LETTER Z WITH LINE BELOW
-1E96; F; 0068 0331; # LATIN SMALL LETTER H WITH LINE BELOW
-1E97; F; 0074 0308; # LATIN SMALL LETTER T WITH DIAERESIS
-1E98; F; 0077 030A; # LATIN SMALL LETTER W WITH RING ABOVE
-1E99; F; 0079 030A; # LATIN SMALL LETTER Y WITH RING ABOVE
-1E9A; F; 0061 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING
-1E9B; C; 1E61; # LATIN SMALL LETTER LONG S WITH DOT ABOVE
-1E9E; F; 0073 0073; # LATIN CAPITAL LETTER SHARP S
-1E9E; S; 00DF; # LATIN CAPITAL LETTER SHARP S
-1EA0; C; 1EA1; # LATIN CAPITAL LETTER A WITH DOT BELOW
-1EA2; C; 1EA3; # LATIN CAPITAL LETTER A WITH HOOK ABOVE
-1EA4; C; 1EA5; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
-1EA6; C; 1EA7; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE
-1EA8; C; 1EA9; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
-1EAA; C; 1EAB; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE
-1EAC; C; 1EAD; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW
-1EAE; C; 1EAF; # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
-1EB0; C; 1EB1; # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
-1EB2; C; 1EB3; # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE
-1EB4; C; 1EB5; # LATIN CAPITAL LETTER A WITH BREVE AND TILDE
-1EB6; C; 1EB7; # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW
-1EB8; C; 1EB9; # LATIN CAPITAL LETTER E WITH DOT BELOW
-1EBA; C; 1EBB; # LATIN CAPITAL LETTER E WITH HOOK ABOVE
-1EBC; C; 1EBD; # LATIN CAPITAL LETTER E WITH TILDE
-1EBE; C; 1EBF; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE
-1EC0; C; 1EC1; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE
-1EC2; C; 1EC3; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
-1EC4; C; 1EC5; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE
-1EC6; C; 1EC7; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW
-1EC8; C; 1EC9; # LATIN CAPITAL LETTER I WITH HOOK ABOVE
-1ECA; C; 1ECB; # LATIN CAPITAL LETTER I WITH DOT BELOW
-1ECC; C; 1ECD; # LATIN CAPITAL LETTER O WITH DOT BELOW
-1ECE; C; 1ECF; # LATIN CAPITAL LETTER O WITH HOOK ABOVE
-1ED0; C; 1ED1; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE
-1ED2; C; 1ED3; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE
-1ED4; C; 1ED5; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
-1ED6; C; 1ED7; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE
-1ED8; C; 1ED9; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW
-1EDA; C; 1EDB; # LATIN CAPITAL LETTER O WITH HORN AND ACUTE
-1EDC; C; 1EDD; # LATIN CAPITAL LETTER O WITH HORN AND GRAVE
-1EDE; C; 1EDF; # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE
-1EE0; C; 1EE1; # LATIN CAPITAL LETTER O WITH HORN AND TILDE
-1EE2; C; 1EE3; # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW
-1EE4; C; 1EE5; # LATIN CAPITAL LETTER U WITH DOT BELOW
-1EE6; C; 1EE7; # LATIN CAPITAL LETTER U WITH HOOK ABOVE
-1EE8; C; 1EE9; # LATIN CAPITAL LETTER U WITH HORN AND ACUTE
-1EEA; C; 1EEB; # LATIN CAPITAL LETTER U WITH HORN AND GRAVE
-1EEC; C; 1EED; # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE
-1EEE; C; 1EEF; # LATIN CAPITAL LETTER U WITH HORN AND TILDE
-1EF0; C; 1EF1; # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW
-1EF2; C; 1EF3; # LATIN CAPITAL LETTER Y WITH GRAVE
-1EF4; C; 1EF5; # LATIN CAPITAL LETTER Y WITH DOT BELOW
-1EF6; C; 1EF7; # LATIN CAPITAL LETTER Y WITH HOOK ABOVE
-1EF8; C; 1EF9; # LATIN CAPITAL LETTER Y WITH TILDE
-1EFA; C; 1EFB; # LATIN CAPITAL LETTER MIDDLE-WELSH LL
-1EFC; C; 1EFD; # LATIN CAPITAL LETTER MIDDLE-WELSH V
-1EFE; C; 1EFF; # LATIN CAPITAL LETTER Y WITH LOOP
-1F08; C; 1F00; # GREEK CAPITAL LETTER ALPHA WITH PSILI
-1F09; C; 1F01; # GREEK CAPITAL LETTER ALPHA WITH DASIA
-1F0A; C; 1F02; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA
-1F0B; C; 1F03; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA
-1F0C; C; 1F04; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA
-1F0D; C; 1F05; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA
-1F0E; C; 1F06; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI
-1F0F; C; 1F07; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI
-1F18; C; 1F10; # GREEK CAPITAL LETTER EPSILON WITH PSILI
-1F19; C; 1F11; # GREEK CAPITAL LETTER EPSILON WITH DASIA
-1F1A; C; 1F12; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA
-1F1B; C; 1F13; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA
-1F1C; C; 1F14; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA
-1F1D; C; 1F15; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
-1F28; C; 1F20; # GREEK CAPITAL LETTER ETA WITH PSILI
-1F29; C; 1F21; # GREEK CAPITAL LETTER ETA WITH DASIA
-1F2A; C; 1F22; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA
-1F2B; C; 1F23; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA
-1F2C; C; 1F24; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA
-1F2D; C; 1F25; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA
-1F2E; C; 1F26; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI
-1F2F; C; 1F27; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI
-1F38; C; 1F30; # GREEK CAPITAL LETTER IOTA WITH PSILI
-1F39; C; 1F31; # GREEK CAPITAL LETTER IOTA WITH DASIA
-1F3A; C; 1F32; # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA
-1F3B; C; 1F33; # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA
-1F3C; C; 1F34; # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA
-1F3D; C; 1F35; # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA
-1F3E; C; 1F36; # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI
-1F3F; C; 1F37; # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI
-1F48; C; 1F40; # GREEK CAPITAL LETTER OMICRON WITH PSILI
-1F49; C; 1F41; # GREEK CAPITAL LETTER OMICRON WITH DASIA
-1F4A; C; 1F42; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA
-1F4B; C; 1F43; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA
-1F4C; C; 1F44; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA
-1F4D; C; 1F45; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
-1F50; F; 03C5 0313; # GREEK SMALL LETTER UPSILON WITH PSILI
-1F52; F; 03C5 0313 0300; # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA
-1F54; F; 03C5 0313 0301; # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA
-1F56; F; 03C5 0313 0342; # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI
-1F59; C; 1F51; # GREEK CAPITAL LETTER UPSILON WITH DASIA
-1F5B; C; 1F53; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
-1F5D; C; 1F55; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
-1F5F; C; 1F57; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI
-1F68; C; 1F60; # GREEK CAPITAL LETTER OMEGA WITH PSILI
-1F69; C; 1F61; # GREEK CAPITAL LETTER OMEGA WITH DASIA
-1F6A; C; 1F62; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA
-1F6B; C; 1F63; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA
-1F6C; C; 1F64; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA
-1F6D; C; 1F65; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA
-1F6E; C; 1F66; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI
-1F6F; C; 1F67; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI
-1F80; F; 1F00 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI
-1F81; F; 1F01 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI
-1F82; F; 1F02 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI
-1F83; F; 1F03 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI
-1F84; F; 1F04 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI
-1F85; F; 1F05 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI
-1F86; F; 1F06 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
-1F87; F; 1F07 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
-1F88; F; 1F00 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
-1F88; S; 1F80; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
-1F89; F; 1F01 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
-1F89; S; 1F81; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
-1F8A; F; 1F02 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
-1F8A; S; 1F82; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
-1F8B; F; 1F03 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
-1F8B; S; 1F83; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
-1F8C; F; 1F04 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
-1F8C; S; 1F84; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
-1F8D; F; 1F05 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
-1F8D; S; 1F85; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
-1F8E; F; 1F06 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
-1F8E; S; 1F86; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
-1F8F; F; 1F07 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
-1F8F; S; 1F87; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
-1F90; F; 1F20 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI
-1F91; F; 1F21 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI
-1F92; F; 1F22 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI
-1F93; F; 1F23 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI
-1F94; F; 1F24 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI
-1F95; F; 1F25 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI
-1F96; F; 1F26 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
-1F97; F; 1F27 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
-1F98; F; 1F20 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
-1F98; S; 1F90; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
-1F99; F; 1F21 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
-1F99; S; 1F91; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
-1F9A; F; 1F22 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
-1F9A; S; 1F92; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
-1F9B; F; 1F23 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
-1F9B; S; 1F93; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
-1F9C; F; 1F24 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
-1F9C; S; 1F94; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
-1F9D; F; 1F25 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
-1F9D; S; 1F95; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
-1F9E; F; 1F26 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
-1F9E; S; 1F96; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
-1F9F; F; 1F27 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
-1F9F; S; 1F97; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
-1FA0; F; 1F60 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI
-1FA1; F; 1F61 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI
-1FA2; F; 1F62 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI
-1FA3; F; 1F63 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI
-1FA4; F; 1F64 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI
-1FA5; F; 1F65 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI
-1FA6; F; 1F66 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
-1FA7; F; 1F67 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
-1FA8; F; 1F60 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
-1FA8; S; 1FA0; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
-1FA9; F; 1F61 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
-1FA9; S; 1FA1; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
-1FAA; F; 1F62 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
-1FAA; S; 1FA2; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
-1FAB; F; 1F63 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
-1FAB; S; 1FA3; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
-1FAC; F; 1F64 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
-1FAC; S; 1FA4; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
-1FAD; F; 1F65 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
-1FAD; S; 1FA5; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
-1FAE; F; 1F66 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
-1FAE; S; 1FA6; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
-1FAF; F; 1F67 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
-1FAF; S; 1FA7; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
-1FB2; F; 1F70 03B9; # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI
-1FB3; F; 03B1 03B9; # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI
-1FB4; F; 03AC 03B9; # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
-1FB6; F; 03B1 0342; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI
-1FB7; F; 03B1 0342 03B9; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI
-1FB8; C; 1FB0; # GREEK CAPITAL LETTER ALPHA WITH VRACHY
-1FB9; C; 1FB1; # GREEK CAPITAL LETTER ALPHA WITH MACRON
-1FBA; C; 1F70; # GREEK CAPITAL LETTER ALPHA WITH VARIA
-1FBB; C; 1F71; # GREEK CAPITAL LETTER ALPHA WITH OXIA
-1FBC; F; 03B1 03B9; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
-1FBC; S; 1FB3; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
-1FBE; C; 03B9; # GREEK PROSGEGRAMMENI
-1FC2; F; 1F74 03B9; # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI
-1FC3; F; 03B7 03B9; # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI
-1FC4; F; 03AE 03B9; # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
-1FC6; F; 03B7 0342; # GREEK SMALL LETTER ETA WITH PERISPOMENI
-1FC7; F; 03B7 0342 03B9; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI
-1FC8; C; 1F72; # GREEK CAPITAL LETTER EPSILON WITH VARIA
-1FC9; C; 1F73; # GREEK CAPITAL LETTER EPSILON WITH OXIA
-1FCA; C; 1F74; # GREEK CAPITAL LETTER ETA WITH VARIA
-1FCB; C; 1F75; # GREEK CAPITAL LETTER ETA WITH OXIA
-1FCC; F; 03B7 03B9; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
-1FCC; S; 1FC3; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
-1FD2; F; 03B9 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
-1FD3; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
-1FD6; F; 03B9 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI
-1FD7; F; 03B9 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
-1FD8; C; 1FD0; # GREEK CAPITAL LETTER IOTA WITH VRACHY
-1FD9; C; 1FD1; # GREEK CAPITAL LETTER IOTA WITH MACRON
-1FDA; C; 1F76; # GREEK CAPITAL LETTER IOTA WITH VARIA
-1FDB; C; 1F77; # GREEK CAPITAL LETTER IOTA WITH OXIA
-1FE2; F; 03C5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
-1FE3; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
-1FE4; F; 03C1 0313; # GREEK SMALL LETTER RHO WITH PSILI
-1FE6; F; 03C5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI
-1FE7; F; 03C5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
-1FE8; C; 1FE0; # GREEK CAPITAL LETTER UPSILON WITH VRACHY
-1FE9; C; 1FE1; # GREEK CAPITAL LETTER UPSILON WITH MACRON
-1FEA; C; 1F7A; # GREEK CAPITAL LETTER UPSILON WITH VARIA
-1FEB; C; 1F7B; # GREEK CAPITAL LETTER UPSILON WITH OXIA
-1FEC; C; 1FE5; # GREEK CAPITAL LETTER RHO WITH DASIA
-1FF2; F; 1F7C 03B9; # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI
-1FF3; F; 03C9 03B9; # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI
-1FF4; F; 03CE 03B9; # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
-1FF6; F; 03C9 0342; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI
-1FF7; F; 03C9 0342 03B9; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI
-1FF8; C; 1F78; # GREEK CAPITAL LETTER OMICRON WITH VARIA
-1FF9; C; 1F79; # GREEK CAPITAL LETTER OMICRON WITH OXIA
-1FFA; C; 1F7C; # GREEK CAPITAL LETTER OMEGA WITH VARIA
-1FFB; C; 1F7D; # GREEK CAPITAL LETTER OMEGA WITH OXIA
-1FFC; F; 03C9 03B9; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
-1FFC; S; 1FF3; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
-2126; C; 03C9; # OHM SIGN
-212A; C; 006B; # KELVIN SIGN
-212B; C; 00E5; # ANGSTROM SIGN
-2132; C; 214E; # TURNED CAPITAL F
-2160; C; 2170; # ROMAN NUMERAL ONE
-2161; C; 2171; # ROMAN NUMERAL TWO
-2162; C; 2172; # ROMAN NUMERAL THREE
-2163; C; 2173; # ROMAN NUMERAL FOUR
-2164; C; 2174; # ROMAN NUMERAL FIVE
-2165; C; 2175; # ROMAN NUMERAL SIX
-2166; C; 2176; # ROMAN NUMERAL SEVEN
-2167; C; 2177; # ROMAN NUMERAL EIGHT
-2168; C; 2178; # ROMAN NUMERAL NINE
-2169; C; 2179; # ROMAN NUMERAL TEN
-216A; C; 217A; # ROMAN NUMERAL ELEVEN
-216B; C; 217B; # ROMAN NUMERAL TWELVE
-216C; C; 217C; # ROMAN NUMERAL FIFTY
-216D; C; 217D; # ROMAN NUMERAL ONE HUNDRED
-216E; C; 217E; # ROMAN NUMERAL FIVE HUNDRED
-216F; C; 217F; # ROMAN NUMERAL ONE THOUSAND
-2183; C; 2184; # ROMAN NUMERAL REVERSED ONE HUNDRED
-24B6; C; 24D0; # CIRCLED LATIN CAPITAL LETTER A
-24B7; C; 24D1; # CIRCLED LATIN CAPITAL LETTER B
-24B8; C; 24D2; # CIRCLED LATIN CAPITAL LETTER C
-24B9; C; 24D3; # CIRCLED LATIN CAPITAL LETTER D
-24BA; C; 24D4; # CIRCLED LATIN CAPITAL LETTER E
-24BB; C; 24D5; # CIRCLED LATIN CAPITAL LETTER F
-24BC; C; 24D6; # CIRCLED LATIN CAPITAL LETTER G
-24BD; C; 24D7; # CIRCLED LATIN CAPITAL LETTER H
-24BE; C; 24D8; # CIRCLED LATIN CAPITAL LETTER I
-24BF; C; 24D9; # CIRCLED LATIN CAPITAL LETTER J
-24C0; C; 24DA; # CIRCLED LATIN CAPITAL LETTER K
-24C1; C; 24DB; # CIRCLED LATIN CAPITAL LETTER L
-24C2; C; 24DC; # CIRCLED LATIN CAPITAL LETTER M
-24C3; C; 24DD; # CIRCLED LATIN CAPITAL LETTER N
-24C4; C; 24DE; # CIRCLED LATIN CAPITAL LETTER O
-24C5; C; 24DF; # CIRCLED LATIN CAPITAL LETTER P
-24C6; C; 24E0; # CIRCLED LATIN CAPITAL LETTER Q
-24C7; C; 24E1; # CIRCLED LATIN CAPITAL LETTER R
-24C8; C; 24E2; # CIRCLED LATIN CAPITAL LETTER S
-24C9; C; 24E3; # CIRCLED LATIN CAPITAL LETTER T
-24CA; C; 24E4; # CIRCLED LATIN CAPITAL LETTER U
-24CB; C; 24E5; # CIRCLED LATIN CAPITAL LETTER V
-24CC; C; 24E6; # CIRCLED LATIN CAPITAL LETTER W
-24CD; C; 24E7; # CIRCLED LATIN CAPITAL LETTER X
-24CE; C; 24E8; # CIRCLED LATIN CAPITAL LETTER Y
-24CF; C; 24E9; # CIRCLED LATIN CAPITAL LETTER Z
-2C00; C; 2C30; # GLAGOLITIC CAPITAL LETTER AZU
-2C01; C; 2C31; # GLAGOLITIC CAPITAL LETTER BUKY
-2C02; C; 2C32; # GLAGOLITIC CAPITAL LETTER VEDE
-2C03; C; 2C33; # GLAGOLITIC CAPITAL LETTER GLAGOLI
-2C04; C; 2C34; # GLAGOLITIC CAPITAL LETTER DOBRO
-2C05; C; 2C35; # GLAGOLITIC CAPITAL LETTER YESTU
-2C06; C; 2C36; # GLAGOLITIC CAPITAL LETTER ZHIVETE
-2C07; C; 2C37; # GLAGOLITIC CAPITAL LETTER DZELO
-2C08; C; 2C38; # GLAGOLITIC CAPITAL LETTER ZEMLJA
-2C09; C; 2C39; # GLAGOLITIC CAPITAL LETTER IZHE
-2C0A; C; 2C3A; # GLAGOLITIC CAPITAL LETTER INITIAL IZHE
-2C0B; C; 2C3B; # GLAGOLITIC CAPITAL LETTER I
-2C0C; C; 2C3C; # GLAGOLITIC CAPITAL LETTER DJERVI
-2C0D; C; 2C3D; # GLAGOLITIC CAPITAL LETTER KAKO
-2C0E; C; 2C3E; # GLAGOLITIC CAPITAL LETTER LJUDIJE
-2C0F; C; 2C3F; # GLAGOLITIC CAPITAL LETTER MYSLITE
-2C10; C; 2C40; # GLAGOLITIC CAPITAL LETTER NASHI
-2C11; C; 2C41; # GLAGOLITIC CAPITAL LETTER ONU
-2C12; C; 2C42; # GLAGOLITIC CAPITAL LETTER POKOJI
-2C13; C; 2C43; # GLAGOLITIC CAPITAL LETTER RITSI
-2C14; C; 2C44; # GLAGOLITIC CAPITAL LETTER SLOVO
-2C15; C; 2C45; # GLAGOLITIC CAPITAL LETTER TVRIDO
-2C16; C; 2C46; # GLAGOLITIC CAPITAL LETTER UKU
-2C17; C; 2C47; # GLAGOLITIC CAPITAL LETTER FRITU
-2C18; C; 2C48; # GLAGOLITIC CAPITAL LETTER HERU
-2C19; C; 2C49; # GLAGOLITIC CAPITAL LETTER OTU
-2C1A; C; 2C4A; # GLAGOLITIC CAPITAL LETTER PE
-2C1B; C; 2C4B; # GLAGOLITIC CAPITAL LETTER SHTA
-2C1C; C; 2C4C; # GLAGOLITIC CAPITAL LETTER TSI
-2C1D; C; 2C4D; # GLAGOLITIC CAPITAL LETTER CHRIVI
-2C1E; C; 2C4E; # GLAGOLITIC CAPITAL LETTER SHA
-2C1F; C; 2C4F; # GLAGOLITIC CAPITAL LETTER YERU
-2C20; C; 2C50; # GLAGOLITIC CAPITAL LETTER YERI
-2C21; C; 2C51; # GLAGOLITIC CAPITAL LETTER YATI
-2C22; C; 2C52; # GLAGOLITIC CAPITAL LETTER SPIDERY HA
-2C23; C; 2C53; # GLAGOLITIC CAPITAL LETTER YU
-2C24; C; 2C54; # GLAGOLITIC CAPITAL LETTER SMALL YUS
-2C25; C; 2C55; # GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL
-2C26; C; 2C56; # GLAGOLITIC CAPITAL LETTER YO
-2C27; C; 2C57; # GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS
-2C28; C; 2C58; # GLAGOLITIC CAPITAL LETTER BIG YUS
-2C29; C; 2C59; # GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS
-2C2A; C; 2C5A; # GLAGOLITIC CAPITAL LETTER FITA
-2C2B; C; 2C5B; # GLAGOLITIC CAPITAL LETTER IZHITSA
-2C2C; C; 2C5C; # GLAGOLITIC CAPITAL LETTER SHTAPIC
-2C2D; C; 2C5D; # GLAGOLITIC CAPITAL LETTER TROKUTASTI A
-2C2E; C; 2C5E; # GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
-2C60; C; 2C61; # LATIN CAPITAL LETTER L WITH DOUBLE BAR
-2C62; C; 026B; # LATIN CAPITAL LETTER L WITH MIDDLE TILDE
-2C63; C; 1D7D; # LATIN CAPITAL LETTER P WITH STROKE
-2C64; C; 027D; # LATIN CAPITAL LETTER R WITH TAIL
-2C67; C; 2C68; # LATIN CAPITAL LETTER H WITH DESCENDER
-2C69; C; 2C6A; # LATIN CAPITAL LETTER K WITH DESCENDER
-2C6B; C; 2C6C; # LATIN CAPITAL LETTER Z WITH DESCENDER
-2C6D; C; 0251; # LATIN CAPITAL LETTER ALPHA
-2C6E; C; 0271; # LATIN CAPITAL LETTER M WITH HOOK
-2C6F; C; 0250; # LATIN CAPITAL LETTER TURNED A
-2C70; C; 0252; # LATIN CAPITAL LETTER TURNED ALPHA
-2C72; C; 2C73; # LATIN CAPITAL LETTER W WITH HOOK
-2C75; C; 2C76; # LATIN CAPITAL LETTER HALF H
-2C7E; C; 023F; # LATIN CAPITAL LETTER S WITH SWASH TAIL
-2C7F; C; 0240; # LATIN CAPITAL LETTER Z WITH SWASH TAIL
-2C80; C; 2C81; # COPTIC CAPITAL LETTER ALFA
-2C82; C; 2C83; # COPTIC CAPITAL LETTER VIDA
-2C84; C; 2C85; # COPTIC CAPITAL LETTER GAMMA
-2C86; C; 2C87; # COPTIC CAPITAL LETTER DALDA
-2C88; C; 2C89; # COPTIC CAPITAL LETTER EIE
-2C8A; C; 2C8B; # COPTIC CAPITAL LETTER SOU
-2C8C; C; 2C8D; # COPTIC CAPITAL LETTER ZATA
-2C8E; C; 2C8F; # COPTIC CAPITAL LETTER HATE
-2C90; C; 2C91; # COPTIC CAPITAL LETTER THETHE
-2C92; C; 2C93; # COPTIC CAPITAL LETTER IAUDA
-2C94; C; 2C95; # COPTIC CAPITAL LETTER KAPA
-2C96; C; 2C97; # COPTIC CAPITAL LETTER LAULA
-2C98; C; 2C99; # COPTIC CAPITAL LETTER MI
-2C9A; C; 2C9B; # COPTIC CAPITAL LETTER NI
-2C9C; C; 2C9D; # COPTIC CAPITAL LETTER KSI
-2C9E; C; 2C9F; # COPTIC CAPITAL LETTER O
-2CA0; C; 2CA1; # COPTIC CAPITAL LETTER PI
-2CA2; C; 2CA3; # COPTIC CAPITAL LETTER RO
-2CA4; C; 2CA5; # COPTIC CAPITAL LETTER SIMA
-2CA6; C; 2CA7; # COPTIC CAPITAL LETTER TAU
-2CA8; C; 2CA9; # COPTIC CAPITAL LETTER UA
-2CAA; C; 2CAB; # COPTIC CAPITAL LETTER FI
-2CAC; C; 2CAD; # COPTIC CAPITAL LETTER KHI
-2CAE; C; 2CAF; # COPTIC CAPITAL LETTER PSI
-2CB0; C; 2CB1; # COPTIC CAPITAL LETTER OOU
-2CB2; C; 2CB3; # COPTIC CAPITAL LETTER DIALECT-P ALEF
-2CB4; C; 2CB5; # COPTIC CAPITAL LETTER OLD COPTIC AIN
-2CB6; C; 2CB7; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE
-2CB8; C; 2CB9; # COPTIC CAPITAL LETTER DIALECT-P KAPA
-2CBA; C; 2CBB; # COPTIC CAPITAL LETTER DIALECT-P NI
-2CBC; C; 2CBD; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI
-2CBE; C; 2CBF; # COPTIC CAPITAL LETTER OLD COPTIC OOU
-2CC0; C; 2CC1; # COPTIC CAPITAL LETTER SAMPI
-2CC2; C; 2CC3; # COPTIC CAPITAL LETTER CROSSED SHEI
-2CC4; C; 2CC5; # COPTIC CAPITAL LETTER OLD COPTIC SHEI
-2CC6; C; 2CC7; # COPTIC CAPITAL LETTER OLD COPTIC ESH
-2CC8; C; 2CC9; # COPTIC CAPITAL LETTER AKHMIMIC KHEI
-2CCA; C; 2CCB; # COPTIC CAPITAL LETTER DIALECT-P HORI
-2CCC; C; 2CCD; # COPTIC CAPITAL LETTER OLD COPTIC HORI
-2CCE; C; 2CCF; # COPTIC CAPITAL LETTER OLD COPTIC HA
-2CD0; C; 2CD1; # COPTIC CAPITAL LETTER L-SHAPED HA
-2CD2; C; 2CD3; # COPTIC CAPITAL LETTER OLD COPTIC HEI
-2CD4; C; 2CD5; # COPTIC CAPITAL LETTER OLD COPTIC HAT
-2CD6; C; 2CD7; # COPTIC CAPITAL LETTER OLD COPTIC GANGIA
-2CD8; C; 2CD9; # COPTIC CAPITAL LETTER OLD COPTIC DJA
-2CDA; C; 2CDB; # COPTIC CAPITAL LETTER OLD COPTIC SHIMA
-2CDC; C; 2CDD; # COPTIC CAPITAL LETTER OLD NUBIAN SHIMA
-2CDE; C; 2CDF; # COPTIC CAPITAL LETTER OLD NUBIAN NGI
-2CE0; C; 2CE1; # COPTIC CAPITAL LETTER OLD NUBIAN NYI
-2CE2; C; 2CE3; # COPTIC CAPITAL LETTER OLD NUBIAN WAU
-2CEB; C; 2CEC; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI
-2CED; C; 2CEE; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA
-2CF2; C; 2CF3; # COPTIC CAPITAL LETTER BOHAIRIC KHEI
-A640; C; A641; # CYRILLIC CAPITAL LETTER ZEMLYA
-A642; C; A643; # CYRILLIC CAPITAL LETTER DZELO
-A644; C; A645; # CYRILLIC CAPITAL LETTER REVERSED DZE
-A646; C; A647; # CYRILLIC CAPITAL LETTER IOTA
-A648; C; A649; # CYRILLIC CAPITAL LETTER DJERV
-A64A; C; A64B; # CYRILLIC CAPITAL LETTER MONOGRAPH UK
-A64C; C; A64D; # CYRILLIC CAPITAL LETTER BROAD OMEGA
-A64E; C; A64F; # CYRILLIC CAPITAL LETTER NEUTRAL YER
-A650; C; A651; # CYRILLIC CAPITAL LETTER YERU WITH BACK YER
-A652; C; A653; # CYRILLIC CAPITAL LETTER IOTIFIED YAT
-A654; C; A655; # CYRILLIC CAPITAL LETTER REVERSED YU
-A656; C; A657; # CYRILLIC CAPITAL LETTER IOTIFIED A
-A658; C; A659; # CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS
-A65A; C; A65B; # CYRILLIC CAPITAL LETTER BLENDED YUS
-A65C; C; A65D; # CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS
-A65E; C; A65F; # CYRILLIC CAPITAL LETTER YN
-A660; C; A661; # CYRILLIC CAPITAL LETTER REVERSED TSE
-A662; C; A663; # CYRILLIC CAPITAL LETTER SOFT DE
-A664; C; A665; # CYRILLIC CAPITAL LETTER SOFT EL
-A666; C; A667; # CYRILLIC CAPITAL LETTER SOFT EM
-A668; C; A669; # CYRILLIC CAPITAL LETTER MONOCULAR O
-A66A; C; A66B; # CYRILLIC CAPITAL LETTER BINOCULAR O
-A66C; C; A66D; # CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O
-A680; C; A681; # CYRILLIC CAPITAL LETTER DWE
-A682; C; A683; # CYRILLIC CAPITAL LETTER DZWE
-A684; C; A685; # CYRILLIC CAPITAL LETTER ZHWE
-A686; C; A687; # CYRILLIC CAPITAL LETTER CCHE
-A688; C; A689; # CYRILLIC CAPITAL LETTER DZZE
-A68A; C; A68B; # CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK
-A68C; C; A68D; # CYRILLIC CAPITAL LETTER TWE
-A68E; C; A68F; # CYRILLIC CAPITAL LETTER TSWE
-A690; C; A691; # CYRILLIC CAPITAL LETTER TSSE
-A692; C; A693; # CYRILLIC CAPITAL LETTER TCHE
-A694; C; A695; # CYRILLIC CAPITAL LETTER HWE
-A696; C; A697; # CYRILLIC CAPITAL LETTER SHWE
-A722; C; A723; # LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF
-A724; C; A725; # LATIN CAPITAL LETTER EGYPTOLOGICAL AIN
-A726; C; A727; # LATIN CAPITAL LETTER HENG
-A728; C; A729; # LATIN CAPITAL LETTER TZ
-A72A; C; A72B; # LATIN CAPITAL LETTER TRESILLO
-A72C; C; A72D; # LATIN CAPITAL LETTER CUATRILLO
-A72E; C; A72F; # LATIN CAPITAL LETTER CUATRILLO WITH COMMA
-A732; C; A733; # LATIN CAPITAL LETTER AA
-A734; C; A735; # LATIN CAPITAL LETTER AO
-A736; C; A737; # LATIN CAPITAL LETTER AU
-A738; C; A739; # LATIN CAPITAL LETTER AV
-A73A; C; A73B; # LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR
-A73C; C; A73D; # LATIN CAPITAL LETTER AY
-A73E; C; A73F; # LATIN CAPITAL LETTER REVERSED C WITH DOT
-A740; C; A741; # LATIN CAPITAL LETTER K WITH STROKE
-A742; C; A743; # LATIN CAPITAL LETTER K WITH DIAGONAL STROKE
-A744; C; A745; # LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE
-A746; C; A747; # LATIN CAPITAL LETTER BROKEN L
-A748; C; A749; # LATIN CAPITAL LETTER L WITH HIGH STROKE
-A74A; C; A74B; # LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY
-A74C; C; A74D; # LATIN CAPITAL LETTER O WITH LOOP
-A74E; C; A74F; # LATIN CAPITAL LETTER OO
-A750; C; A751; # LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER
-A752; C; A753; # LATIN CAPITAL LETTER P WITH FLOURISH
-A754; C; A755; # LATIN CAPITAL LETTER P WITH SQUIRREL TAIL
-A756; C; A757; # LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER
-A758; C; A759; # LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE
-A75A; C; A75B; # LATIN CAPITAL LETTER R ROTUNDA
-A75C; C; A75D; # LATIN CAPITAL LETTER RUM ROTUNDA
-A75E; C; A75F; # LATIN CAPITAL LETTER V WITH DIAGONAL STROKE
-A760; C; A761; # LATIN CAPITAL LETTER VY
-A762; C; A763; # LATIN CAPITAL LETTER VISIGOTHIC Z
-A764; C; A765; # LATIN CAPITAL LETTER THORN WITH STROKE
-A766; C; A767; # LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER
-A768; C; A769; # LATIN CAPITAL LETTER VEND
-A76A; C; A76B; # LATIN CAPITAL LETTER ET
-A76C; C; A76D; # LATIN CAPITAL LETTER IS
-A76E; C; A76F; # LATIN CAPITAL LETTER CON
-A779; C; A77A; # LATIN CAPITAL LETTER INSULAR D
-A77B; C; A77C; # LATIN CAPITAL LETTER INSULAR F
-A77D; C; 1D79; # LATIN CAPITAL LETTER INSULAR G
-A77E; C; A77F; # LATIN CAPITAL LETTER TURNED INSULAR G
-A780; C; A781; # LATIN CAPITAL LETTER TURNED L
-A782; C; A783; # LATIN CAPITAL LETTER INSULAR R
-A784; C; A785; # LATIN CAPITAL LETTER INSULAR S
-A786; C; A787; # LATIN CAPITAL LETTER INSULAR T
-A78B; C; A78C; # LATIN CAPITAL LETTER SALTILLO
-A78D; C; 0265; # LATIN CAPITAL LETTER TURNED H
-A790; C; A791; # LATIN CAPITAL LETTER N WITH DESCENDER
-A792; C; A793; # LATIN CAPITAL LETTER C WITH BAR
-A7A0; C; A7A1; # LATIN CAPITAL LETTER G WITH OBLIQUE STROKE
-A7A2; C; A7A3; # LATIN CAPITAL LETTER K WITH OBLIQUE STROKE
-A7A4; C; A7A5; # LATIN CAPITAL LETTER N WITH OBLIQUE STROKE
-A7A6; C; A7A7; # LATIN CAPITAL LETTER R WITH OBLIQUE STROKE
-A7A8; C; A7A9; # LATIN CAPITAL LETTER S WITH OBLIQUE STROKE
-A7AA; C; 0266; # LATIN CAPITAL LETTER H WITH HOOK
-FB00; F; 0066 0066; # LATIN SMALL LIGATURE FF
-FB01; F; 0066 0069; # LATIN SMALL LIGATURE FI
-FB02; F; 0066 006C; # LATIN SMALL LIGATURE FL
-FB03; F; 0066 0066 0069; # LATIN SMALL LIGATURE FFI
-FB04; F; 0066 0066 006C; # LATIN SMALL LIGATURE FFL
-FB05; F; 0073 0074; # LATIN SMALL LIGATURE LONG S T
-FB06; F; 0073 0074; # LATIN SMALL LIGATURE ST
-FB13; F; 0574 0576; # ARMENIAN SMALL LIGATURE MEN NOW
-FB14; F; 0574 0565; # ARMENIAN SMALL LIGATURE MEN ECH
-FB15; F; 0574 056B; # ARMENIAN SMALL LIGATURE MEN INI
-FB16; F; 057E 0576; # ARMENIAN SMALL LIGATURE VEW NOW
-FB17; F; 0574 056D; # ARMENIAN SMALL LIGATURE MEN XEH
-FF21; C; FF41; # FULLWIDTH LATIN CAPITAL LETTER A
-FF22; C; FF42; # FULLWIDTH LATIN CAPITAL LETTER B
-FF23; C; FF43; # FULLWIDTH LATIN CAPITAL LETTER C
-FF24; C; FF44; # FULLWIDTH LATIN CAPITAL LETTER D
-FF25; C; FF45; # FULLWIDTH LATIN CAPITAL LETTER E
-FF26; C; FF46; # FULLWIDTH LATIN CAPITAL LETTER F
-FF27; C; FF47; # FULLWIDTH LATIN CAPITAL LETTER G
-FF28; C; FF48; # FULLWIDTH LATIN CAPITAL LETTER H
-FF29; C; FF49; # FULLWIDTH LATIN CAPITAL LETTER I
-FF2A; C; FF4A; # FULLWIDTH LATIN CAPITAL LETTER J
-FF2B; C; FF4B; # FULLWIDTH LATIN CAPITAL LETTER K
-FF2C; C; FF4C; # FULLWIDTH LATIN CAPITAL LETTER L
-FF2D; C; FF4D; # FULLWIDTH LATIN CAPITAL LETTER M
-FF2E; C; FF4E; # FULLWIDTH LATIN CAPITAL LETTER N
-FF2F; C; FF4F; # FULLWIDTH LATIN CAPITAL LETTER O
-FF30; C; FF50; # FULLWIDTH LATIN CAPITAL LETTER P
-FF31; C; FF51; # FULLWIDTH LATIN CAPITAL LETTER Q
-FF32; C; FF52; # FULLWIDTH LATIN CAPITAL LETTER R
-FF33; C; FF53; # FULLWIDTH LATIN CAPITAL LETTER S
-FF34; C; FF54; # FULLWIDTH LATIN CAPITAL LETTER T
-FF35; C; FF55; # FULLWIDTH LATIN CAPITAL LETTER U
-FF36; C; FF56; # FULLWIDTH LATIN CAPITAL LETTER V
-FF37; C; FF57; # FULLWIDTH LATIN CAPITAL LETTER W
-FF38; C; FF58; # FULLWIDTH LATIN CAPITAL LETTER X
-FF39; C; FF59; # FULLWIDTH LATIN CAPITAL LETTER Y
-FF3A; C; FF5A; # FULLWIDTH LATIN CAPITAL LETTER Z
-10400; C; 10428; # DESERET CAPITAL LETTER LONG I
-10401; C; 10429; # DESERET CAPITAL LETTER LONG E
-10402; C; 1042A; # DESERET CAPITAL LETTER LONG A
-10403; C; 1042B; # DESERET CAPITAL LETTER LONG AH
-10404; C; 1042C; # DESERET CAPITAL LETTER LONG O
-10405; C; 1042D; # DESERET CAPITAL LETTER LONG OO
-10406; C; 1042E; # DESERET CAPITAL LETTER SHORT I
-10407; C; 1042F; # DESERET CAPITAL LETTER SHORT E
-10408; C; 10430; # DESERET CAPITAL LETTER SHORT A
-10409; C; 10431; # DESERET CAPITAL LETTER SHORT AH
-1040A; C; 10432; # DESERET CAPITAL LETTER SHORT O
-1040B; C; 10433; # DESERET CAPITAL LETTER SHORT OO
-1040C; C; 10434; # DESERET CAPITAL LETTER AY
-1040D; C; 10435; # DESERET CAPITAL LETTER OW
-1040E; C; 10436; # DESERET CAPITAL LETTER WU
-1040F; C; 10437; # DESERET CAPITAL LETTER YEE
-10410; C; 10438; # DESERET CAPITAL LETTER H
-10411; C; 10439; # DESERET CAPITAL LETTER PEE
-10412; C; 1043A; # DESERET CAPITAL LETTER BEE
-10413; C; 1043B; # DESERET CAPITAL LETTER TEE
-10414; C; 1043C; # DESERET CAPITAL LETTER DEE
-10415; C; 1043D; # DESERET CAPITAL LETTER CHEE
-10416; C; 1043E; # DESERET CAPITAL LETTER JEE
-10417; C; 1043F; # DESERET CAPITAL LETTER KAY
-10418; C; 10440; # DESERET CAPITAL LETTER GAY
-10419; C; 10441; # DESERET CAPITAL LETTER EF
-1041A; C; 10442; # DESERET CAPITAL LETTER VEE
-1041B; C; 10443; # DESERET CAPITAL LETTER ETH
-1041C; C; 10444; # DESERET CAPITAL LETTER THEE
-1041D; C; 10445; # DESERET CAPITAL LETTER ES
-1041E; C; 10446; # DESERET CAPITAL LETTER ZEE
-1041F; C; 10447; # DESERET CAPITAL LETTER ESH
-10420; C; 10448; # DESERET CAPITAL LETTER ZHEE
-10421; C; 10449; # DESERET CAPITAL LETTER ER
-10422; C; 1044A; # DESERET CAPITAL LETTER EL
-10423; C; 1044B; # DESERET CAPITAL LETTER EM
-10424; C; 1044C; # DESERET CAPITAL LETTER EN
-10425; C; 1044D; # DESERET CAPITAL LETTER ENG
-10426; C; 1044E; # DESERET CAPITAL LETTER OI
-10427; C; 1044F; # DESERET CAPITAL LETTER EW
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/UnicodeData.txt b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/UnicodeData.txt
deleted file mode 100644
index 9f204050c6b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/UnicodeData.txt
+++ /dev/null
@@ -1,24428 +0,0 @@
-0000;<control>;Cc;0;BN;;;;;N;NULL;;;;
-0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;;
-0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;;
-0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;;
-0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;;
-0005;<control>;Cc;0;BN;;;;;N;ENQUIRY;;;;
-0006;<control>;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;;
-0007;<control>;Cc;0;BN;;;;;N;BELL;;;;
-0008;<control>;Cc;0;BN;;;;;N;BACKSPACE;;;;
-0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
-000A;<control>;Cc;0;B;;;;;N;LINE FEED (LF);;;;
-000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
-000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
-000D;<control>;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;;
-000E;<control>;Cc;0;BN;;;;;N;SHIFT OUT;;;;
-000F;<control>;Cc;0;BN;;;;;N;SHIFT IN;;;;
-0010;<control>;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;;
-0011;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;;
-0012;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;;
-0013;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;;
-0014;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;;
-0015;<control>;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;;
-0016;<control>;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;;
-0017;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;;
-0018;<control>;Cc;0;BN;;;;;N;CANCEL;;;;
-0019;<control>;Cc;0;BN;;;;;N;END OF MEDIUM;;;;
-001A;<control>;Cc;0;BN;;;;;N;SUBSTITUTE;;;;
-001B;<control>;Cc;0;BN;;;;;N;ESCAPE;;;;
-001C;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;;
-001D;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;;
-001E;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;;
-001F;<control>;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;;
-0020;SPACE;Zs;0;WS;;;;;N;;;;;
-0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
-0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;;
-0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;;
-0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;;
-0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;;
-0026;AMPERSAND;Po;0;ON;;;;;N;;;;;
-0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;;
-0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;;
-0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;;
-002A;ASTERISK;Po;0;ON;;;;;N;;;;;
-002B;PLUS SIGN;Sm;0;ES;;;;;N;;;;;
-002C;COMMA;Po;0;CS;;;;;N;;;;;
-002D;HYPHEN-MINUS;Pd;0;ES;;;;;N;;;;;
-002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;;
-002F;SOLIDUS;Po;0;CS;;;;;N;SLASH;;;;
-0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;;
-0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;;
-0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;;
-0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;;
-0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;;
-0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;;
-0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;;
-0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;;
-0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;;
-0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;;
-003A;COLON;Po;0;CS;;;;;N;;;;;
-003B;SEMICOLON;Po;0;ON;;;;;N;;;;;
-003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;;
-003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;;
-003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;;
-003F;QUESTION MARK;Po;0;ON;;;;;N;;;;;
-0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;;
-0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061;
-0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062;
-0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063;
-0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064;
-0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065;
-0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066;
-0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067;
-0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068;
-0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069;
-004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A;
-004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B;
-004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C;
-004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D;
-004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E;
-004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F;
-0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070;
-0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071;
-0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072;
-0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073;
-0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074;
-0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075;
-0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076;
-0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077;
-0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078;
-0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079;
-005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A;
-005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;;
-005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;;
-005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;;
-005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;;
-005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;;
-0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;;
-0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041
-0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042
-0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043
-0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044
-0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045
-0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046
-0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047
-0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048
-0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049
-006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A
-006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B
-006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C
-006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D
-006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E
-006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F
-0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050
-0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051
-0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052
-0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053
-0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054
-0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055
-0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056
-0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057
-0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058
-0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059
-007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A
-007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;;
-007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;;
-007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;;
-007E;TILDE;Sm;0;ON;;;;;N;;;;;
-007F;<control>;Cc;0;BN;;;;;N;DELETE;;;;
-0080;<control>;Cc;0;BN;;;;;N;;;;;
-0081;<control>;Cc;0;BN;;;;;N;;;;;
-0082;<control>;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;;
-0083;<control>;Cc;0;BN;;;;;N;NO BREAK HERE;;;;
-0084;<control>;Cc;0;BN;;;;;N;;;;;
-0085;<control>;Cc;0;B;;;;;N;NEXT LINE (NEL);;;;
-0086;<control>;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;;
-0087;<control>;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;;
-0088;<control>;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;;
-0089;<control>;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;;
-008A;<control>;Cc;0;BN;;;;;N;LINE TABULATION SET;;;;
-008B;<control>;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;;
-008C;<control>;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;;
-008D;<control>;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;;
-008E;<control>;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;;
-008F;<control>;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;;
-0090;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;;
-0091;<control>;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;;
-0092;<control>;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;;
-0093;<control>;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;;
-0094;<control>;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;;
-0095;<control>;Cc;0;BN;;;;;N;MESSAGE WAITING;;;;
-0096;<control>;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;;
-0097;<control>;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;;
-0098;<control>;Cc;0;BN;;;;;N;START OF STRING;;;;
-0099;<control>;Cc;0;BN;;;;;N;;;;;
-009A;<control>;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;;
-009B;<control>;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;;
-009C;<control>;Cc;0;BN;;;;;N;STRING TERMINATOR;;;;
-009D;<control>;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;;
-009E;<control>;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;;
-009F;<control>;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;;
-00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
-00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
-00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;;
-00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;;
-00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;;
-00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;;
-00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;;
-00A7;SECTION SIGN;Po;0;ON;;;;;N;;;;;
-00A8;DIAERESIS;Sk;0;ON;<compat> 0020 0308;;;;N;SPACING DIAERESIS;;;;
-00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;;
-00AA;FEMININE ORDINAL INDICATOR;Lo;0;L;<super> 0061;;;;N;;;;;
-00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;;;;
-00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;;
-00AD;SOFT HYPHEN;Cf;0;BN;;;;;N;;;;;
-00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;;
-00AF;MACRON;Sk;0;ON;<compat> 0020 0304;;;;N;SPACING MACRON;;;;
-00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;;
-00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;;
-00B2;SUPERSCRIPT TWO;No;0;EN;<super> 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;;
-00B3;SUPERSCRIPT THREE;No;0;EN;<super> 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;;
-00B4;ACUTE ACCENT;Sk;0;ON;<compat> 0020 0301;;;;N;SPACING ACUTE;;;;
-00B5;MICRO SIGN;Ll;0;L;<compat> 03BC;;;;N;;;039C;;039C
-00B6;PILCROW SIGN;Po;0;ON;;;;;N;PARAGRAPH SIGN;;;;
-00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;;
-00B8;CEDILLA;Sk;0;ON;<compat> 0020 0327;;;;N;SPACING CEDILLA;;;;
-00B9;SUPERSCRIPT ONE;No;0;EN;<super> 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;;
-00BA;MASCULINE ORDINAL INDICATOR;Lo;0;L;<super> 006F;;;;N;;;;;
-00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;;
-00BC;VULGAR FRACTION ONE QUARTER;No;0;ON;<fraction> 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;;
-00BD;VULGAR FRACTION ONE HALF;No;0;ON;<fraction> 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;;
-00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON;<fraction> 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;;
-00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;;
-00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0;
-00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1;
-00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2;
-00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3;
-00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4;
-00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5;
-00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;;;00E6;
-00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7;
-00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8;
-00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9;
-00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA;
-00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB;
-00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC;
-00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED;
-00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE;
-00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF;
-00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;00F0;
-00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1;
-00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2;
-00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3;
-00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4;
-00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5;
-00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6;
-00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;;
-00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8;
-00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9;
-00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA;
-00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB;
-00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC;
-00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD;
-00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;;;00FE;
-00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;;
-00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0
-00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1
-00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2
-00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3
-00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4
-00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5
-00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;;00C6;;00C6
-00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7
-00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8
-00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9
-00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA
-00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB
-00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC
-00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD
-00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE
-00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF
-00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;;00D0;;00D0
-00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1
-00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2
-00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3
-00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4
-00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5
-00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6
-00F7;DIVISION SIGN;Sm;0;ON;;;;;N;;;;;
-00F8;LATIN SMALL LETTER O WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER O SLASH;;00D8;;00D8
-00F9;LATIN SMALL LETTER U WITH GRAVE;Ll;0;L;0075 0300;;;;N;LATIN SMALL LETTER U GRAVE;;00D9;;00D9
-00FA;LATIN SMALL LETTER U WITH ACUTE;Ll;0;L;0075 0301;;;;N;LATIN SMALL LETTER U ACUTE;;00DA;;00DA
-00FB;LATIN SMALL LETTER U WITH CIRCUMFLEX;Ll;0;L;0075 0302;;;;N;LATIN SMALL LETTER U CIRCUMFLEX;;00DB;;00DB
-00FC;LATIN SMALL LETTER U WITH DIAERESIS;Ll;0;L;0075 0308;;;;N;LATIN SMALL LETTER U DIAERESIS;;00DC;;00DC
-00FD;LATIN SMALL LETTER Y WITH ACUTE;Ll;0;L;0079 0301;;;;N;LATIN SMALL LETTER Y ACUTE;;00DD;;00DD
-00FE;LATIN SMALL LETTER THORN;Ll;0;L;;;;;N;;;00DE;;00DE
-00FF;LATIN SMALL LETTER Y WITH DIAERESIS;Ll;0;L;0079 0308;;;;N;LATIN SMALL LETTER Y DIAERESIS;;0178;;0178
-0100;LATIN CAPITAL LETTER A WITH MACRON;Lu;0;L;0041 0304;;;;N;LATIN CAPITAL LETTER A MACRON;;;0101;
-0101;LATIN SMALL LETTER A WITH MACRON;Ll;0;L;0061 0304;;;;N;LATIN SMALL LETTER A MACRON;;0100;;0100
-0102;LATIN CAPITAL LETTER A WITH BREVE;Lu;0;L;0041 0306;;;;N;LATIN CAPITAL LETTER A BREVE;;;0103;
-0103;LATIN SMALL LETTER A WITH BREVE;Ll;0;L;0061 0306;;;;N;LATIN SMALL LETTER A BREVE;;0102;;0102
-0104;LATIN CAPITAL LETTER A WITH OGONEK;Lu;0;L;0041 0328;;;;N;LATIN CAPITAL LETTER A OGONEK;;;0105;
-0105;LATIN SMALL LETTER A WITH OGONEK;Ll;0;L;0061 0328;;;;N;LATIN SMALL LETTER A OGONEK;;0104;;0104
-0106;LATIN CAPITAL LETTER C WITH ACUTE;Lu;0;L;0043 0301;;;;N;LATIN CAPITAL LETTER C ACUTE;;;0107;
-0107;LATIN SMALL LETTER C WITH ACUTE;Ll;0;L;0063 0301;;;;N;LATIN SMALL LETTER C ACUTE;;0106;;0106
-0108;LATIN CAPITAL LETTER C WITH CIRCUMFLEX;Lu;0;L;0043 0302;;;;N;LATIN CAPITAL LETTER C CIRCUMFLEX;;;0109;
-0109;LATIN SMALL LETTER C WITH CIRCUMFLEX;Ll;0;L;0063 0302;;;;N;LATIN SMALL LETTER C CIRCUMFLEX;;0108;;0108
-010A;LATIN CAPITAL LETTER C WITH DOT ABOVE;Lu;0;L;0043 0307;;;;N;LATIN CAPITAL LETTER C DOT;;;010B;
-010B;LATIN SMALL LETTER C WITH DOT ABOVE;Ll;0;L;0063 0307;;;;N;LATIN SMALL LETTER C DOT;;010A;;010A
-010C;LATIN CAPITAL LETTER C WITH CARON;Lu;0;L;0043 030C;;;;N;LATIN CAPITAL LETTER C HACEK;;;010D;
-010D;LATIN SMALL LETTER C WITH CARON;Ll;0;L;0063 030C;;;;N;LATIN SMALL LETTER C HACEK;;010C;;010C
-010E;LATIN CAPITAL LETTER D WITH CARON;Lu;0;L;0044 030C;;;;N;LATIN CAPITAL LETTER D HACEK;;;010F;
-010F;LATIN SMALL LETTER D WITH CARON;Ll;0;L;0064 030C;;;;N;LATIN SMALL LETTER D HACEK;;010E;;010E
-0110;LATIN CAPITAL LETTER D WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D BAR;;;0111;
-0111;LATIN SMALL LETTER D WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER D BAR;;0110;;0110
-0112;LATIN CAPITAL LETTER E WITH MACRON;Lu;0;L;0045 0304;;;;N;LATIN CAPITAL LETTER E MACRON;;;0113;
-0113;LATIN SMALL LETTER E WITH MACRON;Ll;0;L;0065 0304;;;;N;LATIN SMALL LETTER E MACRON;;0112;;0112
-0114;LATIN CAPITAL LETTER E WITH BREVE;Lu;0;L;0045 0306;;;;N;LATIN CAPITAL LETTER E BREVE;;;0115;
-0115;LATIN SMALL LETTER E WITH BREVE;Ll;0;L;0065 0306;;;;N;LATIN SMALL LETTER E BREVE;;0114;;0114
-0116;LATIN CAPITAL LETTER E WITH DOT ABOVE;Lu;0;L;0045 0307;;;;N;LATIN CAPITAL LETTER E DOT;;;0117;
-0117;LATIN SMALL LETTER E WITH DOT ABOVE;Ll;0;L;0065 0307;;;;N;LATIN SMALL LETTER E DOT;;0116;;0116
-0118;LATIN CAPITAL LETTER E WITH OGONEK;Lu;0;L;0045 0328;;;;N;LATIN CAPITAL LETTER E OGONEK;;;0119;
-0119;LATIN SMALL LETTER E WITH OGONEK;Ll;0;L;0065 0328;;;;N;LATIN SMALL LETTER E OGONEK;;0118;;0118
-011A;LATIN CAPITAL LETTER E WITH CARON;Lu;0;L;0045 030C;;;;N;LATIN CAPITAL LETTER E HACEK;;;011B;
-011B;LATIN SMALL LETTER E WITH CARON;Ll;0;L;0065 030C;;;;N;LATIN SMALL LETTER E HACEK;;011A;;011A
-011C;LATIN CAPITAL LETTER G WITH CIRCUMFLEX;Lu;0;L;0047 0302;;;;N;LATIN CAPITAL LETTER G CIRCUMFLEX;;;011D;
-011D;LATIN SMALL LETTER G WITH CIRCUMFLEX;Ll;0;L;0067 0302;;;;N;LATIN SMALL LETTER G CIRCUMFLEX;;011C;;011C
-011E;LATIN CAPITAL LETTER G WITH BREVE;Lu;0;L;0047 0306;;;;N;LATIN CAPITAL LETTER G BREVE;;;011F;
-011F;LATIN SMALL LETTER G WITH BREVE;Ll;0;L;0067 0306;;;;N;LATIN SMALL LETTER G BREVE;;011E;;011E
-0120;LATIN CAPITAL LETTER G WITH DOT ABOVE;Lu;0;L;0047 0307;;;;N;LATIN CAPITAL LETTER G DOT;;;0121;
-0121;LATIN SMALL LETTER G WITH DOT ABOVE;Ll;0;L;0067 0307;;;;N;LATIN SMALL LETTER G DOT;;0120;;0120
-0122;LATIN CAPITAL LETTER G WITH CEDILLA;Lu;0;L;0047 0327;;;;N;LATIN CAPITAL LETTER G CEDILLA;;;0123;
-0123;LATIN SMALL LETTER G WITH CEDILLA;Ll;0;L;0067 0327;;;;N;LATIN SMALL LETTER G CEDILLA;;0122;;0122
-0124;LATIN CAPITAL LETTER H WITH CIRCUMFLEX;Lu;0;L;0048 0302;;;;N;LATIN CAPITAL LETTER H CIRCUMFLEX;;;0125;
-0125;LATIN SMALL LETTER H WITH CIRCUMFLEX;Ll;0;L;0068 0302;;;;N;LATIN SMALL LETTER H CIRCUMFLEX;;0124;;0124
-0126;LATIN CAPITAL LETTER H WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER H BAR;;;0127;
-0127;LATIN SMALL LETTER H WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER H BAR;;0126;;0126
-0128;LATIN CAPITAL LETTER I WITH TILDE;Lu;0;L;0049 0303;;;;N;LATIN CAPITAL LETTER I TILDE;;;0129;
-0129;LATIN SMALL LETTER I WITH TILDE;Ll;0;L;0069 0303;;;;N;LATIN SMALL LETTER I TILDE;;0128;;0128
-012A;LATIN CAPITAL LETTER I WITH MACRON;Lu;0;L;0049 0304;;;;N;LATIN CAPITAL LETTER I MACRON;;;012B;
-012B;LATIN SMALL LETTER I WITH MACRON;Ll;0;L;0069 0304;;;;N;LATIN SMALL LETTER I MACRON;;012A;;012A
-012C;LATIN CAPITAL LETTER I WITH BREVE;Lu;0;L;0049 0306;;;;N;LATIN CAPITAL LETTER I BREVE;;;012D;
-012D;LATIN SMALL LETTER I WITH BREVE;Ll;0;L;0069 0306;;;;N;LATIN SMALL LETTER I BREVE;;012C;;012C
-012E;LATIN CAPITAL LETTER I WITH OGONEK;Lu;0;L;0049 0328;;;;N;LATIN CAPITAL LETTER I OGONEK;;;012F;
-012F;LATIN SMALL LETTER I WITH OGONEK;Ll;0;L;0069 0328;;;;N;LATIN SMALL LETTER I OGONEK;;012E;;012E
-0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069;
-0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049
-0132;LATIN CAPITAL LIGATURE IJ;Lu;0;L;<compat> 0049 004A;;;;N;LATIN CAPITAL LETTER I J;;;0133;
-0133;LATIN SMALL LIGATURE IJ;Ll;0;L;<compat> 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132
-0134;LATIN CAPITAL LETTER J WITH CIRCUMFLEX;Lu;0;L;004A 0302;;;;N;LATIN CAPITAL LETTER J CIRCUMFLEX;;;0135;
-0135;LATIN SMALL LETTER J WITH CIRCUMFLEX;Ll;0;L;006A 0302;;;;N;LATIN SMALL LETTER J CIRCUMFLEX;;0134;;0134
-0136;LATIN CAPITAL LETTER K WITH CEDILLA;Lu;0;L;004B 0327;;;;N;LATIN CAPITAL LETTER K CEDILLA;;;0137;
-0137;LATIN SMALL LETTER K WITH CEDILLA;Ll;0;L;006B 0327;;;;N;LATIN SMALL LETTER K CEDILLA;;0136;;0136
-0138;LATIN SMALL LETTER KRA;Ll;0;L;;;;;N;;;;;
-0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A;
-013A;LATIN SMALL LETTER L WITH ACUTE;Ll;0;L;006C 0301;;;;N;LATIN SMALL LETTER L ACUTE;;0139;;0139
-013B;LATIN CAPITAL LETTER L WITH CEDILLA;Lu;0;L;004C 0327;;;;N;LATIN CAPITAL LETTER L CEDILLA;;;013C;
-013C;LATIN SMALL LETTER L WITH CEDILLA;Ll;0;L;006C 0327;;;;N;LATIN SMALL LETTER L CEDILLA;;013B;;013B
-013D;LATIN CAPITAL LETTER L WITH CARON;Lu;0;L;004C 030C;;;;N;LATIN CAPITAL LETTER L HACEK;;;013E;
-013E;LATIN SMALL LETTER L WITH CARON;Ll;0;L;006C 030C;;;;N;LATIN SMALL LETTER L HACEK;;013D;;013D
-013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L;<compat> 004C 00B7;;;;N;;;;0140;
-0140;LATIN SMALL LETTER L WITH MIDDLE DOT;Ll;0;L;<compat> 006C 00B7;;;;N;;;013F;;013F
-0141;LATIN CAPITAL LETTER L WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER L SLASH;;;0142;
-0142;LATIN SMALL LETTER L WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER L SLASH;;0141;;0141
-0143;LATIN CAPITAL LETTER N WITH ACUTE;Lu;0;L;004E 0301;;;;N;LATIN CAPITAL LETTER N ACUTE;;;0144;
-0144;LATIN SMALL LETTER N WITH ACUTE;Ll;0;L;006E 0301;;;;N;LATIN SMALL LETTER N ACUTE;;0143;;0143
-0145;LATIN CAPITAL LETTER N WITH CEDILLA;Lu;0;L;004E 0327;;;;N;LATIN CAPITAL LETTER N CEDILLA;;;0146;
-0146;LATIN SMALL LETTER N WITH CEDILLA;Ll;0;L;006E 0327;;;;N;LATIN SMALL LETTER N CEDILLA;;0145;;0145
-0147;LATIN CAPITAL LETTER N WITH CARON;Lu;0;L;004E 030C;;;;N;LATIN CAPITAL LETTER N HACEK;;;0148;
-0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147
-0149;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE;Ll;0;L;<compat> 02BC 006E;;;;N;LATIN SMALL LETTER APOSTROPHE N;;;;
-014A;LATIN CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;014B;
-014B;LATIN SMALL LETTER ENG;Ll;0;L;;;;;N;;;014A;;014A
-014C;LATIN CAPITAL LETTER O WITH MACRON;Lu;0;L;004F 0304;;;;N;LATIN CAPITAL LETTER O MACRON;;;014D;
-014D;LATIN SMALL LETTER O WITH MACRON;Ll;0;L;006F 0304;;;;N;LATIN SMALL LETTER O MACRON;;014C;;014C
-014E;LATIN CAPITAL LETTER O WITH BREVE;Lu;0;L;004F 0306;;;;N;LATIN CAPITAL LETTER O BREVE;;;014F;
-014F;LATIN SMALL LETTER O WITH BREVE;Ll;0;L;006F 0306;;;;N;LATIN SMALL LETTER O BREVE;;014E;;014E
-0150;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE;Lu;0;L;004F 030B;;;;N;LATIN CAPITAL LETTER O DOUBLE ACUTE;;;0151;
-0151;LATIN SMALL LETTER O WITH DOUBLE ACUTE;Ll;0;L;006F 030B;;;;N;LATIN SMALL LETTER O DOUBLE ACUTE;;0150;;0150
-0152;LATIN CAPITAL LIGATURE OE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O E;;;0153;
-0153;LATIN SMALL LIGATURE OE;Ll;0;L;;;;;N;LATIN SMALL LETTER O E;;0152;;0152
-0154;LATIN CAPITAL LETTER R WITH ACUTE;Lu;0;L;0052 0301;;;;N;LATIN CAPITAL LETTER R ACUTE;;;0155;
-0155;LATIN SMALL LETTER R WITH ACUTE;Ll;0;L;0072 0301;;;;N;LATIN SMALL LETTER R ACUTE;;0154;;0154
-0156;LATIN CAPITAL LETTER R WITH CEDILLA;Lu;0;L;0052 0327;;;;N;LATIN CAPITAL LETTER R CEDILLA;;;0157;
-0157;LATIN SMALL LETTER R WITH CEDILLA;Ll;0;L;0072 0327;;;;N;LATIN SMALL LETTER R CEDILLA;;0156;;0156
-0158;LATIN CAPITAL LETTER R WITH CARON;Lu;0;L;0052 030C;;;;N;LATIN CAPITAL LETTER R HACEK;;;0159;
-0159;LATIN SMALL LETTER R WITH CARON;Ll;0;L;0072 030C;;;;N;LATIN SMALL LETTER R HACEK;;0158;;0158
-015A;LATIN CAPITAL LETTER S WITH ACUTE;Lu;0;L;0053 0301;;;;N;LATIN CAPITAL LETTER S ACUTE;;;015B;
-015B;LATIN SMALL LETTER S WITH ACUTE;Ll;0;L;0073 0301;;;;N;LATIN SMALL LETTER S ACUTE;;015A;;015A
-015C;LATIN CAPITAL LETTER S WITH CIRCUMFLEX;Lu;0;L;0053 0302;;;;N;LATIN CAPITAL LETTER S CIRCUMFLEX;;;015D;
-015D;LATIN SMALL LETTER S WITH CIRCUMFLEX;Ll;0;L;0073 0302;;;;N;LATIN SMALL LETTER S CIRCUMFLEX;;015C;;015C
-015E;LATIN CAPITAL LETTER S WITH CEDILLA;Lu;0;L;0053 0327;;;;N;LATIN CAPITAL LETTER S CEDILLA;;;015F;
-015F;LATIN SMALL LETTER S WITH CEDILLA;Ll;0;L;0073 0327;;;;N;LATIN SMALL LETTER S CEDILLA;;015E;;015E
-0160;LATIN CAPITAL LETTER S WITH CARON;Lu;0;L;0053 030C;;;;N;LATIN CAPITAL LETTER S HACEK;;;0161;
-0161;LATIN SMALL LETTER S WITH CARON;Ll;0;L;0073 030C;;;;N;LATIN SMALL LETTER S HACEK;;0160;;0160
-0162;LATIN CAPITAL LETTER T WITH CEDILLA;Lu;0;L;0054 0327;;;;N;LATIN CAPITAL LETTER T CEDILLA;;;0163;
-0163;LATIN SMALL LETTER T WITH CEDILLA;Ll;0;L;0074 0327;;;;N;LATIN SMALL LETTER T CEDILLA;;0162;;0162
-0164;LATIN CAPITAL LETTER T WITH CARON;Lu;0;L;0054 030C;;;;N;LATIN CAPITAL LETTER T HACEK;;;0165;
-0165;LATIN SMALL LETTER T WITH CARON;Ll;0;L;0074 030C;;;;N;LATIN SMALL LETTER T HACEK;;0164;;0164
-0166;LATIN CAPITAL LETTER T WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T BAR;;;0167;
-0167;LATIN SMALL LETTER T WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER T BAR;;0166;;0166
-0168;LATIN CAPITAL LETTER U WITH TILDE;Lu;0;L;0055 0303;;;;N;LATIN CAPITAL LETTER U TILDE;;;0169;
-0169;LATIN SMALL LETTER U WITH TILDE;Ll;0;L;0075 0303;;;;N;LATIN SMALL LETTER U TILDE;;0168;;0168
-016A;LATIN CAPITAL LETTER U WITH MACRON;Lu;0;L;0055 0304;;;;N;LATIN CAPITAL LETTER U MACRON;;;016B;
-016B;LATIN SMALL LETTER U WITH MACRON;Ll;0;L;0075 0304;;;;N;LATIN SMALL LETTER U MACRON;;016A;;016A
-016C;LATIN CAPITAL LETTER U WITH BREVE;Lu;0;L;0055 0306;;;;N;LATIN CAPITAL LETTER U BREVE;;;016D;
-016D;LATIN SMALL LETTER U WITH BREVE;Ll;0;L;0075 0306;;;;N;LATIN SMALL LETTER U BREVE;;016C;;016C
-016E;LATIN CAPITAL LETTER U WITH RING ABOVE;Lu;0;L;0055 030A;;;;N;LATIN CAPITAL LETTER U RING;;;016F;
-016F;LATIN SMALL LETTER U WITH RING ABOVE;Ll;0;L;0075 030A;;;;N;LATIN SMALL LETTER U RING;;016E;;016E
-0170;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0055 030B;;;;N;LATIN CAPITAL LETTER U DOUBLE ACUTE;;;0171;
-0171;LATIN SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0075 030B;;;;N;LATIN SMALL LETTER U DOUBLE ACUTE;;0170;;0170
-0172;LATIN CAPITAL LETTER U WITH OGONEK;Lu;0;L;0055 0328;;;;N;LATIN CAPITAL LETTER U OGONEK;;;0173;
-0173;LATIN SMALL LETTER U WITH OGONEK;Ll;0;L;0075 0328;;;;N;LATIN SMALL LETTER U OGONEK;;0172;;0172
-0174;LATIN CAPITAL LETTER W WITH CIRCUMFLEX;Lu;0;L;0057 0302;;;;N;LATIN CAPITAL LETTER W CIRCUMFLEX;;;0175;
-0175;LATIN SMALL LETTER W WITH CIRCUMFLEX;Ll;0;L;0077 0302;;;;N;LATIN SMALL LETTER W CIRCUMFLEX;;0174;;0174
-0176;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX;Lu;0;L;0059 0302;;;;N;LATIN CAPITAL LETTER Y CIRCUMFLEX;;;0177;
-0177;LATIN SMALL LETTER Y WITH CIRCUMFLEX;Ll;0;L;0079 0302;;;;N;LATIN SMALL LETTER Y CIRCUMFLEX;;0176;;0176
-0178;LATIN CAPITAL LETTER Y WITH DIAERESIS;Lu;0;L;0059 0308;;;;N;LATIN CAPITAL LETTER Y DIAERESIS;;;00FF;
-0179;LATIN CAPITAL LETTER Z WITH ACUTE;Lu;0;L;005A 0301;;;;N;LATIN CAPITAL LETTER Z ACUTE;;;017A;
-017A;LATIN SMALL LETTER Z WITH ACUTE;Ll;0;L;007A 0301;;;;N;LATIN SMALL LETTER Z ACUTE;;0179;;0179
-017B;LATIN CAPITAL LETTER Z WITH DOT ABOVE;Lu;0;L;005A 0307;;;;N;LATIN CAPITAL LETTER Z DOT;;;017C;
-017C;LATIN SMALL LETTER Z WITH DOT ABOVE;Ll;0;L;007A 0307;;;;N;LATIN SMALL LETTER Z DOT;;017B;;017B
-017D;LATIN CAPITAL LETTER Z WITH CARON;Lu;0;L;005A 030C;;;;N;LATIN CAPITAL LETTER Z HACEK;;;017E;
-017E;LATIN SMALL LETTER Z WITH CARON;Ll;0;L;007A 030C;;;;N;LATIN SMALL LETTER Z HACEK;;017D;;017D
-017F;LATIN SMALL LETTER LONG S;Ll;0;L;<compat> 0073;;;;N;;;0053;;0053
-0180;LATIN SMALL LETTER B WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER B BAR;;0243;;0243
-0181;LATIN CAPITAL LETTER B WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B HOOK;;;0253;
-0182;LATIN CAPITAL LETTER B WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B TOPBAR;;;0183;
-0183;LATIN SMALL LETTER B WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER B TOPBAR;;0182;;0182
-0184;LATIN CAPITAL LETTER TONE SIX;Lu;0;L;;;;;N;;;;0185;
-0185;LATIN SMALL LETTER TONE SIX;Ll;0;L;;;;;N;;;0184;;0184
-0186;LATIN CAPITAL LETTER OPEN O;Lu;0;L;;;;;N;;;;0254;
-0187;LATIN CAPITAL LETTER C WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER C HOOK;;;0188;
-0188;LATIN SMALL LETTER C WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER C HOOK;;0187;;0187
-0189;LATIN CAPITAL LETTER AFRICAN D;Lu;0;L;;;;;N;;;;0256;
-018A;LATIN CAPITAL LETTER D WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D HOOK;;;0257;
-018B;LATIN CAPITAL LETTER D WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D TOPBAR;;;018C;
-018C;LATIN SMALL LETTER D WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER D TOPBAR;;018B;;018B
-018D;LATIN SMALL LETTER TURNED DELTA;Ll;0;L;;;;;N;;;;;
-018E;LATIN CAPITAL LETTER REVERSED E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER TURNED E;;;01DD;
-018F;LATIN CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;0259;
-0190;LATIN CAPITAL LETTER OPEN E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER EPSILON;;;025B;
-0191;LATIN CAPITAL LETTER F WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER F HOOK;;;0192;
-0192;LATIN SMALL LETTER F WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT F;;0191;;0191
-0193;LATIN CAPITAL LETTER G WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G HOOK;;;0260;
-0194;LATIN CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;0263;
-0195;LATIN SMALL LETTER HV;Ll;0;L;;;;;N;LATIN SMALL LETTER H V;;01F6;;01F6
-0196;LATIN CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;0269;
-0197;LATIN CAPITAL LETTER I WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED I;;;0268;
-0198;LATIN CAPITAL LETTER K WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER K HOOK;;;0199;
-0199;LATIN SMALL LETTER K WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER K HOOK;;0198;;0198
-019A;LATIN SMALL LETTER L WITH BAR;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED L;;023D;;023D
-019B;LATIN SMALL LETTER LAMBDA WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED LAMBDA;;;;
-019C;LATIN CAPITAL LETTER TURNED M;Lu;0;L;;;;;N;;;;026F;
-019D;LATIN CAPITAL LETTER N WITH LEFT HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER N HOOK;;;0272;
-019E;LATIN SMALL LETTER N WITH LONG RIGHT LEG;Ll;0;L;;;;;N;;;0220;;0220
-019F;LATIN CAPITAL LETTER O WITH MIDDLE TILDE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED O;;;0275;
-01A0;LATIN CAPITAL LETTER O WITH HORN;Lu;0;L;004F 031B;;;;N;LATIN CAPITAL LETTER O HORN;;;01A1;
-01A1;LATIN SMALL LETTER O WITH HORN;Ll;0;L;006F 031B;;;;N;LATIN SMALL LETTER O HORN;;01A0;;01A0
-01A2;LATIN CAPITAL LETTER OI;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O I;;;01A3;
-01A3;LATIN SMALL LETTER OI;Ll;0;L;;;;;N;LATIN SMALL LETTER O I;;01A2;;01A2
-01A4;LATIN CAPITAL LETTER P WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER P HOOK;;;01A5;
-01A5;LATIN SMALL LETTER P WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER P HOOK;;01A4;;01A4
-01A6;LATIN LETTER YR;Lu;0;L;;;;;N;LATIN LETTER Y R;;;0280;
-01A7;LATIN CAPITAL LETTER TONE TWO;Lu;0;L;;;;;N;;;;01A8;
-01A8;LATIN SMALL LETTER TONE TWO;Ll;0;L;;;;;N;;;01A7;;01A7
-01A9;LATIN CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;0283;
-01AA;LATIN LETTER REVERSED ESH LOOP;Ll;0;L;;;;;N;;;;;
-01AB;LATIN SMALL LETTER T WITH PALATAL HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T PALATAL HOOK;;;;
-01AC;LATIN CAPITAL LETTER T WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T HOOK;;;01AD;
-01AD;LATIN SMALL LETTER T WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T HOOK;;01AC;;01AC
-01AE;LATIN CAPITAL LETTER T WITH RETROFLEX HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T RETROFLEX HOOK;;;0288;
-01AF;LATIN CAPITAL LETTER U WITH HORN;Lu;0;L;0055 031B;;;;N;LATIN CAPITAL LETTER U HORN;;;01B0;
-01B0;LATIN SMALL LETTER U WITH HORN;Ll;0;L;0075 031B;;;;N;LATIN SMALL LETTER U HORN;;01AF;;01AF
-01B1;LATIN CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;028A;
-01B2;LATIN CAPITAL LETTER V WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER SCRIPT V;;;028B;
-01B3;LATIN CAPITAL LETTER Y WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Y HOOK;;;01B4;
-01B4;LATIN SMALL LETTER Y WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Y HOOK;;01B3;;01B3
-01B5;LATIN CAPITAL LETTER Z WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Z BAR;;;01B6;
-01B6;LATIN SMALL LETTER Z WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER Z BAR;;01B5;;01B5
-01B7;LATIN CAPITAL LETTER EZH;Lu;0;L;;;;;N;LATIN CAPITAL LETTER YOGH;;;0292;
-01B8;LATIN CAPITAL LETTER EZH REVERSED;Lu;0;L;;;;;N;LATIN CAPITAL LETTER REVERSED YOGH;;;01B9;
-01B9;LATIN SMALL LETTER EZH REVERSED;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED YOGH;;01B8;;01B8
-01BA;LATIN SMALL LETTER EZH WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH WITH TAIL;;;;
-01BB;LATIN LETTER TWO WITH STROKE;Lo;0;L;;;;;N;LATIN LETTER TWO BAR;;;;
-01BC;LATIN CAPITAL LETTER TONE FIVE;Lu;0;L;;;;;N;;;;01BD;
-01BD;LATIN SMALL LETTER TONE FIVE;Ll;0;L;;;;;N;;;01BC;;01BC
-01BE;LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER INVERTED GLOTTAL STOP BAR;;;;
-01BF;LATIN LETTER WYNN;Ll;0;L;;;;;N;;;01F7;;01F7
-01C0;LATIN LETTER DENTAL CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE;;;;
-01C1;LATIN LETTER LATERAL CLICK;Lo;0;L;;;;;N;LATIN LETTER DOUBLE PIPE;;;;
-01C2;LATIN LETTER ALVEOLAR CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE DOUBLE BAR;;;;
-01C3;LATIN LETTER RETROFLEX CLICK;Lo;0;L;;;;;N;LATIN LETTER EXCLAMATION MARK;;;;
-01C4;LATIN CAPITAL LETTER DZ WITH CARON;Lu;0;L;<compat> 0044 017D;;;;N;LATIN CAPITAL LETTER D Z HACEK;;;01C6;01C5
-01C5;LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON;Lt;0;L;<compat> 0044 017E;;;;N;LATIN LETTER CAPITAL D SMALL Z HACEK;;01C4;01C6;01C5
-01C6;LATIN SMALL LETTER DZ WITH CARON;Ll;0;L;<compat> 0064 017E;;;;N;LATIN SMALL LETTER D Z HACEK;;01C4;;01C5
-01C7;LATIN CAPITAL LETTER LJ;Lu;0;L;<compat> 004C 004A;;;;N;LATIN CAPITAL LETTER L J;;;01C9;01C8
-01C8;LATIN CAPITAL LETTER L WITH SMALL LETTER J;Lt;0;L;<compat> 004C 006A;;;;N;LATIN LETTER CAPITAL L SMALL J;;01C7;01C9;01C8
-01C9;LATIN SMALL LETTER LJ;Ll;0;L;<compat> 006C 006A;;;;N;LATIN SMALL LETTER L J;;01C7;;01C8
-01CA;LATIN CAPITAL LETTER NJ;Lu;0;L;<compat> 004E 004A;;;;N;LATIN CAPITAL LETTER N J;;;01CC;01CB
-01CB;LATIN CAPITAL LETTER N WITH SMALL LETTER J;Lt;0;L;<compat> 004E 006A;;;;N;LATIN LETTER CAPITAL N SMALL J;;01CA;01CC;01CB
-01CC;LATIN SMALL LETTER NJ;Ll;0;L;<compat> 006E 006A;;;;N;LATIN SMALL LETTER N J;;01CA;;01CB
-01CD;LATIN CAPITAL LETTER A WITH CARON;Lu;0;L;0041 030C;;;;N;LATIN CAPITAL LETTER A HACEK;;;01CE;
-01CE;LATIN SMALL LETTER A WITH CARON;Ll;0;L;0061 030C;;;;N;LATIN SMALL LETTER A HACEK;;01CD;;01CD
-01CF;LATIN CAPITAL LETTER I WITH CARON;Lu;0;L;0049 030C;;;;N;LATIN CAPITAL LETTER I HACEK;;;01D0;
-01D0;LATIN SMALL LETTER I WITH CARON;Ll;0;L;0069 030C;;;;N;LATIN SMALL LETTER I HACEK;;01CF;;01CF
-01D1;LATIN CAPITAL LETTER O WITH CARON;Lu;0;L;004F 030C;;;;N;LATIN CAPITAL LETTER O HACEK;;;01D2;
-01D2;LATIN SMALL LETTER O WITH CARON;Ll;0;L;006F 030C;;;;N;LATIN SMALL LETTER O HACEK;;01D1;;01D1
-01D3;LATIN CAPITAL LETTER U WITH CARON;Lu;0;L;0055 030C;;;;N;LATIN CAPITAL LETTER U HACEK;;;01D4;
-01D4;LATIN SMALL LETTER U WITH CARON;Ll;0;L;0075 030C;;;;N;LATIN SMALL LETTER U HACEK;;01D3;;01D3
-01D5;LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON;Lu;0;L;00DC 0304;;;;N;LATIN CAPITAL LETTER U DIAERESIS MACRON;;;01D6;
-01D6;LATIN SMALL LETTER U WITH DIAERESIS AND MACRON;Ll;0;L;00FC 0304;;;;N;LATIN SMALL LETTER U DIAERESIS MACRON;;01D5;;01D5
-01D7;LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE;Lu;0;L;00DC 0301;;;;N;LATIN CAPITAL LETTER U DIAERESIS ACUTE;;;01D8;
-01D8;LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE;Ll;0;L;00FC 0301;;;;N;LATIN SMALL LETTER U DIAERESIS ACUTE;;01D7;;01D7
-01D9;LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON;Lu;0;L;00DC 030C;;;;N;LATIN CAPITAL LETTER U DIAERESIS HACEK;;;01DA;
-01DA;LATIN SMALL LETTER U WITH DIAERESIS AND CARON;Ll;0;L;00FC 030C;;;;N;LATIN SMALL LETTER U DIAERESIS HACEK;;01D9;;01D9
-01DB;LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE;Lu;0;L;00DC 0300;;;;N;LATIN CAPITAL LETTER U DIAERESIS GRAVE;;;01DC;
-01DC;LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE;Ll;0;L;00FC 0300;;;;N;LATIN SMALL LETTER U DIAERESIS GRAVE;;01DB;;01DB
-01DD;LATIN SMALL LETTER TURNED E;Ll;0;L;;;;;N;;;018E;;018E
-01DE;LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON;Lu;0;L;00C4 0304;;;;N;LATIN CAPITAL LETTER A DIAERESIS MACRON;;;01DF;
-01DF;LATIN SMALL LETTER A WITH DIAERESIS AND MACRON;Ll;0;L;00E4 0304;;;;N;LATIN SMALL LETTER A DIAERESIS MACRON;;01DE;;01DE
-01E0;LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON;Lu;0;L;0226 0304;;;;N;LATIN CAPITAL LETTER A DOT MACRON;;;01E1;
-01E1;LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON;Ll;0;L;0227 0304;;;;N;LATIN SMALL LETTER A DOT MACRON;;01E0;;01E0
-01E2;LATIN CAPITAL LETTER AE WITH MACRON;Lu;0;L;00C6 0304;;;;N;LATIN CAPITAL LETTER A E MACRON;;;01E3;
-01E3;LATIN SMALL LETTER AE WITH MACRON;Ll;0;L;00E6 0304;;;;N;LATIN SMALL LETTER A E MACRON;;01E2;;01E2
-01E4;LATIN CAPITAL LETTER G WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G BAR;;;01E5;
-01E5;LATIN SMALL LETTER G WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER G BAR;;01E4;;01E4
-01E6;LATIN CAPITAL LETTER G WITH CARON;Lu;0;L;0047 030C;;;;N;LATIN CAPITAL LETTER G HACEK;;;01E7;
-01E7;LATIN SMALL LETTER G WITH CARON;Ll;0;L;0067 030C;;;;N;LATIN SMALL LETTER G HACEK;;01E6;;01E6
-01E8;LATIN CAPITAL LETTER K WITH CARON;Lu;0;L;004B 030C;;;;N;LATIN CAPITAL LETTER K HACEK;;;01E9;
-01E9;LATIN SMALL LETTER K WITH CARON;Ll;0;L;006B 030C;;;;N;LATIN SMALL LETTER K HACEK;;01E8;;01E8
-01EA;LATIN CAPITAL LETTER O WITH OGONEK;Lu;0;L;004F 0328;;;;N;LATIN CAPITAL LETTER O OGONEK;;;01EB;
-01EB;LATIN SMALL LETTER O WITH OGONEK;Ll;0;L;006F 0328;;;;N;LATIN SMALL LETTER O OGONEK;;01EA;;01EA
-01EC;LATIN CAPITAL LETTER O WITH OGONEK AND MACRON;Lu;0;L;01EA 0304;;;;N;LATIN CAPITAL LETTER O OGONEK MACRON;;;01ED;
-01ED;LATIN SMALL LETTER O WITH OGONEK AND MACRON;Ll;0;L;01EB 0304;;;;N;LATIN SMALL LETTER O OGONEK MACRON;;01EC;;01EC
-01EE;LATIN CAPITAL LETTER EZH WITH CARON;Lu;0;L;01B7 030C;;;;N;LATIN CAPITAL LETTER YOGH HACEK;;;01EF;
-01EF;LATIN SMALL LETTER EZH WITH CARON;Ll;0;L;0292 030C;;;;N;LATIN SMALL LETTER YOGH HACEK;;01EE;;01EE
-01F0;LATIN SMALL LETTER J WITH CARON;Ll;0;L;006A 030C;;;;N;LATIN SMALL LETTER J HACEK;;;;
-01F1;LATIN CAPITAL LETTER DZ;Lu;0;L;<compat> 0044 005A;;;;N;;;;01F3;01F2
-01F2;LATIN CAPITAL LETTER D WITH SMALL LETTER Z;Lt;0;L;<compat> 0044 007A;;;;N;;;01F1;01F3;01F2
-01F3;LATIN SMALL LETTER DZ;Ll;0;L;<compat> 0064 007A;;;;N;;;01F1;;01F2
-01F4;LATIN CAPITAL LETTER G WITH ACUTE;Lu;0;L;0047 0301;;;;N;;;;01F5;
-01F5;LATIN SMALL LETTER G WITH ACUTE;Ll;0;L;0067 0301;;;;N;;;01F4;;01F4
-01F6;LATIN CAPITAL LETTER HWAIR;Lu;0;L;;;;;N;;;;0195;
-01F7;LATIN CAPITAL LETTER WYNN;Lu;0;L;;;;;N;;;;01BF;
-01F8;LATIN CAPITAL LETTER N WITH GRAVE;Lu;0;L;004E 0300;;;;N;;;;01F9;
-01F9;LATIN SMALL LETTER N WITH GRAVE;Ll;0;L;006E 0300;;;;N;;;01F8;;01F8
-01FA;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE;Lu;0;L;00C5 0301;;;;N;;;;01FB;
-01FB;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE;Ll;0;L;00E5 0301;;;;N;;;01FA;;01FA
-01FC;LATIN CAPITAL LETTER AE WITH ACUTE;Lu;0;L;00C6 0301;;;;N;;;;01FD;
-01FD;LATIN SMALL LETTER AE WITH ACUTE;Ll;0;L;00E6 0301;;;;N;;;01FC;;01FC
-01FE;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE;Lu;0;L;00D8 0301;;;;N;;;;01FF;
-01FF;LATIN SMALL LETTER O WITH STROKE AND ACUTE;Ll;0;L;00F8 0301;;;;N;;;01FE;;01FE
-0200;LATIN CAPITAL LETTER A WITH DOUBLE GRAVE;Lu;0;L;0041 030F;;;;N;;;;0201;
-0201;LATIN SMALL LETTER A WITH DOUBLE GRAVE;Ll;0;L;0061 030F;;;;N;;;0200;;0200
-0202;LATIN CAPITAL LETTER A WITH INVERTED BREVE;Lu;0;L;0041 0311;;;;N;;;;0203;
-0203;LATIN SMALL LETTER A WITH INVERTED BREVE;Ll;0;L;0061 0311;;;;N;;;0202;;0202
-0204;LATIN CAPITAL LETTER E WITH DOUBLE GRAVE;Lu;0;L;0045 030F;;;;N;;;;0205;
-0205;LATIN SMALL LETTER E WITH DOUBLE GRAVE;Ll;0;L;0065 030F;;;;N;;;0204;;0204
-0206;LATIN CAPITAL LETTER E WITH INVERTED BREVE;Lu;0;L;0045 0311;;;;N;;;;0207;
-0207;LATIN SMALL LETTER E WITH INVERTED BREVE;Ll;0;L;0065 0311;;;;N;;;0206;;0206
-0208;LATIN CAPITAL LETTER I WITH DOUBLE GRAVE;Lu;0;L;0049 030F;;;;N;;;;0209;
-0209;LATIN SMALL LETTER I WITH DOUBLE GRAVE;Ll;0;L;0069 030F;;;;N;;;0208;;0208
-020A;LATIN CAPITAL LETTER I WITH INVERTED BREVE;Lu;0;L;0049 0311;;;;N;;;;020B;
-020B;LATIN SMALL LETTER I WITH INVERTED BREVE;Ll;0;L;0069 0311;;;;N;;;020A;;020A
-020C;LATIN CAPITAL LETTER O WITH DOUBLE GRAVE;Lu;0;L;004F 030F;;;;N;;;;020D;
-020D;LATIN SMALL LETTER O WITH DOUBLE GRAVE;Ll;0;L;006F 030F;;;;N;;;020C;;020C
-020E;LATIN CAPITAL LETTER O WITH INVERTED BREVE;Lu;0;L;004F 0311;;;;N;;;;020F;
-020F;LATIN SMALL LETTER O WITH INVERTED BREVE;Ll;0;L;006F 0311;;;;N;;;020E;;020E
-0210;LATIN CAPITAL LETTER R WITH DOUBLE GRAVE;Lu;0;L;0052 030F;;;;N;;;;0211;
-0211;LATIN SMALL LETTER R WITH DOUBLE GRAVE;Ll;0;L;0072 030F;;;;N;;;0210;;0210
-0212;LATIN CAPITAL LETTER R WITH INVERTED BREVE;Lu;0;L;0052 0311;;;;N;;;;0213;
-0213;LATIN SMALL LETTER R WITH INVERTED BREVE;Ll;0;L;0072 0311;;;;N;;;0212;;0212
-0214;LATIN CAPITAL LETTER U WITH DOUBLE GRAVE;Lu;0;L;0055 030F;;;;N;;;;0215;
-0215;LATIN SMALL LETTER U WITH DOUBLE GRAVE;Ll;0;L;0075 030F;;;;N;;;0214;;0214
-0216;LATIN CAPITAL LETTER U WITH INVERTED BREVE;Lu;0;L;0055 0311;;;;N;;;;0217;
-0217;LATIN SMALL LETTER U WITH INVERTED BREVE;Ll;0;L;0075 0311;;;;N;;;0216;;0216
-0218;LATIN CAPITAL LETTER S WITH COMMA BELOW;Lu;0;L;0053 0326;;;;N;;;;0219;
-0219;LATIN SMALL LETTER S WITH COMMA BELOW;Ll;0;L;0073 0326;;;;N;;;0218;;0218
-021A;LATIN CAPITAL LETTER T WITH COMMA BELOW;Lu;0;L;0054 0326;;;;N;;;;021B;
-021B;LATIN SMALL LETTER T WITH COMMA BELOW;Ll;0;L;0074 0326;;;;N;;;021A;;021A
-021C;LATIN CAPITAL LETTER YOGH;Lu;0;L;;;;;N;;;;021D;
-021D;LATIN SMALL LETTER YOGH;Ll;0;L;;;;;N;;;021C;;021C
-021E;LATIN CAPITAL LETTER H WITH CARON;Lu;0;L;0048 030C;;;;N;;;;021F;
-021F;LATIN SMALL LETTER H WITH CARON;Ll;0;L;0068 030C;;;;N;;;021E;;021E
-0220;LATIN CAPITAL LETTER N WITH LONG RIGHT LEG;Lu;0;L;;;;;N;;;;019E;
-0221;LATIN SMALL LETTER D WITH CURL;Ll;0;L;;;;;N;;;;;
-0222;LATIN CAPITAL LETTER OU;Lu;0;L;;;;;N;;;;0223;
-0223;LATIN SMALL LETTER OU;Ll;0;L;;;;;N;;;0222;;0222
-0224;LATIN CAPITAL LETTER Z WITH HOOK;Lu;0;L;;;;;N;;;;0225;
-0225;LATIN SMALL LETTER Z WITH HOOK;Ll;0;L;;;;;N;;;0224;;0224
-0226;LATIN CAPITAL LETTER A WITH DOT ABOVE;Lu;0;L;0041 0307;;;;N;;;;0227;
-0227;LATIN SMALL LETTER A WITH DOT ABOVE;Ll;0;L;0061 0307;;;;N;;;0226;;0226
-0228;LATIN CAPITAL LETTER E WITH CEDILLA;Lu;0;L;0045 0327;;;;N;;;;0229;
-0229;LATIN SMALL LETTER E WITH CEDILLA;Ll;0;L;0065 0327;;;;N;;;0228;;0228
-022A;LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON;Lu;0;L;00D6 0304;;;;N;;;;022B;
-022B;LATIN SMALL LETTER O WITH DIAERESIS AND MACRON;Ll;0;L;00F6 0304;;;;N;;;022A;;022A
-022C;LATIN CAPITAL LETTER O WITH TILDE AND MACRON;Lu;0;L;00D5 0304;;;;N;;;;022D;
-022D;LATIN SMALL LETTER O WITH TILDE AND MACRON;Ll;0;L;00F5 0304;;;;N;;;022C;;022C
-022E;LATIN CAPITAL LETTER O WITH DOT ABOVE;Lu;0;L;004F 0307;;;;N;;;;022F;
-022F;LATIN SMALL LETTER O WITH DOT ABOVE;Ll;0;L;006F 0307;;;;N;;;022E;;022E
-0230;LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON;Lu;0;L;022E 0304;;;;N;;;;0231;
-0231;LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON;Ll;0;L;022F 0304;;;;N;;;0230;;0230
-0232;LATIN CAPITAL LETTER Y WITH MACRON;Lu;0;L;0059 0304;;;;N;;;;0233;
-0233;LATIN SMALL LETTER Y WITH MACRON;Ll;0;L;0079 0304;;;;N;;;0232;;0232
-0234;LATIN SMALL LETTER L WITH CURL;Ll;0;L;;;;;N;;;;;
-0235;LATIN SMALL LETTER N WITH CURL;Ll;0;L;;;;;N;;;;;
-0236;LATIN SMALL LETTER T WITH CURL;Ll;0;L;;;;;N;;;;;
-0237;LATIN SMALL LETTER DOTLESS J;Ll;0;L;;;;;N;;;;;
-0238;LATIN SMALL LETTER DB DIGRAPH;Ll;0;L;;;;;N;;;;;
-0239;LATIN SMALL LETTER QP DIGRAPH;Ll;0;L;;;;;N;;;;;
-023A;LATIN CAPITAL LETTER A WITH STROKE;Lu;0;L;;;;;N;;;;2C65;
-023B;LATIN CAPITAL LETTER C WITH STROKE;Lu;0;L;;;;;N;;;;023C;
-023C;LATIN SMALL LETTER C WITH STROKE;Ll;0;L;;;;;N;;;023B;;023B
-023D;LATIN CAPITAL LETTER L WITH BAR;Lu;0;L;;;;;N;;;;019A;
-023E;LATIN CAPITAL LETTER T WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;2C66;
-023F;LATIN SMALL LETTER S WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7E;;2C7E
-0240;LATIN SMALL LETTER Z WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7F;;2C7F
-0241;LATIN CAPITAL LETTER GLOTTAL STOP;Lu;0;L;;;;;N;;;;0242;
-0242;LATIN SMALL LETTER GLOTTAL STOP;Ll;0;L;;;;;N;;;0241;;0241
-0243;LATIN CAPITAL LETTER B WITH STROKE;Lu;0;L;;;;;N;;;;0180;
-0244;LATIN CAPITAL LETTER U BAR;Lu;0;L;;;;;N;;;;0289;
-0245;LATIN CAPITAL LETTER TURNED V;Lu;0;L;;;;;N;;;;028C;
-0246;LATIN CAPITAL LETTER E WITH STROKE;Lu;0;L;;;;;N;;;;0247;
-0247;LATIN SMALL LETTER E WITH STROKE;Ll;0;L;;;;;N;;;0246;;0246
-0248;LATIN CAPITAL LETTER J WITH STROKE;Lu;0;L;;;;;N;;;;0249;
-0249;LATIN SMALL LETTER J WITH STROKE;Ll;0;L;;;;;N;;;0248;;0248
-024A;LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL;Lu;0;L;;;;;N;;;;024B;
-024B;LATIN SMALL LETTER Q WITH HOOK TAIL;Ll;0;L;;;;;N;;;024A;;024A
-024C;LATIN CAPITAL LETTER R WITH STROKE;Lu;0;L;;;;;N;;;;024D;
-024D;LATIN SMALL LETTER R WITH STROKE;Ll;0;L;;;;;N;;;024C;;024C
-024E;LATIN CAPITAL LETTER Y WITH STROKE;Lu;0;L;;;;;N;;;;024F;
-024F;LATIN SMALL LETTER Y WITH STROKE;Ll;0;L;;;;;N;;;024E;;024E
-0250;LATIN SMALL LETTER TURNED A;Ll;0;L;;;;;N;;;2C6F;;2C6F
-0251;LATIN SMALL LETTER ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT A;;2C6D;;2C6D
-0252;LATIN SMALL LETTER TURNED ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED SCRIPT A;;2C70;;2C70
-0253;LATIN SMALL LETTER B WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER B HOOK;;0181;;0181
-0254;LATIN SMALL LETTER OPEN O;Ll;0;L;;;;;N;;;0186;;0186
-0255;LATIN SMALL LETTER C WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER C CURL;;;;
-0256;LATIN SMALL LETTER D WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER D RETROFLEX HOOK;;0189;;0189
-0257;LATIN SMALL LETTER D WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER D HOOK;;018A;;018A
-0258;LATIN SMALL LETTER REVERSED E;Ll;0;L;;;;;N;;;;;
-0259;LATIN SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;018F;;018F
-025A;LATIN SMALL LETTER SCHWA WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCHWA HOOK;;;;
-025B;LATIN SMALL LETTER OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER EPSILON;;0190;;0190
-025C;LATIN SMALL LETTER REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON;;;;
-025D;LATIN SMALL LETTER REVERSED OPEN E WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON HOOK;;;;
-025E;LATIN SMALL LETTER CLOSED REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED REVERSED EPSILON;;;;
-025F;LATIN SMALL LETTER DOTLESS J WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR;;;;
-0260;LATIN SMALL LETTER G WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER G HOOK;;0193;;0193
-0261;LATIN SMALL LETTER SCRIPT G;Ll;0;L;;;;;N;;;;;
-0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;;
-0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194
-0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;;;
-0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;A78D;;A78D
-0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;A7AA;;A7AA
-0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;;
-0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197
-0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196
-026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;;;
-026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;2C62;;2C62
-026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;;;
-026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;;
-026E;LATIN SMALL LETTER LEZH;Ll;0;L;;;;;N;LATIN SMALL LETTER L YOGH;;;;
-026F;LATIN SMALL LETTER TURNED M;Ll;0;L;;;;;N;;;019C;;019C
-0270;LATIN SMALL LETTER TURNED M WITH LONG LEG;Ll;0;L;;;;;N;;;;;
-0271;LATIN SMALL LETTER M WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER M HOOK;;2C6E;;2C6E
-0272;LATIN SMALL LETTER N WITH LEFT HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N HOOK;;019D;;019D
-0273;LATIN SMALL LETTER N WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N RETROFLEX HOOK;;;;
-0274;LATIN LETTER SMALL CAPITAL N;Ll;0;L;;;;;N;;;;;
-0275;LATIN SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;019F;;019F
-0276;LATIN LETTER SMALL CAPITAL OE;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL O E;;;;
-0277;LATIN SMALL LETTER CLOSED OMEGA;Ll;0;L;;;;;N;;;;;
-0278;LATIN SMALL LETTER PHI;Ll;0;L;;;;;N;;;;;
-0279;LATIN SMALL LETTER TURNED R;Ll;0;L;;;;;N;;;;;
-027A;LATIN SMALL LETTER TURNED R WITH LONG LEG;Ll;0;L;;;;;N;;;;;
-027B;LATIN SMALL LETTER TURNED R WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED R HOOK;;;;
-027C;LATIN SMALL LETTER R WITH LONG LEG;Ll;0;L;;;;;N;;;;;
-027D;LATIN SMALL LETTER R WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER R HOOK;;2C64;;2C64
-027E;LATIN SMALL LETTER R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER FISHHOOK R;;;;
-027F;LATIN SMALL LETTER REVERSED R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED FISHHOOK R;;;;
-0280;LATIN LETTER SMALL CAPITAL R;Ll;0;L;;;;;N;;;01A6;;01A6
-0281;LATIN LETTER SMALL CAPITAL INVERTED R;Ll;0;L;;;;;N;;;;;
-0282;LATIN SMALL LETTER S WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER S HOOK;;;;
-0283;LATIN SMALL LETTER ESH;Ll;0;L;;;;;N;;;01A9;;01A9
-0284;LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR HOOK;;;;
-0285;LATIN SMALL LETTER SQUAT REVERSED ESH;Ll;0;L;;;;;N;;;;;
-0286;LATIN SMALL LETTER ESH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER ESH CURL;;;;
-0287;LATIN SMALL LETTER TURNED T;Ll;0;L;;;;;N;;;;;
-0288;LATIN SMALL LETTER T WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T RETROFLEX HOOK;;01AE;;01AE
-0289;LATIN SMALL LETTER U BAR;Ll;0;L;;;;;N;;;0244;;0244
-028A;LATIN SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;01B1;;01B1
-028B;LATIN SMALL LETTER V WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT V;;01B2;;01B2
-028C;LATIN SMALL LETTER TURNED V;Ll;0;L;;;;;N;;;0245;;0245
-028D;LATIN SMALL LETTER TURNED W;Ll;0;L;;;;;N;;;;;
-028E;LATIN SMALL LETTER TURNED Y;Ll;0;L;;;;;N;;;;;
-028F;LATIN LETTER SMALL CAPITAL Y;Ll;0;L;;;;;N;;;;;
-0290;LATIN SMALL LETTER Z WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Z RETROFLEX HOOK;;;;
-0291;LATIN SMALL LETTER Z WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER Z CURL;;;;
-0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7
-0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;;
-0294;LATIN LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;;
-0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;;
-0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;;
-0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;;
-0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;;
-0299;LATIN LETTER SMALL CAPITAL B;Ll;0;L;;;;;N;;;;;
-029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;;
-029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;;
-029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;;
-029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;;;
-029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;;;
-029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;;
-02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;;
-02A1;LATIN LETTER GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER GLOTTAL STOP BAR;;;;
-02A2;LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP BAR;;;;
-02A3;LATIN SMALL LETTER DZ DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z;;;;
-02A4;LATIN SMALL LETTER DEZH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D YOGH;;;;
-02A5;LATIN SMALL LETTER DZ DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z CURL;;;;
-02A6;LATIN SMALL LETTER TS DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T S;;;;
-02A7;LATIN SMALL LETTER TESH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T ESH;;;;
-02A8;LATIN SMALL LETTER TC DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER T C CURL;;;;
-02A9;LATIN SMALL LETTER FENG DIGRAPH;Ll;0;L;;;;;N;;;;;
-02AA;LATIN SMALL LETTER LS DIGRAPH;Ll;0;L;;;;;N;;;;;
-02AB;LATIN SMALL LETTER LZ DIGRAPH;Ll;0;L;;;;;N;;;;;
-02AC;LATIN LETTER BILABIAL PERCUSSIVE;Ll;0;L;;;;;N;;;;;
-02AD;LATIN LETTER BIDENTAL PERCUSSIVE;Ll;0;L;;;;;N;;;;;
-02AE;LATIN SMALL LETTER TURNED H WITH FISHHOOK;Ll;0;L;;;;;N;;;;;
-02AF;LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL;Ll;0;L;;;;;N;;;;;
-02B0;MODIFIER LETTER SMALL H;Lm;0;L;<super> 0068;;;;N;;;;;
-02B1;MODIFIER LETTER SMALL H WITH HOOK;Lm;0;L;<super> 0266;;;;N;MODIFIER LETTER SMALL H HOOK;;;;
-02B2;MODIFIER LETTER SMALL J;Lm;0;L;<super> 006A;;;;N;;;;;
-02B3;MODIFIER LETTER SMALL R;Lm;0;L;<super> 0072;;;;N;;;;;
-02B4;MODIFIER LETTER SMALL TURNED R;Lm;0;L;<super> 0279;;;;N;;;;;
-02B5;MODIFIER LETTER SMALL TURNED R WITH HOOK;Lm;0;L;<super> 027B;;;;N;MODIFIER LETTER SMALL TURNED R HOOK;;;;
-02B6;MODIFIER LETTER SMALL CAPITAL INVERTED R;Lm;0;L;<super> 0281;;;;N;;;;;
-02B7;MODIFIER LETTER SMALL W;Lm;0;L;<super> 0077;;;;N;;;;;
-02B8;MODIFIER LETTER SMALL Y;Lm;0;L;<super> 0079;;;;N;;;;;
-02B9;MODIFIER LETTER PRIME;Lm;0;ON;;;;;N;;;;;
-02BA;MODIFIER LETTER DOUBLE PRIME;Lm;0;ON;;;;;N;;;;;
-02BB;MODIFIER LETTER TURNED COMMA;Lm;0;L;;;;;N;;;;;
-02BC;MODIFIER LETTER APOSTROPHE;Lm;0;L;;;;;N;;;;;
-02BD;MODIFIER LETTER REVERSED COMMA;Lm;0;L;;;;;N;;;;;
-02BE;MODIFIER LETTER RIGHT HALF RING;Lm;0;L;;;;;N;;;;;
-02BF;MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;;
-02C0;MODIFIER LETTER GLOTTAL STOP;Lm;0;L;;;;;N;;;;;
-02C1;MODIFIER LETTER REVERSED GLOTTAL STOP;Lm;0;L;;;;;N;;;;;
-02C2;MODIFIER LETTER LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;;
-02C3;MODIFIER LETTER RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;;
-02C4;MODIFIER LETTER UP ARROWHEAD;Sk;0;ON;;;;;N;;;;;
-02C5;MODIFIER LETTER DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;;
-02C6;MODIFIER LETTER CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER CIRCUMFLEX;;;;
-02C7;CARON;Lm;0;ON;;;;;N;MODIFIER LETTER HACEK;;;;
-02C8;MODIFIER LETTER VERTICAL LINE;Lm;0;ON;;;;;N;;;;;
-02C9;MODIFIER LETTER MACRON;Lm;0;ON;;;;;N;;;;;
-02CA;MODIFIER LETTER ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER ACUTE;;;;
-02CB;MODIFIER LETTER GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER GRAVE;;;;
-02CC;MODIFIER LETTER LOW VERTICAL LINE;Lm;0;ON;;;;;N;;;;;
-02CD;MODIFIER LETTER LOW MACRON;Lm;0;ON;;;;;N;;;;;
-02CE;MODIFIER LETTER LOW GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW GRAVE;;;;
-02CF;MODIFIER LETTER LOW ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW ACUTE;;;;
-02D0;MODIFIER LETTER TRIANGULAR COLON;Lm;0;L;;;;;N;;;;;
-02D1;MODIFIER LETTER HALF TRIANGULAR COLON;Lm;0;L;;;;;N;;;;;
-02D2;MODIFIER LETTER CENTRED RIGHT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED RIGHT HALF RING;;;;
-02D3;MODIFIER LETTER CENTRED LEFT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED LEFT HALF RING;;;;
-02D4;MODIFIER LETTER UP TACK;Sk;0;ON;;;;;N;;;;;
-02D5;MODIFIER LETTER DOWN TACK;Sk;0;ON;;;;;N;;;;;
-02D6;MODIFIER LETTER PLUS SIGN;Sk;0;ON;;;;;N;;;;;
-02D7;MODIFIER LETTER MINUS SIGN;Sk;0;ON;;;;;N;;;;;
-02D8;BREVE;Sk;0;ON;<compat> 0020 0306;;;;N;SPACING BREVE;;;;
-02D9;DOT ABOVE;Sk;0;ON;<compat> 0020 0307;;;;N;SPACING DOT ABOVE;;;;
-02DA;RING ABOVE;Sk;0;ON;<compat> 0020 030A;;;;N;SPACING RING ABOVE;;;;
-02DB;OGONEK;Sk;0;ON;<compat> 0020 0328;;;;N;SPACING OGONEK;;;;
-02DC;SMALL TILDE;Sk;0;ON;<compat> 0020 0303;;;;N;SPACING TILDE;;;;
-02DD;DOUBLE ACUTE ACCENT;Sk;0;ON;<compat> 0020 030B;;;;N;SPACING DOUBLE ACUTE;;;;
-02DE;MODIFIER LETTER RHOTIC HOOK;Sk;0;ON;;;;;N;;;;;
-02DF;MODIFIER LETTER CROSS ACCENT;Sk;0;ON;;;;;N;;;;;
-02E0;MODIFIER LETTER SMALL GAMMA;Lm;0;L;<super> 0263;;;;N;;;;;
-02E1;MODIFIER LETTER SMALL L;Lm;0;L;<super> 006C;;;;N;;;;;
-02E2;MODIFIER LETTER SMALL S;Lm;0;L;<super> 0073;;;;N;;;;;
-02E3;MODIFIER LETTER SMALL X;Lm;0;L;<super> 0078;;;;N;;;;;
-02E4;MODIFIER LETTER SMALL REVERSED GLOTTAL STOP;Lm;0;L;<super> 0295;;;;N;;;;;
-02E5;MODIFIER LETTER EXTRA-HIGH TONE BAR;Sk;0;ON;;;;;N;;;;;
-02E6;MODIFIER LETTER HIGH TONE BAR;Sk;0;ON;;;;;N;;;;;
-02E7;MODIFIER LETTER MID TONE BAR;Sk;0;ON;;;;;N;;;;;
-02E8;MODIFIER LETTER LOW TONE BAR;Sk;0;ON;;;;;N;;;;;
-02E9;MODIFIER LETTER EXTRA-LOW TONE BAR;Sk;0;ON;;;;;N;;;;;
-02EA;MODIFIER LETTER YIN DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;;
-02EB;MODIFIER LETTER YANG DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;;
-02EC;MODIFIER LETTER VOICING;Lm;0;ON;;;;;N;;;;;
-02ED;MODIFIER LETTER UNASPIRATED;Sk;0;ON;;;;;N;;;;;
-02EE;MODIFIER LETTER DOUBLE APOSTROPHE;Lm;0;L;;;;;N;;;;;
-02EF;MODIFIER LETTER LOW DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;;
-02F0;MODIFIER LETTER LOW UP ARROWHEAD;Sk;0;ON;;;;;N;;;;;
-02F1;MODIFIER LETTER LOW LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;;
-02F2;MODIFIER LETTER LOW RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;;
-02F3;MODIFIER LETTER LOW RING;Sk;0;ON;;;;;N;;;;;
-02F4;MODIFIER LETTER MIDDLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;;
-02F5;MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;;
-02F6;MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT;Sk;0;ON;;;;;N;;;;;
-02F7;MODIFIER LETTER LOW TILDE;Sk;0;ON;;;;;N;;;;;
-02F8;MODIFIER LETTER RAISED COLON;Sk;0;ON;;;;;N;;;;;
-02F9;MODIFIER LETTER BEGIN HIGH TONE;Sk;0;ON;;;;;N;;;;;
-02FA;MODIFIER LETTER END HIGH TONE;Sk;0;ON;;;;;N;;;;;
-02FB;MODIFIER LETTER BEGIN LOW TONE;Sk;0;ON;;;;;N;;;;;
-02FC;MODIFIER LETTER END LOW TONE;Sk;0;ON;;;;;N;;;;;
-02FD;MODIFIER LETTER SHELF;Sk;0;ON;;;;;N;;;;;
-02FE;MODIFIER LETTER OPEN SHELF;Sk;0;ON;;;;;N;;;;;
-02FF;MODIFIER LETTER LOW LEFT ARROW;Sk;0;ON;;;;;N;;;;;
-0300;COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;;
-0301;COMBINING ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING ACUTE;;;;
-0302;COMBINING CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;NON-SPACING CIRCUMFLEX;;;;
-0303;COMBINING TILDE;Mn;230;NSM;;;;;N;NON-SPACING TILDE;;;;
-0304;COMBINING MACRON;Mn;230;NSM;;;;;N;NON-SPACING MACRON;;;;
-0305;COMBINING OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING OVERSCORE;;;;
-0306;COMBINING BREVE;Mn;230;NSM;;;;;N;NON-SPACING BREVE;;;;
-0307;COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOT ABOVE;;;;
-0308;COMBINING DIAERESIS;Mn;230;NSM;;;;;N;NON-SPACING DIAERESIS;;;;
-0309;COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;NON-SPACING HOOK ABOVE;;;;
-030A;COMBINING RING ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RING ABOVE;;;;
-030B;COMBINING DOUBLE ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE ACUTE;;;;
-030C;COMBINING CARON;Mn;230;NSM;;;;;N;NON-SPACING HACEK;;;;
-030D;COMBINING VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL LINE ABOVE;;;;
-030E;COMBINING DOUBLE VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE VERTICAL LINE ABOVE;;;;
-030F;COMBINING DOUBLE GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE GRAVE;;;;
-0310;COMBINING CANDRABINDU;Mn;230;NSM;;;;;N;NON-SPACING CANDRABINDU;;;;
-0311;COMBINING INVERTED BREVE;Mn;230;NSM;;;;;N;NON-SPACING INVERTED BREVE;;;;
-0312;COMBINING TURNED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING TURNED COMMA ABOVE;;;;
-0313;COMBINING COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING COMMA ABOVE;;;;
-0314;COMBINING REVERSED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING REVERSED COMMA ABOVE;;;;
-0315;COMBINING COMMA ABOVE RIGHT;Mn;232;NSM;;;;;N;NON-SPACING COMMA ABOVE RIGHT;;;;
-0316;COMBINING GRAVE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING GRAVE BELOW;;;;
-0317;COMBINING ACUTE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING ACUTE BELOW;;;;
-0318;COMBINING LEFT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT TACK BELOW;;;;
-0319;COMBINING RIGHT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT TACK BELOW;;;;
-031A;COMBINING LEFT ANGLE ABOVE;Mn;232;NSM;;;;;N;NON-SPACING LEFT ANGLE ABOVE;;;;
-031B;COMBINING HORN;Mn;216;NSM;;;;;N;NON-SPACING HORN;;;;
-031C;COMBINING LEFT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT HALF RING BELOW;;;;
-031D;COMBINING UP TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING UP TACK BELOW;;;;
-031E;COMBINING DOWN TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOWN TACK BELOW;;;;
-031F;COMBINING PLUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING PLUS SIGN BELOW;;;;
-0320;COMBINING MINUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING MINUS SIGN BELOW;;;;
-0321;COMBINING PALATALIZED HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING PALATALIZED HOOK BELOW;;;;
-0322;COMBINING RETROFLEX HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING RETROFLEX HOOK BELOW;;;;
-0323;COMBINING DOT BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOT BELOW;;;;
-0324;COMBINING DIAERESIS BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE DOT BELOW;;;;
-0325;COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;;
-0326;COMBINING COMMA BELOW;Mn;220;NSM;;;;;N;NON-SPACING COMMA BELOW;;;;
-0327;COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;;
-0328;COMBINING OGONEK;Mn;202;NSM;;;;;N;NON-SPACING OGONEK;;;;
-0329;COMBINING VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;NON-SPACING VERTICAL LINE BELOW;;;;
-032A;COMBINING BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BRIDGE BELOW;;;;
-032B;COMBINING INVERTED DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED DOUBLE ARCH BELOW;;;;
-032C;COMBINING CARON BELOW;Mn;220;NSM;;;;;N;NON-SPACING HACEK BELOW;;;;
-032D;COMBINING CIRCUMFLEX ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING CIRCUMFLEX BELOW;;;;
-032E;COMBINING BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BREVE BELOW;;;;
-032F;COMBINING INVERTED BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BREVE BELOW;;;;
-0330;COMBINING TILDE BELOW;Mn;220;NSM;;;;;N;NON-SPACING TILDE BELOW;;;;
-0331;COMBINING MACRON BELOW;Mn;220;NSM;;;;;N;NON-SPACING MACRON BELOW;;;;
-0332;COMBINING LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING UNDERSCORE;;;;
-0333;COMBINING DOUBLE LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE UNDERSCORE;;;;
-0334;COMBINING TILDE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING TILDE OVERLAY;;;;
-0335;COMBINING SHORT STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT BAR OVERLAY;;;;
-0336;COMBINING LONG STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG BAR OVERLAY;;;;
-0337;COMBINING SHORT SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT SLASH OVERLAY;;;;
-0338;COMBINING LONG SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG SLASH OVERLAY;;;;
-0339;COMBINING RIGHT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT HALF RING BELOW;;;;
-033A;COMBINING INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BRIDGE BELOW;;;;
-033B;COMBINING SQUARE BELOW;Mn;220;NSM;;;;;N;NON-SPACING SQUARE BELOW;;;;
-033C;COMBINING SEAGULL BELOW;Mn;220;NSM;;;;;N;NON-SPACING SEAGULL BELOW;;;;
-033D;COMBINING X ABOVE;Mn;230;NSM;;;;;N;NON-SPACING X ABOVE;;;;
-033E;COMBINING VERTICAL TILDE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL TILDE;;;;
-033F;COMBINING DOUBLE OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE OVERSCORE;;;;
-0340;COMBINING GRAVE TONE MARK;Mn;230;NSM;0300;;;;N;NON-SPACING GRAVE TONE MARK;;;;
-0341;COMBINING ACUTE TONE MARK;Mn;230;NSM;0301;;;;N;NON-SPACING ACUTE TONE MARK;;;;
-0342;COMBINING GREEK PERISPOMENI;Mn;230;NSM;;;;;N;;;;;
-0343;COMBINING GREEK KORONIS;Mn;230;NSM;0313;;;;N;;;;;
-0344;COMBINING GREEK DIALYTIKA TONOS;Mn;230;NSM;0308 0301;;;;N;GREEK NON-SPACING DIAERESIS TONOS;;;;
-0345;COMBINING GREEK YPOGEGRAMMENI;Mn;240;NSM;;;;;N;GREEK NON-SPACING IOTA BELOW;;0399;;0399
-0346;COMBINING BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;;
-0347;COMBINING EQUALS SIGN BELOW;Mn;220;NSM;;;;;N;;;;;
-0348;COMBINING DOUBLE VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;;;;;
-0349;COMBINING LEFT ANGLE BELOW;Mn;220;NSM;;;;;N;;;;;
-034A;COMBINING NOT TILDE ABOVE;Mn;230;NSM;;;;;N;;;;;
-034B;COMBINING HOMOTHETIC ABOVE;Mn;230;NSM;;;;;N;;;;;
-034C;COMBINING ALMOST EQUAL TO ABOVE;Mn;230;NSM;;;;;N;;;;;
-034D;COMBINING LEFT RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;;
-034E;COMBINING UPWARDS ARROW BELOW;Mn;220;NSM;;;;;N;;;;;
-034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;;
-0350;COMBINING RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;;
-0351;COMBINING LEFT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;;
-0352;COMBINING FERMATA;Mn;230;NSM;;;;;N;;;;;
-0353;COMBINING X BELOW;Mn;220;NSM;;;;;N;;;;;
-0354;COMBINING LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
-0355;COMBINING RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
-0356;COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
-0357;COMBINING RIGHT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;;
-0358;COMBINING DOT ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;;
-0359;COMBINING ASTERISK BELOW;Mn;220;NSM;;;;;N;;;;;
-035A;COMBINING DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;;
-035B;COMBINING ZIGZAG ABOVE;Mn;230;NSM;;;;;N;;;;;
-035C;COMBINING DOUBLE BREVE BELOW;Mn;233;NSM;;;;;N;;;;;
-035D;COMBINING DOUBLE BREVE;Mn;234;NSM;;;;;N;;;;;
-035E;COMBINING DOUBLE MACRON;Mn;234;NSM;;;;;N;;;;;
-035F;COMBINING DOUBLE MACRON BELOW;Mn;233;NSM;;;;;N;;;;;
-0360;COMBINING DOUBLE TILDE;Mn;234;NSM;;;;;N;;;;;
-0361;COMBINING DOUBLE INVERTED BREVE;Mn;234;NSM;;;;;N;;;;;
-0362;COMBINING DOUBLE RIGHTWARDS ARROW BELOW;Mn;233;NSM;;;;;N;;;;;
-0363;COMBINING LATIN SMALL LETTER A;Mn;230;NSM;;;;;N;;;;;
-0364;COMBINING LATIN SMALL LETTER E;Mn;230;NSM;;;;;N;;;;;
-0365;COMBINING LATIN SMALL LETTER I;Mn;230;NSM;;;;;N;;;;;
-0366;COMBINING LATIN SMALL LETTER O;Mn;230;NSM;;;;;N;;;;;
-0367;COMBINING LATIN SMALL LETTER U;Mn;230;NSM;;;;;N;;;;;
-0368;COMBINING LATIN SMALL LETTER C;Mn;230;NSM;;;;;N;;;;;
-0369;COMBINING LATIN SMALL LETTER D;Mn;230;NSM;;;;;N;;;;;
-036A;COMBINING LATIN SMALL LETTER H;Mn;230;NSM;;;;;N;;;;;
-036B;COMBINING LATIN SMALL LETTER M;Mn;230;NSM;;;;;N;;;;;
-036C;COMBINING LATIN SMALL LETTER R;Mn;230;NSM;;;;;N;;;;;
-036D;COMBINING LATIN SMALL LETTER T;Mn;230;NSM;;;;;N;;;;;
-036E;COMBINING LATIN SMALL LETTER V;Mn;230;NSM;;;;;N;;;;;
-036F;COMBINING LATIN SMALL LETTER X;Mn;230;NSM;;;;;N;;;;;
-0370;GREEK CAPITAL LETTER HETA;Lu;0;L;;;;;N;;;;0371;
-0371;GREEK SMALL LETTER HETA;Ll;0;L;;;;;N;;;0370;;0370
-0372;GREEK CAPITAL LETTER ARCHAIC SAMPI;Lu;0;L;;;;;N;;;;0373;
-0373;GREEK SMALL LETTER ARCHAIC SAMPI;Ll;0;L;;;;;N;;;0372;;0372
-0374;GREEK NUMERAL SIGN;Lm;0;ON;02B9;;;;N;GREEK UPPER NUMERAL SIGN;;;;
-0375;GREEK LOWER NUMERAL SIGN;Sk;0;ON;;;;;N;;;;;
-0376;GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA;Lu;0;L;;;;;N;;;;0377;
-0377;GREEK SMALL LETTER PAMPHYLIAN DIGAMMA;Ll;0;L;;;;;N;;;0376;;0376
-037A;GREEK YPOGEGRAMMENI;Lm;0;L;<compat> 0020 0345;;;;N;GREEK SPACING IOTA BELOW;;;;
-037B;GREEK SMALL REVERSED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FD;;03FD
-037C;GREEK SMALL DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FE;;03FE
-037D;GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FF;;03FF
-037E;GREEK QUESTION MARK;Po;0;ON;003B;;;;N;;;;;
-0384;GREEK TONOS;Sk;0;ON;<compat> 0020 0301;;;;N;GREEK SPACING TONOS;;;;
-0385;GREEK DIALYTIKA TONOS;Sk;0;ON;00A8 0301;;;;N;GREEK SPACING DIAERESIS TONOS;;;;
-0386;GREEK CAPITAL LETTER ALPHA WITH TONOS;Lu;0;L;0391 0301;;;;N;GREEK CAPITAL LETTER ALPHA TONOS;;;03AC;
-0387;GREEK ANO TELEIA;Po;0;ON;00B7;;;;N;;;;;
-0388;GREEK CAPITAL LETTER EPSILON WITH TONOS;Lu;0;L;0395 0301;;;;N;GREEK CAPITAL LETTER EPSILON TONOS;;;03AD;
-0389;GREEK CAPITAL LETTER ETA WITH TONOS;Lu;0;L;0397 0301;;;;N;GREEK CAPITAL LETTER ETA TONOS;;;03AE;
-038A;GREEK CAPITAL LETTER IOTA WITH TONOS;Lu;0;L;0399 0301;;;;N;GREEK CAPITAL LETTER IOTA TONOS;;;03AF;
-038C;GREEK CAPITAL LETTER OMICRON WITH TONOS;Lu;0;L;039F 0301;;;;N;GREEK CAPITAL LETTER OMICRON TONOS;;;03CC;
-038E;GREEK CAPITAL LETTER UPSILON WITH TONOS;Lu;0;L;03A5 0301;;;;N;GREEK CAPITAL LETTER UPSILON TONOS;;;03CD;
-038F;GREEK CAPITAL LETTER OMEGA WITH TONOS;Lu;0;L;03A9 0301;;;;N;GREEK CAPITAL LETTER OMEGA TONOS;;;03CE;
-0390;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS;Ll;0;L;03CA 0301;;;;N;GREEK SMALL LETTER IOTA DIAERESIS TONOS;;;;
-0391;GREEK CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;03B1;
-0392;GREEK CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;03B2;
-0393;GREEK CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;03B3;
-0394;GREEK CAPITAL LETTER DELTA;Lu;0;L;;;;;N;;;;03B4;
-0395;GREEK CAPITAL LETTER EPSILON;Lu;0;L;;;;;N;;;;03B5;
-0396;GREEK CAPITAL LETTER ZETA;Lu;0;L;;;;;N;;;;03B6;
-0397;GREEK CAPITAL LETTER ETA;Lu;0;L;;;;;N;;;;03B7;
-0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8;
-0399;GREEK CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;03B9;
-039A;GREEK CAPITAL LETTER KAPPA;Lu;0;L;;;;;N;;;;03BA;
-039B;GREEK CAPITAL LETTER LAMDA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER LAMBDA;;;03BB;
-039C;GREEK CAPITAL LETTER MU;Lu;0;L;;;;;N;;;;03BC;
-039D;GREEK CAPITAL LETTER NU;Lu;0;L;;;;;N;;;;03BD;
-039E;GREEK CAPITAL LETTER XI;Lu;0;L;;;;;N;;;;03BE;
-039F;GREEK CAPITAL LETTER OMICRON;Lu;0;L;;;;;N;;;;03BF;
-03A0;GREEK CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;03C0;
-03A1;GREEK CAPITAL LETTER RHO;Lu;0;L;;;;;N;;;;03C1;
-03A3;GREEK CAPITAL LETTER SIGMA;Lu;0;L;;;;;N;;;;03C3;
-03A4;GREEK CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;03C4;
-03A5;GREEK CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;03C5;
-03A6;GREEK CAPITAL LETTER PHI;Lu;0;L;;;;;N;;;;03C6;
-03A7;GREEK CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;03C7;
-03A8;GREEK CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;03C8;
-03A9;GREEK CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;03C9;
-03AA;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA;Lu;0;L;0399 0308;;;;N;GREEK CAPITAL LETTER IOTA DIAERESIS;;;03CA;
-03AB;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA;Lu;0;L;03A5 0308;;;;N;GREEK CAPITAL LETTER UPSILON DIAERESIS;;;03CB;
-03AC;GREEK SMALL LETTER ALPHA WITH TONOS;Ll;0;L;03B1 0301;;;;N;GREEK SMALL LETTER ALPHA TONOS;;0386;;0386
-03AD;GREEK SMALL LETTER EPSILON WITH TONOS;Ll;0;L;03B5 0301;;;;N;GREEK SMALL LETTER EPSILON TONOS;;0388;;0388
-03AE;GREEK SMALL LETTER ETA WITH TONOS;Ll;0;L;03B7 0301;;;;N;GREEK SMALL LETTER ETA TONOS;;0389;;0389
-03AF;GREEK SMALL LETTER IOTA WITH TONOS;Ll;0;L;03B9 0301;;;;N;GREEK SMALL LETTER IOTA TONOS;;038A;;038A
-03B0;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS;Ll;0;L;03CB 0301;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS TONOS;;;;
-03B1;GREEK SMALL LETTER ALPHA;Ll;0;L;;;;;N;;;0391;;0391
-03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392
-03B3;GREEK SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0393;;0393
-03B4;GREEK SMALL LETTER DELTA;Ll;0;L;;;;;N;;;0394;;0394
-03B5;GREEK SMALL LETTER EPSILON;Ll;0;L;;;;;N;;;0395;;0395
-03B6;GREEK SMALL LETTER ZETA;Ll;0;L;;;;;N;;;0396;;0396
-03B7;GREEK SMALL LETTER ETA;Ll;0;L;;;;;N;;;0397;;0397
-03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398
-03B9;GREEK SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0399;;0399
-03BA;GREEK SMALL LETTER KAPPA;Ll;0;L;;;;;N;;;039A;;039A
-03BB;GREEK SMALL LETTER LAMDA;Ll;0;L;;;;;N;GREEK SMALL LETTER LAMBDA;;039B;;039B
-03BC;GREEK SMALL LETTER MU;Ll;0;L;;;;;N;;;039C;;039C
-03BD;GREEK SMALL LETTER NU;Ll;0;L;;;;;N;;;039D;;039D
-03BE;GREEK SMALL LETTER XI;Ll;0;L;;;;;N;;;039E;;039E
-03BF;GREEK SMALL LETTER OMICRON;Ll;0;L;;;;;N;;;039F;;039F
-03C0;GREEK SMALL LETTER PI;Ll;0;L;;;;;N;;;03A0;;03A0
-03C1;GREEK SMALL LETTER RHO;Ll;0;L;;;;;N;;;03A1;;03A1
-03C2;GREEK SMALL LETTER FINAL SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3
-03C3;GREEK SMALL LETTER SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3
-03C4;GREEK SMALL LETTER TAU;Ll;0;L;;;;;N;;;03A4;;03A4
-03C5;GREEK SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;03A5;;03A5
-03C6;GREEK SMALL LETTER PHI;Ll;0;L;;;;;N;;;03A6;;03A6
-03C7;GREEK SMALL LETTER CHI;Ll;0;L;;;;;N;;;03A7;;03A7
-03C8;GREEK SMALL LETTER PSI;Ll;0;L;;;;;N;;;03A8;;03A8
-03C9;GREEK SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;03A9;;03A9
-03CA;GREEK SMALL LETTER IOTA WITH DIALYTIKA;Ll;0;L;03B9 0308;;;;N;GREEK SMALL LETTER IOTA DIAERESIS;;03AA;;03AA
-03CB;GREEK SMALL LETTER UPSILON WITH DIALYTIKA;Ll;0;L;03C5 0308;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS;;03AB;;03AB
-03CC;GREEK SMALL LETTER OMICRON WITH TONOS;Ll;0;L;03BF 0301;;;;N;GREEK SMALL LETTER OMICRON TONOS;;038C;;038C
-03CD;GREEK SMALL LETTER UPSILON WITH TONOS;Ll;0;L;03C5 0301;;;;N;GREEK SMALL LETTER UPSILON TONOS;;038E;;038E
-03CE;GREEK SMALL LETTER OMEGA WITH TONOS;Ll;0;L;03C9 0301;;;;N;GREEK SMALL LETTER OMEGA TONOS;;038F;;038F
-03CF;GREEK CAPITAL KAI SYMBOL;Lu;0;L;;;;;N;;;;03D7;
-03D0;GREEK BETA SYMBOL;Ll;0;L;<compat> 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392
-03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398
-03D2;GREEK UPSILON WITH HOOK SYMBOL;Lu;0;L;<compat> 03A5;;;;N;GREEK CAPITAL LETTER UPSILON HOOK;;;;
-03D3;GREEK UPSILON WITH ACUTE AND HOOK SYMBOL;Lu;0;L;03D2 0301;;;;N;GREEK CAPITAL LETTER UPSILON HOOK TONOS;;;;
-03D4;GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL;Lu;0;L;03D2 0308;;;;N;GREEK CAPITAL LETTER UPSILON HOOK DIAERESIS;;;;
-03D5;GREEK PHI SYMBOL;Ll;0;L;<compat> 03C6;;;;N;GREEK SMALL LETTER SCRIPT PHI;;03A6;;03A6
-03D6;GREEK PI SYMBOL;Ll;0;L;<compat> 03C0;;;;N;GREEK SMALL LETTER OMEGA PI;;03A0;;03A0
-03D7;GREEK KAI SYMBOL;Ll;0;L;;;;;N;;;03CF;;03CF
-03D8;GREEK LETTER ARCHAIC KOPPA;Lu;0;L;;;;;N;;;;03D9;
-03D9;GREEK SMALL LETTER ARCHAIC KOPPA;Ll;0;L;;;;;N;;;03D8;;03D8
-03DA;GREEK LETTER STIGMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER STIGMA;;;03DB;
-03DB;GREEK SMALL LETTER STIGMA;Ll;0;L;;;;;N;;;03DA;;03DA
-03DC;GREEK LETTER DIGAMMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DIGAMMA;;;03DD;
-03DD;GREEK SMALL LETTER DIGAMMA;Ll;0;L;;;;;N;;;03DC;;03DC
-03DE;GREEK LETTER KOPPA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KOPPA;;;03DF;
-03DF;GREEK SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;03DE;;03DE
-03E0;GREEK LETTER SAMPI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SAMPI;;;03E1;
-03E1;GREEK SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;03E0;;03E0
-03E2;COPTIC CAPITAL LETTER SHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHEI;;;03E3;
-03E3;COPTIC SMALL LETTER SHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER SHEI;;03E2;;03E2
-03E4;COPTIC CAPITAL LETTER FEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER FEI;;;03E5;
-03E5;COPTIC SMALL LETTER FEI;Ll;0;L;;;;;N;GREEK SMALL LETTER FEI;;03E4;;03E4
-03E6;COPTIC CAPITAL LETTER KHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KHEI;;;03E7;
-03E7;COPTIC SMALL LETTER KHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER KHEI;;03E6;;03E6
-03E8;COPTIC CAPITAL LETTER HORI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER HORI;;;03E9;
-03E9;COPTIC SMALL LETTER HORI;Ll;0;L;;;;;N;GREEK SMALL LETTER HORI;;03E8;;03E8
-03EA;COPTIC CAPITAL LETTER GANGIA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER GANGIA;;;03EB;
-03EB;COPTIC SMALL LETTER GANGIA;Ll;0;L;;;;;N;GREEK SMALL LETTER GANGIA;;03EA;;03EA
-03EC;COPTIC CAPITAL LETTER SHIMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHIMA;;;03ED;
-03ED;COPTIC SMALL LETTER SHIMA;Ll;0;L;;;;;N;GREEK SMALL LETTER SHIMA;;03EC;;03EC
-03EE;COPTIC CAPITAL LETTER DEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DEI;;;03EF;
-03EF;COPTIC SMALL LETTER DEI;Ll;0;L;;;;;N;GREEK SMALL LETTER DEI;;03EE;;03EE
-03F0;GREEK KAPPA SYMBOL;Ll;0;L;<compat> 03BA;;;;N;GREEK SMALL LETTER SCRIPT KAPPA;;039A;;039A
-03F1;GREEK RHO SYMBOL;Ll;0;L;<compat> 03C1;;;;N;GREEK SMALL LETTER TAILED RHO;;03A1;;03A1
-03F2;GREEK LUNATE SIGMA SYMBOL;Ll;0;L;<compat> 03C2;;;;N;GREEK SMALL LETTER LUNATE SIGMA;;03F9;;03F9
-03F3;GREEK LETTER YOT;Ll;0;L;;;;;N;;;;;
-03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8;
-03F5;GREEK LUNATE EPSILON SYMBOL;Ll;0;L;<compat> 03B5;;;;N;;;0395;;0395
-03F6;GREEK REVERSED LUNATE EPSILON SYMBOL;Sm;0;ON;;;;;N;;;;;
-03F7;GREEK CAPITAL LETTER SHO;Lu;0;L;;;;;N;;;;03F8;
-03F8;GREEK SMALL LETTER SHO;Ll;0;L;;;;;N;;;03F7;;03F7
-03F9;GREEK CAPITAL LUNATE SIGMA SYMBOL;Lu;0;L;<compat> 03A3;;;;N;;;;03F2;
-03FA;GREEK CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;03FB;
-03FB;GREEK SMALL LETTER SAN;Ll;0;L;;;;;N;;;03FA;;03FA
-03FC;GREEK RHO WITH STROKE SYMBOL;Ll;0;L;;;;;N;;;;;
-03FD;GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037B;
-03FE;GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037C;
-03FF;GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037D;
-0400;CYRILLIC CAPITAL LETTER IE WITH GRAVE;Lu;0;L;0415 0300;;;;N;;;;0450;
-0401;CYRILLIC CAPITAL LETTER IO;Lu;0;L;0415 0308;;;;N;;;;0451;
-0402;CYRILLIC CAPITAL LETTER DJE;Lu;0;L;;;;;N;;;;0452;
-0403;CYRILLIC CAPITAL LETTER GJE;Lu;0;L;0413 0301;;;;N;;;;0453;
-0404;CYRILLIC CAPITAL LETTER UKRAINIAN IE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER E;;;0454;
-0405;CYRILLIC CAPITAL LETTER DZE;Lu;0;L;;;;;N;;;;0455;
-0406;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER I;;;0456;
-0407;CYRILLIC CAPITAL LETTER YI;Lu;0;L;0406 0308;;;;N;;;;0457;
-0408;CYRILLIC CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;0458;
-0409;CYRILLIC CAPITAL LETTER LJE;Lu;0;L;;;;;N;;;;0459;
-040A;CYRILLIC CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;045A;
-040B;CYRILLIC CAPITAL LETTER TSHE;Lu;0;L;;;;;N;;;;045B;
-040C;CYRILLIC CAPITAL LETTER KJE;Lu;0;L;041A 0301;;;;N;;;;045C;
-040D;CYRILLIC CAPITAL LETTER I WITH GRAVE;Lu;0;L;0418 0300;;;;N;;;;045D;
-040E;CYRILLIC CAPITAL LETTER SHORT U;Lu;0;L;0423 0306;;;;N;;;;045E;
-040F;CYRILLIC CAPITAL LETTER DZHE;Lu;0;L;;;;;N;;;;045F;
-0410;CYRILLIC CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0430;
-0411;CYRILLIC CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;0431;
-0412;CYRILLIC CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;0432;
-0413;CYRILLIC CAPITAL LETTER GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE;;;0433;
-0414;CYRILLIC CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;0434;
-0415;CYRILLIC CAPITAL LETTER IE;Lu;0;L;;;;;N;;;;0435;
-0416;CYRILLIC CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;0436;
-0417;CYRILLIC CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;0437;
-0418;CYRILLIC CAPITAL LETTER I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER II;;;0438;
-0419;CYRILLIC CAPITAL LETTER SHORT I;Lu;0;L;0418 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT II;;;0439;
-041A;CYRILLIC CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;043A;
-041B;CYRILLIC CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;043B;
-041C;CYRILLIC CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;043C;
-041D;CYRILLIC CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;043D;
-041E;CYRILLIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;043E;
-041F;CYRILLIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;043F;
-0420;CYRILLIC CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;0440;
-0421;CYRILLIC CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;0441;
-0422;CYRILLIC CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;0442;
-0423;CYRILLIC CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0443;
-0424;CYRILLIC CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;0444;
-0425;CYRILLIC CAPITAL LETTER HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA;;;0445;
-0426;CYRILLIC CAPITAL LETTER TSE;Lu;0;L;;;;;N;;;;0446;
-0427;CYRILLIC CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;0447;
-0428;CYRILLIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0448;
-0429;CYRILLIC CAPITAL LETTER SHCHA;Lu;0;L;;;;;N;;;;0449;
-042A;CYRILLIC CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;044A;
-042B;CYRILLIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER YERI;;;044B;
-042C;CYRILLIC CAPITAL LETTER SOFT SIGN;Lu;0;L;;;;;N;;;;044C;
-042D;CYRILLIC CAPITAL LETTER E;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED E;;;044D;
-042E;CYRILLIC CAPITAL LETTER YU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IU;;;044E;
-042F;CYRILLIC CAPITAL LETTER YA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IA;;;044F;
-0430;CYRILLIC SMALL LETTER A;Ll;0;L;;;;;N;;;0410;;0410
-0431;CYRILLIC SMALL LETTER BE;Ll;0;L;;;;;N;;;0411;;0411
-0432;CYRILLIC SMALL LETTER VE;Ll;0;L;;;;;N;;;0412;;0412
-0433;CYRILLIC SMALL LETTER GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE;;0413;;0413
-0434;CYRILLIC SMALL LETTER DE;Ll;0;L;;;;;N;;;0414;;0414
-0435;CYRILLIC SMALL LETTER IE;Ll;0;L;;;;;N;;;0415;;0415
-0436;CYRILLIC SMALL LETTER ZHE;Ll;0;L;;;;;N;;;0416;;0416
-0437;CYRILLIC SMALL LETTER ZE;Ll;0;L;;;;;N;;;0417;;0417
-0438;CYRILLIC SMALL LETTER I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER II;;0418;;0418
-0439;CYRILLIC SMALL LETTER SHORT I;Ll;0;L;0438 0306;;;;N;CYRILLIC SMALL LETTER SHORT II;;0419;;0419
-043A;CYRILLIC SMALL LETTER KA;Ll;0;L;;;;;N;;;041A;;041A
-043B;CYRILLIC SMALL LETTER EL;Ll;0;L;;;;;N;;;041B;;041B
-043C;CYRILLIC SMALL LETTER EM;Ll;0;L;;;;;N;;;041C;;041C
-043D;CYRILLIC SMALL LETTER EN;Ll;0;L;;;;;N;;;041D;;041D
-043E;CYRILLIC SMALL LETTER O;Ll;0;L;;;;;N;;;041E;;041E
-043F;CYRILLIC SMALL LETTER PE;Ll;0;L;;;;;N;;;041F;;041F
-0440;CYRILLIC SMALL LETTER ER;Ll;0;L;;;;;N;;;0420;;0420
-0441;CYRILLIC SMALL LETTER ES;Ll;0;L;;;;;N;;;0421;;0421
-0442;CYRILLIC SMALL LETTER TE;Ll;0;L;;;;;N;;;0422;;0422
-0443;CYRILLIC SMALL LETTER U;Ll;0;L;;;;;N;;;0423;;0423
-0444;CYRILLIC SMALL LETTER EF;Ll;0;L;;;;;N;;;0424;;0424
-0445;CYRILLIC SMALL LETTER HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA;;0425;;0425
-0446;CYRILLIC SMALL LETTER TSE;Ll;0;L;;;;;N;;;0426;;0426
-0447;CYRILLIC SMALL LETTER CHE;Ll;0;L;;;;;N;;;0427;;0427
-0448;CYRILLIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;0428;;0428
-0449;CYRILLIC SMALL LETTER SHCHA;Ll;0;L;;;;;N;;;0429;;0429
-044A;CYRILLIC SMALL LETTER HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A
-044B;CYRILLIC SMALL LETTER YERU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER YERI;;042B;;042B
-044C;CYRILLIC SMALL LETTER SOFT SIGN;Ll;0;L;;;;;N;;;042C;;042C
-044D;CYRILLIC SMALL LETTER E;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED E;;042D;;042D
-044E;CYRILLIC SMALL LETTER YU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IU;;042E;;042E
-044F;CYRILLIC SMALL LETTER YA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IA;;042F;;042F
-0450;CYRILLIC SMALL LETTER IE WITH GRAVE;Ll;0;L;0435 0300;;;;N;;;0400;;0400
-0451;CYRILLIC SMALL LETTER IO;Ll;0;L;0435 0308;;;;N;;;0401;;0401
-0452;CYRILLIC SMALL LETTER DJE;Ll;0;L;;;;;N;;;0402;;0402
-0453;CYRILLIC SMALL LETTER GJE;Ll;0;L;0433 0301;;;;N;;;0403;;0403
-0454;CYRILLIC SMALL LETTER UKRAINIAN IE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER E;;0404;;0404
-0455;CYRILLIC SMALL LETTER DZE;Ll;0;L;;;;;N;;;0405;;0405
-0456;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER I;;0406;;0406
-0457;CYRILLIC SMALL LETTER YI;Ll;0;L;0456 0308;;;;N;;;0407;;0407
-0458;CYRILLIC SMALL LETTER JE;Ll;0;L;;;;;N;;;0408;;0408
-0459;CYRILLIC SMALL LETTER LJE;Ll;0;L;;;;;N;;;0409;;0409
-045A;CYRILLIC SMALL LETTER NJE;Ll;0;L;;;;;N;;;040A;;040A
-045B;CYRILLIC SMALL LETTER TSHE;Ll;0;L;;;;;N;;;040B;;040B
-045C;CYRILLIC SMALL LETTER KJE;Ll;0;L;043A 0301;;;;N;;;040C;;040C
-045D;CYRILLIC SMALL LETTER I WITH GRAVE;Ll;0;L;0438 0300;;;;N;;;040D;;040D
-045E;CYRILLIC SMALL LETTER SHORT U;Ll;0;L;0443 0306;;;;N;;;040E;;040E
-045F;CYRILLIC SMALL LETTER DZHE;Ll;0;L;;;;;N;;;040F;;040F
-0460;CYRILLIC CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;0461;
-0461;CYRILLIC SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;0460;;0460
-0462;CYRILLIC CAPITAL LETTER YAT;Lu;0;L;;;;;N;;;;0463;
-0463;CYRILLIC SMALL LETTER YAT;Ll;0;L;;;;;N;;;0462;;0462
-0464;CYRILLIC CAPITAL LETTER IOTIFIED E;Lu;0;L;;;;;N;;;;0465;
-0465;CYRILLIC SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;0464;;0464
-0466;CYRILLIC CAPITAL LETTER LITTLE YUS;Lu;0;L;;;;;N;;;;0467;
-0467;CYRILLIC SMALL LETTER LITTLE YUS;Ll;0;L;;;;;N;;;0466;;0466
-0468;CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS;Lu;0;L;;;;;N;;;;0469;
-0469;CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS;Ll;0;L;;;;;N;;;0468;;0468
-046A;CYRILLIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;046B;
-046B;CYRILLIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;046A;;046A
-046C;CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS;Lu;0;L;;;;;N;;;;046D;
-046D;CYRILLIC SMALL LETTER IOTIFIED BIG YUS;Ll;0;L;;;;;N;;;046C;;046C
-046E;CYRILLIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;046F;
-046F;CYRILLIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;046E;;046E
-0470;CYRILLIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;0471;
-0471;CYRILLIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;0470;;0470
-0472;CYRILLIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;0473;
-0473;CYRILLIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;0472;;0472
-0474;CYRILLIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;0475;
-0475;CYRILLIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;0474;;0474
-0476;CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Lu;0;L;0474 030F;;;;N;CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE;;;0477;
-0477;CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Ll;0;L;0475 030F;;;;N;CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE;;0476;;0476
-0478;CYRILLIC CAPITAL LETTER UK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER UK DIGRAPH;;;0479;
-0479;CYRILLIC SMALL LETTER UK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER UK DIGRAPH;;0478;;0478
-047A;CYRILLIC CAPITAL LETTER ROUND OMEGA;Lu;0;L;;;;;N;;;;047B;
-047B;CYRILLIC SMALL LETTER ROUND OMEGA;Ll;0;L;;;;;N;;;047A;;047A
-047C;CYRILLIC CAPITAL LETTER OMEGA WITH TITLO;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER OMEGA TITLO;;;047D;
-047D;CYRILLIC SMALL LETTER OMEGA WITH TITLO;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER OMEGA TITLO;;047C;;047C
-047E;CYRILLIC CAPITAL LETTER OT;Lu;0;L;;;;;N;;;;047F;
-047F;CYRILLIC SMALL LETTER OT;Ll;0;L;;;;;N;;;047E;;047E
-0480;CYRILLIC CAPITAL LETTER KOPPA;Lu;0;L;;;;;N;;;;0481;
-0481;CYRILLIC SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;0480;;0480
-0482;CYRILLIC THOUSANDS SIGN;So;0;L;;;;;N;;;;;
-0483;COMBINING CYRILLIC TITLO;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING TITLO;;;;
-0484;COMBINING CYRILLIC PALATALIZATION;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PALATALIZATION;;;;
-0485;COMBINING CYRILLIC DASIA PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING DASIA PNEUMATA;;;;
-0486;COMBINING CYRILLIC PSILI PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PSILI PNEUMATA;;;;
-0487;COMBINING CYRILLIC POKRYTIE;Mn;230;NSM;;;;;N;;;;;
-0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;;
-0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;;
-048A;CYRILLIC CAPITAL LETTER SHORT I WITH TAIL;Lu;0;L;;;;;N;;;;048B;
-048B;CYRILLIC SMALL LETTER SHORT I WITH TAIL;Ll;0;L;;;;;N;;;048A;;048A
-048C;CYRILLIC CAPITAL LETTER SEMISOFT SIGN;Lu;0;L;;;;;N;;;;048D;
-048D;CYRILLIC SMALL LETTER SEMISOFT SIGN;Ll;0;L;;;;;N;;;048C;;048C
-048E;CYRILLIC CAPITAL LETTER ER WITH TICK;Lu;0;L;;;;;N;;;;048F;
-048F;CYRILLIC SMALL LETTER ER WITH TICK;Ll;0;L;;;;;N;;;048E;;048E
-0490;CYRILLIC CAPITAL LETTER GHE WITH UPTURN;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE WITH UPTURN;;;0491;
-0491;CYRILLIC SMALL LETTER GHE WITH UPTURN;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE WITH UPTURN;;0490;;0490
-0492;CYRILLIC CAPITAL LETTER GHE WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE BAR;;;0493;
-0493;CYRILLIC SMALL LETTER GHE WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE BAR;;0492;;0492
-0494;CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE HOOK;;;0495;
-0495;CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE HOOK;;0494;;0494
-0496;CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER;;;0497;
-0497;CYRILLIC SMALL LETTER ZHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER;;0496;;0496
-0498;CYRILLIC CAPITAL LETTER ZE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZE CEDILLA;;;0499;
-0499;CYRILLIC SMALL LETTER ZE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZE CEDILLA;;0498;;0498
-049A;CYRILLIC CAPITAL LETTER KA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER;;;049B;
-049B;CYRILLIC SMALL LETTER KA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER;;049A;;049A
-049C;CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA VERTICAL BAR;;;049D;
-049D;CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA VERTICAL BAR;;049C;;049C
-049E;CYRILLIC CAPITAL LETTER KA WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA BAR;;;049F;
-049F;CYRILLIC SMALL LETTER KA WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA BAR;;049E;;049E
-04A0;CYRILLIC CAPITAL LETTER BASHKIR KA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED GE KA;;;04A1;
-04A1;CYRILLIC SMALL LETTER BASHKIR KA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED GE KA;;04A0;;04A0
-04A2;CYRILLIC CAPITAL LETTER EN WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER;;;04A3;
-04A3;CYRILLIC SMALL LETTER EN WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER;;04A2;;04A2
-04A4;CYRILLIC CAPITAL LIGATURE EN GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN GE;;;04A5;
-04A5;CYRILLIC SMALL LIGATURE EN GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN GE;;04A4;;04A4
-04A6;CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER PE HOOK;;;04A7;
-04A7;CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER PE HOOK;;04A6;;04A6
-04A8;CYRILLIC CAPITAL LETTER ABKHASIAN HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER O HOOK;;;04A9;
-04A9;CYRILLIC SMALL LETTER ABKHASIAN HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER O HOOK;;04A8;;04A8
-04AA;CYRILLIC CAPITAL LETTER ES WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ES CEDILLA;;;04AB;
-04AB;CYRILLIC SMALL LETTER ES WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ES CEDILLA;;04AA;;04AA
-04AC;CYRILLIC CAPITAL LETTER TE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER;;;04AD;
-04AD;CYRILLIC SMALL LETTER TE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER;;04AC;;04AC
-04AE;CYRILLIC CAPITAL LETTER STRAIGHT U;Lu;0;L;;;;;N;;;;04AF;
-04AF;CYRILLIC SMALL LETTER STRAIGHT U;Ll;0;L;;;;;N;;;04AE;;04AE
-04B0;CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER STRAIGHT U BAR;;;04B1;
-04B1;CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER STRAIGHT U BAR;;04B0;;04B0
-04B2;CYRILLIC CAPITAL LETTER HA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER;;;04B3;
-04B3;CYRILLIC SMALL LETTER HA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER;;04B2;;04B2
-04B4;CYRILLIC CAPITAL LIGATURE TE TSE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE TSE;;;04B5;
-04B5;CYRILLIC SMALL LIGATURE TE TSE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE TSE;;04B4;;04B4
-04B6;CYRILLIC CAPITAL LETTER CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER;;;04B7;
-04B7;CYRILLIC SMALL LETTER CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER;;04B6;;04B6
-04B8;CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE VERTICAL BAR;;;04B9;
-04B9;CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE VERTICAL BAR;;04B8;;04B8
-04BA;CYRILLIC CAPITAL LETTER SHHA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER H;;;04BB;
-04BB;CYRILLIC SMALL LETTER SHHA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER H;;04BA;;04BA
-04BC;CYRILLIC CAPITAL LETTER ABKHASIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK;;;04BD;
-04BD;CYRILLIC SMALL LETTER ABKHASIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK;;04BC;;04BC
-04BE;CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK OGONEK;;;04BF;
-04BF;CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK OGONEK;;04BE;;04BE
-04C0;CYRILLIC LETTER PALOCHKA;Lu;0;L;;;;;N;CYRILLIC LETTER I;;;04CF;
-04C1;CYRILLIC CAPITAL LETTER ZHE WITH BREVE;Lu;0;L;0416 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT ZHE;;;04C2;
-04C2;CYRILLIC SMALL LETTER ZHE WITH BREVE;Ll;0;L;0436 0306;;;;N;CYRILLIC SMALL LETTER SHORT ZHE;;04C1;;04C1
-04C3;CYRILLIC CAPITAL LETTER KA WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA HOOK;;;04C4;
-04C4;CYRILLIC SMALL LETTER KA WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA HOOK;;04C3;;04C3
-04C5;CYRILLIC CAPITAL LETTER EL WITH TAIL;Lu;0;L;;;;;N;;;;04C6;
-04C6;CYRILLIC SMALL LETTER EL WITH TAIL;Ll;0;L;;;;;N;;;04C5;;04C5
-04C7;CYRILLIC CAPITAL LETTER EN WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN HOOK;;;04C8;
-04C8;CYRILLIC SMALL LETTER EN WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN HOOK;;04C7;;04C7
-04C9;CYRILLIC CAPITAL LETTER EN WITH TAIL;Lu;0;L;;;;;N;;;;04CA;
-04CA;CYRILLIC SMALL LETTER EN WITH TAIL;Ll;0;L;;;;;N;;;04C9;;04C9
-04CB;CYRILLIC CAPITAL LETTER KHAKASSIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER;;;04CC;
-04CC;CYRILLIC SMALL LETTER KHAKASSIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER;;04CB;;04CB
-04CD;CYRILLIC CAPITAL LETTER EM WITH TAIL;Lu;0;L;;;;;N;;;;04CE;
-04CE;CYRILLIC SMALL LETTER EM WITH TAIL;Ll;0;L;;;;;N;;;04CD;;04CD
-04CF;CYRILLIC SMALL LETTER PALOCHKA;Ll;0;L;;;;;N;;;04C0;;04C0
-04D0;CYRILLIC CAPITAL LETTER A WITH BREVE;Lu;0;L;0410 0306;;;;N;;;;04D1;
-04D1;CYRILLIC SMALL LETTER A WITH BREVE;Ll;0;L;0430 0306;;;;N;;;04D0;;04D0
-04D2;CYRILLIC CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0410 0308;;;;N;;;;04D3;
-04D3;CYRILLIC SMALL LETTER A WITH DIAERESIS;Ll;0;L;0430 0308;;;;N;;;04D2;;04D2
-04D4;CYRILLIC CAPITAL LIGATURE A IE;Lu;0;L;;;;;N;;;;04D5;
-04D5;CYRILLIC SMALL LIGATURE A IE;Ll;0;L;;;;;N;;;04D4;;04D4
-04D6;CYRILLIC CAPITAL LETTER IE WITH BREVE;Lu;0;L;0415 0306;;;;N;;;;04D7;
-04D7;CYRILLIC SMALL LETTER IE WITH BREVE;Ll;0;L;0435 0306;;;;N;;;04D6;;04D6
-04D8;CYRILLIC CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;04D9;
-04D9;CYRILLIC SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;04D8;;04D8
-04DA;CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS;Lu;0;L;04D8 0308;;;;N;;;;04DB;
-04DB;CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS;Ll;0;L;04D9 0308;;;;N;;;04DA;;04DA
-04DC;CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS;Lu;0;L;0416 0308;;;;N;;;;04DD;
-04DD;CYRILLIC SMALL LETTER ZHE WITH DIAERESIS;Ll;0;L;0436 0308;;;;N;;;04DC;;04DC
-04DE;CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS;Lu;0;L;0417 0308;;;;N;;;;04DF;
-04DF;CYRILLIC SMALL LETTER ZE WITH DIAERESIS;Ll;0;L;0437 0308;;;;N;;;04DE;;04DE
-04E0;CYRILLIC CAPITAL LETTER ABKHASIAN DZE;Lu;0;L;;;;;N;;;;04E1;
-04E1;CYRILLIC SMALL LETTER ABKHASIAN DZE;Ll;0;L;;;;;N;;;04E0;;04E0
-04E2;CYRILLIC CAPITAL LETTER I WITH MACRON;Lu;0;L;0418 0304;;;;N;;;;04E3;
-04E3;CYRILLIC SMALL LETTER I WITH MACRON;Ll;0;L;0438 0304;;;;N;;;04E2;;04E2
-04E4;CYRILLIC CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0418 0308;;;;N;;;;04E5;
-04E5;CYRILLIC SMALL LETTER I WITH DIAERESIS;Ll;0;L;0438 0308;;;;N;;;04E4;;04E4
-04E6;CYRILLIC CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;041E 0308;;;;N;;;;04E7;
-04E7;CYRILLIC SMALL LETTER O WITH DIAERESIS;Ll;0;L;043E 0308;;;;N;;;04E6;;04E6
-04E8;CYRILLIC CAPITAL LETTER BARRED O;Lu;0;L;;;;;N;;;;04E9;
-04E9;CYRILLIC SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;04E8;;04E8
-04EA;CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS;Lu;0;L;04E8 0308;;;;N;;;;04EB;
-04EB;CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS;Ll;0;L;04E9 0308;;;;N;;;04EA;;04EA
-04EC;CYRILLIC CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;042D 0308;;;;N;;;;04ED;
-04ED;CYRILLIC SMALL LETTER E WITH DIAERESIS;Ll;0;L;044D 0308;;;;N;;;04EC;;04EC
-04EE;CYRILLIC CAPITAL LETTER U WITH MACRON;Lu;0;L;0423 0304;;;;N;;;;04EF;
-04EF;CYRILLIC SMALL LETTER U WITH MACRON;Ll;0;L;0443 0304;;;;N;;;04EE;;04EE
-04F0;CYRILLIC CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0423 0308;;;;N;;;;04F1;
-04F1;CYRILLIC SMALL LETTER U WITH DIAERESIS;Ll;0;L;0443 0308;;;;N;;;04F0;;04F0
-04F2;CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0423 030B;;;;N;;;;04F3;
-04F3;CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0443 030B;;;;N;;;04F2;;04F2
-04F4;CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS;Lu;0;L;0427 0308;;;;N;;;;04F5;
-04F5;CYRILLIC SMALL LETTER CHE WITH DIAERESIS;Ll;0;L;0447 0308;;;;N;;;04F4;;04F4
-04F6;CYRILLIC CAPITAL LETTER GHE WITH DESCENDER;Lu;0;L;;;;;N;;;;04F7;
-04F7;CYRILLIC SMALL LETTER GHE WITH DESCENDER;Ll;0;L;;;;;N;;;04F6;;04F6
-04F8;CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS;Lu;0;L;042B 0308;;;;N;;;;04F9;
-04F9;CYRILLIC SMALL LETTER YERU WITH DIAERESIS;Ll;0;L;044B 0308;;;;N;;;04F8;;04F8
-04FA;CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK;Lu;0;L;;;;;N;;;;04FB;
-04FB;CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK;Ll;0;L;;;;;N;;;04FA;;04FA
-04FC;CYRILLIC CAPITAL LETTER HA WITH HOOK;Lu;0;L;;;;;N;;;;04FD;
-04FD;CYRILLIC SMALL LETTER HA WITH HOOK;Ll;0;L;;;;;N;;;04FC;;04FC
-04FE;CYRILLIC CAPITAL LETTER HA WITH STROKE;Lu;0;L;;;;;N;;;;04FF;
-04FF;CYRILLIC SMALL LETTER HA WITH STROKE;Ll;0;L;;;;;N;;;04FE;;04FE
-0500;CYRILLIC CAPITAL LETTER KOMI DE;Lu;0;L;;;;;N;;;;0501;
-0501;CYRILLIC SMALL LETTER KOMI DE;Ll;0;L;;;;;N;;;0500;;0500
-0502;CYRILLIC CAPITAL LETTER KOMI DJE;Lu;0;L;;;;;N;;;;0503;
-0503;CYRILLIC SMALL LETTER KOMI DJE;Ll;0;L;;;;;N;;;0502;;0502
-0504;CYRILLIC CAPITAL LETTER KOMI ZJE;Lu;0;L;;;;;N;;;;0505;
-0505;CYRILLIC SMALL LETTER KOMI ZJE;Ll;0;L;;;;;N;;;0504;;0504
-0506;CYRILLIC CAPITAL LETTER KOMI DZJE;Lu;0;L;;;;;N;;;;0507;
-0507;CYRILLIC SMALL LETTER KOMI DZJE;Ll;0;L;;;;;N;;;0506;;0506
-0508;CYRILLIC CAPITAL LETTER KOMI LJE;Lu;0;L;;;;;N;;;;0509;
-0509;CYRILLIC SMALL LETTER KOMI LJE;Ll;0;L;;;;;N;;;0508;;0508
-050A;CYRILLIC CAPITAL LETTER KOMI NJE;Lu;0;L;;;;;N;;;;050B;
-050B;CYRILLIC SMALL LETTER KOMI NJE;Ll;0;L;;;;;N;;;050A;;050A
-050C;CYRILLIC CAPITAL LETTER KOMI SJE;Lu;0;L;;;;;N;;;;050D;
-050D;CYRILLIC SMALL LETTER KOMI SJE;Ll;0;L;;;;;N;;;050C;;050C
-050E;CYRILLIC CAPITAL LETTER KOMI TJE;Lu;0;L;;;;;N;;;;050F;
-050F;CYRILLIC SMALL LETTER KOMI TJE;Ll;0;L;;;;;N;;;050E;;050E
-0510;CYRILLIC CAPITAL LETTER REVERSED ZE;Lu;0;L;;;;;N;;;;0511;
-0511;CYRILLIC SMALL LETTER REVERSED ZE;Ll;0;L;;;;;N;;;0510;;0510
-0512;CYRILLIC CAPITAL LETTER EL WITH HOOK;Lu;0;L;;;;;N;;;;0513;
-0513;CYRILLIC SMALL LETTER EL WITH HOOK;Ll;0;L;;;;;N;;;0512;;0512
-0514;CYRILLIC CAPITAL LETTER LHA;Lu;0;L;;;;;N;;;;0515;
-0515;CYRILLIC SMALL LETTER LHA;Ll;0;L;;;;;N;;;0514;;0514
-0516;CYRILLIC CAPITAL LETTER RHA;Lu;0;L;;;;;N;;;;0517;
-0517;CYRILLIC SMALL LETTER RHA;Ll;0;L;;;;;N;;;0516;;0516
-0518;CYRILLIC CAPITAL LETTER YAE;Lu;0;L;;;;;N;;;;0519;
-0519;CYRILLIC SMALL LETTER YAE;Ll;0;L;;;;;N;;;0518;;0518
-051A;CYRILLIC CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;051B;
-051B;CYRILLIC SMALL LETTER QA;Ll;0;L;;;;;N;;;051A;;051A
-051C;CYRILLIC CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;051D;
-051D;CYRILLIC SMALL LETTER WE;Ll;0;L;;;;;N;;;051C;;051C
-051E;CYRILLIC CAPITAL LETTER ALEUT KA;Lu;0;L;;;;;N;;;;051F;
-051F;CYRILLIC SMALL LETTER ALEUT KA;Ll;0;L;;;;;N;;;051E;;051E
-0520;CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0521;
-0521;CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0520;;0520
-0522;CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0523;
-0523;CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0522;;0522
-0524;CYRILLIC CAPITAL LETTER PE WITH DESCENDER;Lu;0;L;;;;;N;;;;0525;
-0525;CYRILLIC SMALL LETTER PE WITH DESCENDER;Ll;0;L;;;;;N;;;0524;;0524
-0526;CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER;Lu;0;L;;;;;N;;;;0527;
-0527;CYRILLIC SMALL LETTER SHHA WITH DESCENDER;Ll;0;L;;;;;N;;;0526;;0526
-0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561;
-0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562;
-0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563;
-0534;ARMENIAN CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;0564;
-0535;ARMENIAN CAPITAL LETTER ECH;Lu;0;L;;;;;N;;;;0565;
-0536;ARMENIAN CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;0566;
-0537;ARMENIAN CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;0567;
-0538;ARMENIAN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;0568;
-0539;ARMENIAN CAPITAL LETTER TO;Lu;0;L;;;;;N;;;;0569;
-053A;ARMENIAN CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;056A;
-053B;ARMENIAN CAPITAL LETTER INI;Lu;0;L;;;;;N;;;;056B;
-053C;ARMENIAN CAPITAL LETTER LIWN;Lu;0;L;;;;;N;;;;056C;
-053D;ARMENIAN CAPITAL LETTER XEH;Lu;0;L;;;;;N;;;;056D;
-053E;ARMENIAN CAPITAL LETTER CA;Lu;0;L;;;;;N;;;;056E;
-053F;ARMENIAN CAPITAL LETTER KEN;Lu;0;L;;;;;N;;;;056F;
-0540;ARMENIAN CAPITAL LETTER HO;Lu;0;L;;;;;N;;;;0570;
-0541;ARMENIAN CAPITAL LETTER JA;Lu;0;L;;;;;N;;;;0571;
-0542;ARMENIAN CAPITAL LETTER GHAD;Lu;0;L;;;;;N;ARMENIAN CAPITAL LETTER LAD;;;0572;
-0543;ARMENIAN CAPITAL LETTER CHEH;Lu;0;L;;;;;N;;;;0573;
-0544;ARMENIAN CAPITAL LETTER MEN;Lu;0;L;;;;;N;;;;0574;
-0545;ARMENIAN CAPITAL LETTER YI;Lu;0;L;;;;;N;;;;0575;
-0546;ARMENIAN CAPITAL LETTER NOW;Lu;0;L;;;;;N;;;;0576;
-0547;ARMENIAN CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0577;
-0548;ARMENIAN CAPITAL LETTER VO;Lu;0;L;;;;;N;;;;0578;
-0549;ARMENIAN CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;0579;
-054A;ARMENIAN CAPITAL LETTER PEH;Lu;0;L;;;;;N;;;;057A;
-054B;ARMENIAN CAPITAL LETTER JHEH;Lu;0;L;;;;;N;;;;057B;
-054C;ARMENIAN CAPITAL LETTER RA;Lu;0;L;;;;;N;;;;057C;
-054D;ARMENIAN CAPITAL LETTER SEH;Lu;0;L;;;;;N;;;;057D;
-054E;ARMENIAN CAPITAL LETTER VEW;Lu;0;L;;;;;N;;;;057E;
-054F;ARMENIAN CAPITAL LETTER TIWN;Lu;0;L;;;;;N;;;;057F;
-0550;ARMENIAN CAPITAL LETTER REH;Lu;0;L;;;;;N;;;;0580;
-0551;ARMENIAN CAPITAL LETTER CO;Lu;0;L;;;;;N;;;;0581;
-0552;ARMENIAN CAPITAL LETTER YIWN;Lu;0;L;;;;;N;;;;0582;
-0553;ARMENIAN CAPITAL LETTER PIWR;Lu;0;L;;;;;N;;;;0583;
-0554;ARMENIAN CAPITAL LETTER KEH;Lu;0;L;;;;;N;;;;0584;
-0555;ARMENIAN CAPITAL LETTER OH;Lu;0;L;;;;;N;;;;0585;
-0556;ARMENIAN CAPITAL LETTER FEH;Lu;0;L;;;;;N;;;;0586;
-0559;ARMENIAN MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;;
-055A;ARMENIAN APOSTROPHE;Po;0;L;;;;;N;ARMENIAN MODIFIER LETTER RIGHT HALF RING;;;;
-055B;ARMENIAN EMPHASIS MARK;Po;0;L;;;;;N;;;;;
-055C;ARMENIAN EXCLAMATION MARK;Po;0;L;;;;;N;;;;;
-055D;ARMENIAN COMMA;Po;0;L;;;;;N;;;;;
-055E;ARMENIAN QUESTION MARK;Po;0;L;;;;;N;;;;;
-055F;ARMENIAN ABBREVIATION MARK;Po;0;L;;;;;N;;;;;
-0561;ARMENIAN SMALL LETTER AYB;Ll;0;L;;;;;N;;;0531;;0531
-0562;ARMENIAN SMALL LETTER BEN;Ll;0;L;;;;;N;;;0532;;0532
-0563;ARMENIAN SMALL LETTER GIM;Ll;0;L;;;;;N;;;0533;;0533
-0564;ARMENIAN SMALL LETTER DA;Ll;0;L;;;;;N;;;0534;;0534
-0565;ARMENIAN SMALL LETTER ECH;Ll;0;L;;;;;N;;;0535;;0535
-0566;ARMENIAN SMALL LETTER ZA;Ll;0;L;;;;;N;;;0536;;0536
-0567;ARMENIAN SMALL LETTER EH;Ll;0;L;;;;;N;;;0537;;0537
-0568;ARMENIAN SMALL LETTER ET;Ll;0;L;;;;;N;;;0538;;0538
-0569;ARMENIAN SMALL LETTER TO;Ll;0;L;;;;;N;;;0539;;0539
-056A;ARMENIAN SMALL LETTER ZHE;Ll;0;L;;;;;N;;;053A;;053A
-056B;ARMENIAN SMALL LETTER INI;Ll;0;L;;;;;N;;;053B;;053B
-056C;ARMENIAN SMALL LETTER LIWN;Ll;0;L;;;;;N;;;053C;;053C
-056D;ARMENIAN SMALL LETTER XEH;Ll;0;L;;;;;N;;;053D;;053D
-056E;ARMENIAN SMALL LETTER CA;Ll;0;L;;;;;N;;;053E;;053E
-056F;ARMENIAN SMALL LETTER KEN;Ll;0;L;;;;;N;;;053F;;053F
-0570;ARMENIAN SMALL LETTER HO;Ll;0;L;;;;;N;;;0540;;0540
-0571;ARMENIAN SMALL LETTER JA;Ll;0;L;;;;;N;;;0541;;0541
-0572;ARMENIAN SMALL LETTER GHAD;Ll;0;L;;;;;N;ARMENIAN SMALL LETTER LAD;;0542;;0542
-0573;ARMENIAN SMALL LETTER CHEH;Ll;0;L;;;;;N;;;0543;;0543
-0574;ARMENIAN SMALL LETTER MEN;Ll;0;L;;;;;N;;;0544;;0544
-0575;ARMENIAN SMALL LETTER YI;Ll;0;L;;;;;N;;;0545;;0545
-0576;ARMENIAN SMALL LETTER NOW;Ll;0;L;;;;;N;;;0546;;0546
-0577;ARMENIAN SMALL LETTER SHA;Ll;0;L;;;;;N;;;0547;;0547
-0578;ARMENIAN SMALL LETTER VO;Ll;0;L;;;;;N;;;0548;;0548
-0579;ARMENIAN SMALL LETTER CHA;Ll;0;L;;;;;N;;;0549;;0549
-057A;ARMENIAN SMALL LETTER PEH;Ll;0;L;;;;;N;;;054A;;054A
-057B;ARMENIAN SMALL LETTER JHEH;Ll;0;L;;;;;N;;;054B;;054B
-057C;ARMENIAN SMALL LETTER RA;Ll;0;L;;;;;N;;;054C;;054C
-057D;ARMENIAN SMALL LETTER SEH;Ll;0;L;;;;;N;;;054D;;054D
-057E;ARMENIAN SMALL LETTER VEW;Ll;0;L;;;;;N;;;054E;;054E
-057F;ARMENIAN SMALL LETTER TIWN;Ll;0;L;;;;;N;;;054F;;054F
-0580;ARMENIAN SMALL LETTER REH;Ll;0;L;;;;;N;;;0550;;0550
-0581;ARMENIAN SMALL LETTER CO;Ll;0;L;;;;;N;;;0551;;0551
-0582;ARMENIAN SMALL LETTER YIWN;Ll;0;L;;;;;N;;;0552;;0552
-0583;ARMENIAN SMALL LETTER PIWR;Ll;0;L;;;;;N;;;0553;;0553
-0584;ARMENIAN SMALL LETTER KEH;Ll;0;L;;;;;N;;;0554;;0554
-0585;ARMENIAN SMALL LETTER OH;Ll;0;L;;;;;N;;;0555;;0555
-0586;ARMENIAN SMALL LETTER FEH;Ll;0;L;;;;;N;;;0556;;0556
-0587;ARMENIAN SMALL LIGATURE ECH YIWN;Ll;0;L;<compat> 0565 0582;;;;N;;;;;
-0589;ARMENIAN FULL STOP;Po;0;L;;;;;N;ARMENIAN PERIOD;;;;
-058A;ARMENIAN HYPHEN;Pd;0;ON;;;;;N;;;;;
-058F;ARMENIAN DRAM SIGN;Sc;0;ET;;;;;N;;;;;
-0591;HEBREW ACCENT ETNAHTA;Mn;220;NSM;;;;;N;;;;;
-0592;HEBREW ACCENT SEGOL;Mn;230;NSM;;;;;N;;;;;
-0593;HEBREW ACCENT SHALSHELET;Mn;230;NSM;;;;;N;;;;;
-0594;HEBREW ACCENT ZAQEF QATAN;Mn;230;NSM;;;;;N;;;;;
-0595;HEBREW ACCENT ZAQEF GADOL;Mn;230;NSM;;;;;N;;;;;
-0596;HEBREW ACCENT TIPEHA;Mn;220;NSM;;;;;N;;;;;
-0597;HEBREW ACCENT REVIA;Mn;230;NSM;;;;;N;;;;;
-0598;HEBREW ACCENT ZARQA;Mn;230;NSM;;;;;N;;;;;
-0599;HEBREW ACCENT PASHTA;Mn;230;NSM;;;;;N;;;;;
-059A;HEBREW ACCENT YETIV;Mn;222;NSM;;;;;N;;;;;
-059B;HEBREW ACCENT TEVIR;Mn;220;NSM;;;;;N;;;;;
-059C;HEBREW ACCENT GERESH;Mn;230;NSM;;;;;N;;;;;
-059D;HEBREW ACCENT GERESH MUQDAM;Mn;230;NSM;;;;;N;;;;;
-059E;HEBREW ACCENT GERSHAYIM;Mn;230;NSM;;;;;N;;;;;
-059F;HEBREW ACCENT QARNEY PARA;Mn;230;NSM;;;;;N;;;;;
-05A0;HEBREW ACCENT TELISHA GEDOLA;Mn;230;NSM;;;;;N;;;;;
-05A1;HEBREW ACCENT PAZER;Mn;230;NSM;;;;;N;;;;;
-05A2;HEBREW ACCENT ATNAH HAFUKH;Mn;220;NSM;;;;;N;;;;;
-05A3;HEBREW ACCENT MUNAH;Mn;220;NSM;;;;;N;;;;;
-05A4;HEBREW ACCENT MAHAPAKH;Mn;220;NSM;;;;;N;;;;;
-05A5;HEBREW ACCENT MERKHA;Mn;220;NSM;;;;;N;;;;;
-05A6;HEBREW ACCENT MERKHA KEFULA;Mn;220;NSM;;;;;N;;;;;
-05A7;HEBREW ACCENT DARGA;Mn;220;NSM;;;;;N;;;;;
-05A8;HEBREW ACCENT QADMA;Mn;230;NSM;;;;;N;;;;;
-05A9;HEBREW ACCENT TELISHA QETANA;Mn;230;NSM;;;;;N;;;;;
-05AA;HEBREW ACCENT YERAH BEN YOMO;Mn;220;NSM;;;;;N;;;;;
-05AB;HEBREW ACCENT OLE;Mn;230;NSM;;;;;N;;;;;
-05AC;HEBREW ACCENT ILUY;Mn;230;NSM;;;;;N;;;;;
-05AD;HEBREW ACCENT DEHI;Mn;222;NSM;;;;;N;;;;;
-05AE;HEBREW ACCENT ZINOR;Mn;228;NSM;;;;;N;;;;;
-05AF;HEBREW MARK MASORA CIRCLE;Mn;230;NSM;;;;;N;;;;;
-05B0;HEBREW POINT SHEVA;Mn;10;NSM;;;;;N;;;;;
-05B1;HEBREW POINT HATAF SEGOL;Mn;11;NSM;;;;;N;;;;;
-05B2;HEBREW POINT HATAF PATAH;Mn;12;NSM;;;;;N;;;;;
-05B3;HEBREW POINT HATAF QAMATS;Mn;13;NSM;;;;;N;;;;;
-05B4;HEBREW POINT HIRIQ;Mn;14;NSM;;;;;N;;;;;
-05B5;HEBREW POINT TSERE;Mn;15;NSM;;;;;N;;;;;
-05B6;HEBREW POINT SEGOL;Mn;16;NSM;;;;;N;;;;;
-05B7;HEBREW POINT PATAH;Mn;17;NSM;;;;;N;;;;;
-05B8;HEBREW POINT QAMATS;Mn;18;NSM;;;;;N;;;;;
-05B9;HEBREW POINT HOLAM;Mn;19;NSM;;;;;N;;;;;
-05BA;HEBREW POINT HOLAM HASER FOR VAV;Mn;19;NSM;;;;;N;;;;;
-05BB;HEBREW POINT QUBUTS;Mn;20;NSM;;;;;N;;;;;
-05BC;HEBREW POINT DAGESH OR MAPIQ;Mn;21;NSM;;;;;N;HEBREW POINT DAGESH;;;;
-05BD;HEBREW POINT METEG;Mn;22;NSM;;;;;N;;;;;
-05BE;HEBREW PUNCTUATION MAQAF;Pd;0;R;;;;;N;;;;;
-05BF;HEBREW POINT RAFE;Mn;23;NSM;;;;;N;;;;;
-05C0;HEBREW PUNCTUATION PASEQ;Po;0;R;;;;;N;HEBREW POINT PASEQ;;;;
-05C1;HEBREW POINT SHIN DOT;Mn;24;NSM;;;;;N;;;;;
-05C2;HEBREW POINT SIN DOT;Mn;25;NSM;;;;;N;;;;;
-05C3;HEBREW PUNCTUATION SOF PASUQ;Po;0;R;;;;;N;;;;;
-05C4;HEBREW MARK UPPER DOT;Mn;230;NSM;;;;;N;;;;;
-05C5;HEBREW MARK LOWER DOT;Mn;220;NSM;;;;;N;;;;;
-05C6;HEBREW PUNCTUATION NUN HAFUKHA;Po;0;R;;;;;N;;;;;
-05C7;HEBREW POINT QAMATS QATAN;Mn;18;NSM;;;;;N;;;;;
-05D0;HEBREW LETTER ALEF;Lo;0;R;;;;;N;;;;;
-05D1;HEBREW LETTER BET;Lo;0;R;;;;;N;;;;;
-05D2;HEBREW LETTER GIMEL;Lo;0;R;;;;;N;;;;;
-05D3;HEBREW LETTER DALET;Lo;0;R;;;;;N;;;;;
-05D4;HEBREW LETTER HE;Lo;0;R;;;;;N;;;;;
-05D5;HEBREW LETTER VAV;Lo;0;R;;;;;N;;;;;
-05D6;HEBREW LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
-05D7;HEBREW LETTER HET;Lo;0;R;;;;;N;;;;;
-05D8;HEBREW LETTER TET;Lo;0;R;;;;;N;;;;;
-05D9;HEBREW LETTER YOD;Lo;0;R;;;;;N;;;;;
-05DA;HEBREW LETTER FINAL KAF;Lo;0;R;;;;;N;;;;;
-05DB;HEBREW LETTER KAF;Lo;0;R;;;;;N;;;;;
-05DC;HEBREW LETTER LAMED;Lo;0;R;;;;;N;;;;;
-05DD;HEBREW LETTER FINAL MEM;Lo;0;R;;;;;N;;;;;
-05DE;HEBREW LETTER MEM;Lo;0;R;;;;;N;;;;;
-05DF;HEBREW LETTER FINAL NUN;Lo;0;R;;;;;N;;;;;
-05E0;HEBREW LETTER NUN;Lo;0;R;;;;;N;;;;;
-05E1;HEBREW LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
-05E2;HEBREW LETTER AYIN;Lo;0;R;;;;;N;;;;;
-05E3;HEBREW LETTER FINAL PE;Lo;0;R;;;;;N;;;;;
-05E4;HEBREW LETTER PE;Lo;0;R;;;;;N;;;;;
-05E5;HEBREW LETTER FINAL TSADI;Lo;0;R;;;;;N;;;;;
-05E6;HEBREW LETTER TSADI;Lo;0;R;;;;;N;;;;;
-05E7;HEBREW LETTER QOF;Lo;0;R;;;;;N;;;;;
-05E8;HEBREW LETTER RESH;Lo;0;R;;;;;N;;;;;
-05E9;HEBREW LETTER SHIN;Lo;0;R;;;;;N;;;;;
-05EA;HEBREW LETTER TAV;Lo;0;R;;;;;N;;;;;
-05F0;HEBREW LIGATURE YIDDISH DOUBLE VAV;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE VAV;;;;
-05F1;HEBREW LIGATURE YIDDISH VAV YOD;Lo;0;R;;;;;N;HEBREW LETTER VAV YOD;;;;
-05F2;HEBREW LIGATURE YIDDISH DOUBLE YOD;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE YOD;;;;
-05F3;HEBREW PUNCTUATION GERESH;Po;0;R;;;;;N;;;;;
-05F4;HEBREW PUNCTUATION GERSHAYIM;Po;0;R;;;;;N;;;;;
-0600;ARABIC NUMBER SIGN;Cf;0;AN;;;;;N;;;;;
-0601;ARABIC SIGN SANAH;Cf;0;AN;;;;;N;;;;;
-0602;ARABIC FOOTNOTE MARKER;Cf;0;AN;;;;;N;;;;;
-0603;ARABIC SIGN SAFHA;Cf;0;AN;;;;;N;;;;;
-0604;ARABIC SIGN SAMVAT;Cf;0;AN;;;;;N;;;;;
-0606;ARABIC-INDIC CUBE ROOT;Sm;0;ON;;;;;N;;;;;
-0607;ARABIC-INDIC FOURTH ROOT;Sm;0;ON;;;;;N;;;;;
-0608;ARABIC RAY;Sm;0;AL;;;;;N;;;;;
-0609;ARABIC-INDIC PER MILLE SIGN;Po;0;ET;;;;;N;;;;;
-060A;ARABIC-INDIC PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;;
-060B;AFGHANI SIGN;Sc;0;AL;;;;;N;;;;;
-060C;ARABIC COMMA;Po;0;CS;;;;;N;;;;;
-060D;ARABIC DATE SEPARATOR;Po;0;AL;;;;;N;;;;;
-060E;ARABIC POETIC VERSE SIGN;So;0;ON;;;;;N;;;;;
-060F;ARABIC SIGN MISRA;So;0;ON;;;;;N;;;;;
-0610;ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM;Mn;230;NSM;;;;;N;;;;;
-0611;ARABIC SIGN ALAYHE ASSALLAM;Mn;230;NSM;;;;;N;;;;;
-0612;ARABIC SIGN RAHMATULLAH ALAYHE;Mn;230;NSM;;;;;N;;;;;
-0613;ARABIC SIGN RADI ALLAHOU ANHU;Mn;230;NSM;;;;;N;;;;;
-0614;ARABIC SIGN TAKHALLUS;Mn;230;NSM;;;;;N;;;;;
-0615;ARABIC SMALL HIGH TAH;Mn;230;NSM;;;;;N;;;;;
-0616;ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH;Mn;230;NSM;;;;;N;;;;;
-0617;ARABIC SMALL HIGH ZAIN;Mn;230;NSM;;;;;N;;;;;
-0618;ARABIC SMALL FATHA;Mn;30;NSM;;;;;N;;;;;
-0619;ARABIC SMALL DAMMA;Mn;31;NSM;;;;;N;;;;;
-061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;;
-061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;;
-061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;;
-061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;;
-0620;ARABIC LETTER KASHMIRI YEH;Lo;0;AL;;;;;N;;;;;
-0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;;
-0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;;
-0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;;
-0624;ARABIC LETTER WAW WITH HAMZA ABOVE;Lo;0;AL;0648 0654;;;;N;ARABIC LETTER HAMZAH ON WAW;;;;
-0625;ARABIC LETTER ALEF WITH HAMZA BELOW;Lo;0;AL;0627 0655;;;;N;ARABIC LETTER HAMZAH UNDER ALEF;;;;
-0626;ARABIC LETTER YEH WITH HAMZA ABOVE;Lo;0;AL;064A 0654;;;;N;ARABIC LETTER HAMZAH ON YA;;;;
-0627;ARABIC LETTER ALEF;Lo;0;AL;;;;;N;;;;;
-0628;ARABIC LETTER BEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA;;;;
-0629;ARABIC LETTER TEH MARBUTA;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH;;;;
-062A;ARABIC LETTER TEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA;;;;
-062B;ARABIC LETTER THEH;Lo;0;AL;;;;;N;ARABIC LETTER THAA;;;;
-062C;ARABIC LETTER JEEM;Lo;0;AL;;;;;N;;;;;
-062D;ARABIC LETTER HAH;Lo;0;AL;;;;;N;ARABIC LETTER HAA;;;;
-062E;ARABIC LETTER KHAH;Lo;0;AL;;;;;N;ARABIC LETTER KHAA;;;;
-062F;ARABIC LETTER DAL;Lo;0;AL;;;;;N;;;;;
-0630;ARABIC LETTER THAL;Lo;0;AL;;;;;N;;;;;
-0631;ARABIC LETTER REH;Lo;0;AL;;;;;N;ARABIC LETTER RA;;;;
-0632;ARABIC LETTER ZAIN;Lo;0;AL;;;;;N;;;;;
-0633;ARABIC LETTER SEEN;Lo;0;AL;;;;;N;;;;;
-0634;ARABIC LETTER SHEEN;Lo;0;AL;;;;;N;;;;;
-0635;ARABIC LETTER SAD;Lo;0;AL;;;;;N;;;;;
-0636;ARABIC LETTER DAD;Lo;0;AL;;;;;N;;;;;
-0637;ARABIC LETTER TAH;Lo;0;AL;;;;;N;;;;;
-0638;ARABIC LETTER ZAH;Lo;0;AL;;;;;N;ARABIC LETTER DHAH;;;;
-0639;ARABIC LETTER AIN;Lo;0;AL;;;;;N;;;;;
-063A;ARABIC LETTER GHAIN;Lo;0;AL;;;;;N;;;;;
-063B;ARABIC LETTER KEHEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-063C;ARABIC LETTER KEHEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
-063D;ARABIC LETTER FARSI YEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
-063E;ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-063F;ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-0640;ARABIC TATWEEL;Lm;0;AL;;;;;N;;;;;
-0641;ARABIC LETTER FEH;Lo;0;AL;;;;;N;ARABIC LETTER FA;;;;
-0642;ARABIC LETTER QAF;Lo;0;AL;;;;;N;;;;;
-0643;ARABIC LETTER KAF;Lo;0;AL;;;;;N;ARABIC LETTER CAF;;;;
-0644;ARABIC LETTER LAM;Lo;0;AL;;;;;N;;;;;
-0645;ARABIC LETTER MEEM;Lo;0;AL;;;;;N;;;;;
-0646;ARABIC LETTER NOON;Lo;0;AL;;;;;N;;;;;
-0647;ARABIC LETTER HEH;Lo;0;AL;;;;;N;ARABIC LETTER HA;;;;
-0648;ARABIC LETTER WAW;Lo;0;AL;;;;;N;;;;;
-0649;ARABIC LETTER ALEF MAKSURA;Lo;0;AL;;;;;N;ARABIC LETTER ALEF MAQSURAH;;;;
-064A;ARABIC LETTER YEH;Lo;0;AL;;;;;N;ARABIC LETTER YA;;;;
-064B;ARABIC FATHATAN;Mn;27;NSM;;;;;N;;;;;
-064C;ARABIC DAMMATAN;Mn;28;NSM;;;;;N;;;;;
-064D;ARABIC KASRATAN;Mn;29;NSM;;;;;N;;;;;
-064E;ARABIC FATHA;Mn;30;NSM;;;;;N;ARABIC FATHAH;;;;
-064F;ARABIC DAMMA;Mn;31;NSM;;;;;N;ARABIC DAMMAH;;;;
-0650;ARABIC KASRA;Mn;32;NSM;;;;;N;ARABIC KASRAH;;;;
-0651;ARABIC SHADDA;Mn;33;NSM;;;;;N;ARABIC SHADDAH;;;;
-0652;ARABIC SUKUN;Mn;34;NSM;;;;;N;;;;;
-0653;ARABIC MADDAH ABOVE;Mn;230;NSM;;;;;N;;;;;
-0654;ARABIC HAMZA ABOVE;Mn;230;NSM;;;;;N;;;;;
-0655;ARABIC HAMZA BELOW;Mn;220;NSM;;;;;N;;;;;
-0656;ARABIC SUBSCRIPT ALEF;Mn;220;NSM;;;;;N;;;;;
-0657;ARABIC INVERTED DAMMA;Mn;230;NSM;;;;;N;;;;;
-0658;ARABIC MARK NOON GHUNNA;Mn;230;NSM;;;;;N;;;;;
-0659;ARABIC ZWARAKAY;Mn;230;NSM;;;;;N;;;;;
-065A;ARABIC VOWEL SIGN SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;;
-065B;ARABIC VOWEL SIGN INVERTED SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;;
-065C;ARABIC VOWEL SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;;
-065D;ARABIC REVERSED DAMMA;Mn;230;NSM;;;;;N;;;;;
-065E;ARABIC FATHA WITH TWO DOTS;Mn;230;NSM;;;;;N;;;;;
-065F;ARABIC WAVY HAMZA BELOW;Mn;220;NSM;;;;;N;;;;;
-0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;;
-0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;;
-0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;;
-0663;ARABIC-INDIC DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;;
-0664;ARABIC-INDIC DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;;
-0665;ARABIC-INDIC DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;;
-0666;ARABIC-INDIC DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;;
-0667;ARABIC-INDIC DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;;
-0668;ARABIC-INDIC DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;;
-0669;ARABIC-INDIC DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;;
-066A;ARABIC PERCENT SIGN;Po;0;ET;;;;;N;;;;;
-066B;ARABIC DECIMAL SEPARATOR;Po;0;AN;;;;;N;;;;;
-066C;ARABIC THOUSANDS SEPARATOR;Po;0;AN;;;;;N;;;;;
-066D;ARABIC FIVE POINTED STAR;Po;0;AL;;;;;N;;;;;
-066E;ARABIC LETTER DOTLESS BEH;Lo;0;AL;;;;;N;;;;;
-066F;ARABIC LETTER DOTLESS QAF;Lo;0;AL;;;;;N;;;;;
-0670;ARABIC LETTER SUPERSCRIPT ALEF;Mn;35;NSM;;;;;N;ARABIC ALEF ABOVE;;;;
-0671;ARABIC LETTER ALEF WASLA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAT WASL ON ALEF;;;;
-0672;ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH ON ALEF;;;;
-0673;ARABIC LETTER ALEF WITH WAVY HAMZA BELOW;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH UNDER ALEF;;;;
-0674;ARABIC LETTER HIGH HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HIGH HAMZAH;;;;
-0675;ARABIC LETTER HIGH HAMZA ALEF;Lo;0;AL;<compat> 0627 0674;;;;N;ARABIC LETTER HIGH HAMZAH ALEF;;;;
-0676;ARABIC LETTER HIGH HAMZA WAW;Lo;0;AL;<compat> 0648 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW;;;;
-0677;ARABIC LETTER U WITH HAMZA ABOVE;Lo;0;AL;<compat> 06C7 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW WITH DAMMAH;;;;
-0678;ARABIC LETTER HIGH HAMZA YEH;Lo;0;AL;<compat> 064A 0674;;;;N;ARABIC LETTER HIGH HAMZAH YA;;;;
-0679;ARABIC LETTER TTEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH SMALL TAH;;;;
-067A;ARABIC LETTER TTEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH TWO DOTS VERTICAL ABOVE;;;;
-067B;ARABIC LETTER BEEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH TWO DOTS VERTICAL BELOW;;;;
-067C;ARABIC LETTER TEH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH RING;;;;
-067D;ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS ABOVE DOWNWARD;;;;
-067E;ARABIC LETTER PEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS BELOW;;;;
-067F;ARABIC LETTER TEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH FOUR DOTS ABOVE;;;;
-0680;ARABIC LETTER BEHEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH FOUR DOTS BELOW;;;;
-0681;ARABIC LETTER HAH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH ON HAA;;;;
-0682;ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH TWO DOTS VERTICAL ABOVE;;;;
-0683;ARABIC LETTER NYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS;;;;
-0684;ARABIC LETTER DYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS VERTICAL;;;;
-0685;ARABIC LETTER HAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH THREE DOTS ABOVE;;;;
-0686;ARABIC LETTER TCHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE THREE DOTS DOWNWARD;;;;
-0687;ARABIC LETTER TCHEHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE FOUR DOTS;;;;
-0688;ARABIC LETTER DDAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH SMALL TAH;;;;
-0689;ARABIC LETTER DAL WITH RING;Lo;0;AL;;;;;N;;;;;
-068A;ARABIC LETTER DAL WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
-068B;ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;;
-068C;ARABIC LETTER DAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS ABOVE;;;;
-068D;ARABIC LETTER DDAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS BELOW;;;;
-068E;ARABIC LETTER DUL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE;;;;
-068F;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARD;;;;
-0690;ARABIC LETTER DAL WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-0691;ARABIC LETTER RREH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL TAH;;;;
-0692;ARABIC LETTER REH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V;;;;
-0693;ARABIC LETTER REH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH RING;;;;
-0694;ARABIC LETTER REH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW;;;;
-0695;ARABIC LETTER REH WITH SMALL V BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V BELOW;;;;
-0696;ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW AND DOT ABOVE;;;;
-0697;ARABIC LETTER REH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH TWO DOTS ABOVE;;;;
-0698;ARABIC LETTER JEH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH THREE DOTS ABOVE;;;;
-0699;ARABIC LETTER REH WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH FOUR DOTS ABOVE;;;;
-069A;ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-069B;ARABIC LETTER SEEN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
-069C;ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-069D;ARABIC LETTER SAD WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
-069E;ARABIC LETTER SAD WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-069F;ARABIC LETTER TAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-06A0;ARABIC LETTER AIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-06A1;ARABIC LETTER DOTLESS FEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS FA;;;;
-06A2;ARABIC LETTER FEH WITH DOT MOVED BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT MOVED BELOW;;;;
-06A3;ARABIC LETTER FEH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT BELOW;;;;
-06A4;ARABIC LETTER VEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS ABOVE;;;;
-06A5;ARABIC LETTER FEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS BELOW;;;;
-06A6;ARABIC LETTER PEHEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH FOUR DOTS ABOVE;;;;
-06A7;ARABIC LETTER QAF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-06A8;ARABIC LETTER QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-06A9;ARABIC LETTER KEHEH;Lo;0;AL;;;;;N;ARABIC LETTER OPEN CAF;;;;
-06AA;ARABIC LETTER SWASH KAF;Lo;0;AL;;;;;N;ARABIC LETTER SWASH CAF;;;;
-06AB;ARABIC LETTER KAF WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH RING;;;;
-06AC;ARABIC LETTER KAF WITH DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH DOT ABOVE;;;;
-06AD;ARABIC LETTER NG;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS ABOVE;;;;
-06AE;ARABIC LETTER KAF WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS BELOW;;;;
-06AF;ARABIC LETTER GAF;Lo;0;AL;;;;;N;;;;;
-06B0;ARABIC LETTER GAF WITH RING;Lo;0;AL;;;;;N;;;;;
-06B1;ARABIC LETTER NGOEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS ABOVE;;;;
-06B2;ARABIC LETTER GAF WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
-06B3;ARABIC LETTER GUEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS VERTICAL BELOW;;;;
-06B4;ARABIC LETTER GAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-06B5;ARABIC LETTER LAM WITH SMALL V;Lo;0;AL;;;;;N;;;;;
-06B6;ARABIC LETTER LAM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-06B7;ARABIC LETTER LAM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-06B8;ARABIC LETTER LAM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
-06B9;ARABIC LETTER NOON WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
-06BA;ARABIC LETTER NOON GHUNNA;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON;;;;
-06BB;ARABIC LETTER RNOON;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON WITH SMALL TAH;;;;
-06BC;ARABIC LETTER NOON WITH RING;Lo;0;AL;;;;;N;;;;;
-06BD;ARABIC LETTER NOON WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-06BE;ARABIC LETTER HEH DOACHASHMEE;Lo;0;AL;;;;;N;ARABIC LETTER KNOTTED HA;;;;
-06BF;ARABIC LETTER TCHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-06C0;ARABIC LETTER HEH WITH YEH ABOVE;Lo;0;AL;06D5 0654;;;;N;ARABIC LETTER HAMZAH ON HA;;;;
-06C1;ARABIC LETTER HEH GOAL;Lo;0;AL;;;;;N;ARABIC LETTER HA GOAL;;;;
-06C2;ARABIC LETTER HEH GOAL WITH HAMZA ABOVE;Lo;0;AL;06C1 0654;;;;N;ARABIC LETTER HAMZAH ON HA GOAL;;;;
-06C3;ARABIC LETTER TEH MARBUTA GOAL;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH GOAL;;;;
-06C4;ARABIC LETTER WAW WITH RING;Lo;0;AL;;;;;N;;;;;
-06C5;ARABIC LETTER KIRGHIZ OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH BAR;;;;
-06C6;ARABIC LETTER OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH SMALL V;;;;
-06C7;ARABIC LETTER U;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH DAMMAH;;;;
-06C8;ARABIC LETTER YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH ALEF ABOVE;;;;
-06C9;ARABIC LETTER KIRGHIZ YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH INVERTED SMALL V;;;;
-06CA;ARABIC LETTER WAW WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-06CB;ARABIC LETTER VE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH THREE DOTS ABOVE;;;;
-06CC;ARABIC LETTER FARSI YEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS YA;;;;
-06CD;ARABIC LETTER YEH WITH TAIL;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TAIL;;;;
-06CE;ARABIC LETTER YEH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH SMALL V;;;;
-06CF;ARABIC LETTER WAW WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-06D0;ARABIC LETTER E;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TWO DOTS VERTICAL BELOW;;;;
-06D1;ARABIC LETTER YEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH THREE DOTS BELOW;;;;
-06D2;ARABIC LETTER YEH BARREE;Lo;0;AL;;;;;N;ARABIC LETTER YA BARREE;;;;
-06D3;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE;Lo;0;AL;06D2 0654;;;;N;ARABIC LETTER HAMZAH ON YA BARREE;;;;
-06D4;ARABIC FULL STOP;Po;0;AL;;;;;N;ARABIC PERIOD;;;;
-06D5;ARABIC LETTER AE;Lo;0;AL;;;;;N;;;;;
-06D6;ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;;
-06D7;ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;;
-06D8;ARABIC SMALL HIGH MEEM INITIAL FORM;Mn;230;NSM;;;;;N;;;;;
-06D9;ARABIC SMALL HIGH LAM ALEF;Mn;230;NSM;;;;;N;;;;;
-06DA;ARABIC SMALL HIGH JEEM;Mn;230;NSM;;;;;N;;;;;
-06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;;
-06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;;
-06DD;ARABIC END OF AYAH;Cf;0;AN;;;;;N;;;;;
-06DE;ARABIC START OF RUB EL HIZB;So;0;ON;;;;;N;;;;;
-06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;;
-06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;;
-06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;;
-06E2;ARABIC SMALL HIGH MEEM ISOLATED FORM;Mn;230;NSM;;;;;N;;;;;
-06E3;ARABIC SMALL LOW SEEN;Mn;220;NSM;;;;;N;;;;;
-06E4;ARABIC SMALL HIGH MADDA;Mn;230;NSM;;;;;N;;;;;
-06E5;ARABIC SMALL WAW;Lm;0;AL;;;;;N;;;;;
-06E6;ARABIC SMALL YEH;Lm;0;AL;;;;;N;;;;;
-06E7;ARABIC SMALL HIGH YEH;Mn;230;NSM;;;;;N;;;;;
-06E8;ARABIC SMALL HIGH NOON;Mn;230;NSM;;;;;N;;;;;
-06E9;ARABIC PLACE OF SAJDAH;So;0;ON;;;;;N;;;;;
-06EA;ARABIC EMPTY CENTRE LOW STOP;Mn;220;NSM;;;;;N;;;;;
-06EB;ARABIC EMPTY CENTRE HIGH STOP;Mn;230;NSM;;;;;N;;;;;
-06EC;ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE;Mn;230;NSM;;;;;N;;;;;
-06ED;ARABIC SMALL LOW MEEM;Mn;220;NSM;;;;;N;;;;;
-06EE;ARABIC LETTER DAL WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
-06EF;ARABIC LETTER REH WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
-06F0;EXTENDED ARABIC-INDIC DIGIT ZERO;Nd;0;EN;;0;0;0;N;EASTERN ARABIC-INDIC DIGIT ZERO;;;;
-06F1;EXTENDED ARABIC-INDIC DIGIT ONE;Nd;0;EN;;1;1;1;N;EASTERN ARABIC-INDIC DIGIT ONE;;;;
-06F2;EXTENDED ARABIC-INDIC DIGIT TWO;Nd;0;EN;;2;2;2;N;EASTERN ARABIC-INDIC DIGIT TWO;;;;
-06F3;EXTENDED ARABIC-INDIC DIGIT THREE;Nd;0;EN;;3;3;3;N;EASTERN ARABIC-INDIC DIGIT THREE;;;;
-06F4;EXTENDED ARABIC-INDIC DIGIT FOUR;Nd;0;EN;;4;4;4;N;EASTERN ARABIC-INDIC DIGIT FOUR;;;;
-06F5;EXTENDED ARABIC-INDIC DIGIT FIVE;Nd;0;EN;;5;5;5;N;EASTERN ARABIC-INDIC DIGIT FIVE;;;;
-06F6;EXTENDED ARABIC-INDIC DIGIT SIX;Nd;0;EN;;6;6;6;N;EASTERN ARABIC-INDIC DIGIT SIX;;;;
-06F7;EXTENDED ARABIC-INDIC DIGIT SEVEN;Nd;0;EN;;7;7;7;N;EASTERN ARABIC-INDIC DIGIT SEVEN;;;;
-06F8;EXTENDED ARABIC-INDIC DIGIT EIGHT;Nd;0;EN;;8;8;8;N;EASTERN ARABIC-INDIC DIGIT EIGHT;;;;
-06F9;EXTENDED ARABIC-INDIC DIGIT NINE;Nd;0;EN;;9;9;9;N;EASTERN ARABIC-INDIC DIGIT NINE;;;;
-06FA;ARABIC LETTER SHEEN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
-06FB;ARABIC LETTER DAD WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
-06FC;ARABIC LETTER GHAIN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
-06FD;ARABIC SIGN SINDHI AMPERSAND;So;0;AL;;;;;N;;;;;
-06FE;ARABIC SIGN SINDHI POSTPOSITION MEN;So;0;AL;;;;;N;;;;;
-06FF;ARABIC LETTER HEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
-0700;SYRIAC END OF PARAGRAPH;Po;0;AL;;;;;N;;;;;
-0701;SYRIAC SUPRALINEAR FULL STOP;Po;0;AL;;;;;N;;;;;
-0702;SYRIAC SUBLINEAR FULL STOP;Po;0;AL;;;;;N;;;;;
-0703;SYRIAC SUPRALINEAR COLON;Po;0;AL;;;;;N;;;;;
-0704;SYRIAC SUBLINEAR COLON;Po;0;AL;;;;;N;;;;;
-0705;SYRIAC HORIZONTAL COLON;Po;0;AL;;;;;N;;;;;
-0706;SYRIAC COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;;
-0707;SYRIAC COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;;
-0708;SYRIAC SUPRALINEAR COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;;
-0709;SYRIAC SUBLINEAR COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;;
-070A;SYRIAC CONTRACTION;Po;0;AL;;;;;N;;;;;
-070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;;
-070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;;
-070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;;
-070F;SYRIAC ABBREVIATION MARK;Cf;0;AL;;;;;N;;;;;
-0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;;
-0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;;
-0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;;
-0713;SYRIAC LETTER GAMAL;Lo;0;AL;;;;;N;;;;;
-0714;SYRIAC LETTER GAMAL GARSHUNI;Lo;0;AL;;;;;N;;;;;
-0715;SYRIAC LETTER DALATH;Lo;0;AL;;;;;N;;;;;
-0716;SYRIAC LETTER DOTLESS DALATH RISH;Lo;0;AL;;;;;N;;;;;
-0717;SYRIAC LETTER HE;Lo;0;AL;;;;;N;;;;;
-0718;SYRIAC LETTER WAW;Lo;0;AL;;;;;N;;;;;
-0719;SYRIAC LETTER ZAIN;Lo;0;AL;;;;;N;;;;;
-071A;SYRIAC LETTER HETH;Lo;0;AL;;;;;N;;;;;
-071B;SYRIAC LETTER TETH;Lo;0;AL;;;;;N;;;;;
-071C;SYRIAC LETTER TETH GARSHUNI;Lo;0;AL;;;;;N;;;;;
-071D;SYRIAC LETTER YUDH;Lo;0;AL;;;;;N;;;;;
-071E;SYRIAC LETTER YUDH HE;Lo;0;AL;;;;;N;;;;;
-071F;SYRIAC LETTER KAPH;Lo;0;AL;;;;;N;;;;;
-0720;SYRIAC LETTER LAMADH;Lo;0;AL;;;;;N;;;;;
-0721;SYRIAC LETTER MIM;Lo;0;AL;;;;;N;;;;;
-0722;SYRIAC LETTER NUN;Lo;0;AL;;;;;N;;;;;
-0723;SYRIAC LETTER SEMKATH;Lo;0;AL;;;;;N;;;;;
-0724;SYRIAC LETTER FINAL SEMKATH;Lo;0;AL;;;;;N;;;;;
-0725;SYRIAC LETTER E;Lo;0;AL;;;;;N;;;;;
-0726;SYRIAC LETTER PE;Lo;0;AL;;;;;N;;;;;
-0727;SYRIAC LETTER REVERSED PE;Lo;0;AL;;;;;N;;;;;
-0728;SYRIAC LETTER SADHE;Lo;0;AL;;;;;N;;;;;
-0729;SYRIAC LETTER QAPH;Lo;0;AL;;;;;N;;;;;
-072A;SYRIAC LETTER RISH;Lo;0;AL;;;;;N;;;;;
-072B;SYRIAC LETTER SHIN;Lo;0;AL;;;;;N;;;;;
-072C;SYRIAC LETTER TAW;Lo;0;AL;;;;;N;;;;;
-072D;SYRIAC LETTER PERSIAN BHETH;Lo;0;AL;;;;;N;;;;;
-072E;SYRIAC LETTER PERSIAN GHAMAL;Lo;0;AL;;;;;N;;;;;
-072F;SYRIAC LETTER PERSIAN DHALATH;Lo;0;AL;;;;;N;;;;;
-0730;SYRIAC PTHAHA ABOVE;Mn;230;NSM;;;;;N;;;;;
-0731;SYRIAC PTHAHA BELOW;Mn;220;NSM;;;;;N;;;;;
-0732;SYRIAC PTHAHA DOTTED;Mn;230;NSM;;;;;N;;;;;
-0733;SYRIAC ZQAPHA ABOVE;Mn;230;NSM;;;;;N;;;;;
-0734;SYRIAC ZQAPHA BELOW;Mn;220;NSM;;;;;N;;;;;
-0735;SYRIAC ZQAPHA DOTTED;Mn;230;NSM;;;;;N;;;;;
-0736;SYRIAC RBASA ABOVE;Mn;230;NSM;;;;;N;;;;;
-0737;SYRIAC RBASA BELOW;Mn;220;NSM;;;;;N;;;;;
-0738;SYRIAC DOTTED ZLAMA HORIZONTAL;Mn;220;NSM;;;;;N;;;;;
-0739;SYRIAC DOTTED ZLAMA ANGULAR;Mn;220;NSM;;;;;N;;;;;
-073A;SYRIAC HBASA ABOVE;Mn;230;NSM;;;;;N;;;;;
-073B;SYRIAC HBASA BELOW;Mn;220;NSM;;;;;N;;;;;
-073C;SYRIAC HBASA-ESASA DOTTED;Mn;220;NSM;;;;;N;;;;;
-073D;SYRIAC ESASA ABOVE;Mn;230;NSM;;;;;N;;;;;
-073E;SYRIAC ESASA BELOW;Mn;220;NSM;;;;;N;;;;;
-073F;SYRIAC RWAHA;Mn;230;NSM;;;;;N;;;;;
-0740;SYRIAC FEMININE DOT;Mn;230;NSM;;;;;N;;;;;
-0741;SYRIAC QUSHSHAYA;Mn;230;NSM;;;;;N;;;;;
-0742;SYRIAC RUKKAKHA;Mn;220;NSM;;;;;N;;;;;
-0743;SYRIAC TWO VERTICAL DOTS ABOVE;Mn;230;NSM;;;;;N;;;;;
-0744;SYRIAC TWO VERTICAL DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
-0745;SYRIAC THREE DOTS ABOVE;Mn;230;NSM;;;;;N;;;;;
-0746;SYRIAC THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
-0747;SYRIAC OBLIQUE LINE ABOVE;Mn;230;NSM;;;;;N;;;;;
-0748;SYRIAC OBLIQUE LINE BELOW;Mn;220;NSM;;;;;N;;;;;
-0749;SYRIAC MUSIC;Mn;230;NSM;;;;;N;;;;;
-074A;SYRIAC BARREKH;Mn;230;NSM;;;;;N;;;;;
-074D;SYRIAC LETTER SOGDIAN ZHAIN;Lo;0;AL;;;;;N;;;;;
-074E;SYRIAC LETTER SOGDIAN KHAPH;Lo;0;AL;;;;;N;;;;;
-074F;SYRIAC LETTER SOGDIAN FE;Lo;0;AL;;;;;N;;;;;
-0750;ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW;Lo;0;AL;;;;;N;;;;;
-0751;ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-0752;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;;
-0753;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-0754;ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-0755;ARABIC LETTER BEH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;;
-0756;ARABIC LETTER BEH WITH SMALL V;Lo;0;AL;;;;;N;;;;;
-0757;ARABIC LETTER HAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-0758;ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;;
-0759;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;;
-075A;ARABIC LETTER DAL WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;;
-075B;ARABIC LETTER REH WITH STROKE;Lo;0;AL;;;;;N;;;;;
-075C;ARABIC LETTER SEEN WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-075D;ARABIC LETTER AIN WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-075E;ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE;Lo;0;AL;;;;;N;;;;;
-075F;ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;;
-0760;ARABIC LETTER FEH WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
-0761;ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;;
-0762;ARABIC LETTER KEHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-0763;ARABIC LETTER KEHEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-0764;ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;;
-0765;ARABIC LETTER MEEM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-0766;ARABIC LETTER MEEM WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
-0767;ARABIC LETTER NOON WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
-0768;ARABIC LETTER NOON WITH SMALL TAH;Lo;0;AL;;;;;N;;;;;
-0769;ARABIC LETTER NOON WITH SMALL V;Lo;0;AL;;;;;N;;;;;
-076A;ARABIC LETTER LAM WITH BAR;Lo;0;AL;;;;;N;;;;;
-076B;ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;;
-076C;ARABIC LETTER REH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;;
-076D;ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;;
-076E;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW;Lo;0;AL;;;;;N;;;;;
-076F;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;;
-0770;ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;;
-0771;ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;;
-0772;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;;
-0773;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;;
-0774;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;;
-0775;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;;
-0776;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;;
-0777;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;;
-0778;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;;
-0779;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;;
-077A;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;;
-077B;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;;
-077C;ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;;
-077D;ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE;Lo;0;AL;;;;;N;;;;;
-077E;ARABIC LETTER SEEN WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
-077F;ARABIC LETTER KAF WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-0780;THAANA LETTER HAA;Lo;0;AL;;;;;N;;;;;
-0781;THAANA LETTER SHAVIYANI;Lo;0;AL;;;;;N;;;;;
-0782;THAANA LETTER NOONU;Lo;0;AL;;;;;N;;;;;
-0783;THAANA LETTER RAA;Lo;0;AL;;;;;N;;;;;
-0784;THAANA LETTER BAA;Lo;0;AL;;;;;N;;;;;
-0785;THAANA LETTER LHAVIYANI;Lo;0;AL;;;;;N;;;;;
-0786;THAANA LETTER KAAFU;Lo;0;AL;;;;;N;;;;;
-0787;THAANA LETTER ALIFU;Lo;0;AL;;;;;N;;;;;
-0788;THAANA LETTER VAAVU;Lo;0;AL;;;;;N;;;;;
-0789;THAANA LETTER MEEMU;Lo;0;AL;;;;;N;;;;;
-078A;THAANA LETTER FAAFU;Lo;0;AL;;;;;N;;;;;
-078B;THAANA LETTER DHAALU;Lo;0;AL;;;;;N;;;;;
-078C;THAANA LETTER THAA;Lo;0;AL;;;;;N;;;;;
-078D;THAANA LETTER LAAMU;Lo;0;AL;;;;;N;;;;;
-078E;THAANA LETTER GAAFU;Lo;0;AL;;;;;N;;;;;
-078F;THAANA LETTER GNAVIYANI;Lo;0;AL;;;;;N;;;;;
-0790;THAANA LETTER SEENU;Lo;0;AL;;;;;N;;;;;
-0791;THAANA LETTER DAVIYANI;Lo;0;AL;;;;;N;;;;;
-0792;THAANA LETTER ZAVIYANI;Lo;0;AL;;;;;N;;;;;
-0793;THAANA LETTER TAVIYANI;Lo;0;AL;;;;;N;;;;;
-0794;THAANA LETTER YAA;Lo;0;AL;;;;;N;;;;;
-0795;THAANA LETTER PAVIYANI;Lo;0;AL;;;;;N;;;;;
-0796;THAANA LETTER JAVIYANI;Lo;0;AL;;;;;N;;;;;
-0797;THAANA LETTER CHAVIYANI;Lo;0;AL;;;;;N;;;;;
-0798;THAANA LETTER TTAA;Lo;0;AL;;;;;N;;;;;
-0799;THAANA LETTER HHAA;Lo;0;AL;;;;;N;;;;;
-079A;THAANA LETTER KHAA;Lo;0;AL;;;;;N;;;;;
-079B;THAANA LETTER THAALU;Lo;0;AL;;;;;N;;;;;
-079C;THAANA LETTER ZAA;Lo;0;AL;;;;;N;;;;;
-079D;THAANA LETTER SHEENU;Lo;0;AL;;;;;N;;;;;
-079E;THAANA LETTER SAADHU;Lo;0;AL;;;;;N;;;;;
-079F;THAANA LETTER DAADHU;Lo;0;AL;;;;;N;;;;;
-07A0;THAANA LETTER TO;Lo;0;AL;;;;;N;;;;;
-07A1;THAANA LETTER ZO;Lo;0;AL;;;;;N;;;;;
-07A2;THAANA LETTER AINU;Lo;0;AL;;;;;N;;;;;
-07A3;THAANA LETTER GHAINU;Lo;0;AL;;;;;N;;;;;
-07A4;THAANA LETTER QAAFU;Lo;0;AL;;;;;N;;;;;
-07A5;THAANA LETTER WAAVU;Lo;0;AL;;;;;N;;;;;
-07A6;THAANA ABAFILI;Mn;0;NSM;;;;;N;;;;;
-07A7;THAANA AABAAFILI;Mn;0;NSM;;;;;N;;;;;
-07A8;THAANA IBIFILI;Mn;0;NSM;;;;;N;;;;;
-07A9;THAANA EEBEEFILI;Mn;0;NSM;;;;;N;;;;;
-07AA;THAANA UBUFILI;Mn;0;NSM;;;;;N;;;;;
-07AB;THAANA OOBOOFILI;Mn;0;NSM;;;;;N;;;;;
-07AC;THAANA EBEFILI;Mn;0;NSM;;;;;N;;;;;
-07AD;THAANA EYBEYFILI;Mn;0;NSM;;;;;N;;;;;
-07AE;THAANA OBOFILI;Mn;0;NSM;;;;;N;;;;;
-07AF;THAANA OABOAFILI;Mn;0;NSM;;;;;N;;;;;
-07B0;THAANA SUKUN;Mn;0;NSM;;;;;N;;;;;
-07B1;THAANA LETTER NAA;Lo;0;AL;;;;;N;;;;;
-07C0;NKO DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;;
-07C1;NKO DIGIT ONE;Nd;0;R;;1;1;1;N;;;;;
-07C2;NKO DIGIT TWO;Nd;0;R;;2;2;2;N;;;;;
-07C3;NKO DIGIT THREE;Nd;0;R;;3;3;3;N;;;;;
-07C4;NKO DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;;
-07C5;NKO DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;;
-07C6;NKO DIGIT SIX;Nd;0;R;;6;6;6;N;;;;;
-07C7;NKO DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;;
-07C8;NKO DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;;
-07C9;NKO DIGIT NINE;Nd;0;R;;9;9;9;N;;;;;
-07CA;NKO LETTER A;Lo;0;R;;;;;N;;;;;
-07CB;NKO LETTER EE;Lo;0;R;;;;;N;;;;;
-07CC;NKO LETTER I;Lo;0;R;;;;;N;;;;;
-07CD;NKO LETTER E;Lo;0;R;;;;;N;;;;;
-07CE;NKO LETTER U;Lo;0;R;;;;;N;;;;;
-07CF;NKO LETTER OO;Lo;0;R;;;;;N;;;;;
-07D0;NKO LETTER O;Lo;0;R;;;;;N;;;;;
-07D1;NKO LETTER DAGBASINNA;Lo;0;R;;;;;N;;;;;
-07D2;NKO LETTER N;Lo;0;R;;;;;N;;;;;
-07D3;NKO LETTER BA;Lo;0;R;;;;;N;;;;;
-07D4;NKO LETTER PA;Lo;0;R;;;;;N;;;;;
-07D5;NKO LETTER TA;Lo;0;R;;;;;N;;;;;
-07D6;NKO LETTER JA;Lo;0;R;;;;;N;;;;;
-07D7;NKO LETTER CHA;Lo;0;R;;;;;N;;;;;
-07D8;NKO LETTER DA;Lo;0;R;;;;;N;;;;;
-07D9;NKO LETTER RA;Lo;0;R;;;;;N;;;;;
-07DA;NKO LETTER RRA;Lo;0;R;;;;;N;;;;;
-07DB;NKO LETTER SA;Lo;0;R;;;;;N;;;;;
-07DC;NKO LETTER GBA;Lo;0;R;;;;;N;;;;;
-07DD;NKO LETTER FA;Lo;0;R;;;;;N;;;;;
-07DE;NKO LETTER KA;Lo;0;R;;;;;N;;;;;
-07DF;NKO LETTER LA;Lo;0;R;;;;;N;;;;;
-07E0;NKO LETTER NA WOLOSO;Lo;0;R;;;;;N;;;;;
-07E1;NKO LETTER MA;Lo;0;R;;;;;N;;;;;
-07E2;NKO LETTER NYA;Lo;0;R;;;;;N;;;;;
-07E3;NKO LETTER NA;Lo;0;R;;;;;N;;;;;
-07E4;NKO LETTER HA;Lo;0;R;;;;;N;;;;;
-07E5;NKO LETTER WA;Lo;0;R;;;;;N;;;;;
-07E6;NKO LETTER YA;Lo;0;R;;;;;N;;;;;
-07E7;NKO LETTER NYA WOLOSO;Lo;0;R;;;;;N;;;;;
-07E8;NKO LETTER JONA JA;Lo;0;R;;;;;N;;;;;
-07E9;NKO LETTER JONA CHA;Lo;0;R;;;;;N;;;;;
-07EA;NKO LETTER JONA RA;Lo;0;R;;;;;N;;;;;
-07EB;NKO COMBINING SHORT HIGH TONE;Mn;230;NSM;;;;;N;;;;;
-07EC;NKO COMBINING SHORT LOW TONE;Mn;230;NSM;;;;;N;;;;;
-07ED;NKO COMBINING SHORT RISING TONE;Mn;230;NSM;;;;;N;;;;;
-07EE;NKO COMBINING LONG DESCENDING TONE;Mn;230;NSM;;;;;N;;;;;
-07EF;NKO COMBINING LONG HIGH TONE;Mn;230;NSM;;;;;N;;;;;
-07F0;NKO COMBINING LONG LOW TONE;Mn;230;NSM;;;;;N;;;;;
-07F1;NKO COMBINING LONG RISING TONE;Mn;230;NSM;;;;;N;;;;;
-07F2;NKO COMBINING NASALIZATION MARK;Mn;220;NSM;;;;;N;;;;;
-07F3;NKO COMBINING DOUBLE DOT ABOVE;Mn;230;NSM;;;;;N;;;;;
-07F4;NKO HIGH TONE APOSTROPHE;Lm;0;R;;;;;N;;;;;
-07F5;NKO LOW TONE APOSTROPHE;Lm;0;R;;;;;N;;;;;
-07F6;NKO SYMBOL OO DENNEN;So;0;ON;;;;;N;;;;;
-07F7;NKO SYMBOL GBAKURUNEN;Po;0;ON;;;;;N;;;;;
-07F8;NKO COMMA;Po;0;ON;;;;;N;;;;;
-07F9;NKO EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
-07FA;NKO LAJANYALAN;Lm;0;R;;;;;N;;;;;
-0800;SAMARITAN LETTER ALAF;Lo;0;R;;;;;N;;;;;
-0801;SAMARITAN LETTER BIT;Lo;0;R;;;;;N;;;;;
-0802;SAMARITAN LETTER GAMAN;Lo;0;R;;;;;N;;;;;
-0803;SAMARITAN LETTER DALAT;Lo;0;R;;;;;N;;;;;
-0804;SAMARITAN LETTER IY;Lo;0;R;;;;;N;;;;;
-0805;SAMARITAN LETTER BAA;Lo;0;R;;;;;N;;;;;
-0806;SAMARITAN LETTER ZEN;Lo;0;R;;;;;N;;;;;
-0807;SAMARITAN LETTER IT;Lo;0;R;;;;;N;;;;;
-0808;SAMARITAN LETTER TIT;Lo;0;R;;;;;N;;;;;
-0809;SAMARITAN LETTER YUT;Lo;0;R;;;;;N;;;;;
-080A;SAMARITAN LETTER KAAF;Lo;0;R;;;;;N;;;;;
-080B;SAMARITAN LETTER LABAT;Lo;0;R;;;;;N;;;;;
-080C;SAMARITAN LETTER MIM;Lo;0;R;;;;;N;;;;;
-080D;SAMARITAN LETTER NUN;Lo;0;R;;;;;N;;;;;
-080E;SAMARITAN LETTER SINGAAT;Lo;0;R;;;;;N;;;;;
-080F;SAMARITAN LETTER IN;Lo;0;R;;;;;N;;;;;
-0810;SAMARITAN LETTER FI;Lo;0;R;;;;;N;;;;;
-0811;SAMARITAN LETTER TSAADIY;Lo;0;R;;;;;N;;;;;
-0812;SAMARITAN LETTER QUF;Lo;0;R;;;;;N;;;;;
-0813;SAMARITAN LETTER RISH;Lo;0;R;;;;;N;;;;;
-0814;SAMARITAN LETTER SHAN;Lo;0;R;;;;;N;;;;;
-0815;SAMARITAN LETTER TAAF;Lo;0;R;;;;;N;;;;;
-0816;SAMARITAN MARK IN;Mn;230;NSM;;;;;N;;;;;
-0817;SAMARITAN MARK IN-ALAF;Mn;230;NSM;;;;;N;;;;;
-0818;SAMARITAN MARK OCCLUSION;Mn;230;NSM;;;;;N;;;;;
-0819;SAMARITAN MARK DAGESH;Mn;230;NSM;;;;;N;;;;;
-081A;SAMARITAN MODIFIER LETTER EPENTHETIC YUT;Lm;0;R;;;;;N;;;;;
-081B;SAMARITAN MARK EPENTHETIC YUT;Mn;230;NSM;;;;;N;;;;;
-081C;SAMARITAN VOWEL SIGN LONG E;Mn;230;NSM;;;;;N;;;;;
-081D;SAMARITAN VOWEL SIGN E;Mn;230;NSM;;;;;N;;;;;
-081E;SAMARITAN VOWEL SIGN OVERLONG AA;Mn;230;NSM;;;;;N;;;;;
-081F;SAMARITAN VOWEL SIGN LONG AA;Mn;230;NSM;;;;;N;;;;;
-0820;SAMARITAN VOWEL SIGN AA;Mn;230;NSM;;;;;N;;;;;
-0821;SAMARITAN VOWEL SIGN OVERLONG A;Mn;230;NSM;;;;;N;;;;;
-0822;SAMARITAN VOWEL SIGN LONG A;Mn;230;NSM;;;;;N;;;;;
-0823;SAMARITAN VOWEL SIGN A;Mn;230;NSM;;;;;N;;;;;
-0824;SAMARITAN MODIFIER LETTER SHORT A;Lm;0;R;;;;;N;;;;;
-0825;SAMARITAN VOWEL SIGN SHORT A;Mn;230;NSM;;;;;N;;;;;
-0826;SAMARITAN VOWEL SIGN LONG U;Mn;230;NSM;;;;;N;;;;;
-0827;SAMARITAN VOWEL SIGN U;Mn;230;NSM;;;;;N;;;;;
-0828;SAMARITAN MODIFIER LETTER I;Lm;0;R;;;;;N;;;;;
-0829;SAMARITAN VOWEL SIGN LONG I;Mn;230;NSM;;;;;N;;;;;
-082A;SAMARITAN VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;;
-082B;SAMARITAN VOWEL SIGN O;Mn;230;NSM;;;;;N;;;;;
-082C;SAMARITAN VOWEL SIGN SUKUN;Mn;230;NSM;;;;;N;;;;;
-082D;SAMARITAN MARK NEQUDAA;Mn;230;NSM;;;;;N;;;;;
-0830;SAMARITAN PUNCTUATION NEQUDAA;Po;0;R;;;;;N;;;;;
-0831;SAMARITAN PUNCTUATION AFSAAQ;Po;0;R;;;;;N;;;;;
-0832;SAMARITAN PUNCTUATION ANGED;Po;0;R;;;;;N;;;;;
-0833;SAMARITAN PUNCTUATION BAU;Po;0;R;;;;;N;;;;;
-0834;SAMARITAN PUNCTUATION ATMAAU;Po;0;R;;;;;N;;;;;
-0835;SAMARITAN PUNCTUATION SHIYYAALAA;Po;0;R;;;;;N;;;;;
-0836;SAMARITAN ABBREVIATION MARK;Po;0;R;;;;;N;;;;;
-0837;SAMARITAN PUNCTUATION MELODIC QITSA;Po;0;R;;;;;N;;;;;
-0838;SAMARITAN PUNCTUATION ZIQAA;Po;0;R;;;;;N;;;;;
-0839;SAMARITAN PUNCTUATION QITSA;Po;0;R;;;;;N;;;;;
-083A;SAMARITAN PUNCTUATION ZAEF;Po;0;R;;;;;N;;;;;
-083B;SAMARITAN PUNCTUATION TURU;Po;0;R;;;;;N;;;;;
-083C;SAMARITAN PUNCTUATION ARKAANU;Po;0;R;;;;;N;;;;;
-083D;SAMARITAN PUNCTUATION SOF MASHFAAT;Po;0;R;;;;;N;;;;;
-083E;SAMARITAN PUNCTUATION ANNAAU;Po;0;R;;;;;N;;;;;
-0840;MANDAIC LETTER HALQA;Lo;0;R;;;;;N;;;;;
-0841;MANDAIC LETTER AB;Lo;0;R;;;;;N;;;;;
-0842;MANDAIC LETTER AG;Lo;0;R;;;;;N;;;;;
-0843;MANDAIC LETTER AD;Lo;0;R;;;;;N;;;;;
-0844;MANDAIC LETTER AH;Lo;0;R;;;;;N;;;;;
-0845;MANDAIC LETTER USHENNA;Lo;0;R;;;;;N;;;;;
-0846;MANDAIC LETTER AZ;Lo;0;R;;;;;N;;;;;
-0847;MANDAIC LETTER IT;Lo;0;R;;;;;N;;;;;
-0848;MANDAIC LETTER ATT;Lo;0;R;;;;;N;;;;;
-0849;MANDAIC LETTER AKSA;Lo;0;R;;;;;N;;;;;
-084A;MANDAIC LETTER AK;Lo;0;R;;;;;N;;;;;
-084B;MANDAIC LETTER AL;Lo;0;R;;;;;N;;;;;
-084C;MANDAIC LETTER AM;Lo;0;R;;;;;N;;;;;
-084D;MANDAIC LETTER AN;Lo;0;R;;;;;N;;;;;
-084E;MANDAIC LETTER AS;Lo;0;R;;;;;N;;;;;
-084F;MANDAIC LETTER IN;Lo;0;R;;;;;N;;;;;
-0850;MANDAIC LETTER AP;Lo;0;R;;;;;N;;;;;
-0851;MANDAIC LETTER ASZ;Lo;0;R;;;;;N;;;;;
-0852;MANDAIC LETTER AQ;Lo;0;R;;;;;N;;;;;
-0853;MANDAIC LETTER AR;Lo;0;R;;;;;N;;;;;
-0854;MANDAIC LETTER ASH;Lo;0;R;;;;;N;;;;;
-0855;MANDAIC LETTER AT;Lo;0;R;;;;;N;;;;;
-0856;MANDAIC LETTER DUSHENNA;Lo;0;R;;;;;N;;;;;
-0857;MANDAIC LETTER KAD;Lo;0;R;;;;;N;;;;;
-0858;MANDAIC LETTER AIN;Lo;0;R;;;;;N;;;;;
-0859;MANDAIC AFFRICATION MARK;Mn;220;NSM;;;;;N;;;;;
-085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;;
-085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;;
-085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;;
-08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;;
-08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-08A3;ARABIC LETTER TAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-08A4;ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-08A5;ARABIC LETTER QAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
-08A6;ARABIC LETTER LAM WITH DOUBLE BAR;Lo;0;AL;;;;;N;;;;;
-08A7;ARABIC LETTER MEEM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
-08A8;ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE;Lo;0;AL;;;;;N;;;;;
-08A9;ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
-08AA;ARABIC LETTER REH WITH LOOP;Lo;0;AL;;;;;N;;;;;
-08AB;ARABIC LETTER WAW WITH DOT WITHIN;Lo;0;AL;;;;;N;;;;;
-08AC;ARABIC LETTER ROHINGYA YEH;Lo;0;AL;;;;;N;;;;;
-08E4;ARABIC CURLY FATHA;Mn;230;NSM;;;;;N;;;;;
-08E5;ARABIC CURLY DAMMA;Mn;230;NSM;;;;;N;;;;;
-08E6;ARABIC CURLY KASRA;Mn;220;NSM;;;;;N;;;;;
-08E7;ARABIC CURLY FATHATAN;Mn;230;NSM;;;;;N;;;;;
-08E8;ARABIC CURLY DAMMATAN;Mn;230;NSM;;;;;N;;;;;
-08E9;ARABIC CURLY KASRATAN;Mn;220;NSM;;;;;N;;;;;
-08EA;ARABIC TONE ONE DOT ABOVE;Mn;230;NSM;;;;;N;;;;;
-08EB;ARABIC TONE TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;;
-08EC;ARABIC TONE LOOP ABOVE;Mn;230;NSM;;;;;N;;;;;
-08ED;ARABIC TONE ONE DOT BELOW;Mn;220;NSM;;;;;N;;;;;
-08EE;ARABIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
-08EF;ARABIC TONE LOOP BELOW;Mn;220;NSM;;;;;N;;;;;
-08F0;ARABIC OPEN FATHATAN;Mn;27;NSM;;;;;N;;;;;
-08F1;ARABIC OPEN DAMMATAN;Mn;28;NSM;;;;;N;;;;;
-08F2;ARABIC OPEN KASRATAN;Mn;29;NSM;;;;;N;;;;;
-08F3;ARABIC SMALL HIGH WAW;Mn;230;NSM;;;;;N;;;;;
-08F4;ARABIC FATHA WITH RING;Mn;230;NSM;;;;;N;;;;;
-08F5;ARABIC FATHA WITH DOT ABOVE;Mn;230;NSM;;;;;N;;;;;
-08F6;ARABIC KASRA WITH DOT BELOW;Mn;220;NSM;;;;;N;;;;;
-08F7;ARABIC LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;;
-08F8;ARABIC RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;;
-08F9;ARABIC LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
-08FA;ARABIC RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
-08FB;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;;
-08FC;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;;
-08FD;ARABIC RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;;
-08FE;ARABIC DAMMA WITH DOT;Mn;230;NSM;;;;;N;;;;;
-0900;DEVANAGARI SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
-0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
-0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-0903;DEVANAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-0904;DEVANAGARI LETTER SHORT A;Lo;0;L;;;;;N;;;;;
-0905;DEVANAGARI LETTER A;Lo;0;L;;;;;N;;;;;
-0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;;
-0907;DEVANAGARI LETTER I;Lo;0;L;;;;;N;;;;;
-0908;DEVANAGARI LETTER II;Lo;0;L;;;;;N;;;;;
-0909;DEVANAGARI LETTER U;Lo;0;L;;;;;N;;;;;
-090A;DEVANAGARI LETTER UU;Lo;0;L;;;;;N;;;;;
-090B;DEVANAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-090C;DEVANAGARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-090D;DEVANAGARI LETTER CANDRA E;Lo;0;L;;;;;N;;;;;
-090E;DEVANAGARI LETTER SHORT E;Lo;0;L;;;;;N;;;;;
-090F;DEVANAGARI LETTER E;Lo;0;L;;;;;N;;;;;
-0910;DEVANAGARI LETTER AI;Lo;0;L;;;;;N;;;;;
-0911;DEVANAGARI LETTER CANDRA O;Lo;0;L;;;;;N;;;;;
-0912;DEVANAGARI LETTER SHORT O;Lo;0;L;;;;;N;;;;;
-0913;DEVANAGARI LETTER O;Lo;0;L;;;;;N;;;;;
-0914;DEVANAGARI LETTER AU;Lo;0;L;;;;;N;;;;;
-0915;DEVANAGARI LETTER KA;Lo;0;L;;;;;N;;;;;
-0916;DEVANAGARI LETTER KHA;Lo;0;L;;;;;N;;;;;
-0917;DEVANAGARI LETTER GA;Lo;0;L;;;;;N;;;;;
-0918;DEVANAGARI LETTER GHA;Lo;0;L;;;;;N;;;;;
-0919;DEVANAGARI LETTER NGA;Lo;0;L;;;;;N;;;;;
-091A;DEVANAGARI LETTER CA;Lo;0;L;;;;;N;;;;;
-091B;DEVANAGARI LETTER CHA;Lo;0;L;;;;;N;;;;;
-091C;DEVANAGARI LETTER JA;Lo;0;L;;;;;N;;;;;
-091D;DEVANAGARI LETTER JHA;Lo;0;L;;;;;N;;;;;
-091E;DEVANAGARI LETTER NYA;Lo;0;L;;;;;N;;;;;
-091F;DEVANAGARI LETTER TTA;Lo;0;L;;;;;N;;;;;
-0920;DEVANAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;;
-0921;DEVANAGARI LETTER DDA;Lo;0;L;;;;;N;;;;;
-0922;DEVANAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;;
-0923;DEVANAGARI LETTER NNA;Lo;0;L;;;;;N;;;;;
-0924;DEVANAGARI LETTER TA;Lo;0;L;;;;;N;;;;;
-0925;DEVANAGARI LETTER THA;Lo;0;L;;;;;N;;;;;
-0926;DEVANAGARI LETTER DA;Lo;0;L;;;;;N;;;;;
-0927;DEVANAGARI LETTER DHA;Lo;0;L;;;;;N;;;;;
-0928;DEVANAGARI LETTER NA;Lo;0;L;;;;;N;;;;;
-0929;DEVANAGARI LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;;
-092A;DEVANAGARI LETTER PA;Lo;0;L;;;;;N;;;;;
-092B;DEVANAGARI LETTER PHA;Lo;0;L;;;;;N;;;;;
-092C;DEVANAGARI LETTER BA;Lo;0;L;;;;;N;;;;;
-092D;DEVANAGARI LETTER BHA;Lo;0;L;;;;;N;;;;;
-092E;DEVANAGARI LETTER MA;Lo;0;L;;;;;N;;;;;
-092F;DEVANAGARI LETTER YA;Lo;0;L;;;;;N;;;;;
-0930;DEVANAGARI LETTER RA;Lo;0;L;;;;;N;;;;;
-0931;DEVANAGARI LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;;
-0932;DEVANAGARI LETTER LA;Lo;0;L;;;;;N;;;;;
-0933;DEVANAGARI LETTER LLA;Lo;0;L;;;;;N;;;;;
-0934;DEVANAGARI LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;;
-0935;DEVANAGARI LETTER VA;Lo;0;L;;;;;N;;;;;
-0936;DEVANAGARI LETTER SHA;Lo;0;L;;;;;N;;;;;
-0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;;
-0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;;
-0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;;
-093A;DEVANAGARI VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;;
-093B;DEVANAGARI VOWEL SIGN OOE;Mc;0;L;;;;;N;;;;;
-093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
-093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-093F;DEVANAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-0940;DEVANAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-0941;DEVANAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-0942;DEVANAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-0943;DEVANAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
-0944;DEVANAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
-0945;DEVANAGARI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;;
-0946;DEVANAGARI VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;;
-0947;DEVANAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-0948;DEVANAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-0949;DEVANAGARI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;;
-094A;DEVANAGARI VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;;
-094B;DEVANAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-094E;DEVANAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;;
-094F;DEVANAGARI VOWEL SIGN AW;Mc;0;L;;;;;N;;;;;
-0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;;
-0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;;
-0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;;
-0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;;
-0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;;
-0955;DEVANAGARI VOWEL SIGN CANDRA LONG E;Mn;0;NSM;;;;;N;;;;;
-0956;DEVANAGARI VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;;
-0957;DEVANAGARI VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;;
-0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;;
-0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;;
-095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;;
-095B;DEVANAGARI LETTER ZA;Lo;0;L;091C 093C;;;;N;;;;;
-095C;DEVANAGARI LETTER DDDHA;Lo;0;L;0921 093C;;;;N;;;;;
-095D;DEVANAGARI LETTER RHA;Lo;0;L;0922 093C;;;;N;;;;;
-095E;DEVANAGARI LETTER FA;Lo;0;L;092B 093C;;;;N;;;;;
-095F;DEVANAGARI LETTER YYA;Lo;0;L;092F 093C;;;;N;;;;;
-0960;DEVANAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-0961;DEVANAGARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-0962;DEVANAGARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-0963;DEVANAGARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-0964;DEVANAGARI DANDA;Po;0;L;;;;;N;;;;;
-0965;DEVANAGARI DOUBLE DANDA;Po;0;L;;;;;N;;;;;
-0966;DEVANAGARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0967;DEVANAGARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0968;DEVANAGARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0969;DEVANAGARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-096A;DEVANAGARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-096B;DEVANAGARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-096C;DEVANAGARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-096D;DEVANAGARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-096E;DEVANAGARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-096F;DEVANAGARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
-0971;DEVANAGARI SIGN HIGH SPACING DOT;Lm;0;L;;;;;N;;;;;
-0972;DEVANAGARI LETTER CANDRA A;Lo;0;L;;;;;N;;;;;
-0973;DEVANAGARI LETTER OE;Lo;0;L;;;;;N;;;;;
-0974;DEVANAGARI LETTER OOE;Lo;0;L;;;;;N;;;;;
-0975;DEVANAGARI LETTER AW;Lo;0;L;;;;;N;;;;;
-0976;DEVANAGARI LETTER UE;Lo;0;L;;;;;N;;;;;
-0977;DEVANAGARI LETTER UUE;Lo;0;L;;;;;N;;;;;
-0979;DEVANAGARI LETTER ZHA;Lo;0;L;;;;;N;;;;;
-097A;DEVANAGARI LETTER HEAVY YA;Lo;0;L;;;;;N;;;;;
-097B;DEVANAGARI LETTER GGA;Lo;0;L;;;;;N;;;;;
-097C;DEVANAGARI LETTER JJA;Lo;0;L;;;;;N;;;;;
-097D;DEVANAGARI LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;;
-097E;DEVANAGARI LETTER DDDA;Lo;0;L;;;;;N;;;;;
-097F;DEVANAGARI LETTER BBA;Lo;0;L;;;;;N;;;;;
-0981;BENGALI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
-0982;BENGALI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
-0983;BENGALI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-0985;BENGALI LETTER A;Lo;0;L;;;;;N;;;;;
-0986;BENGALI LETTER AA;Lo;0;L;;;;;N;;;;;
-0987;BENGALI LETTER I;Lo;0;L;;;;;N;;;;;
-0988;BENGALI LETTER II;Lo;0;L;;;;;N;;;;;
-0989;BENGALI LETTER U;Lo;0;L;;;;;N;;;;;
-098A;BENGALI LETTER UU;Lo;0;L;;;;;N;;;;;
-098B;BENGALI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-098C;BENGALI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-098F;BENGALI LETTER E;Lo;0;L;;;;;N;;;;;
-0990;BENGALI LETTER AI;Lo;0;L;;;;;N;;;;;
-0993;BENGALI LETTER O;Lo;0;L;;;;;N;;;;;
-0994;BENGALI LETTER AU;Lo;0;L;;;;;N;;;;;
-0995;BENGALI LETTER KA;Lo;0;L;;;;;N;;;;;
-0996;BENGALI LETTER KHA;Lo;0;L;;;;;N;;;;;
-0997;BENGALI LETTER GA;Lo;0;L;;;;;N;;;;;
-0998;BENGALI LETTER GHA;Lo;0;L;;;;;N;;;;;
-0999;BENGALI LETTER NGA;Lo;0;L;;;;;N;;;;;
-099A;BENGALI LETTER CA;Lo;0;L;;;;;N;;;;;
-099B;BENGALI LETTER CHA;Lo;0;L;;;;;N;;;;;
-099C;BENGALI LETTER JA;Lo;0;L;;;;;N;;;;;
-099D;BENGALI LETTER JHA;Lo;0;L;;;;;N;;;;;
-099E;BENGALI LETTER NYA;Lo;0;L;;;;;N;;;;;
-099F;BENGALI LETTER TTA;Lo;0;L;;;;;N;;;;;
-09A0;BENGALI LETTER TTHA;Lo;0;L;;;;;N;;;;;
-09A1;BENGALI LETTER DDA;Lo;0;L;;;;;N;;;;;
-09A2;BENGALI LETTER DDHA;Lo;0;L;;;;;N;;;;;
-09A3;BENGALI LETTER NNA;Lo;0;L;;;;;N;;;;;
-09A4;BENGALI LETTER TA;Lo;0;L;;;;;N;;;;;
-09A5;BENGALI LETTER THA;Lo;0;L;;;;;N;;;;;
-09A6;BENGALI LETTER DA;Lo;0;L;;;;;N;;;;;
-09A7;BENGALI LETTER DHA;Lo;0;L;;;;;N;;;;;
-09A8;BENGALI LETTER NA;Lo;0;L;;;;;N;;;;;
-09AA;BENGALI LETTER PA;Lo;0;L;;;;;N;;;;;
-09AB;BENGALI LETTER PHA;Lo;0;L;;;;;N;;;;;
-09AC;BENGALI LETTER BA;Lo;0;L;;;;;N;;;;;
-09AD;BENGALI LETTER BHA;Lo;0;L;;;;;N;;;;;
-09AE;BENGALI LETTER MA;Lo;0;L;;;;;N;;;;;
-09AF;BENGALI LETTER YA;Lo;0;L;;;;;N;;;;;
-09B0;BENGALI LETTER RA;Lo;0;L;;;;;N;;;;;
-09B2;BENGALI LETTER LA;Lo;0;L;;;;;N;;;;;
-09B6;BENGALI LETTER SHA;Lo;0;L;;;;;N;;;;;
-09B7;BENGALI LETTER SSA;Lo;0;L;;;;;N;;;;;
-09B8;BENGALI LETTER SA;Lo;0;L;;;;;N;;;;;
-09B9;BENGALI LETTER HA;Lo;0;L;;;;;N;;;;;
-09BC;BENGALI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-09BD;BENGALI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
-09BE;BENGALI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-09BF;BENGALI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-09C0;BENGALI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-09C1;BENGALI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-09C2;BENGALI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-09C3;BENGALI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
-09C4;BENGALI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
-09C7;BENGALI VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-09C8;BENGALI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-09CB;BENGALI VOWEL SIGN O;Mc;0;L;09C7 09BE;;;;N;;;;;
-09CC;BENGALI VOWEL SIGN AU;Mc;0;L;09C7 09D7;;;;N;;;;;
-09CD;BENGALI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-09CE;BENGALI LETTER KHANDA TA;Lo;0;L;;;;;N;;;;;
-09D7;BENGALI AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
-09DC;BENGALI LETTER RRA;Lo;0;L;09A1 09BC;;;;N;;;;;
-09DD;BENGALI LETTER RHA;Lo;0;L;09A2 09BC;;;;N;;;;;
-09DF;BENGALI LETTER YYA;Lo;0;L;09AF 09BC;;;;N;;;;;
-09E0;BENGALI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-09E1;BENGALI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-09E2;BENGALI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-09E3;BENGALI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-09E6;BENGALI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-09E7;BENGALI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-09E8;BENGALI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-09E9;BENGALI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-09EA;BENGALI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-09EB;BENGALI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-09EC;BENGALI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-09ED;BENGALI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-09EE;BENGALI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-09EF;BENGALI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-09F0;BENGALI LETTER RA WITH MIDDLE DIAGONAL;Lo;0;L;;;;;N;;;;;
-09F1;BENGALI LETTER RA WITH LOWER DIAGONAL;Lo;0;L;;;;;N;BENGALI LETTER VA WITH LOWER DIAGONAL;;;;
-09F2;BENGALI RUPEE MARK;Sc;0;ET;;;;;N;;;;;
-09F3;BENGALI RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
-09F4;BENGALI CURRENCY NUMERATOR ONE;No;0;L;;;;1/16;N;;;;;
-09F5;BENGALI CURRENCY NUMERATOR TWO;No;0;L;;;;1/8;N;;;;;
-09F6;BENGALI CURRENCY NUMERATOR THREE;No;0;L;;;;3/16;N;;;;;
-09F7;BENGALI CURRENCY NUMERATOR FOUR;No;0;L;;;;1/4;N;;;;;
-09F8;BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR;No;0;L;;;;3/4;N;;;;;
-09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;;
-09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;;
-09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;;
-0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;;
-0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;;
-0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-0A05;GURMUKHI LETTER A;Lo;0;L;;;;;N;;;;;
-0A06;GURMUKHI LETTER AA;Lo;0;L;;;;;N;;;;;
-0A07;GURMUKHI LETTER I;Lo;0;L;;;;;N;;;;;
-0A08;GURMUKHI LETTER II;Lo;0;L;;;;;N;;;;;
-0A09;GURMUKHI LETTER U;Lo;0;L;;;;;N;;;;;
-0A0A;GURMUKHI LETTER UU;Lo;0;L;;;;;N;;;;;
-0A0F;GURMUKHI LETTER EE;Lo;0;L;;;;;N;;;;;
-0A10;GURMUKHI LETTER AI;Lo;0;L;;;;;N;;;;;
-0A13;GURMUKHI LETTER OO;Lo;0;L;;;;;N;;;;;
-0A14;GURMUKHI LETTER AU;Lo;0;L;;;;;N;;;;;
-0A15;GURMUKHI LETTER KA;Lo;0;L;;;;;N;;;;;
-0A16;GURMUKHI LETTER KHA;Lo;0;L;;;;;N;;;;;
-0A17;GURMUKHI LETTER GA;Lo;0;L;;;;;N;;;;;
-0A18;GURMUKHI LETTER GHA;Lo;0;L;;;;;N;;;;;
-0A19;GURMUKHI LETTER NGA;Lo;0;L;;;;;N;;;;;
-0A1A;GURMUKHI LETTER CA;Lo;0;L;;;;;N;;;;;
-0A1B;GURMUKHI LETTER CHA;Lo;0;L;;;;;N;;;;;
-0A1C;GURMUKHI LETTER JA;Lo;0;L;;;;;N;;;;;
-0A1D;GURMUKHI LETTER JHA;Lo;0;L;;;;;N;;;;;
-0A1E;GURMUKHI LETTER NYA;Lo;0;L;;;;;N;;;;;
-0A1F;GURMUKHI LETTER TTA;Lo;0;L;;;;;N;;;;;
-0A20;GURMUKHI LETTER TTHA;Lo;0;L;;;;;N;;;;;
-0A21;GURMUKHI LETTER DDA;Lo;0;L;;;;;N;;;;;
-0A22;GURMUKHI LETTER DDHA;Lo;0;L;;;;;N;;;;;
-0A23;GURMUKHI LETTER NNA;Lo;0;L;;;;;N;;;;;
-0A24;GURMUKHI LETTER TA;Lo;0;L;;;;;N;;;;;
-0A25;GURMUKHI LETTER THA;Lo;0;L;;;;;N;;;;;
-0A26;GURMUKHI LETTER DA;Lo;0;L;;;;;N;;;;;
-0A27;GURMUKHI LETTER DHA;Lo;0;L;;;;;N;;;;;
-0A28;GURMUKHI LETTER NA;Lo;0;L;;;;;N;;;;;
-0A2A;GURMUKHI LETTER PA;Lo;0;L;;;;;N;;;;;
-0A2B;GURMUKHI LETTER PHA;Lo;0;L;;;;;N;;;;;
-0A2C;GURMUKHI LETTER BA;Lo;0;L;;;;;N;;;;;
-0A2D;GURMUKHI LETTER BHA;Lo;0;L;;;;;N;;;;;
-0A2E;GURMUKHI LETTER MA;Lo;0;L;;;;;N;;;;;
-0A2F;GURMUKHI LETTER YA;Lo;0;L;;;;;N;;;;;
-0A30;GURMUKHI LETTER RA;Lo;0;L;;;;;N;;;;;
-0A32;GURMUKHI LETTER LA;Lo;0;L;;;;;N;;;;;
-0A33;GURMUKHI LETTER LLA;Lo;0;L;0A32 0A3C;;;;N;;;;;
-0A35;GURMUKHI LETTER VA;Lo;0;L;;;;;N;;;;;
-0A36;GURMUKHI LETTER SHA;Lo;0;L;0A38 0A3C;;;;N;;;;;
-0A38;GURMUKHI LETTER SA;Lo;0;L;;;;;N;;;;;
-0A39;GURMUKHI LETTER HA;Lo;0;L;;;;;N;;;;;
-0A3C;GURMUKHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-0A3E;GURMUKHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-0A3F;GURMUKHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-0A40;GURMUKHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-0A41;GURMUKHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-0A42;GURMUKHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-0A47;GURMUKHI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;;
-0A48;GURMUKHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-0A4B;GURMUKHI VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;;
-0A4C;GURMUKHI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
-0A4D;GURMUKHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-0A51;GURMUKHI SIGN UDAAT;Mn;0;NSM;;;;;N;;;;;
-0A59;GURMUKHI LETTER KHHA;Lo;0;L;0A16 0A3C;;;;N;;;;;
-0A5A;GURMUKHI LETTER GHHA;Lo;0;L;0A17 0A3C;;;;N;;;;;
-0A5B;GURMUKHI LETTER ZA;Lo;0;L;0A1C 0A3C;;;;N;;;;;
-0A5C;GURMUKHI LETTER RRA;Lo;0;L;;;;;N;;;;;
-0A5E;GURMUKHI LETTER FA;Lo;0;L;0A2B 0A3C;;;;N;;;;;
-0A66;GURMUKHI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0A67;GURMUKHI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0A68;GURMUKHI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0A69;GURMUKHI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0A6A;GURMUKHI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0A6B;GURMUKHI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0A6C;GURMUKHI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0A6D;GURMUKHI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0A6E;GURMUKHI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0A6F;GURMUKHI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0A70;GURMUKHI TIPPI;Mn;0;NSM;;;;;N;;;;;
-0A71;GURMUKHI ADDAK;Mn;0;NSM;;;;;N;;;;;
-0A72;GURMUKHI IRI;Lo;0;L;;;;;N;;;;;
-0A73;GURMUKHI URA;Lo;0;L;;;;;N;;;;;
-0A74;GURMUKHI EK ONKAR;Lo;0;L;;;;;N;;;;;
-0A75;GURMUKHI SIGN YAKASH;Mn;0;NSM;;;;;N;;;;;
-0A81;GUJARATI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
-0A82;GUJARATI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-0A83;GUJARATI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-0A85;GUJARATI LETTER A;Lo;0;L;;;;;N;;;;;
-0A86;GUJARATI LETTER AA;Lo;0;L;;;;;N;;;;;
-0A87;GUJARATI LETTER I;Lo;0;L;;;;;N;;;;;
-0A88;GUJARATI LETTER II;Lo;0;L;;;;;N;;;;;
-0A89;GUJARATI LETTER U;Lo;0;L;;;;;N;;;;;
-0A8A;GUJARATI LETTER UU;Lo;0;L;;;;;N;;;;;
-0A8B;GUJARATI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-0A8C;GUJARATI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-0A8D;GUJARATI VOWEL CANDRA E;Lo;0;L;;;;;N;;;;;
-0A8F;GUJARATI LETTER E;Lo;0;L;;;;;N;;;;;
-0A90;GUJARATI LETTER AI;Lo;0;L;;;;;N;;;;;
-0A91;GUJARATI VOWEL CANDRA O;Lo;0;L;;;;;N;;;;;
-0A93;GUJARATI LETTER O;Lo;0;L;;;;;N;;;;;
-0A94;GUJARATI LETTER AU;Lo;0;L;;;;;N;;;;;
-0A95;GUJARATI LETTER KA;Lo;0;L;;;;;N;;;;;
-0A96;GUJARATI LETTER KHA;Lo;0;L;;;;;N;;;;;
-0A97;GUJARATI LETTER GA;Lo;0;L;;;;;N;;;;;
-0A98;GUJARATI LETTER GHA;Lo;0;L;;;;;N;;;;;
-0A99;GUJARATI LETTER NGA;Lo;0;L;;;;;N;;;;;
-0A9A;GUJARATI LETTER CA;Lo;0;L;;;;;N;;;;;
-0A9B;GUJARATI LETTER CHA;Lo;0;L;;;;;N;;;;;
-0A9C;GUJARATI LETTER JA;Lo;0;L;;;;;N;;;;;
-0A9D;GUJARATI LETTER JHA;Lo;0;L;;;;;N;;;;;
-0A9E;GUJARATI LETTER NYA;Lo;0;L;;;;;N;;;;;
-0A9F;GUJARATI LETTER TTA;Lo;0;L;;;;;N;;;;;
-0AA0;GUJARATI LETTER TTHA;Lo;0;L;;;;;N;;;;;
-0AA1;GUJARATI LETTER DDA;Lo;0;L;;;;;N;;;;;
-0AA2;GUJARATI LETTER DDHA;Lo;0;L;;;;;N;;;;;
-0AA3;GUJARATI LETTER NNA;Lo;0;L;;;;;N;;;;;
-0AA4;GUJARATI LETTER TA;Lo;0;L;;;;;N;;;;;
-0AA5;GUJARATI LETTER THA;Lo;0;L;;;;;N;;;;;
-0AA6;GUJARATI LETTER DA;Lo;0;L;;;;;N;;;;;
-0AA7;GUJARATI LETTER DHA;Lo;0;L;;;;;N;;;;;
-0AA8;GUJARATI LETTER NA;Lo;0;L;;;;;N;;;;;
-0AAA;GUJARATI LETTER PA;Lo;0;L;;;;;N;;;;;
-0AAB;GUJARATI LETTER PHA;Lo;0;L;;;;;N;;;;;
-0AAC;GUJARATI LETTER BA;Lo;0;L;;;;;N;;;;;
-0AAD;GUJARATI LETTER BHA;Lo;0;L;;;;;N;;;;;
-0AAE;GUJARATI LETTER MA;Lo;0;L;;;;;N;;;;;
-0AAF;GUJARATI LETTER YA;Lo;0;L;;;;;N;;;;;
-0AB0;GUJARATI LETTER RA;Lo;0;L;;;;;N;;;;;
-0AB2;GUJARATI LETTER LA;Lo;0;L;;;;;N;;;;;
-0AB3;GUJARATI LETTER LLA;Lo;0;L;;;;;N;;;;;
-0AB5;GUJARATI LETTER VA;Lo;0;L;;;;;N;;;;;
-0AB6;GUJARATI LETTER SHA;Lo;0;L;;;;;N;;;;;
-0AB7;GUJARATI LETTER SSA;Lo;0;L;;;;;N;;;;;
-0AB8;GUJARATI LETTER SA;Lo;0;L;;;;;N;;;;;
-0AB9;GUJARATI LETTER HA;Lo;0;L;;;;;N;;;;;
-0ABC;GUJARATI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-0ABD;GUJARATI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
-0ABE;GUJARATI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-0ABF;GUJARATI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-0AC0;GUJARATI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-0AC1;GUJARATI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-0AC2;GUJARATI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-0AC3;GUJARATI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
-0AC4;GUJARATI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
-0AC5;GUJARATI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;;
-0AC7;GUJARATI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-0AC8;GUJARATI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-0AC9;GUJARATI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;;
-0ACB;GUJARATI VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-0ACC;GUJARATI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-0ACD;GUJARATI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-0AD0;GUJARATI OM;Lo;0;L;;;;;N;;;;;
-0AE0;GUJARATI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-0AE1;GUJARATI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-0AE2;GUJARATI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-0AE3;GUJARATI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-0AE6;GUJARATI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0AE7;GUJARATI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0AE8;GUJARATI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0AE9;GUJARATI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0AEA;GUJARATI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0AEB;GUJARATI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0AEC;GUJARATI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0AED;GUJARATI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0AEE;GUJARATI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
-0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
-0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
-0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
-0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-0B05;ORIYA LETTER A;Lo;0;L;;;;;N;;;;;
-0B06;ORIYA LETTER AA;Lo;0;L;;;;;N;;;;;
-0B07;ORIYA LETTER I;Lo;0;L;;;;;N;;;;;
-0B08;ORIYA LETTER II;Lo;0;L;;;;;N;;;;;
-0B09;ORIYA LETTER U;Lo;0;L;;;;;N;;;;;
-0B0A;ORIYA LETTER UU;Lo;0;L;;;;;N;;;;;
-0B0B;ORIYA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-0B0C;ORIYA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-0B0F;ORIYA LETTER E;Lo;0;L;;;;;N;;;;;
-0B10;ORIYA LETTER AI;Lo;0;L;;;;;N;;;;;
-0B13;ORIYA LETTER O;Lo;0;L;;;;;N;;;;;
-0B14;ORIYA LETTER AU;Lo;0;L;;;;;N;;;;;
-0B15;ORIYA LETTER KA;Lo;0;L;;;;;N;;;;;
-0B16;ORIYA LETTER KHA;Lo;0;L;;;;;N;;;;;
-0B17;ORIYA LETTER GA;Lo;0;L;;;;;N;;;;;
-0B18;ORIYA LETTER GHA;Lo;0;L;;;;;N;;;;;
-0B19;ORIYA LETTER NGA;Lo;0;L;;;;;N;;;;;
-0B1A;ORIYA LETTER CA;Lo;0;L;;;;;N;;;;;
-0B1B;ORIYA LETTER CHA;Lo;0;L;;;;;N;;;;;
-0B1C;ORIYA LETTER JA;Lo;0;L;;;;;N;;;;;
-0B1D;ORIYA LETTER JHA;Lo;0;L;;;;;N;;;;;
-0B1E;ORIYA LETTER NYA;Lo;0;L;;;;;N;;;;;
-0B1F;ORIYA LETTER TTA;Lo;0;L;;;;;N;;;;;
-0B20;ORIYA LETTER TTHA;Lo;0;L;;;;;N;;;;;
-0B21;ORIYA LETTER DDA;Lo;0;L;;;;;N;;;;;
-0B22;ORIYA LETTER DDHA;Lo;0;L;;;;;N;;;;;
-0B23;ORIYA LETTER NNA;Lo;0;L;;;;;N;;;;;
-0B24;ORIYA LETTER TA;Lo;0;L;;;;;N;;;;;
-0B25;ORIYA LETTER THA;Lo;0;L;;;;;N;;;;;
-0B26;ORIYA LETTER DA;Lo;0;L;;;;;N;;;;;
-0B27;ORIYA LETTER DHA;Lo;0;L;;;;;N;;;;;
-0B28;ORIYA LETTER NA;Lo;0;L;;;;;N;;;;;
-0B2A;ORIYA LETTER PA;Lo;0;L;;;;;N;;;;;
-0B2B;ORIYA LETTER PHA;Lo;0;L;;;;;N;;;;;
-0B2C;ORIYA LETTER BA;Lo;0;L;;;;;N;;;;;
-0B2D;ORIYA LETTER BHA;Lo;0;L;;;;;N;;;;;
-0B2E;ORIYA LETTER MA;Lo;0;L;;;;;N;;;;;
-0B2F;ORIYA LETTER YA;Lo;0;L;;;;;N;;;;;
-0B30;ORIYA LETTER RA;Lo;0;L;;;;;N;;;;;
-0B32;ORIYA LETTER LA;Lo;0;L;;;;;N;;;;;
-0B33;ORIYA LETTER LLA;Lo;0;L;;;;;N;;;;;
-0B35;ORIYA LETTER VA;Lo;0;L;;;;;N;;;;;
-0B36;ORIYA LETTER SHA;Lo;0;L;;;;;N;;;;;
-0B37;ORIYA LETTER SSA;Lo;0;L;;;;;N;;;;;
-0B38;ORIYA LETTER SA;Lo;0;L;;;;;N;;;;;
-0B39;ORIYA LETTER HA;Lo;0;L;;;;;N;;;;;
-0B3C;ORIYA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-0B3D;ORIYA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
-0B3E;ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-0B3F;ORIYA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-0B40;ORIYA VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-0B41;ORIYA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-0B42;ORIYA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-0B43;ORIYA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
-0B44;ORIYA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
-0B47;ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-0B48;ORIYA VOWEL SIGN AI;Mc;0;L;0B47 0B56;;;;N;;;;;
-0B4B;ORIYA VOWEL SIGN O;Mc;0;L;0B47 0B3E;;;;N;;;;;
-0B4C;ORIYA VOWEL SIGN AU;Mc;0;L;0B47 0B57;;;;N;;;;;
-0B4D;ORIYA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-0B56;ORIYA AI LENGTH MARK;Mn;0;NSM;;;;;N;;;;;
-0B57;ORIYA AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
-0B5C;ORIYA LETTER RRA;Lo;0;L;0B21 0B3C;;;;N;;;;;
-0B5D;ORIYA LETTER RHA;Lo;0;L;0B22 0B3C;;;;N;;;;;
-0B5F;ORIYA LETTER YYA;Lo;0;L;;;;;N;;;;;
-0B60;ORIYA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-0B61;ORIYA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-0B62;ORIYA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-0B63;ORIYA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-0B66;ORIYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0B67;ORIYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0B68;ORIYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0B69;ORIYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0B6A;ORIYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0B6B;ORIYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0B6C;ORIYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0B6D;ORIYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0B6E;ORIYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;;
-0B71;ORIYA LETTER WA;Lo;0;L;;;;;N;;;;;
-0B72;ORIYA FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;;
-0B73;ORIYA FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;;
-0B74;ORIYA FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;;
-0B75;ORIYA FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;;
-0B76;ORIYA FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;;
-0B77;ORIYA FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;;
-0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;;
-0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;;
-0B86;TAMIL LETTER AA;Lo;0;L;;;;;N;;;;;
-0B87;TAMIL LETTER I;Lo;0;L;;;;;N;;;;;
-0B88;TAMIL LETTER II;Lo;0;L;;;;;N;;;;;
-0B89;TAMIL LETTER U;Lo;0;L;;;;;N;;;;;
-0B8A;TAMIL LETTER UU;Lo;0;L;;;;;N;;;;;
-0B8E;TAMIL LETTER E;Lo;0;L;;;;;N;;;;;
-0B8F;TAMIL LETTER EE;Lo;0;L;;;;;N;;;;;
-0B90;TAMIL LETTER AI;Lo;0;L;;;;;N;;;;;
-0B92;TAMIL LETTER O;Lo;0;L;;;;;N;;;;;
-0B93;TAMIL LETTER OO;Lo;0;L;;;;;N;;;;;
-0B94;TAMIL LETTER AU;Lo;0;L;0B92 0BD7;;;;N;;;;;
-0B95;TAMIL LETTER KA;Lo;0;L;;;;;N;;;;;
-0B99;TAMIL LETTER NGA;Lo;0;L;;;;;N;;;;;
-0B9A;TAMIL LETTER CA;Lo;0;L;;;;;N;;;;;
-0B9C;TAMIL LETTER JA;Lo;0;L;;;;;N;;;;;
-0B9E;TAMIL LETTER NYA;Lo;0;L;;;;;N;;;;;
-0B9F;TAMIL LETTER TTA;Lo;0;L;;;;;N;;;;;
-0BA3;TAMIL LETTER NNA;Lo;0;L;;;;;N;;;;;
-0BA4;TAMIL LETTER TA;Lo;0;L;;;;;N;;;;;
-0BA8;TAMIL LETTER NA;Lo;0;L;;;;;N;;;;;
-0BA9;TAMIL LETTER NNNA;Lo;0;L;;;;;N;;;;;
-0BAA;TAMIL LETTER PA;Lo;0;L;;;;;N;;;;;
-0BAE;TAMIL LETTER MA;Lo;0;L;;;;;N;;;;;
-0BAF;TAMIL LETTER YA;Lo;0;L;;;;;N;;;;;
-0BB0;TAMIL LETTER RA;Lo;0;L;;;;;N;;;;;
-0BB1;TAMIL LETTER RRA;Lo;0;L;;;;;N;;;;;
-0BB2;TAMIL LETTER LA;Lo;0;L;;;;;N;;;;;
-0BB3;TAMIL LETTER LLA;Lo;0;L;;;;;N;;;;;
-0BB4;TAMIL LETTER LLLA;Lo;0;L;;;;;N;;;;;
-0BB5;TAMIL LETTER VA;Lo;0;L;;;;;N;;;;;
-0BB6;TAMIL LETTER SHA;Lo;0;L;;;;;N;;;;;
-0BB7;TAMIL LETTER SSA;Lo;0;L;;;;;N;;;;;
-0BB8;TAMIL LETTER SA;Lo;0;L;;;;;N;;;;;
-0BB9;TAMIL LETTER HA;Lo;0;L;;;;;N;;;;;
-0BBE;TAMIL VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-0BBF;TAMIL VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-0BC0;TAMIL VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-0BC1;TAMIL VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-0BC2;TAMIL VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
-0BC6;TAMIL VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-0BC7;TAMIL VOWEL SIGN EE;Mc;0;L;;;;;N;;;;;
-0BC8;TAMIL VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-0BCA;TAMIL VOWEL SIGN O;Mc;0;L;0BC6 0BBE;;;;N;;;;;
-0BCB;TAMIL VOWEL SIGN OO;Mc;0;L;0BC7 0BBE;;;;N;;;;;
-0BCC;TAMIL VOWEL SIGN AU;Mc;0;L;0BC6 0BD7;;;;N;;;;;
-0BCD;TAMIL SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-0BD0;TAMIL OM;Lo;0;L;;;;;N;;;;;
-0BD7;TAMIL AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
-0BE6;TAMIL DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0BE7;TAMIL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0BE8;TAMIL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0BE9;TAMIL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0BEA;TAMIL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0BEB;TAMIL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0BEC;TAMIL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0BED;TAMIL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0BEE;TAMIL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0BEF;TAMIL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0BF0;TAMIL NUMBER TEN;No;0;L;;;;10;N;;;;;
-0BF1;TAMIL NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;;
-0BF2;TAMIL NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;;
-0BF3;TAMIL DAY SIGN;So;0;ON;;;;;N;;;;;
-0BF4;TAMIL MONTH SIGN;So;0;ON;;;;;N;;;;;
-0BF5;TAMIL YEAR SIGN;So;0;ON;;;;;N;;;;;
-0BF6;TAMIL DEBIT SIGN;So;0;ON;;;;;N;;;;;
-0BF7;TAMIL CREDIT SIGN;So;0;ON;;;;;N;;;;;
-0BF8;TAMIL AS ABOVE SIGN;So;0;ON;;;;;N;;;;;
-0BF9;TAMIL RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
-0BFA;TAMIL NUMBER SIGN;So;0;ON;;;;;N;;;;;
-0C01;TELUGU SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;;
-0C02;TELUGU SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
-0C03;TELUGU SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-0C05;TELUGU LETTER A;Lo;0;L;;;;;N;;;;;
-0C06;TELUGU LETTER AA;Lo;0;L;;;;;N;;;;;
-0C07;TELUGU LETTER I;Lo;0;L;;;;;N;;;;;
-0C08;TELUGU LETTER II;Lo;0;L;;;;;N;;;;;
-0C09;TELUGU LETTER U;Lo;0;L;;;;;N;;;;;
-0C0A;TELUGU LETTER UU;Lo;0;L;;;;;N;;;;;
-0C0B;TELUGU LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-0C0C;TELUGU LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-0C0E;TELUGU LETTER E;Lo;0;L;;;;;N;;;;;
-0C0F;TELUGU LETTER EE;Lo;0;L;;;;;N;;;;;
-0C10;TELUGU LETTER AI;Lo;0;L;;;;;N;;;;;
-0C12;TELUGU LETTER O;Lo;0;L;;;;;N;;;;;
-0C13;TELUGU LETTER OO;Lo;0;L;;;;;N;;;;;
-0C14;TELUGU LETTER AU;Lo;0;L;;;;;N;;;;;
-0C15;TELUGU LETTER KA;Lo;0;L;;;;;N;;;;;
-0C16;TELUGU LETTER KHA;Lo;0;L;;;;;N;;;;;
-0C17;TELUGU LETTER GA;Lo;0;L;;;;;N;;;;;
-0C18;TELUGU LETTER GHA;Lo;0;L;;;;;N;;;;;
-0C19;TELUGU LETTER NGA;Lo;0;L;;;;;N;;;;;
-0C1A;TELUGU LETTER CA;Lo;0;L;;;;;N;;;;;
-0C1B;TELUGU LETTER CHA;Lo;0;L;;;;;N;;;;;
-0C1C;TELUGU LETTER JA;Lo;0;L;;;;;N;;;;;
-0C1D;TELUGU LETTER JHA;Lo;0;L;;;;;N;;;;;
-0C1E;TELUGU LETTER NYA;Lo;0;L;;;;;N;;;;;
-0C1F;TELUGU LETTER TTA;Lo;0;L;;;;;N;;;;;
-0C20;TELUGU LETTER TTHA;Lo;0;L;;;;;N;;;;;
-0C21;TELUGU LETTER DDA;Lo;0;L;;;;;N;;;;;
-0C22;TELUGU LETTER DDHA;Lo;0;L;;;;;N;;;;;
-0C23;TELUGU LETTER NNA;Lo;0;L;;;;;N;;;;;
-0C24;TELUGU LETTER TA;Lo;0;L;;;;;N;;;;;
-0C25;TELUGU LETTER THA;Lo;0;L;;;;;N;;;;;
-0C26;TELUGU LETTER DA;Lo;0;L;;;;;N;;;;;
-0C27;TELUGU LETTER DHA;Lo;0;L;;;;;N;;;;;
-0C28;TELUGU LETTER NA;Lo;0;L;;;;;N;;;;;
-0C2A;TELUGU LETTER PA;Lo;0;L;;;;;N;;;;;
-0C2B;TELUGU LETTER PHA;Lo;0;L;;;;;N;;;;;
-0C2C;TELUGU LETTER BA;Lo;0;L;;;;;N;;;;;
-0C2D;TELUGU LETTER BHA;Lo;0;L;;;;;N;;;;;
-0C2E;TELUGU LETTER MA;Lo;0;L;;;;;N;;;;;
-0C2F;TELUGU LETTER YA;Lo;0;L;;;;;N;;;;;
-0C30;TELUGU LETTER RA;Lo;0;L;;;;;N;;;;;
-0C31;TELUGU LETTER RRA;Lo;0;L;;;;;N;;;;;
-0C32;TELUGU LETTER LA;Lo;0;L;;;;;N;;;;;
-0C33;TELUGU LETTER LLA;Lo;0;L;;;;;N;;;;;
-0C35;TELUGU LETTER VA;Lo;0;L;;;;;N;;;;;
-0C36;TELUGU LETTER SHA;Lo;0;L;;;;;N;;;;;
-0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;;
-0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;;
-0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;;
-0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
-0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;;
-0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-0C40;TELUGU VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-0C41;TELUGU VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-0C42;TELUGU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
-0C43;TELUGU VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;;
-0C44;TELUGU VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;;
-0C46;TELUGU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-0C47;TELUGU VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;;
-0C48;TELUGU VOWEL SIGN AI;Mn;0;NSM;0C46 0C56;;;;N;;;;;
-0C4A;TELUGU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
-0C4B;TELUGU VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;;
-0C4C;TELUGU VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
-0C4D;TELUGU SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-0C55;TELUGU LENGTH MARK;Mn;84;NSM;;;;;N;;;;;
-0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;;
-0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;;
-0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;;
-0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-0C63;TELUGU VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-0C66;TELUGU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0C67;TELUGU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0C68;TELUGU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0C69;TELUGU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0C6A;TELUGU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0C6B;TELUGU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0C6C;TELUGU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0C6D;TELUGU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0C6E;TELUGU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0C6F;TELUGU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0C78;TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR;No;0;ON;;;;0;N;;;;;
-0C79;TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR;No;0;ON;;;;1;N;;;;;
-0C7A;TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR;No;0;ON;;;;2;N;;;;;
-0C7B;TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR;No;0;ON;;;;3;N;;;;;
-0C7C;TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR;No;0;ON;;;;1;N;;;;;
-0C7D;TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR;No;0;ON;;;;2;N;;;;;
-0C7E;TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR;No;0;ON;;;;3;N;;;;;
-0C7F;TELUGU SIGN TUUMU;So;0;L;;;;;N;;;;;
-0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
-0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-0C85;KANNADA LETTER A;Lo;0;L;;;;;N;;;;;
-0C86;KANNADA LETTER AA;Lo;0;L;;;;;N;;;;;
-0C87;KANNADA LETTER I;Lo;0;L;;;;;N;;;;;
-0C88;KANNADA LETTER II;Lo;0;L;;;;;N;;;;;
-0C89;KANNADA LETTER U;Lo;0;L;;;;;N;;;;;
-0C8A;KANNADA LETTER UU;Lo;0;L;;;;;N;;;;;
-0C8B;KANNADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-0C8C;KANNADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-0C8E;KANNADA LETTER E;Lo;0;L;;;;;N;;;;;
-0C8F;KANNADA LETTER EE;Lo;0;L;;;;;N;;;;;
-0C90;KANNADA LETTER AI;Lo;0;L;;;;;N;;;;;
-0C92;KANNADA LETTER O;Lo;0;L;;;;;N;;;;;
-0C93;KANNADA LETTER OO;Lo;0;L;;;;;N;;;;;
-0C94;KANNADA LETTER AU;Lo;0;L;;;;;N;;;;;
-0C95;KANNADA LETTER KA;Lo;0;L;;;;;N;;;;;
-0C96;KANNADA LETTER KHA;Lo;0;L;;;;;N;;;;;
-0C97;KANNADA LETTER GA;Lo;0;L;;;;;N;;;;;
-0C98;KANNADA LETTER GHA;Lo;0;L;;;;;N;;;;;
-0C99;KANNADA LETTER NGA;Lo;0;L;;;;;N;;;;;
-0C9A;KANNADA LETTER CA;Lo;0;L;;;;;N;;;;;
-0C9B;KANNADA LETTER CHA;Lo;0;L;;;;;N;;;;;
-0C9C;KANNADA LETTER JA;Lo;0;L;;;;;N;;;;;
-0C9D;KANNADA LETTER JHA;Lo;0;L;;;;;N;;;;;
-0C9E;KANNADA LETTER NYA;Lo;0;L;;;;;N;;;;;
-0C9F;KANNADA LETTER TTA;Lo;0;L;;;;;N;;;;;
-0CA0;KANNADA LETTER TTHA;Lo;0;L;;;;;N;;;;;
-0CA1;KANNADA LETTER DDA;Lo;0;L;;;;;N;;;;;
-0CA2;KANNADA LETTER DDHA;Lo;0;L;;;;;N;;;;;
-0CA3;KANNADA LETTER NNA;Lo;0;L;;;;;N;;;;;
-0CA4;KANNADA LETTER TA;Lo;0;L;;;;;N;;;;;
-0CA5;KANNADA LETTER THA;Lo;0;L;;;;;N;;;;;
-0CA6;KANNADA LETTER DA;Lo;0;L;;;;;N;;;;;
-0CA7;KANNADA LETTER DHA;Lo;0;L;;;;;N;;;;;
-0CA8;KANNADA LETTER NA;Lo;0;L;;;;;N;;;;;
-0CAA;KANNADA LETTER PA;Lo;0;L;;;;;N;;;;;
-0CAB;KANNADA LETTER PHA;Lo;0;L;;;;;N;;;;;
-0CAC;KANNADA LETTER BA;Lo;0;L;;;;;N;;;;;
-0CAD;KANNADA LETTER BHA;Lo;0;L;;;;;N;;;;;
-0CAE;KANNADA LETTER MA;Lo;0;L;;;;;N;;;;;
-0CAF;KANNADA LETTER YA;Lo;0;L;;;;;N;;;;;
-0CB0;KANNADA LETTER RA;Lo;0;L;;;;;N;;;;;
-0CB1;KANNADA LETTER RRA;Lo;0;L;;;;;N;;;;;
-0CB2;KANNADA LETTER LA;Lo;0;L;;;;;N;;;;;
-0CB3;KANNADA LETTER LLA;Lo;0;L;;;;;N;;;;;
-0CB5;KANNADA LETTER VA;Lo;0;L;;;;;N;;;;;
-0CB6;KANNADA LETTER SHA;Lo;0;L;;;;;N;;;;;
-0CB7;KANNADA LETTER SSA;Lo;0;L;;;;;N;;;;;
-0CB8;KANNADA LETTER SA;Lo;0;L;;;;;N;;;;;
-0CB9;KANNADA LETTER HA;Lo;0;L;;;;;N;;;;;
-0CBC;KANNADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-0CBD;KANNADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
-0CBE;KANNADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-0CBF;KANNADA VOWEL SIGN I;Mn;0;L;;;;;N;;;;;
-0CC0;KANNADA VOWEL SIGN II;Mc;0;L;0CBF 0CD5;;;;N;;;;;
-0CC1;KANNADA VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-0CC2;KANNADA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
-0CC3;KANNADA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;;
-0CC4;KANNADA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;;
-0CC6;KANNADA VOWEL SIGN E;Mn;0;L;;;;;N;;;;;
-0CC7;KANNADA VOWEL SIGN EE;Mc;0;L;0CC6 0CD5;;;;N;;;;;
-0CC8;KANNADA VOWEL SIGN AI;Mc;0;L;0CC6 0CD6;;;;N;;;;;
-0CCA;KANNADA VOWEL SIGN O;Mc;0;L;0CC6 0CC2;;;;N;;;;;
-0CCB;KANNADA VOWEL SIGN OO;Mc;0;L;0CCA 0CD5;;;;N;;;;;
-0CCC;KANNADA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
-0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;;
-0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;;
-0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;;
-0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-0CE2;KANNADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-0CE3;KANNADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-0CE6;KANNADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0CE7;KANNADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0CE8;KANNADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0CE9;KANNADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0CEA;KANNADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0CEB;KANNADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0CEC;KANNADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;;
-0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;;
-0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
-0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;;
-0D06;MALAYALAM LETTER AA;Lo;0;L;;;;;N;;;;;
-0D07;MALAYALAM LETTER I;Lo;0;L;;;;;N;;;;;
-0D08;MALAYALAM LETTER II;Lo;0;L;;;;;N;;;;;
-0D09;MALAYALAM LETTER U;Lo;0;L;;;;;N;;;;;
-0D0A;MALAYALAM LETTER UU;Lo;0;L;;;;;N;;;;;
-0D0B;MALAYALAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-0D0C;MALAYALAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-0D0E;MALAYALAM LETTER E;Lo;0;L;;;;;N;;;;;
-0D0F;MALAYALAM LETTER EE;Lo;0;L;;;;;N;;;;;
-0D10;MALAYALAM LETTER AI;Lo;0;L;;;;;N;;;;;
-0D12;MALAYALAM LETTER O;Lo;0;L;;;;;N;;;;;
-0D13;MALAYALAM LETTER OO;Lo;0;L;;;;;N;;;;;
-0D14;MALAYALAM LETTER AU;Lo;0;L;;;;;N;;;;;
-0D15;MALAYALAM LETTER KA;Lo;0;L;;;;;N;;;;;
-0D16;MALAYALAM LETTER KHA;Lo;0;L;;;;;N;;;;;
-0D17;MALAYALAM LETTER GA;Lo;0;L;;;;;N;;;;;
-0D18;MALAYALAM LETTER GHA;Lo;0;L;;;;;N;;;;;
-0D19;MALAYALAM LETTER NGA;Lo;0;L;;;;;N;;;;;
-0D1A;MALAYALAM LETTER CA;Lo;0;L;;;;;N;;;;;
-0D1B;MALAYALAM LETTER CHA;Lo;0;L;;;;;N;;;;;
-0D1C;MALAYALAM LETTER JA;Lo;0;L;;;;;N;;;;;
-0D1D;MALAYALAM LETTER JHA;Lo;0;L;;;;;N;;;;;
-0D1E;MALAYALAM LETTER NYA;Lo;0;L;;;;;N;;;;;
-0D1F;MALAYALAM LETTER TTA;Lo;0;L;;;;;N;;;;;
-0D20;MALAYALAM LETTER TTHA;Lo;0;L;;;;;N;;;;;
-0D21;MALAYALAM LETTER DDA;Lo;0;L;;;;;N;;;;;
-0D22;MALAYALAM LETTER DDHA;Lo;0;L;;;;;N;;;;;
-0D23;MALAYALAM LETTER NNA;Lo;0;L;;;;;N;;;;;
-0D24;MALAYALAM LETTER TA;Lo;0;L;;;;;N;;;;;
-0D25;MALAYALAM LETTER THA;Lo;0;L;;;;;N;;;;;
-0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;;
-0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;;
-0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;;
-0D29;MALAYALAM LETTER NNNA;Lo;0;L;;;;;N;;;;;
-0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;;
-0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;;
-0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;;
-0D2D;MALAYALAM LETTER BHA;Lo;0;L;;;;;N;;;;;
-0D2E;MALAYALAM LETTER MA;Lo;0;L;;;;;N;;;;;
-0D2F;MALAYALAM LETTER YA;Lo;0;L;;;;;N;;;;;
-0D30;MALAYALAM LETTER RA;Lo;0;L;;;;;N;;;;;
-0D31;MALAYALAM LETTER RRA;Lo;0;L;;;;;N;;;;;
-0D32;MALAYALAM LETTER LA;Lo;0;L;;;;;N;;;;;
-0D33;MALAYALAM LETTER LLA;Lo;0;L;;;;;N;;;;;
-0D34;MALAYALAM LETTER LLLA;Lo;0;L;;;;;N;;;;;
-0D35;MALAYALAM LETTER VA;Lo;0;L;;;;;N;;;;;
-0D36;MALAYALAM LETTER SHA;Lo;0;L;;;;;N;;;;;
-0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;;
-0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;;
-0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;;
-0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;;
-0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
-0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-0D40;MALAYALAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-0D41;MALAYALAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-0D42;MALAYALAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-0D43;MALAYALAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
-0D44;MALAYALAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
-0D46;MALAYALAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-0D47;MALAYALAM VOWEL SIGN EE;Mc;0;L;;;;;N;;;;;
-0D48;MALAYALAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-0D4A;MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;;
-0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;;
-0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;;
-0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-0D4E;MALAYALAM LETTER DOT REPH;Lo;0;L;;;;;N;;;;;
-0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
-0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-0D62;MALAYALAM VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-0D63;MALAYALAM VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-0D66;MALAYALAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0D67;MALAYALAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0D68;MALAYALAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0D69;MALAYALAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0D6A;MALAYALAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0D6B;MALAYALAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0D6C;MALAYALAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0D6D;MALAYALAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0D6E;MALAYALAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0D6F;MALAYALAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0D70;MALAYALAM NUMBER TEN;No;0;L;;;;10;N;;;;;
-0D71;MALAYALAM NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;;
-0D72;MALAYALAM NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;;
-0D73;MALAYALAM FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;;
-0D74;MALAYALAM FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;;
-0D75;MALAYALAM FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;;
-0D79;MALAYALAM DATE MARK;So;0;L;;;;;N;;;;;
-0D7A;MALAYALAM LETTER CHILLU NN;Lo;0;L;;;;;N;;;;;
-0D7B;MALAYALAM LETTER CHILLU N;Lo;0;L;;;;;N;;;;;
-0D7C;MALAYALAM LETTER CHILLU RR;Lo;0;L;;;;;N;;;;;
-0D7D;MALAYALAM LETTER CHILLU L;Lo;0;L;;;;;N;;;;;
-0D7E;MALAYALAM LETTER CHILLU LL;Lo;0;L;;;;;N;;;;;
-0D7F;MALAYALAM LETTER CHILLU K;Lo;0;L;;;;;N;;;;;
-0D82;SINHALA SIGN ANUSVARAYA;Mc;0;L;;;;;N;;;;;
-0D83;SINHALA SIGN VISARGAYA;Mc;0;L;;;;;N;;;;;
-0D85;SINHALA LETTER AYANNA;Lo;0;L;;;;;N;;;;;
-0D86;SINHALA LETTER AAYANNA;Lo;0;L;;;;;N;;;;;
-0D87;SINHALA LETTER AEYANNA;Lo;0;L;;;;;N;;;;;
-0D88;SINHALA LETTER AEEYANNA;Lo;0;L;;;;;N;;;;;
-0D89;SINHALA LETTER IYANNA;Lo;0;L;;;;;N;;;;;
-0D8A;SINHALA LETTER IIYANNA;Lo;0;L;;;;;N;;;;;
-0D8B;SINHALA LETTER UYANNA;Lo;0;L;;;;;N;;;;;
-0D8C;SINHALA LETTER UUYANNA;Lo;0;L;;;;;N;;;;;
-0D8D;SINHALA LETTER IRUYANNA;Lo;0;L;;;;;N;;;;;
-0D8E;SINHALA LETTER IRUUYANNA;Lo;0;L;;;;;N;;;;;
-0D8F;SINHALA LETTER ILUYANNA;Lo;0;L;;;;;N;;;;;
-0D90;SINHALA LETTER ILUUYANNA;Lo;0;L;;;;;N;;;;;
-0D91;SINHALA LETTER EYANNA;Lo;0;L;;;;;N;;;;;
-0D92;SINHALA LETTER EEYANNA;Lo;0;L;;;;;N;;;;;
-0D93;SINHALA LETTER AIYANNA;Lo;0;L;;;;;N;;;;;
-0D94;SINHALA LETTER OYANNA;Lo;0;L;;;;;N;;;;;
-0D95;SINHALA LETTER OOYANNA;Lo;0;L;;;;;N;;;;;
-0D96;SINHALA LETTER AUYANNA;Lo;0;L;;;;;N;;;;;
-0D9A;SINHALA LETTER ALPAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;;
-0D9B;SINHALA LETTER MAHAAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;;
-0D9C;SINHALA LETTER ALPAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;;
-0D9D;SINHALA LETTER MAHAAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;;
-0D9E;SINHALA LETTER KANTAJA NAASIKYAYA;Lo;0;L;;;;;N;;;;;
-0D9F;SINHALA LETTER SANYAKA GAYANNA;Lo;0;L;;;;;N;;;;;
-0DA0;SINHALA LETTER ALPAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;;
-0DA1;SINHALA LETTER MAHAAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;;
-0DA2;SINHALA LETTER ALPAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;;
-0DA3;SINHALA LETTER MAHAAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;;
-0DA4;SINHALA LETTER TAALUJA NAASIKYAYA;Lo;0;L;;;;;N;;;;;
-0DA5;SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA;Lo;0;L;;;;;N;;;;;
-0DA6;SINHALA LETTER SANYAKA JAYANNA;Lo;0;L;;;;;N;;;;;
-0DA7;SINHALA LETTER ALPAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;;
-0DA8;SINHALA LETTER MAHAAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;;
-0DA9;SINHALA LETTER ALPAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;;
-0DAA;SINHALA LETTER MAHAAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;;
-0DAB;SINHALA LETTER MUURDHAJA NAYANNA;Lo;0;L;;;;;N;;;;;
-0DAC;SINHALA LETTER SANYAKA DDAYANNA;Lo;0;L;;;;;N;;;;;
-0DAD;SINHALA LETTER ALPAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;;
-0DAE;SINHALA LETTER MAHAAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;;
-0DAF;SINHALA LETTER ALPAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;;
-0DB0;SINHALA LETTER MAHAAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;;
-0DB1;SINHALA LETTER DANTAJA NAYANNA;Lo;0;L;;;;;N;;;;;
-0DB3;SINHALA LETTER SANYAKA DAYANNA;Lo;0;L;;;;;N;;;;;
-0DB4;SINHALA LETTER ALPAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;;
-0DB5;SINHALA LETTER MAHAAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;;
-0DB6;SINHALA LETTER ALPAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;;
-0DB7;SINHALA LETTER MAHAAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;;
-0DB8;SINHALA LETTER MAYANNA;Lo;0;L;;;;;N;;;;;
-0DB9;SINHALA LETTER AMBA BAYANNA;Lo;0;L;;;;;N;;;;;
-0DBA;SINHALA LETTER YAYANNA;Lo;0;L;;;;;N;;;;;
-0DBB;SINHALA LETTER RAYANNA;Lo;0;L;;;;;N;;;;;
-0DBD;SINHALA LETTER DANTAJA LAYANNA;Lo;0;L;;;;;N;;;;;
-0DC0;SINHALA LETTER VAYANNA;Lo;0;L;;;;;N;;;;;
-0DC1;SINHALA LETTER TAALUJA SAYANNA;Lo;0;L;;;;;N;;;;;
-0DC2;SINHALA LETTER MUURDHAJA SAYANNA;Lo;0;L;;;;;N;;;;;
-0DC3;SINHALA LETTER DANTAJA SAYANNA;Lo;0;L;;;;;N;;;;;
-0DC4;SINHALA LETTER HAYANNA;Lo;0;L;;;;;N;;;;;
-0DC5;SINHALA LETTER MUURDHAJA LAYANNA;Lo;0;L;;;;;N;;;;;
-0DC6;SINHALA LETTER FAYANNA;Lo;0;L;;;;;N;;;;;
-0DCA;SINHALA SIGN AL-LAKUNA;Mn;9;NSM;;;;;N;;;;;
-0DCF;SINHALA VOWEL SIGN AELA-PILLA;Mc;0;L;;;;;N;;;;;
-0DD0;SINHALA VOWEL SIGN KETTI AEDA-PILLA;Mc;0;L;;;;;N;;;;;
-0DD1;SINHALA VOWEL SIGN DIGA AEDA-PILLA;Mc;0;L;;;;;N;;;;;
-0DD2;SINHALA VOWEL SIGN KETTI IS-PILLA;Mn;0;NSM;;;;;N;;;;;
-0DD3;SINHALA VOWEL SIGN DIGA IS-PILLA;Mn;0;NSM;;;;;N;;;;;
-0DD4;SINHALA VOWEL SIGN KETTI PAA-PILLA;Mn;0;NSM;;;;;N;;;;;
-0DD6;SINHALA VOWEL SIGN DIGA PAA-PILLA;Mn;0;NSM;;;;;N;;;;;
-0DD8;SINHALA VOWEL SIGN GAETTA-PILLA;Mc;0;L;;;;;N;;;;;
-0DD9;SINHALA VOWEL SIGN KOMBUVA;Mc;0;L;;;;;N;;;;;
-0DDA;SINHALA VOWEL SIGN DIGA KOMBUVA;Mc;0;L;0DD9 0DCA;;;;N;;;;;
-0DDB;SINHALA VOWEL SIGN KOMBU DEKA;Mc;0;L;;;;;N;;;;;
-0DDC;SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA;Mc;0;L;0DD9 0DCF;;;;N;;;;;
-0DDD;SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA;Mc;0;L;0DDC 0DCA;;;;N;;;;;
-0DDE;SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA;Mc;0;L;0DD9 0DDF;;;;N;;;;;
-0DDF;SINHALA VOWEL SIGN GAYANUKITTA;Mc;0;L;;;;;N;;;;;
-0DF2;SINHALA VOWEL SIGN DIGA GAETTA-PILLA;Mc;0;L;;;;;N;;;;;
-0DF3;SINHALA VOWEL SIGN DIGA GAYANUKITTA;Mc;0;L;;;;;N;;;;;
-0DF4;SINHALA PUNCTUATION KUNDDALIYA;Po;0;L;;;;;N;;;;;
-0E01;THAI CHARACTER KO KAI;Lo;0;L;;;;;N;THAI LETTER KO KAI;;;;
-0E02;THAI CHARACTER KHO KHAI;Lo;0;L;;;;;N;THAI LETTER KHO KHAI;;;;
-0E03;THAI CHARACTER KHO KHUAT;Lo;0;L;;;;;N;THAI LETTER KHO KHUAT;;;;
-0E04;THAI CHARACTER KHO KHWAI;Lo;0;L;;;;;N;THAI LETTER KHO KHWAI;;;;
-0E05;THAI CHARACTER KHO KHON;Lo;0;L;;;;;N;THAI LETTER KHO KHON;;;;
-0E06;THAI CHARACTER KHO RAKHANG;Lo;0;L;;;;;N;THAI LETTER KHO RAKHANG;;;;
-0E07;THAI CHARACTER NGO NGU;Lo;0;L;;;;;N;THAI LETTER NGO NGU;;;;
-0E08;THAI CHARACTER CHO CHAN;Lo;0;L;;;;;N;THAI LETTER CHO CHAN;;;;
-0E09;THAI CHARACTER CHO CHING;Lo;0;L;;;;;N;THAI LETTER CHO CHING;;;;
-0E0A;THAI CHARACTER CHO CHANG;Lo;0;L;;;;;N;THAI LETTER CHO CHANG;;;;
-0E0B;THAI CHARACTER SO SO;Lo;0;L;;;;;N;THAI LETTER SO SO;;;;
-0E0C;THAI CHARACTER CHO CHOE;Lo;0;L;;;;;N;THAI LETTER CHO CHOE;;;;
-0E0D;THAI CHARACTER YO YING;Lo;0;L;;;;;N;THAI LETTER YO YING;;;;
-0E0E;THAI CHARACTER DO CHADA;Lo;0;L;;;;;N;THAI LETTER DO CHADA;;;;
-0E0F;THAI CHARACTER TO PATAK;Lo;0;L;;;;;N;THAI LETTER TO PATAK;;;;
-0E10;THAI CHARACTER THO THAN;Lo;0;L;;;;;N;THAI LETTER THO THAN;;;;
-0E11;THAI CHARACTER THO NANGMONTHO;Lo;0;L;;;;;N;THAI LETTER THO NANGMONTHO;;;;
-0E12;THAI CHARACTER THO PHUTHAO;Lo;0;L;;;;;N;THAI LETTER THO PHUTHAO;;;;
-0E13;THAI CHARACTER NO NEN;Lo;0;L;;;;;N;THAI LETTER NO NEN;;;;
-0E14;THAI CHARACTER DO DEK;Lo;0;L;;;;;N;THAI LETTER DO DEK;;;;
-0E15;THAI CHARACTER TO TAO;Lo;0;L;;;;;N;THAI LETTER TO TAO;;;;
-0E16;THAI CHARACTER THO THUNG;Lo;0;L;;;;;N;THAI LETTER THO THUNG;;;;
-0E17;THAI CHARACTER THO THAHAN;Lo;0;L;;;;;N;THAI LETTER THO THAHAN;;;;
-0E18;THAI CHARACTER THO THONG;Lo;0;L;;;;;N;THAI LETTER THO THONG;;;;
-0E19;THAI CHARACTER NO NU;Lo;0;L;;;;;N;THAI LETTER NO NU;;;;
-0E1A;THAI CHARACTER BO BAIMAI;Lo;0;L;;;;;N;THAI LETTER BO BAIMAI;;;;
-0E1B;THAI CHARACTER PO PLA;Lo;0;L;;;;;N;THAI LETTER PO PLA;;;;
-0E1C;THAI CHARACTER PHO PHUNG;Lo;0;L;;;;;N;THAI LETTER PHO PHUNG;;;;
-0E1D;THAI CHARACTER FO FA;Lo;0;L;;;;;N;THAI LETTER FO FA;;;;
-0E1E;THAI CHARACTER PHO PHAN;Lo;0;L;;;;;N;THAI LETTER PHO PHAN;;;;
-0E1F;THAI CHARACTER FO FAN;Lo;0;L;;;;;N;THAI LETTER FO FAN;;;;
-0E20;THAI CHARACTER PHO SAMPHAO;Lo;0;L;;;;;N;THAI LETTER PHO SAMPHAO;;;;
-0E21;THAI CHARACTER MO MA;Lo;0;L;;;;;N;THAI LETTER MO MA;;;;
-0E22;THAI CHARACTER YO YAK;Lo;0;L;;;;;N;THAI LETTER YO YAK;;;;
-0E23;THAI CHARACTER RO RUA;Lo;0;L;;;;;N;THAI LETTER RO RUA;;;;
-0E24;THAI CHARACTER RU;Lo;0;L;;;;;N;THAI LETTER RU;;;;
-0E25;THAI CHARACTER LO LING;Lo;0;L;;;;;N;THAI LETTER LO LING;;;;
-0E26;THAI CHARACTER LU;Lo;0;L;;;;;N;THAI LETTER LU;;;;
-0E27;THAI CHARACTER WO WAEN;Lo;0;L;;;;;N;THAI LETTER WO WAEN;;;;
-0E28;THAI CHARACTER SO SALA;Lo;0;L;;;;;N;THAI LETTER SO SALA;;;;
-0E29;THAI CHARACTER SO RUSI;Lo;0;L;;;;;N;THAI LETTER SO RUSI;;;;
-0E2A;THAI CHARACTER SO SUA;Lo;0;L;;;;;N;THAI LETTER SO SUA;;;;
-0E2B;THAI CHARACTER HO HIP;Lo;0;L;;;;;N;THAI LETTER HO HIP;;;;
-0E2C;THAI CHARACTER LO CHULA;Lo;0;L;;;;;N;THAI LETTER LO CHULA;;;;
-0E2D;THAI CHARACTER O ANG;Lo;0;L;;;;;N;THAI LETTER O ANG;;;;
-0E2E;THAI CHARACTER HO NOKHUK;Lo;0;L;;;;;N;THAI LETTER HO NOK HUK;;;;
-0E2F;THAI CHARACTER PAIYANNOI;Lo;0;L;;;;;N;THAI PAI YAN NOI;;;;
-0E30;THAI CHARACTER SARA A;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA A;;;;
-0E31;THAI CHARACTER MAI HAN-AKAT;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI HAN-AKAT;;;;
-0E32;THAI CHARACTER SARA AA;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AA;;;;
-0E33;THAI CHARACTER SARA AM;Lo;0;L;<compat> 0E4D 0E32;;;;N;THAI VOWEL SIGN SARA AM;;;;
-0E34;THAI CHARACTER SARA I;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA I;;;;
-0E35;THAI CHARACTER SARA II;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA II;;;;
-0E36;THAI CHARACTER SARA UE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UE;;;;
-0E37;THAI CHARACTER SARA UEE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UEE;;;;
-0E38;THAI CHARACTER SARA U;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA U;;;;
-0E39;THAI CHARACTER SARA UU;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA UU;;;;
-0E3A;THAI CHARACTER PHINTHU;Mn;9;NSM;;;;;N;THAI VOWEL SIGN PHINTHU;;;;
-0E3F;THAI CURRENCY SYMBOL BAHT;Sc;0;ET;;;;;N;THAI BAHT SIGN;;;;
-0E40;THAI CHARACTER SARA E;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA E;;;;
-0E41;THAI CHARACTER SARA AE;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AE;;;;
-0E42;THAI CHARACTER SARA O;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA O;;;;
-0E43;THAI CHARACTER SARA AI MAIMUAN;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MUAN;;;;
-0E44;THAI CHARACTER SARA AI MAIMALAI;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MALAI;;;;
-0E45;THAI CHARACTER LAKKHANGYAO;Lo;0;L;;;;;N;THAI LAK KHANG YAO;;;;
-0E46;THAI CHARACTER MAIYAMOK;Lm;0;L;;;;;N;THAI MAI YAMOK;;;;
-0E47;THAI CHARACTER MAITAIKHU;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI TAI KHU;;;;
-0E48;THAI CHARACTER MAI EK;Mn;107;NSM;;;;;N;THAI TONE MAI EK;;;;
-0E49;THAI CHARACTER MAI THO;Mn;107;NSM;;;;;N;THAI TONE MAI THO;;;;
-0E4A;THAI CHARACTER MAI TRI;Mn;107;NSM;;;;;N;THAI TONE MAI TRI;;;;
-0E4B;THAI CHARACTER MAI CHATTAWA;Mn;107;NSM;;;;;N;THAI TONE MAI CHATTAWA;;;;
-0E4C;THAI CHARACTER THANTHAKHAT;Mn;0;NSM;;;;;N;THAI THANTHAKHAT;;;;
-0E4D;THAI CHARACTER NIKHAHIT;Mn;0;NSM;;;;;N;THAI NIKKHAHIT;;;;
-0E4E;THAI CHARACTER YAMAKKAN;Mn;0;NSM;;;;;N;THAI YAMAKKAN;;;;
-0E4F;THAI CHARACTER FONGMAN;Po;0;L;;;;;N;THAI FONGMAN;;;;
-0E50;THAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0E51;THAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0E52;THAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0E53;THAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0E54;THAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0E55;THAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0E56;THAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0E57;THAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0E58;THAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0E59;THAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0E5A;THAI CHARACTER ANGKHANKHU;Po;0;L;;;;;N;THAI ANGKHANKHU;;;;
-0E5B;THAI CHARACTER KHOMUT;Po;0;L;;;;;N;THAI KHOMUT;;;;
-0E81;LAO LETTER KO;Lo;0;L;;;;;N;;;;;
-0E82;LAO LETTER KHO SUNG;Lo;0;L;;;;;N;;;;;
-0E84;LAO LETTER KHO TAM;Lo;0;L;;;;;N;;;;;
-0E87;LAO LETTER NGO;Lo;0;L;;;;;N;;;;;
-0E88;LAO LETTER CO;Lo;0;L;;;;;N;;;;;
-0E8A;LAO LETTER SO TAM;Lo;0;L;;;;;N;;;;;
-0E8D;LAO LETTER NYO;Lo;0;L;;;;;N;;;;;
-0E94;LAO LETTER DO;Lo;0;L;;;;;N;;;;;
-0E95;LAO LETTER TO;Lo;0;L;;;;;N;;;;;
-0E96;LAO LETTER THO SUNG;Lo;0;L;;;;;N;;;;;
-0E97;LAO LETTER THO TAM;Lo;0;L;;;;;N;;;;;
-0E99;LAO LETTER NO;Lo;0;L;;;;;N;;;;;
-0E9A;LAO LETTER BO;Lo;0;L;;;;;N;;;;;
-0E9B;LAO LETTER PO;Lo;0;L;;;;;N;;;;;
-0E9C;LAO LETTER PHO SUNG;Lo;0;L;;;;;N;;;;;
-0E9D;LAO LETTER FO TAM;Lo;0;L;;;;;N;;;;;
-0E9E;LAO LETTER PHO TAM;Lo;0;L;;;;;N;;;;;
-0E9F;LAO LETTER FO SUNG;Lo;0;L;;;;;N;;;;;
-0EA1;LAO LETTER MO;Lo;0;L;;;;;N;;;;;
-0EA2;LAO LETTER YO;Lo;0;L;;;;;N;;;;;
-0EA3;LAO LETTER LO LING;Lo;0;L;;;;;N;;;;;
-0EA5;LAO LETTER LO LOOT;Lo;0;L;;;;;N;;;;;
-0EA7;LAO LETTER WO;Lo;0;L;;;;;N;;;;;
-0EAA;LAO LETTER SO SUNG;Lo;0;L;;;;;N;;;;;
-0EAB;LAO LETTER HO SUNG;Lo;0;L;;;;;N;;;;;
-0EAD;LAO LETTER O;Lo;0;L;;;;;N;;;;;
-0EAE;LAO LETTER HO TAM;Lo;0;L;;;;;N;;;;;
-0EAF;LAO ELLIPSIS;Lo;0;L;;;;;N;;;;;
-0EB0;LAO VOWEL SIGN A;Lo;0;L;;;;;N;;;;;
-0EB1;LAO VOWEL SIGN MAI KAN;Mn;0;NSM;;;;;N;;;;;
-0EB2;LAO VOWEL SIGN AA;Lo;0;L;;;;;N;;;;;
-0EB3;LAO VOWEL SIGN AM;Lo;0;L;<compat> 0ECD 0EB2;;;;N;;;;;
-0EB4;LAO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-0EB5;LAO VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-0EB6;LAO VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;;
-0EB7;LAO VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;;
-0EB8;LAO VOWEL SIGN U;Mn;118;NSM;;;;;N;;;;;
-0EB9;LAO VOWEL SIGN UU;Mn;118;NSM;;;;;N;;;;;
-0EBB;LAO VOWEL SIGN MAI KON;Mn;0;NSM;;;;;N;;;;;
-0EBC;LAO SEMIVOWEL SIGN LO;Mn;0;NSM;;;;;N;;;;;
-0EBD;LAO SEMIVOWEL SIGN NYO;Lo;0;L;;;;;N;;;;;
-0EC0;LAO VOWEL SIGN E;Lo;0;L;;;;;N;;;;;
-0EC1;LAO VOWEL SIGN EI;Lo;0;L;;;;;N;;;;;
-0EC2;LAO VOWEL SIGN O;Lo;0;L;;;;;N;;;;;
-0EC3;LAO VOWEL SIGN AY;Lo;0;L;;;;;N;;;;;
-0EC4;LAO VOWEL SIGN AI;Lo;0;L;;;;;N;;;;;
-0EC6;LAO KO LA;Lm;0;L;;;;;N;;;;;
-0EC8;LAO TONE MAI EK;Mn;122;NSM;;;;;N;;;;;
-0EC9;LAO TONE MAI THO;Mn;122;NSM;;;;;N;;;;;
-0ECA;LAO TONE MAI TI;Mn;122;NSM;;;;;N;;;;;
-0ECB;LAO TONE MAI CATAWA;Mn;122;NSM;;;;;N;;;;;
-0ECC;LAO CANCELLATION MARK;Mn;0;NSM;;;;;N;;;;;
-0ECD;LAO NIGGAHITA;Mn;0;NSM;;;;;N;;;;;
-0ED0;LAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0ED1;LAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0ED2;LAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0ED3;LAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0ED4;LAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0ED5;LAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0ED6;LAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0ED7;LAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0ED8;LAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0ED9;LAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0EDC;LAO HO NO;Lo;0;L;<compat> 0EAB 0E99;;;;N;;;;;
-0EDD;LAO HO MO;Lo;0;L;<compat> 0EAB 0EA1;;;;N;;;;;
-0EDE;LAO LETTER KHMU GO;Lo;0;L;;;;;N;;;;;
-0EDF;LAO LETTER KHMU NYO;Lo;0;L;;;;;N;;;;;
-0F00;TIBETAN SYLLABLE OM;Lo;0;L;;;;;N;;;;;
-0F01;TIBETAN MARK GTER YIG MGO TRUNCATED A;So;0;L;;;;;N;;;;;
-0F02;TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA;So;0;L;;;;;N;;;;;
-0F03;TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA;So;0;L;;;;;N;;;;;
-0F04;TIBETAN MARK INITIAL YIG MGO MDUN MA;Po;0;L;;;;;N;TIBETAN SINGLE ORNAMENT;;;;
-0F05;TIBETAN MARK CLOSING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;;
-0F06;TIBETAN MARK CARET YIG MGO PHUR SHAD MA;Po;0;L;;;;;N;;;;;
-0F07;TIBETAN MARK YIG MGO TSHEG SHAD MA;Po;0;L;;;;;N;;;;;
-0F08;TIBETAN MARK SBRUL SHAD;Po;0;L;;;;;N;TIBETAN RGYANSHAD;;;;
-0F09;TIBETAN MARK BSKUR YIG MGO;Po;0;L;;;;;N;;;;;
-0F0A;TIBETAN MARK BKA- SHOG YIG MGO;Po;0;L;;;;;N;;;;;
-0F0B;TIBETAN MARK INTERSYLLABIC TSHEG;Po;0;L;;;;;N;TIBETAN TSEG;;;;
-0F0C;TIBETAN MARK DELIMITER TSHEG BSTAR;Po;0;L;<noBreak> 0F0B;;;;N;;;;;
-0F0D;TIBETAN MARK SHAD;Po;0;L;;;;;N;TIBETAN SHAD;;;;
-0F0E;TIBETAN MARK NYIS SHAD;Po;0;L;;;;;N;TIBETAN DOUBLE SHAD;;;;
-0F0F;TIBETAN MARK TSHEG SHAD;Po;0;L;;;;;N;;;;;
-0F10;TIBETAN MARK NYIS TSHEG SHAD;Po;0;L;;;;;N;;;;;
-0F11;TIBETAN MARK RIN CHEN SPUNGS SHAD;Po;0;L;;;;;N;TIBETAN RINCHANPHUNGSHAD;;;;
-0F12;TIBETAN MARK RGYA GRAM SHAD;Po;0;L;;;;;N;;;;;
-0F13;TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN;So;0;L;;;;;N;;;;;
-0F14;TIBETAN MARK GTER TSHEG;Po;0;L;;;;;N;TIBETAN COMMA;;;;
-0F15;TIBETAN LOGOTYPE SIGN CHAD RTAGS;So;0;L;;;;;N;;;;;
-0F16;TIBETAN LOGOTYPE SIGN LHAG RTAGS;So;0;L;;;;;N;;;;;
-0F17;TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS;So;0;L;;;;;N;;;;;
-0F18;TIBETAN ASTROLOGICAL SIGN -KHYUD PA;Mn;220;NSM;;;;;N;;;;;
-0F19;TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS;Mn;220;NSM;;;;;N;;;;;
-0F1A;TIBETAN SIGN RDEL DKAR GCIG;So;0;L;;;;;N;;;;;
-0F1B;TIBETAN SIGN RDEL DKAR GNYIS;So;0;L;;;;;N;;;;;
-0F1C;TIBETAN SIGN RDEL DKAR GSUM;So;0;L;;;;;N;;;;;
-0F1D;TIBETAN SIGN RDEL NAG GCIG;So;0;L;;;;;N;;;;;
-0F1E;TIBETAN SIGN RDEL NAG GNYIS;So;0;L;;;;;N;;;;;
-0F1F;TIBETAN SIGN RDEL DKAR RDEL NAG;So;0;L;;;;;N;;;;;
-0F20;TIBETAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-0F21;TIBETAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-0F22;TIBETAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-0F23;TIBETAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-0F24;TIBETAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-0F25;TIBETAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-0F26;TIBETAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-0F27;TIBETAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-0F28;TIBETAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-0F29;TIBETAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-0F2A;TIBETAN DIGIT HALF ONE;No;0;L;;;;1/2;N;;;;;
-0F2B;TIBETAN DIGIT HALF TWO;No;0;L;;;;3/2;N;;;;;
-0F2C;TIBETAN DIGIT HALF THREE;No;0;L;;;;5/2;N;;;;;
-0F2D;TIBETAN DIGIT HALF FOUR;No;0;L;;;;7/2;N;;;;;
-0F2E;TIBETAN DIGIT HALF FIVE;No;0;L;;;;9/2;N;;;;;
-0F2F;TIBETAN DIGIT HALF SIX;No;0;L;;;;11/2;N;;;;;
-0F30;TIBETAN DIGIT HALF SEVEN;No;0;L;;;;13/2;N;;;;;
-0F31;TIBETAN DIGIT HALF EIGHT;No;0;L;;;;15/2;N;;;;;
-0F32;TIBETAN DIGIT HALF NINE;No;0;L;;;;17/2;N;;;;;
-0F33;TIBETAN DIGIT HALF ZERO;No;0;L;;;;-1/2;N;;;;;
-0F34;TIBETAN MARK BSDUS RTAGS;So;0;L;;;;;N;;;;;
-0F35;TIBETAN MARK NGAS BZUNG NYI ZLA;Mn;220;NSM;;;;;N;TIBETAN HONORIFIC UNDER RING;;;;
-0F36;TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN;So;0;L;;;;;N;;;;;
-0F37;TIBETAN MARK NGAS BZUNG SGOR RTAGS;Mn;220;NSM;;;;;N;TIBETAN UNDER RING;;;;
-0F38;TIBETAN MARK CHE MGO;So;0;L;;;;;N;;;;;
-0F39;TIBETAN MARK TSA -PHRU;Mn;216;NSM;;;;;N;TIBETAN LENITION MARK;;;;
-0F3A;TIBETAN MARK GUG RTAGS GYON;Ps;0;ON;;;;;Y;;;;;
-0F3B;TIBETAN MARK GUG RTAGS GYAS;Pe;0;ON;;;;;Y;;;;;
-0F3C;TIBETAN MARK ANG KHANG GYON;Ps;0;ON;;;;;Y;TIBETAN LEFT BRACE;;;;
-0F3D;TIBETAN MARK ANG KHANG GYAS;Pe;0;ON;;;;;Y;TIBETAN RIGHT BRACE;;;;
-0F3E;TIBETAN SIGN YAR TSHES;Mc;0;L;;;;;N;;;;;
-0F3F;TIBETAN SIGN MAR TSHES;Mc;0;L;;;;;N;;;;;
-0F40;TIBETAN LETTER KA;Lo;0;L;;;;;N;;;;;
-0F41;TIBETAN LETTER KHA;Lo;0;L;;;;;N;;;;;
-0F42;TIBETAN LETTER GA;Lo;0;L;;;;;N;;;;;
-0F43;TIBETAN LETTER GHA;Lo;0;L;0F42 0FB7;;;;N;;;;;
-0F44;TIBETAN LETTER NGA;Lo;0;L;;;;;N;;;;;
-0F45;TIBETAN LETTER CA;Lo;0;L;;;;;N;;;;;
-0F46;TIBETAN LETTER CHA;Lo;0;L;;;;;N;;;;;
-0F47;TIBETAN LETTER JA;Lo;0;L;;;;;N;;;;;
-0F49;TIBETAN LETTER NYA;Lo;0;L;;;;;N;;;;;
-0F4A;TIBETAN LETTER TTA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED TA;;;;
-0F4B;TIBETAN LETTER TTHA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED THA;;;;
-0F4C;TIBETAN LETTER DDA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED DA;;;;
-0F4D;TIBETAN LETTER DDHA;Lo;0;L;0F4C 0FB7;;;;N;;;;;
-0F4E;TIBETAN LETTER NNA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED NA;;;;
-0F4F;TIBETAN LETTER TA;Lo;0;L;;;;;N;;;;;
-0F50;TIBETAN LETTER THA;Lo;0;L;;;;;N;;;;;
-0F51;TIBETAN LETTER DA;Lo;0;L;;;;;N;;;;;
-0F52;TIBETAN LETTER DHA;Lo;0;L;0F51 0FB7;;;;N;;;;;
-0F53;TIBETAN LETTER NA;Lo;0;L;;;;;N;;;;;
-0F54;TIBETAN LETTER PA;Lo;0;L;;;;;N;;;;;
-0F55;TIBETAN LETTER PHA;Lo;0;L;;;;;N;;;;;
-0F56;TIBETAN LETTER BA;Lo;0;L;;;;;N;;;;;
-0F57;TIBETAN LETTER BHA;Lo;0;L;0F56 0FB7;;;;N;;;;;
-0F58;TIBETAN LETTER MA;Lo;0;L;;;;;N;;;;;
-0F59;TIBETAN LETTER TSA;Lo;0;L;;;;;N;;;;;
-0F5A;TIBETAN LETTER TSHA;Lo;0;L;;;;;N;;;;;
-0F5B;TIBETAN LETTER DZA;Lo;0;L;;;;;N;;;;;
-0F5C;TIBETAN LETTER DZHA;Lo;0;L;0F5B 0FB7;;;;N;;;;;
-0F5D;TIBETAN LETTER WA;Lo;0;L;;;;;N;;;;;
-0F5E;TIBETAN LETTER ZHA;Lo;0;L;;;;;N;;;;;
-0F5F;TIBETAN LETTER ZA;Lo;0;L;;;;;N;;;;;
-0F60;TIBETAN LETTER -A;Lo;0;L;;;;;N;TIBETAN LETTER AA;;;;
-0F61;TIBETAN LETTER YA;Lo;0;L;;;;;N;;;;;
-0F62;TIBETAN LETTER RA;Lo;0;L;;;;;N;;;;;
-0F63;TIBETAN LETTER LA;Lo;0;L;;;;;N;;;;;
-0F64;TIBETAN LETTER SHA;Lo;0;L;;;;;N;;;;;
-0F65;TIBETAN LETTER SSA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED SHA;;;;
-0F66;TIBETAN LETTER SA;Lo;0;L;;;;;N;;;;;
-0F67;TIBETAN LETTER HA;Lo;0;L;;;;;N;;;;;
-0F68;TIBETAN LETTER A;Lo;0;L;;;;;N;;;;;
-0F69;TIBETAN LETTER KSSA;Lo;0;L;0F40 0FB5;;;;N;;;;;
-0F6A;TIBETAN LETTER FIXED-FORM RA;Lo;0;L;;;;;N;;;;;
-0F6B;TIBETAN LETTER KKA;Lo;0;L;;;;;N;;;;;
-0F6C;TIBETAN LETTER RRA;Lo;0;L;;;;;N;;;;;
-0F71;TIBETAN VOWEL SIGN AA;Mn;129;NSM;;;;;N;;;;;
-0F72;TIBETAN VOWEL SIGN I;Mn;130;NSM;;;;;N;;;;;
-0F73;TIBETAN VOWEL SIGN II;Mn;0;NSM;0F71 0F72;;;;N;;;;;
-0F74;TIBETAN VOWEL SIGN U;Mn;132;NSM;;;;;N;;;;;
-0F75;TIBETAN VOWEL SIGN UU;Mn;0;NSM;0F71 0F74;;;;N;;;;;
-0F76;TIBETAN VOWEL SIGN VOCALIC R;Mn;0;NSM;0FB2 0F80;;;;N;;;;;
-0F77;TIBETAN VOWEL SIGN VOCALIC RR;Mn;0;NSM;<compat> 0FB2 0F81;;;;N;;;;;
-0F78;TIBETAN VOWEL SIGN VOCALIC L;Mn;0;NSM;0FB3 0F80;;;;N;;;;;
-0F79;TIBETAN VOWEL SIGN VOCALIC LL;Mn;0;NSM;<compat> 0FB3 0F81;;;;N;;;;;
-0F7A;TIBETAN VOWEL SIGN E;Mn;130;NSM;;;;;N;;;;;
-0F7B;TIBETAN VOWEL SIGN EE;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AI;;;;
-0F7C;TIBETAN VOWEL SIGN O;Mn;130;NSM;;;;;N;;;;;
-0F7D;TIBETAN VOWEL SIGN OO;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AU;;;;
-0F7E;TIBETAN SIGN RJES SU NGA RO;Mn;0;NSM;;;;;N;TIBETAN ANUSVARA;;;;
-0F7F;TIBETAN SIGN RNAM BCAD;Mc;0;L;;;;;N;TIBETAN VISARGA;;;;
-0F80;TIBETAN VOWEL SIGN REVERSED I;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN SHORT I;;;;
-0F81;TIBETAN VOWEL SIGN REVERSED II;Mn;0;NSM;0F71 0F80;;;;N;;;;;
-0F82;TIBETAN SIGN NYI ZLA NAA DA;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU WITH ORNAMENT;;;;
-0F83;TIBETAN SIGN SNA LDAN;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU;;;;
-0F84;TIBETAN MARK HALANTA;Mn;9;NSM;;;;;N;TIBETAN VIRAMA;;;;
-0F85;TIBETAN MARK PALUTA;Po;0;L;;;;;N;TIBETAN CHUCHENYIGE;;;;
-0F86;TIBETAN SIGN LCI RTAGS;Mn;230;NSM;;;;;N;;;;;
-0F87;TIBETAN SIGN YANG RTAGS;Mn;230;NSM;;;;;N;;;;;
-0F88;TIBETAN SIGN LCE TSA CAN;Lo;0;L;;;;;N;;;;;
-0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;;;;
-0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;;;;
-0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;;;;
-0F8C;TIBETAN SIGN INVERTED MCHU CAN;Lo;0;L;;;;;N;;;;;
-0F8D;TIBETAN SUBJOINED SIGN LCE TSA CAN;Mn;0;NSM;;;;;N;;;;;
-0F8E;TIBETAN SUBJOINED SIGN MCHU CAN;Mn;0;NSM;;;;;N;;;;;
-0F8F;TIBETAN SUBJOINED SIGN INVERTED MCHU CAN;Mn;0;NSM;;;;;N;;;;;
-0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;;
-0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;;
-0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;;
-0F93;TIBETAN SUBJOINED LETTER GHA;Mn;0;NSM;0F92 0FB7;;;;N;;;;;
-0F94;TIBETAN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;;
-0F95;TIBETAN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;;
-0F96;TIBETAN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;;
-0F97;TIBETAN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;;
-0F99;TIBETAN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;;
-0F9A;TIBETAN SUBJOINED LETTER TTA;Mn;0;NSM;;;;;N;;;;;
-0F9B;TIBETAN SUBJOINED LETTER TTHA;Mn;0;NSM;;;;;N;;;;;
-0F9C;TIBETAN SUBJOINED LETTER DDA;Mn;0;NSM;;;;;N;;;;;
-0F9D;TIBETAN SUBJOINED LETTER DDHA;Mn;0;NSM;0F9C 0FB7;;;;N;;;;;
-0F9E;TIBETAN SUBJOINED LETTER NNA;Mn;0;NSM;;;;;N;;;;;
-0F9F;TIBETAN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;;
-0FA0;TIBETAN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;;
-0FA1;TIBETAN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;;
-0FA2;TIBETAN SUBJOINED LETTER DHA;Mn;0;NSM;0FA1 0FB7;;;;N;;;;;
-0FA3;TIBETAN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;;
-0FA4;TIBETAN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;;
-0FA5;TIBETAN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;;
-0FA6;TIBETAN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;;
-0FA7;TIBETAN SUBJOINED LETTER BHA;Mn;0;NSM;0FA6 0FB7;;;;N;;;;;
-0FA8;TIBETAN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;;
-0FA9;TIBETAN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;;
-0FAA;TIBETAN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;;
-0FAB;TIBETAN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;;
-0FAC;TIBETAN SUBJOINED LETTER DZHA;Mn;0;NSM;0FAB 0FB7;;;;N;;;;;
-0FAD;TIBETAN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;;
-0FAE;TIBETAN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;;
-0FAF;TIBETAN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;;
-0FB0;TIBETAN SUBJOINED LETTER -A;Mn;0;NSM;;;;;N;;;;;
-0FB1;TIBETAN SUBJOINED LETTER YA;Mn;0;NSM;;;;;N;;;;;
-0FB2;TIBETAN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;;
-0FB3;TIBETAN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;;
-0FB4;TIBETAN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;;
-0FB5;TIBETAN SUBJOINED LETTER SSA;Mn;0;NSM;;;;;N;;;;;
-0FB6;TIBETAN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;;
-0FB7;TIBETAN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;;
-0FB8;TIBETAN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;;
-0FB9;TIBETAN SUBJOINED LETTER KSSA;Mn;0;NSM;0F90 0FB5;;;;N;;;;;
-0FBA;TIBETAN SUBJOINED LETTER FIXED-FORM WA;Mn;0;NSM;;;;;N;;;;;
-0FBB;TIBETAN SUBJOINED LETTER FIXED-FORM YA;Mn;0;NSM;;;;;N;;;;;
-0FBC;TIBETAN SUBJOINED LETTER FIXED-FORM RA;Mn;0;NSM;;;;;N;;;;;
-0FBE;TIBETAN KU RU KHA;So;0;L;;;;;N;;;;;
-0FBF;TIBETAN KU RU KHA BZHI MIG CAN;So;0;L;;;;;N;;;;;
-0FC0;TIBETAN CANTILLATION SIGN HEAVY BEAT;So;0;L;;;;;N;;;;;
-0FC1;TIBETAN CANTILLATION SIGN LIGHT BEAT;So;0;L;;;;;N;;;;;
-0FC2;TIBETAN CANTILLATION SIGN CANG TE-U;So;0;L;;;;;N;;;;;
-0FC3;TIBETAN CANTILLATION SIGN SBUB -CHAL;So;0;L;;;;;N;;;;;
-0FC4;TIBETAN SYMBOL DRIL BU;So;0;L;;;;;N;;;;;
-0FC5;TIBETAN SYMBOL RDO RJE;So;0;L;;;;;N;;;;;
-0FC6;TIBETAN SYMBOL PADMA GDAN;Mn;220;NSM;;;;;N;;;;;
-0FC7;TIBETAN SYMBOL RDO RJE RGYA GRAM;So;0;L;;;;;N;;;;;
-0FC8;TIBETAN SYMBOL PHUR PA;So;0;L;;;;;N;;;;;
-0FC9;TIBETAN SYMBOL NOR BU;So;0;L;;;;;N;;;;;
-0FCA;TIBETAN SYMBOL NOR BU NYIS -KHYIL;So;0;L;;;;;N;;;;;
-0FCB;TIBETAN SYMBOL NOR BU GSUM -KHYIL;So;0;L;;;;;N;;;;;
-0FCC;TIBETAN SYMBOL NOR BU BZHI -KHYIL;So;0;L;;;;;N;;;;;
-0FCE;TIBETAN SIGN RDEL NAG RDEL DKAR;So;0;L;;;;;N;;;;;
-0FCF;TIBETAN SIGN RDEL NAG GSUM;So;0;L;;;;;N;;;;;
-0FD0;TIBETAN MARK BSKA- SHOG GI MGO RGYAN;Po;0;L;;;;;N;;;;;
-0FD1;TIBETAN MARK MNYAM YIG GI MGO RGYAN;Po;0;L;;;;;N;;;;;
-0FD2;TIBETAN MARK NYIS TSHEG;Po;0;L;;;;;N;;;;;
-0FD3;TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA;Po;0;L;;;;;N;;;;;
-0FD4;TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;;
-0FD5;RIGHT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;;
-0FD6;LEFT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;;
-0FD7;RIGHT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;;
-0FD8;LEFT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;;
-0FD9;TIBETAN MARK LEADING MCHAN RTAGS;Po;0;L;;;;;N;;;;;
-0FDA;TIBETAN MARK TRAILING MCHAN RTAGS;Po;0;L;;;;;N;;;;;
-1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;;
-1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;;
-1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;;
-1003;MYANMAR LETTER GHA;Lo;0;L;;;;;N;;;;;
-1004;MYANMAR LETTER NGA;Lo;0;L;;;;;N;;;;;
-1005;MYANMAR LETTER CA;Lo;0;L;;;;;N;;;;;
-1006;MYANMAR LETTER CHA;Lo;0;L;;;;;N;;;;;
-1007;MYANMAR LETTER JA;Lo;0;L;;;;;N;;;;;
-1008;MYANMAR LETTER JHA;Lo;0;L;;;;;N;;;;;
-1009;MYANMAR LETTER NYA;Lo;0;L;;;;;N;;;;;
-100A;MYANMAR LETTER NNYA;Lo;0;L;;;;;N;;;;;
-100B;MYANMAR LETTER TTA;Lo;0;L;;;;;N;;;;;
-100C;MYANMAR LETTER TTHA;Lo;0;L;;;;;N;;;;;
-100D;MYANMAR LETTER DDA;Lo;0;L;;;;;N;;;;;
-100E;MYANMAR LETTER DDHA;Lo;0;L;;;;;N;;;;;
-100F;MYANMAR LETTER NNA;Lo;0;L;;;;;N;;;;;
-1010;MYANMAR LETTER TA;Lo;0;L;;;;;N;;;;;
-1011;MYANMAR LETTER THA;Lo;0;L;;;;;N;;;;;
-1012;MYANMAR LETTER DA;Lo;0;L;;;;;N;;;;;
-1013;MYANMAR LETTER DHA;Lo;0;L;;;;;N;;;;;
-1014;MYANMAR LETTER NA;Lo;0;L;;;;;N;;;;;
-1015;MYANMAR LETTER PA;Lo;0;L;;;;;N;;;;;
-1016;MYANMAR LETTER PHA;Lo;0;L;;;;;N;;;;;
-1017;MYANMAR LETTER BA;Lo;0;L;;;;;N;;;;;
-1018;MYANMAR LETTER BHA;Lo;0;L;;;;;N;;;;;
-1019;MYANMAR LETTER MA;Lo;0;L;;;;;N;;;;;
-101A;MYANMAR LETTER YA;Lo;0;L;;;;;N;;;;;
-101B;MYANMAR LETTER RA;Lo;0;L;;;;;N;;;;;
-101C;MYANMAR LETTER LA;Lo;0;L;;;;;N;;;;;
-101D;MYANMAR LETTER WA;Lo;0;L;;;;;N;;;;;
-101E;MYANMAR LETTER SA;Lo;0;L;;;;;N;;;;;
-101F;MYANMAR LETTER HA;Lo;0;L;;;;;N;;;;;
-1020;MYANMAR LETTER LLA;Lo;0;L;;;;;N;;;;;
-1021;MYANMAR LETTER A;Lo;0;L;;;;;N;;;;;
-1022;MYANMAR LETTER SHAN A;Lo;0;L;;;;;N;;;;;
-1023;MYANMAR LETTER I;Lo;0;L;;;;;N;;;;;
-1024;MYANMAR LETTER II;Lo;0;L;;;;;N;;;;;
-1025;MYANMAR LETTER U;Lo;0;L;;;;;N;;;;;
-1026;MYANMAR LETTER UU;Lo;0;L;1025 102E;;;;N;;;;;
-1027;MYANMAR LETTER E;Lo;0;L;;;;;N;;;;;
-1028;MYANMAR LETTER MON E;Lo;0;L;;;;;N;;;;;
-1029;MYANMAR LETTER O;Lo;0;L;;;;;N;;;;;
-102A;MYANMAR LETTER AU;Lo;0;L;;;;;N;;;;;
-102B;MYANMAR VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;;
-102C;MYANMAR VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-102D;MYANMAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-102E;MYANMAR VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-102F;MYANMAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1030;MYANMAR VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-1031;MYANMAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-1032;MYANMAR VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-1033;MYANMAR VOWEL SIGN MON II;Mn;0;NSM;;;;;N;;;;;
-1034;MYANMAR VOWEL SIGN MON O;Mn;0;NSM;;;;;N;;;;;
-1035;MYANMAR VOWEL SIGN E ABOVE;Mn;0;NSM;;;;;N;;;;;
-1036;MYANMAR SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-1037;MYANMAR SIGN DOT BELOW;Mn;7;NSM;;;;;N;;;;;
-1038;MYANMAR SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-1039;MYANMAR SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-103A;MYANMAR SIGN ASAT;Mn;9;NSM;;;;;N;;;;;
-103B;MYANMAR CONSONANT SIGN MEDIAL YA;Mc;0;L;;;;;N;;;;;
-103C;MYANMAR CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;;
-103D;MYANMAR CONSONANT SIGN MEDIAL WA;Mn;0;NSM;;;;;N;;;;;
-103E;MYANMAR CONSONANT SIGN MEDIAL HA;Mn;0;NSM;;;;;N;;;;;
-103F;MYANMAR LETTER GREAT SA;Lo;0;L;;;;;N;;;;;
-1040;MYANMAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1041;MYANMAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1042;MYANMAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1043;MYANMAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1044;MYANMAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1045;MYANMAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1046;MYANMAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1047;MYANMAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1048;MYANMAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1049;MYANMAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-104A;MYANMAR SIGN LITTLE SECTION;Po;0;L;;;;;N;;;;;
-104B;MYANMAR SIGN SECTION;Po;0;L;;;;;N;;;;;
-104C;MYANMAR SYMBOL LOCATIVE;Po;0;L;;;;;N;;;;;
-104D;MYANMAR SYMBOL COMPLETED;Po;0;L;;;;;N;;;;;
-104E;MYANMAR SYMBOL AFOREMENTIONED;Po;0;L;;;;;N;;;;;
-104F;MYANMAR SYMBOL GENITIVE;Po;0;L;;;;;N;;;;;
-1050;MYANMAR LETTER SHA;Lo;0;L;;;;;N;;;;;
-1051;MYANMAR LETTER SSA;Lo;0;L;;;;;N;;;;;
-1052;MYANMAR LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-1053;MYANMAR LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-1054;MYANMAR LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-1055;MYANMAR LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-1056;MYANMAR VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;;
-1057;MYANMAR VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;;
-1058;MYANMAR VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-1059;MYANMAR VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-105A;MYANMAR LETTER MON NGA;Lo;0;L;;;;;N;;;;;
-105B;MYANMAR LETTER MON JHA;Lo;0;L;;;;;N;;;;;
-105C;MYANMAR LETTER MON BBA;Lo;0;L;;;;;N;;;;;
-105D;MYANMAR LETTER MON BBE;Lo;0;L;;;;;N;;;;;
-105E;MYANMAR CONSONANT SIGN MON MEDIAL NA;Mn;0;NSM;;;;;N;;;;;
-105F;MYANMAR CONSONANT SIGN MON MEDIAL MA;Mn;0;NSM;;;;;N;;;;;
-1060;MYANMAR CONSONANT SIGN MON MEDIAL LA;Mn;0;NSM;;;;;N;;;;;
-1061;MYANMAR LETTER SGAW KAREN SHA;Lo;0;L;;;;;N;;;;;
-1062;MYANMAR VOWEL SIGN SGAW KAREN EU;Mc;0;L;;;;;N;;;;;
-1063;MYANMAR TONE MARK SGAW KAREN HATHI;Mc;0;L;;;;;N;;;;;
-1064;MYANMAR TONE MARK SGAW KAREN KE PHO;Mc;0;L;;;;;N;;;;;
-1065;MYANMAR LETTER WESTERN PWO KAREN THA;Lo;0;L;;;;;N;;;;;
-1066;MYANMAR LETTER WESTERN PWO KAREN PWA;Lo;0;L;;;;;N;;;;;
-1067;MYANMAR VOWEL SIGN WESTERN PWO KAREN EU;Mc;0;L;;;;;N;;;;;
-1068;MYANMAR VOWEL SIGN WESTERN PWO KAREN UE;Mc;0;L;;;;;N;;;;;
-1069;MYANMAR SIGN WESTERN PWO KAREN TONE-1;Mc;0;L;;;;;N;;;;;
-106A;MYANMAR SIGN WESTERN PWO KAREN TONE-2;Mc;0;L;;;;;N;;;;;
-106B;MYANMAR SIGN WESTERN PWO KAREN TONE-3;Mc;0;L;;;;;N;;;;;
-106C;MYANMAR SIGN WESTERN PWO KAREN TONE-4;Mc;0;L;;;;;N;;;;;
-106D;MYANMAR SIGN WESTERN PWO KAREN TONE-5;Mc;0;L;;;;;N;;;;;
-106E;MYANMAR LETTER EASTERN PWO KAREN NNA;Lo;0;L;;;;;N;;;;;
-106F;MYANMAR LETTER EASTERN PWO KAREN YWA;Lo;0;L;;;;;N;;;;;
-1070;MYANMAR LETTER EASTERN PWO KAREN GHWA;Lo;0;L;;;;;N;;;;;
-1071;MYANMAR VOWEL SIGN GEBA KAREN I;Mn;0;NSM;;;;;N;;;;;
-1072;MYANMAR VOWEL SIGN KAYAH OE;Mn;0;NSM;;;;;N;;;;;
-1073;MYANMAR VOWEL SIGN KAYAH U;Mn;0;NSM;;;;;N;;;;;
-1074;MYANMAR VOWEL SIGN KAYAH EE;Mn;0;NSM;;;;;N;;;;;
-1075;MYANMAR LETTER SHAN KA;Lo;0;L;;;;;N;;;;;
-1076;MYANMAR LETTER SHAN KHA;Lo;0;L;;;;;N;;;;;
-1077;MYANMAR LETTER SHAN GA;Lo;0;L;;;;;N;;;;;
-1078;MYANMAR LETTER SHAN CA;Lo;0;L;;;;;N;;;;;
-1079;MYANMAR LETTER SHAN ZA;Lo;0;L;;;;;N;;;;;
-107A;MYANMAR LETTER SHAN NYA;Lo;0;L;;;;;N;;;;;
-107B;MYANMAR LETTER SHAN DA;Lo;0;L;;;;;N;;;;;
-107C;MYANMAR LETTER SHAN NA;Lo;0;L;;;;;N;;;;;
-107D;MYANMAR LETTER SHAN PHA;Lo;0;L;;;;;N;;;;;
-107E;MYANMAR LETTER SHAN FA;Lo;0;L;;;;;N;;;;;
-107F;MYANMAR LETTER SHAN BA;Lo;0;L;;;;;N;;;;;
-1080;MYANMAR LETTER SHAN THA;Lo;0;L;;;;;N;;;;;
-1081;MYANMAR LETTER SHAN HA;Lo;0;L;;;;;N;;;;;
-1082;MYANMAR CONSONANT SIGN SHAN MEDIAL WA;Mn;0;NSM;;;;;N;;;;;
-1083;MYANMAR VOWEL SIGN SHAN AA;Mc;0;L;;;;;N;;;;;
-1084;MYANMAR VOWEL SIGN SHAN E;Mc;0;L;;;;;N;;;;;
-1085;MYANMAR VOWEL SIGN SHAN E ABOVE;Mn;0;NSM;;;;;N;;;;;
-1086;MYANMAR VOWEL SIGN SHAN FINAL Y;Mn;0;NSM;;;;;N;;;;;
-1087;MYANMAR SIGN SHAN TONE-2;Mc;0;L;;;;;N;;;;;
-1088;MYANMAR SIGN SHAN TONE-3;Mc;0;L;;;;;N;;;;;
-1089;MYANMAR SIGN SHAN TONE-5;Mc;0;L;;;;;N;;;;;
-108A;MYANMAR SIGN SHAN TONE-6;Mc;0;L;;;;;N;;;;;
-108B;MYANMAR SIGN SHAN COUNCIL TONE-2;Mc;0;L;;;;;N;;;;;
-108C;MYANMAR SIGN SHAN COUNCIL TONE-3;Mc;0;L;;;;;N;;;;;
-108D;MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE;Mn;220;NSM;;;;;N;;;;;
-108E;MYANMAR LETTER RUMAI PALAUNG FA;Lo;0;L;;;;;N;;;;;
-108F;MYANMAR SIGN RUMAI PALAUNG TONE-5;Mc;0;L;;;;;N;;;;;
-1090;MYANMAR SHAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1091;MYANMAR SHAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1092;MYANMAR SHAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1093;MYANMAR SHAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1094;MYANMAR SHAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1095;MYANMAR SHAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1096;MYANMAR SHAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1097;MYANMAR SHAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1098;MYANMAR SHAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1099;MYANMAR SHAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-109A;MYANMAR SIGN KHAMTI TONE-1;Mc;0;L;;;;;N;;;;;
-109B;MYANMAR SIGN KHAMTI TONE-3;Mc;0;L;;;;;N;;;;;
-109C;MYANMAR VOWEL SIGN AITON A;Mc;0;L;;;;;N;;;;;
-109D;MYANMAR VOWEL SIGN AITON AI;Mn;0;NSM;;;;;N;;;;;
-109E;MYANMAR SYMBOL SHAN ONE;So;0;L;;;;;N;;;;;
-109F;MYANMAR SYMBOL SHAN EXCLAMATION;So;0;L;;;;;N;;;;;
-10A0;GEORGIAN CAPITAL LETTER AN;Lu;0;L;;;;;N;;;;2D00;
-10A1;GEORGIAN CAPITAL LETTER BAN;Lu;0;L;;;;;N;;;;2D01;
-10A2;GEORGIAN CAPITAL LETTER GAN;Lu;0;L;;;;;N;;;;2D02;
-10A3;GEORGIAN CAPITAL LETTER DON;Lu;0;L;;;;;N;;;;2D03;
-10A4;GEORGIAN CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;2D04;
-10A5;GEORGIAN CAPITAL LETTER VIN;Lu;0;L;;;;;N;;;;2D05;
-10A6;GEORGIAN CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;;;2D06;
-10A7;GEORGIAN CAPITAL LETTER TAN;Lu;0;L;;;;;N;;;;2D07;
-10A8;GEORGIAN CAPITAL LETTER IN;Lu;0;L;;;;;N;;;;2D08;
-10A9;GEORGIAN CAPITAL LETTER KAN;Lu;0;L;;;;;N;;;;2D09;
-10AA;GEORGIAN CAPITAL LETTER LAS;Lu;0;L;;;;;N;;;;2D0A;
-10AB;GEORGIAN CAPITAL LETTER MAN;Lu;0;L;;;;;N;;;;2D0B;
-10AC;GEORGIAN CAPITAL LETTER NAR;Lu;0;L;;;;;N;;;;2D0C;
-10AD;GEORGIAN CAPITAL LETTER ON;Lu;0;L;;;;;N;;;;2D0D;
-10AE;GEORGIAN CAPITAL LETTER PAR;Lu;0;L;;;;;N;;;;2D0E;
-10AF;GEORGIAN CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;;;2D0F;
-10B0;GEORGIAN CAPITAL LETTER RAE;Lu;0;L;;;;;N;;;;2D10;
-10B1;GEORGIAN CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;2D11;
-10B2;GEORGIAN CAPITAL LETTER TAR;Lu;0;L;;;;;N;;;;2D12;
-10B3;GEORGIAN CAPITAL LETTER UN;Lu;0;L;;;;;N;;;;2D13;
-10B4;GEORGIAN CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;;;2D14;
-10B5;GEORGIAN CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;;;2D15;
-10B6;GEORGIAN CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;;;2D16;
-10B7;GEORGIAN CAPITAL LETTER QAR;Lu;0;L;;;;;N;;;;2D17;
-10B8;GEORGIAN CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;;;2D18;
-10B9;GEORGIAN CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;;;2D19;
-10BA;GEORGIAN CAPITAL LETTER CAN;Lu;0;L;;;;;N;;;;2D1A;
-10BB;GEORGIAN CAPITAL LETTER JIL;Lu;0;L;;;;;N;;;;2D1B;
-10BC;GEORGIAN CAPITAL LETTER CIL;Lu;0;L;;;;;N;;;;2D1C;
-10BD;GEORGIAN CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;;;2D1D;
-10BE;GEORGIAN CAPITAL LETTER XAN;Lu;0;L;;;;;N;;;;2D1E;
-10BF;GEORGIAN CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;;;2D1F;
-10C0;GEORGIAN CAPITAL LETTER HAE;Lu;0;L;;;;;N;;;;2D20;
-10C1;GEORGIAN CAPITAL LETTER HE;Lu;0;L;;;;;N;;;;2D21;
-10C2;GEORGIAN CAPITAL LETTER HIE;Lu;0;L;;;;;N;;;;2D22;
-10C3;GEORGIAN CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;2D23;
-10C4;GEORGIAN CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;2D24;
-10C5;GEORGIAN CAPITAL LETTER HOE;Lu;0;L;;;;;N;;;;2D25;
-10C7;GEORGIAN CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;2D27;
-10CD;GEORGIAN CAPITAL LETTER AEN;Lu;0;L;;;;;N;;;;2D2D;
-10D0;GEORGIAN LETTER AN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER AN;;;;
-10D1;GEORGIAN LETTER BAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER BAN;;;;
-10D2;GEORGIAN LETTER GAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GAN;;;;
-10D3;GEORGIAN LETTER DON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER DON;;;;
-10D4;GEORGIAN LETTER EN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER EN;;;;
-10D5;GEORGIAN LETTER VIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER VIN;;;;
-10D6;GEORGIAN LETTER ZEN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZEN;;;;
-10D7;GEORGIAN LETTER TAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAN;;;;
-10D8;GEORGIAN LETTER IN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER IN;;;;
-10D9;GEORGIAN LETTER KAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KAN;;;;
-10DA;GEORGIAN LETTER LAS;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER LAS;;;;
-10DB;GEORGIAN LETTER MAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER MAN;;;;
-10DC;GEORGIAN LETTER NAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER NAR;;;;
-10DD;GEORGIAN LETTER ON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ON;;;;
-10DE;GEORGIAN LETTER PAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PAR;;;;
-10DF;GEORGIAN LETTER ZHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZHAR;;;;
-10E0;GEORGIAN LETTER RAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER RAE;;;;
-10E1;GEORGIAN LETTER SAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SAN;;;;
-10E2;GEORGIAN LETTER TAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAR;;;;
-10E3;GEORGIAN LETTER UN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER UN;;;;
-10E4;GEORGIAN LETTER PHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PHAR;;;;
-10E5;GEORGIAN LETTER KHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KHAR;;;;
-10E6;GEORGIAN LETTER GHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GHAN;;;;
-10E7;GEORGIAN LETTER QAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER QAR;;;;
-10E8;GEORGIAN LETTER SHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SHIN;;;;
-10E9;GEORGIAN LETTER CHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHIN;;;;
-10EA;GEORGIAN LETTER CAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CAN;;;;
-10EB;GEORGIAN LETTER JIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JIL;;;;
-10EC;GEORGIAN LETTER CIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CIL;;;;
-10ED;GEORGIAN LETTER CHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHAR;;;;
-10EE;GEORGIAN LETTER XAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER XAN;;;;
-10EF;GEORGIAN LETTER JHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JHAN;;;;
-10F0;GEORGIAN LETTER HAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAE;;;;
-10F1;GEORGIAN LETTER HE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HE;;;;
-10F2;GEORGIAN LETTER HIE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HIE;;;;
-10F3;GEORGIAN LETTER WE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER WE;;;;
-10F4;GEORGIAN LETTER HAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAR;;;;
-10F5;GEORGIAN LETTER HOE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HOE;;;;
-10F6;GEORGIAN LETTER FI;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER FI;;;;
-10F7;GEORGIAN LETTER YN;Lo;0;L;;;;;N;;;;;
-10F8;GEORGIAN LETTER ELIFI;Lo;0;L;;;;;N;;;;;
-10F9;GEORGIAN LETTER TURNED GAN;Lo;0;L;;;;;N;;;;;
-10FA;GEORGIAN LETTER AIN;Lo;0;L;;;;;N;;;;;
-10FB;GEORGIAN PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;;
-10FC;MODIFIER LETTER GEORGIAN NAR;Lm;0;L;<super> 10DC;;;;N;;;;;
-10FD;GEORGIAN LETTER AEN;Lo;0;L;;;;;N;;;;;
-10FE;GEORGIAN LETTER HARD SIGN;Lo;0;L;;;;;N;;;;;
-10FF;GEORGIAN LETTER LABIAL SIGN;Lo;0;L;;;;;N;;;;;
-1100;HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;;
-1101;HANGUL CHOSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
-1102;HANGUL CHOSEONG NIEUN;Lo;0;L;;;;;N;;;;;
-1103;HANGUL CHOSEONG TIKEUT;Lo;0;L;;;;;N;;;;;
-1104;HANGUL CHOSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;;
-1105;HANGUL CHOSEONG RIEUL;Lo;0;L;;;;;N;;;;;
-1106;HANGUL CHOSEONG MIEUM;Lo;0;L;;;;;N;;;;;
-1107;HANGUL CHOSEONG PIEUP;Lo;0;L;;;;;N;;;;;
-1108;HANGUL CHOSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;;
-1109;HANGUL CHOSEONG SIOS;Lo;0;L;;;;;N;;;;;
-110A;HANGUL CHOSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;;
-110B;HANGUL CHOSEONG IEUNG;Lo;0;L;;;;;N;;;;;
-110C;HANGUL CHOSEONG CIEUC;Lo;0;L;;;;;N;;;;;
-110D;HANGUL CHOSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;;
-110E;HANGUL CHOSEONG CHIEUCH;Lo;0;L;;;;;N;;;;;
-110F;HANGUL CHOSEONG KHIEUKH;Lo;0;L;;;;;N;;;;;
-1110;HANGUL CHOSEONG THIEUTH;Lo;0;L;;;;;N;;;;;
-1111;HANGUL CHOSEONG PHIEUPH;Lo;0;L;;;;;N;;;;;
-1112;HANGUL CHOSEONG HIEUH;Lo;0;L;;;;;N;;;;;
-1113;HANGUL CHOSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;;
-1114;HANGUL CHOSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;;
-1115;HANGUL CHOSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;;
-1116;HANGUL CHOSEONG NIEUN-PIEUP;Lo;0;L;;;;;N;;;;;
-1117;HANGUL CHOSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;;
-1118;HANGUL CHOSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;;
-1119;HANGUL CHOSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;;
-111A;HANGUL CHOSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;;
-111B;HANGUL CHOSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;;
-111C;HANGUL CHOSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;;
-111D;HANGUL CHOSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;;
-111E;HANGUL CHOSEONG PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;;
-111F;HANGUL CHOSEONG PIEUP-NIEUN;Lo;0;L;;;;;N;;;;;
-1120;HANGUL CHOSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;;
-1121;HANGUL CHOSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;;
-1122;HANGUL CHOSEONG PIEUP-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
-1123;HANGUL CHOSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
-1124;HANGUL CHOSEONG PIEUP-SIOS-PIEUP;Lo;0;L;;;;;N;;;;;
-1125;HANGUL CHOSEONG PIEUP-SSANGSIOS;Lo;0;L;;;;;N;;;;;
-1126;HANGUL CHOSEONG PIEUP-SIOS-CIEUC;Lo;0;L;;;;;N;;;;;
-1127;HANGUL CHOSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;;
-1128;HANGUL CHOSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;;
-1129;HANGUL CHOSEONG PIEUP-THIEUTH;Lo;0;L;;;;;N;;;;;
-112A;HANGUL CHOSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;;
-112B;HANGUL CHOSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
-112C;HANGUL CHOSEONG KAPYEOUNSSANGPIEUP;Lo;0;L;;;;;N;;;;;
-112D;HANGUL CHOSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
-112E;HANGUL CHOSEONG SIOS-NIEUN;Lo;0;L;;;;;N;;;;;
-112F;HANGUL CHOSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
-1130;HANGUL CHOSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;;
-1131;HANGUL CHOSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;;
-1132;HANGUL CHOSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;;
-1133;HANGUL CHOSEONG SIOS-PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;;
-1134;HANGUL CHOSEONG SIOS-SSANGSIOS;Lo;0;L;;;;;N;;;;;
-1135;HANGUL CHOSEONG SIOS-IEUNG;Lo;0;L;;;;;N;;;;;
-1136;HANGUL CHOSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;;
-1137;HANGUL CHOSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;;
-1138;HANGUL CHOSEONG SIOS-KHIEUKH;Lo;0;L;;;;;N;;;;;
-1139;HANGUL CHOSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;;
-113A;HANGUL CHOSEONG SIOS-PHIEUPH;Lo;0;L;;;;;N;;;;;
-113B;HANGUL CHOSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;;
-113C;HANGUL CHOSEONG CHITUEUMSIOS;Lo;0;L;;;;;N;;;;;
-113D;HANGUL CHOSEONG CHITUEUMSSANGSIOS;Lo;0;L;;;;;N;;;;;
-113E;HANGUL CHOSEONG CEONGCHIEUMSIOS;Lo;0;L;;;;;N;;;;;
-113F;HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS;Lo;0;L;;;;;N;;;;;
-1140;HANGUL CHOSEONG PANSIOS;Lo;0;L;;;;;N;;;;;
-1141;HANGUL CHOSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;;
-1142;HANGUL CHOSEONG IEUNG-TIKEUT;Lo;0;L;;;;;N;;;;;
-1143;HANGUL CHOSEONG IEUNG-MIEUM;Lo;0;L;;;;;N;;;;;
-1144;HANGUL CHOSEONG IEUNG-PIEUP;Lo;0;L;;;;;N;;;;;
-1145;HANGUL CHOSEONG IEUNG-SIOS;Lo;0;L;;;;;N;;;;;
-1146;HANGUL CHOSEONG IEUNG-PANSIOS;Lo;0;L;;;;;N;;;;;
-1147;HANGUL CHOSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;;
-1148;HANGUL CHOSEONG IEUNG-CIEUC;Lo;0;L;;;;;N;;;;;
-1149;HANGUL CHOSEONG IEUNG-CHIEUCH;Lo;0;L;;;;;N;;;;;
-114A;HANGUL CHOSEONG IEUNG-THIEUTH;Lo;0;L;;;;;N;;;;;
-114B;HANGUL CHOSEONG IEUNG-PHIEUPH;Lo;0;L;;;;;N;;;;;
-114C;HANGUL CHOSEONG YESIEUNG;Lo;0;L;;;;;N;;;;;
-114D;HANGUL CHOSEONG CIEUC-IEUNG;Lo;0;L;;;;;N;;;;;
-114E;HANGUL CHOSEONG CHITUEUMCIEUC;Lo;0;L;;;;;N;;;;;
-114F;HANGUL CHOSEONG CHITUEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;;
-1150;HANGUL CHOSEONG CEONGCHIEUMCIEUC;Lo;0;L;;;;;N;;;;;
-1151;HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;;
-1152;HANGUL CHOSEONG CHIEUCH-KHIEUKH;Lo;0;L;;;;;N;;;;;
-1153;HANGUL CHOSEONG CHIEUCH-HIEUH;Lo;0;L;;;;;N;;;;;
-1154;HANGUL CHOSEONG CHITUEUMCHIEUCH;Lo;0;L;;;;;N;;;;;
-1155;HANGUL CHOSEONG CEONGCHIEUMCHIEUCH;Lo;0;L;;;;;N;;;;;
-1156;HANGUL CHOSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;;
-1157;HANGUL CHOSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;;
-1158;HANGUL CHOSEONG SSANGHIEUH;Lo;0;L;;;;;N;;;;;
-1159;HANGUL CHOSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;;
-115A;HANGUL CHOSEONG KIYEOK-TIKEUT;Lo;0;L;;;;;N;;;;;
-115B;HANGUL CHOSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;;
-115C;HANGUL CHOSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;;
-115D;HANGUL CHOSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;;
-115E;HANGUL CHOSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;;
-115F;HANGUL CHOSEONG FILLER;Lo;0;L;;;;;N;;;;;
-1160;HANGUL JUNGSEONG FILLER;Lo;0;L;;;;;N;;;;;
-1161;HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;;
-1162;HANGUL JUNGSEONG AE;Lo;0;L;;;;;N;;;;;
-1163;HANGUL JUNGSEONG YA;Lo;0;L;;;;;N;;;;;
-1164;HANGUL JUNGSEONG YAE;Lo;0;L;;;;;N;;;;;
-1165;HANGUL JUNGSEONG EO;Lo;0;L;;;;;N;;;;;
-1166;HANGUL JUNGSEONG E;Lo;0;L;;;;;N;;;;;
-1167;HANGUL JUNGSEONG YEO;Lo;0;L;;;;;N;;;;;
-1168;HANGUL JUNGSEONG YE;Lo;0;L;;;;;N;;;;;
-1169;HANGUL JUNGSEONG O;Lo;0;L;;;;;N;;;;;
-116A;HANGUL JUNGSEONG WA;Lo;0;L;;;;;N;;;;;
-116B;HANGUL JUNGSEONG WAE;Lo;0;L;;;;;N;;;;;
-116C;HANGUL JUNGSEONG OE;Lo;0;L;;;;;N;;;;;
-116D;HANGUL JUNGSEONG YO;Lo;0;L;;;;;N;;;;;
-116E;HANGUL JUNGSEONG U;Lo;0;L;;;;;N;;;;;
-116F;HANGUL JUNGSEONG WEO;Lo;0;L;;;;;N;;;;;
-1170;HANGUL JUNGSEONG WE;Lo;0;L;;;;;N;;;;;
-1171;HANGUL JUNGSEONG WI;Lo;0;L;;;;;N;;;;;
-1172;HANGUL JUNGSEONG YU;Lo;0;L;;;;;N;;;;;
-1173;HANGUL JUNGSEONG EU;Lo;0;L;;;;;N;;;;;
-1174;HANGUL JUNGSEONG YI;Lo;0;L;;;;;N;;;;;
-1175;HANGUL JUNGSEONG I;Lo;0;L;;;;;N;;;;;
-1176;HANGUL JUNGSEONG A-O;Lo;0;L;;;;;N;;;;;
-1177;HANGUL JUNGSEONG A-U;Lo;0;L;;;;;N;;;;;
-1178;HANGUL JUNGSEONG YA-O;Lo;0;L;;;;;N;;;;;
-1179;HANGUL JUNGSEONG YA-YO;Lo;0;L;;;;;N;;;;;
-117A;HANGUL JUNGSEONG EO-O;Lo;0;L;;;;;N;;;;;
-117B;HANGUL JUNGSEONG EO-U;Lo;0;L;;;;;N;;;;;
-117C;HANGUL JUNGSEONG EO-EU;Lo;0;L;;;;;N;;;;;
-117D;HANGUL JUNGSEONG YEO-O;Lo;0;L;;;;;N;;;;;
-117E;HANGUL JUNGSEONG YEO-U;Lo;0;L;;;;;N;;;;;
-117F;HANGUL JUNGSEONG O-EO;Lo;0;L;;;;;N;;;;;
-1180;HANGUL JUNGSEONG O-E;Lo;0;L;;;;;N;;;;;
-1181;HANGUL JUNGSEONG O-YE;Lo;0;L;;;;;N;;;;;
-1182;HANGUL JUNGSEONG O-O;Lo;0;L;;;;;N;;;;;
-1183;HANGUL JUNGSEONG O-U;Lo;0;L;;;;;N;;;;;
-1184;HANGUL JUNGSEONG YO-YA;Lo;0;L;;;;;N;;;;;
-1185;HANGUL JUNGSEONG YO-YAE;Lo;0;L;;;;;N;;;;;
-1186;HANGUL JUNGSEONG YO-YEO;Lo;0;L;;;;;N;;;;;
-1187;HANGUL JUNGSEONG YO-O;Lo;0;L;;;;;N;;;;;
-1188;HANGUL JUNGSEONG YO-I;Lo;0;L;;;;;N;;;;;
-1189;HANGUL JUNGSEONG U-A;Lo;0;L;;;;;N;;;;;
-118A;HANGUL JUNGSEONG U-AE;Lo;0;L;;;;;N;;;;;
-118B;HANGUL JUNGSEONG U-EO-EU;Lo;0;L;;;;;N;;;;;
-118C;HANGUL JUNGSEONG U-YE;Lo;0;L;;;;;N;;;;;
-118D;HANGUL JUNGSEONG U-U;Lo;0;L;;;;;N;;;;;
-118E;HANGUL JUNGSEONG YU-A;Lo;0;L;;;;;N;;;;;
-118F;HANGUL JUNGSEONG YU-EO;Lo;0;L;;;;;N;;;;;
-1190;HANGUL JUNGSEONG YU-E;Lo;0;L;;;;;N;;;;;
-1191;HANGUL JUNGSEONG YU-YEO;Lo;0;L;;;;;N;;;;;
-1192;HANGUL JUNGSEONG YU-YE;Lo;0;L;;;;;N;;;;;
-1193;HANGUL JUNGSEONG YU-U;Lo;0;L;;;;;N;;;;;
-1194;HANGUL JUNGSEONG YU-I;Lo;0;L;;;;;N;;;;;
-1195;HANGUL JUNGSEONG EU-U;Lo;0;L;;;;;N;;;;;
-1196;HANGUL JUNGSEONG EU-EU;Lo;0;L;;;;;N;;;;;
-1197;HANGUL JUNGSEONG YI-U;Lo;0;L;;;;;N;;;;;
-1198;HANGUL JUNGSEONG I-A;Lo;0;L;;;;;N;;;;;
-1199;HANGUL JUNGSEONG I-YA;Lo;0;L;;;;;N;;;;;
-119A;HANGUL JUNGSEONG I-O;Lo;0;L;;;;;N;;;;;
-119B;HANGUL JUNGSEONG I-U;Lo;0;L;;;;;N;;;;;
-119C;HANGUL JUNGSEONG I-EU;Lo;0;L;;;;;N;;;;;
-119D;HANGUL JUNGSEONG I-ARAEA;Lo;0;L;;;;;N;;;;;
-119E;HANGUL JUNGSEONG ARAEA;Lo;0;L;;;;;N;;;;;
-119F;HANGUL JUNGSEONG ARAEA-EO;Lo;0;L;;;;;N;;;;;
-11A0;HANGUL JUNGSEONG ARAEA-U;Lo;0;L;;;;;N;;;;;
-11A1;HANGUL JUNGSEONG ARAEA-I;Lo;0;L;;;;;N;;;;;
-11A2;HANGUL JUNGSEONG SSANGARAEA;Lo;0;L;;;;;N;;;;;
-11A3;HANGUL JUNGSEONG A-EU;Lo;0;L;;;;;N;;;;;
-11A4;HANGUL JUNGSEONG YA-U;Lo;0;L;;;;;N;;;;;
-11A5;HANGUL JUNGSEONG YEO-YA;Lo;0;L;;;;;N;;;;;
-11A6;HANGUL JUNGSEONG O-YA;Lo;0;L;;;;;N;;;;;
-11A7;HANGUL JUNGSEONG O-YAE;Lo;0;L;;;;;N;;;;;
-11A8;HANGUL JONGSEONG KIYEOK;Lo;0;L;;;;;N;;;;;
-11A9;HANGUL JONGSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
-11AA;HANGUL JONGSEONG KIYEOK-SIOS;Lo;0;L;;;;;N;;;;;
-11AB;HANGUL JONGSEONG NIEUN;Lo;0;L;;;;;N;;;;;
-11AC;HANGUL JONGSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;;
-11AD;HANGUL JONGSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;;
-11AE;HANGUL JONGSEONG TIKEUT;Lo;0;L;;;;;N;;;;;
-11AF;HANGUL JONGSEONG RIEUL;Lo;0;L;;;;;N;;;;;
-11B0;HANGUL JONGSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;;
-11B1;HANGUL JONGSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;;
-11B2;HANGUL JONGSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;;
-11B3;HANGUL JONGSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;;
-11B4;HANGUL JONGSEONG RIEUL-THIEUTH;Lo;0;L;;;;;N;;;;;
-11B5;HANGUL JONGSEONG RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;;
-11B6;HANGUL JONGSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;;
-11B7;HANGUL JONGSEONG MIEUM;Lo;0;L;;;;;N;;;;;
-11B8;HANGUL JONGSEONG PIEUP;Lo;0;L;;;;;N;;;;;
-11B9;HANGUL JONGSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;;
-11BA;HANGUL JONGSEONG SIOS;Lo;0;L;;;;;N;;;;;
-11BB;HANGUL JONGSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;;
-11BC;HANGUL JONGSEONG IEUNG;Lo;0;L;;;;;N;;;;;
-11BD;HANGUL JONGSEONG CIEUC;Lo;0;L;;;;;N;;;;;
-11BE;HANGUL JONGSEONG CHIEUCH;Lo;0;L;;;;;N;;;;;
-11BF;HANGUL JONGSEONG KHIEUKH;Lo;0;L;;;;;N;;;;;
-11C0;HANGUL JONGSEONG THIEUTH;Lo;0;L;;;;;N;;;;;
-11C1;HANGUL JONGSEONG PHIEUPH;Lo;0;L;;;;;N;;;;;
-11C2;HANGUL JONGSEONG HIEUH;Lo;0;L;;;;;N;;;;;
-11C3;HANGUL JONGSEONG KIYEOK-RIEUL;Lo;0;L;;;;;N;;;;;
-11C4;HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
-11C5;HANGUL JONGSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;;
-11C6;HANGUL JONGSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;;
-11C7;HANGUL JONGSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;;
-11C8;HANGUL JONGSEONG NIEUN-PANSIOS;Lo;0;L;;;;;N;;;;;
-11C9;HANGUL JONGSEONG NIEUN-THIEUTH;Lo;0;L;;;;;N;;;;;
-11CA;HANGUL JONGSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;;
-11CB;HANGUL JONGSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;;
-11CC;HANGUL JONGSEONG RIEUL-KIYEOK-SIOS;Lo;0;L;;;;;N;;;;;
-11CD;HANGUL JONGSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;;
-11CE;HANGUL JONGSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;;
-11CF;HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH;Lo;0;L;;;;;N;;;;;
-11D0;HANGUL JONGSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;;
-11D1;HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;;
-11D2;HANGUL JONGSEONG RIEUL-MIEUM-SIOS;Lo;0;L;;;;;N;;;;;
-11D3;HANGUL JONGSEONG RIEUL-PIEUP-SIOS;Lo;0;L;;;;;N;;;;;
-11D4;HANGUL JONGSEONG RIEUL-PIEUP-HIEUH;Lo;0;L;;;;;N;;;;;
-11D5;HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
-11D6;HANGUL JONGSEONG RIEUL-SSANGSIOS;Lo;0;L;;;;;N;;;;;
-11D7;HANGUL JONGSEONG RIEUL-PANSIOS;Lo;0;L;;;;;N;;;;;
-11D8;HANGUL JONGSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;;
-11D9;HANGUL JONGSEONG RIEUL-YEORINHIEUH;Lo;0;L;;;;;N;;;;;
-11DA;HANGUL JONGSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;;
-11DB;HANGUL JONGSEONG MIEUM-RIEUL;Lo;0;L;;;;;N;;;;;
-11DC;HANGUL JONGSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;;
-11DD;HANGUL JONGSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;;
-11DE;HANGUL JONGSEONG MIEUM-SSANGSIOS;Lo;0;L;;;;;N;;;;;
-11DF;HANGUL JONGSEONG MIEUM-PANSIOS;Lo;0;L;;;;;N;;;;;
-11E0;HANGUL JONGSEONG MIEUM-CHIEUCH;Lo;0;L;;;;;N;;;;;
-11E1;HANGUL JONGSEONG MIEUM-HIEUH;Lo;0;L;;;;;N;;;;;
-11E2;HANGUL JONGSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;;
-11E3;HANGUL JONGSEONG PIEUP-RIEUL;Lo;0;L;;;;;N;;;;;
-11E4;HANGUL JONGSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;;
-11E5;HANGUL JONGSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;;
-11E6;HANGUL JONGSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
-11E7;HANGUL JONGSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
-11E8;HANGUL JONGSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
-11E9;HANGUL JONGSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;;
-11EA;HANGUL JONGSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;;
-11EB;HANGUL JONGSEONG PANSIOS;Lo;0;L;;;;;N;;;;;
-11EC;HANGUL JONGSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;;
-11ED;HANGUL JONGSEONG IEUNG-SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
-11EE;HANGUL JONGSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;;
-11EF;HANGUL JONGSEONG IEUNG-KHIEUKH;Lo;0;L;;;;;N;;;;;
-11F0;HANGUL JONGSEONG YESIEUNG;Lo;0;L;;;;;N;;;;;
-11F1;HANGUL JONGSEONG YESIEUNG-SIOS;Lo;0;L;;;;;N;;;;;
-11F2;HANGUL JONGSEONG YESIEUNG-PANSIOS;Lo;0;L;;;;;N;;;;;
-11F3;HANGUL JONGSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;;
-11F4;HANGUL JONGSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;;
-11F5;HANGUL JONGSEONG HIEUH-NIEUN;Lo;0;L;;;;;N;;;;;
-11F6;HANGUL JONGSEONG HIEUH-RIEUL;Lo;0;L;;;;;N;;;;;
-11F7;HANGUL JONGSEONG HIEUH-MIEUM;Lo;0;L;;;;;N;;;;;
-11F8;HANGUL JONGSEONG HIEUH-PIEUP;Lo;0;L;;;;;N;;;;;
-11F9;HANGUL JONGSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;;
-11FA;HANGUL JONGSEONG KIYEOK-NIEUN;Lo;0;L;;;;;N;;;;;
-11FB;HANGUL JONGSEONG KIYEOK-PIEUP;Lo;0;L;;;;;N;;;;;
-11FC;HANGUL JONGSEONG KIYEOK-CHIEUCH;Lo;0;L;;;;;N;;;;;
-11FD;HANGUL JONGSEONG KIYEOK-KHIEUKH;Lo;0;L;;;;;N;;;;;
-11FE;HANGUL JONGSEONG KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;;
-11FF;HANGUL JONGSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;;
-1200;ETHIOPIC SYLLABLE HA;Lo;0;L;;;;;N;;;;;
-1201;ETHIOPIC SYLLABLE HU;Lo;0;L;;;;;N;;;;;
-1202;ETHIOPIC SYLLABLE HI;Lo;0;L;;;;;N;;;;;
-1203;ETHIOPIC SYLLABLE HAA;Lo;0;L;;;;;N;;;;;
-1204;ETHIOPIC SYLLABLE HEE;Lo;0;L;;;;;N;;;;;
-1205;ETHIOPIC SYLLABLE HE;Lo;0;L;;;;;N;;;;;
-1206;ETHIOPIC SYLLABLE HO;Lo;0;L;;;;;N;;;;;
-1207;ETHIOPIC SYLLABLE HOA;Lo;0;L;;;;;N;;;;;
-1208;ETHIOPIC SYLLABLE LA;Lo;0;L;;;;;N;;;;;
-1209;ETHIOPIC SYLLABLE LU;Lo;0;L;;;;;N;;;;;
-120A;ETHIOPIC SYLLABLE LI;Lo;0;L;;;;;N;;;;;
-120B;ETHIOPIC SYLLABLE LAA;Lo;0;L;;;;;N;;;;;
-120C;ETHIOPIC SYLLABLE LEE;Lo;0;L;;;;;N;;;;;
-120D;ETHIOPIC SYLLABLE LE;Lo;0;L;;;;;N;;;;;
-120E;ETHIOPIC SYLLABLE LO;Lo;0;L;;;;;N;;;;;
-120F;ETHIOPIC SYLLABLE LWA;Lo;0;L;;;;;N;;;;;
-1210;ETHIOPIC SYLLABLE HHA;Lo;0;L;;;;;N;;;;;
-1211;ETHIOPIC SYLLABLE HHU;Lo;0;L;;;;;N;;;;;
-1212;ETHIOPIC SYLLABLE HHI;Lo;0;L;;;;;N;;;;;
-1213;ETHIOPIC SYLLABLE HHAA;Lo;0;L;;;;;N;;;;;
-1214;ETHIOPIC SYLLABLE HHEE;Lo;0;L;;;;;N;;;;;
-1215;ETHIOPIC SYLLABLE HHE;Lo;0;L;;;;;N;;;;;
-1216;ETHIOPIC SYLLABLE HHO;Lo;0;L;;;;;N;;;;;
-1217;ETHIOPIC SYLLABLE HHWA;Lo;0;L;;;;;N;;;;;
-1218;ETHIOPIC SYLLABLE MA;Lo;0;L;;;;;N;;;;;
-1219;ETHIOPIC SYLLABLE MU;Lo;0;L;;;;;N;;;;;
-121A;ETHIOPIC SYLLABLE MI;Lo;0;L;;;;;N;;;;;
-121B;ETHIOPIC SYLLABLE MAA;Lo;0;L;;;;;N;;;;;
-121C;ETHIOPIC SYLLABLE MEE;Lo;0;L;;;;;N;;;;;
-121D;ETHIOPIC SYLLABLE ME;Lo;0;L;;;;;N;;;;;
-121E;ETHIOPIC SYLLABLE MO;Lo;0;L;;;;;N;;;;;
-121F;ETHIOPIC SYLLABLE MWA;Lo;0;L;;;;;N;;;;;
-1220;ETHIOPIC SYLLABLE SZA;Lo;0;L;;;;;N;;;;;
-1221;ETHIOPIC SYLLABLE SZU;Lo;0;L;;;;;N;;;;;
-1222;ETHIOPIC SYLLABLE SZI;Lo;0;L;;;;;N;;;;;
-1223;ETHIOPIC SYLLABLE SZAA;Lo;0;L;;;;;N;;;;;
-1224;ETHIOPIC SYLLABLE SZEE;Lo;0;L;;;;;N;;;;;
-1225;ETHIOPIC SYLLABLE SZE;Lo;0;L;;;;;N;;;;;
-1226;ETHIOPIC SYLLABLE SZO;Lo;0;L;;;;;N;;;;;
-1227;ETHIOPIC SYLLABLE SZWA;Lo;0;L;;;;;N;;;;;
-1228;ETHIOPIC SYLLABLE RA;Lo;0;L;;;;;N;;;;;
-1229;ETHIOPIC SYLLABLE RU;Lo;0;L;;;;;N;;;;;
-122A;ETHIOPIC SYLLABLE RI;Lo;0;L;;;;;N;;;;;
-122B;ETHIOPIC SYLLABLE RAA;Lo;0;L;;;;;N;;;;;
-122C;ETHIOPIC SYLLABLE REE;Lo;0;L;;;;;N;;;;;
-122D;ETHIOPIC SYLLABLE RE;Lo;0;L;;;;;N;;;;;
-122E;ETHIOPIC SYLLABLE RO;Lo;0;L;;;;;N;;;;;
-122F;ETHIOPIC SYLLABLE RWA;Lo;0;L;;;;;N;;;;;
-1230;ETHIOPIC SYLLABLE SA;Lo;0;L;;;;;N;;;;;
-1231;ETHIOPIC SYLLABLE SU;Lo;0;L;;;;;N;;;;;
-1232;ETHIOPIC SYLLABLE SI;Lo;0;L;;;;;N;;;;;
-1233;ETHIOPIC SYLLABLE SAA;Lo;0;L;;;;;N;;;;;
-1234;ETHIOPIC SYLLABLE SEE;Lo;0;L;;;;;N;;;;;
-1235;ETHIOPIC SYLLABLE SE;Lo;0;L;;;;;N;;;;;
-1236;ETHIOPIC SYLLABLE SO;Lo;0;L;;;;;N;;;;;
-1237;ETHIOPIC SYLLABLE SWA;Lo;0;L;;;;;N;;;;;
-1238;ETHIOPIC SYLLABLE SHA;Lo;0;L;;;;;N;;;;;
-1239;ETHIOPIC SYLLABLE SHU;Lo;0;L;;;;;N;;;;;
-123A;ETHIOPIC SYLLABLE SHI;Lo;0;L;;;;;N;;;;;
-123B;ETHIOPIC SYLLABLE SHAA;Lo;0;L;;;;;N;;;;;
-123C;ETHIOPIC SYLLABLE SHEE;Lo;0;L;;;;;N;;;;;
-123D;ETHIOPIC SYLLABLE SHE;Lo;0;L;;;;;N;;;;;
-123E;ETHIOPIC SYLLABLE SHO;Lo;0;L;;;;;N;;;;;
-123F;ETHIOPIC SYLLABLE SHWA;Lo;0;L;;;;;N;;;;;
-1240;ETHIOPIC SYLLABLE QA;Lo;0;L;;;;;N;;;;;
-1241;ETHIOPIC SYLLABLE QU;Lo;0;L;;;;;N;;;;;
-1242;ETHIOPIC SYLLABLE QI;Lo;0;L;;;;;N;;;;;
-1243;ETHIOPIC SYLLABLE QAA;Lo;0;L;;;;;N;;;;;
-1244;ETHIOPIC SYLLABLE QEE;Lo;0;L;;;;;N;;;;;
-1245;ETHIOPIC SYLLABLE QE;Lo;0;L;;;;;N;;;;;
-1246;ETHIOPIC SYLLABLE QO;Lo;0;L;;;;;N;;;;;
-1247;ETHIOPIC SYLLABLE QOA;Lo;0;L;;;;;N;;;;;
-1248;ETHIOPIC SYLLABLE QWA;Lo;0;L;;;;;N;;;;;
-124A;ETHIOPIC SYLLABLE QWI;Lo;0;L;;;;;N;;;;;
-124B;ETHIOPIC SYLLABLE QWAA;Lo;0;L;;;;;N;;;;;
-124C;ETHIOPIC SYLLABLE QWEE;Lo;0;L;;;;;N;;;;;
-124D;ETHIOPIC SYLLABLE QWE;Lo;0;L;;;;;N;;;;;
-1250;ETHIOPIC SYLLABLE QHA;Lo;0;L;;;;;N;;;;;
-1251;ETHIOPIC SYLLABLE QHU;Lo;0;L;;;;;N;;;;;
-1252;ETHIOPIC SYLLABLE QHI;Lo;0;L;;;;;N;;;;;
-1253;ETHIOPIC SYLLABLE QHAA;Lo;0;L;;;;;N;;;;;
-1254;ETHIOPIC SYLLABLE QHEE;Lo;0;L;;;;;N;;;;;
-1255;ETHIOPIC SYLLABLE QHE;Lo;0;L;;;;;N;;;;;
-1256;ETHIOPIC SYLLABLE QHO;Lo;0;L;;;;;N;;;;;
-1258;ETHIOPIC SYLLABLE QHWA;Lo;0;L;;;;;N;;;;;
-125A;ETHIOPIC SYLLABLE QHWI;Lo;0;L;;;;;N;;;;;
-125B;ETHIOPIC SYLLABLE QHWAA;Lo;0;L;;;;;N;;;;;
-125C;ETHIOPIC SYLLABLE QHWEE;Lo;0;L;;;;;N;;;;;
-125D;ETHIOPIC SYLLABLE QHWE;Lo;0;L;;;;;N;;;;;
-1260;ETHIOPIC SYLLABLE BA;Lo;0;L;;;;;N;;;;;
-1261;ETHIOPIC SYLLABLE BU;Lo;0;L;;;;;N;;;;;
-1262;ETHIOPIC SYLLABLE BI;Lo;0;L;;;;;N;;;;;
-1263;ETHIOPIC SYLLABLE BAA;Lo;0;L;;;;;N;;;;;
-1264;ETHIOPIC SYLLABLE BEE;Lo;0;L;;;;;N;;;;;
-1265;ETHIOPIC SYLLABLE BE;Lo;0;L;;;;;N;;;;;
-1266;ETHIOPIC SYLLABLE BO;Lo;0;L;;;;;N;;;;;
-1267;ETHIOPIC SYLLABLE BWA;Lo;0;L;;;;;N;;;;;
-1268;ETHIOPIC SYLLABLE VA;Lo;0;L;;;;;N;;;;;
-1269;ETHIOPIC SYLLABLE VU;Lo;0;L;;;;;N;;;;;
-126A;ETHIOPIC SYLLABLE VI;Lo;0;L;;;;;N;;;;;
-126B;ETHIOPIC SYLLABLE VAA;Lo;0;L;;;;;N;;;;;
-126C;ETHIOPIC SYLLABLE VEE;Lo;0;L;;;;;N;;;;;
-126D;ETHIOPIC SYLLABLE VE;Lo;0;L;;;;;N;;;;;
-126E;ETHIOPIC SYLLABLE VO;Lo;0;L;;;;;N;;;;;
-126F;ETHIOPIC SYLLABLE VWA;Lo;0;L;;;;;N;;;;;
-1270;ETHIOPIC SYLLABLE TA;Lo;0;L;;;;;N;;;;;
-1271;ETHIOPIC SYLLABLE TU;Lo;0;L;;;;;N;;;;;
-1272;ETHIOPIC SYLLABLE TI;Lo;0;L;;;;;N;;;;;
-1273;ETHIOPIC SYLLABLE TAA;Lo;0;L;;;;;N;;;;;
-1274;ETHIOPIC SYLLABLE TEE;Lo;0;L;;;;;N;;;;;
-1275;ETHIOPIC SYLLABLE TE;Lo;0;L;;;;;N;;;;;
-1276;ETHIOPIC SYLLABLE TO;Lo;0;L;;;;;N;;;;;
-1277;ETHIOPIC SYLLABLE TWA;Lo;0;L;;;;;N;;;;;
-1278;ETHIOPIC SYLLABLE CA;Lo;0;L;;;;;N;;;;;
-1279;ETHIOPIC SYLLABLE CU;Lo;0;L;;;;;N;;;;;
-127A;ETHIOPIC SYLLABLE CI;Lo;0;L;;;;;N;;;;;
-127B;ETHIOPIC SYLLABLE CAA;Lo;0;L;;;;;N;;;;;
-127C;ETHIOPIC SYLLABLE CEE;Lo;0;L;;;;;N;;;;;
-127D;ETHIOPIC SYLLABLE CE;Lo;0;L;;;;;N;;;;;
-127E;ETHIOPIC SYLLABLE CO;Lo;0;L;;;;;N;;;;;
-127F;ETHIOPIC SYLLABLE CWA;Lo;0;L;;;;;N;;;;;
-1280;ETHIOPIC SYLLABLE XA;Lo;0;L;;;;;N;;;;;
-1281;ETHIOPIC SYLLABLE XU;Lo;0;L;;;;;N;;;;;
-1282;ETHIOPIC SYLLABLE XI;Lo;0;L;;;;;N;;;;;
-1283;ETHIOPIC SYLLABLE XAA;Lo;0;L;;;;;N;;;;;
-1284;ETHIOPIC SYLLABLE XEE;Lo;0;L;;;;;N;;;;;
-1285;ETHIOPIC SYLLABLE XE;Lo;0;L;;;;;N;;;;;
-1286;ETHIOPIC SYLLABLE XO;Lo;0;L;;;;;N;;;;;
-1287;ETHIOPIC SYLLABLE XOA;Lo;0;L;;;;;N;;;;;
-1288;ETHIOPIC SYLLABLE XWA;Lo;0;L;;;;;N;;;;;
-128A;ETHIOPIC SYLLABLE XWI;Lo;0;L;;;;;N;;;;;
-128B;ETHIOPIC SYLLABLE XWAA;Lo;0;L;;;;;N;;;;;
-128C;ETHIOPIC SYLLABLE XWEE;Lo;0;L;;;;;N;;;;;
-128D;ETHIOPIC SYLLABLE XWE;Lo;0;L;;;;;N;;;;;
-1290;ETHIOPIC SYLLABLE NA;Lo;0;L;;;;;N;;;;;
-1291;ETHIOPIC SYLLABLE NU;Lo;0;L;;;;;N;;;;;
-1292;ETHIOPIC SYLLABLE NI;Lo;0;L;;;;;N;;;;;
-1293;ETHIOPIC SYLLABLE NAA;Lo;0;L;;;;;N;;;;;
-1294;ETHIOPIC SYLLABLE NEE;Lo;0;L;;;;;N;;;;;
-1295;ETHIOPIC SYLLABLE NE;Lo;0;L;;;;;N;;;;;
-1296;ETHIOPIC SYLLABLE NO;Lo;0;L;;;;;N;;;;;
-1297;ETHIOPIC SYLLABLE NWA;Lo;0;L;;;;;N;;;;;
-1298;ETHIOPIC SYLLABLE NYA;Lo;0;L;;;;;N;;;;;
-1299;ETHIOPIC SYLLABLE NYU;Lo;0;L;;;;;N;;;;;
-129A;ETHIOPIC SYLLABLE NYI;Lo;0;L;;;;;N;;;;;
-129B;ETHIOPIC SYLLABLE NYAA;Lo;0;L;;;;;N;;;;;
-129C;ETHIOPIC SYLLABLE NYEE;Lo;0;L;;;;;N;;;;;
-129D;ETHIOPIC SYLLABLE NYE;Lo;0;L;;;;;N;;;;;
-129E;ETHIOPIC SYLLABLE NYO;Lo;0;L;;;;;N;;;;;
-129F;ETHIOPIC SYLLABLE NYWA;Lo;0;L;;;;;N;;;;;
-12A0;ETHIOPIC SYLLABLE GLOTTAL A;Lo;0;L;;;;;N;;;;;
-12A1;ETHIOPIC SYLLABLE GLOTTAL U;Lo;0;L;;;;;N;;;;;
-12A2;ETHIOPIC SYLLABLE GLOTTAL I;Lo;0;L;;;;;N;;;;;
-12A3;ETHIOPIC SYLLABLE GLOTTAL AA;Lo;0;L;;;;;N;;;;;
-12A4;ETHIOPIC SYLLABLE GLOTTAL EE;Lo;0;L;;;;;N;;;;;
-12A5;ETHIOPIC SYLLABLE GLOTTAL E;Lo;0;L;;;;;N;;;;;
-12A6;ETHIOPIC SYLLABLE GLOTTAL O;Lo;0;L;;;;;N;;;;;
-12A7;ETHIOPIC SYLLABLE GLOTTAL WA;Lo;0;L;;;;;N;;;;;
-12A8;ETHIOPIC SYLLABLE KA;Lo;0;L;;;;;N;;;;;
-12A9;ETHIOPIC SYLLABLE KU;Lo;0;L;;;;;N;;;;;
-12AA;ETHIOPIC SYLLABLE KI;Lo;0;L;;;;;N;;;;;
-12AB;ETHIOPIC SYLLABLE KAA;Lo;0;L;;;;;N;;;;;
-12AC;ETHIOPIC SYLLABLE KEE;Lo;0;L;;;;;N;;;;;
-12AD;ETHIOPIC SYLLABLE KE;Lo;0;L;;;;;N;;;;;
-12AE;ETHIOPIC SYLLABLE KO;Lo;0;L;;;;;N;;;;;
-12AF;ETHIOPIC SYLLABLE KOA;Lo;0;L;;;;;N;;;;;
-12B0;ETHIOPIC SYLLABLE KWA;Lo;0;L;;;;;N;;;;;
-12B2;ETHIOPIC SYLLABLE KWI;Lo;0;L;;;;;N;;;;;
-12B3;ETHIOPIC SYLLABLE KWAA;Lo;0;L;;;;;N;;;;;
-12B4;ETHIOPIC SYLLABLE KWEE;Lo;0;L;;;;;N;;;;;
-12B5;ETHIOPIC SYLLABLE KWE;Lo;0;L;;;;;N;;;;;
-12B8;ETHIOPIC SYLLABLE KXA;Lo;0;L;;;;;N;;;;;
-12B9;ETHIOPIC SYLLABLE KXU;Lo;0;L;;;;;N;;;;;
-12BA;ETHIOPIC SYLLABLE KXI;Lo;0;L;;;;;N;;;;;
-12BB;ETHIOPIC SYLLABLE KXAA;Lo;0;L;;;;;N;;;;;
-12BC;ETHIOPIC SYLLABLE KXEE;Lo;0;L;;;;;N;;;;;
-12BD;ETHIOPIC SYLLABLE KXE;Lo;0;L;;;;;N;;;;;
-12BE;ETHIOPIC SYLLABLE KXO;Lo;0;L;;;;;N;;;;;
-12C0;ETHIOPIC SYLLABLE KXWA;Lo;0;L;;;;;N;;;;;
-12C2;ETHIOPIC SYLLABLE KXWI;Lo;0;L;;;;;N;;;;;
-12C3;ETHIOPIC SYLLABLE KXWAA;Lo;0;L;;;;;N;;;;;
-12C4;ETHIOPIC SYLLABLE KXWEE;Lo;0;L;;;;;N;;;;;
-12C5;ETHIOPIC SYLLABLE KXWE;Lo;0;L;;;;;N;;;;;
-12C8;ETHIOPIC SYLLABLE WA;Lo;0;L;;;;;N;;;;;
-12C9;ETHIOPIC SYLLABLE WU;Lo;0;L;;;;;N;;;;;
-12CA;ETHIOPIC SYLLABLE WI;Lo;0;L;;;;;N;;;;;
-12CB;ETHIOPIC SYLLABLE WAA;Lo;0;L;;;;;N;;;;;
-12CC;ETHIOPIC SYLLABLE WEE;Lo;0;L;;;;;N;;;;;
-12CD;ETHIOPIC SYLLABLE WE;Lo;0;L;;;;;N;;;;;
-12CE;ETHIOPIC SYLLABLE WO;Lo;0;L;;;;;N;;;;;
-12CF;ETHIOPIC SYLLABLE WOA;Lo;0;L;;;;;N;;;;;
-12D0;ETHIOPIC SYLLABLE PHARYNGEAL A;Lo;0;L;;;;;N;;;;;
-12D1;ETHIOPIC SYLLABLE PHARYNGEAL U;Lo;0;L;;;;;N;;;;;
-12D2;ETHIOPIC SYLLABLE PHARYNGEAL I;Lo;0;L;;;;;N;;;;;
-12D3;ETHIOPIC SYLLABLE PHARYNGEAL AA;Lo;0;L;;;;;N;;;;;
-12D4;ETHIOPIC SYLLABLE PHARYNGEAL EE;Lo;0;L;;;;;N;;;;;
-12D5;ETHIOPIC SYLLABLE PHARYNGEAL E;Lo;0;L;;;;;N;;;;;
-12D6;ETHIOPIC SYLLABLE PHARYNGEAL O;Lo;0;L;;;;;N;;;;;
-12D8;ETHIOPIC SYLLABLE ZA;Lo;0;L;;;;;N;;;;;
-12D9;ETHIOPIC SYLLABLE ZU;Lo;0;L;;;;;N;;;;;
-12DA;ETHIOPIC SYLLABLE ZI;Lo;0;L;;;;;N;;;;;
-12DB;ETHIOPIC SYLLABLE ZAA;Lo;0;L;;;;;N;;;;;
-12DC;ETHIOPIC SYLLABLE ZEE;Lo;0;L;;;;;N;;;;;
-12DD;ETHIOPIC SYLLABLE ZE;Lo;0;L;;;;;N;;;;;
-12DE;ETHIOPIC SYLLABLE ZO;Lo;0;L;;;;;N;;;;;
-12DF;ETHIOPIC SYLLABLE ZWA;Lo;0;L;;;;;N;;;;;
-12E0;ETHIOPIC SYLLABLE ZHA;Lo;0;L;;;;;N;;;;;
-12E1;ETHIOPIC SYLLABLE ZHU;Lo;0;L;;;;;N;;;;;
-12E2;ETHIOPIC SYLLABLE ZHI;Lo;0;L;;;;;N;;;;;
-12E3;ETHIOPIC SYLLABLE ZHAA;Lo;0;L;;;;;N;;;;;
-12E4;ETHIOPIC SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;;
-12E5;ETHIOPIC SYLLABLE ZHE;Lo;0;L;;;;;N;;;;;
-12E6;ETHIOPIC SYLLABLE ZHO;Lo;0;L;;;;;N;;;;;
-12E7;ETHIOPIC SYLLABLE ZHWA;Lo;0;L;;;;;N;;;;;
-12E8;ETHIOPIC SYLLABLE YA;Lo;0;L;;;;;N;;;;;
-12E9;ETHIOPIC SYLLABLE YU;Lo;0;L;;;;;N;;;;;
-12EA;ETHIOPIC SYLLABLE YI;Lo;0;L;;;;;N;;;;;
-12EB;ETHIOPIC SYLLABLE YAA;Lo;0;L;;;;;N;;;;;
-12EC;ETHIOPIC SYLLABLE YEE;Lo;0;L;;;;;N;;;;;
-12ED;ETHIOPIC SYLLABLE YE;Lo;0;L;;;;;N;;;;;
-12EE;ETHIOPIC SYLLABLE YO;Lo;0;L;;;;;N;;;;;
-12EF;ETHIOPIC SYLLABLE YOA;Lo;0;L;;;;;N;;;;;
-12F0;ETHIOPIC SYLLABLE DA;Lo;0;L;;;;;N;;;;;
-12F1;ETHIOPIC SYLLABLE DU;Lo;0;L;;;;;N;;;;;
-12F2;ETHIOPIC SYLLABLE DI;Lo;0;L;;;;;N;;;;;
-12F3;ETHIOPIC SYLLABLE DAA;Lo;0;L;;;;;N;;;;;
-12F4;ETHIOPIC SYLLABLE DEE;Lo;0;L;;;;;N;;;;;
-12F5;ETHIOPIC SYLLABLE DE;Lo;0;L;;;;;N;;;;;
-12F6;ETHIOPIC SYLLABLE DO;Lo;0;L;;;;;N;;;;;
-12F7;ETHIOPIC SYLLABLE DWA;Lo;0;L;;;;;N;;;;;
-12F8;ETHIOPIC SYLLABLE DDA;Lo;0;L;;;;;N;;;;;
-12F9;ETHIOPIC SYLLABLE DDU;Lo;0;L;;;;;N;;;;;
-12FA;ETHIOPIC SYLLABLE DDI;Lo;0;L;;;;;N;;;;;
-12FB;ETHIOPIC SYLLABLE DDAA;Lo;0;L;;;;;N;;;;;
-12FC;ETHIOPIC SYLLABLE DDEE;Lo;0;L;;;;;N;;;;;
-12FD;ETHIOPIC SYLLABLE DDE;Lo;0;L;;;;;N;;;;;
-12FE;ETHIOPIC SYLLABLE DDO;Lo;0;L;;;;;N;;;;;
-12FF;ETHIOPIC SYLLABLE DDWA;Lo;0;L;;;;;N;;;;;
-1300;ETHIOPIC SYLLABLE JA;Lo;0;L;;;;;N;;;;;
-1301;ETHIOPIC SYLLABLE JU;Lo;0;L;;;;;N;;;;;
-1302;ETHIOPIC SYLLABLE JI;Lo;0;L;;;;;N;;;;;
-1303;ETHIOPIC SYLLABLE JAA;Lo;0;L;;;;;N;;;;;
-1304;ETHIOPIC SYLLABLE JEE;Lo;0;L;;;;;N;;;;;
-1305;ETHIOPIC SYLLABLE JE;Lo;0;L;;;;;N;;;;;
-1306;ETHIOPIC SYLLABLE JO;Lo;0;L;;;;;N;;;;;
-1307;ETHIOPIC SYLLABLE JWA;Lo;0;L;;;;;N;;;;;
-1308;ETHIOPIC SYLLABLE GA;Lo;0;L;;;;;N;;;;;
-1309;ETHIOPIC SYLLABLE GU;Lo;0;L;;;;;N;;;;;
-130A;ETHIOPIC SYLLABLE GI;Lo;0;L;;;;;N;;;;;
-130B;ETHIOPIC SYLLABLE GAA;Lo;0;L;;;;;N;;;;;
-130C;ETHIOPIC SYLLABLE GEE;Lo;0;L;;;;;N;;;;;
-130D;ETHIOPIC SYLLABLE GE;Lo;0;L;;;;;N;;;;;
-130E;ETHIOPIC SYLLABLE GO;Lo;0;L;;;;;N;;;;;
-130F;ETHIOPIC SYLLABLE GOA;Lo;0;L;;;;;N;;;;;
-1310;ETHIOPIC SYLLABLE GWA;Lo;0;L;;;;;N;;;;;
-1312;ETHIOPIC SYLLABLE GWI;Lo;0;L;;;;;N;;;;;
-1313;ETHIOPIC SYLLABLE GWAA;Lo;0;L;;;;;N;;;;;
-1314;ETHIOPIC SYLLABLE GWEE;Lo;0;L;;;;;N;;;;;
-1315;ETHIOPIC SYLLABLE GWE;Lo;0;L;;;;;N;;;;;
-1318;ETHIOPIC SYLLABLE GGA;Lo;0;L;;;;;N;;;;;
-1319;ETHIOPIC SYLLABLE GGU;Lo;0;L;;;;;N;;;;;
-131A;ETHIOPIC SYLLABLE GGI;Lo;0;L;;;;;N;;;;;
-131B;ETHIOPIC SYLLABLE GGAA;Lo;0;L;;;;;N;;;;;
-131C;ETHIOPIC SYLLABLE GGEE;Lo;0;L;;;;;N;;;;;
-131D;ETHIOPIC SYLLABLE GGE;Lo;0;L;;;;;N;;;;;
-131E;ETHIOPIC SYLLABLE GGO;Lo;0;L;;;;;N;;;;;
-131F;ETHIOPIC SYLLABLE GGWAA;Lo;0;L;;;;;N;;;;;
-1320;ETHIOPIC SYLLABLE THA;Lo;0;L;;;;;N;;;;;
-1321;ETHIOPIC SYLLABLE THU;Lo;0;L;;;;;N;;;;;
-1322;ETHIOPIC SYLLABLE THI;Lo;0;L;;;;;N;;;;;
-1323;ETHIOPIC SYLLABLE THAA;Lo;0;L;;;;;N;;;;;
-1324;ETHIOPIC SYLLABLE THEE;Lo;0;L;;;;;N;;;;;
-1325;ETHIOPIC SYLLABLE THE;Lo;0;L;;;;;N;;;;;
-1326;ETHIOPIC SYLLABLE THO;Lo;0;L;;;;;N;;;;;
-1327;ETHIOPIC SYLLABLE THWA;Lo;0;L;;;;;N;;;;;
-1328;ETHIOPIC SYLLABLE CHA;Lo;0;L;;;;;N;;;;;
-1329;ETHIOPIC SYLLABLE CHU;Lo;0;L;;;;;N;;;;;
-132A;ETHIOPIC SYLLABLE CHI;Lo;0;L;;;;;N;;;;;
-132B;ETHIOPIC SYLLABLE CHAA;Lo;0;L;;;;;N;;;;;
-132C;ETHIOPIC SYLLABLE CHEE;Lo;0;L;;;;;N;;;;;
-132D;ETHIOPIC SYLLABLE CHE;Lo;0;L;;;;;N;;;;;
-132E;ETHIOPIC SYLLABLE CHO;Lo;0;L;;;;;N;;;;;
-132F;ETHIOPIC SYLLABLE CHWA;Lo;0;L;;;;;N;;;;;
-1330;ETHIOPIC SYLLABLE PHA;Lo;0;L;;;;;N;;;;;
-1331;ETHIOPIC SYLLABLE PHU;Lo;0;L;;;;;N;;;;;
-1332;ETHIOPIC SYLLABLE PHI;Lo;0;L;;;;;N;;;;;
-1333;ETHIOPIC SYLLABLE PHAA;Lo;0;L;;;;;N;;;;;
-1334;ETHIOPIC SYLLABLE PHEE;Lo;0;L;;;;;N;;;;;
-1335;ETHIOPIC SYLLABLE PHE;Lo;0;L;;;;;N;;;;;
-1336;ETHIOPIC SYLLABLE PHO;Lo;0;L;;;;;N;;;;;
-1337;ETHIOPIC SYLLABLE PHWA;Lo;0;L;;;;;N;;;;;
-1338;ETHIOPIC SYLLABLE TSA;Lo;0;L;;;;;N;;;;;
-1339;ETHIOPIC SYLLABLE TSU;Lo;0;L;;;;;N;;;;;
-133A;ETHIOPIC SYLLABLE TSI;Lo;0;L;;;;;N;;;;;
-133B;ETHIOPIC SYLLABLE TSAA;Lo;0;L;;;;;N;;;;;
-133C;ETHIOPIC SYLLABLE TSEE;Lo;0;L;;;;;N;;;;;
-133D;ETHIOPIC SYLLABLE TSE;Lo;0;L;;;;;N;;;;;
-133E;ETHIOPIC SYLLABLE TSO;Lo;0;L;;;;;N;;;;;
-133F;ETHIOPIC SYLLABLE TSWA;Lo;0;L;;;;;N;;;;;
-1340;ETHIOPIC SYLLABLE TZA;Lo;0;L;;;;;N;;;;;
-1341;ETHIOPIC SYLLABLE TZU;Lo;0;L;;;;;N;;;;;
-1342;ETHIOPIC SYLLABLE TZI;Lo;0;L;;;;;N;;;;;
-1343;ETHIOPIC SYLLABLE TZAA;Lo;0;L;;;;;N;;;;;
-1344;ETHIOPIC SYLLABLE TZEE;Lo;0;L;;;;;N;;;;;
-1345;ETHIOPIC SYLLABLE TZE;Lo;0;L;;;;;N;;;;;
-1346;ETHIOPIC SYLLABLE TZO;Lo;0;L;;;;;N;;;;;
-1347;ETHIOPIC SYLLABLE TZOA;Lo;0;L;;;;;N;;;;;
-1348;ETHIOPIC SYLLABLE FA;Lo;0;L;;;;;N;;;;;
-1349;ETHIOPIC SYLLABLE FU;Lo;0;L;;;;;N;;;;;
-134A;ETHIOPIC SYLLABLE FI;Lo;0;L;;;;;N;;;;;
-134B;ETHIOPIC SYLLABLE FAA;Lo;0;L;;;;;N;;;;;
-134C;ETHIOPIC SYLLABLE FEE;Lo;0;L;;;;;N;;;;;
-134D;ETHIOPIC SYLLABLE FE;Lo;0;L;;;;;N;;;;;
-134E;ETHIOPIC SYLLABLE FO;Lo;0;L;;;;;N;;;;;
-134F;ETHIOPIC SYLLABLE FWA;Lo;0;L;;;;;N;;;;;
-1350;ETHIOPIC SYLLABLE PA;Lo;0;L;;;;;N;;;;;
-1351;ETHIOPIC SYLLABLE PU;Lo;0;L;;;;;N;;;;;
-1352;ETHIOPIC SYLLABLE PI;Lo;0;L;;;;;N;;;;;
-1353;ETHIOPIC SYLLABLE PAA;Lo;0;L;;;;;N;;;;;
-1354;ETHIOPIC SYLLABLE PEE;Lo;0;L;;;;;N;;;;;
-1355;ETHIOPIC SYLLABLE PE;Lo;0;L;;;;;N;;;;;
-1356;ETHIOPIC SYLLABLE PO;Lo;0;L;;;;;N;;;;;
-1357;ETHIOPIC SYLLABLE PWA;Lo;0;L;;;;;N;;;;;
-1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;;
-1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;;
-135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;;
-135D;ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;;
-135E;ETHIOPIC COMBINING VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;;
-135F;ETHIOPIC COMBINING GEMINATION MARK;Mn;230;NSM;;;;;N;;;;;
-1360;ETHIOPIC SECTION MARK;Po;0;L;;;;;N;;;;;
-1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;;
-1362;ETHIOPIC FULL STOP;Po;0;L;;;;;N;;;;;
-1363;ETHIOPIC COMMA;Po;0;L;;;;;N;;;;;
-1364;ETHIOPIC SEMICOLON;Po;0;L;;;;;N;;;;;
-1365;ETHIOPIC COLON;Po;0;L;;;;;N;;;;;
-1366;ETHIOPIC PREFACE COLON;Po;0;L;;;;;N;;;;;
-1367;ETHIOPIC QUESTION MARK;Po;0;L;;;;;N;;;;;
-1368;ETHIOPIC PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;;
-1369;ETHIOPIC DIGIT ONE;No;0;L;;;1;1;N;;;;;
-136A;ETHIOPIC DIGIT TWO;No;0;L;;;2;2;N;;;;;
-136B;ETHIOPIC DIGIT THREE;No;0;L;;;3;3;N;;;;;
-136C;ETHIOPIC DIGIT FOUR;No;0;L;;;4;4;N;;;;;
-136D;ETHIOPIC DIGIT FIVE;No;0;L;;;5;5;N;;;;;
-136E;ETHIOPIC DIGIT SIX;No;0;L;;;6;6;N;;;;;
-136F;ETHIOPIC DIGIT SEVEN;No;0;L;;;7;7;N;;;;;
-1370;ETHIOPIC DIGIT EIGHT;No;0;L;;;8;8;N;;;;;
-1371;ETHIOPIC DIGIT NINE;No;0;L;;;9;9;N;;;;;
-1372;ETHIOPIC NUMBER TEN;No;0;L;;;;10;N;;;;;
-1373;ETHIOPIC NUMBER TWENTY;No;0;L;;;;20;N;;;;;
-1374;ETHIOPIC NUMBER THIRTY;No;0;L;;;;30;N;;;;;
-1375;ETHIOPIC NUMBER FORTY;No;0;L;;;;40;N;;;;;
-1376;ETHIOPIC NUMBER FIFTY;No;0;L;;;;50;N;;;;;
-1377;ETHIOPIC NUMBER SIXTY;No;0;L;;;;60;N;;;;;
-1378;ETHIOPIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;;
-1379;ETHIOPIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;;
-137A;ETHIOPIC NUMBER NINETY;No;0;L;;;;90;N;;;;;
-137B;ETHIOPIC NUMBER HUNDRED;No;0;L;;;;100;N;;;;;
-137C;ETHIOPIC NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;;
-1380;ETHIOPIC SYLLABLE SEBATBEIT MWA;Lo;0;L;;;;;N;;;;;
-1381;ETHIOPIC SYLLABLE MWI;Lo;0;L;;;;;N;;;;;
-1382;ETHIOPIC SYLLABLE MWEE;Lo;0;L;;;;;N;;;;;
-1383;ETHIOPIC SYLLABLE MWE;Lo;0;L;;;;;N;;;;;
-1384;ETHIOPIC SYLLABLE SEBATBEIT BWA;Lo;0;L;;;;;N;;;;;
-1385;ETHIOPIC SYLLABLE BWI;Lo;0;L;;;;;N;;;;;
-1386;ETHIOPIC SYLLABLE BWEE;Lo;0;L;;;;;N;;;;;
-1387;ETHIOPIC SYLLABLE BWE;Lo;0;L;;;;;N;;;;;
-1388;ETHIOPIC SYLLABLE SEBATBEIT FWA;Lo;0;L;;;;;N;;;;;
-1389;ETHIOPIC SYLLABLE FWI;Lo;0;L;;;;;N;;;;;
-138A;ETHIOPIC SYLLABLE FWEE;Lo;0;L;;;;;N;;;;;
-138B;ETHIOPIC SYLLABLE FWE;Lo;0;L;;;;;N;;;;;
-138C;ETHIOPIC SYLLABLE SEBATBEIT PWA;Lo;0;L;;;;;N;;;;;
-138D;ETHIOPIC SYLLABLE PWI;Lo;0;L;;;;;N;;;;;
-138E;ETHIOPIC SYLLABLE PWEE;Lo;0;L;;;;;N;;;;;
-138F;ETHIOPIC SYLLABLE PWE;Lo;0;L;;;;;N;;;;;
-1390;ETHIOPIC TONAL MARK YIZET;So;0;ON;;;;;N;;;;;
-1391;ETHIOPIC TONAL MARK DERET;So;0;ON;;;;;N;;;;;
-1392;ETHIOPIC TONAL MARK RIKRIK;So;0;ON;;;;;N;;;;;
-1393;ETHIOPIC TONAL MARK SHORT RIKRIK;So;0;ON;;;;;N;;;;;
-1394;ETHIOPIC TONAL MARK DIFAT;So;0;ON;;;;;N;;;;;
-1395;ETHIOPIC TONAL MARK KENAT;So;0;ON;;;;;N;;;;;
-1396;ETHIOPIC TONAL MARK CHIRET;So;0;ON;;;;;N;;;;;
-1397;ETHIOPIC TONAL MARK HIDET;So;0;ON;;;;;N;;;;;
-1398;ETHIOPIC TONAL MARK DERET-HIDET;So;0;ON;;;;;N;;;;;
-1399;ETHIOPIC TONAL MARK KURT;So;0;ON;;;;;N;;;;;
-13A0;CHEROKEE LETTER A;Lo;0;L;;;;;N;;;;;
-13A1;CHEROKEE LETTER E;Lo;0;L;;;;;N;;;;;
-13A2;CHEROKEE LETTER I;Lo;0;L;;;;;N;;;;;
-13A3;CHEROKEE LETTER O;Lo;0;L;;;;;N;;;;;
-13A4;CHEROKEE LETTER U;Lo;0;L;;;;;N;;;;;
-13A5;CHEROKEE LETTER V;Lo;0;L;;;;;N;;;;;
-13A6;CHEROKEE LETTER GA;Lo;0;L;;;;;N;;;;;
-13A7;CHEROKEE LETTER KA;Lo;0;L;;;;;N;;;;;
-13A8;CHEROKEE LETTER GE;Lo;0;L;;;;;N;;;;;
-13A9;CHEROKEE LETTER GI;Lo;0;L;;;;;N;;;;;
-13AA;CHEROKEE LETTER GO;Lo;0;L;;;;;N;;;;;
-13AB;CHEROKEE LETTER GU;Lo;0;L;;;;;N;;;;;
-13AC;CHEROKEE LETTER GV;Lo;0;L;;;;;N;;;;;
-13AD;CHEROKEE LETTER HA;Lo;0;L;;;;;N;;;;;
-13AE;CHEROKEE LETTER HE;Lo;0;L;;;;;N;;;;;
-13AF;CHEROKEE LETTER HI;Lo;0;L;;;;;N;;;;;
-13B0;CHEROKEE LETTER HO;Lo;0;L;;;;;N;;;;;
-13B1;CHEROKEE LETTER HU;Lo;0;L;;;;;N;;;;;
-13B2;CHEROKEE LETTER HV;Lo;0;L;;;;;N;;;;;
-13B3;CHEROKEE LETTER LA;Lo;0;L;;;;;N;;;;;
-13B4;CHEROKEE LETTER LE;Lo;0;L;;;;;N;;;;;
-13B5;CHEROKEE LETTER LI;Lo;0;L;;;;;N;;;;;
-13B6;CHEROKEE LETTER LO;Lo;0;L;;;;;N;;;;;
-13B7;CHEROKEE LETTER LU;Lo;0;L;;;;;N;;;;;
-13B8;CHEROKEE LETTER LV;Lo;0;L;;;;;N;;;;;
-13B9;CHEROKEE LETTER MA;Lo;0;L;;;;;N;;;;;
-13BA;CHEROKEE LETTER ME;Lo;0;L;;;;;N;;;;;
-13BB;CHEROKEE LETTER MI;Lo;0;L;;;;;N;;;;;
-13BC;CHEROKEE LETTER MO;Lo;0;L;;;;;N;;;;;
-13BD;CHEROKEE LETTER MU;Lo;0;L;;;;;N;;;;;
-13BE;CHEROKEE LETTER NA;Lo;0;L;;;;;N;;;;;
-13BF;CHEROKEE LETTER HNA;Lo;0;L;;;;;N;;;;;
-13C0;CHEROKEE LETTER NAH;Lo;0;L;;;;;N;;;;;
-13C1;CHEROKEE LETTER NE;Lo;0;L;;;;;N;;;;;
-13C2;CHEROKEE LETTER NI;Lo;0;L;;;;;N;;;;;
-13C3;CHEROKEE LETTER NO;Lo;0;L;;;;;N;;;;;
-13C4;CHEROKEE LETTER NU;Lo;0;L;;;;;N;;;;;
-13C5;CHEROKEE LETTER NV;Lo;0;L;;;;;N;;;;;
-13C6;CHEROKEE LETTER QUA;Lo;0;L;;;;;N;;;;;
-13C7;CHEROKEE LETTER QUE;Lo;0;L;;;;;N;;;;;
-13C8;CHEROKEE LETTER QUI;Lo;0;L;;;;;N;;;;;
-13C9;CHEROKEE LETTER QUO;Lo;0;L;;;;;N;;;;;
-13CA;CHEROKEE LETTER QUU;Lo;0;L;;;;;N;;;;;
-13CB;CHEROKEE LETTER QUV;Lo;0;L;;;;;N;;;;;
-13CC;CHEROKEE LETTER SA;Lo;0;L;;;;;N;;;;;
-13CD;CHEROKEE LETTER S;Lo;0;L;;;;;N;;;;;
-13CE;CHEROKEE LETTER SE;Lo;0;L;;;;;N;;;;;
-13CF;CHEROKEE LETTER SI;Lo;0;L;;;;;N;;;;;
-13D0;CHEROKEE LETTER SO;Lo;0;L;;;;;N;;;;;
-13D1;CHEROKEE LETTER SU;Lo;0;L;;;;;N;;;;;
-13D2;CHEROKEE LETTER SV;Lo;0;L;;;;;N;;;;;
-13D3;CHEROKEE LETTER DA;Lo;0;L;;;;;N;;;;;
-13D4;CHEROKEE LETTER TA;Lo;0;L;;;;;N;;;;;
-13D5;CHEROKEE LETTER DE;Lo;0;L;;;;;N;;;;;
-13D6;CHEROKEE LETTER TE;Lo;0;L;;;;;N;;;;;
-13D7;CHEROKEE LETTER DI;Lo;0;L;;;;;N;;;;;
-13D8;CHEROKEE LETTER TI;Lo;0;L;;;;;N;;;;;
-13D9;CHEROKEE LETTER DO;Lo;0;L;;;;;N;;;;;
-13DA;CHEROKEE LETTER DU;Lo;0;L;;;;;N;;;;;
-13DB;CHEROKEE LETTER DV;Lo;0;L;;;;;N;;;;;
-13DC;CHEROKEE LETTER DLA;Lo;0;L;;;;;N;;;;;
-13DD;CHEROKEE LETTER TLA;Lo;0;L;;;;;N;;;;;
-13DE;CHEROKEE LETTER TLE;Lo;0;L;;;;;N;;;;;
-13DF;CHEROKEE LETTER TLI;Lo;0;L;;;;;N;;;;;
-13E0;CHEROKEE LETTER TLO;Lo;0;L;;;;;N;;;;;
-13E1;CHEROKEE LETTER TLU;Lo;0;L;;;;;N;;;;;
-13E2;CHEROKEE LETTER TLV;Lo;0;L;;;;;N;;;;;
-13E3;CHEROKEE LETTER TSA;Lo;0;L;;;;;N;;;;;
-13E4;CHEROKEE LETTER TSE;Lo;0;L;;;;;N;;;;;
-13E5;CHEROKEE LETTER TSI;Lo;0;L;;;;;N;;;;;
-13E6;CHEROKEE LETTER TSO;Lo;0;L;;;;;N;;;;;
-13E7;CHEROKEE LETTER TSU;Lo;0;L;;;;;N;;;;;
-13E8;CHEROKEE LETTER TSV;Lo;0;L;;;;;N;;;;;
-13E9;CHEROKEE LETTER WA;Lo;0;L;;;;;N;;;;;
-13EA;CHEROKEE LETTER WE;Lo;0;L;;;;;N;;;;;
-13EB;CHEROKEE LETTER WI;Lo;0;L;;;;;N;;;;;
-13EC;CHEROKEE LETTER WO;Lo;0;L;;;;;N;;;;;
-13ED;CHEROKEE LETTER WU;Lo;0;L;;;;;N;;;;;
-13EE;CHEROKEE LETTER WV;Lo;0;L;;;;;N;;;;;
-13EF;CHEROKEE LETTER YA;Lo;0;L;;;;;N;;;;;
-13F0;CHEROKEE LETTER YE;Lo;0;L;;;;;N;;;;;
-13F1;CHEROKEE LETTER YI;Lo;0;L;;;;;N;;;;;
-13F2;CHEROKEE LETTER YO;Lo;0;L;;;;;N;;;;;
-13F3;CHEROKEE LETTER YU;Lo;0;L;;;;;N;;;;;
-13F4;CHEROKEE LETTER YV;Lo;0;L;;;;;N;;;;;
-1400;CANADIAN SYLLABICS HYPHEN;Pd;0;ON;;;;;N;;;;;
-1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;;
-1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;;
-1403;CANADIAN SYLLABICS I;Lo;0;L;;;;;N;;;;;
-1404;CANADIAN SYLLABICS II;Lo;0;L;;;;;N;;;;;
-1405;CANADIAN SYLLABICS O;Lo;0;L;;;;;N;;;;;
-1406;CANADIAN SYLLABICS OO;Lo;0;L;;;;;N;;;;;
-1407;CANADIAN SYLLABICS Y-CREE OO;Lo;0;L;;;;;N;;;;;
-1408;CANADIAN SYLLABICS CARRIER EE;Lo;0;L;;;;;N;;;;;
-1409;CANADIAN SYLLABICS CARRIER I;Lo;0;L;;;;;N;;;;;
-140A;CANADIAN SYLLABICS A;Lo;0;L;;;;;N;;;;;
-140B;CANADIAN SYLLABICS AA;Lo;0;L;;;;;N;;;;;
-140C;CANADIAN SYLLABICS WE;Lo;0;L;;;;;N;;;;;
-140D;CANADIAN SYLLABICS WEST-CREE WE;Lo;0;L;;;;;N;;;;;
-140E;CANADIAN SYLLABICS WI;Lo;0;L;;;;;N;;;;;
-140F;CANADIAN SYLLABICS WEST-CREE WI;Lo;0;L;;;;;N;;;;;
-1410;CANADIAN SYLLABICS WII;Lo;0;L;;;;;N;;;;;
-1411;CANADIAN SYLLABICS WEST-CREE WII;Lo;0;L;;;;;N;;;;;
-1412;CANADIAN SYLLABICS WO;Lo;0;L;;;;;N;;;;;
-1413;CANADIAN SYLLABICS WEST-CREE WO;Lo;0;L;;;;;N;;;;;
-1414;CANADIAN SYLLABICS WOO;Lo;0;L;;;;;N;;;;;
-1415;CANADIAN SYLLABICS WEST-CREE WOO;Lo;0;L;;;;;N;;;;;
-1416;CANADIAN SYLLABICS NASKAPI WOO;Lo;0;L;;;;;N;;;;;
-1417;CANADIAN SYLLABICS WA;Lo;0;L;;;;;N;;;;;
-1418;CANADIAN SYLLABICS WEST-CREE WA;Lo;0;L;;;;;N;;;;;
-1419;CANADIAN SYLLABICS WAA;Lo;0;L;;;;;N;;;;;
-141A;CANADIAN SYLLABICS WEST-CREE WAA;Lo;0;L;;;;;N;;;;;
-141B;CANADIAN SYLLABICS NASKAPI WAA;Lo;0;L;;;;;N;;;;;
-141C;CANADIAN SYLLABICS AI;Lo;0;L;;;;;N;;;;;
-141D;CANADIAN SYLLABICS Y-CREE W;Lo;0;L;;;;;N;;;;;
-141E;CANADIAN SYLLABICS GLOTTAL STOP;Lo;0;L;;;;;N;;;;;
-141F;CANADIAN SYLLABICS FINAL ACUTE;Lo;0;L;;;;;N;;;;;
-1420;CANADIAN SYLLABICS FINAL GRAVE;Lo;0;L;;;;;N;;;;;
-1421;CANADIAN SYLLABICS FINAL BOTTOM HALF RING;Lo;0;L;;;;;N;;;;;
-1422;CANADIAN SYLLABICS FINAL TOP HALF RING;Lo;0;L;;;;;N;;;;;
-1423;CANADIAN SYLLABICS FINAL RIGHT HALF RING;Lo;0;L;;;;;N;;;;;
-1424;CANADIAN SYLLABICS FINAL RING;Lo;0;L;;;;;N;;;;;
-1425;CANADIAN SYLLABICS FINAL DOUBLE ACUTE;Lo;0;L;;;;;N;;;;;
-1426;CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES;Lo;0;L;;;;;N;;;;;
-1427;CANADIAN SYLLABICS FINAL MIDDLE DOT;Lo;0;L;;;;;N;;;;;
-1428;CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE;Lo;0;L;;;;;N;;;;;
-1429;CANADIAN SYLLABICS FINAL PLUS;Lo;0;L;;;;;N;;;;;
-142A;CANADIAN SYLLABICS FINAL DOWN TACK;Lo;0;L;;;;;N;;;;;
-142B;CANADIAN SYLLABICS EN;Lo;0;L;;;;;N;;;;;
-142C;CANADIAN SYLLABICS IN;Lo;0;L;;;;;N;;;;;
-142D;CANADIAN SYLLABICS ON;Lo;0;L;;;;;N;;;;;
-142E;CANADIAN SYLLABICS AN;Lo;0;L;;;;;N;;;;;
-142F;CANADIAN SYLLABICS PE;Lo;0;L;;;;;N;;;;;
-1430;CANADIAN SYLLABICS PAAI;Lo;0;L;;;;;N;;;;;
-1431;CANADIAN SYLLABICS PI;Lo;0;L;;;;;N;;;;;
-1432;CANADIAN SYLLABICS PII;Lo;0;L;;;;;N;;;;;
-1433;CANADIAN SYLLABICS PO;Lo;0;L;;;;;N;;;;;
-1434;CANADIAN SYLLABICS POO;Lo;0;L;;;;;N;;;;;
-1435;CANADIAN SYLLABICS Y-CREE POO;Lo;0;L;;;;;N;;;;;
-1436;CANADIAN SYLLABICS CARRIER HEE;Lo;0;L;;;;;N;;;;;
-1437;CANADIAN SYLLABICS CARRIER HI;Lo;0;L;;;;;N;;;;;
-1438;CANADIAN SYLLABICS PA;Lo;0;L;;;;;N;;;;;
-1439;CANADIAN SYLLABICS PAA;Lo;0;L;;;;;N;;;;;
-143A;CANADIAN SYLLABICS PWE;Lo;0;L;;;;;N;;;;;
-143B;CANADIAN SYLLABICS WEST-CREE PWE;Lo;0;L;;;;;N;;;;;
-143C;CANADIAN SYLLABICS PWI;Lo;0;L;;;;;N;;;;;
-143D;CANADIAN SYLLABICS WEST-CREE PWI;Lo;0;L;;;;;N;;;;;
-143E;CANADIAN SYLLABICS PWII;Lo;0;L;;;;;N;;;;;
-143F;CANADIAN SYLLABICS WEST-CREE PWII;Lo;0;L;;;;;N;;;;;
-1440;CANADIAN SYLLABICS PWO;Lo;0;L;;;;;N;;;;;
-1441;CANADIAN SYLLABICS WEST-CREE PWO;Lo;0;L;;;;;N;;;;;
-1442;CANADIAN SYLLABICS PWOO;Lo;0;L;;;;;N;;;;;
-1443;CANADIAN SYLLABICS WEST-CREE PWOO;Lo;0;L;;;;;N;;;;;
-1444;CANADIAN SYLLABICS PWA;Lo;0;L;;;;;N;;;;;
-1445;CANADIAN SYLLABICS WEST-CREE PWA;Lo;0;L;;;;;N;;;;;
-1446;CANADIAN SYLLABICS PWAA;Lo;0;L;;;;;N;;;;;
-1447;CANADIAN SYLLABICS WEST-CREE PWAA;Lo;0;L;;;;;N;;;;;
-1448;CANADIAN SYLLABICS Y-CREE PWAA;Lo;0;L;;;;;N;;;;;
-1449;CANADIAN SYLLABICS P;Lo;0;L;;;;;N;;;;;
-144A;CANADIAN SYLLABICS WEST-CREE P;Lo;0;L;;;;;N;;;;;
-144B;CANADIAN SYLLABICS CARRIER H;Lo;0;L;;;;;N;;;;;
-144C;CANADIAN SYLLABICS TE;Lo;0;L;;;;;N;;;;;
-144D;CANADIAN SYLLABICS TAAI;Lo;0;L;;;;;N;;;;;
-144E;CANADIAN SYLLABICS TI;Lo;0;L;;;;;N;;;;;
-144F;CANADIAN SYLLABICS TII;Lo;0;L;;;;;N;;;;;
-1450;CANADIAN SYLLABICS TO;Lo;0;L;;;;;N;;;;;
-1451;CANADIAN SYLLABICS TOO;Lo;0;L;;;;;N;;;;;
-1452;CANADIAN SYLLABICS Y-CREE TOO;Lo;0;L;;;;;N;;;;;
-1453;CANADIAN SYLLABICS CARRIER DEE;Lo;0;L;;;;;N;;;;;
-1454;CANADIAN SYLLABICS CARRIER DI;Lo;0;L;;;;;N;;;;;
-1455;CANADIAN SYLLABICS TA;Lo;0;L;;;;;N;;;;;
-1456;CANADIAN SYLLABICS TAA;Lo;0;L;;;;;N;;;;;
-1457;CANADIAN SYLLABICS TWE;Lo;0;L;;;;;N;;;;;
-1458;CANADIAN SYLLABICS WEST-CREE TWE;Lo;0;L;;;;;N;;;;;
-1459;CANADIAN SYLLABICS TWI;Lo;0;L;;;;;N;;;;;
-145A;CANADIAN SYLLABICS WEST-CREE TWI;Lo;0;L;;;;;N;;;;;
-145B;CANADIAN SYLLABICS TWII;Lo;0;L;;;;;N;;;;;
-145C;CANADIAN SYLLABICS WEST-CREE TWII;Lo;0;L;;;;;N;;;;;
-145D;CANADIAN SYLLABICS TWO;Lo;0;L;;;;;N;;;;;
-145E;CANADIAN SYLLABICS WEST-CREE TWO;Lo;0;L;;;;;N;;;;;
-145F;CANADIAN SYLLABICS TWOO;Lo;0;L;;;;;N;;;;;
-1460;CANADIAN SYLLABICS WEST-CREE TWOO;Lo;0;L;;;;;N;;;;;
-1461;CANADIAN SYLLABICS TWA;Lo;0;L;;;;;N;;;;;
-1462;CANADIAN SYLLABICS WEST-CREE TWA;Lo;0;L;;;;;N;;;;;
-1463;CANADIAN SYLLABICS TWAA;Lo;0;L;;;;;N;;;;;
-1464;CANADIAN SYLLABICS WEST-CREE TWAA;Lo;0;L;;;;;N;;;;;
-1465;CANADIAN SYLLABICS NASKAPI TWAA;Lo;0;L;;;;;N;;;;;
-1466;CANADIAN SYLLABICS T;Lo;0;L;;;;;N;;;;;
-1467;CANADIAN SYLLABICS TTE;Lo;0;L;;;;;N;;;;;
-1468;CANADIAN SYLLABICS TTI;Lo;0;L;;;;;N;;;;;
-1469;CANADIAN SYLLABICS TTO;Lo;0;L;;;;;N;;;;;
-146A;CANADIAN SYLLABICS TTA;Lo;0;L;;;;;N;;;;;
-146B;CANADIAN SYLLABICS KE;Lo;0;L;;;;;N;;;;;
-146C;CANADIAN SYLLABICS KAAI;Lo;0;L;;;;;N;;;;;
-146D;CANADIAN SYLLABICS KI;Lo;0;L;;;;;N;;;;;
-146E;CANADIAN SYLLABICS KII;Lo;0;L;;;;;N;;;;;
-146F;CANADIAN SYLLABICS KO;Lo;0;L;;;;;N;;;;;
-1470;CANADIAN SYLLABICS KOO;Lo;0;L;;;;;N;;;;;
-1471;CANADIAN SYLLABICS Y-CREE KOO;Lo;0;L;;;;;N;;;;;
-1472;CANADIAN SYLLABICS KA;Lo;0;L;;;;;N;;;;;
-1473;CANADIAN SYLLABICS KAA;Lo;0;L;;;;;N;;;;;
-1474;CANADIAN SYLLABICS KWE;Lo;0;L;;;;;N;;;;;
-1475;CANADIAN SYLLABICS WEST-CREE KWE;Lo;0;L;;;;;N;;;;;
-1476;CANADIAN SYLLABICS KWI;Lo;0;L;;;;;N;;;;;
-1477;CANADIAN SYLLABICS WEST-CREE KWI;Lo;0;L;;;;;N;;;;;
-1478;CANADIAN SYLLABICS KWII;Lo;0;L;;;;;N;;;;;
-1479;CANADIAN SYLLABICS WEST-CREE KWII;Lo;0;L;;;;;N;;;;;
-147A;CANADIAN SYLLABICS KWO;Lo;0;L;;;;;N;;;;;
-147B;CANADIAN SYLLABICS WEST-CREE KWO;Lo;0;L;;;;;N;;;;;
-147C;CANADIAN SYLLABICS KWOO;Lo;0;L;;;;;N;;;;;
-147D;CANADIAN SYLLABICS WEST-CREE KWOO;Lo;0;L;;;;;N;;;;;
-147E;CANADIAN SYLLABICS KWA;Lo;0;L;;;;;N;;;;;
-147F;CANADIAN SYLLABICS WEST-CREE KWA;Lo;0;L;;;;;N;;;;;
-1480;CANADIAN SYLLABICS KWAA;Lo;0;L;;;;;N;;;;;
-1481;CANADIAN SYLLABICS WEST-CREE KWAA;Lo;0;L;;;;;N;;;;;
-1482;CANADIAN SYLLABICS NASKAPI KWAA;Lo;0;L;;;;;N;;;;;
-1483;CANADIAN SYLLABICS K;Lo;0;L;;;;;N;;;;;
-1484;CANADIAN SYLLABICS KW;Lo;0;L;;;;;N;;;;;
-1485;CANADIAN SYLLABICS SOUTH-SLAVEY KEH;Lo;0;L;;;;;N;;;;;
-1486;CANADIAN SYLLABICS SOUTH-SLAVEY KIH;Lo;0;L;;;;;N;;;;;
-1487;CANADIAN SYLLABICS SOUTH-SLAVEY KOH;Lo;0;L;;;;;N;;;;;
-1488;CANADIAN SYLLABICS SOUTH-SLAVEY KAH;Lo;0;L;;;;;N;;;;;
-1489;CANADIAN SYLLABICS CE;Lo;0;L;;;;;N;;;;;
-148A;CANADIAN SYLLABICS CAAI;Lo;0;L;;;;;N;;;;;
-148B;CANADIAN SYLLABICS CI;Lo;0;L;;;;;N;;;;;
-148C;CANADIAN SYLLABICS CII;Lo;0;L;;;;;N;;;;;
-148D;CANADIAN SYLLABICS CO;Lo;0;L;;;;;N;;;;;
-148E;CANADIAN SYLLABICS COO;Lo;0;L;;;;;N;;;;;
-148F;CANADIAN SYLLABICS Y-CREE COO;Lo;0;L;;;;;N;;;;;
-1490;CANADIAN SYLLABICS CA;Lo;0;L;;;;;N;;;;;
-1491;CANADIAN SYLLABICS CAA;Lo;0;L;;;;;N;;;;;
-1492;CANADIAN SYLLABICS CWE;Lo;0;L;;;;;N;;;;;
-1493;CANADIAN SYLLABICS WEST-CREE CWE;Lo;0;L;;;;;N;;;;;
-1494;CANADIAN SYLLABICS CWI;Lo;0;L;;;;;N;;;;;
-1495;CANADIAN SYLLABICS WEST-CREE CWI;Lo;0;L;;;;;N;;;;;
-1496;CANADIAN SYLLABICS CWII;Lo;0;L;;;;;N;;;;;
-1497;CANADIAN SYLLABICS WEST-CREE CWII;Lo;0;L;;;;;N;;;;;
-1498;CANADIAN SYLLABICS CWO;Lo;0;L;;;;;N;;;;;
-1499;CANADIAN SYLLABICS WEST-CREE CWO;Lo;0;L;;;;;N;;;;;
-149A;CANADIAN SYLLABICS CWOO;Lo;0;L;;;;;N;;;;;
-149B;CANADIAN SYLLABICS WEST-CREE CWOO;Lo;0;L;;;;;N;;;;;
-149C;CANADIAN SYLLABICS CWA;Lo;0;L;;;;;N;;;;;
-149D;CANADIAN SYLLABICS WEST-CREE CWA;Lo;0;L;;;;;N;;;;;
-149E;CANADIAN SYLLABICS CWAA;Lo;0;L;;;;;N;;;;;
-149F;CANADIAN SYLLABICS WEST-CREE CWAA;Lo;0;L;;;;;N;;;;;
-14A0;CANADIAN SYLLABICS NASKAPI CWAA;Lo;0;L;;;;;N;;;;;
-14A1;CANADIAN SYLLABICS C;Lo;0;L;;;;;N;;;;;
-14A2;CANADIAN SYLLABICS SAYISI TH;Lo;0;L;;;;;N;;;;;
-14A3;CANADIAN SYLLABICS ME;Lo;0;L;;;;;N;;;;;
-14A4;CANADIAN SYLLABICS MAAI;Lo;0;L;;;;;N;;;;;
-14A5;CANADIAN SYLLABICS MI;Lo;0;L;;;;;N;;;;;
-14A6;CANADIAN SYLLABICS MII;Lo;0;L;;;;;N;;;;;
-14A7;CANADIAN SYLLABICS MO;Lo;0;L;;;;;N;;;;;
-14A8;CANADIAN SYLLABICS MOO;Lo;0;L;;;;;N;;;;;
-14A9;CANADIAN SYLLABICS Y-CREE MOO;Lo;0;L;;;;;N;;;;;
-14AA;CANADIAN SYLLABICS MA;Lo;0;L;;;;;N;;;;;
-14AB;CANADIAN SYLLABICS MAA;Lo;0;L;;;;;N;;;;;
-14AC;CANADIAN SYLLABICS MWE;Lo;0;L;;;;;N;;;;;
-14AD;CANADIAN SYLLABICS WEST-CREE MWE;Lo;0;L;;;;;N;;;;;
-14AE;CANADIAN SYLLABICS MWI;Lo;0;L;;;;;N;;;;;
-14AF;CANADIAN SYLLABICS WEST-CREE MWI;Lo;0;L;;;;;N;;;;;
-14B0;CANADIAN SYLLABICS MWII;Lo;0;L;;;;;N;;;;;
-14B1;CANADIAN SYLLABICS WEST-CREE MWII;Lo;0;L;;;;;N;;;;;
-14B2;CANADIAN SYLLABICS MWO;Lo;0;L;;;;;N;;;;;
-14B3;CANADIAN SYLLABICS WEST-CREE MWO;Lo;0;L;;;;;N;;;;;
-14B4;CANADIAN SYLLABICS MWOO;Lo;0;L;;;;;N;;;;;
-14B5;CANADIAN SYLLABICS WEST-CREE MWOO;Lo;0;L;;;;;N;;;;;
-14B6;CANADIAN SYLLABICS MWA;Lo;0;L;;;;;N;;;;;
-14B7;CANADIAN SYLLABICS WEST-CREE MWA;Lo;0;L;;;;;N;;;;;
-14B8;CANADIAN SYLLABICS MWAA;Lo;0;L;;;;;N;;;;;
-14B9;CANADIAN SYLLABICS WEST-CREE MWAA;Lo;0;L;;;;;N;;;;;
-14BA;CANADIAN SYLLABICS NASKAPI MWAA;Lo;0;L;;;;;N;;;;;
-14BB;CANADIAN SYLLABICS M;Lo;0;L;;;;;N;;;;;
-14BC;CANADIAN SYLLABICS WEST-CREE M;Lo;0;L;;;;;N;;;;;
-14BD;CANADIAN SYLLABICS MH;Lo;0;L;;;;;N;;;;;
-14BE;CANADIAN SYLLABICS ATHAPASCAN M;Lo;0;L;;;;;N;;;;;
-14BF;CANADIAN SYLLABICS SAYISI M;Lo;0;L;;;;;N;;;;;
-14C0;CANADIAN SYLLABICS NE;Lo;0;L;;;;;N;;;;;
-14C1;CANADIAN SYLLABICS NAAI;Lo;0;L;;;;;N;;;;;
-14C2;CANADIAN SYLLABICS NI;Lo;0;L;;;;;N;;;;;
-14C3;CANADIAN SYLLABICS NII;Lo;0;L;;;;;N;;;;;
-14C4;CANADIAN SYLLABICS NO;Lo;0;L;;;;;N;;;;;
-14C5;CANADIAN SYLLABICS NOO;Lo;0;L;;;;;N;;;;;
-14C6;CANADIAN SYLLABICS Y-CREE NOO;Lo;0;L;;;;;N;;;;;
-14C7;CANADIAN SYLLABICS NA;Lo;0;L;;;;;N;;;;;
-14C8;CANADIAN SYLLABICS NAA;Lo;0;L;;;;;N;;;;;
-14C9;CANADIAN SYLLABICS NWE;Lo;0;L;;;;;N;;;;;
-14CA;CANADIAN SYLLABICS WEST-CREE NWE;Lo;0;L;;;;;N;;;;;
-14CB;CANADIAN SYLLABICS NWA;Lo;0;L;;;;;N;;;;;
-14CC;CANADIAN SYLLABICS WEST-CREE NWA;Lo;0;L;;;;;N;;;;;
-14CD;CANADIAN SYLLABICS NWAA;Lo;0;L;;;;;N;;;;;
-14CE;CANADIAN SYLLABICS WEST-CREE NWAA;Lo;0;L;;;;;N;;;;;
-14CF;CANADIAN SYLLABICS NASKAPI NWAA;Lo;0;L;;;;;N;;;;;
-14D0;CANADIAN SYLLABICS N;Lo;0;L;;;;;N;;;;;
-14D1;CANADIAN SYLLABICS CARRIER NG;Lo;0;L;;;;;N;;;;;
-14D2;CANADIAN SYLLABICS NH;Lo;0;L;;;;;N;;;;;
-14D3;CANADIAN SYLLABICS LE;Lo;0;L;;;;;N;;;;;
-14D4;CANADIAN SYLLABICS LAAI;Lo;0;L;;;;;N;;;;;
-14D5;CANADIAN SYLLABICS LI;Lo;0;L;;;;;N;;;;;
-14D6;CANADIAN SYLLABICS LII;Lo;0;L;;;;;N;;;;;
-14D7;CANADIAN SYLLABICS LO;Lo;0;L;;;;;N;;;;;
-14D8;CANADIAN SYLLABICS LOO;Lo;0;L;;;;;N;;;;;
-14D9;CANADIAN SYLLABICS Y-CREE LOO;Lo;0;L;;;;;N;;;;;
-14DA;CANADIAN SYLLABICS LA;Lo;0;L;;;;;N;;;;;
-14DB;CANADIAN SYLLABICS LAA;Lo;0;L;;;;;N;;;;;
-14DC;CANADIAN SYLLABICS LWE;Lo;0;L;;;;;N;;;;;
-14DD;CANADIAN SYLLABICS WEST-CREE LWE;Lo;0;L;;;;;N;;;;;
-14DE;CANADIAN SYLLABICS LWI;Lo;0;L;;;;;N;;;;;
-14DF;CANADIAN SYLLABICS WEST-CREE LWI;Lo;0;L;;;;;N;;;;;
-14E0;CANADIAN SYLLABICS LWII;Lo;0;L;;;;;N;;;;;
-14E1;CANADIAN SYLLABICS WEST-CREE LWII;Lo;0;L;;;;;N;;;;;
-14E2;CANADIAN SYLLABICS LWO;Lo;0;L;;;;;N;;;;;
-14E3;CANADIAN SYLLABICS WEST-CREE LWO;Lo;0;L;;;;;N;;;;;
-14E4;CANADIAN SYLLABICS LWOO;Lo;0;L;;;;;N;;;;;
-14E5;CANADIAN SYLLABICS WEST-CREE LWOO;Lo;0;L;;;;;N;;;;;
-14E6;CANADIAN SYLLABICS LWA;Lo;0;L;;;;;N;;;;;
-14E7;CANADIAN SYLLABICS WEST-CREE LWA;Lo;0;L;;;;;N;;;;;
-14E8;CANADIAN SYLLABICS LWAA;Lo;0;L;;;;;N;;;;;
-14E9;CANADIAN SYLLABICS WEST-CREE LWAA;Lo;0;L;;;;;N;;;;;
-14EA;CANADIAN SYLLABICS L;Lo;0;L;;;;;N;;;;;
-14EB;CANADIAN SYLLABICS WEST-CREE L;Lo;0;L;;;;;N;;;;;
-14EC;CANADIAN SYLLABICS MEDIAL L;Lo;0;L;;;;;N;;;;;
-14ED;CANADIAN SYLLABICS SE;Lo;0;L;;;;;N;;;;;
-14EE;CANADIAN SYLLABICS SAAI;Lo;0;L;;;;;N;;;;;
-14EF;CANADIAN SYLLABICS SI;Lo;0;L;;;;;N;;;;;
-14F0;CANADIAN SYLLABICS SII;Lo;0;L;;;;;N;;;;;
-14F1;CANADIAN SYLLABICS SO;Lo;0;L;;;;;N;;;;;
-14F2;CANADIAN SYLLABICS SOO;Lo;0;L;;;;;N;;;;;
-14F3;CANADIAN SYLLABICS Y-CREE SOO;Lo;0;L;;;;;N;;;;;
-14F4;CANADIAN SYLLABICS SA;Lo;0;L;;;;;N;;;;;
-14F5;CANADIAN SYLLABICS SAA;Lo;0;L;;;;;N;;;;;
-14F6;CANADIAN SYLLABICS SWE;Lo;0;L;;;;;N;;;;;
-14F7;CANADIAN SYLLABICS WEST-CREE SWE;Lo;0;L;;;;;N;;;;;
-14F8;CANADIAN SYLLABICS SWI;Lo;0;L;;;;;N;;;;;
-14F9;CANADIAN SYLLABICS WEST-CREE SWI;Lo;0;L;;;;;N;;;;;
-14FA;CANADIAN SYLLABICS SWII;Lo;0;L;;;;;N;;;;;
-14FB;CANADIAN SYLLABICS WEST-CREE SWII;Lo;0;L;;;;;N;;;;;
-14FC;CANADIAN SYLLABICS SWO;Lo;0;L;;;;;N;;;;;
-14FD;CANADIAN SYLLABICS WEST-CREE SWO;Lo;0;L;;;;;N;;;;;
-14FE;CANADIAN SYLLABICS SWOO;Lo;0;L;;;;;N;;;;;
-14FF;CANADIAN SYLLABICS WEST-CREE SWOO;Lo;0;L;;;;;N;;;;;
-1500;CANADIAN SYLLABICS SWA;Lo;0;L;;;;;N;;;;;
-1501;CANADIAN SYLLABICS WEST-CREE SWA;Lo;0;L;;;;;N;;;;;
-1502;CANADIAN SYLLABICS SWAA;Lo;0;L;;;;;N;;;;;
-1503;CANADIAN SYLLABICS WEST-CREE SWAA;Lo;0;L;;;;;N;;;;;
-1504;CANADIAN SYLLABICS NASKAPI SWAA;Lo;0;L;;;;;N;;;;;
-1505;CANADIAN SYLLABICS S;Lo;0;L;;;;;N;;;;;
-1506;CANADIAN SYLLABICS ATHAPASCAN S;Lo;0;L;;;;;N;;;;;
-1507;CANADIAN SYLLABICS SW;Lo;0;L;;;;;N;;;;;
-1508;CANADIAN SYLLABICS BLACKFOOT S;Lo;0;L;;;;;N;;;;;
-1509;CANADIAN SYLLABICS MOOSE-CREE SK;Lo;0;L;;;;;N;;;;;
-150A;CANADIAN SYLLABICS NASKAPI SKW;Lo;0;L;;;;;N;;;;;
-150B;CANADIAN SYLLABICS NASKAPI S-W;Lo;0;L;;;;;N;;;;;
-150C;CANADIAN SYLLABICS NASKAPI SPWA;Lo;0;L;;;;;N;;;;;
-150D;CANADIAN SYLLABICS NASKAPI STWA;Lo;0;L;;;;;N;;;;;
-150E;CANADIAN SYLLABICS NASKAPI SKWA;Lo;0;L;;;;;N;;;;;
-150F;CANADIAN SYLLABICS NASKAPI SCWA;Lo;0;L;;;;;N;;;;;
-1510;CANADIAN SYLLABICS SHE;Lo;0;L;;;;;N;;;;;
-1511;CANADIAN SYLLABICS SHI;Lo;0;L;;;;;N;;;;;
-1512;CANADIAN SYLLABICS SHII;Lo;0;L;;;;;N;;;;;
-1513;CANADIAN SYLLABICS SHO;Lo;0;L;;;;;N;;;;;
-1514;CANADIAN SYLLABICS SHOO;Lo;0;L;;;;;N;;;;;
-1515;CANADIAN SYLLABICS SHA;Lo;0;L;;;;;N;;;;;
-1516;CANADIAN SYLLABICS SHAA;Lo;0;L;;;;;N;;;;;
-1517;CANADIAN SYLLABICS SHWE;Lo;0;L;;;;;N;;;;;
-1518;CANADIAN SYLLABICS WEST-CREE SHWE;Lo;0;L;;;;;N;;;;;
-1519;CANADIAN SYLLABICS SHWI;Lo;0;L;;;;;N;;;;;
-151A;CANADIAN SYLLABICS WEST-CREE SHWI;Lo;0;L;;;;;N;;;;;
-151B;CANADIAN SYLLABICS SHWII;Lo;0;L;;;;;N;;;;;
-151C;CANADIAN SYLLABICS WEST-CREE SHWII;Lo;0;L;;;;;N;;;;;
-151D;CANADIAN SYLLABICS SHWO;Lo;0;L;;;;;N;;;;;
-151E;CANADIAN SYLLABICS WEST-CREE SHWO;Lo;0;L;;;;;N;;;;;
-151F;CANADIAN SYLLABICS SHWOO;Lo;0;L;;;;;N;;;;;
-1520;CANADIAN SYLLABICS WEST-CREE SHWOO;Lo;0;L;;;;;N;;;;;
-1521;CANADIAN SYLLABICS SHWA;Lo;0;L;;;;;N;;;;;
-1522;CANADIAN SYLLABICS WEST-CREE SHWA;Lo;0;L;;;;;N;;;;;
-1523;CANADIAN SYLLABICS SHWAA;Lo;0;L;;;;;N;;;;;
-1524;CANADIAN SYLLABICS WEST-CREE SHWAA;Lo;0;L;;;;;N;;;;;
-1525;CANADIAN SYLLABICS SH;Lo;0;L;;;;;N;;;;;
-1526;CANADIAN SYLLABICS YE;Lo;0;L;;;;;N;;;;;
-1527;CANADIAN SYLLABICS YAAI;Lo;0;L;;;;;N;;;;;
-1528;CANADIAN SYLLABICS YI;Lo;0;L;;;;;N;;;;;
-1529;CANADIAN SYLLABICS YII;Lo;0;L;;;;;N;;;;;
-152A;CANADIAN SYLLABICS YO;Lo;0;L;;;;;N;;;;;
-152B;CANADIAN SYLLABICS YOO;Lo;0;L;;;;;N;;;;;
-152C;CANADIAN SYLLABICS Y-CREE YOO;Lo;0;L;;;;;N;;;;;
-152D;CANADIAN SYLLABICS YA;Lo;0;L;;;;;N;;;;;
-152E;CANADIAN SYLLABICS YAA;Lo;0;L;;;;;N;;;;;
-152F;CANADIAN SYLLABICS YWE;Lo;0;L;;;;;N;;;;;
-1530;CANADIAN SYLLABICS WEST-CREE YWE;Lo;0;L;;;;;N;;;;;
-1531;CANADIAN SYLLABICS YWI;Lo;0;L;;;;;N;;;;;
-1532;CANADIAN SYLLABICS WEST-CREE YWI;Lo;0;L;;;;;N;;;;;
-1533;CANADIAN SYLLABICS YWII;Lo;0;L;;;;;N;;;;;
-1534;CANADIAN SYLLABICS WEST-CREE YWII;Lo;0;L;;;;;N;;;;;
-1535;CANADIAN SYLLABICS YWO;Lo;0;L;;;;;N;;;;;
-1536;CANADIAN SYLLABICS WEST-CREE YWO;Lo;0;L;;;;;N;;;;;
-1537;CANADIAN SYLLABICS YWOO;Lo;0;L;;;;;N;;;;;
-1538;CANADIAN SYLLABICS WEST-CREE YWOO;Lo;0;L;;;;;N;;;;;
-1539;CANADIAN SYLLABICS YWA;Lo;0;L;;;;;N;;;;;
-153A;CANADIAN SYLLABICS WEST-CREE YWA;Lo;0;L;;;;;N;;;;;
-153B;CANADIAN SYLLABICS YWAA;Lo;0;L;;;;;N;;;;;
-153C;CANADIAN SYLLABICS WEST-CREE YWAA;Lo;0;L;;;;;N;;;;;
-153D;CANADIAN SYLLABICS NASKAPI YWAA;Lo;0;L;;;;;N;;;;;
-153E;CANADIAN SYLLABICS Y;Lo;0;L;;;;;N;;;;;
-153F;CANADIAN SYLLABICS BIBLE-CREE Y;Lo;0;L;;;;;N;;;;;
-1540;CANADIAN SYLLABICS WEST-CREE Y;Lo;0;L;;;;;N;;;;;
-1541;CANADIAN SYLLABICS SAYISI YI;Lo;0;L;;;;;N;;;;;
-1542;CANADIAN SYLLABICS RE;Lo;0;L;;;;;N;;;;;
-1543;CANADIAN SYLLABICS R-CREE RE;Lo;0;L;;;;;N;;;;;
-1544;CANADIAN SYLLABICS WEST-CREE LE;Lo;0;L;;;;;N;;;;;
-1545;CANADIAN SYLLABICS RAAI;Lo;0;L;;;;;N;;;;;
-1546;CANADIAN SYLLABICS RI;Lo;0;L;;;;;N;;;;;
-1547;CANADIAN SYLLABICS RII;Lo;0;L;;;;;N;;;;;
-1548;CANADIAN SYLLABICS RO;Lo;0;L;;;;;N;;;;;
-1549;CANADIAN SYLLABICS ROO;Lo;0;L;;;;;N;;;;;
-154A;CANADIAN SYLLABICS WEST-CREE LO;Lo;0;L;;;;;N;;;;;
-154B;CANADIAN SYLLABICS RA;Lo;0;L;;;;;N;;;;;
-154C;CANADIAN SYLLABICS RAA;Lo;0;L;;;;;N;;;;;
-154D;CANADIAN SYLLABICS WEST-CREE LA;Lo;0;L;;;;;N;;;;;
-154E;CANADIAN SYLLABICS RWAA;Lo;0;L;;;;;N;;;;;
-154F;CANADIAN SYLLABICS WEST-CREE RWAA;Lo;0;L;;;;;N;;;;;
-1550;CANADIAN SYLLABICS R;Lo;0;L;;;;;N;;;;;
-1551;CANADIAN SYLLABICS WEST-CREE R;Lo;0;L;;;;;N;;;;;
-1552;CANADIAN SYLLABICS MEDIAL R;Lo;0;L;;;;;N;;;;;
-1553;CANADIAN SYLLABICS FE;Lo;0;L;;;;;N;;;;;
-1554;CANADIAN SYLLABICS FAAI;Lo;0;L;;;;;N;;;;;
-1555;CANADIAN SYLLABICS FI;Lo;0;L;;;;;N;;;;;
-1556;CANADIAN SYLLABICS FII;Lo;0;L;;;;;N;;;;;
-1557;CANADIAN SYLLABICS FO;Lo;0;L;;;;;N;;;;;
-1558;CANADIAN SYLLABICS FOO;Lo;0;L;;;;;N;;;;;
-1559;CANADIAN SYLLABICS FA;Lo;0;L;;;;;N;;;;;
-155A;CANADIAN SYLLABICS FAA;Lo;0;L;;;;;N;;;;;
-155B;CANADIAN SYLLABICS FWAA;Lo;0;L;;;;;N;;;;;
-155C;CANADIAN SYLLABICS WEST-CREE FWAA;Lo;0;L;;;;;N;;;;;
-155D;CANADIAN SYLLABICS F;Lo;0;L;;;;;N;;;;;
-155E;CANADIAN SYLLABICS THE;Lo;0;L;;;;;N;;;;;
-155F;CANADIAN SYLLABICS N-CREE THE;Lo;0;L;;;;;N;;;;;
-1560;CANADIAN SYLLABICS THI;Lo;0;L;;;;;N;;;;;
-1561;CANADIAN SYLLABICS N-CREE THI;Lo;0;L;;;;;N;;;;;
-1562;CANADIAN SYLLABICS THII;Lo;0;L;;;;;N;;;;;
-1563;CANADIAN SYLLABICS N-CREE THII;Lo;0;L;;;;;N;;;;;
-1564;CANADIAN SYLLABICS THO;Lo;0;L;;;;;N;;;;;
-1565;CANADIAN SYLLABICS THOO;Lo;0;L;;;;;N;;;;;
-1566;CANADIAN SYLLABICS THA;Lo;0;L;;;;;N;;;;;
-1567;CANADIAN SYLLABICS THAA;Lo;0;L;;;;;N;;;;;
-1568;CANADIAN SYLLABICS THWAA;Lo;0;L;;;;;N;;;;;
-1569;CANADIAN SYLLABICS WEST-CREE THWAA;Lo;0;L;;;;;N;;;;;
-156A;CANADIAN SYLLABICS TH;Lo;0;L;;;;;N;;;;;
-156B;CANADIAN SYLLABICS TTHE;Lo;0;L;;;;;N;;;;;
-156C;CANADIAN SYLLABICS TTHI;Lo;0;L;;;;;N;;;;;
-156D;CANADIAN SYLLABICS TTHO;Lo;0;L;;;;;N;;;;;
-156E;CANADIAN SYLLABICS TTHA;Lo;0;L;;;;;N;;;;;
-156F;CANADIAN SYLLABICS TTH;Lo;0;L;;;;;N;;;;;
-1570;CANADIAN SYLLABICS TYE;Lo;0;L;;;;;N;;;;;
-1571;CANADIAN SYLLABICS TYI;Lo;0;L;;;;;N;;;;;
-1572;CANADIAN SYLLABICS TYO;Lo;0;L;;;;;N;;;;;
-1573;CANADIAN SYLLABICS TYA;Lo;0;L;;;;;N;;;;;
-1574;CANADIAN SYLLABICS NUNAVIK HE;Lo;0;L;;;;;N;;;;;
-1575;CANADIAN SYLLABICS NUNAVIK HI;Lo;0;L;;;;;N;;;;;
-1576;CANADIAN SYLLABICS NUNAVIK HII;Lo;0;L;;;;;N;;;;;
-1577;CANADIAN SYLLABICS NUNAVIK HO;Lo;0;L;;;;;N;;;;;
-1578;CANADIAN SYLLABICS NUNAVIK HOO;Lo;0;L;;;;;N;;;;;
-1579;CANADIAN SYLLABICS NUNAVIK HA;Lo;0;L;;;;;N;;;;;
-157A;CANADIAN SYLLABICS NUNAVIK HAA;Lo;0;L;;;;;N;;;;;
-157B;CANADIAN SYLLABICS NUNAVIK H;Lo;0;L;;;;;N;;;;;
-157C;CANADIAN SYLLABICS NUNAVUT H;Lo;0;L;;;;;N;;;;;
-157D;CANADIAN SYLLABICS HK;Lo;0;L;;;;;N;;;;;
-157E;CANADIAN SYLLABICS QAAI;Lo;0;L;;;;;N;;;;;
-157F;CANADIAN SYLLABICS QI;Lo;0;L;;;;;N;;;;;
-1580;CANADIAN SYLLABICS QII;Lo;0;L;;;;;N;;;;;
-1581;CANADIAN SYLLABICS QO;Lo;0;L;;;;;N;;;;;
-1582;CANADIAN SYLLABICS QOO;Lo;0;L;;;;;N;;;;;
-1583;CANADIAN SYLLABICS QA;Lo;0;L;;;;;N;;;;;
-1584;CANADIAN SYLLABICS QAA;Lo;0;L;;;;;N;;;;;
-1585;CANADIAN SYLLABICS Q;Lo;0;L;;;;;N;;;;;
-1586;CANADIAN SYLLABICS TLHE;Lo;0;L;;;;;N;;;;;
-1587;CANADIAN SYLLABICS TLHI;Lo;0;L;;;;;N;;;;;
-1588;CANADIAN SYLLABICS TLHO;Lo;0;L;;;;;N;;;;;
-1589;CANADIAN SYLLABICS TLHA;Lo;0;L;;;;;N;;;;;
-158A;CANADIAN SYLLABICS WEST-CREE RE;Lo;0;L;;;;;N;;;;;
-158B;CANADIAN SYLLABICS WEST-CREE RI;Lo;0;L;;;;;N;;;;;
-158C;CANADIAN SYLLABICS WEST-CREE RO;Lo;0;L;;;;;N;;;;;
-158D;CANADIAN SYLLABICS WEST-CREE RA;Lo;0;L;;;;;N;;;;;
-158E;CANADIAN SYLLABICS NGAAI;Lo;0;L;;;;;N;;;;;
-158F;CANADIAN SYLLABICS NGI;Lo;0;L;;;;;N;;;;;
-1590;CANADIAN SYLLABICS NGII;Lo;0;L;;;;;N;;;;;
-1591;CANADIAN SYLLABICS NGO;Lo;0;L;;;;;N;;;;;
-1592;CANADIAN SYLLABICS NGOO;Lo;0;L;;;;;N;;;;;
-1593;CANADIAN SYLLABICS NGA;Lo;0;L;;;;;N;;;;;
-1594;CANADIAN SYLLABICS NGAA;Lo;0;L;;;;;N;;;;;
-1595;CANADIAN SYLLABICS NG;Lo;0;L;;;;;N;;;;;
-1596;CANADIAN SYLLABICS NNG;Lo;0;L;;;;;N;;;;;
-1597;CANADIAN SYLLABICS SAYISI SHE;Lo;0;L;;;;;N;;;;;
-1598;CANADIAN SYLLABICS SAYISI SHI;Lo;0;L;;;;;N;;;;;
-1599;CANADIAN SYLLABICS SAYISI SHO;Lo;0;L;;;;;N;;;;;
-159A;CANADIAN SYLLABICS SAYISI SHA;Lo;0;L;;;;;N;;;;;
-159B;CANADIAN SYLLABICS WOODS-CREE THE;Lo;0;L;;;;;N;;;;;
-159C;CANADIAN SYLLABICS WOODS-CREE THI;Lo;0;L;;;;;N;;;;;
-159D;CANADIAN SYLLABICS WOODS-CREE THO;Lo;0;L;;;;;N;;;;;
-159E;CANADIAN SYLLABICS WOODS-CREE THA;Lo;0;L;;;;;N;;;;;
-159F;CANADIAN SYLLABICS WOODS-CREE TH;Lo;0;L;;;;;N;;;;;
-15A0;CANADIAN SYLLABICS LHI;Lo;0;L;;;;;N;;;;;
-15A1;CANADIAN SYLLABICS LHII;Lo;0;L;;;;;N;;;;;
-15A2;CANADIAN SYLLABICS LHO;Lo;0;L;;;;;N;;;;;
-15A3;CANADIAN SYLLABICS LHOO;Lo;0;L;;;;;N;;;;;
-15A4;CANADIAN SYLLABICS LHA;Lo;0;L;;;;;N;;;;;
-15A5;CANADIAN SYLLABICS LHAA;Lo;0;L;;;;;N;;;;;
-15A6;CANADIAN SYLLABICS LH;Lo;0;L;;;;;N;;;;;
-15A7;CANADIAN SYLLABICS TH-CREE THE;Lo;0;L;;;;;N;;;;;
-15A8;CANADIAN SYLLABICS TH-CREE THI;Lo;0;L;;;;;N;;;;;
-15A9;CANADIAN SYLLABICS TH-CREE THII;Lo;0;L;;;;;N;;;;;
-15AA;CANADIAN SYLLABICS TH-CREE THO;Lo;0;L;;;;;N;;;;;
-15AB;CANADIAN SYLLABICS TH-CREE THOO;Lo;0;L;;;;;N;;;;;
-15AC;CANADIAN SYLLABICS TH-CREE THA;Lo;0;L;;;;;N;;;;;
-15AD;CANADIAN SYLLABICS TH-CREE THAA;Lo;0;L;;;;;N;;;;;
-15AE;CANADIAN SYLLABICS TH-CREE TH;Lo;0;L;;;;;N;;;;;
-15AF;CANADIAN SYLLABICS AIVILIK B;Lo;0;L;;;;;N;;;;;
-15B0;CANADIAN SYLLABICS BLACKFOOT E;Lo;0;L;;;;;N;;;;;
-15B1;CANADIAN SYLLABICS BLACKFOOT I;Lo;0;L;;;;;N;;;;;
-15B2;CANADIAN SYLLABICS BLACKFOOT O;Lo;0;L;;;;;N;;;;;
-15B3;CANADIAN SYLLABICS BLACKFOOT A;Lo;0;L;;;;;N;;;;;
-15B4;CANADIAN SYLLABICS BLACKFOOT WE;Lo;0;L;;;;;N;;;;;
-15B5;CANADIAN SYLLABICS BLACKFOOT WI;Lo;0;L;;;;;N;;;;;
-15B6;CANADIAN SYLLABICS BLACKFOOT WO;Lo;0;L;;;;;N;;;;;
-15B7;CANADIAN SYLLABICS BLACKFOOT WA;Lo;0;L;;;;;N;;;;;
-15B8;CANADIAN SYLLABICS BLACKFOOT NE;Lo;0;L;;;;;N;;;;;
-15B9;CANADIAN SYLLABICS BLACKFOOT NI;Lo;0;L;;;;;N;;;;;
-15BA;CANADIAN SYLLABICS BLACKFOOT NO;Lo;0;L;;;;;N;;;;;
-15BB;CANADIAN SYLLABICS BLACKFOOT NA;Lo;0;L;;;;;N;;;;;
-15BC;CANADIAN SYLLABICS BLACKFOOT KE;Lo;0;L;;;;;N;;;;;
-15BD;CANADIAN SYLLABICS BLACKFOOT KI;Lo;0;L;;;;;N;;;;;
-15BE;CANADIAN SYLLABICS BLACKFOOT KO;Lo;0;L;;;;;N;;;;;
-15BF;CANADIAN SYLLABICS BLACKFOOT KA;Lo;0;L;;;;;N;;;;;
-15C0;CANADIAN SYLLABICS SAYISI HE;Lo;0;L;;;;;N;;;;;
-15C1;CANADIAN SYLLABICS SAYISI HI;Lo;0;L;;;;;N;;;;;
-15C2;CANADIAN SYLLABICS SAYISI HO;Lo;0;L;;;;;N;;;;;
-15C3;CANADIAN SYLLABICS SAYISI HA;Lo;0;L;;;;;N;;;;;
-15C4;CANADIAN SYLLABICS CARRIER GHU;Lo;0;L;;;;;N;;;;;
-15C5;CANADIAN SYLLABICS CARRIER GHO;Lo;0;L;;;;;N;;;;;
-15C6;CANADIAN SYLLABICS CARRIER GHE;Lo;0;L;;;;;N;;;;;
-15C7;CANADIAN SYLLABICS CARRIER GHEE;Lo;0;L;;;;;N;;;;;
-15C8;CANADIAN SYLLABICS CARRIER GHI;Lo;0;L;;;;;N;;;;;
-15C9;CANADIAN SYLLABICS CARRIER GHA;Lo;0;L;;;;;N;;;;;
-15CA;CANADIAN SYLLABICS CARRIER RU;Lo;0;L;;;;;N;;;;;
-15CB;CANADIAN SYLLABICS CARRIER RO;Lo;0;L;;;;;N;;;;;
-15CC;CANADIAN SYLLABICS CARRIER RE;Lo;0;L;;;;;N;;;;;
-15CD;CANADIAN SYLLABICS CARRIER REE;Lo;0;L;;;;;N;;;;;
-15CE;CANADIAN SYLLABICS CARRIER RI;Lo;0;L;;;;;N;;;;;
-15CF;CANADIAN SYLLABICS CARRIER RA;Lo;0;L;;;;;N;;;;;
-15D0;CANADIAN SYLLABICS CARRIER WU;Lo;0;L;;;;;N;;;;;
-15D1;CANADIAN SYLLABICS CARRIER WO;Lo;0;L;;;;;N;;;;;
-15D2;CANADIAN SYLLABICS CARRIER WE;Lo;0;L;;;;;N;;;;;
-15D3;CANADIAN SYLLABICS CARRIER WEE;Lo;0;L;;;;;N;;;;;
-15D4;CANADIAN SYLLABICS CARRIER WI;Lo;0;L;;;;;N;;;;;
-15D5;CANADIAN SYLLABICS CARRIER WA;Lo;0;L;;;;;N;;;;;
-15D6;CANADIAN SYLLABICS CARRIER HWU;Lo;0;L;;;;;N;;;;;
-15D7;CANADIAN SYLLABICS CARRIER HWO;Lo;0;L;;;;;N;;;;;
-15D8;CANADIAN SYLLABICS CARRIER HWE;Lo;0;L;;;;;N;;;;;
-15D9;CANADIAN SYLLABICS CARRIER HWEE;Lo;0;L;;;;;N;;;;;
-15DA;CANADIAN SYLLABICS CARRIER HWI;Lo;0;L;;;;;N;;;;;
-15DB;CANADIAN SYLLABICS CARRIER HWA;Lo;0;L;;;;;N;;;;;
-15DC;CANADIAN SYLLABICS CARRIER THU;Lo;0;L;;;;;N;;;;;
-15DD;CANADIAN SYLLABICS CARRIER THO;Lo;0;L;;;;;N;;;;;
-15DE;CANADIAN SYLLABICS CARRIER THE;Lo;0;L;;;;;N;;;;;
-15DF;CANADIAN SYLLABICS CARRIER THEE;Lo;0;L;;;;;N;;;;;
-15E0;CANADIAN SYLLABICS CARRIER THI;Lo;0;L;;;;;N;;;;;
-15E1;CANADIAN SYLLABICS CARRIER THA;Lo;0;L;;;;;N;;;;;
-15E2;CANADIAN SYLLABICS CARRIER TTU;Lo;0;L;;;;;N;;;;;
-15E3;CANADIAN SYLLABICS CARRIER TTO;Lo;0;L;;;;;N;;;;;
-15E4;CANADIAN SYLLABICS CARRIER TTE;Lo;0;L;;;;;N;;;;;
-15E5;CANADIAN SYLLABICS CARRIER TTEE;Lo;0;L;;;;;N;;;;;
-15E6;CANADIAN SYLLABICS CARRIER TTI;Lo;0;L;;;;;N;;;;;
-15E7;CANADIAN SYLLABICS CARRIER TTA;Lo;0;L;;;;;N;;;;;
-15E8;CANADIAN SYLLABICS CARRIER PU;Lo;0;L;;;;;N;;;;;
-15E9;CANADIAN SYLLABICS CARRIER PO;Lo;0;L;;;;;N;;;;;
-15EA;CANADIAN SYLLABICS CARRIER PE;Lo;0;L;;;;;N;;;;;
-15EB;CANADIAN SYLLABICS CARRIER PEE;Lo;0;L;;;;;N;;;;;
-15EC;CANADIAN SYLLABICS CARRIER PI;Lo;0;L;;;;;N;;;;;
-15ED;CANADIAN SYLLABICS CARRIER PA;Lo;0;L;;;;;N;;;;;
-15EE;CANADIAN SYLLABICS CARRIER P;Lo;0;L;;;;;N;;;;;
-15EF;CANADIAN SYLLABICS CARRIER GU;Lo;0;L;;;;;N;;;;;
-15F0;CANADIAN SYLLABICS CARRIER GO;Lo;0;L;;;;;N;;;;;
-15F1;CANADIAN SYLLABICS CARRIER GE;Lo;0;L;;;;;N;;;;;
-15F2;CANADIAN SYLLABICS CARRIER GEE;Lo;0;L;;;;;N;;;;;
-15F3;CANADIAN SYLLABICS CARRIER GI;Lo;0;L;;;;;N;;;;;
-15F4;CANADIAN SYLLABICS CARRIER GA;Lo;0;L;;;;;N;;;;;
-15F5;CANADIAN SYLLABICS CARRIER KHU;Lo;0;L;;;;;N;;;;;
-15F6;CANADIAN SYLLABICS CARRIER KHO;Lo;0;L;;;;;N;;;;;
-15F7;CANADIAN SYLLABICS CARRIER KHE;Lo;0;L;;;;;N;;;;;
-15F8;CANADIAN SYLLABICS CARRIER KHEE;Lo;0;L;;;;;N;;;;;
-15F9;CANADIAN SYLLABICS CARRIER KHI;Lo;0;L;;;;;N;;;;;
-15FA;CANADIAN SYLLABICS CARRIER KHA;Lo;0;L;;;;;N;;;;;
-15FB;CANADIAN SYLLABICS CARRIER KKU;Lo;0;L;;;;;N;;;;;
-15FC;CANADIAN SYLLABICS CARRIER KKO;Lo;0;L;;;;;N;;;;;
-15FD;CANADIAN SYLLABICS CARRIER KKE;Lo;0;L;;;;;N;;;;;
-15FE;CANADIAN SYLLABICS CARRIER KKEE;Lo;0;L;;;;;N;;;;;
-15FF;CANADIAN SYLLABICS CARRIER KKI;Lo;0;L;;;;;N;;;;;
-1600;CANADIAN SYLLABICS CARRIER KKA;Lo;0;L;;;;;N;;;;;
-1601;CANADIAN SYLLABICS CARRIER KK;Lo;0;L;;;;;N;;;;;
-1602;CANADIAN SYLLABICS CARRIER NU;Lo;0;L;;;;;N;;;;;
-1603;CANADIAN SYLLABICS CARRIER NO;Lo;0;L;;;;;N;;;;;
-1604;CANADIAN SYLLABICS CARRIER NE;Lo;0;L;;;;;N;;;;;
-1605;CANADIAN SYLLABICS CARRIER NEE;Lo;0;L;;;;;N;;;;;
-1606;CANADIAN SYLLABICS CARRIER NI;Lo;0;L;;;;;N;;;;;
-1607;CANADIAN SYLLABICS CARRIER NA;Lo;0;L;;;;;N;;;;;
-1608;CANADIAN SYLLABICS CARRIER MU;Lo;0;L;;;;;N;;;;;
-1609;CANADIAN SYLLABICS CARRIER MO;Lo;0;L;;;;;N;;;;;
-160A;CANADIAN SYLLABICS CARRIER ME;Lo;0;L;;;;;N;;;;;
-160B;CANADIAN SYLLABICS CARRIER MEE;Lo;0;L;;;;;N;;;;;
-160C;CANADIAN SYLLABICS CARRIER MI;Lo;0;L;;;;;N;;;;;
-160D;CANADIAN SYLLABICS CARRIER MA;Lo;0;L;;;;;N;;;;;
-160E;CANADIAN SYLLABICS CARRIER YU;Lo;0;L;;;;;N;;;;;
-160F;CANADIAN SYLLABICS CARRIER YO;Lo;0;L;;;;;N;;;;;
-1610;CANADIAN SYLLABICS CARRIER YE;Lo;0;L;;;;;N;;;;;
-1611;CANADIAN SYLLABICS CARRIER YEE;Lo;0;L;;;;;N;;;;;
-1612;CANADIAN SYLLABICS CARRIER YI;Lo;0;L;;;;;N;;;;;
-1613;CANADIAN SYLLABICS CARRIER YA;Lo;0;L;;;;;N;;;;;
-1614;CANADIAN SYLLABICS CARRIER JU;Lo;0;L;;;;;N;;;;;
-1615;CANADIAN SYLLABICS SAYISI JU;Lo;0;L;;;;;N;;;;;
-1616;CANADIAN SYLLABICS CARRIER JO;Lo;0;L;;;;;N;;;;;
-1617;CANADIAN SYLLABICS CARRIER JE;Lo;0;L;;;;;N;;;;;
-1618;CANADIAN SYLLABICS CARRIER JEE;Lo;0;L;;;;;N;;;;;
-1619;CANADIAN SYLLABICS CARRIER JI;Lo;0;L;;;;;N;;;;;
-161A;CANADIAN SYLLABICS SAYISI JI;Lo;0;L;;;;;N;;;;;
-161B;CANADIAN SYLLABICS CARRIER JA;Lo;0;L;;;;;N;;;;;
-161C;CANADIAN SYLLABICS CARRIER JJU;Lo;0;L;;;;;N;;;;;
-161D;CANADIAN SYLLABICS CARRIER JJO;Lo;0;L;;;;;N;;;;;
-161E;CANADIAN SYLLABICS CARRIER JJE;Lo;0;L;;;;;N;;;;;
-161F;CANADIAN SYLLABICS CARRIER JJEE;Lo;0;L;;;;;N;;;;;
-1620;CANADIAN SYLLABICS CARRIER JJI;Lo;0;L;;;;;N;;;;;
-1621;CANADIAN SYLLABICS CARRIER JJA;Lo;0;L;;;;;N;;;;;
-1622;CANADIAN SYLLABICS CARRIER LU;Lo;0;L;;;;;N;;;;;
-1623;CANADIAN SYLLABICS CARRIER LO;Lo;0;L;;;;;N;;;;;
-1624;CANADIAN SYLLABICS CARRIER LE;Lo;0;L;;;;;N;;;;;
-1625;CANADIAN SYLLABICS CARRIER LEE;Lo;0;L;;;;;N;;;;;
-1626;CANADIAN SYLLABICS CARRIER LI;Lo;0;L;;;;;N;;;;;
-1627;CANADIAN SYLLABICS CARRIER LA;Lo;0;L;;;;;N;;;;;
-1628;CANADIAN SYLLABICS CARRIER DLU;Lo;0;L;;;;;N;;;;;
-1629;CANADIAN SYLLABICS CARRIER DLO;Lo;0;L;;;;;N;;;;;
-162A;CANADIAN SYLLABICS CARRIER DLE;Lo;0;L;;;;;N;;;;;
-162B;CANADIAN SYLLABICS CARRIER DLEE;Lo;0;L;;;;;N;;;;;
-162C;CANADIAN SYLLABICS CARRIER DLI;Lo;0;L;;;;;N;;;;;
-162D;CANADIAN SYLLABICS CARRIER DLA;Lo;0;L;;;;;N;;;;;
-162E;CANADIAN SYLLABICS CARRIER LHU;Lo;0;L;;;;;N;;;;;
-162F;CANADIAN SYLLABICS CARRIER LHO;Lo;0;L;;;;;N;;;;;
-1630;CANADIAN SYLLABICS CARRIER LHE;Lo;0;L;;;;;N;;;;;
-1631;CANADIAN SYLLABICS CARRIER LHEE;Lo;0;L;;;;;N;;;;;
-1632;CANADIAN SYLLABICS CARRIER LHI;Lo;0;L;;;;;N;;;;;
-1633;CANADIAN SYLLABICS CARRIER LHA;Lo;0;L;;;;;N;;;;;
-1634;CANADIAN SYLLABICS CARRIER TLHU;Lo;0;L;;;;;N;;;;;
-1635;CANADIAN SYLLABICS CARRIER TLHO;Lo;0;L;;;;;N;;;;;
-1636;CANADIAN SYLLABICS CARRIER TLHE;Lo;0;L;;;;;N;;;;;
-1637;CANADIAN SYLLABICS CARRIER TLHEE;Lo;0;L;;;;;N;;;;;
-1638;CANADIAN SYLLABICS CARRIER TLHI;Lo;0;L;;;;;N;;;;;
-1639;CANADIAN SYLLABICS CARRIER TLHA;Lo;0;L;;;;;N;;;;;
-163A;CANADIAN SYLLABICS CARRIER TLU;Lo;0;L;;;;;N;;;;;
-163B;CANADIAN SYLLABICS CARRIER TLO;Lo;0;L;;;;;N;;;;;
-163C;CANADIAN SYLLABICS CARRIER TLE;Lo;0;L;;;;;N;;;;;
-163D;CANADIAN SYLLABICS CARRIER TLEE;Lo;0;L;;;;;N;;;;;
-163E;CANADIAN SYLLABICS CARRIER TLI;Lo;0;L;;;;;N;;;;;
-163F;CANADIAN SYLLABICS CARRIER TLA;Lo;0;L;;;;;N;;;;;
-1640;CANADIAN SYLLABICS CARRIER ZU;Lo;0;L;;;;;N;;;;;
-1641;CANADIAN SYLLABICS CARRIER ZO;Lo;0;L;;;;;N;;;;;
-1642;CANADIAN SYLLABICS CARRIER ZE;Lo;0;L;;;;;N;;;;;
-1643;CANADIAN SYLLABICS CARRIER ZEE;Lo;0;L;;;;;N;;;;;
-1644;CANADIAN SYLLABICS CARRIER ZI;Lo;0;L;;;;;N;;;;;
-1645;CANADIAN SYLLABICS CARRIER ZA;Lo;0;L;;;;;N;;;;;
-1646;CANADIAN SYLLABICS CARRIER Z;Lo;0;L;;;;;N;;;;;
-1647;CANADIAN SYLLABICS CARRIER INITIAL Z;Lo;0;L;;;;;N;;;;;
-1648;CANADIAN SYLLABICS CARRIER DZU;Lo;0;L;;;;;N;;;;;
-1649;CANADIAN SYLLABICS CARRIER DZO;Lo;0;L;;;;;N;;;;;
-164A;CANADIAN SYLLABICS CARRIER DZE;Lo;0;L;;;;;N;;;;;
-164B;CANADIAN SYLLABICS CARRIER DZEE;Lo;0;L;;;;;N;;;;;
-164C;CANADIAN SYLLABICS CARRIER DZI;Lo;0;L;;;;;N;;;;;
-164D;CANADIAN SYLLABICS CARRIER DZA;Lo;0;L;;;;;N;;;;;
-164E;CANADIAN SYLLABICS CARRIER SU;Lo;0;L;;;;;N;;;;;
-164F;CANADIAN SYLLABICS CARRIER SO;Lo;0;L;;;;;N;;;;;
-1650;CANADIAN SYLLABICS CARRIER SE;Lo;0;L;;;;;N;;;;;
-1651;CANADIAN SYLLABICS CARRIER SEE;Lo;0;L;;;;;N;;;;;
-1652;CANADIAN SYLLABICS CARRIER SI;Lo;0;L;;;;;N;;;;;
-1653;CANADIAN SYLLABICS CARRIER SA;Lo;0;L;;;;;N;;;;;
-1654;CANADIAN SYLLABICS CARRIER SHU;Lo;0;L;;;;;N;;;;;
-1655;CANADIAN SYLLABICS CARRIER SHO;Lo;0;L;;;;;N;;;;;
-1656;CANADIAN SYLLABICS CARRIER SHE;Lo;0;L;;;;;N;;;;;
-1657;CANADIAN SYLLABICS CARRIER SHEE;Lo;0;L;;;;;N;;;;;
-1658;CANADIAN SYLLABICS CARRIER SHI;Lo;0;L;;;;;N;;;;;
-1659;CANADIAN SYLLABICS CARRIER SHA;Lo;0;L;;;;;N;;;;;
-165A;CANADIAN SYLLABICS CARRIER SH;Lo;0;L;;;;;N;;;;;
-165B;CANADIAN SYLLABICS CARRIER TSU;Lo;0;L;;;;;N;;;;;
-165C;CANADIAN SYLLABICS CARRIER TSO;Lo;0;L;;;;;N;;;;;
-165D;CANADIAN SYLLABICS CARRIER TSE;Lo;0;L;;;;;N;;;;;
-165E;CANADIAN SYLLABICS CARRIER TSEE;Lo;0;L;;;;;N;;;;;
-165F;CANADIAN SYLLABICS CARRIER TSI;Lo;0;L;;;;;N;;;;;
-1660;CANADIAN SYLLABICS CARRIER TSA;Lo;0;L;;;;;N;;;;;
-1661;CANADIAN SYLLABICS CARRIER CHU;Lo;0;L;;;;;N;;;;;
-1662;CANADIAN SYLLABICS CARRIER CHO;Lo;0;L;;;;;N;;;;;
-1663;CANADIAN SYLLABICS CARRIER CHE;Lo;0;L;;;;;N;;;;;
-1664;CANADIAN SYLLABICS CARRIER CHEE;Lo;0;L;;;;;N;;;;;
-1665;CANADIAN SYLLABICS CARRIER CHI;Lo;0;L;;;;;N;;;;;
-1666;CANADIAN SYLLABICS CARRIER CHA;Lo;0;L;;;;;N;;;;;
-1667;CANADIAN SYLLABICS CARRIER TTSU;Lo;0;L;;;;;N;;;;;
-1668;CANADIAN SYLLABICS CARRIER TTSO;Lo;0;L;;;;;N;;;;;
-1669;CANADIAN SYLLABICS CARRIER TTSE;Lo;0;L;;;;;N;;;;;
-166A;CANADIAN SYLLABICS CARRIER TTSEE;Lo;0;L;;;;;N;;;;;
-166B;CANADIAN SYLLABICS CARRIER TTSI;Lo;0;L;;;;;N;;;;;
-166C;CANADIAN SYLLABICS CARRIER TTSA;Lo;0;L;;;;;N;;;;;
-166D;CANADIAN SYLLABICS CHI SIGN;Po;0;L;;;;;N;;;;;
-166E;CANADIAN SYLLABICS FULL STOP;Po;0;L;;;;;N;;;;;
-166F;CANADIAN SYLLABICS QAI;Lo;0;L;;;;;N;;;;;
-1670;CANADIAN SYLLABICS NGAI;Lo;0;L;;;;;N;;;;;
-1671;CANADIAN SYLLABICS NNGI;Lo;0;L;;;;;N;;;;;
-1672;CANADIAN SYLLABICS NNGII;Lo;0;L;;;;;N;;;;;
-1673;CANADIAN SYLLABICS NNGO;Lo;0;L;;;;;N;;;;;
-1674;CANADIAN SYLLABICS NNGOO;Lo;0;L;;;;;N;;;;;
-1675;CANADIAN SYLLABICS NNGA;Lo;0;L;;;;;N;;;;;
-1676;CANADIAN SYLLABICS NNGAA;Lo;0;L;;;;;N;;;;;
-1677;CANADIAN SYLLABICS WOODS-CREE THWEE;Lo;0;L;;;;;N;;;;;
-1678;CANADIAN SYLLABICS WOODS-CREE THWI;Lo;0;L;;;;;N;;;;;
-1679;CANADIAN SYLLABICS WOODS-CREE THWII;Lo;0;L;;;;;N;;;;;
-167A;CANADIAN SYLLABICS WOODS-CREE THWO;Lo;0;L;;;;;N;;;;;
-167B;CANADIAN SYLLABICS WOODS-CREE THWOO;Lo;0;L;;;;;N;;;;;
-167C;CANADIAN SYLLABICS WOODS-CREE THWA;Lo;0;L;;;;;N;;;;;
-167D;CANADIAN SYLLABICS WOODS-CREE THWAA;Lo;0;L;;;;;N;;;;;
-167E;CANADIAN SYLLABICS WOODS-CREE FINAL TH;Lo;0;L;;;;;N;;;;;
-167F;CANADIAN SYLLABICS BLACKFOOT W;Lo;0;L;;;;;N;;;;;
-1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
-1681;OGHAM LETTER BEITH;Lo;0;L;;;;;N;;;;;
-1682;OGHAM LETTER LUIS;Lo;0;L;;;;;N;;;;;
-1683;OGHAM LETTER FEARN;Lo;0;L;;;;;N;;;;;
-1684;OGHAM LETTER SAIL;Lo;0;L;;;;;N;;;;;
-1685;OGHAM LETTER NION;Lo;0;L;;;;;N;;;;;
-1686;OGHAM LETTER UATH;Lo;0;L;;;;;N;;;;;
-1687;OGHAM LETTER DAIR;Lo;0;L;;;;;N;;;;;
-1688;OGHAM LETTER TINNE;Lo;0;L;;;;;N;;;;;
-1689;OGHAM LETTER COLL;Lo;0;L;;;;;N;;;;;
-168A;OGHAM LETTER CEIRT;Lo;0;L;;;;;N;;;;;
-168B;OGHAM LETTER MUIN;Lo;0;L;;;;;N;;;;;
-168C;OGHAM LETTER GORT;Lo;0;L;;;;;N;;;;;
-168D;OGHAM LETTER NGEADAL;Lo;0;L;;;;;N;;;;;
-168E;OGHAM LETTER STRAIF;Lo;0;L;;;;;N;;;;;
-168F;OGHAM LETTER RUIS;Lo;0;L;;;;;N;;;;;
-1690;OGHAM LETTER AILM;Lo;0;L;;;;;N;;;;;
-1691;OGHAM LETTER ONN;Lo;0;L;;;;;N;;;;;
-1692;OGHAM LETTER UR;Lo;0;L;;;;;N;;;;;
-1693;OGHAM LETTER EADHADH;Lo;0;L;;;;;N;;;;;
-1694;OGHAM LETTER IODHADH;Lo;0;L;;;;;N;;;;;
-1695;OGHAM LETTER EABHADH;Lo;0;L;;;;;N;;;;;
-1696;OGHAM LETTER OR;Lo;0;L;;;;;N;;;;;
-1697;OGHAM LETTER UILLEANN;Lo;0;L;;;;;N;;;;;
-1698;OGHAM LETTER IFIN;Lo;0;L;;;;;N;;;;;
-1699;OGHAM LETTER EAMHANCHOLL;Lo;0;L;;;;;N;;;;;
-169A;OGHAM LETTER PEITH;Lo;0;L;;;;;N;;;;;
-169B;OGHAM FEATHER MARK;Ps;0;ON;;;;;Y;;;;;
-169C;OGHAM REVERSED FEATHER MARK;Pe;0;ON;;;;;Y;;;;;
-16A0;RUNIC LETTER FEHU FEOH FE F;Lo;0;L;;;;;N;;;;;
-16A1;RUNIC LETTER V;Lo;0;L;;;;;N;;;;;
-16A2;RUNIC LETTER URUZ UR U;Lo;0;L;;;;;N;;;;;
-16A3;RUNIC LETTER YR;Lo;0;L;;;;;N;;;;;
-16A4;RUNIC LETTER Y;Lo;0;L;;;;;N;;;;;
-16A5;RUNIC LETTER W;Lo;0;L;;;;;N;;;;;
-16A6;RUNIC LETTER THURISAZ THURS THORN;Lo;0;L;;;;;N;;;;;
-16A7;RUNIC LETTER ETH;Lo;0;L;;;;;N;;;;;
-16A8;RUNIC LETTER ANSUZ A;Lo;0;L;;;;;N;;;;;
-16A9;RUNIC LETTER OS O;Lo;0;L;;;;;N;;;;;
-16AA;RUNIC LETTER AC A;Lo;0;L;;;;;N;;;;;
-16AB;RUNIC LETTER AESC;Lo;0;L;;;;;N;;;;;
-16AC;RUNIC LETTER LONG-BRANCH-OSS O;Lo;0;L;;;;;N;;;;;
-16AD;RUNIC LETTER SHORT-TWIG-OSS O;Lo;0;L;;;;;N;;;;;
-16AE;RUNIC LETTER O;Lo;0;L;;;;;N;;;;;
-16AF;RUNIC LETTER OE;Lo;0;L;;;;;N;;;;;
-16B0;RUNIC LETTER ON;Lo;0;L;;;;;N;;;;;
-16B1;RUNIC LETTER RAIDO RAD REID R;Lo;0;L;;;;;N;;;;;
-16B2;RUNIC LETTER KAUNA;Lo;0;L;;;;;N;;;;;
-16B3;RUNIC LETTER CEN;Lo;0;L;;;;;N;;;;;
-16B4;RUNIC LETTER KAUN K;Lo;0;L;;;;;N;;;;;
-16B5;RUNIC LETTER G;Lo;0;L;;;;;N;;;;;
-16B6;RUNIC LETTER ENG;Lo;0;L;;;;;N;;;;;
-16B7;RUNIC LETTER GEBO GYFU G;Lo;0;L;;;;;N;;;;;
-16B8;RUNIC LETTER GAR;Lo;0;L;;;;;N;;;;;
-16B9;RUNIC LETTER WUNJO WYNN W;Lo;0;L;;;;;N;;;;;
-16BA;RUNIC LETTER HAGLAZ H;Lo;0;L;;;;;N;;;;;
-16BB;RUNIC LETTER HAEGL H;Lo;0;L;;;;;N;;;;;
-16BC;RUNIC LETTER LONG-BRANCH-HAGALL H;Lo;0;L;;;;;N;;;;;
-16BD;RUNIC LETTER SHORT-TWIG-HAGALL H;Lo;0;L;;;;;N;;;;;
-16BE;RUNIC LETTER NAUDIZ NYD NAUD N;Lo;0;L;;;;;N;;;;;
-16BF;RUNIC LETTER SHORT-TWIG-NAUD N;Lo;0;L;;;;;N;;;;;
-16C0;RUNIC LETTER DOTTED-N;Lo;0;L;;;;;N;;;;;
-16C1;RUNIC LETTER ISAZ IS ISS I;Lo;0;L;;;;;N;;;;;
-16C2;RUNIC LETTER E;Lo;0;L;;;;;N;;;;;
-16C3;RUNIC LETTER JERAN J;Lo;0;L;;;;;N;;;;;
-16C4;RUNIC LETTER GER;Lo;0;L;;;;;N;;;;;
-16C5;RUNIC LETTER LONG-BRANCH-AR AE;Lo;0;L;;;;;N;;;;;
-16C6;RUNIC LETTER SHORT-TWIG-AR A;Lo;0;L;;;;;N;;;;;
-16C7;RUNIC LETTER IWAZ EOH;Lo;0;L;;;;;N;;;;;
-16C8;RUNIC LETTER PERTHO PEORTH P;Lo;0;L;;;;;N;;;;;
-16C9;RUNIC LETTER ALGIZ EOLHX;Lo;0;L;;;;;N;;;;;
-16CA;RUNIC LETTER SOWILO S;Lo;0;L;;;;;N;;;;;
-16CB;RUNIC LETTER SIGEL LONG-BRANCH-SOL S;Lo;0;L;;;;;N;;;;;
-16CC;RUNIC LETTER SHORT-TWIG-SOL S;Lo;0;L;;;;;N;;;;;
-16CD;RUNIC LETTER C;Lo;0;L;;;;;N;;;;;
-16CE;RUNIC LETTER Z;Lo;0;L;;;;;N;;;;;
-16CF;RUNIC LETTER TIWAZ TIR TYR T;Lo;0;L;;;;;N;;;;;
-16D0;RUNIC LETTER SHORT-TWIG-TYR T;Lo;0;L;;;;;N;;;;;
-16D1;RUNIC LETTER D;Lo;0;L;;;;;N;;;;;
-16D2;RUNIC LETTER BERKANAN BEORC BJARKAN B;Lo;0;L;;;;;N;;;;;
-16D3;RUNIC LETTER SHORT-TWIG-BJARKAN B;Lo;0;L;;;;;N;;;;;
-16D4;RUNIC LETTER DOTTED-P;Lo;0;L;;;;;N;;;;;
-16D5;RUNIC LETTER OPEN-P;Lo;0;L;;;;;N;;;;;
-16D6;RUNIC LETTER EHWAZ EH E;Lo;0;L;;;;;N;;;;;
-16D7;RUNIC LETTER MANNAZ MAN M;Lo;0;L;;;;;N;;;;;
-16D8;RUNIC LETTER LONG-BRANCH-MADR M;Lo;0;L;;;;;N;;;;;
-16D9;RUNIC LETTER SHORT-TWIG-MADR M;Lo;0;L;;;;;N;;;;;
-16DA;RUNIC LETTER LAUKAZ LAGU LOGR L;Lo;0;L;;;;;N;;;;;
-16DB;RUNIC LETTER DOTTED-L;Lo;0;L;;;;;N;;;;;
-16DC;RUNIC LETTER INGWAZ;Lo;0;L;;;;;N;;;;;
-16DD;RUNIC LETTER ING;Lo;0;L;;;;;N;;;;;
-16DE;RUNIC LETTER DAGAZ DAEG D;Lo;0;L;;;;;N;;;;;
-16DF;RUNIC LETTER OTHALAN ETHEL O;Lo;0;L;;;;;N;;;;;
-16E0;RUNIC LETTER EAR;Lo;0;L;;;;;N;;;;;
-16E1;RUNIC LETTER IOR;Lo;0;L;;;;;N;;;;;
-16E2;RUNIC LETTER CWEORTH;Lo;0;L;;;;;N;;;;;
-16E3;RUNIC LETTER CALC;Lo;0;L;;;;;N;;;;;
-16E4;RUNIC LETTER CEALC;Lo;0;L;;;;;N;;;;;
-16E5;RUNIC LETTER STAN;Lo;0;L;;;;;N;;;;;
-16E6;RUNIC LETTER LONG-BRANCH-YR;Lo;0;L;;;;;N;;;;;
-16E7;RUNIC LETTER SHORT-TWIG-YR;Lo;0;L;;;;;N;;;;;
-16E8;RUNIC LETTER ICELANDIC-YR;Lo;0;L;;;;;N;;;;;
-16E9;RUNIC LETTER Q;Lo;0;L;;;;;N;;;;;
-16EA;RUNIC LETTER X;Lo;0;L;;;;;N;;;;;
-16EB;RUNIC SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;;
-16EC;RUNIC MULTIPLE PUNCTUATION;Po;0;L;;;;;N;;;;;
-16ED;RUNIC CROSS PUNCTUATION;Po;0;L;;;;;N;;;;;
-16EE;RUNIC ARLAUG SYMBOL;Nl;0;L;;;;17;N;;;;;
-16EF;RUNIC TVIMADUR SYMBOL;Nl;0;L;;;;18;N;;;;;
-16F0;RUNIC BELGTHOR SYMBOL;Nl;0;L;;;;19;N;;;;;
-1700;TAGALOG LETTER A;Lo;0;L;;;;;N;;;;;
-1701;TAGALOG LETTER I;Lo;0;L;;;;;N;;;;;
-1702;TAGALOG LETTER U;Lo;0;L;;;;;N;;;;;
-1703;TAGALOG LETTER KA;Lo;0;L;;;;;N;;;;;
-1704;TAGALOG LETTER GA;Lo;0;L;;;;;N;;;;;
-1705;TAGALOG LETTER NGA;Lo;0;L;;;;;N;;;;;
-1706;TAGALOG LETTER TA;Lo;0;L;;;;;N;;;;;
-1707;TAGALOG LETTER DA;Lo;0;L;;;;;N;;;;;
-1708;TAGALOG LETTER NA;Lo;0;L;;;;;N;;;;;
-1709;TAGALOG LETTER PA;Lo;0;L;;;;;N;;;;;
-170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;;
-170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;;
-170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;;
-170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;;
-170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;;
-1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;;
-1711;TAGALOG LETTER HA;Lo;0;L;;;;;N;;;;;
-1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;;
-1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;;
-1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;;
-1723;HANUNOO LETTER KA;Lo;0;L;;;;;N;;;;;
-1724;HANUNOO LETTER GA;Lo;0;L;;;;;N;;;;;
-1725;HANUNOO LETTER NGA;Lo;0;L;;;;;N;;;;;
-1726;HANUNOO LETTER TA;Lo;0;L;;;;;N;;;;;
-1727;HANUNOO LETTER DA;Lo;0;L;;;;;N;;;;;
-1728;HANUNOO LETTER NA;Lo;0;L;;;;;N;;;;;
-1729;HANUNOO LETTER PA;Lo;0;L;;;;;N;;;;;
-172A;HANUNOO LETTER BA;Lo;0;L;;;;;N;;;;;
-172B;HANUNOO LETTER MA;Lo;0;L;;;;;N;;;;;
-172C;HANUNOO LETTER YA;Lo;0;L;;;;;N;;;;;
-172D;HANUNOO LETTER RA;Lo;0;L;;;;;N;;;;;
-172E;HANUNOO LETTER LA;Lo;0;L;;;;;N;;;;;
-172F;HANUNOO LETTER WA;Lo;0;L;;;;;N;;;;;
-1730;HANUNOO LETTER SA;Lo;0;L;;;;;N;;;;;
-1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;;
-1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;;
-1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;;
-1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;;
-1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;;
-1741;BUHID LETTER I;Lo;0;L;;;;;N;;;;;
-1742;BUHID LETTER U;Lo;0;L;;;;;N;;;;;
-1743;BUHID LETTER KA;Lo;0;L;;;;;N;;;;;
-1744;BUHID LETTER GA;Lo;0;L;;;;;N;;;;;
-1745;BUHID LETTER NGA;Lo;0;L;;;;;N;;;;;
-1746;BUHID LETTER TA;Lo;0;L;;;;;N;;;;;
-1747;BUHID LETTER DA;Lo;0;L;;;;;N;;;;;
-1748;BUHID LETTER NA;Lo;0;L;;;;;N;;;;;
-1749;BUHID LETTER PA;Lo;0;L;;;;;N;;;;;
-174A;BUHID LETTER BA;Lo;0;L;;;;;N;;;;;
-174B;BUHID LETTER MA;Lo;0;L;;;;;N;;;;;
-174C;BUHID LETTER YA;Lo;0;L;;;;;N;;;;;
-174D;BUHID LETTER RA;Lo;0;L;;;;;N;;;;;
-174E;BUHID LETTER LA;Lo;0;L;;;;;N;;;;;
-174F;BUHID LETTER WA;Lo;0;L;;;;;N;;;;;
-1750;BUHID LETTER SA;Lo;0;L;;;;;N;;;;;
-1751;BUHID LETTER HA;Lo;0;L;;;;;N;;;;;
-1752;BUHID VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-1753;BUHID VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1760;TAGBANWA LETTER A;Lo;0;L;;;;;N;;;;;
-1761;TAGBANWA LETTER I;Lo;0;L;;;;;N;;;;;
-1762;TAGBANWA LETTER U;Lo;0;L;;;;;N;;;;;
-1763;TAGBANWA LETTER KA;Lo;0;L;;;;;N;;;;;
-1764;TAGBANWA LETTER GA;Lo;0;L;;;;;N;;;;;
-1765;TAGBANWA LETTER NGA;Lo;0;L;;;;;N;;;;;
-1766;TAGBANWA LETTER TA;Lo;0;L;;;;;N;;;;;
-1767;TAGBANWA LETTER DA;Lo;0;L;;;;;N;;;;;
-1768;TAGBANWA LETTER NA;Lo;0;L;;;;;N;;;;;
-1769;TAGBANWA LETTER PA;Lo;0;L;;;;;N;;;;;
-176A;TAGBANWA LETTER BA;Lo;0;L;;;;;N;;;;;
-176B;TAGBANWA LETTER MA;Lo;0;L;;;;;N;;;;;
-176C;TAGBANWA LETTER YA;Lo;0;L;;;;;N;;;;;
-176E;TAGBANWA LETTER LA;Lo;0;L;;;;;N;;;;;
-176F;TAGBANWA LETTER WA;Lo;0;L;;;;;N;;;;;
-1770;TAGBANWA LETTER SA;Lo;0;L;;;;;N;;;;;
-1772;TAGBANWA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-1773;TAGBANWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1780;KHMER LETTER KA;Lo;0;L;;;;;N;;;;;
-1781;KHMER LETTER KHA;Lo;0;L;;;;;N;;;;;
-1782;KHMER LETTER KO;Lo;0;L;;;;;N;;;;;
-1783;KHMER LETTER KHO;Lo;0;L;;;;;N;;;;;
-1784;KHMER LETTER NGO;Lo;0;L;;;;;N;;;;;
-1785;KHMER LETTER CA;Lo;0;L;;;;;N;;;;;
-1786;KHMER LETTER CHA;Lo;0;L;;;;;N;;;;;
-1787;KHMER LETTER CO;Lo;0;L;;;;;N;;;;;
-1788;KHMER LETTER CHO;Lo;0;L;;;;;N;;;;;
-1789;KHMER LETTER NYO;Lo;0;L;;;;;N;;;;;
-178A;KHMER LETTER DA;Lo;0;L;;;;;N;;;;;
-178B;KHMER LETTER TTHA;Lo;0;L;;;;;N;;;;;
-178C;KHMER LETTER DO;Lo;0;L;;;;;N;;;;;
-178D;KHMER LETTER TTHO;Lo;0;L;;;;;N;;;;;
-178E;KHMER LETTER NNO;Lo;0;L;;;;;N;;;;;
-178F;KHMER LETTER TA;Lo;0;L;;;;;N;;;;;
-1790;KHMER LETTER THA;Lo;0;L;;;;;N;;;;;
-1791;KHMER LETTER TO;Lo;0;L;;;;;N;;;;;
-1792;KHMER LETTER THO;Lo;0;L;;;;;N;;;;;
-1793;KHMER LETTER NO;Lo;0;L;;;;;N;;;;;
-1794;KHMER LETTER BA;Lo;0;L;;;;;N;;;;;
-1795;KHMER LETTER PHA;Lo;0;L;;;;;N;;;;;
-1796;KHMER LETTER PO;Lo;0;L;;;;;N;;;;;
-1797;KHMER LETTER PHO;Lo;0;L;;;;;N;;;;;
-1798;KHMER LETTER MO;Lo;0;L;;;;;N;;;;;
-1799;KHMER LETTER YO;Lo;0;L;;;;;N;;;;;
-179A;KHMER LETTER RO;Lo;0;L;;;;;N;;;;;
-179B;KHMER LETTER LO;Lo;0;L;;;;;N;;;;;
-179C;KHMER LETTER VO;Lo;0;L;;;;;N;;;;;
-179D;KHMER LETTER SHA;Lo;0;L;;;;;N;;;;;
-179E;KHMER LETTER SSO;Lo;0;L;;;;;N;;;;;
-179F;KHMER LETTER SA;Lo;0;L;;;;;N;;;;;
-17A0;KHMER LETTER HA;Lo;0;L;;;;;N;;;;;
-17A1;KHMER LETTER LA;Lo;0;L;;;;;N;;;;;
-17A2;KHMER LETTER QA;Lo;0;L;;;;;N;;;;;
-17A3;KHMER INDEPENDENT VOWEL QAQ;Lo;0;L;;;;;N;;;;;
-17A4;KHMER INDEPENDENT VOWEL QAA;Lo;0;L;;;;;N;;;;;
-17A5;KHMER INDEPENDENT VOWEL QI;Lo;0;L;;;;;N;;;;;
-17A6;KHMER INDEPENDENT VOWEL QII;Lo;0;L;;;;;N;;;;;
-17A7;KHMER INDEPENDENT VOWEL QU;Lo;0;L;;;;;N;;;;;
-17A8;KHMER INDEPENDENT VOWEL QUK;Lo;0;L;;;;;N;;;;;
-17A9;KHMER INDEPENDENT VOWEL QUU;Lo;0;L;;;;;N;;;;;
-17AA;KHMER INDEPENDENT VOWEL QUUV;Lo;0;L;;;;;N;;;;;
-17AB;KHMER INDEPENDENT VOWEL RY;Lo;0;L;;;;;N;;;;;
-17AC;KHMER INDEPENDENT VOWEL RYY;Lo;0;L;;;;;N;;;;;
-17AD;KHMER INDEPENDENT VOWEL LY;Lo;0;L;;;;;N;;;;;
-17AE;KHMER INDEPENDENT VOWEL LYY;Lo;0;L;;;;;N;;;;;
-17AF;KHMER INDEPENDENT VOWEL QE;Lo;0;L;;;;;N;;;;;
-17B0;KHMER INDEPENDENT VOWEL QAI;Lo;0;L;;;;;N;;;;;
-17B1;KHMER INDEPENDENT VOWEL QOO TYPE ONE;Lo;0;L;;;;;N;;;;;
-17B2;KHMER INDEPENDENT VOWEL QOO TYPE TWO;Lo;0;L;;;;;N;;;;;
-17B3;KHMER INDEPENDENT VOWEL QAU;Lo;0;L;;;;;N;;;;;
-17B4;KHMER VOWEL INHERENT AQ;Mn;0;NSM;;;;;N;;;;;
-17B5;KHMER VOWEL INHERENT AA;Mn;0;NSM;;;;;N;;;;;
-17B6;KHMER VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-17B7;KHMER VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-17B8;KHMER VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-17B9;KHMER VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;;
-17BA;KHMER VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;;
-17BB;KHMER VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-17BC;KHMER VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-17BD;KHMER VOWEL SIGN UA;Mn;0;NSM;;;;;N;;;;;
-17BE;KHMER VOWEL SIGN OE;Mc;0;L;;;;;N;;;;;
-17BF;KHMER VOWEL SIGN YA;Mc;0;L;;;;;N;;;;;
-17C0;KHMER VOWEL SIGN IE;Mc;0;L;;;;;N;;;;;
-17C1;KHMER VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-17C2;KHMER VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
-17C3;KHMER VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-17C4;KHMER VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
-17C5;KHMER VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-17C6;KHMER SIGN NIKAHIT;Mn;0;NSM;;;;;N;;;;;
-17C7;KHMER SIGN REAHMUK;Mc;0;L;;;;;N;;;;;
-17C8;KHMER SIGN YUUKALEAPINTU;Mc;0;L;;;;;N;;;;;
-17C9;KHMER SIGN MUUSIKATOAN;Mn;0;NSM;;;;;N;;;;;
-17CA;KHMER SIGN TRIISAP;Mn;0;NSM;;;;;N;;;;;
-17CB;KHMER SIGN BANTOC;Mn;0;NSM;;;;;N;;;;;
-17CC;KHMER SIGN ROBAT;Mn;0;NSM;;;;;N;;;;;
-17CD;KHMER SIGN TOANDAKHIAT;Mn;0;NSM;;;;;N;;;;;
-17CE;KHMER SIGN KAKABAT;Mn;0;NSM;;;;;N;;;;;
-17CF;KHMER SIGN AHSDA;Mn;0;NSM;;;;;N;;;;;
-17D0;KHMER SIGN SAMYOK SANNYA;Mn;0;NSM;;;;;N;;;;;
-17D1;KHMER SIGN VIRIAM;Mn;0;NSM;;;;;N;;;;;
-17D2;KHMER SIGN COENG;Mn;9;NSM;;;;;N;;;;;
-17D3;KHMER SIGN BATHAMASAT;Mn;0;NSM;;;;;N;;;;;
-17D4;KHMER SIGN KHAN;Po;0;L;;;;;N;;;;;
-17D5;KHMER SIGN BARIYOOSAN;Po;0;L;;;;;N;;;;;
-17D6;KHMER SIGN CAMNUC PII KUUH;Po;0;L;;;;;N;;;;;
-17D7;KHMER SIGN LEK TOO;Lm;0;L;;;;;N;;;;;
-17D8;KHMER SIGN BEYYAL;Po;0;L;;;;;N;;;;;
-17D9;KHMER SIGN PHNAEK MUAN;Po;0;L;;;;;N;;;;;
-17DA;KHMER SIGN KOOMUUT;Po;0;L;;;;;N;;;;;
-17DB;KHMER CURRENCY SYMBOL RIEL;Sc;0;ET;;;;;N;;;;;
-17DC;KHMER SIGN AVAKRAHASANYA;Lo;0;L;;;;;N;;;;;
-17DD;KHMER SIGN ATTHACAN;Mn;230;NSM;;;;;N;;;;;
-17E0;KHMER DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-17E1;KHMER DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-17E2;KHMER DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-17E3;KHMER DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-17E4;KHMER DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-17E5;KHMER DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-17E6;KHMER DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-17E7;KHMER DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-17E8;KHMER DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-17E9;KHMER DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-17F0;KHMER SYMBOL LEK ATTAK SON;No;0;ON;;;;0;N;;;;;
-17F1;KHMER SYMBOL LEK ATTAK MUOY;No;0;ON;;;;1;N;;;;;
-17F2;KHMER SYMBOL LEK ATTAK PII;No;0;ON;;;;2;N;;;;;
-17F3;KHMER SYMBOL LEK ATTAK BEI;No;0;ON;;;;3;N;;;;;
-17F4;KHMER SYMBOL LEK ATTAK BUON;No;0;ON;;;;4;N;;;;;
-17F5;KHMER SYMBOL LEK ATTAK PRAM;No;0;ON;;;;5;N;;;;;
-17F6;KHMER SYMBOL LEK ATTAK PRAM-MUOY;No;0;ON;;;;6;N;;;;;
-17F7;KHMER SYMBOL LEK ATTAK PRAM-PII;No;0;ON;;;;7;N;;;;;
-17F8;KHMER SYMBOL LEK ATTAK PRAM-BEI;No;0;ON;;;;8;N;;;;;
-17F9;KHMER SYMBOL LEK ATTAK PRAM-BUON;No;0;ON;;;;9;N;;;;;
-1800;MONGOLIAN BIRGA;Po;0;ON;;;;;N;;;;;
-1801;MONGOLIAN ELLIPSIS;Po;0;ON;;;;;N;;;;;
-1802;MONGOLIAN COMMA;Po;0;ON;;;;;N;;;;;
-1803;MONGOLIAN FULL STOP;Po;0;ON;;;;;N;;;;;
-1804;MONGOLIAN COLON;Po;0;ON;;;;;N;;;;;
-1805;MONGOLIAN FOUR DOTS;Po;0;ON;;;;;N;;;;;
-1806;MONGOLIAN TODO SOFT HYPHEN;Pd;0;ON;;;;;N;;;;;
-1807;MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER;Po;0;ON;;;;;N;;;;;
-1808;MONGOLIAN MANCHU COMMA;Po;0;ON;;;;;N;;;;;
-1809;MONGOLIAN MANCHU FULL STOP;Po;0;ON;;;;;N;;;;;
-180A;MONGOLIAN NIRUGU;Po;0;ON;;;;;N;;;;;
-180B;MONGOLIAN FREE VARIATION SELECTOR ONE;Mn;0;NSM;;;;;N;;;;;
-180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;;
-180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;;
-180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
-1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1813;MONGOLIAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1814;MONGOLIAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1815;MONGOLIAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1816;MONGOLIAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1817;MONGOLIAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1818;MONGOLIAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1819;MONGOLIAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-1820;MONGOLIAN LETTER A;Lo;0;L;;;;;N;;;;;
-1821;MONGOLIAN LETTER E;Lo;0;L;;;;;N;;;;;
-1822;MONGOLIAN LETTER I;Lo;0;L;;;;;N;;;;;
-1823;MONGOLIAN LETTER O;Lo;0;L;;;;;N;;;;;
-1824;MONGOLIAN LETTER U;Lo;0;L;;;;;N;;;;;
-1825;MONGOLIAN LETTER OE;Lo;0;L;;;;;N;;;;;
-1826;MONGOLIAN LETTER UE;Lo;0;L;;;;;N;;;;;
-1827;MONGOLIAN LETTER EE;Lo;0;L;;;;;N;;;;;
-1828;MONGOLIAN LETTER NA;Lo;0;L;;;;;N;;;;;
-1829;MONGOLIAN LETTER ANG;Lo;0;L;;;;;N;;;;;
-182A;MONGOLIAN LETTER BA;Lo;0;L;;;;;N;;;;;
-182B;MONGOLIAN LETTER PA;Lo;0;L;;;;;N;;;;;
-182C;MONGOLIAN LETTER QA;Lo;0;L;;;;;N;;;;;
-182D;MONGOLIAN LETTER GA;Lo;0;L;;;;;N;;;;;
-182E;MONGOLIAN LETTER MA;Lo;0;L;;;;;N;;;;;
-182F;MONGOLIAN LETTER LA;Lo;0;L;;;;;N;;;;;
-1830;MONGOLIAN LETTER SA;Lo;0;L;;;;;N;;;;;
-1831;MONGOLIAN LETTER SHA;Lo;0;L;;;;;N;;;;;
-1832;MONGOLIAN LETTER TA;Lo;0;L;;;;;N;;;;;
-1833;MONGOLIAN LETTER DA;Lo;0;L;;;;;N;;;;;
-1834;MONGOLIAN LETTER CHA;Lo;0;L;;;;;N;;;;;
-1835;MONGOLIAN LETTER JA;Lo;0;L;;;;;N;;;;;
-1836;MONGOLIAN LETTER YA;Lo;0;L;;;;;N;;;;;
-1837;MONGOLIAN LETTER RA;Lo;0;L;;;;;N;;;;;
-1838;MONGOLIAN LETTER WA;Lo;0;L;;;;;N;;;;;
-1839;MONGOLIAN LETTER FA;Lo;0;L;;;;;N;;;;;
-183A;MONGOLIAN LETTER KA;Lo;0;L;;;;;N;;;;;
-183B;MONGOLIAN LETTER KHA;Lo;0;L;;;;;N;;;;;
-183C;MONGOLIAN LETTER TSA;Lo;0;L;;;;;N;;;;;
-183D;MONGOLIAN LETTER ZA;Lo;0;L;;;;;N;;;;;
-183E;MONGOLIAN LETTER HAA;Lo;0;L;;;;;N;;;;;
-183F;MONGOLIAN LETTER ZRA;Lo;0;L;;;;;N;;;;;
-1840;MONGOLIAN LETTER LHA;Lo;0;L;;;;;N;;;;;
-1841;MONGOLIAN LETTER ZHI;Lo;0;L;;;;;N;;;;;
-1842;MONGOLIAN LETTER CHI;Lo;0;L;;;;;N;;;;;
-1843;MONGOLIAN LETTER TODO LONG VOWEL SIGN;Lm;0;L;;;;;N;;;;;
-1844;MONGOLIAN LETTER TODO E;Lo;0;L;;;;;N;;;;;
-1845;MONGOLIAN LETTER TODO I;Lo;0;L;;;;;N;;;;;
-1846;MONGOLIAN LETTER TODO O;Lo;0;L;;;;;N;;;;;
-1847;MONGOLIAN LETTER TODO U;Lo;0;L;;;;;N;;;;;
-1848;MONGOLIAN LETTER TODO OE;Lo;0;L;;;;;N;;;;;
-1849;MONGOLIAN LETTER TODO UE;Lo;0;L;;;;;N;;;;;
-184A;MONGOLIAN LETTER TODO ANG;Lo;0;L;;;;;N;;;;;
-184B;MONGOLIAN LETTER TODO BA;Lo;0;L;;;;;N;;;;;
-184C;MONGOLIAN LETTER TODO PA;Lo;0;L;;;;;N;;;;;
-184D;MONGOLIAN LETTER TODO QA;Lo;0;L;;;;;N;;;;;
-184E;MONGOLIAN LETTER TODO GA;Lo;0;L;;;;;N;;;;;
-184F;MONGOLIAN LETTER TODO MA;Lo;0;L;;;;;N;;;;;
-1850;MONGOLIAN LETTER TODO TA;Lo;0;L;;;;;N;;;;;
-1851;MONGOLIAN LETTER TODO DA;Lo;0;L;;;;;N;;;;;
-1852;MONGOLIAN LETTER TODO CHA;Lo;0;L;;;;;N;;;;;
-1853;MONGOLIAN LETTER TODO JA;Lo;0;L;;;;;N;;;;;
-1854;MONGOLIAN LETTER TODO TSA;Lo;0;L;;;;;N;;;;;
-1855;MONGOLIAN LETTER TODO YA;Lo;0;L;;;;;N;;;;;
-1856;MONGOLIAN LETTER TODO WA;Lo;0;L;;;;;N;;;;;
-1857;MONGOLIAN LETTER TODO KA;Lo;0;L;;;;;N;;;;;
-1858;MONGOLIAN LETTER TODO GAA;Lo;0;L;;;;;N;;;;;
-1859;MONGOLIAN LETTER TODO HAA;Lo;0;L;;;;;N;;;;;
-185A;MONGOLIAN LETTER TODO JIA;Lo;0;L;;;;;N;;;;;
-185B;MONGOLIAN LETTER TODO NIA;Lo;0;L;;;;;N;;;;;
-185C;MONGOLIAN LETTER TODO DZA;Lo;0;L;;;;;N;;;;;
-185D;MONGOLIAN LETTER SIBE E;Lo;0;L;;;;;N;;;;;
-185E;MONGOLIAN LETTER SIBE I;Lo;0;L;;;;;N;;;;;
-185F;MONGOLIAN LETTER SIBE IY;Lo;0;L;;;;;N;;;;;
-1860;MONGOLIAN LETTER SIBE UE;Lo;0;L;;;;;N;;;;;
-1861;MONGOLIAN LETTER SIBE U;Lo;0;L;;;;;N;;;;;
-1862;MONGOLIAN LETTER SIBE ANG;Lo;0;L;;;;;N;;;;;
-1863;MONGOLIAN LETTER SIBE KA;Lo;0;L;;;;;N;;;;;
-1864;MONGOLIAN LETTER SIBE GA;Lo;0;L;;;;;N;;;;;
-1865;MONGOLIAN LETTER SIBE HA;Lo;0;L;;;;;N;;;;;
-1866;MONGOLIAN LETTER SIBE PA;Lo;0;L;;;;;N;;;;;
-1867;MONGOLIAN LETTER SIBE SHA;Lo;0;L;;;;;N;;;;;
-1868;MONGOLIAN LETTER SIBE TA;Lo;0;L;;;;;N;;;;;
-1869;MONGOLIAN LETTER SIBE DA;Lo;0;L;;;;;N;;;;;
-186A;MONGOLIAN LETTER SIBE JA;Lo;0;L;;;;;N;;;;;
-186B;MONGOLIAN LETTER SIBE FA;Lo;0;L;;;;;N;;;;;
-186C;MONGOLIAN LETTER SIBE GAA;Lo;0;L;;;;;N;;;;;
-186D;MONGOLIAN LETTER SIBE HAA;Lo;0;L;;;;;N;;;;;
-186E;MONGOLIAN LETTER SIBE TSA;Lo;0;L;;;;;N;;;;;
-186F;MONGOLIAN LETTER SIBE ZA;Lo;0;L;;;;;N;;;;;
-1870;MONGOLIAN LETTER SIBE RAA;Lo;0;L;;;;;N;;;;;
-1871;MONGOLIAN LETTER SIBE CHA;Lo;0;L;;;;;N;;;;;
-1872;MONGOLIAN LETTER SIBE ZHA;Lo;0;L;;;;;N;;;;;
-1873;MONGOLIAN LETTER MANCHU I;Lo;0;L;;;;;N;;;;;
-1874;MONGOLIAN LETTER MANCHU KA;Lo;0;L;;;;;N;;;;;
-1875;MONGOLIAN LETTER MANCHU RA;Lo;0;L;;;;;N;;;;;
-1876;MONGOLIAN LETTER MANCHU FA;Lo;0;L;;;;;N;;;;;
-1877;MONGOLIAN LETTER MANCHU ZHA;Lo;0;L;;;;;N;;;;;
-1880;MONGOLIAN LETTER ALI GALI ANUSVARA ONE;Lo;0;L;;;;;N;;;;;
-1881;MONGOLIAN LETTER ALI GALI VISARGA ONE;Lo;0;L;;;;;N;;;;;
-1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;;
-1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;;
-1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;;
-1885;MONGOLIAN LETTER ALI GALI BALUDA;Lo;0;L;;;;;N;;;;;
-1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Lo;0;L;;;;;N;;;;;
-1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;;
-1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;;
-1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;;
-188A;MONGOLIAN LETTER ALI GALI NGA;Lo;0;L;;;;;N;;;;;
-188B;MONGOLIAN LETTER ALI GALI CA;Lo;0;L;;;;;N;;;;;
-188C;MONGOLIAN LETTER ALI GALI TTA;Lo;0;L;;;;;N;;;;;
-188D;MONGOLIAN LETTER ALI GALI TTHA;Lo;0;L;;;;;N;;;;;
-188E;MONGOLIAN LETTER ALI GALI DDA;Lo;0;L;;;;;N;;;;;
-188F;MONGOLIAN LETTER ALI GALI NNA;Lo;0;L;;;;;N;;;;;
-1890;MONGOLIAN LETTER ALI GALI TA;Lo;0;L;;;;;N;;;;;
-1891;MONGOLIAN LETTER ALI GALI DA;Lo;0;L;;;;;N;;;;;
-1892;MONGOLIAN LETTER ALI GALI PA;Lo;0;L;;;;;N;;;;;
-1893;MONGOLIAN LETTER ALI GALI PHA;Lo;0;L;;;;;N;;;;;
-1894;MONGOLIAN LETTER ALI GALI SSA;Lo;0;L;;;;;N;;;;;
-1895;MONGOLIAN LETTER ALI GALI ZHA;Lo;0;L;;;;;N;;;;;
-1896;MONGOLIAN LETTER ALI GALI ZA;Lo;0;L;;;;;N;;;;;
-1897;MONGOLIAN LETTER ALI GALI AH;Lo;0;L;;;;;N;;;;;
-1898;MONGOLIAN LETTER TODO ALI GALI TA;Lo;0;L;;;;;N;;;;;
-1899;MONGOLIAN LETTER TODO ALI GALI ZHA;Lo;0;L;;;;;N;;;;;
-189A;MONGOLIAN LETTER MANCHU ALI GALI GHA;Lo;0;L;;;;;N;;;;;
-189B;MONGOLIAN LETTER MANCHU ALI GALI NGA;Lo;0;L;;;;;N;;;;;
-189C;MONGOLIAN LETTER MANCHU ALI GALI CA;Lo;0;L;;;;;N;;;;;
-189D;MONGOLIAN LETTER MANCHU ALI GALI JHA;Lo;0;L;;;;;N;;;;;
-189E;MONGOLIAN LETTER MANCHU ALI GALI TTA;Lo;0;L;;;;;N;;;;;
-189F;MONGOLIAN LETTER MANCHU ALI GALI DDHA;Lo;0;L;;;;;N;;;;;
-18A0;MONGOLIAN LETTER MANCHU ALI GALI TA;Lo;0;L;;;;;N;;;;;
-18A1;MONGOLIAN LETTER MANCHU ALI GALI DHA;Lo;0;L;;;;;N;;;;;
-18A2;MONGOLIAN LETTER MANCHU ALI GALI SSA;Lo;0;L;;;;;N;;;;;
-18A3;MONGOLIAN LETTER MANCHU ALI GALI CYA;Lo;0;L;;;;;N;;;;;
-18A4;MONGOLIAN LETTER MANCHU ALI GALI ZHA;Lo;0;L;;;;;N;;;;;
-18A5;MONGOLIAN LETTER MANCHU ALI GALI ZA;Lo;0;L;;;;;N;;;;;
-18A6;MONGOLIAN LETTER ALI GALI HALF U;Lo;0;L;;;;;N;;;;;
-18A7;MONGOLIAN LETTER ALI GALI HALF YA;Lo;0;L;;;;;N;;;;;
-18A8;MONGOLIAN LETTER MANCHU ALI GALI BHA;Lo;0;L;;;;;N;;;;;
-18A9;MONGOLIAN LETTER ALI GALI DAGALGA;Mn;228;NSM;;;;;N;;;;;
-18AA;MONGOLIAN LETTER MANCHU ALI GALI LHA;Lo;0;L;;;;;N;;;;;
-18B0;CANADIAN SYLLABICS OY;Lo;0;L;;;;;N;;;;;
-18B1;CANADIAN SYLLABICS AY;Lo;0;L;;;;;N;;;;;
-18B2;CANADIAN SYLLABICS AAY;Lo;0;L;;;;;N;;;;;
-18B3;CANADIAN SYLLABICS WAY;Lo;0;L;;;;;N;;;;;
-18B4;CANADIAN SYLLABICS POY;Lo;0;L;;;;;N;;;;;
-18B5;CANADIAN SYLLABICS PAY;Lo;0;L;;;;;N;;;;;
-18B6;CANADIAN SYLLABICS PWOY;Lo;0;L;;;;;N;;;;;
-18B7;CANADIAN SYLLABICS TAY;Lo;0;L;;;;;N;;;;;
-18B8;CANADIAN SYLLABICS KAY;Lo;0;L;;;;;N;;;;;
-18B9;CANADIAN SYLLABICS KWAY;Lo;0;L;;;;;N;;;;;
-18BA;CANADIAN SYLLABICS MAY;Lo;0;L;;;;;N;;;;;
-18BB;CANADIAN SYLLABICS NOY;Lo;0;L;;;;;N;;;;;
-18BC;CANADIAN SYLLABICS NAY;Lo;0;L;;;;;N;;;;;
-18BD;CANADIAN SYLLABICS LAY;Lo;0;L;;;;;N;;;;;
-18BE;CANADIAN SYLLABICS SOY;Lo;0;L;;;;;N;;;;;
-18BF;CANADIAN SYLLABICS SAY;Lo;0;L;;;;;N;;;;;
-18C0;CANADIAN SYLLABICS SHOY;Lo;0;L;;;;;N;;;;;
-18C1;CANADIAN SYLLABICS SHAY;Lo;0;L;;;;;N;;;;;
-18C2;CANADIAN SYLLABICS SHWOY;Lo;0;L;;;;;N;;;;;
-18C3;CANADIAN SYLLABICS YOY;Lo;0;L;;;;;N;;;;;
-18C4;CANADIAN SYLLABICS YAY;Lo;0;L;;;;;N;;;;;
-18C5;CANADIAN SYLLABICS RAY;Lo;0;L;;;;;N;;;;;
-18C6;CANADIAN SYLLABICS NWI;Lo;0;L;;;;;N;;;;;
-18C7;CANADIAN SYLLABICS OJIBWAY NWI;Lo;0;L;;;;;N;;;;;
-18C8;CANADIAN SYLLABICS NWII;Lo;0;L;;;;;N;;;;;
-18C9;CANADIAN SYLLABICS OJIBWAY NWII;Lo;0;L;;;;;N;;;;;
-18CA;CANADIAN SYLLABICS NWO;Lo;0;L;;;;;N;;;;;
-18CB;CANADIAN SYLLABICS OJIBWAY NWO;Lo;0;L;;;;;N;;;;;
-18CC;CANADIAN SYLLABICS NWOO;Lo;0;L;;;;;N;;;;;
-18CD;CANADIAN SYLLABICS OJIBWAY NWOO;Lo;0;L;;;;;N;;;;;
-18CE;CANADIAN SYLLABICS RWEE;Lo;0;L;;;;;N;;;;;
-18CF;CANADIAN SYLLABICS RWI;Lo;0;L;;;;;N;;;;;
-18D0;CANADIAN SYLLABICS RWII;Lo;0;L;;;;;N;;;;;
-18D1;CANADIAN SYLLABICS RWO;Lo;0;L;;;;;N;;;;;
-18D2;CANADIAN SYLLABICS RWOO;Lo;0;L;;;;;N;;;;;
-18D3;CANADIAN SYLLABICS RWA;Lo;0;L;;;;;N;;;;;
-18D4;CANADIAN SYLLABICS OJIBWAY P;Lo;0;L;;;;;N;;;;;
-18D5;CANADIAN SYLLABICS OJIBWAY T;Lo;0;L;;;;;N;;;;;
-18D6;CANADIAN SYLLABICS OJIBWAY K;Lo;0;L;;;;;N;;;;;
-18D7;CANADIAN SYLLABICS OJIBWAY C;Lo;0;L;;;;;N;;;;;
-18D8;CANADIAN SYLLABICS OJIBWAY M;Lo;0;L;;;;;N;;;;;
-18D9;CANADIAN SYLLABICS OJIBWAY N;Lo;0;L;;;;;N;;;;;
-18DA;CANADIAN SYLLABICS OJIBWAY S;Lo;0;L;;;;;N;;;;;
-18DB;CANADIAN SYLLABICS OJIBWAY SH;Lo;0;L;;;;;N;;;;;
-18DC;CANADIAN SYLLABICS EASTERN W;Lo;0;L;;;;;N;;;;;
-18DD;CANADIAN SYLLABICS WESTERN W;Lo;0;L;;;;;N;;;;;
-18DE;CANADIAN SYLLABICS FINAL SMALL RING;Lo;0;L;;;;;N;;;;;
-18DF;CANADIAN SYLLABICS FINAL RAISED DOT;Lo;0;L;;;;;N;;;;;
-18E0;CANADIAN SYLLABICS R-CREE RWE;Lo;0;L;;;;;N;;;;;
-18E1;CANADIAN SYLLABICS WEST-CREE LOO;Lo;0;L;;;;;N;;;;;
-18E2;CANADIAN SYLLABICS WEST-CREE LAA;Lo;0;L;;;;;N;;;;;
-18E3;CANADIAN SYLLABICS THWE;Lo;0;L;;;;;N;;;;;
-18E4;CANADIAN SYLLABICS THWA;Lo;0;L;;;;;N;;;;;
-18E5;CANADIAN SYLLABICS TTHWE;Lo;0;L;;;;;N;;;;;
-18E6;CANADIAN SYLLABICS TTHOO;Lo;0;L;;;;;N;;;;;
-18E7;CANADIAN SYLLABICS TTHAA;Lo;0;L;;;;;N;;;;;
-18E8;CANADIAN SYLLABICS TLHWE;Lo;0;L;;;;;N;;;;;
-18E9;CANADIAN SYLLABICS TLHOO;Lo;0;L;;;;;N;;;;;
-18EA;CANADIAN SYLLABICS SAYISI SHWE;Lo;0;L;;;;;N;;;;;
-18EB;CANADIAN SYLLABICS SAYISI SHOO;Lo;0;L;;;;;N;;;;;
-18EC;CANADIAN SYLLABICS SAYISI HOO;Lo;0;L;;;;;N;;;;;
-18ED;CANADIAN SYLLABICS CARRIER GWU;Lo;0;L;;;;;N;;;;;
-18EE;CANADIAN SYLLABICS CARRIER DENE GEE;Lo;0;L;;;;;N;;;;;
-18EF;CANADIAN SYLLABICS CARRIER GAA;Lo;0;L;;;;;N;;;;;
-18F0;CANADIAN SYLLABICS CARRIER GWA;Lo;0;L;;;;;N;;;;;
-18F1;CANADIAN SYLLABICS SAYISI JUU;Lo;0;L;;;;;N;;;;;
-18F2;CANADIAN SYLLABICS CARRIER JWA;Lo;0;L;;;;;N;;;;;
-18F3;CANADIAN SYLLABICS BEAVER DENE L;Lo;0;L;;;;;N;;;;;
-18F4;CANADIAN SYLLABICS BEAVER DENE R;Lo;0;L;;;;;N;;;;;
-18F5;CANADIAN SYLLABICS CARRIER DENTAL S;Lo;0;L;;;;;N;;;;;
-1900;LIMBU VOWEL-CARRIER LETTER;Lo;0;L;;;;;N;;;;;
-1901;LIMBU LETTER KA;Lo;0;L;;;;;N;;;;;
-1902;LIMBU LETTER KHA;Lo;0;L;;;;;N;;;;;
-1903;LIMBU LETTER GA;Lo;0;L;;;;;N;;;;;
-1904;LIMBU LETTER GHA;Lo;0;L;;;;;N;;;;;
-1905;LIMBU LETTER NGA;Lo;0;L;;;;;N;;;;;
-1906;LIMBU LETTER CA;Lo;0;L;;;;;N;;;;;
-1907;LIMBU LETTER CHA;Lo;0;L;;;;;N;;;;;
-1908;LIMBU LETTER JA;Lo;0;L;;;;;N;;;;;
-1909;LIMBU LETTER JHA;Lo;0;L;;;;;N;;;;;
-190A;LIMBU LETTER YAN;Lo;0;L;;;;;N;;;;;
-190B;LIMBU LETTER TA;Lo;0;L;;;;;N;;;;;
-190C;LIMBU LETTER THA;Lo;0;L;;;;;N;;;;;
-190D;LIMBU LETTER DA;Lo;0;L;;;;;N;;;;;
-190E;LIMBU LETTER DHA;Lo;0;L;;;;;N;;;;;
-190F;LIMBU LETTER NA;Lo;0;L;;;;;N;;;;;
-1910;LIMBU LETTER PA;Lo;0;L;;;;;N;;;;;
-1911;LIMBU LETTER PHA;Lo;0;L;;;;;N;;;;;
-1912;LIMBU LETTER BA;Lo;0;L;;;;;N;;;;;
-1913;LIMBU LETTER BHA;Lo;0;L;;;;;N;;;;;
-1914;LIMBU LETTER MA;Lo;0;L;;;;;N;;;;;
-1915;LIMBU LETTER YA;Lo;0;L;;;;;N;;;;;
-1916;LIMBU LETTER RA;Lo;0;L;;;;;N;;;;;
-1917;LIMBU LETTER LA;Lo;0;L;;;;;N;;;;;
-1918;LIMBU LETTER WA;Lo;0;L;;;;;N;;;;;
-1919;LIMBU LETTER SHA;Lo;0;L;;;;;N;;;;;
-191A;LIMBU LETTER SSA;Lo;0;L;;;;;N;;;;;
-191B;LIMBU LETTER SA;Lo;0;L;;;;;N;;;;;
-191C;LIMBU LETTER HA;Lo;0;L;;;;;N;;;;;
-1920;LIMBU VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;;
-1921;LIMBU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-1922;LIMBU VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1923;LIMBU VOWEL SIGN EE;Mc;0;L;;;;;N;;;;;
-1924;LIMBU VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-1925;LIMBU VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
-1926;LIMBU VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-1927;LIMBU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-1928;LIMBU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
-1929;LIMBU SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;;
-192A;LIMBU SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;;
-192B;LIMBU SUBJOINED LETTER WA;Mc;0;L;;;;;N;;;;;
-1930;LIMBU SMALL LETTER KA;Mc;0;L;;;;;N;;;;;
-1931;LIMBU SMALL LETTER NGA;Mc;0;L;;;;;N;;;;;
-1932;LIMBU SMALL LETTER ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-1933;LIMBU SMALL LETTER TA;Mc;0;L;;;;;N;;;;;
-1934;LIMBU SMALL LETTER NA;Mc;0;L;;;;;N;;;;;
-1935;LIMBU SMALL LETTER PA;Mc;0;L;;;;;N;;;;;
-1936;LIMBU SMALL LETTER MA;Mc;0;L;;;;;N;;;;;
-1937;LIMBU SMALL LETTER RA;Mc;0;L;;;;;N;;;;;
-1938;LIMBU SMALL LETTER LA;Mc;0;L;;;;;N;;;;;
-1939;LIMBU SIGN MUKPHRENG;Mn;222;NSM;;;;;N;;;;;
-193A;LIMBU SIGN KEMPHRENG;Mn;230;NSM;;;;;N;;;;;
-193B;LIMBU SIGN SA-I;Mn;220;NSM;;;;;N;;;;;
-1940;LIMBU SIGN LOO;So;0;ON;;;;;N;;;;;
-1944;LIMBU EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
-1945;LIMBU QUESTION MARK;Po;0;ON;;;;;N;;;;;
-1946;LIMBU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1947;LIMBU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1948;LIMBU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1949;LIMBU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-194A;LIMBU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-194B;LIMBU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-194C;LIMBU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-194D;LIMBU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-194E;LIMBU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-194F;LIMBU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-1950;TAI LE LETTER KA;Lo;0;L;;;;;N;;;;;
-1951;TAI LE LETTER XA;Lo;0;L;;;;;N;;;;;
-1952;TAI LE LETTER NGA;Lo;0;L;;;;;N;;;;;
-1953;TAI LE LETTER TSA;Lo;0;L;;;;;N;;;;;
-1954;TAI LE LETTER SA;Lo;0;L;;;;;N;;;;;
-1955;TAI LE LETTER YA;Lo;0;L;;;;;N;;;;;
-1956;TAI LE LETTER TA;Lo;0;L;;;;;N;;;;;
-1957;TAI LE LETTER THA;Lo;0;L;;;;;N;;;;;
-1958;TAI LE LETTER LA;Lo;0;L;;;;;N;;;;;
-1959;TAI LE LETTER PA;Lo;0;L;;;;;N;;;;;
-195A;TAI LE LETTER PHA;Lo;0;L;;;;;N;;;;;
-195B;TAI LE LETTER MA;Lo;0;L;;;;;N;;;;;
-195C;TAI LE LETTER FA;Lo;0;L;;;;;N;;;;;
-195D;TAI LE LETTER VA;Lo;0;L;;;;;N;;;;;
-195E;TAI LE LETTER HA;Lo;0;L;;;;;N;;;;;
-195F;TAI LE LETTER QA;Lo;0;L;;;;;N;;;;;
-1960;TAI LE LETTER KHA;Lo;0;L;;;;;N;;;;;
-1961;TAI LE LETTER TSHA;Lo;0;L;;;;;N;;;;;
-1962;TAI LE LETTER NA;Lo;0;L;;;;;N;;;;;
-1963;TAI LE LETTER A;Lo;0;L;;;;;N;;;;;
-1964;TAI LE LETTER I;Lo;0;L;;;;;N;;;;;
-1965;TAI LE LETTER EE;Lo;0;L;;;;;N;;;;;
-1966;TAI LE LETTER EH;Lo;0;L;;;;;N;;;;;
-1967;TAI LE LETTER U;Lo;0;L;;;;;N;;;;;
-1968;TAI LE LETTER OO;Lo;0;L;;;;;N;;;;;
-1969;TAI LE LETTER O;Lo;0;L;;;;;N;;;;;
-196A;TAI LE LETTER UE;Lo;0;L;;;;;N;;;;;
-196B;TAI LE LETTER E;Lo;0;L;;;;;N;;;;;
-196C;TAI LE LETTER AUE;Lo;0;L;;;;;N;;;;;
-196D;TAI LE LETTER AI;Lo;0;L;;;;;N;;;;;
-1970;TAI LE LETTER TONE-2;Lo;0;L;;;;;N;;;;;
-1971;TAI LE LETTER TONE-3;Lo;0;L;;;;;N;;;;;
-1972;TAI LE LETTER TONE-4;Lo;0;L;;;;;N;;;;;
-1973;TAI LE LETTER TONE-5;Lo;0;L;;;;;N;;;;;
-1974;TAI LE LETTER TONE-6;Lo;0;L;;;;;N;;;;;
-1980;NEW TAI LUE LETTER HIGH QA;Lo;0;L;;;;;N;;;;;
-1981;NEW TAI LUE LETTER LOW QA;Lo;0;L;;;;;N;;;;;
-1982;NEW TAI LUE LETTER HIGH KA;Lo;0;L;;;;;N;;;;;
-1983;NEW TAI LUE LETTER HIGH XA;Lo;0;L;;;;;N;;;;;
-1984;NEW TAI LUE LETTER HIGH NGA;Lo;0;L;;;;;N;;;;;
-1985;NEW TAI LUE LETTER LOW KA;Lo;0;L;;;;;N;;;;;
-1986;NEW TAI LUE LETTER LOW XA;Lo;0;L;;;;;N;;;;;
-1987;NEW TAI LUE LETTER LOW NGA;Lo;0;L;;;;;N;;;;;
-1988;NEW TAI LUE LETTER HIGH TSA;Lo;0;L;;;;;N;;;;;
-1989;NEW TAI LUE LETTER HIGH SA;Lo;0;L;;;;;N;;;;;
-198A;NEW TAI LUE LETTER HIGH YA;Lo;0;L;;;;;N;;;;;
-198B;NEW TAI LUE LETTER LOW TSA;Lo;0;L;;;;;N;;;;;
-198C;NEW TAI LUE LETTER LOW SA;Lo;0;L;;;;;N;;;;;
-198D;NEW TAI LUE LETTER LOW YA;Lo;0;L;;;;;N;;;;;
-198E;NEW TAI LUE LETTER HIGH TA;Lo;0;L;;;;;N;;;;;
-198F;NEW TAI LUE LETTER HIGH THA;Lo;0;L;;;;;N;;;;;
-1990;NEW TAI LUE LETTER HIGH NA;Lo;0;L;;;;;N;;;;;
-1991;NEW TAI LUE LETTER LOW TA;Lo;0;L;;;;;N;;;;;
-1992;NEW TAI LUE LETTER LOW THA;Lo;0;L;;;;;N;;;;;
-1993;NEW TAI LUE LETTER LOW NA;Lo;0;L;;;;;N;;;;;
-1994;NEW TAI LUE LETTER HIGH PA;Lo;0;L;;;;;N;;;;;
-1995;NEW TAI LUE LETTER HIGH PHA;Lo;0;L;;;;;N;;;;;
-1996;NEW TAI LUE LETTER HIGH MA;Lo;0;L;;;;;N;;;;;
-1997;NEW TAI LUE LETTER LOW PA;Lo;0;L;;;;;N;;;;;
-1998;NEW TAI LUE LETTER LOW PHA;Lo;0;L;;;;;N;;;;;
-1999;NEW TAI LUE LETTER LOW MA;Lo;0;L;;;;;N;;;;;
-199A;NEW TAI LUE LETTER HIGH FA;Lo;0;L;;;;;N;;;;;
-199B;NEW TAI LUE LETTER HIGH VA;Lo;0;L;;;;;N;;;;;
-199C;NEW TAI LUE LETTER HIGH LA;Lo;0;L;;;;;N;;;;;
-199D;NEW TAI LUE LETTER LOW FA;Lo;0;L;;;;;N;;;;;
-199E;NEW TAI LUE LETTER LOW VA;Lo;0;L;;;;;N;;;;;
-199F;NEW TAI LUE LETTER LOW LA;Lo;0;L;;;;;N;;;;;
-19A0;NEW TAI LUE LETTER HIGH HA;Lo;0;L;;;;;N;;;;;
-19A1;NEW TAI LUE LETTER HIGH DA;Lo;0;L;;;;;N;;;;;
-19A2;NEW TAI LUE LETTER HIGH BA;Lo;0;L;;;;;N;;;;;
-19A3;NEW TAI LUE LETTER LOW HA;Lo;0;L;;;;;N;;;;;
-19A4;NEW TAI LUE LETTER LOW DA;Lo;0;L;;;;;N;;;;;
-19A5;NEW TAI LUE LETTER LOW BA;Lo;0;L;;;;;N;;;;;
-19A6;NEW TAI LUE LETTER HIGH KVA;Lo;0;L;;;;;N;;;;;
-19A7;NEW TAI LUE LETTER HIGH XVA;Lo;0;L;;;;;N;;;;;
-19A8;NEW TAI LUE LETTER LOW KVA;Lo;0;L;;;;;N;;;;;
-19A9;NEW TAI LUE LETTER LOW XVA;Lo;0;L;;;;;N;;;;;
-19AA;NEW TAI LUE LETTER HIGH SUA;Lo;0;L;;;;;N;;;;;
-19AB;NEW TAI LUE LETTER LOW SUA;Lo;0;L;;;;;N;;;;;
-19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Mc;0;L;;;;;N;;;;;
-19B1;NEW TAI LUE VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-19B2;NEW TAI LUE VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-19B3;NEW TAI LUE VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-19B4;NEW TAI LUE VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
-19B5;NEW TAI LUE VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-19B6;NEW TAI LUE VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
-19B7;NEW TAI LUE VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-19B8;NEW TAI LUE VOWEL SIGN OA;Mc;0;L;;;;;N;;;;;
-19B9;NEW TAI LUE VOWEL SIGN UE;Mc;0;L;;;;;N;;;;;
-19BA;NEW TAI LUE VOWEL SIGN AY;Mc;0;L;;;;;N;;;;;
-19BB;NEW TAI LUE VOWEL SIGN AAY;Mc;0;L;;;;;N;;;;;
-19BC;NEW TAI LUE VOWEL SIGN UY;Mc;0;L;;;;;N;;;;;
-19BD;NEW TAI LUE VOWEL SIGN OY;Mc;0;L;;;;;N;;;;;
-19BE;NEW TAI LUE VOWEL SIGN OAY;Mc;0;L;;;;;N;;;;;
-19BF;NEW TAI LUE VOWEL SIGN UEY;Mc;0;L;;;;;N;;;;;
-19C0;NEW TAI LUE VOWEL SIGN IY;Mc;0;L;;;;;N;;;;;
-19C1;NEW TAI LUE LETTER FINAL V;Lo;0;L;;;;;N;;;;;
-19C2;NEW TAI LUE LETTER FINAL NG;Lo;0;L;;;;;N;;;;;
-19C3;NEW TAI LUE LETTER FINAL N;Lo;0;L;;;;;N;;;;;
-19C4;NEW TAI LUE LETTER FINAL M;Lo;0;L;;;;;N;;;;;
-19C5;NEW TAI LUE LETTER FINAL K;Lo;0;L;;;;;N;;;;;
-19C6;NEW TAI LUE LETTER FINAL D;Lo;0;L;;;;;N;;;;;
-19C7;NEW TAI LUE LETTER FINAL B;Lo;0;L;;;;;N;;;;;
-19C8;NEW TAI LUE TONE MARK-1;Mc;0;L;;;;;N;;;;;
-19C9;NEW TAI LUE TONE MARK-2;Mc;0;L;;;;;N;;;;;
-19D0;NEW TAI LUE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-19D1;NEW TAI LUE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-19D2;NEW TAI LUE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-19D3;NEW TAI LUE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-19D4;NEW TAI LUE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-19D5;NEW TAI LUE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-19D6;NEW TAI LUE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-19D7;NEW TAI LUE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-19D8;NEW TAI LUE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-19D9;NEW TAI LUE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-19DA;NEW TAI LUE THAM DIGIT ONE;No;0;L;;;1;1;N;;;;;
-19DE;NEW TAI LUE SIGN LAE;So;0;ON;;;;;N;;;;;
-19DF;NEW TAI LUE SIGN LAEV;So;0;ON;;;;;N;;;;;
-19E0;KHMER SYMBOL PATHAMASAT;So;0;ON;;;;;N;;;;;
-19E1;KHMER SYMBOL MUOY KOET;So;0;ON;;;;;N;;;;;
-19E2;KHMER SYMBOL PII KOET;So;0;ON;;;;;N;;;;;
-19E3;KHMER SYMBOL BEI KOET;So;0;ON;;;;;N;;;;;
-19E4;KHMER SYMBOL BUON KOET;So;0;ON;;;;;N;;;;;
-19E5;KHMER SYMBOL PRAM KOET;So;0;ON;;;;;N;;;;;
-19E6;KHMER SYMBOL PRAM-MUOY KOET;So;0;ON;;;;;N;;;;;
-19E7;KHMER SYMBOL PRAM-PII KOET;So;0;ON;;;;;N;;;;;
-19E8;KHMER SYMBOL PRAM-BEI KOET;So;0;ON;;;;;N;;;;;
-19E9;KHMER SYMBOL PRAM-BUON KOET;So;0;ON;;;;;N;;;;;
-19EA;KHMER SYMBOL DAP KOET;So;0;ON;;;;;N;;;;;
-19EB;KHMER SYMBOL DAP-MUOY KOET;So;0;ON;;;;;N;;;;;
-19EC;KHMER SYMBOL DAP-PII KOET;So;0;ON;;;;;N;;;;;
-19ED;KHMER SYMBOL DAP-BEI KOET;So;0;ON;;;;;N;;;;;
-19EE;KHMER SYMBOL DAP-BUON KOET;So;0;ON;;;;;N;;;;;
-19EF;KHMER SYMBOL DAP-PRAM KOET;So;0;ON;;;;;N;;;;;
-19F0;KHMER SYMBOL TUTEYASAT;So;0;ON;;;;;N;;;;;
-19F1;KHMER SYMBOL MUOY ROC;So;0;ON;;;;;N;;;;;
-19F2;KHMER SYMBOL PII ROC;So;0;ON;;;;;N;;;;;
-19F3;KHMER SYMBOL BEI ROC;So;0;ON;;;;;N;;;;;
-19F4;KHMER SYMBOL BUON ROC;So;0;ON;;;;;N;;;;;
-19F5;KHMER SYMBOL PRAM ROC;So;0;ON;;;;;N;;;;;
-19F6;KHMER SYMBOL PRAM-MUOY ROC;So;0;ON;;;;;N;;;;;
-19F7;KHMER SYMBOL PRAM-PII ROC;So;0;ON;;;;;N;;;;;
-19F8;KHMER SYMBOL PRAM-BEI ROC;So;0;ON;;;;;N;;;;;
-19F9;KHMER SYMBOL PRAM-BUON ROC;So;0;ON;;;;;N;;;;;
-19FA;KHMER SYMBOL DAP ROC;So;0;ON;;;;;N;;;;;
-19FB;KHMER SYMBOL DAP-MUOY ROC;So;0;ON;;;;;N;;;;;
-19FC;KHMER SYMBOL DAP-PII ROC;So;0;ON;;;;;N;;;;;
-19FD;KHMER SYMBOL DAP-BEI ROC;So;0;ON;;;;;N;;;;;
-19FE;KHMER SYMBOL DAP-BUON ROC;So;0;ON;;;;;N;;;;;
-19FF;KHMER SYMBOL DAP-PRAM ROC;So;0;ON;;;;;N;;;;;
-1A00;BUGINESE LETTER KA;Lo;0;L;;;;;N;;;;;
-1A01;BUGINESE LETTER GA;Lo;0;L;;;;;N;;;;;
-1A02;BUGINESE LETTER NGA;Lo;0;L;;;;;N;;;;;
-1A03;BUGINESE LETTER NGKA;Lo;0;L;;;;;N;;;;;
-1A04;BUGINESE LETTER PA;Lo;0;L;;;;;N;;;;;
-1A05;BUGINESE LETTER BA;Lo;0;L;;;;;N;;;;;
-1A06;BUGINESE LETTER MA;Lo;0;L;;;;;N;;;;;
-1A07;BUGINESE LETTER MPA;Lo;0;L;;;;;N;;;;;
-1A08;BUGINESE LETTER TA;Lo;0;L;;;;;N;;;;;
-1A09;BUGINESE LETTER DA;Lo;0;L;;;;;N;;;;;
-1A0A;BUGINESE LETTER NA;Lo;0;L;;;;;N;;;;;
-1A0B;BUGINESE LETTER NRA;Lo;0;L;;;;;N;;;;;
-1A0C;BUGINESE LETTER CA;Lo;0;L;;;;;N;;;;;
-1A0D;BUGINESE LETTER JA;Lo;0;L;;;;;N;;;;;
-1A0E;BUGINESE LETTER NYA;Lo;0;L;;;;;N;;;;;
-1A0F;BUGINESE LETTER NYCA;Lo;0;L;;;;;N;;;;;
-1A10;BUGINESE LETTER YA;Lo;0;L;;;;;N;;;;;
-1A11;BUGINESE LETTER RA;Lo;0;L;;;;;N;;;;;
-1A12;BUGINESE LETTER LA;Lo;0;L;;;;;N;;;;;
-1A13;BUGINESE LETTER VA;Lo;0;L;;;;;N;;;;;
-1A14;BUGINESE LETTER SA;Lo;0;L;;;;;N;;;;;
-1A15;BUGINESE LETTER A;Lo;0;L;;;;;N;;;;;
-1A16;BUGINESE LETTER HA;Lo;0;L;;;;;N;;;;;
-1A17;BUGINESE VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;;
-1A18;BUGINESE VOWEL SIGN U;Mn;220;NSM;;;;;N;;;;;
-1A19;BUGINESE VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-1A1A;BUGINESE VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-1A1B;BUGINESE VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
-1A1E;BUGINESE PALLAWA;Po;0;L;;;;;N;;;;;
-1A1F;BUGINESE END OF SECTION;Po;0;L;;;;;N;;;;;
-1A20;TAI THAM LETTER HIGH KA;Lo;0;L;;;;;N;;;;;
-1A21;TAI THAM LETTER HIGH KHA;Lo;0;L;;;;;N;;;;;
-1A22;TAI THAM LETTER HIGH KXA;Lo;0;L;;;;;N;;;;;
-1A23;TAI THAM LETTER LOW KA;Lo;0;L;;;;;N;;;;;
-1A24;TAI THAM LETTER LOW KXA;Lo;0;L;;;;;N;;;;;
-1A25;TAI THAM LETTER LOW KHA;Lo;0;L;;;;;N;;;;;
-1A26;TAI THAM LETTER NGA;Lo;0;L;;;;;N;;;;;
-1A27;TAI THAM LETTER HIGH CA;Lo;0;L;;;;;N;;;;;
-1A28;TAI THAM LETTER HIGH CHA;Lo;0;L;;;;;N;;;;;
-1A29;TAI THAM LETTER LOW CA;Lo;0;L;;;;;N;;;;;
-1A2A;TAI THAM LETTER LOW SA;Lo;0;L;;;;;N;;;;;
-1A2B;TAI THAM LETTER LOW CHA;Lo;0;L;;;;;N;;;;;
-1A2C;TAI THAM LETTER NYA;Lo;0;L;;;;;N;;;;;
-1A2D;TAI THAM LETTER RATA;Lo;0;L;;;;;N;;;;;
-1A2E;TAI THAM LETTER HIGH RATHA;Lo;0;L;;;;;N;;;;;
-1A2F;TAI THAM LETTER DA;Lo;0;L;;;;;N;;;;;
-1A30;TAI THAM LETTER LOW RATHA;Lo;0;L;;;;;N;;;;;
-1A31;TAI THAM LETTER RANA;Lo;0;L;;;;;N;;;;;
-1A32;TAI THAM LETTER HIGH TA;Lo;0;L;;;;;N;;;;;
-1A33;TAI THAM LETTER HIGH THA;Lo;0;L;;;;;N;;;;;
-1A34;TAI THAM LETTER LOW TA;Lo;0;L;;;;;N;;;;;
-1A35;TAI THAM LETTER LOW THA;Lo;0;L;;;;;N;;;;;
-1A36;TAI THAM LETTER NA;Lo;0;L;;;;;N;;;;;
-1A37;TAI THAM LETTER BA;Lo;0;L;;;;;N;;;;;
-1A38;TAI THAM LETTER HIGH PA;Lo;0;L;;;;;N;;;;;
-1A39;TAI THAM LETTER HIGH PHA;Lo;0;L;;;;;N;;;;;
-1A3A;TAI THAM LETTER HIGH FA;Lo;0;L;;;;;N;;;;;
-1A3B;TAI THAM LETTER LOW PA;Lo;0;L;;;;;N;;;;;
-1A3C;TAI THAM LETTER LOW FA;Lo;0;L;;;;;N;;;;;
-1A3D;TAI THAM LETTER LOW PHA;Lo;0;L;;;;;N;;;;;
-1A3E;TAI THAM LETTER MA;Lo;0;L;;;;;N;;;;;
-1A3F;TAI THAM LETTER LOW YA;Lo;0;L;;;;;N;;;;;
-1A40;TAI THAM LETTER HIGH YA;Lo;0;L;;;;;N;;;;;
-1A41;TAI THAM LETTER RA;Lo;0;L;;;;;N;;;;;
-1A42;TAI THAM LETTER RUE;Lo;0;L;;;;;N;;;;;
-1A43;TAI THAM LETTER LA;Lo;0;L;;;;;N;;;;;
-1A44;TAI THAM LETTER LUE;Lo;0;L;;;;;N;;;;;
-1A45;TAI THAM LETTER WA;Lo;0;L;;;;;N;;;;;
-1A46;TAI THAM LETTER HIGH SHA;Lo;0;L;;;;;N;;;;;
-1A47;TAI THAM LETTER HIGH SSA;Lo;0;L;;;;;N;;;;;
-1A48;TAI THAM LETTER HIGH SA;Lo;0;L;;;;;N;;;;;
-1A49;TAI THAM LETTER HIGH HA;Lo;0;L;;;;;N;;;;;
-1A4A;TAI THAM LETTER LLA;Lo;0;L;;;;;N;;;;;
-1A4B;TAI THAM LETTER A;Lo;0;L;;;;;N;;;;;
-1A4C;TAI THAM LETTER LOW HA;Lo;0;L;;;;;N;;;;;
-1A4D;TAI THAM LETTER I;Lo;0;L;;;;;N;;;;;
-1A4E;TAI THAM LETTER II;Lo;0;L;;;;;N;;;;;
-1A4F;TAI THAM LETTER U;Lo;0;L;;;;;N;;;;;
-1A50;TAI THAM LETTER UU;Lo;0;L;;;;;N;;;;;
-1A51;TAI THAM LETTER EE;Lo;0;L;;;;;N;;;;;
-1A52;TAI THAM LETTER OO;Lo;0;L;;;;;N;;;;;
-1A53;TAI THAM LETTER LAE;Lo;0;L;;;;;N;;;;;
-1A54;TAI THAM LETTER GREAT SA;Lo;0;L;;;;;N;;;;;
-1A55;TAI THAM CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;;
-1A56;TAI THAM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;;
-1A57;TAI THAM CONSONANT SIGN LA TANG LAI;Mc;0;L;;;;;N;;;;;
-1A58;TAI THAM SIGN MAI KANG LAI;Mn;0;NSM;;;;;N;;;;;
-1A59;TAI THAM CONSONANT SIGN FINAL NGA;Mn;0;NSM;;;;;N;;;;;
-1A5A;TAI THAM CONSONANT SIGN LOW PA;Mn;0;NSM;;;;;N;;;;;
-1A5B;TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA;Mn;0;NSM;;;;;N;;;;;
-1A5C;TAI THAM CONSONANT SIGN MA;Mn;0;NSM;;;;;N;;;;;
-1A5D;TAI THAM CONSONANT SIGN BA;Mn;0;NSM;;;;;N;;;;;
-1A5E;TAI THAM CONSONANT SIGN SA;Mn;0;NSM;;;;;N;;;;;
-1A60;TAI THAM SIGN SAKOT;Mn;9;NSM;;;;;N;;;;;
-1A61;TAI THAM VOWEL SIGN A;Mc;0;L;;;;;N;;;;;
-1A62;TAI THAM VOWEL SIGN MAI SAT;Mn;0;NSM;;;;;N;;;;;
-1A63;TAI THAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-1A64;TAI THAM VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;;
-1A65;TAI THAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-1A66;TAI THAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-1A67;TAI THAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;;
-1A68;TAI THAM VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;;
-1A69;TAI THAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1A6A;TAI THAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-1A6B;TAI THAM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
-1A6C;TAI THAM VOWEL SIGN OA BELOW;Mn;0;NSM;;;;;N;;;;;
-1A6D;TAI THAM VOWEL SIGN OY;Mc;0;L;;;;;N;;;;;
-1A6E;TAI THAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-1A6F;TAI THAM VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
-1A70;TAI THAM VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
-1A71;TAI THAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-1A72;TAI THAM VOWEL SIGN THAM AI;Mc;0;L;;;;;N;;;;;
-1A73;TAI THAM VOWEL SIGN OA ABOVE;Mn;0;NSM;;;;;N;;;;;
-1A74;TAI THAM SIGN MAI KANG;Mn;0;NSM;;;;;N;;;;;
-1A75;TAI THAM SIGN TONE-1;Mn;230;NSM;;;;;N;;;;;
-1A76;TAI THAM SIGN TONE-2;Mn;230;NSM;;;;;N;;;;;
-1A77;TAI THAM SIGN KHUEN TONE-3;Mn;230;NSM;;;;;N;;;;;
-1A78;TAI THAM SIGN KHUEN TONE-4;Mn;230;NSM;;;;;N;;;;;
-1A79;TAI THAM SIGN KHUEN TONE-5;Mn;230;NSM;;;;;N;;;;;
-1A7A;TAI THAM SIGN RA HAAM;Mn;230;NSM;;;;;N;;;;;
-1A7B;TAI THAM SIGN MAI SAM;Mn;230;NSM;;;;;N;;;;;
-1A7C;TAI THAM SIGN KHUEN-LUE KARAN;Mn;230;NSM;;;;;N;;;;;
-1A7F;TAI THAM COMBINING CRYPTOGRAMMIC DOT;Mn;220;NSM;;;;;N;;;;;
-1A80;TAI THAM HORA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1A81;TAI THAM HORA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1A82;TAI THAM HORA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1A83;TAI THAM HORA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1A84;TAI THAM HORA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1A85;TAI THAM HORA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1A86;TAI THAM HORA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1A87;TAI THAM HORA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1A88;TAI THAM HORA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1A89;TAI THAM HORA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-1A90;TAI THAM THAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1A91;TAI THAM THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1A92;TAI THAM THAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1A93;TAI THAM THAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1A94;TAI THAM THAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1A95;TAI THAM THAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1A96;TAI THAM THAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1A97;TAI THAM THAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1A98;TAI THAM THAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1A99;TAI THAM THAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-1AA0;TAI THAM SIGN WIANG;Po;0;L;;;;;N;;;;;
-1AA1;TAI THAM SIGN WIANGWAAK;Po;0;L;;;;;N;;;;;
-1AA2;TAI THAM SIGN SAWAN;Po;0;L;;;;;N;;;;;
-1AA3;TAI THAM SIGN KEOW;Po;0;L;;;;;N;;;;;
-1AA4;TAI THAM SIGN HOY;Po;0;L;;;;;N;;;;;
-1AA5;TAI THAM SIGN DOKMAI;Po;0;L;;;;;N;;;;;
-1AA6;TAI THAM SIGN REVERSED ROTATED RANA;Po;0;L;;;;;N;;;;;
-1AA7;TAI THAM SIGN MAI YAMOK;Lm;0;L;;;;;N;;;;;
-1AA8;TAI THAM SIGN KAAN;Po;0;L;;;;;N;;;;;
-1AA9;TAI THAM SIGN KAANKUU;Po;0;L;;;;;N;;;;;
-1AAA;TAI THAM SIGN SATKAAN;Po;0;L;;;;;N;;;;;
-1AAB;TAI THAM SIGN SATKAANKUU;Po;0;L;;;;;N;;;;;
-1AAC;TAI THAM SIGN HANG;Po;0;L;;;;;N;;;;;
-1AAD;TAI THAM SIGN CAANG;Po;0;L;;;;;N;;;;;
-1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;;
-1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;;
-1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;;
-1B03;BALINESE SIGN SURANG;Mn;0;NSM;;;;;N;;;;;
-1B04;BALINESE SIGN BISAH;Mc;0;L;;;;;N;;;;;
-1B05;BALINESE LETTER AKARA;Lo;0;L;;;;;N;;;;;
-1B06;BALINESE LETTER AKARA TEDUNG;Lo;0;L;1B05 1B35;;;;N;;;;;
-1B07;BALINESE LETTER IKARA;Lo;0;L;;;;;N;;;;;
-1B08;BALINESE LETTER IKARA TEDUNG;Lo;0;L;1B07 1B35;;;;N;;;;;
-1B09;BALINESE LETTER UKARA;Lo;0;L;;;;;N;;;;;
-1B0A;BALINESE LETTER UKARA TEDUNG;Lo;0;L;1B09 1B35;;;;N;;;;;
-1B0B;BALINESE LETTER RA REPA;Lo;0;L;;;;;N;;;;;
-1B0C;BALINESE LETTER RA REPA TEDUNG;Lo;0;L;1B0B 1B35;;;;N;;;;;
-1B0D;BALINESE LETTER LA LENGA;Lo;0;L;;;;;N;;;;;
-1B0E;BALINESE LETTER LA LENGA TEDUNG;Lo;0;L;1B0D 1B35;;;;N;;;;;
-1B0F;BALINESE LETTER EKARA;Lo;0;L;;;;;N;;;;;
-1B10;BALINESE LETTER AIKARA;Lo;0;L;;;;;N;;;;;
-1B11;BALINESE LETTER OKARA;Lo;0;L;;;;;N;;;;;
-1B12;BALINESE LETTER OKARA TEDUNG;Lo;0;L;1B11 1B35;;;;N;;;;;
-1B13;BALINESE LETTER KA;Lo;0;L;;;;;N;;;;;
-1B14;BALINESE LETTER KA MAHAPRANA;Lo;0;L;;;;;N;;;;;
-1B15;BALINESE LETTER GA;Lo;0;L;;;;;N;;;;;
-1B16;BALINESE LETTER GA GORA;Lo;0;L;;;;;N;;;;;
-1B17;BALINESE LETTER NGA;Lo;0;L;;;;;N;;;;;
-1B18;BALINESE LETTER CA;Lo;0;L;;;;;N;;;;;
-1B19;BALINESE LETTER CA LACA;Lo;0;L;;;;;N;;;;;
-1B1A;BALINESE LETTER JA;Lo;0;L;;;;;N;;;;;
-1B1B;BALINESE LETTER JA JERA;Lo;0;L;;;;;N;;;;;
-1B1C;BALINESE LETTER NYA;Lo;0;L;;;;;N;;;;;
-1B1D;BALINESE LETTER TA LATIK;Lo;0;L;;;;;N;;;;;
-1B1E;BALINESE LETTER TA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;;
-1B1F;BALINESE LETTER DA MURDA ALPAPRANA;Lo;0;L;;;;;N;;;;;
-1B20;BALINESE LETTER DA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;;
-1B21;BALINESE LETTER NA RAMBAT;Lo;0;L;;;;;N;;;;;
-1B22;BALINESE LETTER TA;Lo;0;L;;;;;N;;;;;
-1B23;BALINESE LETTER TA TAWA;Lo;0;L;;;;;N;;;;;
-1B24;BALINESE LETTER DA;Lo;0;L;;;;;N;;;;;
-1B25;BALINESE LETTER DA MADU;Lo;0;L;;;;;N;;;;;
-1B26;BALINESE LETTER NA;Lo;0;L;;;;;N;;;;;
-1B27;BALINESE LETTER PA;Lo;0;L;;;;;N;;;;;
-1B28;BALINESE LETTER PA KAPAL;Lo;0;L;;;;;N;;;;;
-1B29;BALINESE LETTER BA;Lo;0;L;;;;;N;;;;;
-1B2A;BALINESE LETTER BA KEMBANG;Lo;0;L;;;;;N;;;;;
-1B2B;BALINESE LETTER MA;Lo;0;L;;;;;N;;;;;
-1B2C;BALINESE LETTER YA;Lo;0;L;;;;;N;;;;;
-1B2D;BALINESE LETTER RA;Lo;0;L;;;;;N;;;;;
-1B2E;BALINESE LETTER LA;Lo;0;L;;;;;N;;;;;
-1B2F;BALINESE LETTER WA;Lo;0;L;;;;;N;;;;;
-1B30;BALINESE LETTER SA SAGA;Lo;0;L;;;;;N;;;;;
-1B31;BALINESE LETTER SA SAPA;Lo;0;L;;;;;N;;;;;
-1B32;BALINESE LETTER SA;Lo;0;L;;;;;N;;;;;
-1B33;BALINESE LETTER HA;Lo;0;L;;;;;N;;;;;
-1B34;BALINESE SIGN REREKAN;Mn;7;NSM;;;;;N;;;;;
-1B35;BALINESE VOWEL SIGN TEDUNG;Mc;0;L;;;;;N;;;;;
-1B36;BALINESE VOWEL SIGN ULU;Mn;0;NSM;;;;;N;;;;;
-1B37;BALINESE VOWEL SIGN ULU SARI;Mn;0;NSM;;;;;N;;;;;
-1B38;BALINESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;;
-1B39;BALINESE VOWEL SIGN SUKU ILUT;Mn;0;NSM;;;;;N;;;;;
-1B3A;BALINESE VOWEL SIGN RA REPA;Mn;0;NSM;;;;;N;;;;;
-1B3B;BALINESE VOWEL SIGN RA REPA TEDUNG;Mc;0;L;1B3A 1B35;;;;N;;;;;
-1B3C;BALINESE VOWEL SIGN LA LENGA;Mn;0;NSM;;;;;N;;;;;
-1B3D;BALINESE VOWEL SIGN LA LENGA TEDUNG;Mc;0;L;1B3C 1B35;;;;N;;;;;
-1B3E;BALINESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;;
-1B3F;BALINESE VOWEL SIGN TALING REPA;Mc;0;L;;;;;N;;;;;
-1B40;BALINESE VOWEL SIGN TALING TEDUNG;Mc;0;L;1B3E 1B35;;;;N;;;;;
-1B41;BALINESE VOWEL SIGN TALING REPA TEDUNG;Mc;0;L;1B3F 1B35;;;;N;;;;;
-1B42;BALINESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;;
-1B43;BALINESE VOWEL SIGN PEPET TEDUNG;Mc;0;L;1B42 1B35;;;;N;;;;;
-1B44;BALINESE ADEG ADEG;Mc;9;L;;;;;N;;;;;
-1B45;BALINESE LETTER KAF SASAK;Lo;0;L;;;;;N;;;;;
-1B46;BALINESE LETTER KHOT SASAK;Lo;0;L;;;;;N;;;;;
-1B47;BALINESE LETTER TZIR SASAK;Lo;0;L;;;;;N;;;;;
-1B48;BALINESE LETTER EF SASAK;Lo;0;L;;;;;N;;;;;
-1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;;
-1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;;
-1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;;
-1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1B53;BALINESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1B54;BALINESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1B55;BALINESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1B56;BALINESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1B57;BALINESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1B58;BALINESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1B59;BALINESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-1B5A;BALINESE PANTI;Po;0;L;;;;;N;;;;;
-1B5B;BALINESE PAMADA;Po;0;L;;;;;N;;;;;
-1B5C;BALINESE WINDU;Po;0;L;;;;;N;;;;;
-1B5D;BALINESE CARIK PAMUNGKAH;Po;0;L;;;;;N;;;;;
-1B5E;BALINESE CARIK SIKI;Po;0;L;;;;;N;;;;;
-1B5F;BALINESE CARIK PAREREN;Po;0;L;;;;;N;;;;;
-1B60;BALINESE PAMENENG;Po;0;L;;;;;N;;;;;
-1B61;BALINESE MUSICAL SYMBOL DONG;So;0;L;;;;;N;;;;;
-1B62;BALINESE MUSICAL SYMBOL DENG;So;0;L;;;;;N;;;;;
-1B63;BALINESE MUSICAL SYMBOL DUNG;So;0;L;;;;;N;;;;;
-1B64;BALINESE MUSICAL SYMBOL DANG;So;0;L;;;;;N;;;;;
-1B65;BALINESE MUSICAL SYMBOL DANG SURANG;So;0;L;;;;;N;;;;;
-1B66;BALINESE MUSICAL SYMBOL DING;So;0;L;;;;;N;;;;;
-1B67;BALINESE MUSICAL SYMBOL DAENG;So;0;L;;;;;N;;;;;
-1B68;BALINESE MUSICAL SYMBOL DEUNG;So;0;L;;;;;N;;;;;
-1B69;BALINESE MUSICAL SYMBOL DAING;So;0;L;;;;;N;;;;;
-1B6A;BALINESE MUSICAL SYMBOL DANG GEDE;So;0;L;;;;;N;;;;;
-1B6B;BALINESE MUSICAL SYMBOL COMBINING TEGEH;Mn;230;NSM;;;;;N;;;;;
-1B6C;BALINESE MUSICAL SYMBOL COMBINING ENDEP;Mn;220;NSM;;;;;N;;;;;
-1B6D;BALINESE MUSICAL SYMBOL COMBINING KEMPUL;Mn;230;NSM;;;;;N;;;;;
-1B6E;BALINESE MUSICAL SYMBOL COMBINING KEMPLI;Mn;230;NSM;;;;;N;;;;;
-1B6F;BALINESE MUSICAL SYMBOL COMBINING JEGOGAN;Mn;230;NSM;;;;;N;;;;;
-1B70;BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;;
-1B71;BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;;
-1B72;BALINESE MUSICAL SYMBOL COMBINING BENDE;Mn;230;NSM;;;;;N;;;;;
-1B73;BALINESE MUSICAL SYMBOL COMBINING GONG;Mn;230;NSM;;;;;N;;;;;
-1B74;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG;So;0;L;;;;;N;;;;;
-1B75;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG;So;0;L;;;;;N;;;;;
-1B76;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK;So;0;L;;;;;N;;;;;
-1B77;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK;So;0;L;;;;;N;;;;;
-1B78;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG;So;0;L;;;;;N;;;;;
-1B79;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG;So;0;L;;;;;N;;;;;
-1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;;
-1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;;
-1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;;
-1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;;
-1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;;
-1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;;
-1B83;SUNDANESE LETTER A;Lo;0;L;;;;;N;;;;;
-1B84;SUNDANESE LETTER I;Lo;0;L;;;;;N;;;;;
-1B85;SUNDANESE LETTER U;Lo;0;L;;;;;N;;;;;
-1B86;SUNDANESE LETTER AE;Lo;0;L;;;;;N;;;;;
-1B87;SUNDANESE LETTER O;Lo;0;L;;;;;N;;;;;
-1B88;SUNDANESE LETTER E;Lo;0;L;;;;;N;;;;;
-1B89;SUNDANESE LETTER EU;Lo;0;L;;;;;N;;;;;
-1B8A;SUNDANESE LETTER KA;Lo;0;L;;;;;N;;;;;
-1B8B;SUNDANESE LETTER QA;Lo;0;L;;;;;N;;;;;
-1B8C;SUNDANESE LETTER GA;Lo;0;L;;;;;N;;;;;
-1B8D;SUNDANESE LETTER NGA;Lo;0;L;;;;;N;;;;;
-1B8E;SUNDANESE LETTER CA;Lo;0;L;;;;;N;;;;;
-1B8F;SUNDANESE LETTER JA;Lo;0;L;;;;;N;;;;;
-1B90;SUNDANESE LETTER ZA;Lo;0;L;;;;;N;;;;;
-1B91;SUNDANESE LETTER NYA;Lo;0;L;;;;;N;;;;;
-1B92;SUNDANESE LETTER TA;Lo;0;L;;;;;N;;;;;
-1B93;SUNDANESE LETTER DA;Lo;0;L;;;;;N;;;;;
-1B94;SUNDANESE LETTER NA;Lo;0;L;;;;;N;;;;;
-1B95;SUNDANESE LETTER PA;Lo;0;L;;;;;N;;;;;
-1B96;SUNDANESE LETTER FA;Lo;0;L;;;;;N;;;;;
-1B97;SUNDANESE LETTER VA;Lo;0;L;;;;;N;;;;;
-1B98;SUNDANESE LETTER BA;Lo;0;L;;;;;N;;;;;
-1B99;SUNDANESE LETTER MA;Lo;0;L;;;;;N;;;;;
-1B9A;SUNDANESE LETTER YA;Lo;0;L;;;;;N;;;;;
-1B9B;SUNDANESE LETTER RA;Lo;0;L;;;;;N;;;;;
-1B9C;SUNDANESE LETTER LA;Lo;0;L;;;;;N;;;;;
-1B9D;SUNDANESE LETTER WA;Lo;0;L;;;;;N;;;;;
-1B9E;SUNDANESE LETTER SA;Lo;0;L;;;;;N;;;;;
-1B9F;SUNDANESE LETTER XA;Lo;0;L;;;;;N;;;;;
-1BA0;SUNDANESE LETTER HA;Lo;0;L;;;;;N;;;;;
-1BA1;SUNDANESE CONSONANT SIGN PAMINGKAL;Mc;0;L;;;;;N;;;;;
-1BA2;SUNDANESE CONSONANT SIGN PANYAKRA;Mn;0;NSM;;;;;N;;;;;
-1BA3;SUNDANESE CONSONANT SIGN PANYIKU;Mn;0;NSM;;;;;N;;;;;
-1BA4;SUNDANESE VOWEL SIGN PANGHULU;Mn;0;NSM;;;;;N;;;;;
-1BA5;SUNDANESE VOWEL SIGN PANYUKU;Mn;0;NSM;;;;;N;;;;;
-1BA6;SUNDANESE VOWEL SIGN PANAELAENG;Mc;0;L;;;;;N;;;;;
-1BA7;SUNDANESE VOWEL SIGN PANOLONG;Mc;0;L;;;;;N;;;;;
-1BA8;SUNDANESE VOWEL SIGN PAMEPET;Mn;0;NSM;;;;;N;;;;;
-1BA9;SUNDANESE VOWEL SIGN PANEULEUNG;Mn;0;NSM;;;;;N;;;;;
-1BAA;SUNDANESE SIGN PAMAAEH;Mc;9;L;;;;;N;;;;;
-1BAB;SUNDANESE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-1BAC;SUNDANESE CONSONANT SIGN PASANGAN MA;Mc;0;L;;;;;N;;;;;
-1BAD;SUNDANESE CONSONANT SIGN PASANGAN WA;Mc;0;L;;;;;N;;;;;
-1BAE;SUNDANESE LETTER KHA;Lo;0;L;;;;;N;;;;;
-1BAF;SUNDANESE LETTER SYA;Lo;0;L;;;;;N;;;;;
-1BB0;SUNDANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1BB1;SUNDANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1BB2;SUNDANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1BB3;SUNDANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1BB4;SUNDANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1BB5;SUNDANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1BB6;SUNDANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1BB7;SUNDANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1BB8;SUNDANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1BB9;SUNDANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-1BBA;SUNDANESE AVAGRAHA;Lo;0;L;;;;;N;;;;;
-1BBB;SUNDANESE LETTER REU;Lo;0;L;;;;;N;;;;;
-1BBC;SUNDANESE LETTER LEU;Lo;0;L;;;;;N;;;;;
-1BBD;SUNDANESE LETTER BHA;Lo;0;L;;;;;N;;;;;
-1BBE;SUNDANESE LETTER FINAL K;Lo;0;L;;;;;N;;;;;
-1BBF;SUNDANESE LETTER FINAL M;Lo;0;L;;;;;N;;;;;
-1BC0;BATAK LETTER A;Lo;0;L;;;;;N;;;;;
-1BC1;BATAK LETTER SIMALUNGUN A;Lo;0;L;;;;;N;;;;;
-1BC2;BATAK LETTER HA;Lo;0;L;;;;;N;;;;;
-1BC3;BATAK LETTER SIMALUNGUN HA;Lo;0;L;;;;;N;;;;;
-1BC4;BATAK LETTER MANDAILING HA;Lo;0;L;;;;;N;;;;;
-1BC5;BATAK LETTER BA;Lo;0;L;;;;;N;;;;;
-1BC6;BATAK LETTER KARO BA;Lo;0;L;;;;;N;;;;;
-1BC7;BATAK LETTER PA;Lo;0;L;;;;;N;;;;;
-1BC8;BATAK LETTER SIMALUNGUN PA;Lo;0;L;;;;;N;;;;;
-1BC9;BATAK LETTER NA;Lo;0;L;;;;;N;;;;;
-1BCA;BATAK LETTER MANDAILING NA;Lo;0;L;;;;;N;;;;;
-1BCB;BATAK LETTER WA;Lo;0;L;;;;;N;;;;;
-1BCC;BATAK LETTER SIMALUNGUN WA;Lo;0;L;;;;;N;;;;;
-1BCD;BATAK LETTER PAKPAK WA;Lo;0;L;;;;;N;;;;;
-1BCE;BATAK LETTER GA;Lo;0;L;;;;;N;;;;;
-1BCF;BATAK LETTER SIMALUNGUN GA;Lo;0;L;;;;;N;;;;;
-1BD0;BATAK LETTER JA;Lo;0;L;;;;;N;;;;;
-1BD1;BATAK LETTER DA;Lo;0;L;;;;;N;;;;;
-1BD2;BATAK LETTER RA;Lo;0;L;;;;;N;;;;;
-1BD3;BATAK LETTER SIMALUNGUN RA;Lo;0;L;;;;;N;;;;;
-1BD4;BATAK LETTER MA;Lo;0;L;;;;;N;;;;;
-1BD5;BATAK LETTER SIMALUNGUN MA;Lo;0;L;;;;;N;;;;;
-1BD6;BATAK LETTER SOUTHERN TA;Lo;0;L;;;;;N;;;;;
-1BD7;BATAK LETTER NORTHERN TA;Lo;0;L;;;;;N;;;;;
-1BD8;BATAK LETTER SA;Lo;0;L;;;;;N;;;;;
-1BD9;BATAK LETTER SIMALUNGUN SA;Lo;0;L;;;;;N;;;;;
-1BDA;BATAK LETTER MANDAILING SA;Lo;0;L;;;;;N;;;;;
-1BDB;BATAK LETTER YA;Lo;0;L;;;;;N;;;;;
-1BDC;BATAK LETTER SIMALUNGUN YA;Lo;0;L;;;;;N;;;;;
-1BDD;BATAK LETTER NGA;Lo;0;L;;;;;N;;;;;
-1BDE;BATAK LETTER LA;Lo;0;L;;;;;N;;;;;
-1BDF;BATAK LETTER SIMALUNGUN LA;Lo;0;L;;;;;N;;;;;
-1BE0;BATAK LETTER NYA;Lo;0;L;;;;;N;;;;;
-1BE1;BATAK LETTER CA;Lo;0;L;;;;;N;;;;;
-1BE2;BATAK LETTER NDA;Lo;0;L;;;;;N;;;;;
-1BE3;BATAK LETTER MBA;Lo;0;L;;;;;N;;;;;
-1BE4;BATAK LETTER I;Lo;0;L;;;;;N;;;;;
-1BE5;BATAK LETTER U;Lo;0;L;;;;;N;;;;;
-1BE6;BATAK SIGN TOMPI;Mn;7;NSM;;;;;N;;;;;
-1BE7;BATAK VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-1BE8;BATAK VOWEL SIGN PAKPAK E;Mn;0;NSM;;;;;N;;;;;
-1BE9;BATAK VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;;
-1BEA;BATAK VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-1BEB;BATAK VOWEL SIGN KARO I;Mc;0;L;;;;;N;;;;;
-1BEC;BATAK VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-1BED;BATAK VOWEL SIGN KARO O;Mn;0;NSM;;;;;N;;;;;
-1BEE;BATAK VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-1BEF;BATAK VOWEL SIGN U FOR SIMALUNGUN SA;Mn;0;NSM;;;;;N;;;;;
-1BF0;BATAK CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;;
-1BF1;BATAK CONSONANT SIGN H;Mn;0;NSM;;;;;N;;;;;
-1BF2;BATAK PANGOLAT;Mc;9;L;;;;;N;;;;;
-1BF3;BATAK PANONGONAN;Mc;9;L;;;;;N;;;;;
-1BFC;BATAK SYMBOL BINDU NA METEK;Po;0;L;;;;;N;;;;;
-1BFD;BATAK SYMBOL BINDU PINARBORAS;Po;0;L;;;;;N;;;;;
-1BFE;BATAK SYMBOL BINDU JUDUL;Po;0;L;;;;;N;;;;;
-1BFF;BATAK SYMBOL BINDU PANGOLAT;Po;0;L;;;;;N;;;;;
-1C00;LEPCHA LETTER KA;Lo;0;L;;;;;N;;;;;
-1C01;LEPCHA LETTER KLA;Lo;0;L;;;;;N;;;;;
-1C02;LEPCHA LETTER KHA;Lo;0;L;;;;;N;;;;;
-1C03;LEPCHA LETTER GA;Lo;0;L;;;;;N;;;;;
-1C04;LEPCHA LETTER GLA;Lo;0;L;;;;;N;;;;;
-1C05;LEPCHA LETTER NGA;Lo;0;L;;;;;N;;;;;
-1C06;LEPCHA LETTER CA;Lo;0;L;;;;;N;;;;;
-1C07;LEPCHA LETTER CHA;Lo;0;L;;;;;N;;;;;
-1C08;LEPCHA LETTER JA;Lo;0;L;;;;;N;;;;;
-1C09;LEPCHA LETTER NYA;Lo;0;L;;;;;N;;;;;
-1C0A;LEPCHA LETTER TA;Lo;0;L;;;;;N;;;;;
-1C0B;LEPCHA LETTER THA;Lo;0;L;;;;;N;;;;;
-1C0C;LEPCHA LETTER DA;Lo;0;L;;;;;N;;;;;
-1C0D;LEPCHA LETTER NA;Lo;0;L;;;;;N;;;;;
-1C0E;LEPCHA LETTER PA;Lo;0;L;;;;;N;;;;;
-1C0F;LEPCHA LETTER PLA;Lo;0;L;;;;;N;;;;;
-1C10;LEPCHA LETTER PHA;Lo;0;L;;;;;N;;;;;
-1C11;LEPCHA LETTER FA;Lo;0;L;;;;;N;;;;;
-1C12;LEPCHA LETTER FLA;Lo;0;L;;;;;N;;;;;
-1C13;LEPCHA LETTER BA;Lo;0;L;;;;;N;;;;;
-1C14;LEPCHA LETTER BLA;Lo;0;L;;;;;N;;;;;
-1C15;LEPCHA LETTER MA;Lo;0;L;;;;;N;;;;;
-1C16;LEPCHA LETTER MLA;Lo;0;L;;;;;N;;;;;
-1C17;LEPCHA LETTER TSA;Lo;0;L;;;;;N;;;;;
-1C18;LEPCHA LETTER TSHA;Lo;0;L;;;;;N;;;;;
-1C19;LEPCHA LETTER DZA;Lo;0;L;;;;;N;;;;;
-1C1A;LEPCHA LETTER YA;Lo;0;L;;;;;N;;;;;
-1C1B;LEPCHA LETTER RA;Lo;0;L;;;;;N;;;;;
-1C1C;LEPCHA LETTER LA;Lo;0;L;;;;;N;;;;;
-1C1D;LEPCHA LETTER HA;Lo;0;L;;;;;N;;;;;
-1C1E;LEPCHA LETTER HLA;Lo;0;L;;;;;N;;;;;
-1C1F;LEPCHA LETTER VA;Lo;0;L;;;;;N;;;;;
-1C20;LEPCHA LETTER SA;Lo;0;L;;;;;N;;;;;
-1C21;LEPCHA LETTER SHA;Lo;0;L;;;;;N;;;;;
-1C22;LEPCHA LETTER WA;Lo;0;L;;;;;N;;;;;
-1C23;LEPCHA LETTER A;Lo;0;L;;;;;N;;;;;
-1C24;LEPCHA SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;;
-1C25;LEPCHA SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;;
-1C26;LEPCHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-1C27;LEPCHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-1C28;LEPCHA VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-1C29;LEPCHA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
-1C2A;LEPCHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-1C2B;LEPCHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
-1C2C;LEPCHA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-1C2D;LEPCHA CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;;
-1C2E;LEPCHA CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;;
-1C2F;LEPCHA CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;;
-1C30;LEPCHA CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;;
-1C31;LEPCHA CONSONANT SIGN P;Mn;0;NSM;;;;;N;;;;;
-1C32;LEPCHA CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;;
-1C33;LEPCHA CONSONANT SIGN T;Mn;0;NSM;;;;;N;;;;;
-1C34;LEPCHA CONSONANT SIGN NYIN-DO;Mc;0;L;;;;;N;;;;;
-1C35;LEPCHA CONSONANT SIGN KANG;Mc;0;L;;;;;N;;;;;
-1C36;LEPCHA SIGN RAN;Mn;0;NSM;;;;;N;;;;;
-1C37;LEPCHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-1C3B;LEPCHA PUNCTUATION TA-ROL;Po;0;L;;;;;N;;;;;
-1C3C;LEPCHA PUNCTUATION NYET THYOOM TA-ROL;Po;0;L;;;;;N;;;;;
-1C3D;LEPCHA PUNCTUATION CER-WA;Po;0;L;;;;;N;;;;;
-1C3E;LEPCHA PUNCTUATION TSHOOK CER-WA;Po;0;L;;;;;N;;;;;
-1C3F;LEPCHA PUNCTUATION TSHOOK;Po;0;L;;;;;N;;;;;
-1C40;LEPCHA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1C41;LEPCHA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1C42;LEPCHA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1C43;LEPCHA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1C44;LEPCHA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1C45;LEPCHA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1C46;LEPCHA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1C47;LEPCHA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1C48;LEPCHA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1C49;LEPCHA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-1C4D;LEPCHA LETTER TTA;Lo;0;L;;;;;N;;;;;
-1C4E;LEPCHA LETTER TTHA;Lo;0;L;;;;;N;;;;;
-1C4F;LEPCHA LETTER DDA;Lo;0;L;;;;;N;;;;;
-1C50;OL CHIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-1C51;OL CHIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-1C52;OL CHIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-1C53;OL CHIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1C54;OL CHIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1C55;OL CHIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1C56;OL CHIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1C57;OL CHIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1C58;OL CHIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1C59;OL CHIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-1C5A;OL CHIKI LETTER LA;Lo;0;L;;;;;N;;;;;
-1C5B;OL CHIKI LETTER AT;Lo;0;L;;;;;N;;;;;
-1C5C;OL CHIKI LETTER AG;Lo;0;L;;;;;N;;;;;
-1C5D;OL CHIKI LETTER ANG;Lo;0;L;;;;;N;;;;;
-1C5E;OL CHIKI LETTER AL;Lo;0;L;;;;;N;;;;;
-1C5F;OL CHIKI LETTER LAA;Lo;0;L;;;;;N;;;;;
-1C60;OL CHIKI LETTER AAK;Lo;0;L;;;;;N;;;;;
-1C61;OL CHIKI LETTER AAJ;Lo;0;L;;;;;N;;;;;
-1C62;OL CHIKI LETTER AAM;Lo;0;L;;;;;N;;;;;
-1C63;OL CHIKI LETTER AAW;Lo;0;L;;;;;N;;;;;
-1C64;OL CHIKI LETTER LI;Lo;0;L;;;;;N;;;;;
-1C65;OL CHIKI LETTER IS;Lo;0;L;;;;;N;;;;;
-1C66;OL CHIKI LETTER IH;Lo;0;L;;;;;N;;;;;
-1C67;OL CHIKI LETTER INY;Lo;0;L;;;;;N;;;;;
-1C68;OL CHIKI LETTER IR;Lo;0;L;;;;;N;;;;;
-1C69;OL CHIKI LETTER LU;Lo;0;L;;;;;N;;;;;
-1C6A;OL CHIKI LETTER UC;Lo;0;L;;;;;N;;;;;
-1C6B;OL CHIKI LETTER UD;Lo;0;L;;;;;N;;;;;
-1C6C;OL CHIKI LETTER UNN;Lo;0;L;;;;;N;;;;;
-1C6D;OL CHIKI LETTER UY;Lo;0;L;;;;;N;;;;;
-1C6E;OL CHIKI LETTER LE;Lo;0;L;;;;;N;;;;;
-1C6F;OL CHIKI LETTER EP;Lo;0;L;;;;;N;;;;;
-1C70;OL CHIKI LETTER EDD;Lo;0;L;;;;;N;;;;;
-1C71;OL CHIKI LETTER EN;Lo;0;L;;;;;N;;;;;
-1C72;OL CHIKI LETTER ERR;Lo;0;L;;;;;N;;;;;
-1C73;OL CHIKI LETTER LO;Lo;0;L;;;;;N;;;;;
-1C74;OL CHIKI LETTER OTT;Lo;0;L;;;;;N;;;;;
-1C75;OL CHIKI LETTER OB;Lo;0;L;;;;;N;;;;;
-1C76;OL CHIKI LETTER OV;Lo;0;L;;;;;N;;;;;
-1C77;OL CHIKI LETTER OH;Lo;0;L;;;;;N;;;;;
-1C78;OL CHIKI MU TTUDDAG;Lm;0;L;;;;;N;;;;;
-1C79;OL CHIKI GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;;
-1C7A;OL CHIKI MU-GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;;
-1C7B;OL CHIKI RELAA;Lm;0;L;;;;;N;;;;;
-1C7C;OL CHIKI PHAARKAA;Lm;0;L;;;;;N;;;;;
-1C7D;OL CHIKI AHAD;Lm;0;L;;;;;N;;;;;
-1C7E;OL CHIKI PUNCTUATION MUCAAD;Po;0;L;;;;;N;;;;;
-1C7F;OL CHIKI PUNCTUATION DOUBLE MUCAAD;Po;0;L;;;;;N;;;;;
-1CC0;SUNDANESE PUNCTUATION BINDU SURYA;Po;0;L;;;;;N;;;;;
-1CC1;SUNDANESE PUNCTUATION BINDU PANGLONG;Po;0;L;;;;;N;;;;;
-1CC2;SUNDANESE PUNCTUATION BINDU PURNAMA;Po;0;L;;;;;N;;;;;
-1CC3;SUNDANESE PUNCTUATION BINDU CAKRA;Po;0;L;;;;;N;;;;;
-1CC4;SUNDANESE PUNCTUATION BINDU LEU SATANGA;Po;0;L;;;;;N;;;;;
-1CC5;SUNDANESE PUNCTUATION BINDU KA SATANGA;Po;0;L;;;;;N;;;;;
-1CC6;SUNDANESE PUNCTUATION BINDU DA SATANGA;Po;0;L;;;;;N;;;;;
-1CC7;SUNDANESE PUNCTUATION BINDU BA SATANGA;Po;0;L;;;;;N;;;;;
-1CD0;VEDIC TONE KARSHANA;Mn;230;NSM;;;;;N;;;;;
-1CD1;VEDIC TONE SHARA;Mn;230;NSM;;;;;N;;;;;
-1CD2;VEDIC TONE PRENKHA;Mn;230;NSM;;;;;N;;;;;
-1CD3;VEDIC SIGN NIHSHVASA;Po;0;L;;;;;N;;;;;
-1CD4;VEDIC SIGN YAJURVEDIC MIDLINE SVARITA;Mn;1;NSM;;;;;N;;;;;
-1CD5;VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;;
-1CD6;VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;;
-1CD7;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;;
-1CD8;VEDIC TONE CANDRA BELOW;Mn;220;NSM;;;;;N;;;;;
-1CD9;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER;Mn;220;NSM;;;;;N;;;;;
-1CDA;VEDIC TONE DOUBLE SVARITA;Mn;230;NSM;;;;;N;;;;;
-1CDB;VEDIC TONE TRIPLE SVARITA;Mn;230;NSM;;;;;N;;;;;
-1CDC;VEDIC TONE KATHAKA ANUDATTA;Mn;220;NSM;;;;;N;;;;;
-1CDD;VEDIC TONE DOT BELOW;Mn;220;NSM;;;;;N;;;;;
-1CDE;VEDIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
-1CDF;VEDIC TONE THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
-1CE0;VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA;Mn;230;NSM;;;;;N;;;;;
-1CE1;VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA;Mc;0;L;;;;;N;;;;;
-1CE2;VEDIC SIGN VISARGA SVARITA;Mn;1;NSM;;;;;N;;;;;
-1CE3;VEDIC SIGN VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;;
-1CE4;VEDIC SIGN REVERSED VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;;
-1CE5;VEDIC SIGN VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;;
-1CE6;VEDIC SIGN REVERSED VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;;
-1CE7;VEDIC SIGN VISARGA UDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;;
-1CE8;VEDIC SIGN VISARGA ANUDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;;
-1CE9;VEDIC SIGN ANUSVARA ANTARGOMUKHA;Lo;0;L;;;;;N;;;;;
-1CEA;VEDIC SIGN ANUSVARA BAHIRGOMUKHA;Lo;0;L;;;;;N;;;;;
-1CEB;VEDIC SIGN ANUSVARA VAMAGOMUKHA;Lo;0;L;;;;;N;;;;;
-1CEC;VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL;Lo;0;L;;;;;N;;;;;
-1CED;VEDIC SIGN TIRYAK;Mn;220;NSM;;;;;N;;;;;
-1CEE;VEDIC SIGN HEXIFORM LONG ANUSVARA;Lo;0;L;;;;;N;;;;;
-1CEF;VEDIC SIGN LONG ANUSVARA;Lo;0;L;;;;;N;;;;;
-1CF0;VEDIC SIGN RTHANG LONG ANUSVARA;Lo;0;L;;;;;N;;;;;
-1CF1;VEDIC SIGN ANUSVARA UBHAYATO MUKHA;Lo;0;L;;;;;N;;;;;
-1CF2;VEDIC SIGN ARDHAVISARGA;Mc;0;L;;;;;N;;;;;
-1CF3;VEDIC SIGN ROTATED ARDHAVISARGA;Mc;0;L;;;;;N;;;;;
-1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;;
-1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;;
-1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;;
-1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;;
-1D01;LATIN LETTER SMALL CAPITAL AE;Ll;0;L;;;;;N;;;;;
-1D02;LATIN SMALL LETTER TURNED AE;Ll;0;L;;;;;N;;;;;
-1D03;LATIN LETTER SMALL CAPITAL BARRED B;Ll;0;L;;;;;N;;;;;
-1D04;LATIN LETTER SMALL CAPITAL C;Ll;0;L;;;;;N;;;;;
-1D05;LATIN LETTER SMALL CAPITAL D;Ll;0;L;;;;;N;;;;;
-1D06;LATIN LETTER SMALL CAPITAL ETH;Ll;0;L;;;;;N;;;;;
-1D07;LATIN LETTER SMALL CAPITAL E;Ll;0;L;;;;;N;;;;;
-1D08;LATIN SMALL LETTER TURNED OPEN E;Ll;0;L;;;;;N;;;;;
-1D09;LATIN SMALL LETTER TURNED I;Ll;0;L;;;;;N;;;;;
-1D0A;LATIN LETTER SMALL CAPITAL J;Ll;0;L;;;;;N;;;;;
-1D0B;LATIN LETTER SMALL CAPITAL K;Ll;0;L;;;;;N;;;;;
-1D0C;LATIN LETTER SMALL CAPITAL L WITH STROKE;Ll;0;L;;;;;N;;;;;
-1D0D;LATIN LETTER SMALL CAPITAL M;Ll;0;L;;;;;N;;;;;
-1D0E;LATIN LETTER SMALL CAPITAL REVERSED N;Ll;0;L;;;;;N;;;;;
-1D0F;LATIN LETTER SMALL CAPITAL O;Ll;0;L;;;;;N;;;;;
-1D10;LATIN LETTER SMALL CAPITAL OPEN O;Ll;0;L;;;;;N;;;;;
-1D11;LATIN SMALL LETTER SIDEWAYS O;Ll;0;L;;;;;N;;;;;
-1D12;LATIN SMALL LETTER SIDEWAYS OPEN O;Ll;0;L;;;;;N;;;;;
-1D13;LATIN SMALL LETTER SIDEWAYS O WITH STROKE;Ll;0;L;;;;;N;;;;;
-1D14;LATIN SMALL LETTER TURNED OE;Ll;0;L;;;;;N;;;;;
-1D15;LATIN LETTER SMALL CAPITAL OU;Ll;0;L;;;;;N;;;;;
-1D16;LATIN SMALL LETTER TOP HALF O;Ll;0;L;;;;;N;;;;;
-1D17;LATIN SMALL LETTER BOTTOM HALF O;Ll;0;L;;;;;N;;;;;
-1D18;LATIN LETTER SMALL CAPITAL P;Ll;0;L;;;;;N;;;;;
-1D19;LATIN LETTER SMALL CAPITAL REVERSED R;Ll;0;L;;;;;N;;;;;
-1D1A;LATIN LETTER SMALL CAPITAL TURNED R;Ll;0;L;;;;;N;;;;;
-1D1B;LATIN LETTER SMALL CAPITAL T;Ll;0;L;;;;;N;;;;;
-1D1C;LATIN LETTER SMALL CAPITAL U;Ll;0;L;;;;;N;;;;;
-1D1D;LATIN SMALL LETTER SIDEWAYS U;Ll;0;L;;;;;N;;;;;
-1D1E;LATIN SMALL LETTER SIDEWAYS DIAERESIZED U;Ll;0;L;;;;;N;;;;;
-1D1F;LATIN SMALL LETTER SIDEWAYS TURNED M;Ll;0;L;;;;;N;;;;;
-1D20;LATIN LETTER SMALL CAPITAL V;Ll;0;L;;;;;N;;;;;
-1D21;LATIN LETTER SMALL CAPITAL W;Ll;0;L;;;;;N;;;;;
-1D22;LATIN LETTER SMALL CAPITAL Z;Ll;0;L;;;;;N;;;;;
-1D23;LATIN LETTER SMALL CAPITAL EZH;Ll;0;L;;;;;N;;;;;
-1D24;LATIN LETTER VOICED LARYNGEAL SPIRANT;Ll;0;L;;;;;N;;;;;
-1D25;LATIN LETTER AIN;Ll;0;L;;;;;N;;;;;
-1D26;GREEK LETTER SMALL CAPITAL GAMMA;Ll;0;L;;;;;N;;;;;
-1D27;GREEK LETTER SMALL CAPITAL LAMDA;Ll;0;L;;;;;N;;;;;
-1D28;GREEK LETTER SMALL CAPITAL PI;Ll;0;L;;;;;N;;;;;
-1D29;GREEK LETTER SMALL CAPITAL RHO;Ll;0;L;;;;;N;;;;;
-1D2A;GREEK LETTER SMALL CAPITAL PSI;Ll;0;L;;;;;N;;;;;
-1D2B;CYRILLIC LETTER SMALL CAPITAL EL;Ll;0;L;;;;;N;;;;;
-1D2C;MODIFIER LETTER CAPITAL A;Lm;0;L;<super> 0041;;;;N;;;;;
-1D2D;MODIFIER LETTER CAPITAL AE;Lm;0;L;<super> 00C6;;;;N;;;;;
-1D2E;MODIFIER LETTER CAPITAL B;Lm;0;L;<super> 0042;;;;N;;;;;
-1D2F;MODIFIER LETTER CAPITAL BARRED B;Lm;0;L;;;;;N;;;;;
-1D30;MODIFIER LETTER CAPITAL D;Lm;0;L;<super> 0044;;;;N;;;;;
-1D31;MODIFIER LETTER CAPITAL E;Lm;0;L;<super> 0045;;;;N;;;;;
-1D32;MODIFIER LETTER CAPITAL REVERSED E;Lm;0;L;<super> 018E;;;;N;;;;;
-1D33;MODIFIER LETTER CAPITAL G;Lm;0;L;<super> 0047;;;;N;;;;;
-1D34;MODIFIER LETTER CAPITAL H;Lm;0;L;<super> 0048;;;;N;;;;;
-1D35;MODIFIER LETTER CAPITAL I;Lm;0;L;<super> 0049;;;;N;;;;;
-1D36;MODIFIER LETTER CAPITAL J;Lm;0;L;<super> 004A;;;;N;;;;;
-1D37;MODIFIER LETTER CAPITAL K;Lm;0;L;<super> 004B;;;;N;;;;;
-1D38;MODIFIER LETTER CAPITAL L;Lm;0;L;<super> 004C;;;;N;;;;;
-1D39;MODIFIER LETTER CAPITAL M;Lm;0;L;<super> 004D;;;;N;;;;;
-1D3A;MODIFIER LETTER CAPITAL N;Lm;0;L;<super> 004E;;;;N;;;;;
-1D3B;MODIFIER LETTER CAPITAL REVERSED N;Lm;0;L;;;;;N;;;;;
-1D3C;MODIFIER LETTER CAPITAL O;Lm;0;L;<super> 004F;;;;N;;;;;
-1D3D;MODIFIER LETTER CAPITAL OU;Lm;0;L;<super> 0222;;;;N;;;;;
-1D3E;MODIFIER LETTER CAPITAL P;Lm;0;L;<super> 0050;;;;N;;;;;
-1D3F;MODIFIER LETTER CAPITAL R;Lm;0;L;<super> 0052;;;;N;;;;;
-1D40;MODIFIER LETTER CAPITAL T;Lm;0;L;<super> 0054;;;;N;;;;;
-1D41;MODIFIER LETTER CAPITAL U;Lm;0;L;<super> 0055;;;;N;;;;;
-1D42;MODIFIER LETTER CAPITAL W;Lm;0;L;<super> 0057;;;;N;;;;;
-1D43;MODIFIER LETTER SMALL A;Lm;0;L;<super> 0061;;;;N;;;;;
-1D44;MODIFIER LETTER SMALL TURNED A;Lm;0;L;<super> 0250;;;;N;;;;;
-1D45;MODIFIER LETTER SMALL ALPHA;Lm;0;L;<super> 0251;;;;N;;;;;
-1D46;MODIFIER LETTER SMALL TURNED AE;Lm;0;L;<super> 1D02;;;;N;;;;;
-1D47;MODIFIER LETTER SMALL B;Lm;0;L;<super> 0062;;;;N;;;;;
-1D48;MODIFIER LETTER SMALL D;Lm;0;L;<super> 0064;;;;N;;;;;
-1D49;MODIFIER LETTER SMALL E;Lm;0;L;<super> 0065;;;;N;;;;;
-1D4A;MODIFIER LETTER SMALL SCHWA;Lm;0;L;<super> 0259;;;;N;;;;;
-1D4B;MODIFIER LETTER SMALL OPEN E;Lm;0;L;<super> 025B;;;;N;;;;;
-1D4C;MODIFIER LETTER SMALL TURNED OPEN E;Lm;0;L;<super> 025C;;;;N;;;;;
-1D4D;MODIFIER LETTER SMALL G;Lm;0;L;<super> 0067;;;;N;;;;;
-1D4E;MODIFIER LETTER SMALL TURNED I;Lm;0;L;;;;;N;;;;;
-1D4F;MODIFIER LETTER SMALL K;Lm;0;L;<super> 006B;;;;N;;;;;
-1D50;MODIFIER LETTER SMALL M;Lm;0;L;<super> 006D;;;;N;;;;;
-1D51;MODIFIER LETTER SMALL ENG;Lm;0;L;<super> 014B;;;;N;;;;;
-1D52;MODIFIER LETTER SMALL O;Lm;0;L;<super> 006F;;;;N;;;;;
-1D53;MODIFIER LETTER SMALL OPEN O;Lm;0;L;<super> 0254;;;;N;;;;;
-1D54;MODIFIER LETTER SMALL TOP HALF O;Lm;0;L;<super> 1D16;;;;N;;;;;
-1D55;MODIFIER LETTER SMALL BOTTOM HALF O;Lm;0;L;<super> 1D17;;;;N;;;;;
-1D56;MODIFIER LETTER SMALL P;Lm;0;L;<super> 0070;;;;N;;;;;
-1D57;MODIFIER LETTER SMALL T;Lm;0;L;<super> 0074;;;;N;;;;;
-1D58;MODIFIER LETTER SMALL U;Lm;0;L;<super> 0075;;;;N;;;;;
-1D59;MODIFIER LETTER SMALL SIDEWAYS U;Lm;0;L;<super> 1D1D;;;;N;;;;;
-1D5A;MODIFIER LETTER SMALL TURNED M;Lm;0;L;<super> 026F;;;;N;;;;;
-1D5B;MODIFIER LETTER SMALL V;Lm;0;L;<super> 0076;;;;N;;;;;
-1D5C;MODIFIER LETTER SMALL AIN;Lm;0;L;<super> 1D25;;;;N;;;;;
-1D5D;MODIFIER LETTER SMALL BETA;Lm;0;L;<super> 03B2;;;;N;;;;;
-1D5E;MODIFIER LETTER SMALL GREEK GAMMA;Lm;0;L;<super> 03B3;;;;N;;;;;
-1D5F;MODIFIER LETTER SMALL DELTA;Lm;0;L;<super> 03B4;;;;N;;;;;
-1D60;MODIFIER LETTER SMALL GREEK PHI;Lm;0;L;<super> 03C6;;;;N;;;;;
-1D61;MODIFIER LETTER SMALL CHI;Lm;0;L;<super> 03C7;;;;N;;;;;
-1D62;LATIN SUBSCRIPT SMALL LETTER I;Lm;0;L;<sub> 0069;;;;N;;;;;
-1D63;LATIN SUBSCRIPT SMALL LETTER R;Lm;0;L;<sub> 0072;;;;N;;;;;
-1D64;LATIN SUBSCRIPT SMALL LETTER U;Lm;0;L;<sub> 0075;;;;N;;;;;
-1D65;LATIN SUBSCRIPT SMALL LETTER V;Lm;0;L;<sub> 0076;;;;N;;;;;
-1D66;GREEK SUBSCRIPT SMALL LETTER BETA;Lm;0;L;<sub> 03B2;;;;N;;;;;
-1D67;GREEK SUBSCRIPT SMALL LETTER GAMMA;Lm;0;L;<sub> 03B3;;;;N;;;;;
-1D68;GREEK SUBSCRIPT SMALL LETTER RHO;Lm;0;L;<sub> 03C1;;;;N;;;;;
-1D69;GREEK SUBSCRIPT SMALL LETTER PHI;Lm;0;L;<sub> 03C6;;;;N;;;;;
-1D6A;GREEK SUBSCRIPT SMALL LETTER CHI;Lm;0;L;<sub> 03C7;;;;N;;;;;
-1D6B;LATIN SMALL LETTER UE;Ll;0;L;;;;;N;;;;;
-1D6C;LATIN SMALL LETTER B WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D6D;LATIN SMALL LETTER D WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D6E;LATIN SMALL LETTER F WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D6F;LATIN SMALL LETTER M WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D70;LATIN SMALL LETTER N WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D71;LATIN SMALL LETTER P WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D72;LATIN SMALL LETTER R WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D73;LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D74;LATIN SMALL LETTER S WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D75;LATIN SMALL LETTER T WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D76;LATIN SMALL LETTER Z WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
-1D77;LATIN SMALL LETTER TURNED G;Ll;0;L;;;;;N;;;;;
-1D78;MODIFIER LETTER CYRILLIC EN;Lm;0;L;<super> 043D;;;;N;;;;;
-1D79;LATIN SMALL LETTER INSULAR G;Ll;0;L;;;;;N;;;A77D;;A77D
-1D7A;LATIN SMALL LETTER TH WITH STRIKETHROUGH;Ll;0;L;;;;;N;;;;;
-1D7B;LATIN SMALL CAPITAL LETTER I WITH STROKE;Ll;0;L;;;;;N;;;;;
-1D7C;LATIN SMALL LETTER IOTA WITH STROKE;Ll;0;L;;;;;N;;;;;
-1D7D;LATIN SMALL LETTER P WITH STROKE;Ll;0;L;;;;;N;;;2C63;;2C63
-1D7E;LATIN SMALL CAPITAL LETTER U WITH STROKE;Ll;0;L;;;;;N;;;;;
-1D7F;LATIN SMALL LETTER UPSILON WITH STROKE;Ll;0;L;;;;;N;;;;;
-1D80;LATIN SMALL LETTER B WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D81;LATIN SMALL LETTER D WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D82;LATIN SMALL LETTER F WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D83;LATIN SMALL LETTER G WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D84;LATIN SMALL LETTER K WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D85;LATIN SMALL LETTER L WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D86;LATIN SMALL LETTER M WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D87;LATIN SMALL LETTER N WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D88;LATIN SMALL LETTER P WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D89;LATIN SMALL LETTER R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D8A;LATIN SMALL LETTER S WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D8B;LATIN SMALL LETTER ESH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D8C;LATIN SMALL LETTER V WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D8D;LATIN SMALL LETTER X WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D8E;LATIN SMALL LETTER Z WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
-1D8F;LATIN SMALL LETTER A WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D90;LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D91;LATIN SMALL LETTER D WITH HOOK AND TAIL;Ll;0;L;;;;;N;;;;;
-1D92;LATIN SMALL LETTER E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D93;LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D94;LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D95;LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D96;LATIN SMALL LETTER I WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D97;LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D98;LATIN SMALL LETTER ESH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D99;LATIN SMALL LETTER U WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D9A;LATIN SMALL LETTER EZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
-1D9B;MODIFIER LETTER SMALL TURNED ALPHA;Lm;0;L;<super> 0252;;;;N;;;;;
-1D9C;MODIFIER LETTER SMALL C;Lm;0;L;<super> 0063;;;;N;;;;;
-1D9D;MODIFIER LETTER SMALL C WITH CURL;Lm;0;L;<super> 0255;;;;N;;;;;
-1D9E;MODIFIER LETTER SMALL ETH;Lm;0;L;<super> 00F0;;;;N;;;;;
-1D9F;MODIFIER LETTER SMALL REVERSED OPEN E;Lm;0;L;<super> 025C;;;;N;;;;;
-1DA0;MODIFIER LETTER SMALL F;Lm;0;L;<super> 0066;;;;N;;;;;
-1DA1;MODIFIER LETTER SMALL DOTLESS J WITH STROKE;Lm;0;L;<super> 025F;;;;N;;;;;
-1DA2;MODIFIER LETTER SMALL SCRIPT G;Lm;0;L;<super> 0261;;;;N;;;;;
-1DA3;MODIFIER LETTER SMALL TURNED H;Lm;0;L;<super> 0265;;;;N;;;;;
-1DA4;MODIFIER LETTER SMALL I WITH STROKE;Lm;0;L;<super> 0268;;;;N;;;;;
-1DA5;MODIFIER LETTER SMALL IOTA;Lm;0;L;<super> 0269;;;;N;;;;;
-1DA6;MODIFIER LETTER SMALL CAPITAL I;Lm;0;L;<super> 026A;;;;N;;;;;
-1DA7;MODIFIER LETTER SMALL CAPITAL I WITH STROKE;Lm;0;L;<super> 1D7B;;;;N;;;;;
-1DA8;MODIFIER LETTER SMALL J WITH CROSSED-TAIL;Lm;0;L;<super> 029D;;;;N;;;;;
-1DA9;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK;Lm;0;L;<super> 026D;;;;N;;;;;
-1DAA;MODIFIER LETTER SMALL L WITH PALATAL HOOK;Lm;0;L;<super> 1D85;;;;N;;;;;
-1DAB;MODIFIER LETTER SMALL CAPITAL L;Lm;0;L;<super> 029F;;;;N;;;;;
-1DAC;MODIFIER LETTER SMALL M WITH HOOK;Lm;0;L;<super> 0271;;;;N;;;;;
-1DAD;MODIFIER LETTER SMALL TURNED M WITH LONG LEG;Lm;0;L;<super> 0270;;;;N;;;;;
-1DAE;MODIFIER LETTER SMALL N WITH LEFT HOOK;Lm;0;L;<super> 0272;;;;N;;;;;
-1DAF;MODIFIER LETTER SMALL N WITH RETROFLEX HOOK;Lm;0;L;<super> 0273;;;;N;;;;;
-1DB0;MODIFIER LETTER SMALL CAPITAL N;Lm;0;L;<super> 0274;;;;N;;;;;
-1DB1;MODIFIER LETTER SMALL BARRED O;Lm;0;L;<super> 0275;;;;N;;;;;
-1DB2;MODIFIER LETTER SMALL PHI;Lm;0;L;<super> 0278;;;;N;;;;;
-1DB3;MODIFIER LETTER SMALL S WITH HOOK;Lm;0;L;<super> 0282;;;;N;;;;;
-1DB4;MODIFIER LETTER SMALL ESH;Lm;0;L;<super> 0283;;;;N;;;;;
-1DB5;MODIFIER LETTER SMALL T WITH PALATAL HOOK;Lm;0;L;<super> 01AB;;;;N;;;;;
-1DB6;MODIFIER LETTER SMALL U BAR;Lm;0;L;<super> 0289;;;;N;;;;;
-1DB7;MODIFIER LETTER SMALL UPSILON;Lm;0;L;<super> 028A;;;;N;;;;;
-1DB8;MODIFIER LETTER SMALL CAPITAL U;Lm;0;L;<super> 1D1C;;;;N;;;;;
-1DB9;MODIFIER LETTER SMALL V WITH HOOK;Lm;0;L;<super> 028B;;;;N;;;;;
-1DBA;MODIFIER LETTER SMALL TURNED V;Lm;0;L;<super> 028C;;;;N;;;;;
-1DBB;MODIFIER LETTER SMALL Z;Lm;0;L;<super> 007A;;;;N;;;;;
-1DBC;MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK;Lm;0;L;<super> 0290;;;;N;;;;;
-1DBD;MODIFIER LETTER SMALL Z WITH CURL;Lm;0;L;<super> 0291;;;;N;;;;;
-1DBE;MODIFIER LETTER SMALL EZH;Lm;0;L;<super> 0292;;;;N;;;;;
-1DBF;MODIFIER LETTER SMALL THETA;Lm;0;L;<super> 03B8;;;;N;;;;;
-1DC0;COMBINING DOTTED GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;;
-1DC1;COMBINING DOTTED ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;;
-1DC2;COMBINING SNAKE BELOW;Mn;220;NSM;;;;;N;;;;;
-1DC3;COMBINING SUSPENSION MARK;Mn;230;NSM;;;;;N;;;;;
-1DC4;COMBINING MACRON-ACUTE;Mn;230;NSM;;;;;N;;;;;
-1DC5;COMBINING GRAVE-MACRON;Mn;230;NSM;;;;;N;;;;;
-1DC6;COMBINING MACRON-GRAVE;Mn;230;NSM;;;;;N;;;;;
-1DC7;COMBINING ACUTE-MACRON;Mn;230;NSM;;;;;N;;;;;
-1DC8;COMBINING GRAVE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;;
-1DC9;COMBINING ACUTE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;;
-1DCA;COMBINING LATIN SMALL LETTER R BELOW;Mn;220;NSM;;;;;N;;;;;
-1DCB;COMBINING BREVE-MACRON;Mn;230;NSM;;;;;N;;;;;
-1DCC;COMBINING MACRON-BREVE;Mn;230;NSM;;;;;N;;;;;
-1DCD;COMBINING DOUBLE CIRCUMFLEX ABOVE;Mn;234;NSM;;;;;N;;;;;
-1DCE;COMBINING OGONEK ABOVE;Mn;214;NSM;;;;;N;;;;;
-1DCF;COMBINING ZIGZAG BELOW;Mn;220;NSM;;;;;N;;;;;
-1DD0;COMBINING IS BELOW;Mn;202;NSM;;;;;N;;;;;
-1DD1;COMBINING UR ABOVE;Mn;230;NSM;;;;;N;;;;;
-1DD2;COMBINING US ABOVE;Mn;230;NSM;;;;;N;;;;;
-1DD3;COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE;Mn;230;NSM;;;;;N;;;;;
-1DD4;COMBINING LATIN SMALL LETTER AE;Mn;230;NSM;;;;;N;;;;;
-1DD5;COMBINING LATIN SMALL LETTER AO;Mn;230;NSM;;;;;N;;;;;
-1DD6;COMBINING LATIN SMALL LETTER AV;Mn;230;NSM;;;;;N;;;;;
-1DD7;COMBINING LATIN SMALL LETTER C CEDILLA;Mn;230;NSM;;;;;N;;;;;
-1DD8;COMBINING LATIN SMALL LETTER INSULAR D;Mn;230;NSM;;;;;N;;;;;
-1DD9;COMBINING LATIN SMALL LETTER ETH;Mn;230;NSM;;;;;N;;;;;
-1DDA;COMBINING LATIN SMALL LETTER G;Mn;230;NSM;;;;;N;;;;;
-1DDB;COMBINING LATIN LETTER SMALL CAPITAL G;Mn;230;NSM;;;;;N;;;;;
-1DDC;COMBINING LATIN SMALL LETTER K;Mn;230;NSM;;;;;N;;;;;
-1DDD;COMBINING LATIN SMALL LETTER L;Mn;230;NSM;;;;;N;;;;;
-1DDE;COMBINING LATIN LETTER SMALL CAPITAL L;Mn;230;NSM;;;;;N;;;;;
-1DDF;COMBINING LATIN LETTER SMALL CAPITAL M;Mn;230;NSM;;;;;N;;;;;
-1DE0;COMBINING LATIN SMALL LETTER N;Mn;230;NSM;;;;;N;;;;;
-1DE1;COMBINING LATIN LETTER SMALL CAPITAL N;Mn;230;NSM;;;;;N;;;;;
-1DE2;COMBINING LATIN LETTER SMALL CAPITAL R;Mn;230;NSM;;;;;N;;;;;
-1DE3;COMBINING LATIN SMALL LETTER R ROTUNDA;Mn;230;NSM;;;;;N;;;;;
-1DE4;COMBINING LATIN SMALL LETTER S;Mn;230;NSM;;;;;N;;;;;
-1DE5;COMBINING LATIN SMALL LETTER LONG S;Mn;230;NSM;;;;;N;;;;;
-1DE6;COMBINING LATIN SMALL LETTER Z;Mn;230;NSM;;;;;N;;;;;
-1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;;
-1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;;
-1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;;
-1DFF;COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
-1E00;LATIN CAPITAL LETTER A WITH RING BELOW;Lu;0;L;0041 0325;;;;N;;;;1E01;
-1E01;LATIN SMALL LETTER A WITH RING BELOW;Ll;0;L;0061 0325;;;;N;;;1E00;;1E00
-1E02;LATIN CAPITAL LETTER B WITH DOT ABOVE;Lu;0;L;0042 0307;;;;N;;;;1E03;
-1E03;LATIN SMALL LETTER B WITH DOT ABOVE;Ll;0;L;0062 0307;;;;N;;;1E02;;1E02
-1E04;LATIN CAPITAL LETTER B WITH DOT BELOW;Lu;0;L;0042 0323;;;;N;;;;1E05;
-1E05;LATIN SMALL LETTER B WITH DOT BELOW;Ll;0;L;0062 0323;;;;N;;;1E04;;1E04
-1E06;LATIN CAPITAL LETTER B WITH LINE BELOW;Lu;0;L;0042 0331;;;;N;;;;1E07;
-1E07;LATIN SMALL LETTER B WITH LINE BELOW;Ll;0;L;0062 0331;;;;N;;;1E06;;1E06
-1E08;LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE;Lu;0;L;00C7 0301;;;;N;;;;1E09;
-1E09;LATIN SMALL LETTER C WITH CEDILLA AND ACUTE;Ll;0;L;00E7 0301;;;;N;;;1E08;;1E08
-1E0A;LATIN CAPITAL LETTER D WITH DOT ABOVE;Lu;0;L;0044 0307;;;;N;;;;1E0B;
-1E0B;LATIN SMALL LETTER D WITH DOT ABOVE;Ll;0;L;0064 0307;;;;N;;;1E0A;;1E0A
-1E0C;LATIN CAPITAL LETTER D WITH DOT BELOW;Lu;0;L;0044 0323;;;;N;;;;1E0D;
-1E0D;LATIN SMALL LETTER D WITH DOT BELOW;Ll;0;L;0064 0323;;;;N;;;1E0C;;1E0C
-1E0E;LATIN CAPITAL LETTER D WITH LINE BELOW;Lu;0;L;0044 0331;;;;N;;;;1E0F;
-1E0F;LATIN SMALL LETTER D WITH LINE BELOW;Ll;0;L;0064 0331;;;;N;;;1E0E;;1E0E
-1E10;LATIN CAPITAL LETTER D WITH CEDILLA;Lu;0;L;0044 0327;;;;N;;;;1E11;
-1E11;LATIN SMALL LETTER D WITH CEDILLA;Ll;0;L;0064 0327;;;;N;;;1E10;;1E10
-1E12;LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW;Lu;0;L;0044 032D;;;;N;;;;1E13;
-1E13;LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW;Ll;0;L;0064 032D;;;;N;;;1E12;;1E12
-1E14;LATIN CAPITAL LETTER E WITH MACRON AND GRAVE;Lu;0;L;0112 0300;;;;N;;;;1E15;
-1E15;LATIN SMALL LETTER E WITH MACRON AND GRAVE;Ll;0;L;0113 0300;;;;N;;;1E14;;1E14
-1E16;LATIN CAPITAL LETTER E WITH MACRON AND ACUTE;Lu;0;L;0112 0301;;;;N;;;;1E17;
-1E17;LATIN SMALL LETTER E WITH MACRON AND ACUTE;Ll;0;L;0113 0301;;;;N;;;1E16;;1E16
-1E18;LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW;Lu;0;L;0045 032D;;;;N;;;;1E19;
-1E19;LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW;Ll;0;L;0065 032D;;;;N;;;1E18;;1E18
-1E1A;LATIN CAPITAL LETTER E WITH TILDE BELOW;Lu;0;L;0045 0330;;;;N;;;;1E1B;
-1E1B;LATIN SMALL LETTER E WITH TILDE BELOW;Ll;0;L;0065 0330;;;;N;;;1E1A;;1E1A
-1E1C;LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE;Lu;0;L;0228 0306;;;;N;;;;1E1D;
-1E1D;LATIN SMALL LETTER E WITH CEDILLA AND BREVE;Ll;0;L;0229 0306;;;;N;;;1E1C;;1E1C
-1E1E;LATIN CAPITAL LETTER F WITH DOT ABOVE;Lu;0;L;0046 0307;;;;N;;;;1E1F;
-1E1F;LATIN SMALL LETTER F WITH DOT ABOVE;Ll;0;L;0066 0307;;;;N;;;1E1E;;1E1E
-1E20;LATIN CAPITAL LETTER G WITH MACRON;Lu;0;L;0047 0304;;;;N;;;;1E21;
-1E21;LATIN SMALL LETTER G WITH MACRON;Ll;0;L;0067 0304;;;;N;;;1E20;;1E20
-1E22;LATIN CAPITAL LETTER H WITH DOT ABOVE;Lu;0;L;0048 0307;;;;N;;;;1E23;
-1E23;LATIN SMALL LETTER H WITH DOT ABOVE;Ll;0;L;0068 0307;;;;N;;;1E22;;1E22
-1E24;LATIN CAPITAL LETTER H WITH DOT BELOW;Lu;0;L;0048 0323;;;;N;;;;1E25;
-1E25;LATIN SMALL LETTER H WITH DOT BELOW;Ll;0;L;0068 0323;;;;N;;;1E24;;1E24
-1E26;LATIN CAPITAL LETTER H WITH DIAERESIS;Lu;0;L;0048 0308;;;;N;;;;1E27;
-1E27;LATIN SMALL LETTER H WITH DIAERESIS;Ll;0;L;0068 0308;;;;N;;;1E26;;1E26
-1E28;LATIN CAPITAL LETTER H WITH CEDILLA;Lu;0;L;0048 0327;;;;N;;;;1E29;
-1E29;LATIN SMALL LETTER H WITH CEDILLA;Ll;0;L;0068 0327;;;;N;;;1E28;;1E28
-1E2A;LATIN CAPITAL LETTER H WITH BREVE BELOW;Lu;0;L;0048 032E;;;;N;;;;1E2B;
-1E2B;LATIN SMALL LETTER H WITH BREVE BELOW;Ll;0;L;0068 032E;;;;N;;;1E2A;;1E2A
-1E2C;LATIN CAPITAL LETTER I WITH TILDE BELOW;Lu;0;L;0049 0330;;;;N;;;;1E2D;
-1E2D;LATIN SMALL LETTER I WITH TILDE BELOW;Ll;0;L;0069 0330;;;;N;;;1E2C;;1E2C
-1E2E;LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE;Lu;0;L;00CF 0301;;;;N;;;;1E2F;
-1E2F;LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE;Ll;0;L;00EF 0301;;;;N;;;1E2E;;1E2E
-1E30;LATIN CAPITAL LETTER K WITH ACUTE;Lu;0;L;004B 0301;;;;N;;;;1E31;
-1E31;LATIN SMALL LETTER K WITH ACUTE;Ll;0;L;006B 0301;;;;N;;;1E30;;1E30
-1E32;LATIN CAPITAL LETTER K WITH DOT BELOW;Lu;0;L;004B 0323;;;;N;;;;1E33;
-1E33;LATIN SMALL LETTER K WITH DOT BELOW;Ll;0;L;006B 0323;;;;N;;;1E32;;1E32
-1E34;LATIN CAPITAL LETTER K WITH LINE BELOW;Lu;0;L;004B 0331;;;;N;;;;1E35;
-1E35;LATIN SMALL LETTER K WITH LINE BELOW;Ll;0;L;006B 0331;;;;N;;;1E34;;1E34
-1E36;LATIN CAPITAL LETTER L WITH DOT BELOW;Lu;0;L;004C 0323;;;;N;;;;1E37;
-1E37;LATIN SMALL LETTER L WITH DOT BELOW;Ll;0;L;006C 0323;;;;N;;;1E36;;1E36
-1E38;LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON;Lu;0;L;1E36 0304;;;;N;;;;1E39;
-1E39;LATIN SMALL LETTER L WITH DOT BELOW AND MACRON;Ll;0;L;1E37 0304;;;;N;;;1E38;;1E38
-1E3A;LATIN CAPITAL LETTER L WITH LINE BELOW;Lu;0;L;004C 0331;;;;N;;;;1E3B;
-1E3B;LATIN SMALL LETTER L WITH LINE BELOW;Ll;0;L;006C 0331;;;;N;;;1E3A;;1E3A
-1E3C;LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW;Lu;0;L;004C 032D;;;;N;;;;1E3D;
-1E3D;LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW;Ll;0;L;006C 032D;;;;N;;;1E3C;;1E3C
-1E3E;LATIN CAPITAL LETTER M WITH ACUTE;Lu;0;L;004D 0301;;;;N;;;;1E3F;
-1E3F;LATIN SMALL LETTER M WITH ACUTE;Ll;0;L;006D 0301;;;;N;;;1E3E;;1E3E
-1E40;LATIN CAPITAL LETTER M WITH DOT ABOVE;Lu;0;L;004D 0307;;;;N;;;;1E41;
-1E41;LATIN SMALL LETTER M WITH DOT ABOVE;Ll;0;L;006D 0307;;;;N;;;1E40;;1E40
-1E42;LATIN CAPITAL LETTER M WITH DOT BELOW;Lu;0;L;004D 0323;;;;N;;;;1E43;
-1E43;LATIN SMALL LETTER M WITH DOT BELOW;Ll;0;L;006D 0323;;;;N;;;1E42;;1E42
-1E44;LATIN CAPITAL LETTER N WITH DOT ABOVE;Lu;0;L;004E 0307;;;;N;;;;1E45;
-1E45;LATIN SMALL LETTER N WITH DOT ABOVE;Ll;0;L;006E 0307;;;;N;;;1E44;;1E44
-1E46;LATIN CAPITAL LETTER N WITH DOT BELOW;Lu;0;L;004E 0323;;;;N;;;;1E47;
-1E47;LATIN SMALL LETTER N WITH DOT BELOW;Ll;0;L;006E 0323;;;;N;;;1E46;;1E46
-1E48;LATIN CAPITAL LETTER N WITH LINE BELOW;Lu;0;L;004E 0331;;;;N;;;;1E49;
-1E49;LATIN SMALL LETTER N WITH LINE BELOW;Ll;0;L;006E 0331;;;;N;;;1E48;;1E48
-1E4A;LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW;Lu;0;L;004E 032D;;;;N;;;;1E4B;
-1E4B;LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW;Ll;0;L;006E 032D;;;;N;;;1E4A;;1E4A
-1E4C;LATIN CAPITAL LETTER O WITH TILDE AND ACUTE;Lu;0;L;00D5 0301;;;;N;;;;1E4D;
-1E4D;LATIN SMALL LETTER O WITH TILDE AND ACUTE;Ll;0;L;00F5 0301;;;;N;;;1E4C;;1E4C
-1E4E;LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS;Lu;0;L;00D5 0308;;;;N;;;;1E4F;
-1E4F;LATIN SMALL LETTER O WITH TILDE AND DIAERESIS;Ll;0;L;00F5 0308;;;;N;;;1E4E;;1E4E
-1E50;LATIN CAPITAL LETTER O WITH MACRON AND GRAVE;Lu;0;L;014C 0300;;;;N;;;;1E51;
-1E51;LATIN SMALL LETTER O WITH MACRON AND GRAVE;Ll;0;L;014D 0300;;;;N;;;1E50;;1E50
-1E52;LATIN CAPITAL LETTER O WITH MACRON AND ACUTE;Lu;0;L;014C 0301;;;;N;;;;1E53;
-1E53;LATIN SMALL LETTER O WITH MACRON AND ACUTE;Ll;0;L;014D 0301;;;;N;;;1E52;;1E52
-1E54;LATIN CAPITAL LETTER P WITH ACUTE;Lu;0;L;0050 0301;;;;N;;;;1E55;
-1E55;LATIN SMALL LETTER P WITH ACUTE;Ll;0;L;0070 0301;;;;N;;;1E54;;1E54
-1E56;LATIN CAPITAL LETTER P WITH DOT ABOVE;Lu;0;L;0050 0307;;;;N;;;;1E57;
-1E57;LATIN SMALL LETTER P WITH DOT ABOVE;Ll;0;L;0070 0307;;;;N;;;1E56;;1E56
-1E58;LATIN CAPITAL LETTER R WITH DOT ABOVE;Lu;0;L;0052 0307;;;;N;;;;1E59;
-1E59;LATIN SMALL LETTER R WITH DOT ABOVE;Ll;0;L;0072 0307;;;;N;;;1E58;;1E58
-1E5A;LATIN CAPITAL LETTER R WITH DOT BELOW;Lu;0;L;0052 0323;;;;N;;;;1E5B;
-1E5B;LATIN SMALL LETTER R WITH DOT BELOW;Ll;0;L;0072 0323;;;;N;;;1E5A;;1E5A
-1E5C;LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON;Lu;0;L;1E5A 0304;;;;N;;;;1E5D;
-1E5D;LATIN SMALL LETTER R WITH DOT BELOW AND MACRON;Ll;0;L;1E5B 0304;;;;N;;;1E5C;;1E5C
-1E5E;LATIN CAPITAL LETTER R WITH LINE BELOW;Lu;0;L;0052 0331;;;;N;;;;1E5F;
-1E5F;LATIN SMALL LETTER R WITH LINE BELOW;Ll;0;L;0072 0331;;;;N;;;1E5E;;1E5E
-1E60;LATIN CAPITAL LETTER S WITH DOT ABOVE;Lu;0;L;0053 0307;;;;N;;;;1E61;
-1E61;LATIN SMALL LETTER S WITH DOT ABOVE;Ll;0;L;0073 0307;;;;N;;;1E60;;1E60
-1E62;LATIN CAPITAL LETTER S WITH DOT BELOW;Lu;0;L;0053 0323;;;;N;;;;1E63;
-1E63;LATIN SMALL LETTER S WITH DOT BELOW;Ll;0;L;0073 0323;;;;N;;;1E62;;1E62
-1E64;LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE;Lu;0;L;015A 0307;;;;N;;;;1E65;
-1E65;LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE;Ll;0;L;015B 0307;;;;N;;;1E64;;1E64
-1E66;LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE;Lu;0;L;0160 0307;;;;N;;;;1E67;
-1E67;LATIN SMALL LETTER S WITH CARON AND DOT ABOVE;Ll;0;L;0161 0307;;;;N;;;1E66;;1E66
-1E68;LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE;Lu;0;L;1E62 0307;;;;N;;;;1E69;
-1E69;LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE;Ll;0;L;1E63 0307;;;;N;;;1E68;;1E68
-1E6A;LATIN CAPITAL LETTER T WITH DOT ABOVE;Lu;0;L;0054 0307;;;;N;;;;1E6B;
-1E6B;LATIN SMALL LETTER T WITH DOT ABOVE;Ll;0;L;0074 0307;;;;N;;;1E6A;;1E6A
-1E6C;LATIN CAPITAL LETTER T WITH DOT BELOW;Lu;0;L;0054 0323;;;;N;;;;1E6D;
-1E6D;LATIN SMALL LETTER T WITH DOT BELOW;Ll;0;L;0074 0323;;;;N;;;1E6C;;1E6C
-1E6E;LATIN CAPITAL LETTER T WITH LINE BELOW;Lu;0;L;0054 0331;;;;N;;;;1E6F;
-1E6F;LATIN SMALL LETTER T WITH LINE BELOW;Ll;0;L;0074 0331;;;;N;;;1E6E;;1E6E
-1E70;LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW;Lu;0;L;0054 032D;;;;N;;;;1E71;
-1E71;LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW;Ll;0;L;0074 032D;;;;N;;;1E70;;1E70
-1E72;LATIN CAPITAL LETTER U WITH DIAERESIS BELOW;Lu;0;L;0055 0324;;;;N;;;;1E73;
-1E73;LATIN SMALL LETTER U WITH DIAERESIS BELOW;Ll;0;L;0075 0324;;;;N;;;1E72;;1E72
-1E74;LATIN CAPITAL LETTER U WITH TILDE BELOW;Lu;0;L;0055 0330;;;;N;;;;1E75;
-1E75;LATIN SMALL LETTER U WITH TILDE BELOW;Ll;0;L;0075 0330;;;;N;;;1E74;;1E74
-1E76;LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW;Lu;0;L;0055 032D;;;;N;;;;1E77;
-1E77;LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW;Ll;0;L;0075 032D;;;;N;;;1E76;;1E76
-1E78;LATIN CAPITAL LETTER U WITH TILDE AND ACUTE;Lu;0;L;0168 0301;;;;N;;;;1E79;
-1E79;LATIN SMALL LETTER U WITH TILDE AND ACUTE;Ll;0;L;0169 0301;;;;N;;;1E78;;1E78
-1E7A;LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS;Lu;0;L;016A 0308;;;;N;;;;1E7B;
-1E7B;LATIN SMALL LETTER U WITH MACRON AND DIAERESIS;Ll;0;L;016B 0308;;;;N;;;1E7A;;1E7A
-1E7C;LATIN CAPITAL LETTER V WITH TILDE;Lu;0;L;0056 0303;;;;N;;;;1E7D;
-1E7D;LATIN SMALL LETTER V WITH TILDE;Ll;0;L;0076 0303;;;;N;;;1E7C;;1E7C
-1E7E;LATIN CAPITAL LETTER V WITH DOT BELOW;Lu;0;L;0056 0323;;;;N;;;;1E7F;
-1E7F;LATIN SMALL LETTER V WITH DOT BELOW;Ll;0;L;0076 0323;;;;N;;;1E7E;;1E7E
-1E80;LATIN CAPITAL LETTER W WITH GRAVE;Lu;0;L;0057 0300;;;;N;;;;1E81;
-1E81;LATIN SMALL LETTER W WITH GRAVE;Ll;0;L;0077 0300;;;;N;;;1E80;;1E80
-1E82;LATIN CAPITAL LETTER W WITH ACUTE;Lu;0;L;0057 0301;;;;N;;;;1E83;
-1E83;LATIN SMALL LETTER W WITH ACUTE;Ll;0;L;0077 0301;;;;N;;;1E82;;1E82
-1E84;LATIN CAPITAL LETTER W WITH DIAERESIS;Lu;0;L;0057 0308;;;;N;;;;1E85;
-1E85;LATIN SMALL LETTER W WITH DIAERESIS;Ll;0;L;0077 0308;;;;N;;;1E84;;1E84
-1E86;LATIN CAPITAL LETTER W WITH DOT ABOVE;Lu;0;L;0057 0307;;;;N;;;;1E87;
-1E87;LATIN SMALL LETTER W WITH DOT ABOVE;Ll;0;L;0077 0307;;;;N;;;1E86;;1E86
-1E88;LATIN CAPITAL LETTER W WITH DOT BELOW;Lu;0;L;0057 0323;;;;N;;;;1E89;
-1E89;LATIN SMALL LETTER W WITH DOT BELOW;Ll;0;L;0077 0323;;;;N;;;1E88;;1E88
-1E8A;LATIN CAPITAL LETTER X WITH DOT ABOVE;Lu;0;L;0058 0307;;;;N;;;;1E8B;
-1E8B;LATIN SMALL LETTER X WITH DOT ABOVE;Ll;0;L;0078 0307;;;;N;;;1E8A;;1E8A
-1E8C;LATIN CAPITAL LETTER X WITH DIAERESIS;Lu;0;L;0058 0308;;;;N;;;;1E8D;
-1E8D;LATIN SMALL LETTER X WITH DIAERESIS;Ll;0;L;0078 0308;;;;N;;;1E8C;;1E8C
-1E8E;LATIN CAPITAL LETTER Y WITH DOT ABOVE;Lu;0;L;0059 0307;;;;N;;;;1E8F;
-1E8F;LATIN SMALL LETTER Y WITH DOT ABOVE;Ll;0;L;0079 0307;;;;N;;;1E8E;;1E8E
-1E90;LATIN CAPITAL LETTER Z WITH CIRCUMFLEX;Lu;0;L;005A 0302;;;;N;;;;1E91;
-1E91;LATIN SMALL LETTER Z WITH CIRCUMFLEX;Ll;0;L;007A 0302;;;;N;;;1E90;;1E90
-1E92;LATIN CAPITAL LETTER Z WITH DOT BELOW;Lu;0;L;005A 0323;;;;N;;;;1E93;
-1E93;LATIN SMALL LETTER Z WITH DOT BELOW;Ll;0;L;007A 0323;;;;N;;;1E92;;1E92
-1E94;LATIN CAPITAL LETTER Z WITH LINE BELOW;Lu;0;L;005A 0331;;;;N;;;;1E95;
-1E95;LATIN SMALL LETTER Z WITH LINE BELOW;Ll;0;L;007A 0331;;;;N;;;1E94;;1E94
-1E96;LATIN SMALL LETTER H WITH LINE BELOW;Ll;0;L;0068 0331;;;;N;;;;;
-1E97;LATIN SMALL LETTER T WITH DIAERESIS;Ll;0;L;0074 0308;;;;N;;;;;
-1E98;LATIN SMALL LETTER W WITH RING ABOVE;Ll;0;L;0077 030A;;;;N;;;;;
-1E99;LATIN SMALL LETTER Y WITH RING ABOVE;Ll;0;L;0079 030A;;;;N;;;;;
-1E9A;LATIN SMALL LETTER A WITH RIGHT HALF RING;Ll;0;L;<compat> 0061 02BE;;;;N;;;;;
-1E9B;LATIN SMALL LETTER LONG S WITH DOT ABOVE;Ll;0;L;017F 0307;;;;N;;;1E60;;1E60
-1E9C;LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;;;
-1E9D;LATIN SMALL LETTER LONG S WITH HIGH STROKE;Ll;0;L;;;;;N;;;;;
-1E9E;LATIN CAPITAL LETTER SHARP S;Lu;0;L;;;;;N;;;;00DF;
-1E9F;LATIN SMALL LETTER DELTA;Ll;0;L;;;;;N;;;;;
-1EA0;LATIN CAPITAL LETTER A WITH DOT BELOW;Lu;0;L;0041 0323;;;;N;;;;1EA1;
-1EA1;LATIN SMALL LETTER A WITH DOT BELOW;Ll;0;L;0061 0323;;;;N;;;1EA0;;1EA0
-1EA2;LATIN CAPITAL LETTER A WITH HOOK ABOVE;Lu;0;L;0041 0309;;;;N;;;;1EA3;
-1EA3;LATIN SMALL LETTER A WITH HOOK ABOVE;Ll;0;L;0061 0309;;;;N;;;1EA2;;1EA2
-1EA4;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00C2 0301;;;;N;;;;1EA5;
-1EA5;LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00E2 0301;;;;N;;;1EA4;;1EA4
-1EA6;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00C2 0300;;;;N;;;;1EA7;
-1EA7;LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00E2 0300;;;;N;;;1EA6;;1EA6
-1EA8;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00C2 0309;;;;N;;;;1EA9;
-1EA9;LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00E2 0309;;;;N;;;1EA8;;1EA8
-1EAA;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE;Lu;0;L;00C2 0303;;;;N;;;;1EAB;
-1EAB;LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE;Ll;0;L;00E2 0303;;;;N;;;1EAA;;1EAA
-1EAC;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EA0 0302;;;;N;;;;1EAD;
-1EAD;LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EA1 0302;;;;N;;;1EAC;;1EAC
-1EAE;LATIN CAPITAL LETTER A WITH BREVE AND ACUTE;Lu;0;L;0102 0301;;;;N;;;;1EAF;
-1EAF;LATIN SMALL LETTER A WITH BREVE AND ACUTE;Ll;0;L;0103 0301;;;;N;;;1EAE;;1EAE
-1EB0;LATIN CAPITAL LETTER A WITH BREVE AND GRAVE;Lu;0;L;0102 0300;;;;N;;;;1EB1;
-1EB1;LATIN SMALL LETTER A WITH BREVE AND GRAVE;Ll;0;L;0103 0300;;;;N;;;1EB0;;1EB0
-1EB2;LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE;Lu;0;L;0102 0309;;;;N;;;;1EB3;
-1EB3;LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE;Ll;0;L;0103 0309;;;;N;;;1EB2;;1EB2
-1EB4;LATIN CAPITAL LETTER A WITH BREVE AND TILDE;Lu;0;L;0102 0303;;;;N;;;;1EB5;
-1EB5;LATIN SMALL LETTER A WITH BREVE AND TILDE;Ll;0;L;0103 0303;;;;N;;;1EB4;;1EB4
-1EB6;LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW;Lu;0;L;1EA0 0306;;;;N;;;;1EB7;
-1EB7;LATIN SMALL LETTER A WITH BREVE AND DOT BELOW;Ll;0;L;1EA1 0306;;;;N;;;1EB6;;1EB6
-1EB8;LATIN CAPITAL LETTER E WITH DOT BELOW;Lu;0;L;0045 0323;;;;N;;;;1EB9;
-1EB9;LATIN SMALL LETTER E WITH DOT BELOW;Ll;0;L;0065 0323;;;;N;;;1EB8;;1EB8
-1EBA;LATIN CAPITAL LETTER E WITH HOOK ABOVE;Lu;0;L;0045 0309;;;;N;;;;1EBB;
-1EBB;LATIN SMALL LETTER E WITH HOOK ABOVE;Ll;0;L;0065 0309;;;;N;;;1EBA;;1EBA
-1EBC;LATIN CAPITAL LETTER E WITH TILDE;Lu;0;L;0045 0303;;;;N;;;;1EBD;
-1EBD;LATIN SMALL LETTER E WITH TILDE;Ll;0;L;0065 0303;;;;N;;;1EBC;;1EBC
-1EBE;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00CA 0301;;;;N;;;;1EBF;
-1EBF;LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00EA 0301;;;;N;;;1EBE;;1EBE
-1EC0;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00CA 0300;;;;N;;;;1EC1;
-1EC1;LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00EA 0300;;;;N;;;1EC0;;1EC0
-1EC2;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00CA 0309;;;;N;;;;1EC3;
-1EC3;LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00EA 0309;;;;N;;;1EC2;;1EC2
-1EC4;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE;Lu;0;L;00CA 0303;;;;N;;;;1EC5;
-1EC5;LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE;Ll;0;L;00EA 0303;;;;N;;;1EC4;;1EC4
-1EC6;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EB8 0302;;;;N;;;;1EC7;
-1EC7;LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EB9 0302;;;;N;;;1EC6;;1EC6
-1EC8;LATIN CAPITAL LETTER I WITH HOOK ABOVE;Lu;0;L;0049 0309;;;;N;;;;1EC9;
-1EC9;LATIN SMALL LETTER I WITH HOOK ABOVE;Ll;0;L;0069 0309;;;;N;;;1EC8;;1EC8
-1ECA;LATIN CAPITAL LETTER I WITH DOT BELOW;Lu;0;L;0049 0323;;;;N;;;;1ECB;
-1ECB;LATIN SMALL LETTER I WITH DOT BELOW;Ll;0;L;0069 0323;;;;N;;;1ECA;;1ECA
-1ECC;LATIN CAPITAL LETTER O WITH DOT BELOW;Lu;0;L;004F 0323;;;;N;;;;1ECD;
-1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC
-1ECE;LATIN CAPITAL LETTER O WITH HOOK ABOVE;Lu;0;L;004F 0309;;;;N;;;;1ECF;
-1ECF;LATIN SMALL LETTER O WITH HOOK ABOVE;Ll;0;L;006F 0309;;;;N;;;1ECE;;1ECE
-1ED0;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00D4 0301;;;;N;;;;1ED1;
-1ED1;LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00F4 0301;;;;N;;;1ED0;;1ED0
-1ED2;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00D4 0300;;;;N;;;;1ED3;
-1ED3;LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00F4 0300;;;;N;;;1ED2;;1ED2
-1ED4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00D4 0309;;;;N;;;;1ED5;
-1ED5;LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00F4 0309;;;;N;;;1ED4;;1ED4
-1ED6;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE;Lu;0;L;00D4 0303;;;;N;;;;1ED7;
-1ED7;LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE;Ll;0;L;00F4 0303;;;;N;;;1ED6;;1ED6
-1ED8;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1ECC 0302;;;;N;;;;1ED9;
-1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8
-1EDA;LATIN CAPITAL LETTER O WITH HORN AND ACUTE;Lu;0;L;01A0 0301;;;;N;;;;1EDB;
-1EDB;LATIN SMALL LETTER O WITH HORN AND ACUTE;Ll;0;L;01A1 0301;;;;N;;;1EDA;;1EDA
-1EDC;LATIN CAPITAL LETTER O WITH HORN AND GRAVE;Lu;0;L;01A0 0300;;;;N;;;;1EDD;
-1EDD;LATIN SMALL LETTER O WITH HORN AND GRAVE;Ll;0;L;01A1 0300;;;;N;;;1EDC;;1EDC
-1EDE;LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE;Lu;0;L;01A0 0309;;;;N;;;;1EDF;
-1EDF;LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE;Ll;0;L;01A1 0309;;;;N;;;1EDE;;1EDE
-1EE0;LATIN CAPITAL LETTER O WITH HORN AND TILDE;Lu;0;L;01A0 0303;;;;N;;;;1EE1;
-1EE1;LATIN SMALL LETTER O WITH HORN AND TILDE;Ll;0;L;01A1 0303;;;;N;;;1EE0;;1EE0
-1EE2;LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW;Lu;0;L;01A0 0323;;;;N;;;;1EE3;
-1EE3;LATIN SMALL LETTER O WITH HORN AND DOT BELOW;Ll;0;L;01A1 0323;;;;N;;;1EE2;;1EE2
-1EE4;LATIN CAPITAL LETTER U WITH DOT BELOW;Lu;0;L;0055 0323;;;;N;;;;1EE5;
-1EE5;LATIN SMALL LETTER U WITH DOT BELOW;Ll;0;L;0075 0323;;;;N;;;1EE4;;1EE4
-1EE6;LATIN CAPITAL LETTER U WITH HOOK ABOVE;Lu;0;L;0055 0309;;;;N;;;;1EE7;
-1EE7;LATIN SMALL LETTER U WITH HOOK ABOVE;Ll;0;L;0075 0309;;;;N;;;1EE6;;1EE6
-1EE8;LATIN CAPITAL LETTER U WITH HORN AND ACUTE;Lu;0;L;01AF 0301;;;;N;;;;1EE9;
-1EE9;LATIN SMALL LETTER U WITH HORN AND ACUTE;Ll;0;L;01B0 0301;;;;N;;;1EE8;;1EE8
-1EEA;LATIN CAPITAL LETTER U WITH HORN AND GRAVE;Lu;0;L;01AF 0300;;;;N;;;;1EEB;
-1EEB;LATIN SMALL LETTER U WITH HORN AND GRAVE;Ll;0;L;01B0 0300;;;;N;;;1EEA;;1EEA
-1EEC;LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE;Lu;0;L;01AF 0309;;;;N;;;;1EED;
-1EED;LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE;Ll;0;L;01B0 0309;;;;N;;;1EEC;;1EEC
-1EEE;LATIN CAPITAL LETTER U WITH HORN AND TILDE;Lu;0;L;01AF 0303;;;;N;;;;1EEF;
-1EEF;LATIN SMALL LETTER U WITH HORN AND TILDE;Ll;0;L;01B0 0303;;;;N;;;1EEE;;1EEE
-1EF0;LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW;Lu;0;L;01AF 0323;;;;N;;;;1EF1;
-1EF1;LATIN SMALL LETTER U WITH HORN AND DOT BELOW;Ll;0;L;01B0 0323;;;;N;;;1EF0;;1EF0
-1EF2;LATIN CAPITAL LETTER Y WITH GRAVE;Lu;0;L;0059 0300;;;;N;;;;1EF3;
-1EF3;LATIN SMALL LETTER Y WITH GRAVE;Ll;0;L;0079 0300;;;;N;;;1EF2;;1EF2
-1EF4;LATIN CAPITAL LETTER Y WITH DOT BELOW;Lu;0;L;0059 0323;;;;N;;;;1EF5;
-1EF5;LATIN SMALL LETTER Y WITH DOT BELOW;Ll;0;L;0079 0323;;;;N;;;1EF4;;1EF4
-1EF6;LATIN CAPITAL LETTER Y WITH HOOK ABOVE;Lu;0;L;0059 0309;;;;N;;;;1EF7;
-1EF7;LATIN SMALL LETTER Y WITH HOOK ABOVE;Ll;0;L;0079 0309;;;;N;;;1EF6;;1EF6
-1EF8;LATIN CAPITAL LETTER Y WITH TILDE;Lu;0;L;0059 0303;;;;N;;;;1EF9;
-1EF9;LATIN SMALL LETTER Y WITH TILDE;Ll;0;L;0079 0303;;;;N;;;1EF8;;1EF8
-1EFA;LATIN CAPITAL LETTER MIDDLE-WELSH LL;Lu;0;L;;;;;N;;;;1EFB;
-1EFB;LATIN SMALL LETTER MIDDLE-WELSH LL;Ll;0;L;;;;;N;;;1EFA;;1EFA
-1EFC;LATIN CAPITAL LETTER MIDDLE-WELSH V;Lu;0;L;;;;;N;;;;1EFD;
-1EFD;LATIN SMALL LETTER MIDDLE-WELSH V;Ll;0;L;;;;;N;;;1EFC;;1EFC
-1EFE;LATIN CAPITAL LETTER Y WITH LOOP;Lu;0;L;;;;;N;;;;1EFF;
-1EFF;LATIN SMALL LETTER Y WITH LOOP;Ll;0;L;;;;;N;;;1EFE;;1EFE
-1F00;GREEK SMALL LETTER ALPHA WITH PSILI;Ll;0;L;03B1 0313;;;;N;;;1F08;;1F08
-1F01;GREEK SMALL LETTER ALPHA WITH DASIA;Ll;0;L;03B1 0314;;;;N;;;1F09;;1F09
-1F02;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA;Ll;0;L;1F00 0300;;;;N;;;1F0A;;1F0A
-1F03;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA;Ll;0;L;1F01 0300;;;;N;;;1F0B;;1F0B
-1F04;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA;Ll;0;L;1F00 0301;;;;N;;;1F0C;;1F0C
-1F05;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA;Ll;0;L;1F01 0301;;;;N;;;1F0D;;1F0D
-1F06;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI;Ll;0;L;1F00 0342;;;;N;;;1F0E;;1F0E
-1F07;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI;Ll;0;L;1F01 0342;;;;N;;;1F0F;;1F0F
-1F08;GREEK CAPITAL LETTER ALPHA WITH PSILI;Lu;0;L;0391 0313;;;;N;;;;1F00;
-1F09;GREEK CAPITAL LETTER ALPHA WITH DASIA;Lu;0;L;0391 0314;;;;N;;;;1F01;
-1F0A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA;Lu;0;L;1F08 0300;;;;N;;;;1F02;
-1F0B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA;Lu;0;L;1F09 0300;;;;N;;;;1F03;
-1F0C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA;Lu;0;L;1F08 0301;;;;N;;;;1F04;
-1F0D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA;Lu;0;L;1F09 0301;;;;N;;;;1F05;
-1F0E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI;Lu;0;L;1F08 0342;;;;N;;;;1F06;
-1F0F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI;Lu;0;L;1F09 0342;;;;N;;;;1F07;
-1F10;GREEK SMALL LETTER EPSILON WITH PSILI;Ll;0;L;03B5 0313;;;;N;;;1F18;;1F18
-1F11;GREEK SMALL LETTER EPSILON WITH DASIA;Ll;0;L;03B5 0314;;;;N;;;1F19;;1F19
-1F12;GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA;Ll;0;L;1F10 0300;;;;N;;;1F1A;;1F1A
-1F13;GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA;Ll;0;L;1F11 0300;;;;N;;;1F1B;;1F1B
-1F14;GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA;Ll;0;L;1F10 0301;;;;N;;;1F1C;;1F1C
-1F15;GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA;Ll;0;L;1F11 0301;;;;N;;;1F1D;;1F1D
-1F18;GREEK CAPITAL LETTER EPSILON WITH PSILI;Lu;0;L;0395 0313;;;;N;;;;1F10;
-1F19;GREEK CAPITAL LETTER EPSILON WITH DASIA;Lu;0;L;0395 0314;;;;N;;;;1F11;
-1F1A;GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA;Lu;0;L;1F18 0300;;;;N;;;;1F12;
-1F1B;GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA;Lu;0;L;1F19 0300;;;;N;;;;1F13;
-1F1C;GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA;Lu;0;L;1F18 0301;;;;N;;;;1F14;
-1F1D;GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA;Lu;0;L;1F19 0301;;;;N;;;;1F15;
-1F20;GREEK SMALL LETTER ETA WITH PSILI;Ll;0;L;03B7 0313;;;;N;;;1F28;;1F28
-1F21;GREEK SMALL LETTER ETA WITH DASIA;Ll;0;L;03B7 0314;;;;N;;;1F29;;1F29
-1F22;GREEK SMALL LETTER ETA WITH PSILI AND VARIA;Ll;0;L;1F20 0300;;;;N;;;1F2A;;1F2A
-1F23;GREEK SMALL LETTER ETA WITH DASIA AND VARIA;Ll;0;L;1F21 0300;;;;N;;;1F2B;;1F2B
-1F24;GREEK SMALL LETTER ETA WITH PSILI AND OXIA;Ll;0;L;1F20 0301;;;;N;;;1F2C;;1F2C
-1F25;GREEK SMALL LETTER ETA WITH DASIA AND OXIA;Ll;0;L;1F21 0301;;;;N;;;1F2D;;1F2D
-1F26;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI;Ll;0;L;1F20 0342;;;;N;;;1F2E;;1F2E
-1F27;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI;Ll;0;L;1F21 0342;;;;N;;;1F2F;;1F2F
-1F28;GREEK CAPITAL LETTER ETA WITH PSILI;Lu;0;L;0397 0313;;;;N;;;;1F20;
-1F29;GREEK CAPITAL LETTER ETA WITH DASIA;Lu;0;L;0397 0314;;;;N;;;;1F21;
-1F2A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA;Lu;0;L;1F28 0300;;;;N;;;;1F22;
-1F2B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA;Lu;0;L;1F29 0300;;;;N;;;;1F23;
-1F2C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA;Lu;0;L;1F28 0301;;;;N;;;;1F24;
-1F2D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA;Lu;0;L;1F29 0301;;;;N;;;;1F25;
-1F2E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI;Lu;0;L;1F28 0342;;;;N;;;;1F26;
-1F2F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI;Lu;0;L;1F29 0342;;;;N;;;;1F27;
-1F30;GREEK SMALL LETTER IOTA WITH PSILI;Ll;0;L;03B9 0313;;;;N;;;1F38;;1F38
-1F31;GREEK SMALL LETTER IOTA WITH DASIA;Ll;0;L;03B9 0314;;;;N;;;1F39;;1F39
-1F32;GREEK SMALL LETTER IOTA WITH PSILI AND VARIA;Ll;0;L;1F30 0300;;;;N;;;1F3A;;1F3A
-1F33;GREEK SMALL LETTER IOTA WITH DASIA AND VARIA;Ll;0;L;1F31 0300;;;;N;;;1F3B;;1F3B
-1F34;GREEK SMALL LETTER IOTA WITH PSILI AND OXIA;Ll;0;L;1F30 0301;;;;N;;;1F3C;;1F3C
-1F35;GREEK SMALL LETTER IOTA WITH DASIA AND OXIA;Ll;0;L;1F31 0301;;;;N;;;1F3D;;1F3D
-1F36;GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI;Ll;0;L;1F30 0342;;;;N;;;1F3E;;1F3E
-1F37;GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI;Ll;0;L;1F31 0342;;;;N;;;1F3F;;1F3F
-1F38;GREEK CAPITAL LETTER IOTA WITH PSILI;Lu;0;L;0399 0313;;;;N;;;;1F30;
-1F39;GREEK CAPITAL LETTER IOTA WITH DASIA;Lu;0;L;0399 0314;;;;N;;;;1F31;
-1F3A;GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA;Lu;0;L;1F38 0300;;;;N;;;;1F32;
-1F3B;GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA;Lu;0;L;1F39 0300;;;;N;;;;1F33;
-1F3C;GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA;Lu;0;L;1F38 0301;;;;N;;;;1F34;
-1F3D;GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA;Lu;0;L;1F39 0301;;;;N;;;;1F35;
-1F3E;GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI;Lu;0;L;1F38 0342;;;;N;;;;1F36;
-1F3F;GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI;Lu;0;L;1F39 0342;;;;N;;;;1F37;
-1F40;GREEK SMALL LETTER OMICRON WITH PSILI;Ll;0;L;03BF 0313;;;;N;;;1F48;;1F48
-1F41;GREEK SMALL LETTER OMICRON WITH DASIA;Ll;0;L;03BF 0314;;;;N;;;1F49;;1F49
-1F42;GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA;Ll;0;L;1F40 0300;;;;N;;;1F4A;;1F4A
-1F43;GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA;Ll;0;L;1F41 0300;;;;N;;;1F4B;;1F4B
-1F44;GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA;Ll;0;L;1F40 0301;;;;N;;;1F4C;;1F4C
-1F45;GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA;Ll;0;L;1F41 0301;;;;N;;;1F4D;;1F4D
-1F48;GREEK CAPITAL LETTER OMICRON WITH PSILI;Lu;0;L;039F 0313;;;;N;;;;1F40;
-1F49;GREEK CAPITAL LETTER OMICRON WITH DASIA;Lu;0;L;039F 0314;;;;N;;;;1F41;
-1F4A;GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA;Lu;0;L;1F48 0300;;;;N;;;;1F42;
-1F4B;GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA;Lu;0;L;1F49 0300;;;;N;;;;1F43;
-1F4C;GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA;Lu;0;L;1F48 0301;;;;N;;;;1F44;
-1F4D;GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA;Lu;0;L;1F49 0301;;;;N;;;;1F45;
-1F50;GREEK SMALL LETTER UPSILON WITH PSILI;Ll;0;L;03C5 0313;;;;N;;;;;
-1F51;GREEK SMALL LETTER UPSILON WITH DASIA;Ll;0;L;03C5 0314;;;;N;;;1F59;;1F59
-1F52;GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA;Ll;0;L;1F50 0300;;;;N;;;;;
-1F53;GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA;Ll;0;L;1F51 0300;;;;N;;;1F5B;;1F5B
-1F54;GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA;Ll;0;L;1F50 0301;;;;N;;;;;
-1F55;GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA;Ll;0;L;1F51 0301;;;;N;;;1F5D;;1F5D
-1F56;GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI;Ll;0;L;1F50 0342;;;;N;;;;;
-1F57;GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI;Ll;0;L;1F51 0342;;;;N;;;1F5F;;1F5F
-1F59;GREEK CAPITAL LETTER UPSILON WITH DASIA;Lu;0;L;03A5 0314;;;;N;;;;1F51;
-1F5B;GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA;Lu;0;L;1F59 0300;;;;N;;;;1F53;
-1F5D;GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA;Lu;0;L;1F59 0301;;;;N;;;;1F55;
-1F5F;GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI;Lu;0;L;1F59 0342;;;;N;;;;1F57;
-1F60;GREEK SMALL LETTER OMEGA WITH PSILI;Ll;0;L;03C9 0313;;;;N;;;1F68;;1F68
-1F61;GREEK SMALL LETTER OMEGA WITH DASIA;Ll;0;L;03C9 0314;;;;N;;;1F69;;1F69
-1F62;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA;Ll;0;L;1F60 0300;;;;N;;;1F6A;;1F6A
-1F63;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA;Ll;0;L;1F61 0300;;;;N;;;1F6B;;1F6B
-1F64;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA;Ll;0;L;1F60 0301;;;;N;;;1F6C;;1F6C
-1F65;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA;Ll;0;L;1F61 0301;;;;N;;;1F6D;;1F6D
-1F66;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI;Ll;0;L;1F60 0342;;;;N;;;1F6E;;1F6E
-1F67;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI;Ll;0;L;1F61 0342;;;;N;;;1F6F;;1F6F
-1F68;GREEK CAPITAL LETTER OMEGA WITH PSILI;Lu;0;L;03A9 0313;;;;N;;;;1F60;
-1F69;GREEK CAPITAL LETTER OMEGA WITH DASIA;Lu;0;L;03A9 0314;;;;N;;;;1F61;
-1F6A;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA;Lu;0;L;1F68 0300;;;;N;;;;1F62;
-1F6B;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA;Lu;0;L;1F69 0300;;;;N;;;;1F63;
-1F6C;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA;Lu;0;L;1F68 0301;;;;N;;;;1F64;
-1F6D;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA;Lu;0;L;1F69 0301;;;;N;;;;1F65;
-1F6E;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI;Lu;0;L;1F68 0342;;;;N;;;;1F66;
-1F6F;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI;Lu;0;L;1F69 0342;;;;N;;;;1F67;
-1F70;GREEK SMALL LETTER ALPHA WITH VARIA;Ll;0;L;03B1 0300;;;;N;;;1FBA;;1FBA
-1F71;GREEK SMALL LETTER ALPHA WITH OXIA;Ll;0;L;03AC;;;;N;;;1FBB;;1FBB
-1F72;GREEK SMALL LETTER EPSILON WITH VARIA;Ll;0;L;03B5 0300;;;;N;;;1FC8;;1FC8
-1F73;GREEK SMALL LETTER EPSILON WITH OXIA;Ll;0;L;03AD;;;;N;;;1FC9;;1FC9
-1F74;GREEK SMALL LETTER ETA WITH VARIA;Ll;0;L;03B7 0300;;;;N;;;1FCA;;1FCA
-1F75;GREEK SMALL LETTER ETA WITH OXIA;Ll;0;L;03AE;;;;N;;;1FCB;;1FCB
-1F76;GREEK SMALL LETTER IOTA WITH VARIA;Ll;0;L;03B9 0300;;;;N;;;1FDA;;1FDA
-1F77;GREEK SMALL LETTER IOTA WITH OXIA;Ll;0;L;03AF;;;;N;;;1FDB;;1FDB
-1F78;GREEK SMALL LETTER OMICRON WITH VARIA;Ll;0;L;03BF 0300;;;;N;;;1FF8;;1FF8
-1F79;GREEK SMALL LETTER OMICRON WITH OXIA;Ll;0;L;03CC;;;;N;;;1FF9;;1FF9
-1F7A;GREEK SMALL LETTER UPSILON WITH VARIA;Ll;0;L;03C5 0300;;;;N;;;1FEA;;1FEA
-1F7B;GREEK SMALL LETTER UPSILON WITH OXIA;Ll;0;L;03CD;;;;N;;;1FEB;;1FEB
-1F7C;GREEK SMALL LETTER OMEGA WITH VARIA;Ll;0;L;03C9 0300;;;;N;;;1FFA;;1FFA
-1F7D;GREEK SMALL LETTER OMEGA WITH OXIA;Ll;0;L;03CE;;;;N;;;1FFB;;1FFB
-1F80;GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F00 0345;;;;N;;;1F88;;1F88
-1F81;GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F01 0345;;;;N;;;1F89;;1F89
-1F82;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F02 0345;;;;N;;;1F8A;;1F8A
-1F83;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F03 0345;;;;N;;;1F8B;;1F8B
-1F84;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F04 0345;;;;N;;;1F8C;;1F8C
-1F85;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F05 0345;;;;N;;;1F8D;;1F8D
-1F86;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F06 0345;;;;N;;;1F8E;;1F8E
-1F87;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F07 0345;;;;N;;;1F8F;;1F8F
-1F88;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F08 0345;;;;N;;;;1F80;
-1F89;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F09 0345;;;;N;;;;1F81;
-1F8A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0A 0345;;;;N;;;;1F82;
-1F8B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0B 0345;;;;N;;;;1F83;
-1F8C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0C 0345;;;;N;;;;1F84;
-1F8D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0D 0345;;;;N;;;;1F85;
-1F8E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0E 0345;;;;N;;;;1F86;
-1F8F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0F 0345;;;;N;;;;1F87;
-1F90;GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F20 0345;;;;N;;;1F98;;1F98
-1F91;GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F21 0345;;;;N;;;1F99;;1F99
-1F92;GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F22 0345;;;;N;;;1F9A;;1F9A
-1F93;GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F23 0345;;;;N;;;1F9B;;1F9B
-1F94;GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F24 0345;;;;N;;;1F9C;;1F9C
-1F95;GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F25 0345;;;;N;;;1F9D;;1F9D
-1F96;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F26 0345;;;;N;;;1F9E;;1F9E
-1F97;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F27 0345;;;;N;;;1F9F;;1F9F
-1F98;GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F28 0345;;;;N;;;;1F90;
-1F99;GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F29 0345;;;;N;;;;1F91;
-1F9A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2A 0345;;;;N;;;;1F92;
-1F9B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2B 0345;;;;N;;;;1F93;
-1F9C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2C 0345;;;;N;;;;1F94;
-1F9D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2D 0345;;;;N;;;;1F95;
-1F9E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2E 0345;;;;N;;;;1F96;
-1F9F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2F 0345;;;;N;;;;1F97;
-1FA0;GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F60 0345;;;;N;;;1FA8;;1FA8
-1FA1;GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F61 0345;;;;N;;;1FA9;;1FA9
-1FA2;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F62 0345;;;;N;;;1FAA;;1FAA
-1FA3;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F63 0345;;;;N;;;1FAB;;1FAB
-1FA4;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F64 0345;;;;N;;;1FAC;;1FAC
-1FA5;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F65 0345;;;;N;;;1FAD;;1FAD
-1FA6;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F66 0345;;;;N;;;1FAE;;1FAE
-1FA7;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F67 0345;;;;N;;;1FAF;;1FAF
-1FA8;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F68 0345;;;;N;;;;1FA0;
-1FA9;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F69 0345;;;;N;;;;1FA1;
-1FAA;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6A 0345;;;;N;;;;1FA2;
-1FAB;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6B 0345;;;;N;;;;1FA3;
-1FAC;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6C 0345;;;;N;;;;1FA4;
-1FAD;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6D 0345;;;;N;;;;1FA5;
-1FAE;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6E 0345;;;;N;;;;1FA6;
-1FAF;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6F 0345;;;;N;;;;1FA7;
-1FB0;GREEK SMALL LETTER ALPHA WITH VRACHY;Ll;0;L;03B1 0306;;;;N;;;1FB8;;1FB8
-1FB1;GREEK SMALL LETTER ALPHA WITH MACRON;Ll;0;L;03B1 0304;;;;N;;;1FB9;;1FB9
-1FB2;GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F70 0345;;;;N;;;;;
-1FB3;GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI;Ll;0;L;03B1 0345;;;;N;;;1FBC;;1FBC
-1FB4;GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AC 0345;;;;N;;;;;
-1FB6;GREEK SMALL LETTER ALPHA WITH PERISPOMENI;Ll;0;L;03B1 0342;;;;N;;;;;
-1FB7;GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FB6 0345;;;;N;;;;;
-1FB8;GREEK CAPITAL LETTER ALPHA WITH VRACHY;Lu;0;L;0391 0306;;;;N;;;;1FB0;
-1FB9;GREEK CAPITAL LETTER ALPHA WITH MACRON;Lu;0;L;0391 0304;;;;N;;;;1FB1;
-1FBA;GREEK CAPITAL LETTER ALPHA WITH VARIA;Lu;0;L;0391 0300;;;;N;;;;1F70;
-1FBB;GREEK CAPITAL LETTER ALPHA WITH OXIA;Lu;0;L;0386;;;;N;;;;1F71;
-1FBC;GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI;Lt;0;L;0391 0345;;;;N;;;;1FB3;
-1FBD;GREEK KORONIS;Sk;0;ON;<compat> 0020 0313;;;;N;;;;;
-1FBE;GREEK PROSGEGRAMMENI;Ll;0;L;03B9;;;;N;;;0399;;0399
-1FBF;GREEK PSILI;Sk;0;ON;<compat> 0020 0313;;;;N;;;;;
-1FC0;GREEK PERISPOMENI;Sk;0;ON;<compat> 0020 0342;;;;N;;;;;
-1FC1;GREEK DIALYTIKA AND PERISPOMENI;Sk;0;ON;00A8 0342;;;;N;;;;;
-1FC2;GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F74 0345;;;;N;;;;;
-1FC3;GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI;Ll;0;L;03B7 0345;;;;N;;;1FCC;;1FCC
-1FC4;GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AE 0345;;;;N;;;;;
-1FC6;GREEK SMALL LETTER ETA WITH PERISPOMENI;Ll;0;L;03B7 0342;;;;N;;;;;
-1FC7;GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FC6 0345;;;;N;;;;;
-1FC8;GREEK CAPITAL LETTER EPSILON WITH VARIA;Lu;0;L;0395 0300;;;;N;;;;1F72;
-1FC9;GREEK CAPITAL LETTER EPSILON WITH OXIA;Lu;0;L;0388;;;;N;;;;1F73;
-1FCA;GREEK CAPITAL LETTER ETA WITH VARIA;Lu;0;L;0397 0300;;;;N;;;;1F74;
-1FCB;GREEK CAPITAL LETTER ETA WITH OXIA;Lu;0;L;0389;;;;N;;;;1F75;
-1FCC;GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI;Lt;0;L;0397 0345;;;;N;;;;1FC3;
-1FCD;GREEK PSILI AND VARIA;Sk;0;ON;1FBF 0300;;;;N;;;;;
-1FCE;GREEK PSILI AND OXIA;Sk;0;ON;1FBF 0301;;;;N;;;;;
-1FCF;GREEK PSILI AND PERISPOMENI;Sk;0;ON;1FBF 0342;;;;N;;;;;
-1FD0;GREEK SMALL LETTER IOTA WITH VRACHY;Ll;0;L;03B9 0306;;;;N;;;1FD8;;1FD8
-1FD1;GREEK SMALL LETTER IOTA WITH MACRON;Ll;0;L;03B9 0304;;;;N;;;1FD9;;1FD9
-1FD2;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA;Ll;0;L;03CA 0300;;;;N;;;;;
-1FD3;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA;Ll;0;L;0390;;;;N;;;;;
-1FD6;GREEK SMALL LETTER IOTA WITH PERISPOMENI;Ll;0;L;03B9 0342;;;;N;;;;;
-1FD7;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CA 0342;;;;N;;;;;
-1FD8;GREEK CAPITAL LETTER IOTA WITH VRACHY;Lu;0;L;0399 0306;;;;N;;;;1FD0;
-1FD9;GREEK CAPITAL LETTER IOTA WITH MACRON;Lu;0;L;0399 0304;;;;N;;;;1FD1;
-1FDA;GREEK CAPITAL LETTER IOTA WITH VARIA;Lu;0;L;0399 0300;;;;N;;;;1F76;
-1FDB;GREEK CAPITAL LETTER IOTA WITH OXIA;Lu;0;L;038A;;;;N;;;;1F77;
-1FDD;GREEK DASIA AND VARIA;Sk;0;ON;1FFE 0300;;;;N;;;;;
-1FDE;GREEK DASIA AND OXIA;Sk;0;ON;1FFE 0301;;;;N;;;;;
-1FDF;GREEK DASIA AND PERISPOMENI;Sk;0;ON;1FFE 0342;;;;N;;;;;
-1FE0;GREEK SMALL LETTER UPSILON WITH VRACHY;Ll;0;L;03C5 0306;;;;N;;;1FE8;;1FE8
-1FE1;GREEK SMALL LETTER UPSILON WITH MACRON;Ll;0;L;03C5 0304;;;;N;;;1FE9;;1FE9
-1FE2;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA;Ll;0;L;03CB 0300;;;;N;;;;;
-1FE3;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA;Ll;0;L;03B0;;;;N;;;;;
-1FE4;GREEK SMALL LETTER RHO WITH PSILI;Ll;0;L;03C1 0313;;;;N;;;;;
-1FE5;GREEK SMALL LETTER RHO WITH DASIA;Ll;0;L;03C1 0314;;;;N;;;1FEC;;1FEC
-1FE6;GREEK SMALL LETTER UPSILON WITH PERISPOMENI;Ll;0;L;03C5 0342;;;;N;;;;;
-1FE7;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CB 0342;;;;N;;;;;
-1FE8;GREEK CAPITAL LETTER UPSILON WITH VRACHY;Lu;0;L;03A5 0306;;;;N;;;;1FE0;
-1FE9;GREEK CAPITAL LETTER UPSILON WITH MACRON;Lu;0;L;03A5 0304;;;;N;;;;1FE1;
-1FEA;GREEK CAPITAL LETTER UPSILON WITH VARIA;Lu;0;L;03A5 0300;;;;N;;;;1F7A;
-1FEB;GREEK CAPITAL LETTER UPSILON WITH OXIA;Lu;0;L;038E;;;;N;;;;1F7B;
-1FEC;GREEK CAPITAL LETTER RHO WITH DASIA;Lu;0;L;03A1 0314;;;;N;;;;1FE5;
-1FED;GREEK DIALYTIKA AND VARIA;Sk;0;ON;00A8 0300;;;;N;;;;;
-1FEE;GREEK DIALYTIKA AND OXIA;Sk;0;ON;0385;;;;N;;;;;
-1FEF;GREEK VARIA;Sk;0;ON;0060;;;;N;;;;;
-1FF2;GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F7C 0345;;;;N;;;;;
-1FF3;GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI;Ll;0;L;03C9 0345;;;;N;;;1FFC;;1FFC
-1FF4;GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03CE 0345;;;;N;;;;;
-1FF6;GREEK SMALL LETTER OMEGA WITH PERISPOMENI;Ll;0;L;03C9 0342;;;;N;;;;;
-1FF7;GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FF6 0345;;;;N;;;;;
-1FF8;GREEK CAPITAL LETTER OMICRON WITH VARIA;Lu;0;L;039F 0300;;;;N;;;;1F78;
-1FF9;GREEK CAPITAL LETTER OMICRON WITH OXIA;Lu;0;L;038C;;;;N;;;;1F79;
-1FFA;GREEK CAPITAL LETTER OMEGA WITH VARIA;Lu;0;L;03A9 0300;;;;N;;;;1F7C;
-1FFB;GREEK CAPITAL LETTER OMEGA WITH OXIA;Lu;0;L;038F;;;;N;;;;1F7D;
-1FFC;GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI;Lt;0;L;03A9 0345;;;;N;;;;1FF3;
-1FFD;GREEK OXIA;Sk;0;ON;00B4;;;;N;;;;;
-1FFE;GREEK DASIA;Sk;0;ON;<compat> 0020 0314;;;;N;;;;;
-2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
-2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
-2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
-2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-200B;ZERO WIDTH SPACE;Cf;0;BN;;;;;N;;;;;
-200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;;
-200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;;
-200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;;
-200F;RIGHT-TO-LEFT MARK;Cf;0;R;;;;;N;;;;;
-2010;HYPHEN;Pd;0;ON;;;;;N;;;;;
-2011;NON-BREAKING HYPHEN;Pd;0;ON;<noBreak> 2010;;;;N;;;;;
-2012;FIGURE DASH;Pd;0;ON;;;;;N;;;;;
-2013;EN DASH;Pd;0;ON;;;;;N;;;;;
-2014;EM DASH;Pd;0;ON;;;;;N;;;;;
-2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;;
-2016;DOUBLE VERTICAL LINE;Po;0;ON;;;;;N;DOUBLE VERTICAL BAR;;;;
-2017;DOUBLE LOW LINE;Po;0;ON;<compat> 0020 0333;;;;N;SPACING DOUBLE UNDERSCORE;;;;
-2018;LEFT SINGLE QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE TURNED COMMA QUOTATION MARK;;;;
-2019;RIGHT SINGLE QUOTATION MARK;Pf;0;ON;;;;;N;SINGLE COMMA QUOTATION MARK;;;;
-201A;SINGLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW SINGLE COMMA QUOTATION MARK;;;;
-201B;SINGLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE REVERSED COMMA QUOTATION MARK;;;;
-201C;LEFT DOUBLE QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE TURNED COMMA QUOTATION MARK;;;;
-201D;RIGHT DOUBLE QUOTATION MARK;Pf;0;ON;;;;;N;DOUBLE COMMA QUOTATION MARK;;;;
-201E;DOUBLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW DOUBLE COMMA QUOTATION MARK;;;;
-201F;DOUBLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE REVERSED COMMA QUOTATION MARK;;;;
-2020;DAGGER;Po;0;ON;;;;;N;;;;;
-2021;DOUBLE DAGGER;Po;0;ON;;;;;N;;;;;
-2022;BULLET;Po;0;ON;;;;;N;;;;;
-2023;TRIANGULAR BULLET;Po;0;ON;;;;;N;;;;;
-2024;ONE DOT LEADER;Po;0;ON;<compat> 002E;;;;N;;;;;
-2025;TWO DOT LEADER;Po;0;ON;<compat> 002E 002E;;;;N;;;;;
-2026;HORIZONTAL ELLIPSIS;Po;0;ON;<compat> 002E 002E 002E;;;;N;;;;;
-2027;HYPHENATION POINT;Po;0;ON;;;;;N;;;;;
-2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;;
-2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;;
-202A;LEFT-TO-RIGHT EMBEDDING;Cf;0;LRE;;;;;N;;;;;
-202B;RIGHT-TO-LEFT EMBEDDING;Cf;0;RLE;;;;;N;;;;;
-202C;POP DIRECTIONAL FORMATTING;Cf;0;PDF;;;;;N;;;;;
-202D;LEFT-TO-RIGHT OVERRIDE;Cf;0;LRO;;;;;N;;;;;
-202E;RIGHT-TO-LEFT OVERRIDE;Cf;0;RLO;;;;;N;;;;;
-202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
-2030;PER MILLE SIGN;Po;0;ET;;;;;N;;;;;
-2031;PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;;
-2032;PRIME;Po;0;ET;;;;;N;;;;;
-2033;DOUBLE PRIME;Po;0;ET;<compat> 2032 2032;;;;N;;;;;
-2034;TRIPLE PRIME;Po;0;ET;<compat> 2032 2032 2032;;;;N;;;;;
-2035;REVERSED PRIME;Po;0;ON;;;;;N;;;;;
-2036;REVERSED DOUBLE PRIME;Po;0;ON;<compat> 2035 2035;;;;N;;;;;
-2037;REVERSED TRIPLE PRIME;Po;0;ON;<compat> 2035 2035 2035;;;;N;;;;;
-2038;CARET;Po;0;ON;;;;;N;;;;;
-2039;SINGLE LEFT-POINTING ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING SINGLE GUILLEMET;;;;
-203A;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING SINGLE GUILLEMET;;;;
-203B;REFERENCE MARK;Po;0;ON;;;;;N;;;;;
-203C;DOUBLE EXCLAMATION MARK;Po;0;ON;<compat> 0021 0021;;;;N;;;;;
-203D;INTERROBANG;Po;0;ON;;;;;N;;;;;
-203E;OVERLINE;Po;0;ON;<compat> 0020 0305;;;;N;SPACING OVERSCORE;;;;
-203F;UNDERTIE;Pc;0;ON;;;;;N;;;;;
-2040;CHARACTER TIE;Pc;0;ON;;;;;N;;;;;
-2041;CARET INSERTION POINT;Po;0;ON;;;;;N;;;;;
-2042;ASTERISM;Po;0;ON;;;;;N;;;;;
-2043;HYPHEN BULLET;Po;0;ON;;;;;N;;;;;
-2044;FRACTION SLASH;Sm;0;CS;;;;;N;;;;;
-2045;LEFT SQUARE BRACKET WITH QUILL;Ps;0;ON;;;;;Y;;;;;
-2046;RIGHT SQUARE BRACKET WITH QUILL;Pe;0;ON;;;;;Y;;;;;
-2047;DOUBLE QUESTION MARK;Po;0;ON;<compat> 003F 003F;;;;N;;;;;
-2048;QUESTION EXCLAMATION MARK;Po;0;ON;<compat> 003F 0021;;;;N;;;;;
-2049;EXCLAMATION QUESTION MARK;Po;0;ON;<compat> 0021 003F;;;;N;;;;;
-204A;TIRONIAN SIGN ET;Po;0;ON;;;;;N;;;;;
-204B;REVERSED PILCROW SIGN;Po;0;ON;;;;;N;;;;;
-204C;BLACK LEFTWARDS BULLET;Po;0;ON;;;;;N;;;;;
-204D;BLACK RIGHTWARDS BULLET;Po;0;ON;;;;;N;;;;;
-204E;LOW ASTERISK;Po;0;ON;;;;;N;;;;;
-204F;REVERSED SEMICOLON;Po;0;ON;;;;;N;;;;;
-2050;CLOSE UP;Po;0;ON;;;;;N;;;;;
-2051;TWO ASTERISKS ALIGNED VERTICALLY;Po;0;ON;;;;;N;;;;;
-2052;COMMERCIAL MINUS SIGN;Sm;0;ON;;;;;N;;;;;
-2053;SWUNG DASH;Po;0;ON;;;;;N;;;;;
-2054;INVERTED UNDERTIE;Pc;0;ON;;;;;N;;;;;
-2055;FLOWER PUNCTUATION MARK;Po;0;ON;;;;;N;;;;;
-2056;THREE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-2057;QUADRUPLE PRIME;Po;0;ON;<compat> 2032 2032 2032 2032;;;;N;;;;;
-2058;FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-2059;FIVE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-205A;TWO DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-205B;FOUR DOT MARK;Po;0;ON;;;;;N;;;;;
-205C;DOTTED CROSS;Po;0;ON;;;;;N;;;;;
-205D;TRICOLON;Po;0;ON;;;;;N;;;;;
-205E;VERTICAL FOUR DOTS;Po;0;ON;;;;;N;;;;;
-205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-2060;WORD JOINER;Cf;0;BN;;;;;N;;;;;
-2061;FUNCTION APPLICATION;Cf;0;BN;;;;;N;;;;;
-2062;INVISIBLE TIMES;Cf;0;BN;;;;;N;;;;;
-2063;INVISIBLE SEPARATOR;Cf;0;BN;;;;;N;;;;;
-2064;INVISIBLE PLUS;Cf;0;BN;;;;;N;;;;;
-206A;INHIBIT SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;;
-206B;ACTIVATE SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;;
-206C;INHIBIT ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;;
-206D;ACTIVATE ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;;
-206E;NATIONAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;;
-206F;NOMINAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;;
-2070;SUPERSCRIPT ZERO;No;0;EN;<super> 0030;;0;0;N;SUPERSCRIPT DIGIT ZERO;;;;
-2071;SUPERSCRIPT LATIN SMALL LETTER I;Lm;0;L;<super> 0069;;;;N;;;;;
-2074;SUPERSCRIPT FOUR;No;0;EN;<super> 0034;;4;4;N;SUPERSCRIPT DIGIT FOUR;;;;
-2075;SUPERSCRIPT FIVE;No;0;EN;<super> 0035;;5;5;N;SUPERSCRIPT DIGIT FIVE;;;;
-2076;SUPERSCRIPT SIX;No;0;EN;<super> 0036;;6;6;N;SUPERSCRIPT DIGIT SIX;;;;
-2077;SUPERSCRIPT SEVEN;No;0;EN;<super> 0037;;7;7;N;SUPERSCRIPT DIGIT SEVEN;;;;
-2078;SUPERSCRIPT EIGHT;No;0;EN;<super> 0038;;8;8;N;SUPERSCRIPT DIGIT EIGHT;;;;
-2079;SUPERSCRIPT NINE;No;0;EN;<super> 0039;;9;9;N;SUPERSCRIPT DIGIT NINE;;;;
-207A;SUPERSCRIPT PLUS SIGN;Sm;0;ES;<super> 002B;;;;N;;;;;
-207B;SUPERSCRIPT MINUS;Sm;0;ES;<super> 2212;;;;N;SUPERSCRIPT HYPHEN-MINUS;;;;
-207C;SUPERSCRIPT EQUALS SIGN;Sm;0;ON;<super> 003D;;;;N;;;;;
-207D;SUPERSCRIPT LEFT PARENTHESIS;Ps;0;ON;<super> 0028;;;;Y;SUPERSCRIPT OPENING PARENTHESIS;;;;
-207E;SUPERSCRIPT RIGHT PARENTHESIS;Pe;0;ON;<super> 0029;;;;Y;SUPERSCRIPT CLOSING PARENTHESIS;;;;
-207F;SUPERSCRIPT LATIN SMALL LETTER N;Lm;0;L;<super> 006E;;;;N;;;;;
-2080;SUBSCRIPT ZERO;No;0;EN;<sub> 0030;;0;0;N;SUBSCRIPT DIGIT ZERO;;;;
-2081;SUBSCRIPT ONE;No;0;EN;<sub> 0031;;1;1;N;SUBSCRIPT DIGIT ONE;;;;
-2082;SUBSCRIPT TWO;No;0;EN;<sub> 0032;;2;2;N;SUBSCRIPT DIGIT TWO;;;;
-2083;SUBSCRIPT THREE;No;0;EN;<sub> 0033;;3;3;N;SUBSCRIPT DIGIT THREE;;;;
-2084;SUBSCRIPT FOUR;No;0;EN;<sub> 0034;;4;4;N;SUBSCRIPT DIGIT FOUR;;;;
-2085;SUBSCRIPT FIVE;No;0;EN;<sub> 0035;;5;5;N;SUBSCRIPT DIGIT FIVE;;;;
-2086;SUBSCRIPT SIX;No;0;EN;<sub> 0036;;6;6;N;SUBSCRIPT DIGIT SIX;;;;
-2087;SUBSCRIPT SEVEN;No;0;EN;<sub> 0037;;7;7;N;SUBSCRIPT DIGIT SEVEN;;;;
-2088;SUBSCRIPT EIGHT;No;0;EN;<sub> 0038;;8;8;N;SUBSCRIPT DIGIT EIGHT;;;;
-2089;SUBSCRIPT NINE;No;0;EN;<sub> 0039;;9;9;N;SUBSCRIPT DIGIT NINE;;;;
-208A;SUBSCRIPT PLUS SIGN;Sm;0;ES;<sub> 002B;;;;N;;;;;
-208B;SUBSCRIPT MINUS;Sm;0;ES;<sub> 2212;;;;N;SUBSCRIPT HYPHEN-MINUS;;;;
-208C;SUBSCRIPT EQUALS SIGN;Sm;0;ON;<sub> 003D;;;;N;;;;;
-208D;SUBSCRIPT LEFT PARENTHESIS;Ps;0;ON;<sub> 0028;;;;Y;SUBSCRIPT OPENING PARENTHESIS;;;;
-208E;SUBSCRIPT RIGHT PARENTHESIS;Pe;0;ON;<sub> 0029;;;;Y;SUBSCRIPT CLOSING PARENTHESIS;;;;
-2090;LATIN SUBSCRIPT SMALL LETTER A;Lm;0;L;<sub> 0061;;;;N;;;;;
-2091;LATIN SUBSCRIPT SMALL LETTER E;Lm;0;L;<sub> 0065;;;;N;;;;;
-2092;LATIN SUBSCRIPT SMALL LETTER O;Lm;0;L;<sub> 006F;;;;N;;;;;
-2093;LATIN SUBSCRIPT SMALL LETTER X;Lm;0;L;<sub> 0078;;;;N;;;;;
-2094;LATIN SUBSCRIPT SMALL LETTER SCHWA;Lm;0;L;<sub> 0259;;;;N;;;;;
-2095;LATIN SUBSCRIPT SMALL LETTER H;Lm;0;L;<sub> 0068;;;;N;;;;;
-2096;LATIN SUBSCRIPT SMALL LETTER K;Lm;0;L;<sub> 006B;;;;N;;;;;
-2097;LATIN SUBSCRIPT SMALL LETTER L;Lm;0;L;<sub> 006C;;;;N;;;;;
-2098;LATIN SUBSCRIPT SMALL LETTER M;Lm;0;L;<sub> 006D;;;;N;;;;;
-2099;LATIN SUBSCRIPT SMALL LETTER N;Lm;0;L;<sub> 006E;;;;N;;;;;
-209A;LATIN SUBSCRIPT SMALL LETTER P;Lm;0;L;<sub> 0070;;;;N;;;;;
-209B;LATIN SUBSCRIPT SMALL LETTER S;Lm;0;L;<sub> 0073;;;;N;;;;;
-209C;LATIN SUBSCRIPT SMALL LETTER T;Lm;0;L;<sub> 0074;;;;N;;;;;
-20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;;
-20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;;
-20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;;
-20A3;FRENCH FRANC SIGN;Sc;0;ET;;;;;N;;;;;
-20A4;LIRA SIGN;Sc;0;ET;;;;;N;;;;;
-20A5;MILL SIGN;Sc;0;ET;;;;;N;;;;;
-20A6;NAIRA SIGN;Sc;0;ET;;;;;N;;;;;
-20A7;PESETA SIGN;Sc;0;ET;;;;;N;;;;;
-20A8;RUPEE SIGN;Sc;0;ET;<compat> 0052 0073;;;;N;;;;;
-20A9;WON SIGN;Sc;0;ET;;;;;N;;;;;
-20AA;NEW SHEQEL SIGN;Sc;0;ET;;;;;N;;;;;
-20AB;DONG SIGN;Sc;0;ET;;;;;N;;;;;
-20AC;EURO SIGN;Sc;0;ET;;;;;N;;;;;
-20AD;KIP SIGN;Sc;0;ET;;;;;N;;;;;
-20AE;TUGRIK SIGN;Sc;0;ET;;;;;N;;;;;
-20AF;DRACHMA SIGN;Sc;0;ET;;;;;N;;;;;
-20B0;GERMAN PENNY SIGN;Sc;0;ET;;;;;N;;;;;
-20B1;PESO SIGN;Sc;0;ET;;;;;N;;;;;
-20B2;GUARANI SIGN;Sc;0;ET;;;;;N;;;;;
-20B3;AUSTRAL SIGN;Sc;0;ET;;;;;N;;;;;
-20B4;HRYVNIA SIGN;Sc;0;ET;;;;;N;;;;;
-20B5;CEDI SIGN;Sc;0;ET;;;;;N;;;;;
-20B6;LIVRE TOURNOIS SIGN;Sc;0;ET;;;;;N;;;;;
-20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;;
-20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;;
-20B9;INDIAN RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
-20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;;
-20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;;
-20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;;
-20D3;COMBINING SHORT VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT VERTICAL BAR OVERLAY;;;;
-20D4;COMBINING ANTICLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING ANTICLOCKWISE ARROW ABOVE;;;;
-20D5;COMBINING CLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING CLOCKWISE ARROW ABOVE;;;;
-20D6;COMBINING LEFT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT ARROW ABOVE;;;;
-20D7;COMBINING RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT ARROW ABOVE;;;;
-20D8;COMBINING RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING RING OVERLAY;;;;
-20D9;COMBINING CLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING CLOCKWISE RING OVERLAY;;;;
-20DA;COMBINING ANTICLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING ANTICLOCKWISE RING OVERLAY;;;;
-20DB;COMBINING THREE DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING THREE DOTS ABOVE;;;;
-20DC;COMBINING FOUR DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING FOUR DOTS ABOVE;;;;
-20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;;
-20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;;
-20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;;
-20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;;
-20E1;COMBINING LEFT RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT RIGHT ARROW ABOVE;;;;
-20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;;
-20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;;
-20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;;
-20E5;COMBINING REVERSE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;;
-20E6;COMBINING DOUBLE VERTICAL STROKE OVERLAY;Mn;1;NSM;;;;;N;;;;;
-20E7;COMBINING ANNUITY SYMBOL;Mn;230;NSM;;;;;N;;;;;
-20E8;COMBINING TRIPLE UNDERDOT;Mn;220;NSM;;;;;N;;;;;
-20E9;COMBINING WIDE BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;;
-20EA;COMBINING LEFTWARDS ARROW OVERLAY;Mn;1;NSM;;;;;N;;;;;
-20EB;COMBINING LONG DOUBLE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;;
-20EC;COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;;
-20ED;COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;;
-20EE;COMBINING LEFT ARROW BELOW;Mn;220;NSM;;;;;N;;;;;
-20EF;COMBINING RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;;
-20F0;COMBINING ASTERISK ABOVE;Mn;230;NSM;;;;;N;;;;;
-2100;ACCOUNT OF;So;0;ON;<compat> 0061 002F 0063;;;;N;;;;;
-2101;ADDRESSED TO THE SUBJECT;So;0;ON;<compat> 0061 002F 0073;;;;N;;;;;
-2102;DOUBLE-STRUCK CAPITAL C;Lu;0;L;<font> 0043;;;;N;DOUBLE-STRUCK C;;;;
-2103;DEGREE CELSIUS;So;0;ON;<compat> 00B0 0043;;;;N;DEGREES CENTIGRADE;;;;
-2104;CENTRE LINE SYMBOL;So;0;ON;;;;;N;C L SYMBOL;;;;
-2105;CARE OF;So;0;ON;<compat> 0063 002F 006F;;;;N;;;;;
-2106;CADA UNA;So;0;ON;<compat> 0063 002F 0075;;;;N;;;;;
-2107;EULER CONSTANT;Lu;0;L;<compat> 0190;;;;N;EULERS;;;;
-2108;SCRUPLE;So;0;ON;;;;;N;;;;;
-2109;DEGREE FAHRENHEIT;So;0;ON;<compat> 00B0 0046;;;;N;DEGREES FAHRENHEIT;;;;
-210A;SCRIPT SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-210B;SCRIPT CAPITAL H;Lu;0;L;<font> 0048;;;;N;SCRIPT H;;;;
-210C;BLACK-LETTER CAPITAL H;Lu;0;L;<font> 0048;;;;N;BLACK-LETTER H;;;;
-210D;DOUBLE-STRUCK CAPITAL H;Lu;0;L;<font> 0048;;;;N;DOUBLE-STRUCK H;;;;
-210E;PLANCK CONSTANT;Ll;0;L;<font> 0068;;;;N;;;;;
-210F;PLANCK CONSTANT OVER TWO PI;Ll;0;L;<font> 0127;;;;N;PLANCK CONSTANT OVER 2 PI;;;;
-2110;SCRIPT CAPITAL I;Lu;0;L;<font> 0049;;;;N;SCRIPT I;;;;
-2111;BLACK-LETTER CAPITAL I;Lu;0;L;<font> 0049;;;;N;BLACK-LETTER I;;;;
-2112;SCRIPT CAPITAL L;Lu;0;L;<font> 004C;;;;N;SCRIPT L;;;;
-2113;SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-2114;L B BAR SYMBOL;So;0;ON;;;;;N;;;;;
-2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L;<font> 004E;;;;N;DOUBLE-STRUCK N;;;;
-2116;NUMERO SIGN;So;0;ON;<compat> 004E 006F;;;;N;NUMERO;;;;
-2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;;
-2118;SCRIPT CAPITAL P;Sm;0;ON;;;;;N;SCRIPT P;;;;
-2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L;<font> 0050;;;;N;DOUBLE-STRUCK P;;;;
-211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L;<font> 0051;;;;N;DOUBLE-STRUCK Q;;;;
-211B;SCRIPT CAPITAL R;Lu;0;L;<font> 0052;;;;N;SCRIPT R;;;;
-211C;BLACK-LETTER CAPITAL R;Lu;0;L;<font> 0052;;;;N;BLACK-LETTER R;;;;
-211D;DOUBLE-STRUCK CAPITAL R;Lu;0;L;<font> 0052;;;;N;DOUBLE-STRUCK R;;;;
-211E;PRESCRIPTION TAKE;So;0;ON;;;;;N;;;;;
-211F;RESPONSE;So;0;ON;;;;;N;;;;;
-2120;SERVICE MARK;So;0;ON;<super> 0053 004D;;;;N;;;;;
-2121;TELEPHONE SIGN;So;0;ON;<compat> 0054 0045 004C;;;;N;T E L SYMBOL;;;;
-2122;TRADE MARK SIGN;So;0;ON;<super> 0054 004D;;;;N;TRADEMARK;;;;
-2123;VERSICLE;So;0;ON;;;;;N;;;;;
-2124;DOUBLE-STRUCK CAPITAL Z;Lu;0;L;<font> 005A;;;;N;DOUBLE-STRUCK Z;;;;
-2125;OUNCE SIGN;So;0;ON;;;;;N;OUNCE;;;;
-2126;OHM SIGN;Lu;0;L;03A9;;;;N;OHM;;;03C9;
-2127;INVERTED OHM SIGN;So;0;ON;;;;;N;MHO;;;;
-2128;BLACK-LETTER CAPITAL Z;Lu;0;L;<font> 005A;;;;N;BLACK-LETTER Z;;;;
-2129;TURNED GREEK SMALL LETTER IOTA;So;0;ON;;;;;N;;;;;
-212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B;
-212B;ANGSTROM SIGN;Lu;0;L;00C5;;;;N;ANGSTROM UNIT;;;00E5;
-212C;SCRIPT CAPITAL B;Lu;0;L;<font> 0042;;;;N;SCRIPT B;;;;
-212D;BLACK-LETTER CAPITAL C;Lu;0;L;<font> 0043;;;;N;BLACK-LETTER C;;;;
-212E;ESTIMATED SYMBOL;So;0;ET;;;;;N;;;;;
-212F;SCRIPT SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-2130;SCRIPT CAPITAL E;Lu;0;L;<font> 0045;;;;N;SCRIPT E;;;;
-2131;SCRIPT CAPITAL F;Lu;0;L;<font> 0046;;;;N;SCRIPT F;;;;
-2132;TURNED CAPITAL F;Lu;0;L;;;;;N;TURNED F;;;214E;
-2133;SCRIPT CAPITAL M;Lu;0;L;<font> 004D;;;;N;SCRIPT M;;;;
-2134;SCRIPT SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-2135;ALEF SYMBOL;Lo;0;L;<compat> 05D0;;;;N;FIRST TRANSFINITE CARDINAL;;;;
-2136;BET SYMBOL;Lo;0;L;<compat> 05D1;;;;N;SECOND TRANSFINITE CARDINAL;;;;
-2137;GIMEL SYMBOL;Lo;0;L;<compat> 05D2;;;;N;THIRD TRANSFINITE CARDINAL;;;;
-2138;DALET SYMBOL;Lo;0;L;<compat> 05D3;;;;N;FOURTH TRANSFINITE CARDINAL;;;;
-2139;INFORMATION SOURCE;Ll;0;L;<font> 0069;;;;N;;;;;
-213A;ROTATED CAPITAL Q;So;0;ON;;;;;N;;;;;
-213B;FACSIMILE SIGN;So;0;ON;<compat> 0046 0041 0058;;;;N;;;;;
-213C;DOUBLE-STRUCK SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
-213D;DOUBLE-STRUCK SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
-213E;DOUBLE-STRUCK CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
-213F;DOUBLE-STRUCK CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
-2140;DOUBLE-STRUCK N-ARY SUMMATION;Sm;0;ON;<font> 2211;;;;Y;;;;;
-2141;TURNED SANS-SERIF CAPITAL G;Sm;0;ON;;;;;N;;;;;
-2142;TURNED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;;
-2143;REVERSED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;;
-2144;TURNED SANS-SERIF CAPITAL Y;Sm;0;ON;;;;;N;;;;;
-2145;DOUBLE-STRUCK ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-2146;DOUBLE-STRUCK ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-2147;DOUBLE-STRUCK ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-2148;DOUBLE-STRUCK ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-2149;DOUBLE-STRUCK ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-214A;PROPERTY LINE;So;0;ON;;;;;N;;;;;
-214B;TURNED AMPERSAND;Sm;0;ON;;;;;N;;;;;
-214C;PER SIGN;So;0;ON;;;;;N;;;;;
-214D;AKTIESELSKAB;So;0;ON;;;;;N;;;;;
-214E;TURNED SMALL F;Ll;0;L;;;;;N;;;2132;;2132
-214F;SYMBOL FOR SAMARITAN SOURCE;So;0;L;;;;;N;;;;;
-2150;VULGAR FRACTION ONE SEVENTH;No;0;ON;<fraction> 0031 2044 0037;;;1/7;N;;;;;
-2151;VULGAR FRACTION ONE NINTH;No;0;ON;<fraction> 0031 2044 0039;;;1/9;N;;;;;
-2152;VULGAR FRACTION ONE TENTH;No;0;ON;<fraction> 0031 2044 0031 0030;;;1/10;N;;;;;
-2153;VULGAR FRACTION ONE THIRD;No;0;ON;<fraction> 0031 2044 0033;;;1/3;N;FRACTION ONE THIRD;;;;
-2154;VULGAR FRACTION TWO THIRDS;No;0;ON;<fraction> 0032 2044 0033;;;2/3;N;FRACTION TWO THIRDS;;;;
-2155;VULGAR FRACTION ONE FIFTH;No;0;ON;<fraction> 0031 2044 0035;;;1/5;N;FRACTION ONE FIFTH;;;;
-2156;VULGAR FRACTION TWO FIFTHS;No;0;ON;<fraction> 0032 2044 0035;;;2/5;N;FRACTION TWO FIFTHS;;;;
-2157;VULGAR FRACTION THREE FIFTHS;No;0;ON;<fraction> 0033 2044 0035;;;3/5;N;FRACTION THREE FIFTHS;;;;
-2158;VULGAR FRACTION FOUR FIFTHS;No;0;ON;<fraction> 0034 2044 0035;;;4/5;N;FRACTION FOUR FIFTHS;;;;
-2159;VULGAR FRACTION ONE SIXTH;No;0;ON;<fraction> 0031 2044 0036;;;1/6;N;FRACTION ONE SIXTH;;;;
-215A;VULGAR FRACTION FIVE SIXTHS;No;0;ON;<fraction> 0035 2044 0036;;;5/6;N;FRACTION FIVE SIXTHS;;;;
-215B;VULGAR FRACTION ONE EIGHTH;No;0;ON;<fraction> 0031 2044 0038;;;1/8;N;FRACTION ONE EIGHTH;;;;
-215C;VULGAR FRACTION THREE EIGHTHS;No;0;ON;<fraction> 0033 2044 0038;;;3/8;N;FRACTION THREE EIGHTHS;;;;
-215D;VULGAR FRACTION FIVE EIGHTHS;No;0;ON;<fraction> 0035 2044 0038;;;5/8;N;FRACTION FIVE EIGHTHS;;;;
-215E;VULGAR FRACTION SEVEN EIGHTHS;No;0;ON;<fraction> 0037 2044 0038;;;7/8;N;FRACTION SEVEN EIGHTHS;;;;
-215F;FRACTION NUMERATOR ONE;No;0;ON;<fraction> 0031 2044;;;1;N;;;;;
-2160;ROMAN NUMERAL ONE;Nl;0;L;<compat> 0049;;;1;N;;;;2170;
-2161;ROMAN NUMERAL TWO;Nl;0;L;<compat> 0049 0049;;;2;N;;;;2171;
-2162;ROMAN NUMERAL THREE;Nl;0;L;<compat> 0049 0049 0049;;;3;N;;;;2172;
-2163;ROMAN NUMERAL FOUR;Nl;0;L;<compat> 0049 0056;;;4;N;;;;2173;
-2164;ROMAN NUMERAL FIVE;Nl;0;L;<compat> 0056;;;5;N;;;;2174;
-2165;ROMAN NUMERAL SIX;Nl;0;L;<compat> 0056 0049;;;6;N;;;;2175;
-2166;ROMAN NUMERAL SEVEN;Nl;0;L;<compat> 0056 0049 0049;;;7;N;;;;2176;
-2167;ROMAN NUMERAL EIGHT;Nl;0;L;<compat> 0056 0049 0049 0049;;;8;N;;;;2177;
-2168;ROMAN NUMERAL NINE;Nl;0;L;<compat> 0049 0058;;;9;N;;;;2178;
-2169;ROMAN NUMERAL TEN;Nl;0;L;<compat> 0058;;;10;N;;;;2179;
-216A;ROMAN NUMERAL ELEVEN;Nl;0;L;<compat> 0058 0049;;;11;N;;;;217A;
-216B;ROMAN NUMERAL TWELVE;Nl;0;L;<compat> 0058 0049 0049;;;12;N;;;;217B;
-216C;ROMAN NUMERAL FIFTY;Nl;0;L;<compat> 004C;;;50;N;;;;217C;
-216D;ROMAN NUMERAL ONE HUNDRED;Nl;0;L;<compat> 0043;;;100;N;;;;217D;
-216E;ROMAN NUMERAL FIVE HUNDRED;Nl;0;L;<compat> 0044;;;500;N;;;;217E;
-216F;ROMAN NUMERAL ONE THOUSAND;Nl;0;L;<compat> 004D;;;1000;N;;;;217F;
-2170;SMALL ROMAN NUMERAL ONE;Nl;0;L;<compat> 0069;;;1;N;;;2160;;2160
-2171;SMALL ROMAN NUMERAL TWO;Nl;0;L;<compat> 0069 0069;;;2;N;;;2161;;2161
-2172;SMALL ROMAN NUMERAL THREE;Nl;0;L;<compat> 0069 0069 0069;;;3;N;;;2162;;2162
-2173;SMALL ROMAN NUMERAL FOUR;Nl;0;L;<compat> 0069 0076;;;4;N;;;2163;;2163
-2174;SMALL ROMAN NUMERAL FIVE;Nl;0;L;<compat> 0076;;;5;N;;;2164;;2164
-2175;SMALL ROMAN NUMERAL SIX;Nl;0;L;<compat> 0076 0069;;;6;N;;;2165;;2165
-2176;SMALL ROMAN NUMERAL SEVEN;Nl;0;L;<compat> 0076 0069 0069;;;7;N;;;2166;;2166
-2177;SMALL ROMAN NUMERAL EIGHT;Nl;0;L;<compat> 0076 0069 0069 0069;;;8;N;;;2167;;2167
-2178;SMALL ROMAN NUMERAL NINE;Nl;0;L;<compat> 0069 0078;;;9;N;;;2168;;2168
-2179;SMALL ROMAN NUMERAL TEN;Nl;0;L;<compat> 0078;;;10;N;;;2169;;2169
-217A;SMALL ROMAN NUMERAL ELEVEN;Nl;0;L;<compat> 0078 0069;;;11;N;;;216A;;216A
-217B;SMALL ROMAN NUMERAL TWELVE;Nl;0;L;<compat> 0078 0069 0069;;;12;N;;;216B;;216B
-217C;SMALL ROMAN NUMERAL FIFTY;Nl;0;L;<compat> 006C;;;50;N;;;216C;;216C
-217D;SMALL ROMAN NUMERAL ONE HUNDRED;Nl;0;L;<compat> 0063;;;100;N;;;216D;;216D
-217E;SMALL ROMAN NUMERAL FIVE HUNDRED;Nl;0;L;<compat> 0064;;;500;N;;;216E;;216E
-217F;SMALL ROMAN NUMERAL ONE THOUSAND;Nl;0;L;<compat> 006D;;;1000;N;;;216F;;216F
-2180;ROMAN NUMERAL ONE THOUSAND C D;Nl;0;L;;;;1000;N;;;;;
-2181;ROMAN NUMERAL FIVE THOUSAND;Nl;0;L;;;;5000;N;;;;;
-2182;ROMAN NUMERAL TEN THOUSAND;Nl;0;L;;;;10000;N;;;;;
-2183;ROMAN NUMERAL REVERSED ONE HUNDRED;Lu;0;L;;;;;N;;;;2184;
-2184;LATIN SMALL LETTER REVERSED C;Ll;0;L;;;;;N;;;2183;;2183
-2185;ROMAN NUMERAL SIX LATE FORM;Nl;0;L;;;;6;N;;;;;
-2186;ROMAN NUMERAL FIFTY EARLY FORM;Nl;0;L;;;;50;N;;;;;
-2187;ROMAN NUMERAL FIFTY THOUSAND;Nl;0;L;;;;50000;N;;;;;
-2188;ROMAN NUMERAL ONE HUNDRED THOUSAND;Nl;0;L;;;;100000;N;;;;;
-2189;VULGAR FRACTION ZERO THIRDS;No;0;ON;<fraction> 0030 2044 0033;;;0;N;;;;;
-2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;;
-2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;;
-2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;;
-2193;DOWNWARDS ARROW;Sm;0;ON;;;;;N;DOWN ARROW;;;;
-2194;LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;;
-2195;UP DOWN ARROW;So;0;ON;;;;;N;;;;;
-2196;NORTH WEST ARROW;So;0;ON;;;;;N;UPPER LEFT ARROW;;;;
-2197;NORTH EAST ARROW;So;0;ON;;;;;N;UPPER RIGHT ARROW;;;;
-2198;SOUTH EAST ARROW;So;0;ON;;;;;N;LOWER RIGHT ARROW;;;;
-2199;SOUTH WEST ARROW;So;0;ON;;;;;N;LOWER LEFT ARROW;;;;
-219A;LEFTWARDS ARROW WITH STROKE;Sm;0;ON;2190 0338;;;;N;LEFT ARROW WITH STROKE;;;;
-219B;RIGHTWARDS ARROW WITH STROKE;Sm;0;ON;2192 0338;;;;N;RIGHT ARROW WITH STROKE;;;;
-219C;LEFTWARDS WAVE ARROW;So;0;ON;;;;;N;LEFT WAVE ARROW;;;;
-219D;RIGHTWARDS WAVE ARROW;So;0;ON;;;;;N;RIGHT WAVE ARROW;;;;
-219E;LEFTWARDS TWO HEADED ARROW;So;0;ON;;;;;N;LEFT TWO HEADED ARROW;;;;
-219F;UPWARDS TWO HEADED ARROW;So;0;ON;;;;;N;UP TWO HEADED ARROW;;;;
-21A0;RIGHTWARDS TWO HEADED ARROW;Sm;0;ON;;;;;N;RIGHT TWO HEADED ARROW;;;;
-21A1;DOWNWARDS TWO HEADED ARROW;So;0;ON;;;;;N;DOWN TWO HEADED ARROW;;;;
-21A2;LEFTWARDS ARROW WITH TAIL;So;0;ON;;;;;N;LEFT ARROW WITH TAIL;;;;
-21A3;RIGHTWARDS ARROW WITH TAIL;Sm;0;ON;;;;;N;RIGHT ARROW WITH TAIL;;;;
-21A4;LEFTWARDS ARROW FROM BAR;So;0;ON;;;;;N;LEFT ARROW FROM BAR;;;;
-21A5;UPWARDS ARROW FROM BAR;So;0;ON;;;;;N;UP ARROW FROM BAR;;;;
-21A6;RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;RIGHT ARROW FROM BAR;;;;
-21A7;DOWNWARDS ARROW FROM BAR;So;0;ON;;;;;N;DOWN ARROW FROM BAR;;;;
-21A8;UP DOWN ARROW WITH BASE;So;0;ON;;;;;N;;;;;
-21A9;LEFTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;LEFT ARROW WITH HOOK;;;;
-21AA;RIGHTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;RIGHT ARROW WITH HOOK;;;;
-21AB;LEFTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;LEFT ARROW WITH LOOP;;;;
-21AC;RIGHTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;RIGHT ARROW WITH LOOP;;;;
-21AD;LEFT RIGHT WAVE ARROW;So;0;ON;;;;;N;;;;;
-21AE;LEFT RIGHT ARROW WITH STROKE;Sm;0;ON;2194 0338;;;;N;;;;;
-21AF;DOWNWARDS ZIGZAG ARROW;So;0;ON;;;;;N;DOWN ZIGZAG ARROW;;;;
-21B0;UPWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP LEFT;;;;
-21B1;UPWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP RIGHT;;;;
-21B2;DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP LEFT;;;;
-21B3;DOWNWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP RIGHT;;;;
-21B4;RIGHTWARDS ARROW WITH CORNER DOWNWARDS;So;0;ON;;;;;N;RIGHT ARROW WITH CORNER DOWN;;;;
-21B5;DOWNWARDS ARROW WITH CORNER LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH CORNER LEFT;;;;
-21B6;ANTICLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;;
-21B7;CLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;;
-21B8;NORTH WEST ARROW TO LONG BAR;So;0;ON;;;;;N;UPPER LEFT ARROW TO LONG BAR;;;;
-21B9;LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR;;;;
-21BA;ANTICLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;;
-21BB;CLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;;
-21BC;LEFTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB UP;;;;
-21BD;LEFTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB DOWN;;;;
-21BE;UPWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB RIGHT;;;;
-21BF;UPWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB LEFT;;;;
-21C0;RIGHTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB UP;;;;
-21C1;RIGHTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB DOWN;;;;
-21C2;DOWNWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB RIGHT;;;;
-21C3;DOWNWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB LEFT;;;;
-21C4;RIGHTWARDS ARROW OVER LEFTWARDS ARROW;So;0;ON;;;;;N;RIGHT ARROW OVER LEFT ARROW;;;;
-21C5;UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW;So;0;ON;;;;;N;UP ARROW LEFT OF DOWN ARROW;;;;
-21C6;LEFTWARDS ARROW OVER RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT ARROW OVER RIGHT ARROW;;;;
-21C7;LEFTWARDS PAIRED ARROWS;So;0;ON;;;;;N;LEFT PAIRED ARROWS;;;;
-21C8;UPWARDS PAIRED ARROWS;So;0;ON;;;;;N;UP PAIRED ARROWS;;;;
-21C9;RIGHTWARDS PAIRED ARROWS;So;0;ON;;;;;N;RIGHT PAIRED ARROWS;;;;
-21CA;DOWNWARDS PAIRED ARROWS;So;0;ON;;;;;N;DOWN PAIRED ARROWS;;;;
-21CB;LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON;So;0;ON;;;;;N;LEFT HARPOON OVER RIGHT HARPOON;;;;
-21CC;RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON;So;0;ON;;;;;N;RIGHT HARPOON OVER LEFT HARPOON;;;;
-21CD;LEFTWARDS DOUBLE ARROW WITH STROKE;So;0;ON;21D0 0338;;;;N;LEFT DOUBLE ARROW WITH STROKE;;;;
-21CE;LEFT RIGHT DOUBLE ARROW WITH STROKE;Sm;0;ON;21D4 0338;;;;N;;;;;
-21CF;RIGHTWARDS DOUBLE ARROW WITH STROKE;Sm;0;ON;21D2 0338;;;;N;RIGHT DOUBLE ARROW WITH STROKE;;;;
-21D0;LEFTWARDS DOUBLE ARROW;So;0;ON;;;;;N;LEFT DOUBLE ARROW;;;;
-21D1;UPWARDS DOUBLE ARROW;So;0;ON;;;;;N;UP DOUBLE ARROW;;;;
-21D2;RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;RIGHT DOUBLE ARROW;;;;
-21D3;DOWNWARDS DOUBLE ARROW;So;0;ON;;;;;N;DOWN DOUBLE ARROW;;;;
-21D4;LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;;
-21D5;UP DOWN DOUBLE ARROW;So;0;ON;;;;;N;;;;;
-21D6;NORTH WEST DOUBLE ARROW;So;0;ON;;;;;N;UPPER LEFT DOUBLE ARROW;;;;
-21D7;NORTH EAST DOUBLE ARROW;So;0;ON;;;;;N;UPPER RIGHT DOUBLE ARROW;;;;
-21D8;SOUTH EAST DOUBLE ARROW;So;0;ON;;;;;N;LOWER RIGHT DOUBLE ARROW;;;;
-21D9;SOUTH WEST DOUBLE ARROW;So;0;ON;;;;;N;LOWER LEFT DOUBLE ARROW;;;;
-21DA;LEFTWARDS TRIPLE ARROW;So;0;ON;;;;;N;LEFT TRIPLE ARROW;;;;
-21DB;RIGHTWARDS TRIPLE ARROW;So;0;ON;;;;;N;RIGHT TRIPLE ARROW;;;;
-21DC;LEFTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;LEFT SQUIGGLE ARROW;;;;
-21DD;RIGHTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;RIGHT SQUIGGLE ARROW;;;;
-21DE;UPWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;UP ARROW WITH DOUBLE STROKE;;;;
-21DF;DOWNWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;DOWN ARROW WITH DOUBLE STROKE;;;;
-21E0;LEFTWARDS DASHED ARROW;So;0;ON;;;;;N;LEFT DASHED ARROW;;;;
-21E1;UPWARDS DASHED ARROW;So;0;ON;;;;;N;UP DASHED ARROW;;;;
-21E2;RIGHTWARDS DASHED ARROW;So;0;ON;;;;;N;RIGHT DASHED ARROW;;;;
-21E3;DOWNWARDS DASHED ARROW;So;0;ON;;;;;N;DOWN DASHED ARROW;;;;
-21E4;LEFTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR;;;;
-21E5;RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;RIGHT ARROW TO BAR;;;;
-21E6;LEFTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE LEFT ARROW;;;;
-21E7;UPWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE UP ARROW;;;;
-21E8;RIGHTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE RIGHT ARROW;;;;
-21E9;DOWNWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE DOWN ARROW;;;;
-21EA;UPWARDS WHITE ARROW FROM BAR;So;0;ON;;;;;N;WHITE UP ARROW FROM BAR;;;;
-21EB;UPWARDS WHITE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;;
-21EC;UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;;
-21ED;UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR;So;0;ON;;;;;N;;;;;
-21EE;UPWARDS WHITE DOUBLE ARROW;So;0;ON;;;;;N;;;;;
-21EF;UPWARDS WHITE DOUBLE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;;
-21F0;RIGHTWARDS WHITE ARROW FROM WALL;So;0;ON;;;;;N;;;;;
-21F1;NORTH WEST ARROW TO CORNER;So;0;ON;;;;;N;;;;;
-21F2;SOUTH EAST ARROW TO CORNER;So;0;ON;;;;;N;;;;;
-21F3;UP DOWN WHITE ARROW;So;0;ON;;;;;N;;;;;
-21F4;RIGHT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
-21F5;DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-21F6;THREE RIGHTWARDS ARROWS;Sm;0;ON;;;;;N;;;;;
-21F7;LEFTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-21F8;RIGHTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-21F9;LEFT RIGHT ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-21FA;LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-21FB;RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-21FC;LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-21FD;LEFTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;;
-21FE;RIGHTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;;
-21FF;LEFT RIGHT OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;;
-2200;FOR ALL;Sm;0;ON;;;;;N;;;;;
-2201;COMPLEMENT;Sm;0;ON;;;;;Y;;;;;
-2202;PARTIAL DIFFERENTIAL;Sm;0;ON;;;;;Y;;;;;
-2203;THERE EXISTS;Sm;0;ON;;;;;Y;;;;;
-2204;THERE DOES NOT EXIST;Sm;0;ON;2203 0338;;;;Y;;;;;
-2205;EMPTY SET;Sm;0;ON;;;;;N;;;;;
-2206;INCREMENT;Sm;0;ON;;;;;N;;;;;
-2207;NABLA;Sm;0;ON;;;;;N;;;;;
-2208;ELEMENT OF;Sm;0;ON;;;;;Y;;;;;
-2209;NOT AN ELEMENT OF;Sm;0;ON;2208 0338;;;;Y;;;;;
-220A;SMALL ELEMENT OF;Sm;0;ON;;;;;Y;;;;;
-220B;CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;;
-220C;DOES NOT CONTAIN AS MEMBER;Sm;0;ON;220B 0338;;;;Y;;;;;
-220D;SMALL CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;;
-220E;END OF PROOF;Sm;0;ON;;;;;N;;;;;
-220F;N-ARY PRODUCT;Sm;0;ON;;;;;N;;;;;
-2210;N-ARY COPRODUCT;Sm;0;ON;;;;;N;;;;;
-2211;N-ARY SUMMATION;Sm;0;ON;;;;;Y;;;;;
-2212;MINUS SIGN;Sm;0;ES;;;;;N;;;;;
-2213;MINUS-OR-PLUS SIGN;Sm;0;ET;;;;;N;;;;;
-2214;DOT PLUS;Sm;0;ON;;;;;N;;;;;
-2215;DIVISION SLASH;Sm;0;ON;;;;;Y;;;;;
-2216;SET MINUS;Sm;0;ON;;;;;Y;;;;;
-2217;ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;;
-2218;RING OPERATOR;Sm;0;ON;;;;;N;;;;;
-2219;BULLET OPERATOR;Sm;0;ON;;;;;N;;;;;
-221A;SQUARE ROOT;Sm;0;ON;;;;;Y;;;;;
-221B;CUBE ROOT;Sm;0;ON;;;;;Y;;;;;
-221C;FOURTH ROOT;Sm;0;ON;;;;;Y;;;;;
-221D;PROPORTIONAL TO;Sm;0;ON;;;;;Y;;;;;
-221E;INFINITY;Sm;0;ON;;;;;N;;;;;
-221F;RIGHT ANGLE;Sm;0;ON;;;;;Y;;;;;
-2220;ANGLE;Sm;0;ON;;;;;Y;;;;;
-2221;MEASURED ANGLE;Sm;0;ON;;;;;Y;;;;;
-2222;SPHERICAL ANGLE;Sm;0;ON;;;;;Y;;;;;
-2223;DIVIDES;Sm;0;ON;;;;;N;;;;;
-2224;DOES NOT DIVIDE;Sm;0;ON;2223 0338;;;;Y;;;;;
-2225;PARALLEL TO;Sm;0;ON;;;;;N;;;;;
-2226;NOT PARALLEL TO;Sm;0;ON;2225 0338;;;;Y;;;;;
-2227;LOGICAL AND;Sm;0;ON;;;;;N;;;;;
-2228;LOGICAL OR;Sm;0;ON;;;;;N;;;;;
-2229;INTERSECTION;Sm;0;ON;;;;;N;;;;;
-222A;UNION;Sm;0;ON;;;;;N;;;;;
-222B;INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-222C;DOUBLE INTEGRAL;Sm;0;ON;<compat> 222B 222B;;;;Y;;;;;
-222D;TRIPLE INTEGRAL;Sm;0;ON;<compat> 222B 222B 222B;;;;Y;;;;;
-222E;CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-222F;SURFACE INTEGRAL;Sm;0;ON;<compat> 222E 222E;;;;Y;;;;;
-2230;VOLUME INTEGRAL;Sm;0;ON;<compat> 222E 222E 222E;;;;Y;;;;;
-2231;CLOCKWISE INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-2232;CLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-2233;ANTICLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-2234;THEREFORE;Sm;0;ON;;;;;N;;;;;
-2235;BECAUSE;Sm;0;ON;;;;;N;;;;;
-2236;RATIO;Sm;0;ON;;;;;N;;;;;
-2237;PROPORTION;Sm;0;ON;;;;;N;;;;;
-2238;DOT MINUS;Sm;0;ON;;;;;N;;;;;
-2239;EXCESS;Sm;0;ON;;;;;Y;;;;;
-223A;GEOMETRIC PROPORTION;Sm;0;ON;;;;;N;;;;;
-223B;HOMOTHETIC;Sm;0;ON;;;;;Y;;;;;
-223C;TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
-223D;REVERSED TILDE;Sm;0;ON;;;;;Y;;;;;
-223E;INVERTED LAZY S;Sm;0;ON;;;;;Y;;;;;
-223F;SINE WAVE;Sm;0;ON;;;;;Y;;;;;
-2240;WREATH PRODUCT;Sm;0;ON;;;;;Y;;;;;
-2241;NOT TILDE;Sm;0;ON;223C 0338;;;;Y;;;;;
-2242;MINUS TILDE;Sm;0;ON;;;;;Y;;;;;
-2243;ASYMPTOTICALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2244;NOT ASYMPTOTICALLY EQUAL TO;Sm;0;ON;2243 0338;;;;Y;;;;;
-2245;APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2246;APPROXIMATELY BUT NOT ACTUALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2247;NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO;Sm;0;ON;2245 0338;;;;Y;;;;;
-2248;ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2249;NOT ALMOST EQUAL TO;Sm;0;ON;2248 0338;;;;Y;;;;;
-224A;ALMOST EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-224B;TRIPLE TILDE;Sm;0;ON;;;;;Y;;;;;
-224C;ALL EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-224D;EQUIVALENT TO;Sm;0;ON;;;;;N;;;;;
-224E;GEOMETRICALLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;;
-224F;DIFFERENCE BETWEEN;Sm;0;ON;;;;;N;;;;;
-2250;APPROACHES THE LIMIT;Sm;0;ON;;;;;N;;;;;
-2251;GEOMETRICALLY EQUAL TO;Sm;0;ON;;;;;N;;;;;
-2252;APPROXIMATELY EQUAL TO OR THE IMAGE OF;Sm;0;ON;;;;;Y;;;;;
-2253;IMAGE OF OR APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2254;COLON EQUALS;Sm;0;ON;;;;;Y;COLON EQUAL;;;;
-2255;EQUALS COLON;Sm;0;ON;;;;;Y;EQUAL COLON;;;;
-2256;RING IN EQUAL TO;Sm;0;ON;;;;;N;;;;;
-2257;RING EQUAL TO;Sm;0;ON;;;;;N;;;;;
-2258;CORRESPONDS TO;Sm;0;ON;;;;;N;;;;;
-2259;ESTIMATES;Sm;0;ON;;;;;N;;;;;
-225A;EQUIANGULAR TO;Sm;0;ON;;;;;N;;;;;
-225B;STAR EQUALS;Sm;0;ON;;;;;N;;;;;
-225C;DELTA EQUAL TO;Sm;0;ON;;;;;N;;;;;
-225D;EQUAL TO BY DEFINITION;Sm;0;ON;;;;;N;;;;;
-225E;MEASURED BY;Sm;0;ON;;;;;N;;;;;
-225F;QUESTIONED EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2260;NOT EQUAL TO;Sm;0;ON;003D 0338;;;;Y;;;;;
-2261;IDENTICAL TO;Sm;0;ON;;;;;N;;;;;
-2262;NOT IDENTICAL TO;Sm;0;ON;2261 0338;;;;Y;;;;;
-2263;STRICTLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;;
-2264;LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUAL TO;;;;
-2265;GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUAL TO;;;;
-2266;LESS-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OVER EQUAL TO;;;;
-2267;GREATER-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OVER EQUAL TO;;;;
-2268;LESS-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUAL TO;;;;
-2269;GREATER-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUAL TO;;;;
-226A;MUCH LESS-THAN;Sm;0;ON;;;;;Y;MUCH LESS THAN;;;;
-226B;MUCH GREATER-THAN;Sm;0;ON;;;;;Y;MUCH GREATER THAN;;;;
-226C;BETWEEN;Sm;0;ON;;;;;N;;;;;
-226D;NOT EQUIVALENT TO;Sm;0;ON;224D 0338;;;;N;;;;;
-226E;NOT LESS-THAN;Sm;0;ON;003C 0338;;;;Y;NOT LESS THAN;;;;
-226F;NOT GREATER-THAN;Sm;0;ON;003E 0338;;;;Y;NOT GREATER THAN;;;;
-2270;NEITHER LESS-THAN NOR EQUAL TO;Sm;0;ON;2264 0338;;;;Y;NEITHER LESS THAN NOR EQUAL TO;;;;
-2271;NEITHER GREATER-THAN NOR EQUAL TO;Sm;0;ON;2265 0338;;;;Y;NEITHER GREATER THAN NOR EQUAL TO;;;;
-2272;LESS-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUIVALENT TO;;;;
-2273;GREATER-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUIVALENT TO;;;;
-2274;NEITHER LESS-THAN NOR EQUIVALENT TO;Sm;0;ON;2272 0338;;;;Y;NEITHER LESS THAN NOR EQUIVALENT TO;;;;
-2275;NEITHER GREATER-THAN NOR EQUIVALENT TO;Sm;0;ON;2273 0338;;;;Y;NEITHER GREATER THAN NOR EQUIVALENT TO;;;;
-2276;LESS-THAN OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN OR GREATER THAN;;;;
-2277;GREATER-THAN OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN OR LESS THAN;;;;
-2278;NEITHER LESS-THAN NOR GREATER-THAN;Sm;0;ON;2276 0338;;;;Y;NEITHER LESS THAN NOR GREATER THAN;;;;
-2279;NEITHER GREATER-THAN NOR LESS-THAN;Sm;0;ON;2277 0338;;;;Y;NEITHER GREATER THAN NOR LESS THAN;;;;
-227A;PRECEDES;Sm;0;ON;;;;;Y;;;;;
-227B;SUCCEEDS;Sm;0;ON;;;;;Y;;;;;
-227C;PRECEDES OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-227D;SUCCEEDS OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-227E;PRECEDES OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;;
-227F;SUCCEEDS OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;;
-2280;DOES NOT PRECEDE;Sm;0;ON;227A 0338;;;;Y;;;;;
-2281;DOES NOT SUCCEED;Sm;0;ON;227B 0338;;;;Y;;;;;
-2282;SUBSET OF;Sm;0;ON;;;;;Y;;;;;
-2283;SUPERSET OF;Sm;0;ON;;;;;Y;;;;;
-2284;NOT A SUBSET OF;Sm;0;ON;2282 0338;;;;Y;;;;;
-2285;NOT A SUPERSET OF;Sm;0;ON;2283 0338;;;;Y;;;;;
-2286;SUBSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2287;SUPERSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2288;NEITHER A SUBSET OF NOR EQUAL TO;Sm;0;ON;2286 0338;;;;Y;;;;;
-2289;NEITHER A SUPERSET OF NOR EQUAL TO;Sm;0;ON;2287 0338;;;;Y;;;;;
-228A;SUBSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUBSET OF OR NOT EQUAL TO;;;;
-228B;SUPERSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUPERSET OF OR NOT EQUAL TO;;;;
-228C;MULTISET;Sm;0;ON;;;;;Y;;;;;
-228D;MULTISET MULTIPLICATION;Sm;0;ON;;;;;N;;;;;
-228E;MULTISET UNION;Sm;0;ON;;;;;N;;;;;
-228F;SQUARE IMAGE OF;Sm;0;ON;;;;;Y;;;;;
-2290;SQUARE ORIGINAL OF;Sm;0;ON;;;;;Y;;;;;
-2291;SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2292;SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2293;SQUARE CAP;Sm;0;ON;;;;;N;;;;;
-2294;SQUARE CUP;Sm;0;ON;;;;;N;;;;;
-2295;CIRCLED PLUS;Sm;0;ON;;;;;N;;;;;
-2296;CIRCLED MINUS;Sm;0;ON;;;;;N;;;;;
-2297;CIRCLED TIMES;Sm;0;ON;;;;;N;;;;;
-2298;CIRCLED DIVISION SLASH;Sm;0;ON;;;;;Y;;;;;
-2299;CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;;
-229A;CIRCLED RING OPERATOR;Sm;0;ON;;;;;N;;;;;
-229B;CIRCLED ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;;
-229C;CIRCLED EQUALS;Sm;0;ON;;;;;N;;;;;
-229D;CIRCLED DASH;Sm;0;ON;;;;;N;;;;;
-229E;SQUARED PLUS;Sm;0;ON;;;;;N;;;;;
-229F;SQUARED MINUS;Sm;0;ON;;;;;N;;;;;
-22A0;SQUARED TIMES;Sm;0;ON;;;;;N;;;;;
-22A1;SQUARED DOT OPERATOR;Sm;0;ON;;;;;N;;;;;
-22A2;RIGHT TACK;Sm;0;ON;;;;;Y;;;;;
-22A3;LEFT TACK;Sm;0;ON;;;;;Y;;;;;
-22A4;DOWN TACK;Sm;0;ON;;;;;N;;;;;
-22A5;UP TACK;Sm;0;ON;;;;;N;;;;;
-22A6;ASSERTION;Sm;0;ON;;;;;Y;;;;;
-22A7;MODELS;Sm;0;ON;;;;;Y;;;;;
-22A8;TRUE;Sm;0;ON;;;;;Y;;;;;
-22A9;FORCES;Sm;0;ON;;;;;Y;;;;;
-22AA;TRIPLE VERTICAL BAR RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
-22AB;DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
-22AC;DOES NOT PROVE;Sm;0;ON;22A2 0338;;;;Y;;;;;
-22AD;NOT TRUE;Sm;0;ON;22A8 0338;;;;Y;;;;;
-22AE;DOES NOT FORCE;Sm;0;ON;22A9 0338;;;;Y;;;;;
-22AF;NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;22AB 0338;;;;Y;;;;;
-22B0;PRECEDES UNDER RELATION;Sm;0;ON;;;;;Y;;;;;
-22B1;SUCCEEDS UNDER RELATION;Sm;0;ON;;;;;Y;;;;;
-22B2;NORMAL SUBGROUP OF;Sm;0;ON;;;;;Y;;;;;
-22B3;CONTAINS AS NORMAL SUBGROUP;Sm;0;ON;;;;;Y;;;;;
-22B4;NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-22B5;CONTAINS AS NORMAL SUBGROUP OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-22B6;ORIGINAL OF;Sm;0;ON;;;;;Y;;;;;
-22B7;IMAGE OF;Sm;0;ON;;;;;Y;;;;;
-22B8;MULTIMAP;Sm;0;ON;;;;;Y;;;;;
-22B9;HERMITIAN CONJUGATE MATRIX;Sm;0;ON;;;;;N;;;;;
-22BA;INTERCALATE;Sm;0;ON;;;;;N;;;;;
-22BB;XOR;Sm;0;ON;;;;;N;;;;;
-22BC;NAND;Sm;0;ON;;;;;N;;;;;
-22BD;NOR;Sm;0;ON;;;;;N;;;;;
-22BE;RIGHT ANGLE WITH ARC;Sm;0;ON;;;;;Y;;;;;
-22BF;RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;;
-22C0;N-ARY LOGICAL AND;Sm;0;ON;;;;;N;;;;;
-22C1;N-ARY LOGICAL OR;Sm;0;ON;;;;;N;;;;;
-22C2;N-ARY INTERSECTION;Sm;0;ON;;;;;N;;;;;
-22C3;N-ARY UNION;Sm;0;ON;;;;;N;;;;;
-22C4;DIAMOND OPERATOR;Sm;0;ON;;;;;N;;;;;
-22C5;DOT OPERATOR;Sm;0;ON;;;;;N;;;;;
-22C6;STAR OPERATOR;Sm;0;ON;;;;;N;;;;;
-22C7;DIVISION TIMES;Sm;0;ON;;;;;N;;;;;
-22C8;BOWTIE;Sm;0;ON;;;;;N;;;;;
-22C9;LEFT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;;
-22CA;RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;;
-22CB;LEFT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;;
-22CC;RIGHT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;;
-22CD;REVERSED TILDE EQUALS;Sm;0;ON;;;;;Y;;;;;
-22CE;CURLY LOGICAL OR;Sm;0;ON;;;;;N;;;;;
-22CF;CURLY LOGICAL AND;Sm;0;ON;;;;;N;;;;;
-22D0;DOUBLE SUBSET;Sm;0;ON;;;;;Y;;;;;
-22D1;DOUBLE SUPERSET;Sm;0;ON;;;;;Y;;;;;
-22D2;DOUBLE INTERSECTION;Sm;0;ON;;;;;N;;;;;
-22D3;DOUBLE UNION;Sm;0;ON;;;;;N;;;;;
-22D4;PITCHFORK;Sm;0;ON;;;;;N;;;;;
-22D5;EQUAL AND PARALLEL TO;Sm;0;ON;;;;;N;;;;;
-22D6;LESS-THAN WITH DOT;Sm;0;ON;;;;;Y;LESS THAN WITH DOT;;;;
-22D7;GREATER-THAN WITH DOT;Sm;0;ON;;;;;Y;GREATER THAN WITH DOT;;;;
-22D8;VERY MUCH LESS-THAN;Sm;0;ON;;;;;Y;VERY MUCH LESS THAN;;;;
-22D9;VERY MUCH GREATER-THAN;Sm;0;ON;;;;;Y;VERY MUCH GREATER THAN;;;;
-22DA;LESS-THAN EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN EQUAL TO OR GREATER THAN;;;;
-22DB;GREATER-THAN EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN EQUAL TO OR LESS THAN;;;;
-22DC;EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR LESS THAN;;;;
-22DD;EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR GREATER THAN;;;;
-22DE;EQUAL TO OR PRECEDES;Sm;0;ON;;;;;Y;;;;;
-22DF;EQUAL TO OR SUCCEEDS;Sm;0;ON;;;;;Y;;;;;
-22E0;DOES NOT PRECEDE OR EQUAL;Sm;0;ON;227C 0338;;;;Y;;;;;
-22E1;DOES NOT SUCCEED OR EQUAL;Sm;0;ON;227D 0338;;;;Y;;;;;
-22E2;NOT SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;2291 0338;;;;Y;;;;;
-22E3;NOT SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;2292 0338;;;;Y;;;;;
-22E4;SQUARE IMAGE OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-22E5;SQUARE ORIGINAL OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-22E6;LESS-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUIVALENT TO;;;;
-22E7;GREATER-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUIVALENT TO;;;;
-22E8;PRECEDES BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;;
-22E9;SUCCEEDS BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;;
-22EA;NOT NORMAL SUBGROUP OF;Sm;0;ON;22B2 0338;;;;Y;;;;;
-22EB;DOES NOT CONTAIN AS NORMAL SUBGROUP;Sm;0;ON;22B3 0338;;;;Y;;;;;
-22EC;NOT NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;22B4 0338;;;;Y;;;;;
-22ED;DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL;Sm;0;ON;22B5 0338;;;;Y;;;;;
-22EE;VERTICAL ELLIPSIS;Sm;0;ON;;;;;N;;;;;
-22EF;MIDLINE HORIZONTAL ELLIPSIS;Sm;0;ON;;;;;N;;;;;
-22F0;UP RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;;
-22F1;DOWN RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;;
-22F2;ELEMENT OF WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
-22F3;ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
-22F4;SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
-22F5;ELEMENT OF WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
-22F6;ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
-22F7;SMALL ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
-22F8;ELEMENT OF WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
-22F9;ELEMENT OF WITH TWO HORIZONTAL STROKES;Sm;0;ON;;;;;Y;;;;;
-22FA;CONTAINS WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
-22FB;CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
-22FC;SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
-22FD;CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
-22FE;SMALL CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
-22FF;Z NOTATION BAG MEMBERSHIP;Sm;0;ON;;;;;Y;;;;;
-2300;DIAMETER SIGN;So;0;ON;;;;;N;;;;;
-2301;ELECTRIC ARROW;So;0;ON;;;;;N;;;;;
-2302;HOUSE;So;0;ON;;;;;N;;;;;
-2303;UP ARROWHEAD;So;0;ON;;;;;N;;;;;
-2304;DOWN ARROWHEAD;So;0;ON;;;;;N;;;;;
-2305;PROJECTIVE;So;0;ON;;;;;N;;;;;
-2306;PERSPECTIVE;So;0;ON;;;;;N;;;;;
-2307;WAVY LINE;So;0;ON;;;;;N;;;;;
-2308;LEFT CEILING;Sm;0;ON;;;;;Y;;;;;
-2309;RIGHT CEILING;Sm;0;ON;;;;;Y;;;;;
-230A;LEFT FLOOR;Sm;0;ON;;;;;Y;;;;;
-230B;RIGHT FLOOR;Sm;0;ON;;;;;Y;;;;;
-230C;BOTTOM RIGHT CROP;So;0;ON;;;;;N;;;;;
-230D;BOTTOM LEFT CROP;So;0;ON;;;;;N;;;;;
-230E;TOP RIGHT CROP;So;0;ON;;;;;N;;;;;
-230F;TOP LEFT CROP;So;0;ON;;;;;N;;;;;
-2310;REVERSED NOT SIGN;So;0;ON;;;;;N;;;;;
-2311;SQUARE LOZENGE;So;0;ON;;;;;N;;;;;
-2312;ARC;So;0;ON;;;;;N;;;;;
-2313;SEGMENT;So;0;ON;;;;;N;;;;;
-2314;SECTOR;So;0;ON;;;;;N;;;;;
-2315;TELEPHONE RECORDER;So;0;ON;;;;;N;;;;;
-2316;POSITION INDICATOR;So;0;ON;;;;;N;;;;;
-2317;VIEWDATA SQUARE;So;0;ON;;;;;N;;;;;
-2318;PLACE OF INTEREST SIGN;So;0;ON;;;;;N;COMMAND KEY;;;;
-2319;TURNED NOT SIGN;So;0;ON;;;;;N;;;;;
-231A;WATCH;So;0;ON;;;;;N;;;;;
-231B;HOURGLASS;So;0;ON;;;;;N;;;;;
-231C;TOP LEFT CORNER;So;0;ON;;;;;N;;;;;
-231D;TOP RIGHT CORNER;So;0;ON;;;;;N;;;;;
-231E;BOTTOM LEFT CORNER;So;0;ON;;;;;N;;;;;
-231F;BOTTOM RIGHT CORNER;So;0;ON;;;;;N;;;;;
-2320;TOP HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-2321;BOTTOM HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-2322;FROWN;So;0;ON;;;;;N;;;;;
-2323;SMILE;So;0;ON;;;;;N;;;;;
-2324;UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS;So;0;ON;;;;;N;ENTER KEY;;;;
-2325;OPTION KEY;So;0;ON;;;;;N;;;;;
-2326;ERASE TO THE RIGHT;So;0;ON;;;;;N;DELETE TO THE RIGHT KEY;;;;
-2327;X IN A RECTANGLE BOX;So;0;ON;;;;;N;CLEAR KEY;;;;
-2328;KEYBOARD;So;0;ON;;;;;N;;;;;
-2329;LEFT-POINTING ANGLE BRACKET;Ps;0;ON;3008;;;;Y;BRA;;;;
-232A;RIGHT-POINTING ANGLE BRACKET;Pe;0;ON;3009;;;;Y;KET;;;;
-232B;ERASE TO THE LEFT;So;0;ON;;;;;N;DELETE TO THE LEFT KEY;;;;
-232C;BENZENE RING;So;0;ON;;;;;N;;;;;
-232D;CYLINDRICITY;So;0;ON;;;;;N;;;;;
-232E;ALL AROUND-PROFILE;So;0;ON;;;;;N;;;;;
-232F;SYMMETRY;So;0;ON;;;;;N;;;;;
-2330;TOTAL RUNOUT;So;0;ON;;;;;N;;;;;
-2331;DIMENSION ORIGIN;So;0;ON;;;;;N;;;;;
-2332;CONICAL TAPER;So;0;ON;;;;;N;;;;;
-2333;SLOPE;So;0;ON;;;;;N;;;;;
-2334;COUNTERBORE;So;0;ON;;;;;N;;;;;
-2335;COUNTERSINK;So;0;ON;;;;;N;;;;;
-2336;APL FUNCTIONAL SYMBOL I-BEAM;So;0;L;;;;;N;;;;;
-2337;APL FUNCTIONAL SYMBOL SQUISH QUAD;So;0;L;;;;;N;;;;;
-2338;APL FUNCTIONAL SYMBOL QUAD EQUAL;So;0;L;;;;;N;;;;;
-2339;APL FUNCTIONAL SYMBOL QUAD DIVIDE;So;0;L;;;;;N;;;;;
-233A;APL FUNCTIONAL SYMBOL QUAD DIAMOND;So;0;L;;;;;N;;;;;
-233B;APL FUNCTIONAL SYMBOL QUAD JOT;So;0;L;;;;;N;;;;;
-233C;APL FUNCTIONAL SYMBOL QUAD CIRCLE;So;0;L;;;;;N;;;;;
-233D;APL FUNCTIONAL SYMBOL CIRCLE STILE;So;0;L;;;;;N;;;;;
-233E;APL FUNCTIONAL SYMBOL CIRCLE JOT;So;0;L;;;;;N;;;;;
-233F;APL FUNCTIONAL SYMBOL SLASH BAR;So;0;L;;;;;N;;;;;
-2340;APL FUNCTIONAL SYMBOL BACKSLASH BAR;So;0;L;;;;;N;;;;;
-2341;APL FUNCTIONAL SYMBOL QUAD SLASH;So;0;L;;;;;N;;;;;
-2342;APL FUNCTIONAL SYMBOL QUAD BACKSLASH;So;0;L;;;;;N;;;;;
-2343;APL FUNCTIONAL SYMBOL QUAD LESS-THAN;So;0;L;;;;;N;;;;;
-2344;APL FUNCTIONAL SYMBOL QUAD GREATER-THAN;So;0;L;;;;;N;;;;;
-2345;APL FUNCTIONAL SYMBOL LEFTWARDS VANE;So;0;L;;;;;N;;;;;
-2346;APL FUNCTIONAL SYMBOL RIGHTWARDS VANE;So;0;L;;;;;N;;;;;
-2347;APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW;So;0;L;;;;;N;;;;;
-2348;APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW;So;0;L;;;;;N;;;;;
-2349;APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH;So;0;L;;;;;N;;;;;
-234A;APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR;So;0;L;;;;;N;;;;;
-234B;APL FUNCTIONAL SYMBOL DELTA STILE;So;0;L;;;;;N;;;;;
-234C;APL FUNCTIONAL SYMBOL QUAD DOWN CARET;So;0;L;;;;;N;;;;;
-234D;APL FUNCTIONAL SYMBOL QUAD DELTA;So;0;L;;;;;N;;;;;
-234E;APL FUNCTIONAL SYMBOL DOWN TACK JOT;So;0;L;;;;;N;;;;;
-234F;APL FUNCTIONAL SYMBOL UPWARDS VANE;So;0;L;;;;;N;;;;;
-2350;APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW;So;0;L;;;;;N;;;;;
-2351;APL FUNCTIONAL SYMBOL UP TACK OVERBAR;So;0;L;;;;;N;;;;;
-2352;APL FUNCTIONAL SYMBOL DEL STILE;So;0;L;;;;;N;;;;;
-2353;APL FUNCTIONAL SYMBOL QUAD UP CARET;So;0;L;;;;;N;;;;;
-2354;APL FUNCTIONAL SYMBOL QUAD DEL;So;0;L;;;;;N;;;;;
-2355;APL FUNCTIONAL SYMBOL UP TACK JOT;So;0;L;;;;;N;;;;;
-2356;APL FUNCTIONAL SYMBOL DOWNWARDS VANE;So;0;L;;;;;N;;;;;
-2357;APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW;So;0;L;;;;;N;;;;;
-2358;APL FUNCTIONAL SYMBOL QUOTE UNDERBAR;So;0;L;;;;;N;;;;;
-2359;APL FUNCTIONAL SYMBOL DELTA UNDERBAR;So;0;L;;;;;N;;;;;
-235A;APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR;So;0;L;;;;;N;;;;;
-235B;APL FUNCTIONAL SYMBOL JOT UNDERBAR;So;0;L;;;;;N;;;;;
-235C;APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR;So;0;L;;;;;N;;;;;
-235D;APL FUNCTIONAL SYMBOL UP SHOE JOT;So;0;L;;;;;N;;;;;
-235E;APL FUNCTIONAL SYMBOL QUOTE QUAD;So;0;L;;;;;N;;;;;
-235F;APL FUNCTIONAL SYMBOL CIRCLE STAR;So;0;L;;;;;N;;;;;
-2360;APL FUNCTIONAL SYMBOL QUAD COLON;So;0;L;;;;;N;;;;;
-2361;APL FUNCTIONAL SYMBOL UP TACK DIAERESIS;So;0;L;;;;;N;;;;;
-2362;APL FUNCTIONAL SYMBOL DEL DIAERESIS;So;0;L;;;;;N;;;;;
-2363;APL FUNCTIONAL SYMBOL STAR DIAERESIS;So;0;L;;;;;N;;;;;
-2364;APL FUNCTIONAL SYMBOL JOT DIAERESIS;So;0;L;;;;;N;;;;;
-2365;APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS;So;0;L;;;;;N;;;;;
-2366;APL FUNCTIONAL SYMBOL DOWN SHOE STILE;So;0;L;;;;;N;;;;;
-2367;APL FUNCTIONAL SYMBOL LEFT SHOE STILE;So;0;L;;;;;N;;;;;
-2368;APL FUNCTIONAL SYMBOL TILDE DIAERESIS;So;0;L;;;;;N;;;;;
-2369;APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS;So;0;L;;;;;N;;;;;
-236A;APL FUNCTIONAL SYMBOL COMMA BAR;So;0;L;;;;;N;;;;;
-236B;APL FUNCTIONAL SYMBOL DEL TILDE;So;0;L;;;;;N;;;;;
-236C;APL FUNCTIONAL SYMBOL ZILDE;So;0;L;;;;;N;;;;;
-236D;APL FUNCTIONAL SYMBOL STILE TILDE;So;0;L;;;;;N;;;;;
-236E;APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR;So;0;L;;;;;N;;;;;
-236F;APL FUNCTIONAL SYMBOL QUAD NOT EQUAL;So;0;L;;;;;N;;;;;
-2370;APL FUNCTIONAL SYMBOL QUAD QUESTION;So;0;L;;;;;N;;;;;
-2371;APL FUNCTIONAL SYMBOL DOWN CARET TILDE;So;0;L;;;;;N;;;;;
-2372;APL FUNCTIONAL SYMBOL UP CARET TILDE;So;0;L;;;;;N;;;;;
-2373;APL FUNCTIONAL SYMBOL IOTA;So;0;L;;;;;N;;;;;
-2374;APL FUNCTIONAL SYMBOL RHO;So;0;L;;;;;N;;;;;
-2375;APL FUNCTIONAL SYMBOL OMEGA;So;0;L;;;;;N;;;;;
-2376;APL FUNCTIONAL SYMBOL ALPHA UNDERBAR;So;0;L;;;;;N;;;;;
-2377;APL FUNCTIONAL SYMBOL EPSILON UNDERBAR;So;0;L;;;;;N;;;;;
-2378;APL FUNCTIONAL SYMBOL IOTA UNDERBAR;So;0;L;;;;;N;;;;;
-2379;APL FUNCTIONAL SYMBOL OMEGA UNDERBAR;So;0;L;;;;;N;;;;;
-237A;APL FUNCTIONAL SYMBOL ALPHA;So;0;L;;;;;N;;;;;
-237B;NOT CHECK MARK;So;0;ON;;;;;N;;;;;
-237C;RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW;Sm;0;ON;;;;;N;;;;;
-237D;SHOULDERED OPEN BOX;So;0;ON;;;;;N;;;;;
-237E;BELL SYMBOL;So;0;ON;;;;;N;;;;;
-237F;VERTICAL LINE WITH MIDDLE DOT;So;0;ON;;;;;N;;;;;
-2380;INSERTION SYMBOL;So;0;ON;;;;;N;;;;;
-2381;CONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;;
-2382;DISCONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;;
-2383;EMPHASIS SYMBOL;So;0;ON;;;;;N;;;;;
-2384;COMPOSITION SYMBOL;So;0;ON;;;;;N;;;;;
-2385;WHITE SQUARE WITH CENTRE VERTICAL LINE;So;0;ON;;;;;N;;;;;
-2386;ENTER SYMBOL;So;0;ON;;;;;N;;;;;
-2387;ALTERNATIVE KEY SYMBOL;So;0;ON;;;;;N;;;;;
-2388;HELM SYMBOL;So;0;ON;;;;;N;;;;;
-2389;CIRCLED HORIZONTAL BAR WITH NOTCH;So;0;ON;;;;;N;;;;;
-238A;CIRCLED TRIANGLE DOWN;So;0;ON;;;;;N;;;;;
-238B;BROKEN CIRCLE WITH NORTHWEST ARROW;So;0;ON;;;;;N;;;;;
-238C;UNDO SYMBOL;So;0;ON;;;;;N;;;;;
-238D;MONOSTABLE SYMBOL;So;0;ON;;;;;N;;;;;
-238E;HYSTERESIS SYMBOL;So;0;ON;;;;;N;;;;;
-238F;OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL;So;0;ON;;;;;N;;;;;
-2390;OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL;So;0;ON;;;;;N;;;;;
-2391;PASSIVE-PULL-DOWN-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;;
-2392;PASSIVE-PULL-UP-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;;
-2393;DIRECT CURRENT SYMBOL FORM TWO;So;0;ON;;;;;N;;;;;
-2394;SOFTWARE-FUNCTION SYMBOL;So;0;ON;;;;;N;;;;;
-2395;APL FUNCTIONAL SYMBOL QUAD;So;0;L;;;;;N;;;;;
-2396;DECIMAL SEPARATOR KEY SYMBOL;So;0;ON;;;;;N;;;;;
-2397;PREVIOUS PAGE;So;0;ON;;;;;N;;;;;
-2398;NEXT PAGE;So;0;ON;;;;;N;;;;;
-2399;PRINT SCREEN SYMBOL;So;0;ON;;;;;N;;;;;
-239A;CLEAR SCREEN SYMBOL;So;0;ON;;;;;N;;;;;
-239B;LEFT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;;
-239C;LEFT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;;
-239D;LEFT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;;
-239E;RIGHT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;;
-239F;RIGHT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;;
-23A0;RIGHT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;;
-23A1;LEFT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;;
-23A2;LEFT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;;
-23A3;LEFT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;;
-23A4;RIGHT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;;
-23A5;RIGHT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;;
-23A6;RIGHT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;;
-23A7;LEFT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;;
-23A8;LEFT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;;
-23A9;LEFT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;;
-23AA;CURLY BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;;
-23AB;RIGHT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;;
-23AC;RIGHT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;;
-23AD;RIGHT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;;
-23AE;INTEGRAL EXTENSION;Sm;0;ON;;;;;N;;;;;
-23AF;HORIZONTAL LINE EXTENSION;Sm;0;ON;;;;;N;;;;;
-23B0;UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;;
-23B1;UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;;
-23B2;SUMMATION TOP;Sm;0;ON;;;;;N;;;;;
-23B3;SUMMATION BOTTOM;Sm;0;ON;;;;;N;;;;;
-23B4;TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;;
-23B5;BOTTOM SQUARE BRACKET;So;0;ON;;;;;N;;;;;
-23B6;BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;;
-23B7;RADICAL SYMBOL BOTTOM;So;0;ON;;;;;N;;;;;
-23B8;LEFT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;;
-23B9;RIGHT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;;
-23BA;HORIZONTAL SCAN LINE-1;So;0;ON;;;;;N;;;;;
-23BB;HORIZONTAL SCAN LINE-3;So;0;ON;;;;;N;;;;;
-23BC;HORIZONTAL SCAN LINE-7;So;0;ON;;;;;N;;;;;
-23BD;HORIZONTAL SCAN LINE-9;So;0;ON;;;;;N;;;;;
-23BE;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;;
-23BF;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;;
-23C0;DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE;So;0;ON;;;;;N;;;;;
-23C1;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;;
-23C2;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;;
-23C3;DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE;So;0;ON;;;;;N;;;;;
-23C4;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;;
-23C5;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;;
-23C6;DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE;So;0;ON;;;;;N;;;;;
-23C7;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;;
-23C8;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;;
-23C9;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;;;;;
-23CA;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;;;;;
-23CB;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;;
-23CC;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;;
-23CD;SQUARE FOOT;So;0;ON;;;;;N;;;;;
-23CE;RETURN SYMBOL;So;0;ON;;;;;N;;;;;
-23CF;EJECT SYMBOL;So;0;ON;;;;;N;;;;;
-23D0;VERTICAL LINE EXTENSION;So;0;ON;;;;;N;;;;;
-23D1;METRICAL BREVE;So;0;ON;;;;;N;;;;;
-23D2;METRICAL LONG OVER SHORT;So;0;ON;;;;;N;;;;;
-23D3;METRICAL SHORT OVER LONG;So;0;ON;;;;;N;;;;;
-23D4;METRICAL LONG OVER TWO SHORTS;So;0;ON;;;;;N;;;;;
-23D5;METRICAL TWO SHORTS OVER LONG;So;0;ON;;;;;N;;;;;
-23D6;METRICAL TWO SHORTS JOINED;So;0;ON;;;;;N;;;;;
-23D7;METRICAL TRISEME;So;0;ON;;;;;N;;;;;
-23D8;METRICAL TETRASEME;So;0;ON;;;;;N;;;;;
-23D9;METRICAL PENTASEME;So;0;ON;;;;;N;;;;;
-23DA;EARTH GROUND;So;0;ON;;;;;N;;;;;
-23DB;FUSE;So;0;ON;;;;;N;;;;;
-23DC;TOP PARENTHESIS;Sm;0;ON;;;;;N;;;;;
-23DD;BOTTOM PARENTHESIS;Sm;0;ON;;;;;N;;;;;
-23DE;TOP CURLY BRACKET;Sm;0;ON;;;;;N;;;;;
-23DF;BOTTOM CURLY BRACKET;Sm;0;ON;;;;;N;;;;;
-23E0;TOP TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;;
-23E1;BOTTOM TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;;
-23E2;WHITE TRAPEZIUM;So;0;ON;;;;;N;;;;;
-23E3;BENZENE RING WITH CIRCLE;So;0;ON;;;;;N;;;;;
-23E4;STRAIGHTNESS;So;0;ON;;;;;N;;;;;
-23E5;FLATNESS;So;0;ON;;;;;N;;;;;
-23E6;AC CURRENT;So;0;ON;;;;;N;;;;;
-23E7;ELECTRICAL INTERSECTION;So;0;ON;;;;;N;;;;;
-23E8;DECIMAL EXPONENT SYMBOL;So;0;ON;;;;;N;;;;;
-23E9;BLACK RIGHT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;;
-23EA;BLACK LEFT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;;
-23EB;BLACK UP-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;;
-23EC;BLACK DOWN-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;;
-23ED;BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;;
-23EE;BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;;
-23EF;BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;;
-23F0;ALARM CLOCK;So;0;ON;;;;;N;;;;;
-23F1;STOPWATCH;So;0;ON;;;;;N;;;;;
-23F2;TIMER CLOCK;So;0;ON;;;;;N;;;;;
-23F3;HOURGLASS WITH FLOWING SAND;So;0;ON;;;;;N;;;;;
-2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;;
-2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;;
-2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;;
-2403;SYMBOL FOR END OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR END OF TEXT;;;;
-2404;SYMBOL FOR END OF TRANSMISSION;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION;;;;
-2405;SYMBOL FOR ENQUIRY;So;0;ON;;;;;N;GRAPHIC FOR ENQUIRY;;;;
-2406;SYMBOL FOR ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR ACKNOWLEDGE;;;;
-2407;SYMBOL FOR BELL;So;0;ON;;;;;N;GRAPHIC FOR BELL;;;;
-2408;SYMBOL FOR BACKSPACE;So;0;ON;;;;;N;GRAPHIC FOR BACKSPACE;;;;
-2409;SYMBOL FOR HORIZONTAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR HORIZONTAL TABULATION;;;;
-240A;SYMBOL FOR LINE FEED;So;0;ON;;;;;N;GRAPHIC FOR LINE FEED;;;;
-240B;SYMBOL FOR VERTICAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR VERTICAL TABULATION;;;;
-240C;SYMBOL FOR FORM FEED;So;0;ON;;;;;N;GRAPHIC FOR FORM FEED;;;;
-240D;SYMBOL FOR CARRIAGE RETURN;So;0;ON;;;;;N;GRAPHIC FOR CARRIAGE RETURN;;;;
-240E;SYMBOL FOR SHIFT OUT;So;0;ON;;;;;N;GRAPHIC FOR SHIFT OUT;;;;
-240F;SYMBOL FOR SHIFT IN;So;0;ON;;;;;N;GRAPHIC FOR SHIFT IN;;;;
-2410;SYMBOL FOR DATA LINK ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR DATA LINK ESCAPE;;;;
-2411;SYMBOL FOR DEVICE CONTROL ONE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL ONE;;;;
-2412;SYMBOL FOR DEVICE CONTROL TWO;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL TWO;;;;
-2413;SYMBOL FOR DEVICE CONTROL THREE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL THREE;;;;
-2414;SYMBOL FOR DEVICE CONTROL FOUR;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL FOUR;;;;
-2415;SYMBOL FOR NEGATIVE ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR NEGATIVE ACKNOWLEDGE;;;;
-2416;SYMBOL FOR SYNCHRONOUS IDLE;So;0;ON;;;;;N;GRAPHIC FOR SYNCHRONOUS IDLE;;;;
-2417;SYMBOL FOR END OF TRANSMISSION BLOCK;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION BLOCK;;;;
-2418;SYMBOL FOR CANCEL;So;0;ON;;;;;N;GRAPHIC FOR CANCEL;;;;
-2419;SYMBOL FOR END OF MEDIUM;So;0;ON;;;;;N;GRAPHIC FOR END OF MEDIUM;;;;
-241A;SYMBOL FOR SUBSTITUTE;So;0;ON;;;;;N;GRAPHIC FOR SUBSTITUTE;;;;
-241B;SYMBOL FOR ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR ESCAPE;;;;
-241C;SYMBOL FOR FILE SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR FILE SEPARATOR;;;;
-241D;SYMBOL FOR GROUP SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR GROUP SEPARATOR;;;;
-241E;SYMBOL FOR RECORD SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR RECORD SEPARATOR;;;;
-241F;SYMBOL FOR UNIT SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR UNIT SEPARATOR;;;;
-2420;SYMBOL FOR SPACE;So;0;ON;;;;;N;GRAPHIC FOR SPACE;;;;
-2421;SYMBOL FOR DELETE;So;0;ON;;;;;N;GRAPHIC FOR DELETE;;;;
-2422;BLANK SYMBOL;So;0;ON;;;;;N;BLANK;;;;
-2423;OPEN BOX;So;0;ON;;;;;N;;;;;
-2424;SYMBOL FOR NEWLINE;So;0;ON;;;;;N;GRAPHIC FOR NEWLINE;;;;
-2425;SYMBOL FOR DELETE FORM TWO;So;0;ON;;;;;N;;;;;
-2426;SYMBOL FOR SUBSTITUTE FORM TWO;So;0;ON;;;;;N;;;;;
-2440;OCR HOOK;So;0;ON;;;;;N;;;;;
-2441;OCR CHAIR;So;0;ON;;;;;N;;;;;
-2442;OCR FORK;So;0;ON;;;;;N;;;;;
-2443;OCR INVERTED FORK;So;0;ON;;;;;N;;;;;
-2444;OCR BELT BUCKLE;So;0;ON;;;;;N;;;;;
-2445;OCR BOW TIE;So;0;ON;;;;;N;;;;;
-2446;OCR BRANCH BANK IDENTIFICATION;So;0;ON;;;;;N;;;;;
-2447;OCR AMOUNT OF CHECK;So;0;ON;;;;;N;;;;;
-2448;OCR DASH;So;0;ON;;;;;N;;;;;
-2449;OCR CUSTOMER ACCOUNT NUMBER;So;0;ON;;;;;N;;;;;
-244A;OCR DOUBLE BACKSLASH;So;0;ON;;;;;N;;;;;
-2460;CIRCLED DIGIT ONE;No;0;ON;<circle> 0031;;1;1;N;;;;;
-2461;CIRCLED DIGIT TWO;No;0;ON;<circle> 0032;;2;2;N;;;;;
-2462;CIRCLED DIGIT THREE;No;0;ON;<circle> 0033;;3;3;N;;;;;
-2463;CIRCLED DIGIT FOUR;No;0;ON;<circle> 0034;;4;4;N;;;;;
-2464;CIRCLED DIGIT FIVE;No;0;ON;<circle> 0035;;5;5;N;;;;;
-2465;CIRCLED DIGIT SIX;No;0;ON;<circle> 0036;;6;6;N;;;;;
-2466;CIRCLED DIGIT SEVEN;No;0;ON;<circle> 0037;;7;7;N;;;;;
-2467;CIRCLED DIGIT EIGHT;No;0;ON;<circle> 0038;;8;8;N;;;;;
-2468;CIRCLED DIGIT NINE;No;0;ON;<circle> 0039;;9;9;N;;;;;
-2469;CIRCLED NUMBER TEN;No;0;ON;<circle> 0031 0030;;;10;N;;;;;
-246A;CIRCLED NUMBER ELEVEN;No;0;ON;<circle> 0031 0031;;;11;N;;;;;
-246B;CIRCLED NUMBER TWELVE;No;0;ON;<circle> 0031 0032;;;12;N;;;;;
-246C;CIRCLED NUMBER THIRTEEN;No;0;ON;<circle> 0031 0033;;;13;N;;;;;
-246D;CIRCLED NUMBER FOURTEEN;No;0;ON;<circle> 0031 0034;;;14;N;;;;;
-246E;CIRCLED NUMBER FIFTEEN;No;0;ON;<circle> 0031 0035;;;15;N;;;;;
-246F;CIRCLED NUMBER SIXTEEN;No;0;ON;<circle> 0031 0036;;;16;N;;;;;
-2470;CIRCLED NUMBER SEVENTEEN;No;0;ON;<circle> 0031 0037;;;17;N;;;;;
-2471;CIRCLED NUMBER EIGHTEEN;No;0;ON;<circle> 0031 0038;;;18;N;;;;;
-2472;CIRCLED NUMBER NINETEEN;No;0;ON;<circle> 0031 0039;;;19;N;;;;;
-2473;CIRCLED NUMBER TWENTY;No;0;ON;<circle> 0032 0030;;;20;N;;;;;
-2474;PARENTHESIZED DIGIT ONE;No;0;ON;<compat> 0028 0031 0029;;1;1;N;;;;;
-2475;PARENTHESIZED DIGIT TWO;No;0;ON;<compat> 0028 0032 0029;;2;2;N;;;;;
-2476;PARENTHESIZED DIGIT THREE;No;0;ON;<compat> 0028 0033 0029;;3;3;N;;;;;
-2477;PARENTHESIZED DIGIT FOUR;No;0;ON;<compat> 0028 0034 0029;;4;4;N;;;;;
-2478;PARENTHESIZED DIGIT FIVE;No;0;ON;<compat> 0028 0035 0029;;5;5;N;;;;;
-2479;PARENTHESIZED DIGIT SIX;No;0;ON;<compat> 0028 0036 0029;;6;6;N;;;;;
-247A;PARENTHESIZED DIGIT SEVEN;No;0;ON;<compat> 0028 0037 0029;;7;7;N;;;;;
-247B;PARENTHESIZED DIGIT EIGHT;No;0;ON;<compat> 0028 0038 0029;;8;8;N;;;;;
-247C;PARENTHESIZED DIGIT NINE;No;0;ON;<compat> 0028 0039 0029;;9;9;N;;;;;
-247D;PARENTHESIZED NUMBER TEN;No;0;ON;<compat> 0028 0031 0030 0029;;;10;N;;;;;
-247E;PARENTHESIZED NUMBER ELEVEN;No;0;ON;<compat> 0028 0031 0031 0029;;;11;N;;;;;
-247F;PARENTHESIZED NUMBER TWELVE;No;0;ON;<compat> 0028 0031 0032 0029;;;12;N;;;;;
-2480;PARENTHESIZED NUMBER THIRTEEN;No;0;ON;<compat> 0028 0031 0033 0029;;;13;N;;;;;
-2481;PARENTHESIZED NUMBER FOURTEEN;No;0;ON;<compat> 0028 0031 0034 0029;;;14;N;;;;;
-2482;PARENTHESIZED NUMBER FIFTEEN;No;0;ON;<compat> 0028 0031 0035 0029;;;15;N;;;;;
-2483;PARENTHESIZED NUMBER SIXTEEN;No;0;ON;<compat> 0028 0031 0036 0029;;;16;N;;;;;
-2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;ON;<compat> 0028 0031 0037 0029;;;17;N;;;;;
-2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;ON;<compat> 0028 0031 0038 0029;;;18;N;;;;;
-2486;PARENTHESIZED NUMBER NINETEEN;No;0;ON;<compat> 0028 0031 0039 0029;;;19;N;;;;;
-2487;PARENTHESIZED NUMBER TWENTY;No;0;ON;<compat> 0028 0032 0030 0029;;;20;N;;;;;
-2488;DIGIT ONE FULL STOP;No;0;EN;<compat> 0031 002E;;1;1;N;DIGIT ONE PERIOD;;;;
-2489;DIGIT TWO FULL STOP;No;0;EN;<compat> 0032 002E;;2;2;N;DIGIT TWO PERIOD;;;;
-248A;DIGIT THREE FULL STOP;No;0;EN;<compat> 0033 002E;;3;3;N;DIGIT THREE PERIOD;;;;
-248B;DIGIT FOUR FULL STOP;No;0;EN;<compat> 0034 002E;;4;4;N;DIGIT FOUR PERIOD;;;;
-248C;DIGIT FIVE FULL STOP;No;0;EN;<compat> 0035 002E;;5;5;N;DIGIT FIVE PERIOD;;;;
-248D;DIGIT SIX FULL STOP;No;0;EN;<compat> 0036 002E;;6;6;N;DIGIT SIX PERIOD;;;;
-248E;DIGIT SEVEN FULL STOP;No;0;EN;<compat> 0037 002E;;7;7;N;DIGIT SEVEN PERIOD;;;;
-248F;DIGIT EIGHT FULL STOP;No;0;EN;<compat> 0038 002E;;8;8;N;DIGIT EIGHT PERIOD;;;;
-2490;DIGIT NINE FULL STOP;No;0;EN;<compat> 0039 002E;;9;9;N;DIGIT NINE PERIOD;;;;
-2491;NUMBER TEN FULL STOP;No;0;EN;<compat> 0031 0030 002E;;;10;N;NUMBER TEN PERIOD;;;;
-2492;NUMBER ELEVEN FULL STOP;No;0;EN;<compat> 0031 0031 002E;;;11;N;NUMBER ELEVEN PERIOD;;;;
-2493;NUMBER TWELVE FULL STOP;No;0;EN;<compat> 0031 0032 002E;;;12;N;NUMBER TWELVE PERIOD;;;;
-2494;NUMBER THIRTEEN FULL STOP;No;0;EN;<compat> 0031 0033 002E;;;13;N;NUMBER THIRTEEN PERIOD;;;;
-2495;NUMBER FOURTEEN FULL STOP;No;0;EN;<compat> 0031 0034 002E;;;14;N;NUMBER FOURTEEN PERIOD;;;;
-2496;NUMBER FIFTEEN FULL STOP;No;0;EN;<compat> 0031 0035 002E;;;15;N;NUMBER FIFTEEN PERIOD;;;;
-2497;NUMBER SIXTEEN FULL STOP;No;0;EN;<compat> 0031 0036 002E;;;16;N;NUMBER SIXTEEN PERIOD;;;;
-2498;NUMBER SEVENTEEN FULL STOP;No;0;EN;<compat> 0031 0037 002E;;;17;N;NUMBER SEVENTEEN PERIOD;;;;
-2499;NUMBER EIGHTEEN FULL STOP;No;0;EN;<compat> 0031 0038 002E;;;18;N;NUMBER EIGHTEEN PERIOD;;;;
-249A;NUMBER NINETEEN FULL STOP;No;0;EN;<compat> 0031 0039 002E;;;19;N;NUMBER NINETEEN PERIOD;;;;
-249B;NUMBER TWENTY FULL STOP;No;0;EN;<compat> 0032 0030 002E;;;20;N;NUMBER TWENTY PERIOD;;;;
-249C;PARENTHESIZED LATIN SMALL LETTER A;So;0;L;<compat> 0028 0061 0029;;;;N;;;;;
-249D;PARENTHESIZED LATIN SMALL LETTER B;So;0;L;<compat> 0028 0062 0029;;;;N;;;;;
-249E;PARENTHESIZED LATIN SMALL LETTER C;So;0;L;<compat> 0028 0063 0029;;;;N;;;;;
-249F;PARENTHESIZED LATIN SMALL LETTER D;So;0;L;<compat> 0028 0064 0029;;;;N;;;;;
-24A0;PARENTHESIZED LATIN SMALL LETTER E;So;0;L;<compat> 0028 0065 0029;;;;N;;;;;
-24A1;PARENTHESIZED LATIN SMALL LETTER F;So;0;L;<compat> 0028 0066 0029;;;;N;;;;;
-24A2;PARENTHESIZED LATIN SMALL LETTER G;So;0;L;<compat> 0028 0067 0029;;;;N;;;;;
-24A3;PARENTHESIZED LATIN SMALL LETTER H;So;0;L;<compat> 0028 0068 0029;;;;N;;;;;
-24A4;PARENTHESIZED LATIN SMALL LETTER I;So;0;L;<compat> 0028 0069 0029;;;;N;;;;;
-24A5;PARENTHESIZED LATIN SMALL LETTER J;So;0;L;<compat> 0028 006A 0029;;;;N;;;;;
-24A6;PARENTHESIZED LATIN SMALL LETTER K;So;0;L;<compat> 0028 006B 0029;;;;N;;;;;
-24A7;PARENTHESIZED LATIN SMALL LETTER L;So;0;L;<compat> 0028 006C 0029;;;;N;;;;;
-24A8;PARENTHESIZED LATIN SMALL LETTER M;So;0;L;<compat> 0028 006D 0029;;;;N;;;;;
-24A9;PARENTHESIZED LATIN SMALL LETTER N;So;0;L;<compat> 0028 006E 0029;;;;N;;;;;
-24AA;PARENTHESIZED LATIN SMALL LETTER O;So;0;L;<compat> 0028 006F 0029;;;;N;;;;;
-24AB;PARENTHESIZED LATIN SMALL LETTER P;So;0;L;<compat> 0028 0070 0029;;;;N;;;;;
-24AC;PARENTHESIZED LATIN SMALL LETTER Q;So;0;L;<compat> 0028 0071 0029;;;;N;;;;;
-24AD;PARENTHESIZED LATIN SMALL LETTER R;So;0;L;<compat> 0028 0072 0029;;;;N;;;;;
-24AE;PARENTHESIZED LATIN SMALL LETTER S;So;0;L;<compat> 0028 0073 0029;;;;N;;;;;
-24AF;PARENTHESIZED LATIN SMALL LETTER T;So;0;L;<compat> 0028 0074 0029;;;;N;;;;;
-24B0;PARENTHESIZED LATIN SMALL LETTER U;So;0;L;<compat> 0028 0075 0029;;;;N;;;;;
-24B1;PARENTHESIZED LATIN SMALL LETTER V;So;0;L;<compat> 0028 0076 0029;;;;N;;;;;
-24B2;PARENTHESIZED LATIN SMALL LETTER W;So;0;L;<compat> 0028 0077 0029;;;;N;;;;;
-24B3;PARENTHESIZED LATIN SMALL LETTER X;So;0;L;<compat> 0028 0078 0029;;;;N;;;;;
-24B4;PARENTHESIZED LATIN SMALL LETTER Y;So;0;L;<compat> 0028 0079 0029;;;;N;;;;;
-24B5;PARENTHESIZED LATIN SMALL LETTER Z;So;0;L;<compat> 0028 007A 0029;;;;N;;;;;
-24B6;CIRCLED LATIN CAPITAL LETTER A;So;0;L;<circle> 0041;;;;N;;;;24D0;
-24B7;CIRCLED LATIN CAPITAL LETTER B;So;0;L;<circle> 0042;;;;N;;;;24D1;
-24B8;CIRCLED LATIN CAPITAL LETTER C;So;0;L;<circle> 0043;;;;N;;;;24D2;
-24B9;CIRCLED LATIN CAPITAL LETTER D;So;0;L;<circle> 0044;;;;N;;;;24D3;
-24BA;CIRCLED LATIN CAPITAL LETTER E;So;0;L;<circle> 0045;;;;N;;;;24D4;
-24BB;CIRCLED LATIN CAPITAL LETTER F;So;0;L;<circle> 0046;;;;N;;;;24D5;
-24BC;CIRCLED LATIN CAPITAL LETTER G;So;0;L;<circle> 0047;;;;N;;;;24D6;
-24BD;CIRCLED LATIN CAPITAL LETTER H;So;0;L;<circle> 0048;;;;N;;;;24D7;
-24BE;CIRCLED LATIN CAPITAL LETTER I;So;0;L;<circle> 0049;;;;N;;;;24D8;
-24BF;CIRCLED LATIN CAPITAL LETTER J;So;0;L;<circle> 004A;;;;N;;;;24D9;
-24C0;CIRCLED LATIN CAPITAL LETTER K;So;0;L;<circle> 004B;;;;N;;;;24DA;
-24C1;CIRCLED LATIN CAPITAL LETTER L;So;0;L;<circle> 004C;;;;N;;;;24DB;
-24C2;CIRCLED LATIN CAPITAL LETTER M;So;0;L;<circle> 004D;;;;N;;;;24DC;
-24C3;CIRCLED LATIN CAPITAL LETTER N;So;0;L;<circle> 004E;;;;N;;;;24DD;
-24C4;CIRCLED LATIN CAPITAL LETTER O;So;0;L;<circle> 004F;;;;N;;;;24DE;
-24C5;CIRCLED LATIN CAPITAL LETTER P;So;0;L;<circle> 0050;;;;N;;;;24DF;
-24C6;CIRCLED LATIN CAPITAL LETTER Q;So;0;L;<circle> 0051;;;;N;;;;24E0;
-24C7;CIRCLED LATIN CAPITAL LETTER R;So;0;L;<circle> 0052;;;;N;;;;24E1;
-24C8;CIRCLED LATIN CAPITAL LETTER S;So;0;L;<circle> 0053;;;;N;;;;24E2;
-24C9;CIRCLED LATIN CAPITAL LETTER T;So;0;L;<circle> 0054;;;;N;;;;24E3;
-24CA;CIRCLED LATIN CAPITAL LETTER U;So;0;L;<circle> 0055;;;;N;;;;24E4;
-24CB;CIRCLED LATIN CAPITAL LETTER V;So;0;L;<circle> 0056;;;;N;;;;24E5;
-24CC;CIRCLED LATIN CAPITAL LETTER W;So;0;L;<circle> 0057;;;;N;;;;24E6;
-24CD;CIRCLED LATIN CAPITAL LETTER X;So;0;L;<circle> 0058;;;;N;;;;24E7;
-24CE;CIRCLED LATIN CAPITAL LETTER Y;So;0;L;<circle> 0059;;;;N;;;;24E8;
-24CF;CIRCLED LATIN CAPITAL LETTER Z;So;0;L;<circle> 005A;;;;N;;;;24E9;
-24D0;CIRCLED LATIN SMALL LETTER A;So;0;L;<circle> 0061;;;;N;;;24B6;;24B6
-24D1;CIRCLED LATIN SMALL LETTER B;So;0;L;<circle> 0062;;;;N;;;24B7;;24B7
-24D2;CIRCLED LATIN SMALL LETTER C;So;0;L;<circle> 0063;;;;N;;;24B8;;24B8
-24D3;CIRCLED LATIN SMALL LETTER D;So;0;L;<circle> 0064;;;;N;;;24B9;;24B9
-24D4;CIRCLED LATIN SMALL LETTER E;So;0;L;<circle> 0065;;;;N;;;24BA;;24BA
-24D5;CIRCLED LATIN SMALL LETTER F;So;0;L;<circle> 0066;;;;N;;;24BB;;24BB
-24D6;CIRCLED LATIN SMALL LETTER G;So;0;L;<circle> 0067;;;;N;;;24BC;;24BC
-24D7;CIRCLED LATIN SMALL LETTER H;So;0;L;<circle> 0068;;;;N;;;24BD;;24BD
-24D8;CIRCLED LATIN SMALL LETTER I;So;0;L;<circle> 0069;;;;N;;;24BE;;24BE
-24D9;CIRCLED LATIN SMALL LETTER J;So;0;L;<circle> 006A;;;;N;;;24BF;;24BF
-24DA;CIRCLED LATIN SMALL LETTER K;So;0;L;<circle> 006B;;;;N;;;24C0;;24C0
-24DB;CIRCLED LATIN SMALL LETTER L;So;0;L;<circle> 006C;;;;N;;;24C1;;24C1
-24DC;CIRCLED LATIN SMALL LETTER M;So;0;L;<circle> 006D;;;;N;;;24C2;;24C2
-24DD;CIRCLED LATIN SMALL LETTER N;So;0;L;<circle> 006E;;;;N;;;24C3;;24C3
-24DE;CIRCLED LATIN SMALL LETTER O;So;0;L;<circle> 006F;;;;N;;;24C4;;24C4
-24DF;CIRCLED LATIN SMALL LETTER P;So;0;L;<circle> 0070;;;;N;;;24C5;;24C5
-24E0;CIRCLED LATIN SMALL LETTER Q;So;0;L;<circle> 0071;;;;N;;;24C6;;24C6
-24E1;CIRCLED LATIN SMALL LETTER R;So;0;L;<circle> 0072;;;;N;;;24C7;;24C7
-24E2;CIRCLED LATIN SMALL LETTER S;So;0;L;<circle> 0073;;;;N;;;24C8;;24C8
-24E3;CIRCLED LATIN SMALL LETTER T;So;0;L;<circle> 0074;;;;N;;;24C9;;24C9
-24E4;CIRCLED LATIN SMALL LETTER U;So;0;L;<circle> 0075;;;;N;;;24CA;;24CA
-24E5;CIRCLED LATIN SMALL LETTER V;So;0;L;<circle> 0076;;;;N;;;24CB;;24CB
-24E6;CIRCLED LATIN SMALL LETTER W;So;0;L;<circle> 0077;;;;N;;;24CC;;24CC
-24E7;CIRCLED LATIN SMALL LETTER X;So;0;L;<circle> 0078;;;;N;;;24CD;;24CD
-24E8;CIRCLED LATIN SMALL LETTER Y;So;0;L;<circle> 0079;;;;N;;;24CE;;24CE
-24E9;CIRCLED LATIN SMALL LETTER Z;So;0;L;<circle> 007A;;;;N;;;24CF;;24CF
-24EA;CIRCLED DIGIT ZERO;No;0;ON;<circle> 0030;;0;0;N;;;;;
-24EB;NEGATIVE CIRCLED NUMBER ELEVEN;No;0;ON;;;;11;N;;;;;
-24EC;NEGATIVE CIRCLED NUMBER TWELVE;No;0;ON;;;;12;N;;;;;
-24ED;NEGATIVE CIRCLED NUMBER THIRTEEN;No;0;ON;;;;13;N;;;;;
-24EE;NEGATIVE CIRCLED NUMBER FOURTEEN;No;0;ON;;;;14;N;;;;;
-24EF;NEGATIVE CIRCLED NUMBER FIFTEEN;No;0;ON;;;;15;N;;;;;
-24F0;NEGATIVE CIRCLED NUMBER SIXTEEN;No;0;ON;;;;16;N;;;;;
-24F1;NEGATIVE CIRCLED NUMBER SEVENTEEN;No;0;ON;;;;17;N;;;;;
-24F2;NEGATIVE CIRCLED NUMBER EIGHTEEN;No;0;ON;;;;18;N;;;;;
-24F3;NEGATIVE CIRCLED NUMBER NINETEEN;No;0;ON;;;;19;N;;;;;
-24F4;NEGATIVE CIRCLED NUMBER TWENTY;No;0;ON;;;;20;N;;;;;
-24F5;DOUBLE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;;;;;
-24F6;DOUBLE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;;;;;
-24F7;DOUBLE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;;;;;
-24F8;DOUBLE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;;;;;
-24F9;DOUBLE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;;;;;
-24FA;DOUBLE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;;;;;
-24FB;DOUBLE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;;;;;
-24FC;DOUBLE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;;;;;
-24FD;DOUBLE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;;;;;
-24FE;DOUBLE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;;;;;
-24FF;NEGATIVE CIRCLED DIGIT ZERO;No;0;ON;;;0;0;N;;;;;
-2500;BOX DRAWINGS LIGHT HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT HORIZONTAL;;;;
-2501;BOX DRAWINGS HEAVY HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY HORIZONTAL;;;;
-2502;BOX DRAWINGS LIGHT VERTICAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL;;;;
-2503;BOX DRAWINGS HEAVY VERTICAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL;;;;
-2504;BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH HORIZONTAL;;;;
-2505;BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH HORIZONTAL;;;;
-2506;BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH VERTICAL;;;;
-2507;BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH VERTICAL;;;;
-2508;BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH HORIZONTAL;;;;
-2509;BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH HORIZONTAL;;;;
-250A;BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH VERTICAL;;;;
-250B;BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH VERTICAL;;;;
-250C;BOX DRAWINGS LIGHT DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND RIGHT;;;;
-250D;BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT HEAVY;;;;
-250E;BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT LIGHT;;;;
-250F;BOX DRAWINGS HEAVY DOWN AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND RIGHT;;;;
-2510;BOX DRAWINGS LIGHT DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND LEFT;;;;
-2511;BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT HEAVY;;;;
-2512;BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT LIGHT;;;;
-2513;BOX DRAWINGS HEAVY DOWN AND LEFT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND LEFT;;;;
-2514;BOX DRAWINGS LIGHT UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT UP AND RIGHT;;;;
-2515;BOX DRAWINGS UP LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT HEAVY;;;;
-2516;BOX DRAWINGS UP HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT LIGHT;;;;
-2517;BOX DRAWINGS HEAVY UP AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY UP AND RIGHT;;;;
-2518;BOX DRAWINGS LIGHT UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT UP AND LEFT;;;;
-2519;BOX DRAWINGS UP LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT HEAVY;;;;
-251A;BOX DRAWINGS UP HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT LIGHT;;;;
-251B;BOX DRAWINGS HEAVY UP AND LEFT;So;0;ON;;;;;N;FORMS HEAVY UP AND LEFT;;;;
-251C;BOX DRAWINGS LIGHT VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND RIGHT;;;;
-251D;BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND RIGHT HEAVY;;;;
-251E;BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT DOWN LIGHT;;;;
-251F;BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT UP LIGHT;;;;
-2520;BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND RIGHT LIGHT;;;;
-2521;BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT UP HEAVY;;;;
-2522;BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT DOWN HEAVY;;;;
-2523;BOX DRAWINGS HEAVY VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND RIGHT;;;;
-2524;BOX DRAWINGS LIGHT VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND LEFT;;;;
-2525;BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND LEFT HEAVY;;;;
-2526;BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT DOWN LIGHT;;;;
-2527;BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT UP LIGHT;;;;
-2528;BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND LEFT LIGHT;;;;
-2529;BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT UP HEAVY;;;;
-252A;BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT DOWN HEAVY;;;;
-252B;BOX DRAWINGS HEAVY VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND LEFT;;;;
-252C;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOWN AND HORIZONTAL;;;;
-252D;BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT DOWN LIGHT;;;;
-252E;BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT DOWN LIGHT;;;;
-252F;BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND HORIZONTAL HEAVY;;;;
-2530;BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND HORIZONTAL LIGHT;;;;
-2531;BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT DOWN HEAVY;;;;
-2532;BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT DOWN HEAVY;;;;
-2533;BOX DRAWINGS HEAVY DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOWN AND HORIZONTAL;;;;
-2534;BOX DRAWINGS LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT UP AND HORIZONTAL;;;;
-2535;BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT UP LIGHT;;;;
-2536;BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT UP LIGHT;;;;
-2537;BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND HORIZONTAL HEAVY;;;;
-2538;BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND HORIZONTAL LIGHT;;;;
-2539;BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT UP HEAVY;;;;
-253A;BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT UP HEAVY;;;;
-253B;BOX DRAWINGS HEAVY UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY UP AND HORIZONTAL;;;;
-253C;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND HORIZONTAL;;;;
-253D;BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT;;;;
-253E;BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT;;;;
-253F;BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY;;;;
-2540;BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT;;;;
-2541;BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT;;;;
-2542;BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT;;;;
-2543;BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT;;;;
-2544;BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT;;;;
-2545;BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT;;;;
-2546;BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT;;;;
-2547;BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY;;;;
-2548;BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY;;;;
-2549;BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY;;;;
-254A;BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY;;;;
-254B;BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND HORIZONTAL;;;;
-254C;BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH HORIZONTAL;;;;
-254D;BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH HORIZONTAL;;;;
-254E;BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH VERTICAL;;;;
-254F;BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH VERTICAL;;;;
-2550;BOX DRAWINGS DOUBLE HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE HORIZONTAL;;;;
-2551;BOX DRAWINGS DOUBLE VERTICAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL;;;;
-2552;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND RIGHT DOUBLE;;;;
-2553;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND RIGHT SINGLE;;;;
-2554;BOX DRAWINGS DOUBLE DOWN AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND RIGHT;;;;
-2555;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND LEFT DOUBLE;;;;
-2556;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND LEFT SINGLE;;;;
-2557;BOX DRAWINGS DOUBLE DOWN AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND LEFT;;;;
-2558;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND RIGHT DOUBLE;;;;
-2559;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND RIGHT SINGLE;;;;
-255A;BOX DRAWINGS DOUBLE UP AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE UP AND RIGHT;;;;
-255B;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND LEFT DOUBLE;;;;
-255C;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND LEFT SINGLE;;;;
-255D;BOX DRAWINGS DOUBLE UP AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE UP AND LEFT;;;;
-255E;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND RIGHT DOUBLE;;;;
-255F;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND RIGHT SINGLE;;;;
-2560;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND RIGHT;;;;
-2561;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND LEFT DOUBLE;;;;
-2562;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND LEFT SINGLE;;;;
-2563;BOX DRAWINGS DOUBLE VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND LEFT;;;;
-2564;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND HORIZONTAL DOUBLE;;;;
-2565;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND HORIZONTAL SINGLE;;;;
-2566;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND HORIZONTAL;;;;
-2567;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND HORIZONTAL DOUBLE;;;;
-2568;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND HORIZONTAL SINGLE;;;;
-2569;BOX DRAWINGS DOUBLE UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE UP AND HORIZONTAL;;;;
-256A;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE;;;;
-256B;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE;;;;
-256C;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND HORIZONTAL;;;;
-256D;BOX DRAWINGS LIGHT ARC DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND RIGHT;;;;
-256E;BOX DRAWINGS LIGHT ARC DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND LEFT;;;;
-256F;BOX DRAWINGS LIGHT ARC UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND LEFT;;;;
-2570;BOX DRAWINGS LIGHT ARC UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND RIGHT;;;;
-2571;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;;;;
-2572;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;;;;
-2573;BOX DRAWINGS LIGHT DIAGONAL CROSS;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL CROSS;;;;
-2574;BOX DRAWINGS LIGHT LEFT;So;0;ON;;;;;N;FORMS LIGHT LEFT;;;;
-2575;BOX DRAWINGS LIGHT UP;So;0;ON;;;;;N;FORMS LIGHT UP;;;;
-2576;BOX DRAWINGS LIGHT RIGHT;So;0;ON;;;;;N;FORMS LIGHT RIGHT;;;;
-2577;BOX DRAWINGS LIGHT DOWN;So;0;ON;;;;;N;FORMS LIGHT DOWN;;;;
-2578;BOX DRAWINGS HEAVY LEFT;So;0;ON;;;;;N;FORMS HEAVY LEFT;;;;
-2579;BOX DRAWINGS HEAVY UP;So;0;ON;;;;;N;FORMS HEAVY UP;;;;
-257A;BOX DRAWINGS HEAVY RIGHT;So;0;ON;;;;;N;FORMS HEAVY RIGHT;;;;
-257B;BOX DRAWINGS HEAVY DOWN;So;0;ON;;;;;N;FORMS HEAVY DOWN;;;;
-257C;BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT;So;0;ON;;;;;N;FORMS LIGHT LEFT AND HEAVY RIGHT;;;;
-257D;BOX DRAWINGS LIGHT UP AND HEAVY DOWN;So;0;ON;;;;;N;FORMS LIGHT UP AND HEAVY DOWN;;;;
-257E;BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT;So;0;ON;;;;;N;FORMS HEAVY LEFT AND LIGHT RIGHT;;;;
-257F;BOX DRAWINGS HEAVY UP AND LIGHT DOWN;So;0;ON;;;;;N;FORMS HEAVY UP AND LIGHT DOWN;;;;
-2580;UPPER HALF BLOCK;So;0;ON;;;;;N;;;;;
-2581;LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;;
-2582;LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;;
-2583;LOWER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
-2584;LOWER HALF BLOCK;So;0;ON;;;;;N;;;;;
-2585;LOWER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
-2586;LOWER THREE QUARTERS BLOCK;So;0;ON;;;;;N;LOWER THREE QUARTER BLOCK;;;;
-2587;LOWER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
-2588;FULL BLOCK;So;0;ON;;;;;N;;;;;
-2589;LEFT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
-258A;LEFT THREE QUARTERS BLOCK;So;0;ON;;;;;N;LEFT THREE QUARTER BLOCK;;;;
-258B;LEFT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
-258C;LEFT HALF BLOCK;So;0;ON;;;;;N;;;;;
-258D;LEFT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
-258E;LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;;
-258F;LEFT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;;
-2590;RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;;
-2591;LIGHT SHADE;So;0;ON;;;;;N;;;;;
-2592;MEDIUM SHADE;So;0;ON;;;;;N;;;;;
-2593;DARK SHADE;So;0;ON;;;;;N;;;;;
-2594;UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;;
-2595;RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;;
-2596;QUADRANT LOWER LEFT;So;0;ON;;;;;N;;;;;
-2597;QUADRANT LOWER RIGHT;So;0;ON;;;;;N;;;;;
-2598;QUADRANT UPPER LEFT;So;0;ON;;;;;N;;;;;
-2599;QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;;
-259A;QUADRANT UPPER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;;
-259B;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;;
-259C;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;;
-259D;QUADRANT UPPER RIGHT;So;0;ON;;;;;N;;;;;
-259E;QUADRANT UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;;
-259F;QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;;
-25A0;BLACK SQUARE;So;0;ON;;;;;N;;;;;
-25A1;WHITE SQUARE;So;0;ON;;;;;N;;;;;
-25A2;WHITE SQUARE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;;
-25A3;WHITE SQUARE CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;;
-25A4;SQUARE WITH HORIZONTAL FILL;So;0;ON;;;;;N;;;;;
-25A5;SQUARE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;;
-25A6;SQUARE WITH ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;;
-25A7;SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;;
-25A8;SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;;
-25A9;SQUARE WITH DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;;
-25AA;BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;;
-25AB;WHITE SMALL SQUARE;So;0;ON;;;;;N;;;;;
-25AC;BLACK RECTANGLE;So;0;ON;;;;;N;;;;;
-25AD;WHITE RECTANGLE;So;0;ON;;;;;N;;;;;
-25AE;BLACK VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;;
-25AF;WHITE VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;;
-25B0;BLACK PARALLELOGRAM;So;0;ON;;;;;N;;;;;
-25B1;WHITE PARALLELOGRAM;So;0;ON;;;;;N;;;;;
-25B2;BLACK UP-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING TRIANGLE;;;;
-25B3;WHITE UP-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE;;;;
-25B4;BLACK UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING SMALL TRIANGLE;;;;
-25B5;WHITE UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING SMALL TRIANGLE;;;;
-25B6;BLACK RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING TRIANGLE;;;;
-25B7;WHITE RIGHT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE RIGHT POINTING TRIANGLE;;;;
-25B8;BLACK RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING SMALL TRIANGLE;;;;
-25B9;WHITE RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE RIGHT POINTING SMALL TRIANGLE;;;;
-25BA;BLACK RIGHT-POINTING POINTER;So;0;ON;;;;;N;BLACK RIGHT POINTING POINTER;;;;
-25BB;WHITE RIGHT-POINTING POINTER;So;0;ON;;;;;N;WHITE RIGHT POINTING POINTER;;;;
-25BC;BLACK DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING TRIANGLE;;;;
-25BD;WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING TRIANGLE;;;;
-25BE;BLACK DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING SMALL TRIANGLE;;;;
-25BF;WHITE DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING SMALL TRIANGLE;;;;
-25C0;BLACK LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING TRIANGLE;;;;
-25C1;WHITE LEFT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE LEFT POINTING TRIANGLE;;;;
-25C2;BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING SMALL TRIANGLE;;;;
-25C3;WHITE LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE LEFT POINTING SMALL TRIANGLE;;;;
-25C4;BLACK LEFT-POINTING POINTER;So;0;ON;;;;;N;BLACK LEFT POINTING POINTER;;;;
-25C5;WHITE LEFT-POINTING POINTER;So;0;ON;;;;;N;WHITE LEFT POINTING POINTER;;;;
-25C6;BLACK DIAMOND;So;0;ON;;;;;N;;;;;
-25C7;WHITE DIAMOND;So;0;ON;;;;;N;;;;;
-25C8;WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;;
-25C9;FISHEYE;So;0;ON;;;;;N;;;;;
-25CA;LOZENGE;So;0;ON;;;;;N;;;;;
-25CB;WHITE CIRCLE;So;0;ON;;;;;N;;;;;
-25CC;DOTTED CIRCLE;So;0;ON;;;;;N;;;;;
-25CD;CIRCLE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;;
-25CE;BULLSEYE;So;0;ON;;;;;N;;;;;
-25CF;BLACK CIRCLE;So;0;ON;;;;;N;;;;;
-25D0;CIRCLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;;
-25D1;CIRCLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;;
-25D2;CIRCLE WITH LOWER HALF BLACK;So;0;ON;;;;;N;;;;;
-25D3;CIRCLE WITH UPPER HALF BLACK;So;0;ON;;;;;N;;;;;
-25D4;CIRCLE WITH UPPER RIGHT QUADRANT BLACK;So;0;ON;;;;;N;;;;;
-25D5;CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK;So;0;ON;;;;;N;;;;;
-25D6;LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;;
-25D7;RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;;
-25D8;INVERSE BULLET;So;0;ON;;;;;N;;;;;
-25D9;INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;;
-25DA;UPPER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;;
-25DB;LOWER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;;
-25DC;UPPER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;;
-25DD;UPPER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;;
-25DE;LOWER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;;
-25DF;LOWER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;;
-25E0;UPPER HALF CIRCLE;So;0;ON;;;;;N;;;;;
-25E1;LOWER HALF CIRCLE;So;0;ON;;;;;N;;;;;
-25E2;BLACK LOWER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;;
-25E3;BLACK LOWER LEFT TRIANGLE;So;0;ON;;;;;N;;;;;
-25E4;BLACK UPPER LEFT TRIANGLE;So;0;ON;;;;;N;;;;;
-25E5;BLACK UPPER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;;
-25E6;WHITE BULLET;So;0;ON;;;;;N;;;;;
-25E7;SQUARE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;;
-25E8;SQUARE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;;
-25E9;SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;;
-25EA;SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;;
-25EB;WHITE SQUARE WITH VERTICAL BISECTING LINE;So;0;ON;;;;;N;;;;;
-25EC;WHITE UP-POINTING TRIANGLE WITH DOT;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE WITH DOT;;;;
-25ED;UP-POINTING TRIANGLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH LEFT HALF BLACK;;;;
-25EE;UP-POINTING TRIANGLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH RIGHT HALF BLACK;;;;
-25EF;LARGE CIRCLE;So;0;ON;;;;;N;;;;;
-25F0;WHITE SQUARE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;;
-25F1;WHITE SQUARE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;;
-25F2;WHITE SQUARE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;;
-25F3;WHITE SQUARE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;;
-25F4;WHITE CIRCLE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;;
-25F5;WHITE CIRCLE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;;
-25F6;WHITE CIRCLE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;;
-25F7;WHITE CIRCLE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;;
-25F8;UPPER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;;
-25F9;UPPER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;;
-25FA;LOWER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;;
-25FB;WHITE MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;;
-25FC;BLACK MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;;
-25FD;WHITE MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;;
-25FE;BLACK MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;;
-25FF;LOWER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;;
-2600;BLACK SUN WITH RAYS;So;0;ON;;;;;N;;;;;
-2601;CLOUD;So;0;ON;;;;;N;;;;;
-2602;UMBRELLA;So;0;ON;;;;;N;;;;;
-2603;SNOWMAN;So;0;ON;;;;;N;;;;;
-2604;COMET;So;0;ON;;;;;N;;;;;
-2605;BLACK STAR;So;0;ON;;;;;N;;;;;
-2606;WHITE STAR;So;0;ON;;;;;N;;;;;
-2607;LIGHTNING;So;0;ON;;;;;N;;;;;
-2608;THUNDERSTORM;So;0;ON;;;;;N;;;;;
-2609;SUN;So;0;ON;;;;;N;;;;;
-260A;ASCENDING NODE;So;0;ON;;;;;N;;;;;
-260B;DESCENDING NODE;So;0;ON;;;;;N;;;;;
-260C;CONJUNCTION;So;0;ON;;;;;N;;;;;
-260D;OPPOSITION;So;0;ON;;;;;N;;;;;
-260E;BLACK TELEPHONE;So;0;ON;;;;;N;;;;;
-260F;WHITE TELEPHONE;So;0;ON;;;;;N;;;;;
-2610;BALLOT BOX;So;0;ON;;;;;N;;;;;
-2611;BALLOT BOX WITH CHECK;So;0;ON;;;;;N;;;;;
-2612;BALLOT BOX WITH X;So;0;ON;;;;;N;;;;;
-2613;SALTIRE;So;0;ON;;;;;N;;;;;
-2614;UMBRELLA WITH RAIN DROPS;So;0;ON;;;;;N;;;;;
-2615;HOT BEVERAGE;So;0;ON;;;;;N;;;;;
-2616;WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;;
-2617;BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;;
-2618;SHAMROCK;So;0;ON;;;;;N;;;;;
-2619;REVERSED ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;;
-261A;BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;;
-261B;BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;;
-261C;WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;;
-261D;WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;;
-261E;WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;;
-261F;WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;;
-2620;SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;;
-2621;CAUTION SIGN;So;0;ON;;;;;N;;;;;
-2622;RADIOACTIVE SIGN;So;0;ON;;;;;N;;;;;
-2623;BIOHAZARD SIGN;So;0;ON;;;;;N;;;;;
-2624;CADUCEUS;So;0;ON;;;;;N;;;;;
-2625;ANKH;So;0;ON;;;;;N;;;;;
-2626;ORTHODOX CROSS;So;0;ON;;;;;N;;;;;
-2627;CHI RHO;So;0;ON;;;;;N;;;;;
-2628;CROSS OF LORRAINE;So;0;ON;;;;;N;;;;;
-2629;CROSS OF JERUSALEM;So;0;ON;;;;;N;;;;;
-262A;STAR AND CRESCENT;So;0;ON;;;;;N;;;;;
-262B;FARSI SYMBOL;So;0;ON;;;;;N;SYMBOL OF IRAN;;;;
-262C;ADI SHAKTI;So;0;ON;;;;;N;;;;;
-262D;HAMMER AND SICKLE;So;0;ON;;;;;N;;;;;
-262E;PEACE SYMBOL;So;0;ON;;;;;N;;;;;
-262F;YIN YANG;So;0;ON;;;;;N;;;;;
-2630;TRIGRAM FOR HEAVEN;So;0;ON;;;;;N;;;;;
-2631;TRIGRAM FOR LAKE;So;0;ON;;;;;N;;;;;
-2632;TRIGRAM FOR FIRE;So;0;ON;;;;;N;;;;;
-2633;TRIGRAM FOR THUNDER;So;0;ON;;;;;N;;;;;
-2634;TRIGRAM FOR WIND;So;0;ON;;;;;N;;;;;
-2635;TRIGRAM FOR WATER;So;0;ON;;;;;N;;;;;
-2636;TRIGRAM FOR MOUNTAIN;So;0;ON;;;;;N;;;;;
-2637;TRIGRAM FOR EARTH;So;0;ON;;;;;N;;;;;
-2638;WHEEL OF DHARMA;So;0;ON;;;;;N;;;;;
-2639;WHITE FROWNING FACE;So;0;ON;;;;;N;;;;;
-263A;WHITE SMILING FACE;So;0;ON;;;;;N;;;;;
-263B;BLACK SMILING FACE;So;0;ON;;;;;N;;;;;
-263C;WHITE SUN WITH RAYS;So;0;ON;;;;;N;;;;;
-263D;FIRST QUARTER MOON;So;0;ON;;;;;N;;;;;
-263E;LAST QUARTER MOON;So;0;ON;;;;;N;;;;;
-263F;MERCURY;So;0;ON;;;;;N;;;;;
-2640;FEMALE SIGN;So;0;ON;;;;;N;;;;;
-2641;EARTH;So;0;ON;;;;;N;;;;;
-2642;MALE SIGN;So;0;ON;;;;;N;;;;;
-2643;JUPITER;So;0;ON;;;;;N;;;;;
-2644;SATURN;So;0;ON;;;;;N;;;;;
-2645;URANUS;So;0;ON;;;;;N;;;;;
-2646;NEPTUNE;So;0;ON;;;;;N;;;;;
-2647;PLUTO;So;0;ON;;;;;N;;;;;
-2648;ARIES;So;0;ON;;;;;N;;;;;
-2649;TAURUS;So;0;ON;;;;;N;;;;;
-264A;GEMINI;So;0;ON;;;;;N;;;;;
-264B;CANCER;So;0;ON;;;;;N;;;;;
-264C;LEO;So;0;ON;;;;;N;;;;;
-264D;VIRGO;So;0;ON;;;;;N;;;;;
-264E;LIBRA;So;0;ON;;;;;N;;;;;
-264F;SCORPIUS;So;0;ON;;;;;N;;;;;
-2650;SAGITTARIUS;So;0;ON;;;;;N;;;;;
-2651;CAPRICORN;So;0;ON;;;;;N;;;;;
-2652;AQUARIUS;So;0;ON;;;;;N;;;;;
-2653;PISCES;So;0;ON;;;;;N;;;;;
-2654;WHITE CHESS KING;So;0;ON;;;;;N;;;;;
-2655;WHITE CHESS QUEEN;So;0;ON;;;;;N;;;;;
-2656;WHITE CHESS ROOK;So;0;ON;;;;;N;;;;;
-2657;WHITE CHESS BISHOP;So;0;ON;;;;;N;;;;;
-2658;WHITE CHESS KNIGHT;So;0;ON;;;;;N;;;;;
-2659;WHITE CHESS PAWN;So;0;ON;;;;;N;;;;;
-265A;BLACK CHESS KING;So;0;ON;;;;;N;;;;;
-265B;BLACK CHESS QUEEN;So;0;ON;;;;;N;;;;;
-265C;BLACK CHESS ROOK;So;0;ON;;;;;N;;;;;
-265D;BLACK CHESS BISHOP;So;0;ON;;;;;N;;;;;
-265E;BLACK CHESS KNIGHT;So;0;ON;;;;;N;;;;;
-265F;BLACK CHESS PAWN;So;0;ON;;;;;N;;;;;
-2660;BLACK SPADE SUIT;So;0;ON;;;;;N;;;;;
-2661;WHITE HEART SUIT;So;0;ON;;;;;N;;;;;
-2662;WHITE DIAMOND SUIT;So;0;ON;;;;;N;;;;;
-2663;BLACK CLUB SUIT;So;0;ON;;;;;N;;;;;
-2664;WHITE SPADE SUIT;So;0;ON;;;;;N;;;;;
-2665;BLACK HEART SUIT;So;0;ON;;;;;N;;;;;
-2666;BLACK DIAMOND SUIT;So;0;ON;;;;;N;;;;;
-2667;WHITE CLUB SUIT;So;0;ON;;;;;N;;;;;
-2668;HOT SPRINGS;So;0;ON;;;;;N;;;;;
-2669;QUARTER NOTE;So;0;ON;;;;;N;;;;;
-266A;EIGHTH NOTE;So;0;ON;;;;;N;;;;;
-266B;BEAMED EIGHTH NOTES;So;0;ON;;;;;N;BARRED EIGHTH NOTES;;;;
-266C;BEAMED SIXTEENTH NOTES;So;0;ON;;;;;N;BARRED SIXTEENTH NOTES;;;;
-266D;MUSIC FLAT SIGN;So;0;ON;;;;;N;FLAT;;;;
-266E;MUSIC NATURAL SIGN;So;0;ON;;;;;N;NATURAL;;;;
-266F;MUSIC SHARP SIGN;Sm;0;ON;;;;;N;SHARP;;;;
-2670;WEST SYRIAC CROSS;So;0;ON;;;;;N;;;;;
-2671;EAST SYRIAC CROSS;So;0;ON;;;;;N;;;;;
-2672;UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;;
-2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;;;;
-2674;RECYCLING SYMBOL FOR TYPE-2 PLASTICS;So;0;ON;;;;;N;;;;;
-2675;RECYCLING SYMBOL FOR TYPE-3 PLASTICS;So;0;ON;;;;;N;;;;;
-2676;RECYCLING SYMBOL FOR TYPE-4 PLASTICS;So;0;ON;;;;;N;;;;;
-2677;RECYCLING SYMBOL FOR TYPE-5 PLASTICS;So;0;ON;;;;;N;;;;;
-2678;RECYCLING SYMBOL FOR TYPE-6 PLASTICS;So;0;ON;;;;;N;;;;;
-2679;RECYCLING SYMBOL FOR TYPE-7 PLASTICS;So;0;ON;;;;;N;;;;;
-267A;RECYCLING SYMBOL FOR GENERIC MATERIALS;So;0;ON;;;;;N;;;;;
-267B;BLACK UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;;
-267C;RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;;
-267D;PARTIALLY-RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;;
-267E;PERMANENT PAPER SIGN;So;0;ON;;;;;N;;;;;
-267F;WHEELCHAIR SYMBOL;So;0;ON;;;;;N;;;;;
-2680;DIE FACE-1;So;0;ON;;;;;N;;;;;
-2681;DIE FACE-2;So;0;ON;;;;;N;;;;;
-2682;DIE FACE-3;So;0;ON;;;;;N;;;;;
-2683;DIE FACE-4;So;0;ON;;;;;N;;;;;
-2684;DIE FACE-5;So;0;ON;;;;;N;;;;;
-2685;DIE FACE-6;So;0;ON;;;;;N;;;;;
-2686;WHITE CIRCLE WITH DOT RIGHT;So;0;ON;;;;;N;;;;;
-2687;WHITE CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;;
-2688;BLACK CIRCLE WITH WHITE DOT RIGHT;So;0;ON;;;;;N;;;;;
-2689;BLACK CIRCLE WITH TWO WHITE DOTS;So;0;ON;;;;;N;;;;;
-268A;MONOGRAM FOR YANG;So;0;ON;;;;;N;;;;;
-268B;MONOGRAM FOR YIN;So;0;ON;;;;;N;;;;;
-268C;DIGRAM FOR GREATER YANG;So;0;ON;;;;;N;;;;;
-268D;DIGRAM FOR LESSER YIN;So;0;ON;;;;;N;;;;;
-268E;DIGRAM FOR LESSER YANG;So;0;ON;;;;;N;;;;;
-268F;DIGRAM FOR GREATER YIN;So;0;ON;;;;;N;;;;;
-2690;WHITE FLAG;So;0;ON;;;;;N;;;;;
-2691;BLACK FLAG;So;0;ON;;;;;N;;;;;
-2692;HAMMER AND PICK;So;0;ON;;;;;N;;;;;
-2693;ANCHOR;So;0;ON;;;;;N;;;;;
-2694;CROSSED SWORDS;So;0;ON;;;;;N;;;;;
-2695;STAFF OF AESCULAPIUS;So;0;ON;;;;;N;;;;;
-2696;SCALES;So;0;ON;;;;;N;;;;;
-2697;ALEMBIC;So;0;ON;;;;;N;;;;;
-2698;FLOWER;So;0;ON;;;;;N;;;;;
-2699;GEAR;So;0;ON;;;;;N;;;;;
-269A;STAFF OF HERMES;So;0;ON;;;;;N;;;;;
-269B;ATOM SYMBOL;So;0;ON;;;;;N;;;;;
-269C;FLEUR-DE-LIS;So;0;ON;;;;;N;;;;;
-269D;OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;;
-269E;THREE LINES CONVERGING RIGHT;So;0;ON;;;;;N;;;;;
-269F;THREE LINES CONVERGING LEFT;So;0;ON;;;;;N;;;;;
-26A0;WARNING SIGN;So;0;ON;;;;;N;;;;;
-26A1;HIGH VOLTAGE SIGN;So;0;ON;;;;;N;;;;;
-26A2;DOUBLED FEMALE SIGN;So;0;ON;;;;;N;;;;;
-26A3;DOUBLED MALE SIGN;So;0;ON;;;;;N;;;;;
-26A4;INTERLOCKED FEMALE AND MALE SIGN;So;0;ON;;;;;N;;;;;
-26A5;MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;;
-26A6;MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;;
-26A7;MALE WITH STROKE AND MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;;
-26A8;VERTICAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;;
-26A9;HORIZONTAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;;
-26AA;MEDIUM WHITE CIRCLE;So;0;ON;;;;;N;;;;;
-26AB;MEDIUM BLACK CIRCLE;So;0;ON;;;;;N;;;;;
-26AC;MEDIUM SMALL WHITE CIRCLE;So;0;L;;;;;N;;;;;
-26AD;MARRIAGE SYMBOL;So;0;ON;;;;;N;;;;;
-26AE;DIVORCE SYMBOL;So;0;ON;;;;;N;;;;;
-26AF;UNMARRIED PARTNERSHIP SYMBOL;So;0;ON;;;;;N;;;;;
-26B0;COFFIN;So;0;ON;;;;;N;;;;;
-26B1;FUNERAL URN;So;0;ON;;;;;N;;;;;
-26B2;NEUTER;So;0;ON;;;;;N;;;;;
-26B3;CERES;So;0;ON;;;;;N;;;;;
-26B4;PALLAS;So;0;ON;;;;;N;;;;;
-26B5;JUNO;So;0;ON;;;;;N;;;;;
-26B6;VESTA;So;0;ON;;;;;N;;;;;
-26B7;CHIRON;So;0;ON;;;;;N;;;;;
-26B8;BLACK MOON LILITH;So;0;ON;;;;;N;;;;;
-26B9;SEXTILE;So;0;ON;;;;;N;;;;;
-26BA;SEMISEXTILE;So;0;ON;;;;;N;;;;;
-26BB;QUINCUNX;So;0;ON;;;;;N;;;;;
-26BC;SESQUIQUADRATE;So;0;ON;;;;;N;;;;;
-26BD;SOCCER BALL;So;0;ON;;;;;N;;;;;
-26BE;BASEBALL;So;0;ON;;;;;N;;;;;
-26BF;SQUARED KEY;So;0;ON;;;;;N;;;;;
-26C0;WHITE DRAUGHTS MAN;So;0;ON;;;;;N;;;;;
-26C1;WHITE DRAUGHTS KING;So;0;ON;;;;;N;;;;;
-26C2;BLACK DRAUGHTS MAN;So;0;ON;;;;;N;;;;;
-26C3;BLACK DRAUGHTS KING;So;0;ON;;;;;N;;;;;
-26C4;SNOWMAN WITHOUT SNOW;So;0;ON;;;;;N;;;;;
-26C5;SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;;
-26C6;RAIN;So;0;ON;;;;;N;;;;;
-26C7;BLACK SNOWMAN;So;0;ON;;;;;N;;;;;
-26C8;THUNDER CLOUD AND RAIN;So;0;ON;;;;;N;;;;;
-26C9;TURNED WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;;
-26CA;TURNED BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;;
-26CB;WHITE DIAMOND IN SQUARE;So;0;ON;;;;;N;;;;;
-26CC;CROSSING LANES;So;0;ON;;;;;N;;;;;
-26CD;DISABLED CAR;So;0;ON;;;;;N;;;;;
-26CE;OPHIUCHUS;So;0;ON;;;;;N;;;;;
-26CF;PICK;So;0;ON;;;;;N;;;;;
-26D0;CAR SLIDING;So;0;ON;;;;;N;;;;;
-26D1;HELMET WITH WHITE CROSS;So;0;ON;;;;;N;;;;;
-26D2;CIRCLED CROSSING LANES;So;0;ON;;;;;N;;;;;
-26D3;CHAINS;So;0;ON;;;;;N;;;;;
-26D4;NO ENTRY;So;0;ON;;;;;N;;;;;
-26D5;ALTERNATE ONE-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;;
-26D6;BLACK TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;;
-26D7;WHITE TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;;
-26D8;BLACK LEFT LANE MERGE;So;0;ON;;;;;N;;;;;
-26D9;WHITE LEFT LANE MERGE;So;0;ON;;;;;N;;;;;
-26DA;DRIVE SLOW SIGN;So;0;ON;;;;;N;;;;;
-26DB;HEAVY WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;;
-26DC;LEFT CLOSED ENTRY;So;0;ON;;;;;N;;;;;
-26DD;SQUARED SALTIRE;So;0;ON;;;;;N;;;;;
-26DE;FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE;So;0;ON;;;;;N;;;;;
-26DF;BLACK TRUCK;So;0;ON;;;;;N;;;;;
-26E0;RESTRICTED LEFT ENTRY-1;So;0;ON;;;;;N;;;;;
-26E1;RESTRICTED LEFT ENTRY-2;So;0;ON;;;;;N;;;;;
-26E2;ASTRONOMICAL SYMBOL FOR URANUS;So;0;ON;;;;;N;;;;;
-26E3;HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE;So;0;ON;;;;;N;;;;;
-26E4;PENTAGRAM;So;0;ON;;;;;N;;;;;
-26E5;RIGHT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;;
-26E6;LEFT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;;
-26E7;INVERTED PENTAGRAM;So;0;ON;;;;;N;;;;;
-26E8;BLACK CROSS ON SHIELD;So;0;ON;;;;;N;;;;;
-26E9;SHINTO SHRINE;So;0;ON;;;;;N;;;;;
-26EA;CHURCH;So;0;ON;;;;;N;;;;;
-26EB;CASTLE;So;0;ON;;;;;N;;;;;
-26EC;HISTORIC SITE;So;0;ON;;;;;N;;;;;
-26ED;GEAR WITHOUT HUB;So;0;ON;;;;;N;;;;;
-26EE;GEAR WITH HANDLES;So;0;ON;;;;;N;;;;;
-26EF;MAP SYMBOL FOR LIGHTHOUSE;So;0;ON;;;;;N;;;;;
-26F0;MOUNTAIN;So;0;ON;;;;;N;;;;;
-26F1;UMBRELLA ON GROUND;So;0;ON;;;;;N;;;;;
-26F2;FOUNTAIN;So;0;ON;;;;;N;;;;;
-26F3;FLAG IN HOLE;So;0;ON;;;;;N;;;;;
-26F4;FERRY;So;0;ON;;;;;N;;;;;
-26F5;SAILBOAT;So;0;ON;;;;;N;;;;;
-26F6;SQUARE FOUR CORNERS;So;0;ON;;;;;N;;;;;
-26F7;SKIER;So;0;ON;;;;;N;;;;;
-26F8;ICE SKATE;So;0;ON;;;;;N;;;;;
-26F9;PERSON WITH BALL;So;0;ON;;;;;N;;;;;
-26FA;TENT;So;0;ON;;;;;N;;;;;
-26FB;JAPANESE BANK SYMBOL;So;0;ON;;;;;N;;;;;
-26FC;HEADSTONE GRAVEYARD SYMBOL;So;0;ON;;;;;N;;;;;
-26FD;FUEL PUMP;So;0;ON;;;;;N;;;;;
-26FE;CUP ON BLACK SQUARE;So;0;ON;;;;;N;;;;;
-26FF;WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE;So;0;ON;;;;;N;;;;;
-2701;UPPER BLADE SCISSORS;So;0;ON;;;;;N;;;;;
-2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;;
-2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;;
-2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;;
-2705;WHITE HEAVY CHECK MARK;So;0;ON;;;;;N;;;;;
-2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;;
-2707;TAPE DRIVE;So;0;ON;;;;;N;;;;;
-2708;AIRPLANE;So;0;ON;;;;;N;;;;;
-2709;ENVELOPE;So;0;ON;;;;;N;;;;;
-270A;RAISED FIST;So;0;ON;;;;;N;;;;;
-270B;RAISED HAND;So;0;ON;;;;;N;;;;;
-270C;VICTORY HAND;So;0;ON;;;;;N;;;;;
-270D;WRITING HAND;So;0;ON;;;;;N;;;;;
-270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;;
-270F;PENCIL;So;0;ON;;;;;N;;;;;
-2710;UPPER RIGHT PENCIL;So;0;ON;;;;;N;;;;;
-2711;WHITE NIB;So;0;ON;;;;;N;;;;;
-2712;BLACK NIB;So;0;ON;;;;;N;;;;;
-2713;CHECK MARK;So;0;ON;;;;;N;;;;;
-2714;HEAVY CHECK MARK;So;0;ON;;;;;N;;;;;
-2715;MULTIPLICATION X;So;0;ON;;;;;N;;;;;
-2716;HEAVY MULTIPLICATION X;So;0;ON;;;;;N;;;;;
-2717;BALLOT X;So;0;ON;;;;;N;;;;;
-2718;HEAVY BALLOT X;So;0;ON;;;;;N;;;;;
-2719;OUTLINED GREEK CROSS;So;0;ON;;;;;N;;;;;
-271A;HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;;
-271B;OPEN CENTRE CROSS;So;0;ON;;;;;N;OPEN CENTER CROSS;;;;
-271C;HEAVY OPEN CENTRE CROSS;So;0;ON;;;;;N;HEAVY OPEN CENTER CROSS;;;;
-271D;LATIN CROSS;So;0;ON;;;;;N;;;;;
-271E;SHADOWED WHITE LATIN CROSS;So;0;ON;;;;;N;;;;;
-271F;OUTLINED LATIN CROSS;So;0;ON;;;;;N;;;;;
-2720;MALTESE CROSS;So;0;ON;;;;;N;;;;;
-2721;STAR OF DAVID;So;0;ON;;;;;N;;;;;
-2722;FOUR TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
-2723;FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
-2724;HEAVY FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
-2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
-2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;;
-2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;;
-2728;SPARKLES;So;0;ON;;;;;N;;;;;
-2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;;
-272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;;
-272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;;
-272C;BLACK CENTRE WHITE STAR;So;0;ON;;;;;N;BLACK CENTER WHITE STAR;;;;
-272D;OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;;
-272E;HEAVY OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;;
-272F;PINWHEEL STAR;So;0;ON;;;;;N;;;;;
-2730;SHADOWED WHITE STAR;So;0;ON;;;;;N;;;;;
-2731;HEAVY ASTERISK;So;0;ON;;;;;N;;;;;
-2732;OPEN CENTRE ASTERISK;So;0;ON;;;;;N;OPEN CENTER ASTERISK;;;;
-2733;EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
-2734;EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;;
-2735;EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;;
-2736;SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;;
-2737;EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;;
-2738;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;;
-2739;TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;;
-273A;SIXTEEN POINTED ASTERISK;So;0;ON;;;;;N;;;;;
-273B;TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
-273C;OPEN CENTRE TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;OPEN CENTER TEARDROP-SPOKED ASTERISK;;;;
-273D;HEAVY TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
-273E;SIX PETALLED BLACK AND WHITE FLORETTE;So;0;ON;;;;;N;;;;;
-273F;BLACK FLORETTE;So;0;ON;;;;;N;;;;;
-2740;WHITE FLORETTE;So;0;ON;;;;;N;;;;;
-2741;EIGHT PETALLED OUTLINED BLACK FLORETTE;So;0;ON;;;;;N;;;;;
-2742;CIRCLED OPEN CENTRE EIGHT POINTED STAR;So;0;ON;;;;;N;CIRCLED OPEN CENTER EIGHT POINTED STAR;;;;
-2743;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK;So;0;ON;;;;;N;;;;;
-2744;SNOWFLAKE;So;0;ON;;;;;N;;;;;
-2745;TIGHT TRIFOLIATE SNOWFLAKE;So;0;ON;;;;;N;;;;;
-2746;HEAVY CHEVRON SNOWFLAKE;So;0;ON;;;;;N;;;;;
-2747;SPARKLE;So;0;ON;;;;;N;;;;;
-2748;HEAVY SPARKLE;So;0;ON;;;;;N;;;;;
-2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
-274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;;
-274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;;
-274C;CROSS MARK;So;0;ON;;;;;N;;;;;
-274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;;
-274E;NEGATIVE SQUARED CROSS MARK;So;0;ON;;;;;N;;;;;
-274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;;
-2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;;
-2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;;
-2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;;
-2753;BLACK QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-2754;WHITE QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-2755;WHITE EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;;
-2757;HEAVY EXCLAMATION MARK SYMBOL;So;0;ON;;;;;N;;;;;
-2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;;
-2759;MEDIUM VERTICAL BAR;So;0;ON;;;;;N;;;;;
-275A;HEAVY VERTICAL BAR;So;0;ON;;;;;N;;;;;
-275B;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-275F;HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-2760;HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;;
-2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
-2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;;
-2765;ROTATED HEAVY BLACK HEART BULLET;So;0;ON;;;;;N;;;;;
-2766;FLORAL HEART;So;0;ON;;;;;N;;;;;
-2767;ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;;
-2768;MEDIUM LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;;
-2769;MEDIUM RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;;
-276A;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;;
-276B;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;;
-276C;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;;
-276D;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;;
-276E;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT;Ps;0;ON;;;;;Y;;;;;
-276F;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT;Pe;0;ON;;;;;Y;;;;;
-2770;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;;
-2771;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;;
-2772;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;;
-2773;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;;
-2774;MEDIUM LEFT CURLY BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;;
-2775;MEDIUM RIGHT CURLY BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;;
-2776;DINGBAT NEGATIVE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED DIGIT ONE;;;;
-2777;DINGBAT NEGATIVE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED DIGIT TWO;;;;
-2778;DINGBAT NEGATIVE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED DIGIT THREE;;;;
-2779;DINGBAT NEGATIVE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED DIGIT FOUR;;;;
-277A;DINGBAT NEGATIVE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED DIGIT FIVE;;;;
-277B;DINGBAT NEGATIVE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED DIGIT SIX;;;;
-277C;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED DIGIT SEVEN;;;;
-277D;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED DIGIT EIGHT;;;;
-277E;DINGBAT NEGATIVE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED DIGIT NINE;;;;
-277F;DINGBAT NEGATIVE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED NUMBER TEN;;;;
-2780;DINGBAT CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;CIRCLED SANS-SERIF DIGIT ONE;;;;
-2781;DINGBAT CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;CIRCLED SANS-SERIF DIGIT TWO;;;;
-2782;DINGBAT CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;CIRCLED SANS-SERIF DIGIT THREE;;;;
-2783;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;CIRCLED SANS-SERIF DIGIT FOUR;;;;
-2784;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;CIRCLED SANS-SERIF DIGIT FIVE;;;;
-2785;DINGBAT CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;CIRCLED SANS-SERIF DIGIT SIX;;;;
-2786;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;CIRCLED SANS-SERIF DIGIT SEVEN;;;;
-2787;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;CIRCLED SANS-SERIF DIGIT EIGHT;;;;
-2788;DINGBAT CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;CIRCLED SANS-SERIF DIGIT NINE;;;;
-2789;DINGBAT CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;CIRCLED SANS-SERIF NUMBER TEN;;;;
-278A;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED SANS-SERIF DIGIT ONE;;;;
-278B;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED SANS-SERIF DIGIT TWO;;;;
-278C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED SANS-SERIF DIGIT THREE;;;;
-278D;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED SANS-SERIF DIGIT FOUR;;;;
-278E;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED SANS-SERIF DIGIT FIVE;;;;
-278F;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED SANS-SERIF DIGIT SIX;;;;
-2790;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED SANS-SERIF DIGIT SEVEN;;;;
-2791;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED SANS-SERIF DIGIT EIGHT;;;;
-2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;;
-2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;;
-2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;;
-2795;HEAVY PLUS SIGN;So;0;ON;;;;;N;;;;;
-2796;HEAVY MINUS SIGN;So;0;ON;;;;;N;;;;;
-2797;HEAVY DIVISION SIGN;So;0;ON;;;;;N;;;;;
-2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;;
-2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;;
-279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;;
-279B;DRAFTING POINT RIGHTWARDS ARROW;So;0;ON;;;;;N;DRAFTING POINT RIGHT ARROW;;;;
-279C;HEAVY ROUND-TIPPED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY ROUND-TIPPED RIGHT ARROW;;;;
-279D;TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;TRIANGLE-HEADED RIGHT ARROW;;;;
-279E;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TRIANGLE-HEADED RIGHT ARROW;;;;
-279F;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;DASHED TRIANGLE-HEADED RIGHT ARROW;;;;
-27A0;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW;;;;
-27A1;BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK RIGHT ARROW;;;;
-27A2;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D TOP-LIGHTED RIGHT ARROWHEAD;;;;
-27A3;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD;;;;
-27A4;BLACK RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;BLACK RIGHT ARROWHEAD;;;;
-27A5;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED DOWN AND RIGHT ARROW;;;;
-27A6;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED UP AND RIGHT ARROW;;;;
-27A7;SQUAT BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;SQUAT BLACK RIGHT ARROW;;;;
-27A8;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY CONCAVE-POINTED BLACK RIGHT ARROW;;;;
-27A9;RIGHT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;RIGHT-SHADED WHITE RIGHT ARROW;;;;
-27AA;LEFT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT-SHADED WHITE RIGHT ARROW;;;;
-27AB;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;BACK-TILTED SHADOWED WHITE RIGHT ARROW;;;;
-27AC;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;FRONT-TILTED SHADOWED WHITE RIGHT ARROW;;;;
-27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;;
-27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;;
-27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;;
-27B0;CURLY LOOP;So;0;ON;;;;;N;;;;;
-27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;;
-27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;;
-27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;;
-27B4;BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED LOWER RIGHT ARROW;;;;
-27B5;BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK-FEATHERED RIGHT ARROW;;;;
-27B6;BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED UPPER RIGHT ARROW;;;;
-27B7;HEAVY BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED LOWER RIGHT ARROW;;;;
-27B8;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED RIGHT ARROW;;;;
-27B9;HEAVY BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED UPPER RIGHT ARROW;;;;
-27BA;TEARDROP-BARBED RIGHTWARDS ARROW;So;0;ON;;;;;N;TEARDROP-BARBED RIGHT ARROW;;;;
-27BB;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TEARDROP-SHANKED RIGHT ARROW;;;;
-27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;;
-27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;;
-27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;;
-27BF;DOUBLE CURLY LOOP;So;0;ON;;;;;N;;;;;
-27C0;THREE DIMENSIONAL ANGLE;Sm;0;ON;;;;;Y;;;;;
-27C1;WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE;Sm;0;ON;;;;;N;;;;;
-27C2;PERPENDICULAR;Sm;0;ON;;;;;N;;;;;
-27C3;OPEN SUBSET;Sm;0;ON;;;;;Y;;;;;
-27C4;OPEN SUPERSET;Sm;0;ON;;;;;Y;;;;;
-27C5;LEFT S-SHAPED BAG DELIMITER;Ps;0;ON;;;;;Y;;;;;
-27C6;RIGHT S-SHAPED BAG DELIMITER;Pe;0;ON;;;;;Y;;;;;
-27C7;OR WITH DOT INSIDE;Sm;0;ON;;;;;N;;;;;
-27C8;REVERSE SOLIDUS PRECEDING SUBSET;Sm;0;ON;;;;;Y;;;;;
-27C9;SUPERSET PRECEDING SOLIDUS;Sm;0;ON;;;;;Y;;;;;
-27CA;VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
-27CB;MATHEMATICAL RISING DIAGONAL;Sm;0;ON;;;;;Y;;;;;
-27CC;LONG DIVISION;Sm;0;ON;;;;;Y;;;;;
-27CD;MATHEMATICAL FALLING DIAGONAL;Sm;0;ON;;;;;Y;;;;;
-27CE;SQUARED LOGICAL AND;Sm;0;ON;;;;;N;;;;;
-27CF;SQUARED LOGICAL OR;Sm;0;ON;;;;;N;;;;;
-27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;;
-27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;;
-27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;;
-27D3;LOWER RIGHT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;;
-27D4;UPPER LEFT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;;
-27D5;LEFT OUTER JOIN;Sm;0;ON;;;;;Y;;;;;
-27D6;RIGHT OUTER JOIN;Sm;0;ON;;;;;Y;;;;;
-27D7;FULL OUTER JOIN;Sm;0;ON;;;;;N;;;;;
-27D8;LARGE UP TACK;Sm;0;ON;;;;;N;;;;;
-27D9;LARGE DOWN TACK;Sm;0;ON;;;;;N;;;;;
-27DA;LEFT AND RIGHT DOUBLE TURNSTILE;Sm;0;ON;;;;;N;;;;;
-27DB;LEFT AND RIGHT TACK;Sm;0;ON;;;;;N;;;;;
-27DC;LEFT MULTIMAP;Sm;0;ON;;;;;Y;;;;;
-27DD;LONG RIGHT TACK;Sm;0;ON;;;;;Y;;;;;
-27DE;LONG LEFT TACK;Sm;0;ON;;;;;Y;;;;;
-27DF;UP TACK WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;;
-27E0;LOZENGE DIVIDED BY HORIZONTAL RULE;Sm;0;ON;;;;;N;;;;;
-27E1;WHITE CONCAVE-SIDED DIAMOND;Sm;0;ON;;;;;N;;;;;
-27E2;WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;;
-27E3;WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;;
-27E4;WHITE SQUARE WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;;
-27E5;WHITE SQUARE WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;;
-27E6;MATHEMATICAL LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;;;;;
-27E7;MATHEMATICAL RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;;;;;
-27E8;MATHEMATICAL LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;;
-27E9;MATHEMATICAL RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;;
-27EA;MATHEMATICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;;
-27EB;MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;;
-27EC;MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;;
-27ED;MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;;
-27EE;MATHEMATICAL LEFT FLATTENED PARENTHESIS;Ps;0;ON;;;;;Y;;;;;
-27EF;MATHEMATICAL RIGHT FLATTENED PARENTHESIS;Pe;0;ON;;;;;Y;;;;;
-27F0;UPWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;;
-27F1;DOWNWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;;
-27F2;ANTICLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;;
-27F3;CLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;;
-27F4;RIGHT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;;
-27F5;LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-27F6;LONG RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-27F7;LONG LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;;
-27F8;LONG LEFTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;;
-27F9;LONG RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;;
-27FA;LONG LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;;
-27FB;LONG LEFTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
-27FC;LONG RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
-27FD;LONG LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
-27FE;LONG RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
-27FF;LONG RIGHTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;;
-2800;BRAILLE PATTERN BLANK;So;0;L;;;;;N;;;;;
-2801;BRAILLE PATTERN DOTS-1;So;0;L;;;;;N;;;;;
-2802;BRAILLE PATTERN DOTS-2;So;0;L;;;;;N;;;;;
-2803;BRAILLE PATTERN DOTS-12;So;0;L;;;;;N;;;;;
-2804;BRAILLE PATTERN DOTS-3;So;0;L;;;;;N;;;;;
-2805;BRAILLE PATTERN DOTS-13;So;0;L;;;;;N;;;;;
-2806;BRAILLE PATTERN DOTS-23;So;0;L;;;;;N;;;;;
-2807;BRAILLE PATTERN DOTS-123;So;0;L;;;;;N;;;;;
-2808;BRAILLE PATTERN DOTS-4;So;0;L;;;;;N;;;;;
-2809;BRAILLE PATTERN DOTS-14;So;0;L;;;;;N;;;;;
-280A;BRAILLE PATTERN DOTS-24;So;0;L;;;;;N;;;;;
-280B;BRAILLE PATTERN DOTS-124;So;0;L;;;;;N;;;;;
-280C;BRAILLE PATTERN DOTS-34;So;0;L;;;;;N;;;;;
-280D;BRAILLE PATTERN DOTS-134;So;0;L;;;;;N;;;;;
-280E;BRAILLE PATTERN DOTS-234;So;0;L;;;;;N;;;;;
-280F;BRAILLE PATTERN DOTS-1234;So;0;L;;;;;N;;;;;
-2810;BRAILLE PATTERN DOTS-5;So;0;L;;;;;N;;;;;
-2811;BRAILLE PATTERN DOTS-15;So;0;L;;;;;N;;;;;
-2812;BRAILLE PATTERN DOTS-25;So;0;L;;;;;N;;;;;
-2813;BRAILLE PATTERN DOTS-125;So;0;L;;;;;N;;;;;
-2814;BRAILLE PATTERN DOTS-35;So;0;L;;;;;N;;;;;
-2815;BRAILLE PATTERN DOTS-135;So;0;L;;;;;N;;;;;
-2816;BRAILLE PATTERN DOTS-235;So;0;L;;;;;N;;;;;
-2817;BRAILLE PATTERN DOTS-1235;So;0;L;;;;;N;;;;;
-2818;BRAILLE PATTERN DOTS-45;So;0;L;;;;;N;;;;;
-2819;BRAILLE PATTERN DOTS-145;So;0;L;;;;;N;;;;;
-281A;BRAILLE PATTERN DOTS-245;So;0;L;;;;;N;;;;;
-281B;BRAILLE PATTERN DOTS-1245;So;0;L;;;;;N;;;;;
-281C;BRAILLE PATTERN DOTS-345;So;0;L;;;;;N;;;;;
-281D;BRAILLE PATTERN DOTS-1345;So;0;L;;;;;N;;;;;
-281E;BRAILLE PATTERN DOTS-2345;So;0;L;;;;;N;;;;;
-281F;BRAILLE PATTERN DOTS-12345;So;0;L;;;;;N;;;;;
-2820;BRAILLE PATTERN DOTS-6;So;0;L;;;;;N;;;;;
-2821;BRAILLE PATTERN DOTS-16;So;0;L;;;;;N;;;;;
-2822;BRAILLE PATTERN DOTS-26;So;0;L;;;;;N;;;;;
-2823;BRAILLE PATTERN DOTS-126;So;0;L;;;;;N;;;;;
-2824;BRAILLE PATTERN DOTS-36;So;0;L;;;;;N;;;;;
-2825;BRAILLE PATTERN DOTS-136;So;0;L;;;;;N;;;;;
-2826;BRAILLE PATTERN DOTS-236;So;0;L;;;;;N;;;;;
-2827;BRAILLE PATTERN DOTS-1236;So;0;L;;;;;N;;;;;
-2828;BRAILLE PATTERN DOTS-46;So;0;L;;;;;N;;;;;
-2829;BRAILLE PATTERN DOTS-146;So;0;L;;;;;N;;;;;
-282A;BRAILLE PATTERN DOTS-246;So;0;L;;;;;N;;;;;
-282B;BRAILLE PATTERN DOTS-1246;So;0;L;;;;;N;;;;;
-282C;BRAILLE PATTERN DOTS-346;So;0;L;;;;;N;;;;;
-282D;BRAILLE PATTERN DOTS-1346;So;0;L;;;;;N;;;;;
-282E;BRAILLE PATTERN DOTS-2346;So;0;L;;;;;N;;;;;
-282F;BRAILLE PATTERN DOTS-12346;So;0;L;;;;;N;;;;;
-2830;BRAILLE PATTERN DOTS-56;So;0;L;;;;;N;;;;;
-2831;BRAILLE PATTERN DOTS-156;So;0;L;;;;;N;;;;;
-2832;BRAILLE PATTERN DOTS-256;So;0;L;;;;;N;;;;;
-2833;BRAILLE PATTERN DOTS-1256;So;0;L;;;;;N;;;;;
-2834;BRAILLE PATTERN DOTS-356;So;0;L;;;;;N;;;;;
-2835;BRAILLE PATTERN DOTS-1356;So;0;L;;;;;N;;;;;
-2836;BRAILLE PATTERN DOTS-2356;So;0;L;;;;;N;;;;;
-2837;BRAILLE PATTERN DOTS-12356;So;0;L;;;;;N;;;;;
-2838;BRAILLE PATTERN DOTS-456;So;0;L;;;;;N;;;;;
-2839;BRAILLE PATTERN DOTS-1456;So;0;L;;;;;N;;;;;
-283A;BRAILLE PATTERN DOTS-2456;So;0;L;;;;;N;;;;;
-283B;BRAILLE PATTERN DOTS-12456;So;0;L;;;;;N;;;;;
-283C;BRAILLE PATTERN DOTS-3456;So;0;L;;;;;N;;;;;
-283D;BRAILLE PATTERN DOTS-13456;So;0;L;;;;;N;;;;;
-283E;BRAILLE PATTERN DOTS-23456;So;0;L;;;;;N;;;;;
-283F;BRAILLE PATTERN DOTS-123456;So;0;L;;;;;N;;;;;
-2840;BRAILLE PATTERN DOTS-7;So;0;L;;;;;N;;;;;
-2841;BRAILLE PATTERN DOTS-17;So;0;L;;;;;N;;;;;
-2842;BRAILLE PATTERN DOTS-27;So;0;L;;;;;N;;;;;
-2843;BRAILLE PATTERN DOTS-127;So;0;L;;;;;N;;;;;
-2844;BRAILLE PATTERN DOTS-37;So;0;L;;;;;N;;;;;
-2845;BRAILLE PATTERN DOTS-137;So;0;L;;;;;N;;;;;
-2846;BRAILLE PATTERN DOTS-237;So;0;L;;;;;N;;;;;
-2847;BRAILLE PATTERN DOTS-1237;So;0;L;;;;;N;;;;;
-2848;BRAILLE PATTERN DOTS-47;So;0;L;;;;;N;;;;;
-2849;BRAILLE PATTERN DOTS-147;So;0;L;;;;;N;;;;;
-284A;BRAILLE PATTERN DOTS-247;So;0;L;;;;;N;;;;;
-284B;BRAILLE PATTERN DOTS-1247;So;0;L;;;;;N;;;;;
-284C;BRAILLE PATTERN DOTS-347;So;0;L;;;;;N;;;;;
-284D;BRAILLE PATTERN DOTS-1347;So;0;L;;;;;N;;;;;
-284E;BRAILLE PATTERN DOTS-2347;So;0;L;;;;;N;;;;;
-284F;BRAILLE PATTERN DOTS-12347;So;0;L;;;;;N;;;;;
-2850;BRAILLE PATTERN DOTS-57;So;0;L;;;;;N;;;;;
-2851;BRAILLE PATTERN DOTS-157;So;0;L;;;;;N;;;;;
-2852;BRAILLE PATTERN DOTS-257;So;0;L;;;;;N;;;;;
-2853;BRAILLE PATTERN DOTS-1257;So;0;L;;;;;N;;;;;
-2854;BRAILLE PATTERN DOTS-357;So;0;L;;;;;N;;;;;
-2855;BRAILLE PATTERN DOTS-1357;So;0;L;;;;;N;;;;;
-2856;BRAILLE PATTERN DOTS-2357;So;0;L;;;;;N;;;;;
-2857;BRAILLE PATTERN DOTS-12357;So;0;L;;;;;N;;;;;
-2858;BRAILLE PATTERN DOTS-457;So;0;L;;;;;N;;;;;
-2859;BRAILLE PATTERN DOTS-1457;So;0;L;;;;;N;;;;;
-285A;BRAILLE PATTERN DOTS-2457;So;0;L;;;;;N;;;;;
-285B;BRAILLE PATTERN DOTS-12457;So;0;L;;;;;N;;;;;
-285C;BRAILLE PATTERN DOTS-3457;So;0;L;;;;;N;;;;;
-285D;BRAILLE PATTERN DOTS-13457;So;0;L;;;;;N;;;;;
-285E;BRAILLE PATTERN DOTS-23457;So;0;L;;;;;N;;;;;
-285F;BRAILLE PATTERN DOTS-123457;So;0;L;;;;;N;;;;;
-2860;BRAILLE PATTERN DOTS-67;So;0;L;;;;;N;;;;;
-2861;BRAILLE PATTERN DOTS-167;So;0;L;;;;;N;;;;;
-2862;BRAILLE PATTERN DOTS-267;So;0;L;;;;;N;;;;;
-2863;BRAILLE PATTERN DOTS-1267;So;0;L;;;;;N;;;;;
-2864;BRAILLE PATTERN DOTS-367;So;0;L;;;;;N;;;;;
-2865;BRAILLE PATTERN DOTS-1367;So;0;L;;;;;N;;;;;
-2866;BRAILLE PATTERN DOTS-2367;So;0;L;;;;;N;;;;;
-2867;BRAILLE PATTERN DOTS-12367;So;0;L;;;;;N;;;;;
-2868;BRAILLE PATTERN DOTS-467;So;0;L;;;;;N;;;;;
-2869;BRAILLE PATTERN DOTS-1467;So;0;L;;;;;N;;;;;
-286A;BRAILLE PATTERN DOTS-2467;So;0;L;;;;;N;;;;;
-286B;BRAILLE PATTERN DOTS-12467;So;0;L;;;;;N;;;;;
-286C;BRAILLE PATTERN DOTS-3467;So;0;L;;;;;N;;;;;
-286D;BRAILLE PATTERN DOTS-13467;So;0;L;;;;;N;;;;;
-286E;BRAILLE PATTERN DOTS-23467;So;0;L;;;;;N;;;;;
-286F;BRAILLE PATTERN DOTS-123467;So;0;L;;;;;N;;;;;
-2870;BRAILLE PATTERN DOTS-567;So;0;L;;;;;N;;;;;
-2871;BRAILLE PATTERN DOTS-1567;So;0;L;;;;;N;;;;;
-2872;BRAILLE PATTERN DOTS-2567;So;0;L;;;;;N;;;;;
-2873;BRAILLE PATTERN DOTS-12567;So;0;L;;;;;N;;;;;
-2874;BRAILLE PATTERN DOTS-3567;So;0;L;;;;;N;;;;;
-2875;BRAILLE PATTERN DOTS-13567;So;0;L;;;;;N;;;;;
-2876;BRAILLE PATTERN DOTS-23567;So;0;L;;;;;N;;;;;
-2877;BRAILLE PATTERN DOTS-123567;So;0;L;;;;;N;;;;;
-2878;BRAILLE PATTERN DOTS-4567;So;0;L;;;;;N;;;;;
-2879;BRAILLE PATTERN DOTS-14567;So;0;L;;;;;N;;;;;
-287A;BRAILLE PATTERN DOTS-24567;So;0;L;;;;;N;;;;;
-287B;BRAILLE PATTERN DOTS-124567;So;0;L;;;;;N;;;;;
-287C;BRAILLE PATTERN DOTS-34567;So;0;L;;;;;N;;;;;
-287D;BRAILLE PATTERN DOTS-134567;So;0;L;;;;;N;;;;;
-287E;BRAILLE PATTERN DOTS-234567;So;0;L;;;;;N;;;;;
-287F;BRAILLE PATTERN DOTS-1234567;So;0;L;;;;;N;;;;;
-2880;BRAILLE PATTERN DOTS-8;So;0;L;;;;;N;;;;;
-2881;BRAILLE PATTERN DOTS-18;So;0;L;;;;;N;;;;;
-2882;BRAILLE PATTERN DOTS-28;So;0;L;;;;;N;;;;;
-2883;BRAILLE PATTERN DOTS-128;So;0;L;;;;;N;;;;;
-2884;BRAILLE PATTERN DOTS-38;So;0;L;;;;;N;;;;;
-2885;BRAILLE PATTERN DOTS-138;So;0;L;;;;;N;;;;;
-2886;BRAILLE PATTERN DOTS-238;So;0;L;;;;;N;;;;;
-2887;BRAILLE PATTERN DOTS-1238;So;0;L;;;;;N;;;;;
-2888;BRAILLE PATTERN DOTS-48;So;0;L;;;;;N;;;;;
-2889;BRAILLE PATTERN DOTS-148;So;0;L;;;;;N;;;;;
-288A;BRAILLE PATTERN DOTS-248;So;0;L;;;;;N;;;;;
-288B;BRAILLE PATTERN DOTS-1248;So;0;L;;;;;N;;;;;
-288C;BRAILLE PATTERN DOTS-348;So;0;L;;;;;N;;;;;
-288D;BRAILLE PATTERN DOTS-1348;So;0;L;;;;;N;;;;;
-288E;BRAILLE PATTERN DOTS-2348;So;0;L;;;;;N;;;;;
-288F;BRAILLE PATTERN DOTS-12348;So;0;L;;;;;N;;;;;
-2890;BRAILLE PATTERN DOTS-58;So;0;L;;;;;N;;;;;
-2891;BRAILLE PATTERN DOTS-158;So;0;L;;;;;N;;;;;
-2892;BRAILLE PATTERN DOTS-258;So;0;L;;;;;N;;;;;
-2893;BRAILLE PATTERN DOTS-1258;So;0;L;;;;;N;;;;;
-2894;BRAILLE PATTERN DOTS-358;So;0;L;;;;;N;;;;;
-2895;BRAILLE PATTERN DOTS-1358;So;0;L;;;;;N;;;;;
-2896;BRAILLE PATTERN DOTS-2358;So;0;L;;;;;N;;;;;
-2897;BRAILLE PATTERN DOTS-12358;So;0;L;;;;;N;;;;;
-2898;BRAILLE PATTERN DOTS-458;So;0;L;;;;;N;;;;;
-2899;BRAILLE PATTERN DOTS-1458;So;0;L;;;;;N;;;;;
-289A;BRAILLE PATTERN DOTS-2458;So;0;L;;;;;N;;;;;
-289B;BRAILLE PATTERN DOTS-12458;So;0;L;;;;;N;;;;;
-289C;BRAILLE PATTERN DOTS-3458;So;0;L;;;;;N;;;;;
-289D;BRAILLE PATTERN DOTS-13458;So;0;L;;;;;N;;;;;
-289E;BRAILLE PATTERN DOTS-23458;So;0;L;;;;;N;;;;;
-289F;BRAILLE PATTERN DOTS-123458;So;0;L;;;;;N;;;;;
-28A0;BRAILLE PATTERN DOTS-68;So;0;L;;;;;N;;;;;
-28A1;BRAILLE PATTERN DOTS-168;So;0;L;;;;;N;;;;;
-28A2;BRAILLE PATTERN DOTS-268;So;0;L;;;;;N;;;;;
-28A3;BRAILLE PATTERN DOTS-1268;So;0;L;;;;;N;;;;;
-28A4;BRAILLE PATTERN DOTS-368;So;0;L;;;;;N;;;;;
-28A5;BRAILLE PATTERN DOTS-1368;So;0;L;;;;;N;;;;;
-28A6;BRAILLE PATTERN DOTS-2368;So;0;L;;;;;N;;;;;
-28A7;BRAILLE PATTERN DOTS-12368;So;0;L;;;;;N;;;;;
-28A8;BRAILLE PATTERN DOTS-468;So;0;L;;;;;N;;;;;
-28A9;BRAILLE PATTERN DOTS-1468;So;0;L;;;;;N;;;;;
-28AA;BRAILLE PATTERN DOTS-2468;So;0;L;;;;;N;;;;;
-28AB;BRAILLE PATTERN DOTS-12468;So;0;L;;;;;N;;;;;
-28AC;BRAILLE PATTERN DOTS-3468;So;0;L;;;;;N;;;;;
-28AD;BRAILLE PATTERN DOTS-13468;So;0;L;;;;;N;;;;;
-28AE;BRAILLE PATTERN DOTS-23468;So;0;L;;;;;N;;;;;
-28AF;BRAILLE PATTERN DOTS-123468;So;0;L;;;;;N;;;;;
-28B0;BRAILLE PATTERN DOTS-568;So;0;L;;;;;N;;;;;
-28B1;BRAILLE PATTERN DOTS-1568;So;0;L;;;;;N;;;;;
-28B2;BRAILLE PATTERN DOTS-2568;So;0;L;;;;;N;;;;;
-28B3;BRAILLE PATTERN DOTS-12568;So;0;L;;;;;N;;;;;
-28B4;BRAILLE PATTERN DOTS-3568;So;0;L;;;;;N;;;;;
-28B5;BRAILLE PATTERN DOTS-13568;So;0;L;;;;;N;;;;;
-28B6;BRAILLE PATTERN DOTS-23568;So;0;L;;;;;N;;;;;
-28B7;BRAILLE PATTERN DOTS-123568;So;0;L;;;;;N;;;;;
-28B8;BRAILLE PATTERN DOTS-4568;So;0;L;;;;;N;;;;;
-28B9;BRAILLE PATTERN DOTS-14568;So;0;L;;;;;N;;;;;
-28BA;BRAILLE PATTERN DOTS-24568;So;0;L;;;;;N;;;;;
-28BB;BRAILLE PATTERN DOTS-124568;So;0;L;;;;;N;;;;;
-28BC;BRAILLE PATTERN DOTS-34568;So;0;L;;;;;N;;;;;
-28BD;BRAILLE PATTERN DOTS-134568;So;0;L;;;;;N;;;;;
-28BE;BRAILLE PATTERN DOTS-234568;So;0;L;;;;;N;;;;;
-28BF;BRAILLE PATTERN DOTS-1234568;So;0;L;;;;;N;;;;;
-28C0;BRAILLE PATTERN DOTS-78;So;0;L;;;;;N;;;;;
-28C1;BRAILLE PATTERN DOTS-178;So;0;L;;;;;N;;;;;
-28C2;BRAILLE PATTERN DOTS-278;So;0;L;;;;;N;;;;;
-28C3;BRAILLE PATTERN DOTS-1278;So;0;L;;;;;N;;;;;
-28C4;BRAILLE PATTERN DOTS-378;So;0;L;;;;;N;;;;;
-28C5;BRAILLE PATTERN DOTS-1378;So;0;L;;;;;N;;;;;
-28C6;BRAILLE PATTERN DOTS-2378;So;0;L;;;;;N;;;;;
-28C7;BRAILLE PATTERN DOTS-12378;So;0;L;;;;;N;;;;;
-28C8;BRAILLE PATTERN DOTS-478;So;0;L;;;;;N;;;;;
-28C9;BRAILLE PATTERN DOTS-1478;So;0;L;;;;;N;;;;;
-28CA;BRAILLE PATTERN DOTS-2478;So;0;L;;;;;N;;;;;
-28CB;BRAILLE PATTERN DOTS-12478;So;0;L;;;;;N;;;;;
-28CC;BRAILLE PATTERN DOTS-3478;So;0;L;;;;;N;;;;;
-28CD;BRAILLE PATTERN DOTS-13478;So;0;L;;;;;N;;;;;
-28CE;BRAILLE PATTERN DOTS-23478;So;0;L;;;;;N;;;;;
-28CF;BRAILLE PATTERN DOTS-123478;So;0;L;;;;;N;;;;;
-28D0;BRAILLE PATTERN DOTS-578;So;0;L;;;;;N;;;;;
-28D1;BRAILLE PATTERN DOTS-1578;So;0;L;;;;;N;;;;;
-28D2;BRAILLE PATTERN DOTS-2578;So;0;L;;;;;N;;;;;
-28D3;BRAILLE PATTERN DOTS-12578;So;0;L;;;;;N;;;;;
-28D4;BRAILLE PATTERN DOTS-3578;So;0;L;;;;;N;;;;;
-28D5;BRAILLE PATTERN DOTS-13578;So;0;L;;;;;N;;;;;
-28D6;BRAILLE PATTERN DOTS-23578;So;0;L;;;;;N;;;;;
-28D7;BRAILLE PATTERN DOTS-123578;So;0;L;;;;;N;;;;;
-28D8;BRAILLE PATTERN DOTS-4578;So;0;L;;;;;N;;;;;
-28D9;BRAILLE PATTERN DOTS-14578;So;0;L;;;;;N;;;;;
-28DA;BRAILLE PATTERN DOTS-24578;So;0;L;;;;;N;;;;;
-28DB;BRAILLE PATTERN DOTS-124578;So;0;L;;;;;N;;;;;
-28DC;BRAILLE PATTERN DOTS-34578;So;0;L;;;;;N;;;;;
-28DD;BRAILLE PATTERN DOTS-134578;So;0;L;;;;;N;;;;;
-28DE;BRAILLE PATTERN DOTS-234578;So;0;L;;;;;N;;;;;
-28DF;BRAILLE PATTERN DOTS-1234578;So;0;L;;;;;N;;;;;
-28E0;BRAILLE PATTERN DOTS-678;So;0;L;;;;;N;;;;;
-28E1;BRAILLE PATTERN DOTS-1678;So;0;L;;;;;N;;;;;
-28E2;BRAILLE PATTERN DOTS-2678;So;0;L;;;;;N;;;;;
-28E3;BRAILLE PATTERN DOTS-12678;So;0;L;;;;;N;;;;;
-28E4;BRAILLE PATTERN DOTS-3678;So;0;L;;;;;N;;;;;
-28E5;BRAILLE PATTERN DOTS-13678;So;0;L;;;;;N;;;;;
-28E6;BRAILLE PATTERN DOTS-23678;So;0;L;;;;;N;;;;;
-28E7;BRAILLE PATTERN DOTS-123678;So;0;L;;;;;N;;;;;
-28E8;BRAILLE PATTERN DOTS-4678;So;0;L;;;;;N;;;;;
-28E9;BRAILLE PATTERN DOTS-14678;So;0;L;;;;;N;;;;;
-28EA;BRAILLE PATTERN DOTS-24678;So;0;L;;;;;N;;;;;
-28EB;BRAILLE PATTERN DOTS-124678;So;0;L;;;;;N;;;;;
-28EC;BRAILLE PATTERN DOTS-34678;So;0;L;;;;;N;;;;;
-28ED;BRAILLE PATTERN DOTS-134678;So;0;L;;;;;N;;;;;
-28EE;BRAILLE PATTERN DOTS-234678;So;0;L;;;;;N;;;;;
-28EF;BRAILLE PATTERN DOTS-1234678;So;0;L;;;;;N;;;;;
-28F0;BRAILLE PATTERN DOTS-5678;So;0;L;;;;;N;;;;;
-28F1;BRAILLE PATTERN DOTS-15678;So;0;L;;;;;N;;;;;
-28F2;BRAILLE PATTERN DOTS-25678;So;0;L;;;;;N;;;;;
-28F3;BRAILLE PATTERN DOTS-125678;So;0;L;;;;;N;;;;;
-28F4;BRAILLE PATTERN DOTS-35678;So;0;L;;;;;N;;;;;
-28F5;BRAILLE PATTERN DOTS-135678;So;0;L;;;;;N;;;;;
-28F6;BRAILLE PATTERN DOTS-235678;So;0;L;;;;;N;;;;;
-28F7;BRAILLE PATTERN DOTS-1235678;So;0;L;;;;;N;;;;;
-28F8;BRAILLE PATTERN DOTS-45678;So;0;L;;;;;N;;;;;
-28F9;BRAILLE PATTERN DOTS-145678;So;0;L;;;;;N;;;;;
-28FA;BRAILLE PATTERN DOTS-245678;So;0;L;;;;;N;;;;;
-28FB;BRAILLE PATTERN DOTS-1245678;So;0;L;;;;;N;;;;;
-28FC;BRAILLE PATTERN DOTS-345678;So;0;L;;;;;N;;;;;
-28FD;BRAILLE PATTERN DOTS-1345678;So;0;L;;;;;N;;;;;
-28FE;BRAILLE PATTERN DOTS-2345678;So;0;L;;;;;N;;;;;
-28FF;BRAILLE PATTERN DOTS-12345678;So;0;L;;;;;N;;;;;
-2900;RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2901;RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2902;LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2903;RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2904;LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2905;RIGHTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
-2906;LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
-2907;RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
-2908;DOWNWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
-2909;UPWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
-290A;UPWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;;
-290B;DOWNWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;;
-290C;LEFTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
-290D;RIGHTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
-290E;LEFTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
-290F;RIGHTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
-2910;RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
-2911;RIGHTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;;
-2912;UPWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;;
-2913;DOWNWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;;
-2914;RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2915;RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2916;RIGHTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;;
-2917;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2918;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2919;LEFTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;;
-291A;RIGHTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;;
-291B;LEFTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;;
-291C;RIGHTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;;
-291D;LEFTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
-291E;RIGHTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
-291F;LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
-2920;RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
-2921;NORTH WEST AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
-2922;NORTH EAST AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;;
-2923;NORTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;;
-2924;NORTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;;
-2925;SOUTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;;
-2926;SOUTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;;
-2927;NORTH WEST ARROW AND NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
-2928;NORTH EAST ARROW AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
-2929;SOUTH EAST ARROW AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;;
-292A;SOUTH WEST ARROW AND NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;;
-292B;RISING DIAGONAL CROSSING FALLING DIAGONAL;Sm;0;ON;;;;;N;;;;;
-292C;FALLING DIAGONAL CROSSING RISING DIAGONAL;Sm;0;ON;;;;;N;;;;;
-292D;SOUTH EAST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
-292E;NORTH EAST ARROW CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
-292F;FALLING DIAGONAL CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
-2930;RISING DIAGONAL CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
-2931;NORTH EAST ARROW CROSSING NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;;
-2932;NORTH WEST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
-2933;WAVE ARROW POINTING DIRECTLY RIGHT;Sm;0;ON;;;;;N;;;;;
-2934;ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS;Sm;0;ON;;;;;N;;;;;
-2935;ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS;Sm;0;ON;;;;;N;;;;;
-2936;ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS;Sm;0;ON;;;;;N;;;;;
-2937;ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS;Sm;0;ON;;;;;N;;;;;
-2938;RIGHT-SIDE ARC CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
-2939;LEFT-SIDE ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
-293A;TOP ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
-293B;BOTTOM ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
-293C;TOP ARC CLOCKWISE ARROW WITH MINUS;Sm;0;ON;;;;;N;;;;;
-293D;TOP ARC ANTICLOCKWISE ARROW WITH PLUS;Sm;0;ON;;;;;N;;;;;
-293E;LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
-293F;LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
-2940;ANTICLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;;
-2941;CLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;;
-2942;RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2943;LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2944;SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2945;RIGHTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;;
-2946;LEFTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;;
-2947;RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;;
-2948;LEFT RIGHT ARROW THROUGH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
-2949;UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
-294A;LEFT BARB UP RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;;
-294B;LEFT BARB DOWN RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;;
-294C;UP BARB RIGHT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;;
-294D;UP BARB LEFT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;;
-294E;LEFT BARB UP RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;;
-294F;UP BARB RIGHT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;;
-2950;LEFT BARB DOWN RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;;
-2951;UP BARB LEFT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;;
-2952;LEFTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;;
-2953;RIGHTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;;
-2954;UPWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;;
-2955;DOWNWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;;
-2956;LEFTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;;
-2957;RIGHTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;;
-2958;UPWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;;
-2959;DOWNWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;;
-295A;LEFTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;;
-295B;RIGHTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;;
-295C;UPWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;;
-295D;DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;;
-295E;LEFTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;;
-295F;RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;;
-2960;UPWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;;
-2961;DOWNWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;;
-2962;LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;;
-2963;UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;;
-2964;RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;;
-2965;DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;;
-2966;LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;;
-2967;LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;;
-2968;RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;;
-2969;RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;;
-296A;LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;;
-296B;LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;;
-296C;RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;;
-296D;RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;;
-296E;UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;;
-296F;DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;;
-2970;RIGHT DOUBLE ARROW WITH ROUNDED HEAD;Sm;0;ON;;;;;N;;;;;
-2971;EQUALS SIGN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2972;TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2973;LEFTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;;
-2974;RIGHTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;;
-2975;RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;;
-2976;LESS-THAN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2977;LEFTWARDS ARROW THROUGH LESS-THAN;Sm;0;ON;;;;;N;;;;;
-2978;GREATER-THAN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2979;SUBSET ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-297A;LEFTWARDS ARROW THROUGH SUBSET;Sm;0;ON;;;;;N;;;;;
-297B;SUPERSET ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-297C;LEFT FISH TAIL;Sm;0;ON;;;;;N;;;;;
-297D;RIGHT FISH TAIL;Sm;0;ON;;;;;N;;;;;
-297E;UP FISH TAIL;Sm;0;ON;;;;;N;;;;;
-297F;DOWN FISH TAIL;Sm;0;ON;;;;;N;;;;;
-2980;TRIPLE VERTICAL BAR DELIMITER;Sm;0;ON;;;;;N;;;;;
-2981;Z NOTATION SPOT;Sm;0;ON;;;;;N;;;;;
-2982;Z NOTATION TYPE COLON;Sm;0;ON;;;;;N;;;;;
-2983;LEFT WHITE CURLY BRACKET;Ps;0;ON;;;;;Y;;;;;
-2984;RIGHT WHITE CURLY BRACKET;Pe;0;ON;;;;;Y;;;;;
-2985;LEFT WHITE PARENTHESIS;Ps;0;ON;;;;;Y;;;;;
-2986;RIGHT WHITE PARENTHESIS;Pe;0;ON;;;;;Y;;;;;
-2987;Z NOTATION LEFT IMAGE BRACKET;Ps;0;ON;;;;;Y;;;;;
-2988;Z NOTATION RIGHT IMAGE BRACKET;Pe;0;ON;;;;;Y;;;;;
-2989;Z NOTATION LEFT BINDING BRACKET;Ps;0;ON;;;;;Y;;;;;
-298A;Z NOTATION RIGHT BINDING BRACKET;Pe;0;ON;;;;;Y;;;;;
-298B;LEFT SQUARE BRACKET WITH UNDERBAR;Ps;0;ON;;;;;Y;;;;;
-298C;RIGHT SQUARE BRACKET WITH UNDERBAR;Pe;0;ON;;;;;Y;;;;;
-298D;LEFT SQUARE BRACKET WITH TICK IN TOP CORNER;Ps;0;ON;;;;;Y;;;;;
-298E;RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Pe;0;ON;;;;;Y;;;;;
-298F;LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Ps;0;ON;;;;;Y;;;;;
-2990;RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER;Pe;0;ON;;;;;Y;;;;;
-2991;LEFT ANGLE BRACKET WITH DOT;Ps;0;ON;;;;;Y;;;;;
-2992;RIGHT ANGLE BRACKET WITH DOT;Pe;0;ON;;;;;Y;;;;;
-2993;LEFT ARC LESS-THAN BRACKET;Ps;0;ON;;;;;Y;;;;;
-2994;RIGHT ARC GREATER-THAN BRACKET;Pe;0;ON;;;;;Y;;;;;
-2995;DOUBLE LEFT ARC GREATER-THAN BRACKET;Ps;0;ON;;;;;Y;;;;;
-2996;DOUBLE RIGHT ARC LESS-THAN BRACKET;Pe;0;ON;;;;;Y;;;;;
-2997;LEFT BLACK TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;;
-2998;RIGHT BLACK TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;;
-2999;DOTTED FENCE;Sm;0;ON;;;;;N;;;;;
-299A;VERTICAL ZIGZAG LINE;Sm;0;ON;;;;;N;;;;;
-299B;MEASURED ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;;
-299C;RIGHT ANGLE VARIANT WITH SQUARE;Sm;0;ON;;;;;Y;;;;;
-299D;MEASURED RIGHT ANGLE WITH DOT;Sm;0;ON;;;;;Y;;;;;
-299E;ANGLE WITH S INSIDE;Sm;0;ON;;;;;Y;;;;;
-299F;ACUTE ANGLE;Sm;0;ON;;;;;Y;;;;;
-29A0;SPHERICAL ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;;
-29A1;SPHERICAL ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;;
-29A2;TURNED ANGLE;Sm;0;ON;;;;;Y;;;;;
-29A3;REVERSED ANGLE;Sm;0;ON;;;;;Y;;;;;
-29A4;ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
-29A5;REVERSED ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
-29A6;OBLIQUE ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;;
-29A7;OBLIQUE ANGLE OPENING DOWN;Sm;0;ON;;;;;Y;;;;;
-29A8;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT;Sm;0;ON;;;;;Y;;;;;
-29A9;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT;Sm;0;ON;;;;;Y;;;;;
-29AA;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT;Sm;0;ON;;;;;Y;;;;;
-29AB;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT;Sm;0;ON;;;;;Y;;;;;
-29AC;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP;Sm;0;ON;;;;;Y;;;;;
-29AD;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP;Sm;0;ON;;;;;Y;;;;;
-29AE;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN;Sm;0;ON;;;;;Y;;;;;
-29AF;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN;Sm;0;ON;;;;;Y;;;;;
-29B0;REVERSED EMPTY SET;Sm;0;ON;;;;;N;;;;;
-29B1;EMPTY SET WITH OVERBAR;Sm;0;ON;;;;;N;;;;;
-29B2;EMPTY SET WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;;
-29B3;EMPTY SET WITH RIGHT ARROW ABOVE;Sm;0;ON;;;;;N;;;;;
-29B4;EMPTY SET WITH LEFT ARROW ABOVE;Sm;0;ON;;;;;N;;;;;
-29B5;CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;;
-29B6;CIRCLED VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
-29B7;CIRCLED PARALLEL;Sm;0;ON;;;;;N;;;;;
-29B8;CIRCLED REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;;
-29B9;CIRCLED PERPENDICULAR;Sm;0;ON;;;;;N;;;;;
-29BA;CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
-29BB;CIRCLE WITH SUPERIMPOSED X;Sm;0;ON;;;;;N;;;;;
-29BC;CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN;Sm;0;ON;;;;;N;;;;;
-29BD;UP ARROW THROUGH CIRCLE;Sm;0;ON;;;;;N;;;;;
-29BE;CIRCLED WHITE BULLET;Sm;0;ON;;;;;N;;;;;
-29BF;CIRCLED BULLET;Sm;0;ON;;;;;N;;;;;
-29C0;CIRCLED LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-29C1;CIRCLED GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-29C2;CIRCLE WITH SMALL CIRCLE TO THE RIGHT;Sm;0;ON;;;;;Y;;;;;
-29C3;CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT;Sm;0;ON;;;;;Y;;;;;
-29C4;SQUARED RISING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;;
-29C5;SQUARED FALLING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;;
-29C6;SQUARED ASTERISK;Sm;0;ON;;;;;N;;;;;
-29C7;SQUARED SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
-29C8;SQUARED SQUARE;Sm;0;ON;;;;;N;;;;;
-29C9;TWO JOINED SQUARES;Sm;0;ON;;;;;Y;;;;;
-29CA;TRIANGLE WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
-29CB;TRIANGLE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
-29CC;S IN TRIANGLE;Sm;0;ON;;;;;N;;;;;
-29CD;TRIANGLE WITH SERIFS AT BOTTOM;Sm;0;ON;;;;;N;;;;;
-29CE;RIGHT TRIANGLE ABOVE LEFT TRIANGLE;Sm;0;ON;;;;;Y;;;;;
-29CF;LEFT TRIANGLE BESIDE VERTICAL BAR;Sm;0;ON;;;;;Y;;;;;
-29D0;VERTICAL BAR BESIDE RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;;
-29D1;BOWTIE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
-29D2;BOWTIE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
-29D3;BLACK BOWTIE;Sm;0;ON;;;;;N;;;;;
-29D4;TIMES WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
-29D5;TIMES WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
-29D6;WHITE HOURGLASS;Sm;0;ON;;;;;N;;;;;
-29D7;BLACK HOURGLASS;Sm;0;ON;;;;;N;;;;;
-29D8;LEFT WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;;
-29D9;RIGHT WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;;
-29DA;LEFT DOUBLE WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;;
-29DB;RIGHT DOUBLE WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;;
-29DC;INCOMPLETE INFINITY;Sm;0;ON;;;;;Y;;;;;
-29DD;TIE OVER INFINITY;Sm;0;ON;;;;;N;;;;;
-29DE;INFINITY NEGATED WITH VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
-29DF;DOUBLE-ENDED MULTIMAP;Sm;0;ON;;;;;N;;;;;
-29E0;SQUARE WITH CONTOURED OUTLINE;Sm;0;ON;;;;;N;;;;;
-29E1;INCREASES AS;Sm;0;ON;;;;;Y;;;;;
-29E2;SHUFFLE PRODUCT;Sm;0;ON;;;;;N;;;;;
-29E3;EQUALS SIGN AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;;
-29E4;EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;;
-29E5;IDENTICAL TO AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;;
-29E6;GLEICH STARK;Sm;0;ON;;;;;N;;;;;
-29E7;THERMODYNAMIC;Sm;0;ON;;;;;N;;;;;
-29E8;DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
-29E9;DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
-29EA;BLACK DIAMOND WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;;
-29EB;BLACK LOZENGE;Sm;0;ON;;;;;N;;;;;
-29EC;WHITE CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;;
-29ED;BLACK CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;;
-29EE;ERROR-BARRED WHITE SQUARE;Sm;0;ON;;;;;N;;;;;
-29EF;ERROR-BARRED BLACK SQUARE;Sm;0;ON;;;;;N;;;;;
-29F0;ERROR-BARRED WHITE DIAMOND;Sm;0;ON;;;;;N;;;;;
-29F1;ERROR-BARRED BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
-29F2;ERROR-BARRED WHITE CIRCLE;Sm;0;ON;;;;;N;;;;;
-29F3;ERROR-BARRED BLACK CIRCLE;Sm;0;ON;;;;;N;;;;;
-29F4;RULE-DELAYED;Sm;0;ON;;;;;Y;;;;;
-29F5;REVERSE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;;
-29F6;SOLIDUS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
-29F7;REVERSE SOLIDUS WITH HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
-29F8;BIG SOLIDUS;Sm;0;ON;;;;;Y;;;;;
-29F9;BIG REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;;
-29FA;DOUBLE PLUS;Sm;0;ON;;;;;N;;;;;
-29FB;TRIPLE PLUS;Sm;0;ON;;;;;N;;;;;
-29FC;LEFT-POINTING CURVED ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;;
-29FD;RIGHT-POINTING CURVED ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;;
-29FE;TINY;Sm;0;ON;;;;;N;;;;;
-29FF;MINY;Sm;0;ON;;;;;N;;;;;
-2A00;N-ARY CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;;
-2A01;N-ARY CIRCLED PLUS OPERATOR;Sm;0;ON;;;;;N;;;;;
-2A02;N-ARY CIRCLED TIMES OPERATOR;Sm;0;ON;;;;;N;;;;;
-2A03;N-ARY UNION OPERATOR WITH DOT;Sm;0;ON;;;;;N;;;;;
-2A04;N-ARY UNION OPERATOR WITH PLUS;Sm;0;ON;;;;;N;;;;;
-2A05;N-ARY SQUARE INTERSECTION OPERATOR;Sm;0;ON;;;;;N;;;;;
-2A06;N-ARY SQUARE UNION OPERATOR;Sm;0;ON;;;;;N;;;;;
-2A07;TWO LOGICAL AND OPERATOR;Sm;0;ON;;;;;N;;;;;
-2A08;TWO LOGICAL OR OPERATOR;Sm;0;ON;;;;;N;;;;;
-2A09;N-ARY TIMES OPERATOR;Sm;0;ON;;;;;N;;;;;
-2A0A;MODULO TWO SUM;Sm;0;ON;;;;;Y;;;;;
-2A0B;SUMMATION WITH INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-2A0C;QUADRUPLE INTEGRAL OPERATOR;Sm;0;ON;<compat> 222B 222B 222B 222B;;;;Y;;;;;
-2A0D;FINITE PART INTEGRAL;Sm;0;ON;;;;;Y;;;;;
-2A0E;INTEGRAL WITH DOUBLE STROKE;Sm;0;ON;;;;;Y;;;;;
-2A0F;INTEGRAL AVERAGE WITH SLASH;Sm;0;ON;;;;;Y;;;;;
-2A10;CIRCULATION FUNCTION;Sm;0;ON;;;;;Y;;;;;
-2A11;ANTICLOCKWISE INTEGRATION;Sm;0;ON;;;;;Y;;;;;
-2A12;LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;;
-2A13;LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;;
-2A14;LINE INTEGRATION NOT INCLUDING THE POLE;Sm;0;ON;;;;;Y;;;;;
-2A15;INTEGRAL AROUND A POINT OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2A16;QUATERNION INTEGRAL OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2A17;INTEGRAL WITH LEFTWARDS ARROW WITH HOOK;Sm;0;ON;;;;;Y;;;;;
-2A18;INTEGRAL WITH TIMES SIGN;Sm;0;ON;;;;;Y;;;;;
-2A19;INTEGRAL WITH INTERSECTION;Sm;0;ON;;;;;Y;;;;;
-2A1A;INTEGRAL WITH UNION;Sm;0;ON;;;;;Y;;;;;
-2A1B;INTEGRAL WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
-2A1C;INTEGRAL WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
-2A1D;JOIN;Sm;0;ON;;;;;N;;;;;
-2A1E;LARGE LEFT TRIANGLE OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2A1F;Z NOTATION SCHEMA COMPOSITION;Sm;0;ON;;;;;Y;;;;;
-2A20;Z NOTATION SCHEMA PIPING;Sm;0;ON;;;;;Y;;;;;
-2A21;Z NOTATION SCHEMA PROJECTION;Sm;0;ON;;;;;Y;;;;;
-2A22;PLUS SIGN WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;;
-2A23;PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE;Sm;0;ON;;;;;N;;;;;
-2A24;PLUS SIGN WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;;
-2A25;PLUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;;
-2A26;PLUS SIGN WITH TILDE BELOW;Sm;0;ON;;;;;Y;;;;;
-2A27;PLUS SIGN WITH SUBSCRIPT TWO;Sm;0;ON;;;;;N;;;;;
-2A28;PLUS SIGN WITH BLACK TRIANGLE;Sm;0;ON;;;;;N;;;;;
-2A29;MINUS SIGN WITH COMMA ABOVE;Sm;0;ON;;;;;Y;;;;;
-2A2A;MINUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;;
-2A2B;MINUS SIGN WITH FALLING DOTS;Sm;0;ON;;;;;Y;;;;;
-2A2C;MINUS SIGN WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;;
-2A2D;PLUS SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;;
-2A2E;PLUS SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;;
-2A2F;VECTOR OR CROSS PRODUCT;Sm;0;ON;;;;;N;;;;;
-2A30;MULTIPLICATION SIGN WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
-2A31;MULTIPLICATION SIGN WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
-2A32;SEMIDIRECT PRODUCT WITH BOTTOM CLOSED;Sm;0;ON;;;;;N;;;;;
-2A33;SMASH PRODUCT;Sm;0;ON;;;;;N;;;;;
-2A34;MULTIPLICATION SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;;
-2A35;MULTIPLICATION SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;;
-2A36;CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;N;;;;;
-2A37;MULTIPLICATION SIGN IN DOUBLE CIRCLE;Sm;0;ON;;;;;N;;;;;
-2A38;CIRCLED DIVISION SIGN;Sm;0;ON;;;;;N;;;;;
-2A39;PLUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;;
-2A3A;MINUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;;
-2A3B;MULTIPLICATION SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;;
-2A3C;INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;;
-2A3D;RIGHTHAND INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;;
-2A3E;Z NOTATION RELATIONAL COMPOSITION;Sm;0;ON;;;;;Y;;;;;
-2A3F;AMALGAMATION OR COPRODUCT;Sm;0;ON;;;;;N;;;;;
-2A40;INTERSECTION WITH DOT;Sm;0;ON;;;;;N;;;;;
-2A41;UNION WITH MINUS SIGN;Sm;0;ON;;;;;N;;;;;
-2A42;UNION WITH OVERBAR;Sm;0;ON;;;;;N;;;;;
-2A43;INTERSECTION WITH OVERBAR;Sm;0;ON;;;;;N;;;;;
-2A44;INTERSECTION WITH LOGICAL AND;Sm;0;ON;;;;;N;;;;;
-2A45;UNION WITH LOGICAL OR;Sm;0;ON;;;;;N;;;;;
-2A46;UNION ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;;
-2A47;INTERSECTION ABOVE UNION;Sm;0;ON;;;;;N;;;;;
-2A48;UNION ABOVE BAR ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;;
-2A49;INTERSECTION ABOVE BAR ABOVE UNION;Sm;0;ON;;;;;N;;;;;
-2A4A;UNION BESIDE AND JOINED WITH UNION;Sm;0;ON;;;;;N;;;;;
-2A4B;INTERSECTION BESIDE AND JOINED WITH INTERSECTION;Sm;0;ON;;;;;N;;;;;
-2A4C;CLOSED UNION WITH SERIFS;Sm;0;ON;;;;;N;;;;;
-2A4D;CLOSED INTERSECTION WITH SERIFS;Sm;0;ON;;;;;N;;;;;
-2A4E;DOUBLE SQUARE INTERSECTION;Sm;0;ON;;;;;N;;;;;
-2A4F;DOUBLE SQUARE UNION;Sm;0;ON;;;;;N;;;;;
-2A50;CLOSED UNION WITH SERIFS AND SMASH PRODUCT;Sm;0;ON;;;;;N;;;;;
-2A51;LOGICAL AND WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
-2A52;LOGICAL OR WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
-2A53;DOUBLE LOGICAL AND;Sm;0;ON;;;;;N;;;;;
-2A54;DOUBLE LOGICAL OR;Sm;0;ON;;;;;N;;;;;
-2A55;TWO INTERSECTING LOGICAL AND;Sm;0;ON;;;;;N;;;;;
-2A56;TWO INTERSECTING LOGICAL OR;Sm;0;ON;;;;;N;;;;;
-2A57;SLOPING LARGE OR;Sm;0;ON;;;;;Y;;;;;
-2A58;SLOPING LARGE AND;Sm;0;ON;;;;;Y;;;;;
-2A59;LOGICAL OR OVERLAPPING LOGICAL AND;Sm;0;ON;;;;;N;;;;;
-2A5A;LOGICAL AND WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;;
-2A5B;LOGICAL OR WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;;
-2A5C;LOGICAL AND WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;;
-2A5D;LOGICAL OR WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;;
-2A5E;LOGICAL AND WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;;
-2A5F;LOGICAL AND WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
-2A60;LOGICAL AND WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;;
-2A61;SMALL VEE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
-2A62;LOGICAL OR WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;;
-2A63;LOGICAL OR WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;;
-2A64;Z NOTATION DOMAIN ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;;
-2A65;Z NOTATION RANGE ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;;
-2A66;EQUALS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;;
-2A67;IDENTICAL WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
-2A68;TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2A69;TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2A6A;TILDE OPERATOR WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
-2A6B;TILDE OPERATOR WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;;
-2A6C;SIMILAR MINUS SIMILAR;Sm;0;ON;;;;;Y;;;;;
-2A6D;CONGRUENT WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
-2A6E;EQUALS WITH ASTERISK;Sm;0;ON;;;;;N;;;;;
-2A6F;ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;Y;;;;;
-2A70;APPROXIMATELY EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2A71;EQUALS SIGN ABOVE PLUS SIGN;Sm;0;ON;;;;;N;;;;;
-2A72;PLUS SIGN ABOVE EQUALS SIGN;Sm;0;ON;;;;;N;;;;;
-2A73;EQUALS SIGN ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2A74;DOUBLE COLON EQUAL;Sm;0;ON;<compat> 003A 003A 003D;;;;Y;;;;;
-2A75;TWO CONSECUTIVE EQUALS SIGNS;Sm;0;ON;<compat> 003D 003D;;;;N;;;;;
-2A76;THREE CONSECUTIVE EQUALS SIGNS;Sm;0;ON;<compat> 003D 003D 003D;;;;N;;;;;
-2A77;EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW;Sm;0;ON;;;;;N;;;;;
-2A78;EQUIVALENT WITH FOUR DOTS ABOVE;Sm;0;ON;;;;;N;;;;;
-2A79;LESS-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;;
-2A7A;GREATER-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;;
-2A7B;LESS-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;;
-2A7C;GREATER-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;;
-2A7D;LESS-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2A7E;GREATER-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2A7F;LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;;
-2A80;GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;;
-2A81;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
-2A82;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
-2A83;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT;Sm;0;ON;;;;;Y;;;;;
-2A84;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT;Sm;0;ON;;;;;Y;;;;;
-2A85;LESS-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;;
-2A86;GREATER-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;;
-2A87;LESS-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2A88;GREATER-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2A89;LESS-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;;
-2A8A;GREATER-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;;
-2A8B;LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-2A8C;GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-2A8D;LESS-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;;
-2A8E;GREATER-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;;
-2A8F;LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-2A90;GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-2A91;LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;;
-2A92;GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;;
-2A93;LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;;
-2A94;GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;;
-2A95;SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-2A96;SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-2A97;SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;;
-2A98;SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;;
-2A99;DOUBLE-LINE EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-2A9A;DOUBLE-LINE EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-2A9B;DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-2A9C;DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-2A9D;SIMILAR OR LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-2A9E;SIMILAR OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-2A9F;SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
-2AA0;SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
-2AA1;DOUBLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-2AA2;DOUBLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-2AA3;DOUBLE NESTED LESS-THAN WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
-2AA4;GREATER-THAN OVERLAPPING LESS-THAN;Sm;0;ON;;;;;N;;;;;
-2AA5;GREATER-THAN BESIDE LESS-THAN;Sm;0;ON;;;;;N;;;;;
-2AA6;LESS-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;;
-2AA7;GREATER-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;;
-2AA8;LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;;
-2AA9;GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;;
-2AAA;SMALLER THAN;Sm;0;ON;;;;;Y;;;;;
-2AAB;LARGER THAN;Sm;0;ON;;;;;Y;;;;;
-2AAC;SMALLER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AAD;LARGER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AAE;EQUALS SIGN WITH BUMPY ABOVE;Sm;0;ON;;;;;N;;;;;
-2AAF;PRECEDES ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
-2AB0;SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
-2AB1;PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AB2;SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AB3;PRECEDES ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
-2AB4;SUCCEEDS ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
-2AB5;PRECEDES ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AB6;SUCCEEDS ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AB7;PRECEDES ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AB8;SUCCEEDS ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AB9;PRECEDES ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2ABA;SUCCEEDS ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2ABB;DOUBLE PRECEDES;Sm;0;ON;;;;;Y;;;;;
-2ABC;DOUBLE SUCCEEDS;Sm;0;ON;;;;;Y;;;;;
-2ABD;SUBSET WITH DOT;Sm;0;ON;;;;;Y;;;;;
-2ABE;SUPERSET WITH DOT;Sm;0;ON;;;;;Y;;;;;
-2ABF;SUBSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;;
-2AC0;SUPERSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;;
-2AC1;SUBSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;;
-2AC2;SUPERSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;;
-2AC3;SUBSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
-2AC4;SUPERSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
-2AC5;SUBSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
-2AC6;SUPERSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
-2AC7;SUBSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2AC8;SUPERSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2AC9;SUBSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2ACA;SUPERSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2ACB;SUBSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2ACC;SUPERSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2ACD;SQUARE LEFT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2ACE;SQUARE RIGHT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2ACF;CLOSED SUBSET;Sm;0;ON;;;;;Y;;;;;
-2AD0;CLOSED SUPERSET;Sm;0;ON;;;;;Y;;;;;
-2AD1;CLOSED SUBSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AD2;CLOSED SUPERSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AD3;SUBSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;;
-2AD4;SUPERSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;;
-2AD5;SUBSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;;
-2AD6;SUPERSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;;
-2AD7;SUPERSET BESIDE SUBSET;Sm;0;ON;;;;;N;;;;;
-2AD8;SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET;Sm;0;ON;;;;;N;;;;;
-2AD9;ELEMENT OF OPENING DOWNWARDS;Sm;0;ON;;;;;N;;;;;
-2ADA;PITCHFORK WITH TEE TOP;Sm;0;ON;;;;;N;;;;;
-2ADB;TRANSVERSAL INTERSECTION;Sm;0;ON;;;;;N;;;;;
-2ADC;FORKING;Sm;0;ON;2ADD 0338;;;;Y;;;;;
-2ADD;NONFORKING;Sm;0;ON;;;;;N;;;;;
-2ADE;SHORT LEFT TACK;Sm;0;ON;;;;;Y;;;;;
-2ADF;SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;;
-2AE0;SHORT UP TACK;Sm;0;ON;;;;;N;;;;;
-2AE1;PERPENDICULAR WITH S;Sm;0;ON;;;;;N;;;;;
-2AE2;VERTICAL BAR TRIPLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
-2AE3;DOUBLE VERTICAL BAR LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
-2AE4;VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
-2AE5;DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
-2AE6;LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL;Sm;0;ON;;;;;Y;;;;;
-2AE7;SHORT DOWN TACK WITH OVERBAR;Sm;0;ON;;;;;N;;;;;
-2AE8;SHORT UP TACK WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
-2AE9;SHORT UP TACK ABOVE SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;;
-2AEA;DOUBLE DOWN TACK;Sm;0;ON;;;;;N;;;;;
-2AEB;DOUBLE UP TACK;Sm;0;ON;;;;;N;;;;;
-2AEC;DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;;
-2AED;REVERSED DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;;
-2AEE;DOES NOT DIVIDE WITH REVERSED NEGATION SLASH;Sm;0;ON;;;;;Y;;;;;
-2AEF;VERTICAL LINE WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;;
-2AF0;VERTICAL LINE WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;;
-2AF1;DOWN TACK WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;;
-2AF2;PARALLEL WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
-2AF3;PARALLEL WITH TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2AF4;TRIPLE VERTICAL BAR BINARY RELATION;Sm;0;ON;;;;;N;;;;;
-2AF5;TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
-2AF6;TRIPLE COLON OPERATOR;Sm;0;ON;;;;;N;;;;;
-2AF7;TRIPLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;;
-2AF8;TRIPLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
-2AF9;DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AFA;DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
-2AFB;TRIPLE SOLIDUS BINARY RELATION;Sm;0;ON;;;;;Y;;;;;
-2AFC;LARGE TRIPLE VERTICAL BAR OPERATOR;Sm;0;ON;;;;;N;;;;;
-2AFD;DOUBLE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;;
-2AFE;WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
-2AFF;N-ARY WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
-2B00;NORTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;;
-2B01;NORTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;;
-2B02;SOUTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;;
-2B03;SOUTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;;
-2B04;LEFT RIGHT WHITE ARROW;So;0;ON;;;;;N;;;;;
-2B05;LEFTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B06;UPWARDS BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B07;DOWNWARDS BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B08;NORTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B09;NORTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B0A;SOUTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B0B;SOUTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B0C;LEFT RIGHT BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B0D;UP DOWN BLACK ARROW;So;0;ON;;;;;N;;;;;
-2B0E;RIGHTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;;
-2B0F;RIGHTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;;
-2B10;LEFTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;;
-2B11;LEFTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;;
-2B12;SQUARE WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;;
-2B13;SQUARE WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;;
-2B14;SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;;
-2B15;SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;;
-2B16;DIAMOND WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;;
-2B17;DIAMOND WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;;
-2B18;DIAMOND WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;;
-2B19;DIAMOND WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;;
-2B1A;DOTTED SQUARE;So;0;ON;;;;;N;;;;;
-2B1B;BLACK LARGE SQUARE;So;0;ON;;;;;N;;;;;
-2B1C;WHITE LARGE SQUARE;So;0;ON;;;;;N;;;;;
-2B1D;BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;;
-2B1E;WHITE VERY SMALL SQUARE;So;0;ON;;;;;N;;;;;
-2B1F;BLACK PENTAGON;So;0;ON;;;;;N;;;;;
-2B20;WHITE PENTAGON;So;0;ON;;;;;N;;;;;
-2B21;WHITE HEXAGON;So;0;ON;;;;;N;;;;;
-2B22;BLACK HEXAGON;So;0;ON;;;;;N;;;;;
-2B23;HORIZONTAL BLACK HEXAGON;So;0;ON;;;;;N;;;;;
-2B24;BLACK LARGE CIRCLE;So;0;ON;;;;;N;;;;;
-2B25;BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;;
-2B26;WHITE MEDIUM DIAMOND;So;0;ON;;;;;N;;;;;
-2B27;BLACK MEDIUM LOZENGE;So;0;ON;;;;;N;;;;;
-2B28;WHITE MEDIUM LOZENGE;So;0;ON;;;;;N;;;;;
-2B29;BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;;
-2B2A;BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;;
-2B2B;WHITE SMALL LOZENGE;So;0;ON;;;;;N;;;;;
-2B2C;BLACK HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;;
-2B2D;WHITE HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;;
-2B2E;BLACK VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;;
-2B2F;WHITE VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;;
-2B30;LEFT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
-2B31;THREE LEFTWARDS ARROWS;Sm;0;ON;;;;;N;;;;;
-2B32;LEFT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;;
-2B33;LONG LEFTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;;
-2B34;LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2B35;LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2B36;LEFTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
-2B37;LEFTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
-2B38;LEFTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;;
-2B39;LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2B3A;LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2B3B;LEFTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;;
-2B3C;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2B3D;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
-2B3E;LEFTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;;
-2B3F;WAVE ARROW POINTING DIRECTLY LEFT;Sm;0;ON;;;;;N;;;;;
-2B40;EQUALS SIGN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2B41;REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2B42;LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;;
-2B43;RIGHTWARDS ARROW THROUGH GREATER-THAN;Sm;0;ON;;;;;N;;;;;
-2B44;RIGHTWARDS ARROW THROUGH SUPERSET;Sm;0;ON;;;;;N;;;;;
-2B45;LEFTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;;
-2B46;RIGHTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;;
-2B47;REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2B48;RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;;
-2B49;TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
-2B4A;LEFTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;;
-2B4B;LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;;
-2B4C;RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;;
-2B50;WHITE MEDIUM STAR;So;0;ON;;;;;N;;;;;
-2B51;BLACK SMALL STAR;So;0;ON;;;;;N;;;;;
-2B52;WHITE SMALL STAR;So;0;ON;;;;;N;;;;;
-2B53;BLACK RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;;
-2B54;WHITE RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;;
-2B55;HEAVY LARGE CIRCLE;So;0;ON;;;;;N;;;;;
-2B56;HEAVY OVAL WITH OVAL INSIDE;So;0;ON;;;;;N;;;;;
-2B57;HEAVY CIRCLE WITH CIRCLE INSIDE;So;0;ON;;;;;N;;;;;
-2B58;HEAVY CIRCLE;So;0;ON;;;;;N;;;;;
-2B59;HEAVY CIRCLED SALTIRE;So;0;ON;;;;;N;;;;;
-2C00;GLAGOLITIC CAPITAL LETTER AZU;Lu;0;L;;;;;N;;;;2C30;
-2C01;GLAGOLITIC CAPITAL LETTER BUKY;Lu;0;L;;;;;N;;;;2C31;
-2C02;GLAGOLITIC CAPITAL LETTER VEDE;Lu;0;L;;;;;N;;;;2C32;
-2C03;GLAGOLITIC CAPITAL LETTER GLAGOLI;Lu;0;L;;;;;N;;;;2C33;
-2C04;GLAGOLITIC CAPITAL LETTER DOBRO;Lu;0;L;;;;;N;;;;2C34;
-2C05;GLAGOLITIC CAPITAL LETTER YESTU;Lu;0;L;;;;;N;;;;2C35;
-2C06;GLAGOLITIC CAPITAL LETTER ZHIVETE;Lu;0;L;;;;;N;;;;2C36;
-2C07;GLAGOLITIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;2C37;
-2C08;GLAGOLITIC CAPITAL LETTER ZEMLJA;Lu;0;L;;;;;N;;;;2C38;
-2C09;GLAGOLITIC CAPITAL LETTER IZHE;Lu;0;L;;;;;N;;;;2C39;
-2C0A;GLAGOLITIC CAPITAL LETTER INITIAL IZHE;Lu;0;L;;;;;N;;;;2C3A;
-2C0B;GLAGOLITIC CAPITAL LETTER I;Lu;0;L;;;;;N;;;;2C3B;
-2C0C;GLAGOLITIC CAPITAL LETTER DJERVI;Lu;0;L;;;;;N;;;;2C3C;
-2C0D;GLAGOLITIC CAPITAL LETTER KAKO;Lu;0;L;;;;;N;;;;2C3D;
-2C0E;GLAGOLITIC CAPITAL LETTER LJUDIJE;Lu;0;L;;;;;N;;;;2C3E;
-2C0F;GLAGOLITIC CAPITAL LETTER MYSLITE;Lu;0;L;;;;;N;;;;2C3F;
-2C10;GLAGOLITIC CAPITAL LETTER NASHI;Lu;0;L;;;;;N;;;;2C40;
-2C11;GLAGOLITIC CAPITAL LETTER ONU;Lu;0;L;;;;;N;;;;2C41;
-2C12;GLAGOLITIC CAPITAL LETTER POKOJI;Lu;0;L;;;;;N;;;;2C42;
-2C13;GLAGOLITIC CAPITAL LETTER RITSI;Lu;0;L;;;;;N;;;;2C43;
-2C14;GLAGOLITIC CAPITAL LETTER SLOVO;Lu;0;L;;;;;N;;;;2C44;
-2C15;GLAGOLITIC CAPITAL LETTER TVRIDO;Lu;0;L;;;;;N;;;;2C45;
-2C16;GLAGOLITIC CAPITAL LETTER UKU;Lu;0;L;;;;;N;;;;2C46;
-2C17;GLAGOLITIC CAPITAL LETTER FRITU;Lu;0;L;;;;;N;;;;2C47;
-2C18;GLAGOLITIC CAPITAL LETTER HERU;Lu;0;L;;;;;N;;;;2C48;
-2C19;GLAGOLITIC CAPITAL LETTER OTU;Lu;0;L;;;;;N;;;;2C49;
-2C1A;GLAGOLITIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;2C4A;
-2C1B;GLAGOLITIC CAPITAL LETTER SHTA;Lu;0;L;;;;;N;;;;2C4B;
-2C1C;GLAGOLITIC CAPITAL LETTER TSI;Lu;0;L;;;;;N;;;;2C4C;
-2C1D;GLAGOLITIC CAPITAL LETTER CHRIVI;Lu;0;L;;;;;N;;;;2C4D;
-2C1E;GLAGOLITIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;2C4E;
-2C1F;GLAGOLITIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;;;;2C4F;
-2C20;GLAGOLITIC CAPITAL LETTER YERI;Lu;0;L;;;;;N;;;;2C50;
-2C21;GLAGOLITIC CAPITAL LETTER YATI;Lu;0;L;;;;;N;;;;2C51;
-2C22;GLAGOLITIC CAPITAL LETTER SPIDERY HA;Lu;0;L;;;;;N;;;;2C52;
-2C23;GLAGOLITIC CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;2C53;
-2C24;GLAGOLITIC CAPITAL LETTER SMALL YUS;Lu;0;L;;;;;N;;;;2C54;
-2C25;GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL;Lu;0;L;;;;;N;;;;2C55;
-2C26;GLAGOLITIC CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;2C56;
-2C27;GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS;Lu;0;L;;;;;N;;;;2C57;
-2C28;GLAGOLITIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;2C58;
-2C29;GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS;Lu;0;L;;;;;N;;;;2C59;
-2C2A;GLAGOLITIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;2C5A;
-2C2B;GLAGOLITIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;2C5B;
-2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C;
-2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D;
-2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E;
-2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00
-2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01
-2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02
-2C33;GLAGOLITIC SMALL LETTER GLAGOLI;Ll;0;L;;;;;N;;;2C03;;2C03
-2C34;GLAGOLITIC SMALL LETTER DOBRO;Ll;0;L;;;;;N;;;2C04;;2C04
-2C35;GLAGOLITIC SMALL LETTER YESTU;Ll;0;L;;;;;N;;;2C05;;2C05
-2C36;GLAGOLITIC SMALL LETTER ZHIVETE;Ll;0;L;;;;;N;;;2C06;;2C06
-2C37;GLAGOLITIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;2C07;;2C07
-2C38;GLAGOLITIC SMALL LETTER ZEMLJA;Ll;0;L;;;;;N;;;2C08;;2C08
-2C39;GLAGOLITIC SMALL LETTER IZHE;Ll;0;L;;;;;N;;;2C09;;2C09
-2C3A;GLAGOLITIC SMALL LETTER INITIAL IZHE;Ll;0;L;;;;;N;;;2C0A;;2C0A
-2C3B;GLAGOLITIC SMALL LETTER I;Ll;0;L;;;;;N;;;2C0B;;2C0B
-2C3C;GLAGOLITIC SMALL LETTER DJERVI;Ll;0;L;;;;;N;;;2C0C;;2C0C
-2C3D;GLAGOLITIC SMALL LETTER KAKO;Ll;0;L;;;;;N;;;2C0D;;2C0D
-2C3E;GLAGOLITIC SMALL LETTER LJUDIJE;Ll;0;L;;;;;N;;;2C0E;;2C0E
-2C3F;GLAGOLITIC SMALL LETTER MYSLITE;Ll;0;L;;;;;N;;;2C0F;;2C0F
-2C40;GLAGOLITIC SMALL LETTER NASHI;Ll;0;L;;;;;N;;;2C10;;2C10
-2C41;GLAGOLITIC SMALL LETTER ONU;Ll;0;L;;;;;N;;;2C11;;2C11
-2C42;GLAGOLITIC SMALL LETTER POKOJI;Ll;0;L;;;;;N;;;2C12;;2C12
-2C43;GLAGOLITIC SMALL LETTER RITSI;Ll;0;L;;;;;N;;;2C13;;2C13
-2C44;GLAGOLITIC SMALL LETTER SLOVO;Ll;0;L;;;;;N;;;2C14;;2C14
-2C45;GLAGOLITIC SMALL LETTER TVRIDO;Ll;0;L;;;;;N;;;2C15;;2C15
-2C46;GLAGOLITIC SMALL LETTER UKU;Ll;0;L;;;;;N;;;2C16;;2C16
-2C47;GLAGOLITIC SMALL LETTER FRITU;Ll;0;L;;;;;N;;;2C17;;2C17
-2C48;GLAGOLITIC SMALL LETTER HERU;Ll;0;L;;;;;N;;;2C18;;2C18
-2C49;GLAGOLITIC SMALL LETTER OTU;Ll;0;L;;;;;N;;;2C19;;2C19
-2C4A;GLAGOLITIC SMALL LETTER PE;Ll;0;L;;;;;N;;;2C1A;;2C1A
-2C4B;GLAGOLITIC SMALL LETTER SHTA;Ll;0;L;;;;;N;;;2C1B;;2C1B
-2C4C;GLAGOLITIC SMALL LETTER TSI;Ll;0;L;;;;;N;;;2C1C;;2C1C
-2C4D;GLAGOLITIC SMALL LETTER CHRIVI;Ll;0;L;;;;;N;;;2C1D;;2C1D
-2C4E;GLAGOLITIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;2C1E;;2C1E
-2C4F;GLAGOLITIC SMALL LETTER YERU;Ll;0;L;;;;;N;;;2C1F;;2C1F
-2C50;GLAGOLITIC SMALL LETTER YERI;Ll;0;L;;;;;N;;;2C20;;2C20
-2C51;GLAGOLITIC SMALL LETTER YATI;Ll;0;L;;;;;N;;;2C21;;2C21
-2C52;GLAGOLITIC SMALL LETTER SPIDERY HA;Ll;0;L;;;;;N;;;2C22;;2C22
-2C53;GLAGOLITIC SMALL LETTER YU;Ll;0;L;;;;;N;;;2C23;;2C23
-2C54;GLAGOLITIC SMALL LETTER SMALL YUS;Ll;0;L;;;;;N;;;2C24;;2C24
-2C55;GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL;Ll;0;L;;;;;N;;;2C25;;2C25
-2C56;GLAGOLITIC SMALL LETTER YO;Ll;0;L;;;;;N;;;2C26;;2C26
-2C57;GLAGOLITIC SMALL LETTER IOTATED SMALL YUS;Ll;0;L;;;;;N;;;2C27;;2C27
-2C58;GLAGOLITIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;2C28;;2C28
-2C59;GLAGOLITIC SMALL LETTER IOTATED BIG YUS;Ll;0;L;;;;;N;;;2C29;;2C29
-2C5A;GLAGOLITIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;2C2A;;2C2A
-2C5B;GLAGOLITIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;2C2B;;2C2B
-2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C
-2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D
-2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E
-2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61;
-2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60
-2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B;
-2C63;LATIN CAPITAL LETTER P WITH STROKE;Lu;0;L;;;;;N;;;;1D7D;
-2C64;LATIN CAPITAL LETTER R WITH TAIL;Lu;0;L;;;;;N;;;;027D;
-2C65;LATIN SMALL LETTER A WITH STROKE;Ll;0;L;;;;;N;;;023A;;023A
-2C66;LATIN SMALL LETTER T WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;023E;;023E
-2C67;LATIN CAPITAL LETTER H WITH DESCENDER;Lu;0;L;;;;;N;;;;2C68;
-2C68;LATIN SMALL LETTER H WITH DESCENDER;Ll;0;L;;;;;N;;;2C67;;2C67
-2C69;LATIN CAPITAL LETTER K WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6A;
-2C6A;LATIN SMALL LETTER K WITH DESCENDER;Ll;0;L;;;;;N;;;2C69;;2C69
-2C6B;LATIN CAPITAL LETTER Z WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6C;
-2C6C;LATIN SMALL LETTER Z WITH DESCENDER;Ll;0;L;;;;;N;;;2C6B;;2C6B
-2C6D;LATIN CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;0251;
-2C6E;LATIN CAPITAL LETTER M WITH HOOK;Lu;0;L;;;;;N;;;;0271;
-2C6F;LATIN CAPITAL LETTER TURNED A;Lu;0;L;;;;;N;;;;0250;
-2C70;LATIN CAPITAL LETTER TURNED ALPHA;Lu;0;L;;;;;N;;;;0252;
-2C71;LATIN SMALL LETTER V WITH RIGHT HOOK;Ll;0;L;;;;;N;;;;;
-2C72;LATIN CAPITAL LETTER W WITH HOOK;Lu;0;L;;;;;N;;;;2C73;
-2C73;LATIN SMALL LETTER W WITH HOOK;Ll;0;L;;;;;N;;;2C72;;2C72
-2C74;LATIN SMALL LETTER V WITH CURL;Ll;0;L;;;;;N;;;;;
-2C75;LATIN CAPITAL LETTER HALF H;Lu;0;L;;;;;N;;;;2C76;
-2C76;LATIN SMALL LETTER HALF H;Ll;0;L;;;;;N;;;2C75;;2C75
-2C77;LATIN SMALL LETTER TAILLESS PHI;Ll;0;L;;;;;N;;;;;
-2C78;LATIN SMALL LETTER E WITH NOTCH;Ll;0;L;;;;;N;;;;;
-2C79;LATIN SMALL LETTER TURNED R WITH TAIL;Ll;0;L;;;;;N;;;;;
-2C7A;LATIN SMALL LETTER O WITH LOW RING INSIDE;Ll;0;L;;;;;N;;;;;
-2C7B;LATIN LETTER SMALL CAPITAL TURNED E;Ll;0;L;;;;;N;;;;;
-2C7C;LATIN SUBSCRIPT SMALL LETTER J;Lm;0;L;<sub> 006A;;;;N;;;;;
-2C7D;MODIFIER LETTER CAPITAL V;Lm;0;L;<super> 0056;;;;N;;;;;
-2C7E;LATIN CAPITAL LETTER S WITH SWASH TAIL;Lu;0;L;;;;;N;;;;023F;
-2C7F;LATIN CAPITAL LETTER Z WITH SWASH TAIL;Lu;0;L;;;;;N;;;;0240;
-2C80;COPTIC CAPITAL LETTER ALFA;Lu;0;L;;;;;N;;;;2C81;
-2C81;COPTIC SMALL LETTER ALFA;Ll;0;L;;;;;N;;;2C80;;2C80
-2C82;COPTIC CAPITAL LETTER VIDA;Lu;0;L;;;;;N;;;;2C83;
-2C83;COPTIC SMALL LETTER VIDA;Ll;0;L;;;;;N;;;2C82;;2C82
-2C84;COPTIC CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;2C85;
-2C85;COPTIC SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;2C84;;2C84
-2C86;COPTIC CAPITAL LETTER DALDA;Lu;0;L;;;;;N;;;;2C87;
-2C87;COPTIC SMALL LETTER DALDA;Ll;0;L;;;;;N;;;2C86;;2C86
-2C88;COPTIC CAPITAL LETTER EIE;Lu;0;L;;;;;N;;;;2C89;
-2C89;COPTIC SMALL LETTER EIE;Ll;0;L;;;;;N;;;2C88;;2C88
-2C8A;COPTIC CAPITAL LETTER SOU;Lu;0;L;;;;;N;;;;2C8B;
-2C8B;COPTIC SMALL LETTER SOU;Ll;0;L;;;;;N;;;2C8A;;2C8A
-2C8C;COPTIC CAPITAL LETTER ZATA;Lu;0;L;;;;;N;;;;2C8D;
-2C8D;COPTIC SMALL LETTER ZATA;Ll;0;L;;;;;N;;;2C8C;;2C8C
-2C8E;COPTIC CAPITAL LETTER HATE;Lu;0;L;;;;;N;;;;2C8F;
-2C8F;COPTIC SMALL LETTER HATE;Ll;0;L;;;;;N;;;2C8E;;2C8E
-2C90;COPTIC CAPITAL LETTER THETHE;Lu;0;L;;;;;N;;;;2C91;
-2C91;COPTIC SMALL LETTER THETHE;Ll;0;L;;;;;N;;;2C90;;2C90
-2C92;COPTIC CAPITAL LETTER IAUDA;Lu;0;L;;;;;N;;;;2C93;
-2C93;COPTIC SMALL LETTER IAUDA;Ll;0;L;;;;;N;;;2C92;;2C92
-2C94;COPTIC CAPITAL LETTER KAPA;Lu;0;L;;;;;N;;;;2C95;
-2C95;COPTIC SMALL LETTER KAPA;Ll;0;L;;;;;N;;;2C94;;2C94
-2C96;COPTIC CAPITAL LETTER LAULA;Lu;0;L;;;;;N;;;;2C97;
-2C97;COPTIC SMALL LETTER LAULA;Ll;0;L;;;;;N;;;2C96;;2C96
-2C98;COPTIC CAPITAL LETTER MI;Lu;0;L;;;;;N;;;;2C99;
-2C99;COPTIC SMALL LETTER MI;Ll;0;L;;;;;N;;;2C98;;2C98
-2C9A;COPTIC CAPITAL LETTER NI;Lu;0;L;;;;;N;;;;2C9B;
-2C9B;COPTIC SMALL LETTER NI;Ll;0;L;;;;;N;;;2C9A;;2C9A
-2C9C;COPTIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;2C9D;
-2C9D;COPTIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;2C9C;;2C9C
-2C9E;COPTIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;2C9F;
-2C9F;COPTIC SMALL LETTER O;Ll;0;L;;;;;N;;;2C9E;;2C9E
-2CA0;COPTIC CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;2CA1;
-2CA1;COPTIC SMALL LETTER PI;Ll;0;L;;;;;N;;;2CA0;;2CA0
-2CA2;COPTIC CAPITAL LETTER RO;Lu;0;L;;;;;N;;;;2CA3;
-2CA3;COPTIC SMALL LETTER RO;Ll;0;L;;;;;N;;;2CA2;;2CA2
-2CA4;COPTIC CAPITAL LETTER SIMA;Lu;0;L;;;;;N;;;;2CA5;
-2CA5;COPTIC SMALL LETTER SIMA;Ll;0;L;;;;;N;;;2CA4;;2CA4
-2CA6;COPTIC CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;2CA7;
-2CA7;COPTIC SMALL LETTER TAU;Ll;0;L;;;;;N;;;2CA6;;2CA6
-2CA8;COPTIC CAPITAL LETTER UA;Lu;0;L;;;;;N;;;;2CA9;
-2CA9;COPTIC SMALL LETTER UA;Ll;0;L;;;;;N;;;2CA8;;2CA8
-2CAA;COPTIC CAPITAL LETTER FI;Lu;0;L;;;;;N;;;;2CAB;
-2CAB;COPTIC SMALL LETTER FI;Ll;0;L;;;;;N;;;2CAA;;2CAA
-2CAC;COPTIC CAPITAL LETTER KHI;Lu;0;L;;;;;N;;;;2CAD;
-2CAD;COPTIC SMALL LETTER KHI;Ll;0;L;;;;;N;;;2CAC;;2CAC
-2CAE;COPTIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;2CAF;
-2CAF;COPTIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;2CAE;;2CAE
-2CB0;COPTIC CAPITAL LETTER OOU;Lu;0;L;;;;;N;;;;2CB1;
-2CB1;COPTIC SMALL LETTER OOU;Ll;0;L;;;;;N;;;2CB0;;2CB0
-2CB2;COPTIC CAPITAL LETTER DIALECT-P ALEF;Lu;0;L;;;;;N;;;;2CB3;
-2CB3;COPTIC SMALL LETTER DIALECT-P ALEF;Ll;0;L;;;;;N;;;2CB2;;2CB2
-2CB4;COPTIC CAPITAL LETTER OLD COPTIC AIN;Lu;0;L;;;;;N;;;;2CB5;
-2CB5;COPTIC SMALL LETTER OLD COPTIC AIN;Ll;0;L;;;;;N;;;2CB4;;2CB4
-2CB6;COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE;Lu;0;L;;;;;N;;;;2CB7;
-2CB7;COPTIC SMALL LETTER CRYPTOGRAMMIC EIE;Ll;0;L;;;;;N;;;2CB6;;2CB6
-2CB8;COPTIC CAPITAL LETTER DIALECT-P KAPA;Lu;0;L;;;;;N;;;;2CB9;
-2CB9;COPTIC SMALL LETTER DIALECT-P KAPA;Ll;0;L;;;;;N;;;2CB8;;2CB8
-2CBA;COPTIC CAPITAL LETTER DIALECT-P NI;Lu;0;L;;;;;N;;;;2CBB;
-2CBB;COPTIC SMALL LETTER DIALECT-P NI;Ll;0;L;;;;;N;;;2CBA;;2CBA
-2CBC;COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI;Lu;0;L;;;;;N;;;;2CBD;
-2CBD;COPTIC SMALL LETTER CRYPTOGRAMMIC NI;Ll;0;L;;;;;N;;;2CBC;;2CBC
-2CBE;COPTIC CAPITAL LETTER OLD COPTIC OOU;Lu;0;L;;;;;N;;;;2CBF;
-2CBF;COPTIC SMALL LETTER OLD COPTIC OOU;Ll;0;L;;;;;N;;;2CBE;;2CBE
-2CC0;COPTIC CAPITAL LETTER SAMPI;Lu;0;L;;;;;N;;;;2CC1;
-2CC1;COPTIC SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;2CC0;;2CC0
-2CC2;COPTIC CAPITAL LETTER CROSSED SHEI;Lu;0;L;;;;;N;;;;2CC3;
-2CC3;COPTIC SMALL LETTER CROSSED SHEI;Ll;0;L;;;;;N;;;2CC2;;2CC2
-2CC4;COPTIC CAPITAL LETTER OLD COPTIC SHEI;Lu;0;L;;;;;N;;;;2CC5;
-2CC5;COPTIC SMALL LETTER OLD COPTIC SHEI;Ll;0;L;;;;;N;;;2CC4;;2CC4
-2CC6;COPTIC CAPITAL LETTER OLD COPTIC ESH;Lu;0;L;;;;;N;;;;2CC7;
-2CC7;COPTIC SMALL LETTER OLD COPTIC ESH;Ll;0;L;;;;;N;;;2CC6;;2CC6
-2CC8;COPTIC CAPITAL LETTER AKHMIMIC KHEI;Lu;0;L;;;;;N;;;;2CC9;
-2CC9;COPTIC SMALL LETTER AKHMIMIC KHEI;Ll;0;L;;;;;N;;;2CC8;;2CC8
-2CCA;COPTIC CAPITAL LETTER DIALECT-P HORI;Lu;0;L;;;;;N;;;;2CCB;
-2CCB;COPTIC SMALL LETTER DIALECT-P HORI;Ll;0;L;;;;;N;;;2CCA;;2CCA
-2CCC;COPTIC CAPITAL LETTER OLD COPTIC HORI;Lu;0;L;;;;;N;;;;2CCD;
-2CCD;COPTIC SMALL LETTER OLD COPTIC HORI;Ll;0;L;;;;;N;;;2CCC;;2CCC
-2CCE;COPTIC CAPITAL LETTER OLD COPTIC HA;Lu;0;L;;;;;N;;;;2CCF;
-2CCF;COPTIC SMALL LETTER OLD COPTIC HA;Ll;0;L;;;;;N;;;2CCE;;2CCE
-2CD0;COPTIC CAPITAL LETTER L-SHAPED HA;Lu;0;L;;;;;N;;;;2CD1;
-2CD1;COPTIC SMALL LETTER L-SHAPED HA;Ll;0;L;;;;;N;;;2CD0;;2CD0
-2CD2;COPTIC CAPITAL LETTER OLD COPTIC HEI;Lu;0;L;;;;;N;;;;2CD3;
-2CD3;COPTIC SMALL LETTER OLD COPTIC HEI;Ll;0;L;;;;;N;;;2CD2;;2CD2
-2CD4;COPTIC CAPITAL LETTER OLD COPTIC HAT;Lu;0;L;;;;;N;;;;2CD5;
-2CD5;COPTIC SMALL LETTER OLD COPTIC HAT;Ll;0;L;;;;;N;;;2CD4;;2CD4
-2CD6;COPTIC CAPITAL LETTER OLD COPTIC GANGIA;Lu;0;L;;;;;N;;;;2CD7;
-2CD7;COPTIC SMALL LETTER OLD COPTIC GANGIA;Ll;0;L;;;;;N;;;2CD6;;2CD6
-2CD8;COPTIC CAPITAL LETTER OLD COPTIC DJA;Lu;0;L;;;;;N;;;;2CD9;
-2CD9;COPTIC SMALL LETTER OLD COPTIC DJA;Ll;0;L;;;;;N;;;2CD8;;2CD8
-2CDA;COPTIC CAPITAL LETTER OLD COPTIC SHIMA;Lu;0;L;;;;;N;;;;2CDB;
-2CDB;COPTIC SMALL LETTER OLD COPTIC SHIMA;Ll;0;L;;;;;N;;;2CDA;;2CDA
-2CDC;COPTIC CAPITAL LETTER OLD NUBIAN SHIMA;Lu;0;L;;;;;N;;;;2CDD;
-2CDD;COPTIC SMALL LETTER OLD NUBIAN SHIMA;Ll;0;L;;;;;N;;;2CDC;;2CDC
-2CDE;COPTIC CAPITAL LETTER OLD NUBIAN NGI;Lu;0;L;;;;;N;;;;2CDF;
-2CDF;COPTIC SMALL LETTER OLD NUBIAN NGI;Ll;0;L;;;;;N;;;2CDE;;2CDE
-2CE0;COPTIC CAPITAL LETTER OLD NUBIAN NYI;Lu;0;L;;;;;N;;;;2CE1;
-2CE1;COPTIC SMALL LETTER OLD NUBIAN NYI;Ll;0;L;;;;;N;;;2CE0;;2CE0
-2CE2;COPTIC CAPITAL LETTER OLD NUBIAN WAU;Lu;0;L;;;;;N;;;;2CE3;
-2CE3;COPTIC SMALL LETTER OLD NUBIAN WAU;Ll;0;L;;;;;N;;;2CE2;;2CE2
-2CE4;COPTIC SYMBOL KAI;Ll;0;L;;;;;N;;;;;
-2CE5;COPTIC SYMBOL MI RO;So;0;ON;;;;;N;;;;;
-2CE6;COPTIC SYMBOL PI RO;So;0;ON;;;;;N;;;;;
-2CE7;COPTIC SYMBOL STAUROS;So;0;ON;;;;;N;;;;;
-2CE8;COPTIC SYMBOL TAU RO;So;0;ON;;;;;N;;;;;
-2CE9;COPTIC SYMBOL KHI RO;So;0;ON;;;;;N;;;;;
-2CEA;COPTIC SYMBOL SHIMA SIMA;So;0;ON;;;;;N;;;;;
-2CEB;COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI;Lu;0;L;;;;;N;;;;2CEC;
-2CEC;COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI;Ll;0;L;;;;;N;;;2CEB;;2CEB
-2CED;COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA;Lu;0;L;;;;;N;;;;2CEE;
-2CEE;COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA;Ll;0;L;;;;;N;;;2CED;;2CED
-2CEF;COPTIC COMBINING NI ABOVE;Mn;230;NSM;;;;;N;;;;;
-2CF0;COPTIC COMBINING SPIRITUS ASPER;Mn;230;NSM;;;;;N;;;;;
-2CF1;COPTIC COMBINING SPIRITUS LENIS;Mn;230;NSM;;;;;N;;;;;
-2CF2;COPTIC CAPITAL LETTER BOHAIRIC KHEI;Lu;0;L;;;;;N;;;;2CF3;
-2CF3;COPTIC SMALL LETTER BOHAIRIC KHEI;Ll;0;L;;;;;N;;;2CF2;;2CF2
-2CF9;COPTIC OLD NUBIAN FULL STOP;Po;0;ON;;;;;N;;;;;
-2CFA;COPTIC OLD NUBIAN DIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;;
-2CFB;COPTIC OLD NUBIAN INDIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;;
-2CFC;COPTIC OLD NUBIAN VERSE DIVIDER;Po;0;ON;;;;;N;;;;;
-2CFD;COPTIC FRACTION ONE HALF;No;0;ON;;;;1/2;N;;;;;
-2CFE;COPTIC FULL STOP;Po;0;ON;;;;;N;;;;;
-2CFF;COPTIC MORPHOLOGICAL DIVIDER;Po;0;ON;;;;;N;;;;;
-2D00;GEORGIAN SMALL LETTER AN;Ll;0;L;;;;;N;;;10A0;;10A0
-2D01;GEORGIAN SMALL LETTER BAN;Ll;0;L;;;;;N;;;10A1;;10A1
-2D02;GEORGIAN SMALL LETTER GAN;Ll;0;L;;;;;N;;;10A2;;10A2
-2D03;GEORGIAN SMALL LETTER DON;Ll;0;L;;;;;N;;;10A3;;10A3
-2D04;GEORGIAN SMALL LETTER EN;Ll;0;L;;;;;N;;;10A4;;10A4
-2D05;GEORGIAN SMALL LETTER VIN;Ll;0;L;;;;;N;;;10A5;;10A5
-2D06;GEORGIAN SMALL LETTER ZEN;Ll;0;L;;;;;N;;;10A6;;10A6
-2D07;GEORGIAN SMALL LETTER TAN;Ll;0;L;;;;;N;;;10A7;;10A7
-2D08;GEORGIAN SMALL LETTER IN;Ll;0;L;;;;;N;;;10A8;;10A8
-2D09;GEORGIAN SMALL LETTER KAN;Ll;0;L;;;;;N;;;10A9;;10A9
-2D0A;GEORGIAN SMALL LETTER LAS;Ll;0;L;;;;;N;;;10AA;;10AA
-2D0B;GEORGIAN SMALL LETTER MAN;Ll;0;L;;;;;N;;;10AB;;10AB
-2D0C;GEORGIAN SMALL LETTER NAR;Ll;0;L;;;;;N;;;10AC;;10AC
-2D0D;GEORGIAN SMALL LETTER ON;Ll;0;L;;;;;N;;;10AD;;10AD
-2D0E;GEORGIAN SMALL LETTER PAR;Ll;0;L;;;;;N;;;10AE;;10AE
-2D0F;GEORGIAN SMALL LETTER ZHAR;Ll;0;L;;;;;N;;;10AF;;10AF
-2D10;GEORGIAN SMALL LETTER RAE;Ll;0;L;;;;;N;;;10B0;;10B0
-2D11;GEORGIAN SMALL LETTER SAN;Ll;0;L;;;;;N;;;10B1;;10B1
-2D12;GEORGIAN SMALL LETTER TAR;Ll;0;L;;;;;N;;;10B2;;10B2
-2D13;GEORGIAN SMALL LETTER UN;Ll;0;L;;;;;N;;;10B3;;10B3
-2D14;GEORGIAN SMALL LETTER PHAR;Ll;0;L;;;;;N;;;10B4;;10B4
-2D15;GEORGIAN SMALL LETTER KHAR;Ll;0;L;;;;;N;;;10B5;;10B5
-2D16;GEORGIAN SMALL LETTER GHAN;Ll;0;L;;;;;N;;;10B6;;10B6
-2D17;GEORGIAN SMALL LETTER QAR;Ll;0;L;;;;;N;;;10B7;;10B7
-2D18;GEORGIAN SMALL LETTER SHIN;Ll;0;L;;;;;N;;;10B8;;10B8
-2D19;GEORGIAN SMALL LETTER CHIN;Ll;0;L;;;;;N;;;10B9;;10B9
-2D1A;GEORGIAN SMALL LETTER CAN;Ll;0;L;;;;;N;;;10BA;;10BA
-2D1B;GEORGIAN SMALL LETTER JIL;Ll;0;L;;;;;N;;;10BB;;10BB
-2D1C;GEORGIAN SMALL LETTER CIL;Ll;0;L;;;;;N;;;10BC;;10BC
-2D1D;GEORGIAN SMALL LETTER CHAR;Ll;0;L;;;;;N;;;10BD;;10BD
-2D1E;GEORGIAN SMALL LETTER XAN;Ll;0;L;;;;;N;;;10BE;;10BE
-2D1F;GEORGIAN SMALL LETTER JHAN;Ll;0;L;;;;;N;;;10BF;;10BF
-2D20;GEORGIAN SMALL LETTER HAE;Ll;0;L;;;;;N;;;10C0;;10C0
-2D21;GEORGIAN SMALL LETTER HE;Ll;0;L;;;;;N;;;10C1;;10C1
-2D22;GEORGIAN SMALL LETTER HIE;Ll;0;L;;;;;N;;;10C2;;10C2
-2D23;GEORGIAN SMALL LETTER WE;Ll;0;L;;;;;N;;;10C3;;10C3
-2D24;GEORGIAN SMALL LETTER HAR;Ll;0;L;;;;;N;;;10C4;;10C4
-2D25;GEORGIAN SMALL LETTER HOE;Ll;0;L;;;;;N;;;10C5;;10C5
-2D27;GEORGIAN SMALL LETTER YN;Ll;0;L;;;;;N;;;10C7;;10C7
-2D2D;GEORGIAN SMALL LETTER AEN;Ll;0;L;;;;;N;;;10CD;;10CD
-2D30;TIFINAGH LETTER YA;Lo;0;L;;;;;N;;;;;
-2D31;TIFINAGH LETTER YAB;Lo;0;L;;;;;N;;;;;
-2D32;TIFINAGH LETTER YABH;Lo;0;L;;;;;N;;;;;
-2D33;TIFINAGH LETTER YAG;Lo;0;L;;;;;N;;;;;
-2D34;TIFINAGH LETTER YAGHH;Lo;0;L;;;;;N;;;;;
-2D35;TIFINAGH LETTER BERBER ACADEMY YAJ;Lo;0;L;;;;;N;;;;;
-2D36;TIFINAGH LETTER YAJ;Lo;0;L;;;;;N;;;;;
-2D37;TIFINAGH LETTER YAD;Lo;0;L;;;;;N;;;;;
-2D38;TIFINAGH LETTER YADH;Lo;0;L;;;;;N;;;;;
-2D39;TIFINAGH LETTER YADD;Lo;0;L;;;;;N;;;;;
-2D3A;TIFINAGH LETTER YADDH;Lo;0;L;;;;;N;;;;;
-2D3B;TIFINAGH LETTER YEY;Lo;0;L;;;;;N;;;;;
-2D3C;TIFINAGH LETTER YAF;Lo;0;L;;;;;N;;;;;
-2D3D;TIFINAGH LETTER YAK;Lo;0;L;;;;;N;;;;;
-2D3E;TIFINAGH LETTER TUAREG YAK;Lo;0;L;;;;;N;;;;;
-2D3F;TIFINAGH LETTER YAKHH;Lo;0;L;;;;;N;;;;;
-2D40;TIFINAGH LETTER YAH;Lo;0;L;;;;;N;;;;;
-2D41;TIFINAGH LETTER BERBER ACADEMY YAH;Lo;0;L;;;;;N;;;;;
-2D42;TIFINAGH LETTER TUAREG YAH;Lo;0;L;;;;;N;;;;;
-2D43;TIFINAGH LETTER YAHH;Lo;0;L;;;;;N;;;;;
-2D44;TIFINAGH LETTER YAA;Lo;0;L;;;;;N;;;;;
-2D45;TIFINAGH LETTER YAKH;Lo;0;L;;;;;N;;;;;
-2D46;TIFINAGH LETTER TUAREG YAKH;Lo;0;L;;;;;N;;;;;
-2D47;TIFINAGH LETTER YAQ;Lo;0;L;;;;;N;;;;;
-2D48;TIFINAGH LETTER TUAREG YAQ;Lo;0;L;;;;;N;;;;;
-2D49;TIFINAGH LETTER YI;Lo;0;L;;;;;N;;;;;
-2D4A;TIFINAGH LETTER YAZH;Lo;0;L;;;;;N;;;;;
-2D4B;TIFINAGH LETTER AHAGGAR YAZH;Lo;0;L;;;;;N;;;;;
-2D4C;TIFINAGH LETTER TUAREG YAZH;Lo;0;L;;;;;N;;;;;
-2D4D;TIFINAGH LETTER YAL;Lo;0;L;;;;;N;;;;;
-2D4E;TIFINAGH LETTER YAM;Lo;0;L;;;;;N;;;;;
-2D4F;TIFINAGH LETTER YAN;Lo;0;L;;;;;N;;;;;
-2D50;TIFINAGH LETTER TUAREG YAGN;Lo;0;L;;;;;N;;;;;
-2D51;TIFINAGH LETTER TUAREG YANG;Lo;0;L;;;;;N;;;;;
-2D52;TIFINAGH LETTER YAP;Lo;0;L;;;;;N;;;;;
-2D53;TIFINAGH LETTER YU;Lo;0;L;;;;;N;;;;;
-2D54;TIFINAGH LETTER YAR;Lo;0;L;;;;;N;;;;;
-2D55;TIFINAGH LETTER YARR;Lo;0;L;;;;;N;;;;;
-2D56;TIFINAGH LETTER YAGH;Lo;0;L;;;;;N;;;;;
-2D57;TIFINAGH LETTER TUAREG YAGH;Lo;0;L;;;;;N;;;;;
-2D58;TIFINAGH LETTER AYER YAGH;Lo;0;L;;;;;N;;;;;
-2D59;TIFINAGH LETTER YAS;Lo;0;L;;;;;N;;;;;
-2D5A;TIFINAGH LETTER YASS;Lo;0;L;;;;;N;;;;;
-2D5B;TIFINAGH LETTER YASH;Lo;0;L;;;;;N;;;;;
-2D5C;TIFINAGH LETTER YAT;Lo;0;L;;;;;N;;;;;
-2D5D;TIFINAGH LETTER YATH;Lo;0;L;;;;;N;;;;;
-2D5E;TIFINAGH LETTER YACH;Lo;0;L;;;;;N;;;;;
-2D5F;TIFINAGH LETTER YATT;Lo;0;L;;;;;N;;;;;
-2D60;TIFINAGH LETTER YAV;Lo;0;L;;;;;N;;;;;
-2D61;TIFINAGH LETTER YAW;Lo;0;L;;;;;N;;;;;
-2D62;TIFINAGH LETTER YAY;Lo;0;L;;;;;N;;;;;
-2D63;TIFINAGH LETTER YAZ;Lo;0;L;;;;;N;;;;;
-2D64;TIFINAGH LETTER TAWELLEMET YAZ;Lo;0;L;;;;;N;;;;;
-2D65;TIFINAGH LETTER YAZZ;Lo;0;L;;;;;N;;;;;
-2D66;TIFINAGH LETTER YE;Lo;0;L;;;;;N;;;;;
-2D67;TIFINAGH LETTER YO;Lo;0;L;;;;;N;;;;;
-2D6F;TIFINAGH MODIFIER LETTER LABIALIZATION MARK;Lm;0;L;<super> 2D61;;;;N;;;;;
-2D70;TIFINAGH SEPARATOR MARK;Po;0;L;;;;;N;;;;;
-2D7F;TIFINAGH CONSONANT JOINER;Mn;9;NSM;;;;;N;;;;;
-2D80;ETHIOPIC SYLLABLE LOA;Lo;0;L;;;;;N;;;;;
-2D81;ETHIOPIC SYLLABLE MOA;Lo;0;L;;;;;N;;;;;
-2D82;ETHIOPIC SYLLABLE ROA;Lo;0;L;;;;;N;;;;;
-2D83;ETHIOPIC SYLLABLE SOA;Lo;0;L;;;;;N;;;;;
-2D84;ETHIOPIC SYLLABLE SHOA;Lo;0;L;;;;;N;;;;;
-2D85;ETHIOPIC SYLLABLE BOA;Lo;0;L;;;;;N;;;;;
-2D86;ETHIOPIC SYLLABLE TOA;Lo;0;L;;;;;N;;;;;
-2D87;ETHIOPIC SYLLABLE COA;Lo;0;L;;;;;N;;;;;
-2D88;ETHIOPIC SYLLABLE NOA;Lo;0;L;;;;;N;;;;;
-2D89;ETHIOPIC SYLLABLE NYOA;Lo;0;L;;;;;N;;;;;
-2D8A;ETHIOPIC SYLLABLE GLOTTAL OA;Lo;0;L;;;;;N;;;;;
-2D8B;ETHIOPIC SYLLABLE ZOA;Lo;0;L;;;;;N;;;;;
-2D8C;ETHIOPIC SYLLABLE DOA;Lo;0;L;;;;;N;;;;;
-2D8D;ETHIOPIC SYLLABLE DDOA;Lo;0;L;;;;;N;;;;;
-2D8E;ETHIOPIC SYLLABLE JOA;Lo;0;L;;;;;N;;;;;
-2D8F;ETHIOPIC SYLLABLE THOA;Lo;0;L;;;;;N;;;;;
-2D90;ETHIOPIC SYLLABLE CHOA;Lo;0;L;;;;;N;;;;;
-2D91;ETHIOPIC SYLLABLE PHOA;Lo;0;L;;;;;N;;;;;
-2D92;ETHIOPIC SYLLABLE POA;Lo;0;L;;;;;N;;;;;
-2D93;ETHIOPIC SYLLABLE GGWA;Lo;0;L;;;;;N;;;;;
-2D94;ETHIOPIC SYLLABLE GGWI;Lo;0;L;;;;;N;;;;;
-2D95;ETHIOPIC SYLLABLE GGWEE;Lo;0;L;;;;;N;;;;;
-2D96;ETHIOPIC SYLLABLE GGWE;Lo;0;L;;;;;N;;;;;
-2DA0;ETHIOPIC SYLLABLE SSA;Lo;0;L;;;;;N;;;;;
-2DA1;ETHIOPIC SYLLABLE SSU;Lo;0;L;;;;;N;;;;;
-2DA2;ETHIOPIC SYLLABLE SSI;Lo;0;L;;;;;N;;;;;
-2DA3;ETHIOPIC SYLLABLE SSAA;Lo;0;L;;;;;N;;;;;
-2DA4;ETHIOPIC SYLLABLE SSEE;Lo;0;L;;;;;N;;;;;
-2DA5;ETHIOPIC SYLLABLE SSE;Lo;0;L;;;;;N;;;;;
-2DA6;ETHIOPIC SYLLABLE SSO;Lo;0;L;;;;;N;;;;;
-2DA8;ETHIOPIC SYLLABLE CCA;Lo;0;L;;;;;N;;;;;
-2DA9;ETHIOPIC SYLLABLE CCU;Lo;0;L;;;;;N;;;;;
-2DAA;ETHIOPIC SYLLABLE CCI;Lo;0;L;;;;;N;;;;;
-2DAB;ETHIOPIC SYLLABLE CCAA;Lo;0;L;;;;;N;;;;;
-2DAC;ETHIOPIC SYLLABLE CCEE;Lo;0;L;;;;;N;;;;;
-2DAD;ETHIOPIC SYLLABLE CCE;Lo;0;L;;;;;N;;;;;
-2DAE;ETHIOPIC SYLLABLE CCO;Lo;0;L;;;;;N;;;;;
-2DB0;ETHIOPIC SYLLABLE ZZA;Lo;0;L;;;;;N;;;;;
-2DB1;ETHIOPIC SYLLABLE ZZU;Lo;0;L;;;;;N;;;;;
-2DB2;ETHIOPIC SYLLABLE ZZI;Lo;0;L;;;;;N;;;;;
-2DB3;ETHIOPIC SYLLABLE ZZAA;Lo;0;L;;;;;N;;;;;
-2DB4;ETHIOPIC SYLLABLE ZZEE;Lo;0;L;;;;;N;;;;;
-2DB5;ETHIOPIC SYLLABLE ZZE;Lo;0;L;;;;;N;;;;;
-2DB6;ETHIOPIC SYLLABLE ZZO;Lo;0;L;;;;;N;;;;;
-2DB8;ETHIOPIC SYLLABLE CCHA;Lo;0;L;;;;;N;;;;;
-2DB9;ETHIOPIC SYLLABLE CCHU;Lo;0;L;;;;;N;;;;;
-2DBA;ETHIOPIC SYLLABLE CCHI;Lo;0;L;;;;;N;;;;;
-2DBB;ETHIOPIC SYLLABLE CCHAA;Lo;0;L;;;;;N;;;;;
-2DBC;ETHIOPIC SYLLABLE CCHEE;Lo;0;L;;;;;N;;;;;
-2DBD;ETHIOPIC SYLLABLE CCHE;Lo;0;L;;;;;N;;;;;
-2DBE;ETHIOPIC SYLLABLE CCHO;Lo;0;L;;;;;N;;;;;
-2DC0;ETHIOPIC SYLLABLE QYA;Lo;0;L;;;;;N;;;;;
-2DC1;ETHIOPIC SYLLABLE QYU;Lo;0;L;;;;;N;;;;;
-2DC2;ETHIOPIC SYLLABLE QYI;Lo;0;L;;;;;N;;;;;
-2DC3;ETHIOPIC SYLLABLE QYAA;Lo;0;L;;;;;N;;;;;
-2DC4;ETHIOPIC SYLLABLE QYEE;Lo;0;L;;;;;N;;;;;
-2DC5;ETHIOPIC SYLLABLE QYE;Lo;0;L;;;;;N;;;;;
-2DC6;ETHIOPIC SYLLABLE QYO;Lo;0;L;;;;;N;;;;;
-2DC8;ETHIOPIC SYLLABLE KYA;Lo;0;L;;;;;N;;;;;
-2DC9;ETHIOPIC SYLLABLE KYU;Lo;0;L;;;;;N;;;;;
-2DCA;ETHIOPIC SYLLABLE KYI;Lo;0;L;;;;;N;;;;;
-2DCB;ETHIOPIC SYLLABLE KYAA;Lo;0;L;;;;;N;;;;;
-2DCC;ETHIOPIC SYLLABLE KYEE;Lo;0;L;;;;;N;;;;;
-2DCD;ETHIOPIC SYLLABLE KYE;Lo;0;L;;;;;N;;;;;
-2DCE;ETHIOPIC SYLLABLE KYO;Lo;0;L;;;;;N;;;;;
-2DD0;ETHIOPIC SYLLABLE XYA;Lo;0;L;;;;;N;;;;;
-2DD1;ETHIOPIC SYLLABLE XYU;Lo;0;L;;;;;N;;;;;
-2DD2;ETHIOPIC SYLLABLE XYI;Lo;0;L;;;;;N;;;;;
-2DD3;ETHIOPIC SYLLABLE XYAA;Lo;0;L;;;;;N;;;;;
-2DD4;ETHIOPIC SYLLABLE XYEE;Lo;0;L;;;;;N;;;;;
-2DD5;ETHIOPIC SYLLABLE XYE;Lo;0;L;;;;;N;;;;;
-2DD6;ETHIOPIC SYLLABLE XYO;Lo;0;L;;;;;N;;;;;
-2DD8;ETHIOPIC SYLLABLE GYA;Lo;0;L;;;;;N;;;;;
-2DD9;ETHIOPIC SYLLABLE GYU;Lo;0;L;;;;;N;;;;;
-2DDA;ETHIOPIC SYLLABLE GYI;Lo;0;L;;;;;N;;;;;
-2DDB;ETHIOPIC SYLLABLE GYAA;Lo;0;L;;;;;N;;;;;
-2DDC;ETHIOPIC SYLLABLE GYEE;Lo;0;L;;;;;N;;;;;
-2DDD;ETHIOPIC SYLLABLE GYE;Lo;0;L;;;;;N;;;;;
-2DDE;ETHIOPIC SYLLABLE GYO;Lo;0;L;;;;;N;;;;;
-2DE0;COMBINING CYRILLIC LETTER BE;Mn;230;NSM;;;;;N;;;;;
-2DE1;COMBINING CYRILLIC LETTER VE;Mn;230;NSM;;;;;N;;;;;
-2DE2;COMBINING CYRILLIC LETTER GHE;Mn;230;NSM;;;;;N;;;;;
-2DE3;COMBINING CYRILLIC LETTER DE;Mn;230;NSM;;;;;N;;;;;
-2DE4;COMBINING CYRILLIC LETTER ZHE;Mn;230;NSM;;;;;N;;;;;
-2DE5;COMBINING CYRILLIC LETTER ZE;Mn;230;NSM;;;;;N;;;;;
-2DE6;COMBINING CYRILLIC LETTER KA;Mn;230;NSM;;;;;N;;;;;
-2DE7;COMBINING CYRILLIC LETTER EL;Mn;230;NSM;;;;;N;;;;;
-2DE8;COMBINING CYRILLIC LETTER EM;Mn;230;NSM;;;;;N;;;;;
-2DE9;COMBINING CYRILLIC LETTER EN;Mn;230;NSM;;;;;N;;;;;
-2DEA;COMBINING CYRILLIC LETTER O;Mn;230;NSM;;;;;N;;;;;
-2DEB;COMBINING CYRILLIC LETTER PE;Mn;230;NSM;;;;;N;;;;;
-2DEC;COMBINING CYRILLIC LETTER ER;Mn;230;NSM;;;;;N;;;;;
-2DED;COMBINING CYRILLIC LETTER ES;Mn;230;NSM;;;;;N;;;;;
-2DEE;COMBINING CYRILLIC LETTER TE;Mn;230;NSM;;;;;N;;;;;
-2DEF;COMBINING CYRILLIC LETTER HA;Mn;230;NSM;;;;;N;;;;;
-2DF0;COMBINING CYRILLIC LETTER TSE;Mn;230;NSM;;;;;N;;;;;
-2DF1;COMBINING CYRILLIC LETTER CHE;Mn;230;NSM;;;;;N;;;;;
-2DF2;COMBINING CYRILLIC LETTER SHA;Mn;230;NSM;;;;;N;;;;;
-2DF3;COMBINING CYRILLIC LETTER SHCHA;Mn;230;NSM;;;;;N;;;;;
-2DF4;COMBINING CYRILLIC LETTER FITA;Mn;230;NSM;;;;;N;;;;;
-2DF5;COMBINING CYRILLIC LETTER ES-TE;Mn;230;NSM;;;;;N;;;;;
-2DF6;COMBINING CYRILLIC LETTER A;Mn;230;NSM;;;;;N;;;;;
-2DF7;COMBINING CYRILLIC LETTER IE;Mn;230;NSM;;;;;N;;;;;
-2DF8;COMBINING CYRILLIC LETTER DJERV;Mn;230;NSM;;;;;N;;;;;
-2DF9;COMBINING CYRILLIC LETTER MONOGRAPH UK;Mn;230;NSM;;;;;N;;;;;
-2DFA;COMBINING CYRILLIC LETTER YAT;Mn;230;NSM;;;;;N;;;;;
-2DFB;COMBINING CYRILLIC LETTER YU;Mn;230;NSM;;;;;N;;;;;
-2DFC;COMBINING CYRILLIC LETTER IOTIFIED A;Mn;230;NSM;;;;;N;;;;;
-2DFD;COMBINING CYRILLIC LETTER LITTLE YUS;Mn;230;NSM;;;;;N;;;;;
-2DFE;COMBINING CYRILLIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;;
-2DFF;COMBINING CYRILLIC LETTER IOTIFIED BIG YUS;Mn;230;NSM;;;;;N;;;;;
-2E00;RIGHT ANGLE SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;;
-2E01;RIGHT ANGLE DOTTED SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;;
-2E02;LEFT SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;;
-2E03;RIGHT SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;;
-2E04;LEFT DOTTED SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;;
-2E05;RIGHT DOTTED SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;;
-2E06;RAISED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;;
-2E07;RAISED DOTTED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;;
-2E08;DOTTED TRANSPOSITION MARKER;Po;0;ON;;;;;N;;;;;
-2E09;LEFT TRANSPOSITION BRACKET;Pi;0;ON;;;;;Y;;;;;
-2E0A;RIGHT TRANSPOSITION BRACKET;Pf;0;ON;;;;;Y;;;;;
-2E0B;RAISED SQUARE;Po;0;ON;;;;;N;;;;;
-2E0C;LEFT RAISED OMISSION BRACKET;Pi;0;ON;;;;;Y;;;;;
-2E0D;RIGHT RAISED OMISSION BRACKET;Pf;0;ON;;;;;Y;;;;;
-2E0E;EDITORIAL CORONIS;Po;0;ON;;;;;N;;;;;
-2E0F;PARAGRAPHOS;Po;0;ON;;;;;N;;;;;
-2E10;FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;;
-2E11;REVERSED FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;;
-2E12;HYPODIASTOLE;Po;0;ON;;;;;N;;;;;
-2E13;DOTTED OBELOS;Po;0;ON;;;;;N;;;;;
-2E14;DOWNWARDS ANCORA;Po;0;ON;;;;;N;;;;;
-2E15;UPWARDS ANCORA;Po;0;ON;;;;;N;;;;;
-2E16;DOTTED RIGHT-POINTING ANGLE;Po;0;ON;;;;;N;;;;;
-2E17;DOUBLE OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;;
-2E18;INVERTED INTERROBANG;Po;0;ON;;;;;N;;;;;
-2E19;PALM BRANCH;Po;0;ON;;;;;N;;;;;
-2E1A;HYPHEN WITH DIAERESIS;Pd;0;ON;;;;;N;;;;;
-2E1B;TILDE WITH RING ABOVE;Po;0;ON;;;;;N;;;;;
-2E1C;LEFT LOW PARAPHRASE BRACKET;Pi;0;ON;;;;;Y;;;;;
-2E1D;RIGHT LOW PARAPHRASE BRACKET;Pf;0;ON;;;;;Y;;;;;
-2E1E;TILDE WITH DOT ABOVE;Po;0;ON;;;;;N;;;;;
-2E1F;TILDE WITH DOT BELOW;Po;0;ON;;;;;N;;;;;
-2E20;LEFT VERTICAL BAR WITH QUILL;Pi;0;ON;;;;;Y;;;;;
-2E21;RIGHT VERTICAL BAR WITH QUILL;Pf;0;ON;;;;;Y;;;;;
-2E22;TOP LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;;
-2E23;TOP RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;;
-2E24;BOTTOM LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;;
-2E25;BOTTOM RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;;
-2E26;LEFT SIDEWAYS U BRACKET;Ps;0;ON;;;;;Y;;;;;
-2E27;RIGHT SIDEWAYS U BRACKET;Pe;0;ON;;;;;Y;;;;;
-2E28;LEFT DOUBLE PARENTHESIS;Ps;0;ON;;;;;Y;;;;;
-2E29;RIGHT DOUBLE PARENTHESIS;Pe;0;ON;;;;;Y;;;;;
-2E2A;TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-2E2B;ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;;
-2E2C;SQUARED FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-2E2D;FIVE DOT MARK;Po;0;ON;;;;;N;;;;;
-2E2E;REVERSED QUESTION MARK;Po;0;ON;;;;;N;;;;;
-2E2F;VERTICAL TILDE;Lm;0;ON;;;;;N;;;;;
-2E30;RING POINT;Po;0;ON;;;;;N;;;;;
-2E31;WORD SEPARATOR MIDDLE DOT;Po;0;ON;;;;;N;;;;;
-2E32;TURNED COMMA;Po;0;ON;;;;;N;;;;;
-2E33;RAISED DOT;Po;0;ON;;;;;N;;;;;
-2E34;RAISED COMMA;Po;0;ON;;;;;N;;;;;
-2E35;TURNED SEMICOLON;Po;0;ON;;;;;N;;;;;
-2E36;DAGGER WITH LEFT GUARD;Po;0;ON;;;;;N;;;;;
-2E37;DAGGER WITH RIGHT GUARD;Po;0;ON;;;;;N;;;;;
-2E38;TURNED DAGGER;Po;0;ON;;;;;N;;;;;
-2E39;TOP HALF SECTION SIGN;Po;0;ON;;;;;N;;;;;
-2E3A;TWO-EM DASH;Pd;0;ON;;;;;N;;;;;
-2E3B;THREE-EM DASH;Pd;0;ON;;;;;N;;;;;
-2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;;
-2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;;
-2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;;
-2E83;CJK RADICAL SECOND TWO;So;0;ON;;;;;N;;;;;
-2E84;CJK RADICAL SECOND THREE;So;0;ON;;;;;N;;;;;
-2E85;CJK RADICAL PERSON;So;0;ON;;;;;N;;;;;
-2E86;CJK RADICAL BOX;So;0;ON;;;;;N;;;;;
-2E87;CJK RADICAL TABLE;So;0;ON;;;;;N;;;;;
-2E88;CJK RADICAL KNIFE ONE;So;0;ON;;;;;N;;;;;
-2E89;CJK RADICAL KNIFE TWO;So;0;ON;;;;;N;;;;;
-2E8A;CJK RADICAL DIVINATION;So;0;ON;;;;;N;;;;;
-2E8B;CJK RADICAL SEAL;So;0;ON;;;;;N;;;;;
-2E8C;CJK RADICAL SMALL ONE;So;0;ON;;;;;N;;;;;
-2E8D;CJK RADICAL SMALL TWO;So;0;ON;;;;;N;;;;;
-2E8E;CJK RADICAL LAME ONE;So;0;ON;;;;;N;;;;;
-2E8F;CJK RADICAL LAME TWO;So;0;ON;;;;;N;;;;;
-2E90;CJK RADICAL LAME THREE;So;0;ON;;;;;N;;;;;
-2E91;CJK RADICAL LAME FOUR;So;0;ON;;;;;N;;;;;
-2E92;CJK RADICAL SNAKE;So;0;ON;;;;;N;;;;;
-2E93;CJK RADICAL THREAD;So;0;ON;;;;;N;;;;;
-2E94;CJK RADICAL SNOUT ONE;So;0;ON;;;;;N;;;;;
-2E95;CJK RADICAL SNOUT TWO;So;0;ON;;;;;N;;;;;
-2E96;CJK RADICAL HEART ONE;So;0;ON;;;;;N;;;;;
-2E97;CJK RADICAL HEART TWO;So;0;ON;;;;;N;;;;;
-2E98;CJK RADICAL HAND;So;0;ON;;;;;N;;;;;
-2E99;CJK RADICAL RAP;So;0;ON;;;;;N;;;;;
-2E9B;CJK RADICAL CHOKE;So;0;ON;;;;;N;;;;;
-2E9C;CJK RADICAL SUN;So;0;ON;;;;;N;;;;;
-2E9D;CJK RADICAL MOON;So;0;ON;;;;;N;;;;;
-2E9E;CJK RADICAL DEATH;So;0;ON;;;;;N;;;;;
-2E9F;CJK RADICAL MOTHER;So;0;ON;<compat> 6BCD;;;;N;;;;;
-2EA0;CJK RADICAL CIVILIAN;So;0;ON;;;;;N;;;;;
-2EA1;CJK RADICAL WATER ONE;So;0;ON;;;;;N;;;;;
-2EA2;CJK RADICAL WATER TWO;So;0;ON;;;;;N;;;;;
-2EA3;CJK RADICAL FIRE;So;0;ON;;;;;N;;;;;
-2EA4;CJK RADICAL PAW ONE;So;0;ON;;;;;N;;;;;
-2EA5;CJK RADICAL PAW TWO;So;0;ON;;;;;N;;;;;
-2EA6;CJK RADICAL SIMPLIFIED HALF TREE TRUNK;So;0;ON;;;;;N;;;;;
-2EA7;CJK RADICAL COW;So;0;ON;;;;;N;;;;;
-2EA8;CJK RADICAL DOG;So;0;ON;;;;;N;;;;;
-2EA9;CJK RADICAL JADE;So;0;ON;;;;;N;;;;;
-2EAA;CJK RADICAL BOLT OF CLOTH;So;0;ON;;;;;N;;;;;
-2EAB;CJK RADICAL EYE;So;0;ON;;;;;N;;;;;
-2EAC;CJK RADICAL SPIRIT ONE;So;0;ON;;;;;N;;;;;
-2EAD;CJK RADICAL SPIRIT TWO;So;0;ON;;;;;N;;;;;
-2EAE;CJK RADICAL BAMBOO;So;0;ON;;;;;N;;;;;
-2EAF;CJK RADICAL SILK;So;0;ON;;;;;N;;;;;
-2EB0;CJK RADICAL C-SIMPLIFIED SILK;So;0;ON;;;;;N;;;;;
-2EB1;CJK RADICAL NET ONE;So;0;ON;;;;;N;;;;;
-2EB2;CJK RADICAL NET TWO;So;0;ON;;;;;N;;;;;
-2EB3;CJK RADICAL NET THREE;So;0;ON;;;;;N;;;;;
-2EB4;CJK RADICAL NET FOUR;So;0;ON;;;;;N;;;;;
-2EB5;CJK RADICAL MESH;So;0;ON;;;;;N;;;;;
-2EB6;CJK RADICAL SHEEP;So;0;ON;;;;;N;;;;;
-2EB7;CJK RADICAL RAM;So;0;ON;;;;;N;;;;;
-2EB8;CJK RADICAL EWE;So;0;ON;;;;;N;;;;;
-2EB9;CJK RADICAL OLD;So;0;ON;;;;;N;;;;;
-2EBA;CJK RADICAL BRUSH ONE;So;0;ON;;;;;N;;;;;
-2EBB;CJK RADICAL BRUSH TWO;So;0;ON;;;;;N;;;;;
-2EBC;CJK RADICAL MEAT;So;0;ON;;;;;N;;;;;
-2EBD;CJK RADICAL MORTAR;So;0;ON;;;;;N;;;;;
-2EBE;CJK RADICAL GRASS ONE;So;0;ON;;;;;N;;;;;
-2EBF;CJK RADICAL GRASS TWO;So;0;ON;;;;;N;;;;;
-2EC0;CJK RADICAL GRASS THREE;So;0;ON;;;;;N;;;;;
-2EC1;CJK RADICAL TIGER;So;0;ON;;;;;N;;;;;
-2EC2;CJK RADICAL CLOTHES;So;0;ON;;;;;N;;;;;
-2EC3;CJK RADICAL WEST ONE;So;0;ON;;;;;N;;;;;
-2EC4;CJK RADICAL WEST TWO;So;0;ON;;;;;N;;;;;
-2EC5;CJK RADICAL C-SIMPLIFIED SEE;So;0;ON;;;;;N;;;;;
-2EC6;CJK RADICAL SIMPLIFIED HORN;So;0;ON;;;;;N;;;;;
-2EC7;CJK RADICAL HORN;So;0;ON;;;;;N;;;;;
-2EC8;CJK RADICAL C-SIMPLIFIED SPEECH;So;0;ON;;;;;N;;;;;
-2EC9;CJK RADICAL C-SIMPLIFIED SHELL;So;0;ON;;;;;N;;;;;
-2ECA;CJK RADICAL FOOT;So;0;ON;;;;;N;;;;;
-2ECB;CJK RADICAL C-SIMPLIFIED CART;So;0;ON;;;;;N;;;;;
-2ECC;CJK RADICAL SIMPLIFIED WALK;So;0;ON;;;;;N;;;;;
-2ECD;CJK RADICAL WALK ONE;So;0;ON;;;;;N;;;;;
-2ECE;CJK RADICAL WALK TWO;So;0;ON;;;;;N;;;;;
-2ECF;CJK RADICAL CITY;So;0;ON;;;;;N;;;;;
-2ED0;CJK RADICAL C-SIMPLIFIED GOLD;So;0;ON;;;;;N;;;;;
-2ED1;CJK RADICAL LONG ONE;So;0;ON;;;;;N;;;;;
-2ED2;CJK RADICAL LONG TWO;So;0;ON;;;;;N;;;;;
-2ED3;CJK RADICAL C-SIMPLIFIED LONG;So;0;ON;;;;;N;;;;;
-2ED4;CJK RADICAL C-SIMPLIFIED GATE;So;0;ON;;;;;N;;;;;
-2ED5;CJK RADICAL MOUND ONE;So;0;ON;;;;;N;;;;;
-2ED6;CJK RADICAL MOUND TWO;So;0;ON;;;;;N;;;;;
-2ED7;CJK RADICAL RAIN;So;0;ON;;;;;N;;;;;
-2ED8;CJK RADICAL BLUE;So;0;ON;;;;;N;;;;;
-2ED9;CJK RADICAL C-SIMPLIFIED TANNED LEATHER;So;0;ON;;;;;N;;;;;
-2EDA;CJK RADICAL C-SIMPLIFIED LEAF;So;0;ON;;;;;N;;;;;
-2EDB;CJK RADICAL C-SIMPLIFIED WIND;So;0;ON;;;;;N;;;;;
-2EDC;CJK RADICAL C-SIMPLIFIED FLY;So;0;ON;;;;;N;;;;;
-2EDD;CJK RADICAL EAT ONE;So;0;ON;;;;;N;;;;;
-2EDE;CJK RADICAL EAT TWO;So;0;ON;;;;;N;;;;;
-2EDF;CJK RADICAL EAT THREE;So;0;ON;;;;;N;;;;;
-2EE0;CJK RADICAL C-SIMPLIFIED EAT;So;0;ON;;;;;N;;;;;
-2EE1;CJK RADICAL HEAD;So;0;ON;;;;;N;;;;;
-2EE2;CJK RADICAL C-SIMPLIFIED HORSE;So;0;ON;;;;;N;;;;;
-2EE3;CJK RADICAL BONE;So;0;ON;;;;;N;;;;;
-2EE4;CJK RADICAL GHOST;So;0;ON;;;;;N;;;;;
-2EE5;CJK RADICAL C-SIMPLIFIED FISH;So;0;ON;;;;;N;;;;;
-2EE6;CJK RADICAL C-SIMPLIFIED BIRD;So;0;ON;;;;;N;;;;;
-2EE7;CJK RADICAL C-SIMPLIFIED SALT;So;0;ON;;;;;N;;;;;
-2EE8;CJK RADICAL SIMPLIFIED WHEAT;So;0;ON;;;;;N;;;;;
-2EE9;CJK RADICAL SIMPLIFIED YELLOW;So;0;ON;;;;;N;;;;;
-2EEA;CJK RADICAL C-SIMPLIFIED FROG;So;0;ON;;;;;N;;;;;
-2EEB;CJK RADICAL J-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;;
-2EEC;CJK RADICAL C-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;;
-2EED;CJK RADICAL J-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;;
-2EEE;CJK RADICAL C-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;;
-2EEF;CJK RADICAL J-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;;
-2EF0;CJK RADICAL C-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;;
-2EF1;CJK RADICAL TURTLE;So;0;ON;;;;;N;;;;;
-2EF2;CJK RADICAL J-SIMPLIFIED TURTLE;So;0;ON;;;;;N;;;;;
-2EF3;CJK RADICAL C-SIMPLIFIED TURTLE;So;0;ON;<compat> 9F9F;;;;N;;;;;
-2F00;KANGXI RADICAL ONE;So;0;ON;<compat> 4E00;;;;N;;;;;
-2F01;KANGXI RADICAL LINE;So;0;ON;<compat> 4E28;;;;N;;;;;
-2F02;KANGXI RADICAL DOT;So;0;ON;<compat> 4E36;;;;N;;;;;
-2F03;KANGXI RADICAL SLASH;So;0;ON;<compat> 4E3F;;;;N;;;;;
-2F04;KANGXI RADICAL SECOND;So;0;ON;<compat> 4E59;;;;N;;;;;
-2F05;KANGXI RADICAL HOOK;So;0;ON;<compat> 4E85;;;;N;;;;;
-2F06;KANGXI RADICAL TWO;So;0;ON;<compat> 4E8C;;;;N;;;;;
-2F07;KANGXI RADICAL LID;So;0;ON;<compat> 4EA0;;;;N;;;;;
-2F08;KANGXI RADICAL MAN;So;0;ON;<compat> 4EBA;;;;N;;;;;
-2F09;KANGXI RADICAL LEGS;So;0;ON;<compat> 513F;;;;N;;;;;
-2F0A;KANGXI RADICAL ENTER;So;0;ON;<compat> 5165;;;;N;;;;;
-2F0B;KANGXI RADICAL EIGHT;So;0;ON;<compat> 516B;;;;N;;;;;
-2F0C;KANGXI RADICAL DOWN BOX;So;0;ON;<compat> 5182;;;;N;;;;;
-2F0D;KANGXI RADICAL COVER;So;0;ON;<compat> 5196;;;;N;;;;;
-2F0E;KANGXI RADICAL ICE;So;0;ON;<compat> 51AB;;;;N;;;;;
-2F0F;KANGXI RADICAL TABLE;So;0;ON;<compat> 51E0;;;;N;;;;;
-2F10;KANGXI RADICAL OPEN BOX;So;0;ON;<compat> 51F5;;;;N;;;;;
-2F11;KANGXI RADICAL KNIFE;So;0;ON;<compat> 5200;;;;N;;;;;
-2F12;KANGXI RADICAL POWER;So;0;ON;<compat> 529B;;;;N;;;;;
-2F13;KANGXI RADICAL WRAP;So;0;ON;<compat> 52F9;;;;N;;;;;
-2F14;KANGXI RADICAL SPOON;So;0;ON;<compat> 5315;;;;N;;;;;
-2F15;KANGXI RADICAL RIGHT OPEN BOX;So;0;ON;<compat> 531A;;;;N;;;;;
-2F16;KANGXI RADICAL HIDING ENCLOSURE;So;0;ON;<compat> 5338;;;;N;;;;;
-2F17;KANGXI RADICAL TEN;So;0;ON;<compat> 5341;;;;N;;;;;
-2F18;KANGXI RADICAL DIVINATION;So;0;ON;<compat> 535C;;;;N;;;;;
-2F19;KANGXI RADICAL SEAL;So;0;ON;<compat> 5369;;;;N;;;;;
-2F1A;KANGXI RADICAL CLIFF;So;0;ON;<compat> 5382;;;;N;;;;;
-2F1B;KANGXI RADICAL PRIVATE;So;0;ON;<compat> 53B6;;;;N;;;;;
-2F1C;KANGXI RADICAL AGAIN;So;0;ON;<compat> 53C8;;;;N;;;;;
-2F1D;KANGXI RADICAL MOUTH;So;0;ON;<compat> 53E3;;;;N;;;;;
-2F1E;KANGXI RADICAL ENCLOSURE;So;0;ON;<compat> 56D7;;;;N;;;;;
-2F1F;KANGXI RADICAL EARTH;So;0;ON;<compat> 571F;;;;N;;;;;
-2F20;KANGXI RADICAL SCHOLAR;So;0;ON;<compat> 58EB;;;;N;;;;;
-2F21;KANGXI RADICAL GO;So;0;ON;<compat> 5902;;;;N;;;;;
-2F22;KANGXI RADICAL GO SLOWLY;So;0;ON;<compat> 590A;;;;N;;;;;
-2F23;KANGXI RADICAL EVENING;So;0;ON;<compat> 5915;;;;N;;;;;
-2F24;KANGXI RADICAL BIG;So;0;ON;<compat> 5927;;;;N;;;;;
-2F25;KANGXI RADICAL WOMAN;So;0;ON;<compat> 5973;;;;N;;;;;
-2F26;KANGXI RADICAL CHILD;So;0;ON;<compat> 5B50;;;;N;;;;;
-2F27;KANGXI RADICAL ROOF;So;0;ON;<compat> 5B80;;;;N;;;;;
-2F28;KANGXI RADICAL INCH;So;0;ON;<compat> 5BF8;;;;N;;;;;
-2F29;KANGXI RADICAL SMALL;So;0;ON;<compat> 5C0F;;;;N;;;;;
-2F2A;KANGXI RADICAL LAME;So;0;ON;<compat> 5C22;;;;N;;;;;
-2F2B;KANGXI RADICAL CORPSE;So;0;ON;<compat> 5C38;;;;N;;;;;
-2F2C;KANGXI RADICAL SPROUT;So;0;ON;<compat> 5C6E;;;;N;;;;;
-2F2D;KANGXI RADICAL MOUNTAIN;So;0;ON;<compat> 5C71;;;;N;;;;;
-2F2E;KANGXI RADICAL RIVER;So;0;ON;<compat> 5DDB;;;;N;;;;;
-2F2F;KANGXI RADICAL WORK;So;0;ON;<compat> 5DE5;;;;N;;;;;
-2F30;KANGXI RADICAL ONESELF;So;0;ON;<compat> 5DF1;;;;N;;;;;
-2F31;KANGXI RADICAL TURBAN;So;0;ON;<compat> 5DFE;;;;N;;;;;
-2F32;KANGXI RADICAL DRY;So;0;ON;<compat> 5E72;;;;N;;;;;
-2F33;KANGXI RADICAL SHORT THREAD;So;0;ON;<compat> 5E7A;;;;N;;;;;
-2F34;KANGXI RADICAL DOTTED CLIFF;So;0;ON;<compat> 5E7F;;;;N;;;;;
-2F35;KANGXI RADICAL LONG STRIDE;So;0;ON;<compat> 5EF4;;;;N;;;;;
-2F36;KANGXI RADICAL TWO HANDS;So;0;ON;<compat> 5EFE;;;;N;;;;;
-2F37;KANGXI RADICAL SHOOT;So;0;ON;<compat> 5F0B;;;;N;;;;;
-2F38;KANGXI RADICAL BOW;So;0;ON;<compat> 5F13;;;;N;;;;;
-2F39;KANGXI RADICAL SNOUT;So;0;ON;<compat> 5F50;;;;N;;;;;
-2F3A;KANGXI RADICAL BRISTLE;So;0;ON;<compat> 5F61;;;;N;;;;;
-2F3B;KANGXI RADICAL STEP;So;0;ON;<compat> 5F73;;;;N;;;;;
-2F3C;KANGXI RADICAL HEART;So;0;ON;<compat> 5FC3;;;;N;;;;;
-2F3D;KANGXI RADICAL HALBERD;So;0;ON;<compat> 6208;;;;N;;;;;
-2F3E;KANGXI RADICAL DOOR;So;0;ON;<compat> 6236;;;;N;;;;;
-2F3F;KANGXI RADICAL HAND;So;0;ON;<compat> 624B;;;;N;;;;;
-2F40;KANGXI RADICAL BRANCH;So;0;ON;<compat> 652F;;;;N;;;;;
-2F41;KANGXI RADICAL RAP;So;0;ON;<compat> 6534;;;;N;;;;;
-2F42;KANGXI RADICAL SCRIPT;So;0;ON;<compat> 6587;;;;N;;;;;
-2F43;KANGXI RADICAL DIPPER;So;0;ON;<compat> 6597;;;;N;;;;;
-2F44;KANGXI RADICAL AXE;So;0;ON;<compat> 65A4;;;;N;;;;;
-2F45;KANGXI RADICAL SQUARE;So;0;ON;<compat> 65B9;;;;N;;;;;
-2F46;KANGXI RADICAL NOT;So;0;ON;<compat> 65E0;;;;N;;;;;
-2F47;KANGXI RADICAL SUN;So;0;ON;<compat> 65E5;;;;N;;;;;
-2F48;KANGXI RADICAL SAY;So;0;ON;<compat> 66F0;;;;N;;;;;
-2F49;KANGXI RADICAL MOON;So;0;ON;<compat> 6708;;;;N;;;;;
-2F4A;KANGXI RADICAL TREE;So;0;ON;<compat> 6728;;;;N;;;;;
-2F4B;KANGXI RADICAL LACK;So;0;ON;<compat> 6B20;;;;N;;;;;
-2F4C;KANGXI RADICAL STOP;So;0;ON;<compat> 6B62;;;;N;;;;;
-2F4D;KANGXI RADICAL DEATH;So;0;ON;<compat> 6B79;;;;N;;;;;
-2F4E;KANGXI RADICAL WEAPON;So;0;ON;<compat> 6BB3;;;;N;;;;;
-2F4F;KANGXI RADICAL DO NOT;So;0;ON;<compat> 6BCB;;;;N;;;;;
-2F50;KANGXI RADICAL COMPARE;So;0;ON;<compat> 6BD4;;;;N;;;;;
-2F51;KANGXI RADICAL FUR;So;0;ON;<compat> 6BDB;;;;N;;;;;
-2F52;KANGXI RADICAL CLAN;So;0;ON;<compat> 6C0F;;;;N;;;;;
-2F53;KANGXI RADICAL STEAM;So;0;ON;<compat> 6C14;;;;N;;;;;
-2F54;KANGXI RADICAL WATER;So;0;ON;<compat> 6C34;;;;N;;;;;
-2F55;KANGXI RADICAL FIRE;So;0;ON;<compat> 706B;;;;N;;;;;
-2F56;KANGXI RADICAL CLAW;So;0;ON;<compat> 722A;;;;N;;;;;
-2F57;KANGXI RADICAL FATHER;So;0;ON;<compat> 7236;;;;N;;;;;
-2F58;KANGXI RADICAL DOUBLE X;So;0;ON;<compat> 723B;;;;N;;;;;
-2F59;KANGXI RADICAL HALF TREE TRUNK;So;0;ON;<compat> 723F;;;;N;;;;;
-2F5A;KANGXI RADICAL SLICE;So;0;ON;<compat> 7247;;;;N;;;;;
-2F5B;KANGXI RADICAL FANG;So;0;ON;<compat> 7259;;;;N;;;;;
-2F5C;KANGXI RADICAL COW;So;0;ON;<compat> 725B;;;;N;;;;;
-2F5D;KANGXI RADICAL DOG;So;0;ON;<compat> 72AC;;;;N;;;;;
-2F5E;KANGXI RADICAL PROFOUND;So;0;ON;<compat> 7384;;;;N;;;;;
-2F5F;KANGXI RADICAL JADE;So;0;ON;<compat> 7389;;;;N;;;;;
-2F60;KANGXI RADICAL MELON;So;0;ON;<compat> 74DC;;;;N;;;;;
-2F61;KANGXI RADICAL TILE;So;0;ON;<compat> 74E6;;;;N;;;;;
-2F62;KANGXI RADICAL SWEET;So;0;ON;<compat> 7518;;;;N;;;;;
-2F63;KANGXI RADICAL LIFE;So;0;ON;<compat> 751F;;;;N;;;;;
-2F64;KANGXI RADICAL USE;So;0;ON;<compat> 7528;;;;N;;;;;
-2F65;KANGXI RADICAL FIELD;So;0;ON;<compat> 7530;;;;N;;;;;
-2F66;KANGXI RADICAL BOLT OF CLOTH;So;0;ON;<compat> 758B;;;;N;;;;;
-2F67;KANGXI RADICAL SICKNESS;So;0;ON;<compat> 7592;;;;N;;;;;
-2F68;KANGXI RADICAL DOTTED TENT;So;0;ON;<compat> 7676;;;;N;;;;;
-2F69;KANGXI RADICAL WHITE;So;0;ON;<compat> 767D;;;;N;;;;;
-2F6A;KANGXI RADICAL SKIN;So;0;ON;<compat> 76AE;;;;N;;;;;
-2F6B;KANGXI RADICAL DISH;So;0;ON;<compat> 76BF;;;;N;;;;;
-2F6C;KANGXI RADICAL EYE;So;0;ON;<compat> 76EE;;;;N;;;;;
-2F6D;KANGXI RADICAL SPEAR;So;0;ON;<compat> 77DB;;;;N;;;;;
-2F6E;KANGXI RADICAL ARROW;So;0;ON;<compat> 77E2;;;;N;;;;;
-2F6F;KANGXI RADICAL STONE;So;0;ON;<compat> 77F3;;;;N;;;;;
-2F70;KANGXI RADICAL SPIRIT;So;0;ON;<compat> 793A;;;;N;;;;;
-2F71;KANGXI RADICAL TRACK;So;0;ON;<compat> 79B8;;;;N;;;;;
-2F72;KANGXI RADICAL GRAIN;So;0;ON;<compat> 79BE;;;;N;;;;;
-2F73;KANGXI RADICAL CAVE;So;0;ON;<compat> 7A74;;;;N;;;;;
-2F74;KANGXI RADICAL STAND;So;0;ON;<compat> 7ACB;;;;N;;;;;
-2F75;KANGXI RADICAL BAMBOO;So;0;ON;<compat> 7AF9;;;;N;;;;;
-2F76;KANGXI RADICAL RICE;So;0;ON;<compat> 7C73;;;;N;;;;;
-2F77;KANGXI RADICAL SILK;So;0;ON;<compat> 7CF8;;;;N;;;;;
-2F78;KANGXI RADICAL JAR;So;0;ON;<compat> 7F36;;;;N;;;;;
-2F79;KANGXI RADICAL NET;So;0;ON;<compat> 7F51;;;;N;;;;;
-2F7A;KANGXI RADICAL SHEEP;So;0;ON;<compat> 7F8A;;;;N;;;;;
-2F7B;KANGXI RADICAL FEATHER;So;0;ON;<compat> 7FBD;;;;N;;;;;
-2F7C;KANGXI RADICAL OLD;So;0;ON;<compat> 8001;;;;N;;;;;
-2F7D;KANGXI RADICAL AND;So;0;ON;<compat> 800C;;;;N;;;;;
-2F7E;KANGXI RADICAL PLOW;So;0;ON;<compat> 8012;;;;N;;;;;
-2F7F;KANGXI RADICAL EAR;So;0;ON;<compat> 8033;;;;N;;;;;
-2F80;KANGXI RADICAL BRUSH;So;0;ON;<compat> 807F;;;;N;;;;;
-2F81;KANGXI RADICAL MEAT;So;0;ON;<compat> 8089;;;;N;;;;;
-2F82;KANGXI RADICAL MINISTER;So;0;ON;<compat> 81E3;;;;N;;;;;
-2F83;KANGXI RADICAL SELF;So;0;ON;<compat> 81EA;;;;N;;;;;
-2F84;KANGXI RADICAL ARRIVE;So;0;ON;<compat> 81F3;;;;N;;;;;
-2F85;KANGXI RADICAL MORTAR;So;0;ON;<compat> 81FC;;;;N;;;;;
-2F86;KANGXI RADICAL TONGUE;So;0;ON;<compat> 820C;;;;N;;;;;
-2F87;KANGXI RADICAL OPPOSE;So;0;ON;<compat> 821B;;;;N;;;;;
-2F88;KANGXI RADICAL BOAT;So;0;ON;<compat> 821F;;;;N;;;;;
-2F89;KANGXI RADICAL STOPPING;So;0;ON;<compat> 826E;;;;N;;;;;
-2F8A;KANGXI RADICAL COLOR;So;0;ON;<compat> 8272;;;;N;;;;;
-2F8B;KANGXI RADICAL GRASS;So;0;ON;<compat> 8278;;;;N;;;;;
-2F8C;KANGXI RADICAL TIGER;So;0;ON;<compat> 864D;;;;N;;;;;
-2F8D;KANGXI RADICAL INSECT;So;0;ON;<compat> 866B;;;;N;;;;;
-2F8E;KANGXI RADICAL BLOOD;So;0;ON;<compat> 8840;;;;N;;;;;
-2F8F;KANGXI RADICAL WALK ENCLOSURE;So;0;ON;<compat> 884C;;;;N;;;;;
-2F90;KANGXI RADICAL CLOTHES;So;0;ON;<compat> 8863;;;;N;;;;;
-2F91;KANGXI RADICAL WEST;So;0;ON;<compat> 897E;;;;N;;;;;
-2F92;KANGXI RADICAL SEE;So;0;ON;<compat> 898B;;;;N;;;;;
-2F93;KANGXI RADICAL HORN;So;0;ON;<compat> 89D2;;;;N;;;;;
-2F94;KANGXI RADICAL SPEECH;So;0;ON;<compat> 8A00;;;;N;;;;;
-2F95;KANGXI RADICAL VALLEY;So;0;ON;<compat> 8C37;;;;N;;;;;
-2F96;KANGXI RADICAL BEAN;So;0;ON;<compat> 8C46;;;;N;;;;;
-2F97;KANGXI RADICAL PIG;So;0;ON;<compat> 8C55;;;;N;;;;;
-2F98;KANGXI RADICAL BADGER;So;0;ON;<compat> 8C78;;;;N;;;;;
-2F99;KANGXI RADICAL SHELL;So;0;ON;<compat> 8C9D;;;;N;;;;;
-2F9A;KANGXI RADICAL RED;So;0;ON;<compat> 8D64;;;;N;;;;;
-2F9B;KANGXI RADICAL RUN;So;0;ON;<compat> 8D70;;;;N;;;;;
-2F9C;KANGXI RADICAL FOOT;So;0;ON;<compat> 8DB3;;;;N;;;;;
-2F9D;KANGXI RADICAL BODY;So;0;ON;<compat> 8EAB;;;;N;;;;;
-2F9E;KANGXI RADICAL CART;So;0;ON;<compat> 8ECA;;;;N;;;;;
-2F9F;KANGXI RADICAL BITTER;So;0;ON;<compat> 8F9B;;;;N;;;;;
-2FA0;KANGXI RADICAL MORNING;So;0;ON;<compat> 8FB0;;;;N;;;;;
-2FA1;KANGXI RADICAL WALK;So;0;ON;<compat> 8FB5;;;;N;;;;;
-2FA2;KANGXI RADICAL CITY;So;0;ON;<compat> 9091;;;;N;;;;;
-2FA3;KANGXI RADICAL WINE;So;0;ON;<compat> 9149;;;;N;;;;;
-2FA4;KANGXI RADICAL DISTINGUISH;So;0;ON;<compat> 91C6;;;;N;;;;;
-2FA5;KANGXI RADICAL VILLAGE;So;0;ON;<compat> 91CC;;;;N;;;;;
-2FA6;KANGXI RADICAL GOLD;So;0;ON;<compat> 91D1;;;;N;;;;;
-2FA7;KANGXI RADICAL LONG;So;0;ON;<compat> 9577;;;;N;;;;;
-2FA8;KANGXI RADICAL GATE;So;0;ON;<compat> 9580;;;;N;;;;;
-2FA9;KANGXI RADICAL MOUND;So;0;ON;<compat> 961C;;;;N;;;;;
-2FAA;KANGXI RADICAL SLAVE;So;0;ON;<compat> 96B6;;;;N;;;;;
-2FAB;KANGXI RADICAL SHORT TAILED BIRD;So;0;ON;<compat> 96B9;;;;N;;;;;
-2FAC;KANGXI RADICAL RAIN;So;0;ON;<compat> 96E8;;;;N;;;;;
-2FAD;KANGXI RADICAL BLUE;So;0;ON;<compat> 9751;;;;N;;;;;
-2FAE;KANGXI RADICAL WRONG;So;0;ON;<compat> 975E;;;;N;;;;;
-2FAF;KANGXI RADICAL FACE;So;0;ON;<compat> 9762;;;;N;;;;;
-2FB0;KANGXI RADICAL LEATHER;So;0;ON;<compat> 9769;;;;N;;;;;
-2FB1;KANGXI RADICAL TANNED LEATHER;So;0;ON;<compat> 97CB;;;;N;;;;;
-2FB2;KANGXI RADICAL LEEK;So;0;ON;<compat> 97ED;;;;N;;;;;
-2FB3;KANGXI RADICAL SOUND;So;0;ON;<compat> 97F3;;;;N;;;;;
-2FB4;KANGXI RADICAL LEAF;So;0;ON;<compat> 9801;;;;N;;;;;
-2FB5;KANGXI RADICAL WIND;So;0;ON;<compat> 98A8;;;;N;;;;;
-2FB6;KANGXI RADICAL FLY;So;0;ON;<compat> 98DB;;;;N;;;;;
-2FB7;KANGXI RADICAL EAT;So;0;ON;<compat> 98DF;;;;N;;;;;
-2FB8;KANGXI RADICAL HEAD;So;0;ON;<compat> 9996;;;;N;;;;;
-2FB9;KANGXI RADICAL FRAGRANT;So;0;ON;<compat> 9999;;;;N;;;;;
-2FBA;KANGXI RADICAL HORSE;So;0;ON;<compat> 99AC;;;;N;;;;;
-2FBB;KANGXI RADICAL BONE;So;0;ON;<compat> 9AA8;;;;N;;;;;
-2FBC;KANGXI RADICAL TALL;So;0;ON;<compat> 9AD8;;;;N;;;;;
-2FBD;KANGXI RADICAL HAIR;So;0;ON;<compat> 9ADF;;;;N;;;;;
-2FBE;KANGXI RADICAL FIGHT;So;0;ON;<compat> 9B25;;;;N;;;;;
-2FBF;KANGXI RADICAL SACRIFICIAL WINE;So;0;ON;<compat> 9B2F;;;;N;;;;;
-2FC0;KANGXI RADICAL CAULDRON;So;0;ON;<compat> 9B32;;;;N;;;;;
-2FC1;KANGXI RADICAL GHOST;So;0;ON;<compat> 9B3C;;;;N;;;;;
-2FC2;KANGXI RADICAL FISH;So;0;ON;<compat> 9B5A;;;;N;;;;;
-2FC3;KANGXI RADICAL BIRD;So;0;ON;<compat> 9CE5;;;;N;;;;;
-2FC4;KANGXI RADICAL SALT;So;0;ON;<compat> 9E75;;;;N;;;;;
-2FC5;KANGXI RADICAL DEER;So;0;ON;<compat> 9E7F;;;;N;;;;;
-2FC6;KANGXI RADICAL WHEAT;So;0;ON;<compat> 9EA5;;;;N;;;;;
-2FC7;KANGXI RADICAL HEMP;So;0;ON;<compat> 9EBB;;;;N;;;;;
-2FC8;KANGXI RADICAL YELLOW;So;0;ON;<compat> 9EC3;;;;N;;;;;
-2FC9;KANGXI RADICAL MILLET;So;0;ON;<compat> 9ECD;;;;N;;;;;
-2FCA;KANGXI RADICAL BLACK;So;0;ON;<compat> 9ED1;;;;N;;;;;
-2FCB;KANGXI RADICAL EMBROIDERY;So;0;ON;<compat> 9EF9;;;;N;;;;;
-2FCC;KANGXI RADICAL FROG;So;0;ON;<compat> 9EFD;;;;N;;;;;
-2FCD;KANGXI RADICAL TRIPOD;So;0;ON;<compat> 9F0E;;;;N;;;;;
-2FCE;KANGXI RADICAL DRUM;So;0;ON;<compat> 9F13;;;;N;;;;;
-2FCF;KANGXI RADICAL RAT;So;0;ON;<compat> 9F20;;;;N;;;;;
-2FD0;KANGXI RADICAL NOSE;So;0;ON;<compat> 9F3B;;;;N;;;;;
-2FD1;KANGXI RADICAL EVEN;So;0;ON;<compat> 9F4A;;;;N;;;;;
-2FD2;KANGXI RADICAL TOOTH;So;0;ON;<compat> 9F52;;;;N;;;;;
-2FD3;KANGXI RADICAL DRAGON;So;0;ON;<compat> 9F8D;;;;N;;;;;
-2FD4;KANGXI RADICAL TURTLE;So;0;ON;<compat> 9F9C;;;;N;;;;;
-2FD5;KANGXI RADICAL FLUTE;So;0;ON;<compat> 9FA0;;;;N;;;;;
-2FF0;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT;So;0;ON;;;;;N;;;;;
-2FF1;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW;So;0;ON;;;;;N;;;;;
-2FF2;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT;So;0;ON;;;;;N;;;;;
-2FF3;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW;So;0;ON;;;;;N;;;;;
-2FF4;IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND;So;0;ON;;;;;N;;;;;
-2FF5;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE;So;0;ON;;;;;N;;;;;
-2FF6;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW;So;0;ON;;;;;N;;;;;
-2FF7;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT;So;0;ON;;;;;N;;;;;
-2FF8;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT;So;0;ON;;;;;N;;;;;
-2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;;
-2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;;
-2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;;
-3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
-3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;;
-3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;;
-3003;DITTO MARK;Po;0;ON;;;;;N;;;;;
-3004;JAPANESE INDUSTRIAL STANDARD SYMBOL;So;0;ON;;;;;N;;;;;
-3005;IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;;
-3006;IDEOGRAPHIC CLOSING MARK;Lo;0;L;;;;;N;;;;;
-3007;IDEOGRAPHIC NUMBER ZERO;Nl;0;L;;;;0;N;;;;;
-3008;LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING ANGLE BRACKET;;;;
-3009;RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING ANGLE BRACKET;;;;
-300A;LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING DOUBLE ANGLE BRACKET;;;;
-300B;RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING DOUBLE ANGLE BRACKET;;;;
-300C;LEFT CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING CORNER BRACKET;;;;
-300D;RIGHT CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING CORNER BRACKET;;;;
-300E;LEFT WHITE CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE CORNER BRACKET;;;;
-300F;RIGHT WHITE CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE CORNER BRACKET;;;;
-3010;LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING BLACK LENTICULAR BRACKET;;;;
-3011;RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING BLACK LENTICULAR BRACKET;;;;
-3012;POSTAL MARK;So;0;ON;;;;;N;;;;;
-3013;GETA MARK;So;0;ON;;;;;N;;;;;
-3014;LEFT TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING TORTOISE SHELL BRACKET;;;;
-3015;RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING TORTOISE SHELL BRACKET;;;;
-3016;LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE LENTICULAR BRACKET;;;;
-3017;RIGHT WHITE LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE LENTICULAR BRACKET;;;;
-3018;LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE TORTOISE SHELL BRACKET;;;;
-3019;RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE TORTOISE SHELL BRACKET;;;;
-301A;LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE SQUARE BRACKET;;;;
-301B;RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE SQUARE BRACKET;;;;
-301C;WAVE DASH;Pd;0;ON;;;;;N;;;;;
-301D;REVERSED DOUBLE PRIME QUOTATION MARK;Ps;0;ON;;;;;N;;;;;
-301E;DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;;
-301F;LOW DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;;
-3020;POSTAL MARK FACE;So;0;ON;;;;;N;;;;;
-3021;HANGZHOU NUMERAL ONE;Nl;0;L;;;;1;N;;;;;
-3022;HANGZHOU NUMERAL TWO;Nl;0;L;;;;2;N;;;;;
-3023;HANGZHOU NUMERAL THREE;Nl;0;L;;;;3;N;;;;;
-3024;HANGZHOU NUMERAL FOUR;Nl;0;L;;;;4;N;;;;;
-3025;HANGZHOU NUMERAL FIVE;Nl;0;L;;;;5;N;;;;;
-3026;HANGZHOU NUMERAL SIX;Nl;0;L;;;;6;N;;;;;
-3027;HANGZHOU NUMERAL SEVEN;Nl;0;L;;;;7;N;;;;;
-3028;HANGZHOU NUMERAL EIGHT;Nl;0;L;;;;8;N;;;;;
-3029;HANGZHOU NUMERAL NINE;Nl;0;L;;;;9;N;;;;;
-302A;IDEOGRAPHIC LEVEL TONE MARK;Mn;218;NSM;;;;;N;;;;;
-302B;IDEOGRAPHIC RISING TONE MARK;Mn;228;NSM;;;;;N;;;;;
-302C;IDEOGRAPHIC DEPARTING TONE MARK;Mn;232;NSM;;;;;N;;;;;
-302D;IDEOGRAPHIC ENTERING TONE MARK;Mn;222;NSM;;;;;N;;;;;
-302E;HANGUL SINGLE DOT TONE MARK;Mc;224;L;;;;;N;;;;;
-302F;HANGUL DOUBLE DOT TONE MARK;Mc;224;L;;;;;N;;;;;
-3030;WAVY DASH;Pd;0;ON;;;;;N;;;;;
-3031;VERTICAL KANA REPEAT MARK;Lm;0;L;;;;;N;;;;;
-3032;VERTICAL KANA REPEAT WITH VOICED SOUND MARK;Lm;0;L;;;;;N;;;;;
-3033;VERTICAL KANA REPEAT MARK UPPER HALF;Lm;0;L;;;;;N;;;;;
-3034;VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF;Lm;0;L;;;;;N;;;;;
-3035;VERTICAL KANA REPEAT MARK LOWER HALF;Lm;0;L;;;;;N;;;;;
-3036;CIRCLED POSTAL MARK;So;0;ON;<compat> 3012;;;;N;;;;;
-3037;IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL;So;0;ON;;;;;N;;;;;
-3038;HANGZHOU NUMERAL TEN;Nl;0;L;<compat> 5341;;;10;N;;;;;
-3039;HANGZHOU NUMERAL TWENTY;Nl;0;L;<compat> 5344;;;20;N;;;;;
-303A;HANGZHOU NUMERAL THIRTY;Nl;0;L;<compat> 5345;;;30;N;;;;;
-303B;VERTICAL IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;;
-303C;MASU MARK;Lo;0;L;;;;;N;;;;;
-303D;PART ALTERNATION MARK;Po;0;ON;;;;;N;;;;;
-303E;IDEOGRAPHIC VARIATION INDICATOR;So;0;ON;;;;;N;;;;;
-303F;IDEOGRAPHIC HALF FILL SPACE;So;0;ON;;;;;N;;;;;
-3041;HIRAGANA LETTER SMALL A;Lo;0;L;;;;;N;;;;;
-3042;HIRAGANA LETTER A;Lo;0;L;;;;;N;;;;;
-3043;HIRAGANA LETTER SMALL I;Lo;0;L;;;;;N;;;;;
-3044;HIRAGANA LETTER I;Lo;0;L;;;;;N;;;;;
-3045;HIRAGANA LETTER SMALL U;Lo;0;L;;;;;N;;;;;
-3046;HIRAGANA LETTER U;Lo;0;L;;;;;N;;;;;
-3047;HIRAGANA LETTER SMALL E;Lo;0;L;;;;;N;;;;;
-3048;HIRAGANA LETTER E;Lo;0;L;;;;;N;;;;;
-3049;HIRAGANA LETTER SMALL O;Lo;0;L;;;;;N;;;;;
-304A;HIRAGANA LETTER O;Lo;0;L;;;;;N;;;;;
-304B;HIRAGANA LETTER KA;Lo;0;L;;;;;N;;;;;
-304C;HIRAGANA LETTER GA;Lo;0;L;304B 3099;;;;N;;;;;
-304D;HIRAGANA LETTER KI;Lo;0;L;;;;;N;;;;;
-304E;HIRAGANA LETTER GI;Lo;0;L;304D 3099;;;;N;;;;;
-304F;HIRAGANA LETTER KU;Lo;0;L;;;;;N;;;;;
-3050;HIRAGANA LETTER GU;Lo;0;L;304F 3099;;;;N;;;;;
-3051;HIRAGANA LETTER KE;Lo;0;L;;;;;N;;;;;
-3052;HIRAGANA LETTER GE;Lo;0;L;3051 3099;;;;N;;;;;
-3053;HIRAGANA LETTER KO;Lo;0;L;;;;;N;;;;;
-3054;HIRAGANA LETTER GO;Lo;0;L;3053 3099;;;;N;;;;;
-3055;HIRAGANA LETTER SA;Lo;0;L;;;;;N;;;;;
-3056;HIRAGANA LETTER ZA;Lo;0;L;3055 3099;;;;N;;;;;
-3057;HIRAGANA LETTER SI;Lo;0;L;;;;;N;;;;;
-3058;HIRAGANA LETTER ZI;Lo;0;L;3057 3099;;;;N;;;;;
-3059;HIRAGANA LETTER SU;Lo;0;L;;;;;N;;;;;
-305A;HIRAGANA LETTER ZU;Lo;0;L;3059 3099;;;;N;;;;;
-305B;HIRAGANA LETTER SE;Lo;0;L;;;;;N;;;;;
-305C;HIRAGANA LETTER ZE;Lo;0;L;305B 3099;;;;N;;;;;
-305D;HIRAGANA LETTER SO;Lo;0;L;;;;;N;;;;;
-305E;HIRAGANA LETTER ZO;Lo;0;L;305D 3099;;;;N;;;;;
-305F;HIRAGANA LETTER TA;Lo;0;L;;;;;N;;;;;
-3060;HIRAGANA LETTER DA;Lo;0;L;305F 3099;;;;N;;;;;
-3061;HIRAGANA LETTER TI;Lo;0;L;;;;;N;;;;;
-3062;HIRAGANA LETTER DI;Lo;0;L;3061 3099;;;;N;;;;;
-3063;HIRAGANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;;
-3064;HIRAGANA LETTER TU;Lo;0;L;;;;;N;;;;;
-3065;HIRAGANA LETTER DU;Lo;0;L;3064 3099;;;;N;;;;;
-3066;HIRAGANA LETTER TE;Lo;0;L;;;;;N;;;;;
-3067;HIRAGANA LETTER DE;Lo;0;L;3066 3099;;;;N;;;;;
-3068;HIRAGANA LETTER TO;Lo;0;L;;;;;N;;;;;
-3069;HIRAGANA LETTER DO;Lo;0;L;3068 3099;;;;N;;;;;
-306A;HIRAGANA LETTER NA;Lo;0;L;;;;;N;;;;;
-306B;HIRAGANA LETTER NI;Lo;0;L;;;;;N;;;;;
-306C;HIRAGANA LETTER NU;Lo;0;L;;;;;N;;;;;
-306D;HIRAGANA LETTER NE;Lo;0;L;;;;;N;;;;;
-306E;HIRAGANA LETTER NO;Lo;0;L;;;;;N;;;;;
-306F;HIRAGANA LETTER HA;Lo;0;L;;;;;N;;;;;
-3070;HIRAGANA LETTER BA;Lo;0;L;306F 3099;;;;N;;;;;
-3071;HIRAGANA LETTER PA;Lo;0;L;306F 309A;;;;N;;;;;
-3072;HIRAGANA LETTER HI;Lo;0;L;;;;;N;;;;;
-3073;HIRAGANA LETTER BI;Lo;0;L;3072 3099;;;;N;;;;;
-3074;HIRAGANA LETTER PI;Lo;0;L;3072 309A;;;;N;;;;;
-3075;HIRAGANA LETTER HU;Lo;0;L;;;;;N;;;;;
-3076;HIRAGANA LETTER BU;Lo;0;L;3075 3099;;;;N;;;;;
-3077;HIRAGANA LETTER PU;Lo;0;L;3075 309A;;;;N;;;;;
-3078;HIRAGANA LETTER HE;Lo;0;L;;;;;N;;;;;
-3079;HIRAGANA LETTER BE;Lo;0;L;3078 3099;;;;N;;;;;
-307A;HIRAGANA LETTER PE;Lo;0;L;3078 309A;;;;N;;;;;
-307B;HIRAGANA LETTER HO;Lo;0;L;;;;;N;;;;;
-307C;HIRAGANA LETTER BO;Lo;0;L;307B 3099;;;;N;;;;;
-307D;HIRAGANA LETTER PO;Lo;0;L;307B 309A;;;;N;;;;;
-307E;HIRAGANA LETTER MA;Lo;0;L;;;;;N;;;;;
-307F;HIRAGANA LETTER MI;Lo;0;L;;;;;N;;;;;
-3080;HIRAGANA LETTER MU;Lo;0;L;;;;;N;;;;;
-3081;HIRAGANA LETTER ME;Lo;0;L;;;;;N;;;;;
-3082;HIRAGANA LETTER MO;Lo;0;L;;;;;N;;;;;
-3083;HIRAGANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;;
-3084;HIRAGANA LETTER YA;Lo;0;L;;;;;N;;;;;
-3085;HIRAGANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;;
-3086;HIRAGANA LETTER YU;Lo;0;L;;;;;N;;;;;
-3087;HIRAGANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;;
-3088;HIRAGANA LETTER YO;Lo;0;L;;;;;N;;;;;
-3089;HIRAGANA LETTER RA;Lo;0;L;;;;;N;;;;;
-308A;HIRAGANA LETTER RI;Lo;0;L;;;;;N;;;;;
-308B;HIRAGANA LETTER RU;Lo;0;L;;;;;N;;;;;
-308C;HIRAGANA LETTER RE;Lo;0;L;;;;;N;;;;;
-308D;HIRAGANA LETTER RO;Lo;0;L;;;;;N;;;;;
-308E;HIRAGANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;;
-308F;HIRAGANA LETTER WA;Lo;0;L;;;;;N;;;;;
-3090;HIRAGANA LETTER WI;Lo;0;L;;;;;N;;;;;
-3091;HIRAGANA LETTER WE;Lo;0;L;;;;;N;;;;;
-3092;HIRAGANA LETTER WO;Lo;0;L;;;;;N;;;;;
-3093;HIRAGANA LETTER N;Lo;0;L;;;;;N;;;;;
-3094;HIRAGANA LETTER VU;Lo;0;L;3046 3099;;;;N;;;;;
-3095;HIRAGANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;;
-3096;HIRAGANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;;
-3099;COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA VOICED SOUND MARK;;;;
-309A;COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;;;;
-309B;KATAKANA-HIRAGANA VOICED SOUND MARK;Sk;0;ON;<compat> 0020 3099;;;;N;;;;;
-309C;KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Sk;0;ON;<compat> 0020 309A;;;;N;;;;;
-309D;HIRAGANA ITERATION MARK;Lm;0;L;;;;;N;;;;;
-309E;HIRAGANA VOICED ITERATION MARK;Lm;0;L;309D 3099;;;;N;;;;;
-309F;HIRAGANA DIGRAPH YORI;Lo;0;L;<vertical> 3088 308A;;;;N;;;;;
-30A0;KATAKANA-HIRAGANA DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;;
-30A1;KATAKANA LETTER SMALL A;Lo;0;L;;;;;N;;;;;
-30A2;KATAKANA LETTER A;Lo;0;L;;;;;N;;;;;
-30A3;KATAKANA LETTER SMALL I;Lo;0;L;;;;;N;;;;;
-30A4;KATAKANA LETTER I;Lo;0;L;;;;;N;;;;;
-30A5;KATAKANA LETTER SMALL U;Lo;0;L;;;;;N;;;;;
-30A6;KATAKANA LETTER U;Lo;0;L;;;;;N;;;;;
-30A7;KATAKANA LETTER SMALL E;Lo;0;L;;;;;N;;;;;
-30A8;KATAKANA LETTER E;Lo;0;L;;;;;N;;;;;
-30A9;KATAKANA LETTER SMALL O;Lo;0;L;;;;;N;;;;;
-30AA;KATAKANA LETTER O;Lo;0;L;;;;;N;;;;;
-30AB;KATAKANA LETTER KA;Lo;0;L;;;;;N;;;;;
-30AC;KATAKANA LETTER GA;Lo;0;L;30AB 3099;;;;N;;;;;
-30AD;KATAKANA LETTER KI;Lo;0;L;;;;;N;;;;;
-30AE;KATAKANA LETTER GI;Lo;0;L;30AD 3099;;;;N;;;;;
-30AF;KATAKANA LETTER KU;Lo;0;L;;;;;N;;;;;
-30B0;KATAKANA LETTER GU;Lo;0;L;30AF 3099;;;;N;;;;;
-30B1;KATAKANA LETTER KE;Lo;0;L;;;;;N;;;;;
-30B2;KATAKANA LETTER GE;Lo;0;L;30B1 3099;;;;N;;;;;
-30B3;KATAKANA LETTER KO;Lo;0;L;;;;;N;;;;;
-30B4;KATAKANA LETTER GO;Lo;0;L;30B3 3099;;;;N;;;;;
-30B5;KATAKANA LETTER SA;Lo;0;L;;;;;N;;;;;
-30B6;KATAKANA LETTER ZA;Lo;0;L;30B5 3099;;;;N;;;;;
-30B7;KATAKANA LETTER SI;Lo;0;L;;;;;N;;;;;
-30B8;KATAKANA LETTER ZI;Lo;0;L;30B7 3099;;;;N;;;;;
-30B9;KATAKANA LETTER SU;Lo;0;L;;;;;N;;;;;
-30BA;KATAKANA LETTER ZU;Lo;0;L;30B9 3099;;;;N;;;;;
-30BB;KATAKANA LETTER SE;Lo;0;L;;;;;N;;;;;
-30BC;KATAKANA LETTER ZE;Lo;0;L;30BB 3099;;;;N;;;;;
-30BD;KATAKANA LETTER SO;Lo;0;L;;;;;N;;;;;
-30BE;KATAKANA LETTER ZO;Lo;0;L;30BD 3099;;;;N;;;;;
-30BF;KATAKANA LETTER TA;Lo;0;L;;;;;N;;;;;
-30C0;KATAKANA LETTER DA;Lo;0;L;30BF 3099;;;;N;;;;;
-30C1;KATAKANA LETTER TI;Lo;0;L;;;;;N;;;;;
-30C2;KATAKANA LETTER DI;Lo;0;L;30C1 3099;;;;N;;;;;
-30C3;KATAKANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;;
-30C4;KATAKANA LETTER TU;Lo;0;L;;;;;N;;;;;
-30C5;KATAKANA LETTER DU;Lo;0;L;30C4 3099;;;;N;;;;;
-30C6;KATAKANA LETTER TE;Lo;0;L;;;;;N;;;;;
-30C7;KATAKANA LETTER DE;Lo;0;L;30C6 3099;;;;N;;;;;
-30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;;
-30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;;
-30CA;KATAKANA LETTER NA;Lo;0;L;;;;;N;;;;;
-30CB;KATAKANA LETTER NI;Lo;0;L;;;;;N;;;;;
-30CC;KATAKANA LETTER NU;Lo;0;L;;;;;N;;;;;
-30CD;KATAKANA LETTER NE;Lo;0;L;;;;;N;;;;;
-30CE;KATAKANA LETTER NO;Lo;0;L;;;;;N;;;;;
-30CF;KATAKANA LETTER HA;Lo;0;L;;;;;N;;;;;
-30D0;KATAKANA LETTER BA;Lo;0;L;30CF 3099;;;;N;;;;;
-30D1;KATAKANA LETTER PA;Lo;0;L;30CF 309A;;;;N;;;;;
-30D2;KATAKANA LETTER HI;Lo;0;L;;;;;N;;;;;
-30D3;KATAKANA LETTER BI;Lo;0;L;30D2 3099;;;;N;;;;;
-30D4;KATAKANA LETTER PI;Lo;0;L;30D2 309A;;;;N;;;;;
-30D5;KATAKANA LETTER HU;Lo;0;L;;;;;N;;;;;
-30D6;KATAKANA LETTER BU;Lo;0;L;30D5 3099;;;;N;;;;;
-30D7;KATAKANA LETTER PU;Lo;0;L;30D5 309A;;;;N;;;;;
-30D8;KATAKANA LETTER HE;Lo;0;L;;;;;N;;;;;
-30D9;KATAKANA LETTER BE;Lo;0;L;30D8 3099;;;;N;;;;;
-30DA;KATAKANA LETTER PE;Lo;0;L;30D8 309A;;;;N;;;;;
-30DB;KATAKANA LETTER HO;Lo;0;L;;;;;N;;;;;
-30DC;KATAKANA LETTER BO;Lo;0;L;30DB 3099;;;;N;;;;;
-30DD;KATAKANA LETTER PO;Lo;0;L;30DB 309A;;;;N;;;;;
-30DE;KATAKANA LETTER MA;Lo;0;L;;;;;N;;;;;
-30DF;KATAKANA LETTER MI;Lo;0;L;;;;;N;;;;;
-30E0;KATAKANA LETTER MU;Lo;0;L;;;;;N;;;;;
-30E1;KATAKANA LETTER ME;Lo;0;L;;;;;N;;;;;
-30E2;KATAKANA LETTER MO;Lo;0;L;;;;;N;;;;;
-30E3;KATAKANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;;
-30E4;KATAKANA LETTER YA;Lo;0;L;;;;;N;;;;;
-30E5;KATAKANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;;
-30E6;KATAKANA LETTER YU;Lo;0;L;;;;;N;;;;;
-30E7;KATAKANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;;
-30E8;KATAKANA LETTER YO;Lo;0;L;;;;;N;;;;;
-30E9;KATAKANA LETTER RA;Lo;0;L;;;;;N;;;;;
-30EA;KATAKANA LETTER RI;Lo;0;L;;;;;N;;;;;
-30EB;KATAKANA LETTER RU;Lo;0;L;;;;;N;;;;;
-30EC;KATAKANA LETTER RE;Lo;0;L;;;;;N;;;;;
-30ED;KATAKANA LETTER RO;Lo;0;L;;;;;N;;;;;
-30EE;KATAKANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;;
-30EF;KATAKANA LETTER WA;Lo;0;L;;;;;N;;;;;
-30F0;KATAKANA LETTER WI;Lo;0;L;;;;;N;;;;;
-30F1;KATAKANA LETTER WE;Lo;0;L;;;;;N;;;;;
-30F2;KATAKANA LETTER WO;Lo;0;L;;;;;N;;;;;
-30F3;KATAKANA LETTER N;Lo;0;L;;;;;N;;;;;
-30F4;KATAKANA LETTER VU;Lo;0;L;30A6 3099;;;;N;;;;;
-30F5;KATAKANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;;
-30F6;KATAKANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;;
-30F7;KATAKANA LETTER VA;Lo;0;L;30EF 3099;;;;N;;;;;
-30F8;KATAKANA LETTER VI;Lo;0;L;30F0 3099;;;;N;;;;;
-30F9;KATAKANA LETTER VE;Lo;0;L;30F1 3099;;;;N;;;;;
-30FA;KATAKANA LETTER VO;Lo;0;L;30F2 3099;;;;N;;;;;
-30FB;KATAKANA MIDDLE DOT;Po;0;ON;;;;;N;;;;;
-30FC;KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;;;;;N;;;;;
-30FD;KATAKANA ITERATION MARK;Lm;0;L;;;;;N;;;;;
-30FE;KATAKANA VOICED ITERATION MARK;Lm;0;L;30FD 3099;;;;N;;;;;
-30FF;KATAKANA DIGRAPH KOTO;Lo;0;L;<vertical> 30B3 30C8;;;;N;;;;;
-3105;BOPOMOFO LETTER B;Lo;0;L;;;;;N;;;;;
-3106;BOPOMOFO LETTER P;Lo;0;L;;;;;N;;;;;
-3107;BOPOMOFO LETTER M;Lo;0;L;;;;;N;;;;;
-3108;BOPOMOFO LETTER F;Lo;0;L;;;;;N;;;;;
-3109;BOPOMOFO LETTER D;Lo;0;L;;;;;N;;;;;
-310A;BOPOMOFO LETTER T;Lo;0;L;;;;;N;;;;;
-310B;BOPOMOFO LETTER N;Lo;0;L;;;;;N;;;;;
-310C;BOPOMOFO LETTER L;Lo;0;L;;;;;N;;;;;
-310D;BOPOMOFO LETTER G;Lo;0;L;;;;;N;;;;;
-310E;BOPOMOFO LETTER K;Lo;0;L;;;;;N;;;;;
-310F;BOPOMOFO LETTER H;Lo;0;L;;;;;N;;;;;
-3110;BOPOMOFO LETTER J;Lo;0;L;;;;;N;;;;;
-3111;BOPOMOFO LETTER Q;Lo;0;L;;;;;N;;;;;
-3112;BOPOMOFO LETTER X;Lo;0;L;;;;;N;;;;;
-3113;BOPOMOFO LETTER ZH;Lo;0;L;;;;;N;;;;;
-3114;BOPOMOFO LETTER CH;Lo;0;L;;;;;N;;;;;
-3115;BOPOMOFO LETTER SH;Lo;0;L;;;;;N;;;;;
-3116;BOPOMOFO LETTER R;Lo;0;L;;;;;N;;;;;
-3117;BOPOMOFO LETTER Z;Lo;0;L;;;;;N;;;;;
-3118;BOPOMOFO LETTER C;Lo;0;L;;;;;N;;;;;
-3119;BOPOMOFO LETTER S;Lo;0;L;;;;;N;;;;;
-311A;BOPOMOFO LETTER A;Lo;0;L;;;;;N;;;;;
-311B;BOPOMOFO LETTER O;Lo;0;L;;;;;N;;;;;
-311C;BOPOMOFO LETTER E;Lo;0;L;;;;;N;;;;;
-311D;BOPOMOFO LETTER EH;Lo;0;L;;;;;N;;;;;
-311E;BOPOMOFO LETTER AI;Lo;0;L;;;;;N;;;;;
-311F;BOPOMOFO LETTER EI;Lo;0;L;;;;;N;;;;;
-3120;BOPOMOFO LETTER AU;Lo;0;L;;;;;N;;;;;
-3121;BOPOMOFO LETTER OU;Lo;0;L;;;;;N;;;;;
-3122;BOPOMOFO LETTER AN;Lo;0;L;;;;;N;;;;;
-3123;BOPOMOFO LETTER EN;Lo;0;L;;;;;N;;;;;
-3124;BOPOMOFO LETTER ANG;Lo;0;L;;;;;N;;;;;
-3125;BOPOMOFO LETTER ENG;Lo;0;L;;;;;N;;;;;
-3126;BOPOMOFO LETTER ER;Lo;0;L;;;;;N;;;;;
-3127;BOPOMOFO LETTER I;Lo;0;L;;;;;N;;;;;
-3128;BOPOMOFO LETTER U;Lo;0;L;;;;;N;;;;;
-3129;BOPOMOFO LETTER IU;Lo;0;L;;;;;N;;;;;
-312A;BOPOMOFO LETTER V;Lo;0;L;;;;;N;;;;;
-312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;;
-312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;;
-312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;;
-3131;HANGUL LETTER KIYEOK;Lo;0;L;<compat> 1100;;;;N;HANGUL LETTER GIYEOG;;;;
-3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L;<compat> 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;;
-3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;;
-3134;HANGUL LETTER NIEUN;Lo;0;L;<compat> 1102;;;;N;;;;;
-3135;HANGUL LETTER NIEUN-CIEUC;Lo;0;L;<compat> 11AC;;;;N;HANGUL LETTER NIEUN JIEUJ;;;;
-3136;HANGUL LETTER NIEUN-HIEUH;Lo;0;L;<compat> 11AD;;;;N;HANGUL LETTER NIEUN HIEUH;;;;
-3137;HANGUL LETTER TIKEUT;Lo;0;L;<compat> 1103;;;;N;HANGUL LETTER DIGEUD;;;;
-3138;HANGUL LETTER SSANGTIKEUT;Lo;0;L;<compat> 1104;;;;N;HANGUL LETTER SSANG DIGEUD;;;;
-3139;HANGUL LETTER RIEUL;Lo;0;L;<compat> 1105;;;;N;HANGUL LETTER LIEUL;;;;
-313A;HANGUL LETTER RIEUL-KIYEOK;Lo;0;L;<compat> 11B0;;;;N;HANGUL LETTER LIEUL GIYEOG;;;;
-313B;HANGUL LETTER RIEUL-MIEUM;Lo;0;L;<compat> 11B1;;;;N;HANGUL LETTER LIEUL MIEUM;;;;
-313C;HANGUL LETTER RIEUL-PIEUP;Lo;0;L;<compat> 11B2;;;;N;HANGUL LETTER LIEUL BIEUB;;;;
-313D;HANGUL LETTER RIEUL-SIOS;Lo;0;L;<compat> 11B3;;;;N;HANGUL LETTER LIEUL SIOS;;;;
-313E;HANGUL LETTER RIEUL-THIEUTH;Lo;0;L;<compat> 11B4;;;;N;HANGUL LETTER LIEUL TIEUT;;;;
-313F;HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L;<compat> 11B5;;;;N;HANGUL LETTER LIEUL PIEUP;;;;
-3140;HANGUL LETTER RIEUL-HIEUH;Lo;0;L;<compat> 111A;;;;N;HANGUL LETTER LIEUL HIEUH;;;;
-3141;HANGUL LETTER MIEUM;Lo;0;L;<compat> 1106;;;;N;;;;;
-3142;HANGUL LETTER PIEUP;Lo;0;L;<compat> 1107;;;;N;HANGUL LETTER BIEUB;;;;
-3143;HANGUL LETTER SSANGPIEUP;Lo;0;L;<compat> 1108;;;;N;HANGUL LETTER SSANG BIEUB;;;;
-3144;HANGUL LETTER PIEUP-SIOS;Lo;0;L;<compat> 1121;;;;N;HANGUL LETTER BIEUB SIOS;;;;
-3145;HANGUL LETTER SIOS;Lo;0;L;<compat> 1109;;;;N;;;;;
-3146;HANGUL LETTER SSANGSIOS;Lo;0;L;<compat> 110A;;;;N;HANGUL LETTER SSANG SIOS;;;;
-3147;HANGUL LETTER IEUNG;Lo;0;L;<compat> 110B;;;;N;;;;;
-3148;HANGUL LETTER CIEUC;Lo;0;L;<compat> 110C;;;;N;HANGUL LETTER JIEUJ;;;;
-3149;HANGUL LETTER SSANGCIEUC;Lo;0;L;<compat> 110D;;;;N;HANGUL LETTER SSANG JIEUJ;;;;
-314A;HANGUL LETTER CHIEUCH;Lo;0;L;<compat> 110E;;;;N;HANGUL LETTER CIEUC;;;;
-314B;HANGUL LETTER KHIEUKH;Lo;0;L;<compat> 110F;;;;N;HANGUL LETTER KIYEOK;;;;
-314C;HANGUL LETTER THIEUTH;Lo;0;L;<compat> 1110;;;;N;HANGUL LETTER TIEUT;;;;
-314D;HANGUL LETTER PHIEUPH;Lo;0;L;<compat> 1111;;;;N;HANGUL LETTER PIEUP;;;;
-314E;HANGUL LETTER HIEUH;Lo;0;L;<compat> 1112;;;;N;;;;;
-314F;HANGUL LETTER A;Lo;0;L;<compat> 1161;;;;N;;;;;
-3150;HANGUL LETTER AE;Lo;0;L;<compat> 1162;;;;N;;;;;
-3151;HANGUL LETTER YA;Lo;0;L;<compat> 1163;;;;N;;;;;
-3152;HANGUL LETTER YAE;Lo;0;L;<compat> 1164;;;;N;;;;;
-3153;HANGUL LETTER EO;Lo;0;L;<compat> 1165;;;;N;;;;;
-3154;HANGUL LETTER E;Lo;0;L;<compat> 1166;;;;N;;;;;
-3155;HANGUL LETTER YEO;Lo;0;L;<compat> 1167;;;;N;;;;;
-3156;HANGUL LETTER YE;Lo;0;L;<compat> 1168;;;;N;;;;;
-3157;HANGUL LETTER O;Lo;0;L;<compat> 1169;;;;N;;;;;
-3158;HANGUL LETTER WA;Lo;0;L;<compat> 116A;;;;N;;;;;
-3159;HANGUL LETTER WAE;Lo;0;L;<compat> 116B;;;;N;;;;;
-315A;HANGUL LETTER OE;Lo;0;L;<compat> 116C;;;;N;;;;;
-315B;HANGUL LETTER YO;Lo;0;L;<compat> 116D;;;;N;;;;;
-315C;HANGUL LETTER U;Lo;0;L;<compat> 116E;;;;N;;;;;
-315D;HANGUL LETTER WEO;Lo;0;L;<compat> 116F;;;;N;;;;;
-315E;HANGUL LETTER WE;Lo;0;L;<compat> 1170;;;;N;;;;;
-315F;HANGUL LETTER WI;Lo;0;L;<compat> 1171;;;;N;;;;;
-3160;HANGUL LETTER YU;Lo;0;L;<compat> 1172;;;;N;;;;;
-3161;HANGUL LETTER EU;Lo;0;L;<compat> 1173;;;;N;;;;;
-3162;HANGUL LETTER YI;Lo;0;L;<compat> 1174;;;;N;;;;;
-3163;HANGUL LETTER I;Lo;0;L;<compat> 1175;;;;N;;;;;
-3164;HANGUL FILLER;Lo;0;L;<compat> 1160;;;;N;HANGUL CAE OM;;;;
-3165;HANGUL LETTER SSANGNIEUN;Lo;0;L;<compat> 1114;;;;N;HANGUL LETTER SSANG NIEUN;;;;
-3166;HANGUL LETTER NIEUN-TIKEUT;Lo;0;L;<compat> 1115;;;;N;HANGUL LETTER NIEUN DIGEUD;;;;
-3167;HANGUL LETTER NIEUN-SIOS;Lo;0;L;<compat> 11C7;;;;N;HANGUL LETTER NIEUN SIOS;;;;
-3168;HANGUL LETTER NIEUN-PANSIOS;Lo;0;L;<compat> 11C8;;;;N;HANGUL LETTER NIEUN BAN CHI EUM;;;;
-3169;HANGUL LETTER RIEUL-KIYEOK-SIOS;Lo;0;L;<compat> 11CC;;;;N;HANGUL LETTER LIEUL GIYEOG SIOS;;;;
-316A;HANGUL LETTER RIEUL-TIKEUT;Lo;0;L;<compat> 11CE;;;;N;HANGUL LETTER LIEUL DIGEUD;;;;
-316B;HANGUL LETTER RIEUL-PIEUP-SIOS;Lo;0;L;<compat> 11D3;;;;N;HANGUL LETTER LIEUL BIEUB SIOS;;;;
-316C;HANGUL LETTER RIEUL-PANSIOS;Lo;0;L;<compat> 11D7;;;;N;HANGUL LETTER LIEUL BAN CHI EUM;;;;
-316D;HANGUL LETTER RIEUL-YEORINHIEUH;Lo;0;L;<compat> 11D9;;;;N;HANGUL LETTER LIEUL YEOLIN HIEUH;;;;
-316E;HANGUL LETTER MIEUM-PIEUP;Lo;0;L;<compat> 111C;;;;N;HANGUL LETTER MIEUM BIEUB;;;;
-316F;HANGUL LETTER MIEUM-SIOS;Lo;0;L;<compat> 11DD;;;;N;HANGUL LETTER MIEUM SIOS;;;;
-3170;HANGUL LETTER MIEUM-PANSIOS;Lo;0;L;<compat> 11DF;;;;N;HANGUL LETTER BIEUB BAN CHI EUM;;;;
-3171;HANGUL LETTER KAPYEOUNMIEUM;Lo;0;L;<compat> 111D;;;;N;HANGUL LETTER MIEUM SUN GYEONG EUM;;;;
-3172;HANGUL LETTER PIEUP-KIYEOK;Lo;0;L;<compat> 111E;;;;N;HANGUL LETTER BIEUB GIYEOG;;;;
-3173;HANGUL LETTER PIEUP-TIKEUT;Lo;0;L;<compat> 1120;;;;N;HANGUL LETTER BIEUB DIGEUD;;;;
-3174;HANGUL LETTER PIEUP-SIOS-KIYEOK;Lo;0;L;<compat> 1122;;;;N;HANGUL LETTER BIEUB SIOS GIYEOG;;;;
-3175;HANGUL LETTER PIEUP-SIOS-TIKEUT;Lo;0;L;<compat> 1123;;;;N;HANGUL LETTER BIEUB SIOS DIGEUD;;;;
-3176;HANGUL LETTER PIEUP-CIEUC;Lo;0;L;<compat> 1127;;;;N;HANGUL LETTER BIEUB JIEUJ;;;;
-3177;HANGUL LETTER PIEUP-THIEUTH;Lo;0;L;<compat> 1129;;;;N;HANGUL LETTER BIEUB TIEUT;;;;
-3178;HANGUL LETTER KAPYEOUNPIEUP;Lo;0;L;<compat> 112B;;;;N;HANGUL LETTER BIEUB SUN GYEONG EUM;;;;
-3179;HANGUL LETTER KAPYEOUNSSANGPIEUP;Lo;0;L;<compat> 112C;;;;N;HANGUL LETTER SSANG BIEUB SUN GYEONG EUM;;;;
-317A;HANGUL LETTER SIOS-KIYEOK;Lo;0;L;<compat> 112D;;;;N;HANGUL LETTER SIOS GIYEOG;;;;
-317B;HANGUL LETTER SIOS-NIEUN;Lo;0;L;<compat> 112E;;;;N;HANGUL LETTER SIOS NIEUN;;;;
-317C;HANGUL LETTER SIOS-TIKEUT;Lo;0;L;<compat> 112F;;;;N;HANGUL LETTER SIOS DIGEUD;;;;
-317D;HANGUL LETTER SIOS-PIEUP;Lo;0;L;<compat> 1132;;;;N;HANGUL LETTER SIOS BIEUB;;;;
-317E;HANGUL LETTER SIOS-CIEUC;Lo;0;L;<compat> 1136;;;;N;HANGUL LETTER SIOS JIEUJ;;;;
-317F;HANGUL LETTER PANSIOS;Lo;0;L;<compat> 1140;;;;N;HANGUL LETTER BAN CHI EUM;;;;
-3180;HANGUL LETTER SSANGIEUNG;Lo;0;L;<compat> 1147;;;;N;HANGUL LETTER SSANG IEUNG;;;;
-3181;HANGUL LETTER YESIEUNG;Lo;0;L;<compat> 114C;;;;N;HANGUL LETTER NGIEUNG;;;;
-3182;HANGUL LETTER YESIEUNG-SIOS;Lo;0;L;<compat> 11F1;;;;N;HANGUL LETTER NGIEUNG SIOS;;;;
-3183;HANGUL LETTER YESIEUNG-PANSIOS;Lo;0;L;<compat> 11F2;;;;N;HANGUL LETTER NGIEUNG BAN CHI EUM;;;;
-3184;HANGUL LETTER KAPYEOUNPHIEUPH;Lo;0;L;<compat> 1157;;;;N;HANGUL LETTER PIEUP SUN GYEONG EUM;;;;
-3185;HANGUL LETTER SSANGHIEUH;Lo;0;L;<compat> 1158;;;;N;HANGUL LETTER SSANG HIEUH;;;;
-3186;HANGUL LETTER YEORINHIEUH;Lo;0;L;<compat> 1159;;;;N;HANGUL LETTER YEOLIN HIEUH;;;;
-3187;HANGUL LETTER YO-YA;Lo;0;L;<compat> 1184;;;;N;HANGUL LETTER YOYA;;;;
-3188;HANGUL LETTER YO-YAE;Lo;0;L;<compat> 1185;;;;N;HANGUL LETTER YOYAE;;;;
-3189;HANGUL LETTER YO-I;Lo;0;L;<compat> 1188;;;;N;HANGUL LETTER YOI;;;;
-318A;HANGUL LETTER YU-YEO;Lo;0;L;<compat> 1191;;;;N;HANGUL LETTER YUYEO;;;;
-318B;HANGUL LETTER YU-YE;Lo;0;L;<compat> 1192;;;;N;HANGUL LETTER YUYE;;;;
-318C;HANGUL LETTER YU-I;Lo;0;L;<compat> 1194;;;;N;HANGUL LETTER YUI;;;;
-318D;HANGUL LETTER ARAEA;Lo;0;L;<compat> 119E;;;;N;HANGUL LETTER ALAE A;;;;
-318E;HANGUL LETTER ARAEAE;Lo;0;L;<compat> 11A1;;;;N;HANGUL LETTER ALAE AE;;;;
-3190;IDEOGRAPHIC ANNOTATION LINKING MARK;So;0;L;;;;;N;KANBUN TATETEN;;;;
-3191;IDEOGRAPHIC ANNOTATION REVERSE MARK;So;0;L;;;;;N;KAERITEN RE;;;;
-3192;IDEOGRAPHIC ANNOTATION ONE MARK;No;0;L;<super> 4E00;;;1;N;KAERITEN ITI;;;;
-3193;IDEOGRAPHIC ANNOTATION TWO MARK;No;0;L;<super> 4E8C;;;2;N;KAERITEN NI;;;;
-3194;IDEOGRAPHIC ANNOTATION THREE MARK;No;0;L;<super> 4E09;;;3;N;KAERITEN SAN;;;;
-3195;IDEOGRAPHIC ANNOTATION FOUR MARK;No;0;L;<super> 56DB;;;4;N;KAERITEN SI;;;;
-3196;IDEOGRAPHIC ANNOTATION TOP MARK;So;0;L;<super> 4E0A;;;;N;KAERITEN ZYOU;;;;
-3197;IDEOGRAPHIC ANNOTATION MIDDLE MARK;So;0;L;<super> 4E2D;;;;N;KAERITEN TYUU;;;;
-3198;IDEOGRAPHIC ANNOTATION BOTTOM MARK;So;0;L;<super> 4E0B;;;;N;KAERITEN GE;;;;
-3199;IDEOGRAPHIC ANNOTATION FIRST MARK;So;0;L;<super> 7532;;;;N;KAERITEN KOU;;;;
-319A;IDEOGRAPHIC ANNOTATION SECOND MARK;So;0;L;<super> 4E59;;;;N;KAERITEN OTU;;;;
-319B;IDEOGRAPHIC ANNOTATION THIRD MARK;So;0;L;<super> 4E19;;;;N;KAERITEN HEI;;;;
-319C;IDEOGRAPHIC ANNOTATION FOURTH MARK;So;0;L;<super> 4E01;;;;N;KAERITEN TEI;;;;
-319D;IDEOGRAPHIC ANNOTATION HEAVEN MARK;So;0;L;<super> 5929;;;;N;KAERITEN TEN;;;;
-319E;IDEOGRAPHIC ANNOTATION EARTH MARK;So;0;L;<super> 5730;;;;N;KAERITEN TI;;;;
-319F;IDEOGRAPHIC ANNOTATION MAN MARK;So;0;L;<super> 4EBA;;;;N;KAERITEN ZIN;;;;
-31A0;BOPOMOFO LETTER BU;Lo;0;L;;;;;N;;;;;
-31A1;BOPOMOFO LETTER ZI;Lo;0;L;;;;;N;;;;;
-31A2;BOPOMOFO LETTER JI;Lo;0;L;;;;;N;;;;;
-31A3;BOPOMOFO LETTER GU;Lo;0;L;;;;;N;;;;;
-31A4;BOPOMOFO LETTER EE;Lo;0;L;;;;;N;;;;;
-31A5;BOPOMOFO LETTER ENN;Lo;0;L;;;;;N;;;;;
-31A6;BOPOMOFO LETTER OO;Lo;0;L;;;;;N;;;;;
-31A7;BOPOMOFO LETTER ONN;Lo;0;L;;;;;N;;;;;
-31A8;BOPOMOFO LETTER IR;Lo;0;L;;;;;N;;;;;
-31A9;BOPOMOFO LETTER ANN;Lo;0;L;;;;;N;;;;;
-31AA;BOPOMOFO LETTER INN;Lo;0;L;;;;;N;;;;;
-31AB;BOPOMOFO LETTER UNN;Lo;0;L;;;;;N;;;;;
-31AC;BOPOMOFO LETTER IM;Lo;0;L;;;;;N;;;;;
-31AD;BOPOMOFO LETTER NGG;Lo;0;L;;;;;N;;;;;
-31AE;BOPOMOFO LETTER AINN;Lo;0;L;;;;;N;;;;;
-31AF;BOPOMOFO LETTER AUNN;Lo;0;L;;;;;N;;;;;
-31B0;BOPOMOFO LETTER AM;Lo;0;L;;;;;N;;;;;
-31B1;BOPOMOFO LETTER OM;Lo;0;L;;;;;N;;;;;
-31B2;BOPOMOFO LETTER ONG;Lo;0;L;;;;;N;;;;;
-31B3;BOPOMOFO LETTER INNN;Lo;0;L;;;;;N;;;;;
-31B4;BOPOMOFO FINAL LETTER P;Lo;0;L;;;;;N;;;;;
-31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;;
-31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;;
-31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;;
-31B8;BOPOMOFO LETTER GH;Lo;0;L;;;;;N;;;;;
-31B9;BOPOMOFO LETTER LH;Lo;0;L;;;;;N;;;;;
-31BA;BOPOMOFO LETTER ZY;Lo;0;L;;;;;N;;;;;
-31C0;CJK STROKE T;So;0;ON;;;;;N;;;;;
-31C1;CJK STROKE WG;So;0;ON;;;;;N;;;;;
-31C2;CJK STROKE XG;So;0;ON;;;;;N;;;;;
-31C3;CJK STROKE BXG;So;0;ON;;;;;N;;;;;
-31C4;CJK STROKE SW;So;0;ON;;;;;N;;;;;
-31C5;CJK STROKE HZZ;So;0;ON;;;;;N;;;;;
-31C6;CJK STROKE HZG;So;0;ON;;;;;N;;;;;
-31C7;CJK STROKE HP;So;0;ON;;;;;N;;;;;
-31C8;CJK STROKE HZWG;So;0;ON;;;;;N;;;;;
-31C9;CJK STROKE SZWG;So;0;ON;;;;;N;;;;;
-31CA;CJK STROKE HZT;So;0;ON;;;;;N;;;;;
-31CB;CJK STROKE HZZP;So;0;ON;;;;;N;;;;;
-31CC;CJK STROKE HPWG;So;0;ON;;;;;N;;;;;
-31CD;CJK STROKE HZW;So;0;ON;;;;;N;;;;;
-31CE;CJK STROKE HZZZ;So;0;ON;;;;;N;;;;;
-31CF;CJK STROKE N;So;0;ON;;;;;N;;;;;
-31D0;CJK STROKE H;So;0;ON;;;;;N;;;;;
-31D1;CJK STROKE S;So;0;ON;;;;;N;;;;;
-31D2;CJK STROKE P;So;0;ON;;;;;N;;;;;
-31D3;CJK STROKE SP;So;0;ON;;;;;N;;;;;
-31D4;CJK STROKE D;So;0;ON;;;;;N;;;;;
-31D5;CJK STROKE HZ;So;0;ON;;;;;N;;;;;
-31D6;CJK STROKE HG;So;0;ON;;;;;N;;;;;
-31D7;CJK STROKE SZ;So;0;ON;;;;;N;;;;;
-31D8;CJK STROKE SWZ;So;0;ON;;;;;N;;;;;
-31D9;CJK STROKE ST;So;0;ON;;;;;N;;;;;
-31DA;CJK STROKE SG;So;0;ON;;;;;N;;;;;
-31DB;CJK STROKE PD;So;0;ON;;;;;N;;;;;
-31DC;CJK STROKE PZ;So;0;ON;;;;;N;;;;;
-31DD;CJK STROKE TN;So;0;ON;;;;;N;;;;;
-31DE;CJK STROKE SZZ;So;0;ON;;;;;N;;;;;
-31DF;CJK STROKE SWG;So;0;ON;;;;;N;;;;;
-31E0;CJK STROKE HXWG;So;0;ON;;;;;N;;;;;
-31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;;
-31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;;
-31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;;
-31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;;
-31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;;
-31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;;
-31F3;KATAKANA LETTER SMALL TO;Lo;0;L;;;;;N;;;;;
-31F4;KATAKANA LETTER SMALL NU;Lo;0;L;;;;;N;;;;;
-31F5;KATAKANA LETTER SMALL HA;Lo;0;L;;;;;N;;;;;
-31F6;KATAKANA LETTER SMALL HI;Lo;0;L;;;;;N;;;;;
-31F7;KATAKANA LETTER SMALL HU;Lo;0;L;;;;;N;;;;;
-31F8;KATAKANA LETTER SMALL HE;Lo;0;L;;;;;N;;;;;
-31F9;KATAKANA LETTER SMALL HO;Lo;0;L;;;;;N;;;;;
-31FA;KATAKANA LETTER SMALL MU;Lo;0;L;;;;;N;;;;;
-31FB;KATAKANA LETTER SMALL RA;Lo;0;L;;;;;N;;;;;
-31FC;KATAKANA LETTER SMALL RI;Lo;0;L;;;;;N;;;;;
-31FD;KATAKANA LETTER SMALL RU;Lo;0;L;;;;;N;;;;;
-31FE;KATAKANA LETTER SMALL RE;Lo;0;L;;;;;N;;;;;
-31FF;KATAKANA LETTER SMALL RO;Lo;0;L;;;;;N;;;;;
-3200;PARENTHESIZED HANGUL KIYEOK;So;0;L;<compat> 0028 1100 0029;;;;N;PARENTHESIZED HANGUL GIYEOG;;;;
-3201;PARENTHESIZED HANGUL NIEUN;So;0;L;<compat> 0028 1102 0029;;;;N;;;;;
-3202;PARENTHESIZED HANGUL TIKEUT;So;0;L;<compat> 0028 1103 0029;;;;N;PARENTHESIZED HANGUL DIGEUD;;;;
-3203;PARENTHESIZED HANGUL RIEUL;So;0;L;<compat> 0028 1105 0029;;;;N;PARENTHESIZED HANGUL LIEUL;;;;
-3204;PARENTHESIZED HANGUL MIEUM;So;0;L;<compat> 0028 1106 0029;;;;N;;;;;
-3205;PARENTHESIZED HANGUL PIEUP;So;0;L;<compat> 0028 1107 0029;;;;N;PARENTHESIZED HANGUL BIEUB;;;;
-3206;PARENTHESIZED HANGUL SIOS;So;0;L;<compat> 0028 1109 0029;;;;N;;;;;
-3207;PARENTHESIZED HANGUL IEUNG;So;0;L;<compat> 0028 110B 0029;;;;N;;;;;
-3208;PARENTHESIZED HANGUL CIEUC;So;0;L;<compat> 0028 110C 0029;;;;N;PARENTHESIZED HANGUL JIEUJ;;;;
-3209;PARENTHESIZED HANGUL CHIEUCH;So;0;L;<compat> 0028 110E 0029;;;;N;PARENTHESIZED HANGUL CIEUC;;;;
-320A;PARENTHESIZED HANGUL KHIEUKH;So;0;L;<compat> 0028 110F 0029;;;;N;PARENTHESIZED HANGUL KIYEOK;;;;
-320B;PARENTHESIZED HANGUL THIEUTH;So;0;L;<compat> 0028 1110 0029;;;;N;PARENTHESIZED HANGUL TIEUT;;;;
-320C;PARENTHESIZED HANGUL PHIEUPH;So;0;L;<compat> 0028 1111 0029;;;;N;PARENTHESIZED HANGUL PIEUP;;;;
-320D;PARENTHESIZED HANGUL HIEUH;So;0;L;<compat> 0028 1112 0029;;;;N;;;;;
-320E;PARENTHESIZED HANGUL KIYEOK A;So;0;L;<compat> 0028 1100 1161 0029;;;;N;PARENTHESIZED HANGUL GA;;;;
-320F;PARENTHESIZED HANGUL NIEUN A;So;0;L;<compat> 0028 1102 1161 0029;;;;N;PARENTHESIZED HANGUL NA;;;;
-3210;PARENTHESIZED HANGUL TIKEUT A;So;0;L;<compat> 0028 1103 1161 0029;;;;N;PARENTHESIZED HANGUL DA;;;;
-3211;PARENTHESIZED HANGUL RIEUL A;So;0;L;<compat> 0028 1105 1161 0029;;;;N;PARENTHESIZED HANGUL LA;;;;
-3212;PARENTHESIZED HANGUL MIEUM A;So;0;L;<compat> 0028 1106 1161 0029;;;;N;PARENTHESIZED HANGUL MA;;;;
-3213;PARENTHESIZED HANGUL PIEUP A;So;0;L;<compat> 0028 1107 1161 0029;;;;N;PARENTHESIZED HANGUL BA;;;;
-3214;PARENTHESIZED HANGUL SIOS A;So;0;L;<compat> 0028 1109 1161 0029;;;;N;PARENTHESIZED HANGUL SA;;;;
-3215;PARENTHESIZED HANGUL IEUNG A;So;0;L;<compat> 0028 110B 1161 0029;;;;N;PARENTHESIZED HANGUL A;;;;
-3216;PARENTHESIZED HANGUL CIEUC A;So;0;L;<compat> 0028 110C 1161 0029;;;;N;PARENTHESIZED HANGUL JA;;;;
-3217;PARENTHESIZED HANGUL CHIEUCH A;So;0;L;<compat> 0028 110E 1161 0029;;;;N;PARENTHESIZED HANGUL CA;;;;
-3218;PARENTHESIZED HANGUL KHIEUKH A;So;0;L;<compat> 0028 110F 1161 0029;;;;N;PARENTHESIZED HANGUL KA;;;;
-3219;PARENTHESIZED HANGUL THIEUTH A;So;0;L;<compat> 0028 1110 1161 0029;;;;N;PARENTHESIZED HANGUL TA;;;;
-321A;PARENTHESIZED HANGUL PHIEUPH A;So;0;L;<compat> 0028 1111 1161 0029;;;;N;PARENTHESIZED HANGUL PA;;;;
-321B;PARENTHESIZED HANGUL HIEUH A;So;0;L;<compat> 0028 1112 1161 0029;;;;N;PARENTHESIZED HANGUL HA;;;;
-321C;PARENTHESIZED HANGUL CIEUC U;So;0;L;<compat> 0028 110C 116E 0029;;;;N;PARENTHESIZED HANGUL JU;;;;
-321D;PARENTHESIZED KOREAN CHARACTER OJEON;So;0;ON;<compat> 0028 110B 1169 110C 1165 11AB 0029;;;;N;;;;;
-321E;PARENTHESIZED KOREAN CHARACTER O HU;So;0;ON;<compat> 0028 110B 1169 1112 116E 0029;;;;N;;;;;
-3220;PARENTHESIZED IDEOGRAPH ONE;No;0;L;<compat> 0028 4E00 0029;;;1;N;;;;;
-3221;PARENTHESIZED IDEOGRAPH TWO;No;0;L;<compat> 0028 4E8C 0029;;;2;N;;;;;
-3222;PARENTHESIZED IDEOGRAPH THREE;No;0;L;<compat> 0028 4E09 0029;;;3;N;;;;;
-3223;PARENTHESIZED IDEOGRAPH FOUR;No;0;L;<compat> 0028 56DB 0029;;;4;N;;;;;
-3224;PARENTHESIZED IDEOGRAPH FIVE;No;0;L;<compat> 0028 4E94 0029;;;5;N;;;;;
-3225;PARENTHESIZED IDEOGRAPH SIX;No;0;L;<compat> 0028 516D 0029;;;6;N;;;;;
-3226;PARENTHESIZED IDEOGRAPH SEVEN;No;0;L;<compat> 0028 4E03 0029;;;7;N;;;;;
-3227;PARENTHESIZED IDEOGRAPH EIGHT;No;0;L;<compat> 0028 516B 0029;;;8;N;;;;;
-3228;PARENTHESIZED IDEOGRAPH NINE;No;0;L;<compat> 0028 4E5D 0029;;;9;N;;;;;
-3229;PARENTHESIZED IDEOGRAPH TEN;No;0;L;<compat> 0028 5341 0029;;;10;N;;;;;
-322A;PARENTHESIZED IDEOGRAPH MOON;So;0;L;<compat> 0028 6708 0029;;;;N;;;;;
-322B;PARENTHESIZED IDEOGRAPH FIRE;So;0;L;<compat> 0028 706B 0029;;;;N;;;;;
-322C;PARENTHESIZED IDEOGRAPH WATER;So;0;L;<compat> 0028 6C34 0029;;;;N;;;;;
-322D;PARENTHESIZED IDEOGRAPH WOOD;So;0;L;<compat> 0028 6728 0029;;;;N;;;;;
-322E;PARENTHESIZED IDEOGRAPH METAL;So;0;L;<compat> 0028 91D1 0029;;;;N;;;;;
-322F;PARENTHESIZED IDEOGRAPH EARTH;So;0;L;<compat> 0028 571F 0029;;;;N;;;;;
-3230;PARENTHESIZED IDEOGRAPH SUN;So;0;L;<compat> 0028 65E5 0029;;;;N;;;;;
-3231;PARENTHESIZED IDEOGRAPH STOCK;So;0;L;<compat> 0028 682A 0029;;;;N;;;;;
-3232;PARENTHESIZED IDEOGRAPH HAVE;So;0;L;<compat> 0028 6709 0029;;;;N;;;;;
-3233;PARENTHESIZED IDEOGRAPH SOCIETY;So;0;L;<compat> 0028 793E 0029;;;;N;;;;;
-3234;PARENTHESIZED IDEOGRAPH NAME;So;0;L;<compat> 0028 540D 0029;;;;N;;;;;
-3235;PARENTHESIZED IDEOGRAPH SPECIAL;So;0;L;<compat> 0028 7279 0029;;;;N;;;;;
-3236;PARENTHESIZED IDEOGRAPH FINANCIAL;So;0;L;<compat> 0028 8CA1 0029;;;;N;;;;;
-3237;PARENTHESIZED IDEOGRAPH CONGRATULATION;So;0;L;<compat> 0028 795D 0029;;;;N;;;;;
-3238;PARENTHESIZED IDEOGRAPH LABOR;So;0;L;<compat> 0028 52B4 0029;;;;N;;;;;
-3239;PARENTHESIZED IDEOGRAPH REPRESENT;So;0;L;<compat> 0028 4EE3 0029;;;;N;;;;;
-323A;PARENTHESIZED IDEOGRAPH CALL;So;0;L;<compat> 0028 547C 0029;;;;N;;;;;
-323B;PARENTHESIZED IDEOGRAPH STUDY;So;0;L;<compat> 0028 5B66 0029;;;;N;;;;;
-323C;PARENTHESIZED IDEOGRAPH SUPERVISE;So;0;L;<compat> 0028 76E3 0029;;;;N;;;;;
-323D;PARENTHESIZED IDEOGRAPH ENTERPRISE;So;0;L;<compat> 0028 4F01 0029;;;;N;;;;;
-323E;PARENTHESIZED IDEOGRAPH RESOURCE;So;0;L;<compat> 0028 8CC7 0029;;;;N;;;;;
-323F;PARENTHESIZED IDEOGRAPH ALLIANCE;So;0;L;<compat> 0028 5354 0029;;;;N;;;;;
-3240;PARENTHESIZED IDEOGRAPH FESTIVAL;So;0;L;<compat> 0028 796D 0029;;;;N;;;;;
-3241;PARENTHESIZED IDEOGRAPH REST;So;0;L;<compat> 0028 4F11 0029;;;;N;;;;;
-3242;PARENTHESIZED IDEOGRAPH SELF;So;0;L;<compat> 0028 81EA 0029;;;;N;;;;;
-3243;PARENTHESIZED IDEOGRAPH REACH;So;0;L;<compat> 0028 81F3 0029;;;;N;;;;;
-3244;CIRCLED IDEOGRAPH QUESTION;So;0;L;<circle> 554F;;;;N;;;;;
-3245;CIRCLED IDEOGRAPH KINDERGARTEN;So;0;L;<circle> 5E7C;;;;N;;;;;
-3246;CIRCLED IDEOGRAPH SCHOOL;So;0;L;<circle> 6587;;;;N;;;;;
-3247;CIRCLED IDEOGRAPH KOTO;So;0;L;<circle> 7B8F;;;;N;;;;;
-3248;CIRCLED NUMBER TEN ON BLACK SQUARE;No;0;L;;;;10;N;;;;;
-3249;CIRCLED NUMBER TWENTY ON BLACK SQUARE;No;0;L;;;;20;N;;;;;
-324A;CIRCLED NUMBER THIRTY ON BLACK SQUARE;No;0;L;;;;30;N;;;;;
-324B;CIRCLED NUMBER FORTY ON BLACK SQUARE;No;0;L;;;;40;N;;;;;
-324C;CIRCLED NUMBER FIFTY ON BLACK SQUARE;No;0;L;;;;50;N;;;;;
-324D;CIRCLED NUMBER SIXTY ON BLACK SQUARE;No;0;L;;;;60;N;;;;;
-324E;CIRCLED NUMBER SEVENTY ON BLACK SQUARE;No;0;L;;;;70;N;;;;;
-324F;CIRCLED NUMBER EIGHTY ON BLACK SQUARE;No;0;L;;;;80;N;;;;;
-3250;PARTNERSHIP SIGN;So;0;ON;<square> 0050 0054 0045;;;;N;;;;;
-3251;CIRCLED NUMBER TWENTY ONE;No;0;ON;<circle> 0032 0031;;;21;N;;;;;
-3252;CIRCLED NUMBER TWENTY TWO;No;0;ON;<circle> 0032 0032;;;22;N;;;;;
-3253;CIRCLED NUMBER TWENTY THREE;No;0;ON;<circle> 0032 0033;;;23;N;;;;;
-3254;CIRCLED NUMBER TWENTY FOUR;No;0;ON;<circle> 0032 0034;;;24;N;;;;;
-3255;CIRCLED NUMBER TWENTY FIVE;No;0;ON;<circle> 0032 0035;;;25;N;;;;;
-3256;CIRCLED NUMBER TWENTY SIX;No;0;ON;<circle> 0032 0036;;;26;N;;;;;
-3257;CIRCLED NUMBER TWENTY SEVEN;No;0;ON;<circle> 0032 0037;;;27;N;;;;;
-3258;CIRCLED NUMBER TWENTY EIGHT;No;0;ON;<circle> 0032 0038;;;28;N;;;;;
-3259;CIRCLED NUMBER TWENTY NINE;No;0;ON;<circle> 0032 0039;;;29;N;;;;;
-325A;CIRCLED NUMBER THIRTY;No;0;ON;<circle> 0033 0030;;;30;N;;;;;
-325B;CIRCLED NUMBER THIRTY ONE;No;0;ON;<circle> 0033 0031;;;31;N;;;;;
-325C;CIRCLED NUMBER THIRTY TWO;No;0;ON;<circle> 0033 0032;;;32;N;;;;;
-325D;CIRCLED NUMBER THIRTY THREE;No;0;ON;<circle> 0033 0033;;;33;N;;;;;
-325E;CIRCLED NUMBER THIRTY FOUR;No;0;ON;<circle> 0033 0034;;;34;N;;;;;
-325F;CIRCLED NUMBER THIRTY FIVE;No;0;ON;<circle> 0033 0035;;;35;N;;;;;
-3260;CIRCLED HANGUL KIYEOK;So;0;L;<circle> 1100;;;;N;CIRCLED HANGUL GIYEOG;;;;
-3261;CIRCLED HANGUL NIEUN;So;0;L;<circle> 1102;;;;N;;;;;
-3262;CIRCLED HANGUL TIKEUT;So;0;L;<circle> 1103;;;;N;CIRCLED HANGUL DIGEUD;;;;
-3263;CIRCLED HANGUL RIEUL;So;0;L;<circle> 1105;;;;N;CIRCLED HANGUL LIEUL;;;;
-3264;CIRCLED HANGUL MIEUM;So;0;L;<circle> 1106;;;;N;;;;;
-3265;CIRCLED HANGUL PIEUP;So;0;L;<circle> 1107;;;;N;CIRCLED HANGUL BIEUB;;;;
-3266;CIRCLED HANGUL SIOS;So;0;L;<circle> 1109;;;;N;;;;;
-3267;CIRCLED HANGUL IEUNG;So;0;L;<circle> 110B;;;;N;;;;;
-3268;CIRCLED HANGUL CIEUC;So;0;L;<circle> 110C;;;;N;CIRCLED HANGUL JIEUJ;;;;
-3269;CIRCLED HANGUL CHIEUCH;So;0;L;<circle> 110E;;;;N;CIRCLED HANGUL CIEUC;;;;
-326A;CIRCLED HANGUL KHIEUKH;So;0;L;<circle> 110F;;;;N;CIRCLED HANGUL KIYEOK;;;;
-326B;CIRCLED HANGUL THIEUTH;So;0;L;<circle> 1110;;;;N;CIRCLED HANGUL TIEUT;;;;
-326C;CIRCLED HANGUL PHIEUPH;So;0;L;<circle> 1111;;;;N;CIRCLED HANGUL PIEUP;;;;
-326D;CIRCLED HANGUL HIEUH;So;0;L;<circle> 1112;;;;N;;;;;
-326E;CIRCLED HANGUL KIYEOK A;So;0;L;<circle> 1100 1161;;;;N;CIRCLED HANGUL GA;;;;
-326F;CIRCLED HANGUL NIEUN A;So;0;L;<circle> 1102 1161;;;;N;CIRCLED HANGUL NA;;;;
-3270;CIRCLED HANGUL TIKEUT A;So;0;L;<circle> 1103 1161;;;;N;CIRCLED HANGUL DA;;;;
-3271;CIRCLED HANGUL RIEUL A;So;0;L;<circle> 1105 1161;;;;N;CIRCLED HANGUL LA;;;;
-3272;CIRCLED HANGUL MIEUM A;So;0;L;<circle> 1106 1161;;;;N;CIRCLED HANGUL MA;;;;
-3273;CIRCLED HANGUL PIEUP A;So;0;L;<circle> 1107 1161;;;;N;CIRCLED HANGUL BA;;;;
-3274;CIRCLED HANGUL SIOS A;So;0;L;<circle> 1109 1161;;;;N;CIRCLED HANGUL SA;;;;
-3275;CIRCLED HANGUL IEUNG A;So;0;L;<circle> 110B 1161;;;;N;CIRCLED HANGUL A;;;;
-3276;CIRCLED HANGUL CIEUC A;So;0;L;<circle> 110C 1161;;;;N;CIRCLED HANGUL JA;;;;
-3277;CIRCLED HANGUL CHIEUCH A;So;0;L;<circle> 110E 1161;;;;N;CIRCLED HANGUL CA;;;;
-3278;CIRCLED HANGUL KHIEUKH A;So;0;L;<circle> 110F 1161;;;;N;CIRCLED HANGUL KA;;;;
-3279;CIRCLED HANGUL THIEUTH A;So;0;L;<circle> 1110 1161;;;;N;CIRCLED HANGUL TA;;;;
-327A;CIRCLED HANGUL PHIEUPH A;So;0;L;<circle> 1111 1161;;;;N;CIRCLED HANGUL PA;;;;
-327B;CIRCLED HANGUL HIEUH A;So;0;L;<circle> 1112 1161;;;;N;CIRCLED HANGUL HA;;;;
-327C;CIRCLED KOREAN CHARACTER CHAMKO;So;0;ON;<circle> 110E 1161 11B7 1100 1169;;;;N;;;;;
-327D;CIRCLED KOREAN CHARACTER JUEUI;So;0;ON;<circle> 110C 116E 110B 1174;;;;N;;;;;
-327E;CIRCLED HANGUL IEUNG U;So;0;ON;<circle> 110B 116E;;;;N;;;;;
-327F;KOREAN STANDARD SYMBOL;So;0;L;;;;;N;;;;;
-3280;CIRCLED IDEOGRAPH ONE;No;0;L;<circle> 4E00;;;1;N;;;;;
-3281;CIRCLED IDEOGRAPH TWO;No;0;L;<circle> 4E8C;;;2;N;;;;;
-3282;CIRCLED IDEOGRAPH THREE;No;0;L;<circle> 4E09;;;3;N;;;;;
-3283;CIRCLED IDEOGRAPH FOUR;No;0;L;<circle> 56DB;;;4;N;;;;;
-3284;CIRCLED IDEOGRAPH FIVE;No;0;L;<circle> 4E94;;;5;N;;;;;
-3285;CIRCLED IDEOGRAPH SIX;No;0;L;<circle> 516D;;;6;N;;;;;
-3286;CIRCLED IDEOGRAPH SEVEN;No;0;L;<circle> 4E03;;;7;N;;;;;
-3287;CIRCLED IDEOGRAPH EIGHT;No;0;L;<circle> 516B;;;8;N;;;;;
-3288;CIRCLED IDEOGRAPH NINE;No;0;L;<circle> 4E5D;;;9;N;;;;;
-3289;CIRCLED IDEOGRAPH TEN;No;0;L;<circle> 5341;;;10;N;;;;;
-328A;CIRCLED IDEOGRAPH MOON;So;0;L;<circle> 6708;;;;N;;;;;
-328B;CIRCLED IDEOGRAPH FIRE;So;0;L;<circle> 706B;;;;N;;;;;
-328C;CIRCLED IDEOGRAPH WATER;So;0;L;<circle> 6C34;;;;N;;;;;
-328D;CIRCLED IDEOGRAPH WOOD;So;0;L;<circle> 6728;;;;N;;;;;
-328E;CIRCLED IDEOGRAPH METAL;So;0;L;<circle> 91D1;;;;N;;;;;
-328F;CIRCLED IDEOGRAPH EARTH;So;0;L;<circle> 571F;;;;N;;;;;
-3290;CIRCLED IDEOGRAPH SUN;So;0;L;<circle> 65E5;;;;N;;;;;
-3291;CIRCLED IDEOGRAPH STOCK;So;0;L;<circle> 682A;;;;N;;;;;
-3292;CIRCLED IDEOGRAPH HAVE;So;0;L;<circle> 6709;;;;N;;;;;
-3293;CIRCLED IDEOGRAPH SOCIETY;So;0;L;<circle> 793E;;;;N;;;;;
-3294;CIRCLED IDEOGRAPH NAME;So;0;L;<circle> 540D;;;;N;;;;;
-3295;CIRCLED IDEOGRAPH SPECIAL;So;0;L;<circle> 7279;;;;N;;;;;
-3296;CIRCLED IDEOGRAPH FINANCIAL;So;0;L;<circle> 8CA1;;;;N;;;;;
-3297;CIRCLED IDEOGRAPH CONGRATULATION;So;0;L;<circle> 795D;;;;N;;;;;
-3298;CIRCLED IDEOGRAPH LABOR;So;0;L;<circle> 52B4;;;;N;;;;;
-3299;CIRCLED IDEOGRAPH SECRET;So;0;L;<circle> 79D8;;;;N;;;;;
-329A;CIRCLED IDEOGRAPH MALE;So;0;L;<circle> 7537;;;;N;;;;;
-329B;CIRCLED IDEOGRAPH FEMALE;So;0;L;<circle> 5973;;;;N;;;;;
-329C;CIRCLED IDEOGRAPH SUITABLE;So;0;L;<circle> 9069;;;;N;;;;;
-329D;CIRCLED IDEOGRAPH EXCELLENT;So;0;L;<circle> 512A;;;;N;;;;;
-329E;CIRCLED IDEOGRAPH PRINT;So;0;L;<circle> 5370;;;;N;;;;;
-329F;CIRCLED IDEOGRAPH ATTENTION;So;0;L;<circle> 6CE8;;;;N;;;;;
-32A0;CIRCLED IDEOGRAPH ITEM;So;0;L;<circle> 9805;;;;N;;;;;
-32A1;CIRCLED IDEOGRAPH REST;So;0;L;<circle> 4F11;;;;N;;;;;
-32A2;CIRCLED IDEOGRAPH COPY;So;0;L;<circle> 5199;;;;N;;;;;
-32A3;CIRCLED IDEOGRAPH CORRECT;So;0;L;<circle> 6B63;;;;N;;;;;
-32A4;CIRCLED IDEOGRAPH HIGH;So;0;L;<circle> 4E0A;;;;N;;;;;
-32A5;CIRCLED IDEOGRAPH CENTRE;So;0;L;<circle> 4E2D;;;;N;CIRCLED IDEOGRAPH CENTER;;;;
-32A6;CIRCLED IDEOGRAPH LOW;So;0;L;<circle> 4E0B;;;;N;;;;;
-32A7;CIRCLED IDEOGRAPH LEFT;So;0;L;<circle> 5DE6;;;;N;;;;;
-32A8;CIRCLED IDEOGRAPH RIGHT;So;0;L;<circle> 53F3;;;;N;;;;;
-32A9;CIRCLED IDEOGRAPH MEDICINE;So;0;L;<circle> 533B;;;;N;;;;;
-32AA;CIRCLED IDEOGRAPH RELIGION;So;0;L;<circle> 5B97;;;;N;;;;;
-32AB;CIRCLED IDEOGRAPH STUDY;So;0;L;<circle> 5B66;;;;N;;;;;
-32AC;CIRCLED IDEOGRAPH SUPERVISE;So;0;L;<circle> 76E3;;;;N;;;;;
-32AD;CIRCLED IDEOGRAPH ENTERPRISE;So;0;L;<circle> 4F01;;;;N;;;;;
-32AE;CIRCLED IDEOGRAPH RESOURCE;So;0;L;<circle> 8CC7;;;;N;;;;;
-32AF;CIRCLED IDEOGRAPH ALLIANCE;So;0;L;<circle> 5354;;;;N;;;;;
-32B0;CIRCLED IDEOGRAPH NIGHT;So;0;L;<circle> 591C;;;;N;;;;;
-32B1;CIRCLED NUMBER THIRTY SIX;No;0;ON;<circle> 0033 0036;;;36;N;;;;;
-32B2;CIRCLED NUMBER THIRTY SEVEN;No;0;ON;<circle> 0033 0037;;;37;N;;;;;
-32B3;CIRCLED NUMBER THIRTY EIGHT;No;0;ON;<circle> 0033 0038;;;38;N;;;;;
-32B4;CIRCLED NUMBER THIRTY NINE;No;0;ON;<circle> 0033 0039;;;39;N;;;;;
-32B5;CIRCLED NUMBER FORTY;No;0;ON;<circle> 0034 0030;;;40;N;;;;;
-32B6;CIRCLED NUMBER FORTY ONE;No;0;ON;<circle> 0034 0031;;;41;N;;;;;
-32B7;CIRCLED NUMBER FORTY TWO;No;0;ON;<circle> 0034 0032;;;42;N;;;;;
-32B8;CIRCLED NUMBER FORTY THREE;No;0;ON;<circle> 0034 0033;;;43;N;;;;;
-32B9;CIRCLED NUMBER FORTY FOUR;No;0;ON;<circle> 0034 0034;;;44;N;;;;;
-32BA;CIRCLED NUMBER FORTY FIVE;No;0;ON;<circle> 0034 0035;;;45;N;;;;;
-32BB;CIRCLED NUMBER FORTY SIX;No;0;ON;<circle> 0034 0036;;;46;N;;;;;
-32BC;CIRCLED NUMBER FORTY SEVEN;No;0;ON;<circle> 0034 0037;;;47;N;;;;;
-32BD;CIRCLED NUMBER FORTY EIGHT;No;0;ON;<circle> 0034 0038;;;48;N;;;;;
-32BE;CIRCLED NUMBER FORTY NINE;No;0;ON;<circle> 0034 0039;;;49;N;;;;;
-32BF;CIRCLED NUMBER FIFTY;No;0;ON;<circle> 0035 0030;;;50;N;;;;;
-32C0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY;So;0;L;<compat> 0031 6708;;;;N;;;;;
-32C1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY;So;0;L;<compat> 0032 6708;;;;N;;;;;
-32C2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH;So;0;L;<compat> 0033 6708;;;;N;;;;;
-32C3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL;So;0;L;<compat> 0034 6708;;;;N;;;;;
-32C4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY;So;0;L;<compat> 0035 6708;;;;N;;;;;
-32C5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE;So;0;L;<compat> 0036 6708;;;;N;;;;;
-32C6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY;So;0;L;<compat> 0037 6708;;;;N;;;;;
-32C7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST;So;0;L;<compat> 0038 6708;;;;N;;;;;
-32C8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER;So;0;L;<compat> 0039 6708;;;;N;;;;;
-32C9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER;So;0;L;<compat> 0031 0030 6708;;;;N;;;;;
-32CA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER;So;0;L;<compat> 0031 0031 6708;;;;N;;;;;
-32CB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER;So;0;L;<compat> 0031 0032 6708;;;;N;;;;;
-32CC;SQUARE HG;So;0;ON;<square> 0048 0067;;;;N;;;;;
-32CD;SQUARE ERG;So;0;ON;<square> 0065 0072 0067;;;;N;;;;;
-32CE;SQUARE EV;So;0;ON;<square> 0065 0056;;;;N;;;;;
-32CF;LIMITED LIABILITY SIGN;So;0;ON;<square> 004C 0054 0044;;;;N;;;;;
-32D0;CIRCLED KATAKANA A;So;0;L;<circle> 30A2;;;;N;;;;;
-32D1;CIRCLED KATAKANA I;So;0;L;<circle> 30A4;;;;N;;;;;
-32D2;CIRCLED KATAKANA U;So;0;L;<circle> 30A6;;;;N;;;;;
-32D3;CIRCLED KATAKANA E;So;0;L;<circle> 30A8;;;;N;;;;;
-32D4;CIRCLED KATAKANA O;So;0;L;<circle> 30AA;;;;N;;;;;
-32D5;CIRCLED KATAKANA KA;So;0;L;<circle> 30AB;;;;N;;;;;
-32D6;CIRCLED KATAKANA KI;So;0;L;<circle> 30AD;;;;N;;;;;
-32D7;CIRCLED KATAKANA KU;So;0;L;<circle> 30AF;;;;N;;;;;
-32D8;CIRCLED KATAKANA KE;So;0;L;<circle> 30B1;;;;N;;;;;
-32D9;CIRCLED KATAKANA KO;So;0;L;<circle> 30B3;;;;N;;;;;
-32DA;CIRCLED KATAKANA SA;So;0;L;<circle> 30B5;;;;N;;;;;
-32DB;CIRCLED KATAKANA SI;So;0;L;<circle> 30B7;;;;N;;;;;
-32DC;CIRCLED KATAKANA SU;So;0;L;<circle> 30B9;;;;N;;;;;
-32DD;CIRCLED KATAKANA SE;So;0;L;<circle> 30BB;;;;N;;;;;
-32DE;CIRCLED KATAKANA SO;So;0;L;<circle> 30BD;;;;N;;;;;
-32DF;CIRCLED KATAKANA TA;So;0;L;<circle> 30BF;;;;N;;;;;
-32E0;CIRCLED KATAKANA TI;So;0;L;<circle> 30C1;;;;N;;;;;
-32E1;CIRCLED KATAKANA TU;So;0;L;<circle> 30C4;;;;N;;;;;
-32E2;CIRCLED KATAKANA TE;So;0;L;<circle> 30C6;;;;N;;;;;
-32E3;CIRCLED KATAKANA TO;So;0;L;<circle> 30C8;;;;N;;;;;
-32E4;CIRCLED KATAKANA NA;So;0;L;<circle> 30CA;;;;N;;;;;
-32E5;CIRCLED KATAKANA NI;So;0;L;<circle> 30CB;;;;N;;;;;
-32E6;CIRCLED KATAKANA NU;So;0;L;<circle> 30CC;;;;N;;;;;
-32E7;CIRCLED KATAKANA NE;So;0;L;<circle> 30CD;;;;N;;;;;
-32E8;CIRCLED KATAKANA NO;So;0;L;<circle> 30CE;;;;N;;;;;
-32E9;CIRCLED KATAKANA HA;So;0;L;<circle> 30CF;;;;N;;;;;
-32EA;CIRCLED KATAKANA HI;So;0;L;<circle> 30D2;;;;N;;;;;
-32EB;CIRCLED KATAKANA HU;So;0;L;<circle> 30D5;;;;N;;;;;
-32EC;CIRCLED KATAKANA HE;So;0;L;<circle> 30D8;;;;N;;;;;
-32ED;CIRCLED KATAKANA HO;So;0;L;<circle> 30DB;;;;N;;;;;
-32EE;CIRCLED KATAKANA MA;So;0;L;<circle> 30DE;;;;N;;;;;
-32EF;CIRCLED KATAKANA MI;So;0;L;<circle> 30DF;;;;N;;;;;
-32F0;CIRCLED KATAKANA MU;So;0;L;<circle> 30E0;;;;N;;;;;
-32F1;CIRCLED KATAKANA ME;So;0;L;<circle> 30E1;;;;N;;;;;
-32F2;CIRCLED KATAKANA MO;So;0;L;<circle> 30E2;;;;N;;;;;
-32F3;CIRCLED KATAKANA YA;So;0;L;<circle> 30E4;;;;N;;;;;
-32F4;CIRCLED KATAKANA YU;So;0;L;<circle> 30E6;;;;N;;;;;
-32F5;CIRCLED KATAKANA YO;So;0;L;<circle> 30E8;;;;N;;;;;
-32F6;CIRCLED KATAKANA RA;So;0;L;<circle> 30E9;;;;N;;;;;
-32F7;CIRCLED KATAKANA RI;So;0;L;<circle> 30EA;;;;N;;;;;
-32F8;CIRCLED KATAKANA RU;So;0;L;<circle> 30EB;;;;N;;;;;
-32F9;CIRCLED KATAKANA RE;So;0;L;<circle> 30EC;;;;N;;;;;
-32FA;CIRCLED KATAKANA RO;So;0;L;<circle> 30ED;;;;N;;;;;
-32FB;CIRCLED KATAKANA WA;So;0;L;<circle> 30EF;;;;N;;;;;
-32FC;CIRCLED KATAKANA WI;So;0;L;<circle> 30F0;;;;N;;;;;
-32FD;CIRCLED KATAKANA WE;So;0;L;<circle> 30F1;;;;N;;;;;
-32FE;CIRCLED KATAKANA WO;So;0;L;<circle> 30F2;;;;N;;;;;
-3300;SQUARE APAATO;So;0;L;<square> 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;;
-3301;SQUARE ARUHUA;So;0;L;<square> 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;;
-3302;SQUARE ANPEA;So;0;L;<square> 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;;
-3303;SQUARE AARU;So;0;L;<square> 30A2 30FC 30EB;;;;N;SQUARED AARU;;;;
-3304;SQUARE ININGU;So;0;L;<square> 30A4 30CB 30F3 30B0;;;;N;SQUARED ININGU;;;;
-3305;SQUARE INTI;So;0;L;<square> 30A4 30F3 30C1;;;;N;SQUARED INTI;;;;
-3306;SQUARE UON;So;0;L;<square> 30A6 30A9 30F3;;;;N;SQUARED UON;;;;
-3307;SQUARE ESUKUUDO;So;0;L;<square> 30A8 30B9 30AF 30FC 30C9;;;;N;SQUARED ESUKUUDO;;;;
-3308;SQUARE EEKAA;So;0;L;<square> 30A8 30FC 30AB 30FC;;;;N;SQUARED EEKAA;;;;
-3309;SQUARE ONSU;So;0;L;<square> 30AA 30F3 30B9;;;;N;SQUARED ONSU;;;;
-330A;SQUARE OOMU;So;0;L;<square> 30AA 30FC 30E0;;;;N;SQUARED OOMU;;;;
-330B;SQUARE KAIRI;So;0;L;<square> 30AB 30A4 30EA;;;;N;SQUARED KAIRI;;;;
-330C;SQUARE KARATTO;So;0;L;<square> 30AB 30E9 30C3 30C8;;;;N;SQUARED KARATTO;;;;
-330D;SQUARE KARORII;So;0;L;<square> 30AB 30ED 30EA 30FC;;;;N;SQUARED KARORII;;;;
-330E;SQUARE GARON;So;0;L;<square> 30AC 30ED 30F3;;;;N;SQUARED GARON;;;;
-330F;SQUARE GANMA;So;0;L;<square> 30AC 30F3 30DE;;;;N;SQUARED GANMA;;;;
-3310;SQUARE GIGA;So;0;L;<square> 30AE 30AC;;;;N;SQUARED GIGA;;;;
-3311;SQUARE GINII;So;0;L;<square> 30AE 30CB 30FC;;;;N;SQUARED GINII;;;;
-3312;SQUARE KYURII;So;0;L;<square> 30AD 30E5 30EA 30FC;;;;N;SQUARED KYURII;;;;
-3313;SQUARE GIRUDAA;So;0;L;<square> 30AE 30EB 30C0 30FC;;;;N;SQUARED GIRUDAA;;;;
-3314;SQUARE KIRO;So;0;L;<square> 30AD 30ED;;;;N;SQUARED KIRO;;;;
-3315;SQUARE KIROGURAMU;So;0;L;<square> 30AD 30ED 30B0 30E9 30E0;;;;N;SQUARED KIROGURAMU;;;;
-3316;SQUARE KIROMEETORU;So;0;L;<square> 30AD 30ED 30E1 30FC 30C8 30EB;;;;N;SQUARED KIROMEETORU;;;;
-3317;SQUARE KIROWATTO;So;0;L;<square> 30AD 30ED 30EF 30C3 30C8;;;;N;SQUARED KIROWATTO;;;;
-3318;SQUARE GURAMU;So;0;L;<square> 30B0 30E9 30E0;;;;N;SQUARED GURAMU;;;;
-3319;SQUARE GURAMUTON;So;0;L;<square> 30B0 30E9 30E0 30C8 30F3;;;;N;SQUARED GURAMUTON;;;;
-331A;SQUARE KURUZEIRO;So;0;L;<square> 30AF 30EB 30BC 30A4 30ED;;;;N;SQUARED KURUZEIRO;;;;
-331B;SQUARE KUROONE;So;0;L;<square> 30AF 30ED 30FC 30CD;;;;N;SQUARED KUROONE;;;;
-331C;SQUARE KEESU;So;0;L;<square> 30B1 30FC 30B9;;;;N;SQUARED KEESU;;;;
-331D;SQUARE KORUNA;So;0;L;<square> 30B3 30EB 30CA;;;;N;SQUARED KORUNA;;;;
-331E;SQUARE KOOPO;So;0;L;<square> 30B3 30FC 30DD;;;;N;SQUARED KOOPO;;;;
-331F;SQUARE SAIKURU;So;0;L;<square> 30B5 30A4 30AF 30EB;;;;N;SQUARED SAIKURU;;;;
-3320;SQUARE SANTIIMU;So;0;L;<square> 30B5 30F3 30C1 30FC 30E0;;;;N;SQUARED SANTIIMU;;;;
-3321;SQUARE SIRINGU;So;0;L;<square> 30B7 30EA 30F3 30B0;;;;N;SQUARED SIRINGU;;;;
-3322;SQUARE SENTI;So;0;L;<square> 30BB 30F3 30C1;;;;N;SQUARED SENTI;;;;
-3323;SQUARE SENTO;So;0;L;<square> 30BB 30F3 30C8;;;;N;SQUARED SENTO;;;;
-3324;SQUARE DAASU;So;0;L;<square> 30C0 30FC 30B9;;;;N;SQUARED DAASU;;;;
-3325;SQUARE DESI;So;0;L;<square> 30C7 30B7;;;;N;SQUARED DESI;;;;
-3326;SQUARE DORU;So;0;L;<square> 30C9 30EB;;;;N;SQUARED DORU;;;;
-3327;SQUARE TON;So;0;L;<square> 30C8 30F3;;;;N;SQUARED TON;;;;
-3328;SQUARE NANO;So;0;L;<square> 30CA 30CE;;;;N;SQUARED NANO;;;;
-3329;SQUARE NOTTO;So;0;L;<square> 30CE 30C3 30C8;;;;N;SQUARED NOTTO;;;;
-332A;SQUARE HAITU;So;0;L;<square> 30CF 30A4 30C4;;;;N;SQUARED HAITU;;;;
-332B;SQUARE PAASENTO;So;0;L;<square> 30D1 30FC 30BB 30F3 30C8;;;;N;SQUARED PAASENTO;;;;
-332C;SQUARE PAATU;So;0;L;<square> 30D1 30FC 30C4;;;;N;SQUARED PAATU;;;;
-332D;SQUARE BAARERU;So;0;L;<square> 30D0 30FC 30EC 30EB;;;;N;SQUARED BAARERU;;;;
-332E;SQUARE PIASUTORU;So;0;L;<square> 30D4 30A2 30B9 30C8 30EB;;;;N;SQUARED PIASUTORU;;;;
-332F;SQUARE PIKURU;So;0;L;<square> 30D4 30AF 30EB;;;;N;SQUARED PIKURU;;;;
-3330;SQUARE PIKO;So;0;L;<square> 30D4 30B3;;;;N;SQUARED PIKO;;;;
-3331;SQUARE BIRU;So;0;L;<square> 30D3 30EB;;;;N;SQUARED BIRU;;;;
-3332;SQUARE HUARADDO;So;0;L;<square> 30D5 30A1 30E9 30C3 30C9;;;;N;SQUARED HUARADDO;;;;
-3333;SQUARE HUIITO;So;0;L;<square> 30D5 30A3 30FC 30C8;;;;N;SQUARED HUIITO;;;;
-3334;SQUARE BUSSYERU;So;0;L;<square> 30D6 30C3 30B7 30A7 30EB;;;;N;SQUARED BUSSYERU;;;;
-3335;SQUARE HURAN;So;0;L;<square> 30D5 30E9 30F3;;;;N;SQUARED HURAN;;;;
-3336;SQUARE HEKUTAARU;So;0;L;<square> 30D8 30AF 30BF 30FC 30EB;;;;N;SQUARED HEKUTAARU;;;;
-3337;SQUARE PESO;So;0;L;<square> 30DA 30BD;;;;N;SQUARED PESO;;;;
-3338;SQUARE PENIHI;So;0;L;<square> 30DA 30CB 30D2;;;;N;SQUARED PENIHI;;;;
-3339;SQUARE HERUTU;So;0;L;<square> 30D8 30EB 30C4;;;;N;SQUARED HERUTU;;;;
-333A;SQUARE PENSU;So;0;L;<square> 30DA 30F3 30B9;;;;N;SQUARED PENSU;;;;
-333B;SQUARE PEEZI;So;0;L;<square> 30DA 30FC 30B8;;;;N;SQUARED PEEZI;;;;
-333C;SQUARE BEETA;So;0;L;<square> 30D9 30FC 30BF;;;;N;SQUARED BEETA;;;;
-333D;SQUARE POINTO;So;0;L;<square> 30DD 30A4 30F3 30C8;;;;N;SQUARED POINTO;;;;
-333E;SQUARE BORUTO;So;0;L;<square> 30DC 30EB 30C8;;;;N;SQUARED BORUTO;;;;
-333F;SQUARE HON;So;0;L;<square> 30DB 30F3;;;;N;SQUARED HON;;;;
-3340;SQUARE PONDO;So;0;L;<square> 30DD 30F3 30C9;;;;N;SQUARED PONDO;;;;
-3341;SQUARE HOORU;So;0;L;<square> 30DB 30FC 30EB;;;;N;SQUARED HOORU;;;;
-3342;SQUARE HOON;So;0;L;<square> 30DB 30FC 30F3;;;;N;SQUARED HOON;;;;
-3343;SQUARE MAIKURO;So;0;L;<square> 30DE 30A4 30AF 30ED;;;;N;SQUARED MAIKURO;;;;
-3344;SQUARE MAIRU;So;0;L;<square> 30DE 30A4 30EB;;;;N;SQUARED MAIRU;;;;
-3345;SQUARE MAHHA;So;0;L;<square> 30DE 30C3 30CF;;;;N;SQUARED MAHHA;;;;
-3346;SQUARE MARUKU;So;0;L;<square> 30DE 30EB 30AF;;;;N;SQUARED MARUKU;;;;
-3347;SQUARE MANSYON;So;0;L;<square> 30DE 30F3 30B7 30E7 30F3;;;;N;SQUARED MANSYON;;;;
-3348;SQUARE MIKURON;So;0;L;<square> 30DF 30AF 30ED 30F3;;;;N;SQUARED MIKURON;;;;
-3349;SQUARE MIRI;So;0;L;<square> 30DF 30EA;;;;N;SQUARED MIRI;;;;
-334A;SQUARE MIRIBAARU;So;0;L;<square> 30DF 30EA 30D0 30FC 30EB;;;;N;SQUARED MIRIBAARU;;;;
-334B;SQUARE MEGA;So;0;L;<square> 30E1 30AC;;;;N;SQUARED MEGA;;;;
-334C;SQUARE MEGATON;So;0;L;<square> 30E1 30AC 30C8 30F3;;;;N;SQUARED MEGATON;;;;
-334D;SQUARE MEETORU;So;0;L;<square> 30E1 30FC 30C8 30EB;;;;N;SQUARED MEETORU;;;;
-334E;SQUARE YAADO;So;0;L;<square> 30E4 30FC 30C9;;;;N;SQUARED YAADO;;;;
-334F;SQUARE YAARU;So;0;L;<square> 30E4 30FC 30EB;;;;N;SQUARED YAARU;;;;
-3350;SQUARE YUAN;So;0;L;<square> 30E6 30A2 30F3;;;;N;SQUARED YUAN;;;;
-3351;SQUARE RITTORU;So;0;L;<square> 30EA 30C3 30C8 30EB;;;;N;SQUARED RITTORU;;;;
-3352;SQUARE RIRA;So;0;L;<square> 30EA 30E9;;;;N;SQUARED RIRA;;;;
-3353;SQUARE RUPII;So;0;L;<square> 30EB 30D4 30FC;;;;N;SQUARED RUPII;;;;
-3354;SQUARE RUUBURU;So;0;L;<square> 30EB 30FC 30D6 30EB;;;;N;SQUARED RUUBURU;;;;
-3355;SQUARE REMU;So;0;L;<square> 30EC 30E0;;;;N;SQUARED REMU;;;;
-3356;SQUARE RENTOGEN;So;0;L;<square> 30EC 30F3 30C8 30B2 30F3;;;;N;SQUARED RENTOGEN;;;;
-3357;SQUARE WATTO;So;0;L;<square> 30EF 30C3 30C8;;;;N;SQUARED WATTO;;;;
-3358;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO;So;0;L;<compat> 0030 70B9;;;;N;;;;;
-3359;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE;So;0;L;<compat> 0031 70B9;;;;N;;;;;
-335A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO;So;0;L;<compat> 0032 70B9;;;;N;;;;;
-335B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE;So;0;L;<compat> 0033 70B9;;;;N;;;;;
-335C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR;So;0;L;<compat> 0034 70B9;;;;N;;;;;
-335D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE;So;0;L;<compat> 0035 70B9;;;;N;;;;;
-335E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX;So;0;L;<compat> 0036 70B9;;;;N;;;;;
-335F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN;So;0;L;<compat> 0037 70B9;;;;N;;;;;
-3360;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT;So;0;L;<compat> 0038 70B9;;;;N;;;;;
-3361;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE;So;0;L;<compat> 0039 70B9;;;;N;;;;;
-3362;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN;So;0;L;<compat> 0031 0030 70B9;;;;N;;;;;
-3363;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN;So;0;L;<compat> 0031 0031 70B9;;;;N;;;;;
-3364;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE;So;0;L;<compat> 0031 0032 70B9;;;;N;;;;;
-3365;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN;So;0;L;<compat> 0031 0033 70B9;;;;N;;;;;
-3366;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN;So;0;L;<compat> 0031 0034 70B9;;;;N;;;;;
-3367;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN;So;0;L;<compat> 0031 0035 70B9;;;;N;;;;;
-3368;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN;So;0;L;<compat> 0031 0036 70B9;;;;N;;;;;
-3369;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN;So;0;L;<compat> 0031 0037 70B9;;;;N;;;;;
-336A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN;So;0;L;<compat> 0031 0038 70B9;;;;N;;;;;
-336B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN;So;0;L;<compat> 0031 0039 70B9;;;;N;;;;;
-336C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY;So;0;L;<compat> 0032 0030 70B9;;;;N;;;;;
-336D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE;So;0;L;<compat> 0032 0031 70B9;;;;N;;;;;
-336E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO;So;0;L;<compat> 0032 0032 70B9;;;;N;;;;;
-336F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE;So;0;L;<compat> 0032 0033 70B9;;;;N;;;;;
-3370;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR;So;0;L;<compat> 0032 0034 70B9;;;;N;;;;;
-3371;SQUARE HPA;So;0;L;<square> 0068 0050 0061;;;;N;;;;;
-3372;SQUARE DA;So;0;L;<square> 0064 0061;;;;N;;;;;
-3373;SQUARE AU;So;0;L;<square> 0041 0055;;;;N;;;;;
-3374;SQUARE BAR;So;0;L;<square> 0062 0061 0072;;;;N;;;;;
-3375;SQUARE OV;So;0;L;<square> 006F 0056;;;;N;;;;;
-3376;SQUARE PC;So;0;L;<square> 0070 0063;;;;N;;;;;
-3377;SQUARE DM;So;0;ON;<square> 0064 006D;;;;N;;;;;
-3378;SQUARE DM SQUARED;So;0;ON;<square> 0064 006D 00B2;;;;N;;;;;
-3379;SQUARE DM CUBED;So;0;ON;<square> 0064 006D 00B3;;;;N;;;;;
-337A;SQUARE IU;So;0;ON;<square> 0049 0055;;;;N;;;;;
-337B;SQUARE ERA NAME HEISEI;So;0;L;<square> 5E73 6210;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME HEISEI;;;;
-337C;SQUARE ERA NAME SYOUWA;So;0;L;<square> 662D 548C;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME SYOUWA;;;;
-337D;SQUARE ERA NAME TAISYOU;So;0;L;<square> 5927 6B63;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME TAISYOU;;;;
-337E;SQUARE ERA NAME MEIZI;So;0;L;<square> 660E 6CBB;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME MEIZI;;;;
-337F;SQUARE CORPORATION;So;0;L;<square> 682A 5F0F 4F1A 793E;;;;N;SQUARED FOUR IDEOGRAPHS CORPORATION;;;;
-3380;SQUARE PA AMPS;So;0;L;<square> 0070 0041;;;;N;SQUARED PA AMPS;;;;
-3381;SQUARE NA;So;0;L;<square> 006E 0041;;;;N;SQUARED NA;;;;
-3382;SQUARE MU A;So;0;L;<square> 03BC 0041;;;;N;SQUARED MU A;;;;
-3383;SQUARE MA;So;0;L;<square> 006D 0041;;;;N;SQUARED MA;;;;
-3384;SQUARE KA;So;0;L;<square> 006B 0041;;;;N;SQUARED KA;;;;
-3385;SQUARE KB;So;0;L;<square> 004B 0042;;;;N;SQUARED KB;;;;
-3386;SQUARE MB;So;0;L;<square> 004D 0042;;;;N;SQUARED MB;;;;
-3387;SQUARE GB;So;0;L;<square> 0047 0042;;;;N;SQUARED GB;;;;
-3388;SQUARE CAL;So;0;L;<square> 0063 0061 006C;;;;N;SQUARED CAL;;;;
-3389;SQUARE KCAL;So;0;L;<square> 006B 0063 0061 006C;;;;N;SQUARED KCAL;;;;
-338A;SQUARE PF;So;0;L;<square> 0070 0046;;;;N;SQUARED PF;;;;
-338B;SQUARE NF;So;0;L;<square> 006E 0046;;;;N;SQUARED NF;;;;
-338C;SQUARE MU F;So;0;L;<square> 03BC 0046;;;;N;SQUARED MU F;;;;
-338D;SQUARE MU G;So;0;L;<square> 03BC 0067;;;;N;SQUARED MU G;;;;
-338E;SQUARE MG;So;0;L;<square> 006D 0067;;;;N;SQUARED MG;;;;
-338F;SQUARE KG;So;0;L;<square> 006B 0067;;;;N;SQUARED KG;;;;
-3390;SQUARE HZ;So;0;L;<square> 0048 007A;;;;N;SQUARED HZ;;;;
-3391;SQUARE KHZ;So;0;L;<square> 006B 0048 007A;;;;N;SQUARED KHZ;;;;
-3392;SQUARE MHZ;So;0;L;<square> 004D 0048 007A;;;;N;SQUARED MHZ;;;;
-3393;SQUARE GHZ;So;0;L;<square> 0047 0048 007A;;;;N;SQUARED GHZ;;;;
-3394;SQUARE THZ;So;0;L;<square> 0054 0048 007A;;;;N;SQUARED THZ;;;;
-3395;SQUARE MU L;So;0;L;<square> 03BC 2113;;;;N;SQUARED MU L;;;;
-3396;SQUARE ML;So;0;L;<square> 006D 2113;;;;N;SQUARED ML;;;;
-3397;SQUARE DL;So;0;L;<square> 0064 2113;;;;N;SQUARED DL;;;;
-3398;SQUARE KL;So;0;L;<square> 006B 2113;;;;N;SQUARED KL;;;;
-3399;SQUARE FM;So;0;L;<square> 0066 006D;;;;N;SQUARED FM;;;;
-339A;SQUARE NM;So;0;L;<square> 006E 006D;;;;N;SQUARED NM;;;;
-339B;SQUARE MU M;So;0;L;<square> 03BC 006D;;;;N;SQUARED MU M;;;;
-339C;SQUARE MM;So;0;L;<square> 006D 006D;;;;N;SQUARED MM;;;;
-339D;SQUARE CM;So;0;L;<square> 0063 006D;;;;N;SQUARED CM;;;;
-339E;SQUARE KM;So;0;L;<square> 006B 006D;;;;N;SQUARED KM;;;;
-339F;SQUARE MM SQUARED;So;0;L;<square> 006D 006D 00B2;;;;N;SQUARED MM SQUARED;;;;
-33A0;SQUARE CM SQUARED;So;0;L;<square> 0063 006D 00B2;;;;N;SQUARED CM SQUARED;;;;
-33A1;SQUARE M SQUARED;So;0;L;<square> 006D 00B2;;;;N;SQUARED M SQUARED;;;;
-33A2;SQUARE KM SQUARED;So;0;L;<square> 006B 006D 00B2;;;;N;SQUARED KM SQUARED;;;;
-33A3;SQUARE MM CUBED;So;0;L;<square> 006D 006D 00B3;;;;N;SQUARED MM CUBED;;;;
-33A4;SQUARE CM CUBED;So;0;L;<square> 0063 006D 00B3;;;;N;SQUARED CM CUBED;;;;
-33A5;SQUARE M CUBED;So;0;L;<square> 006D 00B3;;;;N;SQUARED M CUBED;;;;
-33A6;SQUARE KM CUBED;So;0;L;<square> 006B 006D 00B3;;;;N;SQUARED KM CUBED;;;;
-33A7;SQUARE M OVER S;So;0;L;<square> 006D 2215 0073;;;;N;SQUARED M OVER S;;;;
-33A8;SQUARE M OVER S SQUARED;So;0;L;<square> 006D 2215 0073 00B2;;;;N;SQUARED M OVER S SQUARED;;;;
-33A9;SQUARE PA;So;0;L;<square> 0050 0061;;;;N;SQUARED PA;;;;
-33AA;SQUARE KPA;So;0;L;<square> 006B 0050 0061;;;;N;SQUARED KPA;;;;
-33AB;SQUARE MPA;So;0;L;<square> 004D 0050 0061;;;;N;SQUARED MPA;;;;
-33AC;SQUARE GPA;So;0;L;<square> 0047 0050 0061;;;;N;SQUARED GPA;;;;
-33AD;SQUARE RAD;So;0;L;<square> 0072 0061 0064;;;;N;SQUARED RAD;;;;
-33AE;SQUARE RAD OVER S;So;0;L;<square> 0072 0061 0064 2215 0073;;;;N;SQUARED RAD OVER S;;;;
-33AF;SQUARE RAD OVER S SQUARED;So;0;L;<square> 0072 0061 0064 2215 0073 00B2;;;;N;SQUARED RAD OVER S SQUARED;;;;
-33B0;SQUARE PS;So;0;L;<square> 0070 0073;;;;N;SQUARED PS;;;;
-33B1;SQUARE NS;So;0;L;<square> 006E 0073;;;;N;SQUARED NS;;;;
-33B2;SQUARE MU S;So;0;L;<square> 03BC 0073;;;;N;SQUARED MU S;;;;
-33B3;SQUARE MS;So;0;L;<square> 006D 0073;;;;N;SQUARED MS;;;;
-33B4;SQUARE PV;So;0;L;<square> 0070 0056;;;;N;SQUARED PV;;;;
-33B5;SQUARE NV;So;0;L;<square> 006E 0056;;;;N;SQUARED NV;;;;
-33B6;SQUARE MU V;So;0;L;<square> 03BC 0056;;;;N;SQUARED MU V;;;;
-33B7;SQUARE MV;So;0;L;<square> 006D 0056;;;;N;SQUARED MV;;;;
-33B8;SQUARE KV;So;0;L;<square> 006B 0056;;;;N;SQUARED KV;;;;
-33B9;SQUARE MV MEGA;So;0;L;<square> 004D 0056;;;;N;SQUARED MV MEGA;;;;
-33BA;SQUARE PW;So;0;L;<square> 0070 0057;;;;N;SQUARED PW;;;;
-33BB;SQUARE NW;So;0;L;<square> 006E 0057;;;;N;SQUARED NW;;;;
-33BC;SQUARE MU W;So;0;L;<square> 03BC 0057;;;;N;SQUARED MU W;;;;
-33BD;SQUARE MW;So;0;L;<square> 006D 0057;;;;N;SQUARED MW;;;;
-33BE;SQUARE KW;So;0;L;<square> 006B 0057;;;;N;SQUARED KW;;;;
-33BF;SQUARE MW MEGA;So;0;L;<square> 004D 0057;;;;N;SQUARED MW MEGA;;;;
-33C0;SQUARE K OHM;So;0;L;<square> 006B 03A9;;;;N;SQUARED K OHM;;;;
-33C1;SQUARE M OHM;So;0;L;<square> 004D 03A9;;;;N;SQUARED M OHM;;;;
-33C2;SQUARE AM;So;0;L;<square> 0061 002E 006D 002E;;;;N;SQUARED AM;;;;
-33C3;SQUARE BQ;So;0;L;<square> 0042 0071;;;;N;SQUARED BQ;;;;
-33C4;SQUARE CC;So;0;L;<square> 0063 0063;;;;N;SQUARED CC;;;;
-33C5;SQUARE CD;So;0;L;<square> 0063 0064;;;;N;SQUARED CD;;;;
-33C6;SQUARE C OVER KG;So;0;L;<square> 0043 2215 006B 0067;;;;N;SQUARED C OVER KG;;;;
-33C7;SQUARE CO;So;0;L;<square> 0043 006F 002E;;;;N;SQUARED CO;;;;
-33C8;SQUARE DB;So;0;L;<square> 0064 0042;;;;N;SQUARED DB;;;;
-33C9;SQUARE GY;So;0;L;<square> 0047 0079;;;;N;SQUARED GY;;;;
-33CA;SQUARE HA;So;0;L;<square> 0068 0061;;;;N;SQUARED HA;;;;
-33CB;SQUARE HP;So;0;L;<square> 0048 0050;;;;N;SQUARED HP;;;;
-33CC;SQUARE IN;So;0;L;<square> 0069 006E;;;;N;SQUARED IN;;;;
-33CD;SQUARE KK;So;0;L;<square> 004B 004B;;;;N;SQUARED KK;;;;
-33CE;SQUARE KM CAPITAL;So;0;L;<square> 004B 004D;;;;N;SQUARED KM CAPITAL;;;;
-33CF;SQUARE KT;So;0;L;<square> 006B 0074;;;;N;SQUARED KT;;;;
-33D0;SQUARE LM;So;0;L;<square> 006C 006D;;;;N;SQUARED LM;;;;
-33D1;SQUARE LN;So;0;L;<square> 006C 006E;;;;N;SQUARED LN;;;;
-33D2;SQUARE LOG;So;0;L;<square> 006C 006F 0067;;;;N;SQUARED LOG;;;;
-33D3;SQUARE LX;So;0;L;<square> 006C 0078;;;;N;SQUARED LX;;;;
-33D4;SQUARE MB SMALL;So;0;L;<square> 006D 0062;;;;N;SQUARED MB SMALL;;;;
-33D5;SQUARE MIL;So;0;L;<square> 006D 0069 006C;;;;N;SQUARED MIL;;;;
-33D6;SQUARE MOL;So;0;L;<square> 006D 006F 006C;;;;N;SQUARED MOL;;;;
-33D7;SQUARE PH;So;0;L;<square> 0050 0048;;;;N;SQUARED PH;;;;
-33D8;SQUARE PM;So;0;L;<square> 0070 002E 006D 002E;;;;N;SQUARED PM;;;;
-33D9;SQUARE PPM;So;0;L;<square> 0050 0050 004D;;;;N;SQUARED PPM;;;;
-33DA;SQUARE PR;So;0;L;<square> 0050 0052;;;;N;SQUARED PR;;;;
-33DB;SQUARE SR;So;0;L;<square> 0073 0072;;;;N;SQUARED SR;;;;
-33DC;SQUARE SV;So;0;L;<square> 0053 0076;;;;N;SQUARED SV;;;;
-33DD;SQUARE WB;So;0;L;<square> 0057 0062;;;;N;SQUARED WB;;;;
-33DE;SQUARE V OVER M;So;0;ON;<square> 0056 2215 006D;;;;N;;;;;
-33DF;SQUARE A OVER M;So;0;ON;<square> 0041 2215 006D;;;;N;;;;;
-33E0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE;So;0;L;<compat> 0031 65E5;;;;N;;;;;
-33E1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO;So;0;L;<compat> 0032 65E5;;;;N;;;;;
-33E2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE;So;0;L;<compat> 0033 65E5;;;;N;;;;;
-33E3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR;So;0;L;<compat> 0034 65E5;;;;N;;;;;
-33E4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE;So;0;L;<compat> 0035 65E5;;;;N;;;;;
-33E5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX;So;0;L;<compat> 0036 65E5;;;;N;;;;;
-33E6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN;So;0;L;<compat> 0037 65E5;;;;N;;;;;
-33E7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT;So;0;L;<compat> 0038 65E5;;;;N;;;;;
-33E8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE;So;0;L;<compat> 0039 65E5;;;;N;;;;;
-33E9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN;So;0;L;<compat> 0031 0030 65E5;;;;N;;;;;
-33EA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN;So;0;L;<compat> 0031 0031 65E5;;;;N;;;;;
-33EB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE;So;0;L;<compat> 0031 0032 65E5;;;;N;;;;;
-33EC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN;So;0;L;<compat> 0031 0033 65E5;;;;N;;;;;
-33ED;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN;So;0;L;<compat> 0031 0034 65E5;;;;N;;;;;
-33EE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN;So;0;L;<compat> 0031 0035 65E5;;;;N;;;;;
-33EF;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN;So;0;L;<compat> 0031 0036 65E5;;;;N;;;;;
-33F0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN;So;0;L;<compat> 0031 0037 65E5;;;;N;;;;;
-33F1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN;So;0;L;<compat> 0031 0038 65E5;;;;N;;;;;
-33F2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN;So;0;L;<compat> 0031 0039 65E5;;;;N;;;;;
-33F3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY;So;0;L;<compat> 0032 0030 65E5;;;;N;;;;;
-33F4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE;So;0;L;<compat> 0032 0031 65E5;;;;N;;;;;
-33F5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO;So;0;L;<compat> 0032 0032 65E5;;;;N;;;;;
-33F6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE;So;0;L;<compat> 0032 0033 65E5;;;;N;;;;;
-33F7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR;So;0;L;<compat> 0032 0034 65E5;;;;N;;;;;
-33F8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE;So;0;L;<compat> 0032 0035 65E5;;;;N;;;;;
-33F9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX;So;0;L;<compat> 0032 0036 65E5;;;;N;;;;;
-33FA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN;So;0;L;<compat> 0032 0037 65E5;;;;N;;;;;
-33FB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT;So;0;L;<compat> 0032 0038 65E5;;;;N;;;;;
-33FC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE;So;0;L;<compat> 0032 0039 65E5;;;;N;;;;;
-33FD;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY;So;0;L;<compat> 0033 0030 65E5;;;;N;;;;;
-33FE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE;So;0;L;<compat> 0033 0031 65E5;;;;N;;;;;
-33FF;SQUARE GAL;So;0;ON;<square> 0067 0061 006C;;;;N;;;;;
-3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
-4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
-4DC0;HEXAGRAM FOR THE CREATIVE HEAVEN;So;0;ON;;;;;N;;;;;
-4DC1;HEXAGRAM FOR THE RECEPTIVE EARTH;So;0;ON;;;;;N;;;;;
-4DC2;HEXAGRAM FOR DIFFICULTY AT THE BEGINNING;So;0;ON;;;;;N;;;;;
-4DC3;HEXAGRAM FOR YOUTHFUL FOLLY;So;0;ON;;;;;N;;;;;
-4DC4;HEXAGRAM FOR WAITING;So;0;ON;;;;;N;;;;;
-4DC5;HEXAGRAM FOR CONFLICT;So;0;ON;;;;;N;;;;;
-4DC6;HEXAGRAM FOR THE ARMY;So;0;ON;;;;;N;;;;;
-4DC7;HEXAGRAM FOR HOLDING TOGETHER;So;0;ON;;;;;N;;;;;
-4DC8;HEXAGRAM FOR SMALL TAMING;So;0;ON;;;;;N;;;;;
-4DC9;HEXAGRAM FOR TREADING;So;0;ON;;;;;N;;;;;
-4DCA;HEXAGRAM FOR PEACE;So;0;ON;;;;;N;;;;;
-4DCB;HEXAGRAM FOR STANDSTILL;So;0;ON;;;;;N;;;;;
-4DCC;HEXAGRAM FOR FELLOWSHIP;So;0;ON;;;;;N;;;;;
-4DCD;HEXAGRAM FOR GREAT POSSESSION;So;0;ON;;;;;N;;;;;
-4DCE;HEXAGRAM FOR MODESTY;So;0;ON;;;;;N;;;;;
-4DCF;HEXAGRAM FOR ENTHUSIASM;So;0;ON;;;;;N;;;;;
-4DD0;HEXAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;;
-4DD1;HEXAGRAM FOR WORK ON THE DECAYED;So;0;ON;;;;;N;;;;;
-4DD2;HEXAGRAM FOR APPROACH;So;0;ON;;;;;N;;;;;
-4DD3;HEXAGRAM FOR CONTEMPLATION;So;0;ON;;;;;N;;;;;
-4DD4;HEXAGRAM FOR BITING THROUGH;So;0;ON;;;;;N;;;;;
-4DD5;HEXAGRAM FOR GRACE;So;0;ON;;;;;N;;;;;
-4DD6;HEXAGRAM FOR SPLITTING APART;So;0;ON;;;;;N;;;;;
-4DD7;HEXAGRAM FOR RETURN;So;0;ON;;;;;N;;;;;
-4DD8;HEXAGRAM FOR INNOCENCE;So;0;ON;;;;;N;;;;;
-4DD9;HEXAGRAM FOR GREAT TAMING;So;0;ON;;;;;N;;;;;
-4DDA;HEXAGRAM FOR MOUTH CORNERS;So;0;ON;;;;;N;;;;;
-4DDB;HEXAGRAM FOR GREAT PREPONDERANCE;So;0;ON;;;;;N;;;;;
-4DDC;HEXAGRAM FOR THE ABYSMAL WATER;So;0;ON;;;;;N;;;;;
-4DDD;HEXAGRAM FOR THE CLINGING FIRE;So;0;ON;;;;;N;;;;;
-4DDE;HEXAGRAM FOR INFLUENCE;So;0;ON;;;;;N;;;;;
-4DDF;HEXAGRAM FOR DURATION;So;0;ON;;;;;N;;;;;
-4DE0;HEXAGRAM FOR RETREAT;So;0;ON;;;;;N;;;;;
-4DE1;HEXAGRAM FOR GREAT POWER;So;0;ON;;;;;N;;;;;
-4DE2;HEXAGRAM FOR PROGRESS;So;0;ON;;;;;N;;;;;
-4DE3;HEXAGRAM FOR DARKENING OF THE LIGHT;So;0;ON;;;;;N;;;;;
-4DE4;HEXAGRAM FOR THE FAMILY;So;0;ON;;;;;N;;;;;
-4DE5;HEXAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;;
-4DE6;HEXAGRAM FOR OBSTRUCTION;So;0;ON;;;;;N;;;;;
-4DE7;HEXAGRAM FOR DELIVERANCE;So;0;ON;;;;;N;;;;;
-4DE8;HEXAGRAM FOR DECREASE;So;0;ON;;;;;N;;;;;
-4DE9;HEXAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;;
-4DEA;HEXAGRAM FOR BREAKTHROUGH;So;0;ON;;;;;N;;;;;
-4DEB;HEXAGRAM FOR COMING TO MEET;So;0;ON;;;;;N;;;;;
-4DEC;HEXAGRAM FOR GATHERING TOGETHER;So;0;ON;;;;;N;;;;;
-4DED;HEXAGRAM FOR PUSHING UPWARD;So;0;ON;;;;;N;;;;;
-4DEE;HEXAGRAM FOR OPPRESSION;So;0;ON;;;;;N;;;;;
-4DEF;HEXAGRAM FOR THE WELL;So;0;ON;;;;;N;;;;;
-4DF0;HEXAGRAM FOR REVOLUTION;So;0;ON;;;;;N;;;;;
-4DF1;HEXAGRAM FOR THE CAULDRON;So;0;ON;;;;;N;;;;;
-4DF2;HEXAGRAM FOR THE AROUSING THUNDER;So;0;ON;;;;;N;;;;;
-4DF3;HEXAGRAM FOR THE KEEPING STILL MOUNTAIN;So;0;ON;;;;;N;;;;;
-4DF4;HEXAGRAM FOR DEVELOPMENT;So;0;ON;;;;;N;;;;;
-4DF5;HEXAGRAM FOR THE MARRYING MAIDEN;So;0;ON;;;;;N;;;;;
-4DF6;HEXAGRAM FOR ABUNDANCE;So;0;ON;;;;;N;;;;;
-4DF7;HEXAGRAM FOR THE WANDERER;So;0;ON;;;;;N;;;;;
-4DF8;HEXAGRAM FOR THE GENTLE WIND;So;0;ON;;;;;N;;;;;
-4DF9;HEXAGRAM FOR THE JOYOUS LAKE;So;0;ON;;;;;N;;;;;
-4DFA;HEXAGRAM FOR DISPERSION;So;0;ON;;;;;N;;;;;
-4DFB;HEXAGRAM FOR LIMITATION;So;0;ON;;;;;N;;;;;
-4DFC;HEXAGRAM FOR INNER TRUTH;So;0;ON;;;;;N;;;;;
-4DFD;HEXAGRAM FOR SMALL PREPONDERANCE;So;0;ON;;;;;N;;;;;
-4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;;
-4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;;
-4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;;
-9FCC;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
-A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;;
-A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;;
-A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;;
-A003;YI SYLLABLE IP;Lo;0;L;;;;;N;;;;;
-A004;YI SYLLABLE IET;Lo;0;L;;;;;N;;;;;
-A005;YI SYLLABLE IEX;Lo;0;L;;;;;N;;;;;
-A006;YI SYLLABLE IE;Lo;0;L;;;;;N;;;;;
-A007;YI SYLLABLE IEP;Lo;0;L;;;;;N;;;;;
-A008;YI SYLLABLE AT;Lo;0;L;;;;;N;;;;;
-A009;YI SYLLABLE AX;Lo;0;L;;;;;N;;;;;
-A00A;YI SYLLABLE A;Lo;0;L;;;;;N;;;;;
-A00B;YI SYLLABLE AP;Lo;0;L;;;;;N;;;;;
-A00C;YI SYLLABLE UOX;Lo;0;L;;;;;N;;;;;
-A00D;YI SYLLABLE UO;Lo;0;L;;;;;N;;;;;
-A00E;YI SYLLABLE UOP;Lo;0;L;;;;;N;;;;;
-A00F;YI SYLLABLE OT;Lo;0;L;;;;;N;;;;;
-A010;YI SYLLABLE OX;Lo;0;L;;;;;N;;;;;
-A011;YI SYLLABLE O;Lo;0;L;;;;;N;;;;;
-A012;YI SYLLABLE OP;Lo;0;L;;;;;N;;;;;
-A013;YI SYLLABLE EX;Lo;0;L;;;;;N;;;;;
-A014;YI SYLLABLE E;Lo;0;L;;;;;N;;;;;
-A015;YI SYLLABLE WU;Lm;0;L;;;;;N;;;;;
-A016;YI SYLLABLE BIT;Lo;0;L;;;;;N;;;;;
-A017;YI SYLLABLE BIX;Lo;0;L;;;;;N;;;;;
-A018;YI SYLLABLE BI;Lo;0;L;;;;;N;;;;;
-A019;YI SYLLABLE BIP;Lo;0;L;;;;;N;;;;;
-A01A;YI SYLLABLE BIET;Lo;0;L;;;;;N;;;;;
-A01B;YI SYLLABLE BIEX;Lo;0;L;;;;;N;;;;;
-A01C;YI SYLLABLE BIE;Lo;0;L;;;;;N;;;;;
-A01D;YI SYLLABLE BIEP;Lo;0;L;;;;;N;;;;;
-A01E;YI SYLLABLE BAT;Lo;0;L;;;;;N;;;;;
-A01F;YI SYLLABLE BAX;Lo;0;L;;;;;N;;;;;
-A020;YI SYLLABLE BA;Lo;0;L;;;;;N;;;;;
-A021;YI SYLLABLE BAP;Lo;0;L;;;;;N;;;;;
-A022;YI SYLLABLE BUOX;Lo;0;L;;;;;N;;;;;
-A023;YI SYLLABLE BUO;Lo;0;L;;;;;N;;;;;
-A024;YI SYLLABLE BUOP;Lo;0;L;;;;;N;;;;;
-A025;YI SYLLABLE BOT;Lo;0;L;;;;;N;;;;;
-A026;YI SYLLABLE BOX;Lo;0;L;;;;;N;;;;;
-A027;YI SYLLABLE BO;Lo;0;L;;;;;N;;;;;
-A028;YI SYLLABLE BOP;Lo;0;L;;;;;N;;;;;
-A029;YI SYLLABLE BEX;Lo;0;L;;;;;N;;;;;
-A02A;YI SYLLABLE BE;Lo;0;L;;;;;N;;;;;
-A02B;YI SYLLABLE BEP;Lo;0;L;;;;;N;;;;;
-A02C;YI SYLLABLE BUT;Lo;0;L;;;;;N;;;;;
-A02D;YI SYLLABLE BUX;Lo;0;L;;;;;N;;;;;
-A02E;YI SYLLABLE BU;Lo;0;L;;;;;N;;;;;
-A02F;YI SYLLABLE BUP;Lo;0;L;;;;;N;;;;;
-A030;YI SYLLABLE BURX;Lo;0;L;;;;;N;;;;;
-A031;YI SYLLABLE BUR;Lo;0;L;;;;;N;;;;;
-A032;YI SYLLABLE BYT;Lo;0;L;;;;;N;;;;;
-A033;YI SYLLABLE BYX;Lo;0;L;;;;;N;;;;;
-A034;YI SYLLABLE BY;Lo;0;L;;;;;N;;;;;
-A035;YI SYLLABLE BYP;Lo;0;L;;;;;N;;;;;
-A036;YI SYLLABLE BYRX;Lo;0;L;;;;;N;;;;;
-A037;YI SYLLABLE BYR;Lo;0;L;;;;;N;;;;;
-A038;YI SYLLABLE PIT;Lo;0;L;;;;;N;;;;;
-A039;YI SYLLABLE PIX;Lo;0;L;;;;;N;;;;;
-A03A;YI SYLLABLE PI;Lo;0;L;;;;;N;;;;;
-A03B;YI SYLLABLE PIP;Lo;0;L;;;;;N;;;;;
-A03C;YI SYLLABLE PIEX;Lo;0;L;;;;;N;;;;;
-A03D;YI SYLLABLE PIE;Lo;0;L;;;;;N;;;;;
-A03E;YI SYLLABLE PIEP;Lo;0;L;;;;;N;;;;;
-A03F;YI SYLLABLE PAT;Lo;0;L;;;;;N;;;;;
-A040;YI SYLLABLE PAX;Lo;0;L;;;;;N;;;;;
-A041;YI SYLLABLE PA;Lo;0;L;;;;;N;;;;;
-A042;YI SYLLABLE PAP;Lo;0;L;;;;;N;;;;;
-A043;YI SYLLABLE PUOX;Lo;0;L;;;;;N;;;;;
-A044;YI SYLLABLE PUO;Lo;0;L;;;;;N;;;;;
-A045;YI SYLLABLE PUOP;Lo;0;L;;;;;N;;;;;
-A046;YI SYLLABLE POT;Lo;0;L;;;;;N;;;;;
-A047;YI SYLLABLE POX;Lo;0;L;;;;;N;;;;;
-A048;YI SYLLABLE PO;Lo;0;L;;;;;N;;;;;
-A049;YI SYLLABLE POP;Lo;0;L;;;;;N;;;;;
-A04A;YI SYLLABLE PUT;Lo;0;L;;;;;N;;;;;
-A04B;YI SYLLABLE PUX;Lo;0;L;;;;;N;;;;;
-A04C;YI SYLLABLE PU;Lo;0;L;;;;;N;;;;;
-A04D;YI SYLLABLE PUP;Lo;0;L;;;;;N;;;;;
-A04E;YI SYLLABLE PURX;Lo;0;L;;;;;N;;;;;
-A04F;YI SYLLABLE PUR;Lo;0;L;;;;;N;;;;;
-A050;YI SYLLABLE PYT;Lo;0;L;;;;;N;;;;;
-A051;YI SYLLABLE PYX;Lo;0;L;;;;;N;;;;;
-A052;YI SYLLABLE PY;Lo;0;L;;;;;N;;;;;
-A053;YI SYLLABLE PYP;Lo;0;L;;;;;N;;;;;
-A054;YI SYLLABLE PYRX;Lo;0;L;;;;;N;;;;;
-A055;YI SYLLABLE PYR;Lo;0;L;;;;;N;;;;;
-A056;YI SYLLABLE BBIT;Lo;0;L;;;;;N;;;;;
-A057;YI SYLLABLE BBIX;Lo;0;L;;;;;N;;;;;
-A058;YI SYLLABLE BBI;Lo;0;L;;;;;N;;;;;
-A059;YI SYLLABLE BBIP;Lo;0;L;;;;;N;;;;;
-A05A;YI SYLLABLE BBIET;Lo;0;L;;;;;N;;;;;
-A05B;YI SYLLABLE BBIEX;Lo;0;L;;;;;N;;;;;
-A05C;YI SYLLABLE BBIE;Lo;0;L;;;;;N;;;;;
-A05D;YI SYLLABLE BBIEP;Lo;0;L;;;;;N;;;;;
-A05E;YI SYLLABLE BBAT;Lo;0;L;;;;;N;;;;;
-A05F;YI SYLLABLE BBAX;Lo;0;L;;;;;N;;;;;
-A060;YI SYLLABLE BBA;Lo;0;L;;;;;N;;;;;
-A061;YI SYLLABLE BBAP;Lo;0;L;;;;;N;;;;;
-A062;YI SYLLABLE BBUOX;Lo;0;L;;;;;N;;;;;
-A063;YI SYLLABLE BBUO;Lo;0;L;;;;;N;;;;;
-A064;YI SYLLABLE BBUOP;Lo;0;L;;;;;N;;;;;
-A065;YI SYLLABLE BBOT;Lo;0;L;;;;;N;;;;;
-A066;YI SYLLABLE BBOX;Lo;0;L;;;;;N;;;;;
-A067;YI SYLLABLE BBO;Lo;0;L;;;;;N;;;;;
-A068;YI SYLLABLE BBOP;Lo;0;L;;;;;N;;;;;
-A069;YI SYLLABLE BBEX;Lo;0;L;;;;;N;;;;;
-A06A;YI SYLLABLE BBE;Lo;0;L;;;;;N;;;;;
-A06B;YI SYLLABLE BBEP;Lo;0;L;;;;;N;;;;;
-A06C;YI SYLLABLE BBUT;Lo;0;L;;;;;N;;;;;
-A06D;YI SYLLABLE BBUX;Lo;0;L;;;;;N;;;;;
-A06E;YI SYLLABLE BBU;Lo;0;L;;;;;N;;;;;
-A06F;YI SYLLABLE BBUP;Lo;0;L;;;;;N;;;;;
-A070;YI SYLLABLE BBURX;Lo;0;L;;;;;N;;;;;
-A071;YI SYLLABLE BBUR;Lo;0;L;;;;;N;;;;;
-A072;YI SYLLABLE BBYT;Lo;0;L;;;;;N;;;;;
-A073;YI SYLLABLE BBYX;Lo;0;L;;;;;N;;;;;
-A074;YI SYLLABLE BBY;Lo;0;L;;;;;N;;;;;
-A075;YI SYLLABLE BBYP;Lo;0;L;;;;;N;;;;;
-A076;YI SYLLABLE NBIT;Lo;0;L;;;;;N;;;;;
-A077;YI SYLLABLE NBIX;Lo;0;L;;;;;N;;;;;
-A078;YI SYLLABLE NBI;Lo;0;L;;;;;N;;;;;
-A079;YI SYLLABLE NBIP;Lo;0;L;;;;;N;;;;;
-A07A;YI SYLLABLE NBIEX;Lo;0;L;;;;;N;;;;;
-A07B;YI SYLLABLE NBIE;Lo;0;L;;;;;N;;;;;
-A07C;YI SYLLABLE NBIEP;Lo;0;L;;;;;N;;;;;
-A07D;YI SYLLABLE NBAT;Lo;0;L;;;;;N;;;;;
-A07E;YI SYLLABLE NBAX;Lo;0;L;;;;;N;;;;;
-A07F;YI SYLLABLE NBA;Lo;0;L;;;;;N;;;;;
-A080;YI SYLLABLE NBAP;Lo;0;L;;;;;N;;;;;
-A081;YI SYLLABLE NBOT;Lo;0;L;;;;;N;;;;;
-A082;YI SYLLABLE NBOX;Lo;0;L;;;;;N;;;;;
-A083;YI SYLLABLE NBO;Lo;0;L;;;;;N;;;;;
-A084;YI SYLLABLE NBOP;Lo;0;L;;;;;N;;;;;
-A085;YI SYLLABLE NBUT;Lo;0;L;;;;;N;;;;;
-A086;YI SYLLABLE NBUX;Lo;0;L;;;;;N;;;;;
-A087;YI SYLLABLE NBU;Lo;0;L;;;;;N;;;;;
-A088;YI SYLLABLE NBUP;Lo;0;L;;;;;N;;;;;
-A089;YI SYLLABLE NBURX;Lo;0;L;;;;;N;;;;;
-A08A;YI SYLLABLE NBUR;Lo;0;L;;;;;N;;;;;
-A08B;YI SYLLABLE NBYT;Lo;0;L;;;;;N;;;;;
-A08C;YI SYLLABLE NBYX;Lo;0;L;;;;;N;;;;;
-A08D;YI SYLLABLE NBY;Lo;0;L;;;;;N;;;;;
-A08E;YI SYLLABLE NBYP;Lo;0;L;;;;;N;;;;;
-A08F;YI SYLLABLE NBYRX;Lo;0;L;;;;;N;;;;;
-A090;YI SYLLABLE NBYR;Lo;0;L;;;;;N;;;;;
-A091;YI SYLLABLE HMIT;Lo;0;L;;;;;N;;;;;
-A092;YI SYLLABLE HMIX;Lo;0;L;;;;;N;;;;;
-A093;YI SYLLABLE HMI;Lo;0;L;;;;;N;;;;;
-A094;YI SYLLABLE HMIP;Lo;0;L;;;;;N;;;;;
-A095;YI SYLLABLE HMIEX;Lo;0;L;;;;;N;;;;;
-A096;YI SYLLABLE HMIE;Lo;0;L;;;;;N;;;;;
-A097;YI SYLLABLE HMIEP;Lo;0;L;;;;;N;;;;;
-A098;YI SYLLABLE HMAT;Lo;0;L;;;;;N;;;;;
-A099;YI SYLLABLE HMAX;Lo;0;L;;;;;N;;;;;
-A09A;YI SYLLABLE HMA;Lo;0;L;;;;;N;;;;;
-A09B;YI SYLLABLE HMAP;Lo;0;L;;;;;N;;;;;
-A09C;YI SYLLABLE HMUOX;Lo;0;L;;;;;N;;;;;
-A09D;YI SYLLABLE HMUO;Lo;0;L;;;;;N;;;;;
-A09E;YI SYLLABLE HMUOP;Lo;0;L;;;;;N;;;;;
-A09F;YI SYLLABLE HMOT;Lo;0;L;;;;;N;;;;;
-A0A0;YI SYLLABLE HMOX;Lo;0;L;;;;;N;;;;;
-A0A1;YI SYLLABLE HMO;Lo;0;L;;;;;N;;;;;
-A0A2;YI SYLLABLE HMOP;Lo;0;L;;;;;N;;;;;
-A0A3;YI SYLLABLE HMUT;Lo;0;L;;;;;N;;;;;
-A0A4;YI SYLLABLE HMUX;Lo;0;L;;;;;N;;;;;
-A0A5;YI SYLLABLE HMU;Lo;0;L;;;;;N;;;;;
-A0A6;YI SYLLABLE HMUP;Lo;0;L;;;;;N;;;;;
-A0A7;YI SYLLABLE HMURX;Lo;0;L;;;;;N;;;;;
-A0A8;YI SYLLABLE HMUR;Lo;0;L;;;;;N;;;;;
-A0A9;YI SYLLABLE HMYX;Lo;0;L;;;;;N;;;;;
-A0AA;YI SYLLABLE HMY;Lo;0;L;;;;;N;;;;;
-A0AB;YI SYLLABLE HMYP;Lo;0;L;;;;;N;;;;;
-A0AC;YI SYLLABLE HMYRX;Lo;0;L;;;;;N;;;;;
-A0AD;YI SYLLABLE HMYR;Lo;0;L;;;;;N;;;;;
-A0AE;YI SYLLABLE MIT;Lo;0;L;;;;;N;;;;;
-A0AF;YI SYLLABLE MIX;Lo;0;L;;;;;N;;;;;
-A0B0;YI SYLLABLE MI;Lo;0;L;;;;;N;;;;;
-A0B1;YI SYLLABLE MIP;Lo;0;L;;;;;N;;;;;
-A0B2;YI SYLLABLE MIEX;Lo;0;L;;;;;N;;;;;
-A0B3;YI SYLLABLE MIE;Lo;0;L;;;;;N;;;;;
-A0B4;YI SYLLABLE MIEP;Lo;0;L;;;;;N;;;;;
-A0B5;YI SYLLABLE MAT;Lo;0;L;;;;;N;;;;;
-A0B6;YI SYLLABLE MAX;Lo;0;L;;;;;N;;;;;
-A0B7;YI SYLLABLE MA;Lo;0;L;;;;;N;;;;;
-A0B8;YI SYLLABLE MAP;Lo;0;L;;;;;N;;;;;
-A0B9;YI SYLLABLE MUOT;Lo;0;L;;;;;N;;;;;
-A0BA;YI SYLLABLE MUOX;Lo;0;L;;;;;N;;;;;
-A0BB;YI SYLLABLE MUO;Lo;0;L;;;;;N;;;;;
-A0BC;YI SYLLABLE MUOP;Lo;0;L;;;;;N;;;;;
-A0BD;YI SYLLABLE MOT;Lo;0;L;;;;;N;;;;;
-A0BE;YI SYLLABLE MOX;Lo;0;L;;;;;N;;;;;
-A0BF;YI SYLLABLE MO;Lo;0;L;;;;;N;;;;;
-A0C0;YI SYLLABLE MOP;Lo;0;L;;;;;N;;;;;
-A0C1;YI SYLLABLE MEX;Lo;0;L;;;;;N;;;;;
-A0C2;YI SYLLABLE ME;Lo;0;L;;;;;N;;;;;
-A0C3;YI SYLLABLE MUT;Lo;0;L;;;;;N;;;;;
-A0C4;YI SYLLABLE MUX;Lo;0;L;;;;;N;;;;;
-A0C5;YI SYLLABLE MU;Lo;0;L;;;;;N;;;;;
-A0C6;YI SYLLABLE MUP;Lo;0;L;;;;;N;;;;;
-A0C7;YI SYLLABLE MURX;Lo;0;L;;;;;N;;;;;
-A0C8;YI SYLLABLE MUR;Lo;0;L;;;;;N;;;;;
-A0C9;YI SYLLABLE MYT;Lo;0;L;;;;;N;;;;;
-A0CA;YI SYLLABLE MYX;Lo;0;L;;;;;N;;;;;
-A0CB;YI SYLLABLE MY;Lo;0;L;;;;;N;;;;;
-A0CC;YI SYLLABLE MYP;Lo;0;L;;;;;N;;;;;
-A0CD;YI SYLLABLE FIT;Lo;0;L;;;;;N;;;;;
-A0CE;YI SYLLABLE FIX;Lo;0;L;;;;;N;;;;;
-A0CF;YI SYLLABLE FI;Lo;0;L;;;;;N;;;;;
-A0D0;YI SYLLABLE FIP;Lo;0;L;;;;;N;;;;;
-A0D1;YI SYLLABLE FAT;Lo;0;L;;;;;N;;;;;
-A0D2;YI SYLLABLE FAX;Lo;0;L;;;;;N;;;;;
-A0D3;YI SYLLABLE FA;Lo;0;L;;;;;N;;;;;
-A0D4;YI SYLLABLE FAP;Lo;0;L;;;;;N;;;;;
-A0D5;YI SYLLABLE FOX;Lo;0;L;;;;;N;;;;;
-A0D6;YI SYLLABLE FO;Lo;0;L;;;;;N;;;;;
-A0D7;YI SYLLABLE FOP;Lo;0;L;;;;;N;;;;;
-A0D8;YI SYLLABLE FUT;Lo;0;L;;;;;N;;;;;
-A0D9;YI SYLLABLE FUX;Lo;0;L;;;;;N;;;;;
-A0DA;YI SYLLABLE FU;Lo;0;L;;;;;N;;;;;
-A0DB;YI SYLLABLE FUP;Lo;0;L;;;;;N;;;;;
-A0DC;YI SYLLABLE FURX;Lo;0;L;;;;;N;;;;;
-A0DD;YI SYLLABLE FUR;Lo;0;L;;;;;N;;;;;
-A0DE;YI SYLLABLE FYT;Lo;0;L;;;;;N;;;;;
-A0DF;YI SYLLABLE FYX;Lo;0;L;;;;;N;;;;;
-A0E0;YI SYLLABLE FY;Lo;0;L;;;;;N;;;;;
-A0E1;YI SYLLABLE FYP;Lo;0;L;;;;;N;;;;;
-A0E2;YI SYLLABLE VIT;Lo;0;L;;;;;N;;;;;
-A0E3;YI SYLLABLE VIX;Lo;0;L;;;;;N;;;;;
-A0E4;YI SYLLABLE VI;Lo;0;L;;;;;N;;;;;
-A0E5;YI SYLLABLE VIP;Lo;0;L;;;;;N;;;;;
-A0E6;YI SYLLABLE VIET;Lo;0;L;;;;;N;;;;;
-A0E7;YI SYLLABLE VIEX;Lo;0;L;;;;;N;;;;;
-A0E8;YI SYLLABLE VIE;Lo;0;L;;;;;N;;;;;
-A0E9;YI SYLLABLE VIEP;Lo;0;L;;;;;N;;;;;
-A0EA;YI SYLLABLE VAT;Lo;0;L;;;;;N;;;;;
-A0EB;YI SYLLABLE VAX;Lo;0;L;;;;;N;;;;;
-A0EC;YI SYLLABLE VA;Lo;0;L;;;;;N;;;;;
-A0ED;YI SYLLABLE VAP;Lo;0;L;;;;;N;;;;;
-A0EE;YI SYLLABLE VOT;Lo;0;L;;;;;N;;;;;
-A0EF;YI SYLLABLE VOX;Lo;0;L;;;;;N;;;;;
-A0F0;YI SYLLABLE VO;Lo;0;L;;;;;N;;;;;
-A0F1;YI SYLLABLE VOP;Lo;0;L;;;;;N;;;;;
-A0F2;YI SYLLABLE VEX;Lo;0;L;;;;;N;;;;;
-A0F3;YI SYLLABLE VEP;Lo;0;L;;;;;N;;;;;
-A0F4;YI SYLLABLE VUT;Lo;0;L;;;;;N;;;;;
-A0F5;YI SYLLABLE VUX;Lo;0;L;;;;;N;;;;;
-A0F6;YI SYLLABLE VU;Lo;0;L;;;;;N;;;;;
-A0F7;YI SYLLABLE VUP;Lo;0;L;;;;;N;;;;;
-A0F8;YI SYLLABLE VURX;Lo;0;L;;;;;N;;;;;
-A0F9;YI SYLLABLE VUR;Lo;0;L;;;;;N;;;;;
-A0FA;YI SYLLABLE VYT;Lo;0;L;;;;;N;;;;;
-A0FB;YI SYLLABLE VYX;Lo;0;L;;;;;N;;;;;
-A0FC;YI SYLLABLE VY;Lo;0;L;;;;;N;;;;;
-A0FD;YI SYLLABLE VYP;Lo;0;L;;;;;N;;;;;
-A0FE;YI SYLLABLE VYRX;Lo;0;L;;;;;N;;;;;
-A0FF;YI SYLLABLE VYR;Lo;0;L;;;;;N;;;;;
-A100;YI SYLLABLE DIT;Lo;0;L;;;;;N;;;;;
-A101;YI SYLLABLE DIX;Lo;0;L;;;;;N;;;;;
-A102;YI SYLLABLE DI;Lo;0;L;;;;;N;;;;;
-A103;YI SYLLABLE DIP;Lo;0;L;;;;;N;;;;;
-A104;YI SYLLABLE DIEX;Lo;0;L;;;;;N;;;;;
-A105;YI SYLLABLE DIE;Lo;0;L;;;;;N;;;;;
-A106;YI SYLLABLE DIEP;Lo;0;L;;;;;N;;;;;
-A107;YI SYLLABLE DAT;Lo;0;L;;;;;N;;;;;
-A108;YI SYLLABLE DAX;Lo;0;L;;;;;N;;;;;
-A109;YI SYLLABLE DA;Lo;0;L;;;;;N;;;;;
-A10A;YI SYLLABLE DAP;Lo;0;L;;;;;N;;;;;
-A10B;YI SYLLABLE DUOX;Lo;0;L;;;;;N;;;;;
-A10C;YI SYLLABLE DUO;Lo;0;L;;;;;N;;;;;
-A10D;YI SYLLABLE DOT;Lo;0;L;;;;;N;;;;;
-A10E;YI SYLLABLE DOX;Lo;0;L;;;;;N;;;;;
-A10F;YI SYLLABLE DO;Lo;0;L;;;;;N;;;;;
-A110;YI SYLLABLE DOP;Lo;0;L;;;;;N;;;;;
-A111;YI SYLLABLE DEX;Lo;0;L;;;;;N;;;;;
-A112;YI SYLLABLE DE;Lo;0;L;;;;;N;;;;;
-A113;YI SYLLABLE DEP;Lo;0;L;;;;;N;;;;;
-A114;YI SYLLABLE DUT;Lo;0;L;;;;;N;;;;;
-A115;YI SYLLABLE DUX;Lo;0;L;;;;;N;;;;;
-A116;YI SYLLABLE DU;Lo;0;L;;;;;N;;;;;
-A117;YI SYLLABLE DUP;Lo;0;L;;;;;N;;;;;
-A118;YI SYLLABLE DURX;Lo;0;L;;;;;N;;;;;
-A119;YI SYLLABLE DUR;Lo;0;L;;;;;N;;;;;
-A11A;YI SYLLABLE TIT;Lo;0;L;;;;;N;;;;;
-A11B;YI SYLLABLE TIX;Lo;0;L;;;;;N;;;;;
-A11C;YI SYLLABLE TI;Lo;0;L;;;;;N;;;;;
-A11D;YI SYLLABLE TIP;Lo;0;L;;;;;N;;;;;
-A11E;YI SYLLABLE TIEX;Lo;0;L;;;;;N;;;;;
-A11F;YI SYLLABLE TIE;Lo;0;L;;;;;N;;;;;
-A120;YI SYLLABLE TIEP;Lo;0;L;;;;;N;;;;;
-A121;YI SYLLABLE TAT;Lo;0;L;;;;;N;;;;;
-A122;YI SYLLABLE TAX;Lo;0;L;;;;;N;;;;;
-A123;YI SYLLABLE TA;Lo;0;L;;;;;N;;;;;
-A124;YI SYLLABLE TAP;Lo;0;L;;;;;N;;;;;
-A125;YI SYLLABLE TUOT;Lo;0;L;;;;;N;;;;;
-A126;YI SYLLABLE TUOX;Lo;0;L;;;;;N;;;;;
-A127;YI SYLLABLE TUO;Lo;0;L;;;;;N;;;;;
-A128;YI SYLLABLE TUOP;Lo;0;L;;;;;N;;;;;
-A129;YI SYLLABLE TOT;Lo;0;L;;;;;N;;;;;
-A12A;YI SYLLABLE TOX;Lo;0;L;;;;;N;;;;;
-A12B;YI SYLLABLE TO;Lo;0;L;;;;;N;;;;;
-A12C;YI SYLLABLE TOP;Lo;0;L;;;;;N;;;;;
-A12D;YI SYLLABLE TEX;Lo;0;L;;;;;N;;;;;
-A12E;YI SYLLABLE TE;Lo;0;L;;;;;N;;;;;
-A12F;YI SYLLABLE TEP;Lo;0;L;;;;;N;;;;;
-A130;YI SYLLABLE TUT;Lo;0;L;;;;;N;;;;;
-A131;YI SYLLABLE TUX;Lo;0;L;;;;;N;;;;;
-A132;YI SYLLABLE TU;Lo;0;L;;;;;N;;;;;
-A133;YI SYLLABLE TUP;Lo;0;L;;;;;N;;;;;
-A134;YI SYLLABLE TURX;Lo;0;L;;;;;N;;;;;
-A135;YI SYLLABLE TUR;Lo;0;L;;;;;N;;;;;
-A136;YI SYLLABLE DDIT;Lo;0;L;;;;;N;;;;;
-A137;YI SYLLABLE DDIX;Lo;0;L;;;;;N;;;;;
-A138;YI SYLLABLE DDI;Lo;0;L;;;;;N;;;;;
-A139;YI SYLLABLE DDIP;Lo;0;L;;;;;N;;;;;
-A13A;YI SYLLABLE DDIEX;Lo;0;L;;;;;N;;;;;
-A13B;YI SYLLABLE DDIE;Lo;0;L;;;;;N;;;;;
-A13C;YI SYLLABLE DDIEP;Lo;0;L;;;;;N;;;;;
-A13D;YI SYLLABLE DDAT;Lo;0;L;;;;;N;;;;;
-A13E;YI SYLLABLE DDAX;Lo;0;L;;;;;N;;;;;
-A13F;YI SYLLABLE DDA;Lo;0;L;;;;;N;;;;;
-A140;YI SYLLABLE DDAP;Lo;0;L;;;;;N;;;;;
-A141;YI SYLLABLE DDUOX;Lo;0;L;;;;;N;;;;;
-A142;YI SYLLABLE DDUO;Lo;0;L;;;;;N;;;;;
-A143;YI SYLLABLE DDUOP;Lo;0;L;;;;;N;;;;;
-A144;YI SYLLABLE DDOT;Lo;0;L;;;;;N;;;;;
-A145;YI SYLLABLE DDOX;Lo;0;L;;;;;N;;;;;
-A146;YI SYLLABLE DDO;Lo;0;L;;;;;N;;;;;
-A147;YI SYLLABLE DDOP;Lo;0;L;;;;;N;;;;;
-A148;YI SYLLABLE DDEX;Lo;0;L;;;;;N;;;;;
-A149;YI SYLLABLE DDE;Lo;0;L;;;;;N;;;;;
-A14A;YI SYLLABLE DDEP;Lo;0;L;;;;;N;;;;;
-A14B;YI SYLLABLE DDUT;Lo;0;L;;;;;N;;;;;
-A14C;YI SYLLABLE DDUX;Lo;0;L;;;;;N;;;;;
-A14D;YI SYLLABLE DDU;Lo;0;L;;;;;N;;;;;
-A14E;YI SYLLABLE DDUP;Lo;0;L;;;;;N;;;;;
-A14F;YI SYLLABLE DDURX;Lo;0;L;;;;;N;;;;;
-A150;YI SYLLABLE DDUR;Lo;0;L;;;;;N;;;;;
-A151;YI SYLLABLE NDIT;Lo;0;L;;;;;N;;;;;
-A152;YI SYLLABLE NDIX;Lo;0;L;;;;;N;;;;;
-A153;YI SYLLABLE NDI;Lo;0;L;;;;;N;;;;;
-A154;YI SYLLABLE NDIP;Lo;0;L;;;;;N;;;;;
-A155;YI SYLLABLE NDIEX;Lo;0;L;;;;;N;;;;;
-A156;YI SYLLABLE NDIE;Lo;0;L;;;;;N;;;;;
-A157;YI SYLLABLE NDAT;Lo;0;L;;;;;N;;;;;
-A158;YI SYLLABLE NDAX;Lo;0;L;;;;;N;;;;;
-A159;YI SYLLABLE NDA;Lo;0;L;;;;;N;;;;;
-A15A;YI SYLLABLE NDAP;Lo;0;L;;;;;N;;;;;
-A15B;YI SYLLABLE NDOT;Lo;0;L;;;;;N;;;;;
-A15C;YI SYLLABLE NDOX;Lo;0;L;;;;;N;;;;;
-A15D;YI SYLLABLE NDO;Lo;0;L;;;;;N;;;;;
-A15E;YI SYLLABLE NDOP;Lo;0;L;;;;;N;;;;;
-A15F;YI SYLLABLE NDEX;Lo;0;L;;;;;N;;;;;
-A160;YI SYLLABLE NDE;Lo;0;L;;;;;N;;;;;
-A161;YI SYLLABLE NDEP;Lo;0;L;;;;;N;;;;;
-A162;YI SYLLABLE NDUT;Lo;0;L;;;;;N;;;;;
-A163;YI SYLLABLE NDUX;Lo;0;L;;;;;N;;;;;
-A164;YI SYLLABLE NDU;Lo;0;L;;;;;N;;;;;
-A165;YI SYLLABLE NDUP;Lo;0;L;;;;;N;;;;;
-A166;YI SYLLABLE NDURX;Lo;0;L;;;;;N;;;;;
-A167;YI SYLLABLE NDUR;Lo;0;L;;;;;N;;;;;
-A168;YI SYLLABLE HNIT;Lo;0;L;;;;;N;;;;;
-A169;YI SYLLABLE HNIX;Lo;0;L;;;;;N;;;;;
-A16A;YI SYLLABLE HNI;Lo;0;L;;;;;N;;;;;
-A16B;YI SYLLABLE HNIP;Lo;0;L;;;;;N;;;;;
-A16C;YI SYLLABLE HNIET;Lo;0;L;;;;;N;;;;;
-A16D;YI SYLLABLE HNIEX;Lo;0;L;;;;;N;;;;;
-A16E;YI SYLLABLE HNIE;Lo;0;L;;;;;N;;;;;
-A16F;YI SYLLABLE HNIEP;Lo;0;L;;;;;N;;;;;
-A170;YI SYLLABLE HNAT;Lo;0;L;;;;;N;;;;;
-A171;YI SYLLABLE HNAX;Lo;0;L;;;;;N;;;;;
-A172;YI SYLLABLE HNA;Lo;0;L;;;;;N;;;;;
-A173;YI SYLLABLE HNAP;Lo;0;L;;;;;N;;;;;
-A174;YI SYLLABLE HNUOX;Lo;0;L;;;;;N;;;;;
-A175;YI SYLLABLE HNUO;Lo;0;L;;;;;N;;;;;
-A176;YI SYLLABLE HNOT;Lo;0;L;;;;;N;;;;;
-A177;YI SYLLABLE HNOX;Lo;0;L;;;;;N;;;;;
-A178;YI SYLLABLE HNOP;Lo;0;L;;;;;N;;;;;
-A179;YI SYLLABLE HNEX;Lo;0;L;;;;;N;;;;;
-A17A;YI SYLLABLE HNE;Lo;0;L;;;;;N;;;;;
-A17B;YI SYLLABLE HNEP;Lo;0;L;;;;;N;;;;;
-A17C;YI SYLLABLE HNUT;Lo;0;L;;;;;N;;;;;
-A17D;YI SYLLABLE NIT;Lo;0;L;;;;;N;;;;;
-A17E;YI SYLLABLE NIX;Lo;0;L;;;;;N;;;;;
-A17F;YI SYLLABLE NI;Lo;0;L;;;;;N;;;;;
-A180;YI SYLLABLE NIP;Lo;0;L;;;;;N;;;;;
-A181;YI SYLLABLE NIEX;Lo;0;L;;;;;N;;;;;
-A182;YI SYLLABLE NIE;Lo;0;L;;;;;N;;;;;
-A183;YI SYLLABLE NIEP;Lo;0;L;;;;;N;;;;;
-A184;YI SYLLABLE NAX;Lo;0;L;;;;;N;;;;;
-A185;YI SYLLABLE NA;Lo;0;L;;;;;N;;;;;
-A186;YI SYLLABLE NAP;Lo;0;L;;;;;N;;;;;
-A187;YI SYLLABLE NUOX;Lo;0;L;;;;;N;;;;;
-A188;YI SYLLABLE NUO;Lo;0;L;;;;;N;;;;;
-A189;YI SYLLABLE NUOP;Lo;0;L;;;;;N;;;;;
-A18A;YI SYLLABLE NOT;Lo;0;L;;;;;N;;;;;
-A18B;YI SYLLABLE NOX;Lo;0;L;;;;;N;;;;;
-A18C;YI SYLLABLE NO;Lo;0;L;;;;;N;;;;;
-A18D;YI SYLLABLE NOP;Lo;0;L;;;;;N;;;;;
-A18E;YI SYLLABLE NEX;Lo;0;L;;;;;N;;;;;
-A18F;YI SYLLABLE NE;Lo;0;L;;;;;N;;;;;
-A190;YI SYLLABLE NEP;Lo;0;L;;;;;N;;;;;
-A191;YI SYLLABLE NUT;Lo;0;L;;;;;N;;;;;
-A192;YI SYLLABLE NUX;Lo;0;L;;;;;N;;;;;
-A193;YI SYLLABLE NU;Lo;0;L;;;;;N;;;;;
-A194;YI SYLLABLE NUP;Lo;0;L;;;;;N;;;;;
-A195;YI SYLLABLE NURX;Lo;0;L;;;;;N;;;;;
-A196;YI SYLLABLE NUR;Lo;0;L;;;;;N;;;;;
-A197;YI SYLLABLE HLIT;Lo;0;L;;;;;N;;;;;
-A198;YI SYLLABLE HLIX;Lo;0;L;;;;;N;;;;;
-A199;YI SYLLABLE HLI;Lo;0;L;;;;;N;;;;;
-A19A;YI SYLLABLE HLIP;Lo;0;L;;;;;N;;;;;
-A19B;YI SYLLABLE HLIEX;Lo;0;L;;;;;N;;;;;
-A19C;YI SYLLABLE HLIE;Lo;0;L;;;;;N;;;;;
-A19D;YI SYLLABLE HLIEP;Lo;0;L;;;;;N;;;;;
-A19E;YI SYLLABLE HLAT;Lo;0;L;;;;;N;;;;;
-A19F;YI SYLLABLE HLAX;Lo;0;L;;;;;N;;;;;
-A1A0;YI SYLLABLE HLA;Lo;0;L;;;;;N;;;;;
-A1A1;YI SYLLABLE HLAP;Lo;0;L;;;;;N;;;;;
-A1A2;YI SYLLABLE HLUOX;Lo;0;L;;;;;N;;;;;
-A1A3;YI SYLLABLE HLUO;Lo;0;L;;;;;N;;;;;
-A1A4;YI SYLLABLE HLUOP;Lo;0;L;;;;;N;;;;;
-A1A5;YI SYLLABLE HLOX;Lo;0;L;;;;;N;;;;;
-A1A6;YI SYLLABLE HLO;Lo;0;L;;;;;N;;;;;
-A1A7;YI SYLLABLE HLOP;Lo;0;L;;;;;N;;;;;
-A1A8;YI SYLLABLE HLEX;Lo;0;L;;;;;N;;;;;
-A1A9;YI SYLLABLE HLE;Lo;0;L;;;;;N;;;;;
-A1AA;YI SYLLABLE HLEP;Lo;0;L;;;;;N;;;;;
-A1AB;YI SYLLABLE HLUT;Lo;0;L;;;;;N;;;;;
-A1AC;YI SYLLABLE HLUX;Lo;0;L;;;;;N;;;;;
-A1AD;YI SYLLABLE HLU;Lo;0;L;;;;;N;;;;;
-A1AE;YI SYLLABLE HLUP;Lo;0;L;;;;;N;;;;;
-A1AF;YI SYLLABLE HLURX;Lo;0;L;;;;;N;;;;;
-A1B0;YI SYLLABLE HLUR;Lo;0;L;;;;;N;;;;;
-A1B1;YI SYLLABLE HLYT;Lo;0;L;;;;;N;;;;;
-A1B2;YI SYLLABLE HLYX;Lo;0;L;;;;;N;;;;;
-A1B3;YI SYLLABLE HLY;Lo;0;L;;;;;N;;;;;
-A1B4;YI SYLLABLE HLYP;Lo;0;L;;;;;N;;;;;
-A1B5;YI SYLLABLE HLYRX;Lo;0;L;;;;;N;;;;;
-A1B6;YI SYLLABLE HLYR;Lo;0;L;;;;;N;;;;;
-A1B7;YI SYLLABLE LIT;Lo;0;L;;;;;N;;;;;
-A1B8;YI SYLLABLE LIX;Lo;0;L;;;;;N;;;;;
-A1B9;YI SYLLABLE LI;Lo;0;L;;;;;N;;;;;
-A1BA;YI SYLLABLE LIP;Lo;0;L;;;;;N;;;;;
-A1BB;YI SYLLABLE LIET;Lo;0;L;;;;;N;;;;;
-A1BC;YI SYLLABLE LIEX;Lo;0;L;;;;;N;;;;;
-A1BD;YI SYLLABLE LIE;Lo;0;L;;;;;N;;;;;
-A1BE;YI SYLLABLE LIEP;Lo;0;L;;;;;N;;;;;
-A1BF;YI SYLLABLE LAT;Lo;0;L;;;;;N;;;;;
-A1C0;YI SYLLABLE LAX;Lo;0;L;;;;;N;;;;;
-A1C1;YI SYLLABLE LA;Lo;0;L;;;;;N;;;;;
-A1C2;YI SYLLABLE LAP;Lo;0;L;;;;;N;;;;;
-A1C3;YI SYLLABLE LUOT;Lo;0;L;;;;;N;;;;;
-A1C4;YI SYLLABLE LUOX;Lo;0;L;;;;;N;;;;;
-A1C5;YI SYLLABLE LUO;Lo;0;L;;;;;N;;;;;
-A1C6;YI SYLLABLE LUOP;Lo;0;L;;;;;N;;;;;
-A1C7;YI SYLLABLE LOT;Lo;0;L;;;;;N;;;;;
-A1C8;YI SYLLABLE LOX;Lo;0;L;;;;;N;;;;;
-A1C9;YI SYLLABLE LO;Lo;0;L;;;;;N;;;;;
-A1CA;YI SYLLABLE LOP;Lo;0;L;;;;;N;;;;;
-A1CB;YI SYLLABLE LEX;Lo;0;L;;;;;N;;;;;
-A1CC;YI SYLLABLE LE;Lo;0;L;;;;;N;;;;;
-A1CD;YI SYLLABLE LEP;Lo;0;L;;;;;N;;;;;
-A1CE;YI SYLLABLE LUT;Lo;0;L;;;;;N;;;;;
-A1CF;YI SYLLABLE LUX;Lo;0;L;;;;;N;;;;;
-A1D0;YI SYLLABLE LU;Lo;0;L;;;;;N;;;;;
-A1D1;YI SYLLABLE LUP;Lo;0;L;;;;;N;;;;;
-A1D2;YI SYLLABLE LURX;Lo;0;L;;;;;N;;;;;
-A1D3;YI SYLLABLE LUR;Lo;0;L;;;;;N;;;;;
-A1D4;YI SYLLABLE LYT;Lo;0;L;;;;;N;;;;;
-A1D5;YI SYLLABLE LYX;Lo;0;L;;;;;N;;;;;
-A1D6;YI SYLLABLE LY;Lo;0;L;;;;;N;;;;;
-A1D7;YI SYLLABLE LYP;Lo;0;L;;;;;N;;;;;
-A1D8;YI SYLLABLE LYRX;Lo;0;L;;;;;N;;;;;
-A1D9;YI SYLLABLE LYR;Lo;0;L;;;;;N;;;;;
-A1DA;YI SYLLABLE GIT;Lo;0;L;;;;;N;;;;;
-A1DB;YI SYLLABLE GIX;Lo;0;L;;;;;N;;;;;
-A1DC;YI SYLLABLE GI;Lo;0;L;;;;;N;;;;;
-A1DD;YI SYLLABLE GIP;Lo;0;L;;;;;N;;;;;
-A1DE;YI SYLLABLE GIET;Lo;0;L;;;;;N;;;;;
-A1DF;YI SYLLABLE GIEX;Lo;0;L;;;;;N;;;;;
-A1E0;YI SYLLABLE GIE;Lo;0;L;;;;;N;;;;;
-A1E1;YI SYLLABLE GIEP;Lo;0;L;;;;;N;;;;;
-A1E2;YI SYLLABLE GAT;Lo;0;L;;;;;N;;;;;
-A1E3;YI SYLLABLE GAX;Lo;0;L;;;;;N;;;;;
-A1E4;YI SYLLABLE GA;Lo;0;L;;;;;N;;;;;
-A1E5;YI SYLLABLE GAP;Lo;0;L;;;;;N;;;;;
-A1E6;YI SYLLABLE GUOT;Lo;0;L;;;;;N;;;;;
-A1E7;YI SYLLABLE GUOX;Lo;0;L;;;;;N;;;;;
-A1E8;YI SYLLABLE GUO;Lo;0;L;;;;;N;;;;;
-A1E9;YI SYLLABLE GUOP;Lo;0;L;;;;;N;;;;;
-A1EA;YI SYLLABLE GOT;Lo;0;L;;;;;N;;;;;
-A1EB;YI SYLLABLE GOX;Lo;0;L;;;;;N;;;;;
-A1EC;YI SYLLABLE GO;Lo;0;L;;;;;N;;;;;
-A1ED;YI SYLLABLE GOP;Lo;0;L;;;;;N;;;;;
-A1EE;YI SYLLABLE GET;Lo;0;L;;;;;N;;;;;
-A1EF;YI SYLLABLE GEX;Lo;0;L;;;;;N;;;;;
-A1F0;YI SYLLABLE GE;Lo;0;L;;;;;N;;;;;
-A1F1;YI SYLLABLE GEP;Lo;0;L;;;;;N;;;;;
-A1F2;YI SYLLABLE GUT;Lo;0;L;;;;;N;;;;;
-A1F3;YI SYLLABLE GUX;Lo;0;L;;;;;N;;;;;
-A1F4;YI SYLLABLE GU;Lo;0;L;;;;;N;;;;;
-A1F5;YI SYLLABLE GUP;Lo;0;L;;;;;N;;;;;
-A1F6;YI SYLLABLE GURX;Lo;0;L;;;;;N;;;;;
-A1F7;YI SYLLABLE GUR;Lo;0;L;;;;;N;;;;;
-A1F8;YI SYLLABLE KIT;Lo;0;L;;;;;N;;;;;
-A1F9;YI SYLLABLE KIX;Lo;0;L;;;;;N;;;;;
-A1FA;YI SYLLABLE KI;Lo;0;L;;;;;N;;;;;
-A1FB;YI SYLLABLE KIP;Lo;0;L;;;;;N;;;;;
-A1FC;YI SYLLABLE KIEX;Lo;0;L;;;;;N;;;;;
-A1FD;YI SYLLABLE KIE;Lo;0;L;;;;;N;;;;;
-A1FE;YI SYLLABLE KIEP;Lo;0;L;;;;;N;;;;;
-A1FF;YI SYLLABLE KAT;Lo;0;L;;;;;N;;;;;
-A200;YI SYLLABLE KAX;Lo;0;L;;;;;N;;;;;
-A201;YI SYLLABLE KA;Lo;0;L;;;;;N;;;;;
-A202;YI SYLLABLE KAP;Lo;0;L;;;;;N;;;;;
-A203;YI SYLLABLE KUOX;Lo;0;L;;;;;N;;;;;
-A204;YI SYLLABLE KUO;Lo;0;L;;;;;N;;;;;
-A205;YI SYLLABLE KUOP;Lo;0;L;;;;;N;;;;;
-A206;YI SYLLABLE KOT;Lo;0;L;;;;;N;;;;;
-A207;YI SYLLABLE KOX;Lo;0;L;;;;;N;;;;;
-A208;YI SYLLABLE KO;Lo;0;L;;;;;N;;;;;
-A209;YI SYLLABLE KOP;Lo;0;L;;;;;N;;;;;
-A20A;YI SYLLABLE KET;Lo;0;L;;;;;N;;;;;
-A20B;YI SYLLABLE KEX;Lo;0;L;;;;;N;;;;;
-A20C;YI SYLLABLE KE;Lo;0;L;;;;;N;;;;;
-A20D;YI SYLLABLE KEP;Lo;0;L;;;;;N;;;;;
-A20E;YI SYLLABLE KUT;Lo;0;L;;;;;N;;;;;
-A20F;YI SYLLABLE KUX;Lo;0;L;;;;;N;;;;;
-A210;YI SYLLABLE KU;Lo;0;L;;;;;N;;;;;
-A211;YI SYLLABLE KUP;Lo;0;L;;;;;N;;;;;
-A212;YI SYLLABLE KURX;Lo;0;L;;;;;N;;;;;
-A213;YI SYLLABLE KUR;Lo;0;L;;;;;N;;;;;
-A214;YI SYLLABLE GGIT;Lo;0;L;;;;;N;;;;;
-A215;YI SYLLABLE GGIX;Lo;0;L;;;;;N;;;;;
-A216;YI SYLLABLE GGI;Lo;0;L;;;;;N;;;;;
-A217;YI SYLLABLE GGIEX;Lo;0;L;;;;;N;;;;;
-A218;YI SYLLABLE GGIE;Lo;0;L;;;;;N;;;;;
-A219;YI SYLLABLE GGIEP;Lo;0;L;;;;;N;;;;;
-A21A;YI SYLLABLE GGAT;Lo;0;L;;;;;N;;;;;
-A21B;YI SYLLABLE GGAX;Lo;0;L;;;;;N;;;;;
-A21C;YI SYLLABLE GGA;Lo;0;L;;;;;N;;;;;
-A21D;YI SYLLABLE GGAP;Lo;0;L;;;;;N;;;;;
-A21E;YI SYLLABLE GGUOT;Lo;0;L;;;;;N;;;;;
-A21F;YI SYLLABLE GGUOX;Lo;0;L;;;;;N;;;;;
-A220;YI SYLLABLE GGUO;Lo;0;L;;;;;N;;;;;
-A221;YI SYLLABLE GGUOP;Lo;0;L;;;;;N;;;;;
-A222;YI SYLLABLE GGOT;Lo;0;L;;;;;N;;;;;
-A223;YI SYLLABLE GGOX;Lo;0;L;;;;;N;;;;;
-A224;YI SYLLABLE GGO;Lo;0;L;;;;;N;;;;;
-A225;YI SYLLABLE GGOP;Lo;0;L;;;;;N;;;;;
-A226;YI SYLLABLE GGET;Lo;0;L;;;;;N;;;;;
-A227;YI SYLLABLE GGEX;Lo;0;L;;;;;N;;;;;
-A228;YI SYLLABLE GGE;Lo;0;L;;;;;N;;;;;
-A229;YI SYLLABLE GGEP;Lo;0;L;;;;;N;;;;;
-A22A;YI SYLLABLE GGUT;Lo;0;L;;;;;N;;;;;
-A22B;YI SYLLABLE GGUX;Lo;0;L;;;;;N;;;;;
-A22C;YI SYLLABLE GGU;Lo;0;L;;;;;N;;;;;
-A22D;YI SYLLABLE GGUP;Lo;0;L;;;;;N;;;;;
-A22E;YI SYLLABLE GGURX;Lo;0;L;;;;;N;;;;;
-A22F;YI SYLLABLE GGUR;Lo;0;L;;;;;N;;;;;
-A230;YI SYLLABLE MGIEX;Lo;0;L;;;;;N;;;;;
-A231;YI SYLLABLE MGIE;Lo;0;L;;;;;N;;;;;
-A232;YI SYLLABLE MGAT;Lo;0;L;;;;;N;;;;;
-A233;YI SYLLABLE MGAX;Lo;0;L;;;;;N;;;;;
-A234;YI SYLLABLE MGA;Lo;0;L;;;;;N;;;;;
-A235;YI SYLLABLE MGAP;Lo;0;L;;;;;N;;;;;
-A236;YI SYLLABLE MGUOX;Lo;0;L;;;;;N;;;;;
-A237;YI SYLLABLE MGUO;Lo;0;L;;;;;N;;;;;
-A238;YI SYLLABLE MGUOP;Lo;0;L;;;;;N;;;;;
-A239;YI SYLLABLE MGOT;Lo;0;L;;;;;N;;;;;
-A23A;YI SYLLABLE MGOX;Lo;0;L;;;;;N;;;;;
-A23B;YI SYLLABLE MGO;Lo;0;L;;;;;N;;;;;
-A23C;YI SYLLABLE MGOP;Lo;0;L;;;;;N;;;;;
-A23D;YI SYLLABLE MGEX;Lo;0;L;;;;;N;;;;;
-A23E;YI SYLLABLE MGE;Lo;0;L;;;;;N;;;;;
-A23F;YI SYLLABLE MGEP;Lo;0;L;;;;;N;;;;;
-A240;YI SYLLABLE MGUT;Lo;0;L;;;;;N;;;;;
-A241;YI SYLLABLE MGUX;Lo;0;L;;;;;N;;;;;
-A242;YI SYLLABLE MGU;Lo;0;L;;;;;N;;;;;
-A243;YI SYLLABLE MGUP;Lo;0;L;;;;;N;;;;;
-A244;YI SYLLABLE MGURX;Lo;0;L;;;;;N;;;;;
-A245;YI SYLLABLE MGUR;Lo;0;L;;;;;N;;;;;
-A246;YI SYLLABLE HXIT;Lo;0;L;;;;;N;;;;;
-A247;YI SYLLABLE HXIX;Lo;0;L;;;;;N;;;;;
-A248;YI SYLLABLE HXI;Lo;0;L;;;;;N;;;;;
-A249;YI SYLLABLE HXIP;Lo;0;L;;;;;N;;;;;
-A24A;YI SYLLABLE HXIET;Lo;0;L;;;;;N;;;;;
-A24B;YI SYLLABLE HXIEX;Lo;0;L;;;;;N;;;;;
-A24C;YI SYLLABLE HXIE;Lo;0;L;;;;;N;;;;;
-A24D;YI SYLLABLE HXIEP;Lo;0;L;;;;;N;;;;;
-A24E;YI SYLLABLE HXAT;Lo;0;L;;;;;N;;;;;
-A24F;YI SYLLABLE HXAX;Lo;0;L;;;;;N;;;;;
-A250;YI SYLLABLE HXA;Lo;0;L;;;;;N;;;;;
-A251;YI SYLLABLE HXAP;Lo;0;L;;;;;N;;;;;
-A252;YI SYLLABLE HXUOT;Lo;0;L;;;;;N;;;;;
-A253;YI SYLLABLE HXUOX;Lo;0;L;;;;;N;;;;;
-A254;YI SYLLABLE HXUO;Lo;0;L;;;;;N;;;;;
-A255;YI SYLLABLE HXUOP;Lo;0;L;;;;;N;;;;;
-A256;YI SYLLABLE HXOT;Lo;0;L;;;;;N;;;;;
-A257;YI SYLLABLE HXOX;Lo;0;L;;;;;N;;;;;
-A258;YI SYLLABLE HXO;Lo;0;L;;;;;N;;;;;
-A259;YI SYLLABLE HXOP;Lo;0;L;;;;;N;;;;;
-A25A;YI SYLLABLE HXEX;Lo;0;L;;;;;N;;;;;
-A25B;YI SYLLABLE HXE;Lo;0;L;;;;;N;;;;;
-A25C;YI SYLLABLE HXEP;Lo;0;L;;;;;N;;;;;
-A25D;YI SYLLABLE NGIEX;Lo;0;L;;;;;N;;;;;
-A25E;YI SYLLABLE NGIE;Lo;0;L;;;;;N;;;;;
-A25F;YI SYLLABLE NGIEP;Lo;0;L;;;;;N;;;;;
-A260;YI SYLLABLE NGAT;Lo;0;L;;;;;N;;;;;
-A261;YI SYLLABLE NGAX;Lo;0;L;;;;;N;;;;;
-A262;YI SYLLABLE NGA;Lo;0;L;;;;;N;;;;;
-A263;YI SYLLABLE NGAP;Lo;0;L;;;;;N;;;;;
-A264;YI SYLLABLE NGUOT;Lo;0;L;;;;;N;;;;;
-A265;YI SYLLABLE NGUOX;Lo;0;L;;;;;N;;;;;
-A266;YI SYLLABLE NGUO;Lo;0;L;;;;;N;;;;;
-A267;YI SYLLABLE NGOT;Lo;0;L;;;;;N;;;;;
-A268;YI SYLLABLE NGOX;Lo;0;L;;;;;N;;;;;
-A269;YI SYLLABLE NGO;Lo;0;L;;;;;N;;;;;
-A26A;YI SYLLABLE NGOP;Lo;0;L;;;;;N;;;;;
-A26B;YI SYLLABLE NGEX;Lo;0;L;;;;;N;;;;;
-A26C;YI SYLLABLE NGE;Lo;0;L;;;;;N;;;;;
-A26D;YI SYLLABLE NGEP;Lo;0;L;;;;;N;;;;;
-A26E;YI SYLLABLE HIT;Lo;0;L;;;;;N;;;;;
-A26F;YI SYLLABLE HIEX;Lo;0;L;;;;;N;;;;;
-A270;YI SYLLABLE HIE;Lo;0;L;;;;;N;;;;;
-A271;YI SYLLABLE HAT;Lo;0;L;;;;;N;;;;;
-A272;YI SYLLABLE HAX;Lo;0;L;;;;;N;;;;;
-A273;YI SYLLABLE HA;Lo;0;L;;;;;N;;;;;
-A274;YI SYLLABLE HAP;Lo;0;L;;;;;N;;;;;
-A275;YI SYLLABLE HUOT;Lo;0;L;;;;;N;;;;;
-A276;YI SYLLABLE HUOX;Lo;0;L;;;;;N;;;;;
-A277;YI SYLLABLE HUO;Lo;0;L;;;;;N;;;;;
-A278;YI SYLLABLE HUOP;Lo;0;L;;;;;N;;;;;
-A279;YI SYLLABLE HOT;Lo;0;L;;;;;N;;;;;
-A27A;YI SYLLABLE HOX;Lo;0;L;;;;;N;;;;;
-A27B;YI SYLLABLE HO;Lo;0;L;;;;;N;;;;;
-A27C;YI SYLLABLE HOP;Lo;0;L;;;;;N;;;;;
-A27D;YI SYLLABLE HEX;Lo;0;L;;;;;N;;;;;
-A27E;YI SYLLABLE HE;Lo;0;L;;;;;N;;;;;
-A27F;YI SYLLABLE HEP;Lo;0;L;;;;;N;;;;;
-A280;YI SYLLABLE WAT;Lo;0;L;;;;;N;;;;;
-A281;YI SYLLABLE WAX;Lo;0;L;;;;;N;;;;;
-A282;YI SYLLABLE WA;Lo;0;L;;;;;N;;;;;
-A283;YI SYLLABLE WAP;Lo;0;L;;;;;N;;;;;
-A284;YI SYLLABLE WUOX;Lo;0;L;;;;;N;;;;;
-A285;YI SYLLABLE WUO;Lo;0;L;;;;;N;;;;;
-A286;YI SYLLABLE WUOP;Lo;0;L;;;;;N;;;;;
-A287;YI SYLLABLE WOX;Lo;0;L;;;;;N;;;;;
-A288;YI SYLLABLE WO;Lo;0;L;;;;;N;;;;;
-A289;YI SYLLABLE WOP;Lo;0;L;;;;;N;;;;;
-A28A;YI SYLLABLE WEX;Lo;0;L;;;;;N;;;;;
-A28B;YI SYLLABLE WE;Lo;0;L;;;;;N;;;;;
-A28C;YI SYLLABLE WEP;Lo;0;L;;;;;N;;;;;
-A28D;YI SYLLABLE ZIT;Lo;0;L;;;;;N;;;;;
-A28E;YI SYLLABLE ZIX;Lo;0;L;;;;;N;;;;;
-A28F;YI SYLLABLE ZI;Lo;0;L;;;;;N;;;;;
-A290;YI SYLLABLE ZIP;Lo;0;L;;;;;N;;;;;
-A291;YI SYLLABLE ZIEX;Lo;0;L;;;;;N;;;;;
-A292;YI SYLLABLE ZIE;Lo;0;L;;;;;N;;;;;
-A293;YI SYLLABLE ZIEP;Lo;0;L;;;;;N;;;;;
-A294;YI SYLLABLE ZAT;Lo;0;L;;;;;N;;;;;
-A295;YI SYLLABLE ZAX;Lo;0;L;;;;;N;;;;;
-A296;YI SYLLABLE ZA;Lo;0;L;;;;;N;;;;;
-A297;YI SYLLABLE ZAP;Lo;0;L;;;;;N;;;;;
-A298;YI SYLLABLE ZUOX;Lo;0;L;;;;;N;;;;;
-A299;YI SYLLABLE ZUO;Lo;0;L;;;;;N;;;;;
-A29A;YI SYLLABLE ZUOP;Lo;0;L;;;;;N;;;;;
-A29B;YI SYLLABLE ZOT;Lo;0;L;;;;;N;;;;;
-A29C;YI SYLLABLE ZOX;Lo;0;L;;;;;N;;;;;
-A29D;YI SYLLABLE ZO;Lo;0;L;;;;;N;;;;;
-A29E;YI SYLLABLE ZOP;Lo;0;L;;;;;N;;;;;
-A29F;YI SYLLABLE ZEX;Lo;0;L;;;;;N;;;;;
-A2A0;YI SYLLABLE ZE;Lo;0;L;;;;;N;;;;;
-A2A1;YI SYLLABLE ZEP;Lo;0;L;;;;;N;;;;;
-A2A2;YI SYLLABLE ZUT;Lo;0;L;;;;;N;;;;;
-A2A3;YI SYLLABLE ZUX;Lo;0;L;;;;;N;;;;;
-A2A4;YI SYLLABLE ZU;Lo;0;L;;;;;N;;;;;
-A2A5;YI SYLLABLE ZUP;Lo;0;L;;;;;N;;;;;
-A2A6;YI SYLLABLE ZURX;Lo;0;L;;;;;N;;;;;
-A2A7;YI SYLLABLE ZUR;Lo;0;L;;;;;N;;;;;
-A2A8;YI SYLLABLE ZYT;Lo;0;L;;;;;N;;;;;
-A2A9;YI SYLLABLE ZYX;Lo;0;L;;;;;N;;;;;
-A2AA;YI SYLLABLE ZY;Lo;0;L;;;;;N;;;;;
-A2AB;YI SYLLABLE ZYP;Lo;0;L;;;;;N;;;;;
-A2AC;YI SYLLABLE ZYRX;Lo;0;L;;;;;N;;;;;
-A2AD;YI SYLLABLE ZYR;Lo;0;L;;;;;N;;;;;
-A2AE;YI SYLLABLE CIT;Lo;0;L;;;;;N;;;;;
-A2AF;YI SYLLABLE CIX;Lo;0;L;;;;;N;;;;;
-A2B0;YI SYLLABLE CI;Lo;0;L;;;;;N;;;;;
-A2B1;YI SYLLABLE CIP;Lo;0;L;;;;;N;;;;;
-A2B2;YI SYLLABLE CIET;Lo;0;L;;;;;N;;;;;
-A2B3;YI SYLLABLE CIEX;Lo;0;L;;;;;N;;;;;
-A2B4;YI SYLLABLE CIE;Lo;0;L;;;;;N;;;;;
-A2B5;YI SYLLABLE CIEP;Lo;0;L;;;;;N;;;;;
-A2B6;YI SYLLABLE CAT;Lo;0;L;;;;;N;;;;;
-A2B7;YI SYLLABLE CAX;Lo;0;L;;;;;N;;;;;
-A2B8;YI SYLLABLE CA;Lo;0;L;;;;;N;;;;;
-A2B9;YI SYLLABLE CAP;Lo;0;L;;;;;N;;;;;
-A2BA;YI SYLLABLE CUOX;Lo;0;L;;;;;N;;;;;
-A2BB;YI SYLLABLE CUO;Lo;0;L;;;;;N;;;;;
-A2BC;YI SYLLABLE CUOP;Lo;0;L;;;;;N;;;;;
-A2BD;YI SYLLABLE COT;Lo;0;L;;;;;N;;;;;
-A2BE;YI SYLLABLE COX;Lo;0;L;;;;;N;;;;;
-A2BF;YI SYLLABLE CO;Lo;0;L;;;;;N;;;;;
-A2C0;YI SYLLABLE COP;Lo;0;L;;;;;N;;;;;
-A2C1;YI SYLLABLE CEX;Lo;0;L;;;;;N;;;;;
-A2C2;YI SYLLABLE CE;Lo;0;L;;;;;N;;;;;
-A2C3;YI SYLLABLE CEP;Lo;0;L;;;;;N;;;;;
-A2C4;YI SYLLABLE CUT;Lo;0;L;;;;;N;;;;;
-A2C5;YI SYLLABLE CUX;Lo;0;L;;;;;N;;;;;
-A2C6;YI SYLLABLE CU;Lo;0;L;;;;;N;;;;;
-A2C7;YI SYLLABLE CUP;Lo;0;L;;;;;N;;;;;
-A2C8;YI SYLLABLE CURX;Lo;0;L;;;;;N;;;;;
-A2C9;YI SYLLABLE CUR;Lo;0;L;;;;;N;;;;;
-A2CA;YI SYLLABLE CYT;Lo;0;L;;;;;N;;;;;
-A2CB;YI SYLLABLE CYX;Lo;0;L;;;;;N;;;;;
-A2CC;YI SYLLABLE CY;Lo;0;L;;;;;N;;;;;
-A2CD;YI SYLLABLE CYP;Lo;0;L;;;;;N;;;;;
-A2CE;YI SYLLABLE CYRX;Lo;0;L;;;;;N;;;;;
-A2CF;YI SYLLABLE CYR;Lo;0;L;;;;;N;;;;;
-A2D0;YI SYLLABLE ZZIT;Lo;0;L;;;;;N;;;;;
-A2D1;YI SYLLABLE ZZIX;Lo;0;L;;;;;N;;;;;
-A2D2;YI SYLLABLE ZZI;Lo;0;L;;;;;N;;;;;
-A2D3;YI SYLLABLE ZZIP;Lo;0;L;;;;;N;;;;;
-A2D4;YI SYLLABLE ZZIET;Lo;0;L;;;;;N;;;;;
-A2D5;YI SYLLABLE ZZIEX;Lo;0;L;;;;;N;;;;;
-A2D6;YI SYLLABLE ZZIE;Lo;0;L;;;;;N;;;;;
-A2D7;YI SYLLABLE ZZIEP;Lo;0;L;;;;;N;;;;;
-A2D8;YI SYLLABLE ZZAT;Lo;0;L;;;;;N;;;;;
-A2D9;YI SYLLABLE ZZAX;Lo;0;L;;;;;N;;;;;
-A2DA;YI SYLLABLE ZZA;Lo;0;L;;;;;N;;;;;
-A2DB;YI SYLLABLE ZZAP;Lo;0;L;;;;;N;;;;;
-A2DC;YI SYLLABLE ZZOX;Lo;0;L;;;;;N;;;;;
-A2DD;YI SYLLABLE ZZO;Lo;0;L;;;;;N;;;;;
-A2DE;YI SYLLABLE ZZOP;Lo;0;L;;;;;N;;;;;
-A2DF;YI SYLLABLE ZZEX;Lo;0;L;;;;;N;;;;;
-A2E0;YI SYLLABLE ZZE;Lo;0;L;;;;;N;;;;;
-A2E1;YI SYLLABLE ZZEP;Lo;0;L;;;;;N;;;;;
-A2E2;YI SYLLABLE ZZUX;Lo;0;L;;;;;N;;;;;
-A2E3;YI SYLLABLE ZZU;Lo;0;L;;;;;N;;;;;
-A2E4;YI SYLLABLE ZZUP;Lo;0;L;;;;;N;;;;;
-A2E5;YI SYLLABLE ZZURX;Lo;0;L;;;;;N;;;;;
-A2E6;YI SYLLABLE ZZUR;Lo;0;L;;;;;N;;;;;
-A2E7;YI SYLLABLE ZZYT;Lo;0;L;;;;;N;;;;;
-A2E8;YI SYLLABLE ZZYX;Lo;0;L;;;;;N;;;;;
-A2E9;YI SYLLABLE ZZY;Lo;0;L;;;;;N;;;;;
-A2EA;YI SYLLABLE ZZYP;Lo;0;L;;;;;N;;;;;
-A2EB;YI SYLLABLE ZZYRX;Lo;0;L;;;;;N;;;;;
-A2EC;YI SYLLABLE ZZYR;Lo;0;L;;;;;N;;;;;
-A2ED;YI SYLLABLE NZIT;Lo;0;L;;;;;N;;;;;
-A2EE;YI SYLLABLE NZIX;Lo;0;L;;;;;N;;;;;
-A2EF;YI SYLLABLE NZI;Lo;0;L;;;;;N;;;;;
-A2F0;YI SYLLABLE NZIP;Lo;0;L;;;;;N;;;;;
-A2F1;YI SYLLABLE NZIEX;Lo;0;L;;;;;N;;;;;
-A2F2;YI SYLLABLE NZIE;Lo;0;L;;;;;N;;;;;
-A2F3;YI SYLLABLE NZIEP;Lo;0;L;;;;;N;;;;;
-A2F4;YI SYLLABLE NZAT;Lo;0;L;;;;;N;;;;;
-A2F5;YI SYLLABLE NZAX;Lo;0;L;;;;;N;;;;;
-A2F6;YI SYLLABLE NZA;Lo;0;L;;;;;N;;;;;
-A2F7;YI SYLLABLE NZAP;Lo;0;L;;;;;N;;;;;
-A2F8;YI SYLLABLE NZUOX;Lo;0;L;;;;;N;;;;;
-A2F9;YI SYLLABLE NZUO;Lo;0;L;;;;;N;;;;;
-A2FA;YI SYLLABLE NZOX;Lo;0;L;;;;;N;;;;;
-A2FB;YI SYLLABLE NZOP;Lo;0;L;;;;;N;;;;;
-A2FC;YI SYLLABLE NZEX;Lo;0;L;;;;;N;;;;;
-A2FD;YI SYLLABLE NZE;Lo;0;L;;;;;N;;;;;
-A2FE;YI SYLLABLE NZUX;Lo;0;L;;;;;N;;;;;
-A2FF;YI SYLLABLE NZU;Lo;0;L;;;;;N;;;;;
-A300;YI SYLLABLE NZUP;Lo;0;L;;;;;N;;;;;
-A301;YI SYLLABLE NZURX;Lo;0;L;;;;;N;;;;;
-A302;YI SYLLABLE NZUR;Lo;0;L;;;;;N;;;;;
-A303;YI SYLLABLE NZYT;Lo;0;L;;;;;N;;;;;
-A304;YI SYLLABLE NZYX;Lo;0;L;;;;;N;;;;;
-A305;YI SYLLABLE NZY;Lo;0;L;;;;;N;;;;;
-A306;YI SYLLABLE NZYP;Lo;0;L;;;;;N;;;;;
-A307;YI SYLLABLE NZYRX;Lo;0;L;;;;;N;;;;;
-A308;YI SYLLABLE NZYR;Lo;0;L;;;;;N;;;;;
-A309;YI SYLLABLE SIT;Lo;0;L;;;;;N;;;;;
-A30A;YI SYLLABLE SIX;Lo;0;L;;;;;N;;;;;
-A30B;YI SYLLABLE SI;Lo;0;L;;;;;N;;;;;
-A30C;YI SYLLABLE SIP;Lo;0;L;;;;;N;;;;;
-A30D;YI SYLLABLE SIEX;Lo;0;L;;;;;N;;;;;
-A30E;YI SYLLABLE SIE;Lo;0;L;;;;;N;;;;;
-A30F;YI SYLLABLE SIEP;Lo;0;L;;;;;N;;;;;
-A310;YI SYLLABLE SAT;Lo;0;L;;;;;N;;;;;
-A311;YI SYLLABLE SAX;Lo;0;L;;;;;N;;;;;
-A312;YI SYLLABLE SA;Lo;0;L;;;;;N;;;;;
-A313;YI SYLLABLE SAP;Lo;0;L;;;;;N;;;;;
-A314;YI SYLLABLE SUOX;Lo;0;L;;;;;N;;;;;
-A315;YI SYLLABLE SUO;Lo;0;L;;;;;N;;;;;
-A316;YI SYLLABLE SUOP;Lo;0;L;;;;;N;;;;;
-A317;YI SYLLABLE SOT;Lo;0;L;;;;;N;;;;;
-A318;YI SYLLABLE SOX;Lo;0;L;;;;;N;;;;;
-A319;YI SYLLABLE SO;Lo;0;L;;;;;N;;;;;
-A31A;YI SYLLABLE SOP;Lo;0;L;;;;;N;;;;;
-A31B;YI SYLLABLE SEX;Lo;0;L;;;;;N;;;;;
-A31C;YI SYLLABLE SE;Lo;0;L;;;;;N;;;;;
-A31D;YI SYLLABLE SEP;Lo;0;L;;;;;N;;;;;
-A31E;YI SYLLABLE SUT;Lo;0;L;;;;;N;;;;;
-A31F;YI SYLLABLE SUX;Lo;0;L;;;;;N;;;;;
-A320;YI SYLLABLE SU;Lo;0;L;;;;;N;;;;;
-A321;YI SYLLABLE SUP;Lo;0;L;;;;;N;;;;;
-A322;YI SYLLABLE SURX;Lo;0;L;;;;;N;;;;;
-A323;YI SYLLABLE SUR;Lo;0;L;;;;;N;;;;;
-A324;YI SYLLABLE SYT;Lo;0;L;;;;;N;;;;;
-A325;YI SYLLABLE SYX;Lo;0;L;;;;;N;;;;;
-A326;YI SYLLABLE SY;Lo;0;L;;;;;N;;;;;
-A327;YI SYLLABLE SYP;Lo;0;L;;;;;N;;;;;
-A328;YI SYLLABLE SYRX;Lo;0;L;;;;;N;;;;;
-A329;YI SYLLABLE SYR;Lo;0;L;;;;;N;;;;;
-A32A;YI SYLLABLE SSIT;Lo;0;L;;;;;N;;;;;
-A32B;YI SYLLABLE SSIX;Lo;0;L;;;;;N;;;;;
-A32C;YI SYLLABLE SSI;Lo;0;L;;;;;N;;;;;
-A32D;YI SYLLABLE SSIP;Lo;0;L;;;;;N;;;;;
-A32E;YI SYLLABLE SSIEX;Lo;0;L;;;;;N;;;;;
-A32F;YI SYLLABLE SSIE;Lo;0;L;;;;;N;;;;;
-A330;YI SYLLABLE SSIEP;Lo;0;L;;;;;N;;;;;
-A331;YI SYLLABLE SSAT;Lo;0;L;;;;;N;;;;;
-A332;YI SYLLABLE SSAX;Lo;0;L;;;;;N;;;;;
-A333;YI SYLLABLE SSA;Lo;0;L;;;;;N;;;;;
-A334;YI SYLLABLE SSAP;Lo;0;L;;;;;N;;;;;
-A335;YI SYLLABLE SSOT;Lo;0;L;;;;;N;;;;;
-A336;YI SYLLABLE SSOX;Lo;0;L;;;;;N;;;;;
-A337;YI SYLLABLE SSO;Lo;0;L;;;;;N;;;;;
-A338;YI SYLLABLE SSOP;Lo;0;L;;;;;N;;;;;
-A339;YI SYLLABLE SSEX;Lo;0;L;;;;;N;;;;;
-A33A;YI SYLLABLE SSE;Lo;0;L;;;;;N;;;;;
-A33B;YI SYLLABLE SSEP;Lo;0;L;;;;;N;;;;;
-A33C;YI SYLLABLE SSUT;Lo;0;L;;;;;N;;;;;
-A33D;YI SYLLABLE SSUX;Lo;0;L;;;;;N;;;;;
-A33E;YI SYLLABLE SSU;Lo;0;L;;;;;N;;;;;
-A33F;YI SYLLABLE SSUP;Lo;0;L;;;;;N;;;;;
-A340;YI SYLLABLE SSYT;Lo;0;L;;;;;N;;;;;
-A341;YI SYLLABLE SSYX;Lo;0;L;;;;;N;;;;;
-A342;YI SYLLABLE SSY;Lo;0;L;;;;;N;;;;;
-A343;YI SYLLABLE SSYP;Lo;0;L;;;;;N;;;;;
-A344;YI SYLLABLE SSYRX;Lo;0;L;;;;;N;;;;;
-A345;YI SYLLABLE SSYR;Lo;0;L;;;;;N;;;;;
-A346;YI SYLLABLE ZHAT;Lo;0;L;;;;;N;;;;;
-A347;YI SYLLABLE ZHAX;Lo;0;L;;;;;N;;;;;
-A348;YI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;;
-A349;YI SYLLABLE ZHAP;Lo;0;L;;;;;N;;;;;
-A34A;YI SYLLABLE ZHUOX;Lo;0;L;;;;;N;;;;;
-A34B;YI SYLLABLE ZHUO;Lo;0;L;;;;;N;;;;;
-A34C;YI SYLLABLE ZHUOP;Lo;0;L;;;;;N;;;;;
-A34D;YI SYLLABLE ZHOT;Lo;0;L;;;;;N;;;;;
-A34E;YI SYLLABLE ZHOX;Lo;0;L;;;;;N;;;;;
-A34F;YI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;;
-A350;YI SYLLABLE ZHOP;Lo;0;L;;;;;N;;;;;
-A351;YI SYLLABLE ZHET;Lo;0;L;;;;;N;;;;;
-A352;YI SYLLABLE ZHEX;Lo;0;L;;;;;N;;;;;
-A353;YI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;;
-A354;YI SYLLABLE ZHEP;Lo;0;L;;;;;N;;;;;
-A355;YI SYLLABLE ZHUT;Lo;0;L;;;;;N;;;;;
-A356;YI SYLLABLE ZHUX;Lo;0;L;;;;;N;;;;;
-A357;YI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;;
-A358;YI SYLLABLE ZHUP;Lo;0;L;;;;;N;;;;;
-A359;YI SYLLABLE ZHURX;Lo;0;L;;;;;N;;;;;
-A35A;YI SYLLABLE ZHUR;Lo;0;L;;;;;N;;;;;
-A35B;YI SYLLABLE ZHYT;Lo;0;L;;;;;N;;;;;
-A35C;YI SYLLABLE ZHYX;Lo;0;L;;;;;N;;;;;
-A35D;YI SYLLABLE ZHY;Lo;0;L;;;;;N;;;;;
-A35E;YI SYLLABLE ZHYP;Lo;0;L;;;;;N;;;;;
-A35F;YI SYLLABLE ZHYRX;Lo;0;L;;;;;N;;;;;
-A360;YI SYLLABLE ZHYR;Lo;0;L;;;;;N;;;;;
-A361;YI SYLLABLE CHAT;Lo;0;L;;;;;N;;;;;
-A362;YI SYLLABLE CHAX;Lo;0;L;;;;;N;;;;;
-A363;YI SYLLABLE CHA;Lo;0;L;;;;;N;;;;;
-A364;YI SYLLABLE CHAP;Lo;0;L;;;;;N;;;;;
-A365;YI SYLLABLE CHUOT;Lo;0;L;;;;;N;;;;;
-A366;YI SYLLABLE CHUOX;Lo;0;L;;;;;N;;;;;
-A367;YI SYLLABLE CHUO;Lo;0;L;;;;;N;;;;;
-A368;YI SYLLABLE CHUOP;Lo;0;L;;;;;N;;;;;
-A369;YI SYLLABLE CHOT;Lo;0;L;;;;;N;;;;;
-A36A;YI SYLLABLE CHOX;Lo;0;L;;;;;N;;;;;
-A36B;YI SYLLABLE CHO;Lo;0;L;;;;;N;;;;;
-A36C;YI SYLLABLE CHOP;Lo;0;L;;;;;N;;;;;
-A36D;YI SYLLABLE CHET;Lo;0;L;;;;;N;;;;;
-A36E;YI SYLLABLE CHEX;Lo;0;L;;;;;N;;;;;
-A36F;YI SYLLABLE CHE;Lo;0;L;;;;;N;;;;;
-A370;YI SYLLABLE CHEP;Lo;0;L;;;;;N;;;;;
-A371;YI SYLLABLE CHUX;Lo;0;L;;;;;N;;;;;
-A372;YI SYLLABLE CHU;Lo;0;L;;;;;N;;;;;
-A373;YI SYLLABLE CHUP;Lo;0;L;;;;;N;;;;;
-A374;YI SYLLABLE CHURX;Lo;0;L;;;;;N;;;;;
-A375;YI SYLLABLE CHUR;Lo;0;L;;;;;N;;;;;
-A376;YI SYLLABLE CHYT;Lo;0;L;;;;;N;;;;;
-A377;YI SYLLABLE CHYX;Lo;0;L;;;;;N;;;;;
-A378;YI SYLLABLE CHY;Lo;0;L;;;;;N;;;;;
-A379;YI SYLLABLE CHYP;Lo;0;L;;;;;N;;;;;
-A37A;YI SYLLABLE CHYRX;Lo;0;L;;;;;N;;;;;
-A37B;YI SYLLABLE CHYR;Lo;0;L;;;;;N;;;;;
-A37C;YI SYLLABLE RRAX;Lo;0;L;;;;;N;;;;;
-A37D;YI SYLLABLE RRA;Lo;0;L;;;;;N;;;;;
-A37E;YI SYLLABLE RRUOX;Lo;0;L;;;;;N;;;;;
-A37F;YI SYLLABLE RRUO;Lo;0;L;;;;;N;;;;;
-A380;YI SYLLABLE RROT;Lo;0;L;;;;;N;;;;;
-A381;YI SYLLABLE RROX;Lo;0;L;;;;;N;;;;;
-A382;YI SYLLABLE RRO;Lo;0;L;;;;;N;;;;;
-A383;YI SYLLABLE RROP;Lo;0;L;;;;;N;;;;;
-A384;YI SYLLABLE RRET;Lo;0;L;;;;;N;;;;;
-A385;YI SYLLABLE RREX;Lo;0;L;;;;;N;;;;;
-A386;YI SYLLABLE RRE;Lo;0;L;;;;;N;;;;;
-A387;YI SYLLABLE RREP;Lo;0;L;;;;;N;;;;;
-A388;YI SYLLABLE RRUT;Lo;0;L;;;;;N;;;;;
-A389;YI SYLLABLE RRUX;Lo;0;L;;;;;N;;;;;
-A38A;YI SYLLABLE RRU;Lo;0;L;;;;;N;;;;;
-A38B;YI SYLLABLE RRUP;Lo;0;L;;;;;N;;;;;
-A38C;YI SYLLABLE RRURX;Lo;0;L;;;;;N;;;;;
-A38D;YI SYLLABLE RRUR;Lo;0;L;;;;;N;;;;;
-A38E;YI SYLLABLE RRYT;Lo;0;L;;;;;N;;;;;
-A38F;YI SYLLABLE RRYX;Lo;0;L;;;;;N;;;;;
-A390;YI SYLLABLE RRY;Lo;0;L;;;;;N;;;;;
-A391;YI SYLLABLE RRYP;Lo;0;L;;;;;N;;;;;
-A392;YI SYLLABLE RRYRX;Lo;0;L;;;;;N;;;;;
-A393;YI SYLLABLE RRYR;Lo;0;L;;;;;N;;;;;
-A394;YI SYLLABLE NRAT;Lo;0;L;;;;;N;;;;;
-A395;YI SYLLABLE NRAX;Lo;0;L;;;;;N;;;;;
-A396;YI SYLLABLE NRA;Lo;0;L;;;;;N;;;;;
-A397;YI SYLLABLE NRAP;Lo;0;L;;;;;N;;;;;
-A398;YI SYLLABLE NROX;Lo;0;L;;;;;N;;;;;
-A399;YI SYLLABLE NRO;Lo;0;L;;;;;N;;;;;
-A39A;YI SYLLABLE NROP;Lo;0;L;;;;;N;;;;;
-A39B;YI SYLLABLE NRET;Lo;0;L;;;;;N;;;;;
-A39C;YI SYLLABLE NREX;Lo;0;L;;;;;N;;;;;
-A39D;YI SYLLABLE NRE;Lo;0;L;;;;;N;;;;;
-A39E;YI SYLLABLE NREP;Lo;0;L;;;;;N;;;;;
-A39F;YI SYLLABLE NRUT;Lo;0;L;;;;;N;;;;;
-A3A0;YI SYLLABLE NRUX;Lo;0;L;;;;;N;;;;;
-A3A1;YI SYLLABLE NRU;Lo;0;L;;;;;N;;;;;
-A3A2;YI SYLLABLE NRUP;Lo;0;L;;;;;N;;;;;
-A3A3;YI SYLLABLE NRURX;Lo;0;L;;;;;N;;;;;
-A3A4;YI SYLLABLE NRUR;Lo;0;L;;;;;N;;;;;
-A3A5;YI SYLLABLE NRYT;Lo;0;L;;;;;N;;;;;
-A3A6;YI SYLLABLE NRYX;Lo;0;L;;;;;N;;;;;
-A3A7;YI SYLLABLE NRY;Lo;0;L;;;;;N;;;;;
-A3A8;YI SYLLABLE NRYP;Lo;0;L;;;;;N;;;;;
-A3A9;YI SYLLABLE NRYRX;Lo;0;L;;;;;N;;;;;
-A3AA;YI SYLLABLE NRYR;Lo;0;L;;;;;N;;;;;
-A3AB;YI SYLLABLE SHAT;Lo;0;L;;;;;N;;;;;
-A3AC;YI SYLLABLE SHAX;Lo;0;L;;;;;N;;;;;
-A3AD;YI SYLLABLE SHA;Lo;0;L;;;;;N;;;;;
-A3AE;YI SYLLABLE SHAP;Lo;0;L;;;;;N;;;;;
-A3AF;YI SYLLABLE SHUOX;Lo;0;L;;;;;N;;;;;
-A3B0;YI SYLLABLE SHUO;Lo;0;L;;;;;N;;;;;
-A3B1;YI SYLLABLE SHUOP;Lo;0;L;;;;;N;;;;;
-A3B2;YI SYLLABLE SHOT;Lo;0;L;;;;;N;;;;;
-A3B3;YI SYLLABLE SHOX;Lo;0;L;;;;;N;;;;;
-A3B4;YI SYLLABLE SHO;Lo;0;L;;;;;N;;;;;
-A3B5;YI SYLLABLE SHOP;Lo;0;L;;;;;N;;;;;
-A3B6;YI SYLLABLE SHET;Lo;0;L;;;;;N;;;;;
-A3B7;YI SYLLABLE SHEX;Lo;0;L;;;;;N;;;;;
-A3B8;YI SYLLABLE SHE;Lo;0;L;;;;;N;;;;;
-A3B9;YI SYLLABLE SHEP;Lo;0;L;;;;;N;;;;;
-A3BA;YI SYLLABLE SHUT;Lo;0;L;;;;;N;;;;;
-A3BB;YI SYLLABLE SHUX;Lo;0;L;;;;;N;;;;;
-A3BC;YI SYLLABLE SHU;Lo;0;L;;;;;N;;;;;
-A3BD;YI SYLLABLE SHUP;Lo;0;L;;;;;N;;;;;
-A3BE;YI SYLLABLE SHURX;Lo;0;L;;;;;N;;;;;
-A3BF;YI SYLLABLE SHUR;Lo;0;L;;;;;N;;;;;
-A3C0;YI SYLLABLE SHYT;Lo;0;L;;;;;N;;;;;
-A3C1;YI SYLLABLE SHYX;Lo;0;L;;;;;N;;;;;
-A3C2;YI SYLLABLE SHY;Lo;0;L;;;;;N;;;;;
-A3C3;YI SYLLABLE SHYP;Lo;0;L;;;;;N;;;;;
-A3C4;YI SYLLABLE SHYRX;Lo;0;L;;;;;N;;;;;
-A3C5;YI SYLLABLE SHYR;Lo;0;L;;;;;N;;;;;
-A3C6;YI SYLLABLE RAT;Lo;0;L;;;;;N;;;;;
-A3C7;YI SYLLABLE RAX;Lo;0;L;;;;;N;;;;;
-A3C8;YI SYLLABLE RA;Lo;0;L;;;;;N;;;;;
-A3C9;YI SYLLABLE RAP;Lo;0;L;;;;;N;;;;;
-A3CA;YI SYLLABLE RUOX;Lo;0;L;;;;;N;;;;;
-A3CB;YI SYLLABLE RUO;Lo;0;L;;;;;N;;;;;
-A3CC;YI SYLLABLE RUOP;Lo;0;L;;;;;N;;;;;
-A3CD;YI SYLLABLE ROT;Lo;0;L;;;;;N;;;;;
-A3CE;YI SYLLABLE ROX;Lo;0;L;;;;;N;;;;;
-A3CF;YI SYLLABLE RO;Lo;0;L;;;;;N;;;;;
-A3D0;YI SYLLABLE ROP;Lo;0;L;;;;;N;;;;;
-A3D1;YI SYLLABLE REX;Lo;0;L;;;;;N;;;;;
-A3D2;YI SYLLABLE RE;Lo;0;L;;;;;N;;;;;
-A3D3;YI SYLLABLE REP;Lo;0;L;;;;;N;;;;;
-A3D4;YI SYLLABLE RUT;Lo;0;L;;;;;N;;;;;
-A3D5;YI SYLLABLE RUX;Lo;0;L;;;;;N;;;;;
-A3D6;YI SYLLABLE RU;Lo;0;L;;;;;N;;;;;
-A3D7;YI SYLLABLE RUP;Lo;0;L;;;;;N;;;;;
-A3D8;YI SYLLABLE RURX;Lo;0;L;;;;;N;;;;;
-A3D9;YI SYLLABLE RUR;Lo;0;L;;;;;N;;;;;
-A3DA;YI SYLLABLE RYT;Lo;0;L;;;;;N;;;;;
-A3DB;YI SYLLABLE RYX;Lo;0;L;;;;;N;;;;;
-A3DC;YI SYLLABLE RY;Lo;0;L;;;;;N;;;;;
-A3DD;YI SYLLABLE RYP;Lo;0;L;;;;;N;;;;;
-A3DE;YI SYLLABLE RYRX;Lo;0;L;;;;;N;;;;;
-A3DF;YI SYLLABLE RYR;Lo;0;L;;;;;N;;;;;
-A3E0;YI SYLLABLE JIT;Lo;0;L;;;;;N;;;;;
-A3E1;YI SYLLABLE JIX;Lo;0;L;;;;;N;;;;;
-A3E2;YI SYLLABLE JI;Lo;0;L;;;;;N;;;;;
-A3E3;YI SYLLABLE JIP;Lo;0;L;;;;;N;;;;;
-A3E4;YI SYLLABLE JIET;Lo;0;L;;;;;N;;;;;
-A3E5;YI SYLLABLE JIEX;Lo;0;L;;;;;N;;;;;
-A3E6;YI SYLLABLE JIE;Lo;0;L;;;;;N;;;;;
-A3E7;YI SYLLABLE JIEP;Lo;0;L;;;;;N;;;;;
-A3E8;YI SYLLABLE JUOT;Lo;0;L;;;;;N;;;;;
-A3E9;YI SYLLABLE JUOX;Lo;0;L;;;;;N;;;;;
-A3EA;YI SYLLABLE JUO;Lo;0;L;;;;;N;;;;;
-A3EB;YI SYLLABLE JUOP;Lo;0;L;;;;;N;;;;;
-A3EC;YI SYLLABLE JOT;Lo;0;L;;;;;N;;;;;
-A3ED;YI SYLLABLE JOX;Lo;0;L;;;;;N;;;;;
-A3EE;YI SYLLABLE JO;Lo;0;L;;;;;N;;;;;
-A3EF;YI SYLLABLE JOP;Lo;0;L;;;;;N;;;;;
-A3F0;YI SYLLABLE JUT;Lo;0;L;;;;;N;;;;;
-A3F1;YI SYLLABLE JUX;Lo;0;L;;;;;N;;;;;
-A3F2;YI SYLLABLE JU;Lo;0;L;;;;;N;;;;;
-A3F3;YI SYLLABLE JUP;Lo;0;L;;;;;N;;;;;
-A3F4;YI SYLLABLE JURX;Lo;0;L;;;;;N;;;;;
-A3F5;YI SYLLABLE JUR;Lo;0;L;;;;;N;;;;;
-A3F6;YI SYLLABLE JYT;Lo;0;L;;;;;N;;;;;
-A3F7;YI SYLLABLE JYX;Lo;0;L;;;;;N;;;;;
-A3F8;YI SYLLABLE JY;Lo;0;L;;;;;N;;;;;
-A3F9;YI SYLLABLE JYP;Lo;0;L;;;;;N;;;;;
-A3FA;YI SYLLABLE JYRX;Lo;0;L;;;;;N;;;;;
-A3FB;YI SYLLABLE JYR;Lo;0;L;;;;;N;;;;;
-A3FC;YI SYLLABLE QIT;Lo;0;L;;;;;N;;;;;
-A3FD;YI SYLLABLE QIX;Lo;0;L;;;;;N;;;;;
-A3FE;YI SYLLABLE QI;Lo;0;L;;;;;N;;;;;
-A3FF;YI SYLLABLE QIP;Lo;0;L;;;;;N;;;;;
-A400;YI SYLLABLE QIET;Lo;0;L;;;;;N;;;;;
-A401;YI SYLLABLE QIEX;Lo;0;L;;;;;N;;;;;
-A402;YI SYLLABLE QIE;Lo;0;L;;;;;N;;;;;
-A403;YI SYLLABLE QIEP;Lo;0;L;;;;;N;;;;;
-A404;YI SYLLABLE QUOT;Lo;0;L;;;;;N;;;;;
-A405;YI SYLLABLE QUOX;Lo;0;L;;;;;N;;;;;
-A406;YI SYLLABLE QUO;Lo;0;L;;;;;N;;;;;
-A407;YI SYLLABLE QUOP;Lo;0;L;;;;;N;;;;;
-A408;YI SYLLABLE QOT;Lo;0;L;;;;;N;;;;;
-A409;YI SYLLABLE QOX;Lo;0;L;;;;;N;;;;;
-A40A;YI SYLLABLE QO;Lo;0;L;;;;;N;;;;;
-A40B;YI SYLLABLE QOP;Lo;0;L;;;;;N;;;;;
-A40C;YI SYLLABLE QUT;Lo;0;L;;;;;N;;;;;
-A40D;YI SYLLABLE QUX;Lo;0;L;;;;;N;;;;;
-A40E;YI SYLLABLE QU;Lo;0;L;;;;;N;;;;;
-A40F;YI SYLLABLE QUP;Lo;0;L;;;;;N;;;;;
-A410;YI SYLLABLE QURX;Lo;0;L;;;;;N;;;;;
-A411;YI SYLLABLE QUR;Lo;0;L;;;;;N;;;;;
-A412;YI SYLLABLE QYT;Lo;0;L;;;;;N;;;;;
-A413;YI SYLLABLE QYX;Lo;0;L;;;;;N;;;;;
-A414;YI SYLLABLE QY;Lo;0;L;;;;;N;;;;;
-A415;YI SYLLABLE QYP;Lo;0;L;;;;;N;;;;;
-A416;YI SYLLABLE QYRX;Lo;0;L;;;;;N;;;;;
-A417;YI SYLLABLE QYR;Lo;0;L;;;;;N;;;;;
-A418;YI SYLLABLE JJIT;Lo;0;L;;;;;N;;;;;
-A419;YI SYLLABLE JJIX;Lo;0;L;;;;;N;;;;;
-A41A;YI SYLLABLE JJI;Lo;0;L;;;;;N;;;;;
-A41B;YI SYLLABLE JJIP;Lo;0;L;;;;;N;;;;;
-A41C;YI SYLLABLE JJIET;Lo;0;L;;;;;N;;;;;
-A41D;YI SYLLABLE JJIEX;Lo;0;L;;;;;N;;;;;
-A41E;YI SYLLABLE JJIE;Lo;0;L;;;;;N;;;;;
-A41F;YI SYLLABLE JJIEP;Lo;0;L;;;;;N;;;;;
-A420;YI SYLLABLE JJUOX;Lo;0;L;;;;;N;;;;;
-A421;YI SYLLABLE JJUO;Lo;0;L;;;;;N;;;;;
-A422;YI SYLLABLE JJUOP;Lo;0;L;;;;;N;;;;;
-A423;YI SYLLABLE JJOT;Lo;0;L;;;;;N;;;;;
-A424;YI SYLLABLE JJOX;Lo;0;L;;;;;N;;;;;
-A425;YI SYLLABLE JJO;Lo;0;L;;;;;N;;;;;
-A426;YI SYLLABLE JJOP;Lo;0;L;;;;;N;;;;;
-A427;YI SYLLABLE JJUT;Lo;0;L;;;;;N;;;;;
-A428;YI SYLLABLE JJUX;Lo;0;L;;;;;N;;;;;
-A429;YI SYLLABLE JJU;Lo;0;L;;;;;N;;;;;
-A42A;YI SYLLABLE JJUP;Lo;0;L;;;;;N;;;;;
-A42B;YI SYLLABLE JJURX;Lo;0;L;;;;;N;;;;;
-A42C;YI SYLLABLE JJUR;Lo;0;L;;;;;N;;;;;
-A42D;YI SYLLABLE JJYT;Lo;0;L;;;;;N;;;;;
-A42E;YI SYLLABLE JJYX;Lo;0;L;;;;;N;;;;;
-A42F;YI SYLLABLE JJY;Lo;0;L;;;;;N;;;;;
-A430;YI SYLLABLE JJYP;Lo;0;L;;;;;N;;;;;
-A431;YI SYLLABLE NJIT;Lo;0;L;;;;;N;;;;;
-A432;YI SYLLABLE NJIX;Lo;0;L;;;;;N;;;;;
-A433;YI SYLLABLE NJI;Lo;0;L;;;;;N;;;;;
-A434;YI SYLLABLE NJIP;Lo;0;L;;;;;N;;;;;
-A435;YI SYLLABLE NJIET;Lo;0;L;;;;;N;;;;;
-A436;YI SYLLABLE NJIEX;Lo;0;L;;;;;N;;;;;
-A437;YI SYLLABLE NJIE;Lo;0;L;;;;;N;;;;;
-A438;YI SYLLABLE NJIEP;Lo;0;L;;;;;N;;;;;
-A439;YI SYLLABLE NJUOX;Lo;0;L;;;;;N;;;;;
-A43A;YI SYLLABLE NJUO;Lo;0;L;;;;;N;;;;;
-A43B;YI SYLLABLE NJOT;Lo;0;L;;;;;N;;;;;
-A43C;YI SYLLABLE NJOX;Lo;0;L;;;;;N;;;;;
-A43D;YI SYLLABLE NJO;Lo;0;L;;;;;N;;;;;
-A43E;YI SYLLABLE NJOP;Lo;0;L;;;;;N;;;;;
-A43F;YI SYLLABLE NJUX;Lo;0;L;;;;;N;;;;;
-A440;YI SYLLABLE NJU;Lo;0;L;;;;;N;;;;;
-A441;YI SYLLABLE NJUP;Lo;0;L;;;;;N;;;;;
-A442;YI SYLLABLE NJURX;Lo;0;L;;;;;N;;;;;
-A443;YI SYLLABLE NJUR;Lo;0;L;;;;;N;;;;;
-A444;YI SYLLABLE NJYT;Lo;0;L;;;;;N;;;;;
-A445;YI SYLLABLE NJYX;Lo;0;L;;;;;N;;;;;
-A446;YI SYLLABLE NJY;Lo;0;L;;;;;N;;;;;
-A447;YI SYLLABLE NJYP;Lo;0;L;;;;;N;;;;;
-A448;YI SYLLABLE NJYRX;Lo;0;L;;;;;N;;;;;
-A449;YI SYLLABLE NJYR;Lo;0;L;;;;;N;;;;;
-A44A;YI SYLLABLE NYIT;Lo;0;L;;;;;N;;;;;
-A44B;YI SYLLABLE NYIX;Lo;0;L;;;;;N;;;;;
-A44C;YI SYLLABLE NYI;Lo;0;L;;;;;N;;;;;
-A44D;YI SYLLABLE NYIP;Lo;0;L;;;;;N;;;;;
-A44E;YI SYLLABLE NYIET;Lo;0;L;;;;;N;;;;;
-A44F;YI SYLLABLE NYIEX;Lo;0;L;;;;;N;;;;;
-A450;YI SYLLABLE NYIE;Lo;0;L;;;;;N;;;;;
-A451;YI SYLLABLE NYIEP;Lo;0;L;;;;;N;;;;;
-A452;YI SYLLABLE NYUOX;Lo;0;L;;;;;N;;;;;
-A453;YI SYLLABLE NYUO;Lo;0;L;;;;;N;;;;;
-A454;YI SYLLABLE NYUOP;Lo;0;L;;;;;N;;;;;
-A455;YI SYLLABLE NYOT;Lo;0;L;;;;;N;;;;;
-A456;YI SYLLABLE NYOX;Lo;0;L;;;;;N;;;;;
-A457;YI SYLLABLE NYO;Lo;0;L;;;;;N;;;;;
-A458;YI SYLLABLE NYOP;Lo;0;L;;;;;N;;;;;
-A459;YI SYLLABLE NYUT;Lo;0;L;;;;;N;;;;;
-A45A;YI SYLLABLE NYUX;Lo;0;L;;;;;N;;;;;
-A45B;YI SYLLABLE NYU;Lo;0;L;;;;;N;;;;;
-A45C;YI SYLLABLE NYUP;Lo;0;L;;;;;N;;;;;
-A45D;YI SYLLABLE XIT;Lo;0;L;;;;;N;;;;;
-A45E;YI SYLLABLE XIX;Lo;0;L;;;;;N;;;;;
-A45F;YI SYLLABLE XI;Lo;0;L;;;;;N;;;;;
-A460;YI SYLLABLE XIP;Lo;0;L;;;;;N;;;;;
-A461;YI SYLLABLE XIET;Lo;0;L;;;;;N;;;;;
-A462;YI SYLLABLE XIEX;Lo;0;L;;;;;N;;;;;
-A463;YI SYLLABLE XIE;Lo;0;L;;;;;N;;;;;
-A464;YI SYLLABLE XIEP;Lo;0;L;;;;;N;;;;;
-A465;YI SYLLABLE XUOX;Lo;0;L;;;;;N;;;;;
-A466;YI SYLLABLE XUO;Lo;0;L;;;;;N;;;;;
-A467;YI SYLLABLE XOT;Lo;0;L;;;;;N;;;;;
-A468;YI SYLLABLE XOX;Lo;0;L;;;;;N;;;;;
-A469;YI SYLLABLE XO;Lo;0;L;;;;;N;;;;;
-A46A;YI SYLLABLE XOP;Lo;0;L;;;;;N;;;;;
-A46B;YI SYLLABLE XYT;Lo;0;L;;;;;N;;;;;
-A46C;YI SYLLABLE XYX;Lo;0;L;;;;;N;;;;;
-A46D;YI SYLLABLE XY;Lo;0;L;;;;;N;;;;;
-A46E;YI SYLLABLE XYP;Lo;0;L;;;;;N;;;;;
-A46F;YI SYLLABLE XYRX;Lo;0;L;;;;;N;;;;;
-A470;YI SYLLABLE XYR;Lo;0;L;;;;;N;;;;;
-A471;YI SYLLABLE YIT;Lo;0;L;;;;;N;;;;;
-A472;YI SYLLABLE YIX;Lo;0;L;;;;;N;;;;;
-A473;YI SYLLABLE YI;Lo;0;L;;;;;N;;;;;
-A474;YI SYLLABLE YIP;Lo;0;L;;;;;N;;;;;
-A475;YI SYLLABLE YIET;Lo;0;L;;;;;N;;;;;
-A476;YI SYLLABLE YIEX;Lo;0;L;;;;;N;;;;;
-A477;YI SYLLABLE YIE;Lo;0;L;;;;;N;;;;;
-A478;YI SYLLABLE YIEP;Lo;0;L;;;;;N;;;;;
-A479;YI SYLLABLE YUOT;Lo;0;L;;;;;N;;;;;
-A47A;YI SYLLABLE YUOX;Lo;0;L;;;;;N;;;;;
-A47B;YI SYLLABLE YUO;Lo;0;L;;;;;N;;;;;
-A47C;YI SYLLABLE YUOP;Lo;0;L;;;;;N;;;;;
-A47D;YI SYLLABLE YOT;Lo;0;L;;;;;N;;;;;
-A47E;YI SYLLABLE YOX;Lo;0;L;;;;;N;;;;;
-A47F;YI SYLLABLE YO;Lo;0;L;;;;;N;;;;;
-A480;YI SYLLABLE YOP;Lo;0;L;;;;;N;;;;;
-A481;YI SYLLABLE YUT;Lo;0;L;;;;;N;;;;;
-A482;YI SYLLABLE YUX;Lo;0;L;;;;;N;;;;;
-A483;YI SYLLABLE YU;Lo;0;L;;;;;N;;;;;
-A484;YI SYLLABLE YUP;Lo;0;L;;;;;N;;;;;
-A485;YI SYLLABLE YURX;Lo;0;L;;;;;N;;;;;
-A486;YI SYLLABLE YUR;Lo;0;L;;;;;N;;;;;
-A487;YI SYLLABLE YYT;Lo;0;L;;;;;N;;;;;
-A488;YI SYLLABLE YYX;Lo;0;L;;;;;N;;;;;
-A489;YI SYLLABLE YY;Lo;0;L;;;;;N;;;;;
-A48A;YI SYLLABLE YYP;Lo;0;L;;;;;N;;;;;
-A48B;YI SYLLABLE YYRX;Lo;0;L;;;;;N;;;;;
-A48C;YI SYLLABLE YYR;Lo;0;L;;;;;N;;;;;
-A490;YI RADICAL QOT;So;0;ON;;;;;N;;;;;
-A491;YI RADICAL LI;So;0;ON;;;;;N;;;;;
-A492;YI RADICAL KIT;So;0;ON;;;;;N;;;;;
-A493;YI RADICAL NYIP;So;0;ON;;;;;N;;;;;
-A494;YI RADICAL CYP;So;0;ON;;;;;N;;;;;
-A495;YI RADICAL SSI;So;0;ON;;;;;N;;;;;
-A496;YI RADICAL GGOP;So;0;ON;;;;;N;;;;;
-A497;YI RADICAL GEP;So;0;ON;;;;;N;;;;;
-A498;YI RADICAL MI;So;0;ON;;;;;N;;;;;
-A499;YI RADICAL HXIT;So;0;ON;;;;;N;;;;;
-A49A;YI RADICAL LYR;So;0;ON;;;;;N;;;;;
-A49B;YI RADICAL BBUT;So;0;ON;;;;;N;;;;;
-A49C;YI RADICAL MOP;So;0;ON;;;;;N;;;;;
-A49D;YI RADICAL YO;So;0;ON;;;;;N;;;;;
-A49E;YI RADICAL PUT;So;0;ON;;;;;N;;;;;
-A49F;YI RADICAL HXUO;So;0;ON;;;;;N;;;;;
-A4A0;YI RADICAL TAT;So;0;ON;;;;;N;;;;;
-A4A1;YI RADICAL GA;So;0;ON;;;;;N;;;;;
-A4A2;YI RADICAL ZUP;So;0;ON;;;;;N;;;;;
-A4A3;YI RADICAL CYT;So;0;ON;;;;;N;;;;;
-A4A4;YI RADICAL DDUR;So;0;ON;;;;;N;;;;;
-A4A5;YI RADICAL BUR;So;0;ON;;;;;N;;;;;
-A4A6;YI RADICAL GGUO;So;0;ON;;;;;N;;;;;
-A4A7;YI RADICAL NYOP;So;0;ON;;;;;N;;;;;
-A4A8;YI RADICAL TU;So;0;ON;;;;;N;;;;;
-A4A9;YI RADICAL OP;So;0;ON;;;;;N;;;;;
-A4AA;YI RADICAL JJUT;So;0;ON;;;;;N;;;;;
-A4AB;YI RADICAL ZOT;So;0;ON;;;;;N;;;;;
-A4AC;YI RADICAL PYT;So;0;ON;;;;;N;;;;;
-A4AD;YI RADICAL HMO;So;0;ON;;;;;N;;;;;
-A4AE;YI RADICAL YIT;So;0;ON;;;;;N;;;;;
-A4AF;YI RADICAL VUR;So;0;ON;;;;;N;;;;;
-A4B0;YI RADICAL SHY;So;0;ON;;;;;N;;;;;
-A4B1;YI RADICAL VEP;So;0;ON;;;;;N;;;;;
-A4B2;YI RADICAL ZA;So;0;ON;;;;;N;;;;;
-A4B3;YI RADICAL JO;So;0;ON;;;;;N;;;;;
-A4B4;YI RADICAL NZUP;So;0;ON;;;;;N;;;;;
-A4B5;YI RADICAL JJY;So;0;ON;;;;;N;;;;;
-A4B6;YI RADICAL GOT;So;0;ON;;;;;N;;;;;
-A4B7;YI RADICAL JJIE;So;0;ON;;;;;N;;;;;
-A4B8;YI RADICAL WO;So;0;ON;;;;;N;;;;;
-A4B9;YI RADICAL DU;So;0;ON;;;;;N;;;;;
-A4BA;YI RADICAL SHUR;So;0;ON;;;;;N;;;;;
-A4BB;YI RADICAL LIE;So;0;ON;;;;;N;;;;;
-A4BC;YI RADICAL CY;So;0;ON;;;;;N;;;;;
-A4BD;YI RADICAL CUOP;So;0;ON;;;;;N;;;;;
-A4BE;YI RADICAL CIP;So;0;ON;;;;;N;;;;;
-A4BF;YI RADICAL HXOP;So;0;ON;;;;;N;;;;;
-A4C0;YI RADICAL SHAT;So;0;ON;;;;;N;;;;;
-A4C1;YI RADICAL ZUR;So;0;ON;;;;;N;;;;;
-A4C2;YI RADICAL SHOP;So;0;ON;;;;;N;;;;;
-A4C3;YI RADICAL CHE;So;0;ON;;;;;N;;;;;
-A4C4;YI RADICAL ZZIET;So;0;ON;;;;;N;;;;;
-A4C5;YI RADICAL NBIE;So;0;ON;;;;;N;;;;;
-A4C6;YI RADICAL KE;So;0;ON;;;;;N;;;;;
-A4D0;LISU LETTER BA;Lo;0;L;;;;;N;;;;;
-A4D1;LISU LETTER PA;Lo;0;L;;;;;N;;;;;
-A4D2;LISU LETTER PHA;Lo;0;L;;;;;N;;;;;
-A4D3;LISU LETTER DA;Lo;0;L;;;;;N;;;;;
-A4D4;LISU LETTER TA;Lo;0;L;;;;;N;;;;;
-A4D5;LISU LETTER THA;Lo;0;L;;;;;N;;;;;
-A4D6;LISU LETTER GA;Lo;0;L;;;;;N;;;;;
-A4D7;LISU LETTER KA;Lo;0;L;;;;;N;;;;;
-A4D8;LISU LETTER KHA;Lo;0;L;;;;;N;;;;;
-A4D9;LISU LETTER JA;Lo;0;L;;;;;N;;;;;
-A4DA;LISU LETTER CA;Lo;0;L;;;;;N;;;;;
-A4DB;LISU LETTER CHA;Lo;0;L;;;;;N;;;;;
-A4DC;LISU LETTER DZA;Lo;0;L;;;;;N;;;;;
-A4DD;LISU LETTER TSA;Lo;0;L;;;;;N;;;;;
-A4DE;LISU LETTER TSHA;Lo;0;L;;;;;N;;;;;
-A4DF;LISU LETTER MA;Lo;0;L;;;;;N;;;;;
-A4E0;LISU LETTER NA;Lo;0;L;;;;;N;;;;;
-A4E1;LISU LETTER LA;Lo;0;L;;;;;N;;;;;
-A4E2;LISU LETTER SA;Lo;0;L;;;;;N;;;;;
-A4E3;LISU LETTER ZHA;Lo;0;L;;;;;N;;;;;
-A4E4;LISU LETTER ZA;Lo;0;L;;;;;N;;;;;
-A4E5;LISU LETTER NGA;Lo;0;L;;;;;N;;;;;
-A4E6;LISU LETTER HA;Lo;0;L;;;;;N;;;;;
-A4E7;LISU LETTER XA;Lo;0;L;;;;;N;;;;;
-A4E8;LISU LETTER HHA;Lo;0;L;;;;;N;;;;;
-A4E9;LISU LETTER FA;Lo;0;L;;;;;N;;;;;
-A4EA;LISU LETTER WA;Lo;0;L;;;;;N;;;;;
-A4EB;LISU LETTER SHA;Lo;0;L;;;;;N;;;;;
-A4EC;LISU LETTER YA;Lo;0;L;;;;;N;;;;;
-A4ED;LISU LETTER GHA;Lo;0;L;;;;;N;;;;;
-A4EE;LISU LETTER A;Lo;0;L;;;;;N;;;;;
-A4EF;LISU LETTER AE;Lo;0;L;;;;;N;;;;;
-A4F0;LISU LETTER E;Lo;0;L;;;;;N;;;;;
-A4F1;LISU LETTER EU;Lo;0;L;;;;;N;;;;;
-A4F2;LISU LETTER I;Lo;0;L;;;;;N;;;;;
-A4F3;LISU LETTER O;Lo;0;L;;;;;N;;;;;
-A4F4;LISU LETTER U;Lo;0;L;;;;;N;;;;;
-A4F5;LISU LETTER UE;Lo;0;L;;;;;N;;;;;
-A4F6;LISU LETTER UH;Lo;0;L;;;;;N;;;;;
-A4F7;LISU LETTER OE;Lo;0;L;;;;;N;;;;;
-A4F8;LISU LETTER TONE MYA TI;Lm;0;L;;;;;N;;;;;
-A4F9;LISU LETTER TONE NA PO;Lm;0;L;;;;;N;;;;;
-A4FA;LISU LETTER TONE MYA CYA;Lm;0;L;;;;;N;;;;;
-A4FB;LISU LETTER TONE MYA BO;Lm;0;L;;;;;N;;;;;
-A4FC;LISU LETTER TONE MYA NA;Lm;0;L;;;;;N;;;;;
-A4FD;LISU LETTER TONE MYA JEU;Lm;0;L;;;;;N;;;;;
-A4FE;LISU PUNCTUATION COMMA;Po;0;L;;;;;N;;;;;
-A4FF;LISU PUNCTUATION FULL STOP;Po;0;L;;;;;N;;;;;
-A500;VAI SYLLABLE EE;Lo;0;L;;;;;N;;;;;
-A501;VAI SYLLABLE EEN;Lo;0;L;;;;;N;;;;;
-A502;VAI SYLLABLE HEE;Lo;0;L;;;;;N;;;;;
-A503;VAI SYLLABLE WEE;Lo;0;L;;;;;N;;;;;
-A504;VAI SYLLABLE WEEN;Lo;0;L;;;;;N;;;;;
-A505;VAI SYLLABLE PEE;Lo;0;L;;;;;N;;;;;
-A506;VAI SYLLABLE BHEE;Lo;0;L;;;;;N;;;;;
-A507;VAI SYLLABLE BEE;Lo;0;L;;;;;N;;;;;
-A508;VAI SYLLABLE MBEE;Lo;0;L;;;;;N;;;;;
-A509;VAI SYLLABLE KPEE;Lo;0;L;;;;;N;;;;;
-A50A;VAI SYLLABLE MGBEE;Lo;0;L;;;;;N;;;;;
-A50B;VAI SYLLABLE GBEE;Lo;0;L;;;;;N;;;;;
-A50C;VAI SYLLABLE FEE;Lo;0;L;;;;;N;;;;;
-A50D;VAI SYLLABLE VEE;Lo;0;L;;;;;N;;;;;
-A50E;VAI SYLLABLE TEE;Lo;0;L;;;;;N;;;;;
-A50F;VAI SYLLABLE THEE;Lo;0;L;;;;;N;;;;;
-A510;VAI SYLLABLE DHEE;Lo;0;L;;;;;N;;;;;
-A511;VAI SYLLABLE DHHEE;Lo;0;L;;;;;N;;;;;
-A512;VAI SYLLABLE LEE;Lo;0;L;;;;;N;;;;;
-A513;VAI SYLLABLE REE;Lo;0;L;;;;;N;;;;;
-A514;VAI SYLLABLE DEE;Lo;0;L;;;;;N;;;;;
-A515;VAI SYLLABLE NDEE;Lo;0;L;;;;;N;;;;;
-A516;VAI SYLLABLE SEE;Lo;0;L;;;;;N;;;;;
-A517;VAI SYLLABLE SHEE;Lo;0;L;;;;;N;;;;;
-A518;VAI SYLLABLE ZEE;Lo;0;L;;;;;N;;;;;
-A519;VAI SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;;
-A51A;VAI SYLLABLE CEE;Lo;0;L;;;;;N;;;;;
-A51B;VAI SYLLABLE JEE;Lo;0;L;;;;;N;;;;;
-A51C;VAI SYLLABLE NJEE;Lo;0;L;;;;;N;;;;;
-A51D;VAI SYLLABLE YEE;Lo;0;L;;;;;N;;;;;
-A51E;VAI SYLLABLE KEE;Lo;0;L;;;;;N;;;;;
-A51F;VAI SYLLABLE NGGEE;Lo;0;L;;;;;N;;;;;
-A520;VAI SYLLABLE GEE;Lo;0;L;;;;;N;;;;;
-A521;VAI SYLLABLE MEE;Lo;0;L;;;;;N;;;;;
-A522;VAI SYLLABLE NEE;Lo;0;L;;;;;N;;;;;
-A523;VAI SYLLABLE NYEE;Lo;0;L;;;;;N;;;;;
-A524;VAI SYLLABLE I;Lo;0;L;;;;;N;;;;;
-A525;VAI SYLLABLE IN;Lo;0;L;;;;;N;;;;;
-A526;VAI SYLLABLE HI;Lo;0;L;;;;;N;;;;;
-A527;VAI SYLLABLE HIN;Lo;0;L;;;;;N;;;;;
-A528;VAI SYLLABLE WI;Lo;0;L;;;;;N;;;;;
-A529;VAI SYLLABLE WIN;Lo;0;L;;;;;N;;;;;
-A52A;VAI SYLLABLE PI;Lo;0;L;;;;;N;;;;;
-A52B;VAI SYLLABLE BHI;Lo;0;L;;;;;N;;;;;
-A52C;VAI SYLLABLE BI;Lo;0;L;;;;;N;;;;;
-A52D;VAI SYLLABLE MBI;Lo;0;L;;;;;N;;;;;
-A52E;VAI SYLLABLE KPI;Lo;0;L;;;;;N;;;;;
-A52F;VAI SYLLABLE MGBI;Lo;0;L;;;;;N;;;;;
-A530;VAI SYLLABLE GBI;Lo;0;L;;;;;N;;;;;
-A531;VAI SYLLABLE FI;Lo;0;L;;;;;N;;;;;
-A532;VAI SYLLABLE VI;Lo;0;L;;;;;N;;;;;
-A533;VAI SYLLABLE TI;Lo;0;L;;;;;N;;;;;
-A534;VAI SYLLABLE THI;Lo;0;L;;;;;N;;;;;
-A535;VAI SYLLABLE DHI;Lo;0;L;;;;;N;;;;;
-A536;VAI SYLLABLE DHHI;Lo;0;L;;;;;N;;;;;
-A537;VAI SYLLABLE LI;Lo;0;L;;;;;N;;;;;
-A538;VAI SYLLABLE RI;Lo;0;L;;;;;N;;;;;
-A539;VAI SYLLABLE DI;Lo;0;L;;;;;N;;;;;
-A53A;VAI SYLLABLE NDI;Lo;0;L;;;;;N;;;;;
-A53B;VAI SYLLABLE SI;Lo;0;L;;;;;N;;;;;
-A53C;VAI SYLLABLE SHI;Lo;0;L;;;;;N;;;;;
-A53D;VAI SYLLABLE ZI;Lo;0;L;;;;;N;;;;;
-A53E;VAI SYLLABLE ZHI;Lo;0;L;;;;;N;;;;;
-A53F;VAI SYLLABLE CI;Lo;0;L;;;;;N;;;;;
-A540;VAI SYLLABLE JI;Lo;0;L;;;;;N;;;;;
-A541;VAI SYLLABLE NJI;Lo;0;L;;;;;N;;;;;
-A542;VAI SYLLABLE YI;Lo;0;L;;;;;N;;;;;
-A543;VAI SYLLABLE KI;Lo;0;L;;;;;N;;;;;
-A544;VAI SYLLABLE NGGI;Lo;0;L;;;;;N;;;;;
-A545;VAI SYLLABLE GI;Lo;0;L;;;;;N;;;;;
-A546;VAI SYLLABLE MI;Lo;0;L;;;;;N;;;;;
-A547;VAI SYLLABLE NI;Lo;0;L;;;;;N;;;;;
-A548;VAI SYLLABLE NYI;Lo;0;L;;;;;N;;;;;
-A549;VAI SYLLABLE A;Lo;0;L;;;;;N;;;;;
-A54A;VAI SYLLABLE AN;Lo;0;L;;;;;N;;;;;
-A54B;VAI SYLLABLE NGAN;Lo;0;L;;;;;N;;;;;
-A54C;VAI SYLLABLE HA;Lo;0;L;;;;;N;;;;;
-A54D;VAI SYLLABLE HAN;Lo;0;L;;;;;N;;;;;
-A54E;VAI SYLLABLE WA;Lo;0;L;;;;;N;;;;;
-A54F;VAI SYLLABLE WAN;Lo;0;L;;;;;N;;;;;
-A550;VAI SYLLABLE PA;Lo;0;L;;;;;N;;;;;
-A551;VAI SYLLABLE BHA;Lo;0;L;;;;;N;;;;;
-A552;VAI SYLLABLE BA;Lo;0;L;;;;;N;;;;;
-A553;VAI SYLLABLE MBA;Lo;0;L;;;;;N;;;;;
-A554;VAI SYLLABLE KPA;Lo;0;L;;;;;N;;;;;
-A555;VAI SYLLABLE KPAN;Lo;0;L;;;;;N;;;;;
-A556;VAI SYLLABLE MGBA;Lo;0;L;;;;;N;;;;;
-A557;VAI SYLLABLE GBA;Lo;0;L;;;;;N;;;;;
-A558;VAI SYLLABLE FA;Lo;0;L;;;;;N;;;;;
-A559;VAI SYLLABLE VA;Lo;0;L;;;;;N;;;;;
-A55A;VAI SYLLABLE TA;Lo;0;L;;;;;N;;;;;
-A55B;VAI SYLLABLE THA;Lo;0;L;;;;;N;;;;;
-A55C;VAI SYLLABLE DHA;Lo;0;L;;;;;N;;;;;
-A55D;VAI SYLLABLE DHHA;Lo;0;L;;;;;N;;;;;
-A55E;VAI SYLLABLE LA;Lo;0;L;;;;;N;;;;;
-A55F;VAI SYLLABLE RA;Lo;0;L;;;;;N;;;;;
-A560;VAI SYLLABLE DA;Lo;0;L;;;;;N;;;;;
-A561;VAI SYLLABLE NDA;Lo;0;L;;;;;N;;;;;
-A562;VAI SYLLABLE SA;Lo;0;L;;;;;N;;;;;
-A563;VAI SYLLABLE SHA;Lo;0;L;;;;;N;;;;;
-A564;VAI SYLLABLE ZA;Lo;0;L;;;;;N;;;;;
-A565;VAI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;;
-A566;VAI SYLLABLE CA;Lo;0;L;;;;;N;;;;;
-A567;VAI SYLLABLE JA;Lo;0;L;;;;;N;;;;;
-A568;VAI SYLLABLE NJA;Lo;0;L;;;;;N;;;;;
-A569;VAI SYLLABLE YA;Lo;0;L;;;;;N;;;;;
-A56A;VAI SYLLABLE KA;Lo;0;L;;;;;N;;;;;
-A56B;VAI SYLLABLE KAN;Lo;0;L;;;;;N;;;;;
-A56C;VAI SYLLABLE NGGA;Lo;0;L;;;;;N;;;;;
-A56D;VAI SYLLABLE GA;Lo;0;L;;;;;N;;;;;
-A56E;VAI SYLLABLE MA;Lo;0;L;;;;;N;;;;;
-A56F;VAI SYLLABLE NA;Lo;0;L;;;;;N;;;;;
-A570;VAI SYLLABLE NYA;Lo;0;L;;;;;N;;;;;
-A571;VAI SYLLABLE OO;Lo;0;L;;;;;N;;;;;
-A572;VAI SYLLABLE OON;Lo;0;L;;;;;N;;;;;
-A573;VAI SYLLABLE HOO;Lo;0;L;;;;;N;;;;;
-A574;VAI SYLLABLE WOO;Lo;0;L;;;;;N;;;;;
-A575;VAI SYLLABLE WOON;Lo;0;L;;;;;N;;;;;
-A576;VAI SYLLABLE POO;Lo;0;L;;;;;N;;;;;
-A577;VAI SYLLABLE BHOO;Lo;0;L;;;;;N;;;;;
-A578;VAI SYLLABLE BOO;Lo;0;L;;;;;N;;;;;
-A579;VAI SYLLABLE MBOO;Lo;0;L;;;;;N;;;;;
-A57A;VAI SYLLABLE KPOO;Lo;0;L;;;;;N;;;;;
-A57B;VAI SYLLABLE MGBOO;Lo;0;L;;;;;N;;;;;
-A57C;VAI SYLLABLE GBOO;Lo;0;L;;;;;N;;;;;
-A57D;VAI SYLLABLE FOO;Lo;0;L;;;;;N;;;;;
-A57E;VAI SYLLABLE VOO;Lo;0;L;;;;;N;;;;;
-A57F;VAI SYLLABLE TOO;Lo;0;L;;;;;N;;;;;
-A580;VAI SYLLABLE THOO;Lo;0;L;;;;;N;;;;;
-A581;VAI SYLLABLE DHOO;Lo;0;L;;;;;N;;;;;
-A582;VAI SYLLABLE DHHOO;Lo;0;L;;;;;N;;;;;
-A583;VAI SYLLABLE LOO;Lo;0;L;;;;;N;;;;;
-A584;VAI SYLLABLE ROO;Lo;0;L;;;;;N;;;;;
-A585;VAI SYLLABLE DOO;Lo;0;L;;;;;N;;;;;
-A586;VAI SYLLABLE NDOO;Lo;0;L;;;;;N;;;;;
-A587;VAI SYLLABLE SOO;Lo;0;L;;;;;N;;;;;
-A588;VAI SYLLABLE SHOO;Lo;0;L;;;;;N;;;;;
-A589;VAI SYLLABLE ZOO;Lo;0;L;;;;;N;;;;;
-A58A;VAI SYLLABLE ZHOO;Lo;0;L;;;;;N;;;;;
-A58B;VAI SYLLABLE COO;Lo;0;L;;;;;N;;;;;
-A58C;VAI SYLLABLE JOO;Lo;0;L;;;;;N;;;;;
-A58D;VAI SYLLABLE NJOO;Lo;0;L;;;;;N;;;;;
-A58E;VAI SYLLABLE YOO;Lo;0;L;;;;;N;;;;;
-A58F;VAI SYLLABLE KOO;Lo;0;L;;;;;N;;;;;
-A590;VAI SYLLABLE NGGOO;Lo;0;L;;;;;N;;;;;
-A591;VAI SYLLABLE GOO;Lo;0;L;;;;;N;;;;;
-A592;VAI SYLLABLE MOO;Lo;0;L;;;;;N;;;;;
-A593;VAI SYLLABLE NOO;Lo;0;L;;;;;N;;;;;
-A594;VAI SYLLABLE NYOO;Lo;0;L;;;;;N;;;;;
-A595;VAI SYLLABLE U;Lo;0;L;;;;;N;;;;;
-A596;VAI SYLLABLE UN;Lo;0;L;;;;;N;;;;;
-A597;VAI SYLLABLE HU;Lo;0;L;;;;;N;;;;;
-A598;VAI SYLLABLE HUN;Lo;0;L;;;;;N;;;;;
-A599;VAI SYLLABLE WU;Lo;0;L;;;;;N;;;;;
-A59A;VAI SYLLABLE WUN;Lo;0;L;;;;;N;;;;;
-A59B;VAI SYLLABLE PU;Lo;0;L;;;;;N;;;;;
-A59C;VAI SYLLABLE BHU;Lo;0;L;;;;;N;;;;;
-A59D;VAI SYLLABLE BU;Lo;0;L;;;;;N;;;;;
-A59E;VAI SYLLABLE MBU;Lo;0;L;;;;;N;;;;;
-A59F;VAI SYLLABLE KPU;Lo;0;L;;;;;N;;;;;
-A5A0;VAI SYLLABLE MGBU;Lo;0;L;;;;;N;;;;;
-A5A1;VAI SYLLABLE GBU;Lo;0;L;;;;;N;;;;;
-A5A2;VAI SYLLABLE FU;Lo;0;L;;;;;N;;;;;
-A5A3;VAI SYLLABLE VU;Lo;0;L;;;;;N;;;;;
-A5A4;VAI SYLLABLE TU;Lo;0;L;;;;;N;;;;;
-A5A5;VAI SYLLABLE THU;Lo;0;L;;;;;N;;;;;
-A5A6;VAI SYLLABLE DHU;Lo;0;L;;;;;N;;;;;
-A5A7;VAI SYLLABLE DHHU;Lo;0;L;;;;;N;;;;;
-A5A8;VAI SYLLABLE LU;Lo;0;L;;;;;N;;;;;
-A5A9;VAI SYLLABLE RU;Lo;0;L;;;;;N;;;;;
-A5AA;VAI SYLLABLE DU;Lo;0;L;;;;;N;;;;;
-A5AB;VAI SYLLABLE NDU;Lo;0;L;;;;;N;;;;;
-A5AC;VAI SYLLABLE SU;Lo;0;L;;;;;N;;;;;
-A5AD;VAI SYLLABLE SHU;Lo;0;L;;;;;N;;;;;
-A5AE;VAI SYLLABLE ZU;Lo;0;L;;;;;N;;;;;
-A5AF;VAI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;;
-A5B0;VAI SYLLABLE CU;Lo;0;L;;;;;N;;;;;
-A5B1;VAI SYLLABLE JU;Lo;0;L;;;;;N;;;;;
-A5B2;VAI SYLLABLE NJU;Lo;0;L;;;;;N;;;;;
-A5B3;VAI SYLLABLE YU;Lo;0;L;;;;;N;;;;;
-A5B4;VAI SYLLABLE KU;Lo;0;L;;;;;N;;;;;
-A5B5;VAI SYLLABLE NGGU;Lo;0;L;;;;;N;;;;;
-A5B6;VAI SYLLABLE GU;Lo;0;L;;;;;N;;;;;
-A5B7;VAI SYLLABLE MU;Lo;0;L;;;;;N;;;;;
-A5B8;VAI SYLLABLE NU;Lo;0;L;;;;;N;;;;;
-A5B9;VAI SYLLABLE NYU;Lo;0;L;;;;;N;;;;;
-A5BA;VAI SYLLABLE O;Lo;0;L;;;;;N;;;;;
-A5BB;VAI SYLLABLE ON;Lo;0;L;;;;;N;;;;;
-A5BC;VAI SYLLABLE NGON;Lo;0;L;;;;;N;;;;;
-A5BD;VAI SYLLABLE HO;Lo;0;L;;;;;N;;;;;
-A5BE;VAI SYLLABLE HON;Lo;0;L;;;;;N;;;;;
-A5BF;VAI SYLLABLE WO;Lo;0;L;;;;;N;;;;;
-A5C0;VAI SYLLABLE WON;Lo;0;L;;;;;N;;;;;
-A5C1;VAI SYLLABLE PO;Lo;0;L;;;;;N;;;;;
-A5C2;VAI SYLLABLE BHO;Lo;0;L;;;;;N;;;;;
-A5C3;VAI SYLLABLE BO;Lo;0;L;;;;;N;;;;;
-A5C4;VAI SYLLABLE MBO;Lo;0;L;;;;;N;;;;;
-A5C5;VAI SYLLABLE KPO;Lo;0;L;;;;;N;;;;;
-A5C6;VAI SYLLABLE MGBO;Lo;0;L;;;;;N;;;;;
-A5C7;VAI SYLLABLE GBO;Lo;0;L;;;;;N;;;;;
-A5C8;VAI SYLLABLE GBON;Lo;0;L;;;;;N;;;;;
-A5C9;VAI SYLLABLE FO;Lo;0;L;;;;;N;;;;;
-A5CA;VAI SYLLABLE VO;Lo;0;L;;;;;N;;;;;
-A5CB;VAI SYLLABLE TO;Lo;0;L;;;;;N;;;;;
-A5CC;VAI SYLLABLE THO;Lo;0;L;;;;;N;;;;;
-A5CD;VAI SYLLABLE DHO;Lo;0;L;;;;;N;;;;;
-A5CE;VAI SYLLABLE DHHO;Lo;0;L;;;;;N;;;;;
-A5CF;VAI SYLLABLE LO;Lo;0;L;;;;;N;;;;;
-A5D0;VAI SYLLABLE RO;Lo;0;L;;;;;N;;;;;
-A5D1;VAI SYLLABLE DO;Lo;0;L;;;;;N;;;;;
-A5D2;VAI SYLLABLE NDO;Lo;0;L;;;;;N;;;;;
-A5D3;VAI SYLLABLE SO;Lo;0;L;;;;;N;;;;;
-A5D4;VAI SYLLABLE SHO;Lo;0;L;;;;;N;;;;;
-A5D5;VAI SYLLABLE ZO;Lo;0;L;;;;;N;;;;;
-A5D6;VAI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;;
-A5D7;VAI SYLLABLE CO;Lo;0;L;;;;;N;;;;;
-A5D8;VAI SYLLABLE JO;Lo;0;L;;;;;N;;;;;
-A5D9;VAI SYLLABLE NJO;Lo;0;L;;;;;N;;;;;
-A5DA;VAI SYLLABLE YO;Lo;0;L;;;;;N;;;;;
-A5DB;VAI SYLLABLE KO;Lo;0;L;;;;;N;;;;;
-A5DC;VAI SYLLABLE NGGO;Lo;0;L;;;;;N;;;;;
-A5DD;VAI SYLLABLE GO;Lo;0;L;;;;;N;;;;;
-A5DE;VAI SYLLABLE MO;Lo;0;L;;;;;N;;;;;
-A5DF;VAI SYLLABLE NO;Lo;0;L;;;;;N;;;;;
-A5E0;VAI SYLLABLE NYO;Lo;0;L;;;;;N;;;;;
-A5E1;VAI SYLLABLE E;Lo;0;L;;;;;N;;;;;
-A5E2;VAI SYLLABLE EN;Lo;0;L;;;;;N;;;;;
-A5E3;VAI SYLLABLE NGEN;Lo;0;L;;;;;N;;;;;
-A5E4;VAI SYLLABLE HE;Lo;0;L;;;;;N;;;;;
-A5E5;VAI SYLLABLE HEN;Lo;0;L;;;;;N;;;;;
-A5E6;VAI SYLLABLE WE;Lo;0;L;;;;;N;;;;;
-A5E7;VAI SYLLABLE WEN;Lo;0;L;;;;;N;;;;;
-A5E8;VAI SYLLABLE PE;Lo;0;L;;;;;N;;;;;
-A5E9;VAI SYLLABLE BHE;Lo;0;L;;;;;N;;;;;
-A5EA;VAI SYLLABLE BE;Lo;0;L;;;;;N;;;;;
-A5EB;VAI SYLLABLE MBE;Lo;0;L;;;;;N;;;;;
-A5EC;VAI SYLLABLE KPE;Lo;0;L;;;;;N;;;;;
-A5ED;VAI SYLLABLE KPEN;Lo;0;L;;;;;N;;;;;
-A5EE;VAI SYLLABLE MGBE;Lo;0;L;;;;;N;;;;;
-A5EF;VAI SYLLABLE GBE;Lo;0;L;;;;;N;;;;;
-A5F0;VAI SYLLABLE GBEN;Lo;0;L;;;;;N;;;;;
-A5F1;VAI SYLLABLE FE;Lo;0;L;;;;;N;;;;;
-A5F2;VAI SYLLABLE VE;Lo;0;L;;;;;N;;;;;
-A5F3;VAI SYLLABLE TE;Lo;0;L;;;;;N;;;;;
-A5F4;VAI SYLLABLE THE;Lo;0;L;;;;;N;;;;;
-A5F5;VAI SYLLABLE DHE;Lo;0;L;;;;;N;;;;;
-A5F6;VAI SYLLABLE DHHE;Lo;0;L;;;;;N;;;;;
-A5F7;VAI SYLLABLE LE;Lo;0;L;;;;;N;;;;;
-A5F8;VAI SYLLABLE RE;Lo;0;L;;;;;N;;;;;
-A5F9;VAI SYLLABLE DE;Lo;0;L;;;;;N;;;;;
-A5FA;VAI SYLLABLE NDE;Lo;0;L;;;;;N;;;;;
-A5FB;VAI SYLLABLE SE;Lo;0;L;;;;;N;;;;;
-A5FC;VAI SYLLABLE SHE;Lo;0;L;;;;;N;;;;;
-A5FD;VAI SYLLABLE ZE;Lo;0;L;;;;;N;;;;;
-A5FE;VAI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;;
-A5FF;VAI SYLLABLE CE;Lo;0;L;;;;;N;;;;;
-A600;VAI SYLLABLE JE;Lo;0;L;;;;;N;;;;;
-A601;VAI SYLLABLE NJE;Lo;0;L;;;;;N;;;;;
-A602;VAI SYLLABLE YE;Lo;0;L;;;;;N;;;;;
-A603;VAI SYLLABLE KE;Lo;0;L;;;;;N;;;;;
-A604;VAI SYLLABLE NGGE;Lo;0;L;;;;;N;;;;;
-A605;VAI SYLLABLE NGGEN;Lo;0;L;;;;;N;;;;;
-A606;VAI SYLLABLE GE;Lo;0;L;;;;;N;;;;;
-A607;VAI SYLLABLE GEN;Lo;0;L;;;;;N;;;;;
-A608;VAI SYLLABLE ME;Lo;0;L;;;;;N;;;;;
-A609;VAI SYLLABLE NE;Lo;0;L;;;;;N;;;;;
-A60A;VAI SYLLABLE NYE;Lo;0;L;;;;;N;;;;;
-A60B;VAI SYLLABLE NG;Lo;0;L;;;;;N;;;;;
-A60C;VAI SYLLABLE LENGTHENER;Lm;0;L;;;;;N;;;;;
-A60D;VAI COMMA;Po;0;ON;;;;;N;;;;;
-A60E;VAI FULL STOP;Po;0;ON;;;;;N;;;;;
-A60F;VAI QUESTION MARK;Po;0;ON;;;;;N;;;;;
-A610;VAI SYLLABLE NDOLE FA;Lo;0;L;;;;;N;;;;;
-A611;VAI SYLLABLE NDOLE KA;Lo;0;L;;;;;N;;;;;
-A612;VAI SYLLABLE NDOLE SOO;Lo;0;L;;;;;N;;;;;
-A613;VAI SYMBOL FEENG;Lo;0;L;;;;;N;;;;;
-A614;VAI SYMBOL KEENG;Lo;0;L;;;;;N;;;;;
-A615;VAI SYMBOL TING;Lo;0;L;;;;;N;;;;;
-A616;VAI SYMBOL NII;Lo;0;L;;;;;N;;;;;
-A617;VAI SYMBOL BANG;Lo;0;L;;;;;N;;;;;
-A618;VAI SYMBOL FAA;Lo;0;L;;;;;N;;;;;
-A619;VAI SYMBOL TAA;Lo;0;L;;;;;N;;;;;
-A61A;VAI SYMBOL DANG;Lo;0;L;;;;;N;;;;;
-A61B;VAI SYMBOL DOONG;Lo;0;L;;;;;N;;;;;
-A61C;VAI SYMBOL KUNG;Lo;0;L;;;;;N;;;;;
-A61D;VAI SYMBOL TONG;Lo;0;L;;;;;N;;;;;
-A61E;VAI SYMBOL DO-O;Lo;0;L;;;;;N;;;;;
-A61F;VAI SYMBOL JONG;Lo;0;L;;;;;N;;;;;
-A620;VAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-A621;VAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-A622;VAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-A623;VAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-A624;VAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-A625;VAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-A626;VAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-A627;VAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-A628;VAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-A629;VAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-A62A;VAI SYLLABLE NDOLE MA;Lo;0;L;;;;;N;;;;;
-A62B;VAI SYLLABLE NDOLE DO;Lo;0;L;;;;;N;;;;;
-A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641;
-A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640
-A642;CYRILLIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;A643;
-A643;CYRILLIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;A642;;A642
-A644;CYRILLIC CAPITAL LETTER REVERSED DZE;Lu;0;L;;;;;N;;;;A645;
-A645;CYRILLIC SMALL LETTER REVERSED DZE;Ll;0;L;;;;;N;;;A644;;A644
-A646;CYRILLIC CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;A647;
-A647;CYRILLIC SMALL LETTER IOTA;Ll;0;L;;;;;N;;;A646;;A646
-A648;CYRILLIC CAPITAL LETTER DJERV;Lu;0;L;;;;;N;;;;A649;
-A649;CYRILLIC SMALL LETTER DJERV;Ll;0;L;;;;;N;;;A648;;A648
-A64A;CYRILLIC CAPITAL LETTER MONOGRAPH UK;Lu;0;L;;;;;N;;;;A64B;
-A64B;CYRILLIC SMALL LETTER MONOGRAPH UK;Ll;0;L;;;;;N;;;A64A;;A64A
-A64C;CYRILLIC CAPITAL LETTER BROAD OMEGA;Lu;0;L;;;;;N;;;;A64D;
-A64D;CYRILLIC SMALL LETTER BROAD OMEGA;Ll;0;L;;;;;N;;;A64C;;A64C
-A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F;
-A64F;CYRILLIC SMALL LETTER NEUTRAL YER;Ll;0;L;;;;;N;;;A64E;;A64E
-A650;CYRILLIC CAPITAL LETTER YERU WITH BACK YER;Lu;0;L;;;;;N;;;;A651;
-A651;CYRILLIC SMALL LETTER YERU WITH BACK YER;Ll;0;L;;;;;N;;;A650;;A650
-A652;CYRILLIC CAPITAL LETTER IOTIFIED YAT;Lu;0;L;;;;;N;;;;A653;
-A653;CYRILLIC SMALL LETTER IOTIFIED YAT;Ll;0;L;;;;;N;;;A652;;A652
-A654;CYRILLIC CAPITAL LETTER REVERSED YU;Lu;0;L;;;;;N;;;;A655;
-A655;CYRILLIC SMALL LETTER REVERSED YU;Ll;0;L;;;;;N;;;A654;;A654
-A656;CYRILLIC CAPITAL LETTER IOTIFIED A;Lu;0;L;;;;;N;;;;A657;
-A657;CYRILLIC SMALL LETTER IOTIFIED A;Ll;0;L;;;;;N;;;A656;;A656
-A658;CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A659;
-A659;CYRILLIC SMALL LETTER CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A658;;A658
-A65A;CYRILLIC CAPITAL LETTER BLENDED YUS;Lu;0;L;;;;;N;;;;A65B;
-A65B;CYRILLIC SMALL LETTER BLENDED YUS;Ll;0;L;;;;;N;;;A65A;;A65A
-A65C;CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A65D;
-A65D;CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A65C;;A65C
-A65E;CYRILLIC CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;A65F;
-A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E
-A660;CYRILLIC CAPITAL LETTER REVERSED TSE;Lu;0;L;;;;;N;;;;A661;
-A661;CYRILLIC SMALL LETTER REVERSED TSE;Ll;0;L;;;;;N;;;A660;;A660
-A662;CYRILLIC CAPITAL LETTER SOFT DE;Lu;0;L;;;;;N;;;;A663;
-A663;CYRILLIC SMALL LETTER SOFT DE;Ll;0;L;;;;;N;;;A662;;A662
-A664;CYRILLIC CAPITAL LETTER SOFT EL;Lu;0;L;;;;;N;;;;A665;
-A665;CYRILLIC SMALL LETTER SOFT EL;Ll;0;L;;;;;N;;;A664;;A664
-A666;CYRILLIC CAPITAL LETTER SOFT EM;Lu;0;L;;;;;N;;;;A667;
-A667;CYRILLIC SMALL LETTER SOFT EM;Ll;0;L;;;;;N;;;A666;;A666
-A668;CYRILLIC CAPITAL LETTER MONOCULAR O;Lu;0;L;;;;;N;;;;A669;
-A669;CYRILLIC SMALL LETTER MONOCULAR O;Ll;0;L;;;;;N;;;A668;;A668
-A66A;CYRILLIC CAPITAL LETTER BINOCULAR O;Lu;0;L;;;;;N;;;;A66B;
-A66B;CYRILLIC SMALL LETTER BINOCULAR O;Ll;0;L;;;;;N;;;A66A;;A66A
-A66C;CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O;Lu;0;L;;;;;N;;;;A66D;
-A66D;CYRILLIC SMALL LETTER DOUBLE MONOCULAR O;Ll;0;L;;;;;N;;;A66C;;A66C
-A66E;CYRILLIC LETTER MULTIOCULAR O;Lo;0;L;;;;;N;;;;;
-A66F;COMBINING CYRILLIC VZMET;Mn;230;NSM;;;;;N;;;;;
-A670;COMBINING CYRILLIC TEN MILLIONS SIGN;Me;0;NSM;;;;;N;;;;;
-A671;COMBINING CYRILLIC HUNDRED MILLIONS SIGN;Me;0;NSM;;;;;N;;;;;
-A672;COMBINING CYRILLIC THOUSAND MILLIONS SIGN;Me;0;NSM;;;;;N;;;;;
-A673;SLAVONIC ASTERISK;Po;0;ON;;;;;N;;;;;
-A674;COMBINING CYRILLIC LETTER UKRAINIAN IE;Mn;230;NSM;;;;;N;;;;;
-A675;COMBINING CYRILLIC LETTER I;Mn;230;NSM;;;;;N;;;;;
-A676;COMBINING CYRILLIC LETTER YI;Mn;230;NSM;;;;;N;;;;;
-A677;COMBINING CYRILLIC LETTER U;Mn;230;NSM;;;;;N;;;;;
-A678;COMBINING CYRILLIC LETTER HARD SIGN;Mn;230;NSM;;;;;N;;;;;
-A679;COMBINING CYRILLIC LETTER YERU;Mn;230;NSM;;;;;N;;;;;
-A67A;COMBINING CYRILLIC LETTER SOFT SIGN;Mn;230;NSM;;;;;N;;;;;
-A67B;COMBINING CYRILLIC LETTER OMEGA;Mn;230;NSM;;;;;N;;;;;
-A67C;COMBINING CYRILLIC KAVYKA;Mn;230;NSM;;;;;N;;;;;
-A67D;COMBINING CYRILLIC PAYEROK;Mn;230;NSM;;;;;N;;;;;
-A67E;CYRILLIC KAVYKA;Po;0;ON;;;;;N;;;;;
-A67F;CYRILLIC PAYEROK;Lm;0;ON;;;;;N;;;;;
-A680;CYRILLIC CAPITAL LETTER DWE;Lu;0;L;;;;;N;;;;A681;
-A681;CYRILLIC SMALL LETTER DWE;Ll;0;L;;;;;N;;;A680;;A680
-A682;CYRILLIC CAPITAL LETTER DZWE;Lu;0;L;;;;;N;;;;A683;
-A683;CYRILLIC SMALL LETTER DZWE;Ll;0;L;;;;;N;;;A682;;A682
-A684;CYRILLIC CAPITAL LETTER ZHWE;Lu;0;L;;;;;N;;;;A685;
-A685;CYRILLIC SMALL LETTER ZHWE;Ll;0;L;;;;;N;;;A684;;A684
-A686;CYRILLIC CAPITAL LETTER CCHE;Lu;0;L;;;;;N;;;;A687;
-A687;CYRILLIC SMALL LETTER CCHE;Ll;0;L;;;;;N;;;A686;;A686
-A688;CYRILLIC CAPITAL LETTER DZZE;Lu;0;L;;;;;N;;;;A689;
-A689;CYRILLIC SMALL LETTER DZZE;Ll;0;L;;;;;N;;;A688;;A688
-A68A;CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;A68B;
-A68B;CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;A68A;;A68A
-A68C;CYRILLIC CAPITAL LETTER TWE;Lu;0;L;;;;;N;;;;A68D;
-A68D;CYRILLIC SMALL LETTER TWE;Ll;0;L;;;;;N;;;A68C;;A68C
-A68E;CYRILLIC CAPITAL LETTER TSWE;Lu;0;L;;;;;N;;;;A68F;
-A68F;CYRILLIC SMALL LETTER TSWE;Ll;0;L;;;;;N;;;A68E;;A68E
-A690;CYRILLIC CAPITAL LETTER TSSE;Lu;0;L;;;;;N;;;;A691;
-A691;CYRILLIC SMALL LETTER TSSE;Ll;0;L;;;;;N;;;A690;;A690
-A692;CYRILLIC CAPITAL LETTER TCHE;Lu;0;L;;;;;N;;;;A693;
-A693;CYRILLIC SMALL LETTER TCHE;Ll;0;L;;;;;N;;;A692;;A692
-A694;CYRILLIC CAPITAL LETTER HWE;Lu;0;L;;;;;N;;;;A695;
-A695;CYRILLIC SMALL LETTER HWE;Ll;0;L;;;;;N;;;A694;;A694
-A696;CYRILLIC CAPITAL LETTER SHWE;Lu;0;L;;;;;N;;;;A697;
-A697;CYRILLIC SMALL LETTER SHWE;Ll;0;L;;;;;N;;;A696;;A696
-A69F;COMBINING CYRILLIC LETTER IOTIFIED E;Mn;230;NSM;;;;;N;;;;;
-A6A0;BAMUM LETTER A;Lo;0;L;;;;;N;;;;;
-A6A1;BAMUM LETTER KA;Lo;0;L;;;;;N;;;;;
-A6A2;BAMUM LETTER U;Lo;0;L;;;;;N;;;;;
-A6A3;BAMUM LETTER KU;Lo;0;L;;;;;N;;;;;
-A6A4;BAMUM LETTER EE;Lo;0;L;;;;;N;;;;;
-A6A5;BAMUM LETTER REE;Lo;0;L;;;;;N;;;;;
-A6A6;BAMUM LETTER TAE;Lo;0;L;;;;;N;;;;;
-A6A7;BAMUM LETTER O;Lo;0;L;;;;;N;;;;;
-A6A8;BAMUM LETTER NYI;Lo;0;L;;;;;N;;;;;
-A6A9;BAMUM LETTER I;Lo;0;L;;;;;N;;;;;
-A6AA;BAMUM LETTER LA;Lo;0;L;;;;;N;;;;;
-A6AB;BAMUM LETTER PA;Lo;0;L;;;;;N;;;;;
-A6AC;BAMUM LETTER RII;Lo;0;L;;;;;N;;;;;
-A6AD;BAMUM LETTER RIEE;Lo;0;L;;;;;N;;;;;
-A6AE;BAMUM LETTER LEEEE;Lo;0;L;;;;;N;;;;;
-A6AF;BAMUM LETTER MEEEE;Lo;0;L;;;;;N;;;;;
-A6B0;BAMUM LETTER TAA;Lo;0;L;;;;;N;;;;;
-A6B1;BAMUM LETTER NDAA;Lo;0;L;;;;;N;;;;;
-A6B2;BAMUM LETTER NJAEM;Lo;0;L;;;;;N;;;;;
-A6B3;BAMUM LETTER M;Lo;0;L;;;;;N;;;;;
-A6B4;BAMUM LETTER SUU;Lo;0;L;;;;;N;;;;;
-A6B5;BAMUM LETTER MU;Lo;0;L;;;;;N;;;;;
-A6B6;BAMUM LETTER SHII;Lo;0;L;;;;;N;;;;;
-A6B7;BAMUM LETTER SI;Lo;0;L;;;;;N;;;;;
-A6B8;BAMUM LETTER SHEUX;Lo;0;L;;;;;N;;;;;
-A6B9;BAMUM LETTER SEUX;Lo;0;L;;;;;N;;;;;
-A6BA;BAMUM LETTER KYEE;Lo;0;L;;;;;N;;;;;
-A6BB;BAMUM LETTER KET;Lo;0;L;;;;;N;;;;;
-A6BC;BAMUM LETTER NUAE;Lo;0;L;;;;;N;;;;;
-A6BD;BAMUM LETTER NU;Lo;0;L;;;;;N;;;;;
-A6BE;BAMUM LETTER NJUAE;Lo;0;L;;;;;N;;;;;
-A6BF;BAMUM LETTER YOQ;Lo;0;L;;;;;N;;;;;
-A6C0;BAMUM LETTER SHU;Lo;0;L;;;;;N;;;;;
-A6C1;BAMUM LETTER YUQ;Lo;0;L;;;;;N;;;;;
-A6C2;BAMUM LETTER YA;Lo;0;L;;;;;N;;;;;
-A6C3;BAMUM LETTER NSHA;Lo;0;L;;;;;N;;;;;
-A6C4;BAMUM LETTER KEUX;Lo;0;L;;;;;N;;;;;
-A6C5;BAMUM LETTER PEUX;Lo;0;L;;;;;N;;;;;
-A6C6;BAMUM LETTER NJEE;Lo;0;L;;;;;N;;;;;
-A6C7;BAMUM LETTER NTEE;Lo;0;L;;;;;N;;;;;
-A6C8;BAMUM LETTER PUE;Lo;0;L;;;;;N;;;;;
-A6C9;BAMUM LETTER WUE;Lo;0;L;;;;;N;;;;;
-A6CA;BAMUM LETTER PEE;Lo;0;L;;;;;N;;;;;
-A6CB;BAMUM LETTER FEE;Lo;0;L;;;;;N;;;;;
-A6CC;BAMUM LETTER RU;Lo;0;L;;;;;N;;;;;
-A6CD;BAMUM LETTER LU;Lo;0;L;;;;;N;;;;;
-A6CE;BAMUM LETTER MI;Lo;0;L;;;;;N;;;;;
-A6CF;BAMUM LETTER NI;Lo;0;L;;;;;N;;;;;
-A6D0;BAMUM LETTER REUX;Lo;0;L;;;;;N;;;;;
-A6D1;BAMUM LETTER RAE;Lo;0;L;;;;;N;;;;;
-A6D2;BAMUM LETTER KEN;Lo;0;L;;;;;N;;;;;
-A6D3;BAMUM LETTER NGKWAEN;Lo;0;L;;;;;N;;;;;
-A6D4;BAMUM LETTER NGGA;Lo;0;L;;;;;N;;;;;
-A6D5;BAMUM LETTER NGA;Lo;0;L;;;;;N;;;;;
-A6D6;BAMUM LETTER SHO;Lo;0;L;;;;;N;;;;;
-A6D7;BAMUM LETTER PUAE;Lo;0;L;;;;;N;;;;;
-A6D8;BAMUM LETTER FU;Lo;0;L;;;;;N;;;;;
-A6D9;BAMUM LETTER FOM;Lo;0;L;;;;;N;;;;;
-A6DA;BAMUM LETTER WA;Lo;0;L;;;;;N;;;;;
-A6DB;BAMUM LETTER NA;Lo;0;L;;;;;N;;;;;
-A6DC;BAMUM LETTER LI;Lo;0;L;;;;;N;;;;;
-A6DD;BAMUM LETTER PI;Lo;0;L;;;;;N;;;;;
-A6DE;BAMUM LETTER LOQ;Lo;0;L;;;;;N;;;;;
-A6DF;BAMUM LETTER KO;Lo;0;L;;;;;N;;;;;
-A6E0;BAMUM LETTER MBEN;Lo;0;L;;;;;N;;;;;
-A6E1;BAMUM LETTER REN;Lo;0;L;;;;;N;;;;;
-A6E2;BAMUM LETTER MEN;Lo;0;L;;;;;N;;;;;
-A6E3;BAMUM LETTER MA;Lo;0;L;;;;;N;;;;;
-A6E4;BAMUM LETTER TI;Lo;0;L;;;;;N;;;;;
-A6E5;BAMUM LETTER KI;Lo;0;L;;;;;N;;;;;
-A6E6;BAMUM LETTER MO;Nl;0;L;;;;1;N;;;;;
-A6E7;BAMUM LETTER MBAA;Nl;0;L;;;;2;N;;;;;
-A6E8;BAMUM LETTER TET;Nl;0;L;;;;3;N;;;;;
-A6E9;BAMUM LETTER KPA;Nl;0;L;;;;4;N;;;;;
-A6EA;BAMUM LETTER TEN;Nl;0;L;;;;5;N;;;;;
-A6EB;BAMUM LETTER NTUU;Nl;0;L;;;;6;N;;;;;
-A6EC;BAMUM LETTER SAMBA;Nl;0;L;;;;7;N;;;;;
-A6ED;BAMUM LETTER FAAMAE;Nl;0;L;;;;8;N;;;;;
-A6EE;BAMUM LETTER KOVUU;Nl;0;L;;;;9;N;;;;;
-A6EF;BAMUM LETTER KOGHOM;Nl;0;L;;;;0;N;;;;;
-A6F0;BAMUM COMBINING MARK KOQNDON;Mn;230;NSM;;;;;N;;;;;
-A6F1;BAMUM COMBINING MARK TUKWENTIS;Mn;230;NSM;;;;;N;;;;;
-A6F2;BAMUM NJAEMLI;Po;0;L;;;;;N;;;;;
-A6F3;BAMUM FULL STOP;Po;0;L;;;;;N;;;;;
-A6F4;BAMUM COLON;Po;0;L;;;;;N;;;;;
-A6F5;BAMUM COMMA;Po;0;L;;;;;N;;;;;
-A6F6;BAMUM SEMICOLON;Po;0;L;;;;;N;;;;;
-A6F7;BAMUM QUESTION MARK;Po;0;L;;;;;N;;;;;
-A700;MODIFIER LETTER CHINESE TONE YIN PING;Sk;0;ON;;;;;N;;;;;
-A701;MODIFIER LETTER CHINESE TONE YANG PING;Sk;0;ON;;;;;N;;;;;
-A702;MODIFIER LETTER CHINESE TONE YIN SHANG;Sk;0;ON;;;;;N;;;;;
-A703;MODIFIER LETTER CHINESE TONE YANG SHANG;Sk;0;ON;;;;;N;;;;;
-A704;MODIFIER LETTER CHINESE TONE YIN QU;Sk;0;ON;;;;;N;;;;;
-A705;MODIFIER LETTER CHINESE TONE YANG QU;Sk;0;ON;;;;;N;;;;;
-A706;MODIFIER LETTER CHINESE TONE YIN RU;Sk;0;ON;;;;;N;;;;;
-A707;MODIFIER LETTER CHINESE TONE YANG RU;Sk;0;ON;;;;;N;;;;;
-A708;MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
-A709;MODIFIER LETTER HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
-A70A;MODIFIER LETTER MID DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
-A70B;MODIFIER LETTER LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
-A70C;MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
-A70D;MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A70E;MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A70F;MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A710;MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A711;MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A712;MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A713;MODIFIER LETTER HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A714;MODIFIER LETTER MID LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A715;MODIFIER LETTER LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A716;MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
-A717;MODIFIER LETTER DOT VERTICAL BAR;Lm;0;ON;;;;;N;;;;;
-A718;MODIFIER LETTER DOT SLASH;Lm;0;ON;;;;;N;;;;;
-A719;MODIFIER LETTER DOT HORIZONTAL BAR;Lm;0;ON;;;;;N;;;;;
-A71A;MODIFIER LETTER LOWER RIGHT CORNER ANGLE;Lm;0;ON;;;;;N;;;;;
-A71B;MODIFIER LETTER RAISED UP ARROW;Lm;0;ON;;;;;N;;;;;
-A71C;MODIFIER LETTER RAISED DOWN ARROW;Lm;0;ON;;;;;N;;;;;
-A71D;MODIFIER LETTER RAISED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;;
-A71E;MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;;
-A71F;MODIFIER LETTER LOW INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;;
-A720;MODIFIER LETTER STRESS AND HIGH TONE;Sk;0;ON;;;;;N;;;;;
-A721;MODIFIER LETTER STRESS AND LOW TONE;Sk;0;ON;;;;;N;;;;;
-A722;LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF;Lu;0;L;;;;;N;;;;A723;
-A723;LATIN SMALL LETTER EGYPTOLOGICAL ALEF;Ll;0;L;;;;;N;;;A722;;A722
-A724;LATIN CAPITAL LETTER EGYPTOLOGICAL AIN;Lu;0;L;;;;;N;;;;A725;
-A725;LATIN SMALL LETTER EGYPTOLOGICAL AIN;Ll;0;L;;;;;N;;;A724;;A724
-A726;LATIN CAPITAL LETTER HENG;Lu;0;L;;;;;N;;;;A727;
-A727;LATIN SMALL LETTER HENG;Ll;0;L;;;;;N;;;A726;;A726
-A728;LATIN CAPITAL LETTER TZ;Lu;0;L;;;;;N;;;;A729;
-A729;LATIN SMALL LETTER TZ;Ll;0;L;;;;;N;;;A728;;A728
-A72A;LATIN CAPITAL LETTER TRESILLO;Lu;0;L;;;;;N;;;;A72B;
-A72B;LATIN SMALL LETTER TRESILLO;Ll;0;L;;;;;N;;;A72A;;A72A
-A72C;LATIN CAPITAL LETTER CUATRILLO;Lu;0;L;;;;;N;;;;A72D;
-A72D;LATIN SMALL LETTER CUATRILLO;Ll;0;L;;;;;N;;;A72C;;A72C
-A72E;LATIN CAPITAL LETTER CUATRILLO WITH COMMA;Lu;0;L;;;;;N;;;;A72F;
-A72F;LATIN SMALL LETTER CUATRILLO WITH COMMA;Ll;0;L;;;;;N;;;A72E;;A72E
-A730;LATIN LETTER SMALL CAPITAL F;Ll;0;L;;;;;N;;;;;
-A731;LATIN LETTER SMALL CAPITAL S;Ll;0;L;;;;;N;;;;;
-A732;LATIN CAPITAL LETTER AA;Lu;0;L;;;;;N;;;;A733;
-A733;LATIN SMALL LETTER AA;Ll;0;L;;;;;N;;;A732;;A732
-A734;LATIN CAPITAL LETTER AO;Lu;0;L;;;;;N;;;;A735;
-A735;LATIN SMALL LETTER AO;Ll;0;L;;;;;N;;;A734;;A734
-A736;LATIN CAPITAL LETTER AU;Lu;0;L;;;;;N;;;;A737;
-A737;LATIN SMALL LETTER AU;Ll;0;L;;;;;N;;;A736;;A736
-A738;LATIN CAPITAL LETTER AV;Lu;0;L;;;;;N;;;;A739;
-A739;LATIN SMALL LETTER AV;Ll;0;L;;;;;N;;;A738;;A738
-A73A;LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR;Lu;0;L;;;;;N;;;;A73B;
-A73B;LATIN SMALL LETTER AV WITH HORIZONTAL BAR;Ll;0;L;;;;;N;;;A73A;;A73A
-A73C;LATIN CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;A73D;
-A73D;LATIN SMALL LETTER AY;Ll;0;L;;;;;N;;;A73C;;A73C
-A73E;LATIN CAPITAL LETTER REVERSED C WITH DOT;Lu;0;L;;;;;N;;;;A73F;
-A73F;LATIN SMALL LETTER REVERSED C WITH DOT;Ll;0;L;;;;;N;;;A73E;;A73E
-A740;LATIN CAPITAL LETTER K WITH STROKE;Lu;0;L;;;;;N;;;;A741;
-A741;LATIN SMALL LETTER K WITH STROKE;Ll;0;L;;;;;N;;;A740;;A740
-A742;LATIN CAPITAL LETTER K WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A743;
-A743;LATIN SMALL LETTER K WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A742;;A742
-A744;LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A745;
-A745;LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE;Ll;0;L;;;;;N;;;A744;;A744
-A746;LATIN CAPITAL LETTER BROKEN L;Lu;0;L;;;;;N;;;;A747;
-A747;LATIN SMALL LETTER BROKEN L;Ll;0;L;;;;;N;;;A746;;A746
-A748;LATIN CAPITAL LETTER L WITH HIGH STROKE;Lu;0;L;;;;;N;;;;A749;
-A749;LATIN SMALL LETTER L WITH HIGH STROKE;Ll;0;L;;;;;N;;;A748;;A748
-A74A;LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY;Lu;0;L;;;;;N;;;;A74B;
-A74B;LATIN SMALL LETTER O WITH LONG STROKE OVERLAY;Ll;0;L;;;;;N;;;A74A;;A74A
-A74C;LATIN CAPITAL LETTER O WITH LOOP;Lu;0;L;;;;;N;;;;A74D;
-A74D;LATIN SMALL LETTER O WITH LOOP;Ll;0;L;;;;;N;;;A74C;;A74C
-A74E;LATIN CAPITAL LETTER OO;Lu;0;L;;;;;N;;;;A74F;
-A74F;LATIN SMALL LETTER OO;Ll;0;L;;;;;N;;;A74E;;A74E
-A750;LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A751;
-A751;LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A750;;A750
-A752;LATIN CAPITAL LETTER P WITH FLOURISH;Lu;0;L;;;;;N;;;;A753;
-A753;LATIN SMALL LETTER P WITH FLOURISH;Ll;0;L;;;;;N;;;A752;;A752
-A754;LATIN CAPITAL LETTER P WITH SQUIRREL TAIL;Lu;0;L;;;;;N;;;;A755;
-A755;LATIN SMALL LETTER P WITH SQUIRREL TAIL;Ll;0;L;;;;;N;;;A754;;A754
-A756;LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A757;
-A757;LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A756;;A756
-A758;LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A759;
-A759;LATIN SMALL LETTER Q WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A758;;A758
-A75A;LATIN CAPITAL LETTER R ROTUNDA;Lu;0;L;;;;;N;;;;A75B;
-A75B;LATIN SMALL LETTER R ROTUNDA;Ll;0;L;;;;;N;;;A75A;;A75A
-A75C;LATIN CAPITAL LETTER RUM ROTUNDA;Lu;0;L;;;;;N;;;;A75D;
-A75D;LATIN SMALL LETTER RUM ROTUNDA;Ll;0;L;;;;;N;;;A75C;;A75C
-A75E;LATIN CAPITAL LETTER V WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A75F;
-A75F;LATIN SMALL LETTER V WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A75E;;A75E
-A760;LATIN CAPITAL LETTER VY;Lu;0;L;;;;;N;;;;A761;
-A761;LATIN SMALL LETTER VY;Ll;0;L;;;;;N;;;A760;;A760
-A762;LATIN CAPITAL LETTER VISIGOTHIC Z;Lu;0;L;;;;;N;;;;A763;
-A763;LATIN SMALL LETTER VISIGOTHIC Z;Ll;0;L;;;;;N;;;A762;;A762
-A764;LATIN CAPITAL LETTER THORN WITH STROKE;Lu;0;L;;;;;N;;;;A765;
-A765;LATIN SMALL LETTER THORN WITH STROKE;Ll;0;L;;;;;N;;;A764;;A764
-A766;LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A767;
-A767;LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A766;;A766
-A768;LATIN CAPITAL LETTER VEND;Lu;0;L;;;;;N;;;;A769;
-A769;LATIN SMALL LETTER VEND;Ll;0;L;;;;;N;;;A768;;A768
-A76A;LATIN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;A76B;
-A76B;LATIN SMALL LETTER ET;Ll;0;L;;;;;N;;;A76A;;A76A
-A76C;LATIN CAPITAL LETTER IS;Lu;0;L;;;;;N;;;;A76D;
-A76D;LATIN SMALL LETTER IS;Ll;0;L;;;;;N;;;A76C;;A76C
-A76E;LATIN CAPITAL LETTER CON;Lu;0;L;;;;;N;;;;A76F;
-A76F;LATIN SMALL LETTER CON;Ll;0;L;;;;;N;;;A76E;;A76E
-A770;MODIFIER LETTER US;Lm;0;L;<super> A76F;;;;N;;;;;
-A771;LATIN SMALL LETTER DUM;Ll;0;L;;;;;N;;;;;
-A772;LATIN SMALL LETTER LUM;Ll;0;L;;;;;N;;;;;
-A773;LATIN SMALL LETTER MUM;Ll;0;L;;;;;N;;;;;
-A774;LATIN SMALL LETTER NUM;Ll;0;L;;;;;N;;;;;
-A775;LATIN SMALL LETTER RUM;Ll;0;L;;;;;N;;;;;
-A776;LATIN LETTER SMALL CAPITAL RUM;Ll;0;L;;;;;N;;;;;
-A777;LATIN SMALL LETTER TUM;Ll;0;L;;;;;N;;;;;
-A778;LATIN SMALL LETTER UM;Ll;0;L;;;;;N;;;;;
-A779;LATIN CAPITAL LETTER INSULAR D;Lu;0;L;;;;;N;;;;A77A;
-A77A;LATIN SMALL LETTER INSULAR D;Ll;0;L;;;;;N;;;A779;;A779
-A77B;LATIN CAPITAL LETTER INSULAR F;Lu;0;L;;;;;N;;;;A77C;
-A77C;LATIN SMALL LETTER INSULAR F;Ll;0;L;;;;;N;;;A77B;;A77B
-A77D;LATIN CAPITAL LETTER INSULAR G;Lu;0;L;;;;;N;;;;1D79;
-A77E;LATIN CAPITAL LETTER TURNED INSULAR G;Lu;0;L;;;;;N;;;;A77F;
-A77F;LATIN SMALL LETTER TURNED INSULAR G;Ll;0;L;;;;;N;;;A77E;;A77E
-A780;LATIN CAPITAL LETTER TURNED L;Lu;0;L;;;;;N;;;;A781;
-A781;LATIN SMALL LETTER TURNED L;Ll;0;L;;;;;N;;;A780;;A780
-A782;LATIN CAPITAL LETTER INSULAR R;Lu;0;L;;;;;N;;;;A783;
-A783;LATIN SMALL LETTER INSULAR R;Ll;0;L;;;;;N;;;A782;;A782
-A784;LATIN CAPITAL LETTER INSULAR S;Lu;0;L;;;;;N;;;;A785;
-A785;LATIN SMALL LETTER INSULAR S;Ll;0;L;;;;;N;;;A784;;A784
-A786;LATIN CAPITAL LETTER INSULAR T;Lu;0;L;;;;;N;;;;A787;
-A787;LATIN SMALL LETTER INSULAR T;Ll;0;L;;;;;N;;;A786;;A786
-A788;MODIFIER LETTER LOW CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;;;;;
-A789;MODIFIER LETTER COLON;Sk;0;L;;;;;N;;;;;
-A78A;MODIFIER LETTER SHORT EQUALS SIGN;Sk;0;L;;;;;N;;;;;
-A78B;LATIN CAPITAL LETTER SALTILLO;Lu;0;L;;;;;N;;;;A78C;
-A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B
-A78D;LATIN CAPITAL LETTER TURNED H;Lu;0;L;;;;;N;;;;0265;
-A78E;LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT;Ll;0;L;;;;;N;;;;;
-A790;LATIN CAPITAL LETTER N WITH DESCENDER;Lu;0;L;;;;;N;;;;A791;
-A791;LATIN SMALL LETTER N WITH DESCENDER;Ll;0;L;;;;;N;;;A790;;A790
-A792;LATIN CAPITAL LETTER C WITH BAR;Lu;0;L;;;;;N;;;;A793;
-A793;LATIN SMALL LETTER C WITH BAR;Ll;0;L;;;;;N;;;A792;;A792
-A7A0;LATIN CAPITAL LETTER G WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A1;
-A7A1;LATIN SMALL LETTER G WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A0;;A7A0
-A7A2;LATIN CAPITAL LETTER K WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A3;
-A7A3;LATIN SMALL LETTER K WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A2;;A7A2
-A7A4;LATIN CAPITAL LETTER N WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A5;
-A7A5;LATIN SMALL LETTER N WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A4;;A7A4
-A7A6;LATIN CAPITAL LETTER R WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A7;
-A7A7;LATIN SMALL LETTER R WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A6;;A7A6
-A7A8;LATIN CAPITAL LETTER S WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A9;
-A7A9;LATIN SMALL LETTER S WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A8;;A7A8
-A7AA;LATIN CAPITAL LETTER H WITH HOOK;Lu;0;L;;;;;N;;;;0266;
-A7F8;MODIFIER LETTER CAPITAL H WITH STROKE;Lm;0;L;<super> 0126;;;;N;;;;;
-A7F9;MODIFIER LETTER SMALL LIGATURE OE;Lm;0;L;<super> 0153;;;;N;;;;;
-A7FA;LATIN LETTER SMALL CAPITAL TURNED M;Ll;0;L;;;;;N;;;;;
-A7FB;LATIN EPIGRAPHIC LETTER REVERSED F;Lo;0;L;;;;;N;;;;;
-A7FC;LATIN EPIGRAPHIC LETTER REVERSED P;Lo;0;L;;;;;N;;;;;
-A7FD;LATIN EPIGRAPHIC LETTER INVERTED M;Lo;0;L;;;;;N;;;;;
-A7FE;LATIN EPIGRAPHIC LETTER I LONGA;Lo;0;L;;;;;N;;;;;
-A7FF;LATIN EPIGRAPHIC LETTER ARCHAIC M;Lo;0;L;;;;;N;;;;;
-A800;SYLOTI NAGRI LETTER A;Lo;0;L;;;;;N;;;;;
-A801;SYLOTI NAGRI LETTER I;Lo;0;L;;;;;N;;;;;
-A802;SYLOTI NAGRI SIGN DVISVARA;Mn;0;NSM;;;;;N;;;;;
-A803;SYLOTI NAGRI LETTER U;Lo;0;L;;;;;N;;;;;
-A804;SYLOTI NAGRI LETTER E;Lo;0;L;;;;;N;;;;;
-A805;SYLOTI NAGRI LETTER O;Lo;0;L;;;;;N;;;;;
-A806;SYLOTI NAGRI SIGN HASANTA;Mn;9;NSM;;;;;N;;;;;
-A807;SYLOTI NAGRI LETTER KO;Lo;0;L;;;;;N;;;;;
-A808;SYLOTI NAGRI LETTER KHO;Lo;0;L;;;;;N;;;;;
-A809;SYLOTI NAGRI LETTER GO;Lo;0;L;;;;;N;;;;;
-A80A;SYLOTI NAGRI LETTER GHO;Lo;0;L;;;;;N;;;;;
-A80B;SYLOTI NAGRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-A80C;SYLOTI NAGRI LETTER CO;Lo;0;L;;;;;N;;;;;
-A80D;SYLOTI NAGRI LETTER CHO;Lo;0;L;;;;;N;;;;;
-A80E;SYLOTI NAGRI LETTER JO;Lo;0;L;;;;;N;;;;;
-A80F;SYLOTI NAGRI LETTER JHO;Lo;0;L;;;;;N;;;;;
-A810;SYLOTI NAGRI LETTER TTO;Lo;0;L;;;;;N;;;;;
-A811;SYLOTI NAGRI LETTER TTHO;Lo;0;L;;;;;N;;;;;
-A812;SYLOTI NAGRI LETTER DDO;Lo;0;L;;;;;N;;;;;
-A813;SYLOTI NAGRI LETTER DDHO;Lo;0;L;;;;;N;;;;;
-A814;SYLOTI NAGRI LETTER TO;Lo;0;L;;;;;N;;;;;
-A815;SYLOTI NAGRI LETTER THO;Lo;0;L;;;;;N;;;;;
-A816;SYLOTI NAGRI LETTER DO;Lo;0;L;;;;;N;;;;;
-A817;SYLOTI NAGRI LETTER DHO;Lo;0;L;;;;;N;;;;;
-A818;SYLOTI NAGRI LETTER NO;Lo;0;L;;;;;N;;;;;
-A819;SYLOTI NAGRI LETTER PO;Lo;0;L;;;;;N;;;;;
-A81A;SYLOTI NAGRI LETTER PHO;Lo;0;L;;;;;N;;;;;
-A81B;SYLOTI NAGRI LETTER BO;Lo;0;L;;;;;N;;;;;
-A81C;SYLOTI NAGRI LETTER BHO;Lo;0;L;;;;;N;;;;;
-A81D;SYLOTI NAGRI LETTER MO;Lo;0;L;;;;;N;;;;;
-A81E;SYLOTI NAGRI LETTER RO;Lo;0;L;;;;;N;;;;;
-A81F;SYLOTI NAGRI LETTER LO;Lo;0;L;;;;;N;;;;;
-A820;SYLOTI NAGRI LETTER RRO;Lo;0;L;;;;;N;;;;;
-A821;SYLOTI NAGRI LETTER SO;Lo;0;L;;;;;N;;;;;
-A822;SYLOTI NAGRI LETTER HO;Lo;0;L;;;;;N;;;;;
-A823;SYLOTI NAGRI VOWEL SIGN A;Mc;0;L;;;;;N;;;;;
-A824;SYLOTI NAGRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-A825;SYLOTI NAGRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-A826;SYLOTI NAGRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-A827;SYLOTI NAGRI VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
-A828;SYLOTI NAGRI POETRY MARK-1;So;0;ON;;;;;N;;;;;
-A829;SYLOTI NAGRI POETRY MARK-2;So;0;ON;;;;;N;;;;;
-A82A;SYLOTI NAGRI POETRY MARK-3;So;0;ON;;;;;N;;;;;
-A82B;SYLOTI NAGRI POETRY MARK-4;So;0;ON;;;;;N;;;;;
-A830;NORTH INDIC FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;;
-A831;NORTH INDIC FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;;
-A832;NORTH INDIC FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;;
-A833;NORTH INDIC FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;;
-A834;NORTH INDIC FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;;
-A835;NORTH INDIC FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;;
-A836;NORTH INDIC QUARTER MARK;So;0;L;;;;;N;;;;;
-A837;NORTH INDIC PLACEHOLDER MARK;So;0;L;;;;;N;;;;;
-A838;NORTH INDIC RUPEE MARK;Sc;0;ET;;;;;N;;;;;
-A839;NORTH INDIC QUANTITY MARK;So;0;ET;;;;;N;;;;;
-A840;PHAGS-PA LETTER KA;Lo;0;L;;;;;N;;;;;
-A841;PHAGS-PA LETTER KHA;Lo;0;L;;;;;N;;;;;
-A842;PHAGS-PA LETTER GA;Lo;0;L;;;;;N;;;;;
-A843;PHAGS-PA LETTER NGA;Lo;0;L;;;;;N;;;;;
-A844;PHAGS-PA LETTER CA;Lo;0;L;;;;;N;;;;;
-A845;PHAGS-PA LETTER CHA;Lo;0;L;;;;;N;;;;;
-A846;PHAGS-PA LETTER JA;Lo;0;L;;;;;N;;;;;
-A847;PHAGS-PA LETTER NYA;Lo;0;L;;;;;N;;;;;
-A848;PHAGS-PA LETTER TA;Lo;0;L;;;;;N;;;;;
-A849;PHAGS-PA LETTER THA;Lo;0;L;;;;;N;;;;;
-A84A;PHAGS-PA LETTER DA;Lo;0;L;;;;;N;;;;;
-A84B;PHAGS-PA LETTER NA;Lo;0;L;;;;;N;;;;;
-A84C;PHAGS-PA LETTER PA;Lo;0;L;;;;;N;;;;;
-A84D;PHAGS-PA LETTER PHA;Lo;0;L;;;;;N;;;;;
-A84E;PHAGS-PA LETTER BA;Lo;0;L;;;;;N;;;;;
-A84F;PHAGS-PA LETTER MA;Lo;0;L;;;;;N;;;;;
-A850;PHAGS-PA LETTER TSA;Lo;0;L;;;;;N;;;;;
-A851;PHAGS-PA LETTER TSHA;Lo;0;L;;;;;N;;;;;
-A852;PHAGS-PA LETTER DZA;Lo;0;L;;;;;N;;;;;
-A853;PHAGS-PA LETTER WA;Lo;0;L;;;;;N;;;;;
-A854;PHAGS-PA LETTER ZHA;Lo;0;L;;;;;N;;;;;
-A855;PHAGS-PA LETTER ZA;Lo;0;L;;;;;N;;;;;
-A856;PHAGS-PA LETTER SMALL A;Lo;0;L;;;;;N;;;;;
-A857;PHAGS-PA LETTER YA;Lo;0;L;;;;;N;;;;;
-A858;PHAGS-PA LETTER RA;Lo;0;L;;;;;N;;;;;
-A859;PHAGS-PA LETTER LA;Lo;0;L;;;;;N;;;;;
-A85A;PHAGS-PA LETTER SHA;Lo;0;L;;;;;N;;;;;
-A85B;PHAGS-PA LETTER SA;Lo;0;L;;;;;N;;;;;
-A85C;PHAGS-PA LETTER HA;Lo;0;L;;;;;N;;;;;
-A85D;PHAGS-PA LETTER A;Lo;0;L;;;;;N;;;;;
-A85E;PHAGS-PA LETTER I;Lo;0;L;;;;;N;;;;;
-A85F;PHAGS-PA LETTER U;Lo;0;L;;;;;N;;;;;
-A860;PHAGS-PA LETTER E;Lo;0;L;;;;;N;;;;;
-A861;PHAGS-PA LETTER O;Lo;0;L;;;;;N;;;;;
-A862;PHAGS-PA LETTER QA;Lo;0;L;;;;;N;;;;;
-A863;PHAGS-PA LETTER XA;Lo;0;L;;;;;N;;;;;
-A864;PHAGS-PA LETTER FA;Lo;0;L;;;;;N;;;;;
-A865;PHAGS-PA LETTER GGA;Lo;0;L;;;;;N;;;;;
-A866;PHAGS-PA LETTER EE;Lo;0;L;;;;;N;;;;;
-A867;PHAGS-PA SUBJOINED LETTER WA;Lo;0;L;;;;;N;;;;;
-A868;PHAGS-PA SUBJOINED LETTER YA;Lo;0;L;;;;;N;;;;;
-A869;PHAGS-PA LETTER TTA;Lo;0;L;;;;;N;;;;;
-A86A;PHAGS-PA LETTER TTHA;Lo;0;L;;;;;N;;;;;
-A86B;PHAGS-PA LETTER DDA;Lo;0;L;;;;;N;;;;;
-A86C;PHAGS-PA LETTER NNA;Lo;0;L;;;;;N;;;;;
-A86D;PHAGS-PA LETTER ALTERNATE YA;Lo;0;L;;;;;N;;;;;
-A86E;PHAGS-PA LETTER VOICELESS SHA;Lo;0;L;;;;;N;;;;;
-A86F;PHAGS-PA LETTER VOICED HA;Lo;0;L;;;;;N;;;;;
-A870;PHAGS-PA LETTER ASPIRATED FA;Lo;0;L;;;;;N;;;;;
-A871;PHAGS-PA SUBJOINED LETTER RA;Lo;0;L;;;;;N;;;;;
-A872;PHAGS-PA SUPERFIXED LETTER RA;Lo;0;L;;;;;N;;;;;
-A873;PHAGS-PA LETTER CANDRABINDU;Lo;0;L;;;;;N;;;;;
-A874;PHAGS-PA SINGLE HEAD MARK;Po;0;ON;;;;;N;;;;;
-A875;PHAGS-PA DOUBLE HEAD MARK;Po;0;ON;;;;;N;;;;;
-A876;PHAGS-PA MARK SHAD;Po;0;ON;;;;;N;;;;;
-A877;PHAGS-PA MARK DOUBLE SHAD;Po;0;ON;;;;;N;;;;;
-A880;SAURASHTRA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
-A881;SAURASHTRA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-A882;SAURASHTRA LETTER A;Lo;0;L;;;;;N;;;;;
-A883;SAURASHTRA LETTER AA;Lo;0;L;;;;;N;;;;;
-A884;SAURASHTRA LETTER I;Lo;0;L;;;;;N;;;;;
-A885;SAURASHTRA LETTER II;Lo;0;L;;;;;N;;;;;
-A886;SAURASHTRA LETTER U;Lo;0;L;;;;;N;;;;;
-A887;SAURASHTRA LETTER UU;Lo;0;L;;;;;N;;;;;
-A888;SAURASHTRA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-A889;SAURASHTRA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-A88A;SAURASHTRA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-A88B;SAURASHTRA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-A88C;SAURASHTRA LETTER E;Lo;0;L;;;;;N;;;;;
-A88D;SAURASHTRA LETTER EE;Lo;0;L;;;;;N;;;;;
-A88E;SAURASHTRA LETTER AI;Lo;0;L;;;;;N;;;;;
-A88F;SAURASHTRA LETTER O;Lo;0;L;;;;;N;;;;;
-A890;SAURASHTRA LETTER OO;Lo;0;L;;;;;N;;;;;
-A891;SAURASHTRA LETTER AU;Lo;0;L;;;;;N;;;;;
-A892;SAURASHTRA LETTER KA;Lo;0;L;;;;;N;;;;;
-A893;SAURASHTRA LETTER KHA;Lo;0;L;;;;;N;;;;;
-A894;SAURASHTRA LETTER GA;Lo;0;L;;;;;N;;;;;
-A895;SAURASHTRA LETTER GHA;Lo;0;L;;;;;N;;;;;
-A896;SAURASHTRA LETTER NGA;Lo;0;L;;;;;N;;;;;
-A897;SAURASHTRA LETTER CA;Lo;0;L;;;;;N;;;;;
-A898;SAURASHTRA LETTER CHA;Lo;0;L;;;;;N;;;;;
-A899;SAURASHTRA LETTER JA;Lo;0;L;;;;;N;;;;;
-A89A;SAURASHTRA LETTER JHA;Lo;0;L;;;;;N;;;;;
-A89B;SAURASHTRA LETTER NYA;Lo;0;L;;;;;N;;;;;
-A89C;SAURASHTRA LETTER TTA;Lo;0;L;;;;;N;;;;;
-A89D;SAURASHTRA LETTER TTHA;Lo;0;L;;;;;N;;;;;
-A89E;SAURASHTRA LETTER DDA;Lo;0;L;;;;;N;;;;;
-A89F;SAURASHTRA LETTER DDHA;Lo;0;L;;;;;N;;;;;
-A8A0;SAURASHTRA LETTER NNA;Lo;0;L;;;;;N;;;;;
-A8A1;SAURASHTRA LETTER TA;Lo;0;L;;;;;N;;;;;
-A8A2;SAURASHTRA LETTER THA;Lo;0;L;;;;;N;;;;;
-A8A3;SAURASHTRA LETTER DA;Lo;0;L;;;;;N;;;;;
-A8A4;SAURASHTRA LETTER DHA;Lo;0;L;;;;;N;;;;;
-A8A5;SAURASHTRA LETTER NA;Lo;0;L;;;;;N;;;;;
-A8A6;SAURASHTRA LETTER PA;Lo;0;L;;;;;N;;;;;
-A8A7;SAURASHTRA LETTER PHA;Lo;0;L;;;;;N;;;;;
-A8A8;SAURASHTRA LETTER BA;Lo;0;L;;;;;N;;;;;
-A8A9;SAURASHTRA LETTER BHA;Lo;0;L;;;;;N;;;;;
-A8AA;SAURASHTRA LETTER MA;Lo;0;L;;;;;N;;;;;
-A8AB;SAURASHTRA LETTER YA;Lo;0;L;;;;;N;;;;;
-A8AC;SAURASHTRA LETTER RA;Lo;0;L;;;;;N;;;;;
-A8AD;SAURASHTRA LETTER LA;Lo;0;L;;;;;N;;;;;
-A8AE;SAURASHTRA LETTER VA;Lo;0;L;;;;;N;;;;;
-A8AF;SAURASHTRA LETTER SHA;Lo;0;L;;;;;N;;;;;
-A8B0;SAURASHTRA LETTER SSA;Lo;0;L;;;;;N;;;;;
-A8B1;SAURASHTRA LETTER SA;Lo;0;L;;;;;N;;;;;
-A8B2;SAURASHTRA LETTER HA;Lo;0;L;;;;;N;;;;;
-A8B3;SAURASHTRA LETTER LLA;Lo;0;L;;;;;N;;;;;
-A8B4;SAURASHTRA CONSONANT SIGN HAARU;Mc;0;L;;;;;N;;;;;
-A8B5;SAURASHTRA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-A8B6;SAURASHTRA VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-A8B7;SAURASHTRA VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-A8B8;SAURASHTRA VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-A8B9;SAURASHTRA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
-A8BA;SAURASHTRA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;;
-A8BB;SAURASHTRA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;;
-A8BC;SAURASHTRA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;;
-A8BD;SAURASHTRA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;;
-A8BE;SAURASHTRA VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-A8BF;SAURASHTRA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;;
-A8C0;SAURASHTRA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-A8C1;SAURASHTRA VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-A8C2;SAURASHTRA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
-A8C3;SAURASHTRA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-A8C4;SAURASHTRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-A8CE;SAURASHTRA DANDA;Po;0;L;;;;;N;;;;;
-A8CF;SAURASHTRA DOUBLE DANDA;Po;0;L;;;;;N;;;;;
-A8D0;SAURASHTRA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-A8D1;SAURASHTRA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-A8D2;SAURASHTRA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-A8D3;SAURASHTRA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-A8D4;SAURASHTRA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-A8D5;SAURASHTRA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-A8D6;SAURASHTRA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-A8D7;SAURASHTRA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-A8D8;SAURASHTRA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-A8D9;SAURASHTRA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-A8E0;COMBINING DEVANAGARI DIGIT ZERO;Mn;230;NSM;;;;;N;;;;;
-A8E1;COMBINING DEVANAGARI DIGIT ONE;Mn;230;NSM;;;;;N;;;;;
-A8E2;COMBINING DEVANAGARI DIGIT TWO;Mn;230;NSM;;;;;N;;;;;
-A8E3;COMBINING DEVANAGARI DIGIT THREE;Mn;230;NSM;;;;;N;;;;;
-A8E4;COMBINING DEVANAGARI DIGIT FOUR;Mn;230;NSM;;;;;N;;;;;
-A8E5;COMBINING DEVANAGARI DIGIT FIVE;Mn;230;NSM;;;;;N;;;;;
-A8E6;COMBINING DEVANAGARI DIGIT SIX;Mn;230;NSM;;;;;N;;;;;
-A8E7;COMBINING DEVANAGARI DIGIT SEVEN;Mn;230;NSM;;;;;N;;;;;
-A8E8;COMBINING DEVANAGARI DIGIT EIGHT;Mn;230;NSM;;;;;N;;;;;
-A8E9;COMBINING DEVANAGARI DIGIT NINE;Mn;230;NSM;;;;;N;;;;;
-A8EA;COMBINING DEVANAGARI LETTER A;Mn;230;NSM;;;;;N;;;;;
-A8EB;COMBINING DEVANAGARI LETTER U;Mn;230;NSM;;;;;N;;;;;
-A8EC;COMBINING DEVANAGARI LETTER KA;Mn;230;NSM;;;;;N;;;;;
-A8ED;COMBINING DEVANAGARI LETTER NA;Mn;230;NSM;;;;;N;;;;;
-A8EE;COMBINING DEVANAGARI LETTER PA;Mn;230;NSM;;;;;N;;;;;
-A8EF;COMBINING DEVANAGARI LETTER RA;Mn;230;NSM;;;;;N;;;;;
-A8F0;COMBINING DEVANAGARI LETTER VI;Mn;230;NSM;;;;;N;;;;;
-A8F1;COMBINING DEVANAGARI SIGN AVAGRAHA;Mn;230;NSM;;;;;N;;;;;
-A8F2;DEVANAGARI SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;;
-A8F3;DEVANAGARI SIGN CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;;
-A8F4;DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;;
-A8F5;DEVANAGARI SIGN CANDRABINDU TWO;Lo;0;L;;;;;N;;;;;
-A8F6;DEVANAGARI SIGN CANDRABINDU THREE;Lo;0;L;;;;;N;;;;;
-A8F7;DEVANAGARI SIGN CANDRABINDU AVAGRAHA;Lo;0;L;;;;;N;;;;;
-A8F8;DEVANAGARI SIGN PUSHPIKA;Po;0;L;;;;;N;;;;;
-A8F9;DEVANAGARI GAP FILLER;Po;0;L;;;;;N;;;;;
-A8FA;DEVANAGARI CARET;Po;0;L;;;;;N;;;;;
-A8FB;DEVANAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;;
-A900;KAYAH LI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-A901;KAYAH LI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-A902;KAYAH LI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-A903;KAYAH LI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-A904;KAYAH LI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-A905;KAYAH LI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-A906;KAYAH LI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-A907;KAYAH LI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-A908;KAYAH LI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-A909;KAYAH LI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-A90A;KAYAH LI LETTER KA;Lo;0;L;;;;;N;;;;;
-A90B;KAYAH LI LETTER KHA;Lo;0;L;;;;;N;;;;;
-A90C;KAYAH LI LETTER GA;Lo;0;L;;;;;N;;;;;
-A90D;KAYAH LI LETTER NGA;Lo;0;L;;;;;N;;;;;
-A90E;KAYAH LI LETTER SA;Lo;0;L;;;;;N;;;;;
-A90F;KAYAH LI LETTER SHA;Lo;0;L;;;;;N;;;;;
-A910;KAYAH LI LETTER ZA;Lo;0;L;;;;;N;;;;;
-A911;KAYAH LI LETTER NYA;Lo;0;L;;;;;N;;;;;
-A912;KAYAH LI LETTER TA;Lo;0;L;;;;;N;;;;;
-A913;KAYAH LI LETTER HTA;Lo;0;L;;;;;N;;;;;
-A914;KAYAH LI LETTER NA;Lo;0;L;;;;;N;;;;;
-A915;KAYAH LI LETTER PA;Lo;0;L;;;;;N;;;;;
-A916;KAYAH LI LETTER PHA;Lo;0;L;;;;;N;;;;;
-A917;KAYAH LI LETTER MA;Lo;0;L;;;;;N;;;;;
-A918;KAYAH LI LETTER DA;Lo;0;L;;;;;N;;;;;
-A919;KAYAH LI LETTER BA;Lo;0;L;;;;;N;;;;;
-A91A;KAYAH LI LETTER RA;Lo;0;L;;;;;N;;;;;
-A91B;KAYAH LI LETTER YA;Lo;0;L;;;;;N;;;;;
-A91C;KAYAH LI LETTER LA;Lo;0;L;;;;;N;;;;;
-A91D;KAYAH LI LETTER WA;Lo;0;L;;;;;N;;;;;
-A91E;KAYAH LI LETTER THA;Lo;0;L;;;;;N;;;;;
-A91F;KAYAH LI LETTER HA;Lo;0;L;;;;;N;;;;;
-A920;KAYAH LI LETTER VA;Lo;0;L;;;;;N;;;;;
-A921;KAYAH LI LETTER CA;Lo;0;L;;;;;N;;;;;
-A922;KAYAH LI LETTER A;Lo;0;L;;;;;N;;;;;
-A923;KAYAH LI LETTER OE;Lo;0;L;;;;;N;;;;;
-A924;KAYAH LI LETTER I;Lo;0;L;;;;;N;;;;;
-A925;KAYAH LI LETTER OO;Lo;0;L;;;;;N;;;;;
-A926;KAYAH LI VOWEL UE;Mn;0;NSM;;;;;N;;;;;
-A927;KAYAH LI VOWEL E;Mn;0;NSM;;;;;N;;;;;
-A928;KAYAH LI VOWEL U;Mn;0;NSM;;;;;N;;;;;
-A929;KAYAH LI VOWEL EE;Mn;0;NSM;;;;;N;;;;;
-A92A;KAYAH LI VOWEL O;Mn;0;NSM;;;;;N;;;;;
-A92B;KAYAH LI TONE PLOPHU;Mn;220;NSM;;;;;N;;;;;
-A92C;KAYAH LI TONE CALYA;Mn;220;NSM;;;;;N;;;;;
-A92D;KAYAH LI TONE CALYA PLOPHU;Mn;220;NSM;;;;;N;;;;;
-A92E;KAYAH LI SIGN CWI;Po;0;L;;;;;N;;;;;
-A92F;KAYAH LI SIGN SHYA;Po;0;L;;;;;N;;;;;
-A930;REJANG LETTER KA;Lo;0;L;;;;;N;;;;;
-A931;REJANG LETTER GA;Lo;0;L;;;;;N;;;;;
-A932;REJANG LETTER NGA;Lo;0;L;;;;;N;;;;;
-A933;REJANG LETTER TA;Lo;0;L;;;;;N;;;;;
-A934;REJANG LETTER DA;Lo;0;L;;;;;N;;;;;
-A935;REJANG LETTER NA;Lo;0;L;;;;;N;;;;;
-A936;REJANG LETTER PA;Lo;0;L;;;;;N;;;;;
-A937;REJANG LETTER BA;Lo;0;L;;;;;N;;;;;
-A938;REJANG LETTER MA;Lo;0;L;;;;;N;;;;;
-A939;REJANG LETTER CA;Lo;0;L;;;;;N;;;;;
-A93A;REJANG LETTER JA;Lo;0;L;;;;;N;;;;;
-A93B;REJANG LETTER NYA;Lo;0;L;;;;;N;;;;;
-A93C;REJANG LETTER SA;Lo;0;L;;;;;N;;;;;
-A93D;REJANG LETTER RA;Lo;0;L;;;;;N;;;;;
-A93E;REJANG LETTER LA;Lo;0;L;;;;;N;;;;;
-A93F;REJANG LETTER YA;Lo;0;L;;;;;N;;;;;
-A940;REJANG LETTER WA;Lo;0;L;;;;;N;;;;;
-A941;REJANG LETTER HA;Lo;0;L;;;;;N;;;;;
-A942;REJANG LETTER MBA;Lo;0;L;;;;;N;;;;;
-A943;REJANG LETTER NGGA;Lo;0;L;;;;;N;;;;;
-A944;REJANG LETTER NDA;Lo;0;L;;;;;N;;;;;
-A945;REJANG LETTER NYJA;Lo;0;L;;;;;N;;;;;
-A946;REJANG LETTER A;Lo;0;L;;;;;N;;;;;
-A947;REJANG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-A948;REJANG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-A949;REJANG VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-A94A;REJANG VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-A94B;REJANG VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
-A94C;REJANG VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
-A94D;REJANG VOWEL SIGN EU;Mn;0;NSM;;;;;N;;;;;
-A94E;REJANG VOWEL SIGN EA;Mn;0;NSM;;;;;N;;;;;
-A94F;REJANG CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;;
-A950;REJANG CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;;
-A951;REJANG CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;;
-A952;REJANG CONSONANT SIGN H;Mc;0;L;;;;;N;;;;;
-A953;REJANG VIRAMA;Mc;9;L;;;;;N;;;;;
-A95F;REJANG SECTION MARK;Po;0;L;;;;;N;;;;;
-A960;HANGUL CHOSEONG TIKEUT-MIEUM;Lo;0;L;;;;;N;;;;;
-A961;HANGUL CHOSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;;
-A962;HANGUL CHOSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;;
-A963;HANGUL CHOSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;;
-A964;HANGUL CHOSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;;
-A965;HANGUL CHOSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
-A966;HANGUL CHOSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;;
-A967;HANGUL CHOSEONG RIEUL-SSANGTIKEUT;Lo;0;L;;;;;N;;;;;
-A968;HANGUL CHOSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;;
-A969;HANGUL CHOSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;;
-A96A;HANGUL CHOSEONG RIEUL-SSANGPIEUP;Lo;0;L;;;;;N;;;;;
-A96B;HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
-A96C;HANGUL CHOSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;;
-A96D;HANGUL CHOSEONG RIEUL-CIEUC;Lo;0;L;;;;;N;;;;;
-A96E;HANGUL CHOSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;;
-A96F;HANGUL CHOSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;;
-A970;HANGUL CHOSEONG MIEUM-TIKEUT;Lo;0;L;;;;;N;;;;;
-A971;HANGUL CHOSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;;
-A972;HANGUL CHOSEONG PIEUP-SIOS-THIEUTH;Lo;0;L;;;;;N;;;;;
-A973;HANGUL CHOSEONG PIEUP-KHIEUKH;Lo;0;L;;;;;N;;;;;
-A974;HANGUL CHOSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;;
-A975;HANGUL CHOSEONG SSANGSIOS-PIEUP;Lo;0;L;;;;;N;;;;;
-A976;HANGUL CHOSEONG IEUNG-RIEUL;Lo;0;L;;;;;N;;;;;
-A977;HANGUL CHOSEONG IEUNG-HIEUH;Lo;0;L;;;;;N;;;;;
-A978;HANGUL CHOSEONG SSANGCIEUC-HIEUH;Lo;0;L;;;;;N;;;;;
-A979;HANGUL CHOSEONG SSANGTHIEUTH;Lo;0;L;;;;;N;;;;;
-A97A;HANGUL CHOSEONG PHIEUPH-HIEUH;Lo;0;L;;;;;N;;;;;
-A97B;HANGUL CHOSEONG HIEUH-SIOS;Lo;0;L;;;;;N;;;;;
-A97C;HANGUL CHOSEONG SSANGYEORINHIEUH;Lo;0;L;;;;;N;;;;;
-A980;JAVANESE SIGN PANYANGGA;Mn;0;NSM;;;;;N;;;;;
-A981;JAVANESE SIGN CECAK;Mn;0;NSM;;;;;N;;;;;
-A982;JAVANESE SIGN LAYAR;Mn;0;NSM;;;;;N;;;;;
-A983;JAVANESE SIGN WIGNYAN;Mc;0;L;;;;;N;;;;;
-A984;JAVANESE LETTER A;Lo;0;L;;;;;N;;;;;
-A985;JAVANESE LETTER I KAWI;Lo;0;L;;;;;N;;;;;
-A986;JAVANESE LETTER I;Lo;0;L;;;;;N;;;;;
-A987;JAVANESE LETTER II;Lo;0;L;;;;;N;;;;;
-A988;JAVANESE LETTER U;Lo;0;L;;;;;N;;;;;
-A989;JAVANESE LETTER PA CEREK;Lo;0;L;;;;;N;;;;;
-A98A;JAVANESE LETTER NGA LELET;Lo;0;L;;;;;N;;;;;
-A98B;JAVANESE LETTER NGA LELET RASWADI;Lo;0;L;;;;;N;;;;;
-A98C;JAVANESE LETTER E;Lo;0;L;;;;;N;;;;;
-A98D;JAVANESE LETTER AI;Lo;0;L;;;;;N;;;;;
-A98E;JAVANESE LETTER O;Lo;0;L;;;;;N;;;;;
-A98F;JAVANESE LETTER KA;Lo;0;L;;;;;N;;;;;
-A990;JAVANESE LETTER KA SASAK;Lo;0;L;;;;;N;;;;;
-A991;JAVANESE LETTER KA MURDA;Lo;0;L;;;;;N;;;;;
-A992;JAVANESE LETTER GA;Lo;0;L;;;;;N;;;;;
-A993;JAVANESE LETTER GA MURDA;Lo;0;L;;;;;N;;;;;
-A994;JAVANESE LETTER NGA;Lo;0;L;;;;;N;;;;;
-A995;JAVANESE LETTER CA;Lo;0;L;;;;;N;;;;;
-A996;JAVANESE LETTER CA MURDA;Lo;0;L;;;;;N;;;;;
-A997;JAVANESE LETTER JA;Lo;0;L;;;;;N;;;;;
-A998;JAVANESE LETTER NYA MURDA;Lo;0;L;;;;;N;;;;;
-A999;JAVANESE LETTER JA MAHAPRANA;Lo;0;L;;;;;N;;;;;
-A99A;JAVANESE LETTER NYA;Lo;0;L;;;;;N;;;;;
-A99B;JAVANESE LETTER TTA;Lo;0;L;;;;;N;;;;;
-A99C;JAVANESE LETTER TTA MAHAPRANA;Lo;0;L;;;;;N;;;;;
-A99D;JAVANESE LETTER DDA;Lo;0;L;;;;;N;;;;;
-A99E;JAVANESE LETTER DDA MAHAPRANA;Lo;0;L;;;;;N;;;;;
-A99F;JAVANESE LETTER NA MURDA;Lo;0;L;;;;;N;;;;;
-A9A0;JAVANESE LETTER TA;Lo;0;L;;;;;N;;;;;
-A9A1;JAVANESE LETTER TA MURDA;Lo;0;L;;;;;N;;;;;
-A9A2;JAVANESE LETTER DA;Lo;0;L;;;;;N;;;;;
-A9A3;JAVANESE LETTER DA MAHAPRANA;Lo;0;L;;;;;N;;;;;
-A9A4;JAVANESE LETTER NA;Lo;0;L;;;;;N;;;;;
-A9A5;JAVANESE LETTER PA;Lo;0;L;;;;;N;;;;;
-A9A6;JAVANESE LETTER PA MURDA;Lo;0;L;;;;;N;;;;;
-A9A7;JAVANESE LETTER BA;Lo;0;L;;;;;N;;;;;
-A9A8;JAVANESE LETTER BA MURDA;Lo;0;L;;;;;N;;;;;
-A9A9;JAVANESE LETTER MA;Lo;0;L;;;;;N;;;;;
-A9AA;JAVANESE LETTER YA;Lo;0;L;;;;;N;;;;;
-A9AB;JAVANESE LETTER RA;Lo;0;L;;;;;N;;;;;
-A9AC;JAVANESE LETTER RA AGUNG;Lo;0;L;;;;;N;;;;;
-A9AD;JAVANESE LETTER LA;Lo;0;L;;;;;N;;;;;
-A9AE;JAVANESE LETTER WA;Lo;0;L;;;;;N;;;;;
-A9AF;JAVANESE LETTER SA MURDA;Lo;0;L;;;;;N;;;;;
-A9B0;JAVANESE LETTER SA MAHAPRANA;Lo;0;L;;;;;N;;;;;
-A9B1;JAVANESE LETTER SA;Lo;0;L;;;;;N;;;;;
-A9B2;JAVANESE LETTER HA;Lo;0;L;;;;;N;;;;;
-A9B3;JAVANESE SIGN CECAK TELU;Mn;7;NSM;;;;;N;;;;;
-A9B4;JAVANESE VOWEL SIGN TARUNG;Mc;0;L;;;;;N;;;;;
-A9B5;JAVANESE VOWEL SIGN TOLONG;Mc;0;L;;;;;N;;;;;
-A9B6;JAVANESE VOWEL SIGN WULU;Mn;0;NSM;;;;;N;;;;;
-A9B7;JAVANESE VOWEL SIGN WULU MELIK;Mn;0;NSM;;;;;N;;;;;
-A9B8;JAVANESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;;
-A9B9;JAVANESE VOWEL SIGN SUKU MENDUT;Mn;0;NSM;;;;;N;;;;;
-A9BA;JAVANESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;;
-A9BB;JAVANESE VOWEL SIGN DIRGA MURE;Mc;0;L;;;;;N;;;;;
-A9BC;JAVANESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;;
-A9BD;JAVANESE CONSONANT SIGN KERET;Mc;0;L;;;;;N;;;;;
-A9BE;JAVANESE CONSONANT SIGN PENGKAL;Mc;0;L;;;;;N;;;;;
-A9BF;JAVANESE CONSONANT SIGN CAKRA;Mc;0;L;;;;;N;;;;;
-A9C0;JAVANESE PANGKON;Mc;9;L;;;;;N;;;;;
-A9C1;JAVANESE LEFT RERENGGAN;Po;0;L;;;;;N;;;;;
-A9C2;JAVANESE RIGHT RERENGGAN;Po;0;L;;;;;N;;;;;
-A9C3;JAVANESE PADA ANDAP;Po;0;L;;;;;N;;;;;
-A9C4;JAVANESE PADA MADYA;Po;0;L;;;;;N;;;;;
-A9C5;JAVANESE PADA LUHUR;Po;0;L;;;;;N;;;;;
-A9C6;JAVANESE PADA WINDU;Po;0;L;;;;;N;;;;;
-A9C7;JAVANESE PADA PANGKAT;Po;0;L;;;;;N;;;;;
-A9C8;JAVANESE PADA LINGSA;Po;0;L;;;;;N;;;;;
-A9C9;JAVANESE PADA LUNGSI;Po;0;L;;;;;N;;;;;
-A9CA;JAVANESE PADA ADEG;Po;0;L;;;;;N;;;;;
-A9CB;JAVANESE PADA ADEG ADEG;Po;0;L;;;;;N;;;;;
-A9CC;JAVANESE PADA PISELEH;Po;0;L;;;;;N;;;;;
-A9CD;JAVANESE TURNED PADA PISELEH;Po;0;L;;;;;N;;;;;
-A9CF;JAVANESE PANGRANGKEP;Lm;0;L;;;;;N;;;;;
-A9D0;JAVANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-A9D1;JAVANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-A9D2;JAVANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-A9D3;JAVANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-A9D4;JAVANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-A9D5;JAVANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-A9D6;JAVANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-A9D7;JAVANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-A9D8;JAVANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-A9D9;JAVANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-A9DE;JAVANESE PADA TIRTA TUMETES;Po;0;L;;;;;N;;;;;
-A9DF;JAVANESE PADA ISEN-ISEN;Po;0;L;;;;;N;;;;;
-AA00;CHAM LETTER A;Lo;0;L;;;;;N;;;;;
-AA01;CHAM LETTER I;Lo;0;L;;;;;N;;;;;
-AA02;CHAM LETTER U;Lo;0;L;;;;;N;;;;;
-AA03;CHAM LETTER E;Lo;0;L;;;;;N;;;;;
-AA04;CHAM LETTER AI;Lo;0;L;;;;;N;;;;;
-AA05;CHAM LETTER O;Lo;0;L;;;;;N;;;;;
-AA06;CHAM LETTER KA;Lo;0;L;;;;;N;;;;;
-AA07;CHAM LETTER KHA;Lo;0;L;;;;;N;;;;;
-AA08;CHAM LETTER GA;Lo;0;L;;;;;N;;;;;
-AA09;CHAM LETTER GHA;Lo;0;L;;;;;N;;;;;
-AA0A;CHAM LETTER NGUE;Lo;0;L;;;;;N;;;;;
-AA0B;CHAM LETTER NGA;Lo;0;L;;;;;N;;;;;
-AA0C;CHAM LETTER CHA;Lo;0;L;;;;;N;;;;;
-AA0D;CHAM LETTER CHHA;Lo;0;L;;;;;N;;;;;
-AA0E;CHAM LETTER JA;Lo;0;L;;;;;N;;;;;
-AA0F;CHAM LETTER JHA;Lo;0;L;;;;;N;;;;;
-AA10;CHAM LETTER NHUE;Lo;0;L;;;;;N;;;;;
-AA11;CHAM LETTER NHA;Lo;0;L;;;;;N;;;;;
-AA12;CHAM LETTER NHJA;Lo;0;L;;;;;N;;;;;
-AA13;CHAM LETTER TA;Lo;0;L;;;;;N;;;;;
-AA14;CHAM LETTER THA;Lo;0;L;;;;;N;;;;;
-AA15;CHAM LETTER DA;Lo;0;L;;;;;N;;;;;
-AA16;CHAM LETTER DHA;Lo;0;L;;;;;N;;;;;
-AA17;CHAM LETTER NUE;Lo;0;L;;;;;N;;;;;
-AA18;CHAM LETTER NA;Lo;0;L;;;;;N;;;;;
-AA19;CHAM LETTER DDA;Lo;0;L;;;;;N;;;;;
-AA1A;CHAM LETTER PA;Lo;0;L;;;;;N;;;;;
-AA1B;CHAM LETTER PPA;Lo;0;L;;;;;N;;;;;
-AA1C;CHAM LETTER PHA;Lo;0;L;;;;;N;;;;;
-AA1D;CHAM LETTER BA;Lo;0;L;;;;;N;;;;;
-AA1E;CHAM LETTER BHA;Lo;0;L;;;;;N;;;;;
-AA1F;CHAM LETTER MUE;Lo;0;L;;;;;N;;;;;
-AA20;CHAM LETTER MA;Lo;0;L;;;;;N;;;;;
-AA21;CHAM LETTER BBA;Lo;0;L;;;;;N;;;;;
-AA22;CHAM LETTER YA;Lo;0;L;;;;;N;;;;;
-AA23;CHAM LETTER RA;Lo;0;L;;;;;N;;;;;
-AA24;CHAM LETTER LA;Lo;0;L;;;;;N;;;;;
-AA25;CHAM LETTER VA;Lo;0;L;;;;;N;;;;;
-AA26;CHAM LETTER SSA;Lo;0;L;;;;;N;;;;;
-AA27;CHAM LETTER SA;Lo;0;L;;;;;N;;;;;
-AA28;CHAM LETTER HA;Lo;0;L;;;;;N;;;;;
-AA29;CHAM VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;;
-AA2A;CHAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-AA2B;CHAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-AA2C;CHAM VOWEL SIGN EI;Mn;0;NSM;;;;;N;;;;;
-AA2D;CHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-AA2E;CHAM VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;;
-AA2F;CHAM VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-AA30;CHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-AA31;CHAM VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
-AA32;CHAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;;
-AA33;CHAM CONSONANT SIGN YA;Mc;0;L;;;;;N;;;;;
-AA34;CHAM CONSONANT SIGN RA;Mc;0;L;;;;;N;;;;;
-AA35;CHAM CONSONANT SIGN LA;Mn;0;NSM;;;;;N;;;;;
-AA36;CHAM CONSONANT SIGN WA;Mn;0;NSM;;;;;N;;;;;
-AA40;CHAM LETTER FINAL K;Lo;0;L;;;;;N;;;;;
-AA41;CHAM LETTER FINAL G;Lo;0;L;;;;;N;;;;;
-AA42;CHAM LETTER FINAL NG;Lo;0;L;;;;;N;;;;;
-AA43;CHAM CONSONANT SIGN FINAL NG;Mn;0;NSM;;;;;N;;;;;
-AA44;CHAM LETTER FINAL CH;Lo;0;L;;;;;N;;;;;
-AA45;CHAM LETTER FINAL T;Lo;0;L;;;;;N;;;;;
-AA46;CHAM LETTER FINAL N;Lo;0;L;;;;;N;;;;;
-AA47;CHAM LETTER FINAL P;Lo;0;L;;;;;N;;;;;
-AA48;CHAM LETTER FINAL Y;Lo;0;L;;;;;N;;;;;
-AA49;CHAM LETTER FINAL R;Lo;0;L;;;;;N;;;;;
-AA4A;CHAM LETTER FINAL L;Lo;0;L;;;;;N;;;;;
-AA4B;CHAM LETTER FINAL SS;Lo;0;L;;;;;N;;;;;
-AA4C;CHAM CONSONANT SIGN FINAL M;Mn;0;NSM;;;;;N;;;;;
-AA4D;CHAM CONSONANT SIGN FINAL H;Mc;0;L;;;;;N;;;;;
-AA50;CHAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-AA51;CHAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-AA52;CHAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-AA53;CHAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-AA54;CHAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-AA55;CHAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-AA56;CHAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-AA57;CHAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-AA58;CHAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-AA59;CHAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-AA5C;CHAM PUNCTUATION SPIRAL;Po;0;L;;;;;N;;;;;
-AA5D;CHAM PUNCTUATION DANDA;Po;0;L;;;;;N;;;;;
-AA5E;CHAM PUNCTUATION DOUBLE DANDA;Po;0;L;;;;;N;;;;;
-AA5F;CHAM PUNCTUATION TRIPLE DANDA;Po;0;L;;;;;N;;;;;
-AA60;MYANMAR LETTER KHAMTI GA;Lo;0;L;;;;;N;;;;;
-AA61;MYANMAR LETTER KHAMTI CA;Lo;0;L;;;;;N;;;;;
-AA62;MYANMAR LETTER KHAMTI CHA;Lo;0;L;;;;;N;;;;;
-AA63;MYANMAR LETTER KHAMTI JA;Lo;0;L;;;;;N;;;;;
-AA64;MYANMAR LETTER KHAMTI JHA;Lo;0;L;;;;;N;;;;;
-AA65;MYANMAR LETTER KHAMTI NYA;Lo;0;L;;;;;N;;;;;
-AA66;MYANMAR LETTER KHAMTI TTA;Lo;0;L;;;;;N;;;;;
-AA67;MYANMAR LETTER KHAMTI TTHA;Lo;0;L;;;;;N;;;;;
-AA68;MYANMAR LETTER KHAMTI DDA;Lo;0;L;;;;;N;;;;;
-AA69;MYANMAR LETTER KHAMTI DDHA;Lo;0;L;;;;;N;;;;;
-AA6A;MYANMAR LETTER KHAMTI DHA;Lo;0;L;;;;;N;;;;;
-AA6B;MYANMAR LETTER KHAMTI NA;Lo;0;L;;;;;N;;;;;
-AA6C;MYANMAR LETTER KHAMTI SA;Lo;0;L;;;;;N;;;;;
-AA6D;MYANMAR LETTER KHAMTI HA;Lo;0;L;;;;;N;;;;;
-AA6E;MYANMAR LETTER KHAMTI HHA;Lo;0;L;;;;;N;;;;;
-AA6F;MYANMAR LETTER KHAMTI FA;Lo;0;L;;;;;N;;;;;
-AA70;MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION;Lm;0;L;;;;;N;;;;;
-AA71;MYANMAR LETTER KHAMTI XA;Lo;0;L;;;;;N;;;;;
-AA72;MYANMAR LETTER KHAMTI ZA;Lo;0;L;;;;;N;;;;;
-AA73;MYANMAR LETTER KHAMTI RA;Lo;0;L;;;;;N;;;;;
-AA74;MYANMAR LOGOGRAM KHAMTI OAY;Lo;0;L;;;;;N;;;;;
-AA75;MYANMAR LOGOGRAM KHAMTI QN;Lo;0;L;;;;;N;;;;;
-AA76;MYANMAR LOGOGRAM KHAMTI HM;Lo;0;L;;;;;N;;;;;
-AA77;MYANMAR SYMBOL AITON EXCLAMATION;So;0;L;;;;;N;;;;;
-AA78;MYANMAR SYMBOL AITON ONE;So;0;L;;;;;N;;;;;
-AA79;MYANMAR SYMBOL AITON TWO;So;0;L;;;;;N;;;;;
-AA7A;MYANMAR LETTER AITON RA;Lo;0;L;;;;;N;;;;;
-AA7B;MYANMAR SIGN PAO KAREN TONE;Mc;0;L;;;;;N;;;;;
-AA80;TAI VIET LETTER LOW KO;Lo;0;L;;;;;N;;;;;
-AA81;TAI VIET LETTER HIGH KO;Lo;0;L;;;;;N;;;;;
-AA82;TAI VIET LETTER LOW KHO;Lo;0;L;;;;;N;;;;;
-AA83;TAI VIET LETTER HIGH KHO;Lo;0;L;;;;;N;;;;;
-AA84;TAI VIET LETTER LOW KHHO;Lo;0;L;;;;;N;;;;;
-AA85;TAI VIET LETTER HIGH KHHO;Lo;0;L;;;;;N;;;;;
-AA86;TAI VIET LETTER LOW GO;Lo;0;L;;;;;N;;;;;
-AA87;TAI VIET LETTER HIGH GO;Lo;0;L;;;;;N;;;;;
-AA88;TAI VIET LETTER LOW NGO;Lo;0;L;;;;;N;;;;;
-AA89;TAI VIET LETTER HIGH NGO;Lo;0;L;;;;;N;;;;;
-AA8A;TAI VIET LETTER LOW CO;Lo;0;L;;;;;N;;;;;
-AA8B;TAI VIET LETTER HIGH CO;Lo;0;L;;;;;N;;;;;
-AA8C;TAI VIET LETTER LOW CHO;Lo;0;L;;;;;N;;;;;
-AA8D;TAI VIET LETTER HIGH CHO;Lo;0;L;;;;;N;;;;;
-AA8E;TAI VIET LETTER LOW SO;Lo;0;L;;;;;N;;;;;
-AA8F;TAI VIET LETTER HIGH SO;Lo;0;L;;;;;N;;;;;
-AA90;TAI VIET LETTER LOW NYO;Lo;0;L;;;;;N;;;;;
-AA91;TAI VIET LETTER HIGH NYO;Lo;0;L;;;;;N;;;;;
-AA92;TAI VIET LETTER LOW DO;Lo;0;L;;;;;N;;;;;
-AA93;TAI VIET LETTER HIGH DO;Lo;0;L;;;;;N;;;;;
-AA94;TAI VIET LETTER LOW TO;Lo;0;L;;;;;N;;;;;
-AA95;TAI VIET LETTER HIGH TO;Lo;0;L;;;;;N;;;;;
-AA96;TAI VIET LETTER LOW THO;Lo;0;L;;;;;N;;;;;
-AA97;TAI VIET LETTER HIGH THO;Lo;0;L;;;;;N;;;;;
-AA98;TAI VIET LETTER LOW NO;Lo;0;L;;;;;N;;;;;
-AA99;TAI VIET LETTER HIGH NO;Lo;0;L;;;;;N;;;;;
-AA9A;TAI VIET LETTER LOW BO;Lo;0;L;;;;;N;;;;;
-AA9B;TAI VIET LETTER HIGH BO;Lo;0;L;;;;;N;;;;;
-AA9C;TAI VIET LETTER LOW PO;Lo;0;L;;;;;N;;;;;
-AA9D;TAI VIET LETTER HIGH PO;Lo;0;L;;;;;N;;;;;
-AA9E;TAI VIET LETTER LOW PHO;Lo;0;L;;;;;N;;;;;
-AA9F;TAI VIET LETTER HIGH PHO;Lo;0;L;;;;;N;;;;;
-AAA0;TAI VIET LETTER LOW FO;Lo;0;L;;;;;N;;;;;
-AAA1;TAI VIET LETTER HIGH FO;Lo;0;L;;;;;N;;;;;
-AAA2;TAI VIET LETTER LOW MO;Lo;0;L;;;;;N;;;;;
-AAA3;TAI VIET LETTER HIGH MO;Lo;0;L;;;;;N;;;;;
-AAA4;TAI VIET LETTER LOW YO;Lo;0;L;;;;;N;;;;;
-AAA5;TAI VIET LETTER HIGH YO;Lo;0;L;;;;;N;;;;;
-AAA6;TAI VIET LETTER LOW RO;Lo;0;L;;;;;N;;;;;
-AAA7;TAI VIET LETTER HIGH RO;Lo;0;L;;;;;N;;;;;
-AAA8;TAI VIET LETTER LOW LO;Lo;0;L;;;;;N;;;;;
-AAA9;TAI VIET LETTER HIGH LO;Lo;0;L;;;;;N;;;;;
-AAAA;TAI VIET LETTER LOW VO;Lo;0;L;;;;;N;;;;;
-AAAB;TAI VIET LETTER HIGH VO;Lo;0;L;;;;;N;;;;;
-AAAC;TAI VIET LETTER LOW HO;Lo;0;L;;;;;N;;;;;
-AAAD;TAI VIET LETTER HIGH HO;Lo;0;L;;;;;N;;;;;
-AAAE;TAI VIET LETTER LOW O;Lo;0;L;;;;;N;;;;;
-AAAF;TAI VIET LETTER HIGH O;Lo;0;L;;;;;N;;;;;
-AAB0;TAI VIET MAI KANG;Mn;230;NSM;;;;;N;;;;;
-AAB1;TAI VIET VOWEL AA;Lo;0;L;;;;;N;;;;;
-AAB2;TAI VIET VOWEL I;Mn;230;NSM;;;;;N;;;;;
-AAB3;TAI VIET VOWEL UE;Mn;230;NSM;;;;;N;;;;;
-AAB4;TAI VIET VOWEL U;Mn;220;NSM;;;;;N;;;;;
-AAB5;TAI VIET VOWEL E;Lo;0;L;;;;;N;;;;;
-AAB6;TAI VIET VOWEL O;Lo;0;L;;;;;N;;;;;
-AAB7;TAI VIET MAI KHIT;Mn;230;NSM;;;;;N;;;;;
-AAB8;TAI VIET VOWEL IA;Mn;230;NSM;;;;;N;;;;;
-AAB9;TAI VIET VOWEL UEA;Lo;0;L;;;;;N;;;;;
-AABA;TAI VIET VOWEL UA;Lo;0;L;;;;;N;;;;;
-AABB;TAI VIET VOWEL AUE;Lo;0;L;;;;;N;;;;;
-AABC;TAI VIET VOWEL AY;Lo;0;L;;;;;N;;;;;
-AABD;TAI VIET VOWEL AN;Lo;0;L;;;;;N;;;;;
-AABE;TAI VIET VOWEL AM;Mn;230;NSM;;;;;N;;;;;
-AABF;TAI VIET TONE MAI EK;Mn;230;NSM;;;;;N;;;;;
-AAC0;TAI VIET TONE MAI NUENG;Lo;0;L;;;;;N;;;;;
-AAC1;TAI VIET TONE MAI THO;Mn;230;NSM;;;;;N;;;;;
-AAC2;TAI VIET TONE MAI SONG;Lo;0;L;;;;;N;;;;;
-AADB;TAI VIET SYMBOL KON;Lo;0;L;;;;;N;;;;;
-AADC;TAI VIET SYMBOL NUENG;Lo;0;L;;;;;N;;;;;
-AADD;TAI VIET SYMBOL SAM;Lm;0;L;;;;;N;;;;;
-AADE;TAI VIET SYMBOL HO HOI;Po;0;L;;;;;N;;;;;
-AADF;TAI VIET SYMBOL KOI KOI;Po;0;L;;;;;N;;;;;
-AAE0;MEETEI MAYEK LETTER E;Lo;0;L;;;;;N;;;;;
-AAE1;MEETEI MAYEK LETTER O;Lo;0;L;;;;;N;;;;;
-AAE2;MEETEI MAYEK LETTER CHA;Lo;0;L;;;;;N;;;;;
-AAE3;MEETEI MAYEK LETTER NYA;Lo;0;L;;;;;N;;;;;
-AAE4;MEETEI MAYEK LETTER TTA;Lo;0;L;;;;;N;;;;;
-AAE5;MEETEI MAYEK LETTER TTHA;Lo;0;L;;;;;N;;;;;
-AAE6;MEETEI MAYEK LETTER DDA;Lo;0;L;;;;;N;;;;;
-AAE7;MEETEI MAYEK LETTER DDHA;Lo;0;L;;;;;N;;;;;
-AAE8;MEETEI MAYEK LETTER NNA;Lo;0;L;;;;;N;;;;;
-AAE9;MEETEI MAYEK LETTER SHA;Lo;0;L;;;;;N;;;;;
-AAEA;MEETEI MAYEK LETTER SSA;Lo;0;L;;;;;N;;;;;
-AAEB;MEETEI MAYEK VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-AAEC;MEETEI MAYEK VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-AAED;MEETEI MAYEK VOWEL SIGN AAI;Mn;0;NSM;;;;;N;;;;;
-AAEE;MEETEI MAYEK VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-AAEF;MEETEI MAYEK VOWEL SIGN AAU;Mc;0;L;;;;;N;;;;;
-AAF0;MEETEI MAYEK CHEIKHAN;Po;0;L;;;;;N;;;;;
-AAF1;MEETEI MAYEK AHANG KHUDAM;Po;0;L;;;;;N;;;;;
-AAF2;MEETEI MAYEK ANJI;Lo;0;L;;;;;N;;;;;
-AAF3;MEETEI MAYEK SYLLABLE REPETITION MARK;Lm;0;L;;;;;N;;;;;
-AAF4;MEETEI MAYEK WORD REPETITION MARK;Lm;0;L;;;;;N;;;;;
-AAF5;MEETEI MAYEK VOWEL SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-AAF6;MEETEI MAYEK VIRAMA;Mn;9;NSM;;;;;N;;;;;
-AB01;ETHIOPIC SYLLABLE TTHU;Lo;0;L;;;;;N;;;;;
-AB02;ETHIOPIC SYLLABLE TTHI;Lo;0;L;;;;;N;;;;;
-AB03;ETHIOPIC SYLLABLE TTHAA;Lo;0;L;;;;;N;;;;;
-AB04;ETHIOPIC SYLLABLE TTHEE;Lo;0;L;;;;;N;;;;;
-AB05;ETHIOPIC SYLLABLE TTHE;Lo;0;L;;;;;N;;;;;
-AB06;ETHIOPIC SYLLABLE TTHO;Lo;0;L;;;;;N;;;;;
-AB09;ETHIOPIC SYLLABLE DDHU;Lo;0;L;;;;;N;;;;;
-AB0A;ETHIOPIC SYLLABLE DDHI;Lo;0;L;;;;;N;;;;;
-AB0B;ETHIOPIC SYLLABLE DDHAA;Lo;0;L;;;;;N;;;;;
-AB0C;ETHIOPIC SYLLABLE DDHEE;Lo;0;L;;;;;N;;;;;
-AB0D;ETHIOPIC SYLLABLE DDHE;Lo;0;L;;;;;N;;;;;
-AB0E;ETHIOPIC SYLLABLE DDHO;Lo;0;L;;;;;N;;;;;
-AB11;ETHIOPIC SYLLABLE DZU;Lo;0;L;;;;;N;;;;;
-AB12;ETHIOPIC SYLLABLE DZI;Lo;0;L;;;;;N;;;;;
-AB13;ETHIOPIC SYLLABLE DZAA;Lo;0;L;;;;;N;;;;;
-AB14;ETHIOPIC SYLLABLE DZEE;Lo;0;L;;;;;N;;;;;
-AB15;ETHIOPIC SYLLABLE DZE;Lo;0;L;;;;;N;;;;;
-AB16;ETHIOPIC SYLLABLE DZO;Lo;0;L;;;;;N;;;;;
-AB20;ETHIOPIC SYLLABLE CCHHA;Lo;0;L;;;;;N;;;;;
-AB21;ETHIOPIC SYLLABLE CCHHU;Lo;0;L;;;;;N;;;;;
-AB22;ETHIOPIC SYLLABLE CCHHI;Lo;0;L;;;;;N;;;;;
-AB23;ETHIOPIC SYLLABLE CCHHAA;Lo;0;L;;;;;N;;;;;
-AB24;ETHIOPIC SYLLABLE CCHHEE;Lo;0;L;;;;;N;;;;;
-AB25;ETHIOPIC SYLLABLE CCHHE;Lo;0;L;;;;;N;;;;;
-AB26;ETHIOPIC SYLLABLE CCHHO;Lo;0;L;;;;;N;;;;;
-AB28;ETHIOPIC SYLLABLE BBA;Lo;0;L;;;;;N;;;;;
-AB29;ETHIOPIC SYLLABLE BBU;Lo;0;L;;;;;N;;;;;
-AB2A;ETHIOPIC SYLLABLE BBI;Lo;0;L;;;;;N;;;;;
-AB2B;ETHIOPIC SYLLABLE BBAA;Lo;0;L;;;;;N;;;;;
-AB2C;ETHIOPIC SYLLABLE BBEE;Lo;0;L;;;;;N;;;;;
-AB2D;ETHIOPIC SYLLABLE BBE;Lo;0;L;;;;;N;;;;;
-AB2E;ETHIOPIC SYLLABLE BBO;Lo;0;L;;;;;N;;;;;
-ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;;
-ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;;
-ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;;
-ABC3;MEETEI MAYEK LETTER MIT;Lo;0;L;;;;;N;;;;;
-ABC4;MEETEI MAYEK LETTER PA;Lo;0;L;;;;;N;;;;;
-ABC5;MEETEI MAYEK LETTER NA;Lo;0;L;;;;;N;;;;;
-ABC6;MEETEI MAYEK LETTER CHIL;Lo;0;L;;;;;N;;;;;
-ABC7;MEETEI MAYEK LETTER TIL;Lo;0;L;;;;;N;;;;;
-ABC8;MEETEI MAYEK LETTER KHOU;Lo;0;L;;;;;N;;;;;
-ABC9;MEETEI MAYEK LETTER NGOU;Lo;0;L;;;;;N;;;;;
-ABCA;MEETEI MAYEK LETTER THOU;Lo;0;L;;;;;N;;;;;
-ABCB;MEETEI MAYEK LETTER WAI;Lo;0;L;;;;;N;;;;;
-ABCC;MEETEI MAYEK LETTER YANG;Lo;0;L;;;;;N;;;;;
-ABCD;MEETEI MAYEK LETTER HUK;Lo;0;L;;;;;N;;;;;
-ABCE;MEETEI MAYEK LETTER UN;Lo;0;L;;;;;N;;;;;
-ABCF;MEETEI MAYEK LETTER I;Lo;0;L;;;;;N;;;;;
-ABD0;MEETEI MAYEK LETTER PHAM;Lo;0;L;;;;;N;;;;;
-ABD1;MEETEI MAYEK LETTER ATIYA;Lo;0;L;;;;;N;;;;;
-ABD2;MEETEI MAYEK LETTER GOK;Lo;0;L;;;;;N;;;;;
-ABD3;MEETEI MAYEK LETTER JHAM;Lo;0;L;;;;;N;;;;;
-ABD4;MEETEI MAYEK LETTER RAI;Lo;0;L;;;;;N;;;;;
-ABD5;MEETEI MAYEK LETTER BA;Lo;0;L;;;;;N;;;;;
-ABD6;MEETEI MAYEK LETTER JIL;Lo;0;L;;;;;N;;;;;
-ABD7;MEETEI MAYEK LETTER DIL;Lo;0;L;;;;;N;;;;;
-ABD8;MEETEI MAYEK LETTER GHOU;Lo;0;L;;;;;N;;;;;
-ABD9;MEETEI MAYEK LETTER DHOU;Lo;0;L;;;;;N;;;;;
-ABDA;MEETEI MAYEK LETTER BHAM;Lo;0;L;;;;;N;;;;;
-ABDB;MEETEI MAYEK LETTER KOK LONSUM;Lo;0;L;;;;;N;;;;;
-ABDC;MEETEI MAYEK LETTER LAI LONSUM;Lo;0;L;;;;;N;;;;;
-ABDD;MEETEI MAYEK LETTER MIT LONSUM;Lo;0;L;;;;;N;;;;;
-ABDE;MEETEI MAYEK LETTER PA LONSUM;Lo;0;L;;;;;N;;;;;
-ABDF;MEETEI MAYEK LETTER NA LONSUM;Lo;0;L;;;;;N;;;;;
-ABE0;MEETEI MAYEK LETTER TIL LONSUM;Lo;0;L;;;;;N;;;;;
-ABE1;MEETEI MAYEK LETTER NGOU LONSUM;Lo;0;L;;;;;N;;;;;
-ABE2;MEETEI MAYEK LETTER I LONSUM;Lo;0;L;;;;;N;;;;;
-ABE3;MEETEI MAYEK VOWEL SIGN ONAP;Mc;0;L;;;;;N;;;;;
-ABE4;MEETEI MAYEK VOWEL SIGN INAP;Mc;0;L;;;;;N;;;;;
-ABE5;MEETEI MAYEK VOWEL SIGN ANAP;Mn;0;NSM;;;;;N;;;;;
-ABE6;MEETEI MAYEK VOWEL SIGN YENAP;Mc;0;L;;;;;N;;;;;
-ABE7;MEETEI MAYEK VOWEL SIGN SOUNAP;Mc;0;L;;;;;N;;;;;
-ABE8;MEETEI MAYEK VOWEL SIGN UNAP;Mn;0;NSM;;;;;N;;;;;
-ABE9;MEETEI MAYEK VOWEL SIGN CHEINAP;Mc;0;L;;;;;N;;;;;
-ABEA;MEETEI MAYEK VOWEL SIGN NUNG;Mc;0;L;;;;;N;;;;;
-ABEB;MEETEI MAYEK CHEIKHEI;Po;0;L;;;;;N;;;;;
-ABEC;MEETEI MAYEK LUM IYEK;Mc;0;L;;;;;N;;;;;
-ABED;MEETEI MAYEK APUN IYEK;Mn;9;NSM;;;;;N;;;;;
-ABF0;MEETEI MAYEK DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-ABF1;MEETEI MAYEK DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-ABF2;MEETEI MAYEK DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-ABF3;MEETEI MAYEK DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-ABF4;MEETEI MAYEK DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-ABF5;MEETEI MAYEK DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-ABF6;MEETEI MAYEK DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-ABF7;MEETEI MAYEK DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-ABF8;MEETEI MAYEK DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-ABF9;MEETEI MAYEK DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-AC00;<Hangul Syllable, First>;Lo;0;L;;;;;N;;;;;
-D7A3;<Hangul Syllable, Last>;Lo;0;L;;;;;N;;;;;
-D7B0;HANGUL JUNGSEONG O-YEO;Lo;0;L;;;;;N;;;;;
-D7B1;HANGUL JUNGSEONG O-O-I;Lo;0;L;;;;;N;;;;;
-D7B2;HANGUL JUNGSEONG YO-A;Lo;0;L;;;;;N;;;;;
-D7B3;HANGUL JUNGSEONG YO-AE;Lo;0;L;;;;;N;;;;;
-D7B4;HANGUL JUNGSEONG YO-EO;Lo;0;L;;;;;N;;;;;
-D7B5;HANGUL JUNGSEONG U-YEO;Lo;0;L;;;;;N;;;;;
-D7B6;HANGUL JUNGSEONG U-I-I;Lo;0;L;;;;;N;;;;;
-D7B7;HANGUL JUNGSEONG YU-AE;Lo;0;L;;;;;N;;;;;
-D7B8;HANGUL JUNGSEONG YU-O;Lo;0;L;;;;;N;;;;;
-D7B9;HANGUL JUNGSEONG EU-A;Lo;0;L;;;;;N;;;;;
-D7BA;HANGUL JUNGSEONG EU-EO;Lo;0;L;;;;;N;;;;;
-D7BB;HANGUL JUNGSEONG EU-E;Lo;0;L;;;;;N;;;;;
-D7BC;HANGUL JUNGSEONG EU-O;Lo;0;L;;;;;N;;;;;
-D7BD;HANGUL JUNGSEONG I-YA-O;Lo;0;L;;;;;N;;;;;
-D7BE;HANGUL JUNGSEONG I-YAE;Lo;0;L;;;;;N;;;;;
-D7BF;HANGUL JUNGSEONG I-YEO;Lo;0;L;;;;;N;;;;;
-D7C0;HANGUL JUNGSEONG I-YE;Lo;0;L;;;;;N;;;;;
-D7C1;HANGUL JUNGSEONG I-O-I;Lo;0;L;;;;;N;;;;;
-D7C2;HANGUL JUNGSEONG I-YO;Lo;0;L;;;;;N;;;;;
-D7C3;HANGUL JUNGSEONG I-YU;Lo;0;L;;;;;N;;;;;
-D7C4;HANGUL JUNGSEONG I-I;Lo;0;L;;;;;N;;;;;
-D7C5;HANGUL JUNGSEONG ARAEA-A;Lo;0;L;;;;;N;;;;;
-D7C6;HANGUL JUNGSEONG ARAEA-E;Lo;0;L;;;;;N;;;;;
-D7CB;HANGUL JONGSEONG NIEUN-RIEUL;Lo;0;L;;;;;N;;;;;
-D7CC;HANGUL JONGSEONG NIEUN-CHIEUCH;Lo;0;L;;;;;N;;;;;
-D7CD;HANGUL JONGSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;;
-D7CE;HANGUL JONGSEONG SSANGTIKEUT-PIEUP;Lo;0;L;;;;;N;;;;;
-D7CF;HANGUL JONGSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;;
-D7D0;HANGUL JONGSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;;
-D7D1;HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
-D7D2;HANGUL JONGSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;;
-D7D3;HANGUL JONGSEONG TIKEUT-CHIEUCH;Lo;0;L;;;;;N;;;;;
-D7D4;HANGUL JONGSEONG TIKEUT-THIEUTH;Lo;0;L;;;;;N;;;;;
-D7D5;HANGUL JONGSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
-D7D6;HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;;
-D7D7;HANGUL JONGSEONG SSANGRIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;;
-D7D8;HANGUL JONGSEONG RIEUL-MIEUM-HIEUH;Lo;0;L;;;;;N;;;;;
-D7D9;HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;;
-D7DA;HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;;
-D7DB;HANGUL JONGSEONG RIEUL-YESIEUNG;Lo;0;L;;;;;N;;;;;
-D7DC;HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH;Lo;0;L;;;;;N;;;;;
-D7DD;HANGUL JONGSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;;
-D7DE;HANGUL JONGSEONG MIEUM-NIEUN;Lo;0;L;;;;;N;;;;;
-D7DF;HANGUL JONGSEONG MIEUM-SSANGNIEUN;Lo;0;L;;;;;N;;;;;
-D7E0;HANGUL JONGSEONG SSANGMIEUM;Lo;0;L;;;;;N;;;;;
-D7E1;HANGUL JONGSEONG MIEUM-PIEUP-SIOS;Lo;0;L;;;;;N;;;;;
-D7E2;HANGUL JONGSEONG MIEUM-CIEUC;Lo;0;L;;;;;N;;;;;
-D7E3;HANGUL JONGSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;;
-D7E4;HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;;
-D7E5;HANGUL JONGSEONG PIEUP-MIEUM;Lo;0;L;;;;;N;;;;;
-D7E6;HANGUL JONGSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;;
-D7E7;HANGUL JONGSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
-D7E8;HANGUL JONGSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;;
-D7E9;HANGUL JONGSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;;
-D7EA;HANGUL JONGSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;;
-D7EB;HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
-D7EC;HANGUL JONGSEONG SSANGSIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
-D7ED;HANGUL JONGSEONG SSANGSIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
-D7EE;HANGUL JONGSEONG SIOS-PANSIOS;Lo;0;L;;;;;N;;;;;
-D7EF;HANGUL JONGSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;;
-D7F0;HANGUL JONGSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;;
-D7F1;HANGUL JONGSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;;
-D7F2;HANGUL JONGSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;;
-D7F3;HANGUL JONGSEONG PANSIOS-PIEUP;Lo;0;L;;;;;N;;;;;
-D7F4;HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
-D7F5;HANGUL JONGSEONG YESIEUNG-MIEUM;Lo;0;L;;;;;N;;;;;
-D7F6;HANGUL JONGSEONG YESIEUNG-HIEUH;Lo;0;L;;;;;N;;;;;
-D7F7;HANGUL JONGSEONG CIEUC-PIEUP;Lo;0;L;;;;;N;;;;;
-D7F8;HANGUL JONGSEONG CIEUC-SSANGPIEUP;Lo;0;L;;;;;N;;;;;
-D7F9;HANGUL JONGSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;;
-D7FA;HANGUL JONGSEONG PHIEUPH-SIOS;Lo;0;L;;;;;N;;;;;
-D7FB;HANGUL JONGSEONG PHIEUPH-THIEUTH;Lo;0;L;;;;;N;;;;;
-D800;<Non Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;;
-DB7F;<Non Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;;
-DB80;<Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;;
-DBFF;<Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;;
-DC00;<Low Surrogate, First>;Cs;0;L;;;;;N;;;;;
-DFFF;<Low Surrogate, Last>;Cs;0;L;;;;;N;;;;;
-E000;<Private Use, First>;Co;0;L;;;;;N;;;;;
-F8FF;<Private Use, Last>;Co;0;L;;;;;N;;;;;
-F900;CJK COMPATIBILITY IDEOGRAPH-F900;Lo;0;L;8C48;;;;N;;;;;
-F901;CJK COMPATIBILITY IDEOGRAPH-F901;Lo;0;L;66F4;;;;N;;;;;
-F902;CJK COMPATIBILITY IDEOGRAPH-F902;Lo;0;L;8ECA;;;;N;;;;;
-F903;CJK COMPATIBILITY IDEOGRAPH-F903;Lo;0;L;8CC8;;;;N;;;;;
-F904;CJK COMPATIBILITY IDEOGRAPH-F904;Lo;0;L;6ED1;;;;N;;;;;
-F905;CJK COMPATIBILITY IDEOGRAPH-F905;Lo;0;L;4E32;;;;N;;;;;
-F906;CJK COMPATIBILITY IDEOGRAPH-F906;Lo;0;L;53E5;;;;N;;;;;
-F907;CJK COMPATIBILITY IDEOGRAPH-F907;Lo;0;L;9F9C;;;;N;;;;;
-F908;CJK COMPATIBILITY IDEOGRAPH-F908;Lo;0;L;9F9C;;;;N;;;;;
-F909;CJK COMPATIBILITY IDEOGRAPH-F909;Lo;0;L;5951;;;;N;;;;;
-F90A;CJK COMPATIBILITY IDEOGRAPH-F90A;Lo;0;L;91D1;;;;N;;;;;
-F90B;CJK COMPATIBILITY IDEOGRAPH-F90B;Lo;0;L;5587;;;;N;;;;;
-F90C;CJK COMPATIBILITY IDEOGRAPH-F90C;Lo;0;L;5948;;;;N;;;;;
-F90D;CJK COMPATIBILITY IDEOGRAPH-F90D;Lo;0;L;61F6;;;;N;;;;;
-F90E;CJK COMPATIBILITY IDEOGRAPH-F90E;Lo;0;L;7669;;;;N;;;;;
-F90F;CJK COMPATIBILITY IDEOGRAPH-F90F;Lo;0;L;7F85;;;;N;;;;;
-F910;CJK COMPATIBILITY IDEOGRAPH-F910;Lo;0;L;863F;;;;N;;;;;
-F911;CJK COMPATIBILITY IDEOGRAPH-F911;Lo;0;L;87BA;;;;N;;;;;
-F912;CJK COMPATIBILITY IDEOGRAPH-F912;Lo;0;L;88F8;;;;N;;;;;
-F913;CJK COMPATIBILITY IDEOGRAPH-F913;Lo;0;L;908F;;;;N;;;;;
-F914;CJK COMPATIBILITY IDEOGRAPH-F914;Lo;0;L;6A02;;;;N;;;;;
-F915;CJK COMPATIBILITY IDEOGRAPH-F915;Lo;0;L;6D1B;;;;N;;;;;
-F916;CJK COMPATIBILITY IDEOGRAPH-F916;Lo;0;L;70D9;;;;N;;;;;
-F917;CJK COMPATIBILITY IDEOGRAPH-F917;Lo;0;L;73DE;;;;N;;;;;
-F918;CJK COMPATIBILITY IDEOGRAPH-F918;Lo;0;L;843D;;;;N;;;;;
-F919;CJK COMPATIBILITY IDEOGRAPH-F919;Lo;0;L;916A;;;;N;;;;;
-F91A;CJK COMPATIBILITY IDEOGRAPH-F91A;Lo;0;L;99F1;;;;N;;;;;
-F91B;CJK COMPATIBILITY IDEOGRAPH-F91B;Lo;0;L;4E82;;;;N;;;;;
-F91C;CJK COMPATIBILITY IDEOGRAPH-F91C;Lo;0;L;5375;;;;N;;;;;
-F91D;CJK COMPATIBILITY IDEOGRAPH-F91D;Lo;0;L;6B04;;;;N;;;;;
-F91E;CJK COMPATIBILITY IDEOGRAPH-F91E;Lo;0;L;721B;;;;N;;;;;
-F91F;CJK COMPATIBILITY IDEOGRAPH-F91F;Lo;0;L;862D;;;;N;;;;;
-F920;CJK COMPATIBILITY IDEOGRAPH-F920;Lo;0;L;9E1E;;;;N;;;;;
-F921;CJK COMPATIBILITY IDEOGRAPH-F921;Lo;0;L;5D50;;;;N;;;;;
-F922;CJK COMPATIBILITY IDEOGRAPH-F922;Lo;0;L;6FEB;;;;N;;;;;
-F923;CJK COMPATIBILITY IDEOGRAPH-F923;Lo;0;L;85CD;;;;N;;;;;
-F924;CJK COMPATIBILITY IDEOGRAPH-F924;Lo;0;L;8964;;;;N;;;;;
-F925;CJK COMPATIBILITY IDEOGRAPH-F925;Lo;0;L;62C9;;;;N;;;;;
-F926;CJK COMPATIBILITY IDEOGRAPH-F926;Lo;0;L;81D8;;;;N;;;;;
-F927;CJK COMPATIBILITY IDEOGRAPH-F927;Lo;0;L;881F;;;;N;;;;;
-F928;CJK COMPATIBILITY IDEOGRAPH-F928;Lo;0;L;5ECA;;;;N;;;;;
-F929;CJK COMPATIBILITY IDEOGRAPH-F929;Lo;0;L;6717;;;;N;;;;;
-F92A;CJK COMPATIBILITY IDEOGRAPH-F92A;Lo;0;L;6D6A;;;;N;;;;;
-F92B;CJK COMPATIBILITY IDEOGRAPH-F92B;Lo;0;L;72FC;;;;N;;;;;
-F92C;CJK COMPATIBILITY IDEOGRAPH-F92C;Lo;0;L;90CE;;;;N;;;;;
-F92D;CJK COMPATIBILITY IDEOGRAPH-F92D;Lo;0;L;4F86;;;;N;;;;;
-F92E;CJK COMPATIBILITY IDEOGRAPH-F92E;Lo;0;L;51B7;;;;N;;;;;
-F92F;CJK COMPATIBILITY IDEOGRAPH-F92F;Lo;0;L;52DE;;;;N;;;;;
-F930;CJK COMPATIBILITY IDEOGRAPH-F930;Lo;0;L;64C4;;;;N;;;;;
-F931;CJK COMPATIBILITY IDEOGRAPH-F931;Lo;0;L;6AD3;;;;N;;;;;
-F932;CJK COMPATIBILITY IDEOGRAPH-F932;Lo;0;L;7210;;;;N;;;;;
-F933;CJK COMPATIBILITY IDEOGRAPH-F933;Lo;0;L;76E7;;;;N;;;;;
-F934;CJK COMPATIBILITY IDEOGRAPH-F934;Lo;0;L;8001;;;;N;;;;;
-F935;CJK COMPATIBILITY IDEOGRAPH-F935;Lo;0;L;8606;;;;N;;;;;
-F936;CJK COMPATIBILITY IDEOGRAPH-F936;Lo;0;L;865C;;;;N;;;;;
-F937;CJK COMPATIBILITY IDEOGRAPH-F937;Lo;0;L;8DEF;;;;N;;;;;
-F938;CJK COMPATIBILITY IDEOGRAPH-F938;Lo;0;L;9732;;;;N;;;;;
-F939;CJK COMPATIBILITY IDEOGRAPH-F939;Lo;0;L;9B6F;;;;N;;;;;
-F93A;CJK COMPATIBILITY IDEOGRAPH-F93A;Lo;0;L;9DFA;;;;N;;;;;
-F93B;CJK COMPATIBILITY IDEOGRAPH-F93B;Lo;0;L;788C;;;;N;;;;;
-F93C;CJK COMPATIBILITY IDEOGRAPH-F93C;Lo;0;L;797F;;;;N;;;;;
-F93D;CJK COMPATIBILITY IDEOGRAPH-F93D;Lo;0;L;7DA0;;;;N;;;;;
-F93E;CJK COMPATIBILITY IDEOGRAPH-F93E;Lo;0;L;83C9;;;;N;;;;;
-F93F;CJK COMPATIBILITY IDEOGRAPH-F93F;Lo;0;L;9304;;;;N;;;;;
-F940;CJK COMPATIBILITY IDEOGRAPH-F940;Lo;0;L;9E7F;;;;N;;;;;
-F941;CJK COMPATIBILITY IDEOGRAPH-F941;Lo;0;L;8AD6;;;;N;;;;;
-F942;CJK COMPATIBILITY IDEOGRAPH-F942;Lo;0;L;58DF;;;;N;;;;;
-F943;CJK COMPATIBILITY IDEOGRAPH-F943;Lo;0;L;5F04;;;;N;;;;;
-F944;CJK COMPATIBILITY IDEOGRAPH-F944;Lo;0;L;7C60;;;;N;;;;;
-F945;CJK COMPATIBILITY IDEOGRAPH-F945;Lo;0;L;807E;;;;N;;;;;
-F946;CJK COMPATIBILITY IDEOGRAPH-F946;Lo;0;L;7262;;;;N;;;;;
-F947;CJK COMPATIBILITY IDEOGRAPH-F947;Lo;0;L;78CA;;;;N;;;;;
-F948;CJK COMPATIBILITY IDEOGRAPH-F948;Lo;0;L;8CC2;;;;N;;;;;
-F949;CJK COMPATIBILITY IDEOGRAPH-F949;Lo;0;L;96F7;;;;N;;;;;
-F94A;CJK COMPATIBILITY IDEOGRAPH-F94A;Lo;0;L;58D8;;;;N;;;;;
-F94B;CJK COMPATIBILITY IDEOGRAPH-F94B;Lo;0;L;5C62;;;;N;;;;;
-F94C;CJK COMPATIBILITY IDEOGRAPH-F94C;Lo;0;L;6A13;;;;N;;;;;
-F94D;CJK COMPATIBILITY IDEOGRAPH-F94D;Lo;0;L;6DDA;;;;N;;;;;
-F94E;CJK COMPATIBILITY IDEOGRAPH-F94E;Lo;0;L;6F0F;;;;N;;;;;
-F94F;CJK COMPATIBILITY IDEOGRAPH-F94F;Lo;0;L;7D2F;;;;N;;;;;
-F950;CJK COMPATIBILITY IDEOGRAPH-F950;Lo;0;L;7E37;;;;N;;;;;
-F951;CJK COMPATIBILITY IDEOGRAPH-F951;Lo;0;L;964B;;;;N;;;;;
-F952;CJK COMPATIBILITY IDEOGRAPH-F952;Lo;0;L;52D2;;;;N;;;;;
-F953;CJK COMPATIBILITY IDEOGRAPH-F953;Lo;0;L;808B;;;;N;;;;;
-F954;CJK COMPATIBILITY IDEOGRAPH-F954;Lo;0;L;51DC;;;;N;;;;;
-F955;CJK COMPATIBILITY IDEOGRAPH-F955;Lo;0;L;51CC;;;;N;;;;;
-F956;CJK COMPATIBILITY IDEOGRAPH-F956;Lo;0;L;7A1C;;;;N;;;;;
-F957;CJK COMPATIBILITY IDEOGRAPH-F957;Lo;0;L;7DBE;;;;N;;;;;
-F958;CJK COMPATIBILITY IDEOGRAPH-F958;Lo;0;L;83F1;;;;N;;;;;
-F959;CJK COMPATIBILITY IDEOGRAPH-F959;Lo;0;L;9675;;;;N;;;;;
-F95A;CJK COMPATIBILITY IDEOGRAPH-F95A;Lo;0;L;8B80;;;;N;;;;;
-F95B;CJK COMPATIBILITY IDEOGRAPH-F95B;Lo;0;L;62CF;;;;N;;;;;
-F95C;CJK COMPATIBILITY IDEOGRAPH-F95C;Lo;0;L;6A02;;;;N;;;;;
-F95D;CJK COMPATIBILITY IDEOGRAPH-F95D;Lo;0;L;8AFE;;;;N;;;;;
-F95E;CJK COMPATIBILITY IDEOGRAPH-F95E;Lo;0;L;4E39;;;;N;;;;;
-F95F;CJK COMPATIBILITY IDEOGRAPH-F95F;Lo;0;L;5BE7;;;;N;;;;;
-F960;CJK COMPATIBILITY IDEOGRAPH-F960;Lo;0;L;6012;;;;N;;;;;
-F961;CJK COMPATIBILITY IDEOGRAPH-F961;Lo;0;L;7387;;;;N;;;;;
-F962;CJK COMPATIBILITY IDEOGRAPH-F962;Lo;0;L;7570;;;;N;;;;;
-F963;CJK COMPATIBILITY IDEOGRAPH-F963;Lo;0;L;5317;;;;N;;;;;
-F964;CJK COMPATIBILITY IDEOGRAPH-F964;Lo;0;L;78FB;;;;N;;;;;
-F965;CJK COMPATIBILITY IDEOGRAPH-F965;Lo;0;L;4FBF;;;;N;;;;;
-F966;CJK COMPATIBILITY IDEOGRAPH-F966;Lo;0;L;5FA9;;;;N;;;;;
-F967;CJK COMPATIBILITY IDEOGRAPH-F967;Lo;0;L;4E0D;;;;N;;;;;
-F968;CJK COMPATIBILITY IDEOGRAPH-F968;Lo;0;L;6CCC;;;;N;;;;;
-F969;CJK COMPATIBILITY IDEOGRAPH-F969;Lo;0;L;6578;;;;N;;;;;
-F96A;CJK COMPATIBILITY IDEOGRAPH-F96A;Lo;0;L;7D22;;;;N;;;;;
-F96B;CJK COMPATIBILITY IDEOGRAPH-F96B;Lo;0;L;53C3;;;3;N;;;;;
-F96C;CJK COMPATIBILITY IDEOGRAPH-F96C;Lo;0;L;585E;;;;N;;;;;
-F96D;CJK COMPATIBILITY IDEOGRAPH-F96D;Lo;0;L;7701;;;;N;;;;;
-F96E;CJK COMPATIBILITY IDEOGRAPH-F96E;Lo;0;L;8449;;;;N;;;;;
-F96F;CJK COMPATIBILITY IDEOGRAPH-F96F;Lo;0;L;8AAA;;;;N;;;;;
-F970;CJK COMPATIBILITY IDEOGRAPH-F970;Lo;0;L;6BBA;;;;N;;;;;
-F971;CJK COMPATIBILITY IDEOGRAPH-F971;Lo;0;L;8FB0;;;;N;;;;;
-F972;CJK COMPATIBILITY IDEOGRAPH-F972;Lo;0;L;6C88;;;;N;;;;;
-F973;CJK COMPATIBILITY IDEOGRAPH-F973;Lo;0;L;62FE;;;10;N;;;;;
-F974;CJK COMPATIBILITY IDEOGRAPH-F974;Lo;0;L;82E5;;;;N;;;;;
-F975;CJK COMPATIBILITY IDEOGRAPH-F975;Lo;0;L;63A0;;;;N;;;;;
-F976;CJK COMPATIBILITY IDEOGRAPH-F976;Lo;0;L;7565;;;;N;;;;;
-F977;CJK COMPATIBILITY IDEOGRAPH-F977;Lo;0;L;4EAE;;;;N;;;;;
-F978;CJK COMPATIBILITY IDEOGRAPH-F978;Lo;0;L;5169;;;2;N;;;;;
-F979;CJK COMPATIBILITY IDEOGRAPH-F979;Lo;0;L;51C9;;;;N;;;;;
-F97A;CJK COMPATIBILITY IDEOGRAPH-F97A;Lo;0;L;6881;;;;N;;;;;
-F97B;CJK COMPATIBILITY IDEOGRAPH-F97B;Lo;0;L;7CE7;;;;N;;;;;
-F97C;CJK COMPATIBILITY IDEOGRAPH-F97C;Lo;0;L;826F;;;;N;;;;;
-F97D;CJK COMPATIBILITY IDEOGRAPH-F97D;Lo;0;L;8AD2;;;;N;;;;;
-F97E;CJK COMPATIBILITY IDEOGRAPH-F97E;Lo;0;L;91CF;;;;N;;;;;
-F97F;CJK COMPATIBILITY IDEOGRAPH-F97F;Lo;0;L;52F5;;;;N;;;;;
-F980;CJK COMPATIBILITY IDEOGRAPH-F980;Lo;0;L;5442;;;;N;;;;;
-F981;CJK COMPATIBILITY IDEOGRAPH-F981;Lo;0;L;5973;;;;N;;;;;
-F982;CJK COMPATIBILITY IDEOGRAPH-F982;Lo;0;L;5EEC;;;;N;;;;;
-F983;CJK COMPATIBILITY IDEOGRAPH-F983;Lo;0;L;65C5;;;;N;;;;;
-F984;CJK COMPATIBILITY IDEOGRAPH-F984;Lo;0;L;6FFE;;;;N;;;;;
-F985;CJK COMPATIBILITY IDEOGRAPH-F985;Lo;0;L;792A;;;;N;;;;;
-F986;CJK COMPATIBILITY IDEOGRAPH-F986;Lo;0;L;95AD;;;;N;;;;;
-F987;CJK COMPATIBILITY IDEOGRAPH-F987;Lo;0;L;9A6A;;;;N;;;;;
-F988;CJK COMPATIBILITY IDEOGRAPH-F988;Lo;0;L;9E97;;;;N;;;;;
-F989;CJK COMPATIBILITY IDEOGRAPH-F989;Lo;0;L;9ECE;;;;N;;;;;
-F98A;CJK COMPATIBILITY IDEOGRAPH-F98A;Lo;0;L;529B;;;;N;;;;;
-F98B;CJK COMPATIBILITY IDEOGRAPH-F98B;Lo;0;L;66C6;;;;N;;;;;
-F98C;CJK COMPATIBILITY IDEOGRAPH-F98C;Lo;0;L;6B77;;;;N;;;;;
-F98D;CJK COMPATIBILITY IDEOGRAPH-F98D;Lo;0;L;8F62;;;;N;;;;;
-F98E;CJK COMPATIBILITY IDEOGRAPH-F98E;Lo;0;L;5E74;;;;N;;;;;
-F98F;CJK COMPATIBILITY IDEOGRAPH-F98F;Lo;0;L;6190;;;;N;;;;;
-F990;CJK COMPATIBILITY IDEOGRAPH-F990;Lo;0;L;6200;;;;N;;;;;
-F991;CJK COMPATIBILITY IDEOGRAPH-F991;Lo;0;L;649A;;;;N;;;;;
-F992;CJK COMPATIBILITY IDEOGRAPH-F992;Lo;0;L;6F23;;;;N;;;;;
-F993;CJK COMPATIBILITY IDEOGRAPH-F993;Lo;0;L;7149;;;;N;;;;;
-F994;CJK COMPATIBILITY IDEOGRAPH-F994;Lo;0;L;7489;;;;N;;;;;
-F995;CJK COMPATIBILITY IDEOGRAPH-F995;Lo;0;L;79CA;;;;N;;;;;
-F996;CJK COMPATIBILITY IDEOGRAPH-F996;Lo;0;L;7DF4;;;;N;;;;;
-F997;CJK COMPATIBILITY IDEOGRAPH-F997;Lo;0;L;806F;;;;N;;;;;
-F998;CJK COMPATIBILITY IDEOGRAPH-F998;Lo;0;L;8F26;;;;N;;;;;
-F999;CJK COMPATIBILITY IDEOGRAPH-F999;Lo;0;L;84EE;;;;N;;;;;
-F99A;CJK COMPATIBILITY IDEOGRAPH-F99A;Lo;0;L;9023;;;;N;;;;;
-F99B;CJK COMPATIBILITY IDEOGRAPH-F99B;Lo;0;L;934A;;;;N;;;;;
-F99C;CJK COMPATIBILITY IDEOGRAPH-F99C;Lo;0;L;5217;;;;N;;;;;
-F99D;CJK COMPATIBILITY IDEOGRAPH-F99D;Lo;0;L;52A3;;;;N;;;;;
-F99E;CJK COMPATIBILITY IDEOGRAPH-F99E;Lo;0;L;54BD;;;;N;;;;;
-F99F;CJK COMPATIBILITY IDEOGRAPH-F99F;Lo;0;L;70C8;;;;N;;;;;
-F9A0;CJK COMPATIBILITY IDEOGRAPH-F9A0;Lo;0;L;88C2;;;;N;;;;;
-F9A1;CJK COMPATIBILITY IDEOGRAPH-F9A1;Lo;0;L;8AAA;;;;N;;;;;
-F9A2;CJK COMPATIBILITY IDEOGRAPH-F9A2;Lo;0;L;5EC9;;;;N;;;;;
-F9A3;CJK COMPATIBILITY IDEOGRAPH-F9A3;Lo;0;L;5FF5;;;;N;;;;;
-F9A4;CJK COMPATIBILITY IDEOGRAPH-F9A4;Lo;0;L;637B;;;;N;;;;;
-F9A5;CJK COMPATIBILITY IDEOGRAPH-F9A5;Lo;0;L;6BAE;;;;N;;;;;
-F9A6;CJK COMPATIBILITY IDEOGRAPH-F9A6;Lo;0;L;7C3E;;;;N;;;;;
-F9A7;CJK COMPATIBILITY IDEOGRAPH-F9A7;Lo;0;L;7375;;;;N;;;;;
-F9A8;CJK COMPATIBILITY IDEOGRAPH-F9A8;Lo;0;L;4EE4;;;;N;;;;;
-F9A9;CJK COMPATIBILITY IDEOGRAPH-F9A9;Lo;0;L;56F9;;;;N;;;;;
-F9AA;CJK COMPATIBILITY IDEOGRAPH-F9AA;Lo;0;L;5BE7;;;;N;;;;;
-F9AB;CJK COMPATIBILITY IDEOGRAPH-F9AB;Lo;0;L;5DBA;;;;N;;;;;
-F9AC;CJK COMPATIBILITY IDEOGRAPH-F9AC;Lo;0;L;601C;;;;N;;;;;
-F9AD;CJK COMPATIBILITY IDEOGRAPH-F9AD;Lo;0;L;73B2;;;;N;;;;;
-F9AE;CJK COMPATIBILITY IDEOGRAPH-F9AE;Lo;0;L;7469;;;;N;;;;;
-F9AF;CJK COMPATIBILITY IDEOGRAPH-F9AF;Lo;0;L;7F9A;;;;N;;;;;
-F9B0;CJK COMPATIBILITY IDEOGRAPH-F9B0;Lo;0;L;8046;;;;N;;;;;
-F9B1;CJK COMPATIBILITY IDEOGRAPH-F9B1;Lo;0;L;9234;;;;N;;;;;
-F9B2;CJK COMPATIBILITY IDEOGRAPH-F9B2;Lo;0;L;96F6;;;0;N;;;;;
-F9B3;CJK COMPATIBILITY IDEOGRAPH-F9B3;Lo;0;L;9748;;;;N;;;;;
-F9B4;CJK COMPATIBILITY IDEOGRAPH-F9B4;Lo;0;L;9818;;;;N;;;;;
-F9B5;CJK COMPATIBILITY IDEOGRAPH-F9B5;Lo;0;L;4F8B;;;;N;;;;;
-F9B6;CJK COMPATIBILITY IDEOGRAPH-F9B6;Lo;0;L;79AE;;;;N;;;;;
-F9B7;CJK COMPATIBILITY IDEOGRAPH-F9B7;Lo;0;L;91B4;;;;N;;;;;
-F9B8;CJK COMPATIBILITY IDEOGRAPH-F9B8;Lo;0;L;96B8;;;;N;;;;;
-F9B9;CJK COMPATIBILITY IDEOGRAPH-F9B9;Lo;0;L;60E1;;;;N;;;;;
-F9BA;CJK COMPATIBILITY IDEOGRAPH-F9BA;Lo;0;L;4E86;;;;N;;;;;
-F9BB;CJK COMPATIBILITY IDEOGRAPH-F9BB;Lo;0;L;50DA;;;;N;;;;;
-F9BC;CJK COMPATIBILITY IDEOGRAPH-F9BC;Lo;0;L;5BEE;;;;N;;;;;
-F9BD;CJK COMPATIBILITY IDEOGRAPH-F9BD;Lo;0;L;5C3F;;;;N;;;;;
-F9BE;CJK COMPATIBILITY IDEOGRAPH-F9BE;Lo;0;L;6599;;;;N;;;;;
-F9BF;CJK COMPATIBILITY IDEOGRAPH-F9BF;Lo;0;L;6A02;;;;N;;;;;
-F9C0;CJK COMPATIBILITY IDEOGRAPH-F9C0;Lo;0;L;71CE;;;;N;;;;;
-F9C1;CJK COMPATIBILITY IDEOGRAPH-F9C1;Lo;0;L;7642;;;;N;;;;;
-F9C2;CJK COMPATIBILITY IDEOGRAPH-F9C2;Lo;0;L;84FC;;;;N;;;;;
-F9C3;CJK COMPATIBILITY IDEOGRAPH-F9C3;Lo;0;L;907C;;;;N;;;;;
-F9C4;CJK COMPATIBILITY IDEOGRAPH-F9C4;Lo;0;L;9F8D;;;;N;;;;;
-F9C5;CJK COMPATIBILITY IDEOGRAPH-F9C5;Lo;0;L;6688;;;;N;;;;;
-F9C6;CJK COMPATIBILITY IDEOGRAPH-F9C6;Lo;0;L;962E;;;;N;;;;;
-F9C7;CJK COMPATIBILITY IDEOGRAPH-F9C7;Lo;0;L;5289;;;;N;;;;;
-F9C8;CJK COMPATIBILITY IDEOGRAPH-F9C8;Lo;0;L;677B;;;;N;;;;;
-F9C9;CJK COMPATIBILITY IDEOGRAPH-F9C9;Lo;0;L;67F3;;;;N;;;;;
-F9CA;CJK COMPATIBILITY IDEOGRAPH-F9CA;Lo;0;L;6D41;;;;N;;;;;
-F9CB;CJK COMPATIBILITY IDEOGRAPH-F9CB;Lo;0;L;6E9C;;;;N;;;;;
-F9CC;CJK COMPATIBILITY IDEOGRAPH-F9CC;Lo;0;L;7409;;;;N;;;;;
-F9CD;CJK COMPATIBILITY IDEOGRAPH-F9CD;Lo;0;L;7559;;;;N;;;;;
-F9CE;CJK COMPATIBILITY IDEOGRAPH-F9CE;Lo;0;L;786B;;;;N;;;;;
-F9CF;CJK COMPATIBILITY IDEOGRAPH-F9CF;Lo;0;L;7D10;;;;N;;;;;
-F9D0;CJK COMPATIBILITY IDEOGRAPH-F9D0;Lo;0;L;985E;;;;N;;;;;
-F9D1;CJK COMPATIBILITY IDEOGRAPH-F9D1;Lo;0;L;516D;;;6;N;;;;;
-F9D2;CJK COMPATIBILITY IDEOGRAPH-F9D2;Lo;0;L;622E;;;;N;;;;;
-F9D3;CJK COMPATIBILITY IDEOGRAPH-F9D3;Lo;0;L;9678;;;6;N;;;;;
-F9D4;CJK COMPATIBILITY IDEOGRAPH-F9D4;Lo;0;L;502B;;;;N;;;;;
-F9D5;CJK COMPATIBILITY IDEOGRAPH-F9D5;Lo;0;L;5D19;;;;N;;;;;
-F9D6;CJK COMPATIBILITY IDEOGRAPH-F9D6;Lo;0;L;6DEA;;;;N;;;;;
-F9D7;CJK COMPATIBILITY IDEOGRAPH-F9D7;Lo;0;L;8F2A;;;;N;;;;;
-F9D8;CJK COMPATIBILITY IDEOGRAPH-F9D8;Lo;0;L;5F8B;;;;N;;;;;
-F9D9;CJK COMPATIBILITY IDEOGRAPH-F9D9;Lo;0;L;6144;;;;N;;;;;
-F9DA;CJK COMPATIBILITY IDEOGRAPH-F9DA;Lo;0;L;6817;;;;N;;;;;
-F9DB;CJK COMPATIBILITY IDEOGRAPH-F9DB;Lo;0;L;7387;;;;N;;;;;
-F9DC;CJK COMPATIBILITY IDEOGRAPH-F9DC;Lo;0;L;9686;;;;N;;;;;
-F9DD;CJK COMPATIBILITY IDEOGRAPH-F9DD;Lo;0;L;5229;;;;N;;;;;
-F9DE;CJK COMPATIBILITY IDEOGRAPH-F9DE;Lo;0;L;540F;;;;N;;;;;
-F9DF;CJK COMPATIBILITY IDEOGRAPH-F9DF;Lo;0;L;5C65;;;;N;;;;;
-F9E0;CJK COMPATIBILITY IDEOGRAPH-F9E0;Lo;0;L;6613;;;;N;;;;;
-F9E1;CJK COMPATIBILITY IDEOGRAPH-F9E1;Lo;0;L;674E;;;;N;;;;;
-F9E2;CJK COMPATIBILITY IDEOGRAPH-F9E2;Lo;0;L;68A8;;;;N;;;;;
-F9E3;CJK COMPATIBILITY IDEOGRAPH-F9E3;Lo;0;L;6CE5;;;;N;;;;;
-F9E4;CJK COMPATIBILITY IDEOGRAPH-F9E4;Lo;0;L;7406;;;;N;;;;;
-F9E5;CJK COMPATIBILITY IDEOGRAPH-F9E5;Lo;0;L;75E2;;;;N;;;;;
-F9E6;CJK COMPATIBILITY IDEOGRAPH-F9E6;Lo;0;L;7F79;;;;N;;;;;
-F9E7;CJK COMPATIBILITY IDEOGRAPH-F9E7;Lo;0;L;88CF;;;;N;;;;;
-F9E8;CJK COMPATIBILITY IDEOGRAPH-F9E8;Lo;0;L;88E1;;;;N;;;;;
-F9E9;CJK COMPATIBILITY IDEOGRAPH-F9E9;Lo;0;L;91CC;;;;N;;;;;
-F9EA;CJK COMPATIBILITY IDEOGRAPH-F9EA;Lo;0;L;96E2;;;;N;;;;;
-F9EB;CJK COMPATIBILITY IDEOGRAPH-F9EB;Lo;0;L;533F;;;;N;;;;;
-F9EC;CJK COMPATIBILITY IDEOGRAPH-F9EC;Lo;0;L;6EBA;;;;N;;;;;
-F9ED;CJK COMPATIBILITY IDEOGRAPH-F9ED;Lo;0;L;541D;;;;N;;;;;
-F9EE;CJK COMPATIBILITY IDEOGRAPH-F9EE;Lo;0;L;71D0;;;;N;;;;;
-F9EF;CJK COMPATIBILITY IDEOGRAPH-F9EF;Lo;0;L;7498;;;;N;;;;;
-F9F0;CJK COMPATIBILITY IDEOGRAPH-F9F0;Lo;0;L;85FA;;;;N;;;;;
-F9F1;CJK COMPATIBILITY IDEOGRAPH-F9F1;Lo;0;L;96A3;;;;N;;;;;
-F9F2;CJK COMPATIBILITY IDEOGRAPH-F9F2;Lo;0;L;9C57;;;;N;;;;;
-F9F3;CJK COMPATIBILITY IDEOGRAPH-F9F3;Lo;0;L;9E9F;;;;N;;;;;
-F9F4;CJK COMPATIBILITY IDEOGRAPH-F9F4;Lo;0;L;6797;;;;N;;;;;
-F9F5;CJK COMPATIBILITY IDEOGRAPH-F9F5;Lo;0;L;6DCB;;;;N;;;;;
-F9F6;CJK COMPATIBILITY IDEOGRAPH-F9F6;Lo;0;L;81E8;;;;N;;;;;
-F9F7;CJK COMPATIBILITY IDEOGRAPH-F9F7;Lo;0;L;7ACB;;;;N;;;;;
-F9F8;CJK COMPATIBILITY IDEOGRAPH-F9F8;Lo;0;L;7B20;;;;N;;;;;
-F9F9;CJK COMPATIBILITY IDEOGRAPH-F9F9;Lo;0;L;7C92;;;;N;;;;;
-F9FA;CJK COMPATIBILITY IDEOGRAPH-F9FA;Lo;0;L;72C0;;;;N;;;;;
-F9FB;CJK COMPATIBILITY IDEOGRAPH-F9FB;Lo;0;L;7099;;;;N;;;;;
-F9FC;CJK COMPATIBILITY IDEOGRAPH-F9FC;Lo;0;L;8B58;;;;N;;;;;
-F9FD;CJK COMPATIBILITY IDEOGRAPH-F9FD;Lo;0;L;4EC0;;;10;N;;;;;
-F9FE;CJK COMPATIBILITY IDEOGRAPH-F9FE;Lo;0;L;8336;;;;N;;;;;
-F9FF;CJK COMPATIBILITY IDEOGRAPH-F9FF;Lo;0;L;523A;;;;N;;;;;
-FA00;CJK COMPATIBILITY IDEOGRAPH-FA00;Lo;0;L;5207;;;;N;;;;;
-FA01;CJK COMPATIBILITY IDEOGRAPH-FA01;Lo;0;L;5EA6;;;;N;;;;;
-FA02;CJK COMPATIBILITY IDEOGRAPH-FA02;Lo;0;L;62D3;;;;N;;;;;
-FA03;CJK COMPATIBILITY IDEOGRAPH-FA03;Lo;0;L;7CD6;;;;N;;;;;
-FA04;CJK COMPATIBILITY IDEOGRAPH-FA04;Lo;0;L;5B85;;;;N;;;;;
-FA05;CJK COMPATIBILITY IDEOGRAPH-FA05;Lo;0;L;6D1E;;;;N;;;;;
-FA06;CJK COMPATIBILITY IDEOGRAPH-FA06;Lo;0;L;66B4;;;;N;;;;;
-FA07;CJK COMPATIBILITY IDEOGRAPH-FA07;Lo;0;L;8F3B;;;;N;;;;;
-FA08;CJK COMPATIBILITY IDEOGRAPH-FA08;Lo;0;L;884C;;;;N;;;;;
-FA09;CJK COMPATIBILITY IDEOGRAPH-FA09;Lo;0;L;964D;;;;N;;;;;
-FA0A;CJK COMPATIBILITY IDEOGRAPH-FA0A;Lo;0;L;898B;;;;N;;;;;
-FA0B;CJK COMPATIBILITY IDEOGRAPH-FA0B;Lo;0;L;5ED3;;;;N;;;;;
-FA0C;CJK COMPATIBILITY IDEOGRAPH-FA0C;Lo;0;L;5140;;;;N;;;;;
-FA0D;CJK COMPATIBILITY IDEOGRAPH-FA0D;Lo;0;L;55C0;;;;N;;;;;
-FA0E;CJK COMPATIBILITY IDEOGRAPH-FA0E;Lo;0;L;;;;;N;;;;;
-FA0F;CJK COMPATIBILITY IDEOGRAPH-FA0F;Lo;0;L;;;;;N;;;;;
-FA10;CJK COMPATIBILITY IDEOGRAPH-FA10;Lo;0;L;585A;;;;N;;;;;
-FA11;CJK COMPATIBILITY IDEOGRAPH-FA11;Lo;0;L;;;;;N;;;;;
-FA12;CJK COMPATIBILITY IDEOGRAPH-FA12;Lo;0;L;6674;;;;N;;;;;
-FA13;CJK COMPATIBILITY IDEOGRAPH-FA13;Lo;0;L;;;;;N;;;;;
-FA14;CJK COMPATIBILITY IDEOGRAPH-FA14;Lo;0;L;;;;;N;;;;;
-FA15;CJK COMPATIBILITY IDEOGRAPH-FA15;Lo;0;L;51DE;;;;N;;;;;
-FA16;CJK COMPATIBILITY IDEOGRAPH-FA16;Lo;0;L;732A;;;;N;;;;;
-FA17;CJK COMPATIBILITY IDEOGRAPH-FA17;Lo;0;L;76CA;;;;N;;;;;
-FA18;CJK COMPATIBILITY IDEOGRAPH-FA18;Lo;0;L;793C;;;;N;;;;;
-FA19;CJK COMPATIBILITY IDEOGRAPH-FA19;Lo;0;L;795E;;;;N;;;;;
-FA1A;CJK COMPATIBILITY IDEOGRAPH-FA1A;Lo;0;L;7965;;;;N;;;;;
-FA1B;CJK COMPATIBILITY IDEOGRAPH-FA1B;Lo;0;L;798F;;;;N;;;;;
-FA1C;CJK COMPATIBILITY IDEOGRAPH-FA1C;Lo;0;L;9756;;;;N;;;;;
-FA1D;CJK COMPATIBILITY IDEOGRAPH-FA1D;Lo;0;L;7CBE;;;;N;;;;;
-FA1E;CJK COMPATIBILITY IDEOGRAPH-FA1E;Lo;0;L;7FBD;;;;N;;;;;
-FA1F;CJK COMPATIBILITY IDEOGRAPH-FA1F;Lo;0;L;;;;;N;;;;;
-FA20;CJK COMPATIBILITY IDEOGRAPH-FA20;Lo;0;L;8612;;;;N;;;;;
-FA21;CJK COMPATIBILITY IDEOGRAPH-FA21;Lo;0;L;;;;;N;;;;;
-FA22;CJK COMPATIBILITY IDEOGRAPH-FA22;Lo;0;L;8AF8;;;;N;;;;;
-FA23;CJK COMPATIBILITY IDEOGRAPH-FA23;Lo;0;L;;;;;N;;;;;
-FA24;CJK COMPATIBILITY IDEOGRAPH-FA24;Lo;0;L;;;;;N;;;;;
-FA25;CJK COMPATIBILITY IDEOGRAPH-FA25;Lo;0;L;9038;;;;N;;;;;
-FA26;CJK COMPATIBILITY IDEOGRAPH-FA26;Lo;0;L;90FD;;;;N;;;;;
-FA27;CJK COMPATIBILITY IDEOGRAPH-FA27;Lo;0;L;;;;;N;;;;;
-FA28;CJK COMPATIBILITY IDEOGRAPH-FA28;Lo;0;L;;;;;N;;;;;
-FA29;CJK COMPATIBILITY IDEOGRAPH-FA29;Lo;0;L;;;;;N;;;;;
-FA2A;CJK COMPATIBILITY IDEOGRAPH-FA2A;Lo;0;L;98EF;;;;N;;;;;
-FA2B;CJK COMPATIBILITY IDEOGRAPH-FA2B;Lo;0;L;98FC;;;;N;;;;;
-FA2C;CJK COMPATIBILITY IDEOGRAPH-FA2C;Lo;0;L;9928;;;;N;;;;;
-FA2D;CJK COMPATIBILITY IDEOGRAPH-FA2D;Lo;0;L;9DB4;;;;N;;;;;
-FA2E;CJK COMPATIBILITY IDEOGRAPH-FA2E;Lo;0;L;90DE;;;;N;;;;;
-FA2F;CJK COMPATIBILITY IDEOGRAPH-FA2F;Lo;0;L;96B7;;;;N;;;;;
-FA30;CJK COMPATIBILITY IDEOGRAPH-FA30;Lo;0;L;4FAE;;;;N;;;;;
-FA31;CJK COMPATIBILITY IDEOGRAPH-FA31;Lo;0;L;50E7;;;;N;;;;;
-FA32;CJK COMPATIBILITY IDEOGRAPH-FA32;Lo;0;L;514D;;;;N;;;;;
-FA33;CJK COMPATIBILITY IDEOGRAPH-FA33;Lo;0;L;52C9;;;;N;;;;;
-FA34;CJK COMPATIBILITY IDEOGRAPH-FA34;Lo;0;L;52E4;;;;N;;;;;
-FA35;CJK COMPATIBILITY IDEOGRAPH-FA35;Lo;0;L;5351;;;;N;;;;;
-FA36;CJK COMPATIBILITY IDEOGRAPH-FA36;Lo;0;L;559D;;;;N;;;;;
-FA37;CJK COMPATIBILITY IDEOGRAPH-FA37;Lo;0;L;5606;;;;N;;;;;
-FA38;CJK COMPATIBILITY IDEOGRAPH-FA38;Lo;0;L;5668;;;;N;;;;;
-FA39;CJK COMPATIBILITY IDEOGRAPH-FA39;Lo;0;L;5840;;;;N;;;;;
-FA3A;CJK COMPATIBILITY IDEOGRAPH-FA3A;Lo;0;L;58A8;;;;N;;;;;
-FA3B;CJK COMPATIBILITY IDEOGRAPH-FA3B;Lo;0;L;5C64;;;;N;;;;;
-FA3C;CJK COMPATIBILITY IDEOGRAPH-FA3C;Lo;0;L;5C6E;;;;N;;;;;
-FA3D;CJK COMPATIBILITY IDEOGRAPH-FA3D;Lo;0;L;6094;;;;N;;;;;
-FA3E;CJK COMPATIBILITY IDEOGRAPH-FA3E;Lo;0;L;6168;;;;N;;;;;
-FA3F;CJK COMPATIBILITY IDEOGRAPH-FA3F;Lo;0;L;618E;;;;N;;;;;
-FA40;CJK COMPATIBILITY IDEOGRAPH-FA40;Lo;0;L;61F2;;;;N;;;;;
-FA41;CJK COMPATIBILITY IDEOGRAPH-FA41;Lo;0;L;654F;;;;N;;;;;
-FA42;CJK COMPATIBILITY IDEOGRAPH-FA42;Lo;0;L;65E2;;;;N;;;;;
-FA43;CJK COMPATIBILITY IDEOGRAPH-FA43;Lo;0;L;6691;;;;N;;;;;
-FA44;CJK COMPATIBILITY IDEOGRAPH-FA44;Lo;0;L;6885;;;;N;;;;;
-FA45;CJK COMPATIBILITY IDEOGRAPH-FA45;Lo;0;L;6D77;;;;N;;;;;
-FA46;CJK COMPATIBILITY IDEOGRAPH-FA46;Lo;0;L;6E1A;;;;N;;;;;
-FA47;CJK COMPATIBILITY IDEOGRAPH-FA47;Lo;0;L;6F22;;;;N;;;;;
-FA48;CJK COMPATIBILITY IDEOGRAPH-FA48;Lo;0;L;716E;;;;N;;;;;
-FA49;CJK COMPATIBILITY IDEOGRAPH-FA49;Lo;0;L;722B;;;;N;;;;;
-FA4A;CJK COMPATIBILITY IDEOGRAPH-FA4A;Lo;0;L;7422;;;;N;;;;;
-FA4B;CJK COMPATIBILITY IDEOGRAPH-FA4B;Lo;0;L;7891;;;;N;;;;;
-FA4C;CJK COMPATIBILITY IDEOGRAPH-FA4C;Lo;0;L;793E;;;;N;;;;;
-FA4D;CJK COMPATIBILITY IDEOGRAPH-FA4D;Lo;0;L;7949;;;;N;;;;;
-FA4E;CJK COMPATIBILITY IDEOGRAPH-FA4E;Lo;0;L;7948;;;;N;;;;;
-FA4F;CJK COMPATIBILITY IDEOGRAPH-FA4F;Lo;0;L;7950;;;;N;;;;;
-FA50;CJK COMPATIBILITY IDEOGRAPH-FA50;Lo;0;L;7956;;;;N;;;;;
-FA51;CJK COMPATIBILITY IDEOGRAPH-FA51;Lo;0;L;795D;;;;N;;;;;
-FA52;CJK COMPATIBILITY IDEOGRAPH-FA52;Lo;0;L;798D;;;;N;;;;;
-FA53;CJK COMPATIBILITY IDEOGRAPH-FA53;Lo;0;L;798E;;;;N;;;;;
-FA54;CJK COMPATIBILITY IDEOGRAPH-FA54;Lo;0;L;7A40;;;;N;;;;;
-FA55;CJK COMPATIBILITY IDEOGRAPH-FA55;Lo;0;L;7A81;;;;N;;;;;
-FA56;CJK COMPATIBILITY IDEOGRAPH-FA56;Lo;0;L;7BC0;;;;N;;;;;
-FA57;CJK COMPATIBILITY IDEOGRAPH-FA57;Lo;0;L;7DF4;;;;N;;;;;
-FA58;CJK COMPATIBILITY IDEOGRAPH-FA58;Lo;0;L;7E09;;;;N;;;;;
-FA59;CJK COMPATIBILITY IDEOGRAPH-FA59;Lo;0;L;7E41;;;;N;;;;;
-FA5A;CJK COMPATIBILITY IDEOGRAPH-FA5A;Lo;0;L;7F72;;;;N;;;;;
-FA5B;CJK COMPATIBILITY IDEOGRAPH-FA5B;Lo;0;L;8005;;;;N;;;;;
-FA5C;CJK COMPATIBILITY IDEOGRAPH-FA5C;Lo;0;L;81ED;;;;N;;;;;
-FA5D;CJK COMPATIBILITY IDEOGRAPH-FA5D;Lo;0;L;8279;;;;N;;;;;
-FA5E;CJK COMPATIBILITY IDEOGRAPH-FA5E;Lo;0;L;8279;;;;N;;;;;
-FA5F;CJK COMPATIBILITY IDEOGRAPH-FA5F;Lo;0;L;8457;;;;N;;;;;
-FA60;CJK COMPATIBILITY IDEOGRAPH-FA60;Lo;0;L;8910;;;;N;;;;;
-FA61;CJK COMPATIBILITY IDEOGRAPH-FA61;Lo;0;L;8996;;;;N;;;;;
-FA62;CJK COMPATIBILITY IDEOGRAPH-FA62;Lo;0;L;8B01;;;;N;;;;;
-FA63;CJK COMPATIBILITY IDEOGRAPH-FA63;Lo;0;L;8B39;;;;N;;;;;
-FA64;CJK COMPATIBILITY IDEOGRAPH-FA64;Lo;0;L;8CD3;;;;N;;;;;
-FA65;CJK COMPATIBILITY IDEOGRAPH-FA65;Lo;0;L;8D08;;;;N;;;;;
-FA66;CJK COMPATIBILITY IDEOGRAPH-FA66;Lo;0;L;8FB6;;;;N;;;;;
-FA67;CJK COMPATIBILITY IDEOGRAPH-FA67;Lo;0;L;9038;;;;N;;;;;
-FA68;CJK COMPATIBILITY IDEOGRAPH-FA68;Lo;0;L;96E3;;;;N;;;;;
-FA69;CJK COMPATIBILITY IDEOGRAPH-FA69;Lo;0;L;97FF;;;;N;;;;;
-FA6A;CJK COMPATIBILITY IDEOGRAPH-FA6A;Lo;0;L;983B;;;;N;;;;;
-FA6B;CJK COMPATIBILITY IDEOGRAPH-FA6B;Lo;0;L;6075;;;;N;;;;;
-FA6C;CJK COMPATIBILITY IDEOGRAPH-FA6C;Lo;0;L;242EE;;;;N;;;;;
-FA6D;CJK COMPATIBILITY IDEOGRAPH-FA6D;Lo;0;L;8218;;;;N;;;;;
-FA70;CJK COMPATIBILITY IDEOGRAPH-FA70;Lo;0;L;4E26;;;;N;;;;;
-FA71;CJK COMPATIBILITY IDEOGRAPH-FA71;Lo;0;L;51B5;;;;N;;;;;
-FA72;CJK COMPATIBILITY IDEOGRAPH-FA72;Lo;0;L;5168;;;;N;;;;;
-FA73;CJK COMPATIBILITY IDEOGRAPH-FA73;Lo;0;L;4F80;;;;N;;;;;
-FA74;CJK COMPATIBILITY IDEOGRAPH-FA74;Lo;0;L;5145;;;;N;;;;;
-FA75;CJK COMPATIBILITY IDEOGRAPH-FA75;Lo;0;L;5180;;;;N;;;;;
-FA76;CJK COMPATIBILITY IDEOGRAPH-FA76;Lo;0;L;52C7;;;;N;;;;;
-FA77;CJK COMPATIBILITY IDEOGRAPH-FA77;Lo;0;L;52FA;;;;N;;;;;
-FA78;CJK COMPATIBILITY IDEOGRAPH-FA78;Lo;0;L;559D;;;;N;;;;;
-FA79;CJK COMPATIBILITY IDEOGRAPH-FA79;Lo;0;L;5555;;;;N;;;;;
-FA7A;CJK COMPATIBILITY IDEOGRAPH-FA7A;Lo;0;L;5599;;;;N;;;;;
-FA7B;CJK COMPATIBILITY IDEOGRAPH-FA7B;Lo;0;L;55E2;;;;N;;;;;
-FA7C;CJK COMPATIBILITY IDEOGRAPH-FA7C;Lo;0;L;585A;;;;N;;;;;
-FA7D;CJK COMPATIBILITY IDEOGRAPH-FA7D;Lo;0;L;58B3;;;;N;;;;;
-FA7E;CJK COMPATIBILITY IDEOGRAPH-FA7E;Lo;0;L;5944;;;;N;;;;;
-FA7F;CJK COMPATIBILITY IDEOGRAPH-FA7F;Lo;0;L;5954;;;;N;;;;;
-FA80;CJK COMPATIBILITY IDEOGRAPH-FA80;Lo;0;L;5A62;;;;N;;;;;
-FA81;CJK COMPATIBILITY IDEOGRAPH-FA81;Lo;0;L;5B28;;;;N;;;;;
-FA82;CJK COMPATIBILITY IDEOGRAPH-FA82;Lo;0;L;5ED2;;;;N;;;;;
-FA83;CJK COMPATIBILITY IDEOGRAPH-FA83;Lo;0;L;5ED9;;;;N;;;;;
-FA84;CJK COMPATIBILITY IDEOGRAPH-FA84;Lo;0;L;5F69;;;;N;;;;;
-FA85;CJK COMPATIBILITY IDEOGRAPH-FA85;Lo;0;L;5FAD;;;;N;;;;;
-FA86;CJK COMPATIBILITY IDEOGRAPH-FA86;Lo;0;L;60D8;;;;N;;;;;
-FA87;CJK COMPATIBILITY IDEOGRAPH-FA87;Lo;0;L;614E;;;;N;;;;;
-FA88;CJK COMPATIBILITY IDEOGRAPH-FA88;Lo;0;L;6108;;;;N;;;;;
-FA89;CJK COMPATIBILITY IDEOGRAPH-FA89;Lo;0;L;618E;;;;N;;;;;
-FA8A;CJK COMPATIBILITY IDEOGRAPH-FA8A;Lo;0;L;6160;;;;N;;;;;
-FA8B;CJK COMPATIBILITY IDEOGRAPH-FA8B;Lo;0;L;61F2;;;;N;;;;;
-FA8C;CJK COMPATIBILITY IDEOGRAPH-FA8C;Lo;0;L;6234;;;;N;;;;;
-FA8D;CJK COMPATIBILITY IDEOGRAPH-FA8D;Lo;0;L;63C4;;;;N;;;;;
-FA8E;CJK COMPATIBILITY IDEOGRAPH-FA8E;Lo;0;L;641C;;;;N;;;;;
-FA8F;CJK COMPATIBILITY IDEOGRAPH-FA8F;Lo;0;L;6452;;;;N;;;;;
-FA90;CJK COMPATIBILITY IDEOGRAPH-FA90;Lo;0;L;6556;;;;N;;;;;
-FA91;CJK COMPATIBILITY IDEOGRAPH-FA91;Lo;0;L;6674;;;;N;;;;;
-FA92;CJK COMPATIBILITY IDEOGRAPH-FA92;Lo;0;L;6717;;;;N;;;;;
-FA93;CJK COMPATIBILITY IDEOGRAPH-FA93;Lo;0;L;671B;;;;N;;;;;
-FA94;CJK COMPATIBILITY IDEOGRAPH-FA94;Lo;0;L;6756;;;;N;;;;;
-FA95;CJK COMPATIBILITY IDEOGRAPH-FA95;Lo;0;L;6B79;;;;N;;;;;
-FA96;CJK COMPATIBILITY IDEOGRAPH-FA96;Lo;0;L;6BBA;;;;N;;;;;
-FA97;CJK COMPATIBILITY IDEOGRAPH-FA97;Lo;0;L;6D41;;;;N;;;;;
-FA98;CJK COMPATIBILITY IDEOGRAPH-FA98;Lo;0;L;6EDB;;;;N;;;;;
-FA99;CJK COMPATIBILITY IDEOGRAPH-FA99;Lo;0;L;6ECB;;;;N;;;;;
-FA9A;CJK COMPATIBILITY IDEOGRAPH-FA9A;Lo;0;L;6F22;;;;N;;;;;
-FA9B;CJK COMPATIBILITY IDEOGRAPH-FA9B;Lo;0;L;701E;;;;N;;;;;
-FA9C;CJK COMPATIBILITY IDEOGRAPH-FA9C;Lo;0;L;716E;;;;N;;;;;
-FA9D;CJK COMPATIBILITY IDEOGRAPH-FA9D;Lo;0;L;77A7;;;;N;;;;;
-FA9E;CJK COMPATIBILITY IDEOGRAPH-FA9E;Lo;0;L;7235;;;;N;;;;;
-FA9F;CJK COMPATIBILITY IDEOGRAPH-FA9F;Lo;0;L;72AF;;;;N;;;;;
-FAA0;CJK COMPATIBILITY IDEOGRAPH-FAA0;Lo;0;L;732A;;;;N;;;;;
-FAA1;CJK COMPATIBILITY IDEOGRAPH-FAA1;Lo;0;L;7471;;;;N;;;;;
-FAA2;CJK COMPATIBILITY IDEOGRAPH-FAA2;Lo;0;L;7506;;;;N;;;;;
-FAA3;CJK COMPATIBILITY IDEOGRAPH-FAA3;Lo;0;L;753B;;;;N;;;;;
-FAA4;CJK COMPATIBILITY IDEOGRAPH-FAA4;Lo;0;L;761D;;;;N;;;;;
-FAA5;CJK COMPATIBILITY IDEOGRAPH-FAA5;Lo;0;L;761F;;;;N;;;;;
-FAA6;CJK COMPATIBILITY IDEOGRAPH-FAA6;Lo;0;L;76CA;;;;N;;;;;
-FAA7;CJK COMPATIBILITY IDEOGRAPH-FAA7;Lo;0;L;76DB;;;;N;;;;;
-FAA8;CJK COMPATIBILITY IDEOGRAPH-FAA8;Lo;0;L;76F4;;;;N;;;;;
-FAA9;CJK COMPATIBILITY IDEOGRAPH-FAA9;Lo;0;L;774A;;;;N;;;;;
-FAAA;CJK COMPATIBILITY IDEOGRAPH-FAAA;Lo;0;L;7740;;;;N;;;;;
-FAAB;CJK COMPATIBILITY IDEOGRAPH-FAAB;Lo;0;L;78CC;;;;N;;;;;
-FAAC;CJK COMPATIBILITY IDEOGRAPH-FAAC;Lo;0;L;7AB1;;;;N;;;;;
-FAAD;CJK COMPATIBILITY IDEOGRAPH-FAAD;Lo;0;L;7BC0;;;;N;;;;;
-FAAE;CJK COMPATIBILITY IDEOGRAPH-FAAE;Lo;0;L;7C7B;;;;N;;;;;
-FAAF;CJK COMPATIBILITY IDEOGRAPH-FAAF;Lo;0;L;7D5B;;;;N;;;;;
-FAB0;CJK COMPATIBILITY IDEOGRAPH-FAB0;Lo;0;L;7DF4;;;;N;;;;;
-FAB1;CJK COMPATIBILITY IDEOGRAPH-FAB1;Lo;0;L;7F3E;;;;N;;;;;
-FAB2;CJK COMPATIBILITY IDEOGRAPH-FAB2;Lo;0;L;8005;;;;N;;;;;
-FAB3;CJK COMPATIBILITY IDEOGRAPH-FAB3;Lo;0;L;8352;;;;N;;;;;
-FAB4;CJK COMPATIBILITY IDEOGRAPH-FAB4;Lo;0;L;83EF;;;;N;;;;;
-FAB5;CJK COMPATIBILITY IDEOGRAPH-FAB5;Lo;0;L;8779;;;;N;;;;;
-FAB6;CJK COMPATIBILITY IDEOGRAPH-FAB6;Lo;0;L;8941;;;;N;;;;;
-FAB7;CJK COMPATIBILITY IDEOGRAPH-FAB7;Lo;0;L;8986;;;;N;;;;;
-FAB8;CJK COMPATIBILITY IDEOGRAPH-FAB8;Lo;0;L;8996;;;;N;;;;;
-FAB9;CJK COMPATIBILITY IDEOGRAPH-FAB9;Lo;0;L;8ABF;;;;N;;;;;
-FABA;CJK COMPATIBILITY IDEOGRAPH-FABA;Lo;0;L;8AF8;;;;N;;;;;
-FABB;CJK COMPATIBILITY IDEOGRAPH-FABB;Lo;0;L;8ACB;;;;N;;;;;
-FABC;CJK COMPATIBILITY IDEOGRAPH-FABC;Lo;0;L;8B01;;;;N;;;;;
-FABD;CJK COMPATIBILITY IDEOGRAPH-FABD;Lo;0;L;8AFE;;;;N;;;;;
-FABE;CJK COMPATIBILITY IDEOGRAPH-FABE;Lo;0;L;8AED;;;;N;;;;;
-FABF;CJK COMPATIBILITY IDEOGRAPH-FABF;Lo;0;L;8B39;;;;N;;;;;
-FAC0;CJK COMPATIBILITY IDEOGRAPH-FAC0;Lo;0;L;8B8A;;;;N;;;;;
-FAC1;CJK COMPATIBILITY IDEOGRAPH-FAC1;Lo;0;L;8D08;;;;N;;;;;
-FAC2;CJK COMPATIBILITY IDEOGRAPH-FAC2;Lo;0;L;8F38;;;;N;;;;;
-FAC3;CJK COMPATIBILITY IDEOGRAPH-FAC3;Lo;0;L;9072;;;;N;;;;;
-FAC4;CJK COMPATIBILITY IDEOGRAPH-FAC4;Lo;0;L;9199;;;;N;;;;;
-FAC5;CJK COMPATIBILITY IDEOGRAPH-FAC5;Lo;0;L;9276;;;;N;;;;;
-FAC6;CJK COMPATIBILITY IDEOGRAPH-FAC6;Lo;0;L;967C;;;;N;;;;;
-FAC7;CJK COMPATIBILITY IDEOGRAPH-FAC7;Lo;0;L;96E3;;;;N;;;;;
-FAC8;CJK COMPATIBILITY IDEOGRAPH-FAC8;Lo;0;L;9756;;;;N;;;;;
-FAC9;CJK COMPATIBILITY IDEOGRAPH-FAC9;Lo;0;L;97DB;;;;N;;;;;
-FACA;CJK COMPATIBILITY IDEOGRAPH-FACA;Lo;0;L;97FF;;;;N;;;;;
-FACB;CJK COMPATIBILITY IDEOGRAPH-FACB;Lo;0;L;980B;;;;N;;;;;
-FACC;CJK COMPATIBILITY IDEOGRAPH-FACC;Lo;0;L;983B;;;;N;;;;;
-FACD;CJK COMPATIBILITY IDEOGRAPH-FACD;Lo;0;L;9B12;;;;N;;;;;
-FACE;CJK COMPATIBILITY IDEOGRAPH-FACE;Lo;0;L;9F9C;;;;N;;;;;
-FACF;CJK COMPATIBILITY IDEOGRAPH-FACF;Lo;0;L;2284A;;;;N;;;;;
-FAD0;CJK COMPATIBILITY IDEOGRAPH-FAD0;Lo;0;L;22844;;;;N;;;;;
-FAD1;CJK COMPATIBILITY IDEOGRAPH-FAD1;Lo;0;L;233D5;;;;N;;;;;
-FAD2;CJK COMPATIBILITY IDEOGRAPH-FAD2;Lo;0;L;3B9D;;;;N;;;;;
-FAD3;CJK COMPATIBILITY IDEOGRAPH-FAD3;Lo;0;L;4018;;;;N;;;;;
-FAD4;CJK COMPATIBILITY IDEOGRAPH-FAD4;Lo;0;L;4039;;;;N;;;;;
-FAD5;CJK COMPATIBILITY IDEOGRAPH-FAD5;Lo;0;L;25249;;;;N;;;;;
-FAD6;CJK COMPATIBILITY IDEOGRAPH-FAD6;Lo;0;L;25CD0;;;;N;;;;;
-FAD7;CJK COMPATIBILITY IDEOGRAPH-FAD7;Lo;0;L;27ED3;;;;N;;;;;
-FAD8;CJK COMPATIBILITY IDEOGRAPH-FAD8;Lo;0;L;9F43;;;;N;;;;;
-FAD9;CJK COMPATIBILITY IDEOGRAPH-FAD9;Lo;0;L;9F8E;;;;N;;;;;
-FB00;LATIN SMALL LIGATURE FF;Ll;0;L;<compat> 0066 0066;;;;N;;;;;
-FB01;LATIN SMALL LIGATURE FI;Ll;0;L;<compat> 0066 0069;;;;N;;;;;
-FB02;LATIN SMALL LIGATURE FL;Ll;0;L;<compat> 0066 006C;;;;N;;;;;
-FB03;LATIN SMALL LIGATURE FFI;Ll;0;L;<compat> 0066 0066 0069;;;;N;;;;;
-FB04;LATIN SMALL LIGATURE FFL;Ll;0;L;<compat> 0066 0066 006C;;;;N;;;;;
-FB05;LATIN SMALL LIGATURE LONG S T;Ll;0;L;<compat> 017F 0074;;;;N;;;;;
-FB06;LATIN SMALL LIGATURE ST;Ll;0;L;<compat> 0073 0074;;;;N;;;;;
-FB13;ARMENIAN SMALL LIGATURE MEN NOW;Ll;0;L;<compat> 0574 0576;;;;N;;;;;
-FB14;ARMENIAN SMALL LIGATURE MEN ECH;Ll;0;L;<compat> 0574 0565;;;;N;;;;;
-FB15;ARMENIAN SMALL LIGATURE MEN INI;Ll;0;L;<compat> 0574 056B;;;;N;;;;;
-FB16;ARMENIAN SMALL LIGATURE VEW NOW;Ll;0;L;<compat> 057E 0576;;;;N;;;;;
-FB17;ARMENIAN SMALL LIGATURE MEN XEH;Ll;0;L;<compat> 0574 056D;;;;N;;;;;
-FB1D;HEBREW LETTER YOD WITH HIRIQ;Lo;0;R;05D9 05B4;;;;N;;;;;
-FB1E;HEBREW POINT JUDEO-SPANISH VARIKA;Mn;26;NSM;;;;;N;HEBREW POINT VARIKA;;;;
-FB1F;HEBREW LIGATURE YIDDISH YOD YOD PATAH;Lo;0;R;05F2 05B7;;;;N;;;;;
-FB20;HEBREW LETTER ALTERNATIVE AYIN;Lo;0;R;<font> 05E2;;;;N;;;;;
-FB21;HEBREW LETTER WIDE ALEF;Lo;0;R;<font> 05D0;;;;N;;;;;
-FB22;HEBREW LETTER WIDE DALET;Lo;0;R;<font> 05D3;;;;N;;;;;
-FB23;HEBREW LETTER WIDE HE;Lo;0;R;<font> 05D4;;;;N;;;;;
-FB24;HEBREW LETTER WIDE KAF;Lo;0;R;<font> 05DB;;;;N;;;;;
-FB25;HEBREW LETTER WIDE LAMED;Lo;0;R;<font> 05DC;;;;N;;;;;
-FB26;HEBREW LETTER WIDE FINAL MEM;Lo;0;R;<font> 05DD;;;;N;;;;;
-FB27;HEBREW LETTER WIDE RESH;Lo;0;R;<font> 05E8;;;;N;;;;;
-FB28;HEBREW LETTER WIDE TAV;Lo;0;R;<font> 05EA;;;;N;;;;;
-FB29;HEBREW LETTER ALTERNATIVE PLUS SIGN;Sm;0;ES;<font> 002B;;;;N;;;;;
-FB2A;HEBREW LETTER SHIN WITH SHIN DOT;Lo;0;R;05E9 05C1;;;;N;;;;;
-FB2B;HEBREW LETTER SHIN WITH SIN DOT;Lo;0;R;05E9 05C2;;;;N;;;;;
-FB2C;HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT;Lo;0;R;FB49 05C1;;;;N;;;;;
-FB2D;HEBREW LETTER SHIN WITH DAGESH AND SIN DOT;Lo;0;R;FB49 05C2;;;;N;;;;;
-FB2E;HEBREW LETTER ALEF WITH PATAH;Lo;0;R;05D0 05B7;;;;N;;;;;
-FB2F;HEBREW LETTER ALEF WITH QAMATS;Lo;0;R;05D0 05B8;;;;N;;;;;
-FB30;HEBREW LETTER ALEF WITH MAPIQ;Lo;0;R;05D0 05BC;;;;N;;;;;
-FB31;HEBREW LETTER BET WITH DAGESH;Lo;0;R;05D1 05BC;;;;N;;;;;
-FB32;HEBREW LETTER GIMEL WITH DAGESH;Lo;0;R;05D2 05BC;;;;N;;;;;
-FB33;HEBREW LETTER DALET WITH DAGESH;Lo;0;R;05D3 05BC;;;;N;;;;;
-FB34;HEBREW LETTER HE WITH MAPIQ;Lo;0;R;05D4 05BC;;;;N;;;;;
-FB35;HEBREW LETTER VAV WITH DAGESH;Lo;0;R;05D5 05BC;;;;N;;;;;
-FB36;HEBREW LETTER ZAYIN WITH DAGESH;Lo;0;R;05D6 05BC;;;;N;;;;;
-FB38;HEBREW LETTER TET WITH DAGESH;Lo;0;R;05D8 05BC;;;;N;;;;;
-FB39;HEBREW LETTER YOD WITH DAGESH;Lo;0;R;05D9 05BC;;;;N;;;;;
-FB3A;HEBREW LETTER FINAL KAF WITH DAGESH;Lo;0;R;05DA 05BC;;;;N;;;;;
-FB3B;HEBREW LETTER KAF WITH DAGESH;Lo;0;R;05DB 05BC;;;;N;;;;;
-FB3C;HEBREW LETTER LAMED WITH DAGESH;Lo;0;R;05DC 05BC;;;;N;;;;;
-FB3E;HEBREW LETTER MEM WITH DAGESH;Lo;0;R;05DE 05BC;;;;N;;;;;
-FB40;HEBREW LETTER NUN WITH DAGESH;Lo;0;R;05E0 05BC;;;;N;;;;;
-FB41;HEBREW LETTER SAMEKH WITH DAGESH;Lo;0;R;05E1 05BC;;;;N;;;;;
-FB43;HEBREW LETTER FINAL PE WITH DAGESH;Lo;0;R;05E3 05BC;;;;N;;;;;
-FB44;HEBREW LETTER PE WITH DAGESH;Lo;0;R;05E4 05BC;;;;N;;;;;
-FB46;HEBREW LETTER TSADI WITH DAGESH;Lo;0;R;05E6 05BC;;;;N;;;;;
-FB47;HEBREW LETTER QOF WITH DAGESH;Lo;0;R;05E7 05BC;;;;N;;;;;
-FB48;HEBREW LETTER RESH WITH DAGESH;Lo;0;R;05E8 05BC;;;;N;;;;;
-FB49;HEBREW LETTER SHIN WITH DAGESH;Lo;0;R;05E9 05BC;;;;N;;;;;
-FB4A;HEBREW LETTER TAV WITH DAGESH;Lo;0;R;05EA 05BC;;;;N;;;;;
-FB4B;HEBREW LETTER VAV WITH HOLAM;Lo;0;R;05D5 05B9;;;;N;;;;;
-FB4C;HEBREW LETTER BET WITH RAFE;Lo;0;R;05D1 05BF;;;;N;;;;;
-FB4D;HEBREW LETTER KAF WITH RAFE;Lo;0;R;05DB 05BF;;;;N;;;;;
-FB4E;HEBREW LETTER PE WITH RAFE;Lo;0;R;05E4 05BF;;;;N;;;;;
-FB4F;HEBREW LIGATURE ALEF LAMED;Lo;0;R;<compat> 05D0 05DC;;;;N;;;;;
-FB50;ARABIC LETTER ALEF WASLA ISOLATED FORM;Lo;0;AL;<isolated> 0671;;;;N;;;;;
-FB51;ARABIC LETTER ALEF WASLA FINAL FORM;Lo;0;AL;<final> 0671;;;;N;;;;;
-FB52;ARABIC LETTER BEEH ISOLATED FORM;Lo;0;AL;<isolated> 067B;;;;N;;;;;
-FB53;ARABIC LETTER BEEH FINAL FORM;Lo;0;AL;<final> 067B;;;;N;;;;;
-FB54;ARABIC LETTER BEEH INITIAL FORM;Lo;0;AL;<initial> 067B;;;;N;;;;;
-FB55;ARABIC LETTER BEEH MEDIAL FORM;Lo;0;AL;<medial> 067B;;;;N;;;;;
-FB56;ARABIC LETTER PEH ISOLATED FORM;Lo;0;AL;<isolated> 067E;;;;N;;;;;
-FB57;ARABIC LETTER PEH FINAL FORM;Lo;0;AL;<final> 067E;;;;N;;;;;
-FB58;ARABIC LETTER PEH INITIAL FORM;Lo;0;AL;<initial> 067E;;;;N;;;;;
-FB59;ARABIC LETTER PEH MEDIAL FORM;Lo;0;AL;<medial> 067E;;;;N;;;;;
-FB5A;ARABIC LETTER BEHEH ISOLATED FORM;Lo;0;AL;<isolated> 0680;;;;N;;;;;
-FB5B;ARABIC LETTER BEHEH FINAL FORM;Lo;0;AL;<final> 0680;;;;N;;;;;
-FB5C;ARABIC LETTER BEHEH INITIAL FORM;Lo;0;AL;<initial> 0680;;;;N;;;;;
-FB5D;ARABIC LETTER BEHEH MEDIAL FORM;Lo;0;AL;<medial> 0680;;;;N;;;;;
-FB5E;ARABIC LETTER TTEHEH ISOLATED FORM;Lo;0;AL;<isolated> 067A;;;;N;;;;;
-FB5F;ARABIC LETTER TTEHEH FINAL FORM;Lo;0;AL;<final> 067A;;;;N;;;;;
-FB60;ARABIC LETTER TTEHEH INITIAL FORM;Lo;0;AL;<initial> 067A;;;;N;;;;;
-FB61;ARABIC LETTER TTEHEH MEDIAL FORM;Lo;0;AL;<medial> 067A;;;;N;;;;;
-FB62;ARABIC LETTER TEHEH ISOLATED FORM;Lo;0;AL;<isolated> 067F;;;;N;;;;;
-FB63;ARABIC LETTER TEHEH FINAL FORM;Lo;0;AL;<final> 067F;;;;N;;;;;
-FB64;ARABIC LETTER TEHEH INITIAL FORM;Lo;0;AL;<initial> 067F;;;;N;;;;;
-FB65;ARABIC LETTER TEHEH MEDIAL FORM;Lo;0;AL;<medial> 067F;;;;N;;;;;
-FB66;ARABIC LETTER TTEH ISOLATED FORM;Lo;0;AL;<isolated> 0679;;;;N;;;;;
-FB67;ARABIC LETTER TTEH FINAL FORM;Lo;0;AL;<final> 0679;;;;N;;;;;
-FB68;ARABIC LETTER TTEH INITIAL FORM;Lo;0;AL;<initial> 0679;;;;N;;;;;
-FB69;ARABIC LETTER TTEH MEDIAL FORM;Lo;0;AL;<medial> 0679;;;;N;;;;;
-FB6A;ARABIC LETTER VEH ISOLATED FORM;Lo;0;AL;<isolated> 06A4;;;;N;;;;;
-FB6B;ARABIC LETTER VEH FINAL FORM;Lo;0;AL;<final> 06A4;;;;N;;;;;
-FB6C;ARABIC LETTER VEH INITIAL FORM;Lo;0;AL;<initial> 06A4;;;;N;;;;;
-FB6D;ARABIC LETTER VEH MEDIAL FORM;Lo;0;AL;<medial> 06A4;;;;N;;;;;
-FB6E;ARABIC LETTER PEHEH ISOLATED FORM;Lo;0;AL;<isolated> 06A6;;;;N;;;;;
-FB6F;ARABIC LETTER PEHEH FINAL FORM;Lo;0;AL;<final> 06A6;;;;N;;;;;
-FB70;ARABIC LETTER PEHEH INITIAL FORM;Lo;0;AL;<initial> 06A6;;;;N;;;;;
-FB71;ARABIC LETTER PEHEH MEDIAL FORM;Lo;0;AL;<medial> 06A6;;;;N;;;;;
-FB72;ARABIC LETTER DYEH ISOLATED FORM;Lo;0;AL;<isolated> 0684;;;;N;;;;;
-FB73;ARABIC LETTER DYEH FINAL FORM;Lo;0;AL;<final> 0684;;;;N;;;;;
-FB74;ARABIC LETTER DYEH INITIAL FORM;Lo;0;AL;<initial> 0684;;;;N;;;;;
-FB75;ARABIC LETTER DYEH MEDIAL FORM;Lo;0;AL;<medial> 0684;;;;N;;;;;
-FB76;ARABIC LETTER NYEH ISOLATED FORM;Lo;0;AL;<isolated> 0683;;;;N;;;;;
-FB77;ARABIC LETTER NYEH FINAL FORM;Lo;0;AL;<final> 0683;;;;N;;;;;
-FB78;ARABIC LETTER NYEH INITIAL FORM;Lo;0;AL;<initial> 0683;;;;N;;;;;
-FB79;ARABIC LETTER NYEH MEDIAL FORM;Lo;0;AL;<medial> 0683;;;;N;;;;;
-FB7A;ARABIC LETTER TCHEH ISOLATED FORM;Lo;0;AL;<isolated> 0686;;;;N;;;;;
-FB7B;ARABIC LETTER TCHEH FINAL FORM;Lo;0;AL;<final> 0686;;;;N;;;;;
-FB7C;ARABIC LETTER TCHEH INITIAL FORM;Lo;0;AL;<initial> 0686;;;;N;;;;;
-FB7D;ARABIC LETTER TCHEH MEDIAL FORM;Lo;0;AL;<medial> 0686;;;;N;;;;;
-FB7E;ARABIC LETTER TCHEHEH ISOLATED FORM;Lo;0;AL;<isolated> 0687;;;;N;;;;;
-FB7F;ARABIC LETTER TCHEHEH FINAL FORM;Lo;0;AL;<final> 0687;;;;N;;;;;
-FB80;ARABIC LETTER TCHEHEH INITIAL FORM;Lo;0;AL;<initial> 0687;;;;N;;;;;
-FB81;ARABIC LETTER TCHEHEH MEDIAL FORM;Lo;0;AL;<medial> 0687;;;;N;;;;;
-FB82;ARABIC LETTER DDAHAL ISOLATED FORM;Lo;0;AL;<isolated> 068D;;;;N;;;;;
-FB83;ARABIC LETTER DDAHAL FINAL FORM;Lo;0;AL;<final> 068D;;;;N;;;;;
-FB84;ARABIC LETTER DAHAL ISOLATED FORM;Lo;0;AL;<isolated> 068C;;;;N;;;;;
-FB85;ARABIC LETTER DAHAL FINAL FORM;Lo;0;AL;<final> 068C;;;;N;;;;;
-FB86;ARABIC LETTER DUL ISOLATED FORM;Lo;0;AL;<isolated> 068E;;;;N;;;;;
-FB87;ARABIC LETTER DUL FINAL FORM;Lo;0;AL;<final> 068E;;;;N;;;;;
-FB88;ARABIC LETTER DDAL ISOLATED FORM;Lo;0;AL;<isolated> 0688;;;;N;;;;;
-FB89;ARABIC LETTER DDAL FINAL FORM;Lo;0;AL;<final> 0688;;;;N;;;;;
-FB8A;ARABIC LETTER JEH ISOLATED FORM;Lo;0;AL;<isolated> 0698;;;;N;;;;;
-FB8B;ARABIC LETTER JEH FINAL FORM;Lo;0;AL;<final> 0698;;;;N;;;;;
-FB8C;ARABIC LETTER RREH ISOLATED FORM;Lo;0;AL;<isolated> 0691;;;;N;;;;;
-FB8D;ARABIC LETTER RREH FINAL FORM;Lo;0;AL;<final> 0691;;;;N;;;;;
-FB8E;ARABIC LETTER KEHEH ISOLATED FORM;Lo;0;AL;<isolated> 06A9;;;;N;;;;;
-FB8F;ARABIC LETTER KEHEH FINAL FORM;Lo;0;AL;<final> 06A9;;;;N;;;;;
-FB90;ARABIC LETTER KEHEH INITIAL FORM;Lo;0;AL;<initial> 06A9;;;;N;;;;;
-FB91;ARABIC LETTER KEHEH MEDIAL FORM;Lo;0;AL;<medial> 06A9;;;;N;;;;;
-FB92;ARABIC LETTER GAF ISOLATED FORM;Lo;0;AL;<isolated> 06AF;;;;N;;;;;
-FB93;ARABIC LETTER GAF FINAL FORM;Lo;0;AL;<final> 06AF;;;;N;;;;;
-FB94;ARABIC LETTER GAF INITIAL FORM;Lo;0;AL;<initial> 06AF;;;;N;;;;;
-FB95;ARABIC LETTER GAF MEDIAL FORM;Lo;0;AL;<medial> 06AF;;;;N;;;;;
-FB96;ARABIC LETTER GUEH ISOLATED FORM;Lo;0;AL;<isolated> 06B3;;;;N;;;;;
-FB97;ARABIC LETTER GUEH FINAL FORM;Lo;0;AL;<final> 06B3;;;;N;;;;;
-FB98;ARABIC LETTER GUEH INITIAL FORM;Lo;0;AL;<initial> 06B3;;;;N;;;;;
-FB99;ARABIC LETTER GUEH MEDIAL FORM;Lo;0;AL;<medial> 06B3;;;;N;;;;;
-FB9A;ARABIC LETTER NGOEH ISOLATED FORM;Lo;0;AL;<isolated> 06B1;;;;N;;;;;
-FB9B;ARABIC LETTER NGOEH FINAL FORM;Lo;0;AL;<final> 06B1;;;;N;;;;;
-FB9C;ARABIC LETTER NGOEH INITIAL FORM;Lo;0;AL;<initial> 06B1;;;;N;;;;;
-FB9D;ARABIC LETTER NGOEH MEDIAL FORM;Lo;0;AL;<medial> 06B1;;;;N;;;;;
-FB9E;ARABIC LETTER NOON GHUNNA ISOLATED FORM;Lo;0;AL;<isolated> 06BA;;;;N;;;;;
-FB9F;ARABIC LETTER NOON GHUNNA FINAL FORM;Lo;0;AL;<final> 06BA;;;;N;;;;;
-FBA0;ARABIC LETTER RNOON ISOLATED FORM;Lo;0;AL;<isolated> 06BB;;;;N;;;;;
-FBA1;ARABIC LETTER RNOON FINAL FORM;Lo;0;AL;<final> 06BB;;;;N;;;;;
-FBA2;ARABIC LETTER RNOON INITIAL FORM;Lo;0;AL;<initial> 06BB;;;;N;;;;;
-FBA3;ARABIC LETTER RNOON MEDIAL FORM;Lo;0;AL;<medial> 06BB;;;;N;;;;;
-FBA4;ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 06C0;;;;N;;;;;
-FBA5;ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM;Lo;0;AL;<final> 06C0;;;;N;;;;;
-FBA6;ARABIC LETTER HEH GOAL ISOLATED FORM;Lo;0;AL;<isolated> 06C1;;;;N;;;;;
-FBA7;ARABIC LETTER HEH GOAL FINAL FORM;Lo;0;AL;<final> 06C1;;;;N;;;;;
-FBA8;ARABIC LETTER HEH GOAL INITIAL FORM;Lo;0;AL;<initial> 06C1;;;;N;;;;;
-FBA9;ARABIC LETTER HEH GOAL MEDIAL FORM;Lo;0;AL;<medial> 06C1;;;;N;;;;;
-FBAA;ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM;Lo;0;AL;<isolated> 06BE;;;;N;;;;;
-FBAB;ARABIC LETTER HEH DOACHASHMEE FINAL FORM;Lo;0;AL;<final> 06BE;;;;N;;;;;
-FBAC;ARABIC LETTER HEH DOACHASHMEE INITIAL FORM;Lo;0;AL;<initial> 06BE;;;;N;;;;;
-FBAD;ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM;Lo;0;AL;<medial> 06BE;;;;N;;;;;
-FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL;<isolated> 06D2;;;;N;;;;;
-FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL;<final> 06D2;;;;N;;;;;
-FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 06D3;;;;N;;;;;
-FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 06D3;;;;N;;;;;
-FBB2;ARABIC SYMBOL DOT ABOVE;Sk;0;AL;;;;;N;;;;;
-FBB3;ARABIC SYMBOL DOT BELOW;Sk;0;AL;;;;;N;;;;;
-FBB4;ARABIC SYMBOL TWO DOTS ABOVE;Sk;0;AL;;;;;N;;;;;
-FBB5;ARABIC SYMBOL TWO DOTS BELOW;Sk;0;AL;;;;;N;;;;;
-FBB6;ARABIC SYMBOL THREE DOTS ABOVE;Sk;0;AL;;;;;N;;;;;
-FBB7;ARABIC SYMBOL THREE DOTS BELOW;Sk;0;AL;;;;;N;;;;;
-FBB8;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE;Sk;0;AL;;;;;N;;;;;
-FBB9;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW;Sk;0;AL;;;;;N;;;;;
-FBBA;ARABIC SYMBOL FOUR DOTS ABOVE;Sk;0;AL;;;;;N;;;;;
-FBBB;ARABIC SYMBOL FOUR DOTS BELOW;Sk;0;AL;;;;;N;;;;;
-FBBC;ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW;Sk;0;AL;;;;;N;;;;;
-FBBD;ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE;Sk;0;AL;;;;;N;;;;;
-FBBE;ARABIC SYMBOL TWO DOTS VERTICALLY BELOW;Sk;0;AL;;;;;N;;;;;
-FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;;
-FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;;
-FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;;
-FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL;<isolated> 06AD;;;;N;;;;;
-FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL;<final> 06AD;;;;N;;;;;
-FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL;<initial> 06AD;;;;N;;;;;
-FBD6;ARABIC LETTER NG MEDIAL FORM;Lo;0;AL;<medial> 06AD;;;;N;;;;;
-FBD7;ARABIC LETTER U ISOLATED FORM;Lo;0;AL;<isolated> 06C7;;;;N;;;;;
-FBD8;ARABIC LETTER U FINAL FORM;Lo;0;AL;<final> 06C7;;;;N;;;;;
-FBD9;ARABIC LETTER OE ISOLATED FORM;Lo;0;AL;<isolated> 06C6;;;;N;;;;;
-FBDA;ARABIC LETTER OE FINAL FORM;Lo;0;AL;<final> 06C6;;;;N;;;;;
-FBDB;ARABIC LETTER YU ISOLATED FORM;Lo;0;AL;<isolated> 06C8;;;;N;;;;;
-FBDC;ARABIC LETTER YU FINAL FORM;Lo;0;AL;<final> 06C8;;;;N;;;;;
-FBDD;ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0677;;;;N;;;;;
-FBDE;ARABIC LETTER VE ISOLATED FORM;Lo;0;AL;<isolated> 06CB;;;;N;;;;;
-FBDF;ARABIC LETTER VE FINAL FORM;Lo;0;AL;<final> 06CB;;;;N;;;;;
-FBE0;ARABIC LETTER KIRGHIZ OE ISOLATED FORM;Lo;0;AL;<isolated> 06C5;;;;N;;;;;
-FBE1;ARABIC LETTER KIRGHIZ OE FINAL FORM;Lo;0;AL;<final> 06C5;;;;N;;;;;
-FBE2;ARABIC LETTER KIRGHIZ YU ISOLATED FORM;Lo;0;AL;<isolated> 06C9;;;;N;;;;;
-FBE3;ARABIC LETTER KIRGHIZ YU FINAL FORM;Lo;0;AL;<final> 06C9;;;;N;;;;;
-FBE4;ARABIC LETTER E ISOLATED FORM;Lo;0;AL;<isolated> 06D0;;;;N;;;;;
-FBE5;ARABIC LETTER E FINAL FORM;Lo;0;AL;<final> 06D0;;;;N;;;;;
-FBE6;ARABIC LETTER E INITIAL FORM;Lo;0;AL;<initial> 06D0;;;;N;;;;;
-FBE7;ARABIC LETTER E MEDIAL FORM;Lo;0;AL;<medial> 06D0;;;;N;;;;;
-FBE8;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM;Lo;0;AL;<initial> 0649;;;;N;;;;;
-FBE9;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM;Lo;0;AL;<medial> 0649;;;;N;;;;;
-FBEA;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0626 0627;;;;N;;;;;
-FBEB;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM;Lo;0;AL;<final> 0626 0627;;;;N;;;;;
-FBEC;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM;Lo;0;AL;<isolated> 0626 06D5;;;;N;;;;;
-FBED;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM;Lo;0;AL;<final> 0626 06D5;;;;N;;;;;
-FBEE;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM;Lo;0;AL;<isolated> 0626 0648;;;;N;;;;;
-FBEF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM;Lo;0;AL;<final> 0626 0648;;;;N;;;;;
-FBF0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C7;;;;N;;;;;
-FBF1;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM;Lo;0;AL;<final> 0626 06C7;;;;N;;;;;
-FBF2;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C6;;;;N;;;;;
-FBF3;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM;Lo;0;AL;<final> 0626 06C6;;;;N;;;;;
-FBF4;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C8;;;;N;;;;;
-FBF5;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM;Lo;0;AL;<final> 0626 06C8;;;;N;;;;;
-FBF6;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM;Lo;0;AL;<isolated> 0626 06D0;;;;N;;;;;
-FBF7;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM;Lo;0;AL;<final> 0626 06D0;;;;N;;;;;
-FBF8;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM;Lo;0;AL;<initial> 0626 06D0;;;;N;;;;;
-FBF9;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0626 0649;;;;N;;;;;
-FBFA;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0626 0649;;;;N;;;;;
-FBFB;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM;Lo;0;AL;<initial> 0626 0649;;;;N;;;;;
-FBFC;ARABIC LETTER FARSI YEH ISOLATED FORM;Lo;0;AL;<isolated> 06CC;;;;N;;;;;
-FBFD;ARABIC LETTER FARSI YEH FINAL FORM;Lo;0;AL;<final> 06CC;;;;N;;;;;
-FBFE;ARABIC LETTER FARSI YEH INITIAL FORM;Lo;0;AL;<initial> 06CC;;;;N;;;;;
-FBFF;ARABIC LETTER FARSI YEH MEDIAL FORM;Lo;0;AL;<medial> 06CC;;;;N;;;;;
-FC00;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0626 062C;;;;N;;;;;
-FC01;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0626 062D;;;;N;;;;;
-FC02;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0626 0645;;;;N;;;;;
-FC03;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0626 0649;;;;N;;;;;
-FC04;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0626 064A;;;;N;;;;;
-FC05;ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0628 062C;;;;N;;;;;
-FC06;ARABIC LIGATURE BEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0628 062D;;;;N;;;;;
-FC07;ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0628 062E;;;;N;;;;;
-FC08;ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0628 0645;;;;N;;;;;
-FC09;ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0628 0649;;;;N;;;;;
-FC0A;ARABIC LIGATURE BEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0628 064A;;;;N;;;;;
-FC0B;ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062A 062C;;;;N;;;;;
-FC0C;ARABIC LIGATURE TEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062A 062D;;;;N;;;;;
-FC0D;ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 062A 062E;;;;N;;;;;
-FC0E;ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062A 0645;;;;N;;;;;
-FC0F;ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062A 0649;;;;N;;;;;
-FC10;ARABIC LIGATURE TEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062A 064A;;;;N;;;;;
-FC11;ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062B 062C;;;;N;;;;;
-FC12;ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062B 0645;;;;N;;;;;
-FC13;ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062B 0649;;;;N;;;;;
-FC14;ARABIC LIGATURE THEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062B 064A;;;;N;;;;;
-FC15;ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062C 062D;;;;N;;;;;
-FC16;ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062C 0645;;;;N;;;;;
-FC17;ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062D 062C;;;;N;;;;;
-FC18;ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062D 0645;;;;N;;;;;
-FC19;ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062E 062C;;;;N;;;;;
-FC1A;ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062E 062D;;;;N;;;;;
-FC1B;ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062E 0645;;;;N;;;;;
-FC1C;ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0633 062C;;;;N;;;;;
-FC1D;ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0633 062D;;;;N;;;;;
-FC1E;ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0633 062E;;;;N;;;;;
-FC1F;ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0633 0645;;;;N;;;;;
-FC20;ARABIC LIGATURE SAD WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0635 062D;;;;N;;;;;
-FC21;ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0635 0645;;;;N;;;;;
-FC22;ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0636 062C;;;;N;;;;;
-FC23;ARABIC LIGATURE DAD WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0636 062D;;;;N;;;;;
-FC24;ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0636 062E;;;;N;;;;;
-FC25;ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0636 0645;;;;N;;;;;
-FC26;ARABIC LIGATURE TAH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0637 062D;;;;N;;;;;
-FC27;ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0637 0645;;;;N;;;;;
-FC28;ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0638 0645;;;;N;;;;;
-FC29;ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0639 062C;;;;N;;;;;
-FC2A;ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0639 0645;;;;N;;;;;
-FC2B;ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 063A 062C;;;;N;;;;;
-FC2C;ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 063A 0645;;;;N;;;;;
-FC2D;ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0641 062C;;;;N;;;;;
-FC2E;ARABIC LIGATURE FEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0641 062D;;;;N;;;;;
-FC2F;ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0641 062E;;;;N;;;;;
-FC30;ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0641 0645;;;;N;;;;;
-FC31;ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0641 0649;;;;N;;;;;
-FC32;ARABIC LIGATURE FEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0641 064A;;;;N;;;;;
-FC33;ARABIC LIGATURE QAF WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0642 062D;;;;N;;;;;
-FC34;ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0642 0645;;;;N;;;;;
-FC35;ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0642 0649;;;;N;;;;;
-FC36;ARABIC LIGATURE QAF WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0642 064A;;;;N;;;;;
-FC37;ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0643 0627;;;;N;;;;;
-FC38;ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0643 062C;;;;N;;;;;
-FC39;ARABIC LIGATURE KAF WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0643 062D;;;;N;;;;;
-FC3A;ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0643 062E;;;;N;;;;;
-FC3B;ARABIC LIGATURE KAF WITH LAM ISOLATED FORM;Lo;0;AL;<isolated> 0643 0644;;;;N;;;;;
-FC3C;ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0643 0645;;;;N;;;;;
-FC3D;ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0643 0649;;;;N;;;;;
-FC3E;ARABIC LIGATURE KAF WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0643 064A;;;;N;;;;;
-FC3F;ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0644 062C;;;;N;;;;;
-FC40;ARABIC LIGATURE LAM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0644 062D;;;;N;;;;;
-FC41;ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0644 062E;;;;N;;;;;
-FC42;ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0644 0645;;;;N;;;;;
-FC43;ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0644 0649;;;;N;;;;;
-FC44;ARABIC LIGATURE LAM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0644 064A;;;;N;;;;;
-FC45;ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645 062C;;;;N;;;;;
-FC46;ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0645 062D;;;;N;;;;;
-FC47;ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0645 062E;;;;N;;;;;
-FC48;ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645 0645;;;;N;;;;;
-FC49;ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0645 0649;;;;N;;;;;
-FC4A;ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0645 064A;;;;N;;;;;
-FC4B;ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0646 062C;;;;N;;;;;
-FC4C;ARABIC LIGATURE NOON WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0646 062D;;;;N;;;;;
-FC4D;ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0646 062E;;;;N;;;;;
-FC4E;ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0646 0645;;;;N;;;;;
-FC4F;ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0646 0649;;;;N;;;;;
-FC50;ARABIC LIGATURE NOON WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0646 064A;;;;N;;;;;
-FC51;ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0647 062C;;;;N;;;;;
-FC52;ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0647 0645;;;;N;;;;;
-FC53;ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0647 0649;;;;N;;;;;
-FC54;ARABIC LIGATURE HEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0647 064A;;;;N;;;;;
-FC55;ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 064A 062C;;;;N;;;;;
-FC56;ARABIC LIGATURE YEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 064A 062D;;;;N;;;;;
-FC57;ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 064A 062E;;;;N;;;;;
-FC58;ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 064A 0645;;;;N;;;;;
-FC59;ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 064A 0649;;;;N;;;;;
-FC5A;ARABIC LIGATURE YEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 064A 064A;;;;N;;;;;
-FC5B;ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0630 0670;;;;N;;;;;
-FC5C;ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0631 0670;;;;N;;;;;
-FC5D;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0649 0670;;;;N;;;;;
-FC5E;ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064C 0651;;;;N;;;;;
-FC5F;ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064D 0651;;;;N;;;;;
-FC60;ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064E 0651;;;;N;;;;;
-FC61;ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064F 0651;;;;N;;;;;
-FC62;ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0650 0651;;;;N;;;;;
-FC63;ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0020 0651 0670;;;;N;;;;;
-FC64;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM;Lo;0;AL;<final> 0626 0631;;;;N;;;;;
-FC65;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0626 0632;;;;N;;;;;
-FC66;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM;Lo;0;AL;<final> 0626 0645;;;;N;;;;;
-FC67;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM;Lo;0;AL;<final> 0626 0646;;;;N;;;;;
-FC68;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0626 0649;;;;N;;;;;
-FC69;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM;Lo;0;AL;<final> 0626 064A;;;;N;;;;;
-FC6A;ARABIC LIGATURE BEH WITH REH FINAL FORM;Lo;0;AL;<final> 0628 0631;;;;N;;;;;
-FC6B;ARABIC LIGATURE BEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0628 0632;;;;N;;;;;
-FC6C;ARABIC LIGATURE BEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0628 0645;;;;N;;;;;
-FC6D;ARABIC LIGATURE BEH WITH NOON FINAL FORM;Lo;0;AL;<final> 0628 0646;;;;N;;;;;
-FC6E;ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0628 0649;;;;N;;;;;
-FC6F;ARABIC LIGATURE BEH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 064A;;;;N;;;;;
-FC70;ARABIC LIGATURE TEH WITH REH FINAL FORM;Lo;0;AL;<final> 062A 0631;;;;N;;;;;
-FC71;ARABIC LIGATURE TEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 062A 0632;;;;N;;;;;
-FC72;ARABIC LIGATURE TEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 062A 0645;;;;N;;;;;
-FC73;ARABIC LIGATURE TEH WITH NOON FINAL FORM;Lo;0;AL;<final> 062A 0646;;;;N;;;;;
-FC74;ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 0649;;;;N;;;;;
-FC75;ARABIC LIGATURE TEH WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 064A;;;;N;;;;;
-FC76;ARABIC LIGATURE THEH WITH REH FINAL FORM;Lo;0;AL;<final> 062B 0631;;;;N;;;;;
-FC77;ARABIC LIGATURE THEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 062B 0632;;;;N;;;;;
-FC78;ARABIC LIGATURE THEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 062B 0645;;;;N;;;;;
-FC79;ARABIC LIGATURE THEH WITH NOON FINAL FORM;Lo;0;AL;<final> 062B 0646;;;;N;;;;;
-FC7A;ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062B 0649;;;;N;;;;;
-FC7B;ARABIC LIGATURE THEH WITH YEH FINAL FORM;Lo;0;AL;<final> 062B 064A;;;;N;;;;;
-FC7C;ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0641 0649;;;;N;;;;;
-FC7D;ARABIC LIGATURE FEH WITH YEH FINAL FORM;Lo;0;AL;<final> 0641 064A;;;;N;;;;;
-FC7E;ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0642 0649;;;;N;;;;;
-FC7F;ARABIC LIGATURE QAF WITH YEH FINAL FORM;Lo;0;AL;<final> 0642 064A;;;;N;;;;;
-FC80;ARABIC LIGATURE KAF WITH ALEF FINAL FORM;Lo;0;AL;<final> 0643 0627;;;;N;;;;;
-FC81;ARABIC LIGATURE KAF WITH LAM FINAL FORM;Lo;0;AL;<final> 0643 0644;;;;N;;;;;
-FC82;ARABIC LIGATURE KAF WITH MEEM FINAL FORM;Lo;0;AL;<final> 0643 0645;;;;N;;;;;
-FC83;ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0643 0649;;;;N;;;;;
-FC84;ARABIC LIGATURE KAF WITH YEH FINAL FORM;Lo;0;AL;<final> 0643 064A;;;;N;;;;;
-FC85;ARABIC LIGATURE LAM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 0645;;;;N;;;;;
-FC86;ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0644 0649;;;;N;;;;;
-FC87;ARABIC LIGATURE LAM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 064A;;;;N;;;;;
-FC88;ARABIC LIGATURE MEEM WITH ALEF FINAL FORM;Lo;0;AL;<final> 0645 0627;;;;N;;;;;
-FC89;ARABIC LIGATURE MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0645 0645;;;;N;;;;;
-FC8A;ARABIC LIGATURE NOON WITH REH FINAL FORM;Lo;0;AL;<final> 0646 0631;;;;N;;;;;
-FC8B;ARABIC LIGATURE NOON WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0646 0632;;;;N;;;;;
-FC8C;ARABIC LIGATURE NOON WITH MEEM FINAL FORM;Lo;0;AL;<final> 0646 0645;;;;N;;;;;
-FC8D;ARABIC LIGATURE NOON WITH NOON FINAL FORM;Lo;0;AL;<final> 0646 0646;;;;N;;;;;
-FC8E;ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 0649;;;;N;;;;;
-FC8F;ARABIC LIGATURE NOON WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 064A;;;;N;;;;;
-FC90;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM;Lo;0;AL;<final> 0649 0670;;;;N;;;;;
-FC91;ARABIC LIGATURE YEH WITH REH FINAL FORM;Lo;0;AL;<final> 064A 0631;;;;N;;;;;
-FC92;ARABIC LIGATURE YEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 064A 0632;;;;N;;;;;
-FC93;ARABIC LIGATURE YEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 064A 0645;;;;N;;;;;
-FC94;ARABIC LIGATURE YEH WITH NOON FINAL FORM;Lo;0;AL;<final> 064A 0646;;;;N;;;;;
-FC95;ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 064A 0649;;;;N;;;;;
-FC96;ARABIC LIGATURE YEH WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 064A;;;;N;;;;;
-FC97;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0626 062C;;;;N;;;;;
-FC98;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0626 062D;;;;N;;;;;
-FC99;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0626 062E;;;;N;;;;;
-FC9A;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0626 0645;;;;N;;;;;
-FC9B;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0626 0647;;;;N;;;;;
-FC9C;ARABIC LIGATURE BEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0628 062C;;;;N;;;;;
-FC9D;ARABIC LIGATURE BEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0628 062D;;;;N;;;;;
-FC9E;ARABIC LIGATURE BEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0628 062E;;;;N;;;;;
-FC9F;ARABIC LIGATURE BEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0628 0645;;;;N;;;;;
-FCA0;ARABIC LIGATURE BEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0628 0647;;;;N;;;;;
-FCA1;ARABIC LIGATURE TEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C;;;;N;;;;;
-FCA2;ARABIC LIGATURE TEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062A 062D;;;;N;;;;;
-FCA3;ARABIC LIGATURE TEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 062A 062E;;;;N;;;;;
-FCA4;ARABIC LIGATURE TEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 0645;;;;N;;;;;
-FCA5;ARABIC LIGATURE TEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 062A 0647;;;;N;;;;;
-FCA6;ARABIC LIGATURE THEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062B 0645;;;;N;;;;;
-FCA7;ARABIC LIGATURE JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062C 062D;;;;N;;;;;
-FCA8;ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062C 0645;;;;N;;;;;
-FCA9;ARABIC LIGATURE HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062D 062C;;;;N;;;;;
-FCAA;ARABIC LIGATURE HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062D 0645;;;;N;;;;;
-FCAB;ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062E 062C;;;;N;;;;;
-FCAC;ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062E 0645;;;;N;;;;;
-FCAD;ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 062C;;;;N;;;;;
-FCAE;ARABIC LIGATURE SEEN WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 062D;;;;N;;;;;
-FCAF;ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0633 062E;;;;N;;;;;
-FCB0;ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645;;;;N;;;;;
-FCB1;ARABIC LIGATURE SAD WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0635 062D;;;;N;;;;;
-FCB2;ARABIC LIGATURE SAD WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0635 062E;;;;N;;;;;
-FCB3;ARABIC LIGATURE SAD WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645;;;;N;;;;;
-FCB4;ARABIC LIGATURE DAD WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0636 062C;;;;N;;;;;
-FCB5;ARABIC LIGATURE DAD WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0636 062D;;;;N;;;;;
-FCB6;ARABIC LIGATURE DAD WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0636 062E;;;;N;;;;;
-FCB7;ARABIC LIGATURE DAD WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0636 0645;;;;N;;;;;
-FCB8;ARABIC LIGATURE TAH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0637 062D;;;;N;;;;;
-FCB9;ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0638 0645;;;;N;;;;;
-FCBA;ARABIC LIGATURE AIN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0639 062C;;;;N;;;;;
-FCBB;ARABIC LIGATURE AIN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 0645;;;;N;;;;;
-FCBC;ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 063A 062C;;;;N;;;;;
-FCBD;ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 063A 0645;;;;N;;;;;
-FCBE;ARABIC LIGATURE FEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0641 062C;;;;N;;;;;
-FCBF;ARABIC LIGATURE FEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0641 062D;;;;N;;;;;
-FCC0;ARABIC LIGATURE FEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0641 062E;;;;N;;;;;
-FCC1;ARABIC LIGATURE FEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0641 0645;;;;N;;;;;
-FCC2;ARABIC LIGATURE QAF WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0642 062D;;;;N;;;;;
-FCC3;ARABIC LIGATURE QAF WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0642 0645;;;;N;;;;;
-FCC4;ARABIC LIGATURE KAF WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0643 062C;;;;N;;;;;
-FCC5;ARABIC LIGATURE KAF WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0643 062D;;;;N;;;;;
-FCC6;ARABIC LIGATURE KAF WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0643 062E;;;;N;;;;;
-FCC7;ARABIC LIGATURE KAF WITH LAM INITIAL FORM;Lo;0;AL;<initial> 0643 0644;;;;N;;;;;
-FCC8;ARABIC LIGATURE KAF WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0643 0645;;;;N;;;;;
-FCC9;ARABIC LIGATURE LAM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C;;;;N;;;;;
-FCCA;ARABIC LIGATURE LAM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0644 062D;;;;N;;;;;
-FCCB;ARABIC LIGATURE LAM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0644 062E;;;;N;;;;;
-FCCC;ARABIC LIGATURE LAM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 0645;;;;N;;;;;
-FCCD;ARABIC LIGATURE LAM WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0644 0647;;;;N;;;;;
-FCCE;ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C;;;;N;;;;;
-FCCF;ARABIC LIGATURE MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645 062D;;;;N;;;;;
-FCD0;ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062E;;;;N;;;;;
-FCD1;ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 0645;;;;N;;;;;
-FCD2;ARABIC LIGATURE NOON WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062C;;;;N;;;;;
-FCD3;ARABIC LIGATURE NOON WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0646 062D;;;;N;;;;;
-FCD4;ARABIC LIGATURE NOON WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0646 062E;;;;N;;;;;
-FCD5;ARABIC LIGATURE NOON WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 0645;;;;N;;;;;
-FCD6;ARABIC LIGATURE NOON WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0646 0647;;;;N;;;;;
-FCD7;ARABIC LIGATURE HEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 062C;;;;N;;;;;
-FCD8;ARABIC LIGATURE HEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645;;;;N;;;;;
-FCD9;ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM;Lo;0;AL;<initial> 0647 0670;;;;N;;;;;
-FCDA;ARABIC LIGATURE YEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 064A 062C;;;;N;;;;;
-FCDB;ARABIC LIGATURE YEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 064A 062D;;;;N;;;;;
-FCDC;ARABIC LIGATURE YEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 064A 062E;;;;N;;;;;
-FCDD;ARABIC LIGATURE YEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 064A 0645;;;;N;;;;;
-FCDE;ARABIC LIGATURE YEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 064A 0647;;;;N;;;;;
-FCDF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0626 0645;;;;N;;;;;
-FCE0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0626 0647;;;;N;;;;;
-FCE1;ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0628 0645;;;;N;;;;;
-FCE2;ARABIC LIGATURE BEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0628 0647;;;;N;;;;;
-FCE3;ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 062A 0645;;;;N;;;;;
-FCE4;ARABIC LIGATURE TEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 062A 0647;;;;N;;;;;
-FCE5;ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 062B 0645;;;;N;;;;;
-FCE6;ARABIC LIGATURE THEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 062B 0647;;;;N;;;;;
-FCE7;ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0633 0645;;;;N;;;;;
-FCE8;ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0633 0647;;;;N;;;;;
-FCE9;ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0634 0645;;;;N;;;;;
-FCEA;ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0634 0647;;;;N;;;;;
-FCEB;ARABIC LIGATURE KAF WITH LAM MEDIAL FORM;Lo;0;AL;<medial> 0643 0644;;;;N;;;;;
-FCEC;ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0643 0645;;;;N;;;;;
-FCED;ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0644 0645;;;;N;;;;;
-FCEE;ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0646 0645;;;;N;;;;;
-FCEF;ARABIC LIGATURE NOON WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0646 0647;;;;N;;;;;
-FCF0;ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 064A 0645;;;;N;;;;;
-FCF1;ARABIC LIGATURE YEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 064A 0647;;;;N;;;;;
-FCF2;ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM;Lo;0;AL;<medial> 0640 064E 0651;;;;N;;;;;
-FCF3;ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM;Lo;0;AL;<medial> 0640 064F 0651;;;;N;;;;;
-FCF4;ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM;Lo;0;AL;<medial> 0640 0650 0651;;;;N;;;;;
-FCF5;ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0637 0649;;;;N;;;;;
-FCF6;ARABIC LIGATURE TAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0637 064A;;;;N;;;;;
-FCF7;ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0639 0649;;;;N;;;;;
-FCF8;ARABIC LIGATURE AIN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0639 064A;;;;N;;;;;
-FCF9;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 063A 0649;;;;N;;;;;
-FCFA;ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 063A 064A;;;;N;;;;;
-FCFB;ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0633 0649;;;;N;;;;;
-FCFC;ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0633 064A;;;;N;;;;;
-FCFD;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0634 0649;;;;N;;;;;
-FCFE;ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0634 064A;;;;N;;;;;
-FCFF;ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062D 0649;;;;N;;;;;
-FD00;ARABIC LIGATURE HAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062D 064A;;;;N;;;;;
-FD01;ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062C 0649;;;;N;;;;;
-FD02;ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062C 064A;;;;N;;;;;
-FD03;ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062E 0649;;;;N;;;;;
-FD04;ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062E 064A;;;;N;;;;;
-FD05;ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0635 0649;;;;N;;;;;
-FD06;ARABIC LIGATURE SAD WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0635 064A;;;;N;;;;;
-FD07;ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0636 0649;;;;N;;;;;
-FD08;ARABIC LIGATURE DAD WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0636 064A;;;;N;;;;;
-FD09;ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0634 062C;;;;N;;;;;
-FD0A;ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0634 062D;;;;N;;;;;
-FD0B;ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0634 062E;;;;N;;;;;
-FD0C;ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0634 0645;;;;N;;;;;
-FD0D;ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0634 0631;;;;N;;;;;
-FD0E;ARABIC LIGATURE SEEN WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0633 0631;;;;N;;;;;
-FD0F;ARABIC LIGATURE SAD WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0635 0631;;;;N;;;;;
-FD10;ARABIC LIGATURE DAD WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0636 0631;;;;N;;;;;
-FD11;ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0637 0649;;;;N;;;;;
-FD12;ARABIC LIGATURE TAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0637 064A;;;;N;;;;;
-FD13;ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0639 0649;;;;N;;;;;
-FD14;ARABIC LIGATURE AIN WITH YEH FINAL FORM;Lo;0;AL;<final> 0639 064A;;;;N;;;;;
-FD15;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 063A 0649;;;;N;;;;;
-FD16;ARABIC LIGATURE GHAIN WITH YEH FINAL FORM;Lo;0;AL;<final> 063A 064A;;;;N;;;;;
-FD17;ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 0649;;;;N;;;;;
-FD18;ARABIC LIGATURE SEEN WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 064A;;;;N;;;;;
-FD19;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0634 0649;;;;N;;;;;
-FD1A;ARABIC LIGATURE SHEEN WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 064A;;;;N;;;;;
-FD1B;ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062D 0649;;;;N;;;;;
-FD1C;ARABIC LIGATURE HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 064A;;;;N;;;;;
-FD1D;ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 0649;;;;N;;;;;
-FD1E;ARABIC LIGATURE JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 064A;;;;N;;;;;
-FD1F;ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062E 0649;;;;N;;;;;
-FD20;ARABIC LIGATURE KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062E 064A;;;;N;;;;;
-FD21;ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0635 0649;;;;N;;;;;
-FD22;ARABIC LIGATURE SAD WITH YEH FINAL FORM;Lo;0;AL;<final> 0635 064A;;;;N;;;;;
-FD23;ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0636 0649;;;;N;;;;;
-FD24;ARABIC LIGATURE DAD WITH YEH FINAL FORM;Lo;0;AL;<final> 0636 064A;;;;N;;;;;
-FD25;ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM;Lo;0;AL;<final> 0634 062C;;;;N;;;;;
-FD26;ARABIC LIGATURE SHEEN WITH HAH FINAL FORM;Lo;0;AL;<final> 0634 062D;;;;N;;;;;
-FD27;ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM;Lo;0;AL;<final> 0634 062E;;;;N;;;;;
-FD28;ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 0645;;;;N;;;;;
-FD29;ARABIC LIGATURE SHEEN WITH REH FINAL FORM;Lo;0;AL;<final> 0634 0631;;;;N;;;;;
-FD2A;ARABIC LIGATURE SEEN WITH REH FINAL FORM;Lo;0;AL;<final> 0633 0631;;;;N;;;;;
-FD2B;ARABIC LIGATURE SAD WITH REH FINAL FORM;Lo;0;AL;<final> 0635 0631;;;;N;;;;;
-FD2C;ARABIC LIGATURE DAD WITH REH FINAL FORM;Lo;0;AL;<final> 0636 0631;;;;N;;;;;
-FD2D;ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0634 062C;;;;N;;;;;
-FD2E;ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0634 062D;;;;N;;;;;
-FD2F;ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0634 062E;;;;N;;;;;
-FD30;ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 0645;;;;N;;;;;
-FD31;ARABIC LIGATURE SEEN WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0633 0647;;;;N;;;;;
-FD32;ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0634 0647;;;;N;;;;;
-FD33;ARABIC LIGATURE TAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0637 0645;;;;N;;;;;
-FD34;ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM;Lo;0;AL;<medial> 0633 062C;;;;N;;;;;
-FD35;ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM;Lo;0;AL;<medial> 0633 062D;;;;N;;;;;
-FD36;ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM;Lo;0;AL;<medial> 0633 062E;;;;N;;;;;
-FD37;ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM;Lo;0;AL;<medial> 0634 062C;;;;N;;;;;
-FD38;ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM;Lo;0;AL;<medial> 0634 062D;;;;N;;;;;
-FD39;ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM;Lo;0;AL;<medial> 0634 062E;;;;N;;;;;
-FD3A;ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0637 0645;;;;N;;;;;
-FD3B;ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0638 0645;;;;N;;;;;
-FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL;<final> 0627 064B;;;;N;;;;;
-FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0627 064B;;;;N;;;;;
-FD3E;ORNATE LEFT PARENTHESIS;Ps;0;ON;;;;;N;;;;;
-FD3F;ORNATE RIGHT PARENTHESIS;Pe;0;ON;;;;;N;;;;;
-FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C 0645;;;;N;;;;;
-FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL;<final> 062A 062D 062C;;;;N;;;;;
-FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 062C;;;;N;;;;;
-FD53;ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 0645;;;;N;;;;;
-FD54;ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062E 0645;;;;N;;;;;
-FD55;ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062C;;;;N;;;;;
-FD56;ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062D;;;;N;;;;;
-FD57;ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062E;;;;N;;;;;
-FD58;ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 062C 0645 062D;;;;N;;;;;
-FD59;ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062C 0645 062D;;;;N;;;;;
-FD5A;ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 0645 064A;;;;N;;;;;
-FD5B;ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062D 0645 0649;;;;N;;;;;
-FD5C;ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 062D 062C;;;;N;;;;;
-FD5D;ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 062C 062D;;;;N;;;;;
-FD5E;ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 062C 0649;;;;N;;;;;
-FD5F;ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0633 0645 062D;;;;N;;;;;
-FD60;ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 0645 062D;;;;N;;;;;
-FD61;ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645 062C;;;;N;;;;;
-FD62;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0633 0645 0645;;;;N;;;;;
-FD63;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645 0645;;;;N;;;;;
-FD64;ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM;Lo;0;AL;<final> 0635 062D 062D;;;;N;;;;;
-FD65;ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0635 062D 062D;;;;N;;;;;
-FD66;ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0635 0645 0645;;;;N;;;;;
-FD67;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 062D 0645;;;;N;;;;;
-FD68;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 062D 0645;;;;N;;;;;
-FD69;ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 062C 064A;;;;N;;;;;
-FD6A;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM;Lo;0;AL;<final> 0634 0645 062E;;;;N;;;;;
-FD6B;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0634 0645 062E;;;;N;;;;;
-FD6C;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 0645 0645;;;;N;;;;;
-FD6D;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 0645 0645;;;;N;;;;;
-FD6E;ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0636 062D 0649;;;;N;;;;;
-FD6F;ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0636 062E 0645;;;;N;;;;;
-FD70;ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0636 062E 0645;;;;N;;;;;
-FD71;ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0637 0645 062D;;;;N;;;;;
-FD72;ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0637 0645 062D;;;;N;;;;;
-FD73;ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0637 0645 0645;;;;N;;;;;
-FD74;ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0637 0645 064A;;;;N;;;;;
-FD75;ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0639 062C 0645;;;;N;;;;;
-FD76;ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0639 0645 0645;;;;N;;;;;
-FD77;ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 0645 0645;;;;N;;;;;
-FD78;ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0639 0645 0649;;;;N;;;;;
-FD79;ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 063A 0645 0645;;;;N;;;;;
-FD7A;ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 063A 0645 064A;;;;N;;;;;
-FD7B;ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 063A 0645 0649;;;;N;;;;;
-FD7C;ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0641 062E 0645;;;;N;;;;;
-FD7D;ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0641 062E 0645;;;;N;;;;;
-FD7E;ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0642 0645 062D;;;;N;;;;;
-FD7F;ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0642 0645 0645;;;;N;;;;;
-FD80;ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062D 0645;;;;N;;;;;
-FD81;ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 062D 064A;;;;N;;;;;
-FD82;ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0644 062D 0649;;;;N;;;;;
-FD83;ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C 062C;;;;N;;;;;
-FD84;ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM;Lo;0;AL;<final> 0644 062C 062C;;;;N;;;;;
-FD85;ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062E 0645;;;;N;;;;;
-FD86;ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062E 0645;;;;N;;;;;
-FD87;ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0644 0645 062D;;;;N;;;;;
-FD88;ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0644 0645 062D;;;;N;;;;;
-FD89;ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062D 062C;;;;N;;;;;
-FD8A;ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062D 0645;;;;N;;;;;
-FD8B;ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062D 064A;;;;N;;;;;
-FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062D;;;;N;;;;;
-FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C 0645;;;;N;;;;;
-FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 062C;;;;N;;;;;
-FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 0645;;;;N;;;;;
-FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062E;;;;N;;;;;
-FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 062C;;;;N;;;;;
-FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 0645;;;;N;;;;;
-FD95;ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062D 0645;;;;N;;;;;
-FD96;ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 062D 0649;;;;N;;;;;
-FD97;ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0646 062C 0645;;;;N;;;;;
-FD98;ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062C 0645;;;;N;;;;;
-FD99;ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 062C 0649;;;;N;;;;;
-FD9A;ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 0645 064A;;;;N;;;;;
-FD9B;ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 0645 0649;;;;N;;;;;
-FD9C;ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 064A 0645 0645;;;;N;;;;;
-FD9D;ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 064A 0645 0645;;;;N;;;;;
-FD9E;ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 062E 064A;;;;N;;;;;
-FD9F;ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 062C 064A;;;;N;;;;;
-FDA0;ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 062C 0649;;;;N;;;;;
-FDA1;ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 062E 064A;;;;N;;;;;
-FDA2;ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 062E 0649;;;;N;;;;;
-FDA3;ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 0645 064A;;;;N;;;;;
-FDA4;ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 0645 0649;;;;N;;;;;
-FDA5;ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 0645 064A;;;;N;;;;;
-FDA6;ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 062D 0649;;;;N;;;;;
-FDA7;ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 0645 0649;;;;N;;;;;
-FDA8;ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 062E 0649;;;;N;;;;;
-FDA9;ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0635 062D 064A;;;;N;;;;;
-FDAA;ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 062D 064A;;;;N;;;;;
-FDAB;ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0636 062D 064A;;;;N;;;;;
-FDAC;ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 062C 064A;;;;N;;;;;
-FDAD;ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 0645 064A;;;;N;;;;;
-FDAE;ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 062D 064A;;;;N;;;;;
-FDAF;ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 062C 064A;;;;N;;;;;
-FDB0;ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 0645 064A;;;;N;;;;;
-FDB1;ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 0645 064A;;;;N;;;;;
-FDB2;ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0642 0645 064A;;;;N;;;;;
-FDB3;ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062D 064A;;;;N;;;;;
-FDB4;ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0642 0645 062D;;;;N;;;;;
-FDB5;ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062D 0645;;;;N;;;;;
-FDB6;ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0639 0645 064A;;;;N;;;;;
-FDB7;ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0643 0645 064A;;;;N;;;;;
-FDB8;ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0646 062C 062D;;;;N;;;;;
-FDB9;ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062E 064A;;;;N;;;;;
-FDBA;ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C 0645;;;;N;;;;;
-FDBB;ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0643 0645 0645;;;;N;;;;;
-FDBC;ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062C 0645;;;;N;;;;;
-FDBD;ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0646 062C 062D;;;;N;;;;;
-FDBE;ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 062D 064A;;;;N;;;;;
-FDBF;ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 062C 064A;;;;N;;;;;
-FDC0;ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062C 064A;;;;N;;;;;
-FDC1;ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0641 0645 064A;;;;N;;;;;
-FDC2;ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 062D 064A;;;;N;;;;;
-FDC3;ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0643 0645 0645;;;;N;;;;;
-FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 062C 0645;;;;N;;;;;
-FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645 0645;;;;N;;;;;
-FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 062E 064A;;;;N;;;;;
-FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062C 064A;;;;N;;;;;
-FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 06D2;;;;N;;;;;
-FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0642 0644 06D2;;;;N;;;;;
-FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL;<isolated> 0627 0644 0644 0647;;;;N;;;;;
-FDF3;ARABIC LIGATURE AKBAR ISOLATED FORM;Lo;0;AL;<isolated> 0627 0643 0628 0631;;;;N;;;;;
-FDF4;ARABIC LIGATURE MOHAMMAD ISOLATED FORM;Lo;0;AL;<isolated> 0645 062D 0645 062F;;;;N;;;;;
-FDF5;ARABIC LIGATURE SALAM ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 0639 0645;;;;N;;;;;
-FDF6;ARABIC LIGATURE RASOUL ISOLATED FORM;Lo;0;AL;<isolated> 0631 0633 0648 0644;;;;N;;;;;
-FDF7;ARABIC LIGATURE ALAYHE ISOLATED FORM;Lo;0;AL;<isolated> 0639 0644 064A 0647;;;;N;;;;;
-FDF8;ARABIC LIGATURE WASALLAM ISOLATED FORM;Lo;0;AL;<isolated> 0648 0633 0644 0645;;;;N;;;;;
-FDF9;ARABIC LIGATURE SALLA ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 0649;;;;N;;;;;
-FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL;<isolated> 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645;;;;N;ARABIC LETTER SALLALLAHOU ALAYHE WASALLAM;;;;
-FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL;<isolated> 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;;
-FDFC;RIAL SIGN;Sc;0;AL;<isolated> 0631 06CC 0627 0644;;;;N;;;;;
-FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;;
-FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;;
-FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;;
-FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;;
-FE03;VARIATION SELECTOR-4;Mn;0;NSM;;;;;N;;;;;
-FE04;VARIATION SELECTOR-5;Mn;0;NSM;;;;;N;;;;;
-FE05;VARIATION SELECTOR-6;Mn;0;NSM;;;;;N;;;;;
-FE06;VARIATION SELECTOR-7;Mn;0;NSM;;;;;N;;;;;
-FE07;VARIATION SELECTOR-8;Mn;0;NSM;;;;;N;;;;;
-FE08;VARIATION SELECTOR-9;Mn;0;NSM;;;;;N;;;;;
-FE09;VARIATION SELECTOR-10;Mn;0;NSM;;;;;N;;;;;
-FE0A;VARIATION SELECTOR-11;Mn;0;NSM;;;;;N;;;;;
-FE0B;VARIATION SELECTOR-12;Mn;0;NSM;;;;;N;;;;;
-FE0C;VARIATION SELECTOR-13;Mn;0;NSM;;;;;N;;;;;
-FE0D;VARIATION SELECTOR-14;Mn;0;NSM;;;;;N;;;;;
-FE0E;VARIATION SELECTOR-15;Mn;0;NSM;;;;;N;;;;;
-FE0F;VARIATION SELECTOR-16;Mn;0;NSM;;;;;N;;;;;
-FE10;PRESENTATION FORM FOR VERTICAL COMMA;Po;0;ON;<vertical> 002C;;;;N;;;;;
-FE11;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA;Po;0;ON;<vertical> 3001;;;;N;;;;;
-FE12;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP;Po;0;ON;<vertical> 3002;;;;N;;;;;
-FE13;PRESENTATION FORM FOR VERTICAL COLON;Po;0;ON;<vertical> 003A;;;;N;;;;;
-FE14;PRESENTATION FORM FOR VERTICAL SEMICOLON;Po;0;ON;<vertical> 003B;;;;N;;;;;
-FE15;PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK;Po;0;ON;<vertical> 0021;;;;N;;;;;
-FE16;PRESENTATION FORM FOR VERTICAL QUESTION MARK;Po;0;ON;<vertical> 003F;;;;N;;;;;
-FE17;PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;<vertical> 3016;;;;N;;;;;
-FE18;PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET;Pe;0;ON;<vertical> 3017;;;;N;;;;;
-FE19;PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS;Po;0;ON;<vertical> 2026;;;;N;;;;;
-FE20;COMBINING LIGATURE LEFT HALF;Mn;230;NSM;;;;;N;;;;;
-FE21;COMBINING LIGATURE RIGHT HALF;Mn;230;NSM;;;;;N;;;;;
-FE22;COMBINING DOUBLE TILDE LEFT HALF;Mn;230;NSM;;;;;N;;;;;
-FE23;COMBINING DOUBLE TILDE RIGHT HALF;Mn;230;NSM;;;;;N;;;;;
-FE24;COMBINING MACRON LEFT HALF;Mn;230;NSM;;;;;N;;;;;
-FE25;COMBINING MACRON RIGHT HALF;Mn;230;NSM;;;;;N;;;;;
-FE26;COMBINING CONJOINING MACRON;Mn;230;NSM;;;;;N;;;;;
-FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON;<vertical> 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;;
-FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON;<vertical> 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;;
-FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON;<vertical> 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;;
-FE33;PRESENTATION FORM FOR VERTICAL LOW LINE;Pc;0;ON;<vertical> 005F;;;;N;GLYPH FOR VERTICAL SPACING UNDERSCORE;;;;
-FE34;PRESENTATION FORM FOR VERTICAL WAVY LOW LINE;Pc;0;ON;<vertical> 005F;;;;N;GLYPH FOR VERTICAL SPACING WAVY UNDERSCORE;;;;
-FE35;PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS;Ps;0;ON;<vertical> 0028;;;;N;GLYPH FOR VERTICAL OPENING PARENTHESIS;;;;
-FE36;PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS;Pe;0;ON;<vertical> 0029;;;;N;GLYPH FOR VERTICAL CLOSING PARENTHESIS;;;;
-FE37;PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET;Ps;0;ON;<vertical> 007B;;;;N;GLYPH FOR VERTICAL OPENING CURLY BRACKET;;;;
-FE38;PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET;Pe;0;ON;<vertical> 007D;;;;N;GLYPH FOR VERTICAL CLOSING CURLY BRACKET;;;;
-FE39;PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET;Ps;0;ON;<vertical> 3014;;;;N;GLYPH FOR VERTICAL OPENING TORTOISE SHELL BRACKET;;;;
-FE3A;PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;<vertical> 3015;;;;N;GLYPH FOR VERTICAL CLOSING TORTOISE SHELL BRACKET;;;;
-FE3B;PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;<vertical> 3010;;;;N;GLYPH FOR VERTICAL OPENING BLACK LENTICULAR BRACKET;;;;
-FE3C;PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;<vertical> 3011;;;;N;GLYPH FOR VERTICAL CLOSING BLACK LENTICULAR BRACKET;;;;
-FE3D;PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;<vertical> 300A;;;;N;GLYPH FOR VERTICAL OPENING DOUBLE ANGLE BRACKET;;;;
-FE3E;PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;<vertical> 300B;;;;N;GLYPH FOR VERTICAL CLOSING DOUBLE ANGLE BRACKET;;;;
-FE3F;PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET;Ps;0;ON;<vertical> 3008;;;;N;GLYPH FOR VERTICAL OPENING ANGLE BRACKET;;;;
-FE40;PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET;Pe;0;ON;<vertical> 3009;;;;N;GLYPH FOR VERTICAL CLOSING ANGLE BRACKET;;;;
-FE41;PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET;Ps;0;ON;<vertical> 300C;;;;N;GLYPH FOR VERTICAL OPENING CORNER BRACKET;;;;
-FE42;PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET;Pe;0;ON;<vertical> 300D;;;;N;GLYPH FOR VERTICAL CLOSING CORNER BRACKET;;;;
-FE43;PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET;Ps;0;ON;<vertical> 300E;;;;N;GLYPH FOR VERTICAL OPENING WHITE CORNER BRACKET;;;;
-FE44;PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET;Pe;0;ON;<vertical> 300F;;;;N;GLYPH FOR VERTICAL CLOSING WHITE CORNER BRACKET;;;;
-FE45;SESAME DOT;Po;0;ON;;;;;N;;;;;
-FE46;WHITE SESAME DOT;Po;0;ON;;;;;N;;;;;
-FE47;PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET;Ps;0;ON;<vertical> 005B;;;;N;;;;;
-FE48;PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET;Pe;0;ON;<vertical> 005D;;;;N;;;;;
-FE49;DASHED OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING DASHED OVERSCORE;;;;
-FE4A;CENTRELINE OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING CENTERLINE OVERSCORE;;;;
-FE4B;WAVY OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING WAVY OVERSCORE;;;;
-FE4C;DOUBLE WAVY OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING DOUBLE WAVY OVERSCORE;;;;
-FE4D;DASHED LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING DASHED UNDERSCORE;;;;
-FE4E;CENTRELINE LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING CENTERLINE UNDERSCORE;;;;
-FE4F;WAVY LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING WAVY UNDERSCORE;;;;
-FE50;SMALL COMMA;Po;0;CS;<small> 002C;;;;N;;;;;
-FE51;SMALL IDEOGRAPHIC COMMA;Po;0;ON;<small> 3001;;;;N;;;;;
-FE52;SMALL FULL STOP;Po;0;CS;<small> 002E;;;;N;SMALL PERIOD;;;;
-FE54;SMALL SEMICOLON;Po;0;ON;<small> 003B;;;;N;;;;;
-FE55;SMALL COLON;Po;0;CS;<small> 003A;;;;N;;;;;
-FE56;SMALL QUESTION MARK;Po;0;ON;<small> 003F;;;;N;;;;;
-FE57;SMALL EXCLAMATION MARK;Po;0;ON;<small> 0021;;;;N;;;;;
-FE58;SMALL EM DASH;Pd;0;ON;<small> 2014;;;;N;;;;;
-FE59;SMALL LEFT PARENTHESIS;Ps;0;ON;<small> 0028;;;;Y;SMALL OPENING PARENTHESIS;;;;
-FE5A;SMALL RIGHT PARENTHESIS;Pe;0;ON;<small> 0029;;;;Y;SMALL CLOSING PARENTHESIS;;;;
-FE5B;SMALL LEFT CURLY BRACKET;Ps;0;ON;<small> 007B;;;;Y;SMALL OPENING CURLY BRACKET;;;;
-FE5C;SMALL RIGHT CURLY BRACKET;Pe;0;ON;<small> 007D;;;;Y;SMALL CLOSING CURLY BRACKET;;;;
-FE5D;SMALL LEFT TORTOISE SHELL BRACKET;Ps;0;ON;<small> 3014;;;;Y;SMALL OPENING TORTOISE SHELL BRACKET;;;;
-FE5E;SMALL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;<small> 3015;;;;Y;SMALL CLOSING TORTOISE SHELL BRACKET;;;;
-FE5F;SMALL NUMBER SIGN;Po;0;ET;<small> 0023;;;;N;;;;;
-FE60;SMALL AMPERSAND;Po;0;ON;<small> 0026;;;;N;;;;;
-FE61;SMALL ASTERISK;Po;0;ON;<small> 002A;;;;N;;;;;
-FE62;SMALL PLUS SIGN;Sm;0;ES;<small> 002B;;;;N;;;;;
-FE63;SMALL HYPHEN-MINUS;Pd;0;ES;<small> 002D;;;;N;;;;;
-FE64;SMALL LESS-THAN SIGN;Sm;0;ON;<small> 003C;;;;Y;;;;;
-FE65;SMALL GREATER-THAN SIGN;Sm;0;ON;<small> 003E;;;;Y;;;;;
-FE66;SMALL EQUALS SIGN;Sm;0;ON;<small> 003D;;;;N;;;;;
-FE68;SMALL REVERSE SOLIDUS;Po;0;ON;<small> 005C;;;;N;SMALL BACKSLASH;;;;
-FE69;SMALL DOLLAR SIGN;Sc;0;ET;<small> 0024;;;;N;;;;;
-FE6A;SMALL PERCENT SIGN;Po;0;ET;<small> 0025;;;;N;;;;;
-FE6B;SMALL COMMERCIAL AT;Po;0;ON;<small> 0040;;;;N;;;;;
-FE70;ARABIC FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064B;;;;N;ARABIC SPACING FATHATAN;;;;
-FE71;ARABIC TATWEEL WITH FATHATAN ABOVE;Lo;0;AL;<medial> 0640 064B;;;;N;ARABIC FATHATAN ON TATWEEL;;;;
-FE72;ARABIC DAMMATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064C;;;;N;ARABIC SPACING DAMMATAN;;;;
-FE73;ARABIC TAIL FRAGMENT;Lo;0;AL;;;;;N;;;;;
-FE74;ARABIC KASRATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064D;;;;N;ARABIC SPACING KASRATAN;;;;
-FE76;ARABIC FATHA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064E;;;;N;ARABIC SPACING FATHAH;;;;
-FE77;ARABIC FATHA MEDIAL FORM;Lo;0;AL;<medial> 0640 064E;;;;N;ARABIC FATHAH ON TATWEEL;;;;
-FE78;ARABIC DAMMA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064F;;;;N;ARABIC SPACING DAMMAH;;;;
-FE79;ARABIC DAMMA MEDIAL FORM;Lo;0;AL;<medial> 0640 064F;;;;N;ARABIC DAMMAH ON TATWEEL;;;;
-FE7A;ARABIC KASRA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0650;;;;N;ARABIC SPACING KASRAH;;;;
-FE7B;ARABIC KASRA MEDIAL FORM;Lo;0;AL;<medial> 0640 0650;;;;N;ARABIC KASRAH ON TATWEEL;;;;
-FE7C;ARABIC SHADDA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0651;;;;N;ARABIC SPACING SHADDAH;;;;
-FE7D;ARABIC SHADDA MEDIAL FORM;Lo;0;AL;<medial> 0640 0651;;;;N;ARABIC SHADDAH ON TATWEEL;;;;
-FE7E;ARABIC SUKUN ISOLATED FORM;Lo;0;AL;<isolated> 0020 0652;;;;N;ARABIC SPACING SUKUN;;;;
-FE7F;ARABIC SUKUN MEDIAL FORM;Lo;0;AL;<medial> 0640 0652;;;;N;ARABIC SUKUN ON TATWEEL;;;;
-FE80;ARABIC LETTER HAMZA ISOLATED FORM;Lo;0;AL;<isolated> 0621;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH;;;;
-FE81;ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON ALEF;;;;
-FE82;ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL;<final> 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON ALEF;;;;
-FE83;ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON ALEF;;;;
-FE84;ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON ALEF;;;;
-FE85;ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0624;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON WAW;;;;
-FE86;ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0624;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON WAW;;;;
-FE87;ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL;<isolated> 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER ALEF;;;;
-FE88;ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL;<final> 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER ALEF;;;;
-FE89;ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0626;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON YA;;;;
-FE8A;ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0626;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON YA;;;;
-FE8B;ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM;Lo;0;AL;<initial> 0626;;;;N;GLYPH FOR INITIAL ARABIC HAMZAH ON YA;;;;
-FE8C;ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM;Lo;0;AL;<medial> 0626;;;;N;GLYPH FOR MEDIAL ARABIC HAMZAH ON YA;;;;
-FE8D;ARABIC LETTER ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0627;;;;N;GLYPH FOR ISOLATE ARABIC ALEF;;;;
-FE8E;ARABIC LETTER ALEF FINAL FORM;Lo;0;AL;<final> 0627;;;;N;GLYPH FOR FINAL ARABIC ALEF;;;;
-FE8F;ARABIC LETTER BEH ISOLATED FORM;Lo;0;AL;<isolated> 0628;;;;N;GLYPH FOR ISOLATE ARABIC BAA;;;;
-FE90;ARABIC LETTER BEH FINAL FORM;Lo;0;AL;<final> 0628;;;;N;GLYPH FOR FINAL ARABIC BAA;;;;
-FE91;ARABIC LETTER BEH INITIAL FORM;Lo;0;AL;<initial> 0628;;;;N;GLYPH FOR INITIAL ARABIC BAA;;;;
-FE92;ARABIC LETTER BEH MEDIAL FORM;Lo;0;AL;<medial> 0628;;;;N;GLYPH FOR MEDIAL ARABIC BAA;;;;
-FE93;ARABIC LETTER TEH MARBUTA ISOLATED FORM;Lo;0;AL;<isolated> 0629;;;;N;GLYPH FOR ISOLATE ARABIC TAA MARBUTAH;;;;
-FE94;ARABIC LETTER TEH MARBUTA FINAL FORM;Lo;0;AL;<final> 0629;;;;N;GLYPH FOR FINAL ARABIC TAA MARBUTAH;;;;
-FE95;ARABIC LETTER TEH ISOLATED FORM;Lo;0;AL;<isolated> 062A;;;;N;GLYPH FOR ISOLATE ARABIC TAA;;;;
-FE96;ARABIC LETTER TEH FINAL FORM;Lo;0;AL;<final> 062A;;;;N;GLYPH FOR FINAL ARABIC TAA;;;;
-FE97;ARABIC LETTER TEH INITIAL FORM;Lo;0;AL;<initial> 062A;;;;N;GLYPH FOR INITIAL ARABIC TAA;;;;
-FE98;ARABIC LETTER TEH MEDIAL FORM;Lo;0;AL;<medial> 062A;;;;N;GLYPH FOR MEDIAL ARABIC TAA;;;;
-FE99;ARABIC LETTER THEH ISOLATED FORM;Lo;0;AL;<isolated> 062B;;;;N;GLYPH FOR ISOLATE ARABIC THAA;;;;
-FE9A;ARABIC LETTER THEH FINAL FORM;Lo;0;AL;<final> 062B;;;;N;GLYPH FOR FINAL ARABIC THAA;;;;
-FE9B;ARABIC LETTER THEH INITIAL FORM;Lo;0;AL;<initial> 062B;;;;N;GLYPH FOR INITIAL ARABIC THAA;;;;
-FE9C;ARABIC LETTER THEH MEDIAL FORM;Lo;0;AL;<medial> 062B;;;;N;GLYPH FOR MEDIAL ARABIC THAA;;;;
-FE9D;ARABIC LETTER JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062C;;;;N;GLYPH FOR ISOLATE ARABIC JEEM;;;;
-FE9E;ARABIC LETTER JEEM FINAL FORM;Lo;0;AL;<final> 062C;;;;N;GLYPH FOR FINAL ARABIC JEEM;;;;
-FE9F;ARABIC LETTER JEEM INITIAL FORM;Lo;0;AL;<initial> 062C;;;;N;GLYPH FOR INITIAL ARABIC JEEM;;;;
-FEA0;ARABIC LETTER JEEM MEDIAL FORM;Lo;0;AL;<medial> 062C;;;;N;GLYPH FOR MEDIAL ARABIC JEEM;;;;
-FEA1;ARABIC LETTER HAH ISOLATED FORM;Lo;0;AL;<isolated> 062D;;;;N;GLYPH FOR ISOLATE ARABIC HAA;;;;
-FEA2;ARABIC LETTER HAH FINAL FORM;Lo;0;AL;<final> 062D;;;;N;GLYPH FOR FINAL ARABIC HAA;;;;
-FEA3;ARABIC LETTER HAH INITIAL FORM;Lo;0;AL;<initial> 062D;;;;N;GLYPH FOR INITIAL ARABIC HAA;;;;
-FEA4;ARABIC LETTER HAH MEDIAL FORM;Lo;0;AL;<medial> 062D;;;;N;GLYPH FOR MEDIAL ARABIC HAA;;;;
-FEA5;ARABIC LETTER KHAH ISOLATED FORM;Lo;0;AL;<isolated> 062E;;;;N;GLYPH FOR ISOLATE ARABIC KHAA;;;;
-FEA6;ARABIC LETTER KHAH FINAL FORM;Lo;0;AL;<final> 062E;;;;N;GLYPH FOR FINAL ARABIC KHAA;;;;
-FEA7;ARABIC LETTER KHAH INITIAL FORM;Lo;0;AL;<initial> 062E;;;;N;GLYPH FOR INITIAL ARABIC KHAA;;;;
-FEA8;ARABIC LETTER KHAH MEDIAL FORM;Lo;0;AL;<medial> 062E;;;;N;GLYPH FOR MEDIAL ARABIC KHAA;;;;
-FEA9;ARABIC LETTER DAL ISOLATED FORM;Lo;0;AL;<isolated> 062F;;;;N;GLYPH FOR ISOLATE ARABIC DAL;;;;
-FEAA;ARABIC LETTER DAL FINAL FORM;Lo;0;AL;<final> 062F;;;;N;GLYPH FOR FINAL ARABIC DAL;;;;
-FEAB;ARABIC LETTER THAL ISOLATED FORM;Lo;0;AL;<isolated> 0630;;;;N;GLYPH FOR ISOLATE ARABIC THAL;;;;
-FEAC;ARABIC LETTER THAL FINAL FORM;Lo;0;AL;<final> 0630;;;;N;GLYPH FOR FINAL ARABIC THAL;;;;
-FEAD;ARABIC LETTER REH ISOLATED FORM;Lo;0;AL;<isolated> 0631;;;;N;GLYPH FOR ISOLATE ARABIC RA;;;;
-FEAE;ARABIC LETTER REH FINAL FORM;Lo;0;AL;<final> 0631;;;;N;GLYPH FOR FINAL ARABIC RA;;;;
-FEAF;ARABIC LETTER ZAIN ISOLATED FORM;Lo;0;AL;<isolated> 0632;;;;N;GLYPH FOR ISOLATE ARABIC ZAIN;;;;
-FEB0;ARABIC LETTER ZAIN FINAL FORM;Lo;0;AL;<final> 0632;;;;N;GLYPH FOR FINAL ARABIC ZAIN;;;;
-FEB1;ARABIC LETTER SEEN ISOLATED FORM;Lo;0;AL;<isolated> 0633;;;;N;GLYPH FOR ISOLATE ARABIC SEEN;;;;
-FEB2;ARABIC LETTER SEEN FINAL FORM;Lo;0;AL;<final> 0633;;;;N;GLYPH FOR FINAL ARABIC SEEN;;;;
-FEB3;ARABIC LETTER SEEN INITIAL FORM;Lo;0;AL;<initial> 0633;;;;N;GLYPH FOR INITIAL ARABIC SEEN;;;;
-FEB4;ARABIC LETTER SEEN MEDIAL FORM;Lo;0;AL;<medial> 0633;;;;N;GLYPH FOR MEDIAL ARABIC SEEN;;;;
-FEB5;ARABIC LETTER SHEEN ISOLATED FORM;Lo;0;AL;<isolated> 0634;;;;N;GLYPH FOR ISOLATE ARABIC SHEEN;;;;
-FEB6;ARABIC LETTER SHEEN FINAL FORM;Lo;0;AL;<final> 0634;;;;N;GLYPH FOR FINAL ARABIC SHEEN;;;;
-FEB7;ARABIC LETTER SHEEN INITIAL FORM;Lo;0;AL;<initial> 0634;;;;N;GLYPH FOR INITIAL ARABIC SHEEN;;;;
-FEB8;ARABIC LETTER SHEEN MEDIAL FORM;Lo;0;AL;<medial> 0634;;;;N;GLYPH FOR MEDIAL ARABIC SHEEN;;;;
-FEB9;ARABIC LETTER SAD ISOLATED FORM;Lo;0;AL;<isolated> 0635;;;;N;GLYPH FOR ISOLATE ARABIC SAD;;;;
-FEBA;ARABIC LETTER SAD FINAL FORM;Lo;0;AL;<final> 0635;;;;N;GLYPH FOR FINAL ARABIC SAD;;;;
-FEBB;ARABIC LETTER SAD INITIAL FORM;Lo;0;AL;<initial> 0635;;;;N;GLYPH FOR INITIAL ARABIC SAD;;;;
-FEBC;ARABIC LETTER SAD MEDIAL FORM;Lo;0;AL;<medial> 0635;;;;N;GLYPH FOR MEDIAL ARABIC SAD;;;;
-FEBD;ARABIC LETTER DAD ISOLATED FORM;Lo;0;AL;<isolated> 0636;;;;N;GLYPH FOR ISOLATE ARABIC DAD;;;;
-FEBE;ARABIC LETTER DAD FINAL FORM;Lo;0;AL;<final> 0636;;;;N;GLYPH FOR FINAL ARABIC DAD;;;;
-FEBF;ARABIC LETTER DAD INITIAL FORM;Lo;0;AL;<initial> 0636;;;;N;GLYPH FOR INITIAL ARABIC DAD;;;;
-FEC0;ARABIC LETTER DAD MEDIAL FORM;Lo;0;AL;<medial> 0636;;;;N;GLYPH FOR MEDIAL ARABIC DAD;;;;
-FEC1;ARABIC LETTER TAH ISOLATED FORM;Lo;0;AL;<isolated> 0637;;;;N;GLYPH FOR ISOLATE ARABIC TAH;;;;
-FEC2;ARABIC LETTER TAH FINAL FORM;Lo;0;AL;<final> 0637;;;;N;GLYPH FOR FINAL ARABIC TAH;;;;
-FEC3;ARABIC LETTER TAH INITIAL FORM;Lo;0;AL;<initial> 0637;;;;N;GLYPH FOR INITIAL ARABIC TAH;;;;
-FEC4;ARABIC LETTER TAH MEDIAL FORM;Lo;0;AL;<medial> 0637;;;;N;GLYPH FOR MEDIAL ARABIC TAH;;;;
-FEC5;ARABIC LETTER ZAH ISOLATED FORM;Lo;0;AL;<isolated> 0638;;;;N;GLYPH FOR ISOLATE ARABIC DHAH;;;;
-FEC6;ARABIC LETTER ZAH FINAL FORM;Lo;0;AL;<final> 0638;;;;N;GLYPH FOR FINAL ARABIC DHAH;;;;
-FEC7;ARABIC LETTER ZAH INITIAL FORM;Lo;0;AL;<initial> 0638;;;;N;GLYPH FOR INITIAL ARABIC DHAH;;;;
-FEC8;ARABIC LETTER ZAH MEDIAL FORM;Lo;0;AL;<medial> 0638;;;;N;GLYPH FOR MEDIAL ARABIC DHAH;;;;
-FEC9;ARABIC LETTER AIN ISOLATED FORM;Lo;0;AL;<isolated> 0639;;;;N;GLYPH FOR ISOLATE ARABIC AIN;;;;
-FECA;ARABIC LETTER AIN FINAL FORM;Lo;0;AL;<final> 0639;;;;N;GLYPH FOR FINAL ARABIC AIN;;;;
-FECB;ARABIC LETTER AIN INITIAL FORM;Lo;0;AL;<initial> 0639;;;;N;GLYPH FOR INITIAL ARABIC AIN;;;;
-FECC;ARABIC LETTER AIN MEDIAL FORM;Lo;0;AL;<medial> 0639;;;;N;GLYPH FOR MEDIAL ARABIC AIN;;;;
-FECD;ARABIC LETTER GHAIN ISOLATED FORM;Lo;0;AL;<isolated> 063A;;;;N;GLYPH FOR ISOLATE ARABIC GHAIN;;;;
-FECE;ARABIC LETTER GHAIN FINAL FORM;Lo;0;AL;<final> 063A;;;;N;GLYPH FOR FINAL ARABIC GHAIN;;;;
-FECF;ARABIC LETTER GHAIN INITIAL FORM;Lo;0;AL;<initial> 063A;;;;N;GLYPH FOR INITIAL ARABIC GHAIN;;;;
-FED0;ARABIC LETTER GHAIN MEDIAL FORM;Lo;0;AL;<medial> 063A;;;;N;GLYPH FOR MEDIAL ARABIC GHAIN;;;;
-FED1;ARABIC LETTER FEH ISOLATED FORM;Lo;0;AL;<isolated> 0641;;;;N;GLYPH FOR ISOLATE ARABIC FA;;;;
-FED2;ARABIC LETTER FEH FINAL FORM;Lo;0;AL;<final> 0641;;;;N;GLYPH FOR FINAL ARABIC FA;;;;
-FED3;ARABIC LETTER FEH INITIAL FORM;Lo;0;AL;<initial> 0641;;;;N;GLYPH FOR INITIAL ARABIC FA;;;;
-FED4;ARABIC LETTER FEH MEDIAL FORM;Lo;0;AL;<medial> 0641;;;;N;GLYPH FOR MEDIAL ARABIC FA;;;;
-FED5;ARABIC LETTER QAF ISOLATED FORM;Lo;0;AL;<isolated> 0642;;;;N;GLYPH FOR ISOLATE ARABIC QAF;;;;
-FED6;ARABIC LETTER QAF FINAL FORM;Lo;0;AL;<final> 0642;;;;N;GLYPH FOR FINAL ARABIC QAF;;;;
-FED7;ARABIC LETTER QAF INITIAL FORM;Lo;0;AL;<initial> 0642;;;;N;GLYPH FOR INITIAL ARABIC QAF;;;;
-FED8;ARABIC LETTER QAF MEDIAL FORM;Lo;0;AL;<medial> 0642;;;;N;GLYPH FOR MEDIAL ARABIC QAF;;;;
-FED9;ARABIC LETTER KAF ISOLATED FORM;Lo;0;AL;<isolated> 0643;;;;N;GLYPH FOR ISOLATE ARABIC CAF;;;;
-FEDA;ARABIC LETTER KAF FINAL FORM;Lo;0;AL;<final> 0643;;;;N;GLYPH FOR FINAL ARABIC CAF;;;;
-FEDB;ARABIC LETTER KAF INITIAL FORM;Lo;0;AL;<initial> 0643;;;;N;GLYPH FOR INITIAL ARABIC CAF;;;;
-FEDC;ARABIC LETTER KAF MEDIAL FORM;Lo;0;AL;<medial> 0643;;;;N;GLYPH FOR MEDIAL ARABIC CAF;;;;
-FEDD;ARABIC LETTER LAM ISOLATED FORM;Lo;0;AL;<isolated> 0644;;;;N;GLYPH FOR ISOLATE ARABIC LAM;;;;
-FEDE;ARABIC LETTER LAM FINAL FORM;Lo;0;AL;<final> 0644;;;;N;GLYPH FOR FINAL ARABIC LAM;;;;
-FEDF;ARABIC LETTER LAM INITIAL FORM;Lo;0;AL;<initial> 0644;;;;N;GLYPH FOR INITIAL ARABIC LAM;;;;
-FEE0;ARABIC LETTER LAM MEDIAL FORM;Lo;0;AL;<medial> 0644;;;;N;GLYPH FOR MEDIAL ARABIC LAM;;;;
-FEE1;ARABIC LETTER MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645;;;;N;GLYPH FOR ISOLATE ARABIC MEEM;;;;
-FEE2;ARABIC LETTER MEEM FINAL FORM;Lo;0;AL;<final> 0645;;;;N;GLYPH FOR FINAL ARABIC MEEM;;;;
-FEE3;ARABIC LETTER MEEM INITIAL FORM;Lo;0;AL;<initial> 0645;;;;N;GLYPH FOR INITIAL ARABIC MEEM;;;;
-FEE4;ARABIC LETTER MEEM MEDIAL FORM;Lo;0;AL;<medial> 0645;;;;N;GLYPH FOR MEDIAL ARABIC MEEM;;;;
-FEE5;ARABIC LETTER NOON ISOLATED FORM;Lo;0;AL;<isolated> 0646;;;;N;GLYPH FOR ISOLATE ARABIC NOON;;;;
-FEE6;ARABIC LETTER NOON FINAL FORM;Lo;0;AL;<final> 0646;;;;N;GLYPH FOR FINAL ARABIC NOON;;;;
-FEE7;ARABIC LETTER NOON INITIAL FORM;Lo;0;AL;<initial> 0646;;;;N;GLYPH FOR INITIAL ARABIC NOON;;;;
-FEE8;ARABIC LETTER NOON MEDIAL FORM;Lo;0;AL;<medial> 0646;;;;N;GLYPH FOR MEDIAL ARABIC NOON;;;;
-FEE9;ARABIC LETTER HEH ISOLATED FORM;Lo;0;AL;<isolated> 0647;;;;N;GLYPH FOR ISOLATE ARABIC HA;;;;
-FEEA;ARABIC LETTER HEH FINAL FORM;Lo;0;AL;<final> 0647;;;;N;GLYPH FOR FINAL ARABIC HA;;;;
-FEEB;ARABIC LETTER HEH INITIAL FORM;Lo;0;AL;<initial> 0647;;;;N;GLYPH FOR INITIAL ARABIC HA;;;;
-FEEC;ARABIC LETTER HEH MEDIAL FORM;Lo;0;AL;<medial> 0647;;;;N;GLYPH FOR MEDIAL ARABIC HA;;;;
-FEED;ARABIC LETTER WAW ISOLATED FORM;Lo;0;AL;<isolated> 0648;;;;N;GLYPH FOR ISOLATE ARABIC WAW;;;;
-FEEE;ARABIC LETTER WAW FINAL FORM;Lo;0;AL;<final> 0648;;;;N;GLYPH FOR FINAL ARABIC WAW;;;;
-FEEF;ARABIC LETTER ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0649;;;;N;GLYPH FOR ISOLATE ARABIC ALEF MAQSURAH;;;;
-FEF0;ARABIC LETTER ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0649;;;;N;GLYPH FOR FINAL ARABIC ALEF MAQSURAH;;;;
-FEF1;ARABIC LETTER YEH ISOLATED FORM;Lo;0;AL;<isolated> 064A;;;;N;GLYPH FOR ISOLATE ARABIC YA;;;;
-FEF2;ARABIC LETTER YEH FINAL FORM;Lo;0;AL;<final> 064A;;;;N;GLYPH FOR FINAL ARABIC YA;;;;
-FEF3;ARABIC LETTER YEH INITIAL FORM;Lo;0;AL;<initial> 064A;;;;N;GLYPH FOR INITIAL ARABIC YA;;;;
-FEF4;ARABIC LETTER YEH MEDIAL FORM;Lo;0;AL;<medial> 064A;;;;N;GLYPH FOR MEDIAL ARABIC YA;;;;
-FEF5;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0644 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON LIGATURE LAM ALEF;;;;
-FEF6;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL;<final> 0644 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON LIGATURE LAM ALEF;;;;
-FEF7;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0644 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON LIGATURE LAM ALEF;;;;
-FEF8;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0644 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON LIGATURE LAM ALEF;;;;
-FEF9;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL;<isolated> 0644 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;;
-FEFA;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL;<final> 0644 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;;
-FEFB;ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0644 0627;;;;N;GLYPH FOR ISOLATE ARABIC LIGATURE LAM ALEF;;;;
-FEFC;ARABIC LIGATURE LAM WITH ALEF FINAL FORM;Lo;0;AL;<final> 0644 0627;;;;N;GLYPH FOR FINAL ARABIC LIGATURE LAM ALEF;;;;
-FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
-FF01;FULLWIDTH EXCLAMATION MARK;Po;0;ON;<wide> 0021;;;;N;;;;;
-FF02;FULLWIDTH QUOTATION MARK;Po;0;ON;<wide> 0022;;;;N;;;;;
-FF03;FULLWIDTH NUMBER SIGN;Po;0;ET;<wide> 0023;;;;N;;;;;
-FF04;FULLWIDTH DOLLAR SIGN;Sc;0;ET;<wide> 0024;;;;N;;;;;
-FF05;FULLWIDTH PERCENT SIGN;Po;0;ET;<wide> 0025;;;;N;;;;;
-FF06;FULLWIDTH AMPERSAND;Po;0;ON;<wide> 0026;;;;N;;;;;
-FF07;FULLWIDTH APOSTROPHE;Po;0;ON;<wide> 0027;;;;N;;;;;
-FF08;FULLWIDTH LEFT PARENTHESIS;Ps;0;ON;<wide> 0028;;;;Y;FULLWIDTH OPENING PARENTHESIS;;;;
-FF09;FULLWIDTH RIGHT PARENTHESIS;Pe;0;ON;<wide> 0029;;;;Y;FULLWIDTH CLOSING PARENTHESIS;;;;
-FF0A;FULLWIDTH ASTERISK;Po;0;ON;<wide> 002A;;;;N;;;;;
-FF0B;FULLWIDTH PLUS SIGN;Sm;0;ES;<wide> 002B;;;;N;;;;;
-FF0C;FULLWIDTH COMMA;Po;0;CS;<wide> 002C;;;;N;;;;;
-FF0D;FULLWIDTH HYPHEN-MINUS;Pd;0;ES;<wide> 002D;;;;N;;;;;
-FF0E;FULLWIDTH FULL STOP;Po;0;CS;<wide> 002E;;;;N;FULLWIDTH PERIOD;;;;
-FF0F;FULLWIDTH SOLIDUS;Po;0;CS;<wide> 002F;;;;N;FULLWIDTH SLASH;;;;
-FF10;FULLWIDTH DIGIT ZERO;Nd;0;EN;<wide> 0030;0;0;0;N;;;;;
-FF11;FULLWIDTH DIGIT ONE;Nd;0;EN;<wide> 0031;1;1;1;N;;;;;
-FF12;FULLWIDTH DIGIT TWO;Nd;0;EN;<wide> 0032;2;2;2;N;;;;;
-FF13;FULLWIDTH DIGIT THREE;Nd;0;EN;<wide> 0033;3;3;3;N;;;;;
-FF14;FULLWIDTH DIGIT FOUR;Nd;0;EN;<wide> 0034;4;4;4;N;;;;;
-FF15;FULLWIDTH DIGIT FIVE;Nd;0;EN;<wide> 0035;5;5;5;N;;;;;
-FF16;FULLWIDTH DIGIT SIX;Nd;0;EN;<wide> 0036;6;6;6;N;;;;;
-FF17;FULLWIDTH DIGIT SEVEN;Nd;0;EN;<wide> 0037;7;7;7;N;;;;;
-FF18;FULLWIDTH DIGIT EIGHT;Nd;0;EN;<wide> 0038;8;8;8;N;;;;;
-FF19;FULLWIDTH DIGIT NINE;Nd;0;EN;<wide> 0039;9;9;9;N;;;;;
-FF1A;FULLWIDTH COLON;Po;0;CS;<wide> 003A;;;;N;;;;;
-FF1B;FULLWIDTH SEMICOLON;Po;0;ON;<wide> 003B;;;;N;;;;;
-FF1C;FULLWIDTH LESS-THAN SIGN;Sm;0;ON;<wide> 003C;;;;Y;;;;;
-FF1D;FULLWIDTH EQUALS SIGN;Sm;0;ON;<wide> 003D;;;;N;;;;;
-FF1E;FULLWIDTH GREATER-THAN SIGN;Sm;0;ON;<wide> 003E;;;;Y;;;;;
-FF1F;FULLWIDTH QUESTION MARK;Po;0;ON;<wide> 003F;;;;N;;;;;
-FF20;FULLWIDTH COMMERCIAL AT;Po;0;ON;<wide> 0040;;;;N;;;;;
-FF21;FULLWIDTH LATIN CAPITAL LETTER A;Lu;0;L;<wide> 0041;;;;N;;;;FF41;
-FF22;FULLWIDTH LATIN CAPITAL LETTER B;Lu;0;L;<wide> 0042;;;;N;;;;FF42;
-FF23;FULLWIDTH LATIN CAPITAL LETTER C;Lu;0;L;<wide> 0043;;;;N;;;;FF43;
-FF24;FULLWIDTH LATIN CAPITAL LETTER D;Lu;0;L;<wide> 0044;;;;N;;;;FF44;
-FF25;FULLWIDTH LATIN CAPITAL LETTER E;Lu;0;L;<wide> 0045;;;;N;;;;FF45;
-FF26;FULLWIDTH LATIN CAPITAL LETTER F;Lu;0;L;<wide> 0046;;;;N;;;;FF46;
-FF27;FULLWIDTH LATIN CAPITAL LETTER G;Lu;0;L;<wide> 0047;;;;N;;;;FF47;
-FF28;FULLWIDTH LATIN CAPITAL LETTER H;Lu;0;L;<wide> 0048;;;;N;;;;FF48;
-FF29;FULLWIDTH LATIN CAPITAL LETTER I;Lu;0;L;<wide> 0049;;;;N;;;;FF49;
-FF2A;FULLWIDTH LATIN CAPITAL LETTER J;Lu;0;L;<wide> 004A;;;;N;;;;FF4A;
-FF2B;FULLWIDTH LATIN CAPITAL LETTER K;Lu;0;L;<wide> 004B;;;;N;;;;FF4B;
-FF2C;FULLWIDTH LATIN CAPITAL LETTER L;Lu;0;L;<wide> 004C;;;;N;;;;FF4C;
-FF2D;FULLWIDTH LATIN CAPITAL LETTER M;Lu;0;L;<wide> 004D;;;;N;;;;FF4D;
-FF2E;FULLWIDTH LATIN CAPITAL LETTER N;Lu;0;L;<wide> 004E;;;;N;;;;FF4E;
-FF2F;FULLWIDTH LATIN CAPITAL LETTER O;Lu;0;L;<wide> 004F;;;;N;;;;FF4F;
-FF30;FULLWIDTH LATIN CAPITAL LETTER P;Lu;0;L;<wide> 0050;;;;N;;;;FF50;
-FF31;FULLWIDTH LATIN CAPITAL LETTER Q;Lu;0;L;<wide> 0051;;;;N;;;;FF51;
-FF32;FULLWIDTH LATIN CAPITAL LETTER R;Lu;0;L;<wide> 0052;;;;N;;;;FF52;
-FF33;FULLWIDTH LATIN CAPITAL LETTER S;Lu;0;L;<wide> 0053;;;;N;;;;FF53;
-FF34;FULLWIDTH LATIN CAPITAL LETTER T;Lu;0;L;<wide> 0054;;;;N;;;;FF54;
-FF35;FULLWIDTH LATIN CAPITAL LETTER U;Lu;0;L;<wide> 0055;;;;N;;;;FF55;
-FF36;FULLWIDTH LATIN CAPITAL LETTER V;Lu;0;L;<wide> 0056;;;;N;;;;FF56;
-FF37;FULLWIDTH LATIN CAPITAL LETTER W;Lu;0;L;<wide> 0057;;;;N;;;;FF57;
-FF38;FULLWIDTH LATIN CAPITAL LETTER X;Lu;0;L;<wide> 0058;;;;N;;;;FF58;
-FF39;FULLWIDTH LATIN CAPITAL LETTER Y;Lu;0;L;<wide> 0059;;;;N;;;;FF59;
-FF3A;FULLWIDTH LATIN CAPITAL LETTER Z;Lu;0;L;<wide> 005A;;;;N;;;;FF5A;
-FF3B;FULLWIDTH LEFT SQUARE BRACKET;Ps;0;ON;<wide> 005B;;;;Y;FULLWIDTH OPENING SQUARE BRACKET;;;;
-FF3C;FULLWIDTH REVERSE SOLIDUS;Po;0;ON;<wide> 005C;;;;N;FULLWIDTH BACKSLASH;;;;
-FF3D;FULLWIDTH RIGHT SQUARE BRACKET;Pe;0;ON;<wide> 005D;;;;Y;FULLWIDTH CLOSING SQUARE BRACKET;;;;
-FF3E;FULLWIDTH CIRCUMFLEX ACCENT;Sk;0;ON;<wide> 005E;;;;N;FULLWIDTH SPACING CIRCUMFLEX;;;;
-FF3F;FULLWIDTH LOW LINE;Pc;0;ON;<wide> 005F;;;;N;FULLWIDTH SPACING UNDERSCORE;;;;
-FF40;FULLWIDTH GRAVE ACCENT;Sk;0;ON;<wide> 0060;;;;N;FULLWIDTH SPACING GRAVE;;;;
-FF41;FULLWIDTH LATIN SMALL LETTER A;Ll;0;L;<wide> 0061;;;;N;;;FF21;;FF21
-FF42;FULLWIDTH LATIN SMALL LETTER B;Ll;0;L;<wide> 0062;;;;N;;;FF22;;FF22
-FF43;FULLWIDTH LATIN SMALL LETTER C;Ll;0;L;<wide> 0063;;;;N;;;FF23;;FF23
-FF44;FULLWIDTH LATIN SMALL LETTER D;Ll;0;L;<wide> 0064;;;;N;;;FF24;;FF24
-FF45;FULLWIDTH LATIN SMALL LETTER E;Ll;0;L;<wide> 0065;;;;N;;;FF25;;FF25
-FF46;FULLWIDTH LATIN SMALL LETTER F;Ll;0;L;<wide> 0066;;;;N;;;FF26;;FF26
-FF47;FULLWIDTH LATIN SMALL LETTER G;Ll;0;L;<wide> 0067;;;;N;;;FF27;;FF27
-FF48;FULLWIDTH LATIN SMALL LETTER H;Ll;0;L;<wide> 0068;;;;N;;;FF28;;FF28
-FF49;FULLWIDTH LATIN SMALL LETTER I;Ll;0;L;<wide> 0069;;;;N;;;FF29;;FF29
-FF4A;FULLWIDTH LATIN SMALL LETTER J;Ll;0;L;<wide> 006A;;;;N;;;FF2A;;FF2A
-FF4B;FULLWIDTH LATIN SMALL LETTER K;Ll;0;L;<wide> 006B;;;;N;;;FF2B;;FF2B
-FF4C;FULLWIDTH LATIN SMALL LETTER L;Ll;0;L;<wide> 006C;;;;N;;;FF2C;;FF2C
-FF4D;FULLWIDTH LATIN SMALL LETTER M;Ll;0;L;<wide> 006D;;;;N;;;FF2D;;FF2D
-FF4E;FULLWIDTH LATIN SMALL LETTER N;Ll;0;L;<wide> 006E;;;;N;;;FF2E;;FF2E
-FF4F;FULLWIDTH LATIN SMALL LETTER O;Ll;0;L;<wide> 006F;;;;N;;;FF2F;;FF2F
-FF50;FULLWIDTH LATIN SMALL LETTER P;Ll;0;L;<wide> 0070;;;;N;;;FF30;;FF30
-FF51;FULLWIDTH LATIN SMALL LETTER Q;Ll;0;L;<wide> 0071;;;;N;;;FF31;;FF31
-FF52;FULLWIDTH LATIN SMALL LETTER R;Ll;0;L;<wide> 0072;;;;N;;;FF32;;FF32
-FF53;FULLWIDTH LATIN SMALL LETTER S;Ll;0;L;<wide> 0073;;;;N;;;FF33;;FF33
-FF54;FULLWIDTH LATIN SMALL LETTER T;Ll;0;L;<wide> 0074;;;;N;;;FF34;;FF34
-FF55;FULLWIDTH LATIN SMALL LETTER U;Ll;0;L;<wide> 0075;;;;N;;;FF35;;FF35
-FF56;FULLWIDTH LATIN SMALL LETTER V;Ll;0;L;<wide> 0076;;;;N;;;FF36;;FF36
-FF57;FULLWIDTH LATIN SMALL LETTER W;Ll;0;L;<wide> 0077;;;;N;;;FF37;;FF37
-FF58;FULLWIDTH LATIN SMALL LETTER X;Ll;0;L;<wide> 0078;;;;N;;;FF38;;FF38
-FF59;FULLWIDTH LATIN SMALL LETTER Y;Ll;0;L;<wide> 0079;;;;N;;;FF39;;FF39
-FF5A;FULLWIDTH LATIN SMALL LETTER Z;Ll;0;L;<wide> 007A;;;;N;;;FF3A;;FF3A
-FF5B;FULLWIDTH LEFT CURLY BRACKET;Ps;0;ON;<wide> 007B;;;;Y;FULLWIDTH OPENING CURLY BRACKET;;;;
-FF5C;FULLWIDTH VERTICAL LINE;Sm;0;ON;<wide> 007C;;;;N;FULLWIDTH VERTICAL BAR;;;;
-FF5D;FULLWIDTH RIGHT CURLY BRACKET;Pe;0;ON;<wide> 007D;;;;Y;FULLWIDTH CLOSING CURLY BRACKET;;;;
-FF5E;FULLWIDTH TILDE;Sm;0;ON;<wide> 007E;;;;N;FULLWIDTH SPACING TILDE;;;;
-FF5F;FULLWIDTH LEFT WHITE PARENTHESIS;Ps;0;ON;<wide> 2985;;;;Y;;;;;
-FF60;FULLWIDTH RIGHT WHITE PARENTHESIS;Pe;0;ON;<wide> 2986;;;;Y;;;;;
-FF61;HALFWIDTH IDEOGRAPHIC FULL STOP;Po;0;ON;<narrow> 3002;;;;N;HALFWIDTH IDEOGRAPHIC PERIOD;;;;
-FF62;HALFWIDTH LEFT CORNER BRACKET;Ps;0;ON;<narrow> 300C;;;;Y;HALFWIDTH OPENING CORNER BRACKET;;;;
-FF63;HALFWIDTH RIGHT CORNER BRACKET;Pe;0;ON;<narrow> 300D;;;;Y;HALFWIDTH CLOSING CORNER BRACKET;;;;
-FF64;HALFWIDTH IDEOGRAPHIC COMMA;Po;0;ON;<narrow> 3001;;;;N;;;;;
-FF65;HALFWIDTH KATAKANA MIDDLE DOT;Po;0;ON;<narrow> 30FB;;;;N;;;;;
-FF66;HALFWIDTH KATAKANA LETTER WO;Lo;0;L;<narrow> 30F2;;;;N;;;;;
-FF67;HALFWIDTH KATAKANA LETTER SMALL A;Lo;0;L;<narrow> 30A1;;;;N;;;;;
-FF68;HALFWIDTH KATAKANA LETTER SMALL I;Lo;0;L;<narrow> 30A3;;;;N;;;;;
-FF69;HALFWIDTH KATAKANA LETTER SMALL U;Lo;0;L;<narrow> 30A5;;;;N;;;;;
-FF6A;HALFWIDTH KATAKANA LETTER SMALL E;Lo;0;L;<narrow> 30A7;;;;N;;;;;
-FF6B;HALFWIDTH KATAKANA LETTER SMALL O;Lo;0;L;<narrow> 30A9;;;;N;;;;;
-FF6C;HALFWIDTH KATAKANA LETTER SMALL YA;Lo;0;L;<narrow> 30E3;;;;N;;;;;
-FF6D;HALFWIDTH KATAKANA LETTER SMALL YU;Lo;0;L;<narrow> 30E5;;;;N;;;;;
-FF6E;HALFWIDTH KATAKANA LETTER SMALL YO;Lo;0;L;<narrow> 30E7;;;;N;;;;;
-FF6F;HALFWIDTH KATAKANA LETTER SMALL TU;Lo;0;L;<narrow> 30C3;;;;N;;;;;
-FF70;HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;<narrow> 30FC;;;;N;;;;;
-FF71;HALFWIDTH KATAKANA LETTER A;Lo;0;L;<narrow> 30A2;;;;N;;;;;
-FF72;HALFWIDTH KATAKANA LETTER I;Lo;0;L;<narrow> 30A4;;;;N;;;;;
-FF73;HALFWIDTH KATAKANA LETTER U;Lo;0;L;<narrow> 30A6;;;;N;;;;;
-FF74;HALFWIDTH KATAKANA LETTER E;Lo;0;L;<narrow> 30A8;;;;N;;;;;
-FF75;HALFWIDTH KATAKANA LETTER O;Lo;0;L;<narrow> 30AA;;;;N;;;;;
-FF76;HALFWIDTH KATAKANA LETTER KA;Lo;0;L;<narrow> 30AB;;;;N;;;;;
-FF77;HALFWIDTH KATAKANA LETTER KI;Lo;0;L;<narrow> 30AD;;;;N;;;;;
-FF78;HALFWIDTH KATAKANA LETTER KU;Lo;0;L;<narrow> 30AF;;;;N;;;;;
-FF79;HALFWIDTH KATAKANA LETTER KE;Lo;0;L;<narrow> 30B1;;;;N;;;;;
-FF7A;HALFWIDTH KATAKANA LETTER KO;Lo;0;L;<narrow> 30B3;;;;N;;;;;
-FF7B;HALFWIDTH KATAKANA LETTER SA;Lo;0;L;<narrow> 30B5;;;;N;;;;;
-FF7C;HALFWIDTH KATAKANA LETTER SI;Lo;0;L;<narrow> 30B7;;;;N;;;;;
-FF7D;HALFWIDTH KATAKANA LETTER SU;Lo;0;L;<narrow> 30B9;;;;N;;;;;
-FF7E;HALFWIDTH KATAKANA LETTER SE;Lo;0;L;<narrow> 30BB;;;;N;;;;;
-FF7F;HALFWIDTH KATAKANA LETTER SO;Lo;0;L;<narrow> 30BD;;;;N;;;;;
-FF80;HALFWIDTH KATAKANA LETTER TA;Lo;0;L;<narrow> 30BF;;;;N;;;;;
-FF81;HALFWIDTH KATAKANA LETTER TI;Lo;0;L;<narrow> 30C1;;;;N;;;;;
-FF82;HALFWIDTH KATAKANA LETTER TU;Lo;0;L;<narrow> 30C4;;;;N;;;;;
-FF83;HALFWIDTH KATAKANA LETTER TE;Lo;0;L;<narrow> 30C6;;;;N;;;;;
-FF84;HALFWIDTH KATAKANA LETTER TO;Lo;0;L;<narrow> 30C8;;;;N;;;;;
-FF85;HALFWIDTH KATAKANA LETTER NA;Lo;0;L;<narrow> 30CA;;;;N;;;;;
-FF86;HALFWIDTH KATAKANA LETTER NI;Lo;0;L;<narrow> 30CB;;;;N;;;;;
-FF87;HALFWIDTH KATAKANA LETTER NU;Lo;0;L;<narrow> 30CC;;;;N;;;;;
-FF88;HALFWIDTH KATAKANA LETTER NE;Lo;0;L;<narrow> 30CD;;;;N;;;;;
-FF89;HALFWIDTH KATAKANA LETTER NO;Lo;0;L;<narrow> 30CE;;;;N;;;;;
-FF8A;HALFWIDTH KATAKANA LETTER HA;Lo;0;L;<narrow> 30CF;;;;N;;;;;
-FF8B;HALFWIDTH KATAKANA LETTER HI;Lo;0;L;<narrow> 30D2;;;;N;;;;;
-FF8C;HALFWIDTH KATAKANA LETTER HU;Lo;0;L;<narrow> 30D5;;;;N;;;;;
-FF8D;HALFWIDTH KATAKANA LETTER HE;Lo;0;L;<narrow> 30D8;;;;N;;;;;
-FF8E;HALFWIDTH KATAKANA LETTER HO;Lo;0;L;<narrow> 30DB;;;;N;;;;;
-FF8F;HALFWIDTH KATAKANA LETTER MA;Lo;0;L;<narrow> 30DE;;;;N;;;;;
-FF90;HALFWIDTH KATAKANA LETTER MI;Lo;0;L;<narrow> 30DF;;;;N;;;;;
-FF91;HALFWIDTH KATAKANA LETTER MU;Lo;0;L;<narrow> 30E0;;;;N;;;;;
-FF92;HALFWIDTH KATAKANA LETTER ME;Lo;0;L;<narrow> 30E1;;;;N;;;;;
-FF93;HALFWIDTH KATAKANA LETTER MO;Lo;0;L;<narrow> 30E2;;;;N;;;;;
-FF94;HALFWIDTH KATAKANA LETTER YA;Lo;0;L;<narrow> 30E4;;;;N;;;;;
-FF95;HALFWIDTH KATAKANA LETTER YU;Lo;0;L;<narrow> 30E6;;;;N;;;;;
-FF96;HALFWIDTH KATAKANA LETTER YO;Lo;0;L;<narrow> 30E8;;;;N;;;;;
-FF97;HALFWIDTH KATAKANA LETTER RA;Lo;0;L;<narrow> 30E9;;;;N;;;;;
-FF98;HALFWIDTH KATAKANA LETTER RI;Lo;0;L;<narrow> 30EA;;;;N;;;;;
-FF99;HALFWIDTH KATAKANA LETTER RU;Lo;0;L;<narrow> 30EB;;;;N;;;;;
-FF9A;HALFWIDTH KATAKANA LETTER RE;Lo;0;L;<narrow> 30EC;;;;N;;;;;
-FF9B;HALFWIDTH KATAKANA LETTER RO;Lo;0;L;<narrow> 30ED;;;;N;;;;;
-FF9C;HALFWIDTH KATAKANA LETTER WA;Lo;0;L;<narrow> 30EF;;;;N;;;;;
-FF9D;HALFWIDTH KATAKANA LETTER N;Lo;0;L;<narrow> 30F3;;;;N;;;;;
-FF9E;HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L;<narrow> 3099;;;;N;;;;;
-FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L;<narrow> 309A;;;;N;;;;;
-FFA0;HALFWIDTH HANGUL FILLER;Lo;0;L;<narrow> 3164;;;;N;HALFWIDTH HANGUL CAE OM;;;;
-FFA1;HALFWIDTH HANGUL LETTER KIYEOK;Lo;0;L;<narrow> 3131;;;;N;HALFWIDTH HANGUL LETTER GIYEOG;;;;
-FFA2;HALFWIDTH HANGUL LETTER SSANGKIYEOK;Lo;0;L;<narrow> 3132;;;;N;HALFWIDTH HANGUL LETTER SSANG GIYEOG;;;;
-FFA3;HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<narrow> 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;;
-FFA4;HALFWIDTH HANGUL LETTER NIEUN;Lo;0;L;<narrow> 3134;;;;N;;;;;
-FFA5;HALFWIDTH HANGUL LETTER NIEUN-CIEUC;Lo;0;L;<narrow> 3135;;;;N;HALFWIDTH HANGUL LETTER NIEUN JIEUJ;;;;
-FFA6;HALFWIDTH HANGUL LETTER NIEUN-HIEUH;Lo;0;L;<narrow> 3136;;;;N;HALFWIDTH HANGUL LETTER NIEUN HIEUH;;;;
-FFA7;HALFWIDTH HANGUL LETTER TIKEUT;Lo;0;L;<narrow> 3137;;;;N;HALFWIDTH HANGUL LETTER DIGEUD;;;;
-FFA8;HALFWIDTH HANGUL LETTER SSANGTIKEUT;Lo;0;L;<narrow> 3138;;;;N;HALFWIDTH HANGUL LETTER SSANG DIGEUD;;;;
-FFA9;HALFWIDTH HANGUL LETTER RIEUL;Lo;0;L;<narrow> 3139;;;;N;HALFWIDTH HANGUL LETTER LIEUL;;;;
-FFAA;HALFWIDTH HANGUL LETTER RIEUL-KIYEOK;Lo;0;L;<narrow> 313A;;;;N;HALFWIDTH HANGUL LETTER LIEUL GIYEOG;;;;
-FFAB;HALFWIDTH HANGUL LETTER RIEUL-MIEUM;Lo;0;L;<narrow> 313B;;;;N;HALFWIDTH HANGUL LETTER LIEUL MIEUM;;;;
-FFAC;HALFWIDTH HANGUL LETTER RIEUL-PIEUP;Lo;0;L;<narrow> 313C;;;;N;HALFWIDTH HANGUL LETTER LIEUL BIEUB;;;;
-FFAD;HALFWIDTH HANGUL LETTER RIEUL-SIOS;Lo;0;L;<narrow> 313D;;;;N;HALFWIDTH HANGUL LETTER LIEUL SIOS;;;;
-FFAE;HALFWIDTH HANGUL LETTER RIEUL-THIEUTH;Lo;0;L;<narrow> 313E;;;;N;HALFWIDTH HANGUL LETTER LIEUL TIEUT;;;;
-FFAF;HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L;<narrow> 313F;;;;N;HALFWIDTH HANGUL LETTER LIEUL PIEUP;;;;
-FFB0;HALFWIDTH HANGUL LETTER RIEUL-HIEUH;Lo;0;L;<narrow> 3140;;;;N;HALFWIDTH HANGUL LETTER LIEUL HIEUH;;;;
-FFB1;HALFWIDTH HANGUL LETTER MIEUM;Lo;0;L;<narrow> 3141;;;;N;;;;;
-FFB2;HALFWIDTH HANGUL LETTER PIEUP;Lo;0;L;<narrow> 3142;;;;N;HALFWIDTH HANGUL LETTER BIEUB;;;;
-FFB3;HALFWIDTH HANGUL LETTER SSANGPIEUP;Lo;0;L;<narrow> 3143;;;;N;HALFWIDTH HANGUL LETTER SSANG BIEUB;;;;
-FFB4;HALFWIDTH HANGUL LETTER PIEUP-SIOS;Lo;0;L;<narrow> 3144;;;;N;HALFWIDTH HANGUL LETTER BIEUB SIOS;;;;
-FFB5;HALFWIDTH HANGUL LETTER SIOS;Lo;0;L;<narrow> 3145;;;;N;;;;;
-FFB6;HALFWIDTH HANGUL LETTER SSANGSIOS;Lo;0;L;<narrow> 3146;;;;N;HALFWIDTH HANGUL LETTER SSANG SIOS;;;;
-FFB7;HALFWIDTH HANGUL LETTER IEUNG;Lo;0;L;<narrow> 3147;;;;N;;;;;
-FFB8;HALFWIDTH HANGUL LETTER CIEUC;Lo;0;L;<narrow> 3148;;;;N;HALFWIDTH HANGUL LETTER JIEUJ;;;;
-FFB9;HALFWIDTH HANGUL LETTER SSANGCIEUC;Lo;0;L;<narrow> 3149;;;;N;HALFWIDTH HANGUL LETTER SSANG JIEUJ;;;;
-FFBA;HALFWIDTH HANGUL LETTER CHIEUCH;Lo;0;L;<narrow> 314A;;;;N;HALFWIDTH HANGUL LETTER CIEUC;;;;
-FFBB;HALFWIDTH HANGUL LETTER KHIEUKH;Lo;0;L;<narrow> 314B;;;;N;HALFWIDTH HANGUL LETTER KIYEOK;;;;
-FFBC;HALFWIDTH HANGUL LETTER THIEUTH;Lo;0;L;<narrow> 314C;;;;N;HALFWIDTH HANGUL LETTER TIEUT;;;;
-FFBD;HALFWIDTH HANGUL LETTER PHIEUPH;Lo;0;L;<narrow> 314D;;;;N;HALFWIDTH HANGUL LETTER PIEUP;;;;
-FFBE;HALFWIDTH HANGUL LETTER HIEUH;Lo;0;L;<narrow> 314E;;;;N;;;;;
-FFC2;HALFWIDTH HANGUL LETTER A;Lo;0;L;<narrow> 314F;;;;N;;;;;
-FFC3;HALFWIDTH HANGUL LETTER AE;Lo;0;L;<narrow> 3150;;;;N;;;;;
-FFC4;HALFWIDTH HANGUL LETTER YA;Lo;0;L;<narrow> 3151;;;;N;;;;;
-FFC5;HALFWIDTH HANGUL LETTER YAE;Lo;0;L;<narrow> 3152;;;;N;;;;;
-FFC6;HALFWIDTH HANGUL LETTER EO;Lo;0;L;<narrow> 3153;;;;N;;;;;
-FFC7;HALFWIDTH HANGUL LETTER E;Lo;0;L;<narrow> 3154;;;;N;;;;;
-FFCA;HALFWIDTH HANGUL LETTER YEO;Lo;0;L;<narrow> 3155;;;;N;;;;;
-FFCB;HALFWIDTH HANGUL LETTER YE;Lo;0;L;<narrow> 3156;;;;N;;;;;
-FFCC;HALFWIDTH HANGUL LETTER O;Lo;0;L;<narrow> 3157;;;;N;;;;;
-FFCD;HALFWIDTH HANGUL LETTER WA;Lo;0;L;<narrow> 3158;;;;N;;;;;
-FFCE;HALFWIDTH HANGUL LETTER WAE;Lo;0;L;<narrow> 3159;;;;N;;;;;
-FFCF;HALFWIDTH HANGUL LETTER OE;Lo;0;L;<narrow> 315A;;;;N;;;;;
-FFD2;HALFWIDTH HANGUL LETTER YO;Lo;0;L;<narrow> 315B;;;;N;;;;;
-FFD3;HALFWIDTH HANGUL LETTER U;Lo;0;L;<narrow> 315C;;;;N;;;;;
-FFD4;HALFWIDTH HANGUL LETTER WEO;Lo;0;L;<narrow> 315D;;;;N;;;;;
-FFD5;HALFWIDTH HANGUL LETTER WE;Lo;0;L;<narrow> 315E;;;;N;;;;;
-FFD6;HALFWIDTH HANGUL LETTER WI;Lo;0;L;<narrow> 315F;;;;N;;;;;
-FFD7;HALFWIDTH HANGUL LETTER YU;Lo;0;L;<narrow> 3160;;;;N;;;;;
-FFDA;HALFWIDTH HANGUL LETTER EU;Lo;0;L;<narrow> 3161;;;;N;;;;;
-FFDB;HALFWIDTH HANGUL LETTER YI;Lo;0;L;<narrow> 3162;;;;N;;;;;
-FFDC;HALFWIDTH HANGUL LETTER I;Lo;0;L;<narrow> 3163;;;;N;;;;;
-FFE0;FULLWIDTH CENT SIGN;Sc;0;ET;<wide> 00A2;;;;N;;;;;
-FFE1;FULLWIDTH POUND SIGN;Sc;0;ET;<wide> 00A3;;;;N;;;;;
-FFE2;FULLWIDTH NOT SIGN;Sm;0;ON;<wide> 00AC;;;;N;;;;;
-FFE3;FULLWIDTH MACRON;Sk;0;ON;<wide> 00AF;;;;N;FULLWIDTH SPACING MACRON;;;;
-FFE4;FULLWIDTH BROKEN BAR;So;0;ON;<wide> 00A6;;;;N;FULLWIDTH BROKEN VERTICAL BAR;;;;
-FFE5;FULLWIDTH YEN SIGN;Sc;0;ET;<wide> 00A5;;;;N;;;;;
-FFE6;FULLWIDTH WON SIGN;Sc;0;ET;<wide> 20A9;;;;N;;;;;
-FFE8;HALFWIDTH FORMS LIGHT VERTICAL;So;0;ON;<narrow> 2502;;;;N;;;;;
-FFE9;HALFWIDTH LEFTWARDS ARROW;Sm;0;ON;<narrow> 2190;;;;N;;;;;
-FFEA;HALFWIDTH UPWARDS ARROW;Sm;0;ON;<narrow> 2191;;;;N;;;;;
-FFEB;HALFWIDTH RIGHTWARDS ARROW;Sm;0;ON;<narrow> 2192;;;;N;;;;;
-FFEC;HALFWIDTH DOWNWARDS ARROW;Sm;0;ON;<narrow> 2193;;;;N;;;;;
-FFED;HALFWIDTH BLACK SQUARE;So;0;ON;<narrow> 25A0;;;;N;;;;;
-FFEE;HALFWIDTH WHITE CIRCLE;So;0;ON;<narrow> 25CB;;;;N;;;;;
-FFF9;INTERLINEAR ANNOTATION ANCHOR;Cf;0;ON;;;;;N;;;;;
-FFFA;INTERLINEAR ANNOTATION SEPARATOR;Cf;0;ON;;;;;N;;;;;
-FFFB;INTERLINEAR ANNOTATION TERMINATOR;Cf;0;ON;;;;;N;;;;;
-FFFC;OBJECT REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
-FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
-10000;LINEAR B SYLLABLE B008 A;Lo;0;L;;;;;N;;;;;
-10001;LINEAR B SYLLABLE B038 E;Lo;0;L;;;;;N;;;;;
-10002;LINEAR B SYLLABLE B028 I;Lo;0;L;;;;;N;;;;;
-10003;LINEAR B SYLLABLE B061 O;Lo;0;L;;;;;N;;;;;
-10004;LINEAR B SYLLABLE B010 U;Lo;0;L;;;;;N;;;;;
-10005;LINEAR B SYLLABLE B001 DA;Lo;0;L;;;;;N;;;;;
-10006;LINEAR B SYLLABLE B045 DE;Lo;0;L;;;;;N;;;;;
-10007;LINEAR B SYLLABLE B007 DI;Lo;0;L;;;;;N;;;;;
-10008;LINEAR B SYLLABLE B014 DO;Lo;0;L;;;;;N;;;;;
-10009;LINEAR B SYLLABLE B051 DU;Lo;0;L;;;;;N;;;;;
-1000A;LINEAR B SYLLABLE B057 JA;Lo;0;L;;;;;N;;;;;
-1000B;LINEAR B SYLLABLE B046 JE;Lo;0;L;;;;;N;;;;;
-1000D;LINEAR B SYLLABLE B036 JO;Lo;0;L;;;;;N;;;;;
-1000E;LINEAR B SYLLABLE B065 JU;Lo;0;L;;;;;N;;;;;
-1000F;LINEAR B SYLLABLE B077 KA;Lo;0;L;;;;;N;;;;;
-10010;LINEAR B SYLLABLE B044 KE;Lo;0;L;;;;;N;;;;;
-10011;LINEAR B SYLLABLE B067 KI;Lo;0;L;;;;;N;;;;;
-10012;LINEAR B SYLLABLE B070 KO;Lo;0;L;;;;;N;;;;;
-10013;LINEAR B SYLLABLE B081 KU;Lo;0;L;;;;;N;;;;;
-10014;LINEAR B SYLLABLE B080 MA;Lo;0;L;;;;;N;;;;;
-10015;LINEAR B SYLLABLE B013 ME;Lo;0;L;;;;;N;;;;;
-10016;LINEAR B SYLLABLE B073 MI;Lo;0;L;;;;;N;;;;;
-10017;LINEAR B SYLLABLE B015 MO;Lo;0;L;;;;;N;;;;;
-10018;LINEAR B SYLLABLE B023 MU;Lo;0;L;;;;;N;;;;;
-10019;LINEAR B SYLLABLE B006 NA;Lo;0;L;;;;;N;;;;;
-1001A;LINEAR B SYLLABLE B024 NE;Lo;0;L;;;;;N;;;;;
-1001B;LINEAR B SYLLABLE B030 NI;Lo;0;L;;;;;N;;;;;
-1001C;LINEAR B SYLLABLE B052 NO;Lo;0;L;;;;;N;;;;;
-1001D;LINEAR B SYLLABLE B055 NU;Lo;0;L;;;;;N;;;;;
-1001E;LINEAR B SYLLABLE B003 PA;Lo;0;L;;;;;N;;;;;
-1001F;LINEAR B SYLLABLE B072 PE;Lo;0;L;;;;;N;;;;;
-10020;LINEAR B SYLLABLE B039 PI;Lo;0;L;;;;;N;;;;;
-10021;LINEAR B SYLLABLE B011 PO;Lo;0;L;;;;;N;;;;;
-10022;LINEAR B SYLLABLE B050 PU;Lo;0;L;;;;;N;;;;;
-10023;LINEAR B SYLLABLE B016 QA;Lo;0;L;;;;;N;;;;;
-10024;LINEAR B SYLLABLE B078 QE;Lo;0;L;;;;;N;;;;;
-10025;LINEAR B SYLLABLE B021 QI;Lo;0;L;;;;;N;;;;;
-10026;LINEAR B SYLLABLE B032 QO;Lo;0;L;;;;;N;;;;;
-10028;LINEAR B SYLLABLE B060 RA;Lo;0;L;;;;;N;;;;;
-10029;LINEAR B SYLLABLE B027 RE;Lo;0;L;;;;;N;;;;;
-1002A;LINEAR B SYLLABLE B053 RI;Lo;0;L;;;;;N;;;;;
-1002B;LINEAR B SYLLABLE B002 RO;Lo;0;L;;;;;N;;;;;
-1002C;LINEAR B SYLLABLE B026 RU;Lo;0;L;;;;;N;;;;;
-1002D;LINEAR B SYLLABLE B031 SA;Lo;0;L;;;;;N;;;;;
-1002E;LINEAR B SYLLABLE B009 SE;Lo;0;L;;;;;N;;;;;
-1002F;LINEAR B SYLLABLE B041 SI;Lo;0;L;;;;;N;;;;;
-10030;LINEAR B SYLLABLE B012 SO;Lo;0;L;;;;;N;;;;;
-10031;LINEAR B SYLLABLE B058 SU;Lo;0;L;;;;;N;;;;;
-10032;LINEAR B SYLLABLE B059 TA;Lo;0;L;;;;;N;;;;;
-10033;LINEAR B SYLLABLE B004 TE;Lo;0;L;;;;;N;;;;;
-10034;LINEAR B SYLLABLE B037 TI;Lo;0;L;;;;;N;;;;;
-10035;LINEAR B SYLLABLE B005 TO;Lo;0;L;;;;;N;;;;;
-10036;LINEAR B SYLLABLE B069 TU;Lo;0;L;;;;;N;;;;;
-10037;LINEAR B SYLLABLE B054 WA;Lo;0;L;;;;;N;;;;;
-10038;LINEAR B SYLLABLE B075 WE;Lo;0;L;;;;;N;;;;;
-10039;LINEAR B SYLLABLE B040 WI;Lo;0;L;;;;;N;;;;;
-1003A;LINEAR B SYLLABLE B042 WO;Lo;0;L;;;;;N;;;;;
-1003C;LINEAR B SYLLABLE B017 ZA;Lo;0;L;;;;;N;;;;;
-1003D;LINEAR B SYLLABLE B074 ZE;Lo;0;L;;;;;N;;;;;
-1003F;LINEAR B SYLLABLE B020 ZO;Lo;0;L;;;;;N;;;;;
-10040;LINEAR B SYLLABLE B025 A2;Lo;0;L;;;;;N;;;;;
-10041;LINEAR B SYLLABLE B043 A3;Lo;0;L;;;;;N;;;;;
-10042;LINEAR B SYLLABLE B085 AU;Lo;0;L;;;;;N;;;;;
-10043;LINEAR B SYLLABLE B071 DWE;Lo;0;L;;;;;N;;;;;
-10044;LINEAR B SYLLABLE B090 DWO;Lo;0;L;;;;;N;;;;;
-10045;LINEAR B SYLLABLE B048 NWA;Lo;0;L;;;;;N;;;;;
-10046;LINEAR B SYLLABLE B029 PU2;Lo;0;L;;;;;N;;;;;
-10047;LINEAR B SYLLABLE B062 PTE;Lo;0;L;;;;;N;;;;;
-10048;LINEAR B SYLLABLE B076 RA2;Lo;0;L;;;;;N;;;;;
-10049;LINEAR B SYLLABLE B033 RA3;Lo;0;L;;;;;N;;;;;
-1004A;LINEAR B SYLLABLE B068 RO2;Lo;0;L;;;;;N;;;;;
-1004B;LINEAR B SYLLABLE B066 TA2;Lo;0;L;;;;;N;;;;;
-1004C;LINEAR B SYLLABLE B087 TWE;Lo;0;L;;;;;N;;;;;
-1004D;LINEAR B SYLLABLE B091 TWO;Lo;0;L;;;;;N;;;;;
-10050;LINEAR B SYMBOL B018;Lo;0;L;;;;;N;;;;;
-10051;LINEAR B SYMBOL B019;Lo;0;L;;;;;N;;;;;
-10052;LINEAR B SYMBOL B022;Lo;0;L;;;;;N;;;;;
-10053;LINEAR B SYMBOL B034;Lo;0;L;;;;;N;;;;;
-10054;LINEAR B SYMBOL B047;Lo;0;L;;;;;N;;;;;
-10055;LINEAR B SYMBOL B049;Lo;0;L;;;;;N;;;;;
-10056;LINEAR B SYMBOL B056;Lo;0;L;;;;;N;;;;;
-10057;LINEAR B SYMBOL B063;Lo;0;L;;;;;N;;;;;
-10058;LINEAR B SYMBOL B064;Lo;0;L;;;;;N;;;;;
-10059;LINEAR B SYMBOL B079;Lo;0;L;;;;;N;;;;;
-1005A;LINEAR B SYMBOL B082;Lo;0;L;;;;;N;;;;;
-1005B;LINEAR B SYMBOL B083;Lo;0;L;;;;;N;;;;;
-1005C;LINEAR B SYMBOL B086;Lo;0;L;;;;;N;;;;;
-1005D;LINEAR B SYMBOL B089;Lo;0;L;;;;;N;;;;;
-10080;LINEAR B IDEOGRAM B100 MAN;Lo;0;L;;;;;N;;;;;
-10081;LINEAR B IDEOGRAM B102 WOMAN;Lo;0;L;;;;;N;;;;;
-10082;LINEAR B IDEOGRAM B104 DEER;Lo;0;L;;;;;N;;;;;
-10083;LINEAR B IDEOGRAM B105 EQUID;Lo;0;L;;;;;N;;;;;
-10084;LINEAR B IDEOGRAM B105F MARE;Lo;0;L;;;;;N;;;;;
-10085;LINEAR B IDEOGRAM B105M STALLION;Lo;0;L;;;;;N;;;;;
-10086;LINEAR B IDEOGRAM B106F EWE;Lo;0;L;;;;;N;;;;;
-10087;LINEAR B IDEOGRAM B106M RAM;Lo;0;L;;;;;N;;;;;
-10088;LINEAR B IDEOGRAM B107F SHE-GOAT;Lo;0;L;;;;;N;;;;;
-10089;LINEAR B IDEOGRAM B107M HE-GOAT;Lo;0;L;;;;;N;;;;;
-1008A;LINEAR B IDEOGRAM B108F SOW;Lo;0;L;;;;;N;;;;;
-1008B;LINEAR B IDEOGRAM B108M BOAR;Lo;0;L;;;;;N;;;;;
-1008C;LINEAR B IDEOGRAM B109F COW;Lo;0;L;;;;;N;;;;;
-1008D;LINEAR B IDEOGRAM B109M BULL;Lo;0;L;;;;;N;;;;;
-1008E;LINEAR B IDEOGRAM B120 WHEAT;Lo;0;L;;;;;N;;;;;
-1008F;LINEAR B IDEOGRAM B121 BARLEY;Lo;0;L;;;;;N;;;;;
-10090;LINEAR B IDEOGRAM B122 OLIVE;Lo;0;L;;;;;N;;;;;
-10091;LINEAR B IDEOGRAM B123 SPICE;Lo;0;L;;;;;N;;;;;
-10092;LINEAR B IDEOGRAM B125 CYPERUS;Lo;0;L;;;;;N;;;;;
-10093;LINEAR B MONOGRAM B127 KAPO;Lo;0;L;;;;;N;;;;;
-10094;LINEAR B MONOGRAM B128 KANAKO;Lo;0;L;;;;;N;;;;;
-10095;LINEAR B IDEOGRAM B130 OIL;Lo;0;L;;;;;N;;;;;
-10096;LINEAR B IDEOGRAM B131 WINE;Lo;0;L;;;;;N;;;;;
-10097;LINEAR B IDEOGRAM B132;Lo;0;L;;;;;N;;;;;
-10098;LINEAR B MONOGRAM B133 AREPA;Lo;0;L;;;;;N;;;;;
-10099;LINEAR B MONOGRAM B135 MERI;Lo;0;L;;;;;N;;;;;
-1009A;LINEAR B IDEOGRAM B140 BRONZE;Lo;0;L;;;;;N;;;;;
-1009B;LINEAR B IDEOGRAM B141 GOLD;Lo;0;L;;;;;N;;;;;
-1009C;LINEAR B IDEOGRAM B142;Lo;0;L;;;;;N;;;;;
-1009D;LINEAR B IDEOGRAM B145 WOOL;Lo;0;L;;;;;N;;;;;
-1009E;LINEAR B IDEOGRAM B146;Lo;0;L;;;;;N;;;;;
-1009F;LINEAR B IDEOGRAM B150;Lo;0;L;;;;;N;;;;;
-100A0;LINEAR B IDEOGRAM B151 HORN;Lo;0;L;;;;;N;;;;;
-100A1;LINEAR B IDEOGRAM B152;Lo;0;L;;;;;N;;;;;
-100A2;LINEAR B IDEOGRAM B153;Lo;0;L;;;;;N;;;;;
-100A3;LINEAR B IDEOGRAM B154;Lo;0;L;;;;;N;;;;;
-100A4;LINEAR B MONOGRAM B156 TURO2;Lo;0;L;;;;;N;;;;;
-100A5;LINEAR B IDEOGRAM B157;Lo;0;L;;;;;N;;;;;
-100A6;LINEAR B IDEOGRAM B158;Lo;0;L;;;;;N;;;;;
-100A7;LINEAR B IDEOGRAM B159 CLOTH;Lo;0;L;;;;;N;;;;;
-100A8;LINEAR B IDEOGRAM B160;Lo;0;L;;;;;N;;;;;
-100A9;LINEAR B IDEOGRAM B161;Lo;0;L;;;;;N;;;;;
-100AA;LINEAR B IDEOGRAM B162 GARMENT;Lo;0;L;;;;;N;;;;;
-100AB;LINEAR B IDEOGRAM B163 ARMOUR;Lo;0;L;;;;;N;;;;;
-100AC;LINEAR B IDEOGRAM B164;Lo;0;L;;;;;N;;;;;
-100AD;LINEAR B IDEOGRAM B165;Lo;0;L;;;;;N;;;;;
-100AE;LINEAR B IDEOGRAM B166;Lo;0;L;;;;;N;;;;;
-100AF;LINEAR B IDEOGRAM B167;Lo;0;L;;;;;N;;;;;
-100B0;LINEAR B IDEOGRAM B168;Lo;0;L;;;;;N;;;;;
-100B1;LINEAR B IDEOGRAM B169;Lo;0;L;;;;;N;;;;;
-100B2;LINEAR B IDEOGRAM B170;Lo;0;L;;;;;N;;;;;
-100B3;LINEAR B IDEOGRAM B171;Lo;0;L;;;;;N;;;;;
-100B4;LINEAR B IDEOGRAM B172;Lo;0;L;;;;;N;;;;;
-100B5;LINEAR B IDEOGRAM B173 MONTH;Lo;0;L;;;;;N;;;;;
-100B6;LINEAR B IDEOGRAM B174;Lo;0;L;;;;;N;;;;;
-100B7;LINEAR B IDEOGRAM B176 TREE;Lo;0;L;;;;;N;;;;;
-100B8;LINEAR B IDEOGRAM B177;Lo;0;L;;;;;N;;;;;
-100B9;LINEAR B IDEOGRAM B178;Lo;0;L;;;;;N;;;;;
-100BA;LINEAR B IDEOGRAM B179;Lo;0;L;;;;;N;;;;;
-100BB;LINEAR B IDEOGRAM B180;Lo;0;L;;;;;N;;;;;
-100BC;LINEAR B IDEOGRAM B181;Lo;0;L;;;;;N;;;;;
-100BD;LINEAR B IDEOGRAM B182;Lo;0;L;;;;;N;;;;;
-100BE;LINEAR B IDEOGRAM B183;Lo;0;L;;;;;N;;;;;
-100BF;LINEAR B IDEOGRAM B184;Lo;0;L;;;;;N;;;;;
-100C0;LINEAR B IDEOGRAM B185;Lo;0;L;;;;;N;;;;;
-100C1;LINEAR B IDEOGRAM B189;Lo;0;L;;;;;N;;;;;
-100C2;LINEAR B IDEOGRAM B190;Lo;0;L;;;;;N;;;;;
-100C3;LINEAR B IDEOGRAM B191 HELMET;Lo;0;L;;;;;N;;;;;
-100C4;LINEAR B IDEOGRAM B220 FOOTSTOOL;Lo;0;L;;;;;N;;;;;
-100C5;LINEAR B IDEOGRAM B225 BATHTUB;Lo;0;L;;;;;N;;;;;
-100C6;LINEAR B IDEOGRAM B230 SPEAR;Lo;0;L;;;;;N;;;;;
-100C7;LINEAR B IDEOGRAM B231 ARROW;Lo;0;L;;;;;N;;;;;
-100C8;LINEAR B IDEOGRAM B232;Lo;0;L;;;;;N;;;;;
-100C9;LINEAR B IDEOGRAM B233 SWORD;Lo;0;L;;;;;N;;;;;
-100CA;LINEAR B IDEOGRAM B234;Lo;0;L;;;;;N;;;;;
-100CB;LINEAR B IDEOGRAM B236;Lo;0;L;;;;;N;;;;;
-100CC;LINEAR B IDEOGRAM B240 WHEELED CHARIOT;Lo;0;L;;;;;N;;;;;
-100CD;LINEAR B IDEOGRAM B241 CHARIOT;Lo;0;L;;;;;N;;;;;
-100CE;LINEAR B IDEOGRAM B242 CHARIOT FRAME;Lo;0;L;;;;;N;;;;;
-100CF;LINEAR B IDEOGRAM B243 WHEEL;Lo;0;L;;;;;N;;;;;
-100D0;LINEAR B IDEOGRAM B245;Lo;0;L;;;;;N;;;;;
-100D1;LINEAR B IDEOGRAM B246;Lo;0;L;;;;;N;;;;;
-100D2;LINEAR B MONOGRAM B247 DIPTE;Lo;0;L;;;;;N;;;;;
-100D3;LINEAR B IDEOGRAM B248;Lo;0;L;;;;;N;;;;;
-100D4;LINEAR B IDEOGRAM B249;Lo;0;L;;;;;N;;;;;
-100D5;LINEAR B IDEOGRAM B251;Lo;0;L;;;;;N;;;;;
-100D6;LINEAR B IDEOGRAM B252;Lo;0;L;;;;;N;;;;;
-100D7;LINEAR B IDEOGRAM B253;Lo;0;L;;;;;N;;;;;
-100D8;LINEAR B IDEOGRAM B254 DART;Lo;0;L;;;;;N;;;;;
-100D9;LINEAR B IDEOGRAM B255;Lo;0;L;;;;;N;;;;;
-100DA;LINEAR B IDEOGRAM B256;Lo;0;L;;;;;N;;;;;
-100DB;LINEAR B IDEOGRAM B257;Lo;0;L;;;;;N;;;;;
-100DC;LINEAR B IDEOGRAM B258;Lo;0;L;;;;;N;;;;;
-100DD;LINEAR B IDEOGRAM B259;Lo;0;L;;;;;N;;;;;
-100DE;LINEAR B IDEOGRAM VESSEL B155;Lo;0;L;;;;;N;;;;;
-100DF;LINEAR B IDEOGRAM VESSEL B200;Lo;0;L;;;;;N;;;;;
-100E0;LINEAR B IDEOGRAM VESSEL B201;Lo;0;L;;;;;N;;;;;
-100E1;LINEAR B IDEOGRAM VESSEL B202;Lo;0;L;;;;;N;;;;;
-100E2;LINEAR B IDEOGRAM VESSEL B203;Lo;0;L;;;;;N;;;;;
-100E3;LINEAR B IDEOGRAM VESSEL B204;Lo;0;L;;;;;N;;;;;
-100E4;LINEAR B IDEOGRAM VESSEL B205;Lo;0;L;;;;;N;;;;;
-100E5;LINEAR B IDEOGRAM VESSEL B206;Lo;0;L;;;;;N;;;;;
-100E6;LINEAR B IDEOGRAM VESSEL B207;Lo;0;L;;;;;N;;;;;
-100E7;LINEAR B IDEOGRAM VESSEL B208;Lo;0;L;;;;;N;;;;;
-100E8;LINEAR B IDEOGRAM VESSEL B209;Lo;0;L;;;;;N;;;;;
-100E9;LINEAR B IDEOGRAM VESSEL B210;Lo;0;L;;;;;N;;;;;
-100EA;LINEAR B IDEOGRAM VESSEL B211;Lo;0;L;;;;;N;;;;;
-100EB;LINEAR B IDEOGRAM VESSEL B212;Lo;0;L;;;;;N;;;;;
-100EC;LINEAR B IDEOGRAM VESSEL B213;Lo;0;L;;;;;N;;;;;
-100ED;LINEAR B IDEOGRAM VESSEL B214;Lo;0;L;;;;;N;;;;;
-100EE;LINEAR B IDEOGRAM VESSEL B215;Lo;0;L;;;;;N;;;;;
-100EF;LINEAR B IDEOGRAM VESSEL B216;Lo;0;L;;;;;N;;;;;
-100F0;LINEAR B IDEOGRAM VESSEL B217;Lo;0;L;;;;;N;;;;;
-100F1;LINEAR B IDEOGRAM VESSEL B218;Lo;0;L;;;;;N;;;;;
-100F2;LINEAR B IDEOGRAM VESSEL B219;Lo;0;L;;;;;N;;;;;
-100F3;LINEAR B IDEOGRAM VESSEL B221;Lo;0;L;;;;;N;;;;;
-100F4;LINEAR B IDEOGRAM VESSEL B222;Lo;0;L;;;;;N;;;;;
-100F5;LINEAR B IDEOGRAM VESSEL B226;Lo;0;L;;;;;N;;;;;
-100F6;LINEAR B IDEOGRAM VESSEL B227;Lo;0;L;;;;;N;;;;;
-100F7;LINEAR B IDEOGRAM VESSEL B228;Lo;0;L;;;;;N;;;;;
-100F8;LINEAR B IDEOGRAM VESSEL B229;Lo;0;L;;;;;N;;;;;
-100F9;LINEAR B IDEOGRAM VESSEL B250;Lo;0;L;;;;;N;;;;;
-100FA;LINEAR B IDEOGRAM VESSEL B305;Lo;0;L;;;;;N;;;;;
-10100;AEGEAN WORD SEPARATOR LINE;Po;0;L;;;;;N;;;;;
-10101;AEGEAN WORD SEPARATOR DOT;Po;0;ON;;;;;N;;;;;
-10102;AEGEAN CHECK MARK;Po;0;L;;;;;N;;;;;
-10107;AEGEAN NUMBER ONE;No;0;L;;;;1;N;;;;;
-10108;AEGEAN NUMBER TWO;No;0;L;;;;2;N;;;;;
-10109;AEGEAN NUMBER THREE;No;0;L;;;;3;N;;;;;
-1010A;AEGEAN NUMBER FOUR;No;0;L;;;;4;N;;;;;
-1010B;AEGEAN NUMBER FIVE;No;0;L;;;;5;N;;;;;
-1010C;AEGEAN NUMBER SIX;No;0;L;;;;6;N;;;;;
-1010D;AEGEAN NUMBER SEVEN;No;0;L;;;;7;N;;;;;
-1010E;AEGEAN NUMBER EIGHT;No;0;L;;;;8;N;;;;;
-1010F;AEGEAN NUMBER NINE;No;0;L;;;;9;N;;;;;
-10110;AEGEAN NUMBER TEN;No;0;L;;;;10;N;;;;;
-10111;AEGEAN NUMBER TWENTY;No;0;L;;;;20;N;;;;;
-10112;AEGEAN NUMBER THIRTY;No;0;L;;;;30;N;;;;;
-10113;AEGEAN NUMBER FORTY;No;0;L;;;;40;N;;;;;
-10114;AEGEAN NUMBER FIFTY;No;0;L;;;;50;N;;;;;
-10115;AEGEAN NUMBER SIXTY;No;0;L;;;;60;N;;;;;
-10116;AEGEAN NUMBER SEVENTY;No;0;L;;;;70;N;;;;;
-10117;AEGEAN NUMBER EIGHTY;No;0;L;;;;80;N;;;;;
-10118;AEGEAN NUMBER NINETY;No;0;L;;;;90;N;;;;;
-10119;AEGEAN NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;;
-1011A;AEGEAN NUMBER TWO HUNDRED;No;0;L;;;;200;N;;;;;
-1011B;AEGEAN NUMBER THREE HUNDRED;No;0;L;;;;300;N;;;;;
-1011C;AEGEAN NUMBER FOUR HUNDRED;No;0;L;;;;400;N;;;;;
-1011D;AEGEAN NUMBER FIVE HUNDRED;No;0;L;;;;500;N;;;;;
-1011E;AEGEAN NUMBER SIX HUNDRED;No;0;L;;;;600;N;;;;;
-1011F;AEGEAN NUMBER SEVEN HUNDRED;No;0;L;;;;700;N;;;;;
-10120;AEGEAN NUMBER EIGHT HUNDRED;No;0;L;;;;800;N;;;;;
-10121;AEGEAN NUMBER NINE HUNDRED;No;0;L;;;;900;N;;;;;
-10122;AEGEAN NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;;
-10123;AEGEAN NUMBER TWO THOUSAND;No;0;L;;;;2000;N;;;;;
-10124;AEGEAN NUMBER THREE THOUSAND;No;0;L;;;;3000;N;;;;;
-10125;AEGEAN NUMBER FOUR THOUSAND;No;0;L;;;;4000;N;;;;;
-10126;AEGEAN NUMBER FIVE THOUSAND;No;0;L;;;;5000;N;;;;;
-10127;AEGEAN NUMBER SIX THOUSAND;No;0;L;;;;6000;N;;;;;
-10128;AEGEAN NUMBER SEVEN THOUSAND;No;0;L;;;;7000;N;;;;;
-10129;AEGEAN NUMBER EIGHT THOUSAND;No;0;L;;;;8000;N;;;;;
-1012A;AEGEAN NUMBER NINE THOUSAND;No;0;L;;;;9000;N;;;;;
-1012B;AEGEAN NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;;
-1012C;AEGEAN NUMBER TWENTY THOUSAND;No;0;L;;;;20000;N;;;;;
-1012D;AEGEAN NUMBER THIRTY THOUSAND;No;0;L;;;;30000;N;;;;;
-1012E;AEGEAN NUMBER FORTY THOUSAND;No;0;L;;;;40000;N;;;;;
-1012F;AEGEAN NUMBER FIFTY THOUSAND;No;0;L;;;;50000;N;;;;;
-10130;AEGEAN NUMBER SIXTY THOUSAND;No;0;L;;;;60000;N;;;;;
-10131;AEGEAN NUMBER SEVENTY THOUSAND;No;0;L;;;;70000;N;;;;;
-10132;AEGEAN NUMBER EIGHTY THOUSAND;No;0;L;;;;80000;N;;;;;
-10133;AEGEAN NUMBER NINETY THOUSAND;No;0;L;;;;90000;N;;;;;
-10137;AEGEAN WEIGHT BASE UNIT;So;0;L;;;;;N;;;;;
-10138;AEGEAN WEIGHT FIRST SUBUNIT;So;0;L;;;;;N;;;;;
-10139;AEGEAN WEIGHT SECOND SUBUNIT;So;0;L;;;;;N;;;;;
-1013A;AEGEAN WEIGHT THIRD SUBUNIT;So;0;L;;;;;N;;;;;
-1013B;AEGEAN WEIGHT FOURTH SUBUNIT;So;0;L;;;;;N;;;;;
-1013C;AEGEAN DRY MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;;
-1013D;AEGEAN LIQUID MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;;
-1013E;AEGEAN MEASURE SECOND SUBUNIT;So;0;L;;;;;N;;;;;
-1013F;AEGEAN MEASURE THIRD SUBUNIT;So;0;L;;;;;N;;;;;
-10140;GREEK ACROPHONIC ATTIC ONE QUARTER;Nl;0;ON;;;;1/4;N;;;;;
-10141;GREEK ACROPHONIC ATTIC ONE HALF;Nl;0;ON;;;;1/2;N;;;;;
-10142;GREEK ACROPHONIC ATTIC ONE DRACHMA;Nl;0;ON;;;;1;N;;;;;
-10143;GREEK ACROPHONIC ATTIC FIVE;Nl;0;ON;;;;5;N;;;;;
-10144;GREEK ACROPHONIC ATTIC FIFTY;Nl;0;ON;;;;50;N;;;;;
-10145;GREEK ACROPHONIC ATTIC FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
-10146;GREEK ACROPHONIC ATTIC FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;;
-10147;GREEK ACROPHONIC ATTIC FIFTY THOUSAND;Nl;0;ON;;;;50000;N;;;;;
-10148;GREEK ACROPHONIC ATTIC FIVE TALENTS;Nl;0;ON;;;;5;N;;;;;
-10149;GREEK ACROPHONIC ATTIC TEN TALENTS;Nl;0;ON;;;;10;N;;;;;
-1014A;GREEK ACROPHONIC ATTIC FIFTY TALENTS;Nl;0;ON;;;;50;N;;;;;
-1014B;GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS;Nl;0;ON;;;;100;N;;;;;
-1014C;GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS;Nl;0;ON;;;;500;N;;;;;
-1014D;GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS;Nl;0;ON;;;;1000;N;;;;;
-1014E;GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS;Nl;0;ON;;;;5000;N;;;;;
-1014F;GREEK ACROPHONIC ATTIC FIVE STATERS;Nl;0;ON;;;;5;N;;;;;
-10150;GREEK ACROPHONIC ATTIC TEN STATERS;Nl;0;ON;;;;10;N;;;;;
-10151;GREEK ACROPHONIC ATTIC FIFTY STATERS;Nl;0;ON;;;;50;N;;;;;
-10152;GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS;Nl;0;ON;;;;100;N;;;;;
-10153;GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS;Nl;0;ON;;;;500;N;;;;;
-10154;GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS;Nl;0;ON;;;;1000;N;;;;;
-10155;GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS;Nl;0;ON;;;;10000;N;;;;;
-10156;GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS;Nl;0;ON;;;;50000;N;;;;;
-10157;GREEK ACROPHONIC ATTIC TEN MNAS;Nl;0;ON;;;;10;N;;;;;
-10158;GREEK ACROPHONIC HERAEUM ONE PLETHRON;Nl;0;ON;;;;1;N;;;;;
-10159;GREEK ACROPHONIC THESPIAN ONE;Nl;0;ON;;;;1;N;;;;;
-1015A;GREEK ACROPHONIC HERMIONIAN ONE;Nl;0;ON;;;;1;N;;;;;
-1015B;GREEK ACROPHONIC EPIDAUREAN TWO;Nl;0;ON;;;;2;N;;;;;
-1015C;GREEK ACROPHONIC THESPIAN TWO;Nl;0;ON;;;;2;N;;;;;
-1015D;GREEK ACROPHONIC CYRENAIC TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;;
-1015E;GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;;
-1015F;GREEK ACROPHONIC TROEZENIAN FIVE;Nl;0;ON;;;;5;N;;;;;
-10160;GREEK ACROPHONIC TROEZENIAN TEN;Nl;0;ON;;;;10;N;;;;;
-10161;GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM;Nl;0;ON;;;;10;N;;;;;
-10162;GREEK ACROPHONIC HERMIONIAN TEN;Nl;0;ON;;;;10;N;;;;;
-10163;GREEK ACROPHONIC MESSENIAN TEN;Nl;0;ON;;;;10;N;;;;;
-10164;GREEK ACROPHONIC THESPIAN TEN;Nl;0;ON;;;;10;N;;;;;
-10165;GREEK ACROPHONIC THESPIAN THIRTY;Nl;0;ON;;;;30;N;;;;;
-10166;GREEK ACROPHONIC TROEZENIAN FIFTY;Nl;0;ON;;;;50;N;;;;;
-10167;GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM;Nl;0;ON;;;;50;N;;;;;
-10168;GREEK ACROPHONIC HERMIONIAN FIFTY;Nl;0;ON;;;;50;N;;;;;
-10169;GREEK ACROPHONIC THESPIAN FIFTY;Nl;0;ON;;;;50;N;;;;;
-1016A;GREEK ACROPHONIC THESPIAN ONE HUNDRED;Nl;0;ON;;;;100;N;;;;;
-1016B;GREEK ACROPHONIC THESPIAN THREE HUNDRED;Nl;0;ON;;;;300;N;;;;;
-1016C;GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
-1016D;GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
-1016E;GREEK ACROPHONIC THESPIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
-1016F;GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
-10170;GREEK ACROPHONIC NAXIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
-10171;GREEK ACROPHONIC THESPIAN ONE THOUSAND;Nl;0;ON;;;;1000;N;;;;;
-10172;GREEK ACROPHONIC THESPIAN FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;;
-10173;GREEK ACROPHONIC DELPHIC FIVE MNAS;Nl;0;ON;;;;5;N;;;;;
-10174;GREEK ACROPHONIC STRATIAN FIFTY MNAS;Nl;0;ON;;;;50;N;;;;;
-10175;GREEK ONE HALF SIGN;No;0;ON;;;;1/2;N;;;;;
-10176;GREEK ONE HALF SIGN ALTERNATE FORM;No;0;ON;;;;1/2;N;;;;;
-10177;GREEK TWO THIRDS SIGN;No;0;ON;;;;2/3;N;;;;;
-10178;GREEK THREE QUARTERS SIGN;No;0;ON;;;;3/4;N;;;;;
-10179;GREEK YEAR SIGN;So;0;ON;;;;;N;;;;;
-1017A;GREEK TALENT SIGN;So;0;ON;;;;;N;;;;;
-1017B;GREEK DRACHMA SIGN;So;0;ON;;;;;N;;;;;
-1017C;GREEK OBOL SIGN;So;0;ON;;;;;N;;;;;
-1017D;GREEK TWO OBOLS SIGN;So;0;ON;;;;;N;;;;;
-1017E;GREEK THREE OBOLS SIGN;So;0;ON;;;;;N;;;;;
-1017F;GREEK FOUR OBOLS SIGN;So;0;ON;;;;;N;;;;;
-10180;GREEK FIVE OBOLS SIGN;So;0;ON;;;;;N;;;;;
-10181;GREEK METRETES SIGN;So;0;ON;;;;;N;;;;;
-10182;GREEK KYATHOS BASE SIGN;So;0;ON;;;;;N;;;;;
-10183;GREEK LITRA SIGN;So;0;ON;;;;;N;;;;;
-10184;GREEK OUNKIA SIGN;So;0;ON;;;;;N;;;;;
-10185;GREEK XESTES SIGN;So;0;ON;;;;;N;;;;;
-10186;GREEK ARTABE SIGN;So;0;ON;;;;;N;;;;;
-10187;GREEK AROURA SIGN;So;0;ON;;;;;N;;;;;
-10188;GREEK GRAMMA SIGN;So;0;ON;;;;;N;;;;;
-10189;GREEK TRYBLION BASE SIGN;So;0;ON;;;;;N;;;;;
-1018A;GREEK ZERO SIGN;No;0;ON;;;;0;N;;;;;
-10190;ROMAN SEXTANS SIGN;So;0;ON;;;;;N;;;;;
-10191;ROMAN UNCIA SIGN;So;0;ON;;;;;N;;;;;
-10192;ROMAN SEMUNCIA SIGN;So;0;ON;;;;;N;;;;;
-10193;ROMAN SEXTULA SIGN;So;0;ON;;;;;N;;;;;
-10194;ROMAN DIMIDIA SEXTULA SIGN;So;0;ON;;;;;N;;;;;
-10195;ROMAN SILIQUA SIGN;So;0;ON;;;;;N;;;;;
-10196;ROMAN DENARIUS SIGN;So;0;ON;;;;;N;;;;;
-10197;ROMAN QUINARIUS SIGN;So;0;ON;;;;;N;;;;;
-10198;ROMAN SESTERTIUS SIGN;So;0;ON;;;;;N;;;;;
-10199;ROMAN DUPONDIUS SIGN;So;0;ON;;;;;N;;;;;
-1019A;ROMAN AS SIGN;So;0;ON;;;;;N;;;;;
-1019B;ROMAN CENTURIAL SIGN;So;0;ON;;;;;N;;;;;
-101D0;PHAISTOS DISC SIGN PEDESTRIAN;So;0;L;;;;;N;;;;;
-101D1;PHAISTOS DISC SIGN PLUMED HEAD;So;0;L;;;;;N;;;;;
-101D2;PHAISTOS DISC SIGN TATTOOED HEAD;So;0;L;;;;;N;;;;;
-101D3;PHAISTOS DISC SIGN CAPTIVE;So;0;L;;;;;N;;;;;
-101D4;PHAISTOS DISC SIGN CHILD;So;0;L;;;;;N;;;;;
-101D5;PHAISTOS DISC SIGN WOMAN;So;0;L;;;;;N;;;;;
-101D6;PHAISTOS DISC SIGN HELMET;So;0;L;;;;;N;;;;;
-101D7;PHAISTOS DISC SIGN GAUNTLET;So;0;L;;;;;N;;;;;
-101D8;PHAISTOS DISC SIGN TIARA;So;0;L;;;;;N;;;;;
-101D9;PHAISTOS DISC SIGN ARROW;So;0;L;;;;;N;;;;;
-101DA;PHAISTOS DISC SIGN BOW;So;0;L;;;;;N;;;;;
-101DB;PHAISTOS DISC SIGN SHIELD;So;0;L;;;;;N;;;;;
-101DC;PHAISTOS DISC SIGN CLUB;So;0;L;;;;;N;;;;;
-101DD;PHAISTOS DISC SIGN MANACLES;So;0;L;;;;;N;;;;;
-101DE;PHAISTOS DISC SIGN MATTOCK;So;0;L;;;;;N;;;;;
-101DF;PHAISTOS DISC SIGN SAW;So;0;L;;;;;N;;;;;
-101E0;PHAISTOS DISC SIGN LID;So;0;L;;;;;N;;;;;
-101E1;PHAISTOS DISC SIGN BOOMERANG;So;0;L;;;;;N;;;;;
-101E2;PHAISTOS DISC SIGN CARPENTRY PLANE;So;0;L;;;;;N;;;;;
-101E3;PHAISTOS DISC SIGN DOLIUM;So;0;L;;;;;N;;;;;
-101E4;PHAISTOS DISC SIGN COMB;So;0;L;;;;;N;;;;;
-101E5;PHAISTOS DISC SIGN SLING;So;0;L;;;;;N;;;;;
-101E6;PHAISTOS DISC SIGN COLUMN;So;0;L;;;;;N;;;;;
-101E7;PHAISTOS DISC SIGN BEEHIVE;So;0;L;;;;;N;;;;;
-101E8;PHAISTOS DISC SIGN SHIP;So;0;L;;;;;N;;;;;
-101E9;PHAISTOS DISC SIGN HORN;So;0;L;;;;;N;;;;;
-101EA;PHAISTOS DISC SIGN HIDE;So;0;L;;;;;N;;;;;
-101EB;PHAISTOS DISC SIGN BULLS LEG;So;0;L;;;;;N;;;;;
-101EC;PHAISTOS DISC SIGN CAT;So;0;L;;;;;N;;;;;
-101ED;PHAISTOS DISC SIGN RAM;So;0;L;;;;;N;;;;;
-101EE;PHAISTOS DISC SIGN EAGLE;So;0;L;;;;;N;;;;;
-101EF;PHAISTOS DISC SIGN DOVE;So;0;L;;;;;N;;;;;
-101F0;PHAISTOS DISC SIGN TUNNY;So;0;L;;;;;N;;;;;
-101F1;PHAISTOS DISC SIGN BEE;So;0;L;;;;;N;;;;;
-101F2;PHAISTOS DISC SIGN PLANE TREE;So;0;L;;;;;N;;;;;
-101F3;PHAISTOS DISC SIGN VINE;So;0;L;;;;;N;;;;;
-101F4;PHAISTOS DISC SIGN PAPYRUS;So;0;L;;;;;N;;;;;
-101F5;PHAISTOS DISC SIGN ROSETTE;So;0;L;;;;;N;;;;;
-101F6;PHAISTOS DISC SIGN LILY;So;0;L;;;;;N;;;;;
-101F7;PHAISTOS DISC SIGN OX BACK;So;0;L;;;;;N;;;;;
-101F8;PHAISTOS DISC SIGN FLUTE;So;0;L;;;;;N;;;;;
-101F9;PHAISTOS DISC SIGN GRATER;So;0;L;;;;;N;;;;;
-101FA;PHAISTOS DISC SIGN STRAINER;So;0;L;;;;;N;;;;;
-101FB;PHAISTOS DISC SIGN SMALL AXE;So;0;L;;;;;N;;;;;
-101FC;PHAISTOS DISC SIGN WAVY BAND;So;0;L;;;;;N;;;;;
-101FD;PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE;Mn;220;NSM;;;;;N;;;;;
-10280;LYCIAN LETTER A;Lo;0;L;;;;;N;;;;;
-10281;LYCIAN LETTER E;Lo;0;L;;;;;N;;;;;
-10282;LYCIAN LETTER B;Lo;0;L;;;;;N;;;;;
-10283;LYCIAN LETTER BH;Lo;0;L;;;;;N;;;;;
-10284;LYCIAN LETTER G;Lo;0;L;;;;;N;;;;;
-10285;LYCIAN LETTER D;Lo;0;L;;;;;N;;;;;
-10286;LYCIAN LETTER I;Lo;0;L;;;;;N;;;;;
-10287;LYCIAN LETTER W;Lo;0;L;;;;;N;;;;;
-10288;LYCIAN LETTER Z;Lo;0;L;;;;;N;;;;;
-10289;LYCIAN LETTER TH;Lo;0;L;;;;;N;;;;;
-1028A;LYCIAN LETTER J;Lo;0;L;;;;;N;;;;;
-1028B;LYCIAN LETTER K;Lo;0;L;;;;;N;;;;;
-1028C;LYCIAN LETTER Q;Lo;0;L;;;;;N;;;;;
-1028D;LYCIAN LETTER L;Lo;0;L;;;;;N;;;;;
-1028E;LYCIAN LETTER M;Lo;0;L;;;;;N;;;;;
-1028F;LYCIAN LETTER N;Lo;0;L;;;;;N;;;;;
-10290;LYCIAN LETTER MM;Lo;0;L;;;;;N;;;;;
-10291;LYCIAN LETTER NN;Lo;0;L;;;;;N;;;;;
-10292;LYCIAN LETTER U;Lo;0;L;;;;;N;;;;;
-10293;LYCIAN LETTER P;Lo;0;L;;;;;N;;;;;
-10294;LYCIAN LETTER KK;Lo;0;L;;;;;N;;;;;
-10295;LYCIAN LETTER R;Lo;0;L;;;;;N;;;;;
-10296;LYCIAN LETTER S;Lo;0;L;;;;;N;;;;;
-10297;LYCIAN LETTER T;Lo;0;L;;;;;N;;;;;
-10298;LYCIAN LETTER TT;Lo;0;L;;;;;N;;;;;
-10299;LYCIAN LETTER AN;Lo;0;L;;;;;N;;;;;
-1029A;LYCIAN LETTER EN;Lo;0;L;;;;;N;;;;;
-1029B;LYCIAN LETTER H;Lo;0;L;;;;;N;;;;;
-1029C;LYCIAN LETTER X;Lo;0;L;;;;;N;;;;;
-102A0;CARIAN LETTER A;Lo;0;L;;;;;N;;;;;
-102A1;CARIAN LETTER P2;Lo;0;L;;;;;N;;;;;
-102A2;CARIAN LETTER D;Lo;0;L;;;;;N;;;;;
-102A3;CARIAN LETTER L;Lo;0;L;;;;;N;;;;;
-102A4;CARIAN LETTER UUU;Lo;0;L;;;;;N;;;;;
-102A5;CARIAN LETTER R;Lo;0;L;;;;;N;;;;;
-102A6;CARIAN LETTER LD;Lo;0;L;;;;;N;;;;;
-102A7;CARIAN LETTER A2;Lo;0;L;;;;;N;;;;;
-102A8;CARIAN LETTER Q;Lo;0;L;;;;;N;;;;;
-102A9;CARIAN LETTER B;Lo;0;L;;;;;N;;;;;
-102AA;CARIAN LETTER M;Lo;0;L;;;;;N;;;;;
-102AB;CARIAN LETTER O;Lo;0;L;;;;;N;;;;;
-102AC;CARIAN LETTER D2;Lo;0;L;;;;;N;;;;;
-102AD;CARIAN LETTER T;Lo;0;L;;;;;N;;;;;
-102AE;CARIAN LETTER SH;Lo;0;L;;;;;N;;;;;
-102AF;CARIAN LETTER SH2;Lo;0;L;;;;;N;;;;;
-102B0;CARIAN LETTER S;Lo;0;L;;;;;N;;;;;
-102B1;CARIAN LETTER C-18;Lo;0;L;;;;;N;;;;;
-102B2;CARIAN LETTER U;Lo;0;L;;;;;N;;;;;
-102B3;CARIAN LETTER NN;Lo;0;L;;;;;N;;;;;
-102B4;CARIAN LETTER X;Lo;0;L;;;;;N;;;;;
-102B5;CARIAN LETTER N;Lo;0;L;;;;;N;;;;;
-102B6;CARIAN LETTER TT2;Lo;0;L;;;;;N;;;;;
-102B7;CARIAN LETTER P;Lo;0;L;;;;;N;;;;;
-102B8;CARIAN LETTER SS;Lo;0;L;;;;;N;;;;;
-102B9;CARIAN LETTER I;Lo;0;L;;;;;N;;;;;
-102BA;CARIAN LETTER E;Lo;0;L;;;;;N;;;;;
-102BB;CARIAN LETTER UUUU;Lo;0;L;;;;;N;;;;;
-102BC;CARIAN LETTER K;Lo;0;L;;;;;N;;;;;
-102BD;CARIAN LETTER K2;Lo;0;L;;;;;N;;;;;
-102BE;CARIAN LETTER ND;Lo;0;L;;;;;N;;;;;
-102BF;CARIAN LETTER UU;Lo;0;L;;;;;N;;;;;
-102C0;CARIAN LETTER G;Lo;0;L;;;;;N;;;;;
-102C1;CARIAN LETTER G2;Lo;0;L;;;;;N;;;;;
-102C2;CARIAN LETTER ST;Lo;0;L;;;;;N;;;;;
-102C3;CARIAN LETTER ST2;Lo;0;L;;;;;N;;;;;
-102C4;CARIAN LETTER NG;Lo;0;L;;;;;N;;;;;
-102C5;CARIAN LETTER II;Lo;0;L;;;;;N;;;;;
-102C6;CARIAN LETTER C-39;Lo;0;L;;;;;N;;;;;
-102C7;CARIAN LETTER TT;Lo;0;L;;;;;N;;;;;
-102C8;CARIAN LETTER UUU2;Lo;0;L;;;;;N;;;;;
-102C9;CARIAN LETTER RR;Lo;0;L;;;;;N;;;;;
-102CA;CARIAN LETTER MB;Lo;0;L;;;;;N;;;;;
-102CB;CARIAN LETTER MB2;Lo;0;L;;;;;N;;;;;
-102CC;CARIAN LETTER MB3;Lo;0;L;;;;;N;;;;;
-102CD;CARIAN LETTER MB4;Lo;0;L;;;;;N;;;;;
-102CE;CARIAN LETTER LD2;Lo;0;L;;;;;N;;;;;
-102CF;CARIAN LETTER E2;Lo;0;L;;;;;N;;;;;
-102D0;CARIAN LETTER UUU3;Lo;0;L;;;;;N;;;;;
-10300;OLD ITALIC LETTER A;Lo;0;L;;;;;N;;;;;
-10301;OLD ITALIC LETTER BE;Lo;0;L;;;;;N;;;;;
-10302;OLD ITALIC LETTER KE;Lo;0;L;;;;;N;;;;;
-10303;OLD ITALIC LETTER DE;Lo;0;L;;;;;N;;;;;
-10304;OLD ITALIC LETTER E;Lo;0;L;;;;;N;;;;;
-10305;OLD ITALIC LETTER VE;Lo;0;L;;;;;N;;;;;
-10306;OLD ITALIC LETTER ZE;Lo;0;L;;;;;N;;;;;
-10307;OLD ITALIC LETTER HE;Lo;0;L;;;;;N;;;;;
-10308;OLD ITALIC LETTER THE;Lo;0;L;;;;;N;;;;;
-10309;OLD ITALIC LETTER I;Lo;0;L;;;;;N;;;;;
-1030A;OLD ITALIC LETTER KA;Lo;0;L;;;;;N;;;;;
-1030B;OLD ITALIC LETTER EL;Lo;0;L;;;;;N;;;;;
-1030C;OLD ITALIC LETTER EM;Lo;0;L;;;;;N;;;;;
-1030D;OLD ITALIC LETTER EN;Lo;0;L;;;;;N;;;;;
-1030E;OLD ITALIC LETTER ESH;Lo;0;L;;;;;N;;;;;
-1030F;OLD ITALIC LETTER O;Lo;0;L;;;;;N;;;;;
-10310;OLD ITALIC LETTER PE;Lo;0;L;;;;;N;;;;;
-10311;OLD ITALIC LETTER SHE;Lo;0;L;;;;;N;;;;;
-10312;OLD ITALIC LETTER KU;Lo;0;L;;;;;N;;;;;
-10313;OLD ITALIC LETTER ER;Lo;0;L;;;;;N;;;;;
-10314;OLD ITALIC LETTER ES;Lo;0;L;;;;;N;;;;;
-10315;OLD ITALIC LETTER TE;Lo;0;L;;;;;N;;;;;
-10316;OLD ITALIC LETTER U;Lo;0;L;;;;;N;;;;;
-10317;OLD ITALIC LETTER EKS;Lo;0;L;;;;;N;;;;;
-10318;OLD ITALIC LETTER PHE;Lo;0;L;;;;;N;;;;;
-10319;OLD ITALIC LETTER KHE;Lo;0;L;;;;;N;;;;;
-1031A;OLD ITALIC LETTER EF;Lo;0;L;;;;;N;;;;;
-1031B;OLD ITALIC LETTER ERS;Lo;0;L;;;;;N;;;;;
-1031C;OLD ITALIC LETTER CHE;Lo;0;L;;;;;N;;;;;
-1031D;OLD ITALIC LETTER II;Lo;0;L;;;;;N;;;;;
-1031E;OLD ITALIC LETTER UU;Lo;0;L;;;;;N;;;;;
-10320;OLD ITALIC NUMERAL ONE;No;0;L;;;;1;N;;;;;
-10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;;
-10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;;
-10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;;
-10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;;
-10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;;
-10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;;
-10333;GOTHIC LETTER DAGS;Lo;0;L;;;;;N;;;;;
-10334;GOTHIC LETTER AIHVUS;Lo;0;L;;;;;N;;;;;
-10335;GOTHIC LETTER QAIRTHRA;Lo;0;L;;;;;N;;;;;
-10336;GOTHIC LETTER IUJA;Lo;0;L;;;;;N;;;;;
-10337;GOTHIC LETTER HAGL;Lo;0;L;;;;;N;;;;;
-10338;GOTHIC LETTER THIUTH;Lo;0;L;;;;;N;;;;;
-10339;GOTHIC LETTER EIS;Lo;0;L;;;;;N;;;;;
-1033A;GOTHIC LETTER KUSMA;Lo;0;L;;;;;N;;;;;
-1033B;GOTHIC LETTER LAGUS;Lo;0;L;;;;;N;;;;;
-1033C;GOTHIC LETTER MANNA;Lo;0;L;;;;;N;;;;;
-1033D;GOTHIC LETTER NAUTHS;Lo;0;L;;;;;N;;;;;
-1033E;GOTHIC LETTER JER;Lo;0;L;;;;;N;;;;;
-1033F;GOTHIC LETTER URUS;Lo;0;L;;;;;N;;;;;
-10340;GOTHIC LETTER PAIRTHRA;Lo;0;L;;;;;N;;;;;
-10341;GOTHIC LETTER NINETY;Nl;0;L;;;;90;N;;;;;
-10342;GOTHIC LETTER RAIDA;Lo;0;L;;;;;N;;;;;
-10343;GOTHIC LETTER SAUIL;Lo;0;L;;;;;N;;;;;
-10344;GOTHIC LETTER TEIWS;Lo;0;L;;;;;N;;;;;
-10345;GOTHIC LETTER WINJA;Lo;0;L;;;;;N;;;;;
-10346;GOTHIC LETTER FAIHU;Lo;0;L;;;;;N;;;;;
-10347;GOTHIC LETTER IGGWS;Lo;0;L;;;;;N;;;;;
-10348;GOTHIC LETTER HWAIR;Lo;0;L;;;;;N;;;;;
-10349;GOTHIC LETTER OTHAL;Lo;0;L;;;;;N;;;;;
-1034A;GOTHIC LETTER NINE HUNDRED;Nl;0;L;;;;900;N;;;;;
-10380;UGARITIC LETTER ALPA;Lo;0;L;;;;;N;;;;;
-10381;UGARITIC LETTER BETA;Lo;0;L;;;;;N;;;;;
-10382;UGARITIC LETTER GAMLA;Lo;0;L;;;;;N;;;;;
-10383;UGARITIC LETTER KHA;Lo;0;L;;;;;N;;;;;
-10384;UGARITIC LETTER DELTA;Lo;0;L;;;;;N;;;;;
-10385;UGARITIC LETTER HO;Lo;0;L;;;;;N;;;;;
-10386;UGARITIC LETTER WO;Lo;0;L;;;;;N;;;;;
-10387;UGARITIC LETTER ZETA;Lo;0;L;;;;;N;;;;;
-10388;UGARITIC LETTER HOTA;Lo;0;L;;;;;N;;;;;
-10389;UGARITIC LETTER TET;Lo;0;L;;;;;N;;;;;
-1038A;UGARITIC LETTER YOD;Lo;0;L;;;;;N;;;;;
-1038B;UGARITIC LETTER KAF;Lo;0;L;;;;;N;;;;;
-1038C;UGARITIC LETTER SHIN;Lo;0;L;;;;;N;;;;;
-1038D;UGARITIC LETTER LAMDA;Lo;0;L;;;;;N;;;;;
-1038E;UGARITIC LETTER MEM;Lo;0;L;;;;;N;;;;;
-1038F;UGARITIC LETTER DHAL;Lo;0;L;;;;;N;;;;;
-10390;UGARITIC LETTER NUN;Lo;0;L;;;;;N;;;;;
-10391;UGARITIC LETTER ZU;Lo;0;L;;;;;N;;;;;
-10392;UGARITIC LETTER SAMKA;Lo;0;L;;;;;N;;;;;
-10393;UGARITIC LETTER AIN;Lo;0;L;;;;;N;;;;;
-10394;UGARITIC LETTER PU;Lo;0;L;;;;;N;;;;;
-10395;UGARITIC LETTER SADE;Lo;0;L;;;;;N;;;;;
-10396;UGARITIC LETTER QOPA;Lo;0;L;;;;;N;;;;;
-10397;UGARITIC LETTER RASHA;Lo;0;L;;;;;N;;;;;
-10398;UGARITIC LETTER THANNA;Lo;0;L;;;;;N;;;;;
-10399;UGARITIC LETTER GHAIN;Lo;0;L;;;;;N;;;;;
-1039A;UGARITIC LETTER TO;Lo;0;L;;;;;N;;;;;
-1039B;UGARITIC LETTER I;Lo;0;L;;;;;N;;;;;
-1039C;UGARITIC LETTER U;Lo;0;L;;;;;N;;;;;
-1039D;UGARITIC LETTER SSU;Lo;0;L;;;;;N;;;;;
-1039F;UGARITIC WORD DIVIDER;Po;0;L;;;;;N;;;;;
-103A0;OLD PERSIAN SIGN A;Lo;0;L;;;;;N;;;;;
-103A1;OLD PERSIAN SIGN I;Lo;0;L;;;;;N;;;;;
-103A2;OLD PERSIAN SIGN U;Lo;0;L;;;;;N;;;;;
-103A3;OLD PERSIAN SIGN KA;Lo;0;L;;;;;N;;;;;
-103A4;OLD PERSIAN SIGN KU;Lo;0;L;;;;;N;;;;;
-103A5;OLD PERSIAN SIGN GA;Lo;0;L;;;;;N;;;;;
-103A6;OLD PERSIAN SIGN GU;Lo;0;L;;;;;N;;;;;
-103A7;OLD PERSIAN SIGN XA;Lo;0;L;;;;;N;;;;;
-103A8;OLD PERSIAN SIGN CA;Lo;0;L;;;;;N;;;;;
-103A9;OLD PERSIAN SIGN JA;Lo;0;L;;;;;N;;;;;
-103AA;OLD PERSIAN SIGN JI;Lo;0;L;;;;;N;;;;;
-103AB;OLD PERSIAN SIGN TA;Lo;0;L;;;;;N;;;;;
-103AC;OLD PERSIAN SIGN TU;Lo;0;L;;;;;N;;;;;
-103AD;OLD PERSIAN SIGN DA;Lo;0;L;;;;;N;;;;;
-103AE;OLD PERSIAN SIGN DI;Lo;0;L;;;;;N;;;;;
-103AF;OLD PERSIAN SIGN DU;Lo;0;L;;;;;N;;;;;
-103B0;OLD PERSIAN SIGN THA;Lo;0;L;;;;;N;;;;;
-103B1;OLD PERSIAN SIGN PA;Lo;0;L;;;;;N;;;;;
-103B2;OLD PERSIAN SIGN BA;Lo;0;L;;;;;N;;;;;
-103B3;OLD PERSIAN SIGN FA;Lo;0;L;;;;;N;;;;;
-103B4;OLD PERSIAN SIGN NA;Lo;0;L;;;;;N;;;;;
-103B5;OLD PERSIAN SIGN NU;Lo;0;L;;;;;N;;;;;
-103B6;OLD PERSIAN SIGN MA;Lo;0;L;;;;;N;;;;;
-103B7;OLD PERSIAN SIGN MI;Lo;0;L;;;;;N;;;;;
-103B8;OLD PERSIAN SIGN MU;Lo;0;L;;;;;N;;;;;
-103B9;OLD PERSIAN SIGN YA;Lo;0;L;;;;;N;;;;;
-103BA;OLD PERSIAN SIGN VA;Lo;0;L;;;;;N;;;;;
-103BB;OLD PERSIAN SIGN VI;Lo;0;L;;;;;N;;;;;
-103BC;OLD PERSIAN SIGN RA;Lo;0;L;;;;;N;;;;;
-103BD;OLD PERSIAN SIGN RU;Lo;0;L;;;;;N;;;;;
-103BE;OLD PERSIAN SIGN LA;Lo;0;L;;;;;N;;;;;
-103BF;OLD PERSIAN SIGN SA;Lo;0;L;;;;;N;;;;;
-103C0;OLD PERSIAN SIGN ZA;Lo;0;L;;;;;N;;;;;
-103C1;OLD PERSIAN SIGN SHA;Lo;0;L;;;;;N;;;;;
-103C2;OLD PERSIAN SIGN SSA;Lo;0;L;;;;;N;;;;;
-103C3;OLD PERSIAN SIGN HA;Lo;0;L;;;;;N;;;;;
-103C8;OLD PERSIAN SIGN AURAMAZDAA;Lo;0;L;;;;;N;;;;;
-103C9;OLD PERSIAN SIGN AURAMAZDAA-2;Lo;0;L;;;;;N;;;;;
-103CA;OLD PERSIAN SIGN AURAMAZDAAHA;Lo;0;L;;;;;N;;;;;
-103CB;OLD PERSIAN SIGN XSHAAYATHIYA;Lo;0;L;;;;;N;;;;;
-103CC;OLD PERSIAN SIGN DAHYAAUSH;Lo;0;L;;;;;N;;;;;
-103CD;OLD PERSIAN SIGN DAHYAAUSH-2;Lo;0;L;;;;;N;;;;;
-103CE;OLD PERSIAN SIGN BAGA;Lo;0;L;;;;;N;;;;;
-103CF;OLD PERSIAN SIGN BUUMISH;Lo;0;L;;;;;N;;;;;
-103D0;OLD PERSIAN WORD DIVIDER;Po;0;L;;;;;N;;;;;
-103D1;OLD PERSIAN NUMBER ONE;Nl;0;L;;;;1;N;;;;;
-103D2;OLD PERSIAN NUMBER TWO;Nl;0;L;;;;2;N;;;;;
-103D3;OLD PERSIAN NUMBER TEN;Nl;0;L;;;;10;N;;;;;
-103D4;OLD PERSIAN NUMBER TWENTY;Nl;0;L;;;;20;N;;;;;
-103D5;OLD PERSIAN NUMBER HUNDRED;Nl;0;L;;;;100;N;;;;;
-10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428;
-10401;DESERET CAPITAL LETTER LONG E;Lu;0;L;;;;;N;;;;10429;
-10402;DESERET CAPITAL LETTER LONG A;Lu;0;L;;;;;N;;;;1042A;
-10403;DESERET CAPITAL LETTER LONG AH;Lu;0;L;;;;;N;;;;1042B;
-10404;DESERET CAPITAL LETTER LONG O;Lu;0;L;;;;;N;;;;1042C;
-10405;DESERET CAPITAL LETTER LONG OO;Lu;0;L;;;;;N;;;;1042D;
-10406;DESERET CAPITAL LETTER SHORT I;Lu;0;L;;;;;N;;;;1042E;
-10407;DESERET CAPITAL LETTER SHORT E;Lu;0;L;;;;;N;;;;1042F;
-10408;DESERET CAPITAL LETTER SHORT A;Lu;0;L;;;;;N;;;;10430;
-10409;DESERET CAPITAL LETTER SHORT AH;Lu;0;L;;;;;N;;;;10431;
-1040A;DESERET CAPITAL LETTER SHORT O;Lu;0;L;;;;;N;;;;10432;
-1040B;DESERET CAPITAL LETTER SHORT OO;Lu;0;L;;;;;N;;;;10433;
-1040C;DESERET CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;10434;
-1040D;DESERET CAPITAL LETTER OW;Lu;0;L;;;;;N;;;;10435;
-1040E;DESERET CAPITAL LETTER WU;Lu;0;L;;;;;N;;;;10436;
-1040F;DESERET CAPITAL LETTER YEE;Lu;0;L;;;;;N;;;;10437;
-10410;DESERET CAPITAL LETTER H;Lu;0;L;;;;;N;;;;10438;
-10411;DESERET CAPITAL LETTER PEE;Lu;0;L;;;;;N;;;;10439;
-10412;DESERET CAPITAL LETTER BEE;Lu;0;L;;;;;N;;;;1043A;
-10413;DESERET CAPITAL LETTER TEE;Lu;0;L;;;;;N;;;;1043B;
-10414;DESERET CAPITAL LETTER DEE;Lu;0;L;;;;;N;;;;1043C;
-10415;DESERET CAPITAL LETTER CHEE;Lu;0;L;;;;;N;;;;1043D;
-10416;DESERET CAPITAL LETTER JEE;Lu;0;L;;;;;N;;;;1043E;
-10417;DESERET CAPITAL LETTER KAY;Lu;0;L;;;;;N;;;;1043F;
-10418;DESERET CAPITAL LETTER GAY;Lu;0;L;;;;;N;;;;10440;
-10419;DESERET CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;10441;
-1041A;DESERET CAPITAL LETTER VEE;Lu;0;L;;;;;N;;;;10442;
-1041B;DESERET CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;10443;
-1041C;DESERET CAPITAL LETTER THEE;Lu;0;L;;;;;N;;;;10444;
-1041D;DESERET CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;10445;
-1041E;DESERET CAPITAL LETTER ZEE;Lu;0;L;;;;;N;;;;10446;
-1041F;DESERET CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;10447;
-10420;DESERET CAPITAL LETTER ZHEE;Lu;0;L;;;;;N;;;;10448;
-10421;DESERET CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;10449;
-10422;DESERET CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;1044A;
-10423;DESERET CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;1044B;
-10424;DESERET CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;1044C;
-10425;DESERET CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;1044D;
-10426;DESERET CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;1044E;
-10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F;
-10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400
-10429;DESERET SMALL LETTER LONG E;Ll;0;L;;;;;N;;;10401;;10401
-1042A;DESERET SMALL LETTER LONG A;Ll;0;L;;;;;N;;;10402;;10402
-1042B;DESERET SMALL LETTER LONG AH;Ll;0;L;;;;;N;;;10403;;10403
-1042C;DESERET SMALL LETTER LONG O;Ll;0;L;;;;;N;;;10404;;10404
-1042D;DESERET SMALL LETTER LONG OO;Ll;0;L;;;;;N;;;10405;;10405
-1042E;DESERET SMALL LETTER SHORT I;Ll;0;L;;;;;N;;;10406;;10406
-1042F;DESERET SMALL LETTER SHORT E;Ll;0;L;;;;;N;;;10407;;10407
-10430;DESERET SMALL LETTER SHORT A;Ll;0;L;;;;;N;;;10408;;10408
-10431;DESERET SMALL LETTER SHORT AH;Ll;0;L;;;;;N;;;10409;;10409
-10432;DESERET SMALL LETTER SHORT O;Ll;0;L;;;;;N;;;1040A;;1040A
-10433;DESERET SMALL LETTER SHORT OO;Ll;0;L;;;;;N;;;1040B;;1040B
-10434;DESERET SMALL LETTER AY;Ll;0;L;;;;;N;;;1040C;;1040C
-10435;DESERET SMALL LETTER OW;Ll;0;L;;;;;N;;;1040D;;1040D
-10436;DESERET SMALL LETTER WU;Ll;0;L;;;;;N;;;1040E;;1040E
-10437;DESERET SMALL LETTER YEE;Ll;0;L;;;;;N;;;1040F;;1040F
-10438;DESERET SMALL LETTER H;Ll;0;L;;;;;N;;;10410;;10410
-10439;DESERET SMALL LETTER PEE;Ll;0;L;;;;;N;;;10411;;10411
-1043A;DESERET SMALL LETTER BEE;Ll;0;L;;;;;N;;;10412;;10412
-1043B;DESERET SMALL LETTER TEE;Ll;0;L;;;;;N;;;10413;;10413
-1043C;DESERET SMALL LETTER DEE;Ll;0;L;;;;;N;;;10414;;10414
-1043D;DESERET SMALL LETTER CHEE;Ll;0;L;;;;;N;;;10415;;10415
-1043E;DESERET SMALL LETTER JEE;Ll;0;L;;;;;N;;;10416;;10416
-1043F;DESERET SMALL LETTER KAY;Ll;0;L;;;;;N;;;10417;;10417
-10440;DESERET SMALL LETTER GAY;Ll;0;L;;;;;N;;;10418;;10418
-10441;DESERET SMALL LETTER EF;Ll;0;L;;;;;N;;;10419;;10419
-10442;DESERET SMALL LETTER VEE;Ll;0;L;;;;;N;;;1041A;;1041A
-10443;DESERET SMALL LETTER ETH;Ll;0;L;;;;;N;;;1041B;;1041B
-10444;DESERET SMALL LETTER THEE;Ll;0;L;;;;;N;;;1041C;;1041C
-10445;DESERET SMALL LETTER ES;Ll;0;L;;;;;N;;;1041D;;1041D
-10446;DESERET SMALL LETTER ZEE;Ll;0;L;;;;;N;;;1041E;;1041E
-10447;DESERET SMALL LETTER ESH;Ll;0;L;;;;;N;;;1041F;;1041F
-10448;DESERET SMALL LETTER ZHEE;Ll;0;L;;;;;N;;;10420;;10420
-10449;DESERET SMALL LETTER ER;Ll;0;L;;;;;N;;;10421;;10421
-1044A;DESERET SMALL LETTER EL;Ll;0;L;;;;;N;;;10422;;10422
-1044B;DESERET SMALL LETTER EM;Ll;0;L;;;;;N;;;10423;;10423
-1044C;DESERET SMALL LETTER EN;Ll;0;L;;;;;N;;;10424;;10424
-1044D;DESERET SMALL LETTER ENG;Ll;0;L;;;;;N;;;10425;;10425
-1044E;DESERET SMALL LETTER OI;Ll;0;L;;;;;N;;;10426;;10426
-1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427
-10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;;
-10451;SHAVIAN LETTER TOT;Lo;0;L;;;;;N;;;;;
-10452;SHAVIAN LETTER KICK;Lo;0;L;;;;;N;;;;;
-10453;SHAVIAN LETTER FEE;Lo;0;L;;;;;N;;;;;
-10454;SHAVIAN LETTER THIGH;Lo;0;L;;;;;N;;;;;
-10455;SHAVIAN LETTER SO;Lo;0;L;;;;;N;;;;;
-10456;SHAVIAN LETTER SURE;Lo;0;L;;;;;N;;;;;
-10457;SHAVIAN LETTER CHURCH;Lo;0;L;;;;;N;;;;;
-10458;SHAVIAN LETTER YEA;Lo;0;L;;;;;N;;;;;
-10459;SHAVIAN LETTER HUNG;Lo;0;L;;;;;N;;;;;
-1045A;SHAVIAN LETTER BIB;Lo;0;L;;;;;N;;;;;
-1045B;SHAVIAN LETTER DEAD;Lo;0;L;;;;;N;;;;;
-1045C;SHAVIAN LETTER GAG;Lo;0;L;;;;;N;;;;;
-1045D;SHAVIAN LETTER VOW;Lo;0;L;;;;;N;;;;;
-1045E;SHAVIAN LETTER THEY;Lo;0;L;;;;;N;;;;;
-1045F;SHAVIAN LETTER ZOO;Lo;0;L;;;;;N;;;;;
-10460;SHAVIAN LETTER MEASURE;Lo;0;L;;;;;N;;;;;
-10461;SHAVIAN LETTER JUDGE;Lo;0;L;;;;;N;;;;;
-10462;SHAVIAN LETTER WOE;Lo;0;L;;;;;N;;;;;
-10463;SHAVIAN LETTER HA-HA;Lo;0;L;;;;;N;;;;;
-10464;SHAVIAN LETTER LOLL;Lo;0;L;;;;;N;;;;;
-10465;SHAVIAN LETTER MIME;Lo;0;L;;;;;N;;;;;
-10466;SHAVIAN LETTER IF;Lo;0;L;;;;;N;;;;;
-10467;SHAVIAN LETTER EGG;Lo;0;L;;;;;N;;;;;
-10468;SHAVIAN LETTER ASH;Lo;0;L;;;;;N;;;;;
-10469;SHAVIAN LETTER ADO;Lo;0;L;;;;;N;;;;;
-1046A;SHAVIAN LETTER ON;Lo;0;L;;;;;N;;;;;
-1046B;SHAVIAN LETTER WOOL;Lo;0;L;;;;;N;;;;;
-1046C;SHAVIAN LETTER OUT;Lo;0;L;;;;;N;;;;;
-1046D;SHAVIAN LETTER AH;Lo;0;L;;;;;N;;;;;
-1046E;SHAVIAN LETTER ROAR;Lo;0;L;;;;;N;;;;;
-1046F;SHAVIAN LETTER NUN;Lo;0;L;;;;;N;;;;;
-10470;SHAVIAN LETTER EAT;Lo;0;L;;;;;N;;;;;
-10471;SHAVIAN LETTER AGE;Lo;0;L;;;;;N;;;;;
-10472;SHAVIAN LETTER ICE;Lo;0;L;;;;;N;;;;;
-10473;SHAVIAN LETTER UP;Lo;0;L;;;;;N;;;;;
-10474;SHAVIAN LETTER OAK;Lo;0;L;;;;;N;;;;;
-10475;SHAVIAN LETTER OOZE;Lo;0;L;;;;;N;;;;;
-10476;SHAVIAN LETTER OIL;Lo;0;L;;;;;N;;;;;
-10477;SHAVIAN LETTER AWE;Lo;0;L;;;;;N;;;;;
-10478;SHAVIAN LETTER ARE;Lo;0;L;;;;;N;;;;;
-10479;SHAVIAN LETTER OR;Lo;0;L;;;;;N;;;;;
-1047A;SHAVIAN LETTER AIR;Lo;0;L;;;;;N;;;;;
-1047B;SHAVIAN LETTER ERR;Lo;0;L;;;;;N;;;;;
-1047C;SHAVIAN LETTER ARRAY;Lo;0;L;;;;;N;;;;;
-1047D;SHAVIAN LETTER EAR;Lo;0;L;;;;;N;;;;;
-1047E;SHAVIAN LETTER IAN;Lo;0;L;;;;;N;;;;;
-1047F;SHAVIAN LETTER YEW;Lo;0;L;;;;;N;;;;;
-10480;OSMANYA LETTER ALEF;Lo;0;L;;;;;N;;;;;
-10481;OSMANYA LETTER BA;Lo;0;L;;;;;N;;;;;
-10482;OSMANYA LETTER TA;Lo;0;L;;;;;N;;;;;
-10483;OSMANYA LETTER JA;Lo;0;L;;;;;N;;;;;
-10484;OSMANYA LETTER XA;Lo;0;L;;;;;N;;;;;
-10485;OSMANYA LETTER KHA;Lo;0;L;;;;;N;;;;;
-10486;OSMANYA LETTER DEEL;Lo;0;L;;;;;N;;;;;
-10487;OSMANYA LETTER RA;Lo;0;L;;;;;N;;;;;
-10488;OSMANYA LETTER SA;Lo;0;L;;;;;N;;;;;
-10489;OSMANYA LETTER SHIIN;Lo;0;L;;;;;N;;;;;
-1048A;OSMANYA LETTER DHA;Lo;0;L;;;;;N;;;;;
-1048B;OSMANYA LETTER CAYN;Lo;0;L;;;;;N;;;;;
-1048C;OSMANYA LETTER GA;Lo;0;L;;;;;N;;;;;
-1048D;OSMANYA LETTER FA;Lo;0;L;;;;;N;;;;;
-1048E;OSMANYA LETTER QAAF;Lo;0;L;;;;;N;;;;;
-1048F;OSMANYA LETTER KAAF;Lo;0;L;;;;;N;;;;;
-10490;OSMANYA LETTER LAAN;Lo;0;L;;;;;N;;;;;
-10491;OSMANYA LETTER MIIN;Lo;0;L;;;;;N;;;;;
-10492;OSMANYA LETTER NUUN;Lo;0;L;;;;;N;;;;;
-10493;OSMANYA LETTER WAW;Lo;0;L;;;;;N;;;;;
-10494;OSMANYA LETTER HA;Lo;0;L;;;;;N;;;;;
-10495;OSMANYA LETTER YA;Lo;0;L;;;;;N;;;;;
-10496;OSMANYA LETTER A;Lo;0;L;;;;;N;;;;;
-10497;OSMANYA LETTER E;Lo;0;L;;;;;N;;;;;
-10498;OSMANYA LETTER I;Lo;0;L;;;;;N;;;;;
-10499;OSMANYA LETTER O;Lo;0;L;;;;;N;;;;;
-1049A;OSMANYA LETTER U;Lo;0;L;;;;;N;;;;;
-1049B;OSMANYA LETTER AA;Lo;0;L;;;;;N;;;;;
-1049C;OSMANYA LETTER EE;Lo;0;L;;;;;N;;;;;
-1049D;OSMANYA LETTER OO;Lo;0;L;;;;;N;;;;;
-104A0;OSMANYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-104A1;OSMANYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-104A2;OSMANYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-104A3;OSMANYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-104A4;OSMANYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-104A5;OSMANYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-104A6;OSMANYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-104A7;OSMANYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-104A8;OSMANYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-104A9;OSMANYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;;
-10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;;
-10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;;
-10803;CYPRIOT SYLLABLE O;Lo;0;R;;;;;N;;;;;
-10804;CYPRIOT SYLLABLE U;Lo;0;R;;;;;N;;;;;
-10805;CYPRIOT SYLLABLE JA;Lo;0;R;;;;;N;;;;;
-10808;CYPRIOT SYLLABLE JO;Lo;0;R;;;;;N;;;;;
-1080A;CYPRIOT SYLLABLE KA;Lo;0;R;;;;;N;;;;;
-1080B;CYPRIOT SYLLABLE KE;Lo;0;R;;;;;N;;;;;
-1080C;CYPRIOT SYLLABLE KI;Lo;0;R;;;;;N;;;;;
-1080D;CYPRIOT SYLLABLE KO;Lo;0;R;;;;;N;;;;;
-1080E;CYPRIOT SYLLABLE KU;Lo;0;R;;;;;N;;;;;
-1080F;CYPRIOT SYLLABLE LA;Lo;0;R;;;;;N;;;;;
-10810;CYPRIOT SYLLABLE LE;Lo;0;R;;;;;N;;;;;
-10811;CYPRIOT SYLLABLE LI;Lo;0;R;;;;;N;;;;;
-10812;CYPRIOT SYLLABLE LO;Lo;0;R;;;;;N;;;;;
-10813;CYPRIOT SYLLABLE LU;Lo;0;R;;;;;N;;;;;
-10814;CYPRIOT SYLLABLE MA;Lo;0;R;;;;;N;;;;;
-10815;CYPRIOT SYLLABLE ME;Lo;0;R;;;;;N;;;;;
-10816;CYPRIOT SYLLABLE MI;Lo;0;R;;;;;N;;;;;
-10817;CYPRIOT SYLLABLE MO;Lo;0;R;;;;;N;;;;;
-10818;CYPRIOT SYLLABLE MU;Lo;0;R;;;;;N;;;;;
-10819;CYPRIOT SYLLABLE NA;Lo;0;R;;;;;N;;;;;
-1081A;CYPRIOT SYLLABLE NE;Lo;0;R;;;;;N;;;;;
-1081B;CYPRIOT SYLLABLE NI;Lo;0;R;;;;;N;;;;;
-1081C;CYPRIOT SYLLABLE NO;Lo;0;R;;;;;N;;;;;
-1081D;CYPRIOT SYLLABLE NU;Lo;0;R;;;;;N;;;;;
-1081E;CYPRIOT SYLLABLE PA;Lo;0;R;;;;;N;;;;;
-1081F;CYPRIOT SYLLABLE PE;Lo;0;R;;;;;N;;;;;
-10820;CYPRIOT SYLLABLE PI;Lo;0;R;;;;;N;;;;;
-10821;CYPRIOT SYLLABLE PO;Lo;0;R;;;;;N;;;;;
-10822;CYPRIOT SYLLABLE PU;Lo;0;R;;;;;N;;;;;
-10823;CYPRIOT SYLLABLE RA;Lo;0;R;;;;;N;;;;;
-10824;CYPRIOT SYLLABLE RE;Lo;0;R;;;;;N;;;;;
-10825;CYPRIOT SYLLABLE RI;Lo;0;R;;;;;N;;;;;
-10826;CYPRIOT SYLLABLE RO;Lo;0;R;;;;;N;;;;;
-10827;CYPRIOT SYLLABLE RU;Lo;0;R;;;;;N;;;;;
-10828;CYPRIOT SYLLABLE SA;Lo;0;R;;;;;N;;;;;
-10829;CYPRIOT SYLLABLE SE;Lo;0;R;;;;;N;;;;;
-1082A;CYPRIOT SYLLABLE SI;Lo;0;R;;;;;N;;;;;
-1082B;CYPRIOT SYLLABLE SO;Lo;0;R;;;;;N;;;;;
-1082C;CYPRIOT SYLLABLE SU;Lo;0;R;;;;;N;;;;;
-1082D;CYPRIOT SYLLABLE TA;Lo;0;R;;;;;N;;;;;
-1082E;CYPRIOT SYLLABLE TE;Lo;0;R;;;;;N;;;;;
-1082F;CYPRIOT SYLLABLE TI;Lo;0;R;;;;;N;;;;;
-10830;CYPRIOT SYLLABLE TO;Lo;0;R;;;;;N;;;;;
-10831;CYPRIOT SYLLABLE TU;Lo;0;R;;;;;N;;;;;
-10832;CYPRIOT SYLLABLE WA;Lo;0;R;;;;;N;;;;;
-10833;CYPRIOT SYLLABLE WE;Lo;0;R;;;;;N;;;;;
-10834;CYPRIOT SYLLABLE WI;Lo;0;R;;;;;N;;;;;
-10835;CYPRIOT SYLLABLE WO;Lo;0;R;;;;;N;;;;;
-10837;CYPRIOT SYLLABLE XA;Lo;0;R;;;;;N;;;;;
-10838;CYPRIOT SYLLABLE XE;Lo;0;R;;;;;N;;;;;
-1083C;CYPRIOT SYLLABLE ZA;Lo;0;R;;;;;N;;;;;
-1083F;CYPRIOT SYLLABLE ZO;Lo;0;R;;;;;N;;;;;
-10840;IMPERIAL ARAMAIC LETTER ALEPH;Lo;0;R;;;;;N;;;;;
-10841;IMPERIAL ARAMAIC LETTER BETH;Lo;0;R;;;;;N;;;;;
-10842;IMPERIAL ARAMAIC LETTER GIMEL;Lo;0;R;;;;;N;;;;;
-10843;IMPERIAL ARAMAIC LETTER DALETH;Lo;0;R;;;;;N;;;;;
-10844;IMPERIAL ARAMAIC LETTER HE;Lo;0;R;;;;;N;;;;;
-10845;IMPERIAL ARAMAIC LETTER WAW;Lo;0;R;;;;;N;;;;;
-10846;IMPERIAL ARAMAIC LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
-10847;IMPERIAL ARAMAIC LETTER HETH;Lo;0;R;;;;;N;;;;;
-10848;IMPERIAL ARAMAIC LETTER TETH;Lo;0;R;;;;;N;;;;;
-10849;IMPERIAL ARAMAIC LETTER YODH;Lo;0;R;;;;;N;;;;;
-1084A;IMPERIAL ARAMAIC LETTER KAPH;Lo;0;R;;;;;N;;;;;
-1084B;IMPERIAL ARAMAIC LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
-1084C;IMPERIAL ARAMAIC LETTER MEM;Lo;0;R;;;;;N;;;;;
-1084D;IMPERIAL ARAMAIC LETTER NUN;Lo;0;R;;;;;N;;;;;
-1084E;IMPERIAL ARAMAIC LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
-1084F;IMPERIAL ARAMAIC LETTER AYIN;Lo;0;R;;;;;N;;;;;
-10850;IMPERIAL ARAMAIC LETTER PE;Lo;0;R;;;;;N;;;;;
-10851;IMPERIAL ARAMAIC LETTER SADHE;Lo;0;R;;;;;N;;;;;
-10852;IMPERIAL ARAMAIC LETTER QOPH;Lo;0;R;;;;;N;;;;;
-10853;IMPERIAL ARAMAIC LETTER RESH;Lo;0;R;;;;;N;;;;;
-10854;IMPERIAL ARAMAIC LETTER SHIN;Lo;0;R;;;;;N;;;;;
-10855;IMPERIAL ARAMAIC LETTER TAW;Lo;0;R;;;;;N;;;;;
-10857;IMPERIAL ARAMAIC SECTION SIGN;Po;0;R;;;;;N;;;;;
-10858;IMPERIAL ARAMAIC NUMBER ONE;No;0;R;;;;1;N;;;;;
-10859;IMPERIAL ARAMAIC NUMBER TWO;No;0;R;;;;2;N;;;;;
-1085A;IMPERIAL ARAMAIC NUMBER THREE;No;0;R;;;;3;N;;;;;
-1085B;IMPERIAL ARAMAIC NUMBER TEN;No;0;R;;;;10;N;;;;;
-1085C;IMPERIAL ARAMAIC NUMBER TWENTY;No;0;R;;;;20;N;;;;;
-1085D;IMPERIAL ARAMAIC NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
-1085E;IMPERIAL ARAMAIC NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
-1085F;IMPERIAL ARAMAIC NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;;
-10900;PHOENICIAN LETTER ALF;Lo;0;R;;;;;N;;;;;
-10901;PHOENICIAN LETTER BET;Lo;0;R;;;;;N;;;;;
-10902;PHOENICIAN LETTER GAML;Lo;0;R;;;;;N;;;;;
-10903;PHOENICIAN LETTER DELT;Lo;0;R;;;;;N;;;;;
-10904;PHOENICIAN LETTER HE;Lo;0;R;;;;;N;;;;;
-10905;PHOENICIAN LETTER WAU;Lo;0;R;;;;;N;;;;;
-10906;PHOENICIAN LETTER ZAI;Lo;0;R;;;;;N;;;;;
-10907;PHOENICIAN LETTER HET;Lo;0;R;;;;;N;;;;;
-10908;PHOENICIAN LETTER TET;Lo;0;R;;;;;N;;;;;
-10909;PHOENICIAN LETTER YOD;Lo;0;R;;;;;N;;;;;
-1090A;PHOENICIAN LETTER KAF;Lo;0;R;;;;;N;;;;;
-1090B;PHOENICIAN LETTER LAMD;Lo;0;R;;;;;N;;;;;
-1090C;PHOENICIAN LETTER MEM;Lo;0;R;;;;;N;;;;;
-1090D;PHOENICIAN LETTER NUN;Lo;0;R;;;;;N;;;;;
-1090E;PHOENICIAN LETTER SEMK;Lo;0;R;;;;;N;;;;;
-1090F;PHOENICIAN LETTER AIN;Lo;0;R;;;;;N;;;;;
-10910;PHOENICIAN LETTER PE;Lo;0;R;;;;;N;;;;;
-10911;PHOENICIAN LETTER SADE;Lo;0;R;;;;;N;;;;;
-10912;PHOENICIAN LETTER QOF;Lo;0;R;;;;;N;;;;;
-10913;PHOENICIAN LETTER ROSH;Lo;0;R;;;;;N;;;;;
-10914;PHOENICIAN LETTER SHIN;Lo;0;R;;;;;N;;;;;
-10915;PHOENICIAN LETTER TAU;Lo;0;R;;;;;N;;;;;
-10916;PHOENICIAN NUMBER ONE;No;0;R;;;;1;N;;;;;
-10917;PHOENICIAN NUMBER TEN;No;0;R;;;;10;N;;;;;
-10918;PHOENICIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;;
-10919;PHOENICIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
-1091A;PHOENICIAN NUMBER TWO;No;0;R;;;;2;N;;;;;
-1091B;PHOENICIAN NUMBER THREE;No;0;R;;;;3;N;;;;;
-1091F;PHOENICIAN WORD SEPARATOR;Po;0;ON;;;;;N;;;;;
-10920;LYDIAN LETTER A;Lo;0;R;;;;;N;;;;;
-10921;LYDIAN LETTER B;Lo;0;R;;;;;N;;;;;
-10922;LYDIAN LETTER G;Lo;0;R;;;;;N;;;;;
-10923;LYDIAN LETTER D;Lo;0;R;;;;;N;;;;;
-10924;LYDIAN LETTER E;Lo;0;R;;;;;N;;;;;
-10925;LYDIAN LETTER V;Lo;0;R;;;;;N;;;;;
-10926;LYDIAN LETTER I;Lo;0;R;;;;;N;;;;;
-10927;LYDIAN LETTER Y;Lo;0;R;;;;;N;;;;;
-10928;LYDIAN LETTER K;Lo;0;R;;;;;N;;;;;
-10929;LYDIAN LETTER L;Lo;0;R;;;;;N;;;;;
-1092A;LYDIAN LETTER M;Lo;0;R;;;;;N;;;;;
-1092B;LYDIAN LETTER N;Lo;0;R;;;;;N;;;;;
-1092C;LYDIAN LETTER O;Lo;0;R;;;;;N;;;;;
-1092D;LYDIAN LETTER R;Lo;0;R;;;;;N;;;;;
-1092E;LYDIAN LETTER SS;Lo;0;R;;;;;N;;;;;
-1092F;LYDIAN LETTER T;Lo;0;R;;;;;N;;;;;
-10930;LYDIAN LETTER U;Lo;0;R;;;;;N;;;;;
-10931;LYDIAN LETTER F;Lo;0;R;;;;;N;;;;;
-10932;LYDIAN LETTER Q;Lo;0;R;;;;;N;;;;;
-10933;LYDIAN LETTER S;Lo;0;R;;;;;N;;;;;
-10934;LYDIAN LETTER TT;Lo;0;R;;;;;N;;;;;
-10935;LYDIAN LETTER AN;Lo;0;R;;;;;N;;;;;
-10936;LYDIAN LETTER EN;Lo;0;R;;;;;N;;;;;
-10937;LYDIAN LETTER LY;Lo;0;R;;;;;N;;;;;
-10938;LYDIAN LETTER NN;Lo;0;R;;;;;N;;;;;
-10939;LYDIAN LETTER C;Lo;0;R;;;;;N;;;;;
-1093F;LYDIAN TRIANGULAR MARK;Po;0;R;;;;;N;;;;;
-10980;MEROITIC HIEROGLYPHIC LETTER A;Lo;0;R;;;;;N;;;;;
-10981;MEROITIC HIEROGLYPHIC LETTER E;Lo;0;R;;;;;N;;;;;
-10982;MEROITIC HIEROGLYPHIC LETTER I;Lo;0;R;;;;;N;;;;;
-10983;MEROITIC HIEROGLYPHIC LETTER O;Lo;0;R;;;;;N;;;;;
-10984;MEROITIC HIEROGLYPHIC LETTER YA;Lo;0;R;;;;;N;;;;;
-10985;MEROITIC HIEROGLYPHIC LETTER WA;Lo;0;R;;;;;N;;;;;
-10986;MEROITIC HIEROGLYPHIC LETTER BA;Lo;0;R;;;;;N;;;;;
-10987;MEROITIC HIEROGLYPHIC LETTER BA-2;Lo;0;R;;;;;N;;;;;
-10988;MEROITIC HIEROGLYPHIC LETTER PA;Lo;0;R;;;;;N;;;;;
-10989;MEROITIC HIEROGLYPHIC LETTER MA;Lo;0;R;;;;;N;;;;;
-1098A;MEROITIC HIEROGLYPHIC LETTER NA;Lo;0;R;;;;;N;;;;;
-1098B;MEROITIC HIEROGLYPHIC LETTER NA-2;Lo;0;R;;;;;N;;;;;
-1098C;MEROITIC HIEROGLYPHIC LETTER NE;Lo;0;R;;;;;N;;;;;
-1098D;MEROITIC HIEROGLYPHIC LETTER NE-2;Lo;0;R;;;;;N;;;;;
-1098E;MEROITIC HIEROGLYPHIC LETTER RA;Lo;0;R;;;;;N;;;;;
-1098F;MEROITIC HIEROGLYPHIC LETTER RA-2;Lo;0;R;;;;;N;;;;;
-10990;MEROITIC HIEROGLYPHIC LETTER LA;Lo;0;R;;;;;N;;;;;
-10991;MEROITIC HIEROGLYPHIC LETTER KHA;Lo;0;R;;;;;N;;;;;
-10992;MEROITIC HIEROGLYPHIC LETTER HHA;Lo;0;R;;;;;N;;;;;
-10993;MEROITIC HIEROGLYPHIC LETTER SA;Lo;0;R;;;;;N;;;;;
-10994;MEROITIC HIEROGLYPHIC LETTER SA-2;Lo;0;R;;;;;N;;;;;
-10995;MEROITIC HIEROGLYPHIC LETTER SE;Lo;0;R;;;;;N;;;;;
-10996;MEROITIC HIEROGLYPHIC LETTER KA;Lo;0;R;;;;;N;;;;;
-10997;MEROITIC HIEROGLYPHIC LETTER QA;Lo;0;R;;;;;N;;;;;
-10998;MEROITIC HIEROGLYPHIC LETTER TA;Lo;0;R;;;;;N;;;;;
-10999;MEROITIC HIEROGLYPHIC LETTER TA-2;Lo;0;R;;;;;N;;;;;
-1099A;MEROITIC HIEROGLYPHIC LETTER TE;Lo;0;R;;;;;N;;;;;
-1099B;MEROITIC HIEROGLYPHIC LETTER TE-2;Lo;0;R;;;;;N;;;;;
-1099C;MEROITIC HIEROGLYPHIC LETTER TO;Lo;0;R;;;;;N;;;;;
-1099D;MEROITIC HIEROGLYPHIC LETTER DA;Lo;0;R;;;;;N;;;;;
-1099E;MEROITIC HIEROGLYPHIC SYMBOL VIDJ;Lo;0;R;;;;;N;;;;;
-1099F;MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2;Lo;0;R;;;;;N;;;;;
-109A0;MEROITIC CURSIVE LETTER A;Lo;0;R;;;;;N;;;;;
-109A1;MEROITIC CURSIVE LETTER E;Lo;0;R;;;;;N;;;;;
-109A2;MEROITIC CURSIVE LETTER I;Lo;0;R;;;;;N;;;;;
-109A3;MEROITIC CURSIVE LETTER O;Lo;0;R;;;;;N;;;;;
-109A4;MEROITIC CURSIVE LETTER YA;Lo;0;R;;;;;N;;;;;
-109A5;MEROITIC CURSIVE LETTER WA;Lo;0;R;;;;;N;;;;;
-109A6;MEROITIC CURSIVE LETTER BA;Lo;0;R;;;;;N;;;;;
-109A7;MEROITIC CURSIVE LETTER PA;Lo;0;R;;;;;N;;;;;
-109A8;MEROITIC CURSIVE LETTER MA;Lo;0;R;;;;;N;;;;;
-109A9;MEROITIC CURSIVE LETTER NA;Lo;0;R;;;;;N;;;;;
-109AA;MEROITIC CURSIVE LETTER NE;Lo;0;R;;;;;N;;;;;
-109AB;MEROITIC CURSIVE LETTER RA;Lo;0;R;;;;;N;;;;;
-109AC;MEROITIC CURSIVE LETTER LA;Lo;0;R;;;;;N;;;;;
-109AD;MEROITIC CURSIVE LETTER KHA;Lo;0;R;;;;;N;;;;;
-109AE;MEROITIC CURSIVE LETTER HHA;Lo;0;R;;;;;N;;;;;
-109AF;MEROITIC CURSIVE LETTER SA;Lo;0;R;;;;;N;;;;;
-109B0;MEROITIC CURSIVE LETTER ARCHAIC SA;Lo;0;R;;;;;N;;;;;
-109B1;MEROITIC CURSIVE LETTER SE;Lo;0;R;;;;;N;;;;;
-109B2;MEROITIC CURSIVE LETTER KA;Lo;0;R;;;;;N;;;;;
-109B3;MEROITIC CURSIVE LETTER QA;Lo;0;R;;;;;N;;;;;
-109B4;MEROITIC CURSIVE LETTER TA;Lo;0;R;;;;;N;;;;;
-109B5;MEROITIC CURSIVE LETTER TE;Lo;0;R;;;;;N;;;;;
-109B6;MEROITIC CURSIVE LETTER TO;Lo;0;R;;;;;N;;;;;
-109B7;MEROITIC CURSIVE LETTER DA;Lo;0;R;;;;;N;;;;;
-109BE;MEROITIC CURSIVE LOGOGRAM RMT;Lo;0;R;;;;;N;;;;;
-109BF;MEROITIC CURSIVE LOGOGRAM IMN;Lo;0;R;;;;;N;;;;;
-10A00;KHAROSHTHI LETTER A;Lo;0;R;;;;;N;;;;;
-10A01;KHAROSHTHI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-10A02;KHAROSHTHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-10A03;KHAROSHTHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
-10A05;KHAROSHTHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-10A06;KHAROSHTHI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
-10A0C;KHAROSHTHI VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;;
-10A0D;KHAROSHTHI SIGN DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;;
-10A0E;KHAROSHTHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-10A0F;KHAROSHTHI SIGN VISARGA;Mn;230;NSM;;;;;N;;;;;
-10A10;KHAROSHTHI LETTER KA;Lo;0;R;;;;;N;;;;;
-10A11;KHAROSHTHI LETTER KHA;Lo;0;R;;;;;N;;;;;
-10A12;KHAROSHTHI LETTER GA;Lo;0;R;;;;;N;;;;;
-10A13;KHAROSHTHI LETTER GHA;Lo;0;R;;;;;N;;;;;
-10A15;KHAROSHTHI LETTER CA;Lo;0;R;;;;;N;;;;;
-10A16;KHAROSHTHI LETTER CHA;Lo;0;R;;;;;N;;;;;
-10A17;KHAROSHTHI LETTER JA;Lo;0;R;;;;;N;;;;;
-10A19;KHAROSHTHI LETTER NYA;Lo;0;R;;;;;N;;;;;
-10A1A;KHAROSHTHI LETTER TTA;Lo;0;R;;;;;N;;;;;
-10A1B;KHAROSHTHI LETTER TTHA;Lo;0;R;;;;;N;;;;;
-10A1C;KHAROSHTHI LETTER DDA;Lo;0;R;;;;;N;;;;;
-10A1D;KHAROSHTHI LETTER DDHA;Lo;0;R;;;;;N;;;;;
-10A1E;KHAROSHTHI LETTER NNA;Lo;0;R;;;;;N;;;;;
-10A1F;KHAROSHTHI LETTER TA;Lo;0;R;;;;;N;;;;;
-10A20;KHAROSHTHI LETTER THA;Lo;0;R;;;;;N;;;;;
-10A21;KHAROSHTHI LETTER DA;Lo;0;R;;;;;N;;;;;
-10A22;KHAROSHTHI LETTER DHA;Lo;0;R;;;;;N;;;;;
-10A23;KHAROSHTHI LETTER NA;Lo;0;R;;;;;N;;;;;
-10A24;KHAROSHTHI LETTER PA;Lo;0;R;;;;;N;;;;;
-10A25;KHAROSHTHI LETTER PHA;Lo;0;R;;;;;N;;;;;
-10A26;KHAROSHTHI LETTER BA;Lo;0;R;;;;;N;;;;;
-10A27;KHAROSHTHI LETTER BHA;Lo;0;R;;;;;N;;;;;
-10A28;KHAROSHTHI LETTER MA;Lo;0;R;;;;;N;;;;;
-10A29;KHAROSHTHI LETTER YA;Lo;0;R;;;;;N;;;;;
-10A2A;KHAROSHTHI LETTER RA;Lo;0;R;;;;;N;;;;;
-10A2B;KHAROSHTHI LETTER LA;Lo;0;R;;;;;N;;;;;
-10A2C;KHAROSHTHI LETTER VA;Lo;0;R;;;;;N;;;;;
-10A2D;KHAROSHTHI LETTER SHA;Lo;0;R;;;;;N;;;;;
-10A2E;KHAROSHTHI LETTER SSA;Lo;0;R;;;;;N;;;;;
-10A2F;KHAROSHTHI LETTER SA;Lo;0;R;;;;;N;;;;;
-10A30;KHAROSHTHI LETTER ZA;Lo;0;R;;;;;N;;;;;
-10A31;KHAROSHTHI LETTER HA;Lo;0;R;;;;;N;;;;;
-10A32;KHAROSHTHI LETTER KKA;Lo;0;R;;;;;N;;;;;
-10A33;KHAROSHTHI LETTER TTTHA;Lo;0;R;;;;;N;;;;;
-10A38;KHAROSHTHI SIGN BAR ABOVE;Mn;230;NSM;;;;;N;;;;;
-10A39;KHAROSHTHI SIGN CAUDA;Mn;1;NSM;;;;;N;;;;;
-10A3A;KHAROSHTHI SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;;
-10A3F;KHAROSHTHI VIRAMA;Mn;9;NSM;;;;;N;;;;;
-10A40;KHAROSHTHI DIGIT ONE;No;0;R;;;1;1;N;;;;;
-10A41;KHAROSHTHI DIGIT TWO;No;0;R;;;2;2;N;;;;;
-10A42;KHAROSHTHI DIGIT THREE;No;0;R;;;3;3;N;;;;;
-10A43;KHAROSHTHI DIGIT FOUR;No;0;R;;;4;4;N;;;;;
-10A44;KHAROSHTHI NUMBER TEN;No;0;R;;;;10;N;;;;;
-10A45;KHAROSHTHI NUMBER TWENTY;No;0;R;;;;20;N;;;;;
-10A46;KHAROSHTHI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
-10A47;KHAROSHTHI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
-10A50;KHAROSHTHI PUNCTUATION DOT;Po;0;R;;;;;N;;;;;
-10A51;KHAROSHTHI PUNCTUATION SMALL CIRCLE;Po;0;R;;;;;N;;;;;
-10A52;KHAROSHTHI PUNCTUATION CIRCLE;Po;0;R;;;;;N;;;;;
-10A53;KHAROSHTHI PUNCTUATION CRESCENT BAR;Po;0;R;;;;;N;;;;;
-10A54;KHAROSHTHI PUNCTUATION MANGALAM;Po;0;R;;;;;N;;;;;
-10A55;KHAROSHTHI PUNCTUATION LOTUS;Po;0;R;;;;;N;;;;;
-10A56;KHAROSHTHI PUNCTUATION DANDA;Po;0;R;;;;;N;;;;;
-10A57;KHAROSHTHI PUNCTUATION DOUBLE DANDA;Po;0;R;;;;;N;;;;;
-10A58;KHAROSHTHI PUNCTUATION LINES;Po;0;R;;;;;N;;;;;
-10A60;OLD SOUTH ARABIAN LETTER HE;Lo;0;R;;;;;N;;;;;
-10A61;OLD SOUTH ARABIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
-10A62;OLD SOUTH ARABIAN LETTER HETH;Lo;0;R;;;;;N;;;;;
-10A63;OLD SOUTH ARABIAN LETTER MEM;Lo;0;R;;;;;N;;;;;
-10A64;OLD SOUTH ARABIAN LETTER QOPH;Lo;0;R;;;;;N;;;;;
-10A65;OLD SOUTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;;
-10A66;OLD SOUTH ARABIAN LETTER SHIN;Lo;0;R;;;;;N;;;;;
-10A67;OLD SOUTH ARABIAN LETTER RESH;Lo;0;R;;;;;N;;;;;
-10A68;OLD SOUTH ARABIAN LETTER BETH;Lo;0;R;;;;;N;;;;;
-10A69;OLD SOUTH ARABIAN LETTER TAW;Lo;0;R;;;;;N;;;;;
-10A6A;OLD SOUTH ARABIAN LETTER SAT;Lo;0;R;;;;;N;;;;;
-10A6B;OLD SOUTH ARABIAN LETTER KAPH;Lo;0;R;;;;;N;;;;;
-10A6C;OLD SOUTH ARABIAN LETTER NUN;Lo;0;R;;;;;N;;;;;
-10A6D;OLD SOUTH ARABIAN LETTER KHETH;Lo;0;R;;;;;N;;;;;
-10A6E;OLD SOUTH ARABIAN LETTER SADHE;Lo;0;R;;;;;N;;;;;
-10A6F;OLD SOUTH ARABIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
-10A70;OLD SOUTH ARABIAN LETTER FE;Lo;0;R;;;;;N;;;;;
-10A71;OLD SOUTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;;
-10A72;OLD SOUTH ARABIAN LETTER AYN;Lo;0;R;;;;;N;;;;;
-10A73;OLD SOUTH ARABIAN LETTER DHADHE;Lo;0;R;;;;;N;;;;;
-10A74;OLD SOUTH ARABIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;;
-10A75;OLD SOUTH ARABIAN LETTER DALETH;Lo;0;R;;;;;N;;;;;
-10A76;OLD SOUTH ARABIAN LETTER GHAYN;Lo;0;R;;;;;N;;;;;
-10A77;OLD SOUTH ARABIAN LETTER TETH;Lo;0;R;;;;;N;;;;;
-10A78;OLD SOUTH ARABIAN LETTER ZAYN;Lo;0;R;;;;;N;;;;;
-10A79;OLD SOUTH ARABIAN LETTER DHALETH;Lo;0;R;;;;;N;;;;;
-10A7A;OLD SOUTH ARABIAN LETTER YODH;Lo;0;R;;;;;N;;;;;
-10A7B;OLD SOUTH ARABIAN LETTER THAW;Lo;0;R;;;;;N;;;;;
-10A7C;OLD SOUTH ARABIAN LETTER THETH;Lo;0;R;;;;;N;;;;;
-10A7D;OLD SOUTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;;
-10A7E;OLD SOUTH ARABIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;;
-10A7F;OLD SOUTH ARABIAN NUMERIC INDICATOR;Po;0;R;;;;;N;;;;;
-10B00;AVESTAN LETTER A;Lo;0;R;;;;;N;;;;;
-10B01;AVESTAN LETTER AA;Lo;0;R;;;;;N;;;;;
-10B02;AVESTAN LETTER AO;Lo;0;R;;;;;N;;;;;
-10B03;AVESTAN LETTER AAO;Lo;0;R;;;;;N;;;;;
-10B04;AVESTAN LETTER AN;Lo;0;R;;;;;N;;;;;
-10B05;AVESTAN LETTER AAN;Lo;0;R;;;;;N;;;;;
-10B06;AVESTAN LETTER AE;Lo;0;R;;;;;N;;;;;
-10B07;AVESTAN LETTER AEE;Lo;0;R;;;;;N;;;;;
-10B08;AVESTAN LETTER E;Lo;0;R;;;;;N;;;;;
-10B09;AVESTAN LETTER EE;Lo;0;R;;;;;N;;;;;
-10B0A;AVESTAN LETTER O;Lo;0;R;;;;;N;;;;;
-10B0B;AVESTAN LETTER OO;Lo;0;R;;;;;N;;;;;
-10B0C;AVESTAN LETTER I;Lo;0;R;;;;;N;;;;;
-10B0D;AVESTAN LETTER II;Lo;0;R;;;;;N;;;;;
-10B0E;AVESTAN LETTER U;Lo;0;R;;;;;N;;;;;
-10B0F;AVESTAN LETTER UU;Lo;0;R;;;;;N;;;;;
-10B10;AVESTAN LETTER KE;Lo;0;R;;;;;N;;;;;
-10B11;AVESTAN LETTER XE;Lo;0;R;;;;;N;;;;;
-10B12;AVESTAN LETTER XYE;Lo;0;R;;;;;N;;;;;
-10B13;AVESTAN LETTER XVE;Lo;0;R;;;;;N;;;;;
-10B14;AVESTAN LETTER GE;Lo;0;R;;;;;N;;;;;
-10B15;AVESTAN LETTER GGE;Lo;0;R;;;;;N;;;;;
-10B16;AVESTAN LETTER GHE;Lo;0;R;;;;;N;;;;;
-10B17;AVESTAN LETTER CE;Lo;0;R;;;;;N;;;;;
-10B18;AVESTAN LETTER JE;Lo;0;R;;;;;N;;;;;
-10B19;AVESTAN LETTER TE;Lo;0;R;;;;;N;;;;;
-10B1A;AVESTAN LETTER THE;Lo;0;R;;;;;N;;;;;
-10B1B;AVESTAN LETTER DE;Lo;0;R;;;;;N;;;;;
-10B1C;AVESTAN LETTER DHE;Lo;0;R;;;;;N;;;;;
-10B1D;AVESTAN LETTER TTE;Lo;0;R;;;;;N;;;;;
-10B1E;AVESTAN LETTER PE;Lo;0;R;;;;;N;;;;;
-10B1F;AVESTAN LETTER FE;Lo;0;R;;;;;N;;;;;
-10B20;AVESTAN LETTER BE;Lo;0;R;;;;;N;;;;;
-10B21;AVESTAN LETTER BHE;Lo;0;R;;;;;N;;;;;
-10B22;AVESTAN LETTER NGE;Lo;0;R;;;;;N;;;;;
-10B23;AVESTAN LETTER NGYE;Lo;0;R;;;;;N;;;;;
-10B24;AVESTAN LETTER NGVE;Lo;0;R;;;;;N;;;;;
-10B25;AVESTAN LETTER NE;Lo;0;R;;;;;N;;;;;
-10B26;AVESTAN LETTER NYE;Lo;0;R;;;;;N;;;;;
-10B27;AVESTAN LETTER NNE;Lo;0;R;;;;;N;;;;;
-10B28;AVESTAN LETTER ME;Lo;0;R;;;;;N;;;;;
-10B29;AVESTAN LETTER HME;Lo;0;R;;;;;N;;;;;
-10B2A;AVESTAN LETTER YYE;Lo;0;R;;;;;N;;;;;
-10B2B;AVESTAN LETTER YE;Lo;0;R;;;;;N;;;;;
-10B2C;AVESTAN LETTER VE;Lo;0;R;;;;;N;;;;;
-10B2D;AVESTAN LETTER RE;Lo;0;R;;;;;N;;;;;
-10B2E;AVESTAN LETTER LE;Lo;0;R;;;;;N;;;;;
-10B2F;AVESTAN LETTER SE;Lo;0;R;;;;;N;;;;;
-10B30;AVESTAN LETTER ZE;Lo;0;R;;;;;N;;;;;
-10B31;AVESTAN LETTER SHE;Lo;0;R;;;;;N;;;;;
-10B32;AVESTAN LETTER ZHE;Lo;0;R;;;;;N;;;;;
-10B33;AVESTAN LETTER SHYE;Lo;0;R;;;;;N;;;;;
-10B34;AVESTAN LETTER SSHE;Lo;0;R;;;;;N;;;;;
-10B35;AVESTAN LETTER HE;Lo;0;R;;;;;N;;;;;
-10B39;AVESTAN ABBREVIATION MARK;Po;0;ON;;;;;N;;;;;
-10B3A;TINY TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-10B3B;SMALL TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-10B3C;LARGE TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
-10B3D;LARGE ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;;
-10B3E;LARGE TWO RINGS OVER ONE RING PUNCTUATION;Po;0;ON;;;;;N;;;;;
-10B3F;LARGE ONE RING OVER TWO RINGS PUNCTUATION;Po;0;ON;;;;;N;;;;;
-10B40;INSCRIPTIONAL PARTHIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;;
-10B41;INSCRIPTIONAL PARTHIAN LETTER BETH;Lo;0;R;;;;;N;;;;;
-10B42;INSCRIPTIONAL PARTHIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;;
-10B43;INSCRIPTIONAL PARTHIAN LETTER DALETH;Lo;0;R;;;;;N;;;;;
-10B44;INSCRIPTIONAL PARTHIAN LETTER HE;Lo;0;R;;;;;N;;;;;
-10B45;INSCRIPTIONAL PARTHIAN LETTER WAW;Lo;0;R;;;;;N;;;;;
-10B46;INSCRIPTIONAL PARTHIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
-10B47;INSCRIPTIONAL PARTHIAN LETTER HETH;Lo;0;R;;;;;N;;;;;
-10B48;INSCRIPTIONAL PARTHIAN LETTER TETH;Lo;0;R;;;;;N;;;;;
-10B49;INSCRIPTIONAL PARTHIAN LETTER YODH;Lo;0;R;;;;;N;;;;;
-10B4A;INSCRIPTIONAL PARTHIAN LETTER KAPH;Lo;0;R;;;;;N;;;;;
-10B4B;INSCRIPTIONAL PARTHIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
-10B4C;INSCRIPTIONAL PARTHIAN LETTER MEM;Lo;0;R;;;;;N;;;;;
-10B4D;INSCRIPTIONAL PARTHIAN LETTER NUN;Lo;0;R;;;;;N;;;;;
-10B4E;INSCRIPTIONAL PARTHIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
-10B4F;INSCRIPTIONAL PARTHIAN LETTER AYIN;Lo;0;R;;;;;N;;;;;
-10B50;INSCRIPTIONAL PARTHIAN LETTER PE;Lo;0;R;;;;;N;;;;;
-10B51;INSCRIPTIONAL PARTHIAN LETTER SADHE;Lo;0;R;;;;;N;;;;;
-10B52;INSCRIPTIONAL PARTHIAN LETTER QOPH;Lo;0;R;;;;;N;;;;;
-10B53;INSCRIPTIONAL PARTHIAN LETTER RESH;Lo;0;R;;;;;N;;;;;
-10B54;INSCRIPTIONAL PARTHIAN LETTER SHIN;Lo;0;R;;;;;N;;;;;
-10B55;INSCRIPTIONAL PARTHIAN LETTER TAW;Lo;0;R;;;;;N;;;;;
-10B58;INSCRIPTIONAL PARTHIAN NUMBER ONE;No;0;R;;;;1;N;;;;;
-10B59;INSCRIPTIONAL PARTHIAN NUMBER TWO;No;0;R;;;;2;N;;;;;
-10B5A;INSCRIPTIONAL PARTHIAN NUMBER THREE;No;0;R;;;;3;N;;;;;
-10B5B;INSCRIPTIONAL PARTHIAN NUMBER FOUR;No;0;R;;;;4;N;;;;;
-10B5C;INSCRIPTIONAL PARTHIAN NUMBER TEN;No;0;R;;;;10;N;;;;;
-10B5D;INSCRIPTIONAL PARTHIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;;
-10B5E;INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
-10B5F;INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
-10B60;INSCRIPTIONAL PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;;
-10B61;INSCRIPTIONAL PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;;
-10B62;INSCRIPTIONAL PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;;
-10B63;INSCRIPTIONAL PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;;
-10B64;INSCRIPTIONAL PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;;
-10B65;INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;;
-10B66;INSCRIPTIONAL PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
-10B67;INSCRIPTIONAL PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;;
-10B68;INSCRIPTIONAL PAHLAVI LETTER TETH;Lo;0;R;;;;;N;;;;;
-10B69;INSCRIPTIONAL PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;;
-10B6A;INSCRIPTIONAL PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;;
-10B6B;INSCRIPTIONAL PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
-10B6C;INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;;
-10B6D;INSCRIPTIONAL PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;;
-10B6E;INSCRIPTIONAL PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
-10B6F;INSCRIPTIONAL PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;;
-10B70;INSCRIPTIONAL PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;;
-10B71;INSCRIPTIONAL PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;;
-10B72;INSCRIPTIONAL PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;;
-10B78;INSCRIPTIONAL PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;;
-10B79;INSCRIPTIONAL PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;;
-10B7A;INSCRIPTIONAL PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;;
-10B7B;INSCRIPTIONAL PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;;
-10B7C;INSCRIPTIONAL PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;;
-10B7D;INSCRIPTIONAL PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;;
-10B7E;INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
-10B7F;INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
-10C00;OLD TURKIC LETTER ORKHON A;Lo;0;R;;;;;N;;;;;
-10C01;OLD TURKIC LETTER YENISEI A;Lo;0;R;;;;;N;;;;;
-10C02;OLD TURKIC LETTER YENISEI AE;Lo;0;R;;;;;N;;;;;
-10C03;OLD TURKIC LETTER ORKHON I;Lo;0;R;;;;;N;;;;;
-10C04;OLD TURKIC LETTER YENISEI I;Lo;0;R;;;;;N;;;;;
-10C05;OLD TURKIC LETTER YENISEI E;Lo;0;R;;;;;N;;;;;
-10C06;OLD TURKIC LETTER ORKHON O;Lo;0;R;;;;;N;;;;;
-10C07;OLD TURKIC LETTER ORKHON OE;Lo;0;R;;;;;N;;;;;
-10C08;OLD TURKIC LETTER YENISEI OE;Lo;0;R;;;;;N;;;;;
-10C09;OLD TURKIC LETTER ORKHON AB;Lo;0;R;;;;;N;;;;;
-10C0A;OLD TURKIC LETTER YENISEI AB;Lo;0;R;;;;;N;;;;;
-10C0B;OLD TURKIC LETTER ORKHON AEB;Lo;0;R;;;;;N;;;;;
-10C0C;OLD TURKIC LETTER YENISEI AEB;Lo;0;R;;;;;N;;;;;
-10C0D;OLD TURKIC LETTER ORKHON AG;Lo;0;R;;;;;N;;;;;
-10C0E;OLD TURKIC LETTER YENISEI AG;Lo;0;R;;;;;N;;;;;
-10C0F;OLD TURKIC LETTER ORKHON AEG;Lo;0;R;;;;;N;;;;;
-10C10;OLD TURKIC LETTER YENISEI AEG;Lo;0;R;;;;;N;;;;;
-10C11;OLD TURKIC LETTER ORKHON AD;Lo;0;R;;;;;N;;;;;
-10C12;OLD TURKIC LETTER YENISEI AD;Lo;0;R;;;;;N;;;;;
-10C13;OLD TURKIC LETTER ORKHON AED;Lo;0;R;;;;;N;;;;;
-10C14;OLD TURKIC LETTER ORKHON EZ;Lo;0;R;;;;;N;;;;;
-10C15;OLD TURKIC LETTER YENISEI EZ;Lo;0;R;;;;;N;;;;;
-10C16;OLD TURKIC LETTER ORKHON AY;Lo;0;R;;;;;N;;;;;
-10C17;OLD TURKIC LETTER YENISEI AY;Lo;0;R;;;;;N;;;;;
-10C18;OLD TURKIC LETTER ORKHON AEY;Lo;0;R;;;;;N;;;;;
-10C19;OLD TURKIC LETTER YENISEI AEY;Lo;0;R;;;;;N;;;;;
-10C1A;OLD TURKIC LETTER ORKHON AEK;Lo;0;R;;;;;N;;;;;
-10C1B;OLD TURKIC LETTER YENISEI AEK;Lo;0;R;;;;;N;;;;;
-10C1C;OLD TURKIC LETTER ORKHON OEK;Lo;0;R;;;;;N;;;;;
-10C1D;OLD TURKIC LETTER YENISEI OEK;Lo;0;R;;;;;N;;;;;
-10C1E;OLD TURKIC LETTER ORKHON AL;Lo;0;R;;;;;N;;;;;
-10C1F;OLD TURKIC LETTER YENISEI AL;Lo;0;R;;;;;N;;;;;
-10C20;OLD TURKIC LETTER ORKHON AEL;Lo;0;R;;;;;N;;;;;
-10C21;OLD TURKIC LETTER ORKHON ELT;Lo;0;R;;;;;N;;;;;
-10C22;OLD TURKIC LETTER ORKHON EM;Lo;0;R;;;;;N;;;;;
-10C23;OLD TURKIC LETTER ORKHON AN;Lo;0;R;;;;;N;;;;;
-10C24;OLD TURKIC LETTER ORKHON AEN;Lo;0;R;;;;;N;;;;;
-10C25;OLD TURKIC LETTER YENISEI AEN;Lo;0;R;;;;;N;;;;;
-10C26;OLD TURKIC LETTER ORKHON ENT;Lo;0;R;;;;;N;;;;;
-10C27;OLD TURKIC LETTER YENISEI ENT;Lo;0;R;;;;;N;;;;;
-10C28;OLD TURKIC LETTER ORKHON ENC;Lo;0;R;;;;;N;;;;;
-10C29;OLD TURKIC LETTER YENISEI ENC;Lo;0;R;;;;;N;;;;;
-10C2A;OLD TURKIC LETTER ORKHON ENY;Lo;0;R;;;;;N;;;;;
-10C2B;OLD TURKIC LETTER YENISEI ENY;Lo;0;R;;;;;N;;;;;
-10C2C;OLD TURKIC LETTER YENISEI ANG;Lo;0;R;;;;;N;;;;;
-10C2D;OLD TURKIC LETTER ORKHON ENG;Lo;0;R;;;;;N;;;;;
-10C2E;OLD TURKIC LETTER YENISEI AENG;Lo;0;R;;;;;N;;;;;
-10C2F;OLD TURKIC LETTER ORKHON EP;Lo;0;R;;;;;N;;;;;
-10C30;OLD TURKIC LETTER ORKHON OP;Lo;0;R;;;;;N;;;;;
-10C31;OLD TURKIC LETTER ORKHON IC;Lo;0;R;;;;;N;;;;;
-10C32;OLD TURKIC LETTER ORKHON EC;Lo;0;R;;;;;N;;;;;
-10C33;OLD TURKIC LETTER YENISEI EC;Lo;0;R;;;;;N;;;;;
-10C34;OLD TURKIC LETTER ORKHON AQ;Lo;0;R;;;;;N;;;;;
-10C35;OLD TURKIC LETTER YENISEI AQ;Lo;0;R;;;;;N;;;;;
-10C36;OLD TURKIC LETTER ORKHON IQ;Lo;0;R;;;;;N;;;;;
-10C37;OLD TURKIC LETTER YENISEI IQ;Lo;0;R;;;;;N;;;;;
-10C38;OLD TURKIC LETTER ORKHON OQ;Lo;0;R;;;;;N;;;;;
-10C39;OLD TURKIC LETTER YENISEI OQ;Lo;0;R;;;;;N;;;;;
-10C3A;OLD TURKIC LETTER ORKHON AR;Lo;0;R;;;;;N;;;;;
-10C3B;OLD TURKIC LETTER YENISEI AR;Lo;0;R;;;;;N;;;;;
-10C3C;OLD TURKIC LETTER ORKHON AER;Lo;0;R;;;;;N;;;;;
-10C3D;OLD TURKIC LETTER ORKHON AS;Lo;0;R;;;;;N;;;;;
-10C3E;OLD TURKIC LETTER ORKHON AES;Lo;0;R;;;;;N;;;;;
-10C3F;OLD TURKIC LETTER ORKHON ASH;Lo;0;R;;;;;N;;;;;
-10C40;OLD TURKIC LETTER YENISEI ASH;Lo;0;R;;;;;N;;;;;
-10C41;OLD TURKIC LETTER ORKHON ESH;Lo;0;R;;;;;N;;;;;
-10C42;OLD TURKIC LETTER YENISEI ESH;Lo;0;R;;;;;N;;;;;
-10C43;OLD TURKIC LETTER ORKHON AT;Lo;0;R;;;;;N;;;;;
-10C44;OLD TURKIC LETTER YENISEI AT;Lo;0;R;;;;;N;;;;;
-10C45;OLD TURKIC LETTER ORKHON AET;Lo;0;R;;;;;N;;;;;
-10C46;OLD TURKIC LETTER YENISEI AET;Lo;0;R;;;;;N;;;;;
-10C47;OLD TURKIC LETTER ORKHON OT;Lo;0;R;;;;;N;;;;;
-10C48;OLD TURKIC LETTER ORKHON BASH;Lo;0;R;;;;;N;;;;;
-10E60;RUMI DIGIT ONE;No;0;AN;;;1;1;N;;;;;
-10E61;RUMI DIGIT TWO;No;0;AN;;;2;2;N;;;;;
-10E62;RUMI DIGIT THREE;No;0;AN;;;3;3;N;;;;;
-10E63;RUMI DIGIT FOUR;No;0;AN;;;4;4;N;;;;;
-10E64;RUMI DIGIT FIVE;No;0;AN;;;5;5;N;;;;;
-10E65;RUMI DIGIT SIX;No;0;AN;;;6;6;N;;;;;
-10E66;RUMI DIGIT SEVEN;No;0;AN;;;7;7;N;;;;;
-10E67;RUMI DIGIT EIGHT;No;0;AN;;;8;8;N;;;;;
-10E68;RUMI DIGIT NINE;No;0;AN;;;9;9;N;;;;;
-10E69;RUMI NUMBER TEN;No;0;AN;;;;10;N;;;;;
-10E6A;RUMI NUMBER TWENTY;No;0;AN;;;;20;N;;;;;
-10E6B;RUMI NUMBER THIRTY;No;0;AN;;;;30;N;;;;;
-10E6C;RUMI NUMBER FORTY;No;0;AN;;;;40;N;;;;;
-10E6D;RUMI NUMBER FIFTY;No;0;AN;;;;50;N;;;;;
-10E6E;RUMI NUMBER SIXTY;No;0;AN;;;;60;N;;;;;
-10E6F;RUMI NUMBER SEVENTY;No;0;AN;;;;70;N;;;;;
-10E70;RUMI NUMBER EIGHTY;No;0;AN;;;;80;N;;;;;
-10E71;RUMI NUMBER NINETY;No;0;AN;;;;90;N;;;;;
-10E72;RUMI NUMBER ONE HUNDRED;No;0;AN;;;;100;N;;;;;
-10E73;RUMI NUMBER TWO HUNDRED;No;0;AN;;;;200;N;;;;;
-10E74;RUMI NUMBER THREE HUNDRED;No;0;AN;;;;300;N;;;;;
-10E75;RUMI NUMBER FOUR HUNDRED;No;0;AN;;;;400;N;;;;;
-10E76;RUMI NUMBER FIVE HUNDRED;No;0;AN;;;;500;N;;;;;
-10E77;RUMI NUMBER SIX HUNDRED;No;0;AN;;;;600;N;;;;;
-10E78;RUMI NUMBER SEVEN HUNDRED;No;0;AN;;;;700;N;;;;;
-10E79;RUMI NUMBER EIGHT HUNDRED;No;0;AN;;;;800;N;;;;;
-10E7A;RUMI NUMBER NINE HUNDRED;No;0;AN;;;;900;N;;;;;
-10E7B;RUMI FRACTION ONE HALF;No;0;AN;;;;1/2;N;;;;;
-10E7C;RUMI FRACTION ONE QUARTER;No;0;AN;;;;1/4;N;;;;;
-10E7D;RUMI FRACTION ONE THIRD;No;0;AN;;;;1/3;N;;;;;
-10E7E;RUMI FRACTION TWO THIRDS;No;0;AN;;;;2/3;N;;;;;
-11000;BRAHMI SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;;
-11001;BRAHMI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-11002;BRAHMI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-11003;BRAHMI SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;;
-11004;BRAHMI SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;;
-11005;BRAHMI LETTER A;Lo;0;L;;;;;N;;;;;
-11006;BRAHMI LETTER AA;Lo;0;L;;;;;N;;;;;
-11007;BRAHMI LETTER I;Lo;0;L;;;;;N;;;;;
-11008;BRAHMI LETTER II;Lo;0;L;;;;;N;;;;;
-11009;BRAHMI LETTER U;Lo;0;L;;;;;N;;;;;
-1100A;BRAHMI LETTER UU;Lo;0;L;;;;;N;;;;;
-1100B;BRAHMI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-1100C;BRAHMI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-1100D;BRAHMI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-1100E;BRAHMI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-1100F;BRAHMI LETTER E;Lo;0;L;;;;;N;;;;;
-11010;BRAHMI LETTER AI;Lo;0;L;;;;;N;;;;;
-11011;BRAHMI LETTER O;Lo;0;L;;;;;N;;;;;
-11012;BRAHMI LETTER AU;Lo;0;L;;;;;N;;;;;
-11013;BRAHMI LETTER KA;Lo;0;L;;;;;N;;;;;
-11014;BRAHMI LETTER KHA;Lo;0;L;;;;;N;;;;;
-11015;BRAHMI LETTER GA;Lo;0;L;;;;;N;;;;;
-11016;BRAHMI LETTER GHA;Lo;0;L;;;;;N;;;;;
-11017;BRAHMI LETTER NGA;Lo;0;L;;;;;N;;;;;
-11018;BRAHMI LETTER CA;Lo;0;L;;;;;N;;;;;
-11019;BRAHMI LETTER CHA;Lo;0;L;;;;;N;;;;;
-1101A;BRAHMI LETTER JA;Lo;0;L;;;;;N;;;;;
-1101B;BRAHMI LETTER JHA;Lo;0;L;;;;;N;;;;;
-1101C;BRAHMI LETTER NYA;Lo;0;L;;;;;N;;;;;
-1101D;BRAHMI LETTER TTA;Lo;0;L;;;;;N;;;;;
-1101E;BRAHMI LETTER TTHA;Lo;0;L;;;;;N;;;;;
-1101F;BRAHMI LETTER DDA;Lo;0;L;;;;;N;;;;;
-11020;BRAHMI LETTER DDHA;Lo;0;L;;;;;N;;;;;
-11021;BRAHMI LETTER NNA;Lo;0;L;;;;;N;;;;;
-11022;BRAHMI LETTER TA;Lo;0;L;;;;;N;;;;;
-11023;BRAHMI LETTER THA;Lo;0;L;;;;;N;;;;;
-11024;BRAHMI LETTER DA;Lo;0;L;;;;;N;;;;;
-11025;BRAHMI LETTER DHA;Lo;0;L;;;;;N;;;;;
-11026;BRAHMI LETTER NA;Lo;0;L;;;;;N;;;;;
-11027;BRAHMI LETTER PA;Lo;0;L;;;;;N;;;;;
-11028;BRAHMI LETTER PHA;Lo;0;L;;;;;N;;;;;
-11029;BRAHMI LETTER BA;Lo;0;L;;;;;N;;;;;
-1102A;BRAHMI LETTER BHA;Lo;0;L;;;;;N;;;;;
-1102B;BRAHMI LETTER MA;Lo;0;L;;;;;N;;;;;
-1102C;BRAHMI LETTER YA;Lo;0;L;;;;;N;;;;;
-1102D;BRAHMI LETTER RA;Lo;0;L;;;;;N;;;;;
-1102E;BRAHMI LETTER LA;Lo;0;L;;;;;N;;;;;
-1102F;BRAHMI LETTER VA;Lo;0;L;;;;;N;;;;;
-11030;BRAHMI LETTER SHA;Lo;0;L;;;;;N;;;;;
-11031;BRAHMI LETTER SSA;Lo;0;L;;;;;N;;;;;
-11032;BRAHMI LETTER SA;Lo;0;L;;;;;N;;;;;
-11033;BRAHMI LETTER HA;Lo;0;L;;;;;N;;;;;
-11034;BRAHMI LETTER LLA;Lo;0;L;;;;;N;;;;;
-11035;BRAHMI LETTER OLD TAMIL LLLA;Lo;0;L;;;;;N;;;;;
-11036;BRAHMI LETTER OLD TAMIL RRA;Lo;0;L;;;;;N;;;;;
-11037;BRAHMI LETTER OLD TAMIL NNNA;Lo;0;L;;;;;N;;;;;
-11038;BRAHMI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;;
-11039;BRAHMI VOWEL SIGN BHATTIPROLU AA;Mn;0;NSM;;;;;N;;;;;
-1103A;BRAHMI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-1103B;BRAHMI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-1103C;BRAHMI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1103D;BRAHMI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-1103E;BRAHMI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
-1103F;BRAHMI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
-11040;BRAHMI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-11041;BRAHMI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-11042;BRAHMI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-11043;BRAHMI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-11044;BRAHMI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
-11045;BRAHMI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
-11046;BRAHMI VIRAMA;Mn;9;NSM;;;;;N;;;;;
-11047;BRAHMI DANDA;Po;0;L;;;;;N;;;;;
-11048;BRAHMI DOUBLE DANDA;Po;0;L;;;;;N;;;;;
-11049;BRAHMI PUNCTUATION DOT;Po;0;L;;;;;N;;;;;
-1104A;BRAHMI PUNCTUATION DOUBLE DOT;Po;0;L;;;;;N;;;;;
-1104B;BRAHMI PUNCTUATION LINE;Po;0;L;;;;;N;;;;;
-1104C;BRAHMI PUNCTUATION CRESCENT BAR;Po;0;L;;;;;N;;;;;
-1104D;BRAHMI PUNCTUATION LOTUS;Po;0;L;;;;;N;;;;;
-11052;BRAHMI NUMBER ONE;No;0;ON;;;1;1;N;;;;;
-11053;BRAHMI NUMBER TWO;No;0;ON;;;2;2;N;;;;;
-11054;BRAHMI NUMBER THREE;No;0;ON;;;3;3;N;;;;;
-11055;BRAHMI NUMBER FOUR;No;0;ON;;;4;4;N;;;;;
-11056;BRAHMI NUMBER FIVE;No;0;ON;;;5;5;N;;;;;
-11057;BRAHMI NUMBER SIX;No;0;ON;;;6;6;N;;;;;
-11058;BRAHMI NUMBER SEVEN;No;0;ON;;;7;7;N;;;;;
-11059;BRAHMI NUMBER EIGHT;No;0;ON;;;8;8;N;;;;;
-1105A;BRAHMI NUMBER NINE;No;0;ON;;;9;9;N;;;;;
-1105B;BRAHMI NUMBER TEN;No;0;ON;;;;10;N;;;;;
-1105C;BRAHMI NUMBER TWENTY;No;0;ON;;;;20;N;;;;;
-1105D;BRAHMI NUMBER THIRTY;No;0;ON;;;;30;N;;;;;
-1105E;BRAHMI NUMBER FORTY;No;0;ON;;;;40;N;;;;;
-1105F;BRAHMI NUMBER FIFTY;No;0;ON;;;;50;N;;;;;
-11060;BRAHMI NUMBER SIXTY;No;0;ON;;;;60;N;;;;;
-11061;BRAHMI NUMBER SEVENTY;No;0;ON;;;;70;N;;;;;
-11062;BRAHMI NUMBER EIGHTY;No;0;ON;;;;80;N;;;;;
-11063;BRAHMI NUMBER NINETY;No;0;ON;;;;90;N;;;;;
-11064;BRAHMI NUMBER ONE HUNDRED;No;0;ON;;;;100;N;;;;;
-11065;BRAHMI NUMBER ONE THOUSAND;No;0;ON;;;;1000;N;;;;;
-11066;BRAHMI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-11067;BRAHMI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-11068;BRAHMI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-11069;BRAHMI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1106A;BRAHMI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1106B;BRAHMI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1106C;BRAHMI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1106D;BRAHMI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1106E;BRAHMI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1106F;BRAHMI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
-11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-11082;KAITHI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-11083;KAITHI LETTER A;Lo;0;L;;;;;N;;;;;
-11084;KAITHI LETTER AA;Lo;0;L;;;;;N;;;;;
-11085;KAITHI LETTER I;Lo;0;L;;;;;N;;;;;
-11086;KAITHI LETTER II;Lo;0;L;;;;;N;;;;;
-11087;KAITHI LETTER U;Lo;0;L;;;;;N;;;;;
-11088;KAITHI LETTER UU;Lo;0;L;;;;;N;;;;;
-11089;KAITHI LETTER E;Lo;0;L;;;;;N;;;;;
-1108A;KAITHI LETTER AI;Lo;0;L;;;;;N;;;;;
-1108B;KAITHI LETTER O;Lo;0;L;;;;;N;;;;;
-1108C;KAITHI LETTER AU;Lo;0;L;;;;;N;;;;;
-1108D;KAITHI LETTER KA;Lo;0;L;;;;;N;;;;;
-1108E;KAITHI LETTER KHA;Lo;0;L;;;;;N;;;;;
-1108F;KAITHI LETTER GA;Lo;0;L;;;;;N;;;;;
-11090;KAITHI LETTER GHA;Lo;0;L;;;;;N;;;;;
-11091;KAITHI LETTER NGA;Lo;0;L;;;;;N;;;;;
-11092;KAITHI LETTER CA;Lo;0;L;;;;;N;;;;;
-11093;KAITHI LETTER CHA;Lo;0;L;;;;;N;;;;;
-11094;KAITHI LETTER JA;Lo;0;L;;;;;N;;;;;
-11095;KAITHI LETTER JHA;Lo;0;L;;;;;N;;;;;
-11096;KAITHI LETTER NYA;Lo;0;L;;;;;N;;;;;
-11097;KAITHI LETTER TTA;Lo;0;L;;;;;N;;;;;
-11098;KAITHI LETTER TTHA;Lo;0;L;;;;;N;;;;;
-11099;KAITHI LETTER DDA;Lo;0;L;;;;;N;;;;;
-1109A;KAITHI LETTER DDDHA;Lo;0;L;11099 110BA;;;;N;;;;;
-1109B;KAITHI LETTER DDHA;Lo;0;L;;;;;N;;;;;
-1109C;KAITHI LETTER RHA;Lo;0;L;1109B 110BA;;;;N;;;;;
-1109D;KAITHI LETTER NNA;Lo;0;L;;;;;N;;;;;
-1109E;KAITHI LETTER TA;Lo;0;L;;;;;N;;;;;
-1109F;KAITHI LETTER THA;Lo;0;L;;;;;N;;;;;
-110A0;KAITHI LETTER DA;Lo;0;L;;;;;N;;;;;
-110A1;KAITHI LETTER DHA;Lo;0;L;;;;;N;;;;;
-110A2;KAITHI LETTER NA;Lo;0;L;;;;;N;;;;;
-110A3;KAITHI LETTER PA;Lo;0;L;;;;;N;;;;;
-110A4;KAITHI LETTER PHA;Lo;0;L;;;;;N;;;;;
-110A5;KAITHI LETTER BA;Lo;0;L;;;;;N;;;;;
-110A6;KAITHI LETTER BHA;Lo;0;L;;;;;N;;;;;
-110A7;KAITHI LETTER MA;Lo;0;L;;;;;N;;;;;
-110A8;KAITHI LETTER YA;Lo;0;L;;;;;N;;;;;
-110A9;KAITHI LETTER RA;Lo;0;L;;;;;N;;;;;
-110AA;KAITHI LETTER LA;Lo;0;L;;;;;N;;;;;
-110AB;KAITHI LETTER VA;Lo;0;L;110A5 110BA;;;;N;;;;;
-110AC;KAITHI LETTER SHA;Lo;0;L;;;;;N;;;;;
-110AD;KAITHI LETTER SSA;Lo;0;L;;;;;N;;;;;
-110AE;KAITHI LETTER SA;Lo;0;L;;;;;N;;;;;
-110AF;KAITHI LETTER HA;Lo;0;L;;;;;N;;;;;
-110B0;KAITHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-110B1;KAITHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-110B2;KAITHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-110B3;KAITHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-110B4;KAITHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-110B5;KAITHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-110B6;KAITHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-110B7;KAITHI VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-110B8;KAITHI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-110B9;KAITHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
-110BA;KAITHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-110BB;KAITHI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
-110BC;KAITHI ENUMERATION SIGN;Po;0;L;;;;;N;;;;;
-110BD;KAITHI NUMBER SIGN;Cf;0;L;;;;;N;;;;;
-110BE;KAITHI SECTION MARK;Po;0;L;;;;;N;;;;;
-110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;;
-110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;;
-110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;;
-110D0;SORA SOMPENG LETTER SAH;Lo;0;L;;;;;N;;;;;
-110D1;SORA SOMPENG LETTER TAH;Lo;0;L;;;;;N;;;;;
-110D2;SORA SOMPENG LETTER BAH;Lo;0;L;;;;;N;;;;;
-110D3;SORA SOMPENG LETTER CAH;Lo;0;L;;;;;N;;;;;
-110D4;SORA SOMPENG LETTER DAH;Lo;0;L;;;;;N;;;;;
-110D5;SORA SOMPENG LETTER GAH;Lo;0;L;;;;;N;;;;;
-110D6;SORA SOMPENG LETTER MAH;Lo;0;L;;;;;N;;;;;
-110D7;SORA SOMPENG LETTER NGAH;Lo;0;L;;;;;N;;;;;
-110D8;SORA SOMPENG LETTER LAH;Lo;0;L;;;;;N;;;;;
-110D9;SORA SOMPENG LETTER NAH;Lo;0;L;;;;;N;;;;;
-110DA;SORA SOMPENG LETTER VAH;Lo;0;L;;;;;N;;;;;
-110DB;SORA SOMPENG LETTER PAH;Lo;0;L;;;;;N;;;;;
-110DC;SORA SOMPENG LETTER YAH;Lo;0;L;;;;;N;;;;;
-110DD;SORA SOMPENG LETTER RAH;Lo;0;L;;;;;N;;;;;
-110DE;SORA SOMPENG LETTER HAH;Lo;0;L;;;;;N;;;;;
-110DF;SORA SOMPENG LETTER KAH;Lo;0;L;;;;;N;;;;;
-110E0;SORA SOMPENG LETTER JAH;Lo;0;L;;;;;N;;;;;
-110E1;SORA SOMPENG LETTER NYAH;Lo;0;L;;;;;N;;;;;
-110E2;SORA SOMPENG LETTER AH;Lo;0;L;;;;;N;;;;;
-110E3;SORA SOMPENG LETTER EEH;Lo;0;L;;;;;N;;;;;
-110E4;SORA SOMPENG LETTER IH;Lo;0;L;;;;;N;;;;;
-110E5;SORA SOMPENG LETTER UH;Lo;0;L;;;;;N;;;;;
-110E6;SORA SOMPENG LETTER OH;Lo;0;L;;;;;N;;;;;
-110E7;SORA SOMPENG LETTER EH;Lo;0;L;;;;;N;;;;;
-110E8;SORA SOMPENG LETTER MAE;Lo;0;L;;;;;N;;;;;
-110F0;SORA SOMPENG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-110F1;SORA SOMPENG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-110F2;SORA SOMPENG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-110F3;SORA SOMPENG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-110F4;SORA SOMPENG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-110F5;SORA SOMPENG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-110F6;SORA SOMPENG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-110F7;SORA SOMPENG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-110F8;SORA SOMPENG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-110F9;SORA SOMPENG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-11100;CHAKMA SIGN CANDRABINDU;Mn;230;NSM;;;;;N;;;;;
-11101;CHAKMA SIGN ANUSVARA;Mn;230;NSM;;;;;N;;;;;
-11102;CHAKMA SIGN VISARGA;Mn;230;NSM;;;;;N;;;;;
-11103;CHAKMA LETTER AA;Lo;0;L;;;;;N;;;;;
-11104;CHAKMA LETTER I;Lo;0;L;;;;;N;;;;;
-11105;CHAKMA LETTER U;Lo;0;L;;;;;N;;;;;
-11106;CHAKMA LETTER E;Lo;0;L;;;;;N;;;;;
-11107;CHAKMA LETTER KAA;Lo;0;L;;;;;N;;;;;
-11108;CHAKMA LETTER KHAA;Lo;0;L;;;;;N;;;;;
-11109;CHAKMA LETTER GAA;Lo;0;L;;;;;N;;;;;
-1110A;CHAKMA LETTER GHAA;Lo;0;L;;;;;N;;;;;
-1110B;CHAKMA LETTER NGAA;Lo;0;L;;;;;N;;;;;
-1110C;CHAKMA LETTER CAA;Lo;0;L;;;;;N;;;;;
-1110D;CHAKMA LETTER CHAA;Lo;0;L;;;;;N;;;;;
-1110E;CHAKMA LETTER JAA;Lo;0;L;;;;;N;;;;;
-1110F;CHAKMA LETTER JHAA;Lo;0;L;;;;;N;;;;;
-11110;CHAKMA LETTER NYAA;Lo;0;L;;;;;N;;;;;
-11111;CHAKMA LETTER TTAA;Lo;0;L;;;;;N;;;;;
-11112;CHAKMA LETTER TTHAA;Lo;0;L;;;;;N;;;;;
-11113;CHAKMA LETTER DDAA;Lo;0;L;;;;;N;;;;;
-11114;CHAKMA LETTER DDHAA;Lo;0;L;;;;;N;;;;;
-11115;CHAKMA LETTER NNAA;Lo;0;L;;;;;N;;;;;
-11116;CHAKMA LETTER TAA;Lo;0;L;;;;;N;;;;;
-11117;CHAKMA LETTER THAA;Lo;0;L;;;;;N;;;;;
-11118;CHAKMA LETTER DAA;Lo;0;L;;;;;N;;;;;
-11119;CHAKMA LETTER DHAA;Lo;0;L;;;;;N;;;;;
-1111A;CHAKMA LETTER NAA;Lo;0;L;;;;;N;;;;;
-1111B;CHAKMA LETTER PAA;Lo;0;L;;;;;N;;;;;
-1111C;CHAKMA LETTER PHAA;Lo;0;L;;;;;N;;;;;
-1111D;CHAKMA LETTER BAA;Lo;0;L;;;;;N;;;;;
-1111E;CHAKMA LETTER BHAA;Lo;0;L;;;;;N;;;;;
-1111F;CHAKMA LETTER MAA;Lo;0;L;;;;;N;;;;;
-11120;CHAKMA LETTER YYAA;Lo;0;L;;;;;N;;;;;
-11121;CHAKMA LETTER YAA;Lo;0;L;;;;;N;;;;;
-11122;CHAKMA LETTER RAA;Lo;0;L;;;;;N;;;;;
-11123;CHAKMA LETTER LAA;Lo;0;L;;;;;N;;;;;
-11124;CHAKMA LETTER WAA;Lo;0;L;;;;;N;;;;;
-11125;CHAKMA LETTER SAA;Lo;0;L;;;;;N;;;;;
-11126;CHAKMA LETTER HAA;Lo;0;L;;;;;N;;;;;
-11127;CHAKMA VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;;
-11128;CHAKMA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
-11129;CHAKMA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
-1112A;CHAKMA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1112B;CHAKMA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-1112C;CHAKMA VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-1112D;CHAKMA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-1112E;CHAKMA VOWEL SIGN O;Mn;0;NSM;11131 11127;;;;N;;;;;
-1112F;CHAKMA VOWEL SIGN AU;Mn;0;NSM;11132 11127;;;;N;;;;;
-11130;CHAKMA VOWEL SIGN OI;Mn;0;NSM;;;;;N;;;;;
-11131;CHAKMA O MARK;Mn;0;NSM;;;;;N;;;;;
-11132;CHAKMA AU MARK;Mn;0;NSM;;;;;N;;;;;
-11133;CHAKMA VIRAMA;Mn;9;NSM;;;;;N;;;;;
-11134;CHAKMA MAAYYAA;Mn;9;NSM;;;;;N;;;;;
-11136;CHAKMA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-11137;CHAKMA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-11138;CHAKMA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-11139;CHAKMA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-1113A;CHAKMA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-1113B;CHAKMA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-1113C;CHAKMA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-1113D;CHAKMA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-1113E;CHAKMA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-1113F;CHAKMA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-11140;CHAKMA SECTION MARK;Po;0;L;;;;;N;;;;;
-11141;CHAKMA DANDA;Po;0;L;;;;;N;;;;;
-11142;CHAKMA DOUBLE DANDA;Po;0;L;;;;;N;;;;;
-11143;CHAKMA QUESTION MARK;Po;0;L;;;;;N;;;;;
-11180;SHARADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
-11181;SHARADA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-11182;SHARADA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-11183;SHARADA LETTER A;Lo;0;L;;;;;N;;;;;
-11184;SHARADA LETTER AA;Lo;0;L;;;;;N;;;;;
-11185;SHARADA LETTER I;Lo;0;L;;;;;N;;;;;
-11186;SHARADA LETTER II;Lo;0;L;;;;;N;;;;;
-11187;SHARADA LETTER U;Lo;0;L;;;;;N;;;;;
-11188;SHARADA LETTER UU;Lo;0;L;;;;;N;;;;;
-11189;SHARADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
-1118A;SHARADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
-1118B;SHARADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
-1118C;SHARADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
-1118D;SHARADA LETTER E;Lo;0;L;;;;;N;;;;;
-1118E;SHARADA LETTER AI;Lo;0;L;;;;;N;;;;;
-1118F;SHARADA LETTER O;Lo;0;L;;;;;N;;;;;
-11190;SHARADA LETTER AU;Lo;0;L;;;;;N;;;;;
-11191;SHARADA LETTER KA;Lo;0;L;;;;;N;;;;;
-11192;SHARADA LETTER KHA;Lo;0;L;;;;;N;;;;;
-11193;SHARADA LETTER GA;Lo;0;L;;;;;N;;;;;
-11194;SHARADA LETTER GHA;Lo;0;L;;;;;N;;;;;
-11195;SHARADA LETTER NGA;Lo;0;L;;;;;N;;;;;
-11196;SHARADA LETTER CA;Lo;0;L;;;;;N;;;;;
-11197;SHARADA LETTER CHA;Lo;0;L;;;;;N;;;;;
-11198;SHARADA LETTER JA;Lo;0;L;;;;;N;;;;;
-11199;SHARADA LETTER JHA;Lo;0;L;;;;;N;;;;;
-1119A;SHARADA LETTER NYA;Lo;0;L;;;;;N;;;;;
-1119B;SHARADA LETTER TTA;Lo;0;L;;;;;N;;;;;
-1119C;SHARADA LETTER TTHA;Lo;0;L;;;;;N;;;;;
-1119D;SHARADA LETTER DDA;Lo;0;L;;;;;N;;;;;
-1119E;SHARADA LETTER DDHA;Lo;0;L;;;;;N;;;;;
-1119F;SHARADA LETTER NNA;Lo;0;L;;;;;N;;;;;
-111A0;SHARADA LETTER TA;Lo;0;L;;;;;N;;;;;
-111A1;SHARADA LETTER THA;Lo;0;L;;;;;N;;;;;
-111A2;SHARADA LETTER DA;Lo;0;L;;;;;N;;;;;
-111A3;SHARADA LETTER DHA;Lo;0;L;;;;;N;;;;;
-111A4;SHARADA LETTER NA;Lo;0;L;;;;;N;;;;;
-111A5;SHARADA LETTER PA;Lo;0;L;;;;;N;;;;;
-111A6;SHARADA LETTER PHA;Lo;0;L;;;;;N;;;;;
-111A7;SHARADA LETTER BA;Lo;0;L;;;;;N;;;;;
-111A8;SHARADA LETTER BHA;Lo;0;L;;;;;N;;;;;
-111A9;SHARADA LETTER MA;Lo;0;L;;;;;N;;;;;
-111AA;SHARADA LETTER YA;Lo;0;L;;;;;N;;;;;
-111AB;SHARADA LETTER RA;Lo;0;L;;;;;N;;;;;
-111AC;SHARADA LETTER LA;Lo;0;L;;;;;N;;;;;
-111AD;SHARADA LETTER LLA;Lo;0;L;;;;;N;;;;;
-111AE;SHARADA LETTER VA;Lo;0;L;;;;;N;;;;;
-111AF;SHARADA LETTER SHA;Lo;0;L;;;;;N;;;;;
-111B0;SHARADA LETTER SSA;Lo;0;L;;;;;N;;;;;
-111B1;SHARADA LETTER SA;Lo;0;L;;;;;N;;;;;
-111B2;SHARADA LETTER HA;Lo;0;L;;;;;N;;;;;
-111B3;SHARADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-111B4;SHARADA VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-111B5;SHARADA VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-111B6;SHARADA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-111B7;SHARADA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-111B8;SHARADA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
-111B9;SHARADA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
-111BA;SHARADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
-111BB;SHARADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
-111BC;SHARADA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-111BD;SHARADA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-111BE;SHARADA VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
-111BF;SHARADA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-111C0;SHARADA SIGN VIRAMA;Mc;9;L;;;;;N;;;;;
-111C1;SHARADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
-111C2;SHARADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;;
-111C3;SHARADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;;
-111C4;SHARADA OM;Lo;0;L;;;;;N;;;;;
-111C5;SHARADA DANDA;Po;0;L;;;;;N;;;;;
-111C6;SHARADA DOUBLE DANDA;Po;0;L;;;;;N;;;;;
-111C7;SHARADA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
-111C8;SHARADA SEPARATOR;Po;0;L;;;;;N;;;;;
-111D0;SHARADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-111D1;SHARADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-111D2;SHARADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-111D3;SHARADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-111D4;SHARADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-111D5;SHARADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-111D6;SHARADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-111D7;SHARADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-111D8;SHARADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-111D9;SHARADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-11680;TAKRI LETTER A;Lo;0;L;;;;;N;;;;;
-11681;TAKRI LETTER AA;Lo;0;L;;;;;N;;;;;
-11682;TAKRI LETTER I;Lo;0;L;;;;;N;;;;;
-11683;TAKRI LETTER II;Lo;0;L;;;;;N;;;;;
-11684;TAKRI LETTER U;Lo;0;L;;;;;N;;;;;
-11685;TAKRI LETTER UU;Lo;0;L;;;;;N;;;;;
-11686;TAKRI LETTER E;Lo;0;L;;;;;N;;;;;
-11687;TAKRI LETTER AI;Lo;0;L;;;;;N;;;;;
-11688;TAKRI LETTER O;Lo;0;L;;;;;N;;;;;
-11689;TAKRI LETTER AU;Lo;0;L;;;;;N;;;;;
-1168A;TAKRI LETTER KA;Lo;0;L;;;;;N;;;;;
-1168B;TAKRI LETTER KHA;Lo;0;L;;;;;N;;;;;
-1168C;TAKRI LETTER GA;Lo;0;L;;;;;N;;;;;
-1168D;TAKRI LETTER GHA;Lo;0;L;;;;;N;;;;;
-1168E;TAKRI LETTER NGA;Lo;0;L;;;;;N;;;;;
-1168F;TAKRI LETTER CA;Lo;0;L;;;;;N;;;;;
-11690;TAKRI LETTER CHA;Lo;0;L;;;;;N;;;;;
-11691;TAKRI LETTER JA;Lo;0;L;;;;;N;;;;;
-11692;TAKRI LETTER JHA;Lo;0;L;;;;;N;;;;;
-11693;TAKRI LETTER NYA;Lo;0;L;;;;;N;;;;;
-11694;TAKRI LETTER TTA;Lo;0;L;;;;;N;;;;;
-11695;TAKRI LETTER TTHA;Lo;0;L;;;;;N;;;;;
-11696;TAKRI LETTER DDA;Lo;0;L;;;;;N;;;;;
-11697;TAKRI LETTER DDHA;Lo;0;L;;;;;N;;;;;
-11698;TAKRI LETTER NNA;Lo;0;L;;;;;N;;;;;
-11699;TAKRI LETTER TA;Lo;0;L;;;;;N;;;;;
-1169A;TAKRI LETTER THA;Lo;0;L;;;;;N;;;;;
-1169B;TAKRI LETTER DA;Lo;0;L;;;;;N;;;;;
-1169C;TAKRI LETTER DHA;Lo;0;L;;;;;N;;;;;
-1169D;TAKRI LETTER NA;Lo;0;L;;;;;N;;;;;
-1169E;TAKRI LETTER PA;Lo;0;L;;;;;N;;;;;
-1169F;TAKRI LETTER PHA;Lo;0;L;;;;;N;;;;;
-116A0;TAKRI LETTER BA;Lo;0;L;;;;;N;;;;;
-116A1;TAKRI LETTER BHA;Lo;0;L;;;;;N;;;;;
-116A2;TAKRI LETTER MA;Lo;0;L;;;;;N;;;;;
-116A3;TAKRI LETTER YA;Lo;0;L;;;;;N;;;;;
-116A4;TAKRI LETTER RA;Lo;0;L;;;;;N;;;;;
-116A5;TAKRI LETTER LA;Lo;0;L;;;;;N;;;;;
-116A6;TAKRI LETTER VA;Lo;0;L;;;;;N;;;;;
-116A7;TAKRI LETTER SHA;Lo;0;L;;;;;N;;;;;
-116A8;TAKRI LETTER SA;Lo;0;L;;;;;N;;;;;
-116A9;TAKRI LETTER HA;Lo;0;L;;;;;N;;;;;
-116AA;TAKRI LETTER RRA;Lo;0;L;;;;;N;;;;;
-116AB;TAKRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
-116AC;TAKRI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
-116AD;TAKRI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;;
-116AE;TAKRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-116AF;TAKRI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-116B0;TAKRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-116B1;TAKRI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
-116B2;TAKRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
-116B3;TAKRI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
-116B4;TAKRI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
-116B5;TAKRI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
-116B6;TAKRI SIGN VIRAMA;Mc;9;L;;;;;N;;;;;
-116B7;TAKRI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
-116C0;TAKRI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
-116C1;TAKRI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
-116C2;TAKRI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
-116C3;TAKRI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
-116C4;TAKRI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
-116C5;TAKRI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
-116C6;TAKRI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
-116C7;TAKRI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
-116C8;TAKRI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
-116C9;TAKRI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
-12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;;
-12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;;
-12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;;
-12003;CUNEIFORM SIGN A TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-12004;CUNEIFORM SIGN A TIMES HA;Lo;0;L;;;;;N;;;;;
-12005;CUNEIFORM SIGN A TIMES IGI;Lo;0;L;;;;;N;;;;;
-12006;CUNEIFORM SIGN A TIMES LAGAR GUNU;Lo;0;L;;;;;N;;;;;
-12007;CUNEIFORM SIGN A TIMES MUSH;Lo;0;L;;;;;N;;;;;
-12008;CUNEIFORM SIGN A TIMES SAG;Lo;0;L;;;;;N;;;;;
-12009;CUNEIFORM SIGN A2;Lo;0;L;;;;;N;;;;;
-1200A;CUNEIFORM SIGN AB;Lo;0;L;;;;;N;;;;;
-1200B;CUNEIFORM SIGN AB TIMES ASH2;Lo;0;L;;;;;N;;;;;
-1200C;CUNEIFORM SIGN AB TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;;
-1200D;CUNEIFORM SIGN AB TIMES GAL;Lo;0;L;;;;;N;;;;;
-1200E;CUNEIFORM SIGN AB TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-1200F;CUNEIFORM SIGN AB TIMES HA;Lo;0;L;;;;;N;;;;;
-12010;CUNEIFORM SIGN AB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-12011;CUNEIFORM SIGN AB TIMES IMIN;Lo;0;L;;;;;N;;;;;
-12012;CUNEIFORM SIGN AB TIMES LAGAB;Lo;0;L;;;;;N;;;;;
-12013;CUNEIFORM SIGN AB TIMES SHESH;Lo;0;L;;;;;N;;;;;
-12014;CUNEIFORM SIGN AB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;;
-12015;CUNEIFORM SIGN AB GUNU;Lo;0;L;;;;;N;;;;;
-12016;CUNEIFORM SIGN AB2;Lo;0;L;;;;;N;;;;;
-12017;CUNEIFORM SIGN AB2 TIMES BALAG;Lo;0;L;;;;;N;;;;;
-12018;CUNEIFORM SIGN AB2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-12019;CUNEIFORM SIGN AB2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;;
-1201A;CUNEIFORM SIGN AB2 TIMES SHA3;Lo;0;L;;;;;N;;;;;
-1201B;CUNEIFORM SIGN AB2 TIMES TAK4;Lo;0;L;;;;;N;;;;;
-1201C;CUNEIFORM SIGN AD;Lo;0;L;;;;;N;;;;;
-1201D;CUNEIFORM SIGN AK;Lo;0;L;;;;;N;;;;;
-1201E;CUNEIFORM SIGN AK TIMES ERIN2;Lo;0;L;;;;;N;;;;;
-1201F;CUNEIFORM SIGN AK TIMES SHITA PLUS GISH;Lo;0;L;;;;;N;;;;;
-12020;CUNEIFORM SIGN AL;Lo;0;L;;;;;N;;;;;
-12021;CUNEIFORM SIGN AL TIMES AL;Lo;0;L;;;;;N;;;;;
-12022;CUNEIFORM SIGN AL TIMES DIM2;Lo;0;L;;;;;N;;;;;
-12023;CUNEIFORM SIGN AL TIMES GISH;Lo;0;L;;;;;N;;;;;
-12024;CUNEIFORM SIGN AL TIMES HA;Lo;0;L;;;;;N;;;;;
-12025;CUNEIFORM SIGN AL TIMES KAD3;Lo;0;L;;;;;N;;;;;
-12026;CUNEIFORM SIGN AL TIMES KI;Lo;0;L;;;;;N;;;;;
-12027;CUNEIFORM SIGN AL TIMES SHE;Lo;0;L;;;;;N;;;;;
-12028;CUNEIFORM SIGN AL TIMES USH;Lo;0;L;;;;;N;;;;;
-12029;CUNEIFORM SIGN ALAN;Lo;0;L;;;;;N;;;;;
-1202A;CUNEIFORM SIGN ALEPH;Lo;0;L;;;;;N;;;;;
-1202B;CUNEIFORM SIGN AMAR;Lo;0;L;;;;;N;;;;;
-1202C;CUNEIFORM SIGN AMAR TIMES SHE;Lo;0;L;;;;;N;;;;;
-1202D;CUNEIFORM SIGN AN;Lo;0;L;;;;;N;;;;;
-1202E;CUNEIFORM SIGN AN OVER AN;Lo;0;L;;;;;N;;;;;
-1202F;CUNEIFORM SIGN AN THREE TIMES;Lo;0;L;;;;;N;;;;;
-12030;CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA;Lo;0;L;;;;;N;;;;;
-12031;CUNEIFORM SIGN AN PLUS NAGA SQUARED;Lo;0;L;;;;;N;;;;;
-12032;CUNEIFORM SIGN ANSHE;Lo;0;L;;;;;N;;;;;
-12033;CUNEIFORM SIGN APIN;Lo;0;L;;;;;N;;;;;
-12034;CUNEIFORM SIGN ARAD;Lo;0;L;;;;;N;;;;;
-12035;CUNEIFORM SIGN ARAD TIMES KUR;Lo;0;L;;;;;N;;;;;
-12036;CUNEIFORM SIGN ARKAB;Lo;0;L;;;;;N;;;;;
-12037;CUNEIFORM SIGN ASAL2;Lo;0;L;;;;;N;;;;;
-12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;;N;;;;;
-12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;;N;;;;;
-1203A;CUNEIFORM SIGN ASH KABA TENU;Lo;0;L;;;;;N;;;;;
-1203B;CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP;Lo;0;L;;;;;N;;;;;
-1203C;CUNEIFORM SIGN ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;;
-1203D;CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;;
-1203E;CUNEIFORM SIGN ASH2;Lo;0;L;;;;;N;;;;;
-1203F;CUNEIFORM SIGN ASHGAB;Lo;0;L;;;;;N;;;;;
-12040;CUNEIFORM SIGN BA;Lo;0;L;;;;;N;;;;;
-12041;CUNEIFORM SIGN BAD;Lo;0;L;;;;;N;;;;;
-12042;CUNEIFORM SIGN BAG3;Lo;0;L;;;;;N;;;;;
-12043;CUNEIFORM SIGN BAHAR2;Lo;0;L;;;;;N;;;;;
-12044;CUNEIFORM SIGN BAL;Lo;0;L;;;;;N;;;;;
-12045;CUNEIFORM SIGN BAL OVER BAL;Lo;0;L;;;;;N;;;;;
-12046;CUNEIFORM SIGN BALAG;Lo;0;L;;;;;N;;;;;
-12047;CUNEIFORM SIGN BAR;Lo;0;L;;;;;N;;;;;
-12048;CUNEIFORM SIGN BARA2;Lo;0;L;;;;;N;;;;;
-12049;CUNEIFORM SIGN BI;Lo;0;L;;;;;N;;;;;
-1204A;CUNEIFORM SIGN BI TIMES A;Lo;0;L;;;;;N;;;;;
-1204B;CUNEIFORM SIGN BI TIMES GAR;Lo;0;L;;;;;N;;;;;
-1204C;CUNEIFORM SIGN BI TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-1204D;CUNEIFORM SIGN BU;Lo;0;L;;;;;N;;;;;
-1204E;CUNEIFORM SIGN BU OVER BU AB;Lo;0;L;;;;;N;;;;;
-1204F;CUNEIFORM SIGN BU OVER BU UN;Lo;0;L;;;;;N;;;;;
-12050;CUNEIFORM SIGN BU CROSSING BU;Lo;0;L;;;;;N;;;;;
-12051;CUNEIFORM SIGN BULUG;Lo;0;L;;;;;N;;;;;
-12052;CUNEIFORM SIGN BULUG OVER BULUG;Lo;0;L;;;;;N;;;;;
-12053;CUNEIFORM SIGN BUR;Lo;0;L;;;;;N;;;;;
-12054;CUNEIFORM SIGN BUR2;Lo;0;L;;;;;N;;;;;
-12055;CUNEIFORM SIGN DA;Lo;0;L;;;;;N;;;;;
-12056;CUNEIFORM SIGN DAG;Lo;0;L;;;;;N;;;;;
-12057;CUNEIFORM SIGN DAG KISIM5 TIMES A PLUS MASH;Lo;0;L;;;;;N;;;;;
-12058;CUNEIFORM SIGN DAG KISIM5 TIMES AMAR;Lo;0;L;;;;;N;;;;;
-12059;CUNEIFORM SIGN DAG KISIM5 TIMES BALAG;Lo;0;L;;;;;N;;;;;
-1205A;CUNEIFORM SIGN DAG KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;;
-1205B;CUNEIFORM SIGN DAG KISIM5 TIMES GA;Lo;0;L;;;;;N;;;;;
-1205C;CUNEIFORM SIGN DAG KISIM5 TIMES GA PLUS MASH;Lo;0;L;;;;;N;;;;;
-1205D;CUNEIFORM SIGN DAG KISIM5 TIMES GI;Lo;0;L;;;;;N;;;;;
-1205E;CUNEIFORM SIGN DAG KISIM5 TIMES GIR2;Lo;0;L;;;;;N;;;;;
-1205F;CUNEIFORM SIGN DAG KISIM5 TIMES GUD;Lo;0;L;;;;;N;;;;;
-12060;CUNEIFORM SIGN DAG KISIM5 TIMES HA;Lo;0;L;;;;;N;;;;;
-12061;CUNEIFORM SIGN DAG KISIM5 TIMES IR;Lo;0;L;;;;;N;;;;;
-12062;CUNEIFORM SIGN DAG KISIM5 TIMES IR PLUS LU;Lo;0;L;;;;;N;;;;;
-12063;CUNEIFORM SIGN DAG KISIM5 TIMES KAK;Lo;0;L;;;;;N;;;;;
-12064;CUNEIFORM SIGN DAG KISIM5 TIMES LA;Lo;0;L;;;;;N;;;;;
-12065;CUNEIFORM SIGN DAG KISIM5 TIMES LU;Lo;0;L;;;;;N;;;;;
-12066;CUNEIFORM SIGN DAG KISIM5 TIMES LU PLUS MASH2;Lo;0;L;;;;;N;;;;;
-12067;CUNEIFORM SIGN DAG KISIM5 TIMES LUM;Lo;0;L;;;;;N;;;;;
-12068;CUNEIFORM SIGN DAG KISIM5 TIMES NE;Lo;0;L;;;;;N;;;;;
-12069;CUNEIFORM SIGN DAG KISIM5 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;;
-1206A;CUNEIFORM SIGN DAG KISIM5 TIMES SI;Lo;0;L;;;;;N;;;;;
-1206B;CUNEIFORM SIGN DAG KISIM5 TIMES TAK4;Lo;0;L;;;;;N;;;;;
-1206C;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS GIR2;Lo;0;L;;;;;N;;;;;
-1206D;CUNEIFORM SIGN DAG KISIM5 TIMES USH;Lo;0;L;;;;;N;;;;;
-1206E;CUNEIFORM SIGN DAM;Lo;0;L;;;;;N;;;;;
-1206F;CUNEIFORM SIGN DAR;Lo;0;L;;;;;N;;;;;
-12070;CUNEIFORM SIGN DARA3;Lo;0;L;;;;;N;;;;;
-12071;CUNEIFORM SIGN DARA4;Lo;0;L;;;;;N;;;;;
-12072;CUNEIFORM SIGN DI;Lo;0;L;;;;;N;;;;;
-12073;CUNEIFORM SIGN DIB;Lo;0;L;;;;;N;;;;;
-12074;CUNEIFORM SIGN DIM;Lo;0;L;;;;;N;;;;;
-12075;CUNEIFORM SIGN DIM TIMES SHE;Lo;0;L;;;;;N;;;;;
-12076;CUNEIFORM SIGN DIM2;Lo;0;L;;;;;N;;;;;
-12077;CUNEIFORM SIGN DIN;Lo;0;L;;;;;N;;;;;
-12078;CUNEIFORM SIGN DIN KASKAL U GUNU DISH;Lo;0;L;;;;;N;;;;;
-12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;;N;;;;;
-1207A;CUNEIFORM SIGN DU;Lo;0;L;;;;;N;;;;;
-1207B;CUNEIFORM SIGN DU OVER DU;Lo;0;L;;;;;N;;;;;
-1207C;CUNEIFORM SIGN DU GUNU;Lo;0;L;;;;;N;;;;;
-1207D;CUNEIFORM SIGN DU SHESHIG;Lo;0;L;;;;;N;;;;;
-1207E;CUNEIFORM SIGN DUB;Lo;0;L;;;;;N;;;;;
-1207F;CUNEIFORM SIGN DUB TIMES ESH2;Lo;0;L;;;;;N;;;;;
-12080;CUNEIFORM SIGN DUB2;Lo;0;L;;;;;N;;;;;
-12081;CUNEIFORM SIGN DUG;Lo;0;L;;;;;N;;;;;
-12082;CUNEIFORM SIGN DUGUD;Lo;0;L;;;;;N;;;;;
-12083;CUNEIFORM SIGN DUH;Lo;0;L;;;;;N;;;;;
-12084;CUNEIFORM SIGN DUN;Lo;0;L;;;;;N;;;;;
-12085;CUNEIFORM SIGN DUN3;Lo;0;L;;;;;N;;;;;
-12086;CUNEIFORM SIGN DUN3 GUNU;Lo;0;L;;;;;N;;;;;
-12087;CUNEIFORM SIGN DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;;
-12088;CUNEIFORM SIGN DUN4;Lo;0;L;;;;;N;;;;;
-12089;CUNEIFORM SIGN DUR2;Lo;0;L;;;;;N;;;;;
-1208A;CUNEIFORM SIGN E;Lo;0;L;;;;;N;;;;;
-1208B;CUNEIFORM SIGN E TIMES PAP;Lo;0;L;;;;;N;;;;;
-1208C;CUNEIFORM SIGN E OVER E NUN OVER NUN;Lo;0;L;;;;;N;;;;;
-1208D;CUNEIFORM SIGN E2;Lo;0;L;;;;;N;;;;;
-1208E;CUNEIFORM SIGN E2 TIMES A PLUS HA PLUS DA;Lo;0;L;;;;;N;;;;;
-1208F;CUNEIFORM SIGN E2 TIMES GAR;Lo;0;L;;;;;N;;;;;
-12090;CUNEIFORM SIGN E2 TIMES MI;Lo;0;L;;;;;N;;;;;
-12091;CUNEIFORM SIGN E2 TIMES SAL;Lo;0;L;;;;;N;;;;;
-12092;CUNEIFORM SIGN E2 TIMES SHE;Lo;0;L;;;;;N;;;;;
-12093;CUNEIFORM SIGN E2 TIMES U;Lo;0;L;;;;;N;;;;;
-12094;CUNEIFORM SIGN EDIN;Lo;0;L;;;;;N;;;;;
-12095;CUNEIFORM SIGN EGIR;Lo;0;L;;;;;N;;;;;
-12096;CUNEIFORM SIGN EL;Lo;0;L;;;;;N;;;;;
-12097;CUNEIFORM SIGN EN;Lo;0;L;;;;;N;;;;;
-12098;CUNEIFORM SIGN EN TIMES GAN2;Lo;0;L;;;;;N;;;;;
-12099;CUNEIFORM SIGN EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-1209A;CUNEIFORM SIGN EN TIMES ME;Lo;0;L;;;;;N;;;;;
-1209B;CUNEIFORM SIGN EN CROSSING EN;Lo;0;L;;;;;N;;;;;
-1209C;CUNEIFORM SIGN EN OPPOSING EN;Lo;0;L;;;;;N;;;;;
-1209D;CUNEIFORM SIGN EN SQUARED;Lo;0;L;;;;;N;;;;;
-1209E;CUNEIFORM SIGN EREN;Lo;0;L;;;;;N;;;;;
-1209F;CUNEIFORM SIGN ERIN2;Lo;0;L;;;;;N;;;;;
-120A0;CUNEIFORM SIGN ESH2;Lo;0;L;;;;;N;;;;;
-120A1;CUNEIFORM SIGN EZEN;Lo;0;L;;;;;N;;;;;
-120A2;CUNEIFORM SIGN EZEN TIMES A;Lo;0;L;;;;;N;;;;;
-120A3;CUNEIFORM SIGN EZEN TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;;
-120A4;CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL;Lo;0;L;;;;;N;;;;;
-120A5;CUNEIFORM SIGN EZEN TIMES AN;Lo;0;L;;;;;N;;;;;
-120A6;CUNEIFORM SIGN EZEN TIMES BAD;Lo;0;L;;;;;N;;;;;
-120A7;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;;
-120A8;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;;
-120A9;CUNEIFORM SIGN EZEN TIMES HA;Lo;0;L;;;;;N;;;;;
-120AA;CUNEIFORM SIGN EZEN TIMES HA GUNU;Lo;0;L;;;;;N;;;;;
-120AB;CUNEIFORM SIGN EZEN TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-120AC;CUNEIFORM SIGN EZEN TIMES KASKAL;Lo;0;L;;;;;N;;;;;
-120AD;CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED;Lo;0;L;;;;;N;;;;;
-120AE;CUNEIFORM SIGN EZEN TIMES KU3;Lo;0;L;;;;;N;;;;;
-120AF;CUNEIFORM SIGN EZEN TIMES LA;Lo;0;L;;;;;N;;;;;
-120B0;CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL;Lo;0;L;;;;;N;;;;;
-120B1;CUNEIFORM SIGN EZEN TIMES LI;Lo;0;L;;;;;N;;;;;
-120B2;CUNEIFORM SIGN EZEN TIMES LU;Lo;0;L;;;;;N;;;;;
-120B3;CUNEIFORM SIGN EZEN TIMES U2;Lo;0;L;;;;;N;;;;;
-120B4;CUNEIFORM SIGN EZEN TIMES UD;Lo;0;L;;;;;N;;;;;
-120B5;CUNEIFORM SIGN GA;Lo;0;L;;;;;N;;;;;
-120B6;CUNEIFORM SIGN GA GUNU;Lo;0;L;;;;;N;;;;;
-120B7;CUNEIFORM SIGN GA2;Lo;0;L;;;;;N;;;;;
-120B8;CUNEIFORM SIGN GA2 TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;;
-120B9;CUNEIFORM SIGN GA2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;;
-120BA;CUNEIFORM SIGN GA2 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;;
-120BB;CUNEIFORM SIGN GA2 TIMES AB2 TENU PLUS TAB;Lo;0;L;;;;;N;;;;;
-120BC;CUNEIFORM SIGN GA2 TIMES AN;Lo;0;L;;;;;N;;;;;
-120BD;CUNEIFORM SIGN GA2 TIMES ASH;Lo;0;L;;;;;N;;;;;
-120BE;CUNEIFORM SIGN GA2 TIMES ASH2 PLUS GAL;Lo;0;L;;;;;N;;;;;
-120BF;CUNEIFORM SIGN GA2 TIMES BAD;Lo;0;L;;;;;N;;;;;
-120C0;CUNEIFORM SIGN GA2 TIMES BAR PLUS RA;Lo;0;L;;;;;N;;;;;
-120C1;CUNEIFORM SIGN GA2 TIMES BUR;Lo;0;L;;;;;N;;;;;
-120C2;CUNEIFORM SIGN GA2 TIMES BUR PLUS RA;Lo;0;L;;;;;N;;;;;
-120C3;CUNEIFORM SIGN GA2 TIMES DA;Lo;0;L;;;;;N;;;;;
-120C4;CUNEIFORM SIGN GA2 TIMES DI;Lo;0;L;;;;;N;;;;;
-120C5;CUNEIFORM SIGN GA2 TIMES DIM TIMES SHE;Lo;0;L;;;;;N;;;;;
-120C6;CUNEIFORM SIGN GA2 TIMES DUB;Lo;0;L;;;;;N;;;;;
-120C7;CUNEIFORM SIGN GA2 TIMES EL;Lo;0;L;;;;;N;;;;;
-120C8;CUNEIFORM SIGN GA2 TIMES EL PLUS LA;Lo;0;L;;;;;N;;;;;
-120C9;CUNEIFORM SIGN GA2 TIMES EN;Lo;0;L;;;;;N;;;;;
-120CA;CUNEIFORM SIGN GA2 TIMES EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-120CB;CUNEIFORM SIGN GA2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-120CC;CUNEIFORM SIGN GA2 TIMES GAR;Lo;0;L;;;;;N;;;;;
-120CD;CUNEIFORM SIGN GA2 TIMES GI;Lo;0;L;;;;;N;;;;;
-120CE;CUNEIFORM SIGN GA2 TIMES GI4;Lo;0;L;;;;;N;;;;;
-120CF;CUNEIFORM SIGN GA2 TIMES GI4 PLUS A;Lo;0;L;;;;;N;;;;;
-120D0;CUNEIFORM SIGN GA2 TIMES GIR2 PLUS SU;Lo;0;L;;;;;N;;;;;
-120D1;CUNEIFORM SIGN GA2 TIMES HA PLUS LU PLUS ESH2;Lo;0;L;;;;;N;;;;;
-120D2;CUNEIFORM SIGN GA2 TIMES HAL;Lo;0;L;;;;;N;;;;;
-120D3;CUNEIFORM SIGN GA2 TIMES HAL PLUS LA;Lo;0;L;;;;;N;;;;;
-120D4;CUNEIFORM SIGN GA2 TIMES HI PLUS LI;Lo;0;L;;;;;N;;;;;
-120D5;CUNEIFORM SIGN GA2 TIMES HUB2;Lo;0;L;;;;;N;;;;;
-120D6;CUNEIFORM SIGN GA2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-120D7;CUNEIFORM SIGN GA2 TIMES ISH PLUS HU PLUS ASH;Lo;0;L;;;;;N;;;;;
-120D8;CUNEIFORM SIGN GA2 TIMES KAK;Lo;0;L;;;;;N;;;;;
-120D9;CUNEIFORM SIGN GA2 TIMES KASKAL;Lo;0;L;;;;;N;;;;;
-120DA;CUNEIFORM SIGN GA2 TIMES KID;Lo;0;L;;;;;N;;;;;
-120DB;CUNEIFORM SIGN GA2 TIMES KID PLUS LAL;Lo;0;L;;;;;N;;;;;
-120DC;CUNEIFORM SIGN GA2 TIMES KU3 PLUS AN;Lo;0;L;;;;;N;;;;;
-120DD;CUNEIFORM SIGN GA2 TIMES LA;Lo;0;L;;;;;N;;;;;
-120DE;CUNEIFORM SIGN GA2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;;
-120DF;CUNEIFORM SIGN GA2 TIMES MI;Lo;0;L;;;;;N;;;;;
-120E0;CUNEIFORM SIGN GA2 TIMES NUN;Lo;0;L;;;;;N;;;;;
-120E1;CUNEIFORM SIGN GA2 TIMES NUN OVER NUN;Lo;0;L;;;;;N;;;;;
-120E2;CUNEIFORM SIGN GA2 TIMES PA;Lo;0;L;;;;;N;;;;;
-120E3;CUNEIFORM SIGN GA2 TIMES SAL;Lo;0;L;;;;;N;;;;;
-120E4;CUNEIFORM SIGN GA2 TIMES SAR;Lo;0;L;;;;;N;;;;;
-120E5;CUNEIFORM SIGN GA2 TIMES SHE;Lo;0;L;;;;;N;;;;;
-120E6;CUNEIFORM SIGN GA2 TIMES SHE PLUS TUR;Lo;0;L;;;;;N;;;;;
-120E7;CUNEIFORM SIGN GA2 TIMES SHID;Lo;0;L;;;;;N;;;;;
-120E8;CUNEIFORM SIGN GA2 TIMES SUM;Lo;0;L;;;;;N;;;;;
-120E9;CUNEIFORM SIGN GA2 TIMES TAK4;Lo;0;L;;;;;N;;;;;
-120EA;CUNEIFORM SIGN GA2 TIMES U;Lo;0;L;;;;;N;;;;;
-120EB;CUNEIFORM SIGN GA2 TIMES UD;Lo;0;L;;;;;N;;;;;
-120EC;CUNEIFORM SIGN GA2 TIMES UD PLUS DU;Lo;0;L;;;;;N;;;;;
-120ED;CUNEIFORM SIGN GA2 OVER GA2;Lo;0;L;;;;;N;;;;;
-120EE;CUNEIFORM SIGN GABA;Lo;0;L;;;;;N;;;;;
-120EF;CUNEIFORM SIGN GABA CROSSING GABA;Lo;0;L;;;;;N;;;;;
-120F0;CUNEIFORM SIGN GAD;Lo;0;L;;;;;N;;;;;
-120F1;CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;;
-120F2;CUNEIFORM SIGN GAL;Lo;0;L;;;;;N;;;;;
-120F3;CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;;
-120F4;CUNEIFORM SIGN GALAM;Lo;0;L;;;;;N;;;;;
-120F5;CUNEIFORM SIGN GAM;Lo;0;L;;;;;N;;;;;
-120F6;CUNEIFORM SIGN GAN;Lo;0;L;;;;;N;;;;;
-120F7;CUNEIFORM SIGN GAN2;Lo;0;L;;;;;N;;;;;
-120F8;CUNEIFORM SIGN GAN2 TENU;Lo;0;L;;;;;N;;;;;
-120F9;CUNEIFORM SIGN GAN2 OVER GAN2;Lo;0;L;;;;;N;;;;;
-120FA;CUNEIFORM SIGN GAN2 CROSSING GAN2;Lo;0;L;;;;;N;;;;;
-120FB;CUNEIFORM SIGN GAR;Lo;0;L;;;;;N;;;;;
-120FC;CUNEIFORM SIGN GAR3;Lo;0;L;;;;;N;;;;;
-120FD;CUNEIFORM SIGN GASHAN;Lo;0;L;;;;;N;;;;;
-120FE;CUNEIFORM SIGN GESHTIN;Lo;0;L;;;;;N;;;;;
-120FF;CUNEIFORM SIGN GESHTIN TIMES KUR;Lo;0;L;;;;;N;;;;;
-12100;CUNEIFORM SIGN GI;Lo;0;L;;;;;N;;;;;
-12101;CUNEIFORM SIGN GI TIMES E;Lo;0;L;;;;;N;;;;;
-12102;CUNEIFORM SIGN GI TIMES U;Lo;0;L;;;;;N;;;;;
-12103;CUNEIFORM SIGN GI CROSSING GI;Lo;0;L;;;;;N;;;;;
-12104;CUNEIFORM SIGN GI4;Lo;0;L;;;;;N;;;;;
-12105;CUNEIFORM SIGN GI4 OVER GI4;Lo;0;L;;;;;N;;;;;
-12106;CUNEIFORM SIGN GI4 CROSSING GI4;Lo;0;L;;;;;N;;;;;
-12107;CUNEIFORM SIGN GIDIM;Lo;0;L;;;;;N;;;;;
-12108;CUNEIFORM SIGN GIR2;Lo;0;L;;;;;N;;;;;
-12109;CUNEIFORM SIGN GIR2 GUNU;Lo;0;L;;;;;N;;;;;
-1210A;CUNEIFORM SIGN GIR3;Lo;0;L;;;;;N;;;;;
-1210B;CUNEIFORM SIGN GIR3 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;;
-1210C;CUNEIFORM SIGN GIR3 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-1210D;CUNEIFORM SIGN GIR3 TIMES IGI;Lo;0;L;;;;;N;;;;;
-1210E;CUNEIFORM SIGN GIR3 TIMES LU PLUS IGI;Lo;0;L;;;;;N;;;;;
-1210F;CUNEIFORM SIGN GIR3 TIMES PA;Lo;0;L;;;;;N;;;;;
-12110;CUNEIFORM SIGN GISAL;Lo;0;L;;;;;N;;;;;
-12111;CUNEIFORM SIGN GISH;Lo;0;L;;;;;N;;;;;
-12112;CUNEIFORM SIGN GISH CROSSING GISH;Lo;0;L;;;;;N;;;;;
-12113;CUNEIFORM SIGN GISH TIMES BAD;Lo;0;L;;;;;N;;;;;
-12114;CUNEIFORM SIGN GISH TIMES TAK4;Lo;0;L;;;;;N;;;;;
-12115;CUNEIFORM SIGN GISH TENU;Lo;0;L;;;;;N;;;;;
-12116;CUNEIFORM SIGN GU;Lo;0;L;;;;;N;;;;;
-12117;CUNEIFORM SIGN GU CROSSING GU;Lo;0;L;;;;;N;;;;;
-12118;CUNEIFORM SIGN GU2;Lo;0;L;;;;;N;;;;;
-12119;CUNEIFORM SIGN GU2 TIMES KAK;Lo;0;L;;;;;N;;;;;
-1211A;CUNEIFORM SIGN GU2 TIMES KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-1211B;CUNEIFORM SIGN GU2 TIMES NUN;Lo;0;L;;;;;N;;;;;
-1211C;CUNEIFORM SIGN GU2 TIMES SAL PLUS TUG2;Lo;0;L;;;;;N;;;;;
-1211D;CUNEIFORM SIGN GU2 GUNU;Lo;0;L;;;;;N;;;;;
-1211E;CUNEIFORM SIGN GUD;Lo;0;L;;;;;N;;;;;
-1211F;CUNEIFORM SIGN GUD TIMES A PLUS KUR;Lo;0;L;;;;;N;;;;;
-12120;CUNEIFORM SIGN GUD TIMES KUR;Lo;0;L;;;;;N;;;;;
-12121;CUNEIFORM SIGN GUD OVER GUD LUGAL;Lo;0;L;;;;;N;;;;;
-12122;CUNEIFORM SIGN GUL;Lo;0;L;;;;;N;;;;;
-12123;CUNEIFORM SIGN GUM;Lo;0;L;;;;;N;;;;;
-12124;CUNEIFORM SIGN GUM TIMES SHE;Lo;0;L;;;;;N;;;;;
-12125;CUNEIFORM SIGN GUR;Lo;0;L;;;;;N;;;;;
-12126;CUNEIFORM SIGN GUR7;Lo;0;L;;;;;N;;;;;
-12127;CUNEIFORM SIGN GURUN;Lo;0;L;;;;;N;;;;;
-12128;CUNEIFORM SIGN GURUSH;Lo;0;L;;;;;N;;;;;
-12129;CUNEIFORM SIGN HA;Lo;0;L;;;;;N;;;;;
-1212A;CUNEIFORM SIGN HA TENU;Lo;0;L;;;;;N;;;;;
-1212B;CUNEIFORM SIGN HA GUNU;Lo;0;L;;;;;N;;;;;
-1212C;CUNEIFORM SIGN HAL;Lo;0;L;;;;;N;;;;;
-1212D;CUNEIFORM SIGN HI;Lo;0;L;;;;;N;;;;;
-1212E;CUNEIFORM SIGN HI TIMES ASH;Lo;0;L;;;;;N;;;;;
-1212F;CUNEIFORM SIGN HI TIMES ASH2;Lo;0;L;;;;;N;;;;;
-12130;CUNEIFORM SIGN HI TIMES BAD;Lo;0;L;;;;;N;;;;;
-12131;CUNEIFORM SIGN HI TIMES DISH;Lo;0;L;;;;;N;;;;;
-12132;CUNEIFORM SIGN HI TIMES GAD;Lo;0;L;;;;;N;;;;;
-12133;CUNEIFORM SIGN HI TIMES KIN;Lo;0;L;;;;;N;;;;;
-12134;CUNEIFORM SIGN HI TIMES NUN;Lo;0;L;;;;;N;;;;;
-12135;CUNEIFORM SIGN HI TIMES SHE;Lo;0;L;;;;;N;;;;;
-12136;CUNEIFORM SIGN HI TIMES U;Lo;0;L;;;;;N;;;;;
-12137;CUNEIFORM SIGN HU;Lo;0;L;;;;;N;;;;;
-12138;CUNEIFORM SIGN HUB2;Lo;0;L;;;;;N;;;;;
-12139;CUNEIFORM SIGN HUB2 TIMES AN;Lo;0;L;;;;;N;;;;;
-1213A;CUNEIFORM SIGN HUB2 TIMES HAL;Lo;0;L;;;;;N;;;;;
-1213B;CUNEIFORM SIGN HUB2 TIMES KASKAL;Lo;0;L;;;;;N;;;;;
-1213C;CUNEIFORM SIGN HUB2 TIMES LISH;Lo;0;L;;;;;N;;;;;
-1213D;CUNEIFORM SIGN HUB2 TIMES UD;Lo;0;L;;;;;N;;;;;
-1213E;CUNEIFORM SIGN HUL2;Lo;0;L;;;;;N;;;;;
-1213F;CUNEIFORM SIGN I;Lo;0;L;;;;;N;;;;;
-12140;CUNEIFORM SIGN I A;Lo;0;L;;;;;N;;;;;
-12141;CUNEIFORM SIGN IB;Lo;0;L;;;;;N;;;;;
-12142;CUNEIFORM SIGN IDIM;Lo;0;L;;;;;N;;;;;
-12143;CUNEIFORM SIGN IDIM OVER IDIM BUR;Lo;0;L;;;;;N;;;;;
-12144;CUNEIFORM SIGN IDIM OVER IDIM SQUARED;Lo;0;L;;;;;N;;;;;
-12145;CUNEIFORM SIGN IG;Lo;0;L;;;;;N;;;;;
-12146;CUNEIFORM SIGN IGI;Lo;0;L;;;;;N;;;;;
-12147;CUNEIFORM SIGN IGI DIB;Lo;0;L;;;;;N;;;;;
-12148;CUNEIFORM SIGN IGI RI;Lo;0;L;;;;;N;;;;;
-12149;CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD;Lo;0;L;;;;;N;;;;;
-1214A;CUNEIFORM SIGN IGI GUNU;Lo;0;L;;;;;N;;;;;
-1214B;CUNEIFORM SIGN IL;Lo;0;L;;;;;N;;;;;
-1214C;CUNEIFORM SIGN IL TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-1214D;CUNEIFORM SIGN IL2;Lo;0;L;;;;;N;;;;;
-1214E;CUNEIFORM SIGN IM;Lo;0;L;;;;;N;;;;;
-1214F;CUNEIFORM SIGN IM TIMES TAK4;Lo;0;L;;;;;N;;;;;
-12150;CUNEIFORM SIGN IM CROSSING IM;Lo;0;L;;;;;N;;;;;
-12151;CUNEIFORM SIGN IM OPPOSING IM;Lo;0;L;;;;;N;;;;;
-12152;CUNEIFORM SIGN IM SQUARED;Lo;0;L;;;;;N;;;;;
-12153;CUNEIFORM SIGN IMIN;Lo;0;L;;;;;N;;;;;
-12154;CUNEIFORM SIGN IN;Lo;0;L;;;;;N;;;;;
-12155;CUNEIFORM SIGN IR;Lo;0;L;;;;;N;;;;;
-12156;CUNEIFORM SIGN ISH;Lo;0;L;;;;;N;;;;;
-12157;CUNEIFORM SIGN KA;Lo;0;L;;;;;N;;;;;
-12158;CUNEIFORM SIGN KA TIMES A;Lo;0;L;;;;;N;;;;;
-12159;CUNEIFORM SIGN KA TIMES AD;Lo;0;L;;;;;N;;;;;
-1215A;CUNEIFORM SIGN KA TIMES AD PLUS KU3;Lo;0;L;;;;;N;;;;;
-1215B;CUNEIFORM SIGN KA TIMES ASH2;Lo;0;L;;;;;N;;;;;
-1215C;CUNEIFORM SIGN KA TIMES BAD;Lo;0;L;;;;;N;;;;;
-1215D;CUNEIFORM SIGN KA TIMES BALAG;Lo;0;L;;;;;N;;;;;
-1215E;CUNEIFORM SIGN KA TIMES BAR;Lo;0;L;;;;;N;;;;;
-1215F;CUNEIFORM SIGN KA TIMES BI;Lo;0;L;;;;;N;;;;;
-12160;CUNEIFORM SIGN KA TIMES ERIN2;Lo;0;L;;;;;N;;;;;
-12161;CUNEIFORM SIGN KA TIMES ESH2;Lo;0;L;;;;;N;;;;;
-12162;CUNEIFORM SIGN KA TIMES GA;Lo;0;L;;;;;N;;;;;
-12163;CUNEIFORM SIGN KA TIMES GAL;Lo;0;L;;;;;N;;;;;
-12164;CUNEIFORM SIGN KA TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-12165;CUNEIFORM SIGN KA TIMES GAR;Lo;0;L;;;;;N;;;;;
-12166;CUNEIFORM SIGN KA TIMES GAR PLUS SHA3 PLUS A;Lo;0;L;;;;;N;;;;;
-12167;CUNEIFORM SIGN KA TIMES GI;Lo;0;L;;;;;N;;;;;
-12168;CUNEIFORM SIGN KA TIMES GIR2;Lo;0;L;;;;;N;;;;;
-12169;CUNEIFORM SIGN KA TIMES GISH PLUS SAR;Lo;0;L;;;;;N;;;;;
-1216A;CUNEIFORM SIGN KA TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;;
-1216B;CUNEIFORM SIGN KA TIMES GU;Lo;0;L;;;;;N;;;;;
-1216C;CUNEIFORM SIGN KA TIMES GUR7;Lo;0;L;;;;;N;;;;;
-1216D;CUNEIFORM SIGN KA TIMES IGI;Lo;0;L;;;;;N;;;;;
-1216E;CUNEIFORM SIGN KA TIMES IM;Lo;0;L;;;;;N;;;;;
-1216F;CUNEIFORM SIGN KA TIMES KAK;Lo;0;L;;;;;N;;;;;
-12170;CUNEIFORM SIGN KA TIMES KI;Lo;0;L;;;;;N;;;;;
-12171;CUNEIFORM SIGN KA TIMES KID;Lo;0;L;;;;;N;;;;;
-12172;CUNEIFORM SIGN KA TIMES LI;Lo;0;L;;;;;N;;;;;
-12173;CUNEIFORM SIGN KA TIMES LU;Lo;0;L;;;;;N;;;;;
-12174;CUNEIFORM SIGN KA TIMES ME;Lo;0;L;;;;;N;;;;;
-12175;CUNEIFORM SIGN KA TIMES ME PLUS DU;Lo;0;L;;;;;N;;;;;
-12176;CUNEIFORM SIGN KA TIMES ME PLUS GI;Lo;0;L;;;;;N;;;;;
-12177;CUNEIFORM SIGN KA TIMES ME PLUS TE;Lo;0;L;;;;;N;;;;;
-12178;CUNEIFORM SIGN KA TIMES MI;Lo;0;L;;;;;N;;;;;
-12179;CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ;Lo;0;L;;;;;N;;;;;
-1217A;CUNEIFORM SIGN KA TIMES NE;Lo;0;L;;;;;N;;;;;
-1217B;CUNEIFORM SIGN KA TIMES NUN;Lo;0;L;;;;;N;;;;;
-1217C;CUNEIFORM SIGN KA TIMES PI;Lo;0;L;;;;;N;;;;;
-1217D;CUNEIFORM SIGN KA TIMES RU;Lo;0;L;;;;;N;;;;;
-1217E;CUNEIFORM SIGN KA TIMES SA;Lo;0;L;;;;;N;;;;;
-1217F;CUNEIFORM SIGN KA TIMES SAR;Lo;0;L;;;;;N;;;;;
-12180;CUNEIFORM SIGN KA TIMES SHA;Lo;0;L;;;;;N;;;;;
-12181;CUNEIFORM SIGN KA TIMES SHE;Lo;0;L;;;;;N;;;;;
-12182;CUNEIFORM SIGN KA TIMES SHID;Lo;0;L;;;;;N;;;;;
-12183;CUNEIFORM SIGN KA TIMES SHU;Lo;0;L;;;;;N;;;;;
-12184;CUNEIFORM SIGN KA TIMES SIG;Lo;0;L;;;;;N;;;;;
-12185;CUNEIFORM SIGN KA TIMES SUHUR;Lo;0;L;;;;;N;;;;;
-12186;CUNEIFORM SIGN KA TIMES TAR;Lo;0;L;;;;;N;;;;;
-12187;CUNEIFORM SIGN KA TIMES U;Lo;0;L;;;;;N;;;;;
-12188;CUNEIFORM SIGN KA TIMES U2;Lo;0;L;;;;;N;;;;;
-12189;CUNEIFORM SIGN KA TIMES UD;Lo;0;L;;;;;N;;;;;
-1218A;CUNEIFORM SIGN KA TIMES UMUM TIMES PA;Lo;0;L;;;;;N;;;;;
-1218B;CUNEIFORM SIGN KA TIMES USH;Lo;0;L;;;;;N;;;;;
-1218C;CUNEIFORM SIGN KA TIMES ZI;Lo;0;L;;;;;N;;;;;
-1218D;CUNEIFORM SIGN KA2;Lo;0;L;;;;;N;;;;;
-1218E;CUNEIFORM SIGN KA2 CROSSING KA2;Lo;0;L;;;;;N;;;;;
-1218F;CUNEIFORM SIGN KAB;Lo;0;L;;;;;N;;;;;
-12190;CUNEIFORM SIGN KAD2;Lo;0;L;;;;;N;;;;;
-12191;CUNEIFORM SIGN KAD3;Lo;0;L;;;;;N;;;;;
-12192;CUNEIFORM SIGN KAD4;Lo;0;L;;;;;N;;;;;
-12193;CUNEIFORM SIGN KAD5;Lo;0;L;;;;;N;;;;;
-12194;CUNEIFORM SIGN KAD5 OVER KAD5;Lo;0;L;;;;;N;;;;;
-12195;CUNEIFORM SIGN KAK;Lo;0;L;;;;;N;;;;;
-12196;CUNEIFORM SIGN KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-12197;CUNEIFORM SIGN KAL;Lo;0;L;;;;;N;;;;;
-12198;CUNEIFORM SIGN KAL TIMES BAD;Lo;0;L;;;;;N;;;;;
-12199;CUNEIFORM SIGN KAL CROSSING KAL;Lo;0;L;;;;;N;;;;;
-1219A;CUNEIFORM SIGN KAM2;Lo;0;L;;;;;N;;;;;
-1219B;CUNEIFORM SIGN KAM4;Lo;0;L;;;;;N;;;;;
-1219C;CUNEIFORM SIGN KASKAL;Lo;0;L;;;;;N;;;;;
-1219D;CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;;
-1219E;CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;;
-1219F;CUNEIFORM SIGN KESH2;Lo;0;L;;;;;N;;;;;
-121A0;CUNEIFORM SIGN KI;Lo;0;L;;;;;N;;;;;
-121A1;CUNEIFORM SIGN KI TIMES BAD;Lo;0;L;;;;;N;;;;;
-121A2;CUNEIFORM SIGN KI TIMES U;Lo;0;L;;;;;N;;;;;
-121A3;CUNEIFORM SIGN KI TIMES UD;Lo;0;L;;;;;N;;;;;
-121A4;CUNEIFORM SIGN KID;Lo;0;L;;;;;N;;;;;
-121A5;CUNEIFORM SIGN KIN;Lo;0;L;;;;;N;;;;;
-121A6;CUNEIFORM SIGN KISAL;Lo;0;L;;;;;N;;;;;
-121A7;CUNEIFORM SIGN KISH;Lo;0;L;;;;;N;;;;;
-121A8;CUNEIFORM SIGN KISIM5;Lo;0;L;;;;;N;;;;;
-121A9;CUNEIFORM SIGN KISIM5 OVER KISIM5;Lo;0;L;;;;;N;;;;;
-121AA;CUNEIFORM SIGN KU;Lo;0;L;;;;;N;;;;;
-121AB;CUNEIFORM SIGN KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2;Lo;0;L;;;;;N;;;;;
-121AC;CUNEIFORM SIGN KU3;Lo;0;L;;;;;N;;;;;
-121AD;CUNEIFORM SIGN KU4;Lo;0;L;;;;;N;;;;;
-121AE;CUNEIFORM SIGN KU4 VARIANT FORM;Lo;0;L;;;;;N;;;;;
-121AF;CUNEIFORM SIGN KU7;Lo;0;L;;;;;N;;;;;
-121B0;CUNEIFORM SIGN KUL;Lo;0;L;;;;;N;;;;;
-121B1;CUNEIFORM SIGN KUL GUNU;Lo;0;L;;;;;N;;;;;
-121B2;CUNEIFORM SIGN KUN;Lo;0;L;;;;;N;;;;;
-121B3;CUNEIFORM SIGN KUR;Lo;0;L;;;;;N;;;;;
-121B4;CUNEIFORM SIGN KUR OPPOSING KUR;Lo;0;L;;;;;N;;;;;
-121B5;CUNEIFORM SIGN KUSHU2;Lo;0;L;;;;;N;;;;;
-121B6;CUNEIFORM SIGN KWU318;Lo;0;L;;;;;N;;;;;
-121B7;CUNEIFORM SIGN LA;Lo;0;L;;;;;N;;;;;
-121B8;CUNEIFORM SIGN LAGAB;Lo;0;L;;;;;N;;;;;
-121B9;CUNEIFORM SIGN LAGAB TIMES A;Lo;0;L;;;;;N;;;;;
-121BA;CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;;
-121BB;CUNEIFORM SIGN LAGAB TIMES A PLUS GAR;Lo;0;L;;;;;N;;;;;
-121BC;CUNEIFORM SIGN LAGAB TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;;
-121BD;CUNEIFORM SIGN LAGAB TIMES AL;Lo;0;L;;;;;N;;;;;
-121BE;CUNEIFORM SIGN LAGAB TIMES AN;Lo;0;L;;;;;N;;;;;
-121BF;CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU;Lo;0;L;;;;;N;;;;;
-121C0;CUNEIFORM SIGN LAGAB TIMES BAD;Lo;0;L;;;;;N;;;;;
-121C1;CUNEIFORM SIGN LAGAB TIMES BI;Lo;0;L;;;;;N;;;;;
-121C2;CUNEIFORM SIGN LAGAB TIMES DAR;Lo;0;L;;;;;N;;;;;
-121C3;CUNEIFORM SIGN LAGAB TIMES EN;Lo;0;L;;;;;N;;;;;
-121C4;CUNEIFORM SIGN LAGAB TIMES GA;Lo;0;L;;;;;N;;;;;
-121C5;CUNEIFORM SIGN LAGAB TIMES GAR;Lo;0;L;;;;;N;;;;;
-121C6;CUNEIFORM SIGN LAGAB TIMES GUD;Lo;0;L;;;;;N;;;;;
-121C7;CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD;Lo;0;L;;;;;N;;;;;
-121C8;CUNEIFORM SIGN LAGAB TIMES HA;Lo;0;L;;;;;N;;;;;
-121C9;CUNEIFORM SIGN LAGAB TIMES HAL;Lo;0;L;;;;;N;;;;;
-121CA;CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN;Lo;0;L;;;;;N;;;;;
-121CB;CUNEIFORM SIGN LAGAB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-121CC;CUNEIFORM SIGN LAGAB TIMES IM;Lo;0;L;;;;;N;;;;;
-121CD;CUNEIFORM SIGN LAGAB TIMES IM PLUS HA;Lo;0;L;;;;;N;;;;;
-121CE;CUNEIFORM SIGN LAGAB TIMES IM PLUS LU;Lo;0;L;;;;;N;;;;;
-121CF;CUNEIFORM SIGN LAGAB TIMES KI;Lo;0;L;;;;;N;;;;;
-121D0;CUNEIFORM SIGN LAGAB TIMES KIN;Lo;0;L;;;;;N;;;;;
-121D1;CUNEIFORM SIGN LAGAB TIMES KU3;Lo;0;L;;;;;N;;;;;
-121D2;CUNEIFORM SIGN LAGAB TIMES KUL;Lo;0;L;;;;;N;;;;;
-121D3;CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A;Lo;0;L;;;;;N;;;;;
-121D4;CUNEIFORM SIGN LAGAB TIMES LAGAB;Lo;0;L;;;;;N;;;;;
-121D5;CUNEIFORM SIGN LAGAB TIMES LISH;Lo;0;L;;;;;N;;;;;
-121D6;CUNEIFORM SIGN LAGAB TIMES LU;Lo;0;L;;;;;N;;;;;
-121D7;CUNEIFORM SIGN LAGAB TIMES LUL;Lo;0;L;;;;;N;;;;;
-121D8;CUNEIFORM SIGN LAGAB TIMES ME;Lo;0;L;;;;;N;;;;;
-121D9;CUNEIFORM SIGN LAGAB TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;;
-121DA;CUNEIFORM SIGN LAGAB TIMES MUSH;Lo;0;L;;;;;N;;;;;
-121DB;CUNEIFORM SIGN LAGAB TIMES NE;Lo;0;L;;;;;N;;;;;
-121DC;CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;;
-121DD;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN2;Lo;0;L;;;;;N;;;;;
-121DE;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU;Lo;0;L;;;;;N;;;;;
-121DF;CUNEIFORM SIGN LAGAB TIMES SHU2;Lo;0;L;;;;;N;;;;;
-121E0;CUNEIFORM SIGN LAGAB TIMES SHU2 PLUS SHU2;Lo;0;L;;;;;N;;;;;
-121E1;CUNEIFORM SIGN LAGAB TIMES SUM;Lo;0;L;;;;;N;;;;;
-121E2;CUNEIFORM SIGN LAGAB TIMES TAG;Lo;0;L;;;;;N;;;;;
-121E3;CUNEIFORM SIGN LAGAB TIMES TAK4;Lo;0;L;;;;;N;;;;;
-121E4;CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA;Lo;0;L;;;;;N;;;;;
-121E5;CUNEIFORM SIGN LAGAB TIMES U;Lo;0;L;;;;;N;;;;;
-121E6;CUNEIFORM SIGN LAGAB TIMES U PLUS A;Lo;0;L;;;;;N;;;;;
-121E7;CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;;
-121E8;CUNEIFORM SIGN LAGAB TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;;
-121E9;CUNEIFORM SIGN LAGAB TIMES UD;Lo;0;L;;;;;N;;;;;
-121EA;CUNEIFORM SIGN LAGAB TIMES USH;Lo;0;L;;;;;N;;;;;
-121EB;CUNEIFORM SIGN LAGAB SQUARED;Lo;0;L;;;;;N;;;;;
-121EC;CUNEIFORM SIGN LAGAR;Lo;0;L;;;;;N;;;;;
-121ED;CUNEIFORM SIGN LAGAR TIMES SHE;Lo;0;L;;;;;N;;;;;
-121EE;CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;;
-121EF;CUNEIFORM SIGN LAGAR GUNU;Lo;0;L;;;;;N;;;;;
-121F0;CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE;Lo;0;L;;;;;N;;;;;
-121F1;CUNEIFORM SIGN LAHSHU;Lo;0;L;;;;;N;;;;;
-121F2;CUNEIFORM SIGN LAL;Lo;0;L;;;;;N;;;;;
-121F3;CUNEIFORM SIGN LAL TIMES LAL;Lo;0;L;;;;;N;;;;;
-121F4;CUNEIFORM SIGN LAM;Lo;0;L;;;;;N;;;;;
-121F5;CUNEIFORM SIGN LAM TIMES KUR;Lo;0;L;;;;;N;;;;;
-121F6;CUNEIFORM SIGN LAM TIMES KUR PLUS RU;Lo;0;L;;;;;N;;;;;
-121F7;CUNEIFORM SIGN LI;Lo;0;L;;;;;N;;;;;
-121F8;CUNEIFORM SIGN LIL;Lo;0;L;;;;;N;;;;;
-121F9;CUNEIFORM SIGN LIMMU2;Lo;0;L;;;;;N;;;;;
-121FA;CUNEIFORM SIGN LISH;Lo;0;L;;;;;N;;;;;
-121FB;CUNEIFORM SIGN LU;Lo;0;L;;;;;N;;;;;
-121FC;CUNEIFORM SIGN LU TIMES BAD;Lo;0;L;;;;;N;;;;;
-121FD;CUNEIFORM SIGN LU2;Lo;0;L;;;;;N;;;;;
-121FE;CUNEIFORM SIGN LU2 TIMES AL;Lo;0;L;;;;;N;;;;;
-121FF;CUNEIFORM SIGN LU2 TIMES BAD;Lo;0;L;;;;;N;;;;;
-12200;CUNEIFORM SIGN LU2 TIMES ESH2;Lo;0;L;;;;;N;;;;;
-12201;CUNEIFORM SIGN LU2 TIMES ESH2 TENU;Lo;0;L;;;;;N;;;;;
-12202;CUNEIFORM SIGN LU2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-12203;CUNEIFORM SIGN LU2 TIMES HI TIMES BAD;Lo;0;L;;;;;N;;;;;
-12204;CUNEIFORM SIGN LU2 TIMES IM;Lo;0;L;;;;;N;;;;;
-12205;CUNEIFORM SIGN LU2 TIMES KAD2;Lo;0;L;;;;;N;;;;;
-12206;CUNEIFORM SIGN LU2 TIMES KAD3;Lo;0;L;;;;;N;;;;;
-12207;CUNEIFORM SIGN LU2 TIMES KAD3 PLUS ASH;Lo;0;L;;;;;N;;;;;
-12208;CUNEIFORM SIGN LU2 TIMES KI;Lo;0;L;;;;;N;;;;;
-12209;CUNEIFORM SIGN LU2 TIMES LA PLUS ASH;Lo;0;L;;;;;N;;;;;
-1220A;CUNEIFORM SIGN LU2 TIMES LAGAB;Lo;0;L;;;;;N;;;;;
-1220B;CUNEIFORM SIGN LU2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;;
-1220C;CUNEIFORM SIGN LU2 TIMES NE;Lo;0;L;;;;;N;;;;;
-1220D;CUNEIFORM SIGN LU2 TIMES NU;Lo;0;L;;;;;N;;;;;
-1220E;CUNEIFORM SIGN LU2 TIMES SI PLUS ASH;Lo;0;L;;;;;N;;;;;
-1220F;CUNEIFORM SIGN LU2 TIMES SIK2 PLUS BU;Lo;0;L;;;;;N;;;;;
-12210;CUNEIFORM SIGN LU2 TIMES TUG2;Lo;0;L;;;;;N;;;;;
-12211;CUNEIFORM SIGN LU2 TENU;Lo;0;L;;;;;N;;;;;
-12212;CUNEIFORM SIGN LU2 CROSSING LU2;Lo;0;L;;;;;N;;;;;
-12213;CUNEIFORM SIGN LU2 OPPOSING LU2;Lo;0;L;;;;;N;;;;;
-12214;CUNEIFORM SIGN LU2 SQUARED;Lo;0;L;;;;;N;;;;;
-12215;CUNEIFORM SIGN LU2 SHESHIG;Lo;0;L;;;;;N;;;;;
-12216;CUNEIFORM SIGN LU3;Lo;0;L;;;;;N;;;;;
-12217;CUNEIFORM SIGN LUGAL;Lo;0;L;;;;;N;;;;;
-12218;CUNEIFORM SIGN LUGAL OVER LUGAL;Lo;0;L;;;;;N;;;;;
-12219;CUNEIFORM SIGN LUGAL OPPOSING LUGAL;Lo;0;L;;;;;N;;;;;
-1221A;CUNEIFORM SIGN LUGAL SHESHIG;Lo;0;L;;;;;N;;;;;
-1221B;CUNEIFORM SIGN LUH;Lo;0;L;;;;;N;;;;;
-1221C;CUNEIFORM SIGN LUL;Lo;0;L;;;;;N;;;;;
-1221D;CUNEIFORM SIGN LUM;Lo;0;L;;;;;N;;;;;
-1221E;CUNEIFORM SIGN LUM OVER LUM;Lo;0;L;;;;;N;;;;;
-1221F;CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR;Lo;0;L;;;;;N;;;;;
-12220;CUNEIFORM SIGN MA;Lo;0;L;;;;;N;;;;;
-12221;CUNEIFORM SIGN MA TIMES TAK4;Lo;0;L;;;;;N;;;;;
-12222;CUNEIFORM SIGN MA GUNU;Lo;0;L;;;;;N;;;;;
-12223;CUNEIFORM SIGN MA2;Lo;0;L;;;;;N;;;;;
-12224;CUNEIFORM SIGN MAH;Lo;0;L;;;;;N;;;;;
-12225;CUNEIFORM SIGN MAR;Lo;0;L;;;;;N;;;;;
-12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;;N;;;;;
-12227;CUNEIFORM SIGN MASH2;Lo;0;L;;;;;N;;;;;
-12228;CUNEIFORM SIGN ME;Lo;0;L;;;;;N;;;;;
-12229;CUNEIFORM SIGN MES;Lo;0;L;;;;;N;;;;;
-1222A;CUNEIFORM SIGN MI;Lo;0;L;;;;;N;;;;;
-1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;;N;;;;;
-1222C;CUNEIFORM SIGN MU;Lo;0;L;;;;;N;;;;;
-1222D;CUNEIFORM SIGN MU OVER MU;Lo;0;L;;;;;N;;;;;
-1222E;CUNEIFORM SIGN MUG;Lo;0;L;;;;;N;;;;;
-1222F;CUNEIFORM SIGN MUG GUNU;Lo;0;L;;;;;N;;;;;
-12230;CUNEIFORM SIGN MUNSUB;Lo;0;L;;;;;N;;;;;
-12231;CUNEIFORM SIGN MURGU2;Lo;0;L;;;;;N;;;;;
-12232;CUNEIFORM SIGN MUSH;Lo;0;L;;;;;N;;;;;
-12233;CUNEIFORM SIGN MUSH TIMES A;Lo;0;L;;;;;N;;;;;
-12234;CUNEIFORM SIGN MUSH TIMES KUR;Lo;0;L;;;;;N;;;;;
-12235;CUNEIFORM SIGN MUSH TIMES ZA;Lo;0;L;;;;;N;;;;;
-12236;CUNEIFORM SIGN MUSH OVER MUSH;Lo;0;L;;;;;N;;;;;
-12237;CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA;Lo;0;L;;;;;N;;;;;
-12238;CUNEIFORM SIGN MUSH CROSSING MUSH;Lo;0;L;;;;;N;;;;;
-12239;CUNEIFORM SIGN MUSH3;Lo;0;L;;;;;N;;;;;
-1223A;CUNEIFORM SIGN MUSH3 TIMES A;Lo;0;L;;;;;N;;;;;
-1223B;CUNEIFORM SIGN MUSH3 TIMES A PLUS DI;Lo;0;L;;;;;N;;;;;
-1223C;CUNEIFORM SIGN MUSH3 TIMES DI;Lo;0;L;;;;;N;;;;;
-1223D;CUNEIFORM SIGN MUSH3 GUNU;Lo;0;L;;;;;N;;;;;
-1223E;CUNEIFORM SIGN NA;Lo;0;L;;;;;N;;;;;
-1223F;CUNEIFORM SIGN NA2;Lo;0;L;;;;;N;;;;;
-12240;CUNEIFORM SIGN NAGA;Lo;0;L;;;;;N;;;;;
-12241;CUNEIFORM SIGN NAGA INVERTED;Lo;0;L;;;;;N;;;;;
-12242;CUNEIFORM SIGN NAGA TIMES SHU TENU;Lo;0;L;;;;;N;;;;;
-12243;CUNEIFORM SIGN NAGA OPPOSING NAGA;Lo;0;L;;;;;N;;;;;
-12244;CUNEIFORM SIGN NAGAR;Lo;0;L;;;;;N;;;;;
-12245;CUNEIFORM SIGN NAM NUTILLU;Lo;0;L;;;;;N;;;;;
-12246;CUNEIFORM SIGN NAM;Lo;0;L;;;;;N;;;;;
-12247;CUNEIFORM SIGN NAM2;Lo;0;L;;;;;N;;;;;
-12248;CUNEIFORM SIGN NE;Lo;0;L;;;;;N;;;;;
-12249;CUNEIFORM SIGN NE TIMES A;Lo;0;L;;;;;N;;;;;
-1224A;CUNEIFORM SIGN NE TIMES UD;Lo;0;L;;;;;N;;;;;
-1224B;CUNEIFORM SIGN NE SHESHIG;Lo;0;L;;;;;N;;;;;
-1224C;CUNEIFORM SIGN NI;Lo;0;L;;;;;N;;;;;
-1224D;CUNEIFORM SIGN NI TIMES E;Lo;0;L;;;;;N;;;;;
-1224E;CUNEIFORM SIGN NI2;Lo;0;L;;;;;N;;;;;
-1224F;CUNEIFORM SIGN NIM;Lo;0;L;;;;;N;;;;;
-12250;CUNEIFORM SIGN NIM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-12251;CUNEIFORM SIGN NIM TIMES GAR PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;;
-12252;CUNEIFORM SIGN NINDA2;Lo;0;L;;;;;N;;;;;
-12253;CUNEIFORM SIGN NINDA2 TIMES AN;Lo;0;L;;;;;N;;;;;
-12254;CUNEIFORM SIGN NINDA2 TIMES ASH;Lo;0;L;;;;;N;;;;;
-12255;CUNEIFORM SIGN NINDA2 TIMES ASH PLUS ASH;Lo;0;L;;;;;N;;;;;
-12256;CUNEIFORM SIGN NINDA2 TIMES GUD;Lo;0;L;;;;;N;;;;;
-12257;CUNEIFORM SIGN NINDA2 TIMES ME PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;;
-12258;CUNEIFORM SIGN NINDA2 TIMES NE;Lo;0;L;;;;;N;;;;;
-12259;CUNEIFORM SIGN NINDA2 TIMES NUN;Lo;0;L;;;;;N;;;;;
-1225A;CUNEIFORM SIGN NINDA2 TIMES SHE;Lo;0;L;;;;;N;;;;;
-1225B;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS A AN;Lo;0;L;;;;;N;;;;;
-1225C;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH;Lo;0;L;;;;;N;;;;;
-1225D;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH PLUS ASH;Lo;0;L;;;;;N;;;;;
-1225E;CUNEIFORM SIGN NINDA2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;;
-1225F;CUNEIFORM SIGN NINDA2 TIMES USH;Lo;0;L;;;;;N;;;;;
-12260;CUNEIFORM SIGN NISAG;Lo;0;L;;;;;N;;;;;
-12261;CUNEIFORM SIGN NU;Lo;0;L;;;;;N;;;;;
-12262;CUNEIFORM SIGN NU11;Lo;0;L;;;;;N;;;;;
-12263;CUNEIFORM SIGN NUN;Lo;0;L;;;;;N;;;;;
-12264;CUNEIFORM SIGN NUN LAGAR TIMES GAR;Lo;0;L;;;;;N;;;;;
-12265;CUNEIFORM SIGN NUN LAGAR TIMES MASH;Lo;0;L;;;;;N;;;;;
-12266;CUNEIFORM SIGN NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;;
-12267;CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;;
-12268;CUNEIFORM SIGN NUN LAGAR TIMES USH;Lo;0;L;;;;;N;;;;;
-12269;CUNEIFORM SIGN NUN TENU;Lo;0;L;;;;;N;;;;;
-1226A;CUNEIFORM SIGN NUN OVER NUN;Lo;0;L;;;;;N;;;;;
-1226B;CUNEIFORM SIGN NUN CROSSING NUN;Lo;0;L;;;;;N;;;;;
-1226C;CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR;Lo;0;L;;;;;N;;;;;
-1226D;CUNEIFORM SIGN NUNUZ;Lo;0;L;;;;;N;;;;;
-1226E;CUNEIFORM SIGN NUNUZ AB2 TIMES ASHGAB;Lo;0;L;;;;;N;;;;;
-1226F;CUNEIFORM SIGN NUNUZ AB2 TIMES BI;Lo;0;L;;;;;N;;;;;
-12270;CUNEIFORM SIGN NUNUZ AB2 TIMES DUG;Lo;0;L;;;;;N;;;;;
-12271;CUNEIFORM SIGN NUNUZ AB2 TIMES GUD;Lo;0;L;;;;;N;;;;;
-12272;CUNEIFORM SIGN NUNUZ AB2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-12273;CUNEIFORM SIGN NUNUZ AB2 TIMES KAD3;Lo;0;L;;;;;N;;;;;
-12274;CUNEIFORM SIGN NUNUZ AB2 TIMES LA;Lo;0;L;;;;;N;;;;;
-12275;CUNEIFORM SIGN NUNUZ AB2 TIMES NE;Lo;0;L;;;;;N;;;;;
-12276;CUNEIFORM SIGN NUNUZ AB2 TIMES SILA3;Lo;0;L;;;;;N;;;;;
-12277;CUNEIFORM SIGN NUNUZ AB2 TIMES U2;Lo;0;L;;;;;N;;;;;
-12278;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;;
-12279;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI U;Lo;0;L;;;;;N;;;;;
-1227A;CUNEIFORM SIGN PA;Lo;0;L;;;;;N;;;;;
-1227B;CUNEIFORM SIGN PAD;Lo;0;L;;;;;N;;;;;
-1227C;CUNEIFORM SIGN PAN;Lo;0;L;;;;;N;;;;;
-1227D;CUNEIFORM SIGN PAP;Lo;0;L;;;;;N;;;;;
-1227E;CUNEIFORM SIGN PESH2;Lo;0;L;;;;;N;;;;;
-1227F;CUNEIFORM SIGN PI;Lo;0;L;;;;;N;;;;;
-12280;CUNEIFORM SIGN PI TIMES A;Lo;0;L;;;;;N;;;;;
-12281;CUNEIFORM SIGN PI TIMES AB;Lo;0;L;;;;;N;;;;;
-12282;CUNEIFORM SIGN PI TIMES BI;Lo;0;L;;;;;N;;;;;
-12283;CUNEIFORM SIGN PI TIMES BU;Lo;0;L;;;;;N;;;;;
-12284;CUNEIFORM SIGN PI TIMES E;Lo;0;L;;;;;N;;;;;
-12285;CUNEIFORM SIGN PI TIMES I;Lo;0;L;;;;;N;;;;;
-12286;CUNEIFORM SIGN PI TIMES IB;Lo;0;L;;;;;N;;;;;
-12287;CUNEIFORM SIGN PI TIMES U;Lo;0;L;;;;;N;;;;;
-12288;CUNEIFORM SIGN PI TIMES U2;Lo;0;L;;;;;N;;;;;
-12289;CUNEIFORM SIGN PI CROSSING PI;Lo;0;L;;;;;N;;;;;
-1228A;CUNEIFORM SIGN PIRIG;Lo;0;L;;;;;N;;;;;
-1228B;CUNEIFORM SIGN PIRIG TIMES KAL;Lo;0;L;;;;;N;;;;;
-1228C;CUNEIFORM SIGN PIRIG TIMES UD;Lo;0;L;;;;;N;;;;;
-1228D;CUNEIFORM SIGN PIRIG TIMES ZA;Lo;0;L;;;;;N;;;;;
-1228E;CUNEIFORM SIGN PIRIG OPPOSING PIRIG;Lo;0;L;;;;;N;;;;;
-1228F;CUNEIFORM SIGN RA;Lo;0;L;;;;;N;;;;;
-12290;CUNEIFORM SIGN RAB;Lo;0;L;;;;;N;;;;;
-12291;CUNEIFORM SIGN RI;Lo;0;L;;;;;N;;;;;
-12292;CUNEIFORM SIGN RU;Lo;0;L;;;;;N;;;;;
-12293;CUNEIFORM SIGN SA;Lo;0;L;;;;;N;;;;;
-12294;CUNEIFORM SIGN SAG NUTILLU;Lo;0;L;;;;;N;;;;;
-12295;CUNEIFORM SIGN SAG;Lo;0;L;;;;;N;;;;;
-12296;CUNEIFORM SIGN SAG TIMES A;Lo;0;L;;;;;N;;;;;
-12297;CUNEIFORM SIGN SAG TIMES DU;Lo;0;L;;;;;N;;;;;
-12298;CUNEIFORM SIGN SAG TIMES DUB;Lo;0;L;;;;;N;;;;;
-12299;CUNEIFORM SIGN SAG TIMES HA;Lo;0;L;;;;;N;;;;;
-1229A;CUNEIFORM SIGN SAG TIMES KAK;Lo;0;L;;;;;N;;;;;
-1229B;CUNEIFORM SIGN SAG TIMES KUR;Lo;0;L;;;;;N;;;;;
-1229C;CUNEIFORM SIGN SAG TIMES LUM;Lo;0;L;;;;;N;;;;;
-1229D;CUNEIFORM SIGN SAG TIMES MI;Lo;0;L;;;;;N;;;;;
-1229E;CUNEIFORM SIGN SAG TIMES NUN;Lo;0;L;;;;;N;;;;;
-1229F;CUNEIFORM SIGN SAG TIMES SAL;Lo;0;L;;;;;N;;;;;
-122A0;CUNEIFORM SIGN SAG TIMES SHID;Lo;0;L;;;;;N;;;;;
-122A1;CUNEIFORM SIGN SAG TIMES TAB;Lo;0;L;;;;;N;;;;;
-122A2;CUNEIFORM SIGN SAG TIMES U2;Lo;0;L;;;;;N;;;;;
-122A3;CUNEIFORM SIGN SAG TIMES UB;Lo;0;L;;;;;N;;;;;
-122A4;CUNEIFORM SIGN SAG TIMES UM;Lo;0;L;;;;;N;;;;;
-122A5;CUNEIFORM SIGN SAG TIMES UR;Lo;0;L;;;;;N;;;;;
-122A6;CUNEIFORM SIGN SAG TIMES USH;Lo;0;L;;;;;N;;;;;
-122A7;CUNEIFORM SIGN SAG OVER SAG;Lo;0;L;;;;;N;;;;;
-122A8;CUNEIFORM SIGN SAG GUNU;Lo;0;L;;;;;N;;;;;
-122A9;CUNEIFORM SIGN SAL;Lo;0;L;;;;;N;;;;;
-122AA;CUNEIFORM SIGN SAL LAGAB TIMES ASH2;Lo;0;L;;;;;N;;;;;
-122AB;CUNEIFORM SIGN SANGA2;Lo;0;L;;;;;N;;;;;
-122AC;CUNEIFORM SIGN SAR;Lo;0;L;;;;;N;;;;;
-122AD;CUNEIFORM SIGN SHA;Lo;0;L;;;;;N;;;;;
-122AE;CUNEIFORM SIGN SHA3;Lo;0;L;;;;;N;;;;;
-122AF;CUNEIFORM SIGN SHA3 TIMES A;Lo;0;L;;;;;N;;;;;
-122B0;CUNEIFORM SIGN SHA3 TIMES BAD;Lo;0;L;;;;;N;;;;;
-122B1;CUNEIFORM SIGN SHA3 TIMES GISH;Lo;0;L;;;;;N;;;;;
-122B2;CUNEIFORM SIGN SHA3 TIMES NE;Lo;0;L;;;;;N;;;;;
-122B3;CUNEIFORM SIGN SHA3 TIMES SHU2;Lo;0;L;;;;;N;;;;;
-122B4;CUNEIFORM SIGN SHA3 TIMES TUR;Lo;0;L;;;;;N;;;;;
-122B5;CUNEIFORM SIGN SHA3 TIMES U;Lo;0;L;;;;;N;;;;;
-122B6;CUNEIFORM SIGN SHA3 TIMES U PLUS A;Lo;0;L;;;;;N;;;;;
-122B7;CUNEIFORM SIGN SHA6;Lo;0;L;;;;;N;;;;;
-122B8;CUNEIFORM SIGN SHAB6;Lo;0;L;;;;;N;;;;;
-122B9;CUNEIFORM SIGN SHAR2;Lo;0;L;;;;;N;;;;;
-122BA;CUNEIFORM SIGN SHE;Lo;0;L;;;;;N;;;;;
-122BB;CUNEIFORM SIGN SHE HU;Lo;0;L;;;;;N;;;;;
-122BC;CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;;
-122BD;CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR;Lo;0;L;;;;;N;;;;;
-122BE;CUNEIFORM SIGN SHEG9;Lo;0;L;;;;;N;;;;;
-122BF;CUNEIFORM SIGN SHEN;Lo;0;L;;;;;N;;;;;
-122C0;CUNEIFORM SIGN SHESH;Lo;0;L;;;;;N;;;;;
-122C1;CUNEIFORM SIGN SHESH2;Lo;0;L;;;;;N;;;;;
-122C2;CUNEIFORM SIGN SHESHLAM;Lo;0;L;;;;;N;;;;;
-122C3;CUNEIFORM SIGN SHID;Lo;0;L;;;;;N;;;;;
-122C4;CUNEIFORM SIGN SHID TIMES A;Lo;0;L;;;;;N;;;;;
-122C5;CUNEIFORM SIGN SHID TIMES IM;Lo;0;L;;;;;N;;;;;
-122C6;CUNEIFORM SIGN SHIM;Lo;0;L;;;;;N;;;;;
-122C7;CUNEIFORM SIGN SHIM TIMES A;Lo;0;L;;;;;N;;;;;
-122C8;CUNEIFORM SIGN SHIM TIMES BAL;Lo;0;L;;;;;N;;;;;
-122C9;CUNEIFORM SIGN SHIM TIMES BULUG;Lo;0;L;;;;;N;;;;;
-122CA;CUNEIFORM SIGN SHIM TIMES DIN;Lo;0;L;;;;;N;;;;;
-122CB;CUNEIFORM SIGN SHIM TIMES GAR;Lo;0;L;;;;;N;;;;;
-122CC;CUNEIFORM SIGN SHIM TIMES IGI;Lo;0;L;;;;;N;;;;;
-122CD;CUNEIFORM SIGN SHIM TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
-122CE;CUNEIFORM SIGN SHIM TIMES KUSHU2;Lo;0;L;;;;;N;;;;;
-122CF;CUNEIFORM SIGN SHIM TIMES LUL;Lo;0;L;;;;;N;;;;;
-122D0;CUNEIFORM SIGN SHIM TIMES MUG;Lo;0;L;;;;;N;;;;;
-122D1;CUNEIFORM SIGN SHIM TIMES SAL;Lo;0;L;;;;;N;;;;;
-122D2;CUNEIFORM SIGN SHINIG;Lo;0;L;;;;;N;;;;;
-122D3;CUNEIFORM SIGN SHIR;Lo;0;L;;;;;N;;;;;
-122D4;CUNEIFORM SIGN SHIR TENU;Lo;0;L;;;;;N;;;;;
-122D5;CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR;Lo;0;L;;;;;N;;;;;
-122D6;CUNEIFORM SIGN SHITA;Lo;0;L;;;;;N;;;;;
-122D7;CUNEIFORM SIGN SHU;Lo;0;L;;;;;N;;;;;
-122D8;CUNEIFORM SIGN SHU OVER INVERTED SHU;Lo;0;L;;;;;N;;;;;
-122D9;CUNEIFORM SIGN SHU2;Lo;0;L;;;;;N;;;;;
-122DA;CUNEIFORM SIGN SHUBUR;Lo;0;L;;;;;N;;;;;
-122DB;CUNEIFORM SIGN SI;Lo;0;L;;;;;N;;;;;
-122DC;CUNEIFORM SIGN SI GUNU;Lo;0;L;;;;;N;;;;;
-122DD;CUNEIFORM SIGN SIG;Lo;0;L;;;;;N;;;;;
-122DE;CUNEIFORM SIGN SIG4;Lo;0;L;;;;;N;;;;;
-122DF;CUNEIFORM SIGN SIG4 OVER SIG4 SHU2;Lo;0;L;;;;;N;;;;;
-122E0;CUNEIFORM SIGN SIK2;Lo;0;L;;;;;N;;;;;
-122E1;CUNEIFORM SIGN SILA3;Lo;0;L;;;;;N;;;;;
-122E2;CUNEIFORM SIGN SU;Lo;0;L;;;;;N;;;;;
-122E3;CUNEIFORM SIGN SU OVER SU;Lo;0;L;;;;;N;;;;;
-122E4;CUNEIFORM SIGN SUD;Lo;0;L;;;;;N;;;;;
-122E5;CUNEIFORM SIGN SUD2;Lo;0;L;;;;;N;;;;;
-122E6;CUNEIFORM SIGN SUHUR;Lo;0;L;;;;;N;;;;;
-122E7;CUNEIFORM SIGN SUM;Lo;0;L;;;;;N;;;;;
-122E8;CUNEIFORM SIGN SUMASH;Lo;0;L;;;;;N;;;;;
-122E9;CUNEIFORM SIGN SUR;Lo;0;L;;;;;N;;;;;
-122EA;CUNEIFORM SIGN SUR9;Lo;0;L;;;;;N;;;;;
-122EB;CUNEIFORM SIGN TA;Lo;0;L;;;;;N;;;;;
-122EC;CUNEIFORM SIGN TA ASTERISK;Lo;0;L;;;;;N;;;;;
-122ED;CUNEIFORM SIGN TA TIMES HI;Lo;0;L;;;;;N;;;;;
-122EE;CUNEIFORM SIGN TA TIMES MI;Lo;0;L;;;;;N;;;;;
-122EF;CUNEIFORM SIGN TA GUNU;Lo;0;L;;;;;N;;;;;
-122F0;CUNEIFORM SIGN TAB;Lo;0;L;;;;;N;;;;;
-122F1;CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH;Lo;0;L;;;;;N;;;;;
-122F2;CUNEIFORM SIGN TAB SQUARED;Lo;0;L;;;;;N;;;;;
-122F3;CUNEIFORM SIGN TAG;Lo;0;L;;;;;N;;;;;
-122F4;CUNEIFORM SIGN TAG TIMES BI;Lo;0;L;;;;;N;;;;;
-122F5;CUNEIFORM SIGN TAG TIMES GUD;Lo;0;L;;;;;N;;;;;
-122F6;CUNEIFORM SIGN TAG TIMES SHE;Lo;0;L;;;;;N;;;;;
-122F7;CUNEIFORM SIGN TAG TIMES SHU;Lo;0;L;;;;;N;;;;;
-122F8;CUNEIFORM SIGN TAG TIMES TUG2;Lo;0;L;;;;;N;;;;;
-122F9;CUNEIFORM SIGN TAG TIMES UD;Lo;0;L;;;;;N;;;;;
-122FA;CUNEIFORM SIGN TAK4;Lo;0;L;;;;;N;;;;;
-122FB;CUNEIFORM SIGN TAR;Lo;0;L;;;;;N;;;;;
-122FC;CUNEIFORM SIGN TE;Lo;0;L;;;;;N;;;;;
-122FD;CUNEIFORM SIGN TE GUNU;Lo;0;L;;;;;N;;;;;
-122FE;CUNEIFORM SIGN TI;Lo;0;L;;;;;N;;;;;
-122FF;CUNEIFORM SIGN TI TENU;Lo;0;L;;;;;N;;;;;
-12300;CUNEIFORM SIGN TIL;Lo;0;L;;;;;N;;;;;
-12301;CUNEIFORM SIGN TIR;Lo;0;L;;;;;N;;;;;
-12302;CUNEIFORM SIGN TIR TIMES TAK4;Lo;0;L;;;;;N;;;;;
-12303;CUNEIFORM SIGN TIR OVER TIR;Lo;0;L;;;;;N;;;;;
-12304;CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;;
-12305;CUNEIFORM SIGN TU;Lo;0;L;;;;;N;;;;;
-12306;CUNEIFORM SIGN TUG2;Lo;0;L;;;;;N;;;;;
-12307;CUNEIFORM SIGN TUK;Lo;0;L;;;;;N;;;;;
-12308;CUNEIFORM SIGN TUM;Lo;0;L;;;;;N;;;;;
-12309;CUNEIFORM SIGN TUR;Lo;0;L;;;;;N;;;;;
-1230A;CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA;Lo;0;L;;;;;N;;;;;
-1230B;CUNEIFORM SIGN U;Lo;0;L;;;;;N;;;;;
-1230C;CUNEIFORM SIGN U GUD;Lo;0;L;;;;;N;;;;;
-1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;;N;;;;;
-1230E;CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR;Lo;0;L;;;;;N;;;;;
-1230F;CUNEIFORM SIGN U OVER U SUR OVER SUR;Lo;0;L;;;;;N;;;;;
-12310;CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED;Lo;0;L;;;;;N;;;;;
-12311;CUNEIFORM SIGN U2;Lo;0;L;;;;;N;;;;;
-12312;CUNEIFORM SIGN UB;Lo;0;L;;;;;N;;;;;
-12313;CUNEIFORM SIGN UD;Lo;0;L;;;;;N;;;;;
-12314;CUNEIFORM SIGN UD KUSHU2;Lo;0;L;;;;;N;;;;;
-12315;CUNEIFORM SIGN UD TIMES BAD;Lo;0;L;;;;;N;;;;;
-12316;CUNEIFORM SIGN UD TIMES MI;Lo;0;L;;;;;N;;;;;
-12317;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;;
-12318;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU;Lo;0;L;;;;;N;;;;;
-12319;CUNEIFORM SIGN UD GUNU;Lo;0;L;;;;;N;;;;;
-1231A;CUNEIFORM SIGN UD SHESHIG;Lo;0;L;;;;;N;;;;;
-1231B;CUNEIFORM SIGN UD SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;;
-1231C;CUNEIFORM SIGN UDUG;Lo;0;L;;;;;N;;;;;
-1231D;CUNEIFORM SIGN UM;Lo;0;L;;;;;N;;;;;
-1231E;CUNEIFORM SIGN UM TIMES LAGAB;Lo;0;L;;;;;N;;;;;
-1231F;CUNEIFORM SIGN UM TIMES ME PLUS DA;Lo;0;L;;;;;N;;;;;
-12320;CUNEIFORM SIGN UM TIMES SHA3;Lo;0;L;;;;;N;;;;;
-12321;CUNEIFORM SIGN UM TIMES U;Lo;0;L;;;;;N;;;;;
-12322;CUNEIFORM SIGN UMBIN;Lo;0;L;;;;;N;;;;;
-12323;CUNEIFORM SIGN UMUM;Lo;0;L;;;;;N;;;;;
-12324;CUNEIFORM SIGN UMUM TIMES KASKAL;Lo;0;L;;;;;N;;;;;
-12325;CUNEIFORM SIGN UMUM TIMES PA;Lo;0;L;;;;;N;;;;;
-12326;CUNEIFORM SIGN UN;Lo;0;L;;;;;N;;;;;
-12327;CUNEIFORM SIGN UN GUNU;Lo;0;L;;;;;N;;;;;
-12328;CUNEIFORM SIGN UR;Lo;0;L;;;;;N;;;;;
-12329;CUNEIFORM SIGN UR CROSSING UR;Lo;0;L;;;;;N;;;;;
-1232A;CUNEIFORM SIGN UR SHESHIG;Lo;0;L;;;;;N;;;;;
-1232B;CUNEIFORM SIGN UR2;Lo;0;L;;;;;N;;;;;
-1232C;CUNEIFORM SIGN UR2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;;
-1232D;CUNEIFORM SIGN UR2 TIMES A PLUS NA;Lo;0;L;;;;;N;;;;;
-1232E;CUNEIFORM SIGN UR2 TIMES AL;Lo;0;L;;;;;N;;;;;
-1232F;CUNEIFORM SIGN UR2 TIMES HA;Lo;0;L;;;;;N;;;;;
-12330;CUNEIFORM SIGN UR2 TIMES NUN;Lo;0;L;;;;;N;;;;;
-12331;CUNEIFORM SIGN UR2 TIMES U2;Lo;0;L;;;;;N;;;;;
-12332;CUNEIFORM SIGN UR2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;;
-12333;CUNEIFORM SIGN UR2 TIMES U2 PLUS BI;Lo;0;L;;;;;N;;;;;
-12334;CUNEIFORM SIGN UR4;Lo;0;L;;;;;N;;;;;
-12335;CUNEIFORM SIGN URI;Lo;0;L;;;;;N;;;;;
-12336;CUNEIFORM SIGN URI3;Lo;0;L;;;;;N;;;;;
-12337;CUNEIFORM SIGN URU;Lo;0;L;;;;;N;;;;;
-12338;CUNEIFORM SIGN URU TIMES A;Lo;0;L;;;;;N;;;;;
-12339;CUNEIFORM SIGN URU TIMES ASHGAB;Lo;0;L;;;;;N;;;;;
-1233A;CUNEIFORM SIGN URU TIMES BAR;Lo;0;L;;;;;N;;;;;
-1233B;CUNEIFORM SIGN URU TIMES DUN;Lo;0;L;;;;;N;;;;;
-1233C;CUNEIFORM SIGN URU TIMES GA;Lo;0;L;;;;;N;;;;;
-1233D;CUNEIFORM SIGN URU TIMES GAL;Lo;0;L;;;;;N;;;;;
-1233E;CUNEIFORM SIGN URU TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
-1233F;CUNEIFORM SIGN URU TIMES GAR;Lo;0;L;;;;;N;;;;;
-12340;CUNEIFORM SIGN URU TIMES GU;Lo;0;L;;;;;N;;;;;
-12341;CUNEIFORM SIGN URU TIMES HA;Lo;0;L;;;;;N;;;;;
-12342;CUNEIFORM SIGN URU TIMES IGI;Lo;0;L;;;;;N;;;;;
-12343;CUNEIFORM SIGN URU TIMES IM;Lo;0;L;;;;;N;;;;;
-12344;CUNEIFORM SIGN URU TIMES ISH;Lo;0;L;;;;;N;;;;;
-12345;CUNEIFORM SIGN URU TIMES KI;Lo;0;L;;;;;N;;;;;
-12346;CUNEIFORM SIGN URU TIMES LUM;Lo;0;L;;;;;N;;;;;
-12347;CUNEIFORM SIGN URU TIMES MIN;Lo;0;L;;;;;N;;;;;
-12348;CUNEIFORM SIGN URU TIMES PA;Lo;0;L;;;;;N;;;;;
-12349;CUNEIFORM SIGN URU TIMES SHE;Lo;0;L;;;;;N;;;;;
-1234A;CUNEIFORM SIGN URU TIMES SIG4;Lo;0;L;;;;;N;;;;;
-1234B;CUNEIFORM SIGN URU TIMES TU;Lo;0;L;;;;;N;;;;;
-1234C;CUNEIFORM SIGN URU TIMES U PLUS GUD;Lo;0;L;;;;;N;;;;;
-1234D;CUNEIFORM SIGN URU TIMES UD;Lo;0;L;;;;;N;;;;;
-1234E;CUNEIFORM SIGN URU TIMES URUDA;Lo;0;L;;;;;N;;;;;
-1234F;CUNEIFORM SIGN URUDA;Lo;0;L;;;;;N;;;;;
-12350;CUNEIFORM SIGN URUDA TIMES U;Lo;0;L;;;;;N;;;;;
-12351;CUNEIFORM SIGN USH;Lo;0;L;;;;;N;;;;;
-12352;CUNEIFORM SIGN USH TIMES A;Lo;0;L;;;;;N;;;;;
-12353;CUNEIFORM SIGN USH TIMES KU;Lo;0;L;;;;;N;;;;;
-12354;CUNEIFORM SIGN USH TIMES KUR;Lo;0;L;;;;;N;;;;;
-12355;CUNEIFORM SIGN USH TIMES TAK4;Lo;0;L;;;;;N;;;;;
-12356;CUNEIFORM SIGN USHX;Lo;0;L;;;;;N;;;;;
-12357;CUNEIFORM SIGN USH2;Lo;0;L;;;;;N;;;;;
-12358;CUNEIFORM SIGN USHUMX;Lo;0;L;;;;;N;;;;;
-12359;CUNEIFORM SIGN UTUKI;Lo;0;L;;;;;N;;;;;
-1235A;CUNEIFORM SIGN UZ3;Lo;0;L;;;;;N;;;;;
-1235B;CUNEIFORM SIGN UZ3 TIMES KASKAL;Lo;0;L;;;;;N;;;;;
-1235C;CUNEIFORM SIGN UZU;Lo;0;L;;;;;N;;;;;
-1235D;CUNEIFORM SIGN ZA;Lo;0;L;;;;;N;;;;;
-1235E;CUNEIFORM SIGN ZA TENU;Lo;0;L;;;;;N;;;;;
-1235F;CUNEIFORM SIGN ZA SQUARED TIMES KUR;Lo;0;L;;;;;N;;;;;
-12360;CUNEIFORM SIGN ZAG;Lo;0;L;;;;;N;;;;;
-12361;CUNEIFORM SIGN ZAMX;Lo;0;L;;;;;N;;;;;
-12362;CUNEIFORM SIGN ZE2;Lo;0;L;;;;;N;;;;;
-12363;CUNEIFORM SIGN ZI;Lo;0;L;;;;;N;;;;;
-12364;CUNEIFORM SIGN ZI OVER ZI;Lo;0;L;;;;;N;;;;;
-12365;CUNEIFORM SIGN ZI3;Lo;0;L;;;;;N;;;;;
-12366;CUNEIFORM SIGN ZIB;Lo;0;L;;;;;N;;;;;
-12367;CUNEIFORM SIGN ZIB KABA TENU;Lo;0;L;;;;;N;;;;;
-12368;CUNEIFORM SIGN ZIG;Lo;0;L;;;;;N;;;;;
-12369;CUNEIFORM SIGN ZIZ2;Lo;0;L;;;;;N;;;;;
-1236A;CUNEIFORM SIGN ZU;Lo;0;L;;;;;N;;;;;
-1236B;CUNEIFORM SIGN ZU5;Lo;0;L;;;;;N;;;;;
-1236C;CUNEIFORM SIGN ZU5 TIMES A;Lo;0;L;;;;;N;;;;;
-1236D;CUNEIFORM SIGN ZUBUR;Lo;0;L;;;;;N;;;;;
-1236E;CUNEIFORM SIGN ZUM;Lo;0;L;;;;;N;;;;;
-12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;;
-12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;;
-12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;;
-12403;CUNEIFORM NUMERIC SIGN FIVE ASH;Nl;0;L;;;;5;N;;;;;
-12404;CUNEIFORM NUMERIC SIGN SIX ASH;Nl;0;L;;;;6;N;;;;;
-12405;CUNEIFORM NUMERIC SIGN SEVEN ASH;Nl;0;L;;;;7;N;;;;;
-12406;CUNEIFORM NUMERIC SIGN EIGHT ASH;Nl;0;L;;;;8;N;;;;;
-12407;CUNEIFORM NUMERIC SIGN NINE ASH;Nl;0;L;;;;9;N;;;;;
-12408;CUNEIFORM NUMERIC SIGN THREE DISH;Nl;0;L;;;;3;N;;;;;
-12409;CUNEIFORM NUMERIC SIGN FOUR DISH;Nl;0;L;;;;4;N;;;;;
-1240A;CUNEIFORM NUMERIC SIGN FIVE DISH;Nl;0;L;;;;5;N;;;;;
-1240B;CUNEIFORM NUMERIC SIGN SIX DISH;Nl;0;L;;;;6;N;;;;;
-1240C;CUNEIFORM NUMERIC SIGN SEVEN DISH;Nl;0;L;;;;7;N;;;;;
-1240D;CUNEIFORM NUMERIC SIGN EIGHT DISH;Nl;0;L;;;;8;N;;;;;
-1240E;CUNEIFORM NUMERIC SIGN NINE DISH;Nl;0;L;;;;9;N;;;;;
-1240F;CUNEIFORM NUMERIC SIGN FOUR U;Nl;0;L;;;;4;N;;;;;
-12410;CUNEIFORM NUMERIC SIGN FIVE U;Nl;0;L;;;;5;N;;;;;
-12411;CUNEIFORM NUMERIC SIGN SIX U;Nl;0;L;;;;6;N;;;;;
-12412;CUNEIFORM NUMERIC SIGN SEVEN U;Nl;0;L;;;;7;N;;;;;
-12413;CUNEIFORM NUMERIC SIGN EIGHT U;Nl;0;L;;;;8;N;;;;;
-12414;CUNEIFORM NUMERIC SIGN NINE U;Nl;0;L;;;;9;N;;;;;
-12415;CUNEIFORM NUMERIC SIGN ONE GESH2;Nl;0;L;;;;1;N;;;;;
-12416;CUNEIFORM NUMERIC SIGN TWO GESH2;Nl;0;L;;;;2;N;;;;;
-12417;CUNEIFORM NUMERIC SIGN THREE GESH2;Nl;0;L;;;;3;N;;;;;
-12418;CUNEIFORM NUMERIC SIGN FOUR GESH2;Nl;0;L;;;;4;N;;;;;
-12419;CUNEIFORM NUMERIC SIGN FIVE GESH2;Nl;0;L;;;;5;N;;;;;
-1241A;CUNEIFORM NUMERIC SIGN SIX GESH2;Nl;0;L;;;;6;N;;;;;
-1241B;CUNEIFORM NUMERIC SIGN SEVEN GESH2;Nl;0;L;;;;7;N;;;;;
-1241C;CUNEIFORM NUMERIC SIGN EIGHT GESH2;Nl;0;L;;;;8;N;;;;;
-1241D;CUNEIFORM NUMERIC SIGN NINE GESH2;Nl;0;L;;;;9;N;;;;;
-1241E;CUNEIFORM NUMERIC SIGN ONE GESHU;Nl;0;L;;;;1;N;;;;;
-1241F;CUNEIFORM NUMERIC SIGN TWO GESHU;Nl;0;L;;;;2;N;;;;;
-12420;CUNEIFORM NUMERIC SIGN THREE GESHU;Nl;0;L;;;;3;N;;;;;
-12421;CUNEIFORM NUMERIC SIGN FOUR GESHU;Nl;0;L;;;;4;N;;;;;
-12422;CUNEIFORM NUMERIC SIGN FIVE GESHU;Nl;0;L;;;;5;N;;;;;
-12423;CUNEIFORM NUMERIC SIGN TWO SHAR2;Nl;0;L;;;;2;N;;;;;
-12424;CUNEIFORM NUMERIC SIGN THREE SHAR2;Nl;0;L;;;;3;N;;;;;
-12425;CUNEIFORM NUMERIC SIGN THREE SHAR2 VARIANT FORM;Nl;0;L;;;;3;N;;;;;
-12426;CUNEIFORM NUMERIC SIGN FOUR SHAR2;Nl;0;L;;;;4;N;;;;;
-12427;CUNEIFORM NUMERIC SIGN FIVE SHAR2;Nl;0;L;;;;5;N;;;;;
-12428;CUNEIFORM NUMERIC SIGN SIX SHAR2;Nl;0;L;;;;6;N;;;;;
-12429;CUNEIFORM NUMERIC SIGN SEVEN SHAR2;Nl;0;L;;;;7;N;;;;;
-1242A;CUNEIFORM NUMERIC SIGN EIGHT SHAR2;Nl;0;L;;;;8;N;;;;;
-1242B;CUNEIFORM NUMERIC SIGN NINE SHAR2;Nl;0;L;;;;9;N;;;;;
-1242C;CUNEIFORM NUMERIC SIGN ONE SHARU;Nl;0;L;;;;1;N;;;;;
-1242D;CUNEIFORM NUMERIC SIGN TWO SHARU;Nl;0;L;;;;2;N;;;;;
-1242E;CUNEIFORM NUMERIC SIGN THREE SHARU;Nl;0;L;;;;3;N;;;;;
-1242F;CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM;Nl;0;L;;;;3;N;;;;;
-12430;CUNEIFORM NUMERIC SIGN FOUR SHARU;Nl;0;L;;;;4;N;;;;;
-12431;CUNEIFORM NUMERIC SIGN FIVE SHARU;Nl;0;L;;;;5;N;;;;;
-12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;;N;;;;;
-12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;;N;;;;;
-12434;CUNEIFORM NUMERIC SIGN ONE BURU;Nl;0;L;;;;1;N;;;;;
-12435;CUNEIFORM NUMERIC SIGN TWO BURU;Nl;0;L;;;;2;N;;;;;
-12436;CUNEIFORM NUMERIC SIGN THREE BURU;Nl;0;L;;;;3;N;;;;;
-12437;CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM;Nl;0;L;;;;3;N;;;;;
-12438;CUNEIFORM NUMERIC SIGN FOUR BURU;Nl;0;L;;;;4;N;;;;;
-12439;CUNEIFORM NUMERIC SIGN FIVE BURU;Nl;0;L;;;;5;N;;;;;
-1243A;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH16;Nl;0;L;;;;3;N;;;;;
-1243B;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH21;Nl;0;L;;;;3;N;;;;;
-1243C;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU;Nl;0;L;;;;4;N;;;;;
-1243D;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU4;Nl;0;L;;;;4;N;;;;;
-1243E;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A;Nl;0;L;;;;4;N;;;;;
-1243F;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B;Nl;0;L;;;;4;N;;;;;
-12440;CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH9;Nl;0;L;;;;6;N;;;;;
-12441;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN3;Nl;0;L;;;;7;N;;;;;
-12442;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A;Nl;0;L;;;;7;N;;;;;
-12443;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B;Nl;0;L;;;;7;N;;;;;
-12444;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU;Nl;0;L;;;;8;N;;;;;
-12445;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU3;Nl;0;L;;;;8;N;;;;;
-12446;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU;Nl;0;L;;;;9;N;;;;;
-12447;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU3;Nl;0;L;;;;9;N;;;;;
-12448;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU4;Nl;0;L;;;;9;N;;;;;
-12449;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A;Nl;0;L;;;;9;N;;;;;
-1244A;CUNEIFORM NUMERIC SIGN TWO ASH TENU;Nl;0;L;;;;2;N;;;;;
-1244B;CUNEIFORM NUMERIC SIGN THREE ASH TENU;Nl;0;L;;;;3;N;;;;;
-1244C;CUNEIFORM NUMERIC SIGN FOUR ASH TENU;Nl;0;L;;;;4;N;;;;;
-1244D;CUNEIFORM NUMERIC SIGN FIVE ASH TENU;Nl;0;L;;;;5;N;;;;;
-1244E;CUNEIFORM NUMERIC SIGN SIX ASH TENU;Nl;0;L;;;;6;N;;;;;
-1244F;CUNEIFORM NUMERIC SIGN ONE BAN2;Nl;0;L;;;;1;N;;;;;
-12450;CUNEIFORM NUMERIC SIGN TWO BAN2;Nl;0;L;;;;2;N;;;;;
-12451;CUNEIFORM NUMERIC SIGN THREE BAN2;Nl;0;L;;;;3;N;;;;;
-12452;CUNEIFORM NUMERIC SIGN FOUR BAN2;Nl;0;L;;;;4;N;;;;;
-12453;CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM;Nl;0;L;;;;4;N;;;;;
-12454;CUNEIFORM NUMERIC SIGN FIVE BAN2;Nl;0;L;;;;5;N;;;;;
-12455;CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM;Nl;0;L;;;;5;N;;;;;
-12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;;N;;;;;
-12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;;N;;;;;
-12458;CUNEIFORM NUMERIC SIGN ONE ESHE3;Nl;0;L;;;;1;N;;;;;
-12459;CUNEIFORM NUMERIC SIGN TWO ESHE3;Nl;0;L;;;;2;N;;;;;
-1245A;CUNEIFORM NUMERIC SIGN ONE THIRD DISH;Nl;0;L;;;;1/3;N;;;;;
-1245B;CUNEIFORM NUMERIC SIGN TWO THIRDS DISH;Nl;0;L;;;;2/3;N;;;;;
-1245C;CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH;Nl;0;L;;;;5/6;N;;;;;
-1245D;CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A;Nl;0;L;;;;1/3;N;;;;;
-1245E;CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A;Nl;0;L;;;;2/3;N;;;;;
-1245F;CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH;Nl;0;L;;;;1/8;N;;;;;
-12460;CUNEIFORM NUMERIC SIGN ONE QUARTER ASH;Nl;0;L;;;;1/4;N;;;;;
-12461;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH;Nl;0;L;;;;1/6;N;;;;;
-12462;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER;Nl;0;L;;;;1/4;N;;;;;
-12470;CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER;Po;0;L;;;;;N;;;;;
-12471;CUNEIFORM PUNCTUATION SIGN VERTICAL COLON;Po;0;L;;;;;N;;;;;
-12472;CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON;Po;0;L;;;;;N;;;;;
-12473;CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON;Po;0;L;;;;;N;;;;;
-13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;;
-13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;;
-13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;;
-13003;EGYPTIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;;
-13004;EGYPTIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;;
-13005;EGYPTIAN HIEROGLYPH A005A;Lo;0;L;;;;;N;;;;;
-13006;EGYPTIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;;
-13007;EGYPTIAN HIEROGLYPH A006A;Lo;0;L;;;;;N;;;;;
-13008;EGYPTIAN HIEROGLYPH A006B;Lo;0;L;;;;;N;;;;;
-13009;EGYPTIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;;
-1300A;EGYPTIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;;
-1300B;EGYPTIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;;
-1300C;EGYPTIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;;
-1300D;EGYPTIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;;
-1300E;EGYPTIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;;
-1300F;EGYPTIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;;
-13010;EGYPTIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;;
-13011;EGYPTIAN HIEROGLYPH A014A;Lo;0;L;;;;;N;;;;;
-13012;EGYPTIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;;
-13013;EGYPTIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;;
-13014;EGYPTIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;;
-13015;EGYPTIAN HIEROGLYPH A017A;Lo;0;L;;;;;N;;;;;
-13016;EGYPTIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;;
-13017;EGYPTIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;;
-13018;EGYPTIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;;
-13019;EGYPTIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;;
-1301A;EGYPTIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;;
-1301B;EGYPTIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;;
-1301C;EGYPTIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;;
-1301D;EGYPTIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;;
-1301E;EGYPTIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;;
-1301F;EGYPTIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;;
-13020;EGYPTIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;;
-13021;EGYPTIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;;
-13022;EGYPTIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;;
-13023;EGYPTIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;;
-13024;EGYPTIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;;
-13025;EGYPTIAN HIEROGLYPH A032A;Lo;0;L;;;;;N;;;;;
-13026;EGYPTIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;;
-13027;EGYPTIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;;
-13028;EGYPTIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;;
-13029;EGYPTIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;;
-1302A;EGYPTIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;;
-1302B;EGYPTIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;;
-1302C;EGYPTIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;;
-1302D;EGYPTIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;;
-1302E;EGYPTIAN HIEROGLYPH A040A;Lo;0;L;;;;;N;;;;;
-1302F;EGYPTIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;;
-13030;EGYPTIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;;
-13031;EGYPTIAN HIEROGLYPH A042A;Lo;0;L;;;;;N;;;;;
-13032;EGYPTIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;;
-13033;EGYPTIAN HIEROGLYPH A043A;Lo;0;L;;;;;N;;;;;
-13034;EGYPTIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;;
-13035;EGYPTIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;;
-13036;EGYPTIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;;
-13037;EGYPTIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;;
-13038;EGYPTIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;;
-13039;EGYPTIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;;
-1303A;EGYPTIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;;
-1303B;EGYPTIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;;
-1303C;EGYPTIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;;
-1303D;EGYPTIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;;
-1303E;EGYPTIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;;
-1303F;EGYPTIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;;
-13040;EGYPTIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;;
-13041;EGYPTIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;;
-13042;EGYPTIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;;
-13043;EGYPTIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;;
-13044;EGYPTIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;;
-13045;EGYPTIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;;
-13046;EGYPTIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;;
-13047;EGYPTIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;;
-13048;EGYPTIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;;
-13049;EGYPTIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;;
-1304A;EGYPTIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;;
-1304B;EGYPTIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;;
-1304C;EGYPTIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;;
-1304D;EGYPTIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;;
-1304E;EGYPTIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;;
-1304F;EGYPTIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;;
-13050;EGYPTIAN HIEROGLYPH B001;Lo;0;L;;;;;N;;;;;
-13051;EGYPTIAN HIEROGLYPH B002;Lo;0;L;;;;;N;;;;;
-13052;EGYPTIAN HIEROGLYPH B003;Lo;0;L;;;;;N;;;;;
-13053;EGYPTIAN HIEROGLYPH B004;Lo;0;L;;;;;N;;;;;
-13054;EGYPTIAN HIEROGLYPH B005;Lo;0;L;;;;;N;;;;;
-13055;EGYPTIAN HIEROGLYPH B005A;Lo;0;L;;;;;N;;;;;
-13056;EGYPTIAN HIEROGLYPH B006;Lo;0;L;;;;;N;;;;;
-13057;EGYPTIAN HIEROGLYPH B007;Lo;0;L;;;;;N;;;;;
-13058;EGYPTIAN HIEROGLYPH B008;Lo;0;L;;;;;N;;;;;
-13059;EGYPTIAN HIEROGLYPH B009;Lo;0;L;;;;;N;;;;;
-1305A;EGYPTIAN HIEROGLYPH C001;Lo;0;L;;;;;N;;;;;
-1305B;EGYPTIAN HIEROGLYPH C002;Lo;0;L;;;;;N;;;;;
-1305C;EGYPTIAN HIEROGLYPH C002A;Lo;0;L;;;;;N;;;;;
-1305D;EGYPTIAN HIEROGLYPH C002B;Lo;0;L;;;;;N;;;;;
-1305E;EGYPTIAN HIEROGLYPH C002C;Lo;0;L;;;;;N;;;;;
-1305F;EGYPTIAN HIEROGLYPH C003;Lo;0;L;;;;;N;;;;;
-13060;EGYPTIAN HIEROGLYPH C004;Lo;0;L;;;;;N;;;;;
-13061;EGYPTIAN HIEROGLYPH C005;Lo;0;L;;;;;N;;;;;
-13062;EGYPTIAN HIEROGLYPH C006;Lo;0;L;;;;;N;;;;;
-13063;EGYPTIAN HIEROGLYPH C007;Lo;0;L;;;;;N;;;;;
-13064;EGYPTIAN HIEROGLYPH C008;Lo;0;L;;;;;N;;;;;
-13065;EGYPTIAN HIEROGLYPH C009;Lo;0;L;;;;;N;;;;;
-13066;EGYPTIAN HIEROGLYPH C010;Lo;0;L;;;;;N;;;;;
-13067;EGYPTIAN HIEROGLYPH C010A;Lo;0;L;;;;;N;;;;;
-13068;EGYPTIAN HIEROGLYPH C011;Lo;0;L;;;;;N;;;;;
-13069;EGYPTIAN HIEROGLYPH C012;Lo;0;L;;;;;N;;;;;
-1306A;EGYPTIAN HIEROGLYPH C013;Lo;0;L;;;;;N;;;;;
-1306B;EGYPTIAN HIEROGLYPH C014;Lo;0;L;;;;;N;;;;;
-1306C;EGYPTIAN HIEROGLYPH C015;Lo;0;L;;;;;N;;;;;
-1306D;EGYPTIAN HIEROGLYPH C016;Lo;0;L;;;;;N;;;;;
-1306E;EGYPTIAN HIEROGLYPH C017;Lo;0;L;;;;;N;;;;;
-1306F;EGYPTIAN HIEROGLYPH C018;Lo;0;L;;;;;N;;;;;
-13070;EGYPTIAN HIEROGLYPH C019;Lo;0;L;;;;;N;;;;;
-13071;EGYPTIAN HIEROGLYPH C020;Lo;0;L;;;;;N;;;;;
-13072;EGYPTIAN HIEROGLYPH C021;Lo;0;L;;;;;N;;;;;
-13073;EGYPTIAN HIEROGLYPH C022;Lo;0;L;;;;;N;;;;;
-13074;EGYPTIAN HIEROGLYPH C023;Lo;0;L;;;;;N;;;;;
-13075;EGYPTIAN HIEROGLYPH C024;Lo;0;L;;;;;N;;;;;
-13076;EGYPTIAN HIEROGLYPH D001;Lo;0;L;;;;;N;;;;;
-13077;EGYPTIAN HIEROGLYPH D002;Lo;0;L;;;;;N;;;;;
-13078;EGYPTIAN HIEROGLYPH D003;Lo;0;L;;;;;N;;;;;
-13079;EGYPTIAN HIEROGLYPH D004;Lo;0;L;;;;;N;;;;;
-1307A;EGYPTIAN HIEROGLYPH D005;Lo;0;L;;;;;N;;;;;
-1307B;EGYPTIAN HIEROGLYPH D006;Lo;0;L;;;;;N;;;;;
-1307C;EGYPTIAN HIEROGLYPH D007;Lo;0;L;;;;;N;;;;;
-1307D;EGYPTIAN HIEROGLYPH D008;Lo;0;L;;;;;N;;;;;
-1307E;EGYPTIAN HIEROGLYPH D008A;Lo;0;L;;;;;N;;;;;
-1307F;EGYPTIAN HIEROGLYPH D009;Lo;0;L;;;;;N;;;;;
-13080;EGYPTIAN HIEROGLYPH D010;Lo;0;L;;;;;N;;;;;
-13081;EGYPTIAN HIEROGLYPH D011;Lo;0;L;;;;;N;;;;;
-13082;EGYPTIAN HIEROGLYPH D012;Lo;0;L;;;;;N;;;;;
-13083;EGYPTIAN HIEROGLYPH D013;Lo;0;L;;;;;N;;;;;
-13084;EGYPTIAN HIEROGLYPH D014;Lo;0;L;;;;;N;;;;;
-13085;EGYPTIAN HIEROGLYPH D015;Lo;0;L;;;;;N;;;;;
-13086;EGYPTIAN HIEROGLYPH D016;Lo;0;L;;;;;N;;;;;
-13087;EGYPTIAN HIEROGLYPH D017;Lo;0;L;;;;;N;;;;;
-13088;EGYPTIAN HIEROGLYPH D018;Lo;0;L;;;;;N;;;;;
-13089;EGYPTIAN HIEROGLYPH D019;Lo;0;L;;;;;N;;;;;
-1308A;EGYPTIAN HIEROGLYPH D020;Lo;0;L;;;;;N;;;;;
-1308B;EGYPTIAN HIEROGLYPH D021;Lo;0;L;;;;;N;;;;;
-1308C;EGYPTIAN HIEROGLYPH D022;Lo;0;L;;;;;N;;;;;
-1308D;EGYPTIAN HIEROGLYPH D023;Lo;0;L;;;;;N;;;;;
-1308E;EGYPTIAN HIEROGLYPH D024;Lo;0;L;;;;;N;;;;;
-1308F;EGYPTIAN HIEROGLYPH D025;Lo;0;L;;;;;N;;;;;
-13090;EGYPTIAN HIEROGLYPH D026;Lo;0;L;;;;;N;;;;;
-13091;EGYPTIAN HIEROGLYPH D027;Lo;0;L;;;;;N;;;;;
-13092;EGYPTIAN HIEROGLYPH D027A;Lo;0;L;;;;;N;;;;;
-13093;EGYPTIAN HIEROGLYPH D028;Lo;0;L;;;;;N;;;;;
-13094;EGYPTIAN HIEROGLYPH D029;Lo;0;L;;;;;N;;;;;
-13095;EGYPTIAN HIEROGLYPH D030;Lo;0;L;;;;;N;;;;;
-13096;EGYPTIAN HIEROGLYPH D031;Lo;0;L;;;;;N;;;;;
-13097;EGYPTIAN HIEROGLYPH D031A;Lo;0;L;;;;;N;;;;;
-13098;EGYPTIAN HIEROGLYPH D032;Lo;0;L;;;;;N;;;;;
-13099;EGYPTIAN HIEROGLYPH D033;Lo;0;L;;;;;N;;;;;
-1309A;EGYPTIAN HIEROGLYPH D034;Lo;0;L;;;;;N;;;;;
-1309B;EGYPTIAN HIEROGLYPH D034A;Lo;0;L;;;;;N;;;;;
-1309C;EGYPTIAN HIEROGLYPH D035;Lo;0;L;;;;;N;;;;;
-1309D;EGYPTIAN HIEROGLYPH D036;Lo;0;L;;;;;N;;;;;
-1309E;EGYPTIAN HIEROGLYPH D037;Lo;0;L;;;;;N;;;;;
-1309F;EGYPTIAN HIEROGLYPH D038;Lo;0;L;;;;;N;;;;;
-130A0;EGYPTIAN HIEROGLYPH D039;Lo;0;L;;;;;N;;;;;
-130A1;EGYPTIAN HIEROGLYPH D040;Lo;0;L;;;;;N;;;;;
-130A2;EGYPTIAN HIEROGLYPH D041;Lo;0;L;;;;;N;;;;;
-130A3;EGYPTIAN HIEROGLYPH D042;Lo;0;L;;;;;N;;;;;
-130A4;EGYPTIAN HIEROGLYPH D043;Lo;0;L;;;;;N;;;;;
-130A5;EGYPTIAN HIEROGLYPH D044;Lo;0;L;;;;;N;;;;;
-130A6;EGYPTIAN HIEROGLYPH D045;Lo;0;L;;;;;N;;;;;
-130A7;EGYPTIAN HIEROGLYPH D046;Lo;0;L;;;;;N;;;;;
-130A8;EGYPTIAN HIEROGLYPH D046A;Lo;0;L;;;;;N;;;;;
-130A9;EGYPTIAN HIEROGLYPH D047;Lo;0;L;;;;;N;;;;;
-130AA;EGYPTIAN HIEROGLYPH D048;Lo;0;L;;;;;N;;;;;
-130AB;EGYPTIAN HIEROGLYPH D048A;Lo;0;L;;;;;N;;;;;
-130AC;EGYPTIAN HIEROGLYPH D049;Lo;0;L;;;;;N;;;;;
-130AD;EGYPTIAN HIEROGLYPH D050;Lo;0;L;;;;;N;;;;;
-130AE;EGYPTIAN HIEROGLYPH D050A;Lo;0;L;;;;;N;;;;;
-130AF;EGYPTIAN HIEROGLYPH D050B;Lo;0;L;;;;;N;;;;;
-130B0;EGYPTIAN HIEROGLYPH D050C;Lo;0;L;;;;;N;;;;;
-130B1;EGYPTIAN HIEROGLYPH D050D;Lo;0;L;;;;;N;;;;;
-130B2;EGYPTIAN HIEROGLYPH D050E;Lo;0;L;;;;;N;;;;;
-130B3;EGYPTIAN HIEROGLYPH D050F;Lo;0;L;;;;;N;;;;;
-130B4;EGYPTIAN HIEROGLYPH D050G;Lo;0;L;;;;;N;;;;;
-130B5;EGYPTIAN HIEROGLYPH D050H;Lo;0;L;;;;;N;;;;;
-130B6;EGYPTIAN HIEROGLYPH D050I;Lo;0;L;;;;;N;;;;;
-130B7;EGYPTIAN HIEROGLYPH D051;Lo;0;L;;;;;N;;;;;
-130B8;EGYPTIAN HIEROGLYPH D052;Lo;0;L;;;;;N;;;;;
-130B9;EGYPTIAN HIEROGLYPH D052A;Lo;0;L;;;;;N;;;;;
-130BA;EGYPTIAN HIEROGLYPH D053;Lo;0;L;;;;;N;;;;;
-130BB;EGYPTIAN HIEROGLYPH D054;Lo;0;L;;;;;N;;;;;
-130BC;EGYPTIAN HIEROGLYPH D054A;Lo;0;L;;;;;N;;;;;
-130BD;EGYPTIAN HIEROGLYPH D055;Lo;0;L;;;;;N;;;;;
-130BE;EGYPTIAN HIEROGLYPH D056;Lo;0;L;;;;;N;;;;;
-130BF;EGYPTIAN HIEROGLYPH D057;Lo;0;L;;;;;N;;;;;
-130C0;EGYPTIAN HIEROGLYPH D058;Lo;0;L;;;;;N;;;;;
-130C1;EGYPTIAN HIEROGLYPH D059;Lo;0;L;;;;;N;;;;;
-130C2;EGYPTIAN HIEROGLYPH D060;Lo;0;L;;;;;N;;;;;
-130C3;EGYPTIAN HIEROGLYPH D061;Lo;0;L;;;;;N;;;;;
-130C4;EGYPTIAN HIEROGLYPH D062;Lo;0;L;;;;;N;;;;;
-130C5;EGYPTIAN HIEROGLYPH D063;Lo;0;L;;;;;N;;;;;
-130C6;EGYPTIAN HIEROGLYPH D064;Lo;0;L;;;;;N;;;;;
-130C7;EGYPTIAN HIEROGLYPH D065;Lo;0;L;;;;;N;;;;;
-130C8;EGYPTIAN HIEROGLYPH D066;Lo;0;L;;;;;N;;;;;
-130C9;EGYPTIAN HIEROGLYPH D067;Lo;0;L;;;;;N;;;;;
-130CA;EGYPTIAN HIEROGLYPH D067A;Lo;0;L;;;;;N;;;;;
-130CB;EGYPTIAN HIEROGLYPH D067B;Lo;0;L;;;;;N;;;;;
-130CC;EGYPTIAN HIEROGLYPH D067C;Lo;0;L;;;;;N;;;;;
-130CD;EGYPTIAN HIEROGLYPH D067D;Lo;0;L;;;;;N;;;;;
-130CE;EGYPTIAN HIEROGLYPH D067E;Lo;0;L;;;;;N;;;;;
-130CF;EGYPTIAN HIEROGLYPH D067F;Lo;0;L;;;;;N;;;;;
-130D0;EGYPTIAN HIEROGLYPH D067G;Lo;0;L;;;;;N;;;;;
-130D1;EGYPTIAN HIEROGLYPH D067H;Lo;0;L;;;;;N;;;;;
-130D2;EGYPTIAN HIEROGLYPH E001;Lo;0;L;;;;;N;;;;;
-130D3;EGYPTIAN HIEROGLYPH E002;Lo;0;L;;;;;N;;;;;
-130D4;EGYPTIAN HIEROGLYPH E003;Lo;0;L;;;;;N;;;;;
-130D5;EGYPTIAN HIEROGLYPH E004;Lo;0;L;;;;;N;;;;;
-130D6;EGYPTIAN HIEROGLYPH E005;Lo;0;L;;;;;N;;;;;
-130D7;EGYPTIAN HIEROGLYPH E006;Lo;0;L;;;;;N;;;;;
-130D8;EGYPTIAN HIEROGLYPH E007;Lo;0;L;;;;;N;;;;;
-130D9;EGYPTIAN HIEROGLYPH E008;Lo;0;L;;;;;N;;;;;
-130DA;EGYPTIAN HIEROGLYPH E008A;Lo;0;L;;;;;N;;;;;
-130DB;EGYPTIAN HIEROGLYPH E009;Lo;0;L;;;;;N;;;;;
-130DC;EGYPTIAN HIEROGLYPH E009A;Lo;0;L;;;;;N;;;;;
-130DD;EGYPTIAN HIEROGLYPH E010;Lo;0;L;;;;;N;;;;;
-130DE;EGYPTIAN HIEROGLYPH E011;Lo;0;L;;;;;N;;;;;
-130DF;EGYPTIAN HIEROGLYPH E012;Lo;0;L;;;;;N;;;;;
-130E0;EGYPTIAN HIEROGLYPH E013;Lo;0;L;;;;;N;;;;;
-130E1;EGYPTIAN HIEROGLYPH E014;Lo;0;L;;;;;N;;;;;
-130E2;EGYPTIAN HIEROGLYPH E015;Lo;0;L;;;;;N;;;;;
-130E3;EGYPTIAN HIEROGLYPH E016;Lo;0;L;;;;;N;;;;;
-130E4;EGYPTIAN HIEROGLYPH E016A;Lo;0;L;;;;;N;;;;;
-130E5;EGYPTIAN HIEROGLYPH E017;Lo;0;L;;;;;N;;;;;
-130E6;EGYPTIAN HIEROGLYPH E017A;Lo;0;L;;;;;N;;;;;
-130E7;EGYPTIAN HIEROGLYPH E018;Lo;0;L;;;;;N;;;;;
-130E8;EGYPTIAN HIEROGLYPH E019;Lo;0;L;;;;;N;;;;;
-130E9;EGYPTIAN HIEROGLYPH E020;Lo;0;L;;;;;N;;;;;
-130EA;EGYPTIAN HIEROGLYPH E020A;Lo;0;L;;;;;N;;;;;
-130EB;EGYPTIAN HIEROGLYPH E021;Lo;0;L;;;;;N;;;;;
-130EC;EGYPTIAN HIEROGLYPH E022;Lo;0;L;;;;;N;;;;;
-130ED;EGYPTIAN HIEROGLYPH E023;Lo;0;L;;;;;N;;;;;
-130EE;EGYPTIAN HIEROGLYPH E024;Lo;0;L;;;;;N;;;;;
-130EF;EGYPTIAN HIEROGLYPH E025;Lo;0;L;;;;;N;;;;;
-130F0;EGYPTIAN HIEROGLYPH E026;Lo;0;L;;;;;N;;;;;
-130F1;EGYPTIAN HIEROGLYPH E027;Lo;0;L;;;;;N;;;;;
-130F2;EGYPTIAN HIEROGLYPH E028;Lo;0;L;;;;;N;;;;;
-130F3;EGYPTIAN HIEROGLYPH E028A;Lo;0;L;;;;;N;;;;;
-130F4;EGYPTIAN HIEROGLYPH E029;Lo;0;L;;;;;N;;;;;
-130F5;EGYPTIAN HIEROGLYPH E030;Lo;0;L;;;;;N;;;;;
-130F6;EGYPTIAN HIEROGLYPH E031;Lo;0;L;;;;;N;;;;;
-130F7;EGYPTIAN HIEROGLYPH E032;Lo;0;L;;;;;N;;;;;
-130F8;EGYPTIAN HIEROGLYPH E033;Lo;0;L;;;;;N;;;;;
-130F9;EGYPTIAN HIEROGLYPH E034;Lo;0;L;;;;;N;;;;;
-130FA;EGYPTIAN HIEROGLYPH E034A;Lo;0;L;;;;;N;;;;;
-130FB;EGYPTIAN HIEROGLYPH E036;Lo;0;L;;;;;N;;;;;
-130FC;EGYPTIAN HIEROGLYPH E037;Lo;0;L;;;;;N;;;;;
-130FD;EGYPTIAN HIEROGLYPH E038;Lo;0;L;;;;;N;;;;;
-130FE;EGYPTIAN HIEROGLYPH F001;Lo;0;L;;;;;N;;;;;
-130FF;EGYPTIAN HIEROGLYPH F001A;Lo;0;L;;;;;N;;;;;
-13100;EGYPTIAN HIEROGLYPH F002;Lo;0;L;;;;;N;;;;;
-13101;EGYPTIAN HIEROGLYPH F003;Lo;0;L;;;;;N;;;;;
-13102;EGYPTIAN HIEROGLYPH F004;Lo;0;L;;;;;N;;;;;
-13103;EGYPTIAN HIEROGLYPH F005;Lo;0;L;;;;;N;;;;;
-13104;EGYPTIAN HIEROGLYPH F006;Lo;0;L;;;;;N;;;;;
-13105;EGYPTIAN HIEROGLYPH F007;Lo;0;L;;;;;N;;;;;
-13106;EGYPTIAN HIEROGLYPH F008;Lo;0;L;;;;;N;;;;;
-13107;EGYPTIAN HIEROGLYPH F009;Lo;0;L;;;;;N;;;;;
-13108;EGYPTIAN HIEROGLYPH F010;Lo;0;L;;;;;N;;;;;
-13109;EGYPTIAN HIEROGLYPH F011;Lo;0;L;;;;;N;;;;;
-1310A;EGYPTIAN HIEROGLYPH F012;Lo;0;L;;;;;N;;;;;
-1310B;EGYPTIAN HIEROGLYPH F013;Lo;0;L;;;;;N;;;;;
-1310C;EGYPTIAN HIEROGLYPH F013A;Lo;0;L;;;;;N;;;;;
-1310D;EGYPTIAN HIEROGLYPH F014;Lo;0;L;;;;;N;;;;;
-1310E;EGYPTIAN HIEROGLYPH F015;Lo;0;L;;;;;N;;;;;
-1310F;EGYPTIAN HIEROGLYPH F016;Lo;0;L;;;;;N;;;;;
-13110;EGYPTIAN HIEROGLYPH F017;Lo;0;L;;;;;N;;;;;
-13111;EGYPTIAN HIEROGLYPH F018;Lo;0;L;;;;;N;;;;;
-13112;EGYPTIAN HIEROGLYPH F019;Lo;0;L;;;;;N;;;;;
-13113;EGYPTIAN HIEROGLYPH F020;Lo;0;L;;;;;N;;;;;
-13114;EGYPTIAN HIEROGLYPH F021;Lo;0;L;;;;;N;;;;;
-13115;EGYPTIAN HIEROGLYPH F021A;Lo;0;L;;;;;N;;;;;
-13116;EGYPTIAN HIEROGLYPH F022;Lo;0;L;;;;;N;;;;;
-13117;EGYPTIAN HIEROGLYPH F023;Lo;0;L;;;;;N;;;;;
-13118;EGYPTIAN HIEROGLYPH F024;Lo;0;L;;;;;N;;;;;
-13119;EGYPTIAN HIEROGLYPH F025;Lo;0;L;;;;;N;;;;;
-1311A;EGYPTIAN HIEROGLYPH F026;Lo;0;L;;;;;N;;;;;
-1311B;EGYPTIAN HIEROGLYPH F027;Lo;0;L;;;;;N;;;;;
-1311C;EGYPTIAN HIEROGLYPH F028;Lo;0;L;;;;;N;;;;;
-1311D;EGYPTIAN HIEROGLYPH F029;Lo;0;L;;;;;N;;;;;
-1311E;EGYPTIAN HIEROGLYPH F030;Lo;0;L;;;;;N;;;;;
-1311F;EGYPTIAN HIEROGLYPH F031;Lo;0;L;;;;;N;;;;;
-13120;EGYPTIAN HIEROGLYPH F031A;Lo;0;L;;;;;N;;;;;
-13121;EGYPTIAN HIEROGLYPH F032;Lo;0;L;;;;;N;;;;;
-13122;EGYPTIAN HIEROGLYPH F033;Lo;0;L;;;;;N;;;;;
-13123;EGYPTIAN HIEROGLYPH F034;Lo;0;L;;;;;N;;;;;
-13124;EGYPTIAN HIEROGLYPH F035;Lo;0;L;;;;;N;;;;;
-13125;EGYPTIAN HIEROGLYPH F036;Lo;0;L;;;;;N;;;;;
-13126;EGYPTIAN HIEROGLYPH F037;Lo;0;L;;;;;N;;;;;
-13127;EGYPTIAN HIEROGLYPH F037A;Lo;0;L;;;;;N;;;;;
-13128;EGYPTIAN HIEROGLYPH F038;Lo;0;L;;;;;N;;;;;
-13129;EGYPTIAN HIEROGLYPH F038A;Lo;0;L;;;;;N;;;;;
-1312A;EGYPTIAN HIEROGLYPH F039;Lo;0;L;;;;;N;;;;;
-1312B;EGYPTIAN HIEROGLYPH F040;Lo;0;L;;;;;N;;;;;
-1312C;EGYPTIAN HIEROGLYPH F041;Lo;0;L;;;;;N;;;;;
-1312D;EGYPTIAN HIEROGLYPH F042;Lo;0;L;;;;;N;;;;;
-1312E;EGYPTIAN HIEROGLYPH F043;Lo;0;L;;;;;N;;;;;
-1312F;EGYPTIAN HIEROGLYPH F044;Lo;0;L;;;;;N;;;;;
-13130;EGYPTIAN HIEROGLYPH F045;Lo;0;L;;;;;N;;;;;
-13131;EGYPTIAN HIEROGLYPH F045A;Lo;0;L;;;;;N;;;;;
-13132;EGYPTIAN HIEROGLYPH F046;Lo;0;L;;;;;N;;;;;
-13133;EGYPTIAN HIEROGLYPH F046A;Lo;0;L;;;;;N;;;;;
-13134;EGYPTIAN HIEROGLYPH F047;Lo;0;L;;;;;N;;;;;
-13135;EGYPTIAN HIEROGLYPH F047A;Lo;0;L;;;;;N;;;;;
-13136;EGYPTIAN HIEROGLYPH F048;Lo;0;L;;;;;N;;;;;
-13137;EGYPTIAN HIEROGLYPH F049;Lo;0;L;;;;;N;;;;;
-13138;EGYPTIAN HIEROGLYPH F050;Lo;0;L;;;;;N;;;;;
-13139;EGYPTIAN HIEROGLYPH F051;Lo;0;L;;;;;N;;;;;
-1313A;EGYPTIAN HIEROGLYPH F051A;Lo;0;L;;;;;N;;;;;
-1313B;EGYPTIAN HIEROGLYPH F051B;Lo;0;L;;;;;N;;;;;
-1313C;EGYPTIAN HIEROGLYPH F051C;Lo;0;L;;;;;N;;;;;
-1313D;EGYPTIAN HIEROGLYPH F052;Lo;0;L;;;;;N;;;;;
-1313E;EGYPTIAN HIEROGLYPH F053;Lo;0;L;;;;;N;;;;;
-1313F;EGYPTIAN HIEROGLYPH G001;Lo;0;L;;;;;N;;;;;
-13140;EGYPTIAN HIEROGLYPH G002;Lo;0;L;;;;;N;;;;;
-13141;EGYPTIAN HIEROGLYPH G003;Lo;0;L;;;;;N;;;;;
-13142;EGYPTIAN HIEROGLYPH G004;Lo;0;L;;;;;N;;;;;
-13143;EGYPTIAN HIEROGLYPH G005;Lo;0;L;;;;;N;;;;;
-13144;EGYPTIAN HIEROGLYPH G006;Lo;0;L;;;;;N;;;;;
-13145;EGYPTIAN HIEROGLYPH G006A;Lo;0;L;;;;;N;;;;;
-13146;EGYPTIAN HIEROGLYPH G007;Lo;0;L;;;;;N;;;;;
-13147;EGYPTIAN HIEROGLYPH G007A;Lo;0;L;;;;;N;;;;;
-13148;EGYPTIAN HIEROGLYPH G007B;Lo;0;L;;;;;N;;;;;
-13149;EGYPTIAN HIEROGLYPH G008;Lo;0;L;;;;;N;;;;;
-1314A;EGYPTIAN HIEROGLYPH G009;Lo;0;L;;;;;N;;;;;
-1314B;EGYPTIAN HIEROGLYPH G010;Lo;0;L;;;;;N;;;;;
-1314C;EGYPTIAN HIEROGLYPH G011;Lo;0;L;;;;;N;;;;;
-1314D;EGYPTIAN HIEROGLYPH G011A;Lo;0;L;;;;;N;;;;;
-1314E;EGYPTIAN HIEROGLYPH G012;Lo;0;L;;;;;N;;;;;
-1314F;EGYPTIAN HIEROGLYPH G013;Lo;0;L;;;;;N;;;;;
-13150;EGYPTIAN HIEROGLYPH G014;Lo;0;L;;;;;N;;;;;
-13151;EGYPTIAN HIEROGLYPH G015;Lo;0;L;;;;;N;;;;;
-13152;EGYPTIAN HIEROGLYPH G016;Lo;0;L;;;;;N;;;;;
-13153;EGYPTIAN HIEROGLYPH G017;Lo;0;L;;;;;N;;;;;
-13154;EGYPTIAN HIEROGLYPH G018;Lo;0;L;;;;;N;;;;;
-13155;EGYPTIAN HIEROGLYPH G019;Lo;0;L;;;;;N;;;;;
-13156;EGYPTIAN HIEROGLYPH G020;Lo;0;L;;;;;N;;;;;
-13157;EGYPTIAN HIEROGLYPH G020A;Lo;0;L;;;;;N;;;;;
-13158;EGYPTIAN HIEROGLYPH G021;Lo;0;L;;;;;N;;;;;
-13159;EGYPTIAN HIEROGLYPH G022;Lo;0;L;;;;;N;;;;;
-1315A;EGYPTIAN HIEROGLYPH G023;Lo;0;L;;;;;N;;;;;
-1315B;EGYPTIAN HIEROGLYPH G024;Lo;0;L;;;;;N;;;;;
-1315C;EGYPTIAN HIEROGLYPH G025;Lo;0;L;;;;;N;;;;;
-1315D;EGYPTIAN HIEROGLYPH G026;Lo;0;L;;;;;N;;;;;
-1315E;EGYPTIAN HIEROGLYPH G026A;Lo;0;L;;;;;N;;;;;
-1315F;EGYPTIAN HIEROGLYPH G027;Lo;0;L;;;;;N;;;;;
-13160;EGYPTIAN HIEROGLYPH G028;Lo;0;L;;;;;N;;;;;
-13161;EGYPTIAN HIEROGLYPH G029;Lo;0;L;;;;;N;;;;;
-13162;EGYPTIAN HIEROGLYPH G030;Lo;0;L;;;;;N;;;;;
-13163;EGYPTIAN HIEROGLYPH G031;Lo;0;L;;;;;N;;;;;
-13164;EGYPTIAN HIEROGLYPH G032;Lo;0;L;;;;;N;;;;;
-13165;EGYPTIAN HIEROGLYPH G033;Lo;0;L;;;;;N;;;;;
-13166;EGYPTIAN HIEROGLYPH G034;Lo;0;L;;;;;N;;;;;
-13167;EGYPTIAN HIEROGLYPH G035;Lo;0;L;;;;;N;;;;;
-13168;EGYPTIAN HIEROGLYPH G036;Lo;0;L;;;;;N;;;;;
-13169;EGYPTIAN HIEROGLYPH G036A;Lo;0;L;;;;;N;;;;;
-1316A;EGYPTIAN HIEROGLYPH G037;Lo;0;L;;;;;N;;;;;
-1316B;EGYPTIAN HIEROGLYPH G037A;Lo;0;L;;;;;N;;;;;
-1316C;EGYPTIAN HIEROGLYPH G038;Lo;0;L;;;;;N;;;;;
-1316D;EGYPTIAN HIEROGLYPH G039;Lo;0;L;;;;;N;;;;;
-1316E;EGYPTIAN HIEROGLYPH G040;Lo;0;L;;;;;N;;;;;
-1316F;EGYPTIAN HIEROGLYPH G041;Lo;0;L;;;;;N;;;;;
-13170;EGYPTIAN HIEROGLYPH G042;Lo;0;L;;;;;N;;;;;
-13171;EGYPTIAN HIEROGLYPH G043;Lo;0;L;;;;;N;;;;;
-13172;EGYPTIAN HIEROGLYPH G043A;Lo;0;L;;;;;N;;;;;
-13173;EGYPTIAN HIEROGLYPH G044;Lo;0;L;;;;;N;;;;;
-13174;EGYPTIAN HIEROGLYPH G045;Lo;0;L;;;;;N;;;;;
-13175;EGYPTIAN HIEROGLYPH G045A;Lo;0;L;;;;;N;;;;;
-13176;EGYPTIAN HIEROGLYPH G046;Lo;0;L;;;;;N;;;;;
-13177;EGYPTIAN HIEROGLYPH G047;Lo;0;L;;;;;N;;;;;
-13178;EGYPTIAN HIEROGLYPH G048;Lo;0;L;;;;;N;;;;;
-13179;EGYPTIAN HIEROGLYPH G049;Lo;0;L;;;;;N;;;;;
-1317A;EGYPTIAN HIEROGLYPH G050;Lo;0;L;;;;;N;;;;;
-1317B;EGYPTIAN HIEROGLYPH G051;Lo;0;L;;;;;N;;;;;
-1317C;EGYPTIAN HIEROGLYPH G052;Lo;0;L;;;;;N;;;;;
-1317D;EGYPTIAN HIEROGLYPH G053;Lo;0;L;;;;;N;;;;;
-1317E;EGYPTIAN HIEROGLYPH G054;Lo;0;L;;;;;N;;;;;
-1317F;EGYPTIAN HIEROGLYPH H001;Lo;0;L;;;;;N;;;;;
-13180;EGYPTIAN HIEROGLYPH H002;Lo;0;L;;;;;N;;;;;
-13181;EGYPTIAN HIEROGLYPH H003;Lo;0;L;;;;;N;;;;;
-13182;EGYPTIAN HIEROGLYPH H004;Lo;0;L;;;;;N;;;;;
-13183;EGYPTIAN HIEROGLYPH H005;Lo;0;L;;;;;N;;;;;
-13184;EGYPTIAN HIEROGLYPH H006;Lo;0;L;;;;;N;;;;;
-13185;EGYPTIAN HIEROGLYPH H006A;Lo;0;L;;;;;N;;;;;
-13186;EGYPTIAN HIEROGLYPH H007;Lo;0;L;;;;;N;;;;;
-13187;EGYPTIAN HIEROGLYPH H008;Lo;0;L;;;;;N;;;;;
-13188;EGYPTIAN HIEROGLYPH I001;Lo;0;L;;;;;N;;;;;
-13189;EGYPTIAN HIEROGLYPH I002;Lo;0;L;;;;;N;;;;;
-1318A;EGYPTIAN HIEROGLYPH I003;Lo;0;L;;;;;N;;;;;
-1318B;EGYPTIAN HIEROGLYPH I004;Lo;0;L;;;;;N;;;;;
-1318C;EGYPTIAN HIEROGLYPH I005;Lo;0;L;;;;;N;;;;;
-1318D;EGYPTIAN HIEROGLYPH I005A;Lo;0;L;;;;;N;;;;;
-1318E;EGYPTIAN HIEROGLYPH I006;Lo;0;L;;;;;N;;;;;
-1318F;EGYPTIAN HIEROGLYPH I007;Lo;0;L;;;;;N;;;;;
-13190;EGYPTIAN HIEROGLYPH I008;Lo;0;L;;;;;N;;;;;
-13191;EGYPTIAN HIEROGLYPH I009;Lo;0;L;;;;;N;;;;;
-13192;EGYPTIAN HIEROGLYPH I009A;Lo;0;L;;;;;N;;;;;
-13193;EGYPTIAN HIEROGLYPH I010;Lo;0;L;;;;;N;;;;;
-13194;EGYPTIAN HIEROGLYPH I010A;Lo;0;L;;;;;N;;;;;
-13195;EGYPTIAN HIEROGLYPH I011;Lo;0;L;;;;;N;;;;;
-13196;EGYPTIAN HIEROGLYPH I011A;Lo;0;L;;;;;N;;;;;
-13197;EGYPTIAN HIEROGLYPH I012;Lo;0;L;;;;;N;;;;;
-13198;EGYPTIAN HIEROGLYPH I013;Lo;0;L;;;;;N;;;;;
-13199;EGYPTIAN HIEROGLYPH I014;Lo;0;L;;;;;N;;;;;
-1319A;EGYPTIAN HIEROGLYPH I015;Lo;0;L;;;;;N;;;;;
-1319B;EGYPTIAN HIEROGLYPH K001;Lo;0;L;;;;;N;;;;;
-1319C;EGYPTIAN HIEROGLYPH K002;Lo;0;L;;;;;N;;;;;
-1319D;EGYPTIAN HIEROGLYPH K003;Lo;0;L;;;;;N;;;;;
-1319E;EGYPTIAN HIEROGLYPH K004;Lo;0;L;;;;;N;;;;;
-1319F;EGYPTIAN HIEROGLYPH K005;Lo;0;L;;;;;N;;;;;
-131A0;EGYPTIAN HIEROGLYPH K006;Lo;0;L;;;;;N;;;;;
-131A1;EGYPTIAN HIEROGLYPH K007;Lo;0;L;;;;;N;;;;;
-131A2;EGYPTIAN HIEROGLYPH K008;Lo;0;L;;;;;N;;;;;
-131A3;EGYPTIAN HIEROGLYPH L001;Lo;0;L;;;;;N;;;;;
-131A4;EGYPTIAN HIEROGLYPH L002;Lo;0;L;;;;;N;;;;;
-131A5;EGYPTIAN HIEROGLYPH L002A;Lo;0;L;;;;;N;;;;;
-131A6;EGYPTIAN HIEROGLYPH L003;Lo;0;L;;;;;N;;;;;
-131A7;EGYPTIAN HIEROGLYPH L004;Lo;0;L;;;;;N;;;;;
-131A8;EGYPTIAN HIEROGLYPH L005;Lo;0;L;;;;;N;;;;;
-131A9;EGYPTIAN HIEROGLYPH L006;Lo;0;L;;;;;N;;;;;
-131AA;EGYPTIAN HIEROGLYPH L006A;Lo;0;L;;;;;N;;;;;
-131AB;EGYPTIAN HIEROGLYPH L007;Lo;0;L;;;;;N;;;;;
-131AC;EGYPTIAN HIEROGLYPH L008;Lo;0;L;;;;;N;;;;;
-131AD;EGYPTIAN HIEROGLYPH M001;Lo;0;L;;;;;N;;;;;
-131AE;EGYPTIAN HIEROGLYPH M001A;Lo;0;L;;;;;N;;;;;
-131AF;EGYPTIAN HIEROGLYPH M001B;Lo;0;L;;;;;N;;;;;
-131B0;EGYPTIAN HIEROGLYPH M002;Lo;0;L;;;;;N;;;;;
-131B1;EGYPTIAN HIEROGLYPH M003;Lo;0;L;;;;;N;;;;;
-131B2;EGYPTIAN HIEROGLYPH M003A;Lo;0;L;;;;;N;;;;;
-131B3;EGYPTIAN HIEROGLYPH M004;Lo;0;L;;;;;N;;;;;
-131B4;EGYPTIAN HIEROGLYPH M005;Lo;0;L;;;;;N;;;;;
-131B5;EGYPTIAN HIEROGLYPH M006;Lo;0;L;;;;;N;;;;;
-131B6;EGYPTIAN HIEROGLYPH M007;Lo;0;L;;;;;N;;;;;
-131B7;EGYPTIAN HIEROGLYPH M008;Lo;0;L;;;;;N;;;;;
-131B8;EGYPTIAN HIEROGLYPH M009;Lo;0;L;;;;;N;;;;;
-131B9;EGYPTIAN HIEROGLYPH M010;Lo;0;L;;;;;N;;;;;
-131BA;EGYPTIAN HIEROGLYPH M010A;Lo;0;L;;;;;N;;;;;
-131BB;EGYPTIAN HIEROGLYPH M011;Lo;0;L;;;;;N;;;;;
-131BC;EGYPTIAN HIEROGLYPH M012;Lo;0;L;;;;;N;;;;;
-131BD;EGYPTIAN HIEROGLYPH M012A;Lo;0;L;;;;;N;;;;;
-131BE;EGYPTIAN HIEROGLYPH M012B;Lo;0;L;;;;;N;;;;;
-131BF;EGYPTIAN HIEROGLYPH M012C;Lo;0;L;;;;;N;;;;;
-131C0;EGYPTIAN HIEROGLYPH M012D;Lo;0;L;;;;;N;;;;;
-131C1;EGYPTIAN HIEROGLYPH M012E;Lo;0;L;;;;;N;;;;;
-131C2;EGYPTIAN HIEROGLYPH M012F;Lo;0;L;;;;;N;;;;;
-131C3;EGYPTIAN HIEROGLYPH M012G;Lo;0;L;;;;;N;;;;;
-131C4;EGYPTIAN HIEROGLYPH M012H;Lo;0;L;;;;;N;;;;;
-131C5;EGYPTIAN HIEROGLYPH M013;Lo;0;L;;;;;N;;;;;
-131C6;EGYPTIAN HIEROGLYPH M014;Lo;0;L;;;;;N;;;;;
-131C7;EGYPTIAN HIEROGLYPH M015;Lo;0;L;;;;;N;;;;;
-131C8;EGYPTIAN HIEROGLYPH M015A;Lo;0;L;;;;;N;;;;;
-131C9;EGYPTIAN HIEROGLYPH M016;Lo;0;L;;;;;N;;;;;
-131CA;EGYPTIAN HIEROGLYPH M016A;Lo;0;L;;;;;N;;;;;
-131CB;EGYPTIAN HIEROGLYPH M017;Lo;0;L;;;;;N;;;;;
-131CC;EGYPTIAN HIEROGLYPH M017A;Lo;0;L;;;;;N;;;;;
-131CD;EGYPTIAN HIEROGLYPH M018;Lo;0;L;;;;;N;;;;;
-131CE;EGYPTIAN HIEROGLYPH M019;Lo;0;L;;;;;N;;;;;
-131CF;EGYPTIAN HIEROGLYPH M020;Lo;0;L;;;;;N;;;;;
-131D0;EGYPTIAN HIEROGLYPH M021;Lo;0;L;;;;;N;;;;;
-131D1;EGYPTIAN HIEROGLYPH M022;Lo;0;L;;;;;N;;;;;
-131D2;EGYPTIAN HIEROGLYPH M022A;Lo;0;L;;;;;N;;;;;
-131D3;EGYPTIAN HIEROGLYPH M023;Lo;0;L;;;;;N;;;;;
-131D4;EGYPTIAN HIEROGLYPH M024;Lo;0;L;;;;;N;;;;;
-131D5;EGYPTIAN HIEROGLYPH M024A;Lo;0;L;;;;;N;;;;;
-131D6;EGYPTIAN HIEROGLYPH M025;Lo;0;L;;;;;N;;;;;
-131D7;EGYPTIAN HIEROGLYPH M026;Lo;0;L;;;;;N;;;;;
-131D8;EGYPTIAN HIEROGLYPH M027;Lo;0;L;;;;;N;;;;;
-131D9;EGYPTIAN HIEROGLYPH M028;Lo;0;L;;;;;N;;;;;
-131DA;EGYPTIAN HIEROGLYPH M028A;Lo;0;L;;;;;N;;;;;
-131DB;EGYPTIAN HIEROGLYPH M029;Lo;0;L;;;;;N;;;;;
-131DC;EGYPTIAN HIEROGLYPH M030;Lo;0;L;;;;;N;;;;;
-131DD;EGYPTIAN HIEROGLYPH M031;Lo;0;L;;;;;N;;;;;
-131DE;EGYPTIAN HIEROGLYPH M031A;Lo;0;L;;;;;N;;;;;
-131DF;EGYPTIAN HIEROGLYPH M032;Lo;0;L;;;;;N;;;;;
-131E0;EGYPTIAN HIEROGLYPH M033;Lo;0;L;;;;;N;;;;;
-131E1;EGYPTIAN HIEROGLYPH M033A;Lo;0;L;;;;;N;;;;;
-131E2;EGYPTIAN HIEROGLYPH M033B;Lo;0;L;;;;;N;;;;;
-131E3;EGYPTIAN HIEROGLYPH M034;Lo;0;L;;;;;N;;;;;
-131E4;EGYPTIAN HIEROGLYPH M035;Lo;0;L;;;;;N;;;;;
-131E5;EGYPTIAN HIEROGLYPH M036;Lo;0;L;;;;;N;;;;;
-131E6;EGYPTIAN HIEROGLYPH M037;Lo;0;L;;;;;N;;;;;
-131E7;EGYPTIAN HIEROGLYPH M038;Lo;0;L;;;;;N;;;;;
-131E8;EGYPTIAN HIEROGLYPH M039;Lo;0;L;;;;;N;;;;;
-131E9;EGYPTIAN HIEROGLYPH M040;Lo;0;L;;;;;N;;;;;
-131EA;EGYPTIAN HIEROGLYPH M040A;Lo;0;L;;;;;N;;;;;
-131EB;EGYPTIAN HIEROGLYPH M041;Lo;0;L;;;;;N;;;;;
-131EC;EGYPTIAN HIEROGLYPH M042;Lo;0;L;;;;;N;;;;;
-131ED;EGYPTIAN HIEROGLYPH M043;Lo;0;L;;;;;N;;;;;
-131EE;EGYPTIAN HIEROGLYPH M044;Lo;0;L;;;;;N;;;;;
-131EF;EGYPTIAN HIEROGLYPH N001;Lo;0;L;;;;;N;;;;;
-131F0;EGYPTIAN HIEROGLYPH N002;Lo;0;L;;;;;N;;;;;
-131F1;EGYPTIAN HIEROGLYPH N003;Lo;0;L;;;;;N;;;;;
-131F2;EGYPTIAN HIEROGLYPH N004;Lo;0;L;;;;;N;;;;;
-131F3;EGYPTIAN HIEROGLYPH N005;Lo;0;L;;;;;N;;;;;
-131F4;EGYPTIAN HIEROGLYPH N006;Lo;0;L;;;;;N;;;;;
-131F5;EGYPTIAN HIEROGLYPH N007;Lo;0;L;;;;;N;;;;;
-131F6;EGYPTIAN HIEROGLYPH N008;Lo;0;L;;;;;N;;;;;
-131F7;EGYPTIAN HIEROGLYPH N009;Lo;0;L;;;;;N;;;;;
-131F8;EGYPTIAN HIEROGLYPH N010;Lo;0;L;;;;;N;;;;;
-131F9;EGYPTIAN HIEROGLYPH N011;Lo;0;L;;;;;N;;;;;
-131FA;EGYPTIAN HIEROGLYPH N012;Lo;0;L;;;;;N;;;;;
-131FB;EGYPTIAN HIEROGLYPH N013;Lo;0;L;;;;;N;;;;;
-131FC;EGYPTIAN HIEROGLYPH N014;Lo;0;L;;;;;N;;;;;
-131FD;EGYPTIAN HIEROGLYPH N015;Lo;0;L;;;;;N;;;;;
-131FE;EGYPTIAN HIEROGLYPH N016;Lo;0;L;;;;;N;;;;;
-131FF;EGYPTIAN HIEROGLYPH N017;Lo;0;L;;;;;N;;;;;
-13200;EGYPTIAN HIEROGLYPH N018;Lo;0;L;;;;;N;;;;;
-13201;EGYPTIAN HIEROGLYPH N018A;Lo;0;L;;;;;N;;;;;
-13202;EGYPTIAN HIEROGLYPH N018B;Lo;0;L;;;;;N;;;;;
-13203;EGYPTIAN HIEROGLYPH N019;Lo;0;L;;;;;N;;;;;
-13204;EGYPTIAN HIEROGLYPH N020;Lo;0;L;;;;;N;;;;;
-13205;EGYPTIAN HIEROGLYPH N021;Lo;0;L;;;;;N;;;;;
-13206;EGYPTIAN HIEROGLYPH N022;Lo;0;L;;;;;N;;;;;
-13207;EGYPTIAN HIEROGLYPH N023;Lo;0;L;;;;;N;;;;;
-13208;EGYPTIAN HIEROGLYPH N024;Lo;0;L;;;;;N;;;;;
-13209;EGYPTIAN HIEROGLYPH N025;Lo;0;L;;;;;N;;;;;
-1320A;EGYPTIAN HIEROGLYPH N025A;Lo;0;L;;;;;N;;;;;
-1320B;EGYPTIAN HIEROGLYPH N026;Lo;0;L;;;;;N;;;;;
-1320C;EGYPTIAN HIEROGLYPH N027;Lo;0;L;;;;;N;;;;;
-1320D;EGYPTIAN HIEROGLYPH N028;Lo;0;L;;;;;N;;;;;
-1320E;EGYPTIAN HIEROGLYPH N029;Lo;0;L;;;;;N;;;;;
-1320F;EGYPTIAN HIEROGLYPH N030;Lo;0;L;;;;;N;;;;;
-13210;EGYPTIAN HIEROGLYPH N031;Lo;0;L;;;;;N;;;;;
-13211;EGYPTIAN HIEROGLYPH N032;Lo;0;L;;;;;N;;;;;
-13212;EGYPTIAN HIEROGLYPH N033;Lo;0;L;;;;;N;;;;;
-13213;EGYPTIAN HIEROGLYPH N033A;Lo;0;L;;;;;N;;;;;
-13214;EGYPTIAN HIEROGLYPH N034;Lo;0;L;;;;;N;;;;;
-13215;EGYPTIAN HIEROGLYPH N034A;Lo;0;L;;;;;N;;;;;
-13216;EGYPTIAN HIEROGLYPH N035;Lo;0;L;;;;;N;;;;;
-13217;EGYPTIAN HIEROGLYPH N035A;Lo;0;L;;;;;N;;;;;
-13218;EGYPTIAN HIEROGLYPH N036;Lo;0;L;;;;;N;;;;;
-13219;EGYPTIAN HIEROGLYPH N037;Lo;0;L;;;;;N;;;;;
-1321A;EGYPTIAN HIEROGLYPH N037A;Lo;0;L;;;;;N;;;;;
-1321B;EGYPTIAN HIEROGLYPH N038;Lo;0;L;;;;;N;;;;;
-1321C;EGYPTIAN HIEROGLYPH N039;Lo;0;L;;;;;N;;;;;
-1321D;EGYPTIAN HIEROGLYPH N040;Lo;0;L;;;;;N;;;;;
-1321E;EGYPTIAN HIEROGLYPH N041;Lo;0;L;;;;;N;;;;;
-1321F;EGYPTIAN HIEROGLYPH N042;Lo;0;L;;;;;N;;;;;
-13220;EGYPTIAN HIEROGLYPH NL001;Lo;0;L;;;;;N;;;;;
-13221;EGYPTIAN HIEROGLYPH NL002;Lo;0;L;;;;;N;;;;;
-13222;EGYPTIAN HIEROGLYPH NL003;Lo;0;L;;;;;N;;;;;
-13223;EGYPTIAN HIEROGLYPH NL004;Lo;0;L;;;;;N;;;;;
-13224;EGYPTIAN HIEROGLYPH NL005;Lo;0;L;;;;;N;;;;;
-13225;EGYPTIAN HIEROGLYPH NL005A;Lo;0;L;;;;;N;;;;;
-13226;EGYPTIAN HIEROGLYPH NL006;Lo;0;L;;;;;N;;;;;
-13227;EGYPTIAN HIEROGLYPH NL007;Lo;0;L;;;;;N;;;;;
-13228;EGYPTIAN HIEROGLYPH NL008;Lo;0;L;;;;;N;;;;;
-13229;EGYPTIAN HIEROGLYPH NL009;Lo;0;L;;;;;N;;;;;
-1322A;EGYPTIAN HIEROGLYPH NL010;Lo;0;L;;;;;N;;;;;
-1322B;EGYPTIAN HIEROGLYPH NL011;Lo;0;L;;;;;N;;;;;
-1322C;EGYPTIAN HIEROGLYPH NL012;Lo;0;L;;;;;N;;;;;
-1322D;EGYPTIAN HIEROGLYPH NL013;Lo;0;L;;;;;N;;;;;
-1322E;EGYPTIAN HIEROGLYPH NL014;Lo;0;L;;;;;N;;;;;
-1322F;EGYPTIAN HIEROGLYPH NL015;Lo;0;L;;;;;N;;;;;
-13230;EGYPTIAN HIEROGLYPH NL016;Lo;0;L;;;;;N;;;;;
-13231;EGYPTIAN HIEROGLYPH NL017;Lo;0;L;;;;;N;;;;;
-13232;EGYPTIAN HIEROGLYPH NL017A;Lo;0;L;;;;;N;;;;;
-13233;EGYPTIAN HIEROGLYPH NL018;Lo;0;L;;;;;N;;;;;
-13234;EGYPTIAN HIEROGLYPH NL019;Lo;0;L;;;;;N;;;;;
-13235;EGYPTIAN HIEROGLYPH NL020;Lo;0;L;;;;;N;;;;;
-13236;EGYPTIAN HIEROGLYPH NU001;Lo;0;L;;;;;N;;;;;
-13237;EGYPTIAN HIEROGLYPH NU002;Lo;0;L;;;;;N;;;;;
-13238;EGYPTIAN HIEROGLYPH NU003;Lo;0;L;;;;;N;;;;;
-13239;EGYPTIAN HIEROGLYPH NU004;Lo;0;L;;;;;N;;;;;
-1323A;EGYPTIAN HIEROGLYPH NU005;Lo;0;L;;;;;N;;;;;
-1323B;EGYPTIAN HIEROGLYPH NU006;Lo;0;L;;;;;N;;;;;
-1323C;EGYPTIAN HIEROGLYPH NU007;Lo;0;L;;;;;N;;;;;
-1323D;EGYPTIAN HIEROGLYPH NU008;Lo;0;L;;;;;N;;;;;
-1323E;EGYPTIAN HIEROGLYPH NU009;Lo;0;L;;;;;N;;;;;
-1323F;EGYPTIAN HIEROGLYPH NU010;Lo;0;L;;;;;N;;;;;
-13240;EGYPTIAN HIEROGLYPH NU010A;Lo;0;L;;;;;N;;;;;
-13241;EGYPTIAN HIEROGLYPH NU011;Lo;0;L;;;;;N;;;;;
-13242;EGYPTIAN HIEROGLYPH NU011A;Lo;0;L;;;;;N;;;;;
-13243;EGYPTIAN HIEROGLYPH NU012;Lo;0;L;;;;;N;;;;;
-13244;EGYPTIAN HIEROGLYPH NU013;Lo;0;L;;;;;N;;;;;
-13245;EGYPTIAN HIEROGLYPH NU014;Lo;0;L;;;;;N;;;;;
-13246;EGYPTIAN HIEROGLYPH NU015;Lo;0;L;;;;;N;;;;;
-13247;EGYPTIAN HIEROGLYPH NU016;Lo;0;L;;;;;N;;;;;
-13248;EGYPTIAN HIEROGLYPH NU017;Lo;0;L;;;;;N;;;;;
-13249;EGYPTIAN HIEROGLYPH NU018;Lo;0;L;;;;;N;;;;;
-1324A;EGYPTIAN HIEROGLYPH NU018A;Lo;0;L;;;;;N;;;;;
-1324B;EGYPTIAN HIEROGLYPH NU019;Lo;0;L;;;;;N;;;;;
-1324C;EGYPTIAN HIEROGLYPH NU020;Lo;0;L;;;;;N;;;;;
-1324D;EGYPTIAN HIEROGLYPH NU021;Lo;0;L;;;;;N;;;;;
-1324E;EGYPTIAN HIEROGLYPH NU022;Lo;0;L;;;;;N;;;;;
-1324F;EGYPTIAN HIEROGLYPH NU022A;Lo;0;L;;;;;N;;;;;
-13250;EGYPTIAN HIEROGLYPH O001;Lo;0;L;;;;;N;;;;;
-13251;EGYPTIAN HIEROGLYPH O001A;Lo;0;L;;;;;N;;;;;
-13252;EGYPTIAN HIEROGLYPH O002;Lo;0;L;;;;;N;;;;;
-13253;EGYPTIAN HIEROGLYPH O003;Lo;0;L;;;;;N;;;;;
-13254;EGYPTIAN HIEROGLYPH O004;Lo;0;L;;;;;N;;;;;
-13255;EGYPTIAN HIEROGLYPH O005;Lo;0;L;;;;;N;;;;;
-13256;EGYPTIAN HIEROGLYPH O005A;Lo;0;L;;;;;N;;;;;
-13257;EGYPTIAN HIEROGLYPH O006;Lo;0;L;;;;;N;;;;;
-13258;EGYPTIAN HIEROGLYPH O006A;Lo;0;L;;;;;N;;;;;
-13259;EGYPTIAN HIEROGLYPH O006B;Lo;0;L;;;;;N;;;;;
-1325A;EGYPTIAN HIEROGLYPH O006C;Lo;0;L;;;;;N;;;;;
-1325B;EGYPTIAN HIEROGLYPH O006D;Lo;0;L;;;;;N;;;;;
-1325C;EGYPTIAN HIEROGLYPH O006E;Lo;0;L;;;;;N;;;;;
-1325D;EGYPTIAN HIEROGLYPH O006F;Lo;0;L;;;;;N;;;;;
-1325E;EGYPTIAN HIEROGLYPH O007;Lo;0;L;;;;;N;;;;;
-1325F;EGYPTIAN HIEROGLYPH O008;Lo;0;L;;;;;N;;;;;
-13260;EGYPTIAN HIEROGLYPH O009;Lo;0;L;;;;;N;;;;;
-13261;EGYPTIAN HIEROGLYPH O010;Lo;0;L;;;;;N;;;;;
-13262;EGYPTIAN HIEROGLYPH O010A;Lo;0;L;;;;;N;;;;;
-13263;EGYPTIAN HIEROGLYPH O010B;Lo;0;L;;;;;N;;;;;
-13264;EGYPTIAN HIEROGLYPH O010C;Lo;0;L;;;;;N;;;;;
-13265;EGYPTIAN HIEROGLYPH O011;Lo;0;L;;;;;N;;;;;
-13266;EGYPTIAN HIEROGLYPH O012;Lo;0;L;;;;;N;;;;;
-13267;EGYPTIAN HIEROGLYPH O013;Lo;0;L;;;;;N;;;;;
-13268;EGYPTIAN HIEROGLYPH O014;Lo;0;L;;;;;N;;;;;
-13269;EGYPTIAN HIEROGLYPH O015;Lo;0;L;;;;;N;;;;;
-1326A;EGYPTIAN HIEROGLYPH O016;Lo;0;L;;;;;N;;;;;
-1326B;EGYPTIAN HIEROGLYPH O017;Lo;0;L;;;;;N;;;;;
-1326C;EGYPTIAN HIEROGLYPH O018;Lo;0;L;;;;;N;;;;;
-1326D;EGYPTIAN HIEROGLYPH O019;Lo;0;L;;;;;N;;;;;
-1326E;EGYPTIAN HIEROGLYPH O019A;Lo;0;L;;;;;N;;;;;
-1326F;EGYPTIAN HIEROGLYPH O020;Lo;0;L;;;;;N;;;;;
-13270;EGYPTIAN HIEROGLYPH O020A;Lo;0;L;;;;;N;;;;;
-13271;EGYPTIAN HIEROGLYPH O021;Lo;0;L;;;;;N;;;;;
-13272;EGYPTIAN HIEROGLYPH O022;Lo;0;L;;;;;N;;;;;
-13273;EGYPTIAN HIEROGLYPH O023;Lo;0;L;;;;;N;;;;;
-13274;EGYPTIAN HIEROGLYPH O024;Lo;0;L;;;;;N;;;;;
-13275;EGYPTIAN HIEROGLYPH O024A;Lo;0;L;;;;;N;;;;;
-13276;EGYPTIAN HIEROGLYPH O025;Lo;0;L;;;;;N;;;;;
-13277;EGYPTIAN HIEROGLYPH O025A;Lo;0;L;;;;;N;;;;;
-13278;EGYPTIAN HIEROGLYPH O026;Lo;0;L;;;;;N;;;;;
-13279;EGYPTIAN HIEROGLYPH O027;Lo;0;L;;;;;N;;;;;
-1327A;EGYPTIAN HIEROGLYPH O028;Lo;0;L;;;;;N;;;;;
-1327B;EGYPTIAN HIEROGLYPH O029;Lo;0;L;;;;;N;;;;;
-1327C;EGYPTIAN HIEROGLYPH O029A;Lo;0;L;;;;;N;;;;;
-1327D;EGYPTIAN HIEROGLYPH O030;Lo;0;L;;;;;N;;;;;
-1327E;EGYPTIAN HIEROGLYPH O030A;Lo;0;L;;;;;N;;;;;
-1327F;EGYPTIAN HIEROGLYPH O031;Lo;0;L;;;;;N;;;;;
-13280;EGYPTIAN HIEROGLYPH O032;Lo;0;L;;;;;N;;;;;
-13281;EGYPTIAN HIEROGLYPH O033;Lo;0;L;;;;;N;;;;;
-13282;EGYPTIAN HIEROGLYPH O033A;Lo;0;L;;;;;N;;;;;
-13283;EGYPTIAN HIEROGLYPH O034;Lo;0;L;;;;;N;;;;;
-13284;EGYPTIAN HIEROGLYPH O035;Lo;0;L;;;;;N;;;;;
-13285;EGYPTIAN HIEROGLYPH O036;Lo;0;L;;;;;N;;;;;
-13286;EGYPTIAN HIEROGLYPH O036A;Lo;0;L;;;;;N;;;;;
-13287;EGYPTIAN HIEROGLYPH O036B;Lo;0;L;;;;;N;;;;;
-13288;EGYPTIAN HIEROGLYPH O036C;Lo;0;L;;;;;N;;;;;
-13289;EGYPTIAN HIEROGLYPH O036D;Lo;0;L;;;;;N;;;;;
-1328A;EGYPTIAN HIEROGLYPH O037;Lo;0;L;;;;;N;;;;;
-1328B;EGYPTIAN HIEROGLYPH O038;Lo;0;L;;;;;N;;;;;
-1328C;EGYPTIAN HIEROGLYPH O039;Lo;0;L;;;;;N;;;;;
-1328D;EGYPTIAN HIEROGLYPH O040;Lo;0;L;;;;;N;;;;;
-1328E;EGYPTIAN HIEROGLYPH O041;Lo;0;L;;;;;N;;;;;
-1328F;EGYPTIAN HIEROGLYPH O042;Lo;0;L;;;;;N;;;;;
-13290;EGYPTIAN HIEROGLYPH O043;Lo;0;L;;;;;N;;;;;
-13291;EGYPTIAN HIEROGLYPH O044;Lo;0;L;;;;;N;;;;;
-13292;EGYPTIAN HIEROGLYPH O045;Lo;0;L;;;;;N;;;;;
-13293;EGYPTIAN HIEROGLYPH O046;Lo;0;L;;;;;N;;;;;
-13294;EGYPTIAN HIEROGLYPH O047;Lo;0;L;;;;;N;;;;;
-13295;EGYPTIAN HIEROGLYPH O048;Lo;0;L;;;;;N;;;;;
-13296;EGYPTIAN HIEROGLYPH O049;Lo;0;L;;;;;N;;;;;
-13297;EGYPTIAN HIEROGLYPH O050;Lo;0;L;;;;;N;;;;;
-13298;EGYPTIAN HIEROGLYPH O050A;Lo;0;L;;;;;N;;;;;
-13299;EGYPTIAN HIEROGLYPH O050B;Lo;0;L;;;;;N;;;;;
-1329A;EGYPTIAN HIEROGLYPH O051;Lo;0;L;;;;;N;;;;;
-1329B;EGYPTIAN HIEROGLYPH P001;Lo;0;L;;;;;N;;;;;
-1329C;EGYPTIAN HIEROGLYPH P001A;Lo;0;L;;;;;N;;;;;
-1329D;EGYPTIAN HIEROGLYPH P002;Lo;0;L;;;;;N;;;;;
-1329E;EGYPTIAN HIEROGLYPH P003;Lo;0;L;;;;;N;;;;;
-1329F;EGYPTIAN HIEROGLYPH P003A;Lo;0;L;;;;;N;;;;;
-132A0;EGYPTIAN HIEROGLYPH P004;Lo;0;L;;;;;N;;;;;
-132A1;EGYPTIAN HIEROGLYPH P005;Lo;0;L;;;;;N;;;;;
-132A2;EGYPTIAN HIEROGLYPH P006;Lo;0;L;;;;;N;;;;;
-132A3;EGYPTIAN HIEROGLYPH P007;Lo;0;L;;;;;N;;;;;
-132A4;EGYPTIAN HIEROGLYPH P008;Lo;0;L;;;;;N;;;;;
-132A5;EGYPTIAN HIEROGLYPH P009;Lo;0;L;;;;;N;;;;;
-132A6;EGYPTIAN HIEROGLYPH P010;Lo;0;L;;;;;N;;;;;
-132A7;EGYPTIAN HIEROGLYPH P011;Lo;0;L;;;;;N;;;;;
-132A8;EGYPTIAN HIEROGLYPH Q001;Lo;0;L;;;;;N;;;;;
-132A9;EGYPTIAN HIEROGLYPH Q002;Lo;0;L;;;;;N;;;;;
-132AA;EGYPTIAN HIEROGLYPH Q003;Lo;0;L;;;;;N;;;;;
-132AB;EGYPTIAN HIEROGLYPH Q004;Lo;0;L;;;;;N;;;;;
-132AC;EGYPTIAN HIEROGLYPH Q005;Lo;0;L;;;;;N;;;;;
-132AD;EGYPTIAN HIEROGLYPH Q006;Lo;0;L;;;;;N;;;;;
-132AE;EGYPTIAN HIEROGLYPH Q007;Lo;0;L;;;;;N;;;;;
-132AF;EGYPTIAN HIEROGLYPH R001;Lo;0;L;;;;;N;;;;;
-132B0;EGYPTIAN HIEROGLYPH R002;Lo;0;L;;;;;N;;;;;
-132B1;EGYPTIAN HIEROGLYPH R002A;Lo;0;L;;;;;N;;;;;
-132B2;EGYPTIAN HIEROGLYPH R003;Lo;0;L;;;;;N;;;;;
-132B3;EGYPTIAN HIEROGLYPH R003A;Lo;0;L;;;;;N;;;;;
-132B4;EGYPTIAN HIEROGLYPH R003B;Lo;0;L;;;;;N;;;;;
-132B5;EGYPTIAN HIEROGLYPH R004;Lo;0;L;;;;;N;;;;;
-132B6;EGYPTIAN HIEROGLYPH R005;Lo;0;L;;;;;N;;;;;
-132B7;EGYPTIAN HIEROGLYPH R006;Lo;0;L;;;;;N;;;;;
-132B8;EGYPTIAN HIEROGLYPH R007;Lo;0;L;;;;;N;;;;;
-132B9;EGYPTIAN HIEROGLYPH R008;Lo;0;L;;;;;N;;;;;
-132BA;EGYPTIAN HIEROGLYPH R009;Lo;0;L;;;;;N;;;;;
-132BB;EGYPTIAN HIEROGLYPH R010;Lo;0;L;;;;;N;;;;;
-132BC;EGYPTIAN HIEROGLYPH R010A;Lo;0;L;;;;;N;;;;;
-132BD;EGYPTIAN HIEROGLYPH R011;Lo;0;L;;;;;N;;;;;
-132BE;EGYPTIAN HIEROGLYPH R012;Lo;0;L;;;;;N;;;;;
-132BF;EGYPTIAN HIEROGLYPH R013;Lo;0;L;;;;;N;;;;;
-132C0;EGYPTIAN HIEROGLYPH R014;Lo;0;L;;;;;N;;;;;
-132C1;EGYPTIAN HIEROGLYPH R015;Lo;0;L;;;;;N;;;;;
-132C2;EGYPTIAN HIEROGLYPH R016;Lo;0;L;;;;;N;;;;;
-132C3;EGYPTIAN HIEROGLYPH R016A;Lo;0;L;;;;;N;;;;;
-132C4;EGYPTIAN HIEROGLYPH R017;Lo;0;L;;;;;N;;;;;
-132C5;EGYPTIAN HIEROGLYPH R018;Lo;0;L;;;;;N;;;;;
-132C6;EGYPTIAN HIEROGLYPH R019;Lo;0;L;;;;;N;;;;;
-132C7;EGYPTIAN HIEROGLYPH R020;Lo;0;L;;;;;N;;;;;
-132C8;EGYPTIAN HIEROGLYPH R021;Lo;0;L;;;;;N;;;;;
-132C9;EGYPTIAN HIEROGLYPH R022;Lo;0;L;;;;;N;;;;;
-132CA;EGYPTIAN HIEROGLYPH R023;Lo;0;L;;;;;N;;;;;
-132CB;EGYPTIAN HIEROGLYPH R024;Lo;0;L;;;;;N;;;;;
-132CC;EGYPTIAN HIEROGLYPH R025;Lo;0;L;;;;;N;;;;;
-132CD;EGYPTIAN HIEROGLYPH R026;Lo;0;L;;;;;N;;;;;
-132CE;EGYPTIAN HIEROGLYPH R027;Lo;0;L;;;;;N;;;;;
-132CF;EGYPTIAN HIEROGLYPH R028;Lo;0;L;;;;;N;;;;;
-132D0;EGYPTIAN HIEROGLYPH R029;Lo;0;L;;;;;N;;;;;
-132D1;EGYPTIAN HIEROGLYPH S001;Lo;0;L;;;;;N;;;;;
-132D2;EGYPTIAN HIEROGLYPH S002;Lo;0;L;;;;;N;;;;;
-132D3;EGYPTIAN HIEROGLYPH S002A;Lo;0;L;;;;;N;;;;;
-132D4;EGYPTIAN HIEROGLYPH S003;Lo;0;L;;;;;N;;;;;
-132D5;EGYPTIAN HIEROGLYPH S004;Lo;0;L;;;;;N;;;;;
-132D6;EGYPTIAN HIEROGLYPH S005;Lo;0;L;;;;;N;;;;;
-132D7;EGYPTIAN HIEROGLYPH S006;Lo;0;L;;;;;N;;;;;
-132D8;EGYPTIAN HIEROGLYPH S006A;Lo;0;L;;;;;N;;;;;
-132D9;EGYPTIAN HIEROGLYPH S007;Lo;0;L;;;;;N;;;;;
-132DA;EGYPTIAN HIEROGLYPH S008;Lo;0;L;;;;;N;;;;;
-132DB;EGYPTIAN HIEROGLYPH S009;Lo;0;L;;;;;N;;;;;
-132DC;EGYPTIAN HIEROGLYPH S010;Lo;0;L;;;;;N;;;;;
-132DD;EGYPTIAN HIEROGLYPH S011;Lo;0;L;;;;;N;;;;;
-132DE;EGYPTIAN HIEROGLYPH S012;Lo;0;L;;;;;N;;;;;
-132DF;EGYPTIAN HIEROGLYPH S013;Lo;0;L;;;;;N;;;;;
-132E0;EGYPTIAN HIEROGLYPH S014;Lo;0;L;;;;;N;;;;;
-132E1;EGYPTIAN HIEROGLYPH S014A;Lo;0;L;;;;;N;;;;;
-132E2;EGYPTIAN HIEROGLYPH S014B;Lo;0;L;;;;;N;;;;;
-132E3;EGYPTIAN HIEROGLYPH S015;Lo;0;L;;;;;N;;;;;
-132E4;EGYPTIAN HIEROGLYPH S016;Lo;0;L;;;;;N;;;;;
-132E5;EGYPTIAN HIEROGLYPH S017;Lo;0;L;;;;;N;;;;;
-132E6;EGYPTIAN HIEROGLYPH S017A;Lo;0;L;;;;;N;;;;;
-132E7;EGYPTIAN HIEROGLYPH S018;Lo;0;L;;;;;N;;;;;
-132E8;EGYPTIAN HIEROGLYPH S019;Lo;0;L;;;;;N;;;;;
-132E9;EGYPTIAN HIEROGLYPH S020;Lo;0;L;;;;;N;;;;;
-132EA;EGYPTIAN HIEROGLYPH S021;Lo;0;L;;;;;N;;;;;
-132EB;EGYPTIAN HIEROGLYPH S022;Lo;0;L;;;;;N;;;;;
-132EC;EGYPTIAN HIEROGLYPH S023;Lo;0;L;;;;;N;;;;;
-132ED;EGYPTIAN HIEROGLYPH S024;Lo;0;L;;;;;N;;;;;
-132EE;EGYPTIAN HIEROGLYPH S025;Lo;0;L;;;;;N;;;;;
-132EF;EGYPTIAN HIEROGLYPH S026;Lo;0;L;;;;;N;;;;;
-132F0;EGYPTIAN HIEROGLYPH S026A;Lo;0;L;;;;;N;;;;;
-132F1;EGYPTIAN HIEROGLYPH S026B;Lo;0;L;;;;;N;;;;;
-132F2;EGYPTIAN HIEROGLYPH S027;Lo;0;L;;;;;N;;;;;
-132F3;EGYPTIAN HIEROGLYPH S028;Lo;0;L;;;;;N;;;;;
-132F4;EGYPTIAN HIEROGLYPH S029;Lo;0;L;;;;;N;;;;;
-132F5;EGYPTIAN HIEROGLYPH S030;Lo;0;L;;;;;N;;;;;
-132F6;EGYPTIAN HIEROGLYPH S031;Lo;0;L;;;;;N;;;;;
-132F7;EGYPTIAN HIEROGLYPH S032;Lo;0;L;;;;;N;;;;;
-132F8;EGYPTIAN HIEROGLYPH S033;Lo;0;L;;;;;N;;;;;
-132F9;EGYPTIAN HIEROGLYPH S034;Lo;0;L;;;;;N;;;;;
-132FA;EGYPTIAN HIEROGLYPH S035;Lo;0;L;;;;;N;;;;;
-132FB;EGYPTIAN HIEROGLYPH S035A;Lo;0;L;;;;;N;;;;;
-132FC;EGYPTIAN HIEROGLYPH S036;Lo;0;L;;;;;N;;;;;
-132FD;EGYPTIAN HIEROGLYPH S037;Lo;0;L;;;;;N;;;;;
-132FE;EGYPTIAN HIEROGLYPH S038;Lo;0;L;;;;;N;;;;;
-132FF;EGYPTIAN HIEROGLYPH S039;Lo;0;L;;;;;N;;;;;
-13300;EGYPTIAN HIEROGLYPH S040;Lo;0;L;;;;;N;;;;;
-13301;EGYPTIAN HIEROGLYPH S041;Lo;0;L;;;;;N;;;;;
-13302;EGYPTIAN HIEROGLYPH S042;Lo;0;L;;;;;N;;;;;
-13303;EGYPTIAN HIEROGLYPH S043;Lo;0;L;;;;;N;;;;;
-13304;EGYPTIAN HIEROGLYPH S044;Lo;0;L;;;;;N;;;;;
-13305;EGYPTIAN HIEROGLYPH S045;Lo;0;L;;;;;N;;;;;
-13306;EGYPTIAN HIEROGLYPH S046;Lo;0;L;;;;;N;;;;;
-13307;EGYPTIAN HIEROGLYPH T001;Lo;0;L;;;;;N;;;;;
-13308;EGYPTIAN HIEROGLYPH T002;Lo;0;L;;;;;N;;;;;
-13309;EGYPTIAN HIEROGLYPH T003;Lo;0;L;;;;;N;;;;;
-1330A;EGYPTIAN HIEROGLYPH T003A;Lo;0;L;;;;;N;;;;;
-1330B;EGYPTIAN HIEROGLYPH T004;Lo;0;L;;;;;N;;;;;
-1330C;EGYPTIAN HIEROGLYPH T005;Lo;0;L;;;;;N;;;;;
-1330D;EGYPTIAN HIEROGLYPH T006;Lo;0;L;;;;;N;;;;;
-1330E;EGYPTIAN HIEROGLYPH T007;Lo;0;L;;;;;N;;;;;
-1330F;EGYPTIAN HIEROGLYPH T007A;Lo;0;L;;;;;N;;;;;
-13310;EGYPTIAN HIEROGLYPH T008;Lo;0;L;;;;;N;;;;;
-13311;EGYPTIAN HIEROGLYPH T008A;Lo;0;L;;;;;N;;;;;
-13312;EGYPTIAN HIEROGLYPH T009;Lo;0;L;;;;;N;;;;;
-13313;EGYPTIAN HIEROGLYPH T009A;Lo;0;L;;;;;N;;;;;
-13314;EGYPTIAN HIEROGLYPH T010;Lo;0;L;;;;;N;;;;;
-13315;EGYPTIAN HIEROGLYPH T011;Lo;0;L;;;;;N;;;;;
-13316;EGYPTIAN HIEROGLYPH T011A;Lo;0;L;;;;;N;;;;;
-13317;EGYPTIAN HIEROGLYPH T012;Lo;0;L;;;;;N;;;;;
-13318;EGYPTIAN HIEROGLYPH T013;Lo;0;L;;;;;N;;;;;
-13319;EGYPTIAN HIEROGLYPH T014;Lo;0;L;;;;;N;;;;;
-1331A;EGYPTIAN HIEROGLYPH T015;Lo;0;L;;;;;N;;;;;
-1331B;EGYPTIAN HIEROGLYPH T016;Lo;0;L;;;;;N;;;;;
-1331C;EGYPTIAN HIEROGLYPH T016A;Lo;0;L;;;;;N;;;;;
-1331D;EGYPTIAN HIEROGLYPH T017;Lo;0;L;;;;;N;;;;;
-1331E;EGYPTIAN HIEROGLYPH T018;Lo;0;L;;;;;N;;;;;
-1331F;EGYPTIAN HIEROGLYPH T019;Lo;0;L;;;;;N;;;;;
-13320;EGYPTIAN HIEROGLYPH T020;Lo;0;L;;;;;N;;;;;
-13321;EGYPTIAN HIEROGLYPH T021;Lo;0;L;;;;;N;;;;;
-13322;EGYPTIAN HIEROGLYPH T022;Lo;0;L;;;;;N;;;;;
-13323;EGYPTIAN HIEROGLYPH T023;Lo;0;L;;;;;N;;;;;
-13324;EGYPTIAN HIEROGLYPH T024;Lo;0;L;;;;;N;;;;;
-13325;EGYPTIAN HIEROGLYPH T025;Lo;0;L;;;;;N;;;;;
-13326;EGYPTIAN HIEROGLYPH T026;Lo;0;L;;;;;N;;;;;
-13327;EGYPTIAN HIEROGLYPH T027;Lo;0;L;;;;;N;;;;;
-13328;EGYPTIAN HIEROGLYPH T028;Lo;0;L;;;;;N;;;;;
-13329;EGYPTIAN HIEROGLYPH T029;Lo;0;L;;;;;N;;;;;
-1332A;EGYPTIAN HIEROGLYPH T030;Lo;0;L;;;;;N;;;;;
-1332B;EGYPTIAN HIEROGLYPH T031;Lo;0;L;;;;;N;;;;;
-1332C;EGYPTIAN HIEROGLYPH T032;Lo;0;L;;;;;N;;;;;
-1332D;EGYPTIAN HIEROGLYPH T032A;Lo;0;L;;;;;N;;;;;
-1332E;EGYPTIAN HIEROGLYPH T033;Lo;0;L;;;;;N;;;;;
-1332F;EGYPTIAN HIEROGLYPH T033A;Lo;0;L;;;;;N;;;;;
-13330;EGYPTIAN HIEROGLYPH T034;Lo;0;L;;;;;N;;;;;
-13331;EGYPTIAN HIEROGLYPH T035;Lo;0;L;;;;;N;;;;;
-13332;EGYPTIAN HIEROGLYPH T036;Lo;0;L;;;;;N;;;;;
-13333;EGYPTIAN HIEROGLYPH U001;Lo;0;L;;;;;N;;;;;
-13334;EGYPTIAN HIEROGLYPH U002;Lo;0;L;;;;;N;;;;;
-13335;EGYPTIAN HIEROGLYPH U003;Lo;0;L;;;;;N;;;;;
-13336;EGYPTIAN HIEROGLYPH U004;Lo;0;L;;;;;N;;;;;
-13337;EGYPTIAN HIEROGLYPH U005;Lo;0;L;;;;;N;;;;;
-13338;EGYPTIAN HIEROGLYPH U006;Lo;0;L;;;;;N;;;;;
-13339;EGYPTIAN HIEROGLYPH U006A;Lo;0;L;;;;;N;;;;;
-1333A;EGYPTIAN HIEROGLYPH U006B;Lo;0;L;;;;;N;;;;;
-1333B;EGYPTIAN HIEROGLYPH U007;Lo;0;L;;;;;N;;;;;
-1333C;EGYPTIAN HIEROGLYPH U008;Lo;0;L;;;;;N;;;;;
-1333D;EGYPTIAN HIEROGLYPH U009;Lo;0;L;;;;;N;;;;;
-1333E;EGYPTIAN HIEROGLYPH U010;Lo;0;L;;;;;N;;;;;
-1333F;EGYPTIAN HIEROGLYPH U011;Lo;0;L;;;;;N;;;;;
-13340;EGYPTIAN HIEROGLYPH U012;Lo;0;L;;;;;N;;;;;
-13341;EGYPTIAN HIEROGLYPH U013;Lo;0;L;;;;;N;;;;;
-13342;EGYPTIAN HIEROGLYPH U014;Lo;0;L;;;;;N;;;;;
-13343;EGYPTIAN HIEROGLYPH U015;Lo;0;L;;;;;N;;;;;
-13344;EGYPTIAN HIEROGLYPH U016;Lo;0;L;;;;;N;;;;;
-13345;EGYPTIAN HIEROGLYPH U017;Lo;0;L;;;;;N;;;;;
-13346;EGYPTIAN HIEROGLYPH U018;Lo;0;L;;;;;N;;;;;
-13347;EGYPTIAN HIEROGLYPH U019;Lo;0;L;;;;;N;;;;;
-13348;EGYPTIAN HIEROGLYPH U020;Lo;0;L;;;;;N;;;;;
-13349;EGYPTIAN HIEROGLYPH U021;Lo;0;L;;;;;N;;;;;
-1334A;EGYPTIAN HIEROGLYPH U022;Lo;0;L;;;;;N;;;;;
-1334B;EGYPTIAN HIEROGLYPH U023;Lo;0;L;;;;;N;;;;;
-1334C;EGYPTIAN HIEROGLYPH U023A;Lo;0;L;;;;;N;;;;;
-1334D;EGYPTIAN HIEROGLYPH U024;Lo;0;L;;;;;N;;;;;
-1334E;EGYPTIAN HIEROGLYPH U025;Lo;0;L;;;;;N;;;;;
-1334F;EGYPTIAN HIEROGLYPH U026;Lo;0;L;;;;;N;;;;;
-13350;EGYPTIAN HIEROGLYPH U027;Lo;0;L;;;;;N;;;;;
-13351;EGYPTIAN HIEROGLYPH U028;Lo;0;L;;;;;N;;;;;
-13352;EGYPTIAN HIEROGLYPH U029;Lo;0;L;;;;;N;;;;;
-13353;EGYPTIAN HIEROGLYPH U029A;Lo;0;L;;;;;N;;;;;
-13354;EGYPTIAN HIEROGLYPH U030;Lo;0;L;;;;;N;;;;;
-13355;EGYPTIAN HIEROGLYPH U031;Lo;0;L;;;;;N;;;;;
-13356;EGYPTIAN HIEROGLYPH U032;Lo;0;L;;;;;N;;;;;
-13357;EGYPTIAN HIEROGLYPH U032A;Lo;0;L;;;;;N;;;;;
-13358;EGYPTIAN HIEROGLYPH U033;Lo;0;L;;;;;N;;;;;
-13359;EGYPTIAN HIEROGLYPH U034;Lo;0;L;;;;;N;;;;;
-1335A;EGYPTIAN HIEROGLYPH U035;Lo;0;L;;;;;N;;;;;
-1335B;EGYPTIAN HIEROGLYPH U036;Lo;0;L;;;;;N;;;;;
-1335C;EGYPTIAN HIEROGLYPH U037;Lo;0;L;;;;;N;;;;;
-1335D;EGYPTIAN HIEROGLYPH U038;Lo;0;L;;;;;N;;;;;
-1335E;EGYPTIAN HIEROGLYPH U039;Lo;0;L;;;;;N;;;;;
-1335F;EGYPTIAN HIEROGLYPH U040;Lo;0;L;;;;;N;;;;;
-13360;EGYPTIAN HIEROGLYPH U041;Lo;0;L;;;;;N;;;;;
-13361;EGYPTIAN HIEROGLYPH U042;Lo;0;L;;;;;N;;;;;
-13362;EGYPTIAN HIEROGLYPH V001;Lo;0;L;;;;;N;;;;;
-13363;EGYPTIAN HIEROGLYPH V001A;Lo;0;L;;;;;N;;;;;
-13364;EGYPTIAN HIEROGLYPH V001B;Lo;0;L;;;;;N;;;;;
-13365;EGYPTIAN HIEROGLYPH V001C;Lo;0;L;;;;;N;;;;;
-13366;EGYPTIAN HIEROGLYPH V001D;Lo;0;L;;;;;N;;;;;
-13367;EGYPTIAN HIEROGLYPH V001E;Lo;0;L;;;;;N;;;;;
-13368;EGYPTIAN HIEROGLYPH V001F;Lo;0;L;;;;;N;;;;;
-13369;EGYPTIAN HIEROGLYPH V001G;Lo;0;L;;;;;N;;;;;
-1336A;EGYPTIAN HIEROGLYPH V001H;Lo;0;L;;;;;N;;;;;
-1336B;EGYPTIAN HIEROGLYPH V001I;Lo;0;L;;;;;N;;;;;
-1336C;EGYPTIAN HIEROGLYPH V002;Lo;0;L;;;;;N;;;;;
-1336D;EGYPTIAN HIEROGLYPH V002A;Lo;0;L;;;;;N;;;;;
-1336E;EGYPTIAN HIEROGLYPH V003;Lo;0;L;;;;;N;;;;;
-1336F;EGYPTIAN HIEROGLYPH V004;Lo;0;L;;;;;N;;;;;
-13370;EGYPTIAN HIEROGLYPH V005;Lo;0;L;;;;;N;;;;;
-13371;EGYPTIAN HIEROGLYPH V006;Lo;0;L;;;;;N;;;;;
-13372;EGYPTIAN HIEROGLYPH V007;Lo;0;L;;;;;N;;;;;
-13373;EGYPTIAN HIEROGLYPH V007A;Lo;0;L;;;;;N;;;;;
-13374;EGYPTIAN HIEROGLYPH V007B;Lo;0;L;;;;;N;;;;;
-13375;EGYPTIAN HIEROGLYPH V008;Lo;0;L;;;;;N;;;;;
-13376;EGYPTIAN HIEROGLYPH V009;Lo;0;L;;;;;N;;;;;
-13377;EGYPTIAN HIEROGLYPH V010;Lo;0;L;;;;;N;;;;;
-13378;EGYPTIAN HIEROGLYPH V011;Lo;0;L;;;;;N;;;;;
-13379;EGYPTIAN HIEROGLYPH V011A;Lo;0;L;;;;;N;;;;;
-1337A;EGYPTIAN HIEROGLYPH V011B;Lo;0;L;;;;;N;;;;;
-1337B;EGYPTIAN HIEROGLYPH V011C;Lo;0;L;;;;;N;;;;;
-1337C;EGYPTIAN HIEROGLYPH V012;Lo;0;L;;;;;N;;;;;
-1337D;EGYPTIAN HIEROGLYPH V012A;Lo;0;L;;;;;N;;;;;
-1337E;EGYPTIAN HIEROGLYPH V012B;Lo;0;L;;;;;N;;;;;
-1337F;EGYPTIAN HIEROGLYPH V013;Lo;0;L;;;;;N;;;;;
-13380;EGYPTIAN HIEROGLYPH V014;Lo;0;L;;;;;N;;;;;
-13381;EGYPTIAN HIEROGLYPH V015;Lo;0;L;;;;;N;;;;;
-13382;EGYPTIAN HIEROGLYPH V016;Lo;0;L;;;;;N;;;;;
-13383;EGYPTIAN HIEROGLYPH V017;Lo;0;L;;;;;N;;;;;
-13384;EGYPTIAN HIEROGLYPH V018;Lo;0;L;;;;;N;;;;;
-13385;EGYPTIAN HIEROGLYPH V019;Lo;0;L;;;;;N;;;;;
-13386;EGYPTIAN HIEROGLYPH V020;Lo;0;L;;;;;N;;;;;
-13387;EGYPTIAN HIEROGLYPH V020A;Lo;0;L;;;;;N;;;;;
-13388;EGYPTIAN HIEROGLYPH V020B;Lo;0;L;;;;;N;;;;;
-13389;EGYPTIAN HIEROGLYPH V020C;Lo;0;L;;;;;N;;;;;
-1338A;EGYPTIAN HIEROGLYPH V020D;Lo;0;L;;;;;N;;;;;
-1338B;EGYPTIAN HIEROGLYPH V020E;Lo;0;L;;;;;N;;;;;
-1338C;EGYPTIAN HIEROGLYPH V020F;Lo;0;L;;;;;N;;;;;
-1338D;EGYPTIAN HIEROGLYPH V020G;Lo;0;L;;;;;N;;;;;
-1338E;EGYPTIAN HIEROGLYPH V020H;Lo;0;L;;;;;N;;;;;
-1338F;EGYPTIAN HIEROGLYPH V020I;Lo;0;L;;;;;N;;;;;
-13390;EGYPTIAN HIEROGLYPH V020J;Lo;0;L;;;;;N;;;;;
-13391;EGYPTIAN HIEROGLYPH V020K;Lo;0;L;;;;;N;;;;;
-13392;EGYPTIAN HIEROGLYPH V020L;Lo;0;L;;;;;N;;;;;
-13393;EGYPTIAN HIEROGLYPH V021;Lo;0;L;;;;;N;;;;;
-13394;EGYPTIAN HIEROGLYPH V022;Lo;0;L;;;;;N;;;;;
-13395;EGYPTIAN HIEROGLYPH V023;Lo;0;L;;;;;N;;;;;
-13396;EGYPTIAN HIEROGLYPH V023A;Lo;0;L;;;;;N;;;;;
-13397;EGYPTIAN HIEROGLYPH V024;Lo;0;L;;;;;N;;;;;
-13398;EGYPTIAN HIEROGLYPH V025;Lo;0;L;;;;;N;;;;;
-13399;EGYPTIAN HIEROGLYPH V026;Lo;0;L;;;;;N;;;;;
-1339A;EGYPTIAN HIEROGLYPH V027;Lo;0;L;;;;;N;;;;;
-1339B;EGYPTIAN HIEROGLYPH V028;Lo;0;L;;;;;N;;;;;
-1339C;EGYPTIAN HIEROGLYPH V028A;Lo;0;L;;;;;N;;;;;
-1339D;EGYPTIAN HIEROGLYPH V029;Lo;0;L;;;;;N;;;;;
-1339E;EGYPTIAN HIEROGLYPH V029A;Lo;0;L;;;;;N;;;;;
-1339F;EGYPTIAN HIEROGLYPH V030;Lo;0;L;;;;;N;;;;;
-133A0;EGYPTIAN HIEROGLYPH V030A;Lo;0;L;;;;;N;;;;;
-133A1;EGYPTIAN HIEROGLYPH V031;Lo;0;L;;;;;N;;;;;
-133A2;EGYPTIAN HIEROGLYPH V031A;Lo;0;L;;;;;N;;;;;
-133A3;EGYPTIAN HIEROGLYPH V032;Lo;0;L;;;;;N;;;;;
-133A4;EGYPTIAN HIEROGLYPH V033;Lo;0;L;;;;;N;;;;;
-133A5;EGYPTIAN HIEROGLYPH V033A;Lo;0;L;;;;;N;;;;;
-133A6;EGYPTIAN HIEROGLYPH V034;Lo;0;L;;;;;N;;;;;
-133A7;EGYPTIAN HIEROGLYPH V035;Lo;0;L;;;;;N;;;;;
-133A8;EGYPTIAN HIEROGLYPH V036;Lo;0;L;;;;;N;;;;;
-133A9;EGYPTIAN HIEROGLYPH V037;Lo;0;L;;;;;N;;;;;
-133AA;EGYPTIAN HIEROGLYPH V037A;Lo;0;L;;;;;N;;;;;
-133AB;EGYPTIAN HIEROGLYPH V038;Lo;0;L;;;;;N;;;;;
-133AC;EGYPTIAN HIEROGLYPH V039;Lo;0;L;;;;;N;;;;;
-133AD;EGYPTIAN HIEROGLYPH V040;Lo;0;L;;;;;N;;;;;
-133AE;EGYPTIAN HIEROGLYPH V040A;Lo;0;L;;;;;N;;;;;
-133AF;EGYPTIAN HIEROGLYPH W001;Lo;0;L;;;;;N;;;;;
-133B0;EGYPTIAN HIEROGLYPH W002;Lo;0;L;;;;;N;;;;;
-133B1;EGYPTIAN HIEROGLYPH W003;Lo;0;L;;;;;N;;;;;
-133B2;EGYPTIAN HIEROGLYPH W003A;Lo;0;L;;;;;N;;;;;
-133B3;EGYPTIAN HIEROGLYPH W004;Lo;0;L;;;;;N;;;;;
-133B4;EGYPTIAN HIEROGLYPH W005;Lo;0;L;;;;;N;;;;;
-133B5;EGYPTIAN HIEROGLYPH W006;Lo;0;L;;;;;N;;;;;
-133B6;EGYPTIAN HIEROGLYPH W007;Lo;0;L;;;;;N;;;;;
-133B7;EGYPTIAN HIEROGLYPH W008;Lo;0;L;;;;;N;;;;;
-133B8;EGYPTIAN HIEROGLYPH W009;Lo;0;L;;;;;N;;;;;
-133B9;EGYPTIAN HIEROGLYPH W009A;Lo;0;L;;;;;N;;;;;
-133BA;EGYPTIAN HIEROGLYPH W010;Lo;0;L;;;;;N;;;;;
-133BB;EGYPTIAN HIEROGLYPH W010A;Lo;0;L;;;;;N;;;;;
-133BC;EGYPTIAN HIEROGLYPH W011;Lo;0;L;;;;;N;;;;;
-133BD;EGYPTIAN HIEROGLYPH W012;Lo;0;L;;;;;N;;;;;
-133BE;EGYPTIAN HIEROGLYPH W013;Lo;0;L;;;;;N;;;;;
-133BF;EGYPTIAN HIEROGLYPH W014;Lo;0;L;;;;;N;;;;;
-133C0;EGYPTIAN HIEROGLYPH W014A;Lo;0;L;;;;;N;;;;;
-133C1;EGYPTIAN HIEROGLYPH W015;Lo;0;L;;;;;N;;;;;
-133C2;EGYPTIAN HIEROGLYPH W016;Lo;0;L;;;;;N;;;;;
-133C3;EGYPTIAN HIEROGLYPH W017;Lo;0;L;;;;;N;;;;;
-133C4;EGYPTIAN HIEROGLYPH W017A;Lo;0;L;;;;;N;;;;;
-133C5;EGYPTIAN HIEROGLYPH W018;Lo;0;L;;;;;N;;;;;
-133C6;EGYPTIAN HIEROGLYPH W018A;Lo;0;L;;;;;N;;;;;
-133C7;EGYPTIAN HIEROGLYPH W019;Lo;0;L;;;;;N;;;;;
-133C8;EGYPTIAN HIEROGLYPH W020;Lo;0;L;;;;;N;;;;;
-133C9;EGYPTIAN HIEROGLYPH W021;Lo;0;L;;;;;N;;;;;
-133CA;EGYPTIAN HIEROGLYPH W022;Lo;0;L;;;;;N;;;;;
-133CB;EGYPTIAN HIEROGLYPH W023;Lo;0;L;;;;;N;;;;;
-133CC;EGYPTIAN HIEROGLYPH W024;Lo;0;L;;;;;N;;;;;
-133CD;EGYPTIAN HIEROGLYPH W024A;Lo;0;L;;;;;N;;;;;
-133CE;EGYPTIAN HIEROGLYPH W025;Lo;0;L;;;;;N;;;;;
-133CF;EGYPTIAN HIEROGLYPH X001;Lo;0;L;;;;;N;;;;;
-133D0;EGYPTIAN HIEROGLYPH X002;Lo;0;L;;;;;N;;;;;
-133D1;EGYPTIAN HIEROGLYPH X003;Lo;0;L;;;;;N;;;;;
-133D2;EGYPTIAN HIEROGLYPH X004;Lo;0;L;;;;;N;;;;;
-133D3;EGYPTIAN HIEROGLYPH X004A;Lo;0;L;;;;;N;;;;;
-133D4;EGYPTIAN HIEROGLYPH X004B;Lo;0;L;;;;;N;;;;;
-133D5;EGYPTIAN HIEROGLYPH X005;Lo;0;L;;;;;N;;;;;
-133D6;EGYPTIAN HIEROGLYPH X006;Lo;0;L;;;;;N;;;;;
-133D7;EGYPTIAN HIEROGLYPH X006A;Lo;0;L;;;;;N;;;;;
-133D8;EGYPTIAN HIEROGLYPH X007;Lo;0;L;;;;;N;;;;;
-133D9;EGYPTIAN HIEROGLYPH X008;Lo;0;L;;;;;N;;;;;
-133DA;EGYPTIAN HIEROGLYPH X008A;Lo;0;L;;;;;N;;;;;
-133DB;EGYPTIAN HIEROGLYPH Y001;Lo;0;L;;;;;N;;;;;
-133DC;EGYPTIAN HIEROGLYPH Y001A;Lo;0;L;;;;;N;;;;;
-133DD;EGYPTIAN HIEROGLYPH Y002;Lo;0;L;;;;;N;;;;;
-133DE;EGYPTIAN HIEROGLYPH Y003;Lo;0;L;;;;;N;;;;;
-133DF;EGYPTIAN HIEROGLYPH Y004;Lo;0;L;;;;;N;;;;;
-133E0;EGYPTIAN HIEROGLYPH Y005;Lo;0;L;;;;;N;;;;;
-133E1;EGYPTIAN HIEROGLYPH Y006;Lo;0;L;;;;;N;;;;;
-133E2;EGYPTIAN HIEROGLYPH Y007;Lo;0;L;;;;;N;;;;;
-133E3;EGYPTIAN HIEROGLYPH Y008;Lo;0;L;;;;;N;;;;;
-133E4;EGYPTIAN HIEROGLYPH Z001;Lo;0;L;;;;;N;;;;;
-133E5;EGYPTIAN HIEROGLYPH Z002;Lo;0;L;;;;;N;;;;;
-133E6;EGYPTIAN HIEROGLYPH Z002A;Lo;0;L;;;;;N;;;;;
-133E7;EGYPTIAN HIEROGLYPH Z002B;Lo;0;L;;;;;N;;;;;
-133E8;EGYPTIAN HIEROGLYPH Z002C;Lo;0;L;;;;;N;;;;;
-133E9;EGYPTIAN HIEROGLYPH Z002D;Lo;0;L;;;;;N;;;;;
-133EA;EGYPTIAN HIEROGLYPH Z003;Lo;0;L;;;;;N;;;;;
-133EB;EGYPTIAN HIEROGLYPH Z003A;Lo;0;L;;;;;N;;;;;
-133EC;EGYPTIAN HIEROGLYPH Z003B;Lo;0;L;;;;;N;;;;;
-133ED;EGYPTIAN HIEROGLYPH Z004;Lo;0;L;;;;;N;;;;;
-133EE;EGYPTIAN HIEROGLYPH Z004A;Lo;0;L;;;;;N;;;;;
-133EF;EGYPTIAN HIEROGLYPH Z005;Lo;0;L;;;;;N;;;;;
-133F0;EGYPTIAN HIEROGLYPH Z005A;Lo;0;L;;;;;N;;;;;
-133F1;EGYPTIAN HIEROGLYPH Z006;Lo;0;L;;;;;N;;;;;
-133F2;EGYPTIAN HIEROGLYPH Z007;Lo;0;L;;;;;N;;;;;
-133F3;EGYPTIAN HIEROGLYPH Z008;Lo;0;L;;;;;N;;;;;
-133F4;EGYPTIAN HIEROGLYPH Z009;Lo;0;L;;;;;N;;;;;
-133F5;EGYPTIAN HIEROGLYPH Z010;Lo;0;L;;;;;N;;;;;
-133F6;EGYPTIAN HIEROGLYPH Z011;Lo;0;L;;;;;N;;;;;
-133F7;EGYPTIAN HIEROGLYPH Z012;Lo;0;L;;;;;N;;;;;
-133F8;EGYPTIAN HIEROGLYPH Z013;Lo;0;L;;;;;N;;;;;
-133F9;EGYPTIAN HIEROGLYPH Z014;Lo;0;L;;;;;N;;;;;
-133FA;EGYPTIAN HIEROGLYPH Z015;Lo;0;L;;;;;N;;;;;
-133FB;EGYPTIAN HIEROGLYPH Z015A;Lo;0;L;;;;;N;;;;;
-133FC;EGYPTIAN HIEROGLYPH Z015B;Lo;0;L;;;;;N;;;;;
-133FD;EGYPTIAN HIEROGLYPH Z015C;Lo;0;L;;;;;N;;;;;
-133FE;EGYPTIAN HIEROGLYPH Z015D;Lo;0;L;;;;;N;;;;;
-133FF;EGYPTIAN HIEROGLYPH Z015E;Lo;0;L;;;;;N;;;;;
-13400;EGYPTIAN HIEROGLYPH Z015F;Lo;0;L;;;;;N;;;;;
-13401;EGYPTIAN HIEROGLYPH Z015G;Lo;0;L;;;;;N;;;;;
-13402;EGYPTIAN HIEROGLYPH Z015H;Lo;0;L;;;;;N;;;;;
-13403;EGYPTIAN HIEROGLYPH Z015I;Lo;0;L;;;;;N;;;;;
-13404;EGYPTIAN HIEROGLYPH Z016;Lo;0;L;;;;;N;;;;;
-13405;EGYPTIAN HIEROGLYPH Z016A;Lo;0;L;;;;;N;;;;;
-13406;EGYPTIAN HIEROGLYPH Z016B;Lo;0;L;;;;;N;;;;;
-13407;EGYPTIAN HIEROGLYPH Z016C;Lo;0;L;;;;;N;;;;;
-13408;EGYPTIAN HIEROGLYPH Z016D;Lo;0;L;;;;;N;;;;;
-13409;EGYPTIAN HIEROGLYPH Z016E;Lo;0;L;;;;;N;;;;;
-1340A;EGYPTIAN HIEROGLYPH Z016F;Lo;0;L;;;;;N;;;;;
-1340B;EGYPTIAN HIEROGLYPH Z016G;Lo;0;L;;;;;N;;;;;
-1340C;EGYPTIAN HIEROGLYPH Z016H;Lo;0;L;;;;;N;;;;;
-1340D;EGYPTIAN HIEROGLYPH AA001;Lo;0;L;;;;;N;;;;;
-1340E;EGYPTIAN HIEROGLYPH AA002;Lo;0;L;;;;;N;;;;;
-1340F;EGYPTIAN HIEROGLYPH AA003;Lo;0;L;;;;;N;;;;;
-13410;EGYPTIAN HIEROGLYPH AA004;Lo;0;L;;;;;N;;;;;
-13411;EGYPTIAN HIEROGLYPH AA005;Lo;0;L;;;;;N;;;;;
-13412;EGYPTIAN HIEROGLYPH AA006;Lo;0;L;;;;;N;;;;;
-13413;EGYPTIAN HIEROGLYPH AA007;Lo;0;L;;;;;N;;;;;
-13414;EGYPTIAN HIEROGLYPH AA007A;Lo;0;L;;;;;N;;;;;
-13415;EGYPTIAN HIEROGLYPH AA007B;Lo;0;L;;;;;N;;;;;
-13416;EGYPTIAN HIEROGLYPH AA008;Lo;0;L;;;;;N;;;;;
-13417;EGYPTIAN HIEROGLYPH AA009;Lo;0;L;;;;;N;;;;;
-13418;EGYPTIAN HIEROGLYPH AA010;Lo;0;L;;;;;N;;;;;
-13419;EGYPTIAN HIEROGLYPH AA011;Lo;0;L;;;;;N;;;;;
-1341A;EGYPTIAN HIEROGLYPH AA012;Lo;0;L;;;;;N;;;;;
-1341B;EGYPTIAN HIEROGLYPH AA013;Lo;0;L;;;;;N;;;;;
-1341C;EGYPTIAN HIEROGLYPH AA014;Lo;0;L;;;;;N;;;;;
-1341D;EGYPTIAN HIEROGLYPH AA015;Lo;0;L;;;;;N;;;;;
-1341E;EGYPTIAN HIEROGLYPH AA016;Lo;0;L;;;;;N;;;;;
-1341F;EGYPTIAN HIEROGLYPH AA017;Lo;0;L;;;;;N;;;;;
-13420;EGYPTIAN HIEROGLYPH AA018;Lo;0;L;;;;;N;;;;;
-13421;EGYPTIAN HIEROGLYPH AA019;Lo;0;L;;;;;N;;;;;
-13422;EGYPTIAN HIEROGLYPH AA020;Lo;0;L;;;;;N;;;;;
-13423;EGYPTIAN HIEROGLYPH AA021;Lo;0;L;;;;;N;;;;;
-13424;EGYPTIAN HIEROGLYPH AA022;Lo;0;L;;;;;N;;;;;
-13425;EGYPTIAN HIEROGLYPH AA023;Lo;0;L;;;;;N;;;;;
-13426;EGYPTIAN HIEROGLYPH AA024;Lo;0;L;;;;;N;;;;;
-13427;EGYPTIAN HIEROGLYPH AA025;Lo;0;L;;;;;N;;;;;
-13428;EGYPTIAN HIEROGLYPH AA026;Lo;0;L;;;;;N;;;;;
-13429;EGYPTIAN HIEROGLYPH AA027;Lo;0;L;;;;;N;;;;;
-1342A;EGYPTIAN HIEROGLYPH AA028;Lo;0;L;;;;;N;;;;;
-1342B;EGYPTIAN HIEROGLYPH AA029;Lo;0;L;;;;;N;;;;;
-1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;;
-1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;;
-1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;;
-16800;BAMUM LETTER PHASE-A NGKUE MFON;Lo;0;L;;;;;N;;;;;
-16801;BAMUM LETTER PHASE-A GBIEE FON;Lo;0;L;;;;;N;;;;;
-16802;BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE;Lo;0;L;;;;;N;;;;;
-16803;BAMUM LETTER PHASE-A PON MFON PIPAEMBA;Lo;0;L;;;;;N;;;;;
-16804;BAMUM LETTER PHASE-A NAA MFON;Lo;0;L;;;;;N;;;;;
-16805;BAMUM LETTER PHASE-A SHUENSHUET;Lo;0;L;;;;;N;;;;;
-16806;BAMUM LETTER PHASE-A TITA MFON;Lo;0;L;;;;;N;;;;;
-16807;BAMUM LETTER PHASE-A NZA MFON;Lo;0;L;;;;;N;;;;;
-16808;BAMUM LETTER PHASE-A SHINDA PA NJI;Lo;0;L;;;;;N;;;;;
-16809;BAMUM LETTER PHASE-A PON PA NJI PIPAEMGBIEE;Lo;0;L;;;;;N;;;;;
-1680A;BAMUM LETTER PHASE-A PON PA NJI PIPAEMBA;Lo;0;L;;;;;N;;;;;
-1680B;BAMUM LETTER PHASE-A MAEMBGBIEE;Lo;0;L;;;;;N;;;;;
-1680C;BAMUM LETTER PHASE-A TU MAEMBA;Lo;0;L;;;;;N;;;;;
-1680D;BAMUM LETTER PHASE-A NGANGU;Lo;0;L;;;;;N;;;;;
-1680E;BAMUM LETTER PHASE-A MAEMVEUX;Lo;0;L;;;;;N;;;;;
-1680F;BAMUM LETTER PHASE-A MANSUAE;Lo;0;L;;;;;N;;;;;
-16810;BAMUM LETTER PHASE-A MVEUAENGAM;Lo;0;L;;;;;N;;;;;
-16811;BAMUM LETTER PHASE-A SEUNYAM;Lo;0;L;;;;;N;;;;;
-16812;BAMUM LETTER PHASE-A NTOQPEN;Lo;0;L;;;;;N;;;;;
-16813;BAMUM LETTER PHASE-A KEUKEUTNDA;Lo;0;L;;;;;N;;;;;
-16814;BAMUM LETTER PHASE-A NKINDI;Lo;0;L;;;;;N;;;;;
-16815;BAMUM LETTER PHASE-A SUU;Lo;0;L;;;;;N;;;;;
-16816;BAMUM LETTER PHASE-A NGKUENZEUM;Lo;0;L;;;;;N;;;;;
-16817;BAMUM LETTER PHASE-A LAPAQ;Lo;0;L;;;;;N;;;;;
-16818;BAMUM LETTER PHASE-A LET KUT;Lo;0;L;;;;;N;;;;;
-16819;BAMUM LETTER PHASE-A NTAP MFAA;Lo;0;L;;;;;N;;;;;
-1681A;BAMUM LETTER PHASE-A MAEKEUP;Lo;0;L;;;;;N;;;;;
-1681B;BAMUM LETTER PHASE-A PASHAE;Lo;0;L;;;;;N;;;;;
-1681C;BAMUM LETTER PHASE-A GHEUAERAE;Lo;0;L;;;;;N;;;;;
-1681D;BAMUM LETTER PHASE-A PAMSHAE;Lo;0;L;;;;;N;;;;;
-1681E;BAMUM LETTER PHASE-A MON NGGEUAET;Lo;0;L;;;;;N;;;;;
-1681F;BAMUM LETTER PHASE-A NZUN MEUT;Lo;0;L;;;;;N;;;;;
-16820;BAMUM LETTER PHASE-A U YUQ NAE;Lo;0;L;;;;;N;;;;;
-16821;BAMUM LETTER PHASE-A GHEUAEGHEUAE;Lo;0;L;;;;;N;;;;;
-16822;BAMUM LETTER PHASE-A NTAP NTAA;Lo;0;L;;;;;N;;;;;
-16823;BAMUM LETTER PHASE-A SISA;Lo;0;L;;;;;N;;;;;
-16824;BAMUM LETTER PHASE-A MGBASA;Lo;0;L;;;;;N;;;;;
-16825;BAMUM LETTER PHASE-A MEUNJOMNDEUQ;Lo;0;L;;;;;N;;;;;
-16826;BAMUM LETTER PHASE-A MOOMPUQ;Lo;0;L;;;;;N;;;;;
-16827;BAMUM LETTER PHASE-A KAFA;Lo;0;L;;;;;N;;;;;
-16828;BAMUM LETTER PHASE-A PA LEERAEWA;Lo;0;L;;;;;N;;;;;
-16829;BAMUM LETTER PHASE-A NDA LEERAEWA;Lo;0;L;;;;;N;;;;;
-1682A;BAMUM LETTER PHASE-A PET;Lo;0;L;;;;;N;;;;;
-1682B;BAMUM LETTER PHASE-A MAEMKPEN;Lo;0;L;;;;;N;;;;;
-1682C;BAMUM LETTER PHASE-A NIKA;Lo;0;L;;;;;N;;;;;
-1682D;BAMUM LETTER PHASE-A PUP;Lo;0;L;;;;;N;;;;;
-1682E;BAMUM LETTER PHASE-A TUAEP;Lo;0;L;;;;;N;;;;;
-1682F;BAMUM LETTER PHASE-A LUAEP;Lo;0;L;;;;;N;;;;;
-16830;BAMUM LETTER PHASE-A SONJAM;Lo;0;L;;;;;N;;;;;
-16831;BAMUM LETTER PHASE-A TEUTEUWEN;Lo;0;L;;;;;N;;;;;
-16832;BAMUM LETTER PHASE-A MAENYI;Lo;0;L;;;;;N;;;;;
-16833;BAMUM LETTER PHASE-A KET;Lo;0;L;;;;;N;;;;;
-16834;BAMUM LETTER PHASE-A NDAANGGEUAET;Lo;0;L;;;;;N;;;;;
-16835;BAMUM LETTER PHASE-A KUOQ;Lo;0;L;;;;;N;;;;;
-16836;BAMUM LETTER PHASE-A MOOMEUT;Lo;0;L;;;;;N;;;;;
-16837;BAMUM LETTER PHASE-A SHUM;Lo;0;L;;;;;N;;;;;
-16838;BAMUM LETTER PHASE-A LOMMAE;Lo;0;L;;;;;N;;;;;
-16839;BAMUM LETTER PHASE-A FIRI;Lo;0;L;;;;;N;;;;;
-1683A;BAMUM LETTER PHASE-A ROM;Lo;0;L;;;;;N;;;;;
-1683B;BAMUM LETTER PHASE-A KPOQ;Lo;0;L;;;;;N;;;;;
-1683C;BAMUM LETTER PHASE-A SOQ;Lo;0;L;;;;;N;;;;;
-1683D;BAMUM LETTER PHASE-A MAP PIEET;Lo;0;L;;;;;N;;;;;
-1683E;BAMUM LETTER PHASE-A SHIRAE;Lo;0;L;;;;;N;;;;;
-1683F;BAMUM LETTER PHASE-A NTAP;Lo;0;L;;;;;N;;;;;
-16840;BAMUM LETTER PHASE-A SHOQ NSHUT YUM;Lo;0;L;;;;;N;;;;;
-16841;BAMUM LETTER PHASE-A NYIT MONGKEUAEQ;Lo;0;L;;;;;N;;;;;
-16842;BAMUM LETTER PHASE-A PAARAE;Lo;0;L;;;;;N;;;;;
-16843;BAMUM LETTER PHASE-A NKAARAE;Lo;0;L;;;;;N;;;;;
-16844;BAMUM LETTER PHASE-A UNKNOWN;Lo;0;L;;;;;N;;;;;
-16845;BAMUM LETTER PHASE-A NGGEN;Lo;0;L;;;;;N;;;;;
-16846;BAMUM LETTER PHASE-A MAESI;Lo;0;L;;;;;N;;;;;
-16847;BAMUM LETTER PHASE-A NJAM;Lo;0;L;;;;;N;;;;;
-16848;BAMUM LETTER PHASE-A MBANYI;Lo;0;L;;;;;N;;;;;
-16849;BAMUM LETTER PHASE-A NYET;Lo;0;L;;;;;N;;;;;
-1684A;BAMUM LETTER PHASE-A TEUAEN;Lo;0;L;;;;;N;;;;;
-1684B;BAMUM LETTER PHASE-A SOT;Lo;0;L;;;;;N;;;;;
-1684C;BAMUM LETTER PHASE-A PAAM;Lo;0;L;;;;;N;;;;;
-1684D;BAMUM LETTER PHASE-A NSHIEE;Lo;0;L;;;;;N;;;;;
-1684E;BAMUM LETTER PHASE-A MAEM;Lo;0;L;;;;;N;;;;;
-1684F;BAMUM LETTER PHASE-A NYI;Lo;0;L;;;;;N;;;;;
-16850;BAMUM LETTER PHASE-A KAQ;Lo;0;L;;;;;N;;;;;
-16851;BAMUM LETTER PHASE-A NSHA;Lo;0;L;;;;;N;;;;;
-16852;BAMUM LETTER PHASE-A VEE;Lo;0;L;;;;;N;;;;;
-16853;BAMUM LETTER PHASE-A LU;Lo;0;L;;;;;N;;;;;
-16854;BAMUM LETTER PHASE-A NEN;Lo;0;L;;;;;N;;;;;
-16855;BAMUM LETTER PHASE-A NAQ;Lo;0;L;;;;;N;;;;;
-16856;BAMUM LETTER PHASE-A MBAQ;Lo;0;L;;;;;N;;;;;
-16857;BAMUM LETTER PHASE-B NSHUET;Lo;0;L;;;;;N;;;;;
-16858;BAMUM LETTER PHASE-B TU MAEMGBIEE;Lo;0;L;;;;;N;;;;;
-16859;BAMUM LETTER PHASE-B SIEE;Lo;0;L;;;;;N;;;;;
-1685A;BAMUM LETTER PHASE-B SET TU;Lo;0;L;;;;;N;;;;;
-1685B;BAMUM LETTER PHASE-B LOM NTEUM;Lo;0;L;;;;;N;;;;;
-1685C;BAMUM LETTER PHASE-B MBA MAELEE;Lo;0;L;;;;;N;;;;;
-1685D;BAMUM LETTER PHASE-B KIEEM;Lo;0;L;;;;;N;;;;;
-1685E;BAMUM LETTER PHASE-B YEURAE;Lo;0;L;;;;;N;;;;;
-1685F;BAMUM LETTER PHASE-B MBAARAE;Lo;0;L;;;;;N;;;;;
-16860;BAMUM LETTER PHASE-B KAM;Lo;0;L;;;;;N;;;;;
-16861;BAMUM LETTER PHASE-B PEESHI;Lo;0;L;;;;;N;;;;;
-16862;BAMUM LETTER PHASE-B YAFU LEERAEWA;Lo;0;L;;;;;N;;;;;
-16863;BAMUM LETTER PHASE-B LAM NSHUT NYAM;Lo;0;L;;;;;N;;;;;
-16864;BAMUM LETTER PHASE-B NTIEE SHEUOQ;Lo;0;L;;;;;N;;;;;
-16865;BAMUM LETTER PHASE-B NDU NJAA;Lo;0;L;;;;;N;;;;;
-16866;BAMUM LETTER PHASE-B GHEUGHEUAEM;Lo;0;L;;;;;N;;;;;
-16867;BAMUM LETTER PHASE-B PIT;Lo;0;L;;;;;N;;;;;
-16868;BAMUM LETTER PHASE-B TU NSIEE;Lo;0;L;;;;;N;;;;;
-16869;BAMUM LETTER PHASE-B SHET NJAQ;Lo;0;L;;;;;N;;;;;
-1686A;BAMUM LETTER PHASE-B SHEUAEQTU;Lo;0;L;;;;;N;;;;;
-1686B;BAMUM LETTER PHASE-B MFON TEUAEQ;Lo;0;L;;;;;N;;;;;
-1686C;BAMUM LETTER PHASE-B MBIT MBAAKET;Lo;0;L;;;;;N;;;;;
-1686D;BAMUM LETTER PHASE-B NYI NTEUM;Lo;0;L;;;;;N;;;;;
-1686E;BAMUM LETTER PHASE-B KEUPUQ;Lo;0;L;;;;;N;;;;;
-1686F;BAMUM LETTER PHASE-B GHEUGHEN;Lo;0;L;;;;;N;;;;;
-16870;BAMUM LETTER PHASE-B KEUYEUX;Lo;0;L;;;;;N;;;;;
-16871;BAMUM LETTER PHASE-B LAANAE;Lo;0;L;;;;;N;;;;;
-16872;BAMUM LETTER PHASE-B PARUM;Lo;0;L;;;;;N;;;;;
-16873;BAMUM LETTER PHASE-B VEUM;Lo;0;L;;;;;N;;;;;
-16874;BAMUM LETTER PHASE-B NGKINDI MVOP;Lo;0;L;;;;;N;;;;;
-16875;BAMUM LETTER PHASE-B NGGEU MBU;Lo;0;L;;;;;N;;;;;
-16876;BAMUM LETTER PHASE-B WUAET;Lo;0;L;;;;;N;;;;;
-16877;BAMUM LETTER PHASE-B SAKEUAE;Lo;0;L;;;;;N;;;;;
-16878;BAMUM LETTER PHASE-B TAAM;Lo;0;L;;;;;N;;;;;
-16879;BAMUM LETTER PHASE-B MEUQ;Lo;0;L;;;;;N;;;;;
-1687A;BAMUM LETTER PHASE-B NGGUOQ;Lo;0;L;;;;;N;;;;;
-1687B;BAMUM LETTER PHASE-B NGGUOQ LARGE;Lo;0;L;;;;;N;;;;;
-1687C;BAMUM LETTER PHASE-B MFIYAQ;Lo;0;L;;;;;N;;;;;
-1687D;BAMUM LETTER PHASE-B SUE;Lo;0;L;;;;;N;;;;;
-1687E;BAMUM LETTER PHASE-B MBEURI;Lo;0;L;;;;;N;;;;;
-1687F;BAMUM LETTER PHASE-B MONTIEEN;Lo;0;L;;;;;N;;;;;
-16880;BAMUM LETTER PHASE-B NYAEMAE;Lo;0;L;;;;;N;;;;;
-16881;BAMUM LETTER PHASE-B PUNGAAM;Lo;0;L;;;;;N;;;;;
-16882;BAMUM LETTER PHASE-B MEUT NGGEET;Lo;0;L;;;;;N;;;;;
-16883;BAMUM LETTER PHASE-B FEUX;Lo;0;L;;;;;N;;;;;
-16884;BAMUM LETTER PHASE-B MBUOQ;Lo;0;L;;;;;N;;;;;
-16885;BAMUM LETTER PHASE-B FEE;Lo;0;L;;;;;N;;;;;
-16886;BAMUM LETTER PHASE-B KEUAEM;Lo;0;L;;;;;N;;;;;
-16887;BAMUM LETTER PHASE-B MA NJEUAENA;Lo;0;L;;;;;N;;;;;
-16888;BAMUM LETTER PHASE-B MA NJUQA;Lo;0;L;;;;;N;;;;;
-16889;BAMUM LETTER PHASE-B LET;Lo;0;L;;;;;N;;;;;
-1688A;BAMUM LETTER PHASE-B NGGAAM;Lo;0;L;;;;;N;;;;;
-1688B;BAMUM LETTER PHASE-B NSEN;Lo;0;L;;;;;N;;;;;
-1688C;BAMUM LETTER PHASE-B MA;Lo;0;L;;;;;N;;;;;
-1688D;BAMUM LETTER PHASE-B KIQ;Lo;0;L;;;;;N;;;;;
-1688E;BAMUM LETTER PHASE-B NGOM;Lo;0;L;;;;;N;;;;;
-1688F;BAMUM LETTER PHASE-C NGKUE MAEMBA;Lo;0;L;;;;;N;;;;;
-16890;BAMUM LETTER PHASE-C NZA;Lo;0;L;;;;;N;;;;;
-16891;BAMUM LETTER PHASE-C YUM;Lo;0;L;;;;;N;;;;;
-16892;BAMUM LETTER PHASE-C WANGKUOQ;Lo;0;L;;;;;N;;;;;
-16893;BAMUM LETTER PHASE-C NGGEN;Lo;0;L;;;;;N;;;;;
-16894;BAMUM LETTER PHASE-C NDEUAEREE;Lo;0;L;;;;;N;;;;;
-16895;BAMUM LETTER PHASE-C NGKAQ;Lo;0;L;;;;;N;;;;;
-16896;BAMUM LETTER PHASE-C GHARAE;Lo;0;L;;;;;N;;;;;
-16897;BAMUM LETTER PHASE-C MBEEKEET;Lo;0;L;;;;;N;;;;;
-16898;BAMUM LETTER PHASE-C GBAYI;Lo;0;L;;;;;N;;;;;
-16899;BAMUM LETTER PHASE-C NYIR MKPARAQ MEUN;Lo;0;L;;;;;N;;;;;
-1689A;BAMUM LETTER PHASE-C NTU MBIT;Lo;0;L;;;;;N;;;;;
-1689B;BAMUM LETTER PHASE-C MBEUM;Lo;0;L;;;;;N;;;;;
-1689C;BAMUM LETTER PHASE-C PIRIEEN;Lo;0;L;;;;;N;;;;;
-1689D;BAMUM LETTER PHASE-C NDOMBU;Lo;0;L;;;;;N;;;;;
-1689E;BAMUM LETTER PHASE-C MBAA CABBAGE-TREE;Lo;0;L;;;;;N;;;;;
-1689F;BAMUM LETTER PHASE-C KEUSHEUAEP;Lo;0;L;;;;;N;;;;;
-168A0;BAMUM LETTER PHASE-C GHAP;Lo;0;L;;;;;N;;;;;
-168A1;BAMUM LETTER PHASE-C KEUKAQ;Lo;0;L;;;;;N;;;;;
-168A2;BAMUM LETTER PHASE-C YU MUOMAE;Lo;0;L;;;;;N;;;;;
-168A3;BAMUM LETTER PHASE-C NZEUM;Lo;0;L;;;;;N;;;;;
-168A4;BAMUM LETTER PHASE-C MBUE;Lo;0;L;;;;;N;;;;;
-168A5;BAMUM LETTER PHASE-C NSEUAEN;Lo;0;L;;;;;N;;;;;
-168A6;BAMUM LETTER PHASE-C MBIT;Lo;0;L;;;;;N;;;;;
-168A7;BAMUM LETTER PHASE-C YEUQ;Lo;0;L;;;;;N;;;;;
-168A8;BAMUM LETTER PHASE-C KPARAQ;Lo;0;L;;;;;N;;;;;
-168A9;BAMUM LETTER PHASE-C KAA;Lo;0;L;;;;;N;;;;;
-168AA;BAMUM LETTER PHASE-C SEUX;Lo;0;L;;;;;N;;;;;
-168AB;BAMUM LETTER PHASE-C NDIDA;Lo;0;L;;;;;N;;;;;
-168AC;BAMUM LETTER PHASE-C TAASHAE;Lo;0;L;;;;;N;;;;;
-168AD;BAMUM LETTER PHASE-C NJUEQ;Lo;0;L;;;;;N;;;;;
-168AE;BAMUM LETTER PHASE-C TITA YUE;Lo;0;L;;;;;N;;;;;
-168AF;BAMUM LETTER PHASE-C SUAET;Lo;0;L;;;;;N;;;;;
-168B0;BAMUM LETTER PHASE-C NGGUAEN NYAM;Lo;0;L;;;;;N;;;;;
-168B1;BAMUM LETTER PHASE-C VEUX;Lo;0;L;;;;;N;;;;;
-168B2;BAMUM LETTER PHASE-C NANSANAQ;Lo;0;L;;;;;N;;;;;
-168B3;BAMUM LETTER PHASE-C MA KEUAERI;Lo;0;L;;;;;N;;;;;
-168B4;BAMUM LETTER PHASE-C NTAA;Lo;0;L;;;;;N;;;;;
-168B5;BAMUM LETTER PHASE-C NGGUON;Lo;0;L;;;;;N;;;;;
-168B6;BAMUM LETTER PHASE-C LAP;Lo;0;L;;;;;N;;;;;
-168B7;BAMUM LETTER PHASE-C MBIRIEEN;Lo;0;L;;;;;N;;;;;
-168B8;BAMUM LETTER PHASE-C MGBASAQ;Lo;0;L;;;;;N;;;;;
-168B9;BAMUM LETTER PHASE-C NTEUNGBA;Lo;0;L;;;;;N;;;;;
-168BA;BAMUM LETTER PHASE-C TEUTEUX;Lo;0;L;;;;;N;;;;;
-168BB;BAMUM LETTER PHASE-C NGGUM;Lo;0;L;;;;;N;;;;;
-168BC;BAMUM LETTER PHASE-C FUE;Lo;0;L;;;;;N;;;;;
-168BD;BAMUM LETTER PHASE-C NDEUT;Lo;0;L;;;;;N;;;;;
-168BE;BAMUM LETTER PHASE-C NSA;Lo;0;L;;;;;N;;;;;
-168BF;BAMUM LETTER PHASE-C NSHAQ;Lo;0;L;;;;;N;;;;;
-168C0;BAMUM LETTER PHASE-C BUNG;Lo;0;L;;;;;N;;;;;
-168C1;BAMUM LETTER PHASE-C VEUAEPEN;Lo;0;L;;;;;N;;;;;
-168C2;BAMUM LETTER PHASE-C MBERAE;Lo;0;L;;;;;N;;;;;
-168C3;BAMUM LETTER PHASE-C RU;Lo;0;L;;;;;N;;;;;
-168C4;BAMUM LETTER PHASE-C NJAEM;Lo;0;L;;;;;N;;;;;
-168C5;BAMUM LETTER PHASE-C LAM;Lo;0;L;;;;;N;;;;;
-168C6;BAMUM LETTER PHASE-C TITUAEP;Lo;0;L;;;;;N;;;;;
-168C7;BAMUM LETTER PHASE-C NSUOT NGOM;Lo;0;L;;;;;N;;;;;
-168C8;BAMUM LETTER PHASE-C NJEEEE;Lo;0;L;;;;;N;;;;;
-168C9;BAMUM LETTER PHASE-C KET;Lo;0;L;;;;;N;;;;;
-168CA;BAMUM LETTER PHASE-C NGGU;Lo;0;L;;;;;N;;;;;
-168CB;BAMUM LETTER PHASE-C MAESI;Lo;0;L;;;;;N;;;;;
-168CC;BAMUM LETTER PHASE-C MBUAEM;Lo;0;L;;;;;N;;;;;
-168CD;BAMUM LETTER PHASE-C LU;Lo;0;L;;;;;N;;;;;
-168CE;BAMUM LETTER PHASE-C KUT;Lo;0;L;;;;;N;;;;;
-168CF;BAMUM LETTER PHASE-C NJAM;Lo;0;L;;;;;N;;;;;
-168D0;BAMUM LETTER PHASE-C NGOM;Lo;0;L;;;;;N;;;;;
-168D1;BAMUM LETTER PHASE-C WUP;Lo;0;L;;;;;N;;;;;
-168D2;BAMUM LETTER PHASE-C NGGUEET;Lo;0;L;;;;;N;;;;;
-168D3;BAMUM LETTER PHASE-C NSOM;Lo;0;L;;;;;N;;;;;
-168D4;BAMUM LETTER PHASE-C NTEN;Lo;0;L;;;;;N;;;;;
-168D5;BAMUM LETTER PHASE-C KUOP NKAARAE;Lo;0;L;;;;;N;;;;;
-168D6;BAMUM LETTER PHASE-C NSUN;Lo;0;L;;;;;N;;;;;
-168D7;BAMUM LETTER PHASE-C NDAM;Lo;0;L;;;;;N;;;;;
-168D8;BAMUM LETTER PHASE-C MA NSIEE;Lo;0;L;;;;;N;;;;;
-168D9;BAMUM LETTER PHASE-C YAA;Lo;0;L;;;;;N;;;;;
-168DA;BAMUM LETTER PHASE-C NDAP;Lo;0;L;;;;;N;;;;;
-168DB;BAMUM LETTER PHASE-C SHUEQ;Lo;0;L;;;;;N;;;;;
-168DC;BAMUM LETTER PHASE-C SETFON;Lo;0;L;;;;;N;;;;;
-168DD;BAMUM LETTER PHASE-C MBI;Lo;0;L;;;;;N;;;;;
-168DE;BAMUM LETTER PHASE-C MAEMBA;Lo;0;L;;;;;N;;;;;
-168DF;BAMUM LETTER PHASE-C MBANYI;Lo;0;L;;;;;N;;;;;
-168E0;BAMUM LETTER PHASE-C KEUSEUX;Lo;0;L;;;;;N;;;;;
-168E1;BAMUM LETTER PHASE-C MBEUX;Lo;0;L;;;;;N;;;;;
-168E2;BAMUM LETTER PHASE-C KEUM;Lo;0;L;;;;;N;;;;;
-168E3;BAMUM LETTER PHASE-C MBAA PICKET;Lo;0;L;;;;;N;;;;;
-168E4;BAMUM LETTER PHASE-C YUWOQ;Lo;0;L;;;;;N;;;;;
-168E5;BAMUM LETTER PHASE-C NJEUX;Lo;0;L;;;;;N;;;;;
-168E6;BAMUM LETTER PHASE-C MIEE;Lo;0;L;;;;;N;;;;;
-168E7;BAMUM LETTER PHASE-C MUAE;Lo;0;L;;;;;N;;;;;
-168E8;BAMUM LETTER PHASE-C SHIQ;Lo;0;L;;;;;N;;;;;
-168E9;BAMUM LETTER PHASE-C KEN LAW;Lo;0;L;;;;;N;;;;;
-168EA;BAMUM LETTER PHASE-C KEN FATIGUE;Lo;0;L;;;;;N;;;;;
-168EB;BAMUM LETTER PHASE-C NGAQ;Lo;0;L;;;;;N;;;;;
-168EC;BAMUM LETTER PHASE-C NAQ;Lo;0;L;;;;;N;;;;;
-168ED;BAMUM LETTER PHASE-C LIQ;Lo;0;L;;;;;N;;;;;
-168EE;BAMUM LETTER PHASE-C PIN;Lo;0;L;;;;;N;;;;;
-168EF;BAMUM LETTER PHASE-C PEN;Lo;0;L;;;;;N;;;;;
-168F0;BAMUM LETTER PHASE-C TET;Lo;0;L;;;;;N;;;;;
-168F1;BAMUM LETTER PHASE-D MBUO;Lo;0;L;;;;;N;;;;;
-168F2;BAMUM LETTER PHASE-D WAP;Lo;0;L;;;;;N;;;;;
-168F3;BAMUM LETTER PHASE-D NJI;Lo;0;L;;;;;N;;;;;
-168F4;BAMUM LETTER PHASE-D MFON;Lo;0;L;;;;;N;;;;;
-168F5;BAMUM LETTER PHASE-D NJIEE;Lo;0;L;;;;;N;;;;;
-168F6;BAMUM LETTER PHASE-D LIEE;Lo;0;L;;;;;N;;;;;
-168F7;BAMUM LETTER PHASE-D NJEUT;Lo;0;L;;;;;N;;;;;
-168F8;BAMUM LETTER PHASE-D NSHEE;Lo;0;L;;;;;N;;;;;
-168F9;BAMUM LETTER PHASE-D NGGAAMAE;Lo;0;L;;;;;N;;;;;
-168FA;BAMUM LETTER PHASE-D NYAM;Lo;0;L;;;;;N;;;;;
-168FB;BAMUM LETTER PHASE-D WUAEN;Lo;0;L;;;;;N;;;;;
-168FC;BAMUM LETTER PHASE-D NGKUN;Lo;0;L;;;;;N;;;;;
-168FD;BAMUM LETTER PHASE-D SHEE;Lo;0;L;;;;;N;;;;;
-168FE;BAMUM LETTER PHASE-D NGKAP;Lo;0;L;;;;;N;;;;;
-168FF;BAMUM LETTER PHASE-D KEUAETMEUN;Lo;0;L;;;;;N;;;;;
-16900;BAMUM LETTER PHASE-D TEUT;Lo;0;L;;;;;N;;;;;
-16901;BAMUM LETTER PHASE-D SHEUAE;Lo;0;L;;;;;N;;;;;
-16902;BAMUM LETTER PHASE-D NJAP;Lo;0;L;;;;;N;;;;;
-16903;BAMUM LETTER PHASE-D SUE;Lo;0;L;;;;;N;;;;;
-16904;BAMUM LETTER PHASE-D KET;Lo;0;L;;;;;N;;;;;
-16905;BAMUM LETTER PHASE-D YAEMMAE;Lo;0;L;;;;;N;;;;;
-16906;BAMUM LETTER PHASE-D KUOM;Lo;0;L;;;;;N;;;;;
-16907;BAMUM LETTER PHASE-D SAP;Lo;0;L;;;;;N;;;;;
-16908;BAMUM LETTER PHASE-D MFEUT;Lo;0;L;;;;;N;;;;;
-16909;BAMUM LETTER PHASE-D NDEUX;Lo;0;L;;;;;N;;;;;
-1690A;BAMUM LETTER PHASE-D MALEERI;Lo;0;L;;;;;N;;;;;
-1690B;BAMUM LETTER PHASE-D MEUT;Lo;0;L;;;;;N;;;;;
-1690C;BAMUM LETTER PHASE-D SEUAEQ;Lo;0;L;;;;;N;;;;;
-1690D;BAMUM LETTER PHASE-D YEN;Lo;0;L;;;;;N;;;;;
-1690E;BAMUM LETTER PHASE-D NJEUAEM;Lo;0;L;;;;;N;;;;;
-1690F;BAMUM LETTER PHASE-D KEUOT MBUAE;Lo;0;L;;;;;N;;;;;
-16910;BAMUM LETTER PHASE-D NGKEURI;Lo;0;L;;;;;N;;;;;
-16911;BAMUM LETTER PHASE-D TU;Lo;0;L;;;;;N;;;;;
-16912;BAMUM LETTER PHASE-D GHAA;Lo;0;L;;;;;N;;;;;
-16913;BAMUM LETTER PHASE-D NGKYEE;Lo;0;L;;;;;N;;;;;
-16914;BAMUM LETTER PHASE-D FEUFEUAET;Lo;0;L;;;;;N;;;;;
-16915;BAMUM LETTER PHASE-D NDEE;Lo;0;L;;;;;N;;;;;
-16916;BAMUM LETTER PHASE-D MGBOFUM;Lo;0;L;;;;;N;;;;;
-16917;BAMUM LETTER PHASE-D LEUAEP;Lo;0;L;;;;;N;;;;;
-16918;BAMUM LETTER PHASE-D NDON;Lo;0;L;;;;;N;;;;;
-16919;BAMUM LETTER PHASE-D MONI;Lo;0;L;;;;;N;;;;;
-1691A;BAMUM LETTER PHASE-D MGBEUN;Lo;0;L;;;;;N;;;;;
-1691B;BAMUM LETTER PHASE-D PUUT;Lo;0;L;;;;;N;;;;;
-1691C;BAMUM LETTER PHASE-D MGBIEE;Lo;0;L;;;;;N;;;;;
-1691D;BAMUM LETTER PHASE-D MFO;Lo;0;L;;;;;N;;;;;
-1691E;BAMUM LETTER PHASE-D LUM;Lo;0;L;;;;;N;;;;;
-1691F;BAMUM LETTER PHASE-D NSIEEP;Lo;0;L;;;;;N;;;;;
-16920;BAMUM LETTER PHASE-D MBAA;Lo;0;L;;;;;N;;;;;
-16921;BAMUM LETTER PHASE-D KWAET;Lo;0;L;;;;;N;;;;;
-16922;BAMUM LETTER PHASE-D NYET;Lo;0;L;;;;;N;;;;;
-16923;BAMUM LETTER PHASE-D TEUAEN;Lo;0;L;;;;;N;;;;;
-16924;BAMUM LETTER PHASE-D SOT;Lo;0;L;;;;;N;;;;;
-16925;BAMUM LETTER PHASE-D YUWOQ;Lo;0;L;;;;;N;;;;;
-16926;BAMUM LETTER PHASE-D KEUM;Lo;0;L;;;;;N;;;;;
-16927;BAMUM LETTER PHASE-D RAEM;Lo;0;L;;;;;N;;;;;
-16928;BAMUM LETTER PHASE-D TEEEE;Lo;0;L;;;;;N;;;;;
-16929;BAMUM LETTER PHASE-D NGKEUAEQ;Lo;0;L;;;;;N;;;;;
-1692A;BAMUM LETTER PHASE-D MFEUAE;Lo;0;L;;;;;N;;;;;
-1692B;BAMUM LETTER PHASE-D NSIEET;Lo;0;L;;;;;N;;;;;
-1692C;BAMUM LETTER PHASE-D KEUP;Lo;0;L;;;;;N;;;;;
-1692D;BAMUM LETTER PHASE-D PIP;Lo;0;L;;;;;N;;;;;
-1692E;BAMUM LETTER PHASE-D PEUTAE;Lo;0;L;;;;;N;;;;;
-1692F;BAMUM LETTER PHASE-D NYUE;Lo;0;L;;;;;N;;;;;
-16930;BAMUM LETTER PHASE-D LET;Lo;0;L;;;;;N;;;;;
-16931;BAMUM LETTER PHASE-D NGGAAM;Lo;0;L;;;;;N;;;;;
-16932;BAMUM LETTER PHASE-D MFIEE;Lo;0;L;;;;;N;;;;;
-16933;BAMUM LETTER PHASE-D NGGWAEN;Lo;0;L;;;;;N;;;;;
-16934;BAMUM LETTER PHASE-D YUOM;Lo;0;L;;;;;N;;;;;
-16935;BAMUM LETTER PHASE-D PAP;Lo;0;L;;;;;N;;;;;
-16936;BAMUM LETTER PHASE-D YUOP;Lo;0;L;;;;;N;;;;;
-16937;BAMUM LETTER PHASE-D NDAM;Lo;0;L;;;;;N;;;;;
-16938;BAMUM LETTER PHASE-D NTEUM;Lo;0;L;;;;;N;;;;;
-16939;BAMUM LETTER PHASE-D SUAE;Lo;0;L;;;;;N;;;;;
-1693A;BAMUM LETTER PHASE-D KUN;Lo;0;L;;;;;N;;;;;
-1693B;BAMUM LETTER PHASE-D NGGEUX;Lo;0;L;;;;;N;;;;;
-1693C;BAMUM LETTER PHASE-D NGKIEE;Lo;0;L;;;;;N;;;;;
-1693D;BAMUM LETTER PHASE-D TUOT;Lo;0;L;;;;;N;;;;;
-1693E;BAMUM LETTER PHASE-D MEUN;Lo;0;L;;;;;N;;;;;
-1693F;BAMUM LETTER PHASE-D KUQ;Lo;0;L;;;;;N;;;;;
-16940;BAMUM LETTER PHASE-D NSUM;Lo;0;L;;;;;N;;;;;
-16941;BAMUM LETTER PHASE-D TEUN;Lo;0;L;;;;;N;;;;;
-16942;BAMUM LETTER PHASE-D MAENJET;Lo;0;L;;;;;N;;;;;
-16943;BAMUM LETTER PHASE-D NGGAP;Lo;0;L;;;;;N;;;;;
-16944;BAMUM LETTER PHASE-D LEUM;Lo;0;L;;;;;N;;;;;
-16945;BAMUM LETTER PHASE-D NGGUOM;Lo;0;L;;;;;N;;;;;
-16946;BAMUM LETTER PHASE-D NSHUT;Lo;0;L;;;;;N;;;;;
-16947;BAMUM LETTER PHASE-D NJUEQ;Lo;0;L;;;;;N;;;;;
-16948;BAMUM LETTER PHASE-D GHEUAE;Lo;0;L;;;;;N;;;;;
-16949;BAMUM LETTER PHASE-D KU;Lo;0;L;;;;;N;;;;;
-1694A;BAMUM LETTER PHASE-D REN OLD;Lo;0;L;;;;;N;;;;;
-1694B;BAMUM LETTER PHASE-D TAE;Lo;0;L;;;;;N;;;;;
-1694C;BAMUM LETTER PHASE-D TOQ;Lo;0;L;;;;;N;;;;;
-1694D;BAMUM LETTER PHASE-D NYI;Lo;0;L;;;;;N;;;;;
-1694E;BAMUM LETTER PHASE-D RII;Lo;0;L;;;;;N;;;;;
-1694F;BAMUM LETTER PHASE-D LEEEE;Lo;0;L;;;;;N;;;;;
-16950;BAMUM LETTER PHASE-D MEEEE;Lo;0;L;;;;;N;;;;;
-16951;BAMUM LETTER PHASE-D M;Lo;0;L;;;;;N;;;;;
-16952;BAMUM LETTER PHASE-D SUU;Lo;0;L;;;;;N;;;;;
-16953;BAMUM LETTER PHASE-D MU;Lo;0;L;;;;;N;;;;;
-16954;BAMUM LETTER PHASE-D SHII;Lo;0;L;;;;;N;;;;;
-16955;BAMUM LETTER PHASE-D SHEUX;Lo;0;L;;;;;N;;;;;
-16956;BAMUM LETTER PHASE-D KYEE;Lo;0;L;;;;;N;;;;;
-16957;BAMUM LETTER PHASE-D NU;Lo;0;L;;;;;N;;;;;
-16958;BAMUM LETTER PHASE-D SHU;Lo;0;L;;;;;N;;;;;
-16959;BAMUM LETTER PHASE-D NTEE;Lo;0;L;;;;;N;;;;;
-1695A;BAMUM LETTER PHASE-D PEE;Lo;0;L;;;;;N;;;;;
-1695B;BAMUM LETTER PHASE-D NI;Lo;0;L;;;;;N;;;;;
-1695C;BAMUM LETTER PHASE-D SHOQ;Lo;0;L;;;;;N;;;;;
-1695D;BAMUM LETTER PHASE-D PUQ;Lo;0;L;;;;;N;;;;;
-1695E;BAMUM LETTER PHASE-D MVOP;Lo;0;L;;;;;N;;;;;
-1695F;BAMUM LETTER PHASE-D LOQ;Lo;0;L;;;;;N;;;;;
-16960;BAMUM LETTER PHASE-D REN MUCH;Lo;0;L;;;;;N;;;;;
-16961;BAMUM LETTER PHASE-D TI;Lo;0;L;;;;;N;;;;;
-16962;BAMUM LETTER PHASE-D NTUU;Lo;0;L;;;;;N;;;;;
-16963;BAMUM LETTER PHASE-D MBAA SEVEN;Lo;0;L;;;;;N;;;;;
-16964;BAMUM LETTER PHASE-D SAQ;Lo;0;L;;;;;N;;;;;
-16965;BAMUM LETTER PHASE-D FAA;Lo;0;L;;;;;N;;;;;
-16966;BAMUM LETTER PHASE-E NDAP;Lo;0;L;;;;;N;;;;;
-16967;BAMUM LETTER PHASE-E TOON;Lo;0;L;;;;;N;;;;;
-16968;BAMUM LETTER PHASE-E MBEUM;Lo;0;L;;;;;N;;;;;
-16969;BAMUM LETTER PHASE-E LAP;Lo;0;L;;;;;N;;;;;
-1696A;BAMUM LETTER PHASE-E VOM;Lo;0;L;;;;;N;;;;;
-1696B;BAMUM LETTER PHASE-E LOON;Lo;0;L;;;;;N;;;;;
-1696C;BAMUM LETTER PHASE-E PAA;Lo;0;L;;;;;N;;;;;
-1696D;BAMUM LETTER PHASE-E SOM;Lo;0;L;;;;;N;;;;;
-1696E;BAMUM LETTER PHASE-E RAQ;Lo;0;L;;;;;N;;;;;
-1696F;BAMUM LETTER PHASE-E NSHUOP;Lo;0;L;;;;;N;;;;;
-16970;BAMUM LETTER PHASE-E NDUN;Lo;0;L;;;;;N;;;;;
-16971;BAMUM LETTER PHASE-E PUAE;Lo;0;L;;;;;N;;;;;
-16972;BAMUM LETTER PHASE-E TAM;Lo;0;L;;;;;N;;;;;
-16973;BAMUM LETTER PHASE-E NGKA;Lo;0;L;;;;;N;;;;;
-16974;BAMUM LETTER PHASE-E KPEUX;Lo;0;L;;;;;N;;;;;
-16975;BAMUM LETTER PHASE-E WUO;Lo;0;L;;;;;N;;;;;
-16976;BAMUM LETTER PHASE-E SEE;Lo;0;L;;;;;N;;;;;
-16977;BAMUM LETTER PHASE-E NGGEUAET;Lo;0;L;;;;;N;;;;;
-16978;BAMUM LETTER PHASE-E PAAM;Lo;0;L;;;;;N;;;;;
-16979;BAMUM LETTER PHASE-E TOO;Lo;0;L;;;;;N;;;;;
-1697A;BAMUM LETTER PHASE-E KUOP;Lo;0;L;;;;;N;;;;;
-1697B;BAMUM LETTER PHASE-E LOM;Lo;0;L;;;;;N;;;;;
-1697C;BAMUM LETTER PHASE-E NSHIEE;Lo;0;L;;;;;N;;;;;
-1697D;BAMUM LETTER PHASE-E NGOP;Lo;0;L;;;;;N;;;;;
-1697E;BAMUM LETTER PHASE-E MAEM;Lo;0;L;;;;;N;;;;;
-1697F;BAMUM LETTER PHASE-E NGKEUX;Lo;0;L;;;;;N;;;;;
-16980;BAMUM LETTER PHASE-E NGOQ;Lo;0;L;;;;;N;;;;;
-16981;BAMUM LETTER PHASE-E NSHUE;Lo;0;L;;;;;N;;;;;
-16982;BAMUM LETTER PHASE-E RIMGBA;Lo;0;L;;;;;N;;;;;
-16983;BAMUM LETTER PHASE-E NJEUX;Lo;0;L;;;;;N;;;;;
-16984;BAMUM LETTER PHASE-E PEEM;Lo;0;L;;;;;N;;;;;
-16985;BAMUM LETTER PHASE-E SAA;Lo;0;L;;;;;N;;;;;
-16986;BAMUM LETTER PHASE-E NGGURAE;Lo;0;L;;;;;N;;;;;
-16987;BAMUM LETTER PHASE-E MGBA;Lo;0;L;;;;;N;;;;;
-16988;BAMUM LETTER PHASE-E GHEUX;Lo;0;L;;;;;N;;;;;
-16989;BAMUM LETTER PHASE-E NGKEUAEM;Lo;0;L;;;;;N;;;;;
-1698A;BAMUM LETTER PHASE-E NJAEMLI;Lo;0;L;;;;;N;;;;;
-1698B;BAMUM LETTER PHASE-E MAP;Lo;0;L;;;;;N;;;;;
-1698C;BAMUM LETTER PHASE-E LOOT;Lo;0;L;;;;;N;;;;;
-1698D;BAMUM LETTER PHASE-E NGGEEEE;Lo;0;L;;;;;N;;;;;
-1698E;BAMUM LETTER PHASE-E NDIQ;Lo;0;L;;;;;N;;;;;
-1698F;BAMUM LETTER PHASE-E TAEN NTEUM;Lo;0;L;;;;;N;;;;;
-16990;BAMUM LETTER PHASE-E SET;Lo;0;L;;;;;N;;;;;
-16991;BAMUM LETTER PHASE-E PUM;Lo;0;L;;;;;N;;;;;
-16992;BAMUM LETTER PHASE-E NDAA SOFTNESS;Lo;0;L;;;;;N;;;;;
-16993;BAMUM LETTER PHASE-E NGGUAESHAE NYAM;Lo;0;L;;;;;N;;;;;
-16994;BAMUM LETTER PHASE-E YIEE;Lo;0;L;;;;;N;;;;;
-16995;BAMUM LETTER PHASE-E GHEUN;Lo;0;L;;;;;N;;;;;
-16996;BAMUM LETTER PHASE-E TUAE;Lo;0;L;;;;;N;;;;;
-16997;BAMUM LETTER PHASE-E YEUAE;Lo;0;L;;;;;N;;;;;
-16998;BAMUM LETTER PHASE-E PO;Lo;0;L;;;;;N;;;;;
-16999;BAMUM LETTER PHASE-E TUMAE;Lo;0;L;;;;;N;;;;;
-1699A;BAMUM LETTER PHASE-E KEUAE;Lo;0;L;;;;;N;;;;;
-1699B;BAMUM LETTER PHASE-E SUAEN;Lo;0;L;;;;;N;;;;;
-1699C;BAMUM LETTER PHASE-E TEUAEQ;Lo;0;L;;;;;N;;;;;
-1699D;BAMUM LETTER PHASE-E VEUAE;Lo;0;L;;;;;N;;;;;
-1699E;BAMUM LETTER PHASE-E WEUX;Lo;0;L;;;;;N;;;;;
-1699F;BAMUM LETTER PHASE-E LAAM;Lo;0;L;;;;;N;;;;;
-169A0;BAMUM LETTER PHASE-E PU;Lo;0;L;;;;;N;;;;;
-169A1;BAMUM LETTER PHASE-E TAAQ;Lo;0;L;;;;;N;;;;;
-169A2;BAMUM LETTER PHASE-E GHAAMAE;Lo;0;L;;;;;N;;;;;
-169A3;BAMUM LETTER PHASE-E NGEUREUT;Lo;0;L;;;;;N;;;;;
-169A4;BAMUM LETTER PHASE-E SHEUAEQ;Lo;0;L;;;;;N;;;;;
-169A5;BAMUM LETTER PHASE-E MGBEN;Lo;0;L;;;;;N;;;;;
-169A6;BAMUM LETTER PHASE-E MBEE;Lo;0;L;;;;;N;;;;;
-169A7;BAMUM LETTER PHASE-E NZAQ;Lo;0;L;;;;;N;;;;;
-169A8;BAMUM LETTER PHASE-E NKOM;Lo;0;L;;;;;N;;;;;
-169A9;BAMUM LETTER PHASE-E GBET;Lo;0;L;;;;;N;;;;;
-169AA;BAMUM LETTER PHASE-E TUM;Lo;0;L;;;;;N;;;;;
-169AB;BAMUM LETTER PHASE-E KUET;Lo;0;L;;;;;N;;;;;
-169AC;BAMUM LETTER PHASE-E YAP;Lo;0;L;;;;;N;;;;;
-169AD;BAMUM LETTER PHASE-E NYI CLEAVER;Lo;0;L;;;;;N;;;;;
-169AE;BAMUM LETTER PHASE-E YIT;Lo;0;L;;;;;N;;;;;
-169AF;BAMUM LETTER PHASE-E MFEUQ;Lo;0;L;;;;;N;;;;;
-169B0;BAMUM LETTER PHASE-E NDIAQ;Lo;0;L;;;;;N;;;;;
-169B1;BAMUM LETTER PHASE-E PIEEQ;Lo;0;L;;;;;N;;;;;
-169B2;BAMUM LETTER PHASE-E YUEQ;Lo;0;L;;;;;N;;;;;
-169B3;BAMUM LETTER PHASE-E LEUAEM;Lo;0;L;;;;;N;;;;;
-169B4;BAMUM LETTER PHASE-E FUE;Lo;0;L;;;;;N;;;;;
-169B5;BAMUM LETTER PHASE-E GBEUX;Lo;0;L;;;;;N;;;;;
-169B6;BAMUM LETTER PHASE-E NGKUP;Lo;0;L;;;;;N;;;;;
-169B7;BAMUM LETTER PHASE-E KET;Lo;0;L;;;;;N;;;;;
-169B8;BAMUM LETTER PHASE-E MAE;Lo;0;L;;;;;N;;;;;
-169B9;BAMUM LETTER PHASE-E NGKAAMI;Lo;0;L;;;;;N;;;;;
-169BA;BAMUM LETTER PHASE-E GHET;Lo;0;L;;;;;N;;;;;
-169BB;BAMUM LETTER PHASE-E FA;Lo;0;L;;;;;N;;;;;
-169BC;BAMUM LETTER PHASE-E NTUM;Lo;0;L;;;;;N;;;;;
-169BD;BAMUM LETTER PHASE-E PEUT;Lo;0;L;;;;;N;;;;;
-169BE;BAMUM LETTER PHASE-E YEUM;Lo;0;L;;;;;N;;;;;
-169BF;BAMUM LETTER PHASE-E NGGEUAE;Lo;0;L;;;;;N;;;;;
-169C0;BAMUM LETTER PHASE-E NYI BETWEEN;Lo;0;L;;;;;N;;;;;
-169C1;BAMUM LETTER PHASE-E NZUQ;Lo;0;L;;;;;N;;;;;
-169C2;BAMUM LETTER PHASE-E POON;Lo;0;L;;;;;N;;;;;
-169C3;BAMUM LETTER PHASE-E MIEE;Lo;0;L;;;;;N;;;;;
-169C4;BAMUM LETTER PHASE-E FUET;Lo;0;L;;;;;N;;;;;
-169C5;BAMUM LETTER PHASE-E NAE;Lo;0;L;;;;;N;;;;;
-169C6;BAMUM LETTER PHASE-E MUAE;Lo;0;L;;;;;N;;;;;
-169C7;BAMUM LETTER PHASE-E GHEUAE;Lo;0;L;;;;;N;;;;;
-169C8;BAMUM LETTER PHASE-E FU I;Lo;0;L;;;;;N;;;;;
-169C9;BAMUM LETTER PHASE-E MVI;Lo;0;L;;;;;N;;;;;
-169CA;BAMUM LETTER PHASE-E PUAQ;Lo;0;L;;;;;N;;;;;
-169CB;BAMUM LETTER PHASE-E NGKUM;Lo;0;L;;;;;N;;;;;
-169CC;BAMUM LETTER PHASE-E KUT;Lo;0;L;;;;;N;;;;;
-169CD;BAMUM LETTER PHASE-E PIET;Lo;0;L;;;;;N;;;;;
-169CE;BAMUM LETTER PHASE-E NTAP;Lo;0;L;;;;;N;;;;;
-169CF;BAMUM LETTER PHASE-E YEUAET;Lo;0;L;;;;;N;;;;;
-169D0;BAMUM LETTER PHASE-E NGGUP;Lo;0;L;;;;;N;;;;;
-169D1;BAMUM LETTER PHASE-E PA PEOPLE;Lo;0;L;;;;;N;;;;;
-169D2;BAMUM LETTER PHASE-E FU CALL;Lo;0;L;;;;;N;;;;;
-169D3;BAMUM LETTER PHASE-E FOM;Lo;0;L;;;;;N;;;;;
-169D4;BAMUM LETTER PHASE-E NJEE;Lo;0;L;;;;;N;;;;;
-169D5;BAMUM LETTER PHASE-E A;Lo;0;L;;;;;N;;;;;
-169D6;BAMUM LETTER PHASE-E TOQ;Lo;0;L;;;;;N;;;;;
-169D7;BAMUM LETTER PHASE-E O;Lo;0;L;;;;;N;;;;;
-169D8;BAMUM LETTER PHASE-E I;Lo;0;L;;;;;N;;;;;
-169D9;BAMUM LETTER PHASE-E LAQ;Lo;0;L;;;;;N;;;;;
-169DA;BAMUM LETTER PHASE-E PA PLURAL;Lo;0;L;;;;;N;;;;;
-169DB;BAMUM LETTER PHASE-E TAA;Lo;0;L;;;;;N;;;;;
-169DC;BAMUM LETTER PHASE-E TAQ;Lo;0;L;;;;;N;;;;;
-169DD;BAMUM LETTER PHASE-E NDAA MY HOUSE;Lo;0;L;;;;;N;;;;;
-169DE;BAMUM LETTER PHASE-E SHIQ;Lo;0;L;;;;;N;;;;;
-169DF;BAMUM LETTER PHASE-E YEUX;Lo;0;L;;;;;N;;;;;
-169E0;BAMUM LETTER PHASE-E NGUAE;Lo;0;L;;;;;N;;;;;
-169E1;BAMUM LETTER PHASE-E YUAEN;Lo;0;L;;;;;N;;;;;
-169E2;BAMUM LETTER PHASE-E YOQ SWIMMING;Lo;0;L;;;;;N;;;;;
-169E3;BAMUM LETTER PHASE-E YOQ COVER;Lo;0;L;;;;;N;;;;;
-169E4;BAMUM LETTER PHASE-E YUQ;Lo;0;L;;;;;N;;;;;
-169E5;BAMUM LETTER PHASE-E YUN;Lo;0;L;;;;;N;;;;;
-169E6;BAMUM LETTER PHASE-E KEUX;Lo;0;L;;;;;N;;;;;
-169E7;BAMUM LETTER PHASE-E PEUX;Lo;0;L;;;;;N;;;;;
-169E8;BAMUM LETTER PHASE-E NJEE EPOCH;Lo;0;L;;;;;N;;;;;
-169E9;BAMUM LETTER PHASE-E PUE;Lo;0;L;;;;;N;;;;;
-169EA;BAMUM LETTER PHASE-E WUE;Lo;0;L;;;;;N;;;;;
-169EB;BAMUM LETTER PHASE-E FEE;Lo;0;L;;;;;N;;;;;
-169EC;BAMUM LETTER PHASE-E VEE;Lo;0;L;;;;;N;;;;;
-169ED;BAMUM LETTER PHASE-E LU;Lo;0;L;;;;;N;;;;;
-169EE;BAMUM LETTER PHASE-E MI;Lo;0;L;;;;;N;;;;;
-169EF;BAMUM LETTER PHASE-E REUX;Lo;0;L;;;;;N;;;;;
-169F0;BAMUM LETTER PHASE-E RAE;Lo;0;L;;;;;N;;;;;
-169F1;BAMUM LETTER PHASE-E NGUAET;Lo;0;L;;;;;N;;;;;
-169F2;BAMUM LETTER PHASE-E NGA;Lo;0;L;;;;;N;;;;;
-169F3;BAMUM LETTER PHASE-E SHO;Lo;0;L;;;;;N;;;;;
-169F4;BAMUM LETTER PHASE-E SHOQ;Lo;0;L;;;;;N;;;;;
-169F5;BAMUM LETTER PHASE-E FU REMEDY;Lo;0;L;;;;;N;;;;;
-169F6;BAMUM LETTER PHASE-E NA;Lo;0;L;;;;;N;;;;;
-169F7;BAMUM LETTER PHASE-E PI;Lo;0;L;;;;;N;;;;;
-169F8;BAMUM LETTER PHASE-E LOQ;Lo;0;L;;;;;N;;;;;
-169F9;BAMUM LETTER PHASE-E KO;Lo;0;L;;;;;N;;;;;
-169FA;BAMUM LETTER PHASE-E MEN;Lo;0;L;;;;;N;;;;;
-169FB;BAMUM LETTER PHASE-E MA;Lo;0;L;;;;;N;;;;;
-169FC;BAMUM LETTER PHASE-E MAQ;Lo;0;L;;;;;N;;;;;
-169FD;BAMUM LETTER PHASE-E TEU;Lo;0;L;;;;;N;;;;;
-169FE;BAMUM LETTER PHASE-E KI;Lo;0;L;;;;;N;;;;;
-169FF;BAMUM LETTER PHASE-E MON;Lo;0;L;;;;;N;;;;;
-16A00;BAMUM LETTER PHASE-E TEN;Lo;0;L;;;;;N;;;;;
-16A01;BAMUM LETTER PHASE-E FAQ;Lo;0;L;;;;;N;;;;;
-16A02;BAMUM LETTER PHASE-E GHOM;Lo;0;L;;;;;N;;;;;
-16A03;BAMUM LETTER PHASE-F KA;Lo;0;L;;;;;N;;;;;
-16A04;BAMUM LETTER PHASE-F U;Lo;0;L;;;;;N;;;;;
-16A05;BAMUM LETTER PHASE-F KU;Lo;0;L;;;;;N;;;;;
-16A06;BAMUM LETTER PHASE-F EE;Lo;0;L;;;;;N;;;;;
-16A07;BAMUM LETTER PHASE-F REE;Lo;0;L;;;;;N;;;;;
-16A08;BAMUM LETTER PHASE-F TAE;Lo;0;L;;;;;N;;;;;
-16A09;BAMUM LETTER PHASE-F NYI;Lo;0;L;;;;;N;;;;;
-16A0A;BAMUM LETTER PHASE-F LA;Lo;0;L;;;;;N;;;;;
-16A0B;BAMUM LETTER PHASE-F RII;Lo;0;L;;;;;N;;;;;
-16A0C;BAMUM LETTER PHASE-F RIEE;Lo;0;L;;;;;N;;;;;
-16A0D;BAMUM LETTER PHASE-F MEEEE;Lo;0;L;;;;;N;;;;;
-16A0E;BAMUM LETTER PHASE-F TAA;Lo;0;L;;;;;N;;;;;
-16A0F;BAMUM LETTER PHASE-F NDAA;Lo;0;L;;;;;N;;;;;
-16A10;BAMUM LETTER PHASE-F NJAEM;Lo;0;L;;;;;N;;;;;
-16A11;BAMUM LETTER PHASE-F M;Lo;0;L;;;;;N;;;;;
-16A12;BAMUM LETTER PHASE-F SUU;Lo;0;L;;;;;N;;;;;
-16A13;BAMUM LETTER PHASE-F SHII;Lo;0;L;;;;;N;;;;;
-16A14;BAMUM LETTER PHASE-F SI;Lo;0;L;;;;;N;;;;;
-16A15;BAMUM LETTER PHASE-F SEUX;Lo;0;L;;;;;N;;;;;
-16A16;BAMUM LETTER PHASE-F KYEE;Lo;0;L;;;;;N;;;;;
-16A17;BAMUM LETTER PHASE-F KET;Lo;0;L;;;;;N;;;;;
-16A18;BAMUM LETTER PHASE-F NUAE;Lo;0;L;;;;;N;;;;;
-16A19;BAMUM LETTER PHASE-F NU;Lo;0;L;;;;;N;;;;;
-16A1A;BAMUM LETTER PHASE-F NJUAE;Lo;0;L;;;;;N;;;;;
-16A1B;BAMUM LETTER PHASE-F YOQ;Lo;0;L;;;;;N;;;;;
-16A1C;BAMUM LETTER PHASE-F SHU;Lo;0;L;;;;;N;;;;;
-16A1D;BAMUM LETTER PHASE-F YA;Lo;0;L;;;;;N;;;;;
-16A1E;BAMUM LETTER PHASE-F NSHA;Lo;0;L;;;;;N;;;;;
-16A1F;BAMUM LETTER PHASE-F PEUX;Lo;0;L;;;;;N;;;;;
-16A20;BAMUM LETTER PHASE-F NTEE;Lo;0;L;;;;;N;;;;;
-16A21;BAMUM LETTER PHASE-F WUE;Lo;0;L;;;;;N;;;;;
-16A22;BAMUM LETTER PHASE-F PEE;Lo;0;L;;;;;N;;;;;
-16A23;BAMUM LETTER PHASE-F RU;Lo;0;L;;;;;N;;;;;
-16A24;BAMUM LETTER PHASE-F NI;Lo;0;L;;;;;N;;;;;
-16A25;BAMUM LETTER PHASE-F REUX;Lo;0;L;;;;;N;;;;;
-16A26;BAMUM LETTER PHASE-F KEN;Lo;0;L;;;;;N;;;;;
-16A27;BAMUM LETTER PHASE-F NGKWAEN;Lo;0;L;;;;;N;;;;;
-16A28;BAMUM LETTER PHASE-F NGGA;Lo;0;L;;;;;N;;;;;
-16A29;BAMUM LETTER PHASE-F SHO;Lo;0;L;;;;;N;;;;;
-16A2A;BAMUM LETTER PHASE-F PUAE;Lo;0;L;;;;;N;;;;;
-16A2B;BAMUM LETTER PHASE-F FOM;Lo;0;L;;;;;N;;;;;
-16A2C;BAMUM LETTER PHASE-F WA;Lo;0;L;;;;;N;;;;;
-16A2D;BAMUM LETTER PHASE-F LI;Lo;0;L;;;;;N;;;;;
-16A2E;BAMUM LETTER PHASE-F LOQ;Lo;0;L;;;;;N;;;;;
-16A2F;BAMUM LETTER PHASE-F KO;Lo;0;L;;;;;N;;;;;
-16A30;BAMUM LETTER PHASE-F MBEN;Lo;0;L;;;;;N;;;;;
-16A31;BAMUM LETTER PHASE-F REN;Lo;0;L;;;;;N;;;;;
-16A32;BAMUM LETTER PHASE-F MA;Lo;0;L;;;;;N;;;;;
-16A33;BAMUM LETTER PHASE-F MO;Lo;0;L;;;;;N;;;;;
-16A34;BAMUM LETTER PHASE-F MBAA;Lo;0;L;;;;;N;;;;;
-16A35;BAMUM LETTER PHASE-F TET;Lo;0;L;;;;;N;;;;;
-16A36;BAMUM LETTER PHASE-F KPA;Lo;0;L;;;;;N;;;;;
-16A37;BAMUM LETTER PHASE-F SAMBA;Lo;0;L;;;;;N;;;;;
-16A38;BAMUM LETTER PHASE-F VUEQ;Lo;0;L;;;;;N;;;;;
-16F00;MIAO LETTER PA;Lo;0;L;;;;;N;;;;;
-16F01;MIAO LETTER BA;Lo;0;L;;;;;N;;;;;
-16F02;MIAO LETTER YI PA;Lo;0;L;;;;;N;;;;;
-16F03;MIAO LETTER PLA;Lo;0;L;;;;;N;;;;;
-16F04;MIAO LETTER MA;Lo;0;L;;;;;N;;;;;
-16F05;MIAO LETTER MHA;Lo;0;L;;;;;N;;;;;
-16F06;MIAO LETTER ARCHAIC MA;Lo;0;L;;;;;N;;;;;
-16F07;MIAO LETTER FA;Lo;0;L;;;;;N;;;;;
-16F08;MIAO LETTER VA;Lo;0;L;;;;;N;;;;;
-16F09;MIAO LETTER VFA;Lo;0;L;;;;;N;;;;;
-16F0A;MIAO LETTER TA;Lo;0;L;;;;;N;;;;;
-16F0B;MIAO LETTER DA;Lo;0;L;;;;;N;;;;;
-16F0C;MIAO LETTER YI TTA;Lo;0;L;;;;;N;;;;;
-16F0D;MIAO LETTER YI TA;Lo;0;L;;;;;N;;;;;
-16F0E;MIAO LETTER TTA;Lo;0;L;;;;;N;;;;;
-16F0F;MIAO LETTER DDA;Lo;0;L;;;;;N;;;;;
-16F10;MIAO LETTER NA;Lo;0;L;;;;;N;;;;;
-16F11;MIAO LETTER NHA;Lo;0;L;;;;;N;;;;;
-16F12;MIAO LETTER YI NNA;Lo;0;L;;;;;N;;;;;
-16F13;MIAO LETTER ARCHAIC NA;Lo;0;L;;;;;N;;;;;
-16F14;MIAO LETTER NNA;Lo;0;L;;;;;N;;;;;
-16F15;MIAO LETTER NNHA;Lo;0;L;;;;;N;;;;;
-16F16;MIAO LETTER LA;Lo;0;L;;;;;N;;;;;
-16F17;MIAO LETTER LYA;Lo;0;L;;;;;N;;;;;
-16F18;MIAO LETTER LHA;Lo;0;L;;;;;N;;;;;
-16F19;MIAO LETTER LHYA;Lo;0;L;;;;;N;;;;;
-16F1A;MIAO LETTER TLHA;Lo;0;L;;;;;N;;;;;
-16F1B;MIAO LETTER DLHA;Lo;0;L;;;;;N;;;;;
-16F1C;MIAO LETTER TLHYA;Lo;0;L;;;;;N;;;;;
-16F1D;MIAO LETTER DLHYA;Lo;0;L;;;;;N;;;;;
-16F1E;MIAO LETTER KA;Lo;0;L;;;;;N;;;;;
-16F1F;MIAO LETTER GA;Lo;0;L;;;;;N;;;;;
-16F20;MIAO LETTER YI KA;Lo;0;L;;;;;N;;;;;
-16F21;MIAO LETTER QA;Lo;0;L;;;;;N;;;;;
-16F22;MIAO LETTER QGA;Lo;0;L;;;;;N;;;;;
-16F23;MIAO LETTER NGA;Lo;0;L;;;;;N;;;;;
-16F24;MIAO LETTER NGHA;Lo;0;L;;;;;N;;;;;
-16F25;MIAO LETTER ARCHAIC NGA;Lo;0;L;;;;;N;;;;;
-16F26;MIAO LETTER HA;Lo;0;L;;;;;N;;;;;
-16F27;MIAO LETTER XA;Lo;0;L;;;;;N;;;;;
-16F28;MIAO LETTER GHA;Lo;0;L;;;;;N;;;;;
-16F29;MIAO LETTER GHHA;Lo;0;L;;;;;N;;;;;
-16F2A;MIAO LETTER TSSA;Lo;0;L;;;;;N;;;;;
-16F2B;MIAO LETTER DZZA;Lo;0;L;;;;;N;;;;;
-16F2C;MIAO LETTER NYA;Lo;0;L;;;;;N;;;;;
-16F2D;MIAO LETTER NYHA;Lo;0;L;;;;;N;;;;;
-16F2E;MIAO LETTER TSHA;Lo;0;L;;;;;N;;;;;
-16F2F;MIAO LETTER DZHA;Lo;0;L;;;;;N;;;;;
-16F30;MIAO LETTER YI TSHA;Lo;0;L;;;;;N;;;;;
-16F31;MIAO LETTER YI DZHA;Lo;0;L;;;;;N;;;;;
-16F32;MIAO LETTER REFORMED TSHA;Lo;0;L;;;;;N;;;;;
-16F33;MIAO LETTER SHA;Lo;0;L;;;;;N;;;;;
-16F34;MIAO LETTER SSA;Lo;0;L;;;;;N;;;;;
-16F35;MIAO LETTER ZHA;Lo;0;L;;;;;N;;;;;
-16F36;MIAO LETTER ZSHA;Lo;0;L;;;;;N;;;;;
-16F37;MIAO LETTER TSA;Lo;0;L;;;;;N;;;;;
-16F38;MIAO LETTER DZA;Lo;0;L;;;;;N;;;;;
-16F39;MIAO LETTER YI TSA;Lo;0;L;;;;;N;;;;;
-16F3A;MIAO LETTER SA;Lo;0;L;;;;;N;;;;;
-16F3B;MIAO LETTER ZA;Lo;0;L;;;;;N;;;;;
-16F3C;MIAO LETTER ZSA;Lo;0;L;;;;;N;;;;;
-16F3D;MIAO LETTER ZZA;Lo;0;L;;;;;N;;;;;
-16F3E;MIAO LETTER ZZSA;Lo;0;L;;;;;N;;;;;
-16F3F;MIAO LETTER ARCHAIC ZZA;Lo;0;L;;;;;N;;;;;
-16F40;MIAO LETTER ZZYA;Lo;0;L;;;;;N;;;;;
-16F41;MIAO LETTER ZZSYA;Lo;0;L;;;;;N;;;;;
-16F42;MIAO LETTER WA;Lo;0;L;;;;;N;;;;;
-16F43;MIAO LETTER AH;Lo;0;L;;;;;N;;;;;
-16F44;MIAO LETTER HHA;Lo;0;L;;;;;N;;;;;
-16F50;MIAO LETTER NASALIZATION;Lo;0;L;;;;;N;;;;;
-16F51;MIAO SIGN ASPIRATION;Mc;0;L;;;;;N;;;;;
-16F52;MIAO SIGN REFORMED VOICING;Mc;0;L;;;;;N;;;;;
-16F53;MIAO SIGN REFORMED ASPIRATION;Mc;0;L;;;;;N;;;;;
-16F54;MIAO VOWEL SIGN A;Mc;0;L;;;;;N;;;;;
-16F55;MIAO VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-16F56;MIAO VOWEL SIGN AHH;Mc;0;L;;;;;N;;;;;
-16F57;MIAO VOWEL SIGN AN;Mc;0;L;;;;;N;;;;;
-16F58;MIAO VOWEL SIGN ANG;Mc;0;L;;;;;N;;;;;
-16F59;MIAO VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-16F5A;MIAO VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
-16F5B;MIAO VOWEL SIGN WO;Mc;0;L;;;;;N;;;;;
-16F5C;MIAO VOWEL SIGN W;Mc;0;L;;;;;N;;;;;
-16F5D;MIAO VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-16F5E;MIAO VOWEL SIGN EN;Mc;0;L;;;;;N;;;;;
-16F5F;MIAO VOWEL SIGN ENG;Mc;0;L;;;;;N;;;;;
-16F60;MIAO VOWEL SIGN OEY;Mc;0;L;;;;;N;;;;;
-16F61;MIAO VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
-16F62;MIAO VOWEL SIGN IA;Mc;0;L;;;;;N;;;;;
-16F63;MIAO VOWEL SIGN IAN;Mc;0;L;;;;;N;;;;;
-16F64;MIAO VOWEL SIGN IANG;Mc;0;L;;;;;N;;;;;
-16F65;MIAO VOWEL SIGN IO;Mc;0;L;;;;;N;;;;;
-16F66;MIAO VOWEL SIGN IE;Mc;0;L;;;;;N;;;;;
-16F67;MIAO VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-16F68;MIAO VOWEL SIGN IU;Mc;0;L;;;;;N;;;;;
-16F69;MIAO VOWEL SIGN ING;Mc;0;L;;;;;N;;;;;
-16F6A;MIAO VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-16F6B;MIAO VOWEL SIGN UA;Mc;0;L;;;;;N;;;;;
-16F6C;MIAO VOWEL SIGN UAN;Mc;0;L;;;;;N;;;;;
-16F6D;MIAO VOWEL SIGN UANG;Mc;0;L;;;;;N;;;;;
-16F6E;MIAO VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
-16F6F;MIAO VOWEL SIGN UEI;Mc;0;L;;;;;N;;;;;
-16F70;MIAO VOWEL SIGN UNG;Mc;0;L;;;;;N;;;;;
-16F71;MIAO VOWEL SIGN Y;Mc;0;L;;;;;N;;;;;
-16F72;MIAO VOWEL SIGN YI;Mc;0;L;;;;;N;;;;;
-16F73;MIAO VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
-16F74;MIAO VOWEL SIGN AEE;Mc;0;L;;;;;N;;;;;
-16F75;MIAO VOWEL SIGN ERR;Mc;0;L;;;;;N;;;;;
-16F76;MIAO VOWEL SIGN ROUNDED ERR;Mc;0;L;;;;;N;;;;;
-16F77;MIAO VOWEL SIGN ER;Mc;0;L;;;;;N;;;;;
-16F78;MIAO VOWEL SIGN ROUNDED ER;Mc;0;L;;;;;N;;;;;
-16F79;MIAO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
-16F7A;MIAO VOWEL SIGN EI;Mc;0;L;;;;;N;;;;;
-16F7B;MIAO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
-16F7C;MIAO VOWEL SIGN OU;Mc;0;L;;;;;N;;;;;
-16F7D;MIAO VOWEL SIGN N;Mc;0;L;;;;;N;;;;;
-16F7E;MIAO VOWEL SIGN NG;Mc;0;L;;;;;N;;;;;
-16F8F;MIAO TONE RIGHT;Mn;0;NSM;;;;;N;;;;;
-16F90;MIAO TONE TOP RIGHT;Mn;0;NSM;;;;;N;;;;;
-16F91;MIAO TONE ABOVE;Mn;0;NSM;;;;;N;;;;;
-16F92;MIAO TONE BELOW;Mn;0;NSM;;;;;N;;;;;
-16F93;MIAO LETTER TONE-2;Lm;0;L;;;;;N;;;;;
-16F94;MIAO LETTER TONE-3;Lm;0;L;;;;;N;;;;;
-16F95;MIAO LETTER TONE-4;Lm;0;L;;;;;N;;;;;
-16F96;MIAO LETTER TONE-5;Lm;0;L;;;;;N;;;;;
-16F97;MIAO LETTER TONE-6;Lm;0;L;;;;;N;;;;;
-16F98;MIAO LETTER TONE-7;Lm;0;L;;;;;N;;;;;
-16F99;MIAO LETTER TONE-8;Lm;0;L;;;;;N;;;;;
-16F9A;MIAO LETTER REFORMED TONE-1;Lm;0;L;;;;;N;;;;;
-16F9B;MIAO LETTER REFORMED TONE-2;Lm;0;L;;;;;N;;;;;
-16F9C;MIAO LETTER REFORMED TONE-4;Lm;0;L;;;;;N;;;;;
-16F9D;MIAO LETTER REFORMED TONE-5;Lm;0;L;;;;;N;;;;;
-16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;;
-16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;;
-1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;;
-1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;;
-1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;;
-1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;;
-1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;;
-1D003;BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON;So;0;L;;;;;N;;;;;
-1D004;BYZANTINE MUSICAL SYMBOL OXEIA DIPLI;So;0;L;;;;;N;;;;;
-1D005;BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON;So;0;L;;;;;N;;;;;
-1D006;BYZANTINE MUSICAL SYMBOL VAREIA DIPLI;So;0;L;;;;;N;;;;;
-1D007;BYZANTINE MUSICAL SYMBOL KATHISTI;So;0;L;;;;;N;;;;;
-1D008;BYZANTINE MUSICAL SYMBOL SYRMATIKI;So;0;L;;;;;N;;;;;
-1D009;BYZANTINE MUSICAL SYMBOL PARAKLITIKI;So;0;L;;;;;N;;;;;
-1D00A;BYZANTINE MUSICAL SYMBOL YPOKRISIS;So;0;L;;;;;N;;;;;
-1D00B;BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI;So;0;L;;;;;N;;;;;
-1D00C;BYZANTINE MUSICAL SYMBOL KREMASTI;So;0;L;;;;;N;;;;;
-1D00D;BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON;So;0;L;;;;;N;;;;;
-1D00E;BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON;So;0;L;;;;;N;;;;;
-1D00F;BYZANTINE MUSICAL SYMBOL TELEIA;So;0;L;;;;;N;;;;;
-1D010;BYZANTINE MUSICAL SYMBOL KENTIMATA;So;0;L;;;;;N;;;;;
-1D011;BYZANTINE MUSICAL SYMBOL APOSTROFOS;So;0;L;;;;;N;;;;;
-1D012;BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI;So;0;L;;;;;N;;;;;
-1D013;BYZANTINE MUSICAL SYMBOL SYNEVMA;So;0;L;;;;;N;;;;;
-1D014;BYZANTINE MUSICAL SYMBOL THITA;So;0;L;;;;;N;;;;;
-1D015;BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION;So;0;L;;;;;N;;;;;
-1D016;BYZANTINE MUSICAL SYMBOL GORGON ARCHAION;So;0;L;;;;;N;;;;;
-1D017;BYZANTINE MUSICAL SYMBOL PSILON;So;0;L;;;;;N;;;;;
-1D018;BYZANTINE MUSICAL SYMBOL CHAMILON;So;0;L;;;;;N;;;;;
-1D019;BYZANTINE MUSICAL SYMBOL VATHY;So;0;L;;;;;N;;;;;
-1D01A;BYZANTINE MUSICAL SYMBOL ISON ARCHAION;So;0;L;;;;;N;;;;;
-1D01B;BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION;So;0;L;;;;;N;;;;;
-1D01C;BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION;So;0;L;;;;;N;;;;;
-1D01D;BYZANTINE MUSICAL SYMBOL SAXIMATA;So;0;L;;;;;N;;;;;
-1D01E;BYZANTINE MUSICAL SYMBOL PARICHON;So;0;L;;;;;N;;;;;
-1D01F;BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA;So;0;L;;;;;N;;;;;
-1D020;BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION;So;0;L;;;;;N;;;;;
-1D021;BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION;So;0;L;;;;;N;;;;;
-1D022;BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION;So;0;L;;;;;N;;;;;
-1D023;BYZANTINE MUSICAL SYMBOL APOTHEMA;So;0;L;;;;;N;;;;;
-1D024;BYZANTINE MUSICAL SYMBOL KLASMA;So;0;L;;;;;N;;;;;
-1D025;BYZANTINE MUSICAL SYMBOL REVMA;So;0;L;;;;;N;;;;;
-1D026;BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION;So;0;L;;;;;N;;;;;
-1D027;BYZANTINE MUSICAL SYMBOL TINAGMA;So;0;L;;;;;N;;;;;
-1D028;BYZANTINE MUSICAL SYMBOL ANATRICHISMA;So;0;L;;;;;N;;;;;
-1D029;BYZANTINE MUSICAL SYMBOL SEISMA;So;0;L;;;;;N;;;;;
-1D02A;BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION;So;0;L;;;;;N;;;;;
-1D02B;BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU;So;0;L;;;;;N;;;;;
-1D02C;BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION;So;0;L;;;;;N;;;;;
-1D02D;BYZANTINE MUSICAL SYMBOL THEMA;So;0;L;;;;;N;;;;;
-1D02E;BYZANTINE MUSICAL SYMBOL LEMOI;So;0;L;;;;;N;;;;;
-1D02F;BYZANTINE MUSICAL SYMBOL DYO;So;0;L;;;;;N;;;;;
-1D030;BYZANTINE MUSICAL SYMBOL TRIA;So;0;L;;;;;N;;;;;
-1D031;BYZANTINE MUSICAL SYMBOL TESSERA;So;0;L;;;;;N;;;;;
-1D032;BYZANTINE MUSICAL SYMBOL KRATIMATA;So;0;L;;;;;N;;;;;
-1D033;BYZANTINE MUSICAL SYMBOL APESO EXO NEO;So;0;L;;;;;N;;;;;
-1D034;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION;So;0;L;;;;;N;;;;;
-1D035;BYZANTINE MUSICAL SYMBOL IMIFTHORA;So;0;L;;;;;N;;;;;
-1D036;BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION;So;0;L;;;;;N;;;;;
-1D037;BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON;So;0;L;;;;;N;;;;;
-1D038;BYZANTINE MUSICAL SYMBOL PELASTON;So;0;L;;;;;N;;;;;
-1D039;BYZANTINE MUSICAL SYMBOL PSIFISTON;So;0;L;;;;;N;;;;;
-1D03A;BYZANTINE MUSICAL SYMBOL KONTEVMA;So;0;L;;;;;N;;;;;
-1D03B;BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION;So;0;L;;;;;N;;;;;
-1D03C;BYZANTINE MUSICAL SYMBOL RAPISMA;So;0;L;;;;;N;;;;;
-1D03D;BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION;So;0;L;;;;;N;;;;;
-1D03E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION;So;0;L;;;;;N;;;;;
-1D03F;BYZANTINE MUSICAL SYMBOL ICHADIN;So;0;L;;;;;N;;;;;
-1D040;BYZANTINE MUSICAL SYMBOL NANA;So;0;L;;;;;N;;;;;
-1D041;BYZANTINE MUSICAL SYMBOL PETASMA;So;0;L;;;;;N;;;;;
-1D042;BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO;So;0;L;;;;;N;;;;;
-1D043;BYZANTINE MUSICAL SYMBOL TROMIKON ALLO;So;0;L;;;;;N;;;;;
-1D044;BYZANTINE MUSICAL SYMBOL STRAGGISMATA;So;0;L;;;;;N;;;;;
-1D045;BYZANTINE MUSICAL SYMBOL GRONTHISMATA;So;0;L;;;;;N;;;;;
-1D046;BYZANTINE MUSICAL SYMBOL ISON NEO;So;0;L;;;;;N;;;;;
-1D047;BYZANTINE MUSICAL SYMBOL OLIGON NEO;So;0;L;;;;;N;;;;;
-1D048;BYZANTINE MUSICAL SYMBOL OXEIA NEO;So;0;L;;;;;N;;;;;
-1D049;BYZANTINE MUSICAL SYMBOL PETASTI;So;0;L;;;;;N;;;;;
-1D04A;BYZANTINE MUSICAL SYMBOL KOUFISMA;So;0;L;;;;;N;;;;;
-1D04B;BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA;So;0;L;;;;;N;;;;;
-1D04C;BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA;So;0;L;;;;;N;;;;;
-1D04D;BYZANTINE MUSICAL SYMBOL PELASTON NEO;So;0;L;;;;;N;;;;;
-1D04E;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO;So;0;L;;;;;N;;;;;
-1D04F;BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO;So;0;L;;;;;N;;;;;
-1D050;BYZANTINE MUSICAL SYMBOL YPSILI;So;0;L;;;;;N;;;;;
-1D051;BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO;So;0;L;;;;;N;;;;;
-1D052;BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO;So;0;L;;;;;N;;;;;
-1D053;BYZANTINE MUSICAL SYMBOL YPORROI;So;0;L;;;;;N;;;;;
-1D054;BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON;So;0;L;;;;;N;;;;;
-1D055;BYZANTINE MUSICAL SYMBOL ELAFRON;So;0;L;;;;;N;;;;;
-1D056;BYZANTINE MUSICAL SYMBOL CHAMILI;So;0;L;;;;;N;;;;;
-1D057;BYZANTINE MUSICAL SYMBOL MIKRON ISON;So;0;L;;;;;N;;;;;
-1D058;BYZANTINE MUSICAL SYMBOL VAREIA NEO;So;0;L;;;;;N;;;;;
-1D059;BYZANTINE MUSICAL SYMBOL PIASMA NEO;So;0;L;;;;;N;;;;;
-1D05A;BYZANTINE MUSICAL SYMBOL PSIFISTON NEO;So;0;L;;;;;N;;;;;
-1D05B;BYZANTINE MUSICAL SYMBOL OMALON;So;0;L;;;;;N;;;;;
-1D05C;BYZANTINE MUSICAL SYMBOL ANTIKENOMA;So;0;L;;;;;N;;;;;
-1D05D;BYZANTINE MUSICAL SYMBOL LYGISMA;So;0;L;;;;;N;;;;;
-1D05E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO;So;0;L;;;;;N;;;;;
-1D05F;BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO;So;0;L;;;;;N;;;;;
-1D060;BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA;So;0;L;;;;;N;;;;;
-1D061;BYZANTINE MUSICAL SYMBOL KYLISMA;So;0;L;;;;;N;;;;;
-1D062;BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA;So;0;L;;;;;N;;;;;
-1D063;BYZANTINE MUSICAL SYMBOL TROMIKON NEO;So;0;L;;;;;N;;;;;
-1D064;BYZANTINE MUSICAL SYMBOL EKSTREPTON;So;0;L;;;;;N;;;;;
-1D065;BYZANTINE MUSICAL SYMBOL SYNAGMA NEO;So;0;L;;;;;N;;;;;
-1D066;BYZANTINE MUSICAL SYMBOL SYRMA;So;0;L;;;;;N;;;;;
-1D067;BYZANTINE MUSICAL SYMBOL CHOREVMA NEO;So;0;L;;;;;N;;;;;
-1D068;BYZANTINE MUSICAL SYMBOL EPEGERMA;So;0;L;;;;;N;;;;;
-1D069;BYZANTINE MUSICAL SYMBOL SEISMA NEO;So;0;L;;;;;N;;;;;
-1D06A;BYZANTINE MUSICAL SYMBOL XIRON KLASMA;So;0;L;;;;;N;;;;;
-1D06B;BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON;So;0;L;;;;;N;;;;;
-1D06C;BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA;So;0;L;;;;;N;;;;;
-1D06D;BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA;So;0;L;;;;;N;;;;;
-1D06E;BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA;So;0;L;;;;;N;;;;;
-1D06F;BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA;So;0;L;;;;;N;;;;;
-1D070;BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA;So;0;L;;;;;N;;;;;
-1D071;BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA;So;0;L;;;;;N;;;;;
-1D072;BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON;So;0;L;;;;;N;;;;;
-1D073;BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON;So;0;L;;;;;N;;;;;
-1D074;BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON;So;0;L;;;;;N;;;;;
-1D075;BYZANTINE MUSICAL SYMBOL OYRANISMA NEO;So;0;L;;;;;N;;;;;
-1D076;BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO;So;0;L;;;;;N;;;;;
-1D077;BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO;So;0;L;;;;;N;;;;;
-1D078;BYZANTINE MUSICAL SYMBOL THEMA APLOUN;So;0;L;;;;;N;;;;;
-1D079;BYZANTINE MUSICAL SYMBOL THES KAI APOTHES;So;0;L;;;;;N;;;;;
-1D07A;BYZANTINE MUSICAL SYMBOL KATAVASMA;So;0;L;;;;;N;;;;;
-1D07B;BYZANTINE MUSICAL SYMBOL ENDOFONON;So;0;L;;;;;N;;;;;
-1D07C;BYZANTINE MUSICAL SYMBOL YFEN KATO;So;0;L;;;;;N;;;;;
-1D07D;BYZANTINE MUSICAL SYMBOL YFEN ANO;So;0;L;;;;;N;;;;;
-1D07E;BYZANTINE MUSICAL SYMBOL STAVROS;So;0;L;;;;;N;;;;;
-1D07F;BYZANTINE MUSICAL SYMBOL KLASMA ANO;So;0;L;;;;;N;;;;;
-1D080;BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION;So;0;L;;;;;N;;;;;
-1D081;BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION;So;0;L;;;;;N;;;;;
-1D082;BYZANTINE MUSICAL SYMBOL KRATIMA ALLO;So;0;L;;;;;N;;;;;
-1D083;BYZANTINE MUSICAL SYMBOL KRATIMA NEO;So;0;L;;;;;N;;;;;
-1D084;BYZANTINE MUSICAL SYMBOL APODERMA NEO;So;0;L;;;;;N;;;;;
-1D085;BYZANTINE MUSICAL SYMBOL APLI;So;0;L;;;;;N;;;;;
-1D086;BYZANTINE MUSICAL SYMBOL DIPLI;So;0;L;;;;;N;;;;;
-1D087;BYZANTINE MUSICAL SYMBOL TRIPLI;So;0;L;;;;;N;;;;;
-1D088;BYZANTINE MUSICAL SYMBOL TETRAPLI;So;0;L;;;;;N;;;;;
-1D089;BYZANTINE MUSICAL SYMBOL KORONIS;So;0;L;;;;;N;;;;;
-1D08A;BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU;So;0;L;;;;;N;;;;;
-1D08B;BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON;So;0;L;;;;;N;;;;;
-1D08C;BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON;So;0;L;;;;;N;;;;;
-1D08D;BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON;So;0;L;;;;;N;;;;;
-1D08E;BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU;So;0;L;;;;;N;;;;;
-1D08F;BYZANTINE MUSICAL SYMBOL GORGON NEO ANO;So;0;L;;;;;N;;;;;
-1D090;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA;So;0;L;;;;;N;;;;;
-1D091;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;;
-1D092;BYZANTINE MUSICAL SYMBOL DIGORGON;So;0;L;;;;;N;;;;;
-1D093;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO;So;0;L;;;;;N;;;;;
-1D094;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO;So;0;L;;;;;N;;;;;
-1D095;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;;
-1D096;BYZANTINE MUSICAL SYMBOL TRIGORGON;So;0;L;;;;;N;;;;;
-1D097;BYZANTINE MUSICAL SYMBOL ARGON;So;0;L;;;;;N;;;;;
-1D098;BYZANTINE MUSICAL SYMBOL IMIDIARGON;So;0;L;;;;;N;;;;;
-1D099;BYZANTINE MUSICAL SYMBOL DIARGON;So;0;L;;;;;N;;;;;
-1D09A;BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI;So;0;L;;;;;N;;;;;
-1D09B;BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI;So;0;L;;;;;N;;;;;
-1D09C;BYZANTINE MUSICAL SYMBOL AGOGI ARGI;So;0;L;;;;;N;;;;;
-1D09D;BYZANTINE MUSICAL SYMBOL AGOGI METRIA;So;0;L;;;;;N;;;;;
-1D09E;BYZANTINE MUSICAL SYMBOL AGOGI MESI;So;0;L;;;;;N;;;;;
-1D09F;BYZANTINE MUSICAL SYMBOL AGOGI GORGI;So;0;L;;;;;N;;;;;
-1D0A0;BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI;So;0;L;;;;;N;;;;;
-1D0A1;BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI;So;0;L;;;;;N;;;;;
-1D0A2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS;So;0;L;;;;;N;;;;;
-1D0A3;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS;So;0;L;;;;;N;;;;;
-1D0A4;BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS;So;0;L;;;;;N;;;;;
-1D0A5;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS;So;0;L;;;;;N;;;;;
-1D0A6;BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS;So;0;L;;;;;N;;;;;
-1D0A7;BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS;So;0;L;;;;;N;;;;;
-1D0A8;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS;So;0;L;;;;;N;;;;;
-1D0A9;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS;So;0;L;;;;;N;;;;;
-1D0AA;BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS;So;0;L;;;;;N;;;;;
-1D0AB;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS;So;0;L;;;;;N;;;;;
-1D0AC;BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS;So;0;L;;;;;N;;;;;
-1D0AD;BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS;So;0;L;;;;;N;;;;;
-1D0AE;BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS;So;0;L;;;;;N;;;;;
-1D0AF;BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS;So;0;L;;;;;N;;;;;
-1D0B0;BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS;So;0;L;;;;;N;;;;;
-1D0B1;BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS;So;0;L;;;;;N;;;;;
-1D0B2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS;So;0;L;;;;;N;;;;;
-1D0B3;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS;So;0;L;;;;;N;;;;;
-1D0B4;BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN;So;0;L;;;;;N;;;;;
-1D0B5;BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN;So;0;L;;;;;N;;;;;
-1D0B6;BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU;So;0;L;;;;;N;;;;;
-1D0B7;BYZANTINE MUSICAL SYMBOL IMIFONON;So;0;L;;;;;N;;;;;
-1D0B8;BYZANTINE MUSICAL SYMBOL IMIFTHORON;So;0;L;;;;;N;;;;;
-1D0B9;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU;So;0;L;;;;;N;;;;;
-1D0BA;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA;So;0;L;;;;;N;;;;;
-1D0BB;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA;So;0;L;;;;;N;;;;;
-1D0BC;BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS;So;0;L;;;;;N;;;;;
-1D0BD;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI;So;0;L;;;;;N;;;;;
-1D0BE;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI;So;0;L;;;;;N;;;;;
-1D0BF;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE;So;0;L;;;;;N;;;;;
-1D0C0;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO;So;0;L;;;;;N;;;;;
-1D0C1;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO;So;0;L;;;;;N;;;;;
-1D0C2;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO;So;0;L;;;;;N;;;;;
-1D0C3;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS;So;0;L;;;;;N;;;;;
-1D0C4;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS;So;0;L;;;;;N;;;;;
-1D0C5;BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS;So;0;L;;;;;N;;;;;
-1D0C6;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI;So;0;L;;;;;N;;;;;
-1D0C7;BYZANTINE MUSICAL SYMBOL FTHORA NENANO;So;0;L;;;;;N;;;;;
-1D0C8;BYZANTINE MUSICAL SYMBOL CHROA ZYGOS;So;0;L;;;;;N;;;;;
-1D0C9;BYZANTINE MUSICAL SYMBOL CHROA KLITON;So;0;L;;;;;N;;;;;
-1D0CA;BYZANTINE MUSICAL SYMBOL CHROA SPATHI;So;0;L;;;;;N;;;;;
-1D0CB;BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION;So;0;L;;;;;N;;;;;
-1D0CC;BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA;So;0;L;;;;;N;;;;;
-1D0CD;BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION;So;0;L;;;;;N;;;;;
-1D0CE;BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION;So;0;L;;;;;N;;;;;
-1D0CF;BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION;So;0;L;;;;;N;;;;;
-1D0D0;BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;;
-1D0D1;BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;;
-1D0D2;BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;;
-1D0D3;BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;;
-1D0D4;BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;;
-1D0D5;BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;;
-1D0D6;BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;;
-1D0D7;BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;;
-1D0D8;BYZANTINE MUSICAL SYMBOL GENIKI DIESIS;So;0;L;;;;;N;;;;;
-1D0D9;BYZANTINE MUSICAL SYMBOL GENIKI YFESIS;So;0;L;;;;;N;;;;;
-1D0DA;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI;So;0;L;;;;;N;;;;;
-1D0DB;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI;So;0;L;;;;;N;;;;;
-1D0DC;BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI;So;0;L;;;;;N;;;;;
-1D0DD;BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS;So;0;L;;;;;N;;;;;
-1D0DE;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS;So;0;L;;;;;N;;;;;
-1D0DF;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU;So;0;L;;;;;N;;;;;
-1D0E0;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU;So;0;L;;;;;N;;;;;
-1D0E1;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU;So;0;L;;;;;N;;;;;
-1D0E2;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS;So;0;L;;;;;N;;;;;
-1D0E3;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU;So;0;L;;;;;N;;;;;
-1D0E4;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU;So;0;L;;;;;N;;;;;
-1D0E5;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU;So;0;L;;;;;N;;;;;
-1D0E6;BYZANTINE MUSICAL SYMBOL DIGRAMMA GG;So;0;L;;;;;N;;;;;
-1D0E7;BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU;So;0;L;;;;;N;;;;;
-1D0E8;BYZANTINE MUSICAL SYMBOL STIGMA;So;0;L;;;;;N;;;;;
-1D0E9;BYZANTINE MUSICAL SYMBOL ARKTIKO PA;So;0;L;;;;;N;;;;;
-1D0EA;BYZANTINE MUSICAL SYMBOL ARKTIKO VOU;So;0;L;;;;;N;;;;;
-1D0EB;BYZANTINE MUSICAL SYMBOL ARKTIKO GA;So;0;L;;;;;N;;;;;
-1D0EC;BYZANTINE MUSICAL SYMBOL ARKTIKO DI;So;0;L;;;;;N;;;;;
-1D0ED;BYZANTINE MUSICAL SYMBOL ARKTIKO KE;So;0;L;;;;;N;;;;;
-1D0EE;BYZANTINE MUSICAL SYMBOL ARKTIKO ZO;So;0;L;;;;;N;;;;;
-1D0EF;BYZANTINE MUSICAL SYMBOL ARKTIKO NI;So;0;L;;;;;N;;;;;
-1D0F0;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO;So;0;L;;;;;N;;;;;
-1D0F1;BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO;So;0;L;;;;;N;;;;;
-1D0F2;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO;So;0;L;;;;;N;;;;;
-1D0F3;BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO;So;0;L;;;;;N;;;;;
-1D0F4;BYZANTINE MUSICAL SYMBOL KLASMA KATO;So;0;L;;;;;N;;;;;
-1D0F5;BYZANTINE MUSICAL SYMBOL GORGON NEO KATO;So;0;L;;;;;N;;;;;
-1D100;MUSICAL SYMBOL SINGLE BARLINE;So;0;L;;;;;N;;;;;
-1D101;MUSICAL SYMBOL DOUBLE BARLINE;So;0;L;;;;;N;;;;;
-1D102;MUSICAL SYMBOL FINAL BARLINE;So;0;L;;;;;N;;;;;
-1D103;MUSICAL SYMBOL REVERSE FINAL BARLINE;So;0;L;;;;;N;;;;;
-1D104;MUSICAL SYMBOL DASHED BARLINE;So;0;L;;;;;N;;;;;
-1D105;MUSICAL SYMBOL SHORT BARLINE;So;0;L;;;;;N;;;;;
-1D106;MUSICAL SYMBOL LEFT REPEAT SIGN;So;0;L;;;;;N;;;;;
-1D107;MUSICAL SYMBOL RIGHT REPEAT SIGN;So;0;L;;;;;N;;;;;
-1D108;MUSICAL SYMBOL REPEAT DOTS;So;0;L;;;;;N;;;;;
-1D109;MUSICAL SYMBOL DAL SEGNO;So;0;L;;;;;N;;;;;
-1D10A;MUSICAL SYMBOL DA CAPO;So;0;L;;;;;N;;;;;
-1D10B;MUSICAL SYMBOL SEGNO;So;0;L;;;;;N;;;;;
-1D10C;MUSICAL SYMBOL CODA;So;0;L;;;;;N;;;;;
-1D10D;MUSICAL SYMBOL REPEATED FIGURE-1;So;0;L;;;;;N;;;;;
-1D10E;MUSICAL SYMBOL REPEATED FIGURE-2;So;0;L;;;;;N;;;;;
-1D10F;MUSICAL SYMBOL REPEATED FIGURE-3;So;0;L;;;;;N;;;;;
-1D110;MUSICAL SYMBOL FERMATA;So;0;L;;;;;N;;;;;
-1D111;MUSICAL SYMBOL FERMATA BELOW;So;0;L;;;;;N;;;;;
-1D112;MUSICAL SYMBOL BREATH MARK;So;0;L;;;;;N;;;;;
-1D113;MUSICAL SYMBOL CAESURA;So;0;L;;;;;N;;;;;
-1D114;MUSICAL SYMBOL BRACE;So;0;L;;;;;N;;;;;
-1D115;MUSICAL SYMBOL BRACKET;So;0;L;;;;;N;;;;;
-1D116;MUSICAL SYMBOL ONE-LINE STAFF;So;0;L;;;;;N;;;;;
-1D117;MUSICAL SYMBOL TWO-LINE STAFF;So;0;L;;;;;N;;;;;
-1D118;MUSICAL SYMBOL THREE-LINE STAFF;So;0;L;;;;;N;;;;;
-1D119;MUSICAL SYMBOL FOUR-LINE STAFF;So;0;L;;;;;N;;;;;
-1D11A;MUSICAL SYMBOL FIVE-LINE STAFF;So;0;L;;;;;N;;;;;
-1D11B;MUSICAL SYMBOL SIX-LINE STAFF;So;0;L;;;;;N;;;;;
-1D11C;MUSICAL SYMBOL SIX-STRING FRETBOARD;So;0;L;;;;;N;;;;;
-1D11D;MUSICAL SYMBOL FOUR-STRING FRETBOARD;So;0;L;;;;;N;;;;;
-1D11E;MUSICAL SYMBOL G CLEF;So;0;L;;;;;N;;;;;
-1D11F;MUSICAL SYMBOL G CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;;
-1D120;MUSICAL SYMBOL G CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;;
-1D121;MUSICAL SYMBOL C CLEF;So;0;L;;;;;N;;;;;
-1D122;MUSICAL SYMBOL F CLEF;So;0;L;;;;;N;;;;;
-1D123;MUSICAL SYMBOL F CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;;
-1D124;MUSICAL SYMBOL F CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;;
-1D125;MUSICAL SYMBOL DRUM CLEF-1;So;0;L;;;;;N;;;;;
-1D126;MUSICAL SYMBOL DRUM CLEF-2;So;0;L;;;;;N;;;;;
-1D129;MUSICAL SYMBOL MULTIPLE MEASURE REST;So;0;L;;;;;N;;;;;
-1D12A;MUSICAL SYMBOL DOUBLE SHARP;So;0;L;;;;;N;;;;;
-1D12B;MUSICAL SYMBOL DOUBLE FLAT;So;0;L;;;;;N;;;;;
-1D12C;MUSICAL SYMBOL FLAT UP;So;0;L;;;;;N;;;;;
-1D12D;MUSICAL SYMBOL FLAT DOWN;So;0;L;;;;;N;;;;;
-1D12E;MUSICAL SYMBOL NATURAL UP;So;0;L;;;;;N;;;;;
-1D12F;MUSICAL SYMBOL NATURAL DOWN;So;0;L;;;;;N;;;;;
-1D130;MUSICAL SYMBOL SHARP UP;So;0;L;;;;;N;;;;;
-1D131;MUSICAL SYMBOL SHARP DOWN;So;0;L;;;;;N;;;;;
-1D132;MUSICAL SYMBOL QUARTER TONE SHARP;So;0;L;;;;;N;;;;;
-1D133;MUSICAL SYMBOL QUARTER TONE FLAT;So;0;L;;;;;N;;;;;
-1D134;MUSICAL SYMBOL COMMON TIME;So;0;L;;;;;N;;;;;
-1D135;MUSICAL SYMBOL CUT TIME;So;0;L;;;;;N;;;;;
-1D136;MUSICAL SYMBOL OTTAVA ALTA;So;0;L;;;;;N;;;;;
-1D137;MUSICAL SYMBOL OTTAVA BASSA;So;0;L;;;;;N;;;;;
-1D138;MUSICAL SYMBOL QUINDICESIMA ALTA;So;0;L;;;;;N;;;;;
-1D139;MUSICAL SYMBOL QUINDICESIMA BASSA;So;0;L;;;;;N;;;;;
-1D13A;MUSICAL SYMBOL MULTI REST;So;0;L;;;;;N;;;;;
-1D13B;MUSICAL SYMBOL WHOLE REST;So;0;L;;;;;N;;;;;
-1D13C;MUSICAL SYMBOL HALF REST;So;0;L;;;;;N;;;;;
-1D13D;MUSICAL SYMBOL QUARTER REST;So;0;L;;;;;N;;;;;
-1D13E;MUSICAL SYMBOL EIGHTH REST;So;0;L;;;;;N;;;;;
-1D13F;MUSICAL SYMBOL SIXTEENTH REST;So;0;L;;;;;N;;;;;
-1D140;MUSICAL SYMBOL THIRTY-SECOND REST;So;0;L;;;;;N;;;;;
-1D141;MUSICAL SYMBOL SIXTY-FOURTH REST;So;0;L;;;;;N;;;;;
-1D142;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST;So;0;L;;;;;N;;;;;
-1D143;MUSICAL SYMBOL X NOTEHEAD;So;0;L;;;;;N;;;;;
-1D144;MUSICAL SYMBOL PLUS NOTEHEAD;So;0;L;;;;;N;;;;;
-1D145;MUSICAL SYMBOL CIRCLE X NOTEHEAD;So;0;L;;;;;N;;;;;
-1D146;MUSICAL SYMBOL SQUARE NOTEHEAD WHITE;So;0;L;;;;;N;;;;;
-1D147;MUSICAL SYMBOL SQUARE NOTEHEAD BLACK;So;0;L;;;;;N;;;;;
-1D148;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE;So;0;L;;;;;N;;;;;
-1D149;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK;So;0;L;;;;;N;;;;;
-1D14A;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE;So;0;L;;;;;N;;;;;
-1D14B;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK;So;0;L;;;;;N;;;;;
-1D14C;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE;So;0;L;;;;;N;;;;;
-1D14D;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK;So;0;L;;;;;N;;;;;
-1D14E;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;;
-1D14F;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;;
-1D150;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE;So;0;L;;;;;N;;;;;
-1D151;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK;So;0;L;;;;;N;;;;;
-1D152;MUSICAL SYMBOL MOON NOTEHEAD WHITE;So;0;L;;;;;N;;;;;
-1D153;MUSICAL SYMBOL MOON NOTEHEAD BLACK;So;0;L;;;;;N;;;;;
-1D154;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;;
-1D155;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;;
-1D156;MUSICAL SYMBOL PARENTHESIS NOTEHEAD;So;0;L;;;;;N;;;;;
-1D157;MUSICAL SYMBOL VOID NOTEHEAD;So;0;L;;;;;N;;;;;
-1D158;MUSICAL SYMBOL NOTEHEAD BLACK;So;0;L;;;;;N;;;;;
-1D159;MUSICAL SYMBOL NULL NOTEHEAD;So;0;L;;;;;N;;;;;
-1D15A;MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE;So;0;L;;;;;N;;;;;
-1D15B;MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK;So;0;L;;;;;N;;;;;
-1D15C;MUSICAL SYMBOL BREVE;So;0;L;;;;;N;;;;;
-1D15D;MUSICAL SYMBOL WHOLE NOTE;So;0;L;;;;;N;;;;;
-1D15E;MUSICAL SYMBOL HALF NOTE;So;0;L;1D157 1D165;;;;N;;;;;
-1D15F;MUSICAL SYMBOL QUARTER NOTE;So;0;L;1D158 1D165;;;;N;;;;;
-1D160;MUSICAL SYMBOL EIGHTH NOTE;So;0;L;1D15F 1D16E;;;;N;;;;;
-1D161;MUSICAL SYMBOL SIXTEENTH NOTE;So;0;L;1D15F 1D16F;;;;N;;;;;
-1D162;MUSICAL SYMBOL THIRTY-SECOND NOTE;So;0;L;1D15F 1D170;;;;N;;;;;
-1D163;MUSICAL SYMBOL SIXTY-FOURTH NOTE;So;0;L;1D15F 1D171;;;;N;;;;;
-1D164;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE;So;0;L;1D15F 1D172;;;;N;;;;;
-1D165;MUSICAL SYMBOL COMBINING STEM;Mc;216;L;;;;;N;;;;;
-1D166;MUSICAL SYMBOL COMBINING SPRECHGESANG STEM;Mc;216;L;;;;;N;;;;;
-1D167;MUSICAL SYMBOL COMBINING TREMOLO-1;Mn;1;NSM;;;;;N;;;;;
-1D168;MUSICAL SYMBOL COMBINING TREMOLO-2;Mn;1;NSM;;;;;N;;;;;
-1D169;MUSICAL SYMBOL COMBINING TREMOLO-3;Mn;1;NSM;;;;;N;;;;;
-1D16A;MUSICAL SYMBOL FINGERED TREMOLO-1;So;0;L;;;;;N;;;;;
-1D16B;MUSICAL SYMBOL FINGERED TREMOLO-2;So;0;L;;;;;N;;;;;
-1D16C;MUSICAL SYMBOL FINGERED TREMOLO-3;So;0;L;;;;;N;;;;;
-1D16D;MUSICAL SYMBOL COMBINING AUGMENTATION DOT;Mc;226;L;;;;;N;;;;;
-1D16E;MUSICAL SYMBOL COMBINING FLAG-1;Mc;216;L;;;;;N;;;;;
-1D16F;MUSICAL SYMBOL COMBINING FLAG-2;Mc;216;L;;;;;N;;;;;
-1D170;MUSICAL SYMBOL COMBINING FLAG-3;Mc;216;L;;;;;N;;;;;
-1D171;MUSICAL SYMBOL COMBINING FLAG-4;Mc;216;L;;;;;N;;;;;
-1D172;MUSICAL SYMBOL COMBINING FLAG-5;Mc;216;L;;;;;N;;;;;
-1D173;MUSICAL SYMBOL BEGIN BEAM;Cf;0;BN;;;;;N;;;;;
-1D174;MUSICAL SYMBOL END BEAM;Cf;0;BN;;;;;N;;;;;
-1D175;MUSICAL SYMBOL BEGIN TIE;Cf;0;BN;;;;;N;;;;;
-1D176;MUSICAL SYMBOL END TIE;Cf;0;BN;;;;;N;;;;;
-1D177;MUSICAL SYMBOL BEGIN SLUR;Cf;0;BN;;;;;N;;;;;
-1D178;MUSICAL SYMBOL END SLUR;Cf;0;BN;;;;;N;;;;;
-1D179;MUSICAL SYMBOL BEGIN PHRASE;Cf;0;BN;;;;;N;;;;;
-1D17A;MUSICAL SYMBOL END PHRASE;Cf;0;BN;;;;;N;;;;;
-1D17B;MUSICAL SYMBOL COMBINING ACCENT;Mn;220;NSM;;;;;N;;;;;
-1D17C;MUSICAL SYMBOL COMBINING STACCATO;Mn;220;NSM;;;;;N;;;;;
-1D17D;MUSICAL SYMBOL COMBINING TENUTO;Mn;220;NSM;;;;;N;;;;;
-1D17E;MUSICAL SYMBOL COMBINING STACCATISSIMO;Mn;220;NSM;;;;;N;;;;;
-1D17F;MUSICAL SYMBOL COMBINING MARCATO;Mn;220;NSM;;;;;N;;;;;
-1D180;MUSICAL SYMBOL COMBINING MARCATO-STACCATO;Mn;220;NSM;;;;;N;;;;;
-1D181;MUSICAL SYMBOL COMBINING ACCENT-STACCATO;Mn;220;NSM;;;;;N;;;;;
-1D182;MUSICAL SYMBOL COMBINING LOURE;Mn;220;NSM;;;;;N;;;;;
-1D183;MUSICAL SYMBOL ARPEGGIATO UP;So;0;L;;;;;N;;;;;
-1D184;MUSICAL SYMBOL ARPEGGIATO DOWN;So;0;L;;;;;N;;;;;
-1D185;MUSICAL SYMBOL COMBINING DOIT;Mn;230;NSM;;;;;N;;;;;
-1D186;MUSICAL SYMBOL COMBINING RIP;Mn;230;NSM;;;;;N;;;;;
-1D187;MUSICAL SYMBOL COMBINING FLIP;Mn;230;NSM;;;;;N;;;;;
-1D188;MUSICAL SYMBOL COMBINING SMEAR;Mn;230;NSM;;;;;N;;;;;
-1D189;MUSICAL SYMBOL COMBINING BEND;Mn;230;NSM;;;;;N;;;;;
-1D18A;MUSICAL SYMBOL COMBINING DOUBLE TONGUE;Mn;220;NSM;;;;;N;;;;;
-1D18B;MUSICAL SYMBOL COMBINING TRIPLE TONGUE;Mn;220;NSM;;;;;N;;;;;
-1D18C;MUSICAL SYMBOL RINFORZANDO;So;0;L;;;;;N;;;;;
-1D18D;MUSICAL SYMBOL SUBITO;So;0;L;;;;;N;;;;;
-1D18E;MUSICAL SYMBOL Z;So;0;L;;;;;N;;;;;
-1D18F;MUSICAL SYMBOL PIANO;So;0;L;;;;;N;;;;;
-1D190;MUSICAL SYMBOL MEZZO;So;0;L;;;;;N;;;;;
-1D191;MUSICAL SYMBOL FORTE;So;0;L;;;;;N;;;;;
-1D192;MUSICAL SYMBOL CRESCENDO;So;0;L;;;;;N;;;;;
-1D193;MUSICAL SYMBOL DECRESCENDO;So;0;L;;;;;N;;;;;
-1D194;MUSICAL SYMBOL GRACE NOTE SLASH;So;0;L;;;;;N;;;;;
-1D195;MUSICAL SYMBOL GRACE NOTE NO SLASH;So;0;L;;;;;N;;;;;
-1D196;MUSICAL SYMBOL TR;So;0;L;;;;;N;;;;;
-1D197;MUSICAL SYMBOL TURN;So;0;L;;;;;N;;;;;
-1D198;MUSICAL SYMBOL INVERTED TURN;So;0;L;;;;;N;;;;;
-1D199;MUSICAL SYMBOL TURN SLASH;So;0;L;;;;;N;;;;;
-1D19A;MUSICAL SYMBOL TURN UP;So;0;L;;;;;N;;;;;
-1D19B;MUSICAL SYMBOL ORNAMENT STROKE-1;So;0;L;;;;;N;;;;;
-1D19C;MUSICAL SYMBOL ORNAMENT STROKE-2;So;0;L;;;;;N;;;;;
-1D19D;MUSICAL SYMBOL ORNAMENT STROKE-3;So;0;L;;;;;N;;;;;
-1D19E;MUSICAL SYMBOL ORNAMENT STROKE-4;So;0;L;;;;;N;;;;;
-1D19F;MUSICAL SYMBOL ORNAMENT STROKE-5;So;0;L;;;;;N;;;;;
-1D1A0;MUSICAL SYMBOL ORNAMENT STROKE-6;So;0;L;;;;;N;;;;;
-1D1A1;MUSICAL SYMBOL ORNAMENT STROKE-7;So;0;L;;;;;N;;;;;
-1D1A2;MUSICAL SYMBOL ORNAMENT STROKE-8;So;0;L;;;;;N;;;;;
-1D1A3;MUSICAL SYMBOL ORNAMENT STROKE-9;So;0;L;;;;;N;;;;;
-1D1A4;MUSICAL SYMBOL ORNAMENT STROKE-10;So;0;L;;;;;N;;;;;
-1D1A5;MUSICAL SYMBOL ORNAMENT STROKE-11;So;0;L;;;;;N;;;;;
-1D1A6;MUSICAL SYMBOL HAUPTSTIMME;So;0;L;;;;;N;;;;;
-1D1A7;MUSICAL SYMBOL NEBENSTIMME;So;0;L;;;;;N;;;;;
-1D1A8;MUSICAL SYMBOL END OF STIMME;So;0;L;;;;;N;;;;;
-1D1A9;MUSICAL SYMBOL DEGREE SLASH;So;0;L;;;;;N;;;;;
-1D1AA;MUSICAL SYMBOL COMBINING DOWN BOW;Mn;230;NSM;;;;;N;;;;;
-1D1AB;MUSICAL SYMBOL COMBINING UP BOW;Mn;230;NSM;;;;;N;;;;;
-1D1AC;MUSICAL SYMBOL COMBINING HARMONIC;Mn;230;NSM;;;;;N;;;;;
-1D1AD;MUSICAL SYMBOL COMBINING SNAP PIZZICATO;Mn;230;NSM;;;;;N;;;;;
-1D1AE;MUSICAL SYMBOL PEDAL MARK;So;0;L;;;;;N;;;;;
-1D1AF;MUSICAL SYMBOL PEDAL UP MARK;So;0;L;;;;;N;;;;;
-1D1B0;MUSICAL SYMBOL HALF PEDAL MARK;So;0;L;;;;;N;;;;;
-1D1B1;MUSICAL SYMBOL GLISSANDO UP;So;0;L;;;;;N;;;;;
-1D1B2;MUSICAL SYMBOL GLISSANDO DOWN;So;0;L;;;;;N;;;;;
-1D1B3;MUSICAL SYMBOL WITH FINGERNAILS;So;0;L;;;;;N;;;;;
-1D1B4;MUSICAL SYMBOL DAMP;So;0;L;;;;;N;;;;;
-1D1B5;MUSICAL SYMBOL DAMP ALL;So;0;L;;;;;N;;;;;
-1D1B6;MUSICAL SYMBOL MAXIMA;So;0;L;;;;;N;;;;;
-1D1B7;MUSICAL SYMBOL LONGA;So;0;L;;;;;N;;;;;
-1D1B8;MUSICAL SYMBOL BREVIS;So;0;L;;;;;N;;;;;
-1D1B9;MUSICAL SYMBOL SEMIBREVIS WHITE;So;0;L;;;;;N;;;;;
-1D1BA;MUSICAL SYMBOL SEMIBREVIS BLACK;So;0;L;;;;;N;;;;;
-1D1BB;MUSICAL SYMBOL MINIMA;So;0;L;1D1B9 1D165;;;;N;;;;;
-1D1BC;MUSICAL SYMBOL MINIMA BLACK;So;0;L;1D1BA 1D165;;;;N;;;;;
-1D1BD;MUSICAL SYMBOL SEMIMINIMA WHITE;So;0;L;1D1BB 1D16E;;;;N;;;;;
-1D1BE;MUSICAL SYMBOL SEMIMINIMA BLACK;So;0;L;1D1BC 1D16E;;;;N;;;;;
-1D1BF;MUSICAL SYMBOL FUSA WHITE;So;0;L;1D1BB 1D16F;;;;N;;;;;
-1D1C0;MUSICAL SYMBOL FUSA BLACK;So;0;L;1D1BC 1D16F;;;;N;;;;;
-1D1C1;MUSICAL SYMBOL LONGA PERFECTA REST;So;0;L;;;;;N;;;;;
-1D1C2;MUSICAL SYMBOL LONGA IMPERFECTA REST;So;0;L;;;;;N;;;;;
-1D1C3;MUSICAL SYMBOL BREVIS REST;So;0;L;;;;;N;;;;;
-1D1C4;MUSICAL SYMBOL SEMIBREVIS REST;So;0;L;;;;;N;;;;;
-1D1C5;MUSICAL SYMBOL MINIMA REST;So;0;L;;;;;N;;;;;
-1D1C6;MUSICAL SYMBOL SEMIMINIMA REST;So;0;L;;;;;N;;;;;
-1D1C7;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;;
-1D1C8;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;;
-1D1C9;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;;
-1D1CA;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;;
-1D1CB;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;;
-1D1CC;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;;
-1D1CD;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2;So;0;L;;;;;N;;;;;
-1D1CE;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3;So;0;L;;;;;N;;;;;
-1D1CF;MUSICAL SYMBOL CROIX;So;0;L;;;;;N;;;;;
-1D1D0;MUSICAL SYMBOL GREGORIAN C CLEF;So;0;L;;;;;N;;;;;
-1D1D1;MUSICAL SYMBOL GREGORIAN F CLEF;So;0;L;;;;;N;;;;;
-1D1D2;MUSICAL SYMBOL SQUARE B;So;0;L;;;;;N;;;;;
-1D1D3;MUSICAL SYMBOL VIRGA;So;0;L;;;;;N;;;;;
-1D1D4;MUSICAL SYMBOL PODATUS;So;0;L;;;;;N;;;;;
-1D1D5;MUSICAL SYMBOL CLIVIS;So;0;L;;;;;N;;;;;
-1D1D6;MUSICAL SYMBOL SCANDICUS;So;0;L;;;;;N;;;;;
-1D1D7;MUSICAL SYMBOL CLIMACUS;So;0;L;;;;;N;;;;;
-1D1D8;MUSICAL SYMBOL TORCULUS;So;0;L;;;;;N;;;;;
-1D1D9;MUSICAL SYMBOL PORRECTUS;So;0;L;;;;;N;;;;;
-1D1DA;MUSICAL SYMBOL PORRECTUS FLEXUS;So;0;L;;;;;N;;;;;
-1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;;
-1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;;
-1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;;
-1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;;
-1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;;
-1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;;
-1D203;GREEK VOCAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;;
-1D204;GREEK VOCAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;;
-1D205;GREEK VOCAL NOTATION SYMBOL-6;So;0;ON;;;;;N;;;;;
-1D206;GREEK VOCAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;;
-1D207;GREEK VOCAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;;
-1D208;GREEK VOCAL NOTATION SYMBOL-9;So;0;ON;;;;;N;;;;;
-1D209;GREEK VOCAL NOTATION SYMBOL-10;So;0;ON;;;;;N;;;;;
-1D20A;GREEK VOCAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;;
-1D20B;GREEK VOCAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;;
-1D20C;GREEK VOCAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;;
-1D20D;GREEK VOCAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;;
-1D20E;GREEK VOCAL NOTATION SYMBOL-15;So;0;ON;;;;;N;;;;;
-1D20F;GREEK VOCAL NOTATION SYMBOL-16;So;0;ON;;;;;N;;;;;
-1D210;GREEK VOCAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;;
-1D211;GREEK VOCAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;;
-1D212;GREEK VOCAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;;
-1D213;GREEK VOCAL NOTATION SYMBOL-20;So;0;ON;;;;;N;;;;;
-1D214;GREEK VOCAL NOTATION SYMBOL-21;So;0;ON;;;;;N;;;;;
-1D215;GREEK VOCAL NOTATION SYMBOL-22;So;0;ON;;;;;N;;;;;
-1D216;GREEK VOCAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;;
-1D217;GREEK VOCAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;;
-1D218;GREEK VOCAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;;
-1D219;GREEK VOCAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;;
-1D21A;GREEK VOCAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;;
-1D21B;GREEK VOCAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;;
-1D21C;GREEK VOCAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;;
-1D21D;GREEK INSTRUMENTAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;;
-1D21E;GREEK INSTRUMENTAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;;
-1D21F;GREEK INSTRUMENTAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;;
-1D220;GREEK INSTRUMENTAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;;
-1D221;GREEK INSTRUMENTAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;;
-1D222;GREEK INSTRUMENTAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;;
-1D223;GREEK INSTRUMENTAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;;
-1D224;GREEK INSTRUMENTAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;;
-1D225;GREEK INSTRUMENTAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;;
-1D226;GREEK INSTRUMENTAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;;
-1D227;GREEK INSTRUMENTAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;;
-1D228;GREEK INSTRUMENTAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;;
-1D229;GREEK INSTRUMENTAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;;
-1D22A;GREEK INSTRUMENTAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;;
-1D22B;GREEK INSTRUMENTAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;;
-1D22C;GREEK INSTRUMENTAL NOTATION SYMBOL-25;So;0;ON;;;;;N;;;;;
-1D22D;GREEK INSTRUMENTAL NOTATION SYMBOL-26;So;0;ON;;;;;N;;;;;
-1D22E;GREEK INSTRUMENTAL NOTATION SYMBOL-27;So;0;ON;;;;;N;;;;;
-1D22F;GREEK INSTRUMENTAL NOTATION SYMBOL-29;So;0;ON;;;;;N;;;;;
-1D230;GREEK INSTRUMENTAL NOTATION SYMBOL-30;So;0;ON;;;;;N;;;;;
-1D231;GREEK INSTRUMENTAL NOTATION SYMBOL-32;So;0;ON;;;;;N;;;;;
-1D232;GREEK INSTRUMENTAL NOTATION SYMBOL-36;So;0;ON;;;;;N;;;;;
-1D233;GREEK INSTRUMENTAL NOTATION SYMBOL-37;So;0;ON;;;;;N;;;;;
-1D234;GREEK INSTRUMENTAL NOTATION SYMBOL-38;So;0;ON;;;;;N;;;;;
-1D235;GREEK INSTRUMENTAL NOTATION SYMBOL-39;So;0;ON;;;;;N;;;;;
-1D236;GREEK INSTRUMENTAL NOTATION SYMBOL-40;So;0;ON;;;;;N;;;;;
-1D237;GREEK INSTRUMENTAL NOTATION SYMBOL-42;So;0;ON;;;;;N;;;;;
-1D238;GREEK INSTRUMENTAL NOTATION SYMBOL-43;So;0;ON;;;;;N;;;;;
-1D239;GREEK INSTRUMENTAL NOTATION SYMBOL-45;So;0;ON;;;;;N;;;;;
-1D23A;GREEK INSTRUMENTAL NOTATION SYMBOL-47;So;0;ON;;;;;N;;;;;
-1D23B;GREEK INSTRUMENTAL NOTATION SYMBOL-48;So;0;ON;;;;;N;;;;;
-1D23C;GREEK INSTRUMENTAL NOTATION SYMBOL-49;So;0;ON;;;;;N;;;;;
-1D23D;GREEK INSTRUMENTAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;;
-1D23E;GREEK INSTRUMENTAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;;
-1D23F;GREEK INSTRUMENTAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;;
-1D240;GREEK INSTRUMENTAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;;
-1D241;GREEK INSTRUMENTAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;;
-1D242;COMBINING GREEK MUSICAL TRISEME;Mn;230;NSM;;;;;N;;;;;
-1D243;COMBINING GREEK MUSICAL TETRASEME;Mn;230;NSM;;;;;N;;;;;
-1D244;COMBINING GREEK MUSICAL PENTASEME;Mn;230;NSM;;;;;N;;;;;
-1D245;GREEK MUSICAL LEIMMA;So;0;ON;;;;;N;;;;;
-1D300;MONOGRAM FOR EARTH;So;0;ON;;;;;N;;;;;
-1D301;DIGRAM FOR HEAVENLY EARTH;So;0;ON;;;;;N;;;;;
-1D302;DIGRAM FOR HUMAN EARTH;So;0;ON;;;;;N;;;;;
-1D303;DIGRAM FOR EARTHLY HEAVEN;So;0;ON;;;;;N;;;;;
-1D304;DIGRAM FOR EARTHLY HUMAN;So;0;ON;;;;;N;;;;;
-1D305;DIGRAM FOR EARTH;So;0;ON;;;;;N;;;;;
-1D306;TETRAGRAM FOR CENTRE;So;0;ON;;;;;N;;;;;
-1D307;TETRAGRAM FOR FULL CIRCLE;So;0;ON;;;;;N;;;;;
-1D308;TETRAGRAM FOR MIRED;So;0;ON;;;;;N;;;;;
-1D309;TETRAGRAM FOR BARRIER;So;0;ON;;;;;N;;;;;
-1D30A;TETRAGRAM FOR KEEPING SMALL;So;0;ON;;;;;N;;;;;
-1D30B;TETRAGRAM FOR CONTRARIETY;So;0;ON;;;;;N;;;;;
-1D30C;TETRAGRAM FOR ASCENT;So;0;ON;;;;;N;;;;;
-1D30D;TETRAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;;
-1D30E;TETRAGRAM FOR BRANCHING OUT;So;0;ON;;;;;N;;;;;
-1D30F;TETRAGRAM FOR DEFECTIVENESS OR DISTORTION;So;0;ON;;;;;N;;;;;
-1D310;TETRAGRAM FOR DIVERGENCE;So;0;ON;;;;;N;;;;;
-1D311;TETRAGRAM FOR YOUTHFULNESS;So;0;ON;;;;;N;;;;;
-1D312;TETRAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;;
-1D313;TETRAGRAM FOR PENETRATION;So;0;ON;;;;;N;;;;;
-1D314;TETRAGRAM FOR REACH;So;0;ON;;;;;N;;;;;
-1D315;TETRAGRAM FOR CONTACT;So;0;ON;;;;;N;;;;;
-1D316;TETRAGRAM FOR HOLDING BACK;So;0;ON;;;;;N;;;;;
-1D317;TETRAGRAM FOR WAITING;So;0;ON;;;;;N;;;;;
-1D318;TETRAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;;
-1D319;TETRAGRAM FOR ADVANCE;So;0;ON;;;;;N;;;;;
-1D31A;TETRAGRAM FOR RELEASE;So;0;ON;;;;;N;;;;;
-1D31B;TETRAGRAM FOR RESISTANCE;So;0;ON;;;;;N;;;;;
-1D31C;TETRAGRAM FOR EASE;So;0;ON;;;;;N;;;;;
-1D31D;TETRAGRAM FOR JOY;So;0;ON;;;;;N;;;;;
-1D31E;TETRAGRAM FOR CONTENTION;So;0;ON;;;;;N;;;;;
-1D31F;TETRAGRAM FOR ENDEAVOUR;So;0;ON;;;;;N;;;;;
-1D320;TETRAGRAM FOR DUTIES;So;0;ON;;;;;N;;;;;
-1D321;TETRAGRAM FOR CHANGE;So;0;ON;;;;;N;;;;;
-1D322;TETRAGRAM FOR DECISIVENESS;So;0;ON;;;;;N;;;;;
-1D323;TETRAGRAM FOR BOLD RESOLUTION;So;0;ON;;;;;N;;;;;
-1D324;TETRAGRAM FOR PACKING;So;0;ON;;;;;N;;;;;
-1D325;TETRAGRAM FOR LEGION;So;0;ON;;;;;N;;;;;
-1D326;TETRAGRAM FOR CLOSENESS;So;0;ON;;;;;N;;;;;
-1D327;TETRAGRAM FOR KINSHIP;So;0;ON;;;;;N;;;;;
-1D328;TETRAGRAM FOR GATHERING;So;0;ON;;;;;N;;;;;
-1D329;TETRAGRAM FOR STRENGTH;So;0;ON;;;;;N;;;;;
-1D32A;TETRAGRAM FOR PURITY;So;0;ON;;;;;N;;;;;
-1D32B;TETRAGRAM FOR FULLNESS;So;0;ON;;;;;N;;;;;
-1D32C;TETRAGRAM FOR RESIDENCE;So;0;ON;;;;;N;;;;;
-1D32D;TETRAGRAM FOR LAW OR MODEL;So;0;ON;;;;;N;;;;;
-1D32E;TETRAGRAM FOR RESPONSE;So;0;ON;;;;;N;;;;;
-1D32F;TETRAGRAM FOR GOING TO MEET;So;0;ON;;;;;N;;;;;
-1D330;TETRAGRAM FOR ENCOUNTERS;So;0;ON;;;;;N;;;;;
-1D331;TETRAGRAM FOR STOVE;So;0;ON;;;;;N;;;;;
-1D332;TETRAGRAM FOR GREATNESS;So;0;ON;;;;;N;;;;;
-1D333;TETRAGRAM FOR ENLARGEMENT;So;0;ON;;;;;N;;;;;
-1D334;TETRAGRAM FOR PATTERN;So;0;ON;;;;;N;;;;;
-1D335;TETRAGRAM FOR RITUAL;So;0;ON;;;;;N;;;;;
-1D336;TETRAGRAM FOR FLIGHT;So;0;ON;;;;;N;;;;;
-1D337;TETRAGRAM FOR VASTNESS OR WASTING;So;0;ON;;;;;N;;;;;
-1D338;TETRAGRAM FOR CONSTANCY;So;0;ON;;;;;N;;;;;
-1D339;TETRAGRAM FOR MEASURE;So;0;ON;;;;;N;;;;;
-1D33A;TETRAGRAM FOR ETERNITY;So;0;ON;;;;;N;;;;;
-1D33B;TETRAGRAM FOR UNITY;So;0;ON;;;;;N;;;;;
-1D33C;TETRAGRAM FOR DIMINISHMENT;So;0;ON;;;;;N;;;;;
-1D33D;TETRAGRAM FOR CLOSED MOUTH;So;0;ON;;;;;N;;;;;
-1D33E;TETRAGRAM FOR GUARDEDNESS;So;0;ON;;;;;N;;;;;
-1D33F;TETRAGRAM FOR GATHERING IN;So;0;ON;;;;;N;;;;;
-1D340;TETRAGRAM FOR MASSING;So;0;ON;;;;;N;;;;;
-1D341;TETRAGRAM FOR ACCUMULATION;So;0;ON;;;;;N;;;;;
-1D342;TETRAGRAM FOR EMBELLISHMENT;So;0;ON;;;;;N;;;;;
-1D343;TETRAGRAM FOR DOUBT;So;0;ON;;;;;N;;;;;
-1D344;TETRAGRAM FOR WATCH;So;0;ON;;;;;N;;;;;
-1D345;TETRAGRAM FOR SINKING;So;0;ON;;;;;N;;;;;
-1D346;TETRAGRAM FOR INNER;So;0;ON;;;;;N;;;;;
-1D347;TETRAGRAM FOR DEPARTURE;So;0;ON;;;;;N;;;;;
-1D348;TETRAGRAM FOR DARKENING;So;0;ON;;;;;N;;;;;
-1D349;TETRAGRAM FOR DIMMING;So;0;ON;;;;;N;;;;;
-1D34A;TETRAGRAM FOR EXHAUSTION;So;0;ON;;;;;N;;;;;
-1D34B;TETRAGRAM FOR SEVERANCE;So;0;ON;;;;;N;;;;;
-1D34C;TETRAGRAM FOR STOPPAGE;So;0;ON;;;;;N;;;;;
-1D34D;TETRAGRAM FOR HARDNESS;So;0;ON;;;;;N;;;;;
-1D34E;TETRAGRAM FOR COMPLETION;So;0;ON;;;;;N;;;;;
-1D34F;TETRAGRAM FOR CLOSURE;So;0;ON;;;;;N;;;;;
-1D350;TETRAGRAM FOR FAILURE;So;0;ON;;;;;N;;;;;
-1D351;TETRAGRAM FOR AGGRAVATION;So;0;ON;;;;;N;;;;;
-1D352;TETRAGRAM FOR COMPLIANCE;So;0;ON;;;;;N;;;;;
-1D353;TETRAGRAM FOR ON THE VERGE;So;0;ON;;;;;N;;;;;
-1D354;TETRAGRAM FOR DIFFICULTIES;So;0;ON;;;;;N;;;;;
-1D355;TETRAGRAM FOR LABOURING;So;0;ON;;;;;N;;;;;
-1D356;TETRAGRAM FOR FOSTERING;So;0;ON;;;;;N;;;;;
-1D360;COUNTING ROD UNIT DIGIT ONE;No;0;L;;;;1;N;;;;;
-1D361;COUNTING ROD UNIT DIGIT TWO;No;0;L;;;;2;N;;;;;
-1D362;COUNTING ROD UNIT DIGIT THREE;No;0;L;;;;3;N;;;;;
-1D363;COUNTING ROD UNIT DIGIT FOUR;No;0;L;;;;4;N;;;;;
-1D364;COUNTING ROD UNIT DIGIT FIVE;No;0;L;;;;5;N;;;;;
-1D365;COUNTING ROD UNIT DIGIT SIX;No;0;L;;;;6;N;;;;;
-1D366;COUNTING ROD UNIT DIGIT SEVEN;No;0;L;;;;7;N;;;;;
-1D367;COUNTING ROD UNIT DIGIT EIGHT;No;0;L;;;;8;N;;;;;
-1D368;COUNTING ROD UNIT DIGIT NINE;No;0;L;;;;9;N;;;;;
-1D369;COUNTING ROD TENS DIGIT ONE;No;0;L;;;;10;N;;;;;
-1D36A;COUNTING ROD TENS DIGIT TWO;No;0;L;;;;20;N;;;;;
-1D36B;COUNTING ROD TENS DIGIT THREE;No;0;L;;;;30;N;;;;;
-1D36C;COUNTING ROD TENS DIGIT FOUR;No;0;L;;;;40;N;;;;;
-1D36D;COUNTING ROD TENS DIGIT FIVE;No;0;L;;;;50;N;;;;;
-1D36E;COUNTING ROD TENS DIGIT SIX;No;0;L;;;;60;N;;;;;
-1D36F;COUNTING ROD TENS DIGIT SEVEN;No;0;L;;;;70;N;;;;;
-1D370;COUNTING ROD TENS DIGIT EIGHT;No;0;L;;;;80;N;;;;;
-1D371;COUNTING ROD TENS DIGIT NINE;No;0;L;;;;90;N;;;;;
-1D400;MATHEMATICAL BOLD CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D401;MATHEMATICAL BOLD CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D402;MATHEMATICAL BOLD CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D403;MATHEMATICAL BOLD CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D404;MATHEMATICAL BOLD CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D405;MATHEMATICAL BOLD CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D406;MATHEMATICAL BOLD CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D407;MATHEMATICAL BOLD CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D408;MATHEMATICAL BOLD CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D409;MATHEMATICAL BOLD CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D40A;MATHEMATICAL BOLD CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D40B;MATHEMATICAL BOLD CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D40C;MATHEMATICAL BOLD CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D40D;MATHEMATICAL BOLD CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D40E;MATHEMATICAL BOLD CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D40F;MATHEMATICAL BOLD CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D410;MATHEMATICAL BOLD CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D411;MATHEMATICAL BOLD CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D412;MATHEMATICAL BOLD CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D413;MATHEMATICAL BOLD CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D414;MATHEMATICAL BOLD CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D415;MATHEMATICAL BOLD CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D416;MATHEMATICAL BOLD CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D417;MATHEMATICAL BOLD CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D418;MATHEMATICAL BOLD CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D419;MATHEMATICAL BOLD CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D41A;MATHEMATICAL BOLD SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D41B;MATHEMATICAL BOLD SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D41C;MATHEMATICAL BOLD SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D41D;MATHEMATICAL BOLD SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D41E;MATHEMATICAL BOLD SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D41F;MATHEMATICAL BOLD SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D420;MATHEMATICAL BOLD SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D421;MATHEMATICAL BOLD SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D422;MATHEMATICAL BOLD SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D423;MATHEMATICAL BOLD SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D424;MATHEMATICAL BOLD SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D425;MATHEMATICAL BOLD SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D426;MATHEMATICAL BOLD SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D427;MATHEMATICAL BOLD SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D428;MATHEMATICAL BOLD SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D429;MATHEMATICAL BOLD SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D42A;MATHEMATICAL BOLD SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D42B;MATHEMATICAL BOLD SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D42C;MATHEMATICAL BOLD SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D42D;MATHEMATICAL BOLD SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D42E;MATHEMATICAL BOLD SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D42F;MATHEMATICAL BOLD SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D430;MATHEMATICAL BOLD SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D431;MATHEMATICAL BOLD SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D432;MATHEMATICAL BOLD SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D433;MATHEMATICAL BOLD SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D434;MATHEMATICAL ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D435;MATHEMATICAL ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D436;MATHEMATICAL ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D437;MATHEMATICAL ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D438;MATHEMATICAL ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D439;MATHEMATICAL ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D43A;MATHEMATICAL ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D43B;MATHEMATICAL ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D43C;MATHEMATICAL ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D43D;MATHEMATICAL ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D43E;MATHEMATICAL ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D43F;MATHEMATICAL ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D440;MATHEMATICAL ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D441;MATHEMATICAL ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D442;MATHEMATICAL ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D443;MATHEMATICAL ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D444;MATHEMATICAL ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D445;MATHEMATICAL ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D446;MATHEMATICAL ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D447;MATHEMATICAL ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D448;MATHEMATICAL ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D449;MATHEMATICAL ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D44A;MATHEMATICAL ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D44B;MATHEMATICAL ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D44C;MATHEMATICAL ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D44D;MATHEMATICAL ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D44E;MATHEMATICAL ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D44F;MATHEMATICAL ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D450;MATHEMATICAL ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D451;MATHEMATICAL ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D452;MATHEMATICAL ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D453;MATHEMATICAL ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D454;MATHEMATICAL ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D456;MATHEMATICAL ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D457;MATHEMATICAL ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D458;MATHEMATICAL ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D459;MATHEMATICAL ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D45A;MATHEMATICAL ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D45B;MATHEMATICAL ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D45C;MATHEMATICAL ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D45D;MATHEMATICAL ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D45E;MATHEMATICAL ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D45F;MATHEMATICAL ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D460;MATHEMATICAL ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D461;MATHEMATICAL ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D462;MATHEMATICAL ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D463;MATHEMATICAL ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D464;MATHEMATICAL ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D465;MATHEMATICAL ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D466;MATHEMATICAL ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D467;MATHEMATICAL ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D468;MATHEMATICAL BOLD ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D469;MATHEMATICAL BOLD ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D46A;MATHEMATICAL BOLD ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D46B;MATHEMATICAL BOLD ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D46C;MATHEMATICAL BOLD ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D46D;MATHEMATICAL BOLD ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D46E;MATHEMATICAL BOLD ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D46F;MATHEMATICAL BOLD ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D470;MATHEMATICAL BOLD ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D471;MATHEMATICAL BOLD ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D472;MATHEMATICAL BOLD ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D473;MATHEMATICAL BOLD ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D474;MATHEMATICAL BOLD ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D475;MATHEMATICAL BOLD ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D476;MATHEMATICAL BOLD ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D477;MATHEMATICAL BOLD ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D478;MATHEMATICAL BOLD ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D479;MATHEMATICAL BOLD ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D47A;MATHEMATICAL BOLD ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D47B;MATHEMATICAL BOLD ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D47C;MATHEMATICAL BOLD ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D47D;MATHEMATICAL BOLD ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D47E;MATHEMATICAL BOLD ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D47F;MATHEMATICAL BOLD ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D480;MATHEMATICAL BOLD ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D481;MATHEMATICAL BOLD ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D482;MATHEMATICAL BOLD ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D483;MATHEMATICAL BOLD ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D484;MATHEMATICAL BOLD ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D485;MATHEMATICAL BOLD ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D486;MATHEMATICAL BOLD ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D487;MATHEMATICAL BOLD ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D488;MATHEMATICAL BOLD ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D489;MATHEMATICAL BOLD ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D48A;MATHEMATICAL BOLD ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D48B;MATHEMATICAL BOLD ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D48C;MATHEMATICAL BOLD ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D48D;MATHEMATICAL BOLD ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D48E;MATHEMATICAL BOLD ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D48F;MATHEMATICAL BOLD ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D490;MATHEMATICAL BOLD ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D491;MATHEMATICAL BOLD ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D492;MATHEMATICAL BOLD ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D493;MATHEMATICAL BOLD ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D494;MATHEMATICAL BOLD ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D495;MATHEMATICAL BOLD ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D496;MATHEMATICAL BOLD ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D497;MATHEMATICAL BOLD ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D498;MATHEMATICAL BOLD ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D499;MATHEMATICAL BOLD ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D49A;MATHEMATICAL BOLD ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D49B;MATHEMATICAL BOLD ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D49C;MATHEMATICAL SCRIPT CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D49E;MATHEMATICAL SCRIPT CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D49F;MATHEMATICAL SCRIPT CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D4A2;MATHEMATICAL SCRIPT CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D4A5;MATHEMATICAL SCRIPT CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D4A6;MATHEMATICAL SCRIPT CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D4A9;MATHEMATICAL SCRIPT CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D4AA;MATHEMATICAL SCRIPT CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D4AB;MATHEMATICAL SCRIPT CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D4AC;MATHEMATICAL SCRIPT CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D4AE;MATHEMATICAL SCRIPT CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D4AF;MATHEMATICAL SCRIPT CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D4B0;MATHEMATICAL SCRIPT CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D4B1;MATHEMATICAL SCRIPT CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D4B2;MATHEMATICAL SCRIPT CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D4B3;MATHEMATICAL SCRIPT CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D4B4;MATHEMATICAL SCRIPT CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D4B5;MATHEMATICAL SCRIPT CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D4B6;MATHEMATICAL SCRIPT SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D4B7;MATHEMATICAL SCRIPT SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D4B8;MATHEMATICAL SCRIPT SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D4B9;MATHEMATICAL SCRIPT SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D4BB;MATHEMATICAL SCRIPT SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D4BD;MATHEMATICAL SCRIPT SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D4BE;MATHEMATICAL SCRIPT SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D4BF;MATHEMATICAL SCRIPT SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D4C0;MATHEMATICAL SCRIPT SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D4C1;MATHEMATICAL SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D4C2;MATHEMATICAL SCRIPT SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D4C3;MATHEMATICAL SCRIPT SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D4C5;MATHEMATICAL SCRIPT SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D4C6;MATHEMATICAL SCRIPT SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D4C7;MATHEMATICAL SCRIPT SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D4C8;MATHEMATICAL SCRIPT SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D4C9;MATHEMATICAL SCRIPT SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D4CA;MATHEMATICAL SCRIPT SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D4CB;MATHEMATICAL SCRIPT SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D4CC;MATHEMATICAL SCRIPT SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D4CD;MATHEMATICAL SCRIPT SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D4CE;MATHEMATICAL SCRIPT SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D4CF;MATHEMATICAL SCRIPT SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D4D0;MATHEMATICAL BOLD SCRIPT CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D4D1;MATHEMATICAL BOLD SCRIPT CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D4D2;MATHEMATICAL BOLD SCRIPT CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D4D3;MATHEMATICAL BOLD SCRIPT CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D4D4;MATHEMATICAL BOLD SCRIPT CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D4D5;MATHEMATICAL BOLD SCRIPT CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D4D6;MATHEMATICAL BOLD SCRIPT CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D4D7;MATHEMATICAL BOLD SCRIPT CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D4D8;MATHEMATICAL BOLD SCRIPT CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D4D9;MATHEMATICAL BOLD SCRIPT CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D4DA;MATHEMATICAL BOLD SCRIPT CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D4DB;MATHEMATICAL BOLD SCRIPT CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D4DC;MATHEMATICAL BOLD SCRIPT CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D4DD;MATHEMATICAL BOLD SCRIPT CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D4DE;MATHEMATICAL BOLD SCRIPT CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D4DF;MATHEMATICAL BOLD SCRIPT CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D4E0;MATHEMATICAL BOLD SCRIPT CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D4E1;MATHEMATICAL BOLD SCRIPT CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D4E2;MATHEMATICAL BOLD SCRIPT CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D4E3;MATHEMATICAL BOLD SCRIPT CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D4E4;MATHEMATICAL BOLD SCRIPT CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D4E5;MATHEMATICAL BOLD SCRIPT CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D4E6;MATHEMATICAL BOLD SCRIPT CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D4E7;MATHEMATICAL BOLD SCRIPT CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D4E8;MATHEMATICAL BOLD SCRIPT CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D4E9;MATHEMATICAL BOLD SCRIPT CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D4EA;MATHEMATICAL BOLD SCRIPT SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D4EB;MATHEMATICAL BOLD SCRIPT SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D4EC;MATHEMATICAL BOLD SCRIPT SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D4ED;MATHEMATICAL BOLD SCRIPT SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D4EE;MATHEMATICAL BOLD SCRIPT SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D4EF;MATHEMATICAL BOLD SCRIPT SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D4F0;MATHEMATICAL BOLD SCRIPT SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D4F1;MATHEMATICAL BOLD SCRIPT SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D4F2;MATHEMATICAL BOLD SCRIPT SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D4F3;MATHEMATICAL BOLD SCRIPT SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D4F4;MATHEMATICAL BOLD SCRIPT SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D4F5;MATHEMATICAL BOLD SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D4F6;MATHEMATICAL BOLD SCRIPT SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D4F7;MATHEMATICAL BOLD SCRIPT SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D4F8;MATHEMATICAL BOLD SCRIPT SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D4F9;MATHEMATICAL BOLD SCRIPT SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D4FA;MATHEMATICAL BOLD SCRIPT SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D4FB;MATHEMATICAL BOLD SCRIPT SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D4FC;MATHEMATICAL BOLD SCRIPT SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D4FD;MATHEMATICAL BOLD SCRIPT SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D4FE;MATHEMATICAL BOLD SCRIPT SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D4FF;MATHEMATICAL BOLD SCRIPT SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D500;MATHEMATICAL BOLD SCRIPT SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D501;MATHEMATICAL BOLD SCRIPT SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D502;MATHEMATICAL BOLD SCRIPT SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D503;MATHEMATICAL BOLD SCRIPT SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D504;MATHEMATICAL FRAKTUR CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D505;MATHEMATICAL FRAKTUR CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D507;MATHEMATICAL FRAKTUR CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D508;MATHEMATICAL FRAKTUR CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D509;MATHEMATICAL FRAKTUR CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D50A;MATHEMATICAL FRAKTUR CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D50D;MATHEMATICAL FRAKTUR CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D50E;MATHEMATICAL FRAKTUR CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D50F;MATHEMATICAL FRAKTUR CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D510;MATHEMATICAL FRAKTUR CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D511;MATHEMATICAL FRAKTUR CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D512;MATHEMATICAL FRAKTUR CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D513;MATHEMATICAL FRAKTUR CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D514;MATHEMATICAL FRAKTUR CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D516;MATHEMATICAL FRAKTUR CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D517;MATHEMATICAL FRAKTUR CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D518;MATHEMATICAL FRAKTUR CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D519;MATHEMATICAL FRAKTUR CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D51A;MATHEMATICAL FRAKTUR CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D51B;MATHEMATICAL FRAKTUR CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D51C;MATHEMATICAL FRAKTUR CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D51E;MATHEMATICAL FRAKTUR SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D51F;MATHEMATICAL FRAKTUR SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D520;MATHEMATICAL FRAKTUR SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D521;MATHEMATICAL FRAKTUR SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D522;MATHEMATICAL FRAKTUR SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D523;MATHEMATICAL FRAKTUR SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D524;MATHEMATICAL FRAKTUR SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D525;MATHEMATICAL FRAKTUR SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D526;MATHEMATICAL FRAKTUR SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D527;MATHEMATICAL FRAKTUR SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D528;MATHEMATICAL FRAKTUR SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D529;MATHEMATICAL FRAKTUR SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D52A;MATHEMATICAL FRAKTUR SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D52B;MATHEMATICAL FRAKTUR SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D52C;MATHEMATICAL FRAKTUR SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D52D;MATHEMATICAL FRAKTUR SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D52E;MATHEMATICAL FRAKTUR SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D52F;MATHEMATICAL FRAKTUR SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D530;MATHEMATICAL FRAKTUR SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D531;MATHEMATICAL FRAKTUR SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D532;MATHEMATICAL FRAKTUR SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D533;MATHEMATICAL FRAKTUR SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D534;MATHEMATICAL FRAKTUR SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D535;MATHEMATICAL FRAKTUR SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D536;MATHEMATICAL FRAKTUR SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D537;MATHEMATICAL FRAKTUR SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D538;MATHEMATICAL DOUBLE-STRUCK CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D539;MATHEMATICAL DOUBLE-STRUCK CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D53B;MATHEMATICAL DOUBLE-STRUCK CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D53C;MATHEMATICAL DOUBLE-STRUCK CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D53D;MATHEMATICAL DOUBLE-STRUCK CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D53E;MATHEMATICAL DOUBLE-STRUCK CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D540;MATHEMATICAL DOUBLE-STRUCK CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D541;MATHEMATICAL DOUBLE-STRUCK CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D542;MATHEMATICAL DOUBLE-STRUCK CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D543;MATHEMATICAL DOUBLE-STRUCK CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D544;MATHEMATICAL DOUBLE-STRUCK CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D546;MATHEMATICAL DOUBLE-STRUCK CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D54A;MATHEMATICAL DOUBLE-STRUCK CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D54B;MATHEMATICAL DOUBLE-STRUCK CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D54C;MATHEMATICAL DOUBLE-STRUCK CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D54D;MATHEMATICAL DOUBLE-STRUCK CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D54E;MATHEMATICAL DOUBLE-STRUCK CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D54F;MATHEMATICAL DOUBLE-STRUCK CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D550;MATHEMATICAL DOUBLE-STRUCK CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D552;MATHEMATICAL DOUBLE-STRUCK SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D553;MATHEMATICAL DOUBLE-STRUCK SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D554;MATHEMATICAL DOUBLE-STRUCK SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D555;MATHEMATICAL DOUBLE-STRUCK SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D556;MATHEMATICAL DOUBLE-STRUCK SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D557;MATHEMATICAL DOUBLE-STRUCK SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D558;MATHEMATICAL DOUBLE-STRUCK SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D559;MATHEMATICAL DOUBLE-STRUCK SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D55A;MATHEMATICAL DOUBLE-STRUCK SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D55B;MATHEMATICAL DOUBLE-STRUCK SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D55C;MATHEMATICAL DOUBLE-STRUCK SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D55D;MATHEMATICAL DOUBLE-STRUCK SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D55E;MATHEMATICAL DOUBLE-STRUCK SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D55F;MATHEMATICAL DOUBLE-STRUCK SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D560;MATHEMATICAL DOUBLE-STRUCK SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D561;MATHEMATICAL DOUBLE-STRUCK SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D562;MATHEMATICAL DOUBLE-STRUCK SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D563;MATHEMATICAL DOUBLE-STRUCK SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D564;MATHEMATICAL DOUBLE-STRUCK SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D565;MATHEMATICAL DOUBLE-STRUCK SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D566;MATHEMATICAL DOUBLE-STRUCK SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D567;MATHEMATICAL DOUBLE-STRUCK SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D568;MATHEMATICAL DOUBLE-STRUCK SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D569;MATHEMATICAL DOUBLE-STRUCK SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D56A;MATHEMATICAL DOUBLE-STRUCK SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D56B;MATHEMATICAL DOUBLE-STRUCK SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D56C;MATHEMATICAL BOLD FRAKTUR CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D56D;MATHEMATICAL BOLD FRAKTUR CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D56E;MATHEMATICAL BOLD FRAKTUR CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D56F;MATHEMATICAL BOLD FRAKTUR CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D570;MATHEMATICAL BOLD FRAKTUR CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D571;MATHEMATICAL BOLD FRAKTUR CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D572;MATHEMATICAL BOLD FRAKTUR CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D573;MATHEMATICAL BOLD FRAKTUR CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D574;MATHEMATICAL BOLD FRAKTUR CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D575;MATHEMATICAL BOLD FRAKTUR CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D576;MATHEMATICAL BOLD FRAKTUR CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D577;MATHEMATICAL BOLD FRAKTUR CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D578;MATHEMATICAL BOLD FRAKTUR CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D579;MATHEMATICAL BOLD FRAKTUR CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D57A;MATHEMATICAL BOLD FRAKTUR CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D57B;MATHEMATICAL BOLD FRAKTUR CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D57C;MATHEMATICAL BOLD FRAKTUR CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D57D;MATHEMATICAL BOLD FRAKTUR CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D57E;MATHEMATICAL BOLD FRAKTUR CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D57F;MATHEMATICAL BOLD FRAKTUR CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D580;MATHEMATICAL BOLD FRAKTUR CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D581;MATHEMATICAL BOLD FRAKTUR CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D582;MATHEMATICAL BOLD FRAKTUR CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D583;MATHEMATICAL BOLD FRAKTUR CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D584;MATHEMATICAL BOLD FRAKTUR CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D585;MATHEMATICAL BOLD FRAKTUR CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D586;MATHEMATICAL BOLD FRAKTUR SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D587;MATHEMATICAL BOLD FRAKTUR SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D588;MATHEMATICAL BOLD FRAKTUR SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D589;MATHEMATICAL BOLD FRAKTUR SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D58A;MATHEMATICAL BOLD FRAKTUR SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D58B;MATHEMATICAL BOLD FRAKTUR SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D58C;MATHEMATICAL BOLD FRAKTUR SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D58D;MATHEMATICAL BOLD FRAKTUR SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D58E;MATHEMATICAL BOLD FRAKTUR SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D58F;MATHEMATICAL BOLD FRAKTUR SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D590;MATHEMATICAL BOLD FRAKTUR SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D591;MATHEMATICAL BOLD FRAKTUR SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D592;MATHEMATICAL BOLD FRAKTUR SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D593;MATHEMATICAL BOLD FRAKTUR SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D594;MATHEMATICAL BOLD FRAKTUR SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D595;MATHEMATICAL BOLD FRAKTUR SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D596;MATHEMATICAL BOLD FRAKTUR SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D597;MATHEMATICAL BOLD FRAKTUR SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D598;MATHEMATICAL BOLD FRAKTUR SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D599;MATHEMATICAL BOLD FRAKTUR SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D59A;MATHEMATICAL BOLD FRAKTUR SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D59B;MATHEMATICAL BOLD FRAKTUR SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D59C;MATHEMATICAL BOLD FRAKTUR SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D59D;MATHEMATICAL BOLD FRAKTUR SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D59E;MATHEMATICAL BOLD FRAKTUR SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D59F;MATHEMATICAL BOLD FRAKTUR SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D5A0;MATHEMATICAL SANS-SERIF CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D5A1;MATHEMATICAL SANS-SERIF CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D5A2;MATHEMATICAL SANS-SERIF CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D5A3;MATHEMATICAL SANS-SERIF CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D5A4;MATHEMATICAL SANS-SERIF CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D5A5;MATHEMATICAL SANS-SERIF CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D5A6;MATHEMATICAL SANS-SERIF CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D5A7;MATHEMATICAL SANS-SERIF CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D5A8;MATHEMATICAL SANS-SERIF CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D5A9;MATHEMATICAL SANS-SERIF CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D5AA;MATHEMATICAL SANS-SERIF CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D5AB;MATHEMATICAL SANS-SERIF CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D5AC;MATHEMATICAL SANS-SERIF CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D5AD;MATHEMATICAL SANS-SERIF CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D5AE;MATHEMATICAL SANS-SERIF CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D5AF;MATHEMATICAL SANS-SERIF CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D5B0;MATHEMATICAL SANS-SERIF CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D5B1;MATHEMATICAL SANS-SERIF CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D5B2;MATHEMATICAL SANS-SERIF CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D5B3;MATHEMATICAL SANS-SERIF CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D5B4;MATHEMATICAL SANS-SERIF CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D5B5;MATHEMATICAL SANS-SERIF CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D5B6;MATHEMATICAL SANS-SERIF CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D5B7;MATHEMATICAL SANS-SERIF CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D5B8;MATHEMATICAL SANS-SERIF CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D5B9;MATHEMATICAL SANS-SERIF CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D5BA;MATHEMATICAL SANS-SERIF SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D5BB;MATHEMATICAL SANS-SERIF SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D5BC;MATHEMATICAL SANS-SERIF SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D5BD;MATHEMATICAL SANS-SERIF SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D5BE;MATHEMATICAL SANS-SERIF SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D5BF;MATHEMATICAL SANS-SERIF SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D5C0;MATHEMATICAL SANS-SERIF SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D5C1;MATHEMATICAL SANS-SERIF SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D5C2;MATHEMATICAL SANS-SERIF SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D5C3;MATHEMATICAL SANS-SERIF SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D5C4;MATHEMATICAL SANS-SERIF SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D5C5;MATHEMATICAL SANS-SERIF SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D5C6;MATHEMATICAL SANS-SERIF SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D5C7;MATHEMATICAL SANS-SERIF SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D5C8;MATHEMATICAL SANS-SERIF SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D5C9;MATHEMATICAL SANS-SERIF SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D5CA;MATHEMATICAL SANS-SERIF SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D5CB;MATHEMATICAL SANS-SERIF SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D5CC;MATHEMATICAL SANS-SERIF SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D5CD;MATHEMATICAL SANS-SERIF SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D5CE;MATHEMATICAL SANS-SERIF SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D5CF;MATHEMATICAL SANS-SERIF SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D5D0;MATHEMATICAL SANS-SERIF SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D5D1;MATHEMATICAL SANS-SERIF SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D5D2;MATHEMATICAL SANS-SERIF SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D5D3;MATHEMATICAL SANS-SERIF SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D5D4;MATHEMATICAL SANS-SERIF BOLD CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D5D5;MATHEMATICAL SANS-SERIF BOLD CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D5D6;MATHEMATICAL SANS-SERIF BOLD CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D5D7;MATHEMATICAL SANS-SERIF BOLD CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D5D8;MATHEMATICAL SANS-SERIF BOLD CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D5D9;MATHEMATICAL SANS-SERIF BOLD CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D5DA;MATHEMATICAL SANS-SERIF BOLD CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D5DB;MATHEMATICAL SANS-SERIF BOLD CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D5DC;MATHEMATICAL SANS-SERIF BOLD CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D5DD;MATHEMATICAL SANS-SERIF BOLD CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D5DE;MATHEMATICAL SANS-SERIF BOLD CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D5DF;MATHEMATICAL SANS-SERIF BOLD CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D5E0;MATHEMATICAL SANS-SERIF BOLD CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D5E1;MATHEMATICAL SANS-SERIF BOLD CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D5E2;MATHEMATICAL SANS-SERIF BOLD CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D5E3;MATHEMATICAL SANS-SERIF BOLD CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D5E4;MATHEMATICAL SANS-SERIF BOLD CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D5E5;MATHEMATICAL SANS-SERIF BOLD CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D5E6;MATHEMATICAL SANS-SERIF BOLD CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D5E7;MATHEMATICAL SANS-SERIF BOLD CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D5E8;MATHEMATICAL SANS-SERIF BOLD CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D5E9;MATHEMATICAL SANS-SERIF BOLD CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D5EA;MATHEMATICAL SANS-SERIF BOLD CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D5EB;MATHEMATICAL SANS-SERIF BOLD CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D5EC;MATHEMATICAL SANS-SERIF BOLD CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D5ED;MATHEMATICAL SANS-SERIF BOLD CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D5EE;MATHEMATICAL SANS-SERIF BOLD SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D5EF;MATHEMATICAL SANS-SERIF BOLD SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D5F0;MATHEMATICAL SANS-SERIF BOLD SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D5F1;MATHEMATICAL SANS-SERIF BOLD SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D5F2;MATHEMATICAL SANS-SERIF BOLD SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D5F3;MATHEMATICAL SANS-SERIF BOLD SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D5F4;MATHEMATICAL SANS-SERIF BOLD SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D5F5;MATHEMATICAL SANS-SERIF BOLD SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D5F6;MATHEMATICAL SANS-SERIF BOLD SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D5F7;MATHEMATICAL SANS-SERIF BOLD SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D5F8;MATHEMATICAL SANS-SERIF BOLD SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D5F9;MATHEMATICAL SANS-SERIF BOLD SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D5FA;MATHEMATICAL SANS-SERIF BOLD SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D5FB;MATHEMATICAL SANS-SERIF BOLD SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D5FC;MATHEMATICAL SANS-SERIF BOLD SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D5FD;MATHEMATICAL SANS-SERIF BOLD SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D5FE;MATHEMATICAL SANS-SERIF BOLD SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D5FF;MATHEMATICAL SANS-SERIF BOLD SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D600;MATHEMATICAL SANS-SERIF BOLD SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D601;MATHEMATICAL SANS-SERIF BOLD SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D602;MATHEMATICAL SANS-SERIF BOLD SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D603;MATHEMATICAL SANS-SERIF BOLD SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D604;MATHEMATICAL SANS-SERIF BOLD SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D605;MATHEMATICAL SANS-SERIF BOLD SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D606;MATHEMATICAL SANS-SERIF BOLD SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D607;MATHEMATICAL SANS-SERIF BOLD SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D608;MATHEMATICAL SANS-SERIF ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D609;MATHEMATICAL SANS-SERIF ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D60A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D60B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D60C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D60D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D60E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D60F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D610;MATHEMATICAL SANS-SERIF ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D611;MATHEMATICAL SANS-SERIF ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D612;MATHEMATICAL SANS-SERIF ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D613;MATHEMATICAL SANS-SERIF ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D614;MATHEMATICAL SANS-SERIF ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D615;MATHEMATICAL SANS-SERIF ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D616;MATHEMATICAL SANS-SERIF ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D617;MATHEMATICAL SANS-SERIF ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D618;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D619;MATHEMATICAL SANS-SERIF ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D61A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D61B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D61C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D61D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D61E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D61F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D620;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D621;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D622;MATHEMATICAL SANS-SERIF ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D623;MATHEMATICAL SANS-SERIF ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D624;MATHEMATICAL SANS-SERIF ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D625;MATHEMATICAL SANS-SERIF ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D626;MATHEMATICAL SANS-SERIF ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D627;MATHEMATICAL SANS-SERIF ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D628;MATHEMATICAL SANS-SERIF ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D629;MATHEMATICAL SANS-SERIF ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D62A;MATHEMATICAL SANS-SERIF ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D62B;MATHEMATICAL SANS-SERIF ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D62C;MATHEMATICAL SANS-SERIF ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D62D;MATHEMATICAL SANS-SERIF ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D62E;MATHEMATICAL SANS-SERIF ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D62F;MATHEMATICAL SANS-SERIF ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D630;MATHEMATICAL SANS-SERIF ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D631;MATHEMATICAL SANS-SERIF ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D632;MATHEMATICAL SANS-SERIF ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D633;MATHEMATICAL SANS-SERIF ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D634;MATHEMATICAL SANS-SERIF ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D635;MATHEMATICAL SANS-SERIF ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D636;MATHEMATICAL SANS-SERIF ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D637;MATHEMATICAL SANS-SERIF ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D638;MATHEMATICAL SANS-SERIF ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D639;MATHEMATICAL SANS-SERIF ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D63A;MATHEMATICAL SANS-SERIF ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D63B;MATHEMATICAL SANS-SERIF ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D63C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D63D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D63E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D63F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D640;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D641;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D642;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D643;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D644;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D645;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D646;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D647;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D648;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D649;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D64A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D64B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D64C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D64D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D64E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D64F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D650;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D651;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D652;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D653;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D654;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D655;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D656;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D657;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D658;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D659;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D65A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D65B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D65C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D65D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D65E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D65F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D660;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D661;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D662;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D663;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D664;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D665;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D666;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D667;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D668;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D669;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D66A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D66B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D66C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D66D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D66E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D66F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D670;MATHEMATICAL MONOSPACE CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
-1D671;MATHEMATICAL MONOSPACE CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
-1D672;MATHEMATICAL MONOSPACE CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
-1D673;MATHEMATICAL MONOSPACE CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
-1D674;MATHEMATICAL MONOSPACE CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
-1D675;MATHEMATICAL MONOSPACE CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
-1D676;MATHEMATICAL MONOSPACE CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
-1D677;MATHEMATICAL MONOSPACE CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
-1D678;MATHEMATICAL MONOSPACE CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
-1D679;MATHEMATICAL MONOSPACE CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
-1D67A;MATHEMATICAL MONOSPACE CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
-1D67B;MATHEMATICAL MONOSPACE CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
-1D67C;MATHEMATICAL MONOSPACE CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
-1D67D;MATHEMATICAL MONOSPACE CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
-1D67E;MATHEMATICAL MONOSPACE CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
-1D67F;MATHEMATICAL MONOSPACE CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
-1D680;MATHEMATICAL MONOSPACE CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
-1D681;MATHEMATICAL MONOSPACE CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
-1D682;MATHEMATICAL MONOSPACE CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
-1D683;MATHEMATICAL MONOSPACE CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
-1D684;MATHEMATICAL MONOSPACE CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
-1D685;MATHEMATICAL MONOSPACE CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
-1D686;MATHEMATICAL MONOSPACE CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
-1D687;MATHEMATICAL MONOSPACE CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
-1D688;MATHEMATICAL MONOSPACE CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
-1D689;MATHEMATICAL MONOSPACE CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
-1D68A;MATHEMATICAL MONOSPACE SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
-1D68B;MATHEMATICAL MONOSPACE SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
-1D68C;MATHEMATICAL MONOSPACE SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
-1D68D;MATHEMATICAL MONOSPACE SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
-1D68E;MATHEMATICAL MONOSPACE SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
-1D68F;MATHEMATICAL MONOSPACE SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
-1D690;MATHEMATICAL MONOSPACE SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
-1D691;MATHEMATICAL MONOSPACE SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
-1D692;MATHEMATICAL MONOSPACE SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
-1D693;MATHEMATICAL MONOSPACE SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
-1D694;MATHEMATICAL MONOSPACE SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
-1D695;MATHEMATICAL MONOSPACE SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
-1D696;MATHEMATICAL MONOSPACE SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
-1D697;MATHEMATICAL MONOSPACE SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
-1D698;MATHEMATICAL MONOSPACE SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
-1D699;MATHEMATICAL MONOSPACE SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
-1D69A;MATHEMATICAL MONOSPACE SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
-1D69B;MATHEMATICAL MONOSPACE SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
-1D69C;MATHEMATICAL MONOSPACE SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
-1D69D;MATHEMATICAL MONOSPACE SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
-1D69E;MATHEMATICAL MONOSPACE SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
-1D69F;MATHEMATICAL MONOSPACE SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
-1D6A0;MATHEMATICAL MONOSPACE SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
-1D6A1;MATHEMATICAL MONOSPACE SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
-1D6A2;MATHEMATICAL MONOSPACE SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
-1D6A3;MATHEMATICAL MONOSPACE SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
-1D6A4;MATHEMATICAL ITALIC SMALL DOTLESS I;Ll;0;L;<font> 0131;;;;N;;;;;
-1D6A5;MATHEMATICAL ITALIC SMALL DOTLESS J;Ll;0;L;<font> 0237;;;;N;;;;;
-1D6A8;MATHEMATICAL BOLD CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
-1D6A9;MATHEMATICAL BOLD CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
-1D6AA;MATHEMATICAL BOLD CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
-1D6AB;MATHEMATICAL BOLD CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
-1D6AC;MATHEMATICAL BOLD CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
-1D6AD;MATHEMATICAL BOLD CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
-1D6AE;MATHEMATICAL BOLD CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
-1D6AF;MATHEMATICAL BOLD CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
-1D6B0;MATHEMATICAL BOLD CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
-1D6B1;MATHEMATICAL BOLD CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
-1D6B2;MATHEMATICAL BOLD CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
-1D6B3;MATHEMATICAL BOLD CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
-1D6B4;MATHEMATICAL BOLD CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
-1D6B5;MATHEMATICAL BOLD CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
-1D6B6;MATHEMATICAL BOLD CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
-1D6B7;MATHEMATICAL BOLD CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
-1D6B8;MATHEMATICAL BOLD CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
-1D6B9;MATHEMATICAL BOLD CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
-1D6BA;MATHEMATICAL BOLD CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
-1D6BB;MATHEMATICAL BOLD CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
-1D6BC;MATHEMATICAL BOLD CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
-1D6BD;MATHEMATICAL BOLD CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
-1D6BE;MATHEMATICAL BOLD CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
-1D6BF;MATHEMATICAL BOLD CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
-1D6C0;MATHEMATICAL BOLD CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
-1D6C1;MATHEMATICAL BOLD NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
-1D6C2;MATHEMATICAL BOLD SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
-1D6C3;MATHEMATICAL BOLD SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
-1D6C4;MATHEMATICAL BOLD SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
-1D6C5;MATHEMATICAL BOLD SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
-1D6C6;MATHEMATICAL BOLD SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
-1D6C7;MATHEMATICAL BOLD SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
-1D6C8;MATHEMATICAL BOLD SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
-1D6C9;MATHEMATICAL BOLD SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
-1D6CA;MATHEMATICAL BOLD SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
-1D6CB;MATHEMATICAL BOLD SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
-1D6CC;MATHEMATICAL BOLD SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
-1D6CD;MATHEMATICAL BOLD SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
-1D6CE;MATHEMATICAL BOLD SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
-1D6CF;MATHEMATICAL BOLD SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
-1D6D0;MATHEMATICAL BOLD SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
-1D6D1;MATHEMATICAL BOLD SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
-1D6D2;MATHEMATICAL BOLD SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
-1D6D3;MATHEMATICAL BOLD SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
-1D6D4;MATHEMATICAL BOLD SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
-1D6D5;MATHEMATICAL BOLD SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
-1D6D6;MATHEMATICAL BOLD SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
-1D6D7;MATHEMATICAL BOLD SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
-1D6D8;MATHEMATICAL BOLD SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
-1D6D9;MATHEMATICAL BOLD SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
-1D6DA;MATHEMATICAL BOLD SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
-1D6DB;MATHEMATICAL BOLD PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
-1D6DC;MATHEMATICAL BOLD EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
-1D6DD;MATHEMATICAL BOLD THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
-1D6DE;MATHEMATICAL BOLD KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
-1D6DF;MATHEMATICAL BOLD PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
-1D6E0;MATHEMATICAL BOLD RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
-1D6E1;MATHEMATICAL BOLD PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
-1D6E2;MATHEMATICAL ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
-1D6E3;MATHEMATICAL ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
-1D6E4;MATHEMATICAL ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
-1D6E5;MATHEMATICAL ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
-1D6E6;MATHEMATICAL ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
-1D6E7;MATHEMATICAL ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
-1D6E8;MATHEMATICAL ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
-1D6E9;MATHEMATICAL ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
-1D6EA;MATHEMATICAL ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
-1D6EB;MATHEMATICAL ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
-1D6EC;MATHEMATICAL ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
-1D6ED;MATHEMATICAL ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
-1D6EE;MATHEMATICAL ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
-1D6EF;MATHEMATICAL ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
-1D6F0;MATHEMATICAL ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
-1D6F1;MATHEMATICAL ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
-1D6F2;MATHEMATICAL ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
-1D6F3;MATHEMATICAL ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
-1D6F4;MATHEMATICAL ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
-1D6F5;MATHEMATICAL ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
-1D6F6;MATHEMATICAL ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
-1D6F7;MATHEMATICAL ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
-1D6F8;MATHEMATICAL ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
-1D6F9;MATHEMATICAL ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
-1D6FA;MATHEMATICAL ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
-1D6FB;MATHEMATICAL ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
-1D6FC;MATHEMATICAL ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
-1D6FD;MATHEMATICAL ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
-1D6FE;MATHEMATICAL ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
-1D6FF;MATHEMATICAL ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
-1D700;MATHEMATICAL ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
-1D701;MATHEMATICAL ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
-1D702;MATHEMATICAL ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
-1D703;MATHEMATICAL ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
-1D704;MATHEMATICAL ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
-1D705;MATHEMATICAL ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
-1D706;MATHEMATICAL ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
-1D707;MATHEMATICAL ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
-1D708;MATHEMATICAL ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
-1D709;MATHEMATICAL ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
-1D70A;MATHEMATICAL ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
-1D70B;MATHEMATICAL ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
-1D70C;MATHEMATICAL ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
-1D70D;MATHEMATICAL ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
-1D70E;MATHEMATICAL ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
-1D70F;MATHEMATICAL ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
-1D710;MATHEMATICAL ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
-1D711;MATHEMATICAL ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
-1D712;MATHEMATICAL ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
-1D713;MATHEMATICAL ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
-1D714;MATHEMATICAL ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
-1D715;MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
-1D716;MATHEMATICAL ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
-1D717;MATHEMATICAL ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
-1D718;MATHEMATICAL ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
-1D719;MATHEMATICAL ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
-1D71A;MATHEMATICAL ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
-1D71B;MATHEMATICAL ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
-1D71C;MATHEMATICAL BOLD ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
-1D71D;MATHEMATICAL BOLD ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
-1D71E;MATHEMATICAL BOLD ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
-1D71F;MATHEMATICAL BOLD ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
-1D720;MATHEMATICAL BOLD ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
-1D721;MATHEMATICAL BOLD ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
-1D722;MATHEMATICAL BOLD ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
-1D723;MATHEMATICAL BOLD ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
-1D724;MATHEMATICAL BOLD ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
-1D725;MATHEMATICAL BOLD ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
-1D726;MATHEMATICAL BOLD ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
-1D727;MATHEMATICAL BOLD ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
-1D728;MATHEMATICAL BOLD ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
-1D729;MATHEMATICAL BOLD ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
-1D72A;MATHEMATICAL BOLD ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
-1D72B;MATHEMATICAL BOLD ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
-1D72C;MATHEMATICAL BOLD ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
-1D72D;MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
-1D72E;MATHEMATICAL BOLD ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
-1D72F;MATHEMATICAL BOLD ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
-1D730;MATHEMATICAL BOLD ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
-1D731;MATHEMATICAL BOLD ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
-1D732;MATHEMATICAL BOLD ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
-1D733;MATHEMATICAL BOLD ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
-1D734;MATHEMATICAL BOLD ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
-1D735;MATHEMATICAL BOLD ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
-1D736;MATHEMATICAL BOLD ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
-1D737;MATHEMATICAL BOLD ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
-1D738;MATHEMATICAL BOLD ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
-1D739;MATHEMATICAL BOLD ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
-1D73A;MATHEMATICAL BOLD ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
-1D73B;MATHEMATICAL BOLD ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
-1D73C;MATHEMATICAL BOLD ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
-1D73D;MATHEMATICAL BOLD ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
-1D73E;MATHEMATICAL BOLD ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
-1D73F;MATHEMATICAL BOLD ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
-1D740;MATHEMATICAL BOLD ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
-1D741;MATHEMATICAL BOLD ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
-1D742;MATHEMATICAL BOLD ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
-1D743;MATHEMATICAL BOLD ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
-1D744;MATHEMATICAL BOLD ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
-1D745;MATHEMATICAL BOLD ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
-1D746;MATHEMATICAL BOLD ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
-1D747;MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
-1D748;MATHEMATICAL BOLD ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
-1D749;MATHEMATICAL BOLD ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
-1D74A;MATHEMATICAL BOLD ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
-1D74B;MATHEMATICAL BOLD ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
-1D74C;MATHEMATICAL BOLD ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
-1D74D;MATHEMATICAL BOLD ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
-1D74E;MATHEMATICAL BOLD ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
-1D74F;MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
-1D750;MATHEMATICAL BOLD ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
-1D751;MATHEMATICAL BOLD ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
-1D752;MATHEMATICAL BOLD ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
-1D753;MATHEMATICAL BOLD ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
-1D754;MATHEMATICAL BOLD ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
-1D755;MATHEMATICAL BOLD ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
-1D756;MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
-1D757;MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
-1D758;MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
-1D759;MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
-1D75A;MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
-1D75B;MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
-1D75C;MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
-1D75D;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
-1D75E;MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
-1D75F;MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
-1D760;MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
-1D761;MATHEMATICAL SANS-SERIF BOLD CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
-1D762;MATHEMATICAL SANS-SERIF BOLD CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
-1D763;MATHEMATICAL SANS-SERIF BOLD CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
-1D764;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
-1D765;MATHEMATICAL SANS-SERIF BOLD CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
-1D766;MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
-1D767;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
-1D768;MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
-1D769;MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
-1D76A;MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
-1D76B;MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
-1D76C;MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
-1D76D;MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
-1D76E;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
-1D76F;MATHEMATICAL SANS-SERIF BOLD NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
-1D770;MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
-1D771;MATHEMATICAL SANS-SERIF BOLD SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
-1D772;MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
-1D773;MATHEMATICAL SANS-SERIF BOLD SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
-1D774;MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
-1D775;MATHEMATICAL SANS-SERIF BOLD SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
-1D776;MATHEMATICAL SANS-SERIF BOLD SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
-1D777;MATHEMATICAL SANS-SERIF BOLD SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
-1D778;MATHEMATICAL SANS-SERIF BOLD SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
-1D779;MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
-1D77A;MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
-1D77B;MATHEMATICAL SANS-SERIF BOLD SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
-1D77C;MATHEMATICAL SANS-SERIF BOLD SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
-1D77D;MATHEMATICAL SANS-SERIF BOLD SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
-1D77E;MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
-1D77F;MATHEMATICAL SANS-SERIF BOLD SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
-1D780;MATHEMATICAL SANS-SERIF BOLD SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
-1D781;MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
-1D782;MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
-1D783;MATHEMATICAL SANS-SERIF BOLD SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
-1D784;MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
-1D785;MATHEMATICAL SANS-SERIF BOLD SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
-1D786;MATHEMATICAL SANS-SERIF BOLD SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
-1D787;MATHEMATICAL SANS-SERIF BOLD SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
-1D788;MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
-1D789;MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
-1D78A;MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
-1D78B;MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
-1D78C;MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
-1D78D;MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
-1D78E;MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
-1D78F;MATHEMATICAL SANS-SERIF BOLD PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
-1D790;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
-1D791;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
-1D792;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
-1D793;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
-1D794;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
-1D795;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
-1D796;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
-1D797;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
-1D798;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
-1D799;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
-1D79A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
-1D79B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
-1D79C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
-1D79D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
-1D79E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
-1D79F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
-1D7A0;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
-1D7A1;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
-1D7A2;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
-1D7A3;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
-1D7A4;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
-1D7A5;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
-1D7A6;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
-1D7A7;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
-1D7A8;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
-1D7A9;MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
-1D7AA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
-1D7AB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
-1D7AC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
-1D7AD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
-1D7AE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
-1D7AF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
-1D7B0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
-1D7B1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
-1D7B2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
-1D7B3;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
-1D7B4;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
-1D7B5;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
-1D7B6;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
-1D7B7;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
-1D7B8;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
-1D7B9;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
-1D7BA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
-1D7BB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
-1D7BC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
-1D7BD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
-1D7BE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
-1D7BF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
-1D7C0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
-1D7C1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
-1D7C2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
-1D7C3;MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
-1D7C4;MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
-1D7C5;MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
-1D7C6;MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
-1D7C7;MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
-1D7C8;MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
-1D7C9;MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
-1D7CA;MATHEMATICAL BOLD CAPITAL DIGAMMA;Lu;0;L;<font> 03DC;;;;N;;;;;
-1D7CB;MATHEMATICAL BOLD SMALL DIGAMMA;Ll;0;L;<font> 03DD;;;;N;;;;;
-1D7CE;MATHEMATICAL BOLD DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
-1D7CF;MATHEMATICAL BOLD DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
-1D7D0;MATHEMATICAL BOLD DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
-1D7D1;MATHEMATICAL BOLD DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
-1D7D2;MATHEMATICAL BOLD DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
-1D7D3;MATHEMATICAL BOLD DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
-1D7D4;MATHEMATICAL BOLD DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
-1D7D5;MATHEMATICAL BOLD DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
-1D7D6;MATHEMATICAL BOLD DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
-1D7D7;MATHEMATICAL BOLD DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
-1D7D8;MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
-1D7D9;MATHEMATICAL DOUBLE-STRUCK DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
-1D7DA;MATHEMATICAL DOUBLE-STRUCK DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
-1D7DB;MATHEMATICAL DOUBLE-STRUCK DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
-1D7DC;MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
-1D7DD;MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
-1D7DE;MATHEMATICAL DOUBLE-STRUCK DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
-1D7DF;MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
-1D7E0;MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
-1D7E1;MATHEMATICAL DOUBLE-STRUCK DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
-1D7E2;MATHEMATICAL SANS-SERIF DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
-1D7E3;MATHEMATICAL SANS-SERIF DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
-1D7E4;MATHEMATICAL SANS-SERIF DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
-1D7E5;MATHEMATICAL SANS-SERIF DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
-1D7E6;MATHEMATICAL SANS-SERIF DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
-1D7E7;MATHEMATICAL SANS-SERIF DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
-1D7E8;MATHEMATICAL SANS-SERIF DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
-1D7E9;MATHEMATICAL SANS-SERIF DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
-1D7EA;MATHEMATICAL SANS-SERIF DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
-1D7EB;MATHEMATICAL SANS-SERIF DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
-1D7EC;MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
-1D7ED;MATHEMATICAL SANS-SERIF BOLD DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
-1D7EE;MATHEMATICAL SANS-SERIF BOLD DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
-1D7EF;MATHEMATICAL SANS-SERIF BOLD DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
-1D7F0;MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
-1D7F1;MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
-1D7F2;MATHEMATICAL SANS-SERIF BOLD DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
-1D7F3;MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
-1D7F4;MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
-1D7F5;MATHEMATICAL SANS-SERIF BOLD DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
-1D7F6;MATHEMATICAL MONOSPACE DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
-1D7F7;MATHEMATICAL MONOSPACE DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
-1D7F8;MATHEMATICAL MONOSPACE DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
-1D7F9;MATHEMATICAL MONOSPACE DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
-1D7FA;MATHEMATICAL MONOSPACE DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
-1D7FB;MATHEMATICAL MONOSPACE DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
-1D7FC;MATHEMATICAL MONOSPACE DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
-1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
-1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
-1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
-1EE00;ARABIC MATHEMATICAL ALEF;Lo;0;AL;<font> 0627;;;;N;;;;;
-1EE01;ARABIC MATHEMATICAL BEH;Lo;0;AL;<font> 0628;;;;N;;;;;
-1EE02;ARABIC MATHEMATICAL JEEM;Lo;0;AL;<font> 062C;;;;N;;;;;
-1EE03;ARABIC MATHEMATICAL DAL;Lo;0;AL;<font> 062F;;;;N;;;;;
-1EE05;ARABIC MATHEMATICAL WAW;Lo;0;AL;<font> 0648;;;;N;;;;;
-1EE06;ARABIC MATHEMATICAL ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;;
-1EE07;ARABIC MATHEMATICAL HAH;Lo;0;AL;<font> 062D;;;;N;;;;;
-1EE08;ARABIC MATHEMATICAL TAH;Lo;0;AL;<font> 0637;;;;N;;;;;
-1EE09;ARABIC MATHEMATICAL YEH;Lo;0;AL;<font> 064A;;;;N;;;;;
-1EE0A;ARABIC MATHEMATICAL KAF;Lo;0;AL;<font> 0643;;;;N;;;;;
-1EE0B;ARABIC MATHEMATICAL LAM;Lo;0;AL;<font> 0644;;;;N;;;;;
-1EE0C;ARABIC MATHEMATICAL MEEM;Lo;0;AL;<font> 0645;;;;N;;;;;
-1EE0D;ARABIC MATHEMATICAL NOON;Lo;0;AL;<font> 0646;;;;N;;;;;
-1EE0E;ARABIC MATHEMATICAL SEEN;Lo;0;AL;<font> 0633;;;;N;;;;;
-1EE0F;ARABIC MATHEMATICAL AIN;Lo;0;AL;<font> 0639;;;;N;;;;;
-1EE10;ARABIC MATHEMATICAL FEH;Lo;0;AL;<font> 0641;;;;N;;;;;
-1EE11;ARABIC MATHEMATICAL SAD;Lo;0;AL;<font> 0635;;;;N;;;;;
-1EE12;ARABIC MATHEMATICAL QAF;Lo;0;AL;<font> 0642;;;;N;;;;;
-1EE13;ARABIC MATHEMATICAL REH;Lo;0;AL;<font> 0631;;;;N;;;;;
-1EE14;ARABIC MATHEMATICAL SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;;
-1EE15;ARABIC MATHEMATICAL TEH;Lo;0;AL;<font> 062A;;;;N;;;;;
-1EE16;ARABIC MATHEMATICAL THEH;Lo;0;AL;<font> 062B;;;;N;;;;;
-1EE17;ARABIC MATHEMATICAL KHAH;Lo;0;AL;<font> 062E;;;;N;;;;;
-1EE18;ARABIC MATHEMATICAL THAL;Lo;0;AL;<font> 0630;;;;N;;;;;
-1EE19;ARABIC MATHEMATICAL DAD;Lo;0;AL;<font> 0636;;;;N;;;;;
-1EE1A;ARABIC MATHEMATICAL ZAH;Lo;0;AL;<font> 0638;;;;N;;;;;
-1EE1B;ARABIC MATHEMATICAL GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;;
-1EE1C;ARABIC MATHEMATICAL DOTLESS BEH;Lo;0;AL;<font> 066E;;;;N;;;;;
-1EE1D;ARABIC MATHEMATICAL DOTLESS NOON;Lo;0;AL;<font> 06BA;;;;N;;;;;
-1EE1E;ARABIC MATHEMATICAL DOTLESS FEH;Lo;0;AL;<font> 06A1;;;;N;;;;;
-1EE1F;ARABIC MATHEMATICAL DOTLESS QAF;Lo;0;AL;<font> 066F;;;;N;;;;;
-1EE21;ARABIC MATHEMATICAL INITIAL BEH;Lo;0;AL;<font> 0628;;;;N;;;;;
-1EE22;ARABIC MATHEMATICAL INITIAL JEEM;Lo;0;AL;<font> 062C;;;;N;;;;;
-1EE24;ARABIC MATHEMATICAL INITIAL HEH;Lo;0;AL;<font> 0647;;;;N;;;;;
-1EE27;ARABIC MATHEMATICAL INITIAL HAH;Lo;0;AL;<font> 062D;;;;N;;;;;
-1EE29;ARABIC MATHEMATICAL INITIAL YEH;Lo;0;AL;<font> 064A;;;;N;;;;;
-1EE2A;ARABIC MATHEMATICAL INITIAL KAF;Lo;0;AL;<font> 0643;;;;N;;;;;
-1EE2B;ARABIC MATHEMATICAL INITIAL LAM;Lo;0;AL;<font> 0644;;;;N;;;;;
-1EE2C;ARABIC MATHEMATICAL INITIAL MEEM;Lo;0;AL;<font> 0645;;;;N;;;;;
-1EE2D;ARABIC MATHEMATICAL INITIAL NOON;Lo;0;AL;<font> 0646;;;;N;;;;;
-1EE2E;ARABIC MATHEMATICAL INITIAL SEEN;Lo;0;AL;<font> 0633;;;;N;;;;;
-1EE2F;ARABIC MATHEMATICAL INITIAL AIN;Lo;0;AL;<font> 0639;;;;N;;;;;
-1EE30;ARABIC MATHEMATICAL INITIAL FEH;Lo;0;AL;<font> 0641;;;;N;;;;;
-1EE31;ARABIC MATHEMATICAL INITIAL SAD;Lo;0;AL;<font> 0635;;;;N;;;;;
-1EE32;ARABIC MATHEMATICAL INITIAL QAF;Lo;0;AL;<font> 0642;;;;N;;;;;
-1EE34;ARABIC MATHEMATICAL INITIAL SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;;
-1EE35;ARABIC MATHEMATICAL INITIAL TEH;Lo;0;AL;<font> 062A;;;;N;;;;;
-1EE36;ARABIC MATHEMATICAL INITIAL THEH;Lo;0;AL;<font> 062B;;;;N;;;;;
-1EE37;ARABIC MATHEMATICAL INITIAL KHAH;Lo;0;AL;<font> 062E;;;;N;;;;;
-1EE39;ARABIC MATHEMATICAL INITIAL DAD;Lo;0;AL;<font> 0636;;;;N;;;;;
-1EE3B;ARABIC MATHEMATICAL INITIAL GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;;
-1EE42;ARABIC MATHEMATICAL TAILED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;;
-1EE47;ARABIC MATHEMATICAL TAILED HAH;Lo;0;AL;<font> 062D;;;;N;;;;;
-1EE49;ARABIC MATHEMATICAL TAILED YEH;Lo;0;AL;<font> 064A;;;;N;;;;;
-1EE4B;ARABIC MATHEMATICAL TAILED LAM;Lo;0;AL;<font> 0644;;;;N;;;;;
-1EE4D;ARABIC MATHEMATICAL TAILED NOON;Lo;0;AL;<font> 0646;;;;N;;;;;
-1EE4E;ARABIC MATHEMATICAL TAILED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;;
-1EE4F;ARABIC MATHEMATICAL TAILED AIN;Lo;0;AL;<font> 0639;;;;N;;;;;
-1EE51;ARABIC MATHEMATICAL TAILED SAD;Lo;0;AL;<font> 0635;;;;N;;;;;
-1EE52;ARABIC MATHEMATICAL TAILED QAF;Lo;0;AL;<font> 0642;;;;N;;;;;
-1EE54;ARABIC MATHEMATICAL TAILED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;;
-1EE57;ARABIC MATHEMATICAL TAILED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;;
-1EE59;ARABIC MATHEMATICAL TAILED DAD;Lo;0;AL;<font> 0636;;;;N;;;;;
-1EE5B;ARABIC MATHEMATICAL TAILED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;;
-1EE5D;ARABIC MATHEMATICAL TAILED DOTLESS NOON;Lo;0;AL;<font> 06BA;;;;N;;;;;
-1EE5F;ARABIC MATHEMATICAL TAILED DOTLESS QAF;Lo;0;AL;<font> 066F;;;;N;;;;;
-1EE61;ARABIC MATHEMATICAL STRETCHED BEH;Lo;0;AL;<font> 0628;;;;N;;;;;
-1EE62;ARABIC MATHEMATICAL STRETCHED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;;
-1EE64;ARABIC MATHEMATICAL STRETCHED HEH;Lo;0;AL;<font> 0647;;;;N;;;;;
-1EE67;ARABIC MATHEMATICAL STRETCHED HAH;Lo;0;AL;<font> 062D;;;;N;;;;;
-1EE68;ARABIC MATHEMATICAL STRETCHED TAH;Lo;0;AL;<font> 0637;;;;N;;;;;
-1EE69;ARABIC MATHEMATICAL STRETCHED YEH;Lo;0;AL;<font> 064A;;;;N;;;;;
-1EE6A;ARABIC MATHEMATICAL STRETCHED KAF;Lo;0;AL;<font> 0643;;;;N;;;;;
-1EE6C;ARABIC MATHEMATICAL STRETCHED MEEM;Lo;0;AL;<font> 0645;;;;N;;;;;
-1EE6D;ARABIC MATHEMATICAL STRETCHED NOON;Lo;0;AL;<font> 0646;;;;N;;;;;
-1EE6E;ARABIC MATHEMATICAL STRETCHED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;;
-1EE6F;ARABIC MATHEMATICAL STRETCHED AIN;Lo;0;AL;<font> 0639;;;;N;;;;;
-1EE70;ARABIC MATHEMATICAL STRETCHED FEH;Lo;0;AL;<font> 0641;;;;N;;;;;
-1EE71;ARABIC MATHEMATICAL STRETCHED SAD;Lo;0;AL;<font> 0635;;;;N;;;;;
-1EE72;ARABIC MATHEMATICAL STRETCHED QAF;Lo;0;AL;<font> 0642;;;;N;;;;;
-1EE74;ARABIC MATHEMATICAL STRETCHED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;;
-1EE75;ARABIC MATHEMATICAL STRETCHED TEH;Lo;0;AL;<font> 062A;;;;N;;;;;
-1EE76;ARABIC MATHEMATICAL STRETCHED THEH;Lo;0;AL;<font> 062B;;;;N;;;;;
-1EE77;ARABIC MATHEMATICAL STRETCHED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;;
-1EE79;ARABIC MATHEMATICAL STRETCHED DAD;Lo;0;AL;<font> 0636;;;;N;;;;;
-1EE7A;ARABIC MATHEMATICAL STRETCHED ZAH;Lo;0;AL;<font> 0638;;;;N;;;;;
-1EE7B;ARABIC MATHEMATICAL STRETCHED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;;
-1EE7C;ARABIC MATHEMATICAL STRETCHED DOTLESS BEH;Lo;0;AL;<font> 066E;;;;N;;;;;
-1EE7E;ARABIC MATHEMATICAL STRETCHED DOTLESS FEH;Lo;0;AL;<font> 06A1;;;;N;;;;;
-1EE80;ARABIC MATHEMATICAL LOOPED ALEF;Lo;0;AL;<font> 0627;;;;N;;;;;
-1EE81;ARABIC MATHEMATICAL LOOPED BEH;Lo;0;AL;<font> 0628;;;;N;;;;;
-1EE82;ARABIC MATHEMATICAL LOOPED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;;
-1EE83;ARABIC MATHEMATICAL LOOPED DAL;Lo;0;AL;<font> 062F;;;;N;;;;;
-1EE84;ARABIC MATHEMATICAL LOOPED HEH;Lo;0;AL;<font> 0647;;;;N;;;;;
-1EE85;ARABIC MATHEMATICAL LOOPED WAW;Lo;0;AL;<font> 0648;;;;N;;;;;
-1EE86;ARABIC MATHEMATICAL LOOPED ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;;
-1EE87;ARABIC MATHEMATICAL LOOPED HAH;Lo;0;AL;<font> 062D;;;;N;;;;;
-1EE88;ARABIC MATHEMATICAL LOOPED TAH;Lo;0;AL;<font> 0637;;;;N;;;;;
-1EE89;ARABIC MATHEMATICAL LOOPED YEH;Lo;0;AL;<font> 064A;;;;N;;;;;
-1EE8B;ARABIC MATHEMATICAL LOOPED LAM;Lo;0;AL;<font> 0644;;;;N;;;;;
-1EE8C;ARABIC MATHEMATICAL LOOPED MEEM;Lo;0;AL;<font> 0645;;;;N;;;;;
-1EE8D;ARABIC MATHEMATICAL LOOPED NOON;Lo;0;AL;<font> 0646;;;;N;;;;;
-1EE8E;ARABIC MATHEMATICAL LOOPED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;;
-1EE8F;ARABIC MATHEMATICAL LOOPED AIN;Lo;0;AL;<font> 0639;;;;N;;;;;
-1EE90;ARABIC MATHEMATICAL LOOPED FEH;Lo;0;AL;<font> 0641;;;;N;;;;;
-1EE91;ARABIC MATHEMATICAL LOOPED SAD;Lo;0;AL;<font> 0635;;;;N;;;;;
-1EE92;ARABIC MATHEMATICAL LOOPED QAF;Lo;0;AL;<font> 0642;;;;N;;;;;
-1EE93;ARABIC MATHEMATICAL LOOPED REH;Lo;0;AL;<font> 0631;;;;N;;;;;
-1EE94;ARABIC MATHEMATICAL LOOPED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;;
-1EE95;ARABIC MATHEMATICAL LOOPED TEH;Lo;0;AL;<font> 062A;;;;N;;;;;
-1EE96;ARABIC MATHEMATICAL LOOPED THEH;Lo;0;AL;<font> 062B;;;;N;;;;;
-1EE97;ARABIC MATHEMATICAL LOOPED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;;
-1EE98;ARABIC MATHEMATICAL LOOPED THAL;Lo;0;AL;<font> 0630;;;;N;;;;;
-1EE99;ARABIC MATHEMATICAL LOOPED DAD;Lo;0;AL;<font> 0636;;;;N;;;;;
-1EE9A;ARABIC MATHEMATICAL LOOPED ZAH;Lo;0;AL;<font> 0638;;;;N;;;;;
-1EE9B;ARABIC MATHEMATICAL LOOPED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;;
-1EEA1;ARABIC MATHEMATICAL DOUBLE-STRUCK BEH;Lo;0;AL;<font> 0628;;;;N;;;;;
-1EEA2;ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM;Lo;0;AL;<font> 062C;;;;N;;;;;
-1EEA3;ARABIC MATHEMATICAL DOUBLE-STRUCK DAL;Lo;0;AL;<font> 062F;;;;N;;;;;
-1EEA5;ARABIC MATHEMATICAL DOUBLE-STRUCK WAW;Lo;0;AL;<font> 0648;;;;N;;;;;
-1EEA6;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;;
-1EEA7;ARABIC MATHEMATICAL DOUBLE-STRUCK HAH;Lo;0;AL;<font> 062D;;;;N;;;;;
-1EEA8;ARABIC MATHEMATICAL DOUBLE-STRUCK TAH;Lo;0;AL;<font> 0637;;;;N;;;;;
-1EEA9;ARABIC MATHEMATICAL DOUBLE-STRUCK YEH;Lo;0;AL;<font> 064A;;;;N;;;;;
-1EEAB;ARABIC MATHEMATICAL DOUBLE-STRUCK LAM;Lo;0;AL;<font> 0644;;;;N;;;;;
-1EEAC;ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM;Lo;0;AL;<font> 0645;;;;N;;;;;
-1EEAD;ARABIC MATHEMATICAL DOUBLE-STRUCK NOON;Lo;0;AL;<font> 0646;;;;N;;;;;
-1EEAE;ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN;Lo;0;AL;<font> 0633;;;;N;;;;;
-1EEAF;ARABIC MATHEMATICAL DOUBLE-STRUCK AIN;Lo;0;AL;<font> 0639;;;;N;;;;;
-1EEB0;ARABIC MATHEMATICAL DOUBLE-STRUCK FEH;Lo;0;AL;<font> 0641;;;;N;;;;;
-1EEB1;ARABIC MATHEMATICAL DOUBLE-STRUCK SAD;Lo;0;AL;<font> 0635;;;;N;;;;;
-1EEB2;ARABIC MATHEMATICAL DOUBLE-STRUCK QAF;Lo;0;AL;<font> 0642;;;;N;;;;;
-1EEB3;ARABIC MATHEMATICAL DOUBLE-STRUCK REH;Lo;0;AL;<font> 0631;;;;N;;;;;
-1EEB4;ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;;
-1EEB5;ARABIC MATHEMATICAL DOUBLE-STRUCK TEH;Lo;0;AL;<font> 062A;;;;N;;;;;
-1EEB6;ARABIC MATHEMATICAL DOUBLE-STRUCK THEH;Lo;0;AL;<font> 062B;;;;N;;;;;
-1EEB7;ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH;Lo;0;AL;<font> 062E;;;;N;;;;;
-1EEB8;ARABIC MATHEMATICAL DOUBLE-STRUCK THAL;Lo;0;AL;<font> 0630;;;;N;;;;;
-1EEB9;ARABIC MATHEMATICAL DOUBLE-STRUCK DAD;Lo;0;AL;<font> 0636;;;;N;;;;;
-1EEBA;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH;Lo;0;AL;<font> 0638;;;;N;;;;;
-1EEBB;ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;;
-1EEF0;ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL;Sm;0;ON;;;;;N;;;;;
-1EEF1;ARABIC MATHEMATICAL OPERATOR HAH WITH DAL;Sm;0;ON;;;;;N;;;;;
-1F000;MAHJONG TILE EAST WIND;So;0;ON;;;;;N;;;;;
-1F001;MAHJONG TILE SOUTH WIND;So;0;ON;;;;;N;;;;;
-1F002;MAHJONG TILE WEST WIND;So;0;ON;;;;;N;;;;;
-1F003;MAHJONG TILE NORTH WIND;So;0;ON;;;;;N;;;;;
-1F004;MAHJONG TILE RED DRAGON;So;0;ON;;;;;N;;;;;
-1F005;MAHJONG TILE GREEN DRAGON;So;0;ON;;;;;N;;;;;
-1F006;MAHJONG TILE WHITE DRAGON;So;0;ON;;;;;N;;;;;
-1F007;MAHJONG TILE ONE OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F008;MAHJONG TILE TWO OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F009;MAHJONG TILE THREE OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F00A;MAHJONG TILE FOUR OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F00B;MAHJONG TILE FIVE OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F00C;MAHJONG TILE SIX OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F00D;MAHJONG TILE SEVEN OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F00E;MAHJONG TILE EIGHT OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F00F;MAHJONG TILE NINE OF CHARACTERS;So;0;ON;;;;;N;;;;;
-1F010;MAHJONG TILE ONE OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F011;MAHJONG TILE TWO OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F012;MAHJONG TILE THREE OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F013;MAHJONG TILE FOUR OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F014;MAHJONG TILE FIVE OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F015;MAHJONG TILE SIX OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F016;MAHJONG TILE SEVEN OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F017;MAHJONG TILE EIGHT OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F018;MAHJONG TILE NINE OF BAMBOOS;So;0;ON;;;;;N;;;;;
-1F019;MAHJONG TILE ONE OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F01A;MAHJONG TILE TWO OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F01B;MAHJONG TILE THREE OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F01C;MAHJONG TILE FOUR OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F01D;MAHJONG TILE FIVE OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F01E;MAHJONG TILE SIX OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F01F;MAHJONG TILE SEVEN OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F020;MAHJONG TILE EIGHT OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F021;MAHJONG TILE NINE OF CIRCLES;So;0;ON;;;;;N;;;;;
-1F022;MAHJONG TILE PLUM;So;0;ON;;;;;N;;;;;
-1F023;MAHJONG TILE ORCHID;So;0;ON;;;;;N;;;;;
-1F024;MAHJONG TILE BAMBOO;So;0;ON;;;;;N;;;;;
-1F025;MAHJONG TILE CHRYSANTHEMUM;So;0;ON;;;;;N;;;;;
-1F026;MAHJONG TILE SPRING;So;0;ON;;;;;N;;;;;
-1F027;MAHJONG TILE SUMMER;So;0;ON;;;;;N;;;;;
-1F028;MAHJONG TILE AUTUMN;So;0;ON;;;;;N;;;;;
-1F029;MAHJONG TILE WINTER;So;0;ON;;;;;N;;;;;
-1F02A;MAHJONG TILE JOKER;So;0;ON;;;;;N;;;;;
-1F02B;MAHJONG TILE BACK;So;0;ON;;;;;N;;;;;
-1F030;DOMINO TILE HORIZONTAL BACK;So;0;ON;;;;;N;;;;;
-1F031;DOMINO TILE HORIZONTAL-00-00;So;0;ON;;;;;N;;;;;
-1F032;DOMINO TILE HORIZONTAL-00-01;So;0;ON;;;;;N;;;;;
-1F033;DOMINO TILE HORIZONTAL-00-02;So;0;ON;;;;;N;;;;;
-1F034;DOMINO TILE HORIZONTAL-00-03;So;0;ON;;;;;N;;;;;
-1F035;DOMINO TILE HORIZONTAL-00-04;So;0;ON;;;;;N;;;;;
-1F036;DOMINO TILE HORIZONTAL-00-05;So;0;ON;;;;;N;;;;;
-1F037;DOMINO TILE HORIZONTAL-00-06;So;0;ON;;;;;N;;;;;
-1F038;DOMINO TILE HORIZONTAL-01-00;So;0;ON;;;;;N;;;;;
-1F039;DOMINO TILE HORIZONTAL-01-01;So;0;ON;;;;;N;;;;;
-1F03A;DOMINO TILE HORIZONTAL-01-02;So;0;ON;;;;;N;;;;;
-1F03B;DOMINO TILE HORIZONTAL-01-03;So;0;ON;;;;;N;;;;;
-1F03C;DOMINO TILE HORIZONTAL-01-04;So;0;ON;;;;;N;;;;;
-1F03D;DOMINO TILE HORIZONTAL-01-05;So;0;ON;;;;;N;;;;;
-1F03E;DOMINO TILE HORIZONTAL-01-06;So;0;ON;;;;;N;;;;;
-1F03F;DOMINO TILE HORIZONTAL-02-00;So;0;ON;;;;;N;;;;;
-1F040;DOMINO TILE HORIZONTAL-02-01;So;0;ON;;;;;N;;;;;
-1F041;DOMINO TILE HORIZONTAL-02-02;So;0;ON;;;;;N;;;;;
-1F042;DOMINO TILE HORIZONTAL-02-03;So;0;ON;;;;;N;;;;;
-1F043;DOMINO TILE HORIZONTAL-02-04;So;0;ON;;;;;N;;;;;
-1F044;DOMINO TILE HORIZONTAL-02-05;So;0;ON;;;;;N;;;;;
-1F045;DOMINO TILE HORIZONTAL-02-06;So;0;ON;;;;;N;;;;;
-1F046;DOMINO TILE HORIZONTAL-03-00;So;0;ON;;;;;N;;;;;
-1F047;DOMINO TILE HORIZONTAL-03-01;So;0;ON;;;;;N;;;;;
-1F048;DOMINO TILE HORIZONTAL-03-02;So;0;ON;;;;;N;;;;;
-1F049;DOMINO TILE HORIZONTAL-03-03;So;0;ON;;;;;N;;;;;
-1F04A;DOMINO TILE HORIZONTAL-03-04;So;0;ON;;;;;N;;;;;
-1F04B;DOMINO TILE HORIZONTAL-03-05;So;0;ON;;;;;N;;;;;
-1F04C;DOMINO TILE HORIZONTAL-03-06;So;0;ON;;;;;N;;;;;
-1F04D;DOMINO TILE HORIZONTAL-04-00;So;0;ON;;;;;N;;;;;
-1F04E;DOMINO TILE HORIZONTAL-04-01;So;0;ON;;;;;N;;;;;
-1F04F;DOMINO TILE HORIZONTAL-04-02;So;0;ON;;;;;N;;;;;
-1F050;DOMINO TILE HORIZONTAL-04-03;So;0;ON;;;;;N;;;;;
-1F051;DOMINO TILE HORIZONTAL-04-04;So;0;ON;;;;;N;;;;;
-1F052;DOMINO TILE HORIZONTAL-04-05;So;0;ON;;;;;N;;;;;
-1F053;DOMINO TILE HORIZONTAL-04-06;So;0;ON;;;;;N;;;;;
-1F054;DOMINO TILE HORIZONTAL-05-00;So;0;ON;;;;;N;;;;;
-1F055;DOMINO TILE HORIZONTAL-05-01;So;0;ON;;;;;N;;;;;
-1F056;DOMINO TILE HORIZONTAL-05-02;So;0;ON;;;;;N;;;;;
-1F057;DOMINO TILE HORIZONTAL-05-03;So;0;ON;;;;;N;;;;;
-1F058;DOMINO TILE HORIZONTAL-05-04;So;0;ON;;;;;N;;;;;
-1F059;DOMINO TILE HORIZONTAL-05-05;So;0;ON;;;;;N;;;;;
-1F05A;DOMINO TILE HORIZONTAL-05-06;So;0;ON;;;;;N;;;;;
-1F05B;DOMINO TILE HORIZONTAL-06-00;So;0;ON;;;;;N;;;;;
-1F05C;DOMINO TILE HORIZONTAL-06-01;So;0;ON;;;;;N;;;;;
-1F05D;DOMINO TILE HORIZONTAL-06-02;So;0;ON;;;;;N;;;;;
-1F05E;DOMINO TILE HORIZONTAL-06-03;So;0;ON;;;;;N;;;;;
-1F05F;DOMINO TILE HORIZONTAL-06-04;So;0;ON;;;;;N;;;;;
-1F060;DOMINO TILE HORIZONTAL-06-05;So;0;ON;;;;;N;;;;;
-1F061;DOMINO TILE HORIZONTAL-06-06;So;0;ON;;;;;N;;;;;
-1F062;DOMINO TILE VERTICAL BACK;So;0;ON;;;;;N;;;;;
-1F063;DOMINO TILE VERTICAL-00-00;So;0;ON;;;;;N;;;;;
-1F064;DOMINO TILE VERTICAL-00-01;So;0;ON;;;;;N;;;;;
-1F065;DOMINO TILE VERTICAL-00-02;So;0;ON;;;;;N;;;;;
-1F066;DOMINO TILE VERTICAL-00-03;So;0;ON;;;;;N;;;;;
-1F067;DOMINO TILE VERTICAL-00-04;So;0;ON;;;;;N;;;;;
-1F068;DOMINO TILE VERTICAL-00-05;So;0;ON;;;;;N;;;;;
-1F069;DOMINO TILE VERTICAL-00-06;So;0;ON;;;;;N;;;;;
-1F06A;DOMINO TILE VERTICAL-01-00;So;0;ON;;;;;N;;;;;
-1F06B;DOMINO TILE VERTICAL-01-01;So;0;ON;;;;;N;;;;;
-1F06C;DOMINO TILE VERTICAL-01-02;So;0;ON;;;;;N;;;;;
-1F06D;DOMINO TILE VERTICAL-01-03;So;0;ON;;;;;N;;;;;
-1F06E;DOMINO TILE VERTICAL-01-04;So;0;ON;;;;;N;;;;;
-1F06F;DOMINO TILE VERTICAL-01-05;So;0;ON;;;;;N;;;;;
-1F070;DOMINO TILE VERTICAL-01-06;So;0;ON;;;;;N;;;;;
-1F071;DOMINO TILE VERTICAL-02-00;So;0;ON;;;;;N;;;;;
-1F072;DOMINO TILE VERTICAL-02-01;So;0;ON;;;;;N;;;;;
-1F073;DOMINO TILE VERTICAL-02-02;So;0;ON;;;;;N;;;;;
-1F074;DOMINO TILE VERTICAL-02-03;So;0;ON;;;;;N;;;;;
-1F075;DOMINO TILE VERTICAL-02-04;So;0;ON;;;;;N;;;;;
-1F076;DOMINO TILE VERTICAL-02-05;So;0;ON;;;;;N;;;;;
-1F077;DOMINO TILE VERTICAL-02-06;So;0;ON;;;;;N;;;;;
-1F078;DOMINO TILE VERTICAL-03-00;So;0;ON;;;;;N;;;;;
-1F079;DOMINO TILE VERTICAL-03-01;So;0;ON;;;;;N;;;;;
-1F07A;DOMINO TILE VERTICAL-03-02;So;0;ON;;;;;N;;;;;
-1F07B;DOMINO TILE VERTICAL-03-03;So;0;ON;;;;;N;;;;;
-1F07C;DOMINO TILE VERTICAL-03-04;So;0;ON;;;;;N;;;;;
-1F07D;DOMINO TILE VERTICAL-03-05;So;0;ON;;;;;N;;;;;
-1F07E;DOMINO TILE VERTICAL-03-06;So;0;ON;;;;;N;;;;;
-1F07F;DOMINO TILE VERTICAL-04-00;So;0;ON;;;;;N;;;;;
-1F080;DOMINO TILE VERTICAL-04-01;So;0;ON;;;;;N;;;;;
-1F081;DOMINO TILE VERTICAL-04-02;So;0;ON;;;;;N;;;;;
-1F082;DOMINO TILE VERTICAL-04-03;So;0;ON;;;;;N;;;;;
-1F083;DOMINO TILE VERTICAL-04-04;So;0;ON;;;;;N;;;;;
-1F084;DOMINO TILE VERTICAL-04-05;So;0;ON;;;;;N;;;;;
-1F085;DOMINO TILE VERTICAL-04-06;So;0;ON;;;;;N;;;;;
-1F086;DOMINO TILE VERTICAL-05-00;So;0;ON;;;;;N;;;;;
-1F087;DOMINO TILE VERTICAL-05-01;So;0;ON;;;;;N;;;;;
-1F088;DOMINO TILE VERTICAL-05-02;So;0;ON;;;;;N;;;;;
-1F089;DOMINO TILE VERTICAL-05-03;So;0;ON;;;;;N;;;;;
-1F08A;DOMINO TILE VERTICAL-05-04;So;0;ON;;;;;N;;;;;
-1F08B;DOMINO TILE VERTICAL-05-05;So;0;ON;;;;;N;;;;;
-1F08C;DOMINO TILE VERTICAL-05-06;So;0;ON;;;;;N;;;;;
-1F08D;DOMINO TILE VERTICAL-06-00;So;0;ON;;;;;N;;;;;
-1F08E;DOMINO TILE VERTICAL-06-01;So;0;ON;;;;;N;;;;;
-1F08F;DOMINO TILE VERTICAL-06-02;So;0;ON;;;;;N;;;;;
-1F090;DOMINO TILE VERTICAL-06-03;So;0;ON;;;;;N;;;;;
-1F091;DOMINO TILE VERTICAL-06-04;So;0;ON;;;;;N;;;;;
-1F092;DOMINO TILE VERTICAL-06-05;So;0;ON;;;;;N;;;;;
-1F093;DOMINO TILE VERTICAL-06-06;So;0;ON;;;;;N;;;;;
-1F0A0;PLAYING CARD BACK;So;0;ON;;;;;N;;;;;
-1F0A1;PLAYING CARD ACE OF SPADES;So;0;ON;;;;;N;;;;;
-1F0A2;PLAYING CARD TWO OF SPADES;So;0;ON;;;;;N;;;;;
-1F0A3;PLAYING CARD THREE OF SPADES;So;0;ON;;;;;N;;;;;
-1F0A4;PLAYING CARD FOUR OF SPADES;So;0;ON;;;;;N;;;;;
-1F0A5;PLAYING CARD FIVE OF SPADES;So;0;ON;;;;;N;;;;;
-1F0A6;PLAYING CARD SIX OF SPADES;So;0;ON;;;;;N;;;;;
-1F0A7;PLAYING CARD SEVEN OF SPADES;So;0;ON;;;;;N;;;;;
-1F0A8;PLAYING CARD EIGHT OF SPADES;So;0;ON;;;;;N;;;;;
-1F0A9;PLAYING CARD NINE OF SPADES;So;0;ON;;;;;N;;;;;
-1F0AA;PLAYING CARD TEN OF SPADES;So;0;ON;;;;;N;;;;;
-1F0AB;PLAYING CARD JACK OF SPADES;So;0;ON;;;;;N;;;;;
-1F0AC;PLAYING CARD KNIGHT OF SPADES;So;0;ON;;;;;N;;;;;
-1F0AD;PLAYING CARD QUEEN OF SPADES;So;0;ON;;;;;N;;;;;
-1F0AE;PLAYING CARD KING OF SPADES;So;0;ON;;;;;N;;;;;
-1F0B1;PLAYING CARD ACE OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0B2;PLAYING CARD TWO OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0B3;PLAYING CARD THREE OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0B4;PLAYING CARD FOUR OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0B5;PLAYING CARD FIVE OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0B6;PLAYING CARD SIX OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0B7;PLAYING CARD SEVEN OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0B8;PLAYING CARD EIGHT OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0B9;PLAYING CARD NINE OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0BA;PLAYING CARD TEN OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0BB;PLAYING CARD JACK OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0BC;PLAYING CARD KNIGHT OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0BD;PLAYING CARD QUEEN OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0BE;PLAYING CARD KING OF HEARTS;So;0;ON;;;;;N;;;;;
-1F0C1;PLAYING CARD ACE OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0C2;PLAYING CARD TWO OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0C3;PLAYING CARD THREE OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0C4;PLAYING CARD FOUR OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0C5;PLAYING CARD FIVE OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0C6;PLAYING CARD SIX OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0C7;PLAYING CARD SEVEN OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0C8;PLAYING CARD EIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0C9;PLAYING CARD NINE OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0CA;PLAYING CARD TEN OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0CB;PLAYING CARD JACK OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0CC;PLAYING CARD KNIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0CD;PLAYING CARD QUEEN OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0CE;PLAYING CARD KING OF DIAMONDS;So;0;ON;;;;;N;;;;;
-1F0CF;PLAYING CARD BLACK JOKER;So;0;ON;;;;;N;;;;;
-1F0D1;PLAYING CARD ACE OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0D2;PLAYING CARD TWO OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0D3;PLAYING CARD THREE OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0D4;PLAYING CARD FOUR OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0D5;PLAYING CARD FIVE OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0D6;PLAYING CARD SIX OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0D7;PLAYING CARD SEVEN OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0D8;PLAYING CARD EIGHT OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0D9;PLAYING CARD NINE OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0DA;PLAYING CARD TEN OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0DB;PLAYING CARD JACK OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0DC;PLAYING CARD KNIGHT OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0DD;PLAYING CARD QUEEN OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0DE;PLAYING CARD KING OF CLUBS;So;0;ON;;;;;N;;;;;
-1F0DF;PLAYING CARD WHITE JOKER;So;0;ON;;;;;N;;;;;
-1F100;DIGIT ZERO FULL STOP;No;0;EN;<compat> 0030 002E;;0;0;N;;;;;
-1F101;DIGIT ZERO COMMA;No;0;EN;<compat> 0030 002C;;0;0;N;;;;;
-1F102;DIGIT ONE COMMA;No;0;EN;<compat> 0031 002C;;1;1;N;;;;;
-1F103;DIGIT TWO COMMA;No;0;EN;<compat> 0032 002C;;2;2;N;;;;;
-1F104;DIGIT THREE COMMA;No;0;EN;<compat> 0033 002C;;3;3;N;;;;;
-1F105;DIGIT FOUR COMMA;No;0;EN;<compat> 0034 002C;;4;4;N;;;;;
-1F106;DIGIT FIVE COMMA;No;0;EN;<compat> 0035 002C;;5;5;N;;;;;
-1F107;DIGIT SIX COMMA;No;0;EN;<compat> 0036 002C;;6;6;N;;;;;
-1F108;DIGIT SEVEN COMMA;No;0;EN;<compat> 0037 002C;;7;7;N;;;;;
-1F109;DIGIT EIGHT COMMA;No;0;EN;<compat> 0038 002C;;8;8;N;;;;;
-1F10A;DIGIT NINE COMMA;No;0;EN;<compat> 0039 002C;;9;9;N;;;;;
-1F110;PARENTHESIZED LATIN CAPITAL LETTER A;So;0;L;<compat> 0028 0041 0029;;;;N;;;;;
-1F111;PARENTHESIZED LATIN CAPITAL LETTER B;So;0;L;<compat> 0028 0042 0029;;;;N;;;;;
-1F112;PARENTHESIZED LATIN CAPITAL LETTER C;So;0;L;<compat> 0028 0043 0029;;;;N;;;;;
-1F113;PARENTHESIZED LATIN CAPITAL LETTER D;So;0;L;<compat> 0028 0044 0029;;;;N;;;;;
-1F114;PARENTHESIZED LATIN CAPITAL LETTER E;So;0;L;<compat> 0028 0045 0029;;;;N;;;;;
-1F115;PARENTHESIZED LATIN CAPITAL LETTER F;So;0;L;<compat> 0028 0046 0029;;;;N;;;;;
-1F116;PARENTHESIZED LATIN CAPITAL LETTER G;So;0;L;<compat> 0028 0047 0029;;;;N;;;;;
-1F117;PARENTHESIZED LATIN CAPITAL LETTER H;So;0;L;<compat> 0028 0048 0029;;;;N;;;;;
-1F118;PARENTHESIZED LATIN CAPITAL LETTER I;So;0;L;<compat> 0028 0049 0029;;;;N;;;;;
-1F119;PARENTHESIZED LATIN CAPITAL LETTER J;So;0;L;<compat> 0028 004A 0029;;;;N;;;;;
-1F11A;PARENTHESIZED LATIN CAPITAL LETTER K;So;0;L;<compat> 0028 004B 0029;;;;N;;;;;
-1F11B;PARENTHESIZED LATIN CAPITAL LETTER L;So;0;L;<compat> 0028 004C 0029;;;;N;;;;;
-1F11C;PARENTHESIZED LATIN CAPITAL LETTER M;So;0;L;<compat> 0028 004D 0029;;;;N;;;;;
-1F11D;PARENTHESIZED LATIN CAPITAL LETTER N;So;0;L;<compat> 0028 004E 0029;;;;N;;;;;
-1F11E;PARENTHESIZED LATIN CAPITAL LETTER O;So;0;L;<compat> 0028 004F 0029;;;;N;;;;;
-1F11F;PARENTHESIZED LATIN CAPITAL LETTER P;So;0;L;<compat> 0028 0050 0029;;;;N;;;;;
-1F120;PARENTHESIZED LATIN CAPITAL LETTER Q;So;0;L;<compat> 0028 0051 0029;;;;N;;;;;
-1F121;PARENTHESIZED LATIN CAPITAL LETTER R;So;0;L;<compat> 0028 0052 0029;;;;N;;;;;
-1F122;PARENTHESIZED LATIN CAPITAL LETTER S;So;0;L;<compat> 0028 0053 0029;;;;N;;;;;
-1F123;PARENTHESIZED LATIN CAPITAL LETTER T;So;0;L;<compat> 0028 0054 0029;;;;N;;;;;
-1F124;PARENTHESIZED LATIN CAPITAL LETTER U;So;0;L;<compat> 0028 0055 0029;;;;N;;;;;
-1F125;PARENTHESIZED LATIN CAPITAL LETTER V;So;0;L;<compat> 0028 0056 0029;;;;N;;;;;
-1F126;PARENTHESIZED LATIN CAPITAL LETTER W;So;0;L;<compat> 0028 0057 0029;;;;N;;;;;
-1F127;PARENTHESIZED LATIN CAPITAL LETTER X;So;0;L;<compat> 0028 0058 0029;;;;N;;;;;
-1F128;PARENTHESIZED LATIN CAPITAL LETTER Y;So;0;L;<compat> 0028 0059 0029;;;;N;;;;;
-1F129;PARENTHESIZED LATIN CAPITAL LETTER Z;So;0;L;<compat> 0028 005A 0029;;;;N;;;;;
-1F12A;TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S;So;0;L;<compat> 3014 0053 3015;;;;N;;;;;
-1F12B;CIRCLED ITALIC LATIN CAPITAL LETTER C;So;0;L;<circle> 0043;;;;N;;;;;
-1F12C;CIRCLED ITALIC LATIN CAPITAL LETTER R;So;0;L;<circle> 0052;;;;N;;;;;
-1F12D;CIRCLED CD;So;0;L;<circle> 0043 0044;;;;N;;;;;
-1F12E;CIRCLED WZ;So;0;L;<circle> 0057 005A;;;;N;;;;;
-1F130;SQUARED LATIN CAPITAL LETTER A;So;0;L;<square> 0041;;;;N;;;;;
-1F131;SQUARED LATIN CAPITAL LETTER B;So;0;L;<square> 0042;;;;N;;;;;
-1F132;SQUARED LATIN CAPITAL LETTER C;So;0;L;<square> 0043;;;;N;;;;;
-1F133;SQUARED LATIN CAPITAL LETTER D;So;0;L;<square> 0044;;;;N;;;;;
-1F134;SQUARED LATIN CAPITAL LETTER E;So;0;L;<square> 0045;;;;N;;;;;
-1F135;SQUARED LATIN CAPITAL LETTER F;So;0;L;<square> 0046;;;;N;;;;;
-1F136;SQUARED LATIN CAPITAL LETTER G;So;0;L;<square> 0047;;;;N;;;;;
-1F137;SQUARED LATIN CAPITAL LETTER H;So;0;L;<square> 0048;;;;N;;;;;
-1F138;SQUARED LATIN CAPITAL LETTER I;So;0;L;<square> 0049;;;;N;;;;;
-1F139;SQUARED LATIN CAPITAL LETTER J;So;0;L;<square> 004A;;;;N;;;;;
-1F13A;SQUARED LATIN CAPITAL LETTER K;So;0;L;<square> 004B;;;;N;;;;;
-1F13B;SQUARED LATIN CAPITAL LETTER L;So;0;L;<square> 004C;;;;N;;;;;
-1F13C;SQUARED LATIN CAPITAL LETTER M;So;0;L;<square> 004D;;;;N;;;;;
-1F13D;SQUARED LATIN CAPITAL LETTER N;So;0;L;<square> 004E;;;;N;;;;;
-1F13E;SQUARED LATIN CAPITAL LETTER O;So;0;L;<square> 004F;;;;N;;;;;
-1F13F;SQUARED LATIN CAPITAL LETTER P;So;0;L;<square> 0050;;;;N;;;;;
-1F140;SQUARED LATIN CAPITAL LETTER Q;So;0;L;<square> 0051;;;;N;;;;;
-1F141;SQUARED LATIN CAPITAL LETTER R;So;0;L;<square> 0052;;;;N;;;;;
-1F142;SQUARED LATIN CAPITAL LETTER S;So;0;L;<square> 0053;;;;N;;;;;
-1F143;SQUARED LATIN CAPITAL LETTER T;So;0;L;<square> 0054;;;;N;;;;;
-1F144;SQUARED LATIN CAPITAL LETTER U;So;0;L;<square> 0055;;;;N;;;;;
-1F145;SQUARED LATIN CAPITAL LETTER V;So;0;L;<square> 0056;;;;N;;;;;
-1F146;SQUARED LATIN CAPITAL LETTER W;So;0;L;<square> 0057;;;;N;;;;;
-1F147;SQUARED LATIN CAPITAL LETTER X;So;0;L;<square> 0058;;;;N;;;;;
-1F148;SQUARED LATIN CAPITAL LETTER Y;So;0;L;<square> 0059;;;;N;;;;;
-1F149;SQUARED LATIN CAPITAL LETTER Z;So;0;L;<square> 005A;;;;N;;;;;
-1F14A;SQUARED HV;So;0;L;<square> 0048 0056;;;;N;;;;;
-1F14B;SQUARED MV;So;0;L;<square> 004D 0056;;;;N;;;;;
-1F14C;SQUARED SD;So;0;L;<square> 0053 0044;;;;N;;;;;
-1F14D;SQUARED SS;So;0;L;<square> 0053 0053;;;;N;;;;;
-1F14E;SQUARED PPV;So;0;L;<square> 0050 0050 0056;;;;N;;;;;
-1F14F;SQUARED WC;So;0;L;<square> 0057 0043;;;;N;;;;;
-1F150;NEGATIVE CIRCLED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;;
-1F151;NEGATIVE CIRCLED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;;
-1F152;NEGATIVE CIRCLED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;;
-1F153;NEGATIVE CIRCLED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;;
-1F154;NEGATIVE CIRCLED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;;
-1F155;NEGATIVE CIRCLED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;;
-1F156;NEGATIVE CIRCLED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;;
-1F157;NEGATIVE CIRCLED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;;
-1F158;NEGATIVE CIRCLED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;;
-1F159;NEGATIVE CIRCLED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;;
-1F15A;NEGATIVE CIRCLED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;;
-1F15B;NEGATIVE CIRCLED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;;
-1F15C;NEGATIVE CIRCLED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;;
-1F15D;NEGATIVE CIRCLED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;;
-1F15E;NEGATIVE CIRCLED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;;
-1F15F;NEGATIVE CIRCLED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;;
-1F160;NEGATIVE CIRCLED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;;
-1F161;NEGATIVE CIRCLED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;;
-1F162;NEGATIVE CIRCLED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;;
-1F163;NEGATIVE CIRCLED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;;
-1F164;NEGATIVE CIRCLED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;;
-1F165;NEGATIVE CIRCLED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;;
-1F166;NEGATIVE CIRCLED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;;
-1F167;NEGATIVE CIRCLED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;;
-1F168;NEGATIVE CIRCLED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;;
-1F169;NEGATIVE CIRCLED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;;
-1F16A;RAISED MC SIGN;So;0;ON;<super> 004D 0043;;;;N;;;;;
-1F16B;RAISED MD SIGN;So;0;ON;<super> 004D 0044;;;;N;;;;;
-1F170;NEGATIVE SQUARED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;;
-1F171;NEGATIVE SQUARED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;;
-1F172;NEGATIVE SQUARED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;;
-1F173;NEGATIVE SQUARED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;;
-1F174;NEGATIVE SQUARED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;;
-1F175;NEGATIVE SQUARED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;;
-1F176;NEGATIVE SQUARED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;;
-1F177;NEGATIVE SQUARED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;;
-1F178;NEGATIVE SQUARED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;;
-1F179;NEGATIVE SQUARED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;;
-1F17A;NEGATIVE SQUARED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;;
-1F17B;NEGATIVE SQUARED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;;
-1F17C;NEGATIVE SQUARED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;;
-1F17D;NEGATIVE SQUARED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;;
-1F17E;NEGATIVE SQUARED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;;
-1F17F;NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;;
-1F180;NEGATIVE SQUARED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;;
-1F181;NEGATIVE SQUARED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;;
-1F182;NEGATIVE SQUARED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;;
-1F183;NEGATIVE SQUARED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;;
-1F184;NEGATIVE SQUARED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;;
-1F185;NEGATIVE SQUARED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;;
-1F186;NEGATIVE SQUARED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;;
-1F187;NEGATIVE SQUARED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;;
-1F188;NEGATIVE SQUARED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;;
-1F189;NEGATIVE SQUARED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;;
-1F18A;CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;;
-1F18B;NEGATIVE SQUARED IC;So;0;L;;;;;N;;;;;
-1F18C;NEGATIVE SQUARED PA;So;0;L;;;;;N;;;;;
-1F18D;NEGATIVE SQUARED SA;So;0;L;;;;;N;;;;;
-1F18E;NEGATIVE SQUARED AB;So;0;L;;;;;N;;;;;
-1F18F;NEGATIVE SQUARED WC;So;0;L;;;;;N;;;;;
-1F190;SQUARE DJ;So;0;L;<square> 0044 004A;;;;N;;;;;
-1F191;SQUARED CL;So;0;L;;;;;N;;;;;
-1F192;SQUARED COOL;So;0;L;;;;;N;;;;;
-1F193;SQUARED FREE;So;0;L;;;;;N;;;;;
-1F194;SQUARED ID;So;0;L;;;;;N;;;;;
-1F195;SQUARED NEW;So;0;L;;;;;N;;;;;
-1F196;SQUARED NG;So;0;L;;;;;N;;;;;
-1F197;SQUARED OK;So;0;L;;;;;N;;;;;
-1F198;SQUARED SOS;So;0;L;;;;;N;;;;;
-1F199;SQUARED UP WITH EXCLAMATION MARK;So;0;L;;;;;N;;;;;
-1F19A;SQUARED VS;So;0;L;;;;;N;;;;;
-1F1E6;REGIONAL INDICATOR SYMBOL LETTER A;So;0;L;;;;;N;;;;;
-1F1E7;REGIONAL INDICATOR SYMBOL LETTER B;So;0;L;;;;;N;;;;;
-1F1E8;REGIONAL INDICATOR SYMBOL LETTER C;So;0;L;;;;;N;;;;;
-1F1E9;REGIONAL INDICATOR SYMBOL LETTER D;So;0;L;;;;;N;;;;;
-1F1EA;REGIONAL INDICATOR SYMBOL LETTER E;So;0;L;;;;;N;;;;;
-1F1EB;REGIONAL INDICATOR SYMBOL LETTER F;So;0;L;;;;;N;;;;;
-1F1EC;REGIONAL INDICATOR SYMBOL LETTER G;So;0;L;;;;;N;;;;;
-1F1ED;REGIONAL INDICATOR SYMBOL LETTER H;So;0;L;;;;;N;;;;;
-1F1EE;REGIONAL INDICATOR SYMBOL LETTER I;So;0;L;;;;;N;;;;;
-1F1EF;REGIONAL INDICATOR SYMBOL LETTER J;So;0;L;;;;;N;;;;;
-1F1F0;REGIONAL INDICATOR SYMBOL LETTER K;So;0;L;;;;;N;;;;;
-1F1F1;REGIONAL INDICATOR SYMBOL LETTER L;So;0;L;;;;;N;;;;;
-1F1F2;REGIONAL INDICATOR SYMBOL LETTER M;So;0;L;;;;;N;;;;;
-1F1F3;REGIONAL INDICATOR SYMBOL LETTER N;So;0;L;;;;;N;;;;;
-1F1F4;REGIONAL INDICATOR SYMBOL LETTER O;So;0;L;;;;;N;;;;;
-1F1F5;REGIONAL INDICATOR SYMBOL LETTER P;So;0;L;;;;;N;;;;;
-1F1F6;REGIONAL INDICATOR SYMBOL LETTER Q;So;0;L;;;;;N;;;;;
-1F1F7;REGIONAL INDICATOR SYMBOL LETTER R;So;0;L;;;;;N;;;;;
-1F1F8;REGIONAL INDICATOR SYMBOL LETTER S;So;0;L;;;;;N;;;;;
-1F1F9;REGIONAL INDICATOR SYMBOL LETTER T;So;0;L;;;;;N;;;;;
-1F1FA;REGIONAL INDICATOR SYMBOL LETTER U;So;0;L;;;;;N;;;;;
-1F1FB;REGIONAL INDICATOR SYMBOL LETTER V;So;0;L;;;;;N;;;;;
-1F1FC;REGIONAL INDICATOR SYMBOL LETTER W;So;0;L;;;;;N;;;;;
-1F1FD;REGIONAL INDICATOR SYMBOL LETTER X;So;0;L;;;;;N;;;;;
-1F1FE;REGIONAL INDICATOR SYMBOL LETTER Y;So;0;L;;;;;N;;;;;
-1F1FF;REGIONAL INDICATOR SYMBOL LETTER Z;So;0;L;;;;;N;;;;;
-1F200;SQUARE HIRAGANA HOKA;So;0;L;<square> 307B 304B;;;;N;;;;;
-1F201;SQUARED KATAKANA KOKO;So;0;L;<square> 30B3 30B3;;;;N;;;;;
-1F202;SQUARED KATAKANA SA;So;0;L;<square> 30B5;;;;N;;;;;
-1F210;SQUARED CJK UNIFIED IDEOGRAPH-624B;So;0;L;<square> 624B;;;;N;;;;;
-1F211;SQUARED CJK UNIFIED IDEOGRAPH-5B57;So;0;L;<square> 5B57;;;;N;;;;;
-1F212;SQUARED CJK UNIFIED IDEOGRAPH-53CC;So;0;L;<square> 53CC;;;;N;;;;;
-1F213;SQUARED KATAKANA DE;So;0;L;<square> 30C7;;;;N;;;;;
-1F214;SQUARED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L;<square> 4E8C;;;;N;;;;;
-1F215;SQUARED CJK UNIFIED IDEOGRAPH-591A;So;0;L;<square> 591A;;;;N;;;;;
-1F216;SQUARED CJK UNIFIED IDEOGRAPH-89E3;So;0;L;<square> 89E3;;;;N;;;;;
-1F217;SQUARED CJK UNIFIED IDEOGRAPH-5929;So;0;L;<square> 5929;;;;N;;;;;
-1F218;SQUARED CJK UNIFIED IDEOGRAPH-4EA4;So;0;L;<square> 4EA4;;;;N;;;;;
-1F219;SQUARED CJK UNIFIED IDEOGRAPH-6620;So;0;L;<square> 6620;;;;N;;;;;
-1F21A;SQUARED CJK UNIFIED IDEOGRAPH-7121;So;0;L;<square> 7121;;;;N;;;;;
-1F21B;SQUARED CJK UNIFIED IDEOGRAPH-6599;So;0;L;<square> 6599;;;;N;;;;;
-1F21C;SQUARED CJK UNIFIED IDEOGRAPH-524D;So;0;L;<square> 524D;;;;N;;;;;
-1F21D;SQUARED CJK UNIFIED IDEOGRAPH-5F8C;So;0;L;<square> 5F8C;;;;N;;;;;
-1F21E;SQUARED CJK UNIFIED IDEOGRAPH-518D;So;0;L;<square> 518D;;;;N;;;;;
-1F21F;SQUARED CJK UNIFIED IDEOGRAPH-65B0;So;0;L;<square> 65B0;;;;N;;;;;
-1F220;SQUARED CJK UNIFIED IDEOGRAPH-521D;So;0;L;<square> 521D;;;;N;;;;;
-1F221;SQUARED CJK UNIFIED IDEOGRAPH-7D42;So;0;L;<square> 7D42;;;;N;;;;;
-1F222;SQUARED CJK UNIFIED IDEOGRAPH-751F;So;0;L;<square> 751F;;;;N;;;;;
-1F223;SQUARED CJK UNIFIED IDEOGRAPH-8CA9;So;0;L;<square> 8CA9;;;;N;;;;;
-1F224;SQUARED CJK UNIFIED IDEOGRAPH-58F0;So;0;L;<square> 58F0;;;;N;;;;;
-1F225;SQUARED CJK UNIFIED IDEOGRAPH-5439;So;0;L;<square> 5439;;;;N;;;;;
-1F226;SQUARED CJK UNIFIED IDEOGRAPH-6F14;So;0;L;<square> 6F14;;;;N;;;;;
-1F227;SQUARED CJK UNIFIED IDEOGRAPH-6295;So;0;L;<square> 6295;;;;N;;;;;
-1F228;SQUARED CJK UNIFIED IDEOGRAPH-6355;So;0;L;<square> 6355;;;;N;;;;;
-1F229;SQUARED CJK UNIFIED IDEOGRAPH-4E00;So;0;L;<square> 4E00;;;;N;;;;;
-1F22A;SQUARED CJK UNIFIED IDEOGRAPH-4E09;So;0;L;<square> 4E09;;;;N;;;;;
-1F22B;SQUARED CJK UNIFIED IDEOGRAPH-904A;So;0;L;<square> 904A;;;;N;;;;;
-1F22C;SQUARED CJK UNIFIED IDEOGRAPH-5DE6;So;0;L;<square> 5DE6;;;;N;;;;;
-1F22D;SQUARED CJK UNIFIED IDEOGRAPH-4E2D;So;0;L;<square> 4E2D;;;;N;;;;;
-1F22E;SQUARED CJK UNIFIED IDEOGRAPH-53F3;So;0;L;<square> 53F3;;;;N;;;;;
-1F22F;SQUARED CJK UNIFIED IDEOGRAPH-6307;So;0;L;<square> 6307;;;;N;;;;;
-1F230;SQUARED CJK UNIFIED IDEOGRAPH-8D70;So;0;L;<square> 8D70;;;;N;;;;;
-1F231;SQUARED CJK UNIFIED IDEOGRAPH-6253;So;0;L;<square> 6253;;;;N;;;;;
-1F232;SQUARED CJK UNIFIED IDEOGRAPH-7981;So;0;L;<square> 7981;;;;N;;;;;
-1F233;SQUARED CJK UNIFIED IDEOGRAPH-7A7A;So;0;L;<square> 7A7A;;;;N;;;;;
-1F234;SQUARED CJK UNIFIED IDEOGRAPH-5408;So;0;L;<square> 5408;;;;N;;;;;
-1F235;SQUARED CJK UNIFIED IDEOGRAPH-6E80;So;0;L;<square> 6E80;;;;N;;;;;
-1F236;SQUARED CJK UNIFIED IDEOGRAPH-6709;So;0;L;<square> 6709;;;;N;;;;;
-1F237;SQUARED CJK UNIFIED IDEOGRAPH-6708;So;0;L;<square> 6708;;;;N;;;;;
-1F238;SQUARED CJK UNIFIED IDEOGRAPH-7533;So;0;L;<square> 7533;;;;N;;;;;
-1F239;SQUARED CJK UNIFIED IDEOGRAPH-5272;So;0;L;<square> 5272;;;;N;;;;;
-1F23A;SQUARED CJK UNIFIED IDEOGRAPH-55B6;So;0;L;<square> 55B6;;;;N;;;;;
-1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L;<compat> 3014 672C 3015;;;;N;;;;;
-1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L;<compat> 3014 4E09 3015;;;;N;;;;;
-1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L;<compat> 3014 4E8C 3015;;;;N;;;;;
-1F243;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89;So;0;L;<compat> 3014 5B89 3015;;;;N;;;;;
-1F244;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9;So;0;L;<compat> 3014 70B9 3015;;;;N;;;;;
-1F245;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253;So;0;L;<compat> 3014 6253 3015;;;;N;;;;;
-1F246;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7;So;0;L;<compat> 3014 76D7 3015;;;;N;;;;;
-1F247;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD;So;0;L;<compat> 3014 52DD 3015;;;;N;;;;;
-1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L;<compat> 3014 6557 3015;;;;N;;;;;
-1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L;<circle> 5F97;;;;N;;;;;
-1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L;<circle> 53EF;;;;N;;;;;
-1F300;CYCLONE;So;0;ON;;;;;N;;;;;
-1F301;FOGGY;So;0;ON;;;;;N;;;;;
-1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;;
-1F303;NIGHT WITH STARS;So;0;ON;;;;;N;;;;;
-1F304;SUNRISE OVER MOUNTAINS;So;0;ON;;;;;N;;;;;
-1F305;SUNRISE;So;0;ON;;;;;N;;;;;
-1F306;CITYSCAPE AT DUSK;So;0;ON;;;;;N;;;;;
-1F307;SUNSET OVER BUILDINGS;So;0;ON;;;;;N;;;;;
-1F308;RAINBOW;So;0;ON;;;;;N;;;;;
-1F309;BRIDGE AT NIGHT;So;0;ON;;;;;N;;;;;
-1F30A;WATER WAVE;So;0;ON;;;;;N;;;;;
-1F30B;VOLCANO;So;0;ON;;;;;N;;;;;
-1F30C;MILKY WAY;So;0;ON;;;;;N;;;;;
-1F30D;EARTH GLOBE EUROPE-AFRICA;So;0;ON;;;;;N;;;;;
-1F30E;EARTH GLOBE AMERICAS;So;0;ON;;;;;N;;;;;
-1F30F;EARTH GLOBE ASIA-AUSTRALIA;So;0;ON;;;;;N;;;;;
-1F310;GLOBE WITH MERIDIANS;So;0;ON;;;;;N;;;;;
-1F311;NEW MOON SYMBOL;So;0;ON;;;;;N;;;;;
-1F312;WAXING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;;
-1F313;FIRST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;;
-1F314;WAXING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;;
-1F315;FULL MOON SYMBOL;So;0;ON;;;;;N;;;;;
-1F316;WANING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;;
-1F317;LAST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;;
-1F318;WANING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;;
-1F319;CRESCENT MOON;So;0;ON;;;;;N;;;;;
-1F31A;NEW MOON WITH FACE;So;0;ON;;;;;N;;;;;
-1F31B;FIRST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;;
-1F31C;LAST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;;
-1F31D;FULL MOON WITH FACE;So;0;ON;;;;;N;;;;;
-1F31E;SUN WITH FACE;So;0;ON;;;;;N;;;;;
-1F31F;GLOWING STAR;So;0;ON;;;;;N;;;;;
-1F320;SHOOTING STAR;So;0;ON;;;;;N;;;;;
-1F330;CHESTNUT;So;0;ON;;;;;N;;;;;
-1F331;SEEDLING;So;0;ON;;;;;N;;;;;
-1F332;EVERGREEN TREE;So;0;ON;;;;;N;;;;;
-1F333;DECIDUOUS TREE;So;0;ON;;;;;N;;;;;
-1F334;PALM TREE;So;0;ON;;;;;N;;;;;
-1F335;CACTUS;So;0;ON;;;;;N;;;;;
-1F337;TULIP;So;0;ON;;;;;N;;;;;
-1F338;CHERRY BLOSSOM;So;0;ON;;;;;N;;;;;
-1F339;ROSE;So;0;ON;;;;;N;;;;;
-1F33A;HIBISCUS;So;0;ON;;;;;N;;;;;
-1F33B;SUNFLOWER;So;0;ON;;;;;N;;;;;
-1F33C;BLOSSOM;So;0;ON;;;;;N;;;;;
-1F33D;EAR OF MAIZE;So;0;ON;;;;;N;;;;;
-1F33E;EAR OF RICE;So;0;ON;;;;;N;;;;;
-1F33F;HERB;So;0;ON;;;;;N;;;;;
-1F340;FOUR LEAF CLOVER;So;0;ON;;;;;N;;;;;
-1F341;MAPLE LEAF;So;0;ON;;;;;N;;;;;
-1F342;FALLEN LEAF;So;0;ON;;;;;N;;;;;
-1F343;LEAF FLUTTERING IN WIND;So;0;ON;;;;;N;;;;;
-1F344;MUSHROOM;So;0;ON;;;;;N;;;;;
-1F345;TOMATO;So;0;ON;;;;;N;;;;;
-1F346;AUBERGINE;So;0;ON;;;;;N;;;;;
-1F347;GRAPES;So;0;ON;;;;;N;;;;;
-1F348;MELON;So;0;ON;;;;;N;;;;;
-1F349;WATERMELON;So;0;ON;;;;;N;;;;;
-1F34A;TANGERINE;So;0;ON;;;;;N;;;;;
-1F34B;LEMON;So;0;ON;;;;;N;;;;;
-1F34C;BANANA;So;0;ON;;;;;N;;;;;
-1F34D;PINEAPPLE;So;0;ON;;;;;N;;;;;
-1F34E;RED APPLE;So;0;ON;;;;;N;;;;;
-1F34F;GREEN APPLE;So;0;ON;;;;;N;;;;;
-1F350;PEAR;So;0;ON;;;;;N;;;;;
-1F351;PEACH;So;0;ON;;;;;N;;;;;
-1F352;CHERRIES;So;0;ON;;;;;N;;;;;
-1F353;STRAWBERRY;So;0;ON;;;;;N;;;;;
-1F354;HAMBURGER;So;0;ON;;;;;N;;;;;
-1F355;SLICE OF PIZZA;So;0;ON;;;;;N;;;;;
-1F356;MEAT ON BONE;So;0;ON;;;;;N;;;;;
-1F357;POULTRY LEG;So;0;ON;;;;;N;;;;;
-1F358;RICE CRACKER;So;0;ON;;;;;N;;;;;
-1F359;RICE BALL;So;0;ON;;;;;N;;;;;
-1F35A;COOKED RICE;So;0;ON;;;;;N;;;;;
-1F35B;CURRY AND RICE;So;0;ON;;;;;N;;;;;
-1F35C;STEAMING BOWL;So;0;ON;;;;;N;;;;;
-1F35D;SPAGHETTI;So;0;ON;;;;;N;;;;;
-1F35E;BREAD;So;0;ON;;;;;N;;;;;
-1F35F;FRENCH FRIES;So;0;ON;;;;;N;;;;;
-1F360;ROASTED SWEET POTATO;So;0;ON;;;;;N;;;;;
-1F361;DANGO;So;0;ON;;;;;N;;;;;
-1F362;ODEN;So;0;ON;;;;;N;;;;;
-1F363;SUSHI;So;0;ON;;;;;N;;;;;
-1F364;FRIED SHRIMP;So;0;ON;;;;;N;;;;;
-1F365;FISH CAKE WITH SWIRL DESIGN;So;0;ON;;;;;N;;;;;
-1F366;SOFT ICE CREAM;So;0;ON;;;;;N;;;;;
-1F367;SHAVED ICE;So;0;ON;;;;;N;;;;;
-1F368;ICE CREAM;So;0;ON;;;;;N;;;;;
-1F369;DOUGHNUT;So;0;ON;;;;;N;;;;;
-1F36A;COOKIE;So;0;ON;;;;;N;;;;;
-1F36B;CHOCOLATE BAR;So;0;ON;;;;;N;;;;;
-1F36C;CANDY;So;0;ON;;;;;N;;;;;
-1F36D;LOLLIPOP;So;0;ON;;;;;N;;;;;
-1F36E;CUSTARD;So;0;ON;;;;;N;;;;;
-1F36F;HONEY POT;So;0;ON;;;;;N;;;;;
-1F370;SHORTCAKE;So;0;ON;;;;;N;;;;;
-1F371;BENTO BOX;So;0;ON;;;;;N;;;;;
-1F372;POT OF FOOD;So;0;ON;;;;;N;;;;;
-1F373;COOKING;So;0;ON;;;;;N;;;;;
-1F374;FORK AND KNIFE;So;0;ON;;;;;N;;;;;
-1F375;TEACUP WITHOUT HANDLE;So;0;ON;;;;;N;;;;;
-1F376;SAKE BOTTLE AND CUP;So;0;ON;;;;;N;;;;;
-1F377;WINE GLASS;So;0;ON;;;;;N;;;;;
-1F378;COCKTAIL GLASS;So;0;ON;;;;;N;;;;;
-1F379;TROPICAL DRINK;So;0;ON;;;;;N;;;;;
-1F37A;BEER MUG;So;0;ON;;;;;N;;;;;
-1F37B;CLINKING BEER MUGS;So;0;ON;;;;;N;;;;;
-1F37C;BABY BOTTLE;So;0;ON;;;;;N;;;;;
-1F380;RIBBON;So;0;ON;;;;;N;;;;;
-1F381;WRAPPED PRESENT;So;0;ON;;;;;N;;;;;
-1F382;BIRTHDAY CAKE;So;0;ON;;;;;N;;;;;
-1F383;JACK-O-LANTERN;So;0;ON;;;;;N;;;;;
-1F384;CHRISTMAS TREE;So;0;ON;;;;;N;;;;;
-1F385;FATHER CHRISTMAS;So;0;ON;;;;;N;;;;;
-1F386;FIREWORKS;So;0;ON;;;;;N;;;;;
-1F387;FIREWORK SPARKLER;So;0;ON;;;;;N;;;;;
-1F388;BALLOON;So;0;ON;;;;;N;;;;;
-1F389;PARTY POPPER;So;0;ON;;;;;N;;;;;
-1F38A;CONFETTI BALL;So;0;ON;;;;;N;;;;;
-1F38B;TANABATA TREE;So;0;ON;;;;;N;;;;;
-1F38C;CROSSED FLAGS;So;0;ON;;;;;N;;;;;
-1F38D;PINE DECORATION;So;0;ON;;;;;N;;;;;
-1F38E;JAPANESE DOLLS;So;0;ON;;;;;N;;;;;
-1F38F;CARP STREAMER;So;0;ON;;;;;N;;;;;
-1F390;WIND CHIME;So;0;ON;;;;;N;;;;;
-1F391;MOON VIEWING CEREMONY;So;0;ON;;;;;N;;;;;
-1F392;SCHOOL SATCHEL;So;0;ON;;;;;N;;;;;
-1F393;GRADUATION CAP;So;0;ON;;;;;N;;;;;
-1F3A0;CAROUSEL HORSE;So;0;ON;;;;;N;;;;;
-1F3A1;FERRIS WHEEL;So;0;ON;;;;;N;;;;;
-1F3A2;ROLLER COASTER;So;0;ON;;;;;N;;;;;
-1F3A3;FISHING POLE AND FISH;So;0;ON;;;;;N;;;;;
-1F3A4;MICROPHONE;So;0;ON;;;;;N;;;;;
-1F3A5;MOVIE CAMERA;So;0;ON;;;;;N;;;;;
-1F3A6;CINEMA;So;0;ON;;;;;N;;;;;
-1F3A7;HEADPHONE;So;0;ON;;;;;N;;;;;
-1F3A8;ARTIST PALETTE;So;0;ON;;;;;N;;;;;
-1F3A9;TOP HAT;So;0;ON;;;;;N;;;;;
-1F3AA;CIRCUS TENT;So;0;ON;;;;;N;;;;;
-1F3AB;TICKET;So;0;ON;;;;;N;;;;;
-1F3AC;CLAPPER BOARD;So;0;ON;;;;;N;;;;;
-1F3AD;PERFORMING ARTS;So;0;ON;;;;;N;;;;;
-1F3AE;VIDEO GAME;So;0;ON;;;;;N;;;;;
-1F3AF;DIRECT HIT;So;0;ON;;;;;N;;;;;
-1F3B0;SLOT MACHINE;So;0;ON;;;;;N;;;;;
-1F3B1;BILLIARDS;So;0;ON;;;;;N;;;;;
-1F3B2;GAME DIE;So;0;ON;;;;;N;;;;;
-1F3B3;BOWLING;So;0;ON;;;;;N;;;;;
-1F3B4;FLOWER PLAYING CARDS;So;0;ON;;;;;N;;;;;
-1F3B5;MUSICAL NOTE;So;0;ON;;;;;N;;;;;
-1F3B6;MULTIPLE MUSICAL NOTES;So;0;ON;;;;;N;;;;;
-1F3B7;SAXOPHONE;So;0;ON;;;;;N;;;;;
-1F3B8;GUITAR;So;0;ON;;;;;N;;;;;
-1F3B9;MUSICAL KEYBOARD;So;0;ON;;;;;N;;;;;
-1F3BA;TRUMPET;So;0;ON;;;;;N;;;;;
-1F3BB;VIOLIN;So;0;ON;;;;;N;;;;;
-1F3BC;MUSICAL SCORE;So;0;ON;;;;;N;;;;;
-1F3BD;RUNNING SHIRT WITH SASH;So;0;ON;;;;;N;;;;;
-1F3BE;TENNIS RACQUET AND BALL;So;0;ON;;;;;N;;;;;
-1F3BF;SKI AND SKI BOOT;So;0;ON;;;;;N;;;;;
-1F3C0;BASKETBALL AND HOOP;So;0;ON;;;;;N;;;;;
-1F3C1;CHEQUERED FLAG;So;0;ON;;;;;N;;;;;
-1F3C2;SNOWBOARDER;So;0;ON;;;;;N;;;;;
-1F3C3;RUNNER;So;0;ON;;;;;N;;;;;
-1F3C4;SURFER;So;0;ON;;;;;N;;;;;
-1F3C6;TROPHY;So;0;ON;;;;;N;;;;;
-1F3C7;HORSE RACING;So;0;ON;;;;;N;;;;;
-1F3C8;AMERICAN FOOTBALL;So;0;ON;;;;;N;;;;;
-1F3C9;RUGBY FOOTBALL;So;0;ON;;;;;N;;;;;
-1F3CA;SWIMMER;So;0;ON;;;;;N;;;;;
-1F3E0;HOUSE BUILDING;So;0;ON;;;;;N;;;;;
-1F3E1;HOUSE WITH GARDEN;So;0;ON;;;;;N;;;;;
-1F3E2;OFFICE BUILDING;So;0;ON;;;;;N;;;;;
-1F3E3;JAPANESE POST OFFICE;So;0;ON;;;;;N;;;;;
-1F3E4;EUROPEAN POST OFFICE;So;0;ON;;;;;N;;;;;
-1F3E5;HOSPITAL;So;0;ON;;;;;N;;;;;
-1F3E6;BANK;So;0;ON;;;;;N;;;;;
-1F3E7;AUTOMATED TELLER MACHINE;So;0;ON;;;;;N;;;;;
-1F3E8;HOTEL;So;0;ON;;;;;N;;;;;
-1F3E9;LOVE HOTEL;So;0;ON;;;;;N;;;;;
-1F3EA;CONVENIENCE STORE;So;0;ON;;;;;N;;;;;
-1F3EB;SCHOOL;So;0;ON;;;;;N;;;;;
-1F3EC;DEPARTMENT STORE;So;0;ON;;;;;N;;;;;
-1F3ED;FACTORY;So;0;ON;;;;;N;;;;;
-1F3EE;IZAKAYA LANTERN;So;0;ON;;;;;N;;;;;
-1F3EF;JAPANESE CASTLE;So;0;ON;;;;;N;;;;;
-1F3F0;EUROPEAN CASTLE;So;0;ON;;;;;N;;;;;
-1F400;RAT;So;0;ON;;;;;N;;;;;
-1F401;MOUSE;So;0;ON;;;;;N;;;;;
-1F402;OX;So;0;ON;;;;;N;;;;;
-1F403;WATER BUFFALO;So;0;ON;;;;;N;;;;;
-1F404;COW;So;0;ON;;;;;N;;;;;
-1F405;TIGER;So;0;ON;;;;;N;;;;;
-1F406;LEOPARD;So;0;ON;;;;;N;;;;;
-1F407;RABBIT;So;0;ON;;;;;N;;;;;
-1F408;CAT;So;0;ON;;;;;N;;;;;
-1F409;DRAGON;So;0;ON;;;;;N;;;;;
-1F40A;CROCODILE;So;0;ON;;;;;N;;;;;
-1F40B;WHALE;So;0;ON;;;;;N;;;;;
-1F40C;SNAIL;So;0;ON;;;;;N;;;;;
-1F40D;SNAKE;So;0;ON;;;;;N;;;;;
-1F40E;HORSE;So;0;ON;;;;;N;;;;;
-1F40F;RAM;So;0;ON;;;;;N;;;;;
-1F410;GOAT;So;0;ON;;;;;N;;;;;
-1F411;SHEEP;So;0;ON;;;;;N;;;;;
-1F412;MONKEY;So;0;ON;;;;;N;;;;;
-1F413;ROOSTER;So;0;ON;;;;;N;;;;;
-1F414;CHICKEN;So;0;ON;;;;;N;;;;;
-1F415;DOG;So;0;ON;;;;;N;;;;;
-1F416;PIG;So;0;ON;;;;;N;;;;;
-1F417;BOAR;So;0;ON;;;;;N;;;;;
-1F418;ELEPHANT;So;0;ON;;;;;N;;;;;
-1F419;OCTOPUS;So;0;ON;;;;;N;;;;;
-1F41A;SPIRAL SHELL;So;0;ON;;;;;N;;;;;
-1F41B;BUG;So;0;ON;;;;;N;;;;;
-1F41C;ANT;So;0;ON;;;;;N;;;;;
-1F41D;HONEYBEE;So;0;ON;;;;;N;;;;;
-1F41E;LADY BEETLE;So;0;ON;;;;;N;;;;;
-1F41F;FISH;So;0;ON;;;;;N;;;;;
-1F420;TROPICAL FISH;So;0;ON;;;;;N;;;;;
-1F421;BLOWFISH;So;0;ON;;;;;N;;;;;
-1F422;TURTLE;So;0;ON;;;;;N;;;;;
-1F423;HATCHING CHICK;So;0;ON;;;;;N;;;;;
-1F424;BABY CHICK;So;0;ON;;;;;N;;;;;
-1F425;FRONT-FACING BABY CHICK;So;0;ON;;;;;N;;;;;
-1F426;BIRD;So;0;ON;;;;;N;;;;;
-1F427;PENGUIN;So;0;ON;;;;;N;;;;;
-1F428;KOALA;So;0;ON;;;;;N;;;;;
-1F429;POODLE;So;0;ON;;;;;N;;;;;
-1F42A;DROMEDARY CAMEL;So;0;ON;;;;;N;;;;;
-1F42B;BACTRIAN CAMEL;So;0;ON;;;;;N;;;;;
-1F42C;DOLPHIN;So;0;ON;;;;;N;;;;;
-1F42D;MOUSE FACE;So;0;ON;;;;;N;;;;;
-1F42E;COW FACE;So;0;ON;;;;;N;;;;;
-1F42F;TIGER FACE;So;0;ON;;;;;N;;;;;
-1F430;RABBIT FACE;So;0;ON;;;;;N;;;;;
-1F431;CAT FACE;So;0;ON;;;;;N;;;;;
-1F432;DRAGON FACE;So;0;ON;;;;;N;;;;;
-1F433;SPOUTING WHALE;So;0;ON;;;;;N;;;;;
-1F434;HORSE FACE;So;0;ON;;;;;N;;;;;
-1F435;MONKEY FACE;So;0;ON;;;;;N;;;;;
-1F436;DOG FACE;So;0;ON;;;;;N;;;;;
-1F437;PIG FACE;So;0;ON;;;;;N;;;;;
-1F438;FROG FACE;So;0;ON;;;;;N;;;;;
-1F439;HAMSTER FACE;So;0;ON;;;;;N;;;;;
-1F43A;WOLF FACE;So;0;ON;;;;;N;;;;;
-1F43B;BEAR FACE;So;0;ON;;;;;N;;;;;
-1F43C;PANDA FACE;So;0;ON;;;;;N;;;;;
-1F43D;PIG NOSE;So;0;ON;;;;;N;;;;;
-1F43E;PAW PRINTS;So;0;ON;;;;;N;;;;;
-1F440;EYES;So;0;ON;;;;;N;;;;;
-1F442;EAR;So;0;ON;;;;;N;;;;;
-1F443;NOSE;So;0;ON;;;;;N;;;;;
-1F444;MOUTH;So;0;ON;;;;;N;;;;;
-1F445;TONGUE;So;0;ON;;;;;N;;;;;
-1F446;WHITE UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;;
-1F447;WHITE DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;;
-1F448;WHITE LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;;
-1F449;WHITE RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;;
-1F44A;FISTED HAND SIGN;So;0;ON;;;;;N;;;;;
-1F44B;WAVING HAND SIGN;So;0;ON;;;;;N;;;;;
-1F44C;OK HAND SIGN;So;0;ON;;;;;N;;;;;
-1F44D;THUMBS UP SIGN;So;0;ON;;;;;N;;;;;
-1F44E;THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;;
-1F44F;CLAPPING HANDS SIGN;So;0;ON;;;;;N;;;;;
-1F450;OPEN HANDS SIGN;So;0;ON;;;;;N;;;;;
-1F451;CROWN;So;0;ON;;;;;N;;;;;
-1F452;WOMANS HAT;So;0;ON;;;;;N;;;;;
-1F453;EYEGLASSES;So;0;ON;;;;;N;;;;;
-1F454;NECKTIE;So;0;ON;;;;;N;;;;;
-1F455;T-SHIRT;So;0;ON;;;;;N;;;;;
-1F456;JEANS;So;0;ON;;;;;N;;;;;
-1F457;DRESS;So;0;ON;;;;;N;;;;;
-1F458;KIMONO;So;0;ON;;;;;N;;;;;
-1F459;BIKINI;So;0;ON;;;;;N;;;;;
-1F45A;WOMANS CLOTHES;So;0;ON;;;;;N;;;;;
-1F45B;PURSE;So;0;ON;;;;;N;;;;;
-1F45C;HANDBAG;So;0;ON;;;;;N;;;;;
-1F45D;POUCH;So;0;ON;;;;;N;;;;;
-1F45E;MANS SHOE;So;0;ON;;;;;N;;;;;
-1F45F;ATHLETIC SHOE;So;0;ON;;;;;N;;;;;
-1F460;HIGH-HEELED SHOE;So;0;ON;;;;;N;;;;;
-1F461;WOMANS SANDAL;So;0;ON;;;;;N;;;;;
-1F462;WOMANS BOOTS;So;0;ON;;;;;N;;;;;
-1F463;FOOTPRINTS;So;0;ON;;;;;N;;;;;
-1F464;BUST IN SILHOUETTE;So;0;ON;;;;;N;;;;;
-1F465;BUSTS IN SILHOUETTE;So;0;ON;;;;;N;;;;;
-1F466;BOY;So;0;ON;;;;;N;;;;;
-1F467;GIRL;So;0;ON;;;;;N;;;;;
-1F468;MAN;So;0;ON;;;;;N;;;;;
-1F469;WOMAN;So;0;ON;;;;;N;;;;;
-1F46A;FAMILY;So;0;ON;;;;;N;;;;;
-1F46B;MAN AND WOMAN HOLDING HANDS;So;0;ON;;;;;N;;;;;
-1F46C;TWO MEN HOLDING HANDS;So;0;ON;;;;;N;;;;;
-1F46D;TWO WOMEN HOLDING HANDS;So;0;ON;;;;;N;;;;;
-1F46E;POLICE OFFICER;So;0;ON;;;;;N;;;;;
-1F46F;WOMAN WITH BUNNY EARS;So;0;ON;;;;;N;;;;;
-1F470;BRIDE WITH VEIL;So;0;ON;;;;;N;;;;;
-1F471;PERSON WITH BLOND HAIR;So;0;ON;;;;;N;;;;;
-1F472;MAN WITH GUA PI MAO;So;0;ON;;;;;N;;;;;
-1F473;MAN WITH TURBAN;So;0;ON;;;;;N;;;;;
-1F474;OLDER MAN;So;0;ON;;;;;N;;;;;
-1F475;OLDER WOMAN;So;0;ON;;;;;N;;;;;
-1F476;BABY;So;0;ON;;;;;N;;;;;
-1F477;CONSTRUCTION WORKER;So;0;ON;;;;;N;;;;;
-1F478;PRINCESS;So;0;ON;;;;;N;;;;;
-1F479;JAPANESE OGRE;So;0;ON;;;;;N;;;;;
-1F47A;JAPANESE GOBLIN;So;0;ON;;;;;N;;;;;
-1F47B;GHOST;So;0;ON;;;;;N;;;;;
-1F47C;BABY ANGEL;So;0;ON;;;;;N;;;;;
-1F47D;EXTRATERRESTRIAL ALIEN;So;0;ON;;;;;N;;;;;
-1F47E;ALIEN MONSTER;So;0;ON;;;;;N;;;;;
-1F47F;IMP;So;0;ON;;;;;N;;;;;
-1F480;SKULL;So;0;ON;;;;;N;;;;;
-1F481;INFORMATION DESK PERSON;So;0;ON;;;;;N;;;;;
-1F482;GUARDSMAN;So;0;ON;;;;;N;;;;;
-1F483;DANCER;So;0;ON;;;;;N;;;;;
-1F484;LIPSTICK;So;0;ON;;;;;N;;;;;
-1F485;NAIL POLISH;So;0;ON;;;;;N;;;;;
-1F486;FACE MASSAGE;So;0;ON;;;;;N;;;;;
-1F487;HAIRCUT;So;0;ON;;;;;N;;;;;
-1F488;BARBER POLE;So;0;ON;;;;;N;;;;;
-1F489;SYRINGE;So;0;ON;;;;;N;;;;;
-1F48A;PILL;So;0;ON;;;;;N;;;;;
-1F48B;KISS MARK;So;0;ON;;;;;N;;;;;
-1F48C;LOVE LETTER;So;0;ON;;;;;N;;;;;
-1F48D;RING;So;0;ON;;;;;N;;;;;
-1F48E;GEM STONE;So;0;ON;;;;;N;;;;;
-1F48F;KISS;So;0;ON;;;;;N;;;;;
-1F490;BOUQUET;So;0;ON;;;;;N;;;;;
-1F491;COUPLE WITH HEART;So;0;ON;;;;;N;;;;;
-1F492;WEDDING;So;0;ON;;;;;N;;;;;
-1F493;BEATING HEART;So;0;ON;;;;;N;;;;;
-1F494;BROKEN HEART;So;0;ON;;;;;N;;;;;
-1F495;TWO HEARTS;So;0;ON;;;;;N;;;;;
-1F496;SPARKLING HEART;So;0;ON;;;;;N;;;;;
-1F497;GROWING HEART;So;0;ON;;;;;N;;;;;
-1F498;HEART WITH ARROW;So;0;ON;;;;;N;;;;;
-1F499;BLUE HEART;So;0;ON;;;;;N;;;;;
-1F49A;GREEN HEART;So;0;ON;;;;;N;;;;;
-1F49B;YELLOW HEART;So;0;ON;;;;;N;;;;;
-1F49C;PURPLE HEART;So;0;ON;;;;;N;;;;;
-1F49D;HEART WITH RIBBON;So;0;ON;;;;;N;;;;;
-1F49E;REVOLVING HEARTS;So;0;ON;;;;;N;;;;;
-1F49F;HEART DECORATION;So;0;ON;;;;;N;;;;;
-1F4A0;DIAMOND SHAPE WITH A DOT INSIDE;So;0;ON;;;;;N;;;;;
-1F4A1;ELECTRIC LIGHT BULB;So;0;ON;;;;;N;;;;;
-1F4A2;ANGER SYMBOL;So;0;ON;;;;;N;;;;;
-1F4A3;BOMB;So;0;ON;;;;;N;;;;;
-1F4A4;SLEEPING SYMBOL;So;0;ON;;;;;N;;;;;
-1F4A5;COLLISION SYMBOL;So;0;ON;;;;;N;;;;;
-1F4A6;SPLASHING SWEAT SYMBOL;So;0;ON;;;;;N;;;;;
-1F4A7;DROPLET;So;0;ON;;;;;N;;;;;
-1F4A8;DASH SYMBOL;So;0;ON;;;;;N;;;;;
-1F4A9;PILE OF POO;So;0;ON;;;;;N;;;;;
-1F4AA;FLEXED BICEPS;So;0;ON;;;;;N;;;;;
-1F4AB;DIZZY SYMBOL;So;0;ON;;;;;N;;;;;
-1F4AC;SPEECH BALLOON;So;0;ON;;;;;N;;;;;
-1F4AD;THOUGHT BALLOON;So;0;ON;;;;;N;;;;;
-1F4AE;WHITE FLOWER;So;0;ON;;;;;N;;;;;
-1F4AF;HUNDRED POINTS SYMBOL;So;0;ON;;;;;N;;;;;
-1F4B0;MONEY BAG;So;0;ON;;;;;N;;;;;
-1F4B1;CURRENCY EXCHANGE;So;0;ON;;;;;N;;;;;
-1F4B2;HEAVY DOLLAR SIGN;So;0;ON;;;;;N;;;;;
-1F4B3;CREDIT CARD;So;0;ON;;;;;N;;;;;
-1F4B4;BANKNOTE WITH YEN SIGN;So;0;ON;;;;;N;;;;;
-1F4B5;BANKNOTE WITH DOLLAR SIGN;So;0;ON;;;;;N;;;;;
-1F4B6;BANKNOTE WITH EURO SIGN;So;0;ON;;;;;N;;;;;
-1F4B7;BANKNOTE WITH POUND SIGN;So;0;ON;;;;;N;;;;;
-1F4B8;MONEY WITH WINGS;So;0;ON;;;;;N;;;;;
-1F4B9;CHART WITH UPWARDS TREND AND YEN SIGN;So;0;ON;;;;;N;;;;;
-1F4BA;SEAT;So;0;ON;;;;;N;;;;;
-1F4BB;PERSONAL COMPUTER;So;0;ON;;;;;N;;;;;
-1F4BC;BRIEFCASE;So;0;ON;;;;;N;;;;;
-1F4BD;MINIDISC;So;0;ON;;;;;N;;;;;
-1F4BE;FLOPPY DISK;So;0;ON;;;;;N;;;;;
-1F4BF;OPTICAL DISC;So;0;ON;;;;;N;;;;;
-1F4C0;DVD;So;0;ON;;;;;N;;;;;
-1F4C1;FILE FOLDER;So;0;ON;;;;;N;;;;;
-1F4C2;OPEN FILE FOLDER;So;0;ON;;;;;N;;;;;
-1F4C3;PAGE WITH CURL;So;0;ON;;;;;N;;;;;
-1F4C4;PAGE FACING UP;So;0;ON;;;;;N;;;;;
-1F4C5;CALENDAR;So;0;ON;;;;;N;;;;;
-1F4C6;TEAR-OFF CALENDAR;So;0;ON;;;;;N;;;;;
-1F4C7;CARD INDEX;So;0;ON;;;;;N;;;;;
-1F4C8;CHART WITH UPWARDS TREND;So;0;ON;;;;;N;;;;;
-1F4C9;CHART WITH DOWNWARDS TREND;So;0;ON;;;;;N;;;;;
-1F4CA;BAR CHART;So;0;ON;;;;;N;;;;;
-1F4CB;CLIPBOARD;So;0;ON;;;;;N;;;;;
-1F4CC;PUSHPIN;So;0;ON;;;;;N;;;;;
-1F4CD;ROUND PUSHPIN;So;0;ON;;;;;N;;;;;
-1F4CE;PAPERCLIP;So;0;ON;;;;;N;;;;;
-1F4CF;STRAIGHT RULER;So;0;ON;;;;;N;;;;;
-1F4D0;TRIANGULAR RULER;So;0;ON;;;;;N;;;;;
-1F4D1;BOOKMARK TABS;So;0;ON;;;;;N;;;;;
-1F4D2;LEDGER;So;0;ON;;;;;N;;;;;
-1F4D3;NOTEBOOK;So;0;ON;;;;;N;;;;;
-1F4D4;NOTEBOOK WITH DECORATIVE COVER;So;0;ON;;;;;N;;;;;
-1F4D5;CLOSED BOOK;So;0;ON;;;;;N;;;;;
-1F4D6;OPEN BOOK;So;0;ON;;;;;N;;;;;
-1F4D7;GREEN BOOK;So;0;ON;;;;;N;;;;;
-1F4D8;BLUE BOOK;So;0;ON;;;;;N;;;;;
-1F4D9;ORANGE BOOK;So;0;ON;;;;;N;;;;;
-1F4DA;BOOKS;So;0;ON;;;;;N;;;;;
-1F4DB;NAME BADGE;So;0;ON;;;;;N;;;;;
-1F4DC;SCROLL;So;0;ON;;;;;N;;;;;
-1F4DD;MEMO;So;0;ON;;;;;N;;;;;
-1F4DE;TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;;
-1F4DF;PAGER;So;0;ON;;;;;N;;;;;
-1F4E0;FAX MACHINE;So;0;ON;;;;;N;;;;;
-1F4E1;SATELLITE ANTENNA;So;0;ON;;;;;N;;;;;
-1F4E2;PUBLIC ADDRESS LOUDSPEAKER;So;0;ON;;;;;N;;;;;
-1F4E3;CHEERING MEGAPHONE;So;0;ON;;;;;N;;;;;
-1F4E4;OUTBOX TRAY;So;0;ON;;;;;N;;;;;
-1F4E5;INBOX TRAY;So;0;ON;;;;;N;;;;;
-1F4E6;PACKAGE;So;0;ON;;;;;N;;;;;
-1F4E7;E-MAIL SYMBOL;So;0;ON;;;;;N;;;;;
-1F4E8;INCOMING ENVELOPE;So;0;ON;;;;;N;;;;;
-1F4E9;ENVELOPE WITH DOWNWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;;
-1F4EA;CLOSED MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;;
-1F4EB;CLOSED MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;;
-1F4EC;OPEN MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;;
-1F4ED;OPEN MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;;
-1F4EE;POSTBOX;So;0;ON;;;;;N;;;;;
-1F4EF;POSTAL HORN;So;0;ON;;;;;N;;;;;
-1F4F0;NEWSPAPER;So;0;ON;;;;;N;;;;;
-1F4F1;MOBILE PHONE;So;0;ON;;;;;N;;;;;
-1F4F2;MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT;So;0;ON;;;;;N;;;;;
-1F4F3;VIBRATION MODE;So;0;ON;;;;;N;;;;;
-1F4F4;MOBILE PHONE OFF;So;0;ON;;;;;N;;;;;
-1F4F5;NO MOBILE PHONES;So;0;ON;;;;;N;;;;;
-1F4F6;ANTENNA WITH BARS;So;0;ON;;;;;N;;;;;
-1F4F7;CAMERA;So;0;ON;;;;;N;;;;;
-1F4F9;VIDEO CAMERA;So;0;ON;;;;;N;;;;;
-1F4FA;TELEVISION;So;0;ON;;;;;N;;;;;
-1F4FB;RADIO;So;0;ON;;;;;N;;;;;
-1F4FC;VIDEOCASSETTE;So;0;ON;;;;;N;;;;;
-1F500;TWISTED RIGHTWARDS ARROWS;So;0;ON;;;;;N;;;;;
-1F501;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;;
-1F502;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY;So;0;ON;;;;;N;;;;;
-1F503;CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;;
-1F504;ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;;
-1F505;LOW BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;;
-1F506;HIGH BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;;
-1F507;SPEAKER WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;;
-1F508;SPEAKER;So;0;ON;;;;;N;;;;;
-1F509;SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;;
-1F50A;SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;;
-1F50B;BATTERY;So;0;ON;;;;;N;;;;;
-1F50C;ELECTRIC PLUG;So;0;ON;;;;;N;;;;;
-1F50D;LEFT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;;
-1F50E;RIGHT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;;
-1F50F;LOCK WITH INK PEN;So;0;ON;;;;;N;;;;;
-1F510;CLOSED LOCK WITH KEY;So;0;ON;;;;;N;;;;;
-1F511;KEY;So;0;ON;;;;;N;;;;;
-1F512;LOCK;So;0;ON;;;;;N;;;;;
-1F513;OPEN LOCK;So;0;ON;;;;;N;;;;;
-1F514;BELL;So;0;ON;;;;;N;;;;;
-1F515;BELL WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;;
-1F516;BOOKMARK;So;0;ON;;;;;N;;;;;
-1F517;LINK SYMBOL;So;0;ON;;;;;N;;;;;
-1F518;RADIO BUTTON;So;0;ON;;;;;N;;;;;
-1F519;BACK WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;;
-1F51A;END WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;;
-1F51B;ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE;So;0;ON;;;;;N;;;;;
-1F51C;SOON WITH RIGHTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;;
-1F51D;TOP WITH UPWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;;
-1F51E;NO ONE UNDER EIGHTEEN SYMBOL;So;0;ON;;;;;N;;;;;
-1F51F;KEYCAP TEN;So;0;ON;;;;;N;;;;;
-1F520;INPUT SYMBOL FOR LATIN CAPITAL LETTERS;So;0;ON;;;;;N;;;;;
-1F521;INPUT SYMBOL FOR LATIN SMALL LETTERS;So;0;ON;;;;;N;;;;;
-1F522;INPUT SYMBOL FOR NUMBERS;So;0;ON;;;;;N;;;;;
-1F523;INPUT SYMBOL FOR SYMBOLS;So;0;ON;;;;;N;;;;;
-1F524;INPUT SYMBOL FOR LATIN LETTERS;So;0;ON;;;;;N;;;;;
-1F525;FIRE;So;0;ON;;;;;N;;;;;
-1F526;ELECTRIC TORCH;So;0;ON;;;;;N;;;;;
-1F527;WRENCH;So;0;ON;;;;;N;;;;;
-1F528;HAMMER;So;0;ON;;;;;N;;;;;
-1F529;NUT AND BOLT;So;0;ON;;;;;N;;;;;
-1F52A;HOCHO;So;0;ON;;;;;N;;;;;
-1F52B;PISTOL;So;0;ON;;;;;N;;;;;
-1F52C;MICROSCOPE;So;0;ON;;;;;N;;;;;
-1F52D;TELESCOPE;So;0;ON;;;;;N;;;;;
-1F52E;CRYSTAL BALL;So;0;ON;;;;;N;;;;;
-1F52F;SIX POINTED STAR WITH MIDDLE DOT;So;0;ON;;;;;N;;;;;
-1F530;JAPANESE SYMBOL FOR BEGINNER;So;0;ON;;;;;N;;;;;
-1F531;TRIDENT EMBLEM;So;0;ON;;;;;N;;;;;
-1F532;BLACK SQUARE BUTTON;So;0;ON;;;;;N;;;;;
-1F533;WHITE SQUARE BUTTON;So;0;ON;;;;;N;;;;;
-1F534;LARGE RED CIRCLE;So;0;ON;;;;;N;;;;;
-1F535;LARGE BLUE CIRCLE;So;0;ON;;;;;N;;;;;
-1F536;LARGE ORANGE DIAMOND;So;0;ON;;;;;N;;;;;
-1F537;LARGE BLUE DIAMOND;So;0;ON;;;;;N;;;;;
-1F538;SMALL ORANGE DIAMOND;So;0;ON;;;;;N;;;;;
-1F539;SMALL BLUE DIAMOND;So;0;ON;;;;;N;;;;;
-1F53A;UP-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;;
-1F53B;DOWN-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;;
-1F53C;UP-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;;
-1F53D;DOWN-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;;
-1F540;CIRCLED CROSS POMMEE;So;0;ON;;;;;N;;;;;
-1F541;CROSS POMMEE WITH HALF-CIRCLE BELOW;So;0;ON;;;;;N;;;;;
-1F542;CROSS POMMEE;So;0;ON;;;;;N;;;;;
-1F543;NOTCHED LEFT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;;
-1F550;CLOCK FACE ONE OCLOCK;So;0;ON;;;;;N;;;;;
-1F551;CLOCK FACE TWO OCLOCK;So;0;ON;;;;;N;;;;;
-1F552;CLOCK FACE THREE OCLOCK;So;0;ON;;;;;N;;;;;
-1F553;CLOCK FACE FOUR OCLOCK;So;0;ON;;;;;N;;;;;
-1F554;CLOCK FACE FIVE OCLOCK;So;0;ON;;;;;N;;;;;
-1F555;CLOCK FACE SIX OCLOCK;So;0;ON;;;;;N;;;;;
-1F556;CLOCK FACE SEVEN OCLOCK;So;0;ON;;;;;N;;;;;
-1F557;CLOCK FACE EIGHT OCLOCK;So;0;ON;;;;;N;;;;;
-1F558;CLOCK FACE NINE OCLOCK;So;0;ON;;;;;N;;;;;
-1F559;CLOCK FACE TEN OCLOCK;So;0;ON;;;;;N;;;;;
-1F55A;CLOCK FACE ELEVEN OCLOCK;So;0;ON;;;;;N;;;;;
-1F55B;CLOCK FACE TWELVE OCLOCK;So;0;ON;;;;;N;;;;;
-1F55C;CLOCK FACE ONE-THIRTY;So;0;ON;;;;;N;;;;;
-1F55D;CLOCK FACE TWO-THIRTY;So;0;ON;;;;;N;;;;;
-1F55E;CLOCK FACE THREE-THIRTY;So;0;ON;;;;;N;;;;;
-1F55F;CLOCK FACE FOUR-THIRTY;So;0;ON;;;;;N;;;;;
-1F560;CLOCK FACE FIVE-THIRTY;So;0;ON;;;;;N;;;;;
-1F561;CLOCK FACE SIX-THIRTY;So;0;ON;;;;;N;;;;;
-1F562;CLOCK FACE SEVEN-THIRTY;So;0;ON;;;;;N;;;;;
-1F563;CLOCK FACE EIGHT-THIRTY;So;0;ON;;;;;N;;;;;
-1F564;CLOCK FACE NINE-THIRTY;So;0;ON;;;;;N;;;;;
-1F565;CLOCK FACE TEN-THIRTY;So;0;ON;;;;;N;;;;;
-1F566;CLOCK FACE ELEVEN-THIRTY;So;0;ON;;;;;N;;;;;
-1F567;CLOCK FACE TWELVE-THIRTY;So;0;ON;;;;;N;;;;;
-1F5FB;MOUNT FUJI;So;0;ON;;;;;N;;;;;
-1F5FC;TOKYO TOWER;So;0;ON;;;;;N;;;;;
-1F5FD;STATUE OF LIBERTY;So;0;ON;;;;;N;;;;;
-1F5FE;SILHOUETTE OF JAPAN;So;0;ON;;;;;N;;;;;
-1F5FF;MOYAI;So;0;ON;;;;;N;;;;;
-1F600;GRINNING FACE;So;0;ON;;;;;N;;;;;
-1F601;GRINNING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;;
-1F602;FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;;
-1F603;SMILING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;;
-1F604;SMILING FACE WITH OPEN MOUTH AND SMILING EYES;So;0;ON;;;;;N;;;;;
-1F605;SMILING FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;;
-1F606;SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;;
-1F607;SMILING FACE WITH HALO;So;0;ON;;;;;N;;;;;
-1F608;SMILING FACE WITH HORNS;So;0;ON;;;;;N;;;;;
-1F609;WINKING FACE;So;0;ON;;;;;N;;;;;
-1F60A;SMILING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;;
-1F60B;FACE SAVOURING DELICIOUS FOOD;So;0;ON;;;;;N;;;;;
-1F60C;RELIEVED FACE;So;0;ON;;;;;N;;;;;
-1F60D;SMILING FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;;
-1F60E;SMILING FACE WITH SUNGLASSES;So;0;ON;;;;;N;;;;;
-1F60F;SMIRKING FACE;So;0;ON;;;;;N;;;;;
-1F610;NEUTRAL FACE;So;0;ON;;;;;N;;;;;
-1F611;EXPRESSIONLESS FACE;So;0;ON;;;;;N;;;;;
-1F612;UNAMUSED FACE;So;0;ON;;;;;N;;;;;
-1F613;FACE WITH COLD SWEAT;So;0;ON;;;;;N;;;;;
-1F614;PENSIVE FACE;So;0;ON;;;;;N;;;;;
-1F615;CONFUSED FACE;So;0;ON;;;;;N;;;;;
-1F616;CONFOUNDED FACE;So;0;ON;;;;;N;;;;;
-1F617;KISSING FACE;So;0;ON;;;;;N;;;;;
-1F618;FACE THROWING A KISS;So;0;ON;;;;;N;;;;;
-1F619;KISSING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;;
-1F61A;KISSING FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;;
-1F61B;FACE WITH STUCK-OUT TONGUE;So;0;ON;;;;;N;;;;;
-1F61C;FACE WITH STUCK-OUT TONGUE AND WINKING EYE;So;0;ON;;;;;N;;;;;
-1F61D;FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;;
-1F61E;DISAPPOINTED FACE;So;0;ON;;;;;N;;;;;
-1F61F;WORRIED FACE;So;0;ON;;;;;N;;;;;
-1F620;ANGRY FACE;So;0;ON;;;;;N;;;;;
-1F621;POUTING FACE;So;0;ON;;;;;N;;;;;
-1F622;CRYING FACE;So;0;ON;;;;;N;;;;;
-1F623;PERSEVERING FACE;So;0;ON;;;;;N;;;;;
-1F624;FACE WITH LOOK OF TRIUMPH;So;0;ON;;;;;N;;;;;
-1F625;DISAPPOINTED BUT RELIEVED FACE;So;0;ON;;;;;N;;;;;
-1F626;FROWNING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;;
-1F627;ANGUISHED FACE;So;0;ON;;;;;N;;;;;
-1F628;FEARFUL FACE;So;0;ON;;;;;N;;;;;
-1F629;WEARY FACE;So;0;ON;;;;;N;;;;;
-1F62A;SLEEPY FACE;So;0;ON;;;;;N;;;;;
-1F62B;TIRED FACE;So;0;ON;;;;;N;;;;;
-1F62C;GRIMACING FACE;So;0;ON;;;;;N;;;;;
-1F62D;LOUDLY CRYING FACE;So;0;ON;;;;;N;;;;;
-1F62E;FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;;
-1F62F;HUSHED FACE;So;0;ON;;;;;N;;;;;
-1F630;FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;;
-1F631;FACE SCREAMING IN FEAR;So;0;ON;;;;;N;;;;;
-1F632;ASTONISHED FACE;So;0;ON;;;;;N;;;;;
-1F633;FLUSHED FACE;So;0;ON;;;;;N;;;;;
-1F634;SLEEPING FACE;So;0;ON;;;;;N;;;;;
-1F635;DIZZY FACE;So;0;ON;;;;;N;;;;;
-1F636;FACE WITHOUT MOUTH;So;0;ON;;;;;N;;;;;
-1F637;FACE WITH MEDICAL MASK;So;0;ON;;;;;N;;;;;
-1F638;GRINNING CAT FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;;
-1F639;CAT FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;;
-1F63A;SMILING CAT FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;;
-1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;;
-1F63C;CAT FACE WITH WRY SMILE;So;0;ON;;;;;N;;;;;
-1F63D;KISSING CAT FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;;
-1F63E;POUTING CAT FACE;So;0;ON;;;;;N;;;;;
-1F63F;CRYING CAT FACE;So;0;ON;;;;;N;;;;;
-1F640;WEARY CAT FACE;So;0;ON;;;;;N;;;;;
-1F645;FACE WITH NO GOOD GESTURE;So;0;ON;;;;;N;;;;;
-1F646;FACE WITH OK GESTURE;So;0;ON;;;;;N;;;;;
-1F647;PERSON BOWING DEEPLY;So;0;ON;;;;;N;;;;;
-1F648;SEE-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;;
-1F649;HEAR-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;;
-1F64A;SPEAK-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;;
-1F64B;HAPPY PERSON RAISING ONE HAND;So;0;ON;;;;;N;;;;;
-1F64C;PERSON RAISING BOTH HANDS IN CELEBRATION;So;0;ON;;;;;N;;;;;
-1F64D;PERSON FROWNING;So;0;ON;;;;;N;;;;;
-1F64E;PERSON WITH POUTING FACE;So;0;ON;;;;;N;;;;;
-1F64F;PERSON WITH FOLDED HANDS;So;0;ON;;;;;N;;;;;
-1F680;ROCKET;So;0;ON;;;;;N;;;;;
-1F681;HELICOPTER;So;0;ON;;;;;N;;;;;
-1F682;STEAM LOCOMOTIVE;So;0;ON;;;;;N;;;;;
-1F683;RAILWAY CAR;So;0;ON;;;;;N;;;;;
-1F684;HIGH-SPEED TRAIN;So;0;ON;;;;;N;;;;;
-1F685;HIGH-SPEED TRAIN WITH BULLET NOSE;So;0;ON;;;;;N;;;;;
-1F686;TRAIN;So;0;ON;;;;;N;;;;;
-1F687;METRO;So;0;ON;;;;;N;;;;;
-1F688;LIGHT RAIL;So;0;ON;;;;;N;;;;;
-1F689;STATION;So;0;ON;;;;;N;;;;;
-1F68A;TRAM;So;0;ON;;;;;N;;;;;
-1F68B;TRAM CAR;So;0;ON;;;;;N;;;;;
-1F68C;BUS;So;0;ON;;;;;N;;;;;
-1F68D;ONCOMING BUS;So;0;ON;;;;;N;;;;;
-1F68E;TROLLEYBUS;So;0;ON;;;;;N;;;;;
-1F68F;BUS STOP;So;0;ON;;;;;N;;;;;
-1F690;MINIBUS;So;0;ON;;;;;N;;;;;
-1F691;AMBULANCE;So;0;ON;;;;;N;;;;;
-1F692;FIRE ENGINE;So;0;ON;;;;;N;;;;;
-1F693;POLICE CAR;So;0;ON;;;;;N;;;;;
-1F694;ONCOMING POLICE CAR;So;0;ON;;;;;N;;;;;
-1F695;TAXI;So;0;ON;;;;;N;;;;;
-1F696;ONCOMING TAXI;So;0;ON;;;;;N;;;;;
-1F697;AUTOMOBILE;So;0;ON;;;;;N;;;;;
-1F698;ONCOMING AUTOMOBILE;So;0;ON;;;;;N;;;;;
-1F699;RECREATIONAL VEHICLE;So;0;ON;;;;;N;;;;;
-1F69A;DELIVERY TRUCK;So;0;ON;;;;;N;;;;;
-1F69B;ARTICULATED LORRY;So;0;ON;;;;;N;;;;;
-1F69C;TRACTOR;So;0;ON;;;;;N;;;;;
-1F69D;MONORAIL;So;0;ON;;;;;N;;;;;
-1F69E;MOUNTAIN RAILWAY;So;0;ON;;;;;N;;;;;
-1F69F;SUSPENSION RAILWAY;So;0;ON;;;;;N;;;;;
-1F6A0;MOUNTAIN CABLEWAY;So;0;ON;;;;;N;;;;;
-1F6A1;AERIAL TRAMWAY;So;0;ON;;;;;N;;;;;
-1F6A2;SHIP;So;0;ON;;;;;N;;;;;
-1F6A3;ROWBOAT;So;0;ON;;;;;N;;;;;
-1F6A4;SPEEDBOAT;So;0;ON;;;;;N;;;;;
-1F6A5;HORIZONTAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;;
-1F6A6;VERTICAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;;
-1F6A7;CONSTRUCTION SIGN;So;0;ON;;;;;N;;;;;
-1F6A8;POLICE CARS REVOLVING LIGHT;So;0;ON;;;;;N;;;;;
-1F6A9;TRIANGULAR FLAG ON POST;So;0;ON;;;;;N;;;;;
-1F6AA;DOOR;So;0;ON;;;;;N;;;;;
-1F6AB;NO ENTRY SIGN;So;0;ON;;;;;N;;;;;
-1F6AC;SMOKING SYMBOL;So;0;ON;;;;;N;;;;;
-1F6AD;NO SMOKING SYMBOL;So;0;ON;;;;;N;;;;;
-1F6AE;PUT LITTER IN ITS PLACE SYMBOL;So;0;ON;;;;;N;;;;;
-1F6AF;DO NOT LITTER SYMBOL;So;0;ON;;;;;N;;;;;
-1F6B0;POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;;
-1F6B1;NON-POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;;
-1F6B2;BICYCLE;So;0;ON;;;;;N;;;;;
-1F6B3;NO BICYCLES;So;0;ON;;;;;N;;;;;
-1F6B4;BICYCLIST;So;0;ON;;;;;N;;;;;
-1F6B5;MOUNTAIN BICYCLIST;So;0;ON;;;;;N;;;;;
-1F6B6;PEDESTRIAN;So;0;ON;;;;;N;;;;;
-1F6B7;NO PEDESTRIANS;So;0;ON;;;;;N;;;;;
-1F6B8;CHILDREN CROSSING;So;0;ON;;;;;N;;;;;
-1F6B9;MENS SYMBOL;So;0;ON;;;;;N;;;;;
-1F6BA;WOMENS SYMBOL;So;0;ON;;;;;N;;;;;
-1F6BB;RESTROOM;So;0;ON;;;;;N;;;;;
-1F6BC;BABY SYMBOL;So;0;ON;;;;;N;;;;;
-1F6BD;TOILET;So;0;ON;;;;;N;;;;;
-1F6BE;WATER CLOSET;So;0;ON;;;;;N;;;;;
-1F6BF;SHOWER;So;0;ON;;;;;N;;;;;
-1F6C0;BATH;So;0;ON;;;;;N;;;;;
-1F6C1;BATHTUB;So;0;ON;;;;;N;;;;;
-1F6C2;PASSPORT CONTROL;So;0;ON;;;;;N;;;;;
-1F6C3;CUSTOMS;So;0;ON;;;;;N;;;;;
-1F6C4;BAGGAGE CLAIM;So;0;ON;;;;;N;;;;;
-1F6C5;LEFT LUGGAGE;So;0;ON;;;;;N;;;;;
-1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;;
-1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;;
-1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;;
-1F703;ALCHEMICAL SYMBOL FOR EARTH;So;0;ON;;;;;N;;;;;
-1F704;ALCHEMICAL SYMBOL FOR WATER;So;0;ON;;;;;N;;;;;
-1F705;ALCHEMICAL SYMBOL FOR AQUAFORTIS;So;0;ON;;;;;N;;;;;
-1F706;ALCHEMICAL SYMBOL FOR AQUA REGIA;So;0;ON;;;;;N;;;;;
-1F707;ALCHEMICAL SYMBOL FOR AQUA REGIA-2;So;0;ON;;;;;N;;;;;
-1F708;ALCHEMICAL SYMBOL FOR AQUA VITAE;So;0;ON;;;;;N;;;;;
-1F709;ALCHEMICAL SYMBOL FOR AQUA VITAE-2;So;0;ON;;;;;N;;;;;
-1F70A;ALCHEMICAL SYMBOL FOR VINEGAR;So;0;ON;;;;;N;;;;;
-1F70B;ALCHEMICAL SYMBOL FOR VINEGAR-2;So;0;ON;;;;;N;;;;;
-1F70C;ALCHEMICAL SYMBOL FOR VINEGAR-3;So;0;ON;;;;;N;;;;;
-1F70D;ALCHEMICAL SYMBOL FOR SULFUR;So;0;ON;;;;;N;;;;;
-1F70E;ALCHEMICAL SYMBOL FOR PHILOSOPHERS SULFUR;So;0;ON;;;;;N;;;;;
-1F70F;ALCHEMICAL SYMBOL FOR BLACK SULFUR;So;0;ON;;;;;N;;;;;
-1F710;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE;So;0;ON;;;;;N;;;;;
-1F711;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-2;So;0;ON;;;;;N;;;;;
-1F712;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-3;So;0;ON;;;;;N;;;;;
-1F713;ALCHEMICAL SYMBOL FOR CINNABAR;So;0;ON;;;;;N;;;;;
-1F714;ALCHEMICAL SYMBOL FOR SALT;So;0;ON;;;;;N;;;;;
-1F715;ALCHEMICAL SYMBOL FOR NITRE;So;0;ON;;;;;N;;;;;
-1F716;ALCHEMICAL SYMBOL FOR VITRIOL;So;0;ON;;;;;N;;;;;
-1F717;ALCHEMICAL SYMBOL FOR VITRIOL-2;So;0;ON;;;;;N;;;;;
-1F718;ALCHEMICAL SYMBOL FOR ROCK SALT;So;0;ON;;;;;N;;;;;
-1F719;ALCHEMICAL SYMBOL FOR ROCK SALT-2;So;0;ON;;;;;N;;;;;
-1F71A;ALCHEMICAL SYMBOL FOR GOLD;So;0;ON;;;;;N;;;;;
-1F71B;ALCHEMICAL SYMBOL FOR SILVER;So;0;ON;;;;;N;;;;;
-1F71C;ALCHEMICAL SYMBOL FOR IRON ORE;So;0;ON;;;;;N;;;;;
-1F71D;ALCHEMICAL SYMBOL FOR IRON ORE-2;So;0;ON;;;;;N;;;;;
-1F71E;ALCHEMICAL SYMBOL FOR CROCUS OF IRON;So;0;ON;;;;;N;;;;;
-1F71F;ALCHEMICAL SYMBOL FOR REGULUS OF IRON;So;0;ON;;;;;N;;;;;
-1F720;ALCHEMICAL SYMBOL FOR COPPER ORE;So;0;ON;;;;;N;;;;;
-1F721;ALCHEMICAL SYMBOL FOR IRON-COPPER ORE;So;0;ON;;;;;N;;;;;
-1F722;ALCHEMICAL SYMBOL FOR SUBLIMATE OF COPPER;So;0;ON;;;;;N;;;;;
-1F723;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER;So;0;ON;;;;;N;;;;;
-1F724;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER-2;So;0;ON;;;;;N;;;;;
-1F725;ALCHEMICAL SYMBOL FOR COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;;
-1F726;ALCHEMICAL SYMBOL FOR SALT OF COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;;
-1F727;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF COPPER;So;0;ON;;;;;N;;;;;
-1F728;ALCHEMICAL SYMBOL FOR VERDIGRIS;So;0;ON;;;;;N;;;;;
-1F729;ALCHEMICAL SYMBOL FOR TIN ORE;So;0;ON;;;;;N;;;;;
-1F72A;ALCHEMICAL SYMBOL FOR LEAD ORE;So;0;ON;;;;;N;;;;;
-1F72B;ALCHEMICAL SYMBOL FOR ANTIMONY ORE;So;0;ON;;;;;N;;;;;
-1F72C;ALCHEMICAL SYMBOL FOR SUBLIMATE OF ANTIMONY;So;0;ON;;;;;N;;;;;
-1F72D;ALCHEMICAL SYMBOL FOR SALT OF ANTIMONY;So;0;ON;;;;;N;;;;;
-1F72E;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF ANTIMONY;So;0;ON;;;;;N;;;;;
-1F72F;ALCHEMICAL SYMBOL FOR VINEGAR OF ANTIMONY;So;0;ON;;;;;N;;;;;
-1F730;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY;So;0;ON;;;;;N;;;;;
-1F731;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY-2;So;0;ON;;;;;N;;;;;
-1F732;ALCHEMICAL SYMBOL FOR REGULUS;So;0;ON;;;;;N;;;;;
-1F733;ALCHEMICAL SYMBOL FOR REGULUS-2;So;0;ON;;;;;N;;;;;
-1F734;ALCHEMICAL SYMBOL FOR REGULUS-3;So;0;ON;;;;;N;;;;;
-1F735;ALCHEMICAL SYMBOL FOR REGULUS-4;So;0;ON;;;;;N;;;;;
-1F736;ALCHEMICAL SYMBOL FOR ALKALI;So;0;ON;;;;;N;;;;;
-1F737;ALCHEMICAL SYMBOL FOR ALKALI-2;So;0;ON;;;;;N;;;;;
-1F738;ALCHEMICAL SYMBOL FOR MARCASITE;So;0;ON;;;;;N;;;;;
-1F739;ALCHEMICAL SYMBOL FOR SAL-AMMONIAC;So;0;ON;;;;;N;;;;;
-1F73A;ALCHEMICAL SYMBOL FOR ARSENIC;So;0;ON;;;;;N;;;;;
-1F73B;ALCHEMICAL SYMBOL FOR REALGAR;So;0;ON;;;;;N;;;;;
-1F73C;ALCHEMICAL SYMBOL FOR REALGAR-2;So;0;ON;;;;;N;;;;;
-1F73D;ALCHEMICAL SYMBOL FOR AURIPIGMENT;So;0;ON;;;;;N;;;;;
-1F73E;ALCHEMICAL SYMBOL FOR BISMUTH ORE;So;0;ON;;;;;N;;;;;
-1F73F;ALCHEMICAL SYMBOL FOR TARTAR;So;0;ON;;;;;N;;;;;
-1F740;ALCHEMICAL SYMBOL FOR TARTAR-2;So;0;ON;;;;;N;;;;;
-1F741;ALCHEMICAL SYMBOL FOR QUICK LIME;So;0;ON;;;;;N;;;;;
-1F742;ALCHEMICAL SYMBOL FOR BORAX;So;0;ON;;;;;N;;;;;
-1F743;ALCHEMICAL SYMBOL FOR BORAX-2;So;0;ON;;;;;N;;;;;
-1F744;ALCHEMICAL SYMBOL FOR BORAX-3;So;0;ON;;;;;N;;;;;
-1F745;ALCHEMICAL SYMBOL FOR ALUM;So;0;ON;;;;;N;;;;;
-1F746;ALCHEMICAL SYMBOL FOR OIL;So;0;ON;;;;;N;;;;;
-1F747;ALCHEMICAL SYMBOL FOR SPIRIT;So;0;ON;;;;;N;;;;;
-1F748;ALCHEMICAL SYMBOL FOR TINCTURE;So;0;ON;;;;;N;;;;;
-1F749;ALCHEMICAL SYMBOL FOR GUM;So;0;ON;;;;;N;;;;;
-1F74A;ALCHEMICAL SYMBOL FOR WAX;So;0;ON;;;;;N;;;;;
-1F74B;ALCHEMICAL SYMBOL FOR POWDER;So;0;ON;;;;;N;;;;;
-1F74C;ALCHEMICAL SYMBOL FOR CALX;So;0;ON;;;;;N;;;;;
-1F74D;ALCHEMICAL SYMBOL FOR TUTTY;So;0;ON;;;;;N;;;;;
-1F74E;ALCHEMICAL SYMBOL FOR CAPUT MORTUUM;So;0;ON;;;;;N;;;;;
-1F74F;ALCHEMICAL SYMBOL FOR SCEPTER OF JOVE;So;0;ON;;;;;N;;;;;
-1F750;ALCHEMICAL SYMBOL FOR CADUCEUS;So;0;ON;;;;;N;;;;;
-1F751;ALCHEMICAL SYMBOL FOR TRIDENT;So;0;ON;;;;;N;;;;;
-1F752;ALCHEMICAL SYMBOL FOR STARRED TRIDENT;So;0;ON;;;;;N;;;;;
-1F753;ALCHEMICAL SYMBOL FOR LODESTONE;So;0;ON;;;;;N;;;;;
-1F754;ALCHEMICAL SYMBOL FOR SOAP;So;0;ON;;;;;N;;;;;
-1F755;ALCHEMICAL SYMBOL FOR URINE;So;0;ON;;;;;N;;;;;
-1F756;ALCHEMICAL SYMBOL FOR HORSE DUNG;So;0;ON;;;;;N;;;;;
-1F757;ALCHEMICAL SYMBOL FOR ASHES;So;0;ON;;;;;N;;;;;
-1F758;ALCHEMICAL SYMBOL FOR POT ASHES;So;0;ON;;;;;N;;;;;
-1F759;ALCHEMICAL SYMBOL FOR BRICK;So;0;ON;;;;;N;;;;;
-1F75A;ALCHEMICAL SYMBOL FOR POWDERED BRICK;So;0;ON;;;;;N;;;;;
-1F75B;ALCHEMICAL SYMBOL FOR AMALGAM;So;0;ON;;;;;N;;;;;
-1F75C;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM;So;0;ON;;;;;N;;;;;
-1F75D;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM-2;So;0;ON;;;;;N;;;;;
-1F75E;ALCHEMICAL SYMBOL FOR SUBLIMATION;So;0;ON;;;;;N;;;;;
-1F75F;ALCHEMICAL SYMBOL FOR PRECIPITATE;So;0;ON;;;;;N;;;;;
-1F760;ALCHEMICAL SYMBOL FOR DISTILL;So;0;ON;;;;;N;;;;;
-1F761;ALCHEMICAL SYMBOL FOR DISSOLVE;So;0;ON;;;;;N;;;;;
-1F762;ALCHEMICAL SYMBOL FOR DISSOLVE-2;So;0;ON;;;;;N;;;;;
-1F763;ALCHEMICAL SYMBOL FOR PURIFY;So;0;ON;;;;;N;;;;;
-1F764;ALCHEMICAL SYMBOL FOR PUTREFACTION;So;0;ON;;;;;N;;;;;
-1F765;ALCHEMICAL SYMBOL FOR CRUCIBLE;So;0;ON;;;;;N;;;;;
-1F766;ALCHEMICAL SYMBOL FOR CRUCIBLE-2;So;0;ON;;;;;N;;;;;
-1F767;ALCHEMICAL SYMBOL FOR CRUCIBLE-3;So;0;ON;;;;;N;;;;;
-1F768;ALCHEMICAL SYMBOL FOR CRUCIBLE-4;So;0;ON;;;;;N;;;;;
-1F769;ALCHEMICAL SYMBOL FOR CRUCIBLE-5;So;0;ON;;;;;N;;;;;
-1F76A;ALCHEMICAL SYMBOL FOR ALEMBIC;So;0;ON;;;;;N;;;;;
-1F76B;ALCHEMICAL SYMBOL FOR BATH OF MARY;So;0;ON;;;;;N;;;;;
-1F76C;ALCHEMICAL SYMBOL FOR BATH OF VAPOURS;So;0;ON;;;;;N;;;;;
-1F76D;ALCHEMICAL SYMBOL FOR RETORT;So;0;ON;;;;;N;;;;;
-1F76E;ALCHEMICAL SYMBOL FOR HOUR;So;0;ON;;;;;N;;;;;
-1F76F;ALCHEMICAL SYMBOL FOR NIGHT;So;0;ON;;;;;N;;;;;
-1F770;ALCHEMICAL SYMBOL FOR DAY-NIGHT;So;0;ON;;;;;N;;;;;
-1F771;ALCHEMICAL SYMBOL FOR MONTH;So;0;ON;;;;;N;;;;;
-1F772;ALCHEMICAL SYMBOL FOR HALF DRAM;So;0;ON;;;;;N;;;;;
-1F773;ALCHEMICAL SYMBOL FOR HALF OUNCE;So;0;ON;;;;;N;;;;;
-20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;;
-2A6D6;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;;
-2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;;
-2B734;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;;
-2B740;<CJK Ideograph Extension D, First>;Lo;0;L;;;;;N;;;;;
-2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;;
-2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;;
-2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;;
-2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;;
-2F803;CJK COMPATIBILITY IDEOGRAPH-2F803;Lo;0;L;20122;;;;N;;;;;
-2F804;CJK COMPATIBILITY IDEOGRAPH-2F804;Lo;0;L;4F60;;;;N;;;;;
-2F805;CJK COMPATIBILITY IDEOGRAPH-2F805;Lo;0;L;4FAE;;;;N;;;;;
-2F806;CJK COMPATIBILITY IDEOGRAPH-2F806;Lo;0;L;4FBB;;;;N;;;;;
-2F807;CJK COMPATIBILITY IDEOGRAPH-2F807;Lo;0;L;5002;;;;N;;;;;
-2F808;CJK COMPATIBILITY IDEOGRAPH-2F808;Lo;0;L;507A;;;;N;;;;;
-2F809;CJK COMPATIBILITY IDEOGRAPH-2F809;Lo;0;L;5099;;;;N;;;;;
-2F80A;CJK COMPATIBILITY IDEOGRAPH-2F80A;Lo;0;L;50E7;;;;N;;;;;
-2F80B;CJK COMPATIBILITY IDEOGRAPH-2F80B;Lo;0;L;50CF;;;;N;;;;;
-2F80C;CJK COMPATIBILITY IDEOGRAPH-2F80C;Lo;0;L;349E;;;;N;;;;;
-2F80D;CJK COMPATIBILITY IDEOGRAPH-2F80D;Lo;0;L;2063A;;;;N;;;;;
-2F80E;CJK COMPATIBILITY IDEOGRAPH-2F80E;Lo;0;L;514D;;;;N;;;;;
-2F80F;CJK COMPATIBILITY IDEOGRAPH-2F80F;Lo;0;L;5154;;;;N;;;;;
-2F810;CJK COMPATIBILITY IDEOGRAPH-2F810;Lo;0;L;5164;;;;N;;;;;
-2F811;CJK COMPATIBILITY IDEOGRAPH-2F811;Lo;0;L;5177;;;;N;;;;;
-2F812;CJK COMPATIBILITY IDEOGRAPH-2F812;Lo;0;L;2051C;;;;N;;;;;
-2F813;CJK COMPATIBILITY IDEOGRAPH-2F813;Lo;0;L;34B9;;;;N;;;;;
-2F814;CJK COMPATIBILITY IDEOGRAPH-2F814;Lo;0;L;5167;;;;N;;;;;
-2F815;CJK COMPATIBILITY IDEOGRAPH-2F815;Lo;0;L;518D;;;;N;;;;;
-2F816;CJK COMPATIBILITY IDEOGRAPH-2F816;Lo;0;L;2054B;;;;N;;;;;
-2F817;CJK COMPATIBILITY IDEOGRAPH-2F817;Lo;0;L;5197;;;;N;;;;;
-2F818;CJK COMPATIBILITY IDEOGRAPH-2F818;Lo;0;L;51A4;;;;N;;;;;
-2F819;CJK COMPATIBILITY IDEOGRAPH-2F819;Lo;0;L;4ECC;;;;N;;;;;
-2F81A;CJK COMPATIBILITY IDEOGRAPH-2F81A;Lo;0;L;51AC;;;;N;;;;;
-2F81B;CJK COMPATIBILITY IDEOGRAPH-2F81B;Lo;0;L;51B5;;;;N;;;;;
-2F81C;CJK COMPATIBILITY IDEOGRAPH-2F81C;Lo;0;L;291DF;;;;N;;;;;
-2F81D;CJK COMPATIBILITY IDEOGRAPH-2F81D;Lo;0;L;51F5;;;;N;;;;;
-2F81E;CJK COMPATIBILITY IDEOGRAPH-2F81E;Lo;0;L;5203;;;;N;;;;;
-2F81F;CJK COMPATIBILITY IDEOGRAPH-2F81F;Lo;0;L;34DF;;;;N;;;;;
-2F820;CJK COMPATIBILITY IDEOGRAPH-2F820;Lo;0;L;523B;;;;N;;;;;
-2F821;CJK COMPATIBILITY IDEOGRAPH-2F821;Lo;0;L;5246;;;;N;;;;;
-2F822;CJK COMPATIBILITY IDEOGRAPH-2F822;Lo;0;L;5272;;;;N;;;;;
-2F823;CJK COMPATIBILITY IDEOGRAPH-2F823;Lo;0;L;5277;;;;N;;;;;
-2F824;CJK COMPATIBILITY IDEOGRAPH-2F824;Lo;0;L;3515;;;;N;;;;;
-2F825;CJK COMPATIBILITY IDEOGRAPH-2F825;Lo;0;L;52C7;;;;N;;;;;
-2F826;CJK COMPATIBILITY IDEOGRAPH-2F826;Lo;0;L;52C9;;;;N;;;;;
-2F827;CJK COMPATIBILITY IDEOGRAPH-2F827;Lo;0;L;52E4;;;;N;;;;;
-2F828;CJK COMPATIBILITY IDEOGRAPH-2F828;Lo;0;L;52FA;;;;N;;;;;
-2F829;CJK COMPATIBILITY IDEOGRAPH-2F829;Lo;0;L;5305;;;;N;;;;;
-2F82A;CJK COMPATIBILITY IDEOGRAPH-2F82A;Lo;0;L;5306;;;;N;;;;;
-2F82B;CJK COMPATIBILITY IDEOGRAPH-2F82B;Lo;0;L;5317;;;;N;;;;;
-2F82C;CJK COMPATIBILITY IDEOGRAPH-2F82C;Lo;0;L;5349;;;;N;;;;;
-2F82D;CJK COMPATIBILITY IDEOGRAPH-2F82D;Lo;0;L;5351;;;;N;;;;;
-2F82E;CJK COMPATIBILITY IDEOGRAPH-2F82E;Lo;0;L;535A;;;;N;;;;;
-2F82F;CJK COMPATIBILITY IDEOGRAPH-2F82F;Lo;0;L;5373;;;;N;;;;;
-2F830;CJK COMPATIBILITY IDEOGRAPH-2F830;Lo;0;L;537D;;;;N;;;;;
-2F831;CJK COMPATIBILITY IDEOGRAPH-2F831;Lo;0;L;537F;;;;N;;;;;
-2F832;CJK COMPATIBILITY IDEOGRAPH-2F832;Lo;0;L;537F;;;;N;;;;;
-2F833;CJK COMPATIBILITY IDEOGRAPH-2F833;Lo;0;L;537F;;;;N;;;;;
-2F834;CJK COMPATIBILITY IDEOGRAPH-2F834;Lo;0;L;20A2C;;;;N;;;;;
-2F835;CJK COMPATIBILITY IDEOGRAPH-2F835;Lo;0;L;7070;;;;N;;;;;
-2F836;CJK COMPATIBILITY IDEOGRAPH-2F836;Lo;0;L;53CA;;;;N;;;;;
-2F837;CJK COMPATIBILITY IDEOGRAPH-2F837;Lo;0;L;53DF;;;;N;;;;;
-2F838;CJK COMPATIBILITY IDEOGRAPH-2F838;Lo;0;L;20B63;;;;N;;;;;
-2F839;CJK COMPATIBILITY IDEOGRAPH-2F839;Lo;0;L;53EB;;;;N;;;;;
-2F83A;CJK COMPATIBILITY IDEOGRAPH-2F83A;Lo;0;L;53F1;;;;N;;;;;
-2F83B;CJK COMPATIBILITY IDEOGRAPH-2F83B;Lo;0;L;5406;;;;N;;;;;
-2F83C;CJK COMPATIBILITY IDEOGRAPH-2F83C;Lo;0;L;549E;;;;N;;;;;
-2F83D;CJK COMPATIBILITY IDEOGRAPH-2F83D;Lo;0;L;5438;;;;N;;;;;
-2F83E;CJK COMPATIBILITY IDEOGRAPH-2F83E;Lo;0;L;5448;;;;N;;;;;
-2F83F;CJK COMPATIBILITY IDEOGRAPH-2F83F;Lo;0;L;5468;;;;N;;;;;
-2F840;CJK COMPATIBILITY IDEOGRAPH-2F840;Lo;0;L;54A2;;;;N;;;;;
-2F841;CJK COMPATIBILITY IDEOGRAPH-2F841;Lo;0;L;54F6;;;;N;;;;;
-2F842;CJK COMPATIBILITY IDEOGRAPH-2F842;Lo;0;L;5510;;;;N;;;;;
-2F843;CJK COMPATIBILITY IDEOGRAPH-2F843;Lo;0;L;5553;;;;N;;;;;
-2F844;CJK COMPATIBILITY IDEOGRAPH-2F844;Lo;0;L;5563;;;;N;;;;;
-2F845;CJK COMPATIBILITY IDEOGRAPH-2F845;Lo;0;L;5584;;;;N;;;;;
-2F846;CJK COMPATIBILITY IDEOGRAPH-2F846;Lo;0;L;5584;;;;N;;;;;
-2F847;CJK COMPATIBILITY IDEOGRAPH-2F847;Lo;0;L;5599;;;;N;;;;;
-2F848;CJK COMPATIBILITY IDEOGRAPH-2F848;Lo;0;L;55AB;;;;N;;;;;
-2F849;CJK COMPATIBILITY IDEOGRAPH-2F849;Lo;0;L;55B3;;;;N;;;;;
-2F84A;CJK COMPATIBILITY IDEOGRAPH-2F84A;Lo;0;L;55C2;;;;N;;;;;
-2F84B;CJK COMPATIBILITY IDEOGRAPH-2F84B;Lo;0;L;5716;;;;N;;;;;
-2F84C;CJK COMPATIBILITY IDEOGRAPH-2F84C;Lo;0;L;5606;;;;N;;;;;
-2F84D;CJK COMPATIBILITY IDEOGRAPH-2F84D;Lo;0;L;5717;;;;N;;;;;
-2F84E;CJK COMPATIBILITY IDEOGRAPH-2F84E;Lo;0;L;5651;;;;N;;;;;
-2F84F;CJK COMPATIBILITY IDEOGRAPH-2F84F;Lo;0;L;5674;;;;N;;;;;
-2F850;CJK COMPATIBILITY IDEOGRAPH-2F850;Lo;0;L;5207;;;;N;;;;;
-2F851;CJK COMPATIBILITY IDEOGRAPH-2F851;Lo;0;L;58EE;;;;N;;;;;
-2F852;CJK COMPATIBILITY IDEOGRAPH-2F852;Lo;0;L;57CE;;;;N;;;;;
-2F853;CJK COMPATIBILITY IDEOGRAPH-2F853;Lo;0;L;57F4;;;;N;;;;;
-2F854;CJK COMPATIBILITY IDEOGRAPH-2F854;Lo;0;L;580D;;;;N;;;;;
-2F855;CJK COMPATIBILITY IDEOGRAPH-2F855;Lo;0;L;578B;;;;N;;;;;
-2F856;CJK COMPATIBILITY IDEOGRAPH-2F856;Lo;0;L;5832;;;;N;;;;;
-2F857;CJK COMPATIBILITY IDEOGRAPH-2F857;Lo;0;L;5831;;;;N;;;;;
-2F858;CJK COMPATIBILITY IDEOGRAPH-2F858;Lo;0;L;58AC;;;;N;;;;;
-2F859;CJK COMPATIBILITY IDEOGRAPH-2F859;Lo;0;L;214E4;;;;N;;;;;
-2F85A;CJK COMPATIBILITY IDEOGRAPH-2F85A;Lo;0;L;58F2;;;;N;;;;;
-2F85B;CJK COMPATIBILITY IDEOGRAPH-2F85B;Lo;0;L;58F7;;;;N;;;;;
-2F85C;CJK COMPATIBILITY IDEOGRAPH-2F85C;Lo;0;L;5906;;;;N;;;;;
-2F85D;CJK COMPATIBILITY IDEOGRAPH-2F85D;Lo;0;L;591A;;;;N;;;;;
-2F85E;CJK COMPATIBILITY IDEOGRAPH-2F85E;Lo;0;L;5922;;;;N;;;;;
-2F85F;CJK COMPATIBILITY IDEOGRAPH-2F85F;Lo;0;L;5962;;;;N;;;;;
-2F860;CJK COMPATIBILITY IDEOGRAPH-2F860;Lo;0;L;216A8;;;;N;;;;;
-2F861;CJK COMPATIBILITY IDEOGRAPH-2F861;Lo;0;L;216EA;;;;N;;;;;
-2F862;CJK COMPATIBILITY IDEOGRAPH-2F862;Lo;0;L;59EC;;;;N;;;;;
-2F863;CJK COMPATIBILITY IDEOGRAPH-2F863;Lo;0;L;5A1B;;;;N;;;;;
-2F864;CJK COMPATIBILITY IDEOGRAPH-2F864;Lo;0;L;5A27;;;;N;;;;;
-2F865;CJK COMPATIBILITY IDEOGRAPH-2F865;Lo;0;L;59D8;;;;N;;;;;
-2F866;CJK COMPATIBILITY IDEOGRAPH-2F866;Lo;0;L;5A66;;;;N;;;;;
-2F867;CJK COMPATIBILITY IDEOGRAPH-2F867;Lo;0;L;36EE;;;;N;;;;;
-2F868;CJK COMPATIBILITY IDEOGRAPH-2F868;Lo;0;L;36FC;;;;N;;;;;
-2F869;CJK COMPATIBILITY IDEOGRAPH-2F869;Lo;0;L;5B08;;;;N;;;;;
-2F86A;CJK COMPATIBILITY IDEOGRAPH-2F86A;Lo;0;L;5B3E;;;;N;;;;;
-2F86B;CJK COMPATIBILITY IDEOGRAPH-2F86B;Lo;0;L;5B3E;;;;N;;;;;
-2F86C;CJK COMPATIBILITY IDEOGRAPH-2F86C;Lo;0;L;219C8;;;;N;;;;;
-2F86D;CJK COMPATIBILITY IDEOGRAPH-2F86D;Lo;0;L;5BC3;;;;N;;;;;
-2F86E;CJK COMPATIBILITY IDEOGRAPH-2F86E;Lo;0;L;5BD8;;;;N;;;;;
-2F86F;CJK COMPATIBILITY IDEOGRAPH-2F86F;Lo;0;L;5BE7;;;;N;;;;;
-2F870;CJK COMPATIBILITY IDEOGRAPH-2F870;Lo;0;L;5BF3;;;;N;;;;;
-2F871;CJK COMPATIBILITY IDEOGRAPH-2F871;Lo;0;L;21B18;;;;N;;;;;
-2F872;CJK COMPATIBILITY IDEOGRAPH-2F872;Lo;0;L;5BFF;;;;N;;;;;
-2F873;CJK COMPATIBILITY IDEOGRAPH-2F873;Lo;0;L;5C06;;;;N;;;;;
-2F874;CJK COMPATIBILITY IDEOGRAPH-2F874;Lo;0;L;5F53;;;;N;;;;;
-2F875;CJK COMPATIBILITY IDEOGRAPH-2F875;Lo;0;L;5C22;;;;N;;;;;
-2F876;CJK COMPATIBILITY IDEOGRAPH-2F876;Lo;0;L;3781;;;;N;;;;;
-2F877;CJK COMPATIBILITY IDEOGRAPH-2F877;Lo;0;L;5C60;;;;N;;;;;
-2F878;CJK COMPATIBILITY IDEOGRAPH-2F878;Lo;0;L;5C6E;;;;N;;;;;
-2F879;CJK COMPATIBILITY IDEOGRAPH-2F879;Lo;0;L;5CC0;;;;N;;;;;
-2F87A;CJK COMPATIBILITY IDEOGRAPH-2F87A;Lo;0;L;5C8D;;;;N;;;;;
-2F87B;CJK COMPATIBILITY IDEOGRAPH-2F87B;Lo;0;L;21DE4;;;;N;;;;;
-2F87C;CJK COMPATIBILITY IDEOGRAPH-2F87C;Lo;0;L;5D43;;;;N;;;;;
-2F87D;CJK COMPATIBILITY IDEOGRAPH-2F87D;Lo;0;L;21DE6;;;;N;;;;;
-2F87E;CJK COMPATIBILITY IDEOGRAPH-2F87E;Lo;0;L;5D6E;;;;N;;;;;
-2F87F;CJK COMPATIBILITY IDEOGRAPH-2F87F;Lo;0;L;5D6B;;;;N;;;;;
-2F880;CJK COMPATIBILITY IDEOGRAPH-2F880;Lo;0;L;5D7C;;;;N;;;;;
-2F881;CJK COMPATIBILITY IDEOGRAPH-2F881;Lo;0;L;5DE1;;;;N;;;;;
-2F882;CJK COMPATIBILITY IDEOGRAPH-2F882;Lo;0;L;5DE2;;;;N;;;;;
-2F883;CJK COMPATIBILITY IDEOGRAPH-2F883;Lo;0;L;382F;;;;N;;;;;
-2F884;CJK COMPATIBILITY IDEOGRAPH-2F884;Lo;0;L;5DFD;;;;N;;;;;
-2F885;CJK COMPATIBILITY IDEOGRAPH-2F885;Lo;0;L;5E28;;;;N;;;;;
-2F886;CJK COMPATIBILITY IDEOGRAPH-2F886;Lo;0;L;5E3D;;;;N;;;;;
-2F887;CJK COMPATIBILITY IDEOGRAPH-2F887;Lo;0;L;5E69;;;;N;;;;;
-2F888;CJK COMPATIBILITY IDEOGRAPH-2F888;Lo;0;L;3862;;;;N;;;;;
-2F889;CJK COMPATIBILITY IDEOGRAPH-2F889;Lo;0;L;22183;;;;N;;;;;
-2F88A;CJK COMPATIBILITY IDEOGRAPH-2F88A;Lo;0;L;387C;;;;N;;;;;
-2F88B;CJK COMPATIBILITY IDEOGRAPH-2F88B;Lo;0;L;5EB0;;;;N;;;;;
-2F88C;CJK COMPATIBILITY IDEOGRAPH-2F88C;Lo;0;L;5EB3;;;;N;;;;;
-2F88D;CJK COMPATIBILITY IDEOGRAPH-2F88D;Lo;0;L;5EB6;;;;N;;;;;
-2F88E;CJK COMPATIBILITY IDEOGRAPH-2F88E;Lo;0;L;5ECA;;;;N;;;;;
-2F88F;CJK COMPATIBILITY IDEOGRAPH-2F88F;Lo;0;L;2A392;;;;N;;;;;
-2F890;CJK COMPATIBILITY IDEOGRAPH-2F890;Lo;0;L;5EFE;;;9;N;;;;;
-2F891;CJK COMPATIBILITY IDEOGRAPH-2F891;Lo;0;L;22331;;;;N;;;;;
-2F892;CJK COMPATIBILITY IDEOGRAPH-2F892;Lo;0;L;22331;;;;N;;;;;
-2F893;CJK COMPATIBILITY IDEOGRAPH-2F893;Lo;0;L;8201;;;;N;;;;;
-2F894;CJK COMPATIBILITY IDEOGRAPH-2F894;Lo;0;L;5F22;;;;N;;;;;
-2F895;CJK COMPATIBILITY IDEOGRAPH-2F895;Lo;0;L;5F22;;;;N;;;;;
-2F896;CJK COMPATIBILITY IDEOGRAPH-2F896;Lo;0;L;38C7;;;;N;;;;;
-2F897;CJK COMPATIBILITY IDEOGRAPH-2F897;Lo;0;L;232B8;;;;N;;;;;
-2F898;CJK COMPATIBILITY IDEOGRAPH-2F898;Lo;0;L;261DA;;;;N;;;;;
-2F899;CJK COMPATIBILITY IDEOGRAPH-2F899;Lo;0;L;5F62;;;;N;;;;;
-2F89A;CJK COMPATIBILITY IDEOGRAPH-2F89A;Lo;0;L;5F6B;;;;N;;;;;
-2F89B;CJK COMPATIBILITY IDEOGRAPH-2F89B;Lo;0;L;38E3;;;;N;;;;;
-2F89C;CJK COMPATIBILITY IDEOGRAPH-2F89C;Lo;0;L;5F9A;;;;N;;;;;
-2F89D;CJK COMPATIBILITY IDEOGRAPH-2F89D;Lo;0;L;5FCD;;;;N;;;;;
-2F89E;CJK COMPATIBILITY IDEOGRAPH-2F89E;Lo;0;L;5FD7;;;;N;;;;;
-2F89F;CJK COMPATIBILITY IDEOGRAPH-2F89F;Lo;0;L;5FF9;;;;N;;;;;
-2F8A0;CJK COMPATIBILITY IDEOGRAPH-2F8A0;Lo;0;L;6081;;;;N;;;;;
-2F8A1;CJK COMPATIBILITY IDEOGRAPH-2F8A1;Lo;0;L;393A;;;;N;;;;;
-2F8A2;CJK COMPATIBILITY IDEOGRAPH-2F8A2;Lo;0;L;391C;;;;N;;;;;
-2F8A3;CJK COMPATIBILITY IDEOGRAPH-2F8A3;Lo;0;L;6094;;;;N;;;;;
-2F8A4;CJK COMPATIBILITY IDEOGRAPH-2F8A4;Lo;0;L;226D4;;;;N;;;;;
-2F8A5;CJK COMPATIBILITY IDEOGRAPH-2F8A5;Lo;0;L;60C7;;;;N;;;;;
-2F8A6;CJK COMPATIBILITY IDEOGRAPH-2F8A6;Lo;0;L;6148;;;;N;;;;;
-2F8A7;CJK COMPATIBILITY IDEOGRAPH-2F8A7;Lo;0;L;614C;;;;N;;;;;
-2F8A8;CJK COMPATIBILITY IDEOGRAPH-2F8A8;Lo;0;L;614E;;;;N;;;;;
-2F8A9;CJK COMPATIBILITY IDEOGRAPH-2F8A9;Lo;0;L;614C;;;;N;;;;;
-2F8AA;CJK COMPATIBILITY IDEOGRAPH-2F8AA;Lo;0;L;617A;;;;N;;;;;
-2F8AB;CJK COMPATIBILITY IDEOGRAPH-2F8AB;Lo;0;L;618E;;;;N;;;;;
-2F8AC;CJK COMPATIBILITY IDEOGRAPH-2F8AC;Lo;0;L;61B2;;;;N;;;;;
-2F8AD;CJK COMPATIBILITY IDEOGRAPH-2F8AD;Lo;0;L;61A4;;;;N;;;;;
-2F8AE;CJK COMPATIBILITY IDEOGRAPH-2F8AE;Lo;0;L;61AF;;;;N;;;;;
-2F8AF;CJK COMPATIBILITY IDEOGRAPH-2F8AF;Lo;0;L;61DE;;;;N;;;;;
-2F8B0;CJK COMPATIBILITY IDEOGRAPH-2F8B0;Lo;0;L;61F2;;;;N;;;;;
-2F8B1;CJK COMPATIBILITY IDEOGRAPH-2F8B1;Lo;0;L;61F6;;;;N;;;;;
-2F8B2;CJK COMPATIBILITY IDEOGRAPH-2F8B2;Lo;0;L;6210;;;;N;;;;;
-2F8B3;CJK COMPATIBILITY IDEOGRAPH-2F8B3;Lo;0;L;621B;;;;N;;;;;
-2F8B4;CJK COMPATIBILITY IDEOGRAPH-2F8B4;Lo;0;L;625D;;;;N;;;;;
-2F8B5;CJK COMPATIBILITY IDEOGRAPH-2F8B5;Lo;0;L;62B1;;;;N;;;;;
-2F8B6;CJK COMPATIBILITY IDEOGRAPH-2F8B6;Lo;0;L;62D4;;;;N;;;;;
-2F8B7;CJK COMPATIBILITY IDEOGRAPH-2F8B7;Lo;0;L;6350;;;;N;;;;;
-2F8B8;CJK COMPATIBILITY IDEOGRAPH-2F8B8;Lo;0;L;22B0C;;;;N;;;;;
-2F8B9;CJK COMPATIBILITY IDEOGRAPH-2F8B9;Lo;0;L;633D;;;;N;;;;;
-2F8BA;CJK COMPATIBILITY IDEOGRAPH-2F8BA;Lo;0;L;62FC;;;;N;;;;;
-2F8BB;CJK COMPATIBILITY IDEOGRAPH-2F8BB;Lo;0;L;6368;;;;N;;;;;
-2F8BC;CJK COMPATIBILITY IDEOGRAPH-2F8BC;Lo;0;L;6383;;;;N;;;;;
-2F8BD;CJK COMPATIBILITY IDEOGRAPH-2F8BD;Lo;0;L;63E4;;;;N;;;;;
-2F8BE;CJK COMPATIBILITY IDEOGRAPH-2F8BE;Lo;0;L;22BF1;;;;N;;;;;
-2F8BF;CJK COMPATIBILITY IDEOGRAPH-2F8BF;Lo;0;L;6422;;;;N;;;;;
-2F8C0;CJK COMPATIBILITY IDEOGRAPH-2F8C0;Lo;0;L;63C5;;;;N;;;;;
-2F8C1;CJK COMPATIBILITY IDEOGRAPH-2F8C1;Lo;0;L;63A9;;;;N;;;;;
-2F8C2;CJK COMPATIBILITY IDEOGRAPH-2F8C2;Lo;0;L;3A2E;;;;N;;;;;
-2F8C3;CJK COMPATIBILITY IDEOGRAPH-2F8C3;Lo;0;L;6469;;;;N;;;;;
-2F8C4;CJK COMPATIBILITY IDEOGRAPH-2F8C4;Lo;0;L;647E;;;;N;;;;;
-2F8C5;CJK COMPATIBILITY IDEOGRAPH-2F8C5;Lo;0;L;649D;;;;N;;;;;
-2F8C6;CJK COMPATIBILITY IDEOGRAPH-2F8C6;Lo;0;L;6477;;;;N;;;;;
-2F8C7;CJK COMPATIBILITY IDEOGRAPH-2F8C7;Lo;0;L;3A6C;;;;N;;;;;
-2F8C8;CJK COMPATIBILITY IDEOGRAPH-2F8C8;Lo;0;L;654F;;;;N;;;;;
-2F8C9;CJK COMPATIBILITY IDEOGRAPH-2F8C9;Lo;0;L;656C;;;;N;;;;;
-2F8CA;CJK COMPATIBILITY IDEOGRAPH-2F8CA;Lo;0;L;2300A;;;;N;;;;;
-2F8CB;CJK COMPATIBILITY IDEOGRAPH-2F8CB;Lo;0;L;65E3;;;;N;;;;;
-2F8CC;CJK COMPATIBILITY IDEOGRAPH-2F8CC;Lo;0;L;66F8;;;;N;;;;;
-2F8CD;CJK COMPATIBILITY IDEOGRAPH-2F8CD;Lo;0;L;6649;;;;N;;;;;
-2F8CE;CJK COMPATIBILITY IDEOGRAPH-2F8CE;Lo;0;L;3B19;;;;N;;;;;
-2F8CF;CJK COMPATIBILITY IDEOGRAPH-2F8CF;Lo;0;L;6691;;;;N;;;;;
-2F8D0;CJK COMPATIBILITY IDEOGRAPH-2F8D0;Lo;0;L;3B08;;;;N;;;;;
-2F8D1;CJK COMPATIBILITY IDEOGRAPH-2F8D1;Lo;0;L;3AE4;;;;N;;;;;
-2F8D2;CJK COMPATIBILITY IDEOGRAPH-2F8D2;Lo;0;L;5192;;;;N;;;;;
-2F8D3;CJK COMPATIBILITY IDEOGRAPH-2F8D3;Lo;0;L;5195;;;;N;;;;;
-2F8D4;CJK COMPATIBILITY IDEOGRAPH-2F8D4;Lo;0;L;6700;;;;N;;;;;
-2F8D5;CJK COMPATIBILITY IDEOGRAPH-2F8D5;Lo;0;L;669C;;;;N;;;;;
-2F8D6;CJK COMPATIBILITY IDEOGRAPH-2F8D6;Lo;0;L;80AD;;;;N;;;;;
-2F8D7;CJK COMPATIBILITY IDEOGRAPH-2F8D7;Lo;0;L;43D9;;;;N;;;;;
-2F8D8;CJK COMPATIBILITY IDEOGRAPH-2F8D8;Lo;0;L;6717;;;;N;;;;;
-2F8D9;CJK COMPATIBILITY IDEOGRAPH-2F8D9;Lo;0;L;671B;;;;N;;;;;
-2F8DA;CJK COMPATIBILITY IDEOGRAPH-2F8DA;Lo;0;L;6721;;;;N;;;;;
-2F8DB;CJK COMPATIBILITY IDEOGRAPH-2F8DB;Lo;0;L;675E;;;;N;;;;;
-2F8DC;CJK COMPATIBILITY IDEOGRAPH-2F8DC;Lo;0;L;6753;;;;N;;;;;
-2F8DD;CJK COMPATIBILITY IDEOGRAPH-2F8DD;Lo;0;L;233C3;;;;N;;;;;
-2F8DE;CJK COMPATIBILITY IDEOGRAPH-2F8DE;Lo;0;L;3B49;;;;N;;;;;
-2F8DF;CJK COMPATIBILITY IDEOGRAPH-2F8DF;Lo;0;L;67FA;;;;N;;;;;
-2F8E0;CJK COMPATIBILITY IDEOGRAPH-2F8E0;Lo;0;L;6785;;;;N;;;;;
-2F8E1;CJK COMPATIBILITY IDEOGRAPH-2F8E1;Lo;0;L;6852;;;;N;;;;;
-2F8E2;CJK COMPATIBILITY IDEOGRAPH-2F8E2;Lo;0;L;6885;;;;N;;;;;
-2F8E3;CJK COMPATIBILITY IDEOGRAPH-2F8E3;Lo;0;L;2346D;;;;N;;;;;
-2F8E4;CJK COMPATIBILITY IDEOGRAPH-2F8E4;Lo;0;L;688E;;;;N;;;;;
-2F8E5;CJK COMPATIBILITY IDEOGRAPH-2F8E5;Lo;0;L;681F;;;;N;;;;;
-2F8E6;CJK COMPATIBILITY IDEOGRAPH-2F8E6;Lo;0;L;6914;;;;N;;;;;
-2F8E7;CJK COMPATIBILITY IDEOGRAPH-2F8E7;Lo;0;L;3B9D;;;;N;;;;;
-2F8E8;CJK COMPATIBILITY IDEOGRAPH-2F8E8;Lo;0;L;6942;;;;N;;;;;
-2F8E9;CJK COMPATIBILITY IDEOGRAPH-2F8E9;Lo;0;L;69A3;;;;N;;;;;
-2F8EA;CJK COMPATIBILITY IDEOGRAPH-2F8EA;Lo;0;L;69EA;;;;N;;;;;
-2F8EB;CJK COMPATIBILITY IDEOGRAPH-2F8EB;Lo;0;L;6AA8;;;;N;;;;;
-2F8EC;CJK COMPATIBILITY IDEOGRAPH-2F8EC;Lo;0;L;236A3;;;;N;;;;;
-2F8ED;CJK COMPATIBILITY IDEOGRAPH-2F8ED;Lo;0;L;6ADB;;;;N;;;;;
-2F8EE;CJK COMPATIBILITY IDEOGRAPH-2F8EE;Lo;0;L;3C18;;;;N;;;;;
-2F8EF;CJK COMPATIBILITY IDEOGRAPH-2F8EF;Lo;0;L;6B21;;;;N;;;;;
-2F8F0;CJK COMPATIBILITY IDEOGRAPH-2F8F0;Lo;0;L;238A7;;;;N;;;;;
-2F8F1;CJK COMPATIBILITY IDEOGRAPH-2F8F1;Lo;0;L;6B54;;;;N;;;;;
-2F8F2;CJK COMPATIBILITY IDEOGRAPH-2F8F2;Lo;0;L;3C4E;;;;N;;;;;
-2F8F3;CJK COMPATIBILITY IDEOGRAPH-2F8F3;Lo;0;L;6B72;;;;N;;;;;
-2F8F4;CJK COMPATIBILITY IDEOGRAPH-2F8F4;Lo;0;L;6B9F;;;;N;;;;;
-2F8F5;CJK COMPATIBILITY IDEOGRAPH-2F8F5;Lo;0;L;6BBA;;;;N;;;;;
-2F8F6;CJK COMPATIBILITY IDEOGRAPH-2F8F6;Lo;0;L;6BBB;;;;N;;;;;
-2F8F7;CJK COMPATIBILITY IDEOGRAPH-2F8F7;Lo;0;L;23A8D;;;;N;;;;;
-2F8F8;CJK COMPATIBILITY IDEOGRAPH-2F8F8;Lo;0;L;21D0B;;;;N;;;;;
-2F8F9;CJK COMPATIBILITY IDEOGRAPH-2F8F9;Lo;0;L;23AFA;;;;N;;;;;
-2F8FA;CJK COMPATIBILITY IDEOGRAPH-2F8FA;Lo;0;L;6C4E;;;;N;;;;;
-2F8FB;CJK COMPATIBILITY IDEOGRAPH-2F8FB;Lo;0;L;23CBC;;;;N;;;;;
-2F8FC;CJK COMPATIBILITY IDEOGRAPH-2F8FC;Lo;0;L;6CBF;;;;N;;;;;
-2F8FD;CJK COMPATIBILITY IDEOGRAPH-2F8FD;Lo;0;L;6CCD;;;;N;;;;;
-2F8FE;CJK COMPATIBILITY IDEOGRAPH-2F8FE;Lo;0;L;6C67;;;;N;;;;;
-2F8FF;CJK COMPATIBILITY IDEOGRAPH-2F8FF;Lo;0;L;6D16;;;;N;;;;;
-2F900;CJK COMPATIBILITY IDEOGRAPH-2F900;Lo;0;L;6D3E;;;;N;;;;;
-2F901;CJK COMPATIBILITY IDEOGRAPH-2F901;Lo;0;L;6D77;;;;N;;;;;
-2F902;CJK COMPATIBILITY IDEOGRAPH-2F902;Lo;0;L;6D41;;;;N;;;;;
-2F903;CJK COMPATIBILITY IDEOGRAPH-2F903;Lo;0;L;6D69;;;;N;;;;;
-2F904;CJK COMPATIBILITY IDEOGRAPH-2F904;Lo;0;L;6D78;;;;N;;;;;
-2F905;CJK COMPATIBILITY IDEOGRAPH-2F905;Lo;0;L;6D85;;;;N;;;;;
-2F906;CJK COMPATIBILITY IDEOGRAPH-2F906;Lo;0;L;23D1E;;;;N;;;;;
-2F907;CJK COMPATIBILITY IDEOGRAPH-2F907;Lo;0;L;6D34;;;;N;;;;;
-2F908;CJK COMPATIBILITY IDEOGRAPH-2F908;Lo;0;L;6E2F;;;;N;;;;;
-2F909;CJK COMPATIBILITY IDEOGRAPH-2F909;Lo;0;L;6E6E;;;;N;;;;;
-2F90A;CJK COMPATIBILITY IDEOGRAPH-2F90A;Lo;0;L;3D33;;;;N;;;;;
-2F90B;CJK COMPATIBILITY IDEOGRAPH-2F90B;Lo;0;L;6ECB;;;;N;;;;;
-2F90C;CJK COMPATIBILITY IDEOGRAPH-2F90C;Lo;0;L;6EC7;;;;N;;;;;
-2F90D;CJK COMPATIBILITY IDEOGRAPH-2F90D;Lo;0;L;23ED1;;;;N;;;;;
-2F90E;CJK COMPATIBILITY IDEOGRAPH-2F90E;Lo;0;L;6DF9;;;;N;;;;;
-2F90F;CJK COMPATIBILITY IDEOGRAPH-2F90F;Lo;0;L;6F6E;;;;N;;;;;
-2F910;CJK COMPATIBILITY IDEOGRAPH-2F910;Lo;0;L;23F5E;;;;N;;;;;
-2F911;CJK COMPATIBILITY IDEOGRAPH-2F911;Lo;0;L;23F8E;;;;N;;;;;
-2F912;CJK COMPATIBILITY IDEOGRAPH-2F912;Lo;0;L;6FC6;;;;N;;;;;
-2F913;CJK COMPATIBILITY IDEOGRAPH-2F913;Lo;0;L;7039;;;;N;;;;;
-2F914;CJK COMPATIBILITY IDEOGRAPH-2F914;Lo;0;L;701E;;;;N;;;;;
-2F915;CJK COMPATIBILITY IDEOGRAPH-2F915;Lo;0;L;701B;;;;N;;;;;
-2F916;CJK COMPATIBILITY IDEOGRAPH-2F916;Lo;0;L;3D96;;;;N;;;;;
-2F917;CJK COMPATIBILITY IDEOGRAPH-2F917;Lo;0;L;704A;;;;N;;;;;
-2F918;CJK COMPATIBILITY IDEOGRAPH-2F918;Lo;0;L;707D;;;;N;;;;;
-2F919;CJK COMPATIBILITY IDEOGRAPH-2F919;Lo;0;L;7077;;;;N;;;;;
-2F91A;CJK COMPATIBILITY IDEOGRAPH-2F91A;Lo;0;L;70AD;;;;N;;;;;
-2F91B;CJK COMPATIBILITY IDEOGRAPH-2F91B;Lo;0;L;20525;;;;N;;;;;
-2F91C;CJK COMPATIBILITY IDEOGRAPH-2F91C;Lo;0;L;7145;;;;N;;;;;
-2F91D;CJK COMPATIBILITY IDEOGRAPH-2F91D;Lo;0;L;24263;;;;N;;;;;
-2F91E;CJK COMPATIBILITY IDEOGRAPH-2F91E;Lo;0;L;719C;;;;N;;;;;
-2F91F;CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo;0;L;243AB;;;;N;;;;;
-2F920;CJK COMPATIBILITY IDEOGRAPH-2F920;Lo;0;L;7228;;;;N;;;;;
-2F921;CJK COMPATIBILITY IDEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;;
-2F922;CJK COMPATIBILITY IDEOGRAPH-2F922;Lo;0;L;7250;;;;N;;;;;
-2F923;CJK COMPATIBILITY IDEOGRAPH-2F923;Lo;0;L;24608;;;;N;;;;;
-2F924;CJK COMPATIBILITY IDEOGRAPH-2F924;Lo;0;L;7280;;;;N;;;;;
-2F925;CJK COMPATIBILITY IDEOGRAPH-2F925;Lo;0;L;7295;;;;N;;;;;
-2F926;CJK COMPATIBILITY IDEOGRAPH-2F926;Lo;0;L;24735;;;;N;;;;;
-2F927;CJK COMPATIBILITY IDEOGRAPH-2F927;Lo;0;L;24814;;;;N;;;;;
-2F928;CJK COMPATIBILITY IDEOGRAPH-2F928;Lo;0;L;737A;;;;N;;;;;
-2F929;CJK COMPATIBILITY IDEOGRAPH-2F929;Lo;0;L;738B;;;;N;;;;;
-2F92A;CJK COMPATIBILITY IDEOGRAPH-2F92A;Lo;0;L;3EAC;;;;N;;;;;
-2F92B;CJK COMPATIBILITY IDEOGRAPH-2F92B;Lo;0;L;73A5;;;;N;;;;;
-2F92C;CJK COMPATIBILITY IDEOGRAPH-2F92C;Lo;0;L;3EB8;;;;N;;;;;
-2F92D;CJK COMPATIBILITY IDEOGRAPH-2F92D;Lo;0;L;3EB8;;;;N;;;;;
-2F92E;CJK COMPATIBILITY IDEOGRAPH-2F92E;Lo;0;L;7447;;;;N;;;;;
-2F92F;CJK COMPATIBILITY IDEOGRAPH-2F92F;Lo;0;L;745C;;;;N;;;;;
-2F930;CJK COMPATIBILITY IDEOGRAPH-2F930;Lo;0;L;7471;;;;N;;;;;
-2F931;CJK COMPATIBILITY IDEOGRAPH-2F931;Lo;0;L;7485;;;;N;;;;;
-2F932;CJK COMPATIBILITY IDEOGRAPH-2F932;Lo;0;L;74CA;;;;N;;;;;
-2F933;CJK COMPATIBILITY IDEOGRAPH-2F933;Lo;0;L;3F1B;;;;N;;;;;
-2F934;CJK COMPATIBILITY IDEOGRAPH-2F934;Lo;0;L;7524;;;;N;;;;;
-2F935;CJK COMPATIBILITY IDEOGRAPH-2F935;Lo;0;L;24C36;;;;N;;;;;
-2F936;CJK COMPATIBILITY IDEOGRAPH-2F936;Lo;0;L;753E;;;;N;;;;;
-2F937;CJK COMPATIBILITY IDEOGRAPH-2F937;Lo;0;L;24C92;;;;N;;;;;
-2F938;CJK COMPATIBILITY IDEOGRAPH-2F938;Lo;0;L;7570;;;;N;;;;;
-2F939;CJK COMPATIBILITY IDEOGRAPH-2F939;Lo;0;L;2219F;;;;N;;;;;
-2F93A;CJK COMPATIBILITY IDEOGRAPH-2F93A;Lo;0;L;7610;;;;N;;;;;
-2F93B;CJK COMPATIBILITY IDEOGRAPH-2F93B;Lo;0;L;24FA1;;;;N;;;;;
-2F93C;CJK COMPATIBILITY IDEOGRAPH-2F93C;Lo;0;L;24FB8;;;;N;;;;;
-2F93D;CJK COMPATIBILITY IDEOGRAPH-2F93D;Lo;0;L;25044;;;;N;;;;;
-2F93E;CJK COMPATIBILITY IDEOGRAPH-2F93E;Lo;0;L;3FFC;;;;N;;;;;
-2F93F;CJK COMPATIBILITY IDEOGRAPH-2F93F;Lo;0;L;4008;;;;N;;;;;
-2F940;CJK COMPATIBILITY IDEOGRAPH-2F940;Lo;0;L;76F4;;;;N;;;;;
-2F941;CJK COMPATIBILITY IDEOGRAPH-2F941;Lo;0;L;250F3;;;;N;;;;;
-2F942;CJK COMPATIBILITY IDEOGRAPH-2F942;Lo;0;L;250F2;;;;N;;;;;
-2F943;CJK COMPATIBILITY IDEOGRAPH-2F943;Lo;0;L;25119;;;;N;;;;;
-2F944;CJK COMPATIBILITY IDEOGRAPH-2F944;Lo;0;L;25133;;;;N;;;;;
-2F945;CJK COMPATIBILITY IDEOGRAPH-2F945;Lo;0;L;771E;;;;N;;;;;
-2F946;CJK COMPATIBILITY IDEOGRAPH-2F946;Lo;0;L;771F;;;;N;;;;;
-2F947;CJK COMPATIBILITY IDEOGRAPH-2F947;Lo;0;L;771F;;;;N;;;;;
-2F948;CJK COMPATIBILITY IDEOGRAPH-2F948;Lo;0;L;774A;;;;N;;;;;
-2F949;CJK COMPATIBILITY IDEOGRAPH-2F949;Lo;0;L;4039;;;;N;;;;;
-2F94A;CJK COMPATIBILITY IDEOGRAPH-2F94A;Lo;0;L;778B;;;;N;;;;;
-2F94B;CJK COMPATIBILITY IDEOGRAPH-2F94B;Lo;0;L;4046;;;;N;;;;;
-2F94C;CJK COMPATIBILITY IDEOGRAPH-2F94C;Lo;0;L;4096;;;;N;;;;;
-2F94D;CJK COMPATIBILITY IDEOGRAPH-2F94D;Lo;0;L;2541D;;;;N;;;;;
-2F94E;CJK COMPATIBILITY IDEOGRAPH-2F94E;Lo;0;L;784E;;;;N;;;;;
-2F94F;CJK COMPATIBILITY IDEOGRAPH-2F94F;Lo;0;L;788C;;;;N;;;;;
-2F950;CJK COMPATIBILITY IDEOGRAPH-2F950;Lo;0;L;78CC;;;;N;;;;;
-2F951;CJK COMPATIBILITY IDEOGRAPH-2F951;Lo;0;L;40E3;;;;N;;;;;
-2F952;CJK COMPATIBILITY IDEOGRAPH-2F952;Lo;0;L;25626;;;;N;;;;;
-2F953;CJK COMPATIBILITY IDEOGRAPH-2F953;Lo;0;L;7956;;;;N;;;;;
-2F954;CJK COMPATIBILITY IDEOGRAPH-2F954;Lo;0;L;2569A;;;;N;;;;;
-2F955;CJK COMPATIBILITY IDEOGRAPH-2F955;Lo;0;L;256C5;;;;N;;;;;
-2F956;CJK COMPATIBILITY IDEOGRAPH-2F956;Lo;0;L;798F;;;;N;;;;;
-2F957;CJK COMPATIBILITY IDEOGRAPH-2F957;Lo;0;L;79EB;;;;N;;;;;
-2F958;CJK COMPATIBILITY IDEOGRAPH-2F958;Lo;0;L;412F;;;;N;;;;;
-2F959;CJK COMPATIBILITY IDEOGRAPH-2F959;Lo;0;L;7A40;;;;N;;;;;
-2F95A;CJK COMPATIBILITY IDEOGRAPH-2F95A;Lo;0;L;7A4A;;;;N;;;;;
-2F95B;CJK COMPATIBILITY IDEOGRAPH-2F95B;Lo;0;L;7A4F;;;;N;;;;;
-2F95C;CJK COMPATIBILITY IDEOGRAPH-2F95C;Lo;0;L;2597C;;;;N;;;;;
-2F95D;CJK COMPATIBILITY IDEOGRAPH-2F95D;Lo;0;L;25AA7;;;;N;;;;;
-2F95E;CJK COMPATIBILITY IDEOGRAPH-2F95E;Lo;0;L;25AA7;;;;N;;;;;
-2F95F;CJK COMPATIBILITY IDEOGRAPH-2F95F;Lo;0;L;7AEE;;;;N;;;;;
-2F960;CJK COMPATIBILITY IDEOGRAPH-2F960;Lo;0;L;4202;;;;N;;;;;
-2F961;CJK COMPATIBILITY IDEOGRAPH-2F961;Lo;0;L;25BAB;;;;N;;;;;
-2F962;CJK COMPATIBILITY IDEOGRAPH-2F962;Lo;0;L;7BC6;;;;N;;;;;
-2F963;CJK COMPATIBILITY IDEOGRAPH-2F963;Lo;0;L;7BC9;;;;N;;;;;
-2F964;CJK COMPATIBILITY IDEOGRAPH-2F964;Lo;0;L;4227;;;;N;;;;;
-2F965;CJK COMPATIBILITY IDEOGRAPH-2F965;Lo;0;L;25C80;;;;N;;;;;
-2F966;CJK COMPATIBILITY IDEOGRAPH-2F966;Lo;0;L;7CD2;;;;N;;;;;
-2F967;CJK COMPATIBILITY IDEOGRAPH-2F967;Lo;0;L;42A0;;;;N;;;;;
-2F968;CJK COMPATIBILITY IDEOGRAPH-2F968;Lo;0;L;7CE8;;;;N;;;;;
-2F969;CJK COMPATIBILITY IDEOGRAPH-2F969;Lo;0;L;7CE3;;;;N;;;;;
-2F96A;CJK COMPATIBILITY IDEOGRAPH-2F96A;Lo;0;L;7D00;;;;N;;;;;
-2F96B;CJK COMPATIBILITY IDEOGRAPH-2F96B;Lo;0;L;25F86;;;;N;;;;;
-2F96C;CJK COMPATIBILITY IDEOGRAPH-2F96C;Lo;0;L;7D63;;;;N;;;;;
-2F96D;CJK COMPATIBILITY IDEOGRAPH-2F96D;Lo;0;L;4301;;;;N;;;;;
-2F96E;CJK COMPATIBILITY IDEOGRAPH-2F96E;Lo;0;L;7DC7;;;;N;;;;;
-2F96F;CJK COMPATIBILITY IDEOGRAPH-2F96F;Lo;0;L;7E02;;;;N;;;;;
-2F970;CJK COMPATIBILITY IDEOGRAPH-2F970;Lo;0;L;7E45;;;;N;;;;;
-2F971;CJK COMPATIBILITY IDEOGRAPH-2F971;Lo;0;L;4334;;;;N;;;;;
-2F972;CJK COMPATIBILITY IDEOGRAPH-2F972;Lo;0;L;26228;;;;N;;;;;
-2F973;CJK COMPATIBILITY IDEOGRAPH-2F973;Lo;0;L;26247;;;;N;;;;;
-2F974;CJK COMPATIBILITY IDEOGRAPH-2F974;Lo;0;L;4359;;;;N;;;;;
-2F975;CJK COMPATIBILITY IDEOGRAPH-2F975;Lo;0;L;262D9;;;;N;;;;;
-2F976;CJK COMPATIBILITY IDEOGRAPH-2F976;Lo;0;L;7F7A;;;;N;;;;;
-2F977;CJK COMPATIBILITY IDEOGRAPH-2F977;Lo;0;L;2633E;;;;N;;;;;
-2F978;CJK COMPATIBILITY IDEOGRAPH-2F978;Lo;0;L;7F95;;;;N;;;;;
-2F979;CJK COMPATIBILITY IDEOGRAPH-2F979;Lo;0;L;7FFA;;;;N;;;;;
-2F97A;CJK COMPATIBILITY IDEOGRAPH-2F97A;Lo;0;L;8005;;;;N;;;;;
-2F97B;CJK COMPATIBILITY IDEOGRAPH-2F97B;Lo;0;L;264DA;;;;N;;;;;
-2F97C;CJK COMPATIBILITY IDEOGRAPH-2F97C;Lo;0;L;26523;;;;N;;;;;
-2F97D;CJK COMPATIBILITY IDEOGRAPH-2F97D;Lo;0;L;8060;;;;N;;;;;
-2F97E;CJK COMPATIBILITY IDEOGRAPH-2F97E;Lo;0;L;265A8;;;;N;;;;;
-2F97F;CJK COMPATIBILITY IDEOGRAPH-2F97F;Lo;0;L;8070;;;;N;;;;;
-2F980;CJK COMPATIBILITY IDEOGRAPH-2F980;Lo;0;L;2335F;;;;N;;;;;
-2F981;CJK COMPATIBILITY IDEOGRAPH-2F981;Lo;0;L;43D5;;;;N;;;;;
-2F982;CJK COMPATIBILITY IDEOGRAPH-2F982;Lo;0;L;80B2;;;;N;;;;;
-2F983;CJK COMPATIBILITY IDEOGRAPH-2F983;Lo;0;L;8103;;;;N;;;;;
-2F984;CJK COMPATIBILITY IDEOGRAPH-2F984;Lo;0;L;440B;;;;N;;;;;
-2F985;CJK COMPATIBILITY IDEOGRAPH-2F985;Lo;0;L;813E;;;;N;;;;;
-2F986;CJK COMPATIBILITY IDEOGRAPH-2F986;Lo;0;L;5AB5;;;;N;;;;;
-2F987;CJK COMPATIBILITY IDEOGRAPH-2F987;Lo;0;L;267A7;;;;N;;;;;
-2F988;CJK COMPATIBILITY IDEOGRAPH-2F988;Lo;0;L;267B5;;;;N;;;;;
-2F989;CJK COMPATIBILITY IDEOGRAPH-2F989;Lo;0;L;23393;;;;N;;;;;
-2F98A;CJK COMPATIBILITY IDEOGRAPH-2F98A;Lo;0;L;2339C;;;;N;;;;;
-2F98B;CJK COMPATIBILITY IDEOGRAPH-2F98B;Lo;0;L;8201;;;;N;;;;;
-2F98C;CJK COMPATIBILITY IDEOGRAPH-2F98C;Lo;0;L;8204;;;;N;;;;;
-2F98D;CJK COMPATIBILITY IDEOGRAPH-2F98D;Lo;0;L;8F9E;;;;N;;;;;
-2F98E;CJK COMPATIBILITY IDEOGRAPH-2F98E;Lo;0;L;446B;;;;N;;;;;
-2F98F;CJK COMPATIBILITY IDEOGRAPH-2F98F;Lo;0;L;8291;;;;N;;;;;
-2F990;CJK COMPATIBILITY IDEOGRAPH-2F990;Lo;0;L;828B;;;;N;;;;;
-2F991;CJK COMPATIBILITY IDEOGRAPH-2F991;Lo;0;L;829D;;;;N;;;;;
-2F992;CJK COMPATIBILITY IDEOGRAPH-2F992;Lo;0;L;52B3;;;;N;;;;;
-2F993;CJK COMPATIBILITY IDEOGRAPH-2F993;Lo;0;L;82B1;;;;N;;;;;
-2F994;CJK COMPATIBILITY IDEOGRAPH-2F994;Lo;0;L;82B3;;;;N;;;;;
-2F995;CJK COMPATIBILITY IDEOGRAPH-2F995;Lo;0;L;82BD;;;;N;;;;;
-2F996;CJK COMPATIBILITY IDEOGRAPH-2F996;Lo;0;L;82E6;;;;N;;;;;
-2F997;CJK COMPATIBILITY IDEOGRAPH-2F997;Lo;0;L;26B3C;;;;N;;;;;
-2F998;CJK COMPATIBILITY IDEOGRAPH-2F998;Lo;0;L;82E5;;;;N;;;;;
-2F999;CJK COMPATIBILITY IDEOGRAPH-2F999;Lo;0;L;831D;;;;N;;;;;
-2F99A;CJK COMPATIBILITY IDEOGRAPH-2F99A;Lo;0;L;8363;;;;N;;;;;
-2F99B;CJK COMPATIBILITY IDEOGRAPH-2F99B;Lo;0;L;83AD;;;;N;;;;;
-2F99C;CJK COMPATIBILITY IDEOGRAPH-2F99C;Lo;0;L;8323;;;;N;;;;;
-2F99D;CJK COMPATIBILITY IDEOGRAPH-2F99D;Lo;0;L;83BD;;;;N;;;;;
-2F99E;CJK COMPATIBILITY IDEOGRAPH-2F99E;Lo;0;L;83E7;;;;N;;;;;
-2F99F;CJK COMPATIBILITY IDEOGRAPH-2F99F;Lo;0;L;8457;;;;N;;;;;
-2F9A0;CJK COMPATIBILITY IDEOGRAPH-2F9A0;Lo;0;L;8353;;;;N;;;;;
-2F9A1;CJK COMPATIBILITY IDEOGRAPH-2F9A1;Lo;0;L;83CA;;;;N;;;;;
-2F9A2;CJK COMPATIBILITY IDEOGRAPH-2F9A2;Lo;0;L;83CC;;;;N;;;;;
-2F9A3;CJK COMPATIBILITY IDEOGRAPH-2F9A3;Lo;0;L;83DC;;;;N;;;;;
-2F9A4;CJK COMPATIBILITY IDEOGRAPH-2F9A4;Lo;0;L;26C36;;;;N;;;;;
-2F9A5;CJK COMPATIBILITY IDEOGRAPH-2F9A5;Lo;0;L;26D6B;;;;N;;;;;
-2F9A6;CJK COMPATIBILITY IDEOGRAPH-2F9A6;Lo;0;L;26CD5;;;;N;;;;;
-2F9A7;CJK COMPATIBILITY IDEOGRAPH-2F9A7;Lo;0;L;452B;;;;N;;;;;
-2F9A8;CJK COMPATIBILITY IDEOGRAPH-2F9A8;Lo;0;L;84F1;;;;N;;;;;
-2F9A9;CJK COMPATIBILITY IDEOGRAPH-2F9A9;Lo;0;L;84F3;;;;N;;;;;
-2F9AA;CJK COMPATIBILITY IDEOGRAPH-2F9AA;Lo;0;L;8516;;;;N;;;;;
-2F9AB;CJK COMPATIBILITY IDEOGRAPH-2F9AB;Lo;0;L;273CA;;;;N;;;;;
-2F9AC;CJK COMPATIBILITY IDEOGRAPH-2F9AC;Lo;0;L;8564;;;;N;;;;;
-2F9AD;CJK COMPATIBILITY IDEOGRAPH-2F9AD;Lo;0;L;26F2C;;;;N;;;;;
-2F9AE;CJK COMPATIBILITY IDEOGRAPH-2F9AE;Lo;0;L;455D;;;;N;;;;;
-2F9AF;CJK COMPATIBILITY IDEOGRAPH-2F9AF;Lo;0;L;4561;;;;N;;;;;
-2F9B0;CJK COMPATIBILITY IDEOGRAPH-2F9B0;Lo;0;L;26FB1;;;;N;;;;;
-2F9B1;CJK COMPATIBILITY IDEOGRAPH-2F9B1;Lo;0;L;270D2;;;;N;;;;;
-2F9B2;CJK COMPATIBILITY IDEOGRAPH-2F9B2;Lo;0;L;456B;;;;N;;;;;
-2F9B3;CJK COMPATIBILITY IDEOGRAPH-2F9B3;Lo;0;L;8650;;;;N;;;;;
-2F9B4;CJK COMPATIBILITY IDEOGRAPH-2F9B4;Lo;0;L;865C;;;;N;;;;;
-2F9B5;CJK COMPATIBILITY IDEOGRAPH-2F9B5;Lo;0;L;8667;;;;N;;;;;
-2F9B6;CJK COMPATIBILITY IDEOGRAPH-2F9B6;Lo;0;L;8669;;;;N;;;;;
-2F9B7;CJK COMPATIBILITY IDEOGRAPH-2F9B7;Lo;0;L;86A9;;;;N;;;;;
-2F9B8;CJK COMPATIBILITY IDEOGRAPH-2F9B8;Lo;0;L;8688;;;;N;;;;;
-2F9B9;CJK COMPATIBILITY IDEOGRAPH-2F9B9;Lo;0;L;870E;;;;N;;;;;
-2F9BA;CJK COMPATIBILITY IDEOGRAPH-2F9BA;Lo;0;L;86E2;;;;N;;;;;
-2F9BB;CJK COMPATIBILITY IDEOGRAPH-2F9BB;Lo;0;L;8779;;;;N;;;;;
-2F9BC;CJK COMPATIBILITY IDEOGRAPH-2F9BC;Lo;0;L;8728;;;;N;;;;;
-2F9BD;CJK COMPATIBILITY IDEOGRAPH-2F9BD;Lo;0;L;876B;;;;N;;;;;
-2F9BE;CJK COMPATIBILITY IDEOGRAPH-2F9BE;Lo;0;L;8786;;;;N;;;;;
-2F9BF;CJK COMPATIBILITY IDEOGRAPH-2F9BF;Lo;0;L;45D7;;;;N;;;;;
-2F9C0;CJK COMPATIBILITY IDEOGRAPH-2F9C0;Lo;0;L;87E1;;;;N;;;;;
-2F9C1;CJK COMPATIBILITY IDEOGRAPH-2F9C1;Lo;0;L;8801;;;;N;;;;;
-2F9C2;CJK COMPATIBILITY IDEOGRAPH-2F9C2;Lo;0;L;45F9;;;;N;;;;;
-2F9C3;CJK COMPATIBILITY IDEOGRAPH-2F9C3;Lo;0;L;8860;;;;N;;;;;
-2F9C4;CJK COMPATIBILITY IDEOGRAPH-2F9C4;Lo;0;L;8863;;;;N;;;;;
-2F9C5;CJK COMPATIBILITY IDEOGRAPH-2F9C5;Lo;0;L;27667;;;;N;;;;;
-2F9C6;CJK COMPATIBILITY IDEOGRAPH-2F9C6;Lo;0;L;88D7;;;;N;;;;;
-2F9C7;CJK COMPATIBILITY IDEOGRAPH-2F9C7;Lo;0;L;88DE;;;;N;;;;;
-2F9C8;CJK COMPATIBILITY IDEOGRAPH-2F9C8;Lo;0;L;4635;;;;N;;;;;
-2F9C9;CJK COMPATIBILITY IDEOGRAPH-2F9C9;Lo;0;L;88FA;;;;N;;;;;
-2F9CA;CJK COMPATIBILITY IDEOGRAPH-2F9CA;Lo;0;L;34BB;;;;N;;;;;
-2F9CB;CJK COMPATIBILITY IDEOGRAPH-2F9CB;Lo;0;L;278AE;;;;N;;;;;
-2F9CC;CJK COMPATIBILITY IDEOGRAPH-2F9CC;Lo;0;L;27966;;;;N;;;;;
-2F9CD;CJK COMPATIBILITY IDEOGRAPH-2F9CD;Lo;0;L;46BE;;;;N;;;;;
-2F9CE;CJK COMPATIBILITY IDEOGRAPH-2F9CE;Lo;0;L;46C7;;;;N;;;;;
-2F9CF;CJK COMPATIBILITY IDEOGRAPH-2F9CF;Lo;0;L;8AA0;;;;N;;;;;
-2F9D0;CJK COMPATIBILITY IDEOGRAPH-2F9D0;Lo;0;L;8AED;;;;N;;;;;
-2F9D1;CJK COMPATIBILITY IDEOGRAPH-2F9D1;Lo;0;L;8B8A;;;;N;;;;;
-2F9D2;CJK COMPATIBILITY IDEOGRAPH-2F9D2;Lo;0;L;8C55;;;;N;;;;;
-2F9D3;CJK COMPATIBILITY IDEOGRAPH-2F9D3;Lo;0;L;27CA8;;;;N;;;;;
-2F9D4;CJK COMPATIBILITY IDEOGRAPH-2F9D4;Lo;0;L;8CAB;;;;N;;;;;
-2F9D5;CJK COMPATIBILITY IDEOGRAPH-2F9D5;Lo;0;L;8CC1;;;;N;;;;;
-2F9D6;CJK COMPATIBILITY IDEOGRAPH-2F9D6;Lo;0;L;8D1B;;;;N;;;;;
-2F9D7;CJK COMPATIBILITY IDEOGRAPH-2F9D7;Lo;0;L;8D77;;;;N;;;;;
-2F9D8;CJK COMPATIBILITY IDEOGRAPH-2F9D8;Lo;0;L;27F2F;;;;N;;;;;
-2F9D9;CJK COMPATIBILITY IDEOGRAPH-2F9D9;Lo;0;L;20804;;;;N;;;;;
-2F9DA;CJK COMPATIBILITY IDEOGRAPH-2F9DA;Lo;0;L;8DCB;;;;N;;;;;
-2F9DB;CJK COMPATIBILITY IDEOGRAPH-2F9DB;Lo;0;L;8DBC;;;;N;;;;;
-2F9DC;CJK COMPATIBILITY IDEOGRAPH-2F9DC;Lo;0;L;8DF0;;;;N;;;;;
-2F9DD;CJK COMPATIBILITY IDEOGRAPH-2F9DD;Lo;0;L;208DE;;;;N;;;;;
-2F9DE;CJK COMPATIBILITY IDEOGRAPH-2F9DE;Lo;0;L;8ED4;;;;N;;;;;
-2F9DF;CJK COMPATIBILITY IDEOGRAPH-2F9DF;Lo;0;L;8F38;;;;N;;;;;
-2F9E0;CJK COMPATIBILITY IDEOGRAPH-2F9E0;Lo;0;L;285D2;;;;N;;;;;
-2F9E1;CJK COMPATIBILITY IDEOGRAPH-2F9E1;Lo;0;L;285ED;;;;N;;;;;
-2F9E2;CJK COMPATIBILITY IDEOGRAPH-2F9E2;Lo;0;L;9094;;;;N;;;;;
-2F9E3;CJK COMPATIBILITY IDEOGRAPH-2F9E3;Lo;0;L;90F1;;;;N;;;;;
-2F9E4;CJK COMPATIBILITY IDEOGRAPH-2F9E4;Lo;0;L;9111;;;;N;;;;;
-2F9E5;CJK COMPATIBILITY IDEOGRAPH-2F9E5;Lo;0;L;2872E;;;;N;;;;;
-2F9E6;CJK COMPATIBILITY IDEOGRAPH-2F9E6;Lo;0;L;911B;;;;N;;;;;
-2F9E7;CJK COMPATIBILITY IDEOGRAPH-2F9E7;Lo;0;L;9238;;;;N;;;;;
-2F9E8;CJK COMPATIBILITY IDEOGRAPH-2F9E8;Lo;0;L;92D7;;;;N;;;;;
-2F9E9;CJK COMPATIBILITY IDEOGRAPH-2F9E9;Lo;0;L;92D8;;;;N;;;;;
-2F9EA;CJK COMPATIBILITY IDEOGRAPH-2F9EA;Lo;0;L;927C;;;;N;;;;;
-2F9EB;CJK COMPATIBILITY IDEOGRAPH-2F9EB;Lo;0;L;93F9;;;;N;;;;;
-2F9EC;CJK COMPATIBILITY IDEOGRAPH-2F9EC;Lo;0;L;9415;;;;N;;;;;
-2F9ED;CJK COMPATIBILITY IDEOGRAPH-2F9ED;Lo;0;L;28BFA;;;;N;;;;;
-2F9EE;CJK COMPATIBILITY IDEOGRAPH-2F9EE;Lo;0;L;958B;;;;N;;;;;
-2F9EF;CJK COMPATIBILITY IDEOGRAPH-2F9EF;Lo;0;L;4995;;;;N;;;;;
-2F9F0;CJK COMPATIBILITY IDEOGRAPH-2F9F0;Lo;0;L;95B7;;;;N;;;;;
-2F9F1;CJK COMPATIBILITY IDEOGRAPH-2F9F1;Lo;0;L;28D77;;;;N;;;;;
-2F9F2;CJK COMPATIBILITY IDEOGRAPH-2F9F2;Lo;0;L;49E6;;;;N;;;;;
-2F9F3;CJK COMPATIBILITY IDEOGRAPH-2F9F3;Lo;0;L;96C3;;;;N;;;;;
-2F9F4;CJK COMPATIBILITY IDEOGRAPH-2F9F4;Lo;0;L;5DB2;;;;N;;;;;
-2F9F5;CJK COMPATIBILITY IDEOGRAPH-2F9F5;Lo;0;L;9723;;;;N;;;;;
-2F9F6;CJK COMPATIBILITY IDEOGRAPH-2F9F6;Lo;0;L;29145;;;;N;;;;;
-2F9F7;CJK COMPATIBILITY IDEOGRAPH-2F9F7;Lo;0;L;2921A;;;;N;;;;;
-2F9F8;CJK COMPATIBILITY IDEOGRAPH-2F9F8;Lo;0;L;4A6E;;;;N;;;;;
-2F9F9;CJK COMPATIBILITY IDEOGRAPH-2F9F9;Lo;0;L;4A76;;;;N;;;;;
-2F9FA;CJK COMPATIBILITY IDEOGRAPH-2F9FA;Lo;0;L;97E0;;;;N;;;;;
-2F9FB;CJK COMPATIBILITY IDEOGRAPH-2F9FB;Lo;0;L;2940A;;;;N;;;;;
-2F9FC;CJK COMPATIBILITY IDEOGRAPH-2F9FC;Lo;0;L;4AB2;;;;N;;;;;
-2F9FD;CJK COMPATIBILITY IDEOGRAPH-2F9FD;Lo;0;L;29496;;;;N;;;;;
-2F9FE;CJK COMPATIBILITY IDEOGRAPH-2F9FE;Lo;0;L;980B;;;;N;;;;;
-2F9FF;CJK COMPATIBILITY IDEOGRAPH-2F9FF;Lo;0;L;980B;;;;N;;;;;
-2FA00;CJK COMPATIBILITY IDEOGRAPH-2FA00;Lo;0;L;9829;;;;N;;;;;
-2FA01;CJK COMPATIBILITY IDEOGRAPH-2FA01;Lo;0;L;295B6;;;;N;;;;;
-2FA02;CJK COMPATIBILITY IDEOGRAPH-2FA02;Lo;0;L;98E2;;;;N;;;;;
-2FA03;CJK COMPATIBILITY IDEOGRAPH-2FA03;Lo;0;L;4B33;;;;N;;;;;
-2FA04;CJK COMPATIBILITY IDEOGRAPH-2FA04;Lo;0;L;9929;;;;N;;;;;
-2FA05;CJK COMPATIBILITY IDEOGRAPH-2FA05;Lo;0;L;99A7;;;;N;;;;;
-2FA06;CJK COMPATIBILITY IDEOGRAPH-2FA06;Lo;0;L;99C2;;;;N;;;;;
-2FA07;CJK COMPATIBILITY IDEOGRAPH-2FA07;Lo;0;L;99FE;;;;N;;;;;
-2FA08;CJK COMPATIBILITY IDEOGRAPH-2FA08;Lo;0;L;4BCE;;;;N;;;;;
-2FA09;CJK COMPATIBILITY IDEOGRAPH-2FA09;Lo;0;L;29B30;;;;N;;;;;
-2FA0A;CJK COMPATIBILITY IDEOGRAPH-2FA0A;Lo;0;L;9B12;;;;N;;;;;
-2FA0B;CJK COMPATIBILITY IDEOGRAPH-2FA0B;Lo;0;L;9C40;;;;N;;;;;
-2FA0C;CJK COMPATIBILITY IDEOGRAPH-2FA0C;Lo;0;L;9CFD;;;;N;;;;;
-2FA0D;CJK COMPATIBILITY IDEOGRAPH-2FA0D;Lo;0;L;4CCE;;;;N;;;;;
-2FA0E;CJK COMPATIBILITY IDEOGRAPH-2FA0E;Lo;0;L;4CED;;;;N;;;;;
-2FA0F;CJK COMPATIBILITY IDEOGRAPH-2FA0F;Lo;0;L;9D67;;;;N;;;;;
-2FA10;CJK COMPATIBILITY IDEOGRAPH-2FA10;Lo;0;L;2A0CE;;;;N;;;;;
-2FA11;CJK COMPATIBILITY IDEOGRAPH-2FA11;Lo;0;L;4CF8;;;;N;;;;;
-2FA12;CJK COMPATIBILITY IDEOGRAPH-2FA12;Lo;0;L;2A105;;;;N;;;;;
-2FA13;CJK COMPATIBILITY IDEOGRAPH-2FA13;Lo;0;L;2A20E;;;;N;;;;;
-2FA14;CJK COMPATIBILITY IDEOGRAPH-2FA14;Lo;0;L;2A291;;;;N;;;;;
-2FA15;CJK COMPATIBILITY IDEOGRAPH-2FA15;Lo;0;L;9EBB;;;;N;;;;;
-2FA16;CJK COMPATIBILITY IDEOGRAPH-2FA16;Lo;0;L;4D56;;;;N;;;;;
-2FA17;CJK COMPATIBILITY IDEOGRAPH-2FA17;Lo;0;L;9EF9;;;;N;;;;;
-2FA18;CJK COMPATIBILITY IDEOGRAPH-2FA18;Lo;0;L;9EFE;;;;N;;;;;
-2FA19;CJK COMPATIBILITY IDEOGRAPH-2FA19;Lo;0;L;9F05;;;;N;;;;;
-2FA1A;CJK COMPATIBILITY IDEOGRAPH-2FA1A;Lo;0;L;9F0F;;;;N;;;;;
-2FA1B;CJK COMPATIBILITY IDEOGRAPH-2FA1B;Lo;0;L;9F16;;;;N;;;;;
-2FA1C;CJK COMPATIBILITY IDEOGRAPH-2FA1C;Lo;0;L;9F3B;;;;N;;;;;
-2FA1D;CJK COMPATIBILITY IDEOGRAPH-2FA1D;Lo;0;L;2A600;;;;N;;;;;
-E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;;
-E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;;
-E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;;
-E0022;TAG QUOTATION MARK;Cf;0;BN;;;;;N;;;;;
-E0023;TAG NUMBER SIGN;Cf;0;BN;;;;;N;;;;;
-E0024;TAG DOLLAR SIGN;Cf;0;BN;;;;;N;;;;;
-E0025;TAG PERCENT SIGN;Cf;0;BN;;;;;N;;;;;
-E0026;TAG AMPERSAND;Cf;0;BN;;;;;N;;;;;
-E0027;TAG APOSTROPHE;Cf;0;BN;;;;;N;;;;;
-E0028;TAG LEFT PARENTHESIS;Cf;0;BN;;;;;N;;;;;
-E0029;TAG RIGHT PARENTHESIS;Cf;0;BN;;;;;N;;;;;
-E002A;TAG ASTERISK;Cf;0;BN;;;;;N;;;;;
-E002B;TAG PLUS SIGN;Cf;0;BN;;;;;N;;;;;
-E002C;TAG COMMA;Cf;0;BN;;;;;N;;;;;
-E002D;TAG HYPHEN-MINUS;Cf;0;BN;;;;;N;;;;;
-E002E;TAG FULL STOP;Cf;0;BN;;;;;N;;;;;
-E002F;TAG SOLIDUS;Cf;0;BN;;;;;N;;;;;
-E0030;TAG DIGIT ZERO;Cf;0;BN;;;;;N;;;;;
-E0031;TAG DIGIT ONE;Cf;0;BN;;;;;N;;;;;
-E0032;TAG DIGIT TWO;Cf;0;BN;;;;;N;;;;;
-E0033;TAG DIGIT THREE;Cf;0;BN;;;;;N;;;;;
-E0034;TAG DIGIT FOUR;Cf;0;BN;;;;;N;;;;;
-E0035;TAG DIGIT FIVE;Cf;0;BN;;;;;N;;;;;
-E0036;TAG DIGIT SIX;Cf;0;BN;;;;;N;;;;;
-E0037;TAG DIGIT SEVEN;Cf;0;BN;;;;;N;;;;;
-E0038;TAG DIGIT EIGHT;Cf;0;BN;;;;;N;;;;;
-E0039;TAG DIGIT NINE;Cf;0;BN;;;;;N;;;;;
-E003A;TAG COLON;Cf;0;BN;;;;;N;;;;;
-E003B;TAG SEMICOLON;Cf;0;BN;;;;;N;;;;;
-E003C;TAG LESS-THAN SIGN;Cf;0;BN;;;;;N;;;;;
-E003D;TAG EQUALS SIGN;Cf;0;BN;;;;;N;;;;;
-E003E;TAG GREATER-THAN SIGN;Cf;0;BN;;;;;N;;;;;
-E003F;TAG QUESTION MARK;Cf;0;BN;;;;;N;;;;;
-E0040;TAG COMMERCIAL AT;Cf;0;BN;;;;;N;;;;;
-E0041;TAG LATIN CAPITAL LETTER A;Cf;0;BN;;;;;N;;;;;
-E0042;TAG LATIN CAPITAL LETTER B;Cf;0;BN;;;;;N;;;;;
-E0043;TAG LATIN CAPITAL LETTER C;Cf;0;BN;;;;;N;;;;;
-E0044;TAG LATIN CAPITAL LETTER D;Cf;0;BN;;;;;N;;;;;
-E0045;TAG LATIN CAPITAL LETTER E;Cf;0;BN;;;;;N;;;;;
-E0046;TAG LATIN CAPITAL LETTER F;Cf;0;BN;;;;;N;;;;;
-E0047;TAG LATIN CAPITAL LETTER G;Cf;0;BN;;;;;N;;;;;
-E0048;TAG LATIN CAPITAL LETTER H;Cf;0;BN;;;;;N;;;;;
-E0049;TAG LATIN CAPITAL LETTER I;Cf;0;BN;;;;;N;;;;;
-E004A;TAG LATIN CAPITAL LETTER J;Cf;0;BN;;;;;N;;;;;
-E004B;TAG LATIN CAPITAL LETTER K;Cf;0;BN;;;;;N;;;;;
-E004C;TAG LATIN CAPITAL LETTER L;Cf;0;BN;;;;;N;;;;;
-E004D;TAG LATIN CAPITAL LETTER M;Cf;0;BN;;;;;N;;;;;
-E004E;TAG LATIN CAPITAL LETTER N;Cf;0;BN;;;;;N;;;;;
-E004F;TAG LATIN CAPITAL LETTER O;Cf;0;BN;;;;;N;;;;;
-E0050;TAG LATIN CAPITAL LETTER P;Cf;0;BN;;;;;N;;;;;
-E0051;TAG LATIN CAPITAL LETTER Q;Cf;0;BN;;;;;N;;;;;
-E0052;TAG LATIN CAPITAL LETTER R;Cf;0;BN;;;;;N;;;;;
-E0053;TAG LATIN CAPITAL LETTER S;Cf;0;BN;;;;;N;;;;;
-E0054;TAG LATIN CAPITAL LETTER T;Cf;0;BN;;;;;N;;;;;
-E0055;TAG LATIN CAPITAL LETTER U;Cf;0;BN;;;;;N;;;;;
-E0056;TAG LATIN CAPITAL LETTER V;Cf;0;BN;;;;;N;;;;;
-E0057;TAG LATIN CAPITAL LETTER W;Cf;0;BN;;;;;N;;;;;
-E0058;TAG LATIN CAPITAL LETTER X;Cf;0;BN;;;;;N;;;;;
-E0059;TAG LATIN CAPITAL LETTER Y;Cf;0;BN;;;;;N;;;;;
-E005A;TAG LATIN CAPITAL LETTER Z;Cf;0;BN;;;;;N;;;;;
-E005B;TAG LEFT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;;
-E005C;TAG REVERSE SOLIDUS;Cf;0;BN;;;;;N;;;;;
-E005D;TAG RIGHT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;;
-E005E;TAG CIRCUMFLEX ACCENT;Cf;0;BN;;;;;N;;;;;
-E005F;TAG LOW LINE;Cf;0;BN;;;;;N;;;;;
-E0060;TAG GRAVE ACCENT;Cf;0;BN;;;;;N;;;;;
-E0061;TAG LATIN SMALL LETTER A;Cf;0;BN;;;;;N;;;;;
-E0062;TAG LATIN SMALL LETTER B;Cf;0;BN;;;;;N;;;;;
-E0063;TAG LATIN SMALL LETTER C;Cf;0;BN;;;;;N;;;;;
-E0064;TAG LATIN SMALL LETTER D;Cf;0;BN;;;;;N;;;;;
-E0065;TAG LATIN SMALL LETTER E;Cf;0;BN;;;;;N;;;;;
-E0066;TAG LATIN SMALL LETTER F;Cf;0;BN;;;;;N;;;;;
-E0067;TAG LATIN SMALL LETTER G;Cf;0;BN;;;;;N;;;;;
-E0068;TAG LATIN SMALL LETTER H;Cf;0;BN;;;;;N;;;;;
-E0069;TAG LATIN SMALL LETTER I;Cf;0;BN;;;;;N;;;;;
-E006A;TAG LATIN SMALL LETTER J;Cf;0;BN;;;;;N;;;;;
-E006B;TAG LATIN SMALL LETTER K;Cf;0;BN;;;;;N;;;;;
-E006C;TAG LATIN SMALL LETTER L;Cf;0;BN;;;;;N;;;;;
-E006D;TAG LATIN SMALL LETTER M;Cf;0;BN;;;;;N;;;;;
-E006E;TAG LATIN SMALL LETTER N;Cf;0;BN;;;;;N;;;;;
-E006F;TAG LATIN SMALL LETTER O;Cf;0;BN;;;;;N;;;;;
-E0070;TAG LATIN SMALL LETTER P;Cf;0;BN;;;;;N;;;;;
-E0071;TAG LATIN SMALL LETTER Q;Cf;0;BN;;;;;N;;;;;
-E0072;TAG LATIN SMALL LETTER R;Cf;0;BN;;;;;N;;;;;
-E0073;TAG LATIN SMALL LETTER S;Cf;0;BN;;;;;N;;;;;
-E0074;TAG LATIN SMALL LETTER T;Cf;0;BN;;;;;N;;;;;
-E0075;TAG LATIN SMALL LETTER U;Cf;0;BN;;;;;N;;;;;
-E0076;TAG LATIN SMALL LETTER V;Cf;0;BN;;;;;N;;;;;
-E0077;TAG LATIN SMALL LETTER W;Cf;0;BN;;;;;N;;;;;
-E0078;TAG LATIN SMALL LETTER X;Cf;0;BN;;;;;N;;;;;
-E0079;TAG LATIN SMALL LETTER Y;Cf;0;BN;;;;;N;;;;;
-E007A;TAG LATIN SMALL LETTER Z;Cf;0;BN;;;;;N;;;;;
-E007B;TAG LEFT CURLY BRACKET;Cf;0;BN;;;;;N;;;;;
-E007C;TAG VERTICAL LINE;Cf;0;BN;;;;;N;;;;;
-E007D;TAG RIGHT CURLY BRACKET;Cf;0;BN;;;;;N;;;;;
-E007E;TAG TILDE;Cf;0;BN;;;;;N;;;;;
-E007F;CANCEL TAG;Cf;0;BN;;;;;N;;;;;
-E0100;VARIATION SELECTOR-17;Mn;0;NSM;;;;;N;;;;;
-E0101;VARIATION SELECTOR-18;Mn;0;NSM;;;;;N;;;;;
-E0102;VARIATION SELECTOR-19;Mn;0;NSM;;;;;N;;;;;
-E0103;VARIATION SELECTOR-20;Mn;0;NSM;;;;;N;;;;;
-E0104;VARIATION SELECTOR-21;Mn;0;NSM;;;;;N;;;;;
-E0105;VARIATION SELECTOR-22;Mn;0;NSM;;;;;N;;;;;
-E0106;VARIATION SELECTOR-23;Mn;0;NSM;;;;;N;;;;;
-E0107;VARIATION SELECTOR-24;Mn;0;NSM;;;;;N;;;;;
-E0108;VARIATION SELECTOR-25;Mn;0;NSM;;;;;N;;;;;
-E0109;VARIATION SELECTOR-26;Mn;0;NSM;;;;;N;;;;;
-E010A;VARIATION SELECTOR-27;Mn;0;NSM;;;;;N;;;;;
-E010B;VARIATION SELECTOR-28;Mn;0;NSM;;;;;N;;;;;
-E010C;VARIATION SELECTOR-29;Mn;0;NSM;;;;;N;;;;;
-E010D;VARIATION SELECTOR-30;Mn;0;NSM;;;;;N;;;;;
-E010E;VARIATION SELECTOR-31;Mn;0;NSM;;;;;N;;;;;
-E010F;VARIATION SELECTOR-32;Mn;0;NSM;;;;;N;;;;;
-E0110;VARIATION SELECTOR-33;Mn;0;NSM;;;;;N;;;;;
-E0111;VARIATION SELECTOR-34;Mn;0;NSM;;;;;N;;;;;
-E0112;VARIATION SELECTOR-35;Mn;0;NSM;;;;;N;;;;;
-E0113;VARIATION SELECTOR-36;Mn;0;NSM;;;;;N;;;;;
-E0114;VARIATION SELECTOR-37;Mn;0;NSM;;;;;N;;;;;
-E0115;VARIATION SELECTOR-38;Mn;0;NSM;;;;;N;;;;;
-E0116;VARIATION SELECTOR-39;Mn;0;NSM;;;;;N;;;;;
-E0117;VARIATION SELECTOR-40;Mn;0;NSM;;;;;N;;;;;
-E0118;VARIATION SELECTOR-41;Mn;0;NSM;;;;;N;;;;;
-E0119;VARIATION SELECTOR-42;Mn;0;NSM;;;;;N;;;;;
-E011A;VARIATION SELECTOR-43;Mn;0;NSM;;;;;N;;;;;
-E011B;VARIATION SELECTOR-44;Mn;0;NSM;;;;;N;;;;;
-E011C;VARIATION SELECTOR-45;Mn;0;NSM;;;;;N;;;;;
-E011D;VARIATION SELECTOR-46;Mn;0;NSM;;;;;N;;;;;
-E011E;VARIATION SELECTOR-47;Mn;0;NSM;;;;;N;;;;;
-E011F;VARIATION SELECTOR-48;Mn;0;NSM;;;;;N;;;;;
-E0120;VARIATION SELECTOR-49;Mn;0;NSM;;;;;N;;;;;
-E0121;VARIATION SELECTOR-50;Mn;0;NSM;;;;;N;;;;;
-E0122;VARIATION SELECTOR-51;Mn;0;NSM;;;;;N;;;;;
-E0123;VARIATION SELECTOR-52;Mn;0;NSM;;;;;N;;;;;
-E0124;VARIATION SELECTOR-53;Mn;0;NSM;;;;;N;;;;;
-E0125;VARIATION SELECTOR-54;Mn;0;NSM;;;;;N;;;;;
-E0126;VARIATION SELECTOR-55;Mn;0;NSM;;;;;N;;;;;
-E0127;VARIATION SELECTOR-56;Mn;0;NSM;;;;;N;;;;;
-E0128;VARIATION SELECTOR-57;Mn;0;NSM;;;;;N;;;;;
-E0129;VARIATION SELECTOR-58;Mn;0;NSM;;;;;N;;;;;
-E012A;VARIATION SELECTOR-59;Mn;0;NSM;;;;;N;;;;;
-E012B;VARIATION SELECTOR-60;Mn;0;NSM;;;;;N;;;;;
-E012C;VARIATION SELECTOR-61;Mn;0;NSM;;;;;N;;;;;
-E012D;VARIATION SELECTOR-62;Mn;0;NSM;;;;;N;;;;;
-E012E;VARIATION SELECTOR-63;Mn;0;NSM;;;;;N;;;;;
-E012F;VARIATION SELECTOR-64;Mn;0;NSM;;;;;N;;;;;
-E0130;VARIATION SELECTOR-65;Mn;0;NSM;;;;;N;;;;;
-E0131;VARIATION SELECTOR-66;Mn;0;NSM;;;;;N;;;;;
-E0132;VARIATION SELECTOR-67;Mn;0;NSM;;;;;N;;;;;
-E0133;VARIATION SELECTOR-68;Mn;0;NSM;;;;;N;;;;;
-E0134;VARIATION SELECTOR-69;Mn;0;NSM;;;;;N;;;;;
-E0135;VARIATION SELECTOR-70;Mn;0;NSM;;;;;N;;;;;
-E0136;VARIATION SELECTOR-71;Mn;0;NSM;;;;;N;;;;;
-E0137;VARIATION SELECTOR-72;Mn;0;NSM;;;;;N;;;;;
-E0138;VARIATION SELECTOR-73;Mn;0;NSM;;;;;N;;;;;
-E0139;VARIATION SELECTOR-74;Mn;0;NSM;;;;;N;;;;;
-E013A;VARIATION SELECTOR-75;Mn;0;NSM;;;;;N;;;;;
-E013B;VARIATION SELECTOR-76;Mn;0;NSM;;;;;N;;;;;
-E013C;VARIATION SELECTOR-77;Mn;0;NSM;;;;;N;;;;;
-E013D;VARIATION SELECTOR-78;Mn;0;NSM;;;;;N;;;;;
-E013E;VARIATION SELECTOR-79;Mn;0;NSM;;;;;N;;;;;
-E013F;VARIATION SELECTOR-80;Mn;0;NSM;;;;;N;;;;;
-E0140;VARIATION SELECTOR-81;Mn;0;NSM;;;;;N;;;;;
-E0141;VARIATION SELECTOR-82;Mn;0;NSM;;;;;N;;;;;
-E0142;VARIATION SELECTOR-83;Mn;0;NSM;;;;;N;;;;;
-E0143;VARIATION SELECTOR-84;Mn;0;NSM;;;;;N;;;;;
-E0144;VARIATION SELECTOR-85;Mn;0;NSM;;;;;N;;;;;
-E0145;VARIATION SELECTOR-86;Mn;0;NSM;;;;;N;;;;;
-E0146;VARIATION SELECTOR-87;Mn;0;NSM;;;;;N;;;;;
-E0147;VARIATION SELECTOR-88;Mn;0;NSM;;;;;N;;;;;
-E0148;VARIATION SELECTOR-89;Mn;0;NSM;;;;;N;;;;;
-E0149;VARIATION SELECTOR-90;Mn;0;NSM;;;;;N;;;;;
-E014A;VARIATION SELECTOR-91;Mn;0;NSM;;;;;N;;;;;
-E014B;VARIATION SELECTOR-92;Mn;0;NSM;;;;;N;;;;;
-E014C;VARIATION SELECTOR-93;Mn;0;NSM;;;;;N;;;;;
-E014D;VARIATION SELECTOR-94;Mn;0;NSM;;;;;N;;;;;
-E014E;VARIATION SELECTOR-95;Mn;0;NSM;;;;;N;;;;;
-E014F;VARIATION SELECTOR-96;Mn;0;NSM;;;;;N;;;;;
-E0150;VARIATION SELECTOR-97;Mn;0;NSM;;;;;N;;;;;
-E0151;VARIATION SELECTOR-98;Mn;0;NSM;;;;;N;;;;;
-E0152;VARIATION SELECTOR-99;Mn;0;NSM;;;;;N;;;;;
-E0153;VARIATION SELECTOR-100;Mn;0;NSM;;;;;N;;;;;
-E0154;VARIATION SELECTOR-101;Mn;0;NSM;;;;;N;;;;;
-E0155;VARIATION SELECTOR-102;Mn;0;NSM;;;;;N;;;;;
-E0156;VARIATION SELECTOR-103;Mn;0;NSM;;;;;N;;;;;
-E0157;VARIATION SELECTOR-104;Mn;0;NSM;;;;;N;;;;;
-E0158;VARIATION SELECTOR-105;Mn;0;NSM;;;;;N;;;;;
-E0159;VARIATION SELECTOR-106;Mn;0;NSM;;;;;N;;;;;
-E015A;VARIATION SELECTOR-107;Mn;0;NSM;;;;;N;;;;;
-E015B;VARIATION SELECTOR-108;Mn;0;NSM;;;;;N;;;;;
-E015C;VARIATION SELECTOR-109;Mn;0;NSM;;;;;N;;;;;
-E015D;VARIATION SELECTOR-110;Mn;0;NSM;;;;;N;;;;;
-E015E;VARIATION SELECTOR-111;Mn;0;NSM;;;;;N;;;;;
-E015F;VARIATION SELECTOR-112;Mn;0;NSM;;;;;N;;;;;
-E0160;VARIATION SELECTOR-113;Mn;0;NSM;;;;;N;;;;;
-E0161;VARIATION SELECTOR-114;Mn;0;NSM;;;;;N;;;;;
-E0162;VARIATION SELECTOR-115;Mn;0;NSM;;;;;N;;;;;
-E0163;VARIATION SELECTOR-116;Mn;0;NSM;;;;;N;;;;;
-E0164;VARIATION SELECTOR-117;Mn;0;NSM;;;;;N;;;;;
-E0165;VARIATION SELECTOR-118;Mn;0;NSM;;;;;N;;;;;
-E0166;VARIATION SELECTOR-119;Mn;0;NSM;;;;;N;;;;;
-E0167;VARIATION SELECTOR-120;Mn;0;NSM;;;;;N;;;;;
-E0168;VARIATION SELECTOR-121;Mn;0;NSM;;;;;N;;;;;
-E0169;VARIATION SELECTOR-122;Mn;0;NSM;;;;;N;;;;;
-E016A;VARIATION SELECTOR-123;Mn;0;NSM;;;;;N;;;;;
-E016B;VARIATION SELECTOR-124;Mn;0;NSM;;;;;N;;;;;
-E016C;VARIATION SELECTOR-125;Mn;0;NSM;;;;;N;;;;;
-E016D;VARIATION SELECTOR-126;Mn;0;NSM;;;;;N;;;;;
-E016E;VARIATION SELECTOR-127;Mn;0;NSM;;;;;N;;;;;
-E016F;VARIATION SELECTOR-128;Mn;0;NSM;;;;;N;;;;;
-E0170;VARIATION SELECTOR-129;Mn;0;NSM;;;;;N;;;;;
-E0171;VARIATION SELECTOR-130;Mn;0;NSM;;;;;N;;;;;
-E0172;VARIATION SELECTOR-131;Mn;0;NSM;;;;;N;;;;;
-E0173;VARIATION SELECTOR-132;Mn;0;NSM;;;;;N;;;;;
-E0174;VARIATION SELECTOR-133;Mn;0;NSM;;;;;N;;;;;
-E0175;VARIATION SELECTOR-134;Mn;0;NSM;;;;;N;;;;;
-E0176;VARIATION SELECTOR-135;Mn;0;NSM;;;;;N;;;;;
-E0177;VARIATION SELECTOR-136;Mn;0;NSM;;;;;N;;;;;
-E0178;VARIATION SELECTOR-137;Mn;0;NSM;;;;;N;;;;;
-E0179;VARIATION SELECTOR-138;Mn;0;NSM;;;;;N;;;;;
-E017A;VARIATION SELECTOR-139;Mn;0;NSM;;;;;N;;;;;
-E017B;VARIATION SELECTOR-140;Mn;0;NSM;;;;;N;;;;;
-E017C;VARIATION SELECTOR-141;Mn;0;NSM;;;;;N;;;;;
-E017D;VARIATION SELECTOR-142;Mn;0;NSM;;;;;N;;;;;
-E017E;VARIATION SELECTOR-143;Mn;0;NSM;;;;;N;;;;;
-E017F;VARIATION SELECTOR-144;Mn;0;NSM;;;;;N;;;;;
-E0180;VARIATION SELECTOR-145;Mn;0;NSM;;;;;N;;;;;
-E0181;VARIATION SELECTOR-146;Mn;0;NSM;;;;;N;;;;;
-E0182;VARIATION SELECTOR-147;Mn;0;NSM;;;;;N;;;;;
-E0183;VARIATION SELECTOR-148;Mn;0;NSM;;;;;N;;;;;
-E0184;VARIATION SELECTOR-149;Mn;0;NSM;;;;;N;;;;;
-E0185;VARIATION SELECTOR-150;Mn;0;NSM;;;;;N;;;;;
-E0186;VARIATION SELECTOR-151;Mn;0;NSM;;;;;N;;;;;
-E0187;VARIATION SELECTOR-152;Mn;0;NSM;;;;;N;;;;;
-E0188;VARIATION SELECTOR-153;Mn;0;NSM;;;;;N;;;;;
-E0189;VARIATION SELECTOR-154;Mn;0;NSM;;;;;N;;;;;
-E018A;VARIATION SELECTOR-155;Mn;0;NSM;;;;;N;;;;;
-E018B;VARIATION SELECTOR-156;Mn;0;NSM;;;;;N;;;;;
-E018C;VARIATION SELECTOR-157;Mn;0;NSM;;;;;N;;;;;
-E018D;VARIATION SELECTOR-158;Mn;0;NSM;;;;;N;;;;;
-E018E;VARIATION SELECTOR-159;Mn;0;NSM;;;;;N;;;;;
-E018F;VARIATION SELECTOR-160;Mn;0;NSM;;;;;N;;;;;
-E0190;VARIATION SELECTOR-161;Mn;0;NSM;;;;;N;;;;;
-E0191;VARIATION SELECTOR-162;Mn;0;NSM;;;;;N;;;;;
-E0192;VARIATION SELECTOR-163;Mn;0;NSM;;;;;N;;;;;
-E0193;VARIATION SELECTOR-164;Mn;0;NSM;;;;;N;;;;;
-E0194;VARIATION SELECTOR-165;Mn;0;NSM;;;;;N;;;;;
-E0195;VARIATION SELECTOR-166;Mn;0;NSM;;;;;N;;;;;
-E0196;VARIATION SELECTOR-167;Mn;0;NSM;;;;;N;;;;;
-E0197;VARIATION SELECTOR-168;Mn;0;NSM;;;;;N;;;;;
-E0198;VARIATION SELECTOR-169;Mn;0;NSM;;;;;N;;;;;
-E0199;VARIATION SELECTOR-170;Mn;0;NSM;;;;;N;;;;;
-E019A;VARIATION SELECTOR-171;Mn;0;NSM;;;;;N;;;;;
-E019B;VARIATION SELECTOR-172;Mn;0;NSM;;;;;N;;;;;
-E019C;VARIATION SELECTOR-173;Mn;0;NSM;;;;;N;;;;;
-E019D;VARIATION SELECTOR-174;Mn;0;NSM;;;;;N;;;;;
-E019E;VARIATION SELECTOR-175;Mn;0;NSM;;;;;N;;;;;
-E019F;VARIATION SELECTOR-176;Mn;0;NSM;;;;;N;;;;;
-E01A0;VARIATION SELECTOR-177;Mn;0;NSM;;;;;N;;;;;
-E01A1;VARIATION SELECTOR-178;Mn;0;NSM;;;;;N;;;;;
-E01A2;VARIATION SELECTOR-179;Mn;0;NSM;;;;;N;;;;;
-E01A3;VARIATION SELECTOR-180;Mn;0;NSM;;;;;N;;;;;
-E01A4;VARIATION SELECTOR-181;Mn;0;NSM;;;;;N;;;;;
-E01A5;VARIATION SELECTOR-182;Mn;0;NSM;;;;;N;;;;;
-E01A6;VARIATION SELECTOR-183;Mn;0;NSM;;;;;N;;;;;
-E01A7;VARIATION SELECTOR-184;Mn;0;NSM;;;;;N;;;;;
-E01A8;VARIATION SELECTOR-185;Mn;0;NSM;;;;;N;;;;;
-E01A9;VARIATION SELECTOR-186;Mn;0;NSM;;;;;N;;;;;
-E01AA;VARIATION SELECTOR-187;Mn;0;NSM;;;;;N;;;;;
-E01AB;VARIATION SELECTOR-188;Mn;0;NSM;;;;;N;;;;;
-E01AC;VARIATION SELECTOR-189;Mn;0;NSM;;;;;N;;;;;
-E01AD;VARIATION SELECTOR-190;Mn;0;NSM;;;;;N;;;;;
-E01AE;VARIATION SELECTOR-191;Mn;0;NSM;;;;;N;;;;;
-E01AF;VARIATION SELECTOR-192;Mn;0;NSM;;;;;N;;;;;
-E01B0;VARIATION SELECTOR-193;Mn;0;NSM;;;;;N;;;;;
-E01B1;VARIATION SELECTOR-194;Mn;0;NSM;;;;;N;;;;;
-E01B2;VARIATION SELECTOR-195;Mn;0;NSM;;;;;N;;;;;
-E01B3;VARIATION SELECTOR-196;Mn;0;NSM;;;;;N;;;;;
-E01B4;VARIATION SELECTOR-197;Mn;0;NSM;;;;;N;;;;;
-E01B5;VARIATION SELECTOR-198;Mn;0;NSM;;;;;N;;;;;
-E01B6;VARIATION SELECTOR-199;Mn;0;NSM;;;;;N;;;;;
-E01B7;VARIATION SELECTOR-200;Mn;0;NSM;;;;;N;;;;;
-E01B8;VARIATION SELECTOR-201;Mn;0;NSM;;;;;N;;;;;
-E01B9;VARIATION SELECTOR-202;Mn;0;NSM;;;;;N;;;;;
-E01BA;VARIATION SELECTOR-203;Mn;0;NSM;;;;;N;;;;;
-E01BB;VARIATION SELECTOR-204;Mn;0;NSM;;;;;N;;;;;
-E01BC;VARIATION SELECTOR-205;Mn;0;NSM;;;;;N;;;;;
-E01BD;VARIATION SELECTOR-206;Mn;0;NSM;;;;;N;;;;;
-E01BE;VARIATION SELECTOR-207;Mn;0;NSM;;;;;N;;;;;
-E01BF;VARIATION SELECTOR-208;Mn;0;NSM;;;;;N;;;;;
-E01C0;VARIATION SELECTOR-209;Mn;0;NSM;;;;;N;;;;;
-E01C1;VARIATION SELECTOR-210;Mn;0;NSM;;;;;N;;;;;
-E01C2;VARIATION SELECTOR-211;Mn;0;NSM;;;;;N;;;;;
-E01C3;VARIATION SELECTOR-212;Mn;0;NSM;;;;;N;;;;;
-E01C4;VARIATION SELECTOR-213;Mn;0;NSM;;;;;N;;;;;
-E01C5;VARIATION SELECTOR-214;Mn;0;NSM;;;;;N;;;;;
-E01C6;VARIATION SELECTOR-215;Mn;0;NSM;;;;;N;;;;;
-E01C7;VARIATION SELECTOR-216;Mn;0;NSM;;;;;N;;;;;
-E01C8;VARIATION SELECTOR-217;Mn;0;NSM;;;;;N;;;;;
-E01C9;VARIATION SELECTOR-218;Mn;0;NSM;;;;;N;;;;;
-E01CA;VARIATION SELECTOR-219;Mn;0;NSM;;;;;N;;;;;
-E01CB;VARIATION SELECTOR-220;Mn;0;NSM;;;;;N;;;;;
-E01CC;VARIATION SELECTOR-221;Mn;0;NSM;;;;;N;;;;;
-E01CD;VARIATION SELECTOR-222;Mn;0;NSM;;;;;N;;;;;
-E01CE;VARIATION SELECTOR-223;Mn;0;NSM;;;;;N;;;;;
-E01CF;VARIATION SELECTOR-224;Mn;0;NSM;;;;;N;;;;;
-E01D0;VARIATION SELECTOR-225;Mn;0;NSM;;;;;N;;;;;
-E01D1;VARIATION SELECTOR-226;Mn;0;NSM;;;;;N;;;;;
-E01D2;VARIATION SELECTOR-227;Mn;0;NSM;;;;;N;;;;;
-E01D3;VARIATION SELECTOR-228;Mn;0;NSM;;;;;N;;;;;
-E01D4;VARIATION SELECTOR-229;Mn;0;NSM;;;;;N;;;;;
-E01D5;VARIATION SELECTOR-230;Mn;0;NSM;;;;;N;;;;;
-E01D6;VARIATION SELECTOR-231;Mn;0;NSM;;;;;N;;;;;
-E01D7;VARIATION SELECTOR-232;Mn;0;NSM;;;;;N;;;;;
-E01D8;VARIATION SELECTOR-233;Mn;0;NSM;;;;;N;;;;;
-E01D9;VARIATION SELECTOR-234;Mn;0;NSM;;;;;N;;;;;
-E01DA;VARIATION SELECTOR-235;Mn;0;NSM;;;;;N;;;;;
-E01DB;VARIATION SELECTOR-236;Mn;0;NSM;;;;;N;;;;;
-E01DC;VARIATION SELECTOR-237;Mn;0;NSM;;;;;N;;;;;
-E01DD;VARIATION SELECTOR-238;Mn;0;NSM;;;;;N;;;;;
-E01DE;VARIATION SELECTOR-239;Mn;0;NSM;;;;;N;;;;;
-E01DF;VARIATION SELECTOR-240;Mn;0;NSM;;;;;N;;;;;
-E01E0;VARIATION SELECTOR-241;Mn;0;NSM;;;;;N;;;;;
-E01E1;VARIATION SELECTOR-242;Mn;0;NSM;;;;;N;;;;;
-E01E2;VARIATION SELECTOR-243;Mn;0;NSM;;;;;N;;;;;
-E01E3;VARIATION SELECTOR-244;Mn;0;NSM;;;;;N;;;;;
-E01E4;VARIATION SELECTOR-245;Mn;0;NSM;;;;;N;;;;;
-E01E5;VARIATION SELECTOR-246;Mn;0;NSM;;;;;N;;;;;
-E01E6;VARIATION SELECTOR-247;Mn;0;NSM;;;;;N;;;;;
-E01E7;VARIATION SELECTOR-248;Mn;0;NSM;;;;;N;;;;;
-E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;;
-E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;;
-E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;;
-E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;;
-E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;;
-E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;;
-E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;;
-E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;;
-F0000;<Plane 15 Private Use, First>;Co;0;L;;;;;N;;;;;
-FFFFD;<Plane 15 Private Use, Last>;Co;0;L;;;;;N;;;;;
-100000;<Plane 16 Private Use, First>;Co;0;L;;;;;N;;;;;
-10FFFD;<Plane 16 Private Use, Last>;Co;0;L;;;;;N;;;;;
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/mkunicode.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/mkunicode.tcl
deleted file mode 100644
index de89099122c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/mkunicode.tcl
+++ /dev/null
@@ -1,694 +0,0 @@
-
-source [file join [file dirname [info script]] parseunicode.tcl]
-
-proc print_rd {map} {
- global tl_lookup_table
- set aChar [list]
- set lRange [list]
-
- set nRange 1
- set iFirst [lindex $map 0 0]
- set cPrev [lindex $map 0 1]
-
- foreach m [lrange $map 1 end] {
- foreach {i c} $m {}
-
- if {$cPrev == $c} {
- for {set j [expr $iFirst+$nRange]} {$j<$i} {incr j} {
- if {[info exists tl_lookup_table($j)]==0} break
- }
-
- if {$j==$i} {
- set nNew [expr {(1 + $i - $iFirst)}]
- if {$nNew<=8} {
- set nRange $nNew
- continue
- }
- }
- }
-
- lappend lRange [list $iFirst $nRange]
- lappend aChar $cPrev
-
- set iFirst $i
- set cPrev $c
- set nRange 1
- }
- lappend lRange [list $iFirst $nRange]
- lappend aChar $cPrev
-
- puts "/*"
- puts "** If the argument is a codepoint corresponding to a lowercase letter"
- puts "** in the ASCII range with a diacritic added, return the codepoint"
- puts "** of the ASCII letter only. For example, if passed 235 - \"LATIN"
- puts "** SMALL LETTER E WITH DIAERESIS\" - return 65 (\"LATIN SMALL LETTER"
- puts "** E\"). The resuls of passing a codepoint that corresponds to an"
- puts "** uppercase letter are undefined."
- puts "*/"
- puts "static int ${::remove_diacritic}(int c)\{"
- puts " unsigned short aDia\[\] = \{"
- puts -nonewline " 0, "
- set i 1
- foreach r $lRange {
- foreach {iCode nRange} $r {}
- if {($i % 8)==0} {puts "" ; puts -nonewline " " }
- incr i
-
- puts -nonewline [format "%5d" [expr ($iCode<<3) + $nRange-1]]
- puts -nonewline ", "
- }
- puts ""
- puts " \};"
- puts " char aChar\[\] = \{"
- puts -nonewline " '\\0', "
- set i 1
- foreach c $aChar {
- set str "'$c', "
- if {$c == ""} { set str "'\\0', " }
-
- if {($i % 12)==0} {puts "" ; puts -nonewline " " }
- incr i
- puts -nonewline "$str"
- }
- puts ""
- puts " \};"
- puts {
- unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
- int iRes = 0;
- int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
- int iLo = 0;
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( key >= aDia[iTest] ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- assert( key>=aDia[iRes] );
- return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);}
- puts "\}"
-}
-
-proc print_isdiacritic {zFunc map} {
-
- set lCode [list]
- foreach m $map {
- foreach {code char} $m {}
- if {$code && $char == ""} { lappend lCode $code }
- }
- set lCode [lsort -integer $lCode]
- set iFirst [lindex $lCode 0]
- set iLast [lindex $lCode end]
-
- set i1 0
- set i2 0
-
- foreach c $lCode {
- set i [expr $c - $iFirst]
- if {$i < 32} {
- set i1 [expr {$i1 | (1<<$i)}]
- } else {
- set i2 [expr {$i2 | (1<<($i-32))}]
- }
- }
-
- puts "/*"
- puts "** Return true if the argument interpreted as a unicode codepoint"
- puts "** is a diacritical modifier character."
- puts "*/"
- puts "int ${zFunc}\(int c)\{"
- puts " unsigned int mask0 = [format "0x%08X" $i1];"
- puts " unsigned int mask1 = [format "0x%08X" $i2];"
-
- puts " if( c<$iFirst || c>$iLast ) return 0;"
- puts " return (c < $iFirst+32) ?"
- puts " (mask0 & (1 << (c-$iFirst))) :"
- puts " (mask1 & (1 << (c-$iFirst-32)));"
- puts "\}"
-}
-
-
-#-------------------------------------------------------------------------
-
-proc an_load_separator_ranges {} {
- global unicodedata.txt
- set lSep [an_load_unicodedata_text ${unicodedata.txt}]
- unset -nocomplain iFirst
- unset -nocomplain nRange
- set lRange [list]
- foreach sep $lSep {
- if {0==[info exists iFirst]} {
- set iFirst $sep
- set nRange 1
- } elseif { $sep == ($iFirst+$nRange) } {
- incr nRange
- } else {
- lappend lRange [list $iFirst $nRange]
- set iFirst $sep
- set nRange 1
- }
- }
- lappend lRange [list $iFirst $nRange]
- set lRange
-}
-
-proc an_print_range_array {lRange} {
- set iFirstMax 0
- set nRangeMax 0
- foreach range $lRange {
- foreach {iFirst nRange} $range {}
- if {$iFirst > $iFirstMax} {set iFirstMax $iFirst}
- if {$nRange > $nRangeMax} {set nRangeMax $nRange}
- }
- if {$iFirstMax >= (1<<22)} {error "first-max is too large for format"}
- if {$nRangeMax >= (1<<10)} {error "range-max is too large for format"}
-
- puts -nonewline " "
- puts [string trim {
- /* Each unsigned integer in the following array corresponds to a contiguous
- ** range of unicode codepoints that are not either letters or numbers (i.e.
- ** codepoints for which this function should return 0).
- **
- ** The most significant 22 bits in each 32-bit value contain the first
- ** codepoint in the range. The least significant 10 bits are used to store
- ** the size of the range (always at least 1). In other words, the value
- ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
- ** C. It is not possible to represent a range larger than 1023 codepoints
- ** using this format.
- */
- }]
- puts -nonewline " static const unsigned int aEntry\[\] = \{"
- set i 0
- foreach range $lRange {
- foreach {iFirst nRange} $range {}
- set u32 [format "0x%08X" [expr ($iFirst<<10) + $nRange]]
-
- if {($i % 5)==0} {puts "" ; puts -nonewline " "}
- puts -nonewline " $u32,"
- incr i
- }
- puts ""
- puts " \};"
-}
-
-proc an_print_ascii_bitmap {lRange} {
- foreach range $lRange {
- foreach {iFirst nRange} $range {}
- for {set i $iFirst} {$i < ($iFirst+$nRange)} {incr i} {
- if {$i<=127} { set a($i) 1 }
- }
- }
-
- set aAscii [list 0 0 0 0]
- foreach key [array names a] {
- set idx [expr $key >> 5]
- lset aAscii $idx [expr [lindex $aAscii $idx] | (1 << ($key&0x001F))]
- }
-
- puts " static const unsigned int aAscii\[4\] = \{"
- puts -nonewline " "
- foreach v $aAscii { puts -nonewline [format " 0x%08X," $v] }
- puts ""
- puts " \};"
-}
-
-proc print_isalnum {zFunc lRange} {
- puts "/*"
- puts "** Return true if the argument corresponds to a unicode codepoint"
- puts "** classified as either a letter or a number. Otherwise false."
- puts "**"
- puts "** The results are undefined if the value passed to this function"
- puts "** is less than zero."
- puts "*/"
- puts "int ${zFunc}\(int c)\{"
- an_print_range_array $lRange
- an_print_ascii_bitmap $lRange
- puts {
- if( (unsigned int)c<128 ){
- return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
- }else if( (unsigned int)c<(1<<22) ){
- unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
- int iRes = 0;
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
- int iLo = 0;
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( key >= aEntry[iTest] ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- assert( aEntry[0]<key );
- assert( key>=aEntry[iRes] );
- return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
- }
- return 1;}
- puts "\}"
-}
-
-proc print_test_isalnum {zFunc lRange} {
- foreach range $lRange {
- foreach {iFirst nRange} $range {}
- for {set i $iFirst} {$i < ($iFirst+$nRange)} {incr i} { set a($i) 1 }
- }
-
- puts "static int isalnum_test(int *piCode)\{"
- puts -nonewline " unsigned char aAlnum\[\] = \{"
- for {set i 0} {$i < 70000} {incr i} {
- if {($i % 32)==0} { puts "" ; puts -nonewline " " }
- set bFlag [expr ![info exists a($i)]]
- puts -nonewline "${bFlag},"
- }
- puts ""
- puts " \};"
-
- puts -nonewline " int aLargeSep\[\] = \{"
- set i 0
- foreach iSep [lsort -integer [array names a]] {
- if {$iSep<70000} continue
- if {($i % 8)==0} { puts "" ; puts -nonewline " " }
- puts -nonewline " $iSep,"
- incr i
- }
- puts ""
- puts " \};"
- puts -nonewline " int aLargeOther\[\] = \{"
- set i 0
- foreach iSep [lsort -integer [array names a]] {
- if {$iSep<70000} continue
- if {[info exists a([expr $iSep-1])]==0} {
- if {($i % 8)==0} { puts "" ; puts -nonewline " " }
- puts -nonewline " [expr $iSep-1],"
- incr i
- }
- if {[info exists a([expr $iSep+1])]==0} {
- if {($i % 8)==0} { puts "" ; puts -nonewline " " }
- puts -nonewline " [expr $iSep+1],"
- incr i
- }
- }
- puts ""
- puts " \};"
-
- puts [subst -nocommands {
- int i;
- for(i=0; i<sizeof(aAlnum)/sizeof(aAlnum[0]); i++){
- if( ${zFunc}(i)!=aAlnum[i] ){
- *piCode = i;
- return 1;
- }
- }
- for(i=0; i<sizeof(aLargeSep)/sizeof(aLargeSep[0]); i++){
- if( ${zFunc}(aLargeSep[i])!=0 ){
- *piCode = aLargeSep[i];
- return 1;
- }
- }
- for(i=0; i<sizeof(aLargeOther)/sizeof(aLargeOther[0]); i++){
- if( ${zFunc}(aLargeOther[i])!=1 ){
- *piCode = aLargeOther[i];
- return 1;
- }
- }
- }]
- puts " return 0;"
- puts "\}"
-}
-
-#-------------------------------------------------------------------------
-
-proc tl_create_records {} {
- global tl_lookup_table
-
- set iFirst ""
- set nOff 0
- set nRange 0
- set nIncr 0
-
- set lRecord [list]
- foreach code [lsort -integer [array names tl_lookup_table]] {
- set mapping $tl_lookup_table($code)
- if {$iFirst == ""} {
- set iFirst $code
- set nOff [expr $mapping - $code]
- set nRange 1
- set nIncr 1
- } else {
- set diff [expr $code - ($iFirst + ($nIncr * ($nRange - 1)))]
- if { $nRange==1 && ($diff==1 || $diff==2) } {
- set nIncr $diff
- }
-
- if {$diff != $nIncr || ($mapping - $code)!=$nOff} {
- if { $nRange==1 } {set nIncr 1}
- lappend lRecord [list $iFirst $nIncr $nRange $nOff]
- set iFirst $code
- set nOff [expr $mapping - $code]
- set nRange 1
- set nIncr 1
- } else {
- incr nRange
- }
- }
- }
-
- lappend lRecord [list $iFirst $nIncr $nRange $nOff]
-
- set lRecord
-}
-
-proc tl_print_table_header {} {
- puts -nonewline " "
- puts [string trim {
- /* Each entry in the following array defines a rule for folding a range
- ** of codepoints to lower case. The rule applies to a range of nRange
- ** codepoints starting at codepoint iCode.
- **
- ** If the least significant bit in flags is clear, then the rule applies
- ** to all nRange codepoints (i.e. all nRange codepoints are upper case and
- ** need to be folded). Or, if it is set, then the rule only applies to
- ** every second codepoint in the range, starting with codepoint C.
- **
- ** The 7 most significant bits in flags are an index into the aiOff[]
- ** array. If a specific codepoint C does require folding, then its lower
- ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF).
- **
- ** The contents of this array are generated by parsing the CaseFolding.txt
- ** file distributed as part of the "Unicode Character Database". See
- ** http://www.unicode.org for details.
- */
- }]
- puts " static const struct TableEntry \{"
- puts " unsigned short iCode;"
- puts " unsigned char flags;"
- puts " unsigned char nRange;"
- puts " \} aEntry\[\] = \{"
-}
-
-proc tl_print_table_entry {togglevar entry liOff} {
- upvar $togglevar t
- foreach {iFirst nIncr nRange nOff} $entry {}
-
- if {$iFirst > (1<<16)} { return 1 }
-
- if {[info exists t]==0} {set t 0}
- if {$t==0} { puts -nonewline " " }
-
- set flags 0
- if {$nIncr==2} { set flags 1 ; set nRange [expr $nRange * 2]}
- if {$nOff<0} { incr nOff [expr (1<<16)] }
-
- set idx [lsearch $liOff $nOff]
- if {$idx<0} {error "malfunction generating aiOff"}
- set flags [expr $flags + $idx*2]
-
- set txt "{$iFirst, $flags, $nRange},"
- if {$t==2} {
- puts $txt
- } else {
- puts -nonewline [format "% -23s" $txt]
- }
- set t [expr ($t+1)%3]
-
- return 0
-}
-
-proc tl_print_table_footer {togglevar} {
- upvar $togglevar t
- if {$t!=0} {puts ""}
- puts " \};"
-}
-
-proc tl_print_if_entry {entry} {
- foreach {iFirst nIncr nRange nOff} $entry {}
- if {$nIncr==2} {error "tl_print_if_entry needs improvement!"}
-
- puts " else if( c>=$iFirst && c<[expr $iFirst+$nRange] )\{"
- puts " ret = c + $nOff;"
- puts " \}"
-}
-
-proc tl_generate_ioff_table {lRecord} {
- foreach entry $lRecord {
- foreach {iFirst nIncr nRange iOff} $entry {}
- if {$iOff<0} { incr iOff [expr (1<<16)] }
- if {[info exists a($iOff)]} continue
- set a($iOff) 1
- }
-
- set liOff [lsort -integer [array names a]]
- if {[llength $liOff]>128} { error "Too many distinct ioffs" }
- return $liOff
-}
-
-proc tl_print_ioff_table {liOff} {
- puts -nonewline " static const unsigned short aiOff\[\] = \{"
- set i 0
- foreach off $liOff {
- if {($i % 8)==0} {puts "" ; puts -nonewline " "}
- puts -nonewline [format "% -7s" "$off,"]
- incr i
- }
- puts ""
- puts " \};"
-
-}
-
-proc print_fold {zFunc} {
-
- set lRecord [tl_create_records]
-
- set lHigh [list]
- puts "/*"
- puts "** Interpret the argument as a unicode codepoint. If the codepoint"
- puts "** is an upper case character that has a lower case equivalent,"
- puts "** return the codepoint corresponding to the lower case version."
- puts "** Otherwise, return a copy of the argument."
- puts "**"
- puts "** The results are undefined if the value passed to this function"
- puts "** is less than zero."
- puts "*/"
- puts "int ${zFunc}\(int c, int bRemoveDiacritic)\{"
-
- set liOff [tl_generate_ioff_table $lRecord]
- tl_print_table_header
- foreach entry $lRecord {
- if {[tl_print_table_entry toggle $entry $liOff]} {
- lappend lHigh $entry
- }
- }
- tl_print_table_footer toggle
- tl_print_ioff_table $liOff
-
- puts [subst -nocommands {
- int ret = c;
-
- assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
-
- if( c<128 ){
- if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
- }else if( c<65536 ){
- const struct TableEntry *p;
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
- int iLo = 0;
- int iRes = -1;
-
- assert( c>aEntry[0].iCode );
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- int cmp = (c - aEntry[iTest].iCode);
- if( cmp>=0 ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
-
- assert( iRes>=0 && c>=aEntry[iRes].iCode );
- p = &aEntry[iRes];
- if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
- ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
- assert( ret>0 );
- }
-
- if( bRemoveDiacritic ) ret = ${::remove_diacritic}(ret);
- }
- }]
-
- foreach entry $lHigh {
- tl_print_if_entry $entry
- }
-
- puts ""
- puts " return ret;"
- puts "\}"
-}
-
-proc print_fold_test {zFunc mappings} {
- global tl_lookup_table
-
- foreach m $mappings {
- set c [lindex $m 1]
- if {$c == ""} {
- set extra([lindex $m 0]) 0
- } else {
- scan $c %c i
- set extra([lindex $m 0]) $i
- }
- }
-
- puts "static int fold_test(int *piCode)\{"
- puts -nonewline " static int aLookup\[\] = \{"
- for {set i 0} {$i < 70000} {incr i} {
-
- set expected $i
- catch { set expected $tl_lookup_table($i) }
- set expected2 $expected
- catch { set expected2 $extra($expected2) }
-
- if {($i % 4)==0} { puts "" ; puts -nonewline " " }
- puts -nonewline "$expected, $expected2, "
- }
- puts " \};"
- puts " int i;"
- puts " for(i=0; i<sizeof(aLookup)/sizeof(aLookup\[0\]); i++)\{"
- puts " int iCode = (i/2);"
- puts " int bFlag = i & 0x0001;"
- puts " if( ${zFunc}\(iCode, bFlag)!=aLookup\[i\] )\{"
- puts " *piCode = iCode;"
- puts " return 1;"
- puts " \}"
- puts " \}"
- puts " return 0;"
- puts "\}"
-}
-
-
-proc print_fileheader {} {
- puts [string trim {
-/*
-** 2012 May 25
-**
-** 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.
-**
-******************************************************************************
-*/
-
-/*
-** DO NOT EDIT THIS MACHINE GENERATED FILE.
-*/
- }]
- puts ""
- if {$::generate_fts5_code} {
- # no-op
- } else {
- puts "#ifndef SQLITE_DISABLE_FTS3_UNICODE"
- puts "#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)"
- }
- puts ""
- puts "#include <assert.h>"
- puts ""
-}
-
-proc print_test_main {} {
- puts ""
- puts "#include <stdio.h>"
- puts ""
- puts "int main(int argc, char **argv)\{"
- puts " int r1, r2;"
- puts " int code;"
- puts " r1 = isalnum_test(&code);"
- puts " if( r1 ) printf(\"isalnum(): Problem with code %d\\n\",code);"
- puts " else printf(\"isalnum(): test passed\\n\");"
- puts " r2 = fold_test(&code);"
- puts " if( r2 ) printf(\"fold(): Problem with code %d\\n\",code);"
- puts " else printf(\"fold(): test passed\\n\");"
- puts " return (r1 || r2);"
- puts "\}"
-}
-
-# Proces the command line arguments. Exit early if they are not to
-# our liking.
-#
-proc usage {} {
- puts -nonewline stderr "Usage: $::argv0 ?-test? ?-fts5? "
- puts stderr "<CaseFolding.txt file> <UnicodeData.txt file>"
- exit 1
-}
-if {[llength $argv]<2} usage
-set unicodedata.txt [lindex $argv end]
-set casefolding.txt [lindex $argv end-1]
-
-set remove_diacritic remove_diacritic
-set generate_test_code 0
-set generate_fts5_code 0
-set function_prefix "sqlite3Fts"
-for {set i 0} {$i < [llength $argv]-2} {incr i} {
- switch -- [lindex $argv $i] {
- -test {
- set generate_test_code 1
- }
- -fts5 {
- set function_prefix sqlite3Fts5
- set generate_fts5_code 1
- set remove_diacritic fts5_remove_diacritic
- }
- default {
- usage
- }
- }
-}
-
-print_fileheader
-
-# Print the isalnum() function to stdout.
-#
-set lRange [an_load_separator_ranges]
-print_isalnum ${function_prefix}UnicodeIsalnum $lRange
-
-# Leave a gap between the two generated C functions.
-#
-puts ""
-puts ""
-
-# Load the fold data. This is used by the [rd_XXX] commands
-# as well as [print_fold].
-tl_load_casefolding_txt ${casefolding.txt}
-
-set mappings [rd_load_unicodedata_text ${unicodedata.txt}]
-print_rd $mappings
-puts ""
-puts ""
-print_isdiacritic ${function_prefix}UnicodeIsdiacritic $mappings
-puts ""
-puts ""
-
-# Print the fold() function to stdout.
-#
-print_fold ${function_prefix}UnicodeFold
-
-# Print the test routines and main() function to stdout, if -test
-# was specified.
-#
-if {$::generate_test_code} {
- print_test_isalnum ${function_prefix}UnicodeIsalnum $lRange
- print_fold_test ${function_prefix}UnicodeFold $mappings
- print_test_main
-}
-
-if {$generate_fts5_code} {
- # no-op
-} else {
- puts "#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */"
- puts "#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */"
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/parseunicode.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/parseunicode.tcl
deleted file mode 100644
index 0cb2c83a18f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts3/unicode/parseunicode.tcl
+++ /dev/null
@@ -1,146 +0,0 @@
-
-#--------------------------------------------------------------------------
-# Parameter $zName must be a path to the file UnicodeData.txt. This command
-# reads the file and returns a list of mappings required to remove all
-# diacritical marks from a unicode string. Each mapping is itself a list
-# consisting of two elements - the unicode codepoint and the single ASCII
-# character that it should be replaced with, or an empty string if the
-# codepoint should simply be removed from the input. Examples:
-#
-# { 224 a } (replace codepoint 224 to "a")
-# { 769 "" } (remove codepoint 769 from input)
-#
-# Mappings are only returned for non-upper case codepoints. It is assumed
-# that the input has already been folded to lower case.
-#
-proc rd_load_unicodedata_text {zName} {
- global tl_lookup_table
-
- set fd [open $zName]
- set lField {
- code
- character_name
- general_category
- canonical_combining_classes
- bidirectional_category
- character_decomposition_mapping
- decimal_digit_value
- digit_value
- numeric_value
- mirrored
- unicode_1_name
- iso10646_comment_field
- uppercase_mapping
- lowercase_mapping
- titlecase_mapping
- }
- set lRet [list]
-
- while { ![eof $fd] } {
- set line [gets $fd]
- if {$line == ""} continue
-
- set fields [split $line ";"]
- if {[llength $fields] != [llength $lField]} { error "parse error: $line" }
- foreach $lField $fields {}
- if { [llength $character_decomposition_mapping]!=2
- || [string is xdigit [lindex $character_decomposition_mapping 0]]==0
- } {
- continue
- }
-
- set iCode [expr "0x$code"]
- set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"]
- set iDia [expr "0x[lindex $character_decomposition_mapping 1]"]
-
- if {[info exists tl_lookup_table($iCode)]} continue
-
- if { ($iAscii >= 97 && $iAscii <= 122)
- || ($iAscii >= 65 && $iAscii <= 90)
- } {
- lappend lRet [list $iCode [string tolower [format %c $iAscii]]]
- set dia($iDia) 1
- }
- }
-
- foreach d [array names dia] {
- lappend lRet [list $d ""]
- }
- set lRet [lsort -integer -index 0 $lRet]
-
- close $fd
- set lRet
-}
-
-#-------------------------------------------------------------------------
-# Parameter $zName must be a path to the file UnicodeData.txt. This command
-# reads the file and returns a list of codepoints (integers). The list
-# contains all codepoints in the UnicodeData.txt assigned to any "General
-# Category" that is not a "Letter" or "Number".
-#
-proc an_load_unicodedata_text {zName} {
- set fd [open $zName]
- set lField {
- code
- character_name
- general_category
- canonical_combining_classes
- bidirectional_category
- character_decomposition_mapping
- decimal_digit_value
- digit_value
- numeric_value
- mirrored
- unicode_1_name
- iso10646_comment_field
- uppercase_mapping
- lowercase_mapping
- titlecase_mapping
- }
- set lRet [list]
-
- while { ![eof $fd] } {
- set line [gets $fd]
- if {$line == ""} continue
-
- set fields [split $line ";"]
- if {[llength $fields] != [llength $lField]} { error "parse error: $line" }
- foreach $lField $fields {}
-
- set iCode [expr "0x$code"]
- set bAlnum [expr {
- [lsearch {L N} [string range $general_category 0 0]] >= 0
- || $general_category=="Co"
- }]
-
- if { !$bAlnum } { lappend lRet $iCode }
- }
-
- close $fd
- set lRet
-}
-
-proc tl_load_casefolding_txt {zName} {
- global tl_lookup_table
-
- set fd [open $zName]
- while { ![eof $fd] } {
- set line [gets $fd]
- if {[string range $line 0 0] == "#"} continue
- if {$line == ""} continue
-
- foreach x {a b c d} {unset -nocomplain $x}
- foreach {a b c d} [split $line ";"] {}
-
- set a2 [list]
- set c2 [list]
- foreach elem $a { lappend a2 [expr "0x[string trim $elem]"] }
- foreach elem $c { lappend c2 [expr "0x[string trim $elem]"] }
- set b [string trim $b]
- set d [string trim $d]
-
- if {$b=="C" || $b=="S"} { set tl_lookup_table($a2) $c2 }
- }
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/extract_api_docs.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/extract_api_docs.tcl
deleted file mode 100644
index 2320d70b7d5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/extract_api_docs.tcl
+++ /dev/null
@@ -1,252 +0,0 @@
-#
-# 2014 August 24
-#
-# 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 script extracts the documentation for the API used by fts5 auxiliary
-# functions from header file fts5.h. It outputs html text on stdout that
-# is included in the documentation on the web.
-#
-
-set ::fts5_docs_output ""
-if {[info commands hd_putsnl]==""} {
- if {[llength $argv]>0} { set ::extract_api_docs_mode [lindex $argv 0] }
- proc output {text} {
- puts $text
- }
-} else {
- proc output {text} {
- append ::fts5_docs_output "$text\n"
- }
-}
-if {[info exists ::extract_api_docs_mode]==0} {set ::extract_api_docs_mode api}
-
-
-set input_file [file join [file dir [info script]] fts5.h]
-set fd [open $input_file]
-set data [read $fd]
-close $fd
-
-
-# Argument $data is the entire text of the fts5.h file. This function
-# extracts the definition of the Fts5ExtensionApi structure from it and
-# returns a key/value list of structure member names and definitions. i.e.
-#
-# iVersion {int iVersion} xUserData {void *(*xUserData)(Fts5Context*)} ...
-#
-proc get_struct_members {data} {
-
- # Extract the structure definition from the fts5.h file.
- regexp "struct Fts5ExtensionApi {(.*?)};" $data -> defn
-
- # Remove all comments from the structure definition
- regsub -all {/[*].*?[*]/} $defn {} defn2
-
- set res [list]
- foreach member [split $defn2 {;}] {
-
- set member [string trim $member]
- if {$member!=""} {
- catch { set name [lindex $member end] }
- regexp {.*?[(][*]([^)]*)[)]} $member -> name
- lappend res $name $member
- }
- }
-
- set res
-}
-
-proc get_struct_docs {data names} {
- # Extract the structure definition from the fts5.h file.
- regexp {EXTENSION API FUNCTIONS(.*?)[*]/} $data -> docs
-
- set current_doc ""
- set current_header ""
-
- foreach line [split $docs "\n"] {
- regsub {[*]*} $line {} line
- if {[regexp {^ } $line]} {
- append current_doc "$line\n"
- } elseif {[string trim $line]==""} {
- if {$current_header!=""} { append current_doc "\n" }
- } else {
- if {$current_doc != ""} {
- lappend res $current_header $current_doc
- set current_doc ""
- }
- set subject n/a
- regexp {^ *([[:alpha:]]*)} $line -> subject
- if {[lsearch $names $subject]>=0} {
- set current_header $subject
- } else {
- set current_header [string trim $line]
- }
- }
- }
-
- if {$current_doc != ""} {
- lappend res $current_header $current_doc
- }
-
- set res
-}
-
-proc get_tokenizer_docs {data} {
- regexp {(xCreate:.*?)[*]/} $data -> docs
-
- set res "<dl>\n"
- foreach line [split [string trim $docs] "\n"] {
- regexp {[*][*](.*)} $line -> line
- if {[regexp {^ ?x.*:} $line]} {
- append res "<dt><b>$line</b></dt><dd><p style=margin-top:0>\n"
- continue
- }
- if {[regexp {SYNONYM SUPPORT} $line]} {
- set line "</dl><h3>Synonym Support</h3>"
- }
- if {[string trim $line] == ""} {
- append res "<p>\n"
- } else {
- append res "$line\n"
- }
- }
-
- set res
-}
-
-proc get_api_docs {data} {
- # Initialize global array M as a map from Fts5StructureApi member name
- # to member definition. i.e.
- #
- # iVersion -> {int iVersion}
- # xUserData -> {void *(*xUserData)(Fts5Context*)}
- # ...
- #
- array set M [get_struct_members $data]
-
- # Initialize global list D as a map from section name to documentation
- # text. Most (all?) section names are structure member names.
- #
- set D [get_struct_docs $data [array names M]]
-
- output "<dl>"
- foreach {sub docs} $D {
- if {[info exists M($sub)]} {
- set hdr $M($sub)
- set link " id=$sub"
- } else {
- set link ""
- }
-
- #output "<hr color=#eeeee style=\"margin:1em 8.4ex 0 8.4ex;\"$link>"
- #set style "padding-left:6ex;font-size:1.4em;display:block"
- #output "<h style=\"$style\"><pre>$hdr</pre></h>"
-
- regsub -line {^ *[)]} $hdr ")" hdr
- output "<dt style=\"white-space:pre;font-family:monospace;font-size:120%\""
- output "$link>"
- output "<b>$hdr</b></dt><dd>"
-
- set mode ""
- set margin " style=margin-top:0.1em"
- foreach line [split [string trim $docs] "\n"] {
- if {[string trim $line]==""} {
- if {$mode != ""} {output "</$mode>"}
- set mode ""
- } elseif {$mode == ""} {
- if {[regexp {^ } $line]} {
- set mode codeblock
- } else {
- set mode p
- }
- output "<$mode$margin>"
- set margin ""
- }
- output $line
- }
- if {$mode != ""} {output "</$mode>"}
- output "</dd>"
- }
- output "</dl>"
-}
-
-proc get_fts5_struct {data start end} {
- set res ""
- set bOut 0
- foreach line [split $data "\n"] {
- if {$bOut==0} {
- if {[regexp $start $line]} {
- set bOut 1
- }
- }
-
- if {$bOut} {
- append res "$line\n"
- }
-
- if {$bOut} {
- if {[regexp $end $line]} {
- set bOut 0
- }
- }
- }
-
- set map [list /* <i>/* */ */</i>]
- string map $map $res
-}
-
-proc main {data} {
- switch $::extract_api_docs_mode {
- fts5_api {
- output [get_fts5_struct $data "typedef struct fts5_api" "^\};"]
- }
-
- fts5_tokenizer {
- output [get_fts5_struct $data "typedef struct Fts5Tokenizer" "^\};"]
- output [get_fts5_struct $data \
- "Flags that may be passed as the third argument to xTokenize()" \
- "#define FTS5_TOKEN_COLOCATED"
- ]
- }
-
- fts5_extension {
- output [get_fts5_struct $data "typedef.*Fts5ExtensionApi" "^.;"]
- }
-
- Fts5ExtensionApi {
- set struct [get_fts5_struct $data "^struct Fts5ExtensionApi" "^.;"]
- set map [list]
- foreach {k v} [get_struct_members $data] {
- if {[string match x* $k]==0} continue
- lappend map $k "<a href=#$k>$k</a>"
- }
- output [string map $map $struct]
- }
-
- api {
- get_api_docs $data
- }
-
- tokenizer_api {
- output [get_tokenizer_docs $data]
- }
-
- default {
- }
- }
-}
-main $data
-
-set ::fts5_docs_output
-
-
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5.h
deleted file mode 100644
index a45c145d38b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5.h
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-**
-** Interfaces to extend FTS5. Using the interfaces defined in this file,
-** FTS5 may be extended with:
-**
-** * custom tokenizers, and
-** * custom auxiliary functions.
-*/
-
-
-#ifndef _FTS5_H
-#define _FTS5_H
-
-#include "sqlite3.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*************************************************************************
-** CUSTOM AUXILIARY FUNCTIONS
-**
-** Virtual table implementations may overload SQL functions by implementing
-** the sqlite3_module.xFindFunction() method.
-*/
-
-typedef struct Fts5ExtensionApi Fts5ExtensionApi;
-typedef struct Fts5Context Fts5Context;
-typedef struct Fts5PhraseIter Fts5PhraseIter;
-
-typedef void (*fts5_extension_function)(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- sqlite3_context *pCtx, /* Context for returning result/error */
- int nVal, /* Number of values in apVal[] array */
- sqlite3_value **apVal /* Array of trailing arguments */
-);
-
-struct Fts5PhraseIter {
- const unsigned char *a;
- const unsigned char *b;
-};
-
-/*
-** EXTENSION API FUNCTIONS
-**
-** xUserData(pFts):
-** Return a copy of the context pointer the extension function was
-** registered with.
-**
-** xColumnTotalSize(pFts, iCol, pnToken):
-** If parameter iCol is less than zero, set output variable *pnToken
-** to the total number of tokens in the FTS5 table. Or, if iCol is
-** non-negative but less than the number of columns in the table, return
-** the total number of tokens in column iCol, considering all rows in
-** the FTS5 table.
-**
-** If parameter iCol is greater than or equal to the number of columns
-** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
-** an OOM condition or IO error), an appropriate SQLite error code is
-** returned.
-**
-** xColumnCount(pFts):
-** Return the number of columns in the table.
-**
-** xColumnSize(pFts, iCol, pnToken):
-** If parameter iCol is less than zero, set output variable *pnToken
-** to the total number of tokens in the current row. Or, if iCol is
-** non-negative but less than the number of columns in the table, set
-** *pnToken to the number of tokens in column iCol of the current row.
-**
-** If parameter iCol is greater than or equal to the number of columns
-** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
-** an OOM condition or IO error), an appropriate SQLite error code is
-** returned.
-**
-** This function may be quite inefficient if used with an FTS5 table
-** created with the "columnsize=0" option.
-**
-** xColumnText:
-** This function attempts to retrieve the text of column iCol of the
-** current document. If successful, (*pz) is set to point to a buffer
-** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
-** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
-** if an error occurs, an SQLite error code is returned and the final values
-** of (*pz) and (*pn) are undefined.
-**
-** xPhraseCount:
-** Returns the number of phrases in the current query expression.
-**
-** xPhraseSize:
-** Returns the number of tokens in phrase iPhrase of the query. Phrases
-** are numbered starting from zero.
-**
-** xInstCount:
-** Set *pnInst to the total number of occurrences of all phrases within
-** the query within the current row. Return SQLITE_OK if successful, or
-** an error code (i.e. SQLITE_NOMEM) if an error occurs.
-**
-** This API can be quite slow if used with an FTS5 table created with the
-** "detail=none" or "detail=column" option. If the FTS5 table is created
-** with either "detail=none" or "detail=column" and "content=" option
-** (i.e. if it is a contentless table), then this API always returns 0.
-**
-** xInst:
-** Query for the details of phrase match iIdx within the current row.
-** Phrase matches are numbered starting from zero, so the iIdx argument
-** should be greater than or equal to zero and smaller than the value
-** output by xInstCount().
-**
-** Usually, output parameter *piPhrase is set to the phrase number, *piCol
-** to the column in which it occurs and *piOff the token offset of the
-** first token of the phrase. The exception is if the table was created
-** with the offsets=0 option specified. In this case *piOff is always
-** set to -1.
-**
-** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
-** if an error occurs.
-**
-** This API can be quite slow if used with an FTS5 table created with the
-** "detail=none" or "detail=column" option.
-**
-** xRowid:
-** Returns the rowid of the current row.
-**
-** xTokenize:
-** Tokenize text using the tokenizer belonging to the FTS5 table.
-**
-** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback):
-** This API function is used to query the FTS table for phrase iPhrase
-** of the current query. Specifically, a query equivalent to:
-**
-** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid
-**
-** with $p set to a phrase equivalent to the phrase iPhrase of the
-** current query is executed. Any column filter that applies to
-** phrase iPhrase of the current query is included in $p. For each
-** row visited, the callback function passed as the fourth argument
-** is invoked. The context and API objects passed to the callback
-** function may be used to access the properties of each matched row.
-** Invoking Api.xUserData() returns a copy of the pointer passed as
-** the third argument to pUserData.
-**
-** If the callback function returns any value other than SQLITE_OK, the
-** query is abandoned and the xQueryPhrase function returns immediately.
-** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
-** Otherwise, the error code is propagated upwards.
-**
-** If the query runs to completion without incident, SQLITE_OK is returned.
-** Or, if some error occurs before the query completes or is aborted by
-** the callback, an SQLite error code is returned.
-**
-**
-** xSetAuxdata(pFts5, pAux, xDelete)
-**
-** Save the pointer passed as the second argument as the extension functions
-** "auxiliary data". The pointer may then be retrieved by the current or any
-** future invocation of the same fts5 extension function made as part of
-** of the same MATCH query using the xGetAuxdata() API.
-**
-** Each extension function is allocated a single auxiliary data slot for
-** each FTS query (MATCH expression). If the extension function is invoked
-** more than once for a single FTS query, then all invocations share a
-** single auxiliary data context.
-**
-** If there is already an auxiliary data pointer when this function is
-** invoked, then it is replaced by the new pointer. If an xDelete callback
-** was specified along with the original pointer, it is invoked at this
-** point.
-**
-** The xDelete callback, if one is specified, is also invoked on the
-** auxiliary data pointer after the FTS5 query has finished.
-**
-** If an error (e.g. an OOM condition) occurs within this function, an
-** the auxiliary data is set to NULL and an error code returned. If the
-** xDelete parameter was not NULL, it is invoked on the auxiliary data
-** pointer before returning.
-**
-**
-** xGetAuxdata(pFts5, bClear)
-**
-** Returns the current auxiliary data pointer for the fts5 extension
-** function. See the xSetAuxdata() method for details.
-**
-** If the bClear argument is non-zero, then the auxiliary data is cleared
-** (set to NULL) before this function returns. In this case the xDelete,
-** if any, is not invoked.
-**
-**
-** xRowCount(pFts5, pnRow)
-**
-** This function is used to retrieve the total number of rows in the table.
-** In other words, the same value that would be returned by:
-**
-** SELECT count(*) FROM ftstable;
-**
-** xPhraseFirst()
-** This function is used, along with type Fts5PhraseIter and the xPhraseNext
-** method, to iterate through all instances of a single query phrase within
-** the current row. This is the same information as is accessible via the
-** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient
-** to use, this API may be faster under some circumstances. To iterate
-** through instances of phrase iPhrase, use the following code:
-**
-** Fts5PhraseIter iter;
-** int iCol, iOff;
-** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
-** iCol>=0;
-** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
-** ){
-** // An instance of phrase iPhrase at offset iOff of column iCol
-** }
-**
-** The Fts5PhraseIter structure is defined above. Applications should not
-** modify this structure directly - it should only be used as shown above
-** with the xPhraseFirst() and xPhraseNext() API methods (and by
-** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
-**
-** This API can be quite slow if used with an FTS5 table created with the
-** "detail=none" or "detail=column" option. If the FTS5 table is created
-** with either "detail=none" or "detail=column" and "content=" option
-** (i.e. if it is a contentless table), then this API always iterates
-** through an empty set (all calls to xPhraseFirst() set iCol to -1).
-**
-** xPhraseNext()
-** See xPhraseFirst above.
-**
-** xPhraseFirstColumn()
-** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
-** and xPhraseNext() APIs described above. The difference is that instead
-** of iterating through all instances of a phrase in the current row, these
-** APIs are used to iterate through the set of columns in the current row
-** that contain one or more instances of a specified phrase. For example:
-**
-** Fts5PhraseIter iter;
-** int iCol;
-** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
-** iCol>=0;
-** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
-** ){
-** // Column iCol contains at least one instance of phrase iPhrase
-** }
-**
-** This API can be quite slow if used with an FTS5 table created with the
-** "detail=none" option. If the FTS5 table is created with either
-** "detail=none" "content=" option (i.e. if it is a contentless table),
-** then this API always iterates through an empty set (all calls to
-** xPhraseFirstColumn() set iCol to -1).
-**
-** The information accessed using this API and its companion
-** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
-** (or xInst/xInstCount). The chief advantage of this API is that it is
-** significantly more efficient than those alternatives when used with
-** "detail=column" tables.
-**
-** xPhraseNextColumn()
-** See xPhraseFirstColumn above.
-*/
-struct Fts5ExtensionApi {
- int iVersion; /* Currently always set to 3 */
-
- void *(*xUserData)(Fts5Context*);
-
- int (*xColumnCount)(Fts5Context*);
- int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
- int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
-
- int (*xTokenize)(Fts5Context*,
- const char *pText, int nText, /* Text to tokenize */
- void *pCtx, /* Context passed to xToken() */
- int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
- );
-
- int (*xPhraseCount)(Fts5Context*);
- int (*xPhraseSize)(Fts5Context*, int iPhrase);
-
- int (*xInstCount)(Fts5Context*, int *pnInst);
- int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
-
- sqlite3_int64 (*xRowid)(Fts5Context*);
- int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
- int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken);
-
- int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
- int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
- );
- int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
- void *(*xGetAuxdata)(Fts5Context*, int bClear);
-
- int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
- void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
-
- int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
- void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
-};
-
-/*
-** CUSTOM AUXILIARY FUNCTIONS
-*************************************************************************/
-
-/*************************************************************************
-** CUSTOM TOKENIZERS
-**
-** Applications may also register custom tokenizer types. A tokenizer
-** is registered by providing fts5 with a populated instance of the
-** following structure. All structure methods must be defined, setting
-** any member of the fts5_tokenizer struct to NULL leads to undefined
-** behaviour. The structure methods are expected to function as follows:
-**
-** xCreate:
-** This function is used to allocate and initialize a tokenizer instance.
-** A tokenizer instance is required to actually tokenize text.
-**
-** The first argument passed to this function is a copy of the (void*)
-** pointer provided by the application when the fts5_tokenizer object
-** was registered with FTS5 (the third argument to xCreateTokenizer()).
-** The second and third arguments are an array of nul-terminated strings
-** containing the tokenizer arguments, if any, specified following the
-** tokenizer name as part of the CREATE VIRTUAL TABLE statement used
-** to create the FTS5 table.
-**
-** The final argument is an output variable. If successful, (*ppOut)
-** should be set to point to the new tokenizer handle and SQLITE_OK
-** returned. If an error occurs, some value other than SQLITE_OK should
-** be returned. In this case, fts5 assumes that the final value of *ppOut
-** is undefined.
-**
-** xDelete:
-** This function is invoked to delete a tokenizer handle previously
-** allocated using xCreate(). Fts5 guarantees that this function will
-** be invoked exactly once for each successful call to xCreate().
-**
-** xTokenize:
-** This function is expected to tokenize the nText byte string indicated
-** by argument pText. pText may or may not be nul-terminated. The first
-** argument passed to this function is a pointer to an Fts5Tokenizer object
-** returned by an earlier call to xCreate().
-**
-** The second argument indicates the reason that FTS5 is requesting
-** tokenization of the supplied text. This is always one of the following
-** four values:
-**
-** <ul><li> <b>FTS5_TOKENIZE_DOCUMENT</b> - A document is being inserted into
-** or removed from the FTS table. The tokenizer is being invoked to
-** determine the set of tokens to add to (or delete from) the
-** FTS index.
-**
-** <li> <b>FTS5_TOKENIZE_QUERY</b> - A MATCH query is being executed
-** against the FTS index. The tokenizer is being called to tokenize
-** a bareword or quoted string specified as part of the query.
-**
-** <li> <b>(FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX)</b> - Same as
-** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is
-** followed by a "*" character, indicating that the last token
-** returned by the tokenizer will be treated as a token prefix.
-**
-** <li> <b>FTS5_TOKENIZE_AUX</b> - The tokenizer is being invoked to
-** satisfy an fts5_api.xTokenize() request made by an auxiliary
-** function. Or an fts5_api.xColumnSize() request made by the same
-** on a columnsize=0 database.
-** </ul>
-**
-** For each token in the input string, the supplied callback xToken() must
-** be invoked. The first argument to it should be a copy of the pointer
-** passed as the second argument to xTokenize(). The third and fourth
-** arguments are a pointer to a buffer containing the token text, and the
-** size of the token in bytes. The 4th and 5th arguments are the byte offsets
-** of the first byte of and first byte immediately following the text from
-** which the token is derived within the input.
-**
-** The second argument passed to the xToken() callback ("tflags") should
-** normally be set to 0. The exception is if the tokenizer supports
-** synonyms. In this case see the discussion below for details.
-**
-** FTS5 assumes the xToken() callback is invoked for each token in the
-** order that they occur within the input text.
-**
-** If an xToken() callback returns any value other than SQLITE_OK, then
-** the tokenization should be abandoned and the xTokenize() method should
-** immediately return a copy of the xToken() return value. Or, if the
-** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally,
-** if an error occurs with the xTokenize() implementation itself, it
-** may abandon the tokenization and return any error code other than
-** SQLITE_OK or SQLITE_DONE.
-**
-** SYNONYM SUPPORT
-**
-** Custom tokenizers may also support synonyms. Consider a case in which a
-** user wishes to query for a phrase such as "first place". Using the
-** built-in tokenizers, the FTS5 query 'first + place' will match instances
-** of "first place" within the document set, but not alternative forms
-** such as "1st place". In some applications, it would be better to match
-** all instances of "first place" or "1st place" regardless of which form
-** the user specified in the MATCH query text.
-**
-** There are several ways to approach this in FTS5:
-**
-** <ol><li> By mapping all synonyms to a single token. In this case, the
-** In the above example, this means that the tokenizer returns the
-** same token for inputs "first" and "1st". Say that token is in
-** fact "first", so that when the user inserts the document "I won
-** 1st place" entries are added to the index for tokens "i", "won",
-** "first" and "place". If the user then queries for '1st + place',
-** the tokenizer substitutes "first" for "1st" and the query works
-** as expected.
-**
-** <li> By adding multiple synonyms for a single term to the FTS index.
-** In this case, when tokenizing query text, the tokenizer may
-** provide multiple synonyms for a single term within the document.
-** FTS5 then queries the index for each synonym individually. For
-** example, faced with the query:
-**
-** <codeblock>
-** ... MATCH 'first place'</codeblock>
-**
-** the tokenizer offers both "1st" and "first" as synonyms for the
-** first token in the MATCH query and FTS5 effectively runs a query
-** similar to:
-**
-** <codeblock>
-** ... MATCH '(first OR 1st) place'</codeblock>
-**
-** except that, for the purposes of auxiliary functions, the query
-** still appears to contain just two phrases - "(first OR 1st)"
-** being treated as a single phrase.
-**
-** <li> By adding multiple synonyms for a single term to the FTS index.
-** Using this method, when tokenizing document text, the tokenizer
-** provides multiple synonyms for each token. So that when a
-** document such as "I won first place" is tokenized, entries are
-** added to the FTS index for "i", "won", "first", "1st" and
-** "place".
-**
-** This way, even if the tokenizer does not provide synonyms
-** when tokenizing query text (it should not - to do would be
-** inefficient), it doesn't matter if the user queries for
-** 'first + place' or '1st + place', as there are entires in the
-** FTS index corresponding to both forms of the first token.
-** </ol>
-**
-** Whether it is parsing document or query text, any call to xToken that
-** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit
-** is considered to supply a synonym for the previous token. For example,
-** when parsing the document "I won first place", a tokenizer that supports
-** synonyms would call xToken() 5 times, as follows:
-**
-** <codeblock>
-** xToken(pCtx, 0, "i", 1, 0, 1);
-** xToken(pCtx, 0, "won", 3, 2, 5);
-** xToken(pCtx, 0, "first", 5, 6, 11);
-** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11);
-** xToken(pCtx, 0, "place", 5, 12, 17);
-**</codeblock>
-**
-** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time
-** xToken() is called. Multiple synonyms may be specified for a single token
-** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence.
-** There is no limit to the number of synonyms that may be provided for a
-** single token.
-**
-** In many cases, method (1) above is the best approach. It does not add
-** extra data to the FTS index or require FTS5 to query for multiple terms,
-** so it is efficient in terms of disk space and query speed. However, it
-** does not support prefix queries very well. If, as suggested above, the
-** token "first" is subsituted for "1st" by the tokenizer, then the query:
-**
-** <codeblock>
-** ... MATCH '1s*'</codeblock>
-**
-** will not match documents that contain the token "1st" (as the tokenizer
-** will probably not map "1s" to any prefix of "first").
-**
-** For full prefix support, method (3) may be preferred. In this case,
-** because the index contains entries for both "first" and "1st", prefix
-** queries such as 'fi*' or '1s*' will match correctly. However, because
-** extra entries are added to the FTS index, this method uses more space
-** within the database.
-**
-** Method (2) offers a midpoint between (1) and (3). Using this method,
-** a query such as '1s*' will match documents that contain the literal
-** token "1st", but not "first" (assuming the tokenizer is not able to
-** provide synonyms for prefixes). However, a non-prefix query like '1st'
-** will match against "1st" and "first". This method does not require
-** extra disk space, as no extra entries are added to the FTS index.
-** On the other hand, it may require more CPU cycles to run MATCH queries,
-** as separate queries of the FTS index are required for each synonym.
-**
-** When using methods (2) or (3), it is important that the tokenizer only
-** provide synonyms when tokenizing document text (method (2)) or query
-** text (method (3)), not both. Doing so will not cause any errors, but is
-** inefficient.
-*/
-typedef struct Fts5Tokenizer Fts5Tokenizer;
-typedef struct fts5_tokenizer fts5_tokenizer;
-struct fts5_tokenizer {
- int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
- void (*xDelete)(Fts5Tokenizer*);
- int (*xTokenize)(Fts5Tokenizer*,
- void *pCtx,
- int flags, /* Mask of FTS5_TOKENIZE_* flags */
- const char *pText, int nText,
- int (*xToken)(
- void *pCtx, /* Copy of 2nd argument to xTokenize() */
- int tflags, /* Mask of FTS5_TOKEN_* flags */
- const char *pToken, /* Pointer to buffer containing token */
- int nToken, /* Size of token in bytes */
- int iStart, /* Byte offset of token within input text */
- int iEnd /* Byte offset of end of token within input text */
- )
- );
-};
-
-/* Flags that may be passed as the third argument to xTokenize() */
-#define FTS5_TOKENIZE_QUERY 0x0001
-#define FTS5_TOKENIZE_PREFIX 0x0002
-#define FTS5_TOKENIZE_DOCUMENT 0x0004
-#define FTS5_TOKENIZE_AUX 0x0008
-
-/* Flags that may be passed by the tokenizer implementation back to FTS5
-** as the third argument to the supplied xToken callback. */
-#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */
-
-/*
-** END OF CUSTOM TOKENIZERS
-*************************************************************************/
-
-/*************************************************************************
-** FTS5 EXTENSION REGISTRATION API
-*/
-typedef struct fts5_api fts5_api;
-struct fts5_api {
- int iVersion; /* Currently always set to 2 */
-
- /* Create a new tokenizer */
- int (*xCreateTokenizer)(
- fts5_api *pApi,
- const char *zName,
- void *pContext,
- fts5_tokenizer *pTokenizer,
- void (*xDestroy)(void*)
- );
-
- /* Find an existing tokenizer */
- int (*xFindTokenizer)(
- fts5_api *pApi,
- const char *zName,
- void **ppContext,
- fts5_tokenizer *pTokenizer
- );
-
- /* Create a new auxiliary function */
- int (*xCreateFunction)(
- fts5_api *pApi,
- const char *zName,
- void *pContext,
- fts5_extension_function xFunction,
- void (*xDestroy)(void*)
- );
-};
-
-/*
-** END OF REGISTRATION API
-*************************************************************************/
-
-#ifdef __cplusplus
-} /* end of the 'extern "C"' block */
-#endif
-
-#endif /* _FTS5_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5Int.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5Int.h
deleted file mode 100644
index c87583676bb..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5Int.h
+++ /dev/null
@@ -1,794 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-**
-*/
-#ifndef _FTS5INT_H
-#define _FTS5INT_H
-
-#include "fts5.h"
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-#include <string.h>
-#include <assert.h>
-
-#ifndef SQLITE_AMALGAMATION
-
-typedef unsigned char u8;
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef short i16;
-typedef sqlite3_int64 i64;
-typedef sqlite3_uint64 u64;
-
-#ifndef ArraySize
-# define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
-#endif
-
-#define testcase(x)
-#define ALWAYS(x) 1
-#define NEVER(x) 0
-
-#define MIN(x,y) (((x) < (y)) ? (x) : (y))
-#define MAX(x,y) (((x) > (y)) ? (x) : (y))
-
-/*
-** Constants for the largest and smallest possible 64-bit signed integers.
-*/
-# define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
-# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
-
-#endif
-
-/* Truncate very long tokens to this many bytes. Hard limit is
-** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
-** field that occurs at the start of each leaf page (see fts5_index.c). */
-#define FTS5_MAX_TOKEN_SIZE 32768
-
-/*
-** Maximum number of prefix indexes on single FTS5 table. This must be
-** less than 32. If it is set to anything large than that, an #error
-** directive in fts5_index.c will cause the build to fail.
-*/
-#define FTS5_MAX_PREFIX_INDEXES 31
-
-#define FTS5_DEFAULT_NEARDIST 10
-#define FTS5_DEFAULT_RANK "bm25"
-
-/* Name of rank and rowid columns */
-#define FTS5_RANK_NAME "rank"
-#define FTS5_ROWID_NAME "rowid"
-
-#ifdef SQLITE_DEBUG
-# define FTS5_CORRUPT sqlite3Fts5Corrupt()
-int sqlite3Fts5Corrupt(void);
-#else
-# define FTS5_CORRUPT SQLITE_CORRUPT_VTAB
-#endif
-
-/*
-** The assert_nc() macro is similar to the assert() macro, except that it
-** is used for assert() conditions that are true only if it can be
-** guranteed that the database is not corrupt.
-*/
-#ifdef SQLITE_DEBUG
-extern int sqlite3_fts5_may_be_corrupt;
-# define assert_nc(x) assert(sqlite3_fts5_may_be_corrupt || (x))
-#else
-# define assert_nc(x) assert(x)
-#endif
-
-/* Mark a function parameter as unused, to suppress nuisance compiler
-** warnings. */
-#ifndef UNUSED_PARAM
-# define UNUSED_PARAM(X) (void)(X)
-#endif
-
-#ifndef UNUSED_PARAM2
-# define UNUSED_PARAM2(X, Y) (void)(X), (void)(Y)
-#endif
-
-typedef struct Fts5Global Fts5Global;
-typedef struct Fts5Colset Fts5Colset;
-
-/* If a NEAR() clump or phrase may only match a specific set of columns,
-** then an object of the following type is used to record the set of columns.
-** Each entry in the aiCol[] array is a column that may be matched.
-**
-** This object is used by fts5_expr.c and fts5_index.c.
-*/
-struct Fts5Colset {
- int nCol;
- int aiCol[1];
-};
-
-
-
-/**************************************************************************
-** Interface to code in fts5_config.c. fts5_config.c contains contains code
-** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
-*/
-
-typedef struct Fts5Config Fts5Config;
-
-/*
-** An instance of the following structure encodes all information that can
-** be gleaned from the CREATE VIRTUAL TABLE statement.
-**
-** And all information loaded from the %_config table.
-**
-** nAutomerge:
-** The minimum number of segments that an auto-merge operation should
-** attempt to merge together. A value of 1 sets the object to use the
-** compile time default. Zero disables auto-merge altogether.
-**
-** zContent:
-**
-** zContentRowid:
-** The value of the content_rowid= option, if one was specified. Or
-** the string "rowid" otherwise. This text is not quoted - if it is
-** used as part of an SQL statement it needs to be quoted appropriately.
-**
-** zContentExprlist:
-**
-** pzErrmsg:
-** This exists in order to allow the fts5_index.c module to return a
-** decent error message if it encounters a file-format version it does
-** not understand.
-**
-** bColumnsize:
-** True if the %_docsize table is created.
-**
-** bPrefixIndex:
-** This is only used for debugging. If set to false, any prefix indexes
-** are ignored. This value is configured using:
-**
-** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex);
-**
-*/
-struct Fts5Config {
- sqlite3 *db; /* Database handle */
- char *zDb; /* Database holding FTS index (e.g. "main") */
- char *zName; /* Name of FTS index */
- int nCol; /* Number of columns */
- char **azCol; /* Column names */
- u8 *abUnindexed; /* True for unindexed columns */
- int nPrefix; /* Number of prefix indexes */
- int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */
- int eContent; /* An FTS5_CONTENT value */
- char *zContent; /* content table */
- char *zContentRowid; /* "content_rowid=" option value */
- int bColumnsize; /* "columnsize=" option value (dflt==1) */
- int eDetail; /* FTS5_DETAIL_XXX value */
- char *zContentExprlist;
- Fts5Tokenizer *pTok;
- fts5_tokenizer *pTokApi;
-
- /* Values loaded from the %_config table */
- int iCookie; /* Incremented when %_config is modified */
- int pgsz; /* Approximate page size used in %_data */
- int nAutomerge; /* 'automerge' setting */
- int nCrisisMerge; /* Maximum allowed segments per level */
- int nUsermerge; /* 'usermerge' setting */
- int nHashSize; /* Bytes of memory for in-memory hash */
- char *zRank; /* Name of rank function */
- char *zRankArgs; /* Arguments to rank function */
-
- /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
- char **pzErrmsg;
-
-#ifdef SQLITE_DEBUG
- int bPrefixIndex; /* True to use prefix-indexes */
-#endif
-};
-
-/* Current expected value of %_config table 'version' field */
-#define FTS5_CURRENT_VERSION 4
-
-#define FTS5_CONTENT_NORMAL 0
-#define FTS5_CONTENT_NONE 1
-#define FTS5_CONTENT_EXTERNAL 2
-
-#define FTS5_DETAIL_FULL 0
-#define FTS5_DETAIL_NONE 1
-#define FTS5_DETAIL_COLUMNS 2
-
-
-
-int sqlite3Fts5ConfigParse(
- Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
-);
-void sqlite3Fts5ConfigFree(Fts5Config*);
-
-int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig);
-
-int sqlite3Fts5Tokenize(
- Fts5Config *pConfig, /* FTS5 Configuration object */
- int flags, /* FTS5_TOKENIZE_* flags */
- const char *pText, int nText, /* Text to tokenize */
- void *pCtx, /* Context passed to xToken() */
- int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
-);
-
-void sqlite3Fts5Dequote(char *z);
-
-/* Load the contents of the %_config table */
-int sqlite3Fts5ConfigLoad(Fts5Config*, int);
-
-/* Set the value of a single config attribute */
-int sqlite3Fts5ConfigSetValue(Fts5Config*, const char*, sqlite3_value*, int*);
-
-int sqlite3Fts5ConfigParseRank(const char*, char**, char**);
-
-/*
-** End of interface to code in fts5_config.c.
-**************************************************************************/
-
-/**************************************************************************
-** Interface to code in fts5_buffer.c.
-*/
-
-/*
-** Buffer object for the incremental building of string data.
-*/
-typedef struct Fts5Buffer Fts5Buffer;
-struct Fts5Buffer {
- u8 *p;
- int n;
- int nSpace;
-};
-
-int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32);
-void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64);
-void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, u32, const u8*);
-void sqlite3Fts5BufferAppendString(int *, Fts5Buffer*, const char*);
-void sqlite3Fts5BufferFree(Fts5Buffer*);
-void sqlite3Fts5BufferZero(Fts5Buffer*);
-void sqlite3Fts5BufferSet(int*, Fts5Buffer*, int, const u8*);
-void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...);
-
-char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);
-
-#define fts5BufferZero(x) sqlite3Fts5BufferZero(x)
-#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c)
-#define fts5BufferFree(a) sqlite3Fts5BufferFree(a)
-#define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d)
-#define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d)
-
-#define fts5BufferGrow(pRc,pBuf,nn) ( \
- (u32)((pBuf)->n) + (u32)(nn) <= (u32)((pBuf)->nSpace) ? 0 : \
- sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \
-)
-
-/* Write and decode big-endian 32-bit integer values */
-void sqlite3Fts5Put32(u8*, int);
-int sqlite3Fts5Get32(const u8*);
-
-#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
-#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF)
-
-typedef struct Fts5PoslistReader Fts5PoslistReader;
-struct Fts5PoslistReader {
- /* Variables used only by sqlite3Fts5PoslistIterXXX() functions. */
- const u8 *a; /* Position list to iterate through */
- int n; /* Size of buffer at a[] in bytes */
- int i; /* Current offset in a[] */
-
- u8 bFlag; /* For client use (any custom purpose) */
-
- /* Output variables */
- u8 bEof; /* Set to true at EOF */
- i64 iPos; /* (iCol<<32) + iPos */
-};
-int sqlite3Fts5PoslistReaderInit(
- const u8 *a, int n, /* Poslist buffer to iterate through */
- Fts5PoslistReader *pIter /* Iterator object to initialize */
-);
-int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader*);
-
-typedef struct Fts5PoslistWriter Fts5PoslistWriter;
-struct Fts5PoslistWriter {
- i64 iPrev;
-};
-int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64);
-void sqlite3Fts5PoslistSafeAppend(Fts5Buffer*, i64*, i64);
-
-int sqlite3Fts5PoslistNext64(
- const u8 *a, int n, /* Buffer containing poslist */
- int *pi, /* IN/OUT: Offset within a[] */
- i64 *piOff /* IN/OUT: Current offset */
-);
-
-/* Malloc utility */
-void *sqlite3Fts5MallocZero(int *pRc, int nByte);
-char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
-
-/* Character set tests (like isspace(), isalpha() etc.) */
-int sqlite3Fts5IsBareword(char t);
-
-
-/* Bucket of terms object used by the integrity-check in offsets=0 mode. */
-typedef struct Fts5Termset Fts5Termset;
-int sqlite3Fts5TermsetNew(Fts5Termset**);
-int sqlite3Fts5TermsetAdd(Fts5Termset*, int, const char*, int, int *pbPresent);
-void sqlite3Fts5TermsetFree(Fts5Termset*);
-
-/*
-** End of interface to code in fts5_buffer.c.
-**************************************************************************/
-
-/**************************************************************************
-** Interface to code in fts5_index.c. fts5_index.c contains contains code
-** to access the data stored in the %_data table.
-*/
-
-typedef struct Fts5Index Fts5Index;
-typedef struct Fts5IndexIter Fts5IndexIter;
-
-struct Fts5IndexIter {
- i64 iRowid;
- const u8 *pData;
- int nData;
- u8 bEof;
-};
-
-#define sqlite3Fts5IterEof(x) ((x)->bEof)
-
-/*
-** Values used as part of the flags argument passed to IndexQuery().
-*/
-#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */
-#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */
-#define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */
-#define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */
-
-/* The following are used internally by the fts5_index.c module. They are
-** defined here only to make it easier to avoid clashes with the flags
-** above. */
-#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010
-#define FTS5INDEX_QUERY_NOOUTPUT 0x0020
-
-/*
-** Create/destroy an Fts5Index object.
-*/
-int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**);
-int sqlite3Fts5IndexClose(Fts5Index *p);
-
-/*
-** Return a simple checksum value based on the arguments.
-*/
-u64 sqlite3Fts5IndexEntryCksum(
- i64 iRowid,
- int iCol,
- int iPos,
- int iIdx,
- const char *pTerm,
- int nTerm
-);
-
-/*
-** Argument p points to a buffer containing utf-8 text that is n bytes in
-** size. Return the number of bytes in the nChar character prefix of the
-** buffer, or 0 if there are less than nChar characters in total.
-*/
-int sqlite3Fts5IndexCharlenToBytelen(
- const char *p,
- int nByte,
- int nChar
-);
-
-/*
-** Open a new iterator to iterate though all rowids that match the
-** specified token or token prefix.
-*/
-int sqlite3Fts5IndexQuery(
- Fts5Index *p, /* FTS index to query */
- const char *pToken, int nToken, /* Token (or prefix) to query for */
- int flags, /* Mask of FTS5INDEX_QUERY_X flags */
- Fts5Colset *pColset, /* Match these columns only */
- Fts5IndexIter **ppIter /* OUT: New iterator object */
-);
-
-/*
-** The various operations on open token or token prefix iterators opened
-** using sqlite3Fts5IndexQuery().
-*/
-int sqlite3Fts5IterNext(Fts5IndexIter*);
-int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch);
-
-/*
-** Close an iterator opened by sqlite3Fts5IndexQuery().
-*/
-void sqlite3Fts5IterClose(Fts5IndexIter*);
-
-/*
-** This interface is used by the fts5vocab module.
-*/
-const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*);
-int sqlite3Fts5IterNextScan(Fts5IndexIter*);
-
-
-/*
-** Insert or remove data to or from the index. Each time a document is
-** added to or removed from the index, this function is called one or more
-** times.
-**
-** For an insert, it must be called once for each token in the new document.
-** If the operation is a delete, it must be called (at least) once for each
-** unique token in the document with an iCol value less than zero. The iPos
-** argument is ignored for a delete.
-*/
-int sqlite3Fts5IndexWrite(
- Fts5Index *p, /* Index to write to */
- int iCol, /* Column token appears in (-ve -> delete) */
- int iPos, /* Position of token within column */
- const char *pToken, int nToken /* Token to add or remove to or from index */
-);
-
-/*
-** Indicate that subsequent calls to sqlite3Fts5IndexWrite() pertain to
-** document iDocid.
-*/
-int sqlite3Fts5IndexBeginWrite(
- Fts5Index *p, /* Index to write to */
- int bDelete, /* True if current operation is a delete */
- i64 iDocid /* Docid to add or remove data from */
-);
-
-/*
-** Flush any data stored in the in-memory hash tables to the database.
-** Also close any open blob handles.
-*/
-int sqlite3Fts5IndexSync(Fts5Index *p);
-
-/*
-** Discard any data stored in the in-memory hash tables. Do not write it
-** to the database. Additionally, assume that the contents of the %_data
-** table may have changed on disk. So any in-memory caches of %_data
-** records must be invalidated.
-*/
-int sqlite3Fts5IndexRollback(Fts5Index *p);
-
-/*
-** Get or set the "averages" values.
-*/
-int sqlite3Fts5IndexGetAverages(Fts5Index *p, i64 *pnRow, i64 *anSize);
-int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);
-
-/*
-** Functions called by the storage module as part of integrity-check.
-*/
-int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
-
-/*
-** Called during virtual module initialization to register UDF
-** fts5_decode() with SQLite
-*/
-int sqlite3Fts5IndexInit(sqlite3*);
-
-int sqlite3Fts5IndexSetCookie(Fts5Index*, int);
-
-/*
-** Return the total number of entries read from the %_data table by
-** this connection since it was created.
-*/
-int sqlite3Fts5IndexReads(Fts5Index *p);
-
-int sqlite3Fts5IndexReinit(Fts5Index *p);
-int sqlite3Fts5IndexOptimize(Fts5Index *p);
-int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge);
-int sqlite3Fts5IndexReset(Fts5Index *p);
-
-int sqlite3Fts5IndexLoadConfig(Fts5Index *p);
-
-/*
-** End of interface to code in fts5_index.c.
-**************************************************************************/
-
-/**************************************************************************
-** Interface to code in fts5_varint.c.
-*/
-int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v);
-int sqlite3Fts5GetVarintLen(u32 iVal);
-u8 sqlite3Fts5GetVarint(const unsigned char*, u64*);
-int sqlite3Fts5PutVarint(unsigned char *p, u64 v);
-
-#define fts5GetVarint32(a,b) sqlite3Fts5GetVarint32(a,(u32*)&b)
-#define fts5GetVarint sqlite3Fts5GetVarint
-
-#define fts5FastGetVarint32(a, iOff, nVal) { \
- nVal = (a)[iOff++]; \
- if( nVal & 0x80 ){ \
- iOff--; \
- iOff += fts5GetVarint32(&(a)[iOff], nVal); \
- } \
-}
-
-
-/*
-** End of interface to code in fts5_varint.c.
-**************************************************************************/
-
-
-/**************************************************************************
-** Interface to code in fts5.c.
-*/
-
-int sqlite3Fts5GetTokenizer(
- Fts5Global*,
- const char **azArg,
- int nArg,
- Fts5Tokenizer**,
- fts5_tokenizer**,
- char **pzErr
-);
-
-Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
-
-/*
-** End of interface to code in fts5.c.
-**************************************************************************/
-
-/**************************************************************************
-** Interface to code in fts5_hash.c.
-*/
-typedef struct Fts5Hash Fts5Hash;
-
-/*
-** Create a hash table, free a hash table.
-*/
-int sqlite3Fts5HashNew(Fts5Config*, Fts5Hash**, int *pnSize);
-void sqlite3Fts5HashFree(Fts5Hash*);
-
-int sqlite3Fts5HashWrite(
- Fts5Hash*,
- i64 iRowid, /* Rowid for this entry */
- int iCol, /* Column token appears in (-ve -> delete) */
- int iPos, /* Position of token within column */
- char bByte,
- const char *pToken, int nToken /* Token to add or remove to or from index */
-);
-
-/*
-** Empty (but do not delete) a hash table.
-*/
-void sqlite3Fts5HashClear(Fts5Hash*);
-
-int sqlite3Fts5HashQuery(
- Fts5Hash*, /* Hash table to query */
- const char *pTerm, int nTerm, /* Query term */
- const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */
- int *pnDoclist /* OUT: Size of doclist in bytes */
-);
-
-int sqlite3Fts5HashScanInit(
- Fts5Hash*, /* Hash table to query */
- const char *pTerm, int nTerm /* Query prefix */
-);
-void sqlite3Fts5HashScanNext(Fts5Hash*);
-int sqlite3Fts5HashScanEof(Fts5Hash*);
-void sqlite3Fts5HashScanEntry(Fts5Hash *,
- const char **pzTerm, /* OUT: term (nul-terminated) */
- const u8 **ppDoclist, /* OUT: pointer to doclist */
- int *pnDoclist /* OUT: size of doclist in bytes */
-);
-
-
-/*
-** End of interface to code in fts5_hash.c.
-**************************************************************************/
-
-/**************************************************************************
-** Interface to code in fts5_storage.c. fts5_storage.c contains contains
-** code to access the data stored in the %_content and %_docsize tables.
-*/
-
-#define FTS5_STMT_SCAN_ASC 0 /* SELECT rowid, * FROM ... ORDER BY 1 ASC */
-#define FTS5_STMT_SCAN_DESC 1 /* SELECT rowid, * FROM ... ORDER BY 1 DESC */
-#define FTS5_STMT_LOOKUP 2 /* SELECT rowid, * FROM ... WHERE rowid=? */
-
-typedef struct Fts5Storage Fts5Storage;
-
-int sqlite3Fts5StorageOpen(Fts5Config*, Fts5Index*, int, Fts5Storage**, char**);
-int sqlite3Fts5StorageClose(Fts5Storage *p);
-int sqlite3Fts5StorageRename(Fts5Storage*, const char *zName);
-
-int sqlite3Fts5DropAll(Fts5Config*);
-int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **);
-
-int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**);
-int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
-int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
-
-int sqlite3Fts5StorageIntegrity(Fts5Storage *p);
-
-int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**);
-void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*);
-
-int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol);
-int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnAvg);
-int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow);
-
-int sqlite3Fts5StorageSync(Fts5Storage *p);
-int sqlite3Fts5StorageRollback(Fts5Storage *p);
-
-int sqlite3Fts5StorageConfigValue(
- Fts5Storage *p, const char*, sqlite3_value*, int
-);
-
-int sqlite3Fts5StorageDeleteAll(Fts5Storage *p);
-int sqlite3Fts5StorageRebuild(Fts5Storage *p);
-int sqlite3Fts5StorageOptimize(Fts5Storage *p);
-int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge);
-int sqlite3Fts5StorageReset(Fts5Storage *p);
-
-/*
-** End of interface to code in fts5_storage.c.
-**************************************************************************/
-
-
-/**************************************************************************
-** Interface to code in fts5_expr.c.
-*/
-typedef struct Fts5Expr Fts5Expr;
-typedef struct Fts5ExprNode Fts5ExprNode;
-typedef struct Fts5Parse Fts5Parse;
-typedef struct Fts5Token Fts5Token;
-typedef struct Fts5ExprPhrase Fts5ExprPhrase;
-typedef struct Fts5ExprNearset Fts5ExprNearset;
-
-struct Fts5Token {
- const char *p; /* Token text (not NULL terminated) */
- int n; /* Size of buffer p in bytes */
-};
-
-/* Parse a MATCH expression. */
-int sqlite3Fts5ExprNew(
- Fts5Config *pConfig,
- int iCol, /* Column on LHS of MATCH operator */
- const char *zExpr,
- Fts5Expr **ppNew,
- char **pzErr
-);
-
-/*
-** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
-** rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
-** rc = sqlite3Fts5ExprNext(pExpr)
-** ){
-** // The document with rowid iRowid matches the expression!
-** i64 iRowid = sqlite3Fts5ExprRowid(pExpr);
-** }
-*/
-int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc);
-int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax);
-int sqlite3Fts5ExprEof(Fts5Expr*);
-i64 sqlite3Fts5ExprRowid(Fts5Expr*);
-
-void sqlite3Fts5ExprFree(Fts5Expr*);
-
-/* Called during startup to register a UDF with SQLite */
-int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);
-
-int sqlite3Fts5ExprPhraseCount(Fts5Expr*);
-int sqlite3Fts5ExprPhraseSize(Fts5Expr*, int iPhrase);
-int sqlite3Fts5ExprPoslist(Fts5Expr*, int, const u8 **);
-
-typedef struct Fts5PoslistPopulator Fts5PoslistPopulator;
-Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr*, int);
-int sqlite3Fts5ExprPopulatePoslists(
- Fts5Config*, Fts5Expr*, Fts5PoslistPopulator*, int, const char*, int
-);
-void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64);
-
-int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**);
-
-int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *);
-
-/*******************************************
-** The fts5_expr.c API above this point is used by the other hand-written
-** C code in this module. The interfaces below this point are called by
-** the parser code in fts5parse.y. */
-
-void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...);
-
-Fts5ExprNode *sqlite3Fts5ParseNode(
- Fts5Parse *pParse,
- int eType,
- Fts5ExprNode *pLeft,
- Fts5ExprNode *pRight,
- Fts5ExprNearset *pNear
-);
-
-Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
- Fts5Parse *pParse,
- Fts5ExprNode *pLeft,
- Fts5ExprNode *pRight
-);
-
-Fts5ExprPhrase *sqlite3Fts5ParseTerm(
- Fts5Parse *pParse,
- Fts5ExprPhrase *pPhrase,
- Fts5Token *pToken,
- int bPrefix
-);
-
-void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase*);
-
-Fts5ExprNearset *sqlite3Fts5ParseNearset(
- Fts5Parse*,
- Fts5ExprNearset*,
- Fts5ExprPhrase*
-);
-
-Fts5Colset *sqlite3Fts5ParseColset(
- Fts5Parse*,
- Fts5Colset*,
- Fts5Token *
-);
-
-void sqlite3Fts5ParsePhraseFree(Fts5ExprPhrase*);
-void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*);
-void sqlite3Fts5ParseNodeFree(Fts5ExprNode*);
-
-void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
-void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNode*, Fts5Colset*);
-Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse*, Fts5Colset*);
-void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
-void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
-
-/*
-** End of interface to code in fts5_expr.c.
-**************************************************************************/
-
-
-
-/**************************************************************************
-** Interface to code in fts5_aux.c.
-*/
-
-int sqlite3Fts5AuxInit(fts5_api*);
-/*
-** End of interface to code in fts5_aux.c.
-**************************************************************************/
-
-/**************************************************************************
-** Interface to code in fts5_tokenizer.c.
-*/
-
-int sqlite3Fts5TokenizerInit(fts5_api*);
-/*
-** End of interface to code in fts5_tokenizer.c.
-**************************************************************************/
-
-/**************************************************************************
-** Interface to code in fts5_vocab.c.
-*/
-
-int sqlite3Fts5VocabInit(Fts5Global*, sqlite3*);
-
-/*
-** End of interface to code in fts5_vocab.c.
-**************************************************************************/
-
-
-/**************************************************************************
-** Interface to automatically generated code in fts5_unicode2.c.
-*/
-int sqlite3Fts5UnicodeIsalnum(int c);
-int sqlite3Fts5UnicodeIsdiacritic(int c);
-int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic);
-/*
-** End of interface to code in fts5_unicode2.c.
-**************************************************************************/
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_aux.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_aux.c
deleted file mode 100644
index 594b981dda2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_aux.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-*/
-
-
-#include "fts5Int.h"
-#include <math.h> /* amalgamator: keep */
-
-/*
-** Object used to iterate through all "coalesced phrase instances" in
-** a single column of the current row. If the phrase instances in the
-** column being considered do not overlap, this object simply iterates
-** through them. Or, if they do overlap (share one or more tokens in
-** common), each set of overlapping instances is treated as a single
-** match. See documentation for the highlight() auxiliary function for
-** details.
-**
-** Usage is:
-**
-** for(rc = fts5CInstIterNext(pApi, pFts, iCol, &iter);
-** (rc==SQLITE_OK && 0==fts5CInstIterEof(&iter);
-** rc = fts5CInstIterNext(&iter)
-** ){
-** printf("instance starts at %d, ends at %d\n", iter.iStart, iter.iEnd);
-** }
-**
-*/
-typedef struct CInstIter CInstIter;
-struct CInstIter {
- const Fts5ExtensionApi *pApi; /* API offered by current FTS version */
- Fts5Context *pFts; /* First arg to pass to pApi functions */
- int iCol; /* Column to search */
- int iInst; /* Next phrase instance index */
- int nInst; /* Total number of phrase instances */
-
- /* Output variables */
- int iStart; /* First token in coalesced phrase instance */
- int iEnd; /* Last token in coalesced phrase instance */
-};
-
-/*
-** Advance the iterator to the next coalesced phrase instance. Return
-** an SQLite error code if an error occurs, or SQLITE_OK otherwise.
-*/
-static int fts5CInstIterNext(CInstIter *pIter){
- int rc = SQLITE_OK;
- pIter->iStart = -1;
- pIter->iEnd = -1;
-
- while( rc==SQLITE_OK && pIter->iInst<pIter->nInst ){
- int ip; int ic; int io;
- rc = pIter->pApi->xInst(pIter->pFts, pIter->iInst, &ip, &ic, &io);
- if( rc==SQLITE_OK ){
- if( ic==pIter->iCol ){
- int iEnd = io - 1 + pIter->pApi->xPhraseSize(pIter->pFts, ip);
- if( pIter->iStart<0 ){
- pIter->iStart = io;
- pIter->iEnd = iEnd;
- }else if( io<=pIter->iEnd ){
- if( iEnd>pIter->iEnd ) pIter->iEnd = iEnd;
- }else{
- break;
- }
- }
- pIter->iInst++;
- }
- }
-
- return rc;
-}
-
-/*
-** Initialize the iterator object indicated by the final parameter to
-** iterate through coalesced phrase instances in column iCol.
-*/
-static int fts5CInstIterInit(
- const Fts5ExtensionApi *pApi,
- Fts5Context *pFts,
- int iCol,
- CInstIter *pIter
-){
- int rc;
-
- memset(pIter, 0, sizeof(CInstIter));
- pIter->pApi = pApi;
- pIter->pFts = pFts;
- pIter->iCol = iCol;
- rc = pApi->xInstCount(pFts, &pIter->nInst);
-
- if( rc==SQLITE_OK ){
- rc = fts5CInstIterNext(pIter);
- }
-
- return rc;
-}
-
-
-
-/*************************************************************************
-** Start of highlight() implementation.
-*/
-typedef struct HighlightContext HighlightContext;
-struct HighlightContext {
- CInstIter iter; /* Coalesced Instance Iterator */
- int iPos; /* Current token offset in zIn[] */
- int iRangeStart; /* First token to include */
- int iRangeEnd; /* If non-zero, last token to include */
- const char *zOpen; /* Opening highlight */
- const char *zClose; /* Closing highlight */
- const char *zIn; /* Input text */
- int nIn; /* Size of input text in bytes */
- int iOff; /* Current offset within zIn[] */
- char *zOut; /* Output value */
-};
-
-/*
-** Append text to the HighlightContext output string - p->zOut. Argument
-** z points to a buffer containing n bytes of text to append. If n is
-** negative, everything up until the first '\0' is appended to the output.
-**
-** If *pRc is set to any value other than SQLITE_OK when this function is
-** called, it is a no-op. If an error (i.e. an OOM condition) is encountered,
-** *pRc is set to an error code before returning.
-*/
-static void fts5HighlightAppend(
- int *pRc,
- HighlightContext *p,
- const char *z, int n
-){
- if( *pRc==SQLITE_OK ){
- if( n<0 ) n = (int)strlen(z);
- p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z);
- if( p->zOut==0 ) *pRc = SQLITE_NOMEM;
- }
-}
-
-/*
-** Tokenizer callback used by implementation of highlight() function.
-*/
-static int fts5HighlightCb(
- void *pContext, /* Pointer to HighlightContext object */
- int tflags, /* Mask of FTS5_TOKEN_* flags */
- const char *pToken, /* Buffer containing token */
- int nToken, /* Size of token in bytes */
- int iStartOff, /* Start offset of token */
- int iEndOff /* End offset of token */
-){
- HighlightContext *p = (HighlightContext*)pContext;
- int rc = SQLITE_OK;
- int iPos;
-
- UNUSED_PARAM2(pToken, nToken);
-
- if( tflags & FTS5_TOKEN_COLOCATED ) return SQLITE_OK;
- iPos = p->iPos++;
-
- if( p->iRangeEnd>0 ){
- if( iPos<p->iRangeStart || iPos>p->iRangeEnd ) return SQLITE_OK;
- if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff;
- }
-
- if( iPos==p->iter.iStart ){
- fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iStartOff - p->iOff);
- fts5HighlightAppend(&rc, p, p->zOpen, -1);
- p->iOff = iStartOff;
- }
-
- if( iPos==p->iter.iEnd ){
- if( p->iRangeEnd && p->iter.iStart<p->iRangeStart ){
- fts5HighlightAppend(&rc, p, p->zOpen, -1);
- }
- fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
- fts5HighlightAppend(&rc, p, p->zClose, -1);
- p->iOff = iEndOff;
- if( rc==SQLITE_OK ){
- rc = fts5CInstIterNext(&p->iter);
- }
- }
-
- if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){
- fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
- p->iOff = iEndOff;
- if( iPos>=p->iter.iStart && iPos<p->iter.iEnd ){
- fts5HighlightAppend(&rc, p, p->zClose, -1);
- }
- }
-
- return rc;
-}
-
-/*
-** Implementation of highlight() function.
-*/
-static void fts5HighlightFunction(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- sqlite3_context *pCtx, /* Context for returning result/error */
- int nVal, /* Number of values in apVal[] array */
- sqlite3_value **apVal /* Array of trailing arguments */
-){
- HighlightContext ctx;
- int rc;
- int iCol;
-
- if( nVal!=3 ){
- const char *zErr = "wrong number of arguments to function highlight()";
- sqlite3_result_error(pCtx, zErr, -1);
- return;
- }
-
- iCol = sqlite3_value_int(apVal[0]);
- memset(&ctx, 0, sizeof(HighlightContext));
- ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]);
- ctx.zClose = (const char*)sqlite3_value_text(apVal[2]);
- rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn);
-
- if( ctx.zIn ){
- if( rc==SQLITE_OK ){
- rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter);
- }
-
- if( rc==SQLITE_OK ){
- rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
- }
- fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
-
- if( rc==SQLITE_OK ){
- sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
- }
- sqlite3_free(ctx.zOut);
- }
- if( rc!=SQLITE_OK ){
- sqlite3_result_error_code(pCtx, rc);
- }
-}
-/*
-** End of highlight() implementation.
-**************************************************************************/
-
-/*
-** Context object passed to the fts5SentenceFinderCb() function.
-*/
-typedef struct Fts5SFinder Fts5SFinder;
-struct Fts5SFinder {
- int iPos; /* Current token position */
- int nFirstAlloc; /* Allocated size of aFirst[] */
- int nFirst; /* Number of entries in aFirst[] */
- int *aFirst; /* Array of first token in each sentence */
- const char *zDoc; /* Document being tokenized */
-};
-
-/*
-** Add an entry to the Fts5SFinder.aFirst[] array. Grow the array if
-** necessary. Return SQLITE_OK if successful, or SQLITE_NOMEM if an
-** error occurs.
-*/
-static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){
- if( p->nFirstAlloc==p->nFirst ){
- int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64;
- int *aNew;
-
- aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int));
- if( aNew==0 ) return SQLITE_NOMEM;
- p->aFirst = aNew;
- p->nFirstAlloc = nNew;
- }
- p->aFirst[p->nFirst++] = iAdd;
- return SQLITE_OK;
-}
-
-/*
-** This function is an xTokenize() callback used by the auxiliary snippet()
-** function. Its job is to identify tokens that are the first in a sentence.
-** For each such token, an entry is added to the SFinder.aFirst[] array.
-*/
-static int fts5SentenceFinderCb(
- void *pContext, /* Pointer to HighlightContext object */
- int tflags, /* Mask of FTS5_TOKEN_* flags */
- const char *pToken, /* Buffer containing token */
- int nToken, /* Size of token in bytes */
- int iStartOff, /* Start offset of token */
- int iEndOff /* End offset of token */
-){
- int rc = SQLITE_OK;
-
- UNUSED_PARAM2(pToken, nToken);
- UNUSED_PARAM(iEndOff);
-
- if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
- Fts5SFinder *p = (Fts5SFinder*)pContext;
- if( p->iPos>0 ){
- int i;
- char c = 0;
- for(i=iStartOff-1; i>=0; i--){
- c = p->zDoc[i];
- if( c!=' ' && c!='\t' && c!='\n' && c!='\r' ) break;
- }
- if( i!=iStartOff-1 && (c=='.' || c==':') ){
- rc = fts5SentenceFinderAdd(p, p->iPos);
- }
- }else{
- rc = fts5SentenceFinderAdd(p, 0);
- }
- p->iPos++;
- }
- return rc;
-}
-
-static int fts5SnippetScore(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- int nDocsize, /* Size of column in tokens */
- unsigned char *aSeen, /* Array with one element per query phrase */
- int iCol, /* Column to score */
- int iPos, /* Starting offset to score */
- int nToken, /* Max tokens per snippet */
- int *pnScore, /* OUT: Score */
- int *piPos /* OUT: Adjusted offset */
-){
- int rc;
- int i;
- int ip = 0;
- int ic = 0;
- int iOff = 0;
- int iFirst = -1;
- int nInst;
- int nScore = 0;
- int iLast = 0;
-
- rc = pApi->xInstCount(pFts, &nInst);
- for(i=0; i<nInst && rc==SQLITE_OK; i++){
- rc = pApi->xInst(pFts, i, &ip, &ic, &iOff);
- if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){
- nScore += (aSeen[ip] ? 1 : 1000);
- aSeen[ip] = 1;
- if( iFirst<0 ) iFirst = iOff;
- iLast = iOff + pApi->xPhraseSize(pFts, ip);
- }
- }
-
- *pnScore = nScore;
- if( piPos ){
- int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
- if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken;
- if( iAdj<0 ) iAdj = 0;
- *piPos = iAdj;
- }
-
- return rc;
-}
-
-/*
-** Return the value in pVal interpreted as utf-8 text. Except, if pVal
-** contains a NULL value, return a pointer to a static string zero
-** bytes in length instead of a NULL pointer.
-*/
-static const char *fts5ValueToText(sqlite3_value *pVal){
- const char *zRet = (const char*)sqlite3_value_text(pVal);
- return zRet ? zRet : "";
-}
-
-/*
-** Implementation of snippet() function.
-*/
-static void fts5SnippetFunction(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- sqlite3_context *pCtx, /* Context for returning result/error */
- int nVal, /* Number of values in apVal[] array */
- sqlite3_value **apVal /* Array of trailing arguments */
-){
- HighlightContext ctx;
- int rc = SQLITE_OK; /* Return code */
- int iCol; /* 1st argument to snippet() */
- const char *zEllips; /* 4th argument to snippet() */
- int nToken; /* 5th argument to snippet() */
- int nInst = 0; /* Number of instance matches this row */
- int i; /* Used to iterate through instances */
- int nPhrase; /* Number of phrases in query */
- unsigned char *aSeen; /* Array of "seen instance" flags */
- int iBestCol; /* Column containing best snippet */
- int iBestStart = 0; /* First token of best snippet */
- int nBestScore = 0; /* Score of best snippet */
- int nColSize = 0; /* Total size of iBestCol in tokens */
- Fts5SFinder sFinder; /* Used to find the beginnings of sentences */
- int nCol;
-
- if( nVal!=5 ){
- const char *zErr = "wrong number of arguments to function snippet()";
- sqlite3_result_error(pCtx, zErr, -1);
- return;
- }
-
- nCol = pApi->xColumnCount(pFts);
- memset(&ctx, 0, sizeof(HighlightContext));
- iCol = sqlite3_value_int(apVal[0]);
- ctx.zOpen = fts5ValueToText(apVal[1]);
- ctx.zClose = fts5ValueToText(apVal[2]);
- zEllips = fts5ValueToText(apVal[3]);
- nToken = sqlite3_value_int(apVal[4]);
-
- iBestCol = (iCol>=0 ? iCol : 0);
- nPhrase = pApi->xPhraseCount(pFts);
- aSeen = sqlite3_malloc(nPhrase);
- if( aSeen==0 ){
- rc = SQLITE_NOMEM;
- }
- if( rc==SQLITE_OK ){
- rc = pApi->xInstCount(pFts, &nInst);
- }
-
- memset(&sFinder, 0, sizeof(Fts5SFinder));
- for(i=0; i<nCol; i++){
- if( iCol<0 || iCol==i ){
- int nDoc;
- int nDocsize;
- int ii;
- sFinder.iPos = 0;
- sFinder.nFirst = 0;
- rc = pApi->xColumnText(pFts, i, &sFinder.zDoc, &nDoc);
- if( rc!=SQLITE_OK ) break;
- rc = pApi->xTokenize(pFts,
- sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb
- );
- if( rc!=SQLITE_OK ) break;
- rc = pApi->xColumnSize(pFts, i, &nDocsize);
- if( rc!=SQLITE_OK ) break;
-
- for(ii=0; rc==SQLITE_OK && ii<nInst; ii++){
- int ip, ic, io;
- int iAdj;
- int nScore;
- int jj;
-
- rc = pApi->xInst(pFts, ii, &ip, &ic, &io);
- if( ic!=i || rc!=SQLITE_OK ) continue;
- memset(aSeen, 0, nPhrase);
- rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
- io, nToken, &nScore, &iAdj
- );
- if( rc==SQLITE_OK && nScore>nBestScore ){
- nBestScore = nScore;
- iBestCol = i;
- iBestStart = iAdj;
- nColSize = nDocsize;
- }
-
- if( rc==SQLITE_OK && sFinder.nFirst && nDocsize>nToken ){
- for(jj=0; jj<(sFinder.nFirst-1); jj++){
- if( sFinder.aFirst[jj+1]>io ) break;
- }
-
- if( sFinder.aFirst[jj]<io ){
- memset(aSeen, 0, nPhrase);
- rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
- sFinder.aFirst[jj], nToken, &nScore, 0
- );
-
- nScore += (sFinder.aFirst[jj]==0 ? 120 : 100);
- if( rc==SQLITE_OK && nScore>nBestScore ){
- nBestScore = nScore;
- iBestCol = i;
- iBestStart = sFinder.aFirst[jj];
- nColSize = nDocsize;
- }
- }
- }
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn);
- }
- if( rc==SQLITE_OK && nColSize==0 ){
- rc = pApi->xColumnSize(pFts, iBestCol, &nColSize);
- }
- if( ctx.zIn ){
- if( rc==SQLITE_OK ){
- rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
- }
-
- ctx.iRangeStart = iBestStart;
- ctx.iRangeEnd = iBestStart + nToken - 1;
-
- if( iBestStart>0 ){
- fts5HighlightAppend(&rc, &ctx, zEllips, -1);
- }
-
- /* Advance iterator ctx.iter so that it points to the first coalesced
- ** phrase instance at or following position iBestStart. */
- while( ctx.iter.iStart>=0 && ctx.iter.iStart<iBestStart && rc==SQLITE_OK ){
- rc = fts5CInstIterNext(&ctx.iter);
- }
-
- if( rc==SQLITE_OK ){
- rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
- }
- if( ctx.iRangeEnd>=(nColSize-1) ){
- fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
- }else{
- fts5HighlightAppend(&rc, &ctx, zEllips, -1);
- }
- }
- if( rc==SQLITE_OK ){
- sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_error_code(pCtx, rc);
- }
- sqlite3_free(ctx.zOut);
- sqlite3_free(aSeen);
- sqlite3_free(sFinder.aFirst);
-}
-
-/************************************************************************/
-
-/*
-** The first time the bm25() function is called for a query, an instance
-** of the following structure is allocated and populated.
-*/
-typedef struct Fts5Bm25Data Fts5Bm25Data;
-struct Fts5Bm25Data {
- int nPhrase; /* Number of phrases in query */
- double avgdl; /* Average number of tokens in each row */
- double *aIDF; /* IDF for each phrase */
- double *aFreq; /* Array used to calculate phrase freq. */
-};
-
-/*
-** Callback used by fts5Bm25GetData() to count the number of rows in the
-** table matched by each individual phrase within the query.
-*/
-static int fts5CountCb(
- const Fts5ExtensionApi *pApi,
- Fts5Context *pFts,
- void *pUserData /* Pointer to sqlite3_int64 variable */
-){
- sqlite3_int64 *pn = (sqlite3_int64*)pUserData;
- UNUSED_PARAM2(pApi, pFts);
- (*pn)++;
- return SQLITE_OK;
-}
-
-/*
-** Set *ppData to point to the Fts5Bm25Data object for the current query.
-** If the object has not already been allocated, allocate and populate it
-** now.
-*/
-static int fts5Bm25GetData(
- const Fts5ExtensionApi *pApi,
- Fts5Context *pFts,
- Fts5Bm25Data **ppData /* OUT: bm25-data object for this query */
-){
- int rc = SQLITE_OK; /* Return code */
- Fts5Bm25Data *p; /* Object to return */
-
- p = pApi->xGetAuxdata(pFts, 0);
- if( p==0 ){
- int nPhrase; /* Number of phrases in query */
- sqlite3_int64 nRow = 0; /* Number of rows in table */
- sqlite3_int64 nToken = 0; /* Number of tokens in table */
- int nByte; /* Bytes of space to allocate */
- int i;
-
- /* Allocate the Fts5Bm25Data object */
- nPhrase = pApi->xPhraseCount(pFts);
- nByte = sizeof(Fts5Bm25Data) + nPhrase*2*sizeof(double);
- p = (Fts5Bm25Data*)sqlite3_malloc(nByte);
- if( p==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(p, 0, nByte);
- p->nPhrase = nPhrase;
- p->aIDF = (double*)&p[1];
- p->aFreq = &p->aIDF[nPhrase];
- }
-
- /* Calculate the average document length for this FTS5 table */
- if( rc==SQLITE_OK ) rc = pApi->xRowCount(pFts, &nRow);
- if( rc==SQLITE_OK ) rc = pApi->xColumnTotalSize(pFts, -1, &nToken);
- if( rc==SQLITE_OK ) p->avgdl = (double)nToken / (double)nRow;
-
- /* Calculate an IDF for each phrase in the query */
- for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
- sqlite3_int64 nHit = 0;
- rc = pApi->xQueryPhrase(pFts, i, (void*)&nHit, fts5CountCb);
- if( rc==SQLITE_OK ){
- /* Calculate the IDF (Inverse Document Frequency) for phrase i.
- ** This is done using the standard BM25 formula as found on wikipedia:
- **
- ** IDF = log( (N - nHit + 0.5) / (nHit + 0.5) )
- **
- ** where "N" is the total number of documents in the set and nHit
- ** is the number that contain at least one instance of the phrase
- ** under consideration.
- **
- ** The problem with this is that if (N < 2*nHit), the IDF is
- ** negative. Which is undesirable. So the mimimum allowable IDF is
- ** (1e-6) - roughly the same as a term that appears in just over
- ** half of set of 5,000,000 documents. */
- double idf = log( (nRow - nHit + 0.5) / (nHit + 0.5) );
- if( idf<=0.0 ) idf = 1e-6;
- p->aIDF[i] = idf;
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_free(p);
- }else{
- rc = pApi->xSetAuxdata(pFts, p, sqlite3_free);
- }
- if( rc!=SQLITE_OK ) p = 0;
- }
- *ppData = p;
- return rc;
-}
-
-/*
-** Implementation of bm25() function.
-*/
-static void fts5Bm25Function(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- sqlite3_context *pCtx, /* Context for returning result/error */
- int nVal, /* Number of values in apVal[] array */
- sqlite3_value **apVal /* Array of trailing arguments */
-){
- const double k1 = 1.2; /* Constant "k1" from BM25 formula */
- const double b = 0.75; /* Constant "b" from BM25 formula */
- int rc = SQLITE_OK; /* Error code */
- double score = 0.0; /* SQL function return value */
- Fts5Bm25Data *pData; /* Values allocated/calculated once only */
- int i; /* Iterator variable */
- int nInst = 0; /* Value returned by xInstCount() */
- double D = 0.0; /* Total number of tokens in row */
- double *aFreq = 0; /* Array of phrase freq. for current row */
-
- /* Calculate the phrase frequency (symbol "f(qi,D)" in the documentation)
- ** for each phrase in the query for the current row. */
- rc = fts5Bm25GetData(pApi, pFts, &pData);
- if( rc==SQLITE_OK ){
- aFreq = pData->aFreq;
- memset(aFreq, 0, sizeof(double) * pData->nPhrase);
- rc = pApi->xInstCount(pFts, &nInst);
- }
- for(i=0; rc==SQLITE_OK && i<nInst; i++){
- int ip; int ic; int io;
- rc = pApi->xInst(pFts, i, &ip, &ic, &io);
- if( rc==SQLITE_OK ){
- double w = (nVal > ic) ? sqlite3_value_double(apVal[ic]) : 1.0;
- aFreq[ip] += w;
- }
- }
-
- /* Figure out the total size of the current row in tokens. */
- if( rc==SQLITE_OK ){
- int nTok;
- rc = pApi->xColumnSize(pFts, -1, &nTok);
- D = (double)nTok;
- }
-
- /* Determine the BM25 score for the current row. */
- for(i=0; rc==SQLITE_OK && i<pData->nPhrase; i++){
- score += pData->aIDF[i] * (
- ( aFreq[i] * (k1 + 1.0) ) /
- ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
- );
- }
-
- /* If no error has occurred, return the calculated score. Otherwise,
- ** throw an SQL exception. */
- if( rc==SQLITE_OK ){
- sqlite3_result_double(pCtx, -1.0 * score);
- }else{
- sqlite3_result_error_code(pCtx, rc);
- }
-}
-
-int sqlite3Fts5AuxInit(fts5_api *pApi){
- struct Builtin {
- const char *zFunc; /* Function name (nul-terminated) */
- void *pUserData; /* User-data pointer */
- fts5_extension_function xFunc;/* Callback function */
- void (*xDestroy)(void*); /* Destructor function */
- } aBuiltin [] = {
- { "snippet", 0, fts5SnippetFunction, 0 },
- { "highlight", 0, fts5HighlightFunction, 0 },
- { "bm25", 0, fts5Bm25Function, 0 },
- };
- int rc = SQLITE_OK; /* Return code */
- int i; /* To iterate through builtin functions */
-
- for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){
- rc = pApi->xCreateFunction(pApi,
- aBuiltin[i].zFunc,
- aBuiltin[i].pUserData,
- aBuiltin[i].xFunc,
- aBuiltin[i].xDestroy
- );
- }
-
- return rc;
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_buffer.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_buffer.c
deleted file mode 100644
index b11689745b1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_buffer.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-*/
-
-
-
-#include "fts5Int.h"
-
-int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){
- if( (u32)pBuf->nSpace<nByte ){
- u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
- u8 *pNew;
- while( nNew<nByte ){
- nNew = nNew * 2;
- }
- pNew = sqlite3_realloc(pBuf->p, nNew);
- if( pNew==0 ){
- *pRc = SQLITE_NOMEM;
- return 1;
- }else{
- pBuf->nSpace = nNew;
- pBuf->p = pNew;
- }
- }
- return 0;
-}
-
-
-/*
-** Encode value iVal as an SQLite varint and append it to the buffer object
-** pBuf. If an OOM error occurs, set the error code in p.
-*/
-void sqlite3Fts5BufferAppendVarint(int *pRc, Fts5Buffer *pBuf, i64 iVal){
- if( fts5BufferGrow(pRc, pBuf, 9) ) return;
- pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iVal);
-}
-
-void sqlite3Fts5Put32(u8 *aBuf, int iVal){
- aBuf[0] = (iVal>>24) & 0x00FF;
- aBuf[1] = (iVal>>16) & 0x00FF;
- aBuf[2] = (iVal>> 8) & 0x00FF;
- aBuf[3] = (iVal>> 0) & 0x00FF;
-}
-
-int sqlite3Fts5Get32(const u8 *aBuf){
- return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
-}
-
-/*
-** Append buffer nData/pData to buffer pBuf. If an OOM error occurs, set
-** the error code in p. If an error has already occurred when this function
-** is called, it is a no-op.
-*/
-void sqlite3Fts5BufferAppendBlob(
- int *pRc,
- Fts5Buffer *pBuf,
- u32 nData,
- const u8 *pData
-){
- assert_nc( *pRc || nData>=0 );
- if( nData ){
- if( fts5BufferGrow(pRc, pBuf, nData) ) return;
- memcpy(&pBuf->p[pBuf->n], pData, nData);
- pBuf->n += nData;
- }
-}
-
-/*
-** Append the nul-terminated string zStr to the buffer pBuf. This function
-** ensures that the byte following the buffer data is set to 0x00, even
-** though this byte is not included in the pBuf->n count.
-*/
-void sqlite3Fts5BufferAppendString(
- int *pRc,
- Fts5Buffer *pBuf,
- const char *zStr
-){
- int nStr = (int)strlen(zStr);
- sqlite3Fts5BufferAppendBlob(pRc, pBuf, nStr+1, (const u8*)zStr);
- pBuf->n--;
-}
-
-/*
-** Argument zFmt is a printf() style format string. This function performs
-** the printf() style processing, then appends the results to buffer pBuf.
-**
-** Like sqlite3Fts5BufferAppendString(), this function ensures that the byte
-** following the buffer data is set to 0x00, even though this byte is not
-** included in the pBuf->n count.
-*/
-void sqlite3Fts5BufferAppendPrintf(
- int *pRc,
- Fts5Buffer *pBuf,
- char *zFmt, ...
-){
- if( *pRc==SQLITE_OK ){
- char *zTmp;
- va_list ap;
- va_start(ap, zFmt);
- zTmp = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
-
- if( zTmp==0 ){
- *pRc = SQLITE_NOMEM;
- }else{
- sqlite3Fts5BufferAppendString(pRc, pBuf, zTmp);
- sqlite3_free(zTmp);
- }
- }
-}
-
-char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...){
- char *zRet = 0;
- if( *pRc==SQLITE_OK ){
- va_list ap;
- va_start(ap, zFmt);
- zRet = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
- if( zRet==0 ){
- *pRc = SQLITE_NOMEM;
- }
- }
- return zRet;
-}
-
-
-/*
-** Free any buffer allocated by pBuf. Zero the structure before returning.
-*/
-void sqlite3Fts5BufferFree(Fts5Buffer *pBuf){
- sqlite3_free(pBuf->p);
- memset(pBuf, 0, sizeof(Fts5Buffer));
-}
-
-/*
-** Zero the contents of the buffer object. But do not free the associated
-** memory allocation.
-*/
-void sqlite3Fts5BufferZero(Fts5Buffer *pBuf){
- pBuf->n = 0;
-}
-
-/*
-** Set the buffer to contain nData/pData. If an OOM error occurs, leave an
-** the error code in p. If an error has already occurred when this function
-** is called, it is a no-op.
-*/
-void sqlite3Fts5BufferSet(
- int *pRc,
- Fts5Buffer *pBuf,
- int nData,
- const u8 *pData
-){
- pBuf->n = 0;
- sqlite3Fts5BufferAppendBlob(pRc, pBuf, nData, pData);
-}
-
-int sqlite3Fts5PoslistNext64(
- const u8 *a, int n, /* Buffer containing poslist */
- int *pi, /* IN/OUT: Offset within a[] */
- i64 *piOff /* IN/OUT: Current offset */
-){
- int i = *pi;
- if( i>=n ){
- /* EOF */
- *piOff = -1;
- return 1;
- }else{
- i64 iOff = *piOff;
- int iVal;
- fts5FastGetVarint32(a, i, iVal);
- if( iVal==1 ){
- fts5FastGetVarint32(a, i, iVal);
- iOff = ((i64)iVal) << 32;
- fts5FastGetVarint32(a, i, iVal);
- }
- *piOff = iOff + (iVal-2);
- *pi = i;
- return 0;
- }
-}
-
-
-/*
-** Advance the iterator object passed as the only argument. Return true
-** if the iterator reaches EOF, or false otherwise.
-*/
-int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader *pIter){
- if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos) ){
- pIter->bEof = 1;
- }
- return pIter->bEof;
-}
-
-int sqlite3Fts5PoslistReaderInit(
- const u8 *a, int n, /* Poslist buffer to iterate through */
- Fts5PoslistReader *pIter /* Iterator object to initialize */
-){
- memset(pIter, 0, sizeof(*pIter));
- pIter->a = a;
- pIter->n = n;
- sqlite3Fts5PoslistReaderNext(pIter);
- return pIter->bEof;
-}
-
-/*
-** Append position iPos to the position list being accumulated in buffer
-** pBuf, which must be already be large enough to hold the new data.
-** The previous position written to this list is *piPrev. *piPrev is set
-** to iPos before returning.
-*/
-void sqlite3Fts5PoslistSafeAppend(
- Fts5Buffer *pBuf,
- i64 *piPrev,
- i64 iPos
-){
- static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
- if( (iPos & colmask) != (*piPrev & colmask) ){
- pBuf->p[pBuf->n++] = 1;
- pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
- *piPrev = (iPos & colmask);
- }
- pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
- *piPrev = iPos;
-}
-
-int sqlite3Fts5PoslistWriterAppend(
- Fts5Buffer *pBuf,
- Fts5PoslistWriter *pWriter,
- i64 iPos
-){
- int rc = 0; /* Initialized only to suppress erroneous warning from Clang */
- if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc;
- sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos);
- return SQLITE_OK;
-}
-
-void *sqlite3Fts5MallocZero(int *pRc, int nByte){
- void *pRet = 0;
- if( *pRc==SQLITE_OK ){
- pRet = sqlite3_malloc(nByte);
- if( pRet==0 ){
- if( nByte>0 ) *pRc = SQLITE_NOMEM;
- }else{
- memset(pRet, 0, nByte);
- }
- }
- return pRet;
-}
-
-/*
-** Return a nul-terminated copy of the string indicated by pIn. If nIn
-** is non-negative, then it is the length of the string in bytes. Otherwise,
-** the length of the string is determined using strlen().
-**
-** It is the responsibility of the caller to eventually free the returned
-** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned.
-*/
-char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
- char *zRet = 0;
- if( *pRc==SQLITE_OK ){
- if( nIn<0 ){
- nIn = (int)strlen(pIn);
- }
- zRet = (char*)sqlite3_malloc(nIn+1);
- if( zRet ){
- memcpy(zRet, pIn, nIn);
- zRet[nIn] = '\0';
- }else{
- *pRc = SQLITE_NOMEM;
- }
- }
- return zRet;
-}
-
-
-/*
-** Return true if character 't' may be part of an FTS5 bareword, or false
-** otherwise. Characters that may be part of barewords:
-**
-** * All non-ASCII characters,
-** * The 52 upper and lower case ASCII characters, and
-** * The 10 integer ASCII characters.
-** * The underscore character "_" (0x5F).
-** * The unicode "subsitute" character (0x1A).
-*/
-int sqlite3Fts5IsBareword(char t){
- u8 aBareword[128] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 .. 0x0F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 0x10 .. 0x1F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 .. 0x2F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30 .. 0x3F */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 .. 0x4F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50 .. 0x5F */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 .. 0x6F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70 .. 0x7F */
- };
-
- return (t & 0x80) || aBareword[(int)t];
-}
-
-
-/*************************************************************************
-*/
-typedef struct Fts5TermsetEntry Fts5TermsetEntry;
-struct Fts5TermsetEntry {
- char *pTerm;
- int nTerm;
- int iIdx; /* Index (main or aPrefix[] entry) */
- Fts5TermsetEntry *pNext;
-};
-
-struct Fts5Termset {
- Fts5TermsetEntry *apHash[512];
-};
-
-int sqlite3Fts5TermsetNew(Fts5Termset **pp){
- int rc = SQLITE_OK;
- *pp = sqlite3Fts5MallocZero(&rc, sizeof(Fts5Termset));
- return rc;
-}
-
-int sqlite3Fts5TermsetAdd(
- Fts5Termset *p,
- int iIdx,
- const char *pTerm, int nTerm,
- int *pbPresent
-){
- int rc = SQLITE_OK;
- *pbPresent = 0;
- if( p ){
- int i;
- u32 hash = 13;
- Fts5TermsetEntry *pEntry;
-
- /* Calculate a hash value for this term. This is the same hash checksum
- ** used by the fts5_hash.c module. This is not important for correct
- ** operation of the module, but is necessary to ensure that some tests
- ** designed to produce hash table collisions really do work. */
- for(i=nTerm-1; i>=0; i--){
- hash = (hash << 3) ^ hash ^ pTerm[i];
- }
- hash = (hash << 3) ^ hash ^ iIdx;
- hash = hash % ArraySize(p->apHash);
-
- for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){
- if( pEntry->iIdx==iIdx
- && pEntry->nTerm==nTerm
- && memcmp(pEntry->pTerm, pTerm, nTerm)==0
- ){
- *pbPresent = 1;
- break;
- }
- }
-
- if( pEntry==0 ){
- pEntry = sqlite3Fts5MallocZero(&rc, sizeof(Fts5TermsetEntry) + nTerm);
- if( pEntry ){
- pEntry->pTerm = (char*)&pEntry[1];
- pEntry->nTerm = nTerm;
- pEntry->iIdx = iIdx;
- memcpy(pEntry->pTerm, pTerm, nTerm);
- pEntry->pNext = p->apHash[hash];
- p->apHash[hash] = pEntry;
- }
- }
- }
-
- return rc;
-}
-
-void sqlite3Fts5TermsetFree(Fts5Termset *p){
- if( p ){
- u32 i;
- for(i=0; i<ArraySize(p->apHash); i++){
- Fts5TermsetEntry *pEntry = p->apHash[i];
- while( pEntry ){
- Fts5TermsetEntry *pDel = pEntry;
- pEntry = pEntry->pNext;
- sqlite3_free(pDel);
- }
- }
- sqlite3_free(p);
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_config.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_config.c
deleted file mode 100644
index 17fc43e0116..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_config.c
+++ /dev/null
@@ -1,961 +0,0 @@
-/*
-** 2014 Jun 09
-**
-** 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 is an SQLite module implementing full-text search.
-*/
-
-
-#include "fts5Int.h"
-
-#define FTS5_DEFAULT_PAGE_SIZE 4050
-#define FTS5_DEFAULT_AUTOMERGE 4
-#define FTS5_DEFAULT_USERMERGE 4
-#define FTS5_DEFAULT_CRISISMERGE 16
-#define FTS5_DEFAULT_HASHSIZE (1024*1024)
-
-/* Maximum allowed page size */
-#define FTS5_MAX_PAGE_SIZE (128*1024)
-
-static int fts5_iswhitespace(char x){
- return (x==' ');
-}
-
-static int fts5_isopenquote(char x){
- return (x=='"' || x=='\'' || x=='[' || x=='`');
-}
-
-/*
-** Argument pIn points to a character that is part of a nul-terminated
-** string. Return a pointer to the first character following *pIn in
-** the string that is not a white-space character.
-*/
-static const char *fts5ConfigSkipWhitespace(const char *pIn){
- const char *p = pIn;
- if( p ){
- while( fts5_iswhitespace(*p) ){ p++; }
- }
- return p;
-}
-
-/*
-** Argument pIn points to a character that is part of a nul-terminated
-** string. Return a pointer to the first character following *pIn in
-** the string that is not a "bareword" character.
-*/
-static const char *fts5ConfigSkipBareword(const char *pIn){
- const char *p = pIn;
- while ( sqlite3Fts5IsBareword(*p) ) p++;
- if( p==pIn ) p = 0;
- return p;
-}
-
-static int fts5_isdigit(char a){
- return (a>='0' && a<='9');
-}
-
-
-
-static const char *fts5ConfigSkipLiteral(const char *pIn){
- const char *p = pIn;
- switch( *p ){
- case 'n': case 'N':
- if( sqlite3_strnicmp("null", p, 4)==0 ){
- p = &p[4];
- }else{
- p = 0;
- }
- break;
-
- case 'x': case 'X':
- p++;
- if( *p=='\'' ){
- p++;
- while( (*p>='a' && *p<='f')
- || (*p>='A' && *p<='F')
- || (*p>='0' && *p<='9')
- ){
- p++;
- }
- if( *p=='\'' && 0==((p-pIn)%2) ){
- p++;
- }else{
- p = 0;
- }
- }else{
- p = 0;
- }
- break;
-
- case '\'':
- p++;
- while( p ){
- if( *p=='\'' ){
- p++;
- if( *p!='\'' ) break;
- }
- p++;
- if( *p==0 ) p = 0;
- }
- break;
-
- default:
- /* maybe a number */
- if( *p=='+' || *p=='-' ) p++;
- while( fts5_isdigit(*p) ) p++;
-
- /* At this point, if the literal was an integer, the parse is
- ** finished. Or, if it is a floating point value, it may continue
- ** with either a decimal point or an 'E' character. */
- if( *p=='.' && fts5_isdigit(p[1]) ){
- p += 2;
- while( fts5_isdigit(*p) ) p++;
- }
- if( p==pIn ) p = 0;
-
- break;
- }
-
- return p;
-}
-
-/*
-** The first character of the string pointed to by argument z is guaranteed
-** to be an open-quote character (see function fts5_isopenquote()).
-**
-** This function searches for the corresponding close-quote character within
-** the string and, if found, dequotes the string in place and adds a new
-** nul-terminator byte.
-**
-** If the close-quote is found, the value returned is the byte offset of
-** the character immediately following it. Or, if the close-quote is not
-** found, -1 is returned. If -1 is returned, the buffer is left in an
-** undefined state.
-*/
-static int fts5Dequote(char *z){
- char q;
- int iIn = 1;
- int iOut = 0;
- q = z[0];
-
- /* Set stack variable q to the close-quote character */
- assert( q=='[' || q=='\'' || q=='"' || q=='`' );
- if( q=='[' ) q = ']';
-
- while( ALWAYS(z[iIn]) ){
- if( z[iIn]==q ){
- if( z[iIn+1]!=q ){
- /* Character iIn was the close quote. */
- iIn++;
- break;
- }else{
- /* Character iIn and iIn+1 form an escaped quote character. Skip
- ** the input cursor past both and copy a single quote character
- ** to the output buffer. */
- iIn += 2;
- z[iOut++] = q;
- }
- }else{
- z[iOut++] = z[iIn++];
- }
- }
-
- z[iOut] = '\0';
- return iIn;
-}
-
-/*
-** Convert an SQL-style quoted string into a normal string by removing
-** the quote characters. The conversion is done in-place. If the
-** input does not begin with a quote character, then this routine
-** is a no-op.
-**
-** Examples:
-**
-** "abc" becomes abc
-** 'xyz' becomes xyz
-** [pqr] becomes pqr
-** `mno` becomes mno
-*/
-void sqlite3Fts5Dequote(char *z){
- char quote; /* Quote character (if any ) */
-
- assert( 0==fts5_iswhitespace(z[0]) );
- quote = z[0];
- if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
- fts5Dequote(z);
- }
-}
-
-
-struct Fts5Enum {
- const char *zName;
- int eVal;
-};
-typedef struct Fts5Enum Fts5Enum;
-
-static int fts5ConfigSetEnum(
- const Fts5Enum *aEnum,
- const char *zEnum,
- int *peVal
-){
- int nEnum = (int)strlen(zEnum);
- int i;
- int iVal = -1;
-
- for(i=0; aEnum[i].zName; i++){
- if( sqlite3_strnicmp(aEnum[i].zName, zEnum, nEnum)==0 ){
- if( iVal>=0 ) return SQLITE_ERROR;
- iVal = aEnum[i].eVal;
- }
- }
-
- *peVal = iVal;
- return iVal<0 ? SQLITE_ERROR : SQLITE_OK;
-}
-
-/*
-** Parse a "special" CREATE VIRTUAL TABLE directive and update
-** configuration object pConfig as appropriate.
-**
-** If successful, object pConfig is updated and SQLITE_OK returned. If
-** an error occurs, an SQLite error code is returned and an error message
-** may be left in *pzErr. It is the responsibility of the caller to
-** eventually free any such error message using sqlite3_free().
-*/
-static int fts5ConfigParseSpecial(
- Fts5Global *pGlobal,
- Fts5Config *pConfig, /* Configuration object to update */
- const char *zCmd, /* Special command to parse */
- const char *zArg, /* Argument to parse */
- char **pzErr /* OUT: Error message */
-){
- int rc = SQLITE_OK;
- int nCmd = (int)strlen(zCmd);
- if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){
- const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES;
- const char *p;
- int bFirst = 1;
- if( pConfig->aPrefix==0 ){
- pConfig->aPrefix = sqlite3Fts5MallocZero(&rc, nByte);
- if( rc ) return rc;
- }
-
- p = zArg;
- while( 1 ){
- int nPre = 0;
-
- while( p[0]==' ' ) p++;
- if( bFirst==0 && p[0]==',' ){
- p++;
- while( p[0]==' ' ) p++;
- }else if( p[0]=='\0' ){
- break;
- }
- if( p[0]<'0' || p[0]>'9' ){
- *pzErr = sqlite3_mprintf("malformed prefix=... directive");
- rc = SQLITE_ERROR;
- break;
- }
-
- if( pConfig->nPrefix==FTS5_MAX_PREFIX_INDEXES ){
- *pzErr = sqlite3_mprintf(
- "too many prefix indexes (max %d)", FTS5_MAX_PREFIX_INDEXES
- );
- rc = SQLITE_ERROR;
- break;
- }
-
- while( p[0]>='0' && p[0]<='9' && nPre<1000 ){
- nPre = nPre*10 + (p[0] - '0');
- p++;
- }
-
- if( nPre<=0 || nPre>=1000 ){
- *pzErr = sqlite3_mprintf("prefix length out of range (max 999)");
- rc = SQLITE_ERROR;
- break;
- }
-
- pConfig->aPrefix[pConfig->nPrefix] = nPre;
- pConfig->nPrefix++;
- bFirst = 0;
- }
- assert( pConfig->nPrefix<=FTS5_MAX_PREFIX_INDEXES );
- return rc;
- }
-
- if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
- const char *p = (const char*)zArg;
- int nArg = (int)strlen(zArg) + 1;
- char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
- char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
- char *pSpace = pDel;
-
- if( azArg && pSpace ){
- if( pConfig->pTok ){
- *pzErr = sqlite3_mprintf("multiple tokenize=... directives");
- rc = SQLITE_ERROR;
- }else{
- for(nArg=0; p && *p; nArg++){
- const char *p2 = fts5ConfigSkipWhitespace(p);
- if( *p2=='\'' ){
- p = fts5ConfigSkipLiteral(p2);
- }else{
- p = fts5ConfigSkipBareword(p2);
- }
- if( p ){
- memcpy(pSpace, p2, p-p2);
- azArg[nArg] = pSpace;
- sqlite3Fts5Dequote(pSpace);
- pSpace += (p - p2) + 1;
- p = fts5ConfigSkipWhitespace(p);
- }
- }
- if( p==0 ){
- *pzErr = sqlite3_mprintf("parse error in tokenize directive");
- rc = SQLITE_ERROR;
- }else{
- rc = sqlite3Fts5GetTokenizer(pGlobal,
- (const char**)azArg, nArg, &pConfig->pTok, &pConfig->pTokApi,
- pzErr
- );
- }
- }
- }
-
- sqlite3_free(azArg);
- sqlite3_free(pDel);
- return rc;
- }
-
- if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){
- if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
- *pzErr = sqlite3_mprintf("multiple content=... directives");
- rc = SQLITE_ERROR;
- }else{
- if( zArg[0] ){
- pConfig->eContent = FTS5_CONTENT_EXTERNAL;
- pConfig->zContent = sqlite3Fts5Mprintf(&rc, "%Q.%Q", pConfig->zDb,zArg);
- }else{
- pConfig->eContent = FTS5_CONTENT_NONE;
- }
- }
- return rc;
- }
-
- if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){
- if( pConfig->zContentRowid ){
- *pzErr = sqlite3_mprintf("multiple content_rowid=... directives");
- rc = SQLITE_ERROR;
- }else{
- pConfig->zContentRowid = sqlite3Fts5Strndup(&rc, zArg, -1);
- }
- return rc;
- }
-
- if( sqlite3_strnicmp("columnsize", zCmd, nCmd)==0 ){
- if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
- *pzErr = sqlite3_mprintf("malformed columnsize=... directive");
- rc = SQLITE_ERROR;
- }else{
- pConfig->bColumnsize = (zArg[0]=='1');
- }
- return rc;
- }
-
- if( sqlite3_strnicmp("detail", zCmd, nCmd)==0 ){
- const Fts5Enum aDetail[] = {
- { "none", FTS5_DETAIL_NONE },
- { "full", FTS5_DETAIL_FULL },
- { "columns", FTS5_DETAIL_COLUMNS },
- { 0, 0 }
- };
-
- if( (rc = fts5ConfigSetEnum(aDetail, zArg, &pConfig->eDetail)) ){
- *pzErr = sqlite3_mprintf("malformed detail=... directive");
- }
- return rc;
- }
-
- *pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
- return SQLITE_ERROR;
-}
-
-/*
-** Allocate an instance of the default tokenizer ("simple") at
-** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
-** code if an error occurs.
-*/
-static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
- assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
- return sqlite3Fts5GetTokenizer(
- pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0
- );
-}
-
-/*
-** Gobble up the first bareword or quoted word from the input buffer zIn.
-** Return a pointer to the character immediately following the last in
-** the gobbled word if successful, or a NULL pointer otherwise (failed
-** to find close-quote character).
-**
-** Before returning, set pzOut to point to a new buffer containing a
-** nul-terminated, dequoted copy of the gobbled word. If the word was
-** quoted, *pbQuoted is also set to 1 before returning.
-**
-** If *pRc is other than SQLITE_OK when this function is called, it is
-** a no-op (NULL is returned). Otherwise, if an OOM occurs within this
-** function, *pRc is set to SQLITE_NOMEM before returning. *pRc is *not*
-** set if a parse error (failed to find close quote) occurs.
-*/
-static const char *fts5ConfigGobbleWord(
- int *pRc, /* IN/OUT: Error code */
- const char *zIn, /* Buffer to gobble string/bareword from */
- char **pzOut, /* OUT: malloc'd buffer containing str/bw */
- int *pbQuoted /* OUT: Set to true if dequoting required */
-){
- const char *zRet = 0;
-
- int nIn = (int)strlen(zIn);
- char *zOut = sqlite3_malloc(nIn+1);
-
- assert( *pRc==SQLITE_OK );
- *pbQuoted = 0;
- *pzOut = 0;
-
- if( zOut==0 ){
- *pRc = SQLITE_NOMEM;
- }else{
- memcpy(zOut, zIn, nIn+1);
- if( fts5_isopenquote(zOut[0]) ){
- int ii = fts5Dequote(zOut);
- zRet = &zIn[ii];
- *pbQuoted = 1;
- }else{
- zRet = fts5ConfigSkipBareword(zIn);
- if( zRet ){
- zOut[zRet-zIn] = '\0';
- }
- }
- }
-
- if( zRet==0 ){
- sqlite3_free(zOut);
- }else{
- *pzOut = zOut;
- }
-
- return zRet;
-}
-
-static int fts5ConfigParseColumn(
- Fts5Config *p,
- char *zCol,
- char *zArg,
- char **pzErr
-){
- int rc = SQLITE_OK;
- if( 0==sqlite3_stricmp(zCol, FTS5_RANK_NAME)
- || 0==sqlite3_stricmp(zCol, FTS5_ROWID_NAME)
- ){
- *pzErr = sqlite3_mprintf("reserved fts5 column name: %s", zCol);
- rc = SQLITE_ERROR;
- }else if( zArg ){
- if( 0==sqlite3_stricmp(zArg, "unindexed") ){
- p->abUnindexed[p->nCol] = 1;
- }else{
- *pzErr = sqlite3_mprintf("unrecognized column option: %s", zArg);
- rc = SQLITE_ERROR;
- }
- }
-
- p->azCol[p->nCol++] = zCol;
- return rc;
-}
-
-/*
-** Populate the Fts5Config.zContentExprlist string.
-*/
-static int fts5ConfigMakeExprlist(Fts5Config *p){
- int i;
- int rc = SQLITE_OK;
- Fts5Buffer buf = {0, 0, 0};
-
- sqlite3Fts5BufferAppendPrintf(&rc, &buf, "T.%Q", p->zContentRowid);
- if( p->eContent!=FTS5_CONTENT_NONE ){
- for(i=0; i<p->nCol; i++){
- if( p->eContent==FTS5_CONTENT_EXTERNAL ){
- sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]);
- }else{
- sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i);
- }
- }
- }
-
- assert( p->zContentExprlist==0 );
- p->zContentExprlist = (char*)buf.p;
- return rc;
-}
-
-/*
-** Arguments nArg/azArg contain the string arguments passed to the xCreate
-** or xConnect method of the virtual table. This function attempts to
-** allocate an instance of Fts5Config containing the results of parsing
-** those arguments.
-**
-** If successful, SQLITE_OK is returned and *ppOut is set to point to the
-** new Fts5Config object. If an error occurs, an SQLite error code is
-** returned, *ppOut is set to NULL and an error message may be left in
-** *pzErr. It is the responsibility of the caller to eventually free any
-** such error message using sqlite3_free().
-*/
-int sqlite3Fts5ConfigParse(
- Fts5Global *pGlobal,
- sqlite3 *db,
- int nArg, /* Number of arguments */
- const char **azArg, /* Array of nArg CREATE VIRTUAL TABLE args */
- Fts5Config **ppOut, /* OUT: Results of parse */
- char **pzErr /* OUT: Error message */
-){
- int rc = SQLITE_OK; /* Return code */
- Fts5Config *pRet; /* New object to return */
- int i;
- int nByte;
-
- *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
- if( pRet==0 ) return SQLITE_NOMEM;
- memset(pRet, 0, sizeof(Fts5Config));
- pRet->db = db;
- pRet->iCookie = -1;
-
- nByte = nArg * (sizeof(char*) + sizeof(u8));
- pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
- pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
- pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
- pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
- pRet->bColumnsize = 1;
- pRet->eDetail = FTS5_DETAIL_FULL;
-#ifdef SQLITE_DEBUG
- pRet->bPrefixIndex = 1;
-#endif
- if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){
- *pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName);
- rc = SQLITE_ERROR;
- }
-
- for(i=3; rc==SQLITE_OK && i<nArg; i++){
- const char *zOrig = azArg[i];
- const char *z;
- char *zOne = 0;
- char *zTwo = 0;
- int bOption = 0;
- int bMustBeCol = 0;
-
- z = fts5ConfigGobbleWord(&rc, zOrig, &zOne, &bMustBeCol);
- z = fts5ConfigSkipWhitespace(z);
- if( z && *z=='=' ){
- bOption = 1;
- z++;
- if( bMustBeCol ) z = 0;
- }
- z = fts5ConfigSkipWhitespace(z);
- if( z && z[0] ){
- int bDummy;
- z = fts5ConfigGobbleWord(&rc, z, &zTwo, &bDummy);
- if( z && z[0] ) z = 0;
- }
-
- if( rc==SQLITE_OK ){
- if( z==0 ){
- *pzErr = sqlite3_mprintf("parse error in \"%s\"", zOrig);
- rc = SQLITE_ERROR;
- }else{
- if( bOption ){
- rc = fts5ConfigParseSpecial(pGlobal, pRet, zOne, zTwo?zTwo:"", pzErr);
- }else{
- rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
- zOne = 0;
- }
- }
- }
-
- sqlite3_free(zOne);
- sqlite3_free(zTwo);
- }
-
- /* If a tokenizer= option was successfully parsed, the tokenizer has
- ** already been allocated. Otherwise, allocate an instance of the default
- ** tokenizer (unicode61) now. */
- if( rc==SQLITE_OK && pRet->pTok==0 ){
- rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
- }
-
- /* If no zContent option was specified, fill in the default values. */
- if( rc==SQLITE_OK && pRet->zContent==0 ){
- const char *zTail = 0;
- assert( pRet->eContent==FTS5_CONTENT_NORMAL
- || pRet->eContent==FTS5_CONTENT_NONE
- );
- if( pRet->eContent==FTS5_CONTENT_NORMAL ){
- zTail = "content";
- }else if( pRet->bColumnsize ){
- zTail = "docsize";
- }
-
- if( zTail ){
- pRet->zContent = sqlite3Fts5Mprintf(
- &rc, "%Q.'%q_%s'", pRet->zDb, pRet->zName, zTail
- );
- }
- }
-
- if( rc==SQLITE_OK && pRet->zContentRowid==0 ){
- pRet->zContentRowid = sqlite3Fts5Strndup(&rc, "rowid", -1);
- }
-
- /* Formulate the zContentExprlist text */
- if( rc==SQLITE_OK ){
- rc = fts5ConfigMakeExprlist(pRet);
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3Fts5ConfigFree(pRet);
- *ppOut = 0;
- }
- return rc;
-}
-
-/*
-** Free the configuration object passed as the only argument.
-*/
-void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
- if( pConfig ){
- int i;
- if( pConfig->pTok ){
- pConfig->pTokApi->xDelete(pConfig->pTok);
- }
- sqlite3_free(pConfig->zDb);
- sqlite3_free(pConfig->zName);
- for(i=0; i<pConfig->nCol; i++){
- sqlite3_free(pConfig->azCol[i]);
- }
- sqlite3_free(pConfig->azCol);
- sqlite3_free(pConfig->aPrefix);
- sqlite3_free(pConfig->zRank);
- sqlite3_free(pConfig->zRankArgs);
- sqlite3_free(pConfig->zContent);
- sqlite3_free(pConfig->zContentRowid);
- sqlite3_free(pConfig->zContentExprlist);
- sqlite3_free(pConfig);
- }
-}
-
-/*
-** Call sqlite3_declare_vtab() based on the contents of the configuration
-** object passed as the only argument. Return SQLITE_OK if successful, or
-** an SQLite error code if an error occurs.
-*/
-int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig){
- int i;
- int rc = SQLITE_OK;
- char *zSql;
-
- zSql = sqlite3Fts5Mprintf(&rc, "CREATE TABLE x(");
- for(i=0; zSql && i<pConfig->nCol; i++){
- const char *zSep = (i==0?"":", ");
- zSql = sqlite3Fts5Mprintf(&rc, "%z%s%Q", zSql, zSep, pConfig->azCol[i]);
- }
- zSql = sqlite3Fts5Mprintf(&rc, "%z, %Q HIDDEN, %s HIDDEN)",
- zSql, pConfig->zName, FTS5_RANK_NAME
- );
-
- assert( zSql || rc==SQLITE_NOMEM );
- if( zSql ){
- rc = sqlite3_declare_vtab(pConfig->db, zSql);
- sqlite3_free(zSql);
- }
-
- return rc;
-}
-
-/*
-** Tokenize the text passed via the second and third arguments.
-**
-** The callback is invoked once for each token in the input text. The
-** arguments passed to it are, in order:
-**
-** void *pCtx // Copy of 4th argument to sqlite3Fts5Tokenize()
-** const char *pToken // Pointer to buffer containing token
-** int nToken // Size of token in bytes
-** int iStart // Byte offset of start of token within input text
-** int iEnd // Byte offset of end of token within input text
-** int iPos // Position of token in input (first token is 0)
-**
-** If the callback returns a non-zero value the tokenization is abandoned
-** and no further callbacks are issued.
-**
-** This function returns SQLITE_OK if successful or an SQLite error code
-** if an error occurs. If the tokenization was abandoned early because
-** the callback returned SQLITE_DONE, this is not an error and this function
-** still returns SQLITE_OK. Or, if the tokenization was abandoned early
-** because the callback returned another non-zero value, it is assumed
-** to be an SQLite error code and returned to the caller.
-*/
-int sqlite3Fts5Tokenize(
- Fts5Config *pConfig, /* FTS5 Configuration object */
- int flags, /* FTS5_TOKENIZE_* flags */
- const char *pText, int nText, /* Text to tokenize */
- void *pCtx, /* Context passed to xToken() */
- int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
-){
- if( pText==0 ) return SQLITE_OK;
- return pConfig->pTokApi->xTokenize(
- pConfig->pTok, pCtx, flags, pText, nText, xToken
- );
-}
-
-/*
-** Argument pIn points to the first character in what is expected to be
-** a comma-separated list of SQL literals followed by a ')' character.
-** If it actually is this, return a pointer to the ')'. Otherwise, return
-** NULL to indicate a parse error.
-*/
-static const char *fts5ConfigSkipArgs(const char *pIn){
- const char *p = pIn;
-
- while( 1 ){
- p = fts5ConfigSkipWhitespace(p);
- p = fts5ConfigSkipLiteral(p);
- p = fts5ConfigSkipWhitespace(p);
- if( p==0 || *p==')' ) break;
- if( *p!=',' ){
- p = 0;
- break;
- }
- p++;
- }
-
- return p;
-}
-
-/*
-** Parameter zIn contains a rank() function specification. The format of
-** this is:
-**
-** + Bareword (function name)
-** + Open parenthesis - "("
-** + Zero or more SQL literals in a comma separated list
-** + Close parenthesis - ")"
-*/
-int sqlite3Fts5ConfigParseRank(
- const char *zIn, /* Input string */
- char **pzRank, /* OUT: Rank function name */
- char **pzRankArgs /* OUT: Rank function arguments */
-){
- const char *p = zIn;
- const char *pRank;
- char *zRank = 0;
- char *zRankArgs = 0;
- int rc = SQLITE_OK;
-
- *pzRank = 0;
- *pzRankArgs = 0;
-
- if( p==0 ){
- rc = SQLITE_ERROR;
- }else{
- p = fts5ConfigSkipWhitespace(p);
- pRank = p;
- p = fts5ConfigSkipBareword(p);
-
- if( p ){
- zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank);
- if( zRank ) memcpy(zRank, pRank, p-pRank);
- }else{
- rc = SQLITE_ERROR;
- }
-
- if( rc==SQLITE_OK ){
- p = fts5ConfigSkipWhitespace(p);
- if( *p!='(' ) rc = SQLITE_ERROR;
- p++;
- }
- if( rc==SQLITE_OK ){
- const char *pArgs;
- p = fts5ConfigSkipWhitespace(p);
- pArgs = p;
- if( *p!=')' ){
- p = fts5ConfigSkipArgs(p);
- if( p==0 ){
- rc = SQLITE_ERROR;
- }else{
- zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs);
- if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs);
- }
- }
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_free(zRank);
- assert( zRankArgs==0 );
- }else{
- *pzRank = zRank;
- *pzRankArgs = zRankArgs;
- }
- return rc;
-}
-
-int sqlite3Fts5ConfigSetValue(
- Fts5Config *pConfig,
- const char *zKey,
- sqlite3_value *pVal,
- int *pbBadkey
-){
- int rc = SQLITE_OK;
-
- if( 0==sqlite3_stricmp(zKey, "pgsz") ){
- int pgsz = 0;
- if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
- pgsz = sqlite3_value_int(pVal);
- }
- if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){
- *pbBadkey = 1;
- }else{
- pConfig->pgsz = pgsz;
- }
- }
-
- else if( 0==sqlite3_stricmp(zKey, "hashsize") ){
- int nHashSize = -1;
- if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
- nHashSize = sqlite3_value_int(pVal);
- }
- if( nHashSize<=0 ){
- *pbBadkey = 1;
- }else{
- pConfig->nHashSize = nHashSize;
- }
- }
-
- else if( 0==sqlite3_stricmp(zKey, "automerge") ){
- int nAutomerge = -1;
- if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
- nAutomerge = sqlite3_value_int(pVal);
- }
- if( nAutomerge<0 || nAutomerge>64 ){
- *pbBadkey = 1;
- }else{
- if( nAutomerge==1 ) nAutomerge = FTS5_DEFAULT_AUTOMERGE;
- pConfig->nAutomerge = nAutomerge;
- }
- }
-
- else if( 0==sqlite3_stricmp(zKey, "usermerge") ){
- int nUsermerge = -1;
- if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
- nUsermerge = sqlite3_value_int(pVal);
- }
- if( nUsermerge<2 || nUsermerge>16 ){
- *pbBadkey = 1;
- }else{
- pConfig->nUsermerge = nUsermerge;
- }
- }
-
- else if( 0==sqlite3_stricmp(zKey, "crisismerge") ){
- int nCrisisMerge = -1;
- if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
- nCrisisMerge = sqlite3_value_int(pVal);
- }
- if( nCrisisMerge<0 ){
- *pbBadkey = 1;
- }else{
- if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
- pConfig->nCrisisMerge = nCrisisMerge;
- }
- }
-
- else if( 0==sqlite3_stricmp(zKey, "rank") ){
- const char *zIn = (const char*)sqlite3_value_text(pVal);
- char *zRank;
- char *zRankArgs;
- rc = sqlite3Fts5ConfigParseRank(zIn, &zRank, &zRankArgs);
- if( rc==SQLITE_OK ){
- sqlite3_free(pConfig->zRank);
- sqlite3_free(pConfig->zRankArgs);
- pConfig->zRank = zRank;
- pConfig->zRankArgs = zRankArgs;
- }else if( rc==SQLITE_ERROR ){
- rc = SQLITE_OK;
- *pbBadkey = 1;
- }
- }else{
- *pbBadkey = 1;
- }
- return rc;
-}
-
-/*
-** Load the contents of the %_config table into memory.
-*/
-int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
- const char *zSelect = "SELECT k, v FROM %Q.'%q_config'";
- char *zSql;
- sqlite3_stmt *p = 0;
- int rc = SQLITE_OK;
- int iVersion = 0;
-
- /* Set default values */
- pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE;
- pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE;
- pConfig->nUsermerge = FTS5_DEFAULT_USERMERGE;
- pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
- pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE;
-
- zSql = sqlite3Fts5Mprintf(&rc, zSelect, pConfig->zDb, pConfig->zName);
- if( zSql ){
- rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p, 0);
- sqlite3_free(zSql);
- }
-
- assert( rc==SQLITE_OK || p==0 );
- if( rc==SQLITE_OK ){
- while( SQLITE_ROW==sqlite3_step(p) ){
- const char *zK = (const char*)sqlite3_column_text(p, 0);
- sqlite3_value *pVal = sqlite3_column_value(p, 1);
- if( 0==sqlite3_stricmp(zK, "version") ){
- iVersion = sqlite3_value_int(pVal);
- }else{
- int bDummy = 0;
- sqlite3Fts5ConfigSetValue(pConfig, zK, pVal, &bDummy);
- }
- }
- rc = sqlite3_finalize(p);
- }
-
- if( rc==SQLITE_OK && iVersion!=FTS5_CURRENT_VERSION ){
- rc = SQLITE_ERROR;
- if( pConfig->pzErrmsg ){
- assert( 0==*pConfig->pzErrmsg );
- *pConfig->pzErrmsg = sqlite3_mprintf(
- "invalid fts5 file format (found %d, expected %d) - run 'rebuild'",
- iVersion, FTS5_CURRENT_VERSION
- );
- }
- }
-
- if( rc==SQLITE_OK ){
- pConfig->iCookie = iCookie;
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_expr.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_expr.c
deleted file mode 100644
index 03c3d703ddf..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_expr.c
+++ /dev/null
@@ -1,2842 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-**
-*/
-
-
-
-#include "fts5Int.h"
-#include "fts5parse.h"
-
-/*
-** All token types in the generated fts5parse.h file are greater than 0.
-*/
-#define FTS5_EOF 0
-
-#define FTS5_LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
-
-typedef struct Fts5ExprTerm Fts5ExprTerm;
-
-/*
-** Functions generated by lemon from fts5parse.y.
-*/
-void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(u64));
-void sqlite3Fts5ParserFree(void*, void (*freeProc)(void*));
-void sqlite3Fts5Parser(void*, int, Fts5Token, Fts5Parse*);
-#ifndef NDEBUG
-#include <stdio.h>
-void sqlite3Fts5ParserTrace(FILE*, char*);
-#endif
-
-
-struct Fts5Expr {
- Fts5Index *pIndex;
- Fts5Config *pConfig;
- Fts5ExprNode *pRoot;
- int bDesc; /* Iterate in descending rowid order */
- int nPhrase; /* Number of phrases in expression */
- Fts5ExprPhrase **apExprPhrase; /* Pointers to phrase objects */
-};
-
-/*
-** eType:
-** Expression node type. Always one of:
-**
-** FTS5_AND (nChild, apChild valid)
-** FTS5_OR (nChild, apChild valid)
-** FTS5_NOT (nChild, apChild valid)
-** FTS5_STRING (pNear valid)
-** FTS5_TERM (pNear valid)
-*/
-struct Fts5ExprNode {
- int eType; /* Node type */
- int bEof; /* True at EOF */
- int bNomatch; /* True if entry is not a match */
-
- /* Next method for this node. */
- int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64);
-
- i64 iRowid; /* Current rowid */
- Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */
-
- /* Child nodes. For a NOT node, this array always contains 2 entries. For
- ** AND or OR nodes, it contains 2 or more entries. */
- int nChild; /* Number of child nodes */
- Fts5ExprNode *apChild[1]; /* Array of child nodes */
-};
-
-#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
-
-/*
-** Invoke the xNext method of an Fts5ExprNode object. This macro should be
-** used as if it has the same signature as the xNext() methods themselves.
-*/
-#define fts5ExprNodeNext(a,b,c,d) (b)->xNext((a), (b), (c), (d))
-
-/*
-** An instance of the following structure represents a single search term
-** or term prefix.
-*/
-struct Fts5ExprTerm {
- u8 bPrefix; /* True for a prefix term */
- u8 bFirst; /* True if token must be first in column */
- char *zTerm; /* nul-terminated term */
- Fts5IndexIter *pIter; /* Iterator for this term */
- Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */
-};
-
-/*
-** A phrase. One or more terms that must appear in a contiguous sequence
-** within a document for it to match.
-*/
-struct Fts5ExprPhrase {
- Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
- Fts5Buffer poslist; /* Current position list */
- int nTerm; /* Number of entries in aTerm[] */
- Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
-};
-
-/*
-** One or more phrases that must appear within a certain token distance of
-** each other within each matching document.
-*/
-struct Fts5ExprNearset {
- int nNear; /* NEAR parameter */
- Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
- int nPhrase; /* Number of entries in aPhrase[] array */
- Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
-};
-
-
-/*
-** Parse context.
-*/
-struct Fts5Parse {
- Fts5Config *pConfig;
- char *zErr;
- int rc;
- int nPhrase; /* Size of apPhrase array */
- Fts5ExprPhrase **apPhrase; /* Array of all phrases */
- Fts5ExprNode *pExpr; /* Result of a successful parse */
-};
-
-void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
- va_list ap;
- va_start(ap, zFmt);
- if( pParse->rc==SQLITE_OK ){
- pParse->zErr = sqlite3_vmprintf(zFmt, ap);
- pParse->rc = SQLITE_ERROR;
- }
- va_end(ap);
-}
-
-static int fts5ExprIsspace(char t){
- return t==' ' || t=='\t' || t=='\n' || t=='\r';
-}
-
-/*
-** Read the first token from the nul-terminated string at *pz.
-*/
-static int fts5ExprGetToken(
- Fts5Parse *pParse,
- const char **pz, /* IN/OUT: Pointer into buffer */
- Fts5Token *pToken
-){
- const char *z = *pz;
- int tok;
-
- /* Skip past any whitespace */
- while( fts5ExprIsspace(*z) ) z++;
-
- pToken->p = z;
- pToken->n = 1;
- switch( *z ){
- case '(': tok = FTS5_LP; break;
- case ')': tok = FTS5_RP; break;
- case '{': tok = FTS5_LCP; break;
- case '}': tok = FTS5_RCP; break;
- case ':': tok = FTS5_COLON; break;
- case ',': tok = FTS5_COMMA; break;
- case '+': tok = FTS5_PLUS; break;
- case '*': tok = FTS5_STAR; break;
- case '-': tok = FTS5_MINUS; break;
- case '^': tok = FTS5_CARET; break;
- case '\0': tok = FTS5_EOF; break;
-
- case '"': {
- const char *z2;
- tok = FTS5_STRING;
-
- for(z2=&z[1]; 1; z2++){
- if( z2[0]=='"' ){
- z2++;
- if( z2[0]!='"' ) break;
- }
- if( z2[0]=='\0' ){
- sqlite3Fts5ParseError(pParse, "unterminated string");
- return FTS5_EOF;
- }
- }
- pToken->n = (z2 - z);
- break;
- }
-
- default: {
- const char *z2;
- if( sqlite3Fts5IsBareword(z[0])==0 ){
- sqlite3Fts5ParseError(pParse, "fts5: syntax error near \"%.1s\"", z);
- return FTS5_EOF;
- }
- tok = FTS5_STRING;
- for(z2=&z[1]; sqlite3Fts5IsBareword(*z2); z2++);
- pToken->n = (z2 - z);
- if( pToken->n==2 && memcmp(pToken->p, "OR", 2)==0 ) tok = FTS5_OR;
- if( pToken->n==3 && memcmp(pToken->p, "NOT", 3)==0 ) tok = FTS5_NOT;
- if( pToken->n==3 && memcmp(pToken->p, "AND", 3)==0 ) tok = FTS5_AND;
- break;
- }
- }
-
- *pz = &pToken->p[pToken->n];
- return tok;
-}
-
-static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc((int)t); }
-static void fts5ParseFree(void *p){ sqlite3_free(p); }
-
-int sqlite3Fts5ExprNew(
- Fts5Config *pConfig, /* FTS5 Configuration */
- int iCol,
- const char *zExpr, /* Expression text */
- Fts5Expr **ppNew,
- char **pzErr
-){
- Fts5Parse sParse;
- Fts5Token token;
- const char *z = zExpr;
- int t; /* Next token type */
- void *pEngine;
- Fts5Expr *pNew;
-
- *ppNew = 0;
- *pzErr = 0;
- memset(&sParse, 0, sizeof(sParse));
- pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
- if( pEngine==0 ){ return SQLITE_NOMEM; }
- sParse.pConfig = pConfig;
-
- do {
- t = fts5ExprGetToken(&sParse, &z, &token);
- sqlite3Fts5Parser(pEngine, t, token, &sParse);
- }while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
- sqlite3Fts5ParserFree(pEngine, fts5ParseFree);
-
- /* If the LHS of the MATCH expression was a user column, apply the
- ** implicit column-filter. */
- if( iCol<pConfig->nCol && sParse.pExpr && sParse.rc==SQLITE_OK ){
- int n = sizeof(Fts5Colset);
- Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
- if( pColset ){
- pColset->nCol = 1;
- pColset->aiCol[0] = iCol;
- sqlite3Fts5ParseSetColset(&sParse, sParse.pExpr, pColset);
- }
- }
-
- assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 );
- if( sParse.rc==SQLITE_OK ){
- *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
- if( pNew==0 ){
- sParse.rc = SQLITE_NOMEM;
- sqlite3Fts5ParseNodeFree(sParse.pExpr);
- }else{
- if( !sParse.pExpr ){
- const int nByte = sizeof(Fts5ExprNode);
- pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte);
- if( pNew->pRoot ){
- pNew->pRoot->bEof = 1;
- }
- }else{
- pNew->pRoot = sParse.pExpr;
- }
- pNew->pIndex = 0;
- pNew->pConfig = pConfig;
- pNew->apExprPhrase = sParse.apPhrase;
- pNew->nPhrase = sParse.nPhrase;
- sParse.apPhrase = 0;
- }
- }else{
- sqlite3Fts5ParseNodeFree(sParse.pExpr);
- }
-
- sqlite3_free(sParse.apPhrase);
- *pzErr = sParse.zErr;
- return sParse.rc;
-}
-
-/*
-** Free the expression node object passed as the only argument.
-*/
-void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
- if( p ){
- int i;
- for(i=0; i<p->nChild; i++){
- sqlite3Fts5ParseNodeFree(p->apChild[i]);
- }
- sqlite3Fts5ParseNearsetFree(p->pNear);
- sqlite3_free(p);
- }
-}
-
-/*
-** Free the expression object passed as the only argument.
-*/
-void sqlite3Fts5ExprFree(Fts5Expr *p){
- if( p ){
- sqlite3Fts5ParseNodeFree(p->pRoot);
- sqlite3_free(p->apExprPhrase);
- sqlite3_free(p);
- }
-}
-
-/*
-** Argument pTerm must be a synonym iterator. Return the current rowid
-** that it points to.
-*/
-static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){
- i64 iRet = 0;
- int bRetValid = 0;
- Fts5ExprTerm *p;
-
- assert( pTerm->pSynonym );
- assert( bDesc==0 || bDesc==1 );
- for(p=pTerm; p; p=p->pSynonym){
- if( 0==sqlite3Fts5IterEof(p->pIter) ){
- i64 iRowid = p->pIter->iRowid;
- if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){
- iRet = iRowid;
- bRetValid = 1;
- }
- }
- }
-
- if( pbEof && bRetValid==0 ) *pbEof = 1;
- return iRet;
-}
-
-/*
-** Argument pTerm must be a synonym iterator.
-*/
-static int fts5ExprSynonymList(
- Fts5ExprTerm *pTerm,
- i64 iRowid,
- Fts5Buffer *pBuf, /* Use this buffer for space if required */
- u8 **pa, int *pn
-){
- Fts5PoslistReader aStatic[4];
- Fts5PoslistReader *aIter = aStatic;
- int nIter = 0;
- int nAlloc = 4;
- int rc = SQLITE_OK;
- Fts5ExprTerm *p;
-
- assert( pTerm->pSynonym );
- for(p=pTerm; p; p=p->pSynonym){
- Fts5IndexIter *pIter = p->pIter;
- if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){
- if( pIter->nData==0 ) continue;
- if( nIter==nAlloc ){
- int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
- Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
- if( aNew==0 ){
- rc = SQLITE_NOMEM;
- goto synonym_poslist_out;
- }
- memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter);
- nAlloc = nAlloc*2;
- if( aIter!=aStatic ) sqlite3_free(aIter);
- aIter = aNew;
- }
- sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &aIter[nIter]);
- assert( aIter[nIter].bEof==0 );
- nIter++;
- }
- }
-
- if( nIter==1 ){
- *pa = (u8*)aIter[0].a;
- *pn = aIter[0].n;
- }else{
- Fts5PoslistWriter writer = {0};
- i64 iPrev = -1;
- fts5BufferZero(pBuf);
- while( 1 ){
- int i;
- i64 iMin = FTS5_LARGEST_INT64;
- for(i=0; i<nIter; i++){
- if( aIter[i].bEof==0 ){
- if( aIter[i].iPos==iPrev ){
- if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) continue;
- }
- if( aIter[i].iPos<iMin ){
- iMin = aIter[i].iPos;
- }
- }
- }
- if( iMin==FTS5_LARGEST_INT64 || rc!=SQLITE_OK ) break;
- rc = sqlite3Fts5PoslistWriterAppend(pBuf, &writer, iMin);
- iPrev = iMin;
- }
- if( rc==SQLITE_OK ){
- *pa = pBuf->p;
- *pn = pBuf->n;
- }
- }
-
- synonym_poslist_out:
- if( aIter!=aStatic ) sqlite3_free(aIter);
- return rc;
-}
-
-
-/*
-** All individual term iterators in pPhrase are guaranteed to be valid and
-** pointing to the same rowid when this function is called. This function
-** checks if the current rowid really is a match, and if so populates
-** the pPhrase->poslist buffer accordingly. Output parameter *pbMatch
-** is set to true if this is really a match, or false otherwise.
-**
-** SQLITE_OK is returned if an error occurs, or an SQLite error code
-** otherwise. It is not considered an error code if the current rowid is
-** not a match.
-*/
-static int fts5ExprPhraseIsMatch(
- Fts5ExprNode *pNode, /* Node pPhrase belongs to */
- Fts5ExprPhrase *pPhrase, /* Phrase object to initialize */
- int *pbMatch /* OUT: Set to true if really a match */
-){
- Fts5PoslistWriter writer = {0};
- Fts5PoslistReader aStatic[4];
- Fts5PoslistReader *aIter = aStatic;
- int i;
- int rc = SQLITE_OK;
- int bFirst = pPhrase->aTerm[0].bFirst;
-
- fts5BufferZero(&pPhrase->poslist);
-
- /* If the aStatic[] array is not large enough, allocate a large array
- ** using sqlite3_malloc(). This approach could be improved upon. */
- if( pPhrase->nTerm>ArraySize(aStatic) ){
- int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
- aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
- if( !aIter ) return SQLITE_NOMEM;
- }
- memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);
-
- /* Initialize a term iterator for each term in the phrase */
- for(i=0; i<pPhrase->nTerm; i++){
- Fts5ExprTerm *pTerm = &pPhrase->aTerm[i];
- int n = 0;
- int bFlag = 0;
- u8 *a = 0;
- if( pTerm->pSynonym ){
- Fts5Buffer buf = {0, 0, 0};
- rc = fts5ExprSynonymList(pTerm, pNode->iRowid, &buf, &a, &n);
- if( rc ){
- sqlite3_free(a);
- goto ismatch_out;
- }
- if( a==buf.p ) bFlag = 1;
- }else{
- a = (u8*)pTerm->pIter->pData;
- n = pTerm->pIter->nData;
- }
- sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
- aIter[i].bFlag = (u8)bFlag;
- if( aIter[i].bEof ) goto ismatch_out;
- }
-
- while( 1 ){
- int bMatch;
- i64 iPos = aIter[0].iPos;
- do {
- bMatch = 1;
- for(i=0; i<pPhrase->nTerm; i++){
- Fts5PoslistReader *pPos = &aIter[i];
- i64 iAdj = iPos + i;
- if( pPos->iPos!=iAdj ){
- bMatch = 0;
- while( pPos->iPos<iAdj ){
- if( sqlite3Fts5PoslistReaderNext(pPos) ) goto ismatch_out;
- }
- if( pPos->iPos>iAdj ) iPos = pPos->iPos-i;
- }
- }
- }while( bMatch==0 );
-
- /* Append position iPos to the output */
- if( bFirst==0 || FTS5_POS2OFFSET(iPos)==0 ){
- rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos);
- if( rc!=SQLITE_OK ) goto ismatch_out;
- }
-
- for(i=0; i<pPhrase->nTerm; i++){
- if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out;
- }
- }
-
- ismatch_out:
- *pbMatch = (pPhrase->poslist.n>0);
- for(i=0; i<pPhrase->nTerm; i++){
- if( aIter[i].bFlag ) sqlite3_free((u8*)aIter[i].a);
- }
- if( aIter!=aStatic ) sqlite3_free(aIter);
- return rc;
-}
-
-typedef struct Fts5LookaheadReader Fts5LookaheadReader;
-struct Fts5LookaheadReader {
- const u8 *a; /* Buffer containing position list */
- int n; /* Size of buffer a[] in bytes */
- int i; /* Current offset in position list */
- i64 iPos; /* Current position */
- i64 iLookahead; /* Next position */
-};
-
-#define FTS5_LOOKAHEAD_EOF (((i64)1) << 62)
-
-static int fts5LookaheadReaderNext(Fts5LookaheadReader *p){
- p->iPos = p->iLookahead;
- if( sqlite3Fts5PoslistNext64(p->a, p->n, &p->i, &p->iLookahead) ){
- p->iLookahead = FTS5_LOOKAHEAD_EOF;
- }
- return (p->iPos==FTS5_LOOKAHEAD_EOF);
-}
-
-static int fts5LookaheadReaderInit(
- const u8 *a, int n, /* Buffer to read position list from */
- Fts5LookaheadReader *p /* Iterator object to initialize */
-){
- memset(p, 0, sizeof(Fts5LookaheadReader));
- p->a = a;
- p->n = n;
- fts5LookaheadReaderNext(p);
- return fts5LookaheadReaderNext(p);
-}
-
-typedef struct Fts5NearTrimmer Fts5NearTrimmer;
-struct Fts5NearTrimmer {
- Fts5LookaheadReader reader; /* Input iterator */
- Fts5PoslistWriter writer; /* Writer context */
- Fts5Buffer *pOut; /* Output poslist */
-};
-
-/*
-** The near-set object passed as the first argument contains more than
-** one phrase. All phrases currently point to the same row. The
-** Fts5ExprPhrase.poslist buffers are populated accordingly. This function
-** tests if the current row contains instances of each phrase sufficiently
-** close together to meet the NEAR constraint. Non-zero is returned if it
-** does, or zero otherwise.
-**
-** If in/out parameter (*pRc) is set to other than SQLITE_OK when this
-** function is called, it is a no-op. Or, if an error (e.g. SQLITE_NOMEM)
-** occurs within this function (*pRc) is set accordingly before returning.
-** The return value is undefined in both these cases.
-**
-** If no error occurs and non-zero (a match) is returned, the position-list
-** of each phrase object is edited to contain only those entries that
-** meet the constraint before returning.
-*/
-static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
- Fts5NearTrimmer aStatic[4];
- Fts5NearTrimmer *a = aStatic;
- Fts5ExprPhrase **apPhrase = pNear->apPhrase;
-
- int i;
- int rc = *pRc;
- int bMatch;
-
- assert( pNear->nPhrase>1 );
-
- /* If the aStatic[] array is not large enough, allocate a large array
- ** using sqlite3_malloc(). This approach could be improved upon. */
- if( pNear->nPhrase>ArraySize(aStatic) ){
- int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
- a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
- }else{
- memset(aStatic, 0, sizeof(aStatic));
- }
- if( rc!=SQLITE_OK ){
- *pRc = rc;
- return 0;
- }
-
- /* Initialize a lookahead iterator for each phrase. After passing the
- ** buffer and buffer size to the lookaside-reader init function, zero
- ** the phrase poslist buffer. The new poslist for the phrase (containing
- ** the same entries as the original with some entries removed on account
- ** of the NEAR constraint) is written over the original even as it is
- ** being read. This is safe as the entries for the new poslist are a
- ** subset of the old, so it is not possible for data yet to be read to
- ** be overwritten. */
- for(i=0; i<pNear->nPhrase; i++){
- Fts5Buffer *pPoslist = &apPhrase[i]->poslist;
- fts5LookaheadReaderInit(pPoslist->p, pPoslist->n, &a[i].reader);
- pPoslist->n = 0;
- a[i].pOut = pPoslist;
- }
-
- while( 1 ){
- int iAdv;
- i64 iMin;
- i64 iMax;
-
- /* This block advances the phrase iterators until they point to a set of
- ** entries that together comprise a match. */
- iMax = a[0].reader.iPos;
- do {
- bMatch = 1;
- for(i=0; i<pNear->nPhrase; i++){
- Fts5LookaheadReader *pPos = &a[i].reader;
- iMin = iMax - pNear->apPhrase[i]->nTerm - pNear->nNear;
- if( pPos->iPos<iMin || pPos->iPos>iMax ){
- bMatch = 0;
- while( pPos->iPos<iMin ){
- if( fts5LookaheadReaderNext(pPos) ) goto ismatch_out;
- }
- if( pPos->iPos>iMax ) iMax = pPos->iPos;
- }
- }
- }while( bMatch==0 );
-
- /* Add an entry to each output position list */
- for(i=0; i<pNear->nPhrase; i++){
- i64 iPos = a[i].reader.iPos;
- Fts5PoslistWriter *pWriter = &a[i].writer;
- if( a[i].pOut->n==0 || iPos!=pWriter->iPrev ){
- sqlite3Fts5PoslistWriterAppend(a[i].pOut, pWriter, iPos);
- }
- }
-
- iAdv = 0;
- iMin = a[0].reader.iLookahead;
- for(i=0; i<pNear->nPhrase; i++){
- if( a[i].reader.iLookahead < iMin ){
- iMin = a[i].reader.iLookahead;
- iAdv = i;
- }
- }
- if( fts5LookaheadReaderNext(&a[iAdv].reader) ) goto ismatch_out;
- }
-
- ismatch_out: {
- int bRet = a[0].pOut->n>0;
- *pRc = rc;
- if( a!=aStatic ) sqlite3_free(a);
- return bRet;
- }
-}
-
-/*
-** Advance iterator pIter until it points to a value equal to or laster
-** than the initial value of *piLast. If this means the iterator points
-** to a value laster than *piLast, update *piLast to the new lastest value.
-**
-** If the iterator reaches EOF, set *pbEof to true before returning. If
-** an error occurs, set *pRc to an error code. If either *pbEof or *pRc
-** are set, return a non-zero value. Otherwise, return zero.
-*/
-static int fts5ExprAdvanceto(
- Fts5IndexIter *pIter, /* Iterator to advance */
- int bDesc, /* True if iterator is "rowid DESC" */
- i64 *piLast, /* IN/OUT: Lastest rowid seen so far */
- int *pRc, /* OUT: Error code */
- int *pbEof /* OUT: Set to true if EOF */
-){
- i64 iLast = *piLast;
- i64 iRowid;
-
- iRowid = pIter->iRowid;
- if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){
- int rc = sqlite3Fts5IterNextFrom(pIter, iLast);
- if( rc || sqlite3Fts5IterEof(pIter) ){
- *pRc = rc;
- *pbEof = 1;
- return 1;
- }
- iRowid = pIter->iRowid;
- assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) );
- }
- *piLast = iRowid;
-
- return 0;
-}
-
-static int fts5ExprSynonymAdvanceto(
- Fts5ExprTerm *pTerm, /* Term iterator to advance */
- int bDesc, /* True if iterator is "rowid DESC" */
- i64 *piLast, /* IN/OUT: Lastest rowid seen so far */
- int *pRc /* OUT: Error code */
-){
- int rc = SQLITE_OK;
- i64 iLast = *piLast;
- Fts5ExprTerm *p;
- int bEof = 0;
-
- for(p=pTerm; rc==SQLITE_OK && p; p=p->pSynonym){
- if( sqlite3Fts5IterEof(p->pIter)==0 ){
- i64 iRowid = p->pIter->iRowid;
- if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){
- rc = sqlite3Fts5IterNextFrom(p->pIter, iLast);
- }
- }
- }
-
- if( rc!=SQLITE_OK ){
- *pRc = rc;
- bEof = 1;
- }else{
- *piLast = fts5ExprSynonymRowid(pTerm, bDesc, &bEof);
- }
- return bEof;
-}
-
-
-static int fts5ExprNearTest(
- int *pRc,
- Fts5Expr *pExpr, /* Expression that pNear is a part of */
- Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */
-){
- Fts5ExprNearset *pNear = pNode->pNear;
- int rc = *pRc;
-
- if( pExpr->pConfig->eDetail!=FTS5_DETAIL_FULL ){
- Fts5ExprTerm *pTerm;
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
- pPhrase->poslist.n = 0;
- for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
- Fts5IndexIter *pIter = pTerm->pIter;
- if( sqlite3Fts5IterEof(pIter)==0 ){
- if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){
- pPhrase->poslist.n = 1;
- }
- }
- }
- return pPhrase->poslist.n;
- }else{
- int i;
-
- /* Check that each phrase in the nearset matches the current row.
- ** Populate the pPhrase->poslist buffers at the same time. If any
- ** phrase is not a match, break out of the loop early. */
- for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
- if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym
- || pNear->pColset || pPhrase->aTerm[0].bFirst
- ){
- int bMatch = 0;
- rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch);
- if( bMatch==0 ) break;
- }else{
- Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
- fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData);
- }
- }
-
- *pRc = rc;
- if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){
- return 1;
- }
- return 0;
- }
-}
-
-
-/*
-** Initialize all term iterators in the pNear object. If any term is found
-** to match no documents at all, return immediately without initializing any
-** further iterators.
-**
-** If an error occurs, return an SQLite error code. Otherwise, return
-** SQLITE_OK. It is not considered an error if some term matches zero
-** documents.
-*/
-static int fts5ExprNearInitAll(
- Fts5Expr *pExpr,
- Fts5ExprNode *pNode
-){
- Fts5ExprNearset *pNear = pNode->pNear;
- int i;
-
- assert( pNode->bNomatch==0 );
- for(i=0; i<pNear->nPhrase; i++){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
- if( pPhrase->nTerm==0 ){
- pNode->bEof = 1;
- return SQLITE_OK;
- }else{
- int j;
- for(j=0; j<pPhrase->nTerm; j++){
- Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
- Fts5ExprTerm *p;
- int bHit = 0;
-
- for(p=pTerm; p; p=p->pSynonym){
- int rc;
- if( p->pIter ){
- sqlite3Fts5IterClose(p->pIter);
- p->pIter = 0;
- }
- rc = sqlite3Fts5IndexQuery(
- pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm),
- (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
- (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
- pNear->pColset,
- &p->pIter
- );
- assert( (rc==SQLITE_OK)==(p->pIter!=0) );
- if( rc!=SQLITE_OK ) return rc;
- if( 0==sqlite3Fts5IterEof(p->pIter) ){
- bHit = 1;
- }
- }
-
- if( bHit==0 ){
- pNode->bEof = 1;
- return SQLITE_OK;
- }
- }
- }
- }
-
- pNode->bEof = 0;
- return SQLITE_OK;
-}
-
-/*
-** If pExpr is an ASC iterator, this function returns a value with the
-** same sign as:
-**
-** (iLhs - iRhs)
-**
-** Otherwise, if this is a DESC iterator, the opposite is returned:
-**
-** (iRhs - iLhs)
-*/
-static int fts5RowidCmp(
- Fts5Expr *pExpr,
- i64 iLhs,
- i64 iRhs
-){
- assert( pExpr->bDesc==0 || pExpr->bDesc==1 );
- if( pExpr->bDesc==0 ){
- if( iLhs<iRhs ) return -1;
- return (iLhs > iRhs);
- }else{
- if( iLhs>iRhs ) return -1;
- return (iLhs < iRhs);
- }
-}
-
-static void fts5ExprSetEof(Fts5ExprNode *pNode){
- int i;
- pNode->bEof = 1;
- pNode->bNomatch = 0;
- for(i=0; i<pNode->nChild; i++){
- fts5ExprSetEof(pNode->apChild[i]);
- }
-}
-
-static void fts5ExprNodeZeroPoslist(Fts5ExprNode *pNode){
- if( pNode->eType==FTS5_STRING || pNode->eType==FTS5_TERM ){
- Fts5ExprNearset *pNear = pNode->pNear;
- int i;
- for(i=0; i<pNear->nPhrase; i++){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
- pPhrase->poslist.n = 0;
- }
- }else{
- int i;
- for(i=0; i<pNode->nChild; i++){
- fts5ExprNodeZeroPoslist(pNode->apChild[i]);
- }
- }
-}
-
-
-
-/*
-** Compare the values currently indicated by the two nodes as follows:
-**
-** res = (*p1) - (*p2)
-**
-** Nodes that point to values that come later in the iteration order are
-** considered to be larger. Nodes at EOF are the largest of all.
-**
-** This means that if the iteration order is ASC, then numerically larger
-** rowids are considered larger. Or if it is the default DESC, numerically
-** smaller rowids are larger.
-*/
-static int fts5NodeCompare(
- Fts5Expr *pExpr,
- Fts5ExprNode *p1,
- Fts5ExprNode *p2
-){
- if( p2->bEof ) return -1;
- if( p1->bEof ) return +1;
- return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid);
-}
-
-/*
-** All individual term iterators in pNear are guaranteed to be valid when
-** this function is called. This function checks if all term iterators
-** point to the same rowid, and if not, advances them until they do.
-** If an EOF is reached before this happens, *pbEof is set to true before
-** returning.
-**
-** SQLITE_OK is returned if an error occurs, or an SQLite error code
-** otherwise. It is not considered an error code if an iterator reaches
-** EOF.
-*/
-static int fts5ExprNodeTest_STRING(
- Fts5Expr *pExpr, /* Expression pPhrase belongs to */
- Fts5ExprNode *pNode
-){
- Fts5ExprNearset *pNear = pNode->pNear;
- Fts5ExprPhrase *pLeft = pNear->apPhrase[0];
- int rc = SQLITE_OK;
- i64 iLast; /* Lastest rowid any iterator points to */
- int i, j; /* Phrase and token index, respectively */
- int bMatch; /* True if all terms are at the same rowid */
- const int bDesc = pExpr->bDesc;
-
- /* Check that this node should not be FTS5_TERM */
- assert( pNear->nPhrase>1
- || pNear->apPhrase[0]->nTerm>1
- || pNear->apPhrase[0]->aTerm[0].pSynonym
- || pNear->apPhrase[0]->aTerm[0].bFirst
- );
-
- /* Initialize iLast, the "lastest" rowid any iterator points to. If the
- ** iterator skips through rowids in the default ascending order, this means
- ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it
- ** means the minimum rowid. */
- if( pLeft->aTerm[0].pSynonym ){
- iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0);
- }else{
- iLast = pLeft->aTerm[0].pIter->iRowid;
- }
-
- do {
- bMatch = 1;
- for(i=0; i<pNear->nPhrase; i++){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
- for(j=0; j<pPhrase->nTerm; j++){
- Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
- if( pTerm->pSynonym ){
- i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0);
- if( iRowid==iLast ) continue;
- bMatch = 0;
- if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){
- pNode->bNomatch = 0;
- pNode->bEof = 1;
- return rc;
- }
- }else{
- Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
- if( pIter->iRowid==iLast || pIter->bEof ) continue;
- bMatch = 0;
- if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){
- return rc;
- }
- }
- }
- }
- }while( bMatch==0 );
-
- pNode->iRowid = iLast;
- pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK);
- assert( pNode->bEof==0 || pNode->bNomatch==0 );
-
- return rc;
-}
-
-/*
-** Advance the first term iterator in the first phrase of pNear. Set output
-** variable *pbEof to true if it reaches EOF or if an error occurs.
-**
-** Return SQLITE_OK if successful, or an SQLite error code if an error
-** occurs.
-*/
-static int fts5ExprNodeNext_STRING(
- Fts5Expr *pExpr, /* Expression pPhrase belongs to */
- Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */
- int bFromValid,
- i64 iFrom
-){
- Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0];
- int rc = SQLITE_OK;
-
- pNode->bNomatch = 0;
- if( pTerm->pSynonym ){
- int bEof = 1;
- Fts5ExprTerm *p;
-
- /* Find the firstest rowid any synonym points to. */
- i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0);
-
- /* Advance each iterator that currently points to iRowid. Or, if iFrom
- ** is valid - each iterator that points to a rowid before iFrom. */
- for(p=pTerm; p; p=p->pSynonym){
- if( sqlite3Fts5IterEof(p->pIter)==0 ){
- i64 ii = p->pIter->iRowid;
- if( ii==iRowid
- || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc)
- ){
- if( bFromValid ){
- rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom);
- }else{
- rc = sqlite3Fts5IterNext(p->pIter);
- }
- if( rc!=SQLITE_OK ) break;
- if( sqlite3Fts5IterEof(p->pIter)==0 ){
- bEof = 0;
- }
- }else{
- bEof = 0;
- }
- }
- }
-
- /* Set the EOF flag if either all synonym iterators are at EOF or an
- ** error has occurred. */
- pNode->bEof = (rc || bEof);
- }else{
- Fts5IndexIter *pIter = pTerm->pIter;
-
- assert( Fts5NodeIsString(pNode) );
- if( bFromValid ){
- rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
- }else{
- rc = sqlite3Fts5IterNext(pIter);
- }
-
- pNode->bEof = (rc || sqlite3Fts5IterEof(pIter));
- }
-
- if( pNode->bEof==0 ){
- assert( rc==SQLITE_OK );
- rc = fts5ExprNodeTest_STRING(pExpr, pNode);
- }
-
- return rc;
-}
-
-
-static int fts5ExprNodeTest_TERM(
- Fts5Expr *pExpr, /* Expression that pNear is a part of */
- Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */
-){
- /* As this "NEAR" object is actually a single phrase that consists
- ** of a single term only, grab pointers into the poslist managed by the
- ** fts5_index.c iterator object. This is much faster than synthesizing
- ** a new poslist the way we have to for more complicated phrase or NEAR
- ** expressions. */
- Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0];
- Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
-
- assert( pNode->eType==FTS5_TERM );
- assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 );
- assert( pPhrase->aTerm[0].pSynonym==0 );
-
- pPhrase->poslist.n = pIter->nData;
- if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){
- pPhrase->poslist.p = (u8*)pIter->pData;
- }
- pNode->iRowid = pIter->iRowid;
- pNode->bNomatch = (pPhrase->poslist.n==0);
- return SQLITE_OK;
-}
-
-/*
-** xNext() method for a node of type FTS5_TERM.
-*/
-static int fts5ExprNodeNext_TERM(
- Fts5Expr *pExpr,
- Fts5ExprNode *pNode,
- int bFromValid,
- i64 iFrom
-){
- int rc;
- Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter;
-
- assert( pNode->bEof==0 );
- if( bFromValid ){
- rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
- }else{
- rc = sqlite3Fts5IterNext(pIter);
- }
- if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){
- rc = fts5ExprNodeTest_TERM(pExpr, pNode);
- }else{
- pNode->bEof = 1;
- pNode->bNomatch = 0;
- }
- return rc;
-}
-
-static void fts5ExprNodeTest_OR(
- Fts5Expr *pExpr, /* Expression of which pNode is a part */
- Fts5ExprNode *pNode /* Expression node to test */
-){
- Fts5ExprNode *pNext = pNode->apChild[0];
- int i;
-
- for(i=1; i<pNode->nChild; i++){
- Fts5ExprNode *pChild = pNode->apChild[i];
- int cmp = fts5NodeCompare(pExpr, pNext, pChild);
- if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){
- pNext = pChild;
- }
- }
- pNode->iRowid = pNext->iRowid;
- pNode->bEof = pNext->bEof;
- pNode->bNomatch = pNext->bNomatch;
-}
-
-static int fts5ExprNodeNext_OR(
- Fts5Expr *pExpr,
- Fts5ExprNode *pNode,
- int bFromValid,
- i64 iFrom
-){
- int i;
- i64 iLast = pNode->iRowid;
-
- for(i=0; i<pNode->nChild; i++){
- Fts5ExprNode *p1 = pNode->apChild[i];
- assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 );
- if( p1->bEof==0 ){
- if( (p1->iRowid==iLast)
- || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
- ){
- int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
- if( rc!=SQLITE_OK ){
- pNode->bNomatch = 0;
- return rc;
- }
- }
- }
- }
-
- fts5ExprNodeTest_OR(pExpr, pNode);
- return SQLITE_OK;
-}
-
-/*
-** Argument pNode is an FTS5_AND node.
-*/
-static int fts5ExprNodeTest_AND(
- Fts5Expr *pExpr, /* Expression pPhrase belongs to */
- Fts5ExprNode *pAnd /* FTS5_AND node to advance */
-){
- int iChild;
- i64 iLast = pAnd->iRowid;
- int rc = SQLITE_OK;
- int bMatch;
-
- assert( pAnd->bEof==0 );
- do {
- pAnd->bNomatch = 0;
- bMatch = 1;
- for(iChild=0; iChild<pAnd->nChild; iChild++){
- Fts5ExprNode *pChild = pAnd->apChild[iChild];
- int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid);
- if( cmp>0 ){
- /* Advance pChild until it points to iLast or laster */
- rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
- if( rc!=SQLITE_OK ){
- pAnd->bNomatch = 0;
- return rc;
- }
- }
-
- /* If the child node is now at EOF, so is the parent AND node. Otherwise,
- ** the child node is guaranteed to have advanced at least as far as
- ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the
- ** new lastest rowid seen so far. */
- assert( pChild->bEof || fts5RowidCmp(pExpr, iLast, pChild->iRowid)<=0 );
- if( pChild->bEof ){
- fts5ExprSetEof(pAnd);
- bMatch = 1;
- break;
- }else if( iLast!=pChild->iRowid ){
- bMatch = 0;
- iLast = pChild->iRowid;
- }
-
- if( pChild->bNomatch ){
- pAnd->bNomatch = 1;
- }
- }
- }while( bMatch==0 );
-
- if( pAnd->bNomatch && pAnd!=pExpr->pRoot ){
- fts5ExprNodeZeroPoslist(pAnd);
- }
- pAnd->iRowid = iLast;
- return SQLITE_OK;
-}
-
-static int fts5ExprNodeNext_AND(
- Fts5Expr *pExpr,
- Fts5ExprNode *pNode,
- int bFromValid,
- i64 iFrom
-){
- int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
- if( rc==SQLITE_OK ){
- rc = fts5ExprNodeTest_AND(pExpr, pNode);
- }else{
- pNode->bNomatch = 0;
- }
- return rc;
-}
-
-static int fts5ExprNodeTest_NOT(
- Fts5Expr *pExpr, /* Expression pPhrase belongs to */
- Fts5ExprNode *pNode /* FTS5_NOT node to advance */
-){
- int rc = SQLITE_OK;
- Fts5ExprNode *p1 = pNode->apChild[0];
- Fts5ExprNode *p2 = pNode->apChild[1];
- assert( pNode->nChild==2 );
-
- while( rc==SQLITE_OK && p1->bEof==0 ){
- int cmp = fts5NodeCompare(pExpr, p1, p2);
- if( cmp>0 ){
- rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid);
- cmp = fts5NodeCompare(pExpr, p1, p2);
- }
- assert( rc!=SQLITE_OK || cmp<=0 );
- if( cmp || p2->bNomatch ) break;
- rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
- }
- pNode->bEof = p1->bEof;
- pNode->bNomatch = p1->bNomatch;
- pNode->iRowid = p1->iRowid;
- if( p1->bEof ){
- fts5ExprNodeZeroPoslist(p2);
- }
- return rc;
-}
-
-static int fts5ExprNodeNext_NOT(
- Fts5Expr *pExpr,
- Fts5ExprNode *pNode,
- int bFromValid,
- i64 iFrom
-){
- int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
- if( rc==SQLITE_OK ){
- rc = fts5ExprNodeTest_NOT(pExpr, pNode);
- }
- if( rc!=SQLITE_OK ){
- pNode->bNomatch = 0;
- }
- return rc;
-}
-
-/*
-** If pNode currently points to a match, this function returns SQLITE_OK
-** without modifying it. Otherwise, pNode is advanced until it does point
-** to a match or EOF is reached.
-*/
-static int fts5ExprNodeTest(
- Fts5Expr *pExpr, /* Expression of which pNode is a part */
- Fts5ExprNode *pNode /* Expression node to test */
-){
- int rc = SQLITE_OK;
- if( pNode->bEof==0 ){
- switch( pNode->eType ){
-
- case FTS5_STRING: {
- rc = fts5ExprNodeTest_STRING(pExpr, pNode);
- break;
- }
-
- case FTS5_TERM: {
- rc = fts5ExprNodeTest_TERM(pExpr, pNode);
- break;
- }
-
- case FTS5_AND: {
- rc = fts5ExprNodeTest_AND(pExpr, pNode);
- break;
- }
-
- case FTS5_OR: {
- fts5ExprNodeTest_OR(pExpr, pNode);
- break;
- }
-
- default: assert( pNode->eType==FTS5_NOT ); {
- rc = fts5ExprNodeTest_NOT(pExpr, pNode);
- break;
- }
- }
- }
- return rc;
-}
-
-
-/*
-** Set node pNode, which is part of expression pExpr, to point to the first
-** match. If there are no matches, set the Node.bEof flag to indicate EOF.
-**
-** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
-** It is not an error if there are no matches.
-*/
-static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
- int rc = SQLITE_OK;
- pNode->bEof = 0;
- pNode->bNomatch = 0;
-
- if( Fts5NodeIsString(pNode) ){
- /* Initialize all term iterators in the NEAR object. */
- rc = fts5ExprNearInitAll(pExpr, pNode);
- }else if( pNode->xNext==0 ){
- pNode->bEof = 1;
- }else{
- int i;
- int nEof = 0;
- for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){
- Fts5ExprNode *pChild = pNode->apChild[i];
- rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]);
- assert( pChild->bEof==0 || pChild->bEof==1 );
- nEof += pChild->bEof;
- }
- pNode->iRowid = pNode->apChild[0]->iRowid;
-
- switch( pNode->eType ){
- case FTS5_AND:
- if( nEof>0 ) fts5ExprSetEof(pNode);
- break;
-
- case FTS5_OR:
- if( pNode->nChild==nEof ) fts5ExprSetEof(pNode);
- break;
-
- default:
- assert( pNode->eType==FTS5_NOT );
- pNode->bEof = pNode->apChild[0]->bEof;
- break;
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = fts5ExprNodeTest(pExpr, pNode);
- }
- return rc;
-}
-
-
-/*
-** Begin iterating through the set of documents in index pIdx matched by
-** the MATCH expression passed as the first argument. If the "bDesc"
-** parameter is passed a non-zero value, iteration is in descending rowid
-** order. Or, if it is zero, in ascending order.
-**
-** If iterating in ascending rowid order (bDesc==0), the first document
-** visited is that with the smallest rowid that is larger than or equal
-** to parameter iFirst. Or, if iterating in ascending order (bDesc==1),
-** then the first document visited must have a rowid smaller than or
-** equal to iFirst.
-**
-** Return SQLITE_OK if successful, or an SQLite error code otherwise. It
-** is not considered an error if the query does not match any documents.
-*/
-int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
- Fts5ExprNode *pRoot = p->pRoot;
- int rc; /* Return code */
-
- p->pIndex = pIdx;
- p->bDesc = bDesc;
- rc = fts5ExprNodeFirst(p, pRoot);
-
- /* If not at EOF but the current rowid occurs earlier than iFirst in
- ** the iteration order, move to document iFirst or later. */
- if( rc==SQLITE_OK
- && 0==pRoot->bEof
- && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0
- ){
- rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
- }
-
- /* If the iterator is not at a real match, skip forward until it is. */
- while( pRoot->bNomatch ){
- assert( pRoot->bEof==0 && rc==SQLITE_OK );
- rc = fts5ExprNodeNext(p, pRoot, 0, 0);
- }
- return rc;
-}
-
-/*
-** Move to the next document
-**
-** Return SQLITE_OK if successful, or an SQLite error code otherwise. It
-** is not considered an error if the query does not match any documents.
-*/
-int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){
- int rc;
- Fts5ExprNode *pRoot = p->pRoot;
- assert( pRoot->bEof==0 && pRoot->bNomatch==0 );
- do {
- rc = fts5ExprNodeNext(p, pRoot, 0, 0);
- assert( pRoot->bNomatch==0 || (rc==SQLITE_OK && pRoot->bEof==0) );
- }while( pRoot->bNomatch );
- if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){
- pRoot->bEof = 1;
- }
- return rc;
-}
-
-int sqlite3Fts5ExprEof(Fts5Expr *p){
- return p->pRoot->bEof;
-}
-
-i64 sqlite3Fts5ExprRowid(Fts5Expr *p){
- return p->pRoot->iRowid;
-}
-
-static int fts5ParseStringFromToken(Fts5Token *pToken, char **pz){
- int rc = SQLITE_OK;
- *pz = sqlite3Fts5Strndup(&rc, pToken->p, pToken->n);
- return rc;
-}
-
-/*
-** Free the phrase object passed as the only argument.
-*/
-static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){
- if( pPhrase ){
- int i;
- for(i=0; i<pPhrase->nTerm; i++){
- Fts5ExprTerm *pSyn;
- Fts5ExprTerm *pNext;
- Fts5ExprTerm *pTerm = &pPhrase->aTerm[i];
- sqlite3_free(pTerm->zTerm);
- sqlite3Fts5IterClose(pTerm->pIter);
- for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){
- pNext = pSyn->pSynonym;
- sqlite3Fts5IterClose(pSyn->pIter);
- fts5BufferFree((Fts5Buffer*)&pSyn[1]);
- sqlite3_free(pSyn);
- }
- }
- if( pPhrase->poslist.nSpace>0 ) fts5BufferFree(&pPhrase->poslist);
- sqlite3_free(pPhrase);
- }
-}
-
-/*
-** Set the "bFirst" flag on the first token of the phrase passed as the
-** only argument.
-*/
-void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase *pPhrase){
- if( pPhrase && pPhrase->nTerm ){
- pPhrase->aTerm[0].bFirst = 1;
- }
-}
-
-/*
-** If argument pNear is NULL, then a new Fts5ExprNearset object is allocated
-** and populated with pPhrase. Or, if pNear is not NULL, phrase pPhrase is
-** appended to it and the results returned.
-**
-** If an OOM error occurs, both the pNear and pPhrase objects are freed and
-** NULL returned.
-*/
-Fts5ExprNearset *sqlite3Fts5ParseNearset(
- Fts5Parse *pParse, /* Parse context */
- Fts5ExprNearset *pNear, /* Existing nearset, or NULL */
- Fts5ExprPhrase *pPhrase /* Recently parsed phrase */
-){
- const int SZALLOC = 8;
- Fts5ExprNearset *pRet = 0;
-
- if( pParse->rc==SQLITE_OK ){
- if( pPhrase==0 ){
- return pNear;
- }
- if( pNear==0 ){
- int nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
- pRet = sqlite3_malloc(nByte);
- if( pRet==0 ){
- pParse->rc = SQLITE_NOMEM;
- }else{
- memset(pRet, 0, nByte);
- }
- }else if( (pNear->nPhrase % SZALLOC)==0 ){
- int nNew = pNear->nPhrase + SZALLOC;
- int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
-
- pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte);
- if( pRet==0 ){
- pParse->rc = SQLITE_NOMEM;
- }
- }else{
- pRet = pNear;
- }
- }
-
- if( pRet==0 ){
- assert( pParse->rc!=SQLITE_OK );
- sqlite3Fts5ParseNearsetFree(pNear);
- sqlite3Fts5ParsePhraseFree(pPhrase);
- }else{
- if( pRet->nPhrase>0 ){
- Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
- assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
- if( pPhrase->nTerm==0 ){
- fts5ExprPhraseFree(pPhrase);
- pRet->nPhrase--;
- pParse->nPhrase--;
- pPhrase = pLast;
- }else if( pLast->nTerm==0 ){
- fts5ExprPhraseFree(pLast);
- pParse->apPhrase[pParse->nPhrase-2] = pPhrase;
- pParse->nPhrase--;
- pRet->nPhrase--;
- }
- }
- pRet->apPhrase[pRet->nPhrase++] = pPhrase;
- }
- return pRet;
-}
-
-typedef struct TokenCtx TokenCtx;
-struct TokenCtx {
- Fts5ExprPhrase *pPhrase;
- int rc;
-};
-
-/*
-** Callback for tokenizing terms used by ParseTerm().
-*/
-static int fts5ParseTokenize(
- void *pContext, /* Pointer to Fts5InsertCtx object */
- int tflags, /* Mask of FTS5_TOKEN_* flags */
- const char *pToken, /* Buffer containing token */
- int nToken, /* Size of token in bytes */
- int iUnused1, /* Start offset of token */
- int iUnused2 /* End offset of token */
-){
- int rc = SQLITE_OK;
- const int SZALLOC = 8;
- TokenCtx *pCtx = (TokenCtx*)pContext;
- Fts5ExprPhrase *pPhrase = pCtx->pPhrase;
-
- UNUSED_PARAM2(iUnused1, iUnused2);
-
- /* If an error has already occurred, this is a no-op */
- if( pCtx->rc!=SQLITE_OK ) return pCtx->rc;
- if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
-
- if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){
- Fts5ExprTerm *pSyn;
- int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
- pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
- if( pSyn==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pSyn, 0, nByte);
- pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
- memcpy(pSyn->zTerm, pToken, nToken);
- pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
- pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
- }
- }else{
- Fts5ExprTerm *pTerm;
- if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){
- Fts5ExprPhrase *pNew;
- int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
-
- pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase,
- sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
- );
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
- pCtx->pPhrase = pPhrase = pNew;
- pNew->nTerm = nNew - SZALLOC;
- }
- }
-
- if( rc==SQLITE_OK ){
- pTerm = &pPhrase->aTerm[pPhrase->nTerm++];
- memset(pTerm, 0, sizeof(Fts5ExprTerm));
- pTerm->zTerm = sqlite3Fts5Strndup(&rc, pToken, nToken);
- }
- }
-
- pCtx->rc = rc;
- return rc;
-}
-
-
-/*
-** Free the phrase object passed as the only argument.
-*/
-void sqlite3Fts5ParsePhraseFree(Fts5ExprPhrase *pPhrase){
- fts5ExprPhraseFree(pPhrase);
-}
-
-/*
-** Free the phrase object passed as the second argument.
-*/
-void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset *pNear){
- if( pNear ){
- int i;
- for(i=0; i<pNear->nPhrase; i++){
- fts5ExprPhraseFree(pNear->apPhrase[i]);
- }
- sqlite3_free(pNear->pColset);
- sqlite3_free(pNear);
- }
-}
-
-void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
- assert( pParse->pExpr==0 );
- pParse->pExpr = p;
-}
-
-/*
-** This function is called by the parser to process a string token. The
-** string may or may not be quoted. In any case it is tokenized and a
-** phrase object consisting of all tokens returned.
-*/
-Fts5ExprPhrase *sqlite3Fts5ParseTerm(
- Fts5Parse *pParse, /* Parse context */
- Fts5ExprPhrase *pAppend, /* Phrase to append to */
- Fts5Token *pToken, /* String to tokenize */
- int bPrefix /* True if there is a trailing "*" */
-){
- Fts5Config *pConfig = pParse->pConfig;
- TokenCtx sCtx; /* Context object passed to callback */
- int rc; /* Tokenize return code */
- char *z = 0;
-
- memset(&sCtx, 0, sizeof(TokenCtx));
- sCtx.pPhrase = pAppend;
-
- rc = fts5ParseStringFromToken(pToken, &z);
- if( rc==SQLITE_OK ){
- int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0);
- int n;
- sqlite3Fts5Dequote(z);
- n = (int)strlen(z);
- rc = sqlite3Fts5Tokenize(pConfig, flags, z, n, &sCtx, fts5ParseTokenize);
- }
- sqlite3_free(z);
- if( rc || (rc = sCtx.rc) ){
- pParse->rc = rc;
- fts5ExprPhraseFree(sCtx.pPhrase);
- sCtx.pPhrase = 0;
- }else{
-
- if( pAppend==0 ){
- if( (pParse->nPhrase % 8)==0 ){
- int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
- Fts5ExprPhrase **apNew;
- apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte);
- if( apNew==0 ){
- pParse->rc = SQLITE_NOMEM;
- fts5ExprPhraseFree(sCtx.pPhrase);
- return 0;
- }
- pParse->apPhrase = apNew;
- }
- pParse->nPhrase++;
- }
-
- if( sCtx.pPhrase==0 ){
- /* This happens when parsing a token or quoted phrase that contains
- ** no token characters at all. (e.g ... MATCH '""'). */
- sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
- }else if( sCtx.pPhrase->nTerm ){
- sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
- }
- pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
- }
-
- return sCtx.pPhrase;
-}
-
-/*
-** Create a new FTS5 expression by cloning phrase iPhrase of the
-** expression passed as the second argument.
-*/
-int sqlite3Fts5ExprClonePhrase(
- Fts5Expr *pExpr,
- int iPhrase,
- Fts5Expr **ppNew
-){
- int rc = SQLITE_OK; /* Return code */
- Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
- Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
- TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */
-
- pOrig = pExpr->apExprPhrase[iPhrase];
- pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
- if( rc==SQLITE_OK ){
- pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
- sizeof(Fts5ExprPhrase*));
- }
- if( rc==SQLITE_OK ){
- pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc,
- sizeof(Fts5ExprNode));
- }
- if( rc==SQLITE_OK ){
- pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
- sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
- }
- if( rc==SQLITE_OK ){
- Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
- if( pColsetOrig ){
- int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
- Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
- if( pColset ){
- memcpy(pColset, pColsetOrig, nByte);
- }
- pNew->pRoot->pNear->pColset = pColset;
- }
- }
-
- if( pOrig->nTerm ){
- int i; /* Used to iterate through phrase terms */
- for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
- int tflags = 0;
- Fts5ExprTerm *p;
- for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
- const char *zTerm = p->zTerm;
- rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm),
- 0, 0);
- tflags = FTS5_TOKEN_COLOCATED;
- }
- if( rc==SQLITE_OK ){
- sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
- sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst;
- }
- }
- }else{
- /* This happens when parsing a token or quoted phrase that contains
- ** no token characters at all. (e.g ... MATCH '""'). */
- sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
- }
-
- if( rc==SQLITE_OK ){
- /* All the allocations succeeded. Put the expression object together. */
- pNew->pIndex = pExpr->pIndex;
- pNew->pConfig = pExpr->pConfig;
- pNew->nPhrase = 1;
- pNew->apExprPhrase[0] = sCtx.pPhrase;
- pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
- pNew->pRoot->pNear->nPhrase = 1;
- sCtx.pPhrase->pNode = pNew->pRoot;
-
- if( pOrig->nTerm==1
- && pOrig->aTerm[0].pSynonym==0
- && pOrig->aTerm[0].bFirst==0
- ){
- pNew->pRoot->eType = FTS5_TERM;
- pNew->pRoot->xNext = fts5ExprNodeNext_TERM;
- }else{
- pNew->pRoot->eType = FTS5_STRING;
- pNew->pRoot->xNext = fts5ExprNodeNext_STRING;
- }
- }else{
- sqlite3Fts5ExprFree(pNew);
- fts5ExprPhraseFree(sCtx.pPhrase);
- pNew = 0;
- }
-
- *ppNew = pNew;
- return rc;
-}
-
-
-/*
-** Token pTok has appeared in a MATCH expression where the NEAR operator
-** is expected. If token pTok does not contain "NEAR", store an error
-** in the pParse object.
-*/
-void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token *pTok){
- if( pTok->n!=4 || memcmp("NEAR", pTok->p, 4) ){
- sqlite3Fts5ParseError(
- pParse, "fts5: syntax error near \"%.*s\"", pTok->n, pTok->p
- );
- }
-}
-
-void sqlite3Fts5ParseSetDistance(
- Fts5Parse *pParse,
- Fts5ExprNearset *pNear,
- Fts5Token *p
-){
- if( pNear ){
- int nNear = 0;
- int i;
- if( p->n ){
- for(i=0; i<p->n; i++){
- char c = (char)p->p[i];
- if( c<'0' || c>'9' ){
- sqlite3Fts5ParseError(
- pParse, "expected integer, got \"%.*s\"", p->n, p->p
- );
- return;
- }
- nNear = nNear * 10 + (p->p[i] - '0');
- }
- }else{
- nNear = FTS5_DEFAULT_NEARDIST;
- }
- pNear->nNear = nNear;
- }
-}
-
-/*
-** The second argument passed to this function may be NULL, or it may be
-** an existing Fts5Colset object. This function returns a pointer to
-** a new colset object containing the contents of (p) with new value column
-** number iCol appended.
-**
-** If an OOM error occurs, store an error code in pParse and return NULL.
-** The old colset object (if any) is not freed in this case.
-*/
-static Fts5Colset *fts5ParseColset(
- Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */
- Fts5Colset *p, /* Existing colset object */
- int iCol /* New column to add to colset object */
-){
- int nCol = p ? p->nCol : 0; /* Num. columns already in colset object */
- Fts5Colset *pNew; /* New colset object to return */
-
- assert( pParse->rc==SQLITE_OK );
- assert( iCol>=0 && iCol<pParse->pConfig->nCol );
-
- pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
- if( pNew==0 ){
- pParse->rc = SQLITE_NOMEM;
- }else{
- int *aiCol = pNew->aiCol;
- int i, j;
- for(i=0; i<nCol; i++){
- if( aiCol[i]==iCol ) return pNew;
- if( aiCol[i]>iCol ) break;
- }
- for(j=nCol; j>i; j--){
- aiCol[j] = aiCol[j-1];
- }
- aiCol[i] = iCol;
- pNew->nCol = nCol+1;
-
-#ifndef NDEBUG
- /* Check that the array is in order and contains no duplicate entries. */
- for(i=1; i<pNew->nCol; i++) assert( pNew->aiCol[i]>pNew->aiCol[i-1] );
-#endif
- }
-
- return pNew;
-}
-
-/*
-** Allocate and return an Fts5Colset object specifying the inverse of
-** the colset passed as the second argument. Free the colset passed
-** as the second argument before returning.
-*/
-Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
- Fts5Colset *pRet;
- int nCol = pParse->pConfig->nCol;
-
- pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
- sizeof(Fts5Colset) + sizeof(int)*nCol
- );
- if( pRet ){
- int i;
- int iOld = 0;
- for(i=0; i<nCol; i++){
- if( iOld>=p->nCol || p->aiCol[iOld]!=i ){
- pRet->aiCol[pRet->nCol++] = i;
- }else{
- iOld++;
- }
- }
- }
-
- sqlite3_free(p);
- return pRet;
-}
-
-Fts5Colset *sqlite3Fts5ParseColset(
- Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */
- Fts5Colset *pColset, /* Existing colset object */
- Fts5Token *p
-){
- Fts5Colset *pRet = 0;
- int iCol;
- char *z; /* Dequoted copy of token p */
-
- z = sqlite3Fts5Strndup(&pParse->rc, p->p, p->n);
- if( pParse->rc==SQLITE_OK ){
- Fts5Config *pConfig = pParse->pConfig;
- sqlite3Fts5Dequote(z);
- for(iCol=0; iCol<pConfig->nCol; iCol++){
- if( 0==sqlite3_stricmp(pConfig->azCol[iCol], z) ) break;
- }
- if( iCol==pConfig->nCol ){
- sqlite3Fts5ParseError(pParse, "no such column: %s", z);
- }else{
- pRet = fts5ParseColset(pParse, pColset, iCol);
- }
- sqlite3_free(z);
- }
-
- if( pRet==0 ){
- assert( pParse->rc!=SQLITE_OK );
- sqlite3_free(pColset);
- }
-
- return pRet;
-}
-
-/*
-** If argument pOrig is NULL, or if (*pRc) is set to anything other than
-** SQLITE_OK when this function is called, NULL is returned.
-**
-** Otherwise, a copy of (*pOrig) is made into memory obtained from
-** sqlite3Fts5MallocZero() and a pointer to it returned. If the allocation
-** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned.
-*/
-static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
- Fts5Colset *pRet;
- if( pOrig ){
- int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
- pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
- if( pRet ){
- memcpy(pRet, pOrig, nByte);
- }
- }else{
- pRet = 0;
- }
- return pRet;
-}
-
-/*
-** Remove from colset pColset any columns that are not also in colset pMerge.
-*/
-static void fts5MergeColset(Fts5Colset *pColset, Fts5Colset *pMerge){
- int iIn = 0; /* Next input in pColset */
- int iMerge = 0; /* Next input in pMerge */
- int iOut = 0; /* Next output slot in pColset */
-
- while( iIn<pColset->nCol && iMerge<pMerge->nCol ){
- int iDiff = pColset->aiCol[iIn] - pMerge->aiCol[iMerge];
- if( iDiff==0 ){
- pColset->aiCol[iOut++] = pMerge->aiCol[iMerge];
- iMerge++;
- iIn++;
- }else if( iDiff>0 ){
- iMerge++;
- }else{
- iIn++;
- }
- }
- pColset->nCol = iOut;
-}
-
-/*
-** Recursively apply colset pColset to expression node pNode and all of
-** its decendents. If (*ppFree) is not NULL, it contains a spare copy
-** of pColset. This function may use the spare copy and set (*ppFree) to
-** zero, or it may create copies of pColset using fts5CloneColset().
-*/
-static void fts5ParseSetColset(
- Fts5Parse *pParse,
- Fts5ExprNode *pNode,
- Fts5Colset *pColset,
- Fts5Colset **ppFree
-){
- if( pParse->rc==SQLITE_OK ){
- assert( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING
- || pNode->eType==FTS5_AND || pNode->eType==FTS5_OR
- || pNode->eType==FTS5_NOT || pNode->eType==FTS5_EOF
- );
- if( pNode->eType==FTS5_STRING || pNode->eType==FTS5_TERM ){
- Fts5ExprNearset *pNear = pNode->pNear;
- if( pNear->pColset ){
- fts5MergeColset(pNear->pColset, pColset);
- if( pNear->pColset->nCol==0 ){
- pNode->eType = FTS5_EOF;
- pNode->xNext = 0;
- }
- }else if( *ppFree ){
- pNear->pColset = pColset;
- *ppFree = 0;
- }else{
- pNear->pColset = fts5CloneColset(&pParse->rc, pColset);
- }
- }else{
- int i;
- assert( pNode->eType!=FTS5_EOF || pNode->nChild==0 );
- for(i=0; i<pNode->nChild; i++){
- fts5ParseSetColset(pParse, pNode->apChild[i], pColset, ppFree);
- }
- }
- }
-}
-
-/*
-** Apply colset pColset to expression node pExpr and all of its descendents.
-*/
-void sqlite3Fts5ParseSetColset(
- Fts5Parse *pParse,
- Fts5ExprNode *pExpr,
- Fts5Colset *pColset
-){
- Fts5Colset *pFree = pColset;
- if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
- pParse->rc = SQLITE_ERROR;
- pParse->zErr = sqlite3_mprintf(
- "fts5: column queries are not supported (detail=none)"
- );
- }else{
- fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
- }
- sqlite3_free(pFree);
-}
-
-static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
- switch( pNode->eType ){
- case FTS5_STRING: {
- Fts5ExprNearset *pNear = pNode->pNear;
- if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1
- && pNear->apPhrase[0]->aTerm[0].pSynonym==0
- && pNear->apPhrase[0]->aTerm[0].bFirst==0
- ){
- pNode->eType = FTS5_TERM;
- pNode->xNext = fts5ExprNodeNext_TERM;
- }else{
- pNode->xNext = fts5ExprNodeNext_STRING;
- }
- break;
- };
-
- case FTS5_OR: {
- pNode->xNext = fts5ExprNodeNext_OR;
- break;
- };
-
- case FTS5_AND: {
- pNode->xNext = fts5ExprNodeNext_AND;
- break;
- };
-
- default: assert( pNode->eType==FTS5_NOT ); {
- pNode->xNext = fts5ExprNodeNext_NOT;
- break;
- };
- }
-}
-
-static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
- if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){
- int nByte = sizeof(Fts5ExprNode*) * pSub->nChild;
- memcpy(&p->apChild[p->nChild], pSub->apChild, nByte);
- p->nChild += pSub->nChild;
- sqlite3_free(pSub);
- }else{
- p->apChild[p->nChild++] = pSub;
- }
-}
-
-/*
-** Allocate and return a new expression object. If anything goes wrong (i.e.
-** OOM error), leave an error code in pParse and return NULL.
-*/
-Fts5ExprNode *sqlite3Fts5ParseNode(
- Fts5Parse *pParse, /* Parse context */
- int eType, /* FTS5_STRING, AND, OR or NOT */
- Fts5ExprNode *pLeft, /* Left hand child expression */
- Fts5ExprNode *pRight, /* Right hand child expression */
- Fts5ExprNearset *pNear /* For STRING expressions, the near cluster */
-){
- Fts5ExprNode *pRet = 0;
-
- if( pParse->rc==SQLITE_OK ){
- int nChild = 0; /* Number of children of returned node */
- int nByte; /* Bytes of space to allocate for this node */
-
- assert( (eType!=FTS5_STRING && !pNear)
- || (eType==FTS5_STRING && !pLeft && !pRight)
- );
- if( eType==FTS5_STRING && pNear==0 ) return 0;
- if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
- if( eType!=FTS5_STRING && pRight==0 ) return pLeft;
-
- if( eType==FTS5_NOT ){
- nChild = 2;
- }else if( eType==FTS5_AND || eType==FTS5_OR ){
- nChild = 2;
- if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
- if( pRight->eType==eType ) nChild += pRight->nChild-1;
- }
-
- nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
- pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
-
- if( pRet ){
- pRet->eType = eType;
- pRet->pNear = pNear;
- fts5ExprAssignXNext(pRet);
- if( eType==FTS5_STRING ){
- int iPhrase;
- for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
- pNear->apPhrase[iPhrase]->pNode = pRet;
- if( pNear->apPhrase[iPhrase]->nTerm==0 ){
- pRet->xNext = 0;
- pRet->eType = FTS5_EOF;
- }
- }
-
- if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
- if( pNear->nPhrase!=1
- || pPhrase->nTerm>1
- || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
- ){
- assert( pParse->rc==SQLITE_OK );
- pParse->rc = SQLITE_ERROR;
- assert( pParse->zErr==0 );
- pParse->zErr = sqlite3_mprintf(
- "fts5: %s queries are not supported (detail!=full)",
- pNear->nPhrase==1 ? "phrase": "NEAR"
- );
- sqlite3_free(pRet);
- pRet = 0;
- }
- }
- }else{
- fts5ExprAddChildren(pRet, pLeft);
- fts5ExprAddChildren(pRet, pRight);
- }
- }
- }
-
- if( pRet==0 ){
- assert( pParse->rc!=SQLITE_OK );
- sqlite3Fts5ParseNodeFree(pLeft);
- sqlite3Fts5ParseNodeFree(pRight);
- sqlite3Fts5ParseNearsetFree(pNear);
- }
- return pRet;
-}
-
-Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
- Fts5Parse *pParse, /* Parse context */
- Fts5ExprNode *pLeft, /* Left hand child expression */
- Fts5ExprNode *pRight /* Right hand child expression */
-){
- Fts5ExprNode *pRet = 0;
- Fts5ExprNode *pPrev;
-
- if( pParse->rc ){
- sqlite3Fts5ParseNodeFree(pLeft);
- sqlite3Fts5ParseNodeFree(pRight);
- }else{
-
- assert( pLeft->eType==FTS5_STRING
- || pLeft->eType==FTS5_TERM
- || pLeft->eType==FTS5_EOF
- || pLeft->eType==FTS5_AND
- );
- assert( pRight->eType==FTS5_STRING
- || pRight->eType==FTS5_TERM
- || pRight->eType==FTS5_EOF
- );
-
- if( pLeft->eType==FTS5_AND ){
- pPrev = pLeft->apChild[pLeft->nChild-1];
- }else{
- pPrev = pLeft;
- }
- assert( pPrev->eType==FTS5_STRING
- || pPrev->eType==FTS5_TERM
- || pPrev->eType==FTS5_EOF
- );
-
- if( pRight->eType==FTS5_EOF ){
- assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
- sqlite3Fts5ParseNodeFree(pRight);
- pRet = pLeft;
- pParse->nPhrase--;
- }
- else if( pPrev->eType==FTS5_EOF ){
- Fts5ExprPhrase **ap;
-
- if( pPrev==pLeft ){
- pRet = pRight;
- }else{
- pLeft->apChild[pLeft->nChild-1] = pRight;
- pRet = pLeft;
- }
-
- ap = &pParse->apPhrase[pParse->nPhrase-1-pRight->pNear->nPhrase];
- assert( ap[0]==pPrev->pNear->apPhrase[0] );
- memmove(ap, &ap[1], sizeof(Fts5ExprPhrase*)*pRight->pNear->nPhrase);
- pParse->nPhrase--;
-
- sqlite3Fts5ParseNodeFree(pPrev);
- }
- else{
- pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0);
- }
- }
-
- return pRet;
-}
-
-static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
- int nByte = 0;
- Fts5ExprTerm *p;
- char *zQuoted;
-
- /* Determine the maximum amount of space required. */
- for(p=pTerm; p; p=p->pSynonym){
- nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2;
- }
- zQuoted = sqlite3_malloc(nByte);
-
- if( zQuoted ){
- int i = 0;
- for(p=pTerm; p; p=p->pSynonym){
- char *zIn = p->zTerm;
- zQuoted[i++] = '"';
- while( *zIn ){
- if( *zIn=='"' ) zQuoted[i++] = '"';
- zQuoted[i++] = *zIn++;
- }
- zQuoted[i++] = '"';
- if( p->pSynonym ) zQuoted[i++] = '|';
- }
- if( pTerm->bPrefix ){
- zQuoted[i++] = ' ';
- zQuoted[i++] = '*';
- }
- zQuoted[i++] = '\0';
- }
- return zQuoted;
-}
-
-static char *fts5PrintfAppend(char *zApp, const char *zFmt, ...){
- char *zNew;
- va_list ap;
- va_start(ap, zFmt);
- zNew = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
- if( zApp && zNew ){
- char *zNew2 = sqlite3_mprintf("%s%s", zApp, zNew);
- sqlite3_free(zNew);
- zNew = zNew2;
- }
- sqlite3_free(zApp);
- return zNew;
-}
-
-/*
-** Compose a tcl-readable representation of expression pExpr. Return a
-** pointer to a buffer containing that representation. It is the
-** responsibility of the caller to at some point free the buffer using
-** sqlite3_free().
-*/
-static char *fts5ExprPrintTcl(
- Fts5Config *pConfig,
- const char *zNearsetCmd,
- Fts5ExprNode *pExpr
-){
- char *zRet = 0;
- if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){
- Fts5ExprNearset *pNear = pExpr->pNear;
- int i;
- int iTerm;
-
- zRet = fts5PrintfAppend(zRet, "%s ", zNearsetCmd);
- if( zRet==0 ) return 0;
- if( pNear->pColset ){
- int *aiCol = pNear->pColset->aiCol;
- int nCol = pNear->pColset->nCol;
- if( nCol==1 ){
- zRet = fts5PrintfAppend(zRet, "-col %d ", aiCol[0]);
- }else{
- zRet = fts5PrintfAppend(zRet, "-col {%d", aiCol[0]);
- for(i=1; i<pNear->pColset->nCol; i++){
- zRet = fts5PrintfAppend(zRet, " %d", aiCol[i]);
- }
- zRet = fts5PrintfAppend(zRet, "} ");
- }
- if( zRet==0 ) return 0;
- }
-
- if( pNear->nPhrase>1 ){
- zRet = fts5PrintfAppend(zRet, "-near %d ", pNear->nNear);
- if( zRet==0 ) return 0;
- }
-
- zRet = fts5PrintfAppend(zRet, "--");
- if( zRet==0 ) return 0;
-
- for(i=0; i<pNear->nPhrase; i++){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
-
- zRet = fts5PrintfAppend(zRet, " {");
- for(iTerm=0; zRet && iTerm<pPhrase->nTerm; iTerm++){
- char *zTerm = pPhrase->aTerm[iTerm].zTerm;
- zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm);
- if( pPhrase->aTerm[iTerm].bPrefix ){
- zRet = fts5PrintfAppend(zRet, "*");
- }
- }
-
- if( zRet ) zRet = fts5PrintfAppend(zRet, "}");
- if( zRet==0 ) return 0;
- }
-
- }else{
- char const *zOp = 0;
- int i;
- switch( pExpr->eType ){
- case FTS5_AND: zOp = "AND"; break;
- case FTS5_NOT: zOp = "NOT"; break;
- default:
- assert( pExpr->eType==FTS5_OR );
- zOp = "OR";
- break;
- }
-
- zRet = sqlite3_mprintf("%s", zOp);
- for(i=0; zRet && i<pExpr->nChild; i++){
- char *z = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->apChild[i]);
- if( !z ){
- sqlite3_free(zRet);
- zRet = 0;
- }else{
- zRet = fts5PrintfAppend(zRet, " [%z]", z);
- }
- }
- }
-
- return zRet;
-}
-
-static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
- char *zRet = 0;
- if( pExpr->eType==0 ){
- return sqlite3_mprintf("\"\"");
- }else
- if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){
- Fts5ExprNearset *pNear = pExpr->pNear;
- int i;
- int iTerm;
-
- if( pNear->pColset ){
- int iCol = pNear->pColset->aiCol[0];
- zRet = fts5PrintfAppend(zRet, "%s : ", pConfig->azCol[iCol]);
- if( zRet==0 ) return 0;
- }
-
- if( pNear->nPhrase>1 ){
- zRet = fts5PrintfAppend(zRet, "NEAR(");
- if( zRet==0 ) return 0;
- }
-
- for(i=0; i<pNear->nPhrase; i++){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
- if( i!=0 ){
- zRet = fts5PrintfAppend(zRet, " ");
- if( zRet==0 ) return 0;
- }
- for(iTerm=0; iTerm<pPhrase->nTerm; iTerm++){
- char *zTerm = fts5ExprTermPrint(&pPhrase->aTerm[iTerm]);
- if( zTerm ){
- zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" + ", zTerm);
- sqlite3_free(zTerm);
- }
- if( zTerm==0 || zRet==0 ){
- sqlite3_free(zRet);
- return 0;
- }
- }
- }
-
- if( pNear->nPhrase>1 ){
- zRet = fts5PrintfAppend(zRet, ", %d)", pNear->nNear);
- if( zRet==0 ) return 0;
- }
-
- }else{
- char const *zOp = 0;
- int i;
-
- switch( pExpr->eType ){
- case FTS5_AND: zOp = " AND "; break;
- case FTS5_NOT: zOp = " NOT "; break;
- default:
- assert( pExpr->eType==FTS5_OR );
- zOp = " OR ";
- break;
- }
-
- for(i=0; i<pExpr->nChild; i++){
- char *z = fts5ExprPrint(pConfig, pExpr->apChild[i]);
- if( z==0 ){
- sqlite3_free(zRet);
- zRet = 0;
- }else{
- int e = pExpr->apChild[i]->eType;
- int b = (e!=FTS5_STRING && e!=FTS5_TERM && e!=FTS5_EOF);
- zRet = fts5PrintfAppend(zRet, "%s%s%z%s",
- (i==0 ? "" : zOp),
- (b?"(":""), z, (b?")":"")
- );
- }
- if( zRet==0 ) break;
- }
- }
-
- return zRet;
-}
-
-/*
-** The implementation of user-defined scalar functions fts5_expr() (bTcl==0)
-** and fts5_expr_tcl() (bTcl!=0).
-*/
-static void fts5ExprFunction(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args */
- sqlite3_value **apVal, /* Function arguments */
- int bTcl
-){
- Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
- sqlite3 *db = sqlite3_context_db_handle(pCtx);
- const char *zExpr = 0;
- char *zErr = 0;
- Fts5Expr *pExpr = 0;
- int rc;
- int i;
-
- const char **azConfig; /* Array of arguments for Fts5Config */
- const char *zNearsetCmd = "nearset";
- int nConfig; /* Size of azConfig[] */
- Fts5Config *pConfig = 0;
- int iArg = 1;
-
- if( nArg<1 ){
- zErr = sqlite3_mprintf("wrong number of arguments to function %s",
- bTcl ? "fts5_expr_tcl" : "fts5_expr"
- );
- sqlite3_result_error(pCtx, zErr, -1);
- sqlite3_free(zErr);
- return;
- }
-
- if( bTcl && nArg>1 ){
- zNearsetCmd = (const char*)sqlite3_value_text(apVal[1]);
- iArg = 2;
- }
-
- nConfig = 3 + (nArg-iArg);
- azConfig = (const char**)sqlite3_malloc(sizeof(char*) * nConfig);
- if( azConfig==0 ){
- sqlite3_result_error_nomem(pCtx);
- return;
- }
- azConfig[0] = 0;
- azConfig[1] = "main";
- azConfig[2] = "tbl";
- for(i=3; iArg<nArg; iArg++){
- azConfig[i++] = (const char*)sqlite3_value_text(apVal[iArg]);
- }
-
- zExpr = (const char*)sqlite3_value_text(apVal[0]);
-
- rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
- }
- if( rc==SQLITE_OK ){
- char *zText;
- if( pExpr->pRoot->xNext==0 ){
- zText = sqlite3_mprintf("");
- }else if( bTcl ){
- zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot);
- }else{
- zText = fts5ExprPrint(pConfig, pExpr->pRoot);
- }
- if( zText==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_result_text(pCtx, zText, -1, SQLITE_TRANSIENT);
- sqlite3_free(zText);
- }
- }
-
- if( rc!=SQLITE_OK ){
- if( zErr ){
- sqlite3_result_error(pCtx, zErr, -1);
- sqlite3_free(zErr);
- }else{
- sqlite3_result_error_code(pCtx, rc);
- }
- }
- sqlite3_free((void *)azConfig);
- sqlite3Fts5ConfigFree(pConfig);
- sqlite3Fts5ExprFree(pExpr);
-}
-
-static void fts5ExprFunctionHr(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args */
- sqlite3_value **apVal /* Function arguments */
-){
- fts5ExprFunction(pCtx, nArg, apVal, 0);
-}
-static void fts5ExprFunctionTcl(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args */
- sqlite3_value **apVal /* Function arguments */
-){
- fts5ExprFunction(pCtx, nArg, apVal, 1);
-}
-
-/*
-** The implementation of an SQLite user-defined-function that accepts a
-** single integer as an argument. If the integer is an alpha-numeric
-** unicode code point, 1 is returned. Otherwise 0.
-*/
-static void fts5ExprIsAlnum(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args */
- sqlite3_value **apVal /* Function arguments */
-){
- int iCode;
- if( nArg!=1 ){
- sqlite3_result_error(pCtx,
- "wrong number of arguments to function fts5_isalnum", -1
- );
- return;
- }
- iCode = sqlite3_value_int(apVal[0]);
- sqlite3_result_int(pCtx, sqlite3Fts5UnicodeIsalnum(iCode));
-}
-
-static void fts5ExprFold(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args */
- sqlite3_value **apVal /* Function arguments */
-){
- if( nArg!=1 && nArg!=2 ){
- sqlite3_result_error(pCtx,
- "wrong number of arguments to function fts5_fold", -1
- );
- }else{
- int iCode;
- int bRemoveDiacritics = 0;
- iCode = sqlite3_value_int(apVal[0]);
- if( nArg==2 ) bRemoveDiacritics = sqlite3_value_int(apVal[1]);
- sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
- }
-}
-
-/*
-** This is called during initialization to register the fts5_expr() scalar
-** UDF with the SQLite handle passed as the only argument.
-*/
-int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
- struct Fts5ExprFunc {
- const char *z;
- void (*x)(sqlite3_context*,int,sqlite3_value**);
- } aFunc[] = {
- { "fts5_expr", fts5ExprFunctionHr },
- { "fts5_expr_tcl", fts5ExprFunctionTcl },
- { "fts5_isalnum", fts5ExprIsAlnum },
- { "fts5_fold", fts5ExprFold },
- };
- int i;
- int rc = SQLITE_OK;
- void *pCtx = (void*)pGlobal;
-
- for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){
- struct Fts5ExprFunc *p = &aFunc[i];
- rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
- }
-
- /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */
-#ifndef NDEBUG
- (void)sqlite3Fts5ParserTrace;
-#endif
-
- return rc;
-}
-
-/*
-** Return the number of phrases in expression pExpr.
-*/
-int sqlite3Fts5ExprPhraseCount(Fts5Expr *pExpr){
- return (pExpr ? pExpr->nPhrase : 0);
-}
-
-/*
-** Return the number of terms in the iPhrase'th phrase in pExpr.
-*/
-int sqlite3Fts5ExprPhraseSize(Fts5Expr *pExpr, int iPhrase){
- if( iPhrase<0 || iPhrase>=pExpr->nPhrase ) return 0;
- return pExpr->apExprPhrase[iPhrase]->nTerm;
-}
-
-/*
-** This function is used to access the current position list for phrase
-** iPhrase.
-*/
-int sqlite3Fts5ExprPoslist(Fts5Expr *pExpr, int iPhrase, const u8 **pa){
- int nRet;
- Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase];
- Fts5ExprNode *pNode = pPhrase->pNode;
- if( pNode->bEof==0 && pNode->iRowid==pExpr->pRoot->iRowid ){
- *pa = pPhrase->poslist.p;
- nRet = pPhrase->poslist.n;
- }else{
- *pa = 0;
- nRet = 0;
- }
- return nRet;
-}
-
-struct Fts5PoslistPopulator {
- Fts5PoslistWriter writer;
- int bOk; /* True if ok to populate */
- int bMiss;
-};
-
-Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
- Fts5PoslistPopulator *pRet;
- pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
- if( pRet ){
- int i;
- memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
- for(i=0; i<pExpr->nPhrase; i++){
- Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist;
- Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
- assert( pExpr->apExprPhrase[i]->nTerm==1 );
- if( bLive &&
- (pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof)
- ){
- pRet[i].bMiss = 1;
- }else{
- pBuf->n = 0;
- }
- }
- }
- return pRet;
-}
-
-struct Fts5ExprCtx {
- Fts5Expr *pExpr;
- Fts5PoslistPopulator *aPopulator;
- i64 iOff;
-};
-typedef struct Fts5ExprCtx Fts5ExprCtx;
-
-/*
-** TODO: Make this more efficient!
-*/
-static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){
- int i;
- for(i=0; i<pColset->nCol; i++){
- if( pColset->aiCol[i]==iCol ) return 1;
- }
- return 0;
-}
-
-static int fts5ExprPopulatePoslistsCb(
- void *pCtx, /* Copy of 2nd argument to xTokenize() */
- int tflags, /* Mask of FTS5_TOKEN_* flags */
- const char *pToken, /* Pointer to buffer containing token */
- int nToken, /* Size of token in bytes */
- int iUnused1, /* Byte offset of token within input text */
- int iUnused2 /* Byte offset of end of token within input text */
-){
- Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx;
- Fts5Expr *pExpr = p->pExpr;
- int i;
-
- UNUSED_PARAM2(iUnused1, iUnused2);
-
- if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
- if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++;
- for(i=0; i<pExpr->nPhrase; i++){
- Fts5ExprTerm *pTerm;
- if( p->aPopulator[i].bOk==0 ) continue;
- for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
- int nTerm = (int)strlen(pTerm->zTerm);
- if( (nTerm==nToken || (nTerm<nToken && pTerm->bPrefix))
- && memcmp(pTerm->zTerm, pToken, nTerm)==0
- ){
- int rc = sqlite3Fts5PoslistWriterAppend(
- &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
- );
- if( rc ) return rc;
- break;
- }
- }
- }
- return SQLITE_OK;
-}
-
-int sqlite3Fts5ExprPopulatePoslists(
- Fts5Config *pConfig,
- Fts5Expr *pExpr,
- Fts5PoslistPopulator *aPopulator,
- int iCol,
- const char *z, int n
-){
- int i;
- Fts5ExprCtx sCtx;
- sCtx.pExpr = pExpr;
- sCtx.aPopulator = aPopulator;
- sCtx.iOff = (((i64)iCol) << 32) - 1;
-
- for(i=0; i<pExpr->nPhrase; i++){
- Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
- Fts5Colset *pColset = pNode->pNear->pColset;
- if( (pColset && 0==fts5ExprColsetTest(pColset, iCol))
- || aPopulator[i].bMiss
- ){
- aPopulator[i].bOk = 0;
- }else{
- aPopulator[i].bOk = 1;
- }
- }
-
- return sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT, z, n, (void*)&sCtx, fts5ExprPopulatePoslistsCb
- );
-}
-
-static void fts5ExprClearPoslists(Fts5ExprNode *pNode){
- if( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING ){
- pNode->pNear->apPhrase[0]->poslist.n = 0;
- }else{
- int i;
- for(i=0; i<pNode->nChild; i++){
- fts5ExprClearPoslists(pNode->apChild[i]);
- }
- }
-}
-
-static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){
- pNode->iRowid = iRowid;
- pNode->bEof = 0;
- switch( pNode->eType ){
- case FTS5_TERM:
- case FTS5_STRING:
- return (pNode->pNear->apPhrase[0]->poslist.n>0);
-
- case FTS5_AND: {
- int i;
- for(i=0; i<pNode->nChild; i++){
- if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid)==0 ){
- fts5ExprClearPoslists(pNode);
- return 0;
- }
- }
- break;
- }
-
- case FTS5_OR: {
- int i;
- int bRet = 0;
- for(i=0; i<pNode->nChild; i++){
- if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid) ){
- bRet = 1;
- }
- }
- return bRet;
- }
-
- default: {
- assert( pNode->eType==FTS5_NOT );
- if( 0==fts5ExprCheckPoslists(pNode->apChild[0], iRowid)
- || 0!=fts5ExprCheckPoslists(pNode->apChild[1], iRowid)
- ){
- fts5ExprClearPoslists(pNode);
- return 0;
- }
- break;
- }
- }
- return 1;
-}
-
-void sqlite3Fts5ExprCheckPoslists(Fts5Expr *pExpr, i64 iRowid){
- fts5ExprCheckPoslists(pExpr->pRoot, iRowid);
-}
-
-/*
-** This function is only called for detail=columns tables.
-*/
-int sqlite3Fts5ExprPhraseCollist(
- Fts5Expr *pExpr,
- int iPhrase,
- const u8 **ppCollist,
- int *pnCollist
-){
- Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase];
- Fts5ExprNode *pNode = pPhrase->pNode;
- int rc = SQLITE_OK;
-
- assert( iPhrase>=0 && iPhrase<pExpr->nPhrase );
- assert( pExpr->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
-
- if( pNode->bEof==0
- && pNode->iRowid==pExpr->pRoot->iRowid
- && pPhrase->poslist.n>0
- ){
- Fts5ExprTerm *pTerm = &pPhrase->aTerm[0];
- if( pTerm->pSynonym ){
- Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1];
- rc = fts5ExprSynonymList(
- pTerm, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist
- );
- }else{
- *ppCollist = pPhrase->aTerm[0].pIter->pData;
- *pnCollist = pPhrase->aTerm[0].pIter->nData;
- }
- }else{
- *ppCollist = 0;
- *pnCollist = 0;
- }
-
- return rc;
-}
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_hash.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_hash.c
deleted file mode 100644
index 175706151b2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_hash.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
-** 2014 August 11
-**
-** 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.
-**
-******************************************************************************
-**
-*/
-
-
-
-#include "fts5Int.h"
-
-typedef struct Fts5HashEntry Fts5HashEntry;
-
-/*
-** This file contains the implementation of an in-memory hash table used
-** to accumuluate "term -> doclist" content before it is flused to a level-0
-** segment.
-*/
-
-
-struct Fts5Hash {
- int eDetail; /* Copy of Fts5Config.eDetail */
- int *pnByte; /* Pointer to bytes counter */
- int nEntry; /* Number of entries currently in hash */
- int nSlot; /* Size of aSlot[] array */
- Fts5HashEntry *pScan; /* Current ordered scan item */
- Fts5HashEntry **aSlot; /* Array of hash slots */
-};
-
-/*
-** Each entry in the hash table is represented by an object of the
-** following type. Each object, its key (a nul-terminated string) and
-** its current data are stored in a single memory allocation. The
-** key immediately follows the object in memory. The position list
-** data immediately follows the key data in memory.
-**
-** The data that follows the key is in a similar, but not identical format
-** to the doclist data stored in the database. It is:
-**
-** * Rowid, as a varint
-** * Position list, without 0x00 terminator.
-** * Size of previous position list and rowid, as a 4 byte
-** big-endian integer.
-**
-** iRowidOff:
-** Offset of last rowid written to data area. Relative to first byte of
-** structure.
-**
-** nData:
-** Bytes of data written since iRowidOff.
-*/
-struct Fts5HashEntry {
- Fts5HashEntry *pHashNext; /* Next hash entry with same hash-key */
- Fts5HashEntry *pScanNext; /* Next entry in sorted order */
-
- int nAlloc; /* Total size of allocation */
- int iSzPoslist; /* Offset of space for 4-byte poslist size */
- int nData; /* Total bytes of data (incl. structure) */
- int nKey; /* Length of key in bytes */
- u8 bDel; /* Set delete-flag @ iSzPoslist */
- u8 bContent; /* Set content-flag (detail=none mode) */
- i16 iCol; /* Column of last value written */
- int iPos; /* Position of last value written */
- i64 iRowid; /* Rowid of last value written */
-};
-
-/*
-** Eqivalent to:
-**
-** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
-*/
-#define fts5EntryKey(p) ( ((char *)(&(p)[1])) )
-
-
-/*
-** Allocate a new hash table.
-*/
-int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){
- int rc = SQLITE_OK;
- Fts5Hash *pNew;
-
- *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash));
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int nByte;
- memset(pNew, 0, sizeof(Fts5Hash));
- pNew->pnByte = pnByte;
- pNew->eDetail = pConfig->eDetail;
-
- pNew->nSlot = 1024;
- nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
- pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
- if( pNew->aSlot==0 ){
- sqlite3_free(pNew);
- *ppNew = 0;
- rc = SQLITE_NOMEM;
- }else{
- memset(pNew->aSlot, 0, nByte);
- }
- }
- return rc;
-}
-
-/*
-** Free a hash table object.
-*/
-void sqlite3Fts5HashFree(Fts5Hash *pHash){
- if( pHash ){
- sqlite3Fts5HashClear(pHash);
- sqlite3_free(pHash->aSlot);
- sqlite3_free(pHash);
- }
-}
-
-/*
-** Empty (but do not delete) a hash table.
-*/
-void sqlite3Fts5HashClear(Fts5Hash *pHash){
- int i;
- for(i=0; i<pHash->nSlot; i++){
- Fts5HashEntry *pNext;
- Fts5HashEntry *pSlot;
- for(pSlot=pHash->aSlot[i]; pSlot; pSlot=pNext){
- pNext = pSlot->pHashNext;
- sqlite3_free(pSlot);
- }
- }
- memset(pHash->aSlot, 0, pHash->nSlot * sizeof(Fts5HashEntry*));
- pHash->nEntry = 0;
-}
-
-static unsigned int fts5HashKey(int nSlot, const u8 *p, int n){
- int i;
- unsigned int h = 13;
- for(i=n-1; i>=0; i--){
- h = (h << 3) ^ h ^ p[i];
- }
- return (h % nSlot);
-}
-
-static unsigned int fts5HashKey2(int nSlot, u8 b, const u8 *p, int n){
- int i;
- unsigned int h = 13;
- for(i=n-1; i>=0; i--){
- h = (h << 3) ^ h ^ p[i];
- }
- h = (h << 3) ^ h ^ b;
- return (h % nSlot);
-}
-
-/*
-** Resize the hash table by doubling the number of slots.
-*/
-static int fts5HashResize(Fts5Hash *pHash){
- int nNew = pHash->nSlot*2;
- int i;
- Fts5HashEntry **apNew;
- Fts5HashEntry **apOld = pHash->aSlot;
-
- apNew = (Fts5HashEntry**)sqlite3_malloc(nNew*sizeof(Fts5HashEntry*));
- if( !apNew ) return SQLITE_NOMEM;
- memset(apNew, 0, nNew*sizeof(Fts5HashEntry*));
-
- for(i=0; i<pHash->nSlot; i++){
- while( apOld[i] ){
- unsigned int iHash;
- Fts5HashEntry *p = apOld[i];
- apOld[i] = p->pHashNext;
- iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p),
- (int)strlen(fts5EntryKey(p)));
- p->pHashNext = apNew[iHash];
- apNew[iHash] = p;
- }
- }
-
- sqlite3_free(apOld);
- pHash->nSlot = nNew;
- pHash->aSlot = apNew;
- return SQLITE_OK;
-}
-
-static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){
- if( p->iSzPoslist ){
- u8 *pPtr = (u8*)p;
- if( pHash->eDetail==FTS5_DETAIL_NONE ){
- assert( p->nData==p->iSzPoslist );
- if( p->bDel ){
- pPtr[p->nData++] = 0x00;
- if( p->bContent ){
- pPtr[p->nData++] = 0x00;
- }
- }
- }else{
- int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */
- int nPos = nSz*2 + p->bDel; /* Value of nPos field */
-
- assert( p->bDel==0 || p->bDel==1 );
- if( nPos<=127 ){
- pPtr[p->iSzPoslist] = (u8)nPos;
- }else{
- int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
- memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
- sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos);
- p->nData += (nByte-1);
- }
- }
-
- p->iSzPoslist = 0;
- p->bDel = 0;
- p->bContent = 0;
- }
-}
-
-/*
-** Add an entry to the in-memory hash table. The key is the concatenation
-** of bByte and (pToken/nToken). The value is (iRowid/iCol/iPos).
-**
-** (bByte || pToken) -> (iRowid,iCol,iPos)
-**
-** Or, if iCol is negative, then the value is a delete marker.
-*/
-int sqlite3Fts5HashWrite(
- Fts5Hash *pHash,
- i64 iRowid, /* Rowid for this entry */
- int iCol, /* Column token appears in (-ve -> delete) */
- int iPos, /* Position of token within column */
- char bByte, /* First byte of token */
- const char *pToken, int nToken /* Token to add or remove to or from index */
-){
- unsigned int iHash;
- Fts5HashEntry *p;
- u8 *pPtr;
- int nIncr = 0; /* Amount to increment (*pHash->pnByte) by */
- int bNew; /* If non-delete entry should be written */
-
- bNew = (pHash->eDetail==FTS5_DETAIL_FULL);
-
- /* Attempt to locate an existing hash entry */
- iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
- for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
- char *zKey = fts5EntryKey(p);
- if( zKey[0]==bByte
- && p->nKey==nToken
- && memcmp(&zKey[1], pToken, nToken)==0
- ){
- break;
- }
- }
-
- /* If an existing hash entry cannot be found, create a new one. */
- if( p==0 ){
- /* Figure out how much space to allocate */
- char *zKey;
- int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
- if( nByte<128 ) nByte = 128;
-
- /* Grow the Fts5Hash.aSlot[] array if necessary. */
- if( (pHash->nEntry*2)>=pHash->nSlot ){
- int rc = fts5HashResize(pHash);
- if( rc!=SQLITE_OK ) return rc;
- iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
- }
-
- /* Allocate new Fts5HashEntry and add it to the hash table. */
- p = (Fts5HashEntry*)sqlite3_malloc(nByte);
- if( !p ) return SQLITE_NOMEM;
- memset(p, 0, sizeof(Fts5HashEntry));
- p->nAlloc = nByte;
- zKey = fts5EntryKey(p);
- zKey[0] = bByte;
- memcpy(&zKey[1], pToken, nToken);
- assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
- p->nKey = nToken;
- zKey[nToken+1] = '\0';
- p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry);
- p->pHashNext = pHash->aSlot[iHash];
- pHash->aSlot[iHash] = p;
- pHash->nEntry++;
-
- /* Add the first rowid field to the hash-entry */
- p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid);
- p->iRowid = iRowid;
-
- p->iSzPoslist = p->nData;
- if( pHash->eDetail!=FTS5_DETAIL_NONE ){
- p->nData += 1;
- p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
- }
-
- nIncr += p->nData;
- }else{
-
- /* Appending to an existing hash-entry. Check that there is enough
- ** space to append the largest possible new entry. Worst case scenario
- ** is:
- **
- ** + 9 bytes for a new rowid,
- ** + 4 byte reserved for the "poslist size" varint.
- ** + 1 byte for a "new column" byte,
- ** + 3 bytes for a new column number (16-bit max) as a varint,
- ** + 5 bytes for the new position offset (32-bit max).
- */
- if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
- int nNew = p->nAlloc * 2;
- Fts5HashEntry *pNew;
- Fts5HashEntry **pp;
- pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
- if( pNew==0 ) return SQLITE_NOMEM;
- pNew->nAlloc = nNew;
- for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
- *pp = pNew;
- p = pNew;
- }
- nIncr -= p->nData;
- }
- assert( (p->nAlloc - p->nData) >= (9 + 4 + 1 + 3 + 5) );
-
- pPtr = (u8*)p;
-
- /* If this is a new rowid, append the 4-byte size field for the previous
- ** entry, and the new rowid for this entry. */
- if( iRowid!=p->iRowid ){
- fts5HashAddPoslistSize(pHash, p);
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
- p->iRowid = iRowid;
- bNew = 1;
- p->iSzPoslist = p->nData;
- if( pHash->eDetail!=FTS5_DETAIL_NONE ){
- p->nData += 1;
- p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
- p->iPos = 0;
- }
- }
-
- if( iCol>=0 ){
- if( pHash->eDetail==FTS5_DETAIL_NONE ){
- p->bContent = 1;
- }else{
- /* Append a new column value, if necessary */
- assert( iCol>=p->iCol );
- if( iCol!=p->iCol ){
- if( pHash->eDetail==FTS5_DETAIL_FULL ){
- pPtr[p->nData++] = 0x01;
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
- p->iCol = (i16)iCol;
- p->iPos = 0;
- }else{
- bNew = 1;
- p->iCol = (i16)(iPos = iCol);
- }
- }
-
- /* Append the new position offset, if necessary */
- if( bNew ){
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iPos - p->iPos + 2);
- p->iPos = iPos;
- }
- }
- }else{
- /* This is a delete. Set the delete flag. */
- p->bDel = 1;
- }
-
- nIncr += p->nData;
- *pHash->pnByte += nIncr;
- return SQLITE_OK;
-}
-
-
-/*
-** Arguments pLeft and pRight point to linked-lists of hash-entry objects,
-** each sorted in key order. This function merges the two lists into a
-** single list and returns a pointer to its first element.
-*/
-static Fts5HashEntry *fts5HashEntryMerge(
- Fts5HashEntry *pLeft,
- Fts5HashEntry *pRight
-){
- Fts5HashEntry *p1 = pLeft;
- Fts5HashEntry *p2 = pRight;
- Fts5HashEntry *pRet = 0;
- Fts5HashEntry **ppOut = &pRet;
-
- while( p1 || p2 ){
- if( p1==0 ){
- *ppOut = p2;
- p2 = 0;
- }else if( p2==0 ){
- *ppOut = p1;
- p1 = 0;
- }else{
- int i = 0;
- char *zKey1 = fts5EntryKey(p1);
- char *zKey2 = fts5EntryKey(p2);
- while( zKey1[i]==zKey2[i] ) i++;
-
- if( ((u8)zKey1[i])>((u8)zKey2[i]) ){
- /* p2 is smaller */
- *ppOut = p2;
- ppOut = &p2->pScanNext;
- p2 = p2->pScanNext;
- }else{
- /* p1 is smaller */
- *ppOut = p1;
- ppOut = &p1->pScanNext;
- p1 = p1->pScanNext;
- }
- *ppOut = 0;
- }
- }
-
- return pRet;
-}
-
-/*
-** Extract all tokens from hash table iHash and link them into a list
-** in sorted order. The hash table is cleared before returning. It is
-** the responsibility of the caller to free the elements of the returned
-** list.
-*/
-static int fts5HashEntrySort(
- Fts5Hash *pHash,
- const char *pTerm, int nTerm, /* Query prefix, if any */
- Fts5HashEntry **ppSorted
-){
- const int nMergeSlot = 32;
- Fts5HashEntry **ap;
- Fts5HashEntry *pList;
- int iSlot;
- int i;
-
- *ppSorted = 0;
- ap = sqlite3_malloc(sizeof(Fts5HashEntry*) * nMergeSlot);
- if( !ap ) return SQLITE_NOMEM;
- memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);
-
- for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
- Fts5HashEntry *pIter;
- for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
- if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){
- Fts5HashEntry *pEntry = pIter;
- pEntry->pScanNext = 0;
- for(i=0; ap[i]; i++){
- pEntry = fts5HashEntryMerge(pEntry, ap[i]);
- ap[i] = 0;
- }
- ap[i] = pEntry;
- }
- }
- }
-
- pList = 0;
- for(i=0; i<nMergeSlot; i++){
- pList = fts5HashEntryMerge(pList, ap[i]);
- }
-
- pHash->nEntry = 0;
- sqlite3_free(ap);
- *ppSorted = pList;
- return SQLITE_OK;
-}
-
-/*
-** Query the hash table for a doclist associated with term pTerm/nTerm.
-*/
-int sqlite3Fts5HashQuery(
- Fts5Hash *pHash, /* Hash table to query */
- const char *pTerm, int nTerm, /* Query term */
- const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */
- int *pnDoclist /* OUT: Size of doclist in bytes */
-){
- unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
- char *zKey = 0;
- Fts5HashEntry *p;
-
- for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
- zKey = fts5EntryKey(p);
- if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
- }
-
- if( p ){
- fts5HashAddPoslistSize(pHash, p);
- *ppDoclist = (const u8*)&zKey[nTerm+1];
- *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
- }else{
- *ppDoclist = 0;
- *pnDoclist = 0;
- }
-
- return SQLITE_OK;
-}
-
-int sqlite3Fts5HashScanInit(
- Fts5Hash *p, /* Hash table to query */
- const char *pTerm, int nTerm /* Query prefix */
-){
- return fts5HashEntrySort(p, pTerm, nTerm, &p->pScan);
-}
-
-void sqlite3Fts5HashScanNext(Fts5Hash *p){
- assert( !sqlite3Fts5HashScanEof(p) );
- p->pScan = p->pScan->pScanNext;
-}
-
-int sqlite3Fts5HashScanEof(Fts5Hash *p){
- return (p->pScan==0);
-}
-
-void sqlite3Fts5HashScanEntry(
- Fts5Hash *pHash,
- const char **pzTerm, /* OUT: term (nul-terminated) */
- const u8 **ppDoclist, /* OUT: pointer to doclist */
- int *pnDoclist /* OUT: size of doclist in bytes */
-){
- Fts5HashEntry *p;
- if( (p = pHash->pScan) ){
- char *zKey = fts5EntryKey(p);
- int nTerm = (int)strlen(zKey);
- fts5HashAddPoslistSize(pHash, p);
- *pzTerm = zKey;
- *ppDoclist = (const u8*)&zKey[nTerm+1];
- *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
- }else{
- *pzTerm = 0;
- *ppDoclist = 0;
- *pnDoclist = 0;
- }
-}
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_index.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_index.c
deleted file mode 100644
index 412a04faca7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_index.c
+++ /dev/null
@@ -1,6505 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-**
-** Low level access to the FTS index stored in the database file. The
-** routines in this file file implement all read and write access to the
-** %_data table. Other parts of the system access this functionality via
-** the interface defined in fts5Int.h.
-*/
-
-
-#include "fts5Int.h"
-
-/*
-** Overview:
-**
-** The %_data table contains all the FTS indexes for an FTS5 virtual table.
-** As well as the main term index, there may be up to 31 prefix indexes.
-** The format is similar to FTS3/4, except that:
-**
-** * all segment b-tree leaf data is stored in fixed size page records
-** (e.g. 1000 bytes). A single doclist may span multiple pages. Care is
-** taken to ensure it is possible to iterate in either direction through
-** the entries in a doclist, or to seek to a specific entry within a
-** doclist, without loading it into memory.
-**
-** * large doclists that span many pages have associated "doclist index"
-** records that contain a copy of the first rowid on each page spanned by
-** the doclist. This is used to speed up seek operations, and merges of
-** large doclists with very small doclists.
-**
-** * extra fields in the "structure record" record the state of ongoing
-** incremental merge operations.
-**
-*/
-
-
-#define FTS5_OPT_WORK_UNIT 1000 /* Number of leaf pages per optimize step */
-#define FTS5_WORK_UNIT 64 /* Number of leaf pages in unit of work */
-
-#define FTS5_MIN_DLIDX_SIZE 4 /* Add dlidx if this many empty pages */
-
-#define FTS5_MAIN_PREFIX '0'
-
-#if FTS5_MAX_PREFIX_INDEXES > 31
-# error "FTS5_MAX_PREFIX_INDEXES is too large"
-#endif
-
-/*
-** Details:
-**
-** The %_data table managed by this module,
-**
-** CREATE TABLE %_data(id INTEGER PRIMARY KEY, block BLOB);
-**
-** , contains the following 5 types of records. See the comments surrounding
-** the FTS5_*_ROWID macros below for a description of how %_data rowids are
-** assigned to each fo them.
-**
-** 1. Structure Records:
-**
-** The set of segments that make up an index - the index structure - are
-** recorded in a single record within the %_data table. The record consists
-** of a single 32-bit configuration cookie value followed by a list of
-** SQLite varints. If the FTS table features more than one index (because
-** there are one or more prefix indexes), it is guaranteed that all share
-** the same cookie value.
-**
-** Immediately following the configuration cookie, the record begins with
-** three varints:
-**
-** + number of levels,
-** + total number of segments on all levels,
-** + value of write counter.
-**
-** Then, for each level from 0 to nMax:
-**
-** + number of input segments in ongoing merge.
-** + total number of segments in level.
-** + for each segment from oldest to newest:
-** + segment id (always > 0)
-** + first leaf page number (often 1, always greater than 0)
-** + final leaf page number
-**
-** 2. The Averages Record:
-**
-** A single record within the %_data table. The data is a list of varints.
-** The first value is the number of rows in the index. Then, for each column
-** from left to right, the total number of tokens in the column for all
-** rows of the table.
-**
-** 3. Segment leaves:
-**
-** TERM/DOCLIST FORMAT:
-**
-** Most of each segment leaf is taken up by term/doclist data. The
-** general format of term/doclist, starting with the first term
-** on the leaf page, is:
-**
-** varint : size of first term
-** blob: first term data
-** doclist: first doclist
-** zero-or-more {
-** varint: number of bytes in common with previous term
-** varint: number of bytes of new term data (nNew)
-** blob: nNew bytes of new term data
-** doclist: next doclist
-** }
-**
-** doclist format:
-**
-** varint: first rowid
-** poslist: first poslist
-** zero-or-more {
-** varint: rowid delta (always > 0)
-** poslist: next poslist
-** }
-**
-** poslist format:
-**
-** varint: size of poslist in bytes multiplied by 2, not including
-** this field. Plus 1 if this entry carries the "delete" flag.
-** collist: collist for column 0
-** zero-or-more {
-** 0x01 byte
-** varint: column number (I)
-** collist: collist for column I
-** }
-**
-** collist format:
-**
-** varint: first offset + 2
-** zero-or-more {
-** varint: offset delta + 2
-** }
-**
-** PAGE FORMAT
-**
-** Each leaf page begins with a 4-byte header containing 2 16-bit
-** unsigned integer fields in big-endian format. They are:
-**
-** * The byte offset of the first rowid on the page, if it exists
-** and occurs before the first term (otherwise 0).
-**
-** * The byte offset of the start of the page footer. If the page
-** footer is 0 bytes in size, then this field is the same as the
-** size of the leaf page in bytes.
-**
-** The page footer consists of a single varint for each term located
-** on the page. Each varint is the byte offset of the current term
-** within the page, delta-compressed against the previous value. In
-** other words, the first varint in the footer is the byte offset of
-** the first term, the second is the byte offset of the second less that
-** of the first, and so on.
-**
-** The term/doclist format described above is accurate if the entire
-** term/doclist data fits on a single leaf page. If this is not the case,
-** the format is changed in two ways:
-**
-** + if the first rowid on a page occurs before the first term, it
-** is stored as a literal value:
-**
-** varint: first rowid
-**
-** + the first term on each page is stored in the same way as the
-** very first term of the segment:
-**
-** varint : size of first term
-** blob: first term data
-**
-** 5. Segment doclist indexes:
-**
-** Doclist indexes are themselves b-trees, however they usually consist of
-** a single leaf record only. The format of each doclist index leaf page
-** is:
-**
-** * Flags byte. Bits are:
-** 0x01: Clear if leaf is also the root page, otherwise set.
-**
-** * Page number of fts index leaf page. As a varint.
-**
-** * First rowid on page indicated by previous field. As a varint.
-**
-** * A list of varints, one for each subsequent termless page. A
-** positive delta if the termless page contains at least one rowid,
-** or an 0x00 byte otherwise.
-**
-** Internal doclist index nodes are:
-**
-** * Flags byte. Bits are:
-** 0x01: Clear for root page, otherwise set.
-**
-** * Page number of first child page. As a varint.
-**
-** * Copy of first rowid on page indicated by previous field. As a varint.
-**
-** * A list of delta-encoded varints - the first rowid on each subsequent
-** child page.
-**
-*/
-
-/*
-** Rowids for the averages and structure records in the %_data table.
-*/
-#define FTS5_AVERAGES_ROWID 1 /* Rowid used for the averages record */
-#define FTS5_STRUCTURE_ROWID 10 /* The structure record */
-
-/*
-** Macros determining the rowids used by segment leaves and dlidx leaves
-** and nodes. All nodes and leaves are stored in the %_data table with large
-** positive rowids.
-**
-** Each segment has a unique non-zero 16-bit id.
-**
-** The rowid for each segment leaf is found by passing the segment id and
-** the leaf page number to the FTS5_SEGMENT_ROWID macro. Leaves are numbered
-** sequentially starting from 1.
-*/
-#define FTS5_DATA_ID_B 16 /* Max seg id number 65535 */
-#define FTS5_DATA_DLI_B 1 /* Doclist-index flag (1 bit) */
-#define FTS5_DATA_HEIGHT_B 5 /* Max dlidx tree height of 32 */
-#define FTS5_DATA_PAGE_B 31 /* Max page number of 2147483648 */
-
-#define fts5_dri(segid, dlidx, height, pgno) ( \
- ((i64)(segid) << (FTS5_DATA_PAGE_B+FTS5_DATA_HEIGHT_B+FTS5_DATA_DLI_B)) + \
- ((i64)(dlidx) << (FTS5_DATA_PAGE_B + FTS5_DATA_HEIGHT_B)) + \
- ((i64)(height) << (FTS5_DATA_PAGE_B)) + \
- ((i64)(pgno)) \
-)
-
-#define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno)
-#define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno)
-
-/*
-** Maximum segments permitted in a single index
-*/
-#define FTS5_MAX_SEGMENT 2000
-
-#ifdef SQLITE_DEBUG
-int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; }
-#endif
-
-
-/*
-** Each time a blob is read from the %_data table, it is padded with this
-** many zero bytes. This makes it easier to decode the various record formats
-** without overreading if the records are corrupt.
-*/
-#define FTS5_DATA_ZERO_PADDING 8
-#define FTS5_DATA_PADDING 20
-
-typedef struct Fts5Data Fts5Data;
-typedef struct Fts5DlidxIter Fts5DlidxIter;
-typedef struct Fts5DlidxLvl Fts5DlidxLvl;
-typedef struct Fts5DlidxWriter Fts5DlidxWriter;
-typedef struct Fts5Iter Fts5Iter;
-typedef struct Fts5PageWriter Fts5PageWriter;
-typedef struct Fts5SegIter Fts5SegIter;
-typedef struct Fts5DoclistIter Fts5DoclistIter;
-typedef struct Fts5SegWriter Fts5SegWriter;
-typedef struct Fts5Structure Fts5Structure;
-typedef struct Fts5StructureLevel Fts5StructureLevel;
-typedef struct Fts5StructureSegment Fts5StructureSegment;
-
-struct Fts5Data {
- u8 *p; /* Pointer to buffer containing record */
- int nn; /* Size of record in bytes */
- int szLeaf; /* Size of leaf without page-index */
-};
-
-/*
-** One object per %_data table.
-*/
-struct Fts5Index {
- Fts5Config *pConfig; /* Virtual table configuration */
- char *zDataTbl; /* Name of %_data table */
- int nWorkUnit; /* Leaf pages in a "unit" of work */
-
- /*
- ** Variables related to the accumulation of tokens and doclists within the
- ** in-memory hash tables before they are flushed to disk.
- */
- Fts5Hash *pHash; /* Hash table for in-memory data */
- int nPendingData; /* Current bytes of pending data */
- i64 iWriteRowid; /* Rowid for current doc being written */
- int bDelete; /* Current write is a delete */
-
- /* Error state. */
- int rc; /* Current error code */
-
- /* State used by the fts5DataXXX() functions. */
- sqlite3_blob *pReader; /* RO incr-blob open on %_data table */
- sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */
- sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */
- sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */
- sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=? */
- sqlite3_stmt *pIdxSelect;
- int nRead; /* Total number of blocks read */
-
- sqlite3_stmt *pDataVersion;
- i64 iStructVersion; /* data_version when pStruct read */
- Fts5Structure *pStruct; /* Current db structure (or NULL) */
-};
-
-struct Fts5DoclistIter {
- u8 *aEof; /* Pointer to 1 byte past end of doclist */
-
- /* Output variables. aPoslist==0 at EOF */
- i64 iRowid;
- u8 *aPoslist;
- int nPoslist;
- int nSize;
-};
-
-/*
-** The contents of the "structure" record for each index are represented
-** using an Fts5Structure record in memory. Which uses instances of the
-** other Fts5StructureXXX types as components.
-*/
-struct Fts5StructureSegment {
- int iSegid; /* Segment id */
- int pgnoFirst; /* First leaf page number in segment */
- int pgnoLast; /* Last leaf page number in segment */
-};
-struct Fts5StructureLevel {
- int nMerge; /* Number of segments in incr-merge */
- int nSeg; /* Total number of segments on level */
- Fts5StructureSegment *aSeg; /* Array of segments. aSeg[0] is oldest. */
-};
-struct Fts5Structure {
- int nRef; /* Object reference count */
- u64 nWriteCounter; /* Total leaves written to level 0 */
- int nSegment; /* Total segments in this structure */
- int nLevel; /* Number of levels in this index */
- Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
-};
-
-/*
-** An object of type Fts5SegWriter is used to write to segments.
-*/
-struct Fts5PageWriter {
- int pgno; /* Page number for this page */
- int iPrevPgidx; /* Previous value written into pgidx */
- Fts5Buffer buf; /* Buffer containing leaf data */
- Fts5Buffer pgidx; /* Buffer containing page-index */
- Fts5Buffer term; /* Buffer containing previous term on page */
-};
-struct Fts5DlidxWriter {
- int pgno; /* Page number for this page */
- int bPrevValid; /* True if iPrev is valid */
- i64 iPrev; /* Previous rowid value written to page */
- Fts5Buffer buf; /* Buffer containing page data */
-};
-struct Fts5SegWriter {
- int iSegid; /* Segid to write to */
- Fts5PageWriter writer; /* PageWriter object */
- i64 iPrevRowid; /* Previous rowid written to current leaf */
- u8 bFirstRowidInDoclist; /* True if next rowid is first in doclist */
- u8 bFirstRowidInPage; /* True if next rowid is first in page */
- /* TODO1: Can use (writer.pgidx.n==0) instead of bFirstTermInPage */
- u8 bFirstTermInPage; /* True if next term will be first in leaf */
- int nLeafWritten; /* Number of leaf pages written */
- int nEmpty; /* Number of contiguous term-less nodes */
-
- int nDlidx; /* Allocated size of aDlidx[] array */
- Fts5DlidxWriter *aDlidx; /* Array of Fts5DlidxWriter objects */
-
- /* Values to insert into the %_idx table */
- Fts5Buffer btterm; /* Next term to insert into %_idx table */
- int iBtPage; /* Page number corresponding to btterm */
-};
-
-typedef struct Fts5CResult Fts5CResult;
-struct Fts5CResult {
- u16 iFirst; /* aSeg[] index of firstest iterator */
- u8 bTermEq; /* True if the terms are equal */
-};
-
-/*
-** Object for iterating through a single segment, visiting each term/rowid
-** pair in the segment.
-**
-** pSeg:
-** The segment to iterate through.
-**
-** iLeafPgno:
-** Current leaf page number within segment.
-**
-** iLeafOffset:
-** Byte offset within the current leaf that is the first byte of the
-** position list data (one byte passed the position-list size field).
-** rowid field of the current entry. Usually this is the size field of the
-** position list data. The exception is if the rowid for the current entry
-** is the last thing on the leaf page.
-**
-** pLeaf:
-** Buffer containing current leaf page data. Set to NULL at EOF.
-**
-** iTermLeafPgno, iTermLeafOffset:
-** Leaf page number containing the last term read from the segment. And
-** the offset immediately following the term data.
-**
-** flags:
-** Mask of FTS5_SEGITER_XXX values. Interpreted as follows:
-**
-** FTS5_SEGITER_ONETERM:
-** If set, set the iterator to point to EOF after the current doclist
-** has been exhausted. Do not proceed to the next term in the segment.
-**
-** FTS5_SEGITER_REVERSE:
-** This flag is only ever set if FTS5_SEGITER_ONETERM is also set. If
-** it is set, iterate through rowid in descending order instead of the
-** default ascending order.
-**
-** iRowidOffset/nRowidOffset/aRowidOffset:
-** These are used if the FTS5_SEGITER_REVERSE flag is set.
-**
-** For each rowid on the page corresponding to the current term, the
-** corresponding aRowidOffset[] entry is set to the byte offset of the
-** start of the "position-list-size" field within the page.
-**
-** iTermIdx:
-** Index of current term on iTermLeafPgno.
-*/
-struct Fts5SegIter {
- Fts5StructureSegment *pSeg; /* Segment to iterate through */
- int flags; /* Mask of configuration flags */
- int iLeafPgno; /* Current leaf page number */
- Fts5Data *pLeaf; /* Current leaf data */
- Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
- int iLeafOffset; /* Byte offset within current leaf */
-
- /* Next method */
- void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
-
- /* The page and offset from which the current term was read. The offset
- ** is the offset of the first rowid in the current doclist. */
- int iTermLeafPgno;
- int iTermLeafOffset;
-
- int iPgidxOff; /* Next offset in pgidx */
- int iEndofDoclist;
-
- /* The following are only used if the FTS5_SEGITER_REVERSE flag is set. */
- int iRowidOffset; /* Current entry in aRowidOffset[] */
- int nRowidOffset; /* Allocated size of aRowidOffset[] array */
- int *aRowidOffset; /* Array of offset to rowid fields */
-
- Fts5DlidxIter *pDlidx; /* If there is a doclist-index */
-
- /* Variables populated based on current entry. */
- Fts5Buffer term; /* Current term */
- i64 iRowid; /* Current rowid */
- int nPos; /* Number of bytes in current position list */
- u8 bDel; /* True if the delete flag is set */
-};
-
-/*
-** Argument is a pointer to an Fts5Data structure that contains a
-** leaf page.
-*/
-#define ASSERT_SZLEAF_OK(x) assert( \
- (x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \
-)
-
-#define FTS5_SEGITER_ONETERM 0x01
-#define FTS5_SEGITER_REVERSE 0x02
-
-/*
-** Argument is a pointer to an Fts5Data structure that contains a leaf
-** page. This macro evaluates to true if the leaf contains no terms, or
-** false if it contains at least one term.
-*/
-#define fts5LeafIsTermless(x) ((x)->szLeaf >= (x)->nn)
-
-#define fts5LeafTermOff(x, i) (fts5GetU16(&(x)->p[(x)->szLeaf + (i)*2]))
-
-#define fts5LeafFirstRowidOff(x) (fts5GetU16((x)->p))
-
-/*
-** Object for iterating through the merged results of one or more segments,
-** visiting each term/rowid pair in the merged data.
-**
-** nSeg is always a power of two greater than or equal to the number of
-** segments that this object is merging data from. Both the aSeg[] and
-** aFirst[] arrays are sized at nSeg entries. The aSeg[] array is padded
-** with zeroed objects - these are handled as if they were iterators opened
-** on empty segments.
-**
-** The results of comparing segments aSeg[N] and aSeg[N+1], where N is an
-** even number, is stored in aFirst[(nSeg+N)/2]. The "result" of the
-** comparison in this context is the index of the iterator that currently
-** points to the smaller term/rowid combination. Iterators at EOF are
-** considered to be greater than all other iterators.
-**
-** aFirst[1] contains the index in aSeg[] of the iterator that points to
-** the smallest key overall. aFirst[0] is unused.
-**
-** poslist:
-** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
-** There is no way to tell if this is populated or not.
-*/
-struct Fts5Iter {
- Fts5IndexIter base; /* Base class containing output vars */
-
- Fts5Index *pIndex; /* Index that owns this iterator */
- Fts5Structure *pStruct; /* Database structure for this iterator */
- Fts5Buffer poslist; /* Buffer containing current poslist */
- Fts5Colset *pColset; /* Restrict matches to these columns */
-
- /* Invoked to set output variables. */
- void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*);
-
- int nSeg; /* Size of aSeg[] array */
- int bRev; /* True to iterate in reverse order */
- u8 bSkipEmpty; /* True to skip deleted entries */
-
- i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
- Fts5CResult *aFirst; /* Current merge state (see above) */
- Fts5SegIter aSeg[1]; /* Array of segment iterators */
-};
-
-
-/*
-** An instance of the following type is used to iterate through the contents
-** of a doclist-index record.
-**
-** pData:
-** Record containing the doclist-index data.
-**
-** bEof:
-** Set to true once iterator has reached EOF.
-**
-** iOff:
-** Set to the current offset within record pData.
-*/
-struct Fts5DlidxLvl {
- Fts5Data *pData; /* Data for current page of this level */
- int iOff; /* Current offset into pData */
- int bEof; /* At EOF already */
- int iFirstOff; /* Used by reverse iterators */
-
- /* Output variables */
- int iLeafPgno; /* Page number of current leaf page */
- i64 iRowid; /* First rowid on leaf iLeafPgno */
-};
-struct Fts5DlidxIter {
- int nLvl;
- int iSegid;
- Fts5DlidxLvl aLvl[1];
-};
-
-static void fts5PutU16(u8 *aOut, u16 iVal){
- aOut[0] = (iVal>>8);
- aOut[1] = (iVal&0xFF);
-}
-
-static u16 fts5GetU16(const u8 *aIn){
- return ((u16)aIn[0] << 8) + aIn[1];
-}
-
-/*
-** Allocate and return a buffer at least nByte bytes in size.
-**
-** If an OOM error is encountered, return NULL and set the error code in
-** the Fts5Index handle passed as the first argument.
-*/
-static void *fts5IdxMalloc(Fts5Index *p, int nByte){
- return sqlite3Fts5MallocZero(&p->rc, nByte);
-}
-
-/*
-** Compare the contents of the pLeft buffer with the pRight/nRight blob.
-**
-** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
-** +ve if pRight is smaller than pLeft. In other words:
-**
-** res = *pLeft - *pRight
-*/
-#ifdef SQLITE_DEBUG
-static int fts5BufferCompareBlob(
- Fts5Buffer *pLeft, /* Left hand side of comparison */
- const u8 *pRight, int nRight /* Right hand side of comparison */
-){
- int nCmp = MIN(pLeft->n, nRight);
- int res = memcmp(pLeft->p, pRight, nCmp);
- return (res==0 ? (pLeft->n - nRight) : res);
-}
-#endif
-
-/*
-** Compare the contents of the two buffers using memcmp(). If one buffer
-** is a prefix of the other, it is considered the lesser.
-**
-** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
-** +ve if pRight is smaller than pLeft. In other words:
-**
-** res = *pLeft - *pRight
-*/
-static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
- int nCmp = MIN(pLeft->n, pRight->n);
- int res = memcmp(pLeft->p, pRight->p, nCmp);
- return (res==0 ? (pLeft->n - pRight->n) : res);
-}
-
-static int fts5LeafFirstTermOff(Fts5Data *pLeaf){
- int ret;
- fts5GetVarint32(&pLeaf->p[pLeaf->szLeaf], ret);
- return ret;
-}
-
-/*
-** Close the read-only blob handle, if it is open.
-*/
-static void fts5CloseReader(Fts5Index *p){
- if( p->pReader ){
- sqlite3_blob *pReader = p->pReader;
- p->pReader = 0;
- sqlite3_blob_close(pReader);
- }
-}
-
-/*
-** Retrieve a record from the %_data table.
-**
-** If an error occurs, NULL is returned and an error left in the
-** Fts5Index object.
-*/
-static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
- Fts5Data *pRet = 0;
- if( p->rc==SQLITE_OK ){
- int rc = SQLITE_OK;
-
- if( p->pReader ){
- /* This call may return SQLITE_ABORT if there has been a savepoint
- ** rollback since it was last used. In this case a new blob handle
- ** is required. */
- sqlite3_blob *pBlob = p->pReader;
- p->pReader = 0;
- rc = sqlite3_blob_reopen(pBlob, iRowid);
- assert( p->pReader==0 );
- p->pReader = pBlob;
- if( rc!=SQLITE_OK ){
- fts5CloseReader(p);
- }
- if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
- }
-
- /* If the blob handle is not open at this point, open it and seek
- ** to the requested entry. */
- if( p->pReader==0 && rc==SQLITE_OK ){
- Fts5Config *pConfig = p->pConfig;
- rc = sqlite3_blob_open(pConfig->db,
- pConfig->zDb, p->zDataTbl, "block", iRowid, 0, &p->pReader
- );
- }
-
- /* If either of the sqlite3_blob_open() or sqlite3_blob_reopen() calls
- ** above returned SQLITE_ERROR, return SQLITE_CORRUPT_VTAB instead.
- ** All the reasons those functions might return SQLITE_ERROR - missing
- ** table, missing row, non-blob/text in block column - indicate
- ** backing store corruption. */
- if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT;
-
- if( rc==SQLITE_OK ){
- u8 *aOut = 0; /* Read blob data into this buffer */
- int nByte = sqlite3_blob_bytes(p->pReader);
- int nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
- pRet = (Fts5Data*)sqlite3_malloc(nAlloc);
- if( pRet ){
- pRet->nn = nByte;
- aOut = pRet->p = (u8*)&pRet[1];
- }else{
- rc = SQLITE_NOMEM;
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_blob_read(p->pReader, aOut, nByte, 0);
- }
- if( rc!=SQLITE_OK ){
- sqlite3_free(pRet);
- pRet = 0;
- }else{
- /* TODO1: Fix this */
- pRet->szLeaf = fts5GetU16(&pRet->p[2]);
- }
- }
- p->rc = rc;
- p->nRead++;
- }
-
- assert( (pRet==0)==(p->rc!=SQLITE_OK) );
- return pRet;
-}
-
-/*
-** Release a reference to data record returned by an earlier call to
-** fts5DataRead().
-*/
-static void fts5DataRelease(Fts5Data *pData){
- sqlite3_free(pData);
-}
-
-static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
- Fts5Data *pRet = fts5DataRead(p, iRowid);
- if( pRet ){
- if( pRet->szLeaf>pRet->nn ){
- p->rc = FTS5_CORRUPT;
- fts5DataRelease(pRet);
- pRet = 0;
- }
- }
- return pRet;
-}
-
-static int fts5IndexPrepareStmt(
- Fts5Index *p,
- sqlite3_stmt **ppStmt,
- char *zSql
-){
- if( p->rc==SQLITE_OK ){
- if( zSql ){
- p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
- SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
- }else{
- p->rc = SQLITE_NOMEM;
- }
- }
- sqlite3_free(zSql);
- return p->rc;
-}
-
-
-/*
-** INSERT OR REPLACE a record into the %_data table.
-*/
-static void fts5DataWrite(Fts5Index *p, i64 iRowid, const u8 *pData, int nData){
- if( p->rc!=SQLITE_OK ) return;
-
- if( p->pWriter==0 ){
- Fts5Config *pConfig = p->pConfig;
- fts5IndexPrepareStmt(p, &p->pWriter, sqlite3_mprintf(
- "REPLACE INTO '%q'.'%q_data'(id, block) VALUES(?,?)",
- pConfig->zDb, pConfig->zName
- ));
- if( p->rc ) return;
- }
-
- sqlite3_bind_int64(p->pWriter, 1, iRowid);
- sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC);
- sqlite3_step(p->pWriter);
- p->rc = sqlite3_reset(p->pWriter);
- sqlite3_bind_null(p->pWriter, 2);
-}
-
-/*
-** Execute the following SQL:
-**
-** DELETE FROM %_data WHERE id BETWEEN $iFirst AND $iLast
-*/
-static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
- if( p->rc!=SQLITE_OK ) return;
-
- if( p->pDeleter==0 ){
- int rc;
- Fts5Config *pConfig = p->pConfig;
- char *zSql = sqlite3_mprintf(
- "DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?",
- pConfig->zDb, pConfig->zName
- );
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
- SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
- sqlite3_free(zSql);
- }
- if( rc!=SQLITE_OK ){
- p->rc = rc;
- return;
- }
- }
-
- sqlite3_bind_int64(p->pDeleter, 1, iFirst);
- sqlite3_bind_int64(p->pDeleter, 2, iLast);
- sqlite3_step(p->pDeleter);
- p->rc = sqlite3_reset(p->pDeleter);
-}
-
-/*
-** Remove all records associated with segment iSegid.
-*/
-static void fts5DataRemoveSegment(Fts5Index *p, int iSegid){
- i64 iFirst = FTS5_SEGMENT_ROWID(iSegid, 0);
- i64 iLast = FTS5_SEGMENT_ROWID(iSegid+1, 0)-1;
- fts5DataDelete(p, iFirst, iLast);
- if( p->pIdxDeleter==0 ){
- Fts5Config *pConfig = p->pConfig;
- fts5IndexPrepareStmt(p, &p->pIdxDeleter, sqlite3_mprintf(
- "DELETE FROM '%q'.'%q_idx' WHERE segid=?",
- pConfig->zDb, pConfig->zName
- ));
- }
- if( p->rc==SQLITE_OK ){
- sqlite3_bind_int(p->pIdxDeleter, 1, iSegid);
- sqlite3_step(p->pIdxDeleter);
- p->rc = sqlite3_reset(p->pIdxDeleter);
- }
-}
-
-/*
-** Release a reference to an Fts5Structure object returned by an earlier
-** call to fts5StructureRead() or fts5StructureDecode().
-*/
-static void fts5StructureRelease(Fts5Structure *pStruct){
- if( pStruct && 0>=(--pStruct->nRef) ){
- int i;
- assert( pStruct->nRef==0 );
- for(i=0; i<pStruct->nLevel; i++){
- sqlite3_free(pStruct->aLevel[i].aSeg);
- }
- sqlite3_free(pStruct);
- }
-}
-
-static void fts5StructureRef(Fts5Structure *pStruct){
- pStruct->nRef++;
-}
-
-/*
-** Deserialize and return the structure record currently stored in serialized
-** form within buffer pData/nData.
-**
-** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array
-** are over-allocated by one slot. This allows the structure contents
-** to be more easily edited.
-**
-** If an error occurs, *ppOut is set to NULL and an SQLite error code
-** returned. Otherwise, *ppOut is set to point to the new object and
-** SQLITE_OK returned.
-*/
-static int fts5StructureDecode(
- const u8 *pData, /* Buffer containing serialized structure */
- int nData, /* Size of buffer pData in bytes */
- int *piCookie, /* Configuration cookie value */
- Fts5Structure **ppOut /* OUT: Deserialized object */
-){
- int rc = SQLITE_OK;
- int i = 0;
- int iLvl;
- int nLevel = 0;
- int nSegment = 0;
- int nByte; /* Bytes of space to allocate at pRet */
- Fts5Structure *pRet = 0; /* Structure object to return */
-
- /* Grab the cookie value */
- if( piCookie ) *piCookie = sqlite3Fts5Get32(pData);
- i = 4;
-
- /* Read the total number of levels and segments from the start of the
- ** structure record. */
- i += fts5GetVarint32(&pData[i], nLevel);
- i += fts5GetVarint32(&pData[i], nSegment);
- nByte = (
- sizeof(Fts5Structure) + /* Main structure */
- sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
- );
- pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
-
- if( pRet ){
- pRet->nRef = 1;
- pRet->nLevel = nLevel;
- pRet->nSegment = nSegment;
- i += sqlite3Fts5GetVarint(&pData[i], &pRet->nWriteCounter);
-
- for(iLvl=0; rc==SQLITE_OK && iLvl<nLevel; iLvl++){
- Fts5StructureLevel *pLvl = &pRet->aLevel[iLvl];
- int nTotal = 0;
- int iSeg;
-
- if( i>=nData ){
- rc = FTS5_CORRUPT;
- }else{
- i += fts5GetVarint32(&pData[i], pLvl->nMerge);
- i += fts5GetVarint32(&pData[i], nTotal);
- assert( nTotal>=pLvl->nMerge );
- pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
- nTotal * sizeof(Fts5StructureSegment)
- );
- }
-
- if( rc==SQLITE_OK ){
- pLvl->nSeg = nTotal;
- for(iSeg=0; iSeg<nTotal; iSeg++){
- if( i>=nData ){
- rc = FTS5_CORRUPT;
- break;
- }
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid);
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst);
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast);
- }
- }
- }
- if( rc!=SQLITE_OK ){
- fts5StructureRelease(pRet);
- pRet = 0;
- }
- }
-
- *ppOut = pRet;
- return rc;
-}
-
-/*
-**
-*/
-static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
- if( *pRc==SQLITE_OK ){
- Fts5Structure *pStruct = *ppStruct;
- int nLevel = pStruct->nLevel;
- int nByte = (
- sizeof(Fts5Structure) + /* Main structure */
- sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
- );
-
- pStruct = sqlite3_realloc(pStruct, nByte);
- if( pStruct ){
- memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
- pStruct->nLevel++;
- *ppStruct = pStruct;
- }else{
- *pRc = SQLITE_NOMEM;
- }
- }
-}
-
-/*
-** Extend level iLvl so that there is room for at least nExtra more
-** segments.
-*/
-static void fts5StructureExtendLevel(
- int *pRc,
- Fts5Structure *pStruct,
- int iLvl,
- int nExtra,
- int bInsert
-){
- if( *pRc==SQLITE_OK ){
- Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
- Fts5StructureSegment *aNew;
- int nByte;
-
- nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment);
- aNew = sqlite3_realloc(pLvl->aSeg, nByte);
- if( aNew ){
- if( bInsert==0 ){
- memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra);
- }else{
- int nMove = pLvl->nSeg * sizeof(Fts5StructureSegment);
- memmove(&aNew[nExtra], aNew, nMove);
- memset(aNew, 0, sizeof(Fts5StructureSegment) * nExtra);
- }
- pLvl->aSeg = aNew;
- }else{
- *pRc = SQLITE_NOMEM;
- }
- }
-}
-
-static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){
- Fts5Structure *pRet = 0;
- Fts5Config *pConfig = p->pConfig;
- int iCookie; /* Configuration cookie */
- Fts5Data *pData;
-
- pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID);
- if( p->rc==SQLITE_OK ){
- /* TODO: Do we need this if the leaf-index is appended? Probably... */
- memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING);
- p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet);
- if( p->rc==SQLITE_OK && pConfig->iCookie!=iCookie ){
- p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie);
- }
- fts5DataRelease(pData);
- if( p->rc!=SQLITE_OK ){
- fts5StructureRelease(pRet);
- pRet = 0;
- }
- }
-
- return pRet;
-}
-
-static i64 fts5IndexDataVersion(Fts5Index *p){
- i64 iVersion = 0;
-
- if( p->rc==SQLITE_OK ){
- if( p->pDataVersion==0 ){
- p->rc = fts5IndexPrepareStmt(p, &p->pDataVersion,
- sqlite3_mprintf("PRAGMA %Q.data_version", p->pConfig->zDb)
- );
- if( p->rc ) return 0;
- }
-
- if( SQLITE_ROW==sqlite3_step(p->pDataVersion) ){
- iVersion = sqlite3_column_int64(p->pDataVersion, 0);
- }
- p->rc = sqlite3_reset(p->pDataVersion);
- }
-
- return iVersion;
-}
-
-/*
-** Read, deserialize and return the structure record.
-**
-** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array
-** are over-allocated as described for function fts5StructureDecode()
-** above.
-**
-** If an error occurs, NULL is returned and an error code left in the
-** Fts5Index handle. If an error has already occurred when this function
-** is called, it is a no-op.
-*/
-static Fts5Structure *fts5StructureRead(Fts5Index *p){
-
- if( p->pStruct==0 ){
- p->iStructVersion = fts5IndexDataVersion(p);
- if( p->rc==SQLITE_OK ){
- p->pStruct = fts5StructureReadUncached(p);
- }
- }
-
-#if 0
- else{
- Fts5Structure *pTest = fts5StructureReadUncached(p);
- if( pTest ){
- int i, j;
- assert_nc( p->pStruct->nSegment==pTest->nSegment );
- assert_nc( p->pStruct->nLevel==pTest->nLevel );
- for(i=0; i<pTest->nLevel; i++){
- assert_nc( p->pStruct->aLevel[i].nMerge==pTest->aLevel[i].nMerge );
- assert_nc( p->pStruct->aLevel[i].nSeg==pTest->aLevel[i].nSeg );
- for(j=0; j<pTest->aLevel[i].nSeg; j++){
- Fts5StructureSegment *p1 = &pTest->aLevel[i].aSeg[j];
- Fts5StructureSegment *p2 = &p->pStruct->aLevel[i].aSeg[j];
- assert_nc( p1->iSegid==p2->iSegid );
- assert_nc( p1->pgnoFirst==p2->pgnoFirst );
- assert_nc( p1->pgnoLast==p2->pgnoLast );
- }
- }
- fts5StructureRelease(pTest);
- }
- }
-#endif
-
- if( p->rc!=SQLITE_OK ) return 0;
- assert( p->iStructVersion!=0 );
- assert( p->pStruct!=0 );
- fts5StructureRef(p->pStruct);
- return p->pStruct;
-}
-
-static void fts5StructureInvalidate(Fts5Index *p){
- if( p->pStruct ){
- fts5StructureRelease(p->pStruct);
- p->pStruct = 0;
- }
-}
-
-/*
-** Return the total number of segments in index structure pStruct. This
-** function is only ever used as part of assert() conditions.
-*/
-#ifdef SQLITE_DEBUG
-static int fts5StructureCountSegments(Fts5Structure *pStruct){
- int nSegment = 0; /* Total number of segments */
- if( pStruct ){
- int iLvl; /* Used to iterate through levels */
- for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
- nSegment += pStruct->aLevel[iLvl].nSeg;
- }
- }
-
- return nSegment;
-}
-#endif
-
-#define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) { \
- assert( (pBuf)->nSpace>=((pBuf)->n+nBlob) ); \
- memcpy(&(pBuf)->p[(pBuf)->n], pBlob, nBlob); \
- (pBuf)->n += nBlob; \
-}
-
-#define fts5BufferSafeAppendVarint(pBuf, iVal) { \
- (pBuf)->n += sqlite3Fts5PutVarint(&(pBuf)->p[(pBuf)->n], (iVal)); \
- assert( (pBuf)->nSpace>=(pBuf)->n ); \
-}
-
-
-/*
-** Serialize and store the "structure" record.
-**
-** If an error occurs, leave an error code in the Fts5Index object. If an
-** error has already occurred, this function is a no-op.
-*/
-static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){
- if( p->rc==SQLITE_OK ){
- Fts5Buffer buf; /* Buffer to serialize record into */
- int iLvl; /* Used to iterate through levels */
- int iCookie; /* Cookie value to store */
-
- assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
- memset(&buf, 0, sizeof(Fts5Buffer));
-
- /* Append the current configuration cookie */
- iCookie = p->pConfig->iCookie;
- if( iCookie<0 ) iCookie = 0;
-
- if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, 4+9+9+9) ){
- sqlite3Fts5Put32(buf.p, iCookie);
- buf.n = 4;
- fts5BufferSafeAppendVarint(&buf, pStruct->nLevel);
- fts5BufferSafeAppendVarint(&buf, pStruct->nSegment);
- fts5BufferSafeAppendVarint(&buf, (i64)pStruct->nWriteCounter);
- }
-
- for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
- int iSeg; /* Used to iterate through segments */
- Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
- fts5BufferAppendVarint(&p->rc, &buf, pLvl->nMerge);
- fts5BufferAppendVarint(&p->rc, &buf, pLvl->nSeg);
- assert( pLvl->nMerge<=pLvl->nSeg );
-
- for(iSeg=0; iSeg<pLvl->nSeg; iSeg++){
- fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].iSegid);
- fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoFirst);
- fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoLast);
- }
- }
-
- fts5DataWrite(p, FTS5_STRUCTURE_ROWID, buf.p, buf.n);
- fts5BufferFree(&buf);
- }
-}
-
-#if 0
-static void fts5DebugStructure(int*,Fts5Buffer*,Fts5Structure*);
-static void fts5PrintStructure(const char *zCaption, Fts5Structure *pStruct){
- int rc = SQLITE_OK;
- Fts5Buffer buf;
- memset(&buf, 0, sizeof(buf));
- fts5DebugStructure(&rc, &buf, pStruct);
- fprintf(stdout, "%s: %s\n", zCaption, buf.p);
- fflush(stdout);
- fts5BufferFree(&buf);
-}
-#else
-# define fts5PrintStructure(x,y)
-#endif
-
-static int fts5SegmentSize(Fts5StructureSegment *pSeg){
- return 1 + pSeg->pgnoLast - pSeg->pgnoFirst;
-}
-
-/*
-** Return a copy of index structure pStruct. Except, promote as many
-** segments as possible to level iPromote. If an OOM occurs, NULL is
-** returned.
-*/
-static void fts5StructurePromoteTo(
- Fts5Index *p,
- int iPromote,
- int szPromote,
- Fts5Structure *pStruct
-){
- int il, is;
- Fts5StructureLevel *pOut = &pStruct->aLevel[iPromote];
-
- if( pOut->nMerge==0 ){
- for(il=iPromote+1; il<pStruct->nLevel; il++){
- Fts5StructureLevel *pLvl = &pStruct->aLevel[il];
- if( pLvl->nMerge ) return;
- for(is=pLvl->nSeg-1; is>=0; is--){
- int sz = fts5SegmentSize(&pLvl->aSeg[is]);
- if( sz>szPromote ) return;
- fts5StructureExtendLevel(&p->rc, pStruct, iPromote, 1, 1);
- if( p->rc ) return;
- memcpy(pOut->aSeg, &pLvl->aSeg[is], sizeof(Fts5StructureSegment));
- pOut->nSeg++;
- pLvl->nSeg--;
- }
- }
- }
-}
-
-/*
-** A new segment has just been written to level iLvl of index structure
-** pStruct. This function determines if any segments should be promoted
-** as a result. Segments are promoted in two scenarios:
-**
-** a) If the segment just written is smaller than one or more segments
-** within the previous populated level, it is promoted to the previous
-** populated level.
-**
-** b) If the segment just written is larger than the newest segment on
-** the next populated level, then that segment, and any other adjacent
-** segments that are also smaller than the one just written, are
-** promoted.
-**
-** If one or more segments are promoted, the structure object is updated
-** to reflect this.
-*/
-static void fts5StructurePromote(
- Fts5Index *p, /* FTS5 backend object */
- int iLvl, /* Index level just updated */
- Fts5Structure *pStruct /* Index structure */
-){
- if( p->rc==SQLITE_OK ){
- int iTst;
- int iPromote = -1;
- int szPromote = 0; /* Promote anything this size or smaller */
- Fts5StructureSegment *pSeg; /* Segment just written */
- int szSeg; /* Size of segment just written */
- int nSeg = pStruct->aLevel[iLvl].nSeg;
-
- if( nSeg==0 ) return;
- pSeg = &pStruct->aLevel[iLvl].aSeg[pStruct->aLevel[iLvl].nSeg-1];
- szSeg = (1 + pSeg->pgnoLast - pSeg->pgnoFirst);
-
- /* Check for condition (a) */
- for(iTst=iLvl-1; iTst>=0 && pStruct->aLevel[iTst].nSeg==0; iTst--);
- if( iTst>=0 ){
- int i;
- int szMax = 0;
- Fts5StructureLevel *pTst = &pStruct->aLevel[iTst];
- assert( pTst->nMerge==0 );
- for(i=0; i<pTst->nSeg; i++){
- int sz = pTst->aSeg[i].pgnoLast - pTst->aSeg[i].pgnoFirst + 1;
- if( sz>szMax ) szMax = sz;
- }
- if( szMax>=szSeg ){
- /* Condition (a) is true. Promote the newest segment on level
- ** iLvl to level iTst. */
- iPromote = iTst;
- szPromote = szMax;
- }
- }
-
- /* If condition (a) is not met, assume (b) is true. StructurePromoteTo()
- ** is a no-op if it is not. */
- if( iPromote<0 ){
- iPromote = iLvl;
- szPromote = szSeg;
- }
- fts5StructurePromoteTo(p, iPromote, szPromote, pStruct);
- }
-}
-
-
-/*
-** Advance the iterator passed as the only argument. If the end of the
-** doclist-index page is reached, return non-zero.
-*/
-static int fts5DlidxLvlNext(Fts5DlidxLvl *pLvl){
- Fts5Data *pData = pLvl->pData;
-
- if( pLvl->iOff==0 ){
- assert( pLvl->bEof==0 );
- pLvl->iOff = 1;
- pLvl->iOff += fts5GetVarint32(&pData->p[1], pLvl->iLeafPgno);
- pLvl->iOff += fts5GetVarint(&pData->p[pLvl->iOff], (u64*)&pLvl->iRowid);
- pLvl->iFirstOff = pLvl->iOff;
- }else{
- int iOff;
- for(iOff=pLvl->iOff; iOff<pData->nn; iOff++){
- if( pData->p[iOff] ) break;
- }
-
- if( iOff<pData->nn ){
- i64 iVal;
- pLvl->iLeafPgno += (iOff - pLvl->iOff) + 1;
- iOff += fts5GetVarint(&pData->p[iOff], (u64*)&iVal);
- pLvl->iRowid += iVal;
- pLvl->iOff = iOff;
- }else{
- pLvl->bEof = 1;
- }
- }
-
- return pLvl->bEof;
-}
-
-/*
-** Advance the iterator passed as the only argument.
-*/
-static int fts5DlidxIterNextR(Fts5Index *p, Fts5DlidxIter *pIter, int iLvl){
- Fts5DlidxLvl *pLvl = &pIter->aLvl[iLvl];
-
- assert( iLvl<pIter->nLvl );
- if( fts5DlidxLvlNext(pLvl) ){
- if( (iLvl+1) < pIter->nLvl ){
- fts5DlidxIterNextR(p, pIter, iLvl+1);
- if( pLvl[1].bEof==0 ){
- fts5DataRelease(pLvl->pData);
- memset(pLvl, 0, sizeof(Fts5DlidxLvl));
- pLvl->pData = fts5DataRead(p,
- FTS5_DLIDX_ROWID(pIter->iSegid, iLvl, pLvl[1].iLeafPgno)
- );
- if( pLvl->pData ) fts5DlidxLvlNext(pLvl);
- }
- }
- }
-
- return pIter->aLvl[0].bEof;
-}
-static int fts5DlidxIterNext(Fts5Index *p, Fts5DlidxIter *pIter){
- return fts5DlidxIterNextR(p, pIter, 0);
-}
-
-/*
-** The iterator passed as the first argument has the following fields set
-** as follows. This function sets up the rest of the iterator so that it
-** points to the first rowid in the doclist-index.
-**
-** pData:
-** pointer to doclist-index record,
-**
-** When this function is called pIter->iLeafPgno is the page number the
-** doclist is associated with (the one featuring the term).
-*/
-static int fts5DlidxIterFirst(Fts5DlidxIter *pIter){
- int i;
- for(i=0; i<pIter->nLvl; i++){
- fts5DlidxLvlNext(&pIter->aLvl[i]);
- }
- return pIter->aLvl[0].bEof;
-}
-
-
-static int fts5DlidxIterEof(Fts5Index *p, Fts5DlidxIter *pIter){
- return p->rc!=SQLITE_OK || pIter->aLvl[0].bEof;
-}
-
-static void fts5DlidxIterLast(Fts5Index *p, Fts5DlidxIter *pIter){
- int i;
-
- /* Advance each level to the last entry on the last page */
- for(i=pIter->nLvl-1; p->rc==SQLITE_OK && i>=0; i--){
- Fts5DlidxLvl *pLvl = &pIter->aLvl[i];
- while( fts5DlidxLvlNext(pLvl)==0 );
- pLvl->bEof = 0;
-
- if( i>0 ){
- Fts5DlidxLvl *pChild = &pLvl[-1];
- fts5DataRelease(pChild->pData);
- memset(pChild, 0, sizeof(Fts5DlidxLvl));
- pChild->pData = fts5DataRead(p,
- FTS5_DLIDX_ROWID(pIter->iSegid, i-1, pLvl->iLeafPgno)
- );
- }
- }
-}
-
-/*
-** Move the iterator passed as the only argument to the previous entry.
-*/
-static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){
- int iOff = pLvl->iOff;
-
- assert( pLvl->bEof==0 );
- if( iOff<=pLvl->iFirstOff ){
- pLvl->bEof = 1;
- }else{
- u8 *a = pLvl->pData->p;
- i64 iVal;
- int iLimit;
- int ii;
- int nZero = 0;
-
- /* Currently iOff points to the first byte of a varint. This block
- ** decrements iOff until it points to the first byte of the previous
- ** varint. Taking care not to read any memory locations that occur
- ** before the buffer in memory. */
- iLimit = (iOff>9 ? iOff-9 : 0);
- for(iOff--; iOff>iLimit; iOff--){
- if( (a[iOff-1] & 0x80)==0 ) break;
- }
-
- fts5GetVarint(&a[iOff], (u64*)&iVal);
- pLvl->iRowid -= iVal;
- pLvl->iLeafPgno--;
-
- /* Skip backwards past any 0x00 varints. */
- for(ii=iOff-1; ii>=pLvl->iFirstOff && a[ii]==0x00; ii--){
- nZero++;
- }
- if( ii>=pLvl->iFirstOff && (a[ii] & 0x80) ){
- /* The byte immediately before the last 0x00 byte has the 0x80 bit
- ** set. So the last 0x00 is only a varint 0 if there are 8 more 0x80
- ** bytes before a[ii]. */
- int bZero = 0; /* True if last 0x00 counts */
- if( (ii-8)>=pLvl->iFirstOff ){
- int j;
- for(j=1; j<=8 && (a[ii-j] & 0x80); j++);
- bZero = (j>8);
- }
- if( bZero==0 ) nZero--;
- }
- pLvl->iLeafPgno -= nZero;
- pLvl->iOff = iOff - nZero;
- }
-
- return pLvl->bEof;
-}
-
-static int fts5DlidxIterPrevR(Fts5Index *p, Fts5DlidxIter *pIter, int iLvl){
- Fts5DlidxLvl *pLvl = &pIter->aLvl[iLvl];
-
- assert( iLvl<pIter->nLvl );
- if( fts5DlidxLvlPrev(pLvl) ){
- if( (iLvl+1) < pIter->nLvl ){
- fts5DlidxIterPrevR(p, pIter, iLvl+1);
- if( pLvl[1].bEof==0 ){
- fts5DataRelease(pLvl->pData);
- memset(pLvl, 0, sizeof(Fts5DlidxLvl));
- pLvl->pData = fts5DataRead(p,
- FTS5_DLIDX_ROWID(pIter->iSegid, iLvl, pLvl[1].iLeafPgno)
- );
- if( pLvl->pData ){
- while( fts5DlidxLvlNext(pLvl)==0 );
- pLvl->bEof = 0;
- }
- }
- }
- }
-
- return pIter->aLvl[0].bEof;
-}
-static int fts5DlidxIterPrev(Fts5Index *p, Fts5DlidxIter *pIter){
- return fts5DlidxIterPrevR(p, pIter, 0);
-}
-
-/*
-** Free a doclist-index iterator object allocated by fts5DlidxIterInit().
-*/
-static void fts5DlidxIterFree(Fts5DlidxIter *pIter){
- if( pIter ){
- int i;
- for(i=0; i<pIter->nLvl; i++){
- fts5DataRelease(pIter->aLvl[i].pData);
- }
- sqlite3_free(pIter);
- }
-}
-
-static Fts5DlidxIter *fts5DlidxIterInit(
- Fts5Index *p, /* Fts5 Backend to iterate within */
- int bRev, /* True for ORDER BY ASC */
- int iSegid, /* Segment id */
- int iLeafPg /* Leaf page number to load dlidx for */
-){
- Fts5DlidxIter *pIter = 0;
- int i;
- int bDone = 0;
-
- for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
- int nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
- Fts5DlidxIter *pNew;
-
- pNew = (Fts5DlidxIter*)sqlite3_realloc(pIter, nByte);
- if( pNew==0 ){
- p->rc = SQLITE_NOMEM;
- }else{
- i64 iRowid = FTS5_DLIDX_ROWID(iSegid, i, iLeafPg);
- Fts5DlidxLvl *pLvl = &pNew->aLvl[i];
- pIter = pNew;
- memset(pLvl, 0, sizeof(Fts5DlidxLvl));
- pLvl->pData = fts5DataRead(p, iRowid);
- if( pLvl->pData && (pLvl->pData->p[0] & 0x0001)==0 ){
- bDone = 1;
- }
- pIter->nLvl = i+1;
- }
- }
-
- if( p->rc==SQLITE_OK ){
- pIter->iSegid = iSegid;
- if( bRev==0 ){
- fts5DlidxIterFirst(pIter);
- }else{
- fts5DlidxIterLast(p, pIter);
- }
- }
-
- if( p->rc!=SQLITE_OK ){
- fts5DlidxIterFree(pIter);
- pIter = 0;
- }
-
- return pIter;
-}
-
-static i64 fts5DlidxIterRowid(Fts5DlidxIter *pIter){
- return pIter->aLvl[0].iRowid;
-}
-static int fts5DlidxIterPgno(Fts5DlidxIter *pIter){
- return pIter->aLvl[0].iLeafPgno;
-}
-
-/*
-** Load the next leaf page into the segment iterator.
-*/
-static void fts5SegIterNextPage(
- Fts5Index *p, /* FTS5 backend object */
- Fts5SegIter *pIter /* Iterator to advance to next page */
-){
- Fts5Data *pLeaf;
- Fts5StructureSegment *pSeg = pIter->pSeg;
- fts5DataRelease(pIter->pLeaf);
- pIter->iLeafPgno++;
- if( pIter->pNextLeaf ){
- pIter->pLeaf = pIter->pNextLeaf;
- pIter->pNextLeaf = 0;
- }else if( pIter->iLeafPgno<=pSeg->pgnoLast ){
- pIter->pLeaf = fts5LeafRead(p,
- FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno)
- );
- }else{
- pIter->pLeaf = 0;
- }
- pLeaf = pIter->pLeaf;
-
- if( pLeaf ){
- pIter->iPgidxOff = pLeaf->szLeaf;
- if( fts5LeafIsTermless(pLeaf) ){
- pIter->iEndofDoclist = pLeaf->nn+1;
- }else{
- pIter->iPgidxOff += fts5GetVarint32(&pLeaf->p[pIter->iPgidxOff],
- pIter->iEndofDoclist
- );
- }
- }
-}
-
-/*
-** Argument p points to a buffer containing a varint to be interpreted as a
-** position list size field. Read the varint and return the number of bytes
-** read. Before returning, set *pnSz to the number of bytes in the position
-** list, and *pbDel to true if the delete flag is set, or false otherwise.
-*/
-static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){
- int nSz;
- int n = 0;
- fts5FastGetVarint32(p, n, nSz);
- assert_nc( nSz>=0 );
- *pnSz = nSz/2;
- *pbDel = nSz & 0x0001;
- return n;
-}
-
-/*
-** Fts5SegIter.iLeafOffset currently points to the first byte of a
-** position-list size field. Read the value of the field and store it
-** in the following variables:
-**
-** Fts5SegIter.nPos
-** Fts5SegIter.bDel
-**
-** Leave Fts5SegIter.iLeafOffset pointing to the first byte of the
-** position list content (if any).
-*/
-static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
- if( p->rc==SQLITE_OK ){
- int iOff = pIter->iLeafOffset; /* Offset to read at */
- ASSERT_SZLEAF_OK(pIter->pLeaf);
- if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
- int iEod = MIN(pIter->iEndofDoclist, pIter->pLeaf->szLeaf);
- pIter->bDel = 0;
- pIter->nPos = 1;
- if( iOff<iEod && pIter->pLeaf->p[iOff]==0 ){
- pIter->bDel = 1;
- iOff++;
- if( iOff<iEod && pIter->pLeaf->p[iOff]==0 ){
- pIter->nPos = 1;
- iOff++;
- }else{
- pIter->nPos = 0;
- }
- }
- }else{
- int nSz;
- fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz);
- pIter->bDel = (nSz & 0x0001);
- pIter->nPos = nSz>>1;
- assert_nc( pIter->nPos>=0 );
- }
- pIter->iLeafOffset = iOff;
- }
-}
-
-static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
- u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset;
-
- ASSERT_SZLEAF_OK(pIter->pLeaf);
- if( iOff>=pIter->pLeaf->szLeaf ){
- fts5SegIterNextPage(p, pIter);
- if( pIter->pLeaf==0 ){
- if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
- return;
- }
- iOff = 4;
- a = pIter->pLeaf->p;
- }
- iOff += sqlite3Fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid);
- pIter->iLeafOffset = iOff;
-}
-
-/*
-** Fts5SegIter.iLeafOffset currently points to the first byte of the
-** "nSuffix" field of a term. Function parameter nKeep contains the value
-** of the "nPrefix" field (if there was one - it is passed 0 if this is
-** the first term in the segment).
-**
-** This function populates:
-**
-** Fts5SegIter.term
-** Fts5SegIter.rowid
-**
-** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the content of
-** the first position list. The position list belonging to document
-** (Fts5SegIter.iRowid).
-*/
-static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
- u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset; /* Offset to read at */
- int nNew; /* Bytes of new data */
-
- iOff += fts5GetVarint32(&a[iOff], nNew);
- if( iOff+nNew>pIter->pLeaf->nn ){
- p->rc = FTS5_CORRUPT;
- return;
- }
- pIter->term.n = nKeep;
- fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
- iOff += nNew;
- pIter->iTermLeafOffset = iOff;
- pIter->iTermLeafPgno = pIter->iLeafPgno;
- pIter->iLeafOffset = iOff;
-
- if( pIter->iPgidxOff>=pIter->pLeaf->nn ){
- pIter->iEndofDoclist = pIter->pLeaf->nn+1;
- }else{
- int nExtra;
- pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], nExtra);
- pIter->iEndofDoclist += nExtra;
- }
-
- fts5SegIterLoadRowid(p, pIter);
-}
-
-static void fts5SegIterNext(Fts5Index*, Fts5SegIter*, int*);
-static void fts5SegIterNext_Reverse(Fts5Index*, Fts5SegIter*, int*);
-static void fts5SegIterNext_None(Fts5Index*, Fts5SegIter*, int*);
-
-static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
- if( pIter->flags & FTS5_SEGITER_REVERSE ){
- pIter->xNext = fts5SegIterNext_Reverse;
- }else if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
- pIter->xNext = fts5SegIterNext_None;
- }else{
- pIter->xNext = fts5SegIterNext;
- }
-}
-
-/*
-** Initialize the iterator object pIter to iterate through the entries in
-** segment pSeg. The iterator is left pointing to the first entry when
-** this function returns.
-**
-** If an error occurs, Fts5Index.rc is set to an appropriate error code. If
-** an error has already occurred when this function is called, it is a no-op.
-*/
-static void fts5SegIterInit(
- Fts5Index *p, /* FTS index object */
- Fts5StructureSegment *pSeg, /* Description of segment */
- Fts5SegIter *pIter /* Object to populate */
-){
- if( pSeg->pgnoFirst==0 ){
- /* This happens if the segment is being used as an input to an incremental
- ** merge and all data has already been "trimmed". See function
- ** fts5TrimSegments() for details. In this case leave the iterator empty.
- ** The caller will see the (pIter->pLeaf==0) and assume the iterator is
- ** at EOF already. */
- assert( pIter->pLeaf==0 );
- return;
- }
-
- if( p->rc==SQLITE_OK ){
- memset(pIter, 0, sizeof(*pIter));
- fts5SegIterSetNext(p, pIter);
- pIter->pSeg = pSeg;
- pIter->iLeafPgno = pSeg->pgnoFirst-1;
- fts5SegIterNextPage(p, pIter);
- }
-
- if( p->rc==SQLITE_OK ){
- pIter->iLeafOffset = 4;
- assert_nc( pIter->pLeaf->nn>4 );
- assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
- pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
- fts5SegIterLoadTerm(p, pIter, 0);
- fts5SegIterLoadNPos(p, pIter);
- }
-}
-
-/*
-** This function is only ever called on iterators created by calls to
-** Fts5IndexQuery() with the FTS5INDEX_QUERY_DESC flag set.
-**
-** The iterator is in an unusual state when this function is called: the
-** Fts5SegIter.iLeafOffset variable is set to the offset of the start of
-** the position-list size field for the first relevant rowid on the page.
-** Fts5SegIter.rowid is set, but nPos and bDel are not.
-**
-** This function advances the iterator so that it points to the last
-** relevant rowid on the page and, if necessary, initializes the
-** aRowidOffset[] and iRowidOffset variables. At this point the iterator
-** is in its regular state - Fts5SegIter.iLeafOffset points to the first
-** byte of the position list content associated with said rowid.
-*/
-static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
- int eDetail = p->pConfig->eDetail;
- int n = pIter->pLeaf->szLeaf;
- int i = pIter->iLeafOffset;
- u8 *a = pIter->pLeaf->p;
- int iRowidOffset = 0;
-
- if( n>pIter->iEndofDoclist ){
- n = pIter->iEndofDoclist;
- }
-
- ASSERT_SZLEAF_OK(pIter->pLeaf);
- while( 1 ){
- i64 iDelta = 0;
-
- if( eDetail==FTS5_DETAIL_NONE ){
- /* todo */
- if( i<n && a[i]==0 ){
- i++;
- if( i<n && a[i]==0 ) i++;
- }
- }else{
- int nPos;
- int bDummy;
- i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
- i += nPos;
- }
- if( i>=n ) break;
- i += fts5GetVarint(&a[i], (u64*)&iDelta);
- pIter->iRowid += iDelta;
-
- /* If necessary, grow the pIter->aRowidOffset[] array. */
- if( iRowidOffset>=pIter->nRowidOffset ){
- int nNew = pIter->nRowidOffset + 8;
- int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
- if( aNew==0 ){
- p->rc = SQLITE_NOMEM;
- break;
- }
- pIter->aRowidOffset = aNew;
- pIter->nRowidOffset = nNew;
- }
-
- pIter->aRowidOffset[iRowidOffset++] = pIter->iLeafOffset;
- pIter->iLeafOffset = i;
- }
- pIter->iRowidOffset = iRowidOffset;
- fts5SegIterLoadNPos(p, pIter);
-}
-
-/*
-**
-*/
-static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
- assert( pIter->flags & FTS5_SEGITER_REVERSE );
- assert( pIter->flags & FTS5_SEGITER_ONETERM );
-
- fts5DataRelease(pIter->pLeaf);
- pIter->pLeaf = 0;
- while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){
- Fts5Data *pNew;
- pIter->iLeafPgno--;
- pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID(
- pIter->pSeg->iSegid, pIter->iLeafPgno
- ));
- if( pNew ){
- /* iTermLeafOffset may be equal to szLeaf if the term is the last
- ** thing on the page - i.e. the first rowid is on the following page.
- ** In this case leave pIter->pLeaf==0, this iterator is at EOF. */
- if( pIter->iLeafPgno==pIter->iTermLeafPgno ){
- assert( pIter->pLeaf==0 );
- if( pIter->iTermLeafOffset<pNew->szLeaf ){
- pIter->pLeaf = pNew;
- pIter->iLeafOffset = pIter->iTermLeafOffset;
- }
- }else{
- int iRowidOff;
- iRowidOff = fts5LeafFirstRowidOff(pNew);
- if( iRowidOff ){
- pIter->pLeaf = pNew;
- pIter->iLeafOffset = iRowidOff;
- }
- }
-
- if( pIter->pLeaf ){
- u8 *a = &pIter->pLeaf->p[pIter->iLeafOffset];
- pIter->iLeafOffset += fts5GetVarint(a, (u64*)&pIter->iRowid);
- break;
- }else{
- fts5DataRelease(pNew);
- }
- }
- }
-
- if( pIter->pLeaf ){
- pIter->iEndofDoclist = pIter->pLeaf->nn+1;
- fts5SegIterReverseInitPage(p, pIter);
- }
-}
-
-/*
-** Return true if the iterator passed as the second argument currently
-** points to a delete marker. A delete marker is an entry with a 0 byte
-** position-list.
-*/
-static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){
- Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
- return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0);
-}
-
-/*
-** Advance iterator pIter to the next entry.
-**
-** This version of fts5SegIterNext() is only used by reverse iterators.
-*/
-static void fts5SegIterNext_Reverse(
- Fts5Index *p, /* FTS5 backend object */
- Fts5SegIter *pIter, /* Iterator to advance */
- int *pbUnused /* Unused */
-){
- assert( pIter->flags & FTS5_SEGITER_REVERSE );
- assert( pIter->pNextLeaf==0 );
- UNUSED_PARAM(pbUnused);
-
- if( pIter->iRowidOffset>0 ){
- u8 *a = pIter->pLeaf->p;
- int iOff;
- i64 iDelta;
-
- pIter->iRowidOffset--;
- pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
- fts5SegIterLoadNPos(p, pIter);
- iOff = pIter->iLeafOffset;
- if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
- iOff += pIter->nPos;
- }
- fts5GetVarint(&a[iOff], (u64*)&iDelta);
- pIter->iRowid -= iDelta;
- }else{
- fts5SegIterReverseNewPage(p, pIter);
- }
-}
-
-/*
-** Advance iterator pIter to the next entry.
-**
-** This version of fts5SegIterNext() is only used if detail=none and the
-** iterator is not a reverse direction iterator.
-*/
-static void fts5SegIterNext_None(
- Fts5Index *p, /* FTS5 backend object */
- Fts5SegIter *pIter, /* Iterator to advance */
- int *pbNewTerm /* OUT: Set for new term */
-){
- int iOff;
-
- assert( p->rc==SQLITE_OK );
- assert( (pIter->flags & FTS5_SEGITER_REVERSE)==0 );
- assert( p->pConfig->eDetail==FTS5_DETAIL_NONE );
-
- ASSERT_SZLEAF_OK(pIter->pLeaf);
- iOff = pIter->iLeafOffset;
-
- /* Next entry is on the next page */
- if( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){
- fts5SegIterNextPage(p, pIter);
- if( p->rc || pIter->pLeaf==0 ) return;
- pIter->iRowid = 0;
- iOff = 4;
- }
-
- if( iOff<pIter->iEndofDoclist ){
- /* Next entry is on the current page */
- i64 iDelta;
- iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
- pIter->iLeafOffset = iOff;
- pIter->iRowid += iDelta;
- }else if( (pIter->flags & FTS5_SEGITER_ONETERM)==0 ){
- if( pIter->pSeg ){
- int nKeep = 0;
- if( iOff!=fts5LeafFirstTermOff(pIter->pLeaf) ){
- iOff += fts5GetVarint32(&pIter->pLeaf->p[iOff], nKeep);
- }
- pIter->iLeafOffset = iOff;
- fts5SegIterLoadTerm(p, pIter, nKeep);
- }else{
- const u8 *pList = 0;
- const char *zTerm = 0;
- int nList;
- sqlite3Fts5HashScanNext(p->pHash);
- sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
- if( pList==0 ) goto next_none_eof;
- pIter->pLeaf->p = (u8*)pList;
- pIter->pLeaf->nn = nList;
- pIter->pLeaf->szLeaf = nList;
- pIter->iEndofDoclist = nList;
- sqlite3Fts5BufferSet(&p->rc,&pIter->term, (int)strlen(zTerm), (u8*)zTerm);
- pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
- }
-
- if( pbNewTerm ) *pbNewTerm = 1;
- }else{
- goto next_none_eof;
- }
-
- fts5SegIterLoadNPos(p, pIter);
-
- return;
- next_none_eof:
- fts5DataRelease(pIter->pLeaf);
- pIter->pLeaf = 0;
-}
-
-
-/*
-** Advance iterator pIter to the next entry.
-**
-** If an error occurs, Fts5Index.rc is set to an appropriate error code. It
-** is not considered an error if the iterator reaches EOF. If an error has
-** already occurred when this function is called, it is a no-op.
-*/
-static void fts5SegIterNext(
- Fts5Index *p, /* FTS5 backend object */
- Fts5SegIter *pIter, /* Iterator to advance */
- int *pbNewTerm /* OUT: Set for new term */
-){
- Fts5Data *pLeaf = pIter->pLeaf;
- int iOff;
- int bNewTerm = 0;
- int nKeep = 0;
- u8 *a;
- int n;
-
- assert( pbNewTerm==0 || *pbNewTerm==0 );
- assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
-
- /* Search for the end of the position list within the current page. */
- a = pLeaf->p;
- n = pLeaf->szLeaf;
-
- ASSERT_SZLEAF_OK(pLeaf);
- iOff = pIter->iLeafOffset + pIter->nPos;
-
- if( iOff<n ){
- /* The next entry is on the current page. */
- assert_nc( iOff<=pIter->iEndofDoclist );
- if( iOff>=pIter->iEndofDoclist ){
- bNewTerm = 1;
- if( iOff!=fts5LeafFirstTermOff(pLeaf) ){
- iOff += fts5GetVarint32(&a[iOff], nKeep);
- }
- }else{
- u64 iDelta;
- iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta);
- pIter->iRowid += iDelta;
- assert_nc( iDelta>0 );
- }
- pIter->iLeafOffset = iOff;
-
- }else if( pIter->pSeg==0 ){
- const u8 *pList = 0;
- const char *zTerm = 0;
- int nList = 0;
- assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
- if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
- sqlite3Fts5HashScanNext(p->pHash);
- sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
- }
- if( pList==0 ){
- fts5DataRelease(pIter->pLeaf);
- pIter->pLeaf = 0;
- }else{
- pIter->pLeaf->p = (u8*)pList;
- pIter->pLeaf->nn = nList;
- pIter->pLeaf->szLeaf = nList;
- pIter->iEndofDoclist = nList+1;
- sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm),
- (u8*)zTerm);
- pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
- *pbNewTerm = 1;
- }
- }else{
- iOff = 0;
- /* Next entry is not on the current page */
- while( iOff==0 ){
- fts5SegIterNextPage(p, pIter);
- pLeaf = pIter->pLeaf;
- if( pLeaf==0 ) break;
- ASSERT_SZLEAF_OK(pLeaf);
- if( (iOff = fts5LeafFirstRowidOff(pLeaf)) && iOff<pLeaf->szLeaf ){
- iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid);
- pIter->iLeafOffset = iOff;
-
- if( pLeaf->nn>pLeaf->szLeaf ){
- pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
- &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist
- );
- }
- }
- else if( pLeaf->nn>pLeaf->szLeaf ){
- pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
- &pLeaf->p[pLeaf->szLeaf], iOff
- );
- pIter->iLeafOffset = iOff;
- pIter->iEndofDoclist = iOff;
- bNewTerm = 1;
- }
- assert_nc( iOff<pLeaf->szLeaf );
- if( iOff>pLeaf->szLeaf ){
- p->rc = FTS5_CORRUPT;
- return;
- }
- }
- }
-
- /* Check if the iterator is now at EOF. If so, return early. */
- if( pIter->pLeaf ){
- if( bNewTerm ){
- if( pIter->flags & FTS5_SEGITER_ONETERM ){
- fts5DataRelease(pIter->pLeaf);
- pIter->pLeaf = 0;
- }else{
- fts5SegIterLoadTerm(p, pIter, nKeep);
- fts5SegIterLoadNPos(p, pIter);
- if( pbNewTerm ) *pbNewTerm = 1;
- }
- }else{
- /* The following could be done by calling fts5SegIterLoadNPos(). But
- ** this block is particularly performance critical, so equivalent
- ** code is inlined.
- **
- ** Later: Switched back to fts5SegIterLoadNPos() because it supports
- ** detail=none mode. Not ideal.
- */
- int nSz;
- assert( p->rc==SQLITE_OK );
- assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
- fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
- pIter->bDel = (nSz & 0x0001);
- pIter->nPos = nSz>>1;
- assert_nc( pIter->nPos>=0 );
- }
- }
-}
-
-#define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; }
-
-#define fts5IndexSkipVarint(a, iOff) { \
- int iEnd = iOff+9; \
- while( (a[iOff++] & 0x80) && iOff<iEnd ); \
-}
-
-/*
-** Iterator pIter currently points to the first rowid in a doclist. This
-** function sets the iterator up so that iterates in reverse order through
-** the doclist.
-*/
-static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
- Fts5DlidxIter *pDlidx = pIter->pDlidx;
- Fts5Data *pLast = 0;
- int pgnoLast = 0;
-
- if( pDlidx ){
- int iSegid = pIter->pSeg->iSegid;
- pgnoLast = fts5DlidxIterPgno(pDlidx);
- pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast));
- }else{
- Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
-
- /* Currently, Fts5SegIter.iLeafOffset points to the first byte of
- ** position-list content for the current rowid. Back it up so that it
- ** points to the start of the position-list size field. */
- int iPoslist;
- if( pIter->iTermLeafPgno==pIter->iLeafPgno ){
- iPoslist = pIter->iTermLeafOffset;
- }else{
- iPoslist = 4;
- }
- fts5IndexSkipVarint(pLeaf->p, iPoslist);
- pIter->iLeafOffset = iPoslist;
-
- /* If this condition is true then the largest rowid for the current
- ** term may not be stored on the current page. So search forward to
- ** see where said rowid really is. */
- if( pIter->iEndofDoclist>=pLeaf->szLeaf ){
- int pgno;
- Fts5StructureSegment *pSeg = pIter->pSeg;
-
- /* The last rowid in the doclist may not be on the current page. Search
- ** forward to find the page containing the last rowid. */
- for(pgno=pIter->iLeafPgno+1; !p->rc && pgno<=pSeg->pgnoLast; pgno++){
- i64 iAbs = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno);
- Fts5Data *pNew = fts5DataRead(p, iAbs);
- if( pNew ){
- int iRowid, bTermless;
- iRowid = fts5LeafFirstRowidOff(pNew);
- bTermless = fts5LeafIsTermless(pNew);
- if( iRowid ){
- SWAPVAL(Fts5Data*, pNew, pLast);
- pgnoLast = pgno;
- }
- fts5DataRelease(pNew);
- if( bTermless==0 ) break;
- }
- }
- }
- }
-
- /* If pLast is NULL at this point, then the last rowid for this doclist
- ** lies on the page currently indicated by the iterator. In this case
- ** pIter->iLeafOffset is already set to point to the position-list size
- ** field associated with the first relevant rowid on the page.
- **
- ** Or, if pLast is non-NULL, then it is the page that contains the last
- ** rowid. In this case configure the iterator so that it points to the
- ** first rowid on this page.
- */
- if( pLast ){
- int iOff;
- fts5DataRelease(pIter->pLeaf);
- pIter->pLeaf = pLast;
- pIter->iLeafPgno = pgnoLast;
- iOff = fts5LeafFirstRowidOff(pLast);
- iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
- pIter->iLeafOffset = iOff;
-
- if( fts5LeafIsTermless(pLast) ){
- pIter->iEndofDoclist = pLast->nn+1;
- }else{
- pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
- }
-
- }
-
- fts5SegIterReverseInitPage(p, pIter);
-}
-
-/*
-** Iterator pIter currently points to the first rowid of a doclist.
-** There is a doclist-index associated with the final term on the current
-** page. If the current term is the last term on the page, load the
-** doclist-index from disk and initialize an iterator at (pIter->pDlidx).
-*/
-static void fts5SegIterLoadDlidx(Fts5Index *p, Fts5SegIter *pIter){
- int iSeg = pIter->pSeg->iSegid;
- int bRev = (pIter->flags & FTS5_SEGITER_REVERSE);
- Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
-
- assert( pIter->flags & FTS5_SEGITER_ONETERM );
- assert( pIter->pDlidx==0 );
-
- /* Check if the current doclist ends on this page. If it does, return
- ** early without loading the doclist-index (as it belongs to a different
- ** term. */
- if( pIter->iTermLeafPgno==pIter->iLeafPgno
- && pIter->iEndofDoclist<pLeaf->szLeaf
- ){
- return;
- }
-
- pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
-}
-
-/*
-** The iterator object passed as the second argument currently contains
-** no valid values except for the Fts5SegIter.pLeaf member variable. This
-** function searches the leaf page for a term matching (pTerm/nTerm).
-**
-** If the specified term is found on the page, then the iterator is left
-** pointing to it. If argument bGe is zero and the term is not found,
-** the iterator is left pointing at EOF.
-**
-** If bGe is non-zero and the specified term is not found, then the
-** iterator is left pointing to the smallest term in the segment that
-** is larger than the specified term, even if this term is not on the
-** current page.
-*/
-static void fts5LeafSeek(
- Fts5Index *p, /* Leave any error code here */
- int bGe, /* True for a >= search */
- Fts5SegIter *pIter, /* Iterator to seek */
- const u8 *pTerm, int nTerm /* Term to search for */
-){
- int iOff;
- const u8 *a = pIter->pLeaf->p;
- int szLeaf = pIter->pLeaf->szLeaf;
- int n = pIter->pLeaf->nn;
-
- int nMatch = 0;
- int nKeep = 0;
- int nNew = 0;
- int iTermOff;
- int iPgidx; /* Current offset in pgidx */
- int bEndOfPage = 0;
-
- assert( p->rc==SQLITE_OK );
-
- iPgidx = szLeaf;
- iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
- iOff = iTermOff;
- if( iOff>n ){
- p->rc = FTS5_CORRUPT;
- return;
- }
-
- while( 1 ){
-
- /* Figure out how many new bytes are in this term */
- fts5FastGetVarint32(a, iOff, nNew);
- if( nKeep<nMatch ){
- goto search_failed;
- }
-
- assert( nKeep>=nMatch );
- if( nKeep==nMatch ){
- int nCmp;
- int i;
- nCmp = MIN(nNew, nTerm-nMatch);
- for(i=0; i<nCmp; i++){
- if( a[iOff+i]!=pTerm[nMatch+i] ) break;
- }
- nMatch += i;
-
- if( nTerm==nMatch ){
- if( i==nNew ){
- goto search_success;
- }else{
- goto search_failed;
- }
- }else if( i<nNew && a[iOff+i]>pTerm[nMatch] ){
- goto search_failed;
- }
- }
-
- if( iPgidx>=n ){
- bEndOfPage = 1;
- break;
- }
-
- iPgidx += fts5GetVarint32(&a[iPgidx], nKeep);
- iTermOff += nKeep;
- iOff = iTermOff;
-
- if( iOff>=n ){
- p->rc = FTS5_CORRUPT;
- return;
- }
-
- /* Read the nKeep field of the next term. */
- fts5FastGetVarint32(a, iOff, nKeep);
- }
-
- search_failed:
- if( bGe==0 ){
- fts5DataRelease(pIter->pLeaf);
- pIter->pLeaf = 0;
- return;
- }else if( bEndOfPage ){
- do {
- fts5SegIterNextPage(p, pIter);
- if( pIter->pLeaf==0 ) return;
- a = pIter->pLeaf->p;
- if( fts5LeafIsTermless(pIter->pLeaf)==0 ){
- iPgidx = pIter->pLeaf->szLeaf;
- iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
- if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
- p->rc = FTS5_CORRUPT;
- }else{
- nKeep = 0;
- iTermOff = iOff;
- n = pIter->pLeaf->nn;
- iOff += fts5GetVarint32(&a[iOff], nNew);
- break;
- }
- }
- }while( 1 );
- }
-
- search_success:
-
- pIter->iLeafOffset = iOff + nNew;
- pIter->iTermLeafOffset = pIter->iLeafOffset;
- pIter->iTermLeafPgno = pIter->iLeafPgno;
-
- fts5BufferSet(&p->rc, &pIter->term, nKeep, pTerm);
- fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
-
- if( iPgidx>=n ){
- pIter->iEndofDoclist = pIter->pLeaf->nn+1;
- }else{
- int nExtra;
- iPgidx += fts5GetVarint32(&a[iPgidx], nExtra);
- pIter->iEndofDoclist = iTermOff + nExtra;
- }
- pIter->iPgidxOff = iPgidx;
-
- fts5SegIterLoadRowid(p, pIter);
- fts5SegIterLoadNPos(p, pIter);
-}
-
-static sqlite3_stmt *fts5IdxSelectStmt(Fts5Index *p){
- if( p->pIdxSelect==0 ){
- Fts5Config *pConfig = p->pConfig;
- fts5IndexPrepareStmt(p, &p->pIdxSelect, sqlite3_mprintf(
- "SELECT pgno FROM '%q'.'%q_idx' WHERE "
- "segid=? AND term<=? ORDER BY term DESC LIMIT 1",
- pConfig->zDb, pConfig->zName
- ));
- }
- return p->pIdxSelect;
-}
-
-/*
-** Initialize the object pIter to point to term pTerm/nTerm within segment
-** pSeg. If there is no such term in the index, the iterator is set to EOF.
-**
-** If an error occurs, Fts5Index.rc is set to an appropriate error code. If
-** an error has already occurred when this function is called, it is a no-op.
-*/
-static void fts5SegIterSeekInit(
- Fts5Index *p, /* FTS5 backend */
- const u8 *pTerm, int nTerm, /* Term to seek to */
- int flags, /* Mask of FTS5INDEX_XXX flags */
- Fts5StructureSegment *pSeg, /* Description of segment */
- Fts5SegIter *pIter /* Object to populate */
-){
- int iPg = 1;
- int bGe = (flags & FTS5INDEX_QUERY_SCAN);
- int bDlidx = 0; /* True if there is a doclist-index */
- sqlite3_stmt *pIdxSelect = 0;
-
- assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 );
- assert( pTerm && nTerm );
- memset(pIter, 0, sizeof(*pIter));
- pIter->pSeg = pSeg;
-
- /* This block sets stack variable iPg to the leaf page number that may
- ** contain term (pTerm/nTerm), if it is present in the segment. */
- pIdxSelect = fts5IdxSelectStmt(p);
- if( p->rc ) return;
- sqlite3_bind_int(pIdxSelect, 1, pSeg->iSegid);
- sqlite3_bind_blob(pIdxSelect, 2, pTerm, nTerm, SQLITE_STATIC);
- if( SQLITE_ROW==sqlite3_step(pIdxSelect) ){
- i64 val = sqlite3_column_int(pIdxSelect, 0);
- iPg = (int)(val>>1);
- bDlidx = (val & 0x0001);
- }
- p->rc = sqlite3_reset(pIdxSelect);
- sqlite3_bind_null(pIdxSelect, 2);
-
- if( iPg<pSeg->pgnoFirst ){
- iPg = pSeg->pgnoFirst;
- bDlidx = 0;
- }
-
- pIter->iLeafPgno = iPg - 1;
- fts5SegIterNextPage(p, pIter);
-
- if( pIter->pLeaf ){
- fts5LeafSeek(p, bGe, pIter, pTerm, nTerm);
- }
-
- if( p->rc==SQLITE_OK && bGe==0 ){
- pIter->flags |= FTS5_SEGITER_ONETERM;
- if( pIter->pLeaf ){
- if( flags & FTS5INDEX_QUERY_DESC ){
- pIter->flags |= FTS5_SEGITER_REVERSE;
- }
- if( bDlidx ){
- fts5SegIterLoadDlidx(p, pIter);
- }
- if( flags & FTS5INDEX_QUERY_DESC ){
- fts5SegIterReverse(p, pIter);
- }
- }
- }
-
- fts5SegIterSetNext(p, pIter);
-
- /* Either:
- **
- ** 1) an error has occurred, or
- ** 2) the iterator points to EOF, or
- ** 3) the iterator points to an entry with term (pTerm/nTerm), or
- ** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points
- ** to an entry with a term greater than or equal to (pTerm/nTerm).
- */
- assert( p->rc!=SQLITE_OK /* 1 */
- || pIter->pLeaf==0 /* 2 */
- || fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */
- || (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */
- );
-}
-
-/*
-** Initialize the object pIter to point to term pTerm/nTerm within the
-** in-memory hash table. If there is no such term in the hash-table, the
-** iterator is set to EOF.
-**
-** If an error occurs, Fts5Index.rc is set to an appropriate error code. If
-** an error has already occurred when this function is called, it is a no-op.
-*/
-static void fts5SegIterHashInit(
- Fts5Index *p, /* FTS5 backend */
- const u8 *pTerm, int nTerm, /* Term to seek to */
- int flags, /* Mask of FTS5INDEX_XXX flags */
- Fts5SegIter *pIter /* Object to populate */
-){
- const u8 *pList = 0;
- int nList = 0;
- const u8 *z = 0;
- int n = 0;
-
- assert( p->pHash );
- assert( p->rc==SQLITE_OK );
-
- if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){
- p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm);
- sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList);
- n = (z ? (int)strlen((const char*)z) : 0);
- }else{
- pIter->flags |= FTS5_SEGITER_ONETERM;
- sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList);
- z = pTerm;
- n = nTerm;
- }
-
- if( pList ){
- Fts5Data *pLeaf;
- sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z);
- pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
- if( pLeaf==0 ) return;
- pLeaf->p = (u8*)pList;
- pLeaf->nn = pLeaf->szLeaf = nList;
- pIter->pLeaf = pLeaf;
- pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
- pIter->iEndofDoclist = pLeaf->nn;
-
- if( flags & FTS5INDEX_QUERY_DESC ){
- pIter->flags |= FTS5_SEGITER_REVERSE;
- fts5SegIterReverseInitPage(p, pIter);
- }else{
- fts5SegIterLoadNPos(p, pIter);
- }
- }
-
- fts5SegIterSetNext(p, pIter);
-}
-
-/*
-** Zero the iterator passed as the only argument.
-*/
-static void fts5SegIterClear(Fts5SegIter *pIter){
- fts5BufferFree(&pIter->term);
- fts5DataRelease(pIter->pLeaf);
- fts5DataRelease(pIter->pNextLeaf);
- fts5DlidxIterFree(pIter->pDlidx);
- sqlite3_free(pIter->aRowidOffset);
- memset(pIter, 0, sizeof(Fts5SegIter));
-}
-
-#ifdef SQLITE_DEBUG
-
-/*
-** This function is used as part of the big assert() procedure implemented by
-** fts5AssertMultiIterSetup(). It ensures that the result currently stored
-** in *pRes is the correct result of comparing the current positions of the
-** two iterators.
-*/
-static void fts5AssertComparisonResult(
- Fts5Iter *pIter,
- Fts5SegIter *p1,
- Fts5SegIter *p2,
- Fts5CResult *pRes
-){
- int i1 = p1 - pIter->aSeg;
- int i2 = p2 - pIter->aSeg;
-
- if( p1->pLeaf || p2->pLeaf ){
- if( p1->pLeaf==0 ){
- assert( pRes->iFirst==i2 );
- }else if( p2->pLeaf==0 ){
- assert( pRes->iFirst==i1 );
- }else{
- int nMin = MIN(p1->term.n, p2->term.n);
- int res = memcmp(p1->term.p, p2->term.p, nMin);
- if( res==0 ) res = p1->term.n - p2->term.n;
-
- if( res==0 ){
- assert( pRes->bTermEq==1 );
- assert( p1->iRowid!=p2->iRowid );
- res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : 1;
- }else{
- assert( pRes->bTermEq==0 );
- }
-
- if( res<0 ){
- assert( pRes->iFirst==i1 );
- }else{
- assert( pRes->iFirst==i2 );
- }
- }
- }
-}
-
-/*
-** This function is a no-op unless SQLITE_DEBUG is defined when this module
-** is compiled. In that case, this function is essentially an assert()
-** statement used to verify that the contents of the pIter->aFirst[] array
-** are correct.
-*/
-static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){
- if( p->rc==SQLITE_OK ){
- Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
- int i;
-
- assert( (pFirst->pLeaf==0)==pIter->base.bEof );
-
- /* Check that pIter->iSwitchRowid is set correctly. */
- for(i=0; i<pIter->nSeg; i++){
- Fts5SegIter *p1 = &pIter->aSeg[i];
- assert( p1==pFirst
- || p1->pLeaf==0
- || fts5BufferCompare(&pFirst->term, &p1->term)
- || p1->iRowid==pIter->iSwitchRowid
- || (p1->iRowid<pIter->iSwitchRowid)==pIter->bRev
- );
- }
-
- for(i=0; i<pIter->nSeg; i+=2){
- Fts5SegIter *p1 = &pIter->aSeg[i];
- Fts5SegIter *p2 = &pIter->aSeg[i+1];
- Fts5CResult *pRes = &pIter->aFirst[(pIter->nSeg + i) / 2];
- fts5AssertComparisonResult(pIter, p1, p2, pRes);
- }
-
- for(i=1; i<(pIter->nSeg / 2); i+=2){
- Fts5SegIter *p1 = &pIter->aSeg[ pIter->aFirst[i*2].iFirst ];
- Fts5SegIter *p2 = &pIter->aSeg[ pIter->aFirst[i*2+1].iFirst ];
- Fts5CResult *pRes = &pIter->aFirst[i];
- fts5AssertComparisonResult(pIter, p1, p2, pRes);
- }
- }
-}
-#else
-# define fts5AssertMultiIterSetup(x,y)
-#endif
-
-/*
-** Do the comparison necessary to populate pIter->aFirst[iOut].
-**
-** If the returned value is non-zero, then it is the index of an entry
-** in the pIter->aSeg[] array that is (a) not at EOF, and (b) pointing
-** to a key that is a duplicate of another, higher priority,
-** segment-iterator in the pSeg->aSeg[] array.
-*/
-static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){
- int i1; /* Index of left-hand Fts5SegIter */
- int i2; /* Index of right-hand Fts5SegIter */
- int iRes;
- Fts5SegIter *p1; /* Left-hand Fts5SegIter */
- Fts5SegIter *p2; /* Right-hand Fts5SegIter */
- Fts5CResult *pRes = &pIter->aFirst[iOut];
-
- assert( iOut<pIter->nSeg && iOut>0 );
- assert( pIter->bRev==0 || pIter->bRev==1 );
-
- if( iOut>=(pIter->nSeg/2) ){
- i1 = (iOut - pIter->nSeg/2) * 2;
- i2 = i1 + 1;
- }else{
- i1 = pIter->aFirst[iOut*2].iFirst;
- i2 = pIter->aFirst[iOut*2+1].iFirst;
- }
- p1 = &pIter->aSeg[i1];
- p2 = &pIter->aSeg[i2];
-
- pRes->bTermEq = 0;
- if( p1->pLeaf==0 ){ /* If p1 is at EOF */
- iRes = i2;
- }else if( p2->pLeaf==0 ){ /* If p2 is at EOF */
- iRes = i1;
- }else{
- int res = fts5BufferCompare(&p1->term, &p2->term);
- if( res==0 ){
- assert( i2>i1 );
- assert( i2!=0 );
- pRes->bTermEq = 1;
- if( p1->iRowid==p2->iRowid ){
- p1->bDel = p2->bDel;
- return i2;
- }
- res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1;
- }
- assert( res!=0 );
- if( res<0 ){
- iRes = i1;
- }else{
- iRes = i2;
- }
- }
-
- pRes->iFirst = (u16)iRes;
- return 0;
-}
-
-/*
-** Move the seg-iter so that it points to the first rowid on page iLeafPgno.
-** It is an error if leaf iLeafPgno does not exist or contains no rowids.
-*/
-static void fts5SegIterGotoPage(
- Fts5Index *p, /* FTS5 backend object */
- Fts5SegIter *pIter, /* Iterator to advance */
- int iLeafPgno
-){
- assert( iLeafPgno>pIter->iLeafPgno );
-
- if( iLeafPgno>pIter->pSeg->pgnoLast ){
- p->rc = FTS5_CORRUPT;
- }else{
- fts5DataRelease(pIter->pNextLeaf);
- pIter->pNextLeaf = 0;
- pIter->iLeafPgno = iLeafPgno-1;
- fts5SegIterNextPage(p, pIter);
- assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno );
-
- if( p->rc==SQLITE_OK ){
- int iOff;
- u8 *a = pIter->pLeaf->p;
- int n = pIter->pLeaf->szLeaf;
-
- iOff = fts5LeafFirstRowidOff(pIter->pLeaf);
- if( iOff<4 || iOff>=n ){
- p->rc = FTS5_CORRUPT;
- }else{
- iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid);
- pIter->iLeafOffset = iOff;
- fts5SegIterLoadNPos(p, pIter);
- }
- }
- }
-}
-
-/*
-** Advance the iterator passed as the second argument until it is at or
-** past rowid iFrom. Regardless of the value of iFrom, the iterator is
-** always advanced at least once.
-*/
-static void fts5SegIterNextFrom(
- Fts5Index *p, /* FTS5 backend object */
- Fts5SegIter *pIter, /* Iterator to advance */
- i64 iMatch /* Advance iterator at least this far */
-){
- int bRev = (pIter->flags & FTS5_SEGITER_REVERSE);
- Fts5DlidxIter *pDlidx = pIter->pDlidx;
- int iLeafPgno = pIter->iLeafPgno;
- int bMove = 1;
-
- assert( pIter->flags & FTS5_SEGITER_ONETERM );
- assert( pIter->pDlidx );
- assert( pIter->pLeaf );
-
- if( bRev==0 ){
- while( !fts5DlidxIterEof(p, pDlidx) && iMatch>fts5DlidxIterRowid(pDlidx) ){
- iLeafPgno = fts5DlidxIterPgno(pDlidx);
- fts5DlidxIterNext(p, pDlidx);
- }
- assert_nc( iLeafPgno>=pIter->iLeafPgno || p->rc );
- if( iLeafPgno>pIter->iLeafPgno ){
- fts5SegIterGotoPage(p, pIter, iLeafPgno);
- bMove = 0;
- }
- }else{
- assert( pIter->pNextLeaf==0 );
- assert( iMatch<pIter->iRowid );
- while( !fts5DlidxIterEof(p, pDlidx) && iMatch<fts5DlidxIterRowid(pDlidx) ){
- fts5DlidxIterPrev(p, pDlidx);
- }
- iLeafPgno = fts5DlidxIterPgno(pDlidx);
-
- assert( fts5DlidxIterEof(p, pDlidx) || iLeafPgno<=pIter->iLeafPgno );
-
- if( iLeafPgno<pIter->iLeafPgno ){
- pIter->iLeafPgno = iLeafPgno+1;
- fts5SegIterReverseNewPage(p, pIter);
- bMove = 0;
- }
- }
-
- do{
- if( bMove && p->rc==SQLITE_OK ) pIter->xNext(p, pIter, 0);
- if( pIter->pLeaf==0 ) break;
- if( bRev==0 && pIter->iRowid>=iMatch ) break;
- if( bRev!=0 && pIter->iRowid<=iMatch ) break;
- bMove = 1;
- }while( p->rc==SQLITE_OK );
-}
-
-
-/*
-** Free the iterator object passed as the second argument.
-*/
-static void fts5MultiIterFree(Fts5Iter *pIter){
- if( pIter ){
- int i;
- for(i=0; i<pIter->nSeg; i++){
- fts5SegIterClear(&pIter->aSeg[i]);
- }
- fts5StructureRelease(pIter->pStruct);
- fts5BufferFree(&pIter->poslist);
- sqlite3_free(pIter);
- }
-}
-
-static void fts5MultiIterAdvanced(
- Fts5Index *p, /* FTS5 backend to iterate within */
- Fts5Iter *pIter, /* Iterator to update aFirst[] array for */
- int iChanged, /* Index of sub-iterator just advanced */
- int iMinset /* Minimum entry in aFirst[] to set */
-){
- int i;
- for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){
- int iEq;
- if( (iEq = fts5MultiIterDoCompare(pIter, i)) ){
- Fts5SegIter *pSeg = &pIter->aSeg[iEq];
- assert( p->rc==SQLITE_OK );
- pSeg->xNext(p, pSeg, 0);
- i = pIter->nSeg + iEq;
- }
- }
-}
-
-/*
-** Sub-iterator iChanged of iterator pIter has just been advanced. It still
-** points to the same term though - just a different rowid. This function
-** attempts to update the contents of the pIter->aFirst[] accordingly.
-** If it does so successfully, 0 is returned. Otherwise 1.
-**
-** If non-zero is returned, the caller should call fts5MultiIterAdvanced()
-** on the iterator instead. That function does the same as this one, except
-** that it deals with more complicated cases as well.
-*/
-static int fts5MultiIterAdvanceRowid(
- Fts5Iter *pIter, /* Iterator to update aFirst[] array for */
- int iChanged, /* Index of sub-iterator just advanced */
- Fts5SegIter **ppFirst
-){
- Fts5SegIter *pNew = &pIter->aSeg[iChanged];
-
- if( pNew->iRowid==pIter->iSwitchRowid
- || (pNew->iRowid<pIter->iSwitchRowid)==pIter->bRev
- ){
- int i;
- Fts5SegIter *pOther = &pIter->aSeg[iChanged ^ 0x0001];
- pIter->iSwitchRowid = pIter->bRev ? SMALLEST_INT64 : LARGEST_INT64;
- for(i=(pIter->nSeg+iChanged)/2; 1; i=i/2){
- Fts5CResult *pRes = &pIter->aFirst[i];
-
- assert( pNew->pLeaf );
- assert( pRes->bTermEq==0 || pOther->pLeaf );
-
- if( pRes->bTermEq ){
- if( pNew->iRowid==pOther->iRowid ){
- return 1;
- }else if( (pOther->iRowid>pNew->iRowid)==pIter->bRev ){
- pIter->iSwitchRowid = pOther->iRowid;
- pNew = pOther;
- }else if( (pOther->iRowid>pIter->iSwitchRowid)==pIter->bRev ){
- pIter->iSwitchRowid = pOther->iRowid;
- }
- }
- pRes->iFirst = (u16)(pNew - pIter->aSeg);
- if( i==1 ) break;
-
- pOther = &pIter->aSeg[ pIter->aFirst[i ^ 0x0001].iFirst ];
- }
- }
-
- *ppFirst = pNew;
- return 0;
-}
-
-/*
-** Set the pIter->bEof variable based on the state of the sub-iterators.
-*/
-static void fts5MultiIterSetEof(Fts5Iter *pIter){
- Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
- pIter->base.bEof = pSeg->pLeaf==0;
- pIter->iSwitchRowid = pSeg->iRowid;
-}
-
-/*
-** Move the iterator to the next entry.
-**
-** If an error occurs, an error code is left in Fts5Index.rc. It is not
-** considered an error if the iterator reaches EOF, or if it is already at
-** EOF when this function is called.
-*/
-static void fts5MultiIterNext(
- Fts5Index *p,
- Fts5Iter *pIter,
- int bFrom, /* True if argument iFrom is valid */
- i64 iFrom /* Advance at least as far as this */
-){
- int bUseFrom = bFrom;
- assert( pIter->base.bEof==0 );
- while( p->rc==SQLITE_OK ){
- int iFirst = pIter->aFirst[1].iFirst;
- int bNewTerm = 0;
- Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
- assert( p->rc==SQLITE_OK );
- if( bUseFrom && pSeg->pDlidx ){
- fts5SegIterNextFrom(p, pSeg, iFrom);
- }else{
- pSeg->xNext(p, pSeg, &bNewTerm);
- }
-
- if( pSeg->pLeaf==0 || bNewTerm
- || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg)
- ){
- fts5MultiIterAdvanced(p, pIter, iFirst, 1);
- fts5MultiIterSetEof(pIter);
- pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
- if( pSeg->pLeaf==0 ) return;
- }
-
- fts5AssertMultiIterSetup(p, pIter);
- assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf );
- if( pIter->bSkipEmpty==0 || pSeg->nPos ){
- pIter->xSetOutputs(pIter, pSeg);
- return;
- }
- bUseFrom = 0;
- }
-}
-
-static void fts5MultiIterNext2(
- Fts5Index *p,
- Fts5Iter *pIter,
- int *pbNewTerm /* OUT: True if *might* be new term */
-){
- assert( pIter->bSkipEmpty );
- if( p->rc==SQLITE_OK ){
- *pbNewTerm = 0;
- do{
- int iFirst = pIter->aFirst[1].iFirst;
- Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
- int bNewTerm = 0;
-
- assert( p->rc==SQLITE_OK );
- pSeg->xNext(p, pSeg, &bNewTerm);
- if( pSeg->pLeaf==0 || bNewTerm
- || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg)
- ){
- fts5MultiIterAdvanced(p, pIter, iFirst, 1);
- fts5MultiIterSetEof(pIter);
- *pbNewTerm = 1;
- }
- fts5AssertMultiIterSetup(p, pIter);
-
- }while( fts5MultiIterIsEmpty(p, pIter) );
- }
-}
-
-static void fts5IterSetOutputs_Noop(Fts5Iter *pUnused1, Fts5SegIter *pUnused2){
- UNUSED_PARAM2(pUnused1, pUnused2);
-}
-
-static Fts5Iter *fts5MultiIterAlloc(
- Fts5Index *p, /* FTS5 backend to iterate within */
- int nSeg
-){
- Fts5Iter *pNew;
- int nSlot; /* Power of two >= nSeg */
-
- for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
- pNew = fts5IdxMalloc(p,
- sizeof(Fts5Iter) + /* pNew */
- sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */
- sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
- );
- if( pNew ){
- pNew->nSeg = nSlot;
- pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot];
- pNew->pIndex = p;
- pNew->xSetOutputs = fts5IterSetOutputs_Noop;
- }
- return pNew;
-}
-
-static void fts5PoslistCallback(
- Fts5Index *pUnused,
- void *pContext,
- const u8 *pChunk, int nChunk
-){
- UNUSED_PARAM(pUnused);
- assert_nc( nChunk>=0 );
- if( nChunk>0 ){
- fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk);
- }
-}
-
-typedef struct PoslistCallbackCtx PoslistCallbackCtx;
-struct PoslistCallbackCtx {
- Fts5Buffer *pBuf; /* Append to this buffer */
- Fts5Colset *pColset; /* Restrict matches to this column */
- int eState; /* See above */
-};
-
-typedef struct PoslistOffsetsCtx PoslistOffsetsCtx;
-struct PoslistOffsetsCtx {
- Fts5Buffer *pBuf; /* Append to this buffer */
- Fts5Colset *pColset; /* Restrict matches to this column */
- int iRead;
- int iWrite;
-};
-
-/*
-** TODO: Make this more efficient!
-*/
-static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
- int i;
- for(i=0; i<pColset->nCol; i++){
- if( pColset->aiCol[i]==iCol ) return 1;
- }
- return 0;
-}
-
-static void fts5PoslistOffsetsCallback(
- Fts5Index *pUnused,
- void *pContext,
- const u8 *pChunk, int nChunk
-){
- PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext;
- UNUSED_PARAM(pUnused);
- assert_nc( nChunk>=0 );
- if( nChunk>0 ){
- int i = 0;
- while( i<nChunk ){
- int iVal;
- i += fts5GetVarint32(&pChunk[i], iVal);
- iVal += pCtx->iRead - 2;
- pCtx->iRead = iVal;
- if( fts5IndexColsetTest(pCtx->pColset, iVal) ){
- fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite);
- pCtx->iWrite = iVal;
- }
- }
- }
-}
-
-static void fts5PoslistFilterCallback(
- Fts5Index *pUnused,
- void *pContext,
- const u8 *pChunk, int nChunk
-){
- PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext;
- UNUSED_PARAM(pUnused);
- assert_nc( nChunk>=0 );
- if( nChunk>0 ){
- /* Search through to find the first varint with value 1. This is the
- ** start of the next columns hits. */
- int i = 0;
- int iStart = 0;
-
- if( pCtx->eState==2 ){
- int iCol;
- fts5FastGetVarint32(pChunk, i, iCol);
- if( fts5IndexColsetTest(pCtx->pColset, iCol) ){
- pCtx->eState = 1;
- fts5BufferSafeAppendVarint(pCtx->pBuf, 1);
- }else{
- pCtx->eState = 0;
- }
- }
-
- do {
- while( i<nChunk && pChunk[i]!=0x01 ){
- while( pChunk[i] & 0x80 ) i++;
- i++;
- }
- if( pCtx->eState ){
- fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
- }
- if( i<nChunk ){
- int iCol;
- iStart = i;
- i++;
- if( i>=nChunk ){
- pCtx->eState = 2;
- }else{
- fts5FastGetVarint32(pChunk, i, iCol);
- pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol);
- if( pCtx->eState ){
- fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
- iStart = i;
- }
- }
- }
- }while( i<nChunk );
- }
-}
-
-static void fts5ChunkIterate(
- Fts5Index *p, /* Index object */
- Fts5SegIter *pSeg, /* Poslist of this iterator */
- void *pCtx, /* Context pointer for xChunk callback */
- void (*xChunk)(Fts5Index*, void*, const u8*, int)
-){
- int nRem = pSeg->nPos; /* Number of bytes still to come */
- Fts5Data *pData = 0;
- u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset];
- int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset);
- int pgno = pSeg->iLeafPgno;
- int pgnoSave = 0;
-
- /* This function does notmwork with detail=none databases. */
- assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
-
- if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
- pgnoSave = pgno+1;
- }
-
- while( 1 ){
- xChunk(p, pCtx, pChunk, nChunk);
- nRem -= nChunk;
- fts5DataRelease(pData);
- if( nRem<=0 ){
- break;
- }else{
- pgno++;
- pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
- if( pData==0 ) break;
- pChunk = &pData->p[4];
- nChunk = MIN(nRem, pData->szLeaf - 4);
- if( pgno==pgnoSave ){
- assert( pSeg->pNextLeaf==0 );
- pSeg->pNextLeaf = pData;
- pData = 0;
- }
- }
- }
-}
-
-/*
-** Iterator pIter currently points to a valid entry (not EOF). This
-** function appends the position list data for the current entry to
-** buffer pBuf. It does not make a copy of the position-list size
-** field.
-*/
-static void fts5SegiterPoslist(
- Fts5Index *p,
- Fts5SegIter *pSeg,
- Fts5Colset *pColset,
- Fts5Buffer *pBuf
-){
- if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
- if( pColset==0 ){
- fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
- }else{
- if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
- PoslistCallbackCtx sCtx;
- sCtx.pBuf = pBuf;
- sCtx.pColset = pColset;
- sCtx.eState = fts5IndexColsetTest(pColset, 0);
- assert( sCtx.eState==0 || sCtx.eState==1 );
- fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
- }else{
- PoslistOffsetsCtx sCtx;
- memset(&sCtx, 0, sizeof(sCtx));
- sCtx.pBuf = pBuf;
- sCtx.pColset = pColset;
- fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback);
- }
- }
- }
-}
-
-/*
-** IN/OUT parameter (*pa) points to a position list n bytes in size. If
-** the position list contains entries for column iCol, then (*pa) is set
-** to point to the sub-position-list for that column and the number of
-** bytes in it returned. Or, if the argument position list does not
-** contain any entries for column iCol, return 0.
-*/
-static int fts5IndexExtractCol(
- const u8 **pa, /* IN/OUT: Pointer to poslist */
- int n, /* IN: Size of poslist in bytes */
- int iCol /* Column to extract from poslist */
-){
- int iCurrent = 0; /* Anything before the first 0x01 is col 0 */
- const u8 *p = *pa;
- const u8 *pEnd = &p[n]; /* One byte past end of position list */
-
- while( iCol>iCurrent ){
- /* Advance pointer p until it points to pEnd or an 0x01 byte that is
- ** not part of a varint. Note that it is not possible for a negative
- ** or extremely large varint to occur within an uncorrupted position
- ** list. So the last byte of each varint may be assumed to have a clear
- ** 0x80 bit. */
- while( *p!=0x01 ){
- while( *p++ & 0x80 );
- if( p>=pEnd ) return 0;
- }
- *pa = p++;
- iCurrent = *p++;
- if( iCurrent & 0x80 ){
- p--;
- p += fts5GetVarint32(p, iCurrent);
- }
- }
- if( iCol!=iCurrent ) return 0;
-
- /* Advance pointer p until it points to pEnd or an 0x01 byte that is
- ** not part of a varint */
- while( p<pEnd && *p!=0x01 ){
- while( *p++ & 0x80 );
- }
-
- return p - (*pa);
-}
-
-static void fts5IndexExtractColset(
- int *pRc,
- Fts5Colset *pColset, /* Colset to filter on */
- const u8 *pPos, int nPos, /* Position list */
- Fts5Buffer *pBuf /* Output buffer */
-){
- if( *pRc==SQLITE_OK ){
- int i;
- fts5BufferZero(pBuf);
- for(i=0; i<pColset->nCol; i++){
- const u8 *pSub = pPos;
- int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
- if( nSub ){
- fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
- }
- }
- }
-}
-
-/*
-** xSetOutputs callback used by detail=none tables.
-*/
-static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){
- assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE );
- pIter->base.iRowid = pSeg->iRowid;
- pIter->base.nData = pSeg->nPos;
-}
-
-/*
-** xSetOutputs callback used by detail=full and detail=col tables when no
-** column filters are specified.
-*/
-static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){
- pIter->base.iRowid = pSeg->iRowid;
- pIter->base.nData = pSeg->nPos;
-
- assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE );
- assert( pIter->pColset==0 );
-
- if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
- /* All data is stored on the current page. Populate the output
- ** variables to point into the body of the page object. */
- pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset];
- }else{
- /* The data is distributed over two or more pages. Copy it into the
- ** Fts5Iter.poslist buffer and then set the output pointer to point
- ** to this buffer. */
- fts5BufferZero(&pIter->poslist);
- fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist);
- pIter->base.pData = pIter->poslist.p;
- }
-}
-
-/*
-** xSetOutputs callback used when the Fts5Colset object has nCol==0 (match
-** against no columns at all).
-*/
-static void fts5IterSetOutputs_ZeroColset(Fts5Iter *pIter, Fts5SegIter *pSeg){
- UNUSED_PARAM(pSeg);
- pIter->base.nData = 0;
-}
-
-/*
-** xSetOutputs callback used by detail=col when there is a column filter
-** and there are 100 or more columns. Also called as a fallback from
-** fts5IterSetOutputs_Col100 if the column-list spans more than one page.
-*/
-static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){
- fts5BufferZero(&pIter->poslist);
- fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist);
- pIter->base.iRowid = pSeg->iRowid;
- pIter->base.pData = pIter->poslist.p;
- pIter->base.nData = pIter->poslist.n;
-}
-
-/*
-** xSetOutputs callback used when:
-**
-** * detail=col,
-** * there is a column filter, and
-** * the table contains 100 or fewer columns.
-**
-** The last point is to ensure all column numbers are stored as
-** single-byte varints.
-*/
-static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
-
- assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
- assert( pIter->pColset );
-
- if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
- fts5IterSetOutputs_Col(pIter, pSeg);
- }else{
- u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
- u8 *pEnd = (u8*)&a[pSeg->nPos];
- int iPrev = 0;
- int *aiCol = pIter->pColset->aiCol;
- int *aiColEnd = &aiCol[pIter->pColset->nCol];
-
- u8 *aOut = pIter->poslist.p;
- int iPrevOut = 0;
-
- pIter->base.iRowid = pSeg->iRowid;
-
- while( a<pEnd ){
- iPrev += (int)a++[0] - 2;
- while( *aiCol<iPrev ){
- aiCol++;
- if( aiCol==aiColEnd ) goto setoutputs_col_out;
- }
- if( *aiCol==iPrev ){
- *aOut++ = (u8)((iPrev - iPrevOut) + 2);
- iPrevOut = iPrev;
- }
- }
-
-setoutputs_col_out:
- pIter->base.pData = pIter->poslist.p;
- pIter->base.nData = aOut - pIter->poslist.p;
- }
-}
-
-/*
-** xSetOutputs callback used by detail=full when there is a column filter.
-*/
-static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
- Fts5Colset *pColset = pIter->pColset;
- pIter->base.iRowid = pSeg->iRowid;
-
- assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL );
- assert( pColset );
-
- if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
- /* All data is stored on the current page. Populate the output
- ** variables to point into the body of the page object. */
- const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
- if( pColset->nCol==1 ){
- pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
- pIter->base.pData = a;
- }else{
- int *pRc = &pIter->pIndex->rc;
- fts5BufferZero(&pIter->poslist);
- fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
- pIter->base.pData = pIter->poslist.p;
- pIter->base.nData = pIter->poslist.n;
- }
- }else{
- /* The data is distributed over two or more pages. Copy it into the
- ** Fts5Iter.poslist buffer and then set the output pointer to point
- ** to this buffer. */
- fts5BufferZero(&pIter->poslist);
- fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
- pIter->base.pData = pIter->poslist.p;
- pIter->base.nData = pIter->poslist.n;
- }
-}
-
-static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
- if( *pRc==SQLITE_OK ){
- Fts5Config *pConfig = pIter->pIndex->pConfig;
- if( pConfig->eDetail==FTS5_DETAIL_NONE ){
- pIter->xSetOutputs = fts5IterSetOutputs_None;
- }
-
- else if( pIter->pColset==0 ){
- pIter->xSetOutputs = fts5IterSetOutputs_Nocolset;
- }
-
- else if( pIter->pColset->nCol==0 ){
- pIter->xSetOutputs = fts5IterSetOutputs_ZeroColset;
- }
-
- else if( pConfig->eDetail==FTS5_DETAIL_FULL ){
- pIter->xSetOutputs = fts5IterSetOutputs_Full;
- }
-
- else{
- assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS );
- if( pConfig->nCol<=100 ){
- pIter->xSetOutputs = fts5IterSetOutputs_Col100;
- sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol);
- }else{
- pIter->xSetOutputs = fts5IterSetOutputs_Col;
- }
- }
- }
-}
-
-
-/*
-** Allocate a new Fts5Iter object.
-**
-** The new object will be used to iterate through data in structure pStruct.
-** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel
-** is zero or greater, data from the first nSegment segments on level iLevel
-** is merged.
-**
-** The iterator initially points to the first term/rowid entry in the
-** iterated data.
-*/
-static void fts5MultiIterNew(
- Fts5Index *p, /* FTS5 backend to iterate within */
- Fts5Structure *pStruct, /* Structure of specific index */
- int flags, /* FTS5INDEX_QUERY_XXX flags */
- Fts5Colset *pColset, /* Colset to filter on (or NULL) */
- const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */
- int iLevel, /* Level to iterate (-1 for all) */
- int nSegment, /* Number of segments to merge (iLevel>=0) */
- Fts5Iter **ppOut /* New object */
-){
- int nSeg = 0; /* Number of segment-iters in use */
- int iIter = 0; /* */
- int iSeg; /* Used to iterate through segments */
- Fts5StructureLevel *pLvl;
- Fts5Iter *pNew;
-
- assert( (pTerm==0 && nTerm==0) || iLevel<0 );
-
- /* Allocate space for the new multi-seg-iterator. */
- if( p->rc==SQLITE_OK ){
- if( iLevel<0 ){
- assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
- nSeg = pStruct->nSegment;
- nSeg += (p->pHash ? 1 : 0);
- }else{
- nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment);
- }
- }
- *ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
- if( pNew==0 ) return;
- pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
- pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
- pNew->pStruct = pStruct;
- pNew->pColset = pColset;
- fts5StructureRef(pStruct);
- if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
- fts5IterSetOutputCb(&p->rc, pNew);
- }
-
- /* Initialize each of the component segment iterators. */
- if( p->rc==SQLITE_OK ){
- if( iLevel<0 ){
- Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel];
- if( p->pHash ){
- /* Add a segment iterator for the current contents of the hash table. */
- Fts5SegIter *pIter = &pNew->aSeg[iIter++];
- fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter);
- }
- for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){
- for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){
- Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
- Fts5SegIter *pIter = &pNew->aSeg[iIter++];
- if( pTerm==0 ){
- fts5SegIterInit(p, pSeg, pIter);
- }else{
- fts5SegIterSeekInit(p, pTerm, nTerm, flags, pSeg, pIter);
- }
- }
- }
- }else{
- pLvl = &pStruct->aLevel[iLevel];
- for(iSeg=nSeg-1; iSeg>=0; iSeg--){
- fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]);
- }
- }
- assert( iIter==nSeg );
- }
-
- /* If the above was successful, each component iterators now points
- ** to the first entry in its segment. In this case initialize the
- ** aFirst[] array. Or, if an error has occurred, free the iterator
- ** object and set the output variable to NULL. */
- if( p->rc==SQLITE_OK ){
- for(iIter=pNew->nSeg-1; iIter>0; iIter--){
- int iEq;
- if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){
- Fts5SegIter *pSeg = &pNew->aSeg[iEq];
- if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0);
- fts5MultiIterAdvanced(p, pNew, iEq, iIter);
- }
- }
- fts5MultiIterSetEof(pNew);
- fts5AssertMultiIterSetup(p, pNew);
-
- if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){
- fts5MultiIterNext(p, pNew, 0, 0);
- }else if( pNew->base.bEof==0 ){
- Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst];
- pNew->xSetOutputs(pNew, pSeg);
- }
-
- }else{
- fts5MultiIterFree(pNew);
- *ppOut = 0;
- }
-}
-
-/*
-** Create an Fts5Iter that iterates through the doclist provided
-** as the second argument.
-*/
-static void fts5MultiIterNew2(
- Fts5Index *p, /* FTS5 backend to iterate within */
- Fts5Data *pData, /* Doclist to iterate through */
- int bDesc, /* True for descending rowid order */
- Fts5Iter **ppOut /* New object */
-){
- Fts5Iter *pNew;
- pNew = fts5MultiIterAlloc(p, 2);
- if( pNew ){
- Fts5SegIter *pIter = &pNew->aSeg[1];
-
- pIter->flags = FTS5_SEGITER_ONETERM;
- if( pData->szLeaf>0 ){
- pIter->pLeaf = pData;
- pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid);
- pIter->iEndofDoclist = pData->nn;
- pNew->aFirst[1].iFirst = 1;
- if( bDesc ){
- pNew->bRev = 1;
- pIter->flags |= FTS5_SEGITER_REVERSE;
- fts5SegIterReverseInitPage(p, pIter);
- }else{
- fts5SegIterLoadNPos(p, pIter);
- }
- pData = 0;
- }else{
- pNew->base.bEof = 1;
- }
- fts5SegIterSetNext(p, pIter);
-
- *ppOut = pNew;
- }
-
- fts5DataRelease(pData);
-}
-
-/*
-** Return true if the iterator is at EOF or if an error has occurred.
-** False otherwise.
-*/
-static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
- assert( p->rc
- || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof
- );
- return (p->rc || pIter->base.bEof);
-}
-
-/*
-** Return the rowid of the entry that the iterator currently points
-** to. If the iterator points to EOF when this function is called the
-** results are undefined.
-*/
-static i64 fts5MultiIterRowid(Fts5Iter *pIter){
- assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf );
- return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid;
-}
-
-/*
-** Move the iterator to the next entry at or following iMatch.
-*/
-static void fts5MultiIterNextFrom(
- Fts5Index *p,
- Fts5Iter *pIter,
- i64 iMatch
-){
- while( 1 ){
- i64 iRowid;
- fts5MultiIterNext(p, pIter, 1, iMatch);
- if( fts5MultiIterEof(p, pIter) ) break;
- iRowid = fts5MultiIterRowid(pIter);
- if( pIter->bRev==0 && iRowid>=iMatch ) break;
- if( pIter->bRev!=0 && iRowid<=iMatch ) break;
- }
-}
-
-/*
-** Return a pointer to a buffer containing the term associated with the
-** entry that the iterator currently points to.
-*/
-static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){
- Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
- *pn = p->term.n;
- return p->term.p;
-}
-
-/*
-** Allocate a new segment-id for the structure pStruct. The new segment
-** id must be between 1 and 65335 inclusive, and must not be used by
-** any currently existing segment. If a free segment id cannot be found,
-** SQLITE_FULL is returned.
-**
-** If an error has already occurred, this function is a no-op. 0 is
-** returned in this case.
-*/
-static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
- int iSegid = 0;
-
- if( p->rc==SQLITE_OK ){
- if( pStruct->nSegment>=FTS5_MAX_SEGMENT ){
- p->rc = SQLITE_FULL;
- }else{
- /* FTS5_MAX_SEGMENT is currently defined as 2000. So the following
- ** array is 63 elements, or 252 bytes, in size. */
- u32 aUsed[(FTS5_MAX_SEGMENT+31) / 32];
- int iLvl, iSeg;
- int i;
- u32 mask;
- memset(aUsed, 0, sizeof(aUsed));
- for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
- for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
- int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid;
- if( iId<=FTS5_MAX_SEGMENT ){
- aUsed[(iId-1) / 32] |= 1 << ((iId-1) % 32);
- }
- }
- }
-
- for(i=0; aUsed[i]==0xFFFFFFFF; i++);
- mask = aUsed[i];
- for(iSegid=0; mask & (1 << iSegid); iSegid++);
- iSegid += 1 + i*32;
-
-#ifdef SQLITE_DEBUG
- for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
- for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
- assert( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
- }
- }
- assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
-
- {
- sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p);
- if( p->rc==SQLITE_OK ){
- u8 aBlob[2] = {0xff, 0xff};
- sqlite3_bind_int(pIdxSelect, 1, iSegid);
- sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
- assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
- p->rc = sqlite3_reset(pIdxSelect);
- sqlite3_bind_null(pIdxSelect, 2);
- }
- }
-#endif
- }
- }
-
- return iSegid;
-}
-
-/*
-** Discard all data currently cached in the hash-tables.
-*/
-static void fts5IndexDiscardData(Fts5Index *p){
- assert( p->pHash || p->nPendingData==0 );
- if( p->pHash ){
- sqlite3Fts5HashClear(p->pHash);
- p->nPendingData = 0;
- }
-}
-
-/*
-** Return the size of the prefix, in bytes, that buffer
-** (pNew/<length-unknown>) shares with buffer (pOld/nOld).
-**
-** Buffer (pNew/<length-unknown>) is guaranteed to be greater
-** than buffer (pOld/nOld).
-*/
-static int fts5PrefixCompress(int nOld, const u8 *pOld, const u8 *pNew){
- int i;
- for(i=0; i<nOld; i++){
- if( pOld[i]!=pNew[i] ) break;
- }
- return i;
-}
-
-static void fts5WriteDlidxClear(
- Fts5Index *p,
- Fts5SegWriter *pWriter,
- int bFlush /* If true, write dlidx to disk */
-){
- int i;
- assert( bFlush==0 || (pWriter->nDlidx>0 && pWriter->aDlidx[0].buf.n>0) );
- for(i=0; i<pWriter->nDlidx; i++){
- Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[i];
- if( pDlidx->buf.n==0 ) break;
- if( bFlush ){
- assert( pDlidx->pgno!=0 );
- fts5DataWrite(p,
- FTS5_DLIDX_ROWID(pWriter->iSegid, i, pDlidx->pgno),
- pDlidx->buf.p, pDlidx->buf.n
- );
- }
- sqlite3Fts5BufferZero(&pDlidx->buf);
- pDlidx->bPrevValid = 0;
- }
-}
-
-/*
-** Grow the pWriter->aDlidx[] array to at least nLvl elements in size.
-** Any new array elements are zeroed before returning.
-*/
-static int fts5WriteDlidxGrow(
- Fts5Index *p,
- Fts5SegWriter *pWriter,
- int nLvl
-){
- if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){
- Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc(
- pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl
- );
- if( aDlidx==0 ){
- p->rc = SQLITE_NOMEM;
- }else{
- int nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx);
- memset(&aDlidx[pWriter->nDlidx], 0, nByte);
- pWriter->aDlidx = aDlidx;
- pWriter->nDlidx = nLvl;
- }
- }
- return p->rc;
-}
-
-/*
-** If the current doclist-index accumulating in pWriter->aDlidx[] is large
-** enough, flush it to disk and return 1. Otherwise discard it and return
-** zero.
-*/
-static int fts5WriteFlushDlidx(Fts5Index *p, Fts5SegWriter *pWriter){
- int bFlag = 0;
-
- /* If there were FTS5_MIN_DLIDX_SIZE or more empty leaf pages written
- ** to the database, also write the doclist-index to disk. */
- if( pWriter->aDlidx[0].buf.n>0 && pWriter->nEmpty>=FTS5_MIN_DLIDX_SIZE ){
- bFlag = 1;
- }
- fts5WriteDlidxClear(p, pWriter, bFlag);
- pWriter->nEmpty = 0;
- return bFlag;
-}
-
-/*
-** This function is called whenever processing of the doclist for the
-** last term on leaf page (pWriter->iBtPage) is completed.
-**
-** The doclist-index for that term is currently stored in-memory within the
-** Fts5SegWriter.aDlidx[] array. If it is large enough, this function
-** writes it out to disk. Or, if it is too small to bother with, discards
-** it.
-**
-** Fts5SegWriter.btterm currently contains the first term on page iBtPage.
-*/
-static void fts5WriteFlushBtree(Fts5Index *p, Fts5SegWriter *pWriter){
- int bFlag;
-
- assert( pWriter->iBtPage || pWriter->nEmpty==0 );
- if( pWriter->iBtPage==0 ) return;
- bFlag = fts5WriteFlushDlidx(p, pWriter);
-
- if( p->rc==SQLITE_OK ){
- const char *z = (pWriter->btterm.n>0?(const char*)pWriter->btterm.p:"");
- /* The following was already done in fts5WriteInit(): */
- /* sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid); */
- sqlite3_bind_blob(p->pIdxWriter, 2, z, pWriter->btterm.n, SQLITE_STATIC);
- sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1));
- sqlite3_step(p->pIdxWriter);
- p->rc = sqlite3_reset(p->pIdxWriter);
- sqlite3_bind_null(p->pIdxWriter, 2);
- }
- pWriter->iBtPage = 0;
-}
-
-/*
-** This is called once for each leaf page except the first that contains
-** at least one term. Argument (nTerm/pTerm) is the split-key - a term that
-** is larger than all terms written to earlier leaves, and equal to or
-** smaller than the first term on the new leaf.
-**
-** If an error occurs, an error code is left in Fts5Index.rc. If an error
-** has already occurred when this function is called, it is a no-op.
-*/
-static void fts5WriteBtreeTerm(
- Fts5Index *p, /* FTS5 backend object */
- Fts5SegWriter *pWriter, /* Writer object */
- int nTerm, const u8 *pTerm /* First term on new page */
-){
- fts5WriteFlushBtree(p, pWriter);
- fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
- pWriter->iBtPage = pWriter->writer.pgno;
-}
-
-/*
-** This function is called when flushing a leaf page that contains no
-** terms at all to disk.
-*/
-static void fts5WriteBtreeNoTerm(
- Fts5Index *p, /* FTS5 backend object */
- Fts5SegWriter *pWriter /* Writer object */
-){
- /* If there were no rowids on the leaf page either and the doclist-index
- ** has already been started, append an 0x00 byte to it. */
- if( pWriter->bFirstRowidInPage && pWriter->aDlidx[0].buf.n>0 ){
- Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[0];
- assert( pDlidx->bPrevValid );
- sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, 0);
- }
-
- /* Increment the "number of sequential leaves without a term" counter. */
- pWriter->nEmpty++;
-}
-
-static i64 fts5DlidxExtractFirstRowid(Fts5Buffer *pBuf){
- i64 iRowid;
- int iOff;
-
- iOff = 1 + fts5GetVarint(&pBuf->p[1], (u64*)&iRowid);
- fts5GetVarint(&pBuf->p[iOff], (u64*)&iRowid);
- return iRowid;
-}
-
-/*
-** Rowid iRowid has just been appended to the current leaf page. It is the
-** first on the page. This function appends an appropriate entry to the current
-** doclist-index.
-*/
-static void fts5WriteDlidxAppend(
- Fts5Index *p,
- Fts5SegWriter *pWriter,
- i64 iRowid
-){
- int i;
- int bDone = 0;
-
- for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
- i64 iVal;
- Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[i];
-
- if( pDlidx->buf.n>=p->pConfig->pgsz ){
- /* The current doclist-index page is full. Write it to disk and push
- ** a copy of iRowid (which will become the first rowid on the next
- ** doclist-index leaf page) up into the next level of the b-tree
- ** hierarchy. If the node being flushed is currently the root node,
- ** also push its first rowid upwards. */
- pDlidx->buf.p[0] = 0x01; /* Not the root node */
- fts5DataWrite(p,
- FTS5_DLIDX_ROWID(pWriter->iSegid, i, pDlidx->pgno),
- pDlidx->buf.p, pDlidx->buf.n
- );
- fts5WriteDlidxGrow(p, pWriter, i+2);
- pDlidx = &pWriter->aDlidx[i];
- if( p->rc==SQLITE_OK && pDlidx[1].buf.n==0 ){
- i64 iFirst = fts5DlidxExtractFirstRowid(&pDlidx->buf);
-
- /* This was the root node. Push its first rowid up to the new root. */
- pDlidx[1].pgno = pDlidx->pgno;
- sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, 0);
- sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, pDlidx->pgno);
- sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, iFirst);
- pDlidx[1].bPrevValid = 1;
- pDlidx[1].iPrev = iFirst;
- }
-
- sqlite3Fts5BufferZero(&pDlidx->buf);
- pDlidx->bPrevValid = 0;
- pDlidx->pgno++;
- }else{
- bDone = 1;
- }
-
- if( pDlidx->bPrevValid ){
- iVal = iRowid - pDlidx->iPrev;
- }else{
- i64 iPgno = (i==0 ? pWriter->writer.pgno : pDlidx[-1].pgno);
- assert( pDlidx->buf.n==0 );
- sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, !bDone);
- sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, iPgno);
- iVal = iRowid;
- }
-
- sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, iVal);
- pDlidx->bPrevValid = 1;
- pDlidx->iPrev = iRowid;
- }
-}
-
-static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){
- static const u8 zero[] = { 0x00, 0x00, 0x00, 0x00 };
- Fts5PageWriter *pPage = &pWriter->writer;
- i64 iRowid;
-
- assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) );
-
- /* Set the szLeaf header field. */
- assert( 0==fts5GetU16(&pPage->buf.p[2]) );
- fts5PutU16(&pPage->buf.p[2], (u16)pPage->buf.n);
-
- if( pWriter->bFirstTermInPage ){
- /* No term was written to this page. */
- assert( pPage->pgidx.n==0 );
- fts5WriteBtreeNoTerm(p, pWriter);
- }else{
- /* Append the pgidx to the page buffer. Set the szLeaf header field. */
- fts5BufferAppendBlob(&p->rc, &pPage->buf, pPage->pgidx.n, pPage->pgidx.p);
- }
-
- /* Write the page out to disk */
- iRowid = FTS5_SEGMENT_ROWID(pWriter->iSegid, pPage->pgno);
- fts5DataWrite(p, iRowid, pPage->buf.p, pPage->buf.n);
-
- /* Initialize the next page. */
- fts5BufferZero(&pPage->buf);
- fts5BufferZero(&pPage->pgidx);
- fts5BufferAppendBlob(&p->rc, &pPage->buf, 4, zero);
- pPage->iPrevPgidx = 0;
- pPage->pgno++;
-
- /* Increase the leaves written counter */
- pWriter->nLeafWritten++;
-
- /* The new leaf holds no terms or rowids */
- pWriter->bFirstTermInPage = 1;
- pWriter->bFirstRowidInPage = 1;
-}
-
-/*
-** Append term pTerm/nTerm to the segment being written by the writer passed
-** as the second argument.
-**
-** If an error occurs, set the Fts5Index.rc error code. If an error has
-** already occurred, this function is a no-op.
-*/
-static void fts5WriteAppendTerm(
- Fts5Index *p,
- Fts5SegWriter *pWriter,
- int nTerm, const u8 *pTerm
-){
- int nPrefix; /* Bytes of prefix compression for term */
- Fts5PageWriter *pPage = &pWriter->writer;
- Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
-
- assert( p->rc==SQLITE_OK );
- assert( pPage->buf.n>=4 );
- assert( pPage->buf.n>4 || pWriter->bFirstTermInPage );
-
- /* If the current leaf page is full, flush it to disk. */
- if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){
- if( pPage->buf.n>4 ){
- fts5WriteFlushLeaf(p, pWriter);
- }
- fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING);
- }
-
- /* TODO1: Updating pgidx here. */
- pPgidx->n += sqlite3Fts5PutVarint(
- &pPgidx->p[pPgidx->n], pPage->buf.n - pPage->iPrevPgidx
- );
- pPage->iPrevPgidx = pPage->buf.n;
-#if 0
- fts5PutU16(&pPgidx->p[pPgidx->n], pPage->buf.n);
- pPgidx->n += 2;
-#endif
-
- if( pWriter->bFirstTermInPage ){
- nPrefix = 0;
- if( pPage->pgno!=1 ){
- /* This is the first term on a leaf that is not the leftmost leaf in
- ** the segment b-tree. In this case it is necessary to add a term to
- ** the b-tree hierarchy that is (a) larger than the largest term
- ** already written to the segment and (b) smaller than or equal to
- ** this term. In other words, a prefix of (pTerm/nTerm) that is one
- ** byte longer than the longest prefix (pTerm/nTerm) shares with the
- ** previous term.
- **
- ** Usually, the previous term is available in pPage->term. The exception
- ** is if this is the first term written in an incremental-merge step.
- ** In this case the previous term is not available, so just write a
- ** copy of (pTerm/nTerm) into the parent node. This is slightly
- ** inefficient, but still correct. */
- int n = nTerm;
- if( pPage->term.n ){
- n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
- }
- fts5WriteBtreeTerm(p, pWriter, n, pTerm);
- pPage = &pWriter->writer;
- }
- }else{
- nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
- fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix);
- }
-
- /* Append the number of bytes of new data, then the term data itself
- ** to the page. */
- fts5BufferAppendVarint(&p->rc, &pPage->buf, nTerm - nPrefix);
- fts5BufferAppendBlob(&p->rc, &pPage->buf, nTerm - nPrefix, &pTerm[nPrefix]);
-
- /* Update the Fts5PageWriter.term field. */
- fts5BufferSet(&p->rc, &pPage->term, nTerm, pTerm);
- pWriter->bFirstTermInPage = 0;
-
- pWriter->bFirstRowidInPage = 0;
- pWriter->bFirstRowidInDoclist = 1;
-
- assert( p->rc || (pWriter->nDlidx>0 && pWriter->aDlidx[0].buf.n==0) );
- pWriter->aDlidx[0].pgno = pPage->pgno;
-}
-
-/*
-** Append a rowid and position-list size field to the writers output.
-*/
-static void fts5WriteAppendRowid(
- Fts5Index *p,
- Fts5SegWriter *pWriter,
- i64 iRowid
-){
- if( p->rc==SQLITE_OK ){
- Fts5PageWriter *pPage = &pWriter->writer;
-
- if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){
- fts5WriteFlushLeaf(p, pWriter);
- }
-
- /* If this is to be the first rowid written to the page, set the
- ** rowid-pointer in the page-header. Also append a value to the dlidx
- ** buffer, in case a doclist-index is required. */
- if( pWriter->bFirstRowidInPage ){
- fts5PutU16(pPage->buf.p, (u16)pPage->buf.n);
- fts5WriteDlidxAppend(p, pWriter, iRowid);
- }
-
- /* Write the rowid. */
- if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){
- fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
- }else{
- assert( p->rc || iRowid>pWriter->iPrevRowid );
- fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
- }
- pWriter->iPrevRowid = iRowid;
- pWriter->bFirstRowidInDoclist = 0;
- pWriter->bFirstRowidInPage = 0;
- }
-}
-
-static void fts5WriteAppendPoslistData(
- Fts5Index *p,
- Fts5SegWriter *pWriter,
- const u8 *aData,
- int nData
-){
- Fts5PageWriter *pPage = &pWriter->writer;
- const u8 *a = aData;
- int n = nData;
-
- assert( p->pConfig->pgsz>0 );
- while( p->rc==SQLITE_OK
- && (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz
- ){
- int nReq = p->pConfig->pgsz - pPage->buf.n - pPage->pgidx.n;
- int nCopy = 0;
- while( nCopy<nReq ){
- i64 dummy;
- nCopy += fts5GetVarint(&a[nCopy], (u64*)&dummy);
- }
- fts5BufferAppendBlob(&p->rc, &pPage->buf, nCopy, a);
- a += nCopy;
- n -= nCopy;
- fts5WriteFlushLeaf(p, pWriter);
- }
- if( n>0 ){
- fts5BufferAppendBlob(&p->rc, &pPage->buf, n, a);
- }
-}
-
-/*
-** Flush any data cached by the writer object to the database. Free any
-** allocations associated with the writer.
-*/
-static void fts5WriteFinish(
- Fts5Index *p,
- Fts5SegWriter *pWriter, /* Writer object */
- int *pnLeaf /* OUT: Number of leaf pages in b-tree */
-){
- int i;
- Fts5PageWriter *pLeaf = &pWriter->writer;
- if( p->rc==SQLITE_OK ){
- assert( pLeaf->pgno>=1 );
- if( pLeaf->buf.n>4 ){
- fts5WriteFlushLeaf(p, pWriter);
- }
- *pnLeaf = pLeaf->pgno-1;
- if( pLeaf->pgno>1 ){
- fts5WriteFlushBtree(p, pWriter);
- }
- }
- fts5BufferFree(&pLeaf->term);
- fts5BufferFree(&pLeaf->buf);
- fts5BufferFree(&pLeaf->pgidx);
- fts5BufferFree(&pWriter->btterm);
-
- for(i=0; i<pWriter->nDlidx; i++){
- sqlite3Fts5BufferFree(&pWriter->aDlidx[i].buf);
- }
- sqlite3_free(pWriter->aDlidx);
-}
-
-static void fts5WriteInit(
- Fts5Index *p,
- Fts5SegWriter *pWriter,
- int iSegid
-){
- const int nBuffer = p->pConfig->pgsz + FTS5_DATA_PADDING;
-
- memset(pWriter, 0, sizeof(Fts5SegWriter));
- pWriter->iSegid = iSegid;
-
- fts5WriteDlidxGrow(p, pWriter, 1);
- pWriter->writer.pgno = 1;
- pWriter->bFirstTermInPage = 1;
- pWriter->iBtPage = 1;
-
- assert( pWriter->writer.buf.n==0 );
- assert( pWriter->writer.pgidx.n==0 );
-
- /* Grow the two buffers to pgsz + padding bytes in size. */
- sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.pgidx, nBuffer);
- sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.buf, nBuffer);
-
- if( p->pIdxWriter==0 ){
- Fts5Config *pConfig = p->pConfig;
- fts5IndexPrepareStmt(p, &p->pIdxWriter, sqlite3_mprintf(
- "INSERT INTO '%q'.'%q_idx'(segid,term,pgno) VALUES(?,?,?)",
- pConfig->zDb, pConfig->zName
- ));
- }
-
- if( p->rc==SQLITE_OK ){
- /* Initialize the 4-byte leaf-page header to 0x00. */
- memset(pWriter->writer.buf.p, 0, 4);
- pWriter->writer.buf.n = 4;
-
- /* Bind the current output segment id to the index-writer. This is an
- ** optimization over binding the same value over and over as rows are
- ** inserted into %_idx by the current writer. */
- sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid);
- }
-}
-
-/*
-** Iterator pIter was used to iterate through the input segments of on an
-** incremental merge operation. This function is called if the incremental
-** merge step has finished but the input has not been completely exhausted.
-*/
-static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
- int i;
- Fts5Buffer buf;
- memset(&buf, 0, sizeof(Fts5Buffer));
- for(i=0; i<pIter->nSeg; i++){
- Fts5SegIter *pSeg = &pIter->aSeg[i];
- if( pSeg->pSeg==0 ){
- /* no-op */
- }else if( pSeg->pLeaf==0 ){
- /* All keys from this input segment have been transfered to the output.
- ** Set both the first and last page-numbers to 0 to indicate that the
- ** segment is now empty. */
- pSeg->pSeg->pgnoLast = 0;
- pSeg->pSeg->pgnoFirst = 0;
- }else{
- int iOff = pSeg->iTermLeafOffset; /* Offset on new first leaf page */
- i64 iLeafRowid;
- Fts5Data *pData;
- int iId = pSeg->pSeg->iSegid;
- u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00};
-
- iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno);
- pData = fts5DataRead(p, iLeafRowid);
- if( pData ){
- fts5BufferZero(&buf);
- fts5BufferGrow(&p->rc, &buf, pData->nn);
- fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
- fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
- fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
- fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]);
- if( p->rc==SQLITE_OK ){
- /* Set the szLeaf field */
- fts5PutU16(&buf.p[2], (u16)buf.n);
- }
-
- /* Set up the new page-index array */
- fts5BufferAppendVarint(&p->rc, &buf, 4);
- if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
- && pSeg->iEndofDoclist<pData->szLeaf
- ){
- int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
- fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
- fts5BufferAppendBlob(&p->rc, &buf,
- pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
- );
- }
-
- fts5DataRelease(pData);
- pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
- fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
- fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
- }
- }
- }
- fts5BufferFree(&buf);
-}
-
-static void fts5MergeChunkCallback(
- Fts5Index *p,
- void *pCtx,
- const u8 *pChunk, int nChunk
-){
- Fts5SegWriter *pWriter = (Fts5SegWriter*)pCtx;
- fts5WriteAppendPoslistData(p, pWriter, pChunk, nChunk);
-}
-
-/*
-**
-*/
-static void fts5IndexMergeLevel(
- Fts5Index *p, /* FTS5 backend object */
- Fts5Structure **ppStruct, /* IN/OUT: Stucture of index */
- int iLvl, /* Level to read input from */
- int *pnRem /* Write up to this many output leaves */
-){
- Fts5Structure *pStruct = *ppStruct;
- Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
- Fts5StructureLevel *pLvlOut;
- Fts5Iter *pIter = 0; /* Iterator to read input data */
- int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */
- int nInput; /* Number of input segments */
- Fts5SegWriter writer; /* Writer object */
- Fts5StructureSegment *pSeg; /* Output segment */
- Fts5Buffer term;
- int bOldest; /* True if the output segment is the oldest */
- int eDetail = p->pConfig->eDetail;
- const int flags = FTS5INDEX_QUERY_NOOUTPUT;
- int bTermWritten = 0; /* True if current term already output */
-
- assert( iLvl<pStruct->nLevel );
- assert( pLvl->nMerge<=pLvl->nSeg );
-
- memset(&writer, 0, sizeof(Fts5SegWriter));
- memset(&term, 0, sizeof(Fts5Buffer));
- if( pLvl->nMerge ){
- pLvlOut = &pStruct->aLevel[iLvl+1];
- assert( pLvlOut->nSeg>0 );
- nInput = pLvl->nMerge;
- pSeg = &pLvlOut->aSeg[pLvlOut->nSeg-1];
-
- fts5WriteInit(p, &writer, pSeg->iSegid);
- writer.writer.pgno = pSeg->pgnoLast+1;
- writer.iBtPage = 0;
- }else{
- int iSegid = fts5AllocateSegid(p, pStruct);
-
- /* Extend the Fts5Structure object as required to ensure the output
- ** segment exists. */
- if( iLvl==pStruct->nLevel-1 ){
- fts5StructureAddLevel(&p->rc, ppStruct);
- pStruct = *ppStruct;
- }
- fts5StructureExtendLevel(&p->rc, pStruct, iLvl+1, 1, 0);
- if( p->rc ) return;
- pLvl = &pStruct->aLevel[iLvl];
- pLvlOut = &pStruct->aLevel[iLvl+1];
-
- fts5WriteInit(p, &writer, iSegid);
-
- /* Add the new segment to the output level */
- pSeg = &pLvlOut->aSeg[pLvlOut->nSeg];
- pLvlOut->nSeg++;
- pSeg->pgnoFirst = 1;
- pSeg->iSegid = iSegid;
- pStruct->nSegment++;
-
- /* Read input from all segments in the input level */
- nInput = pLvl->nSeg;
- }
- bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2);
-
- assert( iLvl>=0 );
- for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter);
- fts5MultiIterEof(p, pIter)==0;
- fts5MultiIterNext(p, pIter, 0, 0)
- ){
- Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
- int nPos; /* position-list size field value */
- int nTerm;
- const u8 *pTerm;
-
- pTerm = fts5MultiIterTerm(pIter, &nTerm);
- if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
- if( pnRem && writer.nLeafWritten>nRem ){
- break;
- }
- fts5BufferSet(&p->rc, &term, nTerm, pTerm);
- bTermWritten =0;
- }
-
- /* Check for key annihilation. */
- if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue;
-
- if( p->rc==SQLITE_OK && bTermWritten==0 ){
- /* This is a new term. Append a term to the output segment. */
- fts5WriteAppendTerm(p, &writer, nTerm, pTerm);
- bTermWritten = 1;
- }
-
- /* Append the rowid to the output */
- /* WRITEPOSLISTSIZE */
- fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter));
-
- if( eDetail==FTS5_DETAIL_NONE ){
- if( pSegIter->bDel ){
- fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0);
- if( pSegIter->nPos>0 ){
- fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0);
- }
- }
- }else{
- /* Append the position-list data to the output */
- nPos = pSegIter->nPos*2 + pSegIter->bDel;
- fts5BufferAppendVarint(&p->rc, &writer.writer.buf, nPos);
- fts5ChunkIterate(p, pSegIter, (void*)&writer, fts5MergeChunkCallback);
- }
- }
-
- /* Flush the last leaf page to disk. Set the output segment b-tree height
- ** and last leaf page number at the same time. */
- fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
-
- if( fts5MultiIterEof(p, pIter) ){
- int i;
-
- /* Remove the redundant segments from the %_data table */
- for(i=0; i<nInput; i++){
- fts5DataRemoveSegment(p, pLvl->aSeg[i].iSegid);
- }
-
- /* Remove the redundant segments from the input level */
- if( pLvl->nSeg!=nInput ){
- int nMove = (pLvl->nSeg - nInput) * sizeof(Fts5StructureSegment);
- memmove(pLvl->aSeg, &pLvl->aSeg[nInput], nMove);
- }
- pStruct->nSegment -= nInput;
- pLvl->nSeg -= nInput;
- pLvl->nMerge = 0;
- if( pSeg->pgnoLast==0 ){
- pLvlOut->nSeg--;
- pStruct->nSegment--;
- }
- }else{
- assert( pSeg->pgnoLast>0 );
- fts5TrimSegments(p, pIter);
- pLvl->nMerge = nInput;
- }
-
- fts5MultiIterFree(pIter);
- fts5BufferFree(&term);
- if( pnRem ) *pnRem -= writer.nLeafWritten;
-}
-
-/*
-** Do up to nPg pages of automerge work on the index.
-**
-** Return true if any changes were actually made, or false otherwise.
-*/
-static int fts5IndexMerge(
- Fts5Index *p, /* FTS5 backend object */
- Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
- int nPg, /* Pages of work to do */
- int nMin /* Minimum number of segments to merge */
-){
- int nRem = nPg;
- int bRet = 0;
- Fts5Structure *pStruct = *ppStruct;
- while( nRem>0 && p->rc==SQLITE_OK ){
- int iLvl; /* To iterate through levels */
- int iBestLvl = 0; /* Level offering the most input segments */
- int nBest = 0; /* Number of input segments on best level */
-
- /* Set iBestLvl to the level to read input segments from. */
- assert( pStruct->nLevel>0 );
- for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
- Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
- if( pLvl->nMerge ){
- if( pLvl->nMerge>nBest ){
- iBestLvl = iLvl;
- nBest = pLvl->nMerge;
- }
- break;
- }
- if( pLvl->nSeg>nBest ){
- nBest = pLvl->nSeg;
- iBestLvl = iLvl;
- }
- }
-
- /* If nBest is still 0, then the index must be empty. */
-#ifdef SQLITE_DEBUG
- for(iLvl=0; nBest==0 && iLvl<pStruct->nLevel; iLvl++){
- assert( pStruct->aLevel[iLvl].nSeg==0 );
- }
-#endif
-
- if( nBest<nMin && pStruct->aLevel[iBestLvl].nMerge==0 ){
- break;
- }
- bRet = 1;
- fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem);
- if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){
- fts5StructurePromote(p, iBestLvl+1, pStruct);
- }
- }
- *ppStruct = pStruct;
- return bRet;
-}
-
-/*
-** A total of nLeaf leaf pages of data has just been flushed to a level-0
-** segment. This function updates the write-counter accordingly and, if
-** necessary, performs incremental merge work.
-**
-** If an error occurs, set the Fts5Index.rc error code. If an error has
-** already occurred, this function is a no-op.
-*/
-static void fts5IndexAutomerge(
- Fts5Index *p, /* FTS5 backend object */
- Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
- int nLeaf /* Number of output leaves just written */
-){
- if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 ){
- Fts5Structure *pStruct = *ppStruct;
- u64 nWrite; /* Initial value of write-counter */
- int nWork; /* Number of work-quanta to perform */
- int nRem; /* Number of leaf pages left to write */
-
- /* Update the write-counter. While doing so, set nWork. */
- nWrite = pStruct->nWriteCounter;
- nWork = (int)(((nWrite + nLeaf) / p->nWorkUnit) - (nWrite / p->nWorkUnit));
- pStruct->nWriteCounter += nLeaf;
- nRem = (int)(p->nWorkUnit * nWork * pStruct->nLevel);
-
- fts5IndexMerge(p, ppStruct, nRem, p->pConfig->nAutomerge);
- }
-}
-
-static void fts5IndexCrisismerge(
- Fts5Index *p, /* FTS5 backend object */
- Fts5Structure **ppStruct /* IN/OUT: Current structure of index */
-){
- const int nCrisis = p->pConfig->nCrisisMerge;
- Fts5Structure *pStruct = *ppStruct;
- int iLvl = 0;
-
- assert( p->rc!=SQLITE_OK || pStruct->nLevel>0 );
- while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){
- fts5IndexMergeLevel(p, &pStruct, iLvl, 0);
- assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) );
- fts5StructurePromote(p, iLvl+1, pStruct);
- iLvl++;
- }
- *ppStruct = pStruct;
-}
-
-static int fts5IndexReturn(Fts5Index *p){
- int rc = p->rc;
- p->rc = SQLITE_OK;
- return rc;
-}
-
-typedef struct Fts5FlushCtx Fts5FlushCtx;
-struct Fts5FlushCtx {
- Fts5Index *pIdx;
- Fts5SegWriter writer;
-};
-
-/*
-** Buffer aBuf[] contains a list of varints, all small enough to fit
-** in a 32-bit integer. Return the size of the largest prefix of this
-** list nMax bytes or less in size.
-*/
-static int fts5PoslistPrefix(const u8 *aBuf, int nMax){
- int ret;
- u32 dummy;
- ret = fts5GetVarint32(aBuf, dummy);
- if( ret<nMax ){
- while( 1 ){
- int i = fts5GetVarint32(&aBuf[ret], dummy);
- if( (ret + i) > nMax ) break;
- ret += i;
- }
- }
- return ret;
-}
-
-/*
-** Flush the contents of in-memory hash table iHash to a new level-0
-** segment on disk. Also update the corresponding structure record.
-**
-** If an error occurs, set the Fts5Index.rc error code. If an error has
-** already occurred, this function is a no-op.
-*/
-static void fts5FlushOneHash(Fts5Index *p){
- Fts5Hash *pHash = p->pHash;
- Fts5Structure *pStruct;
- int iSegid;
- int pgnoLast = 0; /* Last leaf page number in segment */
-
- /* Obtain a reference to the index structure and allocate a new segment-id
- ** for the new level-0 segment. */
- pStruct = fts5StructureRead(p);
- iSegid = fts5AllocateSegid(p, pStruct);
- fts5StructureInvalidate(p);
-
- if( iSegid ){
- const int pgsz = p->pConfig->pgsz;
- int eDetail = p->pConfig->eDetail;
- Fts5StructureSegment *pSeg; /* New segment within pStruct */
- Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */
- Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */
-
- Fts5SegWriter writer;
- fts5WriteInit(p, &writer, iSegid);
-
- pBuf = &writer.writer.buf;
- pPgidx = &writer.writer.pgidx;
-
- /* fts5WriteInit() should have initialized the buffers to (most likely)
- ** the maximum space required. */
- assert( p->rc || pBuf->nSpace>=(pgsz + FTS5_DATA_PADDING) );
- assert( p->rc || pPgidx->nSpace>=(pgsz + FTS5_DATA_PADDING) );
-
- /* Begin scanning through hash table entries. This loop runs once for each
- ** term/doclist currently stored within the hash table. */
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0);
- }
- while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){
- const char *zTerm; /* Buffer containing term */
- const u8 *pDoclist; /* Pointer to doclist for this term */
- int nDoclist; /* Size of doclist in bytes */
-
- /* Write the term for this entry to disk. */
- sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
- fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm);
-
- assert( writer.bFirstRowidInPage==0 );
- if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
- /* The entire doclist will fit on the current leaf. */
- fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
- }else{
- i64 iRowid = 0;
- i64 iDelta = 0;
- int iOff = 0;
-
- /* The entire doclist will not fit on this leaf. The following
- ** loop iterates through the poslists that make up the current
- ** doclist. */
- while( p->rc==SQLITE_OK && iOff<nDoclist ){
- iOff += fts5GetVarint(&pDoclist[iOff], (u64*)&iDelta);
- iRowid += iDelta;
-
- if( writer.bFirstRowidInPage ){
- fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */
- pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
- writer.bFirstRowidInPage = 0;
- fts5WriteDlidxAppend(p, &writer, iRowid);
- }else{
- pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
- }
- assert( pBuf->n<=pBuf->nSpace );
-
- if( eDetail==FTS5_DETAIL_NONE ){
- if( iOff<nDoclist && pDoclist[iOff]==0 ){
- pBuf->p[pBuf->n++] = 0;
- iOff++;
- if( iOff<nDoclist && pDoclist[iOff]==0 ){
- pBuf->p[pBuf->n++] = 0;
- iOff++;
- }
- }
- if( (pBuf->n + pPgidx->n)>=pgsz ){
- fts5WriteFlushLeaf(p, &writer);
- }
- }else{
- int bDummy;
- int nPos;
- int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy);
- nCopy += nPos;
- if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){
- /* The entire poslist will fit on the current leaf. So copy
- ** it in one go. */
- fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy);
- }else{
- /* The entire poslist will not fit on this leaf. So it needs
- ** to be broken into sections. The only qualification being
- ** that each varint must be stored contiguously. */
- const u8 *pPoslist = &pDoclist[iOff];
- int iPos = 0;
- while( p->rc==SQLITE_OK ){
- int nSpace = pgsz - pBuf->n - pPgidx->n;
- int n = 0;
- if( (nCopy - iPos)<=nSpace ){
- n = nCopy - iPos;
- }else{
- n = fts5PoslistPrefix(&pPoslist[iPos], nSpace);
- }
- assert( n>0 );
- fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n);
- iPos += n;
- if( (pBuf->n + pPgidx->n)>=pgsz ){
- fts5WriteFlushLeaf(p, &writer);
- }
- if( iPos>=nCopy ) break;
- }
- }
- iOff += nCopy;
- }
- }
- }
-
- /* TODO2: Doclist terminator written here. */
- /* pBuf->p[pBuf->n++] = '\0'; */
- assert( pBuf->n<=pBuf->nSpace );
- sqlite3Fts5HashScanNext(pHash);
- }
- sqlite3Fts5HashClear(pHash);
- fts5WriteFinish(p, &writer, &pgnoLast);
-
- /* Update the Fts5Structure. It is written back to the database by the
- ** fts5StructureRelease() call below. */
- if( pStruct->nLevel==0 ){
- fts5StructureAddLevel(&p->rc, &pStruct);
- }
- fts5StructureExtendLevel(&p->rc, pStruct, 0, 1, 0);
- if( p->rc==SQLITE_OK ){
- pSeg = &pStruct->aLevel[0].aSeg[ pStruct->aLevel[0].nSeg++ ];
- pSeg->iSegid = iSegid;
- pSeg->pgnoFirst = 1;
- pSeg->pgnoLast = pgnoLast;
- pStruct->nSegment++;
- }
- fts5StructurePromote(p, 0, pStruct);
- }
-
- fts5IndexAutomerge(p, &pStruct, pgnoLast);
- fts5IndexCrisismerge(p, &pStruct);
- fts5StructureWrite(p, pStruct);
- fts5StructureRelease(pStruct);
-}
-
-/*
-** Flush any data stored in the in-memory hash tables to the database.
-*/
-static void fts5IndexFlush(Fts5Index *p){
- /* Unless it is empty, flush the hash table to disk */
- if( p->nPendingData ){
- assert( p->pHash );
- p->nPendingData = 0;
- fts5FlushOneHash(p);
- }
-}
-
-static Fts5Structure *fts5IndexOptimizeStruct(
- Fts5Index *p,
- Fts5Structure *pStruct
-){
- Fts5Structure *pNew = 0;
- int nByte = sizeof(Fts5Structure);
- int nSeg = pStruct->nSegment;
- int i;
-
- /* Figure out if this structure requires optimization. A structure does
- ** not require optimization if either:
- **
- ** + it consists of fewer than two segments, or
- ** + all segments are on the same level, or
- ** + all segments except one are currently inputs to a merge operation.
- **
- ** In the first case, return NULL. In the second, increment the ref-count
- ** on *pStruct and return a copy of the pointer to it.
- */
- if( nSeg<2 ) return 0;
- for(i=0; i<pStruct->nLevel; i++){
- int nThis = pStruct->aLevel[i].nSeg;
- if( nThis==nSeg || (nThis==nSeg-1 && pStruct->aLevel[i].nMerge==nThis) ){
- fts5StructureRef(pStruct);
- return pStruct;
- }
- assert( pStruct->aLevel[i].nMerge<=nThis );
- }
-
- nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
- pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
-
- if( pNew ){
- Fts5StructureLevel *pLvl;
- nByte = nSeg * sizeof(Fts5StructureSegment);
- pNew->nLevel = pStruct->nLevel+1;
- pNew->nRef = 1;
- pNew->nWriteCounter = pStruct->nWriteCounter;
- pLvl = &pNew->aLevel[pStruct->nLevel];
- pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte);
- if( pLvl->aSeg ){
- int iLvl, iSeg;
- int iSegOut = 0;
- /* Iterate through all segments, from oldest to newest. Add them to
- ** the new Fts5Level object so that pLvl->aSeg[0] is the oldest
- ** segment in the data structure. */
- for(iLvl=pStruct->nLevel-1; iLvl>=0; iLvl--){
- for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
- pLvl->aSeg[iSegOut] = pStruct->aLevel[iLvl].aSeg[iSeg];
- iSegOut++;
- }
- }
- pNew->nSegment = pLvl->nSeg = nSeg;
- }else{
- sqlite3_free(pNew);
- pNew = 0;
- }
- }
-
- return pNew;
-}
-
-int sqlite3Fts5IndexOptimize(Fts5Index *p){
- Fts5Structure *pStruct;
- Fts5Structure *pNew = 0;
-
- assert( p->rc==SQLITE_OK );
- fts5IndexFlush(p);
- pStruct = fts5StructureRead(p);
- fts5StructureInvalidate(p);
-
- if( pStruct ){
- pNew = fts5IndexOptimizeStruct(p, pStruct);
- }
- fts5StructureRelease(pStruct);
-
- assert( pNew==0 || pNew->nSegment>0 );
- if( pNew ){
- int iLvl;
- for(iLvl=0; pNew->aLevel[iLvl].nSeg==0; iLvl++){}
- while( p->rc==SQLITE_OK && pNew->aLevel[iLvl].nSeg>0 ){
- int nRem = FTS5_OPT_WORK_UNIT;
- fts5IndexMergeLevel(p, &pNew, iLvl, &nRem);
- }
-
- fts5StructureWrite(p, pNew);
- fts5StructureRelease(pNew);
- }
-
- return fts5IndexReturn(p);
-}
-
-/*
-** This is called to implement the special "VALUES('merge', $nMerge)"
-** INSERT command.
-*/
-int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
- Fts5Structure *pStruct = fts5StructureRead(p);
- if( pStruct ){
- int nMin = p->pConfig->nUsermerge;
- fts5StructureInvalidate(p);
- if( nMerge<0 ){
- Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct);
- fts5StructureRelease(pStruct);
- pStruct = pNew;
- nMin = 2;
- nMerge = nMerge*-1;
- }
- if( pStruct && pStruct->nLevel ){
- if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
- fts5StructureWrite(p, pStruct);
- }
- }
- fts5StructureRelease(pStruct);
- }
- return fts5IndexReturn(p);
-}
-
-static void fts5AppendRowid(
- Fts5Index *p,
- i64 iDelta,
- Fts5Iter *pUnused,
- Fts5Buffer *pBuf
-){
- UNUSED_PARAM(pUnused);
- fts5BufferAppendVarint(&p->rc, pBuf, iDelta);
-}
-
-static void fts5AppendPoslist(
- Fts5Index *p,
- i64 iDelta,
- Fts5Iter *pMulti,
- Fts5Buffer *pBuf
-){
- int nData = pMulti->base.nData;
- assert( nData>0 );
- if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){
- fts5BufferSafeAppendVarint(pBuf, iDelta);
- fts5BufferSafeAppendVarint(pBuf, nData*2);
- fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData);
- }
-}
-
-
-static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
- u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
-
- assert( pIter->aPoslist );
- if( p>=pIter->aEof ){
- pIter->aPoslist = 0;
- }else{
- i64 iDelta;
-
- p += fts5GetVarint(p, (u64*)&iDelta);
- pIter->iRowid += iDelta;
-
- /* Read position list size */
- if( p[0] & 0x80 ){
- int nPos;
- pIter->nSize = fts5GetVarint32(p, nPos);
- pIter->nPoslist = (nPos>>1);
- }else{
- pIter->nPoslist = ((int)(p[0])) >> 1;
- pIter->nSize = 1;
- }
-
- pIter->aPoslist = p;
- }
-}
-
-static void fts5DoclistIterInit(
- Fts5Buffer *pBuf,
- Fts5DoclistIter *pIter
-){
- memset(pIter, 0, sizeof(*pIter));
- pIter->aPoslist = pBuf->p;
- pIter->aEof = &pBuf->p[pBuf->n];
- fts5DoclistIterNext(pIter);
-}
-
-#if 0
-/*
-** Append a doclist to buffer pBuf.
-**
-** This function assumes that space within the buffer has already been
-** allocated.
-*/
-static void fts5MergeAppendDocid(
- Fts5Buffer *pBuf, /* Buffer to write to */
- i64 *piLastRowid, /* IN/OUT: Previous rowid written (if any) */
- i64 iRowid /* Rowid to append */
-){
- assert( pBuf->n!=0 || (*piLastRowid)==0 );
- fts5BufferSafeAppendVarint(pBuf, iRowid - *piLastRowid);
- *piLastRowid = iRowid;
-}
-#endif
-
-#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \
- assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \
- fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
- (iLastRowid) = (iRowid); \
-}
-
-/*
-** Swap the contents of buffer *p1 with that of *p2.
-*/
-static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){
- Fts5Buffer tmp = *p1;
- *p1 = *p2;
- *p2 = tmp;
-}
-
-static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){
- int i = *piOff;
- if( i>=pBuf->n ){
- *piOff = -1;
- }else{
- u64 iVal;
- *piOff = i + sqlite3Fts5GetVarint(&pBuf->p[i], &iVal);
- *piRowid += iVal;
- }
-}
-
-/*
-** This is the equivalent of fts5MergePrefixLists() for detail=none mode.
-** In this case the buffers consist of a delta-encoded list of rowids only.
-*/
-static void fts5MergeRowidLists(
- Fts5Index *p, /* FTS5 backend object */
- Fts5Buffer *p1, /* First list to merge */
- Fts5Buffer *p2 /* Second list to merge */
-){
- int i1 = 0;
- int i2 = 0;
- i64 iRowid1 = 0;
- i64 iRowid2 = 0;
- i64 iOut = 0;
-
- Fts5Buffer out;
- memset(&out, 0, sizeof(out));
- sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
- if( p->rc ) return;
-
- fts5NextRowid(p1, &i1, &iRowid1);
- fts5NextRowid(p2, &i2, &iRowid2);
- while( i1>=0 || i2>=0 ){
- if( i1>=0 && (i2<0 || iRowid1<iRowid2) ){
- assert( iOut==0 || iRowid1>iOut );
- fts5BufferSafeAppendVarint(&out, iRowid1 - iOut);
- iOut = iRowid1;
- fts5NextRowid(p1, &i1, &iRowid1);
- }else{
- assert( iOut==0 || iRowid2>iOut );
- fts5BufferSafeAppendVarint(&out, iRowid2 - iOut);
- iOut = iRowid2;
- if( i1>=0 && iRowid1==iRowid2 ){
- fts5NextRowid(p1, &i1, &iRowid1);
- }
- fts5NextRowid(p2, &i2, &iRowid2);
- }
- }
-
- fts5BufferSwap(&out, p1);
- fts5BufferFree(&out);
-}
-
-/*
-** Buffers p1 and p2 contain doclists. This function merges the content
-** of the two doclists together and sets buffer p1 to the result before
-** returning.
-**
-** If an error occurs, an error code is left in p->rc. If an error has
-** already occurred, this function is a no-op.
-*/
-static void fts5MergePrefixLists(
- Fts5Index *p, /* FTS5 backend object */
- Fts5Buffer *p1, /* First list to merge */
- Fts5Buffer *p2 /* Second list to merge */
-){
- if( p2->n ){
- i64 iLastRowid = 0;
- Fts5DoclistIter i1;
- Fts5DoclistIter i2;
- Fts5Buffer out = {0, 0, 0};
- Fts5Buffer tmp = {0, 0, 0};
-
- /* The maximum size of the output is equal to the sum of the two
- ** input sizes + 1 varint (9 bytes). The extra varint is because if the
- ** first rowid in one input is a large negative number, and the first in
- ** the other a non-negative number, the delta for the non-negative
- ** number will be larger on disk than the literal integer value
- ** was. */
- if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9) ) return;
- fts5DoclistIterInit(p1, &i1);
- fts5DoclistIterInit(p2, &i2);
-
- while( 1 ){
- if( i1.iRowid<i2.iRowid ){
- /* Copy entry from i1 */
- fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
- fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
- fts5DoclistIterNext(&i1);
- if( i1.aPoslist==0 ) break;
- }
- else if( i2.iRowid!=i1.iRowid ){
- /* Copy entry from i2 */
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
- fts5DoclistIterNext(&i2);
- if( i2.aPoslist==0 ) break;
- }
- else{
- /* Merge the two position lists. */
- i64 iPos1 = 0;
- i64 iPos2 = 0;
- int iOff1 = 0;
- int iOff2 = 0;
- u8 *a1 = &i1.aPoslist[i1.nSize];
- u8 *a2 = &i2.aPoslist[i2.nSize];
-
- i64 iPrev = 0;
- Fts5PoslistWriter writer;
- memset(&writer, 0, sizeof(writer));
-
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferZero(&tmp);
- sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist);
- if( p->rc ) break;
-
- sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- assert( iPos1>=0 && iPos2>=0 );
-
- if( iPos1<iPos2 ){
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- }else{
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- }
-
- if( iPos1>=0 && iPos2>=0 ){
- while( 1 ){
- if( iPos1<iPos2 ){
- if( iPos1!=iPrev ){
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- }
- sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- if( iPos1<0 ) break;
- }else{
- assert( iPos2!=iPrev );
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- if( iPos2<0 ) break;
- }
- }
- }
-
- if( iPos1>=0 ){
- if( iPos1!=iPrev ){
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- }
- fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1);
- }else{
- assert( iPos2>=0 && iPos2!=iPrev );
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2);
- }
-
- /* WRITEPOSLISTSIZE */
- fts5BufferSafeAppendVarint(&out, tmp.n * 2);
- fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
- fts5DoclistIterNext(&i1);
- fts5DoclistIterNext(&i2);
- if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
- }
- }
-
- if( i1.aPoslist ){
- fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
- fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist);
- }
- else if( i2.aPoslist ){
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
- }
- assert( out.n<=(p1->n+p2->n+9) );
-
- fts5BufferSet(&p->rc, p1, out.n, out.p);
- fts5BufferFree(&tmp);
- fts5BufferFree(&out);
- }
-}
-
-static void fts5SetupPrefixIter(
- Fts5Index *p, /* Index to read from */
- int bDesc, /* True for "ORDER BY rowid DESC" */
- const u8 *pToken, /* Buffer containing prefix to match */
- int nToken, /* Size of buffer pToken in bytes */
- Fts5Colset *pColset, /* Restrict matches to these columns */
- Fts5Iter **ppIter /* OUT: New iterator */
-){
- Fts5Structure *pStruct;
- Fts5Buffer *aBuf;
- const int nBuf = 32;
-
- void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
- void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
- if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
- xMerge = fts5MergeRowidLists;
- xAppend = fts5AppendRowid;
- }else{
- xMerge = fts5MergePrefixLists;
- xAppend = fts5AppendPoslist;
- }
-
- aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
- pStruct = fts5StructureRead(p);
-
- if( aBuf && pStruct ){
- const int flags = FTS5INDEX_QUERY_SCAN
- | FTS5INDEX_QUERY_SKIPEMPTY
- | FTS5INDEX_QUERY_NOOUTPUT;
- int i;
- i64 iLastRowid = 0;
- Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
- Fts5Data *pData;
- Fts5Buffer doclist;
- int bNewTerm = 1;
-
- memset(&doclist, 0, sizeof(doclist));
- fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
- fts5IterSetOutputCb(&p->rc, p1);
- for( /* no-op */ ;
- fts5MultiIterEof(p, p1)==0;
- fts5MultiIterNext2(p, p1, &bNewTerm)
- ){
- Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
- int nTerm = pSeg->term.n;
- const u8 *pTerm = pSeg->term.p;
- p1->xSetOutputs(p1, pSeg);
-
- assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
- if( bNewTerm ){
- if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
- }
-
- if( p1->base.nData==0 ) continue;
-
- if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
- for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
- assert( i<nBuf );
- if( aBuf[i].n==0 ){
- fts5BufferSwap(&doclist, &aBuf[i]);
- fts5BufferZero(&doclist);
- }else{
- xMerge(p, &doclist, &aBuf[i]);
- fts5BufferZero(&aBuf[i]);
- }
- }
- iLastRowid = 0;
- }
-
- xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
- iLastRowid = p1->base.iRowid;
- }
-
- for(i=0; i<nBuf; i++){
- if( p->rc==SQLITE_OK ){
- xMerge(p, &doclist, &aBuf[i]);
- }
- fts5BufferFree(&aBuf[i]);
- }
- fts5MultiIterFree(p1);
-
- pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n);
- if( pData ){
- pData->p = (u8*)&pData[1];
- pData->nn = pData->szLeaf = doclist.n;
- if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
- fts5MultiIterNew2(p, pData, bDesc, ppIter);
- }
- fts5BufferFree(&doclist);
- }
-
- fts5StructureRelease(pStruct);
- sqlite3_free(aBuf);
-}
-
-
-/*
-** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
-** to the document with rowid iRowid.
-*/
-int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
- assert( p->rc==SQLITE_OK );
-
- /* Allocate the hash table if it has not already been allocated */
- if( p->pHash==0 ){
- p->rc = sqlite3Fts5HashNew(p->pConfig, &p->pHash, &p->nPendingData);
- }
-
- /* Flush the hash table to disk if required */
- if( iRowid<p->iWriteRowid
- || (iRowid==p->iWriteRowid && p->bDelete==0)
- || (p->nPendingData > p->pConfig->nHashSize)
- ){
- fts5IndexFlush(p);
- }
-
- p->iWriteRowid = iRowid;
- p->bDelete = bDelete;
- return fts5IndexReturn(p);
-}
-
-/*
-** Commit data to disk.
-*/
-int sqlite3Fts5IndexSync(Fts5Index *p){
- assert( p->rc==SQLITE_OK );
- fts5IndexFlush(p);
- fts5CloseReader(p);
- return fts5IndexReturn(p);
-}
-
-/*
-** Discard any data stored in the in-memory hash tables. Do not write it
-** to the database. Additionally, assume that the contents of the %_data
-** table may have changed on disk. So any in-memory caches of %_data
-** records must be invalidated.
-*/
-int sqlite3Fts5IndexRollback(Fts5Index *p){
- fts5CloseReader(p);
- fts5IndexDiscardData(p);
- fts5StructureInvalidate(p);
- /* assert( p->rc==SQLITE_OK ); */
- return SQLITE_OK;
-}
-
-/*
-** The %_data table is completely empty when this function is called. This
-** function populates it with the initial structure objects for each index,
-** and the initial version of the "averages" record (a zero-byte blob).
-*/
-int sqlite3Fts5IndexReinit(Fts5Index *p){
- Fts5Structure s;
- fts5StructureInvalidate(p);
- memset(&s, 0, sizeof(Fts5Structure));
- fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
- fts5StructureWrite(p, &s);
- return fts5IndexReturn(p);
-}
-
-/*
-** Open a new Fts5Index handle. If the bCreate argument is true, create
-** and initialize the underlying %_data table.
-**
-** If successful, set *pp to point to the new object and return SQLITE_OK.
-** Otherwise, set *pp to NULL and return an SQLite error code.
-*/
-int sqlite3Fts5IndexOpen(
- Fts5Config *pConfig,
- int bCreate,
- Fts5Index **pp,
- char **pzErr
-){
- int rc = SQLITE_OK;
- Fts5Index *p; /* New object */
-
- *pp = p = (Fts5Index*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Index));
- if( rc==SQLITE_OK ){
- p->pConfig = pConfig;
- p->nWorkUnit = FTS5_WORK_UNIT;
- p->zDataTbl = sqlite3Fts5Mprintf(&rc, "%s_data", pConfig->zName);
- if( p->zDataTbl && bCreate ){
- rc = sqlite3Fts5CreateTable(
- pConfig, "data", "id INTEGER PRIMARY KEY, block BLOB", 0, pzErr
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5CreateTable(pConfig, "idx",
- "segid, term, pgno, PRIMARY KEY(segid, term)",
- 1, pzErr
- );
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexReinit(p);
- }
- }
- }
-
- assert( rc!=SQLITE_OK || p->rc==SQLITE_OK );
- if( rc ){
- sqlite3Fts5IndexClose(p);
- *pp = 0;
- }
- return rc;
-}
-
-/*
-** Close a handle opened by an earlier call to sqlite3Fts5IndexOpen().
-*/
-int sqlite3Fts5IndexClose(Fts5Index *p){
- int rc = SQLITE_OK;
- if( p ){
- assert( p->pReader==0 );
- fts5StructureInvalidate(p);
- sqlite3_finalize(p->pWriter);
- sqlite3_finalize(p->pDeleter);
- sqlite3_finalize(p->pIdxWriter);
- sqlite3_finalize(p->pIdxDeleter);
- sqlite3_finalize(p->pIdxSelect);
- sqlite3_finalize(p->pDataVersion);
- sqlite3Fts5HashFree(p->pHash);
- sqlite3_free(p->zDataTbl);
- sqlite3_free(p);
- }
- return rc;
-}
-
-/*
-** Argument p points to a buffer containing utf-8 text that is n bytes in
-** size. Return the number of bytes in the nChar character prefix of the
-** buffer, or 0 if there are less than nChar characters in total.
-*/
-int sqlite3Fts5IndexCharlenToBytelen(
- const char *p,
- int nByte,
- int nChar
-){
- int n = 0;
- int i;
- for(i=0; i<nChar; i++){
- if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
- if( (unsigned char)p[n++]>=0xc0 ){
- while( (p[n] & 0xc0)==0x80 ) n++;
- }
- }
- return n;
-}
-
-/*
-** pIn is a UTF-8 encoded string, nIn bytes in size. Return the number of
-** unicode characters in the string.
-*/
-static int fts5IndexCharlen(const char *pIn, int nIn){
- int nChar = 0;
- int i = 0;
- while( i<nIn ){
- if( (unsigned char)pIn[i++]>=0xc0 ){
- while( i<nIn && (pIn[i] & 0xc0)==0x80 ) i++;
- }
- nChar++;
- }
- return nChar;
-}
-
-/*
-** Insert or remove data to or from the index. Each time a document is
-** added to or removed from the index, this function is called one or more
-** times.
-**
-** For an insert, it must be called once for each token in the new document.
-** If the operation is a delete, it must be called (at least) once for each
-** unique token in the document with an iCol value less than zero. The iPos
-** argument is ignored for a delete.
-*/
-int sqlite3Fts5IndexWrite(
- Fts5Index *p, /* Index to write to */
- int iCol, /* Column token appears in (-ve -> delete) */
- int iPos, /* Position of token within column */
- const char *pToken, int nToken /* Token to add or remove to or from index */
-){
- int i; /* Used to iterate through indexes */
- int rc = SQLITE_OK; /* Return code */
- Fts5Config *pConfig = p->pConfig;
-
- assert( p->rc==SQLITE_OK );
- assert( (iCol<0)==p->bDelete );
-
- /* Add the entry to the main terms index. */
- rc = sqlite3Fts5HashWrite(
- p->pHash, p->iWriteRowid, iCol, iPos, FTS5_MAIN_PREFIX, pToken, nToken
- );
-
- for(i=0; i<pConfig->nPrefix && rc==SQLITE_OK; i++){
- const int nChar = pConfig->aPrefix[i];
- int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
- if( nByte ){
- rc = sqlite3Fts5HashWrite(p->pHash,
- p->iWriteRowid, iCol, iPos, (char)(FTS5_MAIN_PREFIX+i+1), pToken,
- nByte
- );
- }
- }
-
- return rc;
-}
-
-/*
-** Open a new iterator to iterate though all rowid that match the
-** specified token or token prefix.
-*/
-int sqlite3Fts5IndexQuery(
- Fts5Index *p, /* FTS index to query */
- const char *pToken, int nToken, /* Token (or prefix) to query for */
- int flags, /* Mask of FTS5INDEX_QUERY_X flags */
- Fts5Colset *pColset, /* Match these columns only */
- Fts5IndexIter **ppIter /* OUT: New iterator object */
-){
- Fts5Config *pConfig = p->pConfig;
- Fts5Iter *pRet = 0;
- Fts5Buffer buf = {0, 0, 0};
-
- /* If the QUERY_SCAN flag is set, all other flags must be clear. */
- assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
-
- if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
- int iIdx = 0; /* Index to search */
- if( nToken ) memcpy(&buf.p[1], pToken, nToken);
-
- /* Figure out which index to search and set iIdx accordingly. If this
- ** is a prefix query for which there is no prefix index, set iIdx to
- ** greater than pConfig->nPrefix to indicate that the query will be
- ** satisfied by scanning multiple terms in the main index.
- **
- ** If the QUERY_TEST_NOIDX flag was specified, then this must be a
- ** prefix-query. Instead of using a prefix-index (if one exists),
- ** evaluate the prefix query using the main FTS index. This is used
- ** for internal sanity checking by the integrity-check in debug
- ** mode only. */
-#ifdef SQLITE_DEBUG
- if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){
- assert( flags & FTS5INDEX_QUERY_PREFIX );
- iIdx = 1+pConfig->nPrefix;
- }else
-#endif
- if( flags & FTS5INDEX_QUERY_PREFIX ){
- int nChar = fts5IndexCharlen(pToken, nToken);
- for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
- if( pConfig->aPrefix[iIdx-1]==nChar ) break;
- }
- }
-
- if( iIdx<=pConfig->nPrefix ){
- /* Straight index lookup */
- Fts5Structure *pStruct = fts5StructureRead(p);
- buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
- if( pStruct ){
- fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY,
- pColset, buf.p, nToken+1, -1, 0, &pRet
- );
- fts5StructureRelease(pStruct);
- }
- }else{
- /* Scan multiple terms in the main index */
- int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
- buf.p[0] = FTS5_MAIN_PREFIX;
- fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
- assert( p->rc!=SQLITE_OK || pRet->pColset==0 );
- fts5IterSetOutputCb(&p->rc, pRet);
- if( p->rc==SQLITE_OK ){
- Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
- if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
- }
- }
-
- if( p->rc ){
- sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
- pRet = 0;
- fts5CloseReader(p);
- }
-
- *ppIter = &pRet->base;
- sqlite3Fts5BufferFree(&buf);
- }
- return fts5IndexReturn(p);
-}
-
-/*
-** Return true if the iterator passed as the only argument is at EOF.
-*/
-/*
-** Move to the next matching rowid.
-*/
-int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
- Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- assert( pIter->pIndex->rc==SQLITE_OK );
- fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
- return fts5IndexReturn(pIter->pIndex);
-}
-
-/*
-** Move to the next matching term/rowid. Used by the fts5vocab module.
-*/
-int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){
- Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- Fts5Index *p = pIter->pIndex;
-
- assert( pIter->pIndex->rc==SQLITE_OK );
-
- fts5MultiIterNext(p, pIter, 0, 0);
- if( p->rc==SQLITE_OK ){
- Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
- if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){
- fts5DataRelease(pSeg->pLeaf);
- pSeg->pLeaf = 0;
- pIter->base.bEof = 1;
- }
- }
-
- return fts5IndexReturn(pIter->pIndex);
-}
-
-/*
-** Move to the next matching rowid that occurs at or after iMatch. The
-** definition of "at or after" depends on whether this iterator iterates
-** in ascending or descending rowid order.
-*/
-int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
- Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
- return fts5IndexReturn(pIter->pIndex);
-}
-
-/*
-** Return the current term.
-*/
-const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
- int n;
- const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
- *pn = n-1;
- return &z[1];
-}
-
-/*
-** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery().
-*/
-void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
- if( pIndexIter ){
- Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- Fts5Index *pIndex = pIter->pIndex;
- fts5MultiIterFree(pIter);
- fts5CloseReader(pIndex);
- }
-}
-
-/*
-** Read and decode the "averages" record from the database.
-**
-** Parameter anSize must point to an array of size nCol, where nCol is
-** the number of user defined columns in the FTS table.
-*/
-int sqlite3Fts5IndexGetAverages(Fts5Index *p, i64 *pnRow, i64 *anSize){
- int nCol = p->pConfig->nCol;
- Fts5Data *pData;
-
- *pnRow = 0;
- memset(anSize, 0, sizeof(i64) * nCol);
- pData = fts5DataRead(p, FTS5_AVERAGES_ROWID);
- if( p->rc==SQLITE_OK && pData->nn ){
- int i = 0;
- int iCol;
- i += fts5GetVarint(&pData->p[i], (u64*)pnRow);
- for(iCol=0; i<pData->nn && iCol<nCol; iCol++){
- i += fts5GetVarint(&pData->p[i], (u64*)&anSize[iCol]);
- }
- }
-
- fts5DataRelease(pData);
- return fts5IndexReturn(p);
-}
-
-/*
-** Replace the current "averages" record with the contents of the buffer
-** supplied as the second argument.
-*/
-int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8 *pData, int nData){
- assert( p->rc==SQLITE_OK );
- fts5DataWrite(p, FTS5_AVERAGES_ROWID, pData, nData);
- return fts5IndexReturn(p);
-}
-
-/*
-** Return the total number of blocks this module has read from the %_data
-** table since it was created.
-*/
-int sqlite3Fts5IndexReads(Fts5Index *p){
- return p->nRead;
-}
-
-/*
-** Set the 32-bit cookie value stored at the start of all structure
-** records to the value passed as the second argument.
-**
-** Return SQLITE_OK if successful, or an SQLite error code if an error
-** occurs.
-*/
-int sqlite3Fts5IndexSetCookie(Fts5Index *p, int iNew){
- int rc; /* Return code */
- Fts5Config *pConfig = p->pConfig; /* Configuration object */
- u8 aCookie[4]; /* Binary representation of iNew */
- sqlite3_blob *pBlob = 0;
-
- assert( p->rc==SQLITE_OK );
- sqlite3Fts5Put32(aCookie, iNew);
-
- rc = sqlite3_blob_open(pConfig->db, pConfig->zDb, p->zDataTbl,
- "block", FTS5_STRUCTURE_ROWID, 1, &pBlob
- );
- if( rc==SQLITE_OK ){
- sqlite3_blob_write(pBlob, aCookie, 4, 0);
- rc = sqlite3_blob_close(pBlob);
- }
-
- return rc;
-}
-
-int sqlite3Fts5IndexLoadConfig(Fts5Index *p){
- Fts5Structure *pStruct;
- pStruct = fts5StructureRead(p);
- fts5StructureRelease(pStruct);
- return fts5IndexReturn(p);
-}
-
-
-/*************************************************************************
-**************************************************************************
-** Below this point is the implementation of the integrity-check
-** functionality.
-*/
-
-/*
-** Return a simple checksum value based on the arguments.
-*/
-u64 sqlite3Fts5IndexEntryCksum(
- i64 iRowid,
- int iCol,
- int iPos,
- int iIdx,
- const char *pTerm,
- int nTerm
-){
- int i;
- u64 ret = iRowid;
- ret += (ret<<3) + iCol;
- ret += (ret<<3) + iPos;
- if( iIdx>=0 ) ret += (ret<<3) + (FTS5_MAIN_PREFIX + iIdx);
- for(i=0; i<nTerm; i++) ret += (ret<<3) + pTerm[i];
- return ret;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** This function is purely an internal test. It does not contribute to
-** FTS functionality, or even the integrity-check, in any way.
-**
-** Instead, it tests that the same set of pgno/rowid combinations are
-** visited regardless of whether the doclist-index identified by parameters
-** iSegid/iLeaf is iterated in forwards or reverse order.
-*/
-static void fts5TestDlidxReverse(
- Fts5Index *p,
- int iSegid, /* Segment id to load from */
- int iLeaf /* Load doclist-index for this leaf */
-){
- Fts5DlidxIter *pDlidx = 0;
- u64 cksum1 = 13;
- u64 cksum2 = 13;
-
- for(pDlidx=fts5DlidxIterInit(p, 0, iSegid, iLeaf);
- fts5DlidxIterEof(p, pDlidx)==0;
- fts5DlidxIterNext(p, pDlidx)
- ){
- i64 iRowid = fts5DlidxIterRowid(pDlidx);
- int pgno = fts5DlidxIterPgno(pDlidx);
- assert( pgno>iLeaf );
- cksum1 += iRowid + ((i64)pgno<<32);
- }
- fts5DlidxIterFree(pDlidx);
- pDlidx = 0;
-
- for(pDlidx=fts5DlidxIterInit(p, 1, iSegid, iLeaf);
- fts5DlidxIterEof(p, pDlidx)==0;
- fts5DlidxIterPrev(p, pDlidx)
- ){
- i64 iRowid = fts5DlidxIterRowid(pDlidx);
- int pgno = fts5DlidxIterPgno(pDlidx);
- assert( fts5DlidxIterPgno(pDlidx)>iLeaf );
- cksum2 += iRowid + ((i64)pgno<<32);
- }
- fts5DlidxIterFree(pDlidx);
- pDlidx = 0;
-
- if( p->rc==SQLITE_OK && cksum1!=cksum2 ) p->rc = FTS5_CORRUPT;
-}
-
-static int fts5QueryCksum(
- Fts5Index *p, /* Fts5 index object */
- int iIdx,
- const char *z, /* Index key to query for */
- int n, /* Size of index key in bytes */
- int flags, /* Flags for Fts5IndexQuery */
- u64 *pCksum /* IN/OUT: Checksum value */
-){
- int eDetail = p->pConfig->eDetail;
- u64 cksum = *pCksum;
- Fts5IndexIter *pIter = 0;
- int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter);
-
- while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){
- i64 rowid = pIter->iRowid;
-
- if( eDetail==FTS5_DETAIL_NONE ){
- cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
- }else{
- Fts5PoslistReader sReader;
- for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader);
- sReader.bEof==0;
- sqlite3Fts5PoslistReaderNext(&sReader)
- ){
- int iCol = FTS5_POS2COLUMN(sReader.iPos);
- int iOff = FTS5_POS2OFFSET(sReader.iPos);
- cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n);
- }
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IterNext(pIter);
- }
- }
- sqlite3Fts5IterClose(pIter);
-
- *pCksum = cksum;
- return rc;
-}
-
-
-/*
-** This function is also purely an internal test. It does not contribute to
-** FTS functionality, or even the integrity-check, in any way.
-*/
-static void fts5TestTerm(
- Fts5Index *p,
- Fts5Buffer *pPrev, /* Previous term */
- const char *z, int n, /* Possibly new term to test */
- u64 expected,
- u64 *pCksum
-){
- int rc = p->rc;
- if( pPrev->n==0 ){
- fts5BufferSet(&rc, pPrev, n, (const u8*)z);
- }else
- if( rc==SQLITE_OK && (pPrev->n!=n || memcmp(pPrev->p, z, n)) ){
- u64 cksum3 = *pCksum;
- const char *zTerm = (const char*)&pPrev->p[1]; /* term sans prefix-byte */
- int nTerm = pPrev->n-1; /* Size of zTerm in bytes */
- int iIdx = (pPrev->p[0] - FTS5_MAIN_PREFIX);
- int flags = (iIdx==0 ? 0 : FTS5INDEX_QUERY_PREFIX);
- u64 ck1 = 0;
- u64 ck2 = 0;
-
- /* Check that the results returned for ASC and DESC queries are
- ** the same. If not, call this corruption. */
- rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, flags, &ck1);
- if( rc==SQLITE_OK ){
- int f = flags|FTS5INDEX_QUERY_DESC;
- rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2);
- }
- if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT;
-
- /* If this is a prefix query, check that the results returned if the
- ** the index is disabled are the same. In both ASC and DESC order.
- **
- ** This check may only be performed if the hash table is empty. This
- ** is because the hash table only supports a single scan query at
- ** a time, and the multi-iter loop from which this function is called
- ** is already performing such a scan. */
- if( p->nPendingData==0 ){
- if( iIdx>0 && rc==SQLITE_OK ){
- int f = flags|FTS5INDEX_QUERY_TEST_NOIDX;
- ck2 = 0;
- rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2);
- if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT;
- }
- if( iIdx>0 && rc==SQLITE_OK ){
- int f = flags|FTS5INDEX_QUERY_TEST_NOIDX|FTS5INDEX_QUERY_DESC;
- ck2 = 0;
- rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2);
- if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT;
- }
- }
-
- cksum3 ^= ck1;
- fts5BufferSet(&rc, pPrev, n, (const u8*)z);
-
- if( rc==SQLITE_OK && cksum3!=expected ){
- rc = FTS5_CORRUPT;
- }
- *pCksum = cksum3;
- }
- p->rc = rc;
-}
-
-#else
-# define fts5TestDlidxReverse(x,y,z)
-# define fts5TestTerm(u,v,w,x,y,z)
-#endif
-
-/*
-** Check that:
-**
-** 1) All leaves of pSeg between iFirst and iLast (inclusive) exist and
-** contain zero terms.
-** 2) All leaves of pSeg between iNoRowid and iLast (inclusive) exist and
-** contain zero rowids.
-*/
-static void fts5IndexIntegrityCheckEmpty(
- Fts5Index *p,
- Fts5StructureSegment *pSeg, /* Segment to check internal consistency */
- int iFirst,
- int iNoRowid,
- int iLast
-){
- int i;
-
- /* Now check that the iter.nEmpty leaves following the current leaf
- ** (a) exist and (b) contain no terms. */
- for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){
- Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
- if( pLeaf ){
- if( !fts5LeafIsTermless(pLeaf) ) p->rc = FTS5_CORRUPT;
- if( i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf) ) p->rc = FTS5_CORRUPT;
- }
- fts5DataRelease(pLeaf);
- }
-}
-
-static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
- int iTermOff = 0;
- int ii;
-
- Fts5Buffer buf1 = {0,0,0};
- Fts5Buffer buf2 = {0,0,0};
-
- ii = pLeaf->szLeaf;
- while( ii<pLeaf->nn && p->rc==SQLITE_OK ){
- int res;
- int iOff;
- int nIncr;
-
- ii += fts5GetVarint32(&pLeaf->p[ii], nIncr);
- iTermOff += nIncr;
- iOff = iTermOff;
-
- if( iOff>=pLeaf->szLeaf ){
- p->rc = FTS5_CORRUPT;
- }else if( iTermOff==nIncr ){
- int nByte;
- iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
- if( (iOff+nByte)>pLeaf->szLeaf ){
- p->rc = FTS5_CORRUPT;
- }else{
- fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
- }
- }else{
- int nKeep, nByte;
- iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep);
- iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
- if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){
- p->rc = FTS5_CORRUPT;
- }else{
- buf1.n = nKeep;
- fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
- }
-
- if( p->rc==SQLITE_OK ){
- res = fts5BufferCompare(&buf1, &buf2);
- if( res<=0 ) p->rc = FTS5_CORRUPT;
- }
- }
- fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p);
- }
-
- fts5BufferFree(&buf1);
- fts5BufferFree(&buf2);
-}
-
-static void fts5IndexIntegrityCheckSegment(
- Fts5Index *p, /* FTS5 backend object */
- Fts5StructureSegment *pSeg /* Segment to check internal consistency */
-){
- Fts5Config *pConfig = p->pConfig;
- sqlite3_stmt *pStmt = 0;
- int rc2;
- int iIdxPrevLeaf = pSeg->pgnoFirst-1;
- int iDlidxPrevLeaf = pSeg->pgnoLast;
-
- if( pSeg->pgnoFirst==0 ) return;
-
- fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
- "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d",
- pConfig->zDb, pConfig->zName, pSeg->iSegid
- ));
-
- /* Iterate through the b-tree hierarchy. */
- while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- i64 iRow; /* Rowid for this leaf */
- Fts5Data *pLeaf; /* Data for this leaf */
-
- int nIdxTerm = sqlite3_column_bytes(pStmt, 1);
- const char *zIdxTerm = (const char*)sqlite3_column_text(pStmt, 1);
- int iIdxLeaf = sqlite3_column_int(pStmt, 2);
- int bIdxDlidx = sqlite3_column_int(pStmt, 3);
-
- /* If the leaf in question has already been trimmed from the segment,
- ** ignore this b-tree entry. Otherwise, load it into memory. */
- if( iIdxLeaf<pSeg->pgnoFirst ) continue;
- iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf);
- pLeaf = fts5LeafRead(p, iRow);
- if( pLeaf==0 ) break;
-
- /* Check that the leaf contains at least one term, and that it is equal
- ** to or larger than the split-key in zIdxTerm. Also check that if there
- ** is also a rowid pointer within the leaf page header, it points to a
- ** location before the term. */
- if( pLeaf->nn<=pLeaf->szLeaf ){
- p->rc = FTS5_CORRUPT;
- }else{
- int iOff; /* Offset of first term on leaf */
- int iRowidOff; /* Offset of first rowid on leaf */
- int nTerm; /* Size of term on leaf in bytes */
- int res; /* Comparison of term and split-key */
-
- iOff = fts5LeafFirstTermOff(pLeaf);
- iRowidOff = fts5LeafFirstRowidOff(pLeaf);
- if( iRowidOff>=iOff ){
- p->rc = FTS5_CORRUPT;
- }else{
- iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
- res = memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
- if( res==0 ) res = nTerm - nIdxTerm;
- if( res<0 ) p->rc = FTS5_CORRUPT;
- }
-
- fts5IntegrityCheckPgidx(p, pLeaf);
- }
- fts5DataRelease(pLeaf);
- if( p->rc ) break;
-
- /* Now check that the iter.nEmpty leaves following the current leaf
- ** (a) exist and (b) contain no terms. */
- fts5IndexIntegrityCheckEmpty(
- p, pSeg, iIdxPrevLeaf+1, iDlidxPrevLeaf+1, iIdxLeaf-1
- );
- if( p->rc ) break;
-
- /* If there is a doclist-index, check that it looks right. */
- if( bIdxDlidx ){
- Fts5DlidxIter *pDlidx = 0; /* For iterating through doclist index */
- int iPrevLeaf = iIdxLeaf;
- int iSegid = pSeg->iSegid;
- int iPg = 0;
- i64 iKey;
-
- for(pDlidx=fts5DlidxIterInit(p, 0, iSegid, iIdxLeaf);
- fts5DlidxIterEof(p, pDlidx)==0;
- fts5DlidxIterNext(p, pDlidx)
- ){
-
- /* Check any rowid-less pages that occur before the current leaf. */
- for(iPg=iPrevLeaf+1; iPg<fts5DlidxIterPgno(pDlidx); iPg++){
- iKey = FTS5_SEGMENT_ROWID(iSegid, iPg);
- pLeaf = fts5DataRead(p, iKey);
- if( pLeaf ){
- if( fts5LeafFirstRowidOff(pLeaf)!=0 ) p->rc = FTS5_CORRUPT;
- fts5DataRelease(pLeaf);
- }
- }
- iPrevLeaf = fts5DlidxIterPgno(pDlidx);
-
- /* Check that the leaf page indicated by the iterator really does
- ** contain the rowid suggested by the same. */
- iKey = FTS5_SEGMENT_ROWID(iSegid, iPrevLeaf);
- pLeaf = fts5DataRead(p, iKey);
- if( pLeaf ){
- i64 iRowid;
- int iRowidOff = fts5LeafFirstRowidOff(pLeaf);
- ASSERT_SZLEAF_OK(pLeaf);
- if( iRowidOff>=pLeaf->szLeaf ){
- p->rc = FTS5_CORRUPT;
- }else{
- fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid);
- if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT;
- }
- fts5DataRelease(pLeaf);
- }
- }
-
- iDlidxPrevLeaf = iPg;
- fts5DlidxIterFree(pDlidx);
- fts5TestDlidxReverse(p, iSegid, iIdxLeaf);
- }else{
- iDlidxPrevLeaf = pSeg->pgnoLast;
- /* TODO: Check there is no doclist index */
- }
-
- iIdxPrevLeaf = iIdxLeaf;
- }
-
- rc2 = sqlite3_finalize(pStmt);
- if( p->rc==SQLITE_OK ) p->rc = rc2;
-
- /* Page iter.iLeaf must now be the rightmost leaf-page in the segment */
-#if 0
- if( p->rc==SQLITE_OK && iter.iLeaf!=pSeg->pgnoLast ){
- p->rc = FTS5_CORRUPT;
- }
-#endif
-}
-
-
-/*
-** Run internal checks to ensure that the FTS index (a) is internally
-** consistent and (b) contains entries for which the XOR of the checksums
-** as calculated by sqlite3Fts5IndexEntryCksum() is cksum.
-**
-** Return SQLITE_CORRUPT if any of the internal checks fail, or if the
-** checksum does not match. Return SQLITE_OK if all checks pass without
-** error, or some other SQLite error code if another error (e.g. OOM)
-** occurs.
-*/
-int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
- int eDetail = p->pConfig->eDetail;
- u64 cksum2 = 0; /* Checksum based on contents of indexes */
- Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
- Fts5Iter *pIter; /* Used to iterate through entire index */
- Fts5Structure *pStruct; /* Index structure */
-
-#ifdef SQLITE_DEBUG
- /* Used by extra internal tests only run if NDEBUG is not defined */
- u64 cksum3 = 0; /* Checksum based on contents of indexes */
- Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */
-#endif
- const int flags = FTS5INDEX_QUERY_NOOUTPUT;
-
- /* Load the FTS index structure */
- pStruct = fts5StructureRead(p);
-
- /* Check that the internal nodes of each segment match the leaves */
- if( pStruct ){
- int iLvl, iSeg;
- for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
- for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
- Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
- fts5IndexIntegrityCheckSegment(p, pSeg);
- }
- }
- }
-
- /* The cksum argument passed to this function is a checksum calculated
- ** based on all expected entries in the FTS index (including prefix index
- ** entries). This block checks that a checksum calculated based on the
- ** actual contents of FTS index is identical.
- **
- ** Two versions of the same checksum are calculated. The first (stack
- ** variable cksum2) based on entries extracted from the full-text index
- ** while doing a linear scan of each individual index in turn.
- **
- ** As each term visited by the linear scans, a separate query for the
- ** same term is performed. cksum3 is calculated based on the entries
- ** extracted by these queries.
- */
- for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, -1, 0, &pIter);
- fts5MultiIterEof(p, pIter)==0;
- fts5MultiIterNext(p, pIter, 0, 0)
- ){
- int n; /* Size of term in bytes */
- i64 iPos = 0; /* Position read from poslist */
- int iOff = 0; /* Offset within poslist */
- i64 iRowid = fts5MultiIterRowid(pIter);
- char *z = (char*)fts5MultiIterTerm(pIter, &n);
-
- /* If this is a new term, query for it. Update cksum3 with the results. */
- fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
-
- if( eDetail==FTS5_DETAIL_NONE ){
- if( 0==fts5MultiIterIsEmpty(p, pIter) ){
- cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, 0, 0, -1, z, n);
- }
- }else{
- poslist.n = 0;
- fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist);
- while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
- int iCol = FTS5_POS2COLUMN(iPos);
- int iTokOff = FTS5_POS2OFFSET(iPos);
- cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n);
- }
- }
- }
- fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
-
- fts5MultiIterFree(pIter);
- if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
-
- fts5StructureRelease(pStruct);
-#ifdef SQLITE_DEBUG
- fts5BufferFree(&term);
-#endif
- fts5BufferFree(&poslist);
- return fts5IndexReturn(p);
-}
-
-/*************************************************************************
-**************************************************************************
-** Below this point is the implementation of the fts5_decode() scalar
-** function only.
-*/
-
-/*
-** Decode a segment-data rowid from the %_data table. This function is
-** the opposite of macro FTS5_SEGMENT_ROWID().
-*/
-static void fts5DecodeRowid(
- i64 iRowid, /* Rowid from %_data table */
- int *piSegid, /* OUT: Segment id */
- int *pbDlidx, /* OUT: Dlidx flag */
- int *piHeight, /* OUT: Height */
- int *piPgno /* OUT: Page number */
-){
- *piPgno = (int)(iRowid & (((i64)1 << FTS5_DATA_PAGE_B) - 1));
- iRowid >>= FTS5_DATA_PAGE_B;
-
- *piHeight = (int)(iRowid & (((i64)1 << FTS5_DATA_HEIGHT_B) - 1));
- iRowid >>= FTS5_DATA_HEIGHT_B;
-
- *pbDlidx = (int)(iRowid & 0x0001);
- iRowid >>= FTS5_DATA_DLI_B;
-
- *piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
-}
-
-static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
- int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */
- fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno);
-
- if( iSegid==0 ){
- if( iKey==FTS5_AVERAGES_ROWID ){
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} ");
- }else{
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{structure}");
- }
- }
- else{
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%ssegid=%d h=%d pgno=%d}",
- bDlidx ? "dlidx " : "", iSegid, iHeight, iPgno
- );
- }
-}
-
-static void fts5DebugStructure(
- int *pRc, /* IN/OUT: error code */
- Fts5Buffer *pBuf,
- Fts5Structure *p
-){
- int iLvl, iSeg; /* Iterate through levels, segments */
-
- for(iLvl=0; iLvl<p->nLevel; iLvl++){
- Fts5StructureLevel *pLvl = &p->aLevel[iLvl];
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf,
- " {lvl=%d nMerge=%d nSeg=%d", iLvl, pLvl->nMerge, pLvl->nSeg
- );
- for(iSeg=0; iSeg<pLvl->nSeg; iSeg++){
- Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}",
- pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast
- );
- }
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
- }
-}
-
-/*
-** This is part of the fts5_decode() debugging aid.
-**
-** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This
-** function appends a human-readable representation of the same object
-** to the buffer passed as the second argument.
-*/
-static void fts5DecodeStructure(
- int *pRc, /* IN/OUT: error code */
- Fts5Buffer *pBuf,
- const u8 *pBlob, int nBlob
-){
- int rc; /* Return code */
- Fts5Structure *p = 0; /* Decoded structure object */
-
- rc = fts5StructureDecode(pBlob, nBlob, 0, &p);
- if( rc!=SQLITE_OK ){
- *pRc = rc;
- return;
- }
-
- fts5DebugStructure(pRc, pBuf, p);
- fts5StructureRelease(p);
-}
-
-/*
-** This is part of the fts5_decode() debugging aid.
-**
-** Arguments pBlob/nBlob contain an "averages" record. This function
-** appends a human-readable representation of record to the buffer passed
-** as the second argument.
-*/
-static void fts5DecodeAverages(
- int *pRc, /* IN/OUT: error code */
- Fts5Buffer *pBuf,
- const u8 *pBlob, int nBlob
-){
- int i = 0;
- const char *zSpace = "";
-
- while( i<nBlob ){
- u64 iVal;
- i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
- zSpace = " ";
- }
-}
-
-/*
-** Buffer (a/n) is assumed to contain a list of serialized varints. Read
-** each varint and append its string representation to buffer pBuf. Return
-** after either the input buffer is exhausted or a 0 value is read.
-**
-** The return value is the number of bytes read from the input buffer.
-*/
-static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
- int iOff = 0;
- while( iOff<n ){
- int iVal;
- iOff += fts5GetVarint32(&a[iOff], iVal);
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %d", iVal);
- }
- return iOff;
-}
-
-/*
-** The start of buffer (a/n) contains the start of a doclist. The doclist
-** may or may not finish within the buffer. This function appends a text
-** representation of the part of the doclist that is present to buffer
-** pBuf.
-**
-** The return value is the number of bytes read from the input buffer.
-*/
-static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
- i64 iDocid = 0;
- int iOff = 0;
-
- if( n>0 ){
- iOff = sqlite3Fts5GetVarint(a, (u64*)&iDocid);
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
- }
- while( iOff<n ){
- int nPos;
- int bDel;
- iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDel);
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " nPos=%d%s", nPos, bDel?"*":"");
- iOff += fts5DecodePoslist(pRc, pBuf, &a[iOff], MIN(n-iOff, nPos));
- if( iOff<n ){
- i64 iDelta;
- iOff += sqlite3Fts5GetVarint(&a[iOff], (u64*)&iDelta);
- iDocid += iDelta;
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
- }
- }
-
- return iOff;
-}
-
-/*
-** This function is part of the fts5_decode() debugging function. It is
-** only ever used with detail=none tables.
-**
-** Buffer (pData/nData) contains a doclist in the format used by detail=none
-** tables. This function appends a human-readable version of that list to
-** buffer pBuf.
-**
-** If *pRc is other than SQLITE_OK when this function is called, it is a
-** no-op. If an OOM or other error occurs within this function, *pRc is
-** set to an SQLite error code before returning. The final state of buffer
-** pBuf is undefined in this case.
-*/
-static void fts5DecodeRowidList(
- int *pRc, /* IN/OUT: Error code */
- Fts5Buffer *pBuf, /* Buffer to append text to */
- const u8 *pData, int nData /* Data to decode list-of-rowids from */
-){
- int i = 0;
- i64 iRowid = 0;
-
- while( i<nData ){
- const char *zApp = "";
- u64 iVal;
- i += sqlite3Fts5GetVarint(&pData[i], &iVal);
- iRowid += iVal;
-
- if( i<nData && pData[i]==0x00 ){
- i++;
- if( i<nData && pData[i]==0x00 ){
- i++;
- zApp = "+";
- }else{
- zApp = "*";
- }
- }
-
- sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
- }
-}
-
-/*
-** The implementation of user-defined scalar function fts5_decode().
-*/
-static void fts5DecodeFunction(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args (always 2) */
- sqlite3_value **apVal /* Function arguments */
-){
- i64 iRowid; /* Rowid for record being decoded */
- int iSegid,iHeight,iPgno,bDlidx;/* Rowid components */
- const u8 *aBlob; int n; /* Record to decode */
- u8 *a = 0;
- Fts5Buffer s; /* Build up text to return here */
- int rc = SQLITE_OK; /* Return code */
- int nSpace = 0;
- int eDetailNone = (sqlite3_user_data(pCtx)!=0);
-
- assert( nArg==2 );
- UNUSED_PARAM(nArg);
- memset(&s, 0, sizeof(Fts5Buffer));
- iRowid = sqlite3_value_int64(apVal[0]);
-
- /* Make a copy of the second argument (a blob) in aBlob[]. The aBlob[]
- ** copy is followed by FTS5_DATA_ZERO_PADDING 0x00 bytes, which prevents
- ** buffer overreads even if the record is corrupt. */
- n = sqlite3_value_bytes(apVal[1]);
- aBlob = sqlite3_value_blob(apVal[1]);
- nSpace = n + FTS5_DATA_ZERO_PADDING;
- a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
- if( a==0 ) goto decode_out;
- memcpy(a, aBlob, n);
-
-
- fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno);
-
- fts5DebugRowid(&rc, &s, iRowid);
- if( bDlidx ){
- Fts5Data dlidx;
- Fts5DlidxLvl lvl;
-
- dlidx.p = a;
- dlidx.nn = n;
-
- memset(&lvl, 0, sizeof(Fts5DlidxLvl));
- lvl.pData = &dlidx;
- lvl.iLeafPgno = iPgno;
-
- for(fts5DlidxLvlNext(&lvl); lvl.bEof==0; fts5DlidxLvlNext(&lvl)){
- sqlite3Fts5BufferAppendPrintf(&rc, &s,
- " %d(%lld)", lvl.iLeafPgno, lvl.iRowid
- );
- }
- }else if( iSegid==0 ){
- if( iRowid==FTS5_AVERAGES_ROWID ){
- fts5DecodeAverages(&rc, &s, a, n);
- }else{
- fts5DecodeStructure(&rc, &s, a, n);
- }
- }else if( eDetailNone ){
- Fts5Buffer term; /* Current term read from page */
- int szLeaf;
- int iPgidxOff = szLeaf = fts5GetU16(&a[2]);
- int iTermOff;
- int nKeep = 0;
- int iOff;
-
- memset(&term, 0, sizeof(Fts5Buffer));
-
- /* Decode any entries that occur before the first term. */
- if( szLeaf<n ){
- iPgidxOff += fts5GetVarint32(&a[iPgidxOff], iTermOff);
- }else{
- iTermOff = szLeaf;
- }
- fts5DecodeRowidList(&rc, &s, &a[4], iTermOff-4);
-
- iOff = iTermOff;
- while( iOff<szLeaf ){
- int nAppend;
-
- /* Read the term data for the next term*/
- iOff += fts5GetVarint32(&a[iOff], nAppend);
- term.n = nKeep;
- fts5BufferAppendBlob(&rc, &term, nAppend, &a[iOff]);
- sqlite3Fts5BufferAppendPrintf(
- &rc, &s, " term=%.*s", term.n, (const char*)term.p
- );
- iOff += nAppend;
-
- /* Figure out where the doclist for this term ends */
- if( iPgidxOff<n ){
- int nIncr;
- iPgidxOff += fts5GetVarint32(&a[iPgidxOff], nIncr);
- iTermOff += nIncr;
- }else{
- iTermOff = szLeaf;
- }
-
- fts5DecodeRowidList(&rc, &s, &a[iOff], iTermOff-iOff);
- iOff = iTermOff;
- if( iOff<szLeaf ){
- iOff += fts5GetVarint32(&a[iOff], nKeep);
- }
- }
-
- fts5BufferFree(&term);
- }else{
- Fts5Buffer term; /* Current term read from page */
- int szLeaf; /* Offset of pgidx in a[] */
- int iPgidxOff;
- int iPgidxPrev = 0; /* Previous value read from pgidx */
- int iTermOff = 0;
- int iRowidOff = 0;
- int iOff;
- int nDoclist;
-
- memset(&term, 0, sizeof(Fts5Buffer));
-
- if( n<4 ){
- sqlite3Fts5BufferSet(&rc, &s, 7, (const u8*)"corrupt");
- goto decode_out;
- }else{
- iRowidOff = fts5GetU16(&a[0]);
- iPgidxOff = szLeaf = fts5GetU16(&a[2]);
- if( iPgidxOff<n ){
- fts5GetVarint32(&a[iPgidxOff], iTermOff);
- }
- }
-
- /* Decode the position list tail at the start of the page */
- if( iRowidOff!=0 ){
- iOff = iRowidOff;
- }else if( iTermOff!=0 ){
- iOff = iTermOff;
- }else{
- iOff = szLeaf;
- }
- fts5DecodePoslist(&rc, &s, &a[4], iOff-4);
-
- /* Decode any more doclist data that appears on the page before the
- ** first term. */
- nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff;
- fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist);
-
- while( iPgidxOff<n ){
- int bFirst = (iPgidxOff==szLeaf); /* True for first term on page */
- int nByte; /* Bytes of data */
- int iEnd;
-
- iPgidxOff += fts5GetVarint32(&a[iPgidxOff], nByte);
- iPgidxPrev += nByte;
- iOff = iPgidxPrev;
-
- if( iPgidxOff<n ){
- fts5GetVarint32(&a[iPgidxOff], nByte);
- iEnd = iPgidxPrev + nByte;
- }else{
- iEnd = szLeaf;
- }
-
- if( bFirst==0 ){
- iOff += fts5GetVarint32(&a[iOff], nByte);
- term.n = nByte;
- }
- iOff += fts5GetVarint32(&a[iOff], nByte);
- fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
- iOff += nByte;
-
- sqlite3Fts5BufferAppendPrintf(
- &rc, &s, " term=%.*s", term.n, (const char*)term.p
- );
- iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], iEnd-iOff);
- }
-
- fts5BufferFree(&term);
- }
-
- decode_out:
- sqlite3_free(a);
- if( rc==SQLITE_OK ){
- sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_error_code(pCtx, rc);
- }
- fts5BufferFree(&s);
-}
-
-/*
-** The implementation of user-defined scalar function fts5_rowid().
-*/
-static void fts5RowidFunction(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args (always 2) */
- sqlite3_value **apVal /* Function arguments */
-){
- const char *zArg;
- if( nArg==0 ){
- sqlite3_result_error(pCtx, "should be: fts5_rowid(subject, ....)", -1);
- }else{
- zArg = (const char*)sqlite3_value_text(apVal[0]);
- if( 0==sqlite3_stricmp(zArg, "segment") ){
- i64 iRowid;
- int segid, pgno;
- if( nArg!=3 ){
- sqlite3_result_error(pCtx,
- "should be: fts5_rowid('segment', segid, pgno))", -1
- );
- }else{
- segid = sqlite3_value_int(apVal[1]);
- pgno = sqlite3_value_int(apVal[2]);
- iRowid = FTS5_SEGMENT_ROWID(segid, pgno);
- sqlite3_result_int64(pCtx, iRowid);
- }
- }else{
- sqlite3_result_error(pCtx,
- "first arg to fts5_rowid() must be 'segment'" , -1
- );
- }
- }
-}
-
-/*
-** This is called as part of registering the FTS5 module with database
-** connection db. It registers several user-defined scalar functions useful
-** with FTS5.
-**
-** If successful, SQLITE_OK is returned. If an error occurs, some other
-** SQLite error code is returned instead.
-*/
-int sqlite3Fts5IndexInit(sqlite3 *db){
- int rc = sqlite3_create_function(
- db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
- );
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(
- db, "fts5_decode_none", 2,
- SQLITE_UTF8, (void*)db, fts5DecodeFunction, 0, 0
- );
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(
- db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0
- );
- }
- return rc;
-}
-
-
-int sqlite3Fts5IndexReset(Fts5Index *p){
- assert( p->pStruct==0 || p->iStructVersion!=0 );
- if( fts5IndexDataVersion(p)!=p->iStructVersion ){
- fts5StructureInvalidate(p);
- }
- return fts5IndexReturn(p);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_main.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_main.c
deleted file mode 100644
index d00eaa1f4f5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_main.c
+++ /dev/null
@@ -1,2752 +0,0 @@
-/*
-** 2014 Jun 09
-**
-** 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 is an SQLite module implementing full-text search.
-*/
-
-
-#include "fts5Int.h"
-
-/*
-** This variable is set to false when running tests for which the on disk
-** structures should not be corrupt. Otherwise, true. If it is false, extra
-** assert() conditions in the fts5 code are activated - conditions that are
-** only true if it is guaranteed that the fts5 database is not corrupt.
-*/
-int sqlite3_fts5_may_be_corrupt = 1;
-
-
-typedef struct Fts5Auxdata Fts5Auxdata;
-typedef struct Fts5Auxiliary Fts5Auxiliary;
-typedef struct Fts5Cursor Fts5Cursor;
-typedef struct Fts5Sorter Fts5Sorter;
-typedef struct Fts5Table Fts5Table;
-typedef struct Fts5TokenizerModule Fts5TokenizerModule;
-
-/*
-** NOTES ON TRANSACTIONS:
-**
-** SQLite invokes the following virtual table methods as transactions are
-** opened and closed by the user:
-**
-** xBegin(): Start of a new transaction.
-** xSync(): Initial part of two-phase commit.
-** xCommit(): Final part of two-phase commit.
-** xRollback(): Rollback the transaction.
-**
-** Anything that is required as part of a commit that may fail is performed
-** in the xSync() callback. Current versions of SQLite ignore any errors
-** returned by xCommit().
-**
-** And as sub-transactions are opened/closed:
-**
-** xSavepoint(int S): Open savepoint S.
-** xRelease(int S): Commit and close savepoint S.
-** xRollbackTo(int S): Rollback to start of savepoint S.
-**
-** During a write-transaction the fts5_index.c module may cache some data
-** in-memory. It is flushed to disk whenever xSync(), xRelease() or
-** xSavepoint() is called. And discarded whenever xRollback() or xRollbackTo()
-** is called.
-**
-** Additionally, if SQLITE_DEBUG is defined, an instance of the following
-** structure is used to record the current transaction state. This information
-** is not required, but it is used in the assert() statements executed by
-** function fts5CheckTransactionState() (see below).
-*/
-struct Fts5TransactionState {
- int eState; /* 0==closed, 1==open, 2==synced */
- int iSavepoint; /* Number of open savepoints (0 -> none) */
-};
-
-/*
-** A single object of this type is allocated when the FTS5 module is
-** registered with a database handle. It is used to store pointers to
-** all registered FTS5 extensions - tokenizers and auxiliary functions.
-*/
-struct Fts5Global {
- fts5_api api; /* User visible part of object (see fts5.h) */
- sqlite3 *db; /* Associated database connection */
- i64 iNextId; /* Used to allocate unique cursor ids */
- Fts5Auxiliary *pAux; /* First in list of all aux. functions */
- Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */
- Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */
- Fts5Cursor *pCsr; /* First in list of all open cursors */
-};
-
-/*
-** Each auxiliary function registered with the FTS5 module is represented
-** by an object of the following type. All such objects are stored as part
-** of the Fts5Global.pAux list.
-*/
-struct Fts5Auxiliary {
- Fts5Global *pGlobal; /* Global context for this function */
- char *zFunc; /* Function name (nul-terminated) */
- void *pUserData; /* User-data pointer */
- fts5_extension_function xFunc; /* Callback function */
- void (*xDestroy)(void*); /* Destructor function */
- Fts5Auxiliary *pNext; /* Next registered auxiliary function */
-};
-
-/*
-** Each tokenizer module registered with the FTS5 module is represented
-** by an object of the following type. All such objects are stored as part
-** of the Fts5Global.pTok list.
-*/
-struct Fts5TokenizerModule {
- char *zName; /* Name of tokenizer */
- void *pUserData; /* User pointer passed to xCreate() */
- fts5_tokenizer x; /* Tokenizer functions */
- void (*xDestroy)(void*); /* Destructor function */
- Fts5TokenizerModule *pNext; /* Next registered tokenizer module */
-};
-
-/*
-** Virtual-table object.
-*/
-struct Fts5Table {
- sqlite3_vtab base; /* Base class used by SQLite core */
- Fts5Config *pConfig; /* Virtual table configuration */
- Fts5Index *pIndex; /* Full-text index */
- Fts5Storage *pStorage; /* Document store */
- Fts5Global *pGlobal; /* Global (connection wide) data */
- Fts5Cursor *pSortCsr; /* Sort data from this cursor */
-#ifdef SQLITE_DEBUG
- struct Fts5TransactionState ts;
-#endif
-};
-
-struct Fts5MatchPhrase {
- Fts5Buffer *pPoslist; /* Pointer to current poslist */
- int nTerm; /* Size of phrase in terms */
-};
-
-/*
-** pStmt:
-** SELECT rowid, <fts> FROM <fts> ORDER BY +rank;
-**
-** aIdx[]:
-** There is one entry in the aIdx[] array for each phrase in the query,
-** the value of which is the offset within aPoslist[] following the last
-** byte of the position list for the corresponding phrase.
-*/
-struct Fts5Sorter {
- sqlite3_stmt *pStmt;
- i64 iRowid; /* Current rowid */
- const u8 *aPoslist; /* Position lists for current row */
- int nIdx; /* Number of entries in aIdx[] */
- int aIdx[1]; /* Offsets into aPoslist for current row */
-};
-
-
-/*
-** Virtual-table cursor object.
-**
-** iSpecial:
-** If this is a 'special' query (refer to function fts5SpecialMatch()),
-** then this variable contains the result of the query.
-**
-** iFirstRowid, iLastRowid:
-** These variables are only used for FTS5_PLAN_MATCH cursors. Assuming the
-** cursor iterates in ascending order of rowids, iFirstRowid is the lower
-** limit of rowids to return, and iLastRowid the upper. In other words, the
-** WHERE clause in the user's query might have been:
-**
-** <tbl> MATCH <expr> AND rowid BETWEEN $iFirstRowid AND $iLastRowid
-**
-** If the cursor iterates in descending order of rowid, iFirstRowid
-** is the upper limit (i.e. the "first" rowid visited) and iLastRowid
-** the lower.
-*/
-struct Fts5Cursor {
- sqlite3_vtab_cursor base; /* Base class used by SQLite core */
- Fts5Cursor *pNext; /* Next cursor in Fts5Cursor.pCsr list */
- int *aColumnSize; /* Values for xColumnSize() */
- i64 iCsrId; /* Cursor id */
-
- /* Zero from this point onwards on cursor reset */
- int ePlan; /* FTS5_PLAN_XXX value */
- int bDesc; /* True for "ORDER BY rowid DESC" queries */
- i64 iFirstRowid; /* Return no rowids earlier than this */
- i64 iLastRowid; /* Return no rowids later than this */
- sqlite3_stmt *pStmt; /* Statement used to read %_content */
- Fts5Expr *pExpr; /* Expression for MATCH queries */
- Fts5Sorter *pSorter; /* Sorter for "ORDER BY rank" queries */
- int csrflags; /* Mask of cursor flags (see below) */
- i64 iSpecial; /* Result of special query */
-
- /* "rank" function. Populated on demand from vtab.xColumn(). */
- char *zRank; /* Custom rank function */
- char *zRankArgs; /* Custom rank function args */
- Fts5Auxiliary *pRank; /* Rank callback (or NULL) */
- int nRankArg; /* Number of trailing arguments for rank() */
- sqlite3_value **apRankArg; /* Array of trailing arguments */
- sqlite3_stmt *pRankArgStmt; /* Origin of objects in apRankArg[] */
-
- /* Auxiliary data storage */
- Fts5Auxiliary *pAux; /* Currently executing extension function */
- Fts5Auxdata *pAuxdata; /* First in linked list of saved aux-data */
-
- /* Cache used by auxiliary functions xInst() and xInstCount() */
- Fts5PoslistReader *aInstIter; /* One for each phrase */
- int nInstAlloc; /* Size of aInst[] array (entries / 3) */
- int nInstCount; /* Number of phrase instances */
- int *aInst; /* 3 integers per phrase instance */
-};
-
-/*
-** Bits that make up the "idxNum" parameter passed indirectly by
-** xBestIndex() to xFilter().
-*/
-#define FTS5_BI_MATCH 0x0001 /* <tbl> MATCH ? */
-#define FTS5_BI_RANK 0x0002 /* rank MATCH ? */
-#define FTS5_BI_ROWID_EQ 0x0004 /* rowid == ? */
-#define FTS5_BI_ROWID_LE 0x0008 /* rowid <= ? */
-#define FTS5_BI_ROWID_GE 0x0010 /* rowid >= ? */
-
-#define FTS5_BI_ORDER_RANK 0x0020
-#define FTS5_BI_ORDER_ROWID 0x0040
-#define FTS5_BI_ORDER_DESC 0x0080
-
-/*
-** Values for Fts5Cursor.csrflags
-*/
-#define FTS5CSR_EOF 0x01
-#define FTS5CSR_REQUIRE_CONTENT 0x02
-#define FTS5CSR_REQUIRE_DOCSIZE 0x04
-#define FTS5CSR_REQUIRE_INST 0x08
-#define FTS5CSR_FREE_ZRANK 0x10
-#define FTS5CSR_REQUIRE_RESEEK 0x20
-#define FTS5CSR_REQUIRE_POSLIST 0x40
-
-#define BitFlagAllTest(x,y) (((x) & (y))==(y))
-#define BitFlagTest(x,y) (((x) & (y))!=0)
-
-
-/*
-** Macros to Set(), Clear() and Test() cursor flags.
-*/
-#define CsrFlagSet(pCsr, flag) ((pCsr)->csrflags |= (flag))
-#define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag))
-#define CsrFlagTest(pCsr, flag) ((pCsr)->csrflags & (flag))
-
-struct Fts5Auxdata {
- Fts5Auxiliary *pAux; /* Extension to which this belongs */
- void *pPtr; /* Pointer value */
- void(*xDelete)(void*); /* Destructor */
- Fts5Auxdata *pNext; /* Next object in linked list */
-};
-
-#ifdef SQLITE_DEBUG
-#define FTS5_BEGIN 1
-#define FTS5_SYNC 2
-#define FTS5_COMMIT 3
-#define FTS5_ROLLBACK 4
-#define FTS5_SAVEPOINT 5
-#define FTS5_RELEASE 6
-#define FTS5_ROLLBACKTO 7
-static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
- switch( op ){
- case FTS5_BEGIN:
- assert( p->ts.eState==0 );
- p->ts.eState = 1;
- p->ts.iSavepoint = -1;
- break;
-
- case FTS5_SYNC:
- assert( p->ts.eState==1 );
- p->ts.eState = 2;
- break;
-
- case FTS5_COMMIT:
- assert( p->ts.eState==2 );
- p->ts.eState = 0;
- break;
-
- case FTS5_ROLLBACK:
- assert( p->ts.eState==1 || p->ts.eState==2 || p->ts.eState==0 );
- p->ts.eState = 0;
- break;
-
- case FTS5_SAVEPOINT:
- assert( p->ts.eState==1 );
- assert( iSavepoint>=0 );
- assert( iSavepoint>p->ts.iSavepoint );
- p->ts.iSavepoint = iSavepoint;
- break;
-
- case FTS5_RELEASE:
- assert( p->ts.eState==1 );
- assert( iSavepoint>=0 );
- assert( iSavepoint<=p->ts.iSavepoint );
- p->ts.iSavepoint = iSavepoint-1;
- break;
-
- case FTS5_ROLLBACKTO:
- assert( p->ts.eState==1 );
- assert( iSavepoint>=0 );
- assert( iSavepoint<=p->ts.iSavepoint );
- p->ts.iSavepoint = iSavepoint;
- break;
- }
-}
-#else
-# define fts5CheckTransactionState(x,y,z)
-#endif
-
-/*
-** Return true if pTab is a contentless table.
-*/
-static int fts5IsContentless(Fts5Table *pTab){
- return pTab->pConfig->eContent==FTS5_CONTENT_NONE;
-}
-
-/*
-** Delete a virtual table handle allocated by fts5InitVtab().
-*/
-static void fts5FreeVtab(Fts5Table *pTab){
- if( pTab ){
- sqlite3Fts5IndexClose(pTab->pIndex);
- sqlite3Fts5StorageClose(pTab->pStorage);
- sqlite3Fts5ConfigFree(pTab->pConfig);
- sqlite3_free(pTab);
- }
-}
-
-/*
-** The xDisconnect() virtual table method.
-*/
-static int fts5DisconnectMethod(sqlite3_vtab *pVtab){
- fts5FreeVtab((Fts5Table*)pVtab);
- return SQLITE_OK;
-}
-
-/*
-** The xDestroy() virtual table method.
-*/
-static int fts5DestroyMethod(sqlite3_vtab *pVtab){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- int rc = sqlite3Fts5DropAll(pTab->pConfig);
- if( rc==SQLITE_OK ){
- fts5FreeVtab((Fts5Table*)pVtab);
- }
- return rc;
-}
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the FTS3 virtual table.
-**
-** The argv[] array contains the following:
-**
-** argv[0] -> module name ("fts5")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> "column name" and other module argument fields.
-*/
-static int fts5InitVtab(
- int bCreate, /* True for xCreate, false for xConnect */
- sqlite3 *db, /* The SQLite database connection */
- void *pAux, /* Hash table containing tokenizers */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
- char **pzErr /* Write any error message here */
-){
- Fts5Global *pGlobal = (Fts5Global*)pAux;
- const char **azConfig = (const char**)argv;
- int rc = SQLITE_OK; /* Return code */
- Fts5Config *pConfig = 0; /* Results of parsing argc/argv */
- Fts5Table *pTab = 0; /* New virtual table object */
-
- /* Allocate the new vtab object and parse the configuration */
- pTab = (Fts5Table*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Table));
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
- assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
- }
- if( rc==SQLITE_OK ){
- pTab->pConfig = pConfig;
- pTab->pGlobal = pGlobal;
- }
-
- /* Open the index sub-system */
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->pIndex, pzErr);
- }
-
- /* Open the storage sub-system */
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageOpen(
- pConfig, pTab->pIndex, bCreate, &pTab->pStorage, pzErr
- );
- }
-
- /* Call sqlite3_declare_vtab() */
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
- }
-
- /* Load the initial configuration */
- if( rc==SQLITE_OK ){
- assert( pConfig->pzErrmsg==0 );
- pConfig->pzErrmsg = pzErr;
- rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
- sqlite3Fts5IndexRollback(pTab->pIndex);
- pConfig->pzErrmsg = 0;
- }
-
- if( rc!=SQLITE_OK ){
- fts5FreeVtab(pTab);
- pTab = 0;
- }else if( bCreate ){
- fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
- }
- *ppVTab = (sqlite3_vtab*)pTab;
- return rc;
-}
-
-/*
-** The xConnect() and xCreate() methods for the virtual table. All the
-** work is done in function fts5InitVtab().
-*/
-static int fts5ConnectMethod(
- sqlite3 *db, /* Database connection */
- void *pAux, /* Pointer to tokenizer hash table */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- return fts5InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr);
-}
-static int fts5CreateMethod(
- sqlite3 *db, /* Database connection */
- void *pAux, /* Pointer to tokenizer hash table */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- return fts5InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
-}
-
-/*
-** The different query plans.
-*/
-#define FTS5_PLAN_MATCH 1 /* (<tbl> MATCH ?) */
-#define FTS5_PLAN_SOURCE 2 /* A source cursor for SORTED_MATCH */
-#define FTS5_PLAN_SPECIAL 3 /* An internal query */
-#define FTS5_PLAN_SORTED_MATCH 4 /* (<tbl> MATCH ? ORDER BY rank) */
-#define FTS5_PLAN_SCAN 5 /* No usable constraint */
-#define FTS5_PLAN_ROWID 6 /* (rowid = ?) */
-
-/*
-** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
-** extension is currently being used by a version of SQLite too old to
-** support index-info flags. In that case this function is a no-op.
-*/
-static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
-#if SQLITE_VERSION_NUMBER>=3008012
-#ifndef SQLITE_CORE
- if( sqlite3_libversion_number()>=3008012 )
-#endif
- {
- pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
- }
-#endif
-}
-
-/*
-** Implementation of the xBestIndex method for FTS5 tables. Within the
-** WHERE constraint, it searches for the following:
-**
-** 1. A MATCH constraint against the special column.
-** 2. A MATCH constraint against the "rank" column.
-** 3. An == constraint against the rowid column.
-** 4. A < or <= constraint against the rowid column.
-** 5. A > or >= constraint against the rowid column.
-**
-** Within the ORDER BY, either:
-**
-** 5. ORDER BY rank [ASC|DESC]
-** 6. ORDER BY rowid [ASC|DESC]
-**
-** Costs are assigned as follows:
-**
-** a) If an unusable MATCH operator is present in the WHERE clause, the
-** cost is unconditionally set to 1e50 (a really big number).
-**
-** a) If a MATCH operator is present, the cost depends on the other
-** constraints also present. As follows:
-**
-** * No other constraints: cost=1000.0
-** * One rowid range constraint: cost=750.0
-** * Both rowid range constraints: cost=500.0
-** * An == rowid constraint: cost=100.0
-**
-** b) Otherwise, if there is no MATCH:
-**
-** * No other constraints: cost=1000000.0
-** * One rowid range constraint: cost=750000.0
-** * Both rowid range constraints: cost=250000.0
-** * An == rowid constraint: cost=10.0
-**
-** Costs are not modified by the ORDER BY clause.
-*/
-static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
- Fts5Table *pTab = (Fts5Table*)pVTab;
- Fts5Config *pConfig = pTab->pConfig;
- const int nCol = pConfig->nCol;
- int idxFlags = 0; /* Parameter passed through to xFilter() */
- int bHasMatch;
- int iNext;
- int i;
-
- struct Constraint {
- int op; /* Mask against sqlite3_index_constraint.op */
- int fts5op; /* FTS5 mask for idxFlags */
- int iCol; /* 0==rowid, 1==tbl, 2==rank */
- int omit; /* True to omit this if found */
- int iConsIndex; /* Index in pInfo->aConstraint[] */
- } aConstraint[] = {
- {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
- FTS5_BI_MATCH, 1, 1, -1},
- {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
- FTS5_BI_RANK, 2, 1, -1},
- {SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1},
- {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE,
- FTS5_BI_ROWID_LE, 0, 0, -1},
- {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE,
- FTS5_BI_ROWID_GE, 0, 0, -1},
- };
-
- int aColMap[3];
- aColMap[0] = -1;
- aColMap[1] = nCol;
- aColMap[2] = nCol+1;
-
- assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
- assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
- assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
- assert( SQLITE_INDEX_CONSTRAINT_GE<SQLITE_INDEX_CONSTRAINT_MATCH );
- assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
-
- /* Set idxFlags flags for all WHERE clause terms that will be used. */
- for(i=0; i<pInfo->nConstraint; i++){
- struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
- int iCol = p->iColumn;
-
- if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
- || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
- ){
- /* A MATCH operator or equivalent */
- if( p->usable ){
- idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
- aConstraint[0].iConsIndex = i;
- }else{
- /* As there exists an unusable MATCH constraint this is an
- ** unusable plan. Set a prohibitively high cost. */
- pInfo->estimatedCost = 1e50;
- return SQLITE_OK;
- }
- }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){
- int j;
- for(j=1; j<ArraySize(aConstraint); j++){
- struct Constraint *pC = &aConstraint[j];
- if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){
- pC->iConsIndex = i;
- idxFlags |= pC->fts5op;
- }
- }
- }
- }
-
- /* Set idxFlags flags for the ORDER BY clause */
- if( pInfo->nOrderBy==1 ){
- int iSort = pInfo->aOrderBy[0].iColumn;
- if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){
- idxFlags |= FTS5_BI_ORDER_RANK;
- }else if( iSort==-1 ){
- idxFlags |= FTS5_BI_ORDER_ROWID;
- }
- if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
- pInfo->orderByConsumed = 1;
- if( pInfo->aOrderBy[0].desc ){
- idxFlags |= FTS5_BI_ORDER_DESC;
- }
- }
- }
-
- /* Calculate the estimated cost based on the flags set in idxFlags. */
- bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH);
- if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){
- pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0;
- if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo);
- }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
- pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
- }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
- pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0;
- }else{
- pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
- }
-
- /* Assign argvIndex values to each constraint in use. */
- iNext = 1;
- for(i=0; i<ArraySize(aConstraint); i++){
- struct Constraint *pC = &aConstraint[i];
- if( pC->iConsIndex>=0 ){
- pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
- pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
- }
- }
-
- pInfo->idxNum = idxFlags;
- return SQLITE_OK;
-}
-
-static int fts5NewTransaction(Fts5Table *pTab){
- Fts5Cursor *pCsr;
- for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
- if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
- }
- return sqlite3Fts5StorageReset(pTab->pStorage);
-}
-
-/*
-** Implementation of xOpen method.
-*/
-static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
- Fts5Table *pTab = (Fts5Table*)pVTab;
- Fts5Config *pConfig = pTab->pConfig;
- Fts5Cursor *pCsr = 0; /* New cursor object */
- int nByte; /* Bytes of space to allocate */
- int rc; /* Return code */
-
- rc = fts5NewTransaction(pTab);
- if( rc==SQLITE_OK ){
- nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
- pCsr = (Fts5Cursor*)sqlite3_malloc(nByte);
- if( pCsr ){
- Fts5Global *pGlobal = pTab->pGlobal;
- memset(pCsr, 0, nByte);
- pCsr->aColumnSize = (int*)&pCsr[1];
- pCsr->pNext = pGlobal->pCsr;
- pGlobal->pCsr = pCsr;
- pCsr->iCsrId = ++pGlobal->iNextId;
- }else{
- rc = SQLITE_NOMEM;
- }
- }
- *ppCsr = (sqlite3_vtab_cursor*)pCsr;
- return rc;
-}
-
-static int fts5StmtType(Fts5Cursor *pCsr){
- if( pCsr->ePlan==FTS5_PLAN_SCAN ){
- return (pCsr->bDesc) ? FTS5_STMT_SCAN_DESC : FTS5_STMT_SCAN_ASC;
- }
- return FTS5_STMT_LOOKUP;
-}
-
-/*
-** This function is called after the cursor passed as the only argument
-** is moved to point at a different row. It clears all cached data
-** specific to the previous row stored by the cursor object.
-*/
-static void fts5CsrNewrow(Fts5Cursor *pCsr){
- CsrFlagSet(pCsr,
- FTS5CSR_REQUIRE_CONTENT
- | FTS5CSR_REQUIRE_DOCSIZE
- | FTS5CSR_REQUIRE_INST
- | FTS5CSR_REQUIRE_POSLIST
- );
-}
-
-static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- Fts5Auxdata *pData;
- Fts5Auxdata *pNext;
-
- sqlite3_free(pCsr->aInstIter);
- sqlite3_free(pCsr->aInst);
- if( pCsr->pStmt ){
- int eStmt = fts5StmtType(pCsr);
- sqlite3Fts5StorageStmtRelease(pTab->pStorage, eStmt, pCsr->pStmt);
- }
- if( pCsr->pSorter ){
- Fts5Sorter *pSorter = pCsr->pSorter;
- sqlite3_finalize(pSorter->pStmt);
- sqlite3_free(pSorter);
- }
-
- if( pCsr->ePlan!=FTS5_PLAN_SOURCE ){
- sqlite3Fts5ExprFree(pCsr->pExpr);
- }
-
- for(pData=pCsr->pAuxdata; pData; pData=pNext){
- pNext = pData->pNext;
- if( pData->xDelete ) pData->xDelete(pData->pPtr);
- sqlite3_free(pData);
- }
-
- sqlite3_finalize(pCsr->pRankArgStmt);
- sqlite3_free(pCsr->apRankArg);
-
- if( CsrFlagTest(pCsr, FTS5CSR_FREE_ZRANK) ){
- sqlite3_free(pCsr->zRank);
- sqlite3_free(pCsr->zRankArgs);
- }
-
- memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr));
-}
-
-
-/*
-** Close the cursor. For additional information see the documentation
-** on the xClose method of the virtual table interface.
-*/
-static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
- if( pCursor ){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
- Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
- Fts5Cursor **pp;
-
- fts5FreeCursorComponents(pCsr);
- /* Remove the cursor from the Fts5Global.pCsr list */
- for(pp=&pTab->pGlobal->pCsr; (*pp)!=pCsr; pp=&(*pp)->pNext);
- *pp = pCsr->pNext;
-
- sqlite3_free(pCsr);
- }
- return SQLITE_OK;
-}
-
-static int fts5SorterNext(Fts5Cursor *pCsr){
- Fts5Sorter *pSorter = pCsr->pSorter;
- int rc;
-
- rc = sqlite3_step(pSorter->pStmt);
- if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- CsrFlagSet(pCsr, FTS5CSR_EOF);
- }else if( rc==SQLITE_ROW ){
- const u8 *a;
- const u8 *aBlob;
- int nBlob;
- int i;
- int iOff = 0;
- rc = SQLITE_OK;
-
- pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
- nBlob = sqlite3_column_bytes(pSorter->pStmt, 1);
- aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1);
-
- /* nBlob==0 in detail=none mode. */
- if( nBlob>0 ){
- for(i=0; i<(pSorter->nIdx-1); i++){
- int iVal;
- a += fts5GetVarint32(a, iVal);
- iOff += iVal;
- pSorter->aIdx[i] = iOff;
- }
- pSorter->aIdx[i] = &aBlob[nBlob] - a;
- pSorter->aPoslist = a;
- }
-
- fts5CsrNewrow(pCsr);
- }
-
- return rc;
-}
-
-
-/*
-** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
-** open on table pTab.
-*/
-static void fts5TripCursors(Fts5Table *pTab){
- Fts5Cursor *pCsr;
- for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
- if( pCsr->ePlan==FTS5_PLAN_MATCH
- && pCsr->base.pVtab==(sqlite3_vtab*)pTab
- ){
- CsrFlagSet(pCsr, FTS5CSR_REQUIRE_RESEEK);
- }
- }
-}
-
-/*
-** If the REQUIRE_RESEEK flag is set on the cursor passed as the first
-** argument, close and reopen all Fts5IndexIter iterators that the cursor
-** is using. Then attempt to move the cursor to a rowid equal to or laster
-** (in the cursors sort order - ASC or DESC) than the current rowid.
-**
-** If the new rowid is not equal to the old, set output parameter *pbSkip
-** to 1 before returning. Otherwise, leave it unchanged.
-**
-** Return SQLITE_OK if successful or if no reseek was required, or an
-** error code if an error occurred.
-*/
-static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
- int rc = SQLITE_OK;
- assert( *pbSkip==0 );
- if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- int bDesc = pCsr->bDesc;
- i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
-
- rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc);
- if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
- *pbSkip = 1;
- }
-
- CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
- fts5CsrNewrow(pCsr);
- if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
- CsrFlagSet(pCsr, FTS5CSR_EOF);
- *pbSkip = 1;
- }
- }
- return rc;
-}
-
-
-/*
-** Advance the cursor to the next row in the table that matches the
-** search criteria.
-**
-** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
-** even if we reach end-of-file. The fts5EofMethod() will be called
-** subsequently to determine whether or not an EOF was hit.
-*/
-static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
- int rc;
-
- assert( (pCsr->ePlan<3)==
- (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE)
- );
- assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) );
-
- if( pCsr->ePlan<3 ){
- int bSkip = 0;
- if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
- rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid);
- CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr));
- fts5CsrNewrow(pCsr);
- }else{
- switch( pCsr->ePlan ){
- case FTS5_PLAN_SPECIAL: {
- CsrFlagSet(pCsr, FTS5CSR_EOF);
- rc = SQLITE_OK;
- break;
- }
-
- case FTS5_PLAN_SORTED_MATCH: {
- rc = fts5SorterNext(pCsr);
- break;
- }
-
- default:
- rc = sqlite3_step(pCsr->pStmt);
- if( rc!=SQLITE_ROW ){
- CsrFlagSet(pCsr, FTS5CSR_EOF);
- rc = sqlite3_reset(pCsr->pStmt);
- }else{
- rc = SQLITE_OK;
- }
- break;
- }
- }
-
- return rc;
-}
-
-
-static int fts5PrepareStatement(
- sqlite3_stmt **ppStmt,
- Fts5Config *pConfig,
- const char *zFmt,
- ...
-){
- sqlite3_stmt *pRet = 0;
- int rc;
- char *zSql;
- va_list ap;
-
- va_start(ap, zFmt);
- zSql = sqlite3_vmprintf(zFmt, ap);
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
- SQLITE_PREPARE_PERSISTENT, &pRet, 0);
- if( rc!=SQLITE_OK ){
- *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
- }
- sqlite3_free(zSql);
- }
-
- va_end(ap);
- *ppStmt = pRet;
- return rc;
-}
-
-static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
- Fts5Config *pConfig = pTab->pConfig;
- Fts5Sorter *pSorter;
- int nPhrase;
- int nByte;
- int rc;
- const char *zRank = pCsr->zRank;
- const char *zRankArgs = pCsr->zRankArgs;
-
- nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
- nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
- pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
- if( pSorter==0 ) return SQLITE_NOMEM;
- memset(pSorter, 0, nByte);
- pSorter->nIdx = nPhrase;
-
- /* TODO: It would be better to have some system for reusing statement
- ** handles here, rather than preparing a new one for each query. But that
- ** is not possible as SQLite reference counts the virtual table objects.
- ** And since the statement required here reads from this very virtual
- ** table, saving it creates a circular reference.
- **
- ** If SQLite a built-in statement cache, this wouldn't be a problem. */
- rc = fts5PrepareStatement(&pSorter->pStmt, pConfig,
- "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
- pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
- (zRankArgs ? ", " : ""),
- (zRankArgs ? zRankArgs : ""),
- bDesc ? "DESC" : "ASC"
- );
-
- pCsr->pSorter = pSorter;
- if( rc==SQLITE_OK ){
- assert( pTab->pSortCsr==0 );
- pTab->pSortCsr = pCsr;
- rc = fts5SorterNext(pCsr);
- pTab->pSortCsr = 0;
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_finalize(pSorter->pStmt);
- sqlite3_free(pSorter);
- pCsr->pSorter = 0;
- }
-
- return rc;
-}
-
-static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
- int rc;
- Fts5Expr *pExpr = pCsr->pExpr;
- rc = sqlite3Fts5ExprFirst(pExpr, pTab->pIndex, pCsr->iFirstRowid, bDesc);
- if( sqlite3Fts5ExprEof(pExpr) ){
- CsrFlagSet(pCsr, FTS5CSR_EOF);
- }
- fts5CsrNewrow(pCsr);
- return rc;
-}
-
-/*
-** Process a "special" query. A special query is identified as one with a
-** MATCH expression that begins with a '*' character. The remainder of
-** the text passed to the MATCH operator are used as the special query
-** parameters.
-*/
-static int fts5SpecialMatch(
- Fts5Table *pTab,
- Fts5Cursor *pCsr,
- const char *zQuery
-){
- int rc = SQLITE_OK; /* Return code */
- const char *z = zQuery; /* Special query text */
- int n; /* Number of bytes in text at z */
-
- while( z[0]==' ' ) z++;
- for(n=0; z[n] && z[n]!=' '; n++);
-
- assert( pTab->base.zErrMsg==0 );
- pCsr->ePlan = FTS5_PLAN_SPECIAL;
-
- if( 0==sqlite3_strnicmp("reads", z, n) ){
- pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->pIndex);
- }
- else if( 0==sqlite3_strnicmp("id", z, n) ){
- pCsr->iSpecial = pCsr->iCsrId;
- }
- else{
- /* An unrecognized directive. Return an error message. */
- pTab->base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
- rc = SQLITE_ERROR;
- }
-
- return rc;
-}
-
-/*
-** Search for an auxiliary function named zName that can be used with table
-** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary
-** structure. Otherwise, if no such function exists, return NULL.
-*/
-static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
- Fts5Auxiliary *pAux;
-
- for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){
- if( sqlite3_stricmp(zName, pAux->zFunc)==0 ) return pAux;
- }
-
- /* No function of the specified name was found. Return 0. */
- return 0;
-}
-
-
-static int fts5FindRankFunction(Fts5Cursor *pCsr){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- Fts5Config *pConfig = pTab->pConfig;
- int rc = SQLITE_OK;
- Fts5Auxiliary *pAux = 0;
- const char *zRank = pCsr->zRank;
- const char *zRankArgs = pCsr->zRankArgs;
-
- if( zRankArgs ){
- char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
- if( zSql ){
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
- SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
- sqlite3_free(zSql);
- assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- int nByte;
- pCsr->nRankArg = sqlite3_column_count(pStmt);
- nByte = sizeof(sqlite3_value*)*pCsr->nRankArg;
- pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte);
- if( rc==SQLITE_OK ){
- int i;
- for(i=0; i<pCsr->nRankArg; i++){
- pCsr->apRankArg[i] = sqlite3_column_value(pStmt, i);
- }
- }
- pCsr->pRankArgStmt = pStmt;
- }else{
- rc = sqlite3_finalize(pStmt);
- assert( rc!=SQLITE_OK );
- }
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- pAux = fts5FindAuxiliary(pTab, zRank);
- if( pAux==0 ){
- assert( pTab->base.zErrMsg==0 );
- pTab->base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
- rc = SQLITE_ERROR;
- }
- }
-
- pCsr->pRank = pAux;
- return rc;
-}
-
-
-static int fts5CursorParseRank(
- Fts5Config *pConfig,
- Fts5Cursor *pCsr,
- sqlite3_value *pRank
-){
- int rc = SQLITE_OK;
- if( pRank ){
- const char *z = (const char*)sqlite3_value_text(pRank);
- char *zRank = 0;
- char *zRankArgs = 0;
-
- if( z==0 ){
- if( sqlite3_value_type(pRank)==SQLITE_NULL ) rc = SQLITE_ERROR;
- }else{
- rc = sqlite3Fts5ConfigParseRank(z, &zRank, &zRankArgs);
- }
- if( rc==SQLITE_OK ){
- pCsr->zRank = zRank;
- pCsr->zRankArgs = zRankArgs;
- CsrFlagSet(pCsr, FTS5CSR_FREE_ZRANK);
- }else if( rc==SQLITE_ERROR ){
- pCsr->base.pVtab->zErrMsg = sqlite3_mprintf(
- "parse error in rank function: %s", z
- );
- }
- }else{
- if( pConfig->zRank ){
- pCsr->zRank = (char*)pConfig->zRank;
- pCsr->zRankArgs = (char*)pConfig->zRankArgs;
- }else{
- pCsr->zRank = (char*)FTS5_DEFAULT_RANK;
- pCsr->zRankArgs = 0;
- }
- }
- return rc;
-}
-
-static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){
- if( pVal ){
- int eType = sqlite3_value_numeric_type(pVal);
- if( eType==SQLITE_INTEGER ){
- return sqlite3_value_int64(pVal);
- }
- }
- return iDefault;
-}
-
-/*
-** This is the xFilter interface for the virtual table. See
-** the virtual table xFilter method documentation for additional
-** information.
-**
-** There are three possible query strategies:
-**
-** 1. Full-text search using a MATCH operator.
-** 2. A by-rowid lookup.
-** 3. A full-table scan.
-*/
-static int fts5FilterMethod(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, /* Strategy index */
- const char *zUnused, /* Unused */
- int nVal, /* Number of elements in apVal */
- sqlite3_value **apVal /* Arguments for the indexing scheme */
-){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
- Fts5Config *pConfig = pTab->pConfig;
- Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
- int rc = SQLITE_OK; /* Error code */
- int iVal = 0; /* Counter for apVal[] */
- int bDesc; /* True if ORDER BY [rank|rowid] DESC */
- int bOrderByRank; /* True if ORDER BY rank */
- sqlite3_value *pMatch = 0; /* <tbl> MATCH ? expression (or NULL) */
- sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */
- sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
- sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
- sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
- int iCol; /* Column on LHS of MATCH operator */
- char **pzErrmsg = pConfig->pzErrmsg;
-
- UNUSED_PARAM(zUnused);
- UNUSED_PARAM(nVal);
-
- if( pCsr->ePlan ){
- fts5FreeCursorComponents(pCsr);
- memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
- }
-
- assert( pCsr->pStmt==0 );
- assert( pCsr->pExpr==0 );
- assert( pCsr->csrflags==0 );
- assert( pCsr->pRank==0 );
- assert( pCsr->zRank==0 );
- assert( pCsr->zRankArgs==0 );
-
- assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg );
- pConfig->pzErrmsg = &pTab->base.zErrMsg;
-
- /* Decode the arguments passed through to this function.
- **
- ** Note: The following set of if(...) statements must be in the same
- ** order as the corresponding entries in the struct at the top of
- ** fts5BestIndexMethod(). */
- if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++];
- if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++];
- if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
- if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
- if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
- iCol = (idxNum>>16);
- assert( iCol>=0 && iCol<=pConfig->nCol );
- assert( iVal==nVal );
- bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
- pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
-
- /* Set the cursor upper and lower rowid limits. Only some strategies
- ** actually use them. This is ok, as the xBestIndex() method leaves the
- ** sqlite3_index_constraint.omit flag clear for range constraints
- ** on the rowid field. */
- if( pRowidEq ){
- pRowidLe = pRowidGe = pRowidEq;
- }
- if( bDesc ){
- pCsr->iFirstRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64);
- pCsr->iLastRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
- }else{
- pCsr->iLastRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64);
- pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
- }
-
- if( pTab->pSortCsr ){
- /* If pSortCsr is non-NULL, then this call is being made as part of
- ** processing for a "... MATCH <expr> ORDER BY rank" query (ePlan is
- ** set to FTS5_PLAN_SORTED_MATCH). pSortCsr is the cursor that will
- ** return results to the user for this query. The current cursor
- ** (pCursor) is used to execute the query issued by function
- ** fts5CursorFirstSorted() above. */
- assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 );
- assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 );
- assert( pCsr->iLastRowid==LARGEST_INT64 );
- assert( pCsr->iFirstRowid==SMALLEST_INT64 );
- pCsr->ePlan = FTS5_PLAN_SOURCE;
- pCsr->pExpr = pTab->pSortCsr->pExpr;
- rc = fts5CursorFirst(pTab, pCsr, bDesc);
- }else if( pMatch ){
- const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
- if( zExpr==0 ) zExpr = "";
-
- rc = fts5CursorParseRank(pConfig, pCsr, pRank);
- if( rc==SQLITE_OK ){
- if( zExpr[0]=='*' ){
- /* The user has issued a query of the form "MATCH '*...'". This
- ** indicates that the MATCH expression is not a full text query,
- ** but a request for an internal parameter. */
- rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
- }else{
- char **pzErr = &pTab->base.zErrMsg;
- rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
- if( rc==SQLITE_OK ){
- if( bOrderByRank ){
- pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
- rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
- }else{
- pCsr->ePlan = FTS5_PLAN_MATCH;
- rc = fts5CursorFirst(pTab, pCsr, bDesc);
- }
- }
- }
- }
- }else if( pConfig->zContent==0 ){
- *pConfig->pzErrmsg = sqlite3_mprintf(
- "%s: table does not support scanning", pConfig->zName
- );
- rc = SQLITE_ERROR;
- }else{
- /* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
- ** by rowid (ePlan==FTS5_PLAN_ROWID). */
- pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
- rc = sqlite3Fts5StorageStmt(
- pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->base.zErrMsg
- );
- if( rc==SQLITE_OK ){
- if( pCsr->ePlan==FTS5_PLAN_ROWID ){
- sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
- }else{
- sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
- sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
- }
- rc = fts5NextMethod(pCursor);
- }
- }
-
- pConfig->pzErrmsg = pzErrmsg;
- return rc;
-}
-
-/*
-** This is the xEof method of the virtual table. SQLite calls this
-** routine to find out if it has reached the end of a result set.
-*/
-static int fts5EofMethod(sqlite3_vtab_cursor *pCursor){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
- return (CsrFlagTest(pCsr, FTS5CSR_EOF) ? 1 : 0);
-}
-
-/*
-** Return the rowid that the cursor currently points to.
-*/
-static i64 fts5CursorRowid(Fts5Cursor *pCsr){
- assert( pCsr->ePlan==FTS5_PLAN_MATCH
- || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
- || pCsr->ePlan==FTS5_PLAN_SOURCE
- );
- if( pCsr->pSorter ){
- return pCsr->pSorter->iRowid;
- }else{
- return sqlite3Fts5ExprRowid(pCsr->pExpr);
- }
-}
-
-/*
-** This is the xRowid method. The SQLite core calls this routine to
-** retrieve the rowid for the current row of the result set. fts5
-** exposes %_content.rowid as the rowid for the virtual table. The
-** rowid should be written to *pRowid.
-*/
-static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
- int ePlan = pCsr->ePlan;
-
- assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
- switch( ePlan ){
- case FTS5_PLAN_SPECIAL:
- *pRowid = 0;
- break;
-
- case FTS5_PLAN_SOURCE:
- case FTS5_PLAN_MATCH:
- case FTS5_PLAN_SORTED_MATCH:
- *pRowid = fts5CursorRowid(pCsr);
- break;
-
- default:
- *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
- break;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** If the cursor requires seeking (bSeekRequired flag is set), seek it.
-** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise.
-**
-** If argument bErrormsg is true and an error occurs, an error message may
-** be left in sqlite3_vtab.zErrMsg.
-*/
-static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
- int rc = SQLITE_OK;
-
- /* If the cursor does not yet have a statement handle, obtain one now. */
- if( pCsr->pStmt==0 ){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- int eStmt = fts5StmtType(pCsr);
- rc = sqlite3Fts5StorageStmt(
- pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->base.zErrMsg:0)
- );
- assert( rc!=SQLITE_OK || pTab->base.zErrMsg==0 );
- assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
- }
-
- if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){
- assert( pCsr->pExpr );
- sqlite3_reset(pCsr->pStmt);
- sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr));
- rc = sqlite3_step(pCsr->pStmt);
- if( rc==SQLITE_ROW ){
- rc = SQLITE_OK;
- CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT);
- }else{
- rc = sqlite3_reset(pCsr->pStmt);
- if( rc==SQLITE_OK ){
- rc = FTS5_CORRUPT;
- }
- }
- }
- return rc;
-}
-
-static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
- va_list ap; /* ... printf arguments */
- va_start(ap, zFormat);
- assert( p->base.zErrMsg==0 );
- p->base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
-}
-
-/*
-** This function is called to handle an FTS INSERT command. In other words,
-** an INSERT statement of the form:
-**
-** INSERT INTO fts(fts) VALUES($pCmd)
-** INSERT INTO fts(fts, rank) VALUES($pCmd, $pVal)
-**
-** Argument pVal is the value assigned to column "fts" by the INSERT
-** statement. This function returns SQLITE_OK if successful, or an SQLite
-** error code if an error occurs.
-**
-** The commands implemented by this function are documented in the "Special
-** INSERT Directives" section of the documentation. It should be updated if
-** more commands are added to this function.
-*/
-static int fts5SpecialInsert(
- Fts5Table *pTab, /* Fts5 table object */
- const char *zCmd, /* Text inserted into table-name column */
- sqlite3_value *pVal /* Value inserted into rank column */
-){
- Fts5Config *pConfig = pTab->pConfig;
- int rc = SQLITE_OK;
- int bError = 0;
-
- if( 0==sqlite3_stricmp("delete-all", zCmd) ){
- if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
- fts5SetVtabError(pTab,
- "'delete-all' may only be used with a "
- "contentless or external content fts5 table"
- );
- rc = SQLITE_ERROR;
- }else{
- rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage);
- }
- }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
- if( pConfig->eContent==FTS5_CONTENT_NONE ){
- fts5SetVtabError(pTab,
- "'rebuild' may not be used with a contentless fts5 table"
- );
- rc = SQLITE_ERROR;
- }else{
- rc = sqlite3Fts5StorageRebuild(pTab->pStorage);
- }
- }else if( 0==sqlite3_stricmp("optimize", zCmd) ){
- rc = sqlite3Fts5StorageOptimize(pTab->pStorage);
- }else if( 0==sqlite3_stricmp("merge", zCmd) ){
- int nMerge = sqlite3_value_int(pVal);
- rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
- }else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
- rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
-#ifdef SQLITE_DEBUG
- }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
- pConfig->bPrefixIndex = sqlite3_value_int(pVal);
-#endif
- }else{
- rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError);
- }
- if( rc==SQLITE_OK ){
- if( bError ){
- rc = SQLITE_ERROR;
- }else{
- rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0);
- }
- }
- }
- return rc;
-}
-
-static int fts5SpecialDelete(
- Fts5Table *pTab,
- sqlite3_value **apVal
-){
- int rc = SQLITE_OK;
- int eType1 = sqlite3_value_type(apVal[1]);
- if( eType1==SQLITE_INTEGER ){
- sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]);
- }
- return rc;
-}
-
-static void fts5StorageInsert(
- int *pRc,
- Fts5Table *pTab,
- sqlite3_value **apVal,
- i64 *piRowid
-){
- int rc = *pRc;
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid);
- }
- *pRc = rc;
-}
-
-/*
-** This function is the implementation of the xUpdate callback used by
-** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
-** inserted, updated or deleted.
-**
-** A delete specifies a single argument - the rowid of the row to remove.
-**
-** Update and insert operations pass:
-**
-** 1. The "old" rowid, or NULL.
-** 2. The "new" rowid.
-** 3. Values for each of the nCol matchable columns.
-** 4. Values for the two hidden columns (<tablename> and "rank").
-*/
-static int fts5UpdateMethod(
- sqlite3_vtab *pVtab, /* Virtual table handle */
- int nArg, /* Size of argument array */
- sqlite3_value **apVal, /* Array of arguments */
- sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
-){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- Fts5Config *pConfig = pTab->pConfig;
- int eType0; /* value_type() of apVal[0] */
- int rc = SQLITE_OK; /* Return code */
-
- /* A transaction must be open when this is called. */
- assert( pTab->ts.eState==1 );
-
- assert( pVtab->zErrMsg==0 );
- assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
- assert( nArg==1
- || sqlite3_value_type(apVal[1])==SQLITE_INTEGER
- || sqlite3_value_type(apVal[1])==SQLITE_NULL
- );
- assert( pTab->pConfig->pzErrmsg==0 );
- pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
-
- /* Put any active cursors into REQUIRE_SEEK state. */
- fts5TripCursors(pTab);
-
- eType0 = sqlite3_value_type(apVal[0]);
- if( eType0==SQLITE_NULL
- && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL
- ){
- /* A "special" INSERT op. These are handled separately. */
- const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]);
- if( pConfig->eContent!=FTS5_CONTENT_NORMAL
- && 0==sqlite3_stricmp("delete", z)
- ){
- rc = fts5SpecialDelete(pTab, apVal);
- }else{
- rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
- }
- }else{
- /* A regular INSERT, UPDATE or DELETE statement. The trick here is that
- ** any conflict on the rowid value must be detected before any
- ** modifications are made to the database file. There are 4 cases:
- **
- ** 1) DELETE
- ** 2) UPDATE (rowid not modified)
- ** 3) UPDATE (rowid modified)
- ** 4) INSERT
- **
- ** Cases 3 and 4 may violate the rowid constraint.
- */
- int eConflict = SQLITE_ABORT;
- if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
- eConflict = sqlite3_vtab_on_conflict(pConfig->db);
- }
-
- assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
- assert( nArg!=1 || eType0==SQLITE_INTEGER );
-
- /* Filter out attempts to run UPDATE or DELETE on contentless tables.
- ** This is not suported. */
- if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
- pTab->base.zErrMsg = sqlite3_mprintf(
- "cannot %s contentless fts5 table: %s",
- (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
- );
- rc = SQLITE_ERROR;
- }
-
- /* DELETE */
- else if( nArg==1 ){
- i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
- }
-
- /* INSERT */
- else if( eType0!=SQLITE_INTEGER ){
- /* If this is a REPLACE, first remove the current entry (if any) */
- if( eConflict==SQLITE_REPLACE
- && sqlite3_value_type(apVal[1])==SQLITE_INTEGER
- ){
- i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
- }
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
- }
-
- /* UPDATE */
- else{
- i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
- i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
- if( iOld!=iNew ){
- if( eConflict==SQLITE_REPLACE ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
- }
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
- }else{
- rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
- }
- }
- }else{
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
- }
- }
- }
-
- pTab->pConfig->pzErrmsg = 0;
- return rc;
-}
-
-/*
-** Implementation of xSync() method.
-*/
-static int fts5SyncMethod(sqlite3_vtab *pVtab){
- int rc;
- Fts5Table *pTab = (Fts5Table*)pVtab;
- fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
- pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
- fts5TripCursors(pTab);
- rc = sqlite3Fts5StorageSync(pTab->pStorage);
- pTab->pConfig->pzErrmsg = 0;
- return rc;
-}
-
-/*
-** Implementation of xBegin() method.
-*/
-static int fts5BeginMethod(sqlite3_vtab *pVtab){
- fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0);
- fts5NewTransaction((Fts5Table*)pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Implementation of xCommit() method. This is a no-op. The contents of
-** the pending-terms hash-table have already been flushed into the database
-** by fts5SyncMethod().
-*/
-static int fts5CommitMethod(sqlite3_vtab *pVtab){
- UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0);
- return SQLITE_OK;
-}
-
-/*
-** Implementation of xRollback(). Discard the contents of the pending-terms
-** hash-table. Any changes made to the database are reverted by SQLite.
-*/
-static int fts5RollbackMethod(sqlite3_vtab *pVtab){
- int rc;
- Fts5Table *pTab = (Fts5Table*)pVtab;
- fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
- rc = sqlite3Fts5StorageRollback(pTab->pStorage);
- return rc;
-}
-
-static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);
-
-static void *fts5ApiUserData(Fts5Context *pCtx){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- return pCsr->pAux->pUserData;
-}
-
-static int fts5ApiColumnCount(Fts5Context *pCtx){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- return ((Fts5Table*)(pCsr->base.pVtab))->pConfig->nCol;
-}
-
-static int fts5ApiColumnTotalSize(
- Fts5Context *pCtx,
- int iCol,
- sqlite3_int64 *pnToken
-){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken);
-}
-
-static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
-}
-
-static int fts5ApiTokenize(
- Fts5Context *pCtx,
- const char *pText, int nText,
- void *pUserData,
- int (*xToken)(void*, int, const char*, int, int, int)
-){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- return sqlite3Fts5Tokenize(
- pTab->pConfig, FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
- );
-}
-
-static int fts5ApiPhraseCount(Fts5Context *pCtx){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- return sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
-}
-
-static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
-}
-
-static int fts5ApiColumnText(
- Fts5Context *pCtx,
- int iCol,
- const char **pz,
- int *pn
-){
- int rc = SQLITE_OK;
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
- *pz = 0;
- *pn = 0;
- }else{
- rc = fts5SeekCursor(pCsr, 0);
- if( rc==SQLITE_OK ){
- *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
- *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
- }
- }
- return rc;
-}
-
-static int fts5CsrPoslist(
- Fts5Cursor *pCsr,
- int iPhrase,
- const u8 **pa,
- int *pn
-){
- Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
- int rc = SQLITE_OK;
- int bLive = (pCsr->pSorter==0);
-
- if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
-
- if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
- Fts5PoslistPopulator *aPopulator;
- int i;
- aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
- if( aPopulator==0 ) rc = SQLITE_NOMEM;
- for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
- int n; const char *z;
- rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ExprPopulatePoslists(
- pConfig, pCsr->pExpr, aPopulator, i, z, n
- );
- }
- }
- sqlite3_free(aPopulator);
-
- if( pCsr->pSorter ){
- sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
- }
- }
- CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
- }
-
- if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
- Fts5Sorter *pSorter = pCsr->pSorter;
- int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
- *pn = pSorter->aIdx[iPhrase] - i1;
- *pa = &pSorter->aPoslist[i1];
- }else{
- *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
- }
-
- return rc;
-}
-
-/*
-** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
-** correctly for the current view. Return SQLITE_OK if successful, or an
-** SQLite error code otherwise.
-*/
-static int fts5CacheInstArray(Fts5Cursor *pCsr){
- int rc = SQLITE_OK;
- Fts5PoslistReader *aIter; /* One iterator for each phrase */
- int nIter; /* Number of iterators/phrases */
-
- nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
- if( pCsr->aInstIter==0 ){
- int nByte = sizeof(Fts5PoslistReader) * nIter;
- pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
- }
- aIter = pCsr->aInstIter;
-
- if( aIter ){
- int nInst = 0; /* Number instances seen so far */
- int i;
-
- /* Initialize all iterators */
- for(i=0; i<nIter && rc==SQLITE_OK; i++){
- const u8 *a;
- int n;
- rc = fts5CsrPoslist(pCsr, i, &a, &n);
- if( rc==SQLITE_OK ){
- sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
- }
- }
-
- if( rc==SQLITE_OK ){
- while( 1 ){
- int *aInst;
- int iBest = -1;
- for(i=0; i<nIter; i++){
- if( (aIter[i].bEof==0)
- && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos)
- ){
- iBest = i;
- }
- }
- if( iBest<0 ) break;
-
- nInst++;
- if( nInst>=pCsr->nInstAlloc ){
- pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
- aInst = (int*)sqlite3_realloc(
- pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
- );
- if( aInst ){
- pCsr->aInst = aInst;
- }else{
- rc = SQLITE_NOMEM;
- break;
- }
- }
-
- aInst = &pCsr->aInst[3 * (nInst-1)];
- aInst[0] = iBest;
- aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
- aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
- sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
- }
- }
-
- pCsr->nInstCount = nInst;
- CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
- }
- return rc;
-}
-
-static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- int rc = SQLITE_OK;
- if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
- || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){
- *pnInst = pCsr->nInstCount;
- }
- return rc;
-}
-
-static int fts5ApiInst(
- Fts5Context *pCtx,
- int iIdx,
- int *piPhrase,
- int *piCol,
- int *piOff
-){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- int rc = SQLITE_OK;
- if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
- || SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
- ){
- if( iIdx<0 || iIdx>=pCsr->nInstCount ){
- rc = SQLITE_RANGE;
-#if 0
- }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){
- *piPhrase = pCsr->aInst[iIdx*3];
- *piCol = pCsr->aInst[iIdx*3 + 2];
- *piOff = -1;
-#endif
- }else{
- *piPhrase = pCsr->aInst[iIdx*3];
- *piCol = pCsr->aInst[iIdx*3 + 1];
- *piOff = pCsr->aInst[iIdx*3 + 2];
- }
- }
- return rc;
-}
-
-static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){
- return fts5CursorRowid((Fts5Cursor*)pCtx);
-}
-
-static int fts5ColumnSizeCb(
- void *pContext, /* Pointer to int */
- int tflags,
- const char *pUnused, /* Buffer containing token */
- int nUnused, /* Size of token in bytes */
- int iUnused1, /* Start offset of token */
- int iUnused2 /* End offset of token */
-){
- int *pCnt = (int*)pContext;
- UNUSED_PARAM2(pUnused, nUnused);
- UNUSED_PARAM2(iUnused1, iUnused2);
- if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
- (*pCnt)++;
- }
- return SQLITE_OK;
-}
-
-static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- Fts5Config *pConfig = pTab->pConfig;
- int rc = SQLITE_OK;
-
- if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
- if( pConfig->bColumnsize ){
- i64 iRowid = fts5CursorRowid(pCsr);
- rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
- }else if( pConfig->zContent==0 ){
- int i;
- for(i=0; i<pConfig->nCol; i++){
- if( pConfig->abUnindexed[i]==0 ){
- pCsr->aColumnSize[i] = -1;
- }
- }
- }else{
- int i;
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( pConfig->abUnindexed[i]==0 ){
- const char *z; int n;
- void *p = (void*)(&pCsr->aColumnSize[i]);
- pCsr->aColumnSize[i] = 0;
- rc = fts5ApiColumnText(pCtx, i, &z, &n);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5Tokenize(
- pConfig, FTS5_TOKENIZE_AUX, z, n, p, fts5ColumnSizeCb
- );
- }
- }
- }
- }
- CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
- }
- if( iCol<0 ){
- int i;
- *pnToken = 0;
- for(i=0; i<pConfig->nCol; i++){
- *pnToken += pCsr->aColumnSize[i];
- }
- }else if( iCol<pConfig->nCol ){
- *pnToken = pCsr->aColumnSize[iCol];
- }else{
- *pnToken = 0;
- rc = SQLITE_RANGE;
- }
- return rc;
-}
-
-/*
-** Implementation of the xSetAuxdata() method.
-*/
-static int fts5ApiSetAuxdata(
- Fts5Context *pCtx, /* Fts5 context */
- void *pPtr, /* Pointer to save as auxdata */
- void(*xDelete)(void*) /* Destructor for pPtr (or NULL) */
-){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Auxdata *pData;
-
- /* Search through the cursors list of Fts5Auxdata objects for one that
- ** corresponds to the currently executing auxiliary function. */
- for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){
- if( pData->pAux==pCsr->pAux ) break;
- }
-
- if( pData ){
- if( pData->xDelete ){
- pData->xDelete(pData->pPtr);
- }
- }else{
- int rc = SQLITE_OK;
- pData = (Fts5Auxdata*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Auxdata));
- if( pData==0 ){
- if( xDelete ) xDelete(pPtr);
- return rc;
- }
- pData->pAux = pCsr->pAux;
- pData->pNext = pCsr->pAuxdata;
- pCsr->pAuxdata = pData;
- }
-
- pData->xDelete = xDelete;
- pData->pPtr = pPtr;
- return SQLITE_OK;
-}
-
-static void *fts5ApiGetAuxdata(Fts5Context *pCtx, int bClear){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Auxdata *pData;
- void *pRet = 0;
-
- for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){
- if( pData->pAux==pCsr->pAux ) break;
- }
-
- if( pData ){
- pRet = pData->pPtr;
- if( bClear ){
- pData->pPtr = 0;
- pData->xDelete = 0;
- }
- }
-
- return pRet;
-}
-
-static void fts5ApiPhraseNext(
- Fts5Context *pUnused,
- Fts5PhraseIter *pIter,
- int *piCol, int *piOff
-){
- UNUSED_PARAM(pUnused);
- if( pIter->a>=pIter->b ){
- *piCol = -1;
- *piOff = -1;
- }else{
- int iVal;
- pIter->a += fts5GetVarint32(pIter->a, iVal);
- if( iVal==1 ){
- pIter->a += fts5GetVarint32(pIter->a, iVal);
- *piCol = iVal;
- *piOff = 0;
- pIter->a += fts5GetVarint32(pIter->a, iVal);
- }
- *piOff += (iVal-2);
- }
-}
-
-static int fts5ApiPhraseFirst(
- Fts5Context *pCtx,
- int iPhrase,
- Fts5PhraseIter *pIter,
- int *piCol, int *piOff
-){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- int n;
- int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
- if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
- *piCol = 0;
- *piOff = 0;
- fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
- }
- return rc;
-}
-
-static void fts5ApiPhraseNextColumn(
- Fts5Context *pCtx,
- Fts5PhraseIter *pIter,
- int *piCol
-){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
-
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- if( pIter->a>=pIter->b ){
- *piCol = -1;
- }else{
- int iIncr;
- pIter->a += fts5GetVarint32(&pIter->a[0], iIncr);
- *piCol += (iIncr-2);
- }
- }else{
- while( 1 ){
- int dummy;
- if( pIter->a>=pIter->b ){
- *piCol = -1;
- return;
- }
- if( pIter->a[0]==0x01 ) break;
- pIter->a += fts5GetVarint32(pIter->a, dummy);
- }
- pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
- }
-}
-
-static int fts5ApiPhraseFirstColumn(
- Fts5Context *pCtx,
- int iPhrase,
- Fts5PhraseIter *pIter,
- int *piCol
-){
- int rc = SQLITE_OK;
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
-
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- Fts5Sorter *pSorter = pCsr->pSorter;
- int n;
- if( pSorter ){
- int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
- n = pSorter->aIdx[iPhrase] - i1;
- pIter->a = &pSorter->aPoslist[i1];
- }else{
- rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
- }
- if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
- *piCol = 0;
- fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
- }
- }else{
- int n;
- rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
- if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
- if( n<=0 ){
- *piCol = -1;
- }else if( pIter->a[0]==0x01 ){
- pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
- }else{
- *piCol = 0;
- }
- }
- }
-
- return rc;
-}
-
-
-static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
- int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
-);
-
-static const Fts5ExtensionApi sFts5Api = {
- 2, /* iVersion */
- fts5ApiUserData,
- fts5ApiColumnCount,
- fts5ApiRowCount,
- fts5ApiColumnTotalSize,
- fts5ApiTokenize,
- fts5ApiPhraseCount,
- fts5ApiPhraseSize,
- fts5ApiInstCount,
- fts5ApiInst,
- fts5ApiRowid,
- fts5ApiColumnText,
- fts5ApiColumnSize,
- fts5ApiQueryPhrase,
- fts5ApiSetAuxdata,
- fts5ApiGetAuxdata,
- fts5ApiPhraseFirst,
- fts5ApiPhraseNext,
- fts5ApiPhraseFirstColumn,
- fts5ApiPhraseNextColumn,
-};
-
-/*
-** Implementation of API function xQueryPhrase().
-*/
-static int fts5ApiQueryPhrase(
- Fts5Context *pCtx,
- int iPhrase,
- void *pUserData,
- int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
-){
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- int rc;
- Fts5Cursor *pNew = 0;
-
- rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew);
- if( rc==SQLITE_OK ){
- pNew->ePlan = FTS5_PLAN_MATCH;
- pNew->iFirstRowid = SMALLEST_INT64;
- pNew->iLastRowid = LARGEST_INT64;
- pNew->base.pVtab = (sqlite3_vtab*)pTab;
- rc = sqlite3Fts5ExprClonePhrase(pCsr->pExpr, iPhrase, &pNew->pExpr);
- }
-
- if( rc==SQLITE_OK ){
- for(rc = fts5CursorFirst(pTab, pNew, 0);
- rc==SQLITE_OK && CsrFlagTest(pNew, FTS5CSR_EOF)==0;
- rc = fts5NextMethod((sqlite3_vtab_cursor*)pNew)
- ){
- rc = xCallback(&sFts5Api, (Fts5Context*)pNew, pUserData);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- break;
- }
- }
- }
-
- fts5CloseMethod((sqlite3_vtab_cursor*)pNew);
- return rc;
-}
-
-static void fts5ApiInvoke(
- Fts5Auxiliary *pAux,
- Fts5Cursor *pCsr,
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- assert( pCsr->pAux==0 );
- pCsr->pAux = pAux;
- pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
- pCsr->pAux = 0;
-}
-
-static Fts5Cursor *fts5CursorFromCsrid(Fts5Global *pGlobal, i64 iCsrId){
- Fts5Cursor *pCsr;
- for(pCsr=pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
- if( pCsr->iCsrId==iCsrId ) break;
- }
- return pCsr;
-}
-
-static void fts5ApiCallback(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
-
- Fts5Auxiliary *pAux;
- Fts5Cursor *pCsr;
- i64 iCsrId;
-
- assert( argc>=1 );
- pAux = (Fts5Auxiliary*)sqlite3_user_data(context);
- iCsrId = sqlite3_value_int64(argv[0]);
-
- pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
- if( pCsr==0 ){
- char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- }else{
- fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
- }
-}
-
-
-/*
-** Given cursor id iId, return a pointer to the corresponding Fts5Index
-** object. Or NULL If the cursor id does not exist.
-**
-** If successful, set *ppConfig to point to the associated config object
-** before returning.
-*/
-Fts5Index *sqlite3Fts5IndexFromCsrid(
- Fts5Global *pGlobal, /* FTS5 global context for db handle */
- i64 iCsrId, /* Id of cursor to find */
- Fts5Config **ppConfig /* OUT: Configuration object */
-){
- Fts5Cursor *pCsr;
- Fts5Table *pTab;
-
- pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
- pTab = (Fts5Table*)pCsr->base.pVtab;
- *ppConfig = pTab->pConfig;
-
- return pTab->pIndex;
-}
-
-/*
-** Return a "position-list blob" corresponding to the current position of
-** cursor pCsr via sqlite3_result_blob(). A position-list blob contains
-** the current position-list for each phrase in the query associated with
-** cursor pCsr.
-**
-** A position-list blob begins with (nPhrase-1) varints, where nPhrase is
-** the number of phrases in the query. Following the varints are the
-** concatenated position lists for each phrase, in order.
-**
-** The first varint (if it exists) contains the size of the position list
-** for phrase 0. The second (same disclaimer) contains the size of position
-** list 1. And so on. There is no size field for the final position list,
-** as it can be derived from the total size of the blob.
-*/
-static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){
- int i;
- int rc = SQLITE_OK;
- int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
- Fts5Buffer val;
-
- memset(&val, 0, sizeof(Fts5Buffer));
- switch( ((Fts5Table*)(pCsr->base.pVtab))->pConfig->eDetail ){
- case FTS5_DETAIL_FULL:
-
- /* Append the varints */
- for(i=0; i<(nPhrase-1); i++){
- const u8 *dummy;
- int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
- sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
- }
-
- /* Append the position lists */
- for(i=0; i<nPhrase; i++){
- const u8 *pPoslist;
- int nPoslist;
- nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
- sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
- }
- break;
-
- case FTS5_DETAIL_COLUMNS:
-
- /* Append the varints */
- for(i=0; rc==SQLITE_OK && i<(nPhrase-1); i++){
- const u8 *dummy;
- int nByte;
- rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &dummy, &nByte);
- sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
- }
-
- /* Append the position lists */
- for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
- const u8 *pPoslist;
- int nPoslist;
- rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &pPoslist, &nPoslist);
- sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
- }
- break;
-
- default:
- break;
- }
-
- sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
- return rc;
-}
-
-/*
-** This is the xColumn method, called by SQLite to request a value from
-** the row that the supplied cursor currently points to.
-*/
-static int fts5ColumnMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
- int iCol /* Index of column to read value from */
-){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
- Fts5Config *pConfig = pTab->pConfig;
- Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
- int rc = SQLITE_OK;
-
- assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
-
- if( pCsr->ePlan==FTS5_PLAN_SPECIAL ){
- if( iCol==pConfig->nCol ){
- sqlite3_result_int64(pCtx, pCsr->iSpecial);
- }
- }else
-
- if( iCol==pConfig->nCol ){
- /* User is requesting the value of the special column with the same name
- ** as the table. Return the cursor integer id number. This value is only
- ** useful in that it may be passed as the first argument to an FTS5
- ** auxiliary function. */
- sqlite3_result_int64(pCtx, pCsr->iCsrId);
- }else if( iCol==pConfig->nCol+1 ){
-
- /* The value of the "rank" column. */
- if( pCsr->ePlan==FTS5_PLAN_SOURCE ){
- fts5PoslistBlob(pCtx, pCsr);
- }else if(
- pCsr->ePlan==FTS5_PLAN_MATCH
- || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
- ){
- if( pCsr->pRank || SQLITE_OK==(rc = fts5FindRankFunction(pCsr)) ){
- fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg);
- }
- }
- }else if( !fts5IsContentless(pTab) ){
- rc = fts5SeekCursor(pCsr, 1);
- if( rc==SQLITE_OK ){
- sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
- }
- }
- return rc;
-}
-
-
-/*
-** This routine implements the xFindFunction method for the FTS3
-** virtual table.
-*/
-static int fts5FindFunctionMethod(
- sqlite3_vtab *pVtab, /* Virtual table handle */
- int nUnused, /* Number of SQL function arguments */
- const char *zName, /* Name of SQL function */
- void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
- void **ppArg /* OUT: User data for *pxFunc */
-){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- Fts5Auxiliary *pAux;
-
- UNUSED_PARAM(nUnused);
- pAux = fts5FindAuxiliary(pTab, zName);
- if( pAux ){
- *pxFunc = fts5ApiCallback;
- *ppArg = (void*)pAux;
- return 1;
- }
-
- /* No function of the specified name was found. Return 0. */
- return 0;
-}
-
-/*
-** Implementation of FTS5 xRename method. Rename an fts5 table.
-*/
-static int fts5RenameMethod(
- sqlite3_vtab *pVtab, /* Virtual table handle */
- const char *zName /* New name of table */
-){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- return sqlite3Fts5StorageRename(pTab->pStorage, zName);
-}
-
-/*
-** The xSavepoint() method.
-**
-** Flush the contents of the pending-terms table to disk.
-*/
-static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
- fts5TripCursors(pTab);
- return sqlite3Fts5StorageSync(pTab->pStorage);
-}
-
-/*
-** The xRelease() method.
-**
-** This is a no-op.
-*/
-static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
- fts5TripCursors(pTab);
- return sqlite3Fts5StorageSync(pTab->pStorage);
-}
-
-/*
-** The xRollbackTo() method.
-**
-** Discard the contents of the pending terms table.
-*/
-static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
- fts5TripCursors(pTab);
- return sqlite3Fts5StorageRollback(pTab->pStorage);
-}
-
-/*
-** Register a new auxiliary function with global context pGlobal.
-*/
-static int fts5CreateAux(
- fts5_api *pApi, /* Global context (one per db handle) */
- const char *zName, /* Name of new function */
- void *pUserData, /* User data for aux. function */
- fts5_extension_function xFunc, /* Aux. function implementation */
- void(*xDestroy)(void*) /* Destructor for pUserData */
-){
- Fts5Global *pGlobal = (Fts5Global*)pApi;
- int rc = sqlite3_overload_function(pGlobal->db, zName, -1);
- if( rc==SQLITE_OK ){
- Fts5Auxiliary *pAux;
- int nName; /* Size of zName in bytes, including \0 */
- int nByte; /* Bytes of space to allocate */
-
- nName = (int)strlen(zName) + 1;
- nByte = sizeof(Fts5Auxiliary) + nName;
- pAux = (Fts5Auxiliary*)sqlite3_malloc(nByte);
- if( pAux ){
- memset(pAux, 0, nByte);
- pAux->zFunc = (char*)&pAux[1];
- memcpy(pAux->zFunc, zName, nName);
- pAux->pGlobal = pGlobal;
- pAux->pUserData = pUserData;
- pAux->xFunc = xFunc;
- pAux->xDestroy = xDestroy;
- pAux->pNext = pGlobal->pAux;
- pGlobal->pAux = pAux;
- }else{
- rc = SQLITE_NOMEM;
- }
- }
-
- return rc;
-}
-
-/*
-** Register a new tokenizer. This is the implementation of the
-** fts5_api.xCreateTokenizer() method.
-*/
-static int fts5CreateTokenizer(
- fts5_api *pApi, /* Global context (one per db handle) */
- const char *zName, /* Name of new function */
- void *pUserData, /* User data for aux. function */
- fts5_tokenizer *pTokenizer, /* Tokenizer implementation */
- void(*xDestroy)(void*) /* Destructor for pUserData */
-){
- Fts5Global *pGlobal = (Fts5Global*)pApi;
- Fts5TokenizerModule *pNew;
- int nName; /* Size of zName and its \0 terminator */
- int nByte; /* Bytes of space to allocate */
- int rc = SQLITE_OK;
-
- nName = (int)strlen(zName) + 1;
- nByte = sizeof(Fts5TokenizerModule) + nName;
- pNew = (Fts5TokenizerModule*)sqlite3_malloc(nByte);
- if( pNew ){
- memset(pNew, 0, nByte);
- pNew->zName = (char*)&pNew[1];
- memcpy(pNew->zName, zName, nName);
- pNew->pUserData = pUserData;
- pNew->x = *pTokenizer;
- pNew->xDestroy = xDestroy;
- pNew->pNext = pGlobal->pTok;
- pGlobal->pTok = pNew;
- if( pNew->pNext==0 ){
- pGlobal->pDfltTok = pNew;
- }
- }else{
- rc = SQLITE_NOMEM;
- }
-
- return rc;
-}
-
-static Fts5TokenizerModule *fts5LocateTokenizer(
- Fts5Global *pGlobal,
- const char *zName
-){
- Fts5TokenizerModule *pMod = 0;
-
- if( zName==0 ){
- pMod = pGlobal->pDfltTok;
- }else{
- for(pMod=pGlobal->pTok; pMod; pMod=pMod->pNext){
- if( sqlite3_stricmp(zName, pMod->zName)==0 ) break;
- }
- }
-
- return pMod;
-}
-
-/*
-** Find a tokenizer. This is the implementation of the
-** fts5_api.xFindTokenizer() method.
-*/
-static int fts5FindTokenizer(
- fts5_api *pApi, /* Global context (one per db handle) */
- const char *zName, /* Name of new function */
- void **ppUserData,
- fts5_tokenizer *pTokenizer /* Populate this object */
-){
- int rc = SQLITE_OK;
- Fts5TokenizerModule *pMod;
-
- pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName);
- if( pMod ){
- *pTokenizer = pMod->x;
- *ppUserData = pMod->pUserData;
- }else{
- memset(pTokenizer, 0, sizeof(fts5_tokenizer));
- rc = SQLITE_ERROR;
- }
-
- return rc;
-}
-
-int sqlite3Fts5GetTokenizer(
- Fts5Global *pGlobal,
- const char **azArg,
- int nArg,
- Fts5Tokenizer **ppTok,
- fts5_tokenizer **ppTokApi,
- char **pzErr
-){
- Fts5TokenizerModule *pMod;
- int rc = SQLITE_OK;
-
- pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
- if( pMod==0 ){
- assert( nArg>0 );
- rc = SQLITE_ERROR;
- *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
- }else{
- rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);
- *ppTokApi = &pMod->x;
- if( rc!=SQLITE_OK && pzErr ){
- *pzErr = sqlite3_mprintf("error in tokenizer constructor");
- }
- }
-
- if( rc!=SQLITE_OK ){
- *ppTokApi = 0;
- *ppTok = 0;
- }
-
- return rc;
-}
-
-static void fts5ModuleDestroy(void *pCtx){
- Fts5TokenizerModule *pTok, *pNextTok;
- Fts5Auxiliary *pAux, *pNextAux;
- Fts5Global *pGlobal = (Fts5Global*)pCtx;
-
- for(pAux=pGlobal->pAux; pAux; pAux=pNextAux){
- pNextAux = pAux->pNext;
- if( pAux->xDestroy ) pAux->xDestroy(pAux->pUserData);
- sqlite3_free(pAux);
- }
-
- for(pTok=pGlobal->pTok; pTok; pTok=pNextTok){
- pNextTok = pTok->pNext;
- if( pTok->xDestroy ) pTok->xDestroy(pTok->pUserData);
- sqlite3_free(pTok);
- }
-
- sqlite3_free(pGlobal);
-}
-
-static void fts5Fts5Func(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args */
- sqlite3_value **apArg /* Function arguments */
-){
- Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
- fts5_api **ppApi;
- UNUSED_PARAM(nArg);
- assert( nArg==1 );
- ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr");
- if( ppApi ) *ppApi = &pGlobal->api;
-}
-
-/*
-** Implementation of fts5_source_id() function.
-*/
-static void fts5SourceIdFunc(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args */
- sqlite3_value **apUnused /* Function arguments */
-){
- assert( nArg==0 );
- UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT);
-}
-
-static int fts5Init(sqlite3 *db){
- static const sqlite3_module fts5Mod = {
- /* iVersion */ 2,
- /* xCreate */ fts5CreateMethod,
- /* xConnect */ fts5ConnectMethod,
- /* xBestIndex */ fts5BestIndexMethod,
- /* xDisconnect */ fts5DisconnectMethod,
- /* xDestroy */ fts5DestroyMethod,
- /* xOpen */ fts5OpenMethod,
- /* xClose */ fts5CloseMethod,
- /* xFilter */ fts5FilterMethod,
- /* xNext */ fts5NextMethod,
- /* xEof */ fts5EofMethod,
- /* xColumn */ fts5ColumnMethod,
- /* xRowid */ fts5RowidMethod,
- /* xUpdate */ fts5UpdateMethod,
- /* xBegin */ fts5BeginMethod,
- /* xSync */ fts5SyncMethod,
- /* xCommit */ fts5CommitMethod,
- /* xRollback */ fts5RollbackMethod,
- /* xFindFunction */ fts5FindFunctionMethod,
- /* xRename */ fts5RenameMethod,
- /* xSavepoint */ fts5SavepointMethod,
- /* xRelease */ fts5ReleaseMethod,
- /* xRollbackTo */ fts5RollbackToMethod,
- };
-
- int rc;
- Fts5Global *pGlobal = 0;
-
- pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
- if( pGlobal==0 ){
- rc = SQLITE_NOMEM;
- }else{
- void *p = (void*)pGlobal;
- memset(pGlobal, 0, sizeof(Fts5Global));
- pGlobal->db = db;
- pGlobal->api.iVersion = 2;
- pGlobal->api.xCreateFunction = fts5CreateAux;
- pGlobal->api.xCreateTokenizer = fts5CreateTokenizer;
- pGlobal->api.xFindTokenizer = fts5FindTokenizer;
- rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy);
- if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db);
- if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db);
- if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api);
- if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api);
- if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(
- db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
- );
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(
- db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0
- );
- }
- }
-
- /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
- ** fts5_test_mi.c is compiled and linked into the executable. And call
- ** its entry point to enable the matchinfo() demo. */
-#ifdef SQLITE_FTS5_ENABLE_TEST_MI
- if( rc==SQLITE_OK ){
- extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
- rc = sqlite3Fts5TestRegisterMatchinfo(db);
- }
-#endif
-
- return rc;
-}
-
-/*
-** The following functions are used to register the module with SQLite. If
-** this module is being built as part of the SQLite core (SQLITE_CORE is
-** defined), then sqlite3_open() will call sqlite3Fts5Init() directly.
-**
-** Or, if this module is being built as a loadable extension,
-** sqlite3Fts5Init() is omitted and the two standard entry points
-** sqlite3_fts_init() and sqlite3_fts5_init() defined instead.
-*/
-#ifndef SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fts_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- return fts5Init(db);
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fts5_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- return fts5Init(db);
-}
-#else
-int sqlite3Fts5Init(sqlite3 *db){
- return fts5Init(db);
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_storage.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_storage.c
deleted file mode 100644
index 70d7135113f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_storage.c
+++ /dev/null
@@ -1,1132 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-**
-*/
-
-
-
-#include "fts5Int.h"
-
-struct Fts5Storage {
- Fts5Config *pConfig;
- Fts5Index *pIndex;
- int bTotalsValid; /* True if nTotalRow/aTotalSize[] are valid */
- i64 nTotalRow; /* Total number of rows in FTS table */
- i64 *aTotalSize; /* Total sizes of each column */
- sqlite3_stmt *aStmt[11];
-};
-
-
-#if FTS5_STMT_SCAN_ASC!=0
-# error "FTS5_STMT_SCAN_ASC mismatch"
-#endif
-#if FTS5_STMT_SCAN_DESC!=1
-# error "FTS5_STMT_SCAN_DESC mismatch"
-#endif
-#if FTS5_STMT_LOOKUP!=2
-# error "FTS5_STMT_LOOKUP mismatch"
-#endif
-
-#define FTS5_STMT_INSERT_CONTENT 3
-#define FTS5_STMT_REPLACE_CONTENT 4
-#define FTS5_STMT_DELETE_CONTENT 5
-#define FTS5_STMT_REPLACE_DOCSIZE 6
-#define FTS5_STMT_DELETE_DOCSIZE 7
-#define FTS5_STMT_LOOKUP_DOCSIZE 8
-#define FTS5_STMT_REPLACE_CONFIG 9
-#define FTS5_STMT_SCAN 10
-
-/*
-** Prepare the two insert statements - Fts5Storage.pInsertContent and
-** Fts5Storage.pInsertDocsize - if they have not already been prepared.
-** Return SQLITE_OK if successful, or an SQLite error code if an error
-** occurs.
-*/
-static int fts5StorageGetStmt(
- Fts5Storage *p, /* Storage handle */
- int eStmt, /* FTS5_STMT_XXX constant */
- sqlite3_stmt **ppStmt, /* OUT: Prepared statement handle */
- char **pzErrMsg /* OUT: Error message (if any) */
-){
- int rc = SQLITE_OK;
-
- /* If there is no %_docsize table, there should be no requests for
- ** statements to operate on it. */
- assert( p->pConfig->bColumnsize || (
- eStmt!=FTS5_STMT_REPLACE_DOCSIZE
- && eStmt!=FTS5_STMT_DELETE_DOCSIZE
- && eStmt!=FTS5_STMT_LOOKUP_DOCSIZE
- ));
-
- assert( eStmt>=0 && eStmt<ArraySize(p->aStmt) );
- if( p->aStmt[eStmt]==0 ){
- const char *azStmt[] = {
- "SELECT %s FROM %s T WHERE T.%Q >= ? AND T.%Q <= ? ORDER BY T.%Q ASC",
- "SELECT %s FROM %s T WHERE T.%Q <= ? AND T.%Q >= ? ORDER BY T.%Q DESC",
- "SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP */
-
- "INSERT INTO %Q.'%q_content' VALUES(%s)", /* INSERT_CONTENT */
- "REPLACE INTO %Q.'%q_content' VALUES(%s)", /* REPLACE_CONTENT */
- "DELETE FROM %Q.'%q_content' WHERE id=?", /* DELETE_CONTENT */
- "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", /* REPLACE_DOCSIZE */
- "DELETE FROM %Q.'%q_docsize' WHERE id=?", /* DELETE_DOCSIZE */
-
- "SELECT sz FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */
-
- "REPLACE INTO %Q.'%q_config' VALUES(?,?)", /* REPLACE_CONFIG */
- "SELECT %s FROM %s AS T", /* SCAN */
- };
- Fts5Config *pC = p->pConfig;
- char *zSql = 0;
-
- switch( eStmt ){
- case FTS5_STMT_SCAN:
- zSql = sqlite3_mprintf(azStmt[eStmt],
- pC->zContentExprlist, pC->zContent
- );
- break;
-
- case FTS5_STMT_SCAN_ASC:
- case FTS5_STMT_SCAN_DESC:
- zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContentExprlist,
- pC->zContent, pC->zContentRowid, pC->zContentRowid,
- pC->zContentRowid
- );
- break;
-
- case FTS5_STMT_LOOKUP:
- zSql = sqlite3_mprintf(azStmt[eStmt],
- pC->zContentExprlist, pC->zContent, pC->zContentRowid
- );
- break;
-
- case FTS5_STMT_INSERT_CONTENT:
- case FTS5_STMT_REPLACE_CONTENT: {
- int nCol = pC->nCol + 1;
- char *zBind;
- int i;
-
- zBind = sqlite3_malloc(1 + nCol*2);
- if( zBind ){
- for(i=0; i<nCol; i++){
- zBind[i*2] = '?';
- zBind[i*2 + 1] = ',';
- }
- zBind[i*2-1] = '\0';
- zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
- sqlite3_free(zBind);
- }
- break;
- }
-
- default:
- zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName);
- break;
- }
-
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v3(pC->db, zSql, -1,
- SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK && pzErrMsg ){
- *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
- }
- }
- }
-
- *ppStmt = p->aStmt[eStmt];
- sqlite3_reset(*ppStmt);
- return rc;
-}
-
-
-static int fts5ExecPrintf(
- sqlite3 *db,
- char **pzErr,
- const char *zFormat,
- ...
-){
- int rc;
- va_list ap; /* ... printf arguments */
- char *zSql;
-
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
-
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_exec(db, zSql, 0, 0, pzErr);
- sqlite3_free(zSql);
- }
-
- va_end(ap);
- return rc;
-}
-
-/*
-** Drop all shadow tables. Return SQLITE_OK if successful or an SQLite error
-** code otherwise.
-*/
-int sqlite3Fts5DropAll(Fts5Config *pConfig){
- int rc = fts5ExecPrintf(pConfig->db, 0,
- "DROP TABLE IF EXISTS %Q.'%q_data';"
- "DROP TABLE IF EXISTS %Q.'%q_idx';"
- "DROP TABLE IF EXISTS %Q.'%q_config';",
- pConfig->zDb, pConfig->zName,
- pConfig->zDb, pConfig->zName,
- pConfig->zDb, pConfig->zName
- );
- if( rc==SQLITE_OK && pConfig->bColumnsize ){
- rc = fts5ExecPrintf(pConfig->db, 0,
- "DROP TABLE IF EXISTS %Q.'%q_docsize';",
- pConfig->zDb, pConfig->zName
- );
- }
- if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
- rc = fts5ExecPrintf(pConfig->db, 0,
- "DROP TABLE IF EXISTS %Q.'%q_content';",
- pConfig->zDb, pConfig->zName
- );
- }
- return rc;
-}
-
-static void fts5StorageRenameOne(
- Fts5Config *pConfig, /* Current FTS5 configuration */
- int *pRc, /* IN/OUT: Error code */
- const char *zTail, /* Tail of table name e.g. "data", "config" */
- const char *zName /* New name of FTS5 table */
-){
- if( *pRc==SQLITE_OK ){
- *pRc = fts5ExecPrintf(pConfig->db, 0,
- "ALTER TABLE %Q.'%q_%s' RENAME TO '%q_%s';",
- pConfig->zDb, pConfig->zName, zTail, zName, zTail
- );
- }
-}
-
-int sqlite3Fts5StorageRename(Fts5Storage *pStorage, const char *zName){
- Fts5Config *pConfig = pStorage->pConfig;
- int rc = sqlite3Fts5StorageSync(pStorage);
-
- fts5StorageRenameOne(pConfig, &rc, "data", zName);
- fts5StorageRenameOne(pConfig, &rc, "idx", zName);
- fts5StorageRenameOne(pConfig, &rc, "config", zName);
- if( pConfig->bColumnsize ){
- fts5StorageRenameOne(pConfig, &rc, "docsize", zName);
- }
- if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
- fts5StorageRenameOne(pConfig, &rc, "content", zName);
- }
- return rc;
-}
-
-/*
-** Create the shadow table named zPost, with definition zDefn. Return
-** SQLITE_OK if successful, or an SQLite error code otherwise.
-*/
-int sqlite3Fts5CreateTable(
- Fts5Config *pConfig, /* FTS5 configuration */
- const char *zPost, /* Shadow table to create (e.g. "content") */
- const char *zDefn, /* Columns etc. for shadow table */
- int bWithout, /* True for without rowid */
- char **pzErr /* OUT: Error message */
-){
- int rc;
- char *zErr = 0;
-
- rc = fts5ExecPrintf(pConfig->db, &zErr, "CREATE TABLE %Q.'%q_%q'(%s)%s",
- pConfig->zDb, pConfig->zName, zPost, zDefn,
-#ifndef SQLITE_FTS5_NO_WITHOUT_ROWID
- bWithout?" WITHOUT ROWID":
-#endif
- ""
- );
- if( zErr ){
- *pzErr = sqlite3_mprintf(
- "fts5: error creating shadow table %q_%s: %s",
- pConfig->zName, zPost, zErr
- );
- sqlite3_free(zErr);
- }
-
- return rc;
-}
-
-/*
-** Open a new Fts5Index handle. If the bCreate argument is true, create
-** and initialize the underlying tables
-**
-** If successful, set *pp to point to the new object and return SQLITE_OK.
-** Otherwise, set *pp to NULL and return an SQLite error code.
-*/
-int sqlite3Fts5StorageOpen(
- Fts5Config *pConfig,
- Fts5Index *pIndex,
- int bCreate,
- Fts5Storage **pp,
- char **pzErr /* OUT: Error message */
-){
- int rc = SQLITE_OK;
- Fts5Storage *p; /* New object */
- int nByte; /* Bytes of space to allocate */
-
- nByte = sizeof(Fts5Storage) /* Fts5Storage object */
- + pConfig->nCol * sizeof(i64); /* Fts5Storage.aTotalSize[] */
- *pp = p = (Fts5Storage*)sqlite3_malloc(nByte);
- if( !p ) return SQLITE_NOMEM;
-
- memset(p, 0, nByte);
- p->aTotalSize = (i64*)&p[1];
- p->pConfig = pConfig;
- p->pIndex = pIndex;
-
- if( bCreate ){
- if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
- int nDefn = 32 + pConfig->nCol*10;
- char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
- if( zDefn==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int i;
- int iOff;
- sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
- iOff = (int)strlen(zDefn);
- for(i=0; i<pConfig->nCol; i++){
- sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
- iOff += (int)strlen(&zDefn[iOff]);
- }
- rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
- }
- sqlite3_free(zDefn);
- }
-
- if( rc==SQLITE_OK && pConfig->bColumnsize ){
- rc = sqlite3Fts5CreateTable(
- pConfig, "docsize", "id INTEGER PRIMARY KEY, sz BLOB", 0, pzErr
- );
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5CreateTable(
- pConfig, "config", "k PRIMARY KEY, v", 1, pzErr
- );
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageConfigValue(p, "version", 0, FTS5_CURRENT_VERSION);
- }
- }
-
- if( rc ){
- sqlite3Fts5StorageClose(p);
- *pp = 0;
- }
- return rc;
-}
-
-/*
-** Close a handle opened by an earlier call to sqlite3Fts5StorageOpen().
-*/
-int sqlite3Fts5StorageClose(Fts5Storage *p){
- int rc = SQLITE_OK;
- if( p ){
- int i;
-
- /* Finalize all SQL statements */
- for(i=0; i<ArraySize(p->aStmt); i++){
- sqlite3_finalize(p->aStmt[i]);
- }
-
- sqlite3_free(p);
- }
- return rc;
-}
-
-typedef struct Fts5InsertCtx Fts5InsertCtx;
-struct Fts5InsertCtx {
- Fts5Storage *pStorage;
- int iCol;
- int szCol; /* Size of column value in tokens */
-};
-
-/*
-** Tokenization callback used when inserting tokens into the FTS index.
-*/
-static int fts5StorageInsertCallback(
- void *pContext, /* Pointer to Fts5InsertCtx object */
- int tflags,
- const char *pToken, /* Buffer containing token */
- int nToken, /* Size of token in bytes */
- int iUnused1, /* Start offset of token */
- int iUnused2 /* End offset of token */
-){
- Fts5InsertCtx *pCtx = (Fts5InsertCtx*)pContext;
- Fts5Index *pIdx = pCtx->pStorage->pIndex;
- UNUSED_PARAM2(iUnused1, iUnused2);
- if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
- if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
- pCtx->szCol++;
- }
- return sqlite3Fts5IndexWrite(pIdx, pCtx->iCol, pCtx->szCol-1, pToken, nToken);
-}
-
-/*
-** If a row with rowid iDel is present in the %_content table, add the
-** delete-markers to the FTS index necessary to delete it. Do not actually
-** remove the %_content row at this time though.
-*/
-static int fts5StorageDeleteFromIndex(
- Fts5Storage *p,
- i64 iDel,
- sqlite3_value **apVal
-){
- Fts5Config *pConfig = p->pConfig;
- sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */
- int rc; /* Return code */
- int rc2; /* sqlite3_reset() return code */
- int iCol;
- Fts5InsertCtx ctx;
-
- if( apVal==0 ){
- rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0);
- if( rc!=SQLITE_OK ) return rc;
- sqlite3_bind_int64(pSeek, 1, iDel);
- if( sqlite3_step(pSeek)!=SQLITE_ROW ){
- return sqlite3_reset(pSeek);
- }
- }
-
- ctx.pStorage = p;
- ctx.iCol = -1;
- rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
- for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
- if( pConfig->abUnindexed[iCol-1]==0 ){
- const char *zText;
- int nText;
- if( pSeek ){
- zText = (const char*)sqlite3_column_text(pSeek, iCol);
- nText = sqlite3_column_bytes(pSeek, iCol);
- }else{
- zText = (const char*)sqlite3_value_text(apVal[iCol-1]);
- nText = sqlite3_value_bytes(apVal[iCol-1]);
- }
- ctx.szCol = 0;
- rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
- zText, nText, (void*)&ctx, fts5StorageInsertCallback
- );
- p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
- }
- }
- p->nTotalRow--;
-
- rc2 = sqlite3_reset(pSeek);
- if( rc==SQLITE_OK ) rc = rc2;
- return rc;
-}
-
-
-/*
-** Insert a record into the %_docsize table. Specifically, do:
-**
-** INSERT OR REPLACE INTO %_docsize(id, sz) VALUES(iRowid, pBuf);
-**
-** If there is no %_docsize table (as happens if the columnsize=0 option
-** is specified when the FTS5 table is created), this function is a no-op.
-*/
-static int fts5StorageInsertDocsize(
- Fts5Storage *p, /* Storage module to write to */
- i64 iRowid, /* id value */
- Fts5Buffer *pBuf /* sz value */
-){
- int rc = SQLITE_OK;
- if( p->pConfig->bColumnsize ){
- sqlite3_stmt *pReplace = 0;
- rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pReplace, 1, iRowid);
- sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
- sqlite3_step(pReplace);
- rc = sqlite3_reset(pReplace);
- sqlite3_bind_null(pReplace, 2);
- }
- }
- return rc;
-}
-
-/*
-** Load the contents of the "averages" record from disk into the
-** p->nTotalRow and p->aTotalSize[] variables. If successful, and if
-** argument bCache is true, set the p->bTotalsValid flag to indicate
-** that the contents of aTotalSize[] and nTotalRow are valid until
-** further notice.
-**
-** Return SQLITE_OK if successful, or an SQLite error code if an error
-** occurs.
-*/
-static int fts5StorageLoadTotals(Fts5Storage *p, int bCache){
- int rc = SQLITE_OK;
- if( p->bTotalsValid==0 ){
- rc = sqlite3Fts5IndexGetAverages(p->pIndex, &p->nTotalRow, p->aTotalSize);
- p->bTotalsValid = bCache;
- }
- return rc;
-}
-
-/*
-** Store the current contents of the p->nTotalRow and p->aTotalSize[]
-** variables in the "averages" record on disk.
-**
-** Return SQLITE_OK if successful, or an SQLite error code if an error
-** occurs.
-*/
-static int fts5StorageSaveTotals(Fts5Storage *p){
- int nCol = p->pConfig->nCol;
- int i;
- Fts5Buffer buf;
- int rc = SQLITE_OK;
- memset(&buf, 0, sizeof(buf));
-
- sqlite3Fts5BufferAppendVarint(&rc, &buf, p->nTotalRow);
- for(i=0; i<nCol; i++){
- sqlite3Fts5BufferAppendVarint(&rc, &buf, p->aTotalSize[i]);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexSetAverages(p->pIndex, buf.p, buf.n);
- }
- sqlite3_free(buf.p);
-
- return rc;
-}
-
-/*
-** Remove a row from the FTS table.
-*/
-int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
- Fts5Config *pConfig = p->pConfig;
- int rc;
- sqlite3_stmt *pDel = 0;
-
- assert( pConfig->eContent!=FTS5_CONTENT_NORMAL || apVal==0 );
- rc = fts5StorageLoadTotals(p, 1);
-
- /* Delete the index records */
- if( rc==SQLITE_OK ){
- rc = fts5StorageDeleteFromIndex(p, iDel, apVal);
- }
-
- /* Delete the %_docsize record */
- if( rc==SQLITE_OK && pConfig->bColumnsize ){
- rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pDel, 1, iDel);
- sqlite3_step(pDel);
- rc = sqlite3_reset(pDel);
- }
- }
-
- /* Delete the %_content record */
- if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
- if( rc==SQLITE_OK ){
- rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
- }
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pDel, 1, iDel);
- sqlite3_step(pDel);
- rc = sqlite3_reset(pDel);
- }
- }
-
- return rc;
-}
-
-/*
-** Delete all entries in the FTS5 index.
-*/
-int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
- Fts5Config *pConfig = p->pConfig;
- int rc;
-
- /* Delete the contents of the %_data and %_docsize tables. */
- rc = fts5ExecPrintf(pConfig->db, 0,
- "DELETE FROM %Q.'%q_data';"
- "DELETE FROM %Q.'%q_idx';",
- pConfig->zDb, pConfig->zName,
- pConfig->zDb, pConfig->zName
- );
- if( rc==SQLITE_OK && pConfig->bColumnsize ){
- rc = fts5ExecPrintf(pConfig->db, 0,
- "DELETE FROM %Q.'%q_docsize';",
- pConfig->zDb, pConfig->zName
- );
- }
-
- /* Reinitialize the %_data table. This call creates the initial structure
- ** and averages records. */
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexReinit(p->pIndex);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageConfigValue(p, "version", 0, FTS5_CURRENT_VERSION);
- }
- return rc;
-}
-
-int sqlite3Fts5StorageRebuild(Fts5Storage *p){
- Fts5Buffer buf = {0,0,0};
- Fts5Config *pConfig = p->pConfig;
- sqlite3_stmt *pScan = 0;
- Fts5InsertCtx ctx;
- int rc;
-
- memset(&ctx, 0, sizeof(Fts5InsertCtx));
- ctx.pStorage = p;
- rc = sqlite3Fts5StorageDeleteAll(p);
- if( rc==SQLITE_OK ){
- rc = fts5StorageLoadTotals(p, 1);
- }
-
- if( rc==SQLITE_OK ){
- rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
- }
-
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){
- i64 iRowid = sqlite3_column_int64(pScan, 0);
-
- sqlite3Fts5BufferZero(&buf);
- rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
- for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
- ctx.szCol = 0;
- if( pConfig->abUnindexed[ctx.iCol]==0 ){
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_column_text(pScan, ctx.iCol+1),
- sqlite3_column_bytes(pScan, ctx.iCol+1),
- (void*)&ctx,
- fts5StorageInsertCallback
- );
- }
- sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
- p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
- }
- p->nTotalRow++;
-
- if( rc==SQLITE_OK ){
- rc = fts5StorageInsertDocsize(p, iRowid, &buf);
- }
- }
- sqlite3_free(buf.p);
-
- /* Write the averages record */
- if( rc==SQLITE_OK ){
- rc = fts5StorageSaveTotals(p);
- }
- return rc;
-}
-
-int sqlite3Fts5StorageOptimize(Fts5Storage *p){
- return sqlite3Fts5IndexOptimize(p->pIndex);
-}
-
-int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge){
- return sqlite3Fts5IndexMerge(p->pIndex, nMerge);
-}
-
-int sqlite3Fts5StorageReset(Fts5Storage *p){
- return sqlite3Fts5IndexReset(p->pIndex);
-}
-
-/*
-** Allocate a new rowid. This is used for "external content" tables when
-** a NULL value is inserted into the rowid column. The new rowid is allocated
-** by inserting a dummy row into the %_docsize table. The dummy will be
-** overwritten later.
-**
-** If the %_docsize table does not exist, SQLITE_MISMATCH is returned. In
-** this case the user is required to provide a rowid explicitly.
-*/
-static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
- int rc = SQLITE_MISMATCH;
- if( p->pConfig->bColumnsize ){
- sqlite3_stmt *pReplace = 0;
- rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_null(pReplace, 1);
- sqlite3_bind_null(pReplace, 2);
- sqlite3_step(pReplace);
- rc = sqlite3_reset(pReplace);
- }
- if( rc==SQLITE_OK ){
- *piRowid = sqlite3_last_insert_rowid(p->pConfig->db);
- }
- }
- return rc;
-}
-
-/*
-** Insert a new row into the FTS content table.
-*/
-int sqlite3Fts5StorageContentInsert(
- Fts5Storage *p,
- sqlite3_value **apVal,
- i64 *piRowid
-){
- Fts5Config *pConfig = p->pConfig;
- int rc = SQLITE_OK;
-
- /* Insert the new row into the %_content table. */
- if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
- if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
- *piRowid = sqlite3_value_int64(apVal[1]);
- }else{
- rc = fts5StorageNewRowid(p, piRowid);
- }
- }else{
- sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */
- int i; /* Counter variable */
- rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
- for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
- rc = sqlite3_bind_value(pInsert, i, apVal[i]);
- }
- if( rc==SQLITE_OK ){
- sqlite3_step(pInsert);
- rc = sqlite3_reset(pInsert);
- }
- *piRowid = sqlite3_last_insert_rowid(pConfig->db);
- }
-
- return rc;
-}
-
-/*
-** Insert new entries into the FTS index and %_docsize table.
-*/
-int sqlite3Fts5StorageIndexInsert(
- Fts5Storage *p,
- sqlite3_value **apVal,
- i64 iRowid
-){
- Fts5Config *pConfig = p->pConfig;
- int rc = SQLITE_OK; /* Return code */
- Fts5InsertCtx ctx; /* Tokenization callback context object */
- Fts5Buffer buf; /* Buffer used to build up %_docsize blob */
-
- memset(&buf, 0, sizeof(Fts5Buffer));
- ctx.pStorage = p;
- rc = fts5StorageLoadTotals(p, 1);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
- }
- for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
- ctx.szCol = 0;
- if( pConfig->abUnindexed[ctx.iCol]==0 ){
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_value_text(apVal[ctx.iCol+2]),
- sqlite3_value_bytes(apVal[ctx.iCol+2]),
- (void*)&ctx,
- fts5StorageInsertCallback
- );
- }
- sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
- p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
- }
- p->nTotalRow++;
-
- /* Write the %_docsize record */
- if( rc==SQLITE_OK ){
- rc = fts5StorageInsertDocsize(p, iRowid, &buf);
- }
- sqlite3_free(buf.p);
-
- return rc;
-}
-
-static int fts5StorageCount(Fts5Storage *p, const char *zSuffix, i64 *pnRow){
- Fts5Config *pConfig = p->pConfig;
- char *zSql;
- int rc;
-
- zSql = sqlite3_mprintf("SELECT count(*) FROM %Q.'%q_%s'",
- pConfig->zDb, pConfig->zName, zSuffix
- );
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_stmt *pCnt = 0;
- rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pCnt, 0);
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pCnt) ){
- *pnRow = sqlite3_column_int64(pCnt, 0);
- }
- rc = sqlite3_finalize(pCnt);
- }
- }
-
- sqlite3_free(zSql);
- return rc;
-}
-
-/*
-** Context object used by sqlite3Fts5StorageIntegrity().
-*/
-typedef struct Fts5IntegrityCtx Fts5IntegrityCtx;
-struct Fts5IntegrityCtx {
- i64 iRowid;
- int iCol;
- int szCol;
- u64 cksum;
- Fts5Termset *pTermset;
- Fts5Config *pConfig;
-};
-
-
-/*
-** Tokenization callback used by integrity check.
-*/
-static int fts5StorageIntegrityCallback(
- void *pContext, /* Pointer to Fts5IntegrityCtx object */
- int tflags,
- const char *pToken, /* Buffer containing token */
- int nToken, /* Size of token in bytes */
- int iUnused1, /* Start offset of token */
- int iUnused2 /* End offset of token */
-){
- Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext;
- Fts5Termset *pTermset = pCtx->pTermset;
- int bPresent;
- int ii;
- int rc = SQLITE_OK;
- int iPos;
- int iCol;
-
- UNUSED_PARAM2(iUnused1, iUnused2);
- if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
-
- if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
- pCtx->szCol++;
- }
-
- switch( pCtx->pConfig->eDetail ){
- case FTS5_DETAIL_FULL:
- iPos = pCtx->szCol-1;
- iCol = pCtx->iCol;
- break;
-
- case FTS5_DETAIL_COLUMNS:
- iPos = pCtx->iCol;
- iCol = 0;
- break;
-
- default:
- assert( pCtx->pConfig->eDetail==FTS5_DETAIL_NONE );
- iPos = 0;
- iCol = 0;
- break;
- }
-
- rc = sqlite3Fts5TermsetAdd(pTermset, 0, pToken, nToken, &bPresent);
- if( rc==SQLITE_OK && bPresent==0 ){
- pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
- pCtx->iRowid, iCol, iPos, 0, pToken, nToken
- );
- }
-
- for(ii=0; rc==SQLITE_OK && ii<pCtx->pConfig->nPrefix; ii++){
- const int nChar = pCtx->pConfig->aPrefix[ii];
- int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
- if( nByte ){
- rc = sqlite3Fts5TermsetAdd(pTermset, ii+1, pToken, nByte, &bPresent);
- if( bPresent==0 ){
- pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
- pCtx->iRowid, iCol, iPos, ii+1, pToken, nByte
- );
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Check that the contents of the FTS index match that of the %_content
-** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return
-** some other SQLite error code if an error occurs while attempting to
-** determine this.
-*/
-int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
- Fts5Config *pConfig = p->pConfig;
- int rc; /* Return code */
- int *aColSize; /* Array of size pConfig->nCol */
- i64 *aTotalSize; /* Array of size pConfig->nCol */
- Fts5IntegrityCtx ctx;
- sqlite3_stmt *pScan;
-
- memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
- ctx.pConfig = p->pConfig;
- aTotalSize = (i64*)sqlite3_malloc(pConfig->nCol * (sizeof(int)+sizeof(i64)));
- if( !aTotalSize ) return SQLITE_NOMEM;
- aColSize = (int*)&aTotalSize[pConfig->nCol];
- memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
-
- /* Generate the expected index checksum based on the contents of the
- ** %_content table. This block stores the checksum in ctx.cksum. */
- rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
- if( rc==SQLITE_OK ){
- int rc2;
- while( SQLITE_ROW==sqlite3_step(pScan) ){
- int i;
- ctx.iRowid = sqlite3_column_int64(pScan, 0);
- ctx.szCol = 0;
- if( pConfig->bColumnsize ){
- rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
- }
- if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
- }
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( pConfig->abUnindexed[i] ) continue;
- ctx.iCol = i;
- ctx.szCol = 0;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_column_text(pScan, i+1),
- sqlite3_column_bytes(pScan, i+1),
- (void*)&ctx,
- fts5StorageIntegrityCallback
- );
- }
- if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
- rc = FTS5_CORRUPT;
- }
- aTotalSize[i] += ctx.szCol;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
- }
- }
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
-
- if( rc!=SQLITE_OK ) break;
- }
- rc2 = sqlite3_reset(pScan);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- /* Test that the "totals" (sometimes called "averages") record looks Ok */
- if( rc==SQLITE_OK ){
- int i;
- rc = fts5StorageLoadTotals(p, 0);
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
- }
- }
-
- /* Check that the %_docsize and %_content tables contain the expected
- ** number of rows. */
- if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
- i64 nRow = 0;
- rc = fts5StorageCount(p, "content", &nRow);
- if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
- }
- if( rc==SQLITE_OK && pConfig->bColumnsize ){
- i64 nRow = 0;
- rc = fts5StorageCount(p, "docsize", &nRow);
- if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
- }
-
- /* Pass the expected checksum down to the FTS index module. It will
- ** verify, amongst other things, that it matches the checksum generated by
- ** inspecting the index itself. */
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum);
- }
-
- sqlite3_free(aTotalSize);
- return rc;
-}
-
-/*
-** Obtain an SQLite statement handle that may be used to read data from the
-** %_content table.
-*/
-int sqlite3Fts5StorageStmt(
- Fts5Storage *p,
- int eStmt,
- sqlite3_stmt **pp,
- char **pzErrMsg
-){
- int rc;
- assert( eStmt==FTS5_STMT_SCAN_ASC
- || eStmt==FTS5_STMT_SCAN_DESC
- || eStmt==FTS5_STMT_LOOKUP
- );
- rc = fts5StorageGetStmt(p, eStmt, pp, pzErrMsg);
- if( rc==SQLITE_OK ){
- assert( p->aStmt[eStmt]==*pp );
- p->aStmt[eStmt] = 0;
- }
- return rc;
-}
-
-/*
-** Release an SQLite statement handle obtained via an earlier call to
-** sqlite3Fts5StorageStmt(). The eStmt parameter passed to this function
-** must match that passed to the sqlite3Fts5StorageStmt() call.
-*/
-void sqlite3Fts5StorageStmtRelease(
- Fts5Storage *p,
- int eStmt,
- sqlite3_stmt *pStmt
-){
- assert( eStmt==FTS5_STMT_SCAN_ASC
- || eStmt==FTS5_STMT_SCAN_DESC
- || eStmt==FTS5_STMT_LOOKUP
- );
- if( p->aStmt[eStmt]==0 ){
- sqlite3_reset(pStmt);
- p->aStmt[eStmt] = pStmt;
- }else{
- sqlite3_finalize(pStmt);
- }
-}
-
-static int fts5StorageDecodeSizeArray(
- int *aCol, int nCol, /* Array to populate */
- const u8 *aBlob, int nBlob /* Record to read varints from */
-){
- int i;
- int iOff = 0;
- for(i=0; i<nCol; i++){
- if( iOff>=nBlob ) return 1;
- iOff += fts5GetVarint32(&aBlob[iOff], aCol[i]);
- }
- return (iOff!=nBlob);
-}
-
-/*
-** Argument aCol points to an array of integers containing one entry for
-** each table column. This function reads the %_docsize record for the
-** specified rowid and populates aCol[] with the results.
-**
-** An SQLite error code is returned if an error occurs, or SQLITE_OK
-** otherwise.
-*/
-int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
- int nCol = p->pConfig->nCol; /* Number of user columns in table */
- sqlite3_stmt *pLookup = 0; /* Statement to query %_docsize */
- int rc; /* Return Code */
-
- assert( p->pConfig->bColumnsize );
- rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
- if( rc==SQLITE_OK ){
- int bCorrupt = 1;
- sqlite3_bind_int64(pLookup, 1, iRowid);
- if( SQLITE_ROW==sqlite3_step(pLookup) ){
- const u8 *aBlob = sqlite3_column_blob(pLookup, 0);
- int nBlob = sqlite3_column_bytes(pLookup, 0);
- if( 0==fts5StorageDecodeSizeArray(aCol, nCol, aBlob, nBlob) ){
- bCorrupt = 0;
- }
- }
- rc = sqlite3_reset(pLookup);
- if( bCorrupt && rc==SQLITE_OK ){
- rc = FTS5_CORRUPT;
- }
- }
-
- return rc;
-}
-
-int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){
- int rc = fts5StorageLoadTotals(p, 0);
- if( rc==SQLITE_OK ){
- *pnToken = 0;
- if( iCol<0 ){
- int i;
- for(i=0; i<p->pConfig->nCol; i++){
- *pnToken += p->aTotalSize[i];
- }
- }else if( iCol<p->pConfig->nCol ){
- *pnToken = p->aTotalSize[iCol];
- }else{
- rc = SQLITE_RANGE;
- }
- }
- return rc;
-}
-
-int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
- int rc = fts5StorageLoadTotals(p, 0);
- if( rc==SQLITE_OK ){
- *pnRow = p->nTotalRow;
- }
- return rc;
-}
-
-/*
-** Flush any data currently held in-memory to disk.
-*/
-int sqlite3Fts5StorageSync(Fts5Storage *p){
- int rc = SQLITE_OK;
- i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db);
- if( p->bTotalsValid ){
- rc = fts5StorageSaveTotals(p);
- p->bTotalsValid = 0;
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexSync(p->pIndex);
- }
- sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid);
- return rc;
-}
-
-int sqlite3Fts5StorageRollback(Fts5Storage *p){
- p->bTotalsValid = 0;
- return sqlite3Fts5IndexRollback(p->pIndex);
-}
-
-int sqlite3Fts5StorageConfigValue(
- Fts5Storage *p,
- const char *z,
- sqlite3_value *pVal,
- int iVal
-){
- sqlite3_stmt *pReplace = 0;
- int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_CONFIG, &pReplace, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_text(pReplace, 1, z, -1, SQLITE_STATIC);
- if( pVal ){
- sqlite3_bind_value(pReplace, 2, pVal);
- }else{
- sqlite3_bind_int(pReplace, 2, iVal);
- }
- sqlite3_step(pReplace);
- rc = sqlite3_reset(pReplace);
- sqlite3_bind_null(pReplace, 1);
- }
- if( rc==SQLITE_OK && pVal ){
- int iNew = p->pConfig->iCookie + 1;
- rc = sqlite3Fts5IndexSetCookie(p->pIndex, iNew);
- if( rc==SQLITE_OK ){
- p->pConfig->iCookie = iNew;
- }
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_tcl.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_tcl.c
deleted file mode 100644
index f33dcae0335..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_tcl.c
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*
-** 2014 Dec 01
-**
-** 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.
-**
-******************************************************************************
-**
-*/
-
-
-#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-#ifdef SQLITE_ENABLE_FTS5
-
-#include "fts5.h"
-#include <string.h>
-#include <assert.h>
-
-extern int sqlite3_fts5_may_be_corrupt;
-extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
-extern int sqlite3Fts5TestRegisterTok(sqlite3*, fts5_api*);
-
-/*************************************************************************
-** This is a copy of the first part of the SqliteDb structure in
-** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
-** can extract the sqlite3* pointer from an existing Tcl SQLite
-** connection.
-*/
-
-extern const char *sqlite3ErrName(int);
-
-struct SqliteDb {
- sqlite3 *db;
-};
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-static int f5tDbPointer(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **ppDb){
- struct SqliteDb *p;
- Tcl_CmdInfo cmdInfo;
- char *z = Tcl_GetString(pObj);
- if( Tcl_GetCommandInfo(interp, z, &cmdInfo) ){
- p = (struct SqliteDb*)cmdInfo.objClientData;
- *ppDb = p->db;
- return TCL_OK;
- }
- return TCL_ERROR;
-}
-
-/* End of code that accesses the SqliteDb struct.
-**************************************************************************/
-
-static int f5tResultToErrorCode(const char *zRes){
- struct ErrorCode {
- int rc;
- const char *zError;
- } aErr[] = {
- { SQLITE_DONE, "SQLITE_DONE" },
- { SQLITE_ERROR, "SQLITE_ERROR" },
- { SQLITE_OK, "SQLITE_OK" },
- { SQLITE_OK, "" },
- };
- int i;
-
- for(i=0; i<sizeof(aErr)/sizeof(aErr[0]); i++){
- if( 0==sqlite3_stricmp(zRes, aErr[i].zError) ){
- return aErr[i].rc;
- }
- }
-
- return SQLITE_ERROR;
-}
-
-static int SQLITE_TCLAPI f5tDbAndApi(
- Tcl_Interp *interp,
- Tcl_Obj *pObj,
- sqlite3 **ppDb,
- fts5_api **ppApi
-){
- sqlite3 *db = 0;
- int rc = f5tDbPointer(interp, pObj, &db);
- if( rc!=TCL_OK ){
- return TCL_ERROR;
- }else{
- sqlite3_stmt *pStmt = 0;
- fts5_api *pApi = 0;
-
- rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
- sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
- sqlite3_step(pStmt);
-
- if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
- Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
-
- *ppDb = db;
- *ppApi = pApi;
- }
-
- return TCL_OK;
-}
-
-typedef struct F5tFunction F5tFunction;
-struct F5tFunction {
- Tcl_Interp *interp;
- Tcl_Obj *pScript;
-};
-
-typedef struct F5tApi F5tApi;
-struct F5tApi {
- const Fts5ExtensionApi *pApi;
- Fts5Context *pFts;
-};
-
-/*
-** An object of this type is used with the xSetAuxdata() and xGetAuxdata()
-** API test wrappers. The tcl interface allows a single tcl value to be
-** saved using xSetAuxdata(). Instead of simply storing a pointer to the
-** tcl object, the code in this file wraps it in an sqlite3_malloc'd
-** instance of the following struct so that if the destructor is not
-** correctly invoked it will be reported as an SQLite memory leak.
-*/
-typedef struct F5tAuxData F5tAuxData;
-struct F5tAuxData {
- Tcl_Obj *pObj;
-};
-
-static int xTokenizeCb(
- void *pCtx,
- int tflags,
- const char *zToken, int nToken,
- int iStart, int iEnd
-){
- F5tFunction *p = (F5tFunction*)pCtx;
- Tcl_Obj *pEval = Tcl_DuplicateObj(p->pScript);
- int rc;
-
- Tcl_IncrRefCount(pEval);
- Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zToken, nToken));
- Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(iStart));
- Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(iEnd));
-
- rc = Tcl_EvalObjEx(p->interp, pEval, 0);
- Tcl_DecrRefCount(pEval);
- if( rc==TCL_OK ){
- rc = f5tResultToErrorCode(Tcl_GetStringResult(p->interp));
- }
-
- return rc;
-}
-
-static int SQLITE_TCLAPI xF5tApi(void*, Tcl_Interp*, int, Tcl_Obj *CONST []);
-
-static int xQueryPhraseCb(
- const Fts5ExtensionApi *pApi,
- Fts5Context *pFts,
- void *pCtx
-){
- F5tFunction *p = (F5tFunction*)pCtx;
- static sqlite3_int64 iCmd = 0;
- Tcl_Obj *pEval;
- int rc;
-
- char zCmd[64];
- F5tApi sApi;
-
- sApi.pApi = pApi;
- sApi.pFts = pFts;
- sprintf(zCmd, "f5t_2_%lld", iCmd++);
- Tcl_CreateObjCommand(p->interp, zCmd, xF5tApi, &sApi, 0);
-
- pEval = Tcl_DuplicateObj(p->pScript);
- Tcl_IncrRefCount(pEval);
- Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zCmd, -1));
- rc = Tcl_EvalObjEx(p->interp, pEval, 0);
- Tcl_DecrRefCount(pEval);
- Tcl_DeleteCommand(p->interp, zCmd);
-
- if( rc==TCL_OK ){
- rc = f5tResultToErrorCode(Tcl_GetStringResult(p->interp));
- }
-
- return rc;
-}
-
-static void xSetAuxdataDestructor(void *p){
- F5tAuxData *pData = (F5tAuxData*)p;
- Tcl_DecrRefCount(pData->pObj);
- sqlite3_free(pData);
-}
-
-/*
-** api sub-command...
-**
-** Description...
-*/
-static int SQLITE_TCLAPI xF5tApi(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- struct Sub {
- const char *zName;
- int nArg;
- const char *zMsg;
- } aSub[] = {
- { "xColumnCount", 0, "" }, /* 0 */
- { "xRowCount", 0, "" }, /* 1 */
- { "xColumnTotalSize", 1, "COL" }, /* 2 */
- { "xTokenize", 2, "TEXT SCRIPT" }, /* 3 */
- { "xPhraseCount", 0, "" }, /* 4 */
- { "xPhraseSize", 1, "PHRASE" }, /* 5 */
- { "xInstCount", 0, "" }, /* 6 */
- { "xInst", 1, "IDX" }, /* 7 */
- { "xRowid", 0, "" }, /* 8 */
- { "xColumnText", 1, "COL" }, /* 9 */
- { "xColumnSize", 1, "COL" }, /* 10 */
- { "xQueryPhrase", 2, "PHRASE SCRIPT" }, /* 11 */
- { "xSetAuxdata", 1, "VALUE" }, /* 12 */
- { "xGetAuxdata", 1, "CLEAR" }, /* 13 */
- { "xSetAuxdataInt", 1, "INTEGER" }, /* 14 */
- { "xGetAuxdataInt", 1, "CLEAR" }, /* 15 */
- { "xPhraseForeach", 4, "IPHRASE COLVAR OFFVAR SCRIPT" }, /* 16 */
- { "xPhraseColumnForeach", 3, "IPHRASE COLVAR SCRIPT" }, /* 17 */
- { 0, 0, 0}
- };
-
- int rc;
- int iSub = 0;
- F5tApi *p = (F5tApi*)clientData;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND");
- return TCL_ERROR;
- }
-
- rc = Tcl_GetIndexFromObjStruct(
- interp, objv[1], aSub, sizeof(aSub[0]), "SUB-COMMAND", 0, &iSub
- );
- if( rc!=TCL_OK ) return rc;
- if( aSub[iSub].nArg!=objc-2 ){
- Tcl_WrongNumArgs(interp, 1, objv, aSub[iSub].zMsg);
- return TCL_ERROR;
- }
-
-#define CASE(i,str) case i: assert( strcmp(aSub[i].zName, str)==0 );
- switch( iSub ){
- CASE(0, "xColumnCount") {
- int nCol;
- nCol = p->pApi->xColumnCount(p->pFts);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nCol));
- }
- break;
- }
- CASE(1, "xRowCount") {
- sqlite3_int64 nRow;
- rc = p->pApi->xRowCount(p->pFts, &nRow);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nRow));
- }
- break;
- }
- CASE(2, "xColumnTotalSize") {
- int iCol;
- sqlite3_int64 nSize;
- if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ) return TCL_ERROR;
- rc = p->pApi->xColumnTotalSize(p->pFts, iCol, &nSize);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize));
- }
- break;
- }
- CASE(3, "xTokenize") {
- int nText;
- char *zText = Tcl_GetStringFromObj(objv[2], &nText);
- F5tFunction ctx;
- ctx.interp = interp;
- ctx.pScript = objv[3];
- rc = p->pApi->xTokenize(p->pFts, zText, nText, &ctx, xTokenizeCb);
- if( rc==SQLITE_OK ){
- Tcl_ResetResult(interp);
- }
- return rc;
- }
- CASE(4, "xPhraseCount") {
- int nPhrase;
- nPhrase = p->pApi->xPhraseCount(p->pFts);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nPhrase));
- }
- break;
- }
- CASE(5, "xPhraseSize") {
- int iPhrase;
- int sz;
- if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ){
- return TCL_ERROR;
- }
- sz = p->pApi->xPhraseSize(p->pFts, iPhrase);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sz));
- }
- break;
- }
- CASE(6, "xInstCount") {
- int nInst;
- rc = p->pApi->xInstCount(p->pFts, &nInst);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nInst));
- }
- break;
- }
- CASE(7, "xInst") {
- int iIdx, ip, ic, io;
- if( Tcl_GetIntFromObj(interp, objv[2], &iIdx) ){
- return TCL_ERROR;
- }
- rc = p->pApi->xInst(p->pFts, iIdx, &ip, &ic, &io);
- if( rc==SQLITE_OK ){
- Tcl_Obj *pList = Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, pList, Tcl_NewIntObj(ip));
- Tcl_ListObjAppendElement(interp, pList, Tcl_NewIntObj(ic));
- Tcl_ListObjAppendElement(interp, pList, Tcl_NewIntObj(io));
- Tcl_SetObjResult(interp, pList);
- }
- break;
- }
- CASE(8, "xRowid") {
- sqlite3_int64 iRowid = p->pApi->xRowid(p->pFts);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iRowid));
- break;
- }
- CASE(9, "xColumnText") {
- const char *z = 0;
- int n = 0;
- int iCol;
- if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ){
- return TCL_ERROR;
- }
- rc = p->pApi->xColumnText(p->pFts, iCol, &z, &n);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(z, n));
- }
- break;
- }
- CASE(10, "xColumnSize") {
- int n = 0;
- int iCol;
- if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ){
- return TCL_ERROR;
- }
- rc = p->pApi->xColumnSize(p->pFts, iCol, &n);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
- }
- break;
- }
- CASE(11, "xQueryPhrase") {
- int iPhrase;
- F5tFunction ctx;
- if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ){
- return TCL_ERROR;
- }
- ctx.interp = interp;
- ctx.pScript = objv[3];
- rc = p->pApi->xQueryPhrase(p->pFts, iPhrase, &ctx, xQueryPhraseCb);
- if( rc==SQLITE_OK ){
- Tcl_ResetResult(interp);
- }
- break;
- }
- CASE(12, "xSetAuxdata") {
- F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc(sizeof(F5tAuxData));
- if( pData==0 ){
- Tcl_AppendResult(interp, "out of memory", 0);
- return TCL_ERROR;
- }
- pData->pObj = objv[2];
- Tcl_IncrRefCount(pData->pObj);
- rc = p->pApi->xSetAuxdata(p->pFts, pData, xSetAuxdataDestructor);
- break;
- }
- CASE(13, "xGetAuxdata") {
- F5tAuxData *pData;
- int bClear;
- if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ){
- return TCL_ERROR;
- }
- pData = (F5tAuxData*)p->pApi->xGetAuxdata(p->pFts, bClear);
- if( pData==0 ){
- Tcl_ResetResult(interp);
- }else{
- Tcl_SetObjResult(interp, pData->pObj);
- if( bClear ){
- xSetAuxdataDestructor((void*)pData);
- }
- }
- break;
- }
-
- /* These two - xSetAuxdataInt and xGetAuxdataInt - are similar to the
- ** xSetAuxdata and xGetAuxdata methods implemented above. The difference
- ** is that they may only save an integer value as auxiliary data, and
- ** do not specify a destructor function. */
- CASE(14, "xSetAuxdataInt") {
- int iVal;
- if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ) return TCL_ERROR;
- rc = p->pApi->xSetAuxdata(p->pFts, (void*)((char*)0 + iVal), 0);
- break;
- }
- CASE(15, "xGetAuxdataInt") {
- int iVal;
- int bClear;
- if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ) return TCL_ERROR;
- iVal = (int)((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
- break;
- }
-
- CASE(16, "xPhraseForeach") {
- int iPhrase;
- int iCol;
- int iOff;
- const char *zColvar;
- const char *zOffvar;
- Tcl_Obj *pScript = objv[5];
- Fts5PhraseIter iter;
-
- if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ) return TCL_ERROR;
- zColvar = Tcl_GetString(objv[3]);
- zOffvar = Tcl_GetString(objv[4]);
-
- rc = p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- for( ;iCol>=0; p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff) ){
- Tcl_SetVar2Ex(interp, zColvar, 0, Tcl_NewIntObj(iCol), 0);
- Tcl_SetVar2Ex(interp, zOffvar, 0, Tcl_NewIntObj(iOff), 0);
- rc = Tcl_EvalObjEx(interp, pScript, 0);
- if( rc==TCL_CONTINUE ) rc = TCL_OK;
- if( rc!=TCL_OK ){
- if( rc==TCL_BREAK ) rc = TCL_OK;
- break;
- }
- }
-
- break;
- }
-
- CASE(17, "xPhraseColumnForeach") {
- int iPhrase;
- int iCol;
- const char *zColvar;
- Tcl_Obj *pScript = objv[4];
- Fts5PhraseIter iter;
-
- if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ) return TCL_ERROR;
- zColvar = Tcl_GetString(objv[3]);
-
- rc = p->pApi->xPhraseFirstColumn(p->pFts, iPhrase, &iter, &iCol);
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_ERROR;
- }
- for( ; iCol>=0; p->pApi->xPhraseNextColumn(p->pFts, &iter, &iCol)){
- Tcl_SetVar2Ex(interp, zColvar, 0, Tcl_NewIntObj(iCol), 0);
- rc = Tcl_EvalObjEx(interp, pScript, 0);
- if( rc==TCL_CONTINUE ) rc = TCL_OK;
- if( rc!=TCL_OK ){
- if( rc==TCL_BREAK ) rc = TCL_OK;
- break;
- }
- }
-
- break;
- }
-
- default:
- assert( 0 );
- break;
- }
-#undef CASE
-
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-static void xF5tFunction(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- sqlite3_context *pCtx, /* Context for returning result/error */
- int nVal, /* Number of values in apVal[] array */
- sqlite3_value **apVal /* Array of trailing arguments */
-){
- F5tFunction *p = (F5tFunction*)pApi->xUserData(pFts);
- Tcl_Obj *pEval; /* Script to evaluate */
- int i;
- int rc;
-
- static sqlite3_int64 iCmd = 0;
- char zCmd[64];
- F5tApi sApi;
- sApi.pApi = pApi;
- sApi.pFts = pFts;
-
- sprintf(zCmd, "f5t_%lld", iCmd++);
- Tcl_CreateObjCommand(p->interp, zCmd, xF5tApi, &sApi, 0);
- pEval = Tcl_DuplicateObj(p->pScript);
- Tcl_IncrRefCount(pEval);
- Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zCmd, -1));
-
- for(i=0; i<nVal; i++){
- Tcl_Obj *pObj = 0;
- switch( sqlite3_value_type(apVal[i]) ){
- case SQLITE_TEXT:
- pObj = Tcl_NewStringObj((const char*)sqlite3_value_text(apVal[i]), -1);
- break;
- case SQLITE_BLOB:
- pObj = Tcl_NewByteArrayObj(
- sqlite3_value_blob(apVal[i]), sqlite3_value_bytes(apVal[i])
- );
- break;
- case SQLITE_INTEGER:
- pObj = Tcl_NewWideIntObj(sqlite3_value_int64(apVal[i]));
- break;
- case SQLITE_FLOAT:
- pObj = Tcl_NewDoubleObj(sqlite3_value_double(apVal[i]));
- break;
- default:
- pObj = Tcl_NewObj();
- break;
- }
- Tcl_ListObjAppendElement(p->interp, pEval, pObj);
- }
-
- rc = Tcl_EvalObjEx(p->interp, pEval, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(pEval);
- Tcl_DeleteCommand(p->interp, zCmd);
-
- if( rc!=TCL_OK ){
- sqlite3_result_error(pCtx, Tcl_GetStringResult(p->interp), -1);
- }else{
- Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
- int n;
- const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
- char c = zType[0];
- if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
- /* Only return a BLOB type if the Tcl variable is a bytearray and
- ** has no string representation. */
- unsigned char *data = Tcl_GetByteArrayFromObj(pVar, &n);
- sqlite3_result_blob(pCtx, data, n, SQLITE_TRANSIENT);
- }else if( c=='b' && strcmp(zType,"boolean")==0 ){
- Tcl_GetIntFromObj(0, pVar, &n);
- sqlite3_result_int(pCtx, n);
- }else if( c=='d' && strcmp(zType,"double")==0 ){
- double r;
- Tcl_GetDoubleFromObj(0, pVar, &r);
- sqlite3_result_double(pCtx, r);
- }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
- (c=='i' && strcmp(zType,"int")==0) ){
- Tcl_WideInt v;
- Tcl_GetWideIntFromObj(0, pVar, &v);
- sqlite3_result_int64(pCtx, v);
- }else{
- unsigned char *data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
- sqlite3_result_text(pCtx, (char *)data, n, SQLITE_TRANSIENT);
- }
- }
-}
-
-static void xF5tDestroy(void *pCtx){
- F5tFunction *p = (F5tFunction*)pCtx;
- Tcl_DecrRefCount(p->pScript);
- ckfree((char *)p);
-}
-
-/*
-** sqlite3_fts5_create_function DB NAME SCRIPT
-**
-** Description...
-*/
-static int SQLITE_TCLAPI f5tCreateFunction(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- char *zName;
- Tcl_Obj *pScript;
- sqlite3 *db = 0;
- fts5_api *pApi = 0;
- F5tFunction *pCtx = 0;
- int rc;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB NAME SCRIPT");
- return TCL_ERROR;
- }
- if( f5tDbAndApi(interp, objv[1], &db, &pApi) ) return TCL_ERROR;
-
- zName = Tcl_GetString(objv[2]);
- pScript = objv[3];
- pCtx = (F5tFunction*)ckalloc(sizeof(F5tFunction));
- pCtx->interp = interp;
- pCtx->pScript = pScript;
- Tcl_IncrRefCount(pScript);
-
- rc = pApi->xCreateFunction(
- pApi, zName, (void*)pCtx, xF5tFunction, xF5tDestroy
- );
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-typedef struct F5tTokenizeCtx F5tTokenizeCtx;
-struct F5tTokenizeCtx {
- Tcl_Obj *pRet;
- int bSubst;
- const char *zInput;
-};
-
-static int xTokenizeCb2(
- void *pCtx,
- int tflags,
- const char *zToken, int nToken,
- int iStart, int iEnd
-){
- F5tTokenizeCtx *p = (F5tTokenizeCtx*)pCtx;
- if( p->bSubst ){
- Tcl_ListObjAppendElement(0, p->pRet, Tcl_NewStringObj(zToken, nToken));
- Tcl_ListObjAppendElement(
- 0, p->pRet, Tcl_NewStringObj(&p->zInput[iStart], iEnd-iStart)
- );
- }else{
- Tcl_ListObjAppendElement(0, p->pRet, Tcl_NewStringObj(zToken, nToken));
- Tcl_ListObjAppendElement(0, p->pRet, Tcl_NewIntObj(iStart));
- Tcl_ListObjAppendElement(0, p->pRet, Tcl_NewIntObj(iEnd));
- }
- return SQLITE_OK;
-}
-
-
-/*
-** sqlite3_fts5_tokenize DB TOKENIZER TEXT
-**
-** Description...
-*/
-static int SQLITE_TCLAPI f5tTokenize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- char *zText;
- int nText;
- sqlite3 *db = 0;
- fts5_api *pApi = 0;
- Fts5Tokenizer *pTok = 0;
- fts5_tokenizer tokenizer;
- Tcl_Obj *pRet = 0;
- void *pUserdata;
- int rc;
-
- int nArg;
- const char **azArg;
- F5tTokenizeCtx ctx;
-
- if( objc!=4 && objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?-subst? DB NAME TEXT");
- return TCL_ERROR;
- }
- if( objc==5 ){
- char *zOpt = Tcl_GetString(objv[1]);
- if( strcmp("-subst", zOpt) ){
- Tcl_AppendResult(interp, "unrecognized option: ", zOpt, 0);
- return TCL_ERROR;
- }
- }
- if( f5tDbAndApi(interp, objv[objc-3], &db, &pApi) ) return TCL_ERROR;
- if( Tcl_SplitList(interp, Tcl_GetString(objv[objc-2]), &nArg, &azArg) ){
- return TCL_ERROR;
- }
- if( nArg==0 ){
- Tcl_AppendResult(interp, "no such tokenizer: ", 0);
- Tcl_Free((void*)azArg);
- return TCL_ERROR;
- }
- zText = Tcl_GetStringFromObj(objv[objc-1], &nText);
-
- rc = pApi->xFindTokenizer(pApi, azArg[0], &pUserdata, &tokenizer);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], 0);
- return TCL_ERROR;
- }
-
- rc = tokenizer.xCreate(pUserdata, &azArg[1], nArg-1, &pTok);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "error in tokenizer.xCreate()", 0);
- return TCL_ERROR;
- }
-
- pRet = Tcl_NewObj();
- Tcl_IncrRefCount(pRet);
- ctx.bSubst = (objc==5);
- ctx.pRet = pRet;
- ctx.zInput = zText;
- rc = tokenizer.xTokenize(
- pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, zText, nText, xTokenizeCb2
- );
- tokenizer.xDelete(pTok);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", 0);
- Tcl_DecrRefCount(pRet);
- return TCL_ERROR;
- }
-
-
- Tcl_Free((void*)azArg);
- Tcl_SetObjResult(interp, pRet);
- Tcl_DecrRefCount(pRet);
- return TCL_OK;
-}
-
-/*************************************************************************
-** Start of tokenizer wrapper.
-*/
-
-typedef struct F5tTokenizerContext F5tTokenizerContext;
-typedef struct F5tTokenizerCb F5tTokenizerCb;
-typedef struct F5tTokenizerModule F5tTokenizerModule;
-typedef struct F5tTokenizerInstance F5tTokenizerInstance;
-
-struct F5tTokenizerContext {
- void *pCtx;
- int (*xToken)(void*, int, const char*, int, int, int);
-};
-
-struct F5tTokenizerModule {
- Tcl_Interp *interp;
- Tcl_Obj *pScript;
- F5tTokenizerContext *pContext;
-};
-
-struct F5tTokenizerInstance {
- Tcl_Interp *interp;
- Tcl_Obj *pScript;
- F5tTokenizerContext *pContext;
-};
-
-static int f5tTokenizerCreate(
- void *pCtx,
- const char **azArg,
- int nArg,
- Fts5Tokenizer **ppOut
-){
- F5tTokenizerModule *pMod = (F5tTokenizerModule*)pCtx;
- Tcl_Obj *pEval;
- int rc = TCL_OK;
- int i;
-
- pEval = Tcl_DuplicateObj(pMod->pScript);
- Tcl_IncrRefCount(pEval);
- for(i=0; rc==TCL_OK && i<nArg; i++){
- Tcl_Obj *pObj = Tcl_NewStringObj(azArg[i], -1);
- rc = Tcl_ListObjAppendElement(pMod->interp, pEval, pObj);
- }
-
- if( rc==TCL_OK ){
- rc = Tcl_EvalObjEx(pMod->interp, pEval, TCL_GLOBAL_ONLY);
- }
- Tcl_DecrRefCount(pEval);
-
- if( rc==TCL_OK ){
- F5tTokenizerInstance *pInst;
- pInst = (F5tTokenizerInstance*)ckalloc(sizeof(F5tTokenizerInstance));
- memset(pInst, 0, sizeof(F5tTokenizerInstance));
- pInst->interp = pMod->interp;
- pInst->pScript = Tcl_GetObjResult(pMod->interp);
- pInst->pContext = pMod->pContext;
- Tcl_IncrRefCount(pInst->pScript);
- *ppOut = (Fts5Tokenizer*)pInst;
- }
-
- return rc;
-}
-
-
-static void f5tTokenizerDelete(Fts5Tokenizer *p){
- F5tTokenizerInstance *pInst = (F5tTokenizerInstance*)p;
- Tcl_DecrRefCount(pInst->pScript);
- ckfree((char *)pInst);
-}
-
-static int f5tTokenizerTokenize(
- Fts5Tokenizer *p,
- void *pCtx,
- int flags,
- const char *pText, int nText,
- int (*xToken)(void*, int, const char*, int, int, int)
-){
- F5tTokenizerInstance *pInst = (F5tTokenizerInstance*)p;
- void *pOldCtx;
- int (*xOldToken)(void*, int, const char*, int, int, int);
- Tcl_Obj *pEval;
- int rc;
- const char *zFlags;
-
- pOldCtx = pInst->pContext->pCtx;
- xOldToken = pInst->pContext->xToken;
-
- pInst->pContext->pCtx = pCtx;
- pInst->pContext->xToken = xToken;
-
- assert(
- flags==FTS5_TOKENIZE_DOCUMENT
- || flags==FTS5_TOKENIZE_AUX
- || flags==FTS5_TOKENIZE_QUERY
- || flags==(FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX)
- );
- pEval = Tcl_DuplicateObj(pInst->pScript);
- Tcl_IncrRefCount(pEval);
- switch( flags ){
- case FTS5_TOKENIZE_DOCUMENT:
- zFlags = "document";
- break;
- case FTS5_TOKENIZE_AUX:
- zFlags = "aux";
- break;
- case FTS5_TOKENIZE_QUERY:
- zFlags = "query";
- break;
- case (FTS5_TOKENIZE_PREFIX | FTS5_TOKENIZE_QUERY):
- zFlags = "prefixquery";
- break;
- default:
- assert( 0 );
- zFlags = "invalid";
- break;
- }
-
- Tcl_ListObjAppendElement(pInst->interp, pEval, Tcl_NewStringObj(zFlags, -1));
- Tcl_ListObjAppendElement(pInst->interp, pEval, Tcl_NewStringObj(pText,nText));
- rc = Tcl_EvalObjEx(pInst->interp, pEval, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(pEval);
-
- pInst->pContext->pCtx = pOldCtx;
- pInst->pContext->xToken = xOldToken;
- return rc;
-}
-
-/*
-** sqlite3_fts5_token ?-colocated? TEXT START END
-*/
-static int SQLITE_TCLAPI f5tTokenizerReturn(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- F5tTokenizerContext *p = (F5tTokenizerContext*)clientData;
- int iStart;
- int iEnd;
- int nToken;
- int tflags = 0;
- char *zToken;
- int rc;
-
- if( objc==5 ){
- int nArg;
- char *zArg = Tcl_GetStringFromObj(objv[1], &nArg);
- if( nArg<=10 && nArg>=2 && memcmp("-colocated", zArg, nArg)==0 ){
- tflags |= FTS5_TOKEN_COLOCATED;
- }else{
- goto usage;
- }
- }else if( objc!=4 ){
- goto usage;
- }
-
- zToken = Tcl_GetStringFromObj(objv[objc-3], &nToken);
- if( Tcl_GetIntFromObj(interp, objv[objc-2], &iStart)
- || Tcl_GetIntFromObj(interp, objv[objc-1], &iEnd)
- ){
- return TCL_ERROR;
- }
-
- if( p->xToken==0 ){
- Tcl_AppendResult(interp,
- "sqlite3_fts5_token may only be used by tokenizer callback", 0
- );
- return TCL_ERROR;
- }
-
- rc = p->xToken(p->pCtx, tflags, zToken, nToken, iStart, iEnd);
- Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
- return rc==SQLITE_OK ? TCL_OK : TCL_ERROR;
-
- usage:
- Tcl_WrongNumArgs(interp, 1, objv, "?-colocated? TEXT START END");
- return TCL_ERROR;
-}
-
-static void f5tDelTokenizer(void *pCtx){
- F5tTokenizerModule *pMod = (F5tTokenizerModule*)pCtx;
- Tcl_DecrRefCount(pMod->pScript);
- ckfree((char *)pMod);
-}
-
-/*
-** sqlite3_fts5_create_tokenizer DB NAME SCRIPT
-**
-** Register a tokenizer named NAME implemented by script SCRIPT. When
-** a tokenizer instance is created (fts5_tokenizer.xCreate), any tokenizer
-** arguments are appended to SCRIPT and the result executed.
-**
-** The value returned by (SCRIPT + args) is itself a tcl script. This
-** script - call it SCRIPT2 - is executed to tokenize text using the
-** tokenizer instance "returned" by SCRIPT. Specifically, to tokenize
-** text SCRIPT2 is invoked with a single argument appended to it - the
-** text to tokenize.
-**
-** SCRIPT2 should invoke the [sqlite3_fts5_token] command once for each
-** token within the tokenized text.
-*/
-static int SQLITE_TCLAPI f5tCreateTokenizer(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- F5tTokenizerContext *pContext = (F5tTokenizerContext*)clientData;
- sqlite3 *db;
- fts5_api *pApi;
- char *zName;
- Tcl_Obj *pScript;
- fts5_tokenizer t;
- F5tTokenizerModule *pMod;
- int rc;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB NAME SCRIPT");
- return TCL_ERROR;
- }
- if( f5tDbAndApi(interp, objv[1], &db, &pApi) ){
- return TCL_ERROR;
- }
- zName = Tcl_GetString(objv[2]);
- pScript = objv[3];
-
- t.xCreate = f5tTokenizerCreate;
- t.xTokenize = f5tTokenizerTokenize;
- t.xDelete = f5tTokenizerDelete;
-
- pMod = (F5tTokenizerModule*)ckalloc(sizeof(F5tTokenizerModule));
- pMod->interp = interp;
- pMod->pScript = pScript;
- pMod->pContext = pContext;
- Tcl_IncrRefCount(pScript);
- rc = pApi->xCreateTokenizer(pApi, zName, (void*)pMod, &t, f5tDelTokenizer);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "error in fts5_api.xCreateTokenizer()", 0);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-static void SQLITE_TCLAPI xF5tFree(ClientData clientData){
- ckfree(clientData);
-}
-
-/*
-** sqlite3_fts5_may_be_corrupt BOOLEAN
-**
-** Set or clear the global "may-be-corrupt" flag. Return the old value.
-*/
-static int SQLITE_TCLAPI f5tMayBeCorrupt(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int bOld = sqlite3_fts5_may_be_corrupt;
-
- if( objc!=2 && objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
- return TCL_ERROR;
- }
- if( objc==2 ){
- int bNew;
- if( Tcl_GetBooleanFromObj(interp, objv[1], &bNew) ) return TCL_ERROR;
- sqlite3_fts5_may_be_corrupt = bNew;
- }
-
- Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
- return TCL_OK;
-}
-
-
-static unsigned int f5t_fts5HashKey(int nSlot, const char *p, int n){
- int i;
- unsigned int h = 13;
- for(i=n-1; i>=0; i--){
- h = (h << 3) ^ h ^ p[i];
- }
- return (h % nSlot);
-}
-
-static int SQLITE_TCLAPI f5tTokenHash(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- char *z;
- int n;
- unsigned int iVal;
- int nSlot;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NSLOT TOKEN");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &nSlot) ){
- return TCL_ERROR;
- }
- z = Tcl_GetStringFromObj(objv[2], &n);
-
- iVal = f5t_fts5HashKey(nSlot, z, n);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI f5tRegisterMatchinfo(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db = 0;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( f5tDbPointer(interp, objv[1], &db) ){
- return TCL_ERROR;
- }
-
- rc = sqlite3Fts5TestRegisterMatchinfo(db);
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI f5tRegisterTok(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db = 0;
- fts5_api *pApi = 0;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( f5tDbAndApi(interp, objv[1], &db, &pApi) ){
- return TCL_ERROR;
- }
-
- rc = sqlite3Fts5TestRegisterTok(db, pApi);
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Entry point.
-*/
-int Fts5tcl_Init(Tcl_Interp *interp){
- static struct Cmd {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- int bTokenizeCtx;
- } aCmd[] = {
- { "sqlite3_fts5_create_tokenizer", f5tCreateTokenizer, 1 },
- { "sqlite3_fts5_token", f5tTokenizerReturn, 1 },
- { "sqlite3_fts5_tokenize", f5tTokenize, 0 },
- { "sqlite3_fts5_create_function", f5tCreateFunction, 0 },
- { "sqlite3_fts5_may_be_corrupt", f5tMayBeCorrupt, 0 },
- { "sqlite3_fts5_token_hash", f5tTokenHash, 0 },
- { "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 },
- { "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 }
- };
- int i;
- F5tTokenizerContext *pContext;
-
- pContext = (F5tTokenizerContext*)ckalloc(sizeof(F5tTokenizerContext));
- memset(pContext, 0, sizeof(*pContext));
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- struct Cmd *p = &aCmd[i];
- void *pCtx = 0;
- if( p->bTokenizeCtx ) pCtx = (void*)pContext;
- Tcl_CreateObjCommand(interp, p->zName, p->xProc, pCtx, (i ? 0 : xF5tFree));
- }
-
- return TCL_OK;
-}
-#else /* SQLITE_ENABLE_FTS5 */
-int Fts5tcl_Init(Tcl_Interp *interp){
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_FTS5 */
-#endif /* SQLITE_TEST */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_test_mi.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_test_mi.c
deleted file mode 100644
index 481d09b2cae..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_test_mi.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
-** 2015 Aug 04
-**
-** 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 contains test code only, it is not included in release
-** versions of FTS5. It contains the implementation of an FTS5 auxiliary
-** function very similar to the FTS4 function matchinfo():
-**
-** https://www.sqlite.org/fts3.html#matchinfo
-**
-** Known differences are that:
-**
-** 1) this function uses the FTS5 definition of "matchable phrase", which
-** excludes any phrases that are part of an expression sub-tree that
-** does not match the current row. This comes up for MATCH queries
-** such as:
-**
-** "a OR (b AND c)"
-**
-** In FTS4, if a single row contains instances of tokens "a" and "c",
-** but not "b", all instances of "c" are considered matches. In FTS5,
-** they are not (as the "b AND c" sub-tree does not match the current
-** row.
-**
-** 2) For the values returned by 'x' that apply to all rows of the table,
-** NEAR constraints are not considered. But for the number of hits in
-** the current row, they are.
-**
-** This file exports a single function that may be called to register the
-** matchinfo() implementation with a database handle:
-**
-** int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db);
-*/
-
-
-#ifdef SQLITE_ENABLE_FTS5
-
-#include "fts5.h"
-#include <assert.h>
-#include <string.h>
-
-typedef struct Fts5MatchinfoCtx Fts5MatchinfoCtx;
-
-#ifndef SQLITE_AMALGAMATION
-typedef unsigned int u32;
-#endif
-
-struct Fts5MatchinfoCtx {
- int nCol; /* Number of cols in FTS5 table */
- int nPhrase; /* Number of phrases in FTS5 query */
- char *zArg; /* nul-term'd copy of 2nd arg */
- int nRet; /* Number of elements in aRet[] */
- u32 *aRet; /* Array of 32-bit unsigned ints to return */
-};
-
-
-
-/*
-** Return a pointer to the fts5_api pointer for database connection db.
-** If an error occurs, return NULL and leave an error in the database
-** handle (accessible using sqlite3_errcode()/errmsg()).
-*/
-static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
- sqlite3_stmt *pStmt = 0;
- int rc;
-
- *ppApi = 0;
- rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr", 0);
- (void)sqlite3_step(pStmt);
- rc = sqlite3_finalize(pStmt);
- }
-
- return rc;
-}
-
-
-/*
-** Argument f should be a flag accepted by matchinfo() (a valid character
-** in the string passed as the second argument). If it is not, -1 is
-** returned. Otherwise, if f is a valid matchinfo flag, the value returned
-** is the number of 32-bit integers added to the output array if the
-** table has nCol columns and the query nPhrase phrases.
-*/
-static int fts5MatchinfoFlagsize(int nCol, int nPhrase, char f){
- int ret = -1;
- switch( f ){
- case 'p': ret = 1; break;
- case 'c': ret = 1; break;
- case 'x': ret = 3 * nCol * nPhrase; break;
- case 'y': ret = nCol * nPhrase; break;
- case 'b': ret = ((nCol + 31) / 32) * nPhrase; break;
- case 'n': ret = 1; break;
- case 'a': ret = nCol; break;
- case 'l': ret = nCol; break;
- case 's': ret = nCol; break;
- }
- return ret;
-}
-
-static int fts5MatchinfoIter(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- Fts5MatchinfoCtx *p,
- int(*x)(const Fts5ExtensionApi*,Fts5Context*,Fts5MatchinfoCtx*,char,u32*)
-){
- int i;
- int n = 0;
- int rc = SQLITE_OK;
- char f;
- for(i=0; (f = p->zArg[i]); i++){
- rc = x(pApi, pFts, p, f, &p->aRet[n]);
- if( rc!=SQLITE_OK ) break;
- n += fts5MatchinfoFlagsize(p->nCol, p->nPhrase, f);
- }
- return rc;
-}
-
-static int fts5MatchinfoXCb(
- const Fts5ExtensionApi *pApi,
- Fts5Context *pFts,
- void *pUserData
-){
- Fts5PhraseIter iter;
- int iCol, iOff;
- u32 *aOut = (u32*)pUserData;
- int iPrev = -1;
-
- for(pApi->xPhraseFirst(pFts, 0, &iter, &iCol, &iOff);
- iCol>=0;
- pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
- ){
- aOut[iCol*3+1]++;
- if( iCol!=iPrev ) aOut[iCol*3 + 2]++;
- iPrev = iCol;
- }
-
- return SQLITE_OK;
-}
-
-static int fts5MatchinfoGlobalCb(
- const Fts5ExtensionApi *pApi,
- Fts5Context *pFts,
- Fts5MatchinfoCtx *p,
- char f,
- u32 *aOut
-){
- int rc = SQLITE_OK;
- switch( f ){
- case 'p':
- aOut[0] = p->nPhrase;
- break;
-
- case 'c':
- aOut[0] = p->nCol;
- break;
-
- case 'x': {
- int i;
- for(i=0; i<p->nPhrase && rc==SQLITE_OK; i++){
- void *pPtr = (void*)&aOut[i * p->nCol * 3];
- rc = pApi->xQueryPhrase(pFts, i, pPtr, fts5MatchinfoXCb);
- }
- break;
- }
-
- case 'n': {
- sqlite3_int64 nRow;
- rc = pApi->xRowCount(pFts, &nRow);
- aOut[0] = (u32)nRow;
- break;
- }
-
- case 'a': {
- sqlite3_int64 nRow = 0;
- rc = pApi->xRowCount(pFts, &nRow);
- if( nRow==0 ){
- memset(aOut, 0, sizeof(u32) * p->nCol);
- }else{
- int i;
- for(i=0; rc==SQLITE_OK && i<p->nCol; i++){
- sqlite3_int64 nToken;
- rc = pApi->xColumnTotalSize(pFts, i, &nToken);
- if( rc==SQLITE_OK){
- aOut[i] = (u32)((2*nToken + nRow) / (2*nRow));
- }
- }
- }
- break;
- }
-
- }
- return rc;
-}
-
-static int fts5MatchinfoLocalCb(
- const Fts5ExtensionApi *pApi,
- Fts5Context *pFts,
- Fts5MatchinfoCtx *p,
- char f,
- u32 *aOut
-){
- int i;
- int rc = SQLITE_OK;
-
- switch( f ){
- case 'b': {
- int iPhrase;
- int nInt = ((p->nCol + 31) / 32) * p->nPhrase;
- for(i=0; i<nInt; i++) aOut[i] = 0;
-
- for(iPhrase=0; iPhrase<p->nPhrase; iPhrase++){
- Fts5PhraseIter iter;
- int iCol;
- for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
- iCol>=0;
- pApi->xPhraseNextColumn(pFts, &iter, &iCol)
- ){
- aOut[iPhrase * ((p->nCol+31)/32) + iCol/32] |= ((u32)1 << iCol%32);
- }
- }
-
- break;
- }
-
- case 'x':
- case 'y': {
- int nMul = (f=='x' ? 3 : 1);
- int iPhrase;
-
- for(i=0; i<(p->nCol*p->nPhrase); i++) aOut[i*nMul] = 0;
-
- for(iPhrase=0; iPhrase<p->nPhrase; iPhrase++){
- Fts5PhraseIter iter;
- int iOff, iCol;
- for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
- iOff>=0;
- pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
- ){
- aOut[nMul * (iCol + iPhrase * p->nCol)]++;
- }
- }
-
- break;
- }
-
- case 'l': {
- for(i=0; rc==SQLITE_OK && i<p->nCol; i++){
- int nToken;
- rc = pApi->xColumnSize(pFts, i, &nToken);
- aOut[i] = (u32)nToken;
- }
- break;
- }
-
- case 's': {
- int nInst;
-
- memset(aOut, 0, sizeof(u32) * p->nCol);
-
- rc = pApi->xInstCount(pFts, &nInst);
- for(i=0; rc==SQLITE_OK && i<nInst; i++){
- int iPhrase, iOff, iCol = 0;
- int iNextPhrase;
- int iNextOff;
- u32 nSeq = 1;
- int j;
-
- rc = pApi->xInst(pFts, i, &iPhrase, &iCol, &iOff);
- iNextPhrase = iPhrase+1;
- iNextOff = iOff+pApi->xPhraseSize(pFts, 0);
- for(j=i+1; rc==SQLITE_OK && j<nInst; j++){
- int ip, ic, io;
- rc = pApi->xInst(pFts, j, &ip, &ic, &io);
- if( ic!=iCol || io>iNextOff ) break;
- if( ip==iNextPhrase && io==iNextOff ){
- nSeq++;
- iNextPhrase = ip+1;
- iNextOff = io + pApi->xPhraseSize(pFts, ip);
- }
- }
-
- if( nSeq>aOut[iCol] ) aOut[iCol] = nSeq;
- }
-
- break;
- }
- }
- return rc;
-}
-
-static Fts5MatchinfoCtx *fts5MatchinfoNew(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- sqlite3_context *pCtx, /* Context for returning error message */
- const char *zArg /* Matchinfo flag string */
-){
- Fts5MatchinfoCtx *p;
- int nCol;
- int nPhrase;
- int i;
- int nInt;
- int nByte;
- int rc;
-
- nCol = pApi->xColumnCount(pFts);
- nPhrase = pApi->xPhraseCount(pFts);
-
- nInt = 0;
- for(i=0; zArg[i]; i++){
- int n = fts5MatchinfoFlagsize(nCol, nPhrase, zArg[i]);
- if( n<0 ){
- char *zErr = sqlite3_mprintf("unrecognized matchinfo flag: %c", zArg[i]);
- sqlite3_result_error(pCtx, zErr, -1);
- sqlite3_free(zErr);
- return 0;
- }
- nInt += n;
- }
-
- nByte = sizeof(Fts5MatchinfoCtx) /* The struct itself */
- + sizeof(u32) * nInt /* The p->aRet[] array */
- + (i+1); /* The p->zArg string */
- p = (Fts5MatchinfoCtx*)sqlite3_malloc(nByte);
- if( p==0 ){
- sqlite3_result_error_nomem(pCtx);
- return 0;
- }
- memset(p, 0, nByte);
-
- p->nCol = nCol;
- p->nPhrase = nPhrase;
- p->aRet = (u32*)&p[1];
- p->nRet = nInt;
- p->zArg = (char*)&p->aRet[nInt];
- memcpy(p->zArg, zArg, i);
-
- rc = fts5MatchinfoIter(pApi, pFts, p, fts5MatchinfoGlobalCb);
- if( rc!=SQLITE_OK ){
- sqlite3_result_error_code(pCtx, rc);
- sqlite3_free(p);
- p = 0;
- }
-
- return p;
-}
-
-static void fts5MatchinfoFunc(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- sqlite3_context *pCtx, /* Context for returning result/error */
- int nVal, /* Number of values in apVal[] array */
- sqlite3_value **apVal /* Array of trailing arguments */
-){
- const char *zArg;
- Fts5MatchinfoCtx *p;
- int rc = SQLITE_OK;
-
- if( nVal>0 ){
- zArg = (const char*)sqlite3_value_text(apVal[0]);
- }else{
- zArg = "pcx";
- }
-
- p = (Fts5MatchinfoCtx*)pApi->xGetAuxdata(pFts, 0);
- if( p==0 || sqlite3_stricmp(zArg, p->zArg) ){
- p = fts5MatchinfoNew(pApi, pFts, pCtx, zArg);
- if( p==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = pApi->xSetAuxdata(pFts, p, sqlite3_free);
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = fts5MatchinfoIter(pApi, pFts, p, fts5MatchinfoLocalCb);
- }
- if( rc!=SQLITE_OK ){
- sqlite3_result_error_code(pCtx, rc);
- }else{
- /* No errors has occured, so return a copy of the array of integers. */
- int nByte = p->nRet * sizeof(u32);
- sqlite3_result_blob(pCtx, (void*)p->aRet, nByte, SQLITE_TRANSIENT);
- }
-}
-
-int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
- int rc; /* Return code */
- fts5_api *pApi; /* FTS5 API functions */
-
- /* Extract the FTS5 API pointer from the database handle. The
- ** fts5_api_from_db() function above is copied verbatim from the
- ** FTS5 documentation. Refer there for details. */
- rc = fts5_api_from_db(db, &pApi);
- if( rc!=SQLITE_OK ) return rc;
-
- /* If fts5_api_from_db() returns NULL, then either FTS5 is not registered
- ** with this database handle, or an error (OOM perhaps?) has occurred.
- **
- ** Also check that the fts5_api object is version 2 or newer.
- */
- if( pApi==0 || pApi->iVersion<2 ){
- return SQLITE_ERROR;
- }
-
- /* Register the implementation of matchinfo() */
- rc = pApi->xCreateFunction(pApi, "matchinfo", 0, fts5MatchinfoFunc, 0);
-
- return rc;
-}
-
-#endif /* SQLITE_ENABLE_FTS5 */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_test_tok.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_test_tok.c
deleted file mode 100644
index 1818e16790d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_test_tok.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
-** 2013 Apr 22
-**
-** 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 contains code for the "fts5tokenize" virtual table module.
-** An fts5tokenize virtual table is created as follows:
-**
-** CREATE VIRTUAL TABLE <tbl> USING fts5tokenize(
-** <tokenizer-name>, <arg-1>, ...
-** );
-**
-** The table created has the following schema:
-**
-** CREATE TABLE <tbl>(input HIDDEN, token, start, end, position)
-**
-** When queried, the query must include a WHERE clause of type:
-**
-** input = <string>
-**
-** The virtual table module tokenizes this <string>, using the FTS3
-** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE
-** statement and returns one row for each token in the result. With
-** fields set as follows:
-**
-** input: Always set to a copy of <string>
-** token: A token from the input.
-** start: Byte offset of the token within the input <string>.
-** end: Byte offset of the byte immediately following the end of the
-** token within the input string.
-** pos: Token offset of token within input.
-**
-*/
-#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5)
-
-#include "fts5.h"
-#include <string.h>
-#include <assert.h>
-
-typedef struct Fts5tokTable Fts5tokTable;
-typedef struct Fts5tokCursor Fts5tokCursor;
-typedef struct Fts5tokRow Fts5tokRow;
-
-/*
-** Virtual table structure.
-*/
-struct Fts5tokTable {
- sqlite3_vtab base; /* Base class used by SQLite core */
- fts5_tokenizer tok; /* Tokenizer functions */
- Fts5Tokenizer *pTok; /* Tokenizer instance */
-};
-
-/*
-** A container for a rows values.
-*/
-struct Fts5tokRow {
- char *zToken;
- int iStart;
- int iEnd;
- int iPos;
-};
-
-/*
-** Virtual table cursor structure.
-*/
-struct Fts5tokCursor {
- sqlite3_vtab_cursor base; /* Base class used by SQLite core */
- int iRowid; /* Current 'rowid' value */
- char *zInput; /* Input string */
- int nRow; /* Number of entries in aRow[] */
- Fts5tokRow *aRow; /* Array of rows to return */
-};
-
-static void fts5tokDequote(char *z){
- char q = z[0];
-
- if( q=='[' || q=='\'' || q=='"' || q=='`' ){
- int iIn = 1;
- int iOut = 0;
- if( q=='[' ) q = ']';
-
- while( z[iIn] ){
- if( z[iIn]==q ){
- if( z[iIn+1]!=q ){
- /* Character iIn was the close quote. */
- iIn++;
- break;
- }else{
- /* Character iIn and iIn+1 form an escaped quote character. Skip
- ** the input cursor past both and copy a single quote character
- ** to the output buffer. */
- iIn += 2;
- z[iOut++] = q;
- }
- }else{
- z[iOut++] = z[iIn++];
- }
- }
-
- z[iOut] = '\0';
- }
-}
-
-/*
-** The second argument, argv[], is an array of pointers to nul-terminated
-** strings. This function makes a copy of the array and strings into a
-** single block of memory. It then dequotes any of the strings that appear
-** to be quoted.
-**
-** If successful, output parameter *pazDequote is set to point at the
-** array of dequoted strings and SQLITE_OK is returned. The caller is
-** responsible for eventually calling sqlite3_free() to free the array
-** in this case. Or, if an error occurs, an SQLite error code is returned.
-** The final value of *pazDequote is undefined in this case.
-*/
-static int fts5tokDequoteArray(
- int argc, /* Number of elements in argv[] */
- const char * const *argv, /* Input array */
- char ***pazDequote /* Output array */
-){
- int rc = SQLITE_OK; /* Return code */
- if( argc==0 ){
- *pazDequote = 0;
- }else{
- int i;
- int nByte = 0;
- char **azDequote;
-
- for(i=0; i<argc; i++){
- nByte += (int)(strlen(argv[i]) + 1);
- }
-
- *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
- if( azDequote==0 ){
- rc = SQLITE_NOMEM;
- }else{
- char *pSpace = (char *)&azDequote[argc];
- for(i=0; i<argc; i++){
- int n = (int)strlen(argv[i]);
- azDequote[i] = pSpace;
- memcpy(pSpace, argv[i], n+1);
- fts5tokDequote(pSpace);
- pSpace += (n+1);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Schema of the tokenizer table.
-*/
-#define FTS3_TOK_SCHEMA "CREATE TABLE x(input HIDDEN, token, start, end, position)"
-
-/*
-** This function does all the work for both the xConnect and xCreate methods.
-** These tables have no persistent representation of their own, so xConnect
-** and xCreate are identical operations.
-**
-** argv[0]: module name
-** argv[1]: database name
-** argv[2]: table name
-** argv[3]: first argument (tokenizer name)
-*/
-static int fts5tokConnectMethod(
- sqlite3 *db, /* Database connection */
- void *pCtx, /* Pointer to fts5_api object */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- fts5_api *pApi = (fts5_api*)pCtx;
- Fts5tokTable *pTab = 0;
- int rc;
- char **azDequote = 0;
- int nDequote = 0;
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(input HIDDEN, token, start, end, position)"
- );
-
- if( rc==SQLITE_OK ){
- nDequote = argc-3;
- rc = fts5tokDequoteArray(nDequote, &argv[3], &azDequote);
- }
-
- if( rc==SQLITE_OK ){
- pTab = (Fts5tokTable*)sqlite3_malloc(sizeof(Fts5tokTable));
- if( pTab==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pTab, 0, sizeof(Fts5tokTable));
- }
- }
-
- if( rc==SQLITE_OK ){
- void *pTokCtx = 0;
- const char *zModule = 0;
- if( nDequote>0 ){
- zModule = azDequote[0];
- }
-
- rc = pApi->xFindTokenizer(pApi, zModule, &pTokCtx, &pTab->tok);
- if( rc==SQLITE_OK ){
- const char **azArg = (const char **)&azDequote[1];
- int nArg = nDequote>0 ? nDequote-1 : 0;
- rc = pTab->tok.xCreate(pTokCtx, azArg, nArg, &pTab->pTok);
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_free(pTab);
- pTab = 0;
- }
-
- *ppVtab = (sqlite3_vtab*)pTab;
- sqlite3_free(azDequote);
- return rc;
-}
-
-/*
-** This function does the work for both the xDisconnect and xDestroy methods.
-** These tables have no persistent representation of their own, so xDisconnect
-** and xDestroy are identical operations.
-*/
-static int fts5tokDisconnectMethod(sqlite3_vtab *pVtab){
- Fts5tokTable *pTab = (Fts5tokTable *)pVtab;
- if( pTab->pTok ){
- pTab->tok.xDelete(pTab->pTok);
- }
- sqlite3_free(pTab);
- return SQLITE_OK;
-}
-
-/*
-** xBestIndex - Analyze a WHERE and ORDER BY clause.
-*/
-static int fts5tokBestIndexMethod(
- sqlite3_vtab *pVTab,
- sqlite3_index_info *pInfo
-){
- int i;
-
- for(i=0; i<pInfo->nConstraint; i++){
- if( pInfo->aConstraint[i].usable
- && pInfo->aConstraint[i].iColumn==0
- && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- pInfo->idxNum = 1;
- pInfo->aConstraintUsage[i].argvIndex = 1;
- pInfo->aConstraintUsage[i].omit = 1;
- pInfo->estimatedCost = 1;
- return SQLITE_OK;
- }
- }
-
- pInfo->idxNum = 0;
- assert( pInfo->estimatedCost>1000000.0 );
-
- return SQLITE_OK;
-}
-
-/*
-** xOpen - Open a cursor.
-*/
-static int fts5tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
- Fts5tokCursor *pCsr;
-
- pCsr = (Fts5tokCursor *)sqlite3_malloc(sizeof(Fts5tokCursor));
- if( pCsr==0 ){
- return SQLITE_NOMEM;
- }
- memset(pCsr, 0, sizeof(Fts5tokCursor));
-
- *ppCsr = (sqlite3_vtab_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** Reset the tokenizer cursor passed as the only argument. As if it had
-** just been returned by fts5tokOpenMethod().
-*/
-static void fts5tokResetCursor(Fts5tokCursor *pCsr){
- int i;
- for(i=0; i<pCsr->nRow; i++){
- sqlite3_free(pCsr->aRow[i].zToken);
- }
- sqlite3_free(pCsr->zInput);
- sqlite3_free(pCsr->aRow);
- pCsr->zInput = 0;
- pCsr->aRow = 0;
- pCsr->nRow = 0;
- pCsr->iRowid = 0;
-}
-
-/*
-** xClose - Close a cursor.
-*/
-static int fts5tokCloseMethod(sqlite3_vtab_cursor *pCursor){
- Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor;
- fts5tokResetCursor(pCsr);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** xNext - Advance the cursor to the next row, if any.
-*/
-static int fts5tokNextMethod(sqlite3_vtab_cursor *pCursor){
- Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor;
- pCsr->iRowid++;
- return SQLITE_OK;
-}
-
-static int fts5tokCb(
- void *pCtx, /* Pointer to Fts5tokCursor */
- int tflags, /* Mask of FTS5_TOKEN_* flags */
- const char *pToken, /* Pointer to buffer containing token */
- int nToken, /* Size of token in bytes */
- int iStart, /* Byte offset of token within input text */
- int iEnd /* Byte offset of end of token within input text */
-){
- Fts5tokCursor *pCsr = (Fts5tokCursor*)pCtx;
- Fts5tokRow *pRow;
-
- if( (pCsr->nRow & (pCsr->nRow-1))==0 ){
- int nNew = pCsr->nRow ? pCsr->nRow*2 : 32;
- Fts5tokRow *aNew;
- aNew = (Fts5tokRow*)sqlite3_realloc(pCsr->aRow, nNew*sizeof(Fts5tokRow));
- if( aNew==0 ) return SQLITE_NOMEM;
- memset(&aNew[pCsr->nRow], 0, sizeof(Fts5tokRow)*(nNew-pCsr->nRow));
- pCsr->aRow = aNew;
- }
-
- pRow = &pCsr->aRow[pCsr->nRow];
- pRow->iStart = iStart;
- pRow->iEnd = iEnd;
- if( pCsr->nRow ){
- pRow->iPos = pRow[-1].iPos + ((tflags & FTS5_TOKEN_COLOCATED) ? 0 : 1);
- }
- pRow->zToken = sqlite3_malloc(nToken+1);
- if( pRow->zToken==0 ) return SQLITE_NOMEM;
- memcpy(pRow->zToken, pToken, nToken);
- pRow->zToken[nToken] = 0;
- pCsr->nRow++;
-
- return SQLITE_OK;
-}
-
-/*
-** xFilter - Initialize a cursor to point at the start of its data.
-*/
-static int fts5tokFilterMethod(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, /* Strategy index */
- const char *idxStr, /* Unused */
- int nVal, /* Number of elements in apVal */
- sqlite3_value **apVal /* Arguments for the indexing scheme */
-){
- int rc = SQLITE_ERROR;
- Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor;
- Fts5tokTable *pTab = (Fts5tokTable *)(pCursor->pVtab);
-
- fts5tokResetCursor(pCsr);
- if( idxNum==1 ){
- const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
- int nByte = sqlite3_value_bytes(apVal[0]);
- pCsr->zInput = sqlite3_malloc(nByte+1);
- if( pCsr->zInput==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memcpy(pCsr->zInput, zByte, nByte);
- pCsr->zInput[nByte] = 0;
- rc = pTab->tok.xTokenize(
- pTab->pTok, (void*)pCsr, 0, zByte, nByte, fts5tokCb
- );
- }
- }
-
- if( rc!=SQLITE_OK ) return rc;
- return fts5tokNextMethod(pCursor);
-}
-
-/*
-** xEof - Return true if the cursor is at EOF, or false otherwise.
-*/
-static int fts5tokEofMethod(sqlite3_vtab_cursor *pCursor){
- Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor;
- return (pCsr->iRowid>pCsr->nRow);
-}
-
-/*
-** xColumn - Return a column value.
-*/
-static int fts5tokColumnMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
- int iCol /* Index of column to read value from */
-){
- Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor;
- Fts5tokRow *pRow = &pCsr->aRow[pCsr->iRowid-1];
-
- /* CREATE TABLE x(input, token, start, end, position) */
- switch( iCol ){
- case 0:
- sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT);
- break;
- case 1:
- sqlite3_result_text(pCtx, pRow->zToken, -1, SQLITE_TRANSIENT);
- break;
- case 2:
- sqlite3_result_int(pCtx, pRow->iStart);
- break;
- case 3:
- sqlite3_result_int(pCtx, pRow->iEnd);
- break;
- default:
- assert( iCol==4 );
- sqlite3_result_int(pCtx, pRow->iPos);
- break;
- }
- return SQLITE_OK;
-}
-
-/*
-** xRowid - Return the current rowid for the cursor.
-*/
-static int fts5tokRowidMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite_int64 *pRowid /* OUT: Rowid value */
-){
- Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor;
- *pRowid = (sqlite3_int64)pCsr->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Register the fts5tok module with database connection db. Return SQLITE_OK
-** if successful or an error code if sqlite3_create_module() fails.
-*/
-int sqlite3Fts5TestRegisterTok(sqlite3 *db, fts5_api *pApi){
- static const sqlite3_module fts5tok_module = {
- 0, /* iVersion */
- fts5tokConnectMethod, /* xCreate */
- fts5tokConnectMethod, /* xConnect */
- fts5tokBestIndexMethod, /* xBestIndex */
- fts5tokDisconnectMethod, /* xDisconnect */
- fts5tokDisconnectMethod, /* xDestroy */
- fts5tokOpenMethod, /* xOpen */
- fts5tokCloseMethod, /* xClose */
- fts5tokFilterMethod, /* xFilter */
- fts5tokNextMethod, /* xNext */
- fts5tokEofMethod, /* xEof */
- fts5tokColumnMethod, /* xColumn */
- fts5tokRowidMethod, /* xRowid */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindFunction */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
- };
- int rc; /* Return code */
-
- rc = sqlite3_create_module(db, "fts5tokenize", &fts5tok_module, (void*)pApi);
- return rc;
-}
-
-#endif /* defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_tokenize.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_tokenize.c
deleted file mode 100644
index b72a0c24ab9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_tokenize.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-*/
-
-
-#include "fts5Int.h"
-
-/**************************************************************************
-** Start of ascii tokenizer implementation.
-*/
-
-/*
-** For tokenizers with no "unicode" modifier, the set of token characters
-** is the same as the set of ASCII range alphanumeric characters.
-*/
-static unsigned char aAsciiTokenChar[128] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00..0x0F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10..0x1F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20..0x2F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30..0x3F */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40..0x4F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x50..0x5F */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60..0x6F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70..0x7F */
-};
-
-typedef struct AsciiTokenizer AsciiTokenizer;
-struct AsciiTokenizer {
- unsigned char aTokenChar[128];
-};
-
-static void fts5AsciiAddExceptions(
- AsciiTokenizer *p,
- const char *zArg,
- int bTokenChars
-){
- int i;
- for(i=0; zArg[i]; i++){
- if( (zArg[i] & 0x80)==0 ){
- p->aTokenChar[(int)zArg[i]] = (unsigned char)bTokenChars;
- }
- }
-}
-
-/*
-** Delete a "ascii" tokenizer.
-*/
-static void fts5AsciiDelete(Fts5Tokenizer *p){
- sqlite3_free(p);
-}
-
-/*
-** Create an "ascii" tokenizer.
-*/
-static int fts5AsciiCreate(
- void *pUnused,
- const char **azArg, int nArg,
- Fts5Tokenizer **ppOut
-){
- int rc = SQLITE_OK;
- AsciiTokenizer *p = 0;
- UNUSED_PARAM(pUnused);
- if( nArg%2 ){
- rc = SQLITE_ERROR;
- }else{
- p = sqlite3_malloc(sizeof(AsciiTokenizer));
- if( p==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int i;
- memset(p, 0, sizeof(AsciiTokenizer));
- memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar));
- for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
- const char *zArg = azArg[i+1];
- if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
- fts5AsciiAddExceptions(p, zArg, 1);
- }else
- if( 0==sqlite3_stricmp(azArg[i], "separators") ){
- fts5AsciiAddExceptions(p, zArg, 0);
- }else{
- rc = SQLITE_ERROR;
- }
- }
- if( rc!=SQLITE_OK ){
- fts5AsciiDelete((Fts5Tokenizer*)p);
- p = 0;
- }
- }
- }
-
- *ppOut = (Fts5Tokenizer*)p;
- return rc;
-}
-
-
-static void asciiFold(char *aOut, const char *aIn, int nByte){
- int i;
- for(i=0; i<nByte; i++){
- char c = aIn[i];
- if( c>='A' && c<='Z' ) c += 32;
- aOut[i] = c;
- }
-}
-
-/*
-** Tokenize some text using the ascii tokenizer.
-*/
-static int fts5AsciiTokenize(
- Fts5Tokenizer *pTokenizer,
- void *pCtx,
- int iUnused,
- const char *pText, int nText,
- int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd)
-){
- AsciiTokenizer *p = (AsciiTokenizer*)pTokenizer;
- int rc = SQLITE_OK;
- int ie;
- int is = 0;
-
- char aFold[64];
- int nFold = sizeof(aFold);
- char *pFold = aFold;
- unsigned char *a = p->aTokenChar;
-
- UNUSED_PARAM(iUnused);
-
- while( is<nText && rc==SQLITE_OK ){
- int nByte;
-
- /* Skip any leading divider characters. */
- while( is<nText && ((pText[is]&0x80)==0 && a[(int)pText[is]]==0) ){
- is++;
- }
- if( is==nText ) break;
-
- /* Count the token characters */
- ie = is+1;
- while( ie<nText && ((pText[ie]&0x80) || a[(int)pText[ie]] ) ){
- ie++;
- }
-
- /* Fold to lower case */
- nByte = ie-is;
- if( nByte>nFold ){
- if( pFold!=aFold ) sqlite3_free(pFold);
- pFold = sqlite3_malloc(nByte*2);
- if( pFold==0 ){
- rc = SQLITE_NOMEM;
- break;
- }
- nFold = nByte*2;
- }
- asciiFold(pFold, &pText[is], nByte);
-
- /* Invoke the token callback */
- rc = xToken(pCtx, 0, pFold, nByte, is, ie);
- is = ie+1;
- }
-
- if( pFold!=aFold ) sqlite3_free(pFold);
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- return rc;
-}
-
-/**************************************************************************
-** Start of unicode61 tokenizer implementation.
-*/
-
-
-/*
-** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
-** from the sqlite3 source file utf.c. If this file is compiled as part
-** of the amalgamation, they are not required.
-*/
-#ifndef SQLITE_AMALGAMATION
-
-static const unsigned char sqlite3Utf8Trans1[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
-};
-
-#define READ_UTF8(zIn, zTerm, c) \
- c = *(zIn++); \
- if( c>=0xc0 ){ \
- c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
- c = (c<<6) + (0x3f & *(zIn++)); \
- } \
- if( c<0x80 \
- || (c&0xFFFFF800)==0xD800 \
- || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
- }
-
-
-#define WRITE_UTF8(zOut, c) { \
- if( c<0x00080 ){ \
- *zOut++ = (unsigned char)(c&0xFF); \
- } \
- else if( c<0x00800 ){ \
- *zOut++ = 0xC0 + (unsigned char)((c>>6)&0x1F); \
- *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
- } \
- else if( c<0x10000 ){ \
- *zOut++ = 0xE0 + (unsigned char)((c>>12)&0x0F); \
- *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
- }else{ \
- *zOut++ = 0xF0 + (unsigned char)((c>>18) & 0x07); \
- *zOut++ = 0x80 + (unsigned char)((c>>12) & 0x3F); \
- *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
- } \
-}
-
-#endif /* ifndef SQLITE_AMALGAMATION */
-
-typedef struct Unicode61Tokenizer Unicode61Tokenizer;
-struct Unicode61Tokenizer {
- unsigned char aTokenChar[128]; /* ASCII range token characters */
- char *aFold; /* Buffer to fold text into */
- int nFold; /* Size of aFold[] in bytes */
- int bRemoveDiacritic; /* True if remove_diacritics=1 is set */
- int nException;
- int *aiException;
-};
-
-static int fts5UnicodeAddExceptions(
- Unicode61Tokenizer *p, /* Tokenizer object */
- const char *z, /* Characters to treat as exceptions */
- int bTokenChars /* 1 for 'tokenchars', 0 for 'separators' */
-){
- int rc = SQLITE_OK;
- int n = (int)strlen(z);
- int *aNew;
-
- if( n>0 ){
- aNew = (int*)sqlite3_realloc(p->aiException, (n+p->nException)*sizeof(int));
- if( aNew ){
- int nNew = p->nException;
- const unsigned char *zCsr = (const unsigned char*)z;
- const unsigned char *zTerm = (const unsigned char*)&z[n];
- while( zCsr<zTerm ){
- int iCode;
- int bToken;
- READ_UTF8(zCsr, zTerm, iCode);
- if( iCode<128 ){
- p->aTokenChar[iCode] = (unsigned char)bTokenChars;
- }else{
- bToken = sqlite3Fts5UnicodeIsalnum(iCode);
- assert( (bToken==0 || bToken==1) );
- assert( (bTokenChars==0 || bTokenChars==1) );
- if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){
- int i;
- for(i=0; i<nNew; i++){
- if( aNew[i]>iCode ) break;
- }
- memmove(&aNew[i+1], &aNew[i], (nNew-i)*sizeof(int));
- aNew[i] = iCode;
- nNew++;
- }
- }
- }
- p->aiException = aNew;
- p->nException = nNew;
- }else{
- rc = SQLITE_NOMEM;
- }
- }
-
- return rc;
-}
-
-/*
-** Return true if the p->aiException[] array contains the value iCode.
-*/
-static int fts5UnicodeIsException(Unicode61Tokenizer *p, int iCode){
- if( p->nException>0 ){
- int *a = p->aiException;
- int iLo = 0;
- int iHi = p->nException-1;
-
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( iCode==a[iTest] ){
- return 1;
- }else if( iCode>a[iTest] ){
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- }
-
- return 0;
-}
-
-/*
-** Delete a "unicode61" tokenizer.
-*/
-static void fts5UnicodeDelete(Fts5Tokenizer *pTok){
- if( pTok ){
- Unicode61Tokenizer *p = (Unicode61Tokenizer*)pTok;
- sqlite3_free(p->aiException);
- sqlite3_free(p->aFold);
- sqlite3_free(p);
- }
- return;
-}
-
-/*
-** Create a "unicode61" tokenizer.
-*/
-static int fts5UnicodeCreate(
- void *pUnused,
- const char **azArg, int nArg,
- Fts5Tokenizer **ppOut
-){
- int rc = SQLITE_OK; /* Return code */
- Unicode61Tokenizer *p = 0; /* New tokenizer object */
-
- UNUSED_PARAM(pUnused);
-
- if( nArg%2 ){
- rc = SQLITE_ERROR;
- }else{
- p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer));
- if( p ){
- int i;
- memset(p, 0, sizeof(Unicode61Tokenizer));
- memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar));
- p->bRemoveDiacritic = 1;
- p->nFold = 64;
- p->aFold = sqlite3_malloc(p->nFold * sizeof(char));
- if( p->aFold==0 ){
- rc = SQLITE_NOMEM;
- }
- for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
- const char *zArg = azArg[i+1];
- if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
- if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
- rc = SQLITE_ERROR;
- }
- p->bRemoveDiacritic = (zArg[0]=='1');
- }else
- if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
- rc = fts5UnicodeAddExceptions(p, zArg, 1);
- }else
- if( 0==sqlite3_stricmp(azArg[i], "separators") ){
- rc = fts5UnicodeAddExceptions(p, zArg, 0);
- }else{
- rc = SQLITE_ERROR;
- }
- }
- }else{
- rc = SQLITE_NOMEM;
- }
- if( rc!=SQLITE_OK ){
- fts5UnicodeDelete((Fts5Tokenizer*)p);
- p = 0;
- }
- *ppOut = (Fts5Tokenizer*)p;
- }
- return rc;
-}
-
-/*
-** Return true if, for the purposes of tokenizing with the tokenizer
-** passed as the first argument, codepoint iCode is considered a token
-** character (not a separator).
-*/
-static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){
- assert( (sqlite3Fts5UnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
- return sqlite3Fts5UnicodeIsalnum(iCode) ^ fts5UnicodeIsException(p, iCode);
-}
-
-static int fts5UnicodeTokenize(
- Fts5Tokenizer *pTokenizer,
- void *pCtx,
- int iUnused,
- const char *pText, int nText,
- int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd)
-){
- Unicode61Tokenizer *p = (Unicode61Tokenizer*)pTokenizer;
- int rc = SQLITE_OK;
- unsigned char *a = p->aTokenChar;
-
- unsigned char *zTerm = (unsigned char*)&pText[nText];
- unsigned char *zCsr = (unsigned char *)pText;
-
- /* Output buffer */
- char *aFold = p->aFold;
- int nFold = p->nFold;
- const char *pEnd = &aFold[nFold-6];
-
- UNUSED_PARAM(iUnused);
-
- /* Each iteration of this loop gobbles up a contiguous run of separators,
- ** then the next token. */
- while( rc==SQLITE_OK ){
- int iCode; /* non-ASCII codepoint read from input */
- char *zOut = aFold;
- int is;
- int ie;
-
- /* Skip any separator characters. */
- while( 1 ){
- if( zCsr>=zTerm ) goto tokenize_done;
- if( *zCsr & 0x80 ) {
- /* A character outside of the ascii range. Skip past it if it is
- ** a separator character. Or break out of the loop if it is not. */
- is = zCsr - (unsigned char*)pText;
- READ_UTF8(zCsr, zTerm, iCode);
- if( fts5UnicodeIsAlnum(p, iCode) ){
- goto non_ascii_tokenchar;
- }
- }else{
- if( a[*zCsr] ){
- is = zCsr - (unsigned char*)pText;
- goto ascii_tokenchar;
- }
- zCsr++;
- }
- }
-
- /* Run through the tokenchars. Fold them into the output buffer along
- ** the way. */
- while( zCsr<zTerm ){
-
- /* Grow the output buffer so that there is sufficient space to fit the
- ** largest possible utf-8 character. */
- if( zOut>pEnd ){
- aFold = sqlite3_malloc(nFold*2);
- if( aFold==0 ){
- rc = SQLITE_NOMEM;
- goto tokenize_done;
- }
- zOut = &aFold[zOut - p->aFold];
- memcpy(aFold, p->aFold, nFold);
- sqlite3_free(p->aFold);
- p->aFold = aFold;
- p->nFold = nFold = nFold*2;
- pEnd = &aFold[nFold-6];
- }
-
- if( *zCsr & 0x80 ){
- /* An non-ascii-range character. Fold it into the output buffer if
- ** it is a token character, or break out of the loop if it is not. */
- READ_UTF8(zCsr, zTerm, iCode);
- if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){
- non_ascii_tokenchar:
- iCode = sqlite3Fts5UnicodeFold(iCode, p->bRemoveDiacritic);
- if( iCode ) WRITE_UTF8(zOut, iCode);
- }else{
- break;
- }
- }else if( a[*zCsr]==0 ){
- /* An ascii-range separator character. End of token. */
- break;
- }else{
- ascii_tokenchar:
- if( *zCsr>='A' && *zCsr<='Z' ){
- *zOut++ = *zCsr + 32;
- }else{
- *zOut++ = *zCsr;
- }
- zCsr++;
- }
- ie = zCsr - (unsigned char*)pText;
- }
-
- /* Invoke the token callback */
- rc = xToken(pCtx, 0, aFold, zOut-aFold, is, ie);
- }
-
- tokenize_done:
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- return rc;
-}
-
-/**************************************************************************
-** Start of porter stemmer implementation.
-*/
-
-/* Any tokens larger than this (in bytes) are passed through without
-** stemming. */
-#define FTS5_PORTER_MAX_TOKEN 64
-
-typedef struct PorterTokenizer PorterTokenizer;
-struct PorterTokenizer {
- fts5_tokenizer tokenizer; /* Parent tokenizer module */
- Fts5Tokenizer *pTokenizer; /* Parent tokenizer instance */
- char aBuf[FTS5_PORTER_MAX_TOKEN + 64];
-};
-
-/*
-** Delete a "porter" tokenizer.
-*/
-static void fts5PorterDelete(Fts5Tokenizer *pTok){
- if( pTok ){
- PorterTokenizer *p = (PorterTokenizer*)pTok;
- if( p->pTokenizer ){
- p->tokenizer.xDelete(p->pTokenizer);
- }
- sqlite3_free(p);
- }
-}
-
-/*
-** Create a "porter" tokenizer.
-*/
-static int fts5PorterCreate(
- void *pCtx,
- const char **azArg, int nArg,
- Fts5Tokenizer **ppOut
-){
- fts5_api *pApi = (fts5_api*)pCtx;
- int rc = SQLITE_OK;
- PorterTokenizer *pRet;
- void *pUserdata = 0;
- const char *zBase = "unicode61";
-
- if( nArg>0 ){
- zBase = azArg[0];
- }
-
- pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer));
- if( pRet ){
- memset(pRet, 0, sizeof(PorterTokenizer));
- rc = pApi->xFindTokenizer(pApi, zBase, &pUserdata, &pRet->tokenizer);
- }else{
- rc = SQLITE_NOMEM;
- }
- if( rc==SQLITE_OK ){
- int nArg2 = (nArg>0 ? nArg-1 : 0);
- const char **azArg2 = (nArg2 ? &azArg[1] : 0);
- rc = pRet->tokenizer.xCreate(pUserdata, azArg2, nArg2, &pRet->pTokenizer);
- }
-
- if( rc!=SQLITE_OK ){
- fts5PorterDelete((Fts5Tokenizer*)pRet);
- pRet = 0;
- }
- *ppOut = (Fts5Tokenizer*)pRet;
- return rc;
-}
-
-typedef struct PorterContext PorterContext;
-struct PorterContext {
- void *pCtx;
- int (*xToken)(void*, int, const char*, int, int, int);
- char *aBuf;
-};
-
-typedef struct PorterRule PorterRule;
-struct PorterRule {
- const char *zSuffix;
- int nSuffix;
- int (*xCond)(char *zStem, int nStem);
- const char *zOutput;
- int nOutput;
-};
-
-#if 0
-static int fts5PorterApply(char *aBuf, int *pnBuf, PorterRule *aRule){
- int ret = -1;
- int nBuf = *pnBuf;
- PorterRule *p;
-
- for(p=aRule; p->zSuffix; p++){
- assert( strlen(p->zSuffix)==p->nSuffix );
- assert( strlen(p->zOutput)==p->nOutput );
- if( nBuf<p->nSuffix ) continue;
- if( 0==memcmp(&aBuf[nBuf - p->nSuffix], p->zSuffix, p->nSuffix) ) break;
- }
-
- if( p->zSuffix ){
- int nStem = nBuf - p->nSuffix;
- if( p->xCond==0 || p->xCond(aBuf, nStem) ){
- memcpy(&aBuf[nStem], p->zOutput, p->nOutput);
- *pnBuf = nStem + p->nOutput;
- ret = p - aRule;
- }
- }
-
- return ret;
-}
-#endif
-
-static int fts5PorterIsVowel(char c, int bYIsVowel){
- return (
- c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || (bYIsVowel && c=='y')
- );
-}
-
-static int fts5PorterGobbleVC(char *zStem, int nStem, int bPrevCons){
- int i;
- int bCons = bPrevCons;
-
- /* Scan for a vowel */
- for(i=0; i<nStem; i++){
- if( 0==(bCons = !fts5PorterIsVowel(zStem[i], bCons)) ) break;
- }
-
- /* Scan for a consonent */
- for(i++; i<nStem; i++){
- if( (bCons = !fts5PorterIsVowel(zStem[i], bCons)) ) return i+1;
- }
- return 0;
-}
-
-/* porter rule condition: (m > 0) */
-static int fts5Porter_MGt0(char *zStem, int nStem){
- return !!fts5PorterGobbleVC(zStem, nStem, 0);
-}
-
-/* porter rule condition: (m > 1) */
-static int fts5Porter_MGt1(char *zStem, int nStem){
- int n;
- n = fts5PorterGobbleVC(zStem, nStem, 0);
- if( n && fts5PorterGobbleVC(&zStem[n], nStem-n, 1) ){
- return 1;
- }
- return 0;
-}
-
-/* porter rule condition: (m = 1) */
-static int fts5Porter_MEq1(char *zStem, int nStem){
- int n;
- n = fts5PorterGobbleVC(zStem, nStem, 0);
- if( n && 0==fts5PorterGobbleVC(&zStem[n], nStem-n, 1) ){
- return 1;
- }
- return 0;
-}
-
-/* porter rule condition: (*o) */
-static int fts5Porter_Ostar(char *zStem, int nStem){
- if( zStem[nStem-1]=='w' || zStem[nStem-1]=='x' || zStem[nStem-1]=='y' ){
- return 0;
- }else{
- int i;
- int mask = 0;
- int bCons = 0;
- for(i=0; i<nStem; i++){
- bCons = !fts5PorterIsVowel(zStem[i], bCons);
- assert( bCons==0 || bCons==1 );
- mask = (mask << 1) + bCons;
- }
- return ((mask & 0x0007)==0x0005);
- }
-}
-
-/* porter rule condition: (m > 1 and (*S or *T)) */
-static int fts5Porter_MGt1_and_S_or_T(char *zStem, int nStem){
- assert( nStem>0 );
- return (zStem[nStem-1]=='s' || zStem[nStem-1]=='t')
- && fts5Porter_MGt1(zStem, nStem);
-}
-
-/* porter rule condition: (*v*) */
-static int fts5Porter_Vowel(char *zStem, int nStem){
- int i;
- for(i=0; i<nStem; i++){
- if( fts5PorterIsVowel(zStem[i], i>0) ){
- return 1;
- }
- }
- return 0;
-}
-
-
-/**************************************************************************
-***************************************************************************
-** GENERATED CODE STARTS HERE (mkportersteps.tcl)
-*/
-
-static int fts5PorterStep4(char *aBuf, int *pnBuf){
- int ret = 0;
- int nBuf = *pnBuf;
- switch( aBuf[nBuf-2] ){
-
- case 'a':
- if( nBuf>2 && 0==memcmp("al", &aBuf[nBuf-2], 2) ){
- if( fts5Porter_MGt1(aBuf, nBuf-2) ){
- *pnBuf = nBuf - 2;
- }
- }
- break;
-
- case 'c':
- if( nBuf>4 && 0==memcmp("ance", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt1(aBuf, nBuf-4) ){
- *pnBuf = nBuf - 4;
- }
- }else if( nBuf>4 && 0==memcmp("ence", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt1(aBuf, nBuf-4) ){
- *pnBuf = nBuf - 4;
- }
- }
- break;
-
- case 'e':
- if( nBuf>2 && 0==memcmp("er", &aBuf[nBuf-2], 2) ){
- if( fts5Porter_MGt1(aBuf, nBuf-2) ){
- *pnBuf = nBuf - 2;
- }
- }
- break;
-
- case 'i':
- if( nBuf>2 && 0==memcmp("ic", &aBuf[nBuf-2], 2) ){
- if( fts5Porter_MGt1(aBuf, nBuf-2) ){
- *pnBuf = nBuf - 2;
- }
- }
- break;
-
- case 'l':
- if( nBuf>4 && 0==memcmp("able", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt1(aBuf, nBuf-4) ){
- *pnBuf = nBuf - 4;
- }
- }else if( nBuf>4 && 0==memcmp("ible", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt1(aBuf, nBuf-4) ){
- *pnBuf = nBuf - 4;
- }
- }
- break;
-
- case 'n':
- if( nBuf>3 && 0==memcmp("ant", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }else if( nBuf>5 && 0==memcmp("ement", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt1(aBuf, nBuf-5) ){
- *pnBuf = nBuf - 5;
- }
- }else if( nBuf>4 && 0==memcmp("ment", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt1(aBuf, nBuf-4) ){
- *pnBuf = nBuf - 4;
- }
- }else if( nBuf>3 && 0==memcmp("ent", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }
- break;
-
- case 'o':
- if( nBuf>3 && 0==memcmp("ion", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1_and_S_or_T(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }else if( nBuf>2 && 0==memcmp("ou", &aBuf[nBuf-2], 2) ){
- if( fts5Porter_MGt1(aBuf, nBuf-2) ){
- *pnBuf = nBuf - 2;
- }
- }
- break;
-
- case 's':
- if( nBuf>3 && 0==memcmp("ism", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }
- break;
-
- case 't':
- if( nBuf>3 && 0==memcmp("ate", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }else if( nBuf>3 && 0==memcmp("iti", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }
- break;
-
- case 'u':
- if( nBuf>3 && 0==memcmp("ous", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }
- break;
-
- case 'v':
- if( nBuf>3 && 0==memcmp("ive", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }
- break;
-
- case 'z':
- if( nBuf>3 && 0==memcmp("ize", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt1(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }
- break;
-
- }
- return ret;
-}
-
-
-static int fts5PorterStep1B2(char *aBuf, int *pnBuf){
- int ret = 0;
- int nBuf = *pnBuf;
- switch( aBuf[nBuf-2] ){
-
- case 'a':
- if( nBuf>2 && 0==memcmp("at", &aBuf[nBuf-2], 2) ){
- memcpy(&aBuf[nBuf-2], "ate", 3);
- *pnBuf = nBuf - 2 + 3;
- ret = 1;
- }
- break;
-
- case 'b':
- if( nBuf>2 && 0==memcmp("bl", &aBuf[nBuf-2], 2) ){
- memcpy(&aBuf[nBuf-2], "ble", 3);
- *pnBuf = nBuf - 2 + 3;
- ret = 1;
- }
- break;
-
- case 'i':
- if( nBuf>2 && 0==memcmp("iz", &aBuf[nBuf-2], 2) ){
- memcpy(&aBuf[nBuf-2], "ize", 3);
- *pnBuf = nBuf - 2 + 3;
- ret = 1;
- }
- break;
-
- }
- return ret;
-}
-
-
-static int fts5PorterStep2(char *aBuf, int *pnBuf){
- int ret = 0;
- int nBuf = *pnBuf;
- switch( aBuf[nBuf-2] ){
-
- case 'a':
- if( nBuf>7 && 0==memcmp("ational", &aBuf[nBuf-7], 7) ){
- if( fts5Porter_MGt0(aBuf, nBuf-7) ){
- memcpy(&aBuf[nBuf-7], "ate", 3);
- *pnBuf = nBuf - 7 + 3;
- }
- }else if( nBuf>6 && 0==memcmp("tional", &aBuf[nBuf-6], 6) ){
- if( fts5Porter_MGt0(aBuf, nBuf-6) ){
- memcpy(&aBuf[nBuf-6], "tion", 4);
- *pnBuf = nBuf - 6 + 4;
- }
- }
- break;
-
- case 'c':
- if( nBuf>4 && 0==memcmp("enci", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt0(aBuf, nBuf-4) ){
- memcpy(&aBuf[nBuf-4], "ence", 4);
- *pnBuf = nBuf - 4 + 4;
- }
- }else if( nBuf>4 && 0==memcmp("anci", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt0(aBuf, nBuf-4) ){
- memcpy(&aBuf[nBuf-4], "ance", 4);
- *pnBuf = nBuf - 4 + 4;
- }
- }
- break;
-
- case 'e':
- if( nBuf>4 && 0==memcmp("izer", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt0(aBuf, nBuf-4) ){
- memcpy(&aBuf[nBuf-4], "ize", 3);
- *pnBuf = nBuf - 4 + 3;
- }
- }
- break;
-
- case 'g':
- if( nBuf>4 && 0==memcmp("logi", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt0(aBuf, nBuf-4) ){
- memcpy(&aBuf[nBuf-4], "log", 3);
- *pnBuf = nBuf - 4 + 3;
- }
- }
- break;
-
- case 'l':
- if( nBuf>3 && 0==memcmp("bli", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt0(aBuf, nBuf-3) ){
- memcpy(&aBuf[nBuf-3], "ble", 3);
- *pnBuf = nBuf - 3 + 3;
- }
- }else if( nBuf>4 && 0==memcmp("alli", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt0(aBuf, nBuf-4) ){
- memcpy(&aBuf[nBuf-4], "al", 2);
- *pnBuf = nBuf - 4 + 2;
- }
- }else if( nBuf>5 && 0==memcmp("entli", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "ent", 3);
- *pnBuf = nBuf - 5 + 3;
- }
- }else if( nBuf>3 && 0==memcmp("eli", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt0(aBuf, nBuf-3) ){
- memcpy(&aBuf[nBuf-3], "e", 1);
- *pnBuf = nBuf - 3 + 1;
- }
- }else if( nBuf>5 && 0==memcmp("ousli", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "ous", 3);
- *pnBuf = nBuf - 5 + 3;
- }
- }
- break;
-
- case 'o':
- if( nBuf>7 && 0==memcmp("ization", &aBuf[nBuf-7], 7) ){
- if( fts5Porter_MGt0(aBuf, nBuf-7) ){
- memcpy(&aBuf[nBuf-7], "ize", 3);
- *pnBuf = nBuf - 7 + 3;
- }
- }else if( nBuf>5 && 0==memcmp("ation", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "ate", 3);
- *pnBuf = nBuf - 5 + 3;
- }
- }else if( nBuf>4 && 0==memcmp("ator", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt0(aBuf, nBuf-4) ){
- memcpy(&aBuf[nBuf-4], "ate", 3);
- *pnBuf = nBuf - 4 + 3;
- }
- }
- break;
-
- case 's':
- if( nBuf>5 && 0==memcmp("alism", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "al", 2);
- *pnBuf = nBuf - 5 + 2;
- }
- }else if( nBuf>7 && 0==memcmp("iveness", &aBuf[nBuf-7], 7) ){
- if( fts5Porter_MGt0(aBuf, nBuf-7) ){
- memcpy(&aBuf[nBuf-7], "ive", 3);
- *pnBuf = nBuf - 7 + 3;
- }
- }else if( nBuf>7 && 0==memcmp("fulness", &aBuf[nBuf-7], 7) ){
- if( fts5Porter_MGt0(aBuf, nBuf-7) ){
- memcpy(&aBuf[nBuf-7], "ful", 3);
- *pnBuf = nBuf - 7 + 3;
- }
- }else if( nBuf>7 && 0==memcmp("ousness", &aBuf[nBuf-7], 7) ){
- if( fts5Porter_MGt0(aBuf, nBuf-7) ){
- memcpy(&aBuf[nBuf-7], "ous", 3);
- *pnBuf = nBuf - 7 + 3;
- }
- }
- break;
-
- case 't':
- if( nBuf>5 && 0==memcmp("aliti", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "al", 2);
- *pnBuf = nBuf - 5 + 2;
- }
- }else if( nBuf>5 && 0==memcmp("iviti", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "ive", 3);
- *pnBuf = nBuf - 5 + 3;
- }
- }else if( nBuf>6 && 0==memcmp("biliti", &aBuf[nBuf-6], 6) ){
- if( fts5Porter_MGt0(aBuf, nBuf-6) ){
- memcpy(&aBuf[nBuf-6], "ble", 3);
- *pnBuf = nBuf - 6 + 3;
- }
- }
- break;
-
- }
- return ret;
-}
-
-
-static int fts5PorterStep3(char *aBuf, int *pnBuf){
- int ret = 0;
- int nBuf = *pnBuf;
- switch( aBuf[nBuf-2] ){
-
- case 'a':
- if( nBuf>4 && 0==memcmp("ical", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt0(aBuf, nBuf-4) ){
- memcpy(&aBuf[nBuf-4], "ic", 2);
- *pnBuf = nBuf - 4 + 2;
- }
- }
- break;
-
- case 's':
- if( nBuf>4 && 0==memcmp("ness", &aBuf[nBuf-4], 4) ){
- if( fts5Porter_MGt0(aBuf, nBuf-4) ){
- *pnBuf = nBuf - 4;
- }
- }
- break;
-
- case 't':
- if( nBuf>5 && 0==memcmp("icate", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "ic", 2);
- *pnBuf = nBuf - 5 + 2;
- }
- }else if( nBuf>5 && 0==memcmp("iciti", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "ic", 2);
- *pnBuf = nBuf - 5 + 2;
- }
- }
- break;
-
- case 'u':
- if( nBuf>3 && 0==memcmp("ful", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt0(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- }
- }
- break;
-
- case 'v':
- if( nBuf>5 && 0==memcmp("ative", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- *pnBuf = nBuf - 5;
- }
- }
- break;
-
- case 'z':
- if( nBuf>5 && 0==memcmp("alize", &aBuf[nBuf-5], 5) ){
- if( fts5Porter_MGt0(aBuf, nBuf-5) ){
- memcpy(&aBuf[nBuf-5], "al", 2);
- *pnBuf = nBuf - 5 + 2;
- }
- }
- break;
-
- }
- return ret;
-}
-
-
-static int fts5PorterStep1B(char *aBuf, int *pnBuf){
- int ret = 0;
- int nBuf = *pnBuf;
- switch( aBuf[nBuf-2] ){
-
- case 'e':
- if( nBuf>3 && 0==memcmp("eed", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_MGt0(aBuf, nBuf-3) ){
- memcpy(&aBuf[nBuf-3], "ee", 2);
- *pnBuf = nBuf - 3 + 2;
- }
- }else if( nBuf>2 && 0==memcmp("ed", &aBuf[nBuf-2], 2) ){
- if( fts5Porter_Vowel(aBuf, nBuf-2) ){
- *pnBuf = nBuf - 2;
- ret = 1;
- }
- }
- break;
-
- case 'n':
- if( nBuf>3 && 0==memcmp("ing", &aBuf[nBuf-3], 3) ){
- if( fts5Porter_Vowel(aBuf, nBuf-3) ){
- *pnBuf = nBuf - 3;
- ret = 1;
- }
- }
- break;
-
- }
- return ret;
-}
-
-/*
-** GENERATED CODE ENDS HERE (mkportersteps.tcl)
-***************************************************************************
-**************************************************************************/
-
-static void fts5PorterStep1A(char *aBuf, int *pnBuf){
- int nBuf = *pnBuf;
- if( aBuf[nBuf-1]=='s' ){
- if( aBuf[nBuf-2]=='e' ){
- if( (nBuf>4 && aBuf[nBuf-4]=='s' && aBuf[nBuf-3]=='s')
- || (nBuf>3 && aBuf[nBuf-3]=='i' )
- ){
- *pnBuf = nBuf-2;
- }else{
- *pnBuf = nBuf-1;
- }
- }
- else if( aBuf[nBuf-2]!='s' ){
- *pnBuf = nBuf-1;
- }
- }
-}
-
-static int fts5PorterCb(
- void *pCtx,
- int tflags,
- const char *pToken,
- int nToken,
- int iStart,
- int iEnd
-){
- PorterContext *p = (PorterContext*)pCtx;
-
- char *aBuf;
- int nBuf;
-
- if( nToken>FTS5_PORTER_MAX_TOKEN || nToken<3 ) goto pass_through;
- aBuf = p->aBuf;
- nBuf = nToken;
- memcpy(aBuf, pToken, nBuf);
-
- /* Step 1. */
- fts5PorterStep1A(aBuf, &nBuf);
- if( fts5PorterStep1B(aBuf, &nBuf) ){
- if( fts5PorterStep1B2(aBuf, &nBuf)==0 ){
- char c = aBuf[nBuf-1];
- if( fts5PorterIsVowel(c, 0)==0
- && c!='l' && c!='s' && c!='z' && c==aBuf[nBuf-2]
- ){
- nBuf--;
- }else if( fts5Porter_MEq1(aBuf, nBuf) && fts5Porter_Ostar(aBuf, nBuf) ){
- aBuf[nBuf++] = 'e';
- }
- }
- }
-
- /* Step 1C. */
- if( aBuf[nBuf-1]=='y' && fts5Porter_Vowel(aBuf, nBuf-1) ){
- aBuf[nBuf-1] = 'i';
- }
-
- /* Steps 2 through 4. */
- fts5PorterStep2(aBuf, &nBuf);
- fts5PorterStep3(aBuf, &nBuf);
- fts5PorterStep4(aBuf, &nBuf);
-
- /* Step 5a. */
- assert( nBuf>0 );
- if( aBuf[nBuf-1]=='e' ){
- if( fts5Porter_MGt1(aBuf, nBuf-1)
- || (fts5Porter_MEq1(aBuf, nBuf-1) && !fts5Porter_Ostar(aBuf, nBuf-1))
- ){
- nBuf--;
- }
- }
-
- /* Step 5b. */
- if( nBuf>1 && aBuf[nBuf-1]=='l'
- && aBuf[nBuf-2]=='l' && fts5Porter_MGt1(aBuf, nBuf-1)
- ){
- nBuf--;
- }
-
- return p->xToken(p->pCtx, tflags, aBuf, nBuf, iStart, iEnd);
-
- pass_through:
- return p->xToken(p->pCtx, tflags, pToken, nToken, iStart, iEnd);
-}
-
-/*
-** Tokenize using the porter tokenizer.
-*/
-static int fts5PorterTokenize(
- Fts5Tokenizer *pTokenizer,
- void *pCtx,
- int flags,
- const char *pText, int nText,
- int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd)
-){
- PorterTokenizer *p = (PorterTokenizer*)pTokenizer;
- PorterContext sCtx;
- sCtx.xToken = xToken;
- sCtx.pCtx = pCtx;
- sCtx.aBuf = p->aBuf;
- return p->tokenizer.xTokenize(
- p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
- );
-}
-
-/*
-** Register all built-in tokenizers with FTS5.
-*/
-int sqlite3Fts5TokenizerInit(fts5_api *pApi){
- struct BuiltinTokenizer {
- const char *zName;
- fts5_tokenizer x;
- } aBuiltin[] = {
- { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
- { "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
- { "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
- };
-
- int rc = SQLITE_OK; /* Return code */
- int i; /* To iterate through builtin functions */
-
- for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){
- rc = pApi->xCreateTokenizer(pApi,
- aBuiltin[i].zName,
- (void*)pApi,
- &aBuiltin[i].x,
- 0
- );
- }
-
- return rc;
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_unicode2.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_unicode2.c
deleted file mode 100644
index 1ef56f61567..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_unicode2.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
-** 2012 May 25
-**
-** 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.
-**
-******************************************************************************
-*/
-
-/*
-** DO NOT EDIT THIS MACHINE GENERATED FILE.
-*/
-
-
-#include <assert.h>
-
-/*
-** Return true if the argument corresponds to a unicode codepoint
-** classified as either a letter or a number. Otherwise false.
-**
-** The results are undefined if the value passed to this function
-** is less than zero.
-*/
-int sqlite3Fts5UnicodeIsalnum(int c){
- /* Each unsigned integer in the following array corresponds to a contiguous
- ** range of unicode codepoints that are not either letters or numbers (i.e.
- ** codepoints for which this function should return 0).
- **
- ** The most significant 22 bits in each 32-bit value contain the first
- ** codepoint in the range. The least significant 10 bits are used to store
- ** the size of the range (always at least 1). In other words, the value
- ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
- ** C. It is not possible to represent a range larger than 1023 codepoints
- ** using this format.
- */
- static const unsigned int aEntry[] = {
- 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
- 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
- 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
- 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
- 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
- 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
- 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
- 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401,
- 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804,
- 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403,
- 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812,
- 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001,
- 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802,
- 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805,
- 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401,
- 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
- 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807,
- 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001,
- 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01,
- 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804,
- 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001,
- 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802,
- 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01,
- 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06,
- 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007,
- 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006,
- 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417,
- 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14,
- 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07,
- 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01,
- 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001,
- 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802,
- 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F,
- 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
- 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802,
- 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006,
- 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D,
- 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802,
- 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027,
- 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
- 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805,
- 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04,
- 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
- 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
- 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B,
- 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A,
- 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
- 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59,
- 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
- 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
- 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
- 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
- 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
- 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
- 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
- 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012,
- 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
- 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002,
- 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
- 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
- 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
- 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802,
- 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013,
- 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06,
- 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003,
- 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01,
- 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403,
- 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009,
- 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003,
- 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003,
- 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E,
- 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046,
- 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401,
- 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401,
- 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F,
- 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C,
- 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002,
- 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025,
- 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6,
- 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46,
- 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060,
- 0x380400F0,
- };
- static const unsigned int aAscii[4] = {
- 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
- };
-
- if( (unsigned int)c<128 ){
- return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
- }else if( (unsigned int)c<(1<<22) ){
- unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
- int iRes = 0;
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
- int iLo = 0;
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( key >= aEntry[iTest] ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- assert( aEntry[0]<key );
- assert( key>=aEntry[iRes] );
- return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
- }
- return 1;
-}
-
-
-/*
-** If the argument is a codepoint corresponding to a lowercase letter
-** in the ASCII range with a diacritic added, return the codepoint
-** of the ASCII letter only. For example, if passed 235 - "LATIN
-** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
-** E"). The resuls of passing a codepoint that corresponds to an
-** uppercase letter are undefined.
-*/
-static int fts5_remove_diacritic(int c){
- unsigned short aDia[] = {
- 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
- 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
- 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
- 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
- 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
- 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
- 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
- 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
- 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
- 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
- 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
- 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
- 62924, 63050, 63082, 63274, 63390,
- };
- char aChar[] = {
- '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
- 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
- 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
- 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
- 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
- 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
- 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
- 'e', 'i', 'o', 'u', 'y',
- };
-
- unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
- int iRes = 0;
- int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
- int iLo = 0;
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( key >= aDia[iTest] ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- assert( key>=aDia[iRes] );
- return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
-}
-
-
-/*
-** Return true if the argument interpreted as a unicode codepoint
-** is a diacritical modifier character.
-*/
-int sqlite3Fts5UnicodeIsdiacritic(int c){
- unsigned int mask0 = 0x08029FDF;
- unsigned int mask1 = 0x000361F8;
- if( c<768 || c>817 ) return 0;
- return (c < 768+32) ?
- (mask0 & (1 << (c-768))) :
- (mask1 & (1 << (c-768-32)));
-}
-
-
-/*
-** Interpret the argument as a unicode codepoint. If the codepoint
-** is an upper case character that has a lower case equivalent,
-** return the codepoint corresponding to the lower case version.
-** Otherwise, return a copy of the argument.
-**
-** The results are undefined if the value passed to this function
-** is less than zero.
-*/
-int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
- /* Each entry in the following array defines a rule for folding a range
- ** of codepoints to lower case. The rule applies to a range of nRange
- ** codepoints starting at codepoint iCode.
- **
- ** If the least significant bit in flags is clear, then the rule applies
- ** to all nRange codepoints (i.e. all nRange codepoints are upper case and
- ** need to be folded). Or, if it is set, then the rule only applies to
- ** every second codepoint in the range, starting with codepoint C.
- **
- ** The 7 most significant bits in flags are an index into the aiOff[]
- ** array. If a specific codepoint C does require folding, then its lower
- ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF).
- **
- ** The contents of this array are generated by parsing the CaseFolding.txt
- ** file distributed as part of the "Unicode Character Database". See
- ** http://www.unicode.org for details.
- */
- static const struct TableEntry {
- unsigned short iCode;
- unsigned char flags;
- unsigned char nRange;
- } aEntry[] = {
- {65, 14, 26}, {181, 64, 1}, {192, 14, 23},
- {216, 14, 7}, {256, 1, 48}, {306, 1, 6},
- {313, 1, 16}, {330, 1, 46}, {376, 116, 1},
- {377, 1, 6}, {383, 104, 1}, {385, 50, 1},
- {386, 1, 4}, {390, 44, 1}, {391, 0, 1},
- {393, 42, 2}, {395, 0, 1}, {398, 32, 1},
- {399, 38, 1}, {400, 40, 1}, {401, 0, 1},
- {403, 42, 1}, {404, 46, 1}, {406, 52, 1},
- {407, 48, 1}, {408, 0, 1}, {412, 52, 1},
- {413, 54, 1}, {415, 56, 1}, {416, 1, 6},
- {422, 60, 1}, {423, 0, 1}, {425, 60, 1},
- {428, 0, 1}, {430, 60, 1}, {431, 0, 1},
- {433, 58, 2}, {435, 1, 4}, {439, 62, 1},
- {440, 0, 1}, {444, 0, 1}, {452, 2, 1},
- {453, 0, 1}, {455, 2, 1}, {456, 0, 1},
- {458, 2, 1}, {459, 1, 18}, {478, 1, 18},
- {497, 2, 1}, {498, 1, 4}, {502, 122, 1},
- {503, 134, 1}, {504, 1, 40}, {544, 110, 1},
- {546, 1, 18}, {570, 70, 1}, {571, 0, 1},
- {573, 108, 1}, {574, 68, 1}, {577, 0, 1},
- {579, 106, 1}, {580, 28, 1}, {581, 30, 1},
- {582, 1, 10}, {837, 36, 1}, {880, 1, 4},
- {886, 0, 1}, {902, 18, 1}, {904, 16, 3},
- {908, 26, 1}, {910, 24, 2}, {913, 14, 17},
- {931, 14, 9}, {962, 0, 1}, {975, 4, 1},
- {976, 140, 1}, {977, 142, 1}, {981, 146, 1},
- {982, 144, 1}, {984, 1, 24}, {1008, 136, 1},
- {1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1},
- {1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1},
- {1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32},
- {1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1},
- {1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38},
- {4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1},
- {7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1},
- {7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6},
- {7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6},
- {8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8},
- {8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2},
- {8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1},
- {8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2},
- {8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2},
- {8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2},
- {8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1},
- {8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16},
- {8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47},
- {11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1},
- {11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1},
- {11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1},
- {11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2},
- {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1},
- {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14},
- {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1},
- {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1},
- {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1},
- {65313, 14, 26},
- };
- static const unsigned short aiOff[] = {
- 1, 2, 8, 15, 16, 26, 28, 32,
- 37, 38, 40, 48, 63, 64, 69, 71,
- 79, 80, 116, 202, 203, 205, 206, 207,
- 209, 210, 211, 213, 214, 217, 218, 219,
- 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721,
- 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274,
- 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406,
- 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462,
- 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511,
- 65514, 65521, 65527, 65528, 65529,
- };
-
- int ret = c;
-
- assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
-
- if( c<128 ){
- if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
- }else if( c<65536 ){
- const struct TableEntry *p;
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
- int iLo = 0;
- int iRes = -1;
-
- assert( c>aEntry[0].iCode );
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- int cmp = (c - aEntry[iTest].iCode);
- if( cmp>=0 ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
-
- assert( iRes>=0 && c>=aEntry[iRes].iCode );
- p = &aEntry[iRes];
- if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
- ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
- assert( ret>0 );
- }
-
- if( bRemoveDiacritic ) ret = fts5_remove_diacritic(ret);
- }
-
- else if( c>=66560 && c<66600 ){
- ret = c + 40;
- }
-
- return ret;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_varint.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_varint.c
deleted file mode 100644
index bb212ab5a8a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_varint.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
-** 2015 May 30
-**
-** 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.
-**
-******************************************************************************
-**
-** Routines for varint serialization and deserialization.
-*/
-
-
-#include "fts5Int.h"
-
-/*
-** This is a copy of the sqlite3GetVarint32() routine from the SQLite core.
-** Except, this version does handle the single byte case that the core
-** version depends on being handled before its function is called.
-*/
-int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v){
- u32 a,b;
-
- /* The 1-byte case. Overwhelmingly the most common. */
- a = *p;
- /* a: p0 (unmasked) */
- if (!(a&0x80))
- {
- /* Values between 0 and 127 */
- *v = a;
- return 1;
- }
-
- /* The 2-byte case */
- p++;
- b = *p;
- /* b: p1 (unmasked) */
- if (!(b&0x80))
- {
- /* Values between 128 and 16383 */
- a &= 0x7f;
- a = a<<7;
- *v = a | b;
- return 2;
- }
-
- /* The 3-byte case */
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<14 | p2 (unmasked) */
- if (!(a&0x80))
- {
- /* Values between 16384 and 2097151 */
- a &= (0x7f<<14)|(0x7f);
- b &= 0x7f;
- b = b<<7;
- *v = a | b;
- return 3;
- }
-
- /* A 32-bit varint is used to store size information in btrees.
- ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
- ** A 3-byte varint is sufficient, for example, to record the size
- ** of a 1048569-byte BLOB or string.
- **
- ** We only unroll the first 1-, 2-, and 3- byte cases. The very
- ** rare larger cases can be handled by the slower 64-bit varint
- ** routine.
- */
- {
- u64 v64;
- u8 n;
- p -= 2;
- n = sqlite3Fts5GetVarint(p, &v64);
- *v = (u32)v64;
- assert( n>3 && n<=9 );
- return n;
- }
-}
-
-
-/*
-** Bitmasks used by sqlite3GetVarint(). These precomputed constants
-** are defined here rather than simply putting the constant expressions
-** inline in order to work around bugs in the RVT compiler.
-**
-** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
-**
-** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
-*/
-#define SLOT_2_0 0x001fc07f
-#define SLOT_4_2_0 0xf01fc07f
-
-/*
-** Read a 64-bit variable-length integer from memory starting at p[0].
-** Return the number of bytes read. The value is stored in *v.
-*/
-u8 sqlite3Fts5GetVarint(const unsigned char *p, u64 *v){
- u32 a,b,s;
-
- a = *p;
- /* a: p0 (unmasked) */
- if (!(a&0x80))
- {
- *v = a;
- return 1;
- }
-
- p++;
- b = *p;
- /* b: p1 (unmasked) */
- if (!(b&0x80))
- {
- a &= 0x7f;
- a = a<<7;
- a |= b;
- *v = a;
- return 2;
- }
-
- /* Verify that constants are precomputed correctly */
- assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
- assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<14 | p2 (unmasked) */
- if (!(a&0x80))
- {
- a &= SLOT_2_0;
- b &= 0x7f;
- b = b<<7;
- a |= b;
- *v = a;
- return 3;
- }
-
- /* CSE1 from below */
- a &= SLOT_2_0;
- p++;
- b = b<<14;
- b |= *p;
- /* b: p1<<14 | p3 (unmasked) */
- if (!(b&0x80))
- {
- b &= SLOT_2_0;
- /* moved CSE1 up */
- /* a &= (0x7f<<14)|(0x7f); */
- a = a<<7;
- a |= b;
- *v = a;
- return 4;
- }
-
- /* a: p0<<14 | p2 (masked) */
- /* b: p1<<14 | p3 (unmasked) */
- /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
- /* moved CSE1 up */
- /* a &= (0x7f<<14)|(0x7f); */
- b &= SLOT_2_0;
- s = a;
- /* s: p0<<14 | p2 (masked) */
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<28 | p2<<14 | p4 (unmasked) */
- if (!(a&0x80))
- {
- /* we can skip these cause they were (effectively) done above in calc'ing s */
- /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
- /* b &= (0x7f<<14)|(0x7f); */
- b = b<<7;
- a |= b;
- s = s>>18;
- *v = ((u64)s)<<32 | a;
- return 5;
- }
-
- /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
- s = s<<7;
- s |= b;
- /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
-
- p++;
- b = b<<14;
- b |= *p;
- /* b: p1<<28 | p3<<14 | p5 (unmasked) */
- if (!(b&0x80))
- {
- /* we can skip this cause it was (effectively) done above in calc'ing s */
- /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
- a &= SLOT_2_0;
- a = a<<7;
- a |= b;
- s = s>>18;
- *v = ((u64)s)<<32 | a;
- return 6;
- }
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p2<<28 | p4<<14 | p6 (unmasked) */
- if (!(a&0x80))
- {
- a &= SLOT_4_2_0;
- b &= SLOT_2_0;
- b = b<<7;
- a |= b;
- s = s>>11;
- *v = ((u64)s)<<32 | a;
- return 7;
- }
-
- /* CSE2 from below */
- a &= SLOT_2_0;
- p++;
- b = b<<14;
- b |= *p;
- /* b: p3<<28 | p5<<14 | p7 (unmasked) */
- if (!(b&0x80))
- {
- b &= SLOT_4_2_0;
- /* moved CSE2 up */
- /* a &= (0x7f<<14)|(0x7f); */
- a = a<<7;
- a |= b;
- s = s>>4;
- *v = ((u64)s)<<32 | a;
- return 8;
- }
-
- p++;
- a = a<<15;
- a |= *p;
- /* a: p4<<29 | p6<<15 | p8 (unmasked) */
-
- /* moved CSE2 up */
- /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
- b &= SLOT_2_0;
- b = b<<8;
- a |= b;
-
- s = s<<4;
- b = p[-4];
- b &= 0x7f;
- b = b>>3;
- s |= b;
-
- *v = ((u64)s)<<32 | a;
-
- return 9;
-}
-
-/*
-** The variable-length integer encoding is as follows:
-**
-** KEY:
-** A = 0xxxxxxx 7 bits of data and one flag bit
-** B = 1xxxxxxx 7 bits of data and one flag bit
-** C = xxxxxxxx 8 bits of data
-**
-** 7 bits - A
-** 14 bits - BA
-** 21 bits - BBA
-** 28 bits - BBBA
-** 35 bits - BBBBA
-** 42 bits - BBBBBA
-** 49 bits - BBBBBBA
-** 56 bits - BBBBBBBA
-** 64 bits - BBBBBBBBC
-*/
-
-#ifdef SQLITE_NOINLINE
-# define FTS5_NOINLINE SQLITE_NOINLINE
-#else
-# define FTS5_NOINLINE
-#endif
-
-/*
-** Write a 64-bit variable-length integer to memory starting at p[0].
-** The length of data write will be between 1 and 9 bytes. The number
-** of bytes written is returned.
-**
-** A variable-length integer consists of the lower 7 bits of each byte
-** for all bytes that have the 8th bit set and one byte with the 8th
-** bit clear. Except, if we get to the 9th byte, it stores the full
-** 8 bits and is the last byte.
-*/
-static int FTS5_NOINLINE fts5PutVarint64(unsigned char *p, u64 v){
- int i, j, n;
- u8 buf[10];
- if( v & (((u64)0xff000000)<<32) ){
- p[8] = (u8)v;
- v >>= 8;
- for(i=7; i>=0; i--){
- p[i] = (u8)((v & 0x7f) | 0x80);
- v >>= 7;
- }
- return 9;
- }
- n = 0;
- do{
- buf[n++] = (u8)((v & 0x7f) | 0x80);
- v >>= 7;
- }while( v!=0 );
- buf[0] &= 0x7f;
- assert( n<=9 );
- for(i=0, j=n-1; j>=0; j--, i++){
- p[i] = buf[j];
- }
- return n;
-}
-
-int sqlite3Fts5PutVarint(unsigned char *p, u64 v){
- if( v<=0x7f ){
- p[0] = v&0x7f;
- return 1;
- }
- if( v<=0x3fff ){
- p[0] = ((v>>7)&0x7f)|0x80;
- p[1] = v&0x7f;
- return 2;
- }
- return fts5PutVarint64(p,v);
-}
-
-
-int sqlite3Fts5GetVarintLen(u32 iVal){
-#if 0
- if( iVal<(1 << 7 ) ) return 1;
-#endif
- assert( iVal>=(1 << 7) );
- if( iVal<(1 << 14) ) return 2;
- if( iVal<(1 << 21) ) return 3;
- if( iVal<(1 << 28) ) return 4;
- return 5;
-}
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_vocab.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_vocab.c
deleted file mode 100644
index 27f2ff3b2c1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5_vocab.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
-** 2015 May 08
-**
-** 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 is an SQLite virtual table module implementing direct access to an
-** existing FTS5 index. The module may create several different types of
-** tables:
-**
-** col:
-** CREATE TABLE vocab(term, col, doc, cnt, PRIMARY KEY(term, col));
-**
-** One row for each term/column combination. The value of $doc is set to
-** the number of fts5 rows that contain at least one instance of term
-** $term within column $col. Field $cnt is set to the total number of
-** instances of term $term in column $col (in any row of the fts5 table).
-**
-** row:
-** CREATE TABLE vocab(term, doc, cnt, PRIMARY KEY(term));
-**
-** One row for each term in the database. The value of $doc is set to
-** the number of fts5 rows that contain at least one instance of term
-** $term. Field $cnt is set to the total number of instances of term
-** $term in the database.
-**
-** instance:
-** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY(<all-fields>));
-**
-** One row for each term instance in the database.
-*/
-
-
-#include "fts5Int.h"
-
-
-typedef struct Fts5VocabTable Fts5VocabTable;
-typedef struct Fts5VocabCursor Fts5VocabCursor;
-
-struct Fts5VocabTable {
- sqlite3_vtab base;
- char *zFts5Tbl; /* Name of fts5 table */
- char *zFts5Db; /* Db containing fts5 table */
- sqlite3 *db; /* Database handle */
- Fts5Global *pGlobal; /* FTS5 global object for this database */
- int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
-};
-
-struct Fts5VocabCursor {
- sqlite3_vtab_cursor base;
- sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
- Fts5Index *pIndex; /* Associated FTS5 index */
-
- int bEof; /* True if this cursor is at EOF */
- Fts5IndexIter *pIter; /* Term/rowid iterator object */
-
- int nLeTerm; /* Size of zLeTerm in bytes */
- char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
-
- /* These are used by 'col' tables only */
- Fts5Config *pConfig; /* Fts5 table configuration */
- int iCol;
- i64 *aCnt;
- i64 *aDoc;
-
- /* Output values used by all tables. */
- i64 rowid; /* This table's current rowid value */
- Fts5Buffer term; /* Current value of 'term' column */
-
- /* Output values Used by 'instance' tables only */
- i64 iInstPos;
- int iInstOff;
-};
-
-#define FTS5_VOCAB_COL 0
-#define FTS5_VOCAB_ROW 1
-#define FTS5_VOCAB_INSTANCE 2
-
-#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
-#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
-#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
-
-/*
-** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
-*/
-#define FTS5_VOCAB_TERM_EQ 0x01
-#define FTS5_VOCAB_TERM_GE 0x02
-#define FTS5_VOCAB_TERM_LE 0x04
-
-
-/*
-** Translate a string containing an fts5vocab table type to an
-** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
-** value and return SQLITE_OK. Otherwise, set *pzErr to an error message
-** and return SQLITE_ERROR.
-*/
-static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){
- int rc = SQLITE_OK;
- char *zCopy = sqlite3Fts5Strndup(&rc, zType, -1);
- if( rc==SQLITE_OK ){
- sqlite3Fts5Dequote(zCopy);
- if( sqlite3_stricmp(zCopy, "col")==0 ){
- *peType = FTS5_VOCAB_COL;
- }else
-
- if( sqlite3_stricmp(zCopy, "row")==0 ){
- *peType = FTS5_VOCAB_ROW;
- }else
- if( sqlite3_stricmp(zCopy, "instance")==0 ){
- *peType = FTS5_VOCAB_INSTANCE;
- }else
- {
- *pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy);
- rc = SQLITE_ERROR;
- }
- sqlite3_free(zCopy);
- }
-
- return rc;
-}
-
-
-/*
-** The xDisconnect() virtual table method.
-*/
-static int fts5VocabDisconnectMethod(sqlite3_vtab *pVtab){
- Fts5VocabTable *pTab = (Fts5VocabTable*)pVtab;
- sqlite3_free(pTab);
- return SQLITE_OK;
-}
-
-/*
-** The xDestroy() virtual table method.
-*/
-static int fts5VocabDestroyMethod(sqlite3_vtab *pVtab){
- Fts5VocabTable *pTab = (Fts5VocabTable*)pVtab;
- sqlite3_free(pTab);
- return SQLITE_OK;
-}
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the FTS3 virtual table.
-**
-** The argv[] array contains the following:
-**
-** argv[0] -> module name ("fts5vocab")
-** argv[1] -> database name
-** argv[2] -> table name
-**
-** then:
-**
-** argv[3] -> name of fts5 table
-** argv[4] -> type of fts5vocab table
-**
-** or, for tables in the TEMP schema only.
-**
-** argv[3] -> name of fts5 tables database
-** argv[4] -> name of fts5 table
-** argv[5] -> type of fts5vocab table
-*/
-static int fts5VocabInitVtab(
- sqlite3 *db, /* The SQLite database connection */
- void *pAux, /* Pointer to Fts5Global object */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
- char **pzErr /* Write any error message here */
-){
- const char *azSchema[] = {
- "CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")",
- "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")",
- "CREATE TABlE vocab(" FTS5_VOCAB_INST_SCHEMA ")"
- };
-
- Fts5VocabTable *pRet = 0;
- int rc = SQLITE_OK; /* Return code */
- int bDb;
-
- bDb = (argc==6 && strlen(argv[1])==4 && memcmp("temp", argv[1], 4)==0);
-
- if( argc!=5 && bDb==0 ){
- *pzErr = sqlite3_mprintf("wrong number of vtable arguments");
- rc = SQLITE_ERROR;
- }else{
- int nByte; /* Bytes of space to allocate */
- const char *zDb = bDb ? argv[3] : argv[1];
- const char *zTab = bDb ? argv[4] : argv[3];
- const char *zType = bDb ? argv[5] : argv[4];
- int nDb = (int)strlen(zDb)+1;
- int nTab = (int)strlen(zTab)+1;
- int eType = 0;
-
- rc = fts5VocabTableType(zType, pzErr, &eType);
- if( rc==SQLITE_OK ){
- assert( eType>=0 && eType<ArraySize(azSchema) );
- rc = sqlite3_declare_vtab(db, azSchema[eType]);
- }
-
- nByte = sizeof(Fts5VocabTable) + nDb + nTab;
- pRet = sqlite3Fts5MallocZero(&rc, nByte);
- if( pRet ){
- pRet->pGlobal = (Fts5Global*)pAux;
- pRet->eType = eType;
- pRet->db = db;
- pRet->zFts5Tbl = (char*)&pRet[1];
- pRet->zFts5Db = &pRet->zFts5Tbl[nTab];
- memcpy(pRet->zFts5Tbl, zTab, nTab);
- memcpy(pRet->zFts5Db, zDb, nDb);
- sqlite3Fts5Dequote(pRet->zFts5Tbl);
- sqlite3Fts5Dequote(pRet->zFts5Db);
- }
- }
-
- *ppVTab = (sqlite3_vtab*)pRet;
- return rc;
-}
-
-
-/*
-** The xConnect() and xCreate() methods for the virtual table. All the
-** work is done in function fts5VocabInitVtab().
-*/
-static int fts5VocabConnectMethod(
- sqlite3 *db, /* Database connection */
- void *pAux, /* Pointer to tokenizer hash table */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- return fts5VocabInitVtab(db, pAux, argc, argv, ppVtab, pzErr);
-}
-static int fts5VocabCreateMethod(
- sqlite3 *db, /* Database connection */
- void *pAux, /* Pointer to tokenizer hash table */
- int argc, /* Number of elements in argv array */
- const char * const *argv, /* xCreate/xConnect argument array */
- sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
- char **pzErr /* OUT: sqlite3_malloc'd error message */
-){
- return fts5VocabInitVtab(db, pAux, argc, argv, ppVtab, pzErr);
-}
-
-/*
-** Implementation of the xBestIndex method.
-**
-** Only constraints of the form:
-**
-** term <= ?
-** term == ?
-** term >= ?
-**
-** are interpreted. Less-than and less-than-or-equal are treated
-** identically, as are greater-than and greater-than-or-equal.
-*/
-static int fts5VocabBestIndexMethod(
- sqlite3_vtab *pUnused,
- sqlite3_index_info *pInfo
-){
- int i;
- int iTermEq = -1;
- int iTermGe = -1;
- int iTermLe = -1;
- int idxNum = 0;
- int nArg = 0;
-
- UNUSED_PARAM(pUnused);
-
- for(i=0; i<pInfo->nConstraint; i++){
- struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
- if( p->usable==0 ) continue;
- if( p->iColumn==0 ){ /* term column */
- if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i;
- if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i;
- if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i;
- if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i;
- if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i;
- }
- }
-
- if( iTermEq>=0 ){
- idxNum |= FTS5_VOCAB_TERM_EQ;
- pInfo->aConstraintUsage[iTermEq].argvIndex = ++nArg;
- pInfo->estimatedCost = 100;
- }else{
- pInfo->estimatedCost = 1000000;
- if( iTermGe>=0 ){
- idxNum |= FTS5_VOCAB_TERM_GE;
- pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg;
- pInfo->estimatedCost = pInfo->estimatedCost / 2;
- }
- if( iTermLe>=0 ){
- idxNum |= FTS5_VOCAB_TERM_LE;
- pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg;
- pInfo->estimatedCost = pInfo->estimatedCost / 2;
- }
- }
-
- /* This virtual table always delivers results in ascending order of
- ** the "term" column (column 0). So if the user has requested this
- ** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the
- ** sqlite3_index_info.orderByConsumed flag to tell the core the results
- ** are already in sorted order. */
- if( pInfo->nOrderBy==1
- && pInfo->aOrderBy[0].iColumn==0
- && pInfo->aOrderBy[0].desc==0
- ){
- pInfo->orderByConsumed = 1;
- }
-
- pInfo->idxNum = idxNum;
- return SQLITE_OK;
-}
-
-/*
-** Implementation of xOpen method.
-*/
-static int fts5VocabOpenMethod(
- sqlite3_vtab *pVTab,
- sqlite3_vtab_cursor **ppCsr
-){
- Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
- Fts5Index *pIndex = 0;
- Fts5Config *pConfig = 0;
- Fts5VocabCursor *pCsr = 0;
- int rc = SQLITE_OK;
- sqlite3_stmt *pStmt = 0;
- char *zSql = 0;
-
- zSql = sqlite3Fts5Mprintf(&rc,
- "SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
- pTab->zFts5Tbl, pTab->zFts5Db, pTab->zFts5Tbl, pTab->zFts5Tbl
- );
- if( zSql ){
- rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
- }
- sqlite3_free(zSql);
- assert( rc==SQLITE_OK || pStmt==0 );
- if( rc==SQLITE_ERROR ) rc = SQLITE_OK;
-
- if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
- i64 iId = sqlite3_column_int64(pStmt, 0);
- pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
- }
-
- if( rc==SQLITE_OK && pIndex==0 ){
- rc = sqlite3_finalize(pStmt);
- pStmt = 0;
- if( rc==SQLITE_OK ){
- pVTab->zErrMsg = sqlite3_mprintf(
- "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
- );
- rc = SQLITE_ERROR;
- }
- }
-
- if( rc==SQLITE_OK ){
- int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
- pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
- }
-
- if( pCsr ){
- pCsr->pIndex = pIndex;
- pCsr->pStmt = pStmt;
- pCsr->pConfig = pConfig;
- pCsr->aCnt = (i64*)&pCsr[1];
- pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
- }else{
- sqlite3_finalize(pStmt);
- }
-
- *ppCsr = (sqlite3_vtab_cursor*)pCsr;
- return rc;
-}
-
-static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
- pCsr->rowid = 0;
- sqlite3Fts5IterClose(pCsr->pIter);
- pCsr->pIter = 0;
- sqlite3_free(pCsr->zLeTerm);
- pCsr->nLeTerm = -1;
- pCsr->zLeTerm = 0;
-}
-
-/*
-** Close the cursor. For additional information see the documentation
-** on the xClose method of the virtual table interface.
-*/
-static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){
- Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
- fts5VocabResetCursor(pCsr);
- sqlite3Fts5BufferFree(&pCsr->term);
- sqlite3_finalize(pCsr->pStmt);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
- int rc = SQLITE_OK;
-
- if( sqlite3Fts5IterEof(pCsr->pIter) ){
- pCsr->bEof = 1;
- }else{
- const char *zTerm;
- int nTerm;
- zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
- if( pCsr->nLeTerm>=0 ){
- int nCmp = MIN(nTerm, pCsr->nLeTerm);
- int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
- if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
- pCsr->bEof = 1;
- }
- }
-
- sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
- }
- return rc;
-}
-
-static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
- int eDetail = pCsr->pConfig->eDetail;
- int rc = SQLITE_OK;
- Fts5IndexIter *pIter = pCsr->pIter;
- i64 *pp = &pCsr->iInstPos;
- int *po = &pCsr->iInstOff;
-
- while( eDetail==FTS5_DETAIL_NONE
- || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
- ){
- pCsr->iInstPos = 0;
- pCsr->iInstOff = 0;
-
- rc = sqlite3Fts5IterNextScan(pCsr->pIter);
- if( rc==SQLITE_OK ){
- rc = fts5VocabInstanceNewTerm(pCsr);
- if( eDetail==FTS5_DETAIL_NONE ) break;
- }
- if( rc ){
- pCsr->bEof = 1;
- break;
- }
- }
-
- return rc;
-}
-
-/*
-** Advance the cursor to the next row in the table.
-*/
-static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
- Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
- Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
- int rc = SQLITE_OK;
- int nCol = pCsr->pConfig->nCol;
-
- pCsr->rowid++;
-
- if( pTab->eType==FTS5_VOCAB_INSTANCE ){
- return fts5VocabInstanceNext(pCsr);
- }
-
- if( pTab->eType==FTS5_VOCAB_COL ){
- for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
- if( pCsr->aDoc[pCsr->iCol] ) break;
- }
- }
-
- if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){
- if( sqlite3Fts5IterEof(pCsr->pIter) ){
- pCsr->bEof = 1;
- }else{
- const char *zTerm;
- int nTerm;
-
- zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
- if( pCsr->nLeTerm>=0 ){
- int nCmp = MIN(nTerm, pCsr->nLeTerm);
- int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
- if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
- pCsr->bEof = 1;
- return SQLITE_OK;
- }
- }
-
- sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
- memset(pCsr->aCnt, 0, nCol * sizeof(i64));
- memset(pCsr->aDoc, 0, nCol * sizeof(i64));
- pCsr->iCol = 0;
-
- assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
- while( rc==SQLITE_OK ){
- int eDetail = pCsr->pConfig->eDetail;
- const u8 *pPos; int nPos; /* Position list */
- i64 iPos = 0; /* 64-bit position read from poslist */
- int iOff = 0; /* Current offset within position list */
-
- pPos = pCsr->pIter->pData;
- nPos = pCsr->pIter->nData;
-
- switch( pTab->eType ){
- case FTS5_VOCAB_ROW:
- if( eDetail==FTS5_DETAIL_FULL ){
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
- pCsr->aCnt[0]++;
- }
- }
- pCsr->aDoc[0]++;
- break;
-
- case FTS5_VOCAB_COL:
- if( eDetail==FTS5_DETAIL_FULL ){
- int iCol = -1;
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
- int ii = FTS5_POS2COLUMN(iPos);
- pCsr->aCnt[ii]++;
- if( iCol!=ii ){
- if( ii>=nCol ){
- rc = FTS5_CORRUPT;
- break;
- }
- pCsr->aDoc[ii]++;
- iCol = ii;
- }
- }
- }else if( eDetail==FTS5_DETAIL_COLUMNS ){
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
- assert_nc( iPos>=0 && iPos<nCol );
- if( iPos>=nCol ){
- rc = FTS5_CORRUPT;
- break;
- }
- pCsr->aDoc[iPos]++;
- }
- }else{
- assert( eDetail==FTS5_DETAIL_NONE );
- pCsr->aDoc[0]++;
- }
- break;
-
- default:
- assert( pTab->eType==FTS5_VOCAB_INSTANCE );
- break;
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IterNextScan(pCsr->pIter);
- }
- if( pTab->eType==FTS5_VOCAB_INSTANCE ) break;
-
- if( rc==SQLITE_OK ){
- zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
- if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
- break;
- }
- if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
- }
- }
- }
- }
-
- if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
- while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++;
- assert( pCsr->iCol<pCsr->pConfig->nCol );
- }
- return rc;
-}
-
-/*
-** This is the xFilter implementation for the virtual table.
-*/
-static int fts5VocabFilterMethod(
- sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
- int idxNum, /* Strategy index */
- const char *zUnused, /* Unused */
- int nUnused, /* Number of elements in apVal */
- sqlite3_value **apVal /* Arguments for the indexing scheme */
-){
- Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
- Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
- int eType = pTab->eType;
- int rc = SQLITE_OK;
-
- int iVal = 0;
- int f = FTS5INDEX_QUERY_SCAN;
- const char *zTerm = 0;
- int nTerm = 0;
-
- sqlite3_value *pEq = 0;
- sqlite3_value *pGe = 0;
- sqlite3_value *pLe = 0;
-
- UNUSED_PARAM2(zUnused, nUnused);
-
- fts5VocabResetCursor(pCsr);
- if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
- if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
- if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
-
- if( pEq ){
- zTerm = (const char *)sqlite3_value_text(pEq);
- nTerm = sqlite3_value_bytes(pEq);
- f = 0;
- }else{
- if( pGe ){
- zTerm = (const char *)sqlite3_value_text(pGe);
- nTerm = sqlite3_value_bytes(pGe);
- }
- if( pLe ){
- const char *zCopy = (const char *)sqlite3_value_text(pLe);
- pCsr->nLeTerm = sqlite3_value_bytes(pLe);
- pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
- if( pCsr->zLeTerm==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1);
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
- }
- if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
- rc = fts5VocabInstanceNewTerm(pCsr);
- }
- if( rc==SQLITE_OK
- && !pCsr->bEof
- && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
- ){
- rc = fts5VocabNextMethod(pCursor);
- }
-
- return rc;
-}
-
-/*
-** This is the xEof method of the virtual table. SQLite calls this
-** routine to find out if it has reached the end of a result set.
-*/
-static int fts5VocabEofMethod(sqlite3_vtab_cursor *pCursor){
- Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
- return pCsr->bEof;
-}
-
-static int fts5VocabColumnMethod(
- sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
- int iCol /* Index of column to read value from */
-){
- Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
- int eDetail = pCsr->pConfig->eDetail;
- int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
- i64 iVal = 0;
-
- if( iCol==0 ){
- sqlite3_result_text(
- pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
- );
- }else if( eType==FTS5_VOCAB_COL ){
- assert( iCol==1 || iCol==2 || iCol==3 );
- if( iCol==1 ){
- if( eDetail!=FTS5_DETAIL_NONE ){
- const char *z = pCsr->pConfig->azCol[pCsr->iCol];
- sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
- }
- }else if( iCol==2 ){
- iVal = pCsr->aDoc[pCsr->iCol];
- }else{
- iVal = pCsr->aCnt[pCsr->iCol];
- }
- }else if( eType==FTS5_VOCAB_ROW ){
- assert( iCol==1 || iCol==2 );
- if( iCol==1 ){
- iVal = pCsr->aDoc[0];
- }else{
- iVal = pCsr->aCnt[0];
- }
- }else{
- assert( eType==FTS5_VOCAB_INSTANCE );
- switch( iCol ){
- case 1:
- sqlite3_result_int64(pCtx, pCsr->pIter->iRowid);
- break;
- case 2: {
- int ii = -1;
- if( eDetail==FTS5_DETAIL_FULL ){
- ii = FTS5_POS2COLUMN(pCsr->iInstPos);
- }else if( eDetail==FTS5_DETAIL_COLUMNS ){
- ii = (int)pCsr->iInstPos;
- }
- if( ii>=0 && ii<pCsr->pConfig->nCol ){
- const char *z = pCsr->pConfig->azCol[ii];
- sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
- }
- break;
- }
- default: {
- assert( iCol==3 );
- if( eDetail==FTS5_DETAIL_FULL ){
- int ii = FTS5_POS2OFFSET(pCsr->iInstPos);
- sqlite3_result_int(pCtx, ii);
- }
- break;
- }
- }
- }
-
- if( iVal>0 ) sqlite3_result_int64(pCtx, iVal);
- return SQLITE_OK;
-}
-
-/*
-** This is the xRowid method. The SQLite core calls this routine to
-** retrieve the rowid for the current row of the result set. The
-** rowid should be written to *pRowid.
-*/
-static int fts5VocabRowidMethod(
- sqlite3_vtab_cursor *pCursor,
- sqlite_int64 *pRowid
-){
- Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
- *pRowid = pCsr->rowid;
- return SQLITE_OK;
-}
-
-int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
- static const sqlite3_module fts5Vocab = {
- /* iVersion */ 2,
- /* xCreate */ fts5VocabCreateMethod,
- /* xConnect */ fts5VocabConnectMethod,
- /* xBestIndex */ fts5VocabBestIndexMethod,
- /* xDisconnect */ fts5VocabDisconnectMethod,
- /* xDestroy */ fts5VocabDestroyMethod,
- /* xOpen */ fts5VocabOpenMethod,
- /* xClose */ fts5VocabCloseMethod,
- /* xFilter */ fts5VocabFilterMethod,
- /* xNext */ fts5VocabNextMethod,
- /* xEof */ fts5VocabEofMethod,
- /* xColumn */ fts5VocabColumnMethod,
- /* xRowid */ fts5VocabRowidMethod,
- /* xUpdate */ 0,
- /* xBegin */ 0,
- /* xSync */ 0,
- /* xCommit */ 0,
- /* xRollback */ 0,
- /* xFindFunction */ 0,
- /* xRename */ 0,
- /* xSavepoint */ 0,
- /* xRelease */ 0,
- /* xRollbackTo */ 0,
- };
- void *p = (void*)pGlobal;
-
- return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0);
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5parse.y b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5parse.y
deleted file mode 100644
index 134125db1fa..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/fts5parse.y
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-** 2014 May 31
-**
-** 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.
-**
-******************************************************************************
-**
-*/
-
-
-// All token codes are small integers with #defines that begin with "TK_"
-%token_prefix FTS5_
-
-// The type of the data attached to each token is Token. This is also the
-// default type for non-terminals.
-//
-%token_type {Fts5Token}
-%default_type {Fts5Token}
-
-// The generated parser function takes a 4th argument as follows:
-%extra_argument {Fts5Parse *pParse}
-
-// This code runs whenever there is a syntax error
-//
-%syntax_error {
- UNUSED_PARAM(yymajor); /* Silence a compiler warning */
- sqlite3Fts5ParseError(
- pParse, "fts5: syntax error near \"%.*s\"",TOKEN.n,TOKEN.p
- );
-}
-%stack_overflow {
- sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow");
-}
-
-// The name of the generated procedure that implements the parser
-// is as follows:
-%name sqlite3Fts5Parser
-
-// The following text is included near the beginning of the C source
-// code file that implements the parser.
-//
-%include {
-#include "fts5Int.h"
-#include "fts5parse.h"
-
-/*
-** Disable all error recovery processing in the parser push-down
-** automaton.
-*/
-#define YYNOERRORRECOVERY 1
-
-/*
-** Make yytestcase() the same as testcase()
-*/
-#define yytestcase(X) testcase(X)
-
-/*
-** Indicate that sqlite3ParserFree() will never be called with a null
-** pointer.
-*/
-#define YYPARSEFREENOTNULL 1
-
-/*
-** Alternative datatype for the argument to the malloc() routine passed
-** into sqlite3ParserAlloc(). The default is size_t.
-*/
-#define YYMALLOCARGTYPE u64
-
-} // end %include
-
-%left OR.
-%left AND.
-%left NOT.
-%left TERM.
-%left COLON.
-
-input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
-%destructor input { (void)pParse; }
-
-%type cnearset {Fts5ExprNode*}
-%type expr {Fts5ExprNode*}
-%type exprlist {Fts5ExprNode*}
-%destructor cnearset { sqlite3Fts5ParseNodeFree($$); }
-%destructor expr { sqlite3Fts5ParseNodeFree($$); }
-%destructor exprlist { sqlite3Fts5ParseNodeFree($$); }
-
-%type colset {Fts5Colset*}
-%destructor colset { sqlite3_free($$); }
-%type colsetlist {Fts5Colset*}
-%destructor colsetlist { sqlite3_free($$); }
-
-colset(A) ::= MINUS LCP colsetlist(X) RCP. {
- A = sqlite3Fts5ParseColsetInvert(pParse, X);
-}
-colset(A) ::= LCP colsetlist(X) RCP. { A = X; }
-colset(A) ::= STRING(X). {
- A = sqlite3Fts5ParseColset(pParse, 0, &X);
-}
-colset(A) ::= MINUS STRING(X). {
- A = sqlite3Fts5ParseColset(pParse, 0, &X);
- A = sqlite3Fts5ParseColsetInvert(pParse, A);
-}
-
-colsetlist(A) ::= colsetlist(Y) STRING(X). {
- A = sqlite3Fts5ParseColset(pParse, Y, &X); }
-colsetlist(A) ::= STRING(X). {
- A = sqlite3Fts5ParseColset(pParse, 0, &X);
-}
-
-expr(A) ::= expr(X) AND expr(Y). {
- A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0);
-}
-expr(A) ::= expr(X) OR expr(Y). {
- A = sqlite3Fts5ParseNode(pParse, FTS5_OR, X, Y, 0);
-}
-expr(A) ::= expr(X) NOT expr(Y). {
- A = sqlite3Fts5ParseNode(pParse, FTS5_NOT, X, Y, 0);
-}
-
-expr(A) ::= colset(X) COLON LP expr(Y) RP. {
- sqlite3Fts5ParseSetColset(pParse, Y, X);
- A = Y;
-}
-expr(A) ::= LP expr(X) RP. {A = X;}
-expr(A) ::= exprlist(X). {A = X;}
-
-exprlist(A) ::= cnearset(X). {A = X;}
-exprlist(A) ::= exprlist(X) cnearset(Y). {
- A = sqlite3Fts5ParseImplicitAnd(pParse, X, Y);
-}
-
-cnearset(A) ::= nearset(X). {
- A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, X);
-}
-cnearset(A) ::= colset(X) COLON nearset(Y). {
- A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, Y);
- sqlite3Fts5ParseSetColset(pParse, A, X);
-}
-
-
-%type nearset {Fts5ExprNearset*}
-%type nearphrases {Fts5ExprNearset*}
-%destructor nearset { sqlite3Fts5ParseNearsetFree($$); }
-%destructor nearphrases { sqlite3Fts5ParseNearsetFree($$); }
-
-nearset(A) ::= phrase(Y). { A = sqlite3Fts5ParseNearset(pParse, 0, Y); }
-nearset(A) ::= CARET phrase(Y). {
- sqlite3Fts5ParseSetCaret(Y);
- A = sqlite3Fts5ParseNearset(pParse, 0, Y);
-}
-nearset(A) ::= STRING(X) LP nearphrases(Y) neardist_opt(Z) RP. {
- sqlite3Fts5ParseNear(pParse, &X);
- sqlite3Fts5ParseSetDistance(pParse, Y, &Z);
- A = Y;
-}
-
-nearphrases(A) ::= phrase(X). {
- A = sqlite3Fts5ParseNearset(pParse, 0, X);
-}
-nearphrases(A) ::= nearphrases(X) phrase(Y). {
- A = sqlite3Fts5ParseNearset(pParse, X, Y);
-}
-
-/*
-** The optional ", <integer>" at the end of the NEAR() arguments.
-*/
-neardist_opt(A) ::= . { A.p = 0; A.n = 0; }
-neardist_opt(A) ::= COMMA STRING(X). { A = X; }
-
-/*
-** A phrase. A set of primitives connected by "+" operators. Examples:
-**
-** "the" + "quick brown" + fo *
-** "the quick brown fo" *
-** the+quick+brown+fo*
-*/
-%type phrase {Fts5ExprPhrase*}
-%destructor phrase { sqlite3Fts5ParsePhraseFree($$); }
-
-phrase(A) ::= phrase(X) PLUS STRING(Y) star_opt(Z). {
- A = sqlite3Fts5ParseTerm(pParse, X, &Y, Z);
-}
-phrase(A) ::= STRING(Y) star_opt(Z). {
- A = sqlite3Fts5ParseTerm(pParse, 0, &Y, Z);
-}
-
-/*
-** Optional "*" character.
-*/
-%type star_opt {int}
-star_opt(A) ::= STAR. { A = 1; }
-star_opt(A) ::= . { A = 0; }
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/mkportersteps.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/mkportersteps.tcl
deleted file mode 100644
index b6214c6bf73..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/mkportersteps.tcl
+++ /dev/null
@@ -1,222 +0,0 @@
-#
-# 2014 Jun 09
-#
-# 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 script generates the implementations of the following C functions,
-# which are part of the porter tokenizer implementation:
-#
-# static int fts5PorterStep1B(char *aBuf, int *pnBuf);
-# static int fts5PorterStep1B2(char *aBuf, int *pnBuf);
-# static int fts5PorterStep2(char *aBuf, int *pnBuf);
-# static int fts5PorterStep3(char *aBuf, int *pnBuf);
-# static int fts5PorterStep4(char *aBuf, int *pnBuf);
-#
-
-set O(Step1B2) {
- { at {} ate 1 }
- { bl {} ble 1 }
- { iz {} ize 1 }
-}
-
-set O(Step1B) {
- { "eed" fts5Porter_MGt0 "ee" 0 }
- { "ed" fts5Porter_Vowel "" 1 }
- { "ing" fts5Porter_Vowel "" 1 }
-}
-
-set O(Step2) {
- { "ational" fts5Porter_MGt0 "ate" }
- { "tional" fts5Porter_MGt0 "tion" }
- { "enci" fts5Porter_MGt0 "ence" }
- { "anci" fts5Porter_MGt0 "ance" }
- { "izer" fts5Porter_MGt0 "ize" }
- { "logi" fts5Porter_MGt0 "log" }
- { "bli" fts5Porter_MGt0 "ble" }
- { "alli" fts5Porter_MGt0 "al" }
- { "entli" fts5Porter_MGt0 "ent" }
- { "eli" fts5Porter_MGt0 "e" }
- { "ousli" fts5Porter_MGt0 "ous" }
- { "ization" fts5Porter_MGt0 "ize" }
- { "ation" fts5Porter_MGt0 "ate" }
- { "ator" fts5Porter_MGt0 "ate" }
- { "alism" fts5Porter_MGt0 "al" }
- { "iveness" fts5Porter_MGt0 "ive" }
- { "fulness" fts5Porter_MGt0 "ful" }
- { "ousness" fts5Porter_MGt0 "ous" }
- { "aliti" fts5Porter_MGt0 "al" }
- { "iviti" fts5Porter_MGt0 "ive" }
- { "biliti" fts5Porter_MGt0 "ble" }
-}
-
-set O(Step3) {
- { "icate" fts5Porter_MGt0 "ic" }
- { "ative" fts5Porter_MGt0 "" }
- { "alize" fts5Porter_MGt0 "al" }
- { "iciti" fts5Porter_MGt0 "ic" }
- { "ical" fts5Porter_MGt0 "ic" }
- { "ful" fts5Porter_MGt0 "" }
- { "ness" fts5Porter_MGt0 "" }
-}
-
-set O(Step4) {
- { "al" fts5Porter_MGt1 "" }
- { "ance" fts5Porter_MGt1 "" }
- { "ence" fts5Porter_MGt1 "" }
- { "er" fts5Porter_MGt1 "" }
- { "ic" fts5Porter_MGt1 "" }
- { "able" fts5Porter_MGt1 "" }
- { "ible" fts5Porter_MGt1 "" }
- { "ant" fts5Porter_MGt1 "" }
- { "ement" fts5Porter_MGt1 "" }
- { "ment" fts5Porter_MGt1 "" }
- { "ent" fts5Porter_MGt1 "" }
- { "ion" fts5Porter_MGt1_and_S_or_T "" }
- { "ou" fts5Porter_MGt1 "" }
- { "ism" fts5Porter_MGt1 "" }
- { "ate" fts5Porter_MGt1 "" }
- { "iti" fts5Porter_MGt1 "" }
- { "ous" fts5Porter_MGt1 "" }
- { "ive" fts5Porter_MGt1 "" }
- { "ize" fts5Porter_MGt1 "" }
-}
-
-proc sort_cb {lhs rhs} {
- set L [string range [lindex $lhs 0] end-1 end-1]
- set R [string range [lindex $rhs 0] end-1 end-1]
- string compare $L $R
-}
-
-proc create_step_function {name data} {
-
- set T(function) {
-static int fts5Porter${name}(char *aBuf, int *pnBuf){
- int ret = 0;
- int nBuf = *pnBuf;
- switch( aBuf[nBuf-2] ){
- ${switchbody}
- }
- return ret;
-}
- }
-
- set T(case) {
- case '${k}':
- ${ifstmts}
- break;
- }
-
- set T(if_0_0_0) {
- if( ${match} ){
- *pnBuf = nBuf - $n;
- }
- }
- set T(if_1_0_0) {
- if( ${match} ){
- if( ${cond} ){
- *pnBuf = nBuf - $n;
- }
- }
- }
- set T(if_0_1_0) {
- if( ${match} ){
- ${memcpy}
- *pnBuf = nBuf - $n + $nRep;
- }
- }
- set T(if_1_1_0) {
- if( ${match} ){
- if( ${cond} ){
- ${memcpy}
- *pnBuf = nBuf - $n + $nRep;
- }
- }
- }
- set T(if_1_0_1) {
- if( ${match} ){
- if( ${cond} ){
- *pnBuf = nBuf - $n;
- ret = 1;
- }
- }
- }
- set T(if_0_1_1) {
- if( ${match} ){
- ${memcpy}
- *pnBuf = nBuf - $n + $nRep;
- ret = 1;
- }
- }
- set T(if_1_1_1) {
- if( ${match} ){
- if( ${cond} ){
- ${memcpy}
- *pnBuf = nBuf - $n + $nRep;
- ret = 1;
- }
- }
- }
-
- set switchbody ""
-
- foreach I $data {
- set k [string range [lindex $I 0] end-1 end-1]
- lappend aCase($k) $I
- }
- foreach k [lsort [array names aCase]] {
- set ifstmts ""
- foreach I $aCase($k) {
- set zSuffix [lindex $I 0] ;# Suffix text for this rule
- set zRep [lindex $I 2] ;# Replacement text for rule
- set xCond [lindex $I 1] ;# Condition callback (or "")
-
- set n [string length $zSuffix]
- set nRep [string length $zRep]
-
- set match "nBuf>$n && 0==memcmp(\"$zSuffix\", &aBuf\[nBuf-$n\], $n)"
- set memcpy "memcpy(&aBuf\[nBuf-$n\], \"$zRep\", $nRep);"
- set cond "${xCond}(aBuf, nBuf-$n)"
-
- set bMemcpy [expr {$nRep>0}]
- set bCond [expr {$xCond!=""}]
- set bRet [expr {[llength $I]>3 && [lindex $I 3]}]
-
- set t $T(if_${bCond}_${bMemcpy}_${bRet})
- lappend ifstmts [string trim [subst -nocommands $t]]
- }
-
- set ifstmts [join $ifstmts "else "]
-
- append switchbody [subst -nocommands $T(case)]
- }
-
-
- puts [subst -nocommands $T(function)]
-}
-
-
-puts [string trim {
-/**************************************************************************
-***************************************************************************
-** GENERATED CODE STARTS HERE (mkportersteps.tcl)
-*/
-}]
-foreach step [array names O] {
- create_step_function $step $O($step)
-}
-puts [string trim {
-/*
-** GENERATED CODE ENDS HERE (mkportersteps.tcl)
-***************************************************************************
-**************************************************************************/
-}]
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/fts5speed.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/fts5speed.tcl
deleted file mode 100644
index 0f38638c26a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/fts5speed.tcl
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-set Q {
- {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'enron'"}
- {25 "SELECT count(*) FROM t1 WHERE t1 MATCH 'hours'"}
- {300 "SELECT count(*) FROM t1 WHERE t1 MATCH 'acid'"}
- {100 "SELECT count(*) FROM t1 WHERE t1 MATCH 'loaned OR mobility OR popcore OR sunk'"}
- {100 "SELECT count(*) FROM t1 WHERE t1 MATCH 'enron AND myapps'"}
- {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'en* AND my*'"}
-
- {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:t*'"}
- {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t* OR b:t* OR c:t* OR d:t* OR e:t* OR f:t* OR g:t*'"}
- {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t*'"}
- {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:the'"}
-
- {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes OR e:holmes OR f:holmes OR g:holmes'" }
- {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes AND e:holmes AND f:holmes AND g:holmes'" }
- {4 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes NOT e:holmes'" }
-}
-
-proc usage {} {
- global Q
- puts stderr "Usage: $::argv0 DATABASE QUERY"
- puts stderr ""
- for {set i 1} {$i <= [llength $Q]} {incr i} {
- puts stderr " $i. [lindex $Q [expr $i-1]]"
- }
- puts stderr ""
- exit -1
-}
-
-
-set nArg [llength $argv]
-if {$nArg!=2 && $nArg!=3} usage
-set database [lindex $argv 0]
-set iquery [lindex $argv 1]
-if {$iquery<1 || $iquery>[llength $Q]} usage
-set nRepeat 0
-if {$nArg==3} { set nRepeat [lindex $argv 2] }
-
-
-sqlite3 db $database
-catch { load_static_extension db fts5 }
-
-incr iquery -1
-set sql [lindex $Q $iquery 1]
-if {$nRepeat==0} {
- set nRepeat [lindex $Q $iquery 0]
-}
-
-puts "sql: $sql"
-puts "nRepeat: $nRepeat"
-if {[regexp matchinfo $sql]} {
- sqlite3_fts5_register_matchinfo db
- db eval $sql
-} else {
- puts "result: [db eval $sql]"
-}
-
-for {set i 1} {$i < $nRepeat} {incr i} {
- db eval $sql
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/fts5txt2db.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/fts5txt2db.tcl
deleted file mode 100644
index 4766b00b06b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/fts5txt2db.tcl
+++ /dev/null
@@ -1,229 +0,0 @@
-##########################################################################
-# 2016 Jan 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.
-#
-proc process_cmdline {} {
- cmdline::process ::A $::argv {
- {fts5 "use fts5 (this is the default)"}
- {fts4 "use fts4"}
- {colsize "10 10 10" "list of column sizes"}
- {tblname "t1" "table name to create"}
- {detail "full" "Fts5 detail mode to use"}
- {repeat 1 "Load each file this many times"}
- {prefix "" "Fts prefix= option"}
- {trans 1 "True to use a transaction"}
- database
- file...
- } {
- This script is designed to create fts4/5 tables with more than one column.
- The -colsize option should be set to a Tcl list of integer values, one for
- each column in the table. Each value is the number of tokens that will be
- inserted into the column value for each row. For example, setting the -colsize
- option to "5 10" creates an FTS table with 2 columns, with roughly 5 and 10
- tokens per row in each, respectively.
-
- Each "FILE" argument should be a text file. The contents of these text files
- is split on whitespace characters to form a list of tokens. The first N1
- tokens are used for the first column of the first row, where N1 is the first
- element of the -colsize list. The next N2 are used for the second column of
- the first row, and so on. Rows are added to the table until the entire list
- of tokens is exhausted.
- }
-}
-
-###########################################################################
-###########################################################################
-# Command line options processor. This is generic code that can be copied
-# between scripts.
-#
-namespace eval cmdline {
- proc cmdline_error {O E {msg ""}} {
- if {$msg != ""} {
- puts stderr "Error: $msg"
- puts stderr ""
- }
-
- set L [list]
- foreach o $O {
- if {[llength $o]==1} {
- lappend L [string toupper $o]
- }
- }
-
- puts stderr "Usage: $::argv0 ?SWITCHES? $L"
- puts stderr ""
- puts stderr "Switches are:"
- foreach o $O {
- if {[llength $o]==3} {
- foreach {a b c} $o {}
- puts stderr [format " -%-15s %s (default \"%s\")" "$a VAL" $c $b]
- } elseif {[llength $o]==2} {
- foreach {a b} $o {}
- puts stderr [format " -%-15s %s" $a $b]
- }
- }
- puts stderr ""
- puts stderr $E
- exit -1
- }
-
- proc process {avar lArgs O E} {
- upvar $avar A
- set zTrailing "" ;# True if ... is present in $O
- set lPosargs [list]
-
- # Populate A() with default values. Also, for each switch in the command
- # line spec, set an entry in the idx() array as follows:
- #
- # {tblname t1 "table name to use"}
- # -> [set idx(-tblname) {tblname t1 "table name to use"}
- #
- # For each position parameter, append its name to $lPosargs. If the ...
- # specifier is present, set $zTrailing to the name of the prefix.
- #
- foreach o $O {
- set nm [lindex $o 0]
- set nArg [llength $o]
- switch -- $nArg {
- 1 {
- if {[string range $nm end-2 end]=="..."} {
- set zTrailing [string range $nm 0 end-3]
- } else {
- lappend lPosargs $nm
- }
- }
- 2 {
- set A($nm) 0
- set idx(-$nm) $o
- }
- 3 {
- set A($nm) [lindex $o 1]
- set idx(-$nm) $o
- }
- default {
- error "Error in command line specification"
- }
- }
- }
-
- # Set explicitly specified option values
- #
- set nArg [llength $lArgs]
- for {set i 0} {$i < $nArg} {incr i} {
- set opt [lindex $lArgs $i]
- if {[string range $opt 0 0]!="-" || $opt=="--"} break
- set c [array names idx "${opt}*"]
- if {[llength $c]==0} { cmdline_error $O $E "Unrecognized option: $opt"}
- if {[llength $c]>1} { cmdline_error $O $E "Ambiguous option: $opt"}
-
- if {[llength $idx($c)]==3} {
- if {$i==[llength $lArgs]-1} {
- cmdline_error $O $E "Option requires argument: $c"
- }
- incr i
- set A([lindex $idx($c) 0]) [lindex $lArgs $i]
- } else {
- set A([lindex $idx($c) 0]) 1
- }
- }
-
- # Deal with position arguments.
- #
- set nPosarg [llength $lPosargs]
- set nRem [expr $nArg - $i]
- if {$nRem < $nPosarg || ($zTrailing=="" && $nRem > $nPosarg)} {
- cmdline_error $O $E
- }
- for {set j 0} {$j < $nPosarg} {incr j} {
- set A([lindex $lPosargs $j]) [lindex $lArgs [expr $j+$i]]
- }
- if {$zTrailing!=""} {
- set A($zTrailing) [lrange $lArgs [expr $j+$i] end]
- }
- }
-} ;# namespace eval cmdline
-# End of command line options processor.
-###########################################################################
-###########################################################################
-
-process_cmdline
-
-# If -fts4 was specified, use fts4. Otherwise, fts5.
-if {$A(fts4)} {
- set A(fts) fts4
-} else {
- set A(fts) fts5
-}
-
-sqlite3 db $A(database)
-
-# Create the FTS table in the db. Return a list of the table columns.
-#
-proc create_table {} {
- global A
- set cols [list a b c d e f g h i j k l m n o p q r s t u v w x y z]
-
- set nCol [llength $A(colsize)]
- set cols [lrange $cols 0 [expr $nCol-1]]
-
- set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $A(tblname) USING $A(fts) ("
- append sql [join $cols ,]
- if {$A(fts)=="fts5"} { append sql ",detail=$A(detail)" }
- append sql ", prefix='$A(prefix)');"
-
- db eval $sql
- return $cols
-}
-
-# Return a list of tokens from the named file.
-#
-proc readfile {file} {
- set fd [open $file]
- set data [read $fd]
- close $fd
- split $data
-}
-
-proc repeat {L n} {
- set res [list]
- for {set i 0} {$i < $n} {incr i} {
- set res [concat $res $L]
- }
- set res
-}
-
-
-# Load all the data into a big list of tokens.
-#
-set tokens [list]
-foreach f $A(file) {
- set tokens [concat $tokens [repeat [readfile $f] $A(repeat)]]
-}
-
-set N [llength $tokens]
-set i 0
-set cols [create_table]
-set sql "INSERT INTO $A(tblname) VALUES(\$R([lindex $cols 0])"
-foreach c [lrange $cols 1 end] {
- append sql ", \$R($c)"
-}
-append sql ")"
-
-if {$A(trans)} { db eval BEGIN }
- while {$i < $N} {
- foreach c $cols s $A(colsize) {
- set R($c) [lrange $tokens $i [expr $i+$s-1]]
- incr i $s
- }
- db eval $sql
- }
-if {$A(trans)} { db eval COMMIT }
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/loadfts5.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/loadfts5.tcl
deleted file mode 100644
index 96fd69260ec..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/loadfts5.tcl
+++ /dev/null
@@ -1,172 +0,0 @@
-
-
-proc loadfile {f} {
- set fd [open $f]
- set data [read $fd]
- close $fd
- return $data
-}
-
-set ::nRow 0
-set ::nRowPerDot 1000
-
-proc load_hierachy {dir} {
- foreach f [glob -nocomplain -dir $dir *] {
- if {$::O(limit) && $::nRow>=$::O(limit)} break
- if {[file isdir $f]} {
- load_hierachy $f
- } else {
- db eval { INSERT INTO t1 VALUES($f, loadfile($f)) }
- incr ::nRow
-
- if {$::O(trans) && ($::nRow % $::O(trans))==0} {
- db eval { COMMIT }
- db eval { INSERT INTO t1(t1) VALUES('integrity-check') }
- db eval { BEGIN }
- }
-
- if {($::nRow % $::nRowPerDot)==0} {
- puts -nonewline .
- if {($::nRow % (65*$::nRowPerDot))==0} { puts "" }
- flush stdout
- }
-
- }
- }
-}
-
-proc usage {} {
- puts stderr "Usage: $::argv0 ?SWITCHES? DATABASE PATH"
- puts stderr ""
- puts stderr "Switches are:"
- puts stderr " -fts4 (use fts4 instead of fts5)"
- puts stderr " -fts5 (use fts5)"
- puts stderr " -porter (use porter tokenizer)"
- puts stderr " -delete (delete the database file before starting)"
- puts stderr " -limit N (load no more than N documents)"
- puts stderr " -automerge N (set the automerge parameter to N)"
- puts stderr " -crisismerge N (set the crisismerge parameter to N)"
- puts stderr " -prefix PREFIX (comma separated prefix= argument)"
- puts stderr " -trans N (commit after N inserts - 0 == never)"
- puts stderr " -hashsize N (set the fts5 hashsize parameter to N)"
- puts stderr " -detail MODE (detail mode for fts5 tables)"
- exit 1
-}
-
-set O(vtab) fts5
-set O(tok) ""
-set O(limit) 0
-set O(delete) 0
-set O(automerge) -1
-set O(crisismerge) -1
-set O(prefix) ""
-set O(trans) 0
-set O(hashsize) -1
-set O(detail) full
-
-if {[llength $argv]<2} usage
-set nOpt [expr {[llength $argv]-2}]
-for {set i 0} {$i < $nOpt} {incr i} {
- set arg [lindex $argv $i]
- switch -- [lindex $argv $i] {
- -fts4 {
- set O(vtab) fts4
- }
-
- -fts5 {
- set O(vtab) fts5
- }
-
- -porter {
- set O(tok) ", tokenize=porter"
- }
-
- -delete {
- set O(delete) 1
- }
-
- -limit {
- if { [incr i]>=$nOpt } usage
- set O(limit) [lindex $argv $i]
- }
-
- -trans {
- if { [incr i]>=$nOpt } usage
- set O(trans) [lindex $argv $i]
- }
-
- -automerge {
- if { [incr i]>=$nOpt } usage
- set O(automerge) [lindex $argv $i]
- }
-
- -crisismerge {
- if { [incr i]>=$nOpt } usage
- set O(crisismerge) [lindex $argv $i]
- }
-
- -prefix {
- if { [incr i]>=$nOpt } usage
- set O(prefix) [lindex $argv $i]
- }
-
- -hashsize {
- if { [incr i]>=$nOpt } usage
- set O(hashsize) [lindex $argv $i]
- }
-
- -detail {
- if { [incr i]>=$nOpt } usage
- set O(detail) [lindex $argv $i]
- }
-
- default {
- usage
- }
- }
-}
-
-set dbfile [lindex $argv end-1]
-if {$O(delete)} { file delete -force $dbfile }
-sqlite3 db $dbfile
-catch { load_static_extension db fts5 }
-db func loadfile loadfile
-db eval "PRAGMA page_size=4096"
-
-db eval BEGIN
- set pref ""
- if {$O(prefix)!=""} { set pref ", prefix='$O(prefix)'" }
- if {$O(vtab)=="fts5"} {
- append pref ", detail=$O(detail)"
- }
- catch {
- db eval "CREATE VIRTUAL TABLE t1 USING $O(vtab) (path, content$O(tok)$pref)"
- db eval "INSERT INTO t1(t1, rank) VALUES('pgsz', 4050);"
- }
-
- if {$O(hashsize)>=0} {
- catch {
- db eval "INSERT INTO t1(t1, rank) VALUES('hashsize', $O(hashsize));"
- }
- }
-
-
- if {$O(automerge)>=0} {
- if {$O(vtab) == "fts5"} {
- db eval { INSERT INTO t1(t1, rank) VALUES('automerge', $O(automerge)) }
- } else {
- db eval { INSERT INTO t1(t1) VALUES('automerge=' || $O(automerge)) }
- }
- }
- if {$O(crisismerge)>=0} {
- if {$O(vtab) == "fts5"} {
- db eval {INSERT INTO t1(t1, rank) VALUES('crisismerge', $O(crisismerge))}
- } else {
- }
- }
- load_hierachy [lindex $argv end]
-db eval COMMIT
-puts ""
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/mkfts5c.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/mkfts5c.tcl
deleted file mode 100644
index 797811d46e2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/mkfts5c.tcl
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/bin/sh
-# restart with tclsh \
-exec tclsh "$0" "$@"
-
-set srcdir [file dirname [file dirname [info script]]]
-set G(src) [string map [list %dir% $srcdir] {
- %dir%/fts5.h
- %dir%/fts5Int.h
- fts5parse.h
- fts5parse.c
- %dir%/fts5_aux.c
- %dir%/fts5_buffer.c
- %dir%/fts5_config.c
- %dir%/fts5_expr.c
- %dir%/fts5_hash.c
- %dir%/fts5_index.c
- %dir%/fts5_main.c
- %dir%/fts5_storage.c
- %dir%/fts5_tokenize.c
- %dir%/fts5_unicode2.c
- %dir%/fts5_varint.c
- %dir%/fts5_vocab.c
-}]
-
-set G(hdr) {
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5)
-
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
-# define NDEBUG 1
-#endif
-#if defined(NDEBUG) && defined(SQLITE_DEBUG)
-# undef NDEBUG
-#endif
-
-}
-
-set G(footer) {
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
-}
-
-#-------------------------------------------------------------------------
-# Read and return the entire contents of text file $zFile from disk.
-#
-proc readfile {zFile} {
- set fd [open $zFile]
- set data [read $fd]
- close $fd
- return $data
-}
-
-#-------------------------------------------------------------------------
-# This command returns a string identifying the current sqlite version -
-# the equivalent of the SQLITE_SOURCE_ID string.
-#
-proc fts5_source_id {zDir} {
- set top [file dirname [file dirname $zDir]]
- set uuid [string trim [readfile [file join $top manifest.uuid]]]
-
- set L [split [readfile [file join $top manifest]]]
- set date [lindex $L [expr [lsearch -exact $L D]+1]]
- set date [string range $date 0 [string last . $date]-1]
- set date [string map {T { }} $date]
-
- return "fts5: $date $uuid"
-}
-
-proc fts5c_init {zOut} {
- global G
- set G(fd) stdout
- set G(fd) [open $zOut w]
-
- puts -nonewline $G(fd) $G(hdr)
-}
-
-proc fts5c_printfile {zIn} {
- global G
- set data [readfile $zIn]
- set zTail [file tail $zIn]
- puts $G(fd) "#line 1 \"$zTail\""
-
- set sub_map [list --FTS5-SOURCE-ID-- [fts5_source_id $::srcdir]]
- if {$zTail=="fts5parse.c"} {
- lappend sub_map yy fts5yy YY fts5YY TOKEN FTS5TOKEN
- }
-
- foreach line [split $data "\n"] {
- if {[regexp {^#include.*fts5} $line]} {
- set line "/* $line */"
- } elseif {
- ![regexp { sqlite3Fts5Init\(} $line]
- && [regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?sqlite3Fts5} $line]
- } {
- set line "static $line"
- }
- set line [string map $sub_map $line]
- puts $G(fd) $line
- }
-}
-
-proc fts5c_close {} {
- global G
- puts -nonewline $G(fd) $G(footer)
- if {$G(fd)!="stdout"} {
- close $G(fd)
- }
-}
-
-
-fts5c_init fts5.c
-foreach f $G(src) { fts5c_printfile $f }
-fts5c_close
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/showfts5.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/showfts5.tcl
deleted file mode 100644
index 75ac0f1c8f8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/fts5/tool/showfts5.tcl
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-#-------------------------------------------------------------------------
-# Process command line arguments.
-#
-proc usage {} {
- puts stderr "usage: $::argv0 ?OPTIONS? database table"
- puts stderr ""
- puts stderr " -nterm (count number of terms in each segment)"
- puts stderr " -segments (output segment contents)"
- puts stderr ""
- exit 1
-}
-
-set O(nterm) 0
-set O(segments) 0
-
-if {[llength $argv]<2} usage
-foreach a [lrange $argv 0 end-2] {
- switch -- $a {
- -nterm {
- set O(nterm) 1
- }
-
- -segments {
- set O(segments) 1
- }
-
- default {
- usage
- }
- }
-}
-
-set database [lindex $argv end-1]
-set tbl [lindex $argv end]
-
-
-#-------------------------------------------------------------------------
-# Count the number of terms in each segment of fts5 table $tbl. Store the
-# counts in the array variable in the parent context named by parameter
-# $arrayname, indexed by segment-id. Example:
-#
-# count_terms fts_tbl A
-# foreach {k v} [array get A] { puts "segid=$k nTerm=$v" }
-#
-proc count_terms {tbl arrayname} {
- upvar A $arrayname
- array unset A
- db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data" {
- set desc [lindex $d 0]
- if {[regexp {^segid=([0-9]*)} $desc -> id]} {
- foreach i [lrange $d 1 end] {
- if {[string match {term=*} $i]} { incr A($id) }
- }
- }
- }
-}
-
-
-#-------------------------------------------------------------------------
-# Start of main program.
-#
-sqlite3 db $database
-catch { load_static_extension db fts5 }
-
-if {$O(nterm)} { count_terms $tbl A }
-
-db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id=10" {
- foreach lvl [lrange $d 1 end] {
- puts [lrange $lvl 0 2]
-
- foreach seg [lrange $lvl 3 end] {
- if {$::O(nterm)} {
- regexp {^id=([0-9]*)} $seg -> id
- set nTerm 0
- catch { set nTerm $A($id) }
- puts [format " % -28s nTerm=%d" $seg $nTerm]
- } else {
- puts [format " % -28s" $seg]
- }
- }
- }
-}
-
-if {$O(segments)} {
- puts ""
- db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id>10" {
- puts $d
- }
-}
-
-
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/README.txt b/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/README.txt
deleted file mode 100644
index af75d22e611..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/README.txt
+++ /dev/null
@@ -1,169 +0,0 @@
-
-This directory contains source code for the SQLite "ICU" extension, an
-integration of the "International Components for Unicode" library with
-SQLite. Documentation follows.
-
- 1. Features
-
- 1.1 SQL Scalars upper() and lower()
- 1.2 Unicode Aware LIKE Operator
- 1.3 ICU Collation Sequences
- 1.4 SQL REGEXP Operator
-
- 2. Compilation and Usage
-
- 3. Bugs, Problems and Security Issues
-
- 3.1 The "case_sensitive_like" Pragma
- 3.2 The SQLITE_MAX_LIKE_PATTERN_LENGTH Macro
- 3.3 Collation Sequence Security Issue
-
-
-1. FEATURES
-
- 1.1 SQL Scalars upper() and lower()
-
- SQLite's built-in implementations of these two functions only
- provide case mapping for the 26 letters used in the English
- language. The ICU based functions provided by this extension
- provide case mapping, where defined, for the full range of
- unicode characters.
-
- ICU provides two types of case mapping, "general" case mapping and
- "language specific". Refer to ICU documentation for the differences
- between the two. Specifically:
-
- http://www.icu-project.org/userguide/caseMappings.html
- http://www.icu-project.org/userguide/posix.html#case_mappings
-
- To utilise "general" case mapping, the upper() or lower() scalar
- functions are invoked with one argument:
-
- upper('abc') -> 'ABC'
- lower('ABC') -> 'abc'
-
- To access ICU "language specific" case mapping, upper() or lower()
- should be invoked with two arguments. The second argument is the name
- of the locale to use. Passing an empty string ("") or SQL NULL value
- as the second argument is the same as invoking the 1 argument version
- of upper() or lower():
-
- lower('I', 'en_us') -> 'i'
- lower('I', 'tr_tr') -> 'ı' (small dotless i)
-
- 1.2 Unicode Aware LIKE Operator
-
- Similarly to the upper() and lower() functions, the built-in SQLite LIKE
- operator understands case equivalence for the 26 letters of the English
- language alphabet. The implementation of LIKE included in this
- extension uses the ICU function u_foldCase() to provide case
- independent comparisons for the full range of unicode characters.
-
- The U_FOLD_CASE_DEFAULT flag is passed to u_foldCase(), meaning the
- dotless 'I' character used in the Turkish language is considered
- to be in the same equivalence class as the dotted 'I' character
- used by many languages (including English).
-
- 1.3 ICU Collation Sequences
-
- A special SQL scalar function, icu_load_collation() is provided that
- may be used to register ICU collation sequences with SQLite. It
- is always called with exactly two arguments, the ICU locale
- identifying the collation sequence to ICU, and the name of the
- SQLite collation sequence to create. For example, to create an
- SQLite collation sequence named "turkish" using Turkish language
- sorting rules, the SQL statement:
-
- SELECT icu_load_collation('tr_TR', 'turkish');
-
- Or, for Australian English:
-
- SELECT icu_load_collation('en_AU', 'australian');
-
- The identifiers "turkish" and "australian" may then be used
- as collation sequence identifiers in SQL statements:
-
- CREATE TABLE aust_turkish_penpals(
- australian_penpal_name TEXT COLLATE australian,
- turkish_penpal_name TEXT COLLATE turkish
- );
-
- 1.4 SQL REGEXP Operator
-
- This extension provides an implementation of the SQL binary
- comparision operator "REGEXP", based on the regular expression functions
- provided by the ICU library. The syntax of the operator is as described
- in SQLite documentation:
-
- <string> REGEXP <re-pattern>
-
- This extension uses the ICU defaults for regular expression matching
- behavior. Specifically, this means that:
-
- * Matching is case-sensitive,
- * Regular expression comments are not allowed within patterns, and
- * The '^' and '$' characters match the beginning and end of the
- <string> argument, not the beginning and end of lines within
- the <string> argument.
-
- Even more specifically, the value passed to the "flags" parameter
- of ICU C function uregex_open() is 0.
-
-
-2 COMPILATION AND USAGE
-
- The easiest way to compile and use the ICU extension is to build
- and use it as a dynamically loadable SQLite extension. To do this
- using gcc on *nix:
-
- gcc -shared icu.c `icu-config --ldflags` -o libSqliteIcu.so
-
- You may need to add "-I" flags so that gcc can find sqlite3ext.h
- and sqlite3.h. The resulting shared lib, libSqliteIcu.so, may be
- loaded into sqlite in the same way as any other dynamically loadable
- extension.
-
-
-3 BUGS, PROBLEMS AND SECURITY ISSUES
-
- 3.1 The "case_sensitive_like" Pragma
-
- This extension does not work well with the "case_sensitive_like"
- pragma. If this pragma is used before the ICU extension is loaded,
- then the pragma has no effect. If the pragma is used after the ICU
- extension is loaded, then SQLite ignores the ICU implementation and
- always uses the built-in LIKE operator.
-
- The ICU extension LIKE operator is always case insensitive.
-
- 3.2 The SQLITE_MAX_LIKE_PATTERN_LENGTH Macro
-
- Passing very long patterns to the built-in SQLite LIKE operator can
- cause excessive CPU usage. To curb this problem, SQLite defines the
- SQLITE_MAX_LIKE_PATTERN_LENGTH macro as the maximum length of a
- pattern in bytes (irrespective of encoding). The default value is
- defined in internal header file "limits.h".
-
- The ICU extension LIKE implementation suffers from the same
- problem and uses the same solution. However, since the ICU extension
- code does not include the SQLite file "limits.h", modifying
- the default value therein does not affect the ICU extension.
- The default value of SQLITE_MAX_LIKE_PATTERN_LENGTH used by
- the ICU extension LIKE operator is 50000, defined in source
- file "icu.c".
-
- 3.3 Collation Sequence Security Issue
-
- Internally, SQLite assumes that indices stored in database files
- are sorted according to the collation sequence indicated by the
- SQL schema. Changing the definition of a collation sequence after
- an index has been built is therefore equivalent to database
- corruption. The SQLite library is not very well tested under
- these conditions, and may contain potential buffer overruns
- or other programming errors that could be exploited by a malicious
- programmer.
-
- If the ICU extension is used in an environment where potentially
- malicious users may execute arbitrary SQL (i.e. gears), they
- should be prevented from invoking the icu_load_collation() function,
- possibly using the authorisation callback.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/icu.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/icu.c
deleted file mode 100644
index 13524ebc2a7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/icu.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
-** 2007 May 6
-**
-** 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.
-**
-*************************************************************************
-** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $
-**
-** This file implements an integration between the ICU library
-** ("International Components for Unicode", an open-source library
-** for handling unicode data) and SQLite. The integration uses
-** ICU to provide the following to SQLite:
-**
-** * An implementation of the SQL regexp() function (and hence REGEXP
-** operator) using the ICU uregex_XX() APIs.
-**
-** * Implementations of the SQL scalar upper() and lower() functions
-** for case mapping.
-**
-** * Integration of ICU and SQLite collation sequences.
-**
-** * An implementation of the LIKE operator that uses ICU to
-** provide case-independent matching.
-*/
-
-#if !defined(SQLITE_CORE) \
- || defined(SQLITE_ENABLE_ICU) \
- || defined(SQLITE_ENABLE_ICU_COLLATIONS)
-
-/* Include ICU headers */
-#include <unicode/utypes.h>
-#include <unicode/uregex.h>
-#include <unicode/ustring.h>
-#include <unicode/ucol.h>
-
-#include <assert.h>
-
-#ifndef SQLITE_CORE
- #include "sqlite3ext.h"
- SQLITE_EXTENSION_INIT1
-#else
- #include "sqlite3.h"
-#endif
-
-/*
-** This function is called when an ICU function called from within
-** the implementation of an SQL scalar function returns an error.
-**
-** The scalar function context passed as the first argument is
-** loaded with an error message based on the following two args.
-*/
-static void icuFunctionError(
- sqlite3_context *pCtx, /* SQLite scalar function context */
- const char *zName, /* Name of ICU function that failed */
- UErrorCode e /* Error code returned by ICU function */
-){
- char zBuf[128];
- sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e));
- zBuf[127] = '\0';
- sqlite3_result_error(pCtx, zBuf, -1);
-}
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
-
-/*
-** Maximum length (in bytes) of the pattern in a LIKE or GLOB
-** operator.
-*/
-#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
-# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
-#endif
-
-/*
-** Version of sqlite3_free() that is always a function, never a macro.
-*/
-static void xFree(void *p){
- sqlite3_free(p);
-}
-
-/*
-** This lookup table is used to help decode the first byte of
-** a multi-byte UTF8 character. It is copied here from SQLite source
-** code file utf8.c.
-*/
-static const unsigned char icuUtf8Trans1[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
-};
-
-#define SQLITE_ICU_READ_UTF8(zIn, c) \
- c = *(zIn++); \
- if( c>=0xc0 ){ \
- c = icuUtf8Trans1[c-0xc0]; \
- while( (*zIn & 0xc0)==0x80 ){ \
- c = (c<<6) + (0x3f & *(zIn++)); \
- } \
- }
-
-#define SQLITE_ICU_SKIP_UTF8(zIn) \
- assert( *zIn ); \
- if( *(zIn++)>=0xc0 ){ \
- while( (*zIn & 0xc0)==0x80 ){zIn++;} \
- }
-
-
-/*
-** Compare two UTF-8 strings for equality where the first string is
-** a "LIKE" expression. Return true (1) if they are the same and
-** false (0) if they are different.
-*/
-static int icuLikeCompare(
- const uint8_t *zPattern, /* LIKE pattern */
- const uint8_t *zString, /* The UTF-8 string to compare against */
- const UChar32 uEsc /* The escape character */
-){
- static const uint32_t MATCH_ONE = (uint32_t)'_';
- static const uint32_t MATCH_ALL = (uint32_t)'%';
-
- int prevEscape = 0; /* True if the previous character was uEsc */
-
- while( 1 ){
-
- /* Read (and consume) the next character from the input pattern. */
- uint32_t uPattern;
- SQLITE_ICU_READ_UTF8(zPattern, uPattern);
- if( uPattern==0 ) break;
-
- /* There are now 4 possibilities:
- **
- ** 1. uPattern is an unescaped match-all character "%",
- ** 2. uPattern is an unescaped match-one character "_",
- ** 3. uPattern is an unescaped escape character, or
- ** 4. uPattern is to be handled as an ordinary character
- */
- if( !prevEscape && uPattern==MATCH_ALL ){
- /* Case 1. */
- uint8_t c;
-
- /* Skip any MATCH_ALL or MATCH_ONE characters that follow a
- ** MATCH_ALL. For each MATCH_ONE, skip one character in the
- ** test string.
- */
- while( (c=*zPattern) == MATCH_ALL || c == MATCH_ONE ){
- if( c==MATCH_ONE ){
- if( *zString==0 ) return 0;
- SQLITE_ICU_SKIP_UTF8(zString);
- }
- zPattern++;
- }
-
- if( *zPattern==0 ) return 1;
-
- while( *zString ){
- if( icuLikeCompare(zPattern, zString, uEsc) ){
- return 1;
- }
- SQLITE_ICU_SKIP_UTF8(zString);
- }
- return 0;
-
- }else if( !prevEscape && uPattern==MATCH_ONE ){
- /* Case 2. */
- if( *zString==0 ) return 0;
- SQLITE_ICU_SKIP_UTF8(zString);
-
- }else if( !prevEscape && uPattern==(uint32_t)uEsc){
- /* Case 3. */
- prevEscape = 1;
-
- }else{
- /* Case 4. */
- uint32_t uString;
- SQLITE_ICU_READ_UTF8(zString, uString);
- uString = (uint32_t)u_foldCase((UChar32)uString, U_FOLD_CASE_DEFAULT);
- uPattern = (uint32_t)u_foldCase((UChar32)uPattern, U_FOLD_CASE_DEFAULT);
- if( uString!=uPattern ){
- return 0;
- }
- prevEscape = 0;
- }
- }
-
- return *zString==0;
-}
-
-/*
-** Implementation of the like() SQL function. This function implements
-** the build-in LIKE operator. The first argument to the function is the
-** pattern and the second argument is the string. So, the SQL statements:
-**
-** A LIKE B
-**
-** is implemented as like(B, A). If there is an escape character E,
-**
-** A LIKE B ESCAPE E
-**
-** is mapped to like(B, A, E).
-*/
-static void icuLikeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zA = sqlite3_value_text(argv[0]);
- const unsigned char *zB = sqlite3_value_text(argv[1]);
- UChar32 uEsc = 0;
-
- /* Limit the length of the LIKE or GLOB pattern to avoid problems
- ** of deep recursion and N*N behavior in patternCompare().
- */
- if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){
- sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
- return;
- }
-
-
- if( argc==3 ){
- /* The escape character string must consist of a single UTF-8 character.
- ** Otherwise, return an error.
- */
- int nE= sqlite3_value_bytes(argv[2]);
- const unsigned char *zE = sqlite3_value_text(argv[2]);
- int i = 0;
- if( zE==0 ) return;
- U8_NEXT(zE, i, nE, uEsc);
- if( i!=nE){
- sqlite3_result_error(context,
- "ESCAPE expression must be a single character", -1);
- return;
- }
- }
-
- if( zA && zB ){
- sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc));
- }
-}
-
-/*
-** Function to delete compiled regexp objects. Registered as
-** a destructor function with sqlite3_set_auxdata().
-*/
-static void icuRegexpDelete(void *p){
- URegularExpression *pExpr = (URegularExpression *)p;
- uregex_close(pExpr);
-}
-
-/*
-** Implementation of SQLite REGEXP operator. This scalar function takes
-** two arguments. The first is a regular expression pattern to compile
-** the second is a string to match against that pattern. If either
-** argument is an SQL NULL, then NULL Is returned. Otherwise, the result
-** is 1 if the string matches the pattern, or 0 otherwise.
-**
-** SQLite maps the regexp() function to the regexp() operator such
-** that the following two are equivalent:
-**
-** zString REGEXP zPattern
-** regexp(zPattern, zString)
-**
-** Uses the following ICU regexp APIs:
-**
-** uregex_open()
-** uregex_matches()
-** uregex_close()
-*/
-static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
- UErrorCode status = U_ZERO_ERROR;
- URegularExpression *pExpr;
- UBool res;
- const UChar *zString = sqlite3_value_text16(apArg[1]);
-
- (void)nArg; /* Unused parameter */
-
- /* If the left hand side of the regexp operator is NULL,
- ** then the result is also NULL.
- */
- if( !zString ){
- return;
- }
-
- pExpr = sqlite3_get_auxdata(p, 0);
- if( !pExpr ){
- const UChar *zPattern = sqlite3_value_text16(apArg[0]);
- if( !zPattern ){
- return;
- }
- pExpr = uregex_open(zPattern, -1, 0, 0, &status);
-
- if( U_SUCCESS(status) ){
- sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete);
- }else{
- assert(!pExpr);
- icuFunctionError(p, "uregex_open", status);
- return;
- }
- }
-
- /* Configure the text that the regular expression operates on. */
- uregex_setText(pExpr, zString, -1, &status);
- if( !U_SUCCESS(status) ){
- icuFunctionError(p, "uregex_setText", status);
- return;
- }
-
- /* Attempt the match */
- res = uregex_matches(pExpr, 0, &status);
- if( !U_SUCCESS(status) ){
- icuFunctionError(p, "uregex_matches", status);
- return;
- }
-
- /* Set the text that the regular expression operates on to a NULL
- ** pointer. This is not really necessary, but it is tidier than
- ** leaving the regular expression object configured with an invalid
- ** pointer after this function returns.
- */
- uregex_setText(pExpr, 0, 0, &status);
-
- /* Return 1 or 0. */
- sqlite3_result_int(p, res ? 1 : 0);
-}
-
-/*
-** Implementations of scalar functions for case mapping - upper() and
-** lower(). Function upper() converts its input to upper-case (ABC).
-** Function lower() converts to lower-case (abc).
-**
-** ICU provides two types of case mapping, "general" case mapping and
-** "language specific". Refer to ICU documentation for the differences
-** between the two.
-**
-** To utilise "general" case mapping, the upper() or lower() scalar
-** functions are invoked with one argument:
-**
-** upper('ABC') -> 'abc'
-** lower('abc') -> 'ABC'
-**
-** To access ICU "language specific" case mapping, upper() or lower()
-** should be invoked with two arguments. The second argument is the name
-** of the locale to use. Passing an empty string ("") or SQL NULL value
-** as the second argument is the same as invoking the 1 argument version
-** of upper() or lower().
-**
-** lower('I', 'en_us') -> 'i'
-** lower('I', 'tr_tr') -> '\u131' (small dotless i)
-**
-** http://www.icu-project.org/userguide/posix.html#case_mappings
-*/
-static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
- const UChar *zInput; /* Pointer to input string */
- UChar *zOutput = 0; /* Pointer to output buffer */
- int nInput; /* Size of utf-16 input string in bytes */
- int nOut; /* Size of output buffer in bytes */
- int cnt;
- int bToUpper; /* True for toupper(), false for tolower() */
- UErrorCode status;
- const char *zLocale = 0;
-
- assert(nArg==1 || nArg==2);
- bToUpper = (sqlite3_user_data(p)!=0);
- if( nArg==2 ){
- zLocale = (const char *)sqlite3_value_text(apArg[1]);
- }
-
- zInput = sqlite3_value_text16(apArg[0]);
- if( !zInput ){
- return;
- }
- nOut = nInput = sqlite3_value_bytes16(apArg[0]);
- if( nOut==0 ){
- sqlite3_result_text16(p, "", 0, SQLITE_STATIC);
- return;
- }
-
- for(cnt=0; cnt<2; cnt++){
- UChar *zNew = sqlite3_realloc(zOutput, nOut);
- if( zNew==0 ){
- sqlite3_free(zOutput);
- sqlite3_result_error_nomem(p);
- return;
- }
- zOutput = zNew;
- status = U_ZERO_ERROR;
- if( bToUpper ){
- nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
- }else{
- nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
- }
-
- if( U_SUCCESS(status) ){
- sqlite3_result_text16(p, zOutput, nOut, xFree);
- }else if( status==U_BUFFER_OVERFLOW_ERROR ){
- assert( cnt==0 );
- continue;
- }else{
- icuFunctionError(p, bToUpper ? "u_strToUpper" : "u_strToLower", status);
- }
- return;
- }
- assert( 0 ); /* Unreachable */
-}
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */
-
-/*
-** Collation sequence destructor function. The pCtx argument points to
-** a UCollator structure previously allocated using ucol_open().
-*/
-static void icuCollationDel(void *pCtx){
- UCollator *p = (UCollator *)pCtx;
- ucol_close(p);
-}
-
-/*
-** Collation sequence comparison function. The pCtx argument points to
-** a UCollator structure previously allocated using ucol_open().
-*/
-static int icuCollationColl(
- void *pCtx,
- int nLeft,
- const void *zLeft,
- int nRight,
- const void *zRight
-){
- UCollationResult res;
- UCollator *p = (UCollator *)pCtx;
- res = ucol_strcoll(p, (UChar *)zLeft, nLeft/2, (UChar *)zRight, nRight/2);
- switch( res ){
- case UCOL_LESS: return -1;
- case UCOL_GREATER: return +1;
- case UCOL_EQUAL: return 0;
- }
- assert(!"Unexpected return value from ucol_strcoll()");
- return 0;
-}
-
-/*
-** Implementation of the scalar function icu_load_collation().
-**
-** This scalar function is used to add ICU collation based collation
-** types to an SQLite database connection. It is intended to be called
-** as follows:
-**
-** SELECT icu_load_collation(<locale>, <collation-name>);
-**
-** Where <locale> is a string containing an ICU locale identifier (i.e.
-** "en_AU", "tr_TR" etc.) and <collation-name> is the name of the
-** collation sequence to create.
-*/
-static void icuLoadCollation(
- sqlite3_context *p,
- int nArg,
- sqlite3_value **apArg
-){
- sqlite3 *db = (sqlite3 *)sqlite3_user_data(p);
- UErrorCode status = U_ZERO_ERROR;
- const char *zLocale; /* Locale identifier - (eg. "jp_JP") */
- const char *zName; /* SQL Collation sequence name (eg. "japanese") */
- UCollator *pUCollator; /* ICU library collation object */
- int rc; /* Return code from sqlite3_create_collation_x() */
-
- assert(nArg==2);
- (void)nArg; /* Unused parameter */
- zLocale = (const char *)sqlite3_value_text(apArg[0]);
- zName = (const char *)sqlite3_value_text(apArg[1]);
-
- if( !zLocale || !zName ){
- return;
- }
-
- pUCollator = ucol_open(zLocale, &status);
- if( !U_SUCCESS(status) ){
- icuFunctionError(p, "ucol_open", status);
- return;
- }
- assert(p);
-
- rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
- icuCollationColl, icuCollationDel
- );
- if( rc!=SQLITE_OK ){
- ucol_close(pUCollator);
- sqlite3_result_error(p, "Error registering collation function", -1);
- }
-}
-
-/*
-** Register the ICU extension functions with database db.
-*/
-int sqlite3IcuInit(sqlite3 *db){
- static const struct IcuScalar {
- const char *zName; /* Function name */
- unsigned char nArg; /* Number of arguments */
- unsigned short enc; /* Optimal text encoding */
- unsigned char iContext; /* sqlite3_user_data() context */
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
- } scalars[] = {
- {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
- {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
- {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
- {"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
- {"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
- {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
- {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
- {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */
- };
- int rc = SQLITE_OK;
- int i;
-
- for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){
- const struct IcuScalar *p = &scalars[i];
- rc = sqlite3_create_function(
- db, p->zName, p->nArg, p->enc,
- p->iContext ? (void*)db : (void*)0,
- p->xFunc, 0, 0
- );
- }
-
- return rc;
-}
-
-#if !SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_icu_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi)
- return sqlite3IcuInit(db);
-}
-#endif
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/sqliteicu.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/sqliteicu.h
deleted file mode 100644
index 69b42f98210..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/icu/sqliteicu.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-** 2008 May 26
-**
-** 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 header file is used by programs that want to link against the
-** ICU extension. All it does is declare the sqlite3IcuInit() interface.
-*/
-#include "sqlite3.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int sqlite3IcuInit(sqlite3 *db);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/Makefile b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/Makefile
deleted file mode 100644
index 7022b5682c5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# This Makefile is designed for use with main.mk in the root directory of
-# this project. After including main.mk, the users makefile should contain:
-#
-# LSMDIR=$(TOP)/ext/lsm1/
-# LSMOPTS=-fPIC
-# include $(LSMDIR)/Makefile
-#
-# The most useful targets are [lsmtest] and [lsm.so].
-#
-
-LSMOBJ = \
- lsm_ckpt.o \
- lsm_file.o \
- lsm_log.o \
- lsm_main.o \
- lsm_mem.o \
- lsm_mutex.o \
- lsm_shared.o \
- lsm_sorted.o \
- lsm_str.o \
- lsm_tree.o \
- lsm_unix.o \
- lsm_win32.o \
- lsm_varint.o \
- lsm_vtab.o
-
-LSMHDR = \
- $(LSMDIR)/lsm.h \
- $(LSMDIR)/lsmInt.h
-
-LSMTESTSRC = $(LSMDIR)/lsm-test/lsmtest1.c $(LSMDIR)/lsm-test/lsmtest2.c \
- $(LSMDIR)/lsm-test/lsmtest3.c $(LSMDIR)/lsm-test/lsmtest4.c \
- $(LSMDIR)/lsm-test/lsmtest5.c $(LSMDIR)/lsm-test/lsmtest6.c \
- $(LSMDIR)/lsm-test/lsmtest7.c $(LSMDIR)/lsm-test/lsmtest8.c \
- $(LSMDIR)/lsm-test/lsmtest9.c \
- $(LSMDIR)/lsm-test/lsmtest_datasource.c \
- $(LSMDIR)/lsm-test/lsmtest_func.c $(LSMDIR)/lsm-test/lsmtest_io.c \
- $(LSMDIR)/lsm-test/lsmtest_main.c $(LSMDIR)/lsm-test/lsmtest_mem.c \
- $(LSMDIR)/lsm-test/lsmtest_tdb.c $(LSMDIR)/lsm-test/lsmtest_tdb3.c \
- $(LSMDIR)/lsm-test/lsmtest_util.c $(LSMDIR)/lsm-test/lsmtest_win32.c
-
-
-# all: lsm.so
-
-LSMOPTS += -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
-
-lsm.so: $(LSMOBJ)
- $(TCCX) -shared -o lsm.so $(LSMOBJ)
-
-%.o: $(LSMDIR)/%.c $(LSMHDR) sqlite3.h
- $(TCCX) $(LSMOPTS) -c $<
-
-lsmtest$(EXE): $(LSMOBJ) $(LSMTESTSRC) $(LSMTESTHDR) sqlite3.o
- # $(TCPPX) -c $(TOP)/lsm-test/lsmtest_tdb2.cc
- $(TCCX) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) sqlite3.o -o lsmtest$(EXE) $(THREADLIB) -lz
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/Makefile.msc b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/Makefile.msc
deleted file mode 100644
index 3e5a3b3310e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/Makefile.msc
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# This Makefile is designed for use with Makefile.msc in the root directory
-# of this project. The Makefile.msc should contain:
-#
-# LSMDIR=$(TOP)\ext\lsm1
-# !INCLUDE $(LSMDIR)\Makefile.msc
-#
-# The most useful targets are [lsmtest.exe] and [lsm.dll].
-#
-
-LSMOBJ = \
- lsm_ckpt.lo \
- lsm_file.lo \
- lsm_log.lo \
- lsm_main.lo \
- lsm_mem.lo \
- lsm_mutex.lo \
- lsm_shared.lo \
- lsm_sorted.lo \
- lsm_str.lo \
- lsm_tree.lo \
- lsm_unix.lo \
- lsm_win32.lo \
- lsm_varint.lo \
- lsm_vtab.lo
-
-LSMHDR = \
- $(LSMDIR)\lsm.h \
- $(LSMDIR)\lsmInt.h
-
-LSMTESTSRC = $(LSMDIR)\lsm-test\lsmtest1.c $(LSMDIR)\lsm-test\lsmtest2.c \
- $(LSMDIR)\lsm-test\lsmtest3.c $(LSMDIR)\lsm-test\lsmtest4.c \
- $(LSMDIR)\lsm-test\lsmtest5.c $(LSMDIR)\lsm-test\lsmtest6.c \
- $(LSMDIR)\lsm-test\lsmtest7.c $(LSMDIR)\lsm-test\lsmtest8.c \
- $(LSMDIR)\lsm-test\lsmtest9.c \
- $(LSMDIR)\lsm-test\lsmtest_datasource.c \
- $(LSMDIR)\lsm-test\lsmtest_func.c $(LSMDIR)\lsm-test\lsmtest_io.c \
- $(LSMDIR)\lsm-test\lsmtest_main.c $(LSMDIR)\lsm-test\lsmtest_mem.c \
- $(LSMDIR)\lsm-test\lsmtest_tdb.c $(LSMDIR)\lsm-test\lsmtest_tdb3.c \
- $(LSMDIR)\lsm-test\lsmtest_util.c $(LSMDIR)\lsm-test\lsmtest_win32.c
-
-# all: lsm.dll lsmtest.exe
-
-LSMOPTS = $(NO_WARN) -DLSM_MUTEX_WIN32=1 -I$(LSMDIR)
-
-!IF $(DEBUG)>2
-LSMOPTS = $(LSMOPTS) -DLSM_DEBUG=1
-!ENDIF
-
-!IF $(MEMDEBUG)!=0
-LSMOPTS = $(LSMOPTS) -DLSM_DEBUG_MEM=1
-!ENDIF
-
-lsm_ckpt.lo: $(LSMDIR)\lsm_ckpt.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_ckpt.c
-
-lsm_file.lo: $(LSMDIR)\lsm_file.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_file.c
-
-lsm_log.lo: $(LSMDIR)\lsm_log.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_log.c
-
-lsm_main.lo: $(LSMDIR)\lsm_main.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_main.c
-
-lsm_mem.lo: $(LSMDIR)\lsm_mem.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_mem.c
-
-lsm_mutex.lo: $(LSMDIR)\lsm_mutex.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_mutex.c
-
-lsm_shared.lo: $(LSMDIR)\lsm_shared.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_shared.c
-
-lsm_sorted.lo: $(LSMDIR)\lsm_sorted.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_sorted.c
-
-lsm_str.lo: $(LSMDIR)\lsm_str.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_str.c
-
-lsm_tree.lo: $(LSMDIR)\lsm_tree.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_tree.c
-
-lsm_unix.lo: $(LSMDIR)\lsm_unix.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_unix.c
-
-lsm_win32.lo: $(LSMDIR)\lsm_win32.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_win32.c
-
-lsm_varint.lo: $(LSMDIR)\lsm_varint.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_varint.c
-
-lsm_vtab.lo: $(LSMDIR)\lsm_vtab.c $(LSMHDR) $(SQLITE3H)
- $(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_vtab.c
-
-lsm.dll: $(LSMOBJ)
- $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ $(LSMOBJ)
- copy /Y $@ $(LSMDIR)\$@
-
-lsmtest.exe: $(LSMOBJ) $(LSMTESTSRC) $(LSMTESTHDR) $(LIBOBJ)
- $(LTLINK) $(LSMOPTS) $(LSMTESTSRC) /link $(LSMOBJ) $(LIBOBJ)
- copy /Y $@ $(LSMDIR)\$@
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/README b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/README
deleted file mode 100644
index 80654ee97ec..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/README
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-Organization of test case files:
-
- lsmtest1.c: Data tests. Tests that perform many inserts and deletes on a
- database file, then verify that the contents of the database can
- be queried.
-
- lsmtest2.c: Crash tests. Tests that attempt to verify that the database
- recovers correctly following an application or system crash.
-
- lsmtest3.c: Rollback tests. Tests that focus on the explicit rollback of
- transactions and sub-transactions.
-
- lsmtest4.c: Multi-client tests.
-
- lsmtest5.c: Multi-client tests with a different thread for each client.
-
- lsmtest6.c: OOM injection tests.
-
- lsmtest7.c: API tests.
-
- lsmtest8.c: Writer crash tests. Tests in this file attempt to verify that
- the system recovers and other clients proceed unaffected if
- a process fails in the middle of a write transaction.
-
- The difference from lsmtest2.c is that this file tests
- live-recovery (recovery from a failure that occurs while other
- clients are still running) whereas lsmtest2.c tests recovery
- from a system or power failure.
-
- lsmtest9.c: More data tests. These focus on testing that calling
- lsm_work(nMerge=1) to compact the database does not corrupt it.
- In other words, that databases containing block-redirects
- can be read and written.
-
-
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest.h
deleted file mode 100644
index ca60424adde..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest.h
+++ /dev/null
@@ -1,303 +0,0 @@
-
-#ifndef __WRAPPER_INT_H_
-#define __WRAPPER_INT_H_
-
-#include "lsmtest_tdb.h"
-#include "sqlite3.h"
-#include "lsm.h"
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#ifndef _WIN32
-# include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef _WIN32
-# include "windows.h"
-# define gettimeofday win32GetTimeOfDay
-# define F_OK (0)
-# define sleep(sec) Sleep(1000 * (sec))
-# define usleep(usec) Sleep(((usec) + 999) / 1000)
-# ifdef _MSC_VER
-# include <io.h>
-# define snprintf _snprintf
-# define fsync(fd) FlushFileBuffers((HANDLE)_get_osfhandle((fd)))
-# define fdatasync(fd) FlushFileBuffers((HANDLE)_get_osfhandle((fd)))
-# define __va_copy(dst,src) ((dst) = (src))
-# define ftruncate(fd,sz) ((_chsize_s((fd), (sz))==0) ? 0 : -1)
-# else
-# error Unsupported C compiler for Windows.
-# endif
-int win32GetTimeOfDay(struct timeval *, void *);
-#endif
-
-#ifndef _LSM_INT_H
-typedef unsigned int u32;
-typedef unsigned char u8;
-typedef long long int i64;
-typedef unsigned long long int u64;
-#endif
-
-
-#define ArraySize(x) ((int)(sizeof(x) / sizeof((x)[0])))
-
-#define MIN(x,y) ((x)<(y) ? (x) : (y))
-#define MAX(x,y) ((x)>(y) ? (x) : (y))
-
-#define unused_parameter(x) (void)(x)
-
-#define TESTDB_DEFAULT_PAGE_SIZE 4096
-#define TESTDB_DEFAULT_CACHE_SIZE 2048
-
-#ifndef _O_BINARY
-# define _O_BINARY (0)
-#endif
-
-/*
-** Ideally, these should be in wrapper.c. But they are here instead so that
-** they can be used by the C++ database wrappers in wrapper2.cc.
-*/
-typedef struct DatabaseMethods DatabaseMethods;
-struct TestDb {
- DatabaseMethods const *pMethods; /* Database methods */
- const char *zLibrary; /* Library name for tdb_open() */
-};
-struct DatabaseMethods {
- int (*xClose)(TestDb *);
- int (*xWrite)(TestDb *, void *, int , void *, int);
- int (*xDelete)(TestDb *, void *, int);
- int (*xDeleteRange)(TestDb *, void *, int, void *, int);
- int (*xFetch)(TestDb *, void *, int, void **, int *);
- int (*xScan)(TestDb *, void *, int, void *, int, void *, int,
- void (*)(void *, void *, int , void *, int)
- );
- int (*xBegin)(TestDb *, int);
- int (*xCommit)(TestDb *, int);
- int (*xRollback)(TestDb *, int);
-};
-
-/*
-** Functions in wrapper2.cc (a C++ source file). wrapper2.cc contains the
-** wrapper for Kyoto Cabinet. Kyoto cabinet has a C API, but
-** the primary interface is the C++ API.
-*/
-int test_kc_open(const char*, const char *zFilename, int bClear, TestDb **ppDb);
-int test_kc_close(TestDb *);
-int test_kc_write(TestDb *, void *, int , void *, int);
-int test_kc_delete(TestDb *, void *, int);
-int test_kc_delete_range(TestDb *, void *, int, void *, int);
-int test_kc_fetch(TestDb *, void *, int, void **, int *);
-int test_kc_scan(TestDb *, void *, int, void *, int, void *, int,
- void (*)(void *, void *, int , void *, int)
-);
-
-int test_mdb_open(const char*, const char *zFile, int bClear, TestDb **ppDb);
-int test_mdb_close(TestDb *);
-int test_mdb_write(TestDb *, void *, int , void *, int);
-int test_mdb_delete(TestDb *, void *, int);
-int test_mdb_fetch(TestDb *, void *, int, void **, int *);
-int test_mdb_scan(TestDb *, void *, int, void *, int, void *, int,
- void (*)(void *, void *, int , void *, int)
-);
-
-/*
-** Functions in wrapper3.c. This file contains the tdb wrapper for lsm.
-** The wrapper for lsm is a bit more involved than the others, as it
-** includes code for a couple of different lsm configurations, and for
-** various types of fault injection and robustness testing.
-*/
-int test_lsm_open(const char*, const char *zFile, int bClear, TestDb **ppDb);
-int test_lsm_lomem_open(const char*, const char*, int bClear, TestDb **ppDb);
-int test_lsm_lomem2_open(const char*, const char*, int bClear, TestDb **ppDb);
-int test_lsm_zip_open(const char*, const char*, int bClear, TestDb **ppDb);
-int test_lsm_small_open(const char*, const char*, int bClear, TestDb **ppDb);
-int test_lsm_mt2(const char*, const char *zFile, int bClear, TestDb **ppDb);
-int test_lsm_mt3(const char*, const char *zFile, int bClear, TestDb **ppDb);
-
-int tdb_lsm_configure(lsm_db *, const char *);
-
-/* Functions in lsmtest_tdb4.c */
-int test_bt_open(const char*, const char *zFile, int bClear, TestDb **ppDb);
-int test_fbt_open(const char*, const char *zFile, int bClear, TestDb **ppDb);
-int test_fbts_open(const char*, const char *zFile, int bClear, TestDb **ppDb);
-
-
-/* Functions in testutil.c. */
-int testPrngInit(void);
-u32 testPrngValue(u32 iVal);
-void testPrngArray(u32 iVal, u32 *aOut, int nOut);
-void testPrngString(u32 iVal, char *aOut, int nOut);
-
-void testErrorInit(int argc, char **);
-void testPrintError(const char *zFormat, ...);
-void testPrintUsage(const char *zArgs);
-void testPrintFUsage(const char *zFormat, ...);
-void testTimeInit(void);
-int testTimeGet(void);
-
-/* Functions in testmem.c. */
-void testMallocInstall(lsm_env *pEnv);
-void testMallocUninstall(lsm_env *pEnv);
-void testMallocCheck(lsm_env *pEnv, int *, int *, FILE *);
-void testMallocOom(lsm_env *pEnv, int, int, void(*)(void*), void *);
-void testMallocOomEnable(lsm_env *pEnv, int);
-
-/* lsmtest.c */
-TestDb *testOpen(const char *zSystem, int, int *pRc);
-void testReopen(TestDb **ppDb, int *pRc);
-void testClose(TestDb **ppDb);
-
-void testFetch(TestDb *, void *, int, void *, int, int *);
-void testWrite(TestDb *, void *, int, void *, int, int *);
-void testDelete(TestDb *, void *, int, int *);
-void testDeleteRange(TestDb *, void *, int, void *, int, int *);
-void testWriteStr(TestDb *, const char *, const char *zVal, int *pRc);
-void testFetchStr(TestDb *, const char *, const char *, int *pRc);
-
-void testBegin(TestDb *pDb, int iTrans, int *pRc);
-void testCommit(TestDb *pDb, int iTrans, int *pRc);
-
-void test_failed(void);
-
-char *testMallocPrintf(const char *zFormat, ...);
-char *testMallocVPrintf(const char *zFormat, va_list ap);
-int testGlobMatch(const char *zPattern, const char *zStr);
-
-void testScanCompare(TestDb *, TestDb *, int, void *, int, void *, int, int *);
-void testFetchCompare(TestDb *, TestDb *, void *, int, int *);
-
-void *testMalloc(int);
-void *testMallocCopy(void *pCopy, int nByte);
-void *testRealloc(void *, int);
-void testFree(void *);
-
-/* lsmtest_bt.c */
-int do_bt(int nArg, char **azArg);
-
-/* testio.c */
-int testVfsConfigureDb(TestDb *pDb);
-
-/* testfunc.c */
-int do_show(int nArg, char **azArg);
-int do_work(int nArg, char **azArg);
-
-/* testio.c */
-int do_io(int nArg, char **azArg);
-
-/* lsmtest2.c */
-void do_crash_test(const char *zPattern, int *pRc);
-int do_rollback_test(int nArg, char **azArg);
-
-/* test3.c */
-void test_rollback(const char *zSystem, const char *zPattern, int *pRc);
-
-/* test4.c */
-void test_mc(const char *zSystem, const char *zPattern, int *pRc);
-
-/* test5.c */
-void test_mt(const char *zSystem, const char *zPattern, int *pRc);
-
-/* lsmtest6.c */
-void test_oom(const char *zPattern, int *pRc);
-void testDeleteLsmdb(const char *zFile);
-
-void testSaveDb(const char *zFile, const char *zAuxExt);
-void testRestoreDb(const char *zFile, const char *zAuxExt);
-void testCopyLsmdb(const char *zFrom, const char *zTo);
-
-/* lsmtest7.c */
-void test_api(const char *zPattern, int *pRc);
-
-/* lsmtest8.c */
-void do_writer_crash_test(const char *zPattern, int *pRc);
-
-/*************************************************************************
-** Interface to functionality in test_datasource.c.
-*/
-typedef struct Datasource Datasource;
-typedef struct DatasourceDefn DatasourceDefn;
-
-struct DatasourceDefn {
- int eType; /* A TEST_DATASOURCE_* value */
- int nMinKey; /* Minimum key size */
- int nMaxKey; /* Maximum key size */
- int nMinVal; /* Minimum value size */
- int nMaxVal; /* Maximum value size */
-};
-
-#define TEST_DATASOURCE_RANDOM 1
-#define TEST_DATASOURCE_SEQUENCE 2
-
-char *testDatasourceName(const DatasourceDefn *);
-Datasource *testDatasourceNew(const DatasourceDefn *);
-void testDatasourceFree(Datasource *);
-void testDatasourceEntry(Datasource *, int, void **, int *, void **, int *);
-/* End of test_datasource.c interface.
-*************************************************************************/
-void testDatasourceFetch(
- TestDb *pDb, /* Database handle */
- Datasource *pData,
- int iKey,
- int *pRc /* IN/OUT: Error code */
-);
-
-void testWriteDatasource(TestDb *, Datasource *, int, int *);
-void testWriteDatasourceRange(TestDb *, Datasource *, int, int, int *);
-void testDeleteDatasource(TestDb *, Datasource *, int, int *);
-void testDeleteDatasourceRange(TestDb *, Datasource *, int, int, int *);
-
-
-/* test1.c */
-void test_data_1(const char *, const char *, int *pRc);
-void test_data_2(const char *, const char *, int *pRc);
-void test_data_3(const char *, const char *, int *pRc);
-void testDbContents(TestDb *, Datasource *, int, int, int, int, int, int *);
-void testCaseProgress(int, int, int, int *);
-int testCaseNDot(void);
-
-void testCompareDb(Datasource *, int, int, TestDb *, TestDb *, int *);
-int testControlDb(TestDb **ppDb);
-
-typedef struct CksumDb CksumDb;
-CksumDb *testCksumArrayNew(Datasource *, int, int, int);
-char *testCksumArrayGet(CksumDb *, int);
-void testCksumArrayFree(CksumDb *);
-void testCaseStart(int *pRc, char *zFmt, ...);
-void testCaseFinish(int rc);
-void testCaseSkip(void);
-int testCaseBegin(int *, const char *, const char *, ...);
-
-#define TEST_CKSUM_BYTES 29
-int testCksumDatabase(TestDb *pDb, char *zOut);
-int testCountDatabase(TestDb *pDb);
-void testCompareInt(int, int, int *);
-void testCompareStr(const char *z1, const char *z2, int *pRc);
-
-/* lsmtest9.c */
-void test_data_4(const char *, const char *, int *pRc);
-
-
-/*
-** Similar to the Tcl_GetIndexFromObjStruct() Tcl library function.
-*/
-#define testArgSelect(w,x,y,z) testArgSelectX(w,x,sizeof(w[0]),y,z)
-int testArgSelectX(void *, const char *, int, const char *, int *);
-
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest1.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest1.c
deleted file mode 100644
index 665dc15e58d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest1.c
+++ /dev/null
@@ -1,654 +0,0 @@
-
-#include "lsmtest.h"
-
-#define DATA_SEQUENTIAL TEST_DATASOURCE_SEQUENCE
-#define DATA_RANDOM TEST_DATASOURCE_RANDOM
-
-typedef struct Datatest1 Datatest1;
-typedef struct Datatest2 Datatest2;
-
-/*
-** An instance of the following structure contains parameters used to
-** customize the test function in this file. Test procedure:
-**
-** 1. Create a data-source based on the "datasource definition" vars.
-**
-** 2. Insert nRow key value pairs into the database.
-**
-** 3. Delete all keys from the database. Deletes are done in the same
-** order as the inserts.
-**
-** During steps 2 and 3 above, after each Datatest1.nVerify inserts or
-** deletes, the following:
-**
-** a. Run Datasource.nTest key lookups and check the results are as expected.
-**
-** b. If Datasource.bTestScan is true, run a handful (8) of range
-** queries (scanning forwards and backwards). Check that the results
-** are as expected.
-**
-** c. Close and reopen the database. Then run (a) and (b) again.
-*/
-struct Datatest1 {
- /* Datasource definition */
- DatasourceDefn defn;
-
- /* Test procedure parameters */
- int nRow; /* Number of rows to insert then delete */
- int nVerify; /* How often to verify the db contents */
- int nTest; /* Number of keys to test (0==all) */
- int bTestScan; /* True to do scan tests */
-};
-
-/*
-** An instance of the following data structure is used to describe the
-** second type of test case in this file. The chief difference between
-** these tests and those described by Datatest1 is that these tests also
-** experiment with range-delete operations. Tests proceed as follows:
-**
-** 1. Open the datasource described by Datatest2.defn.
-**
-** 2. Open a connection on an empty database.
-**
-** 3. Do this Datatest2.nIter times:
-**
-** a) Insert Datatest2.nWrite key-value pairs from the datasource.
-**
-** b) Select two pseudo-random keys and use them as the start
-** and end points of a range-delete operation.
-**
-** c) Verify that the contents of the database are as expected (see
-** below for details).
-**
-** d) Close and then reopen the database handle.
-**
-** e) Verify that the contents of the database are still as expected.
-**
-** The inserts and range deletes are run twice - once on the database being
-** tested and once using a control system (sqlite3, kc etc. - something that
-** works). In order to verify that the contents of the db being tested are
-** correct, the test runs a bunch of scans and lookups on both the test and
-** control databases. If the results are the same, the test passes.
-*/
-struct Datatest2 {
- DatasourceDefn defn;
- int nRange;
- int nWrite; /* Number of writes per iteration */
- int nIter; /* Total number of iterations to run */
-};
-
-/*
-** Generate a unique name for the test case pTest with database system
-** zSystem.
-*/
-static char *getName(const char *zSystem, int bRecover, Datatest1 *pTest){
- char *zRet;
- char *zData;
- zData = testDatasourceName(&pTest->defn);
- zRet = testMallocPrintf("data.%s.%s.rec=%d.%d.%d",
- zSystem, zData, bRecover, pTest->nRow, pTest->nVerify
- );
- testFree(zData);
- return zRet;
-}
-
-int testControlDb(TestDb **ppDb){
-#ifdef HAVE_KYOTOCABINET
- return tdb_open("kyotocabinet", "tmp.db", 1, ppDb);
-#else
- return tdb_open("sqlite3", "", 1, ppDb);
-#endif
-}
-
-void testDatasourceFetch(
- TestDb *pDb, /* Database handle */
- Datasource *pData,
- int iKey,
- int *pRc /* IN/OUT: Error code */
-){
- void *pKey; int nKey; /* Database key to query for */
- void *pVal; int nVal; /* Expected result of query */
-
- testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal);
- testFetch(pDb, pKey, nKey, pVal, nVal, pRc);
-}
-
-/*
-** This function is called to test that the contents of database pDb
-** are as expected. In this case, expected is defined as containing
-** key-value pairs iFirst through iLast, inclusive, from data source
-** pData. In other words, a loop like the following could be used to
-** construct a database with identical contents from scratch.
-**
-** for(i=iFirst; i<=iLast; i++){
-** testDatasourceEntry(pData, i, &pKey, &nKey, &pVal, &nVal);
-** // insert (pKey, nKey) -> (pVal, nVal) into database
-** }
-**
-** The key domain consists of keys 0 to (nRow-1), inclusive, from
-** data source pData. For both scan and lookup tests, keys are selected
-** pseudo-randomly from within this set.
-**
-** This function runs nLookupTest lookup tests and nScanTest scan tests.
-**
-** A lookup test consists of selecting a key from the domain and querying
-** pDb for it. The test fails if the presence of the key and, if present,
-** the associated value do not match the expectations defined above.
-**
-** A scan test involves selecting a key from the domain and running
-** the following queries:
-**
-** 1. Scan all keys equal to or greater than the key, in ascending order.
-** 2. Scan all keys equal to or smaller than the key, in descending order.
-**
-** Additionally, if nLookupTest is greater than zero, the following are
-** run once:
-**
-** 1. Scan all keys in the db, in ascending order.
-** 2. Scan all keys in the db, in descending order.
-**
-** As you would assume, the test fails if the returned values do not match
-** expectations.
-*/
-void testDbContents(
- TestDb *pDb, /* Database handle being tested */
- Datasource *pData, /* pDb contains data from here */
- int nRow, /* Size of key domain */
- int iFirst, /* Index of first key from pData in pDb */
- int iLast, /* Index of last key from pData in pDb */
- int nLookupTest, /* Number of lookup tests to run */
- int nScanTest, /* Number of scan tests to run */
- int *pRc /* IN/OUT: Error code */
-){
- int j;
- int rc = *pRc;
-
- if( rc==0 && nScanTest ){
- TestDb *pDb2 = 0;
-
- /* Open a control db (i.e. one that we assume works) */
- rc = testControlDb(&pDb2);
-
- for(j=iFirst; rc==0 && j<=iLast; j++){
- void *pKey; int nKey; /* Database key to insert */
- void *pVal; int nVal; /* Database value to insert */
- testDatasourceEntry(pData, j, &pKey, &nKey, &pVal, &nVal);
- rc = tdb_write(pDb2, pKey, nKey, pVal, nVal);
- }
-
- if( rc==0 ){
- int iKey1;
- int iKey2;
- void *pKey1; int nKey1; /* Start key */
- void *pKey2; int nKey2; /* Final key */
-
- iKey1 = testPrngValue((iFirst<<8) + (iLast<<16)) % nRow;
- iKey2 = testPrngValue((iLast<<8) + (iFirst<<16)) % nRow;
- testDatasourceEntry(pData, iKey1, &pKey2, &nKey1, 0, 0);
- pKey1 = testMalloc(nKey1+1);
- memcpy(pKey1, pKey2, nKey1+1);
- testDatasourceEntry(pData, iKey2, &pKey2, &nKey2, 0, 0);
-
- testScanCompare(pDb2, pDb, 0, 0, 0, 0, 0, &rc);
- testScanCompare(pDb2, pDb, 0, 0, 0, pKey2, nKey2, &rc);
- testScanCompare(pDb2, pDb, 0, pKey1, nKey1, 0, 0, &rc);
- testScanCompare(pDb2, pDb, 0, pKey1, nKey1, pKey2, nKey2, &rc);
- testScanCompare(pDb2, pDb, 1, 0, 0, 0, 0, &rc);
- testScanCompare(pDb2, pDb, 1, 0, 0, pKey2, nKey2, &rc);
- testScanCompare(pDb2, pDb, 1, pKey1, nKey1, 0, 0, &rc);
- testScanCompare(pDb2, pDb, 1, pKey1, nKey1, pKey2, nKey2, &rc);
- testFree(pKey1);
- }
- tdb_close(pDb2);
- }
-
- /* Test some lookups. */
- for(j=0; rc==0 && j<nLookupTest; j++){
- int iKey; /* Datasource key to test */
- void *pKey; int nKey; /* Database key to query for */
- void *pVal; int nVal; /* Expected result of query */
-
- if( nLookupTest>=nRow ){
- iKey = j;
- }else{
- iKey = testPrngValue(j + (iFirst<<8) + (iLast<<16)) % nRow;
- }
-
- testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal);
- if( iFirst>iKey || iKey>iLast ){
- pVal = 0;
- nVal = -1;
- }
-
- testFetch(pDb, pKey, nKey, pVal, nVal, &rc);
- }
-
- *pRc = rc;
-}
-
-/*
-** This function should be called during long running test cases to output
-** the progress dots (...) to stdout.
-*/
-void testCaseProgress(int i, int n, int nDot, int *piDot){
- int iDot = *piDot;
- while( iDot < ( ((nDot*2+1) * i) / (n*2) ) ){
- printf(".");
- fflush(stdout);
- iDot++;
- }
- *piDot = iDot;
-}
-
-int testCaseNDot(void){ return 20; }
-
-#if 0
-static void printScanCb(
- void *pCtx, void *pKey, int nKey, void *pVal, int nVal
-){
- printf("%s\n", (char *)pKey);
- fflush(stdout);
-}
-#endif
-
-void testReopenRecover(TestDb **ppDb, int *pRc){
- if( *pRc==0 ){
- const char *zLib = tdb_library_name(*ppDb);
- const char *zDflt = tdb_default_db(zLib);
- testCopyLsmdb(zDflt, "bak.db");
- testClose(ppDb);
- testCopyLsmdb("bak.db", zDflt);
- *pRc = tdb_open(zLib, 0, 0, ppDb);
- }
-}
-
-
-static void doDataTest1(
- const char *zSystem, /* Database system to test */
- int bRecover,
- Datatest1 *p, /* Structure containing test parameters */
- int *pRc /* OUT: Error code */
-){
- int i;
- int iDot;
- int rc = LSM_OK;
- Datasource *pData;
- TestDb *pDb;
-
- /* Start the test case, open a database and allocate the datasource. */
- pDb = testOpen(zSystem, 1, &rc);
- pData = testDatasourceNew(&p->defn);
-
- i = 0;
- iDot = 0;
- while( rc==LSM_OK && i<p->nRow ){
-
- /* Insert some data */
- testWriteDatasourceRange(pDb, pData, i, p->nVerify, &rc);
- i += p->nVerify;
-
- /* Check that the db content is correct. */
- testDbContents(pDb, pData, p->nRow, 0, i-1, p->nTest, p->bTestScan, &rc);
-
- if( bRecover ){
- testReopenRecover(&pDb, &rc);
- }else{
- testReopen(&pDb, &rc);
- }
-
- /* Check that the db content is still correct. */
- testDbContents(pDb, pData, p->nRow, 0, i-1, p->nTest, p->bTestScan, &rc);
-
- /* Update the progress dots... */
- testCaseProgress(i, p->nRow, testCaseNDot()/2, &iDot);
- }
-
- i = 0;
- iDot = 0;
- while( rc==LSM_OK && i<p->nRow ){
-
- /* Delete some entries */
- testDeleteDatasourceRange(pDb, pData, i, p->nVerify, &rc);
- i += p->nVerify;
-
- /* Check that the db content is correct. */
- testDbContents(pDb, pData, p->nRow, i, p->nRow-1,p->nTest,p->bTestScan,&rc);
-
- /* Close and reopen the database. */
- if( bRecover ){
- testReopenRecover(&pDb, &rc);
- }else{
- testReopen(&pDb, &rc);
- }
-
- /* Check that the db content is still correct. */
- testDbContents(pDb, pData, p->nRow, i, p->nRow-1,p->nTest,p->bTestScan,&rc);
-
- /* Update the progress dots... */
- testCaseProgress(i, p->nRow, testCaseNDot()/2, &iDot);
- }
-
- /* Free the datasource, close the database and finish the test case. */
- testDatasourceFree(pData);
- tdb_close(pDb);
- testCaseFinish(rc);
- *pRc = rc;
-}
-
-
-void test_data_1(
- const char *zSystem, /* Database system name */
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- Datatest1 aTest[] = {
- { {DATA_RANDOM, 500,600, 1000,2000}, 1000, 100, 10, 0},
- { {DATA_RANDOM, 20,25, 100,200}, 1000, 250, 1000, 1},
- { {DATA_RANDOM, 8,10, 100,200}, 1000, 250, 1000, 1},
- { {DATA_RANDOM, 8,10, 10,20}, 1000, 250, 1000, 1},
- { {DATA_RANDOM, 8,10, 1000,2000}, 1000, 250, 1000, 1},
- { {DATA_RANDOM, 8,100, 10000,20000}, 100, 25, 100, 1},
- { {DATA_RANDOM, 80,100, 10,20}, 1000, 250, 1000, 1},
- { {DATA_RANDOM, 5000,6000, 10,20}, 100, 25, 100, 1},
- { {DATA_SEQUENTIAL, 5,10, 10,20}, 1000, 250, 1000, 1},
- { {DATA_SEQUENTIAL, 5,10, 100,200}, 1000, 250, 1000, 1},
- { {DATA_SEQUENTIAL, 5,10, 1000,2000}, 1000, 250, 1000, 1},
- { {DATA_SEQUENTIAL, 5,100, 10000,20000}, 100, 25, 100, 1},
- { {DATA_RANDOM, 10,10, 100,100}, 100000, 1000, 100, 0},
- { {DATA_SEQUENTIAL, 10,10, 100,100}, 100000, 1000, 100, 0},
- };
-
- int i;
- int bRecover;
-
- for(bRecover=0; bRecover<2; bRecover++){
- if( bRecover==1 && memcmp(zSystem, "lsm", 3) ) break;
- for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
- char *zName = getName(zSystem, bRecover, &aTest[i]);
- if( testCaseBegin(pRc, zPattern, "%s", zName) ){
- doDataTest1(zSystem, bRecover, &aTest[i], pRc);
- }
- testFree(zName);
- }
- }
-}
-
-void testCompareDb(
- Datasource *pData,
- int nData,
- int iSeed,
- TestDb *pControl,
- TestDb *pDb,
- int *pRc
-){
- int i;
-
- static int nCall = 0;
- nCall++;
-
- testScanCompare(pControl, pDb, 0, 0, 0, 0, 0, pRc);
- testScanCompare(pControl, pDb, 1, 0, 0, 0, 0, pRc);
-
- if( *pRc==0 ){
- int iKey1;
- int iKey2;
- void *pKey1; int nKey1; /* Start key */
- void *pKey2; int nKey2; /* Final key */
-
- iKey1 = testPrngValue(iSeed) % nData;
- iKey2 = testPrngValue(iSeed+1) % nData;
- testDatasourceEntry(pData, iKey1, &pKey2, &nKey1, 0, 0);
- pKey1 = testMalloc(nKey1+1);
- memcpy(pKey1, pKey2, nKey1+1);
- testDatasourceEntry(pData, iKey2, &pKey2, &nKey2, 0, 0);
-
- testScanCompare(pControl, pDb, 0, 0, 0, pKey2, nKey2, pRc);
- testScanCompare(pControl, pDb, 0, pKey1, nKey1, 0, 0, pRc);
- testScanCompare(pControl, pDb, 0, pKey1, nKey1, pKey2, nKey2, pRc);
- testScanCompare(pControl, pDb, 1, 0, 0, pKey2, nKey2, pRc);
- testScanCompare(pControl, pDb, 1, pKey1, nKey1, 0, 0, pRc);
- testScanCompare(pControl, pDb, 1, pKey1, nKey1, pKey2, nKey2, pRc);
- testFree(pKey1);
- }
-
- for(i=0; i<nData && *pRc==0; i++){
- void *pKey; int nKey;
- testDatasourceEntry(pData, i, &pKey, &nKey, 0, 0);
- testFetchCompare(pControl, pDb, pKey, nKey, pRc);
- }
-}
-
-static void doDataTest2(
- const char *zSystem, /* Database system to test */
- int bRecover,
- Datatest2 *p, /* Structure containing test parameters */
- int *pRc /* OUT: Error code */
-){
- TestDb *pDb;
- TestDb *pControl;
- Datasource *pData;
- int i;
- int rc = LSM_OK;
- int iDot = 0;
-
- /* Start the test case, open a database and allocate the datasource. */
- pDb = testOpen(zSystem, 1, &rc);
- pData = testDatasourceNew(&p->defn);
- rc = testControlDb(&pControl);
-
- if( tdb_lsm(pDb) ){
- int nBuf = 32 * 1024 * 1024;
- lsm_config(tdb_lsm(pDb), LSM_CONFIG_AUTOFLUSH, &nBuf);
- }
-
- for(i=0; rc==0 && i<p->nIter; i++){
- void *pKey1; int nKey1;
- void *pKey2; int nKey2;
- int ii;
- int nRange = MIN(p->nIter*p->nWrite, p->nRange);
-
- for(ii=0; rc==0 && ii<p->nWrite; ii++){
- int iKey = (i*p->nWrite + ii) % p->nRange;
- testWriteDatasource(pControl, pData, iKey, &rc);
- testWriteDatasource(pDb, pData, iKey, &rc);
- }
-
- testDatasourceEntry(pData, i+1000000, &pKey1, &nKey1, 0, 0);
- pKey1 = testMallocCopy(pKey1, nKey1);
- testDatasourceEntry(pData, i+2000000, &pKey2, &nKey2, 0, 0);
-
- testDeleteRange(pDb, pKey1, nKey1, pKey2, nKey2, &rc);
- testDeleteRange(pControl, pKey1, nKey1, pKey2, nKey2, &rc);
- testFree(pKey1);
-
- testCompareDb(pData, nRange, i, pControl, pDb, &rc);
- if( bRecover ){
- testReopenRecover(&pDb, &rc);
- }else{
- testReopen(&pDb, &rc);
- }
- testCompareDb(pData, nRange, i, pControl, pDb, &rc);
-
- /* Update the progress dots... */
- testCaseProgress(i, p->nIter, testCaseNDot(), &iDot);
- }
-
- testClose(&pDb);
- testClose(&pControl);
- testDatasourceFree(pData);
- testCaseFinish(rc);
- *pRc = rc;
-}
-
-static char *getName2(const char *zSystem, int bRecover, Datatest2 *pTest){
- char *zRet;
- char *zData;
- zData = testDatasourceName(&pTest->defn);
- zRet = testMallocPrintf("data2.%s.%s.rec=%d.%d.%d.%d",
- zSystem, zData, bRecover, pTest->nRange, pTest->nWrite, pTest->nIter
- );
- testFree(zData);
- return zRet;
-}
-
-void test_data_2(
- const char *zSystem, /* Database system name */
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- Datatest2 aTest[] = {
- /* defn, nRange, nWrite, nIter */
- { {DATA_RANDOM, 20,25, 100,200}, 10000, 10, 50 },
- { {DATA_RANDOM, 20,25, 100,200}, 10000, 200, 50 },
- { {DATA_RANDOM, 20,25, 100,200}, 100, 10, 1000 },
- { {DATA_RANDOM, 20,25, 100,200}, 100, 200, 50 },
- };
-
- int i;
- int bRecover;
-
- for(bRecover=0; bRecover<2; bRecover++){
- if( bRecover==1 && memcmp(zSystem, "lsm", 3) ) break;
- for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
- char *zName = getName2(zSystem, bRecover, &aTest[i]);
- if( testCaseBegin(pRc, zPattern, "%s", zName) ){
- doDataTest2(zSystem, bRecover, &aTest[i], pRc);
- }
- testFree(zName);
- }
- }
-}
-
-/*************************************************************************
-** Test case data3.*
-*/
-
-typedef struct Datatest3 Datatest3;
-struct Datatest3 {
- int nRange; /* Keys are between 1 and this value, incl. */
- int nIter; /* Number of iterations */
- int nWrite; /* Number of writes per iteration */
- int nDelete; /* Number of deletes per iteration */
-
- int nValMin; /* Minimum value size for writes */
- int nValMax; /* Maximum value size for writes */
-};
-
-void testPutU32(u8 *aBuf, u32 iVal){
- aBuf[0] = (iVal >> 24) & 0xFF;
- aBuf[1] = (iVal >> 16) & 0xFF;
- aBuf[2] = (iVal >> 8) & 0xFF;
- aBuf[3] = (iVal >> 0) & 0xFF;
-}
-
-void dt3PutKey(u8 *aBuf, int iKey){
- assert( iKey<100000 && iKey>=0 );
- sprintf((char *)aBuf, "%.5d", iKey);
-}
-
-static void doDataTest3(
- const char *zSystem, /* Database system to test */
- Datatest3 *p, /* Structure containing test parameters */
- int *pRc /* OUT: Error code */
-){
- int iDot = 0;
- int rc = *pRc;
- TestDb *pDb;
- u8 *abPresent; /* Array of boolean */
- char *aVal; /* Buffer to hold values */
- int i;
- u32 iSeq = 10; /* prng counter */
-
- abPresent = (u8 *)testMalloc(p->nRange+1);
- aVal = (char *)testMalloc(p->nValMax+1);
- pDb = testOpen(zSystem, 1, &rc);
-
- for(i=0; i<p->nIter && rc==0; i++){
- int ii;
-
- testCaseProgress(i, p->nIter, testCaseNDot(), &iDot);
-
- /* Perform nWrite inserts */
- for(ii=0; ii<p->nWrite; ii++){
- u8 aKey[6];
- u32 iKey;
- int nVal;
-
- iKey = (testPrngValue(iSeq++) % p->nRange) + 1;
- nVal = (testPrngValue(iSeq++) % (p->nValMax - p->nValMin)) + p->nValMin;
- testPrngString(testPrngValue(iSeq++), aVal, nVal);
- dt3PutKey(aKey, iKey);
-
- testWrite(pDb, aKey, sizeof(aKey)-1, aVal, nVal, &rc);
- abPresent[iKey] = 1;
- }
-
- /* Perform nDelete deletes */
- for(ii=0; ii<p->nDelete; ii++){
- u8 aKey1[6];
- u8 aKey2[6];
- u32 iKey;
-
- iKey = (testPrngValue(iSeq++) % p->nRange) + 1;
- dt3PutKey(aKey1, iKey-1);
- dt3PutKey(aKey2, iKey+1);
-
- testDeleteRange(pDb, aKey1, sizeof(aKey1)-1, aKey2, sizeof(aKey2)-1, &rc);
- abPresent[iKey] = 0;
- }
-
- testReopen(&pDb, &rc);
-
- for(ii=1; rc==0 && ii<=p->nRange; ii++){
- int nDbVal;
- void *pDbVal;
- u8 aKey[6];
- int dbrc;
-
- dt3PutKey(aKey, ii);
- dbrc = tdb_fetch(pDb, aKey, sizeof(aKey)-1, &pDbVal, &nDbVal);
- testCompareInt(0, dbrc, &rc);
-
- if( abPresent[ii] ){
- testCompareInt(1, (nDbVal>0), &rc);
- }else{
- testCompareInt(1, (nDbVal<0), &rc);
- }
- }
- }
-
- testClose(&pDb);
- testCaseFinish(rc);
- *pRc = rc;
-}
-
-static char *getName3(const char *zSystem, Datatest3 *p){
- return testMallocPrintf("data3.%s.%d.%d.%d.%d.(%d..%d)",
- zSystem, p->nRange, p->nIter, p->nWrite, p->nDelete,
- p->nValMin, p->nValMax
- );
-}
-
-void test_data_3(
- const char *zSystem, /* Database system name */
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- Datatest3 aTest[] = {
- /* nRange, nIter, nWrite, nDelete, nValMin, nValMax */
- { 100, 1000, 5, 5, 50, 100 },
- { 100, 1000, 2, 2, 5, 10 },
- };
-
- int i;
-
- for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
- char *zName = getName3(zSystem, &aTest[i]);
- if( testCaseBegin(pRc, zPattern, "%s", zName) ){
- doDataTest3(zSystem, &aTest[i], pRc);
- }
- testFree(zName);
- }
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest2.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest2.c
deleted file mode 100644
index d2ef0eb360b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest2.c
+++ /dev/null
@@ -1,488 +0,0 @@
-
-/*
-** This file contains tests related to recovery following application
-** and system crashes (power failures) while writing to the database.
-*/
-
-#include "lsmtest.h"
-
-/*
-** Structure used by testCksumDatabase() to accumulate checksum values in.
-*/
-typedef struct Cksum Cksum;
-struct Cksum {
- int nRow;
- int cksum1;
- int cksum2;
-};
-
-/*
-** tdb_scan() callback used by testCksumDatabase()
-*/
-static void scanCksumDb(
- void *pCtx,
- void *pKey, int nKey,
- void *pVal, int nVal
-){
- Cksum *p = (Cksum *)pCtx;
- int i;
-
- p->nRow++;
- for(i=0; i<nKey; i++){
- p->cksum1 += ((u8 *)pKey)[i];
- p->cksum2 += p->cksum1;
- }
- for(i=0; i<nVal; i++){
- p->cksum1 += ((u8 *)pVal)[i];
- p->cksum2 += p->cksum1;
- }
-}
-
-/*
-** tdb_scan() callback used by testCountDatabase()
-*/
-static void scanCountDb(
- void *pCtx,
- void *pKey, int nKey,
- void *pVal, int nVal
-){
- Cksum *p = (Cksum *)pCtx;
- p->nRow++;
-
- unused_parameter(pKey);
- unused_parameter(nKey);
- unused_parameter(pVal);
- unused_parameter(nVal);
-}
-
-
-/*
-** Iterate through the entire contents of database pDb. Write a checksum
-** string based on the db contents into buffer zOut before returning. A
-** checksum string is at most 29 (TEST_CKSUM_BYTES) bytes in size:
-**
-** * 32-bit integer (10 bytes)
-** * 1 space (1 byte)
-** * 32-bit hex (8 bytes)
-** * 1 space (1 byte)
-** * 32-bit hex (8 bytes)
-** * nul-terminator (1 byte)
-**
-** The number of entries in the database is returned.
-*/
-int testCksumDatabase(
- TestDb *pDb, /* Database handle */
- char *zOut /* Buffer to write checksum to */
-){
- Cksum cksum;
- memset(&cksum, 0, sizeof(Cksum));
- tdb_scan(pDb, (void *)&cksum, 0, 0, 0, 0, 0, scanCksumDb);
- sprintf(zOut, "%d %x %x",
- cksum.nRow, (u32)cksum.cksum1, (u32)cksum.cksum2
- );
- assert( strlen(zOut)<TEST_CKSUM_BYTES );
- return cksum.nRow;
-}
-
-int testCountDatabase(TestDb *pDb){
- Cksum cksum;
- memset(&cksum, 0, sizeof(Cksum));
- tdb_scan(pDb, (void *)&cksum, 0, 0, 0, 0, 0, scanCountDb);
- return cksum.nRow;
-}
-
-/*
-** This function is a no-op if *pRc is not 0 when it is called.
-**
-** Otherwise, the two nul-terminated strings z1 and z1 are compared. If
-** they are the same, the function returns without doing anything. Otherwise,
-** an error message is printed, *pRc is set to 1 and the test_failed()
-** function called.
-*/
-void testCompareStr(const char *z1, const char *z2, int *pRc){
- if( *pRc==0 ){
- if( strcmp(z1, z2) ){
- testPrintError("testCompareStr: \"%s\" != \"%s\"\n", z1, z2);
- *pRc = 1;
- test_failed();
- }
- }
-}
-
-/*
-** This function is a no-op if *pRc is not 0 when it is called.
-**
-** Otherwise, the two integers i1 and i2 are compared. If they are equal,
-** the function returns without doing anything. Otherwise, an error message
-** is printed, *pRc is set to 1 and the test_failed() function called.
-*/
-void testCompareInt(int i1, int i2, int *pRc){
- if( *pRc==0 && i1!=i2 ){
- testPrintError("testCompareInt: %d != %d\n", i1, i2);
- *pRc = 1;
- test_failed();
- }
-}
-
-void testCaseStart(int *pRc, char *zFmt, ...){
- va_list ap;
- va_start(ap, zFmt);
- vprintf(zFmt, ap);
- printf(" ...");
- va_end(ap);
- *pRc = 0;
- fflush(stdout);
-}
-
-/*
-** This function is a no-op if *pRc is non-zero when it is called. Zero
-** is returned in this case.
-**
-** Otherwise, the zFmt (a printf style format string) and following arguments
-** are used to create a test case name. If zPattern is NULL or a glob pattern
-** that matches the test case name, 1 is returned and the test case started.
-** Otherwise, zero is returned and the test case does not start.
-*/
-int testCaseBegin(int *pRc, const char *zPattern, const char *zFmt, ...){
- int res = 0;
- if( *pRc==0 ){
- char *zTest;
- va_list ap;
-
- va_start(ap, zFmt);
- zTest = testMallocVPrintf(zFmt, ap);
- va_end(ap);
- if( zPattern==0 || testGlobMatch(zPattern, zTest) ){
- printf("%-50s ...", zTest);
- res = 1;
- }
- testFree(zTest);
- fflush(stdout);
- }
-
- return res;
-}
-
-void testCaseFinish(int rc){
- if( rc==0 ){
- printf("Ok\n");
- }else{
- printf("FAILED\n");
- }
- fflush(stdout);
-}
-
-void testCaseSkip(){
- printf("Skipped\n");
-}
-
-void testSetupSavedLsmdb(
- const char *zCfg,
- const char *zFile,
- Datasource *pData,
- int nRow,
- int *pRc
-){
- if( *pRc==0 ){
- int rc;
- TestDb *pDb;
- rc = tdb_lsm_open(zCfg, zFile, 1, &pDb);
- if( rc==0 ){
- testWriteDatasourceRange(pDb, pData, 0, nRow, &rc);
- testClose(&pDb);
- if( rc==0 ) testSaveDb(zFile, "log");
- }
- *pRc = rc;
- }
-}
-
-/*
-** This function is a no-op if *pRc is non-zero when it is called.
-**
-** Open the LSM database identified by zFile and compute its checksum
-** (a string, as returned by testCksumDatabase()). If the checksum is
-** identical to zExpect1 or, if it is not NULL, zExpect2, the test passes.
-** Otherwise, print an error message and set *pRc to 1.
-*/
-static void testCompareCksumLsmdb(
- const char *zFile, /* Path to LSM database */
- int bCompress, /* True if db is compressed */
- const char *zExpect1, /* Expected checksum 1 */
- const char *zExpect2, /* Expected checksum 2 (or NULL) */
- int *pRc /* IN/OUT: Test case error code */
-){
- if( *pRc==0 ){
- char zCksum[TEST_CKSUM_BYTES];
- TestDb *pDb;
-
- *pRc = tdb_lsm_open((bCompress?"compression=1 mmap=0":""), zFile, 0, &pDb);
- testCksumDatabase(pDb, zCksum);
- testClose(&pDb);
-
- if( *pRc==0 ){
- int r1 = 0;
- int r2 = -1;
-
- r1 = strcmp(zCksum, zExpect1);
- if( zExpect2 ) r2 = strcmp(zCksum, zExpect2);
- if( r1 && r2 ){
- if( zExpect2 ){
- testPrintError("testCompareCksumLsmdb: \"%s\" != (\"%s\" OR \"%s\")",
- zCksum, zExpect1, zExpect2
- );
- }else{
- testPrintError("testCompareCksumLsmdb: \"%s\" != \"%s\"",
- zCksum, zExpect1
- );
- }
- *pRc = 1;
- test_failed();
- }
- }
- }
-}
-
-#if 0 /* not used */
-static void testCompareCksumBtdb(
- const char *zFile, /* Path to LSM database */
- const char *zExpect1, /* Expected checksum 1 */
- const char *zExpect2, /* Expected checksum 2 (or NULL) */
- int *pRc /* IN/OUT: Test case error code */
-){
- if( *pRc==0 ){
- char zCksum[TEST_CKSUM_BYTES];
- TestDb *pDb;
-
- *pRc = tdb_open("bt", zFile, 0, &pDb);
- testCksumDatabase(pDb, zCksum);
- testClose(&pDb);
-
- if( *pRc==0 ){
- int r1 = 0;
- int r2 = -1;
-
- r1 = strcmp(zCksum, zExpect1);
- if( zExpect2 ) r2 = strcmp(zCksum, zExpect2);
- if( r1 && r2 ){
- if( zExpect2 ){
- testPrintError("testCompareCksumLsmdb: \"%s\" != (\"%s\" OR \"%s\")",
- zCksum, zExpect1, zExpect2
- );
- }else{
- testPrintError("testCompareCksumLsmdb: \"%s\" != \"%s\"",
- zCksum, zExpect1
- );
- }
- *pRc = 1;
- test_failed();
- }
- }
- }
-}
-#endif /* not used */
-
-/* Above this point are reusable test routines. Not clear that they
-** should really be in this file.
-*************************************************************************/
-
-/*
-** This test verifies that if a system crash occurs while doing merge work
-** on the db, no data is lost.
-*/
-static void crash_test1(int bCompress, int *pRc){
- const char *DBNAME = "testdb.lsm";
- const DatasourceDefn defn = {TEST_DATASOURCE_RANDOM, 12, 16, 200, 200};
-
- const int nRow = 5000; /* Database size */
- const int nIter = 200; /* Number of test iterations */
- const int nWork = 20; /* Maximum lsm_work() calls per iteration */
- const int nPage = 15; /* Pages per lsm_work call */
-
- int i;
- int iDot = 0;
- Datasource *pData;
- CksumDb *pCksumDb;
- TestDb *pDb;
- char *zCfg;
-
- const char *azConfig[2] = {
- "page_size=1024 block_size=65536 autoflush=16384 safety=2 mmap=0",
- "page_size=1024 block_size=65536 autoflush=16384 safety=2 "
- " compression=1 mmap=0"
- };
- assert( bCompress==0 || bCompress==1 );
-
- /* Allocate datasource. And calculate the expected checksums. */
- pData = testDatasourceNew(&defn);
- pCksumDb = testCksumArrayNew(pData, nRow, nRow, 1);
-
- /* Setup and save the initial database. */
-
- zCfg = testMallocPrintf("%s automerge=7", azConfig[bCompress]);
- testSetupSavedLsmdb(zCfg, DBNAME, pData, 5000, pRc);
- testFree(zCfg);
-
- for(i=0; i<nIter && *pRc==0; i++){
- int iWork;
- int testrc = 0;
-
- testCaseProgress(i, nIter, testCaseNDot(), &iDot);
-
- /* Restore and open the database. */
- testRestoreDb(DBNAME, "log");
- testrc = tdb_lsm_open(azConfig[bCompress], DBNAME, 0, &pDb);
- assert( testrc==0 );
-
- /* Call lsm_work() on the db */
- tdb_lsm_prepare_sync_crash(pDb, 1 + (i%(nWork*2)));
- for(iWork=0; testrc==0 && iWork<nWork; iWork++){
- int nWrite = 0;
- lsm_db *db = tdb_lsm(pDb);
- testrc = lsm_work(db, 0, nPage, &nWrite);
- /* assert( testrc!=0 || nWrite>0 ); */
- if( testrc==0 ) testrc = lsm_checkpoint(db, 0);
- }
- tdb_close(pDb);
-
- /* Check that the database content is still correct */
- testCompareCksumLsmdb(DBNAME,
- bCompress, testCksumArrayGet(pCksumDb, nRow), 0, pRc);
- }
-
- testCksumArrayFree(pCksumDb);
- testDatasourceFree(pData);
-}
-
-/*
-** This test verifies that if a system crash occurs while committing a
-** transaction to the log file, no earlier transactions are lost or damaged.
-*/
-static void crash_test2(int bCompress, int *pRc){
- const char *DBNAME = "testdb.lsm";
- const DatasourceDefn defn = {TEST_DATASOURCE_RANDOM, 12, 16, 1000, 1000};
-
- const int nIter = 200;
- const int nInsert = 20;
-
- int i;
- int iDot = 0;
- Datasource *pData;
- CksumDb *pCksumDb;
- TestDb *pDb;
-
- /* Allocate datasource. And calculate the expected checksums. */
- pData = testDatasourceNew(&defn);
- pCksumDb = testCksumArrayNew(pData, 100, 100+nInsert, 1);
-
- /* Setup and save the initial database. */
- testSetupSavedLsmdb("", DBNAME, pData, 100, pRc);
-
- for(i=0; i<nIter && *pRc==0; i++){
- int iIns;
- int testrc = 0;
-
- testCaseProgress(i, nIter, testCaseNDot(), &iDot);
-
- /* Restore and open the database. */
- testRestoreDb(DBNAME, "log");
- testrc = tdb_lsm_open("safety=2", DBNAME, 0, &pDb);
- assert( testrc==0 );
-
- /* Insert nInsert records into the database. Crash midway through. */
- tdb_lsm_prepare_sync_crash(pDb, 1 + (i%(nInsert+2)));
- for(iIns=0; iIns<nInsert; iIns++){
- void *pKey; int nKey;
- void *pVal; int nVal;
-
- testDatasourceEntry(pData, 100+iIns, &pKey, &nKey, &pVal, &nVal);
- testrc = tdb_write(pDb, pKey, nKey, pVal, nVal);
- if( testrc ) break;
- }
- tdb_close(pDb);
-
- /* Check that no data was lost when the system crashed. */
- testCompareCksumLsmdb(DBNAME, bCompress,
- testCksumArrayGet(pCksumDb, 100 + iIns),
- testCksumArrayGet(pCksumDb, 100 + iIns + 1),
- pRc
- );
- }
-
- testDatasourceFree(pData);
- testCksumArrayFree(pCksumDb);
-}
-
-
-/*
-** This test verifies that if a system crash occurs when checkpointing
-** the database, data is not lost (assuming that any writes not synced
-** to the db have been synced into the log file).
-*/
-static void crash_test3(int bCompress, int *pRc){
- const char *DBNAME = "testdb.lsm";
- const int nIter = 100;
- const DatasourceDefn defn = {TEST_DATASOURCE_RANDOM, 12, 16, 1000, 1000};
-
- int i;
- int iDot = 0;
- Datasource *pData;
- CksumDb *pCksumDb;
- TestDb *pDb;
-
- /* Allocate datasource. And calculate the expected checksums. */
- pData = testDatasourceNew(&defn);
- pCksumDb = testCksumArrayNew(pData, 110, 150, 10);
-
- /* Setup and save the initial database. */
- testSetupSavedLsmdb("", DBNAME, pData, 100, pRc);
-
- for(i=0; i<nIter && *pRc==0; i++){
- int iOpen;
- testCaseProgress(i, nIter, testCaseNDot(), &iDot);
- testRestoreDb(DBNAME, "log");
-
- for(iOpen=0; iOpen<5; iOpen++){
- /* Open the database. Insert 10 more records. */
- pDb = testOpen("lsm", 0, pRc);
- testWriteDatasourceRange(pDb, pData, 100+iOpen*10, 10, pRc);
-
- /* Schedule a crash simulation then close the db. */
- tdb_lsm_prepare_sync_crash(pDb, 1 + (i%2));
- tdb_close(pDb);
-
- /* Open the database and check that the crash did not cause any
- ** data loss. */
- testCompareCksumLsmdb(DBNAME, bCompress,
- testCksumArrayGet(pCksumDb, 110 + iOpen*10), 0,
- pRc
- );
- }
- }
-
- testDatasourceFree(pData);
- testCksumArrayFree(pCksumDb);
-}
-
-void do_crash_test(const char *zPattern, int *pRc){
- struct Test {
- const char *zTest;
- void (*x)(int, int *);
- int bCompress;
- } aTest [] = {
- { "crash.lsm.1", crash_test1, 0 },
-#ifdef HAVE_ZLIB
- { "crash.lsm_zip.1", crash_test1, 1 },
-#endif
- { "crash.lsm.2", crash_test2, 0 },
- { "crash.lsm.3", crash_test3, 0 },
- };
- int i;
-
- for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
- struct Test *p = &aTest[i];
- if( testCaseBegin(pRc, zPattern, "%s", p->zTest) ){
- p->x(p->bCompress, pRc);
- testCaseFinish(*pRc);
- }
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest3.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest3.c
deleted file mode 100644
index 760dec300f4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest3.c
+++ /dev/null
@@ -1,238 +0,0 @@
-
-
-/*
-** This file contains tests related to the explicit rollback of database
-** transactions and sub-transactions.
-*/
-
-
-/*
-** Repeat 2000 times (until the db contains 100,000 entries):
-**
-** 1. Open a transaction and insert 500 rows, opening a nested
-** sub-transaction each 100 rows.
-**
-** 2. Roll back to each sub-transaction savepoint. Check the database
-** checksum looks Ok.
-**
-** 3. Every second iteration, roll back the main transaction. Check the
-** db checksum is correct. Every other iteration, commit the main
-** transaction (increasing the size of the db by 100 rows).
-*/
-
-
-#include "lsmtest.h"
-
-struct CksumDb {
- int nFirst;
- int nLast;
- int nStep;
- char **azCksum;
-};
-
-CksumDb *testCksumArrayNew(
- Datasource *pData,
- int nFirst,
- int nLast,
- int nStep
-){
- TestDb *pDb;
- CksumDb *pRet;
- int i;
- int nEntry;
- int rc = 0;
-
- assert( nLast>=nFirst && ((nLast-nFirst)%nStep)==0 );
-
- pRet = malloc(sizeof(CksumDb));
- memset(pRet, 0, sizeof(CksumDb));
- pRet->nFirst = nFirst;
- pRet->nLast = nLast;
- pRet->nStep = nStep;
- nEntry = 1 + ((nLast - nFirst) / nStep);
-
- /* Allocate space so that azCksum is an array of nEntry pointers to
- ** buffers each TEST_CKSUM_BYTES in size. */
- pRet->azCksum = (char **)malloc(nEntry * (sizeof(char *) + TEST_CKSUM_BYTES));
- for(i=0; i<nEntry; i++){
- char *pStart = (char *)(&pRet->azCksum[nEntry]);
- pRet->azCksum[i] = &pStart[i * TEST_CKSUM_BYTES];
- }
-
- tdb_open("lsm", "tempdb.lsm", 1, &pDb);
- testWriteDatasourceRange(pDb, pData, 0, nFirst, &rc);
- for(i=0; i<nEntry; i++){
- testCksumDatabase(pDb, pRet->azCksum[i]);
- if( i==nEntry ) break;
- testWriteDatasourceRange(pDb, pData, nFirst+i*nStep, nStep, &rc);
- }
-
- tdb_close(pDb);
-
- return pRet;
-}
-
-char *testCksumArrayGet(CksumDb *p, int nRow){
- int i;
- assert( nRow>=p->nFirst );
- assert( nRow<=p->nLast );
- assert( ((nRow-p->nFirst) % p->nStep)==0 );
-
- i = (nRow - p->nFirst) / p->nStep;
- return p->azCksum[i];
-}
-
-void testCksumArrayFree(CksumDb *p){
- free(p->azCksum);
- memset(p, 0x55, sizeof(*p));
- free(p);
-}
-
-/* End of CksumDb code.
-**************************************************************************/
-
-/*
-** Test utility function. Write key-value pair $i from datasource pData
-** into database pDb.
-*/
-void testWriteDatasource(TestDb *pDb, Datasource *pData, int i, int *pRc){
- void *pKey; int nKey;
- void *pVal; int nVal;
- testDatasourceEntry(pData, i, &pKey, &nKey, &pVal, &nVal);
- testWrite(pDb, pKey, nKey, pVal, nVal, pRc);
-}
-
-/*
-** Test utility function. Delete datasource pData key $i from database pDb.
-*/
-void testDeleteDatasource(TestDb *pDb, Datasource *pData, int i, int *pRc){
- void *pKey; int nKey;
- testDatasourceEntry(pData, i, &pKey, &nKey, 0, 0);
- testDelete(pDb, pKey, nKey, pRc);
-}
-
-/*
-** This function inserts nWrite key/value pairs into database pDb - the
-** nWrite key value pairs starting at iFirst from data source pData.
-*/
-void testWriteDatasourceRange(
- TestDb *pDb, /* Database to write to */
- Datasource *pData, /* Data source to read values from */
- int iFirst, /* Index of first key/value pair */
- int nWrite, /* Number of key/value pairs to write */
- int *pRc /* IN/OUT: Error code */
-){
- int i;
- for(i=0; i<nWrite; i++){
- testWriteDatasource(pDb, pData, iFirst+i, pRc);
- }
-}
-
-void testDeleteDatasourceRange(
- TestDb *pDb, /* Database to write to */
- Datasource *pData, /* Data source to read keys from */
- int iFirst, /* Index of first key */
- int nWrite, /* Number of keys to delete */
- int *pRc /* IN/OUT: Error code */
-){
- int i;
- for(i=0; i<nWrite; i++){
- testDeleteDatasource(pDb, pData, iFirst+i, pRc);
- }
-}
-
-static char *getName(const char *zSystem){
- char *zRet;
- zRet = testMallocPrintf("rollback.%s", zSystem);
- return zRet;
-}
-
-static int rollback_test_1(
- const char *zSystem,
- Datasource *pData
-){
- const int nRepeat = 100;
-
- TestDb *pDb;
- int rc;
- int i;
- CksumDb *pCksum;
- char *zName;
-
- zName = getName(zSystem);
- testCaseStart(&rc, zName);
- testFree(zName);
-
- pCksum = testCksumArrayNew(pData, 0, nRepeat*100, 100);
- pDb = 0;
- rc = tdb_open(zSystem, 0, 1, &pDb);
- if( pDb && tdb_transaction_support(pDb)==0 ){
- testCaseSkip();
- goto skip_rollback_test;
- }
-
- for(i=0; i<nRepeat && rc==0; i++){
- char zCksum[TEST_CKSUM_BYTES];
- int nCurrent = (((i+1)/2) * 100);
- int nDbRow;
- int iTrans;
-
- /* Check that the database is the expected size. */
- nDbRow = testCountDatabase(pDb);
- testCompareInt(nCurrent, nDbRow, &rc);
-
- for(iTrans=2; iTrans<=6 && rc==0; iTrans++){
- tdb_begin(pDb, iTrans);
- testWriteDatasourceRange(pDb, pData, nCurrent, 100, &rc);
- nCurrent += 100;
- }
-
- testCksumDatabase(pDb, zCksum);
- testCompareStr(zCksum, testCksumArrayGet(pCksum, nCurrent), &rc);
-
- for(iTrans=6; iTrans>2 && rc==0; iTrans--){
- tdb_rollback(pDb, iTrans);
- nCurrent -= 100;
- testCksumDatabase(pDb, zCksum);
- testCompareStr(zCksum, testCksumArrayGet(pCksum, nCurrent), &rc);
- }
-
- if( i%2 ){
- tdb_rollback(pDb, 0);
- nCurrent -= 100;
- testCksumDatabase(pDb, zCksum);
- testCompareStr(zCksum, testCksumArrayGet(pCksum, nCurrent), &rc);
- }else{
- tdb_commit(pDb, 0);
- }
- }
- testCaseFinish(rc);
-
- skip_rollback_test:
- tdb_close(pDb);
- testCksumArrayFree(pCksum);
- return rc;
-}
-
-void test_rollback(
- const char *zSystem,
- const char *zPattern,
- int *pRc
-){
- if( *pRc==0 ){
- int bRun = 1;
-
- if( zPattern ){
- char *zName = getName(zSystem);
- bRun = testGlobMatch(zPattern, zName);
- testFree(zName);
- }
-
- if( bRun ){
- DatasourceDefn defn = { TEST_DATASOURCE_RANDOM, 10, 15, 50, 100 };
- Datasource *pData = testDatasourceNew(&defn);
- *pRc = rollback_test_1(zSystem, pData);
- testDatasourceFree(pData);
- }
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest4.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest4.c
deleted file mode 100644
index a47241db929..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest4.c
+++ /dev/null
@@ -1,127 +0,0 @@
-
-/*
-** This file contains test cases involving multiple database clients.
-*/
-
-#include "lsmtest.h"
-
-/*
-** The following code implements test cases "mc1.*".
-**
-** This test case uses one writer and $nReader readers. All connections
-** are driven by a single thread. All connections are opened at the start
-** of the test and remain open until the test is finished.
-**
-** The test consists of $nStep steps. Each step the following is performed:
-**
-** 1. The writer inserts $nWriteStep records into the db.
-**
-** 2. The writer checks that the contents of the db are as expected.
-**
-** 3. Each reader that currently has an open read transaction also checks
-** that the contents of the db are as expected (according to the snapshot
-** the read transaction is reading - see below).
-**
-** After step 1, reader 1 opens a read transaction. After step 2, reader
-** 2 opens a read transaction, and so on. At step ($nReader+1), reader 1
-** closes the current read transaction and opens a new one. And so on.
-** The result is that at step N (for N > $nReader), there exists a reader
-** with an open read transaction reading the snapshot committed following
-** steps (N-$nReader-1) to N.
-*/
-typedef struct Mctest Mctest;
-struct Mctest {
- DatasourceDefn defn; /* Datasource to use */
- int nStep; /* Total number of steps in test */
- int nWriteStep; /* Number of rows to insert each step */
- int nReader; /* Number of read connections */
-};
-static void do_mc_test(
- const char *zSystem, /* Database system to test */
- Mctest *pTest,
- int *pRc /* IN/OUT: return code */
-){
- const int nDomain = pTest->nStep * pTest->nWriteStep;
- Datasource *pData; /* Source of data */
- TestDb *pDb; /* First database connection (writer) */
- int iReader; /* Used to iterate through aReader */
- int iStep; /* Current step in test */
- int iDot = 0; /* Current step in test */
-
- /* Array of reader connections */
- struct Reader {
- TestDb *pDb; /* Connection handle */
- int iLast; /* Current snapshot contains keys 0..iLast */
- } *aReader;
-
- /* Create a data source */
- pData = testDatasourceNew(&pTest->defn);
-
- /* Open the writer connection */
- pDb = testOpen(zSystem, 1, pRc);
-
- /* Allocate aReader */
- aReader = (struct Reader *)testMalloc(sizeof(aReader[0]) * pTest->nReader);
- for(iReader=0; iReader<pTest->nReader; iReader++){
- aReader[iReader].pDb = testOpen(zSystem, 0, pRc);
- }
-
- for(iStep=0; iStep<pTest->nStep; iStep++){
- int iLast;
- int iBegin; /* Start read trans using aReader[iBegin] */
-
- /* Insert nWriteStep more records into the database */
- int iFirst = iStep*pTest->nWriteStep;
- testWriteDatasourceRange(pDb, pData, iFirst, pTest->nWriteStep, pRc);
-
- /* Check that the db is Ok according to the writer */
- iLast = (iStep+1) * pTest->nWriteStep - 1;
- testDbContents(pDb, pData, nDomain, 0, iLast, iLast, 1, pRc);
-
- /* Have reader (iStep % nReader) open a read transaction here. */
- iBegin = (iStep % pTest->nReader);
- if( iBegin<iStep ) tdb_commit(aReader[iBegin].pDb, 0);
- tdb_begin(aReader[iBegin].pDb, 1);
- aReader[iBegin].iLast = iLast;
-
- /* Check that the db is Ok for each open reader */
- for(iReader=0; iReader<pTest->nReader && aReader[iReader].iLast; iReader++){
- iLast = aReader[iReader].iLast;
- testDbContents(
- aReader[iReader].pDb, pData, nDomain, 0, iLast, iLast, 1, pRc
- );
- }
-
- /* Report progress */
- testCaseProgress(iStep, pTest->nStep, testCaseNDot(), &iDot);
- }
-
- /* Close all readers */
- for(iReader=0; iReader<pTest->nReader; iReader++){
- testClose(&aReader[iReader].pDb);
- }
- testFree(aReader);
-
- /* Close the writer-connection and free the datasource */
- testClose(&pDb);
- testDatasourceFree(pData);
-}
-
-
-void test_mc(
- const char *zSystem, /* Database system name */
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- int i;
- Mctest aTest[] = {
- { { TEST_DATASOURCE_RANDOM, 10,10, 100,100 }, 100, 10, 5 },
- };
-
- for(i=0; i<ArraySize(aTest); i++){
- if( testCaseBegin(pRc, zPattern, "mc1.%s.%d", zSystem, i) ){
- do_mc_test(zSystem, &aTest[i], pRc);
- testCaseFinish(*pRc);
- }
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest5.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest5.c
deleted file mode 100644
index f36184e79bf..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest5.c
+++ /dev/null
@@ -1,633 +0,0 @@
-
-/*
-** This file is broken into three semi-autonomous parts:
-**
-** 1. The database functions.
-** 2. The thread wrappers.
-** 3. The implementation of the mt1.* tests.
-*/
-
-/*************************************************************************
-** DATABASE CONTENTS:
-**
-** The database contains up to N key/value pairs, where N is some large
-** number (say 10,000,000). Keys are integer values between 0 and (N-1).
-** The value associated with each key is a pseudo-random blob of data.
-**
-** Key/value pair keys are encoded as the two bytes "k." followed by a
-** 10-digit decimal number. i.e. key 45 -> "k.0000000045".
-**
-** As well as the key/value pairs, the database also contains checksum
-** entries. The checksums form a hierarchy - for every F key/value
-** entries there is one level 1 checksum. And for each F level 1 checksums
-** there is one level 2 checksum. And so on.
-**
-** Checksum keys are encoded as the two byte "c." followed by the
-** checksum level, followed by a 10 digit decimal number containing
-** the value of the first key that contributes to the checksum value.
-** For example, assuming F==10, the level 1 checksum that spans keys
-** 10 to 19 is "c.1.0000000010".
-**
-** Clients may perform one of two operations on the database: a read
-** or a write.
-**
-** READ OPERATIONS:
-**
-** A read operation scans a range of F key/value pairs. It computes
-** the expected checksum and then compares the computed value to the
-** actual value stored in the level 1 checksum entry. It then scans
-** the group of F level 1 checksums, and compares the computed checksum
-** to the associated level 2 checksum value, and so on until the
-** highest level checksum value has been verified.
-**
-** If a checksum ever fails to match the expected value, the test
-** has failed.
-**
-** WRITE OPERATIONS:
-**
-** A write operation involves writing (possibly clobbering) a single
-** key/value pair. The associated level 1 checksum is then recalculated
-** updated. Then the level 2 checksum, and so on until the highest
-** level checksum has been modified.
-**
-** All updates occur inside a single transaction.
-**
-** INTERFACE:
-**
-** The interface used by test cases to read and write the db consists
-** of type DbParameters and the following functions:
-**
-** dbReadOperation()
-** dbWriteOperation()
-*/
-
-#include "lsmtest.h"
-
-typedef struct DbParameters DbParameters;
-struct DbParameters {
- int nFanout; /* Checksum fanout (F) */
- int nKey; /* Size of key space (N) */
-};
-
-#define DB_KEY_BYTES (2+5+10+1)
-
-/*
-** Argument aBuf[] must point to a buffer at least DB_KEY_BYTES in size.
-** This function populates the buffer with a nul-terminated key string
-** corresponding to key iKey.
-*/
-static void dbFormatKey(
- DbParameters *pParam,
- int iLevel,
- int iKey, /* Key value */
- char *aBuf /* Write key string here */
-){
- if( iLevel==0 ){
- snprintf(aBuf, DB_KEY_BYTES, "k.%.10d", iKey);
- }else{
- int f = 1;
- int i;
- for(i=0; i<iLevel; i++) f = f * pParam->nFanout;
- snprintf(aBuf, DB_KEY_BYTES, "c.%d.%.10d", iLevel, f*(iKey/f));
- }
-}
-
-/*
-** Argument aBuf[] must point to a buffer at least DB_KEY_BYTES in size.
-** This function populates the buffer with the string representation of
-** checksum value iVal.
-*/
-static void dbFormatCksumValue(u32 iVal, char *aBuf){
- snprintf(aBuf, DB_KEY_BYTES, "%.10u", iVal);
-}
-
-/*
-** Return the highest level of checksum in the database described
-** by *pParam.
-*/
-static int dbMaxLevel(DbParameters *pParam){
- int iMax;
- int n = 1;
- for(iMax=0; n<pParam->nKey; iMax++){
- n = n * pParam->nFanout;
- }
- return iMax;
-}
-
-static void dbCksum(
- void *pCtx, /* IN/OUT: Pointer to u32 containing cksum */
- void *pKey, int nKey, /* Database key. Unused. */
- void *pVal, int nVal /* Database value. Checksum this. */
-){
- u8 *aVal = (u8 *)pVal;
- u32 *pCksum = (u32 *)pCtx;
- u32 cksum = *pCksum;
- int i;
-
- unused_parameter(pKey);
- unused_parameter(nKey);
-
- for(i=0; i<nVal; i++){
- cksum += (cksum<<3) + (int)aVal[i];
- }
-
- *pCksum = cksum;
-}
-
-/*
-** Compute the value of the checksum stored on level iLevel that contains
-** data from key iKey by scanning the pParam->nFanout entries at level
-** iLevel-1.
-*/
-static u32 dbComputeCksum(
- DbParameters *pParam, /* Database parameters */
- TestDb *pDb, /* Database connection handle */
- int iLevel, /* Level of checksum to compute */
- int iKey, /* Compute checksum for this key */
- int *pRc /* IN/OUT: Error code */
-){
- u32 cksum = 0;
- if( *pRc==0 ){
- int nFirst;
- int nLast;
- int iFirst = 0;
- int iLast = 0;
- int i;
- int f = 1;
- char zFirst[DB_KEY_BYTES];
- char zLast[DB_KEY_BYTES];
-
- assert( iLevel>=1 );
- for(i=0; i<iLevel; i++) f = f * pParam->nFanout;
-
- iFirst = f*(iKey/f);
- iLast = iFirst + f - 1;
- dbFormatKey(pParam, iLevel-1, iFirst, zFirst);
- dbFormatKey(pParam, iLevel-1, iLast, zLast);
- nFirst = strlen(zFirst);
- nLast = strlen(zLast);
-
- *pRc = tdb_scan(pDb, (u32*)&cksum, 0, zFirst, nFirst, zLast, nLast,dbCksum);
- }
-
- return cksum;
-}
-
-static void dbReadOperation(
- DbParameters *pParam, /* Database parameters */
- TestDb *pDb, /* Database connection handle */
- void (*xDelay)(void *),
- void *pDelayCtx,
- int iKey, /* Key to read */
- int *pRc /* IN/OUT: Error code */
-){
- const int iMax = dbMaxLevel(pParam);
- int i;
-
- if( tdb_transaction_support(pDb) ) testBegin(pDb, 1, pRc);
- for(i=1; *pRc==0 && i<=iMax; i++){
- char zCksum[DB_KEY_BYTES];
- char zKey[DB_KEY_BYTES];
- u32 iCksum = 0;
-
- iCksum = dbComputeCksum(pParam, pDb, i, iKey, pRc);
- if( iCksum ){
- if( xDelay && i==1 ) xDelay(pDelayCtx);
- dbFormatCksumValue(iCksum, zCksum);
- dbFormatKey(pParam, i, iKey, zKey);
- testFetchStr(pDb, zKey, zCksum, pRc);
- }
- }
- if( tdb_transaction_support(pDb) ) testCommit(pDb, 0, pRc);
-}
-
-static int dbWriteOperation(
- DbParameters *pParam, /* Database parameters */
- TestDb *pDb, /* Database connection handle */
- int iKey, /* Key to write to */
- const char *zValue, /* Nul-terminated value to write */
- int *pRc /* IN/OUT: Error code */
-){
- const int iMax = dbMaxLevel(pParam);
- char zKey[DB_KEY_BYTES];
- int i;
- int rc;
-
- assert( iKey>=0 && iKey<pParam->nKey );
- dbFormatKey(pParam, 0, iKey, zKey);
-
- /* Open a write transaction. This may fail - SQLITE4_BUSY */
- if( *pRc==0 && tdb_transaction_support(pDb) ){
- rc = tdb_begin(pDb, 2);
- if( rc==5 ) return 0;
- *pRc = rc;
- }
-
- testWriteStr(pDb, zKey, zValue, pRc);
- for(i=1; i<=iMax; i++){
- char zCksum[DB_KEY_BYTES];
- u32 iCksum = 0;
-
- iCksum = dbComputeCksum(pParam, pDb, i, iKey, pRc);
- dbFormatCksumValue(iCksum, zCksum);
- dbFormatKey(pParam, i, iKey, zKey);
- testWriteStr(pDb, zKey, zCksum, pRc);
- }
- if( tdb_transaction_support(pDb) ) testCommit(pDb, 0, pRc);
- return 1;
-}
-
-/*************************************************************************
-** The following block contains testXXX() functions that implement a
-** wrapper around the systems native multi-thread support. There are no
-** synchronization primitives - just functions to launch and join
-** threads. Wrapper functions are:
-**
-** testThreadSupport()
-**
-** testThreadInit()
-** testThreadShutdown()
-** testThreadLaunch()
-** testThreadWait()
-**
-** testThreadSetHalt()
-** testThreadGetHalt()
-** testThreadSetResult()
-** testThreadGetResult()
-**
-** testThreadEnterMutex()
-** testThreadLeaveMutex()
-*/
-typedef struct ThreadSet ThreadSet;
-#ifdef LSM_MUTEX_PTHREADS
-
-#include <pthread.h>
-#include <unistd.h>
-
-typedef struct Thread Thread;
-struct Thread {
- int rc;
- char *zMsg;
- pthread_t id;
- void (*xMain)(ThreadSet *, int, void *);
- void *pCtx;
- ThreadSet *pThreadSet;
-};
-
-struct ThreadSet {
- int bHalt; /* Halt flag */
- int nThread; /* Number of threads */
- Thread *aThread; /* Array of Thread structures */
- pthread_mutex_t mutex; /* Mutex used for cheating */
-};
-
-/*
-** Return true if this build supports threads, or false otherwise. If
-** this function returns false, no other testThreadXXX() functions should
-** be called.
-*/
-static int testThreadSupport(){ return 1; }
-
-/*
-** Allocate and return a thread-set handle with enough space allocated
-** to handle up to nMax threads. Each call to this function should be
-** matched by a call to testThreadShutdown() to delete the object.
-*/
-static ThreadSet *testThreadInit(int nMax){
- int nByte; /* Total space to allocate */
- ThreadSet *p; /* Return value */
-
- nByte = sizeof(ThreadSet) + sizeof(struct Thread) * nMax;
- p = (ThreadSet *)testMalloc(nByte);
- p->nThread = nMax;
- p->aThread = (Thread *)&p[1];
- pthread_mutex_init(&p->mutex, 0);
-
- return p;
-}
-
-/*
-** Delete a thread-set object and release all resources held by it.
-*/
-static void testThreadShutdown(ThreadSet *p){
- int i;
- for(i=0; i<p->nThread; i++){
- testFree(p->aThread[i].zMsg);
- }
- pthread_mutex_destroy(&p->mutex);
- testFree(p);
-}
-
-static void *ttMain(void *pArg){
- Thread *pThread = (Thread *)pArg;
- int iThread;
- iThread = (pThread - pThread->pThreadSet->aThread);
- pThread->xMain(pThread->pThreadSet, iThread, pThread->pCtx);
- return 0;
-}
-
-/*
-** Launch a new thread.
-*/
-static int testThreadLaunch(
- ThreadSet *p,
- int iThread,
- void (*xMain)(ThreadSet *, int, void *),
- void *pCtx
-){
- int rc;
- Thread *pThread;
-
- assert( iThread>=0 && iThread<p->nThread );
-
- pThread = &p->aThread[iThread];
- assert( pThread->pThreadSet==0 );
- pThread->xMain = xMain;
- pThread->pCtx = pCtx;
- pThread->pThreadSet = p;
- rc = pthread_create(&pThread->id, 0, ttMain, (void *)pThread);
-
- return rc;
-}
-
-/*
-** Set the thread-set "halt" flag.
-*/
-static void testThreadSetHalt(ThreadSet *pThreadSet){
- pThreadSet->bHalt = 1;
-}
-
-/*
-** Return the current value of the thread-set "halt" flag.
-*/
-static int testThreadGetHalt(ThreadSet *pThreadSet){
- return pThreadSet->bHalt;
-}
-
-static void testThreadSleep(ThreadSet *pThreadSet, int nMs){
- int nRem = nMs;
- while( nRem>0 && testThreadGetHalt(pThreadSet)==0 ){
- usleep(50000);
- nRem -= 50;
- }
-}
-
-/*
-** Wait for all threads launched to finish before returning. If nMs
-** is greater than zero, set the "halt" flag to tell all threads
-** to halt after waiting nMs milliseconds.
-*/
-static void testThreadWait(ThreadSet *pThreadSet, int nMs){
- int i;
-
- testThreadSleep(pThreadSet, nMs);
- testThreadSetHalt(pThreadSet);
- for(i=0; i<pThreadSet->nThread; i++){
- Thread *pThread = &pThreadSet->aThread[i];
- if( pThread->xMain ){
- pthread_join(pThread->id, 0);
- }
- }
-}
-
-/*
-** Set the result for thread iThread.
-*/
-static void testThreadSetResult(
- ThreadSet *pThreadSet, /* Thread-set handle */
- int iThread, /* Set result for this thread */
- int rc, /* Result error code */
- char *zFmt, /* Result string format */
- ... /* Result string formatting args... */
-){
- va_list ap;
-
- testFree(pThreadSet->aThread[iThread].zMsg);
- pThreadSet->aThread[iThread].rc = rc;
- pThreadSet->aThread[iThread].zMsg = 0;
- if( zFmt ){
- va_start(ap, zFmt);
- pThreadSet->aThread[iThread].zMsg = testMallocVPrintf(zFmt, ap);
- va_end(ap);
- }
-}
-
-/*
-** Retrieve the result for thread iThread.
-*/
-static int testThreadGetResult(
- ThreadSet *pThreadSet, /* Thread-set handle */
- int iThread, /* Get result for this thread */
- const char **pzRes /* OUT: Pointer to result string */
-){
- if( pzRes ) *pzRes = pThreadSet->aThread[iThread].zMsg;
- return pThreadSet->aThread[iThread].rc;
-}
-
-/*
-** Enter and leave the test case mutex.
-*/
-#if 0
-static void testThreadEnterMutex(ThreadSet *p){
- pthread_mutex_lock(&p->mutex);
-}
-static void testThreadLeaveMutex(ThreadSet *p){
- pthread_mutex_unlock(&p->mutex);
-}
-#endif
-#endif
-
-#if !defined(LSM_MUTEX_PTHREADS)
-static int testThreadSupport(){ return 0; }
-
-#define testThreadInit(a) 0
-#define testThreadShutdown(a)
-#define testThreadLaunch(a,b,c,d) 0
-#define testThreadWait(a,b)
-#define testThreadSetHalt(a)
-#define testThreadGetHalt(a) 0
-#define testThreadGetResult(a,b,c) 0
-#define testThreadSleep(a,b) 0
-
-static void testThreadSetResult(ThreadSet *a, int b, int c, char *d, ...){
- unused_parameter(a);
- unused_parameter(b);
- unused_parameter(c);
- unused_parameter(d);
-}
-#endif
-/* End of threads wrapper.
-*************************************************************************/
-
-/*************************************************************************
-** Below this point is the third part of this file - the implementation
-** of the mt1.* tests.
-*/
-typedef struct Mt1Test Mt1Test;
-struct Mt1Test {
- DbParameters param; /* Description of database to read/write */
- int nReadwrite; /* Number of read/write threads */
- int nFastReader; /* Number of fast reader threads */
- int nSlowReader; /* Number of slow reader threads */
- int nMs; /* How long to run for */
- const char *zSystem; /* Database system to test */
-};
-
-typedef struct Mt1DelayCtx Mt1DelayCtx;
-struct Mt1DelayCtx {
- ThreadSet *pSet; /* Threadset to sleep within */
- int nMs; /* Sleep in ms */
-};
-
-static void xMt1Delay(void *pCtx){
- Mt1DelayCtx *p = (Mt1DelayCtx *)pCtx;
- testThreadSleep(p->pSet, p->nMs);
-}
-
-#define MT1_THREAD_RDWR 0
-#define MT1_THREAD_SLOW 1
-#define MT1_THREAD_FAST 2
-
-static void xMt1Work(lsm_db *pDb, void *pCtx){
-#if 0
- char *z = 0;
- lsm_info(pDb, LSM_INFO_DB_STRUCTURE, &z);
- printf("%s\n", z);
- fflush(stdout);
-#endif
-}
-
-/*
-** This is the main() proc for all threads in test case "mt1".
-*/
-static void mt1Main(ThreadSet *pThreadSet, int iThread, void *pCtx){
- Mt1Test *p = (Mt1Test *)pCtx; /* Test parameters */
- Mt1DelayCtx delay;
- int nRead = 0; /* Number of calls to dbReadOperation() */
- int nWrite = 0; /* Number of completed database writes */
- int rc = 0; /* Error code */
- int iPrng; /* Prng argument variable */
- TestDb *pDb; /* Database handle */
- int eType;
-
- delay.pSet = pThreadSet;
- delay.nMs = 0;
- if( iThread<p->nReadwrite ){
- eType = MT1_THREAD_RDWR;
- }else if( iThread<(p->nReadwrite+p->nFastReader) ){
- eType = MT1_THREAD_FAST;
- }else{
- eType = MT1_THREAD_SLOW;
- delay.nMs = (p->nMs / 20);
- }
-
- /* Open a new database connection. Initialize the pseudo-random number
- ** argument based on the thread number. */
- iPrng = testPrngValue(iThread);
- pDb = testOpen(p->zSystem, 0, &rc);
-
- if( rc==0 ){
- tdb_lsm_config_work_hook(pDb, xMt1Work, 0);
- }
-
- /* Loop until either an error occurs or some other thread sets the
- ** halt flag. */
- while( rc==0 && testThreadGetHalt(pThreadSet)==0 ){
- int iKey;
-
- /* Perform a read operation on an arbitrarily selected key. */
- iKey = (testPrngValue(iPrng++) % p->param.nKey);
- dbReadOperation(&p->param, pDb, xMt1Delay, (void *)&delay, iKey, &rc);
- if( rc ) continue;
- nRead++;
-
- /* Attempt to write an arbitrary key value pair (and update the associated
- ** checksum entries). dbWriteOperation() returns 1 if the write is
- ** successful, or 0 if it failed with an LSM_BUSY error. */
- if( eType==MT1_THREAD_RDWR ){
- char aValue[50];
- char aRnd[25];
-
- iKey = (testPrngValue(iPrng++) % p->param.nKey);
- testPrngString(iPrng, aRnd, sizeof(aRnd));
- iPrng += sizeof(aRnd);
- snprintf(aValue, sizeof(aValue), "%d.%s", iThread, aRnd);
- nWrite += dbWriteOperation(&p->param, pDb, iKey, aValue, &rc);
- }
- }
- testClose(&pDb);
-
- /* If an error has occured, set the thread error code and the threadset
- ** halt flag to tell the other test threads to halt. Otherwise, set the
- ** thread error code to 0 and post a message with the number of read
- ** and write operations completed. */
- if( rc ){
- testThreadSetResult(pThreadSet, iThread, rc, 0);
- testThreadSetHalt(pThreadSet);
- }else{
- testThreadSetResult(pThreadSet, iThread, 0, "r/w: %d/%d", nRead, nWrite);
- }
-}
-
-static void do_test_mt1(
- const char *zSystem, /* Database system name */
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- Mt1Test aTest[] = {
- /* param, nReadwrite, nFastReader, nSlowReader, nMs, zSystem */
- { {10, 1000}, 4, 0, 0, 10000, 0 },
- { {10, 1000}, 4, 4, 2, 100000, 0 },
- { {10, 100000}, 4, 0, 0, 10000, 0 },
- { {10, 100000}, 4, 4, 2, 100000, 0 },
- };
- int i;
-
- for(i=0; *pRc==0 && i<ArraySize(aTest); i++){
- Mt1Test *p = &aTest[i];
- int bRun = testCaseBegin(pRc, zPattern,
- "mt1.%s.db=%d,%d.ms=%d.rdwr=%d.fast=%d.slow=%d",
- zSystem, p->param.nFanout, p->param.nKey,
- p->nMs, p->nReadwrite, p->nFastReader, p->nSlowReader
- );
- if( bRun ){
- TestDb *pDb;
- ThreadSet *pSet;
- int iThread;
- int nThread;
-
- p->zSystem = zSystem;
- pDb = testOpen(zSystem, 1, pRc);
-
- nThread = p->nReadwrite + p->nFastReader + p->nSlowReader;
- pSet = testThreadInit(nThread);
- for(iThread=0; *pRc==0 && iThread<nThread; iThread++){
- testThreadLaunch(pSet, iThread, mt1Main, (void *)p);
- }
-
- testThreadWait(pSet, p->nMs);
- for(iThread=0; *pRc==0 && iThread<nThread; iThread++){
- *pRc = testThreadGetResult(pSet, iThread, 0);
- }
- testCaseFinish(*pRc);
-
- for(iThread=0; *pRc==0 && iThread<nThread; iThread++){
- const char *zMsg = 0;
- *pRc = testThreadGetResult(pSet, iThread, &zMsg);
- printf(" Info: thread %d (%d): %s\n", iThread, *pRc, zMsg);
- }
-
- testThreadShutdown(pSet);
- testClose(&pDb);
- }
- }
-}
-
-void test_mt(
- const char *zSystem, /* Database system name */
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- if( testThreadSupport()==0 ) return;
- do_test_mt1(zSystem, zPattern, pRc);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest6.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest6.c
deleted file mode 100644
index a61b738b8fa..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest6.c
+++ /dev/null
@@ -1,661 +0,0 @@
-
-#include "lsmtest.h"
-
-typedef struct OomTest OomTest;
-struct OomTest {
- lsm_env *pEnv;
- int iNext; /* Next value to pass to testMallocOom() */
- int nFail; /* Number of OOM events injected */
- int bEnable;
- int rc; /* Test case error code */
-};
-
-static void testOomStart(OomTest *p){
- memset(p, 0, sizeof(OomTest));
- p->iNext = 1;
- p->bEnable = 1;
- p->nFail = 1;
- p->pEnv = tdb_lsm_env();
-}
-
-static void xOomHook(OomTest *p){
- p->nFail++;
-}
-
-static int testOomContinue(OomTest *p){
- if( p->rc!=0 || (p->iNext>1 && p->nFail==0) ){
- return 0;
- }
- p->nFail = 0;
- testMallocOom(p->pEnv, p->iNext, 0, (void (*)(void*))xOomHook, (void *)p);
- return 1;
-}
-
-static void testOomEnable(OomTest *p, int bEnable){
- p->bEnable = bEnable;
- testMallocOomEnable(p->pEnv, bEnable);
-}
-
-static void testOomNext(OomTest *p){
- p->iNext++;
-}
-
-static int testOomHit(OomTest *p){
- return (p->nFail>0);
-}
-
-static int testOomFinish(OomTest *p){
- return p->rc;
-}
-
-static void testOomAssert(OomTest *p, int bVal){
- if( bVal==0 ){
- test_failed();
- p->rc = 1;
- }
-}
-
-/*
-** Test that the error code matches the state of the OomTest object passed
-** as the first argument. Specifically, check that rc is LSM_NOMEM if an
-** OOM error has already been injected, or LSM_OK if not.
-*/
-static void testOomAssertRc(OomTest *p, int rc){
- testOomAssert(p, rc==LSM_OK || rc==LSM_NOMEM);
- testOomAssert(p, testOomHit(p)==(rc==LSM_NOMEM) || p->bEnable==0 );
-}
-
-static void testOomOpen(
- OomTest *pOom,
- const char *zName,
- lsm_db **ppDb,
- int *pRc
-){
- if( *pRc==LSM_OK ){
- int rc;
- rc = lsm_new(tdb_lsm_env(), ppDb);
- if( rc==LSM_OK ) rc = lsm_open(*ppDb, zName);
- testOomAssertRc(pOom, rc);
- *pRc = rc;
- }
-}
-
-static void testOomFetch(
- OomTest *pOom,
- lsm_db *pDb,
- void *pKey, int nKey,
- void *pVal, int nVal,
- int *pRc
-){
- testOomAssertRc(pOom, *pRc);
- if( *pRc==LSM_OK ){
- lsm_cursor *pCsr;
- int rc;
-
- rc = lsm_csr_open(pDb, &pCsr);
- if( rc==LSM_OK ) rc = lsm_csr_seek(pCsr, pKey, nKey, 0);
- testOomAssertRc(pOom, rc);
-
- if( rc==LSM_OK ){
- const void *p; int n;
- testOomAssert(pOom, lsm_csr_valid(pCsr));
-
- rc = lsm_csr_key(pCsr, &p, &n);
- testOomAssertRc(pOom, rc);
- testOomAssert(pOom, rc!=LSM_OK || (n==nKey && memcmp(pKey, p, nKey)==0) );
- }
-
- if( rc==LSM_OK ){
- const void *p; int n;
- testOomAssert(pOom, lsm_csr_valid(pCsr));
-
- rc = lsm_csr_value(pCsr, &p, &n);
- testOomAssertRc(pOom, rc);
- testOomAssert(pOom, rc!=LSM_OK || (n==nVal && memcmp(pVal, p, nVal)==0) );
- }
-
- lsm_csr_close(pCsr);
- *pRc = rc;
- }
-}
-
-static void testOomWrite(
- OomTest *pOom,
- lsm_db *pDb,
- void *pKey, int nKey,
- void *pVal, int nVal,
- int *pRc
-){
- testOomAssertRc(pOom, *pRc);
- if( *pRc==LSM_OK ){
- int rc;
-
- rc = lsm_insert(pDb, pKey, nKey, pVal, nVal);
- testOomAssertRc(pOom, rc);
-
- *pRc = rc;
- }
-}
-
-
-static void testOomFetchStr(
- OomTest *pOom,
- lsm_db *pDb,
- const char *zKey,
- const char *zVal,
- int *pRc
-){
- int nKey = strlen(zKey);
- int nVal = strlen(zVal);
- testOomFetch(pOom, pDb, (void *)zKey, nKey, (void *)zVal, nVal, pRc);
-}
-
-static void testOomFetchData(
- OomTest *pOom,
- lsm_db *pDb,
- Datasource *pData,
- int iKey,
- int *pRc
-){
- void *pKey; int nKey;
- void *pVal; int nVal;
- testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal);
- testOomFetch(pOom, pDb, pKey, nKey, pVal, nVal, pRc);
-}
-
-static void testOomWriteStr(
- OomTest *pOom,
- lsm_db *pDb,
- const char *zKey,
- const char *zVal,
- int *pRc
-){
- int nKey = strlen(zKey);
- int nVal = strlen(zVal);
- testOomWrite(pOom, pDb, (void *)zKey, nKey, (void *)zVal, nVal, pRc);
-}
-
-static void testOomWriteData(
- OomTest *pOom,
- lsm_db *pDb,
- Datasource *pData,
- int iKey,
- int *pRc
-){
- void *pKey; int nKey;
- void *pVal; int nVal;
- testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal);
- testOomWrite(pOom, pDb, pKey, nKey, pVal, nVal, pRc);
-}
-
-static void testOomScan(
- OomTest *pOom,
- lsm_db *pDb,
- int bReverse,
- const void *pKey, int nKey,
- int nScan,
- int *pRc
-){
- if( *pRc==0 ){
- int rc;
- int iScan = 0;
- lsm_cursor *pCsr;
- int (*xAdvance)(lsm_cursor *) = 0;
-
-
- rc = lsm_csr_open(pDb, &pCsr);
- testOomAssertRc(pOom, rc);
-
- if( rc==LSM_OK ){
- if( bReverse ){
- rc = lsm_csr_seek(pCsr, pKey, nKey, LSM_SEEK_LE);
- xAdvance = lsm_csr_prev;
- }else{
- rc = lsm_csr_seek(pCsr, pKey, nKey, LSM_SEEK_GE);
- xAdvance = lsm_csr_next;
- }
- }
- testOomAssertRc(pOom, rc);
-
- while( rc==LSM_OK && lsm_csr_valid(pCsr) && iScan<nScan ){
- const void *p; int n;
-
- rc = lsm_csr_key(pCsr, &p, &n);
- testOomAssertRc(pOom, rc);
- if( rc==LSM_OK ){
- rc = lsm_csr_value(pCsr, &p, &n);
- testOomAssertRc(pOom, rc);
- }
- if( rc==LSM_OK ){
- rc = xAdvance(pCsr);
- testOomAssertRc(pOom, rc);
- }
- iScan++;
- }
-
- lsm_csr_close(pCsr);
- *pRc = rc;
- }
-}
-
-#define LSMTEST6_TESTDB "testdb.lsm"
-
-void testDeleteLsmdb(const char *zFile){
- char *zLog = testMallocPrintf("%s-log", zFile);
- char *zShm = testMallocPrintf("%s-shm", zFile);
- unlink(zFile);
- unlink(zLog);
- unlink(zShm);
- testFree(zLog);
- testFree(zShm);
-}
-
-static void copy_file(const char *zFrom, const char *zTo, int isDatabase){
-
- if( access(zFrom, F_OK) ){
- unlink(zTo);
- }else{
- int fd1;
- int fd2;
- off_t sz;
- off_t i;
- struct stat buf;
- u8 *aBuf;
-
- fd1 = open(zFrom, O_RDONLY | _O_BINARY, 0644);
- fd2 = open(zTo, O_RDWR | O_CREAT | _O_BINARY, 0644);
-
- fstat(fd1, &buf);
- sz = buf.st_size;
- ftruncate(fd2, sz);
-
- aBuf = testMalloc(4096);
- for(i=0; i<sz; i+=4096){
- int bLockPage = isDatabase && i == 0;
- int nByte = MIN((bLockPage ? 4066 : 4096), sz - i);
- memset(aBuf, 0, 4096);
- read(fd1, aBuf, nByte);
- write(fd2, aBuf, nByte);
- if( bLockPage ){
- lseek(fd1, 4096, SEEK_SET);
- lseek(fd2, 4096, SEEK_SET);
- }
- }
- testFree(aBuf);
-
- close(fd1);
- close(fd2);
- }
-}
-
-void testCopyLsmdb(const char *zFrom, const char *zTo){
- char *zLog1 = testMallocPrintf("%s-log", zFrom);
- char *zLog2 = testMallocPrintf("%s-log", zTo);
- char *zShm1 = testMallocPrintf("%s-shm", zFrom);
- char *zShm2 = testMallocPrintf("%s-shm", zTo);
-
- unlink(zShm2);
- unlink(zLog2);
- unlink(zTo);
- copy_file(zFrom, zTo, 1);
- copy_file(zLog1, zLog2, 0);
- copy_file(zShm1, zShm2, 0);
-
- testFree(zLog1); testFree(zLog2); testFree(zShm1); testFree(zShm2);
-}
-
-/*
-** File zFile is the path to a database. This function makes backups
-** of the database file and its log as follows:
-**
-** cp $(zFile) $(zFile)-save
-** cp $(zFile)-$(zAux) $(zFile)-save-$(zAux)
-**
-** Function testRestoreDb() can be used to copy the files back in the
-** other direction.
-*/
-void testSaveDb(const char *zFile, const char *zAux){
- char *zLog = testMallocPrintf("%s-%s", zFile, zAux);
- char *zFileSave = testMallocPrintf("%s-save", zFile);
- char *zLogSave = testMallocPrintf("%s-%s-save", zFile, zAux);
-
- unlink(zFileSave);
- unlink(zLogSave);
- copy_file(zFile, zFileSave, 1);
- copy_file(zLog, zLogSave, 0);
-
- testFree(zLog); testFree(zFileSave); testFree(zLogSave);
-}
-
-/*
-** File zFile is the path to a database. This function restores
-** a backup of the database made by a previous call to testSaveDb().
-** Specifically, it does the equivalent of:
-**
-** cp $(zFile)-save $(zFile)
-** cp $(zFile)-save-$(zAux) $(zFile)-$(zAux)
-*/
-void testRestoreDb(const char *zFile, const char *zAux){
- char *zLog = testMallocPrintf("%s-%s", zFile, zAux);
- char *zFileSave = testMallocPrintf("%s-save", zFile);
- char *zLogSave = testMallocPrintf("%s-%s-save", zFile, zAux);
-
- copy_file(zFileSave, zFile, 1);
- copy_file(zLogSave, zLog, 0);
-
- testFree(zLog); testFree(zFileSave); testFree(zLogSave);
-}
-
-
-static int lsmWriteStr(lsm_db *pDb, const char *zKey, const char *zVal){
- int nKey = strlen(zKey);
- int nVal = strlen(zVal);
- return lsm_insert(pDb, (void *)zKey, nKey, (void *)zVal, nVal);
-}
-
-static void setup_delete_db(void){
- testDeleteLsmdb(LSMTEST6_TESTDB);
-}
-
-/*
-** Create a small database. With the following content:
-**
-** "one" -> "one"
-** "two" -> "four"
-** "three" -> "nine"
-** "four" -> "sixteen"
-** "five" -> "twentyfive"
-** "six" -> "thirtysix"
-** "seven" -> "fourtynine"
-** "eight" -> "sixtyfour"
-*/
-static void setup_populate_db(void){
- const char *azStr[] = {
- "one", "one",
- "two", "four",
- "three", "nine",
- "four", "sixteen",
- "five", "twentyfive",
- "six", "thirtysix",
- "seven", "fourtynine",
- "eight", "sixtyfour",
- };
- int rc;
- int ii;
- lsm_db *pDb;
-
- testDeleteLsmdb(LSMTEST6_TESTDB);
-
- rc = lsm_new(tdb_lsm_env(), &pDb);
- if( rc==LSM_OK ) rc = lsm_open(pDb, LSMTEST6_TESTDB);
-
- for(ii=0; rc==LSM_OK && ii<ArraySize(azStr); ii+=2){
- rc = lsmWriteStr(pDb, azStr[ii], azStr[ii+1]);
- }
- lsm_close(pDb);
-
- testSaveDb(LSMTEST6_TESTDB, "log");
- assert( rc==LSM_OK );
-}
-
-static Datasource *getDatasource(void){
- const DatasourceDefn defn = { TEST_DATASOURCE_RANDOM, 10, 15, 200, 250 };
- return testDatasourceNew(&defn);
-}
-
-/*
-** Set up a database file with the following properties:
-**
-** * Page size is 1024 bytes.
-** * Block size is 64 KB.
-** * Contains 5000 key-value pairs starting at 0 from the
-** datasource returned getDatasource().
-*/
-static void setup_populate_db2(void){
- Datasource *pData;
- int ii;
- int rc;
- int nBlocksize = 64*1024;
- int nPagesize = 1024;
- int nWritebuffer = 4*1024;
- lsm_db *pDb;
-
- testDeleteLsmdb(LSMTEST6_TESTDB);
- rc = lsm_new(tdb_lsm_env(), &pDb);
- if( rc==LSM_OK ) rc = lsm_open(pDb, LSMTEST6_TESTDB);
-
- lsm_config(pDb, LSM_CONFIG_BLOCK_SIZE, &nBlocksize);
- lsm_config(pDb, LSM_CONFIG_PAGE_SIZE, &nPagesize);
- lsm_config(pDb, LSM_CONFIG_AUTOFLUSH, &nWritebuffer);
-
- pData = getDatasource();
- for(ii=0; rc==LSM_OK && ii<5000; ii++){
- void *pKey; int nKey;
- void *pVal; int nVal;
- testDatasourceEntry(pData, ii, &pKey, &nKey, &pVal, &nVal);
- lsm_insert(pDb, pKey, nKey, pVal, nVal);
- }
- testDatasourceFree(pData);
- lsm_close(pDb);
-
- testSaveDb(LSMTEST6_TESTDB, "log");
- assert( rc==LSM_OK );
-}
-
-/*
-** Test the results of OOM conditions in lsm_new().
-*/
-static void simple_oom_1(OomTest *pOom){
- int rc;
- lsm_db *pDb;
-
- rc = lsm_new(tdb_lsm_env(), &pDb);
- testOomAssertRc(pOom, rc);
-
- lsm_close(pDb);
-}
-
-/*
-** Test the results of OOM conditions in lsm_open().
-*/
-static void simple_oom_2(OomTest *pOom){
- int rc;
- lsm_db *pDb;
-
- rc = lsm_new(tdb_lsm_env(), &pDb);
- if( rc==LSM_OK ){
- rc = lsm_open(pDb, "testdb.lsm");
- }
- testOomAssertRc(pOom, rc);
-
- lsm_close(pDb);
-}
-
-/*
-** Test the results of OOM conditions in simple fetch operations.
-*/
-static void simple_oom_3(OomTest *pOom){
- int rc = LSM_OK;
- lsm_db *pDb;
-
- testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
-
- testOomFetchStr(pOom, pDb, "four", "sixteen", &rc);
- testOomFetchStr(pOom, pDb, "seven", "fourtynine", &rc);
- testOomFetchStr(pOom, pDb, "one", "one", &rc);
- testOomFetchStr(pOom, pDb, "eight", "sixtyfour", &rc);
-
- lsm_close(pDb);
-}
-
-/*
-** Test the results of OOM conditions in simple write operations.
-*/
-static void simple_oom_4(OomTest *pOom){
- int rc = LSM_OK;
- lsm_db *pDb;
-
- testDeleteLsmdb(LSMTEST6_TESTDB);
- testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
-
- testOomWriteStr(pOom, pDb, "123", "onetwothree", &rc);
- testOomWriteStr(pOom, pDb, "456", "fourfivesix", &rc);
- testOomWriteStr(pOom, pDb, "789", "seveneightnine", &rc);
- testOomWriteStr(pOom, pDb, "123", "teneleventwelve", &rc);
- testOomWriteStr(pOom, pDb, "456", "fourteenfifteensixteen", &rc);
-
- lsm_close(pDb);
-}
-
-static void simple_oom_5(OomTest *pOom){
- Datasource *pData = getDatasource();
- int rc = LSM_OK;
- lsm_db *pDb;
-
- testRestoreDb(LSMTEST6_TESTDB, "log");
- testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
-
- testOomFetchData(pOom, pDb, pData, 3333, &rc);
- testOomFetchData(pOom, pDb, pData, 0, &rc);
- testOomFetchData(pOom, pDb, pData, 4999, &rc);
-
- lsm_close(pDb);
- testDatasourceFree(pData);
-}
-
-static void simple_oom_6(OomTest *pOom){
- Datasource *pData = getDatasource();
- int rc = LSM_OK;
- lsm_db *pDb;
-
- testRestoreDb(LSMTEST6_TESTDB, "log");
- testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
-
- testOomWriteData(pOom, pDb, pData, 5000, &rc);
- testOomWriteData(pOom, pDb, pData, 5001, &rc);
- testOomWriteData(pOom, pDb, pData, 5002, &rc);
- testOomFetchData(pOom, pDb, pData, 5001, &rc);
- testOomFetchData(pOom, pDb, pData, 1234, &rc);
-
- lsm_close(pDb);
- testDatasourceFree(pData);
-}
-
-static void simple_oom_7(OomTest *pOom){
- Datasource *pData = getDatasource();
- int rc = LSM_OK;
- lsm_db *pDb;
-
- testRestoreDb(LSMTEST6_TESTDB, "log");
- testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
- testOomScan(pOom, pDb, 0, "abc", 3, 20, &rc);
- lsm_close(pDb);
- testDatasourceFree(pData);
-}
-
-static void simple_oom_8(OomTest *pOom){
- Datasource *pData = getDatasource();
- int rc = LSM_OK;
- lsm_db *pDb;
- testRestoreDb(LSMTEST6_TESTDB, "log");
- testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
- testOomScan(pOom, pDb, 1, "xyz", 3, 20, &rc);
- lsm_close(pDb);
- testDatasourceFree(pData);
-}
-
-/*
-** This test case has two clients connected to a database. The first client
-** hits an OOM while writing to the database. Check that the second
-** connection is still able to query the db following the OOM.
-*/
-static void simple_oom2_1(OomTest *pOom){
- const int nRecord = 100; /* Number of records initially in db */
- const int nIns = 10; /* Number of records inserted with OOM */
-
- Datasource *pData = getDatasource();
- int rc = LSM_OK;
- lsm_db *pDb1;
- lsm_db *pDb2;
- int i;
-
- testDeleteLsmdb(LSMTEST6_TESTDB);
-
- /* Open the two connections. Initialize the in-memory tree so that it
- ** contains 100 records. Do all this with OOM injection disabled. */
- testOomEnable(pOom, 0);
- testOomOpen(pOom, LSMTEST6_TESTDB, &pDb1, &rc);
- testOomOpen(pOom, LSMTEST6_TESTDB, &pDb2, &rc);
- for(i=0; i<nRecord; i++){
- testOomWriteData(pOom, pDb1, pData, i, &rc);
- }
- testOomEnable(pOom, 1);
- assert( rc==0 );
-
- /* Insert 10 more records using pDb1. Stop when an OOM is encountered. */
- for(i=nRecord; i<nRecord+nIns; i++){
- testOomWriteData(pOom, pDb1, pData, i, &rc);
- if( rc ) break;
- }
- testOomAssertRc(pOom, rc);
-
- /* Switch off OOM injection. Write a few rows using pDb2. Then check
- ** that the database may be successfully queried. */
- testOomEnable(pOom, 0);
- rc = 0;
- for(; i<nRecord+nIns && rc==0; i++){
- testOomWriteData(pOom, pDb2, pData, i, &rc);
- }
- for(i=0; i<nRecord+nIns; i++) testOomFetchData(pOom, pDb2, pData, i, &rc);
- testOomEnable(pOom, 1);
-
- lsm_close(pDb1);
- lsm_close(pDb2);
- testDatasourceFree(pData);
-}
-
-
-static void do_test_oom1(const char *zPattern, int *pRc){
- struct SimpleOom {
- const char *zName;
- void (*xSetup)(void);
- void (*xFunc)(OomTest *);
- } aSimple[] = {
- { "oom1.lsm.1", setup_delete_db, simple_oom_1 },
- { "oom1.lsm.2", setup_delete_db, simple_oom_2 },
- { "oom1.lsm.3", setup_populate_db, simple_oom_3 },
- { "oom1.lsm.4", setup_delete_db, simple_oom_4 },
- { "oom1.lsm.5", setup_populate_db2, simple_oom_5 },
- { "oom1.lsm.6", setup_populate_db2, simple_oom_6 },
- { "oom1.lsm.7", setup_populate_db2, simple_oom_7 },
- { "oom1.lsm.8", setup_populate_db2, simple_oom_8 },
-
- { "oom2.lsm.1", setup_delete_db, simple_oom2_1 },
- };
- int i;
-
- for(i=0; i<ArraySize(aSimple); i++){
- if( *pRc==0 && testCaseBegin(pRc, zPattern, "%s", aSimple[i].zName) ){
- OomTest t;
-
- if( aSimple[i].xSetup ){
- aSimple[i].xSetup();
- }
-
- for(testOomStart(&t); testOomContinue(&t); testOomNext(&t)){
- aSimple[i].xFunc(&t);
- }
-
- printf("(%d injections).", t.iNext-2);
- testCaseFinish( (*pRc = testOomFinish(&t)) );
- testMallocOom(tdb_lsm_env(), 0, 0, 0, 0);
- }
- }
-}
-
-void test_oom(
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- do_test_oom1(zPattern, pRc);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest7.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest7.c
deleted file mode 100644
index 2d26b53a746..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest7.c
+++ /dev/null
@@ -1,206 +0,0 @@
-
-
-#include "lsmtest.h"
-
-
-/*
-** Test that the rules for when lsm_csr_next() and lsm_csr_prev() are
-** enforced. Specifically:
-**
-** * Both functions always return LSM_MISUSE if the cursor is at EOF
-** when they are called.
-**
-** * lsm_csr_next() may only be used after lsm_csr_seek(LSM_SEEK_GE) or
-** lsm_csr_first().
-**
-** * lsm_csr_prev() may only be used after lsm_csr_seek(LSM_SEEK_LE) or
-** lsm_csr_last().
-*/
-static void do_test_api1_lsm(lsm_db *pDb, int *pRc){
- int ret;
- lsm_cursor *pCsr;
- lsm_cursor *pCsr2;
- int nKey;
- const void *pKey;
-
- ret = lsm_csr_open(pDb, &pCsr);
- testCompareInt(LSM_OK, ret, pRc);
-
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
-
- ret = lsm_csr_seek(pCsr, "jjj", 3, LSM_SEEK_GE);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
-
- ret = lsm_csr_seek(pCsr, "jjj", 3, LSM_SEEK_LE);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
-
- ret = lsm_csr_seek(pCsr, "jjj", 3, LSM_SEEK_LEFAST);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
-
- ret = lsm_csr_key(pCsr, &pKey, &nKey);
- testCompareInt(LSM_OK, ret, pRc);
-
- ret = lsm_csr_open(pDb, &pCsr2);
- testCompareInt(LSM_OK, ret, pRc);
-
- ret = lsm_csr_seek(pCsr2, pKey, nKey, LSM_SEEK_EQ);
- testCompareInt(LSM_OK, ret, pRc);
- testCompareInt(1, lsm_csr_valid(pCsr2), pRc);
- ret = lsm_csr_next(pCsr2);
- testCompareInt(LSM_MISUSE, ret, pRc);
- ret = lsm_csr_prev(pCsr2);
- testCompareInt(LSM_MISUSE, ret, pRc);
-
- lsm_csr_close(pCsr2);
-
- ret = lsm_csr_first(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
-
- ret = lsm_csr_last(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
-
- ret = lsm_csr_first(pCsr);
- while( lsm_csr_valid(pCsr) ){
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- }
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
-
- ret = lsm_csr_last(pCsr);
- while( lsm_csr_valid(pCsr) ){
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- }
- ret = lsm_csr_prev(pCsr);
- testCompareInt(LSM_OK, ret, pRc);
- ret = lsm_csr_next(pCsr);
- testCompareInt(LSM_MISUSE, ret, pRc);
-
- lsm_csr_close(pCsr);
-}
-
-static void do_test_api1(const char *zPattern, int *pRc){
- if( testCaseBegin(pRc, zPattern, "api1.lsm") ){
- const DatasourceDefn defn = { TEST_DATASOURCE_RANDOM, 10, 15, 200, 250 };
- Datasource *pData;
- TestDb *pDb;
- int rc = 0;
-
- pDb = testOpen("lsm_lomem", 1, &rc);
- pData = testDatasourceNew(&defn);
- testWriteDatasourceRange(pDb, pData, 0, 1000, pRc);
-
- do_test_api1_lsm(tdb_lsm(pDb), pRc);
-
- testDatasourceFree(pData);
- testClose(&pDb);
-
- testCaseFinish(*pRc);
- }
-}
-
-static lsm_db *newLsmConnection(
- const char *zDb,
- int nPgsz,
- int nBlksz,
- int *pRc
-){
- lsm_db *db = 0;
- if( *pRc==0 ){
- int n1 = nPgsz;
- int n2 = nBlksz;
- *pRc = lsm_new(tdb_lsm_env(), &db);
- if( *pRc==0 ){
- if( n1 ) lsm_config(db, LSM_CONFIG_PAGE_SIZE, &n1);
- if( n2 ) lsm_config(db, LSM_CONFIG_BLOCK_SIZE, &n2);
- *pRc = lsm_open(db, "testdb.lsm");
- }
- }
- return db;
-}
-
-static void testPagesize(lsm_db *db, int nPgsz, int nBlksz, int *pRc){
- if( *pRc==0 ){
- int n1 = 0;
- int n2 = 0;
-
- lsm_config(db, LSM_CONFIG_PAGE_SIZE, &n1);
- lsm_config(db, LSM_CONFIG_BLOCK_SIZE, &n2);
-
- testCompareInt(n1, nPgsz, pRc);
- testCompareInt(n2, nBlksz, pRc);
- }
-}
-
-/*
-** Test case "api2" tests that the default page and block sizes of a
-** database may only be modified before lsm_open() is called. And that
-** after lsm_open() is called lsm_config() may be used to read the
-** actual page and block size of the db.
-*/
-static void do_test_api2(const char *zPattern, int *pRc){
- if( *pRc==0 && testCaseBegin(pRc, zPattern, "api2.lsm") ){
- lsm_db *db1 = 0;
- lsm_db *db2 = 0;
-
- testDeleteLsmdb("testdb.lsm");
- db1 = newLsmConnection("testdb.lsm", 0, 0, pRc);
- testPagesize(db1, 4096, 1024, pRc);
- db2 = newLsmConnection("testdb.lsm", 1024, 64*1024, pRc);
- testPagesize(db2, 4096, 1024, pRc);
- lsm_close(db1);
- lsm_close(db2);
-
- testDeleteLsmdb("testdb.lsm");
- db1 = newLsmConnection("testdb.lsm", 1024, 64*1024, pRc);
- testPagesize(db1, 1024, 64*1024, pRc);
- db2 = newLsmConnection("testdb.lsm", 0, 0, pRc);
- testPagesize(db2, 1024, 64*1024, pRc);
- lsm_close(db1);
- lsm_close(db2);
-
- testDeleteLsmdb("testdb.lsm");
- db1 = newLsmConnection("testdb.lsm", 8192, 2*1024, pRc);
- testPagesize(db1, 8192, 2*1024, pRc);
- db2 = newLsmConnection("testdb.lsm", 1024, 64*1024, pRc);
- testPagesize(db2, 8192, 2*1024, pRc);
- lsm_close(db1);
- lsm_close(db2);
-
- testCaseFinish(*pRc);
- }
-}
-
-void test_api(
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- do_test_api1(zPattern, pRc);
- do_test_api2(zPattern, pRc);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest8.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest8.c
deleted file mode 100644
index f734ac6aba2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest8.c
+++ /dev/null
@@ -1,326 +0,0 @@
-
-/*
-** This file contains test cases to verify that "live-recovery" following
-** a mid-transaction failure of a writer process.
-*/
-
-
-/*
-** This test file includes lsmInt.h to get access to the definition of the
-** ShmHeader structure. This is required to cause strategic damage to the
-** shared memory header as part of recovery testing.
-*/
-#include "lsmInt.h"
-
-#include "lsmtest.h"
-
-typedef struct SetupStep SetupStep;
-struct SetupStep {
- int bFlush; /* Flush to disk and checkpoint */
- int iInsStart; /* First key-value from ds to insert */
- int nIns; /* Number of rows to insert */
- int iDelStart; /* First key from ds to delete */
- int nDel; /* Number of rows to delete */
-};
-
-static void doSetupStep(
- TestDb *pDb,
- Datasource *pData,
- const SetupStep *pStep,
- int *pRc
-){
- testWriteDatasourceRange(pDb, pData, pStep->iInsStart, pStep->nIns, pRc);
- testDeleteDatasourceRange(pDb, pData, pStep->iDelStart, pStep->nDel, pRc);
- if( *pRc==0 ){
- int nSave = -1;
- int nBuf = 64;
- lsm_db *db = tdb_lsm(pDb);
-
- lsm_config(db, LSM_CONFIG_AUTOFLUSH, &nSave);
- lsm_config(db, LSM_CONFIG_AUTOFLUSH, &nBuf);
- lsm_begin(db, 1);
- lsm_commit(db, 0);
- lsm_config(db, LSM_CONFIG_AUTOFLUSH, &nSave);
-
- *pRc = lsm_work(db, 0, 0, 0);
- if( *pRc==0 ){
- *pRc = lsm_checkpoint(db, 0);
- }
- }
-}
-
-static void doSetupStepArray(
- TestDb *pDb,
- Datasource *pData,
- const SetupStep *aStep,
- int nStep
-){
- int i;
- for(i=0; i<nStep; i++){
- int rc = 0;
- doSetupStep(pDb, pData, &aStep[i], &rc);
- assert( rc==0 );
- }
-}
-
-static void setupDatabase1(TestDb *pDb, Datasource **ppData){
- const SetupStep aStep[] = {
- { 0, 1, 2000, 0, 0 },
- { 1, 0, 0, 0, 0 },
- { 0, 10001, 1000, 0, 0 },
- };
- const DatasourceDefn defn = {TEST_DATASOURCE_RANDOM, 12, 16, 100, 500};
- Datasource *pData;
-
- pData = testDatasourceNew(&defn);
- doSetupStepArray(pDb, pData, aStep, ArraySize(aStep));
- if( ppData ){
- *ppData = pData;
- }else{
- testDatasourceFree(pData);
- }
-}
-
-#include <stdio.h>
-void testReadFile(const char *zFile, int iOff, void *pOut, int nByte, int *pRc){
- if( *pRc==0 ){
- FILE *fd;
- fd = fopen(zFile, "rb");
- if( fd==0 ){
- *pRc = 1;
- }else{
- if( 0!=fseek(fd, iOff, SEEK_SET) ){
- *pRc = 1;
- }else{
- assert( nByte>=0 );
- if( (size_t)nByte!=fread(pOut, 1, nByte, fd) ){
- *pRc = 1;
- }
- }
- fclose(fd);
- }
- }
-}
-
-void testWriteFile(
- const char *zFile,
- int iOff,
- void *pOut,
- int nByte,
- int *pRc
-){
- if( *pRc==0 ){
- FILE *fd;
- fd = fopen(zFile, "r+b");
- if( fd==0 ){
- *pRc = 1;
- }else{
- if( 0!=fseek(fd, iOff, SEEK_SET) ){
- *pRc = 1;
- }else{
- assert( nByte>=0 );
- if( (size_t)nByte!=fwrite(pOut, 1, nByte, fd) ){
- *pRc = 1;
- }
- }
- fclose(fd);
- }
- }
-}
-
-static ShmHeader *getShmHeader(const char *zDb){
- int rc = 0;
- char *zShm = testMallocPrintf("%s-shm", zDb);
- ShmHeader *pHdr;
-
- pHdr = testMalloc(sizeof(ShmHeader));
- testReadFile(zShm, 0, (void *)pHdr, sizeof(ShmHeader), &rc);
- assert( rc==0 );
-
- return pHdr;
-}
-
-/*
-** This function makes a copy of the three files associated with LSM
-** database zDb (i.e. if zDb is "test.db", it makes copies of "test.db",
-** "test.db-log" and "test.db-shm").
-**
-** It then opens a new database connection to the copy with the xLock() call
-** instrumented so that it appears that some other process already connected
-** to the db (holding a shared lock on DMS2). This prevents recovery from
-** running. Then:
-**
-** 1) Check that the checksum of the database is zCksum.
-** 2) Write a few keys to the database. Then delete the same keys.
-** 3) Check that the checksum is zCksum.
-** 4) Flush the db to disk and run a checkpoint.
-** 5) Check once more that the checksum is still zCksum.
-*/
-static void doLiveRecovery(const char *zDb, const char *zCksum, int *pRc){
- if( *pRc==LSM_OK ){
- const DatasourceDefn defn = {TEST_DATASOURCE_RANDOM, 20, 25, 100, 500};
- Datasource *pData;
- const char *zCopy = "testcopy.lsm";
- char zCksum2[TEST_CKSUM_BYTES];
- TestDb *pDb = 0;
- int rc;
-
- pData = testDatasourceNew(&defn);
-
- testCopyLsmdb(zDb, zCopy);
- rc = tdb_lsm_open("test_no_recovery=1", zCopy, 0, &pDb);
- if( rc==0 ){
- ShmHeader *pHdr;
- lsm_db *db;
- testCksumDatabase(pDb, zCksum2);
- testCompareStr(zCksum, zCksum2, &rc);
-
- testWriteDatasourceRange(pDb, pData, 1, 10, &rc);
- testDeleteDatasourceRange(pDb, pData, 1, 10, &rc);
-
- /* Test that the two tree-headers are now consistent. */
- pHdr = getShmHeader(zCopy);
- if( rc==0 && memcmp(&pHdr->hdr1, &pHdr->hdr2, sizeof(pHdr->hdr1)) ){
- rc = 1;
- }
- testFree(pHdr);
-
- if( rc==0 ){
- int nBuf = 64;
- db = tdb_lsm(pDb);
- lsm_config(db, LSM_CONFIG_AUTOFLUSH, &nBuf);
- lsm_begin(db, 1);
- lsm_commit(db, 0);
- rc = lsm_work(db, 0, 0, 0);
- }
-
- testCksumDatabase(pDb, zCksum2);
- testCompareStr(zCksum, zCksum2, &rc);
- }
-
- testDatasourceFree(pData);
- testClose(&pDb);
- testDeleteLsmdb(zCopy);
- *pRc = rc;
- }
-}
-
-static void doWriterCrash1(int *pRc){
- const int nWrite = 2000;
- const int nStep = 10;
- const int iWriteStart = 20000;
- int rc = 0;
- TestDb *pDb = 0;
- Datasource *pData = 0;
-
- rc = tdb_lsm_open("autowork=0", "testdb.lsm", 1, &pDb);
- if( rc==0 ){
- int iDot = 0;
- char zCksum[TEST_CKSUM_BYTES];
- int i;
- setupDatabase1(pDb, &pData);
- testCksumDatabase(pDb, zCksum);
- testBegin(pDb, 2, &rc);
- for(i=0; rc==0 && i<nWrite; i+=nStep){
- testCaseProgress(i, nWrite, testCaseNDot(), &iDot);
- testWriteDatasourceRange(pDb, pData, iWriteStart+i, nStep, &rc);
- doLiveRecovery("testdb.lsm", zCksum, &rc);
- }
- }
- testCommit(pDb, 0, &rc);
- testClose(&pDb);
- testDatasourceFree(pData);
- *pRc = rc;
-}
-
-/*
-** This test case verifies that inconsistent tree-headers in shared-memory
-** are resolved correctly.
-*/
-static void doWriterCrash2(int *pRc){
- int rc = 0;
- TestDb *pDb = 0;
- Datasource *pData = 0;
-
- rc = tdb_lsm_open("autowork=0", "testdb.lsm", 1, &pDb);
- if( rc==0 ){
- ShmHeader *pHdr1;
- ShmHeader *pHdr2;
- char zCksum1[TEST_CKSUM_BYTES];
- char zCksum2[TEST_CKSUM_BYTES];
-
- pHdr1 = testMalloc(sizeof(ShmHeader));
- pHdr2 = testMalloc(sizeof(ShmHeader));
- setupDatabase1(pDb, &pData);
-
- /* Grab a copy of the shared-memory header. And the db checksum */
- testReadFile("testdb.lsm-shm", 0, (void *)pHdr1, sizeof(ShmHeader), &rc);
- testCksumDatabase(pDb, zCksum1);
-
- /* Modify the database */
- testBegin(pDb, 2, &rc);
- testWriteDatasourceRange(pDb, pData, 30000, 200, &rc);
- testCommit(pDb, 0, &rc);
-
- /* Grab a second copy of the shared-memory header. And the db checksum */
- testReadFile("testdb.lsm-shm", 0, (void *)pHdr2, sizeof(ShmHeader), &rc);
- testCksumDatabase(pDb, zCksum2);
- doLiveRecovery("testdb.lsm", zCksum2, &rc);
-
- /* If both tree-headers are valid, tree-header-1 is used. */
- memcpy(&pHdr2->hdr1, &pHdr1->hdr1, sizeof(pHdr1->hdr1));
- pHdr2->bWriter = 1;
- testWriteFile("testdb.lsm-shm", 0, (void *)pHdr2, sizeof(ShmHeader), &rc);
- doLiveRecovery("testdb.lsm", zCksum1, &rc);
-
- /* If both tree-headers are valid, tree-header-1 is used. */
- memcpy(&pHdr2->hdr1, &pHdr2->hdr2, sizeof(pHdr1->hdr1));
- memcpy(&pHdr2->hdr2, &pHdr1->hdr1, sizeof(pHdr1->hdr1));
- pHdr2->bWriter = 1;
- testWriteFile("testdb.lsm-shm", 0, (void *)pHdr2, sizeof(ShmHeader), &rc);
- doLiveRecovery("testdb.lsm", zCksum2, &rc);
-
- /* If tree-header 1 is invalid, tree-header-2 is used */
- memcpy(&pHdr2->hdr2, &pHdr2->hdr1, sizeof(pHdr1->hdr1));
- pHdr2->hdr1.aCksum[0] = 5;
- pHdr2->hdr1.aCksum[0] = 6;
- pHdr2->bWriter = 1;
- testWriteFile("testdb.lsm-shm", 0, (void *)pHdr2, sizeof(ShmHeader), &rc);
- doLiveRecovery("testdb.lsm", zCksum2, &rc);
-
- /* If tree-header 2 is invalid, tree-header-1 is used */
- memcpy(&pHdr2->hdr1, &pHdr2->hdr2, sizeof(pHdr1->hdr1));
- pHdr2->hdr2.aCksum[0] = 5;
- pHdr2->hdr2.aCksum[0] = 6;
- pHdr2->bWriter = 1;
- testWriteFile("testdb.lsm-shm", 0, (void *)pHdr2, sizeof(ShmHeader), &rc);
- doLiveRecovery("testdb.lsm", zCksum2, &rc);
-
- testFree(pHdr1);
- testFree(pHdr2);
- testClose(&pDb);
- }
-
- *pRc = rc;
-}
-
-void do_writer_crash_test(const char *zPattern, int *pRc){
- struct Test {
- const char *zName;
- void (*xFunc)(int *);
- } aTest[] = {
- { "writercrash1.lsm", doWriterCrash1 },
- { "writercrash2.lsm", doWriterCrash2 },
- };
- int i;
- for(i=0; i<ArraySize(aTest); i++){
- struct Test *p = &aTest[i];
- if( testCaseBegin(pRc, zPattern, p->zName) ){
- p->xFunc(pRc);
- testCaseFinish(*pRc);
- }
- }
-
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest9.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest9.c
deleted file mode 100644
index 144cae72030..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest9.c
+++ /dev/null
@@ -1,143 +0,0 @@
-
-#include "lsmtest.h"
-
-#define DATA_SEQUENTIAL TEST_DATASOURCE_SEQUENCE
-#define DATA_RANDOM TEST_DATASOURCE_RANDOM
-
-typedef struct Datatest4 Datatest4;
-
-/*
-** Test overview:
-**
-** 1. Insert (Datatest4.nRec) records into a database.
-**
-** 2. Repeat (Datatest4.nRepeat) times:
-**
-** 2a. Delete 2/3 of the records in the database.
-**
-** 2b. Run lsm_work(nMerge=1).
-**
-** 2c. Insert as many records as were deleted in 2a.
-**
-** 2d. Check database content is as expected.
-**
-** 2e. If (Datatest4.bReopen) is true, close and reopen the database.
-*/
-struct Datatest4 {
- /* Datasource definition */
- DatasourceDefn defn;
-
- int nRec;
- int nRepeat;
- int bReopen;
-};
-
-static void doDataTest4(
- const char *zSystem, /* Database system to test */
- Datatest4 *p, /* Structure containing test parameters */
- int *pRc /* OUT: Error code */
-){
- lsm_db *db = 0;
- TestDb *pDb;
- TestDb *pControl;
- Datasource *pData;
- int i;
- int rc = 0;
- int iDot = 0;
- int bMultiThreaded = 0; /* True for MT LSM database */
-
- int nRecOn3 = (p->nRec / 3);
- int iData = 0;
-
- /* Start the test case, open a database and allocate the datasource. */
- rc = testControlDb(&pControl);
- pDb = testOpen(zSystem, 1, &rc);
- pData = testDatasourceNew(&p->defn);
- if( rc==0 ){
- db = tdb_lsm(pDb);
- bMultiThreaded = tdb_lsm_multithread(pDb);
- }
-
- testWriteDatasourceRange(pControl, pData, iData, nRecOn3*3, &rc);
- testWriteDatasourceRange(pDb, pData, iData, nRecOn3*3, &rc);
-
- for(i=0; rc==0 && i<p->nRepeat; i++){
-
- testDeleteDatasourceRange(pControl, pData, iData, nRecOn3*2, &rc);
- testDeleteDatasourceRange(pDb, pData, iData, nRecOn3*2, &rc);
-
- if( db ){
- int nDone;
-#if 0
- fprintf(stderr, "lsm_work() start...\n"); fflush(stderr);
-#endif
- do {
- nDone = 0;
- rc = lsm_work(db, 1, (1<<30), &nDone);
- }while( rc==0 && nDone>0 );
- if( bMultiThreaded && rc==LSM_BUSY ) rc = LSM_OK;
-#if 0
- fprintf(stderr, "lsm_work() done...\n"); fflush(stderr);
-#endif
- }
-
-if( i+1<p->nRepeat ){
- iData += (nRecOn3*2);
- testWriteDatasourceRange(pControl, pData, iData+nRecOn3, nRecOn3*2, &rc);
- testWriteDatasourceRange(pDb, pData, iData+nRecOn3, nRecOn3*2, &rc);
-
- testCompareDb(pData, nRecOn3*3, iData, pControl, pDb, &rc);
-
- /* If Datatest4.bReopen is true, close and reopen the database */
- if( p->bReopen ){
- testReopen(&pDb, &rc);
- if( rc==0 ) db = tdb_lsm(pDb);
- }
-}
-
- /* Update the progress dots... */
- testCaseProgress(i, p->nRepeat, testCaseNDot(), &iDot);
- }
-
- testClose(&pDb);
- testClose(&pControl);
- testDatasourceFree(pData);
- testCaseFinish(rc);
- *pRc = rc;
-}
-
-static char *getName4(const char *zSystem, Datatest4 *pTest){
- char *zRet;
- char *zData;
- zData = testDatasourceName(&pTest->defn);
- zRet = testMallocPrintf("data4.%s.%s.%d.%d.%d",
- zSystem, zData, pTest->nRec, pTest->nRepeat, pTest->bReopen
- );
- testFree(zData);
- return zRet;
-}
-
-void test_data_4(
- const char *zSystem, /* Database system name */
- const char *zPattern, /* Run test cases that match this pattern */
- int *pRc /* IN/OUT: Error code */
-){
- Datatest4 aTest[] = {
- /* defn, nRec, nRepeat, bReopen */
- { {DATA_RANDOM, 20,25, 500,600}, 10000, 10, 0 },
- { {DATA_RANDOM, 20,25, 500,600}, 10000, 10, 1 },
- };
-
- int i;
-
- for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
- char *zName = getName4(zSystem, &aTest[i]);
- if( testCaseBegin(pRc, zPattern, "%s", zName) ){
- doDataTest4(zSystem, &aTest[i], pRc);
- }
- testFree(zName);
- }
-}
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_bt.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_bt.c
deleted file mode 100644
index 5135dd0559d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_bt.c
+++ /dev/null
@@ -1,75 +0,0 @@
-
-#include "lsmtest.h"
-#include "bt.h"
-
-int do_bt(int nArg, char **azArg){
- struct Option {
- const char *zName;
- int bPgno;
- int eOpt;
- } aOpt [] = {
- { "dbhdr", 0, BT_INFO_HDRDUMP },
- { "filename", 0, BT_INFO_FILENAME },
- { "block_freelist", 0, BT_INFO_BLOCK_FREELIST },
- { "page_freelist", 0, BT_INFO_PAGE_FREELIST },
- { "filename", 0, BT_INFO_FILENAME },
- { "page", 1, BT_INFO_PAGEDUMP },
- { "page_ascii", 1, BT_INFO_PAGEDUMP_ASCII },
- { "leaks", 0, BT_INFO_PAGE_LEAKS },
- { 0, 0 }
- };
- int iOpt;
- int rc;
- bt_info buf;
- char *zOpt;
- char *zFile;
-
- bt_db *db = 0;
-
- if( nArg<2 ){
- testPrintUsage("FILENAME OPTION ...");
- return -1;
- }
- zFile = azArg[0];
- zOpt = azArg[1];
-
- rc = testArgSelect(aOpt, "option", zOpt, &iOpt);
- if( rc!=0 ) return rc;
- if( nArg!=2+aOpt[iOpt].bPgno ){
- testPrintFUsage("FILENAME %s %s", zOpt, aOpt[iOpt].bPgno ? "PGNO" : "");
- return -4;
- }
-
- rc = sqlite4BtNew(sqlite4_env_default(), 0, &db);
- if( rc!=SQLITE4_OK ){
- testPrintError("sqlite4BtNew() failed: %d", rc);
- return -2;
- }
- rc = sqlite4BtOpen(db, zFile);
- if( rc!=SQLITE4_OK ){
- testPrintError("sqlite4BtOpen() failed: %d", rc);
- return -3;
- }
-
- buf.eType = aOpt[iOpt].eOpt;
- buf.pgno = 0;
- sqlite4_buffer_init(&buf.output, 0);
-
- if( aOpt[iOpt].bPgno ){
- buf.pgno = (u32)atoi(azArg[2]);
- }
-
- rc = sqlite4BtControl(db, BT_CONTROL_INFO, &buf);
- if( rc!=SQLITE4_OK ){
- testPrintError("sqlite4BtControl() failed: %d\n", rc);
- return -4;
- }
-
- printf("%s\n", (char*)buf.output.p);
- sqlite4_buffer_clear(&buf.output);
- return 0;
-}
-
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_datasource.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_datasource.c
deleted file mode 100644
index 0b0fd94e8b3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_datasource.c
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-#include "lsmtest.h"
-
-struct Datasource {
- int eType;
-
- int nMinKey;
- int nMaxKey;
- int nMinVal;
- int nMaxVal;
-
- char *aKey;
- char *aVal;
-};
-
-void testDatasourceEntry(
- Datasource *p,
- int iData,
- void **ppKey, int *pnKey,
- void **ppVal, int *pnVal
-){
- assert( (ppKey==0)==(pnKey==0) );
- assert( (ppVal==0)==(pnVal==0) );
-
- if( ppKey ){
- int nKey = 0;
- switch( p->eType ){
- case TEST_DATASOURCE_RANDOM: {
- int nRange = (1 + p->nMaxKey - p->nMinKey);
- nKey = (int)( testPrngValue((u32)iData) % nRange ) + p->nMinKey;
- testPrngString((u32)iData, p->aKey, nKey);
- break;
- }
- case TEST_DATASOURCE_SEQUENCE:
- nKey = sprintf(p->aKey, "%012d", iData);
- break;
- }
- *ppKey = p->aKey;
- *pnKey = nKey;
- }
- if( ppVal ){
- u32 nVal = testPrngValue((u32)iData)%(1+p->nMaxVal-p->nMinVal)+p->nMinVal;
- testPrngString((u32)~iData, p->aVal, (int)nVal);
- *ppVal = p->aVal;
- *pnVal = (int)nVal;
- }
-}
-
-void testDatasourceFree(Datasource *p){
- testFree(p);
-}
-
-/*
-** Return a pointer to a nul-terminated string that corresponds to the
-** contents of the datasource-definition passed as the first argument.
-** The caller should eventually free the returned pointer using testFree().
-*/
-char *testDatasourceName(const DatasourceDefn *p){
- char *zRet;
- zRet = testMallocPrintf("%s.(%d-%d).(%d-%d)",
- (p->eType==TEST_DATASOURCE_SEQUENCE ? "seq" : "rnd"),
- p->nMinKey, p->nMaxKey,
- p->nMinVal, p->nMaxVal
- );
- return zRet;
-}
-
-Datasource *testDatasourceNew(const DatasourceDefn *pDefn){
- Datasource *p;
- int nMinKey;
- int nMaxKey;
- int nMinVal;
- int nMaxVal;
-
- if( pDefn->eType==TEST_DATASOURCE_SEQUENCE ){
- nMinKey = 128;
- nMaxKey = 128;
- }else{
- nMinKey = MAX(0, pDefn->nMinKey);
- nMaxKey = MAX(nMinKey, pDefn->nMaxKey);
- }
- nMinVal = MAX(0, pDefn->nMinVal);
- nMaxVal = MAX(nMinVal, pDefn->nMaxVal);
-
- p = (Datasource *)testMalloc(sizeof(Datasource) + nMaxKey + nMaxVal + 1);
- p->eType = pDefn->eType;
- p->nMinKey = nMinKey;
- p->nMinVal = nMinVal;
- p->nMaxKey = nMaxKey;
- p->nMaxVal = nMaxVal;
-
- p->aKey = (char *)&p[1];
- p->aVal = &p->aKey[nMaxKey];
- return p;
-};
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_func.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_func.c
deleted file mode 100644
index eb8346aa836..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_func.c
+++ /dev/null
@@ -1,177 +0,0 @@
-
-#include "lsmtest.h"
-
-
-int do_work(int nArg, char **azArg){
- struct Option {
- const char *zName;
- } aOpt [] = {
- { "-nmerge" },
- { "-nkb" },
- { 0 }
- };
-
- lsm_db *pDb;
- int rc;
- int i;
- const char *zDb;
- int nMerge = 1;
- int nKB = (1<<30);
-
- if( nArg==0 ) goto usage;
- zDb = azArg[nArg-1];
- for(i=0; i<(nArg-1); i++){
- int iSel;
- rc = testArgSelect(aOpt, "option", azArg[i], &iSel);
- if( rc ) return rc;
- switch( iSel ){
- case 0:
- i++;
- if( i==(nArg-1) ) goto usage;
- nMerge = atoi(azArg[i]);
- break;
- case 1:
- i++;
- if( i==(nArg-1) ) goto usage;
- nKB = atoi(azArg[i]);
- break;
- }
- }
-
- rc = lsm_new(0, &pDb);
- if( rc!=LSM_OK ){
- testPrintError("lsm_open(): rc=%d\n", rc);
- }else{
- rc = lsm_open(pDb, zDb);
- if( rc!=LSM_OK ){
- testPrintError("lsm_open(): rc=%d\n", rc);
- }else{
- int n = -1;
- lsm_config(pDb, LSM_CONFIG_BLOCK_SIZE, &n);
- n = n*2;
- lsm_config(pDb, LSM_CONFIG_AUTOCHECKPOINT, &n);
-
- rc = lsm_work(pDb, nMerge, nKB, 0);
- if( rc!=LSM_OK ){
- testPrintError("lsm_work(): rc=%d\n", rc);
- }
- }
- }
- if( rc==LSM_OK ){
- rc = lsm_checkpoint(pDb, 0);
- }
-
- lsm_close(pDb);
- return rc;
-
- usage:
- testPrintUsage("?-optimize? ?-n N? DATABASE");
- return -1;
-}
-
-
-/*
-** lsmtest show ?-config LSM-CONFIG? DATABASE ?COMMAND ?PGNO??
-*/
-int do_show(int nArg, char **azArg){
- lsm_db *pDb;
- int rc;
- const char *zDb;
-
- int eOpt = LSM_INFO_DB_STRUCTURE;
- unsigned int iPg = 0;
- int bConfig = 0;
- const char *zConfig = "";
-
- struct Option {
- const char *zName;
- int bConfig;
- int eOpt;
- } aOpt [] = {
- { "array", 0, LSM_INFO_ARRAY_STRUCTURE },
- { "array-pages", 0, LSM_INFO_ARRAY_PAGES },
- { "blocksize", 1, LSM_CONFIG_BLOCK_SIZE },
- { "pagesize", 1, LSM_CONFIG_PAGE_SIZE },
- { "freelist", 0, LSM_INFO_FREELIST },
- { "page-ascii", 0, LSM_INFO_PAGE_ASCII_DUMP },
- { "page-hex", 0, LSM_INFO_PAGE_HEX_DUMP },
- { 0, 0 }
- };
-
- char *z = 0;
- int iDb = 0; /* Index of DATABASE in azArg[] */
-
- /* Check if there is a "-config" option: */
- if( nArg>2 && strlen(azArg[0])>1
- && memcmp(azArg[0], "-config", strlen(azArg[0]))==0
- ){
- zConfig = azArg[1];
- iDb = 2;
- }
- if( nArg<(iDb+1) ) goto usage;
-
- if( nArg>(iDb+1) ){
- rc = testArgSelect(aOpt, "option", azArg[iDb+1], &eOpt);
- if( rc!=0 ) return rc;
- bConfig = aOpt[eOpt].bConfig;
- eOpt = aOpt[eOpt].eOpt;
- if( (bConfig==0 && eOpt==LSM_INFO_FREELIST)
- || (bConfig==1 && eOpt==LSM_CONFIG_BLOCK_SIZE)
- || (bConfig==1 && eOpt==LSM_CONFIG_PAGE_SIZE)
- ){
- if( nArg!=(iDb+2) ) goto usage;
- }else{
- if( nArg!=(iDb+3) ) goto usage;
- iPg = atoi(azArg[iDb+2]);
- }
- }
- zDb = azArg[iDb];
-
- rc = lsm_new(0, &pDb);
- tdb_lsm_configure(pDb, zConfig);
- if( rc!=LSM_OK ){
- testPrintError("lsm_new(): rc=%d\n", rc);
- }else{
- rc = lsm_open(pDb, zDb);
- if( rc!=LSM_OK ){
- testPrintError("lsm_open(): rc=%d\n", rc);
- }
- }
-
- if( rc==LSM_OK ){
- if( bConfig==0 ){
- switch( eOpt ){
- case LSM_INFO_DB_STRUCTURE:
- case LSM_INFO_FREELIST:
- rc = lsm_info(pDb, eOpt, &z);
- break;
- case LSM_INFO_ARRAY_STRUCTURE:
- case LSM_INFO_ARRAY_PAGES:
- case LSM_INFO_PAGE_ASCII_DUMP:
- case LSM_INFO_PAGE_HEX_DUMP:
- rc = lsm_info(pDb, eOpt, iPg, &z);
- break;
- default:
- assert( !"no chance" );
- }
-
- if( rc==LSM_OK ){
- printf("%s\n", z ? z : "");
- fflush(stdout);
- }
- lsm_free(lsm_get_env(pDb), z);
- }else{
- int iRes = -1;
- lsm_config(pDb, eOpt, &iRes);
- printf("%d\n", iRes);
- fflush(stdout);
- }
- }
-
- lsm_close(pDb);
- return rc;
-
- usage:
- testPrintUsage("DATABASE ?array|page-ascii|page-hex PGNO?");
- return -1;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_io.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_io.c
deleted file mode 100644
index 7aa5d109483..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_io.c
+++ /dev/null
@@ -1,248 +0,0 @@
-
-/*
-** SUMMARY
-**
-** This file implements the 'io' subcommand of the test program. It is used
-** for testing the performance of various combinations of write() and fsync()
-** system calls. All operations occur on a single file, which may or may not
-** exist when a test is started.
-**
-** A test consists of a series of commands. Each command is either a write
-** or an fsync. A write is specified as "<amount>@<offset>", where <amount>
-** is the amount of data written, and <offset> is the offset of the file
-** to write to. An <amount> or an <offset> is specified as an integer number
-** of bytes. Or, if postfixed with a "K", "M" or "G", an integer number of
-** KB, MB or GB, respectively. An fsync is simply "S". All commands are
-** case-insensitive.
-**
-** Example test program:
-**
-** 2M@6M 1492K@4M S 4096@4K S
-**
-** This program writes 2 MB of data starting at the offset 6MB offset of
-** the file, followed by 1492 KB of data written at the 4MB offset of the
-** file, followed by a call to fsync(), a write of 4KB of data at byte
-** offset 4096, and finally another call to fsync().
-**
-** Commands may either be specified on the command line (one command per
-** command line argument) or read from stdin. Commands read from stdin
-** must be separated by white-space.
-**
-** COMMAND LINE INVOCATION
-**
-** The sub-command implemented in this file must be invoked with at least
-** two arguments - the path to the file to write to and the page-size to
-** use for writing. If there are more than two arguments, then each
-** subsequent argument is assumed to be a test command. If there are exactly
-** two arguments, the test commands are read from stdin.
-**
-** A write command does not result in a single call to system call write().
-** Instead, the specified region is written sequentially using one or
-** more calls to write(), each of which writes not more than one page of
-** data. For example, if the page-size is 4KB, the command "2M@6M" results
-** in 512 calls to write(), each of which writes 4KB of data.
-**
-** EXAMPLES
-**
-** Two equivalent examples:
-**
-** $ lsmtest io testfile.db 4KB 2M@6M 1492K@4M S 4096@4K S
-** 3544K written in 129 ms
-** $ echo "2M@6M 1492K@4M S 4096@4K S" | lsmtest io testfile.db 4096
-** 3544K written in 127 ms
-**
-*/
-
-#include "lsmtest.h"
-
-typedef struct IoContext IoContext;
-
-struct IoContext {
- int fd;
- int nWrite;
-};
-
-/*
-** As isspace(3)
-*/
-static int safe_isspace(char c){
- if( c&0x80) return 0;
- return isspace(c);
-}
-
-/*
-** As isdigit(3)
-*/
-static int safe_isdigit(char c){
- if( c&0x80) return 0;
- return isdigit(c);
-}
-
-static i64 getNextSize(char *zIn, char **pzOut, int *pRc){
- i64 iRet = 0;
- if( *pRc==0 ){
- char *z = zIn;
-
- if( !safe_isdigit(*z) ){
- *pRc = 1;
- return 0;
- }
-
- /* Process digits */
- while( safe_isdigit(*z) ){
- iRet = iRet*10 + (*z - '0');
- z++;
- }
-
- /* Process suffix */
- switch( *z ){
- case 'k': case 'K':
- iRet = iRet * 1024;
- z++;
- break;
-
- case 'm': case 'M':
- iRet = iRet * 1024 * 1024;
- z++;
- break;
-
- case 'g': case 'G':
- iRet = iRet * 1024 * 1024 * 1024;
- z++;
- break;
- }
-
- if( pzOut ) *pzOut = z;
- }
- return iRet;
-}
-
-static int doOneCmd(
- IoContext *pCtx,
- u8 *aData,
- int pgsz,
- char *zCmd,
- char **pzOut
-){
- char c;
- char *z = zCmd;
-
- while( safe_isspace(*z) ) z++;
- c = *z;
-
- if( c==0 ){
- if( pzOut ) *pzOut = z;
- return 0;
- }
-
- if( c=='s' || c=='S' ){
- if( pzOut ) *pzOut = &z[1];
- return fdatasync(pCtx->fd);
- }
-
- if( safe_isdigit(c) ){
- i64 iOff = 0;
- int nByte = 0;
- int rc = 0;
- int nPg;
- int iPg;
-
- nByte = (int)getNextSize(z, &z, &rc);
- if( rc || *z!='@' ) goto bad_command;
- z++;
- iOff = getNextSize(z, &z, &rc);
- if( rc || (safe_isspace(*z)==0 && *z!='\0') ) goto bad_command;
- if( pzOut ) *pzOut = z;
-
- nPg = (nByte+pgsz-1) / pgsz;
- lseek(pCtx->fd, (off_t)iOff, SEEK_SET);
- for(iPg=0; iPg<nPg; iPg++){
- write(pCtx->fd, aData, pgsz);
- }
- pCtx->nWrite += nByte/1024;
-
- return 0;
- }
-
- bad_command:
- testPrintError("unrecognized command: %s", zCmd);
- return 1;
-}
-
-static int readStdin(char **pzOut){
- int nAlloc = 128;
- char *zOut = 0;
- int nOut = 0;
-
- while( !feof(stdin) ){
- int nRead;
-
- nAlloc = nAlloc*2;
- zOut = realloc(zOut, nAlloc);
- nRead = fread(&zOut[nOut], 1, nAlloc-nOut-1, stdin);
-
- if( nRead==0 ) break;
- nOut += nRead;
- zOut[nOut] = '\0';
- }
-
- *pzOut = zOut;
- return 0;
-}
-
-int do_io(int nArg, char **azArg){
- IoContext ctx;
- int pgsz;
- char *zFile;
- char *zPgsz;
- int i;
- int rc = 0;
-
- char *zStdin = 0;
- char *z;
-
- u8 *aData;
-
- memset(&ctx, 0, sizeof(IoContext));
- if( nArg<2 ){
- testPrintUsage("FILE PGSZ ?CMD-1 ...?");
- return -1;
- }
- zFile = azArg[0];
- zPgsz = azArg[1];
-
- pgsz = (int)getNextSize(zPgsz, 0, &rc);
- if( pgsz<=0 ){
- testPrintError("Ridiculous page size: %d", pgsz);
- return -1;
- }
- aData = malloc(pgsz);
- memset(aData, 0x77, pgsz);
-
- ctx.fd = open(zFile, O_RDWR|O_CREAT|_O_BINARY, 0644);
- if( ctx.fd<0 ){
- perror("open: ");
- return -1;
- }
-
- if( nArg==2 ){
- readStdin(&zStdin);
- testTimeInit();
- z = zStdin;
- while( *z && rc==0 ){
- rc = doOneCmd(&ctx, aData, pgsz, z, &z);
- }
- }else{
- testTimeInit();
- for(i=2; i<nArg; i++){
- rc = doOneCmd(&ctx, aData, pgsz, azArg[i], 0);
- }
- }
-
- printf("%dK written in %d ms\n", ctx.nWrite, testTimeGet());
-
- free(zStdin);
- close(ctx.fd);
-
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_main.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_main.c
deleted file mode 100644
index f4a3ac0d563..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_main.c
+++ /dev/null
@@ -1,1548 +0,0 @@
-
-#include "lsmtest.h"
-#include <sqlite3.h>
-
-void test_failed(){
- assert( 0 );
- return;
-}
-
-#define testSetError(rc) testSetErrorFunc(rc, pRc, __FILE__, __LINE__)
-static void testSetErrorFunc(int rc, int *pRc, const char *zFile, int iLine){
- if( rc ){
- *pRc = rc;
- fprintf(stderr, "FAILED (%s:%d) rc=%d ", zFile, iLine, rc);
- test_failed();
- }
-}
-
-static int lsm_memcmp(u8 *a, u8 *b, int c){
- int i;
- for(i=0; i<c; i++){
- if( a[i]!=b[i] ) return a[i] - b[i];
- }
- return 0;
-}
-
-/*
-** A test utility function.
-*/
-void testFetch(
- TestDb *pDb, /* Database handle */
- void *pKey, int nKey, /* Key to query database for */
- void *pVal, int nVal, /* Expected value */
- int *pRc /* IN/OUT: Error code */
-){
- if( *pRc==0 ){
- void *pDbVal;
- int nDbVal;
- int rc;
-
- static int nCall = 0; nCall++;
-
- rc = tdb_fetch(pDb, pKey, nKey, &pDbVal, &nDbVal);
- testSetError(rc);
- if( rc==0 && (nVal!=nDbVal || (nVal>0 && lsm_memcmp(pVal, pDbVal, nVal))) ){
- testSetError(1);
- }
- }
-}
-
-void testWrite(
- TestDb *pDb, /* Database handle */
- void *pKey, int nKey, /* Key to query database for */
- void *pVal, int nVal, /* Value to write */
- int *pRc /* IN/OUT: Error code */
-){
- if( *pRc==0 ){
- int rc;
-static int nCall = 0;
-nCall++;
- rc = tdb_write(pDb, pKey, nKey, pVal, nVal);
- testSetError(rc);
- }
-}
-void testDelete(
- TestDb *pDb, /* Database handle */
- void *pKey, int nKey, /* Key to query database for */
- int *pRc /* IN/OUT: Error code */
-){
- if( *pRc==0 ){
- int rc;
- *pRc = rc = tdb_delete(pDb, pKey, nKey);
- testSetError(rc);
- }
-}
-void testDeleteRange(
- TestDb *pDb, /* Database handle */
- void *pKey1, int nKey1,
- void *pKey2, int nKey2,
- int *pRc /* IN/OUT: Error code */
-){
- if( *pRc==0 ){
- int rc;
- *pRc = rc = tdb_delete_range(pDb, pKey1, nKey1, pKey2, nKey2);
- testSetError(rc);
- }
-}
-
-void testBegin(TestDb *pDb, int iTrans, int *pRc){
- if( *pRc==0 ){
- int rc;
- rc = tdb_begin(pDb, iTrans);
- testSetError(rc);
- }
-}
-void testCommit(TestDb *pDb, int iTrans, int *pRc){
- if( *pRc==0 ){
- int rc;
- rc = tdb_commit(pDb, iTrans);
- testSetError(rc);
- }
-}
-#if 0 /* unused */
-static void testRollback(TestDb *pDb, int iTrans, int *pRc){
- if( *pRc==0 ){
- int rc;
- rc = tdb_rollback(pDb, iTrans);
- testSetError(rc);
- }
-}
-#endif
-
-void testWriteStr(
- TestDb *pDb, /* Database handle */
- const char *zKey, /* Key to query database for */
- const char *zVal, /* Value to write */
- int *pRc /* IN/OUT: Error code */
-){
- int nVal = (zVal ? strlen(zVal) : 0);
- testWrite(pDb, (void *)zKey, strlen(zKey), (void *)zVal, nVal, pRc);
-}
-
-#if 0 /* unused */
-static void testDeleteStr(TestDb *pDb, const char *zKey, int *pRc){
- testDelete(pDb, (void *)zKey, strlen(zKey), pRc);
-}
-#endif
-void testFetchStr(
- TestDb *pDb, /* Database handle */
- const char *zKey, /* Key to query database for */
- const char *zVal, /* Value to write */
- int *pRc /* IN/OUT: Error code */
-){
- int nVal = (zVal ? strlen(zVal) : 0);
- testFetch(pDb, (void *)zKey, strlen(zKey), (void *)zVal, nVal, pRc);
-}
-
-void testFetchCompare(
- TestDb *pControl,
- TestDb *pDb,
- void *pKey, int nKey,
- int *pRc
-){
- int rc;
- void *pDbVal1;
- void *pDbVal2;
- int nDbVal1;
- int nDbVal2;
-
- static int nCall = 0;
- nCall++;
-
- rc = tdb_fetch(pControl, pKey, nKey, &pDbVal1, &nDbVal1);
- testSetError(rc);
-
- rc = tdb_fetch(pDb, pKey, nKey, &pDbVal2, &nDbVal2);
- testSetError(rc);
-
- if( *pRc==0
- && (nDbVal1!=nDbVal2 || (nDbVal1>0 && memcmp(pDbVal1, pDbVal2, nDbVal1)))
- ){
- testSetError(1);
- }
-}
-
-typedef struct ScanResult ScanResult;
-struct ScanResult {
- TestDb *pDb;
-
- int nRow;
- u32 cksum1;
- u32 cksum2;
- void *pKey1; int nKey1;
- void *pKey2; int nKey2;
-
- int bReverse;
- int nPrevKey;
- u8 aPrevKey[256];
-};
-
-static int keyCompare(void *pKey1, int nKey1, void *pKey2, int nKey2){
- int res;
- res = memcmp(pKey1, pKey2, MIN(nKey1, nKey2));
- if( res==0 ){
- res = nKey1 - nKey2;
- }
- return res;
-}
-
-int test_scan_debug = 0;
-
-static void scanCompareCb(
- void *pCtx,
- void *pKey, int nKey,
- void *pVal, int nVal
-){
- ScanResult *p = (ScanResult *)pCtx;
- u8 *aKey = (u8 *)pKey;
- u8 *aVal = (u8 *)pVal;
- int i;
-
- if( test_scan_debug ){
- printf("%d: %.*s\n", p->nRow, nKey, (char *)pKey);
- fflush(stdout);
- }
-#if 0
- if( test_scan_debug ) printf("%.20s\n", (char *)pVal);
-#endif
-
-#if 0
- /* Check tdb_fetch() matches */
- int rc = 0;
- testFetch(p->pDb, pKey, nKey, pVal, nVal, &rc);
- assert( rc==0 );
-#endif
-
- /* Update the checksum data */
- p->nRow++;
- for(i=0; i<nKey; i++){
- p->cksum1 += ((int)aKey[i] << (i&0x0F));
- p->cksum2 += p->cksum1;
- }
- for(i=0; i<nVal; i++){
- p->cksum1 += ((int)aVal[i] << (i&0x0F));
- p->cksum2 += p->cksum1;
- }
-
- /* Check that the delivered row is not out of order. */
- if( nKey<(int)sizeof(p->aPrevKey) ){
- if( p->nPrevKey ){
- int res = keyCompare(p->aPrevKey, p->nPrevKey, pKey, nKey);
- if( (res<0 && p->bReverse) || (res>0 && p->bReverse==0) ){
- testPrintError("Returned key out of order at %s:%d\n",
- __FILE__, __LINE__
- );
- }
- }
-
- p->nPrevKey = nKey;
- memcpy(p->aPrevKey, pKey, MIN(p->nPrevKey, nKey));
- }
-
- /* Check that the delivered row is within range. */
- if( p->pKey1 && (
- (memcmp(p->pKey1, pKey, MIN(p->nKey1, nKey))>0)
- || (memcmp(p->pKey1, pKey, MIN(p->nKey1, nKey))==0 && p->nKey1>nKey)
- )){
- testPrintError("Returned key too small at %s:%d\n", __FILE__, __LINE__);
- }
- if( p->pKey2 && (
- (memcmp(p->pKey2, pKey, MIN(p->nKey2, nKey))<0)
- || (memcmp(p->pKey2, pKey, MIN(p->nKey2, nKey))==0 && p->nKey2<nKey)
- )){
- testPrintError("Returned key too large at %s:%d\n", __FILE__, __LINE__);
- }
-
-}
-
-/*
-** Scan the contents of the two databases. Check that they match.
-*/
-void testScanCompare(
- TestDb *pDb1, /* Control (trusted) database */
- TestDb *pDb2, /* Database being tested */
- int bReverse,
- void *pKey1, int nKey1,
- void *pKey2, int nKey2,
- int *pRc
-){
- static int nCall = 0; nCall++;
- if( *pRc==0 ){
- ScanResult res1;
- ScanResult res2;
- void *pRes1 = (void *)&res1;
- void *pRes2 = (void *)&res2;
-
- memset(&res1, 0, sizeof(ScanResult));
- memset(&res2, 0, sizeof(ScanResult));
-
- res1.pDb = pDb1;
- res1.nKey1 = nKey1; res1.pKey1 = pKey1;
- res1.nKey2 = nKey2; res1.pKey2 = pKey2;
- res1.bReverse = bReverse;
- res2.pDb = pDb2;
- res2.nKey1 = nKey1; res2.pKey1 = pKey1;
- res2.nKey2 = nKey2; res2.pKey2 = pKey2;
- res2.bReverse = bReverse;
-
- tdb_scan(pDb1, pRes1, bReverse, pKey1, nKey1, pKey2, nKey2, scanCompareCb);
-if( test_scan_debug ) printf("\n\n\n");
- tdb_scan(pDb2, pRes2, bReverse, pKey1, nKey1, pKey2, nKey2, scanCompareCb);
-if( test_scan_debug ) printf("\n\n\n");
-
- if( res1.nRow!=res2.nRow
- || res1.cksum1!=res2.cksum1
- || res1.cksum2!=res2.cksum2
- ){
- printf("expected: %d %X %X\n", res1.nRow, res1.cksum1, res1.cksum2);
- printf("got: %d %X %X\n", res2.nRow, res2.cksum1, res2.cksum2);
- testSetError(1);
- *pRc = 1;
- }
- }
-}
-
-void testClose(TestDb **ppDb){
- tdb_close(*ppDb);
- *ppDb = 0;
-}
-
-TestDb *testOpen(const char *zSystem, int bClear, int *pRc){
- TestDb *pDb = 0;
- if( *pRc==0 ){
- int rc;
- rc = tdb_open(zSystem, 0, bClear, &pDb);
- if( rc!=0 ){
- testSetError(rc);
- *pRc = rc;
- }
- }
- return pDb;
-}
-
-void testReopen(TestDb **ppDb, int *pRc){
- if( *pRc==0 ){
- const char *zLib;
- zLib = tdb_library_name(*ppDb);
- testClose(ppDb);
- *pRc = tdb_open(zLib, 0, 0, ppDb);
- }
-}
-
-
-#if 0 /* unused */
-static void testSystemSelect(const char *zSys, int *piSel, int *pRc){
- if( *pRc==0 ){
- struct SysName { const char *zName; } *aName;
- int nSys;
- int i;
-
- for(nSys=0; tdb_system_name(nSys); nSys++);
- aName = malloc(sizeof(struct SysName) * (nSys+1));
- for(i=0; i<=nSys; i++){
- aName[i].zName = tdb_system_name(i);
- }
-
- *pRc = testArgSelect(aName, "db", zSys, piSel);
- free(aName);
- }
-}
-#endif
-
-char *testMallocVPrintf(const char *zFormat, va_list ap){
- int nByte;
- va_list copy;
- char *zRet;
-
- __va_copy(copy, ap);
- nByte = vsnprintf(0, 0, zFormat, copy);
- va_end(copy);
-
- assert( nByte>=0 );
- zRet = (char *)testMalloc(nByte+1);
- vsnprintf(zRet, nByte+1, zFormat, ap);
- return zRet;
-}
-
-char *testMallocPrintf(const char *zFormat, ...){
- va_list ap;
- char *zRet;
-
- va_start(ap, zFormat);
- zRet = testMallocVPrintf(zFormat, ap);
- va_end(ap);
-
- return zRet;
-}
-
-
-/*
-** A wrapper around malloc(3).
-**
-** This function should be used for all allocations made by test procedures.
-** It has the following properties:
-**
-** * Test code may assume that allocations may not fail.
-** * Returned memory is always zeroed.
-**
-** Allocations made using testMalloc() should be freed using testFree().
-*/
-void *testMalloc(int n){
- u8 *p = (u8*)malloc(n + 8);
- memset(p, 0, n+8);
- *(int*)p = n;
- return (void*)&p[8];
-}
-
-void *testMallocCopy(void *pCopy, int nByte){
- void *pRet = testMalloc(nByte);
- memcpy(pRet, pCopy, nByte);
- return pRet;
-}
-
-void *testRealloc(void *ptr, int n){
- if( ptr ){
- u8 *p = (u8*)ptr - 8;
- int nOrig = *(int*)p;
- p = (u8*)realloc(p, n+8);
- if( nOrig<n ){
- memset(&p[8+nOrig], 0, n-nOrig);
- }
- *(int*)p = n;
- return (void*)&p[8];
- }
- return testMalloc(n);
-}
-
-/*
-** Free an allocation made by an earlier call to testMalloc().
-*/
-void testFree(void *ptr){
- if( ptr ){
- u8 *p = (u8*)ptr - 8;
- memset(p, 0x55, *(int*)p + 8);
- free(p);
- }
-}
-
-/*
-** String zPattern contains a glob pattern. Return true if zStr matches
-** the pattern, or false if it does not.
-*/
-int testGlobMatch(const char *zPattern, const char *zStr){
- int i = 0;
- int j = 0;
-
- while( zPattern[i] ){
- char p = zPattern[i];
-
- if( p=='*' || p=='%' ){
- do {
- if( testGlobMatch(&zPattern[i+1], &zStr[j]) ) return 1;
- }while( zStr[j++] );
- return 0;
- }
-
- if( zStr[j]==0 || (p!='?' && p!=zStr[j]) ){
- /* Match failed. */
- return 0;
- }
-
- j++;
- i++;
- }
-
- return (zPattern[i]==0 && zStr[j]==0);
-}
-
-/*
-** End of test utilities
-**************************************************************************/
-
-int do_test(int nArg, char **azArg){
- int j;
- int rc;
- int nFail = 0;
- const char *zPattern = 0;
-
- if( nArg>1 ){
- testPrintError("Usage: test ?PATTERN?\n");
- return 1;
- }
- if( nArg==1 ){
- zPattern = azArg[0];
- }
-
- for(j=0; tdb_system_name(j); j++){
- rc = 0;
-
- test_data_1(tdb_system_name(j), zPattern, &rc);
- test_data_2(tdb_system_name(j), zPattern, &rc);
- test_data_3(tdb_system_name(j), zPattern, &rc);
- test_data_4(tdb_system_name(j), zPattern, &rc);
- test_rollback(tdb_system_name(j), zPattern, &rc);
- test_mc(tdb_system_name(j), zPattern, &rc);
- test_mt(tdb_system_name(j), zPattern, &rc);
-
- if( rc ) nFail++;
- }
-
- rc = 0;
- test_oom(zPattern, &rc);
- if( rc ) nFail++;
-
- rc = 0;
- test_api(zPattern, &rc);
- if( rc ) nFail++;
-
- rc = 0;
- do_crash_test(zPattern, &rc);
- if( rc ) nFail++;
-
- rc = 0;
- do_writer_crash_test(zPattern, &rc);
- if( rc ) nFail++;
-
- return (nFail!=0);
-}
-
-static lsm_db *configure_lsm_db(TestDb *pDb){
- lsm_db *pLsm;
- pLsm = tdb_lsm(pDb);
- if( pLsm ){
- tdb_lsm_config_str(pDb, "mmap=1 autowork=1 automerge=4 worker_automerge=4");
- }
- return pLsm;
-}
-
-typedef struct WriteHookEvent WriteHookEvent;
-struct WriteHookEvent {
- i64 iOff;
- int nData;
- int nUs;
-};
-WriteHookEvent prev = {0, 0, 0};
-
-static void flushPrev(FILE *pOut){
- if( prev.nData ){
- fprintf(pOut, "w %s %lld %d %d\n", "d", prev.iOff, prev.nData, prev.nUs);
- prev.nData = 0;
- }
-}
-
-#if 0 /* unused */
-static void do_speed_write_hook2(
- void *pCtx,
- int bLog,
- i64 iOff,
- int nData,
- int nUs
-){
- FILE *pOut = (FILE *)pCtx;
- if( bLog ) return;
-
- if( prev.nData && nData && iOff==prev.iOff+prev.nData ){
- prev.nData += nData;
- prev.nUs += nUs;
- }else{
- flushPrev(pOut);
- if( nData==0 ){
- fprintf(pOut, "s %s 0 0 %d\n", (bLog ? "l" : "d"), nUs);
- }else{
- prev.iOff = iOff;
- prev.nData = nData;
- prev.nUs = nUs;
- }
- }
-}
-#endif
-
-#define ST_REPEAT 0
-#define ST_WRITE 1
-#define ST_PAUSE 2
-#define ST_FETCH 3
-#define ST_SCAN 4
-#define ST_NSCAN 5
-#define ST_KEYSIZE 6
-#define ST_VALSIZE 7
-#define ST_TRANS 8
-
-
-static void print_speed_test_help(){
- printf(
-"\n"
-"Repeat the following $repeat times:\n"
-" 1. Insert $write key-value pairs. One transaction for each write op.\n"
-" 2. Pause for $pause ms.\n"
-" 3. Perform $fetch queries on the database.\n"
-"\n"
-" Keys are $keysize bytes in size. Values are $valsize bytes in size\n"
-" Both keys and values are pseudo-randomly generated\n"
-"\n"
-"Options are:\n"
-" -repeat $repeat (default value 10)\n"
-" -write $write (default value 10000)\n"
-" -pause $pause (default value 0)\n"
-" -fetch $fetch (default value 0)\n"
-" -keysize $keysize (default value 12)\n"
-" -valsize $valsize (default value 100)\n"
-" -system $system (default value \"lsm\")\n"
-" -trans $trans (default value 0)\n"
-"\n"
-);
-}
-
-int do_speed_test2(int nArg, char **azArg){
- struct Option {
- const char *zOpt;
- int eVal;
- int iDefault;
- } aOpt[] = {
- { "-repeat", ST_REPEAT, 10},
- { "-write", ST_WRITE, 10000},
- { "-pause", ST_PAUSE, 0},
- { "-fetch", ST_FETCH, 0},
- { "-scan", ST_SCAN, 0},
- { "-nscan", ST_NSCAN, 0},
- { "-keysize", ST_KEYSIZE, 12},
- { "-valsize", ST_VALSIZE, 100},
- { "-trans", ST_TRANS, 0},
- { "-system", -1, 0},
- { "help", -2, 0},
- {0, 0, 0}
- };
- int i;
- int aParam[9];
- int rc = 0;
- int bReadonly = 0;
- int nContent = 0;
-
- TestDb *pDb;
- Datasource *pData;
- DatasourceDefn defn = { TEST_DATASOURCE_RANDOM, 0, 0, 0, 0 };
- char *zSystem = "";
- int bLsm = 1;
- FILE *pLog = 0;
-
-#ifdef NDEBUG
- /* If NDEBUG is defined, disable the dynamic memory related checks in
- ** lsmtest_mem.c. They slow things down. */
- testMallocUninstall(tdb_lsm_env());
-#endif
-
- /* Initialize aParam[] with default values. */
- for(i=0; i<ArraySize(aOpt); i++){
- if( aOpt[i].zOpt ) aParam[aOpt[i].eVal] = aOpt[i].iDefault;
- }
-
- /* Process the command line switches. */
- for(i=0; i<nArg; i+=2){
- int iSel;
- rc = testArgSelect(aOpt, "switch", azArg[i], &iSel);
- if( rc ){
- return rc;
- }
- if( aOpt[iSel].eVal==-2 ){
- print_speed_test_help();
- return 0;
- }
- if( i+1==nArg ){
- testPrintError("option %s requires an argument\n", aOpt[iSel].zOpt);
- return 1;
- }
- if( aOpt[iSel].eVal>=0 ){
- aParam[aOpt[iSel].eVal] = atoi(azArg[i+1]);
- }else{
- zSystem = azArg[i+1];
- bLsm = 0;
-#if 0
- for(j=0; zSystem[j]; j++){
- if( zSystem[j]=='=' ) bLsm = 1;
- }
-#endif
- }
- }
-
- printf("#");
- for(i=0; i<ArraySize(aOpt); i++){
- if( aOpt[i].zOpt ){
- if( aOpt[i].eVal>=0 ){
- printf(" %s=%d", &aOpt[i].zOpt[1], aParam[aOpt[i].eVal]);
- }else if( aOpt[i].eVal==-1 ){
- printf(" %s=\"%s\"", &aOpt[i].zOpt[1], zSystem);
- }
- }
- }
- printf("\n");
-
- defn.nMinKey = defn.nMaxKey = aParam[ST_KEYSIZE];
- defn.nMinVal = defn.nMaxVal = aParam[ST_VALSIZE];
- pData = testDatasourceNew(&defn);
-
- if( aParam[ST_WRITE]==0 ){
- bReadonly = 1;
- }
-
- if( bLsm ){
- rc = tdb_lsm_open(zSystem, "testdb.lsm", !bReadonly, &pDb);
- }else{
- pDb = testOpen(zSystem, !bReadonly, &rc);
- }
- if( rc!=0 ) return rc;
- if( bReadonly ){
- nContent = testCountDatabase(pDb);
- }
-
-#if 0
- pLog = fopen("/tmp/speed.log", "w");
- tdb_lsm_write_hook(pDb, do_speed_write_hook2, (void *)pLog);
-#endif
-
- for(i=0; i<aParam[ST_REPEAT] && rc==0; i++){
- int msWrite, msFetch;
- int iFetch;
- int nWrite = aParam[ST_WRITE];
-
- if( bReadonly ){
- msWrite = 0;
- }else{
- testTimeInit();
-
- if( aParam[ST_TRANS] ) testBegin(pDb, 2, &rc);
- testWriteDatasourceRange(pDb, pData, i*nWrite, nWrite, &rc);
- if( aParam[ST_TRANS] ) testCommit(pDb, 0, &rc);
-
- msWrite = testTimeGet();
- nContent += nWrite;
- }
-
- if( aParam[ST_PAUSE] ){
- if( aParam[ST_PAUSE]/1000 ) sleep(aParam[ST_PAUSE]/1000);
- if( aParam[ST_PAUSE]%1000 ) usleep(1000 * (aParam[ST_PAUSE]%1000));
- }
-
- if( aParam[ST_FETCH] ){
- testTimeInit();
- if( aParam[ST_TRANS] ) testBegin(pDb, 1, &rc);
- for(iFetch=0; iFetch<aParam[ST_FETCH]; iFetch++){
- int iKey = testPrngValue(i*nWrite+iFetch) % nContent;
-#ifndef NDEBUG
- testDatasourceFetch(pDb, pData, iKey, &rc);
-#else
- void *pKey; int nKey; /* Database key to query for */
- void *pVal; int nVal; /* Result of query */
-
- testDatasourceEntry(pData, iKey, &pKey, &nKey, 0, 0);
- rc = tdb_fetch(pDb, pKey, nKey, &pVal, &nVal);
- if( rc==0 && nVal<0 ) rc = 1;
- if( rc ) break;
-#endif
- }
- if( aParam[ST_TRANS] ) testCommit(pDb, 0, &rc);
- msFetch = testTimeGet();
- }else{
- msFetch = 0;
- }
-
- if( i==(aParam[ST_REPEAT]-1) ){
- testTimeInit();
- testClose(&pDb);
- msWrite += testTimeGet();
- }
-
- printf("%d %d %d\n", i, msWrite, msFetch);
- fflush(stdout);
- }
-
- testClose(&pDb);
- testDatasourceFree(pData);
-
- if( pLog ){
- flushPrev(pLog);
- fclose(pLog);
- }
- return rc;
-}
-
-int do_speed_tests(int nArg, char **azArg){
-
- struct DbSystem {
- const char *zLibrary;
- const char *zColor;
- } aSys[] = {
- { "sqlite3", "black" },
- { "leveldb", "blue" },
- { "lsm", "red" },
- { "lsm_mt2", "orange" },
- { "lsm_mt3", "purple" },
- { "kyotocabinet", "green" },
- {0, 0}
- };
-
- int i;
- int j;
- int rc;
- int nSleep = 0; /* ms of rest allowed between INSERT tests */
- int nRow = 0; /* Number of rows to insert into database */
- int nStep; /* Measure INSERT time after this many rows */
- int nSelStep; /* Measure SELECT time after this many rows */
- int nSelTest; /* Number of SELECTs to run for timing */
- int doReadTest = 1;
- int doWriteTest = 1;
-
- int *aTime; /* INSERT timing data */
- int *aWrite; /* Writes per nStep inserts */
- int *aSelTime; /* SELECT timing data */
- int isFirst = 1;
- int bSleep = 0;
-
- /* File to write gnuplot script to. */
- const char *zOut = "lsmtest_speed.gnuplot";
-
- u32 sys_mask = 0;
-
- testMallocUninstall(tdb_lsm_env());
-
- for(i=0; i<nArg; i++){
- struct Opt {
- const char *zOpt;
- int isSwitch;
- } aOpt[] = {
- { "sqlite3" , 0},
- { "leveldb" , 0},
- { "lsm" , 0},
- { "lsm_mt2" , 0},
- { "lsm_mt3" , 0},
- { "kyotocabinet" , 0},
- { "-rows" , 1},
- { "-sleep" , 2},
- { "-testmode" , 3},
- { "-out" , 4},
- { 0, 0}
- };
- int iSel;
-
- rc = testArgSelect(aOpt, "argument", azArg[i], &iSel);
- if( rc ) return rc;
-
- if( aOpt[iSel].isSwitch ){
- i++;
-
- if( i>=nArg ){
- testPrintError("option %s requires an argument\n", aOpt[iSel].zOpt);
- return 1;
- }
- if( aOpt[iSel].isSwitch==1 ){
- nRow = atoi(azArg[i]);
- }
- if( aOpt[iSel].isSwitch==2 ){
- nSleep = atoi(azArg[i]);
- }
- if( aOpt[iSel].isSwitch==3 ){
- struct Mode {
- const char *zMode;
- int doReadTest;
- int doWriteTest;
- } aMode[] = {{"ro", 1, 0} , {"rw", 1, 1}, {"wo", 0, 1}, {0, 0, 0}};
- int iMode;
- rc = testArgSelect(aMode, "option", azArg[i], &iMode);
- if( rc ) return rc;
- doReadTest = aMode[iMode].doReadTest;
- doWriteTest = aMode[iMode].doWriteTest;
- }
- if( aOpt[iSel].isSwitch==4 ){
- /* The "-out FILE" switch. This option is used to specify a file to
- ** write the gnuplot script to. */
- zOut = azArg[i];
- }
- }else{
- /* A db name */
- rc = testArgSelect(aOpt, "system", azArg[i], &iSel);
- if( rc ) return rc;
- sys_mask |= (1<<iSel);
- }
- }
-
- if( sys_mask==0 ) sys_mask = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
- nRow = MAX(nRow, 100000);
- nStep = nRow/100;
- nSelStep = nRow/10;
- nSelTest = (nSelStep > 100000) ? 100000 : nSelStep;
-
- aTime = malloc(sizeof(int) * ArraySize(aSys) * nRow/nStep);
- aWrite = malloc(sizeof(int) * nRow/nStep);
- aSelTime = malloc(sizeof(int) * ArraySize(aSys) * nRow/nSelStep);
-
- /* This loop collects the INSERT speed data. */
- if( doWriteTest ){
- printf("Writing output to file \"%s\".\n", zOut);
-
- for(j=0; aSys[j].zLibrary; j++){
- FILE *pLog = 0;
- TestDb *pDb; /* Database being tested */
- lsm_db *pLsm;
- int iDot = 0;
-
- if( ((1<<j)&sys_mask)==0 ) continue;
- if( bSleep && nSleep ) sqlite3_sleep(nSleep);
- bSleep = 1;
-
- testCaseBegin(&rc, 0, "speed.insert.%s", aSys[j].zLibrary);
-
- rc = tdb_open(aSys[j].zLibrary, 0, 1, &pDb);
- if( rc ) return rc;
-
- pLsm = configure_lsm_db(pDb);
-#if 0
- pLog = fopen("/tmp/speed.log", "w");
- tdb_lsm_write_hook(pDb, do_speed_write_hook2, (void *)pLog);
-#endif
-
- testTimeInit();
- for(i=0; i<nRow; i+=nStep){
- int iStep;
- int nWrite1 = 0, nWrite2 = 0;
- testCaseProgress(i, nRow, testCaseNDot(), &iDot);
- if( pLsm ) lsm_info(pLsm, LSM_INFO_NWRITE, &nWrite1);
- for(iStep=0; iStep<nStep; iStep++){
- u32 aKey[4]; /* 16-byte key */
- u32 aVal[25]; /* 100 byte value */
- testPrngArray(i+iStep, aKey, ArraySize(aKey));
- testPrngArray(i+iStep, aVal, ArraySize(aVal));
- rc = tdb_write(pDb, aKey, sizeof(aKey), aVal, sizeof(aVal));
- }
- aTime[(j*nRow+i)/nStep] = testTimeGet();
- if( pLsm ) lsm_info(pLsm, LSM_INFO_NWRITE, &nWrite2);
- aWrite[i/nStep] = nWrite2 - nWrite1;
- }
-
- tdb_close(pDb);
- if( pLog ) fclose(pLog);
- testCaseFinish(rc);
- }
- }
-
- /* This loop collects the SELECT speed data. */
- if( doReadTest ){
- for(j=0; aSys[j].zLibrary; j++){
- int iDot = 0;
- TestDb *pDb; /* Database being tested */
-
- if( ((1<<j)&sys_mask)==0 ) continue;
- if( bSleep && nSleep ) sqlite3_sleep(nSleep);
- bSleep = 1;
-
- testCaseBegin(&rc, 0, "speed.select.%s", aSys[j].zLibrary);
-
- if( doWriteTest ){
- rc = tdb_open(aSys[j].zLibrary, 0, 1, &pDb);
- if( rc ) return rc;
- configure_lsm_db(pDb);
-
- for(i=0; i<nRow; i+=nSelStep){
- int iStep;
- int iSel;
- testCaseProgress(i, nRow, testCaseNDot(), &iDot);
- for(iStep=0; iStep<nSelStep; iStep++){
- u32 aKey[4]; /* 16-byte key */
- u32 aVal[25]; /* 100 byte value */
- testPrngArray(i+iStep, aKey, ArraySize(aKey));
- testPrngArray(i+iStep, aVal, ArraySize(aVal));
- rc = tdb_write(pDb, aKey, sizeof(aKey), aVal, sizeof(aVal));
- }
-
- testTimeInit();
- for(iSel=0; iSel<nSelTest; iSel++){
- void *pDummy;
- int nDummy;
- u32 iKey;
- u32 aKey[4]; /* 16-byte key */
-
- iKey = testPrngValue(iSel) % (i+nSelStep);
- testPrngArray(iKey, aKey, ArraySize(aKey));
- rc = tdb_fetch(pDb, aKey, sizeof(aKey), &pDummy, &nDummy);
- }
- aSelTime[(j*nRow+i)/nSelStep] = testTimeGet();
- tdb_fetch(pDb, 0, 0, 0, 0);
- }
- }else{
- int t;
- int iSel;
-
- rc = tdb_open(aSys[j].zLibrary, 0, 0, &pDb);
- configure_lsm_db(pDb);
-
- testTimeInit();
- for(iSel=0; rc==LSM_OK && iSel<nSelTest; iSel++){
- void *pDummy;
- int nDummy;
- u32 iKey;
- u32 aKey[4]; /* 16-byte key */
-#ifndef NDEBUG
- u32 aVal[25]; /* 100 byte value */
-#endif
-
- testCaseProgress(iSel, nSelTest, testCaseNDot(), &iDot);
-
- iKey = testPrngValue(iSel) % nRow;
- testPrngArray(iKey, aKey, ArraySize(aKey));
- rc = tdb_fetch(pDb, aKey, sizeof(aKey), &pDummy, &nDummy);
-
-#ifndef NDEBUG
- testPrngArray(iKey, aVal, ArraySize(aVal));
- assert( nDummy==100 && memcmp(aVal, pDummy, 100)==0 );
-#endif
- }
- if( rc!=LSM_OK ) return rc;
-
- t = testTimeGet();
- tdb_fetch(pDb, 0, 0, 0, 0);
-
- printf("%s: %d selects/second\n",
- aSys[j].zLibrary, (int)((double)nSelTest*1000.0/t)
- );
- }
-
- tdb_close(pDb);
- testCaseFinish(rc);
- }
- }
-
-
- if( doWriteTest ){
- FILE *pOut = fopen(zOut, "w");
- if( !pOut ){
- printf("fopen(\"%s\", \"w\"): %s\n", zOut, strerror(errno));
- return 1;
- }
-
- fprintf(pOut, "set xlabel \"Rows Inserted\"\n");
- fprintf(pOut, "set ylabel \"Inserts per second\"\n");
- if( doReadTest ){
- fprintf(pOut, "set y2label \"Selects per second\"\n");
- }else if( sys_mask==(1<<2) ){
- fprintf(pOut, "set y2label \"Page writes per insert\"\n");
- }
- fprintf(pOut, "set yrange [0:*]\n");
- fprintf(pOut, "set y2range [0:*]\n");
- fprintf(pOut, "set xrange [%d:*]\n", MAX(nStep, nRow/20) );
- fprintf(pOut, "set ytics nomirror\n");
- fprintf(pOut, "set y2tics nomirror\n");
- fprintf(pOut, "set key box lw 0.01\n");
- fprintf(pOut, "plot ");
-
- for(j=0; aSys[j].zLibrary; j++){
- if( (1<<j)&sys_mask ){
- const char *zLib = aSys[j].zLibrary;
- fprintf(pOut, "%s\"-\" ti \"%s INSERT\" with lines lc rgb \"%s\" ",
- (isFirst?"":", "), zLib, aSys[j].zColor
- );
- if( doReadTest ){
- fprintf(pOut, ", \"-\" ti \"%s SELECT\" "
- "axis x1y2 with points lw 3 lc rgb \"%s\""
- , zLib, aSys[j].zColor
- );
- }
- isFirst = 0;
- }
- }
-
- assert( strcmp(aSys[2].zLibrary, "lsm")==0 );
- if( sys_mask==(1<<2) && !doReadTest ){
- fprintf(pOut, ", \"-\" ti \"lsm pages written\" "
- "axis x1y2 with boxes lw 1 lc rgb \"grey\""
- );
- }
-
- fprintf(pOut, "\n");
-
- for(j=0; aSys[j].zLibrary; j++){
- if( ((1<<j)&sys_mask)==0 ) continue;
- fprintf(pOut, "# Rows Inserts per second\n");
- for(i=0; i<nRow; i+=nStep){
- int iTime = aTime[(j*nRow+i)/nStep];
- int ips = (int)((i+nStep)*1000.0 / (double)iTime);
- fprintf(pOut, "%d %d\n", i+nStep, ips);
- }
- fprintf(pOut, "end\n");
-
- if( doReadTest ){
- fprintf(pOut, "# Rows Selects per second\n");
- for(i=0; i<nRow; i+=nSelStep){
- int sps = (int)(nSelTest*1000.0/(double)aSelTime[(j*nRow+i)/nSelStep]);
- fprintf(pOut, "%d %d\n", i+nSelStep, sps);
- }
- fprintf(pOut, "end\n");
- }else if( sys_mask==(1<<2) ){
- for(i=0; i<(nRow/nStep); i++){
- fprintf(pOut, "%d %f\n", i*nStep, (double)aWrite[i] / (double)nStep);
- }
- fprintf(pOut, "end\n");
- }
- }
-
- fprintf(pOut, "pause -1\n");
- fclose(pOut);
- }
-
- free(aTime);
- free(aSelTime);
- free(aWrite);
- testMallocInstall(tdb_lsm_env());
- return 0;
-}
-
-/*
-** Usage: lsmtest random ?N?
-**
-** This command prints a sequence of zero or more numbers from the PRNG
-** system to stdout. If the "N" argument is missing, values the first 10
-** values (i=0, i=1, ... i=9) are printed. Otherwise, the first N.
-**
-** This was added to verify that the PRNG values do not change between
-** runs of the lsmtest program.
-*/
-int do_random_tests(int nArg, char **azArg){
- int i;
- int nRand;
- if( nArg==0 ){
- nRand = 10;
- }else if( nArg==1 ){
- nRand = atoi(azArg[0]);
- }else{
- testPrintError("Usage: random ?N?\n");
- return -1;
- }
- for(i=0; i<nRand; i++){
- printf("0x%x\n", testPrngValue(i));
- }
- return 0;
-}
-
-static int testFormatSize(char *aBuf, int nBuf, i64 nByte){
- int res;
- if( nByte<(1<<10) ){
- res = snprintf(aBuf, nBuf, "%d byte", (int)nByte);
- }else if( nByte<(1<<20) ){
- res = snprintf(aBuf, nBuf, "%dK", (int)(nByte/(1<<10)));
- }else{
- res = snprintf(aBuf, nBuf, "%dM", (int)(nByte/(1<<20)));
- }
- return res;
-}
-
-static i64 testReadSize(char *z){
- int n = strlen(z);
- char c = z[n-1];
- i64 nMul = 1;
-
- switch( c ){
- case 'g': case 'G':
- nMul = (1<<30);
- break;
-
- case 'm': case 'M':
- nMul = (1<<20);
- break;
-
- case 'k': case 'K':
- nMul = (1<<10);
- break;
-
- default:
- nMul = 1;
- }
-
- return nMul * (i64)atoi(z);
-}
-
-/*
-** Usage: lsmtest writespeed FILESIZE BLOCKSIZE SYNCSIZE
-*/
-static int do_writer_test(int nArg, char **azArg){
- int nBlock;
- int nSize;
- int i;
- int fd;
- int ms;
- char aFilesize[32];
- char aBlockSize[32];
-
- char *aPage;
- int *aOrder;
- int nSync;
-
- i64 filesize;
- i64 blocksize;
- i64 syncsize;
- int nPage = 4096;
-
- /* How long to sleep before running a trial (in ms). */
-#if 0
- const int nSleep = 10000;
-#endif
- const int nSleep = 0;
-
- if( nArg!=3 ){
- testPrintUsage("FILESIZE BLOCKSIZE SYNCSIZE");
- return -1;
- }
-
- filesize = testReadSize(azArg[0]);
- blocksize = testReadSize(azArg[1]);
- syncsize = testReadSize(azArg[2]);
-
- nBlock = (int)(filesize / blocksize);
- nSize = (int)blocksize;
- nSync = (int)(syncsize / blocksize);
-
- aPage = (char *)malloc(4096);
- aOrder = (int *)malloc(nBlock * sizeof(int));
- for(i=0; i<nBlock; i++) aOrder[i] = i;
- for(i=0; i<(nBlock*25); i++){
- int tmp;
- u32 a = testPrngValue(i);
- u32 b = testPrngValue(a);
- a = a % nBlock;
- b = b % nBlock;
- tmp = aOrder[a];
- aOrder[a] = aOrder[b];
- aOrder[b] = tmp;
- }
-
- testFormatSize(aFilesize, sizeof(aFilesize), (i64)nBlock * (i64)nSize);
- testFormatSize(aBlockSize, sizeof(aFilesize), nSize);
-
- printf("Testing writing a %s file using %s blocks. ", aFilesize, aBlockSize);
- if( nSync==1 ){
- printf("Sync after each block.\n");
- }else{
- printf("Sync after each %d blocks.\n", nSync);
- }
-
- printf("Preparing file... ");
- fflush(stdout);
- unlink("writer.out");
- fd = open("writer.out", O_RDWR|O_CREAT|_O_BINARY, 0664);
- if( fd<0 ){
- testPrintError("open(): %d - %s\n", errno, strerror(errno));
- return -1;
- }
- testTimeInit();
- for(i=0; i<nBlock; i++){
- int iPg;
- memset(aPage, i&0xFF, nPage);
- for(iPg=0; iPg<(nSize/nPage); iPg++){
- write(fd, aPage, nPage);
- }
- }
- fsync(fd);
- printf("ok (%d ms)\n", testTimeGet());
-
- for(i=0; i<5; i++){
- int j;
-
- sqlite3_sleep(nSleep);
- printf("Now writing sequentially... ");
- fflush(stdout);
-
- lseek(fd, 0, SEEK_SET);
- testTimeInit();
- for(j=0; j<nBlock; j++){
- int iPg;
- if( ((j+1)%nSync)==0 ) fdatasync(fd);
- memset(aPage, j&0xFF, nPage);
- for(iPg=0; iPg<(nSize/nPage); iPg++){
- write(fd, aPage, nPage);
- }
- }
- fdatasync(fd);
- ms = testTimeGet();
- printf("%d ms\n", ms);
- sqlite3_sleep(nSleep);
- printf("Now in an arbitrary order... ");
-
- fflush(stdout);
- testTimeInit();
- for(j=0; j<nBlock; j++){
- int iPg;
- if( ((j+1)%nSync)==0 ) fdatasync(fd);
- lseek(fd, aOrder[j]*nSize, SEEK_SET);
- memset(aPage, j&0xFF, nPage);
- for(iPg=0; iPg<(nSize/nPage); iPg++){
- write(fd, aPage, nPage);
- }
- }
- fdatasync(fd);
- ms = testTimeGet();
- printf("%d ms\n", ms);
- }
-
- close(fd);
- free(aPage);
- free(aOrder);
-
- return 0;
-}
-
-static void do_insert_work_hook(lsm_db *db, void *p){
- char *z = 0;
- lsm_info(db, LSM_INFO_DB_STRUCTURE, &z);
- if( z ){
- printf("%s\n", z);
- fflush(stdout);
- lsm_free(lsm_get_env(db), z);
- }
-
- unused_parameter(p);
-}
-
-typedef struct InsertWriteHook InsertWriteHook;
-struct InsertWriteHook {
- FILE *pOut;
- int bLog;
- i64 iOff;
- int nData;
-};
-
-static void flushHook(InsertWriteHook *pHook){
- if( pHook->nData ){
- fprintf(pHook->pOut, "write %s %d %d\n",
- (pHook->bLog ? "log" : "db"), (int)pHook->iOff, pHook->nData
- );
- pHook->nData = 0;
- fflush(pHook->pOut);
- }
-}
-
-static void do_insert_write_hook(
- void *pCtx,
- int bLog,
- i64 iOff,
- int nData,
- int nUs
-){
- InsertWriteHook *pHook = (InsertWriteHook *)pCtx;
- if( bLog ) return;
-
- if( nData==0 ){
- flushHook(pHook);
- fprintf(pHook->pOut, "sync %s\n", (bLog ? "log" : "db"));
- }else if( pHook->nData
- && bLog==pHook->bLog
- && iOff==(pHook->iOff+pHook->nData)
- ){
- pHook->nData += nData;
- }else{
- flushHook(pHook);
- pHook->bLog = bLog;
- pHook->iOff = iOff;
- pHook->nData = nData;
- }
-}
-
-static int do_replay(int nArg, char **azArg){
- char aBuf[4096];
- FILE *pInput;
- FILE *pClose = 0;
- const char *zDb;
-
- lsm_env *pEnv;
- lsm_file *pOut;
- int rc;
-
- if( nArg!=2 ){
- testPrintError("Usage: replay WRITELOG FILE\n");
- return 1;
- }
-
- if( strcmp(azArg[0], "-")==0 ){
- pInput = stdin;
- }else{
- pClose = pInput = fopen(azArg[0], "r");
- }
- zDb = azArg[1];
- pEnv = tdb_lsm_env();
- rc = pEnv->xOpen(pEnv, zDb, 0, &pOut);
- if( rc!=LSM_OK ) return rc;
-
- while( feof(pInput)==0 ){
- char zLine[80];
- fgets(zLine, sizeof(zLine)-1, pInput);
- zLine[sizeof(zLine)-1] = '\0';
-
- if( 0==memcmp("sync db", zLine, 7) ){
- rc = pEnv->xSync(pOut);
- if( rc!=0 ) break;
- }else{
- int iOff;
- int nData;
- int nMatch;
- nMatch = sscanf(zLine, "write db %d %d", &iOff, &nData);
- if( nMatch==2 ){
- int i;
- for(i=0; i<nData; i+=sizeof(aBuf)){
- memset(aBuf, i&0xFF, sizeof(aBuf));
- rc = pEnv->xWrite(pOut, iOff+i, aBuf, sizeof(aBuf));
- if( rc!=0 ) break;
- }
- }
- }
- }
- if( pClose ) fclose(pClose);
- pEnv->xClose(pOut);
-
- return rc;
-}
-
-static int do_insert(int nArg, char **azArg){
- const char *zDb = "lsm";
- TestDb *pDb = 0;
- int i;
- int rc;
- const int nRow = 1 * 1000 * 1000;
-
- DatasourceDefn defn = { TEST_DATASOURCE_RANDOM, 8, 15, 80, 150 };
- Datasource *pData = 0;
-
- if( nArg>1 ){
- testPrintError("Usage: insert ?DATABASE?\n");
- return 1;
- }
- if( nArg==1 ){ zDb = azArg[0]; }
-
- testMallocUninstall(tdb_lsm_env());
- for(i=0; zDb[i] && zDb[i]!='='; i++);
- if( zDb[i] ){
- rc = tdb_lsm_open(zDb, "testdb.lsm", 1, &pDb);
- }else{
- rc = tdb_open(zDb, 0, 1, &pDb);
- }
-
- if( rc!=0 ){
- testPrintError("Error opening db \"%s\": %d\n", zDb, rc);
- }else{
- InsertWriteHook hook;
- memset(&hook, 0, sizeof(hook));
- hook.pOut = fopen("writelog.txt", "w");
-
- pData = testDatasourceNew(&defn);
- tdb_lsm_config_work_hook(pDb, do_insert_work_hook, 0);
- tdb_lsm_write_hook(pDb, do_insert_write_hook, (void *)&hook);
-
- if( rc==0 ){
- for(i=0; i<nRow; i++){
- void *pKey; int nKey; /* Database key to insert */
- void *pVal; int nVal; /* Database value to insert */
- testDatasourceEntry(pData, i, &pKey, &nKey, &pVal, &nVal);
- tdb_write(pDb, pKey, nKey, pVal, nVal);
- }
- }
-
- testDatasourceFree(pData);
- tdb_close(pDb);
- flushHook(&hook);
- fclose(hook.pOut);
- }
- testMallocInstall(tdb_lsm_env());
-
- return rc;
-}
-
-static int st_do_show(int a, char **b) { return do_show(a, b); }
-static int st_do_work(int a, char **b) { return do_work(a, b); }
-static int st_do_io(int a, char **b) { return do_io(a, b); }
-
-#ifdef __linux__
-#include <sys/time.h>
-#include <sys/resource.h>
-
-static void lsmtest_rusage_report(void){
- struct rusage r;
- memset(&r, 0, sizeof(r));
-
- getrusage(RUSAGE_SELF, &r);
- printf("# getrusage: { ru_maxrss %d ru_oublock %d ru_inblock %d }\n",
- (int)r.ru_maxrss, (int)r.ru_oublock, (int)r.ru_inblock
- );
-}
-#else
-static void lsmtest_rusage_report(void){
- /* no-op */
-}
-#endif
-
-int main(int argc, char **argv){
- struct TestFunc {
- const char *zName;
- int bRusageReport;
- int (*xFunc)(int, char **);
- } aTest[] = {
- {"random", 1, do_random_tests},
- {"writespeed", 1, do_writer_test},
- {"io", 1, st_do_io},
-
- {"insert", 1, do_insert},
- {"replay", 1, do_replay},
-
- {"speed", 1, do_speed_tests},
- {"speed2", 1, do_speed_test2},
- {"show", 0, st_do_show},
- {"work", 1, st_do_work},
- {"test", 1, do_test},
-
- {0, 0}
- };
- int rc; /* Return Code */
- int iFunc; /* Index into aTest[] */
-
- int nLeakAlloc = 0; /* Allocations leaked by lsm */
- int nLeakByte = 0; /* Bytes leaked by lsm */
-
-#ifdef LSM_DEBUG_MEM
- FILE *pReport = 0; /* lsm malloc() report file */
- const char *zReport = "malloc.txt generated";
-#else
- const char *zReport = "malloc.txt NOT generated";
-#endif
-
- testMallocInstall(tdb_lsm_env());
-
- if( argc<2 ){
- testPrintError("Usage: %s sub-command ?args...?\n", argv[0]);
- return -1;
- }
-
- /* Initialize error reporting */
- testErrorInit(argc, argv);
-
- /* Initialize PRNG system */
- testPrngInit();
-
- rc = testArgSelect(aTest, "sub-command", argv[1], &iFunc);
- if( rc==0 ){
- rc = aTest[iFunc].xFunc(argc-2, &argv[2]);
- }
-
-#ifdef LSM_DEBUG_MEM
- pReport = fopen("malloc.txt", "w");
- testMallocCheck(tdb_lsm_env(), &nLeakAlloc, &nLeakByte, pReport);
- fclose(pReport);
-#else
- testMallocCheck(tdb_lsm_env(), &nLeakAlloc, &nLeakByte, 0);
-#endif
-
- if( nLeakAlloc ){
- testPrintError("Leaked %d bytes in %d allocations (%s)\n",
- nLeakByte, nLeakAlloc, zReport
- );
- if( rc==0 ) rc = -1;
- }
- testMallocUninstall(tdb_lsm_env());
-
- if( aTest[iFunc].bRusageReport ){
- lsmtest_rusage_report();
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_mem.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_mem.c
deleted file mode 100644
index 4c35e849f25..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_mem.c
+++ /dev/null
@@ -1,409 +0,0 @@
-
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-
-#define ArraySize(x) ((int)(sizeof(x) / sizeof((x)[0])))
-
-#define MIN(x,y) ((x)<(y) ? (x) : (y))
-
-typedef unsigned int u32;
-typedef unsigned char u8;
-typedef long long int i64;
-typedef unsigned long long int u64;
-
-#if defined(__GLIBC__) && defined(LSM_DEBUG_MEM)
- extern int backtrace(void**,int);
- extern void backtrace_symbols_fd(void*const*,int,int);
-# define TM_BACKTRACE 12
-#else
-# define backtrace(A,B) 1
-# define backtrace_symbols_fd(A,B,C)
-#endif
-
-
-typedef struct TmBlockHdr TmBlockHdr;
-typedef struct TmAgg TmAgg;
-typedef struct TmGlobal TmGlobal;
-
-struct TmGlobal {
- /* Linked list of all currently outstanding allocations. And a table of
- ** all allocations, past and present, indexed by backtrace() info. */
- TmBlockHdr *pFirst;
-#ifdef TM_BACKTRACE
- TmAgg *aHash[10000];
-#endif
-
- /* Underlying malloc/realloc/free functions */
- void *(*xMalloc)(int); /* underlying malloc(3) function */
- void *(*xRealloc)(void *, int); /* underlying realloc(3) function */
- void (*xFree)(void *); /* underlying free(3) function */
-
- /* Mutex to protect pFirst and aHash */
- void (*xEnterMutex)(TmGlobal*); /* Call this to enter the mutex */
- void (*xLeaveMutex)(TmGlobal*); /* Call this to leave mutex */
- void (*xDelMutex)(TmGlobal*); /* Call this to delete mutex */
- void *pMutex; /* Mutex handle */
-
- void *(*xSaveMalloc)(void *, size_t);
- void *(*xSaveRealloc)(void *, void *, size_t);
- void (*xSaveFree)(void *, void *);
-
- /* OOM injection scheduling. If nCountdown is greater than zero when a
- ** malloc attempt is made, it is decremented. If this means nCountdown
- ** transitions from 1 to 0, then the allocation fails. If bPersist is true
- ** when this happens, nCountdown is then incremented back to 1 (so that the
- ** next attempt fails too).
- */
- int nCountdown;
- int bPersist;
- int bEnable;
- void (*xHook)(void *);
- void *pHookCtx;
-};
-
-struct TmBlockHdr {
- TmBlockHdr *pNext;
- TmBlockHdr *pPrev;
- int nByte;
-#ifdef TM_BACKTRACE
- TmAgg *pAgg;
-#endif
- u32 iForeGuard;
-};
-
-#ifdef TM_BACKTRACE
-struct TmAgg {
- int nAlloc; /* Number of allocations at this path */
- int nByte; /* Total number of bytes allocated */
- int nOutAlloc; /* Number of outstanding allocations */
- int nOutByte; /* Number of outstanding bytes */
- void *aFrame[TM_BACKTRACE]; /* backtrace() output */
- TmAgg *pNext; /* Next object in hash-table collision */
-};
-#endif
-
-#define FOREGUARD 0x80F5E153
-#define REARGUARD 0xE4676B53
-static const u32 rearguard = REARGUARD;
-
-#define ROUND8(x) (((x)+7)&~7)
-
-#define BLOCK_HDR_SIZE (ROUND8( sizeof(TmBlockHdr) ))
-
-static void lsmtest_oom_error(void){
- static int nErr = 0;
- nErr++;
-}
-
-static void tmEnterMutex(TmGlobal *pTm){
- pTm->xEnterMutex(pTm);
-}
-static void tmLeaveMutex(TmGlobal *pTm){
- pTm->xLeaveMutex(pTm);
-}
-
-static void *tmMalloc(TmGlobal *pTm, int nByte){
- TmBlockHdr *pNew; /* New allocation header block */
- u8 *pUser; /* Return value */
- int nReq; /* Total number of bytes requested */
-
- assert( sizeof(rearguard)==4 );
- nReq = BLOCK_HDR_SIZE + nByte + 4;
- pNew = (TmBlockHdr *)pTm->xMalloc(nReq);
- memset(pNew, 0, sizeof(TmBlockHdr));
-
- tmEnterMutex(pTm);
- assert( pTm->nCountdown>=0 );
- assert( pTm->bPersist==0 || pTm->bPersist==1 );
-
- if( pTm->bEnable && pTm->nCountdown==1 ){
- /* Simulate an OOM error. */
- lsmtest_oom_error();
- pTm->xFree(pNew);
- pTm->nCountdown = pTm->bPersist;
- if( pTm->xHook ) pTm->xHook(pTm->pHookCtx);
- pUser = 0;
- }else{
- if( pTm->bEnable && pTm->nCountdown ) pTm->nCountdown--;
-
- pNew->iForeGuard = FOREGUARD;
- pNew->nByte = nByte;
- pNew->pNext = pTm->pFirst;
-
- if( pTm->pFirst ){
- pTm->pFirst->pPrev = pNew;
- }
- pTm->pFirst = pNew;
-
- pUser = &((u8 *)pNew)[BLOCK_HDR_SIZE];
- memset(pUser, 0x56, nByte);
- memcpy(&pUser[nByte], &rearguard, 4);
-
-#ifdef TM_BACKTRACE
- {
- TmAgg *pAgg;
- int i;
- u32 iHash = 0;
- void *aFrame[TM_BACKTRACE];
- memset(aFrame, 0, sizeof(aFrame));
- backtrace(aFrame, TM_BACKTRACE);
-
- for(i=0; i<ArraySize(aFrame); i++){
- iHash += (u64)(aFrame[i]) + (iHash<<3);
- }
- iHash = iHash % ArraySize(pTm->aHash);
-
- for(pAgg=pTm->aHash[iHash]; pAgg; pAgg=pAgg->pNext){
- if( memcmp(pAgg->aFrame, aFrame, sizeof(aFrame))==0 ) break;
- }
- if( !pAgg ){
- pAgg = (TmAgg *)pTm->xMalloc(sizeof(TmAgg));
- memset(pAgg, 0, sizeof(TmAgg));
- memcpy(pAgg->aFrame, aFrame, sizeof(aFrame));
- pAgg->pNext = pTm->aHash[iHash];
- pTm->aHash[iHash] = pAgg;
- }
- pAgg->nAlloc++;
- pAgg->nByte += nByte;
- pAgg->nOutAlloc++;
- pAgg->nOutByte += nByte;
- pNew->pAgg = pAgg;
- }
-#endif
- }
-
- tmLeaveMutex(pTm);
- return pUser;
-}
-
-static void tmFree(TmGlobal *pTm, void *p){
- if( p ){
- TmBlockHdr *pHdr;
- u8 *pUser = (u8 *)p;
-
- tmEnterMutex(pTm);
- pHdr = (TmBlockHdr *)(pUser - BLOCK_HDR_SIZE);
- assert( pHdr->iForeGuard==FOREGUARD );
- assert( 0==memcmp(&pUser[pHdr->nByte], &rearguard, 4) );
-
- if( pHdr->pPrev ){
- assert( pHdr->pPrev->pNext==pHdr );
- pHdr->pPrev->pNext = pHdr->pNext;
- }else{
- assert( pHdr==pTm->pFirst );
- pTm->pFirst = pHdr->pNext;
- }
- if( pHdr->pNext ){
- assert( pHdr->pNext->pPrev==pHdr );
- pHdr->pNext->pPrev = pHdr->pPrev;
- }
-
-#ifdef TM_BACKTRACE
- pHdr->pAgg->nOutAlloc--;
- pHdr->pAgg->nOutByte -= pHdr->nByte;
-#endif
-
- tmLeaveMutex(pTm);
- memset(pUser, 0x58, pHdr->nByte);
- memset(pHdr, 0x57, sizeof(TmBlockHdr));
- pTm->xFree(pHdr);
- }
-}
-
-static void *tmRealloc(TmGlobal *pTm, void *p, int nByte){
- void *pNew;
-
- pNew = tmMalloc(pTm, nByte);
- if( pNew && p ){
- TmBlockHdr *pHdr;
- u8 *pUser = (u8 *)p;
- pHdr = (TmBlockHdr *)(pUser - BLOCK_HDR_SIZE);
- memcpy(pNew, p, MIN(nByte, pHdr->nByte));
- tmFree(pTm, p);
- }
- return pNew;
-}
-
-static void tmMallocOom(
- TmGlobal *pTm,
- int nCountdown,
- int bPersist,
- void (*xHook)(void *),
- void *pHookCtx
-){
- assert( nCountdown>=0 );
- assert( bPersist==0 || bPersist==1 );
- pTm->nCountdown = nCountdown;
- pTm->bPersist = bPersist;
- pTm->xHook = xHook;
- pTm->pHookCtx = pHookCtx;
- pTm->bEnable = 1;
-}
-
-static void tmMallocOomEnable(
- TmGlobal *pTm,
- int bEnable
-){
- pTm->bEnable = bEnable;
-}
-
-static void tmMallocCheck(
- TmGlobal *pTm,
- int *pnLeakAlloc,
- int *pnLeakByte,
- FILE *pFile
-){
- TmBlockHdr *pHdr;
- int nLeak = 0;
- int nByte = 0;
-
- if( pTm==0 ) return;
-
- for(pHdr=pTm->pFirst; pHdr; pHdr=pHdr->pNext){
- nLeak++;
- nByte += pHdr->nByte;
- }
- if( pnLeakAlloc ) *pnLeakAlloc = nLeak;
- if( pnLeakByte ) *pnLeakByte = nByte;
-
-#ifdef TM_BACKTRACE
- if( pFile ){
- int i;
- fprintf(pFile, "LEAKS\n");
- for(i=0; i<ArraySize(pTm->aHash); i++){
- TmAgg *pAgg;
- for(pAgg=pTm->aHash[i]; pAgg; pAgg=pAgg->pNext){
- if( pAgg->nOutAlloc ){
- int j;
- fprintf(pFile, "%d %d ", pAgg->nOutByte, pAgg->nOutAlloc);
- for(j=0; j<TM_BACKTRACE; j++){
- fprintf(pFile, "%p ", pAgg->aFrame[j]);
- }
- fprintf(pFile, "\n");
- }
- }
- }
- fprintf(pFile, "\nALLOCATIONS\n");
- for(i=0; i<ArraySize(pTm->aHash); i++){
- TmAgg *pAgg;
- for(pAgg=pTm->aHash[i]; pAgg; pAgg=pAgg->pNext){
- int j;
- fprintf(pFile, "%d %d ", pAgg->nByte, pAgg->nAlloc);
- for(j=0; j<TM_BACKTRACE; j++) fprintf(pFile, "%p ", pAgg->aFrame[j]);
- fprintf(pFile, "\n");
- }
- }
- }
-#else
- (void)pFile;
-#endif
-}
-
-
-#include "lsm.h"
-#include "stdlib.h"
-
-typedef struct LsmMutex LsmMutex;
-struct LsmMutex {
- lsm_env *pEnv;
- lsm_mutex *pMutex;
-};
-
-static void tmLsmMutexEnter(TmGlobal *pTm){
- LsmMutex *p = (LsmMutex *)pTm->pMutex;
- p->pEnv->xMutexEnter(p->pMutex);
-}
-static void tmLsmMutexLeave(TmGlobal *pTm){
- LsmMutex *p = (LsmMutex *)(pTm->pMutex);
- p->pEnv->xMutexLeave(p->pMutex);
-}
-static void tmLsmMutexDel(TmGlobal *pTm){
- LsmMutex *p = (LsmMutex *)pTm->pMutex;
- pTm->xFree(p);
-}
-static void *tmLsmMalloc(int n){ return malloc(n); }
-static void tmLsmFree(void *ptr){ free(ptr); }
-static void *tmLsmRealloc(void *ptr, int n){ return realloc(ptr, n); }
-
-static void *tmLsmEnvMalloc(lsm_env *p, size_t n){
- return tmMalloc((TmGlobal *)(p->pMemCtx), n);
-}
-static void tmLsmEnvFree(lsm_env *p, void *ptr){
- tmFree((TmGlobal *)(p->pMemCtx), ptr);
-}
-static void *tmLsmEnvRealloc(lsm_env *p, void *ptr, size_t n){
- return tmRealloc((TmGlobal *)(p->pMemCtx), ptr, n);
-}
-
-void testMallocInstall(lsm_env *pEnv){
- TmGlobal *pGlobal;
- LsmMutex *pMutex;
- assert( pEnv->pMemCtx==0 );
-
- /* Allocate and populate a TmGlobal structure. */
- pGlobal = (TmGlobal *)tmLsmMalloc(sizeof(TmGlobal));
- memset(pGlobal, 0, sizeof(TmGlobal));
- pGlobal->xMalloc = tmLsmMalloc;
- pGlobal->xRealloc = tmLsmRealloc;
- pGlobal->xFree = tmLsmFree;
- pMutex = (LsmMutex *)pGlobal->xMalloc(sizeof(LsmMutex));
- pMutex->pEnv = pEnv;
- pEnv->xMutexStatic(pEnv, LSM_MUTEX_HEAP, &pMutex->pMutex);
- pGlobal->xEnterMutex = tmLsmMutexEnter;
- pGlobal->xLeaveMutex = tmLsmMutexLeave;
- pGlobal->xDelMutex = tmLsmMutexDel;
- pGlobal->pMutex = (void *)pMutex;
-
- pGlobal->xSaveMalloc = pEnv->xMalloc;
- pGlobal->xSaveRealloc = pEnv->xRealloc;
- pGlobal->xSaveFree = pEnv->xFree;
-
- /* Set up pEnv to the use the new TmGlobal */
- pEnv->pMemCtx = (void *)pGlobal;
- pEnv->xMalloc = tmLsmEnvMalloc;
- pEnv->xRealloc = tmLsmEnvRealloc;
- pEnv->xFree = tmLsmEnvFree;
-}
-
-void testMallocUninstall(lsm_env *pEnv){
- TmGlobal *p = (TmGlobal *)pEnv->pMemCtx;
- pEnv->pMemCtx = 0;
- if( p ){
- pEnv->xMalloc = p->xSaveMalloc;
- pEnv->xRealloc = p->xSaveRealloc;
- pEnv->xFree = p->xSaveFree;
- p->xDelMutex(p);
- tmLsmFree(p);
- }
-}
-
-void testMallocCheck(
- lsm_env *pEnv,
- int *pnLeakAlloc,
- int *pnLeakByte,
- FILE *pFile
-){
- if( pEnv->pMemCtx==0 ){
- *pnLeakAlloc = 0;
- *pnLeakByte = 0;
- }else{
- tmMallocCheck((TmGlobal *)(pEnv->pMemCtx), pnLeakAlloc, pnLeakByte, pFile);
- }
-}
-
-void testMallocOom(
- lsm_env *pEnv,
- int nCountdown,
- int bPersist,
- void (*xHook)(void *),
- void *pHookCtx
-){
- TmGlobal *pTm = (TmGlobal *)(pEnv->pMemCtx);
- tmMallocOom(pTm, nCountdown, bPersist, xHook, pHookCtx);
-}
-
-void testMallocOomEnable(lsm_env *pEnv, int bEnable){
- TmGlobal *pTm = (TmGlobal *)(pEnv->pMemCtx);
- tmMallocOomEnable(pTm, bEnable);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb.c
deleted file mode 100644
index 9c4f9df8a44..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb.c
+++ /dev/null
@@ -1,846 +0,0 @@
-
-/*
-** This program attempts to test the correctness of some facets of the
-** LSM database library. Specifically, that the contents of the database
-** are maintained correctly during a series of inserts and deletes.
-*/
-
-
-#include "lsmtest_tdb.h"
-#include "lsm.h"
-
-#include "lsmtest.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#ifndef _WIN32
-# include <unistd.h>
-#endif
-#include <stdio.h>
-
-
-typedef struct SqlDb SqlDb;
-
-static int error_transaction_function(TestDb *p, int iLevel){
- unused_parameter(p);
- unused_parameter(iLevel);
- return -1;
-}
-
-
-/*************************************************************************
-** Begin wrapper for LevelDB.
-*/
-#ifdef HAVE_LEVELDB
-
-#include <leveldb/c.h>
-
-typedef struct LevelDb LevelDb;
-struct LevelDb {
- TestDb base;
- leveldb_t *db;
- leveldb_options_t *pOpt;
- leveldb_writeoptions_t *pWriteOpt;
- leveldb_readoptions_t *pReadOpt;
-
- char *pVal;
-};
-
-static int test_leveldb_close(TestDb *pTestDb){
- LevelDb *pDb = (LevelDb *)pTestDb;
-
- leveldb_close(pDb->db);
- leveldb_writeoptions_destroy(pDb->pWriteOpt);
- leveldb_readoptions_destroy(pDb->pReadOpt);
- leveldb_options_destroy(pDb->pOpt);
- free(pDb->pVal);
- free(pDb);
-
- return 0;
-}
-
-static int test_leveldb_write(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void *pVal,
- int nVal
-){
- LevelDb *pDb = (LevelDb *)pTestDb;
- char *zErr = 0;
- leveldb_put(pDb->db, pDb->pWriteOpt, pKey, nKey, pVal, nVal, &zErr);
- return (zErr!=0);
-}
-
-static int test_leveldb_delete(TestDb *pTestDb, void *pKey, int nKey){
- LevelDb *pDb = (LevelDb *)pTestDb;
- char *zErr = 0;
- leveldb_delete(pDb->db, pDb->pWriteOpt, pKey, nKey, &zErr);
- return (zErr!=0);
-}
-
-static int test_leveldb_fetch(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void **ppVal,
- int *pnVal
-){
- LevelDb *pDb = (LevelDb *)pTestDb;
- char *zErr = 0;
- size_t nVal = 0;
-
- if( pKey==0 ) return 0;
- free(pDb->pVal);
- pDb->pVal = leveldb_get(pDb->db, pDb->pReadOpt, pKey, nKey, &nVal, &zErr);
- *ppVal = (void *)(pDb->pVal);
- if( pDb->pVal==0 ){
- *pnVal = -1;
- }else{
- *pnVal = (int)nVal;
- }
-
- return (zErr!=0);
-}
-
-static int test_leveldb_scan(
- TestDb *pTestDb,
- void *pCtx,
- int bReverse,
- void *pKey1, int nKey1, /* Start of search */
- void *pKey2, int nKey2, /* End of search */
- void (*xCallback)(void *, void *, int , void *, int)
-){
- LevelDb *pDb = (LevelDb *)pTestDb;
- leveldb_iterator_t *iter;
-
- iter = leveldb_create_iterator(pDb->db, pDb->pReadOpt);
-
- if( bReverse==0 ){
- if( pKey1 ){
- leveldb_iter_seek(iter, pKey1, nKey1);
- }else{
- leveldb_iter_seek_to_first(iter);
- }
- }else{
- if( pKey2 ){
- leveldb_iter_seek(iter, pKey2, nKey2);
-
- if( leveldb_iter_valid(iter)==0 ){
- leveldb_iter_seek_to_last(iter);
- }else{
- const char *k; size_t n;
- int res;
- k = leveldb_iter_key(iter, &n);
- res = memcmp(k, pKey2, MIN(n, nKey2));
- if( res==0 ) res = n - nKey2;
- assert( res>=0 );
- if( res>0 ){
- leveldb_iter_prev(iter);
- }
- }
- }else{
- leveldb_iter_seek_to_last(iter);
- }
- }
-
-
- while( leveldb_iter_valid(iter) ){
- const char *k; size_t n;
- const char *v; size_t n2;
- int res;
-
- k = leveldb_iter_key(iter, &n);
- if( bReverse==0 && pKey2 ){
- res = memcmp(k, pKey2, MIN(n, nKey2));
- if( res==0 ) res = n - nKey2;
- if( res>0 ) break;
- }
- if( bReverse!=0 && pKey1 ){
- res = memcmp(k, pKey1, MIN(n, nKey1));
- if( res==0 ) res = n - nKey1;
- if( res<0 ) break;
- }
-
- v = leveldb_iter_value(iter, &n2);
-
- xCallback(pCtx, (void *)k, n, (void *)v, n2);
-
- if( bReverse==0 ){
- leveldb_iter_next(iter);
- }else{
- leveldb_iter_prev(iter);
- }
- }
-
- leveldb_iter_destroy(iter);
- return 0;
-}
-
-static int test_leveldb_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- static const DatabaseMethods LeveldbMethods = {
- test_leveldb_close,
- test_leveldb_write,
- test_leveldb_delete,
- 0,
- test_leveldb_fetch,
- test_leveldb_scan,
- error_transaction_function,
- error_transaction_function,
- error_transaction_function
- };
-
- LevelDb *pLevelDb;
- char *zErr = 0;
-
- if( bClear ){
- char *zCmd = sqlite3_mprintf("rm -rf %s\n", zFilename);
- system(zCmd);
- sqlite3_free(zCmd);
- }
-
- pLevelDb = (LevelDb *)malloc(sizeof(LevelDb));
- memset(pLevelDb, 0, sizeof(LevelDb));
-
- pLevelDb->pOpt = leveldb_options_create();
- leveldb_options_set_create_if_missing(pLevelDb->pOpt, 1);
- pLevelDb->pWriteOpt = leveldb_writeoptions_create();
- pLevelDb->pReadOpt = leveldb_readoptions_create();
-
- pLevelDb->db = leveldb_open(pLevelDb->pOpt, zFilename, &zErr);
-
- if( zErr ){
- test_leveldb_close((TestDb *)pLevelDb);
- *ppDb = 0;
- return 1;
- }
-
- *ppDb = (TestDb *)pLevelDb;
- pLevelDb->base.pMethods = &LeveldbMethods;
- return 0;
-}
-#endif /* HAVE_LEVELDB */
-/*
-** End wrapper for LevelDB.
-*************************************************************************/
-
-#ifdef HAVE_KYOTOCABINET
-static int kc_close(TestDb *pTestDb){
- return test_kc_close(pTestDb);
-}
-
-static int kc_write(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void *pVal,
- int nVal
-){
- return test_kc_write(pTestDb, pKey, nKey, pVal, nVal);
-}
-
-static int kc_delete(TestDb *pTestDb, void *pKey, int nKey){
- return test_kc_delete(pTestDb, pKey, nKey);
-}
-
-static int kc_delete_range(
- TestDb *pTestDb,
- void *pKey1, int nKey1,
- void *pKey2, int nKey2
-){
- return test_kc_delete_range(pTestDb, pKey1, nKey1, pKey2, nKey2);
-}
-
-static int kc_fetch(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void **ppVal,
- int *pnVal
-){
- if( pKey==0 ) return LSM_OK;
- return test_kc_fetch(pTestDb, pKey, nKey, ppVal, pnVal);
-}
-
-static int kc_scan(
- TestDb *pTestDb,
- void *pCtx,
- int bReverse,
- void *pFirst, int nFirst,
- void *pLast, int nLast,
- void (*xCallback)(void *, void *, int , void *, int)
-){
- return test_kc_scan(
- pTestDb, pCtx, bReverse, pFirst, nFirst, pLast, nLast, xCallback
- );
-}
-
-static int kc_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- static const DatabaseMethods KcdbMethods = {
- kc_close,
- kc_write,
- kc_delete,
- kc_delete_range,
- kc_fetch,
- kc_scan,
- error_transaction_function,
- error_transaction_function,
- error_transaction_function
- };
-
- int rc;
- TestDb *pTestDb = 0;
-
- rc = test_kc_open(zFilename, bClear, &pTestDb);
- if( rc!=0 ){
- *ppDb = 0;
- return rc;
- }
- pTestDb->pMethods = &KcdbMethods;
- *ppDb = pTestDb;
- return 0;
-}
-#endif /* HAVE_KYOTOCABINET */
-/*
-** End wrapper for Kyoto cabinet.
-*************************************************************************/
-
-#ifdef HAVE_MDB
-static int mdb_close(TestDb *pTestDb){
- return test_mdb_close(pTestDb);
-}
-
-static int mdb_write(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void *pVal,
- int nVal
-){
- return test_mdb_write(pTestDb, pKey, nKey, pVal, nVal);
-}
-
-static int mdb_delete(TestDb *pTestDb, void *pKey, int nKey){
- return test_mdb_delete(pTestDb, pKey, nKey);
-}
-
-static int mdb_fetch(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void **ppVal,
- int *pnVal
-){
- if( pKey==0 ) return LSM_OK;
- return test_mdb_fetch(pTestDb, pKey, nKey, ppVal, pnVal);
-}
-
-static int mdb_scan(
- TestDb *pTestDb,
- void *pCtx,
- int bReverse,
- void *pFirst, int nFirst,
- void *pLast, int nLast,
- void (*xCallback)(void *, void *, int , void *, int)
-){
- return test_mdb_scan(
- pTestDb, pCtx, bReverse, pFirst, nFirst, pLast, nLast, xCallback
- );
-}
-
-static int mdb_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- static const DatabaseMethods KcdbMethods = {
- mdb_close,
- mdb_write,
- mdb_delete,
- 0,
- mdb_fetch,
- mdb_scan,
- error_transaction_function,
- error_transaction_function,
- error_transaction_function
- };
-
- int rc;
- TestDb *pTestDb = 0;
-
- rc = test_mdb_open(zSpec, zFilename, bClear, &pTestDb);
- if( rc!=0 ){
- *ppDb = 0;
- return rc;
- }
- pTestDb->pMethods = &KcdbMethods;
- *ppDb = pTestDb;
- return 0;
-}
-#endif /* HAVE_MDB */
-
-/*************************************************************************
-** Begin wrapper for SQLite.
-*/
-
-/*
-** nOpenTrans:
-** The number of open nested transactions, in the same sense as used
-** by the tdb_begin/commit/rollback and SQLite 4 KV interfaces. If this
-** value is 0, there are no transactions open at all. If it is 1, then
-** there is a read transaction. If it is 2 or greater, then there are
-** (nOpenTrans-1) nested write transactions open.
-*/
-struct SqlDb {
- TestDb base;
- sqlite3 *db;
- sqlite3_stmt *pInsert;
- sqlite3_stmt *pDelete;
- sqlite3_stmt *pDeleteRange;
- sqlite3_stmt *pFetch;
- sqlite3_stmt *apScan[8];
-
- int nOpenTrans;
-
- /* Used by sql_fetch() to allocate space for results */
- int nAlloc;
- u8 *aAlloc;
-};
-
-static int sql_close(TestDb *pTestDb){
- SqlDb *pDb = (SqlDb *)pTestDb;
- sqlite3_finalize(pDb->pInsert);
- sqlite3_finalize(pDb->pDelete);
- sqlite3_finalize(pDb->pDeleteRange);
- sqlite3_finalize(pDb->pFetch);
- sqlite3_finalize(pDb->apScan[0]);
- sqlite3_finalize(pDb->apScan[1]);
- sqlite3_finalize(pDb->apScan[2]);
- sqlite3_finalize(pDb->apScan[3]);
- sqlite3_finalize(pDb->apScan[4]);
- sqlite3_finalize(pDb->apScan[5]);
- sqlite3_finalize(pDb->apScan[6]);
- sqlite3_finalize(pDb->apScan[7]);
- sqlite3_close(pDb->db);
- free((char *)pDb->aAlloc);
- free((char *)pDb);
- return SQLITE_OK;
-}
-
-static int sql_write(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void *pVal,
- int nVal
-){
- SqlDb *pDb = (SqlDb *)pTestDb;
- sqlite3_bind_blob(pDb->pInsert, 1, pKey, nKey, SQLITE_STATIC);
- sqlite3_bind_blob(pDb->pInsert, 2, pVal, nVal, SQLITE_STATIC);
- sqlite3_step(pDb->pInsert);
- return sqlite3_reset(pDb->pInsert);
-}
-
-static int sql_delete(TestDb *pTestDb, void *pKey, int nKey){
- SqlDb *pDb = (SqlDb *)pTestDb;
- sqlite3_bind_blob(pDb->pDelete, 1, pKey, nKey, SQLITE_STATIC);
- sqlite3_step(pDb->pDelete);
- return sqlite3_reset(pDb->pDelete);
-}
-
-static int sql_delete_range(
- TestDb *pTestDb,
- void *pKey1, int nKey1,
- void *pKey2, int nKey2
-){
- SqlDb *pDb = (SqlDb *)pTestDb;
- sqlite3_bind_blob(pDb->pDeleteRange, 1, pKey1, nKey1, SQLITE_STATIC);
- sqlite3_bind_blob(pDb->pDeleteRange, 2, pKey2, nKey2, SQLITE_STATIC);
- sqlite3_step(pDb->pDeleteRange);
- return sqlite3_reset(pDb->pDeleteRange);
-}
-
-static int sql_fetch(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void **ppVal,
- int *pnVal
-){
- SqlDb *pDb = (SqlDb *)pTestDb;
- int rc;
-
- sqlite3_reset(pDb->pFetch);
- if( pKey==0 ){
- assert( ppVal==0 );
- assert( pnVal==0 );
- return LSM_OK;
- }
-
- sqlite3_bind_blob(pDb->pFetch, 1, pKey, nKey, SQLITE_STATIC);
- rc = sqlite3_step(pDb->pFetch);
- if( rc==SQLITE_ROW ){
- int nVal = sqlite3_column_bytes(pDb->pFetch, 0);
- u8 *aVal = (void *)sqlite3_column_blob(pDb->pFetch, 0);
-
- if( nVal>pDb->nAlloc ){
- free(pDb->aAlloc);
- pDb->aAlloc = (u8 *)malloc(nVal*2);
- pDb->nAlloc = nVal*2;
- }
- memcpy(pDb->aAlloc, aVal, nVal);
- *pnVal = nVal;
- *ppVal = (void *)pDb->aAlloc;
- }else{
- *pnVal = -1;
- *ppVal = 0;
- }
-
- rc = sqlite3_reset(pDb->pFetch);
- return rc;
-}
-
-static int sql_scan(
- TestDb *pTestDb,
- void *pCtx,
- int bReverse,
- void *pFirst, int nFirst,
- void *pLast, int nLast,
- void (*xCallback)(void *, void *, int , void *, int)
-){
- SqlDb *pDb = (SqlDb *)pTestDb;
- sqlite3_stmt *pScan;
-
- assert( bReverse==1 || bReverse==0 );
- pScan = pDb->apScan[(pFirst==0) + (pLast==0)*2 + bReverse*4];
-
- if( pFirst ) sqlite3_bind_blob(pScan, 1, pFirst, nFirst, SQLITE_STATIC);
- if( pLast ) sqlite3_bind_blob(pScan, 2, pLast, nLast, SQLITE_STATIC);
-
- while( SQLITE_ROW==sqlite3_step(pScan) ){
- void *pKey; int nKey;
- void *pVal; int nVal;
-
- nKey = sqlite3_column_bytes(pScan, 0);
- pKey = (void *)sqlite3_column_blob(pScan, 0);
- nVal = sqlite3_column_bytes(pScan, 1);
- pVal = (void *)sqlite3_column_blob(pScan, 1);
-
- xCallback(pCtx, pKey, nKey, pVal, nVal);
- }
- return sqlite3_reset(pScan);
-}
-
-static int sql_begin(TestDb *pTestDb, int iLevel){
- int i;
- SqlDb *pDb = (SqlDb *)pTestDb;
-
- /* iLevel==0 is a no-op */
- if( iLevel==0 ) return 0;
-
- /* If there are no transactions at all open, open a read transaction. */
- if( pDb->nOpenTrans==0 ){
- int rc = sqlite3_exec(pDb->db,
- "BEGIN; SELECT * FROM sqlite_master LIMIT 1;" , 0, 0, 0
- );
- if( rc!=0 ) return rc;
- pDb->nOpenTrans = 1;
- }
-
- /* Open any required write transactions */
- for(i=pDb->nOpenTrans; i<iLevel; i++){
- char *zSql = sqlite3_mprintf("SAVEPOINT x%d", i);
- int rc = sqlite3_exec(pDb->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- pDb->nOpenTrans = iLevel;
- return 0;
-}
-
-static int sql_commit(TestDb *pTestDb, int iLevel){
- SqlDb *pDb = (SqlDb *)pTestDb;
- assert( iLevel>=0 );
-
- /* Close the read transaction if requested. */
- if( pDb->nOpenTrans>=1 && iLevel==0 ){
- int rc = sqlite3_exec(pDb->db, "COMMIT", 0, 0, 0);
- if( rc!=0 ) return rc;
- pDb->nOpenTrans = 0;
- }
-
- /* Close write transactions as required */
- if( pDb->nOpenTrans>iLevel ){
- char *zSql = sqlite3_mprintf("RELEASE x%d", iLevel);
- int rc = sqlite3_exec(pDb->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- if( rc!=0 ) return rc;
- }
-
- pDb->nOpenTrans = iLevel;
- return 0;
-}
-
-static int sql_rollback(TestDb *pTestDb, int iLevel){
- SqlDb *pDb = (SqlDb *)pTestDb;
- assert( iLevel>=0 );
-
- if( pDb->nOpenTrans>=1 && iLevel==0 ){
- /* Close the read transaction if requested. */
- int rc = sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
- if( rc!=0 ) return rc;
- }else if( pDb->nOpenTrans>1 && iLevel==1 ){
- /* Or, rollback and close the top-level write transaction */
- int rc = sqlite3_exec(pDb->db, "ROLLBACK TO x1; RELEASE x1;", 0, 0, 0);
- if( rc!=0 ) return rc;
- }else{
- /* Or, just roll back some nested transactions */
- char *zSql = sqlite3_mprintf("ROLLBACK TO x%d", iLevel-1);
- int rc = sqlite3_exec(pDb->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- if( rc!=0 ) return rc;
- }
-
- pDb->nOpenTrans = iLevel;
- return 0;
-}
-
-static int sql_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- static const DatabaseMethods SqlMethods = {
- sql_close,
- sql_write,
- sql_delete,
- sql_delete_range,
- sql_fetch,
- sql_scan,
- sql_begin,
- sql_commit,
- sql_rollback
- };
- const char *zCreate = "CREATE TABLE IF NOT EXISTS t1(k PRIMARY KEY, v)";
- const char *zInsert = "REPLACE INTO t1 VALUES(?, ?)";
- const char *zDelete = "DELETE FROM t1 WHERE k = ?";
- const char *zRange = "DELETE FROM t1 WHERE k>? AND k<?";
- const char *zFetch = "SELECT v FROM t1 WHERE k = ?";
-
- const char *zScan0 = "SELECT * FROM t1 WHERE k BETWEEN ?1 AND ?2 ORDER BY k";
- const char *zScan1 = "SELECT * FROM t1 WHERE k <= ?2 ORDER BY k";
- const char *zScan2 = "SELECT * FROM t1 WHERE k >= ?1 ORDER BY k";
- const char *zScan3 = "SELECT * FROM t1 ORDER BY k";
-
- const char *zScan4 =
- "SELECT * FROM t1 WHERE k BETWEEN ?1 AND ?2 ORDER BY k DESC";
- const char *zScan5 = "SELECT * FROM t1 WHERE k <= ?2 ORDER BY k DESC";
- const char *zScan6 = "SELECT * FROM t1 WHERE k >= ?1 ORDER BY k DESC";
- const char *zScan7 = "SELECT * FROM t1 ORDER BY k DESC";
-
- int rc;
- SqlDb *pDb;
- char *zPragma;
-
- if( bClear && zFilename && zFilename[0] ){
- unlink(zFilename);
- }
-
- pDb = (SqlDb *)malloc(sizeof(SqlDb));
- memset(pDb, 0, sizeof(SqlDb));
- pDb->base.pMethods = &SqlMethods;
-
- if( 0!=(rc = sqlite3_open(zFilename, &pDb->db))
- || 0!=(rc = sqlite3_exec(pDb->db, zCreate, 0, 0, 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zInsert, -1, &pDb->pInsert, 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zDelete, -1, &pDb->pDelete, 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zRange, -1, &pDb->pDeleteRange, 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zFetch, -1, &pDb->pFetch, 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zScan0, -1, &pDb->apScan[0], 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zScan1, -1, &pDb->apScan[1], 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zScan2, -1, &pDb->apScan[2], 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zScan3, -1, &pDb->apScan[3], 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zScan4, -1, &pDb->apScan[4], 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zScan5, -1, &pDb->apScan[5], 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zScan6, -1, &pDb->apScan[6], 0))
- || 0!=(rc = sqlite3_prepare_v2(pDb->db, zScan7, -1, &pDb->apScan[7], 0))
- ){
- *ppDb = 0;
- sql_close((TestDb *)pDb);
- return rc;
- }
-
- zPragma = sqlite3_mprintf("PRAGMA page_size=%d", TESTDB_DEFAULT_PAGE_SIZE);
- sqlite3_exec(pDb->db, zPragma, 0, 0, 0);
- sqlite3_free(zPragma);
- zPragma = sqlite3_mprintf("PRAGMA cache_size=%d", TESTDB_DEFAULT_CACHE_SIZE);
- sqlite3_exec(pDb->db, zPragma, 0, 0, 0);
- sqlite3_free(zPragma);
-
- /* sqlite3_exec(pDb->db, "PRAGMA locking_mode=EXCLUSIVE", 0, 0, 0); */
- sqlite3_exec(pDb->db, "PRAGMA synchronous=OFF", 0, 0, 0);
- sqlite3_exec(pDb->db, "PRAGMA journal_mode=WAL", 0, 0, 0);
- sqlite3_exec(pDb->db, "PRAGMA wal_autocheckpoint=4096", 0, 0, 0);
- if( zSpec ){
- rc = sqlite3_exec(pDb->db, zSpec, 0, 0, 0);
- if( rc!=SQLITE_OK ){
- sql_close((TestDb *)pDb);
- return rc;
- }
- }
-
- *ppDb = (TestDb *)pDb;
- return 0;
-}
-/*
-** End wrapper for SQLite.
-*************************************************************************/
-
-/*************************************************************************
-** Begin exported functions.
-*/
-static struct Lib {
- const char *zName;
- const char *zDefaultDb;
- int (*xOpen)(const char *, const char *zFilename, int bClear, TestDb **ppDb);
-} aLib[] = {
- { "sqlite3", "testdb.sqlite", sql_open },
- { "lsm_small", "testdb.lsm_small", test_lsm_small_open },
- { "lsm_lomem", "testdb.lsm_lomem", test_lsm_lomem_open },
- { "lsm_lomem2", "testdb.lsm_lomem2", test_lsm_lomem2_open },
-#ifdef HAVE_ZLIB
- { "lsm_zip", "testdb.lsm_zip", test_lsm_zip_open },
-#endif
- { "lsm", "testdb.lsm", test_lsm_open },
-#ifdef LSM_MUTEX_PTHREADS
- { "lsm_mt2", "testdb.lsm_mt2", test_lsm_mt2 },
- { "lsm_mt3", "testdb.lsm_mt3", test_lsm_mt3 },
-#endif
-#ifdef HAVE_LEVELDB
- { "leveldb", "testdb.leveldb", test_leveldb_open },
-#endif
-#ifdef HAVE_KYOTOCABINET
- { "kyotocabinet", "testdb.kc", kc_open },
-#endif
-#ifdef HAVE_MDB
- { "mdb", "./testdb.mdb", mdb_open }
-#endif
-};
-
-const char *tdb_system_name(int i){
- if( i<0 || i>=ArraySize(aLib) ) return 0;
- return aLib[i].zName;
-}
-
-const char *tdb_default_db(const char *zSys){
- int i;
- for(i=0; i<ArraySize(aLib); i++){
- if( strcmp(aLib[i].zName, zSys)==0 ) return aLib[i].zDefaultDb;
- }
- return 0;
-}
-
-int tdb_open(const char *zLib, const char *zDb, int bClear, TestDb **ppDb){
- int i;
- int rc = 1;
- const char *zSpec = 0;
-
- int nLib = 0;
- while( zLib[nLib] && zLib[nLib]!=' ' ){
- nLib++;
- }
- zSpec = &zLib[nLib];
- while( *zSpec==' ' ) zSpec++;
- if( *zSpec=='\0' ) zSpec = 0;
-
- for(i=0; i<ArraySize(aLib); i++){
- if( (int)strlen(aLib[i].zName)==nLib
- && 0==memcmp(zLib, aLib[i].zName, nLib) ){
- rc = aLib[i].xOpen(zSpec, (zDb ? zDb : aLib[i].zDefaultDb), bClear, ppDb);
- if( rc==0 ){
- (*ppDb)->zLibrary = aLib[i].zName;
- }
- break;
- }
- }
-
- if( rc ){
- /* Failed to find the requested database library. Return an error. */
- *ppDb = 0;
- }
- return rc;
-}
-
-int tdb_close(TestDb *pDb){
- if( pDb ){
- return pDb->pMethods->xClose(pDb);
- }
- return 0;
-}
-
-int tdb_write(TestDb *pDb, void *pKey, int nKey, void *pVal, int nVal){
- return pDb->pMethods->xWrite(pDb, pKey, nKey, pVal, nVal);
-}
-
-int tdb_delete(TestDb *pDb, void *pKey, int nKey){
- return pDb->pMethods->xDelete(pDb, pKey, nKey);
-}
-
-int tdb_delete_range(
- TestDb *pDb, void *pKey1, int nKey1, void *pKey2, int nKey2
-){
- return pDb->pMethods->xDeleteRange(pDb, pKey1, nKey1, pKey2, nKey2);
-}
-
-int tdb_fetch(TestDb *pDb, void *pKey, int nKey, void **ppVal, int *pnVal){
- return pDb->pMethods->xFetch(pDb, pKey, nKey, ppVal, pnVal);
-}
-
-int tdb_scan(
- TestDb *pDb, /* Database handle */
- void *pCtx, /* Context pointer to pass to xCallback */
- int bReverse, /* True to scan in reverse order */
- void *pKey1, int nKey1, /* Start of search */
- void *pKey2, int nKey2, /* End of search */
- void (*xCallback)(void *pCtx, void *pKey, int nKey, void *pVal, int nVal)
-){
- return pDb->pMethods->xScan(
- pDb, pCtx, bReverse, pKey1, nKey1, pKey2, nKey2, xCallback
- );
-}
-
-int tdb_begin(TestDb *pDb, int iLevel){
- return pDb->pMethods->xBegin(pDb, iLevel);
-}
-int tdb_commit(TestDb *pDb, int iLevel){
- return pDb->pMethods->xCommit(pDb, iLevel);
-}
-int tdb_rollback(TestDb *pDb, int iLevel){
- return pDb->pMethods->xRollback(pDb, iLevel);
-}
-
-int tdb_transaction_support(TestDb *pDb){
- return (pDb->pMethods->xBegin != error_transaction_function);
-}
-
-const char *tdb_library_name(TestDb *pDb){
- return pDb->zLibrary;
-}
-
-/*
-** End exported functions.
-*************************************************************************/
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb.h
deleted file mode 100644
index c55b6e2f802..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb.h
+++ /dev/null
@@ -1,174 +0,0 @@
-
-/*
-** This file is the interface to a very simple database library used for
-** testing. The interface is similar to that of the LSM. The main virtue
-** of this library is that the same API may be used to access a key-value
-** store implemented by LSM, SQLite or another database system. Which
-** makes it easy to use for correctness and performance tests.
-*/
-
-#ifndef __WRAPPER_H_
-#define __WRAPPER_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "lsm.h"
-
-typedef struct TestDb TestDb;
-
-/*
-** Open a new database connection. The first argument is the name of the
-** database library to use. e.g. something like:
-**
-** "sqlite3"
-** "lsm"
-**
-** See function tdb_system_name() for a list of available database systems.
-**
-** The second argument is the name of the database to open (e.g. a filename).
-**
-** If the third parameter is non-zero, then any existing database by the
-** name of zDb is removed before opening a new one. If it is zero, then an
-** existing database may be opened.
-*/
-int tdb_open(const char *zLibrary, const char *zDb, int bClear, TestDb **ppDb);
-
-/*
-** Close a database handle.
-*/
-int tdb_close(TestDb *pDb);
-
-/*
-** Write a new key/value into the database.
-*/
-int tdb_write(TestDb *pDb, void *pKey, int nKey, void *pVal, int nVal);
-
-/*
-** Delete a key from the database.
-*/
-int tdb_delete(TestDb *pDb, void *pKey, int nKey);
-
-/*
-** Delete a range of keys from the database.
-*/
-int tdb_delete_range(TestDb *, void *pKey1, int nKey1, void *pKey2, int nKey2);
-
-/*
-** Query the database for key (pKey/nKey). If no entry is found, set *ppVal
-** to 0 and *pnVal to -1 before returning. Otherwise, set *ppVal and *pnVal
-** to a pointer to and size of the value associated with (pKey/nKey).
-*/
-int tdb_fetch(TestDb *pDb, void *pKey, int nKey, void **ppVal, int *pnVal);
-
-/*
-** Open and close nested transactions. Currently, these functions only
-** work for SQLite3 and LSM systems. Use the tdb_transaction_support()
-** function to determine if a given TestDb handle supports these methods.
-**
-** These functions and the iLevel parameter follow the same conventions as
-** the SQLite 4 transaction interface. Note that this is slightly different
-** from the way LSM does things. As follows:
-**
-** tdb_begin():
-** A successful call to tdb_begin() with (iLevel>1) guarantees that
-** there are at least (iLevel-1) write transactions open. If iLevel==1,
-** then it guarantees that at least a read-transaction is open. Calling
-** tdb_begin() with iLevel==0 is a no-op.
-**
-** tdb_commit():
-** A successful call to tdb_commit() with (iLevel>1) guarantees that
-** there are at most (iLevel-1) write transactions open. If iLevel==1,
-** then it guarantees that there are no write transactions open (although
-** a read-transaction may remain open). Calling tdb_commit() with
-** iLevel==0 ensures that all transactions, read or write, have been
-** closed and committed.
-**
-** tdb_rollback():
-** This call is similar to tdb_commit(), except that instead of committing
-** transactions, it reverts them. For example, calling tdb_rollback() with
-** iLevel==2 ensures that there is at most one write transaction open, and
-** restores the database to the state that it was in when that transaction
-** was opened.
-**
-** In other words, tdb_commit() just closes transactions - tdb_rollback()
-** closes transactions and then restores the database to the state it
-** was in before those transactions were even opened.
-*/
-int tdb_begin(TestDb *pDb, int iLevel);
-int tdb_commit(TestDb *pDb, int iLevel);
-int tdb_rollback(TestDb *pDb, int iLevel);
-
-/*
-** Return true if transactions are supported, or false otherwise.
-*/
-int tdb_transaction_support(TestDb *pDb);
-
-/*
-** Return the name of the database library (as passed to tdb_open()) used
-** by the handled passed as the first argument.
-*/
-const char *tdb_library_name(TestDb *pDb);
-
-/*
-** Scan a range of database keys. Invoke the callback function for each
-** key visited.
-*/
-int tdb_scan(
- TestDb *pDb, /* Database handle */
- void *pCtx, /* Context pointer to pass to xCallback */
- int bReverse, /* True to scan in reverse order */
- void *pKey1, int nKey1, /* Start of search */
- void *pKey2, int nKey2, /* End of search */
- void (*xCallback)(void *pCtx, void *pKey, int nKey, void *pVal, int nVal)
-);
-
-const char *tdb_system_name(int i);
-const char *tdb_default_db(const char *zSys);
-
-int tdb_lsm_open(const char *zCfg, const char *zDb, int bClear, TestDb **ppDb);
-
-/*
-** If the TestDb handle passed as an argument is a wrapper around an LSM
-** database, return the LSM handle. Otherwise, if the argument is some other
-** database system, return NULL.
-*/
-lsm_db *tdb_lsm(TestDb *pDb);
-
-/*
-** Return true if the db passed as an argument is a multi-threaded LSM
-** connection.
-*/
-int tdb_lsm_multithread(TestDb *pDb);
-
-/*
-** Return a pointer to the lsm_env object used by all lsm database
-** connections initialized as a copy of the object returned by
-** lsm_default_env(). It may be modified (e.g. to override functions)
-** if the caller can guarantee that it is not already in use.
-*/
-lsm_env *tdb_lsm_env(void);
-
-/*
-** The following functions only work with LSM database handles. It is
-** illegal to call them with any other type of database handle specified
-** as an argument.
-*/
-void tdb_lsm_enable_log(TestDb *pDb, int bEnable);
-void tdb_lsm_application_crash(TestDb *pDb);
-void tdb_lsm_prepare_system_crash(TestDb *pDb);
-void tdb_lsm_system_crash(TestDb *pDb);
-void tdb_lsm_prepare_sync_crash(TestDb *pDb, int iSync);
-
-
-void tdb_lsm_safety(TestDb *pDb, int eMode);
-void tdb_lsm_config_work_hook(TestDb *pDb, void (*)(lsm_db *, void *), void *);
-void tdb_lsm_write_hook(TestDb *, void(*)(void*,int,lsm_i64,int,int), void*);
-int tdb_lsm_config_str(TestDb *pDb, const char *zStr);
-
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb2.cc b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb2.cc
deleted file mode 100644
index 307c2b5f07d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb2.cc
+++ /dev/null
@@ -1,370 +0,0 @@
-
-
-#include "lsmtest.h"
-#include <stdlib.h>
-
-#ifdef HAVE_KYOTOCABINET
-#include "kcpolydb.h"
-extern "C" {
- struct KcDb {
- TestDb base;
- kyotocabinet::TreeDB* db;
- char *pVal;
- };
-}
-
-int test_kc_open(const char *zFilename, int bClear, TestDb **ppDb){
- KcDb *pKcDb;
- int ok;
- int rc = 0;
-
- if( bClear ){
- char *zCmd = sqlite3_mprintf("rm -rf %s\n", zFilename);
- system(zCmd);
- sqlite3_free(zCmd);
- }
-
- pKcDb = (KcDb *)malloc(sizeof(KcDb));
- memset(pKcDb, 0, sizeof(KcDb));
-
-
- pKcDb->db = new kyotocabinet::TreeDB();
- pKcDb->db->tune_page(TESTDB_DEFAULT_PAGE_SIZE);
- pKcDb->db->tune_page_cache(
- TESTDB_DEFAULT_PAGE_SIZE * TESTDB_DEFAULT_CACHE_SIZE
- );
- ok = pKcDb->db->open(zFilename,
- kyotocabinet::PolyDB::OWRITER | kyotocabinet::PolyDB::OCREATE
- );
- if( ok==0 ){
- free(pKcDb);
- pKcDb = 0;
- rc = 1;
- }
-
- *ppDb = (TestDb *)pKcDb;
- return rc;
-}
-
-int test_kc_close(TestDb *pDb){
- KcDb *pKcDb = (KcDb *)pDb;
- if( pKcDb->pVal ){
- delete [] pKcDb->pVal;
- }
- pKcDb->db->close();
- delete pKcDb->db;
- free(pKcDb);
- return 0;
-}
-
-int test_kc_write(TestDb *pDb, void *pKey, int nKey, void *pVal, int nVal){
- KcDb *pKcDb = (KcDb *)pDb;
- int ok;
-
- ok = pKcDb->db->set((const char *)pKey, nKey, (const char *)pVal, nVal);
- return (ok ? 0 : 1);
-}
-
-int test_kc_delete(TestDb *pDb, void *pKey, int nKey){
- KcDb *pKcDb = (KcDb *)pDb;
- int ok;
-
- ok = pKcDb->db->remove((const char *)pKey, nKey);
- return (ok ? 0 : 1);
-}
-
-int test_kc_delete_range(
- TestDb *pDb,
- void *pKey1, int nKey1,
- void *pKey2, int nKey2
-){
- int res;
- KcDb *pKcDb = (KcDb *)pDb;
- kyotocabinet::DB::Cursor* pCur = pKcDb->db->cursor();
-
- if( pKey1 ){
- res = pCur->jump((const char *)pKey1, nKey1);
- }else{
- res = pCur->jump();
- }
-
- while( 1 ){
- const char *pKey; size_t nKey;
- const char *pVal; size_t nVal;
-
- pKey = pCur->get(&nKey, &pVal, &nVal);
- if( pKey==0 ) break;
-
-#ifndef NDEBUG
- if( pKey1 ){
- res = memcmp(pKey, pKey1, MIN((size_t)nKey1, nKey));
- assert( res>0 || (res==0 && nKey>nKey1) );
- }
-#endif
-
- if( pKey2 ){
- res = memcmp(pKey, pKey2, MIN((size_t)nKey2, nKey));
- if( res>0 || (res==0 && (size_t)nKey2<nKey) ){
- delete [] pKey;
- break;
- }
- }
- pCur->remove();
- delete [] pKey;
- }
-
- delete pCur;
- return 0;
-}
-
-int test_kc_fetch(
- TestDb *pDb,
- void *pKey,
- int nKey,
- void **ppVal,
- int *pnVal
-){
- KcDb *pKcDb = (KcDb *)pDb;
- size_t nVal;
-
- if( pKcDb->pVal ){
- delete [] pKcDb->pVal;
- pKcDb->pVal = 0;
- }
-
- pKcDb->pVal = pKcDb->db->get((const char *)pKey, nKey, &nVal);
- if( pKcDb->pVal ){
- *ppVal = pKcDb->pVal;
- *pnVal = nVal;
- }else{
- *ppVal = 0;
- *pnVal = -1;
- }
-
- return 0;
-}
-
-int test_kc_scan(
- TestDb *pDb, /* Database handle */
- void *pCtx, /* Context pointer to pass to xCallback */
- int bReverse, /* True for a reverse order scan */
- void *pKey1, int nKey1, /* Start of search */
- void *pKey2, int nKey2, /* End of search */
- void (*xCallback)(void *pCtx, void *pKey, int nKey, void *pVal, int nVal)
-){
- KcDb *pKcDb = (KcDb *)pDb;
- kyotocabinet::DB::Cursor* pCur = pKcDb->db->cursor();
- int res;
-
- if( bReverse==0 ){
- if( pKey1 ){
- res = pCur->jump((const char *)pKey1, nKey1);
- }else{
- res = pCur->jump();
- }
- }else{
- if( pKey2 ){
- res = pCur->jump_back((const char *)pKey2, nKey2);
- }else{
- res = pCur->jump_back();
- }
- }
-
- while( res ){
- const char *pKey; size_t nKey;
- const char *pVal; size_t nVal;
- pKey = pCur->get(&nKey, &pVal, &nVal);
-
- if( bReverse==0 && pKey2 ){
- res = memcmp(pKey, pKey2, MIN((size_t)nKey2, nKey));
- if( res>0 || (res==0 && (size_t)nKey2<nKey) ){
- delete [] pKey;
- break;
- }
- }else if( bReverse!=0 && pKey1 ){
- res = memcmp(pKey, pKey1, MIN((size_t)nKey1, nKey));
- if( res<0 || (res==0 && (size_t)nKey1>nKey) ){
- delete [] pKey;
- break;
- }
- }
-
- xCallback(pCtx, (void *)pKey, (int)nKey, (void *)pVal, (int)nVal);
- delete [] pKey;
-
- if( bReverse ){
- res = pCur->step_back();
- }else{
- res = pCur->step();
- }
- }
-
- delete pCur;
- return 0;
-}
-#endif /* HAVE_KYOTOCABINET */
-
-#ifdef HAVE_MDB
-#include "lmdb.h"
-
-extern "C" {
- struct MdbDb {
- TestDb base;
- MDB_env *env;
- MDB_dbi dbi;
- };
-}
-
-int test_mdb_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- MDB_txn *txn;
- MdbDb *pMdb;
- int rc;
-
- if( bClear ){
- char *zCmd = sqlite3_mprintf("rm -rf %s\n", zFilename);
- system(zCmd);
- sqlite3_free(zCmd);
- }
-
- pMdb = (MdbDb *)malloc(sizeof(MdbDb));
- memset(pMdb, 0, sizeof(MdbDb));
-
- rc = mdb_env_create(&pMdb->env);
- if( rc==0 ) rc = mdb_env_set_mapsize(pMdb->env, 1*1024*1024*1024);
- if( rc==0 ) rc = mdb_env_open(pMdb->env, zFilename, MDB_NOSYNC|MDB_NOSUBDIR, 0600);
- if( rc==0 ) rc = mdb_txn_begin(pMdb->env, NULL, 0, &txn);
- if( rc==0 ){
- rc = mdb_open(txn, NULL, 0, &pMdb->dbi);
- mdb_txn_commit(txn);
- }
-
- *ppDb = (TestDb *)pMdb;
- return rc;
-}
-
-int test_mdb_close(TestDb *pDb){
- MdbDb *pMdb = (MdbDb *)pDb;
-
- mdb_close(pMdb->env, pMdb->dbi);
- mdb_env_close(pMdb->env);
- free(pMdb);
- return 0;
-}
-
-int test_mdb_write(TestDb *pDb, void *pKey, int nKey, void *pVal, int nVal){
- int rc;
- MdbDb *pMdb = (MdbDb *)pDb;
- MDB_val val;
- MDB_val key;
- MDB_txn *txn;
-
- val.mv_size = nVal;
- val.mv_data = pVal;
- key.mv_size = nKey;
- key.mv_data = pKey;
-
- rc = mdb_txn_begin(pMdb->env, NULL, 0, &txn);
- if( rc==0 ){
- rc = mdb_put(txn, pMdb->dbi, &key, &val, 0);
- if( rc==0 ){
- rc = mdb_txn_commit(txn);
- }else{
- mdb_txn_abort(txn);
- }
- }
-
- return rc;
-}
-
-int test_mdb_delete(TestDb *pDb, void *pKey, int nKey){
- int rc;
- MdbDb *pMdb = (MdbDb *)pDb;
- MDB_val key;
- MDB_txn *txn;
-
- key.mv_size = nKey;
- key.mv_data = pKey;
- rc = mdb_txn_begin(pMdb->env, NULL, 0, &txn);
- if( rc==0 ){
- rc = mdb_del(txn, pMdb->dbi, &key, 0);
- if( rc==0 ){
- rc = mdb_txn_commit(txn);
- }else{
- mdb_txn_abort(txn);
- }
- }
-
- return rc;
-}
-
-int test_mdb_fetch(
- TestDb *pDb,
- void *pKey,
- int nKey,
- void **ppVal,
- int *pnVal
-){
- int rc;
- MdbDb *pMdb = (MdbDb *)pDb;
- MDB_val key;
- MDB_txn *txn;
-
- key.mv_size = nKey;
- key.mv_data = pKey;
-
- rc = mdb_txn_begin(pMdb->env, NULL, MDB_RDONLY, &txn);
- if( rc==0 ){
- MDB_val val = {0, 0};
- rc = mdb_get(txn, pMdb->dbi, &key, &val);
- if( rc==MDB_NOTFOUND ){
- rc = 0;
- *ppVal = 0;
- *pnVal = -1;
- }else{
- *ppVal = val.mv_data;
- *pnVal = val.mv_size;
- }
- mdb_txn_commit(txn);
- }
-
- return rc;
-}
-
-int test_mdb_scan(
- TestDb *pDb, /* Database handle */
- void *pCtx, /* Context pointer to pass to xCallback */
- int bReverse, /* True for a reverse order scan */
- void *pKey1, int nKey1, /* Start of search */
- void *pKey2, int nKey2, /* End of search */
- void (*xCallback)(void *pCtx, void *pKey, int nKey, void *pVal, int nVal)
-){
- MdbDb *pMdb = (MdbDb *)pDb;
- int rc;
- MDB_cursor_op op = bReverse ? MDB_PREV : MDB_NEXT;
- MDB_txn *txn;
-
- rc = mdb_txn_begin(pMdb->env, NULL, MDB_RDONLY, &txn);
- if( rc==0 ){
- MDB_cursor *csr;
- MDB_val key = {0, 0};
- MDB_val val = {0, 0};
-
- rc = mdb_cursor_open(txn, pMdb->dbi, &csr);
- if( rc==0 ){
- while( mdb_cursor_get(csr, &key, &val, op)==0 ){
- xCallback(pCtx, key.mv_data, key.mv_size, val.mv_data, val.mv_size);
- }
- mdb_cursor_close(csr);
- }
- }
-
- return rc;
-}
-
-#endif /* HAVE_MDB */
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb3.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb3.c
deleted file mode 100644
index c21e243b5c3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb3.c
+++ /dev/null
@@ -1,1402 +0,0 @@
-
-#include "lsmtest_tdb.h"
-#include "lsm.h"
-#include "lsmtest.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#ifndef _WIN32
-# include <unistd.h>
-#endif
-#include <stdio.h>
-
-#ifndef _WIN32
-# include <sys/time.h>
-#endif
-
-typedef struct LsmDb LsmDb;
-typedef struct LsmWorker LsmWorker;
-typedef struct LsmFile LsmFile;
-
-#define LSMTEST_DFLT_MT_MAX_CKPT (8*1024)
-#define LSMTEST_DFLT_MT_MIN_CKPT (2*1024)
-
-#ifdef LSM_MUTEX_PTHREADS
-#include <pthread.h>
-
-#define LSMTEST_THREAD_CKPT 1
-#define LSMTEST_THREAD_WORKER 2
-#define LSMTEST_THREAD_WORKER_AC 3
-
-/*
-** There are several different types of worker threads that run in different
-** test configurations, depending on the value of LsmWorker.eType.
-**
-** 1. Checkpointer.
-** 2. Worker with auto-checkpoint.
-** 3. Worker without auto-checkpoint.
-*/
-struct LsmWorker {
- LsmDb *pDb; /* Main database structure */
- lsm_db *pWorker; /* Worker database handle */
- pthread_t worker_thread; /* Worker thread */
- pthread_cond_t worker_cond; /* Condition var the worker waits on */
- pthread_mutex_t worker_mutex; /* Mutex used with worker_cond */
- int bDoWork; /* Set to true by client when there is work */
- int worker_rc; /* Store error code here */
- int eType; /* LSMTEST_THREAD_XXX constant */
- int bBlock;
-};
-#else
-struct LsmWorker { int worker_rc; int bBlock; };
-#endif
-
-static void mt_shutdown(LsmDb *);
-
-lsm_env *tdb_lsm_env(void){
- static int bInit = 0;
- static lsm_env env;
- if( bInit==0 ){
- memcpy(&env, lsm_default_env(), sizeof(env));
- bInit = 1;
- }
- return &env;
-}
-
-typedef struct FileSector FileSector;
-typedef struct FileData FileData;
-
-struct FileSector {
- u8 *aOld; /* Old data for this sector */
-};
-
-struct FileData {
- int nSector; /* Allocated size of apSector[] array */
- FileSector *aSector; /* Array of file sectors */
-};
-
-/*
-** bPrepareCrash:
-** If non-zero, the file wrappers maintain enough in-memory data to
-** simulate the effect of a power-failure on the file-system (i.e. that
-** unsynced sectors may be written, not written, or overwritten with
-** arbitrary data when the crash occurs).
-**
-** bCrashed:
-** Set to true after a crash is simulated. Once this variable is true, all
-** VFS methods other than xClose() return LSM_IOERR as soon as they are
-** called (without affecting the contents of the file-system).
-**
-** env:
-** The environment object used by all lsm_db* handles opened by this
-** object (i.e. LsmDb.db plus any worker connections). Variable env.pVfsCtx
-** always points to the containing LsmDb structure.
-*/
-struct LsmDb {
- TestDb base; /* Base class - methods table */
- lsm_env env; /* Environment used by connection db */
- char *zName; /* Database file name */
- lsm_db *db; /* LSM database handle */
-
- lsm_cursor *pCsr; /* Cursor held open during read transaction */
- void *pBuf; /* Buffer for tdb_fetch() output */
- int nBuf; /* Allocated (not used) size of pBuf */
-
- /* Crash testing related state */
- int bCrashed; /* True once a crash has occurred */
- int nAutoCrash; /* Number of syncs until a crash */
- int bPrepareCrash; /* True to store writes in memory */
-
- /* Unsynced data (while crash testing) */
- int szSector; /* Assumed size of disk sectors (512B) */
- FileData aFile[2]; /* Database and log file data */
-
- /* Other test instrumentation */
- int bNoRecovery; /* If true, assume DMS2 is locked */
-
- /* Work hook redirection */
- void (*xWork)(lsm_db *, void *);
- void *pWorkCtx;
-
- /* IO logging hook */
- void (*xWriteHook)(void *, int, lsm_i64, int, int);
- void *pWriteCtx;
-
- /* Worker threads (for lsm_mt) */
- int nMtMinCkpt;
- int nMtMaxCkpt;
- int eMode;
- int nWorker;
- LsmWorker *aWorker;
-};
-
-#define LSMTEST_MODE_SINGLETHREAD 1
-#define LSMTEST_MODE_BACKGROUND_CKPT 2
-#define LSMTEST_MODE_BACKGROUND_WORK 3
-#define LSMTEST_MODE_BACKGROUND_BOTH 4
-
-/*************************************************************************
-**************************************************************************
-** Begin test VFS code.
-*/
-
-struct LsmFile {
- lsm_file *pReal; /* Real underlying file */
- int bLog; /* True for log file. False for db file */
- LsmDb *pDb; /* Database handle that uses this file */
-};
-
-static int testEnvFullpath(
- lsm_env *pEnv, /* Environment for current LsmDb */
- const char *zFile, /* Relative path name */
- char *zOut, /* Output buffer */
- int *pnOut /* IN/OUT: Size of output buffer */
-){
- lsm_env *pRealEnv = tdb_lsm_env();
- return pRealEnv->xFullpath(pRealEnv, zFile, zOut, pnOut);
-}
-
-static int testEnvOpen(
- lsm_env *pEnv, /* Environment for current LsmDb */
- const char *zFile, /* Name of file to open */
- int flags,
- lsm_file **ppFile /* OUT: New file handle object */
-){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmDb *pDb = (LsmDb *)pEnv->pVfsCtx;
- int rc; /* Return Code */
- LsmFile *pRet; /* The new file handle */
- int nFile; /* Length of string zFile in bytes */
-
- nFile = strlen(zFile);
- pRet = (LsmFile *)testMalloc(sizeof(LsmFile));
- pRet->pDb = pDb;
- pRet->bLog = (nFile > 4 && 0==memcmp("-log", &zFile[nFile-4], 4));
-
- rc = pRealEnv->xOpen(pRealEnv, zFile, flags, &pRet->pReal);
- if( rc!=LSM_OK ){
- testFree(pRet);
- pRet = 0;
- }
-
- *ppFile = (lsm_file *)pRet;
- return rc;
-}
-
-static int testEnvRead(lsm_file *pFile, lsm_i64 iOff, void *pData, int nData){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmFile *p = (LsmFile *)pFile;
- if( p->pDb->bCrashed ) return LSM_IOERR;
- return pRealEnv->xRead(p->pReal, iOff, pData, nData);
-}
-
-static int testEnvWrite(lsm_file *pFile, lsm_i64 iOff, void *pData, int nData){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmFile *p = (LsmFile *)pFile;
- LsmDb *pDb = p->pDb;
-
- if( pDb->bCrashed ) return LSM_IOERR;
-
- if( pDb->bPrepareCrash ){
- FileData *pData2 = &pDb->aFile[p->bLog];
- int iFirst;
- int iLast;
- int iSector;
-
- iFirst = (int)(iOff / pDb->szSector);
- iLast = (int)((iOff + nData - 1) / pDb->szSector);
-
- if( pData2->nSector<(iLast+1) ){
- int nNew = ( ((iLast + 1) + 63) / 64 ) * 64;
- assert( nNew>iLast );
- pData2->aSector = (FileSector *)testRealloc(
- pData2->aSector, nNew*sizeof(FileSector)
- );
- memset(&pData2->aSector[pData2->nSector],
- 0, (nNew - pData2->nSector) * sizeof(FileSector)
- );
- pData2->nSector = nNew;
- }
-
- for(iSector=iFirst; iSector<=iLast; iSector++){
- if( pData2->aSector[iSector].aOld==0 ){
- u8 *aOld = (u8 *)testMalloc(pDb->szSector);
- pRealEnv->xRead(
- p->pReal, (lsm_i64)iSector*pDb->szSector, aOld, pDb->szSector
- );
- pData2->aSector[iSector].aOld = aOld;
- }
- }
- }
-
- if( pDb->xWriteHook ){
- int rc;
- int nUs;
- struct timeval t1;
- struct timeval t2;
-
- gettimeofday(&t1, 0);
- assert( nData>0 );
- rc = pRealEnv->xWrite(p->pReal, iOff, pData, nData);
- gettimeofday(&t2, 0);
-
- nUs = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
- pDb->xWriteHook(pDb->pWriteCtx, p->bLog, iOff, nData, nUs);
- return rc;
- }
-
- return pRealEnv->xWrite(p->pReal, iOff, pData, nData);
-}
-
-static void doSystemCrash(LsmDb *pDb);
-
-static int testEnvSync(lsm_file *pFile){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmFile *p = (LsmFile *)pFile;
- LsmDb *pDb = p->pDb;
- FileData *pData = &pDb->aFile[p->bLog];
- int i;
-
- if( pDb->bCrashed ) return LSM_IOERR;
-
- if( pDb->nAutoCrash ){
- pDb->nAutoCrash--;
- if( pDb->nAutoCrash==0 ){
- doSystemCrash(pDb);
- pDb->bCrashed = 1;
- return LSM_IOERR;
- }
- }
-
- if( pDb->bPrepareCrash ){
- for(i=0; i<pData->nSector; i++){
- testFree(pData->aSector[i].aOld);
- pData->aSector[i].aOld = 0;
- }
- }
-
- if( pDb->xWriteHook ){
- int rc;
- int nUs;
- struct timeval t1;
- struct timeval t2;
-
- gettimeofday(&t1, 0);
- rc = pRealEnv->xSync(p->pReal);
- gettimeofday(&t2, 0);
-
- nUs = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
- pDb->xWriteHook(pDb->pWriteCtx, p->bLog, 0, 0, nUs);
- return rc;
- }
-
- return pRealEnv->xSync(p->pReal);
-}
-
-static int testEnvTruncate(lsm_file *pFile, lsm_i64 iOff){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmFile *p = (LsmFile *)pFile;
- if( p->pDb->bCrashed ) return LSM_IOERR;
- return pRealEnv->xTruncate(p->pReal, iOff);
-}
-
-static int testEnvSectorSize(lsm_file *pFile){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmFile *p = (LsmFile *)pFile;
- return pRealEnv->xSectorSize(p->pReal);
-}
-
-static int testEnvRemap(
- lsm_file *pFile,
- lsm_i64 iMin,
- void **ppOut,
- lsm_i64 *pnOut
-){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmFile *p = (LsmFile *)pFile;
- return pRealEnv->xRemap(p->pReal, iMin, ppOut, pnOut);
-}
-
-static int testEnvFileid(
- lsm_file *pFile,
- void *ppOut,
- int *pnOut
-){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmFile *p = (LsmFile *)pFile;
- return pRealEnv->xFileid(p->pReal, ppOut, pnOut);
-}
-
-static int testEnvClose(lsm_file *pFile){
- lsm_env *pRealEnv = tdb_lsm_env();
- LsmFile *p = (LsmFile *)pFile;
-
- pRealEnv->xClose(p->pReal);
- testFree(p);
- return LSM_OK;
-}
-
-static int testEnvUnlink(lsm_env *pEnv, const char *zFile){
- lsm_env *pRealEnv = tdb_lsm_env();
- unused_parameter(pEnv);
- return pRealEnv->xUnlink(pRealEnv, zFile);
-}
-
-static int testEnvLock(lsm_file *pFile, int iLock, int eType){
- LsmFile *p = (LsmFile *)pFile;
- lsm_env *pRealEnv = tdb_lsm_env();
-
- if( iLock==2 && eType==LSM_LOCK_EXCL && p->pDb->bNoRecovery ){
- return LSM_BUSY;
- }
- return pRealEnv->xLock(p->pReal, iLock, eType);
-}
-
-static int testEnvTestLock(lsm_file *pFile, int iLock, int nLock, int eType){
- LsmFile *p = (LsmFile *)pFile;
- lsm_env *pRealEnv = tdb_lsm_env();
-
- if( iLock==2 && eType==LSM_LOCK_EXCL && p->pDb->bNoRecovery ){
- return LSM_BUSY;
- }
- return pRealEnv->xTestLock(p->pReal, iLock, nLock, eType);
-}
-
-static int testEnvShmMap(lsm_file *pFile, int iRegion, int sz, void **pp){
- LsmFile *p = (LsmFile *)pFile;
- lsm_env *pRealEnv = tdb_lsm_env();
- return pRealEnv->xShmMap(p->pReal, iRegion, sz, pp);
-}
-
-static void testEnvShmBarrier(void){
-}
-
-static int testEnvShmUnmap(lsm_file *pFile, int bDel){
- LsmFile *p = (LsmFile *)pFile;
- lsm_env *pRealEnv = tdb_lsm_env();
- return pRealEnv->xShmUnmap(p->pReal, bDel);
-}
-
-static int testEnvSleep(lsm_env *pEnv, int us){
- lsm_env *pRealEnv = tdb_lsm_env();
- return pRealEnv->xSleep(pRealEnv, us);
-}
-
-static void doSystemCrash(LsmDb *pDb){
- lsm_env *pEnv = tdb_lsm_env();
- int iFile;
- int iSeed = pDb->aFile[0].nSector + pDb->aFile[1].nSector;
-
- char *zFile = pDb->zName;
- char *zFree = 0;
-
- for(iFile=0; iFile<2; iFile++){
- lsm_file *pFile = 0;
- int i;
-
- pEnv->xOpen(pEnv, zFile, 0, &pFile);
- for(i=0; i<pDb->aFile[iFile].nSector; i++){
- u8 *aOld = pDb->aFile[iFile].aSector[i].aOld;
- if( aOld ){
- int iOpt = testPrngValue(iSeed++) % 3;
- switch( iOpt ){
- case 0:
- break;
-
- case 1:
- testPrngArray(iSeed++, (u32 *)aOld, pDb->szSector/4);
- /* Fall-through */
-
- case 2:
- pEnv->xWrite(
- pFile, (lsm_i64)i * pDb->szSector, aOld, pDb->szSector
- );
- break;
- }
- testFree(aOld);
- pDb->aFile[iFile].aSector[i].aOld = 0;
- }
- }
- pEnv->xClose(pFile);
- zFree = zFile = sqlite3_mprintf("%s-log", pDb->zName);
- }
-
- sqlite3_free(zFree);
-}
-/*
-** End test VFS code.
-**************************************************************************
-*************************************************************************/
-
-/*************************************************************************
-**************************************************************************
-** Begin test compression hooks.
-*/
-
-#ifdef HAVE_ZLIB
-#include <zlib.h>
-
-static int testZipBound(void *pCtx, int nSrc){
- return compressBound(nSrc);
-}
-
-static int testZipCompress(
- void *pCtx, /* Context pointer */
- char *aOut, int *pnOut, /* OUT: Buffer containing compressed data */
- const char *aIn, int nIn /* Buffer containing input data */
-){
- uLongf n = *pnOut; /* In/out buffer size for compress() */
- int rc; /* compress() return code */
-
- rc = compress((Bytef*)aOut, &n, (Bytef*)aIn, nIn);
- *pnOut = n;
- return (rc==Z_OK ? 0 : LSM_ERROR);
-}
-
-static int testZipUncompress(
- void *pCtx, /* Context pointer */
- char *aOut, int *pnOut, /* OUT: Buffer containing uncompressed data */
- const char *aIn, int nIn /* Buffer containing input data */
-){
- uLongf n = *pnOut; /* In/out buffer size for uncompress() */
- int rc; /* uncompress() return code */
-
- rc = uncompress((Bytef*)aOut, &n, (Bytef*)aIn, nIn);
- *pnOut = n;
- return (rc==Z_OK ? 0 : LSM_ERROR);
-}
-
-static int testConfigureCompression(lsm_db *pDb){
- static lsm_compress zip = {
- 0, /* Context pointer (unused) */
- 1, /* Id value */
- testZipBound, /* xBound method */
- testZipCompress, /* xCompress method */
- testZipUncompress /* xUncompress method */
- };
- return lsm_config(pDb, LSM_CONFIG_SET_COMPRESSION, &zip);
-}
-#endif /* ifdef HAVE_ZLIB */
-
-/*
-** End test compression hooks.
-**************************************************************************
-*************************************************************************/
-
-static int test_lsm_close(TestDb *pTestDb){
- int i;
- int rc = LSM_OK;
- LsmDb *pDb = (LsmDb *)pTestDb;
-
- lsm_csr_close(pDb->pCsr);
- lsm_close(pDb->db);
-
- /* If this is a multi-threaded database, wait on the worker threads. */
- mt_shutdown(pDb);
- for(i=0; i<pDb->nWorker && rc==LSM_OK; i++){
- rc = pDb->aWorker[i].worker_rc;
- }
-
- for(i=0; i<pDb->aFile[0].nSector; i++){
- testFree(pDb->aFile[0].aSector[i].aOld);
- }
- testFree(pDb->aFile[0].aSector);
- for(i=0; i<pDb->aFile[1].nSector; i++){
- testFree(pDb->aFile[1].aSector[i].aOld);
- }
- testFree(pDb->aFile[1].aSector);
-
- memset(pDb, sizeof(LsmDb), 0x11);
- testFree((char *)pDb->pBuf);
- testFree((char *)pDb);
- return rc;
-}
-
-static void mt_signal_worker(LsmDb*, int);
-
-static int waitOnCheckpointer(LsmDb *pDb, lsm_db *db){
- int nSleep = 0;
- int nKB;
- int rc;
-
- do {
- nKB = 0;
- rc = lsm_info(db, LSM_INFO_CHECKPOINT_SIZE, &nKB);
- if( rc!=LSM_OK || nKB<pDb->nMtMaxCkpt ) break;
-#ifdef LSM_MUTEX_PTHREADS
- mt_signal_worker(pDb,
- (pDb->eMode==LSMTEST_MODE_BACKGROUND_CKPT ? 0 : 1)
- );
-#endif
- usleep(5000);
- nSleep += 5;
- }while( 1 );
-
-#if 0
- if( nSleep ) printf("# waitOnCheckpointer(): nSleep=%d\n", nSleep);
-#endif
-
- return rc;
-}
-
-static int waitOnWorker(LsmDb *pDb){
- int rc;
- int nLimit = -1;
- int nSleep = 0;
-
- rc = lsm_config(pDb->db, LSM_CONFIG_AUTOFLUSH, &nLimit);
- do {
- int nOld, nNew, rc2;
- rc2 = lsm_info(pDb->db, LSM_INFO_TREE_SIZE, &nOld, &nNew);
- if( rc2!=LSM_OK ) return rc2;
- if( nOld==0 || nNew<(nLimit/2) ) break;
-#ifdef LSM_MUTEX_PTHREADS
- mt_signal_worker(pDb, 0);
-#endif
- usleep(5000);
- nSleep += 5;
- }while( 1 );
-
-#if 0
- if( nSleep ) printf("# waitOnWorker(): nSleep=%d\n", nSleep);
-#endif
-
- return rc;
-}
-
-static int test_lsm_write(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void *pVal,
- int nVal
-){
- LsmDb *pDb = (LsmDb *)pTestDb;
- int rc = LSM_OK;
-
- if( pDb->eMode==LSMTEST_MODE_BACKGROUND_CKPT ){
- rc = waitOnCheckpointer(pDb, pDb->db);
- }else if(
- pDb->eMode==LSMTEST_MODE_BACKGROUND_WORK
- || pDb->eMode==LSMTEST_MODE_BACKGROUND_BOTH
- ){
- rc = waitOnWorker(pDb);
- }
-
- if( rc==LSM_OK ){
- rc = lsm_insert(pDb->db, pKey, nKey, pVal, nVal);
- }
- return rc;
-}
-
-static int test_lsm_delete(TestDb *pTestDb, void *pKey, int nKey){
- LsmDb *pDb = (LsmDb *)pTestDb;
- return lsm_delete(pDb->db, pKey, nKey);
-}
-
-static int test_lsm_delete_range(
- TestDb *pTestDb,
- void *pKey1, int nKey1,
- void *pKey2, int nKey2
-){
- LsmDb *pDb = (LsmDb *)pTestDb;
- return lsm_delete_range(pDb->db, pKey1, nKey1, pKey2, nKey2);
-}
-
-static int test_lsm_fetch(
- TestDb *pTestDb,
- void *pKey,
- int nKey,
- void **ppVal,
- int *pnVal
-){
- int rc;
- LsmDb *pDb = (LsmDb *)pTestDb;
- lsm_cursor *csr;
-
- if( pKey==0 ) return LSM_OK;
-
- rc = lsm_csr_open(pDb->db, &csr);
- if( rc!=LSM_OK ) return rc;
-
- rc = lsm_csr_seek(csr, pKey, nKey, LSM_SEEK_EQ);
- if( rc==LSM_OK ){
- if( lsm_csr_valid(csr) ){
- const void *pVal; int nVal;
- rc = lsm_csr_value(csr, &pVal, &nVal);
- if( nVal>pDb->nBuf ){
- testFree(pDb->pBuf);
- pDb->pBuf = testMalloc(nVal*2);
- pDb->nBuf = nVal*2;
- }
- memcpy(pDb->pBuf, pVal, nVal);
- *ppVal = pDb->pBuf;
- *pnVal = nVal;
- }else{
- *ppVal = 0;
- *pnVal = -1;
- }
- }
- lsm_csr_close(csr);
- return rc;
-}
-
-static int test_lsm_scan(
- TestDb *pTestDb,
- void *pCtx,
- int bReverse,
- void *pFirst, int nFirst,
- void *pLast, int nLast,
- void (*xCallback)(void *, void *, int , void *, int)
-){
- LsmDb *pDb = (LsmDb *)pTestDb;
- lsm_cursor *csr;
- int rc;
-
- rc = lsm_csr_open(pDb->db, &csr);
- if( rc!=LSM_OK ) return rc;
-
- if( bReverse ){
- if( pLast ){
- rc = lsm_csr_seek(csr, pLast, nLast, LSM_SEEK_LE);
- }else{
- rc = lsm_csr_last(csr);
- }
- }else{
- if( pFirst ){
- rc = lsm_csr_seek(csr, pFirst, nFirst, LSM_SEEK_GE);
- }else{
- rc = lsm_csr_first(csr);
- }
- }
-
- while( rc==LSM_OK && lsm_csr_valid(csr) ){
- const void *pKey; int nKey;
- const void *pVal; int nVal;
- int cmp;
-
- lsm_csr_key(csr, &pKey, &nKey);
- lsm_csr_value(csr, &pVal, &nVal);
-
- if( bReverse && pFirst ){
- cmp = memcmp(pFirst, pKey, MIN(nKey, nFirst));
- if( cmp>0 || (cmp==0 && nFirst>nKey) ) break;
- }else if( bReverse==0 && pLast ){
- cmp = memcmp(pLast, pKey, MIN(nKey, nLast));
- if( cmp<0 || (cmp==0 && nLast<nKey) ) break;
- }
-
- xCallback(pCtx, (void *)pKey, nKey, (void *)pVal, nVal);
-
- if( bReverse ){
- rc = lsm_csr_prev(csr);
- }else{
- rc = lsm_csr_next(csr);
- }
- }
-
- lsm_csr_close(csr);
- return rc;
-}
-
-static int test_lsm_begin(TestDb *pTestDb, int iLevel){
- int rc = LSM_OK;
- LsmDb *pDb = (LsmDb *)pTestDb;
-
- /* iLevel==0 is a no-op. */
- if( iLevel==0 ) return 0;
-
- if( pDb->pCsr==0 ) rc = lsm_csr_open(pDb->db, &pDb->pCsr);
- if( rc==LSM_OK && iLevel>1 ){
- rc = lsm_begin(pDb->db, iLevel-1);
- }
-
- return rc;
-}
-static int test_lsm_commit(TestDb *pTestDb, int iLevel){
- LsmDb *pDb = (LsmDb *)pTestDb;
-
- /* If iLevel==0, close any open read transaction */
- if( iLevel==0 && pDb->pCsr ){
- lsm_csr_close(pDb->pCsr);
- pDb->pCsr = 0;
- }
-
- /* If iLevel==0, close any open read transaction */
- return lsm_commit(pDb->db, MAX(0, iLevel-1));
-}
-static int test_lsm_rollback(TestDb *pTestDb, int iLevel){
- LsmDb *pDb = (LsmDb *)pTestDb;
-
- /* If iLevel==0, close any open read transaction */
- if( iLevel==0 && pDb->pCsr ){
- lsm_csr_close(pDb->pCsr);
- pDb->pCsr = 0;
- }
-
- return lsm_rollback(pDb->db, MAX(0, iLevel-1));
-}
-
-/*
-** A log message callback registered with lsm connections. Prints all
-** messages to stderr.
-*/
-static void xLog(void *pCtx, int rc, const char *z){
- unused_parameter(rc);
- /* fprintf(stderr, "lsm: rc=%d \"%s\"\n", rc, z); */
- if( pCtx ) fprintf(stderr, "%s: ", (char *)pCtx);
- fprintf(stderr, "%s\n", z);
- fflush(stderr);
-}
-
-static void xWorkHook(lsm_db *db, void *pArg){
- LsmDb *p = (LsmDb *)pArg;
- if( p->xWork ) p->xWork(db, p->pWorkCtx);
-}
-
-#define TEST_NO_RECOVERY -1
-#define TEST_COMPRESSION -3
-
-#define TEST_MT_MODE -2
-#define TEST_MT_MIN_CKPT -4
-#define TEST_MT_MAX_CKPT -5
-
-int test_lsm_config_str(
- LsmDb *pLsm,
- lsm_db *db,
- int bWorker,
- const char *zStr,
- int *pnThread
-){
- struct CfgParam {
- const char *zParam;
- int bWorker;
- int eParam;
- } aParam[] = {
- { "autoflush", 0, LSM_CONFIG_AUTOFLUSH },
- { "page_size", 0, LSM_CONFIG_PAGE_SIZE },
- { "block_size", 0, LSM_CONFIG_BLOCK_SIZE },
- { "safety", 0, LSM_CONFIG_SAFETY },
- { "autowork", 0, LSM_CONFIG_AUTOWORK },
- { "autocheckpoint", 0, LSM_CONFIG_AUTOCHECKPOINT },
- { "mmap", 0, LSM_CONFIG_MMAP },
- { "use_log", 0, LSM_CONFIG_USE_LOG },
- { "automerge", 0, LSM_CONFIG_AUTOMERGE },
- { "max_freelist", 0, LSM_CONFIG_MAX_FREELIST },
- { "multi_proc", 0, LSM_CONFIG_MULTIPLE_PROCESSES },
- { "worker_automerge", 1, LSM_CONFIG_AUTOMERGE },
- { "test_no_recovery", 0, TEST_NO_RECOVERY },
- { "bg_min_ckpt", 0, TEST_NO_RECOVERY },
-
- { "mt_mode", 0, TEST_MT_MODE },
- { "mt_min_ckpt", 0, TEST_MT_MIN_CKPT },
- { "mt_max_ckpt", 0, TEST_MT_MAX_CKPT },
-
-#ifdef HAVE_ZLIB
- { "compression", 0, TEST_COMPRESSION },
-#endif
- { 0, 0 }
- };
- const char *z = zStr;
- int nThread = 1;
-
- if( zStr==0 ) return 0;
-
- assert( db );
- while( z[0] ){
- const char *zStart;
-
- /* Skip whitespace */
- while( *z==' ' ) z++;
- zStart = z;
-
- while( *z && *z!='=' ) z++;
- if( *z ){
- int eParam;
- int i;
- int iVal;
- int iMul = 1;
- int rc;
- char zParam[32];
- int nParam = z-zStart;
- if( nParam==0 || nParam>sizeof(zParam)-1 ) goto syntax_error;
-
- memcpy(zParam, zStart, nParam);
- zParam[nParam] = '\0';
- rc = testArgSelect(aParam, "param", zParam, &i);
- if( rc!=0 ) return rc;
- eParam = aParam[i].eParam;
-
- z++;
- zStart = z;
- while( *z>='0' && *z<='9' ) z++;
- if( *z=='k' || *z=='K' ){
- iMul = 1;
- z++;
- }else if( *z=='M' || *z=='M' ){
- iMul = 1024;
- z++;
- }
- nParam = z-zStart;
- if( nParam==0 || nParam>sizeof(zParam)-1 ) goto syntax_error;
- memcpy(zParam, zStart, nParam);
- zParam[nParam] = '\0';
- iVal = atoi(zParam) * iMul;
-
- if( eParam>0 ){
- if( bWorker || aParam[i].bWorker==0 ){
- lsm_config(db, eParam, &iVal);
- }
- }else{
- switch( eParam ){
- case TEST_NO_RECOVERY:
- if( pLsm ) pLsm->bNoRecovery = iVal;
- break;
- case TEST_MT_MODE:
- if( pLsm ) nThread = iVal;
- break;
- case TEST_MT_MIN_CKPT:
- if( pLsm && iVal>0 ) pLsm->nMtMinCkpt = iVal*1024;
- break;
- case TEST_MT_MAX_CKPT:
- if( pLsm && iVal>0 ) pLsm->nMtMaxCkpt = iVal*1024;
- break;
-#ifdef HAVE_ZLIB
- case TEST_COMPRESSION:
- testConfigureCompression(db);
- break;
-#endif
- }
- }
- }else if( z!=zStart ){
- goto syntax_error;
- }
- }
-
- if( pnThread ) *pnThread = nThread;
- if( pLsm && pLsm->nMtMaxCkpt < pLsm->nMtMinCkpt ){
- pLsm->nMtMinCkpt = pLsm->nMtMaxCkpt;
- }
-
- return 0;
- syntax_error:
- testPrintError("syntax error at: \"%s\"\n", z);
- return 1;
-}
-
-int tdb_lsm_config_str(TestDb *pDb, const char *zStr){
- int rc = 0;
- if( tdb_lsm(pDb) ){
-#ifdef LSM_MUTEX_PTHREADS
- int i;
-#endif
- LsmDb *pLsm = (LsmDb *)pDb;
-
- rc = test_lsm_config_str(pLsm, pLsm->db, 0, zStr, 0);
-#ifdef LSM_MUTEX_PTHREADS
- for(i=0; rc==0 && i<pLsm->nWorker; i++){
- rc = test_lsm_config_str(0, pLsm->aWorker[i].pWorker, 1, zStr, 0);
- }
-#endif
- }
- return rc;
-}
-
-int tdb_lsm_configure(lsm_db *db, const char *zConfig){
- return test_lsm_config_str(0, db, 0, zConfig, 0);
-}
-
-static int testLsmStartWorkers(LsmDb *, int, const char *, const char *);
-
-static int testLsmOpen(
- const char *zCfg,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- static const DatabaseMethods LsmMethods = {
- test_lsm_close,
- test_lsm_write,
- test_lsm_delete,
- test_lsm_delete_range,
- test_lsm_fetch,
- test_lsm_scan,
- test_lsm_begin,
- test_lsm_commit,
- test_lsm_rollback
- };
-
- int rc;
- int nFilename;
- LsmDb *pDb;
-
- /* If the bClear flag is set, delete any existing database. */
- assert( zFilename);
- if( bClear ) testDeleteLsmdb(zFilename);
- nFilename = strlen(zFilename);
-
- pDb = (LsmDb *)testMalloc(sizeof(LsmDb) + nFilename + 1);
- memset(pDb, 0, sizeof(LsmDb));
- pDb->base.pMethods = &LsmMethods;
- pDb->zName = (char *)&pDb[1];
- memcpy(pDb->zName, zFilename, nFilename + 1);
-
- /* Default the sector size used for crash simulation to 512 bytes.
- ** Todo: There should be an OS method to obtain this value - just as
- ** there is in SQLite. For now, LSM assumes that it is smaller than
- ** the page size (default 4KB).
- */
- pDb->szSector = 256;
-
- /* Default values for the mt_min_ckpt and mt_max_ckpt parameters. */
- pDb->nMtMinCkpt = LSMTEST_DFLT_MT_MIN_CKPT;
- pDb->nMtMaxCkpt = LSMTEST_DFLT_MT_MAX_CKPT;
-
- memcpy(&pDb->env, tdb_lsm_env(), sizeof(lsm_env));
- pDb->env.pVfsCtx = (void *)pDb;
- pDb->env.xFullpath = testEnvFullpath;
- pDb->env.xOpen = testEnvOpen;
- pDb->env.xRead = testEnvRead;
- pDb->env.xWrite = testEnvWrite;
- pDb->env.xTruncate = testEnvTruncate;
- pDb->env.xSync = testEnvSync;
- pDb->env.xSectorSize = testEnvSectorSize;
- pDb->env.xRemap = testEnvRemap;
- pDb->env.xFileid = testEnvFileid;
- pDb->env.xClose = testEnvClose;
- pDb->env.xUnlink = testEnvUnlink;
- pDb->env.xLock = testEnvLock;
- pDb->env.xTestLock = testEnvTestLock;
- pDb->env.xShmBarrier = testEnvShmBarrier;
- pDb->env.xShmMap = testEnvShmMap;
- pDb->env.xShmUnmap = testEnvShmUnmap;
- pDb->env.xSleep = testEnvSleep;
-
- rc = lsm_new(&pDb->env, &pDb->db);
- if( rc==LSM_OK ){
- int nThread = 1;
- lsm_config_log(pDb->db, xLog, 0);
- lsm_config_work_hook(pDb->db, xWorkHook, (void *)pDb);
-
- rc = test_lsm_config_str(pDb, pDb->db, 0, zCfg, &nThread);
- if( rc==LSM_OK ) rc = lsm_open(pDb->db, zFilename);
-
- pDb->eMode = nThread;
-#ifdef LSM_MUTEX_PTHREADS
- if( rc==LSM_OK && nThread>1 ){
- testLsmStartWorkers(pDb, nThread, zFilename, zCfg);
- }
-#endif
-
- if( rc!=LSM_OK ){
- test_lsm_close((TestDb *)pDb);
- pDb = 0;
- }
- }
-
- *ppDb = (TestDb *)pDb;
- return rc;
-}
-
-int test_lsm_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- return testLsmOpen(zSpec, zFilename, bClear, ppDb);
-}
-
-int test_lsm_small_open(
- const char *zSpec,
- const char *zFile,
- int bClear,
- TestDb **ppDb
-){
- const char *zCfg = "page_size=256 block_size=64 mmap=1024";
- return testLsmOpen(zCfg, zFile, bClear, ppDb);
-}
-
-int test_lsm_lomem_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- /* "max_freelist=4 autocheckpoint=32" */
- const char *zCfg =
- "page_size=256 block_size=64 autoflush=16 "
- "autocheckpoint=32"
- "mmap=0 "
- ;
- return testLsmOpen(zCfg, zFilename, bClear, ppDb);
-}
-
-int test_lsm_lomem2_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- /* "max_freelist=4 autocheckpoint=32" */
- const char *zCfg =
- "page_size=512 block_size=64 autoflush=0 mmap=0 "
- ;
- return testLsmOpen(zCfg, zFilename, bClear, ppDb);
-}
-
-int test_lsm_zip_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- const char *zCfg =
- "page_size=256 block_size=64 autoflush=16 "
- "autocheckpoint=32 compression=1 mmap=0 "
- ;
- return testLsmOpen(zCfg, zFilename, bClear, ppDb);
-}
-
-lsm_db *tdb_lsm(TestDb *pDb){
- if( pDb->pMethods->xClose==test_lsm_close ){
- return ((LsmDb *)pDb)->db;
- }
- return 0;
-}
-
-int tdb_lsm_multithread(TestDb *pDb){
- int ret = 0;
- if( tdb_lsm(pDb) ){
- ret = ((LsmDb*)pDb)->eMode!=LSMTEST_MODE_SINGLETHREAD;
- }
- return ret;
-}
-
-void tdb_lsm_enable_log(TestDb *pDb, int bEnable){
- lsm_db *db = tdb_lsm(pDb);
- if( db ){
- lsm_config_log(db, (bEnable ? xLog : 0), (void *)"client");
- }
-}
-
-void tdb_lsm_application_crash(TestDb *pDb){
- if( tdb_lsm(pDb) ){
- LsmDb *p = (LsmDb *)pDb;
- p->bCrashed = 1;
- }
-}
-
-void tdb_lsm_prepare_system_crash(TestDb *pDb){
- if( tdb_lsm(pDb) ){
- LsmDb *p = (LsmDb *)pDb;
- p->bPrepareCrash = 1;
- }
-}
-
-void tdb_lsm_system_crash(TestDb *pDb){
- if( tdb_lsm(pDb) ){
- LsmDb *p = (LsmDb *)pDb;
- p->bCrashed = 1;
- doSystemCrash(p);
- }
-}
-
-void tdb_lsm_safety(TestDb *pDb, int eMode){
- assert( eMode==LSM_SAFETY_OFF
- || eMode==LSM_SAFETY_NORMAL
- || eMode==LSM_SAFETY_FULL
- );
- if( tdb_lsm(pDb) ){
- int iParam = eMode;
- LsmDb *p = (LsmDb *)pDb;
- lsm_config(p->db, LSM_CONFIG_SAFETY, &iParam);
- }
-}
-
-void tdb_lsm_prepare_sync_crash(TestDb *pDb, int iSync){
- assert( iSync>0 );
- if( tdb_lsm(pDb) ){
- LsmDb *p = (LsmDb *)pDb;
- p->nAutoCrash = iSync;
- p->bPrepareCrash = 1;
- }
-}
-
-void tdb_lsm_config_work_hook(
- TestDb *pDb,
- void (*xWork)(lsm_db *, void *),
- void *pWorkCtx
-){
- if( tdb_lsm(pDb) ){
- LsmDb *p = (LsmDb *)pDb;
- p->xWork = xWork;
- p->pWorkCtx = pWorkCtx;
- }
-}
-
-void tdb_lsm_write_hook(
- TestDb *pDb,
- void (*xWrite)(void *, int, lsm_i64, int, int),
- void *pWriteCtx
-){
- if( tdb_lsm(pDb) ){
- LsmDb *p = (LsmDb *)pDb;
- p->xWriteHook = xWrite;
- p->pWriteCtx = pWriteCtx;
- }
-}
-
-int tdb_lsm_open(const char *zCfg, const char *zDb, int bClear, TestDb **ppDb){
- return testLsmOpen(zCfg, zDb, bClear, ppDb);
-}
-
-#ifdef LSM_MUTEX_PTHREADS
-
-/*
-** Signal worker thread iWorker that there may be work to do.
-*/
-static void mt_signal_worker(LsmDb *pDb, int iWorker){
- LsmWorker *p = &pDb->aWorker[iWorker];
- pthread_mutex_lock(&p->worker_mutex);
- p->bDoWork = 1;
- pthread_cond_signal(&p->worker_cond);
- pthread_mutex_unlock(&p->worker_mutex);
-}
-
-/*
-** This routine is used as the main() for all worker threads.
-*/
-static void *worker_main(void *pArg){
- LsmWorker *p = (LsmWorker *)pArg;
- lsm_db *pWorker; /* Connection to access db through */
-
- pthread_mutex_lock(&p->worker_mutex);
- while( (pWorker = p->pWorker) ){
- int rc = LSM_OK;
-
- /* Do some work. If an error occurs, exit. */
-
- pthread_mutex_unlock(&p->worker_mutex);
- if( p->eType==LSMTEST_THREAD_CKPT ){
- int nKB = 0;
- rc = lsm_info(pWorker, LSM_INFO_CHECKPOINT_SIZE, &nKB);
- if( rc==LSM_OK && nKB>=p->pDb->nMtMinCkpt ){
- rc = lsm_checkpoint(pWorker, 0);
- }
- }else{
- int nWrite;
- do {
-
- if( p->eType==LSMTEST_THREAD_WORKER ){
- waitOnCheckpointer(p->pDb, pWorker);
- }
-
- nWrite = 0;
- rc = lsm_work(pWorker, 0, 256, &nWrite);
-
- if( p->eType==LSMTEST_THREAD_WORKER && nWrite ){
- mt_signal_worker(p->pDb, 1);
- }
- }while( nWrite && p->pWorker );
- }
- pthread_mutex_lock(&p->worker_mutex);
-
- if( rc!=LSM_OK && rc!=LSM_BUSY ){
- p->worker_rc = rc;
- break;
- }
-
- /* The thread will wake up when it is signaled either because another
- ** thread has created some work for this one or because the connection
- ** is being closed. */
- if( p->pWorker && p->bDoWork==0 ){
- pthread_cond_wait(&p->worker_cond, &p->worker_mutex);
- }
- p->bDoWork = 0;
- }
- pthread_mutex_unlock(&p->worker_mutex);
-
- return 0;
-}
-
-
-static void mt_stop_worker(LsmDb *pDb, int iWorker){
- LsmWorker *p = &pDb->aWorker[iWorker];
- if( p->pWorker ){
- void *pDummy;
- lsm_db *pWorker;
-
- /* Signal the worker to stop */
- pthread_mutex_lock(&p->worker_mutex);
- pWorker = p->pWorker;
- p->pWorker = 0;
- pthread_cond_signal(&p->worker_cond);
- pthread_mutex_unlock(&p->worker_mutex);
-
- /* Join the worker thread. */
- pthread_join(p->worker_thread, &pDummy);
-
- /* Free resources allocated in mt_start_worker() */
- pthread_cond_destroy(&p->worker_cond);
- pthread_mutex_destroy(&p->worker_mutex);
- lsm_close(pWorker);
- }
-}
-
-static void mt_shutdown(LsmDb *pDb){
- int i;
- for(i=0; i<pDb->nWorker; i++){
- mt_stop_worker(pDb, i);
- }
-}
-
-/*
-** This callback is invoked by LSM when the client database writes to
-** the database file (i.e. to flush the contents of the in-memory tree).
-** This implies there may be work to do on the database, so signal
-** the worker threads.
-*/
-static void mt_client_work_hook(lsm_db *db, void *pArg){
- LsmDb *pDb = (LsmDb *)pArg; /* LsmDb database handle */
-
- /* Invoke the user level work-hook, if any. */
- if( pDb->xWork ) pDb->xWork(db, pDb->pWorkCtx);
-
- /* Wake up worker thread 0. */
- mt_signal_worker(pDb, 0);
-}
-
-static void mt_worker_work_hook(lsm_db *db, void *pArg){
- LsmDb *pDb = (LsmDb *)pArg; /* LsmDb database handle */
-
- /* Invoke the user level work-hook, if any. */
- if( pDb->xWork ) pDb->xWork(db, pDb->pWorkCtx);
-}
-
-/*
-** Launch worker thread iWorker for database connection pDb.
-*/
-static int mt_start_worker(
- LsmDb *pDb, /* Main database structure */
- int iWorker, /* Worker number to start */
- const char *zFilename, /* File name of database to open */
- const char *zCfg, /* Connection configuration string */
- int eType /* Type of worker thread */
-){
- int rc = 0; /* Return code */
- LsmWorker *p; /* Object to initialize */
-
- assert( iWorker<pDb->nWorker );
- assert( eType==LSMTEST_THREAD_CKPT
- || eType==LSMTEST_THREAD_WORKER
- || eType==LSMTEST_THREAD_WORKER_AC
- );
-
- p = &pDb->aWorker[iWorker];
- p->eType = eType;
- p->pDb = pDb;
-
- /* Open the worker connection */
- if( rc==0 ) rc = lsm_new(&pDb->env, &p->pWorker);
- if( zCfg ){
- test_lsm_config_str(pDb, p->pWorker, 1, zCfg, 0);
- }
- if( rc==0 ) rc = lsm_open(p->pWorker, zFilename);
- lsm_config_log(p->pWorker, xLog, (void *)"worker");
-
- /* Configure the work-hook */
- if( rc==0 ){
- lsm_config_work_hook(p->pWorker, mt_worker_work_hook, (void *)pDb);
- }
-
- if( eType==LSMTEST_THREAD_WORKER ){
- test_lsm_config_str(0, p->pWorker, 1, "autocheckpoint=0", 0);
- }
-
- /* Kick off the worker thread. */
- if( rc==0 ) rc = pthread_cond_init(&p->worker_cond, 0);
- if( rc==0 ) rc = pthread_mutex_init(&p->worker_mutex, 0);
- if( rc==0 ) rc = pthread_create(&p->worker_thread, 0, worker_main, (void *)p);
-
- return rc;
-}
-
-
-static int testLsmStartWorkers(
- LsmDb *pDb, int eModel, const char *zFilename, const char *zCfg
-){
- int rc;
-
- if( eModel<1 || eModel>4 ) return 1;
- if( eModel==1 ) return 0;
-
- /* Configure a work-hook for the client connection. Worker 0 is signalled
- ** every time the users connection writes to the database. */
- lsm_config_work_hook(pDb->db, mt_client_work_hook, (void *)pDb);
-
- /* Allocate space for two worker connections. They may not both be
- ** used, but both are allocated. */
- pDb->aWorker = (LsmWorker *)testMalloc(sizeof(LsmWorker) * 2);
- memset(pDb->aWorker, 0, sizeof(LsmWorker) * 2);
-
- switch( eModel ){
- case LSMTEST_MODE_BACKGROUND_CKPT:
- pDb->nWorker = 1;
- test_lsm_config_str(0, pDb->db, 0, "autocheckpoint=0", 0);
- rc = mt_start_worker(pDb, 0, zFilename, zCfg, LSMTEST_THREAD_CKPT);
- break;
-
- case LSMTEST_MODE_BACKGROUND_WORK:
- pDb->nWorker = 1;
- test_lsm_config_str(0, pDb->db, 0, "autowork=0", 0);
- rc = mt_start_worker(pDb, 0, zFilename, zCfg, LSMTEST_THREAD_WORKER_AC);
- break;
-
- case LSMTEST_MODE_BACKGROUND_BOTH:
- pDb->nWorker = 2;
- test_lsm_config_str(0, pDb->db, 0, "autowork=0", 0);
- rc = mt_start_worker(pDb, 0, zFilename, zCfg, LSMTEST_THREAD_WORKER);
- if( rc==0 ){
- rc = mt_start_worker(pDb, 1, zFilename, zCfg, LSMTEST_THREAD_CKPT);
- }
- break;
- }
-
- return rc;
-}
-
-
-int test_lsm_mt2(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- const char *zCfg = "mt_mode=2";
- return testLsmOpen(zCfg, zFilename, bClear, ppDb);
-}
-
-int test_lsm_mt3(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- const char *zCfg = "mt_mode=4";
- return testLsmOpen(zCfg, zFilename, bClear, ppDb);
-}
-
-#else
-static void mt_shutdown(LsmDb *pDb) {
- unused_parameter(pDb);
-}
-int test_lsm_mt(const char *zFilename, int bClear, TestDb **ppDb){
- unused_parameter(zFilename);
- unused_parameter(bClear);
- unused_parameter(ppDb);
- testPrintError("threads unavailable - recompile with LSM_MUTEX_PTHREADS\n");
- return 1;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb4.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb4.c
deleted file mode 100644
index c45b0529abd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_tdb4.c
+++ /dev/null
@@ -1,982 +0,0 @@
-
-/*
-** This file contains the TestDb bt wrapper.
-*/
-
-#include "lsmtest_tdb.h"
-#include "lsmtest.h"
-#include <unistd.h>
-#include "bt.h"
-
-#include <pthread.h>
-
-typedef struct BtDb BtDb;
-typedef struct BtFile BtFile;
-
-/* Background checkpointer interface (see implementations below). */
-typedef struct bt_ckpter bt_ckpter;
-static int bgc_attach(BtDb *pDb, const char*);
-static int bgc_detach(BtDb *pDb);
-
-/*
-** Each database or log file opened by a database handle is wrapped by
-** an object of the following type.
-*/
-struct BtFile {
- BtDb *pBt; /* Database handle that opened this file */
- bt_env *pVfs; /* Underlying VFS */
- bt_file *pFile; /* File handle belonging to underlying VFS */
- int nSectorSize; /* Size of sectors in bytes */
- int nSector; /* Allocated size of nSector array */
- u8 **apSector; /* Original sector data */
-};
-
-/*
-** nCrashSync:
-** If this value is non-zero, then a "crash-test" is running. If
-** nCrashSync==1, then the crash is simulated during the very next
-** call to the xSync() VFS method (on either the db or log file).
-** If nCrashSync==2, the following call to xSync(), and so on.
-**
-** bCrash:
-** After a crash is simulated, this variable is set. Any subsequent
-** attempts to write to a file or modify the file system in any way
-** fail once this is set. All the caller can do is close the connection.
-**
-** bFastInsert:
-** If this variable is set to true, then a BT_CONTROL_FAST_INSERT_OP
-** control is issued before each callto BtReplace() or BtCsrOpen().
-*/
-struct BtDb {
- TestDb base; /* Base class */
- bt_db *pBt; /* bt database handle */
- sqlite4_env *pEnv; /* SQLite environment (for malloc/free) */
- bt_env *pVfs; /* Underlying VFS */
- int bFastInsert; /* True to use fast-insert */
-
- /* Space for bt_fetch() results */
- u8 *aBuffer; /* Space to store results */
- int nBuffer; /* Allocated size of aBuffer[] in bytes */
- int nRef;
-
- /* Background checkpointer used by mt connections */
- bt_ckpter *pCkpter;
-
- /* Stuff used for crash test simulation */
- BtFile *apFile[2]; /* Database and log files used by pBt */
- bt_env env; /* Private VFS for this object */
- int nCrashSync; /* Number of syncs until crash (see above) */
- int bCrash; /* True once a crash has been simulated */
-};
-
-static int btVfsFullpath(
- sqlite4_env *pEnv,
- bt_env *pVfs,
- const char *z,
- char **pzOut
-){
- BtDb *pBt = (BtDb*)pVfs->pVfsCtx;
- if( pBt->bCrash ) return SQLITE4_IOERR;
- return pBt->pVfs->xFullpath(pEnv, pBt->pVfs, z, pzOut);
-}
-
-static int btVfsOpen(
- sqlite4_env *pEnv,
- bt_env *pVfs,
- const char *zFile,
- int flags, bt_file **ppFile
-){
- BtFile *p;
- BtDb *pBt = (BtDb*)pVfs->pVfsCtx;
- int rc;
-
- if( pBt->bCrash ) return SQLITE4_IOERR;
-
- p = (BtFile*)testMalloc(sizeof(BtFile));
- if( !p ) return SQLITE4_NOMEM;
- if( flags & BT_OPEN_DATABASE ){
- pBt->apFile[0] = p;
- }else if( flags & BT_OPEN_LOG ){
- pBt->apFile[1] = p;
- }
- if( (flags & BT_OPEN_SHARED)==0 ){
- p->pBt = pBt;
- }
- p->pVfs = pBt->pVfs;
-
- rc = pBt->pVfs->xOpen(pEnv, pVfs, zFile, flags, &p->pFile);
- if( rc!=SQLITE4_OK ){
- testFree(p);
- p = 0;
- }else{
- pBt->nRef++;
- }
-
- *ppFile = (bt_file*)p;
- return rc;
-}
-
-static int btVfsSize(bt_file *pFile, sqlite4_int64 *piRes){
- BtFile *p = (BtFile*)pFile;
- if( p->pBt && p->pBt->bCrash ) return SQLITE4_IOERR;
- return p->pVfs->xSize(p->pFile, piRes);
-}
-
-static int btVfsRead(bt_file *pFile, sqlite4_int64 iOff, void *pBuf, int nBuf){
- BtFile *p = (BtFile*)pFile;
- if( p->pBt && p->pBt->bCrash ) return SQLITE4_IOERR;
- return p->pVfs->xRead(p->pFile, iOff, pBuf, nBuf);
-}
-
-static int btFlushSectors(BtFile *p, int iFile){
- sqlite4_int64 iSz;
- int rc;
- int i;
- u8 *aTmp = 0;
-
- rc = p->pBt->pVfs->xSize(p->pFile, &iSz);
- for(i=0; rc==SQLITE4_OK && i<p->nSector; i++){
- if( p->pBt->bCrash && p->apSector[i] ){
-
- /* The system is simulating a crash. There are three choices for
- ** this sector:
- **
- ** 1) Leave it as it is (simulating a successful write),
- ** 2) Restore the original data (simulating a lost write),
- ** 3) Populate the disk sector with garbage data.
- */
- sqlite4_int64 iSOff = p->nSectorSize*i;
- int nWrite = MIN(p->nSectorSize, iSz - iSOff);
-
- if( nWrite ){
- u8 *aWrite = 0;
- int iOpt = (testPrngValue(i) % 3) + 1;
- if( iOpt==1 ){
- aWrite = p->apSector[i];
- }else if( iOpt==3 ){
- if( aTmp==0 ) aTmp = testMalloc(p->nSectorSize);
- aWrite = aTmp;
- testPrngArray(i*13, (u32*)aWrite, nWrite/sizeof(u32));
- }
-
-#if 0
-fprintf(stderr, "handle sector %d of %s with %s\n", i,
- iFile==0 ? "db" : "log",
- iOpt==1 ? "rollback" : iOpt==2 ? "write" : "omit"
-);
-fflush(stderr);
-#endif
-
- if( aWrite ){
- rc = p->pBt->pVfs->xWrite(p->pFile, iSOff, aWrite, nWrite);
- }
- }
- }
- testFree(p->apSector[i]);
- p->apSector[i] = 0;
- }
-
- testFree(aTmp);
- return rc;
-}
-
-static int btSaveSectors(BtFile *p, sqlite4_int64 iOff, int nBuf){
- int rc;
- sqlite4_int64 iSz; /* Size of file on disk */
- int iFirst; /* First sector affected */
- int iSector; /* Current sector */
- int iLast; /* Last sector affected */
-
- if( p->nSectorSize==0 ){
- p->nSectorSize = p->pBt->pVfs->xSectorSize(p->pFile);
- if( p->nSectorSize<512 ) p->nSectorSize = 512;
- }
- iLast = (iOff+nBuf-1) / p->nSectorSize;
- iFirst = iOff / p->nSectorSize;
-
- rc = p->pBt->pVfs->xSize(p->pFile, &iSz);
- for(iSector=iFirst; rc==SQLITE4_OK && iSector<=iLast; iSector++){
- int nRead;
- sqlite4_int64 iSOff = iSector * p->nSectorSize;
- u8 *aBuf = testMalloc(p->nSectorSize);
- nRead = MIN(p->nSectorSize, (iSz - iSOff));
- if( nRead>0 ){
- rc = p->pBt->pVfs->xRead(p->pFile, iSOff, aBuf, nRead);
- }
-
- while( rc==SQLITE4_OK && iSector>=p->nSector ){
- int nNew = p->nSector + 32;
- u8 **apNew = (u8**)testMalloc(nNew * sizeof(u8*));
- memcpy(apNew, p->apSector, p->nSector*sizeof(u8*));
- testFree(p->apSector);
- p->apSector = apNew;
- p->nSector = nNew;
- }
-
- p->apSector[iSector] = aBuf;
- }
-
- return rc;
-}
-
-static int btVfsWrite(bt_file *pFile, sqlite4_int64 iOff, void *pBuf, int nBuf){
- BtFile *p = (BtFile*)pFile;
- if( p->pBt && p->pBt->bCrash ) return SQLITE4_IOERR;
- if( p->pBt && p->pBt->nCrashSync ){
- btSaveSectors(p, iOff, nBuf);
- }
- return p->pVfs->xWrite(p->pFile, iOff, pBuf, nBuf);
-}
-
-static int btVfsTruncate(bt_file *pFile, sqlite4_int64 iOff){
- BtFile *p = (BtFile*)pFile;
- if( p->pBt && p->pBt->bCrash ) return SQLITE4_IOERR;
- return p->pVfs->xTruncate(p->pFile, iOff);
-}
-
-static int btVfsSync(bt_file *pFile){
- int rc = SQLITE4_OK;
- BtFile *p = (BtFile*)pFile;
- BtDb *pBt = p->pBt;
-
- if( pBt ){
- if( pBt->bCrash ) return SQLITE4_IOERR;
- if( pBt->nCrashSync ){
- pBt->nCrashSync--;
- pBt->bCrash = (pBt->nCrashSync==0);
- if( pBt->bCrash ){
- btFlushSectors(pBt->apFile[0], 0);
- btFlushSectors(pBt->apFile[1], 1);
- rc = SQLITE4_IOERR;
- }else{
- btFlushSectors(p, 0);
- }
- }
- }
-
- if( rc==SQLITE4_OK ){
- rc = p->pVfs->xSync(p->pFile);
- }
- return rc;
-}
-
-static int btVfsSectorSize(bt_file *pFile){
- BtFile *p = (BtFile*)pFile;
- return p->pVfs->xSectorSize(p->pFile);
-}
-
-static void btDeref(BtDb *p){
- p->nRef--;
- assert( p->nRef>=0 );
- if( p->nRef<=0 ) testFree(p);
-}
-
-static int btVfsClose(bt_file *pFile){
- BtFile *p = (BtFile*)pFile;
- BtDb *pBt = p->pBt;
- int rc;
- if( pBt ){
- btFlushSectors(p, 0);
- if( p==pBt->apFile[0] ) pBt->apFile[0] = 0;
- if( p==pBt->apFile[1] ) pBt->apFile[1] = 0;
- }
- testFree(p->apSector);
- rc = p->pVfs->xClose(p->pFile);
-#if 0
- btDeref(p->pBt);
-#endif
- testFree(p);
- return rc;
-}
-
-static int btVfsUnlink(sqlite4_env *pEnv, bt_env *pVfs, const char *zFile){
- BtDb *pBt = (BtDb*)pVfs->pVfsCtx;
- if( pBt->bCrash ) return SQLITE4_IOERR;
- return pBt->pVfs->xUnlink(pEnv, pBt->pVfs, zFile);
-}
-
-static int btVfsLock(bt_file *pFile, int iLock, int eType){
- BtFile *p = (BtFile*)pFile;
- if( p->pBt && p->pBt->bCrash ) return SQLITE4_IOERR;
- return p->pVfs->xLock(p->pFile, iLock, eType);
-}
-
-static int btVfsTestLock(bt_file *pFile, int iLock, int nLock, int eType){
- BtFile *p = (BtFile*)pFile;
- if( p->pBt && p->pBt->bCrash ) return SQLITE4_IOERR;
- return p->pVfs->xTestLock(p->pFile, iLock, nLock, eType);
-}
-
-static int btVfsShmMap(bt_file *pFile, int iChunk, int sz, void **ppOut){
- BtFile *p = (BtFile*)pFile;
- if( p->pBt && p->pBt->bCrash ) return SQLITE4_IOERR;
- return p->pVfs->xShmMap(p->pFile, iChunk, sz, ppOut);
-}
-
-static void btVfsShmBarrier(bt_file *pFile){
- BtFile *p = (BtFile*)pFile;
- return p->pVfs->xShmBarrier(p->pFile);
-}
-
-static int btVfsShmUnmap(bt_file *pFile, int bDelete){
- BtFile *p = (BtFile*)pFile;
- if( p->pBt && p->pBt->bCrash ) return SQLITE4_IOERR;
- return p->pVfs->xShmUnmap(p->pFile, bDelete);
-}
-
-static int bt_close(TestDb *pTestDb){
- BtDb *p = (BtDb*)pTestDb;
- int rc = sqlite4BtClose(p->pBt);
- free(p->aBuffer);
- if( p->apFile[0] ) p->apFile[0]->pBt = 0;
- if( p->apFile[1] ) p->apFile[1]->pBt = 0;
- bgc_detach(p);
- testFree(p);
- return rc;
-}
-
-static int btMinTransaction(BtDb *p, int iMin, int *piLevel){
- int iLevel;
- int rc = SQLITE4_OK;
-
- iLevel = sqlite4BtTransactionLevel(p->pBt);
- if( iLevel<iMin ){
- rc = sqlite4BtBegin(p->pBt, iMin);
- *piLevel = iLevel;
- }else{
- *piLevel = -1;
- }
-
- return rc;
-}
-static int btRestoreTransaction(BtDb *p, int iLevel, int rcin){
- int rc = rcin;
- if( iLevel>=0 ){
- if( rc==SQLITE4_OK ){
- rc = sqlite4BtCommit(p->pBt, iLevel);
- }else{
- sqlite4BtRollback(p->pBt, iLevel);
- }
- assert( iLevel==sqlite4BtTransactionLevel(p->pBt) );
- }
- return rc;
-}
-
-static int bt_write(TestDb *pTestDb, void *pK, int nK, void *pV, int nV){
- BtDb *p = (BtDb*)pTestDb;
- int iLevel;
- int rc;
-
- rc = btMinTransaction(p, 2, &iLevel);
- if( rc==SQLITE4_OK ){
- if( p->bFastInsert ) sqlite4BtControl(p->pBt, BT_CONTROL_FAST_INSERT_OP, 0);
- rc = sqlite4BtReplace(p->pBt, pK, nK, pV, nV);
- rc = btRestoreTransaction(p, iLevel, rc);
- }
- return rc;
-}
-
-static int bt_delete(TestDb *pTestDb, void *pK, int nK){
- return bt_write(pTestDb, pK, nK, 0, -1);
-}
-
-static int bt_delete_range(
- TestDb *pTestDb,
- void *pKey1, int nKey1,
- void *pKey2, int nKey2
-){
- BtDb *p = (BtDb*)pTestDb;
- bt_cursor *pCsr = 0;
- int rc = SQLITE4_OK;
- int iLevel;
-
- rc = btMinTransaction(p, 2, &iLevel);
- if( rc==SQLITE4_OK ){
- if( p->bFastInsert ) sqlite4BtControl(p->pBt, BT_CONTROL_FAST_INSERT_OP, 0);
- rc = sqlite4BtCsrOpen(p->pBt, 0, &pCsr);
- }
- while( rc==SQLITE4_OK ){
- const void *pK;
- int n;
- int nCmp;
- int res;
-
- rc = sqlite4BtCsrSeek(pCsr, pKey1, nKey1, BT_SEEK_GE);
- if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
- if( rc!=SQLITE4_OK ) break;
-
- rc = sqlite4BtCsrKey(pCsr, &pK, &n);
- if( rc!=SQLITE4_OK ) break;
-
- nCmp = MIN(n, nKey1);
- res = memcmp(pKey1, pK, nCmp);
- assert( res<0 || (res==0 && nKey1<=n) );
- if( res==0 && nKey1==n ){
- rc = sqlite4BtCsrNext(pCsr);
- if( rc!=SQLITE4_OK ) break;
- rc = sqlite4BtCsrKey(pCsr, &pK, &n);
- if( rc!=SQLITE4_OK ) break;
- }
-
- nCmp = MIN(n, nKey2);
- res = memcmp(pKey2, pK, nCmp);
- if( res<0 || (res==0 && nKey2<=n) ) break;
-
- rc = sqlite4BtDelete(pCsr);
- }
- if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;
-
- sqlite4BtCsrClose(pCsr);
-
- rc = btRestoreTransaction(p, iLevel, rc);
- return rc;
-}
-
-static int bt_fetch(
- TestDb *pTestDb,
- void *pK, int nK,
- void **ppVal, int *pnVal
-){
- BtDb *p = (BtDb*)pTestDb;
- bt_cursor *pCsr = 0;
- int iLevel;
- int rc = SQLITE4_OK;
-
- iLevel = sqlite4BtTransactionLevel(p->pBt);
- if( iLevel==0 ){
- rc = sqlite4BtBegin(p->pBt, 1);
- if( rc!=SQLITE4_OK ) return rc;
- }
-
- if( p->bFastInsert ) sqlite4BtControl(p->pBt, BT_CONTROL_FAST_INSERT_OP, 0);
- rc = sqlite4BtCsrOpen(p->pBt, 0, &pCsr);
- if( rc==SQLITE4_OK ){
- rc = sqlite4BtCsrSeek(pCsr, pK, nK, BT_SEEK_EQ);
- if( rc==SQLITE4_OK ){
- const void *pV = 0;
- int nV = 0;
- rc = sqlite4BtCsrData(pCsr, 0, -1, &pV, &nV);
- if( rc==SQLITE4_OK ){
- if( nV>p->nBuffer ){
- free(p->aBuffer);
- p->aBuffer = (u8*)malloc(nV*2);
- p->nBuffer = nV*2;
- }
- memcpy(p->aBuffer, pV, nV);
- *pnVal = nV;
- *ppVal = (void*)(p->aBuffer);
- }
-
- }else if( rc==SQLITE4_INEXACT || rc==SQLITE4_NOTFOUND ){
- *ppVal = 0;
- *pnVal = -1;
- rc = SQLITE4_OK;
- }
- sqlite4BtCsrClose(pCsr);
- }
-
- if( iLevel==0 ) sqlite4BtCommit(p->pBt, 0);
- return rc;
-}
-
-static int bt_scan(
- TestDb *pTestDb,
- void *pCtx,
- int bReverse,
- void *pFirst, int nFirst,
- void *pLast, int nLast,
- void (*xCallback)(void *, void *, int , void *, int)
-){
- BtDb *p = (BtDb*)pTestDb;
- bt_cursor *pCsr = 0;
- int rc;
- int iLevel;
-
- rc = btMinTransaction(p, 1, &iLevel);
-
- if( rc==SQLITE4_OK ){
- if( p->bFastInsert ) sqlite4BtControl(p->pBt, BT_CONTROL_FAST_INSERT_OP, 0);
- rc = sqlite4BtCsrOpen(p->pBt, 0, &pCsr);
- }
- if( rc==SQLITE4_OK ){
- if( bReverse ){
- if( pLast ){
- rc = sqlite4BtCsrSeek(pCsr, pLast, nLast, BT_SEEK_LE);
- }else{
- rc = sqlite4BtCsrLast(pCsr);
- }
- }else{
- rc = sqlite4BtCsrSeek(pCsr, pFirst, nFirst, BT_SEEK_GE);
- }
- if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
-
- while( rc==SQLITE4_OK ){
- const void *pK = 0; int nK = 0;
- const void *pV = 0; int nV = 0;
-
- rc = sqlite4BtCsrKey(pCsr, &pK, &nK);
- if( rc==SQLITE4_OK ){
- rc = sqlite4BtCsrData(pCsr, 0, -1, &pV, &nV);
- }
-
- if( rc!=SQLITE4_OK ) break;
- if( bReverse ){
- if( pFirst ){
- int res;
- int nCmp = MIN(nK, nFirst);
- res = memcmp(pFirst, pK, nCmp);
- if( res>0 || (res==0 && nK<nFirst) ) break;
- }
- }else{
- if( pLast ){
- int res;
- int nCmp = MIN(nK, nLast);
- res = memcmp(pLast, pK, nCmp);
- if( res<0 || (res==0 && nK>nLast) ) break;
- }
- }
-
- xCallback(pCtx, (void*)pK, nK, (void*)pV, nV);
- if( bReverse ){
- rc = sqlite4BtCsrPrev(pCsr);
- }else{
- rc = sqlite4BtCsrNext(pCsr);
- }
- }
- if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;
-
- sqlite4BtCsrClose(pCsr);
- }
-
- rc = btRestoreTransaction(p, iLevel, rc);
- return rc;
-}
-
-static int bt_begin(TestDb *pTestDb, int iLvl){
- BtDb *p = (BtDb*)pTestDb;
- int rc = sqlite4BtBegin(p->pBt, iLvl);
- return rc;
-}
-
-static int bt_commit(TestDb *pTestDb, int iLvl){
- BtDb *p = (BtDb*)pTestDb;
- int rc = sqlite4BtCommit(p->pBt, iLvl);
- return rc;
-}
-
-static int bt_rollback(TestDb *pTestDb, int iLvl){
- BtDb *p = (BtDb*)pTestDb;
- int rc = sqlite4BtRollback(p->pBt, iLvl);
- return rc;
-}
-
-static int testParseOption(
- const char **pzIn, /* IN/OUT: pointer to next option */
- const char **pzOpt, /* OUT: nul-terminated option name */
- const char **pzArg, /* OUT: nul-terminated option argument */
- char *pSpace /* Temporary space for output params */
-){
- const char *p = *pzIn;
- const char *pStart;
- int n;
-
- char *pOut = pSpace;
-
- while( *p==' ' ) p++;
- pStart = p;
- while( *p && *p!='=' ) p++;
- if( *p==0 ) return 1;
-
- n = (p - pStart);
- memcpy(pOut, pStart, n);
- *pzOpt = pOut;
- pOut += n;
- *pOut++ = '\0';
-
- p++;
- pStart = p;
- while( *p && *p!=' ' ) p++;
- n = (p - pStart);
-
- memcpy(pOut, pStart, n);
- *pzArg = pOut;
- pOut += n;
- *pOut++ = '\0';
-
- *pzIn = p;
- return 0;
-}
-
-static int testParseInt(const char *z, int *piVal){
- int i = 0;
- const char *p = z;
-
- while( *p>='0' && *p<='9' ){
- i = i*10 + (*p - '0');
- p++;
- }
- if( *p=='K' || *p=='k' ){
- i = i * 1024;
- p++;
- }else if( *p=='M' || *p=='m' ){
- i = i * 1024 * 1024;
- p++;
- }
-
- if( *p ) return SQLITE4_ERROR;
- *piVal = i;
- return SQLITE4_OK;
-}
-
-static int testBtConfigure(BtDb *pDb, const char *zCfg, int *pbMt){
- int rc = SQLITE4_OK;
-
- if( zCfg ){
- struct CfgParam {
- const char *zParam;
- int eParam;
- } aParam[] = {
- { "safety", BT_CONTROL_SAFETY },
- { "autockpt", BT_CONTROL_AUTOCKPT },
- { "multiproc", BT_CONTROL_MULTIPROC },
- { "blksz", BT_CONTROL_BLKSZ },
- { "pagesz", BT_CONTROL_PAGESZ },
- { "mt", -1 },
- { "fastinsert", -2 },
- { 0, 0 }
- };
- const char *z = zCfg;
- int n = strlen(z);
- char *aSpace;
- const char *zOpt;
- const char *zArg;
-
- aSpace = (char*)testMalloc(n+2);
- while( rc==SQLITE4_OK && 0==testParseOption(&z, &zOpt, &zArg, aSpace) ){
- int i;
- int iVal;
- rc = testArgSelect(aParam, "param", zOpt, &i);
- if( rc!=SQLITE4_OK ) break;
-
- rc = testParseInt(zArg, &iVal);
- if( rc!=SQLITE4_OK ) break;
-
- switch( aParam[i].eParam ){
- case -1:
- *pbMt = iVal;
- break;
- case -2:
- pDb->bFastInsert = 1;
- break;
- default:
- rc = sqlite4BtControl(pDb->pBt, aParam[i].eParam, (void*)&iVal);
- break;
- }
- }
- testFree(aSpace);
- }
-
- return rc;
-}
-
-
-int test_bt_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
-
- static const DatabaseMethods SqlMethods = {
- bt_close,
- bt_write,
- bt_delete,
- bt_delete_range,
- bt_fetch,
- bt_scan,
- bt_begin,
- bt_commit,
- bt_rollback
- };
- BtDb *p = 0;
- bt_db *pBt = 0;
- int rc;
- sqlite4_env *pEnv = sqlite4_env_default();
-
- if( bClear && zFilename && zFilename[0] ){
- char *zLog = sqlite3_mprintf("%s-wal", zFilename);
- unlink(zFilename);
- unlink(zLog);
- sqlite3_free(zLog);
- }
-
- rc = sqlite4BtNew(pEnv, 0, &pBt);
- if( rc==SQLITE4_OK ){
- int mt = 0; /* True for multi-threaded connection */
-
- p = (BtDb*)testMalloc(sizeof(BtDb));
- p->base.pMethods = &SqlMethods;
- p->pBt = pBt;
- p->pEnv = pEnv;
- p->nRef = 1;
-
- p->env.pVfsCtx = (void*)p;
- p->env.xFullpath = btVfsFullpath;
- p->env.xOpen = btVfsOpen;
- p->env.xSize = btVfsSize;
- p->env.xRead = btVfsRead;
- p->env.xWrite = btVfsWrite;
- p->env.xTruncate = btVfsTruncate;
- p->env.xSync = btVfsSync;
- p->env.xSectorSize = btVfsSectorSize;
- p->env.xClose = btVfsClose;
- p->env.xUnlink = btVfsUnlink;
- p->env.xLock = btVfsLock;
- p->env.xTestLock = btVfsTestLock;
- p->env.xShmMap = btVfsShmMap;
- p->env.xShmBarrier = btVfsShmBarrier;
- p->env.xShmUnmap = btVfsShmUnmap;
-
- sqlite4BtControl(pBt, BT_CONTROL_GETVFS, (void*)&p->pVfs);
- sqlite4BtControl(pBt, BT_CONTROL_SETVFS, (void*)&p->env);
-
- rc = testBtConfigure(p, zSpec, &mt);
- if( rc==SQLITE4_OK ){
- rc = sqlite4BtOpen(pBt, zFilename);
- }
-
- if( rc==SQLITE4_OK && mt ){
- int nAuto = 0;
- rc = bgc_attach(p, zSpec);
- sqlite4BtControl(pBt, BT_CONTROL_AUTOCKPT, (void*)&nAuto);
- }
- }
-
- if( rc!=SQLITE4_OK && p ){
- bt_close(&p->base);
- }
-
- *ppDb = &p->base;
- return rc;
-}
-
-int test_fbt_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- return test_bt_open("fast=1", zFilename, bClear, ppDb);
-}
-
-int test_fbts_open(
- const char *zSpec,
- const char *zFilename,
- int bClear,
- TestDb **ppDb
-){
- return test_bt_open("fast=1 blksz=32K pagesz=512", zFilename, bClear, ppDb);
-}
-
-
-void tdb_bt_prepare_sync_crash(TestDb *pTestDb, int iSync){
- BtDb *p = (BtDb*)pTestDb;
- assert( pTestDb->pMethods->xClose==bt_close );
- assert( p->bCrash==0 );
- p->nCrashSync = iSync;
-}
-
-bt_db *tdb_bt(TestDb *pDb){
- if( pDb->pMethods->xClose==bt_close ){
- return ((BtDb *)pDb)->pBt;
- }
- return 0;
-}
-
-/*************************************************************************
-** Beginning of code for background checkpointer.
-*/
-
-struct bt_ckpter {
- sqlite4_buffer file; /* File name */
- sqlite4_buffer spec; /* Options */
- int nLogsize; /* Minimum log size to checkpoint */
- int nRef; /* Number of clients */
-
- int bDoWork; /* Set by client threads */
- pthread_t ckpter_thread; /* Checkpointer thread */
- pthread_cond_t ckpter_cond; /* Condition var the ckpter waits on */
- pthread_mutex_t ckpter_mutex; /* Mutex used with ckpter_cond */
-
- bt_ckpter *pNext; /* Next object in list at gBgc.pCkpter */
-};
-
-static struct GlobalBackgroundCheckpointer {
- bt_ckpter *pCkpter; /* Linked list of checkpointers */
-} gBgc;
-
-static void *bgc_main(void *pArg){
- BtDb *pDb = 0;
- int rc;
- int mt;
- bt_ckpter *pCkpter = (bt_ckpter*)pArg;
-
- rc = test_bt_open("", (char*)pCkpter->file.p, 0, (TestDb**)&pDb);
- assert( rc==SQLITE4_OK );
- rc = testBtConfigure(pDb, (char*)pCkpter->spec.p, &mt);
-
- while( pCkpter->nRef>0 ){
- bt_db *db = pDb->pBt;
- int nLog = 0;
-
- sqlite4BtBegin(db, 1);
- sqlite4BtCommit(db, 0);
- sqlite4BtControl(db, BT_CONTROL_LOGSIZE, (void*)&nLog);
-
- if( nLog>=pCkpter->nLogsize ){
- int rc;
- bt_checkpoint ckpt;
- memset(&ckpt, 0, sizeof(bt_checkpoint));
- ckpt.nFrameBuffer = nLog/2;
- rc = sqlite4BtControl(db, BT_CONTROL_CHECKPOINT, (void*)&ckpt);
- assert( rc==SQLITE4_OK );
- sqlite4BtControl(db, BT_CONTROL_LOGSIZE, (void*)&nLog);
- }
-
- /* The thread will wake up when it is signaled either because another
- ** thread has created some work for this one or because the connection
- ** is being closed. */
- pthread_mutex_lock(&pCkpter->ckpter_mutex);
- if( pCkpter->bDoWork==0 ){
- pthread_cond_wait(&pCkpter->ckpter_cond, &pCkpter->ckpter_mutex);
- }
- pCkpter->bDoWork = 0;
- pthread_mutex_unlock(&pCkpter->ckpter_mutex);
- }
-
- if( pDb ) bt_close((TestDb*)pDb);
- return 0;
-}
-
-static void bgc_logsize_cb(void *pCtx, int nLogsize){
- bt_ckpter *p = (bt_ckpter*)pCtx;
- if( nLogsize>=p->nLogsize ){
- pthread_mutex_lock(&p->ckpter_mutex);
- p->bDoWork = 1;
- pthread_cond_signal(&p->ckpter_cond);
- pthread_mutex_unlock(&p->ckpter_mutex);
- }
-}
-
-static int bgc_attach(BtDb *pDb, const char *zSpec){
- int rc;
- int n;
- bt_info info;
- bt_ckpter *pCkpter;
-
- /* Figure out the full path to the database opened by handle pDb. */
- info.eType = BT_INFO_FILENAME;
- info.pgno = 0;
- sqlite4_buffer_init(&info.output, 0);
- rc = sqlite4BtControl(pDb->pBt, BT_CONTROL_INFO, (void*)&info);
- if( rc!=SQLITE4_OK ) return rc;
-
- sqlite4_mutex_enter(sqlite4_mutex_alloc(pDb->pEnv, SQLITE4_MUTEX_STATIC_KV));
-
- /* Search for an existing bt_ckpter object. */
- n = info.output.n;
- for(pCkpter=gBgc.pCkpter; pCkpter; pCkpter=pCkpter->pNext){
- if( n==pCkpter->file.n && 0==memcmp(info.output.p, pCkpter->file.p, n) ){
- break;
- }
- }
-
- /* Failed to find a suitable checkpointer. Create a new one. */
- if( pCkpter==0 ){
- bt_logsizecb cb;
-
- pCkpter = testMalloc(sizeof(bt_ckpter));
- memcpy(&pCkpter->file, &info.output, sizeof(sqlite4_buffer));
- info.output.p = 0;
- pCkpter->pNext = gBgc.pCkpter;
- pCkpter->nLogsize = 1000;
- gBgc.pCkpter = pCkpter;
- pCkpter->nRef = 1;
-
- sqlite4_buffer_init(&pCkpter->spec, 0);
- rc = sqlite4_buffer_set(&pCkpter->spec, zSpec, strlen(zSpec)+1);
- assert( rc==SQLITE4_OK );
-
- /* Kick off the checkpointer thread. */
- if( rc==0 ) rc = pthread_cond_init(&pCkpter->ckpter_cond, 0);
- if( rc==0 ) rc = pthread_mutex_init(&pCkpter->ckpter_mutex, 0);
- if( rc==0 ){
- rc = pthread_create(&pCkpter->ckpter_thread, 0, bgc_main, (void*)pCkpter);
- }
- assert( rc==0 ); /* todo: Fix this */
-
- /* Set up the logsize callback for the client thread */
- cb.pCtx = (void*)pCkpter;
- cb.xLogsize = bgc_logsize_cb;
- sqlite4BtControl(pDb->pBt, BT_CONTROL_LOGSIZECB, (void*)&cb);
- }else{
- pCkpter->nRef++;
- }
-
- /* Assuming a checkpointer was encountered or effected, attach the
- ** connection to it. */
- if( pCkpter ){
- pDb->pCkpter = pCkpter;
- }
-
- sqlite4_mutex_leave(sqlite4_mutex_alloc(pDb->pEnv, SQLITE4_MUTEX_STATIC_KV));
- sqlite4_buffer_clear(&info.output);
- return rc;
-}
-
-static int bgc_detach(BtDb *pDb){
- int rc = SQLITE4_OK;
- bt_ckpter *pCkpter = pDb->pCkpter;
- if( pCkpter ){
- int bShutdown = 0; /* True if this is the last reference */
-
- sqlite4_mutex_enter(sqlite4_mutex_alloc(pDb->pEnv,SQLITE4_MUTEX_STATIC_KV));
- pCkpter->nRef--;
- if( pCkpter->nRef==0 ){
- bt_ckpter **pp;
-
- *pp = pCkpter->pNext;
- for(pp=&gBgc.pCkpter; *pp!=pCkpter; pp=&((*pp)->pNext));
- bShutdown = 1;
- }
- sqlite4_mutex_leave(sqlite4_mutex_alloc(pDb->pEnv,SQLITE4_MUTEX_STATIC_KV));
-
- if( bShutdown ){
- void *pDummy;
-
- /* Signal the checkpointer thread. */
- pthread_mutex_lock(&pCkpter->ckpter_mutex);
- pCkpter->bDoWork = 1;
- pthread_cond_signal(&pCkpter->ckpter_cond);
- pthread_mutex_unlock(&pCkpter->ckpter_mutex);
-
- /* Join the checkpointer thread. */
- pthread_join(pCkpter->ckpter_thread, &pDummy);
- pthread_cond_destroy(&pCkpter->ckpter_cond);
- pthread_mutex_destroy(&pCkpter->ckpter_mutex);
-
- sqlite4_buffer_clear(&pCkpter->file);
- sqlite4_buffer_clear(&pCkpter->spec);
- testFree(pCkpter);
- }
-
- pDb->pCkpter = 0;
- }
- return rc;
-}
-
-/*
-** End of background checkpointer.
-*************************************************************************/
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_util.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_util.c
deleted file mode 100644
index adab8a53e81..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_util.c
+++ /dev/null
@@ -1,223 +0,0 @@
-
-#include "lsmtest.h"
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#ifndef _WIN32
-# include <sys/time.h>
-#endif
-
-/*
-** Global variables used within this module.
-*/
-static struct TestutilGlobal {
- char **argv;
- int argc;
-} g = {0, 0};
-
-static struct TestutilRnd {
- unsigned int aRand1[2048]; /* Bits 0..10 */
- unsigned int aRand2[2048]; /* Bits 11..21 */
- unsigned int aRand3[1024]; /* Bits 22..31 */
-} r;
-
-/*************************************************************************
-** The following block is a copy of the implementation of SQLite function
-** sqlite3_randomness. This version has two important differences:
-**
-** 1. It always uses the same seed. So the sequence of random data output
-** is the same for every run of the program.
-**
-** 2. It is not threadsafe.
-*/
-static struct sqlite3PrngType {
- unsigned char i, j; /* State variables */
- unsigned char s[256]; /* State variables */
-} sqlite3Prng = {
- 0xAF, 0x28,
- {
- 0x71, 0xF5, 0xB4, 0x6E, 0x80, 0xAB, 0x1D, 0xB8,
- 0xFB, 0xB7, 0x49, 0xBF, 0xFF, 0x72, 0x2D, 0x14,
- 0x79, 0x09, 0xE3, 0x78, 0x76, 0xB0, 0x2C, 0x0A,
- 0x8E, 0x23, 0xEE, 0xDF, 0xE0, 0x9A, 0x2F, 0x67,
- 0xE1, 0xBE, 0x0E, 0xA7, 0x08, 0x97, 0xEB, 0x77,
- 0x78, 0xBA, 0x9D, 0xCA, 0x49, 0x4C, 0x60, 0x9A,
- 0xF6, 0xBD, 0xDA, 0x7F, 0xBC, 0x48, 0x58, 0x52,
- 0xE5, 0xCD, 0x83, 0x72, 0x23, 0x52, 0xFF, 0x6D,
- 0xEF, 0x0F, 0x82, 0x29, 0xA0, 0x83, 0x3F, 0x7D,
- 0xA4, 0x88, 0x31, 0xE7, 0x88, 0x92, 0x3B, 0x9B,
- 0x3B, 0x2C, 0xC2, 0x4C, 0x71, 0xA2, 0xB0, 0xEA,
- 0x36, 0xD0, 0x00, 0xF1, 0xD3, 0x39, 0x17, 0x5D,
- 0x2A, 0x7A, 0xE4, 0xAD, 0xE1, 0x64, 0xCE, 0x0F,
- 0x9C, 0xD9, 0xF5, 0xED, 0xB0, 0x22, 0x5E, 0x62,
- 0x97, 0x02, 0xA3, 0x8C, 0x67, 0x80, 0xFC, 0x88,
- 0x14, 0x0B, 0x15, 0x10, 0x0F, 0xC7, 0x40, 0xD4,
- 0xF1, 0xF9, 0x0E, 0x1A, 0xCE, 0xB9, 0x1E, 0xA1,
- 0x72, 0x8E, 0xD7, 0x78, 0x39, 0xCD, 0xF4, 0x5D,
- 0x2A, 0x59, 0x26, 0x34, 0xF2, 0x73, 0x0B, 0xA0,
- 0x02, 0x51, 0x2C, 0x03, 0xA3, 0xA7, 0x43, 0x13,
- 0xE8, 0x98, 0x2B, 0xD2, 0x53, 0xF8, 0xEE, 0x91,
- 0x7D, 0xE7, 0xE3, 0xDA, 0xD5, 0xBB, 0xC0, 0x92,
- 0x9D, 0x98, 0x01, 0x2C, 0xF9, 0xB9, 0xA0, 0xEB,
- 0xCF, 0x32, 0xFA, 0x01, 0x49, 0xA5, 0x1D, 0x9A,
- 0x76, 0x86, 0x3F, 0x40, 0xD4, 0x89, 0x8F, 0x9C,
- 0xE2, 0xE3, 0x11, 0x31, 0x37, 0xB2, 0x49, 0x28,
- 0x35, 0xC0, 0x99, 0xB6, 0xD0, 0xBC, 0x66, 0x35,
- 0xF7, 0x83, 0x5B, 0xD7, 0x37, 0x1A, 0x2B, 0x18,
- 0xA6, 0xFF, 0x8D, 0x7C, 0x81, 0xA8, 0xFC, 0x9E,
- 0xC4, 0xEC, 0x80, 0xD0, 0x98, 0xA7, 0x76, 0xCC,
- 0x9C, 0x2F, 0x7B, 0xFF, 0x8E, 0x0E, 0xBB, 0x90,
- 0xAE, 0x13, 0x06, 0xF5, 0x1C, 0x4E, 0x52, 0xF7
- }
-};
-
-/* Generate and return single random byte */
-static unsigned char randomByte(void){
- unsigned char t;
- sqlite3Prng.i++;
- t = sqlite3Prng.s[sqlite3Prng.i];
- sqlite3Prng.j += t;
- sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j];
- sqlite3Prng.s[sqlite3Prng.j] = t;
- t += sqlite3Prng.s[sqlite3Prng.i];
- return sqlite3Prng.s[t];
-}
-
-/*
-** Return N random bytes.
-*/
-static void randomBlob(int nBuf, unsigned char *zBuf){
- int i;
- for(i=0; i<nBuf; i++){
- zBuf[i] = randomByte();
- }
-}
-/*
-** End of code copied from SQLite.
-*************************************************************************/
-
-
-int testPrngInit(void){
- randomBlob(sizeof(r.aRand1), (unsigned char *)r.aRand1);
- randomBlob(sizeof(r.aRand2), (unsigned char *)r.aRand2);
- randomBlob(sizeof(r.aRand3), (unsigned char *)r.aRand3);
- return 0;
-}
-
-unsigned int testPrngValue(unsigned int iVal){
- return
- r.aRand1[iVal & 0x000007FF] ^
- r.aRand2[(iVal>>11) & 0x000007FF] ^
- r.aRand3[(iVal>>22) & 0x000003FF]
- ;
-}
-
-void testPrngArray(unsigned int iVal, unsigned int *aOut, int nOut){
- int i;
- for(i=0; i<nOut; i++){
- aOut[i] = testPrngValue(iVal+i);
- }
-}
-
-void testPrngString(unsigned int iVal, char *aOut, int nOut){
- int i;
- for(i=0; i<(nOut-1); i++){
- aOut[i] = 'a' + (testPrngValue(iVal+i) % 26);
- }
- aOut[i] = '\0';
-}
-
-void testErrorInit(int argc, char **argv){
- g.argc = argc;
- g.argv = argv;
-}
-
-void testPrintError(const char *zFormat, ...){
- va_list ap;
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
-}
-
-void testPrintFUsage(const char *zFormat, ...){
- va_list ap;
- va_start(ap, zFormat);
- fprintf(stderr, "Usage: %s %s ", g.argv[0], g.argv[1]);
- vfprintf(stderr, zFormat, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-void testPrintUsage(const char *zArgs){
- testPrintError("Usage: %s %s %s\n", g.argv[0], g.argv[1], zArgs);
-}
-
-
-static void argError(void *aData, const char *zType, int sz, const char *zArg){
- struct Entry { const char *zName; };
- struct Entry *pEntry;
- const char *zPrev = 0;
-
- testPrintError("unrecognized %s \"%s\": must be ", zType, zArg);
- for(pEntry=(struct Entry *)aData;
- pEntry->zName;
- pEntry=(struct Entry *)&((unsigned char *)pEntry)[sz]
- ){
- if( zPrev ){ testPrintError("%s, ", zPrev); }
- zPrev = pEntry->zName;
- }
- testPrintError("or %s\n", zPrev);
-}
-
-int testArgSelectX(
- void *aData,
- const char *zType,
- int sz,
- const char *zArg,
- int *piOut
-){
- struct Entry { const char *zName; };
- struct Entry *pEntry;
- int nArg = strlen(zArg);
-
- int i = 0;
- int iOut = -1;
- int nOut = 0;
-
- for(pEntry=(struct Entry *)aData;
- pEntry->zName;
- pEntry=(struct Entry *)&((unsigned char *)pEntry)[sz]
- ){
- int nName = strlen(pEntry->zName);
- if( nArg<=nName && memcmp(pEntry->zName, zArg, nArg)==0 ){
- iOut = i;
- if( nName==nArg ){
- nOut = 1;
- break;
- }
- nOut++;
- }
- i++;
- }
-
- if( nOut!=1 ){
- argError(aData, zType, sz, zArg);
- }else{
- *piOut = iOut;
- }
- return (nOut!=1);
-}
-
-struct timeval zero_time;
-
-void testTimeInit(void){
- gettimeofday(&zero_time, 0);
-}
-
-int testTimeGet(void){
- struct timeval now;
- gettimeofday(&now, 0);
- return
- (((int)now.tv_sec - (int)zero_time.tv_sec)*1000) +
- (((int)now.tv_usec - (int)zero_time.tv_usec)/1000);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_win32.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_win32.c
deleted file mode 100644
index 9472723368a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm-test/lsmtest_win32.c
+++ /dev/null
@@ -1,30 +0,0 @@
-
-#include "lsmtest.h"
-
-#ifdef _WIN32
-
-#define TICKS_PER_SECOND (10000000)
-#define TICKS_PER_MICROSECOND (10)
-#define TICKS_UNIX_EPOCH (116444736000000000LL)
-
-int win32GetTimeOfDay(
- struct timeval *tp,
- void *tzp
-){
- FILETIME fileTime;
- ULONGLONG ticks;
- ULONGLONG unixTicks;
-
- unused_parameter(tzp);
- memset(&fileTime, 0, sizeof(FILETIME));
- GetSystemTimeAsFileTime(&fileTime);
- ticks = (ULONGLONG)fileTime.dwHighDateTime << 32;
- ticks |= (ULONGLONG)fileTime.dwLowDateTime;
- unixTicks = ticks - TICKS_UNIX_EPOCH;
- tp->tv_sec = (long)(unixTicks / TICKS_PER_SECOND);
- unixTicks -= ((ULONGLONG)tp->tv_sec * TICKS_PER_SECOND);
- tp->tv_usec = (long)(unixTicks / TICKS_PER_MICROSECOND);
-
- return 0;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm.h
deleted file mode 100644
index 48701c4c5e4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm.h
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
-** 2011-08-10
-**
-** 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 defines the LSM API.
-*/
-#ifndef _LSM_H
-#define _LSM_H
-#include <stddef.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** Opaque handle types.
-*/
-typedef struct lsm_compress lsm_compress; /* Compression library functions */
-typedef struct lsm_compress_factory lsm_compress_factory;
-typedef struct lsm_cursor lsm_cursor; /* Database cursor handle */
-typedef struct lsm_db lsm_db; /* Database connection handle */
-typedef struct lsm_env lsm_env; /* Runtime environment */
-typedef struct lsm_file lsm_file; /* OS file handle */
-typedef struct lsm_mutex lsm_mutex; /* Mutex handle */
-
-/* 64-bit integer type used for file offsets. */
-typedef long long int lsm_i64; /* 64-bit signed integer type */
-
-/* Candidate values for the 3rd argument to lsm_env.xLock() */
-#define LSM_LOCK_UNLOCK 0
-#define LSM_LOCK_SHARED 1
-#define LSM_LOCK_EXCL 2
-
-/* Flags for lsm_env.xOpen() */
-#define LSM_OPEN_READONLY 0x0001
-
-/*
-** CAPI: Database Runtime Environment
-**
-** Run-time environment used by LSM
-*/
-struct lsm_env {
- int nByte; /* Size of this structure in bytes */
- int iVersion; /* Version number of this structure (1) */
- /****** file i/o ***********************************************/
- void *pVfsCtx;
- int (*xFullpath)(lsm_env*, const char *, char *, int *);
- int (*xOpen)(lsm_env*, const char *, int flags, lsm_file **);
- int (*xRead)(lsm_file *, lsm_i64, void *, int);
- int (*xWrite)(lsm_file *, lsm_i64, void *, int);
- int (*xTruncate)(lsm_file *, lsm_i64);
- int (*xSync)(lsm_file *);
- int (*xSectorSize)(lsm_file *);
- int (*xRemap)(lsm_file *, lsm_i64, void **, lsm_i64*);
- int (*xFileid)(lsm_file *, void *pBuf, int *pnBuf);
- int (*xClose)(lsm_file *);
- int (*xUnlink)(lsm_env*, const char *);
- int (*xLock)(lsm_file*, int, int);
- int (*xTestLock)(lsm_file*, int, int, int);
- int (*xShmMap)(lsm_file*, int, int, void **);
- void (*xShmBarrier)(void);
- int (*xShmUnmap)(lsm_file*, int);
- /****** memory allocation ****************************************/
- void *pMemCtx;
- void *(*xMalloc)(lsm_env*, size_t); /* malloc(3) function */
- void *(*xRealloc)(lsm_env*, void *, size_t); /* realloc(3) function */
- void (*xFree)(lsm_env*, void *); /* free(3) function */
- size_t (*xSize)(lsm_env*, void *); /* xSize function */
- /****** mutexes ****************************************************/
- void *pMutexCtx;
- int (*xMutexStatic)(lsm_env*,int,lsm_mutex**); /* Obtain a static mutex */
- int (*xMutexNew)(lsm_env*, lsm_mutex**); /* Get a new dynamic mutex */
- void (*xMutexDel)(lsm_mutex *); /* Delete an allocated mutex */
- void (*xMutexEnter)(lsm_mutex *); /* Grab a mutex */
- int (*xMutexTry)(lsm_mutex *); /* Attempt to obtain a mutex */
- void (*xMutexLeave)(lsm_mutex *); /* Leave a mutex */
- int (*xMutexHeld)(lsm_mutex *); /* Return true if mutex is held */
- int (*xMutexNotHeld)(lsm_mutex *); /* Return true if mutex not held */
- /****** other ****************************************************/
- int (*xSleep)(lsm_env*, int microseconds);
-
- /* New fields may be added in future releases, in which case the
- ** iVersion value will increase. */
-};
-
-/*
-** Values that may be passed as the second argument to xMutexStatic.
-*/
-#define LSM_MUTEX_GLOBAL 1
-#define LSM_MUTEX_HEAP 2
-
-/*
-** CAPI: LSM Error Codes
-*/
-#define LSM_OK 0
-#define LSM_ERROR 1
-#define LSM_BUSY 5
-#define LSM_NOMEM 7
-#define LSM_READONLY 8
-#define LSM_IOERR 10
-#define LSM_CORRUPT 11
-#define LSM_FULL 13
-#define LSM_CANTOPEN 14
-#define LSM_PROTOCOL 15
-#define LSM_MISUSE 21
-
-#define LSM_MISMATCH 50
-
-
-#define LSM_IOERR_NOENT (LSM_IOERR | (1<<8))
-
-/*
-** CAPI: Creating and Destroying Database Connection Handles
-**
-** Open and close a database connection handle.
-*/
-int lsm_new(lsm_env*, lsm_db **ppDb);
-int lsm_close(lsm_db *pDb);
-
-/*
-** CAPI: Connecting to a Database
-*/
-int lsm_open(lsm_db *pDb, const char *zFilename);
-
-/*
-** CAPI: Obtaining pointers to database environments
-**
-** Return a pointer to the environment used by the database connection
-** passed as the first argument. Assuming the argument is valid, this
-** function always returns a valid environment pointer - it cannot fail.
-*/
-lsm_env *lsm_get_env(lsm_db *pDb);
-
-/*
-** The lsm_default_env() function returns a pointer to the default LSM
-** environment for the current platform.
-*/
-lsm_env *lsm_default_env(void);
-
-
-/*
-** CAPI: Configuring a database connection.
-**
-** The lsm_config() function is used to configure a database connection.
-*/
-int lsm_config(lsm_db *, int, ...);
-
-/*
-** The following values may be passed as the second argument to lsm_config().
-**
-** LSM_CONFIG_AUTOFLUSH:
-** A read/write integer parameter.
-**
-** This value determines the amount of data allowed to accumulate in a
-** live in-memory tree before it is marked as old. After committing a
-** transaction, a connection checks if the size of the live in-memory tree,
-** including data structure overhead, is greater than the value of this
-** option in KB. If it is, and there is not already an old in-memory tree,
-** the live in-memory tree is marked as old.
-**
-** The maximum allowable value is 1048576 (1GB). There is no minimum
-** value. If this parameter is set to zero, then an attempt is made to
-** mark the live in-memory tree as old after each transaction is committed.
-**
-** The default value is 1024 (1MB).
-**
-** LSM_CONFIG_PAGE_SIZE:
-** A read/write integer parameter. This parameter may only be set before
-** lsm_open() has been called.
-**
-** LSM_CONFIG_BLOCK_SIZE:
-** A read/write integer parameter.
-**
-** This parameter may only be set before lsm_open() has been called. It
-** must be set to a power of two between 64 and 65536, inclusive (block
-** sizes between 64KB and 64MB).
-**
-** If the connection creates a new database, the block size of the new
-** database is set to the value of this option in KB. After lsm_open()
-** has been called, querying this parameter returns the actual block
-** size of the opened database.
-**
-** The default value is 1024 (1MB blocks).
-**
-** LSM_CONFIG_SAFETY:
-** A read/write integer parameter. Valid values are 0, 1 (the default)
-** and 2. This parameter determines how robust the database is in the
-** face of a system crash (e.g. a power failure or operating system
-** crash). As follows:
-**
-** 0 (off): No robustness. A system crash may corrupt the database.
-**
-** 1 (normal): Some robustness. A system crash may not corrupt the
-** database file, but recently committed transactions may
-** be lost following recovery.
-**
-** 2 (full): Full robustness. A system crash may not corrupt the
-** database file. Following recovery the database file
-** contains all successfully committed transactions.
-**
-** LSM_CONFIG_AUTOWORK:
-** A read/write integer parameter.
-**
-** LSM_CONFIG_AUTOCHECKPOINT:
-** A read/write integer parameter.
-**
-** If this option is set to non-zero value N, then a checkpoint is
-** automatically attempted after each N KB of data have been written to
-** the database file.
-**
-** The amount of uncheckpointed data already written to the database file
-** is a global parameter. After performing database work (writing to the
-** database file), the process checks if the total amount of uncheckpointed
-** data exceeds the value of this paramter. If so, a checkpoint is performed.
-** This means that this option may cause the connection to perform a
-** checkpoint even if the current connection has itself written very little
-** data into the database file.
-**
-** The default value is 2048 (checkpoint every 2MB).
-**
-** LSM_CONFIG_MMAP:
-** A read/write integer parameter. If this value is set to 0, then the
-** database file is accessed using ordinary read/write IO functions. Or,
-** if it is set to 1, then the database file is memory mapped and accessed
-** that way. If this parameter is set to any value N greater than 1, then
-** up to the first N KB of the file are memory mapped, and any remainder
-** accessed using read/write IO.
-**
-** The default value is 1 on 64-bit platforms and 32768 on 32-bit platforms.
-**
-**
-** LSM_CONFIG_USE_LOG:
-** A read/write boolean parameter. True (the default) to use the log
-** file normally. False otherwise.
-**
-** LSM_CONFIG_AUTOMERGE:
-** A read/write integer parameter. The minimum number of segments to
-** merge together at a time. Default value 4.
-**
-** LSM_CONFIG_MAX_FREELIST:
-** A read/write integer parameter. The maximum number of free-list
-** entries that are stored in a database checkpoint (the others are
-** stored elsewhere in the database).
-**
-** There is no reason for an application to configure or query this
-** parameter. It is only present because configuring a small value
-** makes certain parts of the lsm code easier to test.
-**
-** LSM_CONFIG_MULTIPLE_PROCESSES:
-** A read/write boolean parameter. This parameter may only be set before
-** lsm_open() has been called. If true, the library uses shared-memory
-** and posix advisory locks to co-ordinate access by clients from within
-** multiple processes. Otherwise, if false, all database clients must be
-** located in the same process. The default value is true.
-**
-** LSM_CONFIG_SET_COMPRESSION:
-** Set the compression methods used to compress and decompress database
-** content. The argument to this option should be a pointer to a structure
-** of type lsm_compress. The lsm_config() method takes a copy of the
-** structures contents.
-**
-** This option may only be used before lsm_open() is called. Invoking it
-** after lsm_open() has been called results in an LSM_MISUSE error.
-**
-** LSM_CONFIG_GET_COMPRESSION:
-** Query the compression methods used to compress and decompress database
-** content.
-**
-** LSM_CONFIG_SET_COMPRESSION_FACTORY:
-** Configure a factory method to be invoked in case of an LSM_MISMATCH
-** error.
-**
-** LSM_CONFIG_READONLY:
-** A read/write boolean parameter. This parameter may only be set before
-** lsm_open() is called.
-*/
-#define LSM_CONFIG_AUTOFLUSH 1
-#define LSM_CONFIG_PAGE_SIZE 2
-#define LSM_CONFIG_SAFETY 3
-#define LSM_CONFIG_BLOCK_SIZE 4
-#define LSM_CONFIG_AUTOWORK 5
-#define LSM_CONFIG_MMAP 7
-#define LSM_CONFIG_USE_LOG 8
-#define LSM_CONFIG_AUTOMERGE 9
-#define LSM_CONFIG_MAX_FREELIST 10
-#define LSM_CONFIG_MULTIPLE_PROCESSES 11
-#define LSM_CONFIG_AUTOCHECKPOINT 12
-#define LSM_CONFIG_SET_COMPRESSION 13
-#define LSM_CONFIG_GET_COMPRESSION 14
-#define LSM_CONFIG_SET_COMPRESSION_FACTORY 15
-#define LSM_CONFIG_READONLY 16
-
-#define LSM_SAFETY_OFF 0
-#define LSM_SAFETY_NORMAL 1
-#define LSM_SAFETY_FULL 2
-
-/*
-** CAPI: Compression and/or Encryption Hooks
-*/
-struct lsm_compress {
- void *pCtx;
- unsigned int iId;
- int (*xBound)(void *, int nSrc);
- int (*xCompress)(void *, char *, int *, const char *, int);
- int (*xUncompress)(void *, char *, int *, const char *, int);
- void (*xFree)(void *pCtx);
-};
-
-struct lsm_compress_factory {
- void *pCtx;
- int (*xFactory)(void *, lsm_db *, unsigned int);
- void (*xFree)(void *pCtx);
-};
-
-#define LSM_COMPRESSION_EMPTY 0
-#define LSM_COMPRESSION_NONE 1
-
-/*
-** CAPI: Allocating and Freeing Memory
-**
-** Invoke the memory allocation functions that belong to environment
-** pEnv. Or the system defaults if no memory allocation functions have
-** been registered.
-*/
-void *lsm_malloc(lsm_env*, size_t);
-void *lsm_realloc(lsm_env*, void *, size_t);
-void lsm_free(lsm_env*, void *);
-
-/*
-** CAPI: Querying a Connection For Operational Data
-**
-** Query a database connection for operational statistics or data.
-*/
-int lsm_info(lsm_db *, int, ...);
-
-int lsm_get_user_version(lsm_db *, unsigned int *);
-int lsm_set_user_version(lsm_db *, unsigned int);
-
-/*
-** The following values may be passed as the second argument to lsm_info().
-**
-** LSM_INFO_NWRITE:
-** The third parameter should be of type (int *). The location pointed
-** to by the third parameter is set to the number of 4KB pages written to
-** the database file during the lifetime of this connection.
-**
-** LSM_INFO_NREAD:
-** The third parameter should be of type (int *). The location pointed
-** to by the third parameter is set to the number of 4KB pages read from
-** the database file during the lifetime of this connection.
-**
-** LSM_INFO_DB_STRUCTURE:
-** The third argument should be of type (char **). The location pointed
-** to is populated with a pointer to a nul-terminated string containing
-** the string representation of a Tcl data-structure reflecting the
-** current structure of the database file. Specifically, the current state
-** of the worker snapshot. The returned string should be eventually freed
-** by the caller using lsm_free().
-**
-** The returned list contains one element for each level in the database,
-** in order from most to least recent. Each element contains a
-** single element for each segment comprising the corresponding level,
-** starting with the lhs segment, then each of the rhs segments (if any)
-** in order from most to least recent.
-**
-** Each segment element is itself a list of 4 integer values, as follows:
-**
-** <ol><li> First page of segment
-** <li> Last page of segment
-** <li> Root page of segment (if applicable)
-** <li> Total number of pages in segment
-** </ol>
-**
-** LSM_INFO_ARRAY_STRUCTURE:
-** There should be two arguments passed following this option (i.e. a
-** total of four arguments passed to lsm_info()). The first argument
-** should be the page number of the first page in a database array
-** (perhaps obtained from an earlier INFO_DB_STRUCTURE call). The second
-** trailing argument should be of type (char **). The location pointed
-** to is populated with a pointer to a nul-terminated string that must
-** be eventually freed using lsm_free() by the caller.
-**
-** The output string contains the text representation of a Tcl list of
-** integers. Each pair of integers represent a range of pages used by
-** the identified array. For example, if the array occupies database
-** pages 993 to 1024, then pages 2048 to 2777, then the returned string
-** will be "993 1024 2048 2777".
-**
-** If the specified integer argument does not correspond to the first
-** page of any database array, LSM_ERROR is returned and the output
-** pointer is set to a NULL value.
-**
-** LSM_INFO_LOG_STRUCTURE:
-** The third argument should be of type (char **). The location pointed
-** to is populated with a pointer to a nul-terminated string containing
-** the string representation of a Tcl data-structure. The returned
-** string should be eventually freed by the caller using lsm_free().
-**
-** The Tcl structure returned is a list of six integers that describe
-** the current structure of the log file.
-**
-** LSM_INFO_ARRAY_PAGES:
-**
-** LSM_INFO_PAGE_ASCII_DUMP:
-** As with LSM_INFO_ARRAY_STRUCTURE, there should be two arguments passed
-** with calls that specify this option - an integer page number and a
-** (char **) used to return a nul-terminated string that must be later
-** freed using lsm_free(). In this case the output string is populated
-** with a human-readable description of the page content.
-**
-** If the page cannot be decoded, it is not an error. In this case the
-** human-readable output message will report the systems failure to
-** interpret the page data.
-**
-** LSM_INFO_PAGE_HEX_DUMP:
-** This argument is similar to PAGE_ASCII_DUMP, except that keys and
-** values are represented using hexadecimal notation instead of ascii.
-**
-** LSM_INFO_FREELIST:
-** The third argument should be of type (char **). The location pointed
-** to is populated with a pointer to a nul-terminated string containing
-** the string representation of a Tcl data-structure. The returned
-** string should be eventually freed by the caller using lsm_free().
-**
-** The Tcl structure returned is a list containing one element for each
-** free block in the database. The element itself consists of two
-** integers - the block number and the id of the snapshot that freed it.
-**
-** LSM_INFO_CHECKPOINT_SIZE:
-** The third argument should be of type (int *). The location pointed to
-** by this argument is populated with the number of KB written to the
-** database file since the most recent checkpoint.
-**
-** LSM_INFO_TREE_SIZE:
-** If this value is passed as the second argument to an lsm_info() call, it
-** should be followed by two arguments of type (int *) (for a total of four
-** arguments).
-**
-** At any time, there are either one or two tree structures held in shared
-** memory that new database clients will access (there may also be additional
-** tree structures being used by older clients - this API does not provide
-** information on them). One tree structure - the current tree - is used to
-** accumulate new data written to the database. The other tree structure -
-** the old tree - is a read-only tree holding older data and may be flushed
-** to disk at any time.
-**
-** Assuming no error occurs, the location pointed to by the first of the two
-** (int *) arguments is set to the size of the old in-memory tree in KB.
-** The second is set to the size of the current, or live in-memory tree.
-**
-** LSM_INFO_COMPRESSION_ID:
-** This value should be followed by a single argument of type
-** (unsigned int *). If successful, the location pointed to is populated
-** with the database compression id before returning.
-*/
-#define LSM_INFO_NWRITE 1
-#define LSM_INFO_NREAD 2
-#define LSM_INFO_DB_STRUCTURE 3
-#define LSM_INFO_LOG_STRUCTURE 4
-#define LSM_INFO_ARRAY_STRUCTURE 5
-#define LSM_INFO_PAGE_ASCII_DUMP 6
-#define LSM_INFO_PAGE_HEX_DUMP 7
-#define LSM_INFO_FREELIST 8
-#define LSM_INFO_ARRAY_PAGES 9
-#define LSM_INFO_CHECKPOINT_SIZE 10
-#define LSM_INFO_TREE_SIZE 11
-#define LSM_INFO_FREELIST_SIZE 12
-#define LSM_INFO_COMPRESSION_ID 13
-
-
-/*
-** CAPI: Opening and Closing Write Transactions
-**
-** These functions are used to open and close transactions and nested
-** sub-transactions.
-**
-** The lsm_begin() function is used to open transactions and sub-transactions.
-** A successful call to lsm_begin() ensures that there are at least iLevel
-** nested transactions open. To open a top-level transaction, pass iLevel=1.
-** To open a sub-transaction within the top-level transaction, iLevel=2.
-** Passing iLevel=0 is a no-op.
-**
-** lsm_commit() is used to commit transactions and sub-transactions. A
-** successful call to lsm_commit() ensures that there are at most iLevel
-** nested transactions open. To commit a top-level transaction, pass iLevel=0.
-** To commit all sub-transactions inside the main transaction, pass iLevel=1.
-**
-** Function lsm_rollback() is used to roll back transactions and
-** sub-transactions. A successful call to lsm_rollback() restores the database
-** to the state it was in when the iLevel'th nested sub-transaction (if any)
-** was first opened. And then closes transactions to ensure that there are
-** at most iLevel nested transactions open. Passing iLevel=0 rolls back and
-** closes the top-level transaction. iLevel=1 also rolls back the top-level
-** transaction, but leaves it open. iLevel=2 rolls back the sub-transaction
-** nested directly inside the top-level transaction (and leaves it open).
-*/
-int lsm_begin(lsm_db *pDb, int iLevel);
-int lsm_commit(lsm_db *pDb, int iLevel);
-int lsm_rollback(lsm_db *pDb, int iLevel);
-
-/*
-** CAPI: Writing to a Database
-**
-** Write a new value into the database. If a value with a duplicate key
-** already exists it is replaced.
-*/
-int lsm_insert(lsm_db*, const void *pKey, int nKey, const void *pVal, int nVal);
-
-/*
-** Delete a value from the database. No error is returned if the specified
-** key value does not exist in the database.
-*/
-int lsm_delete(lsm_db *, const void *pKey, int nKey);
-
-/*
-** Delete all database entries with keys that are greater than (pKey1/nKey1)
-** and smaller than (pKey2/nKey2). Note that keys (pKey1/nKey1) and
-** (pKey2/nKey2) themselves, if they exist in the database, are not deleted.
-**
-** Return LSM_OK if successful, or an LSM error code otherwise.
-*/
-int lsm_delete_range(lsm_db *,
- const void *pKey1, int nKey1, const void *pKey2, int nKey2
-);
-
-/*
-** CAPI: Explicit Database Work and Checkpointing
-**
-** This function is called by a thread to work on the database structure.
-*/
-int lsm_work(lsm_db *pDb, int nMerge, int nKB, int *pnWrite);
-
-int lsm_flush(lsm_db *pDb);
-
-/*
-** Attempt to checkpoint the current database snapshot. Return an LSM
-** error code if an error occurs or LSM_OK otherwise.
-**
-** If the current snapshot has already been checkpointed, calling this
-** function is a no-op. In this case if pnKB is not NULL, *pnKB is
-** set to 0. Or, if the current snapshot is successfully checkpointed
-** by this function and pbKB is not NULL, *pnKB is set to the number
-** of bytes written to the database file since the previous checkpoint
-** (the same measure as returned by the LSM_INFO_CHECKPOINT_SIZE query).
-*/
-int lsm_checkpoint(lsm_db *pDb, int *pnKB);
-
-/*
-** CAPI: Opening and Closing Database Cursors
-**
-** Open and close a database cursor.
-*/
-int lsm_csr_open(lsm_db *pDb, lsm_cursor **ppCsr);
-int lsm_csr_close(lsm_cursor *pCsr);
-
-/*
-** CAPI: Positioning Database Cursors
-**
-** If the fourth parameter is LSM_SEEK_EQ, LSM_SEEK_GE or LSM_SEEK_LE,
-** this function searches the database for an entry with key (pKey/nKey).
-** If an error occurs, an LSM error code is returned. Otherwise, LSM_OK.
-**
-** If no error occurs and the requested key is present in the database, the
-** cursor is left pointing to the entry with the specified key. Or, if the
-** specified key is not present in the database the state of the cursor
-** depends on the value passed as the final parameter, as follows:
-**
-** LSM_SEEK_EQ:
-** The cursor is left at EOF (invalidated). A call to lsm_csr_valid()
-** returns non-zero.
-**
-** LSM_SEEK_LE:
-** The cursor is left pointing to the largest key in the database that
-** is smaller than (pKey/nKey). If the database contains no keys smaller
-** than (pKey/nKey), the cursor is left at EOF.
-**
-** LSM_SEEK_GE:
-** The cursor is left pointing to the smallest key in the database that
-** is larger than (pKey/nKey). If the database contains no keys larger
-** than (pKey/nKey), the cursor is left at EOF.
-**
-** If the fourth parameter is LSM_SEEK_LEFAST, this function searches the
-** database in a similar manner to LSM_SEEK_LE, with two differences:
-**
-** <ol><li>Even if a key can be found (the cursor is not left at EOF), the
-** lsm_csr_value() function may not be used (attempts to do so return
-** LSM_MISUSE).
-**
-** <li>The key that the cursor is left pointing to may be one that has
-** been recently deleted from the database. In this case it is
-** guaranteed that the returned key is larger than any key currently
-** in the database that is less than or equal to (pKey/nKey).
-** </ol>
-**
-** LSM_SEEK_LEFAST requests are intended to be used to allocate database
-** keys.
-*/
-int lsm_csr_seek(lsm_cursor *pCsr, const void *pKey, int nKey, int eSeek);
-
-int lsm_csr_first(lsm_cursor *pCsr);
-int lsm_csr_last(lsm_cursor *pCsr);
-
-/*
-** Advance the specified cursor to the next or previous key in the database.
-** Return LSM_OK if successful, or an LSM error code otherwise.
-**
-** Functions lsm_csr_seek(), lsm_csr_first() and lsm_csr_last() are "seek"
-** functions. Whether or not lsm_csr_next and lsm_csr_prev may be called
-** successfully also depends on the most recent seek function called on
-** the cursor. Specifically:
-**
-** <ul>
-** <li> At least one seek function must have been called on the cursor.
-** <li> To call lsm_csr_next(), the most recent call to a seek function must
-** have been either lsm_csr_first() or a call to lsm_csr_seek() specifying
-** LSM_SEEK_GE.
-** <li> To call lsm_csr_prev(), the most recent call to a seek function must
-** have been either lsm_csr_last() or a call to lsm_csr_seek() specifying
-** LSM_SEEK_LE.
-** </ul>
-**
-** Otherwise, if the above conditions are not met when lsm_csr_next or
-** lsm_csr_prev is called, LSM_MISUSE is returned and the cursor position
-** remains unchanged.
-*/
-int lsm_csr_next(lsm_cursor *pCsr);
-int lsm_csr_prev(lsm_cursor *pCsr);
-
-/*
-** Values that may be passed as the fourth argument to lsm_csr_seek().
-*/
-#define LSM_SEEK_LEFAST -2
-#define LSM_SEEK_LE -1
-#define LSM_SEEK_EQ 0
-#define LSM_SEEK_GE 1
-
-/*
-** CAPI: Extracting Data From Database Cursors
-**
-** Retrieve data from a database cursor.
-*/
-int lsm_csr_valid(lsm_cursor *pCsr);
-int lsm_csr_key(lsm_cursor *pCsr, const void **ppKey, int *pnKey);
-int lsm_csr_value(lsm_cursor *pCsr, const void **ppVal, int *pnVal);
-
-/*
-** If no error occurs, this function compares the database key passed via
-** the pKey/nKey arguments with the key that the cursor passed as the first
-** argument currently points to. If the cursors key is less than, equal to
-** or greater than pKey/nKey, *piRes is set to less than, equal to or greater
-** than zero before returning. LSM_OK is returned in this case.
-**
-** Or, if an error occurs, an LSM error code is returned and the final
-** value of *piRes is undefined. If the cursor does not point to a valid
-** key when this function is called, LSM_MISUSE is returned.
-*/
-int lsm_csr_cmp(lsm_cursor *pCsr, const void *pKey, int nKey, int *piRes);
-
-/*
-** CAPI: Change these!!
-**
-** Configure a callback to which debugging and other messages should
-** be directed. Only useful for debugging lsm.
-*/
-void lsm_config_log(lsm_db *, void (*)(void *, int, const char *), void *);
-
-/*
-** Configure a callback that is invoked if the database connection ever
-** writes to the database file.
-*/
-void lsm_config_work_hook(lsm_db *, void (*)(lsm_db *, void *), void *);
-
-/* ENDOFAPI */
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-#endif /* ifndef _LSM_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsmInt.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsmInt.h
deleted file mode 100644
index 0f822e47932..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsmInt.h
+++ /dev/null
@@ -1,993 +0,0 @@
-/*
-** 2011-08-18
-**
-** 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.
-**
-*************************************************************************
-** Internal structure definitions for the LSM module.
-*/
-#ifndef _LSM_INT_H
-#define _LSM_INT_H
-
-#include "lsm.h"
-#include <assert.h>
-#include <string.h>
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#ifdef _WIN32
-# ifdef _MSC_VER
-# define snprintf _snprintf
-# endif
-#else
-# include <unistd.h>
-#endif
-
-#ifdef NDEBUG
-# ifdef LSM_DEBUG_EXPENSIVE
-# undef LSM_DEBUG_EXPENSIVE
-# endif
-# ifdef LSM_DEBUG
-# undef LSM_DEBUG
-# endif
-#else
-# ifndef LSM_DEBUG
-# define LSM_DEBUG
-# endif
-#endif
-
-/*
-** Default values for various data structure parameters. These may be
-** overridden by calls to lsm_config().
-*/
-#define LSM_DFLT_PAGE_SIZE (4 * 1024)
-#define LSM_DFLT_BLOCK_SIZE (1 * 1024 * 1024)
-#define LSM_DFLT_AUTOFLUSH (1 * 1024 * 1024)
-#define LSM_DFLT_AUTOCHECKPOINT (i64)(2 * 1024 * 1024)
-#define LSM_DFLT_AUTOWORK 1
-#define LSM_DFLT_LOG_SIZE (128*1024)
-#define LSM_DFLT_AUTOMERGE 4
-#define LSM_DFLT_SAFETY LSM_SAFETY_NORMAL
-#define LSM_DFLT_MMAP (LSM_IS_64_BIT ? 1 : 32768)
-#define LSM_DFLT_MULTIPLE_PROCESSES 1
-#define LSM_DFLT_USE_LOG 1
-
-/* Initial values for log file checksums. These are only used if the
-** database file does not contain a valid checkpoint. */
-#define LSM_CKSUM0_INIT 42
-#define LSM_CKSUM1_INIT 42
-
-/* "mmap" mode is currently only used in environments with 64-bit address
-** spaces. The following macro is used to test for this. */
-#define LSM_IS_64_BIT (sizeof(void*)==8)
-
-#define LSM_AUTOWORK_QUANT 32
-
-typedef struct Database Database;
-typedef struct DbLog DbLog;
-typedef struct FileSystem FileSystem;
-typedef struct Freelist Freelist;
-typedef struct FreelistEntry FreelistEntry;
-typedef struct Level Level;
-typedef struct LogMark LogMark;
-typedef struct LogRegion LogRegion;
-typedef struct LogWriter LogWriter;
-typedef struct LsmString LsmString;
-typedef struct Mempool Mempool;
-typedef struct Merge Merge;
-typedef struct MergeInput MergeInput;
-typedef struct MetaPage MetaPage;
-typedef struct MultiCursor MultiCursor;
-typedef struct Page Page;
-typedef struct Redirect Redirect;
-typedef struct Segment Segment;
-typedef struct SegmentMerger SegmentMerger;
-typedef struct ShmChunk ShmChunk;
-typedef struct ShmHeader ShmHeader;
-typedef struct ShmReader ShmReader;
-typedef struct Snapshot Snapshot;
-typedef struct TransMark TransMark;
-typedef struct Tree Tree;
-typedef struct TreeCursor TreeCursor;
-typedef struct TreeHeader TreeHeader;
-typedef struct TreeMark TreeMark;
-typedef struct TreeRoot TreeRoot;
-
-#ifndef _SQLITEINT_H_
-typedef unsigned char u8;
-typedef unsigned short int u16;
-typedef unsigned int u32;
-typedef lsm_i64 i64;
-typedef unsigned long long int u64;
-#endif
-
-/* A page number is a 64-bit integer. */
-typedef i64 LsmPgno;
-
-#ifdef LSM_DEBUG
-int lsmErrorBkpt(int);
-#else
-# define lsmErrorBkpt(x) (x)
-#endif
-
-#define LSM_PROTOCOL_BKPT lsmErrorBkpt(LSM_PROTOCOL)
-#define LSM_IOERR_BKPT lsmErrorBkpt(LSM_IOERR)
-#define LSM_NOMEM_BKPT lsmErrorBkpt(LSM_NOMEM)
-#define LSM_CORRUPT_BKPT lsmErrorBkpt(LSM_CORRUPT)
-#define LSM_MISUSE_BKPT lsmErrorBkpt(LSM_MISUSE)
-
-#define unused_parameter(x) (void)(x)
-#define array_size(x) (sizeof(x)/sizeof(x[0]))
-
-
-/* The size of each shared-memory chunk */
-#define LSM_SHM_CHUNK_SIZE (32*1024)
-
-/* The number of bytes reserved at the start of each shm chunk for MM. */
-#define LSM_SHM_CHUNK_HDR (sizeof(ShmChunk))
-
-/* The number of available read locks. */
-#define LSM_LOCK_NREADER 6
-
-/* The number of available read-write client locks. */
-#define LSM_LOCK_NRWCLIENT 16
-
-/* Lock definitions.
-*/
-#define LSM_LOCK_DMS1 1 /* Serialize connect/disconnect ops */
-#define LSM_LOCK_DMS2 2 /* Read-write connections */
-#define LSM_LOCK_DMS3 3 /* Read-only connections */
-#define LSM_LOCK_WRITER 4
-#define LSM_LOCK_WORKER 5
-#define LSM_LOCK_CHECKPOINTER 6
-#define LSM_LOCK_ROTRANS 7
-#define LSM_LOCK_READER(i) ((i) + LSM_LOCK_ROTRANS + 1)
-#define LSM_LOCK_RWCLIENT(i) ((i) + LSM_LOCK_READER(LSM_LOCK_NREADER))
-
-#define LSM_N_LOCK LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT)
-
-/*
-** Meta-page size and usable size.
-*/
-#define LSM_META_PAGE_SIZE 4096
-
-#define LSM_META_RW_PAGE_SIZE (LSM_META_PAGE_SIZE - LSM_N_LOCK)
-
-/*
-** Hard limit on the number of free-list entries that may be stored in
-** a checkpoint (the remainder are stored as a system record in the LSM).
-** See also LSM_CONFIG_MAX_FREELIST.
-*/
-#define LSM_MAX_FREELIST_ENTRIES 24
-
-#define LSM_MAX_BLOCK_REDIRECTS 16
-
-#define LSM_ATTEMPTS_BEFORE_PROTOCOL 10000
-
-
-/*
-** Each entry stored in the LSM (or in-memory tree structure) has an
-** associated mask of the following flags.
-*/
-#define LSM_START_DELETE 0x01 /* Start of open-ended delete range */
-#define LSM_END_DELETE 0x02 /* End of open-ended delete range */
-#define LSM_POINT_DELETE 0x04 /* Delete this key */
-#define LSM_INSERT 0x08 /* Insert this key and value */
-#define LSM_SEPARATOR 0x10 /* True if entry is separator key only */
-#define LSM_SYSTEMKEY 0x20 /* True if entry is a system key (FREELIST) */
-
-#define LSM_CONTIGUOUS 0x40 /* Used in lsm_tree.c */
-
-/*
-** A string that can grow by appending.
-*/
-struct LsmString {
- lsm_env *pEnv; /* Run-time environment */
- int n; /* Size of string. -1 indicates error */
- int nAlloc; /* Space allocated for z[] */
- char *z; /* The string content */
-};
-
-typedef struct LsmFile LsmFile;
-struct LsmFile {
- lsm_file *pFile;
- LsmFile *pNext;
-};
-
-/*
-** An instance of the following type is used to store an ordered list of
-** u32 values.
-**
-** Note: This is a place-holder implementation. It should be replaced by
-** a version that avoids making a single large allocation when the array
-** contains a large number of values. For this reason, the internals of
-** this object should only manipulated by the intArrayXXX() functions in
-** lsm_tree.c.
-*/
-typedef struct IntArray IntArray;
-struct IntArray {
- int nAlloc;
- int nArray;
- u32 *aArray;
-};
-
-struct Redirect {
- int n; /* Number of redirects */
- struct RedirectEntry {
- int iFrom;
- int iTo;
- } *a;
-};
-
-/*
-** An instance of this structure represents a point in the history of the
-** tree structure to roll back to. Refer to comments in lsm_tree.c for
-** details.
-*/
-struct TreeMark {
- u32 iRoot; /* Offset of root node in shm file */
- u32 nHeight; /* Current height of tree structure */
- u32 iWrite; /* Write offset in shm file */
- u32 nChunk; /* Number of chunks in shared-memory file */
- u32 iFirst; /* First chunk in linked list */
- u32 iNextShmid; /* Next id to allocate */
- int iRollback; /* Index in lsm->rollback to revert to */
-};
-
-/*
-** An instance of this structure represents a point in the database log.
-*/
-struct LogMark {
- i64 iOff; /* Offset into log (see lsm_log.c) */
- int nBuf; /* Size of in-memory buffer here */
- u8 aBuf[8]; /* Bytes of content in aBuf[] */
- u32 cksum0; /* Checksum 0 at offset (iOff-nBuf) */
- u32 cksum1; /* Checksum 1 at offset (iOff-nBuf) */
-};
-
-struct TransMark {
- TreeMark tree;
- LogMark log;
-};
-
-/*
-** A structure that defines the start and end offsets of a region in the
-** log file. The size of the region in bytes is (iEnd - iStart), so if
-** iEnd==iStart the region is zero bytes in size.
-*/
-struct LogRegion {
- i64 iStart; /* Start of region in log file */
- i64 iEnd; /* End of region in log file */
-};
-
-struct DbLog {
- u32 cksum0; /* Checksum 0 at offset iOff */
- u32 cksum1; /* Checksum 1 at offset iOff */
- i64 iSnapshotId; /* Log space has been reclaimed to this ss */
- LogRegion aRegion[3]; /* Log file regions (see docs in lsm_log.c) */
-};
-
-struct TreeRoot {
- u32 iRoot;
- u32 nHeight;
- u32 nByte; /* Total size of this tree in bytes */
- u32 iTransId;
-};
-
-/*
-** Tree header structure.
-*/
-struct TreeHeader {
- u32 iUsedShmid; /* Id of first shm chunk used by this tree */
- u32 iNextShmid; /* Shm-id of next chunk allocated */
- u32 iFirst; /* Chunk number of smallest shm-id */
- u32 nChunk; /* Number of chunks in shared-memory file */
- TreeRoot root; /* Root and height of current tree */
- u32 iWrite; /* Write offset in shm file */
- TreeRoot oldroot; /* Root and height of the previous tree */
- u32 iOldShmid; /* Last shm-id used by previous tree */
- u32 iUsrVersion; /* get/set_user_version() value */
- i64 iOldLog; /* Log offset associated with old tree */
- u32 oldcksum0;
- u32 oldcksum1;
- DbLog log; /* Current layout of log file */
- u32 aCksum[2]; /* Checksums 1 and 2. */
-};
-
-/*
-** Database handle structure.
-**
-** mLock:
-** A bitmask representing the locks currently held by the connection.
-** An LSM database supports N distinct locks, where N is some number less
-** than or equal to 32. Locks are numbered starting from 1 (see the
-** definitions for LSM_LOCK_WRITER and co.).
-**
-** The least significant 32-bits in mLock represent EXCLUSIVE locks. The
-** most significant are SHARED locks. So, if a connection holds a SHARED
-** lock on lock region iLock, then the following is true:
-**
-** (mLock & ((iLock+32-1) << 1))
-**
-** Or for an EXCLUSIVE lock:
-**
-** (mLock & ((iLock-1) << 1))
-**
-** pCsr:
-** Points to the head of a linked list that contains all currently open
-** cursors. Once this list becomes empty, the user has no outstanding
-** cursors and the database handle can be successfully closed.
-**
-** pCsrCache:
-** This list contains cursor objects that have been closed using
-** lsm_csr_close(). Each time a cursor is closed, it is shifted from
-** the pCsr list to this list. When a new cursor is opened, this list
-** is inspected to see if there exists a cursor object that can be
-** reused. This is an optimization only.
-*/
-struct lsm_db {
-
- /* Database handle configuration */
- lsm_env *pEnv; /* runtime environment */
- int (*xCmp)(void *, int, void *, int); /* Compare function */
-
- /* Values configured by calls to lsm_config */
- int eSafety; /* LSM_SAFETY_OFF, NORMAL or FULL */
- int bAutowork; /* Configured by LSM_CONFIG_AUTOWORK */
- int nTreeLimit; /* Configured by LSM_CONFIG_AUTOFLUSH */
- int nMerge; /* Configured by LSM_CONFIG_AUTOMERGE */
- int bUseLog; /* Configured by LSM_CONFIG_USE_LOG */
- int nDfltPgsz; /* Configured by LSM_CONFIG_PAGE_SIZE */
- int nDfltBlksz; /* Configured by LSM_CONFIG_BLOCK_SIZE */
- int nMaxFreelist; /* Configured by LSM_CONFIG_MAX_FREELIST */
- int iMmap; /* Configured by LSM_CONFIG_MMAP */
- i64 nAutockpt; /* Configured by LSM_CONFIG_AUTOCHECKPOINT */
- int bMultiProc; /* Configured by L_C_MULTIPLE_PROCESSES */
- int bReadonly; /* Configured by LSM_CONFIG_READONLY */
- lsm_compress compress; /* Compression callbacks */
- lsm_compress_factory factory; /* Compression callback factory */
-
- /* Sub-system handles */
- FileSystem *pFS; /* On-disk portion of database */
- Database *pDatabase; /* Database shared data */
-
- int iRwclient; /* Read-write client lock held (-1 == none) */
-
- /* Client transaction context */
- Snapshot *pClient; /* Client snapshot */
- int iReader; /* Read lock held (-1 == unlocked) */
- int bRoTrans; /* True if a read-only db trans is open */
- MultiCursor *pCsr; /* List of all open cursors */
- LogWriter *pLogWriter; /* Context for writing to the log file */
- int nTransOpen; /* Number of opened write transactions */
- int nTransAlloc; /* Allocated size of aTrans[] array */
- TransMark *aTrans; /* Array of marks for transaction rollback */
- IntArray rollback; /* List of tree-nodes to roll back */
- int bDiscardOld; /* True if lsmTreeDiscardOld() was called */
-
- MultiCursor *pCsrCache; /* List of all closed cursors */
-
- /* Worker context */
- Snapshot *pWorker; /* Worker snapshot (or NULL) */
- Freelist *pFreelist; /* See sortedNewToplevel() */
- int bUseFreelist; /* True to use pFreelist */
- int bIncrMerge; /* True if currently doing a merge */
-
- int bInFactory; /* True if within factory.xFactory() */
-
- /* Debugging message callback */
- void (*xLog)(void *, int, const char *);
- void *pLogCtx;
-
- /* Work done notification callback */
- void (*xWork)(lsm_db *, void *);
- void *pWorkCtx;
-
- u64 mLock; /* Mask of current locks. See lsmShmLock(). */
- lsm_db *pNext; /* Next connection to same database */
-
- int nShm; /* Size of apShm[] array */
- void **apShm; /* Shared memory chunks */
- ShmHeader *pShmhdr; /* Live shared-memory header */
- TreeHeader treehdr; /* Local copy of tree-header */
- u32 aSnapshot[LSM_META_PAGE_SIZE / sizeof(u32)];
-};
-
-struct Segment {
- LsmPgno iFirst; /* First page of this run */
- LsmPgno iLastPg; /* Last page of this run */
- LsmPgno iRoot; /* Root page number (if any) */
- int nSize; /* Size of this run in pages */
-
- Redirect *pRedirect; /* Block redirects (or NULL) */
-};
-
-/*
-** iSplitTopic/pSplitKey/nSplitKey:
-** If nRight>0, this buffer contains a copy of the largest key that has
-** already been written to the left-hand-side of the level.
-*/
-struct Level {
- Segment lhs; /* Left-hand (main) segment */
- int nRight; /* Size of apRight[] array */
- Segment *aRhs; /* Old segments being merged into this */
- int iSplitTopic; /* Split key topic (if nRight>0) */
- void *pSplitKey; /* Pointer to split-key (if nRight>0) */
- int nSplitKey; /* Number of bytes in split-key */
-
- u16 iAge; /* Number of times data has been written */
- u16 flags; /* Mask of LEVEL_XXX bits */
- Merge *pMerge; /* Merge operation currently underway */
- Level *pNext; /* Next level in tree */
-};
-
-/*
-** The Level.flags field is set to a combination of the following bits.
-**
-** LEVEL_FREELIST_ONLY:
-** Set if the level consists entirely of free-list entries.
-**
-** LEVEL_INCOMPLETE:
-** This is set while a new toplevel level is being constructed. It is
-** never set for any level other than a new toplevel.
-*/
-#define LEVEL_FREELIST_ONLY 0x0001
-#define LEVEL_INCOMPLETE 0x0002
-
-
-/*
-** A structure describing an ongoing merge. There is an instance of this
-** structure for every Level currently undergoing a merge in the worker
-** snapshot.
-**
-** It is assumed that code that uses an instance of this structure has
-** access to the associated Level struct.
-**
-** iOutputOff:
-** The byte offset to write to next within the last page of the
-** output segment.
-*/
-struct MergeInput {
- LsmPgno iPg; /* Page on which next input is stored */
- int iCell; /* Cell containing next input to merge */
-};
-struct Merge {
- int nInput; /* Number of input runs being merged */
- MergeInput *aInput; /* Array nInput entries in size */
- MergeInput splitkey; /* Location in file of current splitkey */
- int nSkip; /* Number of separators entries to skip */
- int iOutputOff; /* Write offset on output page */
- LsmPgno iCurrentPtr; /* Current pointer value */
-};
-
-/*
-** The first argument to this macro is a pointer to a Segment structure.
-** Returns true if the structure instance indicates that the separators
-** array is valid.
-*/
-#define segmentHasSeparators(pSegment) ((pSegment)->sep.iFirst>0)
-
-/*
-** The values that accompany the lock held by a database reader.
-*/
-struct ShmReader {
- u32 iTreeId;
- i64 iLsmId;
-};
-
-/*
-** An instance of this structure is stored in the first shared-memory
-** page. The shared-memory header.
-**
-** bWriter:
-** Immediately after opening a write transaction taking the WRITER lock,
-** each writer client sets this flag. It is cleared right before the
-** WRITER lock is relinquished. If a subsequent writer finds that this
-** flag is already set when a write transaction is opened, this indicates
-** that a previous writer failed mid-transaction.
-**
-** iMetaPage:
-** If the database file does not contain a valid, synced, checkpoint, this
-** value is set to 0. Otherwise, it is set to the meta-page number that
-** contains the most recently written checkpoint (either 1 or 2).
-**
-** hdr1, hdr2:
-** The two copies of the in-memory tree header. Two copies are required
-** in case a writer fails while updating one of them.
-*/
-struct ShmHeader {
- u32 aSnap1[LSM_META_PAGE_SIZE / 4];
- u32 aSnap2[LSM_META_PAGE_SIZE / 4];
- u32 bWriter;
- u32 iMetaPage;
- TreeHeader hdr1;
- TreeHeader hdr2;
- ShmReader aReader[LSM_LOCK_NREADER];
-};
-
-/*
-** An instance of this structure is stored at the start of each shared-memory
-** chunk except the first (which is the header chunk - see above).
-*/
-struct ShmChunk {
- u32 iShmid;
- u32 iNext;
-};
-
-/*
-** Maximum number of shared-memory chunks allowed in the *-shm file. Since
-** each shared-memory chunk is 32KB in size, this is a theoretical limit only.
-*/
-#define LSM_MAX_SHMCHUNKS (1<<30)
-
-/* Return true if shm-sequence "a" is larger than or equal to "b" */
-#define shm_sequence_ge(a, b) (((u32)a-(u32)b) < LSM_MAX_SHMCHUNKS)
-
-#define LSM_APPLIST_SZ 4
-
-/*
-** An instance of the following structure stores the in-memory part of
-** the current free block list. This structure is to the free block list
-** as the in-memory tree is to the users database content. The contents
-** of the free block list is found by merging the in-memory components
-** with those stored in the LSM, just as the contents of the database is
-** found by merging the in-memory tree with the user data entries in the
-** LSM.
-**
-** Each FreelistEntry structure in the array represents either an insert
-** or delete operation on the free-list. For deletes, the FreelistEntry.iId
-** field is set to -1. For inserts, it is set to zero or greater.
-**
-** The array of FreelistEntry structures is always sorted in order of
-** block number (ascending).
-**
-** When the in-memory free block list is written into the LSM, each insert
-** operation is written separately. The entry key is the bitwise inverse
-** of the block number as a 32-bit big-endian integer. This is done so that
-** the entries in the LSM are sorted in descending order of block id.
-** The associated value is the snapshot id, formated as a varint.
-*/
-struct Freelist {
- FreelistEntry *aEntry; /* Free list entries */
- int nEntry; /* Number of valid slots in aEntry[] */
- int nAlloc; /* Allocated size of aEntry[] */
-};
-struct FreelistEntry {
- u32 iBlk; /* Block number */
- i64 iId; /* Largest snapshot id to use this block */
-};
-
-/*
-** A snapshot of a database. A snapshot contains all the information required
-** to read or write a database file on disk. See the description of struct
-** Database below for futher details.
-*/
-struct Snapshot {
- Database *pDatabase; /* Database this snapshot belongs to */
- u32 iCmpId; /* Id of compression scheme */
- Level *pLevel; /* Pointer to level 0 of snapshot (or NULL) */
- i64 iId; /* Snapshot id */
- i64 iLogOff; /* Log file offset */
- Redirect redirect; /* Block redirection array */
-
- /* Used by worker snapshots only */
- int nBlock; /* Number of blocks in database file */
- LsmPgno aiAppend[LSM_APPLIST_SZ]; /* Append point list */
- Freelist freelist; /* Free block list */
- u32 nWrite; /* Total number of pages written to disk */
-};
-#define LSM_INITIAL_SNAPSHOT_ID 11
-
-/*
-** Functions from file "lsm_ckpt.c".
-*/
-int lsmCheckpointWrite(lsm_db *, u32 *);
-int lsmCheckpointLevels(lsm_db *, int, void **, int *);
-int lsmCheckpointLoadLevels(lsm_db *pDb, void *pVal, int nVal);
-
-int lsmCheckpointRecover(lsm_db *);
-int lsmCheckpointDeserialize(lsm_db *, int, u32 *, Snapshot **);
-
-int lsmCheckpointLoadWorker(lsm_db *pDb);
-int lsmCheckpointStore(lsm_db *pDb, int);
-
-int lsmCheckpointLoad(lsm_db *pDb, int *);
-int lsmCheckpointLoadOk(lsm_db *pDb, int);
-int lsmCheckpointClientCacheOk(lsm_db *);
-
-u32 lsmCheckpointNBlock(u32 *);
-i64 lsmCheckpointId(u32 *, int);
-u32 lsmCheckpointNWrite(u32 *, int);
-i64 lsmCheckpointLogOffset(u32 *);
-int lsmCheckpointPgsz(u32 *);
-int lsmCheckpointBlksz(u32 *);
-void lsmCheckpointLogoffset(u32 *aCkpt, DbLog *pLog);
-void lsmCheckpointZeroLogoffset(lsm_db *);
-
-int lsmCheckpointSaveWorker(lsm_db *pDb, int);
-int lsmDatabaseFull(lsm_db *pDb);
-int lsmCheckpointSynced(lsm_db *pDb, i64 *piId, i64 *piLog, u32 *pnWrite);
-
-int lsmCheckpointSize(lsm_db *db, int *pnByte);
-
-int lsmInfoCompressionId(lsm_db *db, u32 *piCmpId);
-
-/*
-** Functions from file "lsm_tree.c".
-*/
-int lsmTreeNew(lsm_env *, int (*)(void *, int, void *, int), Tree **ppTree);
-void lsmTreeRelease(lsm_env *, Tree *);
-int lsmTreeInit(lsm_db *);
-int lsmTreeRepair(lsm_db *);
-
-void lsmTreeMakeOld(lsm_db *pDb);
-void lsmTreeDiscardOld(lsm_db *pDb);
-int lsmTreeHasOld(lsm_db *pDb);
-
-int lsmTreeSize(lsm_db *);
-int lsmTreeEndTransaction(lsm_db *pDb, int bCommit);
-int lsmTreeLoadHeader(lsm_db *pDb, int *);
-int lsmTreeLoadHeaderOk(lsm_db *, int);
-
-int lsmTreeInsert(lsm_db *pDb, void *pKey, int nKey, void *pVal, int nVal);
-int lsmTreeDelete(lsm_db *db, void *pKey1, int nKey1, void *pKey2, int nKey2);
-void lsmTreeRollback(lsm_db *pDb, TreeMark *pMark);
-void lsmTreeMark(lsm_db *pDb, TreeMark *pMark);
-
-int lsmTreeCursorNew(lsm_db *pDb, int, TreeCursor **);
-void lsmTreeCursorDestroy(TreeCursor *);
-
-int lsmTreeCursorSeek(TreeCursor *pCsr, void *pKey, int nKey, int *pRes);
-int lsmTreeCursorNext(TreeCursor *pCsr);
-int lsmTreeCursorPrev(TreeCursor *pCsr);
-int lsmTreeCursorEnd(TreeCursor *pCsr, int bLast);
-void lsmTreeCursorReset(TreeCursor *pCsr);
-int lsmTreeCursorKey(TreeCursor *pCsr, int *pFlags, void **ppKey, int *pnKey);
-int lsmTreeCursorFlags(TreeCursor *pCsr);
-int lsmTreeCursorValue(TreeCursor *pCsr, void **ppVal, int *pnVal);
-int lsmTreeCursorValid(TreeCursor *pCsr);
-int lsmTreeCursorSave(TreeCursor *pCsr);
-
-void lsmFlagsToString(int flags, char *zFlags);
-
-/*
-** Functions from file "mem.c".
-*/
-void *lsmMalloc(lsm_env*, size_t);
-void lsmFree(lsm_env*, void *);
-void *lsmRealloc(lsm_env*, void *, size_t);
-void *lsmReallocOrFree(lsm_env*, void *, size_t);
-void *lsmReallocOrFreeRc(lsm_env *, void *, size_t, int *);
-
-void *lsmMallocZeroRc(lsm_env*, size_t, int *);
-void *lsmMallocRc(lsm_env*, size_t, int *);
-
-void *lsmMallocZero(lsm_env *pEnv, size_t);
-char *lsmMallocStrdup(lsm_env *pEnv, const char *);
-
-/*
-** Functions from file "lsm_mutex.c".
-*/
-int lsmMutexStatic(lsm_env*, int, lsm_mutex **);
-int lsmMutexNew(lsm_env*, lsm_mutex **);
-void lsmMutexDel(lsm_env*, lsm_mutex *);
-void lsmMutexEnter(lsm_env*, lsm_mutex *);
-int lsmMutexTry(lsm_env*, lsm_mutex *);
-void lsmMutexLeave(lsm_env*, lsm_mutex *);
-
-#ifndef NDEBUG
-int lsmMutexHeld(lsm_env *, lsm_mutex *);
-int lsmMutexNotHeld(lsm_env *, lsm_mutex *);
-#endif
-
-/**************************************************************************
-** Start of functions from "lsm_file.c".
-*/
-int lsmFsOpen(lsm_db *, const char *, int);
-int lsmFsOpenLog(lsm_db *, int *);
-void lsmFsCloseLog(lsm_db *);
-void lsmFsClose(FileSystem *);
-
-int lsmFsUnmap(FileSystem *);
-
-int lsmFsConfigure(lsm_db *db);
-
-int lsmFsBlockSize(FileSystem *);
-void lsmFsSetBlockSize(FileSystem *, int);
-int lsmFsMoveBlock(FileSystem *pFS, Segment *pSeg, int iTo, int iFrom);
-
-int lsmFsPageSize(FileSystem *);
-void lsmFsSetPageSize(FileSystem *, int);
-
-int lsmFsFileid(lsm_db *pDb, void **ppId, int *pnId);
-
-/* Creating, populating, gobbling and deleting sorted runs. */
-void lsmFsGobble(lsm_db *, Segment *, LsmPgno *, int);
-int lsmFsSortedDelete(FileSystem *, Snapshot *, int, Segment *);
-int lsmFsSortedFinish(FileSystem *, Segment *);
-int lsmFsSortedAppend(FileSystem *, Snapshot *, Level *, int, Page **);
-int lsmFsSortedPadding(FileSystem *, Snapshot *, Segment *);
-
-/* Functions to retrieve the lsm_env pointer from a FileSystem or Page object */
-lsm_env *lsmFsEnv(FileSystem *);
-lsm_env *lsmPageEnv(Page *);
-FileSystem *lsmPageFS(Page *);
-
-int lsmFsSectorSize(FileSystem *);
-
-void lsmSortedSplitkey(lsm_db *, Level *, int *);
-
-/* Reading sorted run content. */
-int lsmFsDbPageLast(FileSystem *pFS, Segment *pSeg, Page **ppPg);
-int lsmFsDbPageGet(FileSystem *, Segment *, LsmPgno, Page **);
-int lsmFsDbPageNext(Segment *, Page *, int eDir, Page **);
-
-u8 *lsmFsPageData(Page *, int *);
-int lsmFsPageRelease(Page *);
-int lsmFsPagePersist(Page *);
-void lsmFsPageRef(Page *);
-LsmPgno lsmFsPageNumber(Page *);
-
-int lsmFsNRead(FileSystem *);
-int lsmFsNWrite(FileSystem *);
-
-int lsmFsMetaPageGet(FileSystem *, int, int, MetaPage **);
-int lsmFsMetaPageRelease(MetaPage *);
-u8 *lsmFsMetaPageData(MetaPage *, int *);
-
-#ifdef LSM_DEBUG
-int lsmFsDbPageIsLast(Segment *pSeg, Page *pPg);
-int lsmFsIntegrityCheck(lsm_db *);
-#endif
-
-LsmPgno lsmFsRedirectPage(FileSystem *, Redirect *, LsmPgno);
-
-int lsmFsPageWritable(Page *);
-
-/* Functions to read, write and sync the log file. */
-int lsmFsWriteLog(FileSystem *pFS, i64 iOff, LsmString *pStr);
-int lsmFsSyncLog(FileSystem *pFS);
-int lsmFsReadLog(FileSystem *pFS, i64 iOff, int nRead, LsmString *pStr);
-int lsmFsTruncateLog(FileSystem *pFS, i64 nByte);
-int lsmFsTruncateDb(FileSystem *pFS, i64 nByte);
-int lsmFsCloseAndDeleteLog(FileSystem *pFS);
-
-LsmFile *lsmFsDeferClose(FileSystem *pFS);
-
-/* And to sync the db file */
-int lsmFsSyncDb(FileSystem *, int);
-
-void lsmFsFlushWaiting(FileSystem *, int *);
-
-/* Used by lsm_info(ARRAY_STRUCTURE) and lsm_config(MMAP) */
-int lsmInfoArrayStructure(lsm_db *pDb, int bBlock, LsmPgno iFirst, char **pz);
-int lsmInfoArrayPages(lsm_db *pDb, LsmPgno iFirst, char **pzOut);
-int lsmConfigMmap(lsm_db *pDb, int *piParam);
-
-int lsmEnvOpen(lsm_env *, const char *, int, lsm_file **);
-int lsmEnvClose(lsm_env *pEnv, lsm_file *pFile);
-int lsmEnvLock(lsm_env *pEnv, lsm_file *pFile, int iLock, int eLock);
-int lsmEnvTestLock(lsm_env *pEnv, lsm_file *pFile, int iLock, int nLock, int);
-
-int lsmEnvShmMap(lsm_env *, lsm_file *, int, int, void **);
-void lsmEnvShmBarrier(lsm_env *);
-void lsmEnvShmUnmap(lsm_env *, lsm_file *, int);
-
-void lsmEnvSleep(lsm_env *, int);
-
-int lsmFsReadSyncedId(lsm_db *db, int, i64 *piVal);
-
-int lsmFsSegmentContainsPg(FileSystem *pFS, Segment *, LsmPgno, int *);
-
-void lsmFsPurgeCache(FileSystem *);
-
-/*
-** End of functions from "lsm_file.c".
-**************************************************************************/
-
-/*
-** Functions from file "lsm_sorted.c".
-*/
-int lsmInfoPageDump(lsm_db *, LsmPgno, int, char **);
-void lsmSortedCleanup(lsm_db *);
-int lsmSortedAutoWork(lsm_db *, int nUnit);
-
-int lsmSortedWalkFreelist(lsm_db *, int, int (*)(void *, int, i64), void *);
-
-int lsmSaveWorker(lsm_db *, int);
-
-int lsmFlushTreeToDisk(lsm_db *pDb);
-
-void lsmSortedRemap(lsm_db *pDb);
-
-void lsmSortedFreeLevel(lsm_env *pEnv, Level *);
-
-int lsmSortedAdvanceAll(lsm_db *pDb);
-
-int lsmSortedLoadMerge(lsm_db *, Level *, u32 *, int *);
-int lsmSortedLoadFreelist(lsm_db *pDb, void **, int *);
-
-void *lsmSortedSplitKey(Level *pLevel, int *pnByte);
-
-void lsmSortedSaveTreeCursors(lsm_db *);
-
-int lsmMCursorNew(lsm_db *, MultiCursor **);
-void lsmMCursorClose(MultiCursor *, int);
-int lsmMCursorSeek(MultiCursor *, int, void *, int , int);
-int lsmMCursorFirst(MultiCursor *);
-int lsmMCursorPrev(MultiCursor *);
-int lsmMCursorLast(MultiCursor *);
-int lsmMCursorValid(MultiCursor *);
-int lsmMCursorNext(MultiCursor *);
-int lsmMCursorKey(MultiCursor *, void **, int *);
-int lsmMCursorValue(MultiCursor *, void **, int *);
-int lsmMCursorType(MultiCursor *, int *);
-lsm_db *lsmMCursorDb(MultiCursor *);
-void lsmMCursorFreeCache(lsm_db *);
-
-int lsmSaveCursors(lsm_db *pDb);
-int lsmRestoreCursors(lsm_db *pDb);
-
-void lsmSortedDumpStructure(lsm_db *pDb, Snapshot *, int, int, const char *);
-void lsmFsDumpBlocklists(lsm_db *);
-
-void lsmSortedExpandBtreePage(Page *pPg, int nOrig);
-
-void lsmPutU32(u8 *, u32);
-u32 lsmGetU32(u8 *);
-u64 lsmGetU64(u8 *);
-
-/*
-** Functions from "lsm_varint.c".
-*/
-int lsmVarintPut32(u8 *, int);
-int lsmVarintGet32(u8 *, int *);
-int lsmVarintPut64(u8 *aData, i64 iVal);
-int lsmVarintGet64(const u8 *aData, i64 *piVal);
-
-int lsmVarintLen32(int);
-int lsmVarintSize(u8 c);
-
-/*
-** Functions from file "main.c".
-*/
-void lsmLogMessage(lsm_db *, int, const char *, ...);
-int lsmInfoFreelist(lsm_db *pDb, char **pzOut);
-
-/*
-** Functions from file "lsm_log.c".
-*/
-int lsmLogBegin(lsm_db *pDb);
-int lsmLogWrite(lsm_db *, int, void *, int, void *, int);
-int lsmLogCommit(lsm_db *);
-void lsmLogEnd(lsm_db *pDb, int bCommit);
-void lsmLogTell(lsm_db *, LogMark *);
-void lsmLogSeek(lsm_db *, LogMark *);
-void lsmLogClose(lsm_db *);
-
-int lsmLogRecover(lsm_db *);
-int lsmInfoLogStructure(lsm_db *pDb, char **pzVal);
-
-/* Valid values for the second argument to lsmLogWrite(). */
-#define LSM_WRITE 0x06
-#define LSM_DELETE 0x08
-#define LSM_DRANGE 0x0A
-
-/**************************************************************************
-** Functions from file "lsm_shared.c".
-*/
-
-int lsmDbDatabaseConnect(lsm_db*, const char *);
-void lsmDbDatabaseRelease(lsm_db *);
-
-int lsmBeginReadTrans(lsm_db *);
-int lsmBeginWriteTrans(lsm_db *);
-int lsmBeginFlush(lsm_db *);
-
-int lsmDetectRoTrans(lsm_db *db, int *);
-int lsmBeginRoTrans(lsm_db *db);
-
-int lsmBeginWork(lsm_db *);
-void lsmFinishWork(lsm_db *, int, int *);
-
-int lsmFinishRecovery(lsm_db *);
-void lsmFinishReadTrans(lsm_db *);
-int lsmFinishWriteTrans(lsm_db *, int);
-int lsmFinishFlush(lsm_db *, int);
-
-int lsmSnapshotSetFreelist(lsm_db *, int *, int);
-
-Snapshot *lsmDbSnapshotClient(lsm_db *);
-Snapshot *lsmDbSnapshotWorker(lsm_db *);
-
-void lsmSnapshotSetCkptid(Snapshot *, i64);
-
-Level *lsmDbSnapshotLevel(Snapshot *);
-void lsmDbSnapshotSetLevel(Snapshot *, Level *);
-
-void lsmDbRecoveryComplete(lsm_db *, int);
-
-int lsmBlockAllocate(lsm_db *, int, int *);
-int lsmBlockFree(lsm_db *, int);
-int lsmBlockRefree(lsm_db *, int);
-
-void lsmFreelistDeltaBegin(lsm_db *);
-void lsmFreelistDeltaEnd(lsm_db *);
-int lsmFreelistDelta(lsm_db *pDb);
-
-DbLog *lsmDatabaseLog(lsm_db *pDb);
-
-#ifdef LSM_DEBUG
- int lsmHoldingClientMutex(lsm_db *pDb);
- int lsmShmAssertLock(lsm_db *db, int iLock, int eOp);
- int lsmShmAssertWorker(lsm_db *db);
-#endif
-
-void lsmFreeSnapshot(lsm_env *, Snapshot *);
-
-
-/* Candidate values for the 3rd argument to lsmShmLock() */
-#define LSM_LOCK_UNLOCK 0
-#define LSM_LOCK_SHARED 1
-#define LSM_LOCK_EXCL 2
-
-int lsmShmCacheChunks(lsm_db *db, int nChunk);
-int lsmShmLock(lsm_db *db, int iLock, int eOp, int bBlock);
-int lsmShmTestLock(lsm_db *db, int iLock, int nLock, int eOp);
-void lsmShmBarrier(lsm_db *db);
-
-#ifdef LSM_DEBUG
-void lsmShmHasLock(lsm_db *db, int iLock, int eOp);
-#else
-# define lsmShmHasLock(x,y,z)
-#endif
-
-int lsmReadlock(lsm_db *, i64 iLsm, u32 iShmMin, u32 iShmMax);
-
-int lsmLsmInUse(lsm_db *db, i64 iLsmId, int *pbInUse);
-int lsmTreeInUse(lsm_db *db, u32 iLsmId, int *pbInUse);
-int lsmFreelistAppend(lsm_env *pEnv, Freelist *p, int iBlk, i64 iId);
-
-int lsmDbMultiProc(lsm_db *);
-void lsmDbDeferredClose(lsm_db *, lsm_file *, LsmFile *);
-LsmFile *lsmDbRecycleFd(lsm_db *);
-
-int lsmWalkFreelist(lsm_db *, int, int (*)(void *, int, i64), void *);
-
-int lsmCheckCompressionId(lsm_db *, u32);
-
-
-/**************************************************************************
-** functions in lsm_str.c
-*/
-void lsmStringInit(LsmString*, lsm_env *pEnv);
-int lsmStringExtend(LsmString*, int);
-int lsmStringAppend(LsmString*, const char *, int);
-void lsmStringVAppendf(LsmString*, const char *zFormat, va_list, va_list);
-void lsmStringAppendf(LsmString*, const char *zFormat, ...);
-void lsmStringClear(LsmString*);
-char *lsmMallocPrintf(lsm_env*, const char*, ...);
-int lsmStringBinAppend(LsmString *pStr, const u8 *a, int n);
-
-int lsmStrlen(const char *zName);
-
-
-
-/*
-** Round up a number to the next larger multiple of 8. This is used
-** to force 8-byte alignment on 64-bit architectures.
-*/
-#define ROUND8(x) (((x)+7)&~7)
-
-#define LSM_MIN(x,y) ((x)>(y) ? (y) : (x))
-#define LSM_MAX(x,y) ((x)>(y) ? (x) : (y))
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_ckpt.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_ckpt.c
deleted file mode 100644
index ba92a823cf9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_ckpt.c
+++ /dev/null
@@ -1,1239 +0,0 @@
-/*
-** 2011-09-11
-**
-** 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 contains code to read and write checkpoints.
-**
-** A checkpoint represents the database layout at a single point in time.
-** It includes a log offset. When an existing database is opened, the
-** current state is determined by reading the newest checkpoint and updating
-** it with all committed transactions from the log that follow the specified
-** offset.
-*/
-#include "lsmInt.h"
-
-/*
-** CHECKPOINT BLOB FORMAT:
-**
-** A checkpoint blob is a series of unsigned 32-bit integers stored in
-** big-endian byte order. As follows:
-**
-** Checkpoint header (see the CKPT_HDR_XXX #defines):
-**
-** 1. The checkpoint id MSW.
-** 2. The checkpoint id LSW.
-** 3. The number of integer values in the entire checkpoint, including
-** the two checksum values.
-** 4. The compression scheme id.
-** 5. The total number of blocks in the database.
-** 6. The block size.
-** 7. The number of levels.
-** 8. The nominal database page size.
-** 9. The number of pages (in total) written to the database file.
-**
-** Log pointer:
-**
-** 1. The log offset MSW.
-** 2. The log offset LSW.
-** 3. Log checksum 0.
-** 4. Log checksum 1.
-**
-** Note that the "log offset" is not the literal byte offset. Instead,
-** it is the byte offset multiplied by 2, with least significant bit
-** toggled each time the log pointer value is changed. This is to make
-** sure that this field changes each time the log pointer is updated,
-** even if the log file itself is disabled. See lsmTreeMakeOld().
-**
-** See ckptExportLog() and ckptImportLog().
-**
-** Append points:
-**
-** 8 integers (4 * 64-bit page numbers). See ckptExportAppendlist().
-**
-** For each level in the database, a level record. Formatted as follows:
-**
-** 0. Age of the level (least significant 16-bits). And flags mask (most
-** significant 16-bits).
-** 1. The number of right-hand segments (nRight, possibly 0),
-** 2. Segment record for left-hand segment (8 integers defined below),
-** 3. Segment record for each right-hand segment (8 integers defined below),
-** 4. If nRight>0, The number of segments involved in the merge
-** 5. if nRight>0, Current nSkip value (see Merge structure defn.),
-** 6. For each segment in the merge:
-** 5a. Page number of next cell to read during merge (this field
-** is 64-bits - 2 integers)
-** 5b. Cell number of next cell to read during merge
-** 7. Page containing current split-key (64-bits - 2 integers).
-** 8. Cell within page containing current split-key.
-** 9. Current pointer value (64-bits - 2 integers).
-**
-** The block redirect array:
-**
-** 1. Number of redirections (maximum LSM_MAX_BLOCK_REDIRECTS).
-** 2. For each redirection:
-** a. "from" block number
-** b. "to" block number
-**
-** The in-memory freelist entries. Each entry is either an insert or a
-** delete. The in-memory freelist is to the free-block-list as the
-** in-memory tree is to the users database content.
-**
-** 1. Number of free-list entries stored in checkpoint header.
-** 2. Number of free blocks (in total).
-** 3. Total number of blocks freed during database lifetime.
-** 4. For each entry:
-** 2a. Block number of free block.
-** 2b. A 64-bit integer (MSW followed by LSW). -1 for a delete entry,
-** or the associated checkpoint id for an insert.
-**
-** The checksum:
-**
-** 1. Checksum value 1.
-** 2. Checksum value 2.
-**
-** In the above, a segment record consists of the following four 64-bit
-** fields (converted to 2 * u32 by storing the MSW followed by LSW):
-**
-** 1. First page of array,
-** 2. Last page of array,
-** 3. Root page of array (or 0),
-** 4. Size of array in pages.
-*/
-
-/*
-** LARGE NUMBERS OF LEVEL RECORDS:
-**
-** A limit on the number of rhs segments that may be present in the database
-** file. Defining this limit ensures that all level records fit within
-** the 4096 byte limit for checkpoint blobs.
-**
-** The number of right-hand-side segments in a database is counted as
-** follows:
-**
-** * For each level in the database not undergoing a merge, add 1.
-**
-** * For each level in the database that is undergoing a merge, add
-** the number of segments on the rhs of the level.
-**
-** A level record not undergoing a merge is 10 integers. A level record
-** with nRhs rhs segments and (nRhs+1) input segments (i.e. including the
-** separators from the next level) is (11*nRhs+20) integers. The maximum
-** per right-hand-side level is therefore 21 integers. So the maximum
-** size of all level records in a checkpoint is 21*40=820 integers.
-**
-** TODO: Before pointer values were changed from 32 to 64 bits, the above
-** used to come to 420 bytes - leaving significant space for a free-list
-** prefix. No more. To fix this, reduce the size of the level records in
-** a db snapshot, and improve management of the free-list tail in
-** lsm_sorted.c.
-*/
-#define LSM_MAX_RHS_SEGMENTS 40
-
-/*
-** LARGE NUMBERS OF FREELIST ENTRIES:
-**
-** There is also a limit (LSM_MAX_FREELIST_ENTRIES - defined in lsmInt.h)
-** on the number of free-list entries stored in a checkpoint. Since each
-** free-list entry consists of 3 integers, the maximum free-list size is
-** 3*100=300 integers. Combined with the limit on rhs segments defined
-** above, this ensures that a checkpoint always fits within a 4096 byte
-** meta page.
-**
-** If the database contains more than 100 free blocks, the "overflow" flag
-** in the checkpoint header is set and the remainder are stored in the
-** system FREELIST entry in the LSM (along with user data). The value
-** accompanying the FREELIST key in the LSM is, like a checkpoint, an array
-** of 32-bit big-endian integers. As follows:
-**
-** For each entry:
-** a. Block number of free block.
-** b. MSW of associated checkpoint id.
-** c. LSW of associated checkpoint id.
-**
-** The number of entries is not required - it is implied by the size of the
-** value blob containing the integer array.
-**
-** Note that the limit defined by LSM_MAX_FREELIST_ENTRIES is a hard limit.
-** The actual value used may be configured using LSM_CONFIG_MAX_FREELIST.
-*/
-
-/*
-** The argument to this macro must be of type u32. On a little-endian
-** architecture, it returns the u32 value that results from interpreting
-** the 4 bytes as a big-endian value. On a big-endian architecture, it
-** returns the value that would be produced by intepreting the 4 bytes
-** of the input value as a little-endian integer.
-*/
-#define BYTESWAP32(x) ( \
- (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \
- + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \
-)
-
-static const int one = 1;
-#define LSM_LITTLE_ENDIAN (*(u8 *)(&one))
-
-/* Sizes, in integers, of various parts of the checkpoint. */
-#define CKPT_HDR_SIZE 9
-#define CKPT_LOGPTR_SIZE 4
-#define CKPT_APPENDLIST_SIZE (LSM_APPLIST_SZ * 2)
-
-/* A #define to describe each integer in the checkpoint header. */
-#define CKPT_HDR_ID_MSW 0
-#define CKPT_HDR_ID_LSW 1
-#define CKPT_HDR_NCKPT 2
-#define CKPT_HDR_CMPID 3
-#define CKPT_HDR_NBLOCK 4
-#define CKPT_HDR_BLKSZ 5
-#define CKPT_HDR_NLEVEL 6
-#define CKPT_HDR_PGSZ 7
-#define CKPT_HDR_NWRITE 8
-
-#define CKPT_HDR_LO_MSW 9
-#define CKPT_HDR_LO_LSW 10
-#define CKPT_HDR_LO_CKSUM1 11
-#define CKPT_HDR_LO_CKSUM2 12
-
-typedef struct CkptBuffer CkptBuffer;
-
-/*
-** Dynamic buffer used to accumulate data for a checkpoint.
-*/
-struct CkptBuffer {
- lsm_env *pEnv;
- int nAlloc;
- u32 *aCkpt;
-};
-
-/*
-** Calculate the checksum of the checkpoint specified by arguments aCkpt and
-** nCkpt. Store the checksum in *piCksum1 and *piCksum2 before returning.
-**
-** The value of the nCkpt parameter includes the two checksum values at
-** the end of the checkpoint. They are not used as inputs to the checksum
-** calculation. The checksum is based on the array of (nCkpt-2) integers
-** at aCkpt[].
-*/
-static void ckptChecksum(u32 *aCkpt, u32 nCkpt, u32 *piCksum1, u32 *piCksum2){
- u32 i;
- u32 cksum1 = 1;
- u32 cksum2 = 2;
-
- if( nCkpt % 2 ){
- cksum1 += aCkpt[nCkpt-3] & 0x0000FFFF;
- cksum2 += aCkpt[nCkpt-3] & 0xFFFF0000;
- }
-
- for(i=0; (i+3)<nCkpt; i+=2){
- cksum1 += cksum2 + aCkpt[i];
- cksum2 += cksum1 + aCkpt[i+1];
- }
-
- *piCksum1 = cksum1;
- *piCksum2 = cksum2;
-}
-
-/*
-** Set integer iIdx of the checkpoint accumulating in buffer *p to iVal.
-*/
-static void ckptSetValue(CkptBuffer *p, int iIdx, u32 iVal, int *pRc){
- if( *pRc ) return;
- if( iIdx>=p->nAlloc ){
- int nNew = LSM_MAX(8, iIdx*2);
- p->aCkpt = (u32 *)lsmReallocOrFree(p->pEnv, p->aCkpt, nNew*sizeof(u32));
- if( !p->aCkpt ){
- *pRc = LSM_NOMEM_BKPT;
- return;
- }
- p->nAlloc = nNew;
- }
- p->aCkpt[iIdx] = iVal;
-}
-
-/*
-** Argument aInt points to an array nInt elements in size. Switch the
-** endian-ness of each element of the array.
-*/
-static void ckptChangeEndianness(u32 *aInt, int nInt){
- if( LSM_LITTLE_ENDIAN ){
- int i;
- for(i=0; i<nInt; i++) aInt[i] = BYTESWAP32(aInt[i]);
- }
-}
-
-/*
-** Object *p contains a checkpoint in native byte-order. The checkpoint is
-** nCkpt integers in size, not including any checksum. This function sets
-** the two checksum elements of the checkpoint accordingly.
-*/
-static void ckptAddChecksum(CkptBuffer *p, int nCkpt, int *pRc){
- if( *pRc==LSM_OK ){
- u32 aCksum[2] = {0, 0};
- ckptChecksum(p->aCkpt, nCkpt+2, &aCksum[0], &aCksum[1]);
- ckptSetValue(p, nCkpt, aCksum[0], pRc);
- ckptSetValue(p, nCkpt+1, aCksum[1], pRc);
- }
-}
-
-static void ckptAppend64(CkptBuffer *p, int *piOut, i64 iVal, int *pRc){
- int iOut = *piOut;
- ckptSetValue(p, iOut++, (iVal >> 32) & 0xFFFFFFFF, pRc);
- ckptSetValue(p, iOut++, (iVal & 0xFFFFFFFF), pRc);
- *piOut = iOut;
-}
-
-static i64 ckptRead64(u32 *a){
- return (((i64)a[0]) << 32) + (i64)a[1];
-}
-
-static i64 ckptGobble64(u32 *a, int *piIn){
- int iIn = *piIn;
- *piIn += 2;
- return ckptRead64(&a[iIn]);
-}
-
-
-/*
-** Append a 6-value segment record corresponding to pSeg to the checkpoint
-** buffer passed as the third argument.
-*/
-static void ckptExportSegment(
- Segment *pSeg,
- CkptBuffer *p,
- int *piOut,
- int *pRc
-){
- ckptAppend64(p, piOut, pSeg->iFirst, pRc);
- ckptAppend64(p, piOut, pSeg->iLastPg, pRc);
- ckptAppend64(p, piOut, pSeg->iRoot, pRc);
- ckptAppend64(p, piOut, pSeg->nSize, pRc);
-}
-
-static void ckptExportLevel(
- Level *pLevel, /* Level object to serialize */
- CkptBuffer *p, /* Append new level record to this ckpt */
- int *piOut, /* IN/OUT: Size of checkpoint so far */
- int *pRc /* IN/OUT: Error code */
-){
- int iOut = *piOut;
- Merge *pMerge;
-
- pMerge = pLevel->pMerge;
- ckptSetValue(p, iOut++, (u32)pLevel->iAge + (u32)(pLevel->flags<<16), pRc);
- ckptSetValue(p, iOut++, pLevel->nRight, pRc);
- ckptExportSegment(&pLevel->lhs, p, &iOut, pRc);
-
- assert( (pLevel->nRight>0)==(pMerge!=0) );
- if( pMerge ){
- int i;
- for(i=0; i<pLevel->nRight; i++){
- ckptExportSegment(&pLevel->aRhs[i], p, &iOut, pRc);
- }
- assert( pMerge->nInput==pLevel->nRight
- || pMerge->nInput==pLevel->nRight+1
- );
- ckptSetValue(p, iOut++, pMerge->nInput, pRc);
- ckptSetValue(p, iOut++, pMerge->nSkip, pRc);
- for(i=0; i<pMerge->nInput; i++){
- ckptAppend64(p, &iOut, pMerge->aInput[i].iPg, pRc);
- ckptSetValue(p, iOut++, pMerge->aInput[i].iCell, pRc);
- }
- ckptAppend64(p, &iOut, pMerge->splitkey.iPg, pRc);
- ckptSetValue(p, iOut++, pMerge->splitkey.iCell, pRc);
- ckptAppend64(p, &iOut, pMerge->iCurrentPtr, pRc);
- }
-
- *piOut = iOut;
-}
-
-/*
-** Populate the log offset fields of the checkpoint buffer. 4 values.
-*/
-static void ckptExportLog(
- lsm_db *pDb,
- int bFlush,
- CkptBuffer *p,
- int *piOut,
- int *pRc
-){
- int iOut = *piOut;
-
- assert( iOut==CKPT_HDR_LO_MSW );
-
- if( bFlush ){
- i64 iOff = pDb->treehdr.iOldLog;
- ckptAppend64(p, &iOut, iOff, pRc);
- ckptSetValue(p, iOut++, pDb->treehdr.oldcksum0, pRc);
- ckptSetValue(p, iOut++, pDb->treehdr.oldcksum1, pRc);
- }else{
- for(; iOut<=CKPT_HDR_LO_CKSUM2; iOut++){
- ckptSetValue(p, iOut, pDb->pShmhdr->aSnap2[iOut], pRc);
- }
- }
-
- assert( *pRc || iOut==CKPT_HDR_LO_CKSUM2+1 );
- *piOut = iOut;
-}
-
-static void ckptExportAppendlist(
- lsm_db *db, /* Database connection */
- CkptBuffer *p, /* Checkpoint buffer to write to */
- int *piOut, /* IN/OUT: Offset within checkpoint buffer */
- int *pRc /* IN/OUT: Error code */
-){
- int i;
- LsmPgno *aiAppend = db->pWorker->aiAppend;
-
- for(i=0; i<LSM_APPLIST_SZ; i++){
- ckptAppend64(p, piOut, aiAppend[i], pRc);
- }
-};
-
-static int ckptExportSnapshot(
- lsm_db *pDb, /* Connection handle */
- int bLog, /* True to update log-offset fields */
- i64 iId, /* Checkpoint id */
- int bCksum, /* If true, include checksums */
- void **ppCkpt, /* OUT: Buffer containing checkpoint */
- int *pnCkpt /* OUT: Size of checkpoint in bytes */
-){
- int rc = LSM_OK; /* Return Code */
- FileSystem *pFS = pDb->pFS; /* File system object */
- Snapshot *pSnap = pDb->pWorker; /* Worker snapshot */
- int nLevel = 0; /* Number of levels in checkpoint */
- int iLevel; /* Used to count out nLevel levels */
- int iOut = 0; /* Current offset in aCkpt[] */
- Level *pLevel; /* Level iterator */
- int i; /* Iterator used while serializing freelist */
- CkptBuffer ckpt;
-
- /* Initialize the output buffer */
- memset(&ckpt, 0, sizeof(CkptBuffer));
- ckpt.pEnv = pDb->pEnv;
- iOut = CKPT_HDR_SIZE;
-
- /* Write the log offset into the checkpoint. */
- ckptExportLog(pDb, bLog, &ckpt, &iOut, &rc);
-
- /* Write the append-point list */
- ckptExportAppendlist(pDb, &ckpt, &iOut, &rc);
-
- /* Figure out how many levels will be written to the checkpoint. */
- for(pLevel=lsmDbSnapshotLevel(pSnap); pLevel; pLevel=pLevel->pNext) nLevel++;
-
- /* Serialize nLevel levels. */
- iLevel = 0;
- for(pLevel=lsmDbSnapshotLevel(pSnap); iLevel<nLevel; pLevel=pLevel->pNext){
- ckptExportLevel(pLevel, &ckpt, &iOut, &rc);
- iLevel++;
- }
-
- /* Write the block-redirect list */
- ckptSetValue(&ckpt, iOut++, pSnap->redirect.n, &rc);
- for(i=0; i<pSnap->redirect.n; i++){
- ckptSetValue(&ckpt, iOut++, pSnap->redirect.a[i].iFrom, &rc);
- ckptSetValue(&ckpt, iOut++, pSnap->redirect.a[i].iTo, &rc);
- }
-
- /* Write the freelist */
- assert( pSnap->freelist.nEntry<=pDb->nMaxFreelist );
- if( rc==LSM_OK ){
- int nFree = pSnap->freelist.nEntry;
- ckptSetValue(&ckpt, iOut++, nFree, &rc);
- for(i=0; i<nFree; i++){
- FreelistEntry *p = &pSnap->freelist.aEntry[i];
- ckptSetValue(&ckpt, iOut++, p->iBlk, &rc);
- ckptSetValue(&ckpt, iOut++, (p->iId >> 32) & 0xFFFFFFFF, &rc);
- ckptSetValue(&ckpt, iOut++, p->iId & 0xFFFFFFFF, &rc);
- }
- }
-
- /* Write the checkpoint header */
- assert( iId>=0 );
- assert( pSnap->iCmpId==pDb->compress.iId
- || pSnap->iCmpId==LSM_COMPRESSION_EMPTY
- );
- ckptSetValue(&ckpt, CKPT_HDR_ID_MSW, (u32)(iId>>32), &rc);
- ckptSetValue(&ckpt, CKPT_HDR_ID_LSW, (u32)(iId&0xFFFFFFFF), &rc);
- ckptSetValue(&ckpt, CKPT_HDR_NCKPT, iOut+2, &rc);
- ckptSetValue(&ckpt, CKPT_HDR_CMPID, pDb->compress.iId, &rc);
- ckptSetValue(&ckpt, CKPT_HDR_NBLOCK, pSnap->nBlock, &rc);
- ckptSetValue(&ckpt, CKPT_HDR_BLKSZ, lsmFsBlockSize(pFS), &rc);
- ckptSetValue(&ckpt, CKPT_HDR_NLEVEL, nLevel, &rc);
- ckptSetValue(&ckpt, CKPT_HDR_PGSZ, lsmFsPageSize(pFS), &rc);
- ckptSetValue(&ckpt, CKPT_HDR_NWRITE, pSnap->nWrite, &rc);
-
- if( bCksum ){
- ckptAddChecksum(&ckpt, iOut, &rc);
- }else{
- ckptSetValue(&ckpt, iOut, 0, &rc);
- ckptSetValue(&ckpt, iOut+1, 0, &rc);
- }
- iOut += 2;
- assert( iOut<=1024 );
-
-#ifdef LSM_LOG_FREELIST
- lsmLogMessage(pDb, rc,
- "ckptExportSnapshot(): id=%lld freelist: %d", iId, pSnap->freelist.nEntry
- );
- for(i=0; i<pSnap->freelist.nEntry; i++){
- lsmLogMessage(pDb, rc,
- "ckptExportSnapshot(): iBlk=%d id=%lld",
- pSnap->freelist.aEntry[i].iBlk,
- pSnap->freelist.aEntry[i].iId
- );
- }
-#endif
-
- *ppCkpt = (void *)ckpt.aCkpt;
- if( pnCkpt ) *pnCkpt = sizeof(u32)*iOut;
- return rc;
-}
-
-
-/*
-** Helper function for ckptImport().
-*/
-static void ckptNewSegment(
- u32 *aIn,
- int *piIn,
- Segment *pSegment /* Populate this structure */
-){
- assert( pSegment->iFirst==0 && pSegment->iLastPg==0 );
- assert( pSegment->nSize==0 && pSegment->iRoot==0 );
- pSegment->iFirst = ckptGobble64(aIn, piIn);
- pSegment->iLastPg = ckptGobble64(aIn, piIn);
- pSegment->iRoot = ckptGobble64(aIn, piIn);
- pSegment->nSize = (int)ckptGobble64(aIn, piIn);
- assert( pSegment->iFirst );
-}
-
-static int ckptSetupMerge(lsm_db *pDb, u32 *aInt, int *piIn, Level *pLevel){
- Merge *pMerge; /* Allocated Merge object */
- int nInput; /* Number of input segments in merge */
- int iIn = *piIn; /* Next value to read from aInt[] */
- int i; /* Iterator variable */
- int nByte; /* Number of bytes to allocate */
-
- /* Allocate the Merge object. If malloc() fails, return LSM_NOMEM. */
- nInput = (int)aInt[iIn++];
- nByte = sizeof(Merge) + sizeof(MergeInput) * nInput;
- pMerge = (Merge *)lsmMallocZero(pDb->pEnv, nByte);
- if( !pMerge ) return LSM_NOMEM_BKPT;
- pLevel->pMerge = pMerge;
-
- /* Populate the Merge object. */
- pMerge->aInput = (MergeInput *)&pMerge[1];
- pMerge->nInput = nInput;
- pMerge->iOutputOff = -1;
- pMerge->nSkip = (int)aInt[iIn++];
- for(i=0; i<nInput; i++){
- pMerge->aInput[i].iPg = ckptGobble64(aInt, &iIn);
- pMerge->aInput[i].iCell = (int)aInt[iIn++];
- }
- pMerge->splitkey.iPg = ckptGobble64(aInt, &iIn);
- pMerge->splitkey.iCell = (int)aInt[iIn++];
- pMerge->iCurrentPtr = ckptGobble64(aInt, &iIn);
-
- /* Set *piIn and return LSM_OK. */
- *piIn = iIn;
- return LSM_OK;
-}
-
-
-static int ckptLoadLevels(
- lsm_db *pDb,
- u32 *aIn,
- int *piIn,
- int nLevel,
- Level **ppLevel
-){
- int i;
- int rc = LSM_OK;
- Level *pRet = 0;
- Level **ppNext;
- int iIn = *piIn;
-
- ppNext = &pRet;
- for(i=0; rc==LSM_OK && i<nLevel; i++){
- int iRight;
- Level *pLevel;
-
- /* Allocate space for the Level structure and Level.apRight[] array */
- pLevel = (Level *)lsmMallocZeroRc(pDb->pEnv, sizeof(Level), &rc);
- if( rc==LSM_OK ){
- pLevel->iAge = (u16)(aIn[iIn] & 0x0000FFFF);
- pLevel->flags = (u16)((aIn[iIn]>>16) & 0x0000FFFF);
- iIn++;
- pLevel->nRight = aIn[iIn++];
- if( pLevel->nRight ){
- int nByte = sizeof(Segment) * pLevel->nRight;
- pLevel->aRhs = (Segment *)lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
- }
- if( rc==LSM_OK ){
- *ppNext = pLevel;
- ppNext = &pLevel->pNext;
-
- /* Allocate the main segment */
- ckptNewSegment(aIn, &iIn, &pLevel->lhs);
-
- /* Allocate each of the right-hand segments, if any */
- for(iRight=0; iRight<pLevel->nRight; iRight++){
- ckptNewSegment(aIn, &iIn, &pLevel->aRhs[iRight]);
- }
-
- /* Set up the Merge object, if required */
- if( pLevel->nRight>0 ){
- rc = ckptSetupMerge(pDb, aIn, &iIn, pLevel);
- }
- }
- }
- }
-
- if( rc!=LSM_OK ){
- /* An OOM must have occurred. Free any level structures allocated and
- ** return the error to the caller. */
- lsmSortedFreeLevel(pDb->pEnv, pRet);
- pRet = 0;
- }
-
- *ppLevel = pRet;
- *piIn = iIn;
- return rc;
-}
-
-
-int lsmCheckpointLoadLevels(lsm_db *pDb, void *pVal, int nVal){
- int rc = LSM_OK;
- if( nVal>0 ){
- u32 *aIn;
-
- aIn = lsmMallocRc(pDb->pEnv, nVal, &rc);
- if( aIn ){
- Level *pLevel = 0;
- Level *pParent;
-
- int nIn;
- int nLevel;
- int iIn = 1;
- memcpy(aIn, pVal, nVal);
- nIn = nVal / sizeof(u32);
-
- ckptChangeEndianness(aIn, nIn);
- nLevel = aIn[0];
- rc = ckptLoadLevels(pDb, aIn, &iIn, nLevel, &pLevel);
- lsmFree(pDb->pEnv, aIn);
- assert( rc==LSM_OK || pLevel==0 );
- if( rc==LSM_OK ){
- pParent = lsmDbSnapshotLevel(pDb->pWorker);
- assert( pParent );
- while( pParent->pNext ) pParent = pParent->pNext;
- pParent->pNext = pLevel;
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Return the data for the LEVELS record.
-**
-** The size of the checkpoint that can be stored in the database header
-** must not exceed 1024 32-bit integers. Normally, it does not. However,
-** if it does, part of the checkpoint must be stored in the LSM. This
-** routine returns that part.
-*/
-int lsmCheckpointLevels(
- lsm_db *pDb, /* Database handle */
- int nLevel, /* Number of levels to write to blob */
- void **paVal, /* OUT: Pointer to LEVELS blob */
- int *pnVal /* OUT: Size of LEVELS blob in bytes */
-){
- Level *p; /* Used to iterate through levels */
- int nAll= 0;
- int rc;
- int i;
- int iOut;
- CkptBuffer ckpt;
- assert( nLevel>0 );
-
- for(p=lsmDbSnapshotLevel(pDb->pWorker); p; p=p->pNext) nAll++;
-
- assert( nAll>nLevel );
- nAll -= nLevel;
- for(p=lsmDbSnapshotLevel(pDb->pWorker); p && nAll>0; p=p->pNext) nAll--;
-
- memset(&ckpt, 0, sizeof(CkptBuffer));
- ckpt.pEnv = pDb->pEnv;
-
- ckptSetValue(&ckpt, 0, nLevel, &rc);
- iOut = 1;
- for(i=0; rc==LSM_OK && i<nLevel; i++){
- ckptExportLevel(p, &ckpt, &iOut, &rc);
- p = p->pNext;
- }
- assert( rc!=LSM_OK || p==0 );
-
- if( rc==LSM_OK ){
- ckptChangeEndianness(ckpt.aCkpt, iOut);
- *paVal = (void *)ckpt.aCkpt;
- *pnVal = iOut * sizeof(u32);
- }else{
- *pnVal = 0;
- *paVal = 0;
- }
-
- return rc;
-}
-
-/*
-** Read the checkpoint id from meta-page pPg.
-*/
-static i64 ckptLoadId(MetaPage *pPg){
- i64 ret = 0;
- if( pPg ){
- int nData;
- u8 *aData = lsmFsMetaPageData(pPg, &nData);
- ret = (((i64)lsmGetU32(&aData[CKPT_HDR_ID_MSW*4])) << 32) +
- ((i64)lsmGetU32(&aData[CKPT_HDR_ID_LSW*4]));
- }
- return ret;
-}
-
-/*
-** Return true if the buffer passed as an argument contains a valid
-** checkpoint.
-*/
-static int ckptChecksumOk(u32 *aCkpt){
- u32 nCkpt = aCkpt[CKPT_HDR_NCKPT];
- u32 cksum1;
- u32 cksum2;
-
- if( nCkpt<CKPT_HDR_NCKPT || nCkpt>(LSM_META_RW_PAGE_SIZE)/sizeof(u32) ){
- return 0;
- }
- ckptChecksum(aCkpt, nCkpt, &cksum1, &cksum2);
- return (cksum1==aCkpt[nCkpt-2] && cksum2==aCkpt[nCkpt-1]);
-}
-
-/*
-** Attempt to load a checkpoint from meta page iMeta.
-**
-** This function is a no-op if *pRc is set to any value other than LSM_OK
-** when it is called. If an error occurs, *pRc is set to an LSM error code
-** before returning.
-**
-** If no error occurs and the checkpoint is successfully loaded, copy it to
-** ShmHeader.aSnap1[] and ShmHeader.aSnap2[], and set ShmHeader.iMetaPage
-** to indicate its origin. In this case return 1. Or, if the checkpoint
-** cannot be loaded (because the checksum does not compute), return 0.
-*/
-static int ckptTryLoad(lsm_db *pDb, MetaPage *pPg, u32 iMeta, int *pRc){
- int bLoaded = 0; /* Return value */
- if( *pRc==LSM_OK ){
- int rc = LSM_OK; /* Error code */
- u32 *aCkpt = 0; /* Pointer to buffer containing checkpoint */
- u32 nCkpt; /* Number of elements in aCkpt[] */
- int nData; /* Bytes of data in aData[] */
- u8 *aData; /* Meta page data */
-
- aData = lsmFsMetaPageData(pPg, &nData);
- nCkpt = (u32)lsmGetU32(&aData[CKPT_HDR_NCKPT*sizeof(u32)]);
- if( nCkpt<=nData/sizeof(u32) && nCkpt>CKPT_HDR_NCKPT ){
- aCkpt = (u32 *)lsmMallocRc(pDb->pEnv, nCkpt*sizeof(u32), &rc);
- }
- if( aCkpt ){
- memcpy(aCkpt, aData, nCkpt*sizeof(u32));
- ckptChangeEndianness(aCkpt, nCkpt);
- if( ckptChecksumOk(aCkpt) ){
- ShmHeader *pShm = pDb->pShmhdr;
- memcpy(pShm->aSnap1, aCkpt, nCkpt*sizeof(u32));
- memcpy(pShm->aSnap2, aCkpt, nCkpt*sizeof(u32));
- memcpy(pDb->aSnapshot, aCkpt, nCkpt*sizeof(u32));
- pShm->iMetaPage = iMeta;
- bLoaded = 1;
- }
- }
-
- lsmFree(pDb->pEnv, aCkpt);
- *pRc = rc;
- }
- return bLoaded;
-}
-
-/*
-** Initialize the shared-memory header with an empty snapshot. This function
-** is called when no valid snapshot can be found in the database header.
-*/
-static void ckptLoadEmpty(lsm_db *pDb){
- u32 aCkpt[] = {
- 0, /* CKPT_HDR_ID_MSW */
- 10, /* CKPT_HDR_ID_LSW */
- 0, /* CKPT_HDR_NCKPT */
- LSM_COMPRESSION_EMPTY, /* CKPT_HDR_CMPID */
- 0, /* CKPT_HDR_NBLOCK */
- 0, /* CKPT_HDR_BLKSZ */
- 0, /* CKPT_HDR_NLEVEL */
- 0, /* CKPT_HDR_PGSZ */
- 0, /* CKPT_HDR_NWRITE */
- 0, 0, 1234, 5678, /* The log pointer and initial checksum */
- 0,0,0,0, 0,0,0,0, /* The append list */
- 0, /* The redirected block list */
- 0, /* The free block list */
- 0, 0 /* Space for checksum values */
- };
- u32 nCkpt = array_size(aCkpt);
- ShmHeader *pShm = pDb->pShmhdr;
-
- aCkpt[CKPT_HDR_NCKPT] = nCkpt;
- aCkpt[CKPT_HDR_BLKSZ] = pDb->nDfltBlksz;
- aCkpt[CKPT_HDR_PGSZ] = pDb->nDfltPgsz;
- ckptChecksum(aCkpt, array_size(aCkpt), &aCkpt[nCkpt-2], &aCkpt[nCkpt-1]);
-
- memcpy(pShm->aSnap1, aCkpt, nCkpt*sizeof(u32));
- memcpy(pShm->aSnap2, aCkpt, nCkpt*sizeof(u32));
- memcpy(pDb->aSnapshot, aCkpt, nCkpt*sizeof(u32));
-}
-
-/*
-** This function is called as part of database recovery to initialize the
-** ShmHeader.aSnap1[] and ShmHeader.aSnap2[] snapshots.
-*/
-int lsmCheckpointRecover(lsm_db *pDb){
- int rc = LSM_OK; /* Return Code */
- i64 iId1; /* Id of checkpoint on meta-page 1 */
- i64 iId2; /* Id of checkpoint on meta-page 2 */
- int bLoaded = 0; /* True once checkpoint has been loaded */
- int cmp; /* True if (iId2>iId1) */
- MetaPage *apPg[2] = {0, 0}; /* Meta-pages 1 and 2 */
-
- rc = lsmFsMetaPageGet(pDb->pFS, 0, 1, &apPg[0]);
- if( rc==LSM_OK ) rc = lsmFsMetaPageGet(pDb->pFS, 0, 2, &apPg[1]);
-
- iId1 = ckptLoadId(apPg[0]);
- iId2 = ckptLoadId(apPg[1]);
- cmp = (iId2 > iId1);
- bLoaded = ckptTryLoad(pDb, apPg[cmp?1:0], (cmp?2:1), &rc);
- if( bLoaded==0 ){
- bLoaded = ckptTryLoad(pDb, apPg[cmp?0:1], (cmp?1:2), &rc);
- }
-
- /* The database does not contain a valid checkpoint. Initialize the shared
- ** memory header with an empty checkpoint. */
- if( bLoaded==0 ){
- ckptLoadEmpty(pDb);
- }
-
- lsmFsMetaPageRelease(apPg[0]);
- lsmFsMetaPageRelease(apPg[1]);
-
- return rc;
-}
-
-/*
-** Store the snapshot in pDb->aSnapshot[] in meta-page iMeta.
-*/
-int lsmCheckpointStore(lsm_db *pDb, int iMeta){
- MetaPage *pPg = 0;
- int rc;
-
- assert( iMeta==1 || iMeta==2 );
- rc = lsmFsMetaPageGet(pDb->pFS, 1, iMeta, &pPg);
- if( rc==LSM_OK ){
- u8 *aData;
- int nData;
- int nCkpt;
-
- nCkpt = (int)pDb->aSnapshot[CKPT_HDR_NCKPT];
- aData = lsmFsMetaPageData(pPg, &nData);
- memcpy(aData, pDb->aSnapshot, nCkpt*sizeof(u32));
- ckptChangeEndianness((u32 *)aData, nCkpt);
- rc = lsmFsMetaPageRelease(pPg);
- }
-
- return rc;
-}
-
-/*
-** Copy the current client snapshot from shared-memory to pDb->aSnapshot[].
-*/
-int lsmCheckpointLoad(lsm_db *pDb, int *piRead){
- int nRem = LSM_ATTEMPTS_BEFORE_PROTOCOL;
- ShmHeader *pShm = pDb->pShmhdr;
- while( (nRem--)>0 ){
- int nInt;
-
- nInt = pShm->aSnap1[CKPT_HDR_NCKPT];
- if( nInt<=(LSM_META_RW_PAGE_SIZE / sizeof(u32)) ){
- memcpy(pDb->aSnapshot, pShm->aSnap1, nInt*sizeof(u32));
- if( ckptChecksumOk(pDb->aSnapshot) ){
- if( piRead ) *piRead = 1;
- return LSM_OK;
- }
- }
-
- nInt = pShm->aSnap2[CKPT_HDR_NCKPT];
- if( nInt<=(LSM_META_RW_PAGE_SIZE / sizeof(u32)) ){
- memcpy(pDb->aSnapshot, pShm->aSnap2, nInt*sizeof(u32));
- if( ckptChecksumOk(pDb->aSnapshot) ){
- if( piRead ) *piRead = 2;
- return LSM_OK;
- }
- }
-
- lsmShmBarrier(pDb);
- }
- return LSM_PROTOCOL_BKPT;
-}
-
-int lsmInfoCompressionId(lsm_db *db, u32 *piCmpId){
- int rc;
-
- assert( db->pClient==0 && db->pWorker==0 );
- rc = lsmCheckpointLoad(db, 0);
- if( rc==LSM_OK ){
- *piCmpId = db->aSnapshot[CKPT_HDR_CMPID];
- }
-
- return rc;
-}
-
-int lsmCheckpointLoadOk(lsm_db *pDb, int iSnap){
- u32 *aShm;
- assert( iSnap==1 || iSnap==2 );
- aShm = (iSnap==1) ? pDb->pShmhdr->aSnap1 : pDb->pShmhdr->aSnap2;
- return (lsmCheckpointId(pDb->aSnapshot, 0)==lsmCheckpointId(aShm, 0) );
-}
-
-int lsmCheckpointClientCacheOk(lsm_db *pDb){
- return ( pDb->pClient
- && pDb->pClient->iId==lsmCheckpointId(pDb->aSnapshot, 0)
- && pDb->pClient->iId==lsmCheckpointId(pDb->pShmhdr->aSnap1, 0)
- && pDb->pClient->iId==lsmCheckpointId(pDb->pShmhdr->aSnap2, 0)
- );
-}
-
-int lsmCheckpointLoadWorker(lsm_db *pDb){
- int rc;
- ShmHeader *pShm = pDb->pShmhdr;
- int nInt1;
- int nInt2;
-
- /* Must be holding the WORKER lock to do this. Or DMS2. */
- assert(
- lsmShmAssertLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_EXCL)
- || lsmShmAssertLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL)
- );
-
- /* Check that the two snapshots match. If not, repair them. */
- nInt1 = pShm->aSnap1[CKPT_HDR_NCKPT];
- nInt2 = pShm->aSnap2[CKPT_HDR_NCKPT];
- if( nInt1!=nInt2 || memcmp(pShm->aSnap1, pShm->aSnap2, nInt2*sizeof(u32)) ){
- if( ckptChecksumOk(pShm->aSnap1) ){
- memcpy(pShm->aSnap2, pShm->aSnap1, sizeof(u32)*nInt1);
- }else if( ckptChecksumOk(pShm->aSnap2) ){
- memcpy(pShm->aSnap1, pShm->aSnap2, sizeof(u32)*nInt2);
- }else{
- return LSM_PROTOCOL_BKPT;
- }
- }
-
- rc = lsmCheckpointDeserialize(pDb, 1, pShm->aSnap1, &pDb->pWorker);
- if( pDb->pWorker ) pDb->pWorker->pDatabase = pDb->pDatabase;
-
- if( rc==LSM_OK ){
- rc = lsmCheckCompressionId(pDb, pDb->pWorker->iCmpId);
- }
-
-#if 0
- assert( rc!=LSM_OK || lsmFsIntegrityCheck(pDb) );
-#endif
- return rc;
-}
-
-int lsmCheckpointDeserialize(
- lsm_db *pDb,
- int bInclFreelist, /* If true, deserialize free-list */
- u32 *aCkpt,
- Snapshot **ppSnap
-){
- int rc = LSM_OK;
- Snapshot *pNew;
-
- pNew = (Snapshot *)lsmMallocZeroRc(pDb->pEnv, sizeof(Snapshot), &rc);
- if( rc==LSM_OK ){
- Level *pLvl;
- int nFree;
- int i;
- int nLevel = (int)aCkpt[CKPT_HDR_NLEVEL];
- int iIn = CKPT_HDR_SIZE + CKPT_APPENDLIST_SIZE + CKPT_LOGPTR_SIZE;
-
- pNew->iId = lsmCheckpointId(aCkpt, 0);
- pNew->nBlock = aCkpt[CKPT_HDR_NBLOCK];
- pNew->nWrite = aCkpt[CKPT_HDR_NWRITE];
- rc = ckptLoadLevels(pDb, aCkpt, &iIn, nLevel, &pNew->pLevel);
- pNew->iLogOff = lsmCheckpointLogOffset(aCkpt);
- pNew->iCmpId = aCkpt[CKPT_HDR_CMPID];
-
- /* Make a copy of the append-list */
- for(i=0; i<LSM_APPLIST_SZ; i++){
- u32 *a = &aCkpt[CKPT_HDR_SIZE + CKPT_LOGPTR_SIZE + i*2];
- pNew->aiAppend[i] = ckptRead64(a);
- }
-
- /* Read the block-redirect list */
- pNew->redirect.n = aCkpt[iIn++];
- if( pNew->redirect.n ){
- pNew->redirect.a = lsmMallocZeroRc(pDb->pEnv,
- (sizeof(struct RedirectEntry) * LSM_MAX_BLOCK_REDIRECTS), &rc
- );
- if( rc==LSM_OK ){
- for(i=0; i<pNew->redirect.n; i++){
- pNew->redirect.a[i].iFrom = aCkpt[iIn++];
- pNew->redirect.a[i].iTo = aCkpt[iIn++];
- }
- }
- for(pLvl=pNew->pLevel; pLvl->pNext; pLvl=pLvl->pNext);
- if( pLvl->nRight ){
- pLvl->aRhs[pLvl->nRight-1].pRedirect = &pNew->redirect;
- }else{
- pLvl->lhs.pRedirect = &pNew->redirect;
- }
- }
-
- /* Copy the free-list */
- if( rc==LSM_OK && bInclFreelist ){
- nFree = aCkpt[iIn++];
- if( nFree ){
- pNew->freelist.aEntry = (FreelistEntry *)lsmMallocZeroRc(
- pDb->pEnv, sizeof(FreelistEntry)*nFree, &rc
- );
- if( rc==LSM_OK ){
- int j;
- for(j=0; j<nFree; j++){
- FreelistEntry *p = &pNew->freelist.aEntry[j];
- p->iBlk = aCkpt[iIn++];
- p->iId = ((i64)(aCkpt[iIn])<<32) + aCkpt[iIn+1];
- iIn += 2;
- }
- pNew->freelist.nEntry = pNew->freelist.nAlloc = nFree;
- }
- }
- }
- }
-
- if( rc!=LSM_OK ){
- lsmFreeSnapshot(pDb->pEnv, pNew);
- pNew = 0;
- }
-
- *ppSnap = pNew;
- return rc;
-}
-
-/*
-** Connection pDb must be the worker connection in order to call this
-** function. It returns true if the database already contains the maximum
-** number of levels or false otherwise.
-**
-** This is used when flushing the in-memory tree to disk. If the database
-** is already full, then the caller should invoke lsm_work() or similar
-** until it is not full before creating a new level by flushing the in-memory
-** tree to disk. Limiting the number of levels in the database ensures that
-** the records describing them always fit within the checkpoint blob.
-*/
-int lsmDatabaseFull(lsm_db *pDb){
- Level *p;
- int nRhs = 0;
-
- assert( lsmShmAssertLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_EXCL) );
- assert( pDb->pWorker );
-
- for(p=pDb->pWorker->pLevel; p; p=p->pNext){
- nRhs += (p->nRight ? p->nRight : 1);
- }
-
- return (nRhs >= LSM_MAX_RHS_SEGMENTS);
-}
-
-/*
-** The connection passed as the only argument is currently the worker
-** connection. Some work has been performed on the database by the connection,
-** but no new snapshot has been written into shared memory.
-**
-** This function updates the shared-memory worker and client snapshots with
-** the new snapshot produced by the work performed by pDb.
-**
-** If successful, LSM_OK is returned. Otherwise, if an error occurs, an LSM
-** error code is returned.
-*/
-int lsmCheckpointSaveWorker(lsm_db *pDb, int bFlush){
- Snapshot *pSnap = pDb->pWorker;
- ShmHeader *pShm = pDb->pShmhdr;
- void *p = 0;
- int n = 0;
- int rc;
-
- pSnap->iId++;
- rc = ckptExportSnapshot(pDb, bFlush, pSnap->iId, 1, &p, &n);
- if( rc!=LSM_OK ) return rc;
- assert( ckptChecksumOk((u32 *)p) );
-
- assert( n<=LSM_META_RW_PAGE_SIZE );
- memcpy(pShm->aSnap2, p, n);
- lsmShmBarrier(pDb);
- memcpy(pShm->aSnap1, p, n);
- lsmFree(pDb->pEnv, p);
-
- /* assert( lsmFsIntegrityCheck(pDb) ); */
- return LSM_OK;
-}
-
-/*
-** This function is used to determine the snapshot-id of the most recently
-** checkpointed snapshot. Variable ShmHeader.iMetaPage indicates which of
-** the two meta-pages said snapshot resides on (if any).
-**
-** If successful, this function loads the snapshot from the meta-page,
-** verifies its checksum and sets *piId to the snapshot-id before returning
-** LSM_OK. Or, if the checksum attempt fails, *piId is set to zero and
-** LSM_OK returned. If an error occurs, an LSM error code is returned and
-** the final value of *piId is undefined.
-*/
-int lsmCheckpointSynced(lsm_db *pDb, i64 *piId, i64 *piLog, u32 *pnWrite){
- int rc = LSM_OK;
- MetaPage *pPg;
- u32 iMeta;
-
- iMeta = pDb->pShmhdr->iMetaPage;
- if( iMeta==1 || iMeta==2 ){
- rc = lsmFsMetaPageGet(pDb->pFS, 0, iMeta, &pPg);
- if( rc==LSM_OK ){
- int nCkpt;
- int nData;
- u8 *aData;
-
- aData = lsmFsMetaPageData(pPg, &nData);
- assert( nData==LSM_META_RW_PAGE_SIZE );
- nCkpt = lsmGetU32(&aData[CKPT_HDR_NCKPT*sizeof(u32)]);
- if( nCkpt<(LSM_META_RW_PAGE_SIZE/sizeof(u32)) ){
- u32 *aCopy = lsmMallocRc(pDb->pEnv, sizeof(u32) * nCkpt, &rc);
- if( aCopy ){
- memcpy(aCopy, aData, nCkpt*sizeof(u32));
- ckptChangeEndianness(aCopy, nCkpt);
- if( ckptChecksumOk(aCopy) ){
- if( piId ) *piId = lsmCheckpointId(aCopy, 0);
- if( piLog ) *piLog = (lsmCheckpointLogOffset(aCopy) >> 1);
- if( pnWrite ) *pnWrite = aCopy[CKPT_HDR_NWRITE];
- }
- lsmFree(pDb->pEnv, aCopy);
- }
- }
- lsmFsMetaPageRelease(pPg);
- }
- }
-
- if( (iMeta!=1 && iMeta!=2) || rc!=LSM_OK || pDb->pShmhdr->iMetaPage!=iMeta ){
- if( piId ) *piId = 0;
- if( piLog ) *piLog = 0;
- if( pnWrite ) *pnWrite = 0;
- }
- return rc;
-}
-
-/*
-** Return the checkpoint-id of the checkpoint array passed as the first
-** argument to this function. If the second argument is true, then assume
-** that the checkpoint is made up of 32-bit big-endian integers. If it
-** is false, assume that the integers are in machine byte order.
-*/
-i64 lsmCheckpointId(u32 *aCkpt, int bDisk){
- i64 iId;
- if( bDisk ){
- u8 *aData = (u8 *)aCkpt;
- iId = (((i64)lsmGetU32(&aData[CKPT_HDR_ID_MSW*4])) << 32);
- iId += ((i64)lsmGetU32(&aData[CKPT_HDR_ID_LSW*4]));
- }else{
- iId = ((i64)aCkpt[CKPT_HDR_ID_MSW] << 32) + (i64)aCkpt[CKPT_HDR_ID_LSW];
- }
- return iId;
-}
-
-u32 lsmCheckpointNBlock(u32 *aCkpt){
- return aCkpt[CKPT_HDR_NBLOCK];
-}
-
-u32 lsmCheckpointNWrite(u32 *aCkpt, int bDisk){
- if( bDisk ){
- return lsmGetU32((u8 *)&aCkpt[CKPT_HDR_NWRITE]);
- }else{
- return aCkpt[CKPT_HDR_NWRITE];
- }
-}
-
-i64 lsmCheckpointLogOffset(u32 *aCkpt){
- return ((i64)aCkpt[CKPT_HDR_LO_MSW] << 32) + (i64)aCkpt[CKPT_HDR_LO_LSW];
-}
-
-int lsmCheckpointPgsz(u32 *aCkpt){ return (int)aCkpt[CKPT_HDR_PGSZ]; }
-
-int lsmCheckpointBlksz(u32 *aCkpt){ return (int)aCkpt[CKPT_HDR_BLKSZ]; }
-
-void lsmCheckpointLogoffset(
- u32 *aCkpt,
- DbLog *pLog
-){
- pLog->aRegion[2].iStart = (lsmCheckpointLogOffset(aCkpt) >> 1);
-
- pLog->cksum0 = aCkpt[CKPT_HDR_LO_CKSUM1];
- pLog->cksum1 = aCkpt[CKPT_HDR_LO_CKSUM2];
- pLog->iSnapshotId = lsmCheckpointId(aCkpt, 0);
-}
-
-void lsmCheckpointZeroLogoffset(lsm_db *pDb){
- u32 nCkpt;
-
- nCkpt = pDb->aSnapshot[CKPT_HDR_NCKPT];
- assert( nCkpt>CKPT_HDR_NCKPT );
- assert( nCkpt==pDb->pShmhdr->aSnap1[CKPT_HDR_NCKPT] );
- assert( 0==memcmp(pDb->aSnapshot, pDb->pShmhdr->aSnap1, nCkpt*sizeof(u32)) );
- assert( 0==memcmp(pDb->aSnapshot, pDb->pShmhdr->aSnap2, nCkpt*sizeof(u32)) );
-
- pDb->aSnapshot[CKPT_HDR_LO_MSW] = 0;
- pDb->aSnapshot[CKPT_HDR_LO_LSW] = 0;
- ckptChecksum(pDb->aSnapshot, nCkpt,
- &pDb->aSnapshot[nCkpt-2], &pDb->aSnapshot[nCkpt-1]
- );
-
- memcpy(pDb->pShmhdr->aSnap1, pDb->aSnapshot, nCkpt*sizeof(u32));
- memcpy(pDb->pShmhdr->aSnap2, pDb->aSnapshot, nCkpt*sizeof(u32));
-}
-
-/*
-** Set the output variable to the number of KB of data written into the
-** database file since the most recent checkpoint.
-*/
-int lsmCheckpointSize(lsm_db *db, int *pnKB){
- int rc = LSM_OK;
- u32 nSynced;
-
- /* Set nSynced to the number of pages that had been written when the
- ** database was last checkpointed. */
- rc = lsmCheckpointSynced(db, 0, 0, &nSynced);
-
- if( rc==LSM_OK ){
- u32 nPgsz = db->pShmhdr->aSnap1[CKPT_HDR_PGSZ];
- u32 nWrite = db->pShmhdr->aSnap1[CKPT_HDR_NWRITE];
- *pnKB = (int)(( ((i64)(nWrite - nSynced) * nPgsz) + 1023) / 1024);
- }
-
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_file.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_file.c
deleted file mode 100644
index 1dcdd05d997..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_file.c
+++ /dev/null
@@ -1,3312 +0,0 @@
-/*
-** 2011-08-26
-**
-** 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.
-**
-*************************************************************************
-**
-** NORMAL DATABASE FILE FORMAT
-**
-** The following database file format concepts are used by the code in
-** this file to read and write the database file.
-**
-** Pages:
-**
-** A database file is divided into pages. The first 8KB of the file consists
-** of two 4KB meta-pages. The meta-page size is not configurable. The
-** remainder of the file is made up of database pages. The default database
-** page size is 4KB. Database pages are aligned to page-size boundaries,
-** so if the database page size is larger than 8KB there is a gap between
-** the end of the meta pages and the start of the database pages.
-**
-** Database pages are numbered based on their position in the file. Page N
-** begins at byte offset ((N-1)*pgsz). This means that page 1 does not
-** exist - since it would always overlap with the meta pages. If the
-** page-size is (say) 512 bytes, then the first usable page in the database
-** is page 33.
-**
-** It is assumed that the first two meta pages and the data that follows
-** them are located on different disk sectors. So that if a power failure
-** while writing to a meta page there is no risk of damage to the other
-** meta page or any other part of the database file. TODO: This may need
-** to be revisited.
-**
-** Blocks:
-**
-** The database file is also divided into blocks. The default block size is
-** 1MB. When writing to the database file, an attempt is made to write data
-** in contiguous block-sized chunks.
-**
-** The first and last page on each block are special in that they are 4
-** bytes smaller than all other pages. This is because the last four bytes
-** of space on the first and last pages of each block are reserved for
-** pointers to other blocks (i.e. a 32-bit block number).
-**
-** Runs:
-**
-** A run is a sequence of pages that the upper layer uses to store a
-** sorted array of database keys (and accompanying data - values, FC
-** pointers and so on). Given a page within a run, it is possible to
-** navigate to the next page in the run as follows:
-**
-** a) if the current page is not the last in a block, the next page
-** in the run is located immediately after the current page, OR
-**
-** b) if the current page is the last page in a block, the next page
-** in the run is the first page on the block identified by the
-** block pointer stored in the last 4 bytes of the current block.
-**
-** It is possible to navigate to the previous page in a similar fashion,
-** using the block pointer embedded in the last 4 bytes of the first page
-** of each block as required.
-**
-** The upper layer is responsible for identifying by page number the
-** first and last page of any run that it needs to navigate - there are
-** no "end-of-run" markers stored or identified by this layer. This is
-** necessary as clients reading different database snapshots may access
-** different subsets of a run.
-**
-** THE LOG FILE
-**
-** This file opens and closes the log file. But it does not contain any
-** logic related to the log file format. Instead, it exports the following
-** functions that are used by the code in lsm_log.c to read and write the
-** log file:
-**
-** lsmFsOpenLog
-** lsmFsWriteLog
-** lsmFsSyncLog
-** lsmFsReadLog
-** lsmFsTruncateLog
-** lsmFsCloseAndDeleteLog
-**
-** COMPRESSED DATABASE FILE FORMAT
-**
-** The compressed database file format is very similar to the normal format.
-** The file still begins with two 4KB meta-pages (which are never compressed).
-** It is still divided into blocks.
-**
-** The first and last four bytes of each block are reserved for 32-bit
-** pointer values. Similar to the way four bytes are carved from the end of
-** the first and last page of each block in uncompressed databases. From
-** the point of view of the upper layer, all pages are the same size - this
-** is different from the uncompressed format where the first and last pages
-** on each block are 4 bytes smaller than the others.
-**
-** Pages are stored in variable length compressed form, as follows:
-**
-** * 3-byte size field containing the size of the compressed page image
-** in bytes. The most significant bit of each byte of the size field
-** is always set. The remaining 7 bits are used to store a 21-bit
-** integer value (in big-endian order - the first byte in the field
-** contains the most significant 7 bits). Since the maximum allowed
-** size of a compressed page image is (2^17 - 1) bytes, there are
-** actually 4 unused bits in the size field.
-**
-** In other words, if the size of the compressed page image is nSz,
-** the header can be serialized as follows:
-**
-** u8 aHdr[3]
-** aHdr[0] = 0x80 | (u8)(nSz >> 14);
-** aHdr[1] = 0x80 | (u8)(nSz >> 7);
-** aHdr[2] = 0x80 | (u8)(nSz >> 0);
-**
-** * Compressed page image.
-**
-** * A second copy of the 3-byte record header.
-**
-** A page number is a byte offset into the database file. So the smallest
-** possible page number is 8192 (immediately after the two meta-pages).
-** The first and root page of a segment are identified by a page number
-** corresponding to the byte offset of the first byte in the corresponding
-** page record. The last page of a segment is identified by the byte offset
-** of the last byte in its record.
-**
-** Unlike uncompressed pages, compressed page records may span blocks.
-**
-** Sometimes, in order to avoid touching sectors that contain synced data
-** when writing, it is necessary to insert unused space between compressed
-** page records. This can be done as follows:
-**
-** * For less than 6 bytes of empty space, the first and last byte
-** of the free space contain the total number of free bytes. For
-** example:
-**
-** Block of 4 free bytes: 0x04 0x?? 0x?? 0x04
-** Block of 2 free bytes: 0x02 0x02
-** A single free byte: 0x01
-**
-** * For 6 or more bytes of empty space, a record similar to a
-** compressed page record is added to the segment. A padding record
-** is distinguished from a compressed page record by the most
-** significant bit of the second byte of the size field, which is
-** cleared instead of set.
-*/
-#include "lsmInt.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-/*
-** File-system object. Each database connection allocates a single instance
-** of the following structure. It is used for all access to the database and
-** log files.
-**
-** The database file may be accessed via two methods - using mmap() or using
-** read() and write() calls. In the general case both methods are used - a
-** prefix of the file is mapped into memory and the remainder accessed using
-** read() and write(). This is helpful when accessing very large files (or
-** files that may grow very large during the lifetime of a database
-** connection) on systems with 32-bit address spaces. However, it also requires
-** that this object manage two distinct types of Page objects simultaneously -
-** those that carry pointers to the mapped file and those that carry arrays
-** populated by read() calls.
-**
-** pFree:
-** The head of a singly-linked list that containing currently unused Page
-** structures suitable for use as mmap-page handles. Connected by the
-** Page.pFreeNext pointers.
-**
-** pMapped:
-** The head of a singly-linked list that contains all pages that currently
-** carry pointers to the mapped region. This is used if the region is
-** every remapped - the pointers carried by existing pages can be adjusted
-** to account for the remapping. Connected by the Page.pMappedNext pointers.
-**
-** pWaiting:
-** When the upper layer wishes to append a new b-tree page to a segment,
-** it allocates a Page object that carries a malloc'd block of memory -
-** regardless of the mmap-related configuration. The page is not assigned
-** a page number at first. When the upper layer has finished constructing
-** the page contents, it calls lsmFsPagePersist() to assign a page number
-** to it. At this point it is likely that N pages have been written to the
-** segment, the (N+1)th page is still outstanding and the b-tree page is
-** assigned page number (N+2). To avoid writing page (N+2) before page
-** (N+1), the recently completed b-tree page is held in the singly linked
-** list headed by pWaiting until page (N+1) has been written.
-**
-** Function lsmFsFlushWaiting() is responsible for eventually writing
-** waiting pages to disk.
-**
-** apHash/nHash:
-** Hash table used to store all Page objects that carry malloc'd arrays,
-** except those b-tree pages that have not yet been assigned page numbers.
-** Once they have been assigned page numbers - they are added to this
-** hash table.
-**
-** Hash table overflow chains are connected using the Page.pHashNext
-** pointers.
-**
-** pLruFirst, pLruLast:
-** The first and last entries in a doubly-linked list of pages. This
-** list contains all pages with malloc'd data that are present in the
-** hash table and have a ref-count of zero.
-*/
-struct FileSystem {
- lsm_db *pDb; /* Database handle that owns this object */
- lsm_env *pEnv; /* Environment pointer */
- char *zDb; /* Database file name */
- char *zLog; /* Database file name */
- int nMetasize; /* Size of meta pages in bytes */
- int nMetaRwSize; /* Read/written size of meta pages in bytes */
- int nPagesize; /* Database page-size in bytes */
- int nBlocksize; /* Database block-size in bytes */
-
- /* r/w file descriptors for both files. */
- LsmFile *pLsmFile; /* Used after lsm_close() to link into list */
- lsm_file *fdDb; /* Database file */
- lsm_file *fdLog; /* Log file */
- int szSector; /* Database file sector size */
-
- /* If this is a compressed database, a pointer to the compression methods.
- ** For an uncompressed database, a NULL pointer. */
- lsm_compress *pCompress;
- u8 *aIBuffer; /* Buffer to compress to */
- u8 *aOBuffer; /* Buffer to uncompress from */
- int nBuffer; /* Allocated size of above buffers in bytes */
-
- /* mmap() page related things */
- i64 nMapLimit; /* Maximum bytes of file to map */
- void *pMap; /* Current mapping of database file */
- i64 nMap; /* Bytes mapped at pMap */
- Page *pFree; /* Unused Page structures */
- Page *pMapped; /* List of Page structs that point to pMap */
-
- /* Page cache parameters for non-mmap() pages */
- int nCacheMax; /* Configured cache size (in pages) */
- int nCacheAlloc; /* Current cache size (in pages) */
- Page *pLruFirst; /* Head of the LRU list */
- Page *pLruLast; /* Tail of the LRU list */
- int nHash; /* Number of hash slots in hash table */
- Page **apHash; /* nHash Hash slots */
- Page *pWaiting; /* b-tree pages waiting to be written */
-
- /* Statistics */
- int nOut; /* Number of outstanding pages */
- int nWrite; /* Total number of pages written */
- int nRead; /* Total number of pages read */
-};
-
-/*
-** Database page handle.
-**
-** pSeg:
-** When lsmFsSortedAppend() is called on a compressed database, the new
-** page is not assigned a page number or location in the database file
-** immediately. Instead, these are assigned by the lsmFsPagePersist() call
-** right before it writes the compressed page image to disk.
-**
-** The lsmFsSortedAppend() function sets the pSeg pointer to point to the
-** segment that the new page will be a part of. It is unset by
-** lsmFsPagePersist() after the page is written to disk.
-*/
-struct Page {
- u8 *aData; /* Buffer containing page data */
- int nData; /* Bytes of usable data at aData[] */
- LsmPgno iPg; /* Page number */
- int nRef; /* Number of outstanding references */
- int flags; /* Combination of PAGE_XXX flags */
- Page *pHashNext; /* Next page in hash table slot */
- Page *pLruNext; /* Next page in LRU list */
- Page *pLruPrev; /* Previous page in LRU list */
- FileSystem *pFS; /* File system that owns this page */
-
- /* Only used in compressed database mode: */
- int nCompress; /* Compressed size (or 0 for uncomp. db) */
- int nCompressPrev; /* Compressed size of prev page */
- Segment *pSeg; /* Segment this page will be written to */
-
- /* Pointers for singly linked lists */
- Page *pWaitingNext; /* Next page in FileSystem.pWaiting list */
- Page *pFreeNext; /* Next page in FileSystem.pFree list */
- Page *pMappedNext; /* Next page in FileSystem.pMapped list */
-};
-
-/*
-** Meta-data page handle. There are two meta-data pages at the start of
-** the database file, each FileSystem.nMetasize bytes in size.
-*/
-struct MetaPage {
- int iPg; /* Either 1 or 2 */
- int bWrite; /* Write back to db file on release */
- u8 *aData; /* Pointer to buffer */
- FileSystem *pFS; /* FileSystem that owns this page */
-};
-
-/*
-** Values for LsmPage.flags
-*/
-#define PAGE_DIRTY 0x00000001 /* Set if page is dirty */
-#define PAGE_FREE 0x00000002 /* Set if Page.aData requires lsmFree() */
-#define PAGE_HASPREV 0x00000004 /* Set if page is first on uncomp. block */
-
-/*
-** Number of pgsz byte pages omitted from the start of block 1. The start
-** of block 1 contains two 4096 byte meta pages (8192 bytes in total).
-*/
-#define BLOCK1_HDR_SIZE(pgsz) LSM_MAX(1, 8192/(pgsz))
-
-/*
-** If NDEBUG is not defined, set a breakpoint in function lsmIoerrBkpt()
-** to catch IO errors (any error returned by a VFS method).
-*/
-#ifndef NDEBUG
-static void lsmIoerrBkpt(void){
- static int nErr = 0;
- nErr++;
-}
-static int IOERR_WRAPPER(int rc){
- if( rc!=LSM_OK ) lsmIoerrBkpt();
- return rc;
-}
-#else
-# define IOERR_WRAPPER(rc) (rc)
-#endif
-
-#ifdef NDEBUG
-# define assert_lists_are_ok(x)
-#else
-static Page *fsPageFindInHash(FileSystem *pFS, LsmPgno iPg, int *piHash);
-
-static void assert_lists_are_ok(FileSystem *pFS){
-#if 0
- Page *p;
-
- assert( pFS->nMapLimit>=0 );
-
- /* Check that all pages in the LRU list have nRef==0, pointers to buffers
- ** in heap memory, and corresponding entries in the hash table. */
- for(p=pFS->pLruFirst; p; p=p->pLruNext){
- assert( p==pFS->pLruFirst || p->pLruPrev!=0 );
- assert( p==pFS->pLruLast || p->pLruNext!=0 );
- assert( p->pLruPrev==0 || p->pLruPrev->pLruNext==p );
- assert( p->pLruNext==0 || p->pLruNext->pLruPrev==p );
- assert( p->nRef==0 );
- assert( p->flags & PAGE_FREE );
- assert( p==fsPageFindInHash(pFS, p->iPg, 0) );
- }
-#endif
-}
-#endif
-
-/*
-** Wrappers around the VFS methods of the lsm_env object:
-**
-** lsmEnvOpen()
-** lsmEnvRead()
-** lsmEnvWrite()
-** lsmEnvSync()
-** lsmEnvSectorSize()
-** lsmEnvClose()
-** lsmEnvTruncate()
-** lsmEnvUnlink()
-** lsmEnvRemap()
-*/
-int lsmEnvOpen(lsm_env *pEnv, const char *zFile, int flags, lsm_file **ppNew){
- return pEnv->xOpen(pEnv, zFile, flags, ppNew);
-}
-
-static int lsmEnvRead(
- lsm_env *pEnv,
- lsm_file *pFile,
- lsm_i64 iOff,
- void *pRead,
- int nRead
-){
- return IOERR_WRAPPER( pEnv->xRead(pFile, iOff, pRead, nRead) );
-}
-
-static int lsmEnvWrite(
- lsm_env *pEnv,
- lsm_file *pFile,
- lsm_i64 iOff,
- const void *pWrite,
- int nWrite
-){
- return IOERR_WRAPPER( pEnv->xWrite(pFile, iOff, (void *)pWrite, nWrite) );
-}
-
-static int lsmEnvSync(lsm_env *pEnv, lsm_file *pFile){
- return IOERR_WRAPPER( pEnv->xSync(pFile) );
-}
-
-static int lsmEnvSectorSize(lsm_env *pEnv, lsm_file *pFile){
- return pEnv->xSectorSize(pFile);
-}
-
-int lsmEnvClose(lsm_env *pEnv, lsm_file *pFile){
- return IOERR_WRAPPER( pEnv->xClose(pFile) );
-}
-
-static int lsmEnvTruncate(lsm_env *pEnv, lsm_file *pFile, lsm_i64 nByte){
- return IOERR_WRAPPER( pEnv->xTruncate(pFile, nByte) );
-}
-
-static int lsmEnvUnlink(lsm_env *pEnv, const char *zDel){
- return IOERR_WRAPPER( pEnv->xUnlink(pEnv, zDel) );
-}
-
-static int lsmEnvRemap(
- lsm_env *pEnv,
- lsm_file *pFile,
- i64 szMin,
- void **ppMap,
- i64 *pszMap
-){
- return pEnv->xRemap(pFile, szMin, ppMap, pszMap);
-}
-
-int lsmEnvLock(lsm_env *pEnv, lsm_file *pFile, int iLock, int eLock){
- if( pFile==0 ) return LSM_OK;
- return pEnv->xLock(pFile, iLock, eLock);
-}
-
-int lsmEnvTestLock(
- lsm_env *pEnv,
- lsm_file *pFile,
- int iLock,
- int nLock,
- int eLock
-){
- return pEnv->xTestLock(pFile, iLock, nLock, eLock);
-}
-
-int lsmEnvShmMap(
- lsm_env *pEnv,
- lsm_file *pFile,
- int iChunk,
- int sz,
- void **ppOut
-){
- return pEnv->xShmMap(pFile, iChunk, sz, ppOut);
-}
-
-void lsmEnvShmBarrier(lsm_env *pEnv){
- pEnv->xShmBarrier();
-}
-
-void lsmEnvShmUnmap(lsm_env *pEnv, lsm_file *pFile, int bDel){
- pEnv->xShmUnmap(pFile, bDel);
-}
-
-void lsmEnvSleep(lsm_env *pEnv, int nUs){
- pEnv->xSleep(pEnv, nUs);
-}
-
-
-/*
-** Write the contents of string buffer pStr into the log file, starting at
-** offset iOff.
-*/
-int lsmFsWriteLog(FileSystem *pFS, i64 iOff, LsmString *pStr){
- assert( pFS->fdLog );
- return lsmEnvWrite(pFS->pEnv, pFS->fdLog, iOff, pStr->z, pStr->n);
-}
-
-/*
-** fsync() the log file.
-*/
-int lsmFsSyncLog(FileSystem *pFS){
- assert( pFS->fdLog );
- return lsmEnvSync(pFS->pEnv, pFS->fdLog);
-}
-
-/*
-** Read nRead bytes of data starting at offset iOff of the log file. Append
-** the results to string buffer pStr.
-*/
-int lsmFsReadLog(FileSystem *pFS, i64 iOff, int nRead, LsmString *pStr){
- int rc; /* Return code */
- assert( pFS->fdLog );
- rc = lsmStringExtend(pStr, nRead);
- if( rc==LSM_OK ){
- rc = lsmEnvRead(pFS->pEnv, pFS->fdLog, iOff, &pStr->z[pStr->n], nRead);
- pStr->n += nRead;
- }
- return rc;
-}
-
-/*
-** Truncate the log file to nByte bytes in size.
-*/
-int lsmFsTruncateLog(FileSystem *pFS, i64 nByte){
- if( pFS->fdLog==0 ) return LSM_OK;
- return lsmEnvTruncate(pFS->pEnv, pFS->fdLog, nByte);
-}
-
-/*
-** Truncate the db file to nByte bytes in size.
-*/
-int lsmFsTruncateDb(FileSystem *pFS, i64 nByte){
- if( pFS->fdDb==0 ) return LSM_OK;
- return lsmEnvTruncate(pFS->pEnv, pFS->fdDb, nByte);
-}
-
-/*
-** Close the log file. Then delete it from the file-system. This function
-** is called during database shutdown only.
-*/
-int lsmFsCloseAndDeleteLog(FileSystem *pFS){
- char *zDel;
-
- if( pFS->fdLog ){
- lsmEnvClose(pFS->pEnv, pFS->fdLog );
- pFS->fdLog = 0;
- }
-
- zDel = lsmMallocPrintf(pFS->pEnv, "%s-log", pFS->zDb);
- if( zDel ){
- lsmEnvUnlink(pFS->pEnv, zDel);
- lsmFree(pFS->pEnv, zDel);
- }
- return LSM_OK;
-}
-
-/*
-** Return true if page iReal of the database should be accessed using mmap.
-** False otherwise.
-*/
-static int fsMmapPage(FileSystem *pFS, LsmPgno iReal){
- return ((i64)iReal*pFS->nPagesize <= pFS->nMapLimit);
-}
-
-/*
-** Given that there are currently nHash slots in the hash table, return
-** the hash key for file iFile, page iPg.
-*/
-static int fsHashKey(int nHash, LsmPgno iPg){
- return (iPg % nHash);
-}
-
-/*
-** This is a helper function for lsmFsOpen(). It opens a single file on
-** disk (either the database or log file).
-*/
-static lsm_file *fsOpenFile(
- FileSystem *pFS, /* File system object */
- int bReadonly, /* True to open this file read-only */
- int bLog, /* True for log, false for db */
- int *pRc /* IN/OUT: Error code */
-){
- lsm_file *pFile = 0;
- if( *pRc==LSM_OK ){
- int flags = (bReadonly ? LSM_OPEN_READONLY : 0);
- const char *zPath = (bLog ? pFS->zLog : pFS->zDb);
-
- *pRc = lsmEnvOpen(pFS->pEnv, zPath, flags, &pFile);
- }
- return pFile;
-}
-
-/*
-** If it is not already open, this function opens the log file. It returns
-** LSM_OK if successful (or if the log file was already open) or an LSM
-** error code otherwise.
-**
-** The log file must be opened before any of the following may be called:
-**
-** lsmFsWriteLog
-** lsmFsSyncLog
-** lsmFsReadLog
-*/
-int lsmFsOpenLog(lsm_db *db, int *pbOpen){
- int rc = LSM_OK;
- FileSystem *pFS = db->pFS;
-
- if( 0==pFS->fdLog ){
- pFS->fdLog = fsOpenFile(pFS, db->bReadonly, 1, &rc);
-
- if( rc==LSM_IOERR_NOENT && db->bReadonly ){
- rc = LSM_OK;
- }
- }
-
- if( pbOpen ) *pbOpen = (pFS->fdLog!=0);
- return rc;
-}
-
-/*
-** Close the log file, if it is open.
-*/
-void lsmFsCloseLog(lsm_db *db){
- FileSystem *pFS = db->pFS;
- if( pFS->fdLog ){
- lsmEnvClose(pFS->pEnv, pFS->fdLog);
- pFS->fdLog = 0;
- }
-}
-
-/*
-** Open a connection to a database stored within the file-system.
-**
-** If parameter bReadonly is true, then open a read-only file-descriptor
-** on the database file. It is possible that bReadonly will be false even
-** if the user requested that pDb be opened read-only. This is because the
-** file-descriptor may later on be recycled by a read-write connection.
-** If the db file can be opened for read-write access, it always is. Parameter
-** bReadonly is only ever true if it has already been determined that the
-** db can only be opened for read-only access.
-**
-** Return LSM_OK if successful or an lsm error code otherwise.
-*/
-int lsmFsOpen(
- lsm_db *pDb, /* Database connection to open fd for */
- const char *zDb, /* Full path to database file */
- int bReadonly /* True to open db file read-only */
-){
- FileSystem *pFS;
- int rc = LSM_OK;
- int nDb = strlen(zDb);
- int nByte;
-
- assert( pDb->pFS==0 );
- assert( pDb->pWorker==0 && pDb->pClient==0 );
-
- nByte = sizeof(FileSystem) + nDb+1 + nDb+4+1;
- pFS = (FileSystem *)lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
- if( pFS ){
- LsmFile *pLsmFile;
- pFS->zDb = (char *)&pFS[1];
- pFS->zLog = &pFS->zDb[nDb+1];
- pFS->nPagesize = LSM_DFLT_PAGE_SIZE;
- pFS->nBlocksize = LSM_DFLT_BLOCK_SIZE;
- pFS->nMetasize = LSM_META_PAGE_SIZE;
- pFS->nMetaRwSize = LSM_META_RW_PAGE_SIZE;
- pFS->pDb = pDb;
- pFS->pEnv = pDb->pEnv;
-
- /* Make a copy of the database and log file names. */
- memcpy(pFS->zDb, zDb, nDb+1);
- memcpy(pFS->zLog, zDb, nDb);
- memcpy(&pFS->zLog[nDb], "-log", 5);
-
- /* Allocate the hash-table here. At some point, it should be changed
- ** so that it can grow dynamicly. */
- pFS->nCacheMax = 2048*1024 / pFS->nPagesize;
- pFS->nHash = 4096;
- pFS->apHash = lsmMallocZeroRc(pDb->pEnv, sizeof(Page *) * pFS->nHash, &rc);
-
- /* Open the database file */
- pLsmFile = lsmDbRecycleFd(pDb);
- if( pLsmFile ){
- pFS->pLsmFile = pLsmFile;
- pFS->fdDb = pLsmFile->pFile;
- memset(pLsmFile, 0, sizeof(LsmFile));
- }else{
- pFS->pLsmFile = lsmMallocZeroRc(pDb->pEnv, sizeof(LsmFile), &rc);
- if( rc==LSM_OK ){
- pFS->fdDb = fsOpenFile(pFS, bReadonly, 0, &rc);
- }
- }
-
- if( rc!=LSM_OK ){
- lsmFsClose(pFS);
- pFS = 0;
- }else{
- pFS->szSector = lsmEnvSectorSize(pFS->pEnv, pFS->fdDb);
- }
- }
-
- pDb->pFS = pFS;
- return rc;
-}
-
-/*
-** Configure the file-system object according to the current values of
-** the LSM_CONFIG_MMAP and LSM_CONFIG_SET_COMPRESSION options.
-*/
-int lsmFsConfigure(lsm_db *db){
- FileSystem *pFS = db->pFS;
- if( pFS ){
- lsm_env *pEnv = pFS->pEnv;
- Page *pPg;
-
- assert( pFS->nOut==0 );
- assert( pFS->pWaiting==0 );
- assert( pFS->pMapped==0 );
-
- /* Reset any compression/decompression buffers already allocated */
- lsmFree(pEnv, pFS->aIBuffer);
- lsmFree(pEnv, pFS->aOBuffer);
- pFS->nBuffer = 0;
-
- /* Unmap the file, if it is currently mapped */
- if( pFS->pMap ){
- lsmEnvRemap(pEnv, pFS->fdDb, -1, &pFS->pMap, &pFS->nMap);
- pFS->nMapLimit = 0;
- }
-
- /* Free all allocated page structures */
- pPg = pFS->pLruFirst;
- while( pPg ){
- Page *pNext = pPg->pLruNext;
- assert( pPg->flags & PAGE_FREE );
- lsmFree(pEnv, pPg->aData);
- lsmFree(pEnv, pPg);
- pPg = pNext;
- }
-
- pPg = pFS->pFree;
- while( pPg ){
- Page *pNext = pPg->pFreeNext;
- lsmFree(pEnv, pPg);
- pPg = pNext;
- }
-
- /* Zero pointers that point to deleted page objects */
- pFS->nCacheAlloc = 0;
- pFS->pLruFirst = 0;
- pFS->pLruLast = 0;
- pFS->pFree = 0;
- if( pFS->apHash ){
- memset(pFS->apHash, 0, pFS->nHash*sizeof(pFS->apHash[0]));
- }
-
- /* Configure the FileSystem object */
- if( db->compress.xCompress ){
- pFS->pCompress = &db->compress;
- pFS->nMapLimit = 0;
- }else{
- pFS->pCompress = 0;
- if( db->iMmap==1 ){
- /* Unlimited */
- pFS->nMapLimit = (i64)1 << 60;
- }else{
- /* iMmap is a limit in KB. Set nMapLimit to the same value in bytes. */
- pFS->nMapLimit = (i64)db->iMmap * 1024;
- }
- }
- }
-
- return LSM_OK;
-}
-
-/*
-** Close and destroy a FileSystem object.
-*/
-void lsmFsClose(FileSystem *pFS){
- if( pFS ){
- Page *pPg;
- lsm_env *pEnv = pFS->pEnv;
-
- assert( pFS->nOut==0 );
- pPg = pFS->pLruFirst;
- while( pPg ){
- Page *pNext = pPg->pLruNext;
- if( pPg->flags & PAGE_FREE ) lsmFree(pEnv, pPg->aData);
- lsmFree(pEnv, pPg);
- pPg = pNext;
- }
-
- pPg = pFS->pFree;
- while( pPg ){
- Page *pNext = pPg->pFreeNext;
- if( pPg->flags & PAGE_FREE ) lsmFree(pEnv, pPg->aData);
- lsmFree(pEnv, pPg);
- pPg = pNext;
- }
-
- if( pFS->fdDb ) lsmEnvClose(pFS->pEnv, pFS->fdDb );
- if( pFS->fdLog ) lsmEnvClose(pFS->pEnv, pFS->fdLog );
- lsmFree(pEnv, pFS->pLsmFile);
- lsmFree(pEnv, pFS->apHash);
- lsmFree(pEnv, pFS->aIBuffer);
- lsmFree(pEnv, pFS->aOBuffer);
- lsmFree(pEnv, pFS);
- }
-}
-
-/*
-** This function is called when closing a database handle (i.e. lsm_close())
-** if there exist other connections to the same database within this process.
-** In that case the file-descriptor open on the database file is not closed
-** when the FileSystem object is destroyed, as this would cause any POSIX
-** locks held by the other connections to be silently dropped (see "man close"
-** for details). Instead, the file-descriptor is stored in a list by the
-** lsm_shared.c module until it is either closed or reused.
-**
-** This function returns a pointer to an object that can be linked into
-** the list described above. The returned object now 'owns' the database
-** file descriptr, so that when the FileSystem object is destroyed, it
-** will not be closed.
-**
-** This function may be called at most once in the life-time of a
-** FileSystem object. The results of any operations involving the database
-** file descriptor are undefined once this function has been called.
-**
-** None of this is necessary on non-POSIX systems. But we do it anyway in
-** the name of using as similar code as possible on all platforms.
-*/
-LsmFile *lsmFsDeferClose(FileSystem *pFS){
- LsmFile *p = pFS->pLsmFile;
- assert( p->pNext==0 );
- p->pFile = pFS->fdDb;
- pFS->fdDb = 0;
- pFS->pLsmFile = 0;
- return p;
-}
-
-/*
-** Allocate a buffer and populate it with the output of the xFileid()
-** method of the database file handle. If successful, set *ppId to point
-** to the buffer and *pnId to the number of bytes in the buffer and return
-** LSM_OK. Otherwise, set *ppId and *pnId to zero and return an LSM
-** error code.
-*/
-int lsmFsFileid(lsm_db *pDb, void **ppId, int *pnId){
- lsm_env *pEnv = pDb->pEnv;
- FileSystem *pFS = pDb->pFS;
- int rc;
- int nId = 0;
- void *pId;
-
- rc = pEnv->xFileid(pFS->fdDb, 0, &nId);
- pId = lsmMallocZeroRc(pEnv, nId, &rc);
- if( rc==LSM_OK ) rc = pEnv->xFileid(pFS->fdDb, pId, &nId);
-
- if( rc!=LSM_OK ){
- lsmFree(pEnv, pId);
- pId = 0;
- nId = 0;
- }
-
- *ppId = pId;
- *pnId = nId;
- return rc;
-}
-
-/*
-** Return the nominal page-size used by this file-system. Actual pages
-** may be smaller or larger than this value.
-*/
-int lsmFsPageSize(FileSystem *pFS){
- return pFS->nPagesize;
-}
-
-/*
-** Return the block-size used by this file-system.
-*/
-int lsmFsBlockSize(FileSystem *pFS){
- return pFS->nBlocksize;
-}
-
-/*
-** Configure the nominal page-size used by this file-system. Actual
-** pages may be smaller or larger than this value.
-*/
-void lsmFsSetPageSize(FileSystem *pFS, int nPgsz){
- pFS->nPagesize = nPgsz;
- pFS->nCacheMax = 2048*1024 / pFS->nPagesize;
-}
-
-/*
-** Configure the block-size used by this file-system.
-*/
-void lsmFsSetBlockSize(FileSystem *pFS, int nBlocksize){
- pFS->nBlocksize = nBlocksize;
-}
-
-/*
-** Return the page number of the first page on block iBlock. Blocks are
-** numbered starting from 1.
-**
-** For a compressed database, page numbers are byte offsets. The first
-** page on each block is the byte offset immediately following the 4-byte
-** "previous block" pointer at the start of each block.
-*/
-static LsmPgno fsFirstPageOnBlock(FileSystem *pFS, int iBlock){
- LsmPgno iPg;
- if( pFS->pCompress ){
- if( iBlock==1 ){
- iPg = pFS->nMetasize * 2 + 4;
- }else{
- iPg = pFS->nBlocksize * (LsmPgno)(iBlock-1) + 4;
- }
- }else{
- const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
- if( iBlock==1 ){
- iPg = 1 + ((pFS->nMetasize*2 + pFS->nPagesize - 1) / pFS->nPagesize);
- }else{
- iPg = 1 + (iBlock-1) * nPagePerBlock;
- }
- }
- return iPg;
-}
-
-/*
-** Return the page number of the last page on block iBlock. Blocks are
-** numbered starting from 1.
-**
-** For a compressed database, page numbers are byte offsets. The first
-** page on each block is the byte offset of the byte immediately before
-** the 4-byte "next block" pointer at the end of each block.
-*/
-static LsmPgno fsLastPageOnBlock(FileSystem *pFS, int iBlock){
- if( pFS->pCompress ){
- return pFS->nBlocksize * (LsmPgno)iBlock - 1 - 4;
- }else{
- const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
- return iBlock * nPagePerBlock;
- }
-}
-
-/*
-** Return the block number of the block that page iPg is located on.
-** Blocks are numbered starting from 1.
-*/
-static int fsPageToBlock(FileSystem *pFS, LsmPgno iPg){
- if( pFS->pCompress ){
- return (int)((iPg / pFS->nBlocksize) + 1);
- }else{
- return (int)(1 + ((iPg-1) / (pFS->nBlocksize / pFS->nPagesize)));
- }
-}
-
-/*
-** Return true if page iPg is the last page on its block.
-**
-** This function is only called in non-compressed database mode.
-*/
-static int fsIsLast(FileSystem *pFS, LsmPgno iPg){
- const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
- assert( !pFS->pCompress );
- return ( iPg && (iPg % nPagePerBlock)==0 );
-}
-
-/*
-** Return true if page iPg is the first page on its block.
-**
-** This function is only called in non-compressed database mode.
-*/
-static int fsIsFirst(FileSystem *pFS, LsmPgno iPg){
- const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
- assert( !pFS->pCompress );
- return ( (iPg % nPagePerBlock)==1
- || (iPg<nPagePerBlock && iPg==fsFirstPageOnBlock(pFS, 1))
- );
-}
-
-/*
-** Given a page reference, return a pointer to the buffer containing the
-** pages contents. If parameter pnData is not NULL, set *pnData to the size
-** of the buffer in bytes before returning.
-*/
-u8 *lsmFsPageData(Page *pPage, int *pnData){
- if( pnData ){
- *pnData = pPage->nData;
- }
- return pPage->aData;
-}
-
-/*
-** Return the page number of a page.
-*/
-LsmPgno lsmFsPageNumber(Page *pPage){
- /* assert( (pPage->flags & PAGE_DIRTY)==0 ); */
- return pPage ? pPage->iPg : 0;
-}
-
-/*
-** Page pPg is currently part of the LRU list belonging to pFS. Remove
-** it from the list. pPg->pLruNext and pPg->pLruPrev are cleared by this
-** operation.
-*/
-static void fsPageRemoveFromLru(FileSystem *pFS, Page *pPg){
- assert( pPg->pLruNext || pPg==pFS->pLruLast );
- assert( pPg->pLruPrev || pPg==pFS->pLruFirst );
- if( pPg->pLruNext ){
- pPg->pLruNext->pLruPrev = pPg->pLruPrev;
- }else{
- pFS->pLruLast = pPg->pLruPrev;
- }
- if( pPg->pLruPrev ){
- pPg->pLruPrev->pLruNext = pPg->pLruNext;
- }else{
- pFS->pLruFirst = pPg->pLruNext;
- }
- pPg->pLruPrev = 0;
- pPg->pLruNext = 0;
-}
-
-/*
-** Page pPg is not currently part of the LRU list belonging to pFS. Add it.
-*/
-static void fsPageAddToLru(FileSystem *pFS, Page *pPg){
- assert( pPg->pLruNext==0 && pPg->pLruPrev==0 );
- pPg->pLruPrev = pFS->pLruLast;
- if( pPg->pLruPrev ){
- pPg->pLruPrev->pLruNext = pPg;
- }else{
- pFS->pLruFirst = pPg;
- }
- pFS->pLruLast = pPg;
-}
-
-/*
-** Page pPg is currently stored in the apHash/nHash hash table. Remove it.
-*/
-static void fsPageRemoveFromHash(FileSystem *pFS, Page *pPg){
- int iHash;
- Page **pp;
-
- iHash = fsHashKey(pFS->nHash, pPg->iPg);
- for(pp=&pFS->apHash[iHash]; *pp!=pPg; pp=&(*pp)->pHashNext);
- *pp = pPg->pHashNext;
- pPg->pHashNext = 0;
-}
-
-/*
-** Free a Page object allocated by fsPageBuffer().
-*/
-static void fsPageBufferFree(Page *pPg){
- pPg->pFS->nCacheAlloc--;
- lsmFree(pPg->pFS->pEnv, pPg->aData);
- lsmFree(pPg->pFS->pEnv, pPg);
-}
-
-
-/*
-** Purge the cache of all non-mmap pages with nRef==0.
-*/
-void lsmFsPurgeCache(FileSystem *pFS){
- Page *pPg;
-
- pPg = pFS->pLruFirst;
- while( pPg ){
- Page *pNext = pPg->pLruNext;
- assert( pPg->flags & PAGE_FREE );
- fsPageRemoveFromHash(pFS, pPg);
- fsPageBufferFree(pPg);
- pPg = pNext;
- }
- pFS->pLruFirst = 0;
- pFS->pLruLast = 0;
-
- assert( pFS->nCacheAlloc<=pFS->nOut && pFS->nCacheAlloc>=0 );
-}
-
-/*
-** Search the hash-table for page iPg. If an entry is round, return a pointer
-** to it. Otherwise, return NULL.
-**
-** Either way, if argument piHash is not NULL set *piHash to the hash slot
-** number that page iPg would be stored in before returning.
-*/
-static Page *fsPageFindInHash(FileSystem *pFS, LsmPgno iPg, int *piHash){
- Page *p; /* Return value */
- int iHash = fsHashKey(pFS->nHash, iPg);
-
- if( piHash ) *piHash = iHash;
- for(p=pFS->apHash[iHash]; p; p=p->pHashNext){
- if( p->iPg==iPg) break;
- }
- return p;
-}
-
-/*
-** Allocate and return a non-mmap Page object. If there are already
-** nCacheMax such Page objects outstanding, try to recycle an existing
-** Page instead.
-*/
-static int fsPageBuffer(
- FileSystem *pFS,
- Page **ppOut
-){
- int rc = LSM_OK;
- Page *pPage = 0;
- if( pFS->pLruFirst==0 || pFS->nCacheAlloc<pFS->nCacheMax ){
- /* Allocate a new Page object */
- pPage = lsmMallocZero(pFS->pEnv, sizeof(Page));
- if( !pPage ){
- rc = LSM_NOMEM_BKPT;
- }else{
- pPage->aData = (u8 *)lsmMalloc(pFS->pEnv, pFS->nPagesize);
- if( !pPage->aData ){
- lsmFree(pFS->pEnv, pPage);
- rc = LSM_NOMEM_BKPT;
- pPage = 0;
- }else{
- pFS->nCacheAlloc++;
- }
- }
- }else{
- /* Reuse an existing Page object */
- u8 *aData;
- pPage = pFS->pLruFirst;
- aData = pPage->aData;
- fsPageRemoveFromLru(pFS, pPage);
- fsPageRemoveFromHash(pFS, pPage);
-
- memset(pPage, 0, sizeof(Page));
- pPage->aData = aData;
- }
-
- if( pPage ){
- pPage->flags = PAGE_FREE;
- }
- *ppOut = pPage;
- return rc;
-}
-
-/*
-** Assuming *pRc is initially LSM_OK, attempt to ensure that the
-** memory-mapped region is at least iSz bytes in size. If it is not already,
-** iSz bytes in size, extend it and update the pointers associated with any
-** outstanding Page objects.
-**
-** If *pRc is not LSM_OK when this function is called, it is a no-op.
-** Otherwise, *pRc is set to an lsm error code if an error occurs, or
-** left unmodified otherwise.
-**
-** This function is never called in compressed database mode.
-*/
-static void fsGrowMapping(
- FileSystem *pFS, /* File system object */
- i64 iSz, /* Minimum size to extend mapping to */
- int *pRc /* IN/OUT: Error code */
-){
- assert( pFS->pCompress==0 );
- assert( PAGE_HASPREV==4 );
-
- if( *pRc==LSM_OK && iSz>pFS->nMap ){
- int rc;
- u8 *aOld = pFS->pMap;
- rc = lsmEnvRemap(pFS->pEnv, pFS->fdDb, iSz, &pFS->pMap, &pFS->nMap);
- if( rc==LSM_OK && pFS->pMap!=aOld ){
- Page *pFix;
- i64 iOff = (u8 *)pFS->pMap - aOld;
- for(pFix=pFS->pMapped; pFix; pFix=pFix->pMappedNext){
- pFix->aData += iOff;
- }
- lsmSortedRemap(pFS->pDb);
- }
- *pRc = rc;
- }
-}
-
-/*
-** If it is mapped, unmap the database file.
-*/
-int lsmFsUnmap(FileSystem *pFS){
- int rc = LSM_OK;
- if( pFS ){
- rc = lsmEnvRemap(pFS->pEnv, pFS->fdDb, -1, &pFS->pMap, &pFS->nMap);
- }
- return rc;
-}
-
-/*
-** fsync() the database file.
-*/
-int lsmFsSyncDb(FileSystem *pFS, int nBlock){
- return lsmEnvSync(pFS->pEnv, pFS->fdDb);
-}
-
-/*
-** If block iBlk has been redirected according to the redirections in the
-** object passed as the first argument, return the destination block to
-** which it is redirected. Otherwise, return a copy of iBlk.
-*/
-static int fsRedirectBlock(Redirect *p, int iBlk){
- if( p ){
- int i;
- for(i=0; i<p->n; i++){
- if( iBlk==p->a[i].iFrom ) return p->a[i].iTo;
- }
- }
- assert( iBlk!=0 );
- return iBlk;
-}
-
-/*
-** If page iPg has been redirected according to the redirections in the
-** object passed as the second argument, return the destination page to
-** which it is redirected. Otherwise, return a copy of iPg.
-*/
-LsmPgno lsmFsRedirectPage(FileSystem *pFS, Redirect *pRedir, LsmPgno iPg){
- LsmPgno iReal = iPg;
-
- if( pRedir ){
- const int nPagePerBlock = (
- pFS->pCompress ? pFS->nBlocksize : (pFS->nBlocksize / pFS->nPagesize)
- );
- int iBlk = fsPageToBlock(pFS, iPg);
- int i;
- for(i=0; i<pRedir->n; i++){
- int iFrom = pRedir->a[i].iFrom;
- if( iFrom>iBlk ) break;
- if( iFrom==iBlk ){
- int iTo = pRedir->a[i].iTo;
- iReal = iPg - (LsmPgno)(iFrom - iTo) * nPagePerBlock;
- if( iTo==1 ){
- iReal += (fsFirstPageOnBlock(pFS, 1)-1);
- }
- break;
- }
- }
- }
-
- assert( iReal!=0 );
- return iReal;
-}
-
-/* Required by the circular fsBlockNext<->fsPageGet dependency. */
-static int fsPageGet(FileSystem *, Segment *, LsmPgno, int, Page **, int *);
-
-/*
-** Parameter iBlock is a database file block. This function reads the value
-** stored in the blocks "next block" pointer and stores it in *piNext.
-** LSM_OK is returned if everything is successful, or an LSM error code
-** otherwise.
-*/
-static int fsBlockNext(
- FileSystem *pFS, /* File-system object handle */
- Segment *pSeg, /* Use this segment for block redirects */
- int iBlock, /* Read field from this block */
- int *piNext /* OUT: Next block in linked list */
-){
- int rc;
- int iRead; /* Read block from here */
-
- if( pSeg ){
- iRead = fsRedirectBlock(pSeg->pRedirect, iBlock);
- }else{
- iRead = iBlock;
- }
-
- assert( pFS->nMapLimit==0 || pFS->pCompress==0 );
- if( pFS->pCompress ){
- i64 iOff; /* File offset to read data from */
- u8 aNext[4]; /* 4-byte pointer read from db file */
-
- iOff = (i64)iRead * pFS->nBlocksize - sizeof(aNext);
- rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aNext, sizeof(aNext));
- if( rc==LSM_OK ){
- *piNext = (int)lsmGetU32(aNext);
- }
- }else{
- const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
- Page *pLast;
- rc = fsPageGet(pFS, 0, iRead*nPagePerBlock, 0, &pLast, 0);
- if( rc==LSM_OK ){
- *piNext = lsmGetU32(&pLast->aData[pFS->nPagesize-4]);
- lsmFsPageRelease(pLast);
- }
- }
-
- if( pSeg ){
- *piNext = fsRedirectBlock(pSeg->pRedirect, *piNext);
- }
- return rc;
-}
-
-/*
-** Return the page number of the last page on the same block as page iPg.
-*/
-LsmPgno fsLastPageOnPagesBlock(FileSystem *pFS, LsmPgno iPg){
- return fsLastPageOnBlock(pFS, fsPageToBlock(pFS, iPg));
-}
-
-/*
-** Read nData bytes of data from offset iOff of the database file into
-** buffer aData. If this means reading past the end of a block, follow
-** the block pointer to the next block and continue reading.
-**
-** Offset iOff is an absolute offset - not subject to any block redirection.
-** However any block pointer followed is. Use pSeg->pRedirect in this case.
-**
-** This function is only called in compressed database mode.
-*/
-static int fsReadData(
- FileSystem *pFS, /* File-system handle */
- Segment *pSeg, /* Block redirection */
- i64 iOff, /* Read data from this offset */
- u8 *aData, /* Buffer to read data into */
- int nData /* Number of bytes to read */
-){
- i64 iEob; /* End of block */
- int nRead;
- int rc;
-
- assert( pFS->pCompress );
-
- iEob = fsLastPageOnPagesBlock(pFS, iOff) + 1;
- nRead = (int)LSM_MIN(iEob - iOff, nData);
-
- rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aData, nRead);
- if( rc==LSM_OK && nRead!=nData ){
- int iBlk;
-
- rc = fsBlockNext(pFS, pSeg, fsPageToBlock(pFS, iOff), &iBlk);
- if( rc==LSM_OK ){
- i64 iOff2 = fsFirstPageOnBlock(pFS, iBlk);
- rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff2, &aData[nRead], nData-nRead);
- }
- }
-
- return rc;
-}
-
-/*
-** Parameter iBlock is a database file block. This function reads the value
-** stored in the blocks "previous block" pointer and stores it in *piPrev.
-** LSM_OK is returned if everything is successful, or an LSM error code
-** otherwise.
-*/
-static int fsBlockPrev(
- FileSystem *pFS, /* File-system object handle */
- Segment *pSeg, /* Use this segment for block redirects */
- int iBlock, /* Read field from this block */
- int *piPrev /* OUT: Previous block in linked list */
-){
- int rc = LSM_OK; /* Return code */
-
- assert( pFS->nMapLimit==0 || pFS->pCompress==0 );
- assert( iBlock>0 );
-
- if( pFS->pCompress ){
- i64 iOff = fsFirstPageOnBlock(pFS, iBlock) - 4;
- u8 aPrev[4]; /* 4-byte pointer read from db file */
- rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aPrev, sizeof(aPrev));
- if( rc==LSM_OK ){
- Redirect *pRedir = (pSeg ? pSeg->pRedirect : 0);
- *piPrev = fsRedirectBlock(pRedir, (int)lsmGetU32(aPrev));
- }
- }else{
- assert( 0 );
- }
- return rc;
-}
-
-/*
-** Encode and decode routines for record size fields.
-*/
-static void putRecordSize(u8 *aBuf, int nByte, int bFree){
- aBuf[0] = (u8)(nByte >> 14) | 0x80;
- aBuf[1] = ((u8)(nByte >> 7) & 0x7F) | (bFree ? 0x00 : 0x80);
- aBuf[2] = (u8)nByte | 0x80;
-}
-static int getRecordSize(u8 *aBuf, int *pbFree){
- int nByte;
- nByte = (aBuf[0] & 0x7F) << 14;
- nByte += (aBuf[1] & 0x7F) << 7;
- nByte += (aBuf[2] & 0x7F);
- *pbFree = !(aBuf[1] & 0x80);
- return nByte;
-}
-
-/*
-** Subtract iSub from database file offset iOff and set *piRes to the
-** result. If doing so means passing the start of a block, follow the
-** block pointer stored in the first 4 bytes of the block.
-**
-** Offset iOff is an absolute offset - not subject to any block redirection.
-** However any block pointer followed is. Use pSeg->pRedirect in this case.
-**
-** Return LSM_OK if successful or an lsm error code if an error occurs.
-*/
-static int fsSubtractOffset(
- FileSystem *pFS,
- Segment *pSeg,
- i64 iOff,
- int iSub,
- i64 *piRes
-){
- i64 iStart;
- int iBlk = 0;
- int rc;
-
- assert( pFS->pCompress );
-
- iStart = fsFirstPageOnBlock(pFS, fsPageToBlock(pFS, iOff));
- if( (iOff-iSub)>=iStart ){
- *piRes = (iOff-iSub);
- return LSM_OK;
- }
-
- rc = fsBlockPrev(pFS, pSeg, fsPageToBlock(pFS, iOff), &iBlk);
- *piRes = fsLastPageOnBlock(pFS, iBlk) - iSub + (iOff - iStart + 1);
- return rc;
-}
-
-/*
-** Add iAdd to database file offset iOff and set *piRes to the
-** result. If doing so means passing the end of a block, follow the
-** block pointer stored in the last 4 bytes of the block.
-**
-** Offset iOff is an absolute offset - not subject to any block redirection.
-** However any block pointer followed is. Use pSeg->pRedirect in this case.
-**
-** Return LSM_OK if successful or an lsm error code if an error occurs.
-*/
-static int fsAddOffset(
- FileSystem *pFS,
- Segment *pSeg,
- i64 iOff,
- int iAdd,
- i64 *piRes
-){
- i64 iEob;
- int iBlk;
- int rc;
-
- assert( pFS->pCompress );
-
- iEob = fsLastPageOnPagesBlock(pFS, iOff);
- if( (iOff+iAdd)<=iEob ){
- *piRes = (iOff+iAdd);
- return LSM_OK;
- }
-
- rc = fsBlockNext(pFS, pSeg, fsPageToBlock(pFS, iOff), &iBlk);
- *piRes = fsFirstPageOnBlock(pFS, iBlk) + iAdd - (iEob - iOff + 1);
- return rc;
-}
-
-/*
-** If it is not already allocated, allocate either the FileSystem.aOBuffer (if
-** bWrite is true) or the FileSystem.aIBuffer (if bWrite is false). Return
-** LSM_OK if successful if the attempt to allocate memory fails.
-*/
-static int fsAllocateBuffer(FileSystem *pFS, int bWrite){
- u8 **pp; /* Pointer to either aIBuffer or aOBuffer */
-
- assert( pFS->pCompress );
-
- /* If neither buffer has been allocated, figure out how large they
- ** should be. Store this value in FileSystem.nBuffer. */
- if( pFS->nBuffer==0 ){
- assert( pFS->aIBuffer==0 && pFS->aOBuffer==0 );
- pFS->nBuffer = pFS->pCompress->xBound(pFS->pCompress->pCtx, pFS->nPagesize);
- if( pFS->nBuffer<(pFS->szSector+6) ){
- pFS->nBuffer = pFS->szSector+6;
- }
- }
-
- pp = (bWrite ? &pFS->aOBuffer : &pFS->aIBuffer);
- if( *pp==0 ){
- *pp = lsmMalloc(pFS->pEnv, LSM_MAX(pFS->nBuffer, pFS->nPagesize));
- if( *pp==0 ) return LSM_NOMEM_BKPT;
- }
-
- return LSM_OK;
-}
-
-/*
-** This function is only called in compressed database mode. It reads and
-** uncompresses the compressed data for page pPg from the database and
-** populates the pPg->aData[] buffer and pPg->nCompress field.
-**
-** It is possible that instead of a page record, there is free space
-** at offset pPg->iPgno. In this case no data is read from the file, but
-** output variable *pnSpace is set to the total number of free bytes.
-**
-** LSM_OK is returned if successful, or an LSM error code otherwise.
-*/
-static int fsReadPagedata(
- FileSystem *pFS, /* File-system handle */
- Segment *pSeg, /* pPg is part of this segment */
- Page *pPg, /* Page to read and uncompress data for */
- int *pnSpace /* OUT: Total bytes of free space */
-){
- lsm_compress *p = pFS->pCompress;
- i64 iOff = pPg->iPg;
- u8 aSz[3];
- int rc;
-
- assert( p && pPg->nCompress==0 );
-
- if( fsAllocateBuffer(pFS, 0) ) return LSM_NOMEM;
-
- rc = fsReadData(pFS, pSeg, iOff, aSz, sizeof(aSz));
-
- if( rc==LSM_OK ){
- int bFree;
- if( aSz[0] & 0x80 ){
- pPg->nCompress = (int)getRecordSize(aSz, &bFree);
- }else{
- pPg->nCompress = (int)aSz[0] - sizeof(aSz)*2;
- bFree = 1;
- }
- if( bFree ){
- if( pnSpace ){
- *pnSpace = pPg->nCompress + sizeof(aSz)*2;
- }else{
- rc = LSM_CORRUPT_BKPT;
- }
- }else{
- rc = fsAddOffset(pFS, pSeg, iOff, 3, &iOff);
- if( rc==LSM_OK ){
- if( pPg->nCompress>pFS->nBuffer ){
- rc = LSM_CORRUPT_BKPT;
- }else{
- rc = fsReadData(pFS, pSeg, iOff, pFS->aIBuffer, pPg->nCompress);
- }
- if( rc==LSM_OK ){
- int n = pFS->nPagesize;
- rc = p->xUncompress(p->pCtx,
- (char *)pPg->aData, &n,
- (const char *)pFS->aIBuffer, pPg->nCompress
- );
- if( rc==LSM_OK && n!=pPg->pFS->nPagesize ){
- rc = LSM_CORRUPT_BKPT;
- }
- }
- }
- }
- }
- return rc;
-}
-
-/*
-** Return a handle for a database page.
-**
-** If this file-system object is accessing a compressed database it may be
-** that there is no page record at database file offset iPg. Instead, there
-** may be a free space record. In this case, set *ppPg to NULL and *pnSpace
-** to the total number of free bytes before returning.
-**
-** If no error occurs, LSM_OK is returned. Otherwise, an lsm error code.
-*/
-static int fsPageGet(
- FileSystem *pFS, /* File-system handle */
- Segment *pSeg, /* Block redirection to use (or NULL) */
- LsmPgno iPg, /* Page id */
- int noContent, /* True to not load content from disk */
- Page **ppPg, /* OUT: New page handle */
- int *pnSpace /* OUT: Bytes of free space */
-){
- Page *p;
- int iHash;
- int rc = LSM_OK;
-
- /* In most cases iReal is the same as iPg. Except, if pSeg->pRedirect is
- ** not NULL, and the block containing iPg has been redirected, then iReal
- ** is the page number after redirection. */
- LsmPgno iReal = lsmFsRedirectPage(pFS, (pSeg ? pSeg->pRedirect : 0), iPg);
-
- assert_lists_are_ok(pFS);
- assert( iPg>=fsFirstPageOnBlock(pFS, 1) );
- assert( iReal>=fsFirstPageOnBlock(pFS, 1) );
- *ppPg = 0;
-
- /* Search the hash-table for the page */
- p = fsPageFindInHash(pFS, iReal, &iHash);
-
- if( p ){
- assert( p->flags & PAGE_FREE );
- if( p->nRef==0 ) fsPageRemoveFromLru(pFS, p);
- }else{
-
- if( fsMmapPage(pFS, iReal) ){
- i64 iEnd = (i64)iReal * pFS->nPagesize;
- fsGrowMapping(pFS, iEnd, &rc);
- if( rc!=LSM_OK ) return rc;
-
- if( pFS->pFree ){
- p = pFS->pFree;
- pFS->pFree = p->pFreeNext;
- assert( p->nRef==0 );
- }else{
- p = lsmMallocZeroRc(pFS->pEnv, sizeof(Page), &rc);
- if( rc ) return rc;
- p->pFS = pFS;
- }
- p->aData = &((u8 *)pFS->pMap)[pFS->nPagesize * (iReal-1)];
- p->iPg = iReal;
-
- /* This page now carries a pointer to the mapping. Link it in to
- ** the FileSystem.pMapped list. */
- assert( p->pMappedNext==0 );
- p->pMappedNext = pFS->pMapped;
- pFS->pMapped = p;
-
- assert( pFS->pCompress==0 );
- assert( (p->flags & PAGE_FREE)==0 );
- }else{
- rc = fsPageBuffer(pFS, &p);
- if( rc==LSM_OK ){
- int nSpace = 0;
- p->iPg = iReal;
- p->nRef = 0;
- p->pFS = pFS;
- assert( p->flags==0 || p->flags==PAGE_FREE );
-
-#ifdef LSM_DEBUG
- memset(p->aData, 0x56, pFS->nPagesize);
-#endif
- assert( p->pLruNext==0 && p->pLruPrev==0 );
- if( noContent==0 ){
- if( pFS->pCompress ){
- rc = fsReadPagedata(pFS, pSeg, p, &nSpace);
- }else{
- int nByte = pFS->nPagesize;
- i64 iOff = (i64)(iReal-1) * pFS->nPagesize;
- rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, p->aData, nByte);
- }
- pFS->nRead++;
- }
-
- /* If the xRead() call was successful (or not attempted), link the
- ** page into the page-cache hash-table. Otherwise, if it failed,
- ** free the buffer. */
- if( rc==LSM_OK && nSpace==0 ){
- p->pHashNext = pFS->apHash[iHash];
- pFS->apHash[iHash] = p;
- }else{
- fsPageBufferFree(p);
- p = 0;
- if( pnSpace ) *pnSpace = nSpace;
- }
- }
- }
-
- assert( (rc==LSM_OK && (p || (pnSpace && *pnSpace)))
- || (rc!=LSM_OK && p==0)
- );
- }
-
- if( rc==LSM_OK && p ){
- if( pFS->pCompress==0 && (fsIsLast(pFS, iReal) || fsIsFirst(pFS, iReal)) ){
- p->nData = pFS->nPagesize - 4;
- if( fsIsFirst(pFS, iReal) && p->nRef==0 ){
- p->aData += 4;
- p->flags |= PAGE_HASPREV;
- }
- }else{
- p->nData = pFS->nPagesize;
- }
- pFS->nOut += (p->nRef==0);
- p->nRef++;
- }
- *ppPg = p;
- return rc;
-}
-
-/*
-** Read the 64-bit checkpoint id of the checkpoint currently stored on meta
-** page iMeta of the database file. If no error occurs, store the id value
-** in *piVal and return LSM_OK. Otherwise, return an LSM error code and leave
-** *piVal unmodified.
-**
-** If a checkpointer connection is currently updating meta-page iMeta, or an
-** earlier checkpointer crashed while doing so, the value read into *piVal
-** may be garbage. It is the callers responsibility to deal with this.
-*/
-int lsmFsReadSyncedId(lsm_db *db, int iMeta, i64 *piVal){
- FileSystem *pFS = db->pFS;
- int rc = LSM_OK;
-
- assert( iMeta==1 || iMeta==2 );
- if( pFS->nMapLimit>0 ){
- fsGrowMapping(pFS, iMeta*LSM_META_PAGE_SIZE, &rc);
- if( rc==LSM_OK ){
- *piVal = (i64)lsmGetU64(&((u8 *)pFS->pMap)[(iMeta-1)*LSM_META_PAGE_SIZE]);
- }
- }else{
- MetaPage *pMeta = 0;
- rc = lsmFsMetaPageGet(pFS, 0, iMeta, &pMeta);
- if( rc==LSM_OK ){
- *piVal = (i64)lsmGetU64(pMeta->aData);
- lsmFsMetaPageRelease(pMeta);
- }
- }
-
- return rc;
-}
-
-
-/*
-** Return true if the first or last page of segment pRun falls between iFirst
-** and iLast, inclusive, and pRun is not equal to pIgnore.
-*/
-static int fsRunEndsBetween(
- Segment *pRun,
- Segment *pIgnore,
- LsmPgno iFirst,
- LsmPgno iLast
-){
- return (pRun!=pIgnore && (
- (pRun->iFirst>=iFirst && pRun->iFirst<=iLast)
- || (pRun->iLastPg>=iFirst && pRun->iLastPg<=iLast)
- ));
-}
-
-/*
-** Return true if level pLevel contains a segment other than pIgnore for
-** which the first or last page is between iFirst and iLast, inclusive.
-*/
-static int fsLevelEndsBetween(
- Level *pLevel,
- Segment *pIgnore,
- LsmPgno iFirst,
- LsmPgno iLast
-){
- int i;
-
- if( fsRunEndsBetween(&pLevel->lhs, pIgnore, iFirst, iLast) ){
- return 1;
- }
- for(i=0; i<pLevel->nRight; i++){
- if( fsRunEndsBetween(&pLevel->aRhs[i], pIgnore, iFirst, iLast) ){
- return 1;
- }
- }
-
- return 0;
-}
-
-/*
-** Block iBlk is no longer in use by segment pIgnore. If it is not in use
-** by any other segment, move it to the free block list.
-*/
-static int fsFreeBlock(
- FileSystem *pFS, /* File system object */
- Snapshot *pSnapshot, /* Worker snapshot */
- Segment *pIgnore, /* Ignore this run when searching */
- int iBlk /* Block number of block to free */
-){
- int rc = LSM_OK; /* Return code */
- LsmPgno iFirst; /* First page on block iBlk */
- LsmPgno iLast; /* Last page on block iBlk */
- Level *pLevel; /* Used to iterate through levels */
-
- int iIn; /* Used to iterate through append points */
- int iOut = 0; /* Used to output append points */
- LsmPgno *aApp = pSnapshot->aiAppend;
-
- iFirst = fsFirstPageOnBlock(pFS, iBlk);
- iLast = fsLastPageOnBlock(pFS, iBlk);
-
- /* Check if any other run in the snapshot has a start or end page
- ** within this block. If there is such a run, return early. */
- for(pLevel=lsmDbSnapshotLevel(pSnapshot); pLevel; pLevel=pLevel->pNext){
- if( fsLevelEndsBetween(pLevel, pIgnore, iFirst, iLast) ){
- return LSM_OK;
- }
- }
-
- /* Remove any entries that lie on this block from the append-list. */
- for(iIn=0; iIn<LSM_APPLIST_SZ; iIn++){
- if( aApp[iIn]<iFirst || aApp[iIn]>iLast ){
- aApp[iOut++] = aApp[iIn];
- }
- }
- while( iOut<LSM_APPLIST_SZ ) aApp[iOut++] = 0;
-
- if( rc==LSM_OK ){
- rc = lsmBlockFree(pFS->pDb, iBlk);
- }
- return rc;
-}
-
-/*
-** Delete or otherwise recycle the blocks currently occupied by run pDel.
-*/
-int lsmFsSortedDelete(
- FileSystem *pFS,
- Snapshot *pSnapshot,
- int bZero, /* True to zero the Segment structure */
- Segment *pDel
-){
- if( pDel->iFirst ){
- int rc = LSM_OK;
-
- int iBlk;
- int iLastBlk;
-
- iBlk = fsPageToBlock(pFS, pDel->iFirst);
- iLastBlk = fsPageToBlock(pFS, pDel->iLastPg);
-
- /* Mark all blocks currently used by this sorted run as free */
- while( iBlk && rc==LSM_OK ){
- int iNext = 0;
- if( iBlk!=iLastBlk ){
- rc = fsBlockNext(pFS, pDel, iBlk, &iNext);
- }else if( bZero==0 && pDel->iLastPg!=fsLastPageOnBlock(pFS, iLastBlk) ){
- break;
- }
- rc = fsFreeBlock(pFS, pSnapshot, pDel, iBlk);
- iBlk = iNext;
- }
-
- if( pDel->pRedirect ){
- assert( pDel->pRedirect==&pSnapshot->redirect );
- pSnapshot->redirect.n = 0;
- }
-
- if( bZero ) memset(pDel, 0, sizeof(Segment));
- }
- return LSM_OK;
-}
-
-/*
-** aPgno is an array containing nPgno page numbers. Return the smallest page
-** number from the array that falls on block iBlk. Or, if none of the pages
-** in aPgno[] fall on block iBlk, return 0.
-*/
-static LsmPgno firstOnBlock(
- FileSystem *pFS,
- int iBlk,
- LsmPgno *aPgno,
- int nPgno
-){
- LsmPgno iRet = 0;
- int i;
- for(i=0; i<nPgno; i++){
- LsmPgno iPg = aPgno[i];
- if( fsPageToBlock(pFS, iPg)==iBlk && (iRet==0 || iPg<iRet) ){
- iRet = iPg;
- }
- }
- return iRet;
-}
-
-#ifndef NDEBUG
-/*
-** Return true if page iPg, which is a part of segment p, lies on
-** a redirected block.
-*/
-static int fsPageRedirects(FileSystem *pFS, Segment *p, LsmPgno iPg){
- return (iPg!=0 && iPg!=lsmFsRedirectPage(pFS, p->pRedirect, iPg));
-}
-
-/*
-** Return true if the second argument is not NULL and any of the first
-** last or root pages lie on a redirected block.
-*/
-static int fsSegmentRedirects(FileSystem *pFS, Segment *p){
- return (p && (
- fsPageRedirects(pFS, p, p->iFirst)
- || fsPageRedirects(pFS, p, p->iRoot)
- || fsPageRedirects(pFS, p, p->iLastPg)
- ));
-}
-#endif
-
-/*
-** Argument aPgno is an array of nPgno page numbers. All pages belong to
-** the segment pRun. This function gobbles from the start of the run to the
-** first page that appears in aPgno[] (i.e. so that the aPgno[] entry is
-** the new first page of the run).
-*/
-void lsmFsGobble(
- lsm_db *pDb,
- Segment *pRun,
- LsmPgno *aPgno,
- int nPgno
-){
- int rc = LSM_OK;
- FileSystem *pFS = pDb->pFS;
- Snapshot *pSnapshot = pDb->pWorker;
- int iBlk;
-
- assert( pRun->nSize>0 );
- assert( 0==fsSegmentRedirects(pFS, pRun) );
- assert( nPgno>0 && 0==fsPageRedirects(pFS, pRun, aPgno[0]) );
-
- iBlk = fsPageToBlock(pFS, pRun->iFirst);
- pRun->nSize += (int)(pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
-
- while( rc==LSM_OK ){
- int iNext = 0;
- LsmPgno iFirst = firstOnBlock(pFS, iBlk, aPgno, nPgno);
- if( iFirst ){
- pRun->iFirst = iFirst;
- break;
- }
- rc = fsBlockNext(pFS, pRun, iBlk, &iNext);
- if( rc==LSM_OK ) rc = fsFreeBlock(pFS, pSnapshot, pRun, iBlk);
- pRun->nSize -= (int)(
- 1 + fsLastPageOnBlock(pFS, iBlk) - fsFirstPageOnBlock(pFS, iBlk)
- );
- iBlk = iNext;
- }
-
- pRun->nSize -= (int)(pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
- assert( pRun->nSize>0 );
-}
-
-/*
-** This function is only used in compressed database mode.
-**
-** Argument iPg is the page number (byte offset) of a page within segment
-** pSeg. The page record, including all headers, is nByte bytes in size.
-** Before returning, set *piNext to the page number of the next page in
-** the segment, or to zero if iPg is the last.
-**
-** In other words, do:
-**
-** *piNext = iPg + nByte;
-**
-** But take block overflow and redirection into account.
-*/
-static int fsNextPageOffset(
- FileSystem *pFS, /* File system object */
- Segment *pSeg, /* Segment to move within */
- LsmPgno iPg, /* Offset of current page */
- int nByte, /* Size of current page including headers */
- LsmPgno *piNext /* OUT: Offset of next page. Or zero (EOF) */
-){
- LsmPgno iNext;
- int rc;
-
- assert( pFS->pCompress );
-
- rc = fsAddOffset(pFS, pSeg, iPg, nByte-1, &iNext);
- if( pSeg && iNext==pSeg->iLastPg ){
- iNext = 0;
- }else if( rc==LSM_OK ){
- rc = fsAddOffset(pFS, pSeg, iNext, 1, &iNext);
- }
-
- *piNext = iNext;
- return rc;
-}
-
-/*
-** This function is only used in compressed database mode.
-**
-** Argument iPg is the page number of a pagethat appears in segment pSeg.
-** This function determines the page number of the previous page in the
-** same run. *piPrev is set to the previous page number before returning.
-**
-** LSM_OK is returned if no error occurs. Otherwise, an lsm error code.
-** If any value other than LSM_OK is returned, then the final value of
-** *piPrev is undefined.
-*/
-static int fsGetPageBefore(
- FileSystem *pFS,
- Segment *pSeg,
- LsmPgno iPg,
- LsmPgno *piPrev
-){
- u8 aSz[3];
- int rc;
- i64 iRead;
-
- assert( pFS->pCompress );
-
- rc = fsSubtractOffset(pFS, pSeg, iPg, sizeof(aSz), &iRead);
- if( rc==LSM_OK ) rc = fsReadData(pFS, pSeg, iRead, aSz, sizeof(aSz));
-
- if( rc==LSM_OK ){
- int bFree;
- int nSz;
- if( aSz[2] & 0x80 ){
- nSz = getRecordSize(aSz, &bFree) + sizeof(aSz)*2;
- }else{
- nSz = (int)(aSz[2] & 0x7F);
- bFree = 1;
- }
- rc = fsSubtractOffset(pFS, pSeg, iPg, nSz, piPrev);
- }
-
- return rc;
-}
-
-/*
-** The first argument to this function is a valid reference to a database
-** file page that is part of a sorted run. If parameter eDir is -1, this
-** function attempts to locate and load the previous page in the same run.
-** Or, if eDir is +1, it attempts to find the next page in the same run.
-** The results of passing an eDir value other than positive or negative one
-** are undefined.
-**
-** If parameter pRun is not NULL then it must point to the run that page
-** pPg belongs to. In this case, if pPg is the first or last page of the
-** run, and the request is for the previous or next page, respectively,
-** *ppNext is set to NULL before returning LSM_OK. If pRun is NULL, then it
-** is assumed that the next or previous page, as requested, exists.
-**
-** If the previous/next page does exist and is successfully loaded, *ppNext
-** is set to point to it and LSM_OK is returned. Otherwise, if an error
-** occurs, *ppNext is set to NULL and and lsm error code returned.
-**
-** Page references returned by this function should be released by the
-** caller using lsmFsPageRelease().
-*/
-int lsmFsDbPageNext(Segment *pRun, Page *pPg, int eDir, Page **ppNext){
- int rc = LSM_OK;
- FileSystem *pFS = pPg->pFS;
- LsmPgno iPg = pPg->iPg;
-
- assert( 0==fsSegmentRedirects(pFS, pRun) );
- if( pFS->pCompress ){
- int nSpace = pPg->nCompress + 2*3;
-
- do {
- if( eDir>0 ){
- rc = fsNextPageOffset(pFS, pRun, iPg, nSpace, &iPg);
- }else{
- if( iPg==pRun->iFirst ){
- iPg = 0;
- }else{
- rc = fsGetPageBefore(pFS, pRun, iPg, &iPg);
- }
- }
-
- nSpace = 0;
- if( iPg!=0 ){
- rc = fsPageGet(pFS, pRun, iPg, 0, ppNext, &nSpace);
- assert( (*ppNext==0)==(rc!=LSM_OK || nSpace>0) );
- }else{
- *ppNext = 0;
- }
- }while( nSpace>0 && rc==LSM_OK );
-
- }else{
- Redirect *pRedir = pRun ? pRun->pRedirect : 0;
- assert( eDir==1 || eDir==-1 );
- if( eDir<0 ){
- if( pRun && iPg==pRun->iFirst ){
- *ppNext = 0;
- return LSM_OK;
- }else if( fsIsFirst(pFS, iPg) ){
- assert( pPg->flags & PAGE_HASPREV );
- iPg = fsLastPageOnBlock(pFS, lsmGetU32(&pPg->aData[-4]));
- }else{
- iPg--;
- }
- }else{
- if( pRun ){
- if( iPg==pRun->iLastPg ){
- *ppNext = 0;
- return LSM_OK;
- }
- }
-
- if( fsIsLast(pFS, iPg) ){
- int iBlk = fsRedirectBlock(
- pRedir, lsmGetU32(&pPg->aData[pFS->nPagesize-4])
- );
- iPg = fsFirstPageOnBlock(pFS, iBlk);
- }else{
- iPg++;
- }
- }
- rc = fsPageGet(pFS, pRun, iPg, 0, ppNext, 0);
- }
-
- return rc;
-}
-
-/*
-** This function is called when creating a new segment to determine if the
-** first part of it can be written following an existing segment on an
-** already allocated block. If it is possible, the page number of the first
-** page to use for the new segment is returned. Otherwise zero.
-**
-** If argument pLvl is not NULL, then this function will not attempt to
-** start the new segment immediately following any segment that is part
-** of the right-hand-side of pLvl.
-*/
-static LsmPgno findAppendPoint(FileSystem *pFS, Level *pLvl){
- int i;
- LsmPgno *aiAppend = pFS->pDb->pWorker->aiAppend;
- LsmPgno iRet = 0;
-
- for(i=LSM_APPLIST_SZ-1; iRet==0 && i>=0; i--){
- if( (iRet = aiAppend[i]) ){
- if( pLvl ){
- int iBlk = fsPageToBlock(pFS, iRet);
- int j;
- for(j=0; iRet && j<pLvl->nRight; j++){
- if( fsPageToBlock(pFS, pLvl->aRhs[j].iLastPg)==iBlk ){
- iRet = 0;
- }
- }
- }
- if( iRet ) aiAppend[i] = 0;
- }
- }
- return iRet;
-}
-
-/*
-** Append a page to the left-hand-side of pLvl. Set the ref-count to 1 and
-** return a pointer to it. The page is writable until either
-** lsmFsPagePersist() is called on it or the ref-count drops to zero.
-*/
-int lsmFsSortedAppend(
- FileSystem *pFS,
- Snapshot *pSnapshot,
- Level *pLvl,
- int bDefer,
- Page **ppOut
-){
- int rc = LSM_OK;
- Page *pPg = 0;
- LsmPgno iApp = 0;
- LsmPgno iNext = 0;
- Segment *p = &pLvl->lhs;
- LsmPgno iPrev = p->iLastPg;
-
- *ppOut = 0;
- assert( p->pRedirect==0 );
-
- if( pFS->pCompress || bDefer ){
- /* In compressed database mode the page is not assigned a page number
- ** or location in the database file at this point. This will be done
- ** by the lsmFsPagePersist() call. */
- rc = fsPageBuffer(pFS, &pPg);
- if( rc==LSM_OK ){
- pPg->pFS = pFS;
- pPg->pSeg = p;
- pPg->iPg = 0;
- pPg->flags |= PAGE_DIRTY;
- pPg->nData = pFS->nPagesize;
- assert( pPg->aData );
- if( pFS->pCompress==0 ) pPg->nData -= 4;
-
- pPg->nRef = 1;
- pFS->nOut++;
- }
- }else{
- if( iPrev==0 ){
- iApp = findAppendPoint(pFS, pLvl);
- }else if( fsIsLast(pFS, iPrev) ){
- int iNext2;
- rc = fsBlockNext(pFS, 0, fsPageToBlock(pFS, iPrev), &iNext2);
- if( rc!=LSM_OK ) return rc;
- iApp = fsFirstPageOnBlock(pFS, iNext2);
- }else{
- iApp = iPrev + 1;
- }
-
- /* If this is the first page allocated, or if the page allocated is the
- ** last in the block, also allocate the next block here. */
- if( iApp==0 || fsIsLast(pFS, iApp) ){
- int iNew; /* New block number */
-
- rc = lsmBlockAllocate(pFS->pDb, 0, &iNew);
- if( rc!=LSM_OK ) return rc;
- if( iApp==0 ){
- iApp = fsFirstPageOnBlock(pFS, iNew);
- }else{
- iNext = fsFirstPageOnBlock(pFS, iNew);
- }
- }
-
- /* Grab the new page. */
- pPg = 0;
- rc = fsPageGet(pFS, 0, iApp, 1, &pPg, 0);
- assert( rc==LSM_OK || pPg==0 );
-
- /* If this is the first or last page of a block, fill in the pointer
- ** value at the end of the new page. */
- if( rc==LSM_OK ){
- p->nSize++;
- p->iLastPg = iApp;
- if( p->iFirst==0 ) p->iFirst = iApp;
- pPg->flags |= PAGE_DIRTY;
-
- if( fsIsLast(pFS, iApp) ){
- lsmPutU32(&pPg->aData[pFS->nPagesize-4], fsPageToBlock(pFS, iNext));
- }else if( fsIsFirst(pFS, iApp) ){
- lsmPutU32(&pPg->aData[-4], fsPageToBlock(pFS, iPrev));
- }
- }
- }
-
- *ppOut = pPg;
- return rc;
-}
-
-/*
-** Mark the segment passed as the second argument as finished. Once a segment
-** is marked as finished it is not possible to append any further pages to
-** it.
-**
-** Return LSM_OK if successful or an lsm error code if an error occurs.
-*/
-int lsmFsSortedFinish(FileSystem *pFS, Segment *p){
- int rc = LSM_OK;
- if( p && p->iLastPg ){
- assert( p->pRedirect==0 );
-
- /* Check if the last page of this run happens to be the last of a block.
- ** If it is, then an extra block has already been allocated for this run.
- ** Shift this extra block back to the free-block list.
- **
- ** Otherwise, add the first free page in the last block used by the run
- ** to the lAppend list.
- */
- if( fsLastPageOnPagesBlock(pFS, p->iLastPg)!=p->iLastPg ){
- int i;
- LsmPgno *aiAppend = pFS->pDb->pWorker->aiAppend;
- for(i=0; i<LSM_APPLIST_SZ; i++){
- if( aiAppend[i]==0 ){
- aiAppend[i] = p->iLastPg+1;
- break;
- }
- }
- }else if( pFS->pCompress==0 ){
- Page *pLast;
- rc = fsPageGet(pFS, 0, p->iLastPg, 0, &pLast, 0);
- if( rc==LSM_OK ){
- int iBlk = (int)lsmGetU32(&pLast->aData[pFS->nPagesize-4]);
- lsmBlockRefree(pFS->pDb, iBlk);
- lsmFsPageRelease(pLast);
- }
- }else{
- int iBlk = 0;
- rc = fsBlockNext(pFS, p, fsPageToBlock(pFS, p->iLastPg), &iBlk);
- if( rc==LSM_OK ){
- lsmBlockRefree(pFS->pDb, iBlk);
- }
- }
- }
- return rc;
-}
-
-/*
-** Obtain a reference to page number iPg.
-**
-** Return LSM_OK if successful, or an lsm error code if an error occurs.
-*/
-int lsmFsDbPageGet(FileSystem *pFS, Segment *pSeg, LsmPgno iPg, Page **ppPg){
- return fsPageGet(pFS, pSeg, iPg, 0, ppPg, 0);
-}
-
-/*
-** Obtain a reference to the last page in the segment passed as the
-** second argument.
-**
-** Return LSM_OK if successful, or an lsm error code if an error occurs.
-*/
-int lsmFsDbPageLast(FileSystem *pFS, Segment *pSeg, Page **ppPg){
- int rc;
- LsmPgno iPg = pSeg->iLastPg;
- if( pFS->pCompress ){
- int nSpace;
- iPg++;
- do {
- nSpace = 0;
- rc = fsGetPageBefore(pFS, pSeg, iPg, &iPg);
- if( rc==LSM_OK ){
- rc = fsPageGet(pFS, pSeg, iPg, 0, ppPg, &nSpace);
- }
- }while( rc==LSM_OK && nSpace>0 );
-
- }else{
- rc = fsPageGet(pFS, pSeg, iPg, 0, ppPg, 0);
- }
- return rc;
-}
-
-/*
-** Return a reference to meta-page iPg. If successful, LSM_OK is returned
-** and *ppPg populated with the new page reference. The reference should
-** be released by the caller using lsmFsPageRelease().
-**
-** Otherwise, if an error occurs, *ppPg is set to NULL and an LSM error
-** code is returned.
-*/
-int lsmFsMetaPageGet(
- FileSystem *pFS, /* File-system connection */
- int bWrite, /* True for write access, false for read */
- int iPg, /* Either 1 or 2 */
- MetaPage **ppPg /* OUT: Pointer to MetaPage object */
-){
- int rc = LSM_OK;
- MetaPage *pPg;
- assert( iPg==1 || iPg==2 );
-
- pPg = lsmMallocZeroRc(pFS->pEnv, sizeof(Page), &rc);
-
- if( pPg ){
- i64 iOff = (iPg-1) * pFS->nMetasize;
- if( pFS->nMapLimit>0 ){
- fsGrowMapping(pFS, 2*pFS->nMetasize, &rc);
- pPg->aData = (u8 *)(pFS->pMap) + iOff;
- }else{
- pPg->aData = lsmMallocRc(pFS->pEnv, pFS->nMetasize, &rc);
- if( rc==LSM_OK && bWrite==0 ){
- rc = lsmEnvRead(
- pFS->pEnv, pFS->fdDb, iOff, pPg->aData, pFS->nMetaRwSize
- );
- }
-#ifndef NDEBUG
- /* pPg->aData causes an uninitialized access via a downstreadm write().
- After discussion on this list, this memory should not, for performance
- reasons, be memset. However, tracking down "real" misuse is more
- difficult with this "false" positive, so it is set when NDEBUG.
- */
- else if( rc==LSM_OK ){
- memset( pPg->aData, 0x77, pFS->nMetasize );
- }
-#endif
- }
-
- if( rc!=LSM_OK ){
- if( pFS->nMapLimit==0 ) lsmFree(pFS->pEnv, pPg->aData);
- lsmFree(pFS->pEnv, pPg);
- pPg = 0;
- }else{
- pPg->iPg = iPg;
- pPg->bWrite = bWrite;
- pPg->pFS = pFS;
- }
- }
-
- *ppPg = pPg;
- return rc;
-}
-
-/*
-** Release a meta-page reference obtained via a call to lsmFsMetaPageGet().
-*/
-int lsmFsMetaPageRelease(MetaPage *pPg){
- int rc = LSM_OK;
- if( pPg ){
- FileSystem *pFS = pPg->pFS;
-
- if( pFS->nMapLimit==0 ){
- if( pPg->bWrite ){
- i64 iOff = (pPg->iPg==2 ? pFS->nMetasize : 0);
- int nWrite = pFS->nMetaRwSize;
- rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, pPg->aData, nWrite);
- }
- lsmFree(pFS->pEnv, pPg->aData);
- }
-
- lsmFree(pFS->pEnv, pPg);
- }
- return rc;
-}
-
-/*
-** Return a pointer to a buffer containing the data associated with the
-** meta-page passed as the first argument. If parameter pnData is not NULL,
-** set *pnData to the size of the meta-page in bytes before returning.
-*/
-u8 *lsmFsMetaPageData(MetaPage *pPg, int *pnData){
- if( pnData ) *pnData = pPg->pFS->nMetaRwSize;
- return pPg->aData;
-}
-
-/*
-** Return true if page is currently writable. This is used in assert()
-** statements only.
-*/
-#ifndef NDEBUG
-int lsmFsPageWritable(Page *pPg){
- return (pPg->flags & PAGE_DIRTY) ? 1 : 0;
-}
-#endif
-
-/*
-** This is called when block iFrom is being redirected to iTo. If page
-** number (*piPg) lies on block iFrom, then calculate the equivalent
-** page on block iTo and set *piPg to this value before returning.
-*/
-static void fsMovePage(
- FileSystem *pFS, /* File system object */
- int iTo, /* Destination block */
- int iFrom, /* Source block */
- LsmPgno *piPg /* IN/OUT: Page number */
-){
- LsmPgno iPg = *piPg;
- if( iFrom==fsPageToBlock(pFS, iPg) ){
- const int nPagePerBlock = (
- pFS->pCompress ? pFS ->nBlocksize : (pFS->nBlocksize / pFS->nPagesize)
- );
- *piPg = iPg - (LsmPgno)(iFrom - iTo) * nPagePerBlock;
- }
-}
-
-/*
-** Copy the contents of block iFrom to block iTo.
-**
-** It is safe to assume that there are no outstanding references to pages
-** on block iTo. And that block iFrom is not currently being written. In
-** other words, the data can be read and written directly.
-*/
-int lsmFsMoveBlock(FileSystem *pFS, Segment *pSeg, int iTo, int iFrom){
- Snapshot *p = pFS->pDb->pWorker;
- int rc = LSM_OK;
- int i;
- i64 nMap;
-
- i64 iFromOff = (i64)(iFrom-1) * pFS->nBlocksize;
- i64 iToOff = (i64)(iTo-1) * pFS->nBlocksize;
-
- assert( iTo!=1 );
- assert( iFrom>iTo );
-
- /* Grow the mapping as required. */
- nMap = LSM_MIN(pFS->nMapLimit, (i64)iFrom * pFS->nBlocksize);
- fsGrowMapping(pFS, nMap, &rc);
-
- if( rc==LSM_OK ){
- const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
- int nSz = pFS->nPagesize;
- u8 *aBuf = 0;
- u8 *aData = 0;
-
- for(i=0; rc==LSM_OK && i<nPagePerBlock; i++){
- i64 iOff = iFromOff + i*nSz;
-
- /* Set aData to point to a buffer containing the from page */
- if( (iOff+nSz)<=pFS->nMapLimit ){
- u8 *aMap = (u8 *)(pFS->pMap);
- aData = &aMap[iOff];
- }else{
- if( aBuf==0 ){
- aBuf = (u8 *)lsmMallocRc(pFS->pEnv, nSz, &rc);
- if( aBuf==0 ) break;
- }
- aData = aBuf;
- rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aData, nSz);
- }
-
- /* Copy aData to the to page */
- if( rc==LSM_OK ){
- iOff = iToOff + i*nSz;
- if( (iOff+nSz)<=pFS->nMapLimit ){
- u8 *aMap = (u8 *)(pFS->pMap);
- memcpy(&aMap[iOff], aData, nSz);
- }else{
- rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, aData, nSz);
- }
- }
- }
- lsmFree(pFS->pEnv, aBuf);
- lsmFsPurgeCache(pFS);
- }
-
- /* Update append-point list if necessary */
- for(i=0; i<LSM_APPLIST_SZ; i++){
- fsMovePage(pFS, iTo, iFrom, &p->aiAppend[i]);
- }
-
- /* Update the Segment structure itself */
- fsMovePage(pFS, iTo, iFrom, &pSeg->iFirst);
- fsMovePage(pFS, iTo, iFrom, &pSeg->iLastPg);
- fsMovePage(pFS, iTo, iFrom, &pSeg->iRoot);
-
- return rc;
-}
-
-/*
-** Append raw data to a segment. Return the database file offset that the
-** data is written to (this may be used as the page number if the data
-** being appended is a new page record).
-**
-** This function is only used in compressed database mode.
-*/
-static LsmPgno fsAppendData(
- FileSystem *pFS, /* File-system handle */
- Segment *pSeg, /* Segment to append to */
- const u8 *aData, /* Buffer containing data to write */
- int nData, /* Size of buffer aData[] in bytes */
- int *pRc /* IN/OUT: Error code */
-){
- LsmPgno iRet = 0;
- int rc = *pRc;
- assert( pFS->pCompress );
- if( rc==LSM_OK ){
- int nRem = 0;
- int nWrite = 0;
- LsmPgno iLastOnBlock;
- LsmPgno iApp = pSeg->iLastPg+1;
-
- /* If this is the first data written into the segment, find an append-point
- ** or allocate a new block. */
- if( iApp==1 ){
- pSeg->iFirst = iApp = findAppendPoint(pFS, 0);
- if( iApp==0 ){
- int iBlk;
- rc = lsmBlockAllocate(pFS->pDb, 0, &iBlk);
- pSeg->iFirst = iApp = fsFirstPageOnBlock(pFS, iBlk);
- }
- }
- iRet = iApp;
-
- /* Write as much data as is possible at iApp (usually all of it). */
- iLastOnBlock = fsLastPageOnPagesBlock(pFS, iApp);
- if( rc==LSM_OK ){
- int nSpace = (int)(iLastOnBlock - iApp + 1);
- nWrite = LSM_MIN(nData, nSpace);
- nRem = nData - nWrite;
- assert( nWrite>=0 );
- if( nWrite!=0 ){
- rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iApp, aData, nWrite);
- }
- iApp += nWrite;
- }
-
- /* If required, allocate a new block and write the rest of the data
- ** into it. Set the next and previous block pointers to link the new
- ** block to the old. */
- assert( nRem<=0 || (iApp-1)==iLastOnBlock );
- if( rc==LSM_OK && (iApp-1)==iLastOnBlock ){
- u8 aPtr[4]; /* Space to serialize a u32 */
- int iBlk; /* New block number */
-
- if( nWrite>0 ){
- /* Allocate a new block. */
- rc = lsmBlockAllocate(pFS->pDb, 0, &iBlk);
-
- /* Set the "next" pointer on the old block */
- if( rc==LSM_OK ){
- assert( iApp==(fsPageToBlock(pFS, iApp)*pFS->nBlocksize)-4 );
- lsmPutU32(aPtr, iBlk);
- rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iApp, aPtr, sizeof(aPtr));
- }
-
- /* Set the "prev" pointer on the new block */
- if( rc==LSM_OK ){
- LsmPgno iWrite;
- lsmPutU32(aPtr, fsPageToBlock(pFS, iApp));
- iWrite = fsFirstPageOnBlock(pFS, iBlk);
- rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iWrite-4, aPtr, sizeof(aPtr));
- if( nRem>0 ) iApp = iWrite;
- }
- }else{
- /* The next block is already allocated. */
- assert( nRem>0 );
- assert( pSeg->pRedirect==0 );
- rc = fsBlockNext(pFS, 0, fsPageToBlock(pFS, iApp), &iBlk);
- iRet = iApp = fsFirstPageOnBlock(pFS, iBlk);
- }
-
- /* Write the remaining data into the new block */
- if( rc==LSM_OK && nRem>0 ){
- rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iApp, &aData[nWrite], nRem);
- iApp += nRem;
- }
- }
-
- pSeg->iLastPg = iApp-1;
- *pRc = rc;
- }
-
- return iRet;
-}
-
-/*
-** This function is only called in compressed database mode. It
-** compresses the contents of page pPg and writes the result to the
-** buffer at pFS->aOBuffer. The size of the compressed data is stored in
-** pPg->nCompress.
-**
-** If buffer pFS->aOBuffer[] has not been allocated then this function
-** allocates it. If this fails, LSM_NOMEM is returned. Otherwise, LSM_OK.
-*/
-static int fsCompressIntoBuffer(FileSystem *pFS, Page *pPg){
- lsm_compress *p = pFS->pCompress;
-
- if( fsAllocateBuffer(pFS, 1) ) return LSM_NOMEM;
- assert( pPg->nData==pFS->nPagesize );
-
- pPg->nCompress = pFS->nBuffer;
- return p->xCompress(p->pCtx,
- (char *)pFS->aOBuffer, &pPg->nCompress,
- (const char *)pPg->aData, pPg->nData
- );
-}
-
-/*
-** Append a new page to segment pSeg. Set output variable *piNew to the
-** page number of the new page before returning.
-**
-** If the new page is the last on its block, then the 'next' block that
-** will be used by the segment is allocated here too. In this case output
-** variable *piNext is set to the block number of the next block.
-**
-** If the new page is the first on its block but not the first in the
-** entire segment, set output variable *piPrev to the block number of
-** the previous block in the segment.
-**
-** LSM_OK is returned if successful, or an lsm error code otherwise. If
-** any value other than LSM_OK is returned, then the final value of all
-** output variables is undefined.
-*/
-static int fsAppendPage(
- FileSystem *pFS,
- Segment *pSeg,
- LsmPgno *piNew,
- int *piPrev,
- int *piNext
-){
- LsmPgno iPrev = pSeg->iLastPg;
- int rc;
- assert( iPrev!=0 );
-
- *piPrev = 0;
- *piNext = 0;
-
- if( fsIsLast(pFS, iPrev) ){
- /* Grab the first page on the next block (which has already be
- ** allocated). In this case set *piPrev to tell the caller to set
- ** the "previous block" pointer in the first 4 bytes of the page.
- */
- int iNext;
- int iBlk = fsPageToBlock(pFS, iPrev);
- assert( pSeg->pRedirect==0 );
- rc = fsBlockNext(pFS, 0, iBlk, &iNext);
- if( rc!=LSM_OK ) return rc;
- *piNew = fsFirstPageOnBlock(pFS, iNext);
- *piPrev = iBlk;
- }else{
- *piNew = iPrev+1;
- if( fsIsLast(pFS, *piNew) ){
- /* Allocate the next block here. */
- int iBlk;
- rc = lsmBlockAllocate(pFS->pDb, 0, &iBlk);
- if( rc!=LSM_OK ) return rc;
- *piNext = iBlk;
- }
- }
-
- pSeg->nSize++;
- pSeg->iLastPg = *piNew;
- return LSM_OK;
-}
-
-/*
-** Flush all pages in the FileSystem.pWaiting list to disk.
-*/
-void lsmFsFlushWaiting(FileSystem *pFS, int *pRc){
- int rc = *pRc;
- Page *pPg;
-
- pPg = pFS->pWaiting;
- pFS->pWaiting = 0;
-
- while( pPg ){
- Page *pNext = pPg->pWaitingNext;
- if( rc==LSM_OK ) rc = lsmFsPagePersist(pPg);
- assert( pPg->nRef==1 );
- lsmFsPageRelease(pPg);
- pPg = pNext;
- }
- *pRc = rc;
-}
-
-/*
-** If there exists a hash-table entry associated with page iPg, remove it.
-*/
-static void fsRemoveHashEntry(FileSystem *pFS, LsmPgno iPg){
- Page *p;
- int iHash = fsHashKey(pFS->nHash, iPg);
-
- for(p=pFS->apHash[iHash]; p && p->iPg!=iPg; p=p->pHashNext);
-
- if( p ){
- assert( p->nRef==0 || (p->flags & PAGE_FREE)==0 );
- fsPageRemoveFromHash(pFS, p);
- p->iPg = 0;
- iHash = fsHashKey(pFS->nHash, 0);
- p->pHashNext = pFS->apHash[iHash];
- pFS->apHash[iHash] = p;
- }
-}
-
-/*
-** If the page passed as an argument is dirty, update the database file
-** (or mapping of the database file) with its current contents and mark
-** the page as clean.
-**
-** Return LSM_OK if the operation is a success, or an LSM error code
-** otherwise.
-*/
-int lsmFsPagePersist(Page *pPg){
- int rc = LSM_OK;
- if( pPg && (pPg->flags & PAGE_DIRTY) ){
- FileSystem *pFS = pPg->pFS;
-
- if( pFS->pCompress ){
- int iHash; /* Hash key of assigned page number */
- u8 aSz[3]; /* pPg->nCompress as a 24-bit big-endian */
- assert( pPg->pSeg && pPg->iPg==0 && pPg->nCompress==0 );
-
- /* Compress the page image. */
- rc = fsCompressIntoBuffer(pFS, pPg);
-
- /* Serialize the compressed size into buffer aSz[] */
- putRecordSize(aSz, pPg->nCompress, 0);
-
- /* Write the serialized page record into the database file. */
- pPg->iPg = fsAppendData(pFS, pPg->pSeg, aSz, sizeof(aSz), &rc);
- fsAppendData(pFS, pPg->pSeg, pFS->aOBuffer, pPg->nCompress, &rc);
- fsAppendData(pFS, pPg->pSeg, aSz, sizeof(aSz), &rc);
-
- /* Now that it has a page number, insert the page into the hash table */
- iHash = fsHashKey(pFS->nHash, pPg->iPg);
- pPg->pHashNext = pFS->apHash[iHash];
- pFS->apHash[iHash] = pPg;
-
- pPg->pSeg->nSize += (sizeof(aSz) * 2) + pPg->nCompress;
-
- pPg->flags &= ~PAGE_DIRTY;
- pFS->nWrite++;
- }else{
-
- if( pPg->iPg==0 ){
- /* No page number has been assigned yet. This occurs with pages used
- ** in the b-tree hierarchy. They were not assigned page numbers when
- ** they were created as doing so would cause this call to
- ** lsmFsPagePersist() to write an out-of-order page. Instead a page
- ** number is assigned here so that the page data will be appended
- ** to the current segment.
- */
- Page **pp;
- int iPrev = 0;
- int iNext = 0;
- int iHash;
-
- assert( pPg->pSeg->iFirst );
- assert( pPg->flags & PAGE_FREE );
- assert( (pPg->flags & PAGE_HASPREV)==0 );
- assert( pPg->nData==pFS->nPagesize-4 );
-
- rc = fsAppendPage(pFS, pPg->pSeg, &pPg->iPg, &iPrev, &iNext);
- if( rc!=LSM_OK ) return rc;
-
- assert( pPg->flags & PAGE_FREE );
- iHash = fsHashKey(pFS->nHash, pPg->iPg);
- fsRemoveHashEntry(pFS, pPg->iPg);
- pPg->pHashNext = pFS->apHash[iHash];
- pFS->apHash[iHash] = pPg;
- assert( pPg->pHashNext==0 || pPg->pHashNext->iPg!=pPg->iPg );
-
- if( iPrev ){
- assert( iNext==0 );
- memmove(&pPg->aData[4], pPg->aData, pPg->nData);
- lsmPutU32(pPg->aData, iPrev);
- pPg->flags |= PAGE_HASPREV;
- pPg->aData += 4;
- }else if( iNext ){
- assert( iPrev==0 );
- lsmPutU32(&pPg->aData[pPg->nData], iNext);
- }else{
- int nData = pPg->nData;
- pPg->nData += 4;
- lsmSortedExpandBtreePage(pPg, nData);
- }
-
- pPg->nRef++;
- for(pp=&pFS->pWaiting; *pp; pp=&(*pp)->pWaitingNext);
- *pp = pPg;
- assert( pPg->pWaitingNext==0 );
-
- }else{
- i64 iOff; /* Offset to write within database file */
-
- iOff = (i64)pFS->nPagesize * (i64)(pPg->iPg-1);
- if( fsMmapPage(pFS, pPg->iPg)==0 ){
- u8 *aData = pPg->aData - (pPg->flags & PAGE_HASPREV);
- rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, aData, pFS->nPagesize);
- }else if( pPg->flags & PAGE_FREE ){
- fsGrowMapping(pFS, iOff + pFS->nPagesize, &rc);
- if( rc==LSM_OK ){
- u8 *aTo = &((u8 *)(pFS->pMap))[iOff];
- u8 *aFrom = pPg->aData - (pPg->flags & PAGE_HASPREV);
- memcpy(aTo, aFrom, pFS->nPagesize);
- lsmFree(pFS->pEnv, aFrom);
- pFS->nCacheAlloc--;
- pPg->aData = aTo + (pPg->flags & PAGE_HASPREV);
- pPg->flags &= ~PAGE_FREE;
- fsPageRemoveFromHash(pFS, pPg);
- pPg->pMappedNext = pFS->pMapped;
- pFS->pMapped = pPg;
- }
- }
-
- lsmFsFlushWaiting(pFS, &rc);
- pPg->flags &= ~PAGE_DIRTY;
- pFS->nWrite++;
- }
- }
- }
-
- return rc;
-}
-
-/*
-** For non-compressed databases, this function is a no-op. For compressed
-** databases, it adds a padding record to the segment passed as the third
-** argument.
-**
-** The size of the padding records is selected so that the last byte
-** written is the last byte of a disk sector. This means that if a
-** snapshot is taken and checkpointed, subsequent worker processes will
-** not write to any sector that contains checkpointed data.
-*/
-int lsmFsSortedPadding(
- FileSystem *pFS,
- Snapshot *pSnapshot,
- Segment *pSeg
-){
- int rc = LSM_OK;
- if( pFS->pCompress && pSeg->iFirst ){
- LsmPgno iLast2;
- LsmPgno iLast = pSeg->iLastPg; /* Current last page of segment */
- int nPad; /* Bytes of padding required */
- u8 aSz[3];
-
- iLast2 = (1 + iLast/pFS->szSector) * pFS->szSector - 1;
- assert( fsPageToBlock(pFS, iLast)==fsPageToBlock(pFS, iLast2) );
- nPad = (int)(iLast2 - iLast);
-
- if( iLast2>fsLastPageOnPagesBlock(pFS, iLast) ){
- nPad -= 4;
- }
- assert( nPad>=0 );
-
- if( nPad>=6 ){
- pSeg->nSize += nPad;
- nPad -= 6;
- putRecordSize(aSz, nPad, 1);
- fsAppendData(pFS, pSeg, aSz, sizeof(aSz), &rc);
- memset(pFS->aOBuffer, 0, nPad);
- fsAppendData(pFS, pSeg, pFS->aOBuffer, nPad, &rc);
- fsAppendData(pFS, pSeg, aSz, sizeof(aSz), &rc);
- }else if( nPad>0 ){
- u8 aBuf[5] = {0,0,0,0,0};
- aBuf[0] = (u8)nPad;
- aBuf[nPad-1] = (u8)nPad;
- fsAppendData(pFS, pSeg, aBuf, nPad, &rc);
- }
-
- assert( rc!=LSM_OK
- || pSeg->iLastPg==fsLastPageOnPagesBlock(pFS, pSeg->iLastPg)
- || ((pSeg->iLastPg + 1) % pFS->szSector)==0
- );
- }
-
- return rc;
-}
-
-
-/*
-** Increment the reference count on the page object passed as the first
-** argument.
-*/
-void lsmFsPageRef(Page *pPg){
- if( pPg ){
- pPg->nRef++;
- }
-}
-
-/*
-** Release a page-reference obtained using fsPageGet().
-*/
-int lsmFsPageRelease(Page *pPg){
- int rc = LSM_OK;
- if( pPg ){
- assert( pPg->nRef>0 );
- pPg->nRef--;
- if( pPg->nRef==0 ){
- FileSystem *pFS = pPg->pFS;
- rc = lsmFsPagePersist(pPg);
- pFS->nOut--;
-
- assert( pPg->pFS->pCompress
- || fsIsFirst(pPg->pFS, pPg->iPg)==0
- || (pPg->flags & PAGE_HASPREV)
- );
- pPg->aData -= (pPg->flags & PAGE_HASPREV);
- pPg->flags &= ~PAGE_HASPREV;
-
- if( (pPg->flags & PAGE_FREE)==0 ){
- /* Removed from mapped list */
- Page **pp;
- for(pp=&pFS->pMapped; (*pp)!=pPg; pp=&(*pp)->pMappedNext);
- *pp = pPg->pMappedNext;
- pPg->pMappedNext = 0;
-
- /* Add to free list */
- pPg->pFreeNext = pFS->pFree;
- pFS->pFree = pPg;
- }else{
- fsPageAddToLru(pFS, pPg);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Return the total number of pages read from the database file.
-*/
-int lsmFsNRead(FileSystem *pFS){ return pFS->nRead; }
-
-/*
-** Return the total number of pages written to the database file.
-*/
-int lsmFsNWrite(FileSystem *pFS){ return pFS->nWrite; }
-
-/*
-** Return a copy of the environment pointer used by the file-system object.
-*/
-lsm_env *lsmFsEnv(FileSystem *pFS){
- return pFS->pEnv;
-}
-
-/*
-** Return a copy of the environment pointer used by the file-system object
-** to which this page belongs.
-*/
-lsm_env *lsmPageEnv(Page *pPg) {
- return pPg->pFS->pEnv;
-}
-
-/*
-** Return a pointer to the file-system object associated with the Page
-** passed as the only argument.
-*/
-FileSystem *lsmPageFS(Page *pPg){
- return pPg->pFS;
-}
-
-/*
-** Return the sector-size as reported by the log file handle.
-*/
-int lsmFsSectorSize(FileSystem *pFS){
- return pFS->szSector;
-}
-
-/*
-** Helper function for lsmInfoArrayStructure().
-*/
-static Segment *startsWith(Segment *pRun, LsmPgno iFirst){
- return (iFirst==pRun->iFirst) ? pRun : 0;
-}
-
-/*
-** Return the segment that starts with page iFirst, if any. If no such segment
-** can be found, return NULL.
-*/
-static Segment *findSegment(Snapshot *pWorker, LsmPgno iFirst){
- Level *pLvl; /* Used to iterate through db levels */
- Segment *pSeg = 0; /* Pointer to segment to return */
-
- for(pLvl=lsmDbSnapshotLevel(pWorker); pLvl && pSeg==0; pLvl=pLvl->pNext){
- if( 0==(pSeg = startsWith(&pLvl->lhs, iFirst)) ){
- int i;
- for(i=0; i<pLvl->nRight; i++){
- if( (pSeg = startsWith(&pLvl->aRhs[i], iFirst)) ) break;
- }
- }
- }
-
- return pSeg;
-}
-
-/*
-** This function implements the lsm_info(LSM_INFO_ARRAY_STRUCTURE) request.
-** If successful, *pzOut is set to point to a nul-terminated string
-** containing the array structure and LSM_OK is returned. The caller should
-** eventually free the string using lsmFree().
-**
-** If an error occurs, *pzOut is set to NULL and an LSM error code returned.
-*/
-int lsmInfoArrayStructure(
- lsm_db *pDb,
- int bBlock, /* True for block numbers only */
- LsmPgno iFirst,
- char **pzOut
-){
- int rc = LSM_OK;
- Snapshot *pWorker; /* Worker snapshot */
- Segment *pArray = 0; /* Array to report on */
- int bUnlock = 0;
-
- *pzOut = 0;
- if( iFirst==0 ) return LSM_ERROR;
-
- /* Obtain the worker snapshot */
- pWorker = pDb->pWorker;
- if( !pWorker ){
- rc = lsmBeginWork(pDb);
- if( rc!=LSM_OK ) return rc;
- pWorker = pDb->pWorker;
- bUnlock = 1;
- }
-
- /* Search for the array that starts on page iFirst */
- pArray = findSegment(pWorker, iFirst);
-
- if( pArray==0 ){
- /* Could not find the requested array. This is an error. */
- rc = LSM_ERROR;
- }else{
- FileSystem *pFS = pDb->pFS;
- LsmString str;
- int iBlk;
- int iLastBlk;
-
- iBlk = fsPageToBlock(pFS, pArray->iFirst);
- iLastBlk = fsPageToBlock(pFS, pArray->iLastPg);
-
- lsmStringInit(&str, pDb->pEnv);
- if( bBlock ){
- lsmStringAppendf(&str, "%d", iBlk);
- while( iBlk!=iLastBlk ){
- fsBlockNext(pFS, pArray, iBlk, &iBlk);
- lsmStringAppendf(&str, " %d", iBlk);
- }
- }else{
- lsmStringAppendf(&str, "%d", pArray->iFirst);
- while( iBlk!=iLastBlk ){
- lsmStringAppendf(&str, " %d", fsLastPageOnBlock(pFS, iBlk));
- fsBlockNext(pFS, pArray, iBlk, &iBlk);
- lsmStringAppendf(&str, " %d", fsFirstPageOnBlock(pFS, iBlk));
- }
- lsmStringAppendf(&str, " %d", pArray->iLastPg);
- }
-
- *pzOut = str.z;
- }
-
- if( bUnlock ){
- int rcwork = LSM_BUSY;
- lsmFinishWork(pDb, 0, &rcwork);
- }
- return rc;
-}
-
-int lsmFsSegmentContainsPg(
- FileSystem *pFS,
- Segment *pSeg,
- LsmPgno iPg,
- int *pbRes
-){
- Redirect *pRedir = pSeg->pRedirect;
- int rc = LSM_OK;
- int iBlk;
- int iLastBlk;
- int iPgBlock; /* Block containing page iPg */
-
- iPgBlock = fsPageToBlock(pFS, pSeg->iFirst);
- iBlk = fsRedirectBlock(pRedir, fsPageToBlock(pFS, pSeg->iFirst));
- iLastBlk = fsRedirectBlock(pRedir, fsPageToBlock(pFS, pSeg->iLastPg));
-
- while( iBlk!=iLastBlk && iBlk!=iPgBlock && rc==LSM_OK ){
- rc = fsBlockNext(pFS, pSeg, iBlk, &iBlk);
- }
-
- *pbRes = (iBlk==iPgBlock);
- return rc;
-}
-
-/*
-** This function implements the lsm_info(LSM_INFO_ARRAY_PAGES) request.
-** If successful, *pzOut is set to point to a nul-terminated string
-** containing the array structure and LSM_OK is returned. The caller should
-** eventually free the string using lsmFree().
-**
-** If an error occurs, *pzOut is set to NULL and an LSM error code returned.
-*/
-int lsmInfoArrayPages(lsm_db *pDb, LsmPgno iFirst, char **pzOut){
- int rc = LSM_OK;
- Snapshot *pWorker; /* Worker snapshot */
- Segment *pSeg = 0; /* Array to report on */
- int bUnlock = 0;
-
- *pzOut = 0;
- if( iFirst==0 ) return LSM_ERROR;
-
- /* Obtain the worker snapshot */
- pWorker = pDb->pWorker;
- if( !pWorker ){
- rc = lsmBeginWork(pDb);
- if( rc!=LSM_OK ) return rc;
- pWorker = pDb->pWorker;
- bUnlock = 1;
- }
-
- /* Search for the array that starts on page iFirst */
- pSeg = findSegment(pWorker, iFirst);
-
- if( pSeg==0 ){
- /* Could not find the requested array. This is an error. */
- rc = LSM_ERROR;
- }else{
- Page *pPg = 0;
- FileSystem *pFS = pDb->pFS;
- LsmString str;
-
- lsmStringInit(&str, pDb->pEnv);
- rc = lsmFsDbPageGet(pFS, pSeg, iFirst, &pPg);
- while( rc==LSM_OK && pPg ){
- Page *pNext = 0;
- lsmStringAppendf(&str, " %lld", lsmFsPageNumber(pPg));
- rc = lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
- lsmFsPageRelease(pPg);
- pPg = pNext;
- }
-
- if( rc!=LSM_OK ){
- lsmFree(pDb->pEnv, str.z);
- }else{
- *pzOut = str.z;
- }
- }
-
- if( bUnlock ){
- int rcwork = LSM_BUSY;
- lsmFinishWork(pDb, 0, &rcwork);
- }
- return rc;
-}
-
-/*
-** The following macros are used by the integrity-check code. Associated with
-** each block in the database is an 8-bit bit mask (the entry in the aUsed[]
-** array). As the integrity-check meanders through the database, it sets the
-** following bits to indicate how each block is used.
-**
-** INTEGRITY_CHECK_FIRST_PG:
-** First page of block is in use by sorted run.
-**
-** INTEGRITY_CHECK_LAST_PG:
-** Last page of block is in use by sorted run.
-**
-** INTEGRITY_CHECK_USED:
-** At least one page of the block is in use by a sorted run.
-**
-** INTEGRITY_CHECK_FREE:
-** The free block list contains an entry corresponding to this block.
-*/
-#define INTEGRITY_CHECK_FIRST_PG 0x01
-#define INTEGRITY_CHECK_LAST_PG 0x02
-#define INTEGRITY_CHECK_USED 0x04
-#define INTEGRITY_CHECK_FREE 0x08
-
-/*
-** Helper function for lsmFsIntegrityCheck()
-*/
-static void checkBlocks(
- FileSystem *pFS,
- Segment *pSeg,
- int bExtra, /* If true, count the "next" block if any */
- int nUsed,
- u8 *aUsed
-){
- if( pSeg ){
- if( pSeg && pSeg->nSize>0 ){
- int rc;
- int iBlk; /* Current block (during iteration) */
- int iLastBlk; /* Last block of segment */
- int iFirstBlk; /* First block of segment */
- int bLastIsLastOnBlock; /* True iLast is the last on its block */
-
- assert( 0==fsSegmentRedirects(pFS, pSeg) );
- iBlk = iFirstBlk = fsPageToBlock(pFS, pSeg->iFirst);
- iLastBlk = fsPageToBlock(pFS, pSeg->iLastPg);
-
- bLastIsLastOnBlock = (fsLastPageOnBlock(pFS, iLastBlk)==pSeg->iLastPg);
- assert( iBlk>0 );
-
- do {
- /* iBlk is a part of this sorted run. */
- aUsed[iBlk-1] |= INTEGRITY_CHECK_USED;
-
- /* If the first page of this block is also part of the segment,
- ** set the flag to indicate that the first page of iBlk is in use.
- */
- if( fsFirstPageOnBlock(pFS, iBlk)==pSeg->iFirst || iBlk!=iFirstBlk ){
- assert( (aUsed[iBlk-1] & INTEGRITY_CHECK_FIRST_PG)==0 );
- aUsed[iBlk-1] |= INTEGRITY_CHECK_FIRST_PG;
- }
-
- /* Unless the sorted run finishes before the last page on this block,
- ** the last page of this block is also in use. */
- if( iBlk!=iLastBlk || bLastIsLastOnBlock ){
- assert( (aUsed[iBlk-1] & INTEGRITY_CHECK_LAST_PG)==0 );
- aUsed[iBlk-1] |= INTEGRITY_CHECK_LAST_PG;
- }
-
- /* Special case. The sorted run being scanned is the output run of
- ** a level currently undergoing an incremental merge. The sorted
- ** run ends on the last page of iBlk, but the next block has already
- ** been allocated. So mark it as in use as well. */
- if( iBlk==iLastBlk && bLastIsLastOnBlock && bExtra ){
- int iExtra = 0;
- rc = fsBlockNext(pFS, pSeg, iBlk, &iExtra);
- assert( rc==LSM_OK );
-
- assert( aUsed[iExtra-1]==0 );
- aUsed[iExtra-1] |= INTEGRITY_CHECK_USED;
- aUsed[iExtra-1] |= INTEGRITY_CHECK_FIRST_PG;
- aUsed[iExtra-1] |= INTEGRITY_CHECK_LAST_PG;
- }
-
- /* Move on to the next block in the sorted run. Or set iBlk to zero
- ** in order to break out of the loop if this was the last block in
- ** the run. */
- if( iBlk==iLastBlk ){
- iBlk = 0;
- }else{
- rc = fsBlockNext(pFS, pSeg, iBlk, &iBlk);
- assert( rc==LSM_OK );
- }
- }while( iBlk );
- }
- }
-}
-
-typedef struct CheckFreelistCtx CheckFreelistCtx;
-struct CheckFreelistCtx {
- u8 *aUsed;
- int nBlock;
-};
-static int checkFreelistCb(void *pCtx, int iBlk, i64 iSnapshot){
- CheckFreelistCtx *p = (CheckFreelistCtx *)pCtx;
-
- assert( iBlk>=1 );
- assert( iBlk<=p->nBlock );
- assert( p->aUsed[iBlk-1]==0 );
- p->aUsed[iBlk-1] = INTEGRITY_CHECK_FREE;
- return 0;
-}
-
-/*
-** This function checks that all blocks in the database file are accounted
-** for. For each block, exactly one of the following must be true:
-**
-** + the block is part of a sorted run, or
-** + the block is on the free-block list
-**
-** This function also checks that there are no references to blocks with
-** out-of-range block numbers.
-**
-** If no errors are found, non-zero is returned. If an error is found, an
-** assert() fails.
-*/
-int lsmFsIntegrityCheck(lsm_db *pDb){
- CheckFreelistCtx ctx;
- FileSystem *pFS = pDb->pFS;
- int i;
- int rc;
- Freelist freelist = {0, 0, 0};
- u8 *aUsed;
- Level *pLevel;
- Snapshot *pWorker = pDb->pWorker;
- int nBlock = pWorker->nBlock;
-
-#if 0
- static int nCall = 0;
- nCall++;
- printf("%d calls\n", nCall);
-#endif
-
- aUsed = lsmMallocZero(pDb->pEnv, nBlock);
- if( aUsed==0 ){
- /* Malloc has failed. Since this function is only called within debug
- ** builds, this probably means the user is running an OOM injection test.
- ** Regardless, it will not be possible to run the integrity-check at this
- ** time, so assume the database is Ok and return non-zero. */
- return 1;
- }
-
- for(pLevel=pWorker->pLevel; pLevel; pLevel=pLevel->pNext){
- int j;
- checkBlocks(pFS, &pLevel->lhs, (pLevel->nRight!=0), nBlock, aUsed);
- for(j=0; j<pLevel->nRight; j++){
- checkBlocks(pFS, &pLevel->aRhs[j], 0, nBlock, aUsed);
- }
- }
-
- /* Mark all blocks in the free-list as used */
- ctx.aUsed = aUsed;
- ctx.nBlock = nBlock;
- rc = lsmWalkFreelist(pDb, 0, checkFreelistCb, (void *)&ctx);
-
- if( rc==LSM_OK ){
- for(i=0; i<nBlock; i++) assert( aUsed[i]!=0 );
- }
-
- lsmFree(pDb->pEnv, aUsed);
- lsmFree(pDb->pEnv, freelist.aEntry);
-
- return 1;
-}
-
-#ifndef NDEBUG
-/*
-** Return true if pPg happens to be the last page in segment pSeg. Or false
-** otherwise. This function is only invoked as part of assert() conditions.
-*/
-int lsmFsDbPageIsLast(Segment *pSeg, Page *pPg){
- if( pPg->pFS->pCompress ){
- LsmPgno iNext = 0;
- int rc;
- rc = fsNextPageOffset(pPg->pFS, pSeg, pPg->iPg, pPg->nCompress+6, &iNext);
- return (rc!=LSM_OK || iNext==0);
- }
- return (pPg->iPg==pSeg->iLastPg);
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_log.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_log.c
deleted file mode 100644
index a66e40bccd5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_log.c
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
-** 2011-08-13
-**
-** 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 contains the implementation of LSM database logging. Logging
-** has one purpose in LSM - to make transactions durable.
-**
-** When data is written to an LSM database, it is initially stored in an
-** in-memory tree structure. Since this structure is in volatile memory,
-** if a power failure or application crash occurs it may be lost. To
-** prevent loss of data in this case, each time a record is written to the
-** in-memory tree an equivalent record is appended to the log on disk.
-** If a power failure or application crash does occur, data can be recovered
-** by reading the log.
-**
-** A log file consists of the following types of records representing data
-** written into the database:
-**
-** LOG_WRITE: A key-value pair written to the database.
-** LOG_DELETE: A delete key issued to the database.
-** LOG_COMMIT: A transaction commit.
-**
-** And the following types of records for ancillary purposes..
-**
-** LOG_EOF: A record indicating the end of a log file.
-** LOG_PAD1: A single byte padding record.
-** LOG_PAD2: An N byte padding record (N>1).
-** LOG_JUMP: A pointer to another offset within the log file.
-**
-** Each transaction written to the log contains one or more LOG_WRITE and/or
-** LOG_DELETE records, followed by a LOG_COMMIT record. The LOG_COMMIT record
-** contains an 8-byte checksum based on all previous data written to the
-** log file.
-**
-** LOG CHECKSUMS & RECOVERY
-**
-** Checksums are found in two types of log records: LOG_COMMIT and
-** LOG_CKSUM records. In order to recover content from a log, a client
-** reads each record from the start of the log, calculating a checksum as
-** it does. Each time a LOG_COMMIT or LOG_CKSUM is encountered, the
-** recovery process verifies that the checksum stored in the log
-** matches the calculated checksum. If it does not, the recovery process
-** can stop reading the log.
-**
-** If a recovery process reads records (other than COMMIT or CKSUM)
-** consisting of at least LSM_CKSUM_MAXDATA bytes, then the next record in
-** the log must be either a LOG_CKSUM or LOG_COMMIT record. If it is
-** not, the recovery process also stops reading the log.
-**
-** To recover the log file, it must be read twice. The first time to
-** determine the location of the last valid commit record. And the second
-** time to load data into the in-memory tree.
-**
-** Todo: Surely there is a better way...
-**
-** LOG WRAPPING
-**
-** If the log file were never deleted or wrapped, it would be possible to
-** read it from start to end each time is required recovery (i.e each time
-** the number of database clients changes from 0 to 1). Effectively reading
-** the entire history of the database each time. This would quickly become
-** inefficient. Additionally, since the log file would grow without bound,
-** it wastes storage space.
-**
-** Instead, part of each checkpoint written into the database file contains
-** a log offset (and other information required to read the log starting at
-** at this offset) at which to begin recovery. Offset $O.
-**
-** Once a checkpoint has been written and synced into the database file, it
-** is guaranteed that no recovery process will need to read any data before
-** offset $O of the log file. It is therefore safe to begin overwriting
-** any data that occurs before offset $O.
-**
-** This implementation separates the log into three regions mapped into
-** the log file - regions 0, 1 and 2. During recovery, regions are read
-** in ascending order (i.e. 0, then 1, then 2). Each region is zero or
-** more bytes in size.
-**
-** |---1---|..|--0--|.|--2--|....
-**
-** New records are always appended to the end of region 2.
-**
-** Initially (when it is empty), all three regions are zero bytes in size.
-** Each of them are located at the beginning of the file. As records are
-** added to the log, region 2 grows, so that the log consists of a zero
-** byte region 1, followed by a zero byte region 0, followed by an N byte
-** region 2. After one or more checkpoints have been written to disk,
-** the start point of region 2 is moved to $O. For example:
-**
-** A) ||.........|--2--|....
-**
-** (both regions 0 and 1 are 0 bytes in size at offset 0).
-**
-** Eventually, the log wraps around to write new records into the start.
-** At this point, region 2 is renamed to region 0. Region 0 is renamed
-** to region 2. After appending a few records to the new region 2, the
-** log file looks like this:
-**
-** B) ||--2--|...|--0--|....
-**
-** (region 1 is still 0 bytes in size, located at offset 0).
-**
-** Any checkpoints made at this point may reduce the size of region 0.
-** However, if they do not, and region 2 expands so that it is about to
-** overwrite the start of region 0, then region 2 is renamed to region 1,
-** and a new region 2 created at the end of the file following the existing
-** region 0.
-**
-** C) |---1---|..|--0--|.|-2-|
-**
-** In this state records are appended to region 2 until checkpoints have
-** contracted regions 0 AND 1 UNTil they are both zero bytes in size. They
-** are then shifted to the start of the log file, leaving the system in
-** the equivalent of state A above.
-**
-** Alternatively, state B may transition directly to state A if the size
-** of region 0 is reduced to zero bytes before region 2 threatens to
-** encroach upon it.
-**
-** LOG_PAD1 & LOG_PAD2 RECORDS
-**
-** PAD1 and PAD2 records may appear in a log file at any point. They allow
-** a process writing the log file align the beginning of transactions with
-** the beginning of disk sectors, which increases robustness.
-**
-** RECORD FORMATS:
-**
-** LOG_EOF: * A single 0x00 byte.
-**
-** LOG_PAD1: * A single 0x01 byte.
-**
-** LOG_PAD2: * A single 0x02 byte, followed by
-** * The number of unused bytes (N) as a varint,
-** * An N byte block of unused space.
-**
-** LOG_COMMIT: * A single 0x03 byte.
-** * An 8-byte checksum.
-**
-** LOG_JUMP: * A single 0x04 byte.
-** * Absolute file offset to jump to, encoded as a varint.
-**
-** LOG_WRITE: * A single 0x06 or 0x07 byte,
-** * The number of bytes in the key, encoded as a varint,
-** * The number of bytes in the value, encoded as a varint,
-** * If the first byte was 0x07, an 8 byte checksum.
-** * The key data,
-** * The value data.
-**
-** LOG_DELETE: * A single 0x08 or 0x09 byte,
-** * The number of bytes in the key, encoded as a varint,
-** * If the first byte was 0x09, an 8 byte checksum.
-** * The key data.
-**
-** Varints are as described in lsm_varint.c (SQLite 4 format).
-**
-** CHECKSUMS:
-**
-** The checksum is calculated using two 32-bit unsigned integers, s0 and
-** s1. The initial value for both is 42. It is updated each time a record
-** is written into the log file by treating the encoded (binary) record as
-** an array of 32-bit little-endian integers. Then, if x[] is the integer
-** array, updating the checksum accumulators as follows:
-**
-** for i from 0 to n-1 step 2:
-** s0 += x[i] + s1;
-** s1 += x[i+1] + s0;
-** endfor
-**
-** If the record is not an even multiple of 8-bytes in size it is padded
-** with zeroes to make it so before the checksum is updated.
-**
-** The checksum stored in a COMMIT, WRITE or DELETE is based on all bytes
-** up to the start of the 8-byte checksum itself, including the COMMIT,
-** WRITE or DELETE fields that appear before the checksum in the record.
-**
-** VARINT FORMAT
-**
-** See lsm_varint.c.
-*/
-
-#ifndef _LSM_INT_H
-# include "lsmInt.h"
-#endif
-
-/* Log record types */
-#define LSM_LOG_EOF 0x00
-#define LSM_LOG_PAD1 0x01
-#define LSM_LOG_PAD2 0x02
-#define LSM_LOG_COMMIT 0x03
-#define LSM_LOG_JUMP 0x04
-
-#define LSM_LOG_WRITE 0x06
-#define LSM_LOG_WRITE_CKSUM 0x07
-
-#define LSM_LOG_DELETE 0x08
-#define LSM_LOG_DELETE_CKSUM 0x09
-
-#define LSM_LOG_DRANGE 0x0A
-#define LSM_LOG_DRANGE_CKSUM 0x0B
-
-/* Require a checksum every 32KB. */
-#define LSM_CKSUM_MAXDATA (32*1024)
-
-/* Do not wrap a log file smaller than this in bytes. */
-#define LSM_MIN_LOGWRAP (128*1024)
-
-/*
-** szSector:
-** Commit records must be aligned to end on szSector boundaries. If
-** the safety-mode is set to NORMAL or OFF, this value is 1. Otherwise,
-** if the safety-mode is set to FULL, it is the size of the file-system
-** sectors as reported by lsmFsSectorSize().
-*/
-struct LogWriter {
- u32 cksum0; /* Checksum 0 at offset iOff */
- u32 cksum1; /* Checksum 1 at offset iOff */
- int iCksumBuf; /* Bytes of buf that have been checksummed */
- i64 iOff; /* Offset at start of buffer buf */
- int szSector; /* Sector size for this transaction */
- LogRegion jump; /* Avoid writing to this region */
- i64 iRegion1End; /* End of first region written by trans */
- i64 iRegion2Start; /* Start of second regions written by trans */
- LsmString buf; /* Buffer containing data not yet written */
-};
-
-/*
-** Return the result of interpreting the first 4 bytes in buffer aIn as
-** a 32-bit unsigned little-endian integer.
-*/
-static u32 getU32le(u8 *aIn){
- return ((u32)aIn[3] << 24)
- + ((u32)aIn[2] << 16)
- + ((u32)aIn[1] << 8)
- + ((u32)aIn[0]);
-}
-
-
-/*
-** This function is the same as logCksum(), except that pointer "a" need
-** not be aligned to an 8-byte boundary or padded with zero bytes. This
-** version is slower, but sometimes more convenient to use.
-*/
-static void logCksumUnaligned(
- char *z, /* Input buffer */
- int n, /* Size of input buffer in bytes */
- u32 *pCksum0, /* IN/OUT: Checksum value 1 */
- u32 *pCksum1 /* IN/OUT: Checksum value 2 */
-){
- u8 *a = (u8 *)z;
- u32 cksum0 = *pCksum0;
- u32 cksum1 = *pCksum1;
- int nIn = (n/8) * 8;
- int i;
-
- assert( n>0 );
- for(i=0; i<nIn; i+=8){
- cksum0 += getU32le(&a[i]) + cksum1;
- cksum1 += getU32le(&a[i+4]) + cksum0;
- }
-
- if( nIn!=n ){
- u8 aBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- assert( (n-nIn)<8 && n>nIn );
- memcpy(aBuf, &a[nIn], n-nIn);
- cksum0 += getU32le(aBuf) + cksum1;
- cksum1 += getU32le(&aBuf[4]) + cksum0;
- }
-
- *pCksum0 = cksum0;
- *pCksum1 = cksum1;
-}
-
-/*
-** Update pLog->cksum0 and pLog->cksum1 so that the first nBuf bytes in the
-** write buffer (pLog->buf) are included in the checksum.
-*/
-static void logUpdateCksum(LogWriter *pLog, int nBuf){
- assert( (pLog->iCksumBuf % 8)==0 );
- assert( pLog->iCksumBuf<=nBuf );
- assert( (nBuf % 8)==0 || nBuf==pLog->buf.n );
- if( nBuf>pLog->iCksumBuf ){
- logCksumUnaligned(
- &pLog->buf.z[pLog->iCksumBuf], nBuf-pLog->iCksumBuf,
- &pLog->cksum0, &pLog->cksum1
- );
- }
- pLog->iCksumBuf = nBuf;
-}
-
-static i64 firstByteOnSector(LogWriter *pLog, i64 iOff){
- return (iOff / pLog->szSector) * pLog->szSector;
-}
-static i64 lastByteOnSector(LogWriter *pLog, i64 iOff){
- return firstByteOnSector(pLog, iOff) + pLog->szSector - 1;
-}
-
-/*
-** If possible, reclaim log file space. Log file space is reclaimed after
-** a snapshot that points to the same data in the database file is synced
-** into the db header.
-*/
-static int logReclaimSpace(lsm_db *pDb){
- int rc;
- int iMeta;
- int bRotrans; /* True if there exists some ro-trans */
-
- /* Test if there exists some other connection with a read-only transaction
- ** open. If there does, then log file space may not be reclaimed. */
- rc = lsmDetectRoTrans(pDb, &bRotrans);
- if( rc!=LSM_OK || bRotrans ) return rc;
-
- iMeta = (int)pDb->pShmhdr->iMetaPage;
- if( iMeta==1 || iMeta==2 ){
- DbLog *pLog = &pDb->treehdr.log;
- i64 iSyncedId;
-
- /* Read the snapshot-id of the snapshot stored on meta-page iMeta. Note
- ** that in theory, the value read is untrustworthy (due to a race
- ** condition - see comments above lsmFsReadSyncedId()). So it is only
- ** ever used to conclude that no log space can be reclaimed. If it seems
- ** to indicate that it may be possible to reclaim log space, a
- ** second call to lsmCheckpointSynced() (which does return trustworthy
- ** values) is made below to confirm. */
- rc = lsmFsReadSyncedId(pDb, iMeta, &iSyncedId);
-
- if( rc==LSM_OK && pLog->iSnapshotId!=iSyncedId ){
- i64 iSnapshotId = 0;
- i64 iOff = 0;
- rc = lsmCheckpointSynced(pDb, &iSnapshotId, &iOff, 0);
- if( rc==LSM_OK && pLog->iSnapshotId<iSnapshotId ){
- int iRegion;
- for(iRegion=0; iRegion<3; iRegion++){
- LogRegion *p = &pLog->aRegion[iRegion];
- if( iOff>=p->iStart && iOff<=p->iEnd ) break;
- p->iStart = 0;
- p->iEnd = 0;
- }
- assert( iRegion<3 );
- pLog->aRegion[iRegion].iStart = iOff;
- pLog->iSnapshotId = iSnapshotId;
- }
- }
- }
- return rc;
-}
-
-/*
-** This function is called when a write-transaction is first opened. It
-** is assumed that the caller is holding the client-mutex when it is
-** called.
-**
-** Before returning, this function allocates the LogWriter object that
-** will be used to write to the log file during the write transaction.
-** LSM_OK is returned if no error occurs, otherwise an LSM error code.
-*/
-int lsmLogBegin(lsm_db *pDb){
- int rc = LSM_OK;
- LogWriter *pNew;
- LogRegion *aReg;
-
- if( pDb->bUseLog==0 ) return LSM_OK;
-
- /* If the log file has not yet been opened, open it now. Also allocate
- ** the LogWriter structure, if it has not already been allocated. */
- rc = lsmFsOpenLog(pDb, 0);
- if( pDb->pLogWriter==0 ){
- pNew = lsmMallocZeroRc(pDb->pEnv, sizeof(LogWriter), &rc);
- if( pNew ){
- lsmStringInit(&pNew->buf, pDb->pEnv);
- rc = lsmStringExtend(&pNew->buf, 2);
- }
- pDb->pLogWriter = pNew;
- }else{
- pNew = pDb->pLogWriter;
- assert( (u8 *)(&pNew[1])==(u8 *)(&((&pNew->buf)[1])) );
- memset(pNew, 0, ((u8 *)&pNew->buf) - (u8 *)pNew);
- pNew->buf.n = 0;
- }
-
- if( rc==LSM_OK ){
- /* The following call detects whether or not a new snapshot has been
- ** synced into the database file. If so, it updates the contents of
- ** the pDb->treehdr.log structure to reclaim any space in the log
- ** file that is no longer required.
- **
- ** TODO: Calling this every transaction is overkill. And since the
- ** call has to read and checksum a snapshot from the database file,
- ** it is expensive. It would be better to figure out a way so that
- ** this is only called occasionally - say for every 32KB written to
- ** the log file.
- */
- rc = logReclaimSpace(pDb);
- }
- if( rc!=LSM_OK ){
- lsmLogClose(pDb);
- return rc;
- }
-
- /* Set the effective sector-size for this transaction. Sectors are assumed
- ** to be one byte in size if the safety-mode is OFF or NORMAL, or as
- ** reported by lsmFsSectorSize if it is FULL. */
- if( pDb->eSafety==LSM_SAFETY_FULL ){
- pNew->szSector = lsmFsSectorSize(pDb->pFS);
- assert( pNew->szSector>0 );
- }else{
- pNew->szSector = 1;
- }
-
- /* There are now three scenarios:
- **
- ** 1) Regions 0 and 1 are both zero bytes in size and region 2 begins
- ** at a file offset greater than LSM_MIN_LOGWRAP. In this case, wrap
- ** around to the start and write data into the start of the log file.
- **
- ** 2) Region 1 is zero bytes in size and region 2 occurs earlier in the
- ** file than region 0. In this case, append data to region 2, but
- ** remember to jump over region 1 if required.
- **
- ** 3) Region 2 is the last in the file. Append to it.
- */
- aReg = &pDb->treehdr.log.aRegion[0];
-
- assert( aReg[0].iEnd==0 || aReg[0].iEnd>aReg[0].iStart );
- assert( aReg[1].iEnd==0 || aReg[1].iEnd>aReg[1].iStart );
-
- pNew->cksum0 = pDb->treehdr.log.cksum0;
- pNew->cksum1 = pDb->treehdr.log.cksum1;
-
- if( aReg[0].iEnd==0 && aReg[1].iEnd==0 && aReg[2].iStart>=LSM_MIN_LOGWRAP ){
- /* Case 1. Wrap around to the start of the file. Write an LSM_LOG_JUMP
- ** into the log file in this case. Pad it out to 8 bytes using a PAD2
- ** record so that the checksums can be updated immediately. */
- u8 aJump[] = {
- LSM_LOG_PAD2, 0x04, 0x00, 0x00, 0x00, 0x00, LSM_LOG_JUMP, 0x00
- };
-
- lsmStringBinAppend(&pNew->buf, aJump, sizeof(aJump));
- logUpdateCksum(pNew, pNew->buf.n);
- rc = lsmFsWriteLog(pDb->pFS, aReg[2].iEnd, &pNew->buf);
- pNew->iCksumBuf = pNew->buf.n = 0;
-
- aReg[2].iEnd += 8;
- pNew->jump = aReg[0] = aReg[2];
- aReg[2].iStart = aReg[2].iEnd = 0;
- }else if( aReg[1].iEnd==0 && aReg[2].iEnd<aReg[0].iEnd ){
- /* Case 2. */
- pNew->iOff = aReg[2].iEnd;
- pNew->jump = aReg[0];
- }else{
- /* Case 3. */
- assert( aReg[2].iStart>=aReg[0].iEnd && aReg[2].iStart>=aReg[1].iEnd );
- pNew->iOff = aReg[2].iEnd;
- }
-
- if( pNew->jump.iStart ){
- i64 iRound;
- assert( pNew->jump.iStart>pNew->iOff );
-
- iRound = firstByteOnSector(pNew, pNew->jump.iStart);
- if( iRound>pNew->iOff ) pNew->jump.iStart = iRound;
- pNew->jump.iEnd = lastByteOnSector(pNew, pNew->jump.iEnd);
- }
-
- assert( pDb->pLogWriter==pNew );
- return rc;
-}
-
-/*
-** This function is called when a write-transaction is being closed.
-** Parameter bCommit is true if the transaction is being committed,
-** or false otherwise. The caller must hold the client-mutex to call
-** this function.
-**
-** A call to this function deletes the LogWriter object allocated by
-** lsmLogBegin(). If the transaction is being committed, the shared state
-** in *pLog is updated before returning.
-*/
-void lsmLogEnd(lsm_db *pDb, int bCommit){
- DbLog *pLog;
- LogWriter *p;
- p = pDb->pLogWriter;
-
- if( p==0 ) return;
- pLog = &pDb->treehdr.log;
-
- if( bCommit ){
- pLog->aRegion[2].iEnd = p->iOff;
- pLog->cksum0 = p->cksum0;
- pLog->cksum1 = p->cksum1;
- if( p->iRegion1End ){
- /* This happens when the transaction had to jump over some other
- ** part of the log. */
- assert( pLog->aRegion[1].iEnd==0 );
- assert( pLog->aRegion[2].iStart<p->iRegion1End );
- pLog->aRegion[1].iStart = pLog->aRegion[2].iStart;
- pLog->aRegion[1].iEnd = p->iRegion1End;
- pLog->aRegion[2].iStart = p->iRegion2Start;
- }
- }
-}
-
-static int jumpIfRequired(
- lsm_db *pDb,
- LogWriter *pLog,
- int nReq,
- int *pbJump
-){
- /* Determine if it is necessary to add an LSM_LOG_JUMP to jump over the
- ** jump region before writing the LSM_LOG_WRITE or DELETE record. This
- ** is necessary if there is insufficient room between the current offset
- ** and the jump region to fit the new WRITE/DELETE record and the largest
- ** possible JUMP record with up to 7 bytes of padding (a total of 17
- ** bytes). */
- if( (pLog->jump.iStart > (pLog->iOff + pLog->buf.n))
- && (pLog->jump.iStart < (pLog->iOff + pLog->buf.n + (nReq + 17)))
- ){
- int rc; /* Return code */
- i64 iJump; /* Offset to jump to */
- u8 aJump[10]; /* Encoded jump record */
- int nJump; /* Valid bytes in aJump[] */
- int nPad; /* Bytes of padding required */
-
- /* Serialize the JUMP record */
- iJump = pLog->jump.iEnd+1;
- aJump[0] = LSM_LOG_JUMP;
- nJump = 1 + lsmVarintPut64(&aJump[1], iJump);
-
- /* Adding padding to the contents of the buffer so that it will be a
- ** multiple of 8 bytes in size after the JUMP record is appended. This
- ** is not strictly required, it just makes the keeping the running
- ** checksum up to date in this file a little simpler. */
- nPad = (pLog->buf.n + nJump) % 8;
- if( nPad ){
- u8 aPad[7] = {0,0,0,0,0,0,0};
- nPad = 8-nPad;
- if( nPad==1 ){
- aPad[0] = LSM_LOG_PAD1;
- }else{
- aPad[0] = LSM_LOG_PAD2;
- aPad[1] = (u8)(nPad-2);
- }
- rc = lsmStringBinAppend(&pLog->buf, aPad, nPad);
- if( rc!=LSM_OK ) return rc;
- }
-
- /* Append the JUMP record to the buffer. Then flush the buffer to disk
- ** and update the checksums. The next write to the log file (assuming
- ** there is no transaction rollback) will be to offset iJump (just past
- ** the jump region). */
- rc = lsmStringBinAppend(&pLog->buf, aJump, nJump);
- if( rc!=LSM_OK ) return rc;
- assert( (pLog->buf.n % 8)==0 );
- rc = lsmFsWriteLog(pDb->pFS, pLog->iOff, &pLog->buf);
- if( rc!=LSM_OK ) return rc;
- logUpdateCksum(pLog, pLog->buf.n);
- pLog->iRegion1End = (pLog->iOff + pLog->buf.n);
- pLog->iRegion2Start = iJump;
- pLog->iOff = iJump;
- pLog->iCksumBuf = pLog->buf.n = 0;
- if( pbJump ) *pbJump = 1;
- }
-
- return LSM_OK;
-}
-
-static int logCksumAndFlush(lsm_db *pDb){
- int rc; /* Return code */
- LogWriter *pLog = pDb->pLogWriter;
-
- /* Calculate the checksum value. Append it to the buffer. */
- logUpdateCksum(pLog, pLog->buf.n);
- lsmPutU32((u8 *)&pLog->buf.z[pLog->buf.n], pLog->cksum0);
- pLog->buf.n += 4;
- lsmPutU32((u8 *)&pLog->buf.z[pLog->buf.n], pLog->cksum1);
- pLog->buf.n += 4;
-
- /* Write the contents of the buffer to disk. */
- rc = lsmFsWriteLog(pDb->pFS, pLog->iOff, &pLog->buf);
- pLog->iOff += pLog->buf.n;
- pLog->iCksumBuf = pLog->buf.n = 0;
-
- return rc;
-}
-
-/*
-** Write the contents of the log-buffer to disk. Then write either a CKSUM
-** or COMMIT record, depending on the value of parameter eType.
-*/
-static int logFlush(lsm_db *pDb, int eType){
- int rc;
- int nReq;
- LogWriter *pLog = pDb->pLogWriter;
-
- assert( eType==LSM_LOG_COMMIT );
- assert( pLog );
-
- /* Commit record is always 9 bytes in size. */
- nReq = 9;
- if( eType==LSM_LOG_COMMIT && pLog->szSector>1 ) nReq += pLog->szSector + 17;
- rc = jumpIfRequired(pDb, pLog, nReq, 0);
-
- /* If this is a COMMIT, add padding to the log so that the COMMIT record
- ** is aligned against the end of a disk sector. In other words, add padding
- ** so that the first byte following the COMMIT record lies on a different
- ** sector. */
- if( eType==LSM_LOG_COMMIT && pLog->szSector>1 ){
- int nPad; /* Bytes of padding to add */
-
- /* Determine the value of nPad. */
- nPad = ((pLog->iOff + pLog->buf.n + 9) % pLog->szSector);
- if( nPad ) nPad = pLog->szSector - nPad;
- rc = lsmStringExtend(&pLog->buf, nPad);
- if( rc!=LSM_OK ) return rc;
-
- while( nPad ){
- if( nPad==1 ){
- pLog->buf.z[pLog->buf.n++] = LSM_LOG_PAD1;
- nPad = 0;
- }else{
- int n = LSM_MIN(200, nPad-2);
- pLog->buf.z[pLog->buf.n++] = LSM_LOG_PAD2;
- pLog->buf.z[pLog->buf.n++] = (char)n;
- nPad -= 2;
- memset(&pLog->buf.z[pLog->buf.n], 0x2B, n);
- pLog->buf.n += n;
- nPad -= n;
- }
- }
- }
-
- /* Make sure there is room in the log-buffer to add the CKSUM or COMMIT
- ** record. Then add the first byte of it. */
- rc = lsmStringExtend(&pLog->buf, 9);
- if( rc!=LSM_OK ) return rc;
- pLog->buf.z[pLog->buf.n++] = (char)eType;
- memset(&pLog->buf.z[pLog->buf.n], 0, 8);
-
- rc = logCksumAndFlush(pDb);
-
- /* If this is a commit and synchronous=full, sync the log to disk. */
- if( rc==LSM_OK && eType==LSM_LOG_COMMIT && pDb->eSafety==LSM_SAFETY_FULL ){
- rc = lsmFsSyncLog(pDb->pFS);
- }
- return rc;
-}
-
-/*
-** Append an LSM_LOG_WRITE (if nVal>=0) or LSM_LOG_DELETE (if nVal<0)
-** record to the database log.
-*/
-int lsmLogWrite(
- lsm_db *pDb, /* Database handle */
- int eType,
- void *pKey, int nKey, /* Database key to write to log */
- void *pVal, int nVal /* Database value (or nVal<0) to write */
-){
- int rc = LSM_OK;
- LogWriter *pLog; /* Log object to write to */
- int nReq; /* Bytes of space required in log */
- int bCksum = 0; /* True to embed a checksum in this record */
-
- assert( eType==LSM_WRITE || eType==LSM_DELETE || eType==LSM_DRANGE );
- assert( LSM_LOG_WRITE==LSM_WRITE );
- assert( LSM_LOG_DELETE==LSM_DELETE );
- assert( LSM_LOG_DRANGE==LSM_DRANGE );
- assert( (eType==LSM_LOG_DELETE)==(nVal<0) );
-
- if( pDb->bUseLog==0 ) return LSM_OK;
- pLog = pDb->pLogWriter;
-
- /* Determine how many bytes of space are required, assuming that a checksum
- ** will be embedded in this record (even though it may not be). */
- nReq = 1 + lsmVarintLen32(nKey) + 8 + nKey;
- if( eType!=LSM_LOG_DELETE ) nReq += lsmVarintLen32(nVal) + nVal;
-
- /* Jump over the jump region if required. Set bCksum to true to tell the
- ** code below to include a checksum in the record if either (a) writing
- ** this record would mean that more than LSM_CKSUM_MAXDATA bytes of data
- ** have been written to the log since the last checksum, or (b) the jump
- ** is taken. */
- rc = jumpIfRequired(pDb, pLog, nReq, &bCksum);
- if( (pLog->buf.n+nReq) > LSM_CKSUM_MAXDATA ) bCksum = 1;
-
- if( rc==LSM_OK ){
- rc = lsmStringExtend(&pLog->buf, nReq);
- }
- if( rc==LSM_OK ){
- u8 *a = (u8 *)&pLog->buf.z[pLog->buf.n];
-
- /* Write the record header - the type byte followed by either 1 (for
- ** DELETE) or 2 (for WRITE) varints. */
- assert( LSM_LOG_WRITE_CKSUM == (LSM_LOG_WRITE | 0x0001) );
- assert( LSM_LOG_DELETE_CKSUM == (LSM_LOG_DELETE | 0x0001) );
- assert( LSM_LOG_DRANGE_CKSUM == (LSM_LOG_DRANGE | 0x0001) );
- *(a++) = (u8)eType | (u8)bCksum;
- a += lsmVarintPut32(a, nKey);
- if( eType!=LSM_LOG_DELETE ) a += lsmVarintPut32(a, nVal);
-
- if( bCksum ){
- pLog->buf.n = (a - (u8 *)pLog->buf.z);
- rc = logCksumAndFlush(pDb);
- a = (u8 *)&pLog->buf.z[pLog->buf.n];
- }
-
- memcpy(a, pKey, nKey);
- a += nKey;
- if( eType!=LSM_LOG_DELETE ){
- memcpy(a, pVal, nVal);
- a += nVal;
- }
- pLog->buf.n = a - (u8 *)pLog->buf.z;
- assert( pLog->buf.n<=pLog->buf.nAlloc );
- }
-
- return rc;
-}
-
-/*
-** Append an LSM_LOG_COMMIT record to the database log.
-*/
-int lsmLogCommit(lsm_db *pDb){
- if( pDb->bUseLog==0 ) return LSM_OK;
- return logFlush(pDb, LSM_LOG_COMMIT);
-}
-
-/*
-** Store the current offset and other checksum related information in the
-** structure *pMark. Later, *pMark can be passed to lsmLogSeek() to "rewind"
-** the LogWriter object to the current log file offset. This is used when
-** rolling back savepoint transactions.
-*/
-void lsmLogTell(
- lsm_db *pDb, /* Database handle */
- LogMark *pMark /* Populate this object with current offset */
-){
- LogWriter *pLog;
- int nCksum;
-
- if( pDb->bUseLog==0 ) return;
- pLog = pDb->pLogWriter;
- nCksum = pLog->buf.n & 0xFFFFFFF8;
- logUpdateCksum(pLog, nCksum);
- assert( pLog->iCksumBuf==nCksum );
- pMark->nBuf = pLog->buf.n - nCksum;
- memcpy(pMark->aBuf, &pLog->buf.z[nCksum], pMark->nBuf);
-
- pMark->iOff = pLog->iOff + pLog->buf.n;
- pMark->cksum0 = pLog->cksum0;
- pMark->cksum1 = pLog->cksum1;
-}
-
-/*
-** Seek (rewind) back to the log file offset stored by an ealier call to
-** lsmLogTell() in *pMark.
-*/
-void lsmLogSeek(
- lsm_db *pDb, /* Database handle */
- LogMark *pMark /* Object containing log offset to seek to */
-){
- LogWriter *pLog;
-
- if( pDb->bUseLog==0 ) return;
- pLog = pDb->pLogWriter;
-
- assert( pMark->iOff<=pLog->iOff+pLog->buf.n );
- if( (pMark->iOff & 0xFFFFFFF8)>=pLog->iOff ){
- pLog->buf.n = (int)(pMark->iOff - pLog->iOff);
- pLog->iCksumBuf = (pLog->buf.n & 0xFFFFFFF8);
- }else{
- pLog->buf.n = pMark->nBuf;
- memcpy(pLog->buf.z, pMark->aBuf, pMark->nBuf);
- pLog->iCksumBuf = 0;
- pLog->iOff = pMark->iOff - pMark->nBuf;
- }
- pLog->cksum0 = pMark->cksum0;
- pLog->cksum1 = pMark->cksum1;
-
- if( pMark->iOff > pLog->iRegion1End ) pLog->iRegion1End = 0;
- if( pMark->iOff > pLog->iRegion2Start ) pLog->iRegion2Start = 0;
-}
-
-/*
-** This function does the work for an lsm_info(LOG_STRUCTURE) request.
-*/
-int lsmInfoLogStructure(lsm_db *pDb, char **pzVal){
- int rc = LSM_OK;
- char *zVal = 0;
-
- /* If there is no read or write transaction open, read the latest
- ** tree-header from shared-memory to report on. If necessary, update
- ** it based on the contents of the database header.
- **
- ** No locks are taken here - these are passive read operations only.
- */
- if( pDb->pCsr==0 && pDb->nTransOpen==0 ){
- rc = lsmTreeLoadHeader(pDb, 0);
- if( rc==LSM_OK ) rc = logReclaimSpace(pDb);
- }
-
- if( rc==LSM_OK ){
- DbLog *pLog = &pDb->treehdr.log;
- zVal = lsmMallocPrintf(pDb->pEnv,
- "%d %d %d %d %d %d",
- (int)pLog->aRegion[0].iStart, (int)pLog->aRegion[0].iEnd,
- (int)pLog->aRegion[1].iStart, (int)pLog->aRegion[1].iEnd,
- (int)pLog->aRegion[2].iStart, (int)pLog->aRegion[2].iEnd
- );
- if( !zVal ) rc = LSM_NOMEM_BKPT;
- }
-
- *pzVal = zVal;
- return rc;
-}
-
-/*************************************************************************
-** Begin code for log recovery.
-*/
-
-typedef struct LogReader LogReader;
-struct LogReader {
- FileSystem *pFS; /* File system to read from */
- i64 iOff; /* File offset at end of buf content */
- int iBuf; /* Current read offset in buf */
- LsmString buf; /* Buffer containing file content */
-
- int iCksumBuf; /* Offset in buf corresponding to cksum[01] */
- u32 cksum0; /* Checksum 0 at offset iCksumBuf */
- u32 cksum1; /* Checksum 1 at offset iCksumBuf */
-};
-
-static void logReaderBlob(
- LogReader *p, /* Log reader object */
- LsmString *pBuf, /* Dynamic storage, if required */
- int nBlob, /* Number of bytes to read */
- u8 **ppBlob, /* OUT: Pointer to blob read */
- int *pRc /* IN/OUT: Error code */
-){
- static const int LOG_READ_SIZE = 512;
- int rc = *pRc; /* Return code */
- int nReq = nBlob; /* Bytes required */
-
- while( rc==LSM_OK && nReq>0 ){
- int nAvail; /* Bytes of data available in p->buf */
- if( p->buf.n==p->iBuf ){
- int nCksum; /* Total bytes requiring checksum */
- int nCarry = 0; /* Total bytes requiring checksum */
-
- nCksum = p->iBuf - p->iCksumBuf;
- if( nCksum>0 ){
- nCarry = nCksum % 8;
- nCksum = ((nCksum / 8) * 8);
- if( nCksum>0 ){
- logCksumUnaligned(
- &p->buf.z[p->iCksumBuf], nCksum, &p->cksum0, &p->cksum1
- );
- }
- }
- if( nCarry>0 ) memcpy(p->buf.z, &p->buf.z[p->iBuf-nCarry], nCarry);
- p->buf.n = nCarry;
- p->iBuf = nCarry;
-
- rc = lsmFsReadLog(p->pFS, p->iOff, LOG_READ_SIZE, &p->buf);
- if( rc!=LSM_OK ) break;
- p->iCksumBuf = 0;
- p->iOff += LOG_READ_SIZE;
- }
-
- nAvail = p->buf.n - p->iBuf;
- if( ppBlob && nReq==nBlob && nBlob<=nAvail ){
- *ppBlob = (u8 *)&p->buf.z[p->iBuf];
- p->iBuf += nBlob;
- nReq = 0;
- }else{
- int nCopy = LSM_MIN(nAvail, nReq);
- if( nBlob==nReq ){
- pBuf->n = 0;
- }
- rc = lsmStringBinAppend(pBuf, (u8 *)&p->buf.z[p->iBuf], nCopy);
- nReq -= nCopy;
- p->iBuf += nCopy;
- if( nReq==0 && ppBlob ){
- *ppBlob = (u8*)pBuf->z;
- }
- }
- }
-
- *pRc = rc;
-}
-
-static void logReaderVarint(
- LogReader *p,
- LsmString *pBuf,
- int *piVal, /* OUT: Value read from log */
- int *pRc /* IN/OUT: Error code */
-){
- if( *pRc==LSM_OK ){
- u8 *aVarint;
- if( p->buf.n==p->iBuf ){
- logReaderBlob(p, 0, 10, &aVarint, pRc);
- if( LSM_OK==*pRc ) p->iBuf -= (10 - lsmVarintGet32(aVarint, piVal));
- }else{
- logReaderBlob(p, pBuf, lsmVarintSize(p->buf.z[p->iBuf]), &aVarint, pRc);
- if( LSM_OK==*pRc ) lsmVarintGet32(aVarint, piVal);
- }
- }
-}
-
-static void logReaderByte(LogReader *p, u8 *pByte, int *pRc){
- u8 *pPtr = 0;
- logReaderBlob(p, 0, 1, &pPtr, pRc);
- if( pPtr ) *pByte = *pPtr;
-}
-
-static void logReaderCksum(LogReader *p, LsmString *pBuf, int *pbEof, int *pRc){
- if( *pRc==LSM_OK ){
- u8 *pPtr = 0;
- u32 cksum0, cksum1;
- int nCksum = p->iBuf - p->iCksumBuf;
-
- /* Update in-memory (expected) checksums */
- assert( nCksum>=0 );
- logCksumUnaligned(&p->buf.z[p->iCksumBuf], nCksum, &p->cksum0, &p->cksum1);
- p->iCksumBuf = p->iBuf + 8;
- logReaderBlob(p, pBuf, 8, &pPtr, pRc);
- assert( pPtr || *pRc );
-
- /* Read the checksums from the log file. Set *pbEof if they do not match. */
- if( pPtr ){
- cksum0 = lsmGetU32(pPtr);
- cksum1 = lsmGetU32(&pPtr[4]);
- *pbEof = (cksum0!=p->cksum0 || cksum1!=p->cksum1);
- p->iCksumBuf = p->iBuf;
- }
- }
-}
-
-static void logReaderInit(
- lsm_db *pDb, /* Database handle */
- DbLog *pLog, /* Log object associated with pDb */
- int bInitBuf, /* True if p->buf is uninitialized */
- LogReader *p /* Initialize this LogReader object */
-){
- p->pFS = pDb->pFS;
- p->iOff = pLog->aRegion[2].iStart;
- p->cksum0 = pLog->cksum0;
- p->cksum1 = pLog->cksum1;
- if( bInitBuf ){ lsmStringInit(&p->buf, pDb->pEnv); }
- p->buf.n = 0;
- p->iCksumBuf = 0;
- p->iBuf = 0;
-}
-
-/*
-** This function is called after reading the header of a LOG_DELETE or
-** LOG_WRITE record. Parameter nByte is the total size of the key and
-** value that follow the header just read. Return true if the size and
-** position of the record indicate that it should contain a checksum.
-*/
-static int logRequireCksum(LogReader *p, int nByte){
- return ((p->iBuf + nByte - p->iCksumBuf) > LSM_CKSUM_MAXDATA);
-}
-
-/*
-** Recover the contents of the log file.
-*/
-int lsmLogRecover(lsm_db *pDb){
- LsmString buf1; /* Key buffer */
- LsmString buf2; /* Value buffer */
- LogReader reader; /* Log reader object */
- int rc = LSM_OK; /* Return code */
- int nCommit = 0; /* Number of transactions to recover */
- int iPass;
- int nJump = 0; /* Number of LSM_LOG_JUMP records in pass 0 */
- DbLog *pLog;
- int bOpen;
-
- rc = lsmFsOpenLog(pDb, &bOpen);
- if( rc!=LSM_OK ) return rc;
-
- rc = lsmTreeInit(pDb);
- if( rc!=LSM_OK ) return rc;
-
- pLog = &pDb->treehdr.log;
- lsmCheckpointLogoffset(pDb->pShmhdr->aSnap2, pLog);
-
- logReaderInit(pDb, pLog, 1, &reader);
- lsmStringInit(&buf1, pDb->pEnv);
- lsmStringInit(&buf2, pDb->pEnv);
-
- /* The outer for() loop runs at most twice. The first iteration is to
- ** count the number of committed transactions in the log. The second
- ** iterates through those transactions and updates the in-memory tree
- ** structure with their contents. */
- if( bOpen ){
- for(iPass=0; iPass<2 && rc==LSM_OK; iPass++){
- int bEof = 0;
-
- while( rc==LSM_OK && !bEof ){
- u8 eType = 0;
- logReaderByte(&reader, &eType, &rc);
-
- switch( eType ){
- case LSM_LOG_PAD1:
- break;
-
- case LSM_LOG_PAD2: {
- int nPad;
- logReaderVarint(&reader, &buf1, &nPad, &rc);
- logReaderBlob(&reader, &buf1, nPad, 0, &rc);
- break;
- }
-
- case LSM_LOG_DRANGE:
- case LSM_LOG_DRANGE_CKSUM:
- case LSM_LOG_WRITE:
- case LSM_LOG_WRITE_CKSUM: {
- int nKey;
- int nVal;
- u8 *aVal;
- logReaderVarint(&reader, &buf1, &nKey, &rc);
- logReaderVarint(&reader, &buf2, &nVal, &rc);
-
- if( eType==LSM_LOG_WRITE_CKSUM || eType==LSM_LOG_DRANGE_CKSUM ){
- logReaderCksum(&reader, &buf1, &bEof, &rc);
- }else{
- bEof = logRequireCksum(&reader, nKey+nVal);
- }
- if( bEof ) break;
-
- logReaderBlob(&reader, &buf1, nKey, 0, &rc);
- logReaderBlob(&reader, &buf2, nVal, &aVal, &rc);
- if( iPass==1 && rc==LSM_OK ){
- if( eType==LSM_LOG_WRITE || eType==LSM_LOG_WRITE_CKSUM ){
- rc = lsmTreeInsert(pDb, (u8 *)buf1.z, nKey, aVal, nVal);
- }else{
- rc = lsmTreeDelete(pDb, (u8 *)buf1.z, nKey, aVal, nVal);
- }
- }
- break;
- }
-
- case LSM_LOG_DELETE:
- case LSM_LOG_DELETE_CKSUM: {
- int nKey; u8 *aKey;
- logReaderVarint(&reader, &buf1, &nKey, &rc);
-
- if( eType==LSM_LOG_DELETE_CKSUM ){
- logReaderCksum(&reader, &buf1, &bEof, &rc);
- }else{
- bEof = logRequireCksum(&reader, nKey);
- }
- if( bEof ) break;
-
- logReaderBlob(&reader, &buf1, nKey, &aKey, &rc);
- if( iPass==1 && rc==LSM_OK ){
- rc = lsmTreeInsert(pDb, aKey, nKey, NULL, -1);
- }
- break;
- }
-
- case LSM_LOG_COMMIT:
- logReaderCksum(&reader, &buf1, &bEof, &rc);
- if( bEof==0 ){
- nCommit++;
- assert( nCommit>0 || iPass==1 );
- if( nCommit==0 ) bEof = 1;
- }
- break;
-
- case LSM_LOG_JUMP: {
- int iOff = 0;
- logReaderVarint(&reader, &buf1, &iOff, &rc);
- if( rc==LSM_OK ){
- if( iPass==1 ){
- if( pLog->aRegion[2].iStart==0 ){
- assert( pLog->aRegion[1].iStart==0 );
- pLog->aRegion[1].iEnd = reader.iOff;
- }else{
- assert( pLog->aRegion[0].iStart==0 );
- pLog->aRegion[0].iStart = pLog->aRegion[2].iStart;
- pLog->aRegion[0].iEnd = reader.iOff-reader.buf.n+reader.iBuf;
- }
- pLog->aRegion[2].iStart = iOff;
- }else{
- if( (nJump++)==2 ){
- bEof = 1;
- }
- }
-
- reader.iOff = iOff;
- reader.buf.n = reader.iBuf;
- }
- break;
- }
-
- default:
- /* Including LSM_LOG_EOF */
- bEof = 1;
- break;
- }
- }
-
- if( rc==LSM_OK && iPass==0 ){
- if( nCommit==0 ){
- if( pLog->aRegion[2].iStart==0 ){
- iPass = 1;
- }else{
- pLog->aRegion[2].iStart = 0;
- iPass = -1;
- lsmCheckpointZeroLogoffset(pDb);
- }
- }
- logReaderInit(pDb, pLog, 0, &reader);
- nCommit = nCommit * -1;
- }
- }
- }
-
- /* Initialize DbLog object */
- if( rc==LSM_OK ){
- pLog->aRegion[2].iEnd = reader.iOff - reader.buf.n + reader.iBuf;
- pLog->cksum0 = reader.cksum0;
- pLog->cksum1 = reader.cksum1;
- }
-
- if( rc==LSM_OK ){
- rc = lsmFinishRecovery(pDb);
- }else{
- lsmFinishRecovery(pDb);
- }
-
- if( pDb->bRoTrans ){
- lsmFsCloseLog(pDb);
- }
-
- lsmStringClear(&buf1);
- lsmStringClear(&buf2);
- lsmStringClear(&reader.buf);
- return rc;
-}
-
-void lsmLogClose(lsm_db *db){
- if( db->pLogWriter ){
- lsmFree(db->pEnv, db->pLogWriter->buf.z);
- lsmFree(db->pEnv, db->pLogWriter);
- db->pLogWriter = 0;
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_main.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_main.c
deleted file mode 100644
index a9c48e004e9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_main.c
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*
-** 2011-08-18
-**
-** 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.
-**
-*************************************************************************
-**
-** The main interface to the LSM module.
-*/
-#include "lsmInt.h"
-
-
-#ifdef LSM_DEBUG
-/*
-** This function returns a copy of its only argument.
-**
-** When the library is built with LSM_DEBUG defined, this function is called
-** whenever an error code is generated (not propagated - generated). So
-** if the library is mysteriously returning (say) LSM_IOERR, a breakpoint
-** may be set in this function to determine why.
-*/
-int lsmErrorBkpt(int rc){
- /* Set breakpoint here! */
- return rc;
-}
-
-/*
-** This function contains various assert() statements that test that the
-** lsm_db structure passed as an argument is internally consistent.
-*/
-static void assert_db_state(lsm_db *pDb){
-
- /* If there is at least one cursor or a write transaction open, the database
- ** handle must be holding a pointer to a client snapshot. And the reverse
- ** - if there are no open cursors and no write transactions then there must
- ** not be a client snapshot. */
-
- assert( (pDb->pCsr!=0||pDb->nTransOpen>0)==(pDb->iReader>=0||pDb->bRoTrans) );
-
- assert( (pDb->iReader<0 && pDb->bRoTrans==0) || pDb->pClient!=0 );
-
- assert( pDb->nTransOpen>=0 );
-}
-#else
-# define assert_db_state(x)
-#endif
-
-/*
-** The default key-compare function.
-*/
-static int xCmp(void *p1, int n1, void *p2, int n2){
- int res;
- res = memcmp(p1, p2, LSM_MIN(n1, n2));
- if( res==0 ) res = (n1-n2);
- return res;
-}
-
-static void xLog(void *pCtx, int rc, const char *z){
- (void)(rc);
- (void)(pCtx);
- fprintf(stderr, "%s\n", z);
- fflush(stderr);
-}
-
-/*
-** Allocate a new db handle.
-*/
-int lsm_new(lsm_env *pEnv, lsm_db **ppDb){
- lsm_db *pDb;
-
- /* If the user did not provide an environment, use the default. */
- if( pEnv==0 ) pEnv = lsm_default_env();
- assert( pEnv );
-
- /* Allocate the new database handle */
- *ppDb = pDb = (lsm_db *)lsmMallocZero(pEnv, sizeof(lsm_db));
- if( pDb==0 ) return LSM_NOMEM_BKPT;
-
- /* Initialize the new object */
- pDb->pEnv = pEnv;
- pDb->nTreeLimit = LSM_DFLT_AUTOFLUSH;
- pDb->nAutockpt = LSM_DFLT_AUTOCHECKPOINT;
- pDb->bAutowork = LSM_DFLT_AUTOWORK;
- pDb->eSafety = LSM_DFLT_SAFETY;
- pDb->xCmp = xCmp;
- pDb->nDfltPgsz = LSM_DFLT_PAGE_SIZE;
- pDb->nDfltBlksz = LSM_DFLT_BLOCK_SIZE;
- pDb->nMerge = LSM_DFLT_AUTOMERGE;
- pDb->nMaxFreelist = LSM_MAX_FREELIST_ENTRIES;
- pDb->bUseLog = LSM_DFLT_USE_LOG;
- pDb->iReader = -1;
- pDb->iRwclient = -1;
- pDb->bMultiProc = LSM_DFLT_MULTIPLE_PROCESSES;
- pDb->iMmap = LSM_DFLT_MMAP;
- pDb->xLog = xLog;
- pDb->compress.iId = LSM_COMPRESSION_NONE;
- return LSM_OK;
-}
-
-lsm_env *lsm_get_env(lsm_db *pDb){
- assert( pDb->pEnv );
- return pDb->pEnv;
-}
-
-/*
-** If database handle pDb is currently holding a client snapshot, but does
-** not have any open cursors or write transactions, release it.
-*/
-static void dbReleaseClientSnapshot(lsm_db *pDb){
- if( pDb->nTransOpen==0 && pDb->pCsr==0 ){
- lsmFinishReadTrans(pDb);
- }
-}
-
-static int getFullpathname(
- lsm_env *pEnv,
- const char *zRel,
- char **pzAbs
-){
- int nAlloc = 0;
- char *zAlloc = 0;
- int nReq = 0;
- int rc;
-
- do{
- nAlloc = nReq;
- rc = pEnv->xFullpath(pEnv, zRel, zAlloc, &nReq);
- if( nReq>nAlloc ){
- zAlloc = lsmReallocOrFreeRc(pEnv, zAlloc, nReq, &rc);
- }
- }while( nReq>nAlloc && rc==LSM_OK );
-
- if( rc!=LSM_OK ){
- lsmFree(pEnv, zAlloc);
- zAlloc = 0;
- }
- *pzAbs = zAlloc;
- return rc;
-}
-
-/*
-** Check that the bits in the db->mLock mask are consistent with the
-** value stored in db->iRwclient. An assert shall fail otherwise.
-*/
-static void assertRwclientLockValue(lsm_db *db){
-#ifndef NDEBUG
- u64 msk; /* Mask of mLock bits for RWCLIENT locks */
- u64 rwclient = 0; /* Bit corresponding to db->iRwclient */
-
- if( db->iRwclient>=0 ){
- rwclient = ((u64)1 << (LSM_LOCK_RWCLIENT(db->iRwclient)-1));
- }
- msk = ((u64)1 << (LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT)-1)) - 1;
- msk -= (((u64)1 << (LSM_LOCK_RWCLIENT(0)-1)) - 1);
-
- assert( (db->mLock & msk)==rwclient );
-#endif
-}
-
-/*
-** Open a new connection to database zFilename.
-*/
-int lsm_open(lsm_db *pDb, const char *zFilename){
- int rc;
-
- if( pDb->pDatabase ){
- rc = LSM_MISUSE;
- }else{
- char *zFull;
-
- /* Translate the possibly relative pathname supplied by the user into
- ** an absolute pathname. This is required because the supplied path
- ** is used (either directly or with "-log" appended to it) for more
- ** than one purpose - to open both the database and log files, and
- ** perhaps to unlink the log file during disconnection. An absolute
- ** path is required to ensure that the correct files are operated
- ** on even if the application changes the cwd. */
- rc = getFullpathname(pDb->pEnv, zFilename, &zFull);
- assert( rc==LSM_OK || zFull==0 );
-
- /* Connect to the database. */
- if( rc==LSM_OK ){
- rc = lsmDbDatabaseConnect(pDb, zFull);
- }
-
- if( pDb->bReadonly==0 ){
- /* Configure the file-system connection with the page-size and block-size
- ** of this database. Even if the database file is zero bytes in size
- ** on disk, these values have been set in shared-memory by now, and so
- ** are guaranteed not to change during the lifetime of this connection.
- */
- if( rc==LSM_OK && LSM_OK==(rc = lsmCheckpointLoad(pDb, 0)) ){
- lsmFsSetPageSize(pDb->pFS, lsmCheckpointPgsz(pDb->aSnapshot));
- lsmFsSetBlockSize(pDb->pFS, lsmCheckpointBlksz(pDb->aSnapshot));
- }
- }
-
- lsmFree(pDb->pEnv, zFull);
- assertRwclientLockValue(pDb);
- }
-
- assert( pDb->bReadonly==0 || pDb->bReadonly==1 );
- assert( rc!=LSM_OK || (pDb->pShmhdr==0)==(pDb->bReadonly==1) );
-
- return rc;
-}
-
-int lsm_close(lsm_db *pDb){
- int rc = LSM_OK;
- if( pDb ){
- assert_db_state(pDb);
- if( pDb->pCsr || pDb->nTransOpen ){
- rc = LSM_MISUSE_BKPT;
- }else{
- lsmMCursorFreeCache(pDb);
- lsmFreeSnapshot(pDb->pEnv, pDb->pClient);
- pDb->pClient = 0;
-
- assertRwclientLockValue(pDb);
-
- lsmDbDatabaseRelease(pDb);
- lsmLogClose(pDb);
- lsmFsClose(pDb->pFS);
- /* assert( pDb->mLock==0 ); */
-
- /* Invoke any destructors registered for the compression or
- ** compression factory callbacks. */
- if( pDb->factory.xFree ) pDb->factory.xFree(pDb->factory.pCtx);
- if( pDb->compress.xFree ) pDb->compress.xFree(pDb->compress.pCtx);
-
- lsmFree(pDb->pEnv, pDb->rollback.aArray);
- lsmFree(pDb->pEnv, pDb->aTrans);
- lsmFree(pDb->pEnv, pDb->apShm);
- lsmFree(pDb->pEnv, pDb);
- }
- }
- return rc;
-}
-
-int lsm_config(lsm_db *pDb, int eParam, ...){
- int rc = LSM_OK;
- va_list ap;
- va_start(ap, eParam);
-
- switch( eParam ){
- case LSM_CONFIG_AUTOFLUSH: {
- /* This parameter is read and written in KB. But all internal
- ** processing is done in bytes. */
- int *piVal = va_arg(ap, int *);
- int iVal = *piVal;
- if( iVal>=0 && iVal<=(1024*1024) ){
- pDb->nTreeLimit = iVal*1024;
- }
- *piVal = (pDb->nTreeLimit / 1024);
- break;
- }
-
- case LSM_CONFIG_AUTOWORK: {
- int *piVal = va_arg(ap, int *);
- if( *piVal>=0 ){
- pDb->bAutowork = *piVal;
- }
- *piVal = pDb->bAutowork;
- break;
- }
-
- case LSM_CONFIG_AUTOCHECKPOINT: {
- /* This parameter is read and written in KB. But all internal processing
- ** (including the lsm_db.nAutockpt variable) is done in bytes. */
- int *piVal = va_arg(ap, int *);
- if( *piVal>=0 ){
- int iVal = *piVal;
- pDb->nAutockpt = (i64)iVal * 1024;
- }
- *piVal = (int)(pDb->nAutockpt / 1024);
- break;
- }
-
- case LSM_CONFIG_PAGE_SIZE: {
- int *piVal = va_arg(ap, int *);
- if( pDb->pDatabase ){
- /* If lsm_open() has been called, this is a read-only parameter.
- ** Set the output variable to the page-size according to the
- ** FileSystem object. */
- *piVal = lsmFsPageSize(pDb->pFS);
- }else{
- if( *piVal>=256 && *piVal<=65536 && ((*piVal-1) & *piVal)==0 ){
- pDb->nDfltPgsz = *piVal;
- }else{
- *piVal = pDb->nDfltPgsz;
- }
- }
- break;
- }
-
- case LSM_CONFIG_BLOCK_SIZE: {
- /* This parameter is read and written in KB. But all internal
- ** processing is done in bytes. */
- int *piVal = va_arg(ap, int *);
- if( pDb->pDatabase ){
- /* If lsm_open() has been called, this is a read-only parameter.
- ** Set the output variable to the block-size in KB according to the
- ** FileSystem object. */
- *piVal = lsmFsBlockSize(pDb->pFS) / 1024;
- }else{
- int iVal = *piVal;
- if( iVal>=64 && iVal<=65536 && ((iVal-1) & iVal)==0 ){
- pDb->nDfltBlksz = iVal * 1024;
- }else{
- *piVal = pDb->nDfltBlksz / 1024;
- }
- }
- break;
- }
-
- case LSM_CONFIG_SAFETY: {
- int *piVal = va_arg(ap, int *);
- if( *piVal>=0 && *piVal<=2 ){
- pDb->eSafety = *piVal;
- }
- *piVal = pDb->eSafety;
- break;
- }
-
- case LSM_CONFIG_MMAP: {
- int *piVal = va_arg(ap, int *);
- if( pDb->iReader<0 && *piVal>=0 ){
- pDb->iMmap = *piVal;
- rc = lsmFsConfigure(pDb);
- }
- *piVal = pDb->iMmap;
- break;
- }
-
- case LSM_CONFIG_USE_LOG: {
- int *piVal = va_arg(ap, int *);
- if( pDb->nTransOpen==0 && (*piVal==0 || *piVal==1) ){
- pDb->bUseLog = *piVal;
- }
- *piVal = pDb->bUseLog;
- break;
- }
-
- case LSM_CONFIG_AUTOMERGE: {
- int *piVal = va_arg(ap, int *);
- if( *piVal>1 ) pDb->nMerge = *piVal;
- *piVal = pDb->nMerge;
- break;
- }
-
- case LSM_CONFIG_MAX_FREELIST: {
- int *piVal = va_arg(ap, int *);
- if( *piVal>=2 && *piVal<=LSM_MAX_FREELIST_ENTRIES ){
- pDb->nMaxFreelist = *piVal;
- }
- *piVal = pDb->nMaxFreelist;
- break;
- }
-
- case LSM_CONFIG_MULTIPLE_PROCESSES: {
- int *piVal = va_arg(ap, int *);
- if( pDb->pDatabase ){
- /* If lsm_open() has been called, this is a read-only parameter.
- ** Set the output variable to true if this connection is currently
- ** in multi-process mode. */
- *piVal = lsmDbMultiProc(pDb);
- }else{
- pDb->bMultiProc = *piVal = (*piVal!=0);
- }
- break;
- }
-
- case LSM_CONFIG_READONLY: {
- int *piVal = va_arg(ap, int *);
- /* If lsm_open() has been called, this is a read-only parameter. */
- if( pDb->pDatabase==0 && *piVal>=0 ){
- pDb->bReadonly = *piVal = (*piVal!=0);
- }
- *piVal = pDb->bReadonly;
- break;
- }
-
- case LSM_CONFIG_SET_COMPRESSION: {
- lsm_compress *p = va_arg(ap, lsm_compress *);
- if( pDb->iReader>=0 && pDb->bInFactory==0 ){
- /* May not change compression schemes with an open transaction */
- rc = LSM_MISUSE_BKPT;
- }else{
- if( pDb->compress.xFree ){
- /* Invoke any destructor belonging to the current compression. */
- pDb->compress.xFree(pDb->compress.pCtx);
- }
- if( p->xBound==0 ){
- memset(&pDb->compress, 0, sizeof(lsm_compress));
- pDb->compress.iId = LSM_COMPRESSION_NONE;
- }else{
- memcpy(&pDb->compress, p, sizeof(lsm_compress));
- }
- rc = lsmFsConfigure(pDb);
- }
- break;
- }
-
- case LSM_CONFIG_SET_COMPRESSION_FACTORY: {
- lsm_compress_factory *p = va_arg(ap, lsm_compress_factory *);
- if( pDb->factory.xFree ){
- /* Invoke any destructor belonging to the current factory. */
- pDb->factory.xFree(pDb->factory.pCtx);
- }
- memcpy(&pDb->factory, p, sizeof(lsm_compress_factory));
- break;
- }
-
- case LSM_CONFIG_GET_COMPRESSION: {
- lsm_compress *p = va_arg(ap, lsm_compress *);
- memcpy(p, &pDb->compress, sizeof(lsm_compress));
- break;
- }
-
- default:
- rc = LSM_MISUSE;
- break;
- }
-
- va_end(ap);
- return rc;
-}
-
-void lsmAppendSegmentList(LsmString *pStr, char *zPre, Segment *pSeg){
- lsmStringAppendf(pStr, "%s{%d %d %d %d}", zPre,
- pSeg->iFirst, pSeg->iLastPg, pSeg->iRoot, pSeg->nSize
- );
-}
-
-static int infoGetWorker(lsm_db *pDb, Snapshot **pp, int *pbUnlock){
- int rc = LSM_OK;
-
- assert( *pbUnlock==0 );
- if( !pDb->pWorker ){
- rc = lsmBeginWork(pDb);
- if( rc!=LSM_OK ) return rc;
- *pbUnlock = 1;
- }
- if( pp ) *pp = pDb->pWorker;
- return rc;
-}
-
-static void infoFreeWorker(lsm_db *pDb, int bUnlock){
- if( bUnlock ){
- int rcdummy = LSM_BUSY;
- lsmFinishWork(pDb, 0, &rcdummy);
- }
-}
-
-int lsmStructList(
- lsm_db *pDb, /* Database handle */
- char **pzOut /* OUT: Nul-terminated string (tcl list) */
-){
- Level *pTopLevel = 0; /* Top level of snapshot to report on */
- int rc = LSM_OK;
- Level *p;
- LsmString s;
- Snapshot *pWorker; /* Worker snapshot */
- int bUnlock = 0;
-
- /* Obtain the worker snapshot */
- rc = infoGetWorker(pDb, &pWorker, &bUnlock);
- if( rc!=LSM_OK ) return rc;
-
- /* Format the contents of the snapshot as text */
- pTopLevel = lsmDbSnapshotLevel(pWorker);
- lsmStringInit(&s, pDb->pEnv);
- for(p=pTopLevel; rc==LSM_OK && p; p=p->pNext){
- int i;
- lsmStringAppendf(&s, "%s{%d", (s.n ? " " : ""), (int)p->iAge);
- lsmAppendSegmentList(&s, " ", &p->lhs);
- for(i=0; rc==LSM_OK && i<p->nRight; i++){
- lsmAppendSegmentList(&s, " ", &p->aRhs[i]);
- }
- lsmStringAppend(&s, "}", 1);
- }
- rc = s.n>=0 ? LSM_OK : LSM_NOMEM;
-
- /* Release the snapshot and return */
- infoFreeWorker(pDb, bUnlock);
- *pzOut = s.z;
- return rc;
-}
-
-static int infoFreelistCb(void *pCtx, int iBlk, i64 iSnapshot){
- LsmString *pStr = (LsmString *)pCtx;
- lsmStringAppendf(pStr, "%s{%d %lld}", (pStr->n?" ":""), iBlk, iSnapshot);
- return 0;
-}
-
-int lsmInfoFreelist(lsm_db *pDb, char **pzOut){
- Snapshot *pWorker; /* Worker snapshot */
- int bUnlock = 0;
- LsmString s;
- int rc;
-
- /* Obtain the worker snapshot */
- rc = infoGetWorker(pDb, &pWorker, &bUnlock);
- if( rc!=LSM_OK ) return rc;
-
- lsmStringInit(&s, pDb->pEnv);
- rc = lsmWalkFreelist(pDb, 0, infoFreelistCb, &s);
- if( rc!=LSM_OK ){
- lsmFree(pDb->pEnv, s.z);
- }else{
- *pzOut = s.z;
- }
-
- /* Release the snapshot and return */
- infoFreeWorker(pDb, bUnlock);
- return rc;
-}
-
-static int infoTreeSize(lsm_db *db, int *pnOldKB, int *pnNewKB){
- ShmHeader *pShm = db->pShmhdr;
- TreeHeader *p = &pShm->hdr1;
-
- /* The following code suffers from two race conditions, as it accesses and
- ** trusts the contents of shared memory without verifying checksums:
- **
- ** * The two values read - TreeHeader.root.nByte and oldroot.nByte - are
- ** 32-bit fields. It is assumed that reading from one of these
- ** is atomic - that it is not possible to read a partially written
- ** garbage value. However the two values may be mutually inconsistent.
- **
- ** * TreeHeader.iLogOff is a 64-bit value. And lsmCheckpointLogOffset()
- ** reads a 64-bit value from a snapshot stored in shared memory. It
- ** is assumed that in each case it is possible to read a partially
- ** written garbage value. If this occurs, then the value returned
- ** for the size of the "old" tree may reflect the size of an "old"
- ** tree that was recently flushed to disk.
- **
- ** Given the context in which this function is called (as a result of an
- ** lsm_info(LSM_INFO_TREE_SIZE) request), neither of these are considered to
- ** be problems.
- */
- *pnNewKB = ((int)p->root.nByte + 1023) / 1024;
- if( p->iOldShmid ){
- if( p->iOldLog==lsmCheckpointLogOffset(pShm->aSnap1) ){
- *pnOldKB = 0;
- }else{
- *pnOldKB = ((int)p->oldroot.nByte + 1023) / 1024;
- }
- }else{
- *pnOldKB = 0;
- }
-
- return LSM_OK;
-}
-
-int lsm_info(lsm_db *pDb, int eParam, ...){
- int rc = LSM_OK;
- va_list ap;
- va_start(ap, eParam);
-
- switch( eParam ){
- case LSM_INFO_NWRITE: {
- int *piVal = va_arg(ap, int *);
- *piVal = lsmFsNWrite(pDb->pFS);
- break;
- }
-
- case LSM_INFO_NREAD: {
- int *piVal = va_arg(ap, int *);
- *piVal = lsmFsNRead(pDb->pFS);
- break;
- }
-
- case LSM_INFO_DB_STRUCTURE: {
- char **pzVal = va_arg(ap, char **);
- rc = lsmStructList(pDb, pzVal);
- break;
- }
-
- case LSM_INFO_ARRAY_STRUCTURE: {
- LsmPgno pgno = va_arg(ap, LsmPgno);
- char **pzVal = va_arg(ap, char **);
- rc = lsmInfoArrayStructure(pDb, 0, pgno, pzVal);
- break;
- }
-
- case LSM_INFO_ARRAY_PAGES: {
- LsmPgno pgno = va_arg(ap, LsmPgno);
- char **pzVal = va_arg(ap, char **);
- rc = lsmInfoArrayPages(pDb, pgno, pzVal);
- break;
- }
-
- case LSM_INFO_PAGE_HEX_DUMP:
- case LSM_INFO_PAGE_ASCII_DUMP: {
- LsmPgno pgno = va_arg(ap, LsmPgno);
- char **pzVal = va_arg(ap, char **);
- int bUnlock = 0;
- rc = infoGetWorker(pDb, 0, &bUnlock);
- if( rc==LSM_OK ){
- int bHex = (eParam==LSM_INFO_PAGE_HEX_DUMP);
- rc = lsmInfoPageDump(pDb, pgno, bHex, pzVal);
- }
- infoFreeWorker(pDb, bUnlock);
- break;
- }
-
- case LSM_INFO_LOG_STRUCTURE: {
- char **pzVal = va_arg(ap, char **);
- rc = lsmInfoLogStructure(pDb, pzVal);
- break;
- }
-
- case LSM_INFO_FREELIST: {
- char **pzVal = va_arg(ap, char **);
- rc = lsmInfoFreelist(pDb, pzVal);
- break;
- }
-
- case LSM_INFO_CHECKPOINT_SIZE: {
- int *pnKB = va_arg(ap, int *);
- rc = lsmCheckpointSize(pDb, pnKB);
- break;
- }
-
- case LSM_INFO_TREE_SIZE: {
- int *pnOld = va_arg(ap, int *);
- int *pnNew = va_arg(ap, int *);
- rc = infoTreeSize(pDb, pnOld, pnNew);
- break;
- }
-
- case LSM_INFO_COMPRESSION_ID: {
- unsigned int *piOut = va_arg(ap, unsigned int *);
- if( pDb->pClient ){
- *piOut = pDb->pClient->iCmpId;
- }else{
- rc = lsmInfoCompressionId(pDb, piOut);
- }
- break;
- }
-
- default:
- rc = LSM_MISUSE;
- break;
- }
-
- va_end(ap);
- return rc;
-}
-
-static int doWriteOp(
- lsm_db *pDb,
- int bDeleteRange,
- const void *pKey, int nKey, /* Key to write or delete */
- const void *pVal, int nVal /* Value to write. Or nVal==-1 for a delete */
-){
- int rc = LSM_OK; /* Return code */
- int bCommit = 0; /* True to commit before returning */
-
- if( pDb->nTransOpen==0 ){
- bCommit = 1;
- rc = lsm_begin(pDb, 1);
- }
-
- if( rc==LSM_OK ){
- int eType = (bDeleteRange ? LSM_DRANGE : (nVal>=0?LSM_WRITE:LSM_DELETE));
- rc = lsmLogWrite(pDb, eType, (void *)pKey, nKey, (void *)pVal, nVal);
- }
-
- lsmSortedSaveTreeCursors(pDb);
-
- if( rc==LSM_OK ){
- int pgsz = lsmFsPageSize(pDb->pFS);
- int nQuant = LSM_AUTOWORK_QUANT * pgsz;
- int nBefore;
- int nAfter;
- int nDiff;
-
- if( nQuant>pDb->nTreeLimit ){
- nQuant = LSM_MAX(pDb->nTreeLimit, pgsz);
- }
-
- nBefore = lsmTreeSize(pDb);
- if( bDeleteRange ){
- rc = lsmTreeDelete(pDb, (void *)pKey, nKey, (void *)pVal, nVal);
- }else{
- rc = lsmTreeInsert(pDb, (void *)pKey, nKey, (void *)pVal, nVal);
- }
-
- nAfter = lsmTreeSize(pDb);
- nDiff = (nAfter/nQuant) - (nBefore/nQuant);
- if( rc==LSM_OK && pDb->bAutowork && nDiff!=0 ){
- rc = lsmSortedAutoWork(pDb, nDiff * LSM_AUTOWORK_QUANT);
- }
- }
-
- /* If a transaction was opened at the start of this function, commit it.
- ** Or, if an error has occurred, roll it back. */
- if( bCommit ){
- if( rc==LSM_OK ){
- rc = lsm_commit(pDb, 0);
- }else{
- lsm_rollback(pDb, 0);
- }
- }
-
- return rc;
-}
-
-/*
-** Write a new value into the database.
-*/
-int lsm_insert(
- lsm_db *db, /* Database connection */
- const void *pKey, int nKey, /* Key to write or delete */
- const void *pVal, int nVal /* Value to write. Or nVal==-1 for a delete */
-){
- return doWriteOp(db, 0, pKey, nKey, pVal, nVal);
-}
-
-/*
-** Delete a value from the database.
-*/
-int lsm_delete(lsm_db *db, const void *pKey, int nKey){
- return doWriteOp(db, 0, pKey, nKey, 0, -1);
-}
-
-/*
-** Delete a range of database keys.
-*/
-int lsm_delete_range(
- lsm_db *db, /* Database handle */
- const void *pKey1, int nKey1, /* Lower bound of range to delete */
- const void *pKey2, int nKey2 /* Upper bound of range to delete */
-){
- int rc = LSM_OK;
- if( db->xCmp((void *)pKey1, nKey1, (void *)pKey2, nKey2)<0 ){
- rc = doWriteOp(db, 1, pKey1, nKey1, pKey2, nKey2);
- }
- return rc;
-}
-
-/*
-** Open a new cursor handle.
-**
-** If there are currently no other open cursor handles, and no open write
-** transaction, open a read transaction here.
-*/
-int lsm_csr_open(lsm_db *pDb, lsm_cursor **ppCsr){
- int rc = LSM_OK; /* Return code */
- MultiCursor *pCsr = 0; /* New cursor object */
-
- /* Open a read transaction if one is not already open. */
- assert_db_state(pDb);
-
- if( pDb->pShmhdr==0 ){
- assert( pDb->bReadonly );
- rc = lsmBeginRoTrans(pDb);
- }else if( pDb->iReader<0 ){
- rc = lsmBeginReadTrans(pDb);
- }
-
- /* Allocate the multi-cursor. */
- if( rc==LSM_OK ){
- rc = lsmMCursorNew(pDb, &pCsr);
- }
-
- /* If an error has occured, set the output to NULL and delete any partially
- ** allocated cursor. If this means there are no open cursors, release the
- ** client snapshot. */
- if( rc!=LSM_OK ){
- lsmMCursorClose(pCsr, 0);
- dbReleaseClientSnapshot(pDb);
- }
-
- assert_db_state(pDb);
- *ppCsr = (lsm_cursor *)pCsr;
- return rc;
-}
-
-/*
-** Close a cursor opened using lsm_csr_open().
-*/
-int lsm_csr_close(lsm_cursor *p){
- if( p ){
- lsm_db *pDb = lsmMCursorDb((MultiCursor *)p);
- assert_db_state(pDb);
- lsmMCursorClose((MultiCursor *)p, 1);
- dbReleaseClientSnapshot(pDb);
- assert_db_state(pDb);
- }
- return LSM_OK;
-}
-
-/*
-** Attempt to seek the cursor to the database entry specified by pKey/nKey.
-** If an error occurs (e.g. an OOM or IO error), return an LSM error code.
-** Otherwise, return LSM_OK.
-*/
-int lsm_csr_seek(lsm_cursor *pCsr, const void *pKey, int nKey, int eSeek){
- return lsmMCursorSeek((MultiCursor *)pCsr, 0, (void *)pKey, nKey, eSeek);
-}
-
-int lsm_csr_next(lsm_cursor *pCsr){
- return lsmMCursorNext((MultiCursor *)pCsr);
-}
-
-int lsm_csr_prev(lsm_cursor *pCsr){
- return lsmMCursorPrev((MultiCursor *)pCsr);
-}
-
-int lsm_csr_first(lsm_cursor *pCsr){
- return lsmMCursorFirst((MultiCursor *)pCsr);
-}
-
-int lsm_csr_last(lsm_cursor *pCsr){
- return lsmMCursorLast((MultiCursor *)pCsr);
-}
-
-int lsm_csr_valid(lsm_cursor *pCsr){
- return lsmMCursorValid((MultiCursor *)pCsr);
-}
-
-int lsm_csr_key(lsm_cursor *pCsr, const void **ppKey, int *pnKey){
- return lsmMCursorKey((MultiCursor *)pCsr, (void **)ppKey, pnKey);
-}
-
-int lsm_csr_value(lsm_cursor *pCsr, const void **ppVal, int *pnVal){
- return lsmMCursorValue((MultiCursor *)pCsr, (void **)ppVal, pnVal);
-}
-
-void lsm_config_log(
- lsm_db *pDb,
- void (*xLog)(void *, int, const char *),
- void *pCtx
-){
- pDb->xLog = xLog;
- pDb->pLogCtx = pCtx;
-}
-
-void lsm_config_work_hook(
- lsm_db *pDb,
- void (*xWork)(lsm_db *, void *),
- void *pCtx
-){
- pDb->xWork = xWork;
- pDb->pWorkCtx = pCtx;
-}
-
-void lsmLogMessage(lsm_db *pDb, int rc, const char *zFormat, ...){
- if( pDb->xLog ){
- LsmString s;
- va_list ap, ap2;
- lsmStringInit(&s, pDb->pEnv);
- va_start(ap, zFormat);
- va_start(ap2, zFormat);
- lsmStringVAppendf(&s, zFormat, ap, ap2);
- va_end(ap);
- va_end(ap2);
- pDb->xLog(pDb->pLogCtx, rc, s.z);
- lsmStringClear(&s);
- }
-}
-
-int lsm_begin(lsm_db *pDb, int iLevel){
- int rc;
-
- assert_db_state( pDb );
- rc = (pDb->bReadonly ? LSM_READONLY : LSM_OK);
-
- /* A value less than zero means open one more transaction. */
- if( iLevel<0 ) iLevel = pDb->nTransOpen + 1;
- if( iLevel>pDb->nTransOpen ){
- int i;
-
- /* Extend the pDb->aTrans[] array if required. */
- if( rc==LSM_OK && pDb->nTransAlloc<iLevel ){
- TransMark *aNew; /* New allocation */
- int nByte = sizeof(TransMark) * (iLevel+1);
- aNew = (TransMark *)lsmRealloc(pDb->pEnv, pDb->aTrans, nByte);
- if( !aNew ){
- rc = LSM_NOMEM;
- }else{
- nByte = sizeof(TransMark) * (iLevel+1 - pDb->nTransAlloc);
- memset(&aNew[pDb->nTransAlloc], 0, nByte);
- pDb->nTransAlloc = iLevel+1;
- pDb->aTrans = aNew;
- }
- }
-
- if( rc==LSM_OK && pDb->nTransOpen==0 ){
- rc = lsmBeginWriteTrans(pDb);
- }
-
- if( rc==LSM_OK ){
- for(i=pDb->nTransOpen; i<iLevel; i++){
- lsmTreeMark(pDb, &pDb->aTrans[i].tree);
- lsmLogTell(pDb, &pDb->aTrans[i].log);
- }
- pDb->nTransOpen = iLevel;
- }
- }
-
- return rc;
-}
-
-int lsm_commit(lsm_db *pDb, int iLevel){
- int rc = LSM_OK;
-
- assert_db_state( pDb );
-
- /* A value less than zero means close the innermost nested transaction. */
- if( iLevel<0 ) iLevel = LSM_MAX(0, pDb->nTransOpen - 1);
-
- if( iLevel<pDb->nTransOpen ){
- if( iLevel==0 ){
- int rc2;
- /* Commit the transaction to disk. */
- if( rc==LSM_OK ) rc = lsmLogCommit(pDb);
- if( rc==LSM_OK && pDb->eSafety==LSM_SAFETY_FULL ){
- rc = lsmFsSyncLog(pDb->pFS);
- }
- rc2 = lsmFinishWriteTrans(pDb, (rc==LSM_OK));
- if( rc==LSM_OK ) rc = rc2;
- }
- pDb->nTransOpen = iLevel;
- }
- dbReleaseClientSnapshot(pDb);
- return rc;
-}
-
-int lsm_rollback(lsm_db *pDb, int iLevel){
- int rc = LSM_OK;
- assert_db_state( pDb );
-
- if( pDb->nTransOpen ){
- /* A value less than zero means close the innermost nested transaction. */
- if( iLevel<0 ) iLevel = LSM_MAX(0, pDb->nTransOpen - 1);
-
- if( iLevel<=pDb->nTransOpen ){
- TransMark *pMark = &pDb->aTrans[(iLevel==0 ? 0 : iLevel-1)];
- lsmTreeRollback(pDb, &pMark->tree);
- if( iLevel ) lsmLogSeek(pDb, &pMark->log);
- pDb->nTransOpen = iLevel;
- }
-
- if( pDb->nTransOpen==0 ){
- lsmFinishWriteTrans(pDb, 0);
- }
- dbReleaseClientSnapshot(pDb);
- }
-
- return rc;
-}
-
-int lsm_get_user_version(lsm_db *pDb, unsigned int *piUsr){
- int rc = LSM_OK; /* Return code */
-
- /* Open a read transaction if one is not already open. */
- assert_db_state(pDb);
- if( pDb->pShmhdr==0 ){
- assert( pDb->bReadonly );
- rc = lsmBeginRoTrans(pDb);
- }else if( pDb->iReader<0 ){
- rc = lsmBeginReadTrans(pDb);
- }
-
- /* Allocate the multi-cursor. */
- if( rc==LSM_OK ){
- *piUsr = pDb->treehdr.iUsrVersion;
- }
-
- dbReleaseClientSnapshot(pDb);
- assert_db_state(pDb);
- return rc;
-}
-
-int lsm_set_user_version(lsm_db *pDb, unsigned int iUsr){
- int rc = LSM_OK; /* Return code */
- int bCommit = 0; /* True to commit before returning */
-
- if( pDb->nTransOpen==0 ){
- bCommit = 1;
- rc = lsm_begin(pDb, 1);
- }
-
- if( rc==LSM_OK ){
- pDb->treehdr.iUsrVersion = iUsr;
- }
-
- /* If a transaction was opened at the start of this function, commit it.
- ** Or, if an error has occurred, roll it back. */
- if( bCommit ){
- if( rc==LSM_OK ){
- rc = lsm_commit(pDb, 0);
- }else{
- lsm_rollback(pDb, 0);
- }
- }
-
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_mem.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_mem.c
deleted file mode 100644
index 13dd9fe312c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_mem.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-** 2011-08-18
-**
-** 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.
-**
-*************************************************************************
-**
-** Helper routines for memory allocation.
-*/
-#include "lsmInt.h"
-
-/*
-** The following routines are called internally by LSM sub-routines. In
-** this case a valid environment pointer must be supplied.
-*/
-void *lsmMalloc(lsm_env *pEnv, size_t N){
- assert( pEnv );
- return pEnv->xMalloc(pEnv, N);
-}
-void lsmFree(lsm_env *pEnv, void *p){
- assert( pEnv );
- pEnv->xFree(pEnv, p);
-}
-void *lsmRealloc(lsm_env *pEnv, void *p, size_t N){
- assert( pEnv );
- return pEnv->xRealloc(pEnv, p, N);
-}
-
-/*
-** Core memory allocation routines for LSM.
-*/
-void *lsm_malloc(lsm_env *pEnv, size_t N){
- return lsmMalloc(pEnv ? pEnv : lsm_default_env(), N);
-}
-void lsm_free(lsm_env *pEnv, void *p){
- lsmFree(pEnv ? pEnv : lsm_default_env(), p);
-}
-void *lsm_realloc(lsm_env *pEnv, void *p, size_t N){
- return lsmRealloc(pEnv ? pEnv : lsm_default_env(), p, N);
-}
-
-void *lsmMallocZero(lsm_env *pEnv, size_t N){
- void *pRet;
- assert( pEnv );
- pRet = lsmMalloc(pEnv, N);
- if( pRet ) memset(pRet, 0, N);
- return pRet;
-}
-
-void *lsmMallocRc(lsm_env *pEnv, size_t N, int *pRc){
- void *pRet = 0;
- if( *pRc==LSM_OK ){
- pRet = lsmMalloc(pEnv, N);
- if( pRet==0 ){
- *pRc = LSM_NOMEM_BKPT;
- }
- }
- return pRet;
-}
-
-void *lsmMallocZeroRc(lsm_env *pEnv, size_t N, int *pRc){
- void *pRet = 0;
- if( *pRc==LSM_OK ){
- pRet = lsmMallocZero(pEnv, N);
- if( pRet==0 ){
- *pRc = LSM_NOMEM_BKPT;
- }
- }
- return pRet;
-}
-
-void *lsmReallocOrFree(lsm_env *pEnv, void *p, size_t N){
- void *pNew;
- pNew = lsm_realloc(pEnv, p, N);
- if( !pNew ) lsm_free(pEnv, p);
- return pNew;
-}
-
-void *lsmReallocOrFreeRc(lsm_env *pEnv, void *p, size_t N, int *pRc){
- void *pRet = 0;
- if( *pRc ){
- lsmFree(pEnv, p);
- }else{
- pRet = lsmReallocOrFree(pEnv, p, N);
- if( !pRet ) *pRc = LSM_NOMEM_BKPT;
- }
- return pRet;
-}
-
-char *lsmMallocStrdup(lsm_env *pEnv, const char *zIn){
- int nByte;
- char *zRet;
- nByte = strlen(zIn);
- zRet = lsmMalloc(pEnv, nByte+1);
- if( zRet ){
- memcpy(zRet, zIn, nByte+1);
- }
- return zRet;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_mutex.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_mutex.c
deleted file mode 100644
index cb99b2a61e2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_mutex.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-** 2012-01-30
-**
-** 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.
-**
-*************************************************************************
-**
-** Mutex functions for LSM.
-*/
-#include "lsmInt.h"
-
-/*
-** Allocate a new mutex.
-*/
-int lsmMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
- return pEnv->xMutexNew(pEnv, ppNew);
-}
-
-/*
-** Return a handle for one of the static mutexes.
-*/
-int lsmMutexStatic(lsm_env *pEnv, int iMutex, lsm_mutex **ppStatic){
- return pEnv->xMutexStatic(pEnv, iMutex, ppStatic);
-}
-
-/*
-** Free a mutex allocated by lsmMutexNew().
-*/
-void lsmMutexDel(lsm_env *pEnv, lsm_mutex *pMutex){
- if( pMutex ) pEnv->xMutexDel(pMutex);
-}
-
-/*
-** Enter a mutex.
-*/
-void lsmMutexEnter(lsm_env *pEnv, lsm_mutex *pMutex){
- pEnv->xMutexEnter(pMutex);
-}
-
-/*
-** Attempt to enter a mutex, but do not block. If successful, return zero.
-** Otherwise, if the mutex is already held by some other thread and is not
-** entered, return non zero.
-**
-** Each successful call to this function must be matched by a call to
-** lsmMutexLeave().
-*/
-int lsmMutexTry(lsm_env *pEnv, lsm_mutex *pMutex){
- return pEnv->xMutexTry(pMutex);
-}
-
-/*
-** Leave a mutex.
-*/
-void lsmMutexLeave(lsm_env *pEnv, lsm_mutex *pMutex){
- pEnv->xMutexLeave(pMutex);
-}
-
-#ifndef NDEBUG
-/*
-** Return non-zero if the mutex passed as the second argument is held
-** by the calling thread, or zero otherwise. If the implementation is not
-** able to tell if the mutex is held by the caller, it should return
-** non-zero.
-**
-** This function is only used as part of assert() statements.
-*/
-int lsmMutexHeld(lsm_env *pEnv, lsm_mutex *pMutex){
- return pEnv->xMutexHeld ? pEnv->xMutexHeld(pMutex) : 1;
-}
-
-/*
-** Return non-zero if the mutex passed as the second argument is not
-** held by the calling thread, or zero otherwise. If the implementation
-** is not able to tell if the mutex is held by the caller, it should
-** return non-zero.
-**
-** This function is only used as part of assert() statements.
-*/
-int lsmMutexNotHeld(lsm_env *pEnv, lsm_mutex *pMutex){
- return pEnv->xMutexNotHeld ? pEnv->xMutexNotHeld(pMutex) : 1;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_shared.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_shared.c
deleted file mode 100644
index 2fdacf1eca3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_shared.c
+++ /dev/null
@@ -1,1976 +0,0 @@
-/*
-** 2012-01-23
-**
-** 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.
-**
-*************************************************************************
-**
-** Utilities used to help multiple LSM clients to coexist within the
-** same process space.
-*/
-#include "lsmInt.h"
-
-/*
-** Global data. All global variables used by code in this file are grouped
-** into the following structure instance.
-**
-** pDatabase:
-** Linked list of all Database objects allocated within this process.
-** This list may not be traversed without holding the global mutex (see
-** functions enterGlobalMutex() and leaveGlobalMutex()).
-*/
-static struct SharedData {
- Database *pDatabase; /* Linked list of all Database objects */
-} gShared;
-
-/*
-** Database structure. There is one such structure for each distinct
-** database accessed by this process. They are stored in the singly linked
-** list starting at global variable gShared.pDatabase. Database objects are
-** reference counted. Once the number of connections to the associated
-** database drops to zero, they are removed from the linked list and deleted.
-**
-** pFile:
-** In multi-process mode, this file descriptor is used to obtain locks
-** and to access shared-memory. In single process mode, its only job is
-** to hold the exclusive lock on the file.
-**
-*/
-struct Database {
- /* Protected by the global mutex (enterGlobalMutex/leaveGlobalMutex): */
- char *zName; /* Canonical path to database file */
- int nName; /* strlen(zName) */
- int nDbRef; /* Number of associated lsm_db handles */
- Database *pDbNext; /* Next Database structure in global list */
-
- /* Protected by the local mutex (pClientMutex) */
- int bReadonly; /* True if Database.pFile is read-only */
- int bMultiProc; /* True if running in multi-process mode */
- lsm_file *pFile; /* Used for locks/shm in multi-proc mode */
- LsmFile *pLsmFile; /* List of deferred closes */
- lsm_mutex *pClientMutex; /* Protects the apShmChunk[] and pConn */
- int nShmChunk; /* Number of entries in apShmChunk[] array */
- void **apShmChunk; /* Array of "shared" memory regions */
- lsm_db *pConn; /* List of connections to this db. */
-};
-
-/*
-** Functions to enter and leave the global mutex. This mutex is used
-** to protect the global linked-list headed at gShared.pDatabase.
-*/
-static int enterGlobalMutex(lsm_env *pEnv){
- lsm_mutex *p;
- int rc = lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
- if( rc==LSM_OK ) lsmMutexEnter(pEnv, p);
- return rc;
-}
-static void leaveGlobalMutex(lsm_env *pEnv){
- lsm_mutex *p;
- lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
- lsmMutexLeave(pEnv, p);
-}
-
-#ifdef LSM_DEBUG
-static int holdingGlobalMutex(lsm_env *pEnv){
- lsm_mutex *p;
- lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
- return lsmMutexHeld(pEnv, p);
-}
-#endif
-
-#if 0
-static void assertNotInFreelist(Freelist *p, int iBlk){
- int i;
- for(i=0; i<p->nEntry; i++){
- assert( p->aEntry[i].iBlk!=iBlk );
- }
-}
-#else
-# define assertNotInFreelist(x,y)
-#endif
-
-/*
-** Append an entry to the free-list. If (iId==-1), this is a delete.
-*/
-int freelistAppend(lsm_db *db, u32 iBlk, i64 iId){
- lsm_env *pEnv = db->pEnv;
- Freelist *p;
- int i;
-
- assert( iId==-1 || iId>=0 );
- p = db->bUseFreelist ? db->pFreelist : &db->pWorker->freelist;
-
- /* Extend the space allocated for the freelist, if required */
- assert( p->nAlloc>=p->nEntry );
- if( p->nAlloc==p->nEntry ){
- int nNew;
- int nByte;
- FreelistEntry *aNew;
-
- nNew = (p->nAlloc==0 ? 4 : p->nAlloc*2);
- nByte = sizeof(FreelistEntry) * nNew;
- aNew = (FreelistEntry *)lsmRealloc(pEnv, p->aEntry, nByte);
- if( !aNew ) return LSM_NOMEM_BKPT;
- p->nAlloc = nNew;
- p->aEntry = aNew;
- }
-
- for(i=0; i<p->nEntry; i++){
- assert( i==0 || p->aEntry[i].iBlk > p->aEntry[i-1].iBlk );
- if( p->aEntry[i].iBlk>=iBlk ) break;
- }
-
- if( i<p->nEntry && p->aEntry[i].iBlk==iBlk ){
- /* Clobber an existing entry */
- p->aEntry[i].iId = iId;
- }else{
- /* Insert a new entry into the list */
- int nByte = sizeof(FreelistEntry)*(p->nEntry-i);
- memmove(&p->aEntry[i+1], &p->aEntry[i], nByte);
- p->aEntry[i].iBlk = iBlk;
- p->aEntry[i].iId = iId;
- p->nEntry++;
- }
-
- return LSM_OK;
-}
-
-/*
-** This function frees all resources held by the Database structure passed
-** as the only argument.
-*/
-static void freeDatabase(lsm_env *pEnv, Database *p){
- assert( holdingGlobalMutex(pEnv) );
- if( p ){
- /* Free the mutexes */
- lsmMutexDel(pEnv, p->pClientMutex);
-
- if( p->pFile ){
- lsmEnvClose(pEnv, p->pFile);
- }
-
- /* Free the array of shm pointers */
- lsmFree(pEnv, p->apShmChunk);
-
- /* Free the memory allocated for the Database struct itself */
- lsmFree(pEnv, p);
- }
-}
-
-typedef struct DbTruncateCtx DbTruncateCtx;
-struct DbTruncateCtx {
- int nBlock;
- i64 iInUse;
-};
-
-static int dbTruncateCb(void *pCtx, int iBlk, i64 iSnapshot){
- DbTruncateCtx *p = (DbTruncateCtx *)pCtx;
- if( iBlk!=p->nBlock || (p->iInUse>=0 && iSnapshot>=p->iInUse) ) return 1;
- p->nBlock--;
- return 0;
-}
-
-static int dbTruncate(lsm_db *pDb, i64 iInUse){
- int rc = LSM_OK;
-#if 0
- int i;
- DbTruncateCtx ctx;
-
- assert( pDb->pWorker );
- ctx.nBlock = pDb->pWorker->nBlock;
- ctx.iInUse = iInUse;
-
- rc = lsmWalkFreelist(pDb, 1, dbTruncateCb, (void *)&ctx);
- for(i=ctx.nBlock+1; rc==LSM_OK && i<=pDb->pWorker->nBlock; i++){
- rc = freelistAppend(pDb, i, -1);
- }
-
- if( rc==LSM_OK ){
-#ifdef LSM_LOG_FREELIST
- if( ctx.nBlock!=pDb->pWorker->nBlock ){
- lsmLogMessage(pDb, 0,
- "dbTruncate(): truncated db to %d blocks",ctx.nBlock
- );
- }
-#endif
- pDb->pWorker->nBlock = ctx.nBlock;
- }
-#endif
- return rc;
-}
-
-
-/*
-** This function is called during database shutdown (when the number of
-** connections drops from one to zero). It truncates the database file
-** to as small a size as possible without truncating away any blocks that
-** contain data.
-*/
-static int dbTruncateFile(lsm_db *pDb){
- int rc;
-
- assert( pDb->pWorker==0 );
- assert( lsmShmAssertLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL) );
- rc = lsmCheckpointLoadWorker(pDb);
-
- if( rc==LSM_OK ){
- DbTruncateCtx ctx;
-
- /* Walk the database free-block-list in reverse order. Set ctx.nBlock
- ** to the block number of the last block in the database that actually
- ** contains data. */
- ctx.nBlock = pDb->pWorker->nBlock;
- ctx.iInUse = -1;
- rc = lsmWalkFreelist(pDb, 1, dbTruncateCb, (void *)&ctx);
-
- /* If the last block that contains data is not already the last block in
- ** the database file, truncate the database file so that it is. */
- if( rc==LSM_OK ){
- rc = lsmFsTruncateDb(
- pDb->pFS, (i64)ctx.nBlock*lsmFsBlockSize(pDb->pFS)
- );
- }
- }
-
- lsmFreeSnapshot(pDb->pEnv, pDb->pWorker);
- pDb->pWorker = 0;
- return rc;
-}
-
-static void doDbDisconnect(lsm_db *pDb){
- int rc;
-
- if( pDb->bReadonly ){
- lsmShmLock(pDb, LSM_LOCK_DMS3, LSM_LOCK_UNLOCK, 0);
- }else{
- /* Block for an exclusive lock on DMS1. This lock serializes all calls
- ** to doDbConnect() and doDbDisconnect() across all processes. */
- rc = lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL, 1);
- if( rc==LSM_OK ){
-
- lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_UNLOCK, 0);
-
- /* Try an exclusive lock on DMS2. If successful, this is the last
- ** connection to the database. In this case flush the contents of the
- ** in-memory tree to disk and write a checkpoint. */
- rc = lsmShmTestLock(pDb, LSM_LOCK_DMS2, 1, LSM_LOCK_EXCL);
- if( rc==LSM_OK ){
- rc = lsmShmTestLock(pDb, LSM_LOCK_CHECKPOINTER, 1, LSM_LOCK_EXCL);
- }
- if( rc==LSM_OK ){
- int bReadonly = 0; /* True if there exist read-only conns. */
-
- /* Flush the in-memory tree, if required. If there is data to flush,
- ** this will create a new client snapshot in Database.pClient. The
- ** checkpoint (serialization) of this snapshot may be written to disk
- ** by the following block.
- **
- ** There is no need to take a WRITER lock here. That there are no
- ** other locks on DMS2 guarantees that there are no other read-write
- ** connections at this time (and the lock on DMS1 guarantees that
- ** no new ones may appear).
- */
- rc = lsmTreeLoadHeader(pDb, 0);
- if( rc==LSM_OK && (lsmTreeHasOld(pDb) || lsmTreeSize(pDb)>0) ){
- rc = lsmFlushTreeToDisk(pDb);
- }
-
- /* Now check if there are any read-only connections. If there are,
- ** then do not truncate the db file or unlink the shared-memory
- ** region. */
- if( rc==LSM_OK ){
- rc = lsmShmTestLock(pDb, LSM_LOCK_DMS3, 1, LSM_LOCK_EXCL);
- if( rc==LSM_BUSY ){
- bReadonly = 1;
- rc = LSM_OK;
- }
- }
-
- /* Write a checkpoint to disk. */
- if( rc==LSM_OK ){
- rc = lsmCheckpointWrite(pDb, 0);
- }
-
- /* If the checkpoint was written successfully, delete the log file
- ** and, if possible, truncate the database file. */
- if( rc==LSM_OK ){
- int bRotrans = 0;
- Database *p = pDb->pDatabase;
-
- /* The log file may only be deleted if there are no clients
- ** read-only clients running rotrans transactions. */
- rc = lsmDetectRoTrans(pDb, &bRotrans);
- if( rc==LSM_OK && bRotrans==0 ){
- lsmFsCloseAndDeleteLog(pDb->pFS);
- }
-
- /* The database may only be truncated if there exist no read-only
- ** clients - either connected or running rotrans transactions. */
- if( bReadonly==0 && bRotrans==0 ){
- lsmFsUnmap(pDb->pFS);
- dbTruncateFile(pDb);
- if( p->pFile && p->bMultiProc ){
- lsmEnvShmUnmap(pDb->pEnv, p->pFile, 1);
- }
- }
- }
- }
- }
-
- if( pDb->iRwclient>=0 ){
- lsmShmLock(pDb, LSM_LOCK_RWCLIENT(pDb->iRwclient), LSM_LOCK_UNLOCK, 0);
- pDb->iRwclient = -1;
- }
-
- lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
- }
- pDb->pShmhdr = 0;
-}
-
-static int doDbConnect(lsm_db *pDb){
- const int nUsMax = 100000; /* Max value for nUs */
- int nUs = 1000; /* us to wait between DMS1 attempts */
- int rc;
-
- /* Obtain a pointer to the shared-memory header */
- assert( pDb->pShmhdr==0 );
- assert( pDb->bReadonly==0 );
-
- /* Block for an exclusive lock on DMS1. This lock serializes all calls
- ** to doDbConnect() and doDbDisconnect() across all processes. */
- while( 1 ){
- rc = lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL, 1);
- if( rc!=LSM_BUSY ) break;
- lsmEnvSleep(pDb->pEnv, nUs);
- nUs = nUs * 2;
- if( nUs>nUsMax ) nUs = nUsMax;
- }
- if( rc==LSM_OK ){
- rc = lsmShmCacheChunks(pDb, 1);
- }
- if( rc!=LSM_OK ) return rc;
- pDb->pShmhdr = (ShmHeader *)pDb->apShm[0];
-
- /* Try an exclusive lock on DMS2/DMS3. If successful, this is the first
- ** and only connection to the database. In this case initialize the
- ** shared-memory and run log file recovery. */
- assert( LSM_LOCK_DMS3==1+LSM_LOCK_DMS2 );
- rc = lsmShmTestLock(pDb, LSM_LOCK_DMS2, 2, LSM_LOCK_EXCL);
- if( rc==LSM_OK ){
- memset(pDb->pShmhdr, 0, sizeof(ShmHeader));
- rc = lsmCheckpointRecover(pDb);
- if( rc==LSM_OK ){
- rc = lsmLogRecover(pDb);
- }
- if( rc==LSM_OK ){
- ShmHeader *pShm = pDb->pShmhdr;
- pShm->aReader[0].iLsmId = lsmCheckpointId(pShm->aSnap1, 0);
- pShm->aReader[0].iTreeId = pDb->treehdr.iUsedShmid;
- }
- }else if( rc==LSM_BUSY ){
- rc = LSM_OK;
- }
-
- /* Take a shared lock on DMS2. In multi-process mode this lock "cannot"
- ** fail, as connections may only hold an exclusive lock on DMS2 if they
- ** first hold an exclusive lock on DMS1. And this connection is currently
- ** holding the exclusive lock on DSM1.
- **
- ** However, if some other connection has the database open in single-process
- ** mode, this operation will fail. In this case, return the error to the
- ** caller - the attempt to connect to the db has failed.
- */
- if( rc==LSM_OK ){
- rc = lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_SHARED, 0);
- }
-
- /* If anything went wrong, unlock DMS2. Otherwise, try to take an exclusive
- ** lock on one of the LSM_LOCK_RWCLIENT() locks. Unlock DMS1 in any case. */
- if( rc!=LSM_OK ){
- pDb->pShmhdr = 0;
- }else{
- int i;
- for(i=0; i<LSM_LOCK_NRWCLIENT; i++){
- int rc2 = lsmShmLock(pDb, LSM_LOCK_RWCLIENT(i), LSM_LOCK_EXCL, 0);
- if( rc2==LSM_OK ) pDb->iRwclient = i;
- if( rc2!=LSM_BUSY ){
- rc = rc2;
- break;
- }
- }
- }
- lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
-
- return rc;
-}
-
-static int dbOpenSharedFd(lsm_env *pEnv, Database *p, int bRoOk){
- int rc;
-
- rc = lsmEnvOpen(pEnv, p->zName, 0, &p->pFile);
- if( rc==LSM_IOERR && bRoOk ){
- rc = lsmEnvOpen(pEnv, p->zName, LSM_OPEN_READONLY, &p->pFile);
- p->bReadonly = 1;
- }
-
- return rc;
-}
-
-/*
-** Return a reference to the shared Database handle for the database
-** identified by canonical path zName. If this is the first connection to
-** the named database, a new Database object is allocated. Otherwise, a
-** pointer to an existing object is returned.
-**
-** If successful, *ppDatabase is set to point to the shared Database
-** structure and LSM_OK returned. Otherwise, *ppDatabase is set to NULL
-** and and LSM error code returned.
-**
-** Each successful call to this function should be (eventually) matched
-** by a call to lsmDbDatabaseRelease().
-*/
-int lsmDbDatabaseConnect(
- lsm_db *pDb, /* Database handle */
- const char *zName /* Full-path to db file */
-){
- lsm_env *pEnv = pDb->pEnv;
- int rc; /* Return code */
- Database *p = 0; /* Pointer returned via *ppDatabase */
- int nName = lsmStrlen(zName);
-
- assert( pDb->pDatabase==0 );
- rc = enterGlobalMutex(pEnv);
- if( rc==LSM_OK ){
-
- /* Search the global list for an existing object. TODO: Need something
- ** better than the memcmp() below to figure out if a given Database
- ** object represents the requested file. */
- for(p=gShared.pDatabase; p; p=p->pDbNext){
- if( nName==p->nName && 0==memcmp(zName, p->zName, nName) ) break;
- }
-
- /* If no suitable Database object was found, allocate a new one. */
- if( p==0 ){
- p = (Database *)lsmMallocZeroRc(pEnv, sizeof(Database)+nName+1, &rc);
-
- /* If the allocation was successful, fill in other fields and
- ** allocate the client mutex. */
- if( rc==LSM_OK ){
- p->bMultiProc = pDb->bMultiProc;
- p->zName = (char *)&p[1];
- p->nName = nName;
- memcpy((void *)p->zName, zName, nName+1);
- rc = lsmMutexNew(pEnv, &p->pClientMutex);
- }
-
- /* If nothing has gone wrong so far, open the shared fd. And if that
- ** succeeds and this connection requested single-process mode,
- ** attempt to take the exclusive lock on DMS2. */
- if( rc==LSM_OK ){
- int bReadonly = (pDb->bReadonly && pDb->bMultiProc);
- rc = dbOpenSharedFd(pDb->pEnv, p, bReadonly);
- }
-
- if( rc==LSM_OK && p->bMultiProc==0 ){
- /* Hold an exclusive lock DMS1 while grabbing DMS2. This ensures
- ** that any ongoing call to doDbDisconnect() (even one in another
- ** process) is finished before proceeding. */
- assert( p->bReadonly==0 );
- rc = lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS1, LSM_LOCK_EXCL);
- if( rc==LSM_OK ){
- rc = lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS2, LSM_LOCK_EXCL);
- lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK);
- }
- }
-
- if( rc==LSM_OK ){
- p->pDbNext = gShared.pDatabase;
- gShared.pDatabase = p;
- }else{
- freeDatabase(pEnv, p);
- p = 0;
- }
- }
-
- if( p ){
- p->nDbRef++;
- }
- leaveGlobalMutex(pEnv);
-
- if( p ){
- lsmMutexEnter(pDb->pEnv, p->pClientMutex);
- pDb->pNext = p->pConn;
- p->pConn = pDb;
- lsmMutexLeave(pDb->pEnv, p->pClientMutex);
- }
- }
-
- pDb->pDatabase = p;
- if( rc==LSM_OK ){
- assert( p );
- rc = lsmFsOpen(pDb, zName, p->bReadonly);
- }
-
- /* If the db handle is read-write, then connect to the system now. Run
- ** recovery as necessary. Or, if this is a read-only database handle,
- ** defer attempting to connect to the system until a read-transaction
- ** is opened. */
- if( rc==LSM_OK ){
- rc = lsmFsConfigure(pDb);
- }
- if( rc==LSM_OK && pDb->bReadonly==0 ){
- rc = doDbConnect(pDb);
- }
-
- return rc;
-}
-
-static void dbDeferClose(lsm_db *pDb){
- if( pDb->pFS ){
- LsmFile *pLsmFile;
- Database *p = pDb->pDatabase;
- pLsmFile = lsmFsDeferClose(pDb->pFS);
- pLsmFile->pNext = p->pLsmFile;
- p->pLsmFile = pLsmFile;
- }
-}
-
-LsmFile *lsmDbRecycleFd(lsm_db *db){
- LsmFile *pRet;
- Database *p = db->pDatabase;
- lsmMutexEnter(db->pEnv, p->pClientMutex);
- if( (pRet = p->pLsmFile)!=0 ){
- p->pLsmFile = pRet->pNext;
- }
- lsmMutexLeave(db->pEnv, p->pClientMutex);
- return pRet;
-}
-
-/*
-** Release a reference to a Database object obtained from
-** lsmDbDatabaseConnect(). There should be exactly one call to this function
-** for each successful call to Find().
-*/
-void lsmDbDatabaseRelease(lsm_db *pDb){
- Database *p = pDb->pDatabase;
- if( p ){
- lsm_db **ppDb;
-
- if( pDb->pShmhdr ){
- doDbDisconnect(pDb);
- }
-
- lsmFsUnmap(pDb->pFS);
- lsmMutexEnter(pDb->pEnv, p->pClientMutex);
- for(ppDb=&p->pConn; *ppDb!=pDb; ppDb=&((*ppDb)->pNext));
- *ppDb = pDb->pNext;
- dbDeferClose(pDb);
- lsmMutexLeave(pDb->pEnv, p->pClientMutex);
-
- enterGlobalMutex(pDb->pEnv);
- p->nDbRef--;
- if( p->nDbRef==0 ){
- LsmFile *pIter;
- LsmFile *pNext;
- Database **pp;
-
- /* Remove the Database structure from the linked list. */
- for(pp=&gShared.pDatabase; *pp!=p; pp=&((*pp)->pDbNext));
- *pp = p->pDbNext;
-
- /* If they were allocated from the heap, free the shared memory chunks */
- if( p->bMultiProc==0 ){
- int i;
- for(i=0; i<p->nShmChunk; i++){
- lsmFree(pDb->pEnv, p->apShmChunk[i]);
- }
- }
-
- /* Close any outstanding file descriptors */
- for(pIter=p->pLsmFile; pIter; pIter=pNext){
- pNext = pIter->pNext;
- lsmEnvClose(pDb->pEnv, pIter->pFile);
- lsmFree(pDb->pEnv, pIter);
- }
- freeDatabase(pDb->pEnv, p);
- }
- leaveGlobalMutex(pDb->pEnv);
- }
-}
-
-Level *lsmDbSnapshotLevel(Snapshot *pSnapshot){
- return pSnapshot->pLevel;
-}
-
-void lsmDbSnapshotSetLevel(Snapshot *pSnap, Level *pLevel){
- pSnap->pLevel = pLevel;
-}
-
-/* TODO: Shuffle things around to get rid of this */
-static int firstSnapshotInUse(lsm_db *, i64 *);
-
-/*
-** Context object used by the lsmWalkFreelist() utility.
-*/
-typedef struct WalkFreelistCtx WalkFreelistCtx;
-struct WalkFreelistCtx {
- lsm_db *pDb;
- int bReverse;
- Freelist *pFreelist;
- int iFree;
- int (*xUsr)(void *, int, i64); /* User callback function */
- void *pUsrctx; /* User callback context */
- int bDone; /* Set to true after xUsr() returns true */
-};
-
-/*
-** Callback used by lsmWalkFreelist().
-*/
-static int walkFreelistCb(void *pCtx, int iBlk, i64 iSnapshot){
- WalkFreelistCtx *p = (WalkFreelistCtx *)pCtx;
- const int iDir = (p->bReverse ? -1 : 1);
- Freelist *pFree = p->pFreelist;
-
- assert( p->bDone==0 );
- assert( iBlk>=0 );
- if( pFree ){
- while( (p->iFree < pFree->nEntry) && p->iFree>=0 ){
- FreelistEntry *pEntry = &pFree->aEntry[p->iFree];
- if( (p->bReverse==0 && pEntry->iBlk>(u32)iBlk)
- || (p->bReverse!=0 && pEntry->iBlk<(u32)iBlk)
- ){
- break;
- }else{
- p->iFree += iDir;
- if( pEntry->iId>=0
- && p->xUsr(p->pUsrctx, pEntry->iBlk, pEntry->iId)
- ){
- p->bDone = 1;
- return 1;
- }
- if( pEntry->iBlk==(u32)iBlk ) return 0;
- }
- }
- }
-
- if( p->xUsr(p->pUsrctx, iBlk, iSnapshot) ){
- p->bDone = 1;
- return 1;
- }
- return 0;
-}
-
-/*
-** The database handle passed as the first argument must be the worker
-** connection. This function iterates through the contents of the current
-** free block list, invoking the supplied callback once for each list
-** element.
-**
-** The difference between this function and lsmSortedWalkFreelist() is
-** that lsmSortedWalkFreelist() only considers those free-list elements
-** stored within the LSM. This function also merges in any in-memory
-** elements.
-*/
-int lsmWalkFreelist(
- lsm_db *pDb, /* Database handle (must be worker) */
- int bReverse, /* True to iterate from largest to smallest */
- int (*x)(void *, int, i64), /* Callback function */
- void *pCtx /* First argument to pass to callback */
-){
- const int iDir = (bReverse ? -1 : 1);
- int rc;
- int iCtx;
-
- WalkFreelistCtx ctx[2];
-
- ctx[0].pDb = pDb;
- ctx[0].bReverse = bReverse;
- ctx[0].pFreelist = &pDb->pWorker->freelist;
- if( ctx[0].pFreelist && bReverse ){
- ctx[0].iFree = ctx[0].pFreelist->nEntry-1;
- }else{
- ctx[0].iFree = 0;
- }
- ctx[0].xUsr = walkFreelistCb;
- ctx[0].pUsrctx = (void *)&ctx[1];
- ctx[0].bDone = 0;
-
- ctx[1].pDb = pDb;
- ctx[1].bReverse = bReverse;
- ctx[1].pFreelist = pDb->pFreelist;
- if( ctx[1].pFreelist && bReverse ){
- ctx[1].iFree = ctx[1].pFreelist->nEntry-1;
- }else{
- ctx[1].iFree = 0;
- }
- ctx[1].xUsr = x;
- ctx[1].pUsrctx = pCtx;
- ctx[1].bDone = 0;
-
- rc = lsmSortedWalkFreelist(pDb, bReverse, walkFreelistCb, (void *)&ctx[0]);
-
- if( ctx[0].bDone==0 ){
- for(iCtx=0; iCtx<2; iCtx++){
- int i;
- WalkFreelistCtx *p = &ctx[iCtx];
- for(i=p->iFree;
- p->pFreelist && rc==LSM_OK && i<p->pFreelist->nEntry && i>=0;
- i += iDir
- ){
- FreelistEntry *pEntry = &p->pFreelist->aEntry[i];
- if( pEntry->iId>=0 && p->xUsr(p->pUsrctx, pEntry->iBlk, pEntry->iId) ){
- return LSM_OK;
- }
- }
- }
- }
-
- return rc;
-}
-
-
-typedef struct FindFreeblockCtx FindFreeblockCtx;
-struct FindFreeblockCtx {
- i64 iInUse;
- int iRet;
- int bNotOne;
-};
-
-static int findFreeblockCb(void *pCtx, int iBlk, i64 iSnapshot){
- FindFreeblockCtx *p = (FindFreeblockCtx *)pCtx;
- if( iSnapshot<p->iInUse && (iBlk!=1 || p->bNotOne==0) ){
- p->iRet = iBlk;
- return 1;
- }
- return 0;
-}
-
-static int findFreeblock(lsm_db *pDb, i64 iInUse, int bNotOne, int *piRet){
- int rc; /* Return code */
- FindFreeblockCtx ctx; /* Context object */
-
- ctx.iInUse = iInUse;
- ctx.iRet = 0;
- ctx.bNotOne = bNotOne;
- rc = lsmWalkFreelist(pDb, 0, findFreeblockCb, (void *)&ctx);
- *piRet = ctx.iRet;
-
- return rc;
-}
-
-/*
-** Allocate a new database file block to write data to, either by extending
-** the database file or by recycling a free-list entry. The worker snapshot
-** must be held in order to call this function.
-**
-** If successful, *piBlk is set to the block number allocated and LSM_OK is
-** returned. Otherwise, *piBlk is zeroed and an lsm error code returned.
-*/
-int lsmBlockAllocate(lsm_db *pDb, int iBefore, int *piBlk){
- Snapshot *p = pDb->pWorker;
- int iRet = 0; /* Block number of allocated block */
- int rc = LSM_OK;
- i64 iInUse = 0; /* Snapshot id still in use */
- i64 iSynced = 0; /* Snapshot id synced to disk */
-
- assert( p );
-
-#ifdef LSM_LOG_FREELIST
- {
- static int nCall = 0;
- char *zFree = 0;
- nCall++;
- rc = lsmInfoFreelist(pDb, &zFree);
- if( rc!=LSM_OK ) return rc;
- lsmLogMessage(pDb, 0, "lsmBlockAllocate(): %d freelist: %s", nCall, zFree);
- lsmFree(pDb->pEnv, zFree);
- }
-#endif
-
- /* Set iInUse to the smallest snapshot id that is either:
- **
- ** * Currently in use by a database client,
- ** * May be used by a database client in the future, or
- ** * Is the most recently checkpointed snapshot (i.e. the one that will
- ** be used following recovery if a failure occurs at this point).
- */
- rc = lsmCheckpointSynced(pDb, &iSynced, 0, 0);
- if( rc==LSM_OK && iSynced==0 ) iSynced = p->iId;
- iInUse = iSynced;
- if( rc==LSM_OK && pDb->iReader>=0 ){
- assert( pDb->pClient );
- iInUse = LSM_MIN(iInUse, pDb->pClient->iId);
- }
- if( rc==LSM_OK ) rc = firstSnapshotInUse(pDb, &iInUse);
-
-#ifdef LSM_LOG_FREELIST
- {
- lsmLogMessage(pDb, 0, "lsmBlockAllocate(): "
- "snapshot-in-use: %lld (iSynced=%lld) (client-id=%lld)",
- iInUse, iSynced, (pDb->iReader>=0 ? pDb->pClient->iId : 0)
- );
- }
-#endif
-
-
- /* Unless there exists a read-only transaction (which prevents us from
- ** recycling any blocks regardless, query the free block list for a
- ** suitable block to reuse.
- **
- ** It might seem more natural to check for a read-only transaction at
- ** the start of this function. However, it is better do wait until after
- ** the call to lsmCheckpointSynced() to do so.
- */
- if( rc==LSM_OK ){
- int bRotrans;
- rc = lsmDetectRoTrans(pDb, &bRotrans);
-
- if( rc==LSM_OK && bRotrans==0 ){
- rc = findFreeblock(pDb, iInUse, (iBefore>0), &iRet);
- }
- }
-
- if( iBefore>0 && (iRet<=0 || iRet>=iBefore) ){
- iRet = 0;
-
- }else if( rc==LSM_OK ){
- /* If a block was found in the free block list, use it and remove it from
- ** the list. Otherwise, if no suitable block was found, allocate one from
- ** the end of the file. */
- if( iRet>0 ){
-#ifdef LSM_LOG_FREELIST
- lsmLogMessage(pDb, 0,
- "reusing block %d (snapshot-in-use=%lld)", iRet, iInUse);
-#endif
- rc = freelistAppend(pDb, iRet, -1);
- if( rc==LSM_OK ){
- rc = dbTruncate(pDb, iInUse);
- }
- }else{
- iRet = ++(p->nBlock);
-#ifdef LSM_LOG_FREELIST
- lsmLogMessage(pDb, 0, "extending file to %d blocks", iRet);
-#endif
- }
- }
-
- assert( iBefore>0 || iRet>0 || rc!=LSM_OK );
- *piBlk = iRet;
- return rc;
-}
-
-/*
-** Free a database block. The worker snapshot must be held in order to call
-** this function.
-**
-** If successful, LSM_OK is returned. Otherwise, an lsm error code (e.g.
-** LSM_NOMEM).
-*/
-int lsmBlockFree(lsm_db *pDb, int iBlk){
- Snapshot *p = pDb->pWorker;
- assert( lsmShmAssertWorker(pDb) );
-
-#ifdef LSM_LOG_FREELIST
- lsmLogMessage(pDb, LSM_OK, "lsmBlockFree(): Free block %d", iBlk);
-#endif
-
- return freelistAppend(pDb, iBlk, p->iId);
-}
-
-/*
-** Refree a database block. The worker snapshot must be held in order to call
-** this function.
-**
-** Refreeing is required when a block is allocated using lsmBlockAllocate()
-** but then not used. This function is used to push the block back onto
-** the freelist. Refreeing a block is different from freeing is, as a refreed
-** block may be reused immediately. Whereas a freed block can not be reused
-** until (at least) after the next checkpoint.
-*/
-int lsmBlockRefree(lsm_db *pDb, int iBlk){
- int rc = LSM_OK; /* Return code */
-
-#ifdef LSM_LOG_FREELIST
- lsmLogMessage(pDb, LSM_OK, "lsmBlockRefree(): Refree block %d", iBlk);
-#endif
-
- rc = freelistAppend(pDb, iBlk, 0);
- return rc;
-}
-
-/*
-** If required, copy a database checkpoint from shared memory into the
-** database itself.
-**
-** The WORKER lock must not be held when this is called. This is because
-** this function may indirectly call fsync(). And the WORKER lock should
-** not be held that long (in case it is required by a client flushing an
-** in-memory tree to disk).
-*/
-int lsmCheckpointWrite(lsm_db *pDb, u32 *pnWrite){
- int rc; /* Return Code */
- u32 nWrite = 0;
-
- assert( pDb->pWorker==0 );
- assert( 1 || pDb->pClient==0 );
- assert( lsmShmAssertLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_UNLOCK) );
-
- rc = lsmShmLock(pDb, LSM_LOCK_CHECKPOINTER, LSM_LOCK_EXCL, 0);
- if( rc!=LSM_OK ) return rc;
-
- rc = lsmCheckpointLoad(pDb, 0);
- if( rc==LSM_OK ){
- int nBlock = lsmCheckpointNBlock(pDb->aSnapshot);
- ShmHeader *pShm = pDb->pShmhdr;
- int bDone = 0; /* True if checkpoint is already stored */
-
- /* Check if this checkpoint has already been written to the database
- ** file. If so, set variable bDone to true. */
- if( pShm->iMetaPage ){
- MetaPage *pPg; /* Meta page */
- u8 *aData; /* Meta-page data buffer */
- int nData; /* Size of aData[] in bytes */
- i64 iCkpt; /* Id of checkpoint just loaded */
- i64 iDisk = 0; /* Id of checkpoint already stored in db */
- iCkpt = lsmCheckpointId(pDb->aSnapshot, 0);
- rc = lsmFsMetaPageGet(pDb->pFS, 0, pShm->iMetaPage, &pPg);
- if( rc==LSM_OK ){
- aData = lsmFsMetaPageData(pPg, &nData);
- iDisk = lsmCheckpointId((u32 *)aData, 1);
- nWrite = lsmCheckpointNWrite((u32 *)aData, 1);
- lsmFsMetaPageRelease(pPg);
- }
- bDone = (iDisk>=iCkpt);
- }
-
- if( rc==LSM_OK && bDone==0 ){
- int iMeta = (pShm->iMetaPage % 2) + 1;
- if( pDb->eSafety!=LSM_SAFETY_OFF ){
- rc = lsmFsSyncDb(pDb->pFS, nBlock);
- }
- if( rc==LSM_OK ) rc = lsmCheckpointStore(pDb, iMeta);
- if( rc==LSM_OK && pDb->eSafety!=LSM_SAFETY_OFF){
- rc = lsmFsSyncDb(pDb->pFS, 0);
- }
- if( rc==LSM_OK ){
- pShm->iMetaPage = iMeta;
- nWrite = lsmCheckpointNWrite(pDb->aSnapshot, 0) - nWrite;
- }
-#ifdef LSM_LOG_WORK
- lsmLogMessage(pDb, 0, "finish checkpoint %d",
- (int)lsmCheckpointId(pDb->aSnapshot, 0)
- );
-#endif
- }
- }
-
- lsmShmLock(pDb, LSM_LOCK_CHECKPOINTER, LSM_LOCK_UNLOCK, 0);
- if( pnWrite && rc==LSM_OK ) *pnWrite = nWrite;
- return rc;
-}
-
-int lsmBeginWork(lsm_db *pDb){
- int rc;
-
- /* Attempt to take the WORKER lock */
- rc = lsmShmLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_EXCL, 0);
-
- /* Deserialize the current worker snapshot */
- if( rc==LSM_OK ){
- rc = lsmCheckpointLoadWorker(pDb);
- }
- return rc;
-}
-
-void lsmFreeSnapshot(lsm_env *pEnv, Snapshot *p){
- if( p ){
- lsmSortedFreeLevel(pEnv, p->pLevel);
- lsmFree(pEnv, p->freelist.aEntry);
- lsmFree(pEnv, p->redirect.a);
- lsmFree(pEnv, p);
- }
-}
-
-/*
-** Attempt to populate one of the read-lock slots to contain lock values
-** iLsm/iShm. Or, if such a slot exists already, this function is a no-op.
-**
-** It is not an error if no slot can be populated because the write-lock
-** cannot be obtained. If any other error occurs, return an LSM error code.
-** Otherwise, LSM_OK.
-**
-** This function is called at various points to try to ensure that there
-** always exists at least one read-lock slot that can be used by a read-only
-** client. And so that, in the usual case, there is an "exact match" available
-** whenever a read transaction is opened by any client. At present this
-** function is called when:
-**
-** * A write transaction that called lsmTreeDiscardOld() is committed, and
-** * Whenever the working snapshot is updated (i.e. lsmFinishWork()).
-*/
-static int dbSetReadLock(lsm_db *db, i64 iLsm, u32 iShm){
- int rc = LSM_OK;
- ShmHeader *pShm = db->pShmhdr;
- int i;
-
- /* Check if there is already a slot containing the required values. */
- for(i=0; i<LSM_LOCK_NREADER; i++){
- ShmReader *p = &pShm->aReader[i];
- if( p->iLsmId==iLsm && p->iTreeId==iShm ) return LSM_OK;
- }
-
- /* Iterate through all read-lock slots, attempting to take a write-lock
- ** on each of them. If a write-lock succeeds, populate the locked slot
- ** with the required values and break out of the loop. */
- for(i=0; rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
- rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
- if( rc==LSM_BUSY ){
- rc = LSM_OK;
- }else{
- ShmReader *p = &pShm->aReader[i];
- p->iLsmId = iLsm;
- p->iTreeId = iShm;
- lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
- break;
- }
- }
-
- return rc;
-}
-
-/*
-** Release the read-lock currently held by connection db.
-*/
-int dbReleaseReadlock(lsm_db *db){
- int rc = LSM_OK;
- if( db->iReader>=0 ){
- rc = lsmShmLock(db, LSM_LOCK_READER(db->iReader), LSM_LOCK_UNLOCK, 0);
- db->iReader = -1;
- }
- db->bRoTrans = 0;
- return rc;
-}
-
-
-/*
-** Argument bFlush is true if the contents of the in-memory tree has just
-** been flushed to disk. The significance of this is that once the snapshot
-** created to hold the updated state of the database is synced to disk, log
-** file space can be recycled.
-*/
-void lsmFinishWork(lsm_db *pDb, int bFlush, int *pRc){
- int rc = *pRc;
- assert( rc!=0 || pDb->pWorker );
- if( pDb->pWorker ){
- /* If no error has occurred, serialize the worker snapshot and write
- ** it to shared memory. */
- if( rc==LSM_OK ){
- rc = lsmSaveWorker(pDb, bFlush);
- }
-
- /* Assuming no error has occurred, update a read lock slot with the
- ** new snapshot id (see comments above function dbSetReadLock()). */
- if( rc==LSM_OK ){
- if( pDb->iReader<0 ){
- rc = lsmTreeLoadHeader(pDb, 0);
- }
- if( rc==LSM_OK ){
- rc = dbSetReadLock(pDb, pDb->pWorker->iId, pDb->treehdr.iUsedShmid);
- }
- }
-
- /* Free the snapshot object. */
- lsmFreeSnapshot(pDb->pEnv, pDb->pWorker);
- pDb->pWorker = 0;
- }
-
- lsmShmLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_UNLOCK, 0);
- *pRc = rc;
-}
-
-/*
-** Called when recovery is finished.
-*/
-int lsmFinishRecovery(lsm_db *pDb){
- lsmTreeEndTransaction(pDb, 1);
- return LSM_OK;
-}
-
-/*
-** Check if the currently configured compression functions
-** (LSM_CONFIG_SET_COMPRESSION) are compatible with a database that has its
-** compression id set to iReq. Compression routines are compatible if iReq
-** is zero (indicating the database is empty), or if it is equal to the
-** compression id of the configured compression routines.
-**
-** If the check shows that the current compression are incompatible and there
-** is a compression factory registered, give it a chance to install new
-** compression routines.
-**
-** If, after any registered factory is invoked, the compression functions
-** are still incompatible, return LSM_MISMATCH. Otherwise, LSM_OK.
-*/
-int lsmCheckCompressionId(lsm_db *pDb, u32 iReq){
- if( iReq!=LSM_COMPRESSION_EMPTY && pDb->compress.iId!=iReq ){
- if( pDb->factory.xFactory ){
- pDb->bInFactory = 1;
- pDb->factory.xFactory(pDb->factory.pCtx, pDb, iReq);
- pDb->bInFactory = 0;
- }
- if( pDb->compress.iId!=iReq ){
- /* Incompatible */
- return LSM_MISMATCH;
- }
- }
- /* Compatible */
- return LSM_OK;
-}
-
-/*
-** Begin a read transaction. This function is a no-op if the connection
-** passed as the only argument already has an open read transaction.
-*/
-int lsmBeginReadTrans(lsm_db *pDb){
- const int MAX_READLOCK_ATTEMPTS = 10;
- const int nMaxAttempt = (pDb->bRoTrans ? 1 : MAX_READLOCK_ATTEMPTS);
-
- int rc = LSM_OK; /* Return code */
- int iAttempt = 0;
-
- assert( pDb->pWorker==0 );
-
- while( rc==LSM_OK && pDb->iReader<0 && (iAttempt++)<nMaxAttempt ){
- int iTreehdr = 0;
- int iSnap = 0;
- assert( pDb->pCsr==0 && pDb->nTransOpen==0 );
-
- /* Load the in-memory tree header. */
- rc = lsmTreeLoadHeader(pDb, &iTreehdr);
-
- /* Load the database snapshot */
- if( rc==LSM_OK ){
- if( lsmCheckpointClientCacheOk(pDb)==0 ){
- lsmFreeSnapshot(pDb->pEnv, pDb->pClient);
- pDb->pClient = 0;
- lsmMCursorFreeCache(pDb);
- lsmFsPurgeCache(pDb->pFS);
- rc = lsmCheckpointLoad(pDb, &iSnap);
- }else{
- iSnap = 1;
- }
- }
-
- /* Take a read-lock on the tree and snapshot just loaded. Then check
- ** that the shared-memory still contains the same values. If so, proceed.
- ** Otherwise, relinquish the read-lock and retry the whole procedure
- ** (starting with loading the in-memory tree header). */
- if( rc==LSM_OK ){
- u32 iShmMax = pDb->treehdr.iUsedShmid;
- u32 iShmMin = pDb->treehdr.iNextShmid+1-LSM_MAX_SHMCHUNKS;
- rc = lsmReadlock(
- pDb, lsmCheckpointId(pDb->aSnapshot, 0), iShmMin, iShmMax
- );
- if( rc==LSM_OK ){
- if( lsmTreeLoadHeaderOk(pDb, iTreehdr)
- && lsmCheckpointLoadOk(pDb, iSnap)
- ){
- /* Read lock has been successfully obtained. Deserialize the
- ** checkpoint just loaded. TODO: This will be removed after
- ** lsm_sorted.c is changed to work directly from the serialized
- ** version of the snapshot. */
- if( pDb->pClient==0 ){
- rc = lsmCheckpointDeserialize(pDb, 0, pDb->aSnapshot,&pDb->pClient);
- }
- assert( (rc==LSM_OK)==(pDb->pClient!=0) );
- assert( pDb->iReader>=0 );
-
- /* Check that the client has the right compression hooks loaded.
- ** If not, set rc to LSM_MISMATCH. */
- if( rc==LSM_OK ){
- rc = lsmCheckCompressionId(pDb, pDb->pClient->iCmpId);
- }
- }else{
- rc = dbReleaseReadlock(pDb);
- }
- }
-
- if( rc==LSM_BUSY ){
- rc = LSM_OK;
- }
- }
-#if 0
-if( rc==LSM_OK && pDb->pClient ){
- fprintf(stderr,
- "reading %p: snapshot:%d used-shmid:%d trans-id:%d iOldShmid=%d\n",
- (void *)pDb,
- (int)pDb->pClient->iId, (int)pDb->treehdr.iUsedShmid,
- (int)pDb->treehdr.root.iTransId,
- (int)pDb->treehdr.iOldShmid
- );
-}
-#endif
- }
-
- if( rc==LSM_OK ){
- rc = lsmShmCacheChunks(pDb, pDb->treehdr.nChunk);
- }
- if( rc!=LSM_OK ){
- dbReleaseReadlock(pDb);
- }
- if( pDb->pClient==0 && rc==LSM_OK ) rc = LSM_BUSY;
- return rc;
-}
-
-/*
-** This function is used by a read-write connection to determine if there
-** are currently one or more read-only transactions open on the database
-** (in this context a read-only transaction is one opened by a read-only
-** connection on a non-live database).
-**
-** If no error occurs, LSM_OK is returned and *pbExists is set to true if
-** some other connection has a read-only transaction open, or false
-** otherwise. If an error occurs an LSM error code is returned and the final
-** value of *pbExist is undefined.
-*/
-int lsmDetectRoTrans(lsm_db *db, int *pbExist){
- int rc;
-
- /* Only a read-write connection may use this function. */
- assert( db->bReadonly==0 );
-
- rc = lsmShmTestLock(db, LSM_LOCK_ROTRANS, 1, LSM_LOCK_EXCL);
- if( rc==LSM_BUSY ){
- *pbExist = 1;
- rc = LSM_OK;
- }else{
- *pbExist = 0;
- }
-
- return rc;
-}
-
-/*
-** db is a read-only database handle in the disconnected state. This function
-** attempts to open a read-transaction on the database. This may involve
-** connecting to the database system (opening shared memory etc.).
-*/
-int lsmBeginRoTrans(lsm_db *db){
- int rc = LSM_OK;
-
- assert( db->bReadonly && db->pShmhdr==0 );
- assert( db->iReader<0 );
-
- if( db->bRoTrans==0 ){
-
- /* Attempt a shared-lock on DMS1. */
- rc = lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_SHARED, 0);
- if( rc!=LSM_OK ) return rc;
-
- rc = lsmShmTestLock(
- db, LSM_LOCK_RWCLIENT(0), LSM_LOCK_NREADER, LSM_LOCK_SHARED
- );
- if( rc==LSM_OK ){
- /* System is not live. Take a SHARED lock on the ROTRANS byte and
- ** release DMS1. Locking ROTRANS tells all read-write clients that they
- ** may not recycle any disk space from within the database or log files,
- ** as a read-only client may be using it. */
- rc = lsmShmLock(db, LSM_LOCK_ROTRANS, LSM_LOCK_SHARED, 0);
- lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
-
- if( rc==LSM_OK ){
- db->bRoTrans = 1;
- rc = lsmShmCacheChunks(db, 1);
- if( rc==LSM_OK ){
- db->pShmhdr = (ShmHeader *)db->apShm[0];
- memset(db->pShmhdr, 0, sizeof(ShmHeader));
- rc = lsmCheckpointRecover(db);
- if( rc==LSM_OK ){
- rc = lsmLogRecover(db);
- }
- }
- }
- }else if( rc==LSM_BUSY ){
- /* System is live! */
- rc = lsmShmLock(db, LSM_LOCK_DMS3, LSM_LOCK_SHARED, 0);
- lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
- if( rc==LSM_OK ){
- rc = lsmShmCacheChunks(db, 1);
- if( rc==LSM_OK ){
- db->pShmhdr = (ShmHeader *)db->apShm[0];
- }
- }
- }
-
- if( rc==LSM_OK ){
- rc = lsmBeginReadTrans(db);
- }
- }
-
- return rc;
-}
-
-/*
-** Close the currently open read transaction.
-*/
-void lsmFinishReadTrans(lsm_db *pDb){
-
- /* Worker connections should not be closing read transactions. And
- ** read transactions should only be closed after all cursors and write
- ** transactions have been closed. Finally pClient should be non-NULL
- ** only iff pDb->iReader>=0. */
- assert( pDb->pWorker==0 );
- assert( pDb->pCsr==0 && pDb->nTransOpen==0 );
-
- if( pDb->bRoTrans ){
- int i;
- for(i=0; i<pDb->nShm; i++){
- lsmFree(pDb->pEnv, pDb->apShm[i]);
- }
- lsmFree(pDb->pEnv, pDb->apShm);
- pDb->apShm = 0;
- pDb->nShm = 0;
- pDb->pShmhdr = 0;
-
- lsmShmLock(pDb, LSM_LOCK_ROTRANS, LSM_LOCK_UNLOCK, 0);
- }
- dbReleaseReadlock(pDb);
-}
-
-/*
-** Open a write transaction.
-*/
-int lsmBeginWriteTrans(lsm_db *pDb){
- int rc = LSM_OK; /* Return code */
- ShmHeader *pShm = pDb->pShmhdr; /* Shared memory header */
-
- assert( pDb->nTransOpen==0 );
- assert( pDb->bDiscardOld==0 );
- assert( pDb->bReadonly==0 );
-
- /* If there is no read-transaction open, open one now. */
- if( pDb->iReader<0 ){
- rc = lsmBeginReadTrans(pDb);
- }
-
- /* Attempt to take the WRITER lock */
- if( rc==LSM_OK ){
- rc = lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_EXCL, 0);
- }
-
- /* If the previous writer failed mid-transaction, run emergency rollback. */
- if( rc==LSM_OK && pShm->bWriter ){
- rc = lsmTreeRepair(pDb);
- if( rc==LSM_OK ) pShm->bWriter = 0;
- }
-
- /* Check that this connection is currently reading from the most recent
- ** version of the database. If not, return LSM_BUSY. */
- if( rc==LSM_OK && memcmp(&pShm->hdr1, &pDb->treehdr, sizeof(TreeHeader)) ){
- rc = LSM_BUSY;
- }
-
- if( rc==LSM_OK ){
- rc = lsmLogBegin(pDb);
- }
-
- /* If everything was successful, set the "transaction-in-progress" flag
- ** and return LSM_OK. Otherwise, if some error occurred, relinquish the
- ** WRITER lock and return an error code. */
- if( rc==LSM_OK ){
- TreeHeader *p = &pDb->treehdr;
- pShm->bWriter = 1;
- p->root.iTransId++;
- if( lsmTreeHasOld(pDb) && p->iOldLog==pDb->pClient->iLogOff ){
- lsmTreeDiscardOld(pDb);
- pDb->bDiscardOld = 1;
- }
- }else{
- lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_UNLOCK, 0);
- if( pDb->pCsr==0 ) lsmFinishReadTrans(pDb);
- }
- return rc;
-}
-
-/*
-** End the current write transaction. The connection is left with an open
-** read transaction. It is an error to call this if there is no open write
-** transaction.
-**
-** If the transaction was committed, then a commit record has already been
-** written into the log file when this function is called. Or, if the
-** transaction was rolled back, both the log file and in-memory tree
-** structure have already been restored. In either case, this function
-** merely releases locks and other resources held by the write-transaction.
-**
-** LSM_OK is returned if successful, or an LSM error code otherwise.
-*/
-int lsmFinishWriteTrans(lsm_db *pDb, int bCommit){
- int rc = LSM_OK;
- int bFlush = 0;
-
- lsmLogEnd(pDb, bCommit);
- if( rc==LSM_OK && bCommit && lsmTreeSize(pDb)>pDb->nTreeLimit ){
- bFlush = 1;
- lsmTreeMakeOld(pDb);
- }
- lsmTreeEndTransaction(pDb, bCommit);
-
- if( rc==LSM_OK ){
- if( bFlush && pDb->bAutowork ){
- rc = lsmSortedAutoWork(pDb, 1);
- }else if( bCommit && pDb->bDiscardOld ){
- rc = dbSetReadLock(pDb, pDb->pClient->iId, pDb->treehdr.iUsedShmid);
- }
- }
- pDb->bDiscardOld = 0;
- lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_UNLOCK, 0);
-
- if( bFlush && pDb->bAutowork==0 && pDb->xWork ){
- pDb->xWork(pDb, pDb->pWorkCtx);
- }
- return rc;
-}
-
-
-/*
-** Return non-zero if the caller is holding the client mutex.
-*/
-#ifdef LSM_DEBUG
-int lsmHoldingClientMutex(lsm_db *pDb){
- return lsmMutexHeld(pDb->pEnv, pDb->pDatabase->pClientMutex);
-}
-#endif
-
-static int slotIsUsable(ShmReader *p, i64 iLsm, u32 iShmMin, u32 iShmMax){
- return(
- p->iLsmId && p->iLsmId<=iLsm
- && shm_sequence_ge(iShmMax, p->iTreeId)
- && shm_sequence_ge(p->iTreeId, iShmMin)
- );
-}
-
-/*
-** Obtain a read-lock on database version identified by the combination
-** of snapshot iLsm and tree iTree. Return LSM_OK if successful, or
-** an LSM error code otherwise.
-*/
-int lsmReadlock(lsm_db *db, i64 iLsm, u32 iShmMin, u32 iShmMax){
- int rc = LSM_OK;
- ShmHeader *pShm = db->pShmhdr;
- int i;
-
- assert( db->iReader<0 );
- assert( shm_sequence_ge(iShmMax, iShmMin) );
-
- /* This is a no-op if the read-only transaction flag is set. */
- if( db->bRoTrans ){
- db->iReader = 0;
- return LSM_OK;
- }
-
- /* Search for an exact match. */
- for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
- ShmReader *p = &pShm->aReader[i];
- if( p->iLsmId==iLsm && p->iTreeId==iShmMax ){
- rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
- if( rc==LSM_OK && p->iLsmId==iLsm && p->iTreeId==iShmMax ){
- db->iReader = i;
- }else if( rc==LSM_BUSY ){
- rc = LSM_OK;
- }
- }
- }
-
- /* Try to obtain a write-lock on each slot, in order. If successful, set
- ** the slot values to iLsm/iTree. */
- for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
- rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
- if( rc==LSM_BUSY ){
- rc = LSM_OK;
- }else{
- ShmReader *p = &pShm->aReader[i];
- p->iLsmId = iLsm;
- p->iTreeId = iShmMax;
- rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
- assert( rc!=LSM_BUSY );
- if( rc==LSM_OK ) db->iReader = i;
- }
- }
-
- /* Search for any usable slot */
- for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
- ShmReader *p = &pShm->aReader[i];
- if( slotIsUsable(p, iLsm, iShmMin, iShmMax) ){
- rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
- if( rc==LSM_OK && slotIsUsable(p, iLsm, iShmMin, iShmMax) ){
- db->iReader = i;
- }else if( rc==LSM_BUSY ){
- rc = LSM_OK;
- }
- }
- }
-
- if( rc==LSM_OK && db->iReader<0 ){
- rc = LSM_BUSY;
- }
- return rc;
-}
-
-/*
-** This is used to check if there exists a read-lock locking a particular
-** version of either the in-memory tree or database file.
-**
-** If iLsmId is non-zero, then it is a snapshot id. If there exists a
-** read-lock using this snapshot or newer, set *pbInUse to true. Or,
-** if there is no such read-lock, set it to false.
-**
-** Or, if iLsmId is zero, then iShmid is a shared-memory sequence id.
-** Search for a read-lock using this sequence id or newer. etc.
-*/
-static int isInUse(lsm_db *db, i64 iLsmId, u32 iShmid, int *pbInUse){
- ShmHeader *pShm = db->pShmhdr;
- int i;
- int rc = LSM_OK;
-
- for(i=0; rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
- ShmReader *p = &pShm->aReader[i];
- if( p->iLsmId ){
- if( (iLsmId!=0 && p->iLsmId!=0 && iLsmId>=p->iLsmId)
- || (iLsmId==0 && shm_sequence_ge(p->iTreeId, iShmid))
- ){
- rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
- if( rc==LSM_OK ){
- p->iLsmId = 0;
- lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
- }
- }
- }
- }
-
- if( rc==LSM_BUSY ){
- *pbInUse = 1;
- return LSM_OK;
- }
- *pbInUse = 0;
- return rc;
-}
-
-/*
-** This function is called by worker connections to determine the smallest
-** snapshot id that is currently in use by a database client. The worker
-** connection uses this result to determine whether or not it is safe to
-** recycle a database block.
-*/
-static int firstSnapshotInUse(
- lsm_db *db, /* Database handle */
- i64 *piInUse /* IN/OUT: Smallest snapshot id in use */
-){
- ShmHeader *pShm = db->pShmhdr;
- i64 iInUse = *piInUse;
- int i;
-
- assert( iInUse>0 );
- for(i=0; i<LSM_LOCK_NREADER; i++){
- ShmReader *p = &pShm->aReader[i];
- if( p->iLsmId ){
- i64 iThis = p->iLsmId;
- if( iThis!=0 && iInUse>iThis ){
- int rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
- if( rc==LSM_OK ){
- p->iLsmId = 0;
- lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
- }else if( rc==LSM_BUSY ){
- iInUse = iThis;
- }else{
- /* Some error other than LSM_BUSY. Return the error code to
- ** the caller in this case. */
- return rc;
- }
- }
- }
- }
-
- *piInUse = iInUse;
- return LSM_OK;
-}
-
-int lsmTreeInUse(lsm_db *db, u32 iShmid, int *pbInUse){
- if( db->treehdr.iUsedShmid==iShmid ){
- *pbInUse = 1;
- return LSM_OK;
- }
- return isInUse(db, 0, iShmid, pbInUse);
-}
-
-int lsmLsmInUse(lsm_db *db, i64 iLsmId, int *pbInUse){
- if( db->pClient && db->pClient->iId<=iLsmId ){
- *pbInUse = 1;
- return LSM_OK;
- }
- return isInUse(db, iLsmId, 0, pbInUse);
-}
-
-/*
-** This function may only be called after a successful call to
-** lsmDbDatabaseConnect(). It returns true if the connection is in
-** multi-process mode, or false otherwise.
-*/
-int lsmDbMultiProc(lsm_db *pDb){
- return pDb->pDatabase && pDb->pDatabase->bMultiProc;
-}
-
-
-/*************************************************************************
-**************************************************************************
-**************************************************************************
-**************************************************************************
-**************************************************************************
-*************************************************************************/
-
-/*
-** Ensure that database connection db has cached pointers to at least the
-** first nChunk chunks of shared memory.
-*/
-int lsmShmCacheChunks(lsm_db *db, int nChunk){
- int rc = LSM_OK;
- if( nChunk>db->nShm ){
- static const int NINCR = 16;
- Database *p = db->pDatabase;
- lsm_env *pEnv = db->pEnv;
- int nAlloc;
- int i;
-
- /* Ensure that the db->apShm[] array is large enough. If an attempt to
- ** allocate memory fails, return LSM_NOMEM immediately. The apShm[] array
- ** is always extended in multiples of 16 entries - so the actual allocated
- ** size can be inferred from nShm. */
- nAlloc = ((db->nShm + NINCR - 1) / NINCR) * NINCR;
- while( nChunk>=nAlloc ){
- void **apShm;
- nAlloc += NINCR;
- apShm = lsmRealloc(pEnv, db->apShm, sizeof(void*)*nAlloc);
- if( !apShm ) return LSM_NOMEM_BKPT;
- db->apShm = apShm;
- }
-
- if( db->bRoTrans ){
- for(i=db->nShm; rc==LSM_OK && i<nChunk; i++){
- db->apShm[i] = lsmMallocZeroRc(pEnv, LSM_SHM_CHUNK_SIZE, &rc);
- db->nShm++;
- }
-
- }else{
-
- /* Enter the client mutex */
- lsmMutexEnter(pEnv, p->pClientMutex);
-
- /* Extend the Database objects apShmChunk[] array if necessary. Using the
- ** same pattern as for the lsm_db.apShm[] array above. */
- nAlloc = ((p->nShmChunk + NINCR - 1) / NINCR) * NINCR;
- while( nChunk>=nAlloc ){
- void **apShm;
- nAlloc += NINCR;
- apShm = lsmRealloc(pEnv, p->apShmChunk, sizeof(void*)*nAlloc);
- if( !apShm ){
- rc = LSM_NOMEM_BKPT;
- break;
- }
- p->apShmChunk = apShm;
- }
-
- for(i=db->nShm; rc==LSM_OK && i<nChunk; i++){
- if( i>=p->nShmChunk ){
- void *pChunk = 0;
- if( p->bMultiProc==0 ){
- /* Single process mode */
- pChunk = lsmMallocZeroRc(pEnv, LSM_SHM_CHUNK_SIZE, &rc);
- }else{
- /* Multi-process mode */
- rc = lsmEnvShmMap(pEnv, p->pFile, i, LSM_SHM_CHUNK_SIZE, &pChunk);
- }
- if( rc==LSM_OK ){
- p->apShmChunk[i] = pChunk;
- p->nShmChunk++;
- }
- }
- if( rc==LSM_OK ){
- db->apShm[i] = p->apShmChunk[i];
- db->nShm++;
- }
- }
-
- /* Release the client mutex */
- lsmMutexLeave(pEnv, p->pClientMutex);
- }
- }
-
- return rc;
-}
-
-static int lockSharedFile(lsm_env *pEnv, Database *p, int iLock, int eOp){
- int rc = LSM_OK;
- if( p->bMultiProc ){
- rc = lsmEnvLock(pEnv, p->pFile, iLock, eOp);
- }
- return rc;
-}
-
-/*
-** Test if it would be possible for connection db to obtain a lock of type
-** eType on the nLock locks starting at iLock. If so, return LSM_OK. If it
-** would not be possible to obtain the lock due to a lock held by another
-** connection, return LSM_BUSY. If an IO or other error occurs (i.e. in the
-** lsm_env.xTestLock function), return some other LSM error code.
-**
-** Note that this function never actually locks the database - it merely
-** queries the system to see if there exists a lock that would prevent
-** it from doing so.
-*/
-int lsmShmTestLock(
- lsm_db *db,
- int iLock,
- int nLock,
- int eOp
-){
- int rc = LSM_OK;
- lsm_db *pIter;
- Database *p = db->pDatabase;
- int i;
- u64 mask = 0;
-
- for(i=iLock; i<(iLock+nLock); i++){
- mask |= ((u64)1 << (iLock-1));
- if( eOp==LSM_LOCK_EXCL ) mask |= ((u64)1 << (iLock+32-1));
- }
-
- lsmMutexEnter(db->pEnv, p->pClientMutex);
- for(pIter=p->pConn; pIter; pIter=pIter->pNext){
- if( pIter!=db && (pIter->mLock & mask) ){
- assert( pIter!=db );
- break;
- }
- }
-
- if( pIter ){
- rc = LSM_BUSY;
- }else if( p->bMultiProc ){
- rc = lsmEnvTestLock(db->pEnv, p->pFile, iLock, nLock, eOp);
- }
-
- lsmMutexLeave(db->pEnv, p->pClientMutex);
- return rc;
-}
-
-/*
-** Attempt to obtain the lock identified by the iLock and bExcl parameters.
-** If successful, return LSM_OK. If the lock cannot be obtained because
-** there exists some other conflicting lock, return LSM_BUSY. If some other
-** error occurs, return an LSM error code.
-**
-** Parameter iLock must be one of LSM_LOCK_WRITER, WORKER or CHECKPOINTER,
-** or else a value returned by the LSM_LOCK_READER macro.
-*/
-int lsmShmLock(
- lsm_db *db,
- int iLock,
- int eOp, /* One of LSM_LOCK_UNLOCK, SHARED or EXCL */
- int bBlock /* True for a blocking lock */
-){
- lsm_db *pIter;
- const u64 me = ((u64)1 << (iLock-1));
- const u64 ms = ((u64)1 << (iLock+32-1));
- int rc = LSM_OK;
- Database *p = db->pDatabase;
-
- assert( eOp!=LSM_LOCK_EXCL || p->bReadonly==0 );
- assert( iLock>=1 && iLock<=LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT-1) );
- assert( LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT-1)<=32 );
- assert( eOp==LSM_LOCK_UNLOCK || eOp==LSM_LOCK_SHARED || eOp==LSM_LOCK_EXCL );
-
- /* Check for a no-op. Proceed only if this is not one of those. */
- if( (eOp==LSM_LOCK_UNLOCK && (db->mLock & (me|ms))!=0)
- || (eOp==LSM_LOCK_SHARED && (db->mLock & (me|ms))!=ms)
- || (eOp==LSM_LOCK_EXCL && (db->mLock & me)==0)
- ){
- int nExcl = 0; /* Number of connections holding EXCLUSIVE */
- int nShared = 0; /* Number of connections holding SHARED */
- lsmMutexEnter(db->pEnv, p->pClientMutex);
-
- /* Figure out the locks currently held by this process on iLock, not
- ** including any held by connection db. */
- for(pIter=p->pConn; pIter; pIter=pIter->pNext){
- assert( (pIter->mLock & me)==0 || (pIter->mLock & ms)!=0 );
- if( pIter!=db ){
- if( pIter->mLock & me ){
- nExcl++;
- }else if( pIter->mLock & ms ){
- nShared++;
- }
- }
- }
- assert( nExcl==0 || nExcl==1 );
- assert( nExcl==0 || nShared==0 );
- assert( nExcl==0 || (db->mLock & (me|ms))==0 );
-
- switch( eOp ){
- case LSM_LOCK_UNLOCK:
- if( nShared==0 ){
- lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_UNLOCK);
- }
- db->mLock &= ~(me|ms);
- break;
-
- case LSM_LOCK_SHARED:
- if( nExcl ){
- rc = LSM_BUSY;
- }else{
- if( nShared==0 ){
- rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_SHARED);
- }
- if( rc==LSM_OK ){
- db->mLock |= ms;
- db->mLock &= ~me;
- }
- }
- break;
-
- default:
- assert( eOp==LSM_LOCK_EXCL );
- if( nExcl || nShared ){
- rc = LSM_BUSY;
- }else{
- rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_EXCL);
- if( rc==LSM_OK ){
- db->mLock |= (me|ms);
- }
- }
- break;
- }
-
- lsmMutexLeave(db->pEnv, p->pClientMutex);
- }
-
- return rc;
-}
-
-#ifdef LSM_DEBUG
-
-int shmLockType(lsm_db *db, int iLock){
- const u64 me = ((u64)1 << (iLock-1));
- const u64 ms = ((u64)1 << (iLock+32-1));
-
- if( db->mLock & me ) return LSM_LOCK_EXCL;
- if( db->mLock & ms ) return LSM_LOCK_SHARED;
- return LSM_LOCK_UNLOCK;
-}
-
-/*
-** The arguments passed to this function are similar to those passed to
-** the lsmShmLock() function. However, instead of obtaining a new lock
-** this function returns true if the specified connection already holds
-** (or does not hold) such a lock, depending on the value of eOp. As
-** follows:
-**
-** (eOp==LSM_LOCK_UNLOCK) -> true if db has no lock on iLock
-** (eOp==LSM_LOCK_SHARED) -> true if db has at least a SHARED lock on iLock.
-** (eOp==LSM_LOCK_EXCL) -> true if db has an EXCLUSIVE lock on iLock.
-*/
-int lsmShmAssertLock(lsm_db *db, int iLock, int eOp){
- int ret = 0;
- int eHave;
-
- assert( iLock>=1 && iLock<=LSM_LOCK_READER(LSM_LOCK_NREADER-1) );
- assert( iLock<=16 );
- assert( eOp==LSM_LOCK_UNLOCK || eOp==LSM_LOCK_SHARED || eOp==LSM_LOCK_EXCL );
-
- eHave = shmLockType(db, iLock);
-
- switch( eOp ){
- case LSM_LOCK_UNLOCK:
- ret = (eHave==LSM_LOCK_UNLOCK);
- break;
- case LSM_LOCK_SHARED:
- ret = (eHave!=LSM_LOCK_UNLOCK);
- break;
- case LSM_LOCK_EXCL:
- ret = (eHave==LSM_LOCK_EXCL);
- break;
- default:
- assert( !"bad eOp value passed to lsmShmAssertLock()" );
- break;
- }
-
- return ret;
-}
-
-int lsmShmAssertWorker(lsm_db *db){
- return lsmShmAssertLock(db, LSM_LOCK_WORKER, LSM_LOCK_EXCL) && db->pWorker;
-}
-
-/*
-** This function does not contribute to library functionality, and is not
-** included in release builds. It is intended to be called from within
-** an interactive debugger.
-**
-** When called, this function prints a single line of human readable output
-** to stdout describing the locks currently held by the connection. For
-** example:
-**
-** (gdb) call print_db_locks(pDb)
-** (shared on dms2) (exclusive on writer)
-*/
-void print_db_locks(lsm_db *db){
- int iLock;
- for(iLock=0; iLock<16; iLock++){
- int bOne = 0;
- const char *azLock[] = {0, "shared", "exclusive"};
- const char *azName[] = {
- 0, "dms1", "dms2", "writer", "worker", "checkpointer",
- "reader0", "reader1", "reader2", "reader3", "reader4", "reader5"
- };
- int eHave = shmLockType(db, iLock);
- if( azLock[eHave] ){
- printf("%s(%s on %s)", (bOne?" ":""), azLock[eHave], azName[iLock]);
- bOne = 1;
- }
- }
- printf("\n");
-}
-void print_all_db_locks(lsm_db *db){
- lsm_db *p;
- for(p=db->pDatabase->pConn; p; p=p->pNext){
- printf("%s connection %p ", ((p==db)?"*":""), p);
- print_db_locks(p);
- }
-}
-#endif
-
-void lsmShmBarrier(lsm_db *db){
- lsmEnvShmBarrier(db->pEnv);
-}
-
-int lsm_checkpoint(lsm_db *pDb, int *pnKB){
- int rc; /* Return code */
- u32 nWrite = 0; /* Number of pages checkpointed */
-
- /* Attempt the checkpoint. If successful, nWrite is set to the number of
- ** pages written between this and the previous checkpoint. */
- rc = lsmCheckpointWrite(pDb, &nWrite);
-
- /* If required, calculate the output variable (KB of data checkpointed).
- ** Set it to zero if an error occured. */
- if( pnKB ){
- int nKB = 0;
- if( rc==LSM_OK && nWrite ){
- nKB = (((i64)nWrite * lsmFsPageSize(pDb->pFS)) + 1023) / 1024;
- }
- *pnKB = nKB;
- }
-
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_sorted.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_sorted.c
deleted file mode 100644
index de962b88085..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_sorted.c
+++ /dev/null
@@ -1,6187 +0,0 @@
-/*
-** 2011-08-14
-**
-** 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.
-**
-*************************************************************************
-**
-** PAGE FORMAT:
-**
-** The maximum page size is 65536 bytes.
-**
-** Since all records are equal to or larger than 2 bytes in size, and
-** some space within the page is consumed by the page footer, there must
-** be less than 2^15 records on each page.
-**
-** Each page ends with a footer that describes the pages contents. This
-** footer serves as similar purpose to the page header in an SQLite database.
-** A footer is used instead of a header because it makes it easier to
-** populate a new page based on a sorted list of key/value pairs.
-**
-** The footer consists of the following values (starting at the end of
-** the page and continuing backwards towards the start). All values are
-** stored as unsigned big-endian integers.
-**
-** * Number of records on page (2 bytes).
-** * Flags field (2 bytes).
-** * Left-hand pointer value (8 bytes).
-** * The starting offset of each record (2 bytes per record).
-**
-** Records may span pages. Unless it happens to be an exact fit, the part
-** of the final record that starts on page X that does not fit on page X
-** is stored at the start of page (X+1). This means there may be pages where
-** (N==0). And on most pages the first record that starts on the page will
-** not start at byte offset 0. For example:
-**
-** aaaaa bbbbb ccc <footer> cc eeeee fffff g <footer> gggg....
-**
-** RECORD FORMAT:
-**
-** The first byte of the record is a flags byte. It is a combination
-** of the following flags (defined in lsmInt.h):
-**
-** LSM_START_DELETE
-** LSM_END_DELETE
-** LSM_POINT_DELETE
-** LSM_INSERT
-** LSM_SEPARATOR
-** LSM_SYSTEMKEY
-**
-** Immediately following the type byte is a pointer to the smallest key
-** in the next file that is larger than the key in the current record. The
-** pointer is encoded as a varint. When added to the 32-bit page number
-** stored in the footer, it is the page number of the page that contains the
-** smallest key in the next sorted file that is larger than this key.
-**
-** Next is the number of bytes in the key, encoded as a varint.
-**
-** If the LSM_INSERT flag is set, the number of bytes in the value, as
-** a varint, is next.
-**
-** Finally, the blob of data containing the key, and for LSM_INSERT
-** records, the value as well.
-*/
-
-#ifndef _LSM_INT_H
-# include "lsmInt.h"
-#endif
-
-#define LSM_LOG_STRUCTURE 0
-#define LSM_LOG_DATA 0
-
-/*
-** Macros to help decode record types.
-*/
-#define rtTopic(eType) ((eType) & LSM_SYSTEMKEY)
-#define rtIsDelete(eType) (((eType) & 0x0F)==LSM_POINT_DELETE)
-
-#define rtIsSeparator(eType) (((eType) & LSM_SEPARATOR)!=0)
-#define rtIsWrite(eType) (((eType) & LSM_INSERT)!=0)
-#define rtIsSystem(eType) (((eType) & LSM_SYSTEMKEY)!=0)
-
-/*
-** The following macros are used to access a page footer.
-*/
-#define SEGMENT_NRECORD_OFFSET(pgsz) ((pgsz) - 2)
-#define SEGMENT_FLAGS_OFFSET(pgsz) ((pgsz) - 2 - 2)
-#define SEGMENT_POINTER_OFFSET(pgsz) ((pgsz) - 2 - 2 - 8)
-#define SEGMENT_CELLPTR_OFFSET(pgsz, iCell) ((pgsz) - 2 - 2 - 8 - 2 - (iCell)*2)
-
-#define SEGMENT_EOF(pgsz, nEntry) SEGMENT_CELLPTR_OFFSET(pgsz, nEntry-1)
-
-#define SEGMENT_BTREE_FLAG 0x0001
-#define PGFTR_SKIP_NEXT_FLAG 0x0002
-#define PGFTR_SKIP_THIS_FLAG 0x0004
-
-
-#ifndef LSM_SEGMENTPTR_FREE_THRESHOLD
-# define LSM_SEGMENTPTR_FREE_THRESHOLD 1024
-#endif
-
-typedef struct SegmentPtr SegmentPtr;
-typedef struct LsmBlob LsmBlob;
-
-struct LsmBlob {
- lsm_env *pEnv;
- void *pData;
- int nData;
- int nAlloc;
-};
-
-/*
-** A SegmentPtr object may be used for one of two purposes:
-**
-** * To iterate and/or seek within a single Segment (the combination of a
-** main run and an optional sorted run).
-**
-** * To iterate through the separators array of a segment.
-*/
-struct SegmentPtr {
- Level *pLevel; /* Level object segment is part of */
- Segment *pSeg; /* Segment to access */
-
- /* Current page. See segmentPtrLoadPage(). */
- Page *pPg; /* Current page */
- u16 flags; /* Copy of page flags field */
- int nCell; /* Number of cells on pPg */
- LsmPgno iPtr; /* Base cascade pointer */
-
- /* Current cell. See segmentPtrLoadCell() */
- int iCell; /* Current record within page pPg */
- int eType; /* Type of current record */
- LsmPgno iPgPtr; /* Cascade pointer offset */
- void *pKey; int nKey; /* Key associated with current record */
- void *pVal; int nVal; /* Current record value (eType==WRITE only) */
-
- /* Blobs used to allocate buffers for pKey and pVal as required */
- LsmBlob blob1;
- LsmBlob blob2;
-};
-
-/*
-** Used to iterate through the keys stored in a b-tree hierarchy from start
-** to finish. Only First() and Next() operations are required.
-**
-** btreeCursorNew()
-** btreeCursorFirst()
-** btreeCursorNext()
-** btreeCursorFree()
-** btreeCursorPosition()
-** btreeCursorRestore()
-*/
-typedef struct BtreePg BtreePg;
-typedef struct BtreeCursor BtreeCursor;
-struct BtreePg {
- Page *pPage;
- int iCell;
-};
-struct BtreeCursor {
- Segment *pSeg; /* Iterate through this segments btree */
- FileSystem *pFS; /* File system to read pages from */
- int nDepth; /* Allocated size of aPg[] */
- int iPg; /* Current entry in aPg[]. -1 -> EOF. */
- BtreePg *aPg; /* Pages from root to current location */
-
- /* Cache of current entry. pKey==0 for EOF. */
- void *pKey;
- int nKey;
- int eType;
- LsmPgno iPtr;
-
- /* Storage for key, if not local */
- LsmBlob blob;
-};
-
-
-/*
-** A cursor used for merged searches or iterations through up to one
-** Tree structure and any number of sorted files.
-**
-** lsmMCursorNew()
-** lsmMCursorSeek()
-** lsmMCursorNext()
-** lsmMCursorPrev()
-** lsmMCursorFirst()
-** lsmMCursorLast()
-** lsmMCursorKey()
-** lsmMCursorValue()
-** lsmMCursorValid()
-**
-** iFree:
-** This variable is only used by cursors providing input data for a
-** new top-level segment. Such cursors only ever iterate forwards, not
-** backwards.
-*/
-struct MultiCursor {
- lsm_db *pDb; /* Connection that owns this cursor */
- MultiCursor *pNext; /* Next cursor owned by connection pDb */
- int flags; /* Mask of CURSOR_XXX flags */
-
- int eType; /* Cache of current key type */
- LsmBlob key; /* Cache of current key (or NULL) */
- LsmBlob val; /* Cache of current value */
-
- /* All the component cursors: */
- TreeCursor *apTreeCsr[2]; /* Up to two tree cursors */
- int iFree; /* Next element of free-list (-ve for eof) */
- SegmentPtr *aPtr; /* Array of segment pointers */
- int nPtr; /* Size of array aPtr[] */
- BtreeCursor *pBtCsr; /* b-tree cursor (db writes only) */
-
- /* Comparison results */
- int nTree; /* Size of aTree[] array */
- int *aTree; /* Array of comparison results */
-
- /* Used by cursors flushing the in-memory tree only */
- void *pSystemVal; /* Pointer to buffer to free */
-
- /* Used by worker cursors only */
- LsmPgno *pPrevMergePtr;
-};
-
-/*
-** The following constants are used to assign integers to each component
-** cursor of a multi-cursor.
-*/
-#define CURSOR_DATA_TREE0 0 /* Current tree cursor (apTreeCsr[0]) */
-#define CURSOR_DATA_TREE1 1 /* The "old" tree, if any (apTreeCsr[1]) */
-#define CURSOR_DATA_SYSTEM 2 /* Free-list entries (new-toplevel only) */
-#define CURSOR_DATA_SEGMENT 3 /* First segment pointer (aPtr[0]) */
-
-/*
-** CURSOR_IGNORE_DELETE
-** If set, this cursor will not visit SORTED_DELETE keys.
-**
-** CURSOR_FLUSH_FREELIST
-** This cursor is being used to create a new toplevel. It should also
-** iterate through the contents of the in-memory free block list.
-**
-** CURSOR_IGNORE_SYSTEM
-** If set, this cursor ignores system keys.
-**
-** CURSOR_NEXT_OK
-** Set if it is Ok to call lsm_csr_next().
-**
-** CURSOR_PREV_OK
-** Set if it is Ok to call lsm_csr_prev().
-**
-** CURSOR_READ_SEPARATORS
-** Set if this cursor should visit the separator keys in segment
-** aPtr[nPtr-1].
-**
-** CURSOR_SEEK_EQ
-** Cursor has undergone a successful lsm_csr_seek(LSM_SEEK_EQ) operation.
-** The key and value are stored in MultiCursor.key and MultiCursor.val
-** respectively.
-*/
-#define CURSOR_IGNORE_DELETE 0x00000001
-#define CURSOR_FLUSH_FREELIST 0x00000002
-#define CURSOR_IGNORE_SYSTEM 0x00000010
-#define CURSOR_NEXT_OK 0x00000020
-#define CURSOR_PREV_OK 0x00000040
-#define CURSOR_READ_SEPARATORS 0x00000080
-#define CURSOR_SEEK_EQ 0x00000100
-
-typedef struct MergeWorker MergeWorker;
-typedef struct Hierarchy Hierarchy;
-
-struct Hierarchy {
- Page **apHier;
- int nHier;
-};
-
-/*
-** aSave:
-** When mergeWorkerNextPage() is called to advance to the next page in
-** the output segment, if the bStore flag for an element of aSave[] is
-** true, it is cleared and the corresponding iPgno value is set to the
-** page number of the page just completed.
-**
-** aSave[0] is used to record the pointer value to be pushed into the
-** b-tree hierarchy. aSave[1] is used to save the page number of the
-** page containing the indirect key most recently written to the b-tree.
-** see mergeWorkerPushHierarchy() for details.
-*/
-struct MergeWorker {
- lsm_db *pDb; /* Database handle */
- Level *pLevel; /* Worker snapshot Level being merged */
- MultiCursor *pCsr; /* Cursor to read new segment contents from */
- int bFlush; /* True if this is an in-memory tree flush */
- Hierarchy hier; /* B-tree hierarchy under construction */
- Page *pPage; /* Current output page */
- int nWork; /* Number of calls to mergeWorkerNextPage() */
- LsmPgno *aGobble; /* Gobble point for each input segment */
-
- LsmPgno iIndirect;
- struct SavedPgno {
- LsmPgno iPgno;
- int bStore;
- } aSave[2];
-};
-
-#ifdef LSM_DEBUG_EXPENSIVE
-static int assertPointersOk(lsm_db *, Segment *, Segment *, int);
-static int assertBtreeOk(lsm_db *, Segment *);
-static void assertRunInOrder(lsm_db *pDb, Segment *pSeg);
-#else
-#define assertRunInOrder(x,y)
-#define assertBtreeOk(x,y)
-#endif
-
-
-struct FilePage { u8 *aData; int nData; };
-static u8 *fsPageData(Page *pPg, int *pnData){
- *pnData = ((struct FilePage *)(pPg))->nData;
- return ((struct FilePage *)(pPg))->aData;
-}
-/*UNUSED static u8 *fsPageDataPtr(Page *pPg){
- return ((struct FilePage *)(pPg))->aData;
-}*/
-
-/*
-** Write nVal as a 16-bit unsigned big-endian integer into buffer aOut.
-*/
-void lsmPutU16(u8 *aOut, u16 nVal){
- aOut[0] = (u8)((nVal>>8) & 0xFF);
- aOut[1] = (u8)(nVal & 0xFF);
-}
-
-void lsmPutU32(u8 *aOut, u32 nVal){
- aOut[0] = (u8)((nVal>>24) & 0xFF);
- aOut[1] = (u8)((nVal>>16) & 0xFF);
- aOut[2] = (u8)((nVal>> 8) & 0xFF);
- aOut[3] = (u8)((nVal ) & 0xFF);
-}
-
-int lsmGetU16(u8 *aOut){
- return (aOut[0] << 8) + aOut[1];
-}
-
-u32 lsmGetU32(u8 *aOut){
- return ((u32)aOut[0] << 24)
- + ((u32)aOut[1] << 16)
- + ((u32)aOut[2] << 8)
- + ((u32)aOut[3]);
-}
-
-u64 lsmGetU64(u8 *aOut){
- return ((u64)aOut[0] << 56)
- + ((u64)aOut[1] << 48)
- + ((u64)aOut[2] << 40)
- + ((u64)aOut[3] << 32)
- + ((u64)aOut[4] << 24)
- + ((u32)aOut[5] << 16)
- + ((u32)aOut[6] << 8)
- + ((u32)aOut[7]);
-}
-
-void lsmPutU64(u8 *aOut, u64 nVal){
- aOut[0] = (u8)((nVal>>56) & 0xFF);
- aOut[1] = (u8)((nVal>>48) & 0xFF);
- aOut[2] = (u8)((nVal>>40) & 0xFF);
- aOut[3] = (u8)((nVal>>32) & 0xFF);
- aOut[4] = (u8)((nVal>>24) & 0xFF);
- aOut[5] = (u8)((nVal>>16) & 0xFF);
- aOut[6] = (u8)((nVal>> 8) & 0xFF);
- aOut[7] = (u8)((nVal ) & 0xFF);
-}
-
-static int sortedBlobGrow(lsm_env *pEnv, LsmBlob *pBlob, int nData){
- assert( pBlob->pEnv==pEnv || (pBlob->pEnv==0 && pBlob->pData==0) );
- if( pBlob->nAlloc<nData ){
- pBlob->pData = lsmReallocOrFree(pEnv, pBlob->pData, nData);
- if( !pBlob->pData ) return LSM_NOMEM_BKPT;
- pBlob->nAlloc = nData;
- pBlob->pEnv = pEnv;
- }
- return LSM_OK;
-}
-
-static int sortedBlobSet(lsm_env *pEnv, LsmBlob *pBlob, void *pData, int nData){
- if( sortedBlobGrow(pEnv, pBlob, nData) ) return LSM_NOMEM;
- memcpy(pBlob->pData, pData, nData);
- pBlob->nData = nData;
- return LSM_OK;
-}
-
-#if 0
-static int sortedBlobCopy(LsmBlob *pDest, LsmBlob *pSrc){
- return sortedBlobSet(pDest, pSrc->pData, pSrc->nData);
-}
-#endif
-
-static void sortedBlobFree(LsmBlob *pBlob){
- assert( pBlob->pEnv || pBlob->pData==0 );
- if( pBlob->pData ) lsmFree(pBlob->pEnv, pBlob->pData);
- memset(pBlob, 0, sizeof(LsmBlob));
-}
-
-static int sortedReadData(
- Segment *pSeg,
- Page *pPg,
- int iOff,
- int nByte,
- void **ppData,
- LsmBlob *pBlob
-){
- int rc = LSM_OK;
- int iEnd;
- int nData;
- int nCell;
- u8 *aData;
-
- aData = fsPageData(pPg, &nData);
- nCell = lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]);
- iEnd = SEGMENT_EOF(nData, nCell);
- assert( iEnd>0 && iEnd<nData );
-
- if( iOff+nByte<=iEnd ){
- *ppData = (void *)&aData[iOff];
- }else{
- int nRem = nByte;
- int i = iOff;
- u8 *aDest;
-
- /* Make sure the blob is big enough to store the value being loaded. */
- rc = sortedBlobGrow(lsmPageEnv(pPg), pBlob, nByte);
- if( rc!=LSM_OK ) return rc;
- pBlob->nData = nByte;
- aDest = (u8 *)pBlob->pData;
- *ppData = pBlob->pData;
-
- /* Increment the pointer pages ref-count. */
- lsmFsPageRef(pPg);
-
- while( rc==LSM_OK ){
- Page *pNext;
- int flags;
-
- /* Copy data from pPg into the output buffer. */
- int nCopy = LSM_MIN(nRem, iEnd-i);
- if( nCopy>0 ){
- memcpy(&aDest[nByte-nRem], &aData[i], nCopy);
- nRem -= nCopy;
- i += nCopy;
- assert( nRem==0 || i==iEnd );
- }
- assert( nRem>=0 );
- if( nRem==0 ) break;
- i -= iEnd;
-
- /* Grab the next page in the segment */
-
- do {
- rc = lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
- if( rc==LSM_OK && pNext==0 ){
- rc = LSM_CORRUPT_BKPT;
- }
- if( rc ) break;
- lsmFsPageRelease(pPg);
- pPg = pNext;
- aData = fsPageData(pPg, &nData);
- flags = lsmGetU16(&aData[SEGMENT_FLAGS_OFFSET(nData)]);
- }while( flags&SEGMENT_BTREE_FLAG );
-
- iEnd = SEGMENT_EOF(nData, lsmGetU16(&aData[nData-2]));
- assert( iEnd>0 && iEnd<nData );
- }
-
- lsmFsPageRelease(pPg);
- }
-
- return rc;
-}
-
-static int pageGetNRec(u8 *aData, int nData){
- return (int)lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]);
-}
-
-static LsmPgno pageGetPtr(u8 *aData, int nData){
- return (LsmPgno)lsmGetU64(&aData[SEGMENT_POINTER_OFFSET(nData)]);
-}
-
-static int pageGetFlags(u8 *aData, int nData){
- return (int)lsmGetU16(&aData[SEGMENT_FLAGS_OFFSET(nData)]);
-}
-
-static u8 *pageGetCell(u8 *aData, int nData, int iCell){
- return &aData[lsmGetU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, iCell)])];
-}
-
-/*
-** Return the number of cells on page pPg.
-*/
-static int pageObjGetNRec(Page *pPg){
- int nData;
- u8 *aData = lsmFsPageData(pPg, &nData);
- return pageGetNRec(aData, nData);
-}
-
-/*
-** Return the decoded (possibly relative) pointer value stored in cell
-** iCell from page aData/nData.
-*/
-static LsmPgno pageGetRecordPtr(u8 *aData, int nData, int iCell){
- LsmPgno iRet; /* Return value */
- u8 *aCell; /* Pointer to cell iCell */
-
- assert( iCell<pageGetNRec(aData, nData) && iCell>=0 );
- aCell = pageGetCell(aData, nData, iCell);
- lsmVarintGet64(&aCell[1], &iRet);
- return iRet;
-}
-
-static u8 *pageGetKey(
- Segment *pSeg, /* Segment pPg belongs to */
- Page *pPg, /* Page to read from */
- int iCell, /* Index of cell on page to read */
- int *piTopic, /* OUT: Topic associated with this key */
- int *pnKey, /* OUT: Size of key in bytes */
- LsmBlob *pBlob /* If required, use this for dynamic memory */
-){
- u8 *pKey;
- int nDummy;
- int eType;
- u8 *aData;
- int nData;
-
- aData = fsPageData(pPg, &nData);
-
- assert( !(pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) );
- assert( iCell<pageGetNRec(aData, nData) );
-
- pKey = pageGetCell(aData, nData, iCell);
- eType = *pKey++;
- pKey += lsmVarintGet32(pKey, &nDummy);
- pKey += lsmVarintGet32(pKey, pnKey);
- if( rtIsWrite(eType) ){
- pKey += lsmVarintGet32(pKey, &nDummy);
- }
- *piTopic = rtTopic(eType);
-
- sortedReadData(pSeg, pPg, pKey-aData, *pnKey, (void **)&pKey, pBlob);
- return pKey;
-}
-
-static int pageGetKeyCopy(
- lsm_env *pEnv, /* Environment handle */
- Segment *pSeg, /* Segment pPg belongs to */
- Page *pPg, /* Page to read from */
- int iCell, /* Index of cell on page to read */
- int *piTopic, /* OUT: Topic associated with this key */
- LsmBlob *pBlob /* If required, use this for dynamic memory */
-){
- int rc = LSM_OK;
- int nKey;
- u8 *aKey;
-
- aKey = pageGetKey(pSeg, pPg, iCell, piTopic, &nKey, pBlob);
- assert( (void *)aKey!=pBlob->pData || nKey==pBlob->nData );
- if( (void *)aKey!=pBlob->pData ){
- rc = sortedBlobSet(pEnv, pBlob, aKey, nKey);
- }
-
- return rc;
-}
-
-static LsmPgno pageGetBtreeRef(Page *pPg, int iKey){
- LsmPgno iRef;
- u8 *aData;
- int nData;
- u8 *aCell;
-
- aData = fsPageData(pPg, &nData);
- aCell = pageGetCell(aData, nData, iKey);
- assert( aCell[0]==0 );
- aCell++;
- aCell += lsmVarintGet64(aCell, &iRef);
- lsmVarintGet64(aCell, &iRef);
- assert( iRef>0 );
- return iRef;
-}
-
-#define GETVARINT64(a, i) (((i)=((u8*)(a))[0])<=240?1:lsmVarintGet64((a), &(i)))
-#define GETVARINT32(a, i) (((i)=((u8*)(a))[0])<=240?1:lsmVarintGet32((a), &(i)))
-
-static int pageGetBtreeKey(
- Segment *pSeg, /* Segment page pPg belongs to */
- Page *pPg,
- int iKey,
- LsmPgno *piPtr,
- int *piTopic,
- void **ppKey,
- int *pnKey,
- LsmBlob *pBlob
-){
- u8 *aData;
- int nData;
- u8 *aCell;
- int eType;
-
- aData = fsPageData(pPg, &nData);
- assert( SEGMENT_BTREE_FLAG & pageGetFlags(aData, nData) );
- assert( iKey>=0 && iKey<pageGetNRec(aData, nData) );
-
- aCell = pageGetCell(aData, nData, iKey);
- eType = *aCell++;
- aCell += GETVARINT64(aCell, *piPtr);
-
- if( eType==0 ){
- int rc;
- LsmPgno iRef; /* Page number of referenced page */
- Page *pRef;
- aCell += GETVARINT64(aCell, iRef);
- rc = lsmFsDbPageGet(lsmPageFS(pPg), pSeg, iRef, &pRef);
- if( rc!=LSM_OK ) return rc;
- pageGetKeyCopy(lsmPageEnv(pPg), pSeg, pRef, 0, &eType, pBlob);
- lsmFsPageRelease(pRef);
- *ppKey = pBlob->pData;
- *pnKey = pBlob->nData;
- }else{
- aCell += GETVARINT32(aCell, *pnKey);
- *ppKey = aCell;
- }
- if( piTopic ) *piTopic = rtTopic(eType);
-
- return LSM_OK;
-}
-
-static int btreeCursorLoadKey(BtreeCursor *pCsr){
- int rc = LSM_OK;
- if( pCsr->iPg<0 ){
- pCsr->pKey = 0;
- pCsr->nKey = 0;
- pCsr->eType = 0;
- }else{
- LsmPgno dummy;
- int iPg = pCsr->iPg;
- int iCell = pCsr->aPg[iPg].iCell;
- while( iCell<0 && (--iPg)>=0 ){
- iCell = pCsr->aPg[iPg].iCell-1;
- }
- if( iPg<0 || iCell<0 ) return LSM_CORRUPT_BKPT;
-
- rc = pageGetBtreeKey(
- pCsr->pSeg,
- pCsr->aPg[iPg].pPage, iCell,
- &dummy, &pCsr->eType, &pCsr->pKey, &pCsr->nKey, &pCsr->blob
- );
- pCsr->eType |= LSM_SEPARATOR;
- }
-
- return rc;
-}
-
-static int btreeCursorPtr(u8 *aData, int nData, int iCell){
- int nCell;
-
- nCell = pageGetNRec(aData, nData);
- if( iCell>=nCell ){
- return (int)pageGetPtr(aData, nData);
- }
- return (int)pageGetRecordPtr(aData, nData, iCell);
-}
-
-static int btreeCursorNext(BtreeCursor *pCsr){
- int rc = LSM_OK;
-
- BtreePg *pPg = &pCsr->aPg[pCsr->iPg];
- int nCell;
- u8 *aData;
- int nData;
-
- assert( pCsr->iPg>=0 );
- assert( pCsr->iPg==pCsr->nDepth-1 );
-
- aData = fsPageData(pPg->pPage, &nData);
- nCell = pageGetNRec(aData, nData);
- assert( pPg->iCell<=nCell );
- pPg->iCell++;
- if( pPg->iCell==nCell ){
- LsmPgno iLoad;
-
- /* Up to parent. */
- lsmFsPageRelease(pPg->pPage);
- pPg->pPage = 0;
- pCsr->iPg--;
- while( pCsr->iPg>=0 ){
- pPg = &pCsr->aPg[pCsr->iPg];
- aData = fsPageData(pPg->pPage, &nData);
- if( pPg->iCell<pageGetNRec(aData, nData) ) break;
- lsmFsPageRelease(pPg->pPage);
- pCsr->iPg--;
- }
-
- /* Read the key */
- rc = btreeCursorLoadKey(pCsr);
-
- /* Unless the cursor is at EOF, descend to cell -1 (yes, negative one) of
- ** the left-most most descendent. */
- if( pCsr->iPg>=0 ){
- pCsr->aPg[pCsr->iPg].iCell++;
-
- iLoad = btreeCursorPtr(aData, nData, pPg->iCell);
- do {
- Page *pLoad;
- pCsr->iPg++;
- rc = lsmFsDbPageGet(pCsr->pFS, pCsr->pSeg, iLoad, &pLoad);
- pCsr->aPg[pCsr->iPg].pPage = pLoad;
- pCsr->aPg[pCsr->iPg].iCell = 0;
- if( rc==LSM_OK ){
- if( pCsr->iPg==(pCsr->nDepth-1) ) break;
- aData = fsPageData(pLoad, &nData);
- iLoad = btreeCursorPtr(aData, nData, 0);
- }
- }while( rc==LSM_OK && pCsr->iPg<(pCsr->nDepth-1) );
- pCsr->aPg[pCsr->iPg].iCell = -1;
- }
-
- }else{
- rc = btreeCursorLoadKey(pCsr);
- }
-
- if( rc==LSM_OK && pCsr->iPg>=0 ){
- aData = fsPageData(pCsr->aPg[pCsr->iPg].pPage, &nData);
- pCsr->iPtr = btreeCursorPtr(aData, nData, pCsr->aPg[pCsr->iPg].iCell+1);
- }
-
- return rc;
-}
-
-static void btreeCursorFree(BtreeCursor *pCsr){
- if( pCsr ){
- int i;
- lsm_env *pEnv = lsmFsEnv(pCsr->pFS);
- for(i=0; i<=pCsr->iPg; i++){
- lsmFsPageRelease(pCsr->aPg[i].pPage);
- }
- sortedBlobFree(&pCsr->blob);
- lsmFree(pEnv, pCsr->aPg);
- lsmFree(pEnv, pCsr);
- }
-}
-
-static int btreeCursorFirst(BtreeCursor *pCsr){
- int rc;
-
- Page *pPg = 0;
- FileSystem *pFS = pCsr->pFS;
- int iPg = (int)pCsr->pSeg->iRoot;
-
- do {
- rc = lsmFsDbPageGet(pFS, pCsr->pSeg, iPg, &pPg);
- assert( (rc==LSM_OK)==(pPg!=0) );
- if( rc==LSM_OK ){
- u8 *aData;
- int nData;
- int flags;
-
- aData = fsPageData(pPg, &nData);
- flags = pageGetFlags(aData, nData);
- if( (flags & SEGMENT_BTREE_FLAG)==0 ) break;
-
- if( (pCsr->nDepth % 8)==0 ){
- int nNew = pCsr->nDepth + 8;
- pCsr->aPg = (BtreePg *)lsmReallocOrFreeRc(
- lsmFsEnv(pFS), pCsr->aPg, sizeof(BtreePg) * nNew, &rc
- );
- if( rc==LSM_OK ){
- memset(&pCsr->aPg[pCsr->nDepth], 0, sizeof(BtreePg) * 8);
- }
- }
-
- if( rc==LSM_OK ){
- assert( pCsr->aPg[pCsr->nDepth].iCell==0 );
- pCsr->aPg[pCsr->nDepth].pPage = pPg;
- pCsr->nDepth++;
- iPg = (int)pageGetRecordPtr(aData, nData, 0);
- }
- }
- }while( rc==LSM_OK );
- lsmFsPageRelease(pPg);
- pCsr->iPg = pCsr->nDepth-1;
-
- if( rc==LSM_OK && pCsr->nDepth ){
- pCsr->aPg[pCsr->iPg].iCell = -1;
- rc = btreeCursorNext(pCsr);
- }
-
- return rc;
-}
-
-static void btreeCursorPosition(BtreeCursor *pCsr, MergeInput *p){
- if( pCsr->iPg>=0 ){
- p->iPg = lsmFsPageNumber(pCsr->aPg[pCsr->iPg].pPage);
- p->iCell = ((pCsr->aPg[pCsr->iPg].iCell + 1) << 8) + pCsr->nDepth;
- }else{
- p->iPg = 0;
- p->iCell = 0;
- }
-}
-
-static void btreeCursorSplitkey(BtreeCursor *pCsr, MergeInput *p){
- int iCell = pCsr->aPg[pCsr->iPg].iCell;
- if( iCell>=0 ){
- p->iCell = iCell;
- p->iPg = lsmFsPageNumber(pCsr->aPg[pCsr->iPg].pPage);
- }else{
- int i;
- for(i=pCsr->iPg-1; i>=0; i--){
- if( pCsr->aPg[i].iCell>0 ) break;
- }
- assert( i>=0 );
- p->iCell = pCsr->aPg[i].iCell-1;
- p->iPg = lsmFsPageNumber(pCsr->aPg[i].pPage);
- }
-}
-
-static int sortedKeyCompare(
- int (*xCmp)(void *, int, void *, int),
- int iLhsTopic, void *pLhsKey, int nLhsKey,
- int iRhsTopic, void *pRhsKey, int nRhsKey
-){
- int res = iLhsTopic - iRhsTopic;
- if( res==0 ){
- res = xCmp(pLhsKey, nLhsKey, pRhsKey, nRhsKey);
- }
- return res;
-}
-
-static int btreeCursorRestore(
- BtreeCursor *pCsr,
- int (*xCmp)(void *, int, void *, int),
- MergeInput *p
-){
- int rc = LSM_OK;
-
- if( p->iPg ){
- lsm_env *pEnv = lsmFsEnv(pCsr->pFS);
- int iCell; /* Current cell number on leaf page */
- LsmPgno iLeaf; /* Page number of current leaf page */
- int nDepth; /* Depth of b-tree structure */
- Segment *pSeg = pCsr->pSeg;
-
- /* Decode the MergeInput structure */
- iLeaf = p->iPg;
- nDepth = (p->iCell & 0x00FF);
- iCell = (p->iCell >> 8) - 1;
-
- /* Allocate the BtreeCursor.aPg[] array */
- assert( pCsr->aPg==0 );
- pCsr->aPg = (BtreePg *)lsmMallocZeroRc(pEnv, sizeof(BtreePg) * nDepth, &rc);
-
- /* Populate the last entry of the aPg[] array */
- if( rc==LSM_OK ){
- Page **pp = &pCsr->aPg[nDepth-1].pPage;
- pCsr->iPg = nDepth-1;
- pCsr->nDepth = nDepth;
- pCsr->aPg[pCsr->iPg].iCell = iCell;
- rc = lsmFsDbPageGet(pCsr->pFS, pSeg, iLeaf, pp);
- }
-
- /* Populate any other aPg[] array entries */
- if( rc==LSM_OK && nDepth>1 ){
- LsmBlob blob = {0,0,0};
- void *pSeek;
- int nSeek;
- int iTopicSeek;
- int iPg = 0;
- int iLoad = (int)pSeg->iRoot;
- Page *pPg = pCsr->aPg[nDepth-1].pPage;
-
- if( pageObjGetNRec(pPg)==0 ){
- /* This can happen when pPg is the right-most leaf in the b-tree.
- ** In this case, set the iTopicSeek/pSeek/nSeek key to a value
- ** greater than any real key. */
- assert( iCell==-1 );
- iTopicSeek = 1000;
- pSeek = 0;
- nSeek = 0;
- }else{
- LsmPgno dummy;
- rc = pageGetBtreeKey(pSeg, pPg,
- 0, &dummy, &iTopicSeek, &pSeek, &nSeek, &pCsr->blob
- );
- }
-
- do {
- Page *pPg2;
- rc = lsmFsDbPageGet(pCsr->pFS, pSeg, iLoad, &pPg2);
- assert( rc==LSM_OK || pPg2==0 );
- if( rc==LSM_OK ){
- u8 *aData; /* Buffer containing page data */
- int nData; /* Size of aData[] in bytes */
- int iMin;
- int iMax;
- int iCell2;
-
- aData = fsPageData(pPg2, &nData);
- assert( (pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) );
-
- iLoad = (int)pageGetPtr(aData, nData);
- iCell2 = pageGetNRec(aData, nData);
- iMax = iCell2-1;
- iMin = 0;
-
- while( iMax>=iMin ){
- int iTry = (iMin+iMax)/2;
- void *pKey; int nKey; /* Key for cell iTry */
- int iTopic; /* Topic for key pKeyT/nKeyT */
- LsmPgno iPtr; /* Pointer for cell iTry */
- int res; /* (pSeek - pKeyT) */
-
- rc = pageGetBtreeKey(
- pSeg, pPg2, iTry, &iPtr, &iTopic, &pKey, &nKey, &blob
- );
- if( rc!=LSM_OK ) break;
-
- res = sortedKeyCompare(
- xCmp, iTopicSeek, pSeek, nSeek, iTopic, pKey, nKey
- );
- assert( res!=0 );
-
- if( res<0 ){
- iLoad = (int)iPtr;
- iCell2 = iTry;
- iMax = iTry-1;
- }else{
- iMin = iTry+1;
- }
- }
-
- pCsr->aPg[iPg].pPage = pPg2;
- pCsr->aPg[iPg].iCell = iCell2;
- iPg++;
- assert( iPg!=nDepth-1
- || lsmFsRedirectPage(pCsr->pFS, pSeg->pRedirect, iLoad)==iLeaf
- );
- }
- }while( rc==LSM_OK && iPg<(nDepth-1) );
- sortedBlobFree(&blob);
- }
-
- /* Load the current key and pointer */
- if( rc==LSM_OK ){
- BtreePg *pBtreePg;
- u8 *aData;
- int nData;
-
- pBtreePg = &pCsr->aPg[pCsr->iPg];
- aData = fsPageData(pBtreePg->pPage, &nData);
- pCsr->iPtr = btreeCursorPtr(aData, nData, pBtreePg->iCell+1);
- if( pBtreePg->iCell<0 ){
- LsmPgno dummy;
- int i;
- for(i=pCsr->iPg-1; i>=0; i--){
- if( pCsr->aPg[i].iCell>0 ) break;
- }
- assert( i>=0 );
- rc = pageGetBtreeKey(pSeg,
- pCsr->aPg[i].pPage, pCsr->aPg[i].iCell-1,
- &dummy, &pCsr->eType, &pCsr->pKey, &pCsr->nKey, &pCsr->blob
- );
- pCsr->eType |= LSM_SEPARATOR;
-
- }else{
- rc = btreeCursorLoadKey(pCsr);
- }
- }
- }
- return rc;
-}
-
-static int btreeCursorNew(
- lsm_db *pDb,
- Segment *pSeg,
- BtreeCursor **ppCsr
-){
- int rc = LSM_OK;
- BtreeCursor *pCsr;
-
- assert( pSeg->iRoot );
- pCsr = lsmMallocZeroRc(pDb->pEnv, sizeof(BtreeCursor), &rc);
- if( pCsr ){
- pCsr->pFS = pDb->pFS;
- pCsr->pSeg = pSeg;
- pCsr->iPg = -1;
- }
-
- *ppCsr = pCsr;
- return rc;
-}
-
-static void segmentPtrSetPage(SegmentPtr *pPtr, Page *pNext){
- lsmFsPageRelease(pPtr->pPg);
- if( pNext ){
- int nData;
- u8 *aData = fsPageData(pNext, &nData);
- pPtr->nCell = pageGetNRec(aData, nData);
- pPtr->flags = (u16)pageGetFlags(aData, nData);
- pPtr->iPtr = pageGetPtr(aData, nData);
- }
- pPtr->pPg = pNext;
-}
-
-/*
-** Load a new page into the SegmentPtr object pPtr.
-*/
-static int segmentPtrLoadPage(
- FileSystem *pFS,
- SegmentPtr *pPtr, /* Load page into this SegmentPtr object */
- int iNew /* Page number of new page */
-){
- Page *pPg = 0; /* The new page */
- int rc; /* Return Code */
-
- rc = lsmFsDbPageGet(pFS, pPtr->pSeg, iNew, &pPg);
- assert( rc==LSM_OK || pPg==0 );
- segmentPtrSetPage(pPtr, pPg);
-
- return rc;
-}
-
-static int segmentPtrReadData(
- SegmentPtr *pPtr,
- int iOff,
- int nByte,
- void **ppData,
- LsmBlob *pBlob
-){
- return sortedReadData(pPtr->pSeg, pPtr->pPg, iOff, nByte, ppData, pBlob);
-}
-
-static int segmentPtrNextPage(
- SegmentPtr *pPtr, /* Load page into this SegmentPtr object */
- int eDir /* +1 for next(), -1 for prev() */
-){
- Page *pNext; /* New page to load */
- int rc; /* Return code */
-
- assert( eDir==1 || eDir==-1 );
- assert( pPtr->pPg );
- assert( pPtr->pSeg || eDir>0 );
-
- rc = lsmFsDbPageNext(pPtr->pSeg, pPtr->pPg, eDir, &pNext);
- assert( rc==LSM_OK || pNext==0 );
- segmentPtrSetPage(pPtr, pNext);
- return rc;
-}
-
-static int segmentPtrLoadCell(
- SegmentPtr *pPtr, /* Load page into this SegmentPtr object */
- int iNew /* Cell number of new cell */
-){
- int rc = LSM_OK;
- if( pPtr->pPg ){
- u8 *aData; /* Pointer to page data buffer */
- int iOff; /* Offset in aData[] to read from */
- int nPgsz; /* Size of page (aData[]) in bytes */
-
- assert( iNew<pPtr->nCell );
- pPtr->iCell = iNew;
- aData = fsPageData(pPtr->pPg, &nPgsz);
- iOff = lsmGetU16(&aData[SEGMENT_CELLPTR_OFFSET(nPgsz, pPtr->iCell)]);
- pPtr->eType = aData[iOff];
- iOff++;
- iOff += GETVARINT64(&aData[iOff], pPtr->iPgPtr);
- iOff += GETVARINT32(&aData[iOff], pPtr->nKey);
- if( rtIsWrite(pPtr->eType) ){
- iOff += GETVARINT32(&aData[iOff], pPtr->nVal);
- }
- assert( pPtr->nKey>=0 );
-
- rc = segmentPtrReadData(
- pPtr, iOff, pPtr->nKey, &pPtr->pKey, &pPtr->blob1
- );
- if( rc==LSM_OK && rtIsWrite(pPtr->eType) ){
- rc = segmentPtrReadData(
- pPtr, iOff+pPtr->nKey, pPtr->nVal, &pPtr->pVal, &pPtr->blob2
- );
- }else{
- pPtr->nVal = 0;
- pPtr->pVal = 0;
- }
- }
-
- return rc;
-}
-
-
-static Segment *sortedSplitkeySegment(Level *pLevel){
- Merge *pMerge = pLevel->pMerge;
- MergeInput *p = &pMerge->splitkey;
- Segment *pSeg;
- int i;
-
- for(i=0; i<pMerge->nInput; i++){
- if( p->iPg==pMerge->aInput[i].iPg ) break;
- }
- if( pMerge->nInput==(pLevel->nRight+1) && i>=(pMerge->nInput-1) ){
- pSeg = &pLevel->pNext->lhs;
- }else{
- pSeg = &pLevel->aRhs[i];
- }
-
- return pSeg;
-}
-
-static void sortedSplitkey(lsm_db *pDb, Level *pLevel, int *pRc){
- Segment *pSeg;
- Page *pPg = 0;
- lsm_env *pEnv = pDb->pEnv; /* Environment handle */
- int rc = *pRc;
- Merge *pMerge = pLevel->pMerge;
-
- pSeg = sortedSplitkeySegment(pLevel);
- if( rc==LSM_OK ){
- rc = lsmFsDbPageGet(pDb->pFS, pSeg, pMerge->splitkey.iPg, &pPg);
- }
- if( rc==LSM_OK ){
- int iTopic;
- LsmBlob blob = {0, 0, 0, 0};
- u8 *aData;
- int nData;
-
- aData = lsmFsPageData(pPg, &nData);
- if( pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG ){
- void *pKey;
- int nKey;
- LsmPgno dummy;
- rc = pageGetBtreeKey(pSeg,
- pPg, pMerge->splitkey.iCell, &dummy, &iTopic, &pKey, &nKey, &blob
- );
- if( rc==LSM_OK && blob.pData!=pKey ){
- rc = sortedBlobSet(pEnv, &blob, pKey, nKey);
- }
- }else{
- rc = pageGetKeyCopy(
- pEnv, pSeg, pPg, pMerge->splitkey.iCell, &iTopic, &blob
- );
- }
-
- pLevel->iSplitTopic = iTopic;
- pLevel->pSplitKey = blob.pData;
- pLevel->nSplitKey = blob.nData;
- lsmFsPageRelease(pPg);
- }
-
- *pRc = rc;
-}
-
-/*
-** Reset a segment cursor. Also free its buffers if they are nThreshold
-** bytes or larger in size.
-*/
-static void segmentPtrReset(SegmentPtr *pPtr, int nThreshold){
- lsmFsPageRelease(pPtr->pPg);
- pPtr->pPg = 0;
- pPtr->nCell = 0;
- pPtr->pKey = 0;
- pPtr->nKey = 0;
- pPtr->pVal = 0;
- pPtr->nVal = 0;
- pPtr->eType = 0;
- pPtr->iCell = 0;
- if( pPtr->blob1.nAlloc>=nThreshold ) sortedBlobFree(&pPtr->blob1);
- if( pPtr->blob2.nAlloc>=nThreshold ) sortedBlobFree(&pPtr->blob2);
-}
-
-static int segmentPtrIgnoreSeparators(MultiCursor *pCsr, SegmentPtr *pPtr){
- return (pCsr->flags & CURSOR_READ_SEPARATORS)==0
- || (pPtr!=&pCsr->aPtr[pCsr->nPtr-1]);
-}
-
-static int segmentPtrAdvance(
- MultiCursor *pCsr,
- SegmentPtr *pPtr,
- int bReverse
-){
- int eDir = (bReverse ? -1 : 1);
- Level *pLvl = pPtr->pLevel;
- do {
- int rc;
- int iCell; /* Number of new cell in page */
- int svFlags = 0; /* SegmentPtr.eType before advance */
-
- iCell = pPtr->iCell + eDir;
- assert( pPtr->pPg );
- assert( iCell<=pPtr->nCell && iCell>=-1 );
-
- if( bReverse && pPtr->pSeg!=&pPtr->pLevel->lhs ){
- svFlags = pPtr->eType;
- assert( svFlags );
- }
-
- if( iCell>=pPtr->nCell || iCell<0 ){
- do {
- rc = segmentPtrNextPage(pPtr, eDir);
- }while( rc==LSM_OK
- && pPtr->pPg
- && (pPtr->nCell==0 || (pPtr->flags & SEGMENT_BTREE_FLAG) )
- );
- if( rc!=LSM_OK ) return rc;
- iCell = bReverse ? (pPtr->nCell-1) : 0;
- }
- rc = segmentPtrLoadCell(pPtr, iCell);
- if( rc!=LSM_OK ) return rc;
-
- if( svFlags && pPtr->pPg ){
- int res = sortedKeyCompare(pCsr->pDb->xCmp,
- rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey,
- pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
- );
- if( res<0 ) segmentPtrReset(pPtr, LSM_SEGMENTPTR_FREE_THRESHOLD);
- }
-
- if( pPtr->pPg==0 && (svFlags & LSM_END_DELETE) ){
- Segment *pSeg = pPtr->pSeg;
- rc = lsmFsDbPageGet(pCsr->pDb->pFS, pSeg, pSeg->iFirst, &pPtr->pPg);
- if( rc!=LSM_OK ) return rc;
- pPtr->eType = LSM_START_DELETE | LSM_POINT_DELETE;
- pPtr->eType |= (pLvl->iSplitTopic ? LSM_SYSTEMKEY : 0);
- pPtr->pKey = pLvl->pSplitKey;
- pPtr->nKey = pLvl->nSplitKey;
- }
-
- }while( pCsr
- && pPtr->pPg
- && segmentPtrIgnoreSeparators(pCsr, pPtr)
- && rtIsSeparator(pPtr->eType)
- );
-
- return LSM_OK;
-}
-
-static void segmentPtrEndPage(
- FileSystem *pFS,
- SegmentPtr *pPtr,
- int bLast,
- int *pRc
-){
- if( *pRc==LSM_OK ){
- Segment *pSeg = pPtr->pSeg;
- Page *pNew = 0;
- if( bLast ){
- *pRc = lsmFsDbPageLast(pFS, pSeg, &pNew);
- }else{
- *pRc = lsmFsDbPageGet(pFS, pSeg, pSeg->iFirst, &pNew);
- }
- segmentPtrSetPage(pPtr, pNew);
- }
-}
-
-
-/*
-** Try to move the segment pointer passed as the second argument so that it
-** points at either the first (bLast==0) or last (bLast==1) cell in the valid
-** region of the segment defined by pPtr->iFirst and pPtr->iLast.
-**
-** Return LSM_OK if successful or an lsm error code if something goes
-** wrong (IO error, OOM etc.).
-*/
-static int segmentPtrEnd(MultiCursor *pCsr, SegmentPtr *pPtr, int bLast){
- Level *pLvl = pPtr->pLevel;
- int rc = LSM_OK;
- FileSystem *pFS = pCsr->pDb->pFS;
- int bIgnore;
-
- segmentPtrEndPage(pFS, pPtr, bLast, &rc);
- while( rc==LSM_OK && pPtr->pPg
- && (pPtr->nCell==0 || (pPtr->flags & SEGMENT_BTREE_FLAG))
- ){
- rc = segmentPtrNextPage(pPtr, (bLast ? -1 : 1));
- }
-
- if( rc==LSM_OK && pPtr->pPg ){
- rc = segmentPtrLoadCell(pPtr, bLast ? (pPtr->nCell-1) : 0);
- if( rc==LSM_OK && bLast && pPtr->pSeg!=&pLvl->lhs ){
- int res = sortedKeyCompare(pCsr->pDb->xCmp,
- rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey,
- pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
- );
- if( res<0 ) segmentPtrReset(pPtr, LSM_SEGMENTPTR_FREE_THRESHOLD);
- }
- }
-
- bIgnore = segmentPtrIgnoreSeparators(pCsr, pPtr);
- if( rc==LSM_OK && pPtr->pPg && bIgnore && rtIsSeparator(pPtr->eType) ){
- rc = segmentPtrAdvance(pCsr, pPtr, bLast);
- }
-
-#if 0
- if( bLast && rc==LSM_OK && pPtr->pPg
- && pPtr->pSeg==&pLvl->lhs
- && pLvl->nRight && (pPtr->eType & LSM_START_DELETE)
- ){
- pPtr->iCell++;
- pPtr->eType = LSM_END_DELETE | (pLvl->iSplitTopic);
- pPtr->pKey = pLvl->pSplitKey;
- pPtr->nKey = pLvl->nSplitKey;
- pPtr->pVal = 0;
- pPtr->nVal = 0;
- }
-#endif
-
- return rc;
-}
-
-static void segmentPtrKey(SegmentPtr *pPtr, void **ppKey, int *pnKey){
- assert( pPtr->pPg );
- *ppKey = pPtr->pKey;
- *pnKey = pPtr->nKey;
-}
-
-#if 0 /* NOT USED */
-static char *keyToString(lsm_env *pEnv, void *pKey, int nKey){
- int i;
- u8 *aKey = (u8 *)pKey;
- char *zRet = (char *)lsmMalloc(pEnv, nKey+1);
-
- for(i=0; i<nKey; i++){
- zRet[i] = (char)(isalnum(aKey[i]) ? aKey[i] : '.');
- }
- zRet[nKey] = '\0';
- return zRet;
-}
-#endif
-
-#if 0 /* NOT USED */
-/*
-** Check that the page that pPtr currently has loaded is the correct page
-** to search for key (pKey/nKey). If it is, return 1. Otherwise, an assert
-** fails and this function does not return.
-*/
-static int assertKeyLocation(
- MultiCursor *pCsr,
- SegmentPtr *pPtr,
- void *pKey, int nKey
-){
- lsm_env *pEnv = lsmFsEnv(pCsr->pDb->pFS);
- LsmBlob blob = {0, 0, 0};
- int eDir;
- int iTopic = 0; /* TODO: Fix me */
-
- for(eDir=-1; eDir<=1; eDir+=2){
- Page *pTest = pPtr->pPg;
-
- lsmFsPageRef(pTest);
- while( pTest ){
- Segment *pSeg = pPtr->pSeg;
- Page *pNext;
-
- int rc = lsmFsDbPageNext(pSeg, pTest, eDir, &pNext);
- lsmFsPageRelease(pTest);
- if( rc ) return 1;
- pTest = pNext;
-
- if( pTest ){
- int nData;
- u8 *aData = fsPageData(pTest, &nData);
- int nCell = pageGetNRec(aData, nData);
- int flags = pageGetFlags(aData, nData);
- if( nCell && 0==(flags&SEGMENT_BTREE_FLAG) ){
- int nPgKey;
- int iPgTopic;
- u8 *pPgKey;
- int res;
- int iCell;
-
- iCell = ((eDir < 0) ? (nCell-1) : 0);
- pPgKey = pageGetKey(pSeg, pTest, iCell, &iPgTopic, &nPgKey, &blob);
- res = iTopic - iPgTopic;
- if( res==0 ) res = pCsr->pDb->xCmp(pKey, nKey, pPgKey, nPgKey);
- if( (eDir==1 && res>0) || (eDir==-1 && res<0) ){
- /* Taking this branch means something has gone wrong. */
- char *zMsg = lsmMallocPrintf(pEnv, "Key \"%s\" is not on page %d",
- keyToString(pEnv, pKey, nKey), lsmFsPageNumber(pPtr->pPg)
- );
- fprintf(stderr, "%s\n", zMsg);
- assert( !"assertKeyLocation() failed" );
- }
- lsmFsPageRelease(pTest);
- pTest = 0;
- }
- }
- }
- }
-
- sortedBlobFree(&blob);
- return 1;
-}
-#endif
-
-#ifndef NDEBUG
-static int assertSeekResult(
- MultiCursor *pCsr,
- SegmentPtr *pPtr,
- int iTopic,
- void *pKey,
- int nKey,
- int eSeek
-){
- if( pPtr->pPg ){
- int res;
- res = sortedKeyCompare(pCsr->pDb->xCmp, iTopic, pKey, nKey,
- rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey
- );
-
- if( eSeek==LSM_SEEK_EQ ) return (res==0);
- if( eSeek==LSM_SEEK_LE ) return (res>=0);
- if( eSeek==LSM_SEEK_GE ) return (res<=0);
- }
-
- return 1;
-}
-#endif
-
-static int segmentPtrSearchOversized(
- MultiCursor *pCsr, /* Cursor context */
- SegmentPtr *pPtr, /* Pointer to seek */
- int iTopic, /* Topic of key to search for */
- void *pKey, int nKey /* Key to seek to */
-){
- int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
- int rc = LSM_OK;
-
- /* If the OVERSIZED flag is set, then there is no pointer in the
- ** upper level to the next page in the segment that contains at least
- ** one key. So compare the largest key on the current page with the
- ** key being sought (pKey/nKey). If (pKey/nKey) is larger, advance
- ** to the next page in the segment that contains at least one key.
- */
- while( rc==LSM_OK && (pPtr->flags & PGFTR_SKIP_NEXT_FLAG) ){
- u8 *pLastKey;
- int nLastKey;
- int iLastTopic;
- int res; /* Result of comparison */
- Page *pNext;
-
- /* Load the last key on the current page. */
- pLastKey = pageGetKey(pPtr->pSeg,
- pPtr->pPg, pPtr->nCell-1, &iLastTopic, &nLastKey, &pPtr->blob1
- );
-
- /* If the loaded key is >= than (pKey/nKey), break out of the loop.
- ** If (pKey/nKey) is present in this array, it must be on the current
- ** page. */
- res = sortedKeyCompare(
- xCmp, iLastTopic, pLastKey, nLastKey, iTopic, pKey, nKey
- );
- if( res>=0 ) break;
-
- /* Advance to the next page that contains at least one key. */
- pNext = pPtr->pPg;
- lsmFsPageRef(pNext);
- while( 1 ){
- Page *pLoad;
- u8 *aData; int nData;
-
- rc = lsmFsDbPageNext(pPtr->pSeg, pNext, 1, &pLoad);
- lsmFsPageRelease(pNext);
- pNext = pLoad;
- if( pNext==0 ) break;
-
- assert( rc==LSM_OK );
- aData = lsmFsPageData(pNext, &nData);
- if( (pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG)==0
- && pageGetNRec(aData, nData)>0
- ){
- break;
- }
- }
- if( pNext==0 ) break;
- segmentPtrSetPage(pPtr, pNext);
-
- /* This should probably be an LSM_CORRUPT error. */
- assert( rc!=LSM_OK || (pPtr->flags & PGFTR_SKIP_THIS_FLAG) );
- }
-
- return rc;
-}
-
-static int ptrFwdPointer(
- Page *pPage,
- int iCell,
- Segment *pSeg,
- LsmPgno *piPtr,
- int *pbFound
-){
- Page *pPg = pPage;
- int iFirst = iCell;
- int rc = LSM_OK;
-
- do {
- Page *pNext = 0;
- u8 *aData;
- int nData;
-
- aData = lsmFsPageData(pPg, &nData);
- if( (pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG)==0 ){
- int i;
- int nCell = pageGetNRec(aData, nData);
- for(i=iFirst; i<nCell; i++){
- u8 eType = *pageGetCell(aData, nData, i);
- if( (eType & LSM_START_DELETE)==0 ){
- *pbFound = 1;
- *piPtr = pageGetRecordPtr(aData, nData, i) + pageGetPtr(aData, nData);
- lsmFsPageRelease(pPg);
- return LSM_OK;
- }
- }
- }
-
- rc = lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
- lsmFsPageRelease(pPg);
- pPg = pNext;
- iFirst = 0;
- }while( pPg && rc==LSM_OK );
- lsmFsPageRelease(pPg);
-
- *pbFound = 0;
- return rc;
-}
-
-static int sortedRhsFirst(MultiCursor *pCsr, Level *pLvl, SegmentPtr *pPtr){
- int rc;
- rc = segmentPtrEnd(pCsr, pPtr, 0);
- while( pPtr->pPg && rc==LSM_OK ){
- int res = sortedKeyCompare(pCsr->pDb->xCmp,
- pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey,
- rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey
- );
- if( res<=0 ) break;
- rc = segmentPtrAdvance(pCsr, pPtr, 0);
- }
- return rc;
-}
-
-
-/*
-** This function is called as part of a SEEK_GE op on a multi-cursor if the
-** FC pointer read from segment *pPtr comes from an entry with the
-** LSM_START_DELETE flag set. In this case the pointer value cannot be
-** trusted. Instead, the pointer that should be followed is that associated
-** with the next entry in *pPtr that does not have LSM_START_DELETE set.
-**
-** Why the pointers can't be trusted:
-**
-**
-**
-** TODO: This is a stop-gap solution:
-**
-** At the moment, this function is called from within segmentPtrSeek(),
-** as part of the initial lsmMCursorSeek() call. However, consider a
-** database where the following has occurred:
-**
-** 1. A range delete removes keys 1..9999 using a range delete.
-** 2. Keys 1 through 9999 are reinserted.
-** 3. The levels containing the ops in 1. and 2. above are merged. Call
-** this level N. Level N contains FC pointers to level N+1.
-**
-** Then, if the user attempts to query for (key>=2 LIMIT 10), the
-** lsmMCursorSeek() call will iterate through 9998 entries searching for a
-** pointer down to the level N+1 that is never actually used. It would be
-** much better if the multi-cursor could do this lazily - only seek to the
-** level (N+1) page after the user has moved the cursor on level N passed
-** the big range-delete.
-*/
-static int segmentPtrFwdPointer(
- MultiCursor *pCsr, /* Multi-cursor pPtr belongs to */
- SegmentPtr *pPtr, /* Segment-pointer to extract FC ptr from */
- LsmPgno *piPtr /* OUT: FC pointer value */
-){
- Level *pLvl = pPtr->pLevel;
- Level *pNext = pLvl->pNext;
- Page *pPg = pPtr->pPg;
- int rc;
- int bFound;
- LsmPgno iOut = 0;
-
- if( pPtr->pSeg==&pLvl->lhs || pPtr->pSeg==&pLvl->aRhs[pLvl->nRight-1] ){
- if( pNext==0
- || (pNext->nRight==0 && pNext->lhs.iRoot)
- || (pNext->nRight!=0 && pNext->aRhs[0].iRoot)
- ){
- /* Do nothing. The pointer will not be used anyway. */
- return LSM_OK;
- }
- }else{
- if( pPtr[1].pSeg->iRoot ){
- return LSM_OK;
- }
- }
-
- /* Search for a pointer within the current segment. */
- lsmFsPageRef(pPg);
- rc = ptrFwdPointer(pPg, pPtr->iCell, pPtr->pSeg, &iOut, &bFound);
-
- if( rc==LSM_OK && bFound==0 ){
- /* This case happens when pPtr points to the left-hand-side of a segment
- ** currently undergoing an incremental merge. In this case, jump to the
- ** oldest segment in the right-hand-side of the same level and continue
- ** searching. But - do not consider any keys smaller than the levels
- ** split-key. */
- SegmentPtr ptr;
-
- if( pPtr->pLevel->nRight==0 || pPtr->pSeg!=&pPtr->pLevel->lhs ){
- return LSM_CORRUPT_BKPT;
- }
-
- memset(&ptr, 0, sizeof(SegmentPtr));
- ptr.pLevel = pPtr->pLevel;
- ptr.pSeg = &ptr.pLevel->aRhs[ptr.pLevel->nRight-1];
- rc = sortedRhsFirst(pCsr, ptr.pLevel, &ptr);
- if( rc==LSM_OK ){
- rc = ptrFwdPointer(ptr.pPg, ptr.iCell, ptr.pSeg, &iOut, &bFound);
- ptr.pPg = 0;
- }
- segmentPtrReset(&ptr, 0);
- }
-
- *piPtr = iOut;
- return rc;
-}
-
-static int segmentPtrSeek(
- MultiCursor *pCsr, /* Cursor context */
- SegmentPtr *pPtr, /* Pointer to seek */
- int iTopic, /* Key topic to seek to */
- void *pKey, int nKey, /* Key to seek to */
- int eSeek, /* Search bias - see above */
- int *piPtr, /* OUT: FC pointer */
- int *pbStop
-){
- int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
- int res = 0; /* Result of comparison operation */
- int rc = LSM_OK;
- int iMin;
- int iMax;
- LsmPgno iPtrOut = 0;
-
- /* If the current page contains an oversized entry, then there are no
- ** pointers to one or more of the subsequent pages in the sorted run.
- ** The following call ensures that the segment-ptr points to the correct
- ** page in this case. */
- rc = segmentPtrSearchOversized(pCsr, pPtr, iTopic, pKey, nKey);
- iPtrOut = pPtr->iPtr;
-
- /* Assert that this page is the right page of this segment for the key
- ** that we are searching for. Do this by loading page (iPg-1) and testing
- ** that pKey/nKey is greater than all keys on that page, and then by
- ** loading (iPg+1) and testing that pKey/nKey is smaller than all
- ** the keys it houses.
- **
- ** TODO: With range-deletes in the tree, the test described above may fail.
- */
-#if 0
- assert( assertKeyLocation(pCsr, pPtr, pKey, nKey) );
-#endif
-
- assert( pPtr->nCell>0
- || pPtr->pSeg->nSize==1
- || lsmFsDbPageIsLast(pPtr->pSeg, pPtr->pPg)
- );
- if( pPtr->nCell==0 ){
- segmentPtrReset(pPtr, LSM_SEGMENTPTR_FREE_THRESHOLD);
- }else{
- iMin = 0;
- iMax = pPtr->nCell-1;
-
- while( 1 ){
- int iTry = (iMin+iMax)/2;
- void *pKeyT; int nKeyT; /* Key for cell iTry */
- int iTopicT;
-
- assert( iTry<iMax || iMin==iMax );
-
- rc = segmentPtrLoadCell(pPtr, iTry);
- if( rc!=LSM_OK ) break;
-
- segmentPtrKey(pPtr, &pKeyT, &nKeyT);
- iTopicT = rtTopic(pPtr->eType);
-
- res = sortedKeyCompare(xCmp, iTopicT, pKeyT, nKeyT, iTopic, pKey, nKey);
- if( res<=0 ){
- iPtrOut = pPtr->iPtr + pPtr->iPgPtr;
- }
-
- if( res==0 || iMin==iMax ){
- break;
- }else if( res>0 ){
- iMax = LSM_MAX(iTry-1, iMin);
- }else{
- iMin = iTry+1;
- }
- }
-
- if( rc==LSM_OK ){
- assert( res==0 || (iMin==iMax && iMin>=0 && iMin<pPtr->nCell) );
- if( res ){
- rc = segmentPtrLoadCell(pPtr, iMin);
- }
- assert( rc!=LSM_OK || res>0 || iPtrOut==(pPtr->iPtr + pPtr->iPgPtr) );
-
- if( rc==LSM_OK ){
- switch( eSeek ){
- case LSM_SEEK_EQ: {
- int eType = pPtr->eType;
- if( (res<0 && (eType & LSM_START_DELETE))
- || (res>0 && (eType & LSM_END_DELETE))
- || (res==0 && (eType & LSM_POINT_DELETE))
- ){
- *pbStop = 1;
- }else if( res==0 && (eType & LSM_INSERT) ){
- lsm_env *pEnv = pCsr->pDb->pEnv;
- *pbStop = 1;
- pCsr->eType = pPtr->eType;
- rc = sortedBlobSet(pEnv, &pCsr->key, pPtr->pKey, pPtr->nKey);
- if( rc==LSM_OK ){
- rc = sortedBlobSet(pEnv, &pCsr->val, pPtr->pVal, pPtr->nVal);
- }
- pCsr->flags |= CURSOR_SEEK_EQ;
- }
- segmentPtrReset(pPtr, LSM_SEGMENTPTR_FREE_THRESHOLD);
- break;
- }
- case LSM_SEEK_LE:
- if( res>0 ) rc = segmentPtrAdvance(pCsr, pPtr, 1);
- break;
- case LSM_SEEK_GE: {
- /* Figure out if we need to 'skip' the pointer forward or not */
- if( (res<=0 && (pPtr->eType & LSM_START_DELETE))
- || (res>0 && (pPtr->eType & LSM_END_DELETE))
- ){
- rc = segmentPtrFwdPointer(pCsr, pPtr, &iPtrOut);
- }
- if( res<0 && rc==LSM_OK ){
- rc = segmentPtrAdvance(pCsr, pPtr, 0);
- }
- break;
- }
- }
- }
- }
-
- /* If the cursor seek has found a separator key, and this cursor is
- ** supposed to ignore separators keys, advance to the next entry. */
- if( rc==LSM_OK && pPtr->pPg
- && segmentPtrIgnoreSeparators(pCsr, pPtr)
- && rtIsSeparator(pPtr->eType)
- ){
- assert( eSeek!=LSM_SEEK_EQ );
- rc = segmentPtrAdvance(pCsr, pPtr, eSeek==LSM_SEEK_LE);
- }
- }
-
- assert( rc!=LSM_OK || assertSeekResult(pCsr,pPtr,iTopic,pKey,nKey,eSeek) );
- *piPtr = (int)iPtrOut;
- return rc;
-}
-
-static int seekInBtree(
- MultiCursor *pCsr, /* Multi-cursor object */
- Segment *pSeg, /* Seek within this segment */
- int iTopic,
- void *pKey, int nKey, /* Key to seek to */
- LsmPgno *aPg, /* OUT: Page numbers */
- Page **ppPg /* OUT: Leaf (sorted-run) page reference */
-){
- int i = 0;
- int rc;
- int iPg;
- Page *pPg = 0;
- LsmBlob blob = {0, 0, 0};
-
- iPg = (int)pSeg->iRoot;
- do {
- LsmPgno *piFirst = 0;
- if( aPg ){
- aPg[i++] = iPg;
- piFirst = &aPg[i];
- }
-
- rc = lsmFsDbPageGet(pCsr->pDb->pFS, pSeg, iPg, &pPg);
- assert( rc==LSM_OK || pPg==0 );
- if( rc==LSM_OK ){
- u8 *aData; /* Buffer containing page data */
- int nData; /* Size of aData[] in bytes */
- int iMin;
- int iMax;
- int nRec;
- int flags;
-
- aData = fsPageData(pPg, &nData);
- flags = pageGetFlags(aData, nData);
- if( (flags & SEGMENT_BTREE_FLAG)==0 ) break;
-
- iPg = (int)pageGetPtr(aData, nData);
- nRec = pageGetNRec(aData, nData);
-
- iMin = 0;
- iMax = nRec-1;
- while( iMax>=iMin ){
- int iTry = (iMin+iMax)/2;
- void *pKeyT; int nKeyT; /* Key for cell iTry */
- int iTopicT; /* Topic for key pKeyT/nKeyT */
- LsmPgno iPtr; /* Pointer associated with cell iTry */
- int res; /* (pKey - pKeyT) */
-
- rc = pageGetBtreeKey(
- pSeg, pPg, iTry, &iPtr, &iTopicT, &pKeyT, &nKeyT, &blob
- );
- if( rc!=LSM_OK ) break;
- if( piFirst && pKeyT==blob.pData ){
- *piFirst = pageGetBtreeRef(pPg, iTry);
- piFirst = 0;
- i++;
- }
-
- res = sortedKeyCompare(
- pCsr->pDb->xCmp, iTopic, pKey, nKey, iTopicT, pKeyT, nKeyT
- );
- if( res<0 ){
- iPg = (int)iPtr;
- iMax = iTry-1;
- }else{
- iMin = iTry+1;
- }
- }
- lsmFsPageRelease(pPg);
- pPg = 0;
- }
- }while( rc==LSM_OK );
-
- sortedBlobFree(&blob);
- assert( (rc==LSM_OK)==(pPg!=0) );
- if( ppPg ){
- *ppPg = pPg;
- }else{
- lsmFsPageRelease(pPg);
- }
- return rc;
-}
-
-static int seekInSegment(
- MultiCursor *pCsr,
- SegmentPtr *pPtr,
- int iTopic,
- void *pKey, int nKey,
- int iPg, /* Page to search */
- int eSeek, /* Search bias - see above */
- int *piPtr, /* OUT: FC pointer */
- int *pbStop /* OUT: Stop search flag */
-){
- int iPtr = iPg;
- int rc = LSM_OK;
-
- if( pPtr->pSeg->iRoot ){
- Page *pPg;
- assert( pPtr->pSeg->iRoot!=0 );
- rc = seekInBtree(pCsr, pPtr->pSeg, iTopic, pKey, nKey, 0, &pPg);
- if( rc==LSM_OK ) segmentPtrSetPage(pPtr, pPg);
- }else{
- if( iPtr==0 ){
- iPtr = (int)pPtr->pSeg->iFirst;
- }
- if( rc==LSM_OK ){
- rc = segmentPtrLoadPage(pCsr->pDb->pFS, pPtr, iPtr);
- }
- }
-
- if( rc==LSM_OK ){
- rc = segmentPtrSeek(pCsr, pPtr, iTopic, pKey, nKey, eSeek, piPtr, pbStop);
- }
- return rc;
-}
-
-/*
-** Seek each segment pointer in the array of (pLvl->nRight+1) at aPtr[].
-**
-** pbStop:
-** This parameter is only significant if parameter eSeek is set to
-** LSM_SEEK_EQ. In this case, it is set to true before returning if
-** the seek operation is finished. This can happen in two ways:
-**
-** a) A key matching (pKey/nKey) is found, or
-** b) A point-delete or range-delete deleting the key is found.
-**
-** In case (a), the multi-cursor CURSOR_SEEK_EQ flag is set and the pCsr->key
-** and pCsr->val blobs populated before returning.
-*/
-static int seekInLevel(
- MultiCursor *pCsr, /* Sorted cursor object to seek */
- SegmentPtr *aPtr, /* Pointer to array of (nRhs+1) SPs */
- int eSeek, /* Search bias - see above */
- int iTopic, /* Key topic to search for */
- void *pKey, int nKey, /* Key to search for */
- LsmPgno *piPgno, /* IN/OUT: fraction cascade pointer (or 0) */
- int *pbStop /* OUT: See above */
-){
- Level *pLvl = aPtr[0].pLevel; /* Level to seek within */
- int rc = LSM_OK; /* Return code */
- int iOut = 0; /* Pointer to return to caller */
- int res = -1; /* Result of xCmp(pKey, split) */
- int nRhs = pLvl->nRight; /* Number of right-hand-side segments */
- int bStop = 0;
-
- /* If this is a composite level (one currently undergoing an incremental
- ** merge), figure out if the search key is larger or smaller than the
- ** levels split-key. */
- if( nRhs ){
- res = sortedKeyCompare(pCsr->pDb->xCmp, iTopic, pKey, nKey,
- pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
- );
- }
-
- /* If (res<0), then key pKey/nKey is smaller than the split-key (or this
- ** is not a composite level and there is no split-key). Search the
- ** left-hand-side of the level in this case. */
- if( res<0 ){
- int iPtr = 0;
- if( nRhs==0 ) iPtr = (int)*piPgno;
-
- rc = seekInSegment(
- pCsr, &aPtr[0], iTopic, pKey, nKey, iPtr, eSeek, &iOut, &bStop
- );
- if( rc==LSM_OK && nRhs>0 && eSeek==LSM_SEEK_GE && aPtr[0].pPg==0 ){
- res = 0;
- }
- }
-
- if( res>=0 ){
- int bHit = 0; /* True if at least one rhs is not EOF */
- int iPtr = (int)*piPgno;
- int i;
- for(i=1; rc==LSM_OK && i<=nRhs && bStop==0; i++){
- SegmentPtr *pPtr = &aPtr[i];
- iOut = 0;
- rc = seekInSegment(
- pCsr, pPtr, iTopic, pKey, nKey, iPtr, eSeek, &iOut, &bStop
- );
- iPtr = iOut;
-
- /* If the segment-pointer has settled on a key that is smaller than
- ** the splitkey, invalidate the segment-pointer. */
- if( pPtr->pPg ){
- res = sortedKeyCompare(pCsr->pDb->xCmp,
- rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey,
- pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
- );
- if( res<0 ){
- if( pPtr->eType & LSM_START_DELETE ){
- pPtr->eType &= ~LSM_INSERT;
- pPtr->pKey = pLvl->pSplitKey;
- pPtr->nKey = pLvl->nSplitKey;
- pPtr->pVal = 0;
- pPtr->nVal = 0;
- }else{
- segmentPtrReset(pPtr, LSM_SEGMENTPTR_FREE_THRESHOLD);
- }
- }
- }
-
- if( aPtr[i].pKey ) bHit = 1;
- }
-
- if( rc==LSM_OK && eSeek==LSM_SEEK_LE && bHit==0 ){
- rc = segmentPtrEnd(pCsr, &aPtr[0], 1);
- }
- }
-
- assert( eSeek==LSM_SEEK_EQ || bStop==0 );
- *piPgno = iOut;
- *pbStop = bStop;
- return rc;
-}
-
-static void multiCursorGetKey(
- MultiCursor *pCsr,
- int iKey,
- int *peType, /* OUT: Key type (SORTED_WRITE etc.) */
- void **ppKey, /* OUT: Pointer to buffer containing key */
- int *pnKey /* OUT: Size of *ppKey in bytes */
-){
- int nKey = 0;
- void *pKey = 0;
- int eType = 0;
-
- switch( iKey ){
- case CURSOR_DATA_TREE0:
- case CURSOR_DATA_TREE1: {
- TreeCursor *pTreeCsr = pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0];
- if( lsmTreeCursorValid(pTreeCsr) ){
- lsmTreeCursorKey(pTreeCsr, &eType, &pKey, &nKey);
- }
- break;
- }
-
- case CURSOR_DATA_SYSTEM: {
- Snapshot *pWorker = pCsr->pDb->pWorker;
- if( pWorker && (pCsr->flags & CURSOR_FLUSH_FREELIST) ){
- int nEntry = pWorker->freelist.nEntry;
- if( pCsr->iFree < (nEntry*2) ){
- FreelistEntry *aEntry = pWorker->freelist.aEntry;
- int i = nEntry - 1 - (pCsr->iFree / 2);
- u32 iKey2 = 0;
-
- if( (pCsr->iFree % 2) ){
- eType = LSM_END_DELETE|LSM_SYSTEMKEY;
- iKey2 = aEntry[i].iBlk-1;
- }else if( aEntry[i].iId>=0 ){
- eType = LSM_INSERT|LSM_SYSTEMKEY;
- iKey2 = aEntry[i].iBlk;
-
- /* If the in-memory entry immediately before this one was a
- ** DELETE, and the block number is one greater than the current
- ** block number, mark this entry as an "end-delete-range". */
- if( i<(nEntry-1) && aEntry[i+1].iBlk==iKey2+1 && aEntry[i+1].iId<0 ){
- eType |= LSM_END_DELETE;
- }
-
- }else{
- eType = LSM_START_DELETE|LSM_SYSTEMKEY;
- iKey2 = aEntry[i].iBlk + 1;
- }
-
- /* If the in-memory entry immediately after this one is a
- ** DELETE, and the block number is one less than the current
- ** key, mark this entry as an "start-delete-range". */
- if( i>0 && aEntry[i-1].iBlk==iKey2-1 && aEntry[i-1].iId<0 ){
- eType |= LSM_START_DELETE;
- }
-
- pKey = pCsr->pSystemVal;
- nKey = 4;
- lsmPutU32(pKey, ~iKey2);
- }
- }
- break;
- }
-
- default: {
- int iPtr = iKey - CURSOR_DATA_SEGMENT;
- assert( iPtr>=0 );
- if( iPtr==pCsr->nPtr ){
- if( pCsr->pBtCsr ){
- pKey = pCsr->pBtCsr->pKey;
- nKey = pCsr->pBtCsr->nKey;
- eType = pCsr->pBtCsr->eType;
- }
- }else if( iPtr<pCsr->nPtr ){
- SegmentPtr *pPtr = &pCsr->aPtr[iPtr];
- if( pPtr->pPg ){
- pKey = pPtr->pKey;
- nKey = pPtr->nKey;
- eType = pPtr->eType;
- }
- }
- break;
- }
- }
-
- if( peType ) *peType = eType;
- if( pnKey ) *pnKey = nKey;
- if( ppKey ) *ppKey = pKey;
-}
-
-static int sortedDbKeyCompare(
- MultiCursor *pCsr,
- int iLhsFlags, void *pLhsKey, int nLhsKey,
- int iRhsFlags, void *pRhsKey, int nRhsKey
-){
- int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
- int res;
-
- /* Compare the keys, including the system flag. */
- res = sortedKeyCompare(xCmp,
- rtTopic(iLhsFlags), pLhsKey, nLhsKey,
- rtTopic(iRhsFlags), pRhsKey, nRhsKey
- );
-
- /* If a key has the LSM_START_DELETE flag set, but not the LSM_INSERT or
- ** LSM_POINT_DELETE flags, it is considered a delta larger. This prevents
- ** the beginning of an open-ended set from masking a database entry or
- ** delete at a lower level. */
- if( res==0 && (pCsr->flags & CURSOR_IGNORE_DELETE) ){
- const int m = LSM_POINT_DELETE|LSM_INSERT|LSM_END_DELETE |LSM_START_DELETE;
- int iDel1 = 0;
- int iDel2 = 0;
-
- if( LSM_START_DELETE==(iLhsFlags & m) ) iDel1 = +1;
- if( LSM_END_DELETE ==(iLhsFlags & m) ) iDel1 = -1;
- if( LSM_START_DELETE==(iRhsFlags & m) ) iDel2 = +1;
- if( LSM_END_DELETE ==(iRhsFlags & m) ) iDel2 = -1;
-
- res = (iDel1 - iDel2);
- }
-
- return res;
-}
-
-static void multiCursorDoCompare(MultiCursor *pCsr, int iOut, int bReverse){
- int i1;
- int i2;
- int iRes;
- void *pKey1; int nKey1; int eType1;
- void *pKey2; int nKey2; int eType2;
- const int mul = (bReverse ? -1 : 1);
-
- assert( pCsr->aTree && iOut<pCsr->nTree );
- if( iOut>=(pCsr->nTree/2) ){
- i1 = (iOut - pCsr->nTree/2) * 2;
- i2 = i1 + 1;
- }else{
- i1 = pCsr->aTree[iOut*2];
- i2 = pCsr->aTree[iOut*2+1];
- }
-
- multiCursorGetKey(pCsr, i1, &eType1, &pKey1, &nKey1);
- multiCursorGetKey(pCsr, i2, &eType2, &pKey2, &nKey2);
-
- if( pKey1==0 ){
- iRes = i2;
- }else if( pKey2==0 ){
- iRes = i1;
- }else{
- int res;
-
- /* Compare the keys */
- res = sortedDbKeyCompare(pCsr,
- eType1, pKey1, nKey1, eType2, pKey2, nKey2
- );
-
- res = res * mul;
- if( res==0 ){
- /* The two keys are identical. Normally, this means that the key from
- ** the newer run clobbers the old. However, if the newer key is a
- ** separator key, or a range-delete-boundary only, do not allow it
- ** to clobber an older entry. */
- int nc1 = (eType1 & (LSM_INSERT|LSM_POINT_DELETE))==0;
- int nc2 = (eType2 & (LSM_INSERT|LSM_POINT_DELETE))==0;
- iRes = (nc1 > nc2) ? i2 : i1;
- }else if( res<0 ){
- iRes = i1;
- }else{
- iRes = i2;
- }
- }
-
- pCsr->aTree[iOut] = iRes;
-}
-
-/*
-** This function advances segment pointer iPtr belonging to multi-cursor
-** pCsr forward (bReverse==0) or backward (bReverse!=0).
-**
-** If the segment pointer points to a segment that is part of a composite
-** level, then the following special case is handled.
-**
-** * If iPtr is the lhs of a composite level, and the cursor is being
-** advanced forwards, and segment iPtr is at EOF, move all pointers
-** that correspond to rhs segments of the same level to the first
-** key in their respective data.
-*/
-static int segmentCursorAdvance(
- MultiCursor *pCsr,
- int iPtr,
- int bReverse
-){
- int rc;
- SegmentPtr *pPtr = &pCsr->aPtr[iPtr];
- Level *pLvl = pPtr->pLevel;
- int bComposite; /* True if pPtr is part of composite level */
-
- /* Advance the segment-pointer object. */
- rc = segmentPtrAdvance(pCsr, pPtr, bReverse);
- if( rc!=LSM_OK ) return rc;
-
- bComposite = (pLvl->nRight>0 && pCsr->nPtr>pLvl->nRight);
- if( bComposite && pPtr->pPg==0 ){
- int bFix = 0;
- if( (bReverse==0)==(pPtr->pSeg==&pLvl->lhs) ){
- int i;
- if( bReverse ){
- SegmentPtr *pLhs = &pCsr->aPtr[iPtr - 1 - (pPtr->pSeg - pLvl->aRhs)];
- for(i=0; i<pLvl->nRight; i++){
- if( pLhs[i+1].pPg ) break;
- }
- if( i==pLvl->nRight ){
- bFix = 1;
- rc = segmentPtrEnd(pCsr, pLhs, 1);
- }
- }else{
- bFix = 1;
- for(i=0; rc==LSM_OK && i<pLvl->nRight; i++){
- rc = sortedRhsFirst(pCsr, pLvl, &pCsr->aPtr[iPtr+1+i]);
- }
- }
- }
-
- if( bFix ){
- int i;
- for(i=pCsr->nTree-1; i>0; i--){
- multiCursorDoCompare(pCsr, i, bReverse);
- }
- }
- }
-
-#if 0
- if( bComposite && pPtr->pSeg==&pLvl->lhs /* lhs of composite level */
- && bReverse==0 /* csr advanced forwards */
- && pPtr->pPg==0 /* segment at EOF */
- ){
- int i;
- for(i=0; rc==LSM_OK && i<pLvl->nRight; i++){
- rc = sortedRhsFirst(pCsr, pLvl, &pCsr->aPtr[iPtr+1+i]);
- }
- for(i=pCsr->nTree-1; i>0; i--){
- multiCursorDoCompare(pCsr, i, 0);
- }
- }
-#endif
-
- return rc;
-}
-
-static void mcursorFreeComponents(MultiCursor *pCsr){
- int i;
- lsm_env *pEnv = pCsr->pDb->pEnv;
-
- /* Close the tree cursor, if any. */
- lsmTreeCursorDestroy(pCsr->apTreeCsr[0]);
- lsmTreeCursorDestroy(pCsr->apTreeCsr[1]);
-
- /* Reset the segment pointers */
- for(i=0; i<pCsr->nPtr; i++){
- segmentPtrReset(&pCsr->aPtr[i], 0);
- }
-
- /* And the b-tree cursor, if any */
- btreeCursorFree(pCsr->pBtCsr);
-
- /* Free allocations */
- lsmFree(pEnv, pCsr->aPtr);
- lsmFree(pEnv, pCsr->aTree);
- lsmFree(pEnv, pCsr->pSystemVal);
-
- /* Zero fields */
- pCsr->nPtr = 0;
- pCsr->aPtr = 0;
- pCsr->nTree = 0;
- pCsr->aTree = 0;
- pCsr->pSystemVal = 0;
- pCsr->apTreeCsr[0] = 0;
- pCsr->apTreeCsr[1] = 0;
- pCsr->pBtCsr = 0;
-}
-
-void lsmMCursorFreeCache(lsm_db *pDb){
- MultiCursor *p;
- MultiCursor *pNext;
- for(p=pDb->pCsrCache; p; p=pNext){
- pNext = p->pNext;
- lsmMCursorClose(p, 0);
- }
- pDb->pCsrCache = 0;
-}
-
-/*
-** Close the cursor passed as the first argument.
-**
-** If the bCache parameter is true, then shift the cursor to the pCsrCache
-** list for possible reuse instead of actually deleting it.
-*/
-void lsmMCursorClose(MultiCursor *pCsr, int bCache){
- if( pCsr ){
- lsm_db *pDb = pCsr->pDb;
- MultiCursor **pp; /* Iterator variable */
-
- /* The cursor may or may not be currently part of the linked list
- ** starting at lsm_db.pCsr. If it is, extract it. */
- for(pp=&pDb->pCsr; *pp; pp=&((*pp)->pNext)){
- if( *pp==pCsr ){
- *pp = pCsr->pNext;
- break;
- }
- }
-
- if( bCache ){
- int i; /* Used to iterate through segment-pointers */
-
- /* Release any page references held by this cursor. */
- assert( !pCsr->pBtCsr );
- for(i=0; i<pCsr->nPtr; i++){
- SegmentPtr *pPtr = &pCsr->aPtr[i];
- lsmFsPageRelease(pPtr->pPg);
- pPtr->pPg = 0;
- }
-
- /* Reset the tree cursors */
- lsmTreeCursorReset(pCsr->apTreeCsr[0]);
- lsmTreeCursorReset(pCsr->apTreeCsr[1]);
-
- /* Add the cursor to the pCsrCache list */
- pCsr->pNext = pDb->pCsrCache;
- pDb->pCsrCache = pCsr;
- }else{
- /* Free the allocation used to cache the current key, if any. */
- sortedBlobFree(&pCsr->key);
- sortedBlobFree(&pCsr->val);
-
- /* Free the component cursors */
- mcursorFreeComponents(pCsr);
-
- /* Free the cursor structure itself */
- lsmFree(pDb->pEnv, pCsr);
- }
- }
-}
-
-#define TREE_NONE 0
-#define TREE_OLD 1
-#define TREE_BOTH 2
-
-/*
-** Parameter eTree is one of TREE_OLD or TREE_BOTH.
-*/
-static int multiCursorAddTree(MultiCursor *pCsr, Snapshot *pSnap, int eTree){
- int rc = LSM_OK;
- lsm_db *db = pCsr->pDb;
-
- /* Add a tree cursor on the 'old' tree, if it exists. */
- if( eTree!=TREE_NONE
- && lsmTreeHasOld(db)
- && db->treehdr.iOldLog!=pSnap->iLogOff
- ){
- rc = lsmTreeCursorNew(db, 1, &pCsr->apTreeCsr[1]);
- }
-
- /* Add a tree cursor on the 'current' tree, if required. */
- if( rc==LSM_OK && eTree==TREE_BOTH ){
- rc = lsmTreeCursorNew(db, 0, &pCsr->apTreeCsr[0]);
- }
-
- return rc;
-}
-
-static int multiCursorAddRhs(MultiCursor *pCsr, Level *pLvl){
- int i;
- int nRhs = pLvl->nRight;
-
- assert( pLvl->nRight>0 );
- assert( pCsr->aPtr==0 );
- pCsr->aPtr = lsmMallocZero(pCsr->pDb->pEnv, sizeof(SegmentPtr) * nRhs);
- if( !pCsr->aPtr ) return LSM_NOMEM_BKPT;
- pCsr->nPtr = nRhs;
-
- for(i=0; i<nRhs; i++){
- pCsr->aPtr[i].pSeg = &pLvl->aRhs[i];
- pCsr->aPtr[i].pLevel = pLvl;
- }
-
- return LSM_OK;
-}
-
-static void multiCursorAddOne(MultiCursor *pCsr, Level *pLvl, int *pRc){
- if( *pRc==LSM_OK ){
- int iPtr = pCsr->nPtr;
- int i;
- pCsr->aPtr[iPtr].pLevel = pLvl;
- pCsr->aPtr[iPtr].pSeg = &pLvl->lhs;
- iPtr++;
- for(i=0; i<pLvl->nRight; i++){
- pCsr->aPtr[iPtr].pLevel = pLvl;
- pCsr->aPtr[iPtr].pSeg = &pLvl->aRhs[i];
- iPtr++;
- }
-
- if( pLvl->nRight && pLvl->pSplitKey==0 ){
- sortedSplitkey(pCsr->pDb, pLvl, pRc);
- }
- pCsr->nPtr = iPtr;
- }
-}
-
-static int multiCursorAddAll(MultiCursor *pCsr, Snapshot *pSnap){
- Level *pLvl;
- int nPtr = 0;
- int rc = LSM_OK;
-
- for(pLvl=pSnap->pLevel; pLvl; pLvl=pLvl->pNext){
- /* If the LEVEL_INCOMPLETE flag is set, then this function is being
- ** called (indirectly) from within a sortedNewToplevel() call to
- ** construct pLvl. In this case ignore pLvl - this cursor is going to
- ** be used to retrieve a freelist entry from the LSM, and the partially
- ** complete level may confuse it. */
- if( pLvl->flags & LEVEL_INCOMPLETE ) continue;
- nPtr += (1 + pLvl->nRight);
- }
-
- assert( pCsr->aPtr==0 );
- pCsr->aPtr = lsmMallocZeroRc(pCsr->pDb->pEnv, sizeof(SegmentPtr) * nPtr, &rc);
-
- for(pLvl=pSnap->pLevel; pLvl; pLvl=pLvl->pNext){
- if( (pLvl->flags & LEVEL_INCOMPLETE)==0 ){
- multiCursorAddOne(pCsr, pLvl, &rc);
- }
- }
-
- return rc;
-}
-
-static int multiCursorInit(MultiCursor *pCsr, Snapshot *pSnap){
- int rc;
- rc = multiCursorAddAll(pCsr, pSnap);
- if( rc==LSM_OK ){
- rc = multiCursorAddTree(pCsr, pSnap, TREE_BOTH);
- }
- pCsr->flags |= (CURSOR_IGNORE_SYSTEM | CURSOR_IGNORE_DELETE);
- return rc;
-}
-
-static MultiCursor *multiCursorNew(lsm_db *db, int *pRc){
- MultiCursor *pCsr;
- pCsr = (MultiCursor *)lsmMallocZeroRc(db->pEnv, sizeof(MultiCursor), pRc);
- if( pCsr ){
- pCsr->pNext = db->pCsr;
- db->pCsr = pCsr;
- pCsr->pDb = db;
- }
- return pCsr;
-}
-
-
-void lsmSortedRemap(lsm_db *pDb){
- MultiCursor *pCsr;
- for(pCsr=pDb->pCsr; pCsr; pCsr=pCsr->pNext){
- int iPtr;
- if( pCsr->pBtCsr ){
- btreeCursorLoadKey(pCsr->pBtCsr);
- }
- for(iPtr=0; iPtr<pCsr->nPtr; iPtr++){
- segmentPtrLoadCell(&pCsr->aPtr[iPtr], pCsr->aPtr[iPtr].iCell);
- }
- }
-}
-
-static void multiCursorReadSeparators(MultiCursor *pCsr){
- if( pCsr->nPtr>0 ){
- pCsr->flags |= CURSOR_READ_SEPARATORS;
- }
-}
-
-/*
-** Have this cursor skip over SORTED_DELETE entries.
-*/
-static void multiCursorIgnoreDelete(MultiCursor *pCsr){
- if( pCsr ) pCsr->flags |= CURSOR_IGNORE_DELETE;
-}
-
-/*
-** If the free-block list is not empty, then have this cursor visit a key
-** with (a) the system bit set, and (b) the key "FREELIST" and (c) a value
-** blob containing the serialized free-block list.
-*/
-static int multiCursorVisitFreelist(MultiCursor *pCsr){
- int rc = LSM_OK;
- pCsr->flags |= CURSOR_FLUSH_FREELIST;
- pCsr->pSystemVal = lsmMallocRc(pCsr->pDb->pEnv, 4 + 8, &rc);
- return rc;
-}
-
-/*
-** Allocate and return a new database cursor.
-**
-** This method should only be called to allocate user cursors. As it may
-** recycle a cursor from lsm_db.pCsrCache.
-*/
-int lsmMCursorNew(
- lsm_db *pDb, /* Database handle */
- MultiCursor **ppCsr /* OUT: Allocated cursor */
-){
- MultiCursor *pCsr = 0;
- int rc = LSM_OK;
-
- if( pDb->pCsrCache ){
- int bOld; /* True if there is an old in-memory tree */
-
- /* Remove a cursor from the pCsrCache list and add it to the open list. */
- pCsr = pDb->pCsrCache;
- pDb->pCsrCache = pCsr->pNext;
- pCsr->pNext = pDb->pCsr;
- pDb->pCsr = pCsr;
-
- /* The cursor can almost be used as is, except that the old in-memory
- ** tree cursor may be present and not required, or required and not
- ** present. Fix this if required. */
- bOld = (lsmTreeHasOld(pDb) && pDb->treehdr.iOldLog!=pDb->pClient->iLogOff);
- if( !bOld && pCsr->apTreeCsr[1] ){
- lsmTreeCursorDestroy(pCsr->apTreeCsr[1]);
- pCsr->apTreeCsr[1] = 0;
- }else if( bOld && !pCsr->apTreeCsr[1] ){
- rc = lsmTreeCursorNew(pDb, 1, &pCsr->apTreeCsr[1]);
- }
-
- pCsr->flags = (CURSOR_IGNORE_SYSTEM | CURSOR_IGNORE_DELETE);
-
- }else{
- pCsr = multiCursorNew(pDb, &rc);
- if( rc==LSM_OK ) rc = multiCursorInit(pCsr, pDb->pClient);
- }
-
- if( rc!=LSM_OK ){
- lsmMCursorClose(pCsr, 0);
- pCsr = 0;
- }
- assert( (rc==LSM_OK)==(pCsr!=0) );
- *ppCsr = pCsr;
- return rc;
-}
-
-static int multiCursorGetVal(
- MultiCursor *pCsr,
- int iVal,
- void **ppVal,
- int *pnVal
-){
- int rc = LSM_OK;
-
- *ppVal = 0;
- *pnVal = 0;
-
- switch( iVal ){
- case CURSOR_DATA_TREE0:
- case CURSOR_DATA_TREE1: {
- TreeCursor *pTreeCsr = pCsr->apTreeCsr[iVal-CURSOR_DATA_TREE0];
- if( lsmTreeCursorValid(pTreeCsr) ){
- lsmTreeCursorValue(pTreeCsr, ppVal, pnVal);
- }else{
- *ppVal = 0;
- *pnVal = 0;
- }
- break;
- }
-
- case CURSOR_DATA_SYSTEM: {
- Snapshot *pWorker = pCsr->pDb->pWorker;
- if( pWorker
- && (pCsr->iFree % 2)==0
- && pCsr->iFree < (pWorker->freelist.nEntry*2)
- ){
- int iEntry = pWorker->freelist.nEntry - 1 - (pCsr->iFree / 2);
- u8 *aVal = &((u8 *)(pCsr->pSystemVal))[4];
- lsmPutU64(aVal, pWorker->freelist.aEntry[iEntry].iId);
- *ppVal = aVal;
- *pnVal = 8;
- }
- break;
- }
-
- default: {
- int iPtr = iVal-CURSOR_DATA_SEGMENT;
- if( iPtr<pCsr->nPtr ){
- SegmentPtr *pPtr = &pCsr->aPtr[iPtr];
- if( pPtr->pPg ){
- *ppVal = pPtr->pVal;
- *pnVal = pPtr->nVal;
- }
- }
- }
- }
-
- assert( rc==LSM_OK || (*ppVal==0 && *pnVal==0) );
- return rc;
-}
-
-static int multiCursorAdvance(MultiCursor *pCsr, int bReverse);
-
-/*
-** This function is called by worker connections to walk the part of the
-** free-list stored within the LSM data structure.
-*/
-int lsmSortedWalkFreelist(
- lsm_db *pDb, /* Database handle */
- int bReverse, /* True to iterate from largest to smallest */
- int (*x)(void *, int, i64), /* Callback function */
- void *pCtx /* First argument to pass to callback */
-){
- MultiCursor *pCsr; /* Cursor used to read db */
- int rc = LSM_OK; /* Return Code */
- Snapshot *pSnap = 0;
-
- assert( pDb->pWorker );
- if( pDb->bIncrMerge ){
- rc = lsmCheckpointDeserialize(pDb, 0, pDb->pShmhdr->aSnap1, &pSnap);
- if( rc!=LSM_OK ) return rc;
- }else{
- pSnap = pDb->pWorker;
- }
-
- pCsr = multiCursorNew(pDb, &rc);
- if( pCsr ){
- rc = multiCursorAddAll(pCsr, pSnap);
- pCsr->flags |= CURSOR_IGNORE_DELETE;
- }
-
- if( rc==LSM_OK ){
- if( bReverse==0 ){
- rc = lsmMCursorLast(pCsr);
- }else{
- rc = lsmMCursorSeek(pCsr, 1, "", 0, LSM_SEEK_GE);
- }
-
- while( rc==LSM_OK && lsmMCursorValid(pCsr) && rtIsSystem(pCsr->eType) ){
- void *pKey; int nKey;
- void *pVal = 0; int nVal = 0;
-
- rc = lsmMCursorKey(pCsr, &pKey, &nKey);
- if( rc==LSM_OK ) rc = lsmMCursorValue(pCsr, &pVal, &nVal);
- if( rc==LSM_OK && (nKey!=4 || nVal!=8) ) rc = LSM_CORRUPT_BKPT;
-
- if( rc==LSM_OK ){
- int iBlk;
- i64 iSnap;
- iBlk = (int)(~(lsmGetU32((u8 *)pKey)));
- iSnap = (i64)lsmGetU64((u8 *)pVal);
- if( x(pCtx, iBlk, iSnap) ) break;
- rc = multiCursorAdvance(pCsr, !bReverse);
- }
- }
- }
-
- lsmMCursorClose(pCsr, 0);
- if( pSnap!=pDb->pWorker ){
- lsmFreeSnapshot(pDb->pEnv, pSnap);
- }
-
- return rc;
-}
-
-int lsmSortedLoadFreelist(
- lsm_db *pDb, /* Database handle (must be worker) */
- void **ppVal, /* OUT: Blob containing LSM free-list */
- int *pnVal /* OUT: Size of *ppVal blob in bytes */
-){
- MultiCursor *pCsr; /* Cursor used to retreive free-list */
- int rc = LSM_OK; /* Return Code */
-
- assert( pDb->pWorker );
- assert( *ppVal==0 && *pnVal==0 );
-
- pCsr = multiCursorNew(pDb, &rc);
- if( pCsr ){
- rc = multiCursorAddAll(pCsr, pDb->pWorker);
- pCsr->flags |= CURSOR_IGNORE_DELETE;
- }
-
- if( rc==LSM_OK ){
- rc = lsmMCursorLast(pCsr);
- if( rc==LSM_OK
- && rtIsWrite(pCsr->eType) && rtIsSystem(pCsr->eType)
- && pCsr->key.nData==8
- && 0==memcmp(pCsr->key.pData, "FREELIST", 8)
- ){
- void *pVal; int nVal; /* Value read from database */
- rc = lsmMCursorValue(pCsr, &pVal, &nVal);
- if( rc==LSM_OK ){
- *ppVal = lsmMallocRc(pDb->pEnv, nVal, &rc);
- if( *ppVal ){
- memcpy(*ppVal, pVal, nVal);
- *pnVal = nVal;
- }
- }
- }
-
- lsmMCursorClose(pCsr, 0);
- }
-
- return rc;
-}
-
-static int multiCursorAllocTree(MultiCursor *pCsr){
- int rc = LSM_OK;
- if( pCsr->aTree==0 ){
- int nByte; /* Bytes of space to allocate */
- int nMin; /* Total number of cursors being merged */
-
- nMin = CURSOR_DATA_SEGMENT + pCsr->nPtr + (pCsr->pBtCsr!=0);
- pCsr->nTree = 2;
- while( pCsr->nTree<nMin ){
- pCsr->nTree = pCsr->nTree*2;
- }
-
- nByte = sizeof(int)*pCsr->nTree*2;
- pCsr->aTree = (int *)lsmMallocZeroRc(pCsr->pDb->pEnv, nByte, &rc);
- }
- return rc;
-}
-
-static void multiCursorCacheKey(MultiCursor *pCsr, int *pRc){
- if( *pRc==LSM_OK ){
- void *pKey;
- int nKey;
- multiCursorGetKey(pCsr, pCsr->aTree[1], &pCsr->eType, &pKey, &nKey);
- *pRc = sortedBlobSet(pCsr->pDb->pEnv, &pCsr->key, pKey, nKey);
- }
-}
-
-#ifdef LSM_DEBUG_EXPENSIVE
-static void assertCursorTree(MultiCursor *pCsr){
- int bRev = !!(pCsr->flags & CURSOR_PREV_OK);
- int *aSave = pCsr->aTree;
- int nSave = pCsr->nTree;
- int rc;
-
- pCsr->aTree = 0;
- pCsr->nTree = 0;
- rc = multiCursorAllocTree(pCsr);
- if( rc==LSM_OK ){
- int i;
- for(i=pCsr->nTree-1; i>0; i--){
- multiCursorDoCompare(pCsr, i, bRev);
- }
-
- assert( nSave==pCsr->nTree
- && 0==memcmp(aSave, pCsr->aTree, sizeof(int)*nSave)
- );
-
- lsmFree(pCsr->pDb->pEnv, pCsr->aTree);
- }
-
- pCsr->aTree = aSave;
- pCsr->nTree = nSave;
-}
-#else
-# define assertCursorTree(x)
-#endif
-
-static int mcursorLocationOk(MultiCursor *pCsr, int bDeleteOk){
- int eType = pCsr->eType;
- int iKey;
- int i;
- int rdmask;
-
- assert( pCsr->flags & (CURSOR_NEXT_OK|CURSOR_PREV_OK) );
- assertCursorTree(pCsr);
-
- rdmask = (pCsr->flags & CURSOR_NEXT_OK) ? LSM_END_DELETE : LSM_START_DELETE;
-
- /* If the cursor does not currently point to an actual database key (i.e.
- ** it points to a delete key, or the start or end of a range-delete), and
- ** the CURSOR_IGNORE_DELETE flag is set, skip past this entry. */
- if( (pCsr->flags & CURSOR_IGNORE_DELETE) && bDeleteOk==0 ){
- if( (eType & LSM_INSERT)==0 ) return 0;
- }
-
- /* If the cursor points to a system key (free-list entry), and the
- ** CURSOR_IGNORE_SYSTEM flag is set, skip thie entry. */
- if( (pCsr->flags & CURSOR_IGNORE_SYSTEM) && rtTopic(eType)!=0 ){
- return 0;
- }
-
-#ifndef NDEBUG
- /* This block fires assert() statements to check one of the assumptions
- ** in the comment below - that if the lhs sub-cursor of a level undergoing
- ** a merge is valid, then all the rhs sub-cursors must be at EOF.
- **
- ** Also assert that all rhs sub-cursors are either at EOF or point to
- ** a key that is not less than the level split-key. */
- for(i=0; i<pCsr->nPtr; i++){
- SegmentPtr *pPtr = &pCsr->aPtr[i];
- Level *pLvl = pPtr->pLevel;
- if( pLvl->nRight && pPtr->pPg ){
- if( pPtr->pSeg==&pLvl->lhs ){
- int j;
- for(j=0; j<pLvl->nRight; j++) assert( pPtr[j+1].pPg==0 );
- }else{
- int res = sortedKeyCompare(pCsr->pDb->xCmp,
- rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey,
- pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
- );
- assert( res>=0 );
- }
- }
- }
-#endif
-
- /* Now check if this key has already been deleted by a range-delete. If
- ** so, skip past it.
- **
- ** Assume, for the moment, that the tree contains no levels currently
- ** undergoing incremental merge, and that this cursor is iterating forwards
- ** through the database keys. The cursor currently points to a key in
- ** level L. This key has already been deleted if any of the sub-cursors
- ** that point to levels newer than L (or to the in-memory tree) point to
- ** a key greater than the current key with the LSM_END_DELETE flag set.
- **
- ** Or, if the cursor is iterating backwards through data keys, if any
- ** such sub-cursor points to a key smaller than the current key with the
- ** LSM_START_DELETE flag set.
- **
- ** Why it works with levels undergoing a merge too:
- **
- ** When a cursor iterates forwards, the sub-cursors for the rhs of a
- ** level are only activated once the lhs reaches EOF. So when iterating
- ** forwards, the keys visited are the same as if the level was completely
- ** merged.
- **
- ** If the cursor is iterating backwards, then the lhs sub-cursor is not
- ** initialized until the last of the rhs sub-cursors has reached EOF.
- ** Additionally, if the START_DELETE flag is set on the last entry (in
- ** reverse order - so the entry with the smallest key) of a rhs sub-cursor,
- ** then a pseudo-key equal to the levels split-key with the END_DELETE
- ** flag set is visited by the sub-cursor.
- */
- iKey = pCsr->aTree[1];
- for(i=0; i<iKey; i++){
- int csrflags;
- multiCursorGetKey(pCsr, i, &csrflags, 0, 0);
- if( (rdmask & csrflags) ){
- const int SD_ED = (LSM_START_DELETE|LSM_END_DELETE);
- if( (csrflags & SD_ED)==SD_ED
- || (pCsr->flags & CURSOR_IGNORE_DELETE)==0
- ){
- void *pKey; int nKey;
- multiCursorGetKey(pCsr, i, 0, &pKey, &nKey);
- if( 0==sortedKeyCompare(pCsr->pDb->xCmp,
- rtTopic(eType), pCsr->key.pData, pCsr->key.nData,
- rtTopic(csrflags), pKey, nKey
- )){
- continue;
- }
- }
- return 0;
- }
- }
-
- /* The current cursor position is one this cursor should visit. Return 1. */
- return 1;
-}
-
-static int multiCursorSetupTree(MultiCursor *pCsr, int bRev){
- int rc;
-
- rc = multiCursorAllocTree(pCsr);
- if( rc==LSM_OK ){
- int i;
- for(i=pCsr->nTree-1; i>0; i--){
- multiCursorDoCompare(pCsr, i, bRev);
- }
- }
-
- assertCursorTree(pCsr);
- multiCursorCacheKey(pCsr, &rc);
-
- if( rc==LSM_OK && mcursorLocationOk(pCsr, 0)==0 ){
- rc = multiCursorAdvance(pCsr, bRev);
- }
- return rc;
-}
-
-
-static int multiCursorEnd(MultiCursor *pCsr, int bLast){
- int rc = LSM_OK;
- int i;
-
- pCsr->flags &= ~(CURSOR_NEXT_OK | CURSOR_PREV_OK);
- pCsr->flags |= (bLast ? CURSOR_PREV_OK : CURSOR_NEXT_OK);
- pCsr->iFree = 0;
-
- /* Position the two in-memory tree cursors */
- for(i=0; rc==LSM_OK && i<2; i++){
- if( pCsr->apTreeCsr[i] ){
- rc = lsmTreeCursorEnd(pCsr->apTreeCsr[i], bLast);
- }
- }
-
- for(i=0; rc==LSM_OK && i<pCsr->nPtr; i++){
- SegmentPtr *pPtr = &pCsr->aPtr[i];
- Level *pLvl = pPtr->pLevel;
- int iRhs;
- int bHit = 0;
-
- if( bLast ){
- for(iRhs=0; iRhs<pLvl->nRight && rc==LSM_OK; iRhs++){
- rc = segmentPtrEnd(pCsr, &pPtr[iRhs+1], 1);
- if( pPtr[iRhs+1].pPg ) bHit = 1;
- }
- if( bHit==0 && rc==LSM_OK ){
- rc = segmentPtrEnd(pCsr, pPtr, 1);
- }else{
- segmentPtrReset(pPtr, LSM_SEGMENTPTR_FREE_THRESHOLD);
- }
- }else{
- int bLhs = (pPtr->pSeg==&pLvl->lhs);
- assert( pPtr->pSeg==&pLvl->lhs || pPtr->pSeg==&pLvl->aRhs[0] );
-
- if( bLhs ){
- rc = segmentPtrEnd(pCsr, pPtr, 0);
- if( pPtr->pKey ) bHit = 1;
- }
- for(iRhs=0; iRhs<pLvl->nRight && rc==LSM_OK; iRhs++){
- if( bHit ){
- segmentPtrReset(&pPtr[iRhs+1], LSM_SEGMENTPTR_FREE_THRESHOLD);
- }else{
- rc = sortedRhsFirst(pCsr, pLvl, &pPtr[iRhs+bLhs]);
- }
- }
- }
- i += pLvl->nRight;
- }
-
- /* And the b-tree cursor, if applicable */
- if( rc==LSM_OK && pCsr->pBtCsr ){
- assert( bLast==0 );
- rc = btreeCursorFirst(pCsr->pBtCsr);
- }
-
- if( rc==LSM_OK ){
- rc = multiCursorSetupTree(pCsr, bLast);
- }
-
- return rc;
-}
-
-
-int mcursorSave(MultiCursor *pCsr){
- int rc = LSM_OK;
- if( pCsr->aTree ){
- int iTree = pCsr->aTree[1];
- if( iTree==CURSOR_DATA_TREE0 || iTree==CURSOR_DATA_TREE1 ){
- multiCursorCacheKey(pCsr, &rc);
- }
- }
- mcursorFreeComponents(pCsr);
- return rc;
-}
-
-int mcursorRestore(lsm_db *pDb, MultiCursor *pCsr){
- int rc;
- rc = multiCursorInit(pCsr, pDb->pClient);
- if( rc==LSM_OK && pCsr->key.pData ){
- rc = lsmMCursorSeek(pCsr,
- rtTopic(pCsr->eType), pCsr->key.pData, pCsr->key.nData, +1
- );
- }
- return rc;
-}
-
-int lsmSaveCursors(lsm_db *pDb){
- int rc = LSM_OK;
- MultiCursor *pCsr;
-
- for(pCsr=pDb->pCsr; rc==LSM_OK && pCsr; pCsr=pCsr->pNext){
- rc = mcursorSave(pCsr);
- }
- return rc;
-}
-
-int lsmRestoreCursors(lsm_db *pDb){
- int rc = LSM_OK;
- MultiCursor *pCsr;
-
- for(pCsr=pDb->pCsr; rc==LSM_OK && pCsr; pCsr=pCsr->pNext){
- rc = mcursorRestore(pDb, pCsr);
- }
- return rc;
-}
-
-int lsmMCursorFirst(MultiCursor *pCsr){
- return multiCursorEnd(pCsr, 0);
-}
-
-int lsmMCursorLast(MultiCursor *pCsr){
- return multiCursorEnd(pCsr, 1);
-}
-
-lsm_db *lsmMCursorDb(MultiCursor *pCsr){
- return pCsr->pDb;
-}
-
-void lsmMCursorReset(MultiCursor *pCsr){
- int i;
- lsmTreeCursorReset(pCsr->apTreeCsr[0]);
- lsmTreeCursorReset(pCsr->apTreeCsr[1]);
- for(i=0; i<pCsr->nPtr; i++){
- segmentPtrReset(&pCsr->aPtr[i], LSM_SEGMENTPTR_FREE_THRESHOLD);
- }
- pCsr->key.nData = 0;
-}
-
-static int treeCursorSeek(
- MultiCursor *pCsr,
- TreeCursor *pTreeCsr,
- void *pKey, int nKey,
- int eSeek,
- int *pbStop
-){
- int rc = LSM_OK;
- if( pTreeCsr ){
- int res = 0;
- lsmTreeCursorSeek(pTreeCsr, pKey, nKey, &res);
- switch( eSeek ){
- case LSM_SEEK_EQ: {
- int eType = lsmTreeCursorFlags(pTreeCsr);
- if( (res<0 && (eType & LSM_START_DELETE))
- || (res>0 && (eType & LSM_END_DELETE))
- || (res==0 && (eType & LSM_POINT_DELETE))
- ){
- *pbStop = 1;
- }else if( res==0 && (eType & LSM_INSERT) ){
- lsm_env *pEnv = pCsr->pDb->pEnv;
- void *p; int n; /* Key/value from tree-cursor */
- *pbStop = 1;
- pCsr->flags |= CURSOR_SEEK_EQ;
- rc = lsmTreeCursorKey(pTreeCsr, &pCsr->eType, &p, &n);
- if( rc==LSM_OK ) rc = sortedBlobSet(pEnv, &pCsr->key, p, n);
- if( rc==LSM_OK ) rc = lsmTreeCursorValue(pTreeCsr, &p, &n);
- if( rc==LSM_OK ) rc = sortedBlobSet(pEnv, &pCsr->val, p, n);
- }
- lsmTreeCursorReset(pTreeCsr);
- break;
- }
- case LSM_SEEK_GE:
- if( res<0 && lsmTreeCursorValid(pTreeCsr) ){
- lsmTreeCursorNext(pTreeCsr);
- }
- break;
- default:
- if( res>0 ){
- assert( lsmTreeCursorValid(pTreeCsr) );
- lsmTreeCursorPrev(pTreeCsr);
- }
- break;
- }
- }
- return rc;
-}
-
-
-/*
-** Seek the cursor.
-*/
-int lsmMCursorSeek(
- MultiCursor *pCsr,
- int iTopic,
- void *pKey, int nKey,
- int eSeek
-){
- int eESeek = eSeek; /* Effective eSeek parameter */
- int bStop = 0; /* Set to true to halt search operation */
- int rc = LSM_OK; /* Return code */
- int iPtr = 0; /* Used to iterate through pCsr->aPtr[] */
- LsmPgno iPgno = 0; /* FC pointer value */
-
- assert( pCsr->apTreeCsr[0]==0 || iTopic==0 );
- assert( pCsr->apTreeCsr[1]==0 || iTopic==0 );
-
- if( eESeek==LSM_SEEK_LEFAST ) eESeek = LSM_SEEK_LE;
-
- assert( eESeek==LSM_SEEK_EQ || eESeek==LSM_SEEK_LE || eESeek==LSM_SEEK_GE );
- assert( (pCsr->flags & CURSOR_FLUSH_FREELIST)==0 );
- assert( pCsr->nPtr==0 || pCsr->aPtr[0].pLevel );
-
- pCsr->flags &= ~(CURSOR_NEXT_OK | CURSOR_PREV_OK | CURSOR_SEEK_EQ);
- rc = treeCursorSeek(pCsr, pCsr->apTreeCsr[0], pKey, nKey, eESeek, &bStop);
- if( rc==LSM_OK && bStop==0 ){
- rc = treeCursorSeek(pCsr, pCsr->apTreeCsr[1], pKey, nKey, eESeek, &bStop);
- }
-
- /* Seek all segment pointers. */
- for(iPtr=0; iPtr<pCsr->nPtr && rc==LSM_OK && bStop==0; iPtr++){
- SegmentPtr *pPtr = &pCsr->aPtr[iPtr];
- assert( pPtr->pSeg==&pPtr->pLevel->lhs );
- rc = seekInLevel(pCsr, pPtr, eESeek, iTopic, pKey, nKey, &iPgno, &bStop);
- iPtr += pPtr->pLevel->nRight;
- }
-
- if( eSeek!=LSM_SEEK_EQ ){
- if( rc==LSM_OK ){
- rc = multiCursorAllocTree(pCsr);
- }
- if( rc==LSM_OK ){
- int i;
- for(i=pCsr->nTree-1; i>0; i--){
- multiCursorDoCompare(pCsr, i, eESeek==LSM_SEEK_LE);
- }
- if( eSeek==LSM_SEEK_GE ) pCsr->flags |= CURSOR_NEXT_OK;
- if( eSeek==LSM_SEEK_LE ) pCsr->flags |= CURSOR_PREV_OK;
- }
-
- multiCursorCacheKey(pCsr, &rc);
- if( rc==LSM_OK && eSeek!=LSM_SEEK_LEFAST && 0==mcursorLocationOk(pCsr, 0) ){
- switch( eESeek ){
- case LSM_SEEK_EQ:
- lsmMCursorReset(pCsr);
- break;
- case LSM_SEEK_GE:
- rc = lsmMCursorNext(pCsr);
- break;
- default:
- rc = lsmMCursorPrev(pCsr);
- break;
- }
- }
- }
-
- return rc;
-}
-
-int lsmMCursorValid(MultiCursor *pCsr){
- int res = 0;
- if( pCsr->flags & CURSOR_SEEK_EQ ){
- res = 1;
- }else if( pCsr->aTree ){
- int iKey = pCsr->aTree[1];
- if( iKey==CURSOR_DATA_TREE0 || iKey==CURSOR_DATA_TREE1 ){
- res = lsmTreeCursorValid(pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0]);
- }else{
- void *pKey;
- multiCursorGetKey(pCsr, iKey, 0, &pKey, 0);
- res = pKey!=0;
- }
- }
- return res;
-}
-
-static int mcursorAdvanceOk(
- MultiCursor *pCsr,
- int bReverse,
- int *pRc
-){
- void *pNew; /* Pointer to buffer containing new key */
- int nNew; /* Size of buffer pNew in bytes */
- int eNewType; /* Type of new record */
-
- if( *pRc ) return 1;
-
- /* Check the current key value. If it is not greater than (if bReverse==0)
- ** or less than (if bReverse!=0) the key currently cached in pCsr->key,
- ** then the cursor has not yet been successfully advanced.
- */
- multiCursorGetKey(pCsr, pCsr->aTree[1], &eNewType, &pNew, &nNew);
- if( pNew ){
- int typemask = (pCsr->flags & CURSOR_IGNORE_DELETE) ? ~(0) : LSM_SYSTEMKEY;
- int res = sortedDbKeyCompare(pCsr,
- eNewType & typemask, pNew, nNew,
- pCsr->eType & typemask, pCsr->key.pData, pCsr->key.nData
- );
-
- if( (bReverse==0 && res<=0) || (bReverse!=0 && res>=0) ){
- return 0;
- }
-
- multiCursorCacheKey(pCsr, pRc);
- assert( pCsr->eType==eNewType );
-
- /* If this cursor is configured to skip deleted keys, and the current
- ** cursor points to a SORTED_DELETE entry, then the cursor has not been
- ** successfully advanced.
- **
- ** Similarly, if the cursor is configured to skip system keys and the
- ** current cursor points to a system key, it has not yet been advanced.
- */
- if( *pRc==LSM_OK && 0==mcursorLocationOk(pCsr, 0) ) return 0;
- }
- return 1;
-}
-
-static void flCsrAdvance(MultiCursor *pCsr){
- assert( pCsr->flags & CURSOR_FLUSH_FREELIST );
- if( pCsr->iFree % 2 ){
- pCsr->iFree++;
- }else{
- int nEntry = pCsr->pDb->pWorker->freelist.nEntry;
- FreelistEntry *aEntry = pCsr->pDb->pWorker->freelist.aEntry;
-
- int i = nEntry - 1 - (pCsr->iFree / 2);
-
- /* If the current entry is a delete and the "end-delete" key will not
- ** be attached to the next entry, increment iFree by 1 only. */
- if( aEntry[i].iId<0 ){
- while( 1 ){
- if( i==0 || aEntry[i-1].iBlk!=aEntry[i].iBlk-1 ){
- pCsr->iFree--;
- break;
- }
- if( aEntry[i-1].iId>=0 ) break;
- pCsr->iFree += 2;
- i--;
- }
- }
- pCsr->iFree += 2;
- }
-}
-
-static int multiCursorAdvance(MultiCursor *pCsr, int bReverse){
- int rc = LSM_OK; /* Return Code */
- if( lsmMCursorValid(pCsr) ){
- do {
- int iKey = pCsr->aTree[1];
-
- assertCursorTree(pCsr);
-
- /* If this multi-cursor is advancing forwards, and the sub-cursor
- ** being advanced is the one that separator keys may be being read
- ** from, record the current absolute pointer value. */
- if( pCsr->pPrevMergePtr ){
- if( iKey==(CURSOR_DATA_SEGMENT+pCsr->nPtr) ){
- assert( pCsr->pBtCsr );
- *pCsr->pPrevMergePtr = pCsr->pBtCsr->iPtr;
- }else if( pCsr->pBtCsr==0 && pCsr->nPtr>0
- && iKey==(CURSOR_DATA_SEGMENT+pCsr->nPtr-1)
- ){
- SegmentPtr *pPtr = &pCsr->aPtr[iKey-CURSOR_DATA_SEGMENT];
- *pCsr->pPrevMergePtr = pPtr->iPtr+pPtr->iPgPtr;
- }
- }
-
- if( iKey==CURSOR_DATA_TREE0 || iKey==CURSOR_DATA_TREE1 ){
- TreeCursor *pTreeCsr = pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0];
- if( bReverse ){
- rc = lsmTreeCursorPrev(pTreeCsr);
- }else{
- rc = lsmTreeCursorNext(pTreeCsr);
- }
- }else if( iKey==CURSOR_DATA_SYSTEM ){
- assert( pCsr->flags & CURSOR_FLUSH_FREELIST );
- assert( bReverse==0 );
- flCsrAdvance(pCsr);
- }else if( iKey==(CURSOR_DATA_SEGMENT+pCsr->nPtr) ){
- assert( bReverse==0 && pCsr->pBtCsr );
- rc = btreeCursorNext(pCsr->pBtCsr);
- }else{
- rc = segmentCursorAdvance(pCsr, iKey-CURSOR_DATA_SEGMENT, bReverse);
- }
- if( rc==LSM_OK ){
- int i;
- for(i=(iKey+pCsr->nTree)/2; i>0; i=i/2){
- multiCursorDoCompare(pCsr, i, bReverse);
- }
- assertCursorTree(pCsr);
- }
- }while( mcursorAdvanceOk(pCsr, bReverse, &rc)==0 );
- }
- return rc;
-}
-
-int lsmMCursorNext(MultiCursor *pCsr){
- if( (pCsr->flags & CURSOR_NEXT_OK)==0 ) return LSM_MISUSE_BKPT;
- return multiCursorAdvance(pCsr, 0);
-}
-
-int lsmMCursorPrev(MultiCursor *pCsr){
- if( (pCsr->flags & CURSOR_PREV_OK)==0 ) return LSM_MISUSE_BKPT;
- return multiCursorAdvance(pCsr, 1);
-}
-
-int lsmMCursorKey(MultiCursor *pCsr, void **ppKey, int *pnKey){
- if( (pCsr->flags & CURSOR_SEEK_EQ) || pCsr->aTree==0 ){
- *pnKey = pCsr->key.nData;
- *ppKey = pCsr->key.pData;
- }else{
- int iKey = pCsr->aTree[1];
-
- if( iKey==CURSOR_DATA_TREE0 || iKey==CURSOR_DATA_TREE1 ){
- TreeCursor *pTreeCsr = pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0];
- lsmTreeCursorKey(pTreeCsr, 0, ppKey, pnKey);
- }else{
- int nKey;
-
-#ifndef NDEBUG
- void *pKey;
- int eType;
- multiCursorGetKey(pCsr, iKey, &eType, &pKey, &nKey);
- assert( eType==pCsr->eType );
- assert( nKey==pCsr->key.nData );
- assert( memcmp(pKey, pCsr->key.pData, nKey)==0 );
-#endif
-
- nKey = pCsr->key.nData;
- if( nKey==0 ){
- *ppKey = 0;
- }else{
- *ppKey = pCsr->key.pData;
- }
- *pnKey = nKey;
- }
- }
- return LSM_OK;
-}
-
-/*
-** Compare the current key that cursor csr points to with pKey/nKey. Set
-** *piRes to the result and return LSM_OK.
-*/
-int lsm_csr_cmp(lsm_cursor *csr, const void *pKey, int nKey, int *piRes){
- MultiCursor *pCsr = (MultiCursor *)csr;
- void *pCsrkey; int nCsrkey;
- int rc;
- rc = lsmMCursorKey(pCsr, &pCsrkey, &nCsrkey);
- if( rc==LSM_OK ){
- int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
- *piRes = sortedKeyCompare(xCmp, 0, pCsrkey, nCsrkey, 0, (void *)pKey, nKey);
- }
- return rc;
-}
-
-int lsmMCursorValue(MultiCursor *pCsr, void **ppVal, int *pnVal){
- void *pVal;
- int nVal;
- int rc;
- if( (pCsr->flags & CURSOR_SEEK_EQ) || pCsr->aTree==0 ){
- rc = LSM_OK;
- nVal = pCsr->val.nData;
- pVal = pCsr->val.pData;
- }else{
-
- assert( pCsr->aTree );
- assert( mcursorLocationOk(pCsr, (pCsr->flags & CURSOR_IGNORE_DELETE)) );
-
- rc = multiCursorGetVal(pCsr, pCsr->aTree[1], &pVal, &nVal);
- if( pVal && rc==LSM_OK ){
- rc = sortedBlobSet(pCsr->pDb->pEnv, &pCsr->val, pVal, nVal);
- pVal = pCsr->val.pData;
- }
-
- if( rc!=LSM_OK ){
- pVal = 0;
- nVal = 0;
- }
- }
- *ppVal = pVal;
- *pnVal = nVal;
- return rc;
-}
-
-int lsmMCursorType(MultiCursor *pCsr, int *peType){
- assert( pCsr->aTree );
- multiCursorGetKey(pCsr, pCsr->aTree[1], peType, 0, 0);
- return LSM_OK;
-}
-
-/*
-** Buffer aData[], size nData, is assumed to contain a valid b-tree
-** hierarchy page image. Return the offset in aData[] of the next free
-** byte in the data area (where a new cell may be written if there is
-** space).
-*/
-static int mergeWorkerPageOffset(u8 *aData, int nData){
- int nRec;
- int iOff;
- int nKey;
- int eType;
-
- nRec = lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]);
- iOff = lsmGetU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec-1)]);
- eType = aData[iOff++];
- assert( eType==0
- || eType==(LSM_SYSTEMKEY|LSM_SEPARATOR)
- || eType==(LSM_SEPARATOR)
- );
-
- iOff += lsmVarintGet32(&aData[iOff], &nKey);
- iOff += lsmVarintGet32(&aData[iOff], &nKey);
-
- return iOff + (eType ? nKey : 0);
-}
-
-/*
-** Following a checkpoint operation, database pages that are part of the
-** checkpointed state of the LSM are deemed read-only. This includes the
-** right-most page of the b-tree hierarchy of any separators array under
-** construction, and all pages between it and the b-tree root, inclusive.
-** This is a problem, as when further pages are appended to the separators
-** array, entries must be added to the indicated b-tree hierarchy pages.
-**
-** This function copies all such b-tree pages to new locations, so that
-** they can be modified as required.
-**
-** The complication is that not all database pages are the same size - due
-** to the way the file.c module works some (the first and last in each block)
-** are 4 bytes smaller than the others.
-*/
-static int mergeWorkerMoveHierarchy(
- MergeWorker *pMW, /* Merge worker */
- int bSep /* True for separators run */
-){
- lsm_db *pDb = pMW->pDb; /* Database handle */
- int rc = LSM_OK; /* Return code */
- int i;
- Page **apHier = pMW->hier.apHier;
- int nHier = pMW->hier.nHier;
-
- for(i=0; rc==LSM_OK && i<nHier; i++){
- Page *pNew = 0;
- rc = lsmFsSortedAppend(pDb->pFS, pDb->pWorker, pMW->pLevel, 1, &pNew);
- assert( rc==LSM_OK );
-
- if( rc==LSM_OK ){
- u8 *a1; int n1;
- u8 *a2; int n2;
-
- a1 = fsPageData(pNew, &n1);
- a2 = fsPageData(apHier[i], &n2);
-
- assert( n1==n2 || n1+4==n2 );
-
- if( n1==n2 ){
- memcpy(a1, a2, n2);
- }else{
- int nEntry = pageGetNRec(a2, n2);
- int iEof1 = SEGMENT_EOF(n1, nEntry);
- int iEof2 = SEGMENT_EOF(n2, nEntry);
-
- memcpy(a1, a2, iEof2 - 4);
- memcpy(&a1[iEof1], &a2[iEof2], n2 - iEof2);
- }
-
- lsmFsPageRelease(apHier[i]);
- apHier[i] = pNew;
-
-#if 0
- assert( n1==n2 || n1+4==n2 || n2+4==n1 );
- if( n1>=n2 ){
- /* If n1 (size of the new page) is equal to or greater than n2 (the
- ** size of the old page), then copy the data into the new page. If
- ** n1==n2, this could be done with a single memcpy(). However,
- ** since sometimes n1>n2, the page content and footer must be copied
- ** separately. */
- int nEntry = pageGetNRec(a2, n2);
- int iEof1 = SEGMENT_EOF(n1, nEntry);
- int iEof2 = SEGMENT_EOF(n2, nEntry);
- memcpy(a1, a2, iEof2);
- memcpy(&a1[iEof1], &a2[iEof2], n2 - iEof2);
- lsmFsPageRelease(apHier[i]);
- apHier[i] = pNew;
- }else{
- lsmPutU16(&a1[SEGMENT_FLAGS_OFFSET(n1)], SEGMENT_BTREE_FLAG);
- lsmPutU16(&a1[SEGMENT_NRECORD_OFFSET(n1)], 0);
- lsmPutU64(&a1[SEGMENT_POINTER_OFFSET(n1)], 0);
- i = i - 1;
- lsmFsPageRelease(pNew);
- }
-#endif
- }
- }
-
-#ifdef LSM_DEBUG
- if( rc==LSM_OK ){
- for(i=0; i<nHier; i++) assert( lsmFsPageWritable(apHier[i]) );
- }
-#endif
-
- return rc;
-}
-
-/*
-** Allocate and populate the MergeWorker.apHier[] array.
-*/
-static int mergeWorkerLoadHierarchy(MergeWorker *pMW){
- int rc = LSM_OK;
- Segment *pSeg;
- Hierarchy *p;
-
- pSeg = &pMW->pLevel->lhs;
- p = &pMW->hier;
-
- if( p->apHier==0 && pSeg->iRoot!=0 ){
- FileSystem *pFS = pMW->pDb->pFS;
- lsm_env *pEnv = pMW->pDb->pEnv;
- Page **apHier = 0;
- int nHier = 0;
- int iPg = (int)pSeg->iRoot;
-
- do {
- Page *pPg = 0;
- u8 *aData;
- int nData;
- int flags;
-
- rc = lsmFsDbPageGet(pFS, pSeg, iPg, &pPg);
- if( rc!=LSM_OK ) break;
-
- aData = fsPageData(pPg, &nData);
- flags = pageGetFlags(aData, nData);
- if( flags&SEGMENT_BTREE_FLAG ){
- Page **apNew = (Page **)lsmRealloc(
- pEnv, apHier, sizeof(Page *)*(nHier+1)
- );
- if( apNew==0 ){
- rc = LSM_NOMEM_BKPT;
- break;
- }
- apHier = apNew;
- memmove(&apHier[1], &apHier[0], sizeof(Page *) * nHier);
- nHier++;
-
- apHier[0] = pPg;
- iPg = (int)pageGetPtr(aData, nData);
- }else{
- lsmFsPageRelease(pPg);
- break;
- }
- }while( 1 );
-
- if( rc==LSM_OK ){
- u8 *aData;
- int nData;
- aData = fsPageData(apHier[0], &nData);
- pMW->aSave[0].iPgno = pageGetPtr(aData, nData);
- p->nHier = nHier;
- p->apHier = apHier;
- rc = mergeWorkerMoveHierarchy(pMW, 0);
- }else{
- int i;
- for(i=0; i<nHier; i++){
- lsmFsPageRelease(apHier[i]);
- }
- lsmFree(pEnv, apHier);
- }
- }
-
- return rc;
-}
-
-/*
-** B-tree pages use almost the same format as regular pages. The
-** differences are:
-**
-** 1. The record format is (usually, see below) as follows:
-**
-** + Type byte (always SORTED_SEPARATOR or SORTED_SYSTEM_SEPARATOR),
-** + Absolute pointer value (varint),
-** + Number of bytes in key (varint),
-** + LsmBlob containing key data.
-**
-** 2. All pointer values are stored as absolute values (not offsets
-** relative to the footer pointer value).
-**
-** 3. Each pointer that is part of a record points to a page that
-** contains keys smaller than the records key (note: not "equal to or
-** smaller than - smaller than").
-**
-** 4. The pointer in the page footer of a b-tree page points to a page
-** that contains keys equal to or larger than the largest key on the
-** b-tree page.
-**
-** The reason for having the page footer pointer point to the right-child
-** (instead of the left) is that doing things this way makes the
-** mergeWorkerMoveHierarchy() operation less complicated (since the pointers
-** that need to be updated are all stored as fixed-size integers within the
-** page footer, not varints in page records).
-**
-** Records may not span b-tree pages. If this function is called to add a
-** record larger than (page-size / 4) bytes, then a pointer to the indexed
-** array page that contains the main record is added to the b-tree instead.
-** In this case the record format is:
-**
-** + 0x00 byte (1 byte)
-** + Absolute pointer value (varint),
-** + Absolute page number of page containing key (varint).
-**
-** See function seekInBtree() for the code that traverses b-tree pages.
-*/
-
-static int mergeWorkerBtreeWrite(
- MergeWorker *pMW,
- u8 eType,
- LsmPgno iPtr,
- LsmPgno iKeyPg,
- void *pKey,
- int nKey
-){
- Hierarchy *p = &pMW->hier;
- lsm_db *pDb = pMW->pDb; /* Database handle */
- int rc = LSM_OK; /* Return Code */
- int iLevel; /* Level of b-tree hierachy to write to */
- int nData; /* Size of aData[] in bytes */
- u8 *aData; /* Page data for level iLevel */
- int iOff; /* Offset on b-tree page to write record to */
- int nRec; /* Initial number of records on b-tree page */
-
- /* iKeyPg should be zero for an ordinary b-tree key, or non-zero for an
- ** indirect key. The flags byte for an indirect key is 0x00. */
- assert( (eType==0)==(iKeyPg!=0) );
-
- /* The MergeWorker.apHier[] array contains the right-most leaf of the b-tree
- ** hierarchy, the root node, and all nodes that lie on the path between.
- ** apHier[0] is the right-most leaf and apHier[pMW->nHier-1] is the current
- ** root page.
- **
- ** This loop searches for a node with enough space to store the key on,
- ** starting with the leaf and iterating up towards the root. When the loop
- ** exits, the key may be written to apHier[iLevel]. */
- for(iLevel=0; iLevel<=p->nHier; iLevel++){
- int nByte; /* Number of free bytes required */
-
- if( iLevel==p->nHier ){
- /* Extend the array and allocate a new root page. */
- Page **aNew;
- aNew = (Page **)lsmRealloc(
- pMW->pDb->pEnv, p->apHier, sizeof(Page *)*(p->nHier+1)
- );
- if( !aNew ){
- return LSM_NOMEM_BKPT;
- }
- p->apHier = aNew;
- }else{
- Page *pOld;
- int nFree;
-
- /* If the key will fit on this page, break out of the loop here.
- ** The new entry will be written to page apHier[iLevel]. */
- pOld = p->apHier[iLevel];
- assert( lsmFsPageWritable(pOld) );
- aData = fsPageData(pOld, &nData);
- if( eType==0 ){
- nByte = 2 + 1 + lsmVarintLen32((int)iPtr) + lsmVarintLen32((int)iKeyPg);
- }else{
- nByte = 2 + 1 + lsmVarintLen32((int)iPtr) + lsmVarintLen32(nKey) + nKey;
- }
- nRec = pageGetNRec(aData, nData);
- nFree = SEGMENT_EOF(nData, nRec) - mergeWorkerPageOffset(aData, nData);
- if( nByte<=nFree ) break;
-
- /* Otherwise, this page is full. Set the right-hand-child pointer
- ** to iPtr and release it. */
- lsmPutU64(&aData[SEGMENT_POINTER_OFFSET(nData)], iPtr);
- assert( lsmFsPageNumber(pOld)==0 );
- rc = lsmFsPagePersist(pOld);
- if( rc==LSM_OK ){
- iPtr = lsmFsPageNumber(pOld);
- lsmFsPageRelease(pOld);
- }
- }
-
- /* Allocate a new page for apHier[iLevel]. */
- p->apHier[iLevel] = 0;
- if( rc==LSM_OK ){
- rc = lsmFsSortedAppend(
- pDb->pFS, pDb->pWorker, pMW->pLevel, 1, &p->apHier[iLevel]
- );
- }
- if( rc!=LSM_OK ) return rc;
-
- aData = fsPageData(p->apHier[iLevel], &nData);
- memset(aData, 0, nData);
- lsmPutU16(&aData[SEGMENT_FLAGS_OFFSET(nData)], SEGMENT_BTREE_FLAG);
- lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], 0);
-
- if( iLevel==p->nHier ){
- p->nHier++;
- break;
- }
- }
-
- /* Write the key into page apHier[iLevel]. */
- aData = fsPageData(p->apHier[iLevel], &nData);
- iOff = mergeWorkerPageOffset(aData, nData);
- nRec = pageGetNRec(aData, nData);
- lsmPutU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec)], (u16)iOff);
- lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], (u16)(nRec+1));
- if( eType==0 ){
- aData[iOff++] = 0x00;
- iOff += lsmVarintPut32(&aData[iOff], (int)iPtr);
- iOff += lsmVarintPut32(&aData[iOff], (int)iKeyPg);
- }else{
- aData[iOff++] = eType;
- iOff += lsmVarintPut32(&aData[iOff], (int)iPtr);
- iOff += lsmVarintPut32(&aData[iOff], nKey);
- memcpy(&aData[iOff], pKey, nKey);
- }
-
- return rc;
-}
-
-static int mergeWorkerBtreeIndirect(MergeWorker *pMW){
- int rc = LSM_OK;
- if( pMW->iIndirect ){
- LsmPgno iKeyPg = pMW->aSave[1].iPgno;
- rc = mergeWorkerBtreeWrite(pMW, 0, pMW->iIndirect, iKeyPg, 0, 0);
- pMW->iIndirect = 0;
- }
- return rc;
-}
-
-/*
-** Append the database key (iTopic/pKey/nKey) to the b-tree under
-** construction. This key has not yet been written to a segment page.
-** The pointer that will accompany the new key in the b-tree - that
-** points to the completed segment page that contains keys smaller than
-** (pKey/nKey) is currently stored in pMW->aSave[0].iPgno.
-*/
-static int mergeWorkerPushHierarchy(
- MergeWorker *pMW, /* Merge worker object */
- int iTopic, /* Topic value for this key */
- void *pKey, /* Pointer to key buffer */
- int nKey /* Size of pKey buffer in bytes */
-){
- int rc = LSM_OK; /* Return Code */
- LsmPgno iPtr; /* Pointer value to accompany pKey/nKey */
-
- assert( pMW->aSave[0].bStore==0 );
- assert( pMW->aSave[1].bStore==0 );
- rc = mergeWorkerBtreeIndirect(pMW);
-
- /* Obtain the absolute pointer value to store along with the key in the
- ** page body. This pointer points to a page that contains keys that are
- ** smaller than pKey/nKey. */
- iPtr = pMW->aSave[0].iPgno;
- assert( iPtr!=0 );
-
- /* Determine if the indirect format should be used. */
- if( (nKey*4 > lsmFsPageSize(pMW->pDb->pFS)) ){
- pMW->iIndirect = iPtr;
- pMW->aSave[1].bStore = 1;
- }else{
- rc = mergeWorkerBtreeWrite(
- pMW, (u8)(iTopic | LSM_SEPARATOR), iPtr, 0, pKey, nKey
- );
- }
-
- /* Ensure that the SortedRun.iRoot field is correct. */
- return rc;
-}
-
-static int mergeWorkerFinishHierarchy(
- MergeWorker *pMW /* Merge worker object */
-){
- int i; /* Used to loop through apHier[] */
- int rc = LSM_OK; /* Return code */
- LsmPgno iPtr; /* New right-hand-child pointer value */
-
- iPtr = pMW->aSave[0].iPgno;
- for(i=0; i<pMW->hier.nHier && rc==LSM_OK; i++){
- Page *pPg = pMW->hier.apHier[i];
- int nData; /* Size of aData[] in bytes */
- u8 *aData; /* Page data for pPg */
-
- aData = fsPageData(pPg, &nData);
- lsmPutU64(&aData[SEGMENT_POINTER_OFFSET(nData)], iPtr);
-
- rc = lsmFsPagePersist(pPg);
- iPtr = lsmFsPageNumber(pPg);
- lsmFsPageRelease(pPg);
- }
-
- if( pMW->hier.nHier ){
- pMW->pLevel->lhs.iRoot = iPtr;
- lsmFree(pMW->pDb->pEnv, pMW->hier.apHier);
- pMW->hier.apHier = 0;
- pMW->hier.nHier = 0;
- }
-
- return rc;
-}
-
-static int mergeWorkerAddPadding(
- MergeWorker *pMW /* Merge worker object */
-){
- FileSystem *pFS = pMW->pDb->pFS;
- return lsmFsSortedPadding(pFS, pMW->pDb->pWorker, &pMW->pLevel->lhs);
-}
-
-/*
-** Release all page references currently held by the merge-worker passed
-** as the only argument. Unless an error has occurred, all pages have
-** already been released.
-*/
-static void mergeWorkerReleaseAll(MergeWorker *pMW){
- int i;
- lsmFsPageRelease(pMW->pPage);
- pMW->pPage = 0;
-
- for(i=0; i<pMW->hier.nHier; i++){
- lsmFsPageRelease(pMW->hier.apHier[i]);
- pMW->hier.apHier[i] = 0;
- }
- lsmFree(pMW->pDb->pEnv, pMW->hier.apHier);
- pMW->hier.apHier = 0;
- pMW->hier.nHier = 0;
-}
-
-static int keyszToSkip(FileSystem *pFS, int nKey){
- int nPgsz; /* Nominal database page size */
- nPgsz = lsmFsPageSize(pFS);
- return LSM_MIN(((nKey * 4) / nPgsz), 3);
-}
-
-/*
-** Release the reference to the current output page of merge-worker *pMW
-** (reference pMW->pPage). Set the page number values in aSave[] as
-** required (see comments above struct MergeWorker for details).
-*/
-static int mergeWorkerPersistAndRelease(MergeWorker *pMW){
- int rc;
- int i;
-
- assert( pMW->pPage || (pMW->aSave[0].bStore==0 && pMW->aSave[1].bStore==0) );
-
- /* Persist the page */
- rc = lsmFsPagePersist(pMW->pPage);
-
- /* If required, save the page number. */
- for(i=0; i<2; i++){
- if( pMW->aSave[i].bStore ){
- pMW->aSave[i].iPgno = lsmFsPageNumber(pMW->pPage);
- pMW->aSave[i].bStore = 0;
- }
- }
-
- /* Release the completed output page. */
- lsmFsPageRelease(pMW->pPage);
- pMW->pPage = 0;
- return rc;
-}
-
-/*
-** Advance to the next page of an output run being populated by merge-worker
-** pMW. The footer of the new page is initialized to indicate that it contains
-** zero records. The flags field is cleared. The page footer pointer field
-** is set to iFPtr.
-**
-** If successful, LSM_OK is returned. Otherwise, an error code.
-*/
-static int mergeWorkerNextPage(
- MergeWorker *pMW, /* Merge worker object to append page to */
- LsmPgno iFPtr /* Pointer value for footer of new page */
-){
- int rc = LSM_OK; /* Return code */
- Page *pNext = 0; /* New page appended to run */
- lsm_db *pDb = pMW->pDb; /* Database handle */
-
- rc = lsmFsSortedAppend(pDb->pFS, pDb->pWorker, pMW->pLevel, 0, &pNext);
- assert( rc || pMW->pLevel->lhs.iFirst>0 || pMW->pDb->compress.xCompress );
-
- if( rc==LSM_OK ){
- u8 *aData; /* Data buffer belonging to page pNext */
- int nData; /* Size of aData[] in bytes */
-
- rc = mergeWorkerPersistAndRelease(pMW);
-
- pMW->pPage = pNext;
- pMW->pLevel->pMerge->iOutputOff = 0;
- aData = fsPageData(pNext, &nData);
- lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], 0);
- lsmPutU16(&aData[SEGMENT_FLAGS_OFFSET(nData)], 0);
- lsmPutU64(&aData[SEGMENT_POINTER_OFFSET(nData)], iFPtr);
- pMW->nWork++;
- }
-
- return rc;
-}
-
-/*
-** Write a blob of data into an output segment being populated by a
-** merge-worker object. If argument bSep is true, write into the separators
-** array. Otherwise, the main array.
-**
-** This function is used to write the blobs of data for keys and values.
-*/
-static int mergeWorkerData(
- MergeWorker *pMW, /* Merge worker object */
- int bSep, /* True to write to separators run */
- int iFPtr, /* Footer ptr for new pages */
- u8 *aWrite, /* Write data from this buffer */
- int nWrite /* Size of aWrite[] in bytes */
-){
- int rc = LSM_OK; /* Return code */
- int nRem = nWrite; /* Number of bytes still to write */
-
- while( rc==LSM_OK && nRem>0 ){
- Merge *pMerge = pMW->pLevel->pMerge;
- int nCopy; /* Number of bytes to copy */
- u8 *aData; /* Pointer to buffer of current output page */
- int nData; /* Size of aData[] in bytes */
- int nRec; /* Number of records on current output page */
- int iOff; /* Offset in aData[] to write to */
-
- assert( lsmFsPageWritable(pMW->pPage) );
-
- aData = fsPageData(pMW->pPage, &nData);
- nRec = pageGetNRec(aData, nData);
- iOff = pMerge->iOutputOff;
- nCopy = LSM_MIN(nRem, SEGMENT_EOF(nData, nRec) - iOff);
-
- memcpy(&aData[iOff], &aWrite[nWrite-nRem], nCopy);
- nRem -= nCopy;
-
- if( nRem>0 ){
- rc = mergeWorkerNextPage(pMW, iFPtr);
- }else{
- pMerge->iOutputOff = iOff + nCopy;
- }
- }
-
- return rc;
-}
-
-
-/*
-** The MergeWorker passed as the only argument is working to merge two or
-** more existing segments together (not to flush an in-memory tree). It
-** has not yet written the first key to the first page of the output.
-*/
-static int mergeWorkerFirstPage(MergeWorker *pMW){
- int rc = LSM_OK; /* Return code */
- Page *pPg = 0; /* First page of run pSeg */
- int iFPtr = 0; /* Pointer value read from footer of pPg */
- MultiCursor *pCsr = pMW->pCsr;
-
- assert( pMW->pPage==0 );
-
- if( pCsr->pBtCsr ){
- rc = LSM_OK;
- iFPtr = (int)pMW->pLevel->pNext->lhs.iFirst;
- }else if( pCsr->nPtr>0 ){
- Segment *pSeg;
- pSeg = pCsr->aPtr[pCsr->nPtr-1].pSeg;
- rc = lsmFsDbPageGet(pMW->pDb->pFS, pSeg, pSeg->iFirst, &pPg);
- if( rc==LSM_OK ){
- u8 *aData; /* Buffer for page pPg */
- int nData; /* Size of aData[] in bytes */
- aData = fsPageData(pPg, &nData);
- iFPtr = (int)pageGetPtr(aData, nData);
- lsmFsPageRelease(pPg);
- }
- }
-
- if( rc==LSM_OK ){
- rc = mergeWorkerNextPage(pMW, iFPtr);
- if( pCsr->pPrevMergePtr ) *pCsr->pPrevMergePtr = iFPtr;
- pMW->aSave[0].bStore = 1;
- }
-
- return rc;
-}
-
-static int mergeWorkerWrite(
- MergeWorker *pMW, /* Merge worker object to write into */
- int eType, /* One of SORTED_SEPARATOR, WRITE or DELETE */
- void *pKey, int nKey, /* Key value */
- void *pVal, int nVal, /* Value value */
- int iPtr /* Absolute value of page pointer, or 0 */
-){
- int rc = LSM_OK; /* Return code */
- Merge *pMerge; /* Persistent part of level merge state */
- int nHdr; /* Space required for this record header */
- Page *pPg; /* Page to write to */
- u8 *aData; /* Data buffer for page pWriter->pPage */
- int nData = 0; /* Size of buffer aData[] in bytes */
- int nRec = 0; /* Number of records on page pPg */
- int iFPtr = 0; /* Value of pointer in footer of pPg */
- int iRPtr = 0; /* Value of pointer written into record */
- int iOff = 0; /* Current write offset within page pPg */
- Segment *pSeg; /* Segment being written */
- int flags = 0; /* If != 0, flags value for page footer */
- int bFirst = 0; /* True for first key of output run */
-
- pMerge = pMW->pLevel->pMerge;
- pSeg = &pMW->pLevel->lhs;
-
- if( pSeg->iFirst==0 && pMW->pPage==0 ){
- rc = mergeWorkerFirstPage(pMW);
- bFirst = 1;
- }
- pPg = pMW->pPage;
- if( pPg ){
- aData = fsPageData(pPg, &nData);
- nRec = pageGetNRec(aData, nData);
- iFPtr = (int)pageGetPtr(aData, nData);
- iRPtr = iPtr - iFPtr;
- }
-
- /* Figure out how much space is required by the new record. The space
- ** required is divided into two sections: the header and the body. The
- ** header consists of the intial varint fields. The body are the blobs
- ** of data that correspond to the key and value data. The entire header
- ** must be stored on the page. The body may overflow onto the next and
- ** subsequent pages.
- **
- ** The header space is:
- **
- ** 1) record type - 1 byte.
- ** 2) Page-pointer-offset - 1 varint
- ** 3) Key size - 1 varint
- ** 4) Value size - 1 varint (only if LSM_INSERT flag is set)
- */
- if( rc==LSM_OK ){
- nHdr = 1 + lsmVarintLen32(iRPtr) + lsmVarintLen32(nKey);
- if( rtIsWrite(eType) ) nHdr += lsmVarintLen32(nVal);
-
- /* If the entire header will not fit on page pPg, or if page pPg is
- ** marked read-only, advance to the next page of the output run. */
- iOff = pMerge->iOutputOff;
- if( iOff<0 || pPg==0 || iOff+nHdr > SEGMENT_EOF(nData, nRec+1) ){
- if( iOff>=0 && pPg ){
- /* Zero any free space on the page */
- assert( aData );
- memset(&aData[iOff], 0, SEGMENT_EOF(nData, nRec)-iOff);
- }
- iFPtr = (int)*pMW->pCsr->pPrevMergePtr;
- iRPtr = iPtr - iFPtr;
- iOff = 0;
- nRec = 0;
- rc = mergeWorkerNextPage(pMW, iFPtr);
- pPg = pMW->pPage;
- }
- }
-
- /* If this record header will be the first on the page, and the page is
- ** not the very first in the entire run, add a copy of the key to the
- ** b-tree hierarchy.
- */
- if( rc==LSM_OK && nRec==0 && bFirst==0 ){
- assert( pMerge->nSkip>=0 );
-
- if( pMerge->nSkip==0 ){
- rc = mergeWorkerPushHierarchy(pMW, rtTopic(eType), pKey, nKey);
- assert( pMW->aSave[0].bStore==0 );
- pMW->aSave[0].bStore = 1;
- pMerge->nSkip = keyszToSkip(pMW->pDb->pFS, nKey);
- }else{
- pMerge->nSkip--;
- flags = PGFTR_SKIP_THIS_FLAG;
- }
-
- if( pMerge->nSkip ) flags |= PGFTR_SKIP_NEXT_FLAG;
- }
-
- /* Update the output segment */
- if( rc==LSM_OK ){
- aData = fsPageData(pPg, &nData);
-
- /* Update the page footer. */
- lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], (u16)(nRec+1));
- lsmPutU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec)], (u16)iOff);
- if( flags ) lsmPutU16(&aData[SEGMENT_FLAGS_OFFSET(nData)], (u16)flags);
-
- /* Write the entry header into the current page. */
- aData[iOff++] = (u8)eType; /* 1 */
- iOff += lsmVarintPut32(&aData[iOff], iRPtr); /* 2 */
- iOff += lsmVarintPut32(&aData[iOff], nKey); /* 3 */
- if( rtIsWrite(eType) ) iOff += lsmVarintPut32(&aData[iOff], nVal); /* 4 */
- pMerge->iOutputOff = iOff;
-
- /* Write the key and data into the segment. */
- assert( iFPtr==pageGetPtr(aData, nData) );
- rc = mergeWorkerData(pMW, 0, iFPtr+iRPtr, pKey, nKey);
- if( rc==LSM_OK && rtIsWrite(eType) ){
- if( rc==LSM_OK ){
- rc = mergeWorkerData(pMW, 0, iFPtr+iRPtr, pVal, nVal);
- }
- }
- }
-
- return rc;
-}
-
-
-/*
-** Free all resources allocated by mergeWorkerInit().
-*/
-static void mergeWorkerShutdown(MergeWorker *pMW, int *pRc){
- int i; /* Iterator variable */
- int rc = *pRc;
- MultiCursor *pCsr = pMW->pCsr;
-
- /* Unless the merge has finished, save the cursor position in the
- ** Merge.aInput[] array. See function mergeWorkerInit() for the
- ** code to restore a cursor position based on aInput[]. */
- if( rc==LSM_OK && pCsr ){
- Merge *pMerge = pMW->pLevel->pMerge;
- if( lsmMCursorValid(pCsr) ){
- int bBtree = (pCsr->pBtCsr!=0);
- int iPtr;
-
- /* pMerge->nInput==0 indicates that this is a FlushTree() operation. */
- assert( pMerge->nInput==0 || pMW->pLevel->nRight>0 );
- assert( pMerge->nInput==0 || pMerge->nInput==(pCsr->nPtr+bBtree) );
-
- for(i=0; i<(pMerge->nInput-bBtree); i++){
- SegmentPtr *pPtr = &pCsr->aPtr[i];
- if( pPtr->pPg ){
- pMerge->aInput[i].iPg = lsmFsPageNumber(pPtr->pPg);
- pMerge->aInput[i].iCell = pPtr->iCell;
- }else{
- pMerge->aInput[i].iPg = 0;
- pMerge->aInput[i].iCell = 0;
- }
- }
- if( bBtree && pMerge->nInput ){
- assert( i==pCsr->nPtr );
- btreeCursorPosition(pCsr->pBtCsr, &pMerge->aInput[i]);
- }
-
- /* Store the location of the split-key */
- iPtr = pCsr->aTree[1] - CURSOR_DATA_SEGMENT;
- if( iPtr<pCsr->nPtr ){
- pMerge->splitkey = pMerge->aInput[iPtr];
- }else{
- btreeCursorSplitkey(pCsr->pBtCsr, &pMerge->splitkey);
- }
- }
-
- /* Zero any free space left on the final page. This helps with
- ** compression if using a compression hook. And prevents valgrind
- ** from complaining about uninitialized byte passed to write(). */
- if( pMW->pPage ){
- int nData;
- u8 *aData = fsPageData(pMW->pPage, &nData);
- int iOff = pMerge->iOutputOff;
- int iEof = SEGMENT_EOF(nData, pageGetNRec(aData, nData));
- memset(&aData[iOff], 0, iEof - iOff);
- }
-
- pMerge->iOutputOff = -1;
- }
-
- lsmMCursorClose(pCsr, 0);
-
- /* Persist and release the output page. */
- if( rc==LSM_OK ) rc = mergeWorkerPersistAndRelease(pMW);
- if( rc==LSM_OK ) rc = mergeWorkerBtreeIndirect(pMW);
- if( rc==LSM_OK ) rc = mergeWorkerFinishHierarchy(pMW);
- if( rc==LSM_OK ) rc = mergeWorkerAddPadding(pMW);
- lsmFsFlushWaiting(pMW->pDb->pFS, &rc);
- mergeWorkerReleaseAll(pMW);
-
- lsmFree(pMW->pDb->pEnv, pMW->aGobble);
- pMW->aGobble = 0;
- pMW->pCsr = 0;
-
- *pRc = rc;
-}
-
-/*
-** The cursor passed as the first argument is being used as the input for
-** a merge operation. When this function is called, *piFlags contains the
-** database entry flags for the current entry. The entry about to be written
-** to the output.
-**
-** Note that this function only has to work for cursors configured to
-** iterate forwards (not backwards).
-*/
-static void mergeRangeDeletes(MultiCursor *pCsr, int *piVal, int *piFlags){
- int f = *piFlags;
- int iKey = pCsr->aTree[1];
- int i;
-
- assert( pCsr->flags & CURSOR_NEXT_OK );
- if( pCsr->flags & CURSOR_IGNORE_DELETE ){
- /* The ignore-delete flag is set when the output of the merge will form
- ** the oldest level in the database. In this case there is no point in
- ** retaining any range-delete flags. */
- assert( (f & LSM_POINT_DELETE)==0 );
- f &= ~(LSM_START_DELETE|LSM_END_DELETE);
- }else{
- for(i=0; i<(CURSOR_DATA_SEGMENT + pCsr->nPtr); i++){
- if( i!=iKey ){
- int eType;
- void *pKey;
- int nKey;
- int res;
- multiCursorGetKey(pCsr, i, &eType, &pKey, &nKey);
-
- if( pKey ){
- res = sortedKeyCompare(pCsr->pDb->xCmp,
- rtTopic(pCsr->eType), pCsr->key.pData, pCsr->key.nData,
- rtTopic(eType), pKey, nKey
- );
- assert( res<=0 );
- if( res==0 ){
- if( (f & (LSM_INSERT|LSM_POINT_DELETE))==0 ){
- if( eType & LSM_INSERT ){
- f |= LSM_INSERT;
- *piVal = i;
- }
- else if( eType & LSM_POINT_DELETE ){
- f |= LSM_POINT_DELETE;
- }
- }
- f |= (eType & (LSM_END_DELETE|LSM_START_DELETE));
- }
-
- if( i>iKey && (eType & LSM_END_DELETE) && res<0 ){
- if( f & (LSM_INSERT|LSM_POINT_DELETE) ){
- f |= (LSM_END_DELETE|LSM_START_DELETE);
- }else{
- f = 0;
- }
- break;
- }
- }
- }
- }
-
- assert( (f & LSM_INSERT)==0 || (f & LSM_POINT_DELETE)==0 );
- if( (f & LSM_START_DELETE)
- && (f & LSM_END_DELETE)
- && (f & LSM_POINT_DELETE )
- ){
- f = 0;
- }
- }
-
- *piFlags = f;
-}
-
-static int mergeWorkerStep(MergeWorker *pMW){
- lsm_db *pDb = pMW->pDb; /* Database handle */
- MultiCursor *pCsr; /* Cursor to read input data from */
- int rc = LSM_OK; /* Return code */
- int eType; /* SORTED_SEPARATOR, WRITE or DELETE */
- void *pKey; int nKey; /* Key */
- LsmPgno iPtr;
- int iVal;
-
- pCsr = pMW->pCsr;
-
- /* Pull the next record out of the source cursor. */
- lsmMCursorKey(pCsr, &pKey, &nKey);
- eType = pCsr->eType;
-
- /* Figure out if the output record may have a different pointer value
- ** than the previous. This is the case if the current key is identical to
- ** a key that appears in the lowest level run being merged. If so, set
- ** iPtr to the absolute pointer value. If not, leave iPtr set to zero,
- ** indicating that the output pointer value should be a copy of the pointer
- ** value written with the previous key. */
- iPtr = (pCsr->pPrevMergePtr ? *pCsr->pPrevMergePtr : 0);
- if( pCsr->pBtCsr ){
- BtreeCursor *pBtCsr = pCsr->pBtCsr;
- if( pBtCsr->pKey ){
- int res = rtTopic(pBtCsr->eType) - rtTopic(eType);
- if( res==0 ) res = pDb->xCmp(pBtCsr->pKey, pBtCsr->nKey, pKey, nKey);
- if( 0==res ) iPtr = pBtCsr->iPtr;
- assert( res>=0 );
- }
- }else if( pCsr->nPtr ){
- SegmentPtr *pPtr = &pCsr->aPtr[pCsr->nPtr-1];
- if( pPtr->pPg
- && 0==pDb->xCmp(pPtr->pKey, pPtr->nKey, pKey, nKey)
- ){
- iPtr = pPtr->iPtr+pPtr->iPgPtr;
- }
- }
-
- iVal = pCsr->aTree[1];
- mergeRangeDeletes(pCsr, &iVal, &eType);
-
- if( eType!=0 ){
- if( pMW->aGobble ){
- int iGobble = pCsr->aTree[1] - CURSOR_DATA_SEGMENT;
- if( iGobble<pCsr->nPtr && iGobble>=0 ){
- SegmentPtr *pGobble = &pCsr->aPtr[iGobble];
- if( (pGobble->flags & PGFTR_SKIP_THIS_FLAG)==0 ){
- pMW->aGobble[iGobble] = lsmFsPageNumber(pGobble->pPg);
- }
- }
- }
-
- /* If this is a separator key and we know that the output pointer has not
- ** changed, there is no point in writing an output record. Otherwise,
- ** proceed. */
- if( rc==LSM_OK && (rtIsSeparator(eType)==0 || iPtr!=0) ){
- /* Write the record into the main run. */
- void *pVal; int nVal;
- rc = multiCursorGetVal(pCsr, iVal, &pVal, &nVal);
- if( pVal && rc==LSM_OK ){
- assert( nVal>=0 );
- rc = sortedBlobSet(pDb->pEnv, &pCsr->val, pVal, nVal);
- pVal = pCsr->val.pData;
- }
- if( rc==LSM_OK ){
- rc = mergeWorkerWrite(pMW, eType, pKey, nKey, pVal, nVal, (int)iPtr);
- }
- }
- }
-
- /* Advance the cursor to the next input record (assuming one exists). */
- assert( lsmMCursorValid(pMW->pCsr) );
- if( rc==LSM_OK ) rc = lsmMCursorNext(pMW->pCsr);
-
- return rc;
-}
-
-static int mergeWorkerDone(MergeWorker *pMW){
- return pMW->pCsr==0 || !lsmMCursorValid(pMW->pCsr);
-}
-
-static void sortedFreeLevel(lsm_env *pEnv, Level *p){
- if( p ){
- lsmFree(pEnv, p->pSplitKey);
- lsmFree(pEnv, p->pMerge);
- lsmFree(pEnv, p->aRhs);
- lsmFree(pEnv, p);
- }
-}
-
-static void sortedInvokeWorkHook(lsm_db *pDb){
- if( pDb->xWork ){
- pDb->xWork(pDb, pDb->pWorkCtx);
- }
-}
-
-static int sortedNewToplevel(
- lsm_db *pDb, /* Connection handle */
- int eTree, /* One of the TREE_XXX constants */
- int *pnWrite /* OUT: Number of database pages written */
-){
- int rc = LSM_OK; /* Return Code */
- MultiCursor *pCsr = 0;
- Level *pNext = 0; /* The current top level */
- Level *pNew; /* The new level itself */
- Segment *pLinked = 0; /* Delete separators from this segment */
- Level *pDel = 0; /* Delete this entire level */
- int nWrite = 0; /* Number of database pages written */
- Freelist freelist;
-
- if( eTree!=TREE_NONE ){
- rc = lsmShmCacheChunks(pDb, pDb->treehdr.nChunk);
- }
-
- assert( pDb->bUseFreelist==0 );
- pDb->pFreelist = &freelist;
- pDb->bUseFreelist = 1;
- memset(&freelist, 0, sizeof(freelist));
-
- /* Allocate the new level structure to write to. */
- pNext = lsmDbSnapshotLevel(pDb->pWorker);
- pNew = (Level *)lsmMallocZeroRc(pDb->pEnv, sizeof(Level), &rc);
- if( pNew ){
- pNew->pNext = pNext;
- lsmDbSnapshotSetLevel(pDb->pWorker, pNew);
- }
-
- /* Create a cursor to gather the data required by the new segment. The new
- ** segment contains everything in the tree and pointers to the next segment
- ** in the database (if any). */
- pCsr = multiCursorNew(pDb, &rc);
- if( pCsr ){
- pCsr->pDb = pDb;
- rc = multiCursorVisitFreelist(pCsr);
- if( rc==LSM_OK ){
- rc = multiCursorAddTree(pCsr, pDb->pWorker, eTree);
- }
- if( rc==LSM_OK && pNext && pNext->pMerge==0 ){
- if( (pNext->flags & LEVEL_FREELIST_ONLY) ){
- pDel = pNext;
- pCsr->aPtr = lsmMallocZeroRc(pDb->pEnv, sizeof(SegmentPtr), &rc);
- multiCursorAddOne(pCsr, pNext, &rc);
- }else if( eTree!=TREE_NONE && pNext->lhs.iRoot ){
- pLinked = &pNext->lhs;
- rc = btreeCursorNew(pDb, pLinked, &pCsr->pBtCsr);
- }
- }
-
- /* If this will be the only segment in the database, discard any delete
- ** markers present in the in-memory tree. */
- if( pNext==0 ){
- multiCursorIgnoreDelete(pCsr);
- }
- }
-
- if( rc!=LSM_OK ){
- lsmMCursorClose(pCsr, 0);
- }else{
- LsmPgno iLeftPtr = 0;
- Merge merge; /* Merge object used to create new level */
- MergeWorker mergeworker; /* MergeWorker object for the same purpose */
-
- memset(&merge, 0, sizeof(Merge));
- memset(&mergeworker, 0, sizeof(MergeWorker));
-
- pNew->pMerge = &merge;
- pNew->flags |= LEVEL_INCOMPLETE;
- mergeworker.pDb = pDb;
- mergeworker.pLevel = pNew;
- mergeworker.pCsr = pCsr;
- pCsr->pPrevMergePtr = &iLeftPtr;
-
- /* Mark the separators array for the new level as a "phantom". */
- mergeworker.bFlush = 1;
-
- /* Do the work to create the new merged segment on disk */
- if( rc==LSM_OK ) rc = lsmMCursorFirst(pCsr);
- while( rc==LSM_OK && mergeWorkerDone(&mergeworker)==0 ){
- rc = mergeWorkerStep(&mergeworker);
- }
- mergeWorkerShutdown(&mergeworker, &rc);
- assert( rc!=LSM_OK || mergeworker.nWork==0 || pNew->lhs.iFirst );
- if( rc==LSM_OK && pNew->lhs.iFirst ){
- rc = lsmFsSortedFinish(pDb->pFS, &pNew->lhs);
- }
- nWrite = mergeworker.nWork;
- pNew->flags &= ~LEVEL_INCOMPLETE;
- if( eTree==TREE_NONE ){
- pNew->flags |= LEVEL_FREELIST_ONLY;
- }
- pNew->pMerge = 0;
- }
-
- if( rc!=LSM_OK || pNew->lhs.iFirst==0 ){
- assert( rc!=LSM_OK || pDb->pWorker->freelist.nEntry==0 );
- lsmDbSnapshotSetLevel(pDb->pWorker, pNext);
- sortedFreeLevel(pDb->pEnv, pNew);
- }else{
- if( pLinked ){
- pLinked->iRoot = 0;
- }else if( pDel ){
- assert( pNew->pNext==pDel );
- pNew->pNext = pDel->pNext;
- lsmFsSortedDelete(pDb->pFS, pDb->pWorker, 1, &pDel->lhs);
- sortedFreeLevel(pDb->pEnv, pDel);
- }
-
-#if LSM_LOG_STRUCTURE
- lsmSortedDumpStructure(pDb, pDb->pWorker, LSM_LOG_DATA, 0, "new-toplevel");
-#endif
-
- if( freelist.nEntry ){
- Freelist *p = &pDb->pWorker->freelist;
- lsmFree(pDb->pEnv, p->aEntry);
- memcpy(p, &freelist, sizeof(freelist));
- freelist.aEntry = 0;
- }else{
- pDb->pWorker->freelist.nEntry = 0;
- }
-
- assertBtreeOk(pDb, &pNew->lhs);
- sortedInvokeWorkHook(pDb);
- }
-
- if( pnWrite ) *pnWrite = nWrite;
- pDb->pWorker->nWrite += nWrite;
- pDb->pFreelist = 0;
- pDb->bUseFreelist = 0;
- lsmFree(pDb->pEnv, freelist.aEntry);
- return rc;
-}
-
-/*
-** The nMerge levels in the LSM beginning with pLevel consist of a
-** left-hand-side segment only. Replace these levels with a single new
-** level consisting of a new empty segment on the left-hand-side and the
-** nMerge segments from the replaced levels on the right-hand-side.
-**
-** Also, allocate and populate a Merge object and set Level.pMerge to
-** point to it.
-*/
-static int sortedMergeSetup(
- lsm_db *pDb, /* Database handle */
- Level *pLevel, /* First level to merge */
- int nMerge, /* Merge this many levels together */
- Level **ppNew /* New, merged, level */
-){
- int rc = LSM_OK; /* Return Code */
- Level *pNew; /* New Level object */
- int bUseNext = 0; /* True to link in next separators */
- Merge *pMerge; /* New Merge object */
- int nByte; /* Bytes of space allocated at pMerge */
-
-#ifdef LSM_DEBUG
- int iLevel;
- Level *pX = pLevel;
- for(iLevel=0; iLevel<nMerge; iLevel++){
- assert( pX->nRight==0 );
- pX = pX->pNext;
- }
-#endif
-
- /* Allocate the new Level object */
- pNew = (Level *)lsmMallocZeroRc(pDb->pEnv, sizeof(Level), &rc);
- if( pNew ){
- pNew->aRhs = (Segment *)lsmMallocZeroRc(pDb->pEnv,
- nMerge * sizeof(Segment), &rc);
- }
-
- /* Populate the new Level object */
- if( rc==LSM_OK ){
- Level *pNext = 0; /* Level following pNew */
- int i;
- int bFreeOnly = 1;
- Level *pTopLevel;
- Level *p = pLevel;
- Level **pp;
- pNew->nRight = nMerge;
- pNew->iAge = pLevel->iAge+1;
- for(i=0; i<nMerge; i++){
- assert( p->nRight==0 );
- pNext = p->pNext;
- pNew->aRhs[i] = p->lhs;
- if( (p->flags & LEVEL_FREELIST_ONLY)==0 ) bFreeOnly = 0;
- sortedFreeLevel(pDb->pEnv, p);
- p = pNext;
- }
-
- if( bFreeOnly ) pNew->flags |= LEVEL_FREELIST_ONLY;
-
- /* Replace the old levels with the new. */
- pTopLevel = lsmDbSnapshotLevel(pDb->pWorker);
- pNew->pNext = p;
- for(pp=&pTopLevel; *pp!=pLevel; pp=&((*pp)->pNext));
- *pp = pNew;
- lsmDbSnapshotSetLevel(pDb->pWorker, pTopLevel);
-
- /* Determine whether or not the next separators will be linked in */
- if( pNext && pNext->pMerge==0 && pNext->lhs.iRoot && pNext
- && (bFreeOnly==0 || (pNext->flags & LEVEL_FREELIST_ONLY))
- ){
- bUseNext = 1;
- }
- }
-
- /* Allocate the merge object */
- nByte = sizeof(Merge) + sizeof(MergeInput) * (nMerge + bUseNext);
- pMerge = (Merge *)lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
- if( pMerge ){
- pMerge->aInput = (MergeInput *)&pMerge[1];
- pMerge->nInput = nMerge + bUseNext;
- pNew->pMerge = pMerge;
- }
-
- *ppNew = pNew;
- return rc;
-}
-
-static int mergeWorkerInit(
- lsm_db *pDb, /* Db connection to do merge work */
- Level *pLevel, /* Level to work on merging */
- MergeWorker *pMW /* Object to initialize */
-){
- int rc = LSM_OK; /* Return code */
- Merge *pMerge = pLevel->pMerge; /* Persistent part of merge state */
- MultiCursor *pCsr = 0; /* Cursor opened for pMW */
- Level *pNext = pLevel->pNext; /* Next level in LSM */
-
- assert( pDb->pWorker );
- assert( pLevel->pMerge );
- assert( pLevel->nRight>0 );
-
- memset(pMW, 0, sizeof(MergeWorker));
- pMW->pDb = pDb;
- pMW->pLevel = pLevel;
- pMW->aGobble = lsmMallocZeroRc(pDb->pEnv, sizeof(LsmPgno)*pLevel->nRight,&rc);
-
- /* Create a multi-cursor to read the data to write to the new
- ** segment. The new segment contains:
- **
- ** 1. Records from LHS of each of the nMerge levels being merged.
- ** 2. Separators from either the last level being merged, or the
- ** separators attached to the LHS of the following level, or neither.
- **
- ** If the new level is the lowest (oldest) in the db, discard any
- ** delete keys. Key annihilation.
- */
- pCsr = multiCursorNew(pDb, &rc);
- if( pCsr ){
- pCsr->flags |= CURSOR_NEXT_OK;
- rc = multiCursorAddRhs(pCsr, pLevel);
- }
- if( rc==LSM_OK && pMerge->nInput > pLevel->nRight ){
- rc = btreeCursorNew(pDb, &pNext->lhs, &pCsr->pBtCsr);
- }else if( pNext ){
- multiCursorReadSeparators(pCsr);
- }else{
- multiCursorIgnoreDelete(pCsr);
- }
-
- assert( rc!=LSM_OK || pMerge->nInput==(pCsr->nPtr+(pCsr->pBtCsr!=0)) );
- pMW->pCsr = pCsr;
-
- /* Load the b-tree hierarchy into memory. */
- if( rc==LSM_OK ) rc = mergeWorkerLoadHierarchy(pMW);
- if( rc==LSM_OK && pMW->hier.nHier==0 ){
- pMW->aSave[0].iPgno = pLevel->lhs.iFirst;
- }
-
- /* Position the cursor. */
- if( rc==LSM_OK ){
- pCsr->pPrevMergePtr = &pMerge->iCurrentPtr;
- if( pLevel->lhs.iFirst==0 ){
- /* The output array is still empty. So position the cursor at the very
- ** start of the input. */
- rc = multiCursorEnd(pCsr, 0);
- }else{
- /* The output array is non-empty. Position the cursor based on the
- ** page/cell data saved in the Merge.aInput[] array. */
- int i;
- for(i=0; rc==LSM_OK && i<pCsr->nPtr; i++){
- MergeInput *pInput = &pMerge->aInput[i];
- if( pInput->iPg ){
- SegmentPtr *pPtr;
- assert( pCsr->aPtr[i].pPg==0 );
- pPtr = &pCsr->aPtr[i];
- rc = segmentPtrLoadPage(pDb->pFS, pPtr, (int)pInput->iPg);
- if( rc==LSM_OK && pPtr->nCell>0 ){
- rc = segmentPtrLoadCell(pPtr, pInput->iCell);
- }
- }
- }
-
- if( rc==LSM_OK && pCsr->pBtCsr ){
- int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
- assert( i==pCsr->nPtr );
- rc = btreeCursorRestore(pCsr->pBtCsr, xCmp, &pMerge->aInput[i]);
- }
-
- if( rc==LSM_OK ){
- rc = multiCursorSetupTree(pCsr, 0);
- }
- }
- pCsr->flags |= CURSOR_NEXT_OK;
- }
-
- return rc;
-}
-
-static int sortedBtreeGobble(
- lsm_db *pDb, /* Worker connection */
- MultiCursor *pCsr, /* Multi-cursor being used for a merge */
- int iGobble /* pCsr->aPtr[] entry to operate on */
-){
- int rc = LSM_OK;
- if( rtTopic(pCsr->eType)==0 ){
- Segment *pSeg = pCsr->aPtr[iGobble].pSeg;
- LsmPgno *aPg;
- int nPg;
-
- /* Seek from the root of the b-tree to the segment leaf that may contain
- ** a key equal to the one multi-cursor currently points to. Record the
- ** page number of each b-tree page and the leaf. The segment may be
- ** gobbled up to (but not including) the first of these page numbers.
- */
- assert( pSeg->iRoot>0 );
- aPg = lsmMallocZeroRc(pDb->pEnv, sizeof(LsmPgno)*32, &rc);
- if( rc==LSM_OK ){
- rc = seekInBtree(pCsr, pSeg,
- rtTopic(pCsr->eType), pCsr->key.pData, pCsr->key.nData, aPg, 0
- );
- }
-
- if( rc==LSM_OK ){
- for(nPg=0; aPg[nPg]; nPg++);
- lsmFsGobble(pDb, pSeg, aPg, nPg);
- }
-
- lsmFree(pDb->pEnv, aPg);
- }
- return rc;
-}
-
-/*
-** Argument p points to a level of age N. Return the number of levels in
-** the linked list starting at p that have age=N (always at least 1).
-*/
-static int sortedCountLevels(Level *p){
- int iAge = p->iAge;
- int nRet = 0;
- do {
- nRet++;
- p = p->pNext;
- }while( p && p->iAge==iAge );
- return nRet;
-}
-
-static int sortedSelectLevel(lsm_db *pDb, int nMerge, Level **ppOut){
- Level *pTopLevel = lsmDbSnapshotLevel(pDb->pWorker);
- int rc = LSM_OK;
- Level *pLevel = 0; /* Output value */
- Level *pBest = 0; /* Best level to work on found so far */
- int nBest; /* Number of segments merged at pBest */
- Level *pThis = 0; /* First in run of levels with age=iAge */
- int nThis = 0; /* Number of levels starting at pThis */
-
- assert( nMerge>=1 );
- nBest = LSM_MAX(1, nMerge-1);
-
- /* Find the longest contiguous run of levels not currently undergoing a
- ** merge with the same age in the structure. Or the level being merged
- ** with the largest number of right-hand segments. Work on it. */
- for(pLevel=pTopLevel; pLevel; pLevel=pLevel->pNext){
- if( pLevel->nRight==0 && pThis && pLevel->iAge==pThis->iAge ){
- nThis++;
- }else{
- if( nThis>nBest ){
- if( (pLevel->iAge!=pThis->iAge+1)
- || (pLevel->nRight==0 && sortedCountLevels(pLevel)<=pDb->nMerge)
- ){
- pBest = pThis;
- nBest = nThis;
- }
- }
- if( pLevel->nRight ){
- if( pLevel->nRight>nBest ){
- nBest = pLevel->nRight;
- pBest = pLevel;
- }
- nThis = 0;
- pThis = 0;
- }else{
- pThis = pLevel;
- nThis = 1;
- }
- }
- }
- if( nThis>nBest ){
- assert( pThis );
- pBest = pThis;
- nBest = nThis;
- }
-
- if( pBest==0 && nMerge==1 ){
- int nFree = 0;
- int nUsr = 0;
- for(pLevel=pTopLevel; pLevel; pLevel=pLevel->pNext){
- assert( !pLevel->nRight );
- if( pLevel->flags & LEVEL_FREELIST_ONLY ){
- nFree++;
- }else{
- nUsr++;
- }
- }
- if( nUsr>1 ){
- pBest = pTopLevel;
- nBest = nFree + nUsr;
- }
- }
-
- if( pBest ){
- if( pBest->nRight==0 ){
- rc = sortedMergeSetup(pDb, pBest, nBest, ppOut);
- }else{
- *ppOut = pBest;
- }
- }
-
- return rc;
-}
-
-static int sortedDbIsFull(lsm_db *pDb){
- Level *pTop = lsmDbSnapshotLevel(pDb->pWorker);
-
- if( lsmDatabaseFull(pDb) ) return 1;
- if( pTop && pTop->iAge==0
- && (pTop->nRight || sortedCountLevels(pTop)>=pDb->nMerge)
- ){
- return 1;
- }
- return 0;
-}
-
-typedef struct MoveBlockCtx MoveBlockCtx;
-struct MoveBlockCtx {
- int iSeen; /* Previous free block on list */
- int iFrom; /* Total number of blocks in file */
-};
-
-static int moveBlockCb(void *pCtx, int iBlk, i64 iSnapshot){
- MoveBlockCtx *p = (MoveBlockCtx *)pCtx;
- assert( p->iFrom==0 );
- if( iBlk==(p->iSeen-1) ){
- p->iSeen = iBlk;
- return 0;
- }
- p->iFrom = p->iSeen-1;
- return 1;
-}
-
-/*
-** This function is called to further compact a database for which all
-** of the content has already been merged into a single segment. If
-** possible, it moves the contents of a single block from the end of the
-** file to a free-block that lies closer to the start of the file (allowing
-** the file to be eventually truncated).
-*/
-static int sortedMoveBlock(lsm_db *pDb, int *pnWrite){
- Snapshot *p = pDb->pWorker;
- Level *pLvl = lsmDbSnapshotLevel(p);
- int iFrom; /* Block to move */
- int iTo; /* Destination to move block to */
- int rc; /* Return code */
-
- MoveBlockCtx sCtx;
-
- assert( pLvl->pNext==0 && pLvl->nRight==0 );
- assert( p->redirect.n<=LSM_MAX_BLOCK_REDIRECTS );
-
- *pnWrite = 0;
-
- /* Check that the redirect array is not already full. If it is, return
- ** without moving any database content. */
- if( p->redirect.n>=LSM_MAX_BLOCK_REDIRECTS ) return LSM_OK;
-
- /* Find the last block of content in the database file. Do this by
- ** traversing the free-list in reverse (descending block number) order.
- ** The first block not on the free list is the one that will be moved.
- ** Since the db consists of a single segment, there is no ambiguity as
- ** to which segment the block belongs to. */
- sCtx.iSeen = p->nBlock+1;
- sCtx.iFrom = 0;
- rc = lsmWalkFreelist(pDb, 1, moveBlockCb, &sCtx);
- if( rc!=LSM_OK || sCtx.iFrom==0 ) return rc;
- iFrom = sCtx.iFrom;
-
- /* Find the first free block in the database, ignoring block 1. Block
- ** 1 is tricky as it is smaller than the other blocks. */
- rc = lsmBlockAllocate(pDb, iFrom, &iTo);
- if( rc!=LSM_OK || iTo==0 ) return rc;
- assert( iTo!=1 && iTo<iFrom );
-
- rc = lsmFsMoveBlock(pDb->pFS, &pLvl->lhs, iTo, iFrom);
- if( rc==LSM_OK ){
- if( p->redirect.a==0 ){
- int nByte = sizeof(struct RedirectEntry) * LSM_MAX_BLOCK_REDIRECTS;
- p->redirect.a = lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
- }
- if( rc==LSM_OK ){
-
- /* Check if the block just moved was already redirected. */
- int i;
- for(i=0; i<p->redirect.n; i++){
- if( p->redirect.a[i].iTo==iFrom ) break;
- }
-
- if( i==p->redirect.n ){
- /* Block iFrom was not already redirected. Add a new array entry. */
- memmove(&p->redirect.a[1], &p->redirect.a[0],
- sizeof(struct RedirectEntry) * p->redirect.n
- );
- p->redirect.a[0].iFrom = iFrom;
- p->redirect.a[0].iTo = iTo;
- p->redirect.n++;
- }else{
- /* Block iFrom was already redirected. Overwrite existing entry. */
- p->redirect.a[i].iTo = iTo;
- }
-
- rc = lsmBlockFree(pDb, iFrom);
-
- *pnWrite = lsmFsBlockSize(pDb->pFS) / lsmFsPageSize(pDb->pFS);
- pLvl->lhs.pRedirect = &p->redirect;
- }
- }
-
-#if LSM_LOG_STRUCTURE
- if( rc==LSM_OK ){
- char aBuf[64];
- sprintf(aBuf, "move-block %d/%d", p->redirect.n-1, LSM_MAX_BLOCK_REDIRECTS);
- lsmSortedDumpStructure(pDb, pDb->pWorker, LSM_LOG_DATA, 0, aBuf);
- }
-#endif
- return rc;
-}
-
-/*
-*/
-static int mergeInsertFreelistSegments(
- lsm_db *pDb,
- int nFree,
- MergeWorker *pMW
-){
- int rc = LSM_OK;
- if( nFree>0 ){
- MultiCursor *pCsr = pMW->pCsr;
- Level *pLvl = pMW->pLevel;
- SegmentPtr *aNew1;
- Segment *aNew2;
-
- Level *pIter;
- Level *pNext;
- int i = 0;
-
- aNew1 = (SegmentPtr *)lsmMallocZeroRc(
- pDb->pEnv, sizeof(SegmentPtr) * (pCsr->nPtr+nFree), &rc
- );
- if( rc ) return rc;
- memcpy(&aNew1[nFree], pCsr->aPtr, sizeof(SegmentPtr)*pCsr->nPtr);
- pCsr->nPtr += nFree;
- lsmFree(pDb->pEnv, pCsr->aTree);
- lsmFree(pDb->pEnv, pCsr->aPtr);
- pCsr->aTree = 0;
- pCsr->aPtr = aNew1;
-
- aNew2 = (Segment *)lsmMallocZeroRc(
- pDb->pEnv, sizeof(Segment) * (pLvl->nRight+nFree), &rc
- );
- if( rc ) return rc;
- memcpy(&aNew2[nFree], pLvl->aRhs, sizeof(Segment)*pLvl->nRight);
- pLvl->nRight += nFree;
- lsmFree(pDb->pEnv, pLvl->aRhs);
- pLvl->aRhs = aNew2;
-
- for(pIter=pDb->pWorker->pLevel; rc==LSM_OK && pIter!=pLvl; pIter=pNext){
- Segment *pSeg = &pLvl->aRhs[i];
- memcpy(pSeg, &pIter->lhs, sizeof(Segment));
-
- pCsr->aPtr[i].pSeg = pSeg;
- pCsr->aPtr[i].pLevel = pLvl;
- rc = segmentPtrEnd(pCsr, &pCsr->aPtr[i], 0);
-
- pDb->pWorker->pLevel = pNext = pIter->pNext;
- sortedFreeLevel(pDb->pEnv, pIter);
- i++;
- }
- assert( i==nFree );
- assert( rc!=LSM_OK || pDb->pWorker->pLevel==pLvl );
-
- for(i=nFree; i<pCsr->nPtr; i++){
- pCsr->aPtr[i].pSeg = &pLvl->aRhs[i];
- }
-
- lsmFree(pDb->pEnv, pMW->aGobble);
- pMW->aGobble = 0;
- }
- return rc;
-}
-
-static int sortedWork(
- lsm_db *pDb, /* Database handle. Must be worker. */
- int nWork, /* Number of pages of work to do */
- int nMerge, /* Try to merge this many levels at once */
- int bFlush, /* Set if call is to make room for a flush */
- int *pnWrite /* OUT: Actual number of pages written */
-){
- int rc = LSM_OK; /* Return Code */
- int nRemaining = nWork; /* Units of work to do before returning */
- Snapshot *pWorker = pDb->pWorker;
-
- assert( pWorker );
- if( lsmDbSnapshotLevel(pWorker)==0 ) return LSM_OK;
-
- while( nRemaining>0 ){
- Level *pLevel = 0;
-
- /* Find a level to work on. */
- rc = sortedSelectLevel(pDb, nMerge, &pLevel);
- assert( rc==LSM_OK || pLevel==0 );
-
- if( pLevel==0 ){
- int nDone = 0;
- Level *pTopLevel = lsmDbSnapshotLevel(pDb->pWorker);
- if( bFlush==0 && nMerge==1 && pTopLevel && pTopLevel->pNext==0 ){
- rc = sortedMoveBlock(pDb, &nDone);
- }
- nRemaining -= nDone;
-
- /* Could not find any work to do. Finished. */
- if( nDone==0 ) break;
- }else{
- int bSave = 0;
- Freelist freelist = {0, 0, 0};
- MergeWorker mergeworker; /* State used to work on the level merge */
-
- assert( pDb->bIncrMerge==0 );
- assert( pDb->pFreelist==0 && pDb->bUseFreelist==0 );
-
- pDb->bIncrMerge = 1;
- rc = mergeWorkerInit(pDb, pLevel, &mergeworker);
- assert( mergeworker.nWork==0 );
-
- while( rc==LSM_OK
- && 0==mergeWorkerDone(&mergeworker)
- && (mergeworker.nWork<nRemaining || pDb->bUseFreelist)
- ){
- int eType = rtTopic(mergeworker.pCsr->eType);
- rc = mergeWorkerStep(&mergeworker);
-
- /* If the cursor now points at the first entry past the end of the
- ** user data (i.e. either to EOF or to the first free-list entry
- ** that will be added to the run), then check if it is possible to
- ** merge in any free-list entries that are either in-memory or in
- ** free-list-only blocks. */
- if( rc==LSM_OK && nMerge==1 && eType==0
- && (rtTopic(mergeworker.pCsr->eType) || mergeWorkerDone(&mergeworker))
- ){
- int nFree = 0; /* Number of free-list-only levels to merge */
- Level *pLvl;
- assert( pDb->pFreelist==0 && pDb->bUseFreelist==0 );
-
- /* Now check if all levels containing data newer than this one
- ** are single-segment free-list only levels. If so, they will be
- ** merged in now. */
- for(pLvl=pDb->pWorker->pLevel;
- pLvl!=mergeworker.pLevel && (pLvl->flags & LEVEL_FREELIST_ONLY);
- pLvl=pLvl->pNext
- ){
- assert( pLvl->nRight==0 );
- nFree++;
- }
- if( pLvl==mergeworker.pLevel ){
-
- rc = mergeInsertFreelistSegments(pDb, nFree, &mergeworker);
- if( rc==LSM_OK ){
- rc = multiCursorVisitFreelist(mergeworker.pCsr);
- }
- if( rc==LSM_OK ){
- rc = multiCursorSetupTree(mergeworker.pCsr, 0);
- pDb->pFreelist = &freelist;
- pDb->bUseFreelist = 1;
- }
- }
- }
- }
- nRemaining -= LSM_MAX(mergeworker.nWork, 1);
-
- if( rc==LSM_OK ){
- /* Check if the merge operation is completely finished. If not,
- ** gobble up (declare eligible for recycling) any pages from rhs
- ** segments for which the content has been completely merged into
- ** the lhs of the level. */
- if( mergeWorkerDone(&mergeworker)==0 ){
- int i;
- for(i=0; i<pLevel->nRight; i++){
- SegmentPtr *pGobble = &mergeworker.pCsr->aPtr[i];
- if( pGobble->pSeg->iRoot ){
- rc = sortedBtreeGobble(pDb, mergeworker.pCsr, i);
- }else if( mergeworker.aGobble[i] ){
- lsmFsGobble(pDb, pGobble->pSeg, &mergeworker.aGobble[i], 1);
- }
- }
- }else{
- int i;
- int bEmpty;
- mergeWorkerShutdown(&mergeworker, &rc);
- bEmpty = (pLevel->lhs.iFirst==0);
-
- if( bEmpty==0 && rc==LSM_OK ){
- rc = lsmFsSortedFinish(pDb->pFS, &pLevel->lhs);
- }
-
- if( pDb->bUseFreelist ){
- Freelist *p = &pDb->pWorker->freelist;
- lsmFree(pDb->pEnv, p->aEntry);
- memcpy(p, &freelist, sizeof(freelist));
- pDb->bUseFreelist = 0;
- pDb->pFreelist = 0;
- bSave = 1;
- }
-
- for(i=0; i<pLevel->nRight; i++){
- lsmFsSortedDelete(pDb->pFS, pWorker, 1, &pLevel->aRhs[i]);
- }
-
- if( bEmpty ){
- /* If the new level is completely empty, remove it from the
- ** database snapshot. This can only happen if all input keys were
- ** annihilated. Since keys are only annihilated if the new level
- ** is the last in the linked list (contains the most ancient of
- ** database content), this guarantees that pLevel->pNext==0. */
- Level *pTop; /* Top level of worker snapshot */
- Level **pp; /* Read/write iterator for Level.pNext list */
-
- assert( pLevel->pNext==0 );
-
- /* Remove the level from the worker snapshot. */
- pTop = lsmDbSnapshotLevel(pWorker);
- for(pp=&pTop; *pp!=pLevel; pp=&((*pp)->pNext));
- *pp = pLevel->pNext;
- lsmDbSnapshotSetLevel(pWorker, pTop);
-
- /* Free the Level structure. */
- sortedFreeLevel(pDb->pEnv, pLevel);
- }else{
-
- /* Free the separators of the next level, if required. */
- if( pLevel->pMerge->nInput > pLevel->nRight ){
- assert( pLevel->pNext->lhs.iRoot );
- pLevel->pNext->lhs.iRoot = 0;
- }
-
- /* Zero the right-hand-side of pLevel */
- lsmFree(pDb->pEnv, pLevel->aRhs);
- pLevel->nRight = 0;
- pLevel->aRhs = 0;
-
- /* Free the Merge object */
- lsmFree(pDb->pEnv, pLevel->pMerge);
- pLevel->pMerge = 0;
- }
-
- if( bSave && rc==LSM_OK ){
- pDb->bIncrMerge = 0;
- rc = lsmSaveWorker(pDb, 0);
- }
- }
- }
-
- /* Clean up the MergeWorker object initialized above. If no error
- ** has occurred, invoke the work-hook to inform the application that
- ** the database structure has changed. */
- mergeWorkerShutdown(&mergeworker, &rc);
- pDb->bIncrMerge = 0;
- if( rc==LSM_OK ) sortedInvokeWorkHook(pDb);
-
-#if LSM_LOG_STRUCTURE
- lsmSortedDumpStructure(pDb, pDb->pWorker, LSM_LOG_DATA, 0, "work");
-#endif
- assertBtreeOk(pDb, &pLevel->lhs);
- assertRunInOrder(pDb, &pLevel->lhs);
-
- /* If bFlush is true and the database is no longer considered "full",
- ** break out of the loop even if nRemaining is still greater than
- ** zero. The caller has an in-memory tree to flush to disk. */
- if( bFlush && sortedDbIsFull(pDb)==0 ) break;
- }
- }
-
- if( pnWrite ) *pnWrite = (nWork - nRemaining);
- pWorker->nWrite += (nWork - nRemaining);
-
-#ifdef LSM_LOG_WORK
- lsmLogMessage(pDb, rc, "sortedWork(): %d pages", (nWork-nRemaining));
-#endif
- return rc;
-}
-
-/*
-** The database connection passed as the first argument must be a worker
-** connection. This function checks if there exists an "old" in-memory tree
-** ready to be flushed to disk. If so, true is returned. Otherwise false.
-**
-** If an error occurs, *pRc is set to an LSM error code before returning.
-** It is assumed that *pRc is set to LSM_OK when this function is called.
-*/
-static int sortedTreeHasOld(lsm_db *pDb, int *pRc){
- int rc = LSM_OK;
- int bRet = 0;
-
- assert( pDb->pWorker );
- if( *pRc==LSM_OK ){
- if( rc==LSM_OK
- && pDb->treehdr.iOldShmid
- && pDb->treehdr.iOldLog!=pDb->pWorker->iLogOff
- ){
- bRet = 1;
- }else{
- bRet = 0;
- }
- *pRc = rc;
- }
- assert( *pRc==LSM_OK || bRet==0 );
- return bRet;
-}
-
-/*
-** Create a new free-list only top-level segment. Return LSM_OK if successful
-** or an LSM error code if some error occurs.
-*/
-static int sortedNewFreelistOnly(lsm_db *pDb){
- return sortedNewToplevel(pDb, TREE_NONE, 0);
-}
-
-int lsmSaveWorker(lsm_db *pDb, int bFlush){
- Snapshot *p = pDb->pWorker;
- if( p->freelist.nEntry>pDb->nMaxFreelist ){
- int rc = sortedNewFreelistOnly(pDb);
- if( rc!=LSM_OK ) return rc;
- }
- return lsmCheckpointSaveWorker(pDb, bFlush);
-}
-
-static int doLsmSingleWork(
- lsm_db *pDb,
- int bShutdown,
- int nMerge, /* Minimum segments to merge together */
- int nPage, /* Number of pages to write to disk */
- int *pnWrite, /* OUT: Pages actually written to disk */
- int *pbCkpt /* OUT: True if an auto-checkpoint is req. */
-){
- Snapshot *pWorker; /* Worker snapshot */
- int rc = LSM_OK; /* Return code */
- int bDirty = 0;
- int nMax = nPage; /* Maximum pages to write to disk */
- int nRem = nPage;
- int bCkpt = 0;
-
- assert( nPage>0 );
-
- /* Open the worker 'transaction'. It will be closed before this function
- ** returns. */
- assert( pDb->pWorker==0 );
- rc = lsmBeginWork(pDb);
- if( rc!=LSM_OK ) return rc;
- pWorker = pDb->pWorker;
-
- /* If this connection is doing auto-checkpoints, set nMax (and nRem) so
- ** that this call stops writing when the auto-checkpoint is due. The
- ** caller will do the checkpoint, then possibly call this function again. */
- if( bShutdown==0 && pDb->nAutockpt ){
- u32 nSync;
- u32 nUnsync;
- int nPgsz;
-
- lsmCheckpointSynced(pDb, 0, 0, &nSync);
- nUnsync = lsmCheckpointNWrite(pDb->pShmhdr->aSnap1, 0);
- nPgsz = lsmCheckpointPgsz(pDb->pShmhdr->aSnap1);
-
- nMax = (int)LSM_MIN(nMax, (pDb->nAutockpt/nPgsz) - (int)(nUnsync-nSync));
- if( nMax<nRem ){
- bCkpt = 1;
- nRem = LSM_MAX(nMax, 0);
- }
- }
-
- /* If there exists in-memory data ready to be flushed to disk, attempt
- ** to flush it now. */
- if( pDb->nTransOpen==0 ){
- rc = lsmTreeLoadHeader(pDb, 0);
- }
- if( sortedTreeHasOld(pDb, &rc) ){
- /* sortedDbIsFull() returns non-zero if either (a) there are too many
- ** levels in total in the db, or (b) there are too many levels with the
- ** the same age in the db. Either way, call sortedWork() to merge
- ** existing segments together until this condition is cleared. */
- if( sortedDbIsFull(pDb) ){
- int nPg = 0;
- rc = sortedWork(pDb, nRem, nMerge, 1, &nPg);
- nRem -= nPg;
- assert( rc!=LSM_OK || nRem<=0 || !sortedDbIsFull(pDb) );
- bDirty = 1;
- }
-
- if( rc==LSM_OK && nRem>0 ){
- int nPg = 0;
- rc = sortedNewToplevel(pDb, TREE_OLD, &nPg);
- nRem -= nPg;
- if( rc==LSM_OK ){
- if( pDb->nTransOpen>0 ){
- lsmTreeDiscardOld(pDb);
- }
- rc = lsmSaveWorker(pDb, 1);
- bDirty = 0;
- }
- }
- }
-
- /* If nPage is still greater than zero, do some merging. */
- if( rc==LSM_OK && nRem>0 && bShutdown==0 ){
- int nPg = 0;
- rc = sortedWork(pDb, nRem, nMerge, 0, &nPg);
- nRem -= nPg;
- if( nPg ) bDirty = 1;
- }
-
- /* If the in-memory part of the free-list is too large, write a new
- ** top-level containing just the in-memory free-list entries to disk. */
- if( rc==LSM_OK && pDb->pWorker->freelist.nEntry > pDb->nMaxFreelist ){
- while( rc==LSM_OK && lsmDatabaseFull(pDb) ){
- int nPg = 0;
- rc = sortedWork(pDb, 16, nMerge, 1, &nPg);
- nRem -= nPg;
- }
- if( rc==LSM_OK ){
- rc = sortedNewFreelistOnly(pDb);
- }
- bDirty = 1;
- }
-
- if( rc==LSM_OK ){
- *pnWrite = (nMax - nRem);
- *pbCkpt = (bCkpt && nRem<=0);
- if( nMerge==1 && pDb->nAutockpt>0 && *pnWrite>0
- && pWorker->pLevel
- && pWorker->pLevel->nRight==0
- && pWorker->pLevel->pNext==0
- ){
- *pbCkpt = 1;
- }
- }
-
- if( rc==LSM_OK && bDirty ){
- lsmFinishWork(pDb, 0, &rc);
- }else{
- int rcdummy = LSM_BUSY;
- lsmFinishWork(pDb, 0, &rcdummy);
- *pnWrite = 0;
- }
- assert( pDb->pWorker==0 );
- return rc;
-}
-
-static int doLsmWork(lsm_db *pDb, int nMerge, int nPage, int *pnWrite){
- int rc = LSM_OK; /* Return code */
- int nWrite = 0; /* Number of pages written */
-
- assert( nMerge>=1 );
-
- if( nPage!=0 ){
- int bCkpt = 0;
- do {
- int nThis = 0;
- int nReq = (nPage>=0) ? (nPage-nWrite) : ((int)0x7FFFFFFF);
-
- bCkpt = 0;
- rc = doLsmSingleWork(pDb, 0, nMerge, nReq, &nThis, &bCkpt);
- nWrite += nThis;
- if( rc==LSM_OK && bCkpt ){
- rc = lsm_checkpoint(pDb, 0);
- }
- }while( rc==LSM_OK && bCkpt && (nWrite<nPage || nPage<0) );
- }
-
- if( pnWrite ){
- if( rc==LSM_OK ){
- *pnWrite = nWrite;
- }else{
- *pnWrite = 0;
- }
- }
- return rc;
-}
-
-/*
-** Perform work to merge database segments together.
-*/
-int lsm_work(lsm_db *pDb, int nMerge, int nKB, int *pnWrite){
- int rc; /* Return code */
- int nPgsz; /* Nominal page size in bytes */
- int nPage; /* Equivalent of nKB in pages */
- int nWrite = 0; /* Number of pages written */
-
- /* This function may not be called if pDb has an open read or write
- ** transaction. Return LSM_MISUSE if an application attempts this. */
- if( pDb->nTransOpen || pDb->pCsr ) return LSM_MISUSE_BKPT;
- if( nMerge<=0 ) nMerge = pDb->nMerge;
-
- lsmFsPurgeCache(pDb->pFS);
-
- /* Convert from KB to pages */
- nPgsz = lsmFsPageSize(pDb->pFS);
- if( nKB>=0 ){
- nPage = ((i64)nKB * 1024 + nPgsz - 1) / nPgsz;
- }else{
- nPage = -1;
- }
-
- rc = doLsmWork(pDb, nMerge, nPage, &nWrite);
-
- if( pnWrite ){
- /* Convert back from pages to KB */
- *pnWrite = (int)(((i64)nWrite * 1024 + nPgsz - 1) / nPgsz);
- }
- return rc;
-}
-
-int lsm_flush(lsm_db *db){
- int rc;
-
- if( db->nTransOpen>0 || db->pCsr ){
- rc = LSM_MISUSE_BKPT;
- }else{
- rc = lsmBeginWriteTrans(db);
- if( rc==LSM_OK ){
- lsmFlushTreeToDisk(db);
- lsmTreeDiscardOld(db);
- lsmTreeMakeOld(db);
- lsmTreeDiscardOld(db);
- }
-
- if( rc==LSM_OK ){
- rc = lsmFinishWriteTrans(db, 1);
- }else{
- lsmFinishWriteTrans(db, 0);
- }
- lsmFinishReadTrans(db);
- }
-
- return rc;
-}
-
-/*
-** This function is called in auto-work mode to perform merging work on
-** the data structure. It performs enough merging work to prevent the
-** height of the tree from growing indefinitely assuming that roughly
-** nUnit database pages worth of data have been written to the database
-** (i.e. the in-memory tree) since the last call.
-*/
-int lsmSortedAutoWork(
- lsm_db *pDb, /* Database handle */
- int nUnit /* Pages of data written to in-memory tree */
-){
- int rc = LSM_OK; /* Return code */
- int nDepth = 0; /* Current height of tree (longest path) */
- Level *pLevel; /* Used to iterate through levels */
- int bRestore = 0;
-
- assert( pDb->pWorker==0 );
- assert( pDb->nTransOpen>0 );
-
- /* Determine how many units of work to do before returning. One unit of
- ** work is achieved by writing one page (~4KB) of merged data. */
- for(pLevel=lsmDbSnapshotLevel(pDb->pClient); pLevel; pLevel=pLevel->pNext){
- /* nDepth += LSM_MAX(1, pLevel->nRight); */
- nDepth += 1;
- }
- if( lsmTreeHasOld(pDb) ){
- nDepth += 1;
- bRestore = 1;
- rc = lsmSaveCursors(pDb);
- if( rc!=LSM_OK ) return rc;
- }
-
- if( nDepth>0 ){
- int nRemaining; /* Units of work to do before returning */
-
- nRemaining = nUnit * nDepth;
-#ifdef LSM_LOG_WORK
- lsmLogMessage(pDb, rc, "lsmSortedAutoWork(): %d*%d = %d pages",
- nUnit, nDepth, nRemaining);
-#endif
- assert( nRemaining>=0 );
- rc = doLsmWork(pDb, pDb->nMerge, nRemaining, 0);
- if( rc==LSM_BUSY ) rc = LSM_OK;
-
- if( bRestore && pDb->pCsr ){
- lsmMCursorFreeCache(pDb);
- lsmFreeSnapshot(pDb->pEnv, pDb->pClient);
- pDb->pClient = 0;
- if( rc==LSM_OK ){
- rc = lsmCheckpointLoad(pDb, 0);
- }
- if( rc==LSM_OK ){
- rc = lsmCheckpointDeserialize(pDb, 0, pDb->aSnapshot, &pDb->pClient);
- }
- if( rc==LSM_OK ){
- rc = lsmRestoreCursors(pDb);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** This function is only called during system shutdown. The contents of
-** any in-memory trees present (old or current) are written out to disk.
-*/
-int lsmFlushTreeToDisk(lsm_db *pDb){
- int rc;
-
- rc = lsmBeginWork(pDb);
- while( rc==LSM_OK && sortedDbIsFull(pDb) ){
- rc = sortedWork(pDb, 256, pDb->nMerge, 1, 0);
- }
-
- if( rc==LSM_OK ){
- rc = sortedNewToplevel(pDb, TREE_BOTH, 0);
- }
-
- lsmFinishWork(pDb, 1, &rc);
- return rc;
-}
-
-/*
-** Return a string representation of the segment passed as the only argument.
-** Space for the returned string is allocated using lsmMalloc(), and should
-** be freed by the caller using lsmFree().
-*/
-static char *segToString(lsm_env *pEnv, Segment *pSeg, int nMin){
- int nSize = pSeg->nSize;
- LsmPgno iRoot = pSeg->iRoot;
- LsmPgno iFirst = pSeg->iFirst;
- LsmPgno iLast = pSeg->iLastPg;
- char *z;
-
- char *z1;
- char *z2;
- int nPad;
-
- z1 = lsmMallocPrintf(pEnv, "%d.%d", iFirst, iLast);
- if( iRoot ){
- z2 = lsmMallocPrintf(pEnv, "root=%d", iRoot);
- }else{
- z2 = lsmMallocPrintf(pEnv, "size=%d", nSize);
- }
-
- nPad = nMin - 2 - strlen(z1) - 1 - strlen(z2);
- nPad = LSM_MAX(0, nPad);
-
- if( iRoot ){
- z = lsmMallocPrintf(pEnv, "/%s %*s%s\\", z1, nPad, "", z2);
- }else{
- z = lsmMallocPrintf(pEnv, "|%s %*s%s|", z1, nPad, "", z2);
- }
- lsmFree(pEnv, z1);
- lsmFree(pEnv, z2);
-
- return z;
-}
-
-static int fileToString(
- lsm_db *pDb, /* For xMalloc() */
- char *aBuf,
- int nBuf,
- int nMin,
- Segment *pSeg
-){
- int i = 0;
- if( pSeg ){
- char *zSeg;
-
- zSeg = segToString(pDb->pEnv, pSeg, nMin);
- snprintf(&aBuf[i], nBuf-i, "%s", zSeg);
- i += strlen(&aBuf[i]);
- lsmFree(pDb->pEnv, zSeg);
-
-#ifdef LSM_LOG_FREELIST
- lsmInfoArrayStructure(pDb, 1, pSeg->iFirst, &zSeg);
- snprintf(&aBuf[i], nBuf-1, " (%s)", zSeg);
- i += strlen(&aBuf[i]);
- lsmFree(pDb->pEnv, zSeg);
-#endif
- aBuf[nBuf] = 0;
- }else{
- aBuf[0] = '\0';
- }
-
- return i;
-}
-
-void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
- LsmBlob blob = {0, 0, 0}; /* LsmBlob used for keys */
- LsmString s;
- int i;
-
- int nRec;
- int iPtr;
- int flags;
- u8 *aData;
- int nData;
-
- aData = fsPageData(pPg, &nData);
-
- nRec = pageGetNRec(aData, nData);
- iPtr = (int)pageGetPtr(aData, nData);
- flags = pageGetFlags(aData, nData);
-
- lsmStringInit(&s, pDb->pEnv);
- lsmStringAppendf(&s,"nCell=%d iPtr=%d flags=%d {", nRec, iPtr, flags);
- if( flags&SEGMENT_BTREE_FLAG ) iPtr = 0;
-
- for(i=0; i<nRec; i++){
- Page *pRef = 0; /* Pointer to page iRef */
- int iChar;
- u8 *aKey; int nKey = 0; /* Key */
- u8 *aVal = 0; int nVal = 0; /* Value */
- int iTopic;
- u8 *aCell;
- int iPgPtr;
- int eType;
-
- aCell = pageGetCell(aData, nData, i);
- eType = *aCell++;
- assert( (flags & SEGMENT_BTREE_FLAG) || eType!=0 );
- aCell += lsmVarintGet32(aCell, &iPgPtr);
-
- if( eType==0 ){
- LsmPgno iRef; /* Page number of referenced page */
- aCell += lsmVarintGet64(aCell, &iRef);
- lsmFsDbPageGet(pDb->pFS, pRun, iRef, &pRef);
- aKey = pageGetKey(pRun, pRef, 0, &iTopic, &nKey, &blob);
- }else{
- aCell += lsmVarintGet32(aCell, &nKey);
- if( rtIsWrite(eType) ) aCell += lsmVarintGet32(aCell, &nVal);
- sortedReadData(0, pPg, (aCell-aData), nKey+nVal, (void **)&aKey, &blob);
- aVal = &aKey[nKey];
- iTopic = eType;
- }
-
- lsmStringAppendf(&s, "%s%2X:", (i==0?"":" "), iTopic);
- for(iChar=0; iChar<nKey; iChar++){
- lsmStringAppendf(&s, "%c", isalnum(aKey[iChar]) ? aKey[iChar] : '.');
- }
- if( nVal>0 && bVals ){
- lsmStringAppendf(&s, "##");
- for(iChar=0; iChar<nVal; iChar++){
- lsmStringAppendf(&s, "%c", isalnum(aVal[iChar]) ? aVal[iChar] : '.');
- }
- }
-
- lsmStringAppendf(&s, " %d", iPgPtr+iPtr);
- lsmFsPageRelease(pRef);
- }
- lsmStringAppend(&s, "}", 1);
-
- lsmLogMessage(pDb, LSM_OK, " Page %d: %s", lsmFsPageNumber(pPg), s.z);
- lsmStringClear(&s);
-
- sortedBlobFree(&blob);
-}
-
-static void infoCellDump(
- lsm_db *pDb, /* Database handle */
- Segment *pSeg, /* Segment page belongs to */
- int bIndirect, /* True to follow indirect refs */
- Page *pPg,
- int iCell,
- int *peType,
- int *piPgPtr,
- u8 **paKey, int *pnKey,
- u8 **paVal, int *pnVal,
- LsmBlob *pBlob
-){
- u8 *aData; int nData; /* Page data */
- u8 *aKey; int nKey = 0; /* Key */
- u8 *aVal = 0; int nVal = 0; /* Value */
- int eType;
- int iPgPtr;
- Page *pRef = 0; /* Pointer to page iRef */
- u8 *aCell;
-
- aData = fsPageData(pPg, &nData);
-
- aCell = pageGetCell(aData, nData, iCell);
- eType = *aCell++;
- aCell += lsmVarintGet32(aCell, &iPgPtr);
-
- if( eType==0 ){
- int dummy;
- LsmPgno iRef; /* Page number of referenced page */
- aCell += lsmVarintGet64(aCell, &iRef);
- if( bIndirect ){
- lsmFsDbPageGet(pDb->pFS, pSeg, iRef, &pRef);
- pageGetKeyCopy(pDb->pEnv, pSeg, pRef, 0, &dummy, pBlob);
- aKey = (u8 *)pBlob->pData;
- nKey = pBlob->nData;
- lsmFsPageRelease(pRef);
- }else{
- aKey = (u8 *)"<indirect>";
- nKey = 11;
- }
- }else{
- aCell += lsmVarintGet32(aCell, &nKey);
- if( rtIsWrite(eType) ) aCell += lsmVarintGet32(aCell, &nVal);
- sortedReadData(pSeg, pPg, (aCell-aData), nKey+nVal, (void **)&aKey, pBlob);
- aVal = &aKey[nKey];
- }
-
- if( peType ) *peType = eType;
- if( piPgPtr ) *piPgPtr = iPgPtr;
- if( paKey ) *paKey = aKey;
- if( paVal ) *paVal = aVal;
- if( pnKey ) *pnKey = nKey;
- if( pnVal ) *pnVal = nVal;
-}
-
-static int infoAppendBlob(LsmString *pStr, int bHex, u8 *z, int n){
- int iChar;
- for(iChar=0; iChar<n; iChar++){
- if( bHex ){
- lsmStringAppendf(pStr, "%02X", z[iChar]);
- }else{
- lsmStringAppendf(pStr, "%c", isalnum(z[iChar]) ?z[iChar] : '.');
- }
- }
- return LSM_OK;
-}
-
-#define INFO_PAGE_DUMP_DATA 0x01
-#define INFO_PAGE_DUMP_VALUES 0x02
-#define INFO_PAGE_DUMP_HEX 0x04
-#define INFO_PAGE_DUMP_INDIRECT 0x08
-
-static int infoPageDump(
- lsm_db *pDb, /* Database handle */
- LsmPgno iPg, /* Page number of page to dump */
- int flags,
- char **pzOut /* OUT: lsmMalloc'd string */
-){
- int rc = LSM_OK; /* Return code */
- Page *pPg = 0; /* Handle for page iPg */
- int i, j; /* Loop counters */
- const int perLine = 16; /* Bytes per line in the raw hex dump */
- Segment *pSeg = 0;
- Snapshot *pSnap;
-
- int bValues = (flags & INFO_PAGE_DUMP_VALUES);
- int bHex = (flags & INFO_PAGE_DUMP_HEX);
- int bData = (flags & INFO_PAGE_DUMP_DATA);
- int bIndirect = (flags & INFO_PAGE_DUMP_INDIRECT);
-
- *pzOut = 0;
- if( iPg==0 ) return LSM_ERROR;
-
- assert( pDb->pClient || pDb->pWorker );
- pSnap = pDb->pClient;
- if( pSnap==0 ) pSnap = pDb->pWorker;
- if( pSnap->redirect.n>0 ){
- Level *pLvl;
- int bUse = 0;
- for(pLvl=pSnap->pLevel; pLvl->pNext; pLvl=pLvl->pNext);
- pSeg = (pLvl->nRight==0 ? &pLvl->lhs : &pLvl->aRhs[pLvl->nRight-1]);
- rc = lsmFsSegmentContainsPg(pDb->pFS, pSeg, iPg, &bUse);
- if( bUse==0 ){
- pSeg = 0;
- }
- }
-
- /* iPg is a real page number (not subject to redirection). So it is safe
- ** to pass a NULL in place of the segment pointer as the second argument
- ** to lsmFsDbPageGet() here. */
- if( rc==LSM_OK ){
- rc = lsmFsDbPageGet(pDb->pFS, 0, iPg, &pPg);
- }
-
- if( rc==LSM_OK ){
- LsmBlob blob = {0, 0, 0, 0};
- int nKeyWidth = 0;
- LsmString str;
- int nRec;
- int iPtr;
- int flags2;
- int iCell;
- u8 *aData; int nData; /* Page data and size thereof */
-
- aData = fsPageData(pPg, &nData);
- nRec = pageGetNRec(aData, nData);
- iPtr = (int)pageGetPtr(aData, nData);
- flags2 = pageGetFlags(aData, nData);
-
- lsmStringInit(&str, pDb->pEnv);
- lsmStringAppendf(&str, "Page : %lld (%d bytes)\n", iPg, nData);
- lsmStringAppendf(&str, "nRec : %d\n", nRec);
- lsmStringAppendf(&str, "iPtr : %d\n", iPtr);
- lsmStringAppendf(&str, "flags: %04x\n", flags2);
- lsmStringAppendf(&str, "\n");
-
- for(iCell=0; iCell<nRec; iCell++){
- int nKey;
- infoCellDump(
- pDb, pSeg, bIndirect, pPg, iCell, 0, 0, 0, &nKey, 0, 0, &blob
- );
- if( nKey>nKeyWidth ) nKeyWidth = nKey;
- }
- if( bHex ) nKeyWidth = nKeyWidth * 2;
-
- for(iCell=0; iCell<nRec; iCell++){
- u8 *aKey; int nKey = 0; /* Key */
- u8 *aVal; int nVal = 0; /* Value */
- int iPgPtr;
- int eType;
- LsmPgno iAbsPtr;
- char zFlags[8];
-
- infoCellDump(pDb, pSeg, bIndirect, pPg, iCell, &eType, &iPgPtr,
- &aKey, &nKey, &aVal, &nVal, &blob
- );
- iAbsPtr = iPgPtr + ((flags2 & SEGMENT_BTREE_FLAG) ? 0 : iPtr);
-
- lsmFlagsToString(eType, zFlags);
- lsmStringAppendf(&str, "%s %d (%s) ",
- zFlags, iAbsPtr, (rtTopic(eType) ? "sys" : "usr")
- );
- infoAppendBlob(&str, bHex, aKey, nKey);
- if( nVal>0 && bValues ){
- lsmStringAppendf(&str, "%*s", nKeyWidth - (nKey*(1+bHex)), "");
- lsmStringAppendf(&str, " ");
- infoAppendBlob(&str, bHex, aVal, nVal);
- }
- if( rtTopic(eType) ){
- int iBlk = (int)~lsmGetU32(aKey);
- lsmStringAppendf(&str, " (block=%d", iBlk);
- if( nVal>0 ){
- i64 iSnap = lsmGetU64(aVal);
- lsmStringAppendf(&str, " snapshot=%lld", iSnap);
- }
- lsmStringAppendf(&str, ")");
- }
- lsmStringAppendf(&str, "\n");
- }
-
- if( bData ){
- lsmStringAppendf(&str, "\n-------------------"
- "-------------------------------------------------------------\n");
- lsmStringAppendf(&str, "Page %d\n",
- iPg, (iPg-1)*nData, iPg*nData - 1);
- for(i=0; i<nData; i += perLine){
- lsmStringAppendf(&str, "%04x: ", i);
- for(j=0; j<perLine; j++){
- if( i+j>nData ){
- lsmStringAppendf(&str, " ");
- }else{
- lsmStringAppendf(&str, "%02x ", aData[i+j]);
- }
- }
- lsmStringAppendf(&str, " ");
- for(j=0; j<perLine; j++){
- if( i+j>nData ){
- lsmStringAppendf(&str, " ");
- }else{
- lsmStringAppendf(&str,"%c", isprint(aData[i+j]) ? aData[i+j] : '.');
- }
- }
- lsmStringAppendf(&str,"\n");
- }
- }
-
- *pzOut = str.z;
- sortedBlobFree(&blob);
- lsmFsPageRelease(pPg);
- }
-
- return rc;
-}
-
-int lsmInfoPageDump(
- lsm_db *pDb, /* Database handle */
- LsmPgno iPg, /* Page number of page to dump */
- int bHex, /* True to output key/value in hex form */
- char **pzOut /* OUT: lsmMalloc'd string */
-){
- int flags = INFO_PAGE_DUMP_DATA | INFO_PAGE_DUMP_VALUES;
- if( bHex ) flags |= INFO_PAGE_DUMP_HEX;
- return infoPageDump(pDb, iPg, flags, pzOut);
-}
-
-void sortedDumpSegment(lsm_db *pDb, Segment *pRun, int bVals){
- assert( pDb->xLog );
- if( pRun && pRun->iFirst ){
- int flags = (bVals ? INFO_PAGE_DUMP_VALUES : 0);
- char *zSeg;
- Page *pPg;
-
- zSeg = segToString(pDb->pEnv, pRun, 0);
- lsmLogMessage(pDb, LSM_OK, "Segment: %s", zSeg);
- lsmFree(pDb->pEnv, zSeg);
-
- lsmFsDbPageGet(pDb->pFS, pRun, pRun->iFirst, &pPg);
- while( pPg ){
- Page *pNext;
- char *z = 0;
- infoPageDump(pDb, lsmFsPageNumber(pPg), flags, &z);
- lsmLogMessage(pDb, LSM_OK, "%s", z);
- lsmFree(pDb->pEnv, z);
-#if 0
- sortedDumpPage(pDb, pRun, pPg, bVals);
-#endif
- lsmFsDbPageNext(pRun, pPg, 1, &pNext);
- lsmFsPageRelease(pPg);
- pPg = pNext;
- }
- }
-}
-
-/*
-** Invoke the log callback zero or more times with messages that describe
-** the current database structure.
-*/
-void lsmSortedDumpStructure(
- lsm_db *pDb, /* Database handle (used for xLog callback) */
- Snapshot *pSnap, /* Snapshot to dump */
- int bKeys, /* Output the keys from each segment */
- int bVals, /* Output the values from each segment */
- const char *zWhy /* Caption to print near top of dump */
-){
- Snapshot *pDump = pSnap;
- Level *pTopLevel;
- char *zFree = 0;
-
- assert( pSnap );
- pTopLevel = lsmDbSnapshotLevel(pDump);
- if( pDb->xLog && pTopLevel ){
- static int nCall = 0;
- Level *pLevel;
- int iLevel = 0;
-
- nCall++;
- lsmLogMessage(pDb, LSM_OK, "Database structure %d (%s)", nCall, zWhy);
-
-#if 0
- if( nCall==1031 || nCall==1032 ) bKeys=1;
-#endif
-
- for(pLevel=pTopLevel; pLevel; pLevel=pLevel->pNext){
- char zLeft[1024];
- char zRight[1024];
- int i = 0;
-
- Segment *aLeft[24];
- Segment *aRight[24];
-
- int nLeft = 0;
- int nRight = 0;
-
- Segment *pSeg = &pLevel->lhs;
- aLeft[nLeft++] = pSeg;
-
- for(i=0; i<pLevel->nRight; i++){
- aRight[nRight++] = &pLevel->aRhs[i];
- }
-
-#ifdef LSM_LOG_FREELIST
- if( nRight ){
- memmove(&aRight[1], aRight, sizeof(aRight[0])*nRight);
- aRight[0] = 0;
- nRight++;
- }
-#endif
-
- for(i=0; i<nLeft || i<nRight; i++){
- int iPad = 0;
- char zLevel[32];
- zLeft[0] = '\0';
- zRight[0] = '\0';
-
- if( i<nLeft ){
- fileToString(pDb, zLeft, sizeof(zLeft), 24, aLeft[i]);
- }
- if( i<nRight ){
- fileToString(pDb, zRight, sizeof(zRight), 24, aRight[i]);
- }
-
- if( i==0 ){
- snprintf(zLevel, sizeof(zLevel), "L%d: (age=%d) (flags=%.4x)",
- iLevel, (int)pLevel->iAge, (int)pLevel->flags
- );
- }else{
- zLevel[0] = '\0';
- }
-
- if( nRight==0 ){
- iPad = 10;
- }
-
- lsmLogMessage(pDb, LSM_OK, "% 25s % *s% -35s %s",
- zLevel, iPad, "", zLeft, zRight
- );
- }
-
- iLevel++;
- }
-
- if( bKeys ){
- for(pLevel=pTopLevel; pLevel; pLevel=pLevel->pNext){
- int i;
- sortedDumpSegment(pDb, &pLevel->lhs, bVals);
- for(i=0; i<pLevel->nRight; i++){
- sortedDumpSegment(pDb, &pLevel->aRhs[i], bVals);
- }
- }
- }
- }
-
- lsmInfoFreelist(pDb, &zFree);
- lsmLogMessage(pDb, LSM_OK, "Freelist: %s", zFree);
- lsmFree(pDb->pEnv, zFree);
-
- assert( lsmFsIntegrityCheck(pDb) );
-}
-
-void lsmSortedFreeLevel(lsm_env *pEnv, Level *pLevel){
- Level *pNext;
- Level *p;
-
- for(p=pLevel; p; p=pNext){
- pNext = p->pNext;
- sortedFreeLevel(pEnv, p);
- }
-}
-
-void lsmSortedSaveTreeCursors(lsm_db *pDb){
- MultiCursor *pCsr;
- for(pCsr=pDb->pCsr; pCsr; pCsr=pCsr->pNext){
- lsmTreeCursorSave(pCsr->apTreeCsr[0]);
- lsmTreeCursorSave(pCsr->apTreeCsr[1]);
- }
-}
-
-void lsmSortedExpandBtreePage(Page *pPg, int nOrig){
- u8 *aData;
- int nData;
- int nEntry;
- int iHdr;
-
- aData = lsmFsPageData(pPg, &nData);
- nEntry = pageGetNRec(aData, nOrig);
- iHdr = SEGMENT_EOF(nOrig, nEntry);
- memmove(&aData[iHdr + (nData-nOrig)], &aData[iHdr], nOrig-iHdr);
-}
-
-#ifdef LSM_DEBUG_EXPENSIVE
-static void assertRunInOrder(lsm_db *pDb, Segment *pSeg){
- Page *pPg = 0;
- LsmBlob blob1 = {0, 0, 0, 0};
- LsmBlob blob2 = {0, 0, 0, 0};
-
- lsmFsDbPageGet(pDb->pFS, pSeg, pSeg->iFirst, &pPg);
- while( pPg ){
- u8 *aData; int nData;
- Page *pNext;
-
- aData = lsmFsPageData(pPg, &nData);
- if( 0==(pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) ){
- int i;
- int nRec = pageGetNRec(aData, nData);
- for(i=0; i<nRec; i++){
- int iTopic1, iTopic2;
- pageGetKeyCopy(pDb->pEnv, pSeg, pPg, i, &iTopic1, &blob1);
-
- if( i==0 && blob2.nData ){
- assert( sortedKeyCompare(
- pDb->xCmp, iTopic2, blob2.pData, blob2.nData,
- iTopic1, blob1.pData, blob1.nData
- )<0 );
- }
-
- if( i<(nRec-1) ){
- pageGetKeyCopy(pDb->pEnv, pSeg, pPg, i+1, &iTopic2, &blob2);
- assert( sortedKeyCompare(
- pDb->xCmp, iTopic1, blob1.pData, blob1.nData,
- iTopic2, blob2.pData, blob2.nData
- )<0 );
- }
- }
- }
-
- lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
- lsmFsPageRelease(pPg);
- pPg = pNext;
- }
-
- sortedBlobFree(&blob1);
- sortedBlobFree(&blob2);
-}
-#endif
-
-#ifdef LSM_DEBUG_EXPENSIVE
-/*
-** This function is only included in the build if LSM_DEBUG_EXPENSIVE is
-** defined. Its only purpose is to evaluate various assert() statements to
-** verify that the database is well formed in certain respects.
-**
-** More specifically, it checks that the array pOne contains the required
-** pointers to pTwo. Array pTwo must be a main array. pOne may be either a
-** separators array or another main array. If pOne does not contain the
-** correct set of pointers, an assert() statement fails.
-*/
-static int assertPointersOk(
- lsm_db *pDb, /* Database handle */
- Segment *pOne, /* Segment containing pointers */
- Segment *pTwo, /* Segment containing pointer targets */
- int bRhs /* True if pTwo may have been Gobble()d */
-){
- int rc = LSM_OK; /* Error code */
- SegmentPtr ptr1; /* Iterates through pOne */
- SegmentPtr ptr2; /* Iterates through pTwo */
- LsmPgno iPrev;
-
- assert( pOne && pTwo );
-
- memset(&ptr1, 0, sizeof(ptr1));
- memset(&ptr2, 0, sizeof(ptr1));
- ptr1.pSeg = pOne;
- ptr2.pSeg = pTwo;
- segmentPtrEndPage(pDb->pFS, &ptr1, 0, &rc);
- segmentPtrEndPage(pDb->pFS, &ptr2, 0, &rc);
-
- /* Check that the footer pointer of the first page of pOne points to
- ** the first page of pTwo. */
- iPrev = pTwo->iFirst;
- if( ptr1.iPtr!=iPrev && !bRhs ){
- assert( 0 );
- }
-
- if( rc==LSM_OK && ptr1.nCell>0 ){
- rc = segmentPtrLoadCell(&ptr1, 0);
- }
-
- while( rc==LSM_OK && ptr2.pPg ){
- LsmPgno iThis;
-
- /* Advance to the next page of segment pTwo that contains at least
- ** one cell. Break out of the loop if the iterator reaches EOF. */
- do{
- rc = segmentPtrNextPage(&ptr2, 1);
- assert( rc==LSM_OK );
- }while( rc==LSM_OK && ptr2.pPg && ptr2.nCell==0 );
- if( rc!=LSM_OK || ptr2.pPg==0 ) break;
- iThis = lsmFsPageNumber(ptr2.pPg);
-
- if( (ptr2.flags & (PGFTR_SKIP_THIS_FLAG|SEGMENT_BTREE_FLAG))==0 ){
-
- /* Load the first cell in the array pTwo page. */
- rc = segmentPtrLoadCell(&ptr2, 0);
-
- /* Iterate forwards through pOne, searching for a key that matches the
- ** key ptr2.pKey/nKey. This key should have a pointer to the page that
- ** ptr2 currently points to. */
- while( rc==LSM_OK ){
- int res = rtTopic(ptr1.eType) - rtTopic(ptr2.eType);
- if( res==0 ){
- res = pDb->xCmp(ptr1.pKey, ptr1.nKey, ptr2.pKey, ptr2.nKey);
- }
-
- if( res<0 ){
- assert( bRhs || ptr1.iPtr+ptr1.iPgPtr==iPrev );
- }else if( res>0 ){
- assert( 0 );
- }else{
- assert( ptr1.iPtr+ptr1.iPgPtr==iThis );
- iPrev = iThis;
- break;
- }
-
- rc = segmentPtrAdvance(0, &ptr1, 0);
- if( ptr1.pPg==0 ){
- assert( 0 );
- }
- }
- }
- }
-
- segmentPtrReset(&ptr1, 0);
- segmentPtrReset(&ptr2, 0);
- return LSM_OK;
-}
-
-/*
-** This function is only included in the build if LSM_DEBUG_EXPENSIVE is
-** defined. Its only purpose is to evaluate various assert() statements to
-** verify that the database is well formed in certain respects.
-**
-** More specifically, it checks that the b-tree embedded in array pRun
-** contains the correct keys. If not, an assert() fails.
-*/
-static int assertBtreeOk(
- lsm_db *pDb,
- Segment *pSeg
-){
- int rc = LSM_OK; /* Return code */
- if( pSeg->iRoot ){
- LsmBlob blob = {0, 0, 0}; /* Buffer used to cache overflow keys */
- FileSystem *pFS = pDb->pFS; /* File system to read from */
- Page *pPg = 0; /* Main run page */
- BtreeCursor *pCsr = 0; /* Btree cursor */
-
- rc = btreeCursorNew(pDb, pSeg, &pCsr);
- if( rc==LSM_OK ){
- rc = btreeCursorFirst(pCsr);
- }
- if( rc==LSM_OK ){
- rc = lsmFsDbPageGet(pFS, pSeg, pSeg->iFirst, &pPg);
- }
-
- while( rc==LSM_OK ){
- Page *pNext;
- u8 *aData;
- int nData;
- int flags;
-
- rc = lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
- lsmFsPageRelease(pPg);
- pPg = pNext;
- if( pPg==0 ) break;
- aData = fsPageData(pPg, &nData);
- flags = pageGetFlags(aData, nData);
- if( rc==LSM_OK
- && 0==((SEGMENT_BTREE_FLAG|PGFTR_SKIP_THIS_FLAG) & flags)
- && 0!=pageGetNRec(aData, nData)
- ){
- u8 *pKey;
- int nKey;
- int iTopic;
- pKey = pageGetKey(pSeg, pPg, 0, &iTopic, &nKey, &blob);
- assert( nKey==pCsr->nKey && 0==memcmp(pKey, pCsr->pKey, nKey) );
- assert( lsmFsPageNumber(pPg)==pCsr->iPtr );
- rc = btreeCursorNext(pCsr);
- }
- }
- assert( rc!=LSM_OK || pCsr->pKey==0 );
-
- if( pPg ) lsmFsPageRelease(pPg);
-
- btreeCursorFree(pCsr);
- sortedBlobFree(&blob);
- }
-
- return rc;
-}
-#endif /* ifdef LSM_DEBUG_EXPENSIVE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_str.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_str.c
deleted file mode 100644
index 9b1b63cee24..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_str.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-** 2012-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.
-**
-*************************************************************************
-**
-** Dynamic string functions.
-*/
-#include "lsmInt.h"
-
-/*
-** Turn bulk and uninitialized memory into an LsmString object
-*/
-void lsmStringInit(LsmString *pStr, lsm_env *pEnv){
- memset(pStr, 0, sizeof(pStr[0]));
- pStr->pEnv = pEnv;
-}
-
-/*
-** Increase the memory allocated for holding the string. Realloc as needed.
-**
-** If a memory allocation error occurs, set pStr->n to -1 and free the existing
-** allocation. If a prior memory allocation has occurred, this routine is a
-** no-op.
-*/
-int lsmStringExtend(LsmString *pStr, int nNew){
- assert( nNew>0 );
- if( pStr->n<0 ) return LSM_NOMEM;
- if( pStr->n + nNew >= pStr->nAlloc ){
- int nAlloc = pStr->n + nNew + 100;
- char *zNew = lsmRealloc(pStr->pEnv, pStr->z, nAlloc);
- if( zNew==0 ){
- lsmFree(pStr->pEnv, pStr->z);
- nAlloc = 0;
- pStr->n = -1;
- }
- pStr->nAlloc = nAlloc;
- pStr->z = zNew;
- }
- return (pStr->z ? LSM_OK : LSM_NOMEM_BKPT);
-}
-
-/*
-** Clear an LsmString object, releasing any allocated memory that it holds.
-** This also clears the error indication (if any).
-*/
-void lsmStringClear(LsmString *pStr){
- lsmFree(pStr->pEnv, pStr->z);
- lsmStringInit(pStr, pStr->pEnv);
-}
-
-/*
-** Append N bytes of text to the end of an LsmString object. If
-** N is negative, append the entire string.
-**
-** If the string is in an error state, this routine is a no-op.
-*/
-int lsmStringAppend(LsmString *pStr, const char *z, int N){
- int rc;
- if( N<0 ) N = (int)strlen(z);
- rc = lsmStringExtend(pStr, N+1);
- if( pStr->nAlloc ){
- memcpy(pStr->z+pStr->n, z, N+1);
- pStr->n += N;
- }
- return rc;
-}
-
-int lsmStringBinAppend(LsmString *pStr, const u8 *a, int n){
- int rc;
- rc = lsmStringExtend(pStr, n);
- if( pStr->nAlloc ){
- memcpy(pStr->z+pStr->n, a, n);
- pStr->n += n;
- }
- return rc;
-}
-
-/*
-** Append printf-formatted content to an LsmString.
-*/
-void lsmStringVAppendf(
- LsmString *pStr,
- const char *zFormat,
- va_list ap1,
- va_list ap2
-){
-#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__<199901L)) && \
- !defined(__APPLE__)
- extern int vsnprintf(char *str, size_t size, const char *format, va_list ap)
- /* Compatibility crutch for C89 compilation mode. sqlite3_vsnprintf()
- does not work identically and causes test failures if used here.
- For the time being we are assuming that the target has vsnprintf(),
- but that is not guaranteed to be the case for pure C89 platforms.
- */;
-#endif
- int nWrite;
- int nAvail;
-
- nAvail = pStr->nAlloc - pStr->n;
- nWrite = vsnprintf(pStr->z + pStr->n, nAvail, zFormat, ap1);
-
- if( nWrite>=nAvail ){
- lsmStringExtend(pStr, nWrite+1);
- if( pStr->nAlloc==0 ) return;
- nWrite = vsnprintf(pStr->z + pStr->n, nWrite+1, zFormat, ap2);
- }
-
- pStr->n += nWrite;
- pStr->z[pStr->n] = 0;
-}
-
-void lsmStringAppendf(LsmString *pStr, const char *zFormat, ...){
- va_list ap, ap2;
- va_start(ap, zFormat);
- va_start(ap2, zFormat);
- lsmStringVAppendf(pStr, zFormat, ap, ap2);
- va_end(ap);
- va_end(ap2);
-}
-
-int lsmStrlen(const char *zName){
- int nRet = 0;
- while( zName[nRet] ) nRet++;
- return nRet;
-}
-
-/*
-** Write into memory obtained from lsm_malloc().
-*/
-char *lsmMallocPrintf(lsm_env *pEnv, const char *zFormat, ...){
- LsmString s;
- va_list ap, ap2;
- lsmStringInit(&s, pEnv);
- va_start(ap, zFormat);
- va_start(ap2, zFormat);
- lsmStringVAppendf(&s, zFormat, ap, ap2);
- va_end(ap);
- va_end(ap2);
- if( s.n<0 ) return 0;
- return (char *)lsmReallocOrFree(pEnv, s.z, s.n+1);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_tree.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_tree.c
deleted file mode 100644
index 1a199fc1ce5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_tree.c
+++ /dev/null
@@ -1,2465 +0,0 @@
-/*
-** 2011-08-18
-**
-** 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 contains the implementation of an in-memory tree structure.
-**
-** Technically the tree is a B-tree of order 4 (in the Knuth sense - each
-** node may have up to 4 children). Keys are stored within B-tree nodes by
-** reference. This may be slightly slower than a conventional red-black
-** tree, but it is simpler. It is also an easier structure to modify to
-** create a version that supports nested transaction rollback.
-**
-** This tree does not currently support a delete operation. One is not
-** required. When LSM deletes a key from a database, it inserts a DELETE
-** marker into the data structure. As a result, although the value associated
-** with a key stored in the in-memory tree structure may be modified, no
-** keys are ever removed.
-*/
-
-/*
-** MVCC NOTES
-**
-** The in-memory tree structure supports SQLite-style MVCC. This means
-** that while one client is writing to the tree structure, other clients
-** may still be querying an older snapshot of the tree.
-**
-** One way to implement this is to use an append-only b-tree. In this
-** case instead of modifying nodes in-place, a copy of the node is made
-** and the required modifications made to the copy. The parent of the
-** node is then modified (to update the pointer so that it points to
-** the new copy), which causes a copy of the parent to be made, and so on.
-** This means that each time the tree is written to a new root node is
-** created. A snapshot is identified by the root node that it uses.
-**
-** The problem with the above is that each time the tree is written to,
-** a copy of the node structure modified and all of its ancestor nodes
-** is made. This may prove excessive with large tree structures.
-**
-** To reduce this overhead, the data structure used for a tree node is
-** designed so that it may be edited in place exactly once without
-** affecting existing users. In other words, the node structure is capable
-** of storing two separate versions of the node at the same time.
-** When a node is to be edited, if the node structure already contains
-** two versions, a copy is made as in the append-only approach. Or, if
-** it only contains a single version, it is edited in place.
-**
-** This reduces the overhead so that, roughly, one new node structure
-** must be allocated for each write (on top of those allocations that
-** would have been required by a non-MVCC tree). Logic: Assume that at
-** any time, 50% of nodes in the tree already contain 2 versions. When
-** a new entry is written to a node, there is a 50% chance that a copy
-** of the node will be required. And a 25% chance that a copy of its
-** parent is required. And so on.
-**
-** ROLLBACK
-**
-** The in-memory tree also supports transaction and sub-transaction
-** rollback. In order to rollback to point in time X, the following is
-** necessary:
-**
-** 1. All memory allocated since X must be freed, and
-** 2. All "v2" data adding to nodes that existed at X should be zeroed.
-** 3. The root node must be restored to its X value.
-**
-** The Mempool object used to allocate memory for the tree supports
-** operation (1) - see the lsmPoolMark() and lsmPoolRevert() functions.
-**
-** To support (2), all nodes that have v2 data are part of a singly linked
-** list, sorted by the age of the v2 data (nodes that have had data added
-** most recently are at the end of the list). So to zero all v2 data added
-** since X, the linked list is traversed from the first node added following
-** X onwards.
-**
-*/
-
-#ifndef _LSM_INT_H
-# include "lsmInt.h"
-#endif
-
-#include <string.h>
-
-#define MAX_DEPTH 32
-
-typedef struct TreeKey TreeKey;
-typedef struct TreeNode TreeNode;
-typedef struct TreeLeaf TreeLeaf;
-typedef struct NodeVersion NodeVersion;
-
-struct TreeOld {
- u32 iShmid; /* Last shared-memory chunk in use by old */
- u32 iRoot; /* Offset of root node in shm file */
- u32 nHeight; /* Height of tree structure */
-};
-
-#if 0
-/*
-** assert() that a TreeKey.flags value is sane. Usage:
-**
-** assert( lsmAssertFlagsOk(pTreeKey->flags) );
-*/
-static int lsmAssertFlagsOk(u8 keyflags){
- /* At least one flag must be set. Otherwise, what is this key doing? */
- assert( keyflags!=0 );
-
- /* The POINT_DELETE and INSERT flags cannot both be set. */
- assert( (keyflags & LSM_POINT_DELETE)==0 || (keyflags & LSM_INSERT)==0 );
-
- /* If both the START_DELETE and END_DELETE flags are set, then the INSERT
- ** flag must also be set. In other words - the three DELETE flags cannot
- ** all be set */
- assert( (keyflags & LSM_END_DELETE)==0
- || (keyflags & LSM_START_DELETE)==0
- || (keyflags & LSM_POINT_DELETE)==0
- );
-
- return 1;
-}
-#endif
-static int assert_delete_ranges_match(lsm_db *);
-static int treeCountEntries(lsm_db *db);
-
-/*
-** Container for a key-value pair. Within the *-shm file, each key/value
-** pair is stored in a single allocation (which may not actually be
-** contiguous in memory). Layout is the TreeKey structure, followed by
-** the nKey bytes of key blob, followed by the nValue bytes of value blob
-** (if nValue is non-negative).
-*/
-struct TreeKey {
- int nKey; /* Size of pKey in bytes */
- int nValue; /* Size of pValue. Or negative. */
- u8 flags; /* Various LSM_XXX flags */
-};
-
-#define TKV_KEY(p) ((void *)&(p)[1])
-#define TKV_VAL(p) ((void *)(((u8 *)&(p)[1]) + (p)->nKey))
-
-/*
-** A single tree node. A node structure may contain up to 3 key/value
-** pairs. Internal (non-leaf) nodes have up to 4 children.
-**
-** TODO: Update the format of this to be more compact. Get it working
-** first though...
-*/
-struct TreeNode {
- u32 aiKeyPtr[3]; /* Array of pointers to TreeKey objects */
-
- /* The following fields are present for interior nodes only, not leaves. */
- u32 aiChildPtr[4]; /* Array of pointers to child nodes */
-
- /* The extra child pointer slot. */
- u32 iV2; /* Transaction number of v2 */
- u8 iV2Child; /* apChild[] entry replaced by pV2Ptr */
- u32 iV2Ptr; /* Substitute pointer */
-};
-
-struct TreeLeaf {
- u32 aiKeyPtr[3]; /* Array of pointers to TreeKey objects */
-};
-
-typedef struct TreeBlob TreeBlob;
-struct TreeBlob {
- int n;
- u8 *a;
-};
-
-/*
-** Cursor for searching a tree structure.
-**
-** If a cursor does not point to any element (a.k.a. EOF), then the
-** TreeCursor.iNode variable is set to a negative value. Otherwise, the
-** cursor currently points to key aiCell[iNode] on node apTreeNode[iNode].
-**
-** Entries in the apTreeNode[] and aiCell[] arrays contain the node and
-** index of the TreeNode.apChild[] pointer followed to descend to the
-** current element. Hence apTreeNode[0] always contains the root node of
-** the tree.
-*/
-struct TreeCursor {
- lsm_db *pDb; /* Database handle for this cursor */
- TreeRoot *pRoot; /* Root node and height of tree to access */
- int iNode; /* Cursor points at apTreeNode[iNode] */
- TreeNode *apTreeNode[MAX_DEPTH];/* Current position in tree */
- u8 aiCell[MAX_DEPTH]; /* Current position in tree */
- TreeKey *pSave; /* Saved key */
- TreeBlob blob; /* Dynamic storage for a key */
-};
-
-/*
-** A value guaranteed to be larger than the largest possible transaction
-** id (TreeHeader.iTransId).
-*/
-#define WORKING_VERSION (1<<30)
-
-static int tblobGrow(lsm_db *pDb, TreeBlob *p, int n, int *pRc){
- if( n>p->n ){
- lsmFree(pDb->pEnv, p->a);
- p->a = lsmMallocRc(pDb->pEnv, n, pRc);
- p->n = n;
- }
- return (p->a==0);
-}
-static void tblobFree(lsm_db *pDb, TreeBlob *p){
- lsmFree(pDb->pEnv, p->a);
-}
-
-
-/***********************************************************************
-** Start of IntArray methods. */
-/*
-** Append value iVal to the contents of IntArray *p. Return LSM_OK if
-** successful, or LSM_NOMEM if an OOM condition is encountered.
-*/
-static int intArrayAppend(lsm_env *pEnv, IntArray *p, u32 iVal){
- assert( p->nArray<=p->nAlloc );
- if( p->nArray>=p->nAlloc ){
- u32 *aNew;
- int nNew = p->nArray ? p->nArray*2 : 128;
- aNew = lsmRealloc(pEnv, p->aArray, nNew*sizeof(u32));
- if( !aNew ) return LSM_NOMEM_BKPT;
- p->aArray = aNew;
- p->nAlloc = nNew;
- }
-
- p->aArray[p->nArray++] = iVal;
- return LSM_OK;
-}
-
-/*
-** Zero the IntArray object.
-*/
-static void intArrayFree(lsm_env *pEnv, IntArray *p){
- p->nArray = 0;
-}
-
-/*
-** Return the number of entries currently in the int-array object.
-*/
-static int intArraySize(IntArray *p){
- return p->nArray;
-}
-
-/*
-** Return a copy of the iIdx'th entry in the int-array.
-*/
-static u32 intArrayEntry(IntArray *p, int iIdx){
- return p->aArray[iIdx];
-}
-
-/*
-** Truncate the int-array so that all but the first nVal values are
-** discarded.
-*/
-static void intArrayTruncate(IntArray *p, int nVal){
- p->nArray = nVal;
-}
-/* End of IntArray methods.
-***********************************************************************/
-
-static int treeKeycmp(void *p1, int n1, void *p2, int n2){
- int res;
- res = memcmp(p1, p2, LSM_MIN(n1, n2));
- if( res==0 ) res = (n1-n2);
- return res;
-}
-
-/*
-** The pointer passed as the first argument points to an interior node,
-** not a leaf. This function returns the offset of the iCell'th child
-** sub-tree of the node.
-*/
-static u32 getChildPtr(TreeNode *p, int iVersion, int iCell){
- assert( iVersion>=0 );
- assert( iCell>=0 && iCell<=array_size(p->aiChildPtr) );
- if( p->iV2 && p->iV2<=(u32)iVersion && iCell==p->iV2Child ) return p->iV2Ptr;
- return p->aiChildPtr[iCell];
-}
-
-/*
-** Given an offset within the *-shm file, return the associated chunk number.
-*/
-static int treeOffsetToChunk(u32 iOff){
- assert( LSM_SHM_CHUNK_SIZE==(1<<15) );
- return (int)(iOff>>15);
-}
-
-#define treeShmptrUnsafe(pDb, iPtr) \
-(&((u8*)((pDb)->apShm[(iPtr)>>15]))[(iPtr) & (LSM_SHM_CHUNK_SIZE-1)])
-
-/*
-** Return a pointer to the mapped memory location associated with *-shm
-** file offset iPtr.
-*/
-static void *treeShmptr(lsm_db *pDb, u32 iPtr){
-
- assert( (iPtr>>15)<(u32)pDb->nShm );
- assert( pDb->apShm[iPtr>>15] );
-
- return iPtr ? treeShmptrUnsafe(pDb, iPtr) : 0;
-}
-
-static ShmChunk * treeShmChunk(lsm_db *pDb, int iChunk){
- return (ShmChunk *)(pDb->apShm[iChunk]);
-}
-
-static ShmChunk * treeShmChunkRc(lsm_db *pDb, int iChunk, int *pRc){
- assert( *pRc==LSM_OK );
- if( iChunk<pDb->nShm || LSM_OK==(*pRc = lsmShmCacheChunks(pDb, iChunk+1)) ){
- return (ShmChunk *)(pDb->apShm[iChunk]);
- }
- return 0;
-}
-
-
-#ifndef NDEBUG
-static void assertIsWorkingChild(
- lsm_db *db,
- TreeNode *pNode,
- TreeNode *pParent,
- int iCell
-){
- TreeNode *p;
- u32 iPtr = getChildPtr(pParent, WORKING_VERSION, iCell);
- p = treeShmptr(db, iPtr);
- assert( p==pNode );
-}
-#else
-# define assertIsWorkingChild(w,x,y,z)
-#endif
-
-/* Values for the third argument to treeShmkey(). */
-#define TKV_LOADKEY 1
-#define TKV_LOADVAL 2
-
-static TreeKey *treeShmkey(
- lsm_db *pDb, /* Database handle */
- u32 iPtr, /* Shmptr to TreeKey struct */
- int eLoad, /* Either zero or a TREEKEY_LOADXXX value */
- TreeBlob *pBlob, /* Used if dynamic memory is required */
- int *pRc /* IN/OUT: Error code */
-){
- TreeKey *pRet;
-
- assert( eLoad==TKV_LOADKEY || eLoad==TKV_LOADVAL );
- pRet = (TreeKey *)treeShmptr(pDb, iPtr);
- if( pRet ){
- int nReq; /* Bytes of space required at pRet */
- int nAvail; /* Bytes of space available at pRet */
-
- nReq = sizeof(TreeKey) + pRet->nKey;
- if( eLoad==TKV_LOADVAL && pRet->nValue>0 ){
- nReq += pRet->nValue;
- }
- assert( LSM_SHM_CHUNK_SIZE==(1<<15) );
- nAvail = LSM_SHM_CHUNK_SIZE - (iPtr & (LSM_SHM_CHUNK_SIZE-1));
-
- if( nAvail<nReq ){
- if( tblobGrow(pDb, pBlob, nReq, pRc)==0 ){
- int nLoad = 0;
- while( *pRc==LSM_OK ){
- ShmChunk *pChunk;
- void *p = treeShmptr(pDb, iPtr);
- int n = LSM_MIN(nAvail, nReq-nLoad);
-
- memcpy(&pBlob->a[nLoad], p, n);
- nLoad += n;
- if( nLoad==nReq ) break;
-
- pChunk = treeShmChunk(pDb, treeOffsetToChunk(iPtr));
- assert( pChunk );
- iPtr = (pChunk->iNext * LSM_SHM_CHUNK_SIZE) + LSM_SHM_CHUNK_HDR;
- nAvail = LSM_SHM_CHUNK_SIZE - LSM_SHM_CHUNK_HDR;
- }
- }
- pRet = (TreeKey *)(pBlob->a);
- }
- }
-
- return pRet;
-}
-
-#if defined(LSM_DEBUG) && defined(LSM_EXPENSIVE_ASSERT)
-void assert_leaf_looks_ok(TreeNode *pNode){
- assert( pNode->apKey[1] );
-}
-
-void assert_node_looks_ok(TreeNode *pNode, int nHeight){
- if( pNode ){
- assert( pNode->apKey[1] );
- if( nHeight>1 ){
- int i;
- assert( getChildPtr(pNode, WORKING_VERSION, 1) );
- assert( getChildPtr(pNode, WORKING_VERSION, 2) );
- for(i=0; i<4; i++){
- assert_node_looks_ok(getChildPtr(pNode, WORKING_VERSION, i), nHeight-1);
- }
- }
- }
-}
-
-/*
-** Run various assert() statements to check that the working-version of the
-** tree is correct in the following respects:
-**
-** * todo...
-*/
-void assert_tree_looks_ok(int rc, Tree *pTree){
-}
-#else
-# define assert_tree_looks_ok(x,y)
-#endif
-
-void lsmFlagsToString(int flags, char *zFlags){
-
- zFlags[0] = (flags & LSM_END_DELETE) ? ']' : '.';
-
- /* Only one of LSM_POINT_DELETE, LSM_INSERT and LSM_SEPARATOR should ever
- ** be set. If this is not true, write a '?' to the output. */
- switch( flags & (LSM_POINT_DELETE|LSM_INSERT|LSM_SEPARATOR) ){
- case 0: zFlags[1] = '.'; break;
- case LSM_POINT_DELETE: zFlags[1] = '-'; break;
- case LSM_INSERT: zFlags[1] = '+'; break;
- case LSM_SEPARATOR: zFlags[1] = '^'; break;
- default: zFlags[1] = '?'; break;
- }
-
- zFlags[2] = (flags & LSM_SYSTEMKEY) ? '*' : '.';
- zFlags[3] = (flags & LSM_START_DELETE) ? '[' : '.';
- zFlags[4] = '\0';
-}
-
-#ifdef LSM_DEBUG
-
-/*
-** Pointer pBlob points to a buffer containing a blob of binary data
-** nBlob bytes long. Append the contents of this blob to *pStr, with
-** each octet represented by a 2-digit hexadecimal number. For example,
-** if the input blob is three bytes in size and contains {0x01, 0x44, 0xFF},
-** then "0144ff" is appended to *pStr.
-*/
-static void lsmAppendStrBlob(LsmString *pStr, void *pBlob, int nBlob){
- int i;
- lsmStringExtend(pStr, nBlob*2);
- if( pStr->nAlloc==0 ) return;
- for(i=0; i<nBlob; i++){
- u8 c = ((u8*)pBlob)[i];
- if( c>='a' && c<='z' ){
- pStr->z[pStr->n++] = c;
- }else if( c!=0 || nBlob==1 || i!=(nBlob-1) ){
- pStr->z[pStr->n++] = "0123456789abcdef"[(c>>4)&0xf];
- pStr->z[pStr->n++] = "0123456789abcdef"[c&0xf];
- }
- }
- pStr->z[pStr->n] = 0;
-}
-
-#if 0 /* NOT USED */
-/*
-** Append nIndent space (0x20) characters to string *pStr.
-*/
-static void lsmAppendIndent(LsmString *pStr, int nIndent){
- int i;
- lsmStringExtend(pStr, nIndent);
- for(i=0; i<nIndent; i++) lsmStringAppend(pStr, " ", 1);
-}
-#endif
-
-static void strAppendFlags(LsmString *pStr, u8 flags){
- char zFlags[8];
-
- lsmFlagsToString(flags, zFlags);
- zFlags[4] = ':';
-
- lsmStringAppend(pStr, zFlags, 5);
-}
-
-void dump_node_contents(
- lsm_db *pDb,
- u32 iNode, /* Print out the contents of this node */
- char *zPath, /* Path from root to this node */
- int nPath, /* Number of bytes in zPath */
- int nHeight /* Height: (0==leaf) (1==parent-of-leaf) */
-){
- const char *zSpace = " ";
- int i;
- int rc = LSM_OK;
- LsmString s;
- TreeNode *pNode;
- TreeBlob b = {0, 0};
-
- pNode = (TreeNode *)treeShmptr(pDb, iNode);
-
- if( nHeight==0 ){
- /* Append the nIndent bytes of space to string s. */
- lsmStringInit(&s, pDb->pEnv);
-
- /* Append each key to string s. */
- for(i=0; i<3; i++){
- u32 iPtr = pNode->aiKeyPtr[i];
- if( iPtr ){
- TreeKey *pKey = treeShmkey(pDb, pNode->aiKeyPtr[i],TKV_LOADKEY, &b,&rc);
- strAppendFlags(&s, pKey->flags);
- lsmAppendStrBlob(&s, TKV_KEY(pKey), pKey->nKey);
- lsmStringAppend(&s, " ", -1);
- }
- }
-
- printf("% 6d %.*sleaf%.*s: %s\n",
- iNode, nPath, zPath, 20-nPath-4, zSpace, s.z
- );
- lsmStringClear(&s);
- }else{
- for(i=0; i<4 && nHeight>0; i++){
- u32 iPtr = getChildPtr(pNode, pDb->treehdr.root.iTransId, i);
- zPath[nPath] = (char)(i+'0');
- zPath[nPath+1] = '/';
-
- if( iPtr ){
- dump_node_contents(pDb, iPtr, zPath, nPath+2, nHeight-1);
- }
- if( i!=3 && pNode->aiKeyPtr[i] ){
- TreeKey *pKey = treeShmkey(pDb, pNode->aiKeyPtr[i], TKV_LOADKEY,&b,&rc);
- lsmStringInit(&s, pDb->pEnv);
- strAppendFlags(&s, pKey->flags);
- lsmAppendStrBlob(&s, TKV_KEY(pKey), pKey->nKey);
- printf("% 6d %.*s%.*s: %s\n",
- iNode, nPath+1, zPath, 20-nPath-1, zSpace, s.z);
- lsmStringClear(&s);
- }
- }
- }
-
- tblobFree(pDb, &b);
-}
-
-void dump_tree_contents(lsm_db *pDb, const char *zCaption){
- char zPath[64];
- TreeRoot *p = &pDb->treehdr.root;
- printf("\n%s\n", zCaption);
- zPath[0] = '/';
- if( p->iRoot ){
- dump_node_contents(pDb, p->iRoot, zPath, 1, p->nHeight-1);
- }
- fflush(stdout);
-}
-
-#endif
-
-/*
-** Initialize a cursor object, the space for which has already been
-** allocated.
-*/
-static void treeCursorInit(lsm_db *pDb, int bOld, TreeCursor *pCsr){
- memset(pCsr, 0, sizeof(TreeCursor));
- pCsr->pDb = pDb;
- if( bOld ){
- pCsr->pRoot = &pDb->treehdr.oldroot;
- }else{
- pCsr->pRoot = &pDb->treehdr.root;
- }
- pCsr->iNode = -1;
-}
-
-/*
-** Return a pointer to the mapping of the TreeKey object that the cursor
-** is pointing to.
-*/
-static TreeKey *csrGetKey(TreeCursor *pCsr, TreeBlob *pBlob, int *pRc){
- TreeKey *pRet;
- lsm_db *pDb = pCsr->pDb;
- u32 iPtr = pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]];
-
- assert( iPtr );
- pRet = (TreeKey*)treeShmptrUnsafe(pDb, iPtr);
- if( !(pRet->flags & LSM_CONTIGUOUS) ){
- pRet = treeShmkey(pDb, iPtr, TKV_LOADVAL, pBlob, pRc);
- }
-
- return pRet;
-}
-
-/*
-** Save the current position of tree cursor pCsr.
-*/
-int lsmTreeCursorSave(TreeCursor *pCsr){
- int rc = LSM_OK;
- if( pCsr && pCsr->pSave==0 ){
- int iNode = pCsr->iNode;
- if( iNode>=0 ){
- pCsr->pSave = csrGetKey(pCsr, &pCsr->blob, &rc);
- }
- pCsr->iNode = -1;
- }
- return rc;
-}
-
-/*
-** Restore the position of a saved tree cursor.
-*/
-static int treeCursorRestore(TreeCursor *pCsr, int *pRes){
- int rc = LSM_OK;
- if( pCsr->pSave ){
- TreeKey *pKey = pCsr->pSave;
- pCsr->pSave = 0;
- if( pRes ){
- rc = lsmTreeCursorSeek(pCsr, TKV_KEY(pKey), pKey->nKey, pRes);
- }
- }
- return rc;
-}
-
-/*
-** Allocate nByte bytes of space within the *-shm file. If successful,
-** return LSM_OK and set *piPtr to the offset within the file at which
-** the allocated space is located.
-*/
-static u32 treeShmalloc(lsm_db *pDb, int bAlign, int nByte, int *pRc){
- u32 iRet = 0;
- if( *pRc==LSM_OK ){
- const static int CHUNK_SIZE = LSM_SHM_CHUNK_SIZE;
- const static int CHUNK_HDR = LSM_SHM_CHUNK_HDR;
- u32 iWrite; /* Current write offset */
- u32 iEof; /* End of current chunk */
- int iChunk; /* Current chunk */
-
- assert( nByte <= (CHUNK_SIZE-CHUNK_HDR) );
-
- /* Check if there is enough space on the current chunk to fit the
- ** new allocation. If not, link in a new chunk and put the new
- ** allocation at the start of it. */
- iWrite = pDb->treehdr.iWrite;
- if( bAlign ){
- iWrite = (iWrite + 3) & ~0x0003;
- assert( (iWrite % 4)==0 );
- }
-
- assert( iWrite );
- iChunk = treeOffsetToChunk(iWrite-1);
- iEof = (iChunk+1) * CHUNK_SIZE;
- assert( iEof>=iWrite && (iEof-iWrite)<(u32)CHUNK_SIZE );
- if( (iWrite+nByte)>iEof ){
- ShmChunk *pHdr; /* Header of chunk just finished (iChunk) */
- ShmChunk *pFirst; /* Header of chunk treehdr.iFirst */
- ShmChunk *pNext; /* Header of new chunk */
- int iNext = 0; /* Next chunk */
- int rc = LSM_OK;
-
- pFirst = treeShmChunk(pDb, pDb->treehdr.iFirst);
-
- assert( shm_sequence_ge(pDb->treehdr.iUsedShmid, pFirst->iShmid) );
- assert( (pDb->treehdr.iNextShmid+1-pDb->treehdr.nChunk)==pFirst->iShmid );
-
- /* Check if the chunk at the start of the linked list is still in
- ** use. If not, reuse it. If so, allocate a new chunk by appending
- ** to the *-shm file. */
- if( pDb->treehdr.iUsedShmid!=pFirst->iShmid ){
- int bInUse;
- rc = lsmTreeInUse(pDb, pFirst->iShmid, &bInUse);
- if( rc!=LSM_OK ){
- *pRc = rc;
- return 0;
- }
- if( bInUse==0 ){
- iNext = pDb->treehdr.iFirst;
- pDb->treehdr.iFirst = pFirst->iNext;
- assert( pDb->treehdr.iFirst );
- }
- }
- if( iNext==0 ) iNext = pDb->treehdr.nChunk++;
-
- /* Set the header values for the new chunk */
- pNext = treeShmChunkRc(pDb, iNext, &rc);
- if( pNext ){
- pNext->iNext = 0;
- pNext->iShmid = (pDb->treehdr.iNextShmid++);
- }else{
- *pRc = rc;
- return 0;
- }
-
- /* Set the header values for the chunk just finished */
- pHdr = (ShmChunk *)treeShmptr(pDb, iChunk*CHUNK_SIZE);
- pHdr->iNext = iNext;
-
- /* Advance to the next chunk */
- iWrite = iNext * CHUNK_SIZE + CHUNK_HDR;
- }
-
- /* Allocate space at iWrite. */
- iRet = iWrite;
- pDb->treehdr.iWrite = iWrite + nByte;
- pDb->treehdr.root.nByte += nByte;
- }
- return iRet;
-}
-
-/*
-** Allocate and zero nByte bytes of space within the *-shm file.
-*/
-static void *treeShmallocZero(lsm_db *pDb, int nByte, u32 *piPtr, int *pRc){
- u32 iPtr;
- void *p;
- iPtr = treeShmalloc(pDb, 1, nByte, pRc);
- p = treeShmptr(pDb, iPtr);
- if( p ){
- assert( *pRc==LSM_OK );
- memset(p, 0, nByte);
- *piPtr = iPtr;
- }
- return p;
-}
-
-static TreeNode *newTreeNode(lsm_db *pDb, u32 *piPtr, int *pRc){
- return treeShmallocZero(pDb, sizeof(TreeNode), piPtr, pRc);
-}
-
-static TreeLeaf *newTreeLeaf(lsm_db *pDb, u32 *piPtr, int *pRc){
- return treeShmallocZero(pDb, sizeof(TreeLeaf), piPtr, pRc);
-}
-
-static TreeKey *newTreeKey(
- lsm_db *pDb,
- u32 *piPtr,
- void *pKey, int nKey, /* Key data */
- void *pVal, int nVal, /* Value data (or nVal<0 for delete) */
- int *pRc
-){
- TreeKey *p;
- u32 iPtr;
- u32 iEnd;
- int nRem;
- u8 *a;
- int n;
-
- /* Allocate space for the TreeKey structure itself */
- *piPtr = iPtr = treeShmalloc(pDb, 1, sizeof(TreeKey), pRc);
- p = treeShmptr(pDb, iPtr);
- if( *pRc ) return 0;
- p->nKey = nKey;
- p->nValue = nVal;
-
- /* Allocate and populate the space required for the key and value. */
- n = nRem = nKey;
- a = (u8 *)pKey;
- while( a ){
- while( nRem>0 ){
- u8 *aAlloc;
- int nAlloc;
- u32 iWrite;
-
- iWrite = (pDb->treehdr.iWrite & (LSM_SHM_CHUNK_SIZE-1));
- iWrite = LSM_MAX(iWrite, LSM_SHM_CHUNK_HDR);
- nAlloc = LSM_MIN((LSM_SHM_CHUNK_SIZE-iWrite), (u32)nRem);
-
- aAlloc = treeShmptr(pDb, treeShmalloc(pDb, 0, nAlloc, pRc));
- if( aAlloc==0 ) break;
- memcpy(aAlloc, &a[n-nRem], nAlloc);
- nRem -= nAlloc;
- }
- a = pVal;
- n = nRem = nVal;
- pVal = 0;
- }
-
- iEnd = iPtr + sizeof(TreeKey) + nKey + LSM_MAX(0, nVal);
- if( (iPtr & ~(LSM_SHM_CHUNK_SIZE-1))!=(iEnd & ~(LSM_SHM_CHUNK_SIZE-1)) ){
- p->flags = 0;
- }else{
- p->flags = LSM_CONTIGUOUS;
- }
-
- if( *pRc ) return 0;
-#if 0
- printf("store: %d %s\n", (int)iPtr, (char *)pKey);
-#endif
- return p;
-}
-
-static TreeNode *copyTreeNode(
- lsm_db *pDb,
- TreeNode *pOld,
- u32 *piNew,
- int *pRc
-){
- TreeNode *pNew;
-
- pNew = newTreeNode(pDb, piNew, pRc);
- if( pNew ){
- memcpy(pNew->aiKeyPtr, pOld->aiKeyPtr, sizeof(pNew->aiKeyPtr));
- memcpy(pNew->aiChildPtr, pOld->aiChildPtr, sizeof(pNew->aiChildPtr));
- if( pOld->iV2 ) pNew->aiChildPtr[pOld->iV2Child] = pOld->iV2Ptr;
- }
- return pNew;
-}
-
-static TreeNode *copyTreeLeaf(
- lsm_db *pDb,
- TreeLeaf *pOld,
- u32 *piNew,
- int *pRc
-){
- TreeLeaf *pNew;
- pNew = newTreeLeaf(pDb, piNew, pRc);
- if( pNew ){
- memcpy(pNew, pOld, sizeof(TreeLeaf));
- }
- return (TreeNode *)pNew;
-}
-
-/*
-** The tree cursor passed as the second argument currently points to an
-** internal node (not a leaf). Specifically, to a sub-tree pointer. This
-** function replaces the sub-tree that the cursor currently points to
-** with sub-tree pNew.
-**
-** The sub-tree may be replaced either by writing the "v2 data" on the
-** internal node, or by allocating a new TreeNode structure and then
-** calling this function on the parent of the internal node.
-*/
-static int treeUpdatePtr(lsm_db *pDb, TreeCursor *pCsr, u32 iNew){
- int rc = LSM_OK;
- if( pCsr->iNode<0 ){
- /* iNew is the new root node */
- pDb->treehdr.root.iRoot = iNew;
- }else{
- /* If this node already has version 2 content, allocate a copy and
- ** update the copy with the new pointer value. Otherwise, store the
- ** new pointer as v2 data within the current node structure. */
-
- TreeNode *p; /* The node to be modified */
- int iChildPtr; /* apChild[] entry to modify */
-
- p = pCsr->apTreeNode[pCsr->iNode];
- iChildPtr = pCsr->aiCell[pCsr->iNode];
-
- if( p->iV2 ){
- /* The "allocate new TreeNode" option */
- u32 iCopy;
- TreeNode *pCopy;
- pCopy = copyTreeNode(pDb, p, &iCopy, &rc);
- if( pCopy ){
- assert( rc==LSM_OK );
- pCopy->aiChildPtr[iChildPtr] = iNew;
- pCsr->iNode--;
- rc = treeUpdatePtr(pDb, pCsr, iCopy);
- }
- }else{
- /* The "v2 data" option */
- u32 iPtr;
- assert( pDb->treehdr.root.iTransId>0 );
-
- if( pCsr->iNode ){
- iPtr = getChildPtr(
- pCsr->apTreeNode[pCsr->iNode-1],
- pDb->treehdr.root.iTransId, pCsr->aiCell[pCsr->iNode-1]
- );
- }else{
- iPtr = pDb->treehdr.root.iRoot;
- }
- rc = intArrayAppend(pDb->pEnv, &pDb->rollback, iPtr);
-
- if( rc==LSM_OK ){
- p->iV2 = pDb->treehdr.root.iTransId;
- p->iV2Child = (u8)iChildPtr;
- p->iV2Ptr = iNew;
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Cursor pCsr points at a node that is part of pTree. This function
-** inserts a new key and optionally child node pointer into that node.
-**
-** The position into which the new key and pointer are inserted is
-** determined by the iSlot parameter. The new key will be inserted to
-** the left of the key currently stored in apKey[iSlot]. Or, if iSlot is
-** greater than the index of the rightmost key in the node.
-**
-** Pointer pLeftPtr points to a child tree that contains keys that are
-** smaller than pTreeKey.
-*/
-static int treeInsert(
- lsm_db *pDb, /* Database handle */
- TreeCursor *pCsr, /* Cursor indicating path to insert at */
- u32 iLeftPtr, /* Left child pointer */
- u32 iTreeKey, /* Location of key to insert */
- u32 iRightPtr, /* Right child pointer */
- int iSlot /* Position to insert key into */
-){
- int rc = LSM_OK;
- TreeNode *pNode = pCsr->apTreeNode[pCsr->iNode];
-
- /* Check if the node is currently full. If so, split pNode in two and
- ** call this function recursively to add a key to the parent. Otherwise,
- ** insert the new key directly into pNode. */
- assert( pNode->aiKeyPtr[1] );
- if( pNode->aiKeyPtr[0] && pNode->aiKeyPtr[2] ){
- u32 iLeft; TreeNode *pLeft; /* New left-hand sibling node */
- u32 iRight; TreeNode *pRight; /* New right-hand sibling node */
-
- pLeft = newTreeNode(pDb, &iLeft, &rc);
- pRight = newTreeNode(pDb, &iRight, &rc);
- if( rc ) return rc;
-
- pLeft->aiChildPtr[1] = getChildPtr(pNode, WORKING_VERSION, 0);
- pLeft->aiKeyPtr[1] = pNode->aiKeyPtr[0];
- pLeft->aiChildPtr[2] = getChildPtr(pNode, WORKING_VERSION, 1);
-
- pRight->aiChildPtr[1] = getChildPtr(pNode, WORKING_VERSION, 2);
- pRight->aiKeyPtr[1] = pNode->aiKeyPtr[2];
- pRight->aiChildPtr[2] = getChildPtr(pNode, WORKING_VERSION, 3);
-
- if( pCsr->iNode==0 ){
- /* pNode is the root of the tree. Grow the tree by one level. */
- u32 iRoot; TreeNode *pRoot; /* New root node */
-
- pRoot = newTreeNode(pDb, &iRoot, &rc);
- pRoot->aiKeyPtr[1] = pNode->aiKeyPtr[1];
- pRoot->aiChildPtr[1] = iLeft;
- pRoot->aiChildPtr[2] = iRight;
-
- pDb->treehdr.root.iRoot = iRoot;
- pDb->treehdr.root.nHeight++;
- }else{
-
- pCsr->iNode--;
- rc = treeInsert(pDb, pCsr,
- iLeft, pNode->aiKeyPtr[1], iRight, pCsr->aiCell[pCsr->iNode]
- );
- }
-
- assert( pLeft->iV2==0 );
- assert( pRight->iV2==0 );
- switch( iSlot ){
- case 0:
- pLeft->aiKeyPtr[0] = iTreeKey;
- pLeft->aiChildPtr[0] = iLeftPtr;
- if( iRightPtr ) pLeft->aiChildPtr[1] = iRightPtr;
- break;
- case 1:
- pLeft->aiChildPtr[3] = (iRightPtr ? iRightPtr : pLeft->aiChildPtr[2]);
- pLeft->aiKeyPtr[2] = iTreeKey;
- pLeft->aiChildPtr[2] = iLeftPtr;
- break;
- case 2:
- pRight->aiKeyPtr[0] = iTreeKey;
- pRight->aiChildPtr[0] = iLeftPtr;
- if( iRightPtr ) pRight->aiChildPtr[1] = iRightPtr;
- break;
- case 3:
- pRight->aiChildPtr[3] = (iRightPtr ? iRightPtr : pRight->aiChildPtr[2]);
- pRight->aiKeyPtr[2] = iTreeKey;
- pRight->aiChildPtr[2] = iLeftPtr;
- break;
- }
-
- }else{
- TreeNode *pNew;
- u32 *piKey;
- u32 *piChild;
- u32 iStore = 0;
- u32 iNew = 0;
- int i;
-
- /* Allocate a new version of node pNode. */
- pNew = newTreeNode(pDb, &iNew, &rc);
- if( rc ) return rc;
-
- piKey = pNew->aiKeyPtr;
- piChild = pNew->aiChildPtr;
-
- for(i=0; i<iSlot; i++){
- if( pNode->aiKeyPtr[i] ){
- *(piKey++) = pNode->aiKeyPtr[i];
- *(piChild++) = getChildPtr(pNode, WORKING_VERSION, i);
- }
- }
-
- *piKey++ = iTreeKey;
- *piChild++ = iLeftPtr;
-
- iStore = iRightPtr;
- for(i=iSlot; i<3; i++){
- if( pNode->aiKeyPtr[i] ){
- *(piKey++) = pNode->aiKeyPtr[i];
- *(piChild++) = iStore ? iStore : getChildPtr(pNode, WORKING_VERSION, i);
- iStore = 0;
- }
- }
-
- if( iStore ){
- *piChild = iStore;
- }else{
- *piChild = getChildPtr(pNode, WORKING_VERSION,
- (pNode->aiKeyPtr[2] ? 3 : 2)
- );
- }
- pCsr->iNode--;
- rc = treeUpdatePtr(pDb, pCsr, iNew);
- }
-
- return rc;
-}
-
-static int treeInsertLeaf(
- lsm_db *pDb, /* Database handle */
- TreeCursor *pCsr, /* Cursor structure */
- u32 iTreeKey, /* Key pointer to insert */
- int iSlot /* Insert key to the left of this */
-){
- int rc = LSM_OK; /* Return code */
- TreeNode *pLeaf = pCsr->apTreeNode[pCsr->iNode];
- TreeLeaf *pNew;
- u32 iNew;
-
- assert( iSlot>=0 && iSlot<=4 );
- assert( pCsr->iNode>0 );
- assert( pLeaf->aiKeyPtr[1] );
-
- pCsr->iNode--;
-
- pNew = newTreeLeaf(pDb, &iNew, &rc);
- if( pNew ){
- if( pLeaf->aiKeyPtr[0] && pLeaf->aiKeyPtr[2] ){
- /* The leaf is full. Split it in two. */
- TreeLeaf *pRight;
- u32 iRight;
- pRight = newTreeLeaf(pDb, &iRight, &rc);
- if( pRight ){
- assert( rc==LSM_OK );
- pNew->aiKeyPtr[1] = pLeaf->aiKeyPtr[0];
- pRight->aiKeyPtr[1] = pLeaf->aiKeyPtr[2];
- switch( iSlot ){
- case 0: pNew->aiKeyPtr[0] = iTreeKey; break;
- case 1: pNew->aiKeyPtr[2] = iTreeKey; break;
- case 2: pRight->aiKeyPtr[0] = iTreeKey; break;
- case 3: pRight->aiKeyPtr[2] = iTreeKey; break;
- }
-
- rc = treeInsert(pDb, pCsr, iNew, pLeaf->aiKeyPtr[1], iRight,
- pCsr->aiCell[pCsr->iNode]
- );
- }
- }else{
- int iOut = 0;
- int i;
- for(i=0; i<4; i++){
- if( i==iSlot ) pNew->aiKeyPtr[iOut++] = iTreeKey;
- if( i<3 && pLeaf->aiKeyPtr[i] ){
- pNew->aiKeyPtr[iOut++] = pLeaf->aiKeyPtr[i];
- }
- }
- rc = treeUpdatePtr(pDb, pCsr, iNew);
- }
- }
-
- return rc;
-}
-
-void lsmTreeMakeOld(lsm_db *pDb){
-
- /* A write transaction must be open. Otherwise the code below that
- ** assumes (pDb->pClient->iLogOff) is current may malfunction.
- **
- ** Update: currently this assert fails due to lsm_flush(), which does
- ** not set nTransOpen.
- */
- assert( /* pDb->nTransOpen>0 && */ pDb->iReader>=0 );
-
- if( pDb->treehdr.iOldShmid==0 ){
- pDb->treehdr.iOldLog = (pDb->treehdr.log.aRegion[2].iEnd << 1);
- pDb->treehdr.iOldLog |= (~(pDb->pClient->iLogOff) & (i64)0x0001);
-
- pDb->treehdr.oldcksum0 = pDb->treehdr.log.cksum0;
- pDb->treehdr.oldcksum1 = pDb->treehdr.log.cksum1;
- pDb->treehdr.iOldShmid = pDb->treehdr.iNextShmid-1;
- memcpy(&pDb->treehdr.oldroot, &pDb->treehdr.root, sizeof(TreeRoot));
-
- pDb->treehdr.root.iTransId = 1;
- pDb->treehdr.root.iRoot = 0;
- pDb->treehdr.root.nHeight = 0;
- pDb->treehdr.root.nByte = 0;
- }
-}
-
-void lsmTreeDiscardOld(lsm_db *pDb){
- assert( lsmShmAssertLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_EXCL)
- || lsmShmAssertLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_EXCL)
- );
- pDb->treehdr.iUsedShmid = pDb->treehdr.iOldShmid;
- pDb->treehdr.iOldShmid = 0;
-}
-
-int lsmTreeHasOld(lsm_db *pDb){
- return pDb->treehdr.iOldShmid!=0;
-}
-
-/*
-** This function is called during recovery to initialize the
-** tree header. Only the database connections private copy of the tree-header
-** is initialized here - it will be copied into shared memory if log file
-** recovery is successful.
-*/
-int lsmTreeInit(lsm_db *pDb){
- ShmChunk *pOne;
- int rc = LSM_OK;
-
- memset(&pDb->treehdr, 0, sizeof(TreeHeader));
- pDb->treehdr.root.iTransId = 1;
- pDb->treehdr.iFirst = 1;
- pDb->treehdr.nChunk = 2;
- pDb->treehdr.iWrite = LSM_SHM_CHUNK_SIZE + LSM_SHM_CHUNK_HDR;
- pDb->treehdr.iNextShmid = 2;
- pDb->treehdr.iUsedShmid = 1;
-
- pOne = treeShmChunkRc(pDb, 1, &rc);
- if( pOne ){
- pOne->iNext = 0;
- pOne->iShmid = 1;
- }
- return rc;
-}
-
-static void treeHeaderChecksum(
- TreeHeader *pHdr,
- u32 *aCksum
-){
- u32 cksum1 = 0x12345678;
- u32 cksum2 = 0x9ABCDEF0;
- u32 *a = (u32 *)pHdr;
- int i;
-
- assert( (offsetof(TreeHeader, aCksum) + sizeof(u32)*2)==sizeof(TreeHeader) );
- assert( (sizeof(TreeHeader) % (sizeof(u32)*2))==0 );
-
- for(i=0; i<(offsetof(TreeHeader, aCksum) / sizeof(u32)); i+=2){
- cksum1 += a[i];
- cksum2 += (cksum1 + a[i+1]);
- }
- aCksum[0] = cksum1;
- aCksum[1] = cksum2;
-}
-
-/*
-** Return true if the checksum stored in TreeHeader object *pHdr is
-** consistent with the contents of its other fields.
-*/
-static int treeHeaderChecksumOk(TreeHeader *pHdr){
- u32 aCksum[2];
- treeHeaderChecksum(pHdr, aCksum);
- return (0==memcmp(aCksum, pHdr->aCksum, sizeof(aCksum)));
-}
-
-/*
-** This type is used by functions lsmTreeRepair() and treeSortByShmid() to
-** make relinking the linked list of shared-memory chunks easier.
-*/
-typedef struct ShmChunkLoc ShmChunkLoc;
-struct ShmChunkLoc {
- ShmChunk *pShm;
- u32 iLoc;
-};
-
-/*
-** This function checks that the linked list of shared memory chunks
-** that starts at chunk db->treehdr.iFirst:
-**
-** 1) Includes all chunks in the shared-memory region, and
-** 2) Links them together in order of ascending shm-id.
-**
-** If no error occurs and the conditions above are met, LSM_OK is returned.
-**
-** If either of the conditions are untrue, LSM_CORRUPT is returned. Or, if
-** an error is encountered before the checks are completed, another LSM error
-** code (i.e. LSM_IOERR or LSM_NOMEM) may be returned.
-*/
-static int treeCheckLinkedList(lsm_db *db){
- int rc = LSM_OK;
- int nVisit = 0;
- ShmChunk *p;
-
- p = treeShmChunkRc(db, db->treehdr.iFirst, &rc);
- while( rc==LSM_OK && p ){
- if( p->iNext ){
- if( p->iNext>=db->treehdr.nChunk ){
- rc = LSM_CORRUPT_BKPT;
- }else{
- ShmChunk *pNext = treeShmChunkRc(db, p->iNext, &rc);
- if( rc==LSM_OK ){
- if( pNext->iShmid!=p->iShmid+1 ){
- rc = LSM_CORRUPT_BKPT;
- }
- p = pNext;
- }
- }
- }else{
- p = 0;
- }
- nVisit++;
- }
-
- if( rc==LSM_OK && (u32)nVisit!=db->treehdr.nChunk-1 ){
- rc = LSM_CORRUPT_BKPT;
- }
- return rc;
-}
-
-/*
-** Iterate through the current in-memory tree. If there are any v2-pointers
-** with transaction ids larger than db->treehdr.iTransId, zero them.
-*/
-static int treeRepairPtrs(lsm_db *db){
- int rc = LSM_OK;
-
- if( db->treehdr.root.nHeight>1 ){
- TreeCursor csr; /* Cursor used to iterate through tree */
- u32 iTransId = db->treehdr.root.iTransId;
-
- /* Initialize the cursor structure. Also decrement the nHeight variable
- ** in the tree-header. This will prevent the cursor from visiting any
- ** leaf nodes. */
- db->treehdr.root.nHeight--;
- treeCursorInit(db, 0, &csr);
-
- rc = lsmTreeCursorEnd(&csr, 0);
- while( rc==LSM_OK && lsmTreeCursorValid(&csr) ){
- TreeNode *pNode = csr.apTreeNode[csr.iNode];
- if( pNode->iV2>iTransId ){
- pNode->iV2Child = 0;
- pNode->iV2Ptr = 0;
- pNode->iV2 = 0;
- }
- rc = lsmTreeCursorNext(&csr);
- }
- tblobFree(csr.pDb, &csr.blob);
-
- db->treehdr.root.nHeight++;
- }
-
- return rc;
-}
-
-static int treeRepairList(lsm_db *db){
- int rc = LSM_OK;
- int i;
- ShmChunk *p;
- ShmChunk *pMin = 0;
- u32 iMin = 0;
-
- /* Iterate through all shm chunks. Find the smallest shm-id present in
- ** the shared-memory region. */
- for(i=1; rc==LSM_OK && (u32)i<db->treehdr.nChunk; i++){
- p = treeShmChunkRc(db, i, &rc);
- if( p && (pMin==0 || shm_sequence_ge(pMin->iShmid, p->iShmid)) ){
- pMin = p;
- iMin = i;
- }
- }
-
- /* Fix the shm-id values on any chunks with a shm-id greater than or
- ** equal to treehdr.iNextShmid. Then do a merge-sort of all chunks to
- ** fix the ShmChunk.iNext pointers.
- */
- if( rc==LSM_OK ){
- int nSort;
- int nByte;
- u32 iPrevShmid;
- ShmChunkLoc *aSort;
-
- /* Allocate space for a merge sort. */
- nSort = 1;
- while( (u32)nSort < (db->treehdr.nChunk-1) ) nSort = nSort * 2;
- nByte = sizeof(ShmChunkLoc) * nSort * 2;
- aSort = lsmMallocZeroRc(db->pEnv, nByte, &rc);
- iPrevShmid = pMin->iShmid;
-
- /* Fix all shm-ids, if required. */
- if( rc==LSM_OK ){
- iPrevShmid = pMin->iShmid-1;
- for(i=1; (u32)i<db->treehdr.nChunk; i++){
- p = treeShmChunk(db, i);
- aSort[i-1].pShm = p;
- aSort[i-1].iLoc = i;
- if( (u32)i!=db->treehdr.iFirst ){
- if( shm_sequence_ge(p->iShmid, db->treehdr.iNextShmid) ){
- p->iShmid = iPrevShmid--;
- }
- }
- }
- if( iMin!=db->treehdr.iFirst ){
- p = treeShmChunk(db, db->treehdr.iFirst);
- p->iShmid = iPrevShmid;
- }
- }
-
- if( rc==LSM_OK ){
- ShmChunkLoc *aSpace = &aSort[nSort];
- for(i=0; i<nSort; i++){
- if( aSort[i].pShm ){
- assert( shm_sequence_ge(aSort[i].pShm->iShmid, iPrevShmid) );
- assert( aSpace[aSort[i].pShm->iShmid - iPrevShmid].pShm==0 );
- aSpace[aSort[i].pShm->iShmid - iPrevShmid] = aSort[i];
- }
- }
-
- if( aSpace[nSort-1].pShm ) aSpace[nSort-1].pShm->iNext = 0;
- for(i=0; i<nSort-1; i++){
- if( aSpace[i].pShm ){
- aSpace[i].pShm->iNext = aSpace[i+1].iLoc;
- }
- }
-
- rc = treeCheckLinkedList(db);
- lsmFree(db->pEnv, aSort);
- }
- }
-
- return rc;
-}
-
-/*
-** This function is called as part of opening a write-transaction if the
-** writer-flag is already set - indicating that the previous writer
-** failed before ending its transaction.
-*/
-int lsmTreeRepair(lsm_db *db){
- int rc = LSM_OK;
- TreeHeader hdr;
- ShmHeader *pHdr = db->pShmhdr;
-
- /* Ensure that the two tree-headers are consistent. Copy one over the other
- ** if necessary. Prefer the data from a tree-header for which the checksum
- ** computes. Or, if they both compute, prefer tree-header-1. */
- if( memcmp(&pHdr->hdr1, &pHdr->hdr2, sizeof(TreeHeader)) ){
- if( treeHeaderChecksumOk(&pHdr->hdr1) ){
- memcpy(&pHdr->hdr2, &pHdr->hdr1, sizeof(TreeHeader));
- }else{
- memcpy(&pHdr->hdr1, &pHdr->hdr2, sizeof(TreeHeader));
- }
- }
-
- /* Save the connections current copy of the tree-header. It will be
- ** restored before returning. */
- memcpy(&hdr, &db->treehdr, sizeof(TreeHeader));
-
- /* Walk the tree. Zero any v2 pointers with a transaction-id greater than
- ** the transaction-id currently in the tree-headers. */
- rc = treeRepairPtrs(db);
-
- /* Repair the linked list of shared-memory chunks. */
- if( rc==LSM_OK ){
- rc = treeRepairList(db);
- }
-
- memcpy(&db->treehdr, &hdr, sizeof(TreeHeader));
- return rc;
-}
-
-static void treeOverwriteKey(lsm_db *db, TreeCursor *pCsr, u32 iKey, int *pRc){
- if( *pRc==LSM_OK ){
- TreeRoot *p = &db->treehdr.root;
- TreeNode *pNew;
- u32 iNew;
- TreeNode *pNode = pCsr->apTreeNode[pCsr->iNode];
- int iCell = pCsr->aiCell[pCsr->iNode];
-
- /* Create a copy of this node */
- if( (pCsr->iNode>0 && (u32)pCsr->iNode==(p->nHeight-1)) ){
- pNew = copyTreeLeaf(db, (TreeLeaf *)pNode, &iNew, pRc);
- }else{
- pNew = copyTreeNode(db, pNode, &iNew, pRc);
- }
-
- if( pNew ){
- /* Modify the value in the new version */
- pNew->aiKeyPtr[iCell] = iKey;
-
- /* Change the pointer in the parent (if any) to point at the new
- ** TreeNode */
- pCsr->iNode--;
- treeUpdatePtr(db, pCsr, iNew);
- }
- }
-}
-
-static int treeNextIsEndDelete(lsm_db *db, TreeCursor *pCsr){
- int iNode = pCsr->iNode;
- int iCell = pCsr->aiCell[iNode]+1;
-
- /* Cursor currently points to a leaf node. */
- assert( (u32)pCsr->iNode==(db->treehdr.root.nHeight-1) );
-
- while( iNode>=0 ){
- TreeNode *pNode = pCsr->apTreeNode[iNode];
- if( iCell<3 && pNode->aiKeyPtr[iCell] ){
- int rc = LSM_OK;
- TreeKey *pKey = treeShmptr(db, pNode->aiKeyPtr[iCell]);
- assert( rc==LSM_OK );
- return ((pKey->flags & LSM_END_DELETE) ? 1 : 0);
- }
- iNode--;
- iCell = pCsr->aiCell[iNode];
- }
-
- return 0;
-}
-
-static int treePrevIsStartDelete(lsm_db *db, TreeCursor *pCsr){
- int iNode = pCsr->iNode;
-
- /* Cursor currently points to a leaf node. */
- assert( (u32)pCsr->iNode==(db->treehdr.root.nHeight-1) );
-
- while( iNode>=0 ){
- TreeNode *pNode = pCsr->apTreeNode[iNode];
- int iCell = pCsr->aiCell[iNode]-1;
- if( iCell>=0 && pNode->aiKeyPtr[iCell] ){
- int rc = LSM_OK;
- TreeKey *pKey = treeShmptr(db, pNode->aiKeyPtr[iCell]);
- assert( rc==LSM_OK );
- return ((pKey->flags & LSM_START_DELETE) ? 1 : 0);
- }
- iNode--;
- }
-
- return 0;
-}
-
-
-static int treeInsertEntry(
- lsm_db *pDb, /* Database handle */
- int flags, /* Flags associated with entry */
- void *pKey, /* Pointer to key data */
- int nKey, /* Size of key data in bytes */
- void *pVal, /* Pointer to value data (or NULL) */
- int nVal /* Bytes in value data (or -ve for delete) */
-){
- int rc = LSM_OK; /* Return Code */
- TreeKey *pTreeKey; /* New key-value being inserted */
- u32 iTreeKey;
- TreeRoot *p = &pDb->treehdr.root;
- TreeCursor csr; /* Cursor to seek to pKey/nKey */
- int res = 0; /* Result of seek operation on csr */
-
- assert( nVal>=0 || pVal==0 );
- assert_tree_looks_ok(LSM_OK, pTree);
- assert( flags==LSM_INSERT || flags==LSM_POINT_DELETE
- || flags==LSM_START_DELETE || flags==LSM_END_DELETE
- );
- assert( (flags & LSM_CONTIGUOUS)==0 );
-#if 0
- dump_tree_contents(pDb, "before");
-#endif
-
- if( p->iRoot ){
- TreeKey *pRes; /* Key at end of seek operation */
- treeCursorInit(pDb, 0, &csr);
-
- /* Seek to the leaf (or internal node) that the new key belongs on */
- rc = lsmTreeCursorSeek(&csr, pKey, nKey, &res);
- pRes = csrGetKey(&csr, &csr.blob, &rc);
- if( rc!=LSM_OK ) return rc;
- assert( pRes );
-
- if( flags==LSM_START_DELETE ){
- /* When inserting a start-delete-range entry, if the key that
- ** occurs immediately before the new entry is already a START_DELETE,
- ** then the new entry is not required. */
- if( (res<=0 && (pRes->flags & LSM_START_DELETE))
- || (res>0 && treePrevIsStartDelete(pDb, &csr))
- ){
- goto insert_entry_out;
- }
- }else if( flags==LSM_END_DELETE ){
- /* When inserting an start-delete-range entry, if the key that
- ** occurs immediately after the new entry is already an END_DELETE,
- ** then the new entry is not required. */
- if( (res<0 && treeNextIsEndDelete(pDb, &csr))
- || (res>=0 && (pRes->flags & LSM_END_DELETE))
- ){
- goto insert_entry_out;
- }
- }
-
- if( res==0 && (flags & (LSM_END_DELETE|LSM_START_DELETE)) ){
- if( pRes->flags & LSM_INSERT ){
- nVal = pRes->nValue;
- pVal = TKV_VAL(pRes);
- }
- flags = flags | pRes->flags;
- }
-
- if( flags & (LSM_INSERT|LSM_POINT_DELETE) ){
- if( (res<0 && (pRes->flags & LSM_START_DELETE))
- || (res>0 && (pRes->flags & LSM_END_DELETE))
- ){
- flags = flags | (LSM_END_DELETE|LSM_START_DELETE);
- }else if( res==0 ){
- flags = flags | (pRes->flags & (LSM_END_DELETE|LSM_START_DELETE));
- }
- }
- }else{
- memset(&csr, 0, sizeof(TreeCursor));
- }
-
- /* Allocate and populate a new key-value pair structure */
- pTreeKey = newTreeKey(pDb, &iTreeKey, pKey, nKey, pVal, nVal, &rc);
- if( rc!=LSM_OK ) return rc;
- assert( pTreeKey->flags==0 || pTreeKey->flags==LSM_CONTIGUOUS );
- pTreeKey->flags |= flags;
-
- if( p->iRoot==0 ){
- /* The tree is completely empty. Add a new root node and install
- ** (pKey/nKey) as the middle entry. Even though it is a leaf at the
- ** moment, use newTreeNode() to allocate the node (i.e. allocate enough
- ** space for the fields used by interior nodes). This is because the
- ** treeInsert() routine may convert this node to an interior node. */
- TreeNode *pRoot = newTreeNode(pDb, &p->iRoot, &rc);
- if( rc==LSM_OK ){
- assert( p->nHeight==0 );
- pRoot->aiKeyPtr[1] = iTreeKey;
- p->nHeight = 1;
- }
- }else{
- if( res==0 ){
- /* The search found a match within the tree. */
- treeOverwriteKey(pDb, &csr, iTreeKey, &rc);
- }else{
- /* The cursor now points to the leaf node into which the new entry should
- ** be inserted. There may or may not be a free slot within the leaf for
- ** the new key-value pair.
- **
- ** iSlot is set to the index of the key within pLeaf that the new key
- ** should be inserted to the left of (or to a value 1 greater than the
- ** index of the rightmost key if the new key is larger than all keys
- ** currently stored in the node).
- */
- int iSlot = csr.aiCell[csr.iNode] + (res<0);
- if( csr.iNode==0 ){
- rc = treeInsert(pDb, &csr, 0, iTreeKey, 0, iSlot);
- }else{
- rc = treeInsertLeaf(pDb, &csr, iTreeKey, iSlot);
- }
- }
- }
-
-#if 0
- dump_tree_contents(pDb, "after");
-#endif
- insert_entry_out:
- tblobFree(pDb, &csr.blob);
- assert_tree_looks_ok(rc, pTree);
- return rc;
-}
-
-/*
-** Insert a new entry into the in-memory tree.
-**
-** If the value of the 5th parameter, nVal, is negative, then a delete-marker
-** is inserted into the tree. In this case the value pointer, pVal, must be
-** NULL.
-*/
-int lsmTreeInsert(
- lsm_db *pDb, /* Database handle */
- void *pKey, /* Pointer to key data */
- int nKey, /* Size of key data in bytes */
- void *pVal, /* Pointer to value data (or NULL) */
- int nVal /* Bytes in value data (or -ve for delete) */
-){
- int flags;
- if( nVal<0 ){
- flags = LSM_POINT_DELETE;
- }else{
- flags = LSM_INSERT;
- }
-
- return treeInsertEntry(pDb, flags, pKey, nKey, pVal, nVal);
-}
-
-static int treeDeleteEntry(lsm_db *db, TreeCursor *pCsr, u32 iNewptr){
- TreeRoot *p = &db->treehdr.root;
- TreeNode *pNode = pCsr->apTreeNode[pCsr->iNode];
- int iSlot = pCsr->aiCell[pCsr->iNode];
- int bLeaf;
- int rc = LSM_OK;
-
- assert( pNode->aiKeyPtr[1] );
- assert( pNode->aiKeyPtr[iSlot] );
- assert( iSlot==0 || iSlot==1 || iSlot==2 );
- assert( ((u32)pCsr->iNode==(db->treehdr.root.nHeight-1))==(iNewptr==0) );
-
- bLeaf = ((u32)pCsr->iNode==(p->nHeight-1) && p->nHeight>1);
-
- if( pNode->aiKeyPtr[0] || pNode->aiKeyPtr[2] ){
- /* There are currently at least 2 keys on this node. So just create
- ** a new copy of the node with one of the keys removed. If the node
- ** happens to be the root node of the tree, allocate an entire
- ** TreeNode structure instead of just a TreeLeaf. */
- TreeNode *pNew;
- u32 iNew;
-
- if( bLeaf ){
- pNew = (TreeNode *)newTreeLeaf(db, &iNew, &rc);
- }else{
- pNew = newTreeNode(db, &iNew, &rc);
- }
- if( pNew ){
- int i;
- int iOut = 1;
- for(i=0; i<4; i++){
- if( i==iSlot ){
- i++;
- if( bLeaf==0 ) pNew->aiChildPtr[iOut] = iNewptr;
- if( i<3 ) pNew->aiKeyPtr[iOut] = pNode->aiKeyPtr[i];
- iOut++;
- }else if( bLeaf || p->nHeight==1 ){
- if( i<3 && pNode->aiKeyPtr[i] ){
- pNew->aiKeyPtr[iOut++] = pNode->aiKeyPtr[i];
- }
- }else{
- if( getChildPtr(pNode, WORKING_VERSION, i) ){
- pNew->aiChildPtr[iOut] = getChildPtr(pNode, WORKING_VERSION, i);
- if( i<3 ) pNew->aiKeyPtr[iOut] = pNode->aiKeyPtr[i];
- iOut++;
- }
- }
- }
- assert( iOut<=4 );
- assert( bLeaf || pNew->aiChildPtr[0]==0 );
- pCsr->iNode--;
- rc = treeUpdatePtr(db, pCsr, iNew);
- }
-
- }else if( pCsr->iNode==0 ){
- /* Removing the only key in the root node. iNewptr is the new root. */
- assert( iSlot==1 );
- db->treehdr.root.iRoot = iNewptr;
- db->treehdr.root.nHeight--;
-
- }else{
- /* There is only one key on this node and the node is not the root
- ** node. Find a peer for this node. Then redistribute the contents of
- ** the peer and the parent cell between the parent and either one or
- ** two new nodes. */
- TreeNode *pParent; /* Parent tree node */
- int iPSlot;
- u32 iPeer; /* Pointer to peer leaf node */
- int iDir;
- TreeNode *pPeer; /* The peer leaf node */
- TreeNode *pNew1; u32 iNew1; /* First new leaf node */
-
- assert( iSlot==1 );
-
- pParent = pCsr->apTreeNode[pCsr->iNode-1];
- iPSlot = pCsr->aiCell[pCsr->iNode-1];
-
- if( iPSlot>0 && getChildPtr(pParent, WORKING_VERSION, iPSlot-1) ){
- iDir = -1;
- }else{
- iDir = +1;
- }
- iPeer = getChildPtr(pParent, WORKING_VERSION, iPSlot+iDir);
- pPeer = (TreeNode *)treeShmptr(db, iPeer);
- assertIsWorkingChild(db, pNode, pParent, iPSlot);
-
- /* Allocate the first new leaf node. This is always required. */
- if( bLeaf ){
- pNew1 = (TreeNode *)newTreeLeaf(db, &iNew1, &rc);
- }else{
- pNew1 = (TreeNode *)newTreeNode(db, &iNew1, &rc);
- }
-
- if( pPeer->aiKeyPtr[0] && pPeer->aiKeyPtr[2] ){
- /* Peer node is completely full. This means that two new leaf nodes
- ** and a new parent node are required. */
-
- TreeNode *pNew2; u32 iNew2; /* Second new leaf node */
- TreeNode *pNewP; u32 iNewP; /* New parent node */
-
- if( bLeaf ){
- pNew2 = (TreeNode *)newTreeLeaf(db, &iNew2, &rc);
- }else{
- pNew2 = (TreeNode *)newTreeNode(db, &iNew2, &rc);
- }
- pNewP = copyTreeNode(db, pParent, &iNewP, &rc);
-
- if( iDir==-1 ){
- pNew1->aiKeyPtr[1] = pPeer->aiKeyPtr[0];
- if( bLeaf==0 ){
- pNew1->aiChildPtr[1] = getChildPtr(pPeer, WORKING_VERSION, 0);
- pNew1->aiChildPtr[2] = getChildPtr(pPeer, WORKING_VERSION, 1);
- }
-
- pNewP->aiChildPtr[iPSlot-1] = iNew1;
- pNewP->aiKeyPtr[iPSlot-1] = pPeer->aiKeyPtr[1];
- pNewP->aiChildPtr[iPSlot] = iNew2;
-
- pNew2->aiKeyPtr[0] = pPeer->aiKeyPtr[2];
- pNew2->aiKeyPtr[1] = pParent->aiKeyPtr[iPSlot-1];
- if( bLeaf==0 ){
- pNew2->aiChildPtr[0] = getChildPtr(pPeer, WORKING_VERSION, 2);
- pNew2->aiChildPtr[1] = getChildPtr(pPeer, WORKING_VERSION, 3);
- pNew2->aiChildPtr[2] = iNewptr;
- }
- }else{
- pNew1->aiKeyPtr[1] = pParent->aiKeyPtr[iPSlot];
- if( bLeaf==0 ){
- pNew1->aiChildPtr[1] = iNewptr;
- pNew1->aiChildPtr[2] = getChildPtr(pPeer, WORKING_VERSION, 0);
- }
-
- pNewP->aiChildPtr[iPSlot] = iNew1;
- pNewP->aiKeyPtr[iPSlot] = pPeer->aiKeyPtr[0];
- pNewP->aiChildPtr[iPSlot+1] = iNew2;
-
- pNew2->aiKeyPtr[0] = pPeer->aiKeyPtr[1];
- pNew2->aiKeyPtr[1] = pPeer->aiKeyPtr[2];
- if( bLeaf==0 ){
- pNew2->aiChildPtr[0] = getChildPtr(pPeer, WORKING_VERSION, 1);
- pNew2->aiChildPtr[1] = getChildPtr(pPeer, WORKING_VERSION, 2);
- pNew2->aiChildPtr[2] = getChildPtr(pPeer, WORKING_VERSION, 3);
- }
- }
- assert( pCsr->iNode>=1 );
- pCsr->iNode -= 2;
- if( rc==LSM_OK ){
- assert( pNew1->aiKeyPtr[1] && pNew2->aiKeyPtr[1] );
- rc = treeUpdatePtr(db, pCsr, iNewP);
- }
- }else{
- int iKOut = 0;
- int iPOut = 0;
- int i;
-
- pCsr->iNode--;
-
- if( iDir==1 ){
- pNew1->aiKeyPtr[iKOut++] = pParent->aiKeyPtr[iPSlot];
- if( bLeaf==0 ) pNew1->aiChildPtr[iPOut++] = iNewptr;
- }
- for(i=0; i<3; i++){
- if( pPeer->aiKeyPtr[i] ){
- pNew1->aiKeyPtr[iKOut++] = pPeer->aiKeyPtr[i];
- }
- }
- if( bLeaf==0 ){
- for(i=0; i<4; i++){
- if( getChildPtr(pPeer, WORKING_VERSION, i) ){
- pNew1->aiChildPtr[iPOut++] = getChildPtr(pPeer, WORKING_VERSION, i);
- }
- }
- }
- if( iDir==-1 ){
- iPSlot--;
- pNew1->aiKeyPtr[iKOut++] = pParent->aiKeyPtr[iPSlot];
- if( bLeaf==0 ) pNew1->aiChildPtr[iPOut++] = iNewptr;
- pCsr->aiCell[pCsr->iNode] = (u8)iPSlot;
- }
-
- rc = treeDeleteEntry(db, pCsr, iNew1);
- }
- }
-
- return rc;
-}
-
-/*
-** Delete a range of keys from the tree structure (i.e. the lsm_delete_range()
-** function, not lsm_delete()).
-**
-** This is a two step process:
-**
-** 1) Remove all entries currently stored in the tree that have keys
-** that fall into the deleted range.
-**
-** TODO: There are surely good ways to optimize this step - removing
-** a range of keys from a b-tree. But for now, this function removes
-** them one at a time using the usual approach.
-**
-** 2) Unless the largest key smaller than or equal to (pKey1/nKey1) is
-** already marked as START_DELETE, insert a START_DELETE key.
-** Similarly, unless the smallest key greater than or equal to
-** (pKey2/nKey2) is already START_END, insert a START_END key.
-*/
-int lsmTreeDelete(
- lsm_db *db,
- void *pKey1, int nKey1, /* Start of range */
- void *pKey2, int nKey2 /* End of range */
-){
- int rc = LSM_OK;
- int bDone = 0;
- TreeRoot *p = &db->treehdr.root;
- TreeBlob blob = {0, 0};
-
- /* The range must be sensible - that (key1 < key2). */
- assert( treeKeycmp(pKey1, nKey1, pKey2, nKey2)<0 );
- assert( assert_delete_ranges_match(db) );
-
-#if 0
- static int nCall = 0;
- printf("\n");
- nCall++;
- printf("%d delete %s .. %s\n", nCall, (char *)pKey1, (char *)pKey2);
- dump_tree_contents(db, "before delete");
-#endif
-
- /* Step 1. This loop runs until the tree contains no keys within the
- ** range being deleted. Or until an error occurs. */
- while( bDone==0 && rc==LSM_OK ){
- int res;
- TreeCursor csr; /* Cursor to seek to first key in range */
- void *pDel; int nDel; /* Key to (possibly) delete this iteration */
-#ifndef NDEBUG
- int nEntry = treeCountEntries(db);
-#endif
-
- /* Seek the cursor to the first entry in the tree greater than pKey1. */
- treeCursorInit(db, 0, &csr);
- lsmTreeCursorSeek(&csr, pKey1, nKey1, &res);
- if( res<=0 && lsmTreeCursorValid(&csr) ) lsmTreeCursorNext(&csr);
-
- /* If there is no such entry, or if it is greater than pKey2, then the
- ** tree now contains no keys in the range being deleted. In this case
- ** break out of the loop. */
- bDone = 1;
- if( lsmTreeCursorValid(&csr) ){
- lsmTreeCursorKey(&csr, 0, &pDel, &nDel);
- if( treeKeycmp(pDel, nDel, pKey2, nKey2)<0 ) bDone = 0;
- }
-
- if( bDone==0 ){
- if( (u32)csr.iNode==(p->nHeight-1) ){
- /* The element to delete already lies on a leaf node */
- rc = treeDeleteEntry(db, &csr, 0);
- }else{
- /* 1. Overwrite the current key with a copy of the next key in the
- ** tree (key N).
- **
- ** 2. Seek to key N (cursor will stop at the internal node copy of
- ** N). Move to the next key (original copy of N). Delete
- ** this entry.
- */
- u32 iKey;
- TreeKey *pKey;
- int iNode = csr.iNode;
- lsmTreeCursorNext(&csr);
- assert( (u32)csr.iNode==(p->nHeight-1) );
-
- iKey = csr.apTreeNode[csr.iNode]->aiKeyPtr[csr.aiCell[csr.iNode]];
- lsmTreeCursorPrev(&csr);
-
- treeOverwriteKey(db, &csr, iKey, &rc);
- pKey = treeShmkey(db, iKey, TKV_LOADKEY, &blob, &rc);
- if( pKey ){
- rc = lsmTreeCursorSeek(&csr, TKV_KEY(pKey), pKey->nKey, &res);
- }
- if( rc==LSM_OK ){
- assert( res==0 && csr.iNode==iNode );
- rc = lsmTreeCursorNext(&csr);
- if( rc==LSM_OK ){
- rc = treeDeleteEntry(db, &csr, 0);
- }
- }
- }
- }
-
- /* Clean up any memory allocated by the cursor. */
- tblobFree(db, &csr.blob);
-#if 0
- dump_tree_contents(db, "ddd delete");
-#endif
- assert( bDone || treeCountEntries(db)==(nEntry-1) );
- }
-
-#if 0
- dump_tree_contents(db, "during delete");
-#endif
-
- /* Now insert the START_DELETE and END_DELETE keys. */
- if( rc==LSM_OK ){
- rc = treeInsertEntry(db, LSM_START_DELETE, pKey1, nKey1, 0, -1);
- }
-#if 0
- dump_tree_contents(db, "during delete 2");
-#endif
- if( rc==LSM_OK ){
- rc = treeInsertEntry(db, LSM_END_DELETE, pKey2, nKey2, 0, -1);
- }
-
-#if 0
- dump_tree_contents(db, "after delete");
-#endif
-
- tblobFree(db, &blob);
- assert( assert_delete_ranges_match(db) );
- return rc;
-}
-
-/*
-** Return, in bytes, the amount of memory currently used by the tree
-** structure.
-*/
-int lsmTreeSize(lsm_db *pDb){
- return pDb->treehdr.root.nByte;
-}
-
-/*
-** Open a cursor on the in-memory tree pTree.
-*/
-int lsmTreeCursorNew(lsm_db *pDb, int bOld, TreeCursor **ppCsr){
- TreeCursor *pCsr;
- *ppCsr = pCsr = lsmMalloc(pDb->pEnv, sizeof(TreeCursor));
- if( pCsr ){
- treeCursorInit(pDb, bOld, pCsr);
- return LSM_OK;
- }
- return LSM_NOMEM_BKPT;
-}
-
-/*
-** Close an in-memory tree cursor.
-*/
-void lsmTreeCursorDestroy(TreeCursor *pCsr){
- if( pCsr ){
- tblobFree(pCsr->pDb, &pCsr->blob);
- lsmFree(pCsr->pDb->pEnv, pCsr);
- }
-}
-
-void lsmTreeCursorReset(TreeCursor *pCsr){
- if( pCsr ){
- pCsr->iNode = -1;
- pCsr->pSave = 0;
- }
-}
-
-#ifndef NDEBUG
-static int treeCsrCompare(TreeCursor *pCsr, void *pKey, int nKey, int *pRc){
- TreeKey *p;
- int cmp = 0;
- assert( pCsr->iNode>=0 );
- p = csrGetKey(pCsr, &pCsr->blob, pRc);
- if( p ){
- cmp = treeKeycmp(TKV_KEY(p), p->nKey, pKey, nKey);
- }
- return cmp;
-}
-#endif
-
-
-/*
-** Attempt to seek the cursor passed as the first argument to key (pKey/nKey)
-** in the tree structure. If an exact match for the key is found, leave the
-** cursor pointing to it and set *pRes to zero before returning. If an
-** exact match cannot be found, do one of the following:
-**
-** * Leave the cursor pointing to the smallest element in the tree that
-** is larger than the key and set *pRes to +1, or
-**
-** * Leave the cursor pointing to the largest element in the tree that
-** is smaller than the key and set *pRes to -1, or
-**
-** * If the tree is empty, leave the cursor at EOF and set *pRes to -1.
-*/
-int lsmTreeCursorSeek(TreeCursor *pCsr, void *pKey, int nKey, int *pRes){
- int rc = LSM_OK; /* Return code */
- lsm_db *pDb = pCsr->pDb;
- TreeRoot *pRoot = pCsr->pRoot;
- u32 iNodePtr; /* Location of current node in search */
-
- /* Discard any saved position data */
- treeCursorRestore(pCsr, 0);
-
- iNodePtr = pRoot->iRoot;
- if( iNodePtr==0 ){
- /* Either an error occurred or the tree is completely empty. */
- assert( rc!=LSM_OK || pRoot->iRoot==0 );
- *pRes = -1;
- pCsr->iNode = -1;
- }else{
- TreeBlob b = {0, 0};
- int res = 0; /* Result of comparison function */
- int iNode = -1;
- while( iNodePtr ){
- TreeNode *pNode; /* Node at location iNodePtr */
- int iTest; /* Index of second key to test (0 or 2) */
- u32 iTreeKey;
- TreeKey *pTreeKey; /* Key to compare against */
-
- pNode = (TreeNode *)treeShmptrUnsafe(pDb, iNodePtr);
- iNode++;
- pCsr->apTreeNode[iNode] = pNode;
-
- /* Compare (pKey/nKey) with the key in the middle slot of B-tree node
- ** pNode. The middle slot is never empty. If the comparison is a match,
- ** then the search is finished. Break out of the loop. */
- pTreeKey = (TreeKey*)treeShmptrUnsafe(pDb, pNode->aiKeyPtr[1]);
- if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){
- pTreeKey = treeShmkey(pDb, pNode->aiKeyPtr[1], TKV_LOADKEY, &b, &rc);
- if( rc!=LSM_OK ) break;
- }
- res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey);
- if( res==0 ){
- pCsr->aiCell[iNode] = 1;
- break;
- }
-
- /* Based on the results of the previous comparison, compare (pKey/nKey)
- ** to either the left or right key of the B-tree node, if such a key
- ** exists. */
- iTest = (res>0 ? 0 : 2);
- iTreeKey = pNode->aiKeyPtr[iTest];
- if( iTreeKey ){
- pTreeKey = (TreeKey*)treeShmptrUnsafe(pDb, iTreeKey);
- if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){
- pTreeKey = treeShmkey(pDb, iTreeKey, TKV_LOADKEY, &b, &rc);
- if( rc ) break;
- }
- res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey);
- if( res==0 ){
- pCsr->aiCell[iNode] = (u8)iTest;
- break;
- }
- }else{
- iTest = 1;
- }
-
- if( (u32)iNode<(pRoot->nHeight-1) ){
- iNodePtr = getChildPtr(pNode, pRoot->iTransId, iTest + (res<0));
- }else{
- iNodePtr = 0;
- }
- pCsr->aiCell[iNode] = (u8)(iTest + (iNodePtr && (res<0)));
- }
-
- *pRes = res;
- pCsr->iNode = iNode;
- tblobFree(pDb, &b);
- }
-
- /* assert() that *pRes has been set properly */
-#ifndef NDEBUG
- if( rc==LSM_OK && lsmTreeCursorValid(pCsr) ){
- int cmp = treeCsrCompare(pCsr, pKey, nKey, &rc);
- assert( rc!=LSM_OK || *pRes==cmp || (*pRes ^ cmp)>0 );
- }
-#endif
-
- return rc;
-}
-
-int lsmTreeCursorNext(TreeCursor *pCsr){
-#ifndef NDEBUG
- TreeKey *pK1;
- TreeBlob key1 = {0, 0};
-#endif
- lsm_db *pDb = pCsr->pDb;
- TreeRoot *pRoot = pCsr->pRoot;
- const int iLeaf = pRoot->nHeight-1;
- int iCell;
- int rc = LSM_OK;
- TreeNode *pNode;
-
- /* Restore the cursor position, if required */
- int iRestore = 0;
- treeCursorRestore(pCsr, &iRestore);
- if( iRestore>0 ) return LSM_OK;
-
- /* Save a pointer to the current key. This is used in an assert() at the
- ** end of this function - to check that the 'next' key really is larger
- ** than the current key. */
-#ifndef NDEBUG
- pK1 = csrGetKey(pCsr, &key1, &rc);
- if( rc!=LSM_OK ) return rc;
-#endif
-
- assert( lsmTreeCursorValid(pCsr) );
- assert( pCsr->aiCell[pCsr->iNode]<3 );
-
- pNode = pCsr->apTreeNode[pCsr->iNode];
- iCell = ++pCsr->aiCell[pCsr->iNode];
-
- /* If the current node is not a leaf, and the current cell has sub-tree
- ** associated with it, descend to the left-most key on the left-most
- ** leaf of the sub-tree. */
- if( pCsr->iNode<iLeaf && getChildPtr(pNode, pRoot->iTransId, iCell) ){
- do {
- u32 iNodePtr;
- pCsr->iNode++;
- iNodePtr = getChildPtr(pNode, pRoot->iTransId, iCell);
- pNode = (TreeNode *)treeShmptr(pDb, iNodePtr);
- pCsr->apTreeNode[pCsr->iNode] = pNode;
- iCell = pCsr->aiCell[pCsr->iNode] = (pNode->aiKeyPtr[0]==0);
- }while( pCsr->iNode < iLeaf );
- }
-
- /* Otherwise, the next key is found by following pointer up the tree
- ** until there is a key immediately to the right of the pointer followed
- ** to reach the sub-tree containing the current key. */
- else if( iCell>=3 || pNode->aiKeyPtr[iCell]==0 ){
- while( (--pCsr->iNode)>=0 ){
- iCell = pCsr->aiCell[pCsr->iNode];
- if( iCell<3 && pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[iCell] ) break;
- }
- }
-
-#ifndef NDEBUG
- if( pCsr->iNode>=0 ){
- TreeKey *pK2 = csrGetKey(pCsr, &pCsr->blob, &rc);
- assert( rc||treeKeycmp(TKV_KEY(pK2),pK2->nKey,TKV_KEY(pK1),pK1->nKey)>=0 );
- }
- tblobFree(pDb, &key1);
-#endif
-
- return rc;
-}
-
-int lsmTreeCursorPrev(TreeCursor *pCsr){
-#ifndef NDEBUG
- TreeKey *pK1;
- TreeBlob key1 = {0, 0};
-#endif
- lsm_db *pDb = pCsr->pDb;
- TreeRoot *pRoot = pCsr->pRoot;
- const int iLeaf = pRoot->nHeight-1;
- int iCell;
- int rc = LSM_OK;
- TreeNode *pNode;
-
- /* Restore the cursor position, if required */
- int iRestore = 0;
- treeCursorRestore(pCsr, &iRestore);
- if( iRestore<0 ) return LSM_OK;
-
- /* Save a pointer to the current key. This is used in an assert() at the
- ** end of this function - to check that the 'next' key really is smaller
- ** than the current key. */
-#ifndef NDEBUG
- pK1 = csrGetKey(pCsr, &key1, &rc);
- if( rc!=LSM_OK ) return rc;
-#endif
-
- assert( lsmTreeCursorValid(pCsr) );
- pNode = pCsr->apTreeNode[pCsr->iNode];
- iCell = pCsr->aiCell[pCsr->iNode];
- assert( iCell>=0 && iCell<3 );
-
- /* If the current node is not a leaf, and the current cell has sub-tree
- ** associated with it, descend to the right-most key on the right-most
- ** leaf of the sub-tree. */
- if( pCsr->iNode<iLeaf && getChildPtr(pNode, pRoot->iTransId, iCell) ){
- do {
- u32 iNodePtr;
- pCsr->iNode++;
- iNodePtr = getChildPtr(pNode, pRoot->iTransId, iCell);
- pNode = (TreeNode *)treeShmptr(pDb, iNodePtr);
- if( rc!=LSM_OK ) break;
- pCsr->apTreeNode[pCsr->iNode] = pNode;
- iCell = 1 + (pNode->aiKeyPtr[2]!=0) + (pCsr->iNode < iLeaf);
- pCsr->aiCell[pCsr->iNode] = (u8)iCell;
- }while( pCsr->iNode < iLeaf );
- }
-
- /* Otherwise, the next key is found by following pointer up the tree until
- ** there is a key immediately to the left of the pointer followed to reach
- ** the sub-tree containing the current key. */
- else{
- do {
- iCell = pCsr->aiCell[pCsr->iNode]-1;
- if( iCell>=0 && pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[iCell] ) break;
- }while( (--pCsr->iNode)>=0 );
- pCsr->aiCell[pCsr->iNode] = (u8)iCell;
- }
-
-#ifndef NDEBUG
- if( pCsr->iNode>=0 ){
- TreeKey *pK2 = csrGetKey(pCsr, &pCsr->blob, &rc);
- assert( rc || treeKeycmp(TKV_KEY(pK2),pK2->nKey,TKV_KEY(pK1),pK1->nKey)<0 );
- }
- tblobFree(pDb, &key1);
-#endif
-
- return rc;
-}
-
-/*
-** Move the cursor to the first (bLast==0) or last (bLast!=0) entry in the
-** in-memory tree.
-*/
-int lsmTreeCursorEnd(TreeCursor *pCsr, int bLast){
- lsm_db *pDb = pCsr->pDb;
- TreeRoot *pRoot = pCsr->pRoot;
- int rc = LSM_OK;
-
- u32 iNodePtr;
- pCsr->iNode = -1;
-
- /* Discard any saved position data */
- treeCursorRestore(pCsr, 0);
-
- iNodePtr = pRoot->iRoot;
- while( iNodePtr ){
- int iCell;
- TreeNode *pNode;
-
- pNode = (TreeNode *)treeShmptr(pDb, iNodePtr);
- if( rc ) break;
-
- if( bLast ){
- iCell = ((pNode->aiKeyPtr[2]==0) ? 2 : 3);
- }else{
- iCell = ((pNode->aiKeyPtr[0]==0) ? 1 : 0);
- }
- pCsr->iNode++;
- pCsr->apTreeNode[pCsr->iNode] = pNode;
-
- if( (u32)pCsr->iNode<pRoot->nHeight-1 ){
- iNodePtr = getChildPtr(pNode, pRoot->iTransId, iCell);
- }else{
- iNodePtr = 0;
- }
- pCsr->aiCell[pCsr->iNode] = (u8)(iCell - (iNodePtr==0 && bLast));
- }
-
- return rc;
-}
-
-int lsmTreeCursorFlags(TreeCursor *pCsr){
- int flags = 0;
- if( pCsr && pCsr->iNode>=0 ){
- int rc = LSM_OK;
- TreeKey *pKey = (TreeKey *)treeShmptrUnsafe(pCsr->pDb,
- pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]]
- );
- assert( rc==LSM_OK );
- flags = (pKey->flags & ~LSM_CONTIGUOUS);
- }
- return flags;
-}
-
-int lsmTreeCursorKey(TreeCursor *pCsr, int *pFlags, void **ppKey, int *pnKey){
- TreeKey *pTreeKey;
- int rc = LSM_OK;
-
- assert( lsmTreeCursorValid(pCsr) );
-
- pTreeKey = pCsr->pSave;
- if( !pTreeKey ){
- pTreeKey = csrGetKey(pCsr, &pCsr->blob, &rc);
- }
- if( rc==LSM_OK ){
- *pnKey = pTreeKey->nKey;
- if( pFlags ) *pFlags = pTreeKey->flags;
- *ppKey = (void *)&pTreeKey[1];
- }
-
- return rc;
-}
-
-int lsmTreeCursorValue(TreeCursor *pCsr, void **ppVal, int *pnVal){
- int res = 0;
- int rc;
-
- rc = treeCursorRestore(pCsr, &res);
- if( res==0 ){
- TreeKey *pTreeKey = csrGetKey(pCsr, &pCsr->blob, &rc);
- if( rc==LSM_OK ){
- if( pTreeKey->flags & LSM_INSERT ){
- *pnVal = pTreeKey->nValue;
- *ppVal = TKV_VAL(pTreeKey);
- }else{
- *ppVal = 0;
- *pnVal = -1;
- }
- }
- }else{
- *ppVal = 0;
- *pnVal = 0;
- }
-
- return rc;
-}
-
-/*
-** Return true if the cursor currently points to a valid entry.
-*/
-int lsmTreeCursorValid(TreeCursor *pCsr){
- return (pCsr && (pCsr->pSave || pCsr->iNode>=0));
-}
-
-/*
-** Store a mark in *pMark. Later on, a call to lsmTreeRollback() with a
-** pointer to the same TreeMark structure may be used to roll the tree
-** contents back to their current state.
-*/
-void lsmTreeMark(lsm_db *pDb, TreeMark *pMark){
- pMark->iRoot = pDb->treehdr.root.iRoot;
- pMark->nHeight = pDb->treehdr.root.nHeight;
- pMark->iWrite = pDb->treehdr.iWrite;
- pMark->nChunk = pDb->treehdr.nChunk;
- pMark->iNextShmid = pDb->treehdr.iNextShmid;
- pMark->iRollback = intArraySize(&pDb->rollback);
-}
-
-/*
-** Roll back to mark pMark. Structure *pMark should have been previously
-** populated by a call to lsmTreeMark().
-*/
-void lsmTreeRollback(lsm_db *pDb, TreeMark *pMark){
- int iIdx;
- int nIdx;
- u32 iNext;
- ShmChunk *pChunk;
- u32 iChunk;
- u32 iShmid;
-
- /* Revert all required v2 pointers. */
- nIdx = intArraySize(&pDb->rollback);
- for(iIdx = pMark->iRollback; iIdx<nIdx; iIdx++){
- TreeNode *pNode;
- pNode = treeShmptr(pDb, intArrayEntry(&pDb->rollback, iIdx));
- assert( pNode );
- pNode->iV2 = 0;
- pNode->iV2Child = 0;
- pNode->iV2Ptr = 0;
- }
- intArrayTruncate(&pDb->rollback, pMark->iRollback);
-
- /* Restore the free-chunk list. */
- assert( pMark->iWrite!=0 );
- iChunk = treeOffsetToChunk(pMark->iWrite-1);
- pChunk = treeShmChunk(pDb, iChunk);
- iNext = pChunk->iNext;
- pChunk->iNext = 0;
-
- pChunk = treeShmChunk(pDb, pDb->treehdr.iFirst);
- iShmid = pChunk->iShmid-1;
-
- while( iNext ){
- u32 iFree = iNext; /* Current chunk being rollback-freed */
- ShmChunk *pFree; /* Pointer to chunk iFree */
-
- pFree = treeShmChunk(pDb, iFree);
- iNext = pFree->iNext;
-
- if( iFree<pMark->nChunk ){
- pFree->iNext = pDb->treehdr.iFirst;
- pFree->iShmid = iShmid--;
- pDb->treehdr.iFirst = iFree;
- }
- }
-
- /* Restore the tree-header fields */
- pDb->treehdr.root.iRoot = pMark->iRoot;
- pDb->treehdr.root.nHeight = pMark->nHeight;
- pDb->treehdr.iWrite = pMark->iWrite;
- pDb->treehdr.nChunk = pMark->nChunk;
- pDb->treehdr.iNextShmid = pMark->iNextShmid;
-}
-
-/*
-** Load the in-memory tree header from shared-memory into pDb->treehdr.
-** If the header cannot be loaded, return LSM_PROTOCOL.
-**
-** If the header is successfully loaded and parameter piRead is not NULL,
-** is is set to 1 if the header was loaded from ShmHeader.hdr1, or 2 if
-** the header was loaded from ShmHeader.hdr2.
-*/
-int lsmTreeLoadHeader(lsm_db *pDb, int *piRead){
- int nRem = LSM_ATTEMPTS_BEFORE_PROTOCOL;
- while( (nRem--)>0 ){
- ShmHeader *pShm = pDb->pShmhdr;
-
- memcpy(&pDb->treehdr, &pShm->hdr1, sizeof(TreeHeader));
- if( treeHeaderChecksumOk(&pDb->treehdr) ){
- if( piRead ) *piRead = 1;
- return LSM_OK;
- }
- memcpy(&pDb->treehdr, &pShm->hdr2, sizeof(TreeHeader));
- if( treeHeaderChecksumOk(&pDb->treehdr) ){
- if( piRead ) *piRead = 2;
- return LSM_OK;
- }
-
- lsmShmBarrier(pDb);
- }
- return LSM_PROTOCOL_BKPT;
-}
-
-int lsmTreeLoadHeaderOk(lsm_db *pDb, int iRead){
- TreeHeader *p = (iRead==1) ? &pDb->pShmhdr->hdr1 : &pDb->pShmhdr->hdr2;
- assert( iRead==1 || iRead==2 );
- return (0==memcmp(pDb->treehdr.aCksum, p->aCksum, sizeof(u32)*2));
-}
-
-/*
-** This function is called to conclude a transaction. If argument bCommit
-** is true, the transaction is committed. Otherwise it is rolled back.
-*/
-int lsmTreeEndTransaction(lsm_db *pDb, int bCommit){
- ShmHeader *pShm = pDb->pShmhdr;
-
- treeHeaderChecksum(&pDb->treehdr, pDb->treehdr.aCksum);
- memcpy(&pShm->hdr2, &pDb->treehdr, sizeof(TreeHeader));
- lsmShmBarrier(pDb);
- memcpy(&pShm->hdr1, &pDb->treehdr, sizeof(TreeHeader));
- pShm->bWriter = 0;
- intArrayFree(pDb->pEnv, &pDb->rollback);
-
- return LSM_OK;
-}
-
-#ifndef NDEBUG
-static int assert_delete_ranges_match(lsm_db *db){
- int prev = 0;
- TreeBlob blob = {0, 0};
- TreeCursor csr; /* Cursor used to iterate through tree */
- int rc;
-
- treeCursorInit(db, 0, &csr);
- for( rc = lsmTreeCursorEnd(&csr, 0);
- rc==LSM_OK && lsmTreeCursorValid(&csr);
- rc = lsmTreeCursorNext(&csr)
- ){
- TreeKey *pKey = csrGetKey(&csr, &blob, &rc);
- if( rc!=LSM_OK ) break;
- assert( ((prev&LSM_START_DELETE)==0)==((pKey->flags&LSM_END_DELETE)==0) );
- prev = pKey->flags;
- }
-
- tblobFree(csr.pDb, &csr.blob);
- tblobFree(csr.pDb, &blob);
-
- return 1;
-}
-
-static int treeCountEntries(lsm_db *db){
- TreeCursor csr; /* Cursor used to iterate through tree */
- int rc;
- int nEntry = 0;
-
- treeCursorInit(db, 0, &csr);
- for( rc = lsmTreeCursorEnd(&csr, 0);
- rc==LSM_OK && lsmTreeCursorValid(&csr);
- rc = lsmTreeCursorNext(&csr)
- ){
- nEntry++;
- }
-
- tblobFree(csr.pDb, &csr.blob);
-
- return nEntry;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_unix.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_unix.c
deleted file mode 100644
index 22240771ea6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_unix.c
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
-** 2011-12-03
-**
-** 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.
-**
-*************************************************************************
-**
-** Unix-specific run-time environment implementation for LSM.
-*/
-
-#ifndef _WIN32
-
-#if defined(__GNUC__) || defined(__TINYC__)
-/* workaround for ftruncate() visibility on gcc. */
-# ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 500
-# endif
-#endif
-
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <string.h>
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/mman.h>
-#include "lsmInt.h"
-
-/* There is no fdatasync() call on Android */
-#ifdef __ANDROID__
-# define fdatasync(x) fsync(x)
-#endif
-
-/*
-** An open file is an instance of the following object
-*/
-typedef struct PosixFile PosixFile;
-struct PosixFile {
- lsm_env *pEnv; /* The run-time environment */
- const char *zName; /* Full path to file */
- int fd; /* The open file descriptor */
- int shmfd; /* Shared memory file-descriptor */
- void *pMap; /* Pointer to mapping of file fd */
- off_t nMap; /* Size of mapping at pMap in bytes */
- int nShm; /* Number of entries in array apShm[] */
- void **apShm; /* Array of 32K shared memory segments */
-};
-
-static char *posixShmFile(PosixFile *p){
- char *zShm;
- int nName = strlen(p->zName);
- zShm = (char *)lsmMalloc(p->pEnv, nName+4+1);
- if( zShm ){
- memcpy(zShm, p->zName, nName);
- memcpy(&zShm[nName], "-shm", 5);
- }
- return zShm;
-}
-
-static int lsmPosixOsOpen(
- lsm_env *pEnv,
- const char *zFile,
- int flags,
- lsm_file **ppFile
-){
- int rc = LSM_OK;
- PosixFile *p;
-
- p = lsm_malloc(pEnv, sizeof(PosixFile));
- if( p==0 ){
- rc = LSM_NOMEM;
- }else{
- int bReadonly = (flags & LSM_OPEN_READONLY);
- int oflags = (bReadonly ? O_RDONLY : (O_RDWR|O_CREAT));
- memset(p, 0, sizeof(PosixFile));
- p->zName = zFile;
- p->pEnv = pEnv;
- p->fd = open(zFile, oflags, 0644);
- if( p->fd<0 ){
- lsm_free(pEnv, p);
- p = 0;
- if( errno==ENOENT ){
- rc = lsmErrorBkpt(LSM_IOERR_NOENT);
- }else{
- rc = LSM_IOERR_BKPT;
- }
- }
- }
-
- *ppFile = (lsm_file *)p;
- return rc;
-}
-
-static int lsmPosixOsWrite(
- lsm_file *pFile, /* File to write to */
- lsm_i64 iOff, /* Offset to write to */
- void *pData, /* Write data from this buffer */
- int nData /* Bytes of data to write */
-){
- int rc = LSM_OK;
- PosixFile *p = (PosixFile *)pFile;
- off_t offset;
-
- offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
- if( offset!=iOff ){
- rc = LSM_IOERR_BKPT;
- }else{
- ssize_t prc = write(p->fd, pData, (size_t)nData);
- if( prc<0 ) rc = LSM_IOERR_BKPT;
- }
-
- return rc;
-}
-
-static int lsmPosixOsTruncate(
- lsm_file *pFile, /* File to write to */
- lsm_i64 nSize /* Size to truncate file to */
-){
- PosixFile *p = (PosixFile *)pFile;
- int rc = LSM_OK; /* Return code */
- int prc; /* Posix Return Code */
- struct stat sStat; /* Result of fstat() invocation */
-
- prc = fstat(p->fd, &sStat);
- if( prc==0 && sStat.st_size>nSize ){
- prc = ftruncate(p->fd, (off_t)nSize);
- }
- if( prc<0 ) rc = LSM_IOERR_BKPT;
-
- return rc;
-}
-
-static int lsmPosixOsRead(
- lsm_file *pFile, /* File to read from */
- lsm_i64 iOff, /* Offset to read from */
- void *pData, /* Read data into this buffer */
- int nData /* Bytes of data to read */
-){
- int rc = LSM_OK;
- PosixFile *p = (PosixFile *)pFile;
- off_t offset;
-
- offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
- if( offset!=iOff ){
- rc = LSM_IOERR_BKPT;
- }else{
- ssize_t prc = read(p->fd, pData, (size_t)nData);
- if( prc<0 ){
- rc = LSM_IOERR_BKPT;
- }else if( prc<nData ){
- memset(&((u8 *)pData)[prc], 0, nData - prc);
- }
-
- }
-
- return rc;
-}
-
-static int lsmPosixOsSync(lsm_file *pFile){
- int rc = LSM_OK;
-
-#ifndef LSM_NO_SYNC
- PosixFile *p = (PosixFile *)pFile;
- int prc = 0;
-
- if( p->pMap ){
- prc = msync(p->pMap, p->nMap, MS_SYNC);
- }
- if( prc==0 ) prc = fdatasync(p->fd);
- if( prc<0 ) rc = LSM_IOERR_BKPT;
-#else
- (void)pFile;
-#endif
-
- return rc;
-}
-
-static int lsmPosixOsSectorSize(lsm_file *pFile){
- return 512;
-}
-
-static int lsmPosixOsRemap(
- lsm_file *pFile,
- lsm_i64 iMin,
- void **ppOut,
- lsm_i64 *pnOut
-){
- off_t iSz;
- int prc;
- PosixFile *p = (PosixFile *)pFile;
- struct stat buf;
-
- /* If the file is between 0 and 2MB in size, extend it in chunks of 256K.
- ** Thereafter, in chunks of 1MB at a time. */
- const int aIncrSz[] = {256*1024, 1024*1024};
- int nIncrSz = aIncrSz[iMin>(2*1024*1024)];
-
- if( p->pMap ){
- munmap(p->pMap, p->nMap);
- *ppOut = p->pMap = 0;
- *pnOut = p->nMap = 0;
- }
-
- if( iMin>=0 ){
- memset(&buf, 0, sizeof(buf));
- prc = fstat(p->fd, &buf);
- if( prc!=0 ) return LSM_IOERR_BKPT;
- iSz = buf.st_size;
- if( iSz<iMin ){
- iSz = ((iMin + nIncrSz-1) / nIncrSz) * nIncrSz;
- prc = ftruncate(p->fd, iSz);
- if( prc!=0 ) return LSM_IOERR_BKPT;
- }
-
- p->pMap = mmap(0, iSz, PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0);
- p->nMap = iSz;
- }
-
- *ppOut = p->pMap;
- *pnOut = p->nMap;
- return LSM_OK;
-}
-
-static int lsmPosixOsFullpath(
- lsm_env *pEnv,
- const char *zName,
- char *zOut,
- int *pnOut
-){
- int nBuf = *pnOut;
- int nReq;
-
- if( zName[0]!='/' ){
- char *z;
- char *zTmp;
- int nTmp = 512;
- zTmp = lsmMalloc(pEnv, nTmp);
- while( zTmp ){
- z = getcwd(zTmp, nTmp);
- if( z || errno!=ERANGE ) break;
- nTmp = nTmp*2;
- zTmp = lsmReallocOrFree(pEnv, zTmp, nTmp);
- }
- if( zTmp==0 ) return LSM_NOMEM_BKPT;
- if( z==0 ) return LSM_IOERR_BKPT;
- assert( z==zTmp );
-
- nTmp = strlen(zTmp);
- nReq = nTmp + 1 + strlen(zName) + 1;
- if( nReq<=nBuf ){
- memcpy(zOut, zTmp, nTmp);
- zOut[nTmp] = '/';
- memcpy(&zOut[nTmp+1], zName, strlen(zName)+1);
- }
- lsmFree(pEnv, zTmp);
- }else{
- nReq = strlen(zName)+1;
- if( nReq<=nBuf ){
- memcpy(zOut, zName, strlen(zName)+1);
- }
- }
-
- *pnOut = nReq;
- return LSM_OK;
-}
-
-static int lsmPosixOsFileid(
- lsm_file *pFile,
- void *pBuf,
- int *pnBuf
-){
- int prc;
- int nBuf;
- int nReq;
- PosixFile *p = (PosixFile *)pFile;
- struct stat buf;
-
- nBuf = *pnBuf;
- nReq = (sizeof(buf.st_dev) + sizeof(buf.st_ino));
- *pnBuf = nReq;
- if( nReq>nBuf ) return LSM_OK;
-
- memset(&buf, 0, sizeof(buf));
- prc = fstat(p->fd, &buf);
- if( prc!=0 ) return LSM_IOERR_BKPT;
-
- memcpy(pBuf, &buf.st_dev, sizeof(buf.st_dev));
- memcpy(&(((u8 *)pBuf)[sizeof(buf.st_dev)]), &buf.st_ino, sizeof(buf.st_ino));
- return LSM_OK;
-}
-
-static int lsmPosixOsUnlink(lsm_env *pEnv, const char *zFile){
- int prc = unlink(zFile);
- return prc ? LSM_IOERR_BKPT : LSM_OK;
-}
-
-static int lsmPosixOsLock(lsm_file *pFile, int iLock, int eType){
- int rc = LSM_OK;
- PosixFile *p = (PosixFile *)pFile;
- static const short aType[3] = { F_UNLCK, F_RDLCK, F_WRLCK };
- struct flock lock;
-
- assert( aType[LSM_LOCK_UNLOCK]==F_UNLCK );
- assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
- assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
- assert( eType>=0 && eType<array_size(aType) );
- assert( iLock>0 && iLock<=32 );
-
- memset(&lock, 0, sizeof(lock));
- lock.l_whence = SEEK_SET;
- lock.l_len = 1;
- lock.l_type = aType[eType];
- lock.l_start = (4096-iLock);
-
- if( fcntl(p->fd, F_SETLK, &lock) ){
- int e = errno;
- if( e==EACCES || e==EAGAIN ){
- rc = LSM_BUSY;
- }else{
- rc = LSM_IOERR_BKPT;
- }
- }
-
- return rc;
-}
-
-static int lsmPosixOsTestLock(lsm_file *pFile, int iLock, int nLock, int eType){
- int rc = LSM_OK;
- PosixFile *p = (PosixFile *)pFile;
- static const short aType[3] = { 0, F_RDLCK, F_WRLCK };
- struct flock lock;
-
- assert( eType==LSM_LOCK_SHARED || eType==LSM_LOCK_EXCL );
- assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
- assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
- assert( eType>=0 && eType<array_size(aType) );
- assert( iLock>0 && iLock<=32 );
-
- memset(&lock, 0, sizeof(lock));
- lock.l_whence = SEEK_SET;
- lock.l_len = nLock;
- lock.l_type = aType[eType];
- lock.l_start = (4096-iLock-nLock+1);
-
- if( fcntl(p->fd, F_GETLK, &lock) ){
- rc = LSM_IOERR_BKPT;
- }else if( lock.l_type!=F_UNLCK ){
- rc = LSM_BUSY;
- }
-
- return rc;
-}
-
-static int lsmPosixOsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
- PosixFile *p = (PosixFile *)pFile;
-
- *ppShm = 0;
- assert( sz==LSM_SHM_CHUNK_SIZE );
- if( iChunk>=p->nShm ){
- int i;
- void **apNew;
- int nNew = iChunk+1;
- off_t nReq = nNew * LSM_SHM_CHUNK_SIZE;
- struct stat sStat;
-
- /* If the shared-memory file has not been opened, open it now. */
- if( p->shmfd<=0 ){
- char *zShm = posixShmFile(p);
- if( !zShm ) return LSM_NOMEM_BKPT;
- p->shmfd = open(zShm, O_RDWR|O_CREAT, 0644);
- lsmFree(p->pEnv, zShm);
- if( p->shmfd<0 ){
- return LSM_IOERR_BKPT;
- }
- }
-
- /* If the shared-memory file is not large enough to contain the
- ** requested chunk, cause it to grow. */
- if( fstat(p->shmfd, &sStat) ){
- return LSM_IOERR_BKPT;
- }
- if( sStat.st_size<nReq ){
- if( ftruncate(p->shmfd, nReq) ){
- return LSM_IOERR_BKPT;
- }
- }
-
- apNew = (void **)lsmRealloc(p->pEnv, p->apShm, sizeof(void *) * nNew);
- if( !apNew ) return LSM_NOMEM_BKPT;
- for(i=p->nShm; i<nNew; i++){
- apNew[i] = 0;
- }
- p->apShm = apNew;
- p->nShm = nNew;
- }
-
- if( p->apShm[iChunk]==0 ){
- p->apShm[iChunk] = mmap(0, LSM_SHM_CHUNK_SIZE,
- PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*LSM_SHM_CHUNK_SIZE
- );
- if( p->apShm[iChunk]==0 ) return LSM_IOERR_BKPT;
- }
-
- *ppShm = p->apShm[iChunk];
- return LSM_OK;
-}
-
-static void lsmPosixOsShmBarrier(void){
-}
-
-static int lsmPosixOsShmUnmap(lsm_file *pFile, int bDelete){
- PosixFile *p = (PosixFile *)pFile;
- if( p->shmfd>0 ){
- int i;
- for(i=0; i<p->nShm; i++){
- if( p->apShm[i] ){
- munmap(p->apShm[i], LSM_SHM_CHUNK_SIZE);
- p->apShm[i] = 0;
- }
- }
- close(p->shmfd);
- p->shmfd = 0;
- if( bDelete ){
- char *zShm = posixShmFile(p);
- if( zShm ) unlink(zShm);
- lsmFree(p->pEnv, zShm);
- }
- }
- return LSM_OK;
-}
-
-
-static int lsmPosixOsClose(lsm_file *pFile){
- PosixFile *p = (PosixFile *)pFile;
- lsmPosixOsShmUnmap(pFile, 0);
- if( p->pMap ) munmap(p->pMap, p->nMap);
- close(p->fd);
- lsm_free(p->pEnv, p->apShm);
- lsm_free(p->pEnv, p);
- return LSM_OK;
-}
-
-static int lsmPosixOsSleep(lsm_env *pEnv, int us){
-#if 0
- /* Apparently on Android usleep() returns void */
- if( usleep(us) ) return LSM_IOERR;
-#endif
- usleep(us);
- return LSM_OK;
-}
-
-/****************************************************************************
-** Memory allocation routines.
-*/
-#define BLOCK_HDR_SIZE ROUND8( sizeof(size_t) )
-
-static void *lsmPosixOsMalloc(lsm_env *pEnv, size_t N){
- unsigned char * m;
- N += BLOCK_HDR_SIZE;
- m = (unsigned char *)malloc(N);
- *((size_t*)m) = N;
- return m + BLOCK_HDR_SIZE;
-}
-
-static void lsmPosixOsFree(lsm_env *pEnv, void *p){
- if(p){
- free( ((unsigned char *)p) - BLOCK_HDR_SIZE );
- }
-}
-
-static void *lsmPosixOsRealloc(lsm_env *pEnv, void *p, size_t N){
- unsigned char * m = (unsigned char *)p;
- if(1>N){
- lsmPosixOsFree( pEnv, p );
- return NULL;
- }else if(NULL==p){
- return lsmPosixOsMalloc(pEnv, N);
- }else{
- void * re = NULL;
- m -= BLOCK_HDR_SIZE;
-#if 0 /* arguable: don't shrink */
- size_t * sz = (size_t*)m;
- if(*sz >= (size_t)N){
- return p;
- }
-#endif
- re = realloc( m, N + BLOCK_HDR_SIZE );
- if(re){
- m = (unsigned char *)re;
- *((size_t*)m) = N;
- return m + BLOCK_HDR_SIZE;
- }else{
- return NULL;
- }
- }
-}
-
-static size_t lsmPosixOsMSize(lsm_env *pEnv, void *p){
- unsigned char * m = (unsigned char *)p;
- return *((size_t*)(m-BLOCK_HDR_SIZE));
-}
-#undef BLOCK_HDR_SIZE
-
-
-#ifdef LSM_MUTEX_PTHREADS
-/*************************************************************************
-** Mutex methods for pthreads based systems. If LSM_MUTEX_PTHREADS is
-** missing then a no-op implementation of mutexes found in lsm_mutex.c
-** will be used instead.
-*/
-#include <pthread.h>
-
-typedef struct PthreadMutex PthreadMutex;
-struct PthreadMutex {
- lsm_env *pEnv;
- pthread_mutex_t mutex;
-#ifdef LSM_DEBUG
- pthread_t owner;
-#endif
-};
-
-#ifdef LSM_DEBUG
-# define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER, 0 }
-#else
-# define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER }
-#endif
-
-static int lsmPosixOsMutexStatic(
- lsm_env *pEnv,
- int iMutex,
- lsm_mutex **ppStatic
-){
- static PthreadMutex sMutex[2] = {
- LSM_PTHREAD_STATIC_MUTEX,
- LSM_PTHREAD_STATIC_MUTEX
- };
-
- assert( iMutex==LSM_MUTEX_GLOBAL || iMutex==LSM_MUTEX_HEAP );
- assert( LSM_MUTEX_GLOBAL==1 && LSM_MUTEX_HEAP==2 );
-
- *ppStatic = (lsm_mutex *)&sMutex[iMutex-1];
- return LSM_OK;
-}
-
-static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
- PthreadMutex *pMutex; /* Pointer to new mutex */
- pthread_mutexattr_t attr; /* Attributes object */
-
- pMutex = (PthreadMutex *)lsmMallocZero(pEnv, sizeof(PthreadMutex));
- if( !pMutex ) return LSM_NOMEM_BKPT;
-
- pMutex->pEnv = pEnv;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&pMutex->mutex, &attr);
- pthread_mutexattr_destroy(&attr);
-
- *ppNew = (lsm_mutex *)pMutex;
- return LSM_OK;
-}
-
-static void lsmPosixOsMutexDel(lsm_mutex *p){
- PthreadMutex *pMutex = (PthreadMutex *)p;
- pthread_mutex_destroy(&pMutex->mutex);
- lsmFree(pMutex->pEnv, pMutex);
-}
-
-static void lsmPosixOsMutexEnter(lsm_mutex *p){
- PthreadMutex *pMutex = (PthreadMutex *)p;
- pthread_mutex_lock(&pMutex->mutex);
-
-#ifdef LSM_DEBUG
- assert( !pthread_equal(pMutex->owner, pthread_self()) );
- pMutex->owner = pthread_self();
- assert( pthread_equal(pMutex->owner, pthread_self()) );
-#endif
-}
-
-static int lsmPosixOsMutexTry(lsm_mutex *p){
- int ret;
- PthreadMutex *pMutex = (PthreadMutex *)p;
- ret = pthread_mutex_trylock(&pMutex->mutex);
-#ifdef LSM_DEBUG
- if( ret==0 ){
- assert( !pthread_equal(pMutex->owner, pthread_self()) );
- pMutex->owner = pthread_self();
- assert( pthread_equal(pMutex->owner, pthread_self()) );
- }
-#endif
- return ret;
-}
-
-static void lsmPosixOsMutexLeave(lsm_mutex *p){
- PthreadMutex *pMutex = (PthreadMutex *)p;
-#ifdef LSM_DEBUG
- assert( pthread_equal(pMutex->owner, pthread_self()) );
- pMutex->owner = 0;
- assert( !pthread_equal(pMutex->owner, pthread_self()) );
-#endif
- pthread_mutex_unlock(&pMutex->mutex);
-}
-
-#ifdef LSM_DEBUG
-static int lsmPosixOsMutexHeld(lsm_mutex *p){
- PthreadMutex *pMutex = (PthreadMutex *)p;
- return pMutex ? pthread_equal(pMutex->owner, pthread_self()) : 1;
-}
-static int lsmPosixOsMutexNotHeld(lsm_mutex *p){
- PthreadMutex *pMutex = (PthreadMutex *)p;
- return pMutex ? !pthread_equal(pMutex->owner, pthread_self()) : 1;
-}
-#endif
-/*
-** End of pthreads mutex implementation.
-*************************************************************************/
-#else
-/*************************************************************************
-** Noop mutex implementation
-*/
-typedef struct NoopMutex NoopMutex;
-struct NoopMutex {
- lsm_env *pEnv; /* Environment handle (for xFree()) */
- int bHeld; /* True if mutex is held */
- int bStatic; /* True for a static mutex */
-};
-static NoopMutex aStaticNoopMutex[2] = {
- {0, 0, 1},
- {0, 0, 1},
-};
-
-static int lsmPosixOsMutexStatic(
- lsm_env *pEnv,
- int iMutex,
- lsm_mutex **ppStatic
-){
- assert( iMutex>=1 && iMutex<=(int)array_size(aStaticNoopMutex) );
- *ppStatic = (lsm_mutex *)&aStaticNoopMutex[iMutex-1];
- return LSM_OK;
-}
-static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
- NoopMutex *p;
- p = (NoopMutex *)lsmMallocZero(pEnv, sizeof(NoopMutex));
- if( p ) p->pEnv = pEnv;
- *ppNew = (lsm_mutex *)p;
- return (p ? LSM_OK : LSM_NOMEM_BKPT);
-}
-static void lsmPosixOsMutexDel(lsm_mutex *pMutex) {
- NoopMutex *p = (NoopMutex *)pMutex;
- assert( p->bStatic==0 && p->pEnv );
- lsmFree(p->pEnv, p);
-}
-static void lsmPosixOsMutexEnter(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- assert( p->bHeld==0 );
- p->bHeld = 1;
-}
-static int lsmPosixOsMutexTry(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- assert( p->bHeld==0 );
- p->bHeld = 1;
- return 0;
-}
-static void lsmPosixOsMutexLeave(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- assert( p->bHeld==1 );
- p->bHeld = 0;
-}
-#ifdef LSM_DEBUG
-static int lsmPosixOsMutexHeld(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- return p ? p->bHeld : 1;
-}
-static int lsmPosixOsMutexNotHeld(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- return p ? !p->bHeld : 1;
-}
-#endif
-/***************************************************************************/
-#endif /* else LSM_MUTEX_NONE */
-
-/* Without LSM_DEBUG, the MutexHeld tests are never called */
-#ifndef LSM_DEBUG
-# define lsmPosixOsMutexHeld 0
-# define lsmPosixOsMutexNotHeld 0
-#endif
-
-lsm_env *lsm_default_env(void){
- static lsm_env posix_env = {
- sizeof(lsm_env), /* nByte */
- 1, /* iVersion */
- /***** file i/o ******************/
- 0, /* pVfsCtx */
- lsmPosixOsFullpath, /* xFullpath */
- lsmPosixOsOpen, /* xOpen */
- lsmPosixOsRead, /* xRead */
- lsmPosixOsWrite, /* xWrite */
- lsmPosixOsTruncate, /* xTruncate */
- lsmPosixOsSync, /* xSync */
- lsmPosixOsSectorSize, /* xSectorSize */
- lsmPosixOsRemap, /* xRemap */
- lsmPosixOsFileid, /* xFileid */
- lsmPosixOsClose, /* xClose */
- lsmPosixOsUnlink, /* xUnlink */
- lsmPosixOsLock, /* xLock */
- lsmPosixOsTestLock, /* xTestLock */
- lsmPosixOsShmMap, /* xShmMap */
- lsmPosixOsShmBarrier, /* xShmBarrier */
- lsmPosixOsShmUnmap, /* xShmUnmap */
- /***** memory allocation *********/
- 0, /* pMemCtx */
- lsmPosixOsMalloc, /* xMalloc */
- lsmPosixOsRealloc, /* xRealloc */
- lsmPosixOsFree, /* xFree */
- lsmPosixOsMSize, /* xSize */
- /***** mutexes *********************/
- 0, /* pMutexCtx */
- lsmPosixOsMutexStatic, /* xMutexStatic */
- lsmPosixOsMutexNew, /* xMutexNew */
- lsmPosixOsMutexDel, /* xMutexDel */
- lsmPosixOsMutexEnter, /* xMutexEnter */
- lsmPosixOsMutexTry, /* xMutexTry */
- lsmPosixOsMutexLeave, /* xMutexLeave */
- lsmPosixOsMutexHeld, /* xMutexHeld */
- lsmPosixOsMutexNotHeld, /* xMutexNotHeld */
- /***** other *********************/
- lsmPosixOsSleep, /* xSleep */
- };
- return &posix_env;
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_varint.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_varint.c
deleted file mode 100644
index c550a6405db..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_varint.c
+++ /dev/null
@@ -1,196 +0,0 @@
-
-/*
-** 2012-02-08
-**
-** 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.
-**
-*************************************************************************
-**
-** SQLite4-compatible varint implementation.
-*/
-#include "lsmInt.h"
-
-/*************************************************************************
-** The following is a copy of the varint.c module from SQLite 4.
-*/
-
-/*
-** Decode the varint in z[]. Write the integer value into *pResult and
-** return the number of bytes in the varint.
-*/
-static int lsmSqlite4GetVarint64(const unsigned char *z, u64 *pResult){
- unsigned int x;
- if( z[0]<=240 ){
- *pResult = z[0];
- return 1;
- }
- if( z[0]<=248 ){
- *pResult = (z[0]-241)*256 + z[1] + 240;
- return 2;
- }
- if( z[0]==249 ){
- *pResult = 2288 + 256*z[1] + z[2];
- return 3;
- }
- if( z[0]==250 ){
- *pResult = (z[1]<<16) + (z[2]<<8) + z[3];
- return 4;
- }
- x = (z[1]<<24) + (z[2]<<16) + (z[3]<<8) + z[4];
- if( z[0]==251 ){
- *pResult = x;
- return 5;
- }
- if( z[0]==252 ){
- *pResult = (((u64)x)<<8) + z[5];
- return 6;
- }
- if( z[0]==253 ){
- *pResult = (((u64)x)<<16) + (z[5]<<8) + z[6];
- return 7;
- }
- if( z[0]==254 ){
- *pResult = (((u64)x)<<24) + (z[5]<<16) + (z[6]<<8) + z[7];
- return 8;
- }
- *pResult = (((u64)x)<<32) +
- (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
- return 9;
-}
-
-/*
-** Write a 32-bit unsigned integer as 4 big-endian bytes.
-*/
-static void lsmVarintWrite32(unsigned char *z, unsigned int y){
- z[0] = (unsigned char)(y>>24);
- z[1] = (unsigned char)(y>>16);
- z[2] = (unsigned char)(y>>8);
- z[3] = (unsigned char)(y);
-}
-
-/*
-** Write a varint into z[]. The buffer z[] must be at least 9 characters
-** long to accommodate the largest possible varint. Return the number of
-** bytes of z[] used.
-*/
-static int lsmSqlite4PutVarint64(unsigned char *z, u64 x){
- unsigned int w, y;
- if( x<=240 ){
- z[0] = (unsigned char)x;
- return 1;
- }
- if( x<=2287 ){
- y = (unsigned int)(x - 240);
- z[0] = (unsigned char)(y/256 + 241);
- z[1] = (unsigned char)(y%256);
- return 2;
- }
- if( x<=67823 ){
- y = (unsigned int)(x - 2288);
- z[0] = 249;
- z[1] = (unsigned char)(y/256);
- z[2] = (unsigned char)(y%256);
- return 3;
- }
- y = (unsigned int)x;
- w = (unsigned int)(x>>32);
- if( w==0 ){
- if( y<=16777215 ){
- z[0] = 250;
- z[1] = (unsigned char)(y>>16);
- z[2] = (unsigned char)(y>>8);
- z[3] = (unsigned char)(y);
- return 4;
- }
- z[0] = 251;
- lsmVarintWrite32(z+1, y);
- return 5;
- }
- if( w<=255 ){
- z[0] = 252;
- z[1] = (unsigned char)w;
- lsmVarintWrite32(z+2, y);
- return 6;
- }
- if( w<=32767 ){
- z[0] = 253;
- z[1] = (unsigned char)(w>>8);
- z[2] = (unsigned char)w;
- lsmVarintWrite32(z+3, y);
- return 7;
- }
- if( w<=16777215 ){
- z[0] = 254;
- z[1] = (unsigned char)(w>>16);
- z[2] = (unsigned char)(w>>8);
- z[3] = (unsigned char)w;
- lsmVarintWrite32(z+4, y);
- return 8;
- }
- z[0] = 255;
- lsmVarintWrite32(z+1, w);
- lsmVarintWrite32(z+5, y);
- return 9;
-}
-
-/*
-** End of SQLite 4 code.
-*************************************************************************/
-
-int lsmVarintPut64(u8 *aData, i64 iVal){
- return lsmSqlite4PutVarint64(aData, (u64)iVal);
-}
-
-int lsmVarintGet64(const u8 *aData, i64 *piVal){
- return lsmSqlite4GetVarint64(aData, (u64 *)piVal);
-}
-
-int lsmVarintPut32(u8 *aData, int iVal){
- return lsmSqlite4PutVarint64(aData, (u64)iVal);
-}
-
-int lsmVarintGet32(u8 *z, int *piVal){
- u64 i;
- int ret;
-
- if( z[0]<=240 ){
- *piVal = z[0];
- return 1;
- }
- if( z[0]<=248 ){
- *piVal = (z[0]-241)*256 + z[1] + 240;
- return 2;
- }
- if( z[0]==249 ){
- *piVal = 2288 + 256*z[1] + z[2];
- return 3;
- }
- if( z[0]==250 ){
- *piVal = (z[1]<<16) + (z[2]<<8) + z[3];
- return 4;
- }
-
- ret = lsmSqlite4GetVarint64(z, &i);
- *piVal = (int)i;
- return ret;
-}
-
-int lsmVarintLen32(int n){
- u8 aData[9];
- return lsmVarintPut32(aData, n);
-}
-
-/*
-** The argument is the first byte of a varint. This function returns the
-** total number of bytes in the entire varint (including the first byte).
-*/
-int lsmVarintSize(u8 c){
- if( c<241 ) return 1;
- if( c<249 ) return 2;
- return (int)(c - 246);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_vtab.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_vtab.c
deleted file mode 100644
index fe7c160b621..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_vtab.c
+++ /dev/null
@@ -1,1079 +0,0 @@
-/*
-** 2015-11-16
-**
-** 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 a virtual table for SQLite3 around the LSM
-** storage engine from SQLite4.
-**
-** USAGE
-**
-** CREATE VIRTUAL TABLE demo USING lsm1(filename,key,keytype,value1,...);
-**
-** The filename parameter is the name of the LSM database file, which is
-** separate and distinct from the SQLite3 database file.
-**
-** The keytype must be one of: UINT, TEXT, BLOB. All keys must be of that
-** one type. "UINT" means unsigned integer. The values may be of any
-** SQLite datatype: BLOB, TEXT, INTEGER, FLOAT, or NULL.
-**
-** The virtual table contains read-only hidden columns:
-**
-** lsm1_key A BLOB which is the raw LSM key. If the "keytype"
-** is BLOB or TEXT then this column is exactly the
-** same as the key. For the UINT keytype, this column
-** will be a variable-length integer encoding of the key.
-**
-** lsm1_value A BLOB which is the raw LSM value. All of the value
-** columns are packed into this BLOB using the encoding
-** described below.
-**
-** Attempts to write values into the lsm1_key and lsm1_value columns are
-** silently ignored.
-**
-** EXAMPLE
-**
-** The virtual table declared this way:
-**
-** CREATE VIRTUAL TABLE demo2 USING lsm1('x.lsm',id,UINT,a,b,c,d);
-**
-** Results in a new virtual table named "demo2" that acts as if it has
-** the following schema:
-**
-** CREATE TABLE demo2(
-** id UINT PRIMARY KEY ON CONFLICT REPLACE,
-** a ANY,
-** b ANY,
-** c ANY,
-** d ANY,
-** lsm1_key BLOB HIDDEN,
-** lsm1_value BLOB HIDDEN
-** ) WITHOUT ROWID;
-**
-**
-**
-** INTERNALS
-**
-** The key encoding for BLOB and TEXT is just a copy of the blob or text.
-** UTF-8 is used for text. The key encoding for UINT is the variable-length
-** integer format at https://sqlite.org/src4/doc/trunk/www/varint.wiki.
-**
-** The values are encoded as a single blob (since that is what lsm stores as
-** its content). There is a "type integer" followed by "content" for each
-** value, alternating back and forth. The content might be empty.
-**
-** TYPE1 CONTENT1 TYPE2 CONTENT2 TYPE3 CONTENT3 ....
-**
-** Each "type integer" is encoded as a variable-length integer in the
-** format of the link above. Let the type integer be T. The actual
-** datatype is an integer 0-5 equal to T%6. Values 1 through 5 correspond
-** to SQLITE_INTEGER through SQLITE_NULL. The size of the content in bytes
-** is T/6. Type value 0 means that the value is an integer whose actual
-** values is T/6 and there is no content. The type-value-0 integer format
-** only works for integers in the range of 0 through 40.
-**
-** There is no content for NULL or type-0 integers. For BLOB and TEXT
-** values, the content is the blob data or the UTF-8 text data. For
-** non-negative integers X, the content is a variable-length integer X*2.
-** For negative integers Y, the content is varaible-length integer (1-Y)*2+1.
-** For FLOAT values, the content is the IEEE754 floating point value in
-** native byte-order. This means that FLOAT values will be corrupted when
-** database file is moved between big-endian and little-endian machines.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include "lsm.h"
-#include <assert.h>
-#include <string.h>
-
-/* Forward declaration of subclasses of virtual table objects */
-typedef struct lsm1_vtab lsm1_vtab;
-typedef struct lsm1_cursor lsm1_cursor;
-typedef struct lsm1_vblob lsm1_vblob;
-
-/* Primitive types */
-typedef unsigned char u8;
-typedef unsigned int u32;
-typedef sqlite3_uint64 u64;
-
-/* An open connection to an LSM table */
-struct lsm1_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- lsm_db *pDb; /* Open connection to the LSM table */
- u8 keyType; /* SQLITE_BLOB, _TEXT, or _INTEGER */
- u32 nVal; /* Number of value columns */
-};
-
-
-/* lsm1_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-struct lsm1_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- lsm_cursor *pLsmCur; /* The LSM cursor */
- u8 isDesc; /* 0: scan forward. 1: scan reverse */
- u8 atEof; /* True if the scan is complete */
- u8 bUnique; /* True if no more than one row of output */
- u8 *zData; /* Content of the current row */
- u32 nData; /* Number of bytes in the current row */
- u8 *aeType; /* Types for all column values */
- u32 *aiOfst; /* Offsets to the various fields */
- u32 *aiLen; /* Length of each field */
- u8 *pKey2; /* Loop termination key, or NULL */
- u32 nKey2; /* Length of the loop termination key */
-};
-
-/* An extensible buffer object.
-**
-** Content can be appended. Space to hold new content is automatically
-** allocated.
-*/
-struct lsm1_vblob {
- u8 *a; /* Space to hold content, from sqlite3_malloc64() */
- u64 n; /* Bytes of space used */
- u64 nAlloc; /* Bytes of space allocated */
- u8 errNoMem; /* True if a memory allocation error has been seen */
-};
-
-#if defined(__GNUC__)
-# define LSM1_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER) && _MSC_VER>=1310
-# define LSM1_NOINLINE __declspec(noinline)
-#else
-# define LSM1_NOINLINE
-#endif
-
-
-/* Increase the available space in the vblob object so that it can hold
-** at least N more bytes. Return the number of errors.
-*/
-static int lsm1VblobEnlarge(lsm1_vblob *p, u32 N){
- if( p->n+N>p->nAlloc ){
- if( p->errNoMem ) return 1;
- p->nAlloc += N + (p->nAlloc ? p->nAlloc : N);
- p->a = sqlite3_realloc64(p->a, p->nAlloc);
- if( p->a==0 ){
- p->n = 0;
- p->nAlloc = 0;
- p->errNoMem = 1;
- return 1;
- }
- p->nAlloc = sqlite3_msize(p->a);
- }
- return 0;
-}
-
-/* Append N bytes to a vblob after first enlarging it */
-static LSM1_NOINLINE void lsm1VblobEnlargeAndAppend(
- lsm1_vblob *p,
- const u8 *pData,
- u32 N
-){
- if( p->n+N>p->nAlloc && lsm1VblobEnlarge(p, N) ) return;
- memcpy(p->a+p->n, pData, N);
- p->n += N;
-}
-
-/* Append N bytes to a vblob */
-static void lsm1VblobAppend(lsm1_vblob *p, const u8 *pData, u32 N){
- sqlite3_int64 n = p->n;
- if( n+N>p->nAlloc ){
- lsm1VblobEnlargeAndAppend(p, pData, N);
- }else{
- p->n += N;
- memcpy(p->a+n, pData, N);
- }
-}
-
-/* append text to a vblob */
-static void lsm1VblobAppendText(lsm1_vblob *p, const char *z){
- lsm1VblobAppend(p, (u8*)z, (u32)strlen(z));
-}
-
-/* Dequote the string */
-static void lsm1Dequote(char *z){
- int j;
- char cQuote = z[0];
- size_t i, n;
-
- if( cQuote!='\'' && cQuote!='"' ) return;
- n = strlen(z);
- if( n<2 || z[n-1]!=z[0] ) return;
- for(i=1, j=0; i<n-1; i++){
- if( z[i]==cQuote && z[i+1]==cQuote ) i++;
- z[j++] = z[i];
- }
- z[j] = 0;
-}
-
-
-/*
-** The lsm1Connect() method is invoked to create a new
-** lsm1_vtab that describes the virtual table.
-*/
-static int lsm1Connect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- lsm1_vtab *pNew;
- int rc;
- char *zFilename;
- u8 keyType = 0;
- int i;
- lsm1_vblob sql;
- static const char *azTypes[] = { "UINT", "TEXT", "BLOB" };
- static const u8 aeTypes[] = { SQLITE_INTEGER, SQLITE_TEXT, SQLITE_BLOB };
- static const char *azArgName[] = {"filename", "key", "key type", "value1" };
-
- for(i=0; i<sizeof(azArgName)/sizeof(azArgName[0]); i++){
- if( argc<i+4 || argv[i+3]==0 || argv[i+3][0]==0 ){
- *pzErr = sqlite3_mprintf("%s (%r) argument missing",
- azArgName[i], i+1);
- return SQLITE_ERROR;
- }
- }
- for(i=0; i<sizeof(azTypes)/sizeof(azTypes[0]); i++){
- if( sqlite3_stricmp(azTypes[i],argv[5])==0 ){
- keyType = aeTypes[i];
- break;
- }
- }
- if( keyType==0 ){
- *pzErr = sqlite3_mprintf("key type should be INT, TEXT, or BLOB");
- return SQLITE_ERROR;
- }
- *ppVtab = sqlite3_malloc( sizeof(*pNew) );
- pNew = (lsm1_vtab*)*ppVtab;
- if( pNew==0 ){
- return SQLITE_NOMEM;
- }
- memset(pNew, 0, sizeof(*pNew));
- pNew->keyType = keyType;
- rc = lsm_new(0, &pNew->pDb);
- if( rc ){
- *pzErr = sqlite3_mprintf("lsm_new failed with error code %d", rc);
- rc = SQLITE_ERROR;
- goto connect_failed;
- }
- zFilename = sqlite3_mprintf("%s", argv[3]);
- lsm1Dequote(zFilename);
- rc = lsm_open(pNew->pDb, zFilename);
- sqlite3_free(zFilename);
- if( rc ){
- *pzErr = sqlite3_mprintf("lsm_open failed with %d", rc);
- rc = SQLITE_ERROR;
- goto connect_failed;
- }
-
- memset(&sql, 0, sizeof(sql));
- lsm1VblobAppendText(&sql, "CREATE TABLE x(");
- lsm1VblobAppendText(&sql, argv[4]);
- lsm1VblobAppendText(&sql, " ");
- lsm1VblobAppendText(&sql, argv[5]);
- lsm1VblobAppendText(&sql, " PRIMARY KEY");
- for(i=6; i<argc; i++){
- lsm1VblobAppendText(&sql, ", ");
- lsm1VblobAppendText(&sql, argv[i]);
- pNew->nVal++;
- }
- lsm1VblobAppendText(&sql,
- ", lsm1_command HIDDEN"
- ", lsm1_key HIDDEN"
- ", lsm1_value HIDDEN) WITHOUT ROWID");
- lsm1VblobAppend(&sql, (u8*)"", 1);
- if( sql.errNoMem ){
- rc = SQLITE_NOMEM;
- goto connect_failed;
- }
- rc = sqlite3_declare_vtab(db, (const char*)sql.a);
- sqlite3_free(sql.a);
-
-connect_failed:
- if( rc!=SQLITE_OK ){
- if( pNew ){
- if( pNew->pDb ) lsm_close(pNew->pDb);
- sqlite3_free(pNew);
- }
- *ppVtab = 0;
- }
- return rc;
-}
-
-/*
-** This method is the destructor for lsm1_cursor objects.
-*/
-static int lsm1Disconnect(sqlite3_vtab *pVtab){
- lsm1_vtab *p = (lsm1_vtab*)pVtab;
- lsm_close(p->pDb);
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new lsm1_cursor object.
-*/
-static int lsm1Open(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
- lsm1_vtab *p = (lsm1_vtab*)pVtab;
- lsm1_cursor *pCur;
- int rc;
- pCur = sqlite3_malloc64( sizeof(*pCur)
- + p->nVal*(sizeof(pCur->aiOfst)+sizeof(pCur->aiLen)+1) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->aiOfst = (u32*)&pCur[1];
- pCur->aiLen = &pCur->aiOfst[p->nVal];
- pCur->aeType = (u8*)&pCur->aiLen[p->nVal];
- *ppCursor = &pCur->base;
- rc = lsm_csr_open(p->pDb, &pCur->pLsmCur);
- if( rc==LSM_OK ){
- rc = SQLITE_OK;
- }else{
- sqlite3_free(pCur);
- *ppCursor = 0;
- rc = SQLITE_ERROR;
- }
- return rc;
-}
-
-/*
-** Destructor for a lsm1_cursor.
-*/
-static int lsm1Close(sqlite3_vtab_cursor *cur){
- lsm1_cursor *pCur = (lsm1_cursor*)cur;
- sqlite3_free(pCur->pKey2);
- lsm_csr_close(pCur->pLsmCur);
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a lsm1_cursor to its next row of output.
-*/
-static int lsm1Next(sqlite3_vtab_cursor *cur){
- lsm1_cursor *pCur = (lsm1_cursor*)cur;
- int rc = LSM_OK;
- if( pCur->bUnique ){
- pCur->atEof = 1;
- }else{
- if( pCur->isDesc ){
- rc = lsm_csr_prev(pCur->pLsmCur);
- }else{
- rc = lsm_csr_next(pCur->pLsmCur);
- }
- if( rc==LSM_OK && lsm_csr_valid(pCur->pLsmCur)==0 ){
- pCur->atEof = 1;
- }
- if( pCur->pKey2 && pCur->atEof==0 ){
- const u8 *pVal;
- u32 nVal;
- assert( pCur->isDesc==0 );
- rc = lsm_csr_key(pCur->pLsmCur, (const void**)&pVal, (int*)&nVal);
- if( rc==LSM_OK ){
- u32 len = pCur->nKey2;
- int c;
- if( len>nVal ) len = nVal;
- c = memcmp(pVal, pCur->pKey2, len);
- if( c==0 ) c = nVal - pCur->nKey2;
- if( c>0 ) pCur->atEof = 1;
- }
- }
- pCur->zData = 0;
- }
- return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int lsm1Eof(sqlite3_vtab_cursor *cur){
- lsm1_cursor *pCur = (lsm1_cursor*)cur;
- return pCur->atEof;
-}
-
-/*
-** Rowids are not supported by the underlying virtual table. So always
-** return 0 for the rowid.
-*/
-static int lsm1Rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- *pRowid = 0;
- return SQLITE_OK;
-}
-
-/*
-** Type prefixes on LSM keys
-*/
-#define LSM1_TYPE_NEGATIVE 0
-#define LSM1_TYPE_POSITIVE 1
-#define LSM1_TYPE_TEXT 2
-#define LSM1_TYPE_BLOB 3
-
-/*
-** Write a 32-bit unsigned integer as 4 big-endian bytes.
-*/
-static void varintWrite32(unsigned char *z, unsigned int y){
- z[0] = (unsigned char)(y>>24);
- z[1] = (unsigned char)(y>>16);
- z[2] = (unsigned char)(y>>8);
- z[3] = (unsigned char)(y);
-}
-
-/*
-** Write a varint into z[]. The buffer z[] must be at least 9 characters
-** long to accommodate the largest possible varint. Return the number of
-** bytes of z[] used.
-*/
-static int lsm1PutVarint64(unsigned char *z, sqlite3_uint64 x){
- unsigned int w, y;
- if( x<=240 ){
- z[0] = (unsigned char)x;
- return 1;
- }
- if( x<=2287 ){
- y = (unsigned int)(x - 240);
- z[0] = (unsigned char)(y/256 + 241);
- z[1] = (unsigned char)(y%256);
- return 2;
- }
- if( x<=67823 ){
- y = (unsigned int)(x - 2288);
- z[0] = 249;
- z[1] = (unsigned char)(y/256);
- z[2] = (unsigned char)(y%256);
- return 3;
- }
- y = (unsigned int)x;
- w = (unsigned int)(x>>32);
- if( w==0 ){
- if( y<=16777215 ){
- z[0] = 250;
- z[1] = (unsigned char)(y>>16);
- z[2] = (unsigned char)(y>>8);
- z[3] = (unsigned char)(y);
- return 4;
- }
- z[0] = 251;
- varintWrite32(z+1, y);
- return 5;
- }
- if( w<=255 ){
- z[0] = 252;
- z[1] = (unsigned char)w;
- varintWrite32(z+2, y);
- return 6;
- }
- if( w<=65535 ){
- z[0] = 253;
- z[1] = (unsigned char)(w>>8);
- z[2] = (unsigned char)w;
- varintWrite32(z+3, y);
- return 7;
- }
- if( w<=16777215 ){
- z[0] = 254;
- z[1] = (unsigned char)(w>>16);
- z[2] = (unsigned char)(w>>8);
- z[3] = (unsigned char)w;
- varintWrite32(z+4, y);
- return 8;
- }
- z[0] = 255;
- varintWrite32(z+1, w);
- varintWrite32(z+5, y);
- return 9;
-}
-
-/* Append non-negative integer x as a variable-length integer.
-*/
-static void lsm1VblobAppendVarint(lsm1_vblob *p, sqlite3_uint64 x){
- sqlite3_int64 n = p->n;
- if( n+9>p->nAlloc && lsm1VblobEnlarge(p, 9) ) return;
- p->n += lsm1PutVarint64(p->a+p->n, x);
-}
-
-/*
-** Decode the varint in the first n bytes z[]. Write the integer value
-** into *pResult and return the number of bytes in the varint.
-**
-** If the decode fails because there are not enough bytes in z[] then
-** return 0;
-*/
-static int lsm1GetVarint64(
- const unsigned char *z,
- int n,
- sqlite3_uint64 *pResult
-){
- unsigned int x;
- if( n<1 ) return 0;
- if( z[0]<=240 ){
- *pResult = z[0];
- return 1;
- }
- if( z[0]<=248 ){
- if( n<2 ) return 0;
- *pResult = (z[0]-241)*256 + z[1] + 240;
- return 2;
- }
- if( n<z[0]-246 ) return 0;
- if( z[0]==249 ){
- *pResult = 2288 + 256*z[1] + z[2];
- return 3;
- }
- if( z[0]==250 ){
- *pResult = (z[1]<<16) + (z[2]<<8) + z[3];
- return 4;
- }
- x = (z[1]<<24) + (z[2]<<16) + (z[3]<<8) + z[4];
- if( z[0]==251 ){
- *pResult = x;
- return 5;
- }
- if( z[0]==252 ){
- *pResult = (((sqlite3_uint64)x)<<8) + z[5];
- return 6;
- }
- if( z[0]==253 ){
- *pResult = (((sqlite3_uint64)x)<<16) + (z[5]<<8) + z[6];
- return 7;
- }
- if( z[0]==254 ){
- *pResult = (((sqlite3_uint64)x)<<24) + (z[5]<<16) + (z[6]<<8) + z[7];
- return 8;
- }
- *pResult = (((sqlite3_uint64)x)<<32) +
- (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
- return 9;
-}
-
-/* Encoded a signed integer as a varint. Numbers close to zero uses fewer
-** bytes than numbers far away from zero. However, the result is not in
-** lexicographical order.
-**
-** Encoding: Non-negative integer X is encoding as an unsigned
-** varint X*2. Negative integer Y is encoding as an unsigned
-** varint (1-Y)*2 + 1.
-*/
-static int lsm1PutSignedVarint64(u8 *z, sqlite3_int64 v){
- sqlite3_uint64 u;
- if( v>=0 ){
- u = (sqlite3_uint64)v;
- return lsm1PutVarint64(z, u*2);
- }else{
- u = (sqlite3_uint64)(-1-v);
- return lsm1PutVarint64(z, u*2+1);
- }
-}
-
-/* Decoded a signed varint. */
-static int lsm1GetSignedVarint64(
- const unsigned char *z,
- int n,
- sqlite3_int64 *pResult
-){
- sqlite3_uint64 u = 0;
- n = lsm1GetVarint64(z, n, &u);
- if( u&1 ){
- *pResult = -1 - (sqlite3_int64)(u>>1);
- }else{
- *pResult = (sqlite3_int64)(u>>1);
- }
- return n;
-}
-
-
-/*
-** Read the value part of the key-value pair and decode it into columns.
-*/
-static int lsm1DecodeValues(lsm1_cursor *pCur){
- lsm1_vtab *pTab = (lsm1_vtab*)(pCur->base.pVtab);
- int i, n;
- int rc;
- u8 eType;
- sqlite3_uint64 v;
-
- if( pCur->zData ) return 1;
- rc = lsm_csr_value(pCur->pLsmCur, (const void**)&pCur->zData,
- (int*)&pCur->nData);
- if( rc ) return 0;
- for(i=n=0; i<pTab->nVal; i++){
- v = 0;
- n += lsm1GetVarint64(pCur->zData+n, pCur->nData-n, &v);
- pCur->aeType[i] = eType = (u8)(v%6);
- if( eType==0 ){
- pCur->aiOfst[i] = (u32)(v/6);
- pCur->aiLen[i] = 0;
- }else{
- pCur->aiOfst[i] = n;
- n += (pCur->aiLen[i] = (u32)(v/6));
- }
- if( n>pCur->nData ) break;
- }
- if( i<pTab->nVal ){
- pCur->zData = 0;
- return 0;
- }
- return 1;
-}
-
-/*
-** Return values of columns for the row at which the lsm1_cursor
-** is currently pointing.
-*/
-static int lsm1Column(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- lsm1_cursor *pCur = (lsm1_cursor*)cur;
- lsm1_vtab *pTab = (lsm1_vtab*)(cur->pVtab);
- if( i==0 ){
- /* The key column */
- const void *pVal;
- int nVal;
- if( lsm_csr_key(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
- if( pTab->keyType==SQLITE_BLOB ){
- sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
- }else if( pTab->keyType==SQLITE_TEXT ){
- sqlite3_result_text(ctx,(const char*)pVal, nVal, SQLITE_TRANSIENT);
- }else{
- const unsigned char *z = (const unsigned char*)pVal;
- sqlite3_uint64 v1;
- lsm1GetVarint64(z, nVal, &v1);
- sqlite3_result_int64(ctx, (sqlite3_int64)v1);
- }
- }
- }else if( i>pTab->nVal ){
- if( i==pTab->nVal+2 ){ /* lsm1_key */
- const void *pVal;
- int nVal;
- if( lsm_csr_key(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
- sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
- }
- }else if( i==pTab->nVal+3 ){ /* lsm1_value */
- const void *pVal;
- int nVal;
- if( lsm_csr_value(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
- sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
- }
- }
- }else if( lsm1DecodeValues(pCur) ){
- /* The i-th value column (where leftmost is 1) */
- const u8 *zData;
- u32 nData;
- i--;
- zData = pCur->zData + pCur->aiOfst[i];
- nData = pCur->aiLen[i];
- switch( pCur->aeType[i] ){
- case 0: { /* in-line integer */
- sqlite3_result_int(ctx, pCur->aiOfst[i]);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_int64 v;
- lsm1GetSignedVarint64(zData, nData, &v);
- sqlite3_result_int64(ctx, v);
- break;
- }
- case SQLITE_FLOAT: {
- double v;
- if( nData==sizeof(v) ){
- memcpy(&v, zData, sizeof(v));
- sqlite3_result_double(ctx, v);
- }
- break;
- }
- case SQLITE_TEXT: {
- sqlite3_result_text(ctx, (const char*)zData, nData, SQLITE_TRANSIENT);
- break;
- }
- case SQLITE_BLOB: {
- sqlite3_result_blob(ctx, zData, nData, SQLITE_TRANSIENT);
- break;
- }
- default: {
- /* A NULL. Do nothing */
- }
- }
- }
- return SQLITE_OK;
-}
-
-/* Parameter "pValue" contains an SQL value that is to be used as
-** a key in an LSM table. The type of the key is determined by
-** "keyType". Extract the raw bytes used for the key in LSM1.
-*/
-static void lsm1KeyFromValue(
- int keyType, /* The key type */
- sqlite3_value *pValue, /* The key value */
- u8 *pBuf, /* Storage space for a generated key */
- const u8 **ppKey, /* OUT: the bytes of the key */
- int *pnKey /* OUT: size of the key */
-){
- if( keyType==SQLITE_BLOB ){
- *ppKey = (const u8*)sqlite3_value_blob(pValue);
- *pnKey = sqlite3_value_bytes(pValue);
- }else if( keyType==SQLITE_TEXT ){
- *ppKey = (const u8*)sqlite3_value_text(pValue);
- *pnKey = sqlite3_value_bytes(pValue);
- }else{
- sqlite3_int64 v = sqlite3_value_int64(pValue);
- if( v<0 ) v = 0;
- *pnKey = lsm1PutVarint64(pBuf, v);
- *ppKey = pBuf;
- }
-}
-
-/* Move to the first row to return.
-*/
-static int lsm1Filter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- lsm1_cursor *pCur = (lsm1_cursor *)pVtabCursor;
- lsm1_vtab *pTab = (lsm1_vtab*)(pCur->base.pVtab);
- int rc = LSM_OK;
- int seekType = -1;
- const u8 *pVal = 0;
- int nVal;
- u8 keyType = pTab->keyType;
- u8 aKey1[16];
-
- pCur->atEof = 1;
- sqlite3_free(pCur->pKey2);
- pCur->pKey2 = 0;
- if( idxNum<99 ){
- lsm1KeyFromValue(keyType, argv[0], aKey1, &pVal, &nVal);
- }
- switch( idxNum ){
- case 0: { /* key==argv[0] */
- assert( argc==1 );
- seekType = LSM_SEEK_EQ;
- pCur->isDesc = 0;
- pCur->bUnique = 1;
- break;
- }
- case 1: { /* key>=argv[0] AND key<=argv[1] */
- u8 aKey[12];
- seekType = LSM_SEEK_GE;
- pCur->isDesc = 0;
- pCur->bUnique = 0;
- if( keyType==SQLITE_INTEGER ){
- sqlite3_int64 v = sqlite3_value_int64(argv[1]);
- if( v<0 ) v = 0;
- pCur->nKey2 = lsm1PutVarint64(aKey, (sqlite3_uint64)v);
- pCur->pKey2 = sqlite3_malloc( pCur->nKey2 );
- if( pCur->pKey2==0 ) return SQLITE_NOMEM;
- memcpy(pCur->pKey2, aKey, pCur->nKey2);
- }else{
- pCur->nKey2 = sqlite3_value_bytes(argv[1]);
- pCur->pKey2 = sqlite3_malloc( pCur->nKey2 );
- if( pCur->pKey2==0 ) return SQLITE_NOMEM;
- if( keyType==SQLITE_BLOB ){
- memcpy(pCur->pKey2, sqlite3_value_blob(argv[1]), pCur->nKey2);
- }else{
- memcpy(pCur->pKey2, sqlite3_value_text(argv[1]), pCur->nKey2);
- }
- }
- break;
- }
- case 2: { /* key>=argv[0] */
- seekType = LSM_SEEK_GE;
- pCur->isDesc = 0;
- pCur->bUnique = 0;
- break;
- }
- case 3: { /* key<=argv[0] */
- seekType = LSM_SEEK_LE;
- pCur->isDesc = 1;
- pCur->bUnique = 0;
- break;
- }
- default: { /* full table scan */
- pCur->isDesc = 0;
- pCur->bUnique = 0;
- break;
- }
- }
- if( pVal ){
- rc = lsm_csr_seek(pCur->pLsmCur, pVal, nVal, seekType);
- }else{
- rc = lsm_csr_first(pCur->pLsmCur);
- }
- if( rc==LSM_OK && lsm_csr_valid(pCur->pLsmCur)!=0 ){
- pCur->atEof = 0;
- }
- return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
-}
-
-/*
-** Only comparisons against the key are allowed. The idxNum defines
-** which comparisons are available:
-**
-** 0 key==?1
-** 1 key>=?1 AND key<=?2
-** 2 key>?1 or key>=?1
-** 3 key<?1 or key<=?1
-** 99 Full table scan only
-*/
-static int lsm1BestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i; /* Loop over constraints */
- int idxNum = 99; /* The query plan */
- int nArg = 0; /* Number of arguments to xFilter */
- int argIdx = -1; /* Index of the key== constraint, or -1 if none */
- int iIdx2 = -1; /* The index of the second key */
- int omit1 = 0;
- int omit2 = 0;
-
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint && idxNum<16; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->iColumn!=0 ) continue;
- switch( pConstraint->op ){
- case SQLITE_INDEX_CONSTRAINT_EQ: {
- if( idxNum>0 ){
- argIdx = i;
- iIdx2 = -1;
- idxNum = 0;
- omit1 = 1;
- }
- break;
- }
- case SQLITE_INDEX_CONSTRAINT_GE:
- case SQLITE_INDEX_CONSTRAINT_GT: {
- if( idxNum==99 ){
- argIdx = i;
- idxNum = 2;
- omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE;
- }else if( idxNum==3 ){
- iIdx2 = idxNum;
- omit2 = omit1;
- argIdx = i;
- idxNum = 1;
- omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE;
- }
- break;
- }
- case SQLITE_INDEX_CONSTRAINT_LE:
- case SQLITE_INDEX_CONSTRAINT_LT: {
- if( idxNum==99 ){
- argIdx = i;
- idxNum = 3;
- omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE;
- }else if( idxNum==2 ){
- iIdx2 = i;
- idxNum = 1;
- omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE;
- }
- break;
- }
- }
- }
- if( argIdx>=0 ){
- pIdxInfo->aConstraintUsage[argIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[argIdx].omit = omit1;
- }
- if( iIdx2>=0 ){
- pIdxInfo->aConstraintUsage[iIdx2].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[iIdx2].omit = omit2;
- }
- if( idxNum==0 ){
- pIdxInfo->estimatedCost = (double)1;
- pIdxInfo->estimatedRows = 1;
- pIdxInfo->orderByConsumed = 1;
- }else if( idxNum==1 ){
- pIdxInfo->estimatedCost = (double)100;
- pIdxInfo->estimatedRows = 100;
- }else if( idxNum<99 ){
- pIdxInfo->estimatedCost = (double)5000;
- pIdxInfo->estimatedRows = 5000;
- }else{
- /* Full table scan */
- pIdxInfo->estimatedCost = (double)2147483647;
- pIdxInfo->estimatedRows = 2147483647;
- }
- pIdxInfo->idxNum = idxNum;
- return SQLITE_OK;
-}
-
-/*
-** The xUpdate method is normally used for INSERT, REPLACE, UPDATE, and
-** DELETE. But this virtual table only supports INSERT and REPLACE.
-** DELETE is accomplished by inserting a record with a value of NULL.
-** UPDATE is achieved by using REPLACE.
-*/
-int lsm1Update(
- sqlite3_vtab *pVTab,
- int argc,
- sqlite3_value **argv,
- sqlite_int64 *pRowid
-){
- lsm1_vtab *p = (lsm1_vtab*)pVTab;
- int nKey, nKey2;
- int i;
- int rc = LSM_OK;
- const u8 *pKey, *pKey2;
- unsigned char aKey[16];
- unsigned char pSpace[16];
- lsm1_vblob val;
-
- if( argc==1 ){
- /* DELETE the record whose key is argv[0] */
- lsm1KeyFromValue(p->keyType, argv[0], aKey, &pKey, &nKey);
- lsm_delete(p->pDb, pKey, nKey);
- return SQLITE_OK;
- }
-
- if( sqlite3_value_type(argv[0])!=SQLITE_NULL ){
- /* An UPDATE */
- lsm1KeyFromValue(p->keyType, argv[0], aKey, &pKey, &nKey);
- lsm1KeyFromValue(p->keyType, argv[1], pSpace, &pKey2, &nKey2);
- if( nKey!=nKey2 || memcmp(pKey, pKey2, nKey)!=0 ){
- /* The UPDATE changes the PRIMARY KEY value. DELETE the old key */
- lsm_delete(p->pDb, pKey, nKey);
- }
- /* Fall through into the INSERT case to complete the UPDATE */
- }
-
- /* "INSERT INTO tab(lsm1_command) VALUES('....')" is used to implement
- ** special commands.
- */
- if( sqlite3_value_type(argv[3+p->nVal])!=SQLITE_NULL ){
- return SQLITE_OK;
- }
- lsm1KeyFromValue(p->keyType, argv[2], aKey, &pKey, &nKey);
- memset(&val, 0, sizeof(val));
- for(i=0; i<p->nVal; i++){
- sqlite3_value *pArg = argv[3+i];
- u8 eType = sqlite3_value_type(pArg);
- switch( eType ){
- case SQLITE_NULL: {
- lsm1VblobAppendVarint(&val, SQLITE_NULL);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_int64 v = sqlite3_value_int64(pArg);
- if( v>=0 && v<=240/6 ){
- lsm1VblobAppendVarint(&val, v*6);
- }else{
- int n = lsm1PutSignedVarint64(pSpace, v);
- lsm1VblobAppendVarint(&val, SQLITE_INTEGER + n*6);
- lsm1VblobAppend(&val, pSpace, n);
- }
- break;
- }
- case SQLITE_FLOAT: {
- double r = sqlite3_value_double(pArg);
- lsm1VblobAppendVarint(&val, SQLITE_FLOAT + 8*6);
- lsm1VblobAppend(&val, (u8*)&r, sizeof(r));
- break;
- }
- case SQLITE_BLOB: {
- int n = sqlite3_value_bytes(pArg);
- lsm1VblobAppendVarint(&val, n*6 + SQLITE_BLOB);
- lsm1VblobAppend(&val, sqlite3_value_blob(pArg), n);
- break;
- }
- case SQLITE_TEXT: {
- int n = sqlite3_value_bytes(pArg);
- lsm1VblobAppendVarint(&val, n*6 + SQLITE_TEXT);
- lsm1VblobAppend(&val, sqlite3_value_text(pArg), n);
- break;
- }
- }
- }
- if( val.errNoMem ){
- return SQLITE_NOMEM;
- }
- rc = lsm_insert(p->pDb, pKey, nKey, val.a, val.n);
- sqlite3_free(val.a);
- return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
-}
-
-/* Begin a transaction
-*/
-static int lsm1Begin(sqlite3_vtab *pVtab){
- lsm1_vtab *p = (lsm1_vtab*)pVtab;
- int rc = lsm_begin(p->pDb, 1);
- return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
-}
-
-/* Phase 1 of a transaction commit.
-*/
-static int lsm1Sync(sqlite3_vtab *pVtab){
- return SQLITE_OK;
-}
-
-/* Commit a transaction
-*/
-static int lsm1Commit(sqlite3_vtab *pVtab){
- lsm1_vtab *p = (lsm1_vtab*)pVtab;
- int rc = lsm_commit(p->pDb, 0);
- return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
-}
-
-/* Rollback a transaction
-*/
-static int lsm1Rollback(sqlite3_vtab *pVtab){
- lsm1_vtab *p = (lsm1_vtab*)pVtab;
- int rc = lsm_rollback(p->pDb, 0);
- return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
-}
-
-/*
-** This following structure defines all the methods for the
-** generate_lsm1 virtual table.
-*/
-static sqlite3_module lsm1Module = {
- 0, /* iVersion */
- lsm1Connect, /* xCreate */
- lsm1Connect, /* xConnect */
- lsm1BestIndex, /* xBestIndex */
- lsm1Disconnect, /* xDisconnect */
- lsm1Disconnect, /* xDestroy */
- lsm1Open, /* xOpen - open a cursor */
- lsm1Close, /* xClose - close a cursor */
- lsm1Filter, /* xFilter - configure scan constraints */
- lsm1Next, /* xNext - advance a cursor */
- lsm1Eof, /* xEof - check for end of scan */
- lsm1Column, /* xColumn - read data */
- lsm1Rowid, /* xRowid - read data */
- lsm1Update, /* xUpdate */
- lsm1Begin, /* xBegin */
- lsm1Sync, /* xSync */
- lsm1Commit, /* xCommit */
- lsm1Rollback, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_lsm_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- rc = sqlite3_create_module(db, "lsm1", &lsm1Module, 0);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_win32.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_win32.c
deleted file mode 100644
index 6c5d06b4c8e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/lsm_win32.c
+++ /dev/null
@@ -1,1063 +0,0 @@
-/*
-** 2011-12-03
-**
-** 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.
-**
-*************************************************************************
-**
-** Win32-specific run-time environment implementation for LSM.
-*/
-
-#ifdef _WIN32
-
-#include <assert.h>
-#include <string.h>
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include "windows.h"
-
-#include "lsmInt.h"
-
-/*
-** An open file is an instance of the following object
-*/
-typedef struct Win32File Win32File;
-struct Win32File {
- lsm_env *pEnv; /* The run-time environment */
- const char *zName; /* Full path to file */
-
- HANDLE hFile; /* Open file handle */
- HANDLE hShmFile; /* File handle for *-shm file */
-
- SYSTEM_INFO sysInfo; /* Operating system information */
- HANDLE hMap; /* File handle for mapping */
- LPVOID pMap; /* Pointer to mapping of file fd */
- size_t nMap; /* Size of mapping at pMap in bytes */
- int nShm; /* Number of entries in ahShm[]/apShm[] */
- LPHANDLE ahShm; /* Array of handles for shared mappings */
- LPVOID *apShm; /* Array of 32K shared memory segments */
-};
-
-static char *win32ShmFile(Win32File *pWin32File){
- char *zShm;
- int nName = strlen(pWin32File->zName);
- zShm = (char *)lsmMallocZero(pWin32File->pEnv, nName+4+1);
- if( zShm ){
- memcpy(zShm, pWin32File->zName, nName);
- memcpy(&zShm[nName], "-shm", 5);
- }
- return zShm;
-}
-
-static int win32Sleep(int us){
- Sleep((us + 999) / 1000);
- return LSM_OK;
-}
-
-/*
-** The number of times that an I/O operation will be retried following a
-** locking error - probably caused by antivirus software. Also the initial
-** delay before the first retry. The delay increases linearly with each
-** retry.
-*/
-#ifndef LSM_WIN32_IOERR_RETRY
-# define LSM_WIN32_IOERR_RETRY 10
-#endif
-#ifndef LSM_WIN32_IOERR_RETRY_DELAY
-# define LSM_WIN32_IOERR_RETRY_DELAY 25000
-#endif
-static int win32IoerrRetry = LSM_WIN32_IOERR_RETRY;
-static int win32IoerrRetryDelay = LSM_WIN32_IOERR_RETRY_DELAY;
-
-/*
-** The "win32IoerrCanRetry1" macro is used to determine if a particular
-** I/O error code obtained via GetLastError() is eligible to be retried.
-** It must accept the error code DWORD as its only argument and should
-** return non-zero if the error code is transient in nature and the
-** operation responsible for generating the original error might succeed
-** upon being retried. The argument to this macro should be a variable.
-**
-** Additionally, a macro named "win32IoerrCanRetry2" may be defined. If
-** it is defined, it will be consulted only when the macro
-** "win32IoerrCanRetry1" returns zero. The "win32IoerrCanRetry2" macro
-** is completely optional and may be used to include additional error
-** codes in the set that should result in the failing I/O operation being
-** retried by the caller. If defined, the "win32IoerrCanRetry2" macro
-** must exhibit external semantics identical to those of the
-** "win32IoerrCanRetry1" macro.
-*/
-#if !defined(win32IoerrCanRetry1)
-#define win32IoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \
- ((a)==ERROR_SHARING_VIOLATION) || \
- ((a)==ERROR_LOCK_VIOLATION) || \
- ((a)==ERROR_DEV_NOT_EXIST) || \
- ((a)==ERROR_NETNAME_DELETED) || \
- ((a)==ERROR_SEM_TIMEOUT) || \
- ((a)==ERROR_NETWORK_UNREACHABLE))
-#endif
-
-/*
-** If an I/O error occurs, invoke this routine to see if it should be
-** retried. Return TRUE to retry. Return FALSE to give up with an
-** error.
-*/
-static int win32RetryIoerr(
- lsm_env *pEnv,
- int *pnRetry
-){
- DWORD lastErrno;
- if( *pnRetry>=win32IoerrRetry ){
- return 0;
- }
- lastErrno = GetLastError();
- if( win32IoerrCanRetry1(lastErrno) ){
- win32Sleep(win32IoerrRetryDelay*(1+*pnRetry));
- ++*pnRetry;
- return 1;
- }
-#if defined(win32IoerrCanRetry2)
- else if( win32IoerrCanRetry2(lastErrno) ){
- win32Sleep(win32IoerrRetryDelay*(1+*pnRetry));
- ++*pnRetry;
- return 1;
- }
-#endif
- return 0;
-}
-
-/*
-** Convert a UTF-8 string to Microsoft Unicode.
-**
-** Space to hold the returned string is obtained from lsmMalloc().
-*/
-static LPWSTR win32Utf8ToUnicode(lsm_env *pEnv, const char *zText){
- int nChar;
- LPWSTR zWideText;
-
- nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
- if( nChar==0 ){
- return 0;
- }
- zWideText = lsmMallocZero(pEnv, nChar * sizeof(WCHAR));
- if( zWideText==0 ){
- return 0;
- }
- nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText, nChar);
- if( nChar==0 ){
- lsmFree(pEnv, zWideText);
- zWideText = 0;
- }
- return zWideText;
-}
-
-/*
-** Convert a Microsoft Unicode string to UTF-8.
-**
-** Space to hold the returned string is obtained from lsmMalloc().
-*/
-static char *win32UnicodeToUtf8(lsm_env *pEnv, LPCWSTR zWideText){
- int nByte;
- char *zText;
-
- nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
- if( nByte == 0 ){
- return 0;
- }
- zText = lsmMallocZero(pEnv, nByte);
- if( zText==0 ){
- return 0;
- }
- nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte, 0, 0);
- if( nByte == 0 ){
- lsmFree(pEnv, zText);
- zText = 0;
- }
- return zText;
-}
-
-#if !defined(win32IsNotFound)
-#define win32IsNotFound(a) (((a)==ERROR_FILE_NOT_FOUND) || \
- ((a)==ERROR_PATH_NOT_FOUND))
-#endif
-
-static int win32Open(
- lsm_env *pEnv,
- const char *zFile,
- int flags,
- LPHANDLE phFile
-){
- int rc;
- LPWSTR zConverted;
-
- zConverted = win32Utf8ToUnicode(pEnv, zFile);
- if( zConverted==0 ){
- rc = LSM_NOMEM_BKPT;
- }else{
- int bReadonly = (flags & LSM_OPEN_READONLY);
- DWORD dwDesiredAccess;
- DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
- DWORD dwCreationDisposition;
- DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
- HANDLE hFile;
- int nRetry = 0;
- if( bReadonly ){
- dwDesiredAccess = GENERIC_READ;
- dwCreationDisposition = OPEN_EXISTING;
- }else{
- dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
- dwCreationDisposition = OPEN_ALWAYS;
- }
- while( (hFile = CreateFileW((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL))==INVALID_HANDLE_VALUE &&
- win32RetryIoerr(pEnv, &nRetry) ){
- /* Noop */
- }
- lsmFree(pEnv, zConverted);
- if( hFile!=INVALID_HANDLE_VALUE ){
- *phFile = hFile;
- rc = LSM_OK;
- }else{
- if( win32IsNotFound(GetLastError()) ){
- rc = lsmErrorBkpt(LSM_IOERR_NOENT);
- }else{
- rc = LSM_IOERR_BKPT;
- }
- }
- }
- return rc;
-}
-
-static int lsmWin32OsOpen(
- lsm_env *pEnv,
- const char *zFile,
- int flags,
- lsm_file **ppFile
-){
- int rc = LSM_OK;
- Win32File *pWin32File;
-
- pWin32File = lsmMallocZero(pEnv, sizeof(Win32File));
- if( pWin32File==0 ){
- rc = LSM_NOMEM_BKPT;
- }else{
- HANDLE hFile = NULL;
-
- rc = win32Open(pEnv, zFile, flags, &hFile);
- if( rc==LSM_OK ){
- memset(&pWin32File->sysInfo, 0, sizeof(SYSTEM_INFO));
- GetSystemInfo(&pWin32File->sysInfo);
- pWin32File->pEnv = pEnv;
- pWin32File->zName = zFile;
- pWin32File->hFile = hFile;
- }else{
- lsmFree(pEnv, pWin32File);
- pWin32File = 0;
- }
- }
- *ppFile = (lsm_file *)pWin32File;
- return rc;
-}
-
-static int lsmWin32OsWrite(
- lsm_file *pFile, /* File to write to */
- lsm_i64 iOff, /* Offset to write to */
- void *pData, /* Write data from this buffer */
- int nData /* Bytes of data to write */
-){
- Win32File *pWin32File = (Win32File *)pFile;
- OVERLAPPED overlapped; /* The offset for WriteFile. */
- u8 *aRem = (u8 *)pData; /* Data yet to be written */
- int nRem = nData; /* Number of bytes yet to be written */
- int nRetry = 0; /* Number of retrys */
-
- memset(&overlapped, 0, sizeof(OVERLAPPED));
- overlapped.Offset = (LONG)(iOff & 0XFFFFFFFF);
- overlapped.OffsetHigh = (LONG)((iOff>>32) & 0x7FFFFFFF);
- while( nRem>0 ){
- DWORD nWrite = 0; /* Bytes written using WriteFile */
- if( !WriteFile(pWin32File->hFile, aRem, nRem, &nWrite, &overlapped) ){
- if( win32RetryIoerr(pWin32File->pEnv, &nRetry) ) continue;
- break;
- }
- assert( nWrite==0 || nWrite<=(DWORD)nRem );
- if( nWrite==0 || nWrite>(DWORD)nRem ){
- break;
- }
- iOff += nWrite;
- overlapped.Offset = (LONG)(iOff & 0xFFFFFFFF);
- overlapped.OffsetHigh = (LONG)((iOff>>32) & 0x7FFFFFFF);
- aRem += nWrite;
- nRem -= nWrite;
- }
- if( nRem!=0 ) return LSM_IOERR_BKPT;
- return LSM_OK;
-}
-
-static int win32Truncate(
- HANDLE hFile,
- lsm_i64 nSize
-){
- LARGE_INTEGER offset;
- offset.QuadPart = nSize;
- if( !SetFilePointerEx(hFile, offset, 0, FILE_BEGIN) ){
- return LSM_IOERR_BKPT;
- }
- if (!SetEndOfFile(hFile) ){
- return LSM_IOERR_BKPT;
- }
- return LSM_OK;
-}
-
-static int lsmWin32OsTruncate(
- lsm_file *pFile, /* File to write to */
- lsm_i64 nSize /* Size to truncate file to */
-){
- Win32File *pWin32File = (Win32File *)pFile;
- return win32Truncate(pWin32File->hFile, nSize);
-}
-
-static int lsmWin32OsRead(
- lsm_file *pFile, /* File to read from */
- lsm_i64 iOff, /* Offset to read from */
- void *pData, /* Read data into this buffer */
- int nData /* Bytes of data to read */
-){
- Win32File *pWin32File = (Win32File *)pFile;
- OVERLAPPED overlapped; /* The offset for ReadFile */
- DWORD nRead = 0; /* Bytes read using ReadFile */
- int nRetry = 0; /* Number of retrys */
-
- memset(&overlapped, 0, sizeof(OVERLAPPED));
- overlapped.Offset = (LONG)(iOff & 0XFFFFFFFF);
- overlapped.OffsetHigh = (LONG)((iOff>>32) & 0X7FFFFFFF);
- while( !ReadFile(pWin32File->hFile, pData, nData, &nRead, &overlapped) &&
- GetLastError()!=ERROR_HANDLE_EOF ){
- if( win32RetryIoerr(pWin32File->pEnv, &nRetry) ) continue;
- return LSM_IOERR_BKPT;
- }
- if( nRead<(DWORD)nData ){
- /* Unread parts of the buffer must be zero-filled */
- memset(&((char*)pData)[nRead], 0, nData - nRead);
- }
- return LSM_OK;
-}
-
-static int lsmWin32OsSync(lsm_file *pFile){
- int rc = LSM_OK;
-
-#ifndef LSM_NO_SYNC
- Win32File *pWin32File = (Win32File *)pFile;
-
- if( pWin32File->pMap!=NULL ){
- if( !FlushViewOfFile(pWin32File->pMap, 0) ){
- rc = LSM_IOERR_BKPT;
- }
- }
- if( rc==LSM_OK && !FlushFileBuffers(pWin32File->hFile) ){
- rc = LSM_IOERR_BKPT;
- }
-#else
- unused_parameter(pFile);
-#endif
-
- return rc;
-}
-
-static int lsmWin32OsSectorSize(lsm_file *pFile){
- return 512;
-}
-
-static void win32Unmap(Win32File *pWin32File){
- if( pWin32File->pMap!=NULL ){
- UnmapViewOfFile(pWin32File->pMap);
- pWin32File->pMap = NULL;
- pWin32File->nMap = 0;
- }
- if( pWin32File->hMap!=NULL ){
- CloseHandle(pWin32File->hMap);
- pWin32File->hMap = NULL;
- }
-}
-
-static int lsmWin32OsRemap(
- lsm_file *pFile,
- lsm_i64 iMin,
- void **ppOut,
- lsm_i64 *pnOut
-){
- Win32File *pWin32File = (Win32File *)pFile;
-
- /* If the file is between 0 and 2MB in size, extend it in chunks of 256K.
- ** Thereafter, in chunks of 1MB at a time. */
- const int aIncrSz[] = {256*1024, 1024*1024};
- int nIncrSz = aIncrSz[iMin>(2*1024*1024)];
-
- *ppOut = NULL;
- *pnOut = 0;
-
- win32Unmap(pWin32File);
- if( iMin>=0 ){
- LARGE_INTEGER fileSize;
- DWORD dwSizeHigh;
- DWORD dwSizeLow;
- HANDLE hMap;
- LPVOID pMap;
- memset(&fileSize, 0, sizeof(LARGE_INTEGER));
- if( !GetFileSizeEx(pWin32File->hFile, &fileSize) ){
- return LSM_IOERR_BKPT;
- }
- assert( fileSize.QuadPart>=0 );
- if( fileSize.QuadPart<iMin ){
- int rc;
- fileSize.QuadPart = ((iMin + nIncrSz-1) / nIncrSz) * nIncrSz;
- rc = lsmWin32OsTruncate(pFile, fileSize.QuadPart);
- if( rc!=LSM_OK ){
- return rc;
- }
- }
- dwSizeLow = (DWORD)(fileSize.QuadPart & 0xFFFFFFFF);
- dwSizeHigh = (DWORD)((fileSize.QuadPart & 0x7FFFFFFFFFFFFFFF) >> 32);
- hMap = CreateFileMappingW(pWin32File->hFile, NULL, PAGE_READWRITE,
- dwSizeHigh, dwSizeLow, NULL);
- if( hMap==NULL ){
- return LSM_IOERR_BKPT;
- }
- pWin32File->hMap = hMap;
- assert( fileSize.QuadPart<=0xFFFFFFFF );
- pMap = MapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0,
- (SIZE_T)fileSize.QuadPart);
- if( pMap==NULL ){
- return LSM_IOERR_BKPT;
- }
- pWin32File->pMap = pMap;
- pWin32File->nMap = (SIZE_T)fileSize.QuadPart;
- }
- *ppOut = pWin32File->pMap;
- *pnOut = pWin32File->nMap;
- return LSM_OK;
-}
-
-static BOOL win32IsDriveLetterAndColon(
- const char *zPathname
-){
- return ( isalpha(zPathname[0]) && zPathname[1]==':' );
-}
-
-static int lsmWin32OsFullpath(
- lsm_env *pEnv,
- const char *zName,
- char *zOut,
- int *pnOut
-){
- DWORD nByte;
- void *zConverted;
- LPWSTR zTempWide;
- char *zTempUtf8;
-
- if( zName[0]=='/' && win32IsDriveLetterAndColon(zName+1) ){
- zName++;
- }
- zConverted = win32Utf8ToUnicode(pEnv, zName);
- if( zConverted==0 ){
- return LSM_NOMEM_BKPT;
- }
- nByte = GetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
- if( nByte==0 ){
- lsmFree(pEnv, zConverted);
- return LSM_IOERR_BKPT;
- }
- nByte += 3;
- zTempWide = lsmMallocZero(pEnv, nByte * sizeof(zTempWide[0]));
- if( zTempWide==0 ){
- lsmFree(pEnv, zConverted);
- return LSM_NOMEM_BKPT;
- }
- nByte = GetFullPathNameW((LPCWSTR)zConverted, nByte, zTempWide, 0);
- if( nByte==0 ){
- lsmFree(pEnv, zConverted);
- lsmFree(pEnv, zTempWide);
- return LSM_IOERR_BKPT;
- }
- lsmFree(pEnv, zConverted);
- zTempUtf8 = win32UnicodeToUtf8(pEnv, zTempWide);
- lsmFree(pEnv, zTempWide);
- if( zTempUtf8 ){
- int nOut = *pnOut;
- int nLen = strlen(zTempUtf8) + 1;
- if( nLen<=nOut ){
- snprintf(zOut, nOut, "%s", zTempUtf8);
- }
- lsmFree(pEnv, zTempUtf8);
- *pnOut = nLen;
- return LSM_OK;
- }else{
- return LSM_NOMEM_BKPT;
- }
-}
-
-static int lsmWin32OsFileid(
- lsm_file *pFile,
- void *pBuf,
- int *pnBuf
-){
- int nBuf;
- int nReq;
- u8 *pBuf2 = (u8 *)pBuf;
- Win32File *pWin32File = (Win32File *)pFile;
- BY_HANDLE_FILE_INFORMATION fileInfo;
-
- nBuf = *pnBuf;
- nReq = (sizeof(fileInfo.dwVolumeSerialNumber) +
- sizeof(fileInfo.nFileIndexHigh) +
- sizeof(fileInfo.nFileIndexLow));
- *pnBuf = nReq;
- if( nReq>nBuf ) return LSM_OK;
- memset(&fileInfo, 0, sizeof(BY_HANDLE_FILE_INFORMATION));
- if( !GetFileInformationByHandle(pWin32File->hFile, &fileInfo) ){
- return LSM_IOERR_BKPT;
- }
- nReq = sizeof(fileInfo.dwVolumeSerialNumber);
- memcpy(pBuf2, &fileInfo.dwVolumeSerialNumber, nReq);
- pBuf2 += nReq;
- nReq = sizeof(fileInfo.nFileIndexHigh);
- memcpy(pBuf, &fileInfo.nFileIndexHigh, nReq);
- pBuf2 += nReq;
- nReq = sizeof(fileInfo.nFileIndexLow);
- memcpy(pBuf2, &fileInfo.nFileIndexLow, nReq);
- return LSM_OK;
-}
-
-static int win32Delete(
- lsm_env *pEnv,
- const char *zFile
-){
- int rc;
- LPWSTR zConverted;
-
- zConverted = win32Utf8ToUnicode(pEnv, zFile);
- if( zConverted==0 ){
- rc = LSM_NOMEM_BKPT;
- }else{
- int nRetry = 0;
- DWORD attr;
-
- do {
- attr = GetFileAttributesW(zConverted);
- if ( attr==INVALID_FILE_ATTRIBUTES ){
- rc = LSM_IOERR_BKPT;
- break;
- }
- if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
- rc = LSM_IOERR_BKPT; /* Files only. */
- break;
- }
- if ( DeleteFileW(zConverted) ){
- rc = LSM_OK; /* Deleted OK. */
- break;
- }
- if ( !win32RetryIoerr(pEnv, &nRetry) ){
- rc = LSM_IOERR_BKPT; /* No more retries. */
- break;
- }
- }while( 1 );
- }
- lsmFree(pEnv, zConverted);
- return rc;
-}
-
-static int lsmWin32OsUnlink(lsm_env *pEnv, const char *zFile){
- return win32Delete(pEnv, zFile);
-}
-
-#if !defined(win32IsLockBusy)
-#define win32IsLockBusy(a) (((a)==ERROR_LOCK_VIOLATION) || \
- ((a)==ERROR_IO_PENDING))
-#endif
-
-static int win32LockFile(
- Win32File *pWin32File,
- int iLock,
- int nLock,
- int eType
-){
- OVERLAPPED ovlp;
-
- assert( LSM_LOCK_UNLOCK==0 );
- assert( LSM_LOCK_SHARED==1 );
- assert( LSM_LOCK_EXCL==2 );
- assert( eType>=LSM_LOCK_UNLOCK && eType<=LSM_LOCK_EXCL );
- assert( nLock>=0 );
- assert( iLock>0 && iLock<=32 );
-
- memset(&ovlp, 0, sizeof(OVERLAPPED));
- ovlp.Offset = (4096-iLock-nLock+1);
- if( eType>LSM_LOCK_UNLOCK ){
- DWORD flags = LOCKFILE_FAIL_IMMEDIATELY;
- if( eType>=LSM_LOCK_EXCL ) flags |= LOCKFILE_EXCLUSIVE_LOCK;
- if( !LockFileEx(pWin32File->hFile, flags, 0, (DWORD)nLock, 0, &ovlp) ){
- if( win32IsLockBusy(GetLastError()) ){
- return LSM_BUSY;
- }else{
- return LSM_IOERR_BKPT;
- }
- }
- }else{
- if( !UnlockFileEx(pWin32File->hFile, 0, (DWORD)nLock, 0, &ovlp) ){
- return LSM_IOERR_BKPT;
- }
- }
- return LSM_OK;
-}
-
-static int lsmWin32OsLock(lsm_file *pFile, int iLock, int eType){
- Win32File *pWin32File = (Win32File *)pFile;
- return win32LockFile(pWin32File, iLock, 1, eType);
-}
-
-static int lsmWin32OsTestLock(lsm_file *pFile, int iLock, int nLock, int eType){
- int rc;
- Win32File *pWin32File = (Win32File *)pFile;
- rc = win32LockFile(pWin32File, iLock, nLock, eType);
- if( rc!=LSM_OK ) return rc;
- win32LockFile(pWin32File, iLock, nLock, LSM_LOCK_UNLOCK);
- return LSM_OK;
-}
-
-static int lsmWin32OsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
- int rc;
- Win32File *pWin32File = (Win32File *)pFile;
- int iOffset = iChunk * sz;
- int iOffsetShift = iOffset % pWin32File->sysInfo.dwAllocationGranularity;
- int nNew = iChunk + 1;
- lsm_i64 nReq = nNew * sz;
-
- *ppShm = NULL;
- assert( sz>=0 );
- assert( sz==LSM_SHM_CHUNK_SIZE );
- if( iChunk>=pWin32File->nShm ){
- LPHANDLE ahNew;
- LPVOID *apNew;
- LARGE_INTEGER fileSize;
-
- /* If the shared-memory file has not been opened, open it now. */
- if( pWin32File->hShmFile==NULL ){
- char *zShm = win32ShmFile(pWin32File);
- if( !zShm ) return LSM_NOMEM_BKPT;
- rc = win32Open(pWin32File->pEnv, zShm, 0, &pWin32File->hShmFile);
- lsmFree(pWin32File->pEnv, zShm);
- if( rc!=LSM_OK ){
- return rc;
- }
- }
-
- /* If the shared-memory file is not large enough to contain the
- ** requested chunk, cause it to grow. */
- memset(&fileSize, 0, sizeof(LARGE_INTEGER));
- if( !GetFileSizeEx(pWin32File->hShmFile, &fileSize) ){
- return LSM_IOERR_BKPT;
- }
- assert( fileSize.QuadPart>=0 );
- if( fileSize.QuadPart<nReq ){
- rc = win32Truncate(pWin32File->hShmFile, nReq);
- if( rc!=LSM_OK ){
- return rc;
- }
- }
-
- ahNew = (LPHANDLE)lsmMallocZero(pWin32File->pEnv, sizeof(HANDLE) * nNew);
- if( !ahNew ) return LSM_NOMEM_BKPT;
- apNew = (LPVOID *)lsmMallocZero(pWin32File->pEnv, sizeof(LPVOID) * nNew);
- if( !apNew ){
- lsmFree(pWin32File->pEnv, ahNew);
- return LSM_NOMEM_BKPT;
- }
- memcpy(ahNew, pWin32File->ahShm, sizeof(HANDLE) * pWin32File->nShm);
- memcpy(apNew, pWin32File->apShm, sizeof(LPVOID) * pWin32File->nShm);
- lsmFree(pWin32File->pEnv, pWin32File->ahShm);
- pWin32File->ahShm = ahNew;
- lsmFree(pWin32File->pEnv, pWin32File->apShm);
- pWin32File->apShm = apNew;
- pWin32File->nShm = nNew;
- }
-
- if( pWin32File->ahShm[iChunk]==NULL ){
- HANDLE hMap;
- assert( nReq<=0xFFFFFFFF );
- hMap = CreateFileMappingW(pWin32File->hShmFile, NULL, PAGE_READWRITE, 0,
- (DWORD)nReq, NULL);
- if( hMap==NULL ){
- return LSM_IOERR_BKPT;
- }
- pWin32File->ahShm[iChunk] = hMap;
- }
- if( pWin32File->apShm[iChunk]==NULL ){
- LPVOID pMap;
- pMap = MapViewOfFile(pWin32File->ahShm[iChunk],
- FILE_MAP_WRITE | FILE_MAP_READ, 0,
- iOffset - iOffsetShift, sz + iOffsetShift);
- if( pMap==NULL ){
- return LSM_IOERR_BKPT;
- }
- pWin32File->apShm[iChunk] = pMap;
- }
- if( iOffsetShift!=0 ){
- char *p = (char *)pWin32File->apShm[iChunk];
- *ppShm = (void *)&p[iOffsetShift];
- }else{
- *ppShm = pWin32File->apShm[iChunk];
- }
- return LSM_OK;
-}
-
-static void lsmWin32OsShmBarrier(void){
- MemoryBarrier();
-}
-
-static int lsmWin32OsShmUnmap(lsm_file *pFile, int bDelete){
- Win32File *pWin32File = (Win32File *)pFile;
-
- if( pWin32File->hShmFile!=NULL ){
- int i;
- for(i=0; i<pWin32File->nShm; i++){
- if( pWin32File->apShm[i]!=NULL ){
- UnmapViewOfFile(pWin32File->apShm[i]);
- pWin32File->apShm[i] = NULL;
- }
- if( pWin32File->ahShm[i]!=NULL ){
- CloseHandle(pWin32File->ahShm[i]);
- pWin32File->ahShm[i] = NULL;
- }
- }
- CloseHandle(pWin32File->hShmFile);
- pWin32File->hShmFile = NULL;
- if( bDelete ){
- char *zShm = win32ShmFile(pWin32File);
- if( zShm ){ win32Delete(pWin32File->pEnv, zShm); }
- lsmFree(pWin32File->pEnv, zShm);
- }
- }
- return LSM_OK;
-}
-
-#define MX_CLOSE_ATTEMPT 3
-static int lsmWin32OsClose(lsm_file *pFile){
- int rc;
- int nRetry = 0;
- Win32File *pWin32File = (Win32File *)pFile;
- lsmWin32OsShmUnmap(pFile, 0);
- win32Unmap(pWin32File);
- do{
- if( pWin32File->hFile==NULL ){
- rc = LSM_IOERR_BKPT;
- break;
- }
- rc = CloseHandle(pWin32File->hFile);
- if( rc ){
- pWin32File->hFile = NULL;
- rc = LSM_OK;
- break;
- }
- if( ++nRetry>=MX_CLOSE_ATTEMPT ){
- rc = LSM_IOERR_BKPT;
- break;
- }
- }while( 1 );
- lsmFree(pWin32File->pEnv, pWin32File->ahShm);
- lsmFree(pWin32File->pEnv, pWin32File->apShm);
- lsmFree(pWin32File->pEnv, pWin32File);
- return rc;
-}
-
-static int lsmWin32OsSleep(lsm_env *pEnv, int us){
- unused_parameter(pEnv);
- return win32Sleep(us);
-}
-
-/****************************************************************************
-** Memory allocation routines.
-*/
-
-static void *lsmWin32OsMalloc(lsm_env *pEnv, size_t N){
- assert( HeapValidate(GetProcessHeap(), 0, NULL) );
- return HeapAlloc(GetProcessHeap(), 0, (SIZE_T)N);
-}
-
-static void lsmWin32OsFree(lsm_env *pEnv, void *p){
- assert( HeapValidate(GetProcessHeap(), 0, NULL) );
- if( p ){
- HeapFree(GetProcessHeap(), 0, p);
- }
-}
-
-static void *lsmWin32OsRealloc(lsm_env *pEnv, void *p, size_t N){
- unsigned char *m = (unsigned char *)p;
- assert( HeapValidate(GetProcessHeap(), 0, NULL) );
- if( 1>N ){
- lsmWin32OsFree(pEnv, p);
- return NULL;
- }else if( NULL==p ){
- return lsmWin32OsMalloc(pEnv, N);
- }else{
-#if 0 /* arguable: don't shrink */
- SIZE_T sz = HeapSize(GetProcessHeap(), 0, m);
- if( sz>=(SIZE_T)N ){
- return p;
- }
-#endif
- return HeapReAlloc(GetProcessHeap(), 0, m, N);
- }
-}
-
-static size_t lsmWin32OsMSize(lsm_env *pEnv, void *p){
- assert( HeapValidate(GetProcessHeap(), 0, NULL) );
- return (size_t)HeapSize(GetProcessHeap(), 0, p);
-}
-
-
-#ifdef LSM_MUTEX_WIN32
-/*************************************************************************
-** Mutex methods for Win32 based systems. If LSM_MUTEX_WIN32 is
-** missing then a no-op implementation of mutexes found below will be
-** used instead.
-*/
-#include "windows.h"
-
-typedef struct Win32Mutex Win32Mutex;
-struct Win32Mutex {
- lsm_env *pEnv;
- CRITICAL_SECTION mutex;
-#ifdef LSM_DEBUG
- DWORD owner;
-#endif
-};
-
-#ifndef WIN32_MUTEX_INITIALIZER
-# define WIN32_MUTEX_INITIALIZER { 0 }
-#endif
-
-#ifdef LSM_DEBUG
-# define LSM_WIN32_STATIC_MUTEX { 0, WIN32_MUTEX_INITIALIZER, 0 }
-#else
-# define LSM_WIN32_STATIC_MUTEX { 0, WIN32_MUTEX_INITIALIZER }
-#endif
-
-static int lsmWin32OsMutexStatic(
- lsm_env *pEnv,
- int iMutex,
- lsm_mutex **ppStatic
-){
- static volatile LONG initialized = 0;
- static Win32Mutex sMutex[2] = {
- LSM_WIN32_STATIC_MUTEX,
- LSM_WIN32_STATIC_MUTEX
- };
-
- assert( iMutex==LSM_MUTEX_GLOBAL || iMutex==LSM_MUTEX_HEAP );
- assert( LSM_MUTEX_GLOBAL==1 && LSM_MUTEX_HEAP==2 );
-
- if( InterlockedCompareExchange(&initialized, 1, 0)==0 ){
- int i;
- for(i=0; i<array_size(sMutex); i++){
- InitializeCriticalSection(&sMutex[i].mutex);
- }
- }
- *ppStatic = (lsm_mutex *)&sMutex[iMutex-1];
- return LSM_OK;
-}
-
-static int lsmWin32OsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
- Win32Mutex *pMutex; /* Pointer to new mutex */
-
- pMutex = (Win32Mutex *)lsmMallocZero(pEnv, sizeof(Win32Mutex));
- if( !pMutex ) return LSM_NOMEM_BKPT;
-
- pMutex->pEnv = pEnv;
- InitializeCriticalSection(&pMutex->mutex);
-
- *ppNew = (lsm_mutex *)pMutex;
- return LSM_OK;
-}
-
-static void lsmWin32OsMutexDel(lsm_mutex *p){
- Win32Mutex *pMutex = (Win32Mutex *)p;
- DeleteCriticalSection(&pMutex->mutex);
- lsmFree(pMutex->pEnv, pMutex);
-}
-
-static void lsmWin32OsMutexEnter(lsm_mutex *p){
- Win32Mutex *pMutex = (Win32Mutex *)p;
- EnterCriticalSection(&pMutex->mutex);
-
-#ifdef LSM_DEBUG
- assert( pMutex->owner!=GetCurrentThreadId() );
- pMutex->owner = GetCurrentThreadId();
- assert( pMutex->owner==GetCurrentThreadId() );
-#endif
-}
-
-static int lsmWin32OsMutexTry(lsm_mutex *p){
- BOOL bRet;
- Win32Mutex *pMutex = (Win32Mutex *)p;
- bRet = TryEnterCriticalSection(&pMutex->mutex);
-#ifdef LSM_DEBUG
- if( bRet ){
- assert( pMutex->owner!=GetCurrentThreadId() );
- pMutex->owner = GetCurrentThreadId();
- assert( pMutex->owner==GetCurrentThreadId() );
- }
-#endif
- return !bRet;
-}
-
-static void lsmWin32OsMutexLeave(lsm_mutex *p){
- Win32Mutex *pMutex = (Win32Mutex *)p;
-#ifdef LSM_DEBUG
- assert( pMutex->owner==GetCurrentThreadId() );
- pMutex->owner = 0;
- assert( pMutex->owner!=GetCurrentThreadId() );
-#endif
- LeaveCriticalSection(&pMutex->mutex);
-}
-
-#ifdef LSM_DEBUG
-static int lsmWin32OsMutexHeld(lsm_mutex *p){
- Win32Mutex *pMutex = (Win32Mutex *)p;
- return pMutex ? pMutex->owner==GetCurrentThreadId() : 1;
-}
-static int lsmWin32OsMutexNotHeld(lsm_mutex *p){
- Win32Mutex *pMutex = (Win32Mutex *)p;
- return pMutex ? pMutex->owner!=GetCurrentThreadId() : 1;
-}
-#endif
-/*
-** End of Win32 mutex implementation.
-*************************************************************************/
-#else
-/*************************************************************************
-** Noop mutex implementation
-*/
-typedef struct NoopMutex NoopMutex;
-struct NoopMutex {
- lsm_env *pEnv; /* Environment handle (for xFree()) */
- int bHeld; /* True if mutex is held */
- int bStatic; /* True for a static mutex */
-};
-static NoopMutex aStaticNoopMutex[2] = {
- {0, 0, 1},
- {0, 0, 1},
-};
-
-static int lsmWin32OsMutexStatic(
- lsm_env *pEnv,
- int iMutex,
- lsm_mutex **ppStatic
-){
- assert( iMutex>=1 && iMutex<=(int)array_size(aStaticNoopMutex) );
- *ppStatic = (lsm_mutex *)&aStaticNoopMutex[iMutex-1];
- return LSM_OK;
-}
-static int lsmWin32OsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
- NoopMutex *p;
- p = (NoopMutex *)lsmMallocZero(pEnv, sizeof(NoopMutex));
- if( p ) p->pEnv = pEnv;
- *ppNew = (lsm_mutex *)p;
- return (p ? LSM_OK : LSM_NOMEM_BKPT);
-}
-static void lsmWin32OsMutexDel(lsm_mutex *pMutex) {
- NoopMutex *p = (NoopMutex *)pMutex;
- assert( p->bStatic==0 && p->pEnv );
- lsmFree(p->pEnv, p);
-}
-static void lsmWin32OsMutexEnter(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- assert( p->bHeld==0 );
- p->bHeld = 1;
-}
-static int lsmWin32OsMutexTry(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- assert( p->bHeld==0 );
- p->bHeld = 1;
- return 0;
-}
-static void lsmWin32OsMutexLeave(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- assert( p->bHeld==1 );
- p->bHeld = 0;
-}
-#ifdef LSM_DEBUG
-static int lsmWin32OsMutexHeld(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- return p ? p->bHeld : 1;
-}
-static int lsmWin32OsMutexNotHeld(lsm_mutex *pMutex){
- NoopMutex *p = (NoopMutex *)pMutex;
- return p ? !p->bHeld : 1;
-}
-#endif
-/***************************************************************************/
-#endif /* else LSM_MUTEX_NONE */
-
-/* Without LSM_DEBUG, the MutexHeld tests are never called */
-#ifndef LSM_DEBUG
-# define lsmWin32OsMutexHeld 0
-# define lsmWin32OsMutexNotHeld 0
-#endif
-
-lsm_env *lsm_default_env(void){
- static lsm_env win32_env = {
- sizeof(lsm_env), /* nByte */
- 1, /* iVersion */
- /***** file i/o ******************/
- 0, /* pVfsCtx */
- lsmWin32OsFullpath, /* xFullpath */
- lsmWin32OsOpen, /* xOpen */
- lsmWin32OsRead, /* xRead */
- lsmWin32OsWrite, /* xWrite */
- lsmWin32OsTruncate, /* xTruncate */
- lsmWin32OsSync, /* xSync */
- lsmWin32OsSectorSize, /* xSectorSize */
- lsmWin32OsRemap, /* xRemap */
- lsmWin32OsFileid, /* xFileid */
- lsmWin32OsClose, /* xClose */
- lsmWin32OsUnlink, /* xUnlink */
- lsmWin32OsLock, /* xLock */
- lsmWin32OsTestLock, /* xTestLock */
- lsmWin32OsShmMap, /* xShmMap */
- lsmWin32OsShmBarrier, /* xShmBarrier */
- lsmWin32OsShmUnmap, /* xShmUnmap */
- /***** memory allocation *********/
- 0, /* pMemCtx */
- lsmWin32OsMalloc, /* xMalloc */
- lsmWin32OsRealloc, /* xRealloc */
- lsmWin32OsFree, /* xFree */
- lsmWin32OsMSize, /* xSize */
- /***** mutexes *********************/
- 0, /* pMutexCtx */
- lsmWin32OsMutexStatic, /* xMutexStatic */
- lsmWin32OsMutexNew, /* xMutexNew */
- lsmWin32OsMutexDel, /* xMutexDel */
- lsmWin32OsMutexEnter, /* xMutexEnter */
- lsmWin32OsMutexTry, /* xMutexTry */
- lsmWin32OsMutexLeave, /* xMutexLeave */
- lsmWin32OsMutexHeld, /* xMutexHeld */
- lsmWin32OsMutexNotHeld, /* xMutexNotHeld */
- /***** other *********************/
- lsmWin32OsSleep, /* xSleep */
- };
- return &win32_env;
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/tool/mklsm1c.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/tool/mklsm1c.tcl
deleted file mode 100644
index d4a317b7003..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/lsm1/tool/mklsm1c.tcl
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/bin/sh
-# restart with tclsh \
-exec tclsh "$0" "$@"
-
-set srcdir [file dirname [file dirname [info script]]]
-set G(src) [string map [list %dir% $srcdir] {
- %dir%/lsm.h
- %dir%/lsmInt.h
- %dir%/lsm_vtab.c
- %dir%/lsm_ckpt.c
- %dir%/lsm_file.c
- %dir%/lsm_log.c
- %dir%/lsm_main.c
- %dir%/lsm_mem.c
- %dir%/lsm_mutex.c
- %dir%/lsm_shared.c
- %dir%/lsm_sorted.c
- %dir%/lsm_str.c
- %dir%/lsm_tree.c
- %dir%/lsm_unix.c
- %dir%/lsm_varint.c
- %dir%/lsm_win32.c
-}]
-
-set G(hdr) {
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_LSM1)
-
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
-# define NDEBUG 1
-#endif
-#if defined(NDEBUG) && defined(SQLITE_DEBUG)
-# undef NDEBUG
-#endif
-
-}
-
-set G(footer) {
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_LSM1) */
-}
-
-#-------------------------------------------------------------------------
-# Read and return the entire contents of text file $zFile from disk.
-#
-proc readfile {zFile} {
- set fd [open $zFile]
- set data [read $fd]
- close $fd
- return $data
-}
-
-proc lsm1c_init {zOut} {
- global G
- set G(fd) stdout
- set G(fd) [open $zOut w]
-
- puts -nonewline $G(fd) $G(hdr)
-}
-
-proc lsm1c_printfile {zIn} {
- global G
- set data [readfile $zIn]
- set zTail [file tail $zIn]
- puts $G(fd) "#line 1 \"$zTail\""
-
- foreach line [split $data "\n"] {
- if {[regexp {^# *include.*lsm} $line]} {
- set line "/* $line */"
- } elseif { [regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?lsm[^_]} $line] } {
- set line "static $line"
- }
- puts $G(fd) $line
- }
-}
-
-proc lsm1c_close {} {
- global G
- puts -nonewline $G(fd) $G(footer)
- if {$G(fd)!="stdout"} {
- close $G(fd)
- }
-}
-
-
-lsm1c_init lsm1.c
-foreach f $G(src) { lsm1c_printfile $f }
-lsm1c_close
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/README.md b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/README.md
deleted file mode 100644
index 69cb230255e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/README.md
+++ /dev/null
@@ -1,60 +0,0 @@
-## Miscellaneous Extensions
-
-This folder contains a collection of smaller loadable extensions.
-See <https://www.sqlite.org/loadext.html> for instructions on how
-to compile and use loadable extensions.
-Each extension in this folder is implemented in a single file of C code.
-
-Each source file contains a description in its header comment. See the
-header comments for details about each extension. Additional notes are
-as follows:
-
- * **carray.c** &mdash; This module implements the
- [carray](https://www.sqlite.org/carray.html) table-valued function.
- It is a good example of how to go about implementing a custom
- [table-valued function](https://www.sqlite.org/vtab.html#tabfunc2).
-
- * **csv.c** &mdash; A [virtual table](https://sqlite.org/vtab.html)
- for reading
- [Comma-Separated-Value (CSV) files](https://en.wikipedia.org/wiki/Comma-separated_values).
-
- * **dbdump.c** &mdash; This is not actually a loadable extension, but
- rather a library that implements an approximate equivalent to the
- ".dump" command of the
- [command-line shell](https://www.sqlite.org/cli.html).
-
- * **json1.c** &mdash; Various SQL functions and table-valued functions
- for processing JSON. This extension is already built into the
- [SQLite amalgamation](https://sqlite.org/amalgamation.html). See
- <https://sqlite.org/json1.html> for additional information.
-
- * **memvfs.c** &mdash; This file implements a custom
- [VFS](https://www.sqlite.org/vfs.html) that stores an entire database
- file in a single block of RAM. It serves as a good example of how
- to implement a simple custom VFS.
-
- * **rot13.c** &mdash; This file implements the very simple rot13()
- substitution function. This file makes a good template for implementing
- new custom SQL functions for SQLite.
-
- * **series.c** &mdash; This is an implementation of the
- "generate_series" [virtual table](https://www.sqlite.org/vtab.html).
- It can make a good template for new custom virtual table implementations.
-
- * **shathree.c** &mdash; An implementation of the sha3() and
- sha3_query() SQL functions. The file is named "shathree.c" instead
- of "sha3.c" because the default entry point names in SQLite are based
- on the source filename with digits removed, so if we used the name
- "sha3.c" then the entry point would conflict with the prior "sha1.c"
- extension.
-
- * **unionvtab.c** &mdash; Implementation of the unionvtab and
- [swarmvtab](https://sqlite.org/swarmvtab.html) virtual tables.
- These virtual tables allow a single
- large table to be spread out across multiple database files. In the
- case of swarmvtab, the individual database files can be attached on
- demand.
-
- * **zipfile.c** &mdash; A [virtual table](https://sqlite.org/vtab.html)
- that can read and write a
- [ZIP archive](https://en.wikipedia.org/wiki/Zip_%28file_format%29).
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/amatch.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/amatch.c
deleted file mode 100644
index 914e2633d4b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/amatch.c
+++ /dev/null
@@ -1,1499 +0,0 @@
-/*
-** 2013-03-14
-**
-** 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 contains code for a demonstration virtual table that finds
-** "approximate matches" - strings from a finite set that are nearly the
-** same as a single input string. The virtual table is called "amatch".
-**
-** A amatch virtual table is created like this:
-**
-** CREATE VIRTUAL TABLE f USING approximate_match(
-** vocabulary_table=<tablename>, -- V
-** vocabulary_word=<columnname>, -- W
-** vocabulary_language=<columnname>, -- L
-** edit_distances=<edit-cost-table>
-** );
-**
-** When it is created, the new amatch table must be supplied with the
-** the name of a table V and columns V.W and V.L such that
-**
-** SELECT W FROM V WHERE L=$language
-**
-** returns the allowed vocabulary for the match. If the "vocabulary_language"
-** or L columnname is left unspecified or is an empty string, then no
-** filtering of the vocabulary by language is performed.
-**
-** For efficiency, it is essential that the vocabulary table be indexed:
-**
-** CREATE vocab_index ON V(W)
-**
-** A separate edit-cost-table provides scoring information that defines
-** what it means for one string to be "close" to another.
-**
-** The edit-cost-table must contain exactly four columns (more precisely,
-** the statement "SELECT * FROM <edit-cost-table>" must return records
-** that consist of four columns). It does not matter what the columns are
-** named.
-**
-** Each row in the edit-cost-table represents a single character
-** transformation going from user input to the vocabulary. The leftmost
-** column of the row (column 0) contains an integer identifier of the
-** language to which the transformation rule belongs (see "MULTIPLE LANGUAGES"
-** below). The second column of the row (column 1) contains the input
-** character or characters - the characters of user input. The third
-** column contains characters as they appear in the vocabulary table.
-** And the fourth column contains the integer cost of making the
-** transformation. For example:
-**
-** CREATE TABLE f_data(iLang, cFrom, cTo, Cost);
-** INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, '', 'a', 100);
-** INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, 'b', '', 87);
-** INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, 'o', 'oe', 38);
-** INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, 'oe', 'o', 40);
-**
-** The first row inserted into the edit-cost-table by the SQL script
-** above indicates that the cost of having an extra 'a' in the vocabulary
-** table that is missing in the user input 100. (All costs are integers.
-** Overall cost must not exceed 16777216.) The second INSERT statement
-** creates a rule saying that the cost of having a single letter 'b' in
-** user input which is missing in the vocabulary table is 87. The third
-** INSERT statement mean that the cost of matching an 'o' in user input
-** against an 'oe' in the vocabulary table is 38. And so forth.
-**
-** The following rules are special:
-**
-** INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, '?', '', 97);
-** INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, '', '?', 98);
-** INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, '?', '?', 99);
-**
-** The '?' to '' rule is the cost of having any single character in the input
-** that is not found in the vocabular. The '' to '?' rule is the cost of
-** having a character in the vocabulary table that is missing from input.
-** And the '?' to '?' rule is the cost of doing an arbitrary character
-** substitution. These three generic rules apply across all languages.
-** In other words, the iLang field is ignored for the generic substitution
-** rules. If more than one cost is given for a generic substitution rule,
-** then the lowest cost is used.
-**
-** Once it has been created, the amatch virtual table can be queried
-** as follows:
-**
-** SELECT word, distance FROM f
-** WHERE word MATCH 'abcdefg'
-** AND distance<200;
-**
-** This query outputs the strings contained in the T(F) field that
-** are close to "abcdefg" and in order of increasing distance. No string
-** is output more than once. If there are multiple ways to transform the
-** target string ("abcdefg") into a string in the vocabulary table then
-** the lowest cost transform is the one that is returned. In this example,
-** the search is limited to strings with a total distance of less than 200.
-**
-** For efficiency, it is important to put tight bounds on the distance.
-** The time and memory space needed to perform this query is exponential
-** in the maximum distance. A good rule of thumb is to limit the distance
-** to no more than 1.5 or 2 times the maximum cost of any rule in the
-** edit-cost-table.
-**
-** The amatch is a read-only table. Any attempt to DELETE, INSERT, or
-** UPDATE on a amatch table will throw an error.
-**
-** It is important to put some kind of a limit on the amatch output. This
-** can be either in the form of a LIMIT clause at the end of the query,
-** or better, a "distance<NNN" constraint where NNN is some number. The
-** running time and memory requirement is exponential in the value of NNN
-** so you want to make sure that NNN is not too big. A value of NNN that
-** is about twice the average transformation cost seems to give good results.
-**
-** The amatch table can be useful for tasks such as spelling correction.
-** Suppose all allowed words are in table vocabulary(w). Then one would create
-** an amatch virtual table like this:
-**
-** CREATE VIRTUAL TABLE ex1 USING amatch(
-** vocabtable=vocabulary,
-** vocabcolumn=w,
-** edit_distances=ec1
-** );
-**
-** Then given an input word $word, look up close spellings this way:
-**
-** SELECT word, distance FROM ex1
-** WHERE word MATCH $word AND distance<200;
-**
-** MULTIPLE LANGUAGES
-**
-** Normally, the "iLang" value associated with all character transformations
-** in the edit-cost-table is zero. However, if required, the amatch
-** virtual table allows multiple languages to be defined. Each query uses
-** only a single iLang value. This allows, for example, a single
-** amatch table to support multiple languages.
-**
-** By default, only the rules with iLang=0 are used. To specify an
-** alternative language, a "language = ?" expression must be added to the
-** WHERE clause of a SELECT, where ? is the integer identifier of the desired
-** language. For example:
-**
-** SELECT word, distance FROM ex1
-** WHERE word MATCH $word
-** AND distance<=200
-** AND language=1 -- Specify use language 1 instead of 0
-**
-** If no "language = ?" constraint is specified in the WHERE clause, language
-** 0 is used.
-**
-** LIMITS
-**
-** The maximum language number is 2147483647. The maximum length of either
-** of the strings in the second or third column of the amatch data table
-** is 50 bytes. The maximum cost on a rule is 1000.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Forward declaration of objects used by this implementation
-*/
-typedef struct amatch_vtab amatch_vtab;
-typedef struct amatch_cursor amatch_cursor;
-typedef struct amatch_rule amatch_rule;
-typedef struct amatch_word amatch_word;
-typedef struct amatch_avl amatch_avl;
-
-
-/*****************************************************************************
-** AVL Tree implementation
-*/
-/*
-** Objects that want to be members of the AVL tree should embedded an
-** instance of this structure.
-*/
-struct amatch_avl {
- amatch_word *pWord; /* Points to the object being stored in the tree */
- char *zKey; /* Key. zero-terminated string. Must be unique */
- amatch_avl *pBefore; /* Other elements less than zKey */
- amatch_avl *pAfter; /* Other elements greater than zKey */
- amatch_avl *pUp; /* Parent element */
- short int height; /* Height of this node. Leaf==1 */
- short int imbalance; /* Height difference between pBefore and pAfter */
-};
-
-/* Recompute the amatch_avl.height and amatch_avl.imbalance fields for p.
-** Assume that the children of p have correct heights.
-*/
-static void amatchAvlRecomputeHeight(amatch_avl *p){
- short int hBefore = p->pBefore ? p->pBefore->height : 0;
- short int hAfter = p->pAfter ? p->pAfter->height : 0;
- p->imbalance = hBefore - hAfter; /* -: pAfter higher. +: pBefore higher */
- p->height = (hBefore>hAfter ? hBefore : hAfter)+1;
-}
-
-/*
-** P B
-** / \ / \
-** B Z ==> X P
-** / \ / \
-** X Y Y Z
-**
-*/
-static amatch_avl *amatchAvlRotateBefore(amatch_avl *pP){
- amatch_avl *pB = pP->pBefore;
- amatch_avl *pY = pB->pAfter;
- pB->pUp = pP->pUp;
- pB->pAfter = pP;
- pP->pUp = pB;
- pP->pBefore = pY;
- if( pY ) pY->pUp = pP;
- amatchAvlRecomputeHeight(pP);
- amatchAvlRecomputeHeight(pB);
- return pB;
-}
-
-/*
-** P A
-** / \ / \
-** X A ==> P Z
-** / \ / \
-** Y Z X Y
-**
-*/
-static amatch_avl *amatchAvlRotateAfter(amatch_avl *pP){
- amatch_avl *pA = pP->pAfter;
- amatch_avl *pY = pA->pBefore;
- pA->pUp = pP->pUp;
- pA->pBefore = pP;
- pP->pUp = pA;
- pP->pAfter = pY;
- if( pY ) pY->pUp = pP;
- amatchAvlRecomputeHeight(pP);
- amatchAvlRecomputeHeight(pA);
- return pA;
-}
-
-/*
-** Return a pointer to the pBefore or pAfter pointer in the parent
-** of p that points to p. Or if p is the root node, return pp.
-*/
-static amatch_avl **amatchAvlFromPtr(amatch_avl *p, amatch_avl **pp){
- amatch_avl *pUp = p->pUp;
- if( pUp==0 ) return pp;
- if( pUp->pAfter==p ) return &pUp->pAfter;
- return &pUp->pBefore;
-}
-
-/*
-** Rebalance all nodes starting with p and working up to the root.
-** Return the new root.
-*/
-static amatch_avl *amatchAvlBalance(amatch_avl *p){
- amatch_avl *pTop = p;
- amatch_avl **pp;
- while( p ){
- amatchAvlRecomputeHeight(p);
- if( p->imbalance>=2 ){
- amatch_avl *pB = p->pBefore;
- if( pB->imbalance<0 ) p->pBefore = amatchAvlRotateAfter(pB);
- pp = amatchAvlFromPtr(p,&p);
- p = *pp = amatchAvlRotateBefore(p);
- }else if( p->imbalance<=(-2) ){
- amatch_avl *pA = p->pAfter;
- if( pA->imbalance>0 ) p->pAfter = amatchAvlRotateBefore(pA);
- pp = amatchAvlFromPtr(p,&p);
- p = *pp = amatchAvlRotateAfter(p);
- }
- pTop = p;
- p = p->pUp;
- }
- return pTop;
-}
-
-/* Search the tree rooted at p for an entry with zKey. Return a pointer
-** to the entry or return NULL.
-*/
-static amatch_avl *amatchAvlSearch(amatch_avl *p, const char *zKey){
- int c;
- while( p && (c = strcmp(zKey, p->zKey))!=0 ){
- p = (c<0) ? p->pBefore : p->pAfter;
- }
- return p;
-}
-
-/* Find the first node (the one with the smallest key).
-*/
-static amatch_avl *amatchAvlFirst(amatch_avl *p){
- if( p ) while( p->pBefore ) p = p->pBefore;
- return p;
-}
-
-#if 0 /* NOT USED */
-/* Return the node with the next larger key after p.
-*/
-static amatch_avl *amatchAvlNext(amatch_avl *p){
- amatch_avl *pPrev = 0;
- while( p && p->pAfter==pPrev ){
- pPrev = p;
- p = p->pUp;
- }
- if( p && pPrev==0 ){
- p = amatchAvlFirst(p->pAfter);
- }
- return p;
-}
-#endif
-
-#if 0 /* NOT USED */
-/* Verify AVL tree integrity
-*/
-static int amatchAvlIntegrity(amatch_avl *pHead){
- amatch_avl *p;
- if( pHead==0 ) return 1;
- if( (p = pHead->pBefore)!=0 ){
- assert( p->pUp==pHead );
- assert( amatchAvlIntegrity(p) );
- assert( strcmp(p->zKey, pHead->zKey)<0 );
- while( p->pAfter ) p = p->pAfter;
- assert( strcmp(p->zKey, pHead->zKey)<0 );
- }
- if( (p = pHead->pAfter)!=0 ){
- assert( p->pUp==pHead );
- assert( amatchAvlIntegrity(p) );
- assert( strcmp(p->zKey, pHead->zKey)>0 );
- p = amatchAvlFirst(p);
- assert( strcmp(p->zKey, pHead->zKey)>0 );
- }
- return 1;
-}
-static int amatchAvlIntegrity2(amatch_avl *pHead){
- amatch_avl *p, *pNext;
- for(p=amatchAvlFirst(pHead); p; p=pNext){
- pNext = amatchAvlNext(p);
- if( pNext==0 ) break;
- assert( strcmp(p->zKey, pNext->zKey)<0 );
- }
- return 1;
-}
-#endif
-
-/* Insert a new node pNew. Return NULL on success. If the key is not
-** unique, then do not perform the insert but instead leave pNew unchanged
-** and return a pointer to an existing node with the same key.
-*/
-static amatch_avl *amatchAvlInsert(amatch_avl **ppHead, amatch_avl *pNew){
- int c;
- amatch_avl *p = *ppHead;
- if( p==0 ){
- p = pNew;
- pNew->pUp = 0;
- }else{
- while( p ){
- c = strcmp(pNew->zKey, p->zKey);
- if( c<0 ){
- if( p->pBefore ){
- p = p->pBefore;
- }else{
- p->pBefore = pNew;
- pNew->pUp = p;
- break;
- }
- }else if( c>0 ){
- if( p->pAfter ){
- p = p->pAfter;
- }else{
- p->pAfter = pNew;
- pNew->pUp = p;
- break;
- }
- }else{
- return p;
- }
- }
- }
- pNew->pBefore = 0;
- pNew->pAfter = 0;
- pNew->height = 1;
- pNew->imbalance = 0;
- *ppHead = amatchAvlBalance(p);
- /* assert( amatchAvlIntegrity(*ppHead) ); */
- /* assert( amatchAvlIntegrity2(*ppHead) ); */
- return 0;
-}
-
-/* Remove node pOld from the tree. pOld must be an element of the tree or
-** the AVL tree will become corrupt.
-*/
-static void amatchAvlRemove(amatch_avl **ppHead, amatch_avl *pOld){
- amatch_avl **ppParent;
- amatch_avl *pBalance = 0;
- /* assert( amatchAvlSearch(*ppHead, pOld->zKey)==pOld ); */
- ppParent = amatchAvlFromPtr(pOld, ppHead);
- if( pOld->pBefore==0 && pOld->pAfter==0 ){
- *ppParent = 0;
- pBalance = pOld->pUp;
- }else if( pOld->pBefore && pOld->pAfter ){
- amatch_avl *pX, *pY;
- pX = amatchAvlFirst(pOld->pAfter);
- *amatchAvlFromPtr(pX, 0) = pX->pAfter;
- if( pX->pAfter ) pX->pAfter->pUp = pX->pUp;
- pBalance = pX->pUp;
- pX->pAfter = pOld->pAfter;
- if( pX->pAfter ){
- pX->pAfter->pUp = pX;
- }else{
- assert( pBalance==pOld );
- pBalance = pX;
- }
- pX->pBefore = pY = pOld->pBefore;
- if( pY ) pY->pUp = pX;
- pX->pUp = pOld->pUp;
- *ppParent = pX;
- }else if( pOld->pBefore==0 ){
- *ppParent = pBalance = pOld->pAfter;
- pBalance->pUp = pOld->pUp;
- }else if( pOld->pAfter==0 ){
- *ppParent = pBalance = pOld->pBefore;
- pBalance->pUp = pOld->pUp;
- }
- *ppHead = amatchAvlBalance(pBalance);
- pOld->pUp = 0;
- pOld->pBefore = 0;
- pOld->pAfter = 0;
- /* assert( amatchAvlIntegrity(*ppHead) ); */
- /* assert( amatchAvlIntegrity2(*ppHead) ); */
-}
-/*
-** End of the AVL Tree implementation
-******************************************************************************/
-
-
-/*
-** Various types.
-**
-** amatch_cost is the "cost" of an edit operation.
-**
-** amatch_len is the length of a matching string.
-**
-** amatch_langid is an ruleset identifier.
-*/
-typedef int amatch_cost;
-typedef signed char amatch_len;
-typedef int amatch_langid;
-
-/*
-** Limits
-*/
-#define AMATCH_MX_LENGTH 50 /* Maximum length of a rule string */
-#define AMATCH_MX_LANGID 2147483647 /* Maximum rule ID */
-#define AMATCH_MX_COST 1000 /* Maximum single-rule cost */
-
-/*
-** A match or partial match
-*/
-struct amatch_word {
- amatch_word *pNext; /* Next on a list of all amatch_words */
- amatch_avl sCost; /* Linkage of this node into the cost tree */
- amatch_avl sWord; /* Linkage of this node into the word tree */
- amatch_cost rCost; /* Cost of the match so far */
- int iSeq; /* Sequence number */
- char zCost[10]; /* Cost key (text rendering of rCost) */
- short int nMatch; /* Input characters matched */
- char zWord[4]; /* Text of the word. Extra space appended as needed */
-};
-
-/*
-** Each transformation rule is stored as an instance of this object.
-** All rules are kept on a linked list sorted by rCost.
-*/
-struct amatch_rule {
- amatch_rule *pNext; /* Next rule in order of increasing rCost */
- char *zFrom; /* Transform from (a string from user input) */
- amatch_cost rCost; /* Cost of this transformation */
- amatch_langid iLang; /* The langauge to which this rule belongs */
- amatch_len nFrom, nTo; /* Length of the zFrom and zTo strings */
- char zTo[4]; /* Tranform to V.W value (extra space appended) */
-};
-
-/*
-** A amatch virtual-table object
-*/
-struct amatch_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- char *zClassName; /* Name of this class. Default: "amatch" */
- char *zDb; /* Name of database. (ex: "main") */
- char *zSelf; /* Name of this virtual table */
- char *zCostTab; /* Name of edit-cost-table */
- char *zVocabTab; /* Name of vocabulary table */
- char *zVocabWord; /* Name of vocabulary table word column */
- char *zVocabLang; /* Name of vocabulary table language column */
- amatch_rule *pRule; /* All active rules in this amatch */
- amatch_cost rIns; /* Generic insertion cost '' -> ? */
- amatch_cost rDel; /* Generic deletion cost ? -> '' */
- amatch_cost rSub; /* Generic substitution cost ? -> ? */
- sqlite3 *db; /* The database connection */
- sqlite3_stmt *pVCheck; /* Query to check zVocabTab */
- int nCursor; /* Number of active cursors */
-};
-
-/* A amatch cursor object */
-struct amatch_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3_int64 iRowid; /* The rowid of the current word */
- amatch_langid iLang; /* Use this language ID */
- amatch_cost rLimit; /* Maximum cost of any term */
- int nBuf; /* Space allocated for zBuf */
- int oomErr; /* True following an OOM error */
- int nWord; /* Number of amatch_word objects */
- char *zBuf; /* Temp-use buffer space */
- char *zInput; /* Input word to match against */
- amatch_vtab *pVtab; /* The virtual table this cursor belongs to */
- amatch_word *pAllWords; /* List of all amatch_word objects */
- amatch_word *pCurrent; /* Most recent solution */
- amatch_avl *pCost; /* amatch_word objects keyed by iCost */
- amatch_avl *pWord; /* amatch_word objects keyed by zWord */
-};
-
-/*
-** The two input rule lists are both sorted in order of increasing
-** cost. Merge them together into a single list, sorted by cost, and
-** return a pointer to the head of that list.
-*/
-static amatch_rule *amatchMergeRules(amatch_rule *pA, amatch_rule *pB){
- amatch_rule head;
- amatch_rule *pTail;
-
- pTail = &head;
- while( pA && pB ){
- if( pA->rCost<=pB->rCost ){
- pTail->pNext = pA;
- pTail = pA;
- pA = pA->pNext;
- }else{
- pTail->pNext = pB;
- pTail = pB;
- pB = pB->pNext;
- }
- }
- if( pA==0 ){
- pTail->pNext = pB;
- }else{
- pTail->pNext = pA;
- }
- return head.pNext;
-}
-
-/*
-** Statement pStmt currently points to a row in the amatch data table. This
-** function allocates and populates a amatch_rule structure according to
-** the content of the row.
-**
-** If successful, *ppRule is set to point to the new object and SQLITE_OK
-** is returned. Otherwise, *ppRule is zeroed, *pzErr may be set to point
-** to an error message and an SQLite error code returned.
-*/
-static int amatchLoadOneRule(
- amatch_vtab *p, /* Fuzzer virtual table handle */
- sqlite3_stmt *pStmt, /* Base rule on statements current row */
- amatch_rule **ppRule, /* OUT: New rule object */
- char **pzErr /* OUT: Error message */
-){
- sqlite3_int64 iLang = sqlite3_column_int64(pStmt, 0);
- const char *zFrom = (const char *)sqlite3_column_text(pStmt, 1);
- const char *zTo = (const char *)sqlite3_column_text(pStmt, 2);
- amatch_cost rCost = sqlite3_column_int(pStmt, 3);
-
- int rc = SQLITE_OK; /* Return code */
- int nFrom; /* Size of string zFrom, in bytes */
- int nTo; /* Size of string zTo, in bytes */
- amatch_rule *pRule = 0; /* New rule object to return */
-
- if( zFrom==0 ) zFrom = "";
- if( zTo==0 ) zTo = "";
- nFrom = (int)strlen(zFrom);
- nTo = (int)strlen(zTo);
-
- /* Silently ignore null transformations */
- if( strcmp(zFrom, zTo)==0 ){
- if( zFrom[0]=='?' && zFrom[1]==0 ){
- if( p->rSub==0 || p->rSub>rCost ) p->rSub = rCost;
- }
- *ppRule = 0;
- return SQLITE_OK;
- }
-
- if( rCost<=0 || rCost>AMATCH_MX_COST ){
- *pzErr = sqlite3_mprintf("%s: cost must be between 1 and %d",
- p->zClassName, AMATCH_MX_COST
- );
- rc = SQLITE_ERROR;
- }else
- if( nFrom>AMATCH_MX_LENGTH || nTo>AMATCH_MX_LENGTH ){
- *pzErr = sqlite3_mprintf("%s: maximum string length is %d",
- p->zClassName, AMATCH_MX_LENGTH
- );
- rc = SQLITE_ERROR;
- }else
- if( iLang<0 || iLang>AMATCH_MX_LANGID ){
- *pzErr = sqlite3_mprintf("%s: iLang must be between 0 and %d",
- p->zClassName, AMATCH_MX_LANGID
- );
- rc = SQLITE_ERROR;
- }else
- if( strcmp(zFrom,"")==0 && strcmp(zTo,"?")==0 ){
- if( p->rIns==0 || p->rIns>rCost ) p->rIns = rCost;
- }else
- if( strcmp(zFrom,"?")==0 && strcmp(zTo,"")==0 ){
- if( p->rDel==0 || p->rDel>rCost ) p->rDel = rCost;
- }else
- {
- pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
- if( pRule==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pRule, 0, sizeof(*pRule));
- pRule->zFrom = &pRule->zTo[nTo+1];
- pRule->nFrom = (amatch_len)nFrom;
- memcpy(pRule->zFrom, zFrom, nFrom+1);
- memcpy(pRule->zTo, zTo, nTo+1);
- pRule->nTo = (amatch_len)nTo;
- pRule->rCost = rCost;
- pRule->iLang = (int)iLang;
- }
- }
-
- *ppRule = pRule;
- return rc;
-}
-
-/*
-** Free all the content in the edit-cost-table
-*/
-static void amatchFreeRules(amatch_vtab *p){
- while( p->pRule ){
- amatch_rule *pRule = p->pRule;
- p->pRule = pRule->pNext;
- sqlite3_free(pRule);
- }
- p->pRule = 0;
-}
-
-/*
-** Load the content of the amatch data table into memory.
-*/
-static int amatchLoadRules(
- sqlite3 *db, /* Database handle */
- amatch_vtab *p, /* Virtual amatch table to configure */
- char **pzErr /* OUT: Error message */
-){
- int rc = SQLITE_OK; /* Return code */
- char *zSql; /* SELECT used to read from rules table */
- amatch_rule *pHead = 0;
-
- zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", p->zDb, p->zCostTab);
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int rc2; /* finalize() return code */
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- *pzErr = sqlite3_mprintf("%s: %s", p->zClassName, sqlite3_errmsg(db));
- }else if( sqlite3_column_count(pStmt)!=4 ){
- *pzErr = sqlite3_mprintf("%s: %s has %d columns, expected 4",
- p->zClassName, p->zCostTab, sqlite3_column_count(pStmt)
- );
- rc = SQLITE_ERROR;
- }else{
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- amatch_rule *pRule = 0;
- rc = amatchLoadOneRule(p, pStmt, &pRule, pzErr);
- if( pRule ){
- pRule->pNext = pHead;
- pHead = pRule;
- }
- }
- }
- rc2 = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) rc = rc2;
- }
- sqlite3_free(zSql);
-
- /* All rules are now in a singly linked list starting at pHead. This
- ** block sorts them by cost and then sets amatch_vtab.pRule to point to
- ** point to the head of the sorted list.
- */
- if( rc==SQLITE_OK ){
- unsigned int i;
- amatch_rule *pX;
- amatch_rule *a[15];
- for(i=0; i<sizeof(a)/sizeof(a[0]); i++) a[i] = 0;
- while( (pX = pHead)!=0 ){
- pHead = pX->pNext;
- pX->pNext = 0;
- for(i=0; a[i] && i<sizeof(a)/sizeof(a[0])-1; i++){
- pX = amatchMergeRules(a[i], pX);
- a[i] = 0;
- }
- a[i] = amatchMergeRules(a[i], pX);
- }
- for(pX=a[0], i=1; i<sizeof(a)/sizeof(a[0]); i++){
- pX = amatchMergeRules(a[i], pX);
- }
- p->pRule = amatchMergeRules(p->pRule, pX);
- }else{
- /* An error has occurred. Setting p->pRule to point to the head of the
- ** allocated list ensures that the list will be cleaned up in this case.
- */
- assert( p->pRule==0 );
- p->pRule = pHead;
- }
-
- return rc;
-}
-
-/*
-** This function converts an SQL quoted string into an unquoted string
-** and returns a pointer to a buffer allocated using sqlite3_malloc()
-** containing the result. The caller should eventually free this buffer
-** using sqlite3_free.
-**
-** Examples:
-**
-** "abc" becomes abc
-** 'xyz' becomes xyz
-** [pqr] becomes pqr
-** `mno` becomes mno
-*/
-static char *amatchDequote(const char *zIn){
- int nIn; /* Size of input string, in bytes */
- char *zOut; /* Output (dequoted) string */
-
- nIn = (int)strlen(zIn);
- zOut = sqlite3_malloc(nIn+1);
- if( zOut ){
- char q = zIn[0]; /* Quote character (if any ) */
-
- if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
- memcpy(zOut, zIn, nIn+1);
- }else{
- int iOut = 0; /* Index of next byte to write to output */
- int iIn; /* Index of next byte to read from input */
-
- if( q=='[' ) q = ']';
- for(iIn=1; iIn<nIn; iIn++){
- if( zIn[iIn]==q ) iIn++;
- zOut[iOut++] = zIn[iIn];
- }
- }
- assert( (int)strlen(zOut)<=nIn );
- }
- return zOut;
-}
-
-/*
-** Deallocate the pVCheck prepared statement.
-*/
-static void amatchVCheckClear(amatch_vtab *p){
- if( p->pVCheck ){
- sqlite3_finalize(p->pVCheck);
- p->pVCheck = 0;
- }
-}
-
-/*
-** Deallocate an amatch_vtab object
-*/
-static void amatchFree(amatch_vtab *p){
- if( p ){
- amatchFreeRules(p);
- amatchVCheckClear(p);
- sqlite3_free(p->zClassName);
- sqlite3_free(p->zDb);
- sqlite3_free(p->zCostTab);
- sqlite3_free(p->zVocabTab);
- sqlite3_free(p->zVocabWord);
- sqlite3_free(p->zVocabLang);
- sqlite3_free(p->zSelf);
- memset(p, 0, sizeof(*p));
- sqlite3_free(p);
- }
-}
-
-/*
-** xDisconnect/xDestroy method for the amatch module.
-*/
-static int amatchDisconnect(sqlite3_vtab *pVtab){
- amatch_vtab *p = (amatch_vtab*)pVtab;
- assert( p->nCursor==0 );
- amatchFree(p);
- return SQLITE_OK;
-}
-
-/*
-** Check to see if the argument is of the form:
-**
-** KEY = VALUE
-**
-** If it is, return a pointer to the first character of VALUE.
-** If not, return NULL. Spaces around the = are ignored.
-*/
-static const char *amatchValueOfKey(const char *zKey, const char *zStr){
- int nKey = (int)strlen(zKey);
- int nStr = (int)strlen(zStr);
- int i;
- if( nStr<nKey+1 ) return 0;
- if( memcmp(zStr, zKey, nKey)!=0 ) return 0;
- for(i=nKey; isspace((unsigned char)zStr[i]); i++){}
- if( zStr[i]!='=' ) return 0;
- i++;
- while( isspace((unsigned char)zStr[i]) ){ i++; }
- return zStr+i;
-}
-
-/*
-** xConnect/xCreate method for the amatch module. Arguments are:
-**
-** argv[0] -> module name ("approximate_match")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[3...] -> arguments
-*/
-static int amatchConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- int rc = SQLITE_OK; /* Return code */
- amatch_vtab *pNew = 0; /* New virtual table */
- const char *zModule = argv[0];
- const char *zDb = argv[1];
- const char *zVal;
- int i;
-
- (void)pAux;
- *ppVtab = 0;
- pNew = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- rc = SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- pNew->db = db;
- pNew->zClassName = sqlite3_mprintf("%s", zModule);
- if( pNew->zClassName==0 ) goto amatchConnectError;
- pNew->zDb = sqlite3_mprintf("%s", zDb);
- if( pNew->zDb==0 ) goto amatchConnectError;
- pNew->zSelf = sqlite3_mprintf("%s", argv[2]);
- if( pNew->zSelf==0 ) goto amatchConnectError;
- for(i=3; i<argc; i++){
- zVal = amatchValueOfKey("vocabulary_table", argv[i]);
- if( zVal ){
- sqlite3_free(pNew->zVocabTab);
- pNew->zVocabTab = amatchDequote(zVal);
- if( pNew->zVocabTab==0 ) goto amatchConnectError;
- continue;
- }
- zVal = amatchValueOfKey("vocabulary_word", argv[i]);
- if( zVal ){
- sqlite3_free(pNew->zVocabWord);
- pNew->zVocabWord = amatchDequote(zVal);
- if( pNew->zVocabWord==0 ) goto amatchConnectError;
- continue;
- }
- zVal = amatchValueOfKey("vocabulary_language", argv[i]);
- if( zVal ){
- sqlite3_free(pNew->zVocabLang);
- pNew->zVocabLang = amatchDequote(zVal);
- if( pNew->zVocabLang==0 ) goto amatchConnectError;
- continue;
- }
- zVal = amatchValueOfKey("edit_distances", argv[i]);
- if( zVal ){
- sqlite3_free(pNew->zCostTab);
- pNew->zCostTab = amatchDequote(zVal);
- if( pNew->zCostTab==0 ) goto amatchConnectError;
- continue;
- }
- *pzErr = sqlite3_mprintf("unrecognized argument: [%s]\n", argv[i]);
- amatchFree(pNew);
- *ppVtab = 0;
- return SQLITE_ERROR;
- }
- rc = SQLITE_OK;
- if( pNew->zCostTab==0 ){
- *pzErr = sqlite3_mprintf("no edit_distances table specified");
- rc = SQLITE_ERROR;
- }else{
- rc = amatchLoadRules(db, pNew, pzErr);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(word,distance,language,"
- "command HIDDEN,nword HIDDEN)"
- );
-#define AMATCH_COL_WORD 0
-#define AMATCH_COL_DISTANCE 1
-#define AMATCH_COL_LANGUAGE 2
-#define AMATCH_COL_COMMAND 3
-#define AMATCH_COL_NWORD 4
- }
- if( rc!=SQLITE_OK ){
- amatchFree(pNew);
- }
- *ppVtab = &pNew->base;
- return rc;
-
-amatchConnectError:
- amatchFree(pNew);
- return rc;
-}
-
-/*
-** Open a new amatch cursor.
-*/
-static int amatchOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- amatch_vtab *p = (amatch_vtab*)pVTab;
- amatch_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->pVtab = p;
- *ppCursor = &pCur->base;
- p->nCursor++;
- return SQLITE_OK;
-}
-
-/*
-** Free up all the memory allocated by a cursor. Set it rLimit to 0
-** to indicate that it is at EOF.
-*/
-static void amatchClearCursor(amatch_cursor *pCur){
- amatch_word *pWord, *pNextWord;
- for(pWord=pCur->pAllWords; pWord; pWord=pNextWord){
- pNextWord = pWord->pNext;
- sqlite3_free(pWord);
- }
- pCur->pAllWords = 0;
- sqlite3_free(pCur->zInput);
- pCur->zInput = 0;
- sqlite3_free(pCur->zBuf);
- pCur->zBuf = 0;
- pCur->nBuf = 0;
- pCur->pCost = 0;
- pCur->pWord = 0;
- pCur->pCurrent = 0;
- pCur->rLimit = 1000000;
- pCur->iLang = 0;
- pCur->nWord = 0;
-}
-
-/*
-** Close a amatch cursor.
-*/
-static int amatchClose(sqlite3_vtab_cursor *cur){
- amatch_cursor *pCur = (amatch_cursor *)cur;
- amatchClearCursor(pCur);
- pCur->pVtab->nCursor--;
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Render a 24-bit unsigned integer as a 4-byte base-64 number.
-*/
-static void amatchEncodeInt(int x, char *z){
- static const char a[] =
- "0123456789"
- "ABCDEFGHIJ"
- "KLMNOPQRST"
- "UVWXYZ^abc"
- "defghijklm"
- "nopqrstuvw"
- "xyz~";
- z[0] = a[(x>>18)&0x3f];
- z[1] = a[(x>>12)&0x3f];
- z[2] = a[(x>>6)&0x3f];
- z[3] = a[x&0x3f];
-}
-
-/*
-** Write the zCost[] field for a amatch_word object
-*/
-static void amatchWriteCost(amatch_word *pWord){
- amatchEncodeInt(pWord->rCost, pWord->zCost);
- amatchEncodeInt(pWord->iSeq, pWord->zCost+4);
- pWord->zCost[8] = 0;
-}
-
-/* Circumvent compiler warnings about the use of strcpy() by supplying
-** our own implementation.
-*/
-static void amatchStrcpy(char *dest, const char *src){
- while( (*(dest++) = *(src++))!=0 ){}
-}
-static void amatchStrcat(char *dest, const char *src){
- while( *dest ) dest++;
- amatchStrcpy(dest, src);
-}
-
-/*
-** Add a new amatch_word object to the queue.
-**
-** If a prior amatch_word object with the same zWord, and nMatch
-** already exists, update its rCost (if the new rCost is less) but
-** otherwise leave it unchanged. Do not add a duplicate.
-**
-** Do nothing if the cost exceeds threshold.
-*/
-static void amatchAddWord(
- amatch_cursor *pCur,
- amatch_cost rCost,
- int nMatch,
- const char *zWordBase,
- const char *zWordTail
-){
- amatch_word *pWord;
- amatch_avl *pNode;
- amatch_avl *pOther;
- int nBase, nTail;
- char zBuf[4];
-
- if( rCost>pCur->rLimit ){
- return;
- }
- nBase = (int)strlen(zWordBase);
- nTail = (int)strlen(zWordTail);
- if( nBase+nTail+3>pCur->nBuf ){
- pCur->nBuf = nBase+nTail+100;
- pCur->zBuf = sqlite3_realloc(pCur->zBuf, pCur->nBuf);
- if( pCur->zBuf==0 ){
- pCur->nBuf = 0;
- return;
- }
- }
- amatchEncodeInt(nMatch, zBuf);
- memcpy(pCur->zBuf, zBuf+2, 2);
- memcpy(pCur->zBuf+2, zWordBase, nBase);
- memcpy(pCur->zBuf+2+nBase, zWordTail, nTail+1);
- pNode = amatchAvlSearch(pCur->pWord, pCur->zBuf);
- if( pNode ){
- pWord = pNode->pWord;
- if( pWord->rCost>rCost ){
-#ifdef AMATCH_TRACE_1
- printf("UPDATE [%s][%.*s^%s] %d (\"%s\" \"%s\")\n",
- pWord->zWord+2, pWord->nMatch, pCur->zInput, pCur->zInput,
- pWord->rCost, pWord->zWord, pWord->zCost);
-#endif
- amatchAvlRemove(&pCur->pCost, &pWord->sCost);
- pWord->rCost = rCost;
- amatchWriteCost(pWord);
-#ifdef AMATCH_TRACE_1
- printf(" ---> %d (\"%s\" \"%s\")\n",
- pWord->rCost, pWord->zWord, pWord->zCost);
-#endif
- pOther = amatchAvlInsert(&pCur->pCost, &pWord->sCost);
- assert( pOther==0 ); (void)pOther;
- }
- return;
- }
- pWord = sqlite3_malloc( sizeof(*pWord) + nBase + nTail - 1 );
- if( pWord==0 ) return;
- memset(pWord, 0, sizeof(*pWord));
- pWord->rCost = rCost;
- pWord->iSeq = pCur->nWord++;
- amatchWriteCost(pWord);
- pWord->nMatch = (short)nMatch;
- pWord->pNext = pCur->pAllWords;
- pCur->pAllWords = pWord;
- pWord->sCost.zKey = pWord->zCost;
- pWord->sCost.pWord = pWord;
- pOther = amatchAvlInsert(&pCur->pCost, &pWord->sCost);
- assert( pOther==0 ); (void)pOther;
- pWord->sWord.zKey = pWord->zWord;
- pWord->sWord.pWord = pWord;
- amatchStrcpy(pWord->zWord, pCur->zBuf);
- pOther = amatchAvlInsert(&pCur->pWord, &pWord->sWord);
- assert( pOther==0 ); (void)pOther;
-#ifdef AMATCH_TRACE_1
- printf("INSERT [%s][%.*s^%s] %d (\"%s\" \"%s\")\n", pWord->zWord+2,
- pWord->nMatch, pCur->zInput, pCur->zInput+pWord->nMatch, rCost,
- pWord->zWord, pWord->zCost);
-#endif
-}
-
-
-/*
-** Advance a cursor to its next row of output
-*/
-static int amatchNext(sqlite3_vtab_cursor *cur){
- amatch_cursor *pCur = (amatch_cursor*)cur;
- amatch_word *pWord = 0;
- amatch_avl *pNode;
- int isMatch = 0;
- amatch_vtab *p = pCur->pVtab;
- int nWord;
- int rc;
- int i;
- const char *zW;
- amatch_rule *pRule;
- char *zBuf = 0;
- char nBuf = 0;
- char zNext[8];
- char zNextIn[8];
- int nNextIn;
-
- if( p->pVCheck==0 ){
- char *zSql;
- if( p->zVocabLang && p->zVocabLang[0] ){
- zSql = sqlite3_mprintf(
- "SELECT \"%w\" FROM \"%w\"",
- " WHERE \"%w\">=?1 AND \"%w\"=?2"
- " ORDER BY 1",
- p->zVocabWord, p->zVocabTab,
- p->zVocabWord, p->zVocabLang
- );
- }else{
- zSql = sqlite3_mprintf(
- "SELECT \"%w\" FROM \"%w\""
- " WHERE \"%w\">=?1"
- " ORDER BY 1",
- p->zVocabWord, p->zVocabTab,
- p->zVocabWord
- );
- }
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &p->pVCheck, 0);
- sqlite3_free(zSql);
- if( rc ) return rc;
- }
- sqlite3_bind_int(p->pVCheck, 2, pCur->iLang);
-
- do{
- pNode = amatchAvlFirst(pCur->pCost);
- if( pNode==0 ){
- pWord = 0;
- break;
- }
- pWord = pNode->pWord;
- amatchAvlRemove(&pCur->pCost, &pWord->sCost);
-
-#ifdef AMATCH_TRACE_1
- printf("PROCESS [%s][%.*s^%s] %d (\"%s\" \"%s\")\n",
- pWord->zWord+2, pWord->nMatch, pCur->zInput, pCur->zInput+pWord->nMatch,
- pWord->rCost, pWord->zWord, pWord->zCost);
-#endif
- nWord = (int)strlen(pWord->zWord+2);
- if( nWord+20>nBuf ){
- nBuf = (char)(nWord+100);
- zBuf = sqlite3_realloc(zBuf, nBuf);
- if( zBuf==0 ) return SQLITE_NOMEM;
- }
- amatchStrcpy(zBuf, pWord->zWord+2);
- zNext[0] = 0;
- zNextIn[0] = pCur->zInput[pWord->nMatch];
- if( zNextIn[0] ){
- for(i=1; i<=4 && (pCur->zInput[pWord->nMatch+i]&0xc0)==0x80; i++){
- zNextIn[i] = pCur->zInput[pWord->nMatch+i];
- }
- zNextIn[i] = 0;
- nNextIn = i;
- }else{
- nNextIn = 0;
- }
-
- if( zNextIn[0] && zNextIn[0]!='*' ){
- sqlite3_reset(p->pVCheck);
- amatchStrcat(zBuf, zNextIn);
- sqlite3_bind_text(p->pVCheck, 1, zBuf, nWord+nNextIn, SQLITE_STATIC);
- rc = sqlite3_step(p->pVCheck);
- if( rc==SQLITE_ROW ){
- zW = (const char*)sqlite3_column_text(p->pVCheck, 0);
- if( strncmp(zBuf, zW, nWord+nNextIn)==0 ){
- amatchAddWord(pCur, pWord->rCost, pWord->nMatch+nNextIn, zBuf, "");
- }
- }
- zBuf[nWord] = 0;
- }
-
- while( 1 ){
- amatchStrcpy(zBuf+nWord, zNext);
- sqlite3_reset(p->pVCheck);
- sqlite3_bind_text(p->pVCheck, 1, zBuf, -1, SQLITE_TRANSIENT);
- rc = sqlite3_step(p->pVCheck);
- if( rc!=SQLITE_ROW ) break;
- zW = (const char*)sqlite3_column_text(p->pVCheck, 0);
- amatchStrcpy(zBuf+nWord, zNext);
- if( strncmp(zW, zBuf, nWord)!=0 ) break;
- if( (zNextIn[0]=='*' && zNextIn[1]==0)
- || (zNextIn[0]==0 && zW[nWord]==0)
- ){
- isMatch = 1;
- zNextIn[0] = 0;
- nNextIn = 0;
- break;
- }
- zNext[0] = zW[nWord];
- for(i=1; i<=4 && (zW[nWord+i]&0xc0)==0x80; i++){
- zNext[i] = zW[nWord+i];
- }
- zNext[i] = 0;
- zBuf[nWord] = 0;
- if( p->rIns>0 ){
- amatchAddWord(pCur, pWord->rCost+p->rIns, pWord->nMatch,
- zBuf, zNext);
- }
- if( p->rSub>0 ){
- amatchAddWord(pCur, pWord->rCost+p->rSub, pWord->nMatch+nNextIn,
- zBuf, zNext);
- }
- if( p->rIns<0 && p->rSub<0 ) break;
- zNext[i-1]++; /* FIX ME */
- }
- sqlite3_reset(p->pVCheck);
-
- if( p->rDel>0 ){
- zBuf[nWord] = 0;
- amatchAddWord(pCur, pWord->rCost+p->rDel, pWord->nMatch+nNextIn,
- zBuf, "");
- }
-
- for(pRule=p->pRule; pRule; pRule=pRule->pNext){
- if( pRule->iLang!=pCur->iLang ) continue;
- if( strncmp(pRule->zFrom, pCur->zInput+pWord->nMatch, pRule->nFrom)==0 ){
- amatchAddWord(pCur, pWord->rCost+pRule->rCost,
- pWord->nMatch+pRule->nFrom, pWord->zWord+2, pRule->zTo);
- }
- }
- }while( !isMatch );
- pCur->pCurrent = pWord;
- sqlite3_free(zBuf);
- return SQLITE_OK;
-}
-
-/*
-** Called to "rewind" a cursor back to the beginning so that
-** it starts its output over again. Always called at least once
-** prior to any amatchColumn, amatchRowid, or amatchEof call.
-*/
-static int amatchFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- amatch_cursor *pCur = (amatch_cursor *)pVtabCursor;
- const char *zWord = "*";
- int idx;
-
- amatchClearCursor(pCur);
- idx = 0;
- if( idxNum & 1 ){
- zWord = (const char*)sqlite3_value_text(argv[0]);
- idx++;
- }
- if( idxNum & 2 ){
- pCur->rLimit = (amatch_cost)sqlite3_value_int(argv[idx]);
- idx++;
- }
- if( idxNum & 4 ){
- pCur->iLang = (amatch_cost)sqlite3_value_int(argv[idx]);
- idx++;
- }
- pCur->zInput = sqlite3_mprintf("%s", zWord);
- if( pCur->zInput==0 ) return SQLITE_NOMEM;
- amatchAddWord(pCur, 0, 0, "", "");
- amatchNext(pVtabCursor);
-
- return SQLITE_OK;
-}
-
-/*
-** Only the word and distance columns have values. All other columns
-** return NULL
-*/
-static int amatchColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- amatch_cursor *pCur = (amatch_cursor*)cur;
- switch( i ){
- case AMATCH_COL_WORD: {
- sqlite3_result_text(ctx, pCur->pCurrent->zWord+2, -1, SQLITE_STATIC);
- break;
- }
- case AMATCH_COL_DISTANCE: {
- sqlite3_result_int(ctx, pCur->pCurrent->rCost);
- break;
- }
- case AMATCH_COL_LANGUAGE: {
- sqlite3_result_int(ctx, pCur->iLang);
- break;
- }
- case AMATCH_COL_NWORD: {
- sqlite3_result_int(ctx, pCur->nWord);
- break;
- }
- default: {
- sqlite3_result_null(ctx);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** The rowid.
-*/
-static int amatchRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- amatch_cursor *pCur = (amatch_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** EOF indicator
-*/
-static int amatchEof(sqlite3_vtab_cursor *cur){
- amatch_cursor *pCur = (amatch_cursor*)cur;
- return pCur->pCurrent==0;
-}
-
-/*
-** Search for terms of these forms:
-**
-** (A) word MATCH $str
-** (B1) distance < $value
-** (B2) distance <= $value
-** (C) language == $language
-**
-** The distance< and distance<= are both treated as distance<=.
-** The query plan number is a bit vector:
-**
-** bit 1: Term of the form (A) found
-** bit 2: Term like (B1) or (B2) found
-** bit 3: Term like (C) found
-**
-** If bit-1 is set, $str is always in filter.argv[0]. If bit-2 is set
-** then $value is in filter.argv[0] if bit-1 is clear and is in
-** filter.argv[1] if bit-1 is set. If bit-3 is set, then $ruleid is
-** in filter.argv[0] if bit-1 and bit-2 are both zero, is in
-** filter.argv[1] if exactly one of bit-1 and bit-2 are set, and is in
-** filter.argv[2] if both bit-1 and bit-2 are set.
-*/
-static int amatchBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int iPlan = 0;
- int iDistTerm = -1;
- int iLangTerm = -1;
- int i;
- const struct sqlite3_index_constraint *pConstraint;
-
- (void)tab;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( (iPlan & 1)==0
- && pConstraint->iColumn==0
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH
- ){
- iPlan |= 1;
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- }
- if( (iPlan & 2)==0
- && pConstraint->iColumn==1
- && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
- || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE)
- ){
- iPlan |= 2;
- iDistTerm = i;
- }
- if( (iPlan & 4)==0
- && pConstraint->iColumn==2
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= 4;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- iLangTerm = i;
- }
- }
- if( iPlan & 2 ){
- pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = 1+((iPlan&1)!=0);
- }
- if( iPlan & 4 ){
- int idx = 1;
- if( iPlan & 1 ) idx++;
- if( iPlan & 2 ) idx++;
- pIdxInfo->aConstraintUsage[iLangTerm].argvIndex = idx;
- }
- pIdxInfo->idxNum = iPlan;
- if( pIdxInfo->nOrderBy==1
- && pIdxInfo->aOrderBy[0].iColumn==1
- && pIdxInfo->aOrderBy[0].desc==0
- ){
- pIdxInfo->orderByConsumed = 1;
- }
- pIdxInfo->estimatedCost = (double)10000;
-
- return SQLITE_OK;
-}
-
-/*
-** The xUpdate() method.
-**
-** This implementation disallows DELETE and UPDATE. The only thing
-** allowed is INSERT into the "command" column.
-*/
-static int amatchUpdate(
- sqlite3_vtab *pVTab,
- int argc,
- sqlite3_value **argv,
- sqlite_int64 *pRowid
-){
- amatch_vtab *p = (amatch_vtab*)pVTab;
- const unsigned char *zCmd;
- (void)pRowid;
- if( argc==1 ){
- pVTab->zErrMsg = sqlite3_mprintf("DELETE from %s is not allowed",
- p->zSelf);
- return SQLITE_ERROR;
- }
- if( sqlite3_value_type(argv[0])!=SQLITE_NULL ){
- pVTab->zErrMsg = sqlite3_mprintf("UPDATE of %s is not allowed",
- p->zSelf);
- return SQLITE_ERROR;
- }
- if( sqlite3_value_type(argv[2+AMATCH_COL_WORD])!=SQLITE_NULL
- || sqlite3_value_type(argv[2+AMATCH_COL_DISTANCE])!=SQLITE_NULL
- || sqlite3_value_type(argv[2+AMATCH_COL_LANGUAGE])!=SQLITE_NULL
- ){
- pVTab->zErrMsg = sqlite3_mprintf(
- "INSERT INTO %s allowed for column [command] only", p->zSelf);
- return SQLITE_ERROR;
- }
- zCmd = sqlite3_value_text(argv[2+AMATCH_COL_COMMAND]);
- if( zCmd==0 ) return SQLITE_OK;
-
- return SQLITE_OK;
-}
-
-/*
-** A virtual table module that implements the "approximate_match".
-*/
-static sqlite3_module amatchModule = {
- 0, /* iVersion */
- amatchConnect, /* xCreate */
- amatchConnect, /* xConnect */
- amatchBestIndex, /* xBestIndex */
- amatchDisconnect, /* xDisconnect */
- amatchDisconnect, /* xDestroy */
- amatchOpen, /* xOpen - open a cursor */
- amatchClose, /* xClose - close a cursor */
- amatchFilter, /* xFilter - configure scan constraints */
- amatchNext, /* xNext - advance a cursor */
- amatchEof, /* xEof - check for end of scan */
- amatchColumn, /* xColumn - read data */
- amatchRowid, /* xRowid - read data */
- amatchUpdate, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/*
-** Register the amatch virtual table
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_amatch_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Not used */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_create_module(db, "approximate_match", &amatchModule, 0);
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/anycollseq.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/anycollseq.c
deleted file mode 100644
index 27b7049d5fe..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/anycollseq.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-** 2017-04-16
-**
-** 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 a run-time loadable extension to SQLite that
-** registers a sqlite3_collation_needed() callback to register a fake
-** collating function for any unknown collating sequence. The fake
-** collating function works like BINARY.
-**
-** This extension can be used to load schemas that contain one or more
-** unknown collating sequences.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-
-static int anyCollFunc(
- void *NotUsed,
- int nKey1, const void *pKey1,
- int nKey2, const void *pKey2
-){
- int rc, n;
- n = nKey1<nKey2 ? nKey1 : nKey2;
- rc = memcmp(pKey1, pKey2, n);
- if( rc==0 ) rc = nKey1 - nKey2;
- return rc;
-}
-
-static void anyCollNeeded(
- void *NotUsed,
- sqlite3 *db,
- int eTextRep,
- const char *zCollName
-){
- sqlite3_create_collation(db, zCollName, eTextRep, 0, anyCollFunc);
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_anycollseq_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- rc = sqlite3_collation_needed(db, 0, anyCollNeeded);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/appendvfs.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/appendvfs.c
deleted file mode 100644
index b224245f3d9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/appendvfs.c
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
-** 2017-10-20
-**
-** 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 a VFS shim that allows an SQLite database to be
-** appended onto the end of some other file, such as an executable.
-**
-** A special record must appear at the end of the file that identifies the
-** file as an appended database and provides an offset to page 1. For
-** best performance page 1 should be located at a disk page boundary, though
-** that is not required.
-**
-** When opening a database using this VFS, the connection might treat
-** the file as an ordinary SQLite database, or it might treat is as a
-** database appended onto some other file. Here are the rules:
-**
-** (1) When opening a new empty file, that file is treated as an ordinary
-** database.
-**
-** (2) When opening a file that begins with the standard SQLite prefix
-** string "SQLite format 3", that file is treated as an ordinary
-** database.
-**
-** (3) When opening a file that ends with the appendvfs trailer string
-** "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended
-** database.
-**
-** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is
-** set, then a new database is appended to the already existing file.
-**
-** (5) Otherwise, SQLITE_CANTOPEN is returned.
-**
-** To avoid unnecessary complications with the PENDING_BYTE, the size of
-** the file containing the database is limited to 1GB. This VFS will refuse
-** to read or write past the 1GB mark. This restriction might be lifted in
-** future versions. For now, if you need a large database, then keep the
-** database in a separate file.
-**
-** If the file being opened is not an appended database, then this shim is
-** a pass-through into the default underlying VFS.
-**/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-#include <assert.h>
-
-/* The append mark at the end of the database is:
-**
-** Start-Of-SQLite3-NNNNNNNN
-** 123456789 123456789 12345
-**
-** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
-** the offset to page 1.
-*/
-#define APND_MARK_PREFIX "Start-Of-SQLite3-"
-#define APND_MARK_PREFIX_SZ 17
-#define APND_MARK_SIZE 25
-
-/*
-** Maximum size of the combined prefix + database + append-mark. This
-** must be less than 0x40000000 to avoid locking issues on Windows.
-*/
-#define APND_MAX_SIZE (65536*15259)
-
-/*
-** Forward declaration of objects used by this utility
-*/
-typedef struct sqlite3_vfs ApndVfs;
-typedef struct ApndFile ApndFile;
-
-/* Access to a lower-level VFS that (might) implement dynamic loading,
-** access to randomness, etc.
-*/
-#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
-#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
-
-/* An open file */
-struct ApndFile {
- sqlite3_file base; /* IO methods */
- sqlite3_int64 iPgOne; /* File offset to page 1 */
- sqlite3_int64 iMark; /* Start of the append-mark */
-};
-
-/*
-** Methods for ApndFile
-*/
-static int apndClose(sqlite3_file*);
-static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
-static int apndSync(sqlite3_file*, int flags);
-static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int apndLock(sqlite3_file*, int);
-static int apndUnlock(sqlite3_file*, int);
-static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
-static int apndFileControl(sqlite3_file*, int op, void *pArg);
-static int apndSectorSize(sqlite3_file*);
-static int apndDeviceCharacteristics(sqlite3_file*);
-static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
-static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
-static void apndShmBarrier(sqlite3_file*);
-static int apndShmUnmap(sqlite3_file*, int deleteFlag);
-static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
-static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
-
-/*
-** Methods for ApndVfs
-*/
-static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
-static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
-static void apndDlClose(sqlite3_vfs*, void*);
-static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int apndSleep(sqlite3_vfs*, int microseconds);
-static int apndCurrentTime(sqlite3_vfs*, double*);
-static int apndGetLastError(sqlite3_vfs*, int, char *);
-static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
-static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
-static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
-
-static sqlite3_vfs apnd_vfs = {
- 3, /* iVersion (set when registered) */
- 0, /* szOsFile (set when registered) */
- 1024, /* mxPathname */
- 0, /* pNext */
- "apndvfs", /* zName */
- 0, /* pAppData (set when registered) */
- apndOpen, /* xOpen */
- apndDelete, /* xDelete */
- apndAccess, /* xAccess */
- apndFullPathname, /* xFullPathname */
- apndDlOpen, /* xDlOpen */
- apndDlError, /* xDlError */
- apndDlSym, /* xDlSym */
- apndDlClose, /* xDlClose */
- apndRandomness, /* xRandomness */
- apndSleep, /* xSleep */
- apndCurrentTime, /* xCurrentTime */
- apndGetLastError, /* xGetLastError */
- apndCurrentTimeInt64, /* xCurrentTimeInt64 */
- apndSetSystemCall, /* xSetSystemCall */
- apndGetSystemCall, /* xGetSystemCall */
- apndNextSystemCall /* xNextSystemCall */
-};
-
-static const sqlite3_io_methods apnd_io_methods = {
- 3, /* iVersion */
- apndClose, /* xClose */
- apndRead, /* xRead */
- apndWrite, /* xWrite */
- apndTruncate, /* xTruncate */
- apndSync, /* xSync */
- apndFileSize, /* xFileSize */
- apndLock, /* xLock */
- apndUnlock, /* xUnlock */
- apndCheckReservedLock, /* xCheckReservedLock */
- apndFileControl, /* xFileControl */
- apndSectorSize, /* xSectorSize */
- apndDeviceCharacteristics, /* xDeviceCharacteristics */
- apndShmMap, /* xShmMap */
- apndShmLock, /* xShmLock */
- apndShmBarrier, /* xShmBarrier */
- apndShmUnmap, /* xShmUnmap */
- apndFetch, /* xFetch */
- apndUnfetch /* xUnfetch */
-};
-
-
-
-/*
-** Close an apnd-file.
-*/
-static int apndClose(sqlite3_file *pFile){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xClose(pFile);
-}
-
-/*
-** Read data from an apnd-file.
-*/
-static int apndRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- ApndFile *p = (ApndFile *)pFile;
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne);
-}
-
-/*
-** Add the append-mark onto the end of the file.
-*/
-static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){
- int i;
- unsigned char a[APND_MARK_SIZE];
- memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
- for(i=0; i<8; i++){
- a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff;
- }
- return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark);
-}
-
-/*
-** Write data to an apnd-file.
-*/
-static int apndWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc;
- ApndFile *p = (ApndFile *)pFile;
- pFile = ORIGFILE(pFile);
- if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL;
- rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne);
- if( rc==SQLITE_OK && iOfst + iAmt + p->iPgOne > p->iMark ){
- sqlite3_int64 sz = 0;
- rc = pFile->pMethods->xFileSize(pFile, &sz);
- if( rc==SQLITE_OK ){
- p->iMark = sz - APND_MARK_SIZE;
- if( iOfst + iAmt + p->iPgOne > p->iMark ){
- p->iMark = p->iPgOne + iOfst + iAmt;
- rc = apndWriteMark(p, pFile);
- }
- }
- }
- return rc;
-}
-
-/*
-** Truncate an apnd-file.
-*/
-static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
- int rc;
- ApndFile *p = (ApndFile *)pFile;
- pFile = ORIGFILE(pFile);
- rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE);
- if( rc==SQLITE_OK ){
- p->iMark = p->iPgOne+size;
- rc = apndWriteMark(p, pFile);
- }
- return rc;
-}
-
-/*
-** Sync an apnd-file.
-*/
-static int apndSync(sqlite3_file *pFile, int flags){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xSync(pFile, flags);
-}
-
-/*
-** Return the current file-size of an apnd-file.
-*/
-static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- ApndFile *p = (ApndFile *)pFile;
- int rc;
- pFile = ORIGFILE(p);
- rc = pFile->pMethods->xFileSize(pFile, pSize);
- if( rc==SQLITE_OK && p->iPgOne ){
- *pSize -= p->iPgOne + APND_MARK_SIZE;
- }
- return rc;
-}
-
-/*
-** Lock an apnd-file.
-*/
-static int apndLock(sqlite3_file *pFile, int eLock){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xLock(pFile, eLock);
-}
-
-/*
-** Unlock an apnd-file.
-*/
-static int apndUnlock(sqlite3_file *pFile, int eLock){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xUnlock(pFile, eLock);
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an apnd-file.
-*/
-static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
-}
-
-/*
-** File control method. For custom operations on an apnd-file.
-*/
-static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
- ApndFile *p = (ApndFile *)pFile;
- int rc;
- pFile = ORIGFILE(pFile);
- rc = pFile->pMethods->xFileControl(pFile, op, pArg);
- if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
- *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg);
- }
- return rc;
-}
-
-/*
-** Return the sector-size in bytes for an apnd-file.
-*/
-static int apndSectorSize(sqlite3_file *pFile){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xSectorSize(pFile);
-}
-
-/*
-** Return the device characteristic flags supported by an apnd-file.
-*/
-static int apndDeviceCharacteristics(sqlite3_file *pFile){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xDeviceCharacteristics(pFile);
-}
-
-/* Create a shared memory file mapping */
-static int apndShmMap(
- sqlite3_file *pFile,
- int iPg,
- int pgsz,
- int bExtend,
- void volatile **pp
-){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
-}
-
-/* Perform locking on a shared-memory segment */
-static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xShmLock(pFile,offset,n,flags);
-}
-
-/* Memory barrier operation on shared memory */
-static void apndShmBarrier(sqlite3_file *pFile){
- pFile = ORIGFILE(pFile);
- pFile->pMethods->xShmBarrier(pFile);
-}
-
-/* Unmap a shared memory segment */
-static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
-}
-
-/* Fetch a page of a memory-mapped file */
-static int apndFetch(
- sqlite3_file *pFile,
- sqlite3_int64 iOfst,
- int iAmt,
- void **pp
-){
- ApndFile *p = (ApndFile *)pFile;
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
-}
-
-/* Release a memory-mapped page */
-static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
- ApndFile *p = (ApndFile *)pFile;
- pFile = ORIGFILE(pFile);
- return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
-}
-
-/*
-** Check to see if the file is an ordinary SQLite database file.
-*/
-static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
- int rc;
- char zHdr[16];
- static const char aSqliteHdr[] = "SQLite format 3";
- if( sz<512 ) return 0;
- rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0);
- if( rc ) return 0;
- return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0;
-}
-
-/*
-** Try to read the append-mark off the end of a file. Return the
-** start of the appended database if the append-mark is present. If
-** there is no append-mark, return -1;
-*/
-static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
- int rc, i;
- sqlite3_int64 iMark;
- unsigned char a[APND_MARK_SIZE];
-
- if( sz<=APND_MARK_SIZE ) return -1;
- rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
- if( rc ) return -1;
- if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
- iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56;
- for(i=1; i<8; i++){
- iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i);
- }
- return iMark;
-}
-
-/*
-** Open an apnd file handle.
-*/
-static int apndOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- ApndFile *p;
- sqlite3_file *pSubFile;
- sqlite3_vfs *pSubVfs;
- int rc;
- sqlite3_int64 sz;
- pSubVfs = ORIGVFS(pVfs);
- if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
- }
- p = (ApndFile*)pFile;
- memset(p, 0, sizeof(*p));
- pSubFile = ORIGFILE(pFile);
- p->base.pMethods = &apnd_io_methods;
- rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
- if( rc ) goto apnd_open_done;
- rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
- if( rc ){
- pSubFile->pMethods->xClose(pSubFile);
- goto apnd_open_done;
- }
- if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
- memmove(pFile, pSubFile, pSubVfs->szOsFile);
- return SQLITE_OK;
- }
- p->iMark = 0;
- p->iPgOne = apndReadMark(sz, pFile);
- if( p->iPgOne>0 ){
- return SQLITE_OK;
- }
- if( (flags & SQLITE_OPEN_CREATE)==0 ){
- pSubFile->pMethods->xClose(pSubFile);
- rc = SQLITE_CANTOPEN;
- }
- p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff;
-apnd_open_done:
- if( rc ) pFile->pMethods = 0;
- return rc;
-}
-
-/*
-** All other VFS methods are pass-thrus.
-*/
-static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
-}
-static int apndAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
-}
-static int apndFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
-}
-static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
-}
-static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
-}
-static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
-}
-static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
- ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
-}
-static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
-}
-static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
- return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
-}
-static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
-}
-static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
- return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
-}
-static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
- return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
-}
-static int apndSetSystemCall(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_syscall_ptr pCall
-){
- return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
-}
-static sqlite3_syscall_ptr apndGetSystemCall(
- sqlite3_vfs *pVfs,
- const char *zName
-){
- return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
-}
-static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
- return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-/*
-** This routine is called when the extension is loaded.
-** Register the new VFS.
-*/
-int sqlite3_appendvfs_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- sqlite3_vfs *pOrig;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg;
- (void)db;
- pOrig = sqlite3_vfs_find(0);
- apnd_vfs.iVersion = pOrig->iVersion;
- apnd_vfs.pAppData = pOrig;
- apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
- rc = sqlite3_vfs_register(&apnd_vfs, 0);
-#ifdef APPENDVFS_TEST
- if( rc==SQLITE_OK ){
- rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
- }
-#endif
- if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/btreeinfo.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/btreeinfo.c
deleted file mode 100644
index 131b210a799..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/btreeinfo.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
-** 2017-10-24
-**
-** 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 contains an implementation of the "sqlite_btreeinfo" virtual table.
-**
-** The sqlite_btreeinfo virtual table is a read-only eponymous-only virtual
-** table that shows information about all btrees in an SQLite database file.
-** The schema is like this:
-**
-** CREATE TABLE sqlite_btreeinfo(
-** type TEXT, -- "table" or "index"
-** name TEXT, -- Name of table or index for this btree.
-** tbl_name TEXT, -- Associated table
-** rootpage INT, -- The root page of the btree
-** sql TEXT, -- SQL for this btree - from sqlite_master
-** hasRowid BOOLEAN, -- True if the btree has a rowid
-** nEntry INT, -- Estimated number of enteries
-** nPage INT, -- Estimated number of pages
-** depth INT, -- Depth of the btree
-** szPage INT, -- Size of each page in bytes
-** zSchema TEXT HIDDEN -- The schema to which this btree belongs
-** );
-**
-** The first 5 fields are taken directly from the sqlite_master table.
-** Considering only the first 5 fields, the only difference between
-** this virtual table and the sqlite_master table is that this virtual
-** table omits all entries that have a 0 or NULL rowid - in other words
-** it omits triggers and views.
-**
-** The value added by this table comes in the next 5 fields.
-**
-** Note that nEntry and nPage are *estimated*. They are computed doing
-** a single search from the root to a leaf, counting the number of cells
-** at each level, and assuming that unvisited pages have a similar number
-** of cells.
-**
-** The sqlite_dbpage virtual table must be available for this virtual table
-** to operate.
-**
-** USAGE EXAMPLES:
-**
-** Show the table btrees in a schema order with the tables with the most
-** rows occuring first:
-**
-** SELECT name, nEntry
-** FROM sqlite_btreeinfo
-** WHERE type='table'
-** ORDER BY nEntry DESC, name;
-**
-** Show the names of all WITHOUT ROWID tables:
-**
-** SELECT name FROM sqlite_btreeinfo
-** WHERE type='table' AND NOT hasRowid;
-*/
-#if !defined(SQLITEINT_H)
-#include "sqlite3ext.h"
-#endif
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-#include <assert.h>
-
-/* Columns available in this virtual table */
-#define BINFO_COLUMN_TYPE 0
-#define BINFO_COLUMN_NAME 1
-#define BINFO_COLUMN_TBL_NAME 2
-#define BINFO_COLUMN_ROOTPAGE 3
-#define BINFO_COLUMN_SQL 4
-#define BINFO_COLUMN_HASROWID 5
-#define BINFO_COLUMN_NENTRY 6
-#define BINFO_COLUMN_NPAGE 7
-#define BINFO_COLUMN_DEPTH 8
-#define BINFO_COLUMN_SZPAGE 9
-#define BINFO_COLUMN_SCHEMA 10
-
-/* Forward declarations */
-typedef struct BinfoTable BinfoTable;
-typedef struct BinfoCursor BinfoCursor;
-
-/* A cursor for the sqlite_btreeinfo table */
-struct BinfoCursor {
- sqlite3_vtab_cursor base; /* Base class. Must be first */
- sqlite3_stmt *pStmt; /* Query against sqlite_master */
- int rc; /* Result of previous sqlite_step() call */
- int hasRowid; /* hasRowid value. Negative if unknown. */
- sqlite3_int64 nEntry; /* nEntry value */
- int nPage; /* nPage value */
- int depth; /* depth value */
- int szPage; /* size of a btree page. 0 if unknown */
- char *zSchema; /* Schema being interrogated */
-};
-
-/* The sqlite_btreeinfo table */
-struct BinfoTable {
- sqlite3_vtab base; /* Base class. Must be first */
- sqlite3 *db; /* The databse connection */
-};
-
-/*
-** Connect to the sqlite_btreeinfo virtual table.
-*/
-static int binfoConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- BinfoTable *pTab = 0;
- int rc = SQLITE_OK;
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(\n"
- " type TEXT,\n"
- " name TEXT,\n"
- " tbl_name TEXT,\n"
- " rootpage INT,\n"
- " sql TEXT,\n"
- " hasRowid BOOLEAN,\n"
- " nEntry INT,\n"
- " nPage INT,\n"
- " depth INT,\n"
- " szPage INT,\n"
- " zSchema TEXT HIDDEN\n"
- ")");
- if( rc==SQLITE_OK ){
- pTab = (BinfoTable *)sqlite3_malloc64(sizeof(BinfoTable));
- if( pTab==0 ) rc = SQLITE_NOMEM;
- }
- assert( rc==SQLITE_OK || pTab==0 );
- if( pTab ){
- pTab->db = db;
- }
- *ppVtab = (sqlite3_vtab*)pTab;
- return rc;
-}
-
-/*
-** Disconnect from or destroy a btreeinfo virtual table.
-*/
-static int binfoDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** idxNum:
-**
-** 0 Use "main" for the schema
-** 1 Schema identified by parameter ?1
-*/
-static int binfoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int i;
- pIdxInfo->estimatedCost = 10000.0; /* Cost estimate */
- pIdxInfo->estimatedRows = 100;
- for(i=0; i<pIdxInfo->nConstraint; i++){
- struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
- if( p->usable
- && p->iColumn==BINFO_COLUMN_SCHEMA
- && p->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- pIdxInfo->estimatedCost = 1000.0;
- pIdxInfo->idxNum = 1;
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Open a new btreeinfo cursor.
-*/
-static int binfoOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- BinfoCursor *pCsr;
-
- pCsr = (BinfoCursor *)sqlite3_malloc64(sizeof(BinfoCursor));
- if( pCsr==0 ){
- return SQLITE_NOMEM;
- }else{
- memset(pCsr, 0, sizeof(BinfoCursor));
- pCsr->base.pVtab = pVTab;
- }
-
- *ppCursor = (sqlite3_vtab_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** Close a btreeinfo cursor.
-*/
-static int binfoClose(sqlite3_vtab_cursor *pCursor){
- BinfoCursor *pCsr = (BinfoCursor *)pCursor;
- sqlite3_finalize(pCsr->pStmt);
- sqlite3_free(pCsr->zSchema);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Move a btreeinfo cursor to the next entry in the file.
-*/
-static int binfoNext(sqlite3_vtab_cursor *pCursor){
- BinfoCursor *pCsr = (BinfoCursor *)pCursor;
- pCsr->rc = sqlite3_step(pCsr->pStmt);
- pCsr->hasRowid = -1;
- return pCsr->rc==SQLITE_ERROR ? SQLITE_ERROR : SQLITE_OK;
-}
-
-/* We have reached EOF if previous sqlite3_step() returned
-** anything other than SQLITE_ROW;
-*/
-static int binfoEof(sqlite3_vtab_cursor *pCursor){
- BinfoCursor *pCsr = (BinfoCursor *)pCursor;
- return pCsr->rc!=SQLITE_ROW;
-}
-
-/* Position a cursor back to the beginning.
-*/
-static int binfoFilter(
- sqlite3_vtab_cursor *pCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- BinfoCursor *pCsr = (BinfoCursor *)pCursor;
- BinfoTable *pTab = (BinfoTable *)pCursor->pVtab;
- char *zSql;
- int rc;
-
- sqlite3_free(pCsr->zSchema);
- if( idxNum==1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){
- pCsr->zSchema = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
- }else{
- pCsr->zSchema = sqlite3_mprintf("main");
- }
- zSql = sqlite3_mprintf(
- "SELECT 0, 'table','sqlite_master','sqlite_master',1,NULL "
- "UNION ALL "
- "SELECT rowid, type, name, tbl_name, rootpage, sql"
- " FROM \"%w\".sqlite_master WHERE rootpage>=1",
- pCsr->zSchema);
- sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- pCsr->hasRowid = -1;
- rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
- sqlite3_free(zSql);
- if( rc==SQLITE_OK ){
- rc = binfoNext(pCursor);
- }
- return rc;
-}
-
-/* Decode big-endian integers */
-static unsigned int get_uint16(unsigned char *a){
- return (a[0]<<8)|a[1];
-}
-static unsigned int get_uint32(unsigned char *a){
- return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|a[3];
-}
-
-/* Examine the b-tree rooted at pgno and estimate its size.
-** Return non-zero if anything goes wrong.
-*/
-static int binfoCompute(sqlite3 *db, int pgno, BinfoCursor *pCsr){
- sqlite3_int64 nEntry = 1;
- int nPage = 1;
- unsigned char *aData;
- sqlite3_stmt *pStmt = 0;
- int rc = SQLITE_OK;
- int pgsz = 0;
- int nCell;
- int iCell;
-
- rc = sqlite3_prepare_v2(db,
- "SELECT data FROM sqlite_dbpage('main') WHERE pgno=?1", -1,
- &pStmt, 0);
- if( rc ) return rc;
- pCsr->depth = 1;
- while(1){
- sqlite3_bind_int(pStmt, 1, pgno);
- rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW ){
- rc = SQLITE_ERROR;
- break;
- }
- pCsr->szPage = pgsz = sqlite3_column_bytes(pStmt, 0);
- aData = (unsigned char*)sqlite3_column_blob(pStmt, 0);
- if( aData==0 ){
- rc = SQLITE_NOMEM;
- break;
- }
- if( pgno==1 ){
- aData += 100;
- pgsz -= 100;
- }
- pCsr->hasRowid = aData[0]!=2 && aData[0]!=10;
- nCell = get_uint16(aData+3);
- nEntry *= (nCell+1);
- if( aData[0]==10 || aData[0]==13 ) break;
- nPage *= (nCell+1);
- if( nCell<=1 ){
- pgno = get_uint32(aData+8);
- }else{
- iCell = get_uint16(aData+12+2*(nCell/2));
- if( pgno==1 ) iCell -= 100;
- if( iCell<=12 || iCell>=pgsz-4 ){
- rc = SQLITE_CORRUPT;
- break;
- }
- pgno = get_uint32(aData+iCell);
- }
- pCsr->depth++;
- sqlite3_reset(pStmt);
- }
- sqlite3_finalize(pStmt);
- pCsr->nPage = nPage;
- pCsr->nEntry = nEntry;
- if( rc==SQLITE_ROW ) rc = SQLITE_OK;
- return rc;
-}
-
-/* Return a column for the sqlite_btreeinfo table */
-static int binfoColumn(
- sqlite3_vtab_cursor *pCursor,
- sqlite3_context *ctx,
- int i
-){
- BinfoCursor *pCsr = (BinfoCursor *)pCursor;
- if( i>=BINFO_COLUMN_HASROWID && i<=BINFO_COLUMN_SZPAGE && pCsr->hasRowid<0 ){
- int pgno = sqlite3_column_int(pCsr->pStmt, BINFO_COLUMN_ROOTPAGE+1);
- sqlite3 *db = sqlite3_context_db_handle(ctx);
- int rc = binfoCompute(db, pgno, pCsr);
- if( rc ){
- pCursor->pVtab->zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- return SQLITE_ERROR;
- }
- }
- switch( i ){
- case BINFO_COLUMN_NAME:
- case BINFO_COLUMN_TYPE:
- case BINFO_COLUMN_TBL_NAME:
- case BINFO_COLUMN_ROOTPAGE:
- case BINFO_COLUMN_SQL: {
- sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1));
- break;
- }
- case BINFO_COLUMN_HASROWID: {
- sqlite3_result_int(ctx, pCsr->hasRowid);
- break;
- }
- case BINFO_COLUMN_NENTRY: {
- sqlite3_result_int64(ctx, pCsr->nEntry);
- break;
- }
- case BINFO_COLUMN_NPAGE: {
- sqlite3_result_int(ctx, pCsr->nPage);
- break;
- }
- case BINFO_COLUMN_DEPTH: {
- sqlite3_result_int(ctx, pCsr->depth);
- break;
- }
- case BINFO_COLUMN_SCHEMA: {
- sqlite3_result_text(ctx, pCsr->zSchema, -1, SQLITE_STATIC);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/* Return the ROWID for the sqlite_btreeinfo table */
-static int binfoRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- BinfoCursor *pCsr = (BinfoCursor *)pCursor;
- *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
- return SQLITE_OK;
-}
-
-/*
-** Invoke this routine to register the "sqlite_btreeinfo" virtual table module
-*/
-int sqlite3BinfoRegister(sqlite3 *db){
- static sqlite3_module binfo_module = {
- 0, /* iVersion */
- 0, /* xCreate */
- binfoConnect, /* xConnect */
- binfoBestIndex, /* xBestIndex */
- binfoDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- binfoOpen, /* xOpen - open a cursor */
- binfoClose, /* xClose - close a cursor */
- binfoFilter, /* xFilter - configure scan constraints */
- binfoNext, /* xNext - advance a cursor */
- binfoEof, /* xEof - check for end of scan */
- binfoColumn, /* xColumn - read data */
- binfoRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
- };
- return sqlite3_create_module(db, "sqlite_btreeinfo", &binfo_module, 0);
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_btreeinfo_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- return sqlite3BinfoRegister(db);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/carray.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/carray.c
deleted file mode 100644
index b39904ae153..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/carray.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
-** 2016-06-29
-**
-** 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 demonstrates how to create a table-valued-function that
-** returns the values in a C-language array.
-** Examples:
-**
-** SELECT * FROM carray($ptr,5)
-**
-** The query above returns 5 integers contained in a C-language array
-** at the address $ptr. $ptr is a pointer to the array of integers.
-** The pointer value must be assigned to $ptr using the
-** sqlite3_bind_pointer() interface with a pointer type of "carray".
-** For example:
-**
-** static int aX[] = { 53, 9, 17, 2231, 4, 99 };
-** int i = sqlite3_bind_parameter_index(pStmt, "$ptr");
-** sqlite3_bind_value(pStmt, i, aX, "carray", 0);
-**
-** There is an optional third parameter to determine the datatype of
-** the C-language array. Allowed values of the third parameter are
-** 'int32', 'int64', 'double', 'char*'. Example:
-**
-** SELECT * FROM carray($ptr,10,'char*');
-**
-** The default value of the third parameter is 'int32'.
-**
-** HOW IT WORKS
-**
-** The carray "function" is really a virtual table with the
-** following schema:
-**
-** CREATE TABLE carray(
-** value,
-** pointer HIDDEN,
-** count HIDDEN,
-** ctype TEXT HIDDEN
-** );
-**
-** If the hidden columns "pointer" and "count" are unconstrained, then
-** the virtual table has no rows. Otherwise, the virtual table interprets
-** the integer value of "pointer" as a pointer to the array and "count"
-** as the number of elements in the array. The virtual table steps through
-** the array, element by element.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Allowed datatypes
-*/
-#define CARRAY_INT32 0
-#define CARRAY_INT64 1
-#define CARRAY_DOUBLE 2
-#define CARRAY_TEXT 3
-
-/*
-** Names of types
-*/
-static const char *azType[] = { "int32", "int64", "double", "char*" };
-
-
-/* carray_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-typedef struct carray_cursor carray_cursor;
-struct carray_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3_int64 iRowid; /* The rowid */
- void *pPtr; /* Pointer to the array of values */
- sqlite3_int64 iCnt; /* Number of integers in the array */
- unsigned char eType; /* One of the CARRAY_type values */
-};
-
-/*
-** The carrayConnect() method is invoked to create a new
-** carray_vtab that describes the carray virtual table.
-**
-** Think of this routine as the constructor for carray_vtab objects.
-**
-** All this routine needs to do is:
-**
-** (1) Allocate the carray_vtab object and initialize all fields.
-**
-** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-** result set of queries against carray will look like.
-*/
-static int carrayConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3_vtab *pNew;
- int rc;
-
-/* Column numbers */
-#define CARRAY_COLUMN_VALUE 0
-#define CARRAY_COLUMN_POINTER 1
-#define CARRAY_COLUMN_COUNT 2
-#define CARRAY_COLUMN_CTYPE 3
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(value,pointer hidden,count hidden,ctype hidden)");
- if( rc==SQLITE_OK ){
- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- }
- return rc;
-}
-
-/*
-** This method is the destructor for carray_cursor objects.
-*/
-static int carrayDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new carray_cursor object.
-*/
-static int carrayOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- carray_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Destructor for a carray_cursor.
-*/
-static int carrayClose(sqlite3_vtab_cursor *cur){
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a carray_cursor to its next row of output.
-*/
-static int carrayNext(sqlite3_vtab_cursor *cur){
- carray_cursor *pCur = (carray_cursor*)cur;
- pCur->iRowid++;
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the carray_cursor
-** is currently pointing.
-*/
-static int carrayColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- carray_cursor *pCur = (carray_cursor*)cur;
- sqlite3_int64 x = 0;
- switch( i ){
- case CARRAY_COLUMN_POINTER: return SQLITE_OK;
- case CARRAY_COLUMN_COUNT: x = pCur->iCnt; break;
- case CARRAY_COLUMN_CTYPE: {
- sqlite3_result_text(ctx, azType[pCur->eType], -1, SQLITE_STATIC);
- return SQLITE_OK;
- }
- default: {
- switch( pCur->eType ){
- case CARRAY_INT32: {
- int *p = (int*)pCur->pPtr;
- sqlite3_result_int(ctx, p[pCur->iRowid-1]);
- return SQLITE_OK;
- }
- case CARRAY_INT64: {
- sqlite3_int64 *p = (sqlite3_int64*)pCur->pPtr;
- sqlite3_result_int64(ctx, p[pCur->iRowid-1]);
- return SQLITE_OK;
- }
- case CARRAY_DOUBLE: {
- double *p = (double*)pCur->pPtr;
- sqlite3_result_double(ctx, p[pCur->iRowid-1]);
- return SQLITE_OK;
- }
- case CARRAY_TEXT: {
- const char **p = (const char**)pCur->pPtr;
- sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT);
- return SQLITE_OK;
- }
- }
- }
- }
- sqlite3_result_int64(ctx, x);
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** rowid is the same as the output value.
-*/
-static int carrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- carray_cursor *pCur = (carray_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int carrayEof(sqlite3_vtab_cursor *cur){
- carray_cursor *pCur = (carray_cursor*)cur;
- return pCur->iRowid>pCur->iCnt;
-}
-
-/*
-** This method is called to "rewind" the carray_cursor object back
-** to the first row of output.
-*/
-static int carrayFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- carray_cursor *pCur = (carray_cursor *)pVtabCursor;
- if( idxNum ){
- pCur->pPtr = sqlite3_value_pointer(argv[0], "carray");
- pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0;
- if( idxNum<3 ){
- pCur->eType = CARRAY_INT32;
- }else{
- unsigned char i;
- const char *zType = (const char*)sqlite3_value_text(argv[2]);
- for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
- if( sqlite3_stricmp(zType, azType[i])==0 ) break;
- }
- if( i>=sizeof(azType)/sizeof(azType[0]) ){
- pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
- "unknown datatype: %Q", zType);
- return SQLITE_ERROR;
- }else{
- pCur->eType = i;
- }
- }
- }else{
- pCur->pPtr = 0;
- pCur->iCnt = 0;
- }
- pCur->iRowid = 1;
- return SQLITE_OK;
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the carray virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** In this implementation idxNum is used to represent the
-** query plan. idxStr is unused.
-**
-** idxNum is 2 if the pointer= and count= constraints exist,
-** 3 if the ctype= constraint also exists, and is 0 otherwise.
-** If idxNum is 0, then carray becomes an empty table.
-*/
-static int carrayBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i; /* Loop over constraints */
- int ptrIdx = -1; /* Index of the pointer= constraint, or -1 if none */
- int cntIdx = -1; /* Index of the count= constraint, or -1 if none */
- int ctypeIdx = -1; /* Index of the ctype= constraint, or -1 if none */
-
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case CARRAY_COLUMN_POINTER:
- ptrIdx = i;
- break;
- case CARRAY_COLUMN_COUNT:
- cntIdx = i;
- break;
- case CARRAY_COLUMN_CTYPE:
- ctypeIdx = i;
- break;
- }
- }
- if( ptrIdx>=0 && cntIdx>=0 ){
- pIdxInfo->aConstraintUsage[ptrIdx].argvIndex = 1;
- pIdxInfo->aConstraintUsage[ptrIdx].omit = 1;
- pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2;
- pIdxInfo->aConstraintUsage[cntIdx].omit = 1;
- pIdxInfo->estimatedCost = (double)1;
- pIdxInfo->estimatedRows = 100;
- pIdxInfo->idxNum = 2;
- if( ctypeIdx>=0 ){
- pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3;
- pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1;
- pIdxInfo->idxNum = 3;
- }
- }else{
- pIdxInfo->estimatedCost = (double)2147483647;
- pIdxInfo->estimatedRows = 2147483647;
- pIdxInfo->idxNum = 0;
- }
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** carray virtual table.
-*/
-static sqlite3_module carrayModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- carrayConnect, /* xConnect */
- carrayBestIndex, /* xBestIndex */
- carrayDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- carrayOpen, /* xOpen - open a cursor */
- carrayClose, /* xClose - close a cursor */
- carrayFilter, /* xFilter - configure scan constraints */
- carrayNext, /* xNext - advance a cursor */
- carrayEof, /* xEof - check for end of scan */
- carrayColumn, /* xColumn - read data */
- carrayRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-/*
-** For testing purpose in the TCL test harness, we need a method for
-** setting the pointer value. The inttoptr(X) SQL function accomplishes
-** this. Tcl script will bind an integer to X and the inttoptr() SQL
-** function will use sqlite3_result_pointer() to convert that integer into
-** a pointer.
-**
-** This is for testing on TCL only.
-*/
-#ifdef SQLITE_TEST
-static void inttoptrFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- void *p;
- sqlite3_int64 i64;
- i64 = sqlite3_value_int64(argv[0]);
- if( sizeof(i64)==sizeof(p) ){
- memcpy(&p, &i64, sizeof(p));
- }else{
- int i32 = i64 & 0xffffffff;
- memcpy(&p, &i32, sizeof(p));
- }
- sqlite3_result_pointer(context, p, "carray", 0);
-}
-#endif /* SQLITE_TEST */
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_carray_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_create_module(db, "carray", &carrayModule, 0);
-#ifdef SQLITE_TEST
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "inttoptr", 1, SQLITE_UTF8, 0,
- inttoptrFunc, 0, 0);
- }
-#endif /* SQLITE_TEST */
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/closure.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/closure.c
deleted file mode 100644
index 74bffc7708a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/closure.c
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
-** 2013-04-16
-**
-** 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 contains code for a virtual table that finds the transitive
-** closure of a parent/child relationship in a real table. The virtual
-** table is called "transitive_closure".
-**
-** A transitive_closure virtual table is created like this:
-**
-** CREATE VIRTUAL TABLE x USING transitive_closure(
-** tablename=<tablename>, -- T
-** idcolumn=<columnname>, -- X
-** parentcolumn=<columnname> -- P
-** );
-**
-** When it is created, the new transitive_closure table may be supplied
-** with default values for the name of a table T and columns T.X and T.P.
-** The T.X and T.P columns must contain integers. The ideal case is for
-** T.X to be the INTEGER PRIMARY KEY. The T.P column should reference
-** the T.X column. The row referenced by T.P is the parent of the current row.
-**
-** The tablename, idcolumn, and parentcolumn supplied by the CREATE VIRTUAL
-** TABLE statement may be overridden in individual queries by including
-** terms like tablename='newtable', idcolumn='id2', or
-** parentcolumn='parent3' in the WHERE clause of the query.
-**
-** For efficiency, it is essential that there be an index on the P column:
-**
-** CREATE Tidx1 ON T(P)
-**
-** Suppose a specific instance of the closure table is as follows:
-**
-** CREATE VIRTUAL TABLE ct1 USING transitive_closure(
-** tablename='group',
-** idcolumn='groupId',
-** parentcolumn='parentId'
-** );
-**
-** Such an instance of the transitive_closure virtual table would be
-** appropriate for walking a tree defined using a table like this, for example:
-**
-** CREATE TABLE group(
-** groupId INTEGER PRIMARY KEY,
-** parentId INTEGER REFERENCES group
-** );
-** CREATE INDEX group_idx1 ON group(parentId);
-**
-** The group table above would presumably have other application-specific
-** fields. The key point here is that rows of the group table form a
-** tree. The purpose of the ct1 virtual table is to easily extract
-** branches of that tree.
-**
-** Once it has been created, the ct1 virtual table can be queried
-** as follows:
-**
-** SELECT * FROM element
-** WHERE element.groupId IN (SELECT id FROM ct1 WHERE root=?1);
-**
-** The above query will return all elements that are part of group ?1
-** or children of group ?1 or grand-children of ?1 and so forth for all
-** descendents of group ?1. The same query can be formulated as a join:
-**
-** SELECT element.* FROM element, ct1
-** WHERE element.groupid=ct1.id
-** AND ct1.root=?1;
-**
-** The depth of the transitive_closure (the number of generations of
-** parent/child relations to follow) can be limited by setting "depth"
-** column in the WHERE clause. So, for example, the following query
-** finds only children and grandchildren but no further descendents:
-**
-** SELECT element.* FROM element, ct1
-** WHERE element.groupid=ct1.id
-** AND ct1.root=?1
-** AND ct1.depth<=2;
-**
-** The "ct1.depth<=2" term could be a strict equality "ct1.depth=2" in
-** order to find only the grandchildren of ?1, not ?1 itself or the
-** children of ?1.
-**
-** The root=?1 term must be supplied in WHERE clause or else the query
-** of the ct1 virtual table will return an empty set. The tablename,
-** idcolumn, and parentcolumn attributes can be overridden in the WHERE
-** clause if desired. So, for example, the ct1 table could be repurposed
-** to find ancestors rather than descendents by inverting the roles of
-** the idcolumn and parentcolumn:
-**
-** SELECT element.* FROM element, ct1
-** WHERE element.groupid=ct1.id
-** AND ct1.root=?1
-** AND ct1.idcolumn='parentId'
-** AND ct1.parentcolumn='groupId';
-**
-** Multiple calls to ct1 could be combined. For example, the following
-** query finds all elements that "cousins" of groupId ?1. That is to say
-** elements where the groupId is a grandchild of the grandparent of ?1.
-** (This definition of "cousins" also includes siblings and self.)
-**
-** SELECT element.* FROM element, ct1
-** WHERE element.groupId=ct1.id
-** AND ct1.depth=2
-** AND ct1.root IN (SELECT id FROM ct1
-** WHERE root=?1
-** AND depth=2
-** AND idcolumn='parentId'
-** AND parentcolumn='groupId');
-**
-** In our example, the group.groupId column is unique and thus the
-** subquery will return exactly one row. For that reason, the IN
-** operator could be replaced by "=" to get the same result. But
-** in the general case where the idcolumn is not unique, an IN operator
-** would be required for this kind of query.
-**
-** Note that because the tablename, idcolumn, and parentcolumn can
-** all be specified in the query, it is possible for an application
-** to define a single transitive_closure virtual table for use on lots
-** of different hierarchy tables. One might say:
-**
-** CREATE VIRTUAL TABLE temp.closure USING transitive_closure;
-**
-** As each database connection is being opened. Then the application
-** would always have a "closure" virtual table handy to use for querying.
-**
-** SELECT element.* FROM element, closure
-** WHERE element.groupid=ct1.id
-** AND closure.root=?1
-** AND closure.tablename='group'
-** AND closure.idname='groupId'
-** AND closure.parentname='parentId';
-**
-** See the documentation at http://www.sqlite.org/loadext.html for information
-** on how to compile and use loadable extensions such as this one.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Forward declaration of objects used by this implementation
-*/
-typedef struct closure_vtab closure_vtab;
-typedef struct closure_cursor closure_cursor;
-typedef struct closure_queue closure_queue;
-typedef struct closure_avl closure_avl;
-
-/*****************************************************************************
-** AVL Tree implementation
-*/
-/*
-** Objects that want to be members of the AVL tree should embedded an
-** instance of this structure.
-*/
-struct closure_avl {
- sqlite3_int64 id; /* Id of this entry in the table */
- int iGeneration; /* Which generation is this entry part of */
- closure_avl *pList; /* A linked list of nodes */
- closure_avl *pBefore; /* Other elements less than id */
- closure_avl *pAfter; /* Other elements greater than id */
- closure_avl *pUp; /* Parent element */
- short int height; /* Height of this node. Leaf==1 */
- short int imbalance; /* Height difference between pBefore and pAfter */
-};
-
-/* Recompute the closure_avl.height and closure_avl.imbalance fields for p.
-** Assume that the children of p have correct heights.
-*/
-static void closureAvlRecomputeHeight(closure_avl *p){
- short int hBefore = p->pBefore ? p->pBefore->height : 0;
- short int hAfter = p->pAfter ? p->pAfter->height : 0;
- p->imbalance = hBefore - hAfter; /* -: pAfter higher. +: pBefore higher */
- p->height = (hBefore>hAfter ? hBefore : hAfter)+1;
-}
-
-/*
-** P B
-** / \ / \
-** B Z ==> X P
-** / \ / \
-** X Y Y Z
-**
-*/
-static closure_avl *closureAvlRotateBefore(closure_avl *pP){
- closure_avl *pB = pP->pBefore;
- closure_avl *pY = pB->pAfter;
- pB->pUp = pP->pUp;
- pB->pAfter = pP;
- pP->pUp = pB;
- pP->pBefore = pY;
- if( pY ) pY->pUp = pP;
- closureAvlRecomputeHeight(pP);
- closureAvlRecomputeHeight(pB);
- return pB;
-}
-
-/*
-** P A
-** / \ / \
-** X A ==> P Z
-** / \ / \
-** Y Z X Y
-**
-*/
-static closure_avl *closureAvlRotateAfter(closure_avl *pP){
- closure_avl *pA = pP->pAfter;
- closure_avl *pY = pA->pBefore;
- pA->pUp = pP->pUp;
- pA->pBefore = pP;
- pP->pUp = pA;
- pP->pAfter = pY;
- if( pY ) pY->pUp = pP;
- closureAvlRecomputeHeight(pP);
- closureAvlRecomputeHeight(pA);
- return pA;
-}
-
-/*
-** Return a pointer to the pBefore or pAfter pointer in the parent
-** of p that points to p. Or if p is the root node, return pp.
-*/
-static closure_avl **closureAvlFromPtr(closure_avl *p, closure_avl **pp){
- closure_avl *pUp = p->pUp;
- if( pUp==0 ) return pp;
- if( pUp->pAfter==p ) return &pUp->pAfter;
- return &pUp->pBefore;
-}
-
-/*
-** Rebalance all nodes starting with p and working up to the root.
-** Return the new root.
-*/
-static closure_avl *closureAvlBalance(closure_avl *p){
- closure_avl *pTop = p;
- closure_avl **pp;
- while( p ){
- closureAvlRecomputeHeight(p);
- if( p->imbalance>=2 ){
- closure_avl *pB = p->pBefore;
- if( pB->imbalance<0 ) p->pBefore = closureAvlRotateAfter(pB);
- pp = closureAvlFromPtr(p,&p);
- p = *pp = closureAvlRotateBefore(p);
- }else if( p->imbalance<=(-2) ){
- closure_avl *pA = p->pAfter;
- if( pA->imbalance>0 ) p->pAfter = closureAvlRotateBefore(pA);
- pp = closureAvlFromPtr(p,&p);
- p = *pp = closureAvlRotateAfter(p);
- }
- pTop = p;
- p = p->pUp;
- }
- return pTop;
-}
-
-/* Search the tree rooted at p for an entry with id. Return a pointer
-** to the entry or return NULL.
-*/
-static closure_avl *closureAvlSearch(closure_avl *p, sqlite3_int64 id){
- while( p && id!=p->id ){
- p = (id<p->id) ? p->pBefore : p->pAfter;
- }
- return p;
-}
-
-/* Find the first node (the one with the smallest key).
-*/
-static closure_avl *closureAvlFirst(closure_avl *p){
- if( p ) while( p->pBefore ) p = p->pBefore;
- return p;
-}
-
-/* Return the node with the next larger key after p.
-*/
-closure_avl *closureAvlNext(closure_avl *p){
- closure_avl *pPrev = 0;
- while( p && p->pAfter==pPrev ){
- pPrev = p;
- p = p->pUp;
- }
- if( p && pPrev==0 ){
- p = closureAvlFirst(p->pAfter);
- }
- return p;
-}
-
-/* Insert a new node pNew. Return NULL on success. If the key is not
-** unique, then do not perform the insert but instead leave pNew unchanged
-** and return a pointer to an existing node with the same key.
-*/
-static closure_avl *closureAvlInsert(
- closure_avl **ppHead, /* Head of the tree */
- closure_avl *pNew /* New node to be inserted */
-){
- closure_avl *p = *ppHead;
- if( p==0 ){
- p = pNew;
- pNew->pUp = 0;
- }else{
- while( p ){
- if( pNew->id<p->id ){
- if( p->pBefore ){
- p = p->pBefore;
- }else{
- p->pBefore = pNew;
- pNew->pUp = p;
- break;
- }
- }else if( pNew->id>p->id ){
- if( p->pAfter ){
- p = p->pAfter;
- }else{
- p->pAfter = pNew;
- pNew->pUp = p;
- break;
- }
- }else{
- return p;
- }
- }
- }
- pNew->pBefore = 0;
- pNew->pAfter = 0;
- pNew->height = 1;
- pNew->imbalance = 0;
- *ppHead = closureAvlBalance(p);
- return 0;
-}
-
-/* Walk the tree can call xDestroy on each node
-*/
-static void closureAvlDestroy(closure_avl *p, void (*xDestroy)(closure_avl*)){
- if( p ){
- closureAvlDestroy(p->pBefore, xDestroy);
- closureAvlDestroy(p->pAfter, xDestroy);
- xDestroy(p);
- }
-}
-/*
-** End of the AVL Tree implementation
-******************************************************************************/
-
-/*
-** A closure virtual-table object
-*/
-struct closure_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- char *zDb; /* Name of database. (ex: "main") */
- char *zSelf; /* Name of this virtual table */
- char *zTableName; /* Name of table holding parent/child relation */
- char *zIdColumn; /* Name of ID column of zTableName */
- char *zParentColumn; /* Name of PARENT column in zTableName */
- sqlite3 *db; /* The database connection */
- int nCursor; /* Number of pending cursors */
-};
-
-/* A closure cursor object */
-struct closure_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- closure_vtab *pVtab; /* The virtual table this cursor belongs to */
- char *zTableName; /* Name of table holding parent/child relation */
- char *zIdColumn; /* Name of ID column of zTableName */
- char *zParentColumn; /* Name of PARENT column in zTableName */
- closure_avl *pCurrent; /* Current element of output */
- closure_avl *pClosure; /* The complete closure tree */
-};
-
-/* A queue of AVL nodes */
-struct closure_queue {
- closure_avl *pFirst; /* Oldest node on the queue */
- closure_avl *pLast; /* Youngest node on the queue */
-};
-
-/*
-** Add a node to the end of the queue
-*/
-static void queuePush(closure_queue *pQueue, closure_avl *pNode){
- pNode->pList = 0;
- if( pQueue->pLast ){
- pQueue->pLast->pList = pNode;
- }else{
- pQueue->pFirst = pNode;
- }
- pQueue->pLast = pNode;
-}
-
-/*
-** Extract the oldest element (the front element) from the queue.
-*/
-static closure_avl *queuePull(closure_queue *pQueue){
- closure_avl *p = pQueue->pFirst;
- if( p ){
- pQueue->pFirst = p->pList;
- if( pQueue->pFirst==0 ) pQueue->pLast = 0;
- }
- return p;
-}
-
-/*
-** This function converts an SQL quoted string into an unquoted string
-** and returns a pointer to a buffer allocated using sqlite3_malloc()
-** containing the result. The caller should eventually free this buffer
-** using sqlite3_free.
-**
-** Examples:
-**
-** "abc" becomes abc
-** 'xyz' becomes xyz
-** [pqr] becomes pqr
-** `mno` becomes mno
-*/
-static char *closureDequote(const char *zIn){
- int nIn; /* Size of input string, in bytes */
- char *zOut; /* Output (dequoted) string */
-
- nIn = (int)strlen(zIn);
- zOut = sqlite3_malloc(nIn+1);
- if( zOut ){
- char q = zIn[0]; /* Quote character (if any ) */
-
- if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
- memcpy(zOut, zIn, nIn+1);
- }else{
- int iOut = 0; /* Index of next byte to write to output */
- int iIn; /* Index of next byte to read from input */
-
- if( q=='[' ) q = ']';
- for(iIn=1; iIn<nIn; iIn++){
- if( zIn[iIn]==q ) iIn++;
- zOut[iOut++] = zIn[iIn];
- }
- }
- assert( (int)strlen(zOut)<=nIn );
- }
- return zOut;
-}
-
-/*
-** Deallocate an closure_vtab object
-*/
-static void closureFree(closure_vtab *p){
- if( p ){
- sqlite3_free(p->zDb);
- sqlite3_free(p->zSelf);
- sqlite3_free(p->zTableName);
- sqlite3_free(p->zIdColumn);
- sqlite3_free(p->zParentColumn);
- memset(p, 0, sizeof(*p));
- sqlite3_free(p);
- }
-}
-
-/*
-** xDisconnect/xDestroy method for the closure module.
-*/
-static int closureDisconnect(sqlite3_vtab *pVtab){
- closure_vtab *p = (closure_vtab*)pVtab;
- assert( p->nCursor==0 );
- closureFree(p);
- return SQLITE_OK;
-}
-
-/*
-** Check to see if the argument is of the form:
-**
-** KEY = VALUE
-**
-** If it is, return a pointer to the first character of VALUE.
-** If not, return NULL. Spaces around the = are ignored.
-*/
-static const char *closureValueOfKey(const char *zKey, const char *zStr){
- int nKey = (int)strlen(zKey);
- int nStr = (int)strlen(zStr);
- int i;
- if( nStr<nKey+1 ) return 0;
- if( memcmp(zStr, zKey, nKey)!=0 ) return 0;
- for(i=nKey; isspace((unsigned char)zStr[i]); i++){}
- if( zStr[i]!='=' ) return 0;
- i++;
- while( isspace((unsigned char)zStr[i]) ){ i++; }
- return zStr+i;
-}
-
-/*
-** xConnect/xCreate method for the closure module. Arguments are:
-**
-** argv[0] -> module name ("transitive_closure")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[3...] -> arguments
-*/
-static int closureConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- int rc = SQLITE_OK; /* Return code */
- closure_vtab *pNew = 0; /* New virtual table */
- const char *zDb = argv[1];
- const char *zVal;
- int i;
-
- (void)pAux;
- *ppVtab = 0;
- pNew = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- rc = SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- pNew->db = db;
- pNew->zDb = sqlite3_mprintf("%s", zDb);
- if( pNew->zDb==0 ) goto closureConnectError;
- pNew->zSelf = sqlite3_mprintf("%s", argv[2]);
- if( pNew->zSelf==0 ) goto closureConnectError;
- for(i=3; i<argc; i++){
- zVal = closureValueOfKey("tablename", argv[i]);
- if( zVal ){
- sqlite3_free(pNew->zTableName);
- pNew->zTableName = closureDequote(zVal);
- if( pNew->zTableName==0 ) goto closureConnectError;
- continue;
- }
- zVal = closureValueOfKey("idcolumn", argv[i]);
- if( zVal ){
- sqlite3_free(pNew->zIdColumn);
- pNew->zIdColumn = closureDequote(zVal);
- if( pNew->zIdColumn==0 ) goto closureConnectError;
- continue;
- }
- zVal = closureValueOfKey("parentcolumn", argv[i]);
- if( zVal ){
- sqlite3_free(pNew->zParentColumn);
- pNew->zParentColumn = closureDequote(zVal);
- if( pNew->zParentColumn==0 ) goto closureConnectError;
- continue;
- }
- *pzErr = sqlite3_mprintf("unrecognized argument: [%s]\n", argv[i]);
- closureFree(pNew);
- *ppVtab = 0;
- return SQLITE_ERROR;
- }
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(id,depth,root HIDDEN,tablename HIDDEN,"
- "idcolumn HIDDEN,parentcolumn HIDDEN)"
- );
-#define CLOSURE_COL_ID 0
-#define CLOSURE_COL_DEPTH 1
-#define CLOSURE_COL_ROOT 2
-#define CLOSURE_COL_TABLENAME 3
-#define CLOSURE_COL_IDCOLUMN 4
-#define CLOSURE_COL_PARENTCOLUMN 5
- if( rc!=SQLITE_OK ){
- closureFree(pNew);
- }
- *ppVtab = &pNew->base;
- return rc;
-
-closureConnectError:
- closureFree(pNew);
- return rc;
-}
-
-/*
-** Open a new closure cursor.
-*/
-static int closureOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- closure_vtab *p = (closure_vtab*)pVTab;
- closure_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->pVtab = p;
- *ppCursor = &pCur->base;
- p->nCursor++;
- return SQLITE_OK;
-}
-
-/*
-** Free up all the memory allocated by a cursor. Set it rLimit to 0
-** to indicate that it is at EOF.
-*/
-static void closureClearCursor(closure_cursor *pCur){
- closureAvlDestroy(pCur->pClosure, (void(*)(closure_avl*))sqlite3_free);
- sqlite3_free(pCur->zTableName);
- sqlite3_free(pCur->zIdColumn);
- sqlite3_free(pCur->zParentColumn);
- pCur->zTableName = 0;
- pCur->zIdColumn = 0;
- pCur->zParentColumn = 0;
- pCur->pCurrent = 0;
- pCur->pClosure = 0;
-}
-
-/*
-** Close a closure cursor.
-*/
-static int closureClose(sqlite3_vtab_cursor *cur){
- closure_cursor *pCur = (closure_cursor *)cur;
- closureClearCursor(pCur);
- pCur->pVtab->nCursor--;
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Advance a cursor to its next row of output
-*/
-static int closureNext(sqlite3_vtab_cursor *cur){
- closure_cursor *pCur = (closure_cursor*)cur;
- pCur->pCurrent = closureAvlNext(pCur->pCurrent);
- return SQLITE_OK;
-}
-
-/*
-** Allocate and insert a node
-*/
-static int closureInsertNode(
- closure_queue *pQueue, /* Add new node to this queue */
- closure_cursor *pCur, /* The cursor into which to add the node */
- sqlite3_int64 id, /* The node ID */
- int iGeneration /* The generation number for this node */
-){
- closure_avl *pNew = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- pNew->id = id;
- pNew->iGeneration = iGeneration;
- closureAvlInsert(&pCur->pClosure, pNew);
- queuePush(pQueue, pNew);
- return SQLITE_OK;
-}
-
-/*
-** Called to "rewind" a cursor back to the beginning so that
-** it starts its output over again. Always called at least once
-** prior to any closureColumn, closureRowid, or closureEof call.
-**
-** This routine actually computes the closure.
-**
-** See the comment at the beginning of closureBestIndex() for a
-** description of the meaning of idxNum. The idxStr parameter is
-** not used.
-*/
-static int closureFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- closure_cursor *pCur = (closure_cursor *)pVtabCursor;
- closure_vtab *pVtab = pCur->pVtab;
- sqlite3_int64 iRoot;
- int mxGen = 999999999;
- char *zSql;
- sqlite3_stmt *pStmt;
- closure_avl *pAvl;
- int rc = SQLITE_OK;
- const char *zTableName = pVtab->zTableName;
- const char *zIdColumn = pVtab->zIdColumn;
- const char *zParentColumn = pVtab->zParentColumn;
- closure_queue sQueue;
-
- (void)idxStr; /* Unused parameter */
- (void)argc; /* Unused parameter */
- closureClearCursor(pCur);
- memset(&sQueue, 0, sizeof(sQueue));
- if( (idxNum & 1)==0 ){
- /* No root=$root in the WHERE clause. Return an empty set */
- return SQLITE_OK;
- }
- iRoot = sqlite3_value_int64(argv[0]);
- if( (idxNum & 0x000f0)!=0 ){
- mxGen = sqlite3_value_int(argv[(idxNum>>4)&0x0f]);
- if( (idxNum & 0x00002)!=0 ) mxGen--;
- }
- if( (idxNum & 0x00f00)!=0 ){
- zTableName = (const char*)sqlite3_value_text(argv[(idxNum>>8)&0x0f]);
- pCur->zTableName = sqlite3_mprintf("%s", zTableName);
- }
- if( (idxNum & 0x0f000)!=0 ){
- zIdColumn = (const char*)sqlite3_value_text(argv[(idxNum>>12)&0x0f]);
- pCur->zIdColumn = sqlite3_mprintf("%s", zIdColumn);
- }
- if( (idxNum & 0x0f0000)!=0 ){
- zParentColumn = (const char*)sqlite3_value_text(argv[(idxNum>>16)&0x0f]);
- pCur->zParentColumn = sqlite3_mprintf("%s", zParentColumn);
- }
-
- zSql = sqlite3_mprintf(
- "SELECT \"%w\".\"%w\" FROM \"%w\" WHERE \"%w\".\"%w\"=?1",
- zTableName, zIdColumn, zTableName, zTableName, zParentColumn);
- if( zSql==0 ){
- return SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v2(pVtab->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ){
- sqlite3_free(pVtab->base.zErrMsg);
- pVtab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pVtab->db));
- return rc;
- }
- }
- if( rc==SQLITE_OK ){
- rc = closureInsertNode(&sQueue, pCur, iRoot, 0);
- }
- while( (pAvl = queuePull(&sQueue))!=0 ){
- if( pAvl->iGeneration>=mxGen ) continue;
- sqlite3_bind_int64(pStmt, 1, pAvl->id);
- while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
- if( sqlite3_column_type(pStmt,0)==SQLITE_INTEGER ){
- sqlite3_int64 iNew = sqlite3_column_int64(pStmt, 0);
- if( closureAvlSearch(pCur->pClosure, iNew)==0 ){
- rc = closureInsertNode(&sQueue, pCur, iNew, pAvl->iGeneration+1);
- }
- }
- }
- sqlite3_reset(pStmt);
- }
- sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ){
- pCur->pCurrent = closureAvlFirst(pCur->pClosure);
- }
-
- return rc;
-}
-
-/*
-** Only the word and distance columns have values. All other columns
-** return NULL
-*/
-static int closureColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- closure_cursor *pCur = (closure_cursor*)cur;
- switch( i ){
- case CLOSURE_COL_ID: {
- sqlite3_result_int64(ctx, pCur->pCurrent->id);
- break;
- }
- case CLOSURE_COL_DEPTH: {
- sqlite3_result_int(ctx, pCur->pCurrent->iGeneration);
- break;
- }
- case CLOSURE_COL_ROOT: {
- sqlite3_result_null(ctx);
- break;
- }
- case CLOSURE_COL_TABLENAME: {
- sqlite3_result_text(ctx,
- pCur->zTableName ? pCur->zTableName : pCur->pVtab->zTableName,
- -1, SQLITE_TRANSIENT);
- break;
- }
- case CLOSURE_COL_IDCOLUMN: {
- sqlite3_result_text(ctx,
- pCur->zIdColumn ? pCur->zIdColumn : pCur->pVtab->zIdColumn,
- -1, SQLITE_TRANSIENT);
- break;
- }
- case CLOSURE_COL_PARENTCOLUMN: {
- sqlite3_result_text(ctx,
- pCur->zParentColumn ? pCur->zParentColumn : pCur->pVtab->zParentColumn,
- -1, SQLITE_TRANSIENT);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** The rowid. For the closure table, this is the same as the "id" column.
-*/
-static int closureRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- closure_cursor *pCur = (closure_cursor*)cur;
- *pRowid = pCur->pCurrent->id;
- return SQLITE_OK;
-}
-
-/*
-** EOF indicator
-*/
-static int closureEof(sqlite3_vtab_cursor *cur){
- closure_cursor *pCur = (closure_cursor*)cur;
- return pCur->pCurrent==0;
-}
-
-/*
-** Search for terms of these forms:
-**
-** (A) root = $root
-** (B1) depth < $depth
-** (B2) depth <= $depth
-** (B3) depth = $depth
-** (C) tablename = $tablename
-** (D) idcolumn = $idcolumn
-** (E) parentcolumn = $parentcolumn
-**
-**
-**
-** idxNum meaning
-** ---------- ------------------------------------------------------
-** 0x00000001 Term of the form (A) found
-** 0x00000002 The term of bit-2 is like (B1)
-** 0x000000f0 Index in filter.argv[] of $depth. 0 if not used.
-** 0x00000f00 Index in filter.argv[] of $tablename. 0 if not used.
-** 0x0000f000 Index in filter.argv[] of $idcolumn. 0 if not used
-** 0x000f0000 Index in filter.argv[] of $parentcolumn. 0 if not used.
-**
-** There must be a term of type (A). If there is not, then the index type
-** is 0 and the query will return an empty set.
-*/
-static int closureBestIndex(
- sqlite3_vtab *pTab, /* The virtual table */
- sqlite3_index_info *pIdxInfo /* Information about the query */
-){
- int iPlan = 0;
- int i;
- int idx = 1;
- const struct sqlite3_index_constraint *pConstraint;
- closure_vtab *pVtab = (closure_vtab*)pTab;
- double rCost = 10000000.0;
-
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( (iPlan & 1)==0
- && pConstraint->iColumn==CLOSURE_COL_ROOT
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= 1;
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- rCost /= 100.0;
- }
- if( (iPlan & 0x0000f0)==0
- && pConstraint->iColumn==CLOSURE_COL_DEPTH
- && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
- || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE
- || pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ)
- ){
- iPlan |= idx<<4;
- pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
- if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ) iPlan |= 0x000002;
- rCost /= 5.0;
- }
- if( (iPlan & 0x000f00)==0
- && pConstraint->iColumn==CLOSURE_COL_TABLENAME
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= idx<<8;
- pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- rCost /= 5.0;
- }
- if( (iPlan & 0x00f000)==0
- && pConstraint->iColumn==CLOSURE_COL_IDCOLUMN
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= idx<<12;
- pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- }
- if( (iPlan & 0x0f0000)==0
- && pConstraint->iColumn==CLOSURE_COL_PARENTCOLUMN
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= idx<<16;
- pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- }
- }
- if( (pVtab->zTableName==0 && (iPlan & 0x000f00)==0)
- || (pVtab->zIdColumn==0 && (iPlan & 0x00f000)==0)
- || (pVtab->zParentColumn==0 && (iPlan & 0x0f0000)==0)
- ){
- /* All of tablename, idcolumn, and parentcolumn must be specified
- ** in either the CREATE VIRTUAL TABLE or in the WHERE clause constraints
- ** or else the result is an empty set. */
- iPlan = 0;
- }
- if( (iPlan&1)==0 ){
- /* If there is no usable "root=?" term, then set the index-type to 0.
- ** Also clear any argvIndex variables already set. This is necessary
- ** to prevent the core from throwing an "xBestIndex malfunction error"
- ** error (because the argvIndex values are not contiguously assigned
- ** starting from 1). */
- rCost *= 1e30;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- pIdxInfo->aConstraintUsage[i].argvIndex = 0;
- }
- iPlan = 0;
- }
- pIdxInfo->idxNum = iPlan;
- if( pIdxInfo->nOrderBy==1
- && pIdxInfo->aOrderBy[0].iColumn==CLOSURE_COL_ID
- && pIdxInfo->aOrderBy[0].desc==0
- ){
- pIdxInfo->orderByConsumed = 1;
- }
- pIdxInfo->estimatedCost = rCost;
-
- return SQLITE_OK;
-}
-
-/*
-** A virtual table module that implements the "transitive_closure".
-*/
-static sqlite3_module closureModule = {
- 0, /* iVersion */
- closureConnect, /* xCreate */
- closureConnect, /* xConnect */
- closureBestIndex, /* xBestIndex */
- closureDisconnect, /* xDisconnect */
- closureDisconnect, /* xDestroy */
- closureOpen, /* xOpen - open a cursor */
- closureClose, /* xClose - close a cursor */
- closureFilter, /* xFilter - configure scan constraints */
- closureNext, /* xNext - advance a cursor */
- closureEof, /* xEof - check for end of scan */
- closureColumn, /* xColumn - read data */
- closureRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/*
-** Register the closure virtual table
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_closure_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_create_module(db, "transitive_closure", &closureModule, 0);
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/completion.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/completion.c
deleted file mode 100644
index 89c4f5d5db4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/completion.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
-** 2017-07-10
-**
-** 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 an eponymous virtual table that returns suggested
-** completions for a partial SQL input.
-**
-** Suggested usage:
-**
-** SELECT DISTINCT candidate COLLATE nocase
-** FROM completion($prefix,$wholeline)
-** ORDER BY 1;
-**
-** The two query parameters are optional. $prefix is the text of the
-** current word being typed and that is to be completed. $wholeline is
-** the complete input line, used for context.
-**
-** The raw completion() table might return the same candidate multiple
-** times, for example if the same column name is used to two or more
-** tables. And the candidates are returned in an arbitrary order. Hence,
-** the DISTINCT and ORDER BY are recommended.
-**
-** This virtual table operates at the speed of human typing, and so there
-** is no attempt to make it fast. Even a slow implementation will be much
-** faster than any human can type.
-**
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/* completion_vtab is a subclass of sqlite3_vtab which will
-** serve as the underlying representation of a completion virtual table
-*/
-typedef struct completion_vtab completion_vtab;
-struct completion_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- sqlite3 *db; /* Database connection for this completion vtab */
-};
-
-/* completion_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-typedef struct completion_cursor completion_cursor;
-struct completion_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3 *db; /* Database connection for this cursor */
- int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */
- char *zPrefix; /* The prefix for the word we want to complete */
- char *zLine; /* The whole that we want to complete */
- const char *zCurrentRow; /* Current output row */
- int szRow; /* Length of the zCurrentRow string */
- sqlite3_stmt *pStmt; /* Current statement */
- sqlite3_int64 iRowid; /* The rowid */
- int ePhase; /* Current phase */
- int j; /* inter-phase counter */
-};
-
-/* Values for ePhase:
-*/
-#define COMPLETION_FIRST_PHASE 1
-#define COMPLETION_KEYWORDS 1
-#define COMPLETION_PRAGMAS 2
-#define COMPLETION_FUNCTIONS 3
-#define COMPLETION_COLLATIONS 4
-#define COMPLETION_INDEXES 5
-#define COMPLETION_TRIGGERS 6
-#define COMPLETION_DATABASES 7
-#define COMPLETION_TABLES 8 /* Also VIEWs and TRIGGERs */
-#define COMPLETION_COLUMNS 9
-#define COMPLETION_MODULES 10
-#define COMPLETION_EOF 11
-
-/*
-** The completionConnect() method is invoked to create a new
-** completion_vtab that describes the completion virtual table.
-**
-** Think of this routine as the constructor for completion_vtab objects.
-**
-** All this routine needs to do is:
-**
-** (1) Allocate the completion_vtab object and initialize all fields.
-**
-** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-** result set of queries against completion will look like.
-*/
-static int completionConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- completion_vtab *pNew;
- int rc;
-
- (void)(pAux); /* Unused parameter */
- (void)(argc); /* Unused parameter */
- (void)(argv); /* Unused parameter */
- (void)(pzErr); /* Unused parameter */
-
-/* Column numbers */
-#define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */
-#define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */
-#define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */
-#define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x("
- " candidate TEXT,"
- " prefix TEXT HIDDEN,"
- " wholeline TEXT HIDDEN,"
- " phase INT HIDDEN" /* Used for debugging only */
- ")");
- if( rc==SQLITE_OK ){
- pNew = sqlite3_malloc( sizeof(*pNew) );
- *ppVtab = (sqlite3_vtab*)pNew;
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- pNew->db = db;
- }
- return rc;
-}
-
-/*
-** This method is the destructor for completion_cursor objects.
-*/
-static int completionDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new completion_cursor object.
-*/
-static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- completion_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->db = ((completion_vtab*)p)->db;
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Reset the completion_cursor.
-*/
-static void completionCursorReset(completion_cursor *pCur){
- sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0;
- sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0;
- sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
- pCur->j = 0;
-}
-
-/*
-** Destructor for a completion_cursor.
-*/
-static int completionClose(sqlite3_vtab_cursor *cur){
- completionCursorReset((completion_cursor*)cur);
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-/*
-** Advance a completion_cursor to its next row of output.
-**
-** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
-** record the current state of the scan. This routine sets ->zCurrentRow
-** to the current row of output and then returns. If no more rows remain,
-** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
-** table that has reached the end of its scan.
-**
-** The current implementation just lists potential identifiers and
-** keywords and filters them by zPrefix. Future enhancements should
-** take zLine into account to try to restrict the set of identifiers and
-** keywords based on what would be legal at the current point of input.
-*/
-static int completionNext(sqlite3_vtab_cursor *cur){
- completion_cursor *pCur = (completion_cursor*)cur;
- int eNextPhase = 0; /* Next phase to try if current phase reaches end */
- int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */
- pCur->iRowid++;
- while( pCur->ePhase!=COMPLETION_EOF ){
- switch( pCur->ePhase ){
- case COMPLETION_KEYWORDS: {
- if( pCur->j >= sqlite3_keyword_count() ){
- pCur->zCurrentRow = 0;
- pCur->ePhase = COMPLETION_DATABASES;
- }else{
- sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
- }
- iCol = -1;
- break;
- }
- case COMPLETION_DATABASES: {
- if( pCur->pStmt==0 ){
- sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
- &pCur->pStmt, 0);
- }
- iCol = 1;
- eNextPhase = COMPLETION_TABLES;
- break;
- }
- case COMPLETION_TABLES: {
- if( pCur->pStmt==0 ){
- sqlite3_stmt *pS2;
- char *zSql = 0;
- const char *zSep = "";
- sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
- while( sqlite3_step(pS2)==SQLITE_ROW ){
- const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
- zSql = sqlite3_mprintf(
- "%z%s"
- "SELECT name FROM \"%w\".sqlite_master",
- zSql, zSep, zDb
- );
- if( zSql==0 ) return SQLITE_NOMEM;
- zSep = " UNION ";
- }
- sqlite3_finalize(pS2);
- sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
- sqlite3_free(zSql);
- }
- iCol = 0;
- eNextPhase = COMPLETION_COLUMNS;
- break;
- }
- case COMPLETION_COLUMNS: {
- if( pCur->pStmt==0 ){
- sqlite3_stmt *pS2;
- char *zSql = 0;
- const char *zSep = "";
- sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
- while( sqlite3_step(pS2)==SQLITE_ROW ){
- const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
- zSql = sqlite3_mprintf(
- "%z%s"
- "SELECT pti.name FROM \"%w\".sqlite_master AS sm"
- " JOIN pragma_table_info(sm.name,%Q) AS pti"
- " WHERE sm.type='table'",
- zSql, zSep, zDb, zDb
- );
- if( zSql==0 ) return SQLITE_NOMEM;
- zSep = " UNION ";
- }
- sqlite3_finalize(pS2);
- sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
- sqlite3_free(zSql);
- }
- iCol = 0;
- eNextPhase = COMPLETION_EOF;
- break;
- }
- }
- if( iCol<0 ){
- /* This case is when the phase presets zCurrentRow */
- if( pCur->zCurrentRow==0 ) continue;
- }else{
- if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
- /* Extract the next row of content */
- pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
- pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
- }else{
- /* When all rows are finished, advance to the next phase */
- sqlite3_finalize(pCur->pStmt);
- pCur->pStmt = 0;
- pCur->ePhase = eNextPhase;
- continue;
- }
- }
- if( pCur->nPrefix==0 ) break;
- if( pCur->nPrefix<=pCur->szRow
- && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
- ){
- break;
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the completion_cursor
-** is currently pointing.
-*/
-static int completionColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- completion_cursor *pCur = (completion_cursor*)cur;
- switch( i ){
- case COMPLETION_COLUMN_CANDIDATE: {
- sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
- break;
- }
- case COMPLETION_COLUMN_PREFIX: {
- sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
- break;
- }
- case COMPLETION_COLUMN_WHOLELINE: {
- sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
- break;
- }
- case COMPLETION_COLUMN_PHASE: {
- sqlite3_result_int(ctx, pCur->ePhase);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** rowid is the same as the output value.
-*/
-static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- completion_cursor *pCur = (completion_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int completionEof(sqlite3_vtab_cursor *cur){
- completion_cursor *pCur = (completion_cursor*)cur;
- return pCur->ePhase >= COMPLETION_EOF;
-}
-
-/*
-** This method is called to "rewind" the completion_cursor object back
-** to the first row of output. This method is always called at least
-** once prior to any call to completionColumn() or completionRowid() or
-** completionEof().
-*/
-static int completionFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- completion_cursor *pCur = (completion_cursor *)pVtabCursor;
- int iArg = 0;
- (void)(idxStr); /* Unused parameter */
- (void)(argc); /* Unused parameter */
- completionCursorReset(pCur);
- if( idxNum & 1 ){
- pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
- if( pCur->nPrefix>0 ){
- pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
- if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
- }
- iArg++;
- }
- if( idxNum & 2 ){
- pCur->nLine = sqlite3_value_bytes(argv[iArg]);
- if( pCur->nLine>0 ){
- pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
- if( pCur->zLine==0 ) return SQLITE_NOMEM;
- }
- iArg++;
- }
- if( pCur->zLine!=0 && pCur->zPrefix==0 ){
- int i = pCur->nLine;
- while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
- i--;
- }
- pCur->nPrefix = pCur->nLine - i;
- if( pCur->nPrefix>0 ){
- pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
- if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
- }
- }
- pCur->iRowid = 0;
- pCur->ePhase = COMPLETION_FIRST_PHASE;
- return completionNext(pVtabCursor);
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the completion virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** There are two hidden parameters that act as arguments to the table-valued
-** function: "prefix" and "wholeline". Bit 0 of idxNum is set if "prefix"
-** is available and bit 1 is set if "wholeline" is available.
-*/
-static int completionBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i; /* Loop over constraints */
- int idxNum = 0; /* The query plan bitmask */
- int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */
- int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
- int nArg = 0; /* Number of arguments that completeFilter() expects */
- const struct sqlite3_index_constraint *pConstraint;
-
- (void)(tab); /* Unused parameter */
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case COMPLETION_COLUMN_PREFIX:
- prefixIdx = i;
- idxNum |= 1;
- break;
- case COMPLETION_COLUMN_WHOLELINE:
- wholelineIdx = i;
- idxNum |= 2;
- break;
- }
- }
- if( prefixIdx>=0 ){
- pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
- }
- if( wholelineIdx>=0 ){
- pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
- }
- pIdxInfo->idxNum = idxNum;
- pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
- pIdxInfo->estimatedRows = 500 - 100*nArg;
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** completion virtual table.
-*/
-static sqlite3_module completionModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- completionConnect, /* xConnect */
- completionBestIndex, /* xBestIndex */
- completionDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- completionOpen, /* xOpen - open a cursor */
- completionClose, /* xClose - close a cursor */
- completionFilter, /* xFilter - configure scan constraints */
- completionNext, /* xNext - advance a cursor */
- completionEof, /* xEof - check for end of scan */
- completionColumn, /* xColumn - read data */
- completionRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-int sqlite3CompletionVtabInit(sqlite3 *db){
- int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_create_module(db, "completion", &completionModule, 0);
-#endif
- return rc;
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_completion_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)(pzErrMsg); /* Unused parameter */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3CompletionVtabInit(db);
-#endif
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/compress.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/compress.c
deleted file mode 100644
index 6e7d8b61484..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/compress.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-** 2014-06-13
-**
-** 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 SQLite extension implements SQL compression functions
-** compress() and uncompress() using ZLIB.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <zlib.h>
-
-/*
-** Implementation of the "compress(X)" SQL function. The input X is
-** compressed using zLib and the output is returned.
-**
-** The output is a BLOB that begins with a variable-length integer that
-** is the input size in bytes (the size of X before compression). The
-** variable-length integer is implemented as 1 to 5 bytes. There are
-** seven bits per integer stored in the lower seven bits of each byte.
-** More significant bits occur first. The most significant bit (0x80)
-** is a flag to indicate the end of the integer.
-**
-** This function, SQLAR, and ZIP all use the same "deflate" compression
-** algorithm, but each is subtly different:
-**
-** * ZIP uses raw deflate.
-**
-** * SQLAR uses the "zlib format" which is raw deflate with a two-byte
-** algorithm-identification header and a four-byte checksum at the end.
-**
-** * This utility uses the "zlib format" like SQLAR, but adds the variable-
-** length integer uncompressed size value at the beginning.
-**
-** This function might be extended in the future to support compression
-** formats other than deflate, by providing a different algorithm-id
-** mark following the variable-length integer size parameter.
-*/
-static void compressFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *pIn;
- unsigned char *pOut;
- unsigned int nIn;
- unsigned long int nOut;
- unsigned char x[8];
- int rc;
- int i, j;
-
- pIn = sqlite3_value_blob(argv[0]);
- nIn = sqlite3_value_bytes(argv[0]);
- nOut = 13 + nIn + (nIn+999)/1000;
- pOut = sqlite3_malloc( nOut+5 );
- for(i=4; i>=0; i--){
- x[i] = (nIn >> (7*(4-i)))&0x7f;
- }
- for(i=0; i<4 && x[i]==0; i++){}
- for(j=0; i<=4; i++, j++) pOut[j] = x[i];
- pOut[j-1] |= 0x80;
- rc = compress(&pOut[j], &nOut, pIn, nIn);
- if( rc==Z_OK ){
- sqlite3_result_blob(context, pOut, nOut+j, sqlite3_free);
- }else{
- sqlite3_free(pOut);
- }
-}
-
-/*
-** Implementation of the "uncompress(X)" SQL function. The argument X
-** is a blob which was obtained from compress(Y). The output will be
-** the value Y.
-*/
-static void uncompressFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *pIn;
- unsigned char *pOut;
- unsigned int nIn;
- unsigned long int nOut;
- int rc;
- int i;
-
- pIn = sqlite3_value_blob(argv[0]);
- nIn = sqlite3_value_bytes(argv[0]);
- nOut = 0;
- for(i=0; i<nIn && i<5; i++){
- nOut = (nOut<<7) | (pIn[i]&0x7f);
- if( (pIn[i]&0x80)!=0 ){ i++; break; }
- }
- pOut = sqlite3_malloc( nOut+1 );
- rc = uncompress(pOut, &nOut, &pIn[i], nIn-i);
- if( rc==Z_OK ){
- sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
- }else{
- sqlite3_free(pOut);
- }
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_compress_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
- compressFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "uncompress", 1, SQLITE_UTF8, 0,
- uncompressFunc, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/csv.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/csv.c
deleted file mode 100644
index ec90f96f28a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/csv.c
+++ /dev/null
@@ -1,887 +0,0 @@
-/*
-** 2016-05-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 contains the implementation of an SQLite virtual table for
-** reading CSV files.
-**
-** Usage:
-**
-** .load ./csv
-** CREATE VIRTUAL TABLE temp.csv USING csv(filename=FILENAME);
-** SELECT * FROM csv;
-**
-** The columns are named "c1", "c2", "c3", ... by default. But the
-** application can define its own CREATE TABLE statement as an additional
-** parameter. For example:
-**
-** CREATE VIRTUAL TABLE temp.csv2 USING csv(
-** filename = "../http.log",
-** schema = "CREATE TABLE x(date,ipaddr,url,referrer,userAgent)"
-** );
-**
-** Instead of specifying a file, the text of the CSV can be loaded using
-** the data= parameter.
-**
-** If the columns=N parameter is supplied, then the CSV file is assumed to have
-** N columns. If the columns parameter is omitted, the CSV file is opened
-** as soon as the virtual table is constructed and the first row of the CSV
-** is read in order to count the tables.
-**
-** Some extra debugging features (used for testing virtual tables) are available
-** if this module is compiled with -DSQLITE_TEST.
-*/
-#include <sqlite3ext.h>
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <stdio.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** A macro to hint to the compiler that a function should not be
-** inlined.
-*/
-#if defined(__GNUC__)
-# define CSV_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER) && _MSC_VER>=1310
-# define CSV_NOINLINE __declspec(noinline)
-#else
-# define CSV_NOINLINE
-#endif
-
-
-/* Max size of the error message in a CsvReader */
-#define CSV_MXERR 200
-
-/* Size of the CsvReader input buffer */
-#define CSV_INBUFSZ 1024
-
-/* A context object used when read a CSV file. */
-typedef struct CsvReader CsvReader;
-struct CsvReader {
- FILE *in; /* Read the CSV text from this input stream */
- char *z; /* Accumulated text for a field */
- int n; /* Number of bytes in z */
- int nAlloc; /* Space allocated for z[] */
- int nLine; /* Current line number */
- int bNotFirst; /* True if prior text has been seen */
- int cTerm; /* Character that terminated the most recent field */
- size_t iIn; /* Next unread character in the input buffer */
- size_t nIn; /* Number of characters in the input buffer */
- char *zIn; /* The input buffer */
- char zErr[CSV_MXERR]; /* Error message */
-};
-
-/* Initialize a CsvReader object */
-static void csv_reader_init(CsvReader *p){
- p->in = 0;
- p->z = 0;
- p->n = 0;
- p->nAlloc = 0;
- p->nLine = 0;
- p->bNotFirst = 0;
- p->nIn = 0;
- p->zIn = 0;
- p->zErr[0] = 0;
-}
-
-/* Close and reset a CsvReader object */
-static void csv_reader_reset(CsvReader *p){
- if( p->in ){
- fclose(p->in);
- sqlite3_free(p->zIn);
- }
- sqlite3_free(p->z);
- csv_reader_init(p);
-}
-
-/* Report an error on a CsvReader */
-static void csv_errmsg(CsvReader *p, const char *zFormat, ...){
- va_list ap;
- va_start(ap, zFormat);
- sqlite3_vsnprintf(CSV_MXERR, p->zErr, zFormat, ap);
- va_end(ap);
-}
-
-/* Open the file associated with a CsvReader
-** Return the number of errors.
-*/
-static int csv_reader_open(
- CsvReader *p, /* The reader to open */
- const char *zFilename, /* Read from this filename */
- const char *zData /* ... or use this data */
-){
- if( zFilename ){
- p->zIn = sqlite3_malloc( CSV_INBUFSZ );
- if( p->zIn==0 ){
- csv_errmsg(p, "out of memory");
- return 1;
- }
- p->in = fopen(zFilename, "rb");
- if( p->in==0 ){
- sqlite3_free(p->zIn);
- csv_reader_reset(p);
- csv_errmsg(p, "cannot open '%s' for reading", zFilename);
- return 1;
- }
- }else{
- assert( p->in==0 );
- p->zIn = (char*)zData;
- p->nIn = strlen(zData);
- }
- return 0;
-}
-
-/* The input buffer has overflowed. Refill the input buffer, then
-** return the next character
-*/
-static CSV_NOINLINE int csv_getc_refill(CsvReader *p){
- size_t got;
-
- assert( p->iIn>=p->nIn ); /* Only called on an empty input buffer */
- assert( p->in!=0 ); /* Only called if reading froma file */
-
- got = fread(p->zIn, 1, CSV_INBUFSZ, p->in);
- if( got==0 ) return EOF;
- p->nIn = got;
- p->iIn = 1;
- return p->zIn[0];
-}
-
-/* Return the next character of input. Return EOF at end of input. */
-static int csv_getc(CsvReader *p){
- if( p->iIn >= p->nIn ){
- if( p->in!=0 ) return csv_getc_refill(p);
- return EOF;
- }
- return ((unsigned char*)p->zIn)[p->iIn++];
-}
-
-/* Increase the size of p->z and append character c to the end.
-** Return 0 on success and non-zero if there is an OOM error */
-static CSV_NOINLINE int csv_resize_and_append(CsvReader *p, char c){
- char *zNew;
- int nNew = p->nAlloc*2 + 100;
- zNew = sqlite3_realloc64(p->z, nNew);
- if( zNew ){
- p->z = zNew;
- p->nAlloc = nNew;
- p->z[p->n++] = c;
- return 0;
- }else{
- csv_errmsg(p, "out of memory");
- return 1;
- }
-}
-
-/* Append a single character to the CsvReader.z[] array.
-** Return 0 on success and non-zero if there is an OOM error */
-static int csv_append(CsvReader *p, char c){
- if( p->n>=p->nAlloc-1 ) return csv_resize_and_append(p, c);
- p->z[p->n++] = c;
- return 0;
-}
-
-/* Read a single field of CSV text. Compatible with rfc4180 and extended
-** with the option of having a separator other than ",".
-**
-** + Input comes from p->in.
-** + Store results in p->z of length p->n. Space to hold p->z comes
-** from sqlite3_malloc64().
-** + Keep track of the line number in p->nLine.
-** + Store the character that terminates the field in p->cTerm. Store
-** EOF on end-of-file.
-**
-** Return 0 at EOF or on OOM. On EOF, the p->cTerm character will have
-** been set to EOF.
-*/
-static char *csv_read_one_field(CsvReader *p){
- int c;
- p->n = 0;
- c = csv_getc(p);
- if( c==EOF ){
- p->cTerm = EOF;
- return 0;
- }
- if( c=='"' ){
- int pc, ppc;
- int startLine = p->nLine;
- pc = ppc = 0;
- while( 1 ){
- c = csv_getc(p);
- if( c<='"' || pc=='"' ){
- if( c=='\n' ) p->nLine++;
- if( c=='"' ){
- if( pc=='"' ){
- pc = 0;
- continue;
- }
- }
- if( (c==',' && pc=='"')
- || (c=='\n' && pc=='"')
- || (c=='\n' && pc=='\r' && ppc=='"')
- || (c==EOF && pc=='"')
- ){
- do{ p->n--; }while( p->z[p->n]!='"' );
- p->cTerm = (char)c;
- break;
- }
- if( pc=='"' && c!='\r' ){
- csv_errmsg(p, "line %d: unescaped %c character", p->nLine, '"');
- break;
- }
- if( c==EOF ){
- csv_errmsg(p, "line %d: unterminated %c-quoted field\n",
- startLine, '"');
- p->cTerm = (char)c;
- break;
- }
- }
- if( csv_append(p, (char)c) ) return 0;
- ppc = pc;
- pc = c;
- }
- }else{
- /* If this is the first field being parsed and it begins with the
- ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
- if( (c&0xff)==0xef && p->bNotFirst==0 ){
- csv_append(p, (char)c);
- c = csv_getc(p);
- if( (c&0xff)==0xbb ){
- csv_append(p, (char)c);
- c = csv_getc(p);
- if( (c&0xff)==0xbf ){
- p->bNotFirst = 1;
- p->n = 0;
- return csv_read_one_field(p);
- }
- }
- }
- while( c>',' || (c!=EOF && c!=',' && c!='\n') ){
- if( csv_append(p, (char)c) ) return 0;
- c = csv_getc(p);
- }
- if( c=='\n' ){
- p->nLine++;
- if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
- }
- p->cTerm = (char)c;
- }
- if( p->z ) p->z[p->n] = 0;
- p->bNotFirst = 1;
- return p->z;
-}
-
-
-/* Forward references to the various virtual table methods implemented
-** in this file. */
-static int csvtabCreate(sqlite3*, void*, int, const char*const*,
- sqlite3_vtab**,char**);
-static int csvtabConnect(sqlite3*, void*, int, const char*const*,
- sqlite3_vtab**,char**);
-static int csvtabBestIndex(sqlite3_vtab*,sqlite3_index_info*);
-static int csvtabDisconnect(sqlite3_vtab*);
-static int csvtabOpen(sqlite3_vtab*, sqlite3_vtab_cursor**);
-static int csvtabClose(sqlite3_vtab_cursor*);
-static int csvtabFilter(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv);
-static int csvtabNext(sqlite3_vtab_cursor*);
-static int csvtabEof(sqlite3_vtab_cursor*);
-static int csvtabColumn(sqlite3_vtab_cursor*,sqlite3_context*,int);
-static int csvtabRowid(sqlite3_vtab_cursor*,sqlite3_int64*);
-
-/* An instance of the CSV virtual table */
-typedef struct CsvTable {
- sqlite3_vtab base; /* Base class. Must be first */
- char *zFilename; /* Name of the CSV file */
- char *zData; /* Raw CSV data in lieu of zFilename */
- long iStart; /* Offset to start of data in zFilename */
- int nCol; /* Number of columns in the CSV file */
- unsigned int tstFlags; /* Bit values used for testing */
-} CsvTable;
-
-/* Allowed values for tstFlags */
-#define CSVTEST_FIDX 0x0001 /* Pretend that constrained searchs cost less*/
-
-/* A cursor for the CSV virtual table */
-typedef struct CsvCursor {
- sqlite3_vtab_cursor base; /* Base class. Must be first */
- CsvReader rdr; /* The CsvReader object */
- char **azVal; /* Value of the current row */
- int *aLen; /* Length of each entry */
- sqlite3_int64 iRowid; /* The current rowid. Negative for EOF */
-} CsvCursor;
-
-/* Transfer error message text from a reader into a CsvTable */
-static void csv_xfer_error(CsvTable *pTab, CsvReader *pRdr){
- sqlite3_free(pTab->base.zErrMsg);
- pTab->base.zErrMsg = sqlite3_mprintf("%s", pRdr->zErr);
-}
-
-/*
-** This method is the destructor fo a CsvTable object.
-*/
-static int csvtabDisconnect(sqlite3_vtab *pVtab){
- CsvTable *p = (CsvTable*)pVtab;
- sqlite3_free(p->zFilename);
- sqlite3_free(p->zData);
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/* Skip leading whitespace. Return a pointer to the first non-whitespace
-** character, or to the zero terminator if the string has only whitespace */
-static const char *csv_skip_whitespace(const char *z){
- while( isspace((unsigned char)z[0]) ) z++;
- return z;
-}
-
-/* Remove trailing whitespace from the end of string z[] */
-static void csv_trim_whitespace(char *z){
- size_t n = strlen(z);
- while( n>0 && isspace((unsigned char)z[n]) ) n--;
- z[n] = 0;
-}
-
-/* Dequote the string */
-static void csv_dequote(char *z){
- int j;
- char cQuote = z[0];
- size_t i, n;
-
- if( cQuote!='\'' && cQuote!='"' ) return;
- n = strlen(z);
- if( n<2 || z[n-1]!=z[0] ) return;
- for(i=1, j=0; i<n-1; i++){
- if( z[i]==cQuote && z[i+1]==cQuote ) i++;
- z[j++] = z[i];
- }
- z[j] = 0;
-}
-
-/* Check to see if the string is of the form: "TAG = VALUE" with optional
-** whitespace before and around tokens. If it is, return a pointer to the
-** first character of VALUE. If it is not, return NULL.
-*/
-static const char *csv_parameter(const char *zTag, int nTag, const char *z){
- z = csv_skip_whitespace(z);
- if( strncmp(zTag, z, nTag)!=0 ) return 0;
- z = csv_skip_whitespace(z+nTag);
- if( z[0]!='=' ) return 0;
- return csv_skip_whitespace(z+1);
-}
-
-/* Decode a parameter that requires a dequoted string.
-**
-** Return 1 if the parameter is seen, or 0 if not. 1 is returned
-** even if there is an error. If an error occurs, then an error message
-** is left in p->zErr. If there are no errors, p->zErr[0]==0.
-*/
-static int csv_string_parameter(
- CsvReader *p, /* Leave the error message here, if there is one */
- const char *zParam, /* Parameter we are checking for */
- const char *zArg, /* Raw text of the virtual table argment */
- char **pzVal /* Write the dequoted string value here */
-){
- const char *zValue;
- zValue = csv_parameter(zParam,(int)strlen(zParam),zArg);
- if( zValue==0 ) return 0;
- p->zErr[0] = 0;
- if( *pzVal ){
- csv_errmsg(p, "more than one '%s' parameter", zParam);
- return 1;
- }
- *pzVal = sqlite3_mprintf("%s", zValue);
- if( *pzVal==0 ){
- csv_errmsg(p, "out of memory");
- return 1;
- }
- csv_trim_whitespace(*pzVal);
- csv_dequote(*pzVal);
- return 1;
-}
-
-
-/* Return 0 if the argument is false and 1 if it is true. Return -1 if
-** we cannot really tell.
-*/
-static int csv_boolean(const char *z){
- if( sqlite3_stricmp("yes",z)==0
- || sqlite3_stricmp("on",z)==0
- || sqlite3_stricmp("true",z)==0
- || (z[0]=='1' && z[1]==0)
- ){
- return 1;
- }
- if( sqlite3_stricmp("no",z)==0
- || sqlite3_stricmp("off",z)==0
- || sqlite3_stricmp("false",z)==0
- || (z[0]=='0' && z[1]==0)
- ){
- return 0;
- }
- return -1;
-}
-
-
-/*
-** Parameters:
-** filename=FILENAME Name of file containing CSV content
-** data=TEXT Direct CSV content.
-** schema=SCHEMA Alternative CSV schema.
-** header=YES|NO First row of CSV defines the names of
-** columns if "yes". Default "no".
-** columns=N Assume the CSV file contains N columns.
-**
-** Only available if compiled with SQLITE_TEST:
-**
-** testflags=N Bitmask of test flags. Optional
-**
-** If schema= is omitted, then the columns are named "c0", "c1", "c2",
-** and so forth. If columns=N is omitted, then the file is opened and
-** the number of columns in the first row is counted to determine the
-** column count. If header=YES, then the first row is skipped.
-*/
-static int csvtabConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- CsvTable *pNew = 0; /* The CsvTable object to construct */
- int bHeader = -1; /* header= flags. -1 means not seen yet */
- int rc = SQLITE_OK; /* Result code from this routine */
- int i, j; /* Loop counters */
-#ifdef SQLITE_TEST
- int tstFlags = 0; /* Value for testflags=N parameter */
-#endif
- int nCol = -99; /* Value of the columns= parameter */
- CsvReader sRdr; /* A CSV file reader used to store an error
- ** message and/or to count the number of columns */
- static const char *azParam[] = {
- "filename", "data", "schema",
- };
- char *azPValue[3]; /* Parameter values */
-# define CSV_FILENAME (azPValue[0])
-# define CSV_DATA (azPValue[1])
-# define CSV_SCHEMA (azPValue[2])
-
-
- assert( sizeof(azPValue)==sizeof(azParam) );
- memset(&sRdr, 0, sizeof(sRdr));
- memset(azPValue, 0, sizeof(azPValue));
- for(i=3; i<argc; i++){
- const char *z = argv[i];
- const char *zValue;
- for(j=0; j<sizeof(azParam)/sizeof(azParam[0]); j++){
- if( csv_string_parameter(&sRdr, azParam[j], z, &azPValue[j]) ) break;
- }
- if( j<sizeof(azParam)/sizeof(azParam[0]) ){
- if( sRdr.zErr[0] ) goto csvtab_connect_error;
- }else
- if( (zValue = csv_parameter("header",6,z))!=0 ){
- int x;
- if( bHeader>=0 ){
- csv_errmsg(&sRdr, "more than one 'header' parameter");
- goto csvtab_connect_error;
- }
- x = csv_boolean(zValue);
- if( x==1 ){
- bHeader = 1;
- }else if( x==0 ){
- bHeader = 0;
- }else{
- csv_errmsg(&sRdr, "unrecognized argument to 'header': %s", zValue);
- goto csvtab_connect_error;
- }
- }else
-#ifdef SQLITE_TEST
- if( (zValue = csv_parameter("testflags",9,z))!=0 ){
- tstFlags = (unsigned int)atoi(zValue);
- }else
-#endif
- if( (zValue = csv_parameter("columns",7,z))!=0 ){
- if( nCol>0 ){
- csv_errmsg(&sRdr, "more than one 'columns' parameter");
- goto csvtab_connect_error;
- }
- nCol = atoi(zValue);
- if( nCol<=0 ){
- csv_errmsg(&sRdr, "must have at least one column");
- goto csvtab_connect_error;
- }
- }else
- {
- csv_errmsg(&sRdr, "unrecognized parameter '%s'", z);
- goto csvtab_connect_error;
- }
- }
- if( (CSV_FILENAME==0)==(CSV_DATA==0) ){
- csv_errmsg(&sRdr, "must either filename= or data= but not both");
- goto csvtab_connect_error;
- }
- if( nCol<=0 && csv_reader_open(&sRdr, CSV_FILENAME, CSV_DATA) ){
- goto csvtab_connect_error;
- }
- pNew = sqlite3_malloc( sizeof(*pNew) );
- *ppVtab = (sqlite3_vtab*)pNew;
- if( pNew==0 ) goto csvtab_connect_oom;
- memset(pNew, 0, sizeof(*pNew));
- if( nCol>0 ){
- pNew->nCol = nCol;
- }else{
- do{
- csv_read_one_field(&sRdr);
- pNew->nCol++;
- }while( sRdr.cTerm==',' );
- }
- pNew->zFilename = CSV_FILENAME; CSV_FILENAME = 0;
- pNew->zData = CSV_DATA; CSV_DATA = 0;
-#ifdef SQLITE_TEST
- pNew->tstFlags = tstFlags;
-#endif
- pNew->iStart = bHeader==1 ? ftell(sRdr.in) : 0;
- csv_reader_reset(&sRdr);
- if( CSV_SCHEMA==0 ){
- char *zSep = "";
- CSV_SCHEMA = sqlite3_mprintf("CREATE TABLE x(");
- if( CSV_SCHEMA==0 ) goto csvtab_connect_oom;
- for(i=0; i<pNew->nCol; i++){
- CSV_SCHEMA = sqlite3_mprintf("%z%sc%d TEXT",CSV_SCHEMA, zSep, i);
- zSep = ",";
- }
- CSV_SCHEMA = sqlite3_mprintf("%z);", CSV_SCHEMA);
- }
- rc = sqlite3_declare_vtab(db, CSV_SCHEMA);
- if( rc ) goto csvtab_connect_error;
- for(i=0; i<sizeof(azPValue)/sizeof(azPValue[0]); i++){
- sqlite3_free(azPValue[i]);
- }
- return SQLITE_OK;
-
-csvtab_connect_oom:
- rc = SQLITE_NOMEM;
- csv_errmsg(&sRdr, "out of memory");
-
-csvtab_connect_error:
- if( pNew ) csvtabDisconnect(&pNew->base);
- for(i=0; i<sizeof(azPValue)/sizeof(azPValue[0]); i++){
- sqlite3_free(azPValue[i]);
- }
- if( sRdr.zErr[0] ){
- sqlite3_free(*pzErr);
- *pzErr = sqlite3_mprintf("%s", sRdr.zErr);
- }
- csv_reader_reset(&sRdr);
- if( rc==SQLITE_OK ) rc = SQLITE_ERROR;
- return rc;
-}
-
-/*
-** Reset the current row content held by a CsvCursor.
-*/
-static void csvtabCursorRowReset(CsvCursor *pCur){
- CsvTable *pTab = (CsvTable*)pCur->base.pVtab;
- int i;
- for(i=0; i<pTab->nCol; i++){
- sqlite3_free(pCur->azVal[i]);
- pCur->azVal[i] = 0;
- pCur->aLen[i] = 0;
- }
-}
-
-/*
-** The xConnect and xCreate methods do the same thing, but they must be
-** different so that the virtual table is not an eponymous virtual table.
-*/
-static int csvtabCreate(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- return csvtabConnect(db, pAux, argc, argv, ppVtab, pzErr);
-}
-
-/*
-** Destructor for a CsvCursor.
-*/
-static int csvtabClose(sqlite3_vtab_cursor *cur){
- CsvCursor *pCur = (CsvCursor*)cur;
- csvtabCursorRowReset(pCur);
- csv_reader_reset(&pCur->rdr);
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new CsvTable cursor object.
-*/
-static int csvtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- CsvTable *pTab = (CsvTable*)p;
- CsvCursor *pCur;
- size_t nByte;
- nByte = sizeof(*pCur) + (sizeof(char*)+sizeof(int))*pTab->nCol;
- pCur = sqlite3_malloc64( nByte );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, nByte);
- pCur->azVal = (char**)&pCur[1];
- pCur->aLen = (int*)&pCur->azVal[pTab->nCol];
- *ppCursor = &pCur->base;
- if( csv_reader_open(&pCur->rdr, pTab->zFilename, pTab->zData) ){
- csv_xfer_error(pTab, &pCur->rdr);
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a CsvCursor to its next row of input.
-** Set the EOF marker if we reach the end of input.
-*/
-static int csvtabNext(sqlite3_vtab_cursor *cur){
- CsvCursor *pCur = (CsvCursor*)cur;
- CsvTable *pTab = (CsvTable*)cur->pVtab;
- int i = 0;
- char *z;
- do{
- z = csv_read_one_field(&pCur->rdr);
- if( z==0 ){
- break;
- }
- if( i<pTab->nCol ){
- if( pCur->aLen[i] < pCur->rdr.n+1 ){
- char *zNew = sqlite3_realloc64(pCur->azVal[i], pCur->rdr.n+1);
- if( zNew==0 ){
- csv_errmsg(&pCur->rdr, "out of memory");
- csv_xfer_error(pTab, &pCur->rdr);
- break;
- }
- pCur->azVal[i] = zNew;
- pCur->aLen[i] = pCur->rdr.n+1;
- }
- memcpy(pCur->azVal[i], z, pCur->rdr.n+1);
- i++;
- }
- }while( pCur->rdr.cTerm==',' );
- if( z==0 || (pCur->rdr.cTerm==EOF && i<pTab->nCol) ){
- pCur->iRowid = -1;
- }else{
- pCur->iRowid++;
- while( i<pTab->nCol ){
- sqlite3_free(pCur->azVal[i]);
- pCur->azVal[i] = 0;
- pCur->aLen[i] = 0;
- i++;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the CsvCursor
-** is currently pointing.
-*/
-static int csvtabColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- CsvCursor *pCur = (CsvCursor*)cur;
- CsvTable *pTab = (CsvTable*)cur->pVtab;
- if( i>=0 && i<pTab->nCol && pCur->azVal[i]!=0 ){
- sqlite3_result_text(ctx, pCur->azVal[i], -1, SQLITE_STATIC);
- }
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row.
-*/
-static int csvtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- CsvCursor *pCur = (CsvCursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int csvtabEof(sqlite3_vtab_cursor *cur){
- CsvCursor *pCur = (CsvCursor*)cur;
- return pCur->iRowid<0;
-}
-
-/*
-** Only a full table scan is supported. So xFilter simply rewinds to
-** the beginning.
-*/
-static int csvtabFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- CsvCursor *pCur = (CsvCursor*)pVtabCursor;
- CsvTable *pTab = (CsvTable*)pVtabCursor->pVtab;
- pCur->iRowid = 0;
- if( pCur->rdr.in==0 ){
- assert( pCur->rdr.zIn==pTab->zData );
- assert( pTab->iStart>=0 );
- assert( (size_t)pTab->iStart<=pCur->rdr.nIn );
- pCur->rdr.iIn = pTab->iStart;
- }else{
- fseek(pCur->rdr.in, pTab->iStart, SEEK_SET);
- pCur->rdr.iIn = 0;
- pCur->rdr.nIn = 0;
- }
- return csvtabNext(pVtabCursor);
-}
-
-/*
-** Only a forward full table scan is supported. xBestIndex is mostly
-** a no-op. If CSVTEST_FIDX is set, then the presence of equality
-** constraints lowers the estimated cost, which is fiction, but is useful
-** for testing certain kinds of virtual table behavior.
-*/
-static int csvtabBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- pIdxInfo->estimatedCost = 1000000;
-#ifdef SQLITE_TEST
- if( (((CsvTable*)tab)->tstFlags & CSVTEST_FIDX)!=0 ){
- /* The usual (and sensible) case is to always do a full table scan.
- ** The code in this branch only runs when testflags=1. This code
- ** generates an artifical and unrealistic plan which is useful
- ** for testing virtual table logic but is not helpful to real applications.
- **
- ** Any ==, LIKE, or GLOB constraint is marked as usable by the virtual
- ** table (even though it is not) and the cost of running the virtual table
- ** is reduced from 1 million to just 10. The constraints are *not* marked
- ** as omittable, however, so the query planner should still generate a
- ** plan that gives a correct answer, even if they plan is not optimal.
- */
- int i;
- int nConst = 0;
- for(i=0; i<pIdxInfo->nConstraint; i++){
- unsigned char op;
- if( pIdxInfo->aConstraint[i].usable==0 ) continue;
- op = pIdxInfo->aConstraint[i].op;
- if( op==SQLITE_INDEX_CONSTRAINT_EQ
- || op==SQLITE_INDEX_CONSTRAINT_LIKE
- || op==SQLITE_INDEX_CONSTRAINT_GLOB
- ){
- pIdxInfo->estimatedCost = 10;
- pIdxInfo->aConstraintUsage[nConst].argvIndex = nConst+1;
- nConst++;
- }
- }
- }
-#endif
- return SQLITE_OK;
-}
-
-
-static sqlite3_module CsvModule = {
- 0, /* iVersion */
- csvtabCreate, /* xCreate */
- csvtabConnect, /* xConnect */
- csvtabBestIndex, /* xBestIndex */
- csvtabDisconnect, /* xDisconnect */
- csvtabDisconnect, /* xDestroy */
- csvtabOpen, /* xOpen - open a cursor */
- csvtabClose, /* xClose - close a cursor */
- csvtabFilter, /* xFilter - configure scan constraints */
- csvtabNext, /* xNext - advance a cursor */
- csvtabEof, /* xEof - check for end of scan */
- csvtabColumn, /* xColumn - read data */
- csvtabRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-#ifdef SQLITE_TEST
-/*
-** For virtual table testing, make a version of the CSV virtual table
-** available that has an xUpdate function. But the xUpdate always returns
-** SQLITE_READONLY since the CSV file is not really writable.
-*/
-static int csvtabUpdate(sqlite3_vtab *p,int n,sqlite3_value**v,sqlite3_int64*x){
- return SQLITE_READONLY;
-}
-static sqlite3_module CsvModuleFauxWrite = {
- 0, /* iVersion */
- csvtabCreate, /* xCreate */
- csvtabConnect, /* xConnect */
- csvtabBestIndex, /* xBestIndex */
- csvtabDisconnect, /* xDisconnect */
- csvtabDisconnect, /* xDestroy */
- csvtabOpen, /* xOpen - open a cursor */
- csvtabClose, /* xClose - close a cursor */
- csvtabFilter, /* xFilter - configure scan constraints */
- csvtabNext, /* xNext - advance a cursor */
- csvtabEof, /* xEof - check for end of scan */
- csvtabColumn, /* xColumn - read data */
- csvtabRowid, /* xRowid - read data */
- csvtabUpdate, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-#endif /* SQLITE_TEST */
-
-#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-/*
-** This routine is called when the extension is loaded. The new
-** CSV virtual table module is registered with the calling database
-** connection.
-*/
-int sqlite3_csv_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- int rc;
- SQLITE_EXTENSION_INIT2(pApi);
- rc = sqlite3_create_module(db, "csv", &CsvModule, 0);
-#ifdef SQLITE_TEST
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_module(db, "csv_wr", &CsvModuleFauxWrite, 0);
- }
-#endif
- return rc;
-#else
- return SQLITE_OK;
-#endif
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/dbdump.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/dbdump.c
deleted file mode 100644
index 2ca34a1128f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/dbdump.c
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
-** 2016-03-13
-**
-** 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 a C-language subroutine that converts the content
-** of an SQLite database into UTF-8 text SQL statements that can be used
-** to exactly recreate the original database. ROWID values are preserved.
-**
-** A prototype of the implemented subroutine is this:
-**
-** int sqlite3_db_dump(
-** sqlite3 *db,
-** const char *zSchema,
-** const char *zTable,
-** void (*xCallback)(void*, const char*),
-** void *pArg
-** );
-**
-** The db parameter is the database connection. zSchema is the schema within
-** that database which is to be dumped. Usually the zSchema is "main" but
-** can also be "temp" or any ATTACH-ed database. If zTable is not NULL, then
-** only the content of that one table is dumped. If zTable is NULL, then all
-** tables are dumped.
-**
-** The generate text is passed to xCallback() in multiple calls. The second
-** argument to xCallback() is a copy of the pArg parameter. The first
-** argument is some of the output text that this routine generates. The
-** signature to xCallback() is designed to make it compatible with fputs().
-**
-** The sqlite3_db_dump() subroutine returns SQLITE_OK on success or some error
-** code if it encounters a problem.
-**
-** If this file is compiled with -DDBDUMP_STANDALONE then a "main()" routine
-** is included so that this routine becomes a command-line utility. The
-** command-line utility takes two or three arguments which are the name
-** of the database file, the schema, and optionally the table, forming the
-** first three arguments of a single call to the library routine.
-*/
-#include "sqlite3.h"
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-
-/*
-** The state of the dump process.
-*/
-typedef struct DState DState;
-struct DState {
- sqlite3 *db; /* The database connection */
- int nErr; /* Number of errors seen so far */
- int rc; /* Error code */
- int writableSchema; /* True if in writable_schema mode */
- int (*xCallback)(const char*,void*); /* Send output here */
- void *pArg; /* Argument to xCallback() */
-};
-
-/*
-** A variable length string to which one can append text.
-*/
-typedef struct DText DText;
-struct DText {
- char *z; /* The text */
- int n; /* Number of bytes of content in z[] */
- int nAlloc; /* Number of bytes allocated to z[] */
-};
-
-/*
-** Initialize and destroy a DText object
-*/
-static void initText(DText *p){
- memset(p, 0, sizeof(*p));
-}
-static void freeText(DText *p){
- sqlite3_free(p->z);
- initText(p);
-}
-
-/* zIn is either a pointer to a NULL-terminated string in memory obtained
-** from malloc(), or a NULL pointer. The string pointed to by zAppend is
-** added to zIn, and the result returned in memory obtained from malloc().
-** zIn, if it was not NULL, is freed.
-**
-** If the third argument, quote, is not '\0', then it is used as a
-** quote character for zAppend.
-*/
-static void appendText(DText *p, char const *zAppend, char quote){
- int len;
- int i;
- int nAppend = (int)(strlen(zAppend) & 0x3fffffff);
-
- len = nAppend+p->n+1;
- if( quote ){
- len += 2;
- for(i=0; i<nAppend; i++){
- if( zAppend[i]==quote ) len++;
- }
- }
-
- if( p->n+len>=p->nAlloc ){
- char *zNew;
- p->nAlloc = p->nAlloc*2 + len + 20;
- zNew = sqlite3_realloc(p->z, p->nAlloc);
- if( zNew==0 ){
- freeText(p);
- return;
- }
- p->z = zNew;
- }
-
- if( quote ){
- char *zCsr = p->z+p->n;
- *zCsr++ = quote;
- for(i=0; i<nAppend; i++){
- *zCsr++ = zAppend[i];
- if( zAppend[i]==quote ) *zCsr++ = quote;
- }
- *zCsr++ = quote;
- p->n = (int)(zCsr - p->z);
- *zCsr = '\0';
- }else{
- memcpy(p->z+p->n, zAppend, nAppend);
- p->n += nAppend;
- p->z[p->n] = '\0';
- }
-}
-
-/*
-** Attempt to determine if identifier zName needs to be quoted, either
-** because it contains non-alphanumeric characters, or because it is an
-** SQLite keyword. Be conservative in this estimate: When in doubt assume
-** that quoting is required.
-**
-** Return '"' if quoting is required. Return 0 if no quoting is required.
-*/
-static char quoteChar(const char *zName){
- int i;
- if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
- for(i=0; zName[i]; i++){
- if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
- }
- return sqlite3_keyword_check(zName, i) ? '"' : 0;
-}
-
-
-/*
-** Release memory previously allocated by tableColumnList().
-*/
-static void freeColumnList(char **azCol){
- int i;
- for(i=1; azCol[i]; i++){
- sqlite3_free(azCol[i]);
- }
- /* azCol[0] is a static string */
- sqlite3_free(azCol);
-}
-
-/*
-** Return a list of pointers to strings which are the names of all
-** columns in table zTab. The memory to hold the names is dynamically
-** allocated and must be released by the caller using a subsequent call
-** to freeColumnList().
-**
-** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
-** value that needs to be preserved, then azCol[0] is filled in with the
-** name of the rowid column.
-**
-** The first regular column in the table is azCol[1]. The list is terminated
-** by an entry with azCol[i]==0.
-*/
-static char **tableColumnList(DState *p, const char *zTab){
- char **azCol = 0;
- sqlite3_stmt *pStmt = 0;
- char *zSql;
- int nCol = 0;
- int nAlloc = 0;
- int nPK = 0; /* Number of PRIMARY KEY columns seen */
- int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
- int preserveRowid = 1;
- int rc;
-
- zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
- if( zSql==0 ) return 0;
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ) return 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- if( nCol>=nAlloc-2 ){
- char **azNew;
- nAlloc = nAlloc*2 + nCol + 10;
- azNew = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
- if( azNew==0 ) goto col_oom;
- azCol = azNew;
- azCol[0] = 0;
- }
- azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
- if( azCol[nCol]==0 ) goto col_oom;
- if( sqlite3_column_int(pStmt, 5) ){
- nPK++;
- if( nPK==1
- && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
- "INTEGER")==0
- ){
- isIPK = 1;
- }else{
- isIPK = 0;
- }
- }
- }
- sqlite3_finalize(pStmt);
- pStmt = 0;
- azCol[nCol+1] = 0;
-
- /* The decision of whether or not a rowid really needs to be preserved
- ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
- ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
- ** rowids on tables where the rowid is inaccessible because there are other
- ** columns in the table named "rowid", "_rowid_", and "oid".
- */
- if( isIPK ){
- /* If a single PRIMARY KEY column with type INTEGER was seen, then it
- ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
- ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
- ** ROWID aliases. To distinguish these cases, check to see if
- ** there is a "pk" entry in "PRAGMA index_list". There will be
- ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
- */
- zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
- " WHERE origin='pk'", zTab);
- if( zSql==0 ) goto col_oom;
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ){
- freeColumnList(azCol);
- return 0;
- }
- rc = sqlite3_step(pStmt);
- sqlite3_finalize(pStmt);
- pStmt = 0;
- preserveRowid = rc==SQLITE_ROW;
- }
- if( preserveRowid ){
- /* Only preserve the rowid if we can find a name to use for the
- ** rowid */
- static char *azRowid[] = { "rowid", "_rowid_", "oid" };
- int i, j;
- for(j=0; j<3; j++){
- for(i=1; i<=nCol; i++){
- if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
- }
- if( i>nCol ){
- /* At this point, we know that azRowid[j] is not the name of any
- ** ordinary column in the table. Verify that azRowid[j] is a valid
- ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
- ** tables will fail this last check */
- rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
- if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
- break;
- }
- }
- }
- return azCol;
-
-col_oom:
- sqlite3_finalize(pStmt);
- freeColumnList(azCol);
- p->nErr++;
- p->rc = SQLITE_NOMEM;
- return 0;
-}
-
-/*
-** Send mprintf-formatted content to the output callback.
-*/
-static void output_formatted(DState *p, const char *zFormat, ...){
- va_list ap;
- char *z;
- va_start(ap, zFormat);
- z = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- p->xCallback(z, p->pArg);
- sqlite3_free(z);
-}
-
-/*
-** Find a string that is not found anywhere in z[]. Return a pointer
-** to that string.
-**
-** Try to use zA and zB first. If both of those are already found in z[]
-** then make up some string and store it in the buffer zBuf.
-*/
-static const char *unused_string(
- const char *z, /* Result must not appear anywhere in z */
- const char *zA, const char *zB, /* Try these first */
- char *zBuf /* Space to store a generated string */
-){
- unsigned i = 0;
- if( strstr(z, zA)==0 ) return zA;
- if( strstr(z, zB)==0 ) return zB;
- do{
- sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
- }while( strstr(z,zBuf)!=0 );
- return zBuf;
-}
-
-/*
-** Output the given string as a quoted string using SQL quoting conventions.
-** Additionallly , escape the "\n" and "\r" characters so that they do not
-** get corrupted by end-of-line translation facilities in some operating
-** systems.
-*/
-static void output_quoted_escaped_string(DState *p, const char *z){
- int i;
- char c;
- for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
- if( c==0 ){
- output_formatted(p,"'%s'",z);
- }else{
- const char *zNL = 0;
- const char *zCR = 0;
- int nNL = 0;
- int nCR = 0;
- char zBuf1[20], zBuf2[20];
- for(i=0; z[i]; i++){
- if( z[i]=='\n' ) nNL++;
- if( z[i]=='\r' ) nCR++;
- }
- if( nNL ){
- p->xCallback("replace(", p->pArg);
- zNL = unused_string(z, "\\n", "\\012", zBuf1);
- }
- if( nCR ){
- p->xCallback("replace(", p->pArg);
- zCR = unused_string(z, "\\r", "\\015", zBuf2);
- }
- p->xCallback("'", p->pArg);
- while( *z ){
- for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
- if( c=='\'' ) i++;
- if( i ){
- output_formatted(p, "%.*s", i, z);
- z += i;
- }
- if( c=='\'' ){
- p->xCallback("'", p->pArg);
- continue;
- }
- if( c==0 ){
- break;
- }
- z++;
- if( c=='\n' ){
- p->xCallback(zNL, p->pArg);
- continue;
- }
- p->xCallback(zCR, p->pArg);
- }
- p->xCallback("'", p->pArg);
- if( nCR ){
- output_formatted(p, ",'%s',char(13))", zCR);
- }
- if( nNL ){
- output_formatted(p, ",'%s',char(10))", zNL);
- }
- }
-}
-
-/*
-** This is an sqlite3_exec callback routine used for dumping the database.
-** Each row received by this callback consists of a table name,
-** the table type ("index" or "table") and SQL to create the table.
-** This routine should print text sufficient to recreate the table.
-*/
-static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
- int rc;
- const char *zTable;
- const char *zType;
- const char *zSql;
- DState *p = (DState*)pArg;
- sqlite3_stmt *pStmt;
-
- (void)azCol;
- if( nArg!=3 ) return 1;
- zTable = azArg[0];
- zType = azArg[1];
- zSql = azArg[2];
-
- if( strcmp(zTable, "sqlite_sequence")==0 ){
- p->xCallback("DELETE FROM sqlite_sequence;\n", p->pArg);
- }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
- p->xCallback("ANALYZE sqlite_master;\n", p->pArg);
- }else if( strncmp(zTable, "sqlite_", 7)==0 ){
- return 0;
- }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
- if( !p->writableSchema ){
- p->xCallback("PRAGMA writable_schema=ON;\n", p->pArg);
- p->writableSchema = 1;
- }
- output_formatted(p,
- "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
- "VALUES('table','%q','%q',0,'%q');",
- zTable, zTable, zSql);
- return 0;
- }else{
- if( sqlite3_strglob("CREATE TABLE ['\"]*", zSql)==0 ){
- p->xCallback("CREATE TABLE IF NOT EXISTS ", p->pArg);
- p->xCallback(zSql+13, p->pArg);
- }else{
- p->xCallback(zSql, p->pArg);
- }
- p->xCallback(";\n", p->pArg);
- }
-
- if( strcmp(zType, "table")==0 ){
- DText sSelect;
- DText sTable;
- char **azTCol;
- int i;
- int nCol;
-
- azTCol = tableColumnList(p, zTable);
- if( azTCol==0 ) return 0;
-
- initText(&sTable);
- appendText(&sTable, "INSERT INTO ", 0);
-
- /* Always quote the table name, even if it appears to be pure ascii,
- ** in case it is a keyword. Ex: INSERT INTO "table" ... */
- appendText(&sTable, zTable, quoteChar(zTable));
-
- /* If preserving the rowid, add a column list after the table name.
- ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
- ** instead of the usual "INSERT INTO tab VALUES(...)".
- */
- if( azTCol[0] ){
- appendText(&sTable, "(", 0);
- appendText(&sTable, azTCol[0], 0);
- for(i=1; azTCol[i]; i++){
- appendText(&sTable, ",", 0);
- appendText(&sTable, azTCol[i], quoteChar(azTCol[i]));
- }
- appendText(&sTable, ")", 0);
- }
- appendText(&sTable, " VALUES(", 0);
-
- /* Build an appropriate SELECT statement */
- initText(&sSelect);
- appendText(&sSelect, "SELECT ", 0);
- if( azTCol[0] ){
- appendText(&sSelect, azTCol[0], 0);
- appendText(&sSelect, ",", 0);
- }
- for(i=1; azTCol[i]; i++){
- appendText(&sSelect, azTCol[i], quoteChar(azTCol[i]));
- if( azTCol[i+1] ){
- appendText(&sSelect, ",", 0);
- }
- }
- nCol = i;
- if( azTCol[0]==0 ) nCol--;
- freeColumnList(azTCol);
- appendText(&sSelect, " FROM ", 0);
- appendText(&sSelect, zTable, quoteChar(zTable));
-
- rc = sqlite3_prepare_v2(p->db, sSelect.z, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- p->nErr++;
- if( p->rc==SQLITE_OK ) p->rc = rc;
- }else{
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- p->xCallback(sTable.z, p->pArg);
- for(i=0; i<nCol; i++){
- if( i ) p->xCallback(",", p->pArg);
- switch( sqlite3_column_type(pStmt,i) ){
- case SQLITE_INTEGER: {
- output_formatted(p, "%lld", sqlite3_column_int64(pStmt,i));
- break;
- }
- case SQLITE_FLOAT: {
- double r = sqlite3_column_double(pStmt,i);
- output_formatted(p, "%!.20g", r);
- break;
- }
- case SQLITE_NULL: {
- p->xCallback("NULL", p->pArg);
- break;
- }
- case SQLITE_TEXT: {
- output_quoted_escaped_string(p,
- (const char*)sqlite3_column_text(pStmt,i));
- break;
- }
- case SQLITE_BLOB: {
- int nByte = sqlite3_column_bytes(pStmt,i);
- unsigned char *a = (unsigned char*)sqlite3_column_blob(pStmt,i);
- int j;
- p->xCallback("x'", p->pArg);
- for(j=0; j<nByte; j++){
- char zWord[3];
- zWord[0] = "0123456789abcdef"[(a[j]>>4)&15];
- zWord[1] = "0123456789abcdef"[a[j]&15];
- zWord[2] = 0;
- p->xCallback(zWord, p->pArg);
- }
- p->xCallback("'", p->pArg);
- break;
- }
- }
- }
- p->xCallback(");\n", p->pArg);
- }
- }
- sqlite3_finalize(pStmt);
- freeText(&sTable);
- freeText(&sSelect);
- }
- return 0;
-}
-
-
-/*
-** Execute a query statement that will generate SQL output. Print
-** the result columns, comma-separated, on a line and then add a
-** semicolon terminator to the end of that line.
-**
-** If the number of columns is 1 and that column contains text "--"
-** then write the semicolon on a separate line. That way, if a
-** "--" comment occurs at the end of the statement, the comment
-** won't consume the semicolon terminator.
-*/
-static void output_sql_from_query(
- DState *p, /* Query context */
- const char *zSelect, /* SELECT statement to extract content */
- ...
-){
- sqlite3_stmt *pSelect;
- int rc;
- int nResult;
- int i;
- const char *z;
- char *zSql;
- va_list ap;
- va_start(ap, zSelect);
- zSql = sqlite3_vmprintf(zSelect, ap);
- va_end(ap);
- if( zSql==0 ){
- p->rc = SQLITE_NOMEM;
- p->nErr++;
- return;
- }
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pSelect, 0);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK || !pSelect ){
- output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
- sqlite3_errmsg(p->db));
- p->nErr++;
- return;
- }
- rc = sqlite3_step(pSelect);
- nResult = sqlite3_column_count(pSelect);
- while( rc==SQLITE_ROW ){
- z = (const char*)sqlite3_column_text(pSelect, 0);
- p->xCallback(z, p->pArg);
- for(i=1; i<nResult; i++){
- p->xCallback(",", p->pArg);
- p->xCallback((const char*)sqlite3_column_text(pSelect,i), p->pArg);
- }
- if( z==0 ) z = "";
- while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
- if( z[0] ){
- p->xCallback("\n;\n", p->pArg);
- }else{
- p->xCallback(";\n", p->pArg);
- }
- rc = sqlite3_step(pSelect);
- }
- rc = sqlite3_finalize(pSelect);
- if( rc!=SQLITE_OK ){
- output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
- sqlite3_errmsg(p->db));
- if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
- }
-}
-
-/*
-** Run zQuery. Use dump_callback() as the callback routine so that
-** the contents of the query are output as SQL statements.
-**
-** If we get a SQLITE_CORRUPT error, rerun the query after appending
-** "ORDER BY rowid DESC" to the end.
-*/
-static void run_schema_dump_query(
- DState *p,
- const char *zQuery,
- ...
-){
- char *zErr = 0;
- char *z;
- va_list ap;
- va_start(ap, zQuery);
- z = sqlite3_vmprintf(zQuery, ap);
- va_end(ap);
- sqlite3_exec(p->db, z, dump_callback, p, &zErr);
- sqlite3_free(z);
- if( zErr ){
- output_formatted(p, "/****** %s ******/\n", zErr);
- sqlite3_free(zErr);
- p->nErr++;
- zErr = 0;
- }
-}
-
-/*
-** Convert an SQLite database into SQL statements that will recreate that
-** database.
-*/
-int sqlite3_db_dump(
- sqlite3 *db, /* The database connection */
- const char *zSchema, /* Which schema to dump. Usually "main". */
- const char *zTable, /* Which table to dump. NULL means everything. */
- int (*xCallback)(const char*,void*), /* Output sent to this callback */
- void *pArg /* Second argument of the callback */
-){
- DState x;
- memset(&x, 0, sizeof(x));
- x.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
- if( x.rc ) return x.rc;
- x.db = db;
- x.xCallback = xCallback;
- x.pArg = pArg;
- xCallback("PRAGMA foreign_keys=OFF;\nBEGIN TRANSACTION;\n", pArg);
- if( zTable==0 ){
- run_schema_dump_query(&x,
- "SELECT name, type, sql FROM \"%w\".sqlite_master "
- "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'",
- zSchema
- );
- run_schema_dump_query(&x,
- "SELECT name, type, sql FROM \"%w\".sqlite_master "
- "WHERE name=='sqlite_sequence'", zSchema
- );
- output_sql_from_query(&x,
- "SELECT sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
- );
- }else{
- run_schema_dump_query(&x,
- "SELECT name, type, sql FROM \"%w\".sqlite_master "
- "WHERE tbl_name=%Q COLLATE nocase AND type=='table'"
- " AND sql NOT NULL",
- zSchema, zTable
- );
- output_sql_from_query(&x,
- "SELECT sql FROM \"%w\".sqlite_master "
- "WHERE sql NOT NULL"
- " AND type IN ('index','trigger','view')"
- " AND tbl_name=%Q COLLATE nocase",
- zSchema, zTable
- );
- }
- if( x.writableSchema ){
- xCallback("PRAGMA writable_schema=OFF;\n", pArg);
- }
- xCallback(x.nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n", pArg);
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
- return x.rc;
-}
-
-
-
-/* The generic subroutine is above. The code the follows implements
-** the command-line interface.
-*/
-#ifdef DBDUMP_STANDALONE
-#include <stdio.h>
-
-/*
-** Command-line interface
-*/
-int main(int argc, char **argv){
- sqlite3 *db;
- const char *zDb;
- const char *zSchema;
- const char *zTable = 0;
- int rc;
-
- if( argc<2 || argc>4 ){
- fprintf(stderr, "Usage: %s DATABASE ?SCHEMA? ?TABLE?\n", argv[0]);
- return 1;
- }
- zDb = argv[1];
- zSchema = argc>=3 ? argv[2] : "main";
- zTable = argc==4 ? argv[3] : 0;
-
- rc = sqlite3_open(zDb, &db);
- if( rc ){
- fprintf(stderr, "Cannot open \"%s\": %s\n", zDb, sqlite3_errmsg(db));
- sqlite3_close(db);
- return 1;
- }
- rc = sqlite3_db_dump(db, zSchema, zTable,
- (int(*)(const char*,void*))fputs, (void*)stdout);
- if( rc ){
- fprintf(stderr, "Error: sqlite3_db_dump() returns %d\n", rc);
- }
- sqlite3_close(db);
- return rc!=SQLITE_OK;
-}
-#endif /* DBDUMP_STANDALONE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/eval.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/eval.c
deleted file mode 100644
index e90bfc01000..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/eval.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-** 2014-11-10
-**
-** 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 SQLite extension implements SQL function eval() which runs
-** SQL statements recursively.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-
-/*
-** Structure used to accumulate the output
-*/
-struct EvalResult {
- char *z; /* Accumulated output */
- const char *zSep; /* Separator */
- int szSep; /* Size of the separator string */
- sqlite3_int64 nAlloc; /* Number of bytes allocated for z[] */
- sqlite3_int64 nUsed; /* Number of bytes of z[] actually used */
-};
-
-/*
-** Callback from sqlite_exec() for the eval() function.
-*/
-static int callback(void *pCtx, int argc, char **argv, char **colnames){
- struct EvalResult *p = (struct EvalResult*)pCtx;
- int i;
- if( argv==0 ) return 0;
- for(i=0; i<argc; i++){
- const char *z = argv[i] ? argv[i] : "";
- size_t sz = strlen(z);
- if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
- char *zNew;
- p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
- /* Using sqlite3_realloc64() would be better, but it is a recent
- ** addition and will cause a segfault if loaded by an older version
- ** of SQLite. */
- zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
- if( zNew==0 ){
- sqlite3_free(p->z);
- memset(p, 0, sizeof(*p));
- return 1;
- }
- p->z = zNew;
- }
- if( p->nUsed>0 ){
- memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
- p->nUsed += p->szSep;
- }
- memcpy(&p->z[p->nUsed], z, sz);
- p->nUsed += sz;
- }
- return 0;
-}
-
-/*
-** Implementation of the eval(X) and eval(X,Y) SQL functions.
-**
-** Evaluate the SQL text in X. Return the results, using string
-** Y as the separator. If Y is omitted, use a single space character.
-*/
-static void sqlEvalFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zSql;
- sqlite3 *db;
- char *zErr = 0;
- int rc;
- struct EvalResult x;
-
- memset(&x, 0, sizeof(x));
- x.zSep = " ";
- zSql = (const char*)sqlite3_value_text(argv[0]);
- if( zSql==0 ) return;
- if( argc>1 ){
- x.zSep = (const char*)sqlite3_value_text(argv[1]);
- if( x.zSep==0 ) return;
- }
- x.szSep = (int)strlen(x.zSep);
- db = sqlite3_context_db_handle(context);
- rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
- if( rc!=SQLITE_OK ){
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- }else if( x.zSep==0 ){
- sqlite3_result_error_nomem(context);
- sqlite3_free(x.z);
- }else{
- sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
- }
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_eval_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0,
- sqlEvalFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0,
- sqlEvalFunc, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/fileio.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/fileio.c
deleted file mode 100644
index b734ca0bab2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/fileio.c
+++ /dev/null
@@ -1,926 +0,0 @@
-/*
-** 2014-06-13
-**
-** 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 SQLite extension implements SQL functions readfile() and
-** writefile(), and eponymous virtual type "fsdir".
-**
-** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
-**
-** If neither of the optional arguments is present, then this UDF
-** function writes blob DATA to file FILE. If successful, the number
-** of bytes written is returned. If an error occurs, NULL is returned.
-**
-** If the first option argument - MODE - is present, then it must
-** be passed an integer value that corresponds to a POSIX mode
-** value (file type + permissions, as returned in the stat.st_mode
-** field by the stat() system call). Three types of files may
-** be written/created:
-**
-** regular files: (mode & 0170000)==0100000
-** symbolic links: (mode & 0170000)==0120000
-** directories: (mode & 0170000)==0040000
-**
-** For a directory, the DATA is ignored. For a symbolic link, it is
-** interpreted as text and used as the target of the link. For a
-** regular file, it is interpreted as a blob and written into the
-** named file. Regardless of the type of file, its permissions are
-** set to (mode & 0777) before returning.
-**
-** If the optional MTIME argument is present, then it is interpreted
-** as an integer - the number of seconds since the unix epoch. The
-** modification-time of the target file is set to this value before
-** returning.
-**
-** If three or more arguments are passed to this function and an
-** error is encountered, an exception is raised.
-**
-** READFILE(FILE):
-**
-** Read and return the contents of file FILE (type blob) from disk.
-**
-** FSDIR:
-**
-** Used as follows:
-**
-** SELECT * FROM fsdir($path [, $dir]);
-**
-** Parameter $path is an absolute or relative pathname. If the file that it
-** refers to does not exist, it is an error. If the path refers to a regular
-** file or symbolic link, it returns a single row. Or, if the path refers
-** to a directory, it returns one row for the directory, and one row for each
-** file within the hierarchy rooted at $path.
-**
-** Each row has the following columns:
-**
-** name: Path to file or directory (text value).
-** mode: Value of stat.st_mode for directory entry (an integer).
-** mtime: Value of stat.st_mtime for directory entry (an integer).
-** data: For a regular file, a blob containing the file data. For a
-** symlink, a text value containing the text of the link. For a
-** directory, NULL.
-**
-** If a non-NULL value is specified for the optional $dir parameter and
-** $path is a relative path, then $path is interpreted relative to $dir.
-** And the paths returned in the "name" column of the table are also
-** relative to directory $dir.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#if !defined(_WIN32) && !defined(WIN32)
-# include <unistd.h>
-# include <dirent.h>
-# include <utime.h>
-# include <sys/time.h>
-#else
-# include "windows.h"
-# include <io.h>
-# include <direct.h>
-# include "test_windirent.h"
-# define dirent DIRENT
-# ifndef chmod
-# define chmod _chmod
-# endif
-# ifndef stat
-# define stat _stat
-# endif
-# define mkdir(path,mode) _mkdir(path)
-# define lstat(path,buf) stat(path,buf)
-#endif
-#include <time.h>
-#include <errno.h>
-
-
-#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
-
-/*
-** Set the result stored by context ctx to a blob containing the
-** contents of file zName.
-*/
-static void readFileContents(sqlite3_context *ctx, const char *zName){
- FILE *in;
- long nIn;
- void *pBuf;
-
- in = fopen(zName, "rb");
- if( in==0 ) return;
- fseek(in, 0, SEEK_END);
- nIn = ftell(in);
- rewind(in);
- pBuf = sqlite3_malloc( nIn );
- if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
- sqlite3_result_blob(ctx, pBuf, nIn, sqlite3_free);
- }else{
- sqlite3_free(pBuf);
- }
- fclose(in);
-}
-
-/*
-** Implementation of the "readfile(X)" SQL function. The entire content
-** of the file named X is read and returned as a BLOB. NULL is returned
-** if the file does not exist or is unreadable.
-*/
-static void readfileFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zName;
- (void)(argc); /* Unused parameter */
- zName = (const char*)sqlite3_value_text(argv[0]);
- if( zName==0 ) return;
- readFileContents(context, zName);
-}
-
-/*
-** Set the error message contained in context ctx to the results of
-** vprintf(zFmt, ...).
-*/
-static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
- char *zMsg = 0;
- va_list ap;
- va_start(ap, zFmt);
- zMsg = sqlite3_vmprintf(zFmt, ap);
- sqlite3_result_error(ctx, zMsg, -1);
- sqlite3_free(zMsg);
- va_end(ap);
-}
-
-#if defined(_WIN32)
-/*
-** This function is designed to convert a Win32 FILETIME structure into the
-** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
-*/
-static sqlite3_uint64 fileTimeToUnixTime(
- LPFILETIME pFileTime
-){
- SYSTEMTIME epochSystemTime;
- ULARGE_INTEGER epochIntervals;
- FILETIME epochFileTime;
- ULARGE_INTEGER fileIntervals;
-
- memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
- epochSystemTime.wYear = 1970;
- epochSystemTime.wMonth = 1;
- epochSystemTime.wDay = 1;
- SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
- epochIntervals.LowPart = epochFileTime.dwLowDateTime;
- epochIntervals.HighPart = epochFileTime.dwHighDateTime;
-
- fileIntervals.LowPart = pFileTime->dwLowDateTime;
- fileIntervals.HighPart = pFileTime->dwHighDateTime;
-
- return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
-}
-
-/*
-** This function attempts to normalize the time values found in the stat()
-** buffer to UTC. This is necessary on Win32, where the runtime library
-** appears to return these values as local times.
-*/
-static void statTimesToUtc(
- const char *zPath,
- struct stat *pStatBuf
-){
- HANDLE hFindFile;
- WIN32_FIND_DATAW fd;
- LPWSTR zUnicodeName;
- extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
- zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
- if( zUnicodeName ){
- memset(&fd, 0, sizeof(WIN32_FIND_DATA));
- hFindFile = FindFirstFileW(zUnicodeName, &fd);
- if( hFindFile!=NULL ){
- pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
- pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
- pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
- FindClose(hFindFile);
- }
- sqlite3_free(zUnicodeName);
- }
-}
-#endif
-
-/*
-** This function is used in place of stat(). On Windows, special handling
-** is required in order for the included time to be returned as UTC. On all
-** other systems, this function simply calls stat().
-*/
-static int fileStat(
- const char *zPath,
- struct stat *pStatBuf
-){
-#if defined(_WIN32)
- int rc = stat(zPath, pStatBuf);
- if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
- return rc;
-#else
- return stat(zPath, pStatBuf);
-#endif
-}
-
-/*
-** This function is used in place of lstat(). On Windows, special handling
-** is required in order for the included time to be returned as UTC. On all
-** other systems, this function simply calls lstat().
-*/
-static int fileLinkStat(
- const char *zPath,
- struct stat *pStatBuf
-){
-#if defined(_WIN32)
- int rc = lstat(zPath, pStatBuf);
- if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
- return rc;
-#else
- return lstat(zPath, pStatBuf);
-#endif
-}
-
-/*
-** Argument zFile is the name of a file that will be created and/or written
-** by SQL function writefile(). This function ensures that the directory
-** zFile will be written to exists, creating it if required. The permissions
-** for any path components created by this function are set to (mode&0777).
-**
-** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
-** SQLITE_OK is returned if the directory is successfully created, or
-** SQLITE_ERROR otherwise.
-*/
-static int makeDirectory(
- const char *zFile,
- mode_t mode
-){
- char *zCopy = sqlite3_mprintf("%s", zFile);
- int rc = SQLITE_OK;
-
- if( zCopy==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int nCopy = (int)strlen(zCopy);
- int i = 1;
-
- while( rc==SQLITE_OK ){
- struct stat sStat;
- int rc2;
-
- for(; zCopy[i]!='/' && i<nCopy; i++);
- if( i==nCopy ) break;
- zCopy[i] = '\0';
-
- rc2 = fileStat(zCopy, &sStat);
- if( rc2!=0 ){
- if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR;
- }else{
- if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
- }
- zCopy[i] = '/';
- i++;
- }
-
- sqlite3_free(zCopy);
- }
-
- return rc;
-}
-
-/*
-** This function does the work for the writefile() UDF. Refer to
-** header comments at the top of this file for details.
-*/
-static int writeFile(
- sqlite3_context *pCtx, /* Context to return bytes written in */
- const char *zFile, /* File to write */
- sqlite3_value *pData, /* Data to write */
- mode_t mode, /* MODE parameter passed to writefile() */
- sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
-){
-#if !defined(_WIN32) && !defined(WIN32)
- if( S_ISLNK(mode) ){
- const char *zTo = (const char*)sqlite3_value_text(pData);
- if( symlink(zTo, zFile)<0 ) return 1;
- }else
-#endif
- {
- if( S_ISDIR(mode) ){
- if( mkdir(zFile, mode) ){
- /* The mkdir() call to create the directory failed. This might not
- ** be an error though - if there is already a directory at the same
- ** path and either the permissions already match or can be changed
- ** to do so using chmod(), it is not an error. */
- struct stat sStat;
- if( errno!=EEXIST
- || 0!=fileStat(zFile, &sStat)
- || !S_ISDIR(sStat.st_mode)
- || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
- ){
- return 1;
- }
- }
- }else{
- sqlite3_int64 nWrite = 0;
- const char *z;
- int rc = 0;
- FILE *out = fopen(zFile, "wb");
- if( out==0 ) return 1;
- z = (const char*)sqlite3_value_blob(pData);
- if( z ){
- sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
- nWrite = sqlite3_value_bytes(pData);
- if( nWrite!=n ){
- rc = 1;
- }
- }
- fclose(out);
- if( rc==0 && mode && chmod(zFile, mode & 0777) ){
- rc = 1;
- }
- if( rc ) return 2;
- sqlite3_result_int64(pCtx, nWrite);
- }
- }
-
- if( mtime>=0 ){
-#if defined(_WIN32)
- /* Windows */
- FILETIME lastAccess;
- FILETIME lastWrite;
- SYSTEMTIME currentTime;
- LONGLONG intervals;
- HANDLE hFile;
- LPWSTR zUnicodeName;
- extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
-
- GetSystemTime(&currentTime);
- SystemTimeToFileTime(&currentTime, &lastAccess);
- intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
- lastWrite.dwLowDateTime = (DWORD)intervals;
- lastWrite.dwHighDateTime = intervals >> 32;
- zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
- if( zUnicodeName==0 ){
- return 1;
- }
- hFile = CreateFileW(
- zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL
- );
- sqlite3_free(zUnicodeName);
- if( hFile!=INVALID_HANDLE_VALUE ){
- BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
- CloseHandle(hFile);
- return !bResult;
- }else{
- return 1;
- }
-#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
- /* Recent unix */
- struct timespec times[2];
- times[0].tv_nsec = times[1].tv_nsec = 0;
- times[0].tv_sec = time(0);
- times[1].tv_sec = mtime;
- if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
- return 1;
- }
-#else
- /* Legacy unix */
- struct timeval times[2];
- times[0].tv_usec = times[1].tv_usec = 0;
- times[0].tv_sec = time(0);
- times[1].tv_sec = mtime;
- if( utimes(zFile, times) ){
- return 1;
- }
-#endif
- }
-
- return 0;
-}
-
-/*
-** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
-** Refer to header comments at the top of this file for details.
-*/
-static void writefileFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zFile;
- mode_t mode = 0;
- int res;
- sqlite3_int64 mtime = -1;
-
- if( argc<2 || argc>4 ){
- sqlite3_result_error(context,
- "wrong number of arguments to function writefile()", -1
- );
- return;
- }
-
- zFile = (const char*)sqlite3_value_text(argv[0]);
- if( zFile==0 ) return;
- if( argc>=3 ){
- mode = (mode_t)sqlite3_value_int(argv[2]);
- }
- if( argc==4 ){
- mtime = sqlite3_value_int64(argv[3]);
- }
-
- res = writeFile(context, zFile, argv[1], mode, mtime);
- if( res==1 && errno==ENOENT ){
- if( makeDirectory(zFile, mode)==SQLITE_OK ){
- res = writeFile(context, zFile, argv[1], mode, mtime);
- }
- }
-
- if( argc>2 && res!=0 ){
- if( S_ISLNK(mode) ){
- ctxErrorMsg(context, "failed to create symlink: %s", zFile);
- }else if( S_ISDIR(mode) ){
- ctxErrorMsg(context, "failed to create directory: %s", zFile);
- }else{
- ctxErrorMsg(context, "failed to write file: %s", zFile);
- }
- }
-}
-
-/*
-** SQL function: lsmode(MODE)
-**
-** Given a numberic st_mode from stat(), convert it into a human-readable
-** text string in the style of "ls -l".
-*/
-static void lsModeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int i;
- int iMode = sqlite3_value_int(argv[0]);
- char z[16];
- (void)argc;
- if( S_ISLNK(iMode) ){
- z[0] = 'l';
- }else if( S_ISREG(iMode) ){
- z[0] = '-';
- }else if( S_ISDIR(iMode) ){
- z[0] = 'd';
- }else{
- z[0] = '?';
- }
- for(i=0; i<3; i++){
- int m = (iMode >> ((2-i)*3));
- char *a = &z[1 + i*3];
- a[0] = (m & 0x4) ? 'r' : '-';
- a[1] = (m & 0x2) ? 'w' : '-';
- a[2] = (m & 0x1) ? 'x' : '-';
- }
- z[10] = '\0';
- sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
-}
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Cursor type for recursively iterating through a directory structure.
-*/
-typedef struct fsdir_cursor fsdir_cursor;
-typedef struct FsdirLevel FsdirLevel;
-
-struct FsdirLevel {
- DIR *pDir; /* From opendir() */
- char *zDir; /* Name of directory (nul-terminated) */
-};
-
-struct fsdir_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
-
- int nLvl; /* Number of entries in aLvl[] array */
- int iLvl; /* Index of current entry */
- FsdirLevel *aLvl; /* Hierarchy of directories being traversed */
-
- const char *zBase;
- int nBase;
-
- struct stat sStat; /* Current lstat() results */
- char *zPath; /* Path to current entry */
- sqlite3_int64 iRowid; /* Current rowid */
-};
-
-typedef struct fsdir_tab fsdir_tab;
-struct fsdir_tab {
- sqlite3_vtab base; /* Base class - must be first */
-};
-
-/*
-** Construct a new fsdir virtual table object.
-*/
-static int fsdirConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- fsdir_tab *pNew = 0;
- int rc;
- (void)pAux;
- (void)argc;
- (void)argv;
- (void)pzErr;
- rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
- if( rc==SQLITE_OK ){
- pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- }
- *ppVtab = (sqlite3_vtab*)pNew;
- return rc;
-}
-
-/*
-** This method is the destructor for fsdir vtab objects.
-*/
-static int fsdirDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new fsdir_cursor object.
-*/
-static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- fsdir_cursor *pCur;
- (void)p;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->iLvl = -1;
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Reset a cursor back to the state it was in when first returned
-** by fsdirOpen().
-*/
-static void fsdirResetCursor(fsdir_cursor *pCur){
- int i;
- for(i=0; i<=pCur->iLvl; i++){
- FsdirLevel *pLvl = &pCur->aLvl[i];
- if( pLvl->pDir ) closedir(pLvl->pDir);
- sqlite3_free(pLvl->zDir);
- }
- sqlite3_free(pCur->zPath);
- sqlite3_free(pCur->aLvl);
- pCur->aLvl = 0;
- pCur->zPath = 0;
- pCur->zBase = 0;
- pCur->nBase = 0;
- pCur->nLvl = 0;
- pCur->iLvl = -1;
- pCur->iRowid = 1;
-}
-
-/*
-** Destructor for an fsdir_cursor.
-*/
-static int fsdirClose(sqlite3_vtab_cursor *cur){
- fsdir_cursor *pCur = (fsdir_cursor*)cur;
-
- fsdirResetCursor(pCur);
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Set the error message for the virtual table associated with cursor
-** pCur to the results of vprintf(zFmt, ...).
-*/
-static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
- va_list ap;
- va_start(ap, zFmt);
- pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
-}
-
-
-/*
-** Advance an fsdir_cursor to its next row of output.
-*/
-static int fsdirNext(sqlite3_vtab_cursor *cur){
- fsdir_cursor *pCur = (fsdir_cursor*)cur;
- mode_t m = pCur->sStat.st_mode;
-
- pCur->iRowid++;
- if( S_ISDIR(m) ){
- /* Descend into this directory */
- int iNew = pCur->iLvl + 1;
- FsdirLevel *pLvl;
- if( iNew>=pCur->nLvl ){
- int nNew = iNew+1;
- int nByte = nNew*sizeof(FsdirLevel);
- FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc(pCur->aLvl, nByte);
- if( aNew==0 ) return SQLITE_NOMEM;
- memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
- pCur->aLvl = aNew;
- pCur->nLvl = nNew;
- }
- pCur->iLvl = iNew;
- pLvl = &pCur->aLvl[iNew];
-
- pLvl->zDir = pCur->zPath;
- pCur->zPath = 0;
- pLvl->pDir = opendir(pLvl->zDir);
- if( pLvl->pDir==0 ){
- fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
- return SQLITE_ERROR;
- }
- }
-
- while( pCur->iLvl>=0 ){
- FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
- struct dirent *pEntry = readdir(pLvl->pDir);
- if( pEntry ){
- if( pEntry->d_name[0]=='.' ){
- if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
- if( pEntry->d_name[1]=='\0' ) continue;
- }
- sqlite3_free(pCur->zPath);
- pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
- if( pCur->zPath==0 ) return SQLITE_NOMEM;
- if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
- fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
- }
- closedir(pLvl->pDir);
- sqlite3_free(pLvl->zDir);
- pLvl->pDir = 0;
- pLvl->zDir = 0;
- pCur->iLvl--;
- }
-
- /* EOF */
- sqlite3_free(pCur->zPath);
- pCur->zPath = 0;
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the series_cursor
-** is currently pointing.
-*/
-static int fsdirColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- fsdir_cursor *pCur = (fsdir_cursor*)cur;
- switch( i ){
- case 0: { /* name */
- sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
- break;
- }
-
- case 1: /* mode */
- sqlite3_result_int64(ctx, pCur->sStat.st_mode);
- break;
-
- case 2: /* mtime */
- sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
- break;
-
- case 3: { /* data */
- mode_t m = pCur->sStat.st_mode;
- if( S_ISDIR(m) ){
- sqlite3_result_null(ctx);
-#if !defined(_WIN32) && !defined(WIN32)
- }else if( S_ISLNK(m) ){
- char aStatic[64];
- char *aBuf = aStatic;
- int nBuf = 64;
- int n;
-
- while( 1 ){
- n = readlink(pCur->zPath, aBuf, nBuf);
- if( n<nBuf ) break;
- if( aBuf!=aStatic ) sqlite3_free(aBuf);
- nBuf = nBuf*2;
- aBuf = sqlite3_malloc(nBuf);
- if( aBuf==0 ){
- sqlite3_result_error_nomem(ctx);
- return SQLITE_NOMEM;
- }
- }
-
- sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
- if( aBuf!=aStatic ) sqlite3_free(aBuf);
-#endif
- }else{
- readFileContents(ctx, pCur->zPath);
- }
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** first row returned is assigned rowid value 1, and each subsequent
-** row a value 1 more than that of the previous.
-*/
-static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- fsdir_cursor *pCur = (fsdir_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int fsdirEof(sqlite3_vtab_cursor *cur){
- fsdir_cursor *pCur = (fsdir_cursor*)cur;
- return (pCur->zPath==0);
-}
-
-/*
-** xFilter callback.
-*/
-static int fsdirFilter(
- sqlite3_vtab_cursor *cur,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- const char *zDir = 0;
- fsdir_cursor *pCur = (fsdir_cursor*)cur;
- (void)idxStr;
- fsdirResetCursor(pCur);
-
- if( idxNum==0 ){
- fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
- return SQLITE_ERROR;
- }
-
- assert( argc==idxNum && (argc==1 || argc==2) );
- zDir = (const char*)sqlite3_value_text(argv[0]);
- if( zDir==0 ){
- fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
- return SQLITE_ERROR;
- }
- if( argc==2 ){
- pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
- }
- if( pCur->zBase ){
- pCur->nBase = (int)strlen(pCur->zBase)+1;
- pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
- }else{
- pCur->zPath = sqlite3_mprintf("%s", zDir);
- }
-
- if( pCur->zPath==0 ){
- return SQLITE_NOMEM;
- }
- if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
- fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
- return SQLITE_ERROR;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the generate_series virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** In this implementation idxNum is used to represent the
-** query plan. idxStr is unused.
-**
-** The query plan is represented by bits in idxNum:
-**
-** (1) start = $value -- constraint exists
-** (2) stop = $value -- constraint exists
-** (4) step = $value -- constraint exists
-** (8) output in descending order
-*/
-static int fsdirBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i; /* Loop over constraints */
- int idx4 = -1;
- int idx5 = -1;
- const struct sqlite3_index_constraint *pConstraint;
-
- (void)tab;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- if( pConstraint->iColumn==4 ) idx4 = i;
- if( pConstraint->iColumn==5 ) idx5 = i;
- }
-
- if( idx4<0 ){
- pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
- }else{
- pIdxInfo->aConstraintUsage[idx4].omit = 1;
- pIdxInfo->aConstraintUsage[idx4].argvIndex = 1;
- if( idx5>=0 ){
- pIdxInfo->aConstraintUsage[idx5].omit = 1;
- pIdxInfo->aConstraintUsage[idx5].argvIndex = 2;
- pIdxInfo->idxNum = 2;
- pIdxInfo->estimatedCost = 10.0;
- }else{
- pIdxInfo->idxNum = 1;
- pIdxInfo->estimatedCost = 100.0;
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Register the "fsdir" virtual table.
-*/
-static int fsdirRegister(sqlite3 *db){
- static sqlite3_module fsdirModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- fsdirConnect, /* xConnect */
- fsdirBestIndex, /* xBestIndex */
- fsdirDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- fsdirOpen, /* xOpen - open a cursor */
- fsdirClose, /* xClose - close a cursor */
- fsdirFilter, /* xFilter - configure scan constraints */
- fsdirNext, /* xNext - advance a cursor */
- fsdirEof, /* xEof - check for end of scan */
- fsdirColumn, /* xColumn - read data */
- fsdirRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
- };
-
- int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
- return rc;
-}
-#else /* SQLITE_OMIT_VIRTUALTABLE */
-# define fsdirRegister(x) SQLITE_OK
-#endif
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fileio_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
- readfileFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
- writefileFunc, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
- lsModeFunc, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = fsdirRegister(db);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/fuzzer.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/fuzzer.c
deleted file mode 100644
index 77db56d47a4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/fuzzer.c
+++ /dev/null
@@ -1,1185 +0,0 @@
-/*
-** 2011 March 24
-**
-** 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.
-**
-*************************************************************************
-**
-** Code for a demonstration virtual table that generates variations
-** on an input word at increasing edit distances from the original.
-**
-** A fuzzer virtual table is created like this:
-**
-** CREATE VIRTUAL TABLE f USING fuzzer(<fuzzer-data-table>);
-**
-** When it is created, the new fuzzer table must be supplied with the
-** name of a "fuzzer data table", which must reside in the same database
-** file as the new fuzzer table. The fuzzer data table contains the various
-** transformations and their costs that the fuzzer logic uses to generate
-** variations.
-**
-** The fuzzer data table must contain exactly four columns (more precisely,
-** the statement "SELECT * FROM <fuzzer_data_table>" must return records
-** that consist of four columns). It does not matter what the columns are
-** named.
-**
-** Each row in the fuzzer data table represents a single character
-** transformation. The left most column of the row (column 0) contains an
-** integer value - the identifier of the ruleset to which the transformation
-** rule belongs (see "MULTIPLE RULE SETS" below). The second column of the
-** row (column 0) contains the input character or characters. The third
-** column contains the output character or characters. And the fourth column
-** contains the integer cost of making the transformation. For example:
-**
-** CREATE TABLE f_data(ruleset, cFrom, cTo, Cost);
-** INSERT INTO f_data(ruleset, cFrom, cTo, Cost) VALUES(0, '', 'a', 100);
-** INSERT INTO f_data(ruleset, cFrom, cTo, Cost) VALUES(0, 'b', '', 87);
-** INSERT INTO f_data(ruleset, cFrom, cTo, Cost) VALUES(0, 'o', 'oe', 38);
-** INSERT INTO f_data(ruleset, cFrom, cTo, Cost) VALUES(0, 'oe', 'o', 40);
-**
-** The first row inserted into the fuzzer data table by the SQL script
-** above indicates that the cost of inserting a letter 'a' is 100. (All
-** costs are integers. We recommend that costs be scaled so that the
-** average cost is around 100.) The second INSERT statement creates a rule
-** saying that the cost of deleting a single letter 'b' is 87. The third
-** and fourth INSERT statements mean that the cost of transforming a
-** single letter "o" into the two-letter sequence "oe" is 38 and that the
-** cost of transforming "oe" back into "o" is 40.
-**
-** The contents of the fuzzer data table are loaded into main memory when
-** a fuzzer table is first created, and may be internally reloaded by the
-** system at any subsequent time. Therefore, the fuzzer data table should be
-** populated before the fuzzer table is created and not modified thereafter.
-** If you do need to modify the contents of the fuzzer data table, it is
-** recommended that the associated fuzzer table be dropped, the fuzzer data
-** table edited, and the fuzzer table recreated within a single transaction.
-** Alternatively, the fuzzer data table can be edited then the database
-** connection can be closed and reopened.
-**
-** Once it has been created, the fuzzer table can be queried as follows:
-**
-** SELECT word, distance FROM f
-** WHERE word MATCH 'abcdefg'
-** AND distance<200;
-**
-** This first query outputs the string "abcdefg" and all strings that
-** can be derived from that string by appling the specified transformations.
-** The strings are output together with their total transformation cost
-** (called "distance") and appear in order of increasing cost. No string
-** is output more than once. If there are multiple ways to transform the
-** target string into the output string then the lowest cost transform is
-** the one that is returned. In the example, the search is limited to
-** strings with a total distance of less than 200.
-**
-** The fuzzer is a read-only table. Any attempt to DELETE, INSERT, or
-** UPDATE on a fuzzer table will throw an error.
-**
-** It is important to put some kind of a limit on the fuzzer output. This
-** can be either in the form of a LIMIT clause at the end of the query,
-** or better, a "distance<NNN" constraint where NNN is some number. The
-** running time and memory requirement is exponential in the value of NNN
-** so you want to make sure that NNN is not too big. A value of NNN that
-** is about twice the average transformation cost seems to give good results.
-**
-** The fuzzer table can be useful for tasks such as spelling correction.
-** Suppose there is a second table vocabulary(w) where the w column contains
-** all correctly spelled words. Let $word be a word you want to look up.
-**
-** SELECT vocabulary.w FROM f, vocabulary
-** WHERE f.word MATCH $word
-** AND f.distance<=200
-** AND f.word=vocabulary.w
-** LIMIT 20
-**
-** The query above gives the 20 closest words to the $word being tested.
-** (Note that for good performance, the vocubulary.w column should be
-** indexed.)
-**
-** A similar query can be used to find all words in the dictionary that
-** begin with some prefix $prefix:
-**
-** SELECT vocabulary.w FROM f, vocabulary
-** WHERE f.word MATCH $prefix
-** AND f.distance<=200
-** AND vocabulary.w BETWEEN f.word AND (f.word || x'F7BFBFBF')
-** LIMIT 50
-**
-** This last query will show up to 50 words out of the vocabulary that
-** match or nearly match the $prefix.
-**
-** MULTIPLE RULE SETS
-**
-** Normally, the "ruleset" value associated with all character transformations
-** in the fuzzer data table is zero. However, if required, the fuzzer table
-** allows multiple rulesets to be defined. Each query uses only a single
-** ruleset. This allows, for example, a single fuzzer table to support
-** multiple languages.
-**
-** By default, only the rules from ruleset 0 are used. To specify an
-** alternative ruleset, a "ruleset = ?" expression must be added to the
-** WHERE clause of a SELECT, where ? is the identifier of the desired
-** ruleset. For example:
-**
-** SELECT vocabulary.w FROM f, vocabulary
-** WHERE f.word MATCH $word
-** AND f.distance<=200
-** AND f.word=vocabulary.w
-** AND f.ruleset=1 -- Specify the ruleset to use here
-** LIMIT 20
-**
-** If no "ruleset = ?" constraint is specified in the WHERE clause, ruleset
-** 0 is used.
-**
-** LIMITS
-**
-** The maximum ruleset number is 2147483647. The maximum length of either
-** of the strings in the second or third column of the fuzzer data table
-** is 50 bytes. The maximum cost on a rule is 1000.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-/* If SQLITE_DEBUG is not defined, disable assert statements. */
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
-# define NDEBUG
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Forward declaration of objects used by this implementation
-*/
-typedef struct fuzzer_vtab fuzzer_vtab;
-typedef struct fuzzer_cursor fuzzer_cursor;
-typedef struct fuzzer_rule fuzzer_rule;
-typedef struct fuzzer_seen fuzzer_seen;
-typedef struct fuzzer_stem fuzzer_stem;
-
-/*
-** Various types.
-**
-** fuzzer_cost is the "cost" of an edit operation.
-**
-** fuzzer_len is the length of a matching string.
-**
-** fuzzer_ruleid is an ruleset identifier.
-*/
-typedef int fuzzer_cost;
-typedef signed char fuzzer_len;
-typedef int fuzzer_ruleid;
-
-/*
-** Limits
-*/
-#define FUZZER_MX_LENGTH 50 /* Maximum length of a rule string */
-#define FUZZER_MX_RULEID 2147483647 /* Maximum rule ID */
-#define FUZZER_MX_COST 1000 /* Maximum single-rule cost */
-#define FUZZER_MX_OUTPUT_LENGTH 100 /* Maximum length of an output string */
-
-
-/*
-** Each transformation rule is stored as an instance of this object.
-** All rules are kept on a linked list sorted by rCost.
-*/
-struct fuzzer_rule {
- fuzzer_rule *pNext; /* Next rule in order of increasing rCost */
- char *zFrom; /* Transform from */
- fuzzer_cost rCost; /* Cost of this transformation */
- fuzzer_len nFrom, nTo; /* Length of the zFrom and zTo strings */
- fuzzer_ruleid iRuleset; /* The rule set to which this rule belongs */
- char zTo[4]; /* Transform to (extra space appended) */
-};
-
-/*
-** A stem object is used to generate variants. It is also used to record
-** previously generated outputs.
-**
-** Every stem is added to a hash table as it is output. Generation of
-** duplicate stems is suppressed.
-**
-** Active stems (those that might generate new outputs) are kepts on a linked
-** list sorted by increasing cost. The cost is the sum of rBaseCost and
-** pRule->rCost.
-*/
-struct fuzzer_stem {
- char *zBasis; /* Word being fuzzed */
- const fuzzer_rule *pRule; /* Current rule to apply */
- fuzzer_stem *pNext; /* Next stem in rCost order */
- fuzzer_stem *pHash; /* Next stem with same hash on zBasis */
- fuzzer_cost rBaseCost; /* Base cost of getting to zBasis */
- fuzzer_cost rCostX; /* Precomputed rBaseCost + pRule->rCost */
- fuzzer_len nBasis; /* Length of the zBasis string */
- fuzzer_len n; /* Apply pRule at this character offset */
-};
-
-/*
-** A fuzzer virtual-table object
-*/
-struct fuzzer_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- char *zClassName; /* Name of this class. Default: "fuzzer" */
- fuzzer_rule *pRule; /* All active rules in this fuzzer */
- int nCursor; /* Number of active cursors */
-};
-
-#define FUZZER_HASH 4001 /* Hash table size */
-#define FUZZER_NQUEUE 20 /* Number of slots on the stem queue */
-
-/* A fuzzer cursor object */
-struct fuzzer_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3_int64 iRowid; /* The rowid of the current word */
- fuzzer_vtab *pVtab; /* The virtual table this cursor belongs to */
- fuzzer_cost rLimit; /* Maximum cost of any term */
- fuzzer_stem *pStem; /* Stem with smallest rCostX */
- fuzzer_stem *pDone; /* Stems already processed to completion */
- fuzzer_stem *aQueue[FUZZER_NQUEUE]; /* Queue of stems with higher rCostX */
- int mxQueue; /* Largest used index in aQueue[] */
- char *zBuf; /* Temporary use buffer */
- int nBuf; /* Bytes allocated for zBuf */
- int nStem; /* Number of stems allocated */
- int iRuleset; /* Only process rules from this ruleset */
- fuzzer_rule nullRule; /* Null rule used first */
- fuzzer_stem *apHash[FUZZER_HASH]; /* Hash of previously generated terms */
-};
-
-/*
-** The two input rule lists are both sorted in order of increasing
-** cost. Merge them together into a single list, sorted by cost, and
-** return a pointer to the head of that list.
-*/
-static fuzzer_rule *fuzzerMergeRules(fuzzer_rule *pA, fuzzer_rule *pB){
- fuzzer_rule head;
- fuzzer_rule *pTail;
-
- pTail = &head;
- while( pA && pB ){
- if( pA->rCost<=pB->rCost ){
- pTail->pNext = pA;
- pTail = pA;
- pA = pA->pNext;
- }else{
- pTail->pNext = pB;
- pTail = pB;
- pB = pB->pNext;
- }
- }
- if( pA==0 ){
- pTail->pNext = pB;
- }else{
- pTail->pNext = pA;
- }
- return head.pNext;
-}
-
-/*
-** Statement pStmt currently points to a row in the fuzzer data table. This
-** function allocates and populates a fuzzer_rule structure according to
-** the content of the row.
-**
-** If successful, *ppRule is set to point to the new object and SQLITE_OK
-** is returned. Otherwise, *ppRule is zeroed, *pzErr may be set to point
-** to an error message and an SQLite error code returned.
-*/
-static int fuzzerLoadOneRule(
- fuzzer_vtab *p, /* Fuzzer virtual table handle */
- sqlite3_stmt *pStmt, /* Base rule on statements current row */
- fuzzer_rule **ppRule, /* OUT: New rule object */
- char **pzErr /* OUT: Error message */
-){
- sqlite3_int64 iRuleset = sqlite3_column_int64(pStmt, 0);
- const char *zFrom = (const char *)sqlite3_column_text(pStmt, 1);
- const char *zTo = (const char *)sqlite3_column_text(pStmt, 2);
- int nCost = sqlite3_column_int(pStmt, 3);
-
- int rc = SQLITE_OK; /* Return code */
- int nFrom; /* Size of string zFrom, in bytes */
- int nTo; /* Size of string zTo, in bytes */
- fuzzer_rule *pRule = 0; /* New rule object to return */
-
- if( zFrom==0 ) zFrom = "";
- if( zTo==0 ) zTo = "";
- nFrom = (int)strlen(zFrom);
- nTo = (int)strlen(zTo);
-
- /* Silently ignore null transformations */
- if( strcmp(zFrom, zTo)==0 ){
- *ppRule = 0;
- return SQLITE_OK;
- }
-
- if( nCost<=0 || nCost>FUZZER_MX_COST ){
- *pzErr = sqlite3_mprintf("%s: cost must be between 1 and %d",
- p->zClassName, FUZZER_MX_COST
- );
- rc = SQLITE_ERROR;
- }else
- if( nFrom>FUZZER_MX_LENGTH || nTo>FUZZER_MX_LENGTH ){
- *pzErr = sqlite3_mprintf("%s: maximum string length is %d",
- p->zClassName, FUZZER_MX_LENGTH
- );
- rc = SQLITE_ERROR;
- }else
- if( iRuleset<0 || iRuleset>FUZZER_MX_RULEID ){
- *pzErr = sqlite3_mprintf("%s: ruleset must be between 0 and %d",
- p->zClassName, FUZZER_MX_RULEID
- );
- rc = SQLITE_ERROR;
- }else{
-
- pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
- if( pRule==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pRule, 0, sizeof(*pRule));
- pRule->zFrom = pRule->zTo;
- pRule->zFrom += nTo + 1;
- pRule->nFrom = (fuzzer_len)nFrom;
- memcpy(pRule->zFrom, zFrom, nFrom+1);
- memcpy(pRule->zTo, zTo, nTo+1);
- pRule->nTo = (fuzzer_len)nTo;
- pRule->rCost = nCost;
- pRule->iRuleset = (int)iRuleset;
- }
- }
-
- *ppRule = pRule;
- return rc;
-}
-
-/*
-** Load the content of the fuzzer data table into memory.
-*/
-static int fuzzerLoadRules(
- sqlite3 *db, /* Database handle */
- fuzzer_vtab *p, /* Virtual fuzzer table to configure */
- const char *zDb, /* Database containing rules data */
- const char *zData, /* Table containing rules data */
- char **pzErr /* OUT: Error message */
-){
- int rc = SQLITE_OK; /* Return code */
- char *zSql; /* SELECT used to read from rules table */
- fuzzer_rule *pHead = 0;
-
- zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zData);
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int rc2; /* finalize() return code */
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- *pzErr = sqlite3_mprintf("%s: %s", p->zClassName, sqlite3_errmsg(db));
- }else if( sqlite3_column_count(pStmt)!=4 ){
- *pzErr = sqlite3_mprintf("%s: %s has %d columns, expected 4",
- p->zClassName, zData, sqlite3_column_count(pStmt)
- );
- rc = SQLITE_ERROR;
- }else{
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- fuzzer_rule *pRule = 0;
- rc = fuzzerLoadOneRule(p, pStmt, &pRule, pzErr);
- if( pRule ){
- pRule->pNext = pHead;
- pHead = pRule;
- }
- }
- }
- rc2 = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) rc = rc2;
- }
- sqlite3_free(zSql);
-
- /* All rules are now in a singly linked list starting at pHead. This
- ** block sorts them by cost and then sets fuzzer_vtab.pRule to point to
- ** point to the head of the sorted list.
- */
- if( rc==SQLITE_OK ){
- unsigned int i;
- fuzzer_rule *pX;
- fuzzer_rule *a[15];
- for(i=0; i<sizeof(a)/sizeof(a[0]); i++) a[i] = 0;
- while( (pX = pHead)!=0 ){
- pHead = pX->pNext;
- pX->pNext = 0;
- for(i=0; a[i] && i<sizeof(a)/sizeof(a[0])-1; i++){
- pX = fuzzerMergeRules(a[i], pX);
- a[i] = 0;
- }
- a[i] = fuzzerMergeRules(a[i], pX);
- }
- for(pX=a[0], i=1; i<sizeof(a)/sizeof(a[0]); i++){
- pX = fuzzerMergeRules(a[i], pX);
- }
- p->pRule = fuzzerMergeRules(p->pRule, pX);
- }else{
- /* An error has occurred. Setting p->pRule to point to the head of the
- ** allocated list ensures that the list will be cleaned up in this case.
- */
- assert( p->pRule==0 );
- p->pRule = pHead;
- }
-
- return rc;
-}
-
-/*
-** This function converts an SQL quoted string into an unquoted string
-** and returns a pointer to a buffer allocated using sqlite3_malloc()
-** containing the result. The caller should eventually free this buffer
-** using sqlite3_free.
-**
-** Examples:
-**
-** "abc" becomes abc
-** 'xyz' becomes xyz
-** [pqr] becomes pqr
-** `mno` becomes mno
-*/
-static char *fuzzerDequote(const char *zIn){
- int nIn; /* Size of input string, in bytes */
- char *zOut; /* Output (dequoted) string */
-
- nIn = (int)strlen(zIn);
- zOut = sqlite3_malloc(nIn+1);
- if( zOut ){
- char q = zIn[0]; /* Quote character (if any ) */
-
- if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
- memcpy(zOut, zIn, nIn+1);
- }else{
- int iOut = 0; /* Index of next byte to write to output */
- int iIn; /* Index of next byte to read from input */
-
- if( q=='[' ) q = ']';
- for(iIn=1; iIn<nIn; iIn++){
- if( zIn[iIn]==q ) iIn++;
- zOut[iOut++] = zIn[iIn];
- }
- }
- assert( (int)strlen(zOut)<=nIn );
- }
- return zOut;
-}
-
-/*
-** xDisconnect/xDestroy method for the fuzzer module.
-*/
-static int fuzzerDisconnect(sqlite3_vtab *pVtab){
- fuzzer_vtab *p = (fuzzer_vtab*)pVtab;
- assert( p->nCursor==0 );
- while( p->pRule ){
- fuzzer_rule *pRule = p->pRule;
- p->pRule = pRule->pNext;
- sqlite3_free(pRule);
- }
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** xConnect/xCreate method for the fuzzer module. Arguments are:
-**
-** argv[0] -> module name ("fuzzer")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[3] -> fuzzer rule table name
-*/
-static int fuzzerConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- int rc = SQLITE_OK; /* Return code */
- fuzzer_vtab *pNew = 0; /* New virtual table */
- const char *zModule = argv[0];
- const char *zDb = argv[1];
-
- if( argc!=4 ){
- *pzErr = sqlite3_mprintf(
- "%s: wrong number of CREATE VIRTUAL TABLE arguments", zModule
- );
- rc = SQLITE_ERROR;
- }else{
- int nModule; /* Length of zModule, in bytes */
-
- nModule = (int)strlen(zModule);
- pNew = sqlite3_malloc( sizeof(*pNew) + nModule + 1);
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- char *zTab; /* Dequoted name of fuzzer data table */
-
- memset(pNew, 0, sizeof(*pNew));
- pNew->zClassName = (char*)&pNew[1];
- memcpy(pNew->zClassName, zModule, nModule+1);
-
- zTab = fuzzerDequote(argv[3]);
- if( zTab==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = fuzzerLoadRules(db, pNew, zDb, zTab, pzErr);
- sqlite3_free(zTab);
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_declare_vtab(db, "CREATE TABLE x(word,distance,ruleset)");
- }
- if( rc!=SQLITE_OK ){
- fuzzerDisconnect((sqlite3_vtab *)pNew);
- pNew = 0;
- }
- }
- }
-
- *ppVtab = (sqlite3_vtab *)pNew;
- return rc;
-}
-
-/*
-** Open a new fuzzer cursor.
-*/
-static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- fuzzer_vtab *p = (fuzzer_vtab*)pVTab;
- fuzzer_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->pVtab = p;
- *ppCursor = &pCur->base;
- p->nCursor++;
- return SQLITE_OK;
-}
-
-/*
-** Free all stems in a list.
-*/
-static void fuzzerClearStemList(fuzzer_stem *pStem){
- while( pStem ){
- fuzzer_stem *pNext = pStem->pNext;
- sqlite3_free(pStem);
- pStem = pNext;
- }
-}
-
-/*
-** Free up all the memory allocated by a cursor. Set it rLimit to 0
-** to indicate that it is at EOF.
-*/
-static void fuzzerClearCursor(fuzzer_cursor *pCur, int clearHash){
- int i;
- fuzzerClearStemList(pCur->pStem);
- fuzzerClearStemList(pCur->pDone);
- for(i=0; i<FUZZER_NQUEUE; i++) fuzzerClearStemList(pCur->aQueue[i]);
- pCur->rLimit = (fuzzer_cost)0;
- if( clearHash && pCur->nStem ){
- pCur->mxQueue = 0;
- pCur->pStem = 0;
- pCur->pDone = 0;
- memset(pCur->aQueue, 0, sizeof(pCur->aQueue));
- memset(pCur->apHash, 0, sizeof(pCur->apHash));
- }
- pCur->nStem = 0;
-}
-
-/*
-** Close a fuzzer cursor.
-*/
-static int fuzzerClose(sqlite3_vtab_cursor *cur){
- fuzzer_cursor *pCur = (fuzzer_cursor *)cur;
- fuzzerClearCursor(pCur, 0);
- sqlite3_free(pCur->zBuf);
- pCur->pVtab->nCursor--;
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Compute the current output term for a fuzzer_stem.
-*/
-static int fuzzerRender(
- fuzzer_stem *pStem, /* The stem to be rendered */
- char **pzBuf, /* Write results into this buffer. realloc if needed */
- int *pnBuf /* Size of the buffer */
-){
- const fuzzer_rule *pRule = pStem->pRule;
- int n; /* Size of output term without nul-term */
- char *z; /* Buffer to assemble output term in */
-
- n = pStem->nBasis + pRule->nTo - pRule->nFrom;
- if( (*pnBuf)<n+1 ){
- (*pzBuf) = sqlite3_realloc((*pzBuf), n+100);
- if( (*pzBuf)==0 ) return SQLITE_NOMEM;
- (*pnBuf) = n+100;
- }
- n = pStem->n;
- z = *pzBuf;
- if( n<0 ){
- memcpy(z, pStem->zBasis, pStem->nBasis+1);
- }else{
- memcpy(z, pStem->zBasis, n);
- memcpy(&z[n], pRule->zTo, pRule->nTo);
- memcpy(&z[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom],
- pStem->nBasis-n-pRule->nFrom+1);
- }
-
- assert( z[pStem->nBasis + pRule->nTo - pRule->nFrom]==0 );
- return SQLITE_OK;
-}
-
-/*
-** Compute a hash on zBasis.
-*/
-static unsigned int fuzzerHash(const char *z){
- unsigned int h = 0;
- while( *z ){ h = (h<<3) ^ (h>>29) ^ *(z++); }
- return h % FUZZER_HASH;
-}
-
-/*
-** Current cost of a stem
-*/
-static fuzzer_cost fuzzerCost(fuzzer_stem *pStem){
- return pStem->rCostX = pStem->rBaseCost + pStem->pRule->rCost;
-}
-
-#if 0
-/*
-** Print a description of a fuzzer_stem on stderr.
-*/
-static void fuzzerStemPrint(
- const char *zPrefix,
- fuzzer_stem *pStem,
- const char *zSuffix
-){
- if( pStem->n<0 ){
- fprintf(stderr, "%s[%s](%d)-->self%s",
- zPrefix,
- pStem->zBasis, pStem->rBaseCost,
- zSuffix
- );
- }else{
- char *zBuf = 0;
- int nBuf = 0;
- if( fuzzerRender(pStem, &zBuf, &nBuf)!=SQLITE_OK ) return;
- fprintf(stderr, "%s[%s](%d)-->{%s}(%d)%s",
- zPrefix,
- pStem->zBasis, pStem->rBaseCost, zBuf, pStem->,
- zSuffix
- );
- sqlite3_free(zBuf);
- }
-}
-#endif
-
-/*
-** Return 1 if the string to which the cursor is point has already
-** been emitted. Return 0 if not. Return -1 on a memory allocation
-** failures.
-*/
-static int fuzzerSeen(fuzzer_cursor *pCur, fuzzer_stem *pStem){
- unsigned int h;
- fuzzer_stem *pLookup;
-
- if( fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){
- return -1;
- }
- h = fuzzerHash(pCur->zBuf);
- pLookup = pCur->apHash[h];
- while( pLookup && strcmp(pLookup->zBasis, pCur->zBuf)!=0 ){
- pLookup = pLookup->pHash;
- }
- return pLookup!=0;
-}
-
-/*
-** If argument pRule is NULL, this function returns false.
-**
-** Otherwise, it returns true if rule pRule should be skipped. A rule
-** should be skipped if it does not belong to rule-set iRuleset, or if
-** applying it to stem pStem would create a string longer than
-** FUZZER_MX_OUTPUT_LENGTH bytes.
-*/
-static int fuzzerSkipRule(
- const fuzzer_rule *pRule, /* Determine whether or not to skip this */
- fuzzer_stem *pStem, /* Stem rule may be applied to */
- int iRuleset /* Rule-set used by the current query */
-){
- return pRule && (
- (pRule->iRuleset!=iRuleset)
- || (pStem->nBasis + pRule->nTo - pRule->nFrom)>FUZZER_MX_OUTPUT_LENGTH
- );
-}
-
-/*
-** Advance a fuzzer_stem to its next value. Return 0 if there are
-** no more values that can be generated by this fuzzer_stem. Return
-** -1 on a memory allocation failure.
-*/
-static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){
- const fuzzer_rule *pRule;
- while( (pRule = pStem->pRule)!=0 ){
- assert( pRule==&pCur->nullRule || pRule->iRuleset==pCur->iRuleset );
- while( pStem->n < pStem->nBasis - pRule->nFrom ){
- pStem->n++;
- if( pRule->nFrom==0
- || memcmp(&pStem->zBasis[pStem->n], pRule->zFrom, pRule->nFrom)==0
- ){
- /* Found a rewrite case. Make sure it is not a duplicate */
- int rc = fuzzerSeen(pCur, pStem);
- if( rc<0 ) return -1;
- if( rc==0 ){
- fuzzerCost(pStem);
- return 1;
- }
- }
- }
- pStem->n = -1;
- do{
- pRule = pRule->pNext;
- }while( fuzzerSkipRule(pRule, pStem, pCur->iRuleset) );
- pStem->pRule = pRule;
- if( pRule && fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0;
- }
- return 0;
-}
-
-/*
-** The two input stem lists are both sorted in order of increasing
-** rCostX. Merge them together into a single list, sorted by rCostX, and
-** return a pointer to the head of that new list.
-*/
-static fuzzer_stem *fuzzerMergeStems(fuzzer_stem *pA, fuzzer_stem *pB){
- fuzzer_stem head;
- fuzzer_stem *pTail;
-
- pTail = &head;
- while( pA && pB ){
- if( pA->rCostX<=pB->rCostX ){
- pTail->pNext = pA;
- pTail = pA;
- pA = pA->pNext;
- }else{
- pTail->pNext = pB;
- pTail = pB;
- pB = pB->pNext;
- }
- }
- if( pA==0 ){
- pTail->pNext = pB;
- }else{
- pTail->pNext = pA;
- }
- return head.pNext;
-}
-
-/*
-** Load pCur->pStem with the lowest-cost stem. Return a pointer
-** to the lowest-cost stem.
-*/
-static fuzzer_stem *fuzzerLowestCostStem(fuzzer_cursor *pCur){
- fuzzer_stem *pBest, *pX;
- int iBest;
- int i;
-
- if( pCur->pStem==0 ){
- iBest = -1;
- pBest = 0;
- for(i=0; i<=pCur->mxQueue; i++){
- pX = pCur->aQueue[i];
- if( pX==0 ) continue;
- if( pBest==0 || pBest->rCostX>pX->rCostX ){
- pBest = pX;
- iBest = i;
- }
- }
- if( pBest ){
- pCur->aQueue[iBest] = pBest->pNext;
- pBest->pNext = 0;
- pCur->pStem = pBest;
- }
- }
- return pCur->pStem;
-}
-
-/*
-** Insert pNew into queue of pending stems. Then find the stem
-** with the lowest rCostX and move it into pCur->pStem.
-** list. The insert is done such the pNew is in the correct order
-** according to fuzzer_stem.zBaseCost+fuzzer_stem.pRule->rCost.
-*/
-static fuzzer_stem *fuzzerInsert(fuzzer_cursor *pCur, fuzzer_stem *pNew){
- fuzzer_stem *pX;
- int i;
-
- /* If pCur->pStem exists and is greater than pNew, then make pNew
- ** the new pCur->pStem and insert the old pCur->pStem instead.
- */
- if( (pX = pCur->pStem)!=0 && pX->rCostX>pNew->rCostX ){
- pNew->pNext = 0;
- pCur->pStem = pNew;
- pNew = pX;
- }
-
- /* Insert the new value */
- pNew->pNext = 0;
- pX = pNew;
- for(i=0; i<=pCur->mxQueue; i++){
- if( pCur->aQueue[i] ){
- pX = fuzzerMergeStems(pX, pCur->aQueue[i]);
- pCur->aQueue[i] = 0;
- }else{
- pCur->aQueue[i] = pX;
- break;
- }
- }
- if( i>pCur->mxQueue ){
- if( i<FUZZER_NQUEUE ){
- pCur->mxQueue = i;
- pCur->aQueue[i] = pX;
- }else{
- assert( pCur->mxQueue==FUZZER_NQUEUE-1 );
- pX = fuzzerMergeStems(pX, pCur->aQueue[FUZZER_NQUEUE-1]);
- pCur->aQueue[FUZZER_NQUEUE-1] = pX;
- }
- }
-
- return fuzzerLowestCostStem(pCur);
-}
-
-/*
-** Allocate a new fuzzer_stem. Add it to the hash table but do not
-** link it into either the pCur->pStem or pCur->pDone lists.
-*/
-static fuzzer_stem *fuzzerNewStem(
- fuzzer_cursor *pCur,
- const char *zWord,
- fuzzer_cost rBaseCost
-){
- fuzzer_stem *pNew;
- fuzzer_rule *pRule;
- unsigned int h;
-
- pNew = sqlite3_malloc( sizeof(*pNew) + (int)strlen(zWord) + 1 );
- if( pNew==0 ) return 0;
- memset(pNew, 0, sizeof(*pNew));
- pNew->zBasis = (char*)&pNew[1];
- pNew->nBasis = (fuzzer_len)strlen(zWord);
- memcpy(pNew->zBasis, zWord, pNew->nBasis+1);
- pRule = pCur->pVtab->pRule;
- while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){
- pRule = pRule->pNext;
- }
- pNew->pRule = pRule;
- pNew->n = -1;
- pNew->rBaseCost = pNew->rCostX = rBaseCost;
- h = fuzzerHash(pNew->zBasis);
- pNew->pHash = pCur->apHash[h];
- pCur->apHash[h] = pNew;
- pCur->nStem++;
- return pNew;
-}
-
-
-/*
-** Advance a cursor to its next row of output
-*/
-static int fuzzerNext(sqlite3_vtab_cursor *cur){
- fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
- int rc;
- fuzzer_stem *pStem, *pNew;
-
- pCur->iRowid++;
-
- /* Use the element the cursor is currently point to to create
- ** a new stem and insert the new stem into the priority queue.
- */
- pStem = pCur->pStem;
- if( pStem->rCostX>0 ){
- rc = fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf);
- if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM;
- pNew = fuzzerNewStem(pCur, pCur->zBuf, pStem->rCostX);
- if( pNew ){
- if( fuzzerAdvance(pCur, pNew)==0 ){
- pNew->pNext = pCur->pDone;
- pCur->pDone = pNew;
- }else{
- if( fuzzerInsert(pCur, pNew)==pNew ){
- return SQLITE_OK;
- }
- }
- }else{
- return SQLITE_NOMEM;
- }
- }
-
- /* Adjust the priority queue so that the first element of the
- ** stem list is the next lowest cost word.
- */
- while( (pStem = pCur->pStem)!=0 ){
- int res = fuzzerAdvance(pCur, pStem);
- if( res<0 ){
- return SQLITE_NOMEM;
- }else if( res>0 ){
- pCur->pStem = 0;
- pStem = fuzzerInsert(pCur, pStem);
- if( (rc = fuzzerSeen(pCur, pStem))!=0 ){
- if( rc<0 ) return SQLITE_NOMEM;
- continue;
- }
- return SQLITE_OK; /* New word found */
- }
- pCur->pStem = 0;
- pStem->pNext = pCur->pDone;
- pCur->pDone = pStem;
- if( fuzzerLowestCostStem(pCur) ){
- rc = fuzzerSeen(pCur, pCur->pStem);
- if( rc<0 ) return SQLITE_NOMEM;
- if( rc==0 ){
- return SQLITE_OK;
- }
- }
- }
-
- /* Reach this point only if queue has been exhausted and there is
- ** nothing left to be output. */
- pCur->rLimit = (fuzzer_cost)0;
- return SQLITE_OK;
-}
-
-/*
-** Called to "rewind" a cursor back to the beginning so that
-** it starts its output over again. Always called at least once
-** prior to any fuzzerColumn, fuzzerRowid, or fuzzerEof call.
-*/
-static int fuzzerFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor;
- const char *zWord = "";
- fuzzer_stem *pStem;
- int idx;
-
- fuzzerClearCursor(pCur, 1);
- pCur->rLimit = 2147483647;
- idx = 0;
- if( idxNum & 1 ){
- zWord = (const char*)sqlite3_value_text(argv[0]);
- idx++;
- }
- if( idxNum & 2 ){
- pCur->rLimit = (fuzzer_cost)sqlite3_value_int(argv[idx]);
- idx++;
- }
- if( idxNum & 4 ){
- pCur->iRuleset = (fuzzer_cost)sqlite3_value_int(argv[idx]);
- idx++;
- }
- pCur->nullRule.pNext = pCur->pVtab->pRule;
- pCur->nullRule.rCost = 0;
- pCur->nullRule.nFrom = 0;
- pCur->nullRule.nTo = 0;
- pCur->nullRule.zFrom = "";
- pCur->iRowid = 1;
- assert( pCur->pStem==0 );
-
- /* If the query term is longer than FUZZER_MX_OUTPUT_LENGTH bytes, this
- ** query will return zero rows. */
- if( (int)strlen(zWord)<FUZZER_MX_OUTPUT_LENGTH ){
- pCur->pStem = pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0);
- if( pStem==0 ) return SQLITE_NOMEM;
- pStem->pRule = &pCur->nullRule;
- pStem->n = pStem->nBasis;
- }else{
- pCur->rLimit = 0;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Only the word and distance columns have values. All other columns
-** return NULL
-*/
-static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
- if( i==0 ){
- /* the "word" column */
- if( fuzzerRender(pCur->pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){
- return SQLITE_NOMEM;
- }
- sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT);
- }else if( i==1 ){
- /* the "distance" column */
- sqlite3_result_int(ctx, pCur->pStem->rCostX);
- }else{
- /* All other columns are NULL */
- sqlite3_result_null(ctx);
- }
- return SQLITE_OK;
-}
-
-/*
-** The rowid.
-*/
-static int fuzzerRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** When the fuzzer_cursor.rLimit value is 0 or less, that is a signal
-** that the cursor has nothing more to output.
-*/
-static int fuzzerEof(sqlite3_vtab_cursor *cur){
- fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
- return pCur->rLimit<=(fuzzer_cost)0;
-}
-
-/*
-** Search for terms of these forms:
-**
-** (A) word MATCH $str
-** (B1) distance < $value
-** (B2) distance <= $value
-** (C) ruleid == $ruleid
-**
-** The distance< and distance<= are both treated as distance<=.
-** The query plan number is a bit vector:
-**
-** bit 1: Term of the form (A) found
-** bit 2: Term like (B1) or (B2) found
-** bit 3: Term like (C) found
-**
-** If bit-1 is set, $str is always in filter.argv[0]. If bit-2 is set
-** then $value is in filter.argv[0] if bit-1 is clear and is in
-** filter.argv[1] if bit-1 is set. If bit-3 is set, then $ruleid is
-** in filter.argv[0] if bit-1 and bit-2 are both zero, is in
-** filter.argv[1] if exactly one of bit-1 and bit-2 are set, and is in
-** filter.argv[2] if both bit-1 and bit-2 are set.
-*/
-static int fuzzerBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int iPlan = 0;
- int iDistTerm = -1;
- int iRulesetTerm = -1;
- int i;
- int seenMatch = 0;
- const struct sqlite3_index_constraint *pConstraint;
- double rCost = 1e12;
-
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->iColumn==0
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
- seenMatch = 1;
- }
- if( pConstraint->usable==0 ) continue;
- if( (iPlan & 1)==0
- && pConstraint->iColumn==0
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH
- ){
- iPlan |= 1;
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- rCost /= 1e6;
- }
- if( (iPlan & 2)==0
- && pConstraint->iColumn==1
- && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
- || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE)
- ){
- iPlan |= 2;
- iDistTerm = i;
- rCost /= 10.0;
- }
- if( (iPlan & 4)==0
- && pConstraint->iColumn==2
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= 4;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- iRulesetTerm = i;
- rCost /= 10.0;
- }
- }
- if( iPlan & 2 ){
- pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = 1+((iPlan&1)!=0);
- }
- if( iPlan & 4 ){
- int idx = 1;
- if( iPlan & 1 ) idx++;
- if( iPlan & 2 ) idx++;
- pIdxInfo->aConstraintUsage[iRulesetTerm].argvIndex = idx;
- }
- pIdxInfo->idxNum = iPlan;
- if( pIdxInfo->nOrderBy==1
- && pIdxInfo->aOrderBy[0].iColumn==1
- && pIdxInfo->aOrderBy[0].desc==0
- ){
- pIdxInfo->orderByConsumed = 1;
- }
- if( seenMatch && (iPlan&1)==0 ) rCost = 1e99;
- pIdxInfo->estimatedCost = rCost;
-
- return SQLITE_OK;
-}
-
-/*
-** A virtual table module that implements the "fuzzer".
-*/
-static sqlite3_module fuzzerModule = {
- 0, /* iVersion */
- fuzzerConnect,
- fuzzerConnect,
- fuzzerBestIndex,
- fuzzerDisconnect,
- fuzzerDisconnect,
- fuzzerOpen, /* xOpen - open a cursor */
- fuzzerClose, /* xClose - close a cursor */
- fuzzerFilter, /* xFilter - configure scan constraints */
- fuzzerNext, /* xNext - advance a cursor */
- fuzzerEof, /* xEof - check for end of scan */
- fuzzerColumn, /* xColumn - read data */
- fuzzerRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fuzzer_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_create_module(db, "fuzzer", &fuzzerModule, 0);
-#endif
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/ieee754.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/ieee754.c
deleted file mode 100644
index 20c5e614334..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/ieee754.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-** 2013-04-17
-**
-** 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 SQLite extension implements functions for the exact display
-** and input of IEEE754 Binary64 floating-point numbers.
-**
-** ieee754(X)
-** ieee754(Y,Z)
-**
-** In the first form, the value X should be a floating-point number.
-** The function will return a string of the form 'ieee754(Y,Z)' where
-** Y and Z are integers such that X==Y*pow(2,Z).
-**
-** In the second form, Y and Z are integers which are the mantissa and
-** base-2 exponent of a new floating point number. The function returns
-** a floating-point value equal to Y*pow(2,Z).
-**
-** Examples:
-**
-** ieee754(2.0) -> 'ieee754(2,0)'
-** ieee754(45.25) -> 'ieee754(181,-2)'
-** ieee754(2, 0) -> 2.0
-** ieee754(181, -2) -> 45.25
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-/*
-** Implementation of the ieee754() function
-*/
-static void ieee754func(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- if( argc==1 ){
- sqlite3_int64 m, a;
- double r;
- int e;
- int isNeg;
- char zResult[100];
- assert( sizeof(m)==sizeof(r) );
- if( sqlite3_value_type(argv[0])!=SQLITE_FLOAT ) return;
- r = sqlite3_value_double(argv[0]);
- if( r<0.0 ){
- isNeg = 1;
- r = -r;
- }else{
- isNeg = 0;
- }
- memcpy(&a,&r,sizeof(a));
- if( a==0 ){
- e = 0;
- m = 0;
- }else{
- e = a>>52;
- m = a & ((((sqlite3_int64)1)<<52)-1);
- m |= ((sqlite3_int64)1)<<52;
- while( e<1075 && m>0 && (m&1)==0 ){
- m >>= 1;
- e++;
- }
- if( isNeg ) m = -m;
- }
- sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
- m, e-1075);
- sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
- }else if( argc==2 ){
- sqlite3_int64 m, e, a;
- double r;
- int isNeg = 0;
- m = sqlite3_value_int64(argv[0]);
- e = sqlite3_value_int64(argv[1]);
- if( m<0 ){
- isNeg = 1;
- m = -m;
- if( m<0 ) return;
- }else if( m==0 && e>1000 && e<1000 ){
- sqlite3_result_double(context, 0.0);
- return;
- }
- while( (m>>32)&0xffe00000 ){
- m >>= 1;
- e++;
- }
- while( m!=0 && ((m>>32)&0xfff00000)==0 ){
- m <<= 1;
- e--;
- }
- e += 1075;
- if( e<0 ) e = m = 0;
- if( e>0x7ff ) e = 0x7ff;
- a = m & ((((sqlite3_int64)1)<<52)-1);
- a |= e<<52;
- if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
- memcpy(&r, &a, sizeof(r));
- sqlite3_result_double(context, r);
- }
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_ieee_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "ieee754", 1, SQLITE_UTF8, 0,
- ieee754func, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "ieee754", 2, SQLITE_UTF8, 0,
- ieee754func, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/json1.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/json1.c
deleted file mode 100644
index 735e3c94ac3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/json1.c
+++ /dev/null
@@ -1,2427 +0,0 @@
-/*
-** 2015-08-12
-**
-** 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 SQLite extension implements JSON functions. The interface is
-** modeled after MySQL JSON functions:
-**
-** https://dev.mysql.com/doc/refman/5.7/en/json.html
-**
-** For the time being, all JSON is stored as pure text. (We might add
-** a JSONB type in the future which stores a binary encoding of JSON in
-** a BLOB, but there is no support for JSONB in the current implementation.
-** This implementation parses JSON text at 250 MB/s, so it is hard to see
-** how JSONB might improve on that.)
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
-#if !defined(SQLITEINT_H)
-#include "sqlite3ext.h"
-#endif
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-/* Mark a function parameter as unused, to suppress nuisance compiler
-** warnings. */
-#ifndef UNUSED_PARAM
-# define UNUSED_PARAM(X) (void)(X)
-#endif
-
-#ifndef LARGEST_INT64
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
-/*
-** Versions of isspace(), isalnum() and isdigit() to which it is safe
-** to pass signed char values.
-*/
-#ifdef sqlite3Isdigit
- /* Use the SQLite core versions if this routine is part of the
- ** SQLite amalgamation */
-# define safe_isdigit(x) sqlite3Isdigit(x)
-# define safe_isalnum(x) sqlite3Isalnum(x)
-# define safe_isxdigit(x) sqlite3Isxdigit(x)
-#else
- /* Use the standard library for separate compilation */
-#include <ctype.h> /* amalgamator: keep */
-# define safe_isdigit(x) isdigit((unsigned char)(x))
-# define safe_isalnum(x) isalnum((unsigned char)(x))
-# define safe_isxdigit(x) isxdigit((unsigned char)(x))
-#endif
-
-/*
-** Growing our own isspace() routine this way is twice as fast as
-** the library isspace() function, resulting in a 7% overall performance
-** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
-*/
-static const char jsonIsSpace[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
-
-#ifndef SQLITE_AMALGAMATION
- /* Unsigned integer types. These are already defined in the sqliteInt.h,
- ** but the definitions need to be repeated for separate compilation. */
- typedef sqlite3_uint64 u64;
- typedef unsigned int u32;
- typedef unsigned short int u16;
- typedef unsigned char u8;
-#endif
-
-/* Objects */
-typedef struct JsonString JsonString;
-typedef struct JsonNode JsonNode;
-typedef struct JsonParse JsonParse;
-
-/* An instance of this object represents a JSON string
-** under construction. Really, this is a generic string accumulator
-** that can be and is used to create strings other than JSON.
-*/
-struct JsonString {
- sqlite3_context *pCtx; /* Function context - put error messages here */
- char *zBuf; /* Append JSON content here */
- u64 nAlloc; /* Bytes of storage available in zBuf[] */
- u64 nUsed; /* Bytes of zBuf[] currently used */
- u8 bStatic; /* True if zBuf is static space */
- u8 bErr; /* True if an error has been encountered */
- char zSpace[100]; /* Initial static space */
-};
-
-/* JSON type values
-*/
-#define JSON_NULL 0
-#define JSON_TRUE 1
-#define JSON_FALSE 2
-#define JSON_INT 3
-#define JSON_REAL 4
-#define JSON_STRING 5
-#define JSON_ARRAY 6
-#define JSON_OBJECT 7
-
-/* The "subtype" set for JSON values */
-#define JSON_SUBTYPE 74 /* Ascii for "J" */
-
-/*
-** Names of the various JSON types:
-*/
-static const char * const jsonType[] = {
- "null", "true", "false", "integer", "real", "text", "array", "object"
-};
-
-/* Bit values for the JsonNode.jnFlag field
-*/
-#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */
-#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */
-#define JNODE_REMOVE 0x04 /* Do not output */
-#define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */
-#define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */
-#define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */
-#define JNODE_LABEL 0x40 /* Is a label of an object */
-
-
-/* A single node of parsed JSON
-*/
-struct JsonNode {
- u8 eType; /* One of the JSON_ type values */
- u8 jnFlags; /* JNODE flags */
- u32 n; /* Bytes of content, or number of sub-nodes */
- union {
- const char *zJContent; /* Content for INT, REAL, and STRING */
- u32 iAppend; /* More terms for ARRAY and OBJECT */
- u32 iKey; /* Key for ARRAY objects in json_tree() */
- u32 iReplace; /* Replacement content for JNODE_REPLACE */
- JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */
- } u;
-};
-
-/* A completely parsed JSON string
-*/
-struct JsonParse {
- u32 nNode; /* Number of slots of aNode[] used */
- u32 nAlloc; /* Number of slots of aNode[] allocated */
- JsonNode *aNode; /* Array of nodes containing the parse */
- const char *zJson; /* Original JSON string */
- u32 *aUp; /* Index of parent of each node */
- u8 oom; /* Set to true if out of memory */
- u8 nErr; /* Number of errors seen */
- u16 iDepth; /* Nesting depth */
- int nJson; /* Length of the zJson string in bytes */
-};
-
-/*
-** Maximum nesting depth of JSON for this implementation.
-**
-** This limit is needed to avoid a stack overflow in the recursive
-** descent parser. A depth of 2000 is far deeper than any sane JSON
-** should go.
-*/
-#define JSON_MAX_DEPTH 2000
-
-/**************************************************************************
-** Utility routines for dealing with JsonString objects
-**************************************************************************/
-
-/* Set the JsonString object to an empty string
-*/
-static void jsonZero(JsonString *p){
- p->zBuf = p->zSpace;
- p->nAlloc = sizeof(p->zSpace);
- p->nUsed = 0;
- p->bStatic = 1;
-}
-
-/* Initialize the JsonString object
-*/
-static void jsonInit(JsonString *p, sqlite3_context *pCtx){
- p->pCtx = pCtx;
- p->bErr = 0;
- jsonZero(p);
-}
-
-
-/* Free all allocated memory and reset the JsonString object back to its
-** initial state.
-*/
-static void jsonReset(JsonString *p){
- if( !p->bStatic ) sqlite3_free(p->zBuf);
- jsonZero(p);
-}
-
-
-/* Report an out-of-memory (OOM) condition
-*/
-static void jsonOom(JsonString *p){
- p->bErr = 1;
- sqlite3_result_error_nomem(p->pCtx);
- jsonReset(p);
-}
-
-/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
-** Return zero on success. Return non-zero on an OOM error
-*/
-static int jsonGrow(JsonString *p, u32 N){
- u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10;
- char *zNew;
- if( p->bStatic ){
- if( p->bErr ) return 1;
- zNew = sqlite3_malloc64(nTotal);
- if( zNew==0 ){
- jsonOom(p);
- return SQLITE_NOMEM;
- }
- memcpy(zNew, p->zBuf, (size_t)p->nUsed);
- p->zBuf = zNew;
- p->bStatic = 0;
- }else{
- zNew = sqlite3_realloc64(p->zBuf, nTotal);
- if( zNew==0 ){
- jsonOom(p);
- return SQLITE_NOMEM;
- }
- p->zBuf = zNew;
- }
- p->nAlloc = nTotal;
- return SQLITE_OK;
-}
-
-/* Append N bytes from zIn onto the end of the JsonString string.
-*/
-static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
- if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
- memcpy(p->zBuf+p->nUsed, zIn, N);
- p->nUsed += N;
-}
-
-/* Append formatted text (not to exceed N bytes) to the JsonString.
-*/
-static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){
- va_list ap;
- if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return;
- va_start(ap, zFormat);
- sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap);
- va_end(ap);
- p->nUsed += (int)strlen(p->zBuf+p->nUsed);
-}
-
-/* Append a single character
-*/
-static void jsonAppendChar(JsonString *p, char c){
- if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return;
- p->zBuf[p->nUsed++] = c;
-}
-
-/* Append a comma separator to the output buffer, if the previous
-** character is not '[' or '{'.
-*/
-static void jsonAppendSeparator(JsonString *p){
- char c;
- if( p->nUsed==0 ) return;
- c = p->zBuf[p->nUsed-1];
- if( c!='[' && c!='{' ) jsonAppendChar(p, ',');
-}
-
-/* Append the N-byte string in zIn to the end of the JsonString string
-** under construction. Enclose the string in "..." and escape
-** any double-quotes or backslash characters contained within the
-** string.
-*/
-static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
- u32 i;
- if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
- p->zBuf[p->nUsed++] = '"';
- for(i=0; i<N; i++){
- unsigned char c = ((unsigned const char*)zIn)[i];
- if( c=='"' || c=='\\' ){
- json_simple_escape:
- if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
- p->zBuf[p->nUsed++] = '\\';
- }else if( c<=0x1f ){
- static const char aSpecial[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- assert( sizeof(aSpecial)==32 );
- assert( aSpecial['\b']=='b' );
- assert( aSpecial['\f']=='f' );
- assert( aSpecial['\n']=='n' );
- assert( aSpecial['\r']=='r' );
- assert( aSpecial['\t']=='t' );
- if( aSpecial[c] ){
- c = aSpecial[c];
- goto json_simple_escape;
- }
- if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return;
- p->zBuf[p->nUsed++] = '\\';
- p->zBuf[p->nUsed++] = 'u';
- p->zBuf[p->nUsed++] = '0';
- p->zBuf[p->nUsed++] = '0';
- p->zBuf[p->nUsed++] = '0' + (c>>4);
- c = "0123456789abcdef"[c&0xf];
- }
- p->zBuf[p->nUsed++] = c;
- }
- p->zBuf[p->nUsed++] = '"';
- assert( p->nUsed<p->nAlloc );
-}
-
-/*
-** Append a function parameter value to the JSON string under
-** construction.
-*/
-static void jsonAppendValue(
- JsonString *p, /* Append to this JSON string */
- sqlite3_value *pValue /* Value to append */
-){
- switch( sqlite3_value_type(pValue) ){
- case SQLITE_NULL: {
- jsonAppendRaw(p, "null", 4);
- break;
- }
- case SQLITE_INTEGER:
- case SQLITE_FLOAT: {
- const char *z = (const char*)sqlite3_value_text(pValue);
- u32 n = (u32)sqlite3_value_bytes(pValue);
- jsonAppendRaw(p, z, n);
- break;
- }
- case SQLITE_TEXT: {
- const char *z = (const char*)sqlite3_value_text(pValue);
- u32 n = (u32)sqlite3_value_bytes(pValue);
- if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){
- jsonAppendRaw(p, z, n);
- }else{
- jsonAppendString(p, z, n);
- }
- break;
- }
- default: {
- if( p->bErr==0 ){
- sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
- p->bErr = 2;
- jsonReset(p);
- }
- break;
- }
- }
-}
-
-
-/* Make the JSON in p the result of the SQL function.
-*/
-static void jsonResult(JsonString *p){
- if( p->bErr==0 ){
- sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed,
- p->bStatic ? SQLITE_TRANSIENT : sqlite3_free,
- SQLITE_UTF8);
- jsonZero(p);
- }
- assert( p->bStatic );
-}
-
-/**************************************************************************
-** Utility routines for dealing with JsonNode and JsonParse objects
-**************************************************************************/
-
-/*
-** Return the number of consecutive JsonNode slots need to represent
-** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and
-** OBJECT types, the number might be larger.
-**
-** Appended elements are not counted. The value returned is the number
-** by which the JsonNode counter should increment in order to go to the
-** next peer value.
-*/
-static u32 jsonNodeSize(JsonNode *pNode){
- return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1;
-}
-
-/*
-** Reclaim all memory allocated by a JsonParse object. But do not
-** delete the JsonParse object itself.
-*/
-static void jsonParseReset(JsonParse *pParse){
- sqlite3_free(pParse->aNode);
- pParse->aNode = 0;
- pParse->nNode = 0;
- pParse->nAlloc = 0;
- sqlite3_free(pParse->aUp);
- pParse->aUp = 0;
-}
-
-/*
-** Free a JsonParse object that was obtained from sqlite3_malloc().
-*/
-static void jsonParseFree(JsonParse *pParse){
- jsonParseReset(pParse);
- sqlite3_free(pParse);
-}
-
-/*
-** Convert the JsonNode pNode into a pure JSON string and
-** append to pOut. Subsubstructure is also included. Return
-** the number of JsonNode objects that are encoded.
-*/
-static void jsonRenderNode(
- JsonNode *pNode, /* The node to render */
- JsonString *pOut, /* Write JSON here */
- sqlite3_value **aReplace /* Replacement values */
-){
- if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
- if( pNode->jnFlags & JNODE_REPLACE ){
- jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
- return;
- }
- pNode = pNode->u.pPatch;
- }
- switch( pNode->eType ){
- default: {
- assert( pNode->eType==JSON_NULL );
- jsonAppendRaw(pOut, "null", 4);
- break;
- }
- case JSON_TRUE: {
- jsonAppendRaw(pOut, "true", 4);
- break;
- }
- case JSON_FALSE: {
- jsonAppendRaw(pOut, "false", 5);
- break;
- }
- case JSON_STRING: {
- if( pNode->jnFlags & JNODE_RAW ){
- jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
- break;
- }
- /* Fall through into the next case */
- }
- case JSON_REAL:
- case JSON_INT: {
- jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n);
- break;
- }
- case JSON_ARRAY: {
- u32 j = 1;
- jsonAppendChar(pOut, '[');
- for(;;){
- while( j<=pNode->n ){
- if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){
- jsonAppendSeparator(pOut);
- jsonRenderNode(&pNode[j], pOut, aReplace);
- }
- j += jsonNodeSize(&pNode[j]);
- }
- if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
- pNode = &pNode[pNode->u.iAppend];
- j = 1;
- }
- jsonAppendChar(pOut, ']');
- break;
- }
- case JSON_OBJECT: {
- u32 j = 1;
- jsonAppendChar(pOut, '{');
- for(;;){
- while( j<=pNode->n ){
- if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){
- jsonAppendSeparator(pOut);
- jsonRenderNode(&pNode[j], pOut, aReplace);
- jsonAppendChar(pOut, ':');
- jsonRenderNode(&pNode[j+1], pOut, aReplace);
- }
- j += 1 + jsonNodeSize(&pNode[j+1]);
- }
- if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
- pNode = &pNode[pNode->u.iAppend];
- j = 1;
- }
- jsonAppendChar(pOut, '}');
- break;
- }
- }
-}
-
-/*
-** Return a JsonNode and all its descendents as a JSON string.
-*/
-static void jsonReturnJson(
- JsonNode *pNode, /* Node to return */
- sqlite3_context *pCtx, /* Return value for this function */
- sqlite3_value **aReplace /* Array of replacement values */
-){
- JsonString s;
- jsonInit(&s, pCtx);
- jsonRenderNode(pNode, &s, aReplace);
- jsonResult(&s);
- sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
-}
-
-/*
-** Make the JsonNode the return value of the function.
-*/
-static void jsonReturn(
- JsonNode *pNode, /* Node to return */
- sqlite3_context *pCtx, /* Return value for this function */
- sqlite3_value **aReplace /* Array of replacement values */
-){
- switch( pNode->eType ){
- default: {
- assert( pNode->eType==JSON_NULL );
- sqlite3_result_null(pCtx);
- break;
- }
- case JSON_TRUE: {
- sqlite3_result_int(pCtx, 1);
- break;
- }
- case JSON_FALSE: {
- sqlite3_result_int(pCtx, 0);
- break;
- }
- case JSON_INT: {
- sqlite3_int64 i = 0;
- const char *z = pNode->u.zJContent;
- if( z[0]=='-' ){ z++; }
- while( z[0]>='0' && z[0]<='9' ){
- unsigned v = *(z++) - '0';
- if( i>=LARGEST_INT64/10 ){
- if( i>LARGEST_INT64/10 ) goto int_as_real;
- if( z[0]>='0' && z[0]<='9' ) goto int_as_real;
- if( v==9 ) goto int_as_real;
- if( v==8 ){
- if( pNode->u.zJContent[0]=='-' ){
- sqlite3_result_int64(pCtx, SMALLEST_INT64);
- goto int_done;
- }else{
- goto int_as_real;
- }
- }
- }
- i = i*10 + v;
- }
- if( pNode->u.zJContent[0]=='-' ){ i = -i; }
- sqlite3_result_int64(pCtx, i);
- int_done:
- break;
- int_as_real: /* fall through to real */;
- }
- case JSON_REAL: {
- double r;
-#ifdef SQLITE_AMALGAMATION
- const char *z = pNode->u.zJContent;
- sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
-#else
- r = strtod(pNode->u.zJContent, 0);
-#endif
- sqlite3_result_double(pCtx, r);
- break;
- }
- case JSON_STRING: {
-#if 0 /* Never happens because JNODE_RAW is only set by json_set(),
- ** json_insert() and json_replace() and those routines do not
- ** call jsonReturn() */
- if( pNode->jnFlags & JNODE_RAW ){
- sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
- SQLITE_TRANSIENT);
- }else
-#endif
- assert( (pNode->jnFlags & JNODE_RAW)==0 );
- if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
- /* JSON formatted without any backslash-escapes */
- sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
- SQLITE_TRANSIENT);
- }else{
- /* Translate JSON formatted string into raw text */
- u32 i;
- u32 n = pNode->n;
- const char *z = pNode->u.zJContent;
- char *zOut;
- u32 j;
- zOut = sqlite3_malloc( n+1 );
- if( zOut==0 ){
- sqlite3_result_error_nomem(pCtx);
- break;
- }
- for(i=1, j=0; i<n-1; i++){
- char c = z[i];
- if( c!='\\' ){
- zOut[j++] = c;
- }else{
- c = z[++i];
- if( c=='u' ){
- u32 v = 0, k;
- for(k=0; k<4; i++, k++){
- assert( i<n-2 );
- c = z[i+1];
- assert( safe_isxdigit(c) );
- if( c<='9' ) v = v*16 + c - '0';
- else if( c<='F' ) v = v*16 + c - 'A' + 10;
- else v = v*16 + c - 'a' + 10;
- }
- if( v==0 ) break;
- if( v<=0x7f ){
- zOut[j++] = (char)v;
- }else if( v<=0x7ff ){
- zOut[j++] = (char)(0xc0 | (v>>6));
- zOut[j++] = 0x80 | (v&0x3f);
- }else{
- zOut[j++] = (char)(0xe0 | (v>>12));
- zOut[j++] = 0x80 | ((v>>6)&0x3f);
- zOut[j++] = 0x80 | (v&0x3f);
- }
- }else{
- if( c=='b' ){
- c = '\b';
- }else if( c=='f' ){
- c = '\f';
- }else if( c=='n' ){
- c = '\n';
- }else if( c=='r' ){
- c = '\r';
- }else if( c=='t' ){
- c = '\t';
- }
- zOut[j++] = c;
- }
- }
- }
- zOut[j] = 0;
- sqlite3_result_text(pCtx, zOut, j, sqlite3_free);
- }
- break;
- }
- case JSON_ARRAY:
- case JSON_OBJECT: {
- jsonReturnJson(pNode, pCtx, aReplace);
- break;
- }
- }
-}
-
-/* Forward reference */
-static int jsonParseAddNode(JsonParse*,u32,u32,const char*);
-
-/*
-** A macro to hint to the compiler that a function should not be
-** inlined.
-*/
-#if defined(__GNUC__)
-# define JSON_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER) && _MSC_VER>=1310
-# define JSON_NOINLINE __declspec(noinline)
-#else
-# define JSON_NOINLINE
-#endif
-
-
-static JSON_NOINLINE int jsonParseAddNodeExpand(
- JsonParse *pParse, /* Append the node to this object */
- u32 eType, /* Node type */
- u32 n, /* Content size or sub-node count */
- const char *zContent /* Content */
-){
- u32 nNew;
- JsonNode *pNew;
- assert( pParse->nNode>=pParse->nAlloc );
- if( pParse->oom ) return -1;
- nNew = pParse->nAlloc*2 + 10;
- pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
- if( pNew==0 ){
- pParse->oom = 1;
- return -1;
- }
- pParse->nAlloc = nNew;
- pParse->aNode = pNew;
- assert( pParse->nNode<pParse->nAlloc );
- return jsonParseAddNode(pParse, eType, n, zContent);
-}
-
-/*
-** Create a new JsonNode instance based on the arguments and append that
-** instance to the JsonParse. Return the index in pParse->aNode[] of the
-** new node, or -1 if a memory allocation fails.
-*/
-static int jsonParseAddNode(
- JsonParse *pParse, /* Append the node to this object */
- u32 eType, /* Node type */
- u32 n, /* Content size or sub-node count */
- const char *zContent /* Content */
-){
- JsonNode *p;
- if( pParse->nNode>=pParse->nAlloc ){
- return jsonParseAddNodeExpand(pParse, eType, n, zContent);
- }
- p = &pParse->aNode[pParse->nNode];
- p->eType = (u8)eType;
- p->jnFlags = 0;
- p->n = n;
- p->u.zJContent = zContent;
- return pParse->nNode++;
-}
-
-/*
-** Return true if z[] begins with 4 (or more) hexadecimal digits
-*/
-static int jsonIs4Hex(const char *z){
- int i;
- for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
- return 1;
-}
-
-/*
-** Parse a single JSON value which begins at pParse->zJson[i]. Return the
-** index of the first character past the end of the value parsed.
-**
-** Return negative for a syntax error. Special cases: return -2 if the
-** first non-whitespace character is '}' and return -3 if the first
-** non-whitespace character is ']'.
-*/
-static int jsonParseValue(JsonParse *pParse, u32 i){
- char c;
- u32 j;
- int iThis;
- int x;
- JsonNode *pNode;
- const char *z = pParse->zJson;
- while( safe_isspace(z[i]) ){ i++; }
- if( (c = z[i])=='{' ){
- /* Parse object */
- iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
- if( iThis<0 ) return -1;
- for(j=i+1;;j++){
- while( safe_isspace(z[j]) ){ j++; }
- if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
- x = jsonParseValue(pParse, j);
- if( x<0 ){
- pParse->iDepth--;
- if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
- return -1;
- }
- if( pParse->oom ) return -1;
- pNode = &pParse->aNode[pParse->nNode-1];
- if( pNode->eType!=JSON_STRING ) return -1;
- pNode->jnFlags |= JNODE_LABEL;
- j = x;
- while( safe_isspace(z[j]) ){ j++; }
- if( z[j]!=':' ) return -1;
- j++;
- x = jsonParseValue(pParse, j);
- pParse->iDepth--;
- if( x<0 ) return -1;
- j = x;
- while( safe_isspace(z[j]) ){ j++; }
- c = z[j];
- if( c==',' ) continue;
- if( c!='}' ) return -1;
- break;
- }
- pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
- return j+1;
- }else if( c=='[' ){
- /* Parse array */
- iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
- if( iThis<0 ) return -1;
- for(j=i+1;;j++){
- while( safe_isspace(z[j]) ){ j++; }
- if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
- x = jsonParseValue(pParse, j);
- pParse->iDepth--;
- if( x<0 ){
- if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
- return -1;
- }
- j = x;
- while( safe_isspace(z[j]) ){ j++; }
- c = z[j];
- if( c==',' ) continue;
- if( c!=']' ) return -1;
- break;
- }
- pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
- return j+1;
- }else if( c=='"' ){
- /* Parse string */
- u8 jnFlags = 0;
- j = i+1;
- for(;;){
- c = z[j];
- if( (c & ~0x1f)==0 ){
- /* Control characters are not allowed in strings */
- return -1;
- }
- if( c=='\\' ){
- c = z[++j];
- if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
- || c=='n' || c=='r' || c=='t'
- || (c=='u' && jsonIs4Hex(z+j+1)) ){
- jnFlags = JNODE_ESCAPE;
- }else{
- return -1;
- }
- }else if( c=='"' ){
- break;
- }
- j++;
- }
- jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]);
- if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags;
- return j+1;
- }else if( c=='n'
- && strncmp(z+i,"null",4)==0
- && !safe_isalnum(z[i+4]) ){
- jsonParseAddNode(pParse, JSON_NULL, 0, 0);
- return i+4;
- }else if( c=='t'
- && strncmp(z+i,"true",4)==0
- && !safe_isalnum(z[i+4]) ){
- jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
- return i+4;
- }else if( c=='f'
- && strncmp(z+i,"false",5)==0
- && !safe_isalnum(z[i+5]) ){
- jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
- return i+5;
- }else if( c=='-' || (c>='0' && c<='9') ){
- /* Parse number */
- u8 seenDP = 0;
- u8 seenE = 0;
- assert( '-' < '0' );
- if( c<='0' ){
- j = c=='-' ? i+1 : i;
- if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1;
- }
- j = i+1;
- for(;; j++){
- c = z[j];
- if( c>='0' && c<='9' ) continue;
- if( c=='.' ){
- if( z[j-1]=='-' ) return -1;
- if( seenDP ) return -1;
- seenDP = 1;
- continue;
- }
- if( c=='e' || c=='E' ){
- if( z[j-1]<'0' ) return -1;
- if( seenE ) return -1;
- seenDP = seenE = 1;
- c = z[j+1];
- if( c=='+' || c=='-' ){
- j++;
- c = z[j+1];
- }
- if( c<'0' || c>'9' ) return -1;
- continue;
- }
- break;
- }
- if( z[j-1]<'0' ) return -1;
- jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT,
- j - i, &z[i]);
- return j;
- }else if( c=='}' ){
- return -2; /* End of {...} */
- }else if( c==']' ){
- return -3; /* End of [...] */
- }else if( c==0 ){
- return 0; /* End of file */
- }else{
- return -1; /* Syntax error */
- }
-}
-
-/*
-** Parse a complete JSON string. Return 0 on success or non-zero if there
-** are any errors. If an error occurs, free all memory associated with
-** pParse.
-**
-** pParse is uninitialized when this routine is called.
-*/
-static int jsonParse(
- JsonParse *pParse, /* Initialize and fill this JsonParse object */
- sqlite3_context *pCtx, /* Report errors here */
- const char *zJson /* Input JSON text to be parsed */
-){
- int i;
- memset(pParse, 0, sizeof(*pParse));
- if( zJson==0 ) return 1;
- pParse->zJson = zJson;
- i = jsonParseValue(pParse, 0);
- if( pParse->oom ) i = -1;
- if( i>0 ){
- assert( pParse->iDepth==0 );
- while( safe_isspace(zJson[i]) ) i++;
- if( zJson[i] ) i = -1;
- }
- if( i<=0 ){
- if( pCtx!=0 ){
- if( pParse->oom ){
- sqlite3_result_error_nomem(pCtx);
- }else{
- sqlite3_result_error(pCtx, "malformed JSON", -1);
- }
- }
- jsonParseReset(pParse);
- return 1;
- }
- return 0;
-}
-
-/* Mark node i of pParse as being a child of iParent. Call recursively
-** to fill in all the descendants of node i.
-*/
-static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
- JsonNode *pNode = &pParse->aNode[i];
- u32 j;
- pParse->aUp[i] = iParent;
- switch( pNode->eType ){
- case JSON_ARRAY: {
- for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){
- jsonParseFillInParentage(pParse, i+j, i);
- }
- break;
- }
- case JSON_OBJECT: {
- for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){
- pParse->aUp[i+j] = i;
- jsonParseFillInParentage(pParse, i+j+1, i);
- }
- break;
- }
- default: {
- break;
- }
- }
-}
-
-/*
-** Compute the parentage of all nodes in a completed parse.
-*/
-static int jsonParseFindParents(JsonParse *pParse){
- u32 *aUp;
- assert( pParse->aUp==0 );
- aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode );
- if( aUp==0 ){
- pParse->oom = 1;
- return SQLITE_NOMEM;
- }
- jsonParseFillInParentage(pParse, 0, 0);
- return SQLITE_OK;
-}
-
-/*
-** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
-*/
-#define JSON_CACHE_ID (-429938)
-
-/*
-** Obtain a complete parse of the JSON found in the first argument
-** of the argv array. Use the sqlite3_get_auxdata() cache for this
-** parse if it is available. If the cache is not available or if it
-** is no longer valid, parse the JSON again and return the new parse,
-** and also register the new parse so that it will be available for
-** future sqlite3_get_auxdata() calls.
-*/
-static JsonParse *jsonParseCached(
- sqlite3_context *pCtx,
- sqlite3_value **argv
-){
- const char *zJson = (const char*)sqlite3_value_text(argv[0]);
- int nJson = sqlite3_value_bytes(argv[0]);
- JsonParse *p;
- if( zJson==0 ) return 0;
- p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID);
- if( p && p->nJson==nJson && memcmp(p->zJson,zJson,nJson)==0 ){
- p->nErr = 0;
- return p; /* The cached entry matches, so return it */
- }
- p = sqlite3_malloc( sizeof(*p) + nJson + 1 );
- if( p==0 ){
- sqlite3_result_error_nomem(pCtx);
- return 0;
- }
- memset(p, 0, sizeof(*p));
- p->zJson = (char*)&p[1];
- memcpy((char*)p->zJson, zJson, nJson+1);
- if( jsonParse(p, pCtx, p->zJson) ){
- sqlite3_free(p);
- return 0;
- }
- p->nJson = nJson;
- sqlite3_set_auxdata(pCtx, JSON_CACHE_ID, p, (void(*)(void*))jsonParseFree);
- return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID);
-}
-
-/*
-** Compare the OBJECT label at pNode against zKey,nKey. Return true on
-** a match.
-*/
-static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
- if( pNode->jnFlags & JNODE_RAW ){
- if( pNode->n!=nKey ) return 0;
- return strncmp(pNode->u.zJContent, zKey, nKey)==0;
- }else{
- if( pNode->n!=nKey+2 ) return 0;
- return strncmp(pNode->u.zJContent+1, zKey, nKey)==0;
- }
-}
-
-/* forward declaration */
-static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**);
-
-/*
-** Search along zPath to find the node specified. Return a pointer
-** to that node, or NULL if zPath is malformed or if there is no such
-** node.
-**
-** If pApnd!=0, then try to append new nodes to complete zPath if it is
-** possible to do so and if no existing node corresponds to zPath. If
-** new nodes are appended *pApnd is set to 1.
-*/
-static JsonNode *jsonLookupStep(
- JsonParse *pParse, /* The JSON to search */
- u32 iRoot, /* Begin the search at this node */
- const char *zPath, /* The path to search */
- int *pApnd, /* Append nodes to complete path if not NULL */
- const char **pzErr /* Make *pzErr point to any syntax error in zPath */
-){
- u32 i, j, nKey;
- const char *zKey;
- JsonNode *pRoot = &pParse->aNode[iRoot];
- if( zPath[0]==0 ) return pRoot;
- if( zPath[0]=='.' ){
- if( pRoot->eType!=JSON_OBJECT ) return 0;
- zPath++;
- if( zPath[0]=='"' ){
- zKey = zPath + 1;
- for(i=1; zPath[i] && zPath[i]!='"'; i++){}
- nKey = i-1;
- if( zPath[i] ){
- i++;
- }else{
- *pzErr = zPath;
- return 0;
- }
- }else{
- zKey = zPath;
- for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
- nKey = i;
- }
- if( nKey==0 ){
- *pzErr = zPath;
- return 0;
- }
- j = 1;
- for(;;){
- while( j<=pRoot->n ){
- if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
- return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
- }
- j++;
- j += jsonNodeSize(&pRoot[j]);
- }
- if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
- iRoot += pRoot->u.iAppend;
- pRoot = &pParse->aNode[iRoot];
- j = 1;
- }
- if( pApnd ){
- u32 iStart, iLabel;
- JsonNode *pNode;
- iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
- iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath);
- zPath += i;
- pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
- if( pParse->oom ) return 0;
- if( pNode ){
- pRoot = &pParse->aNode[iRoot];
- pRoot->u.iAppend = iStart - iRoot;
- pRoot->jnFlags |= JNODE_APPEND;
- pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
- }
- return pNode;
- }
- }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){
- if( pRoot->eType!=JSON_ARRAY ) return 0;
- i = 0;
- j = 1;
- while( safe_isdigit(zPath[j]) ){
- i = i*10 + zPath[j] - '0';
- j++;
- }
- if( zPath[j]!=']' ){
- *pzErr = zPath;
- return 0;
- }
- zPath += j + 1;
- j = 1;
- for(;;){
- while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
- if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--;
- j += jsonNodeSize(&pRoot[j]);
- }
- if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
- iRoot += pRoot->u.iAppend;
- pRoot = &pParse->aNode[iRoot];
- j = 1;
- }
- if( j<=pRoot->n ){
- return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr);
- }
- if( i==0 && pApnd ){
- u32 iStart;
- JsonNode *pNode;
- iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0);
- pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
- if( pParse->oom ) return 0;
- if( pNode ){
- pRoot = &pParse->aNode[iRoot];
- pRoot->u.iAppend = iStart - iRoot;
- pRoot->jnFlags |= JNODE_APPEND;
- }
- return pNode;
- }
- }else{
- *pzErr = zPath;
- }
- return 0;
-}
-
-/*
-** Append content to pParse that will complete zPath. Return a pointer
-** to the inserted node, or return NULL if the append fails.
-*/
-static JsonNode *jsonLookupAppend(
- JsonParse *pParse, /* Append content to the JSON parse */
- const char *zPath, /* Description of content to append */
- int *pApnd, /* Set this flag to 1 */
- const char **pzErr /* Make this point to any syntax error */
-){
- *pApnd = 1;
- if( zPath[0]==0 ){
- jsonParseAddNode(pParse, JSON_NULL, 0, 0);
- return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1];
- }
- if( zPath[0]=='.' ){
- jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
- }else if( strncmp(zPath,"[0]",3)==0 ){
- jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
- }else{
- return 0;
- }
- if( pParse->oom ) return 0;
- return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr);
-}
-
-/*
-** Return the text of a syntax error message on a JSON path. Space is
-** obtained from sqlite3_malloc().
-*/
-static char *jsonPathSyntaxError(const char *zErr){
- return sqlite3_mprintf("JSON path error near '%q'", zErr);
-}
-
-/*
-** Do a node lookup using zPath. Return a pointer to the node on success.
-** Return NULL if not found or if there is an error.
-**
-** On an error, write an error message into pCtx and increment the
-** pParse->nErr counter.
-**
-** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if
-** nodes are appended.
-*/
-static JsonNode *jsonLookup(
- JsonParse *pParse, /* The JSON to search */
- const char *zPath, /* The path to search */
- int *pApnd, /* Append nodes to complete path if not NULL */
- sqlite3_context *pCtx /* Report errors here, if not NULL */
-){
- const char *zErr = 0;
- JsonNode *pNode = 0;
- char *zMsg;
-
- if( zPath==0 ) return 0;
- if( zPath[0]!='$' ){
- zErr = zPath;
- goto lookup_err;
- }
- zPath++;
- pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr);
- if( zErr==0 ) return pNode;
-
-lookup_err:
- pParse->nErr++;
- assert( zErr!=0 && pCtx!=0 );
- zMsg = jsonPathSyntaxError(zErr);
- if( zMsg ){
- sqlite3_result_error(pCtx, zMsg, -1);
- sqlite3_free(zMsg);
- }else{
- sqlite3_result_error_nomem(pCtx);
- }
- return 0;
-}
-
-
-/*
-** Report the wrong number of arguments for json_insert(), json_replace()
-** or json_set().
-*/
-static void jsonWrongNumArgs(
- sqlite3_context *pCtx,
- const char *zFuncName
-){
- char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments",
- zFuncName);
- sqlite3_result_error(pCtx, zMsg, -1);
- sqlite3_free(zMsg);
-}
-
-/*
-** Mark all NULL entries in the Object passed in as JNODE_REMOVE.
-*/
-static void jsonRemoveAllNulls(JsonNode *pNode){
- int i, n;
- assert( pNode->eType==JSON_OBJECT );
- n = pNode->n;
- for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){
- switch( pNode[i].eType ){
- case JSON_NULL:
- pNode[i].jnFlags |= JNODE_REMOVE;
- break;
- case JSON_OBJECT:
- jsonRemoveAllNulls(&pNode[i]);
- break;
- }
- }
-}
-
-
-/****************************************************************************
-** SQL functions used for testing and debugging
-****************************************************************************/
-
-#ifdef SQLITE_DEBUG
-/*
-** The json_parse(JSON) function returns a string which describes
-** a parse of the JSON provided. Or it returns NULL if JSON is not
-** well-formed.
-*/
-static void jsonParseFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonString s; /* Output string - not real JSON */
- JsonParse x; /* The parse */
- u32 i;
-
- assert( argc==1 );
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- jsonParseFindParents(&x);
- jsonInit(&s, ctx);
- for(i=0; i<x.nNode; i++){
- const char *zType;
- if( x.aNode[i].jnFlags & JNODE_LABEL ){
- assert( x.aNode[i].eType==JSON_STRING );
- zType = "label";
- }else{
- zType = jsonType[x.aNode[i].eType];
- }
- jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
- i, zType, x.aNode[i].n, x.aUp[i]);
- if( x.aNode[i].u.zJContent!=0 ){
- jsonAppendRaw(&s, " ", 1);
- jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
- }
- jsonAppendRaw(&s, "\n", 1);
- }
- jsonParseReset(&x);
- jsonResult(&s);
-}
-
-/*
-** The json_test1(JSON) function return true (1) if the input is JSON
-** text generated by another json function. It returns (0) if the input
-** is not known to be JSON.
-*/
-static void jsonTest1Func(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- UNUSED_PARAM(argc);
- sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
-}
-#endif /* SQLITE_DEBUG */
-
-/****************************************************************************
-** Scalar SQL function implementations
-****************************************************************************/
-
-/*
-** Implementation of the json_QUOTE(VALUE) function. Return a JSON value
-** corresponding to the SQL value input. Mostly this means putting
-** double-quotes around strings and returning the unquoted string "null"
-** when given a NULL input.
-*/
-static void jsonQuoteFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonString jx;
- UNUSED_PARAM(argc);
-
- jsonInit(&jx, ctx);
- jsonAppendValue(&jx, argv[0]);
- jsonResult(&jx);
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-/*
-** Implementation of the json_array(VALUE,...) function. Return a JSON
-** array that contains all values given in arguments. Or if any argument
-** is a BLOB, throw an error.
-*/
-static void jsonArrayFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- int i;
- JsonString jx;
-
- jsonInit(&jx, ctx);
- jsonAppendChar(&jx, '[');
- for(i=0; i<argc; i++){
- jsonAppendSeparator(&jx);
- jsonAppendValue(&jx, argv[i]);
- }
- jsonAppendChar(&jx, ']');
- jsonResult(&jx);
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-
-/*
-** json_array_length(JSON)
-** json_array_length(JSON, PATH)
-**
-** Return the number of elements in the top-level JSON array.
-** Return 0 if the input is not a well-formed JSON array.
-*/
-static void jsonArrayLengthFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse *p; /* The parse */
- sqlite3_int64 n = 0;
- u32 i;
- JsonNode *pNode;
-
- p = jsonParseCached(ctx, argv);
- if( p==0 ) return;
- assert( p->nNode );
- if( argc==2 ){
- const char *zPath = (const char*)sqlite3_value_text(argv[1]);
- pNode = jsonLookup(p, zPath, 0, ctx);
- }else{
- pNode = p->aNode;
- }
- if( pNode==0 ){
- return;
- }
- if( pNode->eType==JSON_ARRAY ){
- assert( (pNode->jnFlags & JNODE_APPEND)==0 );
- for(i=1; i<=pNode->n; n++){
- i += jsonNodeSize(&pNode[i]);
- }
- }
- sqlite3_result_int64(ctx, n);
-}
-
-/*
-** json_extract(JSON, PATH, ...)
-**
-** Return the element described by PATH. Return NULL if there is no
-** PATH element. If there are multiple PATHs, then return a JSON array
-** with the result from each path. Throw an error if the JSON or any PATH
-** is malformed.
-*/
-static void jsonExtractFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse *p; /* The parse */
- JsonNode *pNode;
- const char *zPath;
- JsonString jx;
- int i;
-
- if( argc<2 ) return;
- p = jsonParseCached(ctx, argv);
- if( p==0 ) return;
- jsonInit(&jx, ctx);
- jsonAppendChar(&jx, '[');
- for(i=1; i<argc; i++){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- pNode = jsonLookup(p, zPath, 0, ctx);
- if( p->nErr ) break;
- if( argc>2 ){
- jsonAppendSeparator(&jx);
- if( pNode ){
- jsonRenderNode(pNode, &jx, 0);
- }else{
- jsonAppendRaw(&jx, "null", 4);
- }
- }else if( pNode ){
- jsonReturn(pNode, ctx, 0);
- }
- }
- if( argc>2 && i==argc ){
- jsonAppendChar(&jx, ']');
- jsonResult(&jx);
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
- }
- jsonReset(&jx);
-}
-
-/* This is the RFC 7396 MergePatch algorithm.
-*/
-static JsonNode *jsonMergePatch(
- JsonParse *pParse, /* The JSON parser that contains the TARGET */
- u32 iTarget, /* Node of the TARGET in pParse */
- JsonNode *pPatch /* The PATCH */
-){
- u32 i, j;
- u32 iRoot;
- JsonNode *pTarget;
- if( pPatch->eType!=JSON_OBJECT ){
- return pPatch;
- }
- assert( iTarget>=0 && iTarget<pParse->nNode );
- pTarget = &pParse->aNode[iTarget];
- assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
- if( pTarget->eType!=JSON_OBJECT ){
- jsonRemoveAllNulls(pPatch);
- return pPatch;
- }
- iRoot = iTarget;
- for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
- u32 nKey;
- const char *zKey;
- assert( pPatch[i].eType==JSON_STRING );
- assert( pPatch[i].jnFlags & JNODE_LABEL );
- nKey = pPatch[i].n;
- zKey = pPatch[i].u.zJContent;
- assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
- for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
- assert( pTarget[j].eType==JSON_STRING );
- assert( pTarget[j].jnFlags & JNODE_LABEL );
- assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
- if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
- if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
- if( pPatch[i+1].eType==JSON_NULL ){
- pTarget[j+1].jnFlags |= JNODE_REMOVE;
- }else{
- JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
- if( pNew==0 ) return 0;
- pTarget = &pParse->aNode[iTarget];
- if( pNew!=&pTarget[j+1] ){
- pTarget[j+1].u.pPatch = pNew;
- pTarget[j+1].jnFlags |= JNODE_PATCH;
- }
- }
- break;
- }
- }
- if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
- int iStart, iPatch;
- iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
- jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
- iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
- if( pParse->oom ) return 0;
- jsonRemoveAllNulls(pPatch);
- pTarget = &pParse->aNode[iTarget];
- pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
- pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
- iRoot = iStart;
- pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
- pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
- }
- }
- return pTarget;
-}
-
-/*
-** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON
-** object that is the result of running the RFC 7396 MergePatch() algorithm
-** on the two arguments.
-*/
-static void jsonPatchFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The JSON that is being patched */
- JsonParse y; /* The patch */
- JsonNode *pResult; /* The result of the merge */
-
- UNUSED_PARAM(argc);
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
- jsonParseReset(&x);
- return;
- }
- pResult = jsonMergePatch(&x, 0, y.aNode);
- assert( pResult!=0 || x.oom );
- if( pResult ){
- jsonReturnJson(pResult, ctx, 0);
- }else{
- sqlite3_result_error_nomem(ctx);
- }
- jsonParseReset(&x);
- jsonParseReset(&y);
-}
-
-
-/*
-** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON
-** object that contains all name/value given in arguments. Or if any name
-** is not a string or if any value is a BLOB, throw an error.
-*/
-static void jsonObjectFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- int i;
- JsonString jx;
- const char *z;
- u32 n;
-
- if( argc&1 ){
- sqlite3_result_error(ctx, "json_object() requires an even number "
- "of arguments", -1);
- return;
- }
- jsonInit(&jx, ctx);
- jsonAppendChar(&jx, '{');
- for(i=0; i<argc; i+=2){
- if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){
- sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1);
- jsonReset(&jx);
- return;
- }
- jsonAppendSeparator(&jx);
- z = (const char*)sqlite3_value_text(argv[i]);
- n = (u32)sqlite3_value_bytes(argv[i]);
- jsonAppendString(&jx, z, n);
- jsonAppendChar(&jx, ':');
- jsonAppendValue(&jx, argv[i+1]);
- }
- jsonAppendChar(&jx, '}');
- jsonResult(&jx);
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-
-/*
-** json_remove(JSON, PATH, ...)
-**
-** Remove the named elements from JSON and return the result. malformed
-** JSON or PATH arguments result in an error.
-*/
-static void jsonRemoveFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- JsonNode *pNode;
- const char *zPath;
- u32 i;
-
- if( argc<1 ) return;
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
- for(i=1; i<(u32)argc; i++){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- if( zPath==0 ) goto remove_done;
- pNode = jsonLookup(&x, zPath, 0, ctx);
- if( x.nErr ) goto remove_done;
- if( pNode ) pNode->jnFlags |= JNODE_REMOVE;
- }
- if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){
- jsonReturnJson(x.aNode, ctx, 0);
- }
-remove_done:
- jsonParseReset(&x);
-}
-
-/*
-** json_replace(JSON, PATH, VALUE, ...)
-**
-** Replace the value at PATH with VALUE. If PATH does not already exist,
-** this routine is a no-op. If JSON or PATH is malformed, throw an error.
-*/
-static void jsonReplaceFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- JsonNode *pNode;
- const char *zPath;
- u32 i;
-
- if( argc<1 ) return;
- if( (argc&1)==0 ) {
- jsonWrongNumArgs(ctx, "replace");
- return;
- }
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
- for(i=1; i<(u32)argc; i+=2){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- pNode = jsonLookup(&x, zPath, 0, ctx);
- if( x.nErr ) goto replace_err;
- if( pNode ){
- pNode->jnFlags |= (u8)JNODE_REPLACE;
- pNode->u.iReplace = i + 1;
- }
- }
- if( x.aNode[0].jnFlags & JNODE_REPLACE ){
- sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
- }else{
- jsonReturnJson(x.aNode, ctx, argv);
- }
-replace_err:
- jsonParseReset(&x);
-}
-
-/*
-** json_set(JSON, PATH, VALUE, ...)
-**
-** Set the value at PATH to VALUE. Create the PATH if it does not already
-** exist. Overwrite existing values that do exist.
-** If JSON or PATH is malformed, throw an error.
-**
-** json_insert(JSON, PATH, VALUE, ...)
-**
-** Create PATH and initialize it to VALUE. If PATH already exists, this
-** routine is a no-op. If JSON or PATH is malformed, throw an error.
-*/
-static void jsonSetFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- JsonNode *pNode;
- const char *zPath;
- u32 i;
- int bApnd;
- int bIsSet = *(int*)sqlite3_user_data(ctx);
-
- if( argc<1 ) return;
- if( (argc&1)==0 ) {
- jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
- return;
- }
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
- for(i=1; i<(u32)argc; i+=2){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- bApnd = 0;
- pNode = jsonLookup(&x, zPath, &bApnd, ctx);
- if( x.oom ){
- sqlite3_result_error_nomem(ctx);
- goto jsonSetDone;
- }else if( x.nErr ){
- goto jsonSetDone;
- }else if( pNode && (bApnd || bIsSet) ){
- pNode->jnFlags |= (u8)JNODE_REPLACE;
- pNode->u.iReplace = i + 1;
- }
- }
- if( x.aNode[0].jnFlags & JNODE_REPLACE ){
- sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
- }else{
- jsonReturnJson(x.aNode, ctx, argv);
- }
-jsonSetDone:
- jsonParseReset(&x);
-}
-
-/*
-** json_type(JSON)
-** json_type(JSON, PATH)
-**
-** Return the top-level "type" of a JSON string. Throw an error if
-** either the JSON or PATH inputs are not well-formed.
-*/
-static void jsonTypeFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- const char *zPath;
- JsonNode *pNode;
-
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
- if( argc==2 ){
- zPath = (const char*)sqlite3_value_text(argv[1]);
- pNode = jsonLookup(&x, zPath, 0, ctx);
- }else{
- pNode = x.aNode;
- }
- if( pNode ){
- sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC);
- }
- jsonParseReset(&x);
-}
-
-/*
-** json_valid(JSON)
-**
-** Return 1 if JSON is a well-formed JSON string according to RFC-7159.
-** Return 0 otherwise.
-*/
-static void jsonValidFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- int rc = 0;
-
- UNUSED_PARAM(argc);
- if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){
- rc = 1;
- }
- jsonParseReset(&x);
- sqlite3_result_int(ctx, rc);
-}
-
-
-/****************************************************************************
-** Aggregate SQL function implementations
-****************************************************************************/
-/*
-** json_group_array(VALUE)
-**
-** Return a JSON array composed of all values in the aggregate.
-*/
-static void jsonArrayStep(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonString *pStr;
- UNUSED_PARAM(argc);
- pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
- if( pStr ){
- if( pStr->zBuf==0 ){
- jsonInit(pStr, ctx);
- jsonAppendChar(pStr, '[');
- }else{
- jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
- }
- jsonAppendValue(pStr, argv[0]);
- }
-}
-static void jsonArrayFinal(sqlite3_context *ctx){
- JsonString *pStr;
- pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
- if( pStr ){
- pStr->pCtx = ctx;
- jsonAppendChar(pStr, ']');
- if( pStr->bErr ){
- if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
- assert( pStr->bStatic );
- }else{
- sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
- pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
- pStr->bStatic = 1;
- }
- }else{
- sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
- }
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-/*
-** json_group_obj(NAME,VALUE)
-**
-** Return a JSON object composed of all names and values in the aggregate.
-*/
-static void jsonObjectStep(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonString *pStr;
- const char *z;
- u32 n;
- UNUSED_PARAM(argc);
- pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
- if( pStr ){
- if( pStr->zBuf==0 ){
- jsonInit(pStr, ctx);
- jsonAppendChar(pStr, '{');
- }else{
- jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
- }
- z = (const char*)sqlite3_value_text(argv[0]);
- n = (u32)sqlite3_value_bytes(argv[0]);
- jsonAppendString(pStr, z, n);
- jsonAppendChar(pStr, ':');
- jsonAppendValue(pStr, argv[1]);
- }
-}
-static void jsonObjectFinal(sqlite3_context *ctx){
- JsonString *pStr;
- pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
- if( pStr ){
- jsonAppendChar(pStr, '}');
- if( pStr->bErr ){
- if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
- assert( pStr->bStatic );
- }else{
- sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
- pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
- pStr->bStatic = 1;
- }
- }else{
- sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
- }
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/****************************************************************************
-** The json_each virtual table
-****************************************************************************/
-typedef struct JsonEachCursor JsonEachCursor;
-struct JsonEachCursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- u32 iRowid; /* The rowid */
- u32 iBegin; /* The first node of the scan */
- u32 i; /* Index in sParse.aNode[] of current row */
- u32 iEnd; /* EOF when i equals or exceeds this value */
- u8 eType; /* Type of top-level element */
- u8 bRecursive; /* True for json_tree(). False for json_each() */
- char *zJson; /* Input JSON */
- char *zRoot; /* Path by which to filter zJson */
- JsonParse sParse; /* Parse of the input JSON */
-};
-
-/* Constructor for the json_each virtual table */
-static int jsonEachConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3_vtab *pNew;
- int rc;
-
-/* Column numbers */
-#define JEACH_KEY 0
-#define JEACH_VALUE 1
-#define JEACH_TYPE 2
-#define JEACH_ATOM 3
-#define JEACH_ID 4
-#define JEACH_PARENT 5
-#define JEACH_FULLKEY 6
-#define JEACH_PATH 7
-#define JEACH_JSON 8
-#define JEACH_ROOT 9
-
- UNUSED_PARAM(pzErr);
- UNUSED_PARAM(argv);
- UNUSED_PARAM(argc);
- UNUSED_PARAM(pAux);
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
- "json HIDDEN,root HIDDEN)");
- if( rc==SQLITE_OK ){
- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- }
- return rc;
-}
-
-/* destructor for json_each virtual table */
-static int jsonEachDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/* constructor for a JsonEachCursor object for json_each(). */
-static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- JsonEachCursor *pCur;
-
- UNUSED_PARAM(p);
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/* constructor for a JsonEachCursor object for json_tree(). */
-static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- int rc = jsonEachOpenEach(p, ppCursor);
- if( rc==SQLITE_OK ){
- JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor;
- pCur->bRecursive = 1;
- }
- return rc;
-}
-
-/* Reset a JsonEachCursor back to its original state. Free any memory
-** held. */
-static void jsonEachCursorReset(JsonEachCursor *p){
- sqlite3_free(p->zJson);
- sqlite3_free(p->zRoot);
- jsonParseReset(&p->sParse);
- p->iRowid = 0;
- p->i = 0;
- p->iEnd = 0;
- p->eType = 0;
- p->zJson = 0;
- p->zRoot = 0;
-}
-
-/* Destructor for a jsonEachCursor object */
-static int jsonEachClose(sqlite3_vtab_cursor *cur){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- jsonEachCursorReset(p);
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-/* Return TRUE if the jsonEachCursor object has been advanced off the end
-** of the JSON object */
-static int jsonEachEof(sqlite3_vtab_cursor *cur){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- return p->i >= p->iEnd;
-}
-
-/* Advance the cursor to the next element for json_tree() */
-static int jsonEachNext(sqlite3_vtab_cursor *cur){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- if( p->bRecursive ){
- if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++;
- p->i++;
- p->iRowid++;
- if( p->i<p->iEnd ){
- u32 iUp = p->sParse.aUp[p->i];
- JsonNode *pUp = &p->sParse.aNode[iUp];
- p->eType = pUp->eType;
- if( pUp->eType==JSON_ARRAY ){
- if( iUp==p->i-1 ){
- pUp->u.iKey = 0;
- }else{
- pUp->u.iKey++;
- }
- }
- }
- }else{
- switch( p->eType ){
- case JSON_ARRAY: {
- p->i += jsonNodeSize(&p->sParse.aNode[p->i]);
- p->iRowid++;
- break;
- }
- case JSON_OBJECT: {
- p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]);
- p->iRowid++;
- break;
- }
- default: {
- p->i = p->iEnd;
- break;
- }
- }
- }
- return SQLITE_OK;
-}
-
-/* Append the name of the path for element i to pStr
-*/
-static void jsonEachComputePath(
- JsonEachCursor *p, /* The cursor */
- JsonString *pStr, /* Write the path here */
- u32 i /* Path to this element */
-){
- JsonNode *pNode, *pUp;
- u32 iUp;
- if( i==0 ){
- jsonAppendChar(pStr, '$');
- return;
- }
- iUp = p->sParse.aUp[i];
- jsonEachComputePath(p, pStr, iUp);
- pNode = &p->sParse.aNode[i];
- pUp = &p->sParse.aNode[iUp];
- if( pUp->eType==JSON_ARRAY ){
- jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
- }else{
- assert( pUp->eType==JSON_OBJECT );
- if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
- assert( pNode->eType==JSON_STRING );
- assert( pNode->jnFlags & JNODE_LABEL );
- jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
- }
-}
-
-/* Return the value of a column */
-static int jsonEachColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- JsonNode *pThis = &p->sParse.aNode[p->i];
- switch( i ){
- case JEACH_KEY: {
- if( p->i==0 ) break;
- if( p->eType==JSON_OBJECT ){
- jsonReturn(pThis, ctx, 0);
- }else if( p->eType==JSON_ARRAY ){
- u32 iKey;
- if( p->bRecursive ){
- if( p->iRowid==0 ) break;
- iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
- }else{
- iKey = p->iRowid;
- }
- sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
- }
- break;
- }
- case JEACH_VALUE: {
- if( pThis->jnFlags & JNODE_LABEL ) pThis++;
- jsonReturn(pThis, ctx, 0);
- break;
- }
- case JEACH_TYPE: {
- if( pThis->jnFlags & JNODE_LABEL ) pThis++;
- sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
- break;
- }
- case JEACH_ATOM: {
- if( pThis->jnFlags & JNODE_LABEL ) pThis++;
- if( pThis->eType>=JSON_ARRAY ) break;
- jsonReturn(pThis, ctx, 0);
- break;
- }
- case JEACH_ID: {
- sqlite3_result_int64(ctx,
- (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0));
- break;
- }
- case JEACH_PARENT: {
- if( p->i>p->iBegin && p->bRecursive ){
- sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]);
- }
- break;
- }
- case JEACH_FULLKEY: {
- JsonString x;
- jsonInit(&x, ctx);
- if( p->bRecursive ){
- jsonEachComputePath(p, &x, p->i);
- }else{
- if( p->zRoot ){
- jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
- }else{
- jsonAppendChar(&x, '$');
- }
- if( p->eType==JSON_ARRAY ){
- jsonPrintf(30, &x, "[%d]", p->iRowid);
- }else if( p->eType==JSON_OBJECT ){
- jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
- }
- }
- jsonResult(&x);
- break;
- }
- case JEACH_PATH: {
- if( p->bRecursive ){
- JsonString x;
- jsonInit(&x, ctx);
- jsonEachComputePath(p, &x, p->sParse.aUp[p->i]);
- jsonResult(&x);
- break;
- }
- /* For json_each() path and root are the same so fall through
- ** into the root case */
- }
- default: {
- const char *zRoot = p->zRoot;
- if( zRoot==0 ) zRoot = "$";
- sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
- break;
- }
- case JEACH_JSON: {
- assert( i==JEACH_JSON );
- sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/* Return the current rowid value */
-static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- *pRowid = p->iRowid;
- return SQLITE_OK;
-}
-
-/* The query strategy is to look for an equality constraint on the json
-** column. Without such a constraint, the table cannot operate. idxNum is
-** 1 if the constraint is found, 3 if the constraint and zRoot are found,
-** and 0 otherwise.
-*/
-static int jsonEachBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i;
- int jsonIdx = -1;
- int rootIdx = -1;
- const struct sqlite3_index_constraint *pConstraint;
-
- UNUSED_PARAM(tab);
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case JEACH_JSON: jsonIdx = i; break;
- case JEACH_ROOT: rootIdx = i; break;
- default: /* no-op */ break;
- }
- }
- if( jsonIdx<0 ){
- pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = 1e99;
- }else{
- pIdxInfo->estimatedCost = 1.0;
- pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1;
- pIdxInfo->aConstraintUsage[jsonIdx].omit = 1;
- if( rootIdx<0 ){
- pIdxInfo->idxNum = 1;
- }else{
- pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2;
- pIdxInfo->aConstraintUsage[rootIdx].omit = 1;
- pIdxInfo->idxNum = 3;
- }
- }
- return SQLITE_OK;
-}
-
-/* Start a search on a new JSON string */
-static int jsonEachFilter(
- sqlite3_vtab_cursor *cur,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- const char *z;
- const char *zRoot = 0;
- sqlite3_int64 n;
-
- UNUSED_PARAM(idxStr);
- UNUSED_PARAM(argc);
- jsonEachCursorReset(p);
- if( idxNum==0 ) return SQLITE_OK;
- z = (const char*)sqlite3_value_text(argv[0]);
- if( z==0 ) return SQLITE_OK;
- n = sqlite3_value_bytes(argv[0]);
- p->zJson = sqlite3_malloc64( n+1 );
- if( p->zJson==0 ) return SQLITE_NOMEM;
- memcpy(p->zJson, z, (size_t)n+1);
- if( jsonParse(&p->sParse, 0, p->zJson) ){
- int rc = SQLITE_NOMEM;
- if( p->sParse.oom==0 ){
- sqlite3_free(cur->pVtab->zErrMsg);
- cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
- if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR;
- }
- jsonEachCursorReset(p);
- return rc;
- }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){
- jsonEachCursorReset(p);
- return SQLITE_NOMEM;
- }else{
- JsonNode *pNode = 0;
- if( idxNum==3 ){
- const char *zErr = 0;
- zRoot = (const char*)sqlite3_value_text(argv[1]);
- if( zRoot==0 ) return SQLITE_OK;
- n = sqlite3_value_bytes(argv[1]);
- p->zRoot = sqlite3_malloc64( n+1 );
- if( p->zRoot==0 ) return SQLITE_NOMEM;
- memcpy(p->zRoot, zRoot, (size_t)n+1);
- if( zRoot[0]!='$' ){
- zErr = zRoot;
- }else{
- pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr);
- }
- if( zErr ){
- sqlite3_free(cur->pVtab->zErrMsg);
- cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr);
- jsonEachCursorReset(p);
- return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
- }else if( pNode==0 ){
- return SQLITE_OK;
- }
- }else{
- pNode = p->sParse.aNode;
- }
- p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
- p->eType = pNode->eType;
- if( p->eType>=JSON_ARRAY ){
- pNode->u.iKey = 0;
- p->iEnd = p->i + pNode->n + 1;
- if( p->bRecursive ){
- p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
- if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
- p->i--;
- }
- }else{
- p->i++;
- }
- }else{
- p->iEnd = p->i+1;
- }
- }
- return SQLITE_OK;
-}
-
-/* The methods of the json_each virtual table */
-static sqlite3_module jsonEachModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- jsonEachConnect, /* xConnect */
- jsonEachBestIndex, /* xBestIndex */
- jsonEachDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- jsonEachOpenEach, /* xOpen - open a cursor */
- jsonEachClose, /* xClose - close a cursor */
- jsonEachFilter, /* xFilter - configure scan constraints */
- jsonEachNext, /* xNext - advance a cursor */
- jsonEachEof, /* xEof - check for end of scan */
- jsonEachColumn, /* xColumn - read data */
- jsonEachRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-
-/* The methods of the json_tree virtual table. */
-static sqlite3_module jsonTreeModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- jsonEachConnect, /* xConnect */
- jsonEachBestIndex, /* xBestIndex */
- jsonEachDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- jsonEachOpenTree, /* xOpen - open a cursor */
- jsonEachClose, /* xClose - close a cursor */
- jsonEachFilter, /* xFilter - configure scan constraints */
- jsonEachNext, /* xNext - advance a cursor */
- jsonEachEof, /* xEof - check for end of scan */
- jsonEachColumn, /* xColumn - read data */
- jsonEachRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/****************************************************************************
-** The following routines are the only publically visible identifiers in this
-** file. Call the following routines in order to register the various SQL
-** functions and the virtual table implemented by this file.
-****************************************************************************/
-
-int sqlite3Json1Init(sqlite3 *db){
- int rc = SQLITE_OK;
- unsigned int i;
- static const struct {
- const char *zName;
- int nArg;
- int flag;
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
- } aFunc[] = {
- { "json", 1, 0, jsonRemoveFunc },
- { "json_array", -1, 0, jsonArrayFunc },
- { "json_array_length", 1, 0, jsonArrayLengthFunc },
- { "json_array_length", 2, 0, jsonArrayLengthFunc },
- { "json_extract", -1, 0, jsonExtractFunc },
- { "json_insert", -1, 0, jsonSetFunc },
- { "json_object", -1, 0, jsonObjectFunc },
- { "json_patch", 2, 0, jsonPatchFunc },
- { "json_quote", 1, 0, jsonQuoteFunc },
- { "json_remove", -1, 0, jsonRemoveFunc },
- { "json_replace", -1, 0, jsonReplaceFunc },
- { "json_set", -1, 1, jsonSetFunc },
- { "json_type", 1, 0, jsonTypeFunc },
- { "json_type", 2, 0, jsonTypeFunc },
- { "json_valid", 1, 0, jsonValidFunc },
-
-#if SQLITE_DEBUG
- /* DEBUG and TESTING functions */
- { "json_parse", 1, 0, jsonParseFunc },
- { "json_test1", 1, 0, jsonTest1Func },
-#endif
- };
- static const struct {
- const char *zName;
- int nArg;
- void (*xStep)(sqlite3_context*,int,sqlite3_value**);
- void (*xFinal)(sqlite3_context*);
- } aAgg[] = {
- { "json_group_array", 1, jsonArrayStep, jsonArrayFinal },
- { "json_group_object", 2, jsonObjectStep, jsonObjectFinal },
- };
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- static const struct {
- const char *zName;
- sqlite3_module *pModule;
- } aMod[] = {
- { "json_each", &jsonEachModule },
- { "json_tree", &jsonTreeModule },
- };
-#endif
- for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
- rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
- SQLITE_UTF8 | SQLITE_DETERMINISTIC,
- (void*)&aFunc[i].flag,
- aFunc[i].xFunc, 0, 0);
- }
- for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
- rc = sqlite3_create_function(db, aAgg[i].zName, aAgg[i].nArg,
- SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
- 0, aAgg[i].xStep, aAgg[i].xFinal);
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
- rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
- }
-#endif
- return rc;
-}
-
-
-#ifndef SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_json_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- return sqlite3Json1Init(db);
-}
-#endif
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/memvfs.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/memvfs.c
deleted file mode 100644
index 27a61c35e4c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/memvfs.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
-** 2016-09-07
-**
-** 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 is an in-memory VFS implementation. The application supplies
-** a chunk of memory to hold the database file.
-**
-** Because there is place to store a rollback or wal journal, the database
-** must use one of journal_mode=MEMORY or journal_mode=NONE.
-**
-** USAGE:
-**
-** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336&max=65536", &db,
-** SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI,
-** "memvfs");
-**
-** These are the query parameters:
-**
-** ptr= The address of the memory buffer that holds the database.
-**
-** sz= The current size the database file
-**
-** maxsz= The maximum size of the database. In other words, the
-** amount of space allocated for the ptr= buffer.
-**
-** freeonclose= If true, then sqlite3_free() is called on the ptr=
-** value when the connection closes.
-**
-** The ptr= and sz= query parameters are required. If maxsz= is omitted,
-** then it defaults to the sz= value. Parameter values can be in either
-** decimal or hexadecimal. The filename in the URI is ignored.
-*/
-#include <sqlite3ext.h>
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-#include <assert.h>
-
-
-/*
-** Forward declaration of objects used by this utility
-*/
-typedef struct sqlite3_vfs MemVfs;
-typedef struct MemFile MemFile;
-
-/* Access to a lower-level VFS that (might) implement dynamic loading,
-** access to randomness, etc.
-*/
-#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
-
-/* An open file */
-struct MemFile {
- sqlite3_file base; /* IO methods */
- sqlite3_int64 sz; /* Size of the file */
- sqlite3_int64 szMax; /* Space allocated to aData */
- unsigned char *aData; /* content of the file */
- int bFreeOnClose; /* Invoke sqlite3_free() on aData at close */
-};
-
-/*
-** Methods for MemFile
-*/
-static int memClose(sqlite3_file*);
-static int memRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int memWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int memTruncate(sqlite3_file*, sqlite3_int64 size);
-static int memSync(sqlite3_file*, int flags);
-static int memFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int memLock(sqlite3_file*, int);
-static int memUnlock(sqlite3_file*, int);
-static int memCheckReservedLock(sqlite3_file*, int *pResOut);
-static int memFileControl(sqlite3_file*, int op, void *pArg);
-static int memSectorSize(sqlite3_file*);
-static int memDeviceCharacteristics(sqlite3_file*);
-static int memShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
-static int memShmLock(sqlite3_file*, int offset, int n, int flags);
-static void memShmBarrier(sqlite3_file*);
-static int memShmUnmap(sqlite3_file*, int deleteFlag);
-static int memFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
-static int memUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
-
-/*
-** Methods for MemVfs
-*/
-static int memOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int memDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int memAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int memFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-static void *memDlOpen(sqlite3_vfs*, const char *zFilename);
-static void memDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*memDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
-static void memDlClose(sqlite3_vfs*, void*);
-static int memRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int memSleep(sqlite3_vfs*, int microseconds);
-static int memCurrentTime(sqlite3_vfs*, double*);
-static int memGetLastError(sqlite3_vfs*, int, char *);
-static int memCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-
-static sqlite3_vfs mem_vfs = {
- 2, /* iVersion */
- 0, /* szOsFile (set when registered) */
- 1024, /* mxPathname */
- 0, /* pNext */
- "memvfs", /* zName */
- 0, /* pAppData (set when registered) */
- memOpen, /* xOpen */
- memDelete, /* xDelete */
- memAccess, /* xAccess */
- memFullPathname, /* xFullPathname */
- memDlOpen, /* xDlOpen */
- memDlError, /* xDlError */
- memDlSym, /* xDlSym */
- memDlClose, /* xDlClose */
- memRandomness, /* xRandomness */
- memSleep, /* xSleep */
- memCurrentTime, /* xCurrentTime */
- memGetLastError, /* xGetLastError */
- memCurrentTimeInt64 /* xCurrentTimeInt64 */
-};
-
-static const sqlite3_io_methods mem_io_methods = {
- 3, /* iVersion */
- memClose, /* xClose */
- memRead, /* xRead */
- memWrite, /* xWrite */
- memTruncate, /* xTruncate */
- memSync, /* xSync */
- memFileSize, /* xFileSize */
- memLock, /* xLock */
- memUnlock, /* xUnlock */
- memCheckReservedLock, /* xCheckReservedLock */
- memFileControl, /* xFileControl */
- memSectorSize, /* xSectorSize */
- memDeviceCharacteristics, /* xDeviceCharacteristics */
- memShmMap, /* xShmMap */
- memShmLock, /* xShmLock */
- memShmBarrier, /* xShmBarrier */
- memShmUnmap, /* xShmUnmap */
- memFetch, /* xFetch */
- memUnfetch /* xUnfetch */
-};
-
-
-
-/*
-** Close an mem-file.
-**
-** The pData pointer is owned by the application, so there is nothing
-** to free.
-*/
-static int memClose(sqlite3_file *pFile){
- MemFile *p = (MemFile *)pFile;
- if( p->bFreeOnClose ) sqlite3_free(p->aData);
- return SQLITE_OK;
-}
-
-/*
-** Read data from an mem-file.
-*/
-static int memRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- MemFile *p = (MemFile *)pFile;
- memcpy(zBuf, p->aData+iOfst, iAmt);
- return SQLITE_OK;
-}
-
-/*
-** Write data to an mem-file.
-*/
-static int memWrite(
- sqlite3_file *pFile,
- const void *z,
- int iAmt,
- sqlite_int64 iOfst
-){
- MemFile *p = (MemFile *)pFile;
- if( iOfst+iAmt>p->sz ){
- if( iOfst+iAmt>p->szMax ) return SQLITE_FULL;
- if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
- p->sz = iOfst+iAmt;
- }
- memcpy(p->aData+iOfst, z, iAmt);
- return SQLITE_OK;
-}
-
-/*
-** Truncate an mem-file.
-*/
-static int memTruncate(sqlite3_file *pFile, sqlite_int64 size){
- MemFile *p = (MemFile *)pFile;
- if( size>p->sz ){
- if( size>p->szMax ) return SQLITE_FULL;
- memset(p->aData+p->sz, 0, size-p->sz);
- }
- p->sz = size;
- return SQLITE_OK;
-}
-
-/*
-** Sync an mem-file.
-*/
-static int memSync(sqlite3_file *pFile, int flags){
- return SQLITE_OK;
-}
-
-/*
-** Return the current file-size of an mem-file.
-*/
-static int memFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- MemFile *p = (MemFile *)pFile;
- *pSize = p->sz;
- return SQLITE_OK;
-}
-
-/*
-** Lock an mem-file.
-*/
-static int memLock(sqlite3_file *pFile, int eLock){
- return SQLITE_OK;
-}
-
-/*
-** Unlock an mem-file.
-*/
-static int memUnlock(sqlite3_file *pFile, int eLock){
- return SQLITE_OK;
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an mem-file.
-*/
-static int memCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- *pResOut = 0;
- return SQLITE_OK;
-}
-
-/*
-** File control method. For custom operations on an mem-file.
-*/
-static int memFileControl(sqlite3_file *pFile, int op, void *pArg){
- MemFile *p = (MemFile *)pFile;
- int rc = SQLITE_NOTFOUND;
- if( op==SQLITE_FCNTL_VFSNAME ){
- *(char**)pArg = sqlite3_mprintf("mem(%p,%lld)", p->aData, p->sz);
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-/*
-** Return the sector-size in bytes for an mem-file.
-*/
-static int memSectorSize(sqlite3_file *pFile){
- return 1024;
-}
-
-/*
-** Return the device characteristic flags supported by an mem-file.
-*/
-static int memDeviceCharacteristics(sqlite3_file *pFile){
- return SQLITE_IOCAP_ATOMIC |
- SQLITE_IOCAP_POWERSAFE_OVERWRITE |
- SQLITE_IOCAP_SAFE_APPEND |
- SQLITE_IOCAP_SEQUENTIAL;
-}
-
-/* Create a shared memory file mapping */
-static int memShmMap(
- sqlite3_file *pFile,
- int iPg,
- int pgsz,
- int bExtend,
- void volatile **pp
-){
- return SQLITE_IOERR_SHMMAP;
-}
-
-/* Perform locking on a shared-memory segment */
-static int memShmLock(sqlite3_file *pFile, int offset, int n, int flags){
- return SQLITE_IOERR_SHMLOCK;
-}
-
-/* Memory barrier operation on shared memory */
-static void memShmBarrier(sqlite3_file *pFile){
- return;
-}
-
-/* Unmap a shared memory segment */
-static int memShmUnmap(sqlite3_file *pFile, int deleteFlag){
- return SQLITE_OK;
-}
-
-/* Fetch a page of a memory-mapped file */
-static int memFetch(
- sqlite3_file *pFile,
- sqlite3_int64 iOfst,
- int iAmt,
- void **pp
-){
- MemFile *p = (MemFile *)pFile;
- *pp = (void*)(p->aData + iOfst);
- return SQLITE_OK;
-}
-
-/* Release a memory-mapped page */
-static int memUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
- return SQLITE_OK;
-}
-
-/*
-** Open an mem file handle.
-*/
-static int memOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- MemFile *p = (MemFile*)pFile;
- memset(p, 0, sizeof(*p));
- if( (flags & SQLITE_OPEN_MAIN_DB)==0 ) return SQLITE_CANTOPEN;
- p->aData = (unsigned char*)sqlite3_uri_int64(zName,"ptr",0);
- if( p->aData==0 ) return SQLITE_CANTOPEN;
- p->sz = sqlite3_uri_int64(zName,"sz",0);
- if( p->sz<0 ) return SQLITE_CANTOPEN;
- p->szMax = sqlite3_uri_int64(zName,"max",p->sz);
- if( p->szMax<p->sz ) return SQLITE_CANTOPEN;
- p->bFreeOnClose = sqlite3_uri_boolean(zName,"freeonclose",0);
- pFile->pMethods = &mem_io_methods;
- return SQLITE_OK;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int memDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- return SQLITE_IOERR_DELETE;
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int memAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- *pResOut = 0;
- return SQLITE_OK;
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (INST_MAX_PATHNAME+1) bytes.
-*/
-static int memFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- sqlite3_snprintf(nOut, zOut, "%s", zPath);
- return SQLITE_OK;
-}
-
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *memDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void memDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*memDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void memDlClose(sqlite3_vfs *pVfs, void *pHandle){
- ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
-}
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int memRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int memSleep(sqlite3_vfs *pVfs, int nMicro){
- return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int memCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
-}
-
-static int memGetLastError(sqlite3_vfs *pVfs, int a, char *b){
- return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
-}
-static int memCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
- return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
-}
-
-#ifdef MEMVFS_TEST
-/*
-** memvfs_from_file(FILENAME, MAXSIZE)
-**
-** This an SQL function used to help in testing the memvfs VFS. The
-** function reads the content of a file into memory and then returns
-** a URI that can be handed to ATTACH to attach the memory buffer as
-** a database. Example:
-**
-** ATTACH memvfs_from_file('test.db',1048576) AS inmem;
-**
-** The optional MAXSIZE argument gives the size of the memory allocation
-** used to hold the database. If omitted, it defaults to the size of the
-** file on disk.
-*/
-#include <stdio.h>
-static void memvfsFromFileFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- unsigned char *p;
- sqlite3_int64 sz;
- sqlite3_int64 szMax;
- FILE *in;
- const char *zFilename = (const char*)sqlite3_value_text(argv[0]);
- char *zUri;
-
- if( zFilename==0 ) return;
- in = fopen(zFilename, "rb");
- if( in==0 ) return;
- fseek(in, 0, SEEK_END);
- szMax = sz = ftell(in);
- rewind(in);
- if( argc>=2 ){
- szMax = sqlite3_value_int64(argv[1]);
- if( szMax<sz ) szMax = sz;
- }
- p = sqlite3_malloc64( szMax );
- if( p==0 ){
- fclose(in);
- sqlite3_result_error_nomem(context);
- return;
- }
- fread(p, sz, 1, in);
- fclose(in);
- zUri = sqlite3_mprintf(
- "file:/mem?vfs=memvfs&ptr=%lld&sz=%lld&max=%lld&freeonclose=1",
- (sqlite3_int64)p, sz, szMax);
- sqlite3_result_text(context, zUri, -1, sqlite3_free);
-}
-#endif /* MEMVFS_TEST */
-
-#ifdef MEMVFS_TEST
-/*
-** memvfs_to_file(SCHEMA, FILENAME)
-**
-** The schema identified by SCHEMA must be a memvfs database. Write
-** the content of this database into FILENAME.
-*/
-static void memvfsToFileFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- MemFile *p = 0;
- FILE *out;
- int rc;
- sqlite3 *db = sqlite3_context_db_handle(context);
- sqlite3_vfs *pVfs = 0;
- const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
- const char *zFilename = (const char*)sqlite3_value_text(argv[1]);
-
- if( zFilename==0 ) return;
- out = fopen(zFilename, "wb");
- if( out==0 ) return;
- rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_VFS_POINTER, &pVfs);
- if( rc || pVfs==0 ) return;
- if( strcmp(pVfs->zName,"memvfs")!=0 ) return;
- rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
- if( rc ) return;
- fwrite(p->aData, 1, (size_t)p->sz, out);
- fclose(out);
-}
-#endif /* MEMVFS_TEST */
-
-#ifdef MEMVFS_TEST
-/* Called for each new database connection */
-static int memvfsRegister(
- sqlite3 *db,
- char **pzErrMsg,
- const struct sqlite3_api_routines *pThunk
-){
- sqlite3_create_function(db, "memvfs_from_file", 1, SQLITE_UTF8, 0,
- memvfsFromFileFunc, 0, 0);
- sqlite3_create_function(db, "memvfs_from_file", 2, SQLITE_UTF8, 0,
- memvfsFromFileFunc, 0, 0);
- sqlite3_create_function(db, "memvfs_to_file", 2, SQLITE_UTF8, 0,
- memvfsToFileFunc, 0, 0);
- return SQLITE_OK;
-}
-#endif /* MEMVFS_TEST */
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-/*
-** This routine is called when the extension is loaded.
-** Register the new VFS.
-*/
-int sqlite3_memvfs_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- mem_vfs.pAppData = sqlite3_vfs_find(0);
- mem_vfs.szOsFile = sizeof(MemFile);
- rc = sqlite3_vfs_register(&mem_vfs, 1);
-#ifdef MEMVFS_TEST
- if( rc==SQLITE_OK ){
- rc = sqlite3_auto_extension((void(*)(void))memvfsRegister);
- }
- if( rc==SQLITE_OK ){
- rc = memvfsRegister(db, pzErrMsg, pApi);
- }
-#endif
- if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/mmapwarm.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/mmapwarm.c
deleted file mode 100644
index 4e23638a99c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/mmapwarm.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-** 2017-09-18
-**
-** 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.
-**
-*************************************************************************
-**
-*/
-
-#include "sqlite3.h"
-
-
-/*
-** This function is used to touch each page of a mapping of a memory
-** mapped SQLite database. Assuming that the system has sufficient free
-** memory and supports sufficiently large mappings, this causes the OS
-** to cache the entire database in main memory, making subsequent
-** database accesses faster.
-**
-** If the second parameter to this function is not NULL, it is the name of
-** the specific database to operate on (i.e. "main" or the name of an
-** attached database).
-**
-** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
-** It is not considered an error if the file is not memory-mapped, or if
-** the mapping does not span the entire file. If an error does occur, a
-** transaction may be left open on the database file.
-**
-** It is illegal to call this function when the database handle has an
-** open transaction. SQLITE_MISUSE is returned in this case.
-*/
-int sqlite3_mmap_warm(sqlite3 *db, const char *zDb){
- int rc = SQLITE_OK;
- char *zSql = 0;
- int pgsz = 0;
- int nTotal = 0;
-
- if( 0==sqlite3_get_autocommit(db) ) return SQLITE_MISUSE;
-
- /* Open a read-only transaction on the file in question */
- zSql = sqlite3_mprintf("BEGIN; SELECT * FROM %s%q%ssqlite_master",
- (zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
- );
- if( zSql==0 ) return SQLITE_NOMEM;
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
-
- /* Find the SQLite page size of the file */
- if( rc==SQLITE_OK ){
- zSql = sqlite3_mprintf("PRAGMA %s%q%spage_size",
- (zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
- );
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_stmt *pPgsz = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pPgsz, 0);
- sqlite3_free(zSql);
- if( rc==SQLITE_OK ){
- if( sqlite3_step(pPgsz)==SQLITE_ROW ){
- pgsz = sqlite3_column_int(pPgsz, 0);
- }
- rc = sqlite3_finalize(pPgsz);
- }
- if( rc==SQLITE_OK && pgsz==0 ){
- rc = SQLITE_ERROR;
- }
- }
- }
-
- /* Touch each mmap'd page of the file */
- if( rc==SQLITE_OK ){
- int rc2;
- sqlite3_file *pFd = 0;
- rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFd);
- if( rc==SQLITE_OK && pFd->pMethods->iVersion>=3 ){
- sqlite3_int64 iPg = 1;
- sqlite3_io_methods const *p = pFd->pMethods;
- while( 1 ){
- unsigned char *pMap;
- rc = p->xFetch(pFd, pgsz*iPg, pgsz, (void**)&pMap);
- if( rc!=SQLITE_OK || pMap==0 ) break;
-
- nTotal += pMap[0];
- nTotal += pMap[pgsz-1];
-
- rc = p->xUnfetch(pFd, pgsz*iPg, (void*)pMap);
- if( rc!=SQLITE_OK ) break;
- iPg++;
- }
- sqlite3_log(SQLITE_OK,
- "sqlite3_mmap_warm_cache: Warmed up %d pages of %s", iPg==1?0:iPg,
- sqlite3_db_filename(db, zDb)
- );
- }
-
- rc2 = sqlite3_exec(db, "END", 0, 0, 0);
- if( rc==SQLITE_OK ) rc = rc2;
- }
-
- return rc;
-}
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/nextchar.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/nextchar.c
deleted file mode 100644
index 49dfd24f1f1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/nextchar.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
-** 2013-02-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 contains code to implement the next_char(A,T,F,W,C) SQL function.
-**
-** The next_char(A,T,F,W,C) function finds all valid "next" characters for
-** string A given the vocabulary in T.F. If the W value exists and is a
-** non-empty string, then it is an SQL expression that limits the entries
-** in T.F that will be considered. If C exists and is a non-empty string,
-** then it is the name of the collating sequence to use for comparison. If
-**
-** Only the first three arguments are required. If the C parameter is
-** omitted or is NULL or is an empty string, then the default collating
-** sequence of T.F is used for comparision. If the W parameter is omitted
-** or is NULL or is an empty string, then no filtering of the output is
-** done.
-**
-** The T.F column should be indexed using collation C or else this routine
-** will be quite slow.
-**
-** For example, suppose an application has a dictionary like this:
-**
-** CREATE TABLE dictionary(word TEXT UNIQUE);
-**
-** Further suppose that for user keypad entry, it is desired to disable
-** (gray out) keys that are not valid as the next character. If the
-** the user has previously entered (say) 'cha' then to find all allowed
-** next characters (and thereby determine when keys should not be grayed
-** out) run the following query:
-**
-** SELECT next_char('cha','dictionary','word');
-**
-** IMPLEMENTATION NOTES:
-**
-** The next_char function is implemented using recursive SQL that makes
-** use of the table name and column name as part of a query. If either
-** the table name or column name are keywords or contain special characters,
-** then they should be escaped. For example:
-**
-** SELECT next_char('cha','[dictionary]','[word]');
-**
-** This also means that the table name can be a subquery:
-**
-** SELECT next_char('cha','(SELECT word AS w FROM dictionary)','w');
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-
-/*
-** A structure to hold context of the next_char() computation across
-** nested function calls.
-*/
-typedef struct nextCharContext nextCharContext;
-struct nextCharContext {
- sqlite3 *db; /* Database connection */
- sqlite3_stmt *pStmt; /* Prepared statement used to query */
- const unsigned char *zPrefix; /* Prefix to scan */
- int nPrefix; /* Size of zPrefix in bytes */
- int nAlloc; /* Space allocated to aResult */
- int nUsed; /* Space used in aResult */
- unsigned int *aResult; /* Array of next characters */
- int mallocFailed; /* True if malloc fails */
- int otherError; /* True for any other failure */
-};
-
-/*
-** Append a result character if the character is not already in the
-** result.
-*/
-static void nextCharAppend(nextCharContext *p, unsigned c){
- int i;
- for(i=0; i<p->nUsed; i++){
- if( p->aResult[i]==c ) return;
- }
- if( p->nUsed+1 > p->nAlloc ){
- unsigned int *aNew;
- int n = p->nAlloc*2 + 30;
- aNew = sqlite3_realloc(p->aResult, n*sizeof(unsigned int));
- if( aNew==0 ){
- p->mallocFailed = 1;
- return;
- }else{
- p->aResult = aNew;
- p->nAlloc = n;
- }
- }
- p->aResult[p->nUsed++] = c;
-}
-
-/*
-** Write a character into z[] as UTF8. Return the number of bytes needed
-** to hold the character
-*/
-static int writeUtf8(unsigned char *z, unsigned c){
- if( c<0x00080 ){
- z[0] = (unsigned char)(c&0xff);
- return 1;
- }
- if( c<0x00800 ){
- z[0] = 0xC0 + (unsigned char)((c>>6)&0x1F);
- z[1] = 0x80 + (unsigned char)(c & 0x3F);
- return 2;
- }
- if( c<0x10000 ){
- z[0] = 0xE0 + (unsigned char)((c>>12)&0x0F);
- z[1] = 0x80 + (unsigned char)((c>>6) & 0x3F);
- z[2] = 0x80 + (unsigned char)(c & 0x3F);
- return 3;
- }
- z[0] = 0xF0 + (unsigned char)((c>>18) & 0x07);
- z[1] = 0x80 + (unsigned char)((c>>12) & 0x3F);
- z[2] = 0x80 + (unsigned char)((c>>6) & 0x3F);
- z[3] = 0x80 + (unsigned char)(c & 0x3F);
- return 4;
-}
-
-/*
-** Read a UTF8 character out of z[] and write it into *pOut. Return
-** the number of bytes in z[] that were used to construct the character.
-*/
-static int readUtf8(const unsigned char *z, unsigned *pOut){
- static const unsigned char validBits[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
- };
- unsigned c = z[0];
- if( c<0xc0 ){
- *pOut = c;
- return 1;
- }else{
- int n = 1;
- c = validBits[c-0xc0];
- while( (z[n] & 0xc0)==0x80 ){
- c = (c<<6) + (0x3f & z[n++]);
- }
- if( c<0x80 || (c&0xFFFFF800)==0xD800 || (c&0xFFFFFFFE)==0xFFFE ){
- c = 0xFFFD;
- }
- *pOut = c;
- return n;
- }
-}
-
-/*
-** The nextCharContext structure has been set up. Add all "next" characters
-** to the result set.
-*/
-static void findNextChars(nextCharContext *p){
- unsigned cPrev = 0;
- unsigned char zPrev[8];
- int n, rc;
-
- for(;;){
- sqlite3_bind_text(p->pStmt, 1, (char*)p->zPrefix, p->nPrefix,
- SQLITE_STATIC);
- n = writeUtf8(zPrev, cPrev+1);
- sqlite3_bind_text(p->pStmt, 2, (char*)zPrev, n, SQLITE_STATIC);
- rc = sqlite3_step(p->pStmt);
- if( rc==SQLITE_DONE ){
- sqlite3_reset(p->pStmt);
- return;
- }else if( rc!=SQLITE_ROW ){
- p->otherError = rc;
- return;
- }else{
- const unsigned char *zOut = sqlite3_column_text(p->pStmt, 0);
- unsigned cNext;
- n = readUtf8(zOut+p->nPrefix, &cNext);
- sqlite3_reset(p->pStmt);
- nextCharAppend(p, cNext);
- cPrev = cNext;
- if( p->mallocFailed ) return;
- }
- }
-}
-
-
-/*
-** next_character(A,T,F,W)
-**
-** Return a string composted of all next possible characters after
-** A for elements of T.F. If W is supplied, then it is an SQL expression
-** that limits the elements in T.F that are considered.
-*/
-static void nextCharFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- nextCharContext c;
- const unsigned char *zTable = sqlite3_value_text(argv[1]);
- const unsigned char *zField = sqlite3_value_text(argv[2]);
- const unsigned char *zWhere;
- const unsigned char *zCollName;
- char *zWhereClause = 0;
- char *zColl = 0;
- char *zSql;
- int rc;
-
- memset(&c, 0, sizeof(c));
- c.db = sqlite3_context_db_handle(context);
- c.zPrefix = sqlite3_value_text(argv[0]);
- c.nPrefix = sqlite3_value_bytes(argv[0]);
- if( zTable==0 || zField==0 || c.zPrefix==0 ) return;
- if( argc>=4
- && (zWhere = sqlite3_value_text(argv[3]))!=0
- && zWhere[0]!=0
- ){
- zWhereClause = sqlite3_mprintf("AND (%s)", zWhere);
- if( zWhereClause==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- }else{
- zWhereClause = "";
- }
- if( argc>=5
- && (zCollName = sqlite3_value_text(argv[4]))!=0
- && zCollName[0]!=0
- ){
- zColl = sqlite3_mprintf("collate \"%w\"", zCollName);
- if( zColl==0 ){
- sqlite3_result_error_nomem(context);
- if( zWhereClause[0] ) sqlite3_free(zWhereClause);
- return;
- }
- }else{
- zColl = "";
- }
- zSql = sqlite3_mprintf(
- "SELECT %s FROM %s"
- " WHERE %s>=(?1 || ?2) %s"
- " AND %s<=(?1 || char(1114111)) %s" /* 1114111 == 0x10ffff */
- " %s"
- " ORDER BY 1 %s ASC LIMIT 1",
- zField, zTable, zField, zColl, zField, zColl, zWhereClause, zColl
- );
- if( zWhereClause[0] ) sqlite3_free(zWhereClause);
- if( zColl[0] ) sqlite3_free(zColl);
- if( zSql==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
-
- rc = sqlite3_prepare_v2(c.db, zSql, -1, &c.pStmt, 0);
- sqlite3_free(zSql);
- if( rc ){
- sqlite3_result_error(context, sqlite3_errmsg(c.db), -1);
- return;
- }
- findNextChars(&c);
- if( c.mallocFailed ){
- sqlite3_result_error_nomem(context);
- }else{
- unsigned char *pRes;
- pRes = sqlite3_malloc( c.nUsed*4 + 1 );
- if( pRes==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- int i;
- int n = 0;
- for(i=0; i<c.nUsed; i++){
- n += writeUtf8(pRes+n, c.aResult[i]);
- }
- pRes[n] = 0;
- sqlite3_result_text(context, (const char*)pRes, n, sqlite3_free);
- }
- }
- sqlite3_finalize(c.pStmt);
- sqlite3_free(c.aResult);
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_nextchar_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "next_char", 3, SQLITE_UTF8, 0,
- nextCharFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "next_char", 4, SQLITE_UTF8, 0,
- nextCharFunc, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "next_char", 5, SQLITE_UTF8, 0,
- nextCharFunc, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/normalize.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/normalize.c
deleted file mode 100644
index fd656f13038..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/normalize.c
+++ /dev/null
@@ -1,707 +0,0 @@
-/*
-** 2018-01-08
-**
-** 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 contains code to implement the sqlite3_normalize() function.
-**
-** char *sqlite3_normalize(const char *zSql);
-**
-** This function takes an SQL string as input and returns a "normalized"
-** version of that string in memory obtained from sqlite3_malloc64(). The
-** caller is responsible for ensuring that the returned memory is freed.
-**
-** If a memory allocation error occurs, this routine returns NULL.
-**
-** The normalization consists of the following transformations:
-**
-** (1) Convert every literal (string, blob literal, numeric constant,
-** or "NULL" constant) into a ?
-**
-** (2) Remove all superfluous whitespace, including comments. Change
-** all required whitespace to a single space character.
-**
-** (3) Lowercase all ASCII characters.
-**
-** (4) If an IN or NOT IN operator is followed by a list of 1 or more
-** values, convert that list into "(?,?,?)".
-**
-** The purpose of normalization is two-fold:
-**
-** (1) Sanitize queries by removing potentially private or sensitive
-** information contained in literals.
-**
-** (2) Identify structurally identical queries by comparing their
-** normalized forms.
-**
-** Command-Line Utility
-** --------------------
-**
-** This file also contains code for a command-line utility that converts
-** SQL queries in text files into their normalized forms. To build the
-** command-line program, compile this file with -DSQLITE_NORMALIZE_CLI
-** and link it against the SQLite library.
-*/
-#include <sqlite3.h>
-#include <string.h>
-
-/*
-** Implementation note:
-**
-** Much of the tokenizer logic is copied out of the tokenize.c source file
-** of SQLite. That logic could be simplified for this particular application,
-** but that would impose a risk of introducing subtle errors. It is best to
-** keep the code as close to the original as possible.
-**
-** The tokenize code is in sync with the SQLite core as of 2018-01-08.
-** Any future changes to the core tokenizer might require corresponding
-** adjustments to the tokenizer logic in this module.
-*/
-
-
-/* Character classes for tokenizing
-**
-** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented
-** using a lookup table, whereas a switch() directly on c uses a binary search.
-** The lookup table is much faster. To maximize speed, and to ensure that
-** a lookup table is used, all of the classes need to be small integers and
-** all of them need to be used within the switch.
-*/
-#define CC_X 0 /* The letter 'x', or start of BLOB literal */
-#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */
-#define CC_ID 2 /* unicode characters usable in IDs */
-#define CC_DIGIT 3 /* Digits */
-#define CC_DOLLAR 4 /* '$' */
-#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */
-#define CC_VARNUM 6 /* '?'. Numeric SQL variables */
-#define CC_SPACE 7 /* Space characters */
-#define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */
-#define CC_QUOTE2 9 /* '['. [...] style quoted ids */
-#define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */
-#define CC_MINUS 11 /* '-'. Minus or SQL-style comment */
-#define CC_LT 12 /* '<'. Part of < or <= or <> */
-#define CC_GT 13 /* '>'. Part of > or >= */
-#define CC_EQ 14 /* '='. Part of = or == */
-#define CC_BANG 15 /* '!'. Part of != */
-#define CC_SLASH 16 /* '/'. / or c-style comment */
-#define CC_LP 17 /* '(' */
-#define CC_RP 18 /* ')' */
-#define CC_SEMI 19 /* ';' */
-#define CC_PLUS 20 /* '+' */
-#define CC_STAR 21 /* '*' */
-#define CC_PERCENT 22 /* '%' */
-#define CC_COMMA 23 /* ',' */
-#define CC_AND 24 /* '&' */
-#define CC_TILDA 25 /* '~' */
-#define CC_DOT 26 /* '.' */
-#define CC_ILLEGAL 27 /* Illegal character */
-
-static const unsigned char aiClass[] = {
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
-/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
-/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1,
-/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27,
-/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
-};
-
-/* An array to map all upper-case characters into their corresponding
-** lower-case character.
-**
-** SQLite only considers US-ASCII (or EBCDIC) characters. We do not
-** handle case conversions for the UTF character set since the tables
-** involved are nearly as big or bigger than SQLite itself.
-*/
-static const unsigned char sqlite3UpperToLower[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
- 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
- 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
- 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
- 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
- 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
- 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
- 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
- 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
- 252,253,254,255
-};
-
-/*
-** The following 256 byte lookup table is used to support SQLites built-in
-** equivalents to the following standard library functions:
-**
-** isspace() 0x01
-** isalpha() 0x02
-** isdigit() 0x04
-** isalnum() 0x06
-** isxdigit() 0x08
-** toupper() 0x20
-** SQLite identifier character 0x40
-** Quote character 0x80
-**
-** Bit 0x20 is set if the mapped character requires translation to upper
-** case. i.e. if the character is a lower-case ASCII character.
-** If x is a lower-case ASCII character, then its upper-case equivalent
-** is (x - 0x20). Therefore toupper() can be implemented as:
-**
-** (x & ~(map[x]&0x20))
-**
-** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
-** array. tolower() is used more often than toupper() by SQLite.
-**
-** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
-** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
-** non-ASCII UTF character. Hence the test for whether or not a character is
-** part of an identifier is 0x46.
-*/
-static const unsigned char sqlite3CtypeMap[256] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */
- 0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27 !"#$%&' */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
- 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
-
- 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
- 0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
- 0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
- 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
-
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */
-
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
-};
-#define sqlite3Toupper(x) ((x)&~(sqlite3CtypeMap[(unsigned char)(x)]&0x20))
-#define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01)
-#define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06)
-#define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02)
-#define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04)
-#define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
-#define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
-#define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80)
-
-
-/*
-** If X is a character that can be used in an identifier then
-** IdChar(X) will be true. Otherwise it is false.
-**
-** For ASCII, any character with the high-order bit set is
-** allowed in an identifier. For 7-bit characters,
-** sqlite3IsIdChar[X] must be 1.
-**
-** For EBCDIC, the rules are more complex but have the same
-** end result.
-**
-** Ticket #1066. the SQL standard does not allow '$' in the
-** middle of identifiers. But many SQL implementations do.
-** SQLite will allow '$' in identifiers for compatibility.
-** But the feature is undocumented.
-*/
-#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
-
-/*
-** Ignore testcase() macros
-*/
-#define testcase(X)
-
-/*
-** Token values
-*/
-#define TK_SPACE 0
-#define TK_NAME 1
-#define TK_LITERAL 2
-#define TK_PUNCT 3
-#define TK_ERROR 4
-
-#define TK_MINUS TK_PUNCT
-#define TK_LP TK_PUNCT
-#define TK_RP TK_PUNCT
-#define TK_SEMI TK_PUNCT
-#define TK_PLUS TK_PUNCT
-#define TK_STAR TK_PUNCT
-#define TK_SLASH TK_PUNCT
-#define TK_REM TK_PUNCT
-#define TK_EQ TK_PUNCT
-#define TK_LE TK_PUNCT
-#define TK_NE TK_PUNCT
-#define TK_LSHIFT TK_PUNCT
-#define TK_LT TK_PUNCT
-#define TK_GE TK_PUNCT
-#define TK_RSHIFT TK_PUNCT
-#define TK_GT TK_PUNCT
-#define TK_GE TK_PUNCT
-#define TK_BITOR TK_PUNCT
-#define TK_CONCAT TK_PUNCT
-#define TK_COMMA TK_PUNCT
-#define TK_BITAND TK_PUNCT
-#define TK_BITNOT TK_PUNCT
-#define TK_STRING TK_LITERAL
-#define TK_ID TK_NAME
-#define TK_ILLEGAL TK_ERROR
-#define TK_DOT TK_PUNCT
-#define TK_INTEGER TK_LITERAL
-#define TK_FLOAT TK_LITERAL
-#define TK_VARIABLE TK_LITERAL
-#define TK_BLOB TK_LITERAL
-
-/*
-** Return the length (in bytes) of the token that begins at z[0].
-** Store the token type in *tokenType before returning.
-*/
-static int sqlite3GetToken(const unsigned char *z, int *tokenType){
- int i, c;
- switch( aiClass[*z] ){ /* Switch on the character-class of the first byte
- ** of the token. See the comment on the CC_ defines
- ** above. */
- case CC_SPACE: {
- for(i=1; sqlite3Isspace(z[i]); i++){}
- *tokenType = TK_SPACE;
- return i;
- }
- case CC_MINUS: {
- if( z[1]=='-' ){
- for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
- *tokenType = TK_SPACE;
- return i;
- }
- *tokenType = TK_MINUS;
- return 1;
- }
- case CC_LP: {
- *tokenType = TK_LP;
- return 1;
- }
- case CC_RP: {
- *tokenType = TK_RP;
- return 1;
- }
- case CC_SEMI: {
- *tokenType = TK_SEMI;
- return 1;
- }
- case CC_PLUS: {
- *tokenType = TK_PLUS;
- return 1;
- }
- case CC_STAR: {
- *tokenType = TK_STAR;
- return 1;
- }
- case CC_SLASH: {
- if( z[1]!='*' || z[2]==0 ){
- *tokenType = TK_SLASH;
- return 1;
- }
- for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
- if( c ) i++;
- *tokenType = TK_SPACE;
- return i;
- }
- case CC_PERCENT: {
- *tokenType = TK_REM;
- return 1;
- }
- case CC_EQ: {
- *tokenType = TK_EQ;
- return 1 + (z[1]=='=');
- }
- case CC_LT: {
- if( (c=z[1])=='=' ){
- *tokenType = TK_LE;
- return 2;
- }else if( c=='>' ){
- *tokenType = TK_NE;
- return 2;
- }else if( c=='<' ){
- *tokenType = TK_LSHIFT;
- return 2;
- }else{
- *tokenType = TK_LT;
- return 1;
- }
- }
- case CC_GT: {
- if( (c=z[1])=='=' ){
- *tokenType = TK_GE;
- return 2;
- }else if( c=='>' ){
- *tokenType = TK_RSHIFT;
- return 2;
- }else{
- *tokenType = TK_GT;
- return 1;
- }
- }
- case CC_BANG: {
- if( z[1]!='=' ){
- *tokenType = TK_ILLEGAL;
- return 1;
- }else{
- *tokenType = TK_NE;
- return 2;
- }
- }
- case CC_PIPE: {
- if( z[1]!='|' ){
- *tokenType = TK_BITOR;
- return 1;
- }else{
- *tokenType = TK_CONCAT;
- return 2;
- }
- }
- case CC_COMMA: {
- *tokenType = TK_COMMA;
- return 1;
- }
- case CC_AND: {
- *tokenType = TK_BITAND;
- return 1;
- }
- case CC_TILDA: {
- *tokenType = TK_BITNOT;
- return 1;
- }
- case CC_QUOTE: {
- int delim = z[0];
- testcase( delim=='`' );
- testcase( delim=='\'' );
- testcase( delim=='"' );
- for(i=1; (c=z[i])!=0; i++){
- if( c==delim ){
- if( z[i+1]==delim ){
- i++;
- }else{
- break;
- }
- }
- }
- if( c=='\'' ){
- *tokenType = TK_STRING;
- return i+1;
- }else if( c!=0 ){
- *tokenType = TK_ID;
- return i+1;
- }else{
- *tokenType = TK_ILLEGAL;
- return i;
- }
- }
- case CC_DOT: {
- if( !sqlite3Isdigit(z[1]) ){
- *tokenType = TK_DOT;
- return 1;
- }
- /* If the next character is a digit, this is a floating point
- ** number that begins with ".". Fall thru into the next case */
- }
- case CC_DIGIT: {
- *tokenType = TK_INTEGER;
- if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
- for(i=3; sqlite3Isxdigit(z[i]); i++){}
- return i;
- }
- for(i=0; sqlite3Isdigit(z[i]); i++){}
- if( z[i]=='.' ){
- i++;
- while( sqlite3Isdigit(z[i]) ){ i++; }
- *tokenType = TK_FLOAT;
- }
- if( (z[i]=='e' || z[i]=='E') &&
- ( sqlite3Isdigit(z[i+1])
- || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
- )
- ){
- i += 2;
- while( sqlite3Isdigit(z[i]) ){ i++; }
- *tokenType = TK_FLOAT;
- }
- while( IdChar(z[i]) ){
- *tokenType = TK_ILLEGAL;
- i++;
- }
- return i;
- }
- case CC_QUOTE2: {
- for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
- *tokenType = c==']' ? TK_ID : TK_ILLEGAL;
- return i;
- }
- case CC_VARNUM: {
- *tokenType = TK_VARIABLE;
- for(i=1; sqlite3Isdigit(z[i]); i++){}
- return i;
- }
- case CC_DOLLAR:
- case CC_VARALPHA: {
- int n = 0;
- testcase( z[0]=='$' ); testcase( z[0]=='@' );
- testcase( z[0]==':' ); testcase( z[0]=='#' );
- *tokenType = TK_VARIABLE;
- for(i=1; (c=z[i])!=0; i++){
- if( IdChar(c) ){
- n++;
- }else if( c=='(' && n>0 ){
- do{
- i++;
- }while( (c=z[i])!=0 && !sqlite3Isspace(c) && c!=')' );
- if( c==')' ){
- i++;
- }else{
- *tokenType = TK_ILLEGAL;
- }
- break;
- }else if( c==':' && z[i+1]==':' ){
- i++;
- }else{
- break;
- }
- }
- if( n==0 ) *tokenType = TK_ILLEGAL;
- return i;
- }
- case CC_KYWD: {
- for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
- if( IdChar(z[i]) ){
- /* This token started out using characters that can appear in keywords,
- ** but z[i] is a character not allowed within keywords, so this must
- ** be an identifier instead */
- i++;
- break;
- }
- *tokenType = TK_ID;
- return i;
- }
- case CC_X: {
- testcase( z[0]=='x' ); testcase( z[0]=='X' );
- if( z[1]=='\'' ){
- *tokenType = TK_BLOB;
- for(i=2; sqlite3Isxdigit(z[i]); i++){}
- if( z[i]!='\'' || i%2 ){
- *tokenType = TK_ILLEGAL;
- while( z[i] && z[i]!='\'' ){ i++; }
- }
- if( z[i] ) i++;
- return i;
- }
- /* If it is not a BLOB literal, then it must be an ID, since no
- ** SQL keywords start with the letter 'x'. Fall through */
- }
- case CC_ID: {
- i = 1;
- break;
- }
- default: {
- *tokenType = TK_ILLEGAL;
- return 1;
- }
- }
- while( IdChar(z[i]) ){ i++; }
- *tokenType = TK_ID;
- return i;
-}
-
-char *sqlite3_normalize(const char *zSql){
- char *z; /* The output string */
- sqlite3_int64 nZ; /* Size of the output string in bytes */
- sqlite3_int64 nSql; /* Size of the input string in bytes */
- int i; /* Next character to read from zSql[] */
- int j; /* Next slot to fill in on z[] */
- int tokenType; /* Type of the next token */
- int n; /* Size of the next token */
- int k; /* Loop counter */
-
- nSql = strlen(zSql);
- nZ = nSql;
- z = sqlite3_malloc64( nZ+2 );
- if( z==0 ) return 0;
- for(i=j=0; zSql[i]; i += n){
- n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
- switch( tokenType ){
- case TK_SPACE: {
- break;
- }
- case TK_ERROR: {
- sqlite3_free(z);
- return 0;
- }
- case TK_LITERAL: {
- z[j++] = '?';
- break;
- }
- case TK_PUNCT:
- case TK_NAME: {
- if( n==4 && sqlite3_strnicmp(zSql+i,"NULL",4)==0 ){
- if( (j>=3 && strncmp(z+j-2,"is",2)==0 && !IdChar(z[j-3]))
- || (j>=4 && strncmp(z+j-3,"not",3)==0 && !IdChar(z[j-4]))
- ){
- /* NULL is a keyword in this case, not a literal value */
- }else{
- /* Here the NULL is a literal value */
- z[j++] = '?';
- break;
- }
- }
- if( j>0 && IdChar(z[j-1]) && IdChar(zSql[i]) ) z[j++] = ' ';
- for(k=0; k<n; k++){
- z[j++] = sqlite3Tolower(zSql[i+k]);
- }
- break;
- }
- }
- }
- while( j>0 && z[j-1]==' ' ){ j--; }
- if( i>0 && z[j-1]!=';' ){ z[j++] = ';'; }
- z[j] = 0;
-
- /* Make a second pass converting "in(...)" where the "..." is not a
- ** SELECT statement into "in(?,?,?)" */
- for(i=0; i<j; i=n){
- char *zIn = strstr(z+i, "in(");
- int nParen;
- if( zIn==0 ) break;
- n = (int)(zIn-z)+3; /* Index of first char past "in(" */
- if( n && IdChar(zIn[-1]) ) continue;
- if( strncmp(zIn, "in(select",9)==0 && !IdChar(zIn[9]) ) continue;
- if( strncmp(zIn, "in(with",7)==0 && !IdChar(zIn[7]) ) continue;
- for(nParen=1, k=0; z[n+k]; k++){
- if( z[n+k]=='(' ) nParen++;
- if( z[n+k]==')' ){
- nParen--;
- if( nParen==0 ) break;
- }
- }
- /* k is the number of bytes in the "..." within "in(...)" */
- if( k<5 ){
- z = sqlite3_realloc64(z, j+(5-k)+1);
- if( z==0 ) return 0;
- memmove(z+n+5, z+n+k, j-(n+k));
- }else if( k>5 ){
- memmove(z+n+5, z+n+k, j-(n+k));
- }
- j = j-k+5;
- z[j] = 0;
- memcpy(z+n, "?,?,?", 5);
- }
- return z;
-}
-
-/*
-** For testing purposes, or to build a stand-alone SQL normalizer program,
-** compile this one source file with the -DSQLITE_NORMALIZE_CLI and link
-** it against any SQLite library. The resulting command-line program will
-** run sqlite3_normalize() over the text of all files named on the command-
-** line and show the result on standard output.
-*/
-#ifdef SQLITE_NORMALIZE_CLI
-#include <stdio.h>
-#include <stdlib.h>
-
-/*
-** Break zIn up into separate SQL statements and run sqlite3_normalize()
-** on each one. Print the result of each run.
-*/
-static void normalizeFile(char *zIn){
- int i;
- if( zIn==0 ) return;
- for(i=0; zIn[i]; i++){
- char cSaved;
- if( zIn[i]!=';' ) continue;
- cSaved = zIn[i+1];
- zIn[i+1] = 0;
- if( sqlite3_complete(zIn) ){
- char *zOut = sqlite3_normalize(zIn);
- if( zOut ){
- printf("%s\n", zOut);
- sqlite3_free(zOut);
- }else{
- fprintf(stderr, "ERROR: %s\n", zIn);
- }
- zIn[i+1] = cSaved;
- zIn += i+1;
- i = -1;
- }else{
- zIn[i+1] = cSaved;
- }
- }
-}
-
-/*
-** The main routine for "sql_normalize". Read files named on the
-** command-line and run the text of each through sqlite3_normalize().
-*/
-int main(int argc, char **argv){
- int i;
- FILE *in;
- char *zBuf = 0;
- sqlite3_int64 sz, got;
-
- for(i=1; i<argc; i++){
- in = fopen(argv[i], "rb");
- if( in==0 ){
- fprintf(stderr, "cannot open \"%s\"\n", argv[i]);
- continue;
- }
- fseek(in, 0, SEEK_END);
- sz = ftell(in);
- rewind(in);
- zBuf = sqlite3_realloc64(zBuf, sz+1);
- if( zBuf==0 ){
- fprintf(stderr, "failed to malloc for %lld bytes\n", sz);
- exit(1);
- }
- got = fread(zBuf, 1, sz, in);
- fclose(in);
- if( got!=sz ){
- fprintf(stderr, "only able to read %lld of %lld bytes from \"%s\"\n",
- got, sz, argv[i]);
- }else{
- zBuf[got] = 0;
- normalizeFile(zBuf);
- }
- }
- sqlite3_free(zBuf);
-}
-#endif /* SQLITE_NORMALIZE_CLI */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/percentile.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/percentile.c
deleted file mode 100644
index a5d7e84913a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/percentile.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-** 2013-05-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 contains code to implement the percentile(Y,P) SQL function
-** as described below:
-**
-** (1) The percentile(Y,P) function is an aggregate function taking
-** exactly two arguments.
-**
-** (2) If the P argument to percentile(Y,P) is not the same for every
-** row in the aggregate then an error is thrown. The word "same"
-** in the previous sentence means that the value differ by less
-** than 0.001.
-**
-** (3) If the P argument to percentile(Y,P) evaluates to anything other
-** than a number in the range of 0.0 to 100.0 inclusive then an
-** error is thrown.
-**
-** (4) If any Y argument to percentile(Y,P) evaluates to a value that
-** is not NULL and is not numeric then an error is thrown.
-**
-** (5) If any Y argument to percentile(Y,P) evaluates to plus or minus
-** infinity then an error is thrown. (SQLite always interprets NaN
-** values as NULL.)
-**
-** (6) Both Y and P in percentile(Y,P) can be arbitrary expressions,
-** including CASE WHEN expressions.
-**
-** (7) The percentile(Y,P) aggregate is able to handle inputs of at least
-** one million (1,000,000) rows.
-**
-** (8) If there are no non-NULL values for Y, then percentile(Y,P)
-** returns NULL.
-**
-** (9) If there is exactly one non-NULL value for Y, the percentile(Y,P)
-** returns the one Y value.
-**
-** (10) If there N non-NULL values of Y where N is two or more and
-** the Y values are ordered from least to greatest and a graph is
-** drawn from 0 to N-1 such that the height of the graph at J is
-** the J-th Y value and such that straight lines are drawn between
-** adjacent Y values, then the percentile(Y,P) function returns
-** the height of the graph at P*(N-1)/100.
-**
-** (11) The percentile(Y,P) function always returns either a floating
-** point number or NULL.
-**
-** (12) The percentile(Y,P) is implemented as a single C99 source-code
-** file that compiles into a shared-library or DLL that can be loaded
-** into SQLite using the sqlite3_load_extension() interface.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-/* The following object is the session context for a single percentile()
-** function. We have to remember all input Y values until the very end.
-** Those values are accumulated in the Percentile.a[] array.
-*/
-typedef struct Percentile Percentile;
-struct Percentile {
- unsigned nAlloc; /* Number of slots allocated for a[] */
- unsigned nUsed; /* Number of slots actually used in a[] */
- double rPct; /* 1.0 more than the value for P */
- double *a; /* Array of Y values */
-};
-
-/*
-** Return TRUE if the input floating-point number is an infinity.
-*/
-static int isInfinity(double r){
- sqlite3_uint64 u;
- assert( sizeof(u)==sizeof(r) );
- memcpy(&u, &r, sizeof(u));
- return ((u>>52)&0x7ff)==0x7ff;
-}
-
-/*
-** Return TRUE if two doubles differ by 0.001 or less
-*/
-static int sameValue(double a, double b){
- a -= b;
- return a>=-0.001 && a<=0.001;
-}
-
-/*
-** The "step" function for percentile(Y,P) is called once for each
-** input row.
-*/
-static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
- Percentile *p;
- double rPct;
- int eType;
- double y;
- assert( argc==2 );
-
- /* Requirement 3: P must be a number between 0 and 100 */
- eType = sqlite3_value_numeric_type(argv[1]);
- rPct = sqlite3_value_double(argv[1]);
- if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) ||
- ((rPct = sqlite3_value_double(argv[1]))<0.0 || rPct>100.0) ){
- sqlite3_result_error(pCtx, "2nd argument to percentile() is not "
- "a number between 0.0 and 100.0", -1);
- return;
- }
-
- /* Allocate the session context. */
- p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
- if( p==0 ) return;
-
- /* Remember the P value. Throw an error if the P value is different
- ** from any prior row, per Requirement (2). */
- if( p->rPct==0.0 ){
- p->rPct = rPct+1.0;
- }else if( !sameValue(p->rPct,rPct+1.0) ){
- sqlite3_result_error(pCtx, "2nd argument to percentile() is not the "
- "same for all input rows", -1);
- return;
- }
-
- /* Ignore rows for which Y is NULL */
- eType = sqlite3_value_type(argv[0]);
- if( eType==SQLITE_NULL ) return;
-
- /* If not NULL, then Y must be numeric. Otherwise throw an error.
- ** Requirement 4 */
- if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
- sqlite3_result_error(pCtx, "1st argument to percentile() is not "
- "numeric", -1);
- return;
- }
-
- /* Throw an error if the Y value is infinity or NaN */
- y = sqlite3_value_double(argv[0]);
- if( isInfinity(y) ){
- sqlite3_result_error(pCtx, "Inf input to percentile()", -1);
- return;
- }
-
- /* Allocate and store the Y */
- if( p->nUsed>=p->nAlloc ){
- unsigned n = p->nAlloc*2 + 250;
- double *a = sqlite3_realloc(p->a, sizeof(double)*n);
- if( a==0 ){
- sqlite3_free(p->a);
- memset(p, 0, sizeof(*p));
- sqlite3_result_error_nomem(pCtx);
- return;
- }
- p->nAlloc = n;
- p->a = a;
- }
- p->a[p->nUsed++] = y;
-}
-
-/*
-** Compare to doubles for sorting using qsort()
-*/
-static int SQLITE_CDECL doubleCmp(const void *pA, const void *pB){
- double a = *(double*)pA;
- double b = *(double*)pB;
- if( a==b ) return 0;
- if( a<b ) return -1;
- return +1;
-}
-
-/*
-** Called to compute the final output of percentile() and to clean
-** up all allocated memory.
-*/
-static void percentFinal(sqlite3_context *pCtx){
- Percentile *p;
- unsigned i1, i2;
- double v1, v2;
- double ix, vx;
- p = (Percentile*)sqlite3_aggregate_context(pCtx, 0);
- if( p==0 ) return;
- if( p->a==0 ) return;
- if( p->nUsed ){
- qsort(p->a, p->nUsed, sizeof(double), doubleCmp);
- ix = (p->rPct-1.0)*(p->nUsed-1)*0.01;
- i1 = (unsigned)ix;
- i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
- v1 = p->a[i1];
- v2 = p->a[i2];
- vx = v1 + (v2-v1)*(ix-i1);
- sqlite3_result_double(pCtx, vx);
- }
- sqlite3_free(p->a);
- memset(p, 0, sizeof(*p));
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_percentile_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "percentile", 2, SQLITE_UTF8, 0,
- 0, percentStep, percentFinal);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/regexp.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/regexp.c
deleted file mode 100644
index b4a8ab5c042..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/regexp.c
+++ /dev/null
@@ -1,760 +0,0 @@
-/*
-** 2012-11-13
-**
-** 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.
-**
-******************************************************************************
-**
-** The code in this file implements a compact but reasonably
-** efficient regular-expression matcher for posix extended regular
-** expressions against UTF8 text.
-**
-** This file is an SQLite extension. It registers a single function
-** named "regexp(A,B)" where A is the regular expression and B is the
-** string to be matched. By registering this function, SQLite will also
-** then implement the "B regexp A" operator. Note that with the function
-** the regular expression comes first, but with the operator it comes
-** second.
-**
-** The following regular expression syntax is supported:
-**
-** X* zero or more occurrences of X
-** X+ one or more occurrences of X
-** X? zero or one occurrences of X
-** X{p,q} between p and q occurrences of X
-** (X) match X
-** X|Y X or Y
-** ^X X occurring at the beginning of the string
-** X$ X occurring at the end of the string
-** . Match any single character
-** \c Character c where c is one of \{}()[]|*+?.
-** \c C-language escapes for c in afnrtv. ex: \t or \n
-** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
-** \xXX Where XX is exactly 2 hex digits, unicode value XX
-** [abc] Any single character from the set abc
-** [^abc] Any single character not in the set abc
-** [a-z] Any single character in the range a-z
-** [^a-z] Any single character not in the range a-z
-** \b Word boundary
-** \w Word character. [A-Za-z0-9_]
-** \W Non-word character
-** \d Digit
-** \D Non-digit
-** \s Whitespace character
-** \S Non-whitespace character
-**
-** A nondeterministic finite automaton (NFA) is used for matching, so the
-** performance is bounded by O(N*M) where N is the size of the regular
-** expression and M is the size of the input string. The matcher never
-** exhibits exponential behavior. Note that the X{p,q} operator expands
-** to p copies of X following by q-p copies of X? and that the size of the
-** regular expression in the O(N*M) performance bound is computed after
-** this expansion.
-*/
-#include <string.h>
-#include <stdlib.h>
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-/*
-** The following #defines change the names of some functions implemented in
-** this file to prevent name collisions with C-library functions of the
-** same name.
-*/
-#define re_match sqlite3re_match
-#define re_compile sqlite3re_compile
-#define re_free sqlite3re_free
-
-/* The end-of-input character */
-#define RE_EOF 0 /* End of input */
-
-/* The NFA is implemented as sequence of opcodes taken from the following
-** set. Each opcode has a single integer argument.
-*/
-#define RE_OP_MATCH 1 /* Match the one character in the argument */
-#define RE_OP_ANY 2 /* Match any one character. (Implements ".") */
-#define RE_OP_ANYSTAR 3 /* Special optimized version of .* */
-#define RE_OP_FORK 4 /* Continue to both next and opcode at iArg */
-#define RE_OP_GOTO 5 /* Jump to opcode at iArg */
-#define RE_OP_ACCEPT 6 /* Halt and indicate a successful match */
-#define RE_OP_CC_INC 7 /* Beginning of a [...] character class */
-#define RE_OP_CC_EXC 8 /* Beginning of a [^...] character class */
-#define RE_OP_CC_VALUE 9 /* Single value in a character class */
-#define RE_OP_CC_RANGE 10 /* Range of values in a character class */
-#define RE_OP_WORD 11 /* Perl word character [A-Za-z0-9_] */
-#define RE_OP_NOTWORD 12 /* Not a perl word character */
-#define RE_OP_DIGIT 13 /* digit: [0-9] */
-#define RE_OP_NOTDIGIT 14 /* Not a digit */
-#define RE_OP_SPACE 15 /* space: [ \t\n\r\v\f] */
-#define RE_OP_NOTSPACE 16 /* Not a digit */
-#define RE_OP_BOUNDARY 17 /* Boundary between word and non-word */
-
-/* Each opcode is a "state" in the NFA */
-typedef unsigned short ReStateNumber;
-
-/* Because this is an NFA and not a DFA, multiple states can be active at
-** once. An instance of the following object records all active states in
-** the NFA. The implementation is optimized for the common case where the
-** number of actives states is small.
-*/
-typedef struct ReStateSet {
- unsigned nState; /* Number of current states */
- ReStateNumber *aState; /* Current states */
-} ReStateSet;
-
-/* An input string read one character at a time.
-*/
-typedef struct ReInput ReInput;
-struct ReInput {
- const unsigned char *z; /* All text */
- int i; /* Next byte to read */
- int mx; /* EOF when i>=mx */
-};
-
-/* A compiled NFA (or an NFA that is in the process of being compiled) is
-** an instance of the following object.
-*/
-typedef struct ReCompiled ReCompiled;
-struct ReCompiled {
- ReInput sIn; /* Regular expression text */
- const char *zErr; /* Error message to return */
- char *aOp; /* Operators for the virtual machine */
- int *aArg; /* Arguments to each operator */
- unsigned (*xNextChar)(ReInput*); /* Next character function */
- unsigned char zInit[12]; /* Initial text to match */
- int nInit; /* Number of characters in zInit */
- unsigned nState; /* Number of entries in aOp[] and aArg[] */
- unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
-};
-
-/* Add a state to the given state set if it is not already there */
-static void re_add_state(ReStateSet *pSet, int newState){
- unsigned i;
- for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
- pSet->aState[pSet->nState++] = (ReStateNumber)newState;
-}
-
-/* Extract the next unicode character from *pzIn and return it. Advance
-** *pzIn to the first byte past the end of the character returned. To
-** be clear: this routine converts utf8 to unicode. This routine is
-** optimized for the common case where the next character is a single byte.
-*/
-static unsigned re_next_char(ReInput *p){
- unsigned c;
- if( p->i>=p->mx ) return 0;
- c = p->z[p->i++];
- if( c>=0x80 ){
- if( (c&0xe0)==0xc0 && p->i<p->mx && (p->z[p->i]&0xc0)==0x80 ){
- c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f);
- if( c<0x80 ) c = 0xfffd;
- }else if( (c&0xf0)==0xe0 && p->i+1<p->mx && (p->z[p->i]&0xc0)==0x80
- && (p->z[p->i+1]&0xc0)==0x80 ){
- c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
- p->i += 2;
- if( c<=0x3ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
- }else if( (c&0xf8)==0xf0 && p->i+3<p->mx && (p->z[p->i]&0xc0)==0x80
- && (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
- c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
- | (p->z[p->i+2]&0x3f);
- p->i += 3;
- if( c<=0xffff || c>0x10ffff ) c = 0xfffd;
- }else{
- c = 0xfffd;
- }
- }
- return c;
-}
-static unsigned re_next_char_nocase(ReInput *p){
- unsigned c = re_next_char(p);
- if( c>='A' && c<='Z' ) c += 'a' - 'A';
- return c;
-}
-
-/* Return true if c is a perl "word" character: [A-Za-z0-9_] */
-static int re_word_char(int c){
- return (c>='0' && c<='9') || (c>='a' && c<='z')
- || (c>='A' && c<='Z') || c=='_';
-}
-
-/* Return true if c is a "digit" character: [0-9] */
-static int re_digit_char(int c){
- return (c>='0' && c<='9');
-}
-
-/* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
-static int re_space_char(int c){
- return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
-}
-
-/* Run a compiled regular expression on the zero-terminated input
-** string zIn[]. Return true on a match and false if there is no match.
-*/
-static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
- ReStateSet aStateSet[2], *pThis, *pNext;
- ReStateNumber aSpace[100];
- ReStateNumber *pToFree;
- unsigned int i = 0;
- unsigned int iSwap = 0;
- int c = RE_EOF+1;
- int cPrev = 0;
- int rc = 0;
- ReInput in;
-
- in.z = zIn;
- in.i = 0;
- in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);
-
- /* Look for the initial prefix match, if there is one. */
- if( pRe->nInit ){
- unsigned char x = pRe->zInit[0];
- while( in.i+pRe->nInit<=in.mx
- && (zIn[in.i]!=x ||
- strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
- ){
- in.i++;
- }
- if( in.i+pRe->nInit>in.mx ) return 0;
- }
-
- if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
- pToFree = 0;
- aStateSet[0].aState = aSpace;
- }else{
- pToFree = sqlite3_malloc( sizeof(ReStateNumber)*2*pRe->nState );
- if( pToFree==0 ) return -1;
- aStateSet[0].aState = pToFree;
- }
- aStateSet[1].aState = &aStateSet[0].aState[pRe->nState];
- pNext = &aStateSet[1];
- pNext->nState = 0;
- re_add_state(pNext, 0);
- while( c!=RE_EOF && pNext->nState>0 ){
- cPrev = c;
- c = pRe->xNextChar(&in);
- pThis = pNext;
- pNext = &aStateSet[iSwap];
- iSwap = 1 - iSwap;
- pNext->nState = 0;
- for(i=0; i<pThis->nState; i++){
- int x = pThis->aState[i];
- switch( pRe->aOp[x] ){
- case RE_OP_MATCH: {
- if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
- break;
- }
- case RE_OP_ANY: {
- re_add_state(pNext, x+1);
- break;
- }
- case RE_OP_WORD: {
- if( re_word_char(c) ) re_add_state(pNext, x+1);
- break;
- }
- case RE_OP_NOTWORD: {
- if( !re_word_char(c) ) re_add_state(pNext, x+1);
- break;
- }
- case RE_OP_DIGIT: {
- if( re_digit_char(c) ) re_add_state(pNext, x+1);
- break;
- }
- case RE_OP_NOTDIGIT: {
- if( !re_digit_char(c) ) re_add_state(pNext, x+1);
- break;
- }
- case RE_OP_SPACE: {
- if( re_space_char(c) ) re_add_state(pNext, x+1);
- break;
- }
- case RE_OP_NOTSPACE: {
- if( !re_space_char(c) ) re_add_state(pNext, x+1);
- break;
- }
- case RE_OP_BOUNDARY: {
- if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
- break;
- }
- case RE_OP_ANYSTAR: {
- re_add_state(pNext, x);
- re_add_state(pThis, x+1);
- break;
- }
- case RE_OP_FORK: {
- re_add_state(pThis, x+pRe->aArg[x]);
- re_add_state(pThis, x+1);
- break;
- }
- case RE_OP_GOTO: {
- re_add_state(pThis, x+pRe->aArg[x]);
- break;
- }
- case RE_OP_ACCEPT: {
- rc = 1;
- goto re_match_end;
- }
- case RE_OP_CC_INC:
- case RE_OP_CC_EXC: {
- int j = 1;
- int n = pRe->aArg[x];
- int hit = 0;
- for(j=1; j>0 && j<n; j++){
- if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
- if( pRe->aArg[x+j]==c ){
- hit = 1;
- j = -1;
- }
- }else{
- if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){
- hit = 1;
- j = -1;
- }else{
- j++;
- }
- }
- }
- if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
- if( hit ) re_add_state(pNext, x+n);
- break;
- }
- }
- }
- }
- for(i=0; i<pNext->nState; i++){
- if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }
- }
-re_match_end:
- sqlite3_free(pToFree);
- return rc;
-}
-
-/* Resize the opcode and argument arrays for an RE under construction.
-*/
-static int re_resize(ReCompiled *p, int N){
- char *aOp;
- int *aArg;
- aOp = sqlite3_realloc(p->aOp, N*sizeof(p->aOp[0]));
- if( aOp==0 ) return 1;
- p->aOp = aOp;
- aArg = sqlite3_realloc(p->aArg, N*sizeof(p->aArg[0]));
- if( aArg==0 ) return 1;
- p->aArg = aArg;
- p->nAlloc = N;
- return 0;
-}
-
-/* Insert a new opcode and argument into an RE under construction. The
-** insertion point is just prior to existing opcode iBefore.
-*/
-static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
- int i;
- if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
- for(i=p->nState; i>iBefore; i--){
- p->aOp[i] = p->aOp[i-1];
- p->aArg[i] = p->aArg[i-1];
- }
- p->nState++;
- p->aOp[iBefore] = (char)op;
- p->aArg[iBefore] = arg;
- return iBefore;
-}
-
-/* Append a new opcode and argument to the end of the RE under construction.
-*/
-static int re_append(ReCompiled *p, int op, int arg){
- return re_insert(p, p->nState, op, arg);
-}
-
-/* Make a copy of N opcodes starting at iStart onto the end of the RE
-** under construction.
-*/
-static void re_copy(ReCompiled *p, int iStart, int N){
- if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return;
- memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0]));
- memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0]));
- p->nState += N;
-}
-
-/* Return true if c is a hexadecimal digit character: [0-9a-fA-F]
-** If c is a hex digit, also set *pV = (*pV)*16 + valueof(c). If
-** c is not a hex digit *pV is unchanged.
-*/
-static int re_hex(int c, int *pV){
- if( c>='0' && c<='9' ){
- c -= '0';
- }else if( c>='a' && c<='f' ){
- c -= 'a' - 10;
- }else if( c>='A' && c<='F' ){
- c -= 'A' - 10;
- }else{
- return 0;
- }
- *pV = (*pV)*16 + (c & 0xff);
- return 1;
-}
-
-/* A backslash character has been seen, read the next character and
-** return its interpretation.
-*/
-static unsigned re_esc_char(ReCompiled *p){
- static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
- static const char zTrans[] = "\a\f\n\r\t\v";
- int i, v = 0;
- char c;
- if( p->sIn.i>=p->sIn.mx ) return 0;
- c = p->sIn.z[p->sIn.i];
- if( c=='u' && p->sIn.i+4<p->sIn.mx ){
- const unsigned char *zIn = p->sIn.z + p->sIn.i;
- if( re_hex(zIn[1],&v)
- && re_hex(zIn[2],&v)
- && re_hex(zIn[3],&v)
- && re_hex(zIn[4],&v)
- ){
- p->sIn.i += 5;
- return v;
- }
- }
- if( c=='x' && p->sIn.i+2<p->sIn.mx ){
- const unsigned char *zIn = p->sIn.z + p->sIn.i;
- if( re_hex(zIn[1],&v)
- && re_hex(zIn[2],&v)
- ){
- p->sIn.i += 3;
- return v;
- }
- }
- for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
- if( zEsc[i] ){
- if( i<6 ) c = zTrans[i];
- p->sIn.i++;
- }else{
- p->zErr = "unknown \\ escape";
- }
- return c;
-}
-
-/* Forward declaration */
-static const char *re_subcompile_string(ReCompiled*);
-
-/* Peek at the next byte of input */
-static unsigned char rePeek(ReCompiled *p){
- return p->sIn.i<p->sIn.mx ? p->sIn.z[p->sIn.i] : 0;
-}
-
-/* Compile RE text into a sequence of opcodes. Continue up to the
-** first unmatched ")" character, then return. If an error is found,
-** return a pointer to the error message string.
-*/
-static const char *re_subcompile_re(ReCompiled *p){
- const char *zErr;
- int iStart, iEnd, iGoto;
- iStart = p->nState;
- zErr = re_subcompile_string(p);
- if( zErr ) return zErr;
- while( rePeek(p)=='|' ){
- iEnd = p->nState;
- re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart);
- iGoto = re_append(p, RE_OP_GOTO, 0);
- p->sIn.i++;
- zErr = re_subcompile_string(p);
- if( zErr ) return zErr;
- p->aArg[iGoto] = p->nState - iGoto;
- }
- return 0;
-}
-
-/* Compile an element of regular expression text (anything that can be
-** an operand to the "|" operator). Return NULL on success or a pointer
-** to the error message if there is a problem.
-*/
-static const char *re_subcompile_string(ReCompiled *p){
- int iPrev = -1;
- int iStart;
- unsigned c;
- const char *zErr;
- while( (c = p->xNextChar(&p->sIn))!=0 ){
- iStart = p->nState;
- switch( c ){
- case '|':
- case '$':
- case ')': {
- p->sIn.i--;
- return 0;
- }
- case '(': {
- zErr = re_subcompile_re(p);
- if( zErr ) return zErr;
- if( rePeek(p)!=')' ) return "unmatched '('";
- p->sIn.i++;
- break;
- }
- case '.': {
- if( rePeek(p)=='*' ){
- re_append(p, RE_OP_ANYSTAR, 0);
- p->sIn.i++;
- }else{
- re_append(p, RE_OP_ANY, 0);
- }
- break;
- }
- case '*': {
- if( iPrev<0 ) return "'*' without operand";
- re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
- re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
- break;
- }
- case '+': {
- if( iPrev<0 ) return "'+' without operand";
- re_append(p, RE_OP_FORK, iPrev - p->nState);
- break;
- }
- case '?': {
- if( iPrev<0 ) return "'?' without operand";
- re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
- break;
- }
- case '{': {
- int m = 0, n = 0;
- int sz, j;
- if( iPrev<0 ) return "'{m,n}' without operand";
- while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; }
- n = m;
- if( c==',' ){
- p->sIn.i++;
- n = 0;
- while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; }
- }
- if( c!='}' ) return "unmatched '{'";
- if( n>0 && n<m ) return "n less than m in '{m,n}'";
- p->sIn.i++;
- sz = p->nState - iPrev;
- if( m==0 ){
- if( n==0 ) return "both m and n are zero in '{m,n}'";
- re_insert(p, iPrev, RE_OP_FORK, sz+1);
- n--;
- }else{
- for(j=1; j<m; j++) re_copy(p, iPrev, sz);
- }
- for(j=m; j<n; j++){
- re_append(p, RE_OP_FORK, sz+1);
- re_copy(p, iPrev, sz);
- }
- if( n==0 && m>0 ){
- re_append(p, RE_OP_FORK, -sz);
- }
- break;
- }
- case '[': {
- int iFirst = p->nState;
- if( rePeek(p)=='^' ){
- re_append(p, RE_OP_CC_EXC, 0);
- p->sIn.i++;
- }else{
- re_append(p, RE_OP_CC_INC, 0);
- }
- while( (c = p->xNextChar(&p->sIn))!=0 ){
- if( c=='[' && rePeek(p)==':' ){
- return "POSIX character classes not supported";
- }
- if( c=='\\' ) c = re_esc_char(p);
- if( rePeek(p)=='-' ){
- re_append(p, RE_OP_CC_RANGE, c);
- p->sIn.i++;
- c = p->xNextChar(&p->sIn);
- if( c=='\\' ) c = re_esc_char(p);
- re_append(p, RE_OP_CC_RANGE, c);
- }else{
- re_append(p, RE_OP_CC_VALUE, c);
- }
- if( rePeek(p)==']' ){ p->sIn.i++; break; }
- }
- if( c==0 ) return "unclosed '['";
- p->aArg[iFirst] = p->nState - iFirst;
- break;
- }
- case '\\': {
- int specialOp = 0;
- switch( rePeek(p) ){
- case 'b': specialOp = RE_OP_BOUNDARY; break;
- case 'd': specialOp = RE_OP_DIGIT; break;
- case 'D': specialOp = RE_OP_NOTDIGIT; break;
- case 's': specialOp = RE_OP_SPACE; break;
- case 'S': specialOp = RE_OP_NOTSPACE; break;
- case 'w': specialOp = RE_OP_WORD; break;
- case 'W': specialOp = RE_OP_NOTWORD; break;
- }
- if( specialOp ){
- p->sIn.i++;
- re_append(p, specialOp, 0);
- }else{
- c = re_esc_char(p);
- re_append(p, RE_OP_MATCH, c);
- }
- break;
- }
- default: {
- re_append(p, RE_OP_MATCH, c);
- break;
- }
- }
- iPrev = iStart;
- }
- return 0;
-}
-
-/* Free and reclaim all the memory used by a previously compiled
-** regular expression. Applications should invoke this routine once
-** for every call to re_compile() to avoid memory leaks.
-*/
-void re_free(ReCompiled *pRe){
- if( pRe ){
- sqlite3_free(pRe->aOp);
- sqlite3_free(pRe->aArg);
- sqlite3_free(pRe);
- }
-}
-
-/*
-** Compile a textual regular expression in zIn[] into a compiled regular
-** expression suitable for us by re_match() and return a pointer to the
-** compiled regular expression in *ppRe. Return NULL on success or an
-** error message if something goes wrong.
-*/
-const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
- ReCompiled *pRe;
- const char *zErr;
- int i, j;
-
- *ppRe = 0;
- pRe = sqlite3_malloc( sizeof(*pRe) );
- if( pRe==0 ){
- return "out of memory";
- }
- memset(pRe, 0, sizeof(*pRe));
- pRe->xNextChar = noCase ? re_next_char_nocase : re_next_char;
- if( re_resize(pRe, 30) ){
- re_free(pRe);
- return "out of memory";
- }
- if( zIn[0]=='^' ){
- zIn++;
- }else{
- re_append(pRe, RE_OP_ANYSTAR, 0);
- }
- pRe->sIn.z = (unsigned char*)zIn;
- pRe->sIn.i = 0;
- pRe->sIn.mx = (int)strlen(zIn);
- zErr = re_subcompile_re(pRe);
- if( zErr ){
- re_free(pRe);
- return zErr;
- }
- if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
- re_append(pRe, RE_OP_MATCH, RE_EOF);
- re_append(pRe, RE_OP_ACCEPT, 0);
- *ppRe = pRe;
- }else if( pRe->sIn.i>=pRe->sIn.mx ){
- re_append(pRe, RE_OP_ACCEPT, 0);
- *ppRe = pRe;
- }else{
- re_free(pRe);
- return "unrecognized character";
- }
-
- /* The following is a performance optimization. If the regex begins with
- ** ".*" (if the input regex lacks an initial "^") and afterwards there are
- ** one or more matching characters, enter those matching characters into
- ** zInit[]. The re_match() routine can then search ahead in the input
- ** string looking for the initial match without having to run the whole
- ** regex engine over the string. Do not worry able trying to match
- ** unicode characters beyond plane 0 - those are very rare and this is
- ** just an optimization. */
- if( pRe->aOp[0]==RE_OP_ANYSTAR ){
- for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
- unsigned x = pRe->aArg[i];
- if( x<=127 ){
- pRe->zInit[j++] = (unsigned char)x;
- }else if( x<=0xfff ){
- pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
- pRe->zInit[j++] = 0x80 | (x&0x3f);
- }else if( x<=0xffff ){
- pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
- pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
- pRe->zInit[j++] = 0x80 | (x&0x3f);
- }else{
- break;
- }
- }
- if( j>0 && pRe->zInit[j-1]==0 ) j--;
- pRe->nInit = j;
- }
- return pRe->zErr;
-}
-
-/*
-** Implementation of the regexp() SQL function. This function implements
-** the build-in REGEXP operator. The first argument to the function is the
-** pattern and the second argument is the string. So, the SQL statements:
-**
-** A REGEXP B
-**
-** is implemented as regexp(B,A).
-*/
-static void re_sql_func(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- ReCompiled *pRe; /* Compiled regular expression */
- const char *zPattern; /* The regular expression */
- const unsigned char *zStr;/* String being searched */
- const char *zErr; /* Compile error message */
- int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
-
- pRe = sqlite3_get_auxdata(context, 0);
- if( pRe==0 ){
- zPattern = (const char*)sqlite3_value_text(argv[0]);
- if( zPattern==0 ) return;
- zErr = re_compile(&pRe, zPattern, 0);
- if( zErr ){
- re_free(pRe);
- sqlite3_result_error(context, zErr, -1);
- return;
- }
- if( pRe==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- setAux = 1;
- }
- zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
- if( zStr!=0 ){
- sqlite3_result_int(context, re_match(pRe, zStr, -1));
- }
- if( setAux ){
- sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
- }
-}
-
-/*
-** Invoke this routine to register the regexp() function with the
-** SQLite database connection.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_regexp_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
- re_sql_func, 0, 0);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/remember.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/remember.c
deleted file mode 100644
index 18f6edec9d3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/remember.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-** 2016-08-09
-**
-** 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 demonstrates how to create an SQL function that is a pass-through
-** for integer values (it returns a copy of its argument) but also saves the
-** value that is passed through into a C-language variable. The address of
-** the C-language variable is supplied as the second argument.
-**
-** This allows, for example, a counter to incremented and the original
-** value retrieved, atomically, using a single statement:
-**
-** UPDATE counterTab SET cnt=remember(cnt,$PTR)+1 WHERE id=$ID
-**
-** Prepare the above statement once. Then to use it, bind the address
-** of the output variable to $PTR using sqlite3_bind_pointer() with a
-** pointer type of "carray" and bind the id of the counter to $ID and
-** run the prepared statement.
-**
-** This implementation of the remember() function uses a "carray"
-** pointer so that it can share pointers with the carray() extension.
-**
-** One can imagine doing similar things with floating-point values and
-** strings, but this demonstration extension will stick to using just
-** integers.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-
-/*
-** remember(V,PTR)
-**
-** Return the integer value V. Also save the value of V in a
-** C-language variable whose address is PTR.
-*/
-static void rememberFunc(
- sqlite3_context *pCtx,
- int argc,
- sqlite3_value **argv
-){
- sqlite3_int64 v;
- sqlite3_int64 *ptr;
- assert( argc==2 );
- v = sqlite3_value_int64(argv[0]);
- ptr = sqlite3_value_pointer(argv[1], "carray");
- if( ptr ) *ptr = v;
- sqlite3_result_int64(pCtx, v);
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_remember_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- rc = sqlite3_create_function(db, "remember", 2, SQLITE_UTF8, 0,
- rememberFunc, 0, 0);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/rot13.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/rot13.c
deleted file mode 100644
index 2e9dd21c60a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/rot13.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-** 2013-05-15
-**
-** 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 SQLite extension implements a rot13() function and a rot13
-** collating sequence.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-/*
-** Perform rot13 encoding on a single ASCII character.
-*/
-static unsigned char rot13(unsigned char c){
- if( c>='a' && c<='z' ){
- c += 13;
- if( c>'z' ) c -= 26;
- }else if( c>='A' && c<='Z' ){
- c += 13;
- if( c>'Z' ) c -= 26;
- }
- return c;
-}
-
-/*
-** Implementation of the rot13() function.
-**
-** Rotate ASCII alphabetic characters by 13 character positions.
-** Non-ASCII characters are unchanged. rot13(rot13(X)) should always
-** equal X.
-*/
-static void rot13func(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zIn;
- int nIn;
- unsigned char *zOut;
- unsigned char *zToFree = 0;
- int i;
- unsigned char zTemp[100];
- assert( argc==1 );
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- zIn = (const unsigned char*)sqlite3_value_text(argv[0]);
- nIn = sqlite3_value_bytes(argv[0]);
- if( nIn<sizeof(zTemp)-1 ){
- zOut = zTemp;
- }else{
- zOut = zToFree = (unsigned char*)sqlite3_malloc64( nIn+1 );
- if( zOut==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- }
- for(i=0; i<nIn; i++) zOut[i] = rot13(zIn[i]);
- zOut[i] = 0;
- sqlite3_result_text(context, (char*)zOut, i, SQLITE_TRANSIENT);
- sqlite3_free(zToFree);
-}
-
-/*
-** Implement the rot13 collating sequence so that if
-**
-** x=y COLLATE rot13
-**
-** Then
-**
-** rot13(x)=rot13(y) COLLATE binary
-*/
-static int rot13CollFunc(
- void *notUsed,
- int nKey1, const void *pKey1,
- int nKey2, const void *pKey2
-){
- const char *zA = (const char*)pKey1;
- const char *zB = (const char*)pKey2;
- int i, x;
- for(i=0; i<nKey1 && i<nKey2; i++){
- x = (int)rot13(zA[i]) - (int)rot13(zB[i]);
- if( x!=0 ) return x;
- }
- return nKey1 - nKey2;
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_rot_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "rot13", 1, SQLITE_UTF8, 0,
- rot13func, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_collation(db, "rot13", SQLITE_UTF8, 0, rot13CollFunc);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/scrub.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/scrub.c
deleted file mode 100644
index 4eb56b0fc27..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/scrub.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
-** 2016-05-05
-**
-** 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 a utility function (and a utility program) that
-** makes a copy of an SQLite database while simultaneously zeroing out all
-** deleted content.
-**
-** Normally (when PRAGMA secure_delete=OFF, which is the default) when SQLite
-** deletes content, it does not overwrite the deleted content but rather marks
-** the region of the file that held that content as being reusable. This can
-** cause deleted content to recoverable from the database file. This stale
-** content is removed by the VACUUM command, but VACUUM can be expensive for
-** large databases. When in PRAGMA secure_delete=ON mode, the deleted content
-** is zeroed, but secure_delete=ON has overhead as well.
-**
-** This utility attempts to make a copy of a complete SQLite database where
-** all of the deleted content is zeroed out in the copy, and it attempts to
-** do so while being faster than running VACUUM.
-**
-** Usage:
-**
-** int sqlite3_scrub_backup(
-** const char *zSourceFile, // Source database filename
-** const char *zDestFile, // Destination database filename
-** char **pzErrMsg // Write error message here
-** );
-**
-** Simply call the API above specifying the filename of the source database
-** and the name of the backup copy. The source database must already exist
-** and can be in active use. (A read lock is held during the backup.) The
-** destination file should not previously exist. If the pzErrMsg parameter
-** is non-NULL and if an error occurs, then an error message might be written
-** into memory obtained from sqlite3_malloc() and *pzErrMsg made to point to
-** that error message. But if the error is an OOM, the error might not be
-** reported. The routine always returns non-zero if there is an error.
-**
-** If compiled with -DSCRUB_STANDALONE then a main() procedure is added and
-** this file becomes a standalone program that can be run as follows:
-**
-** ./sqlite3scrub SOURCE DEST
-*/
-#include "sqlite3.h"
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-typedef struct ScrubState ScrubState;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-
-/* State information for a scrub-and-backup operation */
-struct ScrubState {
- const char *zSrcFile; /* Name of the source file */
- const char *zDestFile; /* Name of the destination file */
- int rcErr; /* Error code */
- char *zErr; /* Error message text */
- sqlite3 *dbSrc; /* Source database connection */
- sqlite3_file *pSrc; /* Source file handle */
- sqlite3 *dbDest; /* Destination database connection */
- sqlite3_file *pDest; /* Destination file handle */
- u32 szPage; /* Page size */
- u32 szUsable; /* Usable bytes on each page */
- u32 nPage; /* Number of pages */
- u32 iLastPage; /* Page number of last page written so far*/
- u8 *page1; /* Content of page 1 */
-};
-
-/* Store an error message */
-static void scrubBackupErr(ScrubState *p, const char *zFormat, ...){
- va_list ap;
- sqlite3_free(p->zErr);
- va_start(ap, zFormat);
- p->zErr = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- if( p->rcErr==0 ) p->rcErr = SQLITE_ERROR;
-}
-
-/* Allocate memory to hold a single page of content */
-static u8 *scrubBackupAllocPage(ScrubState *p){
- u8 *pPage;
- if( p->rcErr ) return 0;
- pPage = sqlite3_malloc( p->szPage );
- if( pPage==0 ) p->rcErr = SQLITE_NOMEM;
- return pPage;
-}
-
-/* Read a page from the source database into memory. Use the memory
-** provided by pBuf if not NULL or allocate a new page if pBuf==NULL.
-*/
-static u8 *scrubBackupRead(ScrubState *p, int pgno, u8 *pBuf){
- int rc;
- sqlite3_int64 iOff;
- u8 *pOut = pBuf;
- if( p->rcErr ) return 0;
- if( pOut==0 ){
- pOut = scrubBackupAllocPage(p);
- if( pOut==0 ) return 0;
- }
- iOff = (pgno-1)*(sqlite3_int64)p->szPage;
- rc = p->pSrc->pMethods->xRead(p->pSrc, pOut, p->szPage, iOff);
- if( rc!=SQLITE_OK ){
- if( pBuf==0 ) sqlite3_free(pOut);
- pOut = 0;
- scrubBackupErr(p, "read failed for page %d", pgno);
- p->rcErr = SQLITE_IOERR;
- }
- return pOut;
-}
-
-/* Write a page to the destination database */
-static void scrubBackupWrite(ScrubState *p, int pgno, const u8 *pData){
- int rc;
- sqlite3_int64 iOff;
- if( p->rcErr ) return;
- iOff = (pgno-1)*(sqlite3_int64)p->szPage;
- rc = p->pDest->pMethods->xWrite(p->pDest, pData, p->szPage, iOff);
- if( rc!=SQLITE_OK ){
- scrubBackupErr(p, "write failed for page %d", pgno);
- p->rcErr = SQLITE_IOERR;
- }
- if( (u32)pgno>p->iLastPage ) p->iLastPage = pgno;
-}
-
-/* Prepare a statement against the "db" database. */
-static sqlite3_stmt *scrubBackupPrepare(
- ScrubState *p, /* Backup context */
- sqlite3 *db, /* Database to prepare against */
- const char *zSql /* SQL statement */
-){
- sqlite3_stmt *pStmt;
- if( p->rcErr ) return 0;
- p->rcErr = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( p->rcErr ){
- scrubBackupErr(p, "SQL error \"%s\" on \"%s\"",
- sqlite3_errmsg(db), zSql);
- sqlite3_finalize(pStmt);
- return 0;
- }
- return pStmt;
-}
-
-
-/* Open the source database file */
-static void scrubBackupOpenSrc(ScrubState *p){
- sqlite3_stmt *pStmt;
- int rc;
- /* Open the source database file */
- p->rcErr = sqlite3_open_v2(p->zSrcFile, &p->dbSrc,
- SQLITE_OPEN_READWRITE |
- SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
- if( p->rcErr ){
- scrubBackupErr(p, "cannot open source database: %s",
- sqlite3_errmsg(p->dbSrc));
- return;
- }
- p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_master; BEGIN;",
- 0, 0, 0);
- if( p->rcErr ){
- scrubBackupErr(p,
- "cannot start a read transaction on the source database: %s",
- sqlite3_errmsg(p->dbSrc));
- return;
- }
- rc = sqlite3_wal_checkpoint_v2(p->dbSrc, "main", SQLITE_CHECKPOINT_FULL,
- 0, 0);
- if( rc ){
- scrubBackupErr(p, "cannot checkpoint the source database");
- return;
- }
- pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_size");
- if( pStmt==0 ) return;
- rc = sqlite3_step(pStmt);
- if( rc==SQLITE_ROW ){
- p->szPage = sqlite3_column_int(pStmt, 0);
- }else{
- scrubBackupErr(p, "unable to determine the page size");
- }
- sqlite3_finalize(pStmt);
- if( p->rcErr ) return;
- pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_count");
- if( pStmt==0 ) return;
- rc = sqlite3_step(pStmt);
- if( rc==SQLITE_ROW ){
- p->nPage = sqlite3_column_int(pStmt, 0);
- }else{
- scrubBackupErr(p, "unable to determine the size of the source database");
- }
- sqlite3_finalize(pStmt);
- sqlite3_file_control(p->dbSrc, "main", SQLITE_FCNTL_FILE_POINTER, &p->pSrc);
- if( p->pSrc==0 || p->pSrc->pMethods==0 ){
- scrubBackupErr(p, "cannot get the source file handle");
- p->rcErr = SQLITE_ERROR;
- }
-}
-
-/* Create and open the destination file */
-static void scrubBackupOpenDest(ScrubState *p){
- sqlite3_stmt *pStmt;
- int rc;
- char *zSql;
- if( p->rcErr ) return;
- p->rcErr = sqlite3_open_v2(p->zDestFile, &p->dbDest,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
- SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
- if( p->rcErr ){
- scrubBackupErr(p, "cannot open destination database: %s",
- sqlite3_errmsg(p->dbDest));
- return;
- }
- zSql = sqlite3_mprintf("PRAGMA page_size(%u);", p->szPage);
- if( zSql==0 ){
- p->rcErr = SQLITE_NOMEM;
- return;
- }
- p->rcErr = sqlite3_exec(p->dbDest, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- if( p->rcErr ){
- scrubBackupErr(p,
- "cannot set the page size on the destination database: %s",
- sqlite3_errmsg(p->dbDest));
- return;
- }
- sqlite3_exec(p->dbDest, "PRAGMA journal_mode=OFF;", 0, 0, 0);
- p->rcErr = sqlite3_exec(p->dbDest, "BEGIN EXCLUSIVE;", 0, 0, 0);
- if( p->rcErr ){
- scrubBackupErr(p,
- "cannot start a write transaction on the destination database: %s",
- sqlite3_errmsg(p->dbDest));
- return;
- }
- pStmt = scrubBackupPrepare(p, p->dbDest, "PRAGMA page_count;");
- if( pStmt==0 ) return;
- rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW ){
- scrubBackupErr(p, "cannot measure the size of the destination");
- }else if( sqlite3_column_int(pStmt, 0)>1 ){
- scrubBackupErr(p, "destination database is not empty - holds %d pages",
- sqlite3_column_int(pStmt, 0));
- }
- sqlite3_finalize(pStmt);
- sqlite3_file_control(p->dbDest, "main", SQLITE_FCNTL_FILE_POINTER, &p->pDest);
- if( p->pDest==0 || p->pDest->pMethods==0 ){
- scrubBackupErr(p, "cannot get the destination file handle");
- p->rcErr = SQLITE_ERROR;
- }
-}
-
-/* Read a 32-bit big-endian integer */
-static u32 scrubBackupInt32(const u8 *a){
- u32 v = a[3];
- v += ((u32)a[2])<<8;
- v += ((u32)a[1])<<16;
- v += ((u32)a[0])<<24;
- return v;
-}
-
-/* Read a 16-bit big-endian integer */
-static u32 scrubBackupInt16(const u8 *a){
- return (a[0]<<8) + a[1];
-}
-
-/*
-** Read a varint. Put the value in *pVal and return the number of bytes.
-*/
-static int scrubBackupVarint(const u8 *z, sqlite3_int64 *pVal){
- sqlite3_int64 v = 0;
- int i;
- for(i=0; i<8; i++){
- v = (v<<7) + (z[i]&0x7f);
- if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
- }
- v = (v<<8) + (z[i]&0xff);
- *pVal = v;
- return 9;
-}
-
-/*
-** Return the number of bytes in a varint.
-*/
-static int scrubBackupVarintSize(const u8 *z){
- int i;
- for(i=0; i<8; i++){
- if( (z[i]&0x80)==0 ){ return i+1; }
- }
- return 9;
-}
-
-/*
-** Copy the freelist trunk page given, and all its descendents,
-** zeroing out as much as possible in the process.
-*/
-static void scrubBackupFreelist(ScrubState *p, int pgno, u32 nFree){
- u8 *a, *aBuf;
- u32 n, mx;
-
- if( p->rcErr ) return;
- aBuf = scrubBackupAllocPage(p);
- if( aBuf==0 ) return;
-
- while( pgno && nFree){
- a = scrubBackupRead(p, pgno, aBuf);
- if( a==0 ) break;
- n = scrubBackupInt32(&a[4]);
- mx = p->szUsable/4 - 2;
- if( n<mx ){
- memset(&a[n*4+8], 0, 4*(mx-n));
- }
- scrubBackupWrite(p, pgno, a);
- pgno = scrubBackupInt32(a);
-#if 0
- /* There is really no point in copying the freelist leaf pages.
- ** Simply leave them uninitialized in the destination database. The
- ** OS filesystem should zero those pages for us automatically.
- */
- for(i=0; i<n && nFree; i++){
- u32 iLeaf = scrubBackupInt32(&a[i*4+8]);
- if( aZero==0 ){
- aZero = scrubBackupAllocPage(p);
- if( aZero==0 ){ pgno = 0; break; }
- memset(aZero, 0, p->szPage);
- }
- scrubBackupWrite(p, iLeaf, aZero);
- nFree--;
- }
-#endif
- }
- sqlite3_free(aBuf);
-}
-
-/*
-** Copy an overflow chain from source to destination. Zero out any
-** unused tail at the end of the overflow chain.
-*/
-static void scrubBackupOverflow(ScrubState *p, int pgno, u32 nByte){
- u8 *a, *aBuf;
-
- aBuf = scrubBackupAllocPage(p);
- if( aBuf==0 ) return;
- while( nByte>0 && pgno!=0 ){
- a = scrubBackupRead(p, pgno, aBuf);
- if( a==0 ) break;
- if( nByte >= (p->szUsable)-4 ){
- nByte -= (p->szUsable) - 4;
- }else{
- u32 x = (p->szUsable - 4) - nByte;
- u32 i = p->szUsable - x;
- memset(&a[i], 0, x);
- nByte = 0;
- }
- scrubBackupWrite(p, pgno, a);
- pgno = scrubBackupInt32(a);
- }
- sqlite3_free(aBuf);
-}
-
-
-/*
-** Copy B-Tree page pgno, and all of its children, from source to destination.
-** Zero out deleted content during the copy.
-*/
-static void scrubBackupBtree(ScrubState *p, int pgno, int iDepth){
- u8 *a;
- u32 i, n, pc;
- u32 nCell;
- u32 nPrefix;
- u32 szHdr;
- u32 iChild;
- u8 *aTop;
- u8 *aCell;
- u32 x, y;
- int ln = 0;
-
-
- if( p->rcErr ) return;
- if( iDepth>50 ){
- scrubBackupErr(p, "corrupt: b-tree too deep at page %d", pgno);
- return;
- }
- if( pgno==1 ){
- a = p->page1;
- }else{
- a = scrubBackupRead(p, pgno, 0);
- if( a==0 ) return;
- }
- nPrefix = pgno==1 ? 100 : 0;
- aTop = &a[nPrefix];
- szHdr = 8 + 4*(aTop[0]==0x02 || aTop[0]==0x05);
- aCell = aTop + szHdr;
- nCell = scrubBackupInt16(&aTop[3]);
-
- /* Zero out the gap between the cell index and the start of the
- ** cell content area */
- x = scrubBackupInt16(&aTop[5]); /* First byte of cell content area */
- if( x>p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
- y = szHdr + nPrefix + nCell*2;
- if( y>x ){ ln=__LINE__; goto btree_corrupt; }
- if( y<x ) memset(a+y, 0, x-y); /* Zero the gap */
-
- /* Zero out all the free blocks */
- pc = scrubBackupInt16(&aTop[1]);
- if( pc>0 && pc<x ){ ln=__LINE__; goto btree_corrupt; }
- while( pc ){
- if( pc>(p->szUsable)-4 ){ ln=__LINE__; goto btree_corrupt; }
- n = scrubBackupInt16(&a[pc+2]);
- if( pc+n>(p->szUsable) ){ ln=__LINE__; goto btree_corrupt; }
- if( n>4 ) memset(&a[pc+4], 0, n-4);
- x = scrubBackupInt16(&a[pc]);
- if( x<pc+4 && x>0 ){ ln=__LINE__; goto btree_corrupt; }
- pc = x;
- }
-
- /* Write this one page */
- scrubBackupWrite(p, pgno, a);
-
- /* Walk the tree and process child pages */
- for(i=0; i<nCell; i++){
- u32 X, M, K, nLocal;
- sqlite3_int64 P;
- pc = scrubBackupInt16(&aCell[i*2]);
- if( pc <= szHdr ){ ln=__LINE__; goto btree_corrupt; }
- if( pc > p->szUsable-3 ){ ln=__LINE__; goto btree_corrupt; }
- if( aTop[0]==0x05 || aTop[0]==0x02 ){
- if( pc+4 > p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
- iChild = scrubBackupInt32(&a[pc]);
- pc += 4;
- scrubBackupBtree(p, iChild, iDepth+1);
- if( aTop[0]==0x05 ) continue;
- }
- pc += scrubBackupVarint(&a[pc], &P);
- if( pc >= p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
- if( aTop[0]==0x0d ){
- X = p->szUsable - 35;
- }else{
- X = ((p->szUsable - 12)*64/255) - 23;
- }
- if( P<=X ){
- /* All content is local. No overflow */
- continue;
- }
- M = ((p->szUsable - 12)*32/255)-23;
- K = M + ((P-M)%(p->szUsable-4));
- if( aTop[0]==0x0d ){
- pc += scrubBackupVarintSize(&a[pc]);
- if( pc > (p->szUsable-4) ){ ln=__LINE__; goto btree_corrupt; }
- }
- nLocal = K<=X ? K : M;
- if( pc+nLocal > p->szUsable-4 ){ ln=__LINE__; goto btree_corrupt; }
- iChild = scrubBackupInt32(&a[pc+nLocal]);
- scrubBackupOverflow(p, iChild, (u32)(P-nLocal));
- }
-
- /* Walk the right-most tree */
- if( aTop[0]==0x05 || aTop[0]==0x02 ){
- iChild = scrubBackupInt32(&aTop[8]);
- scrubBackupBtree(p, iChild, iDepth+1);
- }
-
- /* All done */
- if( pgno>1 ) sqlite3_free(a);
- return;
-
-btree_corrupt:
- scrubBackupErr(p, "corruption on page %d of source database (errid=%d)",
- pgno, ln);
- if( pgno>1 ) sqlite3_free(a);
-}
-
-/*
-** Copy all ptrmap pages from source to destination.
-** This routine is only called if the source database is in autovacuum
-** or incremental vacuum mode.
-*/
-static void scrubBackupPtrmap(ScrubState *p){
- u32 pgno = 2;
- u32 J = p->szUsable/5;
- u32 iLock = (1073742335/p->szPage)+1;
- u8 *a, *pBuf;
- if( p->rcErr ) return;
- pBuf = scrubBackupAllocPage(p);
- if( pBuf==0 ) return;
- while( pgno<=p->nPage ){
- a = scrubBackupRead(p, pgno, pBuf);
- if( a==0 ) break;
- scrubBackupWrite(p, pgno, a);
- pgno += J+1;
- if( pgno==iLock ) pgno++;
- }
- sqlite3_free(pBuf);
-}
-
-int sqlite3_scrub_backup(
- const char *zSrcFile, /* Source file */
- const char *zDestFile, /* Destination file */
- char **pzErr /* Write error here if non-NULL */
-){
- ScrubState s;
- u32 n, i;
- sqlite3_stmt *pStmt;
-
- memset(&s, 0, sizeof(s));
- s.zSrcFile = zSrcFile;
- s.zDestFile = zDestFile;
-
- /* Open both source and destination databases */
- scrubBackupOpenSrc(&s);
- scrubBackupOpenDest(&s);
-
- /* Read in page 1 */
- s.page1 = scrubBackupRead(&s, 1, 0);
- if( s.page1==0 ) goto scrub_abort;
- s.szUsable = s.szPage - s.page1[20];
-
- /* Copy the freelist */
- n = scrubBackupInt32(&s.page1[36]);
- i = scrubBackupInt32(&s.page1[32]);
- if( n ) scrubBackupFreelist(&s, i, n);
-
- /* Copy ptrmap pages */
- n = scrubBackupInt32(&s.page1[52]);
- if( n ) scrubBackupPtrmap(&s);
-
- /* Copy all of the btrees */
- scrubBackupBtree(&s, 1, 0);
- pStmt = scrubBackupPrepare(&s, s.dbSrc,
- "SELECT rootpage FROM sqlite_master WHERE coalesce(rootpage,0)>0");
- if( pStmt==0 ) goto scrub_abort;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- i = (u32)sqlite3_column_int(pStmt, 0);
- scrubBackupBtree(&s, i, 0);
- }
- sqlite3_finalize(pStmt);
-
- /* If the last page of the input db file is a free-list leaf, then the
- ** backup file on disk is still smaller than the size indicated within
- ** the database header. In this case, write a page of zeroes to the
- ** last page of the backup database so that SQLite does not mistakenly
- ** think the db is corrupt. */
- if( s.iLastPage<s.nPage ){
- u8 *aZero = scrubBackupAllocPage(&s);
- if( aZero ){
- memset(aZero, 0, s.szPage);
- scrubBackupWrite(&s, s.nPage, aZero);
- sqlite3_free(aZero);
- }
- }
-
-scrub_abort:
- /* Close the destination database without closing the transaction. If we
- ** commit, page zero will be overwritten. */
- sqlite3_close(s.dbDest);
-
- /* But do close out the read-transaction on the source database */
- sqlite3_exec(s.dbSrc, "COMMIT;", 0, 0, 0);
- sqlite3_close(s.dbSrc);
- sqlite3_free(s.page1);
- if( pzErr ){
- *pzErr = s.zErr;
- }else{
- sqlite3_free(s.zErr);
- }
- return s.rcErr;
-}
-
-#ifdef SCRUB_STANDALONE
-/* Error and warning log */
-static void errorLogCallback(void *pNotUsed, int iErr, const char *zMsg){
- const char *zType;
- switch( iErr&0xff ){
- case SQLITE_WARNING: zType = "WARNING"; break;
- case SQLITE_NOTICE: zType = "NOTICE"; break;
- default: zType = "ERROR"; break;
- }
- fprintf(stderr, "%s: %s\n", zType, zMsg);
-}
-
-/* The main() routine when this utility is run as a stand-alone program */
-int main(int argc, char **argv){
- char *zErr = 0;
- int rc;
- if( argc!=3 ){
- fprintf(stderr,"Usage: %s SOURCE DESTINATION\n", argv[0]);
- exit(1);
- }
- sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, 0);
- rc = sqlite3_scrub_backup(argv[1], argv[2], &zErr);
- if( rc==SQLITE_NOMEM ){
- fprintf(stderr, "%s: out of memory\n", argv[0]);
- exit(1);
- }
- if( zErr ){
- fprintf(stderr, "%s: %s\n", argv[0], zErr);
- sqlite3_free(zErr);
- exit(1);
- }
- return 0;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/series.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/series.c
deleted file mode 100644
index 3df0a37e6b2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/series.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
-** 2015-08-18
-**
-** 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 demonstrates how to create a table-valued-function using
-** a virtual table. This demo implements the generate_series() function
-** which gives similar results to the eponymous function in PostgreSQL.
-** Examples:
-**
-** SELECT * FROM generate_series(0,100,5);
-**
-** The query above returns integers from 0 through 100 counting by steps
-** of 5.
-**
-** SELECT * FROM generate_series(0,100);
-**
-** Integers from 0 through 100 with a step size of 1.
-**
-** SELECT * FROM generate_series(20) LIMIT 10;
-**
-** Integers 20 through 29.
-**
-** HOW IT WORKS
-**
-** The generate_series "function" is really a virtual table with the
-** following schema:
-**
-** CREATE TABLE generate_series(
-** value,
-** start HIDDEN,
-** stop HIDDEN,
-** step HIDDEN
-** );
-**
-** Function arguments in queries against this virtual table are translated
-** into equality constraints against successive hidden columns. In other
-** words, the following pairs of queries are equivalent to each other:
-**
-** SELECT * FROM generate_series(0,100,5);
-** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5;
-**
-** SELECT * FROM generate_series(0,100);
-** SELECT * FROM generate_series WHERE start=0 AND stop=100;
-**
-** SELECT * FROM generate_series(20) LIMIT 10;
-** SELECT * FROM generate_series WHERE start=20 LIMIT 10;
-**
-** The generate_series virtual table implementation leaves the xCreate method
-** set to NULL. This means that it is not possible to do a CREATE VIRTUAL
-** TABLE command with "generate_series" as the USING argument. Instead, there
-** is a single generate_series virtual table that is always available without
-** having to be created first.
-**
-** The xBestIndex method looks for equality constraints against the hidden
-** start, stop, and step columns, and if present, it uses those constraints
-** to bound the sequence of generated values. If the equality constraints
-** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step.
-** xBestIndex returns a small cost when both start and stop are available,
-** and a very large cost if either start or stop are unavailable. This
-** encourages the query planner to order joins such that the bounds of the
-** series are well-defined.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-
-/* series_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-typedef struct series_cursor series_cursor;
-struct series_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- int isDesc; /* True to count down rather than up */
- sqlite3_int64 iRowid; /* The rowid */
- sqlite3_int64 iValue; /* Current value ("value") */
- sqlite3_int64 mnValue; /* Mimimum value ("start") */
- sqlite3_int64 mxValue; /* Maximum value ("stop") */
- sqlite3_int64 iStep; /* Increment ("step") */
-};
-
-/*
-** The seriesConnect() method is invoked to create a new
-** series_vtab that describes the generate_series virtual table.
-**
-** Think of this routine as the constructor for series_vtab objects.
-**
-** All this routine needs to do is:
-**
-** (1) Allocate the series_vtab object and initialize all fields.
-**
-** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-** result set of queries against generate_series will look like.
-*/
-static int seriesConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3_vtab *pNew;
- int rc;
-
-/* Column numbers */
-#define SERIES_COLUMN_VALUE 0
-#define SERIES_COLUMN_START 1
-#define SERIES_COLUMN_STOP 2
-#define SERIES_COLUMN_STEP 3
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
- if( rc==SQLITE_OK ){
- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- }
- return rc;
-}
-
-/*
-** This method is the destructor for series_cursor objects.
-*/
-static int seriesDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new series_cursor object.
-*/
-static int seriesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- series_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Destructor for a series_cursor.
-*/
-static int seriesClose(sqlite3_vtab_cursor *cur){
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a series_cursor to its next row of output.
-*/
-static int seriesNext(sqlite3_vtab_cursor *cur){
- series_cursor *pCur = (series_cursor*)cur;
- if( pCur->isDesc ){
- pCur->iValue -= pCur->iStep;
- }else{
- pCur->iValue += pCur->iStep;
- }
- pCur->iRowid++;
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the series_cursor
-** is currently pointing.
-*/
-static int seriesColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- series_cursor *pCur = (series_cursor*)cur;
- sqlite3_int64 x = 0;
- switch( i ){
- case SERIES_COLUMN_START: x = pCur->mnValue; break;
- case SERIES_COLUMN_STOP: x = pCur->mxValue; break;
- case SERIES_COLUMN_STEP: x = pCur->iStep; break;
- default: x = pCur->iValue; break;
- }
- sqlite3_result_int64(ctx, x);
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** first row returned is assigned rowid value 1, and each subsequent
-** row a value 1 more than that of the previous.
-*/
-static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- series_cursor *pCur = (series_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int seriesEof(sqlite3_vtab_cursor *cur){
- series_cursor *pCur = (series_cursor*)cur;
- if( pCur->isDesc ){
- return pCur->iValue < pCur->mnValue;
- }else{
- return pCur->iValue > pCur->mxValue;
- }
-}
-
-/* True to cause run-time checking of the start=, stop=, and/or step=
-** parameters. The only reason to do this is for testing the
-** constraint checking logic for virtual tables in the SQLite core.
-*/
-#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
-# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
-#endif
-
-/*
-** This method is called to "rewind" the series_cursor object back
-** to the first row of output. This method is always called at least
-** once prior to any call to seriesColumn() or seriesRowid() or
-** seriesEof().
-**
-** The query plan selected by seriesBestIndex is passed in the idxNum
-** parameter. (idxStr is not used in this implementation.) idxNum
-** is a bitmask showing which constraints are available:
-**
-** 1: start=VALUE
-** 2: stop=VALUE
-** 4: step=VALUE
-**
-** Also, if bit 8 is set, that means that the series should be output
-** in descending order rather than in ascending order.
-**
-** This routine should initialize the cursor and position it so that it
-** is pointing at the first row, or pointing off the end of the table
-** (so that seriesEof() will return true) if the table is empty.
-*/
-static int seriesFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- series_cursor *pCur = (series_cursor *)pVtabCursor;
- int i = 0;
- if( idxNum & 1 ){
- pCur->mnValue = sqlite3_value_int64(argv[i++]);
- }else{
- pCur->mnValue = 0;
- }
- if( idxNum & 2 ){
- pCur->mxValue = sqlite3_value_int64(argv[i++]);
- }else{
- pCur->mxValue = 0xffffffff;
- }
- if( idxNum & 4 ){
- pCur->iStep = sqlite3_value_int64(argv[i++]);
- if( pCur->iStep<1 ) pCur->iStep = 1;
- }else{
- pCur->iStep = 1;
- }
- for(i=0; i<argc; i++){
- if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
- /* If any of the constraints have a NULL value, then return no rows.
- ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
- pCur->mnValue = 1;
- pCur->mxValue = 0;
- break;
- }
- }
- if( idxNum & 8 ){
- pCur->isDesc = 1;
- pCur->iValue = pCur->mxValue;
- if( pCur->iStep>0 ){
- pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
- }
- }else{
- pCur->isDesc = 0;
- pCur->iValue = pCur->mnValue;
- }
- pCur->iRowid = 1;
- return SQLITE_OK;
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the generate_series virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** In this implementation idxNum is used to represent the
-** query plan. idxStr is unused.
-**
-** The query plan is represented by bits in idxNum:
-**
-** (1) start = $value -- constraint exists
-** (2) stop = $value -- constraint exists
-** (4) step = $value -- constraint exists
-** (8) output in descending order
-*/
-static int seriesBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i; /* Loop over constraints */
- int idxNum = 0; /* The query plan bitmask */
- int startIdx = -1; /* Index of the start= constraint, or -1 if none */
- int stopIdx = -1; /* Index of the stop= constraint, or -1 if none */
- int stepIdx = -1; /* Index of the step= constraint, or -1 if none */
- int nArg = 0; /* Number of arguments that seriesFilter() expects */
-
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case SERIES_COLUMN_START:
- startIdx = i;
- idxNum |= 1;
- break;
- case SERIES_COLUMN_STOP:
- stopIdx = i;
- idxNum |= 2;
- break;
- case SERIES_COLUMN_STEP:
- stepIdx = i;
- idxNum |= 4;
- break;
- }
- }
- if( startIdx>=0 ){
- pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( stopIdx>=0 ){
- pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( stepIdx>=0 ){
- pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[stepIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( (idxNum & 3)==3 ){
- /* Both start= and stop= boundaries are available. This is the
- ** the preferred case */
- pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
- pIdxInfo->estimatedRows = 1000;
- if( pIdxInfo->nOrderBy==1 ){
- if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
- pIdxInfo->orderByConsumed = 1;
- }
- }else{
- /* If either boundary is missing, we have to generate a huge span
- ** of numbers. Make this case very expensive so that the query
- ** planner will work hard to avoid it. */
- pIdxInfo->estimatedCost = (double)2147483647;
- pIdxInfo->estimatedRows = 2147483647;
- }
- pIdxInfo->idxNum = idxNum;
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** generate_series virtual table.
-*/
-static sqlite3_module seriesModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- seriesConnect, /* xConnect */
- seriesBestIndex, /* xBestIndex */
- seriesDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- seriesOpen, /* xOpen - open a cursor */
- seriesClose, /* xClose - close a cursor */
- seriesFilter, /* xFilter - configure scan constraints */
- seriesNext, /* xNext - advance a cursor */
- seriesEof, /* xEof - check for end of scan */
- seriesColumn, /* xColumn - read data */
- seriesRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_series_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( sqlite3_libversion_number()<3008012 ){
- *pzErrMsg = sqlite3_mprintf(
- "generate_series() requires SQLite 3.8.12 or later");
- return SQLITE_ERROR;
- }
- rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
-#endif
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/sha1.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/sha1.c
deleted file mode 100644
index e2843bdefa4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/sha1.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
-** 2017-01-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 SQLite extension implements a functions that compute SHA1 hashes.
-** Two SQL functions are implemented:
-**
-** sha1(X)
-** sha1_query(Y)
-**
-** The sha1(X) function computes the SHA1 hash of the input X, or NULL if
-** X is NULL.
-**
-** The sha1_query(Y) function evalutes all queries in the SQL statements of Y
-** and returns a hash of their results.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <stdarg.h>
-
-/******************************************************************************
-** The Hash Engine
-*/
-/* Context for the SHA1 hash */
-typedef struct SHA1Context SHA1Context;
-struct SHA1Context {
- unsigned int state[5];
- unsigned int count[2];
- unsigned char buffer[64];
-};
-
-
-#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
-/*
- * GCC by itself only generates left rotates. Use right rotates if
- * possible to be kinder to dinky implementations with iterative rotate
- * instructions.
- */
-#define SHA_ROT(op, x, k) \
- ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
-#define rol(x,k) SHA_ROT("roll", x, k)
-#define ror(x,k) SHA_ROT("rorl", x, k)
-
-#else
-/* Generic C equivalent */
-#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
-#define rol(x,k) SHA_ROT(x,k,32-(k))
-#define ror(x,k) SHA_ROT(x,32-(k),k)
-#endif
-
-
-#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
- |(rol(block[i],8)&0x00FF00FF))
-#define blk0be(i) block[i]
-#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
- ^block[(i+2)&15]^block[i&15],1))
-
-/*
- * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
- *
- * Rl0() for little-endian and Rb0() for big-endian. Endianness is
- * determined at run-time.
- */
-#define Rl0(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define Rb0(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define R1(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define R2(v,w,x,y,z,i) \
- z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
-#define R3(v,w,x,y,z,i) \
- z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
-#define R4(v,w,x,y,z,i) \
- z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
-
-/*
- * Hash a single 512-bit block. This is the core of the algorithm.
- */
-void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
- unsigned int qq[5]; /* a, b, c, d, e; */
- static int one = 1;
- unsigned int block[16];
- memcpy(block, buffer, 64);
- memcpy(qq,state,5*sizeof(unsigned int));
-
-#define a qq[0]
-#define b qq[1]
-#define c qq[2]
-#define d qq[3]
-#define e qq[4]
-
- /* Copy p->state[] to working vars */
- /*
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- */
-
- /* 4 rounds of 20 operations each. Loop unrolled. */
- if( 1 == *(unsigned char*)&one ){
- Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
- Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
- Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
- Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
- }else{
- Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
- Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
- Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
- Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
- }
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
-
-#undef a
-#undef b
-#undef c
-#undef d
-#undef e
-}
-
-
-/* Initialize a SHA1 context */
-static void hash_init(SHA1Context *p){
- /* SHA1 initialization constants */
- p->state[0] = 0x67452301;
- p->state[1] = 0xEFCDAB89;
- p->state[2] = 0x98BADCFE;
- p->state[3] = 0x10325476;
- p->state[4] = 0xC3D2E1F0;
- p->count[0] = p->count[1] = 0;
-}
-
-/* Add new content to the SHA1 hash */
-static void hash_step(
- SHA1Context *p, /* Add content to this context */
- const unsigned char *data, /* Data to be added */
- unsigned int len /* Number of bytes in data */
-){
- unsigned int i, j;
-
- j = p->count[0];
- if( (p->count[0] += len << 3) < j ){
- p->count[1] += (len>>29)+1;
- }
- j = (j >> 3) & 63;
- if( (j + len) > 63 ){
- (void)memcpy(&p->buffer[j], data, (i = 64-j));
- SHA1Transform(p->state, p->buffer);
- for(; i + 63 < len; i += 64){
- SHA1Transform(p->state, &data[i]);
- }
- j = 0;
- }else{
- i = 0;
- }
- (void)memcpy(&p->buffer[j], &data[i], len - i);
-}
-
-/* Compute a string using sqlite3_vsnprintf() and hash it */
-static void hash_step_vformat(
- SHA1Context *p, /* Add content to this context */
- const char *zFormat,
- ...
-){
- va_list ap;
- int n;
- char zBuf[50];
- va_start(ap, zFormat);
- sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
- va_end(ap);
- n = (int)strlen(zBuf);
- hash_step(p, (unsigned char*)zBuf, n);
-}
-
-
-/* Add padding and compute the message digest. Render the
-** message digest as lower-case hexadecimal and put it into
-** zOut[]. zOut[] must be at least 41 bytes long. */
-static void hash_finish(
- SHA1Context *p, /* The SHA1 context to finish and render */
- char *zOut /* Store hexadecimal hash here */
-){
- unsigned int i;
- unsigned char finalcount[8];
- unsigned char digest[20];
- static const char zEncode[] = "0123456789abcdef";
-
- for (i = 0; i < 8; i++){
- finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
- }
- hash_step(p, (const unsigned char *)"\200", 1);
- while ((p->count[0] & 504) != 448){
- hash_step(p, (const unsigned char *)"\0", 1);
- }
- hash_step(p, finalcount, 8); /* Should cause a SHA1Transform() */
- for (i = 0; i < 20; i++){
- digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
- for(i=0; i<20; i++){
- zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
- zOut[i*2+1] = zEncode[digest[i] & 0xf];
- }
- zOut[i*2]= 0;
-}
-/* End of the hashing logic
-*****************************************************************************/
-
-/*
-** Implementation of the sha1(X) function.
-**
-** Return a lower-case hexadecimal rendering of the SHA1 hash of the
-** argument X. If X is a BLOB, it is hashed as is. For all other
-** types of input, X is converted into a UTF-8 string and the string
-** is hash without the trailing 0x00 terminator. The hash of a NULL
-** value is NULL.
-*/
-static void sha1Func(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- SHA1Context cx;
- int eType = sqlite3_value_type(argv[0]);
- int nByte = sqlite3_value_bytes(argv[0]);
- char zOut[44];
-
- assert( argc==1 );
- if( eType==SQLITE_NULL ) return;
- hash_init(&cx);
- if( eType==SQLITE_BLOB ){
- hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
- }else{
- hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
- }
- hash_finish(&cx, zOut);
- sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
-}
-
-/*
-** Implementation of the sha1_query(SQL) function.
-**
-** This function compiles and runs the SQL statement(s) given in the
-** argument. The results are hashed using SHA1 and that hash is returned.
-**
-** The original SQL text is included as part of the hash.
-**
-** The hash is not just a concatenation of the outputs. Each query
-** is delimited and each row and value within the query is delimited,
-** with all values being marked with their datatypes.
-*/
-static void sha1QueryFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- const char *zSql = (const char*)sqlite3_value_text(argv[0]);
- sqlite3_stmt *pStmt = 0;
- int nCol; /* Number of columns in the result set */
- int i; /* Loop counter */
- int rc;
- int n;
- const char *z;
- SHA1Context cx;
- char zOut[44];
-
- assert( argc==1 );
- if( zSql==0 ) return;
- hash_init(&cx);
- while( zSql[0] ){
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
- if( rc ){
- char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
- zSql, sqlite3_errmsg(db));
- sqlite3_finalize(pStmt);
- sqlite3_result_error(context, zMsg, -1);
- sqlite3_free(zMsg);
- return;
- }
- if( !sqlite3_stmt_readonly(pStmt) ){
- char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
- sqlite3_finalize(pStmt);
- sqlite3_result_error(context, zMsg, -1);
- sqlite3_free(zMsg);
- return;
- }
- nCol = sqlite3_column_count(pStmt);
- z = sqlite3_sql(pStmt);
- n = (int)strlen(z);
- hash_step_vformat(&cx,"S%d:",n);
- hash_step(&cx,(unsigned char*)z,n);
-
- /* Compute a hash over the result of the query */
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- hash_step(&cx,(const unsigned char*)"R",1);
- for(i=0; i<nCol; i++){
- switch( sqlite3_column_type(pStmt,i) ){
- case SQLITE_NULL: {
- hash_step(&cx, (const unsigned char*)"N",1);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_uint64 u;
- int j;
- unsigned char x[9];
- sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
- memcpy(&u, &v, 8);
- for(j=8; j>=1; j--){
- x[j] = u & 0xff;
- u >>= 8;
- }
- x[0] = 'I';
- hash_step(&cx, x, 9);
- break;
- }
- case SQLITE_FLOAT: {
- sqlite3_uint64 u;
- int j;
- unsigned char x[9];
- double r = sqlite3_column_double(pStmt,i);
- memcpy(&u, &r, 8);
- for(j=8; j>=1; j--){
- x[j] = u & 0xff;
- u >>= 8;
- }
- x[0] = 'F';
- hash_step(&cx,x,9);
- break;
- }
- case SQLITE_TEXT: {
- int n2 = sqlite3_column_bytes(pStmt, i);
- const unsigned char *z2 = sqlite3_column_text(pStmt, i);
- hash_step_vformat(&cx,"T%d:",n2);
- hash_step(&cx, z2, n2);
- break;
- }
- case SQLITE_BLOB: {
- int n2 = sqlite3_column_bytes(pStmt, i);
- const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
- hash_step_vformat(&cx,"B%d:",n2);
- hash_step(&cx, z2, n2);
- break;
- }
- }
- }
- }
- sqlite3_finalize(pStmt);
- }
- hash_finish(&cx, zOut);
- sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_sha_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "sha1", 1, SQLITE_UTF8, 0,
- sha1Func, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "sha1_query", 1, SQLITE_UTF8, 0,
- sha1QueryFunc, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/shathree.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/shathree.c
deleted file mode 100644
index e5c95407d67..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/shathree.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
-** 2017-03-08
-**
-** 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 SQLite extension implements a functions that compute SHA1 hashes.
-** Two SQL functions are implemented:
-**
-** sha3(X,SIZE)
-** sha3_query(Y,SIZE)
-**
-** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
-** X is NULL.
-**
-** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
-** and returns a hash of their results.
-**
-** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
-** is used. If SIZE is included it must be one of the integers 224, 256,
-** 384, or 512, to determine SHA3 hash variant that is computed.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <stdarg.h>
-typedef sqlite3_uint64 u64;
-
-/******************************************************************************
-** The Hash Engine
-*/
-/*
-** Macros to determine whether the machine is big or little endian,
-** and whether or not that determination is run-time or compile-time.
-**
-** For best performance, an attempt is made to guess at the byte-order
-** using C-preprocessor macros. If that is unsuccessful, or if
-** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
-** at run-time.
-*/
-#ifndef SHA3_BYTEORDER
-# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
- defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)
-# define SHA3_BYTEORDER 1234
-# elif defined(sparc) || defined(__ppc__)
-# define SHA3_BYTEORDER 4321
-# else
-# define SHA3_BYTEORDER 0
-# endif
-#endif
-
-
-/*
-** State structure for a SHA3 hash in progress
-*/
-typedef struct SHA3Context SHA3Context;
-struct SHA3Context {
- union {
- u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
- unsigned char x[1600]; /* ... or 1600 bytes */
- } u;
- unsigned nRate; /* Bytes of input accepted per Keccak iteration */
- unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
- unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
-};
-
-/*
-** A single step of the Keccak mixing function for a 1600-bit state
-*/
-static void KeccakF1600Step(SHA3Context *p){
- int i;
- u64 b0, b1, b2, b3, b4;
- u64 c0, c1, c2, c3, c4;
- u64 d0, d1, d2, d3, d4;
- static const u64 RC[] = {
- 0x0000000000000001ULL, 0x0000000000008082ULL,
- 0x800000000000808aULL, 0x8000000080008000ULL,
- 0x000000000000808bULL, 0x0000000080000001ULL,
- 0x8000000080008081ULL, 0x8000000000008009ULL,
- 0x000000000000008aULL, 0x0000000000000088ULL,
- 0x0000000080008009ULL, 0x000000008000000aULL,
- 0x000000008000808bULL, 0x800000000000008bULL,
- 0x8000000000008089ULL, 0x8000000000008003ULL,
- 0x8000000000008002ULL, 0x8000000000000080ULL,
- 0x000000000000800aULL, 0x800000008000000aULL,
- 0x8000000080008081ULL, 0x8000000000008080ULL,
- 0x0000000080000001ULL, 0x8000000080008008ULL
- };
-# define a00 (p->u.s[0])
-# define a01 (p->u.s[1])
-# define a02 (p->u.s[2])
-# define a03 (p->u.s[3])
-# define a04 (p->u.s[4])
-# define a10 (p->u.s[5])
-# define a11 (p->u.s[6])
-# define a12 (p->u.s[7])
-# define a13 (p->u.s[8])
-# define a14 (p->u.s[9])
-# define a20 (p->u.s[10])
-# define a21 (p->u.s[11])
-# define a22 (p->u.s[12])
-# define a23 (p->u.s[13])
-# define a24 (p->u.s[14])
-# define a30 (p->u.s[15])
-# define a31 (p->u.s[16])
-# define a32 (p->u.s[17])
-# define a33 (p->u.s[18])
-# define a34 (p->u.s[19])
-# define a40 (p->u.s[20])
-# define a41 (p->u.s[21])
-# define a42 (p->u.s[22])
-# define a43 (p->u.s[23])
-# define a44 (p->u.s[24])
-# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
-
- for(i=0; i<24; i+=4){
- c0 = a00^a10^a20^a30^a40;
- c1 = a01^a11^a21^a31^a41;
- c2 = a02^a12^a22^a32^a42;
- c3 = a03^a13^a23^a33^a43;
- c4 = a04^a14^a24^a34^a44;
- d0 = c4^ROL64(c1, 1);
- d1 = c0^ROL64(c2, 1);
- d2 = c1^ROL64(c3, 1);
- d3 = c2^ROL64(c4, 1);
- d4 = c3^ROL64(c0, 1);
-
- b0 = (a00^d0);
- b1 = ROL64((a11^d1), 44);
- b2 = ROL64((a22^d2), 43);
- b3 = ROL64((a33^d3), 21);
- b4 = ROL64((a44^d4), 14);
- a00 = b0 ^((~b1)& b2 );
- a00 ^= RC[i];
- a11 = b1 ^((~b2)& b3 );
- a22 = b2 ^((~b3)& b4 );
- a33 = b3 ^((~b4)& b0 );
- a44 = b4 ^((~b0)& b1 );
-
- b2 = ROL64((a20^d0), 3);
- b3 = ROL64((a31^d1), 45);
- b4 = ROL64((a42^d2), 61);
- b0 = ROL64((a03^d3), 28);
- b1 = ROL64((a14^d4), 20);
- a20 = b0 ^((~b1)& b2 );
- a31 = b1 ^((~b2)& b3 );
- a42 = b2 ^((~b3)& b4 );
- a03 = b3 ^((~b4)& b0 );
- a14 = b4 ^((~b0)& b1 );
-
- b4 = ROL64((a40^d0), 18);
- b0 = ROL64((a01^d1), 1);
- b1 = ROL64((a12^d2), 6);
- b2 = ROL64((a23^d3), 25);
- b3 = ROL64((a34^d4), 8);
- a40 = b0 ^((~b1)& b2 );
- a01 = b1 ^((~b2)& b3 );
- a12 = b2 ^((~b3)& b4 );
- a23 = b3 ^((~b4)& b0 );
- a34 = b4 ^((~b0)& b1 );
-
- b1 = ROL64((a10^d0), 36);
- b2 = ROL64((a21^d1), 10);
- b3 = ROL64((a32^d2), 15);
- b4 = ROL64((a43^d3), 56);
- b0 = ROL64((a04^d4), 27);
- a10 = b0 ^((~b1)& b2 );
- a21 = b1 ^((~b2)& b3 );
- a32 = b2 ^((~b3)& b4 );
- a43 = b3 ^((~b4)& b0 );
- a04 = b4 ^((~b0)& b1 );
-
- b3 = ROL64((a30^d0), 41);
- b4 = ROL64((a41^d1), 2);
- b0 = ROL64((a02^d2), 62);
- b1 = ROL64((a13^d3), 55);
- b2 = ROL64((a24^d4), 39);
- a30 = b0 ^((~b1)& b2 );
- a41 = b1 ^((~b2)& b3 );
- a02 = b2 ^((~b3)& b4 );
- a13 = b3 ^((~b4)& b0 );
- a24 = b4 ^((~b0)& b1 );
-
- c0 = a00^a20^a40^a10^a30;
- c1 = a11^a31^a01^a21^a41;
- c2 = a22^a42^a12^a32^a02;
- c3 = a33^a03^a23^a43^a13;
- c4 = a44^a14^a34^a04^a24;
- d0 = c4^ROL64(c1, 1);
- d1 = c0^ROL64(c2, 1);
- d2 = c1^ROL64(c3, 1);
- d3 = c2^ROL64(c4, 1);
- d4 = c3^ROL64(c0, 1);
-
- b0 = (a00^d0);
- b1 = ROL64((a31^d1), 44);
- b2 = ROL64((a12^d2), 43);
- b3 = ROL64((a43^d3), 21);
- b4 = ROL64((a24^d4), 14);
- a00 = b0 ^((~b1)& b2 );
- a00 ^= RC[i+1];
- a31 = b1 ^((~b2)& b3 );
- a12 = b2 ^((~b3)& b4 );
- a43 = b3 ^((~b4)& b0 );
- a24 = b4 ^((~b0)& b1 );
-
- b2 = ROL64((a40^d0), 3);
- b3 = ROL64((a21^d1), 45);
- b4 = ROL64((a02^d2), 61);
- b0 = ROL64((a33^d3), 28);
- b1 = ROL64((a14^d4), 20);
- a40 = b0 ^((~b1)& b2 );
- a21 = b1 ^((~b2)& b3 );
- a02 = b2 ^((~b3)& b4 );
- a33 = b3 ^((~b4)& b0 );
- a14 = b4 ^((~b0)& b1 );
-
- b4 = ROL64((a30^d0), 18);
- b0 = ROL64((a11^d1), 1);
- b1 = ROL64((a42^d2), 6);
- b2 = ROL64((a23^d3), 25);
- b3 = ROL64((a04^d4), 8);
- a30 = b0 ^((~b1)& b2 );
- a11 = b1 ^((~b2)& b3 );
- a42 = b2 ^((~b3)& b4 );
- a23 = b3 ^((~b4)& b0 );
- a04 = b4 ^((~b0)& b1 );
-
- b1 = ROL64((a20^d0), 36);
- b2 = ROL64((a01^d1), 10);
- b3 = ROL64((a32^d2), 15);
- b4 = ROL64((a13^d3), 56);
- b0 = ROL64((a44^d4), 27);
- a20 = b0 ^((~b1)& b2 );
- a01 = b1 ^((~b2)& b3 );
- a32 = b2 ^((~b3)& b4 );
- a13 = b3 ^((~b4)& b0 );
- a44 = b4 ^((~b0)& b1 );
-
- b3 = ROL64((a10^d0), 41);
- b4 = ROL64((a41^d1), 2);
- b0 = ROL64((a22^d2), 62);
- b1 = ROL64((a03^d3), 55);
- b2 = ROL64((a34^d4), 39);
- a10 = b0 ^((~b1)& b2 );
- a41 = b1 ^((~b2)& b3 );
- a22 = b2 ^((~b3)& b4 );
- a03 = b3 ^((~b4)& b0 );
- a34 = b4 ^((~b0)& b1 );
-
- c0 = a00^a40^a30^a20^a10;
- c1 = a31^a21^a11^a01^a41;
- c2 = a12^a02^a42^a32^a22;
- c3 = a43^a33^a23^a13^a03;
- c4 = a24^a14^a04^a44^a34;
- d0 = c4^ROL64(c1, 1);
- d1 = c0^ROL64(c2, 1);
- d2 = c1^ROL64(c3, 1);
- d3 = c2^ROL64(c4, 1);
- d4 = c3^ROL64(c0, 1);
-
- b0 = (a00^d0);
- b1 = ROL64((a21^d1), 44);
- b2 = ROL64((a42^d2), 43);
- b3 = ROL64((a13^d3), 21);
- b4 = ROL64((a34^d4), 14);
- a00 = b0 ^((~b1)& b2 );
- a00 ^= RC[i+2];
- a21 = b1 ^((~b2)& b3 );
- a42 = b2 ^((~b3)& b4 );
- a13 = b3 ^((~b4)& b0 );
- a34 = b4 ^((~b0)& b1 );
-
- b2 = ROL64((a30^d0), 3);
- b3 = ROL64((a01^d1), 45);
- b4 = ROL64((a22^d2), 61);
- b0 = ROL64((a43^d3), 28);
- b1 = ROL64((a14^d4), 20);
- a30 = b0 ^((~b1)& b2 );
- a01 = b1 ^((~b2)& b3 );
- a22 = b2 ^((~b3)& b4 );
- a43 = b3 ^((~b4)& b0 );
- a14 = b4 ^((~b0)& b1 );
-
- b4 = ROL64((a10^d0), 18);
- b0 = ROL64((a31^d1), 1);
- b1 = ROL64((a02^d2), 6);
- b2 = ROL64((a23^d3), 25);
- b3 = ROL64((a44^d4), 8);
- a10 = b0 ^((~b1)& b2 );
- a31 = b1 ^((~b2)& b3 );
- a02 = b2 ^((~b3)& b4 );
- a23 = b3 ^((~b4)& b0 );
- a44 = b4 ^((~b0)& b1 );
-
- b1 = ROL64((a40^d0), 36);
- b2 = ROL64((a11^d1), 10);
- b3 = ROL64((a32^d2), 15);
- b4 = ROL64((a03^d3), 56);
- b0 = ROL64((a24^d4), 27);
- a40 = b0 ^((~b1)& b2 );
- a11 = b1 ^((~b2)& b3 );
- a32 = b2 ^((~b3)& b4 );
- a03 = b3 ^((~b4)& b0 );
- a24 = b4 ^((~b0)& b1 );
-
- b3 = ROL64((a20^d0), 41);
- b4 = ROL64((a41^d1), 2);
- b0 = ROL64((a12^d2), 62);
- b1 = ROL64((a33^d3), 55);
- b2 = ROL64((a04^d4), 39);
- a20 = b0 ^((~b1)& b2 );
- a41 = b1 ^((~b2)& b3 );
- a12 = b2 ^((~b3)& b4 );
- a33 = b3 ^((~b4)& b0 );
- a04 = b4 ^((~b0)& b1 );
-
- c0 = a00^a30^a10^a40^a20;
- c1 = a21^a01^a31^a11^a41;
- c2 = a42^a22^a02^a32^a12;
- c3 = a13^a43^a23^a03^a33;
- c4 = a34^a14^a44^a24^a04;
- d0 = c4^ROL64(c1, 1);
- d1 = c0^ROL64(c2, 1);
- d2 = c1^ROL64(c3, 1);
- d3 = c2^ROL64(c4, 1);
- d4 = c3^ROL64(c0, 1);
-
- b0 = (a00^d0);
- b1 = ROL64((a01^d1), 44);
- b2 = ROL64((a02^d2), 43);
- b3 = ROL64((a03^d3), 21);
- b4 = ROL64((a04^d4), 14);
- a00 = b0 ^((~b1)& b2 );
- a00 ^= RC[i+3];
- a01 = b1 ^((~b2)& b3 );
- a02 = b2 ^((~b3)& b4 );
- a03 = b3 ^((~b4)& b0 );
- a04 = b4 ^((~b0)& b1 );
-
- b2 = ROL64((a10^d0), 3);
- b3 = ROL64((a11^d1), 45);
- b4 = ROL64((a12^d2), 61);
- b0 = ROL64((a13^d3), 28);
- b1 = ROL64((a14^d4), 20);
- a10 = b0 ^((~b1)& b2 );
- a11 = b1 ^((~b2)& b3 );
- a12 = b2 ^((~b3)& b4 );
- a13 = b3 ^((~b4)& b0 );
- a14 = b4 ^((~b0)& b1 );
-
- b4 = ROL64((a20^d0), 18);
- b0 = ROL64((a21^d1), 1);
- b1 = ROL64((a22^d2), 6);
- b2 = ROL64((a23^d3), 25);
- b3 = ROL64((a24^d4), 8);
- a20 = b0 ^((~b1)& b2 );
- a21 = b1 ^((~b2)& b3 );
- a22 = b2 ^((~b3)& b4 );
- a23 = b3 ^((~b4)& b0 );
- a24 = b4 ^((~b0)& b1 );
-
- b1 = ROL64((a30^d0), 36);
- b2 = ROL64((a31^d1), 10);
- b3 = ROL64((a32^d2), 15);
- b4 = ROL64((a33^d3), 56);
- b0 = ROL64((a34^d4), 27);
- a30 = b0 ^((~b1)& b2 );
- a31 = b1 ^((~b2)& b3 );
- a32 = b2 ^((~b3)& b4 );
- a33 = b3 ^((~b4)& b0 );
- a34 = b4 ^((~b0)& b1 );
-
- b3 = ROL64((a40^d0), 41);
- b4 = ROL64((a41^d1), 2);
- b0 = ROL64((a42^d2), 62);
- b1 = ROL64((a43^d3), 55);
- b2 = ROL64((a44^d4), 39);
- a40 = b0 ^((~b1)& b2 );
- a41 = b1 ^((~b2)& b3 );
- a42 = b2 ^((~b3)& b4 );
- a43 = b3 ^((~b4)& b0 );
- a44 = b4 ^((~b0)& b1 );
- }
-}
-
-/*
-** Initialize a new hash. iSize determines the size of the hash
-** in bits and should be one of 224, 256, 384, or 512. Or iSize
-** can be zero to use the default hash size of 256 bits.
-*/
-static void SHA3Init(SHA3Context *p, int iSize){
- memset(p, 0, sizeof(*p));
- if( iSize>=128 && iSize<=512 ){
- p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
- }else{
- p->nRate = (1600 - 2*256)/8;
- }
-#if SHA3_BYTEORDER==1234
- /* Known to be little-endian at compile-time. No-op */
-#elif SHA3_BYTEORDER==4321
- p->ixMask = 7; /* Big-endian */
-#else
- {
- static unsigned int one = 1;
- if( 1==*(unsigned char*)&one ){
- /* Little endian. No byte swapping. */
- p->ixMask = 0;
- }else{
- /* Big endian. Byte swap. */
- p->ixMask = 7;
- }
- }
-#endif
-}
-
-/*
-** Make consecutive calls to the SHA3Update function to add new content
-** to the hash
-*/
-static void SHA3Update(
- SHA3Context *p,
- const unsigned char *aData,
- unsigned int nData
-){
- unsigned int i = 0;
-#if SHA3_BYTEORDER==1234
- if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
- for(; i+7<nData; i+=8){
- p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
- p->nLoaded += 8;
- if( p->nLoaded>=p->nRate ){
- KeccakF1600Step(p);
- p->nLoaded = 0;
- }
- }
- }
-#endif
- for(; i<nData; i++){
-#if SHA3_BYTEORDER==1234
- p->u.x[p->nLoaded] ^= aData[i];
-#elif SHA3_BYTEORDER==4321
- p->u.x[p->nLoaded^0x07] ^= aData[i];
-#else
- p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
-#endif
- p->nLoaded++;
- if( p->nLoaded==p->nRate ){
- KeccakF1600Step(p);
- p->nLoaded = 0;
- }
- }
-}
-
-/*
-** After all content has been added, invoke SHA3Final() to compute
-** the final hash. The function returns a pointer to the binary
-** hash value.
-*/
-static unsigned char *SHA3Final(SHA3Context *p){
- unsigned int i;
- if( p->nLoaded==p->nRate-1 ){
- const unsigned char c1 = 0x86;
- SHA3Update(p, &c1, 1);
- }else{
- const unsigned char c2 = 0x06;
- const unsigned char c3 = 0x80;
- SHA3Update(p, &c2, 1);
- p->nLoaded = p->nRate - 1;
- SHA3Update(p, &c3, 1);
- }
- for(i=0; i<p->nRate; i++){
- p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
- }
- return &p->u.x[p->nRate];
-}
-/* End of the hashing logic
-*****************************************************************************/
-
-/*
-** Implementation of the sha3(X,SIZE) function.
-**
-** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default
-** size is 256. If X is a BLOB, it is hashed as is.
-** For all other non-NULL types of input, X is converted into a UTF-8 string
-** and the string is hashed without the trailing 0x00 terminator. The hash
-** of a NULL value is NULL.
-*/
-static void sha3Func(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- SHA3Context cx;
- int eType = sqlite3_value_type(argv[0]);
- int nByte = sqlite3_value_bytes(argv[0]);
- int iSize;
- if( argc==1 ){
- iSize = 256;
- }else{
- iSize = sqlite3_value_int(argv[1]);
- if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
- sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
- "384 512", -1);
- return;
- }
- }
- if( eType==SQLITE_NULL ) return;
- SHA3Init(&cx, iSize);
- if( eType==SQLITE_BLOB ){
- SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
- }else{
- SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
- }
- sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
-}
-
-/* Compute a string using sqlite3_vsnprintf() with a maximum length
-** of 50 bytes and add it to the hash.
-*/
-static void hash_step_vformat(
- SHA3Context *p, /* Add content to this context */
- const char *zFormat,
- ...
-){
- va_list ap;
- int n;
- char zBuf[50];
- va_start(ap, zFormat);
- sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
- va_end(ap);
- n = (int)strlen(zBuf);
- SHA3Update(p, (unsigned char*)zBuf, n);
-}
-
-/*
-** Implementation of the sha3_query(SQL,SIZE) function.
-**
-** This function compiles and runs the SQL statement(s) given in the
-** argument. The results are hashed using a SIZE-bit SHA3. The default
-** size is 256.
-**
-** The format of the byte stream that is hashed is summarized as follows:
-**
-** S<n>:<sql>
-** R
-** N
-** I<int>
-** F<ieee-float>
-** B<size>:<bytes>
-** T<size>:<text>
-**
-** <sql> is the original SQL text for each statement run and <n> is
-** the size of that text. The SQL text is UTF-8. A single R character
-** occurs before the start of each row. N means a NULL value.
-** I mean an 8-byte little-endian integer <int>. F is a floating point
-** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
-** B means blobs of <size> bytes. T means text rendered as <size>
-** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII
-** text integers.
-**
-** For each SQL statement in the X input, there is one S segment. Each
-** S segment is followed by zero or more R segments, one for each row in the
-** result set. After each R, there are one or more N, I, F, B, or T segments,
-** one for each column in the result set. Segments are concatentated directly
-** with no delimiters of any kind.
-*/
-static void sha3QueryFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- const char *zSql = (const char*)sqlite3_value_text(argv[0]);
- sqlite3_stmt *pStmt = 0;
- int nCol; /* Number of columns in the result set */
- int i; /* Loop counter */
- int rc;
- int n;
- const char *z;
- SHA3Context cx;
- int iSize;
-
- if( argc==1 ){
- iSize = 256;
- }else{
- iSize = sqlite3_value_int(argv[1]);
- if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
- sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
- "384 512", -1);
- return;
- }
- }
- if( zSql==0 ) return;
- SHA3Init(&cx, iSize);
- while( zSql[0] ){
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
- if( rc ){
- char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
- zSql, sqlite3_errmsg(db));
- sqlite3_finalize(pStmt);
- sqlite3_result_error(context, zMsg, -1);
- sqlite3_free(zMsg);
- return;
- }
- if( !sqlite3_stmt_readonly(pStmt) ){
- char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
- sqlite3_finalize(pStmt);
- sqlite3_result_error(context, zMsg, -1);
- sqlite3_free(zMsg);
- return;
- }
- nCol = sqlite3_column_count(pStmt);
- z = sqlite3_sql(pStmt);
- n = (int)strlen(z);
- hash_step_vformat(&cx,"S%d:",n);
- SHA3Update(&cx,(unsigned char*)z,n);
-
- /* Compute a hash over the result of the query */
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- SHA3Update(&cx,(const unsigned char*)"R",1);
- for(i=0; i<nCol; i++){
- switch( sqlite3_column_type(pStmt,i) ){
- case SQLITE_NULL: {
- SHA3Update(&cx, (const unsigned char*)"N",1);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_uint64 u;
- int j;
- unsigned char x[9];
- sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
- memcpy(&u, &v, 8);
- for(j=8; j>=1; j--){
- x[j] = u & 0xff;
- u >>= 8;
- }
- x[0] = 'I';
- SHA3Update(&cx, x, 9);
- break;
- }
- case SQLITE_FLOAT: {
- sqlite3_uint64 u;
- int j;
- unsigned char x[9];
- double r = sqlite3_column_double(pStmt,i);
- memcpy(&u, &r, 8);
- for(j=8; j>=1; j--){
- x[j] = u & 0xff;
- u >>= 8;
- }
- x[0] = 'F';
- SHA3Update(&cx,x,9);
- break;
- }
- case SQLITE_TEXT: {
- int n2 = sqlite3_column_bytes(pStmt, i);
- const unsigned char *z2 = sqlite3_column_text(pStmt, i);
- hash_step_vformat(&cx,"T%d:",n2);
- SHA3Update(&cx, z2, n2);
- break;
- }
- case SQLITE_BLOB: {
- int n2 = sqlite3_column_bytes(pStmt, i);
- const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
- hash_step_vformat(&cx,"B%d:",n2);
- SHA3Update(&cx, z2, n2);
- break;
- }
- }
- }
- }
- sqlite3_finalize(pStmt);
- }
- sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_shathree_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,
- sha3Func, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,
- sha3Func, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,
- sha3QueryFunc, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,
- sha3QueryFunc, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/showauth.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/showauth.c
deleted file mode 100644
index 87a9a6843c4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/showauth.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-** 2014-09-21
-**
-** 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 SQLite extension adds a debug "authorizer" callback to the database
-** connection. The callback merely writes the authorization request to
-** standard output and returns SQLITE_OK.
-**
-** This extension can be used (for example) in the command-line shell to
-** trace the operation of the authorizer.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <stdio.h>
-
-/*
-** Display the authorization request
-*/
-static int authCallback(
- void *pClientData,
- int op,
- const char *z1,
- const char *z2,
- const char *z3,
- const char *z4
-){
- const char *zOp;
- char zOpSpace[50];
- switch( op ){
- case SQLITE_CREATE_INDEX: zOp = "CREATE_INDEX"; break;
- case SQLITE_CREATE_TABLE: zOp = "CREATE_TABLE"; break;
- case SQLITE_CREATE_TEMP_INDEX: zOp = "CREATE_TEMP_INDEX"; break;
- case SQLITE_CREATE_TEMP_TABLE: zOp = "CREATE_TEMP_TABLE"; break;
- case SQLITE_CREATE_TEMP_TRIGGER: zOp = "CREATE_TEMP_TRIGGER"; break;
- case SQLITE_CREATE_TEMP_VIEW: zOp = "CREATE_TEMP_VIEW"; break;
- case SQLITE_CREATE_TRIGGER: zOp = "CREATE_TRIGGER"; break;
- case SQLITE_CREATE_VIEW: zOp = "CREATE_VIEW"; break;
- case SQLITE_DELETE: zOp = "DELETE"; break;
- case SQLITE_DROP_INDEX: zOp = "DROP_INDEX"; break;
- case SQLITE_DROP_TABLE: zOp = "DROP_TABLE"; break;
- case SQLITE_DROP_TEMP_INDEX: zOp = "DROP_TEMP_INDEX"; break;
- case SQLITE_DROP_TEMP_TABLE: zOp = "DROP_TEMP_TABLE"; break;
- case SQLITE_DROP_TEMP_TRIGGER: zOp = "DROP_TEMP_TRIGGER"; break;
- case SQLITE_DROP_TEMP_VIEW: zOp = "DROP_TEMP_VIEW"; break;
- case SQLITE_DROP_TRIGGER: zOp = "DROP_TRIGGER"; break;
- case SQLITE_DROP_VIEW: zOp = "DROP_VIEW"; break;
- case SQLITE_INSERT: zOp = "INSERT"; break;
- case SQLITE_PRAGMA: zOp = "PRAGMA"; break;
- case SQLITE_READ: zOp = "READ"; break;
- case SQLITE_SELECT: zOp = "SELECT"; break;
- case SQLITE_TRANSACTION: zOp = "TRANSACTION"; break;
- case SQLITE_UPDATE: zOp = "UPDATE"; break;
- case SQLITE_ATTACH: zOp = "ATTACH"; break;
- case SQLITE_DETACH: zOp = "DETACH"; break;
- case SQLITE_ALTER_TABLE: zOp = "ALTER_TABLE"; break;
- case SQLITE_REINDEX: zOp = "REINDEX"; break;
- case SQLITE_ANALYZE: zOp = "ANALYZE"; break;
- case SQLITE_CREATE_VTABLE: zOp = "CREATE_VTABLE"; break;
- case SQLITE_DROP_VTABLE: zOp = "DROP_VTABLE"; break;
- case SQLITE_FUNCTION: zOp = "FUNCTION"; break;
- case SQLITE_SAVEPOINT: zOp = "SAVEPOINT"; break;
- case SQLITE_COPY: zOp = "COPY"; break;
- case SQLITE_RECURSIVE: zOp = "RECURSIVE"; break;
-
-
- default: {
- sqlite3_snprintf(sizeof(zOpSpace), zOpSpace, "%d", op);
- zOp = zOpSpace;
- break;
- }
- }
- if( z1==0 ) z1 = "NULL";
- if( z2==0 ) z2 = "NULL";
- if( z3==0 ) z3 = "NULL";
- if( z4==0 ) z4 = "NULL";
- printf("AUTH: %s,%s,%s,%s,%s\n", zOp, z1, z2, z3, z4);
- return SQLITE_OK;
-}
-
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_showauth_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_set_authorizer(db, authCallback, 0);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/spellfix.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/spellfix.c
deleted file mode 100644
index faceea189ce..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/spellfix.c
+++ /dev/null
@@ -1,3058 +0,0 @@
-/*
-** 2012 April 10
-**
-** 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 module implements the spellfix1 VIRTUAL TABLE that can be used
-** to search a large vocabulary for close matches. See separate
-** documentation (http://www.sqlite.org/spellfix1.html) for details.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-#ifndef SQLITE_AMALGAMATION
-# if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
-# define NDEBUG 1
-# endif
-# if defined(NDEBUG) && defined(SQLITE_DEBUG)
-# undef NDEBUG
-# endif
-# include <string.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <assert.h>
-# define ALWAYS(X) 1
-# define NEVER(X) 0
- typedef unsigned char u8;
- typedef unsigned short u16;
-#endif
-#include <ctype.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Character classes for ASCII characters:
-**
-** 0 '' Silent letters: H W
-** 1 'A' Any vowel: A E I O U (Y)
-** 2 'B' A bilabeal stop or fricative: B F P V W
-** 3 'C' Other fricatives or back stops: C G J K Q S X Z
-** 4 'D' Alveolar stops: D T
-** 5 'H' Letter H at the beginning of a word
-** 6 'L' Glide: L
-** 7 'R' Semivowel: R
-** 8 'M' Nasals: M N
-** 9 'Y' Letter Y at the beginning of a word.
-** 10 '9' Digits: 0 1 2 3 4 5 6 7 8 9
-** 11 ' ' White space
-** 12 '?' Other.
-*/
-#define CCLASS_SILENT 0
-#define CCLASS_VOWEL 1
-#define CCLASS_B 2
-#define CCLASS_C 3
-#define CCLASS_D 4
-#define CCLASS_H 5
-#define CCLASS_L 6
-#define CCLASS_R 7
-#define CCLASS_M 8
-#define CCLASS_Y 9
-#define CCLASS_DIGIT 10
-#define CCLASS_SPACE 11
-#define CCLASS_OTHER 12
-
-/*
-** The following table gives the character class for non-initial ASCII
-** characters.
-*/
-static const unsigned char midClass[] = {
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_SPACE, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_SPACE, /* */ CCLASS_SPACE, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_SPACE,
- /* ! */ CCLASS_OTHER, /* " */ CCLASS_OTHER, /* # */ CCLASS_OTHER,
- /* $ */ CCLASS_OTHER, /* % */ CCLASS_OTHER, /* & */ CCLASS_OTHER,
- /* ' */ CCLASS_SILENT, /* ( */ CCLASS_OTHER, /* ) */ CCLASS_OTHER,
- /* * */ CCLASS_OTHER, /* + */ CCLASS_OTHER, /* , */ CCLASS_OTHER,
- /* - */ CCLASS_OTHER, /* . */ CCLASS_OTHER, /* / */ CCLASS_OTHER,
- /* 0 */ CCLASS_DIGIT, /* 1 */ CCLASS_DIGIT, /* 2 */ CCLASS_DIGIT,
- /* 3 */ CCLASS_DIGIT, /* 4 */ CCLASS_DIGIT, /* 5 */ CCLASS_DIGIT,
- /* 6 */ CCLASS_DIGIT, /* 7 */ CCLASS_DIGIT, /* 8 */ CCLASS_DIGIT,
- /* 9 */ CCLASS_DIGIT, /* : */ CCLASS_OTHER, /* ; */ CCLASS_OTHER,
- /* < */ CCLASS_OTHER, /* = */ CCLASS_OTHER, /* > */ CCLASS_OTHER,
- /* ? */ CCLASS_OTHER, /* @ */ CCLASS_OTHER, /* A */ CCLASS_VOWEL,
- /* B */ CCLASS_B, /* C */ CCLASS_C, /* D */ CCLASS_D,
- /* E */ CCLASS_VOWEL, /* F */ CCLASS_B, /* G */ CCLASS_C,
- /* H */ CCLASS_SILENT, /* I */ CCLASS_VOWEL, /* J */ CCLASS_C,
- /* K */ CCLASS_C, /* L */ CCLASS_L, /* M */ CCLASS_M,
- /* N */ CCLASS_M, /* O */ CCLASS_VOWEL, /* P */ CCLASS_B,
- /* Q */ CCLASS_C, /* R */ CCLASS_R, /* S */ CCLASS_C,
- /* T */ CCLASS_D, /* U */ CCLASS_VOWEL, /* V */ CCLASS_B,
- /* W */ CCLASS_B, /* X */ CCLASS_C, /* Y */ CCLASS_VOWEL,
- /* Z */ CCLASS_C, /* [ */ CCLASS_OTHER, /* \ */ CCLASS_OTHER,
- /* ] */ CCLASS_OTHER, /* ^ */ CCLASS_OTHER, /* _ */ CCLASS_OTHER,
- /* ` */ CCLASS_OTHER, /* a */ CCLASS_VOWEL, /* b */ CCLASS_B,
- /* c */ CCLASS_C, /* d */ CCLASS_D, /* e */ CCLASS_VOWEL,
- /* f */ CCLASS_B, /* g */ CCLASS_C, /* h */ CCLASS_SILENT,
- /* i */ CCLASS_VOWEL, /* j */ CCLASS_C, /* k */ CCLASS_C,
- /* l */ CCLASS_L, /* m */ CCLASS_M, /* n */ CCLASS_M,
- /* o */ CCLASS_VOWEL, /* p */ CCLASS_B, /* q */ CCLASS_C,
- /* r */ CCLASS_R, /* s */ CCLASS_C, /* t */ CCLASS_D,
- /* u */ CCLASS_VOWEL, /* v */ CCLASS_B, /* w */ CCLASS_B,
- /* x */ CCLASS_C, /* y */ CCLASS_VOWEL, /* z */ CCLASS_C,
- /* { */ CCLASS_OTHER, /* | */ CCLASS_OTHER, /* } */ CCLASS_OTHER,
- /* ~ */ CCLASS_OTHER, /* */ CCLASS_OTHER,
-};
-/*
-** This tables gives the character class for ASCII characters that form the
-** initial character of a word. The only difference from midClass is with
-** the letters H, W, and Y.
-*/
-static const unsigned char initClass[] = {
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_SPACE, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_SPACE, /* */ CCLASS_SPACE, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER,
- /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_SPACE,
- /* ! */ CCLASS_OTHER, /* " */ CCLASS_OTHER, /* # */ CCLASS_OTHER,
- /* $ */ CCLASS_OTHER, /* % */ CCLASS_OTHER, /* & */ CCLASS_OTHER,
- /* ' */ CCLASS_OTHER, /* ( */ CCLASS_OTHER, /* ) */ CCLASS_OTHER,
- /* * */ CCLASS_OTHER, /* + */ CCLASS_OTHER, /* , */ CCLASS_OTHER,
- /* - */ CCLASS_OTHER, /* . */ CCLASS_OTHER, /* / */ CCLASS_OTHER,
- /* 0 */ CCLASS_DIGIT, /* 1 */ CCLASS_DIGIT, /* 2 */ CCLASS_DIGIT,
- /* 3 */ CCLASS_DIGIT, /* 4 */ CCLASS_DIGIT, /* 5 */ CCLASS_DIGIT,
- /* 6 */ CCLASS_DIGIT, /* 7 */ CCLASS_DIGIT, /* 8 */ CCLASS_DIGIT,
- /* 9 */ CCLASS_DIGIT, /* : */ CCLASS_OTHER, /* ; */ CCLASS_OTHER,
- /* < */ CCLASS_OTHER, /* = */ CCLASS_OTHER, /* > */ CCLASS_OTHER,
- /* ? */ CCLASS_OTHER, /* @ */ CCLASS_OTHER, /* A */ CCLASS_VOWEL,
- /* B */ CCLASS_B, /* C */ CCLASS_C, /* D */ CCLASS_D,
- /* E */ CCLASS_VOWEL, /* F */ CCLASS_B, /* G */ CCLASS_C,
- /* H */ CCLASS_SILENT, /* I */ CCLASS_VOWEL, /* J */ CCLASS_C,
- /* K */ CCLASS_C, /* L */ CCLASS_L, /* M */ CCLASS_M,
- /* N */ CCLASS_M, /* O */ CCLASS_VOWEL, /* P */ CCLASS_B,
- /* Q */ CCLASS_C, /* R */ CCLASS_R, /* S */ CCLASS_C,
- /* T */ CCLASS_D, /* U */ CCLASS_VOWEL, /* V */ CCLASS_B,
- /* W */ CCLASS_B, /* X */ CCLASS_C, /* Y */ CCLASS_Y,
- /* Z */ CCLASS_C, /* [ */ CCLASS_OTHER, /* \ */ CCLASS_OTHER,
- /* ] */ CCLASS_OTHER, /* ^ */ CCLASS_OTHER, /* _ */ CCLASS_OTHER,
- /* ` */ CCLASS_OTHER, /* a */ CCLASS_VOWEL, /* b */ CCLASS_B,
- /* c */ CCLASS_C, /* d */ CCLASS_D, /* e */ CCLASS_VOWEL,
- /* f */ CCLASS_B, /* g */ CCLASS_C, /* h */ CCLASS_SILENT,
- /* i */ CCLASS_VOWEL, /* j */ CCLASS_C, /* k */ CCLASS_C,
- /* l */ CCLASS_L, /* m */ CCLASS_M, /* n */ CCLASS_M,
- /* o */ CCLASS_VOWEL, /* p */ CCLASS_B, /* q */ CCLASS_C,
- /* r */ CCLASS_R, /* s */ CCLASS_C, /* t */ CCLASS_D,
- /* u */ CCLASS_VOWEL, /* v */ CCLASS_B, /* w */ CCLASS_B,
- /* x */ CCLASS_C, /* y */ CCLASS_Y, /* z */ CCLASS_C,
- /* { */ CCLASS_OTHER, /* | */ CCLASS_OTHER, /* } */ CCLASS_OTHER,
- /* ~ */ CCLASS_OTHER, /* */ CCLASS_OTHER,
-};
-
-/*
-** Mapping from the character class number (0-13) to a symbol for each
-** character class. Note that initClass[] can be used to map the class
-** symbol back into the class number.
-*/
-static const unsigned char className[] = ".ABCDHLRMY9 ?";
-
-/*
-** Generate a "phonetic hash" from a string of ASCII characters
-** in zIn[0..nIn-1].
-**
-** * Map characters by character class as defined above.
-** * Omit double-letters
-** * Omit vowels beside R and L
-** * Omit T when followed by CH
-** * Omit W when followed by R
-** * Omit D when followed by J or G
-** * Omit K in KN or G in GN at the beginning of a word
-**
-** Space to hold the result is obtained from sqlite3_malloc()
-**
-** Return NULL if memory allocation fails.
-*/
-static unsigned char *phoneticHash(const unsigned char *zIn, int nIn){
- unsigned char *zOut = sqlite3_malloc64( nIn + 1 );
- int i;
- int nOut = 0;
- char cPrev = 0x77;
- char cPrevX = 0x77;
- const unsigned char *aClass = initClass;
-
- if( zOut==0 ) return 0;
- if( nIn>2 ){
- switch( zIn[0] ){
- case 'g':
- case 'k': {
- if( zIn[1]=='n' ){ zIn++; nIn--; }
- break;
- }
- }
- }
- for(i=0; i<nIn; i++){
- unsigned char c = zIn[i];
- if( i+1<nIn ){
- if( c=='w' && zIn[i+1]=='r' ) continue;
- if( c=='d' && (zIn[i+1]=='j' || zIn[i+1]=='g') ) continue;
- if( i+2<nIn ){
- if( c=='t' && zIn[i+1]=='c' && zIn[i+2]=='h' ) continue;
- }
- }
- c = aClass[c&0x7f];
- if( c==CCLASS_SPACE ) continue;
- if( c==CCLASS_OTHER && cPrev!=CCLASS_DIGIT ) continue;
- aClass = midClass;
- if( c==CCLASS_VOWEL && (cPrevX==CCLASS_R || cPrevX==CCLASS_L) ){
- continue; /* No vowels beside L or R */
- }
- if( (c==CCLASS_R || c==CCLASS_L) && cPrevX==CCLASS_VOWEL ){
- nOut--; /* No vowels beside L or R */
- }
- cPrev = c;
- if( c==CCLASS_SILENT ) continue;
- cPrevX = c;
- c = className[c];
- assert( nOut>=0 );
- if( nOut==0 || c!=zOut[nOut-1] ) zOut[nOut++] = c;
- }
- zOut[nOut] = 0;
- return zOut;
-}
-
-/*
-** This is an SQL function wrapper around phoneticHash(). See
-** the description of phoneticHash() for additional information.
-*/
-static void phoneticHashSqlFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zIn;
- unsigned char *zOut;
-
- zIn = sqlite3_value_text(argv[0]);
- if( zIn==0 ) return;
- zOut = phoneticHash(zIn, sqlite3_value_bytes(argv[0]));
- if( zOut==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_text(context, (char*)zOut, -1, sqlite3_free);
- }
-}
-
-/*
-** Return the character class number for a character given its
-** context.
-*/
-static char characterClass(char cPrev, char c){
- return cPrev==0 ? initClass[c&0x7f] : midClass[c&0x7f];
-}
-
-/*
-** Return the cost of inserting or deleting character c immediately
-** following character cPrev. If cPrev==0, that means c is the first
-** character of the word.
-*/
-static int insertOrDeleteCost(char cPrev, char c, char cNext){
- char classC = characterClass(cPrev, c);
- char classCprev;
-
- if( classC==CCLASS_SILENT ){
- /* Insert or delete "silent" characters such as H or W */
- return 1;
- }
- if( cPrev==c ){
- /* Repeated characters, or miss a repeat */
- return 10;
- }
- if( classC==CCLASS_VOWEL && (cPrev=='r' || cNext=='r') ){
- return 20; /* Insert a vowel before or after 'r' */
- }
- classCprev = characterClass(cPrev, cPrev);
- if( classC==classCprev ){
- if( classC==CCLASS_VOWEL ){
- /* Remove or add a new vowel to a vowel cluster */
- return 15;
- }else{
- /* Remove or add a consonant not in the same class */
- return 50;
- }
- }
-
- /* any other character insertion or deletion */
- return 100;
-}
-
-/*
-** Divide the insertion cost by this factor when appending to the
-** end of the word.
-*/
-#define FINAL_INS_COST_DIV 4
-
-/*
-** Return the cost of substituting cTo in place of cFrom assuming
-** the previous character is cPrev. If cPrev==0 then cTo is the first
-** character of the word.
-*/
-static int substituteCost(char cPrev, char cFrom, char cTo){
- char classFrom, classTo;
- if( cFrom==cTo ){
- /* Exact match */
- return 0;
- }
- if( cFrom==(cTo^0x20) && ((cTo>='A' && cTo<='Z') || (cTo>='a' && cTo<='z')) ){
- /* differ only in case */
- return 0;
- }
- classFrom = characterClass(cPrev, cFrom);
- classTo = characterClass(cPrev, cTo);
- if( classFrom==classTo ){
- /* Same character class */
- return 40;
- }
- if( classFrom>=CCLASS_B && classFrom<=CCLASS_Y
- && classTo>=CCLASS_B && classTo<=CCLASS_Y ){
- /* Convert from one consonant to another, but in a different class */
- return 75;
- }
- /* Any other subsitution */
- return 100;
-}
-
-/*
-** Given two strings zA and zB which are pure ASCII, return the cost
-** of transforming zA into zB. If zA ends with '*' assume that it is
-** a prefix of zB and give only minimal penalty for extra characters
-** on the end of zB.
-**
-** Smaller numbers mean a closer match.
-**
-** Negative values indicate an error:
-** -1 One of the inputs is NULL
-** -2 Non-ASCII characters on input
-** -3 Unable to allocate memory
-**
-** If pnMatch is not NULL, then *pnMatch is set to the number of bytes
-** of zB that matched the pattern in zA. If zA does not end with a '*',
-** then this value is always the number of bytes in zB (i.e. strlen(zB)).
-** If zA does end in a '*', then it is the number of bytes in the prefix
-** of zB that was deemed to match zA.
-*/
-static int editdist1(const char *zA, const char *zB, int *pnMatch){
- int nA, nB; /* Number of characters in zA[] and zB[] */
- int xA, xB; /* Loop counters for zA[] and zB[] */
- char cA = 0, cB; /* Current character of zA and zB */
- char cAprev, cBprev; /* Previous character of zA and zB */
- char cAnext, cBnext; /* Next character in zA and zB */
- int d; /* North-west cost value */
- int dc = 0; /* North-west character value */
- int res; /* Final result */
- int *m; /* The cost matrix */
- char *cx; /* Corresponding character values */
- int *toFree = 0; /* Malloced space */
- int nMatch = 0;
- int mStack[60+15]; /* Stack space to use if not too much is needed */
-
- /* Early out if either input is NULL */
- if( zA==0 || zB==0 ) return -1;
-
- /* Skip any common prefix */
- while( zA[0] && zA[0]==zB[0] ){ dc = zA[0]; zA++; zB++; nMatch++; }
- if( pnMatch ) *pnMatch = nMatch;
- if( zA[0]==0 && zB[0]==0 ) return 0;
-
-#if 0
- printf("A=\"%s\" B=\"%s\" dc=%c\n", zA, zB, dc?dc:' ');
-#endif
-
- /* Verify input strings and measure their lengths */
- for(nA=0; zA[nA]; nA++){
- if( zA[nA]&0x80 ) return -2;
- }
- for(nB=0; zB[nB]; nB++){
- if( zB[nB]&0x80 ) return -2;
- }
-
- /* Special processing if either string is empty */
- if( nA==0 ){
- cBprev = (char)dc;
- for(xB=res=0; (cB = zB[xB])!=0; xB++){
- res += insertOrDeleteCost(cBprev, cB, zB[xB+1])/FINAL_INS_COST_DIV;
- cBprev = cB;
- }
- return res;
- }
- if( nB==0 ){
- cAprev = (char)dc;
- for(xA=res=0; (cA = zA[xA])!=0; xA++){
- res += insertOrDeleteCost(cAprev, cA, zA[xA+1]);
- cAprev = cA;
- }
- return res;
- }
-
- /* A is a prefix of B */
- if( zA[0]=='*' && zA[1]==0 ) return 0;
-
- /* Allocate and initialize the Wagner matrix */
- if( nB<(sizeof(mStack)*4)/(sizeof(mStack[0])*5) ){
- m = mStack;
- }else{
- m = toFree = sqlite3_malloc64( (nB+1)*5*sizeof(m[0])/4 );
- if( m==0 ) return -3;
- }
- cx = (char*)&m[nB+1];
-
- /* Compute the Wagner edit distance */
- m[0] = 0;
- cx[0] = (char)dc;
- cBprev = (char)dc;
- for(xB=1; xB<=nB; xB++){
- cBnext = zB[xB];
- cB = zB[xB-1];
- cx[xB] = cB;
- m[xB] = m[xB-1] + insertOrDeleteCost(cBprev, cB, cBnext);
- cBprev = cB;
- }
- cAprev = (char)dc;
- for(xA=1; xA<=nA; xA++){
- int lastA = (xA==nA);
- cA = zA[xA-1];
- cAnext = zA[xA];
- if( cA=='*' && lastA ) break;
- d = m[0];
- dc = cx[0];
- m[0] = d + insertOrDeleteCost(cAprev, cA, cAnext);
- cBprev = 0;
- for(xB=1; xB<=nB; xB++){
- int totalCost, insCost, delCost, subCost, ncx;
- cB = zB[xB-1];
- cBnext = zB[xB];
-
- /* Cost to insert cB */
- insCost = insertOrDeleteCost(cx[xB-1], cB, cBnext);
- if( lastA ) insCost /= FINAL_INS_COST_DIV;
-
- /* Cost to delete cA */
- delCost = insertOrDeleteCost(cx[xB], cA, cBnext);
-
- /* Cost to substitute cA->cB */
- subCost = substituteCost(cx[xB-1], cA, cB);
-
- /* Best cost */
- totalCost = insCost + m[xB-1];
- ncx = cB;
- if( (delCost + m[xB])<totalCost ){
- totalCost = delCost + m[xB];
- ncx = cA;
- }
- if( (subCost + d)<totalCost ){
- totalCost = subCost + d;
- }
-
-#if 0
- printf("%d,%d d=%4d u=%4d r=%4d dc=%c cA=%c cB=%c"
- " ins=%4d del=%4d sub=%4d t=%4d ncx=%c\n",
- xA, xB, d, m[xB], m[xB-1], dc?dc:' ', cA, cB,
- insCost, delCost, subCost, totalCost, ncx?ncx:' ');
-#endif
-
- /* Update the matrix */
- d = m[xB];
- dc = cx[xB];
- m[xB] = totalCost;
- cx[xB] = (char)ncx;
- cBprev = cB;
- }
- cAprev = cA;
- }
-
- /* Free the wagner matrix and return the result */
- if( cA=='*' ){
- res = m[1];
- for(xB=1; xB<=nB; xB++){
- if( m[xB]<res ){
- res = m[xB];
- if( pnMatch ) *pnMatch = xB+nMatch;
- }
- }
- }else{
- res = m[nB];
- /* In the current implementation, pnMatch is always NULL if zA does
- ** not end in "*" */
- assert( pnMatch==0 );
- }
- sqlite3_free(toFree);
- return res;
-}
-
-/*
-** Function: editdist(A,B)
-**
-** Return the cost of transforming string A into string B. Both strings
-** must be pure ASCII text. If A ends with '*' then it is assumed to be
-** a prefix of B and extra characters on the end of B have minimal additional
-** cost.
-*/
-static void editdistSqlFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int res = editdist1(
- (const char*)sqlite3_value_text(argv[0]),
- (const char*)sqlite3_value_text(argv[1]),
- 0);
- if( res<0 ){
- if( res==(-3) ){
- sqlite3_result_error_nomem(context);
- }else if( res==(-2) ){
- sqlite3_result_error(context, "non-ASCII input to editdist()", -1);
- }else{
- sqlite3_result_error(context, "NULL input to editdist()", -1);
- }
- }else{
- sqlite3_result_int(context, res);
- }
-}
-
-/* End of the fixed-cost edit distance implementation
-******************************************************************************
-*****************************************************************************
-** Begin: Configurable cost unicode edit distance routines
-*/
-/* Forward declaration of structures */
-typedef struct EditDist3Cost EditDist3Cost;
-typedef struct EditDist3Config EditDist3Config;
-typedef struct EditDist3Point EditDist3Point;
-typedef struct EditDist3From EditDist3From;
-typedef struct EditDist3FromString EditDist3FromString;
-typedef struct EditDist3To EditDist3To;
-typedef struct EditDist3ToString EditDist3ToString;
-typedef struct EditDist3Lang EditDist3Lang;
-
-
-/*
-** An entry in the edit cost table
-*/
-struct EditDist3Cost {
- EditDist3Cost *pNext; /* Next cost element */
- u8 nFrom; /* Number of bytes in aFrom */
- u8 nTo; /* Number of bytes in aTo */
- u16 iCost; /* Cost of this transformation */
- char a[4] ; /* FROM string followed by TO string */
- /* Additional TO and FROM string bytes appended as necessary */
-};
-
-/*
-** Edit costs for a particular language ID
-*/
-struct EditDist3Lang {
- int iLang; /* Language ID */
- int iInsCost; /* Default insertion cost */
- int iDelCost; /* Default deletion cost */
- int iSubCost; /* Default substitution cost */
- EditDist3Cost *pCost; /* Costs */
-};
-
-
-/*
-** The default EditDist3Lang object, with default costs.
-*/
-static const EditDist3Lang editDist3Lang = { 0, 100, 100, 150, 0 };
-
-/*
-** Complete configuration
-*/
-struct EditDist3Config {
- int nLang; /* Number of language IDs. Size of a[] */
- EditDist3Lang *a; /* One for each distinct language ID */
-};
-
-/*
-** Extra information about each character in the FROM string.
-*/
-struct EditDist3From {
- int nSubst; /* Number of substitution cost entries */
- int nDel; /* Number of deletion cost entries */
- int nByte; /* Number of bytes in this character */
- EditDist3Cost **apSubst; /* Array of substitution costs for this element */
- EditDist3Cost **apDel; /* Array of deletion cost entries */
-};
-
-/*
-** A precompiled FROM string.
-*
-** In the common case we expect the FROM string to be reused multiple times.
-** In other words, the common case will be to measure the edit distance
-** from a single origin string to multiple target strings.
-*/
-struct EditDist3FromString {
- char *z; /* The complete text of the FROM string */
- int n; /* Number of characters in the FROM string */
- int isPrefix; /* True if ends with '*' character */
- EditDist3From *a; /* Extra info about each char of the FROM string */
-};
-
-/*
-** Extra information about each character in the TO string.
-*/
-struct EditDist3To {
- int nIns; /* Number of insertion cost entries */
- int nByte; /* Number of bytes in this character */
- EditDist3Cost **apIns; /* Array of deletion cost entries */
-};
-
-/*
-** A precompiled FROM string
-*/
-struct EditDist3ToString {
- char *z; /* The complete text of the TO string */
- int n; /* Number of characters in the TO string */
- EditDist3To *a; /* Extra info about each char of the TO string */
-};
-
-/*
-** Clear or delete an instance of the object that records all edit-distance
-** weights.
-*/
-static void editDist3ConfigClear(EditDist3Config *p){
- int i;
- if( p==0 ) return;
- for(i=0; i<p->nLang; i++){
- EditDist3Cost *pCost, *pNext;
- pCost = p->a[i].pCost;
- while( pCost ){
- pNext = pCost->pNext;
- sqlite3_free(pCost);
- pCost = pNext;
- }
- }
- sqlite3_free(p->a);
- memset(p, 0, sizeof(*p));
-}
-static void editDist3ConfigDelete(void *pIn){
- EditDist3Config *p = (EditDist3Config*)pIn;
- editDist3ConfigClear(p);
- sqlite3_free(p);
-}
-
-/* Compare the FROM values of two EditDist3Cost objects, for sorting.
-** Return negative, zero, or positive if the A is less than, equal to,
-** or greater than B.
-*/
-static int editDist3CostCompare(EditDist3Cost *pA, EditDist3Cost *pB){
- int n = pA->nFrom;
- int rc;
- if( n>pB->nFrom ) n = pB->nFrom;
- rc = strncmp(pA->a, pB->a, n);
- if( rc==0 ) rc = pA->nFrom - pB->nFrom;
- return rc;
-}
-
-/*
-** Merge together two sorted lists of EditDist3Cost objects, in order
-** of increasing FROM.
-*/
-static EditDist3Cost *editDist3CostMerge(
- EditDist3Cost *pA,
- EditDist3Cost *pB
-){
- EditDist3Cost *pHead = 0;
- EditDist3Cost **ppTail = &pHead;
- EditDist3Cost *p;
- while( pA && pB ){
- if( editDist3CostCompare(pA,pB)<=0 ){
- p = pA;
- pA = pA->pNext;
- }else{
- p = pB;
- pB = pB->pNext;
- }
- *ppTail = p;
- ppTail = &p->pNext;
- }
- if( pA ){
- *ppTail = pA;
- }else{
- *ppTail = pB;
- }
- return pHead;
-}
-
-/*
-** Sort a list of EditDist3Cost objects into order of increasing FROM
-*/
-static EditDist3Cost *editDist3CostSort(EditDist3Cost *pList){
- EditDist3Cost *ap[60], *p;
- int i;
- int mx = 0;
- ap[0] = 0;
- ap[1] = 0;
- while( pList ){
- p = pList;
- pList = p->pNext;
- p->pNext = 0;
- for(i=0; ap[i]; i++){
- p = editDist3CostMerge(ap[i],p);
- ap[i] = 0;
- }
- ap[i] = p;
- if( i>mx ){
- mx = i;
- ap[i+1] = 0;
- }
- }
- p = 0;
- for(i=0; i<=mx; i++){
- if( ap[i] ) p = editDist3CostMerge(p,ap[i]);
- }
- return p;
-}
-
-/*
-** Load all edit-distance weights from a table.
-*/
-static int editDist3ConfigLoad(
- EditDist3Config *p, /* The edit distance configuration to load */
- sqlite3 *db, /* Load from this database */
- const char *zTable /* Name of the table from which to load */
-){
- sqlite3_stmt *pStmt;
- int rc, rc2;
- char *zSql;
- int iLangPrev = -9999;
- EditDist3Lang *pLang = 0;
-
- zSql = sqlite3_mprintf("SELECT iLang, cFrom, cTo, iCost"
- " FROM \"%w\" WHERE iLang>=0 ORDER BY iLang", zTable);
- if( zSql==0 ) return SQLITE_NOMEM;
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ) return rc;
- editDist3ConfigClear(p);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- int iLang = sqlite3_column_int(pStmt, 0);
- const char *zFrom = (const char*)sqlite3_column_text(pStmt, 1);
- int nFrom = zFrom ? sqlite3_column_bytes(pStmt, 1) : 0;
- const char *zTo = (const char*)sqlite3_column_text(pStmt, 2);
- int nTo = zTo ? sqlite3_column_bytes(pStmt, 2) : 0;
- int iCost = sqlite3_column_int(pStmt, 3);
-
- assert( zFrom!=0 || nFrom==0 );
- assert( zTo!=0 || nTo==0 );
- if( nFrom>100 || nTo>100 ) continue;
- if( iCost<0 ) continue;
- if( iCost>=10000 ) continue; /* Costs above 10K are considered infinite */
- if( pLang==0 || iLang!=iLangPrev ){
- EditDist3Lang *pNew;
- pNew = sqlite3_realloc64(p->a, (p->nLang+1)*sizeof(p->a[0]));
- if( pNew==0 ){ rc = SQLITE_NOMEM; break; }
- p->a = pNew;
- pLang = &p->a[p->nLang];
- p->nLang++;
- pLang->iLang = iLang;
- pLang->iInsCost = 100;
- pLang->iDelCost = 100;
- pLang->iSubCost = 150;
- pLang->pCost = 0;
- iLangPrev = iLang;
- }
- if( nFrom==1 && zFrom[0]=='?' && nTo==0 ){
- pLang->iDelCost = iCost;
- }else if( nFrom==0 && nTo==1 && zTo[0]=='?' ){
- pLang->iInsCost = iCost;
- }else if( nFrom==1 && nTo==1 && zFrom[0]=='?' && zTo[0]=='?' ){
- pLang->iSubCost = iCost;
- }else{
- EditDist3Cost *pCost;
- int nExtra = nFrom + nTo - 4;
- if( nExtra<0 ) nExtra = 0;
- pCost = sqlite3_malloc64( sizeof(*pCost) + nExtra );
- if( pCost==0 ){ rc = SQLITE_NOMEM; break; }
- pCost->nFrom = (u8)nFrom;
- pCost->nTo = (u8)nTo;
- pCost->iCost = (u16)iCost;
- memcpy(pCost->a, zFrom, nFrom);
- memcpy(pCost->a + nFrom, zTo, nTo);
- pCost->pNext = pLang->pCost;
- pLang->pCost = pCost;
- }
- }
- rc2 = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) rc = rc2;
- if( rc==SQLITE_OK ){
- int iLang;
- for(iLang=0; iLang<p->nLang; iLang++){
- p->a[iLang].pCost = editDist3CostSort(p->a[iLang].pCost);
- }
- }
- return rc;
-}
-
-/*
-** Return the length (in bytes) of a utf-8 character. Or return a maximum
-** of N.
-*/
-static int utf8Len(unsigned char c, int N){
- int len = 1;
- if( c>0x7f ){
- if( (c&0xe0)==0xc0 ){
- len = 2;
- }else if( (c&0xf0)==0xe0 ){
- len = 3;
- }else{
- len = 4;
- }
- }
- if( len>N ) len = N;
- return len;
-}
-
-/*
-** Return TRUE (non-zero) if the To side of the given cost matches
-** the given string.
-*/
-static int matchTo(EditDist3Cost *p, const char *z, int n){
- assert( n>0 );
- if( p->a[p->nFrom]!=z[0] ) return 0;
- if( p->nTo>n ) return 0;
- if( strncmp(p->a+p->nFrom, z, p->nTo)!=0 ) return 0;
- return 1;
-}
-
-/*
-** Return TRUE (non-zero) if the From side of the given cost matches
-** the given string.
-*/
-static int matchFrom(EditDist3Cost *p, const char *z, int n){
- assert( p->nFrom<=n );
- if( p->nFrom ){
- if( p->a[0]!=z[0] ) return 0;
- if( strncmp(p->a, z, p->nFrom)!=0 ) return 0;
- }
- return 1;
-}
-
-/*
-** Return TRUE (non-zero) of the next FROM character and the next TO
-** character are the same.
-*/
-static int matchFromTo(
- EditDist3FromString *pStr, /* Left hand string */
- int n1, /* Index of comparison character on the left */
- const char *z2, /* Right-handl comparison character */
- int n2 /* Bytes remaining in z2[] */
-){
- int b1 = pStr->a[n1].nByte;
- if( b1>n2 ) return 0;
- assert( b1>0 );
- if( pStr->z[n1]!=z2[0] ) return 0;
- if( strncmp(pStr->z+n1, z2, b1)!=0 ) return 0;
- return 1;
-}
-
-/*
-** Delete an EditDist3FromString objecct
-*/
-static void editDist3FromStringDelete(EditDist3FromString *p){
- int i;
- if( p ){
- for(i=0; i<p->n; i++){
- sqlite3_free(p->a[i].apDel);
- sqlite3_free(p->a[i].apSubst);
- }
- sqlite3_free(p);
- }
-}
-
-/*
-** Create a EditDist3FromString object.
-*/
-static EditDist3FromString *editDist3FromStringNew(
- const EditDist3Lang *pLang,
- const char *z,
- int n
-){
- EditDist3FromString *pStr;
- EditDist3Cost *p;
- int i;
-
- if( z==0 ) return 0;
- if( n<0 ) n = (int)strlen(z);
- pStr = sqlite3_malloc64( sizeof(*pStr) + sizeof(pStr->a[0])*n + n + 1 );
- if( pStr==0 ) return 0;
- pStr->a = (EditDist3From*)&pStr[1];
- memset(pStr->a, 0, sizeof(pStr->a[0])*n);
- pStr->n = n;
- pStr->z = (char*)&pStr->a[n];
- memcpy(pStr->z, z, n+1);
- if( n && z[n-1]=='*' ){
- pStr->isPrefix = 1;
- n--;
- pStr->n--;
- pStr->z[n] = 0;
- }else{
- pStr->isPrefix = 0;
- }
-
- for(i=0; i<n; i++){
- EditDist3From *pFrom = &pStr->a[i];
- memset(pFrom, 0, sizeof(*pFrom));
- pFrom->nByte = utf8Len((unsigned char)z[i], n-i);
- for(p=pLang->pCost; p; p=p->pNext){
- EditDist3Cost **apNew;
- if( i+p->nFrom>n ) continue;
- if( matchFrom(p, z+i, n-i)==0 ) continue;
- if( p->nTo==0 ){
- apNew = sqlite3_realloc64(pFrom->apDel,
- sizeof(*apNew)*(pFrom->nDel+1));
- if( apNew==0 ) break;
- pFrom->apDel = apNew;
- apNew[pFrom->nDel++] = p;
- }else{
- apNew = sqlite3_realloc64(pFrom->apSubst,
- sizeof(*apNew)*(pFrom->nSubst+1));
- if( apNew==0 ) break;
- pFrom->apSubst = apNew;
- apNew[pFrom->nSubst++] = p;
- }
- }
- if( p ){
- editDist3FromStringDelete(pStr);
- pStr = 0;
- break;
- }
- }
- return pStr;
-}
-
-/*
-** Update entry m[i] such that it is the minimum of its current value
-** and m[j]+iCost.
-*/
-static void updateCost(
- unsigned int *m,
- int i,
- int j,
- int iCost
-){
- unsigned int b;
- assert( iCost>=0 );
- assert( iCost<10000 );
- b = m[j] + iCost;
- if( b<m[i] ) m[i] = b;
-}
-
-/*
-** How much stack space (int bytes) to use for Wagner matrix in
-** editDist3Core(). If more space than this is required, the entire
-** matrix is taken from the heap. To reduce the load on the memory
-** allocator, make this value as large as practical for the
-** architecture in use.
-*/
-#ifndef SQLITE_SPELLFIX_STACKALLOC_SZ
-# define SQLITE_SPELLFIX_STACKALLOC_SZ (1024)
-#endif
-
-/* Compute the edit distance between two strings.
-**
-** If an error occurs, return a negative number which is the error code.
-**
-** If pnMatch is not NULL, then *pnMatch is set to the number of characters
-** (not bytes) in z2 that matched the search pattern in *pFrom. If pFrom does
-** not contain the pattern for a prefix-search, then this is always the number
-** of characters in z2. If pFrom does contain a prefix search pattern, then
-** it is the number of characters in the prefix of z2 that was deemed to
-** match pFrom.
-*/
-static int editDist3Core(
- EditDist3FromString *pFrom, /* The FROM string */
- const char *z2, /* The TO string */
- int n2, /* Length of the TO string */
- const EditDist3Lang *pLang, /* Edit weights for a particular language ID */
- int *pnMatch /* OUT: Characters in matched prefix */
-){
- int k, n;
- int i1, b1;
- int i2, b2;
- EditDist3FromString f = *pFrom;
- EditDist3To *a2;
- unsigned int *m;
- unsigned int *pToFree;
- int szRow;
- EditDist3Cost *p;
- int res;
- sqlite3_uint64 nByte;
- unsigned int stackSpace[SQLITE_SPELLFIX_STACKALLOC_SZ/sizeof(unsigned int)];
-
- /* allocate the Wagner matrix and the aTo[] array for the TO string */
- n = (f.n+1)*(n2+1);
- n = (n+1)&~1;
- nByte = n*sizeof(m[0]) + sizeof(a2[0])*n2;
- if( nByte<=sizeof(stackSpace) ){
- m = stackSpace;
- pToFree = 0;
- }else{
- m = pToFree = sqlite3_malloc64( nByte );
- if( m==0 ) return -1; /* Out of memory */
- }
- a2 = (EditDist3To*)&m[n];
- memset(a2, 0, sizeof(a2[0])*n2);
-
- /* Fill in the a1[] matrix for all characters of the TO string */
- for(i2=0; i2<n2; i2++){
- a2[i2].nByte = utf8Len((unsigned char)z2[i2], n2-i2);
- for(p=pLang->pCost; p; p=p->pNext){
- EditDist3Cost **apNew;
- if( p->nFrom>0 ) break;
- if( i2+p->nTo>n2 ) continue;
- if( p->a[0]>z2[i2] ) break;
- if( matchTo(p, z2+i2, n2-i2)==0 ) continue;
- a2[i2].nIns++;
- apNew = sqlite3_realloc64(a2[i2].apIns, sizeof(*apNew)*a2[i2].nIns);
- if( apNew==0 ){
- res = -1; /* Out of memory */
- goto editDist3Abort;
- }
- a2[i2].apIns = apNew;
- a2[i2].apIns[a2[i2].nIns-1] = p;
- }
- }
-
- /* Prepare to compute the minimum edit distance */
- szRow = f.n+1;
- memset(m, 0x01, (n2+1)*szRow*sizeof(m[0]));
- m[0] = 0;
-
- /* First fill in the top-row of the matrix with FROM deletion costs */
- for(i1=0; i1<f.n; i1 += b1){
- b1 = f.a[i1].nByte;
- updateCost(m, i1+b1, i1, pLang->iDelCost);
- for(k=0; k<f.a[i1].nDel; k++){
- p = f.a[i1].apDel[k];
- updateCost(m, i1+p->nFrom, i1, p->iCost);
- }
- }
-
- /* Fill in all subsequent rows, top-to-bottom, left-to-right */
- for(i2=0; i2<n2; i2 += b2){
- int rx; /* Starting index for current row */
- int rxp; /* Starting index for previous row */
- b2 = a2[i2].nByte;
- rx = szRow*(i2+b2);
- rxp = szRow*i2;
- updateCost(m, rx, rxp, pLang->iInsCost);
- for(k=0; k<a2[i2].nIns; k++){
- p = a2[i2].apIns[k];
- updateCost(m, szRow*(i2+p->nTo), rxp, p->iCost);
- }
- for(i1=0; i1<f.n; i1+=b1){
- int cx; /* Index of current cell */
- int cxp; /* Index of cell immediately to the left */
- int cxd; /* Index of cell to the left and one row above */
- int cxu; /* Index of cell immediately above */
- b1 = f.a[i1].nByte;
- cxp = rx + i1;
- cx = cxp + b1;
- cxd = rxp + i1;
- cxu = cxd + b1;
- updateCost(m, cx, cxp, pLang->iDelCost);
- for(k=0; k<f.a[i1].nDel; k++){
- p = f.a[i1].apDel[k];
- updateCost(m, cxp+p->nFrom, cxp, p->iCost);
- }
- updateCost(m, cx, cxu, pLang->iInsCost);
- if( matchFromTo(&f, i1, z2+i2, n2-i2) ){
- updateCost(m, cx, cxd, 0);
- }
- updateCost(m, cx, cxd, pLang->iSubCost);
- for(k=0; k<f.a[i1].nSubst; k++){
- p = f.a[i1].apSubst[k];
- if( matchTo(p, z2+i2, n2-i2) ){
- updateCost(m, cxd+p->nFrom+szRow*p->nTo, cxd, p->iCost);
- }
- }
- }
- }
-
-#if 0 /* Enable for debugging */
- printf(" ^");
- for(i1=0; i1<f.n; i1++) printf(" %c-%2x", f.z[i1], f.z[i1]&0xff);
- printf("\n ^:");
- for(i1=0; i1<szRow; i1++){
- int v = m[i1];
- if( v>9999 ) printf(" ****");
- else printf(" %4d", v);
- }
- printf("\n");
- for(i2=0; i2<n2; i2++){
- printf("%c-%02x:", z2[i2], z2[i2]&0xff);
- for(i1=0; i1<szRow; i1++){
- int v = m[(i2+1)*szRow+i1];
- if( v>9999 ) printf(" ****");
- else printf(" %4d", v);
- }
- printf("\n");
- }
-#endif
-
- /* Free memory allocations and return the result */
- res = (int)m[szRow*(n2+1)-1];
- n = n2;
- if( f.isPrefix ){
- for(i2=1; i2<=n2; i2++){
- int b = m[szRow*i2-1];
- if( b<=res ){
- res = b;
- n = i2 - 1;
- }
- }
- }
- if( pnMatch ){
- int nExtra = 0;
- for(k=0; k<n; k++){
- if( (z2[k] & 0xc0)==0x80 ) nExtra++;
- }
- *pnMatch = n - nExtra;
- }
-
-editDist3Abort:
- for(i2=0; i2<n2; i2++) sqlite3_free(a2[i2].apIns);
- sqlite3_free(pToFree);
- return res;
-}
-
-/*
-** Get an appropriate EditDist3Lang object.
-*/
-static const EditDist3Lang *editDist3FindLang(
- EditDist3Config *pConfig,
- int iLang
-){
- int i;
- for(i=0; i<pConfig->nLang; i++){
- if( pConfig->a[i].iLang==iLang ) return &pConfig->a[i];
- }
- return &editDist3Lang;
-}
-
-/*
-** Function: editdist3(A,B,iLang)
-** editdist3(tablename)
-**
-** Return the cost of transforming string A into string B using edit
-** weights for iLang.
-**
-** The second form loads edit weights into memory from a table.
-*/
-static void editDist3SqlFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- EditDist3Config *pConfig = (EditDist3Config*)sqlite3_user_data(context);
- sqlite3 *db = sqlite3_context_db_handle(context);
- int rc;
- if( argc==1 ){
- const char *zTable = (const char*)sqlite3_value_text(argv[0]);
- rc = editDist3ConfigLoad(pConfig, db, zTable);
- if( rc ) sqlite3_result_error_code(context, rc);
- }else{
- const char *zA = (const char*)sqlite3_value_text(argv[0]);
- const char *zB = (const char*)sqlite3_value_text(argv[1]);
- int nA = sqlite3_value_bytes(argv[0]);
- int nB = sqlite3_value_bytes(argv[1]);
- int iLang = argc==3 ? sqlite3_value_int(argv[2]) : 0;
- const EditDist3Lang *pLang = editDist3FindLang(pConfig, iLang);
- EditDist3FromString *pFrom;
- int dist;
-
- pFrom = editDist3FromStringNew(pLang, zA, nA);
- if( pFrom==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- dist = editDist3Core(pFrom, zB, nB, pLang, 0);
- editDist3FromStringDelete(pFrom);
- if( dist==(-1) ){
- sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_int(context, dist);
- }
- }
-}
-
-/*
-** Register the editDist3 function with SQLite
-*/
-static int editDist3Install(sqlite3 *db){
- int rc;
- EditDist3Config *pConfig = sqlite3_malloc64( sizeof(*pConfig) );
- if( pConfig==0 ) return SQLITE_NOMEM;
- memset(pConfig, 0, sizeof(*pConfig));
- rc = sqlite3_create_function_v2(db, "editdist3",
- 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, pConfig,
- editDist3SqlFunc, 0, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function_v2(db, "editdist3",
- 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, pConfig,
- editDist3SqlFunc, 0, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function_v2(db, "editdist3",
- 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, pConfig,
- editDist3SqlFunc, 0, 0, editDist3ConfigDelete);
- }else{
- sqlite3_free(pConfig);
- }
- return rc;
-}
-/* End configurable cost unicode edit distance routines
-******************************************************************************
-******************************************************************************
-** Begin transliterate unicode-to-ascii implementation
-*/
-
-#if !SQLITE_AMALGAMATION
-/*
-** This lookup table is used to help decode the first byte of
-** a multi-byte UTF8 character.
-*/
-static const unsigned char sqlite3Utf8Trans1[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
-};
-#endif
-
-/*
-** Return the value of the first UTF-8 character in the string.
-*/
-static int utf8Read(const unsigned char *z, int n, int *pSize){
- int c, i;
-
- /* All callers to this routine (in the current implementation)
- ** always have n>0. */
- if( NEVER(n==0) ){
- c = i = 0;
- }else{
- c = z[0];
- i = 1;
- if( c>=0xc0 ){
- c = sqlite3Utf8Trans1[c-0xc0];
- while( i<n && (z[i] & 0xc0)==0x80 ){
- c = (c<<6) + (0x3f & z[i++]);
- }
- }
- }
- *pSize = i;
- return c;
-}
-
-/*
-** Return the number of characters in the utf-8 string in the nIn byte
-** buffer pointed to by zIn.
-*/
-static int utf8Charlen(const char *zIn, int nIn){
- int i;
- int nChar = 0;
- for(i=0; i<nIn; nChar++){
- int sz;
- utf8Read((const unsigned char *)&zIn[i], nIn-i, &sz);
- i += sz;
- }
- return nChar;
-}
-
-typedef struct Transliteration Transliteration;
-struct Transliteration {
- unsigned short int cFrom;
- unsigned char cTo0, cTo1, cTo2, cTo3;
-};
-
-/*
-** Table of translations from unicode characters into ASCII.
-*/
-static const Transliteration translit[] = {
- { 0x00A0, 0x20, 0x00, 0x00, 0x00 }, /*   to */
- { 0x00B5, 0x75, 0x00, 0x00, 0x00 }, /* µ to u */
- { 0x00C0, 0x41, 0x00, 0x00, 0x00 }, /* À to A */
- { 0x00C1, 0x41, 0x00, 0x00, 0x00 }, /* Á to A */
- { 0x00C2, 0x41, 0x00, 0x00, 0x00 }, /* Â to A */
- { 0x00C3, 0x41, 0x00, 0x00, 0x00 }, /* Ã to A */
- { 0x00C4, 0x41, 0x65, 0x00, 0x00 }, /* Ä to Ae */
- { 0x00C5, 0x41, 0x61, 0x00, 0x00 }, /* Å to Aa */
- { 0x00C6, 0x41, 0x45, 0x00, 0x00 }, /* Æ to AE */
- { 0x00C7, 0x43, 0x00, 0x00, 0x00 }, /* Ç to C */
- { 0x00C8, 0x45, 0x00, 0x00, 0x00 }, /* È to E */
- { 0x00C9, 0x45, 0x00, 0x00, 0x00 }, /* É to E */
- { 0x00CA, 0x45, 0x00, 0x00, 0x00 }, /* Ê to E */
- { 0x00CB, 0x45, 0x00, 0x00, 0x00 }, /* Ë to E */
- { 0x00CC, 0x49, 0x00, 0x00, 0x00 }, /* Ì to I */
- { 0x00CD, 0x49, 0x00, 0x00, 0x00 }, /* Í to I */
- { 0x00CE, 0x49, 0x00, 0x00, 0x00 }, /* Î to I */
- { 0x00CF, 0x49, 0x00, 0x00, 0x00 }, /* Ï to I */
- { 0x00D0, 0x44, 0x00, 0x00, 0x00 }, /* Ð to D */
- { 0x00D1, 0x4E, 0x00, 0x00, 0x00 }, /* Ñ to N */
- { 0x00D2, 0x4F, 0x00, 0x00, 0x00 }, /* Ò to O */
- { 0x00D3, 0x4F, 0x00, 0x00, 0x00 }, /* Ó to O */
- { 0x00D4, 0x4F, 0x00, 0x00, 0x00 }, /* Ô to O */
- { 0x00D5, 0x4F, 0x00, 0x00, 0x00 }, /* Õ to O */
- { 0x00D6, 0x4F, 0x65, 0x00, 0x00 }, /* Ö to Oe */
- { 0x00D7, 0x78, 0x00, 0x00, 0x00 }, /* × to x */
- { 0x00D8, 0x4F, 0x00, 0x00, 0x00 }, /* Ø to O */
- { 0x00D9, 0x55, 0x00, 0x00, 0x00 }, /* Ù to U */
- { 0x00DA, 0x55, 0x00, 0x00, 0x00 }, /* Ú to U */
- { 0x00DB, 0x55, 0x00, 0x00, 0x00 }, /* Û to U */
- { 0x00DC, 0x55, 0x65, 0x00, 0x00 }, /* Ü to Ue */
- { 0x00DD, 0x59, 0x00, 0x00, 0x00 }, /* Ý to Y */
- { 0x00DE, 0x54, 0x68, 0x00, 0x00 }, /* Þ to Th */
- { 0x00DF, 0x73, 0x73, 0x00, 0x00 }, /* ß to ss */
- { 0x00E0, 0x61, 0x00, 0x00, 0x00 }, /* à to a */
- { 0x00E1, 0x61, 0x00, 0x00, 0x00 }, /* á to a */
- { 0x00E2, 0x61, 0x00, 0x00, 0x00 }, /* â to a */
- { 0x00E3, 0x61, 0x00, 0x00, 0x00 }, /* ã to a */
- { 0x00E4, 0x61, 0x65, 0x00, 0x00 }, /* ä to ae */
- { 0x00E5, 0x61, 0x61, 0x00, 0x00 }, /* å to aa */
- { 0x00E6, 0x61, 0x65, 0x00, 0x00 }, /* æ to ae */
- { 0x00E7, 0x63, 0x00, 0x00, 0x00 }, /* ç to c */
- { 0x00E8, 0x65, 0x00, 0x00, 0x00 }, /* è to e */
- { 0x00E9, 0x65, 0x00, 0x00, 0x00 }, /* é to e */
- { 0x00EA, 0x65, 0x00, 0x00, 0x00 }, /* ê to e */
- { 0x00EB, 0x65, 0x00, 0x00, 0x00 }, /* ë to e */
- { 0x00EC, 0x69, 0x00, 0x00, 0x00 }, /* ì to i */
- { 0x00ED, 0x69, 0x00, 0x00, 0x00 }, /* í to i */
- { 0x00EE, 0x69, 0x00, 0x00, 0x00 }, /* î to i */
- { 0x00EF, 0x69, 0x00, 0x00, 0x00 }, /* ï to i */
- { 0x00F0, 0x64, 0x00, 0x00, 0x00 }, /* ð to d */
- { 0x00F1, 0x6E, 0x00, 0x00, 0x00 }, /* ñ to n */
- { 0x00F2, 0x6F, 0x00, 0x00, 0x00 }, /* ò to o */
- { 0x00F3, 0x6F, 0x00, 0x00, 0x00 }, /* ó to o */
- { 0x00F4, 0x6F, 0x00, 0x00, 0x00 }, /* ô to o */
- { 0x00F5, 0x6F, 0x00, 0x00, 0x00 }, /* õ to o */
- { 0x00F6, 0x6F, 0x65, 0x00, 0x00 }, /* ö to oe */
- { 0x00F7, 0x3A, 0x00, 0x00, 0x00 }, /* ÷ to : */
- { 0x00F8, 0x6F, 0x00, 0x00, 0x00 }, /* ø to o */
- { 0x00F9, 0x75, 0x00, 0x00, 0x00 }, /* ù to u */
- { 0x00FA, 0x75, 0x00, 0x00, 0x00 }, /* ú to u */
- { 0x00FB, 0x75, 0x00, 0x00, 0x00 }, /* û to u */
- { 0x00FC, 0x75, 0x65, 0x00, 0x00 }, /* ü to ue */
- { 0x00FD, 0x79, 0x00, 0x00, 0x00 }, /* ý to y */
- { 0x00FE, 0x74, 0x68, 0x00, 0x00 }, /* þ to th */
- { 0x00FF, 0x79, 0x00, 0x00, 0x00 }, /* ÿ to y */
- { 0x0100, 0x41, 0x00, 0x00, 0x00 }, /* Ā to A */
- { 0x0101, 0x61, 0x00, 0x00, 0x00 }, /* ā to a */
- { 0x0102, 0x41, 0x00, 0x00, 0x00 }, /* Ă to A */
- { 0x0103, 0x61, 0x00, 0x00, 0x00 }, /* ă to a */
- { 0x0104, 0x41, 0x00, 0x00, 0x00 }, /* Ą to A */
- { 0x0105, 0x61, 0x00, 0x00, 0x00 }, /* ą to a */
- { 0x0106, 0x43, 0x00, 0x00, 0x00 }, /* Ć to C */
- { 0x0107, 0x63, 0x00, 0x00, 0x00 }, /* ć to c */
- { 0x0108, 0x43, 0x68, 0x00, 0x00 }, /* Ĉ to Ch */
- { 0x0109, 0x63, 0x68, 0x00, 0x00 }, /* ĉ to ch */
- { 0x010A, 0x43, 0x00, 0x00, 0x00 }, /* Ċ to C */
- { 0x010B, 0x63, 0x00, 0x00, 0x00 }, /* ċ to c */
- { 0x010C, 0x43, 0x00, 0x00, 0x00 }, /* Č to C */
- { 0x010D, 0x63, 0x00, 0x00, 0x00 }, /* č to c */
- { 0x010E, 0x44, 0x00, 0x00, 0x00 }, /* Ď to D */
- { 0x010F, 0x64, 0x00, 0x00, 0x00 }, /* ď to d */
- { 0x0110, 0x44, 0x00, 0x00, 0x00 }, /* Đ to D */
- { 0x0111, 0x64, 0x00, 0x00, 0x00 }, /* đ to d */
- { 0x0112, 0x45, 0x00, 0x00, 0x00 }, /* Ē to E */
- { 0x0113, 0x65, 0x00, 0x00, 0x00 }, /* ē to e */
- { 0x0114, 0x45, 0x00, 0x00, 0x00 }, /* Ĕ to E */
- { 0x0115, 0x65, 0x00, 0x00, 0x00 }, /* ĕ to e */
- { 0x0116, 0x45, 0x00, 0x00, 0x00 }, /* Ė to E */
- { 0x0117, 0x65, 0x00, 0x00, 0x00 }, /* ė to e */
- { 0x0118, 0x45, 0x00, 0x00, 0x00 }, /* Ę to E */
- { 0x0119, 0x65, 0x00, 0x00, 0x00 }, /* ę to e */
- { 0x011A, 0x45, 0x00, 0x00, 0x00 }, /* Ě to E */
- { 0x011B, 0x65, 0x00, 0x00, 0x00 }, /* ě to e */
- { 0x011C, 0x47, 0x68, 0x00, 0x00 }, /* Ĝ to Gh */
- { 0x011D, 0x67, 0x68, 0x00, 0x00 }, /* ĝ to gh */
- { 0x011E, 0x47, 0x00, 0x00, 0x00 }, /* Ğ to G */
- { 0x011F, 0x67, 0x00, 0x00, 0x00 }, /* ğ to g */
- { 0x0120, 0x47, 0x00, 0x00, 0x00 }, /* Ġ to G */
- { 0x0121, 0x67, 0x00, 0x00, 0x00 }, /* ġ to g */
- { 0x0122, 0x47, 0x00, 0x00, 0x00 }, /* Ģ to G */
- { 0x0123, 0x67, 0x00, 0x00, 0x00 }, /* ģ to g */
- { 0x0124, 0x48, 0x68, 0x00, 0x00 }, /* Ĥ to Hh */
- { 0x0125, 0x68, 0x68, 0x00, 0x00 }, /* ĥ to hh */
- { 0x0126, 0x48, 0x00, 0x00, 0x00 }, /* Ħ to H */
- { 0x0127, 0x68, 0x00, 0x00, 0x00 }, /* ħ to h */
- { 0x0128, 0x49, 0x00, 0x00, 0x00 }, /* Ĩ to I */
- { 0x0129, 0x69, 0x00, 0x00, 0x00 }, /* ĩ to i */
- { 0x012A, 0x49, 0x00, 0x00, 0x00 }, /* Ī to I */
- { 0x012B, 0x69, 0x00, 0x00, 0x00 }, /* ī to i */
- { 0x012C, 0x49, 0x00, 0x00, 0x00 }, /* Ĭ to I */
- { 0x012D, 0x69, 0x00, 0x00, 0x00 }, /* ĭ to i */
- { 0x012E, 0x49, 0x00, 0x00, 0x00 }, /* Į to I */
- { 0x012F, 0x69, 0x00, 0x00, 0x00 }, /* į to i */
- { 0x0130, 0x49, 0x00, 0x00, 0x00 }, /* İ to I */
- { 0x0131, 0x69, 0x00, 0x00, 0x00 }, /* ı to i */
- { 0x0132, 0x49, 0x4A, 0x00, 0x00 }, /* IJ to IJ */
- { 0x0133, 0x69, 0x6A, 0x00, 0x00 }, /* ij to ij */
- { 0x0134, 0x4A, 0x68, 0x00, 0x00 }, /* Ĵ to Jh */
- { 0x0135, 0x6A, 0x68, 0x00, 0x00 }, /* ĵ to jh */
- { 0x0136, 0x4B, 0x00, 0x00, 0x00 }, /* Ķ to K */
- { 0x0137, 0x6B, 0x00, 0x00, 0x00 }, /* ķ to k */
- { 0x0138, 0x6B, 0x00, 0x00, 0x00 }, /* ĸ to k */
- { 0x0139, 0x4C, 0x00, 0x00, 0x00 }, /* Ĺ to L */
- { 0x013A, 0x6C, 0x00, 0x00, 0x00 }, /* ĺ to l */
- { 0x013B, 0x4C, 0x00, 0x00, 0x00 }, /* Ļ to L */
- { 0x013C, 0x6C, 0x00, 0x00, 0x00 }, /* ļ to l */
- { 0x013D, 0x4C, 0x00, 0x00, 0x00 }, /* Ľ to L */
- { 0x013E, 0x6C, 0x00, 0x00, 0x00 }, /* ľ to l */
- { 0x013F, 0x4C, 0x2E, 0x00, 0x00 }, /* Ŀ to L. */
- { 0x0140, 0x6C, 0x2E, 0x00, 0x00 }, /* ŀ to l. */
- { 0x0141, 0x4C, 0x00, 0x00, 0x00 }, /* Ł to L */
- { 0x0142, 0x6C, 0x00, 0x00, 0x00 }, /* ł to l */
- { 0x0143, 0x4E, 0x00, 0x00, 0x00 }, /* Ń to N */
- { 0x0144, 0x6E, 0x00, 0x00, 0x00 }, /* ń to n */
- { 0x0145, 0x4E, 0x00, 0x00, 0x00 }, /* Ņ to N */
- { 0x0146, 0x6E, 0x00, 0x00, 0x00 }, /* ņ to n */
- { 0x0147, 0x4E, 0x00, 0x00, 0x00 }, /* Ň to N */
- { 0x0148, 0x6E, 0x00, 0x00, 0x00 }, /* ň to n */
- { 0x0149, 0x27, 0x6E, 0x00, 0x00 }, /* ʼn to 'n */
- { 0x014A, 0x4E, 0x47, 0x00, 0x00 }, /* Ŋ to NG */
- { 0x014B, 0x6E, 0x67, 0x00, 0x00 }, /* ŋ to ng */
- { 0x014C, 0x4F, 0x00, 0x00, 0x00 }, /* Ō to O */
- { 0x014D, 0x6F, 0x00, 0x00, 0x00 }, /* ō to o */
- { 0x014E, 0x4F, 0x00, 0x00, 0x00 }, /* Ŏ to O */
- { 0x014F, 0x6F, 0x00, 0x00, 0x00 }, /* ŏ to o */
- { 0x0150, 0x4F, 0x00, 0x00, 0x00 }, /* Ő to O */
- { 0x0151, 0x6F, 0x00, 0x00, 0x00 }, /* ő to o */
- { 0x0152, 0x4F, 0x45, 0x00, 0x00 }, /* Πto OE */
- { 0x0153, 0x6F, 0x65, 0x00, 0x00 }, /* œ to oe */
- { 0x0154, 0x52, 0x00, 0x00, 0x00 }, /* Ŕ to R */
- { 0x0155, 0x72, 0x00, 0x00, 0x00 }, /* ŕ to r */
- { 0x0156, 0x52, 0x00, 0x00, 0x00 }, /* Ŗ to R */
- { 0x0157, 0x72, 0x00, 0x00, 0x00 }, /* ŗ to r */
- { 0x0158, 0x52, 0x00, 0x00, 0x00 }, /* Ř to R */
- { 0x0159, 0x72, 0x00, 0x00, 0x00 }, /* ř to r */
- { 0x015A, 0x53, 0x00, 0x00, 0x00 }, /* Ś to S */
- { 0x015B, 0x73, 0x00, 0x00, 0x00 }, /* ś to s */
- { 0x015C, 0x53, 0x68, 0x00, 0x00 }, /* Ŝ to Sh */
- { 0x015D, 0x73, 0x68, 0x00, 0x00 }, /* ŝ to sh */
- { 0x015E, 0x53, 0x00, 0x00, 0x00 }, /* Ş to S */
- { 0x015F, 0x73, 0x00, 0x00, 0x00 }, /* ş to s */
- { 0x0160, 0x53, 0x00, 0x00, 0x00 }, /* Š to S */
- { 0x0161, 0x73, 0x00, 0x00, 0x00 }, /* š to s */
- { 0x0162, 0x54, 0x00, 0x00, 0x00 }, /* Ţ to T */
- { 0x0163, 0x74, 0x00, 0x00, 0x00 }, /* ţ to t */
- { 0x0164, 0x54, 0x00, 0x00, 0x00 }, /* Ť to T */
- { 0x0165, 0x74, 0x00, 0x00, 0x00 }, /* ť to t */
- { 0x0166, 0x54, 0x00, 0x00, 0x00 }, /* Ŧ to T */
- { 0x0167, 0x74, 0x00, 0x00, 0x00 }, /* ŧ to t */
- { 0x0168, 0x55, 0x00, 0x00, 0x00 }, /* Ũ to U */
- { 0x0169, 0x75, 0x00, 0x00, 0x00 }, /* ũ to u */
- { 0x016A, 0x55, 0x00, 0x00, 0x00 }, /* Ū to U */
- { 0x016B, 0x75, 0x00, 0x00, 0x00 }, /* ū to u */
- { 0x016C, 0x55, 0x00, 0x00, 0x00 }, /* Ŭ to U */
- { 0x016D, 0x75, 0x00, 0x00, 0x00 }, /* ŭ to u */
- { 0x016E, 0x55, 0x00, 0x00, 0x00 }, /* Ů to U */
- { 0x016F, 0x75, 0x00, 0x00, 0x00 }, /* ů to u */
- { 0x0170, 0x55, 0x00, 0x00, 0x00 }, /* Ű to U */
- { 0x0171, 0x75, 0x00, 0x00, 0x00 }, /* ű to u */
- { 0x0172, 0x55, 0x00, 0x00, 0x00 }, /* Ų to U */
- { 0x0173, 0x75, 0x00, 0x00, 0x00 }, /* ų to u */
- { 0x0174, 0x57, 0x00, 0x00, 0x00 }, /* Ŵ to W */
- { 0x0175, 0x77, 0x00, 0x00, 0x00 }, /* ŵ to w */
- { 0x0176, 0x59, 0x00, 0x00, 0x00 }, /* Ŷ to Y */
- { 0x0177, 0x79, 0x00, 0x00, 0x00 }, /* ŷ to y */
- { 0x0178, 0x59, 0x00, 0x00, 0x00 }, /* Ÿ to Y */
- { 0x0179, 0x5A, 0x00, 0x00, 0x00 }, /* Ź to Z */
- { 0x017A, 0x7A, 0x00, 0x00, 0x00 }, /* ź to z */
- { 0x017B, 0x5A, 0x00, 0x00, 0x00 }, /* Ż to Z */
- { 0x017C, 0x7A, 0x00, 0x00, 0x00 }, /* ż to z */
- { 0x017D, 0x5A, 0x00, 0x00, 0x00 }, /* Ž to Z */
- { 0x017E, 0x7A, 0x00, 0x00, 0x00 }, /* ž to z */
- { 0x017F, 0x73, 0x00, 0x00, 0x00 }, /* ſ to s */
- { 0x0192, 0x66, 0x00, 0x00, 0x00 }, /* ƒ to f */
- { 0x0218, 0x53, 0x00, 0x00, 0x00 }, /* Ș to S */
- { 0x0219, 0x73, 0x00, 0x00, 0x00 }, /* ș to s */
- { 0x021A, 0x54, 0x00, 0x00, 0x00 }, /* Ț to T */
- { 0x021B, 0x74, 0x00, 0x00, 0x00 }, /* ț to t */
- { 0x0386, 0x41, 0x00, 0x00, 0x00 }, /* Ά to A */
- { 0x0388, 0x45, 0x00, 0x00, 0x00 }, /* Έ to E */
- { 0x0389, 0x49, 0x00, 0x00, 0x00 }, /* Ή to I */
- { 0x038A, 0x49, 0x00, 0x00, 0x00 }, /* Ί to I */
- { 0x038C, 0x4f, 0x00, 0x00, 0x00 }, /* Ό to O */
- { 0x038E, 0x59, 0x00, 0x00, 0x00 }, /* Ύ to Y */
- { 0x038F, 0x4f, 0x00, 0x00, 0x00 }, /* Ώ to O */
- { 0x0390, 0x69, 0x00, 0x00, 0x00 }, /* ΐ to i */
- { 0x0391, 0x41, 0x00, 0x00, 0x00 }, /* Α to A */
- { 0x0392, 0x42, 0x00, 0x00, 0x00 }, /* Β to B */
- { 0x0393, 0x47, 0x00, 0x00, 0x00 }, /* Γ to G */
- { 0x0394, 0x44, 0x00, 0x00, 0x00 }, /* Δ to D */
- { 0x0395, 0x45, 0x00, 0x00, 0x00 }, /* Ε to E */
- { 0x0396, 0x5a, 0x00, 0x00, 0x00 }, /* Ζ to Z */
- { 0x0397, 0x49, 0x00, 0x00, 0x00 }, /* Η to I */
- { 0x0398, 0x54, 0x68, 0x00, 0x00 }, /* Θ to Th */
- { 0x0399, 0x49, 0x00, 0x00, 0x00 }, /* Ι to I */
- { 0x039A, 0x4b, 0x00, 0x00, 0x00 }, /* Κ to K */
- { 0x039B, 0x4c, 0x00, 0x00, 0x00 }, /* Λ to L */
- { 0x039C, 0x4d, 0x00, 0x00, 0x00 }, /* Μ to M */
- { 0x039D, 0x4e, 0x00, 0x00, 0x00 }, /* Ν to N */
- { 0x039E, 0x58, 0x00, 0x00, 0x00 }, /* Ξ to X */
- { 0x039F, 0x4f, 0x00, 0x00, 0x00 }, /* Ο to O */
- { 0x03A0, 0x50, 0x00, 0x00, 0x00 }, /* Π to P */
- { 0x03A1, 0x52, 0x00, 0x00, 0x00 }, /* Ρ to R */
- { 0x03A3, 0x53, 0x00, 0x00, 0x00 }, /* Σ to S */
- { 0x03A4, 0x54, 0x00, 0x00, 0x00 }, /* Τ to T */
- { 0x03A5, 0x59, 0x00, 0x00, 0x00 }, /* Υ to Y */
- { 0x03A6, 0x46, 0x00, 0x00, 0x00 }, /* Φ to F */
- { 0x03A7, 0x43, 0x68, 0x00, 0x00 }, /* Χ to Ch */
- { 0x03A8, 0x50, 0x73, 0x00, 0x00 }, /* Ψ to Ps */
- { 0x03A9, 0x4f, 0x00, 0x00, 0x00 }, /* Ω to O */
- { 0x03AA, 0x49, 0x00, 0x00, 0x00 }, /* Ϊ to I */
- { 0x03AB, 0x59, 0x00, 0x00, 0x00 }, /* Ϋ to Y */
- { 0x03AC, 0x61, 0x00, 0x00, 0x00 }, /* ά to a */
- { 0x03AD, 0x65, 0x00, 0x00, 0x00 }, /* έ to e */
- { 0x03AE, 0x69, 0x00, 0x00, 0x00 }, /* ή to i */
- { 0x03AF, 0x69, 0x00, 0x00, 0x00 }, /* ί to i */
- { 0x03B1, 0x61, 0x00, 0x00, 0x00 }, /* α to a */
- { 0x03B2, 0x62, 0x00, 0x00, 0x00 }, /* β to b */
- { 0x03B3, 0x67, 0x00, 0x00, 0x00 }, /* γ to g */
- { 0x03B4, 0x64, 0x00, 0x00, 0x00 }, /* δ to d */
- { 0x03B5, 0x65, 0x00, 0x00, 0x00 }, /* ε to e */
- { 0x03B6, 0x7a, 0x00, 0x00, 0x00 }, /* ζ to z */
- { 0x03B7, 0x69, 0x00, 0x00, 0x00 }, /* η to i */
- { 0x03B8, 0x74, 0x68, 0x00, 0x00 }, /* θ to th */
- { 0x03B9, 0x69, 0x00, 0x00, 0x00 }, /* ι to i */
- { 0x03BA, 0x6b, 0x00, 0x00, 0x00 }, /* κ to k */
- { 0x03BB, 0x6c, 0x00, 0x00, 0x00 }, /* λ to l */
- { 0x03BC, 0x6d, 0x00, 0x00, 0x00 }, /* μ to m */
- { 0x03BD, 0x6e, 0x00, 0x00, 0x00 }, /* ν to n */
- { 0x03BE, 0x78, 0x00, 0x00, 0x00 }, /* ξ to x */
- { 0x03BF, 0x6f, 0x00, 0x00, 0x00 }, /* ο to o */
- { 0x03C0, 0x70, 0x00, 0x00, 0x00 }, /* π to p */
- { 0x03C1, 0x72, 0x00, 0x00, 0x00 }, /* ρ to r */
- { 0x03C3, 0x73, 0x00, 0x00, 0x00 }, /* σ to s */
- { 0x03C4, 0x74, 0x00, 0x00, 0x00 }, /* τ to t */
- { 0x03C5, 0x79, 0x00, 0x00, 0x00 }, /* υ to y */
- { 0x03C6, 0x66, 0x00, 0x00, 0x00 }, /* φ to f */
- { 0x03C7, 0x63, 0x68, 0x00, 0x00 }, /* χ to ch */
- { 0x03C8, 0x70, 0x73, 0x00, 0x00 }, /* ψ to ps */
- { 0x03C9, 0x6f, 0x00, 0x00, 0x00 }, /* ω to o */
- { 0x03CA, 0x69, 0x00, 0x00, 0x00 }, /* ϊ to i */
- { 0x03CB, 0x79, 0x00, 0x00, 0x00 }, /* ϋ to y */
- { 0x03CC, 0x6f, 0x00, 0x00, 0x00 }, /* ό to o */
- { 0x03CD, 0x79, 0x00, 0x00, 0x00 }, /* ύ to y */
- { 0x03CE, 0x69, 0x00, 0x00, 0x00 }, /* ώ to i */
- { 0x0400, 0x45, 0x00, 0x00, 0x00 }, /* Ѐ to E */
- { 0x0401, 0x45, 0x00, 0x00, 0x00 }, /* Ё to E */
- { 0x0402, 0x44, 0x00, 0x00, 0x00 }, /* Ђ to D */
- { 0x0403, 0x47, 0x00, 0x00, 0x00 }, /* Ѓ to G */
- { 0x0404, 0x45, 0x00, 0x00, 0x00 }, /* Є to E */
- { 0x0405, 0x5a, 0x00, 0x00, 0x00 }, /* Ѕ to Z */
- { 0x0406, 0x49, 0x00, 0x00, 0x00 }, /* І to I */
- { 0x0407, 0x49, 0x00, 0x00, 0x00 }, /* Ї to I */
- { 0x0408, 0x4a, 0x00, 0x00, 0x00 }, /* Ј to J */
- { 0x0409, 0x49, 0x00, 0x00, 0x00 }, /* Љ to I */
- { 0x040A, 0x4e, 0x00, 0x00, 0x00 }, /* Њ to N */
- { 0x040B, 0x44, 0x00, 0x00, 0x00 }, /* Ћ to D */
- { 0x040C, 0x4b, 0x00, 0x00, 0x00 }, /* Ќ to K */
- { 0x040D, 0x49, 0x00, 0x00, 0x00 }, /* Ѝ to I */
- { 0x040E, 0x55, 0x00, 0x00, 0x00 }, /* Ў to U */
- { 0x040F, 0x44, 0x00, 0x00, 0x00 }, /* Џ to D */
- { 0x0410, 0x41, 0x00, 0x00, 0x00 }, /* А to A */
- { 0x0411, 0x42, 0x00, 0x00, 0x00 }, /* Б to B */
- { 0x0412, 0x56, 0x00, 0x00, 0x00 }, /* В to V */
- { 0x0413, 0x47, 0x00, 0x00, 0x00 }, /* Г to G */
- { 0x0414, 0x44, 0x00, 0x00, 0x00 }, /* Д to D */
- { 0x0415, 0x45, 0x00, 0x00, 0x00 }, /* Е to E */
- { 0x0416, 0x5a, 0x68, 0x00, 0x00 }, /* Ж to Zh */
- { 0x0417, 0x5a, 0x00, 0x00, 0x00 }, /* З to Z */
- { 0x0418, 0x49, 0x00, 0x00, 0x00 }, /* И to I */
- { 0x0419, 0x49, 0x00, 0x00, 0x00 }, /* Й to I */
- { 0x041A, 0x4b, 0x00, 0x00, 0x00 }, /* К to K */
- { 0x041B, 0x4c, 0x00, 0x00, 0x00 }, /* Л to L */
- { 0x041C, 0x4d, 0x00, 0x00, 0x00 }, /* М to M */
- { 0x041D, 0x4e, 0x00, 0x00, 0x00 }, /* Н to N */
- { 0x041E, 0x4f, 0x00, 0x00, 0x00 }, /* О to O */
- { 0x041F, 0x50, 0x00, 0x00, 0x00 }, /* П to P */
- { 0x0420, 0x52, 0x00, 0x00, 0x00 }, /* Р to R */
- { 0x0421, 0x53, 0x00, 0x00, 0x00 }, /* С to S */
- { 0x0422, 0x54, 0x00, 0x00, 0x00 }, /* Т to T */
- { 0x0423, 0x55, 0x00, 0x00, 0x00 }, /* У to U */
- { 0x0424, 0x46, 0x00, 0x00, 0x00 }, /* Ф to F */
- { 0x0425, 0x4b, 0x68, 0x00, 0x00 }, /* Х to Kh */
- { 0x0426, 0x54, 0x63, 0x00, 0x00 }, /* Ц to Tc */
- { 0x0427, 0x43, 0x68, 0x00, 0x00 }, /* Ч to Ch */
- { 0x0428, 0x53, 0x68, 0x00, 0x00 }, /* Ш to Sh */
- { 0x0429, 0x53, 0x68, 0x63, 0x68 }, /* Щ to Shch */
- { 0x042A, 0x61, 0x00, 0x00, 0x00 }, /* to A */
- { 0x042B, 0x59, 0x00, 0x00, 0x00 }, /* Ы to Y */
- { 0x042C, 0x59, 0x00, 0x00, 0x00 }, /* to Y */
- { 0x042D, 0x45, 0x00, 0x00, 0x00 }, /* Э to E */
- { 0x042E, 0x49, 0x75, 0x00, 0x00 }, /* Ю to Iu */
- { 0x042F, 0x49, 0x61, 0x00, 0x00 }, /* Я to Ia */
- { 0x0430, 0x61, 0x00, 0x00, 0x00 }, /* а to a */
- { 0x0431, 0x62, 0x00, 0x00, 0x00 }, /* б to b */
- { 0x0432, 0x76, 0x00, 0x00, 0x00 }, /* в to v */
- { 0x0433, 0x67, 0x00, 0x00, 0x00 }, /* г to g */
- { 0x0434, 0x64, 0x00, 0x00, 0x00 }, /* д to d */
- { 0x0435, 0x65, 0x00, 0x00, 0x00 }, /* е to e */
- { 0x0436, 0x7a, 0x68, 0x00, 0x00 }, /* ж to zh */
- { 0x0437, 0x7a, 0x00, 0x00, 0x00 }, /* з to z */
- { 0x0438, 0x69, 0x00, 0x00, 0x00 }, /* и to i */
- { 0x0439, 0x69, 0x00, 0x00, 0x00 }, /* й to i */
- { 0x043A, 0x6b, 0x00, 0x00, 0x00 }, /* к to k */
- { 0x043B, 0x6c, 0x00, 0x00, 0x00 }, /* л to l */
- { 0x043C, 0x6d, 0x00, 0x00, 0x00 }, /* м to m */
- { 0x043D, 0x6e, 0x00, 0x00, 0x00 }, /* н to n */
- { 0x043E, 0x6f, 0x00, 0x00, 0x00 }, /* о to o */
- { 0x043F, 0x70, 0x00, 0x00, 0x00 }, /* п to p */
- { 0x0440, 0x72, 0x00, 0x00, 0x00 }, /* р to r */
- { 0x0441, 0x73, 0x00, 0x00, 0x00 }, /* с to s */
- { 0x0442, 0x74, 0x00, 0x00, 0x00 }, /* т to t */
- { 0x0443, 0x75, 0x00, 0x00, 0x00 }, /* у to u */
- { 0x0444, 0x66, 0x00, 0x00, 0x00 }, /* ф to f */
- { 0x0445, 0x6b, 0x68, 0x00, 0x00 }, /* х to kh */
- { 0x0446, 0x74, 0x63, 0x00, 0x00 }, /* ц to tc */
- { 0x0447, 0x63, 0x68, 0x00, 0x00 }, /* ч to ch */
- { 0x0448, 0x73, 0x68, 0x00, 0x00 }, /* ш to sh */
- { 0x0449, 0x73, 0x68, 0x63, 0x68 }, /* щ to shch */
- { 0x044A, 0x61, 0x00, 0x00, 0x00 }, /* to a */
- { 0x044B, 0x79, 0x00, 0x00, 0x00 }, /* ы to y */
- { 0x044C, 0x79, 0x00, 0x00, 0x00 }, /* to y */
- { 0x044D, 0x65, 0x00, 0x00, 0x00 }, /* э to e */
- { 0x044E, 0x69, 0x75, 0x00, 0x00 }, /* ю to iu */
- { 0x044F, 0x69, 0x61, 0x00, 0x00 }, /* я to ia */
- { 0x0450, 0x65, 0x00, 0x00, 0x00 }, /* ѐ to e */
- { 0x0451, 0x65, 0x00, 0x00, 0x00 }, /* ё to e */
- { 0x0452, 0x64, 0x00, 0x00, 0x00 }, /* ђ to d */
- { 0x0453, 0x67, 0x00, 0x00, 0x00 }, /* ѓ to g */
- { 0x0454, 0x65, 0x00, 0x00, 0x00 }, /* є to e */
- { 0x0455, 0x7a, 0x00, 0x00, 0x00 }, /* ѕ to z */
- { 0x0456, 0x69, 0x00, 0x00, 0x00 }, /* і to i */
- { 0x0457, 0x69, 0x00, 0x00, 0x00 }, /* ї to i */
- { 0x0458, 0x6a, 0x00, 0x00, 0x00 }, /* ј to j */
- { 0x0459, 0x69, 0x00, 0x00, 0x00 }, /* љ to i */
- { 0x045A, 0x6e, 0x00, 0x00, 0x00 }, /* њ to n */
- { 0x045B, 0x64, 0x00, 0x00, 0x00 }, /* ћ to d */
- { 0x045C, 0x6b, 0x00, 0x00, 0x00 }, /* ќ to k */
- { 0x045D, 0x69, 0x00, 0x00, 0x00 }, /* ѝ to i */
- { 0x045E, 0x75, 0x00, 0x00, 0x00 }, /* ў to u */
- { 0x045F, 0x64, 0x00, 0x00, 0x00 }, /* џ to d */
- { 0x1E02, 0x42, 0x00, 0x00, 0x00 }, /* Ḃ to B */
- { 0x1E03, 0x62, 0x00, 0x00, 0x00 }, /* ḃ to b */
- { 0x1E0A, 0x44, 0x00, 0x00, 0x00 }, /* Ḋ to D */
- { 0x1E0B, 0x64, 0x00, 0x00, 0x00 }, /* ḋ to d */
- { 0x1E1E, 0x46, 0x00, 0x00, 0x00 }, /* Ḟ to F */
- { 0x1E1F, 0x66, 0x00, 0x00, 0x00 }, /* ḟ to f */
- { 0x1E40, 0x4D, 0x00, 0x00, 0x00 }, /* Ṁ to M */
- { 0x1E41, 0x6D, 0x00, 0x00, 0x00 }, /* ṁ to m */
- { 0x1E56, 0x50, 0x00, 0x00, 0x00 }, /* Ṗ to P */
- { 0x1E57, 0x70, 0x00, 0x00, 0x00 }, /* ṗ to p */
- { 0x1E60, 0x53, 0x00, 0x00, 0x00 }, /* Ṡ to S */
- { 0x1E61, 0x73, 0x00, 0x00, 0x00 }, /* ṡ to s */
- { 0x1E6A, 0x54, 0x00, 0x00, 0x00 }, /* Ṫ to T */
- { 0x1E6B, 0x74, 0x00, 0x00, 0x00 }, /* ṫ to t */
- { 0x1E80, 0x57, 0x00, 0x00, 0x00 }, /* Ẁ to W */
- { 0x1E81, 0x77, 0x00, 0x00, 0x00 }, /* ẁ to w */
- { 0x1E82, 0x57, 0x00, 0x00, 0x00 }, /* Ẃ to W */
- { 0x1E83, 0x77, 0x00, 0x00, 0x00 }, /* ẃ to w */
- { 0x1E84, 0x57, 0x00, 0x00, 0x00 }, /* Ẅ to W */
- { 0x1E85, 0x77, 0x00, 0x00, 0x00 }, /* ẅ to w */
- { 0x1EF2, 0x59, 0x00, 0x00, 0x00 }, /* Ỳ to Y */
- { 0x1EF3, 0x79, 0x00, 0x00, 0x00 }, /* ỳ to y */
- { 0xFB00, 0x66, 0x66, 0x00, 0x00 }, /* ff to ff */
- { 0xFB01, 0x66, 0x69, 0x00, 0x00 }, /* fi to fi */
- { 0xFB02, 0x66, 0x6C, 0x00, 0x00 }, /* fl to fl */
- { 0xFB05, 0x73, 0x74, 0x00, 0x00 }, /* ſt to st */
- { 0xFB06, 0x73, 0x74, 0x00, 0x00 }, /* st to st */
-};
-
-static const Transliteration *spellfixFindTranslit(int c, int *pxTop){
- *pxTop = (sizeof(translit)/sizeof(translit[0])) - 1;
- return translit;
-}
-
-/*
-** Convert the input string from UTF-8 into pure ASCII by converting
-** all non-ASCII characters to some combination of characters in the
-** ASCII subset.
-**
-** The returned string might contain more characters than the input.
-**
-** Space to hold the returned string comes from sqlite3_malloc() and
-** should be freed by the caller.
-*/
-static unsigned char *transliterate(const unsigned char *zIn, int nIn){
- unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 );
- int c, sz, nOut;
- if( zOut==0 ) return 0;
- nOut = 0;
- while( nIn>0 ){
- c = utf8Read(zIn, nIn, &sz);
- zIn += sz;
- nIn -= sz;
- if( c<=127 ){
- zOut[nOut++] = (unsigned char)c;
- }else{
- int xTop, xBtm, x;
- const Transliteration *tbl = spellfixFindTranslit(c, &xTop);
- xBtm = 0;
- while( xTop>=xBtm ){
- x = (xTop + xBtm)/2;
- if( tbl[x].cFrom==c ){
- zOut[nOut++] = tbl[x].cTo0;
- if( tbl[x].cTo1 ){
- zOut[nOut++] = tbl[x].cTo1;
- if( tbl[x].cTo2 ){
- zOut[nOut++] = tbl[x].cTo2;
- if( tbl[x].cTo3 ){
- zOut[nOut++] = tbl[x].cTo3;
- }
- }
- }
- c = 0;
- break;
- }else if( tbl[x].cFrom>c ){
- xTop = x-1;
- }else{
- xBtm = x+1;
- }
- }
- if( c ) zOut[nOut++] = '?';
- }
- }
- zOut[nOut] = 0;
- return zOut;
-}
-
-/*
-** Return the number of characters in the shortest prefix of the input
-** string that transliterates to an ASCII string nTrans bytes or longer.
-** Or, if the transliteration of the input string is less than nTrans
-** bytes in size, return the number of characters in the input string.
-*/
-static int translen_to_charlen(const char *zIn, int nIn, int nTrans){
- int i, c, sz, nOut;
- int nChar;
-
- i = nOut = 0;
- for(nChar=0; i<nIn && nOut<nTrans; nChar++){
- c = utf8Read((const unsigned char *)&zIn[i], nIn-i, &sz);
- i += sz;
-
- nOut++;
- if( c>=128 ){
- int xTop, xBtm, x;
- const Transliteration *tbl = spellfixFindTranslit(c, &xTop);
- xBtm = 0;
- while( xTop>=xBtm ){
- x = (xTop + xBtm)/2;
- if( tbl[x].cFrom==c ){
- if( tbl[x].cTo1 ){
- nOut++;
- if( tbl[x].cTo2 ){
- nOut++;
- if( tbl[x].cTo3 ){
- nOut++;
- }
- }
- }
- break;
- }else if( tbl[x].cFrom>c ){
- xTop = x-1;
- }else{
- xBtm = x+1;
- }
- }
- }
- }
-
- return nChar;
-}
-
-
-/*
-** spellfix1_translit(X)
-**
-** Convert a string that contains non-ASCII Roman characters into
-** pure ASCII.
-*/
-static void transliterateSqlFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zIn = sqlite3_value_text(argv[0]);
- int nIn = sqlite3_value_bytes(argv[0]);
- unsigned char *zOut = transliterate(zIn, nIn);
- if( zOut==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_text(context, (char*)zOut, -1, sqlite3_free);
- }
-}
-
-/*
-** spellfix1_scriptcode(X)
-**
-** Try to determine the dominant script used by the word X and return
-** its ISO 15924 numeric code.
-**
-** The current implementation only understands the following scripts:
-**
-** 215 (Latin)
-** 220 (Cyrillic)
-** 200 (Greek)
-**
-** This routine will return 998 if the input X contains characters from
-** two or more of the above scripts or 999 if X contains no characters
-** from any of the above scripts.
-*/
-static void scriptCodeSqlFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zIn = sqlite3_value_text(argv[0]);
- int nIn = sqlite3_value_bytes(argv[0]);
- int c, sz;
- int scriptMask = 0;
- int res;
- int seenDigit = 0;
-# define SCRIPT_LATIN 0x0001
-# define SCRIPT_CYRILLIC 0x0002
-# define SCRIPT_GREEK 0x0004
-# define SCRIPT_HEBREW 0x0008
-# define SCRIPT_ARABIC 0x0010
-
- while( nIn>0 ){
- c = utf8Read(zIn, nIn, &sz);
- zIn += sz;
- nIn -= sz;
- if( c<0x02af ){
- if( c>=0x80 || midClass[c&0x7f]<CCLASS_DIGIT ){
- scriptMask |= SCRIPT_LATIN;
- }else if( c>='0' && c<='9' ){
- seenDigit = 1;
- }
- }else if( c>=0x0400 && c<=0x04ff ){
- scriptMask |= SCRIPT_CYRILLIC;
- }else if( c>=0x0386 && c<=0x03ce ){
- scriptMask |= SCRIPT_GREEK;
- }else if( c>=0x0590 && c<=0x05ff ){
- scriptMask |= SCRIPT_HEBREW;
- }else if( c>=0x0600 && c<=0x06ff ){
- scriptMask |= SCRIPT_ARABIC;
- }
- }
- if( scriptMask==0 && seenDigit ) scriptMask = SCRIPT_LATIN;
- switch( scriptMask ){
- case 0: res = 999; break;
- case SCRIPT_LATIN: res = 215; break;
- case SCRIPT_CYRILLIC: res = 220; break;
- case SCRIPT_GREEK: res = 200; break;
- case SCRIPT_HEBREW: res = 125; break;
- case SCRIPT_ARABIC: res = 160; break;
- default: res = 998; break;
- }
- sqlite3_result_int(context, res);
-}
-
-/* End transliterate
-******************************************************************************
-******************************************************************************
-** Begin spellfix1 virtual table.
-*/
-
-/* Maximum length of a phonehash used for querying the shadow table */
-#define SPELLFIX_MX_HASH 32
-
-/* Maximum number of hash strings to examine per query */
-#define SPELLFIX_MX_RUN 1
-
-typedef struct spellfix1_vtab spellfix1_vtab;
-typedef struct spellfix1_cursor spellfix1_cursor;
-
-/* Fuzzy-search virtual table object */
-struct spellfix1_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- sqlite3 *db; /* Database connection */
- char *zDbName; /* Name of database holding this table */
- char *zTableName; /* Name of the virtual table */
- char *zCostTable; /* Table holding edit-distance cost numbers */
- EditDist3Config *pConfig3; /* Parsed edit distance costs */
-};
-
-/* Fuzzy-search cursor object */
-struct spellfix1_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- spellfix1_vtab *pVTab; /* The table to which this cursor belongs */
- char *zPattern; /* rhs of MATCH clause */
- int idxNum; /* idxNum value passed to xFilter() */
- int nRow; /* Number of rows of content */
- int nAlloc; /* Number of allocated rows */
- int iRow; /* Current row of content */
- int iLang; /* Value of the langid= constraint */
- int iTop; /* Value of the top= constraint */
- int iScope; /* Value of the scope= constraint */
- int nSearch; /* Number of vocabulary items checked */
- sqlite3_stmt *pFullScan; /* Shadow query for a full table scan */
- struct spellfix1_row { /* For each row of content */
- sqlite3_int64 iRowid; /* Rowid for this row */
- char *zWord; /* Text for this row */
- int iRank; /* Rank for this row */
- int iDistance; /* Distance from pattern for this row */
- int iScore; /* Score for sorting */
- int iMatchlen; /* Value of matchlen column (or -1) */
- char zHash[SPELLFIX_MX_HASH]; /* the phonehash used for this match */
- } *a;
-};
-
-/*
-** Construct one or more SQL statements from the format string given
-** and then evaluate those statements. The success code is written
-** into *pRc.
-**
-** If *pRc is initially non-zero then this routine is a no-op.
-*/
-static void spellfix1DbExec(
- int *pRc, /* Success code */
- sqlite3 *db, /* Database in which to run SQL */
- const char *zFormat, /* Format string for SQL */
- ... /* Arguments to the format string */
-){
- va_list ap;
- char *zSql;
- if( *pRc ) return;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- if( zSql==0 ){
- *pRc = SQLITE_NOMEM;
- }else{
- *pRc = sqlite3_exec(db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
-}
-
-/*
-** xDisconnect/xDestroy method for the fuzzy-search module.
-*/
-static int spellfix1Uninit(int isDestroy, sqlite3_vtab *pVTab){
- spellfix1_vtab *p = (spellfix1_vtab*)pVTab;
- int rc = SQLITE_OK;
- if( isDestroy ){
- sqlite3 *db = p->db;
- spellfix1DbExec(&rc, db, "DROP TABLE IF EXISTS \"%w\".\"%w_vocab\"",
- p->zDbName, p->zTableName);
- }
- if( rc==SQLITE_OK ){
- sqlite3_free(p->zTableName);
- editDist3ConfigDelete(p->pConfig3);
- sqlite3_free(p->zCostTable);
- sqlite3_free(p);
- }
- return rc;
-}
-static int spellfix1Disconnect(sqlite3_vtab *pVTab){
- return spellfix1Uninit(0, pVTab);
-}
-static int spellfix1Destroy(sqlite3_vtab *pVTab){
- return spellfix1Uninit(1, pVTab);
-}
-
-/*
-** Make a copy of a string. Remove leading and trailing whitespace
-** and dequote it.
-*/
-static char *spellfix1Dequote(const char *zIn){
- char *zOut;
- int i, j;
- char c;
- while( isspace((unsigned char)zIn[0]) ) zIn++;
- zOut = sqlite3_mprintf("%s", zIn);
- if( zOut==0 ) return 0;
- i = (int)strlen(zOut);
-#if 0 /* The parser will never leave spaces at the end */
- while( i>0 && isspace(zOut[i-1]) ){ i--; }
-#endif
- zOut[i] = 0;
- c = zOut[0];
- if( c=='\'' || c=='"' ){
- for(i=1, j=0; ALWAYS(zOut[i]); i++){
- zOut[j++] = zOut[i];
- if( zOut[i]==c ){
- if( zOut[i+1]==c ){
- i++;
- }else{
- zOut[j-1] = 0;
- break;
- }
- }
- }
- }
- return zOut;
-}
-
-
-/*
-** xConnect/xCreate method for the spellfix1 module. Arguments are:
-**
-** argv[0] -> module name ("spellfix1")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[3].. -> optional arguments (i.e. "edit_cost_table" parameter)
-*/
-static int spellfix1Init(
- int isCreate,
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab,
- char **pzErr
-){
- spellfix1_vtab *pNew = 0;
- /* const char *zModule = argv[0]; // not used */
- const char *zDbName = argv[1];
- const char *zTableName = argv[2];
- int nDbName;
- int rc = SQLITE_OK;
- int i;
-
- nDbName = (int)strlen(zDbName);
- pNew = sqlite3_malloc64( sizeof(*pNew) + nDbName + 1);
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pNew, 0, sizeof(*pNew));
- pNew->zDbName = (char*)&pNew[1];
- memcpy(pNew->zDbName, zDbName, nDbName+1);
- pNew->zTableName = sqlite3_mprintf("%s", zTableName);
- pNew->db = db;
- if( pNew->zTableName==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(word,rank,distance,langid, "
- "score, matchlen, phonehash HIDDEN, "
- "top HIDDEN, scope HIDDEN, srchcnt HIDDEN, "
- "soundslike HIDDEN, command HIDDEN)"
- );
-#define SPELLFIX_COL_WORD 0
-#define SPELLFIX_COL_RANK 1
-#define SPELLFIX_COL_DISTANCE 2
-#define SPELLFIX_COL_LANGID 3
-#define SPELLFIX_COL_SCORE 4
-#define SPELLFIX_COL_MATCHLEN 5
-#define SPELLFIX_COL_PHONEHASH 6
-#define SPELLFIX_COL_TOP 7
-#define SPELLFIX_COL_SCOPE 8
-#define SPELLFIX_COL_SRCHCNT 9
-#define SPELLFIX_COL_SOUNDSLIKE 10
-#define SPELLFIX_COL_COMMAND 11
- }
- if( rc==SQLITE_OK && isCreate ){
- spellfix1DbExec(&rc, db,
- "CREATE TABLE IF NOT EXISTS \"%w\".\"%w_vocab\"(\n"
- " id INTEGER PRIMARY KEY,\n"
- " rank INT,\n"
- " langid INT,\n"
- " word TEXT,\n"
- " k1 TEXT,\n"
- " k2 TEXT\n"
- ");\n",
- zDbName, zTableName
- );
- spellfix1DbExec(&rc, db,
- "CREATE INDEX IF NOT EXISTS \"%w\".\"%w_vocab_index_langid_k2\" "
- "ON \"%w_vocab\"(langid,k2);",
- zDbName, zTableName, zTableName
- );
- }
- for(i=3; rc==SQLITE_OK && i<argc; i++){
- if( strncmp(argv[i],"edit_cost_table=",16)==0 && pNew->zCostTable==0 ){
- pNew->zCostTable = spellfix1Dequote(&argv[i][16]);
- if( pNew->zCostTable==0 ) rc = SQLITE_NOMEM;
- continue;
- }
- *pzErr = sqlite3_mprintf("bad argument to spellfix1(): \"%s\"", argv[i]);
- rc = SQLITE_ERROR;
- }
- }
-
- if( rc && pNew ){
- *ppVTab = 0;
- spellfix1Uninit(0, &pNew->base);
- }else{
- *ppVTab = (sqlite3_vtab *)pNew;
- }
- return rc;
-}
-
-/*
-** The xConnect and xCreate methods
-*/
-static int spellfix1Connect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab,
- char **pzErr
-){
- return spellfix1Init(0, db, pAux, argc, argv, ppVTab, pzErr);
-}
-static int spellfix1Create(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab,
- char **pzErr
-){
- return spellfix1Init(1, db, pAux, argc, argv, ppVTab, pzErr);
-}
-
-/*
-** Clear all of the content from a cursor.
-*/
-static void spellfix1ResetCursor(spellfix1_cursor *pCur){
- int i;
- for(i=0; i<pCur->nRow; i++){
- sqlite3_free(pCur->a[i].zWord);
- }
- pCur->nRow = 0;
- pCur->iRow = 0;
- pCur->nSearch = 0;
- if( pCur->pFullScan ){
- sqlite3_finalize(pCur->pFullScan);
- pCur->pFullScan = 0;
- }
-}
-
-/*
-** Resize the cursor to hold up to N rows of content
-*/
-static void spellfix1ResizeCursor(spellfix1_cursor *pCur, int N){
- struct spellfix1_row *aNew;
- assert( N>=pCur->nRow );
- aNew = sqlite3_realloc64(pCur->a, sizeof(pCur->a[0])*N);
- if( aNew==0 && N>0 ){
- spellfix1ResetCursor(pCur);
- sqlite3_free(pCur->a);
- pCur->nAlloc = 0;
- pCur->a = 0;
- }else{
- pCur->nAlloc = N;
- pCur->a = aNew;
- }
-}
-
-
-/*
-** Close a fuzzy-search cursor.
-*/
-static int spellfix1Close(sqlite3_vtab_cursor *cur){
- spellfix1_cursor *pCur = (spellfix1_cursor *)cur;
- spellfix1ResetCursor(pCur);
- spellfix1ResizeCursor(pCur, 0);
- sqlite3_free(pCur->zPattern);
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-#define SPELLFIX_IDXNUM_MATCH 0x01 /* word MATCH $str */
-#define SPELLFIX_IDXNUM_LANGID 0x02 /* langid == $langid */
-#define SPELLFIX_IDXNUM_TOP 0x04 /* top = $top */
-#define SPELLFIX_IDXNUM_SCOPE 0x08 /* scope = $scope */
-#define SPELLFIX_IDXNUM_DISTLT 0x10 /* distance < $distance */
-#define SPELLFIX_IDXNUM_DISTLE 0x20 /* distance <= $distance */
-#define SPELLFIX_IDXNUM_ROWID 0x40 /* rowid = $rowid */
-#define SPELLFIX_IDXNUM_DIST (0x10|0x20) /* DISTLT and DISTLE */
-
-/*
-**
-** The plan number is a bitmask of the SPELLFIX_IDXNUM_* values defined
-** above.
-**
-** filter.argv[*] values contains $str, $langid, $top, $scope and $rowid
-** if specified and in that order.
-*/
-static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int iPlan = 0;
- int iLangTerm = -1;
- int iTopTerm = -1;
- int iScopeTerm = -1;
- int iDistTerm = -1;
- int iRowidTerm = -1;
- int i;
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
-
- /* Terms of the form: word MATCH $str */
- if( (iPlan & SPELLFIX_IDXNUM_MATCH)==0
- && pConstraint->iColumn==SPELLFIX_COL_WORD
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH
- ){
- iPlan |= SPELLFIX_IDXNUM_MATCH;
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- }
-
- /* Terms of the form: langid = $langid */
- if( (iPlan & SPELLFIX_IDXNUM_LANGID)==0
- && pConstraint->iColumn==SPELLFIX_COL_LANGID
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= SPELLFIX_IDXNUM_LANGID;
- iLangTerm = i;
- }
-
- /* Terms of the form: top = $top */
- if( (iPlan & SPELLFIX_IDXNUM_TOP)==0
- && pConstraint->iColumn==SPELLFIX_COL_TOP
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= SPELLFIX_IDXNUM_TOP;
- iTopTerm = i;
- }
-
- /* Terms of the form: scope = $scope */
- if( (iPlan & SPELLFIX_IDXNUM_SCOPE)==0
- && pConstraint->iColumn==SPELLFIX_COL_SCOPE
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= SPELLFIX_IDXNUM_SCOPE;
- iScopeTerm = i;
- }
-
- /* Terms of the form: distance < $dist or distance <= $dist */
- if( (iPlan & SPELLFIX_IDXNUM_DIST)==0
- && pConstraint->iColumn==SPELLFIX_COL_DISTANCE
- && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
- || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE)
- ){
- if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){
- iPlan |= SPELLFIX_IDXNUM_DISTLT;
- }else{
- iPlan |= SPELLFIX_IDXNUM_DISTLE;
- }
- iDistTerm = i;
- }
-
- /* Terms of the form: distance < $dist or distance <= $dist */
- if( (iPlan & SPELLFIX_IDXNUM_ROWID)==0
- && pConstraint->iColumn<0
- && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- iPlan |= SPELLFIX_IDXNUM_ROWID;
- iRowidTerm = i;
- }
- }
- if( iPlan&SPELLFIX_IDXNUM_MATCH ){
- int idx = 2;
- pIdxInfo->idxNum = iPlan;
- if( pIdxInfo->nOrderBy==1
- && pIdxInfo->aOrderBy[0].iColumn==SPELLFIX_COL_SCORE
- && pIdxInfo->aOrderBy[0].desc==0
- ){
- pIdxInfo->orderByConsumed = 1; /* Default order by iScore */
- }
- if( iPlan&SPELLFIX_IDXNUM_LANGID ){
- pIdxInfo->aConstraintUsage[iLangTerm].argvIndex = idx++;
- pIdxInfo->aConstraintUsage[iLangTerm].omit = 1;
- }
- if( iPlan&SPELLFIX_IDXNUM_TOP ){
- pIdxInfo->aConstraintUsage[iTopTerm].argvIndex = idx++;
- pIdxInfo->aConstraintUsage[iTopTerm].omit = 1;
- }
- if( iPlan&SPELLFIX_IDXNUM_SCOPE ){
- pIdxInfo->aConstraintUsage[iScopeTerm].argvIndex = idx++;
- pIdxInfo->aConstraintUsage[iScopeTerm].omit = 1;
- }
- if( iPlan&SPELLFIX_IDXNUM_DIST ){
- pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = idx++;
- pIdxInfo->aConstraintUsage[iDistTerm].omit = 1;
- }
- pIdxInfo->estimatedCost = 1e5;
- }else if( (iPlan & SPELLFIX_IDXNUM_ROWID) ){
- pIdxInfo->idxNum = SPELLFIX_IDXNUM_ROWID;
- pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1;
- pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1;
- pIdxInfo->estimatedCost = 5;
- }else{
- pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = 1e50;
- }
- return SQLITE_OK;
-}
-
-/*
-** Open a new fuzzy-search cursor.
-*/
-static int spellfix1Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- spellfix1_vtab *p = (spellfix1_vtab*)pVTab;
- spellfix1_cursor *pCur;
- pCur = sqlite3_malloc64( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->pVTab = p;
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Adjust a distance measurement by the words rank in order to show
-** preference to common words.
-*/
-static int spellfix1Score(int iDistance, int iRank){
- int iLog2;
- for(iLog2=0; iRank>0; iLog2++, iRank>>=1){}
- return iDistance + 32 - iLog2;
-}
-
-/*
-** Compare two spellfix1_row objects for sorting purposes in qsort() such
-** that they sort in order of increasing distance.
-*/
-static int SQLITE_CDECL spellfix1RowCompare(const void *A, const void *B){
- const struct spellfix1_row *a = (const struct spellfix1_row*)A;
- const struct spellfix1_row *b = (const struct spellfix1_row*)B;
- return a->iScore - b->iScore;
-}
-
-/*
-** A structure used to pass information from spellfix1FilterForMatch()
-** into spellfix1RunQuery().
-*/
-typedef struct MatchQuery {
- spellfix1_cursor *pCur; /* The cursor being queried */
- sqlite3_stmt *pStmt; /* shadow table query statment */
- char zHash[SPELLFIX_MX_HASH]; /* The current phonehash for zPattern */
- const char *zPattern; /* Transliterated input string */
- int nPattern; /* Length of zPattern */
- EditDist3FromString *pMatchStr3; /* Original unicode string */
- EditDist3Config *pConfig3; /* Edit-distance cost coefficients */
- const EditDist3Lang *pLang; /* The selected language coefficients */
- int iLang; /* The language id */
- int iScope; /* Default scope */
- int iMaxDist; /* Maximum allowed edit distance, or -1 */
- int rc; /* Error code */
- int nRun; /* Number of prior runs for the same zPattern */
- char azPrior[SPELLFIX_MX_RUN][SPELLFIX_MX_HASH]; /* Prior hashes */
-} MatchQuery;
-
-/*
-** Run a query looking for the best matches against zPattern using
-** zHash as the character class seed hash.
-*/
-static void spellfix1RunQuery(MatchQuery *p, const char *zQuery, int nQuery){
- const char *zK1;
- const char *zWord;
- int iDist;
- int iRank;
- int iScore;
- int iWorst = 0;
- int idx;
- int idxWorst = -1;
- int i;
- int iScope = p->iScope;
- spellfix1_cursor *pCur = p->pCur;
- sqlite3_stmt *pStmt = p->pStmt;
- char zHash1[SPELLFIX_MX_HASH];
- char zHash2[SPELLFIX_MX_HASH];
- char *zClass;
- int nClass;
- int rc;
-
- if( pCur->a==0 || p->rc ) return; /* Prior memory allocation failure */
- zClass = (char*)phoneticHash((unsigned char*)zQuery, nQuery);
- if( zClass==0 ){
- p->rc = SQLITE_NOMEM;
- return;
- }
- nClass = (int)strlen(zClass);
- if( nClass>SPELLFIX_MX_HASH-2 ){
- nClass = SPELLFIX_MX_HASH-2;
- zClass[nClass] = 0;
- }
- if( nClass<=iScope ){
- if( nClass>2 ){
- iScope = nClass-1;
- }else{
- iScope = nClass;
- }
- }
- memcpy(zHash1, zClass, iScope);
- sqlite3_free(zClass);
- zHash1[iScope] = 0;
- memcpy(zHash2, zHash1, iScope);
- zHash2[iScope] = 'Z';
- zHash2[iScope+1] = 0;
-#if SPELLFIX_MX_RUN>1
- for(i=0; i<p->nRun; i++){
- if( strcmp(p->azPrior[i], zHash1)==0 ) return;
- }
-#endif
- assert( p->nRun<SPELLFIX_MX_RUN );
- memcpy(p->azPrior[p->nRun++], zHash1, iScope+1);
- if( sqlite3_bind_text(pStmt, 1, zHash1, -1, SQLITE_STATIC)==SQLITE_NOMEM
- || sqlite3_bind_text(pStmt, 2, zHash2, -1, SQLITE_STATIC)==SQLITE_NOMEM
- ){
- p->rc = SQLITE_NOMEM;
- return;
- }
-#if SPELLFIX_MX_RUN>1
- for(i=0; i<pCur->nRow; i++){
- if( pCur->a[i].iScore>iWorst ){
- iWorst = pCur->a[i].iScore;
- idxWorst = i;
- }
- }
-#endif
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- int iMatchlen = -1;
- iRank = sqlite3_column_int(pStmt, 2);
- if( p->pMatchStr3 ){
- int nWord = sqlite3_column_bytes(pStmt, 1);
- zWord = (const char*)sqlite3_column_text(pStmt, 1);
- iDist = editDist3Core(p->pMatchStr3, zWord, nWord, p->pLang, &iMatchlen);
- }else{
- zK1 = (const char*)sqlite3_column_text(pStmt, 3);
- if( zK1==0 ) continue;
- iDist = editdist1(p->zPattern, zK1, 0);
- }
- if( iDist<0 ){
- p->rc = SQLITE_NOMEM;
- break;
- }
- pCur->nSearch++;
-
- /* If there is a "distance < $dist" or "distance <= $dist" constraint,
- ** check if this row meets it. If not, jump back up to the top of the
- ** loop to process the next row. Otherwise, if the row does match the
- ** distance constraint, check if the pCur->a[] array is already full.
- ** If it is and no explicit "top = ?" constraint was present in the
- ** query, grow the array to ensure there is room for the new entry. */
- assert( (p->iMaxDist>=0)==((pCur->idxNum & SPELLFIX_IDXNUM_DIST) ? 1 : 0) );
- if( p->iMaxDist>=0 ){
- if( iDist>p->iMaxDist ) continue;
- if( pCur->nRow>=pCur->nAlloc && (pCur->idxNum & SPELLFIX_IDXNUM_TOP)==0 ){
- spellfix1ResizeCursor(pCur, pCur->nAlloc*2 + 10);
- if( pCur->a==0 ) break;
- }
- }
-
- iScore = spellfix1Score(iDist,iRank);
- if( pCur->nRow<pCur->nAlloc ){
- idx = pCur->nRow;
- }else if( iScore<iWorst ){
- idx = idxWorst;
- sqlite3_free(pCur->a[idx].zWord);
- }else{
- continue;
- }
-
- pCur->a[idx].zWord = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
- if( pCur->a[idx].zWord==0 ){
- p->rc = SQLITE_NOMEM;
- break;
- }
- pCur->a[idx].iRowid = sqlite3_column_int64(pStmt, 0);
- pCur->a[idx].iRank = iRank;
- pCur->a[idx].iDistance = iDist;
- pCur->a[idx].iScore = iScore;
- pCur->a[idx].iMatchlen = iMatchlen;
- memcpy(pCur->a[idx].zHash, zHash1, iScope+1);
- if( pCur->nRow<pCur->nAlloc ) pCur->nRow++;
- if( pCur->nRow==pCur->nAlloc ){
- iWorst = pCur->a[0].iScore;
- idxWorst = 0;
- for(i=1; i<pCur->nRow; i++){
- iScore = pCur->a[i].iScore;
- if( iWorst<iScore ){
- iWorst = iScore;
- idxWorst = i;
- }
- }
- }
- }
- rc = sqlite3_reset(pStmt);
- if( rc ) p->rc = rc;
-}
-
-/*
-** This version of the xFilter method work if the MATCH term is present
-** and we are doing a scan.
-*/
-static int spellfix1FilterForMatch(
- spellfix1_cursor *pCur,
- int argc,
- sqlite3_value **argv
-){
- int idxNum = pCur->idxNum;
- const unsigned char *zMatchThis; /* RHS of the MATCH operator */
- EditDist3FromString *pMatchStr3 = 0; /* zMatchThis as an editdist string */
- char *zPattern; /* Transliteration of zMatchThis */
- int nPattern; /* Length of zPattern */
- int iLimit = 20; /* Max number of rows of output */
- int iScope = 3; /* Use this many characters of zClass */
- int iLang = 0; /* Language code */
- char *zSql; /* SQL of shadow table query */
- sqlite3_stmt *pStmt = 0; /* Shadow table query */
- int rc; /* Result code */
- int idx = 1; /* Next available filter parameter */
- spellfix1_vtab *p = pCur->pVTab; /* The virtual table that owns pCur */
- MatchQuery x; /* For passing info to RunQuery() */
-
- /* Load the cost table if we have not already done so */
- if( p->zCostTable!=0 && p->pConfig3==0 ){
- p->pConfig3 = sqlite3_malloc64( sizeof(p->pConfig3[0]) );
- if( p->pConfig3==0 ) return SQLITE_NOMEM;
- memset(p->pConfig3, 0, sizeof(p->pConfig3[0]));
- rc = editDist3ConfigLoad(p->pConfig3, p->db, p->zCostTable);
- if( rc ) return rc;
- }
- memset(&x, 0, sizeof(x));
- x.iScope = 3; /* Default scope if none specified by "WHERE scope=N" */
- x.iMaxDist = -1; /* Maximum allowed edit distance */
-
- if( idxNum&2 ){
- iLang = sqlite3_value_int(argv[idx++]);
- }
- if( idxNum&4 ){
- iLimit = sqlite3_value_int(argv[idx++]);
- if( iLimit<1 ) iLimit = 1;
- }
- if( idxNum&8 ){
- x.iScope = sqlite3_value_int(argv[idx++]);
- if( x.iScope<1 ) x.iScope = 1;
- if( x.iScope>SPELLFIX_MX_HASH-2 ) x.iScope = SPELLFIX_MX_HASH-2;
- }
- if( idxNum&(16|32) ){
- x.iMaxDist = sqlite3_value_int(argv[idx++]);
- if( idxNum&16 ) x.iMaxDist--;
- if( x.iMaxDist<0 ) x.iMaxDist = 0;
- }
- spellfix1ResetCursor(pCur);
- spellfix1ResizeCursor(pCur, iLimit);
- zMatchThis = sqlite3_value_text(argv[0]);
- if( zMatchThis==0 ) return SQLITE_OK;
- if( p->pConfig3 ){
- x.pLang = editDist3FindLang(p->pConfig3, iLang);
- pMatchStr3 = editDist3FromStringNew(x.pLang, (const char*)zMatchThis, -1);
- if( pMatchStr3==0 ){
- x.rc = SQLITE_NOMEM;
- goto filter_exit;
- }
- }else{
- x.pLang = 0;
- }
- zPattern = (char*)transliterate(zMatchThis, sqlite3_value_bytes(argv[0]));
- sqlite3_free(pCur->zPattern);
- pCur->zPattern = zPattern;
- if( zPattern==0 ){
- x.rc = SQLITE_NOMEM;
- goto filter_exit;
- }
- nPattern = (int)strlen(zPattern);
- if( zPattern[nPattern-1]=='*' ) nPattern--;
- zSql = sqlite3_mprintf(
- "SELECT id, word, rank, coalesce(k1,word)"
- " FROM \"%w\".\"%w_vocab\""
- " WHERE langid=%d AND k2>=?1 AND k2<?2",
- p->zDbName, p->zTableName, iLang
- );
- if( zSql==0 ){
- x.rc = SQLITE_NOMEM;
- pStmt = 0;
- goto filter_exit;
- }
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- pCur->iLang = iLang;
- x.pCur = pCur;
- x.pStmt = pStmt;
- x.zPattern = zPattern;
- x.nPattern = nPattern;
- x.pMatchStr3 = pMatchStr3;
- x.iLang = iLang;
- x.rc = rc;
- x.pConfig3 = p->pConfig3;
- if( x.rc==SQLITE_OK ){
- spellfix1RunQuery(&x, zPattern, nPattern);
- }
-
- if( pCur->a ){
- qsort(pCur->a, pCur->nRow, sizeof(pCur->a[0]), spellfix1RowCompare);
- pCur->iTop = iLimit;
- pCur->iScope = iScope;
- }else{
- x.rc = SQLITE_NOMEM;
- }
-
-filter_exit:
- sqlite3_finalize(pStmt);
- editDist3FromStringDelete(pMatchStr3);
- return x.rc;
-}
-
-/*
-** This version of xFilter handles a full-table scan case
-*/
-static int spellfix1FilterForFullScan(
- spellfix1_cursor *pCur,
- int argc,
- sqlite3_value **argv
-){
- int rc = SQLITE_OK;
- int idxNum = pCur->idxNum;
- char *zSql;
- spellfix1_vtab *pVTab = pCur->pVTab;
- spellfix1ResetCursor(pCur);
- assert( idxNum==0 || idxNum==64 );
- zSql = sqlite3_mprintf(
- "SELECT word, rank, NULL, langid, id FROM \"%w\".\"%w_vocab\"%s",
- pVTab->zDbName, pVTab->zTableName,
- ((idxNum & 64) ? " WHERE rowid=?" : "")
- );
- if( zSql==0 ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pFullScan, 0);
- sqlite3_free(zSql);
- if( rc==SQLITE_OK && (idxNum & 64) ){
- assert( argc==1 );
- rc = sqlite3_bind_value(pCur->pFullScan, 1, argv[0]);
- }
- pCur->nRow = pCur->iRow = 0;
- if( rc==SQLITE_OK ){
- rc = sqlite3_step(pCur->pFullScan);
- if( rc==SQLITE_ROW ){ pCur->iRow = -1; rc = SQLITE_OK; }
- if( rc==SQLITE_DONE ){ rc = SQLITE_OK; }
- }else{
- pCur->iRow = 0;
- }
- return rc;
-}
-
-
-/*
-** Called to "rewind" a cursor back to the beginning so that
-** it starts its output over again. Always called at least once
-** prior to any spellfix1Column, spellfix1Rowid, or spellfix1Eof call.
-*/
-static int spellfix1Filter(
- sqlite3_vtab_cursor *cur,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- spellfix1_cursor *pCur = (spellfix1_cursor *)cur;
- int rc;
- pCur->idxNum = idxNum;
- if( idxNum & 1 ){
- rc = spellfix1FilterForMatch(pCur, argc, argv);
- }else{
- rc = spellfix1FilterForFullScan(pCur, argc, argv);
- }
- return rc;
-}
-
-
-/*
-** Advance a cursor to its next row of output
-*/
-static int spellfix1Next(sqlite3_vtab_cursor *cur){
- spellfix1_cursor *pCur = (spellfix1_cursor *)cur;
- int rc = SQLITE_OK;
- if( pCur->iRow < pCur->nRow ){
- if( pCur->pFullScan ){
- rc = sqlite3_step(pCur->pFullScan);
- if( rc!=SQLITE_ROW ) pCur->iRow = pCur->nRow;
- if( rc==SQLITE_ROW || rc==SQLITE_DONE ) rc = SQLITE_OK;
- }else{
- pCur->iRow++;
- }
- }
- return rc;
-}
-
-/*
-** Return TRUE if we are at the end-of-file
-*/
-static int spellfix1Eof(sqlite3_vtab_cursor *cur){
- spellfix1_cursor *pCur = (spellfix1_cursor *)cur;
- return pCur->iRow>=pCur->nRow;
-}
-
-/*
-** Return columns from the current row.
-*/
-static int spellfix1Column(
- sqlite3_vtab_cursor *cur,
- sqlite3_context *ctx,
- int i
-){
- spellfix1_cursor *pCur = (spellfix1_cursor*)cur;
- if( pCur->pFullScan ){
- if( i<=SPELLFIX_COL_LANGID ){
- sqlite3_result_value(ctx, sqlite3_column_value(pCur->pFullScan, i));
- }else{
- sqlite3_result_null(ctx);
- }
- return SQLITE_OK;
- }
- switch( i ){
- case SPELLFIX_COL_WORD: {
- sqlite3_result_text(ctx, pCur->a[pCur->iRow].zWord, -1, SQLITE_STATIC);
- break;
- }
- case SPELLFIX_COL_RANK: {
- sqlite3_result_int(ctx, pCur->a[pCur->iRow].iRank);
- break;
- }
- case SPELLFIX_COL_DISTANCE: {
- sqlite3_result_int(ctx, pCur->a[pCur->iRow].iDistance);
- break;
- }
- case SPELLFIX_COL_LANGID: {
- sqlite3_result_int(ctx, pCur->iLang);
- break;
- }
- case SPELLFIX_COL_SCORE: {
- sqlite3_result_int(ctx, pCur->a[pCur->iRow].iScore);
- break;
- }
- case SPELLFIX_COL_MATCHLEN: {
- int iMatchlen = pCur->a[pCur->iRow].iMatchlen;
- if( iMatchlen<0 ){
- int nPattern = (int)strlen(pCur->zPattern);
- char *zWord = pCur->a[pCur->iRow].zWord;
- int nWord = (int)strlen(zWord);
-
- if( nPattern>0 && pCur->zPattern[nPattern-1]=='*' ){
- char *zTranslit;
- int res;
- zTranslit = (char *)transliterate((unsigned char *)zWord, nWord);
- if( !zTranslit ) return SQLITE_NOMEM;
- res = editdist1(pCur->zPattern, zTranslit, &iMatchlen);
- sqlite3_free(zTranslit);
- if( res<0 ) return SQLITE_NOMEM;
- iMatchlen = translen_to_charlen(zWord, nWord, iMatchlen);
- }else{
- iMatchlen = utf8Charlen(zWord, nWord);
- }
- }
-
- sqlite3_result_int(ctx, iMatchlen);
- break;
- }
- case SPELLFIX_COL_PHONEHASH: {
- sqlite3_result_text(ctx, pCur->a[pCur->iRow].zHash, -1, SQLITE_STATIC);
- break;
- }
- case SPELLFIX_COL_TOP: {
- sqlite3_result_int(ctx, pCur->iTop);
- break;
- }
- case SPELLFIX_COL_SCOPE: {
- sqlite3_result_int(ctx, pCur->iScope);
- break;
- }
- case SPELLFIX_COL_SRCHCNT: {
- sqlite3_result_int(ctx, pCur->nSearch);
- break;
- }
- default: {
- sqlite3_result_null(ctx);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** The rowid.
-*/
-static int spellfix1Rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- spellfix1_cursor *pCur = (spellfix1_cursor*)cur;
- if( pCur->pFullScan ){
- *pRowid = sqlite3_column_int64(pCur->pFullScan, 4);
- }else{
- *pRowid = pCur->a[pCur->iRow].iRowid;
- }
- return SQLITE_OK;
-}
-
-/*
-** This function is called by the xUpdate() method. It returns a string
-** containing the conflict mode that xUpdate() should use for the current
-** operation. One of: "ROLLBACK", "IGNORE", "ABORT" or "REPLACE".
-*/
-static const char *spellfix1GetConflict(sqlite3 *db){
- static const char *azConflict[] = {
- /* Note: Instead of "FAIL" - "ABORT". */
- "ROLLBACK", "IGNORE", "ABORT", "ABORT", "REPLACE"
- };
- int eConflict = sqlite3_vtab_on_conflict(db);
-
- assert( eConflict==SQLITE_ROLLBACK || eConflict==SQLITE_IGNORE
- || eConflict==SQLITE_FAIL || eConflict==SQLITE_ABORT
- || eConflict==SQLITE_REPLACE
- );
- assert( SQLITE_ROLLBACK==1 );
- assert( SQLITE_IGNORE==2 );
- assert( SQLITE_FAIL==3 );
- assert( SQLITE_ABORT==4 );
- assert( SQLITE_REPLACE==5 );
-
- return azConflict[eConflict-1];
-}
-
-/*
-** The xUpdate() method.
-*/
-static int spellfix1Update(
- sqlite3_vtab *pVTab,
- int argc,
- sqlite3_value **argv,
- sqlite_int64 *pRowid
-){
- int rc = SQLITE_OK;
- sqlite3_int64 rowid, newRowid;
- spellfix1_vtab *p = (spellfix1_vtab*)pVTab;
- sqlite3 *db = p->db;
-
- if( argc==1 ){
- /* A delete operation on the rowid given by argv[0] */
- rowid = *pRowid = sqlite3_value_int64(argv[0]);
- spellfix1DbExec(&rc, db, "DELETE FROM \"%w\".\"%w_vocab\" "
- " WHERE id=%lld",
- p->zDbName, p->zTableName, rowid);
- }else{
- const unsigned char *zWord = sqlite3_value_text(argv[SPELLFIX_COL_WORD+2]);
- int nWord = sqlite3_value_bytes(argv[SPELLFIX_COL_WORD+2]);
- int iLang = sqlite3_value_int(argv[SPELLFIX_COL_LANGID+2]);
- int iRank = sqlite3_value_int(argv[SPELLFIX_COL_RANK+2]);
- const unsigned char *zSoundslike =
- sqlite3_value_text(argv[SPELLFIX_COL_SOUNDSLIKE+2]);
- int nSoundslike = sqlite3_value_bytes(argv[SPELLFIX_COL_SOUNDSLIKE+2]);
- char *zK1, *zK2;
- int i;
- char c;
- const char *zConflict = spellfix1GetConflict(db);
-
- if( zWord==0 ){
- /* Inserts of the form: INSERT INTO table(command) VALUES('xyzzy');
- ** cause zWord to be NULL, so we look at the "command" column to see
- ** what special actions to take */
- const char *zCmd =
- (const char*)sqlite3_value_text(argv[SPELLFIX_COL_COMMAND+2]);
- if( zCmd==0 ){
- pVTab->zErrMsg = sqlite3_mprintf("NOT NULL constraint failed: %s.word",
- p->zTableName);
- return SQLITE_CONSTRAINT_NOTNULL;
- }
- if( strcmp(zCmd,"reset")==0 ){
- /* Reset the edit cost table (if there is one). */
- editDist3ConfigDelete(p->pConfig3);
- p->pConfig3 = 0;
- return SQLITE_OK;
- }
- if( strncmp(zCmd,"edit_cost_table=",16)==0 ){
- editDist3ConfigDelete(p->pConfig3);
- p->pConfig3 = 0;
- sqlite3_free(p->zCostTable);
- p->zCostTable = spellfix1Dequote(zCmd+16);
- if( p->zCostTable==0 ) return SQLITE_NOMEM;
- if( p->zCostTable[0]==0 || sqlite3_stricmp(p->zCostTable,"null")==0 ){
- sqlite3_free(p->zCostTable);
- p->zCostTable = 0;
- }
- return SQLITE_OK;
- }
- pVTab->zErrMsg = sqlite3_mprintf("unknown value for %s.command: \"%w\"",
- p->zTableName, zCmd);
- return SQLITE_ERROR;
- }
- if( iRank<1 ) iRank = 1;
- if( zSoundslike ){
- zK1 = (char*)transliterate(zSoundslike, nSoundslike);
- }else{
- zK1 = (char*)transliterate(zWord, nWord);
- }
- if( zK1==0 ) return SQLITE_NOMEM;
- for(i=0; (c = zK1[i])!=0; i++){
- if( c>='A' && c<='Z' ) zK1[i] += 'a' - 'A';
- }
- zK2 = (char*)phoneticHash((const unsigned char*)zK1, i);
- if( zK2==0 ){
- sqlite3_free(zK1);
- return SQLITE_NOMEM;
- }
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
- if( sqlite3_value_type(argv[1])==SQLITE_NULL ){
- spellfix1DbExec(&rc, db,
- "INSERT INTO \"%w\".\"%w_vocab\"(rank,langid,word,k1,k2) "
- "VALUES(%d,%d,%Q,nullif(%Q,%Q),%Q)",
- p->zDbName, p->zTableName,
- iRank, iLang, zWord, zK1, zWord, zK2
- );
- }else{
- newRowid = sqlite3_value_int64(argv[1]);
- spellfix1DbExec(&rc, db,
- "INSERT OR %s INTO \"%w\".\"%w_vocab\"(id,rank,langid,word,k1,k2) "
- "VALUES(%lld,%d,%d,%Q,nullif(%Q,%Q),%Q)",
- zConflict, p->zDbName, p->zTableName,
- newRowid, iRank, iLang, zWord, zK1, zWord, zK2
- );
- }
- *pRowid = sqlite3_last_insert_rowid(db);
- }else{
- rowid = sqlite3_value_int64(argv[0]);
- newRowid = *pRowid = sqlite3_value_int64(argv[1]);
- spellfix1DbExec(&rc, db,
- "UPDATE OR %s \"%w\".\"%w_vocab\" SET id=%lld, rank=%d, langid=%d,"
- " word=%Q, k1=nullif(%Q,%Q), k2=%Q WHERE id=%lld",
- zConflict, p->zDbName, p->zTableName, newRowid, iRank, iLang,
- zWord, zK1, zWord, zK2, rowid
- );
- }
- sqlite3_free(zK1);
- sqlite3_free(zK2);
- }
- return rc;
-}
-
-/*
-** Rename the spellfix1 table.
-*/
-static int spellfix1Rename(sqlite3_vtab *pVTab, const char *zNew){
- spellfix1_vtab *p = (spellfix1_vtab*)pVTab;
- sqlite3 *db = p->db;
- int rc = SQLITE_OK;
- char *zNewName = sqlite3_mprintf("%s", zNew);
- if( zNewName==0 ){
- return SQLITE_NOMEM;
- }
- spellfix1DbExec(&rc, db,
- "ALTER TABLE \"%w\".\"%w_vocab\" RENAME TO \"%w_vocab\"",
- p->zDbName, p->zTableName, zNewName
- );
- if( rc==SQLITE_OK ){
- sqlite3_free(p->zTableName);
- p->zTableName = zNewName;
- }else{
- sqlite3_free(zNewName);
- }
- return rc;
-}
-
-
-/*
-** A virtual table module that provides fuzzy search.
-*/
-static sqlite3_module spellfix1Module = {
- 0, /* iVersion */
- spellfix1Create, /* xCreate - handle CREATE VIRTUAL TABLE */
- spellfix1Connect, /* xConnect - reconnected to an existing table */
- spellfix1BestIndex, /* xBestIndex - figure out how to do a query */
- spellfix1Disconnect, /* xDisconnect - close a connection */
- spellfix1Destroy, /* xDestroy - handle DROP TABLE */
- spellfix1Open, /* xOpen - open a cursor */
- spellfix1Close, /* xClose - close a cursor */
- spellfix1Filter, /* xFilter - configure scan constraints */
- spellfix1Next, /* xNext - advance a cursor */
- spellfix1Eof, /* xEof - check for end of scan */
- spellfix1Column, /* xColumn - read data */
- spellfix1Rowid, /* xRowid - read data */
- spellfix1Update, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- spellfix1Rename, /* xRename */
-};
-
-/*
-** Register the various functions and the virtual table.
-*/
-static int spellfix1Register(sqlite3 *db){
- int rc = SQLITE_OK;
- int i;
- rc = sqlite3_create_function(db, "spellfix1_translit", 1,
- SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
- transliterateSqlFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "spellfix1_editdist", 2,
- SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
- editdistSqlFunc, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "spellfix1_phonehash", 1,
- SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
- phoneticHashSqlFunc, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "spellfix1_scriptcode", 1,
- SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
- scriptCodeSqlFunc, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_module(db, "spellfix1", &spellfix1Module, 0);
- }
- if( rc==SQLITE_OK ){
- rc = editDist3Install(db);
- }
-
- /* Verify sanity of the translit[] table */
- for(i=0; i<sizeof(translit)/sizeof(translit[0])-1; i++){
- assert( translit[i].cFrom<translit[i+1].cFrom );
- }
-
- return rc;
-}
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/*
-** Extension load function.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_spellfix_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- return spellfix1Register(db);
-#endif
- return SQLITE_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/sqlar.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/sqlar.c
deleted file mode 100644
index e812d70c99a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/sqlar.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-** 2017-12-17
-**
-** 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.
-**
-******************************************************************************
-**
-** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
-** for working with sqlar archives and used by the shell tool's built-in
-** sqlar support.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <zlib.h>
-
-/*
-** Implementation of the "sqlar_compress(X)" SQL function.
-**
-** If the type of X is SQLITE_BLOB, and compressing that blob using
-** zlib utility function compress() yields a smaller blob, return the
-** compressed blob. Otherwise, return a copy of X.
-**
-** SQLar uses the "zlib format" for compressed content. The zlib format
-** contains a two-byte identification header and a four-byte checksum at
-** the end. This is different from ZIP which uses the raw deflate format.
-**
-** Future enhancements to SQLar might add support for new compression formats.
-** If so, those new formats will be identified by alternative headers in the
-** compressed data.
-*/
-static void sqlarCompressFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- assert( argc==1 );
- if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
- const Bytef *pData = sqlite3_value_blob(argv[0]);
- uLong nData = sqlite3_value_bytes(argv[0]);
- uLongf nOut = compressBound(nData);
- Bytef *pOut;
-
- pOut = (Bytef*)sqlite3_malloc(nOut);
- if( pOut==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }else{
- if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
- sqlite3_result_error(context, "error in compress()", -1);
- }else if( nOut<nData ){
- sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_value(context, argv[0]);
- }
- sqlite3_free(pOut);
- }
- }else{
- sqlite3_result_value(context, argv[0]);
- }
-}
-
-/*
-** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
-**
-** Parameter SZ is interpreted as an integer. If it is less than or
-** equal to zero, then this function returns a copy of X. Or, if
-** SZ is equal to the size of X when interpreted as a blob, also
-** return a copy of X. Otherwise, decompress blob X using zlib
-** utility function uncompress() and return the results (another
-** blob).
-*/
-static void sqlarUncompressFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- uLong nData;
- uLongf sz;
-
- assert( argc==2 );
- sz = sqlite3_value_int(argv[1]);
-
- if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
- sqlite3_result_value(context, argv[0]);
- }else{
- const Bytef *pData= sqlite3_value_blob(argv[0]);
- Bytef *pOut = sqlite3_malloc(sz);
- if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
- sqlite3_result_error(context, "error in uncompress()", -1);
- }else{
- sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
- }
- sqlite3_free(pOut);
- }
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_sqlar_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0,
- sqlarCompressFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0,
- sqlarUncompressFunc, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/stmt.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/stmt.c
deleted file mode 100644
index dbaa0bd64dc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/stmt.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
-** 2017-05-31
-**
-** 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 demonstrates an eponymous virtual table that returns information
-** about all prepared statements for the database connection.
-**
-** Usage example:
-**
-** .load ./stmt
-** .mode line
-** .header on
-** SELECT * FROM stmt;
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB)
-#if !defined(SQLITEINT_H)
-#include "sqlite3ext.h"
-#endif
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/* stmt_vtab is a subclass of sqlite3_vtab which will
-** serve as the underlying representation of a stmt virtual table
-*/
-typedef struct stmt_vtab stmt_vtab;
-struct stmt_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- sqlite3 *db; /* Database connection for this stmt vtab */
-};
-
-/* stmt_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-typedef struct stmt_cursor stmt_cursor;
-struct stmt_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3 *db; /* Database connection for this cursor */
- sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */
- sqlite3_int64 iRowid; /* The rowid */
-};
-
-/*
-** The stmtConnect() method is invoked to create a new
-** stmt_vtab that describes the stmt virtual table.
-**
-** Think of this routine as the constructor for stmt_vtab objects.
-**
-** All this routine needs to do is:
-**
-** (1) Allocate the stmt_vtab object and initialize all fields.
-**
-** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-** result set of queries against stmt will look like.
-*/
-static int stmtConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- stmt_vtab *pNew;
- int rc;
-
-/* Column numbers */
-#define STMT_COLUMN_SQL 0 /* SQL for the statement */
-#define STMT_COLUMN_NCOL 1 /* Number of result columns */
-#define STMT_COLUMN_RO 2 /* True if read-only */
-#define STMT_COLUMN_BUSY 3 /* True if currently busy */
-#define STMT_COLUMN_NSCAN 4 /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
-#define STMT_COLUMN_NSORT 5 /* SQLITE_STMTSTATUS_SORT */
-#define STMT_COLUMN_NAIDX 6 /* SQLITE_STMTSTATUS_AUTOINDEX */
-#define STMT_COLUMN_NSTEP 7 /* SQLITE_STMTSTATUS_VM_STEP */
-#define STMT_COLUMN_REPREP 8 /* SQLITE_STMTSTATUS_REPREPARE */
-#define STMT_COLUMN_RUN 9 /* SQLITE_STMTSTATUS_RUN */
-#define STMT_COLUMN_MEM 10 /* SQLITE_STMTSTATUS_MEMUSED */
-
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
- "reprep,run,mem)");
- if( rc==SQLITE_OK ){
- pNew = sqlite3_malloc( sizeof(*pNew) );
- *ppVtab = (sqlite3_vtab*)pNew;
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- pNew->db = db;
- }
- return rc;
-}
-
-/*
-** This method is the destructor for stmt_cursor objects.
-*/
-static int stmtDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new stmt_cursor object.
-*/
-static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- stmt_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->db = ((stmt_vtab*)p)->db;
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Destructor for a stmt_cursor.
-*/
-static int stmtClose(sqlite3_vtab_cursor *cur){
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a stmt_cursor to its next row of output.
-*/
-static int stmtNext(sqlite3_vtab_cursor *cur){
- stmt_cursor *pCur = (stmt_cursor*)cur;
- pCur->iRowid++;
- pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt);
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the stmt_cursor
-** is currently pointing.
-*/
-static int stmtColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- stmt_cursor *pCur = (stmt_cursor*)cur;
- switch( i ){
- case STMT_COLUMN_SQL: {
- sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
- break;
- }
- case STMT_COLUMN_NCOL: {
- sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
- break;
- }
- case STMT_COLUMN_RO: {
- sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
- break;
- }
- case STMT_COLUMN_BUSY: {
- sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
- break;
- }
- case STMT_COLUMN_MEM: {
- i = SQLITE_STMTSTATUS_MEMUSED +
- STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
- /* Fall thru */
- }
- case STMT_COLUMN_NSCAN:
- case STMT_COLUMN_NSORT:
- case STMT_COLUMN_NAIDX:
- case STMT_COLUMN_NSTEP:
- case STMT_COLUMN_REPREP:
- case STMT_COLUMN_RUN: {
- sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
- i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** rowid is the same as the output value.
-*/
-static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- stmt_cursor *pCur = (stmt_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int stmtEof(sqlite3_vtab_cursor *cur){
- stmt_cursor *pCur = (stmt_cursor*)cur;
- return pCur->pStmt==0;
-}
-
-/*
-** This method is called to "rewind" the stmt_cursor object back
-** to the first row of output. This method is always called at least
-** once prior to any call to stmtColumn() or stmtRowid() or
-** stmtEof().
-*/
-static int stmtFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- stmt_cursor *pCur = (stmt_cursor *)pVtabCursor;
- pCur->pStmt = 0;
- pCur->iRowid = 0;
- return stmtNext(pVtabCursor);
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the stmt virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-*/
-static int stmtBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- pIdxInfo->estimatedCost = (double)500;
- pIdxInfo->estimatedRows = 500;
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** stmt virtual table.
-*/
-static sqlite3_module stmtModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- stmtConnect, /* xConnect */
- stmtBestIndex, /* xBestIndex */
- stmtDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- stmtOpen, /* xOpen - open a cursor */
- stmtClose, /* xClose - close a cursor */
- stmtFilter, /* xFilter - configure scan constraints */
- stmtNext, /* xNext - advance a cursor */
- stmtEof, /* xEof - check for end of scan */
- stmtColumn, /* xColumn - read data */
- stmtRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-int sqlite3StmtVtabInit(sqlite3 *db){
- int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_create_module(db, "sqlite_stmt", &stmtModule, 0);
-#endif
- return rc;
-}
-
-#ifndef SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_stmt_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3StmtVtabInit(db);
-#endif
- return rc;
-}
-#endif /* SQLITE_CORE */
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/templatevtab.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/templatevtab.c
deleted file mode 100644
index 95b5f60caba..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/templatevtab.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
-** 2018-04-19
-**
-** 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 a template virtual-table.
-** Developers can make a copy of this file as a baseline for writing
-** new virtual tables and/or table-valued functions.
-**
-** Steps for writing a new virtual table implementation:
-**
-** (1) Make a copy of this file. Perhaps call it "mynewvtab.c"
-**
-** (2) Replace this header comment with something appropriate for
-** the new virtual table
-**
-** (3) Change every occurrence of "templatevtab" to some other string
-** appropriate for the new virtual table. Ideally, the new string
-** should be the basename of the source file: "mynewvtab". Also
-** globally change "TEMPLATEVTAB" to "MYNEWVTAB".
-**
-** (4) Run a test compilation to make sure the unmodified virtual
-** table works.
-**
-** (5) Begin making incremental changes, testing as you go, to evolve
-** the new virtual table to do what you want it to do.
-**
-** This template is minimal, in the sense that it uses only the required
-** methods on the sqlite3_module object. As a result, templatevtab is
-** a read-only and eponymous-only table. Those limitation can be removed
-** by adding new methods.
-**
-** This template implements an eponymous-only virtual table with a rowid and
-** two columns named "a" and "b". The table as 10 rows with fixed integer
-** values. Usage example:
-**
-** SELECT rowid, a, b FROM templatevtab;
-*/
-#if !defined(SQLITEINT_H)
-#include "sqlite3ext.h"
-#endif
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-#include <assert.h>
-
-/* templatevtab_vtab is a subclass of sqlite3_vtab which is
-** underlying representation of the virtual table
-*/
-typedef struct templatevtab_vtab templatevtab_vtab;
-struct templatevtab_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- /* Add new fields here, as necessary */
-};
-
-/* templatevtab_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-typedef struct templatevtab_cursor templatevtab_cursor;
-struct templatevtab_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- /* Insert new fields here. For this templatevtab we only keep track
- ** of the rowid */
- sqlite3_int64 iRowid; /* The rowid */
-};
-
-/*
-** The templatevtabConnect() method is invoked to create a new
-** template virtual table.
-**
-** Think of this routine as the constructor for templatevtab_vtab objects.
-**
-** All this routine needs to do is:
-**
-** (1) Allocate the templatevtab_vtab object and initialize all fields.
-**
-** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-** result set of queries against the virtual table will look like.
-*/
-static int templatevtabConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- templatevtab_vtab *pNew;
- int rc;
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(a,b)"
- );
- /* For convenience, define symbolic names for the index to each column. */
-#define TEMPLATEVTAB_A 0
-#define TEMPLATEVTAB_B 1
- if( rc==SQLITE_OK ){
- pNew = sqlite3_malloc( sizeof(*pNew) );
- *ppVtab = (sqlite3_vtab*)pNew;
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- }
- return rc;
-}
-
-/*
-** This method is the destructor for templatevtab_vtab objects.
-*/
-static int templatevtabDisconnect(sqlite3_vtab *pVtab){
- templatevtab_vtab *p = (templatevtab_vtab*)pVtab;
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new templatevtab_cursor object.
-*/
-static int templatevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- templatevtab_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Destructor for a templatevtab_cursor.
-*/
-static int templatevtabClose(sqlite3_vtab_cursor *cur){
- templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a templatevtab_cursor to its next row of output.
-*/
-static int templatevtabNext(sqlite3_vtab_cursor *cur){
- templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
- pCur->iRowid++;
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the templatevtab_cursor
-** is currently pointing.
-*/
-static int templatevtabColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
- switch( i ){
- case TEMPLATEVTAB_A:
- sqlite3_result_int(ctx, 1000 + pCur->iRowid);
- break;
- default:
- assert( i==TEMPLATEVTAB_B );
- sqlite3_result_int(ctx, 2000 + pCur->iRowid);
- break;
- }
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** rowid is the same as the output value.
-*/
-static int templatevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int templatevtabEof(sqlite3_vtab_cursor *cur){
- templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
- return pCur->iRowid>=10;
-}
-
-/*
-** This method is called to "rewind" the templatevtab_cursor object back
-** to the first row of output. This method is always called at least
-** once prior to any call to templatevtabColumn() or templatevtabRowid() or
-** templatevtabEof().
-*/
-static int templatevtabFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- templatevtab_cursor *pCur = (templatevtab_cursor *)pVtabCursor;
- pCur->iRowid = 1;
- return SQLITE_OK;
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-*/
-static int templatevtabBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- pIdxInfo->estimatedCost = (double)10;
- pIdxInfo->estimatedRows = 10;
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** virtual table.
-*/
-static sqlite3_module templatevtabModule = {
- /* iVersion */ 0,
- /* xCreate */ 0,
- /* xConnect */ templatevtabConnect,
- /* xBestIndex */ templatevtabBestIndex,
- /* xDisconnect */ templatevtabDisconnect,
- /* xDestroy */ 0,
- /* xOpen */ templatevtabOpen,
- /* xClose */ templatevtabClose,
- /* xFilter */ templatevtabFilter,
- /* xNext */ templatevtabNext,
- /* xEof */ templatevtabEof,
- /* xColumn */ templatevtabColumn,
- /* xRowid */ templatevtabRowid,
- /* xUpdate */ 0,
- /* xBegin */ 0,
- /* xSync */ 0,
- /* xCommit */ 0,
- /* xRollback */ 0,
- /* xFindMethod */ 0,
- /* xRename */ 0,
- /* xSavepoint */ 0,
- /* xRelease */ 0,
- /* xRollbackTo */ 0
-};
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_templatevtab_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- rc = sqlite3_create_module(db, "templatevtab", &templatevtabModule, 0);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/totype.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/totype.c
deleted file mode 100644
index 5dc99f3d7dc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/totype.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
-** 2013-10-14
-**
-** 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 SQLite extension implements functions tointeger(X) and toreal(X).
-**
-** If X is an integer, real, or string value that can be
-** losslessly represented as an integer, then tointeger(X)
-** returns the corresponding integer value.
-** If X is an 8-byte BLOB then that blob is interpreted as
-** a signed two-compliment little-endian encoding of an integer
-** and tointeger(X) returns the corresponding integer value.
-** Otherwise tointeger(X) return NULL.
-**
-** If X is an integer, real, or string value that can be
-** convert into a real number, preserving at least 15 digits
-** of precision, then toreal(X) returns the corresponding real value.
-** If X is an 8-byte BLOB then that blob is interpreted as
-** a 64-bit IEEE754 big-endian floating point value
-** and toreal(X) returns the corresponding real value.
-** Otherwise toreal(X) return NULL.
-**
-** Note that tointeger(X) of an 8-byte BLOB assumes a little-endian
-** encoding whereas toreal(X) of an 8-byte BLOB assumes a big-endian
-** encoding.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-/*
-** Determine if this is running on a big-endian or little-endian
-** processor
-*/
-#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
- || defined(__x86_64) || defined(__x86_64__)
-# define TOTYPE_BIGENDIAN 0
-# define TOTYPE_LITTLEENDIAN 1
-#else
- const int totype_one = 1;
-# define TOTYPE_BIGENDIAN (*(char *)(&totype_one)==0)
-# define TOTYPE_LITTLEENDIAN (*(char *)(&totype_one)==1)
-#endif
-
-/*
-** Constants for the largest and smallest possible 64-bit signed integers.
-** These macros are designed to work correctly on both 32-bit and 64-bit
-** compilers.
-*/
-#ifndef LARGEST_INT64
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
-#endif
-
-#ifndef SMALLEST_INT64
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
-/*
-** Return TRUE if character c is a whitespace character
-*/
-static int totypeIsspace(unsigned char c){
- return c==' ' || c=='\t' || c=='\n' || c=='\v' || c=='\f' || c=='\r';
-}
-
-/*
-** Return TRUE if character c is a digit
-*/
-static int totypeIsdigit(unsigned char c){
- return c>='0' && c<='9';
-}
-
-/*
-** Compare the 19-character string zNum against the text representation
-** value 2^63: 9223372036854775808. Return negative, zero, or positive
-** if zNum is less than, equal to, or greater than the string.
-** Note that zNum must contain exactly 19 characters.
-**
-** Unlike memcmp() this routine is guaranteed to return the difference
-** in the values of the last digit if the only difference is in the
-** last digit. So, for example,
-**
-** totypeCompare2pow63("9223372036854775800")
-**
-** will return -8.
-*/
-static int totypeCompare2pow63(const char *zNum){
- int c = 0;
- int i;
- /* 012345678901234567 */
- const char *pow63 = "922337203685477580";
- for(i=0; c==0 && i<18; i++){
- c = (zNum[i]-pow63[i])*10;
- }
- if( c==0 ){
- c = zNum[18] - '8';
- }
- return c;
-}
-
-/*
-** Convert zNum to a 64-bit signed integer.
-**
-** If the zNum value is representable as a 64-bit twos-complement
-** integer, then write that value into *pNum and return 0.
-**
-** If zNum is exactly 9223372036854665808, return 2. This special
-** case is broken out because while 9223372036854665808 cannot be a
-** signed 64-bit integer, its negative -9223372036854665808 can be.
-**
-** If zNum is too big for a 64-bit integer and is not
-** 9223372036854665808 or if zNum contains any non-numeric text,
-** then return 1.
-**
-** The string is not necessarily zero-terminated.
-*/
-static int totypeAtoi64(const char *zNum, sqlite3_int64 *pNum, int length){
- sqlite3_uint64 u = 0;
- int neg = 0; /* assume positive */
- int i;
- int c = 0;
- int nonNum = 0;
- const char *zStart;
- const char *zEnd = zNum + length;
-
- while( zNum<zEnd && totypeIsspace(*zNum) ) zNum++;
- if( zNum<zEnd ){
- if( *zNum=='-' ){
- neg = 1;
- zNum++;
- }else if( *zNum=='+' ){
- zNum++;
- }
- }
- zStart = zNum;
- while( zNum<zEnd && zNum[0]=='0' ){ zNum++; } /* Skip leading zeros. */
- for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i++){
- u = u*10 + c - '0';
- }
- if( u>LARGEST_INT64 ){
- *pNum = SMALLEST_INT64;
- }else if( neg ){
- *pNum = -(sqlite3_int64)u;
- }else{
- *pNum = (sqlite3_int64)u;
- }
- if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19 || nonNum ){
- /* zNum is empty or contains non-numeric text or is longer
- ** than 19 digits (thus guaranteeing that it is too large) */
- return 1;
- }else if( i<19 ){
- /* Less than 19 digits, so we know that it fits in 64 bits */
- assert( u<=LARGEST_INT64 );
- return 0;
- }else{
- /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
- c = totypeCompare2pow63(zNum);
- if( c<0 ){
- /* zNum is less than 9223372036854775808 so it fits */
- assert( u<=LARGEST_INT64 );
- return 0;
- }else if( c>0 ){
- /* zNum is greater than 9223372036854775808 so it overflows */
- return 1;
- }else{
- /* zNum is exactly 9223372036854775808. Fits if negative. The
- ** special case 2 overflow if positive */
- assert( u-1==LARGEST_INT64 );
- assert( (*pNum)==SMALLEST_INT64 );
- return neg ? 0 : 2;
- }
- }
-}
-
-/*
-** The string z[] is an text representation of a real number.
-** Convert this string to a double and write it into *pResult.
-**
-** The string is not necessarily zero-terminated.
-**
-** Return TRUE if the result is a valid real number (or integer) and FALSE
-** if the string is empty or contains extraneous text. Valid numbers
-** are in one of these formats:
-**
-** [+-]digits[E[+-]digits]
-** [+-]digits.[digits][E[+-]digits]
-** [+-].digits[E[+-]digits]
-**
-** Leading and trailing whitespace is ignored for the purpose of determining
-** validity.
-**
-** If some prefix of the input string is a valid number, this routine
-** returns FALSE but it still converts the prefix and writes the result
-** into *pResult.
-*/
-static int totypeAtoF(const char *z, double *pResult, int length){
- const char *zEnd = z + length;
- /* sign * significand * (10 ^ (esign * exponent)) */
- int sign = 1; /* sign of significand */
- sqlite3_int64 s = 0; /* significand */
- int d = 0; /* adjust exponent for shifting decimal point */
- int esign = 1; /* sign of exponent */
- int e = 0; /* exponent */
- int eValid = 1; /* True exponent is either not used or is well-formed */
- double result;
- int nDigits = 0;
- int nonNum = 0;
-
- *pResult = 0.0; /* Default return value, in case of an error */
-
- /* skip leading spaces */
- while( z<zEnd && totypeIsspace(*z) ) z++;
- if( z>=zEnd ) return 0;
-
- /* get sign of significand */
- if( *z=='-' ){
- sign = -1;
- z++;
- }else if( *z=='+' ){
- z++;
- }
-
- /* skip leading zeroes */
- while( z<zEnd && z[0]=='0' ) z++, nDigits++;
-
- /* copy max significant digits to significand */
- while( z<zEnd && totypeIsdigit(*z) && s<((LARGEST_INT64-9)/10) ){
- s = s*10 + (*z - '0');
- z++, nDigits++;
- }
-
- /* skip non-significant significand digits
- ** (increase exponent by d to shift decimal left) */
- while( z<zEnd && totypeIsdigit(*z) ) z++, nDigits++, d++;
- if( z>=zEnd ) goto totype_atof_calc;
-
- /* if decimal point is present */
- if( *z=='.' ){
- z++;
- /* copy digits from after decimal to significand
- ** (decrease exponent by d to shift decimal right) */
- while( z<zEnd && totypeIsdigit(*z) && s<((LARGEST_INT64-9)/10) ){
- s = s*10 + (*z - '0');
- z++, nDigits++, d--;
- }
- /* skip non-significant digits */
- while( z<zEnd && totypeIsdigit(*z) ) z++, nDigits++;
- }
- if( z>=zEnd ) goto totype_atof_calc;
-
- /* if exponent is present */
- if( *z=='e' || *z=='E' ){
- z++;
- eValid = 0;
- if( z>=zEnd ) goto totype_atof_calc;
- /* get sign of exponent */
- if( *z=='-' ){
- esign = -1;
- z++;
- }else if( *z=='+' ){
- z++;
- }
- /* copy digits to exponent */
- while( z<zEnd && totypeIsdigit(*z) ){
- e = e<10000 ? (e*10 + (*z - '0')) : 10000;
- z++;
- eValid = 1;
- }
- }
-
- /* skip trailing spaces */
- if( nDigits && eValid ){
- while( z<zEnd && totypeIsspace(*z) ) z++;
- }
-
-totype_atof_calc:
- /* adjust exponent by d, and update sign */
- e = (e*esign) + d;
- if( e<0 ) {
- esign = -1;
- e *= -1;
- } else {
- esign = 1;
- }
-
- /* if 0 significand */
- if( !s ) {
- /* In the IEEE 754 standard, zero is signed.
- ** Add the sign if we've seen at least one digit */
- result = (sign<0 && nDigits) ? -(double)0 : (double)0;
- } else {
- /* attempt to reduce exponent */
- if( esign>0 ){
- while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
- }else{
- while( !(s%10) && e>0 ) e--,s/=10;
- }
-
- /* adjust the sign of significand */
- s = sign<0 ? -s : s;
-
- /* if exponent, scale significand as appropriate
- ** and store in result. */
- if( e ){
- double scale = 1.0;
- /* attempt to handle extremely small/large numbers better */
- if( e>307 && e<342 ){
- while( e%308 ) { scale *= 1.0e+1; e -= 1; }
- if( esign<0 ){
- result = s / scale;
- result /= 1.0e+308;
- }else{
- result = s * scale;
- result *= 1.0e+308;
- }
- }else if( e>=342 ){
- if( esign<0 ){
- result = 0.0*s;
- }else{
- result = 1e308*1e308*s; /* Infinity */
- }
- }else{
- /* 1.0e+22 is the largest power of 10 than can be
- ** represented exactly. */
- while( e%22 ) { scale *= 1.0e+1; e -= 1; }
- while( e>0 ) { scale *= 1.0e+22; e -= 22; }
- if( esign<0 ){
- result = s / scale;
- }else{
- result = s * scale;
- }
- }
- } else {
- result = (double)s;
- }
- }
-
- /* store the result */
- *pResult = result;
-
- /* return true if number and no extra non-whitespace chracters after */
- return z>=zEnd && nDigits>0 && eValid && nonNum==0;
-}
-
-/*
-** tointeger(X): If X is any value (integer, double, blob, or string) that
-** can be losslessly converted into an integer, then make the conversion and
-** return the result. Otherwise, return NULL.
-*/
-static void tointegerFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- assert( argc==1 );
- (void)argc;
- switch( sqlite3_value_type(argv[0]) ){
- case SQLITE_FLOAT: {
- double rVal = sqlite3_value_double(argv[0]);
- sqlite3_int64 iVal = (sqlite3_int64)rVal;
- if( rVal==(double)iVal ){
- sqlite3_result_int64(context, iVal);
- }
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_result_int64(context, sqlite3_value_int64(argv[0]));
- break;
- }
- case SQLITE_BLOB: {
- const unsigned char *zBlob = sqlite3_value_blob(argv[0]);
- if( zBlob ){
- int nBlob = sqlite3_value_bytes(argv[0]);
- if( nBlob==sizeof(sqlite3_int64) ){
- sqlite3_int64 iVal;
- if( TOTYPE_BIGENDIAN ){
- int i;
- unsigned char zBlobRev[sizeof(sqlite3_int64)];
- for(i=0; i<sizeof(sqlite3_int64); i++){
- zBlobRev[i] = zBlob[sizeof(sqlite3_int64)-1-i];
- }
- memcpy(&iVal, zBlobRev, sizeof(sqlite3_int64));
- }else{
- memcpy(&iVal, zBlob, sizeof(sqlite3_int64));
- }
- sqlite3_result_int64(context, iVal);
- }
- }
- break;
- }
- case SQLITE_TEXT: {
- const unsigned char *zStr = sqlite3_value_text(argv[0]);
- if( zStr ){
- int nStr = sqlite3_value_bytes(argv[0]);
- if( nStr && !totypeIsspace(zStr[0]) ){
- sqlite3_int64 iVal;
- if( !totypeAtoi64((const char*)zStr, &iVal, nStr) ){
- sqlite3_result_int64(context, iVal);
- }
- }
- }
- break;
- }
- default: {
- assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
- break;
- }
- }
-}
-
-/*
-** toreal(X): If X is any value (integer, double, blob, or string) that can
-** be losslessly converted into a real number, then do so and return that
-** real number. Otherwise return NULL.
-*/
-#if defined(_MSC_VER)
-#pragma warning(disable: 4748)
-#pragma optimize("", off)
-#endif
-static void torealFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- assert( argc==1 );
- (void)argc;
- switch( sqlite3_value_type(argv[0]) ){
- case SQLITE_FLOAT: {
- sqlite3_result_double(context, sqlite3_value_double(argv[0]));
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_int64 iVal = sqlite3_value_int64(argv[0]);
- double rVal = (double)iVal;
- if( iVal==(sqlite3_int64)rVal ){
- sqlite3_result_double(context, rVal);
- }
- break;
- }
- case SQLITE_BLOB: {
- const unsigned char *zBlob = sqlite3_value_blob(argv[0]);
- if( zBlob ){
- int nBlob = sqlite3_value_bytes(argv[0]);
- if( nBlob==sizeof(double) ){
- double rVal;
- if( TOTYPE_LITTLEENDIAN ){
- int i;
- unsigned char zBlobRev[sizeof(double)];
- for(i=0; i<sizeof(double); i++){
- zBlobRev[i] = zBlob[sizeof(double)-1-i];
- }
- memcpy(&rVal, zBlobRev, sizeof(double));
- }else{
- memcpy(&rVal, zBlob, sizeof(double));
- }
- sqlite3_result_double(context, rVal);
- }
- }
- break;
- }
- case SQLITE_TEXT: {
- const unsigned char *zStr = sqlite3_value_text(argv[0]);
- if( zStr ){
- int nStr = sqlite3_value_bytes(argv[0]);
- if( nStr && !totypeIsspace(zStr[0]) && !totypeIsspace(zStr[nStr-1]) ){
- double rVal;
- if( totypeAtoF((const char*)zStr, &rVal, nStr) ){
- sqlite3_result_double(context, rVal);
- return;
- }
- }
- }
- break;
- }
- default: {
- assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
- break;
- }
- }
-}
-#if defined(_MSC_VER)
-#pragma optimize("", on)
-#pragma warning(default: 4748)
-#endif
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_totype_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "tointeger", 1, SQLITE_UTF8, 0,
- tointegerFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "toreal", 1, SQLITE_UTF8, 0,
- torealFunc, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/unionvtab.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/unionvtab.c
deleted file mode 100644
index 94a5c8f013e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/unionvtab.c
+++ /dev/null
@@ -1,1381 +0,0 @@
-/*
-** 2017 July 15
-**
-** 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 contains the implementation of the "unionvtab" and "swarmvtab"
-** virtual tables. These modules provide read-only access to multiple tables,
-** possibly in multiple database files, via a single database object.
-** The source tables must have the following characteristics:
-**
-** * They must all be rowid tables (not VIRTUAL or WITHOUT ROWID
-** tables or views).
-**
-** * Each table must have the same set of columns, declared in
-** the same order and with the same declared types.
-**
-** * The tables must not feature a user-defined column named "_rowid_".
-**
-** * Each table must contain a distinct range of rowid values.
-**
-** The difference between the two virtual table modules is that for
-** "unionvtab", all source tables must be located in the main database or
-** in databases ATTACHed to the main database by the user. For "swarmvtab",
-** the tables may be located in any database file on disk. The "swarmvtab"
-** implementation takes care of opening and closing database files
-** automatically.
-**
-** UNIONVTAB
-**
-** A "unionvtab" virtual table is created as follows:
-**
-** CREATE VIRTUAL TABLE <name> USING unionvtab(<sql-statement>);
-**
-** The implementation evalutes <sql statement> whenever a unionvtab virtual
-** table is created or opened. It should return one row for each source
-** database table. The four columns required of each row are:
-**
-** 1. The name of the database containing the table ("main" or "temp" or
-** the name of an attached database). Or NULL to indicate that all
-** databases should be searched for the table in the usual fashion.
-**
-** 2. The name of the database table.
-**
-** 3. The smallest rowid in the range of rowids that may be stored in the
-** database table (an integer).
-**
-** 4. The largest rowid in the range of rowids that may be stored in the
-** database table (an integer).
-**
-** SWARMVTAB
-**
-** LEGACY SYNTAX:
-**
-** A "swarmvtab" virtual table is created similarly to a unionvtab table:
-**
-** CREATE VIRTUAL TABLE <name>
-** USING swarmvtab(<sql-statement>, <callback>);
-**
-** The difference is that for a swarmvtab table, the first column returned
-** by the <sql statement> must return a path or URI that can be used to open
-** the database file containing the source table. The <callback> option
-** is optional. If included, it is the name of an application-defined
-** SQL function that is invoked with the URI of the file, if the file
-** does not already exist on disk when required by swarmvtab.
-**
-** NEW SYNTAX:
-**
-** Using the new syntax, a swarmvtab table is created with:
-**
-** CREATE VIRTUAL TABLE <name> USING swarmvtab(
-** <sql-statement> [, <options>]
-** );
-**
-** where valid <options> are:
-**
-** missing=<udf-function-name>
-** openclose=<udf-function-name>
-** maxopen=<integer>
-** <sql-parameter>=<text-value>
-**
-** The <sql-statement> must return the same 4 columns as for a swarmvtab
-** table in legacy mode. However, it may also return a 5th column - the
-** "context" column. The text value returned in this column is not used
-** at all by the swarmvtab implementation, except that it is passed as
-** an additional argument to the two UDF functions that may be invoked
-** (see below).
-**
-** The "missing" option, if present, specifies the name of an SQL UDF
-** function to be invoked if a database file is not already present on
-** disk when required by swarmvtab. If the <sql-statement> did not provide
-** a context column, it is invoked as:
-**
-** SELECT <missing-udf>(<database filename/uri>);
-**
-** Or, if there was a context column:
-**
-** SELECT <missing-udf>(<database filename/uri>, <context>);
-**
-** The "openclose" option may also specify a UDF function. This function
-** is invoked right before swarmvtab opens a database, and right after
-** it closes one. The first argument - or first two arguments, if
-** <sql-statement> supplied the context column - is the same as for
-** the "missing" UDF. Following this, the UDF is passed integer value
-** 0 before a db is opened, and 1 right after it is closed. If both
-** a missing and openclose UDF is supplied, the application should expect
-** the following sequence of calls (for a single database):
-**
-** SELECT <openclose-udf>(<db filename>, <context>, 0);
-** if( db not already on disk ){
-** SELECT <missing-udf>(<db filename>, <context>);
-** }
-** ... swarmvtab uses database ...
-** SELECT <openclose-udf>(<db filename>, <context>, 1);
-**
-** The "maxopen" option is used to configure the maximum number of
-** database files swarmvtab will hold open simultaneously (default 9).
-**
-** If an option name begins with a ":" character, then it is assumed
-** to be an SQL parameter. In this case, the specified text value is
-** bound to the same variable of the <sql-statement> before it is
-** executed. It is an error of the named SQL parameter does not exist.
-** For example:
-**
-** CREATE VIRTUAL TABLE swarm USING swarmvtab(
-** 'SELECT :path || localfile, tbl, min, max FROM swarmdir',
-** :path='/home/user/databases/'
-** missing='missing_func'
-** );
-*/
-
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Largest and smallest possible 64-bit signed integers. These macros
-** copied from sqliteInt.h.
-*/
-#ifndef LARGEST_INT64
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
-#endif
-#ifndef SMALLEST_INT64
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
-/*
-** The following is also copied from sqliteInt.h. To facilitate coverage
-** testing.
-*/
-#ifndef ALWAYS
-# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
-# define ALWAYS(X) (1)
-# define NEVER(X) (0)
-# elif !defined(NDEBUG)
-# define ALWAYS(X) ((X)?1:(assert(0),0))
-# define NEVER(X) ((X)?(assert(0),1):0)
-# else
-# define ALWAYS(X) (X)
-# define NEVER(X) (X)
-# endif
-#endif
-
-/*
-** The swarmvtab module attempts to keep the number of open database files
-** at or below this limit. This may not be possible if there are too many
-** simultaneous queries.
-*/
-#define SWARMVTAB_MAX_OPEN 9
-
-typedef struct UnionCsr UnionCsr;
-typedef struct UnionTab UnionTab;
-typedef struct UnionSrc UnionSrc;
-
-/*
-** Each source table (row returned by the initialization query) is
-** represented by an instance of the following structure stored in the
-** UnionTab.aSrc[] array.
-*/
-struct UnionSrc {
- char *zDb; /* Database containing source table */
- char *zTab; /* Source table name */
- sqlite3_int64 iMin; /* Minimum rowid */
- sqlite3_int64 iMax; /* Maximum rowid */
-
- /* Fields used by swarmvtab only */
- char *zFile; /* Database file containing table zTab */
- char *zContext; /* Context string, if any */
- int nUser; /* Current number of users */
- sqlite3 *db; /* Database handle */
- UnionSrc *pNextClosable; /* Next in list of closable sources */
-};
-
-/*
-** Virtual table type for union vtab.
-*/
-struct UnionTab {
- sqlite3_vtab base; /* Base class - must be first */
- sqlite3 *db; /* Database handle */
- int bSwarm; /* 1 for "swarmvtab", 0 for "unionvtab" */
- int iPK; /* INTEGER PRIMARY KEY column, or -1 */
- int nSrc; /* Number of elements in the aSrc[] array */
- UnionSrc *aSrc; /* Array of source tables, sorted by rowid */
-
- /* Used by swarmvtab only */
- int bHasContext; /* Has context strings */
- char *zSourceStr; /* Expected unionSourceToStr() value */
- sqlite3_stmt *pNotFound; /* UDF to invoke if file not found on open */
- sqlite3_stmt *pOpenClose; /* UDF to invoke on open and close */
-
- UnionSrc *pClosable; /* First in list of closable sources */
- int nOpen; /* Current number of open sources */
- int nMaxOpen; /* Maximum number of open sources */
-};
-
-/*
-** Virtual table cursor type for union vtab.
-*/
-struct UnionCsr {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3_stmt *pStmt; /* SQL statement to run */
-
- /* Used by swarmvtab only */
- sqlite3_int64 iMaxRowid; /* Last rowid to visit */
- int iTab; /* Index of table read by pStmt */
-};
-
-/*
-** Given UnionTab table pTab and UnionSrc object pSrc, return the database
-** handle that should be used to access the table identified by pSrc. This
-** is the main db handle for "unionvtab" tables, or the source-specific
-** handle for "swarmvtab".
-*/
-#define unionGetDb(pTab, pSrc) ((pTab)->bSwarm ? (pSrc)->db : (pTab)->db)
-
-/*
-** If *pRc is other than SQLITE_OK when this function is called, it
-** always returns NULL. Otherwise, it attempts to allocate and return
-** a pointer to nByte bytes of zeroed memory. If the memory allocation
-** is attempted but fails, NULL is returned and *pRc is set to
-** SQLITE_NOMEM.
-*/
-static void *unionMalloc(int *pRc, int nByte){
- void *pRet;
- assert( nByte>0 );
- if( *pRc==SQLITE_OK ){
- pRet = sqlite3_malloc(nByte);
- if( pRet ){
- memset(pRet, 0, nByte);
- }else{
- *pRc = SQLITE_NOMEM;
- }
- }else{
- pRet = 0;
- }
- return pRet;
-}
-
-/*
-** If *pRc is other than SQLITE_OK when this function is called, it
-** always returns NULL. Otherwise, it attempts to allocate and return
-** a copy of the nul-terminated string passed as the second argument.
-** If the allocation is attempted but fails, NULL is returned and *pRc is
-** set to SQLITE_NOMEM.
-*/
-static char *unionStrdup(int *pRc, const char *zIn){
- char *zRet = 0;
- if( zIn ){
- int nByte = (int)strlen(zIn) + 1;
- zRet = unionMalloc(pRc, nByte);
- if( zRet ){
- memcpy(zRet, zIn, nByte);
- }
- }
- return zRet;
-}
-
-/*
-** If the first character of the string passed as the only argument to this
-** function is one of the 4 that may be used as an open quote character
-** in SQL, this function assumes that the input is a well-formed quoted SQL
-** string. In this case the string is dequoted in place.
-**
-** If the first character of the input is not an open quote, then this
-** function is a no-op.
-*/
-static void unionDequote(char *z){
- if( z ){
- char q = z[0];
-
- /* Set stack variable q to the close-quote character */
- if( q=='[' || q=='\'' || q=='"' || q=='`' ){
- int iIn = 1;
- int iOut = 0;
- if( q=='[' ) q = ']';
- while( ALWAYS(z[iIn]) ){
- if( z[iIn]==q ){
- if( z[iIn+1]!=q ){
- /* Character iIn was the close quote. */
- iIn++;
- break;
- }else{
- /* Character iIn and iIn+1 form an escaped quote character. Skip
- ** the input cursor past both and copy a single quote character
- ** to the output buffer. */
- iIn += 2;
- z[iOut++] = q;
- }
- }else{
- z[iOut++] = z[iIn++];
- }
- }
- z[iOut] = '\0';
- }
- }
-}
-
-/*
-** This function is a no-op if *pRc is set to other than SQLITE_OK when it
-** is called. NULL is returned in this case.
-**
-** Otherwise, the SQL statement passed as the third argument is prepared
-** against the database handle passed as the second. If the statement is
-** successfully prepared, a pointer to the new statement handle is
-** returned. It is the responsibility of the caller to eventually free the
-** statement by calling sqlite3_finalize(). Alternatively, if statement
-** compilation fails, NULL is returned, *pRc is set to an SQLite error
-** code and *pzErr may be set to an error message buffer allocated by
-** sqlite3_malloc().
-*/
-static sqlite3_stmt *unionPrepare(
- int *pRc, /* IN/OUT: Error code */
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL statement to prepare */
- char **pzErr /* OUT: Error message */
-){
- sqlite3_stmt *pRet = 0;
- assert( pzErr );
- if( *pRc==SQLITE_OK ){
- int rc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
- if( rc!=SQLITE_OK ){
- *pzErr = sqlite3_mprintf("sql error: %s", sqlite3_errmsg(db));
- *pRc = rc;
- }
- }
- return pRet;
-}
-
-/*
-** Like unionPrepare(), except prepare the results of vprintf(zFmt, ...)
-** instead of a constant SQL string.
-*/
-static sqlite3_stmt *unionPreparePrintf(
- int *pRc, /* IN/OUT: Error code */
- char **pzErr, /* OUT: Error message */
- sqlite3 *db, /* Database handle */
- const char *zFmt, /* printf() format string */
- ... /* Trailing printf args */
-){
- sqlite3_stmt *pRet = 0;
- char *zSql;
- va_list ap;
- va_start(ap, zFmt);
-
- zSql = sqlite3_vmprintf(zFmt, ap);
- if( *pRc==SQLITE_OK ){
- if( zSql==0 ){
- *pRc = SQLITE_NOMEM;
- }else{
- pRet = unionPrepare(pRc, db, zSql, pzErr);
- }
- }
- sqlite3_free(zSql);
-
- va_end(ap);
- return pRet;
-}
-
-
-/*
-** Call sqlite3_reset() on SQL statement pStmt. If *pRc is set to
-** SQLITE_OK when this function is called, then it is set to the
-** value returned by sqlite3_reset() before this function exits.
-** In this case, *pzErr may be set to point to an error message
-** buffer allocated by sqlite3_malloc().
-*/
-#if 0
-static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
- int rc = sqlite3_reset(pStmt);
- if( *pRc==SQLITE_OK ){
- *pRc = rc;
- if( rc ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt)));
- }
- }
-}
-#endif
-
-/*
-** Call sqlite3_finalize() on SQL statement pStmt. If *pRc is set to
-** SQLITE_OK when this function is called, then it is set to the
-** value returned by sqlite3_finalize() before this function exits.
-*/
-static void unionFinalize(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
- sqlite3 *db = sqlite3_db_handle(pStmt);
- int rc = sqlite3_finalize(pStmt);
- if( *pRc==SQLITE_OK ){
- *pRc = rc;
- if( rc ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }
- }
-}
-
-/*
-** If an "openclose" UDF was supplied when this virtual table was created,
-** invoke it now. The first argument passed is the name of the database
-** file for source pSrc. The second is integer value bClose.
-**
-** If successful, return SQLITE_OK. Otherwise an SQLite error code. In this
-** case if argument pzErr is not NULL, also set (*pzErr) to an English
-** language error message. The caller is responsible for eventually freeing
-** any error message using sqlite3_free().
-*/
-static int unionInvokeOpenClose(
- UnionTab *pTab,
- UnionSrc *pSrc,
- int bClose,
- char **pzErr
-){
- int rc = SQLITE_OK;
- if( pTab->pOpenClose ){
- sqlite3_bind_text(pTab->pOpenClose, 1, pSrc->zFile, -1, SQLITE_STATIC);
- if( pTab->bHasContext ){
- sqlite3_bind_text(pTab->pOpenClose, 2, pSrc->zContext, -1, SQLITE_STATIC);
- }
- sqlite3_bind_int(pTab->pOpenClose, 2+pTab->bHasContext, bClose);
- sqlite3_step(pTab->pOpenClose);
- if( SQLITE_OK!=(rc = sqlite3_reset(pTab->pOpenClose)) ){
- if( pzErr ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
- }
- }
- }
- return rc;
-}
-
-/*
-** This function is a no-op for unionvtab. For swarmvtab, it attempts to
-** close open database files until at most nMax are open. An SQLite error
-** code is returned if an error occurs, or SQLITE_OK otherwise.
-*/
-static void unionCloseSources(UnionTab *pTab, int nMax){
- while( pTab->pClosable && pTab->nOpen>nMax ){
- UnionSrc *p;
- UnionSrc **pp;
- for(pp=&pTab->pClosable; (*pp)->pNextClosable; pp=&(*pp)->pNextClosable);
- p = *pp;
- assert( p->db );
- sqlite3_close(p->db);
- p->db = 0;
- *pp = 0;
- pTab->nOpen--;
- unionInvokeOpenClose(pTab, p, 1, 0);
- }
-}
-
-/*
-** xDisconnect method.
-*/
-static int unionDisconnect(sqlite3_vtab *pVtab){
- if( pVtab ){
- UnionTab *pTab = (UnionTab*)pVtab;
- int i;
- for(i=0; i<pTab->nSrc; i++){
- UnionSrc *pSrc = &pTab->aSrc[i];
- int bHaveSrcDb = (pSrc->db!=0);
- sqlite3_close(pSrc->db);
- if( bHaveSrcDb ){
- unionInvokeOpenClose(pTab, pSrc, 1, 0);
- }
- sqlite3_free(pSrc->zDb);
- sqlite3_free(pSrc->zTab);
- sqlite3_free(pSrc->zFile);
- sqlite3_free(pSrc->zContext);
- }
- sqlite3_finalize(pTab->pNotFound);
- sqlite3_finalize(pTab->pOpenClose);
- sqlite3_free(pTab->zSourceStr);
- sqlite3_free(pTab->aSrc);
- sqlite3_free(pTab);
- }
- return SQLITE_OK;
-}
-
-/*
-** Check that the table identified by pSrc is a rowid table. If not,
-** return SQLITE_ERROR and set (*pzErr) to point to an English language
-** error message. If the table is a rowid table and no error occurs,
-** return SQLITE_OK and leave (*pzErr) unmodified.
-*/
-static int unionIsIntkeyTable(
- sqlite3 *db, /* Database handle */
- UnionSrc *pSrc, /* Source table to test */
- char **pzErr /* OUT: Error message */
-){
- int bPk = 0;
- const char *zType = 0;
- int rc;
-
- sqlite3_table_column_metadata(
- db, pSrc->zDb, pSrc->zTab, "_rowid_", &zType, 0, 0, &bPk, 0
- );
- rc = sqlite3_errcode(db);
- if( rc==SQLITE_ERROR
- || (rc==SQLITE_OK && (!bPk || sqlite3_stricmp("integer", zType)))
- ){
- rc = SQLITE_ERROR;
- *pzErr = sqlite3_mprintf("no such rowid table: %s%s%s",
- (pSrc->zDb ? pSrc->zDb : ""),
- (pSrc->zDb ? "." : ""),
- pSrc->zTab
- );
- }
- return rc;
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. In this case it returns NULL.
-**
-** Otherwise, this function checks that the source table passed as the
-** second argument (a) exists, (b) is not a view and (c) has a column
-** named "_rowid_" of type "integer" that is the primary key.
-** If this is not the case, *pRc is set to SQLITE_ERROR and NULL is
-** returned.
-**
-** Finally, if the source table passes the checks above, a nul-terminated
-** string describing the column names and types belonging to the source
-** table is returned. Tables with the same set of column names and types
-** cause this function to return identical strings. Is is the responsibility
-** of the caller to free the returned string using sqlite3_free() when
-** it is no longer required.
-*/
-static char *unionSourceToStr(
- int *pRc, /* IN/OUT: Error code */
- UnionTab *pTab, /* Virtual table object */
- UnionSrc *pSrc, /* Source table to test */
- char **pzErr /* OUT: Error message */
-){
- char *zRet = 0;
- if( *pRc==SQLITE_OK ){
- sqlite3 *db = unionGetDb(pTab, pSrc);
- int rc = unionIsIntkeyTable(db, pSrc, pzErr);
- sqlite3_stmt *pStmt = unionPrepare(&rc, db,
- "SELECT group_concat(quote(name) || '.' || quote(type)) "
- "FROM pragma_table_info(?, ?)", pzErr
- );
- if( rc==SQLITE_OK ){
- sqlite3_bind_text(pStmt, 1, pSrc->zTab, -1, SQLITE_STATIC);
- sqlite3_bind_text(pStmt, 2, pSrc->zDb, -1, SQLITE_STATIC);
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- const char *z = (const char*)sqlite3_column_text(pStmt, 0);
- zRet = unionStrdup(&rc, z);
- }
- unionFinalize(&rc, pStmt, pzErr);
- }
- *pRc = rc;
- }
-
- return zRet;
-}
-
-/*
-** Check that all configured source tables exist and have the same column
-** names and datatypes. If this is not the case, or if some other error
-** occurs, return an SQLite error code. In this case *pzErr may be set
-** to point to an error message buffer allocated by sqlite3_mprintf().
-** Or, if no problems regarding the source tables are detected and no
-** other error occurs, SQLITE_OK is returned.
-*/
-static int unionSourceCheck(UnionTab *pTab, char **pzErr){
- int rc = SQLITE_OK;
- char *z0 = 0;
- int i;
-
- assert( *pzErr==0 );
- z0 = unionSourceToStr(&rc, pTab, &pTab->aSrc[0], pzErr);
- for(i=1; i<pTab->nSrc; i++){
- char *z = unionSourceToStr(&rc, pTab, &pTab->aSrc[i], pzErr);
- if( rc==SQLITE_OK && sqlite3_stricmp(z, z0) ){
- *pzErr = sqlite3_mprintf("source table schema mismatch");
- rc = SQLITE_ERROR;
- }
- sqlite3_free(z);
- }
- sqlite3_free(z0);
-
- return rc;
-}
-
-/*
-** Try to open the swarmvtab database. If initially unable, invoke the
-** not-found callback UDF and then try again.
-*/
-static int unionOpenDatabaseInner(UnionTab *pTab, UnionSrc *pSrc, char **pzErr){
- static const int openFlags = SQLITE_OPEN_READONLY | SQLITE_OPEN_URI;
- int rc;
-
- rc = unionInvokeOpenClose(pTab, pSrc, 0, pzErr);
- if( rc!=SQLITE_OK ) return rc;
-
- rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0);
- if( rc==SQLITE_OK ) return rc;
- if( pTab->pNotFound ){
- sqlite3_close(pSrc->db);
- pSrc->db = 0;
- sqlite3_bind_text(pTab->pNotFound, 1, pSrc->zFile, -1, SQLITE_STATIC);
- if( pTab->bHasContext ){
- sqlite3_bind_text(pTab->pNotFound, 2, pSrc->zContext, -1, SQLITE_STATIC);
- }
- sqlite3_step(pTab->pNotFound);
- if( SQLITE_OK!=(rc = sqlite3_reset(pTab->pNotFound)) ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
- return rc;
- }
- rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0);
- }
- if( rc!=SQLITE_OK ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pSrc->db));
- }
- return rc;
-}
-
-/*
-** This function may only be called for swarmvtab tables. The results of
-** calling it on a unionvtab table are undefined.
-**
-** For a swarmvtab table, this function ensures that source database iSrc
-** is open. If the database is opened successfully and the schema is as
-** expected, or if it is already open when this function is called, SQLITE_OK
-** is returned.
-**
-** Alternatively If an error occurs while opening the databases, or if the
-** database schema is unsuitable, an SQLite error code is returned and (*pzErr)
-** may be set to point to an English language error message. In this case it is
-** the responsibility of the caller to eventually free the error message buffer
-** using sqlite3_free().
-*/
-static int unionOpenDatabase(UnionTab *pTab, int iSrc, char **pzErr){
- int rc = SQLITE_OK;
- UnionSrc *pSrc = &pTab->aSrc[iSrc];
-
- assert( pTab->bSwarm && iSrc<pTab->nSrc );
- if( pSrc->db==0 ){
- unionCloseSources(pTab, pTab->nMaxOpen-1);
- rc = unionOpenDatabaseInner(pTab, pSrc, pzErr);
- if( rc==SQLITE_OK ){
- char *z = unionSourceToStr(&rc, pTab, pSrc, pzErr);
- if( rc==SQLITE_OK ){
- if( pTab->zSourceStr==0 ){
- pTab->zSourceStr = z;
- }else{
- if( sqlite3_stricmp(z, pTab->zSourceStr) ){
- *pzErr = sqlite3_mprintf("source table schema mismatch");
- rc = SQLITE_ERROR;
- }
- sqlite3_free(z);
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- pSrc->pNextClosable = pTab->pClosable;
- pTab->pClosable = pSrc;
- pTab->nOpen++;
- }else{
- sqlite3_close(pSrc->db);
- pSrc->db = 0;
- unionInvokeOpenClose(pTab, pSrc, 1, 0);
- }
- }
-
- return rc;
-}
-
-
-/*
-** This function is a no-op for unionvtab tables. For swarmvtab, increment
-** the reference count for source table iTab. If the reference count was
-** zero before it was incremented, also remove the source from the closable
-** list.
-*/
-static void unionIncrRefcount(UnionTab *pTab, int iTab){
- if( pTab->bSwarm ){
- UnionSrc *pSrc = &pTab->aSrc[iTab];
- assert( pSrc->nUser>=0 && pSrc->db );
- if( pSrc->nUser==0 ){
- UnionSrc **pp;
- for(pp=&pTab->pClosable; *pp!=pSrc; pp=&(*pp)->pNextClosable);
- *pp = pSrc->pNextClosable;
- pSrc->pNextClosable = 0;
- }
- pSrc->nUser++;
- }
-}
-
-/*
-** Finalize the SQL statement pCsr->pStmt and return the result.
-**
-** If this is a swarmvtab table (not unionvtab) and pCsr->pStmt was not
-** NULL when this function was called, also decrement the reference
-** count on the associated source table. If this means the source tables
-** refcount is now zero, add it to the closable list.
-*/
-static int unionFinalizeCsrStmt(UnionCsr *pCsr){
- int rc = SQLITE_OK;
- if( pCsr->pStmt ){
- UnionTab *pTab = (UnionTab*)pCsr->base.pVtab;
- UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
- rc = sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- if( pTab->bSwarm ){
- pSrc->nUser--;
- assert( pSrc->nUser>=0 );
- if( pSrc->nUser==0 ){
- pSrc->pNextClosable = pTab->pClosable;
- pTab->pClosable = pSrc;
- }
- unionCloseSources(pTab, pTab->nMaxOpen);
- }
- }
- return rc;
-}
-
-/*
-** Return true if the argument is a space, tab, CR or LF character.
-*/
-static int union_isspace(char c){
- return (c==' ' || c=='\n' || c=='\r' || c=='\t');
-}
-
-/*
-** Return true if the argument is an alphanumeric character in the
-** ASCII range.
-*/
-static int union_isidchar(char c){
- return ((c>='a' && c<='z') || (c>='A' && c<'Z') || (c>='0' && c<='9'));
-}
-
-/*
-** This function is called to handle all arguments following the first
-** (the SQL statement) passed to a swarmvtab (not unionvtab) CREATE
-** VIRTUAL TABLE statement. It may bind parameters to the SQL statement
-** or configure members of the UnionTab object passed as the second
-** argument.
-**
-** Refer to header comments at the top of this file for a description
-** of the arguments parsed.
-**
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. Otherwise, if an error occurs, *pRc is set to an SQLite error
-** code. In this case *pzErr may be set to point to a buffer containing
-** an English language error message. It is the responsibility of the
-** caller to eventually free the buffer using sqlite3_free().
-*/
-static void unionConfigureVtab(
- int *pRc, /* IN/OUT: Error code */
- UnionTab *pTab, /* Table to configure */
- sqlite3_stmt *pStmt, /* SQL statement to find sources */
- int nArg, /* Number of entries in azArg[] array */
- const char * const *azArg, /* Array of arguments to consider */
- char **pzErr /* OUT: Error message */
-){
- int rc = *pRc;
- int i;
- if( rc==SQLITE_OK ){
- pTab->bHasContext = (sqlite3_column_count(pStmt)>4);
- }
- for(i=0; rc==SQLITE_OK && i<nArg; i++){
- char *zArg = unionStrdup(&rc, azArg[i]);
- if( zArg ){
- int nOpt = 0; /* Size of option name in bytes */
- char *zOpt; /* Pointer to option name */
- char *zVal; /* Pointer to value */
-
- unionDequote(zArg);
- zOpt = zArg;
- while( union_isspace(*zOpt) ) zOpt++;
- zVal = zOpt;
- if( *zVal==':' ) zVal++;
- while( union_isidchar(*zVal) ) zVal++;
- nOpt = (int)(zVal-zOpt);
-
- while( union_isspace(*zVal) ) zVal++;
- if( *zVal=='=' ){
- zOpt[nOpt] = '\0';
- zVal++;
- while( union_isspace(*zVal) ) zVal++;
- zVal = unionStrdup(&rc, zVal);
- if( zVal ){
- unionDequote(zVal);
- if( zOpt[0]==':' ){
- /* A value to bind to the SQL statement */
- int iParam = sqlite3_bind_parameter_index(pStmt, zOpt);
- if( iParam==0 ){
- *pzErr = sqlite3_mprintf(
- "swarmvtab: no such SQL parameter: %s", zOpt
- );
- rc = SQLITE_ERROR;
- }else{
- rc = sqlite3_bind_text(pStmt, iParam, zVal, -1, SQLITE_TRANSIENT);
- }
- }else if( nOpt==7 && 0==sqlite3_strnicmp(zOpt, "maxopen", 7) ){
- pTab->nMaxOpen = atoi(zVal);
- if( pTab->nMaxOpen<=0 ){
- *pzErr = sqlite3_mprintf("swarmvtab: illegal maxopen value");
- rc = SQLITE_ERROR;
- }
- }else if( nOpt==7 && 0==sqlite3_strnicmp(zOpt, "missing", 7) ){
- if( pTab->pNotFound ){
- *pzErr = sqlite3_mprintf(
- "swarmvtab: duplicate \"missing\" option");
- rc = SQLITE_ERROR;
- }else{
- pTab->pNotFound = unionPreparePrintf(&rc, pzErr, pTab->db,
- "SELECT \"%w\"(?%s)", zVal, pTab->bHasContext ? ",?" : ""
- );
- }
- }else if( nOpt==9 && 0==sqlite3_strnicmp(zOpt, "openclose", 9) ){
- if( pTab->pOpenClose ){
- *pzErr = sqlite3_mprintf(
- "swarmvtab: duplicate \"openclose\" option");
- rc = SQLITE_ERROR;
- }else{
- pTab->pOpenClose = unionPreparePrintf(&rc, pzErr, pTab->db,
- "SELECT \"%w\"(?,?%s)", zVal, pTab->bHasContext ? ",?" : ""
- );
- }
- }else{
- *pzErr = sqlite3_mprintf("swarmvtab: unrecognized option: %s",zOpt);
- rc = SQLITE_ERROR;
- }
- sqlite3_free(zVal);
- }
- }else{
- if( i==0 && nArg==1 ){
- pTab->pNotFound = unionPreparePrintf(&rc, pzErr, pTab->db,
- "SELECT \"%w\"(?)", zArg
- );
- }else{
- *pzErr = sqlite3_mprintf( "swarmvtab: parse error: %s", azArg[i]);
- rc = SQLITE_ERROR;
- }
- }
- sqlite3_free(zArg);
- }
- }
- *pRc = rc;
-}
-
-/*
-** xConnect/xCreate method.
-**
-** The argv[] array contains the following:
-**
-** argv[0] -> module name ("unionvtab" or "swarmvtab")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[3] -> SQL statement
-** argv[4] -> not-found callback UDF name
-*/
-static int unionConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- UnionTab *pTab = 0;
- int rc = SQLITE_OK;
- int bSwarm = (pAux==0 ? 0 : 1);
- const char *zVtab = (bSwarm ? "swarmvtab" : "unionvtab");
-
- if( sqlite3_stricmp("temp", argv[1]) ){
- /* unionvtab tables may only be created in the temp schema */
- *pzErr = sqlite3_mprintf("%s tables must be created in TEMP schema", zVtab);
- rc = SQLITE_ERROR;
- }else if( argc<4 || (argc>4 && bSwarm==0) ){
- *pzErr = sqlite3_mprintf("wrong number of arguments for %s", zVtab);
- rc = SQLITE_ERROR;
- }else{
- int nAlloc = 0; /* Allocated size of pTab->aSrc[] */
- sqlite3_stmt *pStmt = 0; /* Argument statement */
- char *zArg = unionStrdup(&rc, argv[3]); /* Copy of argument to CVT */
-
- /* Prepare the SQL statement. Instead of executing it directly, sort
- ** the results by the "minimum rowid" field. This makes it easier to
- ** check that there are no rowid range overlaps between source tables
- ** and that the UnionTab.aSrc[] array is always sorted by rowid. */
- unionDequote(zArg);
- pStmt = unionPreparePrintf(&rc, pzErr, db,
- "SELECT * FROM (%z) ORDER BY 3", zArg
- );
-
- /* Allocate the UnionTab structure */
- pTab = unionMalloc(&rc, sizeof(UnionTab));
- if( pTab ){
- assert( rc==SQLITE_OK );
- pTab->db = db;
- pTab->bSwarm = bSwarm;
- pTab->nMaxOpen = SWARMVTAB_MAX_OPEN;
- }
-
- /* Parse other CVT arguments, if any */
- if( bSwarm ){
- unionConfigureVtab(&rc, pTab, pStmt, argc-4, &argv[4], pzErr);
- }
-
- /* Iterate through the rows returned by the SQL statement specified
- ** as an argument to the CREATE VIRTUAL TABLE statement. */
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
- const char *zTab = (const char*)sqlite3_column_text(pStmt, 1);
- sqlite3_int64 iMin = sqlite3_column_int64(pStmt, 2);
- sqlite3_int64 iMax = sqlite3_column_int64(pStmt, 3);
- UnionSrc *pSrc;
-
- /* Grow the pTab->aSrc[] array if required. */
- if( nAlloc<=pTab->nSrc ){
- int nNew = nAlloc ? nAlloc*2 : 8;
- UnionSrc *aNew = (UnionSrc*)sqlite3_realloc(
- pTab->aSrc, nNew*sizeof(UnionSrc)
- );
- if( aNew==0 ){
- rc = SQLITE_NOMEM;
- break;
- }else{
- memset(&aNew[pTab->nSrc], 0, (nNew-pTab->nSrc)*sizeof(UnionSrc));
- pTab->aSrc = aNew;
- nAlloc = nNew;
- }
- }
-
- /* Check for problems with the specified range of rowids */
- if( iMax<iMin || (pTab->nSrc>0 && iMin<=pTab->aSrc[pTab->nSrc-1].iMax) ){
- *pzErr = sqlite3_mprintf("rowid range mismatch error");
- rc = SQLITE_ERROR;
- }
-
- if( rc==SQLITE_OK ){
- pSrc = &pTab->aSrc[pTab->nSrc++];
- pSrc->zTab = unionStrdup(&rc, zTab);
- pSrc->iMin = iMin;
- pSrc->iMax = iMax;
- if( bSwarm ){
- pSrc->zFile = unionStrdup(&rc, zDb);
- }else{
- pSrc->zDb = unionStrdup(&rc, zDb);
- }
- if( pTab->bHasContext ){
- const char *zContext = (const char*)sqlite3_column_text(pStmt, 4);
- pSrc->zContext = unionStrdup(&rc, zContext);
- }
- }
- }
- unionFinalize(&rc, pStmt, pzErr);
- pStmt = 0;
-
- /* It is an error if the SELECT statement returned zero rows. If only
- ** because there is no way to determine the schema of the virtual
- ** table in this case. */
- if( rc==SQLITE_OK && pTab->nSrc==0 ){
- *pzErr = sqlite3_mprintf("no source tables configured");
- rc = SQLITE_ERROR;
- }
-
- /* For unionvtab, verify that all source tables exist and have
- ** compatible schemas. For swarmvtab, attach the first database and
- ** check that the first table is a rowid table only. */
- if( rc==SQLITE_OK ){
- if( bSwarm ){
- rc = unionOpenDatabase(pTab, 0, pzErr);
- }else{
- rc = unionSourceCheck(pTab, pzErr);
- }
- }
-
- /* Compose a CREATE TABLE statement and pass it to declare_vtab() */
- if( rc==SQLITE_OK ){
- UnionSrc *pSrc = &pTab->aSrc[0];
- sqlite3 *tdb = unionGetDb(pTab, pSrc);
- pStmt = unionPreparePrintf(&rc, pzErr, tdb, "SELECT "
- "'CREATE TABLE xyz('"
- " || group_concat(quote(name) || ' ' || type, ', ')"
- " || ')',"
- "max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 "
- "FROM pragma_table_info(%Q, ?)",
- pSrc->zTab, pSrc->zDb
- );
- }
- if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- const char *zDecl = (const char*)sqlite3_column_text(pStmt, 0);
- rc = sqlite3_declare_vtab(db, zDecl);
- pTab->iPK = sqlite3_column_int(pStmt, 1);
- }
-
- unionFinalize(&rc, pStmt, pzErr);
- }
-
- if( rc!=SQLITE_OK ){
- unionDisconnect((sqlite3_vtab*)pTab);
- pTab = 0;
- }
-
- *ppVtab = (sqlite3_vtab*)pTab;
- return rc;
-}
-
-/*
-** xOpen
-*/
-static int unionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- UnionCsr *pCsr;
- int rc = SQLITE_OK;
- (void)p; /* Suppress harmless warning */
- pCsr = (UnionCsr*)unionMalloc(&rc, sizeof(UnionCsr));
- *ppCursor = &pCsr->base;
- return rc;
-}
-
-/*
-** xClose
-*/
-static int unionClose(sqlite3_vtab_cursor *cur){
- UnionCsr *pCsr = (UnionCsr*)cur;
- unionFinalizeCsrStmt(pCsr);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** This function does the work of the xNext() method. Except that, if it
-** returns SQLITE_ROW, it should be called again within the same xNext()
-** method call. See unionNext() for details.
-*/
-static int doUnionNext(UnionCsr *pCsr){
- int rc = SQLITE_OK;
- assert( pCsr->pStmt );
- if( sqlite3_step(pCsr->pStmt)!=SQLITE_ROW ){
- UnionTab *pTab = (UnionTab*)pCsr->base.pVtab;
- rc = unionFinalizeCsrStmt(pCsr);
- if( rc==SQLITE_OK && pTab->bSwarm ){
- pCsr->iTab++;
- if( pCsr->iTab<pTab->nSrc ){
- UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
- if( pCsr->iMaxRowid>=pSrc->iMin ){
- /* It is necessary to scan the next table. */
- rc = unionOpenDatabase(pTab, pCsr->iTab, &pTab->base.zErrMsg);
- pCsr->pStmt = unionPreparePrintf(&rc, &pTab->base.zErrMsg, pSrc->db,
- "SELECT rowid, * FROM %Q %s %lld",
- pSrc->zTab,
- (pSrc->iMax>pCsr->iMaxRowid ? "WHERE _rowid_ <=" : "-- "),
- pCsr->iMaxRowid
- );
- if( rc==SQLITE_OK ){
- assert( pCsr->pStmt );
- unionIncrRefcount(pTab, pCsr->iTab);
- rc = SQLITE_ROW;
- }
- }
- }
- }
- }
-
- return rc;
-}
-
-/*
-** xNext
-*/
-static int unionNext(sqlite3_vtab_cursor *cur){
- int rc;
- do {
- rc = doUnionNext((UnionCsr*)cur);
- }while( rc==SQLITE_ROW );
- return rc;
-}
-
-/*
-** xColumn
-*/
-static int unionColumn(
- sqlite3_vtab_cursor *cur,
- sqlite3_context *ctx,
- int i
-){
- UnionCsr *pCsr = (UnionCsr*)cur;
- sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1));
- return SQLITE_OK;
-}
-
-/*
-** xRowid
-*/
-static int unionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- UnionCsr *pCsr = (UnionCsr*)cur;
- *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
- return SQLITE_OK;
-}
-
-/*
-** xEof
-*/
-static int unionEof(sqlite3_vtab_cursor *cur){
- UnionCsr *pCsr = (UnionCsr*)cur;
- return pCsr->pStmt==0;
-}
-
-/*
-** xFilter
-*/
-static int unionFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- UnionTab *pTab = (UnionTab*)(pVtabCursor->pVtab);
- UnionCsr *pCsr = (UnionCsr*)pVtabCursor;
- int rc = SQLITE_OK;
- int i;
- char *zSql = 0;
- int bZero = 0;
-
- sqlite3_int64 iMin = SMALLEST_INT64;
- sqlite3_int64 iMax = LARGEST_INT64;
-
- assert( idxNum==0
- || idxNum==SQLITE_INDEX_CONSTRAINT_EQ
- || idxNum==SQLITE_INDEX_CONSTRAINT_LE
- || idxNum==SQLITE_INDEX_CONSTRAINT_GE
- || idxNum==SQLITE_INDEX_CONSTRAINT_LT
- || idxNum==SQLITE_INDEX_CONSTRAINT_GT
- || idxNum==(SQLITE_INDEX_CONSTRAINT_GE|SQLITE_INDEX_CONSTRAINT_LE)
- );
-
- (void)idxStr; /* Suppress harmless warning */
-
- if( idxNum==SQLITE_INDEX_CONSTRAINT_EQ ){
- assert( argc==1 );
- iMin = iMax = sqlite3_value_int64(argv[0]);
- }else{
-
- if( idxNum & (SQLITE_INDEX_CONSTRAINT_LE|SQLITE_INDEX_CONSTRAINT_LT) ){
- assert( argc>=1 );
- iMax = sqlite3_value_int64(argv[0]);
- if( idxNum & SQLITE_INDEX_CONSTRAINT_LT ){
- if( iMax==SMALLEST_INT64 ){
- bZero = 1;
- }else{
- iMax--;
- }
- }
- }
-
- if( idxNum & (SQLITE_INDEX_CONSTRAINT_GE|SQLITE_INDEX_CONSTRAINT_GT) ){
- assert( argc>=1 );
- iMin = sqlite3_value_int64(argv[argc-1]);
- if( idxNum & SQLITE_INDEX_CONSTRAINT_GT ){
- if( iMin==LARGEST_INT64 ){
- bZero = 1;
- }else{
- iMin++;
- }
- }
- }
- }
-
- unionFinalizeCsrStmt(pCsr);
- if( bZero ){
- return SQLITE_OK;
- }
-
- for(i=0; i<pTab->nSrc; i++){
- UnionSrc *pSrc = &pTab->aSrc[i];
- if( iMin>pSrc->iMax || iMax<pSrc->iMin ){
- continue;
- }
-
- zSql = sqlite3_mprintf("%z%sSELECT rowid, * FROM %s%q%s%Q"
- , zSql
- , (zSql ? " UNION ALL " : "")
- , (pSrc->zDb ? "'" : "")
- , (pSrc->zDb ? pSrc->zDb : "")
- , (pSrc->zDb ? "'." : "")
- , pSrc->zTab
- );
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- break;
- }
-
- if( iMin==iMax ){
- zSql = sqlite3_mprintf("%z WHERE rowid=%lld", zSql, iMin);
- }else{
- const char *zWhere = "WHERE";
- if( iMin!=SMALLEST_INT64 && iMin>pSrc->iMin ){
- zSql = sqlite3_mprintf("%z WHERE rowid>=%lld", zSql, iMin);
- zWhere = "AND";
- }
- if( iMax!=LARGEST_INT64 && iMax<pSrc->iMax ){
- zSql = sqlite3_mprintf("%z %s rowid<=%lld", zSql, zWhere, iMax);
- }
- }
-
- if( pTab->bSwarm ){
- pCsr->iTab = i;
- pCsr->iMaxRowid = iMax;
- rc = unionOpenDatabase(pTab, i, &pTab->base.zErrMsg);
- break;
- }
- }
-
- if( zSql==0 ){
- return rc;
- }else{
- sqlite3 *db = unionGetDb(pTab, &pTab->aSrc[pCsr->iTab]);
- pCsr->pStmt = unionPrepare(&rc, db, zSql, &pTab->base.zErrMsg);
- if( pCsr->pStmt ){
- unionIncrRefcount(pTab, pCsr->iTab);
- }
- sqlite3_free(zSql);
- }
- if( rc!=SQLITE_OK ) return rc;
- return unionNext(pVtabCursor);
-}
-
-/*
-** xBestIndex.
-**
-** This implementation searches for constraints on the rowid field. EQ,
-** LE, LT, GE and GT are handled.
-**
-** If there is an EQ comparison, then idxNum is set to INDEX_CONSTRAINT_EQ.
-** In this case the only argument passed to xFilter is the rhs of the ==
-** operator.
-**
-** Otherwise, if an LE or LT constraint is found, then the INDEX_CONSTRAINT_LE
-** or INDEX_CONSTRAINT_LT (but not both) bit is set in idxNum. The first
-** argument to xFilter is the rhs of the <= or < operator. Similarly, if
-** an GE or GT constraint is found, then the INDEX_CONSTRAINT_GE or
-** INDEX_CONSTRAINT_GT bit is set in idxNum. The rhs of the >= or > operator
-** is passed as either the first or second argument to xFilter, depending
-** on whether or not there is also a LT|LE constraint.
-*/
-static int unionBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- UnionTab *pTab = (UnionTab*)tab;
- int iEq = -1;
- int iLt = -1;
- int iGt = -1;
- int i;
-
- for(i=0; i<pIdxInfo->nConstraint; i++){
- struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
- if( p->usable && (p->iColumn<0 || p->iColumn==pTab->iPK) ){
- switch( p->op ){
- case SQLITE_INDEX_CONSTRAINT_EQ:
- iEq = i;
- break;
- case SQLITE_INDEX_CONSTRAINT_LE:
- case SQLITE_INDEX_CONSTRAINT_LT:
- iLt = i;
- break;
- case SQLITE_INDEX_CONSTRAINT_GE:
- case SQLITE_INDEX_CONSTRAINT_GT:
- iGt = i;
- break;
- }
- }
- }
-
- if( iEq>=0 ){
- pIdxInfo->estimatedRows = 1;
- pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
- pIdxInfo->estimatedCost = 3.0;
- pIdxInfo->idxNum = SQLITE_INDEX_CONSTRAINT_EQ;
- pIdxInfo->aConstraintUsage[iEq].argvIndex = 1;
- pIdxInfo->aConstraintUsage[iEq].omit = 1;
- }else{
- int iCons = 1;
- int idxNum = 0;
- sqlite3_int64 nRow = 1000000;
- if( iLt>=0 ){
- nRow = nRow / 2;
- pIdxInfo->aConstraintUsage[iLt].argvIndex = iCons++;
- pIdxInfo->aConstraintUsage[iLt].omit = 1;
- idxNum |= pIdxInfo->aConstraint[iLt].op;
- }
- if( iGt>=0 ){
- nRow = nRow / 2;
- pIdxInfo->aConstraintUsage[iGt].argvIndex = iCons++;
- pIdxInfo->aConstraintUsage[iGt].omit = 1;
- idxNum |= pIdxInfo->aConstraint[iGt].op;
- }
- pIdxInfo->estimatedRows = nRow;
- pIdxInfo->estimatedCost = 3.0 * (double)nRow;
- pIdxInfo->idxNum = idxNum;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Register the unionvtab virtual table module with database handle db.
-*/
-static int createUnionVtab(sqlite3 *db){
- static sqlite3_module unionModule = {
- 0, /* iVersion */
- unionConnect,
- unionConnect,
- unionBestIndex, /* xBestIndex - query planner */
- unionDisconnect,
- unionDisconnect,
- unionOpen, /* xOpen - open a cursor */
- unionClose, /* xClose - close a cursor */
- unionFilter, /* xFilter - configure scan constraints */
- unionNext, /* xNext - advance a cursor */
- unionEof, /* xEof - check for end of scan */
- unionColumn, /* xColumn - read data */
- unionRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
- };
- int rc;
-
- rc = sqlite3_create_module(db, "unionvtab", &unionModule, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_module(db, "swarmvtab", &unionModule, (void*)db);
- }
- return rc;
-}
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_unionvtab_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Suppress harmless warning */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = createUnionVtab(db);
-#endif
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vfslog.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vfslog.c
deleted file mode 100644
index b55b06fcf3a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vfslog.c
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
-** 2013-10-09
-**
-** 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 contains the implementation of an SQLite vfs wrapper for
-** unix that generates per-database log files of all disk activity.
-*/
-
-/*
-** This module contains code for a wrapper VFS that causes a log of
-** most VFS calls to be written into a file on disk.
-**
-** Each database connection creates a separate log file in the same
-** directory as the original database and named after the original
-** database. A unique suffix is added to avoid name collisions.
-** Separate log files are used so that concurrent processes do not
-** try to write log operations to the same file at the same instant,
-** resulting in overwritten or comingled log text.
-**
-** Each individual log file records operations by a single database
-** connection on both the original database and its associated rollback
-** journal.
-**
-** The log files are in the comma-separated-value (CSV) format. The
-** log files can be imported into an SQLite database using the ".import"
-** command of the SQLite command-line shell for analysis.
-**
-** One technique for using this module is to append the text of this
-** module to the end of a standard "sqlite3.c" amalgamation file then
-** add the following compile-time options:
-**
-** -DSQLITE_EXTRA_INIT=sqlite3_register_vfslog
-** -DSQLITE_USE_FCNTL_TRACE
-**
-** The first compile-time option causes the sqlite3_register_vfslog()
-** function, defined below, to be invoked when SQLite is initialized.
-** That causes this custom VFS to become the default VFS for all
-** subsequent connections. The SQLITE_USE_FCNTL_TRACE option causes
-** the SQLite core to issue extra sqlite3_file_control() operations
-** with SQLITE_FCNTL_TRACE to give some indication of what is going
-** on in the core.
-*/
-
-#include "sqlite3.h"
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-#if SQLITE_OS_UNIX
-# include <unistd.h>
-#endif
-
-/*
-** Forward declaration of objects used by this utility
-*/
-typedef struct VLogLog VLogLog;
-typedef struct VLogVfs VLogVfs;
-typedef struct VLogFile VLogFile;
-
-/* There is a pair (an array of size 2) of the following objects for
-** each database file being logged. The first contains the filename
-** and is used to log I/O with the main database. The second has
-** a NULL filename and is used to log I/O for the journal. Both
-** out pointers are the same.
-*/
-struct VLogLog {
- VLogLog *pNext; /* Next in a list of all active logs */
- VLogLog **ppPrev; /* Pointer to this in the list */
- int nRef; /* Number of references to this object */
- int nFilename; /* Length of zFilename in bytes */
- char *zFilename; /* Name of database file. NULL for journal */
- FILE *out; /* Write information here */
-};
-
-struct VLogVfs {
- sqlite3_vfs base; /* VFS methods */
- sqlite3_vfs *pVfs; /* Parent VFS */
-};
-
-struct VLogFile {
- sqlite3_file base; /* IO methods */
- sqlite3_file *pReal; /* Underlying file handle */
- VLogLog *pLog; /* The log file for this file */
-};
-
-#define REALVFS(p) (((VLogVfs*)(p))->pVfs)
-
-/*
-** Methods for VLogFile
-*/
-static int vlogClose(sqlite3_file*);
-static int vlogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int vlogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int vlogTruncate(sqlite3_file*, sqlite3_int64 size);
-static int vlogSync(sqlite3_file*, int flags);
-static int vlogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int vlogLock(sqlite3_file*, int);
-static int vlogUnlock(sqlite3_file*, int);
-static int vlogCheckReservedLock(sqlite3_file*, int *pResOut);
-static int vlogFileControl(sqlite3_file*, int op, void *pArg);
-static int vlogSectorSize(sqlite3_file*);
-static int vlogDeviceCharacteristics(sqlite3_file*);
-
-/*
-** Methods for VLogVfs
-*/
-static int vlogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int vlogDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int vlogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int vlogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-static void *vlogDlOpen(sqlite3_vfs*, const char *zFilename);
-static void vlogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
-static void vlogDlClose(sqlite3_vfs*, void*);
-static int vlogRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int vlogSleep(sqlite3_vfs*, int microseconds);
-static int vlogCurrentTime(sqlite3_vfs*, double*);
-static int vlogGetLastError(sqlite3_vfs*, int, char *);
-static int vlogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-
-static VLogVfs vlog_vfs = {
- {
- 1, /* iVersion */
- 0, /* szOsFile (set by register_vlog()) */
- 1024, /* mxPathname */
- 0, /* pNext */
- "vfslog", /* zName */
- 0, /* pAppData */
- vlogOpen, /* xOpen */
- vlogDelete, /* xDelete */
- vlogAccess, /* xAccess */
- vlogFullPathname, /* xFullPathname */
- vlogDlOpen, /* xDlOpen */
- vlogDlError, /* xDlError */
- vlogDlSym, /* xDlSym */
- vlogDlClose, /* xDlClose */
- vlogRandomness, /* xRandomness */
- vlogSleep, /* xSleep */
- vlogCurrentTime, /* xCurrentTime */
- vlogGetLastError, /* xGetLastError */
- vlogCurrentTimeInt64 /* xCurrentTimeInt64 */
- },
- 0
-};
-
-static sqlite3_io_methods vlog_io_methods = {
- 1, /* iVersion */
- vlogClose, /* xClose */
- vlogRead, /* xRead */
- vlogWrite, /* xWrite */
- vlogTruncate, /* xTruncate */
- vlogSync, /* xSync */
- vlogFileSize, /* xFileSize */
- vlogLock, /* xLock */
- vlogUnlock, /* xUnlock */
- vlogCheckReservedLock, /* xCheckReservedLock */
- vlogFileControl, /* xFileControl */
- vlogSectorSize, /* xSectorSize */
- vlogDeviceCharacteristics, /* xDeviceCharacteristics */
- 0, /* xShmMap */
- 0, /* xShmLock */
- 0, /* xShmBarrier */
- 0 /* xShmUnmap */
-};
-
-#if SQLITE_OS_UNIX && !defined(NO_GETTOD)
-#include <sys/time.h>
-static sqlite3_uint64 vlog_time(){
- struct timeval sTime;
- gettimeofday(&sTime, 0);
- return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
-}
-#elif SQLITE_OS_WIN
-#include <windows.h>
-#include <time.h>
-static sqlite3_uint64 vlog_time(){
- FILETIME ft;
- sqlite3_uint64 u64time = 0;
-
- GetSystemTimeAsFileTime(&ft);
-
- u64time |= ft.dwHighDateTime;
- u64time <<= 32;
- u64time |= ft.dwLowDateTime;
-
- /* ft is 100-nanosecond intervals, we want microseconds */
- return u64time /(sqlite3_uint64)10;
-}
-#else
-static sqlite3_uint64 vlog_time(){
- return 0;
-}
-#endif
-
-
-/*
-** Write a message to the log file
-*/
-static void vlogLogPrint(
- VLogLog *pLog, /* The log file to write into */
- sqlite3_int64 tStart, /* Start time of system call */
- sqlite3_int64 tElapse, /* Elapse time of system call */
- const char *zOp, /* Type of system call */
- sqlite3_int64 iArg1, /* First argument */
- sqlite3_int64 iArg2, /* Second argument */
- const char *zArg3, /* Third argument */
- int iRes /* Result */
-){
- char z1[40], z2[40], z3[2000];
- if( pLog==0 ) return;
- if( iArg1>=0 ){
- sqlite3_snprintf(sizeof(z1), z1, "%lld", iArg1);
- }else{
- z1[0] = 0;
- }
- if( iArg2>=0 ){
- sqlite3_snprintf(sizeof(z2), z2, "%lld", iArg2);
- }else{
- z2[0] = 0;
- }
- if( zArg3 ){
- sqlite3_snprintf(sizeof(z3), z3, "\"%.*w\"", sizeof(z3)-4, zArg3);
- }else{
- z3[0] = 0;
- }
- fprintf(pLog->out,"%lld,%lld,%s,%d,%s,%s,%s,%d\n",
- tStart, tElapse, zOp, pLog->zFilename==0, z1, z2, z3, iRes);
-}
-
-/*
-** List of all active log connections. Protected by the master mutex.
-*/
-static VLogLog *allLogs = 0;
-
-/*
-** Close a VLogLog object
-*/
-static void vlogLogClose(VLogLog *p){
- if( p ){
- sqlite3_mutex *pMutex;
- p->nRef--;
- if( p->nRef>0 || p->zFilename==0 ) return;
- pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
- sqlite3_mutex_enter(pMutex);
- *p->ppPrev = p->pNext;
- if( p->pNext ) p->pNext->ppPrev = p->ppPrev;
- sqlite3_mutex_leave(pMutex);
- fclose(p->out);
- sqlite3_free(p);
- }
-}
-
-/*
-** Open a VLogLog object on the given file
-*/
-static VLogLog *vlogLogOpen(const char *zFilename){
- int nName = (int)strlen(zFilename);
- int isJournal = 0;
- sqlite3_mutex *pMutex;
- VLogLog *pLog, *pTemp;
- sqlite3_int64 tNow = 0;
- if( nName>4 && strcmp(zFilename+nName-4,"-wal")==0 ){
- return 0; /* Do not log wal files */
- }else
- if( nName>8 && strcmp(zFilename+nName-8,"-journal")==0 ){
- nName -= 8;
- isJournal = 1;
- }else if( nName>12
- && sqlite3_strglob("-mj??????9??", zFilename+nName-12)==0 ){
- return 0; /* Do not log master journal files */
- }
- pTemp = sqlite3_malloc( sizeof(*pLog)*2 + nName + 60 );
- if( pTemp==0 ) return 0;
- pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
- sqlite3_mutex_enter(pMutex);
- for(pLog=allLogs; pLog; pLog=pLog->pNext){
- if( pLog->nFilename==nName && !memcmp(pLog->zFilename, zFilename, nName) ){
- break;
- }
- }
- if( pLog==0 ){
- pLog = pTemp;
- pTemp = 0;
- memset(pLog, 0, sizeof(*pLog)*2);
- pLog->zFilename = (char*)&pLog[2];
- tNow = vlog_time();
- sqlite3_snprintf(nName+60, pLog->zFilename, "%.*s-debuglog-%lld",
- nName, zFilename, tNow);
- pLog->out = fopen(pLog->zFilename, "a");
- if( pLog->out==0 ){
- sqlite3_mutex_leave(pMutex);
- sqlite3_free(pLog);
- return 0;
- }
- pLog->nFilename = nName;
- pLog[1].out = pLog[0].out;
- pLog->ppPrev = &allLogs;
- if( allLogs ) allLogs->ppPrev = &pLog->pNext;
- pLog->pNext = allLogs;
- allLogs = pLog;
- }
- sqlite3_mutex_leave(pMutex);
- if( pTemp ){
- sqlite3_free(pTemp);
- }else{
-#if SQLITE_OS_UNIX
- char zHost[200];
- zHost[0] = 0;
- gethostname(zHost, sizeof(zHost)-1);
- zHost[sizeof(zHost)-1] = 0;
- vlogLogPrint(pLog, tNow, 0, "IDENT", getpid(), -1, zHost, 0);
-#endif
- }
- if( pLog && isJournal ) pLog++;
- pLog->nRef++;
- return pLog;
-}
-
-
-/*
-** Close an vlog-file.
-*/
-static int vlogClose(sqlite3_file *pFile){
- sqlite3_uint64 tStart, tElapse;
- int rc = SQLITE_OK;
- VLogFile *p = (VLogFile *)pFile;
-
- tStart = vlog_time();
- if( p->pReal->pMethods ){
- rc = p->pReal->pMethods->xClose(p->pReal);
- }
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "CLOSE", -1, -1, 0, rc);
- vlogLogClose(p->pLog);
- return rc;
-}
-
-/*
-** Compute signature for a block of content.
-**
-** For blocks of 16 or fewer bytes, the signature is just a hex dump of
-** the entire block.
-**
-** For blocks of more than 16 bytes, the signature is a hex dump of the
-** first 8 bytes followed by a 64-bit has of the entire block.
-*/
-static void vlogSignature(unsigned char *p, int n, char *zCksum){
- unsigned int s0 = 0, s1 = 0;
- unsigned int *pI;
- int i;
- if( n<=16 ){
- for(i=0; i<n; i++) sqlite3_snprintf(3, zCksum+i*2, "%02x", p[i]);
- }else{
- pI = (unsigned int*)p;
- for(i=0; i<n-7; i+=8){
- s0 += pI[0] + s1;
- s1 += pI[1] + s0;
- pI += 2;
- }
- for(i=0; i<8; i++) sqlite3_snprintf(3, zCksum+i*2, "%02x", p[i]);
- sqlite3_snprintf(18, zCksum+i*2, "-%08x%08x", s0, s1);
- }
-}
-
-/*
-** Convert a big-endian 32-bit integer into a native integer
-*/
-static int bigToNative(const unsigned char *x){
- return (x[0]<<24) + (x[1]<<16) + (x[2]<<8) + x[3];
-}
-
-/*
-** Read data from an vlog-file.
-*/
-static int vlogRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- char zSig[40];
-
- tStart = vlog_time();
- rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
- tElapse = vlog_time() - tStart;
- if( rc==SQLITE_OK ){
- vlogSignature(zBuf, iAmt, zSig);
- }else{
- zSig[0] = 0;
- }
- vlogLogPrint(p->pLog, tStart, tElapse, "READ", iAmt, iOfst, zSig, rc);
- if( rc==SQLITE_OK
- && p->pLog
- && p->pLog->zFilename
- && iOfst<=24
- && iOfst+iAmt>=28
- ){
- unsigned char *x = ((unsigned char*)zBuf)+(24-iOfst);
- unsigned iCtr, nFree = -1;
- char *zFree = 0;
- char zStr[12];
- iCtr = bigToNative(x);
- if( iOfst+iAmt>=40 ){
- zFree = zStr;
- sqlite3_snprintf(sizeof(zStr), zStr, "%d", bigToNative(x+8));
- nFree = bigToNative(x+12);
- }
- vlogLogPrint(p->pLog, tStart, 0, "CHNGCTR-READ", iCtr, nFree, zFree, 0);
- }
- return rc;
-}
-
-/*
-** Write data to an vlog-file.
-*/
-static int vlogWrite(
- sqlite3_file *pFile,
- const void *z,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- char zSig[40];
-
- tStart = vlog_time();
- vlogSignature((unsigned char*)z, iAmt, zSig);
- rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "WRITE", iAmt, iOfst, zSig, rc);
- if( rc==SQLITE_OK
- && p->pLog
- && p->pLog->zFilename
- && iOfst<=24
- && iOfst+iAmt>=28
- ){
- unsigned char *x = ((unsigned char*)z)+(24-iOfst);
- unsigned iCtr, nFree = -1;
- char *zFree = 0;
- char zStr[12];
- iCtr = bigToNative(x);
- if( iOfst+iAmt>=40 ){
- zFree = zStr;
- sqlite3_snprintf(sizeof(zStr), zStr, "%d", bigToNative(x+8));
- nFree = bigToNative(x+12);
- }
- vlogLogPrint(p->pLog, tStart, 0, "CHNGCTR-WRITE", iCtr, nFree, zFree, 0);
- }
- return rc;
-}
-
-/*
-** Truncate an vlog-file.
-*/
-static int vlogTruncate(sqlite3_file *pFile, sqlite_int64 size){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- tStart = vlog_time();
- rc = p->pReal->pMethods->xTruncate(p->pReal, size);
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "TRUNCATE", size, -1, 0, rc);
- return rc;
-}
-
-/*
-** Sync an vlog-file.
-*/
-static int vlogSync(sqlite3_file *pFile, int flags){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- tStart = vlog_time();
- rc = p->pReal->pMethods->xSync(p->pReal, flags);
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "SYNC", flags, -1, 0, rc);
- return rc;
-}
-
-/*
-** Return the current file-size of an vlog-file.
-*/
-static int vlogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- tStart = vlog_time();
- rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "FILESIZE", *pSize, -1, 0, rc);
- return rc;
-}
-
-/*
-** Lock an vlog-file.
-*/
-static int vlogLock(sqlite3_file *pFile, int eLock){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- tStart = vlog_time();
- rc = p->pReal->pMethods->xLock(p->pReal, eLock);
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "LOCK", eLock, -1, 0, rc);
- return rc;
-}
-
-/*
-** Unlock an vlog-file.
-*/
-static int vlogUnlock(sqlite3_file *pFile, int eLock){
- int rc;
- sqlite3_uint64 tStart;
- VLogFile *p = (VLogFile *)pFile;
- tStart = vlog_time();
- vlogLogPrint(p->pLog, tStart, 0, "UNLOCK", eLock, -1, 0, 0);
- rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
- return rc;
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an vlog-file.
-*/
-static int vlogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- tStart = vlog_time();
- rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "CHECKRESERVEDLOCK",
- *pResOut, -1, "", rc);
- return rc;
-}
-
-/*
-** File control method. For custom operations on an vlog-file.
-*/
-static int vlogFileControl(sqlite3_file *pFile, int op, void *pArg){
- VLogFile *p = (VLogFile *)pFile;
- sqlite3_uint64 tStart, tElapse;
- int rc;
- tStart = vlog_time();
- rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
- if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
- *(char**)pArg = sqlite3_mprintf("vlog/%z", *(char**)pArg);
- }
- tElapse = vlog_time() - tStart;
- if( op==SQLITE_FCNTL_TRACE ){
- vlogLogPrint(p->pLog, tStart, tElapse, "TRACE", op, -1, pArg, rc);
- }else if( op==SQLITE_FCNTL_PRAGMA ){
- const char **azArg = (const char **)pArg;
- vlogLogPrint(p->pLog, tStart, tElapse, "FILECONTROL", op, -1, azArg[1], rc);
- }else if( op==SQLITE_FCNTL_SIZE_HINT ){
- sqlite3_int64 sz = *(sqlite3_int64*)pArg;
- vlogLogPrint(p->pLog, tStart, tElapse, "FILECONTROL", op, sz, 0, rc);
- }else{
- vlogLogPrint(p->pLog, tStart, tElapse, "FILECONTROL", op, -1, 0, rc);
- }
- return rc;
-}
-
-/*
-** Return the sector-size in bytes for an vlog-file.
-*/
-static int vlogSectorSize(sqlite3_file *pFile){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- tStart = vlog_time();
- rc = p->pReal->pMethods->xSectorSize(p->pReal);
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "SECTORSIZE", -1, -1, 0, rc);
- return rc;
-}
-
-/*
-** Return the device characteristic flags supported by an vlog-file.
-*/
-static int vlogDeviceCharacteristics(sqlite3_file *pFile){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogFile *p = (VLogFile *)pFile;
- tStart = vlog_time();
- rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
- tElapse = vlog_time() - tStart;
- vlogLogPrint(p->pLog, tStart, tElapse, "DEVCHAR", -1, -1, 0, rc);
- return rc;
-}
-
-
-/*
-** Open an vlog file handle.
-*/
-static int vlogOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- sqlite3_int64 iArg2;
- VLogFile *p = (VLogFile*)pFile;
-
- p->pReal = (sqlite3_file*)&p[1];
- if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
- p->pLog = vlogLogOpen(zName);
- }else{
- p->pLog = 0;
- }
- tStart = vlog_time();
- rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
- tElapse = vlog_time() - tStart;
- iArg2 = pOutFlags ? *pOutFlags : -1;
- vlogLogPrint(p->pLog, tStart, tElapse, "OPEN", flags, iArg2, 0, rc);
- if( rc==SQLITE_OK ){
- pFile->pMethods = &vlog_io_methods;
- }else{
- if( p->pLog ) vlogLogClose(p->pLog);
- p->pLog = 0;
- }
- return rc;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int vlogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogLog *pLog;
- tStart = vlog_time();
- rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
- tElapse = vlog_time() - tStart;
- pLog = vlogLogOpen(zPath);
- vlogLogPrint(pLog, tStart, tElapse, "DELETE", dirSync, -1, 0, rc);
- vlogLogClose(pLog);
- return rc;
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int vlogAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- int rc;
- sqlite3_uint64 tStart, tElapse;
- VLogLog *pLog;
- tStart = vlog_time();
- rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
- tElapse = vlog_time() - tStart;
- pLog = vlogLogOpen(zPath);
- vlogLogPrint(pLog, tStart, tElapse, "ACCESS", flags, *pResOut, 0, rc);
- vlogLogClose(pLog);
- return rc;
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (INST_MAX_PATHNAME+1) bytes.
-*/
-static int vlogFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
-}
-
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *vlogDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void vlogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void vlogDlClose(sqlite3_vfs *pVfs, void *pHandle){
- REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
-}
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int vlogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int vlogSleep(sqlite3_vfs *pVfs, int nMicro){
- return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int vlogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
-}
-
-static int vlogGetLastError(sqlite3_vfs *pVfs, int a, char *b){
- return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
-}
-static int vlogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
- return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
-}
-
-/*
-** Register debugvfs as the default VFS for this process.
-*/
-int sqlite3_register_vfslog(const char *zArg){
- vlog_vfs.pVfs = sqlite3_vfs_find(0);
- vlog_vfs.base.szOsFile = sizeof(VLogFile) + vlog_vfs.pVfs->szOsFile;
- return sqlite3_vfs_register(&vlog_vfs.base, 1);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vfsstat.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vfsstat.c
deleted file mode 100644
index 14753d277d6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vfsstat.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
-** 2016-05-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 contains the implementation of an SQLite vfs shim that
-** tracks I/O. Access to the accumulated status counts is provided using
-** an eponymous virtual table.
-*/
-#include <sqlite3ext.h>
-SQLITE_EXTENSION_INIT1
-
-/*
-** This module contains code for a wrapper VFS that cause stats for
-** most VFS calls to be recorded.
-**
-** To use this module, first compile it as a loadable extension. See
-** https://www.sqlite.org/loadext.html#build for compilations instructions.
-**
-** After compliing, load this extension, then open database connections to be
-** measured. Query usages status using the vfsstat virtual table:
-**
-** SELECT * FROM vfsstat;
-**
-** Reset counters using UPDATE statements against vfsstat:
-**
-** UPDATE vfsstat SET count=0;
-**
-** EXAMPLE SCRIPT:
-**
-** .load ./vfsstat
-** .open test.db
-** DROP TABLE IF EXISTS t1;
-** CREATE TABLE t1(x,y);
-** INSERT INTO t1 VALUES(123, randomblob(5000));
-** CREATE INDEX t1x ON t1(x);
-** DROP TABLE t1;
-** VACUUM;
-** SELECT * FROM vfsstat WHERE count>0;
-**
-** LIMITATIONS:
-**
-** This module increments counters without using mutex protection. So if
-** two or more threads try to use this module at the same time, race conditions
-** may occur which mess up the counts. This is harmless, other than giving
-** incorrect statistics.
-*/
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-/*
-** File types
-*/
-#define VFSSTAT_MAIN 0 /* Main database file */
-#define VFSSTAT_JOURNAL 1 /* Rollback journal */
-#define VFSSTAT_WAL 2 /* Write-ahead log file */
-#define VFSSTAT_MASTERJRNL 3 /* Master journal */
-#define VFSSTAT_SUBJRNL 4 /* Subjournal */
-#define VFSSTAT_TEMPDB 5 /* TEMP database */
-#define VFSSTAT_TEMPJRNL 6 /* Journal for TEMP database */
-#define VFSSTAT_TRANSIENT 7 /* Transient database */
-#define VFSSTAT_ANY 8 /* Unspecified file type */
-#define VFSSTAT_nFile 9 /* This many file types */
-
-/* Names of the file types. These are allowed values for the
-** first column of the vfsstat virtual table.
-*/
-static const char *azFile[] = {
- "database", "journal", "wal", "master-journal", "sub-journal",
- "temp-database", "temp-journal", "transient-db", "*"
-};
-
-/*
-** Stat types
-*/
-#define VFSSTAT_BYTESIN 0 /* Bytes read in */
-#define VFSSTAT_BYTESOUT 1 /* Bytes written out */
-#define VFSSTAT_READ 2 /* Read requests */
-#define VFSSTAT_WRITE 3 /* Write requests */
-#define VFSSTAT_SYNC 4 /* Syncs */
-#define VFSSTAT_OPEN 5 /* File opens */
-#define VFSSTAT_LOCK 6 /* Lock requests */
-#define VFSSTAT_ACCESS 0 /* xAccess calls. filetype==ANY only */
-#define VFSSTAT_DELETE 1 /* xDelete calls. filetype==ANY only */
-#define VFSSTAT_FULLPATH 2 /* xFullPathname calls. ANY only */
-#define VFSSTAT_RANDOM 3 /* xRandomness calls. ANY only */
-#define VFSSTAT_SLEEP 4 /* xSleep calls. ANY only */
-#define VFSSTAT_CURTIME 5 /* xCurrentTime calls. ANY only */
-#define VFSSTAT_nStat 7 /* This many stat types */
-
-
-/* Names for the second column of the vfsstat virtual table for all
-** cases except when the first column is "*" or VFSSTAT_ANY. */
-static const char *azStat[] = {
- "bytes-in", "bytes-out", "read", "write", "sync", "open", "lock",
-};
-static const char *azStatAny[] = {
- "access", "delete", "fullpathname", "randomness", "sleep", "currenttimestamp",
- "not-used"
-};
-
-/* Total number of counters */
-#define VFSSTAT_MXCNT (VFSSTAT_nStat*VFSSTAT_nFile)
-
-/*
-** Performance stats are collected in an instance of the following
-** global array.
-*/
-static sqlite3_uint64 aVfsCnt[VFSSTAT_MXCNT];
-
-/*
-** Access to a specific counter
-*/
-#define STATCNT(filetype,stat) (aVfsCnt[(filetype)*VFSSTAT_nStat+(stat)])
-
-/*
-** Forward declaration of objects used by this utility
-*/
-typedef struct VStatVfs VStatVfs;
-typedef struct VStatFile VStatFile;
-
-/* An instance of the VFS */
-struct VStatVfs {
- sqlite3_vfs base; /* VFS methods */
- sqlite3_vfs *pVfs; /* Parent VFS */
-};
-
-/* An open file */
-struct VStatFile {
- sqlite3_file base; /* IO methods */
- sqlite3_file *pReal; /* Underlying file handle */
- unsigned char eFiletype; /* What type of file is this */
-};
-
-#define REALVFS(p) (((VStatVfs*)(p))->pVfs)
-
-/*
-** Methods for VStatFile
-*/
-static int vstatClose(sqlite3_file*);
-static int vstatRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int vstatWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int vstatTruncate(sqlite3_file*, sqlite3_int64 size);
-static int vstatSync(sqlite3_file*, int flags);
-static int vstatFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int vstatLock(sqlite3_file*, int);
-static int vstatUnlock(sqlite3_file*, int);
-static int vstatCheckReservedLock(sqlite3_file*, int *pResOut);
-static int vstatFileControl(sqlite3_file*, int op, void *pArg);
-static int vstatSectorSize(sqlite3_file*);
-static int vstatDeviceCharacteristics(sqlite3_file*);
-static int vstatShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
-static int vstatShmLock(sqlite3_file*, int offset, int n, int flags);
-static void vstatShmBarrier(sqlite3_file*);
-static int vstatShmUnmap(sqlite3_file*, int deleteFlag);
-static int vstatFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
-static int vstatUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
-
-/*
-** Methods for VStatVfs
-*/
-static int vstatOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int vstatDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int vstatAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int vstatFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-static void *vstatDlOpen(sqlite3_vfs*, const char *zFilename);
-static void vstatDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*vstatDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
-static void vstatDlClose(sqlite3_vfs*, void*);
-static int vstatRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int vstatSleep(sqlite3_vfs*, int microseconds);
-static int vstatCurrentTime(sqlite3_vfs*, double*);
-static int vstatGetLastError(sqlite3_vfs*, int, char *);
-static int vstatCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-
-static VStatVfs vstat_vfs = {
- {
- 2, /* iVersion */
- 0, /* szOsFile (set by register_vstat()) */
- 1024, /* mxPathname */
- 0, /* pNext */
- "vfslog", /* zName */
- 0, /* pAppData */
- vstatOpen, /* xOpen */
- vstatDelete, /* xDelete */
- vstatAccess, /* xAccess */
- vstatFullPathname, /* xFullPathname */
- vstatDlOpen, /* xDlOpen */
- vstatDlError, /* xDlError */
- vstatDlSym, /* xDlSym */
- vstatDlClose, /* xDlClose */
- vstatRandomness, /* xRandomness */
- vstatSleep, /* xSleep */
- vstatCurrentTime, /* xCurrentTime */
- vstatGetLastError, /* xGetLastError */
- vstatCurrentTimeInt64 /* xCurrentTimeInt64 */
- },
- 0
-};
-
-static const sqlite3_io_methods vstat_io_methods = {
- 3, /* iVersion */
- vstatClose, /* xClose */
- vstatRead, /* xRead */
- vstatWrite, /* xWrite */
- vstatTruncate, /* xTruncate */
- vstatSync, /* xSync */
- vstatFileSize, /* xFileSize */
- vstatLock, /* xLock */
- vstatUnlock, /* xUnlock */
- vstatCheckReservedLock, /* xCheckReservedLock */
- vstatFileControl, /* xFileControl */
- vstatSectorSize, /* xSectorSize */
- vstatDeviceCharacteristics, /* xDeviceCharacteristics */
- vstatShmMap, /* xShmMap */
- vstatShmLock, /* xShmLock */
- vstatShmBarrier, /* xShmBarrier */
- vstatShmUnmap, /* xShmUnmap */
- vstatFetch, /* xFetch */
- vstatUnfetch /* xUnfetch */
-};
-
-
-
-/*
-** Close an vstat-file.
-*/
-static int vstatClose(sqlite3_file *pFile){
- VStatFile *p = (VStatFile *)pFile;
- int rc = SQLITE_OK;
-
- if( p->pReal->pMethods ){
- rc = p->pReal->pMethods->xClose(p->pReal);
- }
- return rc;
-}
-
-
-/*
-** Read data from an vstat-file.
-*/
-static int vstatRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
-
- rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
- STATCNT(p->eFiletype,VFSSTAT_READ)++;
- if( rc==SQLITE_OK ){
- STATCNT(p->eFiletype,VFSSTAT_BYTESIN) += iAmt;
- }
- return rc;
-}
-
-/*
-** Write data to an vstat-file.
-*/
-static int vstatWrite(
- sqlite3_file *pFile,
- const void *z,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
-
- rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
- STATCNT(p->eFiletype,VFSSTAT_WRITE)++;
- if( rc==SQLITE_OK ){
- STATCNT(p->eFiletype,VFSSTAT_BYTESOUT) += iAmt;
- }
- return rc;
-}
-
-/*
-** Truncate an vstat-file.
-*/
-static int vstatTruncate(sqlite3_file *pFile, sqlite_int64 size){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
- rc = p->pReal->pMethods->xTruncate(p->pReal, size);
- return rc;
-}
-
-/*
-** Sync an vstat-file.
-*/
-static int vstatSync(sqlite3_file *pFile, int flags){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
- rc = p->pReal->pMethods->xSync(p->pReal, flags);
- STATCNT(p->eFiletype,VFSSTAT_SYNC)++;
- return rc;
-}
-
-/*
-** Return the current file-size of an vstat-file.
-*/
-static int vstatFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
- rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
- return rc;
-}
-
-/*
-** Lock an vstat-file.
-*/
-static int vstatLock(sqlite3_file *pFile, int eLock){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
- rc = p->pReal->pMethods->xLock(p->pReal, eLock);
- STATCNT(p->eFiletype,VFSSTAT_LOCK)++;
- return rc;
-}
-
-/*
-** Unlock an vstat-file.
-*/
-static int vstatUnlock(sqlite3_file *pFile, int eLock){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
- rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
- STATCNT(p->eFiletype,VFSSTAT_LOCK)++;
- return rc;
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an vstat-file.
-*/
-static int vstatCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
- rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
- STATCNT(p->eFiletype,VFSSTAT_LOCK)++;
- return rc;
-}
-
-/*
-** File control method. For custom operations on an vstat-file.
-*/
-static int vstatFileControl(sqlite3_file *pFile, int op, void *pArg){
- VStatFile *p = (VStatFile *)pFile;
- int rc;
- rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
- if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
- *(char**)pArg = sqlite3_mprintf("vstat/%z", *(char**)pArg);
- }
- return rc;
-}
-
-/*
-** Return the sector-size in bytes for an vstat-file.
-*/
-static int vstatSectorSize(sqlite3_file *pFile){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
- rc = p->pReal->pMethods->xSectorSize(p->pReal);
- return rc;
-}
-
-/*
-** Return the device characteristic flags supported by an vstat-file.
-*/
-static int vstatDeviceCharacteristics(sqlite3_file *pFile){
- int rc;
- VStatFile *p = (VStatFile *)pFile;
- rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
- return rc;
-}
-
-/* Create a shared memory file mapping */
-static int vstatShmMap(
- sqlite3_file *pFile,
- int iPg,
- int pgsz,
- int bExtend,
- void volatile **pp
-){
- VStatFile *p = (VStatFile *)pFile;
- return p->pReal->pMethods->xShmMap(p->pReal, iPg, pgsz, bExtend, pp);
-}
-
-/* Perform locking on a shared-memory segment */
-static int vstatShmLock(sqlite3_file *pFile, int offset, int n, int flags){
- VStatFile *p = (VStatFile *)pFile;
- return p->pReal->pMethods->xShmLock(p->pReal, offset, n, flags);
-}
-
-/* Memory barrier operation on shared memory */
-static void vstatShmBarrier(sqlite3_file *pFile){
- VStatFile *p = (VStatFile *)pFile;
- p->pReal->pMethods->xShmBarrier(p->pReal);
-}
-
-/* Unmap a shared memory segment */
-static int vstatShmUnmap(sqlite3_file *pFile, int deleteFlag){
- VStatFile *p = (VStatFile *)pFile;
- return p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
-}
-
-/* Fetch a page of a memory-mapped file */
-static int vstatFetch(
- sqlite3_file *pFile,
- sqlite3_int64 iOfst,
- int iAmt,
- void **pp
-){
- VStatFile *p = (VStatFile *)pFile;
- return p->pReal->pMethods->xFetch(p->pReal, iOfst, iAmt, pp);
-}
-
-/* Release a memory-mapped page */
-static int vstatUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
- VStatFile *p = (VStatFile *)pFile;
- return p->pReal->pMethods->xUnfetch(p->pReal, iOfst, pPage);
-}
-
-/*
-** Open an vstat file handle.
-*/
-static int vstatOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- int rc;
- VStatFile *p = (VStatFile*)pFile;
-
- p->pReal = (sqlite3_file*)&p[1];
- rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
- if( flags & SQLITE_OPEN_MAIN_DB ){
- p->eFiletype = VFSSTAT_MAIN;
- }else if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
- p->eFiletype = VFSSTAT_JOURNAL;
- }else if( flags & SQLITE_OPEN_WAL ){
- p->eFiletype = VFSSTAT_WAL;
- }else if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
- p->eFiletype = VFSSTAT_MASTERJRNL;
- }else if( flags & SQLITE_OPEN_SUBJOURNAL ){
- p->eFiletype = VFSSTAT_SUBJRNL;
- }else if( flags & SQLITE_OPEN_TEMP_DB ){
- p->eFiletype = VFSSTAT_TEMPDB;
- }else if( flags & SQLITE_OPEN_TEMP_JOURNAL ){
- p->eFiletype = VFSSTAT_TEMPJRNL;
- }else{
- p->eFiletype = VFSSTAT_TRANSIENT;
- }
- STATCNT(p->eFiletype,VFSSTAT_OPEN)++;
- pFile->pMethods = rc ? 0 : &vstat_io_methods;
- return rc;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int vstatDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- int rc;
- rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
- STATCNT(VFSSTAT_ANY,VFSSTAT_DELETE)++;
- return rc;
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int vstatAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- int rc;
- rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
- STATCNT(VFSSTAT_ANY,VFSSTAT_ACCESS)++;
- return rc;
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (INST_MAX_PATHNAME+1) bytes.
-*/
-static int vstatFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- STATCNT(VFSSTAT_ANY,VFSSTAT_FULLPATH)++;
- return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
-}
-
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *vstatDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void vstatDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*vstatDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void vstatDlClose(sqlite3_vfs *pVfs, void *pHandle){
- REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
-}
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int vstatRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- STATCNT(VFSSTAT_ANY,VFSSTAT_RANDOM)++;
- return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int vstatSleep(sqlite3_vfs *pVfs, int nMicro){
- STATCNT(VFSSTAT_ANY,VFSSTAT_SLEEP)++;
- return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int vstatCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- STATCNT(VFSSTAT_ANY,VFSSTAT_CURTIME)++;
- return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
-}
-
-static int vstatGetLastError(sqlite3_vfs *pVfs, int a, char *b){
- return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
-}
-static int vstatCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
- STATCNT(VFSSTAT_ANY,VFSSTAT_CURTIME)++;
- return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
-}
-
-/*
-** A virtual table for accessing the stats collected by this VFS shim
-*/
-static int vstattabConnect(sqlite3*, void*, int, const char*const*,
- sqlite3_vtab**,char**);
-static int vstattabBestIndex(sqlite3_vtab*,sqlite3_index_info*);
-static int vstattabDisconnect(sqlite3_vtab*);
-static int vstattabOpen(sqlite3_vtab*, sqlite3_vtab_cursor**);
-static int vstattabClose(sqlite3_vtab_cursor*);
-static int vstattabFilter(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv);
-static int vstattabNext(sqlite3_vtab_cursor*);
-static int vstattabEof(sqlite3_vtab_cursor*);
-static int vstattabColumn(sqlite3_vtab_cursor*,sqlite3_context*,int);
-static int vstattabRowid(sqlite3_vtab_cursor*,sqlite3_int64*);
-static int vstattabUpdate(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
-
-/* A cursor for the vfsstat virtual table */
-typedef struct VfsStatCursor {
- sqlite3_vtab_cursor base; /* Base class. Must be first */
- int i; /* Pointing to this aVfsCnt[] value */
-} VfsStatCursor;
-
-
-static int vstattabConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3_vtab *pNew;
- int rc;
-
-/* Column numbers */
-#define VSTAT_COLUMN_FILE 0
-#define VSTAT_COLUMN_STAT 1
-#define VSTAT_COLUMN_COUNT 2
-
- rc = sqlite3_declare_vtab(db,"CREATE TABLE x(file,stat,count)");
- if( rc==SQLITE_OK ){
- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- }
- return rc;
-}
-
-/*
-** This method is the destructor for vstat table object.
-*/
-static int vstattabDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new vstat table cursor object.
-*/
-static int vstattabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- VfsStatCursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-
-/*
-** Destructor for a VfsStatCursor.
-*/
-static int vstattabClose(sqlite3_vtab_cursor *cur){
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a VfsStatCursor to its next row of output.
-*/
-static int vstattabNext(sqlite3_vtab_cursor *cur){
- ((VfsStatCursor*)cur)->i++;
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the VfsStatCursor
-** is currently pointing.
-*/
-static int vstattabColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- VfsStatCursor *pCur = (VfsStatCursor*)cur;
- switch( i ){
- case VSTAT_COLUMN_FILE: {
- sqlite3_result_text(ctx, azFile[pCur->i/VFSSTAT_nStat], -1, SQLITE_STATIC);
- break;
- }
- case VSTAT_COLUMN_STAT: {
- const char **az;
- az = (pCur->i/VFSSTAT_nStat)==VFSSTAT_ANY ? azStatAny : azStat;
- sqlite3_result_text(ctx, az[pCur->i%VFSSTAT_nStat], -1, SQLITE_STATIC);
- break;
- }
- case VSTAT_COLUMN_COUNT: {
- sqlite3_result_int64(ctx, aVfsCnt[pCur->i]);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row.
-*/
-static int vstattabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- VfsStatCursor *pCur = (VfsStatCursor*)cur;
- *pRowid = pCur->i;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int vstattabEof(sqlite3_vtab_cursor *cur){
- VfsStatCursor *pCur = (VfsStatCursor*)cur;
- return pCur->i >= VFSSTAT_MXCNT;
-}
-
-/*
-** Only a full table scan is supported. So xFilter simply rewinds to
-** the beginning.
-*/
-static int vstattabFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- VfsStatCursor *pCur = (VfsStatCursor*)pVtabCursor;
- pCur->i = 0;
- return SQLITE_OK;
-}
-
-/*
-** Only a forwards full table scan is supported. xBestIndex is a no-op.
-*/
-static int vstattabBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- return SQLITE_OK;
-}
-
-/*
-** Any VSTAT_COLUMN_COUNT can be changed to a positive integer.
-** No deletions or insertions are allowed. No changes to other
-** columns are allowed.
-*/
-static int vstattabUpdate(
- sqlite3_vtab *tab,
- int argc, sqlite3_value **argv,
- sqlite3_int64 *pRowid
-){
- sqlite3_int64 iRowid, x;
- if( argc==1 ) return SQLITE_ERROR;
- if( sqlite3_value_type(argv[0])!=SQLITE_INTEGER ) return SQLITE_ERROR;
- iRowid = sqlite3_value_int64(argv[0]);
- if( iRowid!=sqlite3_value_int64(argv[1]) ) return SQLITE_ERROR;
- if( iRowid<0 || iRowid>=VFSSTAT_MXCNT ) return SQLITE_ERROR;
- if( sqlite3_value_type(argv[VSTAT_COLUMN_COUNT+2])!=SQLITE_INTEGER ){
- return SQLITE_ERROR;
- }
- x = sqlite3_value_int64(argv[VSTAT_COLUMN_COUNT+2]);
- if( x<0 ) return SQLITE_ERROR;
- aVfsCnt[iRowid] = x;
- return SQLITE_OK;
-}
-
-static sqlite3_module VfsStatModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- vstattabConnect, /* xConnect */
- vstattabBestIndex, /* xBestIndex */
- vstattabDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- vstattabOpen, /* xOpen - open a cursor */
- vstattabClose, /* xClose - close a cursor */
- vstattabFilter, /* xFilter - configure scan constraints */
- vstattabNext, /* xNext - advance a cursor */
- vstattabEof, /* xEof - check for end of scan */
- vstattabColumn, /* xColumn - read data */
- vstattabRowid, /* xRowid - read data */
- vstattabUpdate, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-/*
-** This routine is an sqlite3_auto_extension() callback, invoked to register
-** the vfsstat virtual table for all new database connections.
-*/
-static int vstatRegister(
- sqlite3 *db,
- const char **pzErrMsg,
- const struct sqlite3_api_routines *pThunk
-){
- return sqlite3_create_module(db, "vfsstat", &VfsStatModule, 0);
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-/*
-** This routine is called when the extension is loaded.
-**
-** Register the new VFS. Make arrangement to register the virtual table
-** for each new database connection.
-*/
-int sqlite3_vfsstat_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- vstat_vfs.pVfs = sqlite3_vfs_find(0);
- vstat_vfs.base.szOsFile = sizeof(VStatFile) + vstat_vfs.pVfs->szOsFile;
- rc = sqlite3_vfs_register(&vstat_vfs.base, 1);
- if( rc==SQLITE_OK ){
- rc = sqlite3_auto_extension(vstatRegister);
- }
- if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vtablog.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vtablog.c
deleted file mode 100644
index 9e03fd455de..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vtablog.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
-** 2017-08-10
-**
-** 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 a virtual table that prints diagnostic information
-** on stdout when its key interfaces are called. This is intended for
-** interactive analysis and debugging of virtual table interfaces.
-**
-** Usage example:
-**
-** .load ./vtablog
-** CREATE VIRTUAL TABLE temp.log USING vtablog(
-** schema='CREATE TABLE x(a,b,c)',
-** rows=25
-** );
-** SELECT * FROM log;
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-
-
-/* vtablog_vtab is a subclass of sqlite3_vtab which will
-** serve as the underlying representation of a vtablog virtual table
-*/
-typedef struct vtablog_vtab vtablog_vtab;
-struct vtablog_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- int nRow; /* Number of rows in the table */
- int iInst; /* Instance number for this vtablog table */
- int nCursor; /* Number of cursors created */
-};
-
-/* vtablog_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-typedef struct vtablog_cursor vtablog_cursor;
-struct vtablog_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- int iCursor; /* Cursor number */
- sqlite3_int64 iRowid; /* The rowid */
-};
-
-/* Skip leading whitespace. Return a pointer to the first non-whitespace
-** character, or to the zero terminator if the string has only whitespace */
-static const char *vtablog_skip_whitespace(const char *z){
- while( isspace((unsigned char)z[0]) ) z++;
- return z;
-}
-
-/* Remove trailing whitespace from the end of string z[] */
-static void vtablog_trim_whitespace(char *z){
- size_t n = strlen(z);
- while( n>0 && isspace((unsigned char)z[n]) ) n--;
- z[n] = 0;
-}
-
-/* Dequote the string */
-static void vtablog_dequote(char *z){
- int j;
- char cQuote = z[0];
- size_t i, n;
-
- if( cQuote!='\'' && cQuote!='"' ) return;
- n = strlen(z);
- if( n<2 || z[n-1]!=z[0] ) return;
- for(i=1, j=0; i<n-1; i++){
- if( z[i]==cQuote && z[i+1]==cQuote ) i++;
- z[j++] = z[i];
- }
- z[j] = 0;
-}
-
-/* Check to see if the string is of the form: "TAG = VALUE" with optional
-** whitespace before and around tokens. If it is, return a pointer to the
-** first character of VALUE. If it is not, return NULL.
-*/
-static const char *vtablog_parameter(const char *zTag, int nTag, const char *z){
- z = vtablog_skip_whitespace(z);
- if( strncmp(zTag, z, nTag)!=0 ) return 0;
- z = vtablog_skip_whitespace(z+nTag);
- if( z[0]!='=' ) return 0;
- return vtablog_skip_whitespace(z+1);
-}
-
-/* Decode a parameter that requires a dequoted string.
-**
-** Return non-zero on an error.
-*/
-static int vtablog_string_parameter(
- char **pzErr, /* Leave the error message here, if there is one */
- const char *zParam, /* Parameter we are checking for */
- const char *zArg, /* Raw text of the virtual table argment */
- char **pzVal /* Write the dequoted string value here */
-){
- const char *zValue;
- zValue = vtablog_parameter(zParam,(int)strlen(zParam),zArg);
- if( zValue==0 ) return 0;
- if( *pzVal ){
- *pzErr = sqlite3_mprintf("more than one '%s' parameter", zParam);
- return 1;
- }
- *pzVal = sqlite3_mprintf("%s", zValue);
- if( *pzVal==0 ){
- *pzErr = sqlite3_mprintf("out of memory");
- return 1;
- }
- vtablog_trim_whitespace(*pzVal);
- vtablog_dequote(*pzVal);
- return 0;
-}
-
-#if 0 /* not used - yet */
-/* Return 0 if the argument is false and 1 if it is true. Return -1 if
-** we cannot really tell.
-*/
-static int vtablog_boolean(const char *z){
- if( sqlite3_stricmp("yes",z)==0
- || sqlite3_stricmp("on",z)==0
- || sqlite3_stricmp("true",z)==0
- || (z[0]=='1' && z[1]==0)
- ){
- return 1;
- }
- if( sqlite3_stricmp("no",z)==0
- || sqlite3_stricmp("off",z)==0
- || sqlite3_stricmp("false",z)==0
- || (z[0]=='0' && z[1]==0)
- ){
- return 0;
- }
- return -1;
-}
-#endif
-
-/*
-** The vtablogConnect() method is invoked to create a new
-** vtablog_vtab that describes the vtablog virtual table.
-**
-** Think of this routine as the constructor for vtablog_vtab objects.
-**
-** All this routine needs to do is:
-**
-** (1) Allocate the vtablog_vtab object and initialize all fields.
-**
-** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-** result set of queries against vtablog will look like.
-*/
-static int vtablogConnectCreate(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr,
- int isCreate
-){
- static int nInst = 0;
- vtablog_vtab *pNew;
- int i;
- int rc;
- int iInst = ++nInst;
- char *zSchema = 0;
- char *zNRow = 0;
-
- printf("vtablog%s(tab=%d):\n", isCreate ? "Create" : "Connect", iInst);
- printf(" argc=%d\n", argc);
- for(i=0; i<argc; i++){
- printf(" argv[%d] = ", i);
- if( argv[i] ){
- printf("[%s]\n", argv[i]);
- }else{
- printf("NULL\n");
- }
- }
-
- for(i=3; i<argc; i++){
- const char *z = argv[i];
- if( vtablog_string_parameter(pzErr, "schema", z, &zSchema) ){
- return SQLITE_ERROR;
- }
- if( vtablog_string_parameter(pzErr, "rows", z, &zNRow) ){
- return SQLITE_ERROR;
- }
- }
-
- if( zSchema==0 ){
- *pzErr = sqlite3_mprintf("no schema defined");
- return SQLITE_ERROR;
- }
- rc = sqlite3_declare_vtab(db, zSchema);
- if( rc==SQLITE_OK ){
- pNew = sqlite3_malloc( sizeof(*pNew) );
- *ppVtab = (sqlite3_vtab*)pNew;
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- pNew->nRow = 10;
- if( zNRow ) pNew->nRow = atoi(zNRow);
- pNew->iInst = iInst;
- }
- return rc;
-}
-static int vtablogCreate(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- return vtablogConnectCreate(db,pAux,argc,argv,ppVtab,pzErr,1);
-}
-static int vtablogConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- return vtablogConnectCreate(db,pAux,argc,argv,ppVtab,pzErr,0);
-}
-
-
-/*
-** This method is the destructor for vtablog_cursor objects.
-*/
-static int vtablogDisconnect(sqlite3_vtab *pVtab){
- vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
- printf("vtablogDisconnect(%d)\n", pTab->iInst);
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** This method is the destructor for vtablog_cursor objects.
-*/
-static int vtablogDestroy(sqlite3_vtab *pVtab){
- vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
- printf("vtablogDestroy(%d)\n", pTab->iInst);
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new vtablog_cursor object.
-*/
-static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- vtablog_vtab *pTab = (vtablog_vtab*)p;
- vtablog_cursor *pCur;
- printf("vtablogOpen(tab=%d, cursor=%d)\n", pTab->iInst, ++pTab->nCursor);
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->iCursor = pTab->nCursor;
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Destructor for a vtablog_cursor.
-*/
-static int vtablogClose(sqlite3_vtab_cursor *cur){
- vtablog_cursor *pCur = (vtablog_cursor*)cur;
- vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- printf("vtablogClose(tab=%d, cursor=%d)\n", pTab->iInst, pCur->iCursor);
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a vtablog_cursor to its next row of output.
-*/
-static int vtablogNext(sqlite3_vtab_cursor *cur){
- vtablog_cursor *pCur = (vtablog_cursor*)cur;
- vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- printf("vtablogNext(tab=%d, cursor=%d) rowid %d -> %d\n",
- pTab->iInst, pCur->iCursor, (int)pCur->iRowid, (int)pCur->iRowid+1);
- pCur->iRowid++;
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the vtablog_cursor
-** is currently pointing.
-*/
-static int vtablogColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- vtablog_cursor *pCur = (vtablog_cursor*)cur;
- vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- char zVal[50];
-
- if( i<26 ){
- sqlite3_snprintf(sizeof(zVal),zVal,"%c%d",
- "abcdefghijklmnopqrstuvwyz"[i], pCur->iRowid);
- }else{
- sqlite3_snprintf(sizeof(zVal),zVal,"{%d}%d", i, pCur->iRowid);
- }
- printf("vtablogColumn(tab=%d, cursor=%d, i=%d): [%s]\n",
- pTab->iInst, pCur->iCursor, i, zVal);
- sqlite3_result_text(ctx, zVal, -1, SQLITE_TRANSIENT);
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** rowid is the same as the output value.
-*/
-static int vtablogRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- vtablog_cursor *pCur = (vtablog_cursor*)cur;
- vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- printf("vtablogRowid(tab=%d, cursor=%d): %d\n",
- pTab->iInst, pCur->iCursor, (int)pCur->iRowid);
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int vtablogEof(sqlite3_vtab_cursor *cur){
- vtablog_cursor *pCur = (vtablog_cursor*)cur;
- vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- int rc = pCur->iRowid >= pTab->nRow;
- printf("vtablogEof(tab=%d, cursor=%d): %d\n",
- pTab->iInst, pCur->iCursor, rc);
- return rc;
-}
-
-/*
-** Output an sqlite3_value object's value as an SQL literal.
-*/
-static void vtablogQuote(sqlite3_value *p){
- char z[50];
- switch( sqlite3_value_type(p) ){
- case SQLITE_NULL: {
- printf("NULL");
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_snprintf(50,z,"%lld", sqlite3_value_int64(p));
- printf("%s", z);
- break;
- }
- case SQLITE_FLOAT: {
- sqlite3_snprintf(50,z,"%!.20g", sqlite3_value_double(p));
- printf("%s", z);
- break;
- }
- case SQLITE_BLOB: {
- int n = sqlite3_value_bytes(p);
- const unsigned char *z = (const unsigned char*)sqlite3_value_blob(p);
- int i;
- printf("x'");
- for(i=0; i<n; i++) printf("%02x", z[i]);
- printf("'");
- break;
- }
- case SQLITE_TEXT: {
- const char *z = (const char*)sqlite3_value_text(p);
- int i;
- char c;
- for(i=0; (c = z[i])!=0 && c!='\''; i++){}
- if( c==0 ){
- printf("'%s'",z);
- }else{
- printf("'");
- while( *z ){
- for(i=0; (c = z[i])!=0 && c!='\''; i++){}
- if( c=='\'' ) i++;
- if( i ){
- printf("%.*s", i, z);
- z += i;
- }
- if( c=='\'' ){
- printf("'");
- continue;
- }
- if( c==0 ){
- break;
- }
- z++;
- }
- printf("'");
- }
- break;
- }
- }
-}
-
-
-/*
-** This method is called to "rewind" the vtablog_cursor object back
-** to the first row of output. This method is always called at least
-** once prior to any call to vtablogColumn() or vtablogRowid() or
-** vtablogEof().
-*/
-static int vtablogFilter(
- sqlite3_vtab_cursor *cur,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- vtablog_cursor *pCur = (vtablog_cursor *)cur;
- vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- printf("vtablogFilter(tab=%d, cursor=%d):\n", pTab->iInst, pCur->iCursor);
- pCur->iRowid = 0;
- return SQLITE_OK;
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the vtablog virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-*/
-static int vtablogBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- vtablog_vtab *pTab = (vtablog_vtab*)tab;
- printf("vtablogBestIndex(tab=%d):\n", pTab->iInst);
- pIdxInfo->estimatedCost = (double)500;
- pIdxInfo->estimatedRows = 500;
- return SQLITE_OK;
-}
-
-/*
-** SQLite invokes this method to INSERT, UPDATE, or DELETE content from
-** the table.
-**
-** This implementation does not actually make any changes to the table
-** content. It merely logs the fact that the method was invoked
-*/
-static int vtablogUpdate(
- sqlite3_vtab *tab,
- int argc,
- sqlite3_value **argv,
- sqlite_int64 *pRowid
-){
- vtablog_vtab *pTab = (vtablog_vtab*)tab;
- int i;
- printf("vtablogUpdate(tab=%d):\n", pTab->iInst);
- printf(" argc=%d\n", argc);
- for(i=0; i<argc; i++){
- printf(" argv[%d]=", i);
- vtablogQuote(argv[i]);
- printf("\n");
- }
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** vtablog virtual table.
-*/
-static sqlite3_module vtablogModule = {
- 0, /* iVersion */
- vtablogCreate, /* xCreate */
- vtablogConnect, /* xConnect */
- vtablogBestIndex, /* xBestIndex */
- vtablogDisconnect, /* xDisconnect */
- vtablogDestroy, /* xDestroy */
- vtablogOpen, /* xOpen - open a cursor */
- vtablogClose, /* xClose - close a cursor */
- vtablogFilter, /* xFilter - configure scan constraints */
- vtablogNext, /* xNext - advance a cursor */
- vtablogEof, /* xEof - check for end of scan */
- vtablogColumn, /* xColumn - read data */
- vtablogRowid, /* xRowid - read data */
- vtablogUpdate, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
-};
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_vtablog_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc;
- SQLITE_EXTENSION_INIT2(pApi);
- rc = sqlite3_create_module(db, "vtablog", &vtablogModule, 0);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vtshim.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vtshim.c
deleted file mode 100644
index 0709a26a7f1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/vtshim.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
-** 2013-06-12
-**
-** 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.
-**
-*************************************************************************
-**
-** A shim that sits between the SQLite virtual table interface and
-** runtimes with garbage collector based memory management.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/* Forward references */
-typedef struct vtshim_aux vtshim_aux;
-typedef struct vtshim_vtab vtshim_vtab;
-typedef struct vtshim_cursor vtshim_cursor;
-
-
-/* The vtshim_aux argument is the auxiliary parameter that is passed
-** into sqlite3_create_module_v2().
-*/
-struct vtshim_aux {
- void *pChildAux; /* pAux for child virtual tables */
- void (*xChildDestroy)(void*); /* Destructor for pChildAux */
- sqlite3_module *pMod; /* Methods for child virtual tables */
- sqlite3 *db; /* The database to which we are attached */
- char *zName; /* Name of the module */
- int bDisposed; /* True if disposed */
- vtshim_vtab *pAllVtab; /* List of all vtshim_vtab objects */
- sqlite3_module sSelf; /* Methods used by this shim */
-};
-
-/* A vtshim virtual table object */
-struct vtshim_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- sqlite3_vtab *pChild; /* Child virtual table */
- vtshim_aux *pAux; /* Pointer to vtshim_aux object */
- vtshim_cursor *pAllCur; /* List of all cursors */
- vtshim_vtab **ppPrev; /* Previous on list */
- vtshim_vtab *pNext; /* Next on list */
-};
-
-/* A vtshim cursor object */
-struct vtshim_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3_vtab_cursor *pChild; /* Cursor generated by the managed subclass */
- vtshim_cursor **ppPrev; /* Previous on list of all cursors */
- vtshim_cursor *pNext; /* Next on list of all cursors */
-};
-
-/* Macro used to copy the child vtable error message to outer vtable */
-#define VTSHIM_COPY_ERRMSG() \
- do { \
- sqlite3_free(pVtab->base.zErrMsg); \
- pVtab->base.zErrMsg = sqlite3_mprintf("%s", pVtab->pChild->zErrMsg); \
- } while (0)
-
-/* Methods for the vtshim module */
-static int vtshimCreate(
- sqlite3 *db,
- void *ppAux,
- int argc,
- const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- vtshim_aux *pAux = (vtshim_aux*)ppAux;
- vtshim_vtab *pNew;
- int rc;
-
- assert( db==pAux->db );
- if( pAux->bDisposed ){
- if( pzErr ){
- *pzErr = sqlite3_mprintf("virtual table was disposed: \"%s\"",
- pAux->zName);
- }
- return SQLITE_ERROR;
- }
- pNew = sqlite3_malloc( sizeof(*pNew) );
- *ppVtab = (sqlite3_vtab*)pNew;
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- rc = pAux->pMod->xCreate(db, pAux->pChildAux, argc, argv,
- &pNew->pChild, pzErr);
- if( rc ){
- sqlite3_free(pNew);
- *ppVtab = 0;
- return rc;
- }
- pNew->pAux = pAux;
- pNew->ppPrev = &pAux->pAllVtab;
- pNew->pNext = pAux->pAllVtab;
- if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext;
- pAux->pAllVtab = pNew;
- return rc;
-}
-
-static int vtshimConnect(
- sqlite3 *db,
- void *ppAux,
- int argc,
- const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- vtshim_aux *pAux = (vtshim_aux*)ppAux;
- vtshim_vtab *pNew;
- int rc;
-
- assert( db==pAux->db );
- if( pAux->bDisposed ){
- if( pzErr ){
- *pzErr = sqlite3_mprintf("virtual table was disposed: \"%s\"",
- pAux->zName);
- }
- return SQLITE_ERROR;
- }
- pNew = sqlite3_malloc( sizeof(*pNew) );
- *ppVtab = (sqlite3_vtab*)pNew;
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- rc = pAux->pMod->xConnect(db, pAux->pChildAux, argc, argv,
- &pNew->pChild, pzErr);
- if( rc ){
- sqlite3_free(pNew);
- *ppVtab = 0;
- return rc;
- }
- pNew->pAux = pAux;
- pNew->ppPrev = &pAux->pAllVtab;
- pNew->pNext = pAux->pAllVtab;
- if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext;
- pAux->pAllVtab = pNew;
- return rc;
-}
-
-static int vtshimBestIndex(
- sqlite3_vtab *pBase,
- sqlite3_index_info *pIdxInfo
-){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xBestIndex(pVtab->pChild, pIdxInfo);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimDisconnect(sqlite3_vtab *pBase){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc = SQLITE_OK;
- if( !pAux->bDisposed ){
- rc = pAux->pMod->xDisconnect(pVtab->pChild);
- }
- if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev;
- *pVtab->ppPrev = pVtab->pNext;
- sqlite3_free(pVtab);
- return rc;
-}
-
-static int vtshimDestroy(sqlite3_vtab *pBase){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc = SQLITE_OK;
- if( !pAux->bDisposed ){
- rc = pAux->pMod->xDestroy(pVtab->pChild);
- }
- if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev;
- *pVtab->ppPrev = pVtab->pNext;
- sqlite3_free(pVtab);
- return rc;
-}
-
-static int vtshimOpen(sqlite3_vtab *pBase, sqlite3_vtab_cursor **ppCursor){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- vtshim_cursor *pCur;
- int rc;
- *ppCursor = 0;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- rc = pAux->pMod->xOpen(pVtab->pChild, &pCur->pChild);
- if( rc ){
- sqlite3_free(pCur);
- VTSHIM_COPY_ERRMSG();
- return rc;
- }
- pCur->pChild->pVtab = pVtab->pChild;
- *ppCursor = &pCur->base;
- pCur->ppPrev = &pVtab->pAllCur;
- if( pVtab->pAllCur ) pVtab->pAllCur->ppPrev = &pCur->pNext;
- pCur->pNext = pVtab->pAllCur;
- pVtab->pAllCur = pCur;
- return SQLITE_OK;
-}
-
-static int vtshimClose(sqlite3_vtab_cursor *pX){
- vtshim_cursor *pCur = (vtshim_cursor*)pX;
- vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
- vtshim_aux *pAux = pVtab->pAux;
- int rc = SQLITE_OK;
- if( !pAux->bDisposed ){
- rc = pAux->pMod->xClose(pCur->pChild);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- }
- if( pCur->pNext ) pCur->pNext->ppPrev = pCur->ppPrev;
- *pCur->ppPrev = pCur->pNext;
- sqlite3_free(pCur);
- return rc;
-}
-
-static int vtshimFilter(
- sqlite3_vtab_cursor *pX,
- int idxNum,
- const char *idxStr,
- int argc,
- sqlite3_value **argv
-){
- vtshim_cursor *pCur = (vtshim_cursor*)pX;
- vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xFilter(pCur->pChild, idxNum, idxStr, argc, argv);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimNext(sqlite3_vtab_cursor *pX){
- vtshim_cursor *pCur = (vtshim_cursor*)pX;
- vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xNext(pCur->pChild);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimEof(sqlite3_vtab_cursor *pX){
- vtshim_cursor *pCur = (vtshim_cursor*)pX;
- vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return 1;
- rc = pAux->pMod->xEof(pCur->pChild);
- VTSHIM_COPY_ERRMSG();
- return rc;
-}
-
-static int vtshimColumn(sqlite3_vtab_cursor *pX, sqlite3_context *ctx, int i){
- vtshim_cursor *pCur = (vtshim_cursor*)pX;
- vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xColumn(pCur->pChild, ctx, i);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimRowid(sqlite3_vtab_cursor *pX, sqlite3_int64 *pRowid){
- vtshim_cursor *pCur = (vtshim_cursor*)pX;
- vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xRowid(pCur->pChild, pRowid);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimUpdate(
- sqlite3_vtab *pBase,
- int argc,
- sqlite3_value **argv,
- sqlite3_int64 *pRowid
-){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xUpdate(pVtab->pChild, argc, argv, pRowid);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimBegin(sqlite3_vtab *pBase){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xBegin(pVtab->pChild);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimSync(sqlite3_vtab *pBase){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xSync(pVtab->pChild);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimCommit(sqlite3_vtab *pBase){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xCommit(pVtab->pChild);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimRollback(sqlite3_vtab *pBase){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xRollback(pVtab->pChild);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimFindFunction(
- sqlite3_vtab *pBase,
- int nArg,
- const char *zName,
- void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
- void **ppArg
-){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return 0;
- rc = pAux->pMod->xFindFunction(pVtab->pChild, nArg, zName, pxFunc, ppArg);
- VTSHIM_COPY_ERRMSG();
- return rc;
-}
-
-static int vtshimRename(sqlite3_vtab *pBase, const char *zNewName){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xRename(pVtab->pChild, zNewName);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimSavepoint(sqlite3_vtab *pBase, int n){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xSavepoint(pVtab->pChild, n);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimRelease(sqlite3_vtab *pBase, int n){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xRelease(pVtab->pChild, n);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-static int vtshimRollbackTo(sqlite3_vtab *pBase, int n){
- vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
- vtshim_aux *pAux = pVtab->pAux;
- int rc;
- if( pAux->bDisposed ) return SQLITE_ERROR;
- rc = pAux->pMod->xRollbackTo(pVtab->pChild, n);
- if( rc!=SQLITE_OK ){
- VTSHIM_COPY_ERRMSG();
- }
- return rc;
-}
-
-/* The destructor function for a disposible module */
-static void vtshimAuxDestructor(void *pXAux){
- vtshim_aux *pAux = (vtshim_aux*)pXAux;
- assert( pAux->pAllVtab==0 );
- if( !pAux->bDisposed && pAux->xChildDestroy ){
- pAux->xChildDestroy(pAux->pChildAux);
- pAux->xChildDestroy = 0;
- }
- sqlite3_free(pAux->zName);
- sqlite3_free(pAux->pMod);
- sqlite3_free(pAux);
-}
-
-static int vtshimCopyModule(
- const sqlite3_module *pMod, /* Source module to be copied */
- sqlite3_module **ppMod /* Destination for copied module */
-){
- sqlite3_module *p;
- if( !pMod || !ppMod ) return SQLITE_ERROR;
- p = sqlite3_malloc( sizeof(*p) );
- if( p==0 ) return SQLITE_NOMEM;
- memcpy(p, pMod, sizeof(*p));
- *ppMod = p;
- return SQLITE_OK;
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-void *sqlite3_create_disposable_module(
- sqlite3 *db, /* SQLite connection to register module with */
- const char *zName, /* Name of the module */
- const sqlite3_module *p, /* Methods for the module */
- void *pClientData, /* Client data for xCreate/xConnect */
- void(*xDestroy)(void*) /* Module destructor function */
-){
- vtshim_aux *pAux;
- sqlite3_module *pMod;
- int rc;
- pAux = sqlite3_malloc( sizeof(*pAux) );
- if( pAux==0 ){
- if( xDestroy ) xDestroy(pClientData);
- return 0;
- }
- rc = vtshimCopyModule(p, &pMod);
- if( rc!=SQLITE_OK ){
- sqlite3_free(pAux);
- return 0;
- }
- pAux->pChildAux = pClientData;
- pAux->xChildDestroy = xDestroy;
- pAux->pMod = pMod;
- pAux->db = db;
- pAux->zName = sqlite3_mprintf("%s", zName);
- pAux->bDisposed = 0;
- pAux->pAllVtab = 0;
- pAux->sSelf.iVersion = p->iVersion<=2 ? p->iVersion : 2;
- pAux->sSelf.xCreate = p->xCreate ? vtshimCreate : 0;
- pAux->sSelf.xConnect = p->xConnect ? vtshimConnect : 0;
- pAux->sSelf.xBestIndex = p->xBestIndex ? vtshimBestIndex : 0;
- pAux->sSelf.xDisconnect = p->xDisconnect ? vtshimDisconnect : 0;
- pAux->sSelf.xDestroy = p->xDestroy ? vtshimDestroy : 0;
- pAux->sSelf.xOpen = p->xOpen ? vtshimOpen : 0;
- pAux->sSelf.xClose = p->xClose ? vtshimClose : 0;
- pAux->sSelf.xFilter = p->xFilter ? vtshimFilter : 0;
- pAux->sSelf.xNext = p->xNext ? vtshimNext : 0;
- pAux->sSelf.xEof = p->xEof ? vtshimEof : 0;
- pAux->sSelf.xColumn = p->xColumn ? vtshimColumn : 0;
- pAux->sSelf.xRowid = p->xRowid ? vtshimRowid : 0;
- pAux->sSelf.xUpdate = p->xUpdate ? vtshimUpdate : 0;
- pAux->sSelf.xBegin = p->xBegin ? vtshimBegin : 0;
- pAux->sSelf.xSync = p->xSync ? vtshimSync : 0;
- pAux->sSelf.xCommit = p->xCommit ? vtshimCommit : 0;
- pAux->sSelf.xRollback = p->xRollback ? vtshimRollback : 0;
- pAux->sSelf.xFindFunction = p->xFindFunction ? vtshimFindFunction : 0;
- pAux->sSelf.xRename = p->xRename ? vtshimRename : 0;
- if( p->iVersion>=2 ){
- pAux->sSelf.xSavepoint = p->xSavepoint ? vtshimSavepoint : 0;
- pAux->sSelf.xRelease = p->xRelease ? vtshimRelease : 0;
- pAux->sSelf.xRollbackTo = p->xRollbackTo ? vtshimRollbackTo : 0;
- }else{
- pAux->sSelf.xSavepoint = 0;
- pAux->sSelf.xRelease = 0;
- pAux->sSelf.xRollbackTo = 0;
- }
- rc = sqlite3_create_module_v2(db, zName, &pAux->sSelf,
- pAux, vtshimAuxDestructor);
- return rc==SQLITE_OK ? (void*)pAux : 0;
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-void sqlite3_dispose_module(void *pX){
- vtshim_aux *pAux = (vtshim_aux*)pX;
- if( !pAux->bDisposed ){
- vtshim_vtab *pVtab;
- vtshim_cursor *pCur;
- for(pVtab=pAux->pAllVtab; pVtab; pVtab=pVtab->pNext){
- for(pCur=pVtab->pAllCur; pCur; pCur=pCur->pNext){
- pAux->pMod->xClose(pCur->pChild);
- }
- pAux->pMod->xDisconnect(pVtab->pChild);
- }
- pAux->bDisposed = 1;
- if( pAux->xChildDestroy ){
- pAux->xChildDestroy(pAux->pChildAux);
- pAux->xChildDestroy = 0;
- }
- }
-}
-
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_vtshim_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- return SQLITE_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/wholenumber.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/wholenumber.c
deleted file mode 100644
index 63369c6ac47..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/wholenumber.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
-** 2011 April 02
-**
-** 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 a virtual table that returns the whole numbers
-** between 1 and 4294967295, inclusive.
-**
-** Example:
-**
-** CREATE VIRTUAL TABLE nums USING wholenumber;
-** SELECT value FROM nums WHERE value<10;
-**
-** Results in:
-**
-** 1 2 3 4 5 6 7 8 9
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-
-/* A wholenumber cursor object */
-typedef struct wholenumber_cursor wholenumber_cursor;
-struct wholenumber_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3_int64 iValue; /* Current value */
- sqlite3_int64 mxValue; /* Maximum value */
-};
-
-/* Methods for the wholenumber module */
-static int wholenumberConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3_vtab *pNew;
- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- sqlite3_declare_vtab(db, "CREATE TABLE x(value)");
- memset(pNew, 0, sizeof(*pNew));
- return SQLITE_OK;
-}
-/* Note that for this virtual table, the xCreate and xConnect
-** methods are identical. */
-
-static int wholenumberDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-/* The xDisconnect and xDestroy methods are also the same */
-
-
-/*
-** Open a new wholenumber cursor.
-*/
-static int wholenumberOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- wholenumber_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a wholenumber cursor.
-*/
-static int wholenumberClose(sqlite3_vtab_cursor *cur){
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a cursor to its next row of output
-*/
-static int wholenumberNext(sqlite3_vtab_cursor *cur){
- wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
- pCur->iValue++;
- return SQLITE_OK;
-}
-
-/*
-** Return the value associated with a wholenumber.
-*/
-static int wholenumberColumn(
- sqlite3_vtab_cursor *cur,
- sqlite3_context *ctx,
- int i
-){
- wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
- sqlite3_result_int64(ctx, pCur->iValue);
- return SQLITE_OK;
-}
-
-/*
-** The rowid.
-*/
-static int wholenumberRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
- *pRowid = pCur->iValue;
- return SQLITE_OK;
-}
-
-/*
-** When the wholenumber_cursor.rLimit value is 0 or less, that is a signal
-** that the cursor has nothing more to output.
-*/
-static int wholenumberEof(sqlite3_vtab_cursor *cur){
- wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
- return pCur->iValue>pCur->mxValue || pCur->iValue==0;
-}
-
-/*
-** Called to "rewind" a cursor back to the beginning so that
-** it starts its output over again. Always called at least once
-** prior to any wholenumberColumn, wholenumberRowid, or wholenumberEof call.
-**
-** idxNum Constraints
-** ------ ---------------------
-** 0 (none)
-** 1 value > $argv0
-** 2 value >= $argv0
-** 4 value < $argv0
-** 8 value <= $argv0
-**
-** 5 value > $argv0 AND value < $argv1
-** 6 value >= $argv0 AND value < $argv1
-** 9 value > $argv0 AND value <= $argv1
-** 10 value >= $argv0 AND value <= $argv1
-*/
-static int wholenumberFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- wholenumber_cursor *pCur = (wholenumber_cursor *)pVtabCursor;
- sqlite3_int64 v;
- int i = 0;
- pCur->iValue = 1;
- pCur->mxValue = 0xffffffff; /* 4294967295 */
- if( idxNum & 3 ){
- v = sqlite3_value_int64(argv[0]) + (idxNum&1);
- if( v>pCur->iValue && v<=pCur->mxValue ) pCur->iValue = v;
- i++;
- }
- if( idxNum & 12 ){
- v = sqlite3_value_int64(argv[i]) - ((idxNum>>2)&1);
- if( v>=pCur->iValue && v<pCur->mxValue ) pCur->mxValue = v;
- }
- return SQLITE_OK;
-}
-
-/*
-** Search for terms of these forms:
-**
-** (1) value > $value
-** (2) value >= $value
-** (4) value < $value
-** (8) value <= $value
-**
-** idxNum is an ORed combination of 1 or 2 with 4 or 8.
-*/
-static int wholenumberBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i;
- int idxNum = 0;
- int argvIdx = 1;
- int ltIdx = -1;
- int gtIdx = -1;
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GT ){
- idxNum |= 1;
- ltIdx = i;
- }
- if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE ){
- idxNum |= 2;
- ltIdx = i;
- }
- if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){
- idxNum |= 4;
- gtIdx = i;
- }
- if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){
- idxNum |= 8;
- gtIdx = i;
- }
- }
- pIdxInfo->idxNum = idxNum;
- if( ltIdx>=0 ){
- pIdxInfo->aConstraintUsage[ltIdx].argvIndex = argvIdx++;
- pIdxInfo->aConstraintUsage[ltIdx].omit = 1;
- }
- if( gtIdx>=0 ){
- pIdxInfo->aConstraintUsage[gtIdx].argvIndex = argvIdx;
- pIdxInfo->aConstraintUsage[gtIdx].omit = 1;
- }
- if( pIdxInfo->nOrderBy==1
- && pIdxInfo->aOrderBy[0].desc==0
- ){
- pIdxInfo->orderByConsumed = 1;
- }
- if( (idxNum & 12)==0 ){
- pIdxInfo->estimatedCost = (double)100000000;
- }else if( (idxNum & 3)==0 ){
- pIdxInfo->estimatedCost = (double)5;
- }else{
- pIdxInfo->estimatedCost = (double)1;
- }
- return SQLITE_OK;
-}
-
-/*
-** A virtual table module that provides read-only access to a
-** Tcl global variable namespace.
-*/
-static sqlite3_module wholenumberModule = {
- 0, /* iVersion */
- wholenumberConnect,
- wholenumberConnect,
- wholenumberBestIndex,
- wholenumberDisconnect,
- wholenumberDisconnect,
- wholenumberOpen, /* xOpen - open a cursor */
- wholenumberClose, /* xClose - close a cursor */
- wholenumberFilter, /* xFilter - configure scan constraints */
- wholenumberNext, /* xNext - advance a cursor */
- wholenumberEof, /* xEof - check for end of scan */
- wholenumberColumn, /* xColumn - read data */
- wholenumberRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_wholenumber_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_create_module(db, "wholenumber", &wholenumberModule, 0);
-#endif
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/zipfile.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/zipfile.c
deleted file mode 100644
index 9f2258ef0b4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/zipfile.c
+++ /dev/null
@@ -1,2177 +0,0 @@
-/*
-** 2017-12-26
-**
-** 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 a virtual table for reading and writing ZIP archive
-** files.
-**
-** Usage example:
-**
-** SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
-**
-** Current limitations:
-**
-** * No support for encryption
-** * No support for ZIP archives spanning multiple files
-** * No support for zip64 extensions
-** * Only the "inflate/deflate" (zlib) compression method is supported
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <zlib.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-#ifndef SQLITE_AMALGAMATION
-
-typedef sqlite3_int64 i64;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned long u32;
-#define MIN(a,b) ((a)<(b) ? (a) : (b))
-
-#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
-# define ALWAYS(X) (1)
-# define NEVER(X) (0)
-#elif !defined(NDEBUG)
-# define ALWAYS(X) ((X)?1:(assert(0),0))
-# define NEVER(X) ((X)?(assert(0),1):0)
-#else
-# define ALWAYS(X) (X)
-# define NEVER(X) (X)
-#endif
-
-#endif /* SQLITE_AMALGAMATION */
-
-/*
-** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
-**
-** In some ways it would be better to obtain these values from system
-** header files. But, the dependency is undesirable and (a) these
-** have been stable for decades, (b) the values are part of POSIX and
-** are also made explicit in [man stat], and (c) are part of the
-** file format for zip archives.
-*/
-#ifndef S_IFDIR
-# define S_IFDIR 0040000
-#endif
-#ifndef S_IFREG
-# define S_IFREG 0100000
-#endif
-#ifndef S_IFLNK
-# define S_IFLNK 0120000
-#endif
-
-static const char ZIPFILE_SCHEMA[] =
- "CREATE TABLE y("
- "name PRIMARY KEY," /* 0: Name of file in zip archive */
- "mode," /* 1: POSIX mode for file */
- "mtime," /* 2: Last modification time (secs since 1970)*/
- "sz," /* 3: Size of object */
- "rawdata," /* 4: Raw data */
- "data," /* 5: Uncompressed data */
- "method," /* 6: Compression method (integer) */
- "z HIDDEN" /* 7: Name of zip file */
- ") WITHOUT ROWID;";
-
-#define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */
-#define ZIPFILE_BUFFER_SIZE (64*1024)
-
-
-/*
-** Magic numbers used to read and write zip files.
-**
-** ZIPFILE_NEWENTRY_MADEBY:
-** Use this value for the "version-made-by" field in new zip file
-** entries. The upper byte indicates "unix", and the lower byte
-** indicates that the zip file matches pkzip specification 3.0.
-** This is what info-zip seems to do.
-**
-** ZIPFILE_NEWENTRY_REQUIRED:
-** Value for "version-required-to-extract" field of new entries.
-** Version 2.0 is required to support folders and deflate compression.
-**
-** ZIPFILE_NEWENTRY_FLAGS:
-** Value for "general-purpose-bit-flags" field of new entries. Bit
-** 11 means "utf-8 filename and comment".
-**
-** ZIPFILE_SIGNATURE_CDS:
-** First 4 bytes of a valid CDS record.
-**
-** ZIPFILE_SIGNATURE_LFH:
-** First 4 bytes of a valid LFH record.
-**
-** ZIPFILE_SIGNATURE_EOCD
-** First 4 bytes of a valid EOCD record.
-*/
-#define ZIPFILE_EXTRA_TIMESTAMP 0x5455
-#define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30)
-#define ZIPFILE_NEWENTRY_REQUIRED 20
-#define ZIPFILE_NEWENTRY_FLAGS 0x800
-#define ZIPFILE_SIGNATURE_CDS 0x02014b50
-#define ZIPFILE_SIGNATURE_LFH 0x04034b50
-#define ZIPFILE_SIGNATURE_EOCD 0x06054b50
-
-/*
-** The sizes of the fixed-size part of each of the three main data
-** structures in a zip archive.
-*/
-#define ZIPFILE_LFH_FIXED_SZ 30
-#define ZIPFILE_EOCD_FIXED_SZ 22
-#define ZIPFILE_CDS_FIXED_SZ 46
-
-/*
-*** 4.3.16 End of central directory record:
-***
-*** end of central dir signature 4 bytes (0x06054b50)
-*** number of this disk 2 bytes
-*** number of the disk with the
-*** start of the central directory 2 bytes
-*** total number of entries in the
-*** central directory on this disk 2 bytes
-*** total number of entries in
-*** the central directory 2 bytes
-*** size of the central directory 4 bytes
-*** offset of start of central
-*** directory with respect to
-*** the starting disk number 4 bytes
-*** .ZIP file comment length 2 bytes
-*** .ZIP file comment (variable size)
-*/
-typedef struct ZipfileEOCD ZipfileEOCD;
-struct ZipfileEOCD {
- u16 iDisk;
- u16 iFirstDisk;
- u16 nEntry;
- u16 nEntryTotal;
- u32 nSize;
- u32 iOffset;
-};
-
-/*
-*** 4.3.12 Central directory structure:
-***
-*** ...
-***
-*** central file header signature 4 bytes (0x02014b50)
-*** version made by 2 bytes
-*** version needed to extract 2 bytes
-*** general purpose bit flag 2 bytes
-*** compression method 2 bytes
-*** last mod file time 2 bytes
-*** last mod file date 2 bytes
-*** crc-32 4 bytes
-*** compressed size 4 bytes
-*** uncompressed size 4 bytes
-*** file name length 2 bytes
-*** extra field length 2 bytes
-*** file comment length 2 bytes
-*** disk number start 2 bytes
-*** internal file attributes 2 bytes
-*** external file attributes 4 bytes
-*** relative offset of local header 4 bytes
-*/
-typedef struct ZipfileCDS ZipfileCDS;
-struct ZipfileCDS {
- u16 iVersionMadeBy;
- u16 iVersionExtract;
- u16 flags;
- u16 iCompression;
- u16 mTime;
- u16 mDate;
- u32 crc32;
- u32 szCompressed;
- u32 szUncompressed;
- u16 nFile;
- u16 nExtra;
- u16 nComment;
- u16 iDiskStart;
- u16 iInternalAttr;
- u32 iExternalAttr;
- u32 iOffset;
- char *zFile; /* Filename (sqlite3_malloc()) */
-};
-
-/*
-*** 4.3.7 Local file header:
-***
-*** local file header signature 4 bytes (0x04034b50)
-*** version needed to extract 2 bytes
-*** general purpose bit flag 2 bytes
-*** compression method 2 bytes
-*** last mod file time 2 bytes
-*** last mod file date 2 bytes
-*** crc-32 4 bytes
-*** compressed size 4 bytes
-*** uncompressed size 4 bytes
-*** file name length 2 bytes
-*** extra field length 2 bytes
-***
-*/
-typedef struct ZipfileLFH ZipfileLFH;
-struct ZipfileLFH {
- u16 iVersionExtract;
- u16 flags;
- u16 iCompression;
- u16 mTime;
- u16 mDate;
- u32 crc32;
- u32 szCompressed;
- u32 szUncompressed;
- u16 nFile;
- u16 nExtra;
-};
-
-typedef struct ZipfileEntry ZipfileEntry;
-struct ZipfileEntry {
- ZipfileCDS cds; /* Parsed CDS record */
- u32 mUnixTime; /* Modification time, in UNIX format */
- u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */
- i64 iDataOff; /* Offset to data in file (if aData==0) */
- u8 *aData; /* cds.szCompressed bytes of compressed data */
- ZipfileEntry *pNext; /* Next element in in-memory CDS */
-};
-
-/*
-** Cursor type for zipfile tables.
-*/
-typedef struct ZipfileCsr ZipfileCsr;
-struct ZipfileCsr {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- i64 iId; /* Cursor ID */
- u8 bEof; /* True when at EOF */
- u8 bNoop; /* If next xNext() call is no-op */
-
- /* Used outside of write transactions */
- FILE *pFile; /* Zip file */
- i64 iNextOff; /* Offset of next record in central directory */
- ZipfileEOCD eocd; /* Parse of central directory record */
-
- ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */
- ZipfileEntry *pCurrent; /* Current entry */
- ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */
-};
-
-typedef struct ZipfileTab ZipfileTab;
-struct ZipfileTab {
- sqlite3_vtab base; /* Base class - must be first */
- char *zFile; /* Zip file this table accesses (may be NULL) */
- sqlite3 *db; /* Host database connection */
- u8 *aBuffer; /* Temporary buffer used for various tasks */
-
- ZipfileCsr *pCsrList; /* List of cursors */
- i64 iNextCsrid;
-
- /* The following are used by write transactions only */
- ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
- ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */
- FILE *pWriteFd; /* File handle open on zip archive */
- i64 szCurrent; /* Current size of zip archive */
- i64 szOrig; /* Size of archive at start of transaction */
-};
-
-/*
-** Set the error message contained in context ctx to the results of
-** vprintf(zFmt, ...).
-*/
-static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
- char *zMsg = 0;
- va_list ap;
- va_start(ap, zFmt);
- zMsg = sqlite3_vmprintf(zFmt, ap);
- sqlite3_result_error(ctx, zMsg, -1);
- sqlite3_free(zMsg);
- va_end(ap);
-}
-
-/*
-** If string zIn is quoted, dequote it in place. Otherwise, if the string
-** is not quoted, do nothing.
-*/
-static void zipfileDequote(char *zIn){
- char q = zIn[0];
- if( q=='"' || q=='\'' || q=='`' || q=='[' ){
- int iIn = 1;
- int iOut = 0;
- if( q=='[' ) q = ']';
- while( ALWAYS(zIn[iIn]) ){
- char c = zIn[iIn++];
- if( c==q && zIn[iIn++]!=q ) break;
- zIn[iOut++] = c;
- }
- zIn[iOut] = '\0';
- }
-}
-
-/*
-** Construct a new ZipfileTab virtual table object.
-**
-** argv[0] -> module name ("zipfile")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> "column name" and other module argument fields.
-*/
-static int zipfileConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
- int nFile = 0;
- const char *zFile = 0;
- ZipfileTab *pNew = 0;
- int rc;
-
- /* If the table name is not "zipfile", require that the argument be
- ** specified. This stops zipfile tables from being created as:
- **
- ** CREATE VIRTUAL TABLE zzz USING zipfile();
- **
- ** It does not prevent:
- **
- ** CREATE VIRTUAL TABLE zipfile USING zipfile();
- */
- assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
- if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
- *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
- return SQLITE_ERROR;
- }
-
- if( argc>3 ){
- zFile = argv[3];
- nFile = (int)strlen(zFile)+1;
- }
-
- rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
- if( rc==SQLITE_OK ){
- pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, nByte+nFile);
- pNew->db = db;
- pNew->aBuffer = (u8*)&pNew[1];
- if( zFile ){
- pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
- memcpy(pNew->zFile, zFile, nFile);
- zipfileDequote(pNew->zFile);
- }
- }
- *ppVtab = (sqlite3_vtab*)pNew;
- return rc;
-}
-
-/*
-** Free the ZipfileEntry structure indicated by the only argument.
-*/
-static void zipfileEntryFree(ZipfileEntry *p){
- if( p ){
- sqlite3_free(p->cds.zFile);
- sqlite3_free(p);
- }
-}
-
-/*
-** Release resources that should be freed at the end of a write
-** transaction.
-*/
-static void zipfileCleanupTransaction(ZipfileTab *pTab){
- ZipfileEntry *pEntry;
- ZipfileEntry *pNext;
-
- if( pTab->pWriteFd ){
- fclose(pTab->pWriteFd);
- pTab->pWriteFd = 0;
- }
- for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
- pNext = pEntry->pNext;
- zipfileEntryFree(pEntry);
- }
- pTab->pFirstEntry = 0;
- pTab->pLastEntry = 0;
- pTab->szCurrent = 0;
- pTab->szOrig = 0;
-}
-
-/*
-** This method is the destructor for zipfile vtab objects.
-*/
-static int zipfileDisconnect(sqlite3_vtab *pVtab){
- zipfileCleanupTransaction((ZipfileTab*)pVtab);
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new ZipfileCsr object.
-*/
-static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
- ZipfileTab *pTab = (ZipfileTab*)p;
- ZipfileCsr *pCsr;
- pCsr = sqlite3_malloc(sizeof(*pCsr));
- *ppCsr = (sqlite3_vtab_cursor*)pCsr;
- if( pCsr==0 ){
- return SQLITE_NOMEM;
- }
- memset(pCsr, 0, sizeof(*pCsr));
- pCsr->iId = ++pTab->iNextCsrid;
- pCsr->pCsrNext = pTab->pCsrList;
- pTab->pCsrList = pCsr;
- return SQLITE_OK;
-}
-
-/*
-** Reset a cursor back to the state it was in when first returned
-** by zipfileOpen().
-*/
-static void zipfileResetCursor(ZipfileCsr *pCsr){
- ZipfileEntry *p;
- ZipfileEntry *pNext;
-
- pCsr->bEof = 0;
- if( pCsr->pFile ){
- fclose(pCsr->pFile);
- pCsr->pFile = 0;
- zipfileEntryFree(pCsr->pCurrent);
- pCsr->pCurrent = 0;
- }
-
- for(p=pCsr->pFreeEntry; p; p=pNext){
- pNext = p->pNext;
- zipfileEntryFree(p);
- }
-}
-
-/*
-** Destructor for an ZipfileCsr.
-*/
-static int zipfileClose(sqlite3_vtab_cursor *cur){
- ZipfileCsr *pCsr = (ZipfileCsr*)cur;
- ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
- ZipfileCsr **pp;
- zipfileResetCursor(pCsr);
-
- /* Remove this cursor from the ZipfileTab.pCsrList list. */
- for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
- *pp = pCsr->pCsrNext;
-
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Set the error message for the virtual table associated with cursor
-** pCsr to the results of vprintf(zFmt, ...).
-*/
-static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
- va_list ap;
- va_start(ap, zFmt);
- sqlite3_free(pTab->base.zErrMsg);
- pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
-}
-static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
- va_list ap;
- va_start(ap, zFmt);
- sqlite3_free(pCsr->base.pVtab->zErrMsg);
- pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
-}
-
-/*
-** Read nRead bytes of data from offset iOff of file pFile into buffer
-** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
-** otherwise.
-**
-** If an error does occur, output variable (*pzErrmsg) may be set to point
-** to an English language error message. It is the responsibility of the
-** caller to eventually free this buffer using
-** sqlite3_free().
-*/
-static int zipfileReadData(
- FILE *pFile, /* Read from this file */
- u8 *aRead, /* Read into this buffer */
- int nRead, /* Number of bytes to read */
- i64 iOff, /* Offset to read from */
- char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
-){
- size_t n;
- fseek(pFile, (long)iOff, SEEK_SET);
- n = fread(aRead, 1, nRead, pFile);
- if( (int)n!=nRead ){
- *pzErrmsg = sqlite3_mprintf("error in fread()");
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-
-static int zipfileAppendData(
- ZipfileTab *pTab,
- const u8 *aWrite,
- int nWrite
-){
- size_t n;
- fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
- n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
- if( (int)n!=nWrite ){
- pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
- return SQLITE_ERROR;
- }
- pTab->szCurrent += nWrite;
- return SQLITE_OK;
-}
-
-/*
-** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
-*/
-static u16 zipfileGetU16(const u8 *aBuf){
- return (aBuf[1] << 8) + aBuf[0];
-}
-
-/*
-** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
-*/
-static u32 zipfileGetU32(const u8 *aBuf){
- return ((u32)(aBuf[3]) << 24)
- + ((u32)(aBuf[2]) << 16)
- + ((u32)(aBuf[1]) << 8)
- + ((u32)(aBuf[0]) << 0);
-}
-
-/*
-** Write a 16-bit little endiate integer into buffer aBuf.
-*/
-static void zipfilePutU16(u8 *aBuf, u16 val){
- aBuf[0] = val & 0xFF;
- aBuf[1] = (val>>8) & 0xFF;
-}
-
-/*
-** Write a 32-bit little endiate integer into buffer aBuf.
-*/
-static void zipfilePutU32(u8 *aBuf, u32 val){
- aBuf[0] = val & 0xFF;
- aBuf[1] = (val>>8) & 0xFF;
- aBuf[2] = (val>>16) & 0xFF;
- aBuf[3] = (val>>24) & 0xFF;
-}
-
-#define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
-#define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
-
-#define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
-#define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
-
-/*
-** Magic numbers used to read CDS records.
-*/
-#define ZIPFILE_CDS_NFILE_OFF 28
-#define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
-
-/*
-** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
-** if the record is not well-formed, or SQLITE_OK otherwise.
-*/
-static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
- u8 *aRead = aBuf;
- u32 sig = zipfileRead32(aRead);
- int rc = SQLITE_OK;
- if( sig!=ZIPFILE_SIGNATURE_CDS ){
- rc = SQLITE_ERROR;
- }else{
- pCDS->iVersionMadeBy = zipfileRead16(aRead);
- pCDS->iVersionExtract = zipfileRead16(aRead);
- pCDS->flags = zipfileRead16(aRead);
- pCDS->iCompression = zipfileRead16(aRead);
- pCDS->mTime = zipfileRead16(aRead);
- pCDS->mDate = zipfileRead16(aRead);
- pCDS->crc32 = zipfileRead32(aRead);
- pCDS->szCompressed = zipfileRead32(aRead);
- pCDS->szUncompressed = zipfileRead32(aRead);
- assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
- pCDS->nFile = zipfileRead16(aRead);
- pCDS->nExtra = zipfileRead16(aRead);
- pCDS->nComment = zipfileRead16(aRead);
- pCDS->iDiskStart = zipfileRead16(aRead);
- pCDS->iInternalAttr = zipfileRead16(aRead);
- pCDS->iExternalAttr = zipfileRead32(aRead);
- pCDS->iOffset = zipfileRead32(aRead);
- assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
- }
-
- return rc;
-}
-
-/*
-** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
-** if the record is not well-formed, or SQLITE_OK otherwise.
-*/
-static int zipfileReadLFH(
- u8 *aBuffer,
- ZipfileLFH *pLFH
-){
- u8 *aRead = aBuffer;
- int rc = SQLITE_OK;
-
- u32 sig = zipfileRead32(aRead);
- if( sig!=ZIPFILE_SIGNATURE_LFH ){
- rc = SQLITE_ERROR;
- }else{
- pLFH->iVersionExtract = zipfileRead16(aRead);
- pLFH->flags = zipfileRead16(aRead);
- pLFH->iCompression = zipfileRead16(aRead);
- pLFH->mTime = zipfileRead16(aRead);
- pLFH->mDate = zipfileRead16(aRead);
- pLFH->crc32 = zipfileRead32(aRead);
- pLFH->szCompressed = zipfileRead32(aRead);
- pLFH->szUncompressed = zipfileRead32(aRead);
- pLFH->nFile = zipfileRead16(aRead);
- pLFH->nExtra = zipfileRead16(aRead);
- }
- return rc;
-}
-
-
-/*
-** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
-** Scan through this buffer to find an "extra-timestamp" field. If one
-** exists, extract the 32-bit modification-timestamp from it and store
-** the value in output parameter *pmTime.
-**
-** Zero is returned if no extra-timestamp record could be found (and so
-** *pmTime is left unchanged), or non-zero otherwise.
-**
-** The general format of an extra field is:
-**
-** Header ID 2 bytes
-** Data Size 2 bytes
-** Data N bytes
-*/
-static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
- int ret = 0;
- u8 *p = aExtra;
- u8 *pEnd = &aExtra[nExtra];
-
- while( p<pEnd ){
- u16 id = zipfileRead16(p);
- u16 nByte = zipfileRead16(p);
-
- switch( id ){
- case ZIPFILE_EXTRA_TIMESTAMP: {
- u8 b = p[0];
- if( b & 0x01 ){ /* 0x01 -> modtime is present */
- *pmTime = zipfileGetU32(&p[1]);
- ret = 1;
- }
- break;
- }
- }
-
- p += nByte;
- }
- return ret;
-}
-
-/*
-** Convert the standard MS-DOS timestamp stored in the mTime and mDate
-** fields of the CDS structure passed as the only argument to a 32-bit
-** UNIX seconds-since-the-epoch timestamp. Return the result.
-**
-** "Standard" MS-DOS time format:
-**
-** File modification time:
-** Bits 00-04: seconds divided by 2
-** Bits 05-10: minute
-** Bits 11-15: hour
-** File modification date:
-** Bits 00-04: day
-** Bits 05-08: month (1-12)
-** Bits 09-15: years from 1980
-**
-** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
-*/
-static u32 zipfileMtime(ZipfileCDS *pCDS){
- int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
- int M = ((pCDS->mDate >> 5) & 0x0F);
- int D = (pCDS->mDate & 0x1F);
- int B = -13;
-
- int sec = (pCDS->mTime & 0x1F)*2;
- int min = (pCDS->mTime >> 5) & 0x3F;
- int hr = (pCDS->mTime >> 11) & 0x1F;
- i64 JD;
-
- /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
-
- /* Calculate the JD in seconds for noon on the day in question */
- if( M<3 ){
- Y = Y-1;
- M = M+12;
- }
- JD = (i64)(24*60*60) * (
- (int)(365.25 * (Y + 4716))
- + (int)(30.6001 * (M + 1))
- + D + B - 1524
- );
-
- /* Correct the JD for the time within the day */
- JD += (hr-12) * 3600 + min * 60 + sec;
-
- /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
- return (u32)(JD - (i64)(24405875) * 24*60*6);
-}
-
-/*
-** The opposite of zipfileMtime(). This function populates the mTime and
-** mDate fields of the CDS structure passed as the first argument according
-** to the UNIX timestamp value passed as the second.
-*/
-static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
- /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
- i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
-
- int A, B, C, D, E;
- int yr, mon, day;
- int hr, min, sec;
-
- A = (int)((JD - 1867216.25)/36524.25);
- A = (int)(JD + 1 + A - (A/4));
- B = A + 1524;
- C = (int)((B - 122.1)/365.25);
- D = (36525*(C&32767))/100;
- E = (int)((B-D)/30.6001);
-
- day = B - D - (int)(30.6001*E);
- mon = (E<14 ? E-1 : E-13);
- yr = mon>2 ? C-4716 : C-4715;
-
- hr = (mUnixTime % (24*60*60)) / (60*60);
- min = (mUnixTime % (60*60)) / 60;
- sec = (mUnixTime % 60);
-
- if( yr>=1980 ){
- pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
- pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
- }else{
- pCds->mDate = pCds->mTime = 0;
- }
-
- assert( mUnixTime<315507600
- || mUnixTime==zipfileMtime(pCds)
- || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds))
- /* || (mUnixTime % 2) */
- );
-}
-
-/*
-** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
-** size) containing an entire zip archive image. Or, if aBlob is NULL,
-** then pFile is a file-handle open on a zip file. In either case, this
-** function creates a ZipfileEntry object based on the zip archive entry
-** for which the CDS record is at offset iOff.
-**
-** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
-** the new object. Otherwise, an SQLite error code is returned and the
-** final value of (*ppEntry) undefined.
-*/
-static int zipfileGetEntry(
- ZipfileTab *pTab, /* Store any error message here */
- const u8 *aBlob, /* Pointer to in-memory file image */
- int nBlob, /* Size of aBlob[] in bytes */
- FILE *pFile, /* If aBlob==0, read from this file */
- i64 iOff, /* Offset of CDS record */
- ZipfileEntry **ppEntry /* OUT: Pointer to new object */
-){
- u8 *aRead;
- char **pzErr = &pTab->base.zErrMsg;
- int rc = SQLITE_OK;
-
- if( aBlob==0 ){
- aRead = pTab->aBuffer;
- rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
- }else{
- aRead = (u8*)&aBlob[iOff];
- }
-
- if( rc==SQLITE_OK ){
- int nAlloc;
- ZipfileEntry *pNew;
-
- int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
- int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
- nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);
-
- nAlloc = sizeof(ZipfileEntry) + nExtra;
- if( aBlob ){
- nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
- }
-
- pNew = (ZipfileEntry*)sqlite3_malloc(nAlloc);
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pNew, 0, sizeof(ZipfileEntry));
- rc = zipfileReadCDS(aRead, &pNew->cds);
- if( rc!=SQLITE_OK ){
- *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
- }else if( aBlob==0 ){
- rc = zipfileReadData(
- pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
- );
- }else{
- aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
- }
- }
-
- if( rc==SQLITE_OK ){
- u32 *pt = &pNew->mUnixTime;
- pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
- pNew->aExtra = (u8*)&pNew[1];
- memcpy(pNew->aExtra, &aRead[nFile], nExtra);
- if( pNew->cds.zFile==0 ){
- rc = SQLITE_NOMEM;
- }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
- pNew->mUnixTime = zipfileMtime(&pNew->cds);
- }
- }
-
- if( rc==SQLITE_OK ){
- static const int szFix = ZIPFILE_LFH_FIXED_SZ;
- ZipfileLFH lfh;
- if( pFile ){
- rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
- }else{
- aRead = (u8*)&aBlob[pNew->cds.iOffset];
- }
-
- rc = zipfileReadLFH(aRead, &lfh);
- if( rc==SQLITE_OK ){
- pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
- pNew->iDataOff += lfh.nFile + lfh.nExtra;
- if( aBlob && pNew->cds.szCompressed ){
- pNew->aData = &pNew->aExtra[nExtra];
- memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
- }
- }else{
- *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
- (int)pNew->cds.iOffset
- );
- }
- }
-
- if( rc!=SQLITE_OK ){
- zipfileEntryFree(pNew);
- }else{
- *ppEntry = pNew;
- }
- }
-
- return rc;
-}
-
-/*
-** Advance an ZipfileCsr to its next row of output.
-*/
-static int zipfileNext(sqlite3_vtab_cursor *cur){
- ZipfileCsr *pCsr = (ZipfileCsr*)cur;
- int rc = SQLITE_OK;
-
- if( pCsr->pFile ){
- i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
- zipfileEntryFree(pCsr->pCurrent);
- pCsr->pCurrent = 0;
- if( pCsr->iNextOff>=iEof ){
- pCsr->bEof = 1;
- }else{
- ZipfileEntry *p = 0;
- ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
- rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
- if( rc==SQLITE_OK ){
- pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
- pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
- }
- pCsr->pCurrent = p;
- }
- }else{
- if( !pCsr->bNoop ){
- pCsr->pCurrent = pCsr->pCurrent->pNext;
- }
- if( pCsr->pCurrent==0 ){
- pCsr->bEof = 1;
- }
- }
-
- pCsr->bNoop = 0;
- return rc;
-}
-
-static void zipfileFree(void *p) {
- sqlite3_free(p);
-}
-
-/*
-** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
-** size is nOut bytes. This function uncompresses the data and sets the
-** return value in context pCtx to the result (a blob).
-**
-** If an error occurs, an error code is left in pCtx instead.
-*/
-static void zipfileInflate(
- sqlite3_context *pCtx, /* Store result here */
- const u8 *aIn, /* Compressed data */
- int nIn, /* Size of buffer aIn[] in bytes */
- int nOut /* Expected output size */
-){
- u8 *aRes = sqlite3_malloc(nOut);
- if( aRes==0 ){
- sqlite3_result_error_nomem(pCtx);
- }else{
- int err;
- z_stream str;
- memset(&str, 0, sizeof(str));
-
- str.next_in = (Byte*)aIn;
- str.avail_in = nIn;
- str.next_out = (Byte*)aRes;
- str.avail_out = nOut;
-
- err = inflateInit2(&str, -15);
- if( err!=Z_OK ){
- zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
- }else{
- err = inflate(&str, Z_NO_FLUSH);
- if( err!=Z_STREAM_END ){
- zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
- }else{
- sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
- aRes = 0;
- }
- }
- sqlite3_free(aRes);
- inflateEnd(&str);
- }
-}
-
-/*
-** Buffer aIn (size nIn bytes) contains uncompressed data. This function
-** compresses it and sets (*ppOut) to point to a buffer containing the
-** compressed data. The caller is responsible for eventually calling
-** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
-** is set to the size of buffer (*ppOut) in bytes.
-**
-** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
-** code is returned and an error message left in virtual-table handle
-** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
-** case.
-*/
-static int zipfileDeflate(
- const u8 *aIn, int nIn, /* Input */
- u8 **ppOut, int *pnOut, /* Output */
- char **pzErr /* OUT: Error message */
-){
- int nAlloc = (int)compressBound(nIn);
- u8 *aOut;
- int rc = SQLITE_OK;
-
- aOut = (u8*)sqlite3_malloc(nAlloc);
- if( aOut==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int res;
- z_stream str;
- memset(&str, 0, sizeof(str));
- str.next_in = (Bytef*)aIn;
- str.avail_in = nIn;
- str.next_out = aOut;
- str.avail_out = nAlloc;
-
- deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
- res = deflate(&str, Z_FINISH);
-
- if( res==Z_STREAM_END ){
- *ppOut = aOut;
- *pnOut = (int)str.total_out;
- }else{
- sqlite3_free(aOut);
- *pzErr = sqlite3_mprintf("zipfile: deflate() error");
- rc = SQLITE_ERROR;
- }
- deflateEnd(&str);
- }
-
- return rc;
-}
-
-
-/*
-** Return values of columns for the row at which the series_cursor
-** is currently pointing.
-*/
-static int zipfileColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- ZipfileCsr *pCsr = (ZipfileCsr*)cur;
- ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
- int rc = SQLITE_OK;
- switch( i ){
- case 0: /* name */
- sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
- break;
- case 1: /* mode */
- /* TODO: Whether or not the following is correct surely depends on
- ** the platform on which the archive was created. */
- sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
- break;
- case 2: { /* mtime */
- sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
- break;
- }
- case 3: { /* sz */
- if( sqlite3_vtab_nochange(ctx)==0 ){
- sqlite3_result_int64(ctx, pCDS->szUncompressed);
- }
- break;
- }
- case 4: /* rawdata */
- if( sqlite3_vtab_nochange(ctx) ) break;
- case 5: { /* data */
- if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
- int sz = pCDS->szCompressed;
- int szFinal = pCDS->szUncompressed;
- if( szFinal>0 ){
- u8 *aBuf;
- u8 *aFree = 0;
- if( pCsr->pCurrent->aData ){
- aBuf = pCsr->pCurrent->aData;
- }else{
- aBuf = aFree = sqlite3_malloc(sz);
- if( aBuf==0 ){
- rc = SQLITE_NOMEM;
- }else{
- FILE *pFile = pCsr->pFile;
- if( pFile==0 ){
- pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
- }
- rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
- &pCsr->base.pVtab->zErrMsg
- );
- }
- }
- if( rc==SQLITE_OK ){
- if( i==5 && pCDS->iCompression ){
- zipfileInflate(ctx, aBuf, sz, szFinal);
- }else{
- sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
- }
- }
- sqlite3_free(aFree);
- }else{
- /* Figure out if this is a directory or a zero-sized file. Consider
- ** it to be a directory either if the mode suggests so, or if
- ** the final character in the name is '/'. */
- u32 mode = pCDS->iExternalAttr >> 16;
- if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){
- sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
- }
- }
- }
- break;
- }
- case 6: /* method */
- sqlite3_result_int(ctx, pCDS->iCompression);
- break;
- default: /* z */
- assert( i==7 );
- sqlite3_result_int64(ctx, pCsr->iId);
- break;
- }
-
- return rc;
-}
-
-/*
-** Return TRUE if the cursor is at EOF.
-*/
-static int zipfileEof(sqlite3_vtab_cursor *cur){
- ZipfileCsr *pCsr = (ZipfileCsr*)cur;
- return pCsr->bEof;
-}
-
-/*
-** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
-** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
-** is guaranteed to be a file-handle open on a zip file.
-**
-** This function attempts to locate the EOCD record within the zip archive
-** and populate *pEOCD with the results of decoding it. SQLITE_OK is
-** returned if successful. Otherwise, an SQLite error code is returned and
-** an English language error message may be left in virtual-table pTab.
-*/
-static int zipfileReadEOCD(
- ZipfileTab *pTab, /* Return errors here */
- const u8 *aBlob, /* Pointer to in-memory file image */
- int nBlob, /* Size of aBlob[] in bytes */
- FILE *pFile, /* Read from this file if aBlob==0 */
- ZipfileEOCD *pEOCD /* Object to populate */
-){
- u8 *aRead = pTab->aBuffer; /* Temporary buffer */
- int nRead; /* Bytes to read from file */
- int rc = SQLITE_OK;
-
- if( aBlob==0 ){
- i64 iOff; /* Offset to read from */
- i64 szFile; /* Total size of file in bytes */
- fseek(pFile, 0, SEEK_END);
- szFile = (i64)ftell(pFile);
- if( szFile==0 ){
- memset(pEOCD, 0, sizeof(ZipfileEOCD));
- return SQLITE_OK;
- }
- nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
- iOff = szFile - nRead;
- rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
- }else{
- nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
- aRead = (u8*)&aBlob[nBlob-nRead];
- }
-
- if( rc==SQLITE_OK ){
- int i;
-
- /* Scan backwards looking for the signature bytes */
- for(i=nRead-20; i>=0; i--){
- if( aRead[i]==0x50 && aRead[i+1]==0x4b
- && aRead[i+2]==0x05 && aRead[i+3]==0x06
- ){
- break;
- }
- }
- if( i<0 ){
- pTab->base.zErrMsg = sqlite3_mprintf(
- "cannot find end of central directory record"
- );
- return SQLITE_ERROR;
- }
-
- aRead += i+4;
- pEOCD->iDisk = zipfileRead16(aRead);
- pEOCD->iFirstDisk = zipfileRead16(aRead);
- pEOCD->nEntry = zipfileRead16(aRead);
- pEOCD->nEntryTotal = zipfileRead16(aRead);
- pEOCD->nSize = zipfileRead32(aRead);
- pEOCD->iOffset = zipfileRead32(aRead);
- }
-
- return rc;
-}
-
-/*
-** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
-** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
-** to the end of the list. Otherwise, it is added to the list immediately
-** before pBefore (which is guaranteed to be a part of said list).
-*/
-static void zipfileAddEntry(
- ZipfileTab *pTab,
- ZipfileEntry *pBefore,
- ZipfileEntry *pNew
-){
- assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
- assert( pNew->pNext==0 );
- if( pBefore==0 ){
- if( pTab->pFirstEntry==0 ){
- pTab->pFirstEntry = pTab->pLastEntry = pNew;
- }else{
- assert( pTab->pLastEntry->pNext==0 );
- pTab->pLastEntry->pNext = pNew;
- pTab->pLastEntry = pNew;
- }
- }else{
- ZipfileEntry **pp;
- for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
- pNew->pNext = pBefore;
- *pp = pNew;
- }
-}
-
-static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
- ZipfileEOCD eocd;
- int rc;
- int i;
- i64 iOff;
-
- rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
- iOff = eocd.iOffset;
- for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
- ZipfileEntry *pNew = 0;
- rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);
-
- if( rc==SQLITE_OK ){
- zipfileAddEntry(pTab, 0, pNew);
- iOff += ZIPFILE_CDS_FIXED_SZ;
- iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
- }
- }
- return rc;
-}
-
-/*
-** xFilter callback.
-*/
-static int zipfileFilter(
- sqlite3_vtab_cursor *cur,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
- ZipfileCsr *pCsr = (ZipfileCsr*)cur;
- const char *zFile = 0; /* Zip file to scan */
- int rc = SQLITE_OK; /* Return Code */
- int bInMemory = 0; /* True for an in-memory zipfile */
-
- zipfileResetCursor(pCsr);
-
- if( pTab->zFile ){
- zFile = pTab->zFile;
- }else if( idxNum==0 ){
- zipfileCursorErr(pCsr, "zipfile() function requires an argument");
- return SQLITE_ERROR;
- }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
- const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
- int nBlob = sqlite3_value_bytes(argv[0]);
- assert( pTab->pFirstEntry==0 );
- rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
- pCsr->pFreeEntry = pTab->pFirstEntry;
- pTab->pFirstEntry = pTab->pLastEntry = 0;
- if( rc!=SQLITE_OK ) return rc;
- bInMemory = 1;
- }else{
- zFile = (const char*)sqlite3_value_text(argv[0]);
- }
-
- if( 0==pTab->pWriteFd && 0==bInMemory ){
- pCsr->pFile = fopen(zFile, "rb");
- if( pCsr->pFile==0 ){
- zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
- rc = SQLITE_ERROR;
- }else{
- rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
- if( rc==SQLITE_OK ){
- if( pCsr->eocd.nEntry==0 ){
- pCsr->bEof = 1;
- }else{
- pCsr->iNextOff = pCsr->eocd.iOffset;
- rc = zipfileNext(cur);
- }
- }
- }
- }else{
- pCsr->bNoop = 1;
- pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
- rc = zipfileNext(cur);
- }
-
- return rc;
-}
-
-/*
-** xBestIndex callback.
-*/
-static int zipfileBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i;
-
- for(i=0; i<pIdxInfo->nConstraint; i++){
- const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
- if( pCons->usable==0 ) continue;
- if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
- break;
- }
-
- if( i<pIdxInfo->nConstraint ){
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- pIdxInfo->estimatedCost = 1000.0;
- pIdxInfo->idxNum = 1;
- }else{
- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
- pIdxInfo->idxNum = 0;
- }
-
- return SQLITE_OK;
-}
-
-static ZipfileEntry *zipfileNewEntry(const char *zPath){
- ZipfileEntry *pNew;
- pNew = sqlite3_malloc(sizeof(ZipfileEntry));
- if( pNew ){
- memset(pNew, 0, sizeof(ZipfileEntry));
- pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
- if( pNew->cds.zFile==0 ){
- sqlite3_free(pNew);
- pNew = 0;
- }
- }
- return pNew;
-}
-
-static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
- ZipfileCDS *pCds = &pEntry->cds;
- u8 *a = aBuf;
-
- pCds->nExtra = 9;
-
- /* Write the LFH itself */
- zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
- zipfileWrite16(a, pCds->iVersionExtract);
- zipfileWrite16(a, pCds->flags);
- zipfileWrite16(a, pCds->iCompression);
- zipfileWrite16(a, pCds->mTime);
- zipfileWrite16(a, pCds->mDate);
- zipfileWrite32(a, pCds->crc32);
- zipfileWrite32(a, pCds->szCompressed);
- zipfileWrite32(a, pCds->szUncompressed);
- zipfileWrite16(a, (u16)pCds->nFile);
- zipfileWrite16(a, pCds->nExtra);
- assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
-
- /* Add the file name */
- memcpy(a, pCds->zFile, (int)pCds->nFile);
- a += (int)pCds->nFile;
-
- /* The "extra" data */
- zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
- zipfileWrite16(a, 5);
- *a++ = 0x01;
- zipfileWrite32(a, pEntry->mUnixTime);
-
- return a-aBuf;
-}
-
-static int zipfileAppendEntry(
- ZipfileTab *pTab,
- ZipfileEntry *pEntry,
- const u8 *pData,
- int nData
-){
- u8 *aBuf = pTab->aBuffer;
- int nBuf;
- int rc;
-
- nBuf = zipfileSerializeLFH(pEntry, aBuf);
- rc = zipfileAppendData(pTab, aBuf, nBuf);
- if( rc==SQLITE_OK ){
- pEntry->iDataOff = pTab->szCurrent;
- rc = zipfileAppendData(pTab, pData, nData);
- }
-
- return rc;
-}
-
-static int zipfileGetMode(
- sqlite3_value *pVal,
- int bIsDir, /* If true, default to directory */
- u32 *pMode, /* OUT: Mode value */
- char **pzErr /* OUT: Error message */
-){
- const char *z = (const char*)sqlite3_value_text(pVal);
- u32 mode = 0;
- if( z==0 ){
- mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
- }else if( z[0]>='0' && z[0]<='9' ){
- mode = (unsigned int)sqlite3_value_int(pVal);
- }else{
- const char zTemplate[11] = "-rwxrwxrwx";
- int i;
- if( strlen(z)!=10 ) goto parse_error;
- switch( z[0] ){
- case '-': mode |= S_IFREG; break;
- case 'd': mode |= S_IFDIR; break;
- case 'l': mode |= S_IFLNK; break;
- default: goto parse_error;
- }
- for(i=1; i<10; i++){
- if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
- else if( z[i]!='-' ) goto parse_error;
- }
- }
- if( ((mode & S_IFDIR)==0)==bIsDir ){
- /* The "mode" attribute is a directory, but data has been specified.
- ** Or vice-versa - no data but "mode" is a file or symlink. */
- *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
- return SQLITE_CONSTRAINT;
- }
- *pMode = mode;
- return SQLITE_OK;
-
- parse_error:
- *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
- return SQLITE_ERROR;
-}
-
-/*
-** Both (const char*) arguments point to nul-terminated strings. Argument
-** nB is the value of strlen(zB). This function returns 0 if the strings are
-** identical, ignoring any trailing '/' character in either path. */
-static int zipfileComparePath(const char *zA, const char *zB, int nB){
- int nA = (int)strlen(zA);
- if( zA[nA-1]=='/' ) nA--;
- if( zB[nB-1]=='/' ) nB--;
- if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
- return 1;
-}
-
-static int zipfileBegin(sqlite3_vtab *pVtab){
- ZipfileTab *pTab = (ZipfileTab*)pVtab;
- int rc = SQLITE_OK;
-
- assert( pTab->pWriteFd==0 );
-
- /* Open a write fd on the file. Also load the entire central directory
- ** structure into memory. During the transaction any new file data is
- ** appended to the archive file, but the central directory is accumulated
- ** in main-memory until the transaction is committed. */
- pTab->pWriteFd = fopen(pTab->zFile, "ab+");
- if( pTab->pWriteFd==0 ){
- pTab->base.zErrMsg = sqlite3_mprintf(
- "zipfile: failed to open file %s for writing", pTab->zFile
- );
- rc = SQLITE_ERROR;
- }else{
- fseek(pTab->pWriteFd, 0, SEEK_END);
- pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
- rc = zipfileLoadDirectory(pTab, 0, 0);
- }
-
- if( rc!=SQLITE_OK ){
- zipfileCleanupTransaction(pTab);
- }
-
- return rc;
-}
-
-/*
-** Return the current time as a 32-bit timestamp in UNIX epoch format (like
-** time(2)).
-*/
-static u32 zipfileTime(void){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
- u32 ret;
- if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
- i64 ms;
- pVfs->xCurrentTimeInt64(pVfs, &ms);
- ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
- }else{
- double day;
- pVfs->xCurrentTime(pVfs, &day);
- ret = (u32)((day - 2440587.5) * 86400);
- }
- return ret;
-}
-
-/*
-** Return a 32-bit timestamp in UNIX epoch format.
-**
-** If the value passed as the only argument is either NULL or an SQL NULL,
-** return the current time. Otherwise, return the value stored in (*pVal)
-** cast to a 32-bit unsigned integer.
-*/
-static u32 zipfileGetTime(sqlite3_value *pVal){
- if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
- return zipfileTime();
- }
- return (u32)sqlite3_value_int64(pVal);
-}
-
-/*
-** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
-** linked list. Remove it from the list and free the object.
-*/
-static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
- if( pOld ){
- ZipfileEntry **pp;
- for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
- *pp = (*pp)->pNext;
- zipfileEntryFree(pOld);
- }
-}
-
-/*
-** xUpdate method.
-*/
-static int zipfileUpdate(
- sqlite3_vtab *pVtab,
- int nVal,
- sqlite3_value **apVal,
- sqlite_int64 *pRowid
-){
- ZipfileTab *pTab = (ZipfileTab*)pVtab;
- int rc = SQLITE_OK; /* Return Code */
- ZipfileEntry *pNew = 0; /* New in-memory CDS entry */
-
- u32 mode = 0; /* Mode for new entry */
- u32 mTime = 0; /* Modification time for new entry */
- i64 sz = 0; /* Uncompressed size */
- const char *zPath = 0; /* Path for new entry */
- int nPath = 0; /* strlen(zPath) */
- const u8 *pData = 0; /* Pointer to buffer containing content */
- int nData = 0; /* Size of pData buffer in bytes */
- int iMethod = 0; /* Compression method for new entry */
- u8 *pFree = 0; /* Free this */
- char *zFree = 0; /* Also free this */
- ZipfileEntry *pOld = 0;
- ZipfileEntry *pOld2 = 0;
- int bUpdate = 0; /* True for an update that modifies "name" */
- int bIsDir = 0;
- u32 iCrc32 = 0;
-
- if( pTab->pWriteFd==0 ){
- rc = zipfileBegin(pVtab);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- /* If this is a DELETE or UPDATE, find the archive entry to delete. */
- if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
- const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
- int nDelete = (int)strlen(zDelete);
- if( nVal>1 ){
- const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
- if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
- bUpdate = 1;
- }
- }
- for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
- if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
- break;
- }
- assert( pOld->pNext );
- }
- }
-
- if( nVal>1 ){
- /* Check that "sz" and "rawdata" are both NULL: */
- if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
- zipfileTableErr(pTab, "sz must be NULL");
- rc = SQLITE_CONSTRAINT;
- }
- if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
- zipfileTableErr(pTab, "rawdata must be NULL");
- rc = SQLITE_CONSTRAINT;
- }
-
- if( rc==SQLITE_OK ){
- if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
- /* data=NULL. A directory */
- bIsDir = 1;
- }else{
- /* Value specified for "data", and possibly "method". This must be
- ** a regular file or a symlink. */
- const u8 *aIn = sqlite3_value_blob(apVal[7]);
- int nIn = sqlite3_value_bytes(apVal[7]);
- int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
-
- iMethod = sqlite3_value_int(apVal[8]);
- sz = nIn;
- pData = aIn;
- nData = nIn;
- if( iMethod!=0 && iMethod!=8 ){
- zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
- rc = SQLITE_CONSTRAINT;
- }else{
- if( bAuto || iMethod ){
- int nCmp;
- rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
- if( rc==SQLITE_OK ){
- if( iMethod || nCmp<nIn ){
- iMethod = 8;
- pData = pFree;
- nData = nCmp;
- }
- }
- }
- iCrc32 = crc32(0, aIn, nIn);
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
- }
-
- if( rc==SQLITE_OK ){
- zPath = (const char*)sqlite3_value_text(apVal[2]);
- nPath = (int)strlen(zPath);
- mTime = zipfileGetTime(apVal[4]);
- }
-
- if( rc==SQLITE_OK && bIsDir ){
- /* For a directory, check that the last character in the path is a
- ** '/'. This appears to be required for compatibility with info-zip
- ** (the unzip command on unix). It does not create directories
- ** otherwise. */
- if( zPath[nPath-1]!='/' ){
- zFree = sqlite3_mprintf("%s/", zPath);
- if( zFree==0 ){ rc = SQLITE_NOMEM; }
- zPath = (const char*)zFree;
- nPath++;
- }
- }
-
- /* Check that we're not inserting a duplicate entry -OR- updating an
- ** entry with a path, thereby making it into a duplicate. */
- if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
- ZipfileEntry *p;
- for(p=pTab->pFirstEntry; p; p=p->pNext){
- if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
- switch( sqlite3_vtab_on_conflict(pTab->db) ){
- case SQLITE_IGNORE: {
- goto zipfile_update_done;
- }
- case SQLITE_REPLACE: {
- pOld2 = p;
- break;
- }
- default: {
- zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
- rc = SQLITE_CONSTRAINT;
- break;
- }
- }
- break;
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- /* Create the new CDS record. */
- pNew = zipfileNewEntry(zPath);
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
- pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
- pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
- pNew->cds.iCompression = (u16)iMethod;
- zipfileMtimeToDos(&pNew->cds, mTime);
- pNew->cds.crc32 = iCrc32;
- pNew->cds.szCompressed = nData;
- pNew->cds.szUncompressed = (u32)sz;
- pNew->cds.iExternalAttr = (mode<<16);
- pNew->cds.iOffset = (u32)pTab->szCurrent;
- pNew->cds.nFile = (u16)nPath;
- pNew->mUnixTime = (u32)mTime;
- rc = zipfileAppendEntry(pTab, pNew, pData, nData);
- zipfileAddEntry(pTab, pOld, pNew);
- }
- }
- }
-
- if( rc==SQLITE_OK && (pOld || pOld2) ){
- ZipfileCsr *pCsr;
- for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
- if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){
- pCsr->pCurrent = pCsr->pCurrent->pNext;
- pCsr->bNoop = 1;
- }
- }
-
- zipfileRemoveEntryFromList(pTab, pOld);
- zipfileRemoveEntryFromList(pTab, pOld2);
- }
-
-zipfile_update_done:
- sqlite3_free(pFree);
- sqlite3_free(zFree);
- return rc;
-}
-
-static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
- u8 *a = aBuf;
- zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
- zipfileWrite16(a, p->iDisk);
- zipfileWrite16(a, p->iFirstDisk);
- zipfileWrite16(a, p->nEntry);
- zipfileWrite16(a, p->nEntryTotal);
- zipfileWrite32(a, p->nSize);
- zipfileWrite32(a, p->iOffset);
- zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/
-
- return a-aBuf;
-}
-
-static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
- int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
- assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
- return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
-}
-
-/*
-** Serialize the CDS structure into buffer aBuf[]. Return the number
-** of bytes written.
-*/
-static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
- u8 *a = aBuf;
- ZipfileCDS *pCDS = &pEntry->cds;
-
- if( pEntry->aExtra==0 ){
- pCDS->nExtra = 9;
- }
-
- zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
- zipfileWrite16(a, pCDS->iVersionMadeBy);
- zipfileWrite16(a, pCDS->iVersionExtract);
- zipfileWrite16(a, pCDS->flags);
- zipfileWrite16(a, pCDS->iCompression);
- zipfileWrite16(a, pCDS->mTime);
- zipfileWrite16(a, pCDS->mDate);
- zipfileWrite32(a, pCDS->crc32);
- zipfileWrite32(a, pCDS->szCompressed);
- zipfileWrite32(a, pCDS->szUncompressed);
- assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
- zipfileWrite16(a, pCDS->nFile);
- zipfileWrite16(a, pCDS->nExtra);
- zipfileWrite16(a, pCDS->nComment);
- zipfileWrite16(a, pCDS->iDiskStart);
- zipfileWrite16(a, pCDS->iInternalAttr);
- zipfileWrite32(a, pCDS->iExternalAttr);
- zipfileWrite32(a, pCDS->iOffset);
-
- memcpy(a, pCDS->zFile, pCDS->nFile);
- a += pCDS->nFile;
-
- if( pEntry->aExtra ){
- int n = (int)pCDS->nExtra + (int)pCDS->nComment;
- memcpy(a, pEntry->aExtra, n);
- a += n;
- }else{
- assert( pCDS->nExtra==9 );
- zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
- zipfileWrite16(a, 5);
- *a++ = 0x01;
- zipfileWrite32(a, pEntry->mUnixTime);
- }
-
- return a-aBuf;
-}
-
-static int zipfileCommit(sqlite3_vtab *pVtab){
- ZipfileTab *pTab = (ZipfileTab*)pVtab;
- int rc = SQLITE_OK;
- if( pTab->pWriteFd ){
- i64 iOffset = pTab->szCurrent;
- ZipfileEntry *p;
- ZipfileEOCD eocd;
- int nEntry = 0;
-
- /* Write out all entries */
- for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
- int n = zipfileSerializeCDS(p, pTab->aBuffer);
- rc = zipfileAppendData(pTab, pTab->aBuffer, n);
- nEntry++;
- }
-
- /* Write out the EOCD record */
- eocd.iDisk = 0;
- eocd.iFirstDisk = 0;
- eocd.nEntry = (u16)nEntry;
- eocd.nEntryTotal = (u16)nEntry;
- eocd.nSize = (u32)(pTab->szCurrent - iOffset);
- eocd.iOffset = (u32)iOffset;
- rc = zipfileAppendEOCD(pTab, &eocd);
-
- zipfileCleanupTransaction(pTab);
- }
- return rc;
-}
-
-static int zipfileRollback(sqlite3_vtab *pVtab){
- return zipfileCommit(pVtab);
-}
-
-static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
- ZipfileCsr *pCsr;
- for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
- if( iId==pCsr->iId ) break;
- }
- return pCsr;
-}
-
-static void zipfileFunctionCds(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- ZipfileCsr *pCsr;
- ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
- assert( argc>0 );
-
- pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
- if( pCsr ){
- ZipfileCDS *p = &pCsr->pCurrent->cds;
- char *zRes = sqlite3_mprintf("{"
- "\"version-made-by\" : %u, "
- "\"version-to-extract\" : %u, "
- "\"flags\" : %u, "
- "\"compression\" : %u, "
- "\"time\" : %u, "
- "\"date\" : %u, "
- "\"crc32\" : %u, "
- "\"compressed-size\" : %u, "
- "\"uncompressed-size\" : %u, "
- "\"file-name-length\" : %u, "
- "\"extra-field-length\" : %u, "
- "\"file-comment-length\" : %u, "
- "\"disk-number-start\" : %u, "
- "\"internal-attr\" : %u, "
- "\"external-attr\" : %u, "
- "\"offset\" : %u }",
- (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
- (u32)p->flags, (u32)p->iCompression,
- (u32)p->mTime, (u32)p->mDate,
- (u32)p->crc32, (u32)p->szCompressed,
- (u32)p->szUncompressed, (u32)p->nFile,
- (u32)p->nExtra, (u32)p->nComment,
- (u32)p->iDiskStart, (u32)p->iInternalAttr,
- (u32)p->iExternalAttr, (u32)p->iOffset
- );
-
- if( zRes==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
- sqlite3_free(zRes);
- }
- }
-}
-
-/*
-** xFindFunction method.
-*/
-static int zipfileFindFunction(
- sqlite3_vtab *pVtab, /* Virtual table handle */
- int nArg, /* Number of SQL function arguments */
- const char *zName, /* Name of SQL function */
- void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
- void **ppArg /* OUT: User data for *pxFunc */
-){
- if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
- *pxFunc = zipfileFunctionCds;
- *ppArg = (void*)pVtab;
- return 1;
- }
- return 0;
-}
-
-typedef struct ZipfileBuffer ZipfileBuffer;
-struct ZipfileBuffer {
- u8 *a; /* Pointer to buffer */
- int n; /* Size of buffer in bytes */
- int nAlloc; /* Byte allocated at a[] */
-};
-
-typedef struct ZipfileCtx ZipfileCtx;
-struct ZipfileCtx {
- int nEntry;
- ZipfileBuffer body;
- ZipfileBuffer cds;
-};
-
-static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
- if( pBuf->n+nByte>pBuf->nAlloc ){
- u8 *aNew;
- int nNew = pBuf->n ? pBuf->n*2 : 512;
- int nReq = pBuf->n + nByte;
-
- while( nNew<nReq ) nNew = nNew*2;
- aNew = sqlite3_realloc(pBuf->a, nNew);
- if( aNew==0 ) return SQLITE_NOMEM;
- pBuf->a = aNew;
- pBuf->nAlloc = nNew;
- }
- return SQLITE_OK;
-}
-
-/*
-** xStep() callback for the zipfile() aggregate. This can be called in
-** any of the following ways:
-**
-** SELECT zipfile(name,data) ...
-** SELECT zipfile(name,mode,mtime,data) ...
-** SELECT zipfile(name,mode,mtime,data,method) ...
-*/
-void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
- ZipfileCtx *p; /* Aggregate function context */
- ZipfileEntry e; /* New entry to add to zip archive */
-
- sqlite3_value *pName = 0;
- sqlite3_value *pMode = 0;
- sqlite3_value *pMtime = 0;
- sqlite3_value *pData = 0;
- sqlite3_value *pMethod = 0;
-
- int bIsDir = 0;
- u32 mode;
- int rc = SQLITE_OK;
- char *zErr = 0;
-
- int iMethod = -1; /* Compression method to use (0 or 8) */
-
- const u8 *aData = 0; /* Possibly compressed data for new entry */
- int nData = 0; /* Size of aData[] in bytes */
- int szUncompressed = 0; /* Size of data before compression */
- u8 *aFree = 0; /* Free this before returning */
- u32 iCrc32 = 0; /* crc32 of uncompressed data */
-
- char *zName = 0; /* Path (name) of new entry */
- int nName = 0; /* Size of zName in bytes */
- char *zFree = 0; /* Free this before returning */
- int nByte;
-
- memset(&e, 0, sizeof(e));
- p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
- if( p==0 ) return;
-
- /* Martial the arguments into stack variables */
- if( nVal!=2 && nVal!=4 && nVal!=5 ){
- zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
- rc = SQLITE_ERROR;
- goto zipfile_step_out;
- }
- pName = apVal[0];
- if( nVal==2 ){
- pData = apVal[1];
- }else{
- pMode = apVal[1];
- pMtime = apVal[2];
- pData = apVal[3];
- if( nVal==5 ){
- pMethod = apVal[4];
- }
- }
-
- /* Check that the 'name' parameter looks ok. */
- zName = (char*)sqlite3_value_text(pName);
- nName = sqlite3_value_bytes(pName);
- if( zName==0 ){
- zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
- rc = SQLITE_ERROR;
- goto zipfile_step_out;
- }
-
- /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
- ** deflate compression) or NULL (choose automatically). */
- if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
- iMethod = (int)sqlite3_value_int64(pMethod);
- if( iMethod!=0 && iMethod!=8 ){
- zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
- rc = SQLITE_ERROR;
- goto zipfile_step_out;
- }
- }
-
- /* Now inspect the data. If this is NULL, then the new entry must be a
- ** directory. Otherwise, figure out whether or not the data should
- ** be deflated or simply stored in the zip archive. */
- if( sqlite3_value_type(pData)==SQLITE_NULL ){
- bIsDir = 1;
- iMethod = 0;
- }else{
- aData = sqlite3_value_blob(pData);
- szUncompressed = nData = sqlite3_value_bytes(pData);
- iCrc32 = crc32(0, aData, nData);
- if( iMethod<0 || iMethod==8 ){
- int nOut = 0;
- rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
- if( rc!=SQLITE_OK ){
- goto zipfile_step_out;
- }
- if( iMethod==8 || nOut<nData ){
- aData = aFree;
- nData = nOut;
- iMethod = 8;
- }else{
- iMethod = 0;
- }
- }
- }
-
- /* Decode the "mode" argument. */
- rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
- if( rc ) goto zipfile_step_out;
-
- /* Decode the "mtime" argument. */
- e.mUnixTime = zipfileGetTime(pMtime);
-
- /* If this is a directory entry, ensure that there is exactly one '/'
- ** at the end of the path. Or, if this is not a directory and the path
- ** ends in '/' it is an error. */
- if( bIsDir==0 ){
- if( zName[nName-1]=='/' ){
- zErr = sqlite3_mprintf("non-directory name must not end with /");
- rc = SQLITE_ERROR;
- goto zipfile_step_out;
- }
- }else{
- if( zName[nName-1]!='/' ){
- zName = zFree = sqlite3_mprintf("%s/", zName);
- nName++;
- if( zName==0 ){
- rc = SQLITE_NOMEM;
- goto zipfile_step_out;
- }
- }else{
- while( nName>1 && zName[nName-2]=='/' ) nName--;
- }
- }
-
- /* Assemble the ZipfileEntry object for the new zip archive entry */
- e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
- e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
- e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
- e.cds.iCompression = (u16)iMethod;
- zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
- e.cds.crc32 = iCrc32;
- e.cds.szCompressed = nData;
- e.cds.szUncompressed = szUncompressed;
- e.cds.iExternalAttr = (mode<<16);
- e.cds.iOffset = p->body.n;
- e.cds.nFile = (u16)nName;
- e.cds.zFile = zName;
-
- /* Append the LFH to the body of the new archive */
- nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
- if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
- p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
-
- /* Append the data to the body of the new archive */
- if( nData>0 ){
- if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
- memcpy(&p->body.a[p->body.n], aData, nData);
- p->body.n += nData;
- }
-
- /* Append the CDS record to the directory of the new archive */
- nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
- if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
- p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
-
- /* Increment the count of entries in the archive */
- p->nEntry++;
-
- zipfile_step_out:
- sqlite3_free(aFree);
- sqlite3_free(zFree);
- if( rc ){
- if( zErr ){
- sqlite3_result_error(pCtx, zErr, -1);
- }else{
- sqlite3_result_error_code(pCtx, rc);
- }
- }
- sqlite3_free(zErr);
-}
-
-/*
-** xFinalize() callback for zipfile aggregate function.
-*/
-void zipfileFinal(sqlite3_context *pCtx){
- ZipfileCtx *p;
- ZipfileEOCD eocd;
- int nZip;
- u8 *aZip;
-
- p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
- if( p==0 ) return;
- if( p->nEntry>0 ){
- memset(&eocd, 0, sizeof(eocd));
- eocd.nEntry = (u16)p->nEntry;
- eocd.nEntryTotal = (u16)p->nEntry;
- eocd.nSize = p->cds.n;
- eocd.iOffset = p->body.n;
-
- nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
- aZip = (u8*)sqlite3_malloc(nZip);
- if( aZip==0 ){
- sqlite3_result_error_nomem(pCtx);
- }else{
- memcpy(aZip, p->body.a, p->body.n);
- memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
- zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
- sqlite3_result_blob(pCtx, aZip, nZip, zipfileFree);
- }
- }
-
- sqlite3_free(p->body.a);
- sqlite3_free(p->cds.a);
-}
-
-
-/*
-** Register the "zipfile" virtual table.
-*/
-static int zipfileRegister(sqlite3 *db){
- static sqlite3_module zipfileModule = {
- 1, /* iVersion */
- zipfileConnect, /* xCreate */
- zipfileConnect, /* xConnect */
- zipfileBestIndex, /* xBestIndex */
- zipfileDisconnect, /* xDisconnect */
- zipfileDisconnect, /* xDestroy */
- zipfileOpen, /* xOpen - open a cursor */
- zipfileClose, /* xClose - close a cursor */
- zipfileFilter, /* xFilter - configure scan constraints */
- zipfileNext, /* xNext - advance a cursor */
- zipfileEof, /* xEof - check for end of scan */
- zipfileColumn, /* xColumn - read data */
- 0, /* xRowid - read data */
- zipfileUpdate, /* xUpdate */
- zipfileBegin, /* xBegin */
- 0, /* xSync */
- zipfileCommit, /* xCommit */
- zipfileRollback, /* xRollback */
- zipfileFindFunction, /* xFindMethod */
- 0, /* xRename */
- };
-
- int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
- if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
- zipfileStep, zipfileFinal
- );
- }
- return rc;
-}
-#else /* SQLITE_OMIT_VIRTUALTABLE */
-# define zipfileRegister(x) SQLITE_OK
-#endif
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_zipfile_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- return zipfileRegister(db);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/zorder.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/zorder.c
deleted file mode 100644
index c385d3c3c39..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/misc/zorder.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-** 2018-02-09
-**
-** 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.
-**
-******************************************************************************
-**
-** SQL functions for z-order (Morton code) transformations.
-**
-** zorder(X0,X0,..,xN) Generate an N+1 dimension Morton code
-**
-** unzorder(Z,N,I) Extract the I-th dimension from N-dimensional
-** Morton code Z.
-*/
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-
-/*
-** Functions: zorder(X0,X1,....)
-**
-** Convert integers X0, X1, ... into morton code.
-**
-** The output is a signed 64-bit integer. If any argument is too large,
-** an error is thrown.
-*/
-static void zorderFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3_int64 z, x[63];
- int i, j;
- z = 0;
- for(i=0; i<argc; i++){
- x[i] = sqlite3_value_int64(argv[i]);
- }
- if( argc>0 ){
- for(i=0; i<63; i++){
- j = i%argc;
- z |= (x[j]&1)<<i;
- x[j] >>= 1;
- }
- }
- sqlite3_result_int64(context, z);
- for(i=0; i<argc; i++){
- if( x[i] ){
- sqlite3_result_error(context, "parameter too large", -1);
- }
- }
-}
-
-
-/*
-** Functions: unzorder(Z,N,I)
-**
-** Assuming that Z is an N-dimensional Morton code, extract the I-th
-** dimension.
-*/
-static void unzorderFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3_int64 z, n, i, x;
- int j, k;
- z = sqlite3_value_int64(argv[0]);
- n = sqlite3_value_int64(argv[1]);
- i = sqlite3_value_int64(argv[2]);
- x = 0;
- for(k=0, j=i; j<63; j+=n, k++){
- x |= ((z>>j)&1)<<k;
- }
- sqlite3_result_int64(context, x);
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_zorder_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "zorder", -1, SQLITE_UTF8, 0,
- zorderFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "unzorder", 3, SQLITE_UTF8, 0,
- unzorderFunc, 0, 0);
- }
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu.c
deleted file mode 100644
index 1dac4523057..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-** 2014 August 30
-**
-** 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 contains a command-line application that uses the RBU
-** extension. See the usage() function below for an explanation.
-*/
-
-#include "sqlite3rbu.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
-** Print a usage message and exit.
-*/
-void usage(const char *zArgv0){
- fprintf(stderr,
-"Usage: %s ?OPTIONS? TARGET-DB RBU-DB\n"
-"\n"
-"Where options are:\n"
-"\n"
-" -step NSTEP\n"
-" -statstep NSTATSTEP\n"
-" -vacuum\n"
-" -presql SQL\n"
-"\n"
-" If the -vacuum switch is not present, argument RBU-DB must be an RBU\n"
-" database containing an update suitable for target database TARGET-DB.\n"
-" Or, if -vacuum is specified, then TARGET-DB is a database to vacuum using\n"
-" RBU, and RBU-DB is used as the state database for the vacuum (refer to\n"
-" API documentation for details).\n"
-"\n"
-" If NSTEP is set to less than or equal to zero (the default value), this \n"
-" program attempts to perform the entire update or vacuum operation before\n"
-" exiting\n"
-"\n"
-" If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n"
-" to sqlite3rbu_step(). If the RBU update has not been completely applied\n"
-" after the NSTEP'th call is made, the state is saved in the database RBU-DB\n"
-" and the program exits. Subsequent invocations of this (or any other RBU)\n"
-" application will use this state to resume applying the RBU update to the\n"
-" target db.\n"
-"\n"
-, zArgv0);
- exit(1);
-}
-
-void report_default_vfs(){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
- fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName);
-}
-
-void report_rbu_vfs(sqlite3rbu *pRbu){
- sqlite3 *db = sqlite3rbu_db(pRbu, 0);
- if( db ){
- char *zName = 0;
- sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName);
- if( zName ){
- fprintf(stdout, "using vfs \"%s\"\n", zName);
- }else{
- fprintf(stdout, "vfs name not available\n");
- }
- sqlite3_free(zName);
- }
-}
-
-int main(int argc, char **argv){
- int i;
- const char *zTarget; /* Target database to apply RBU to */
- const char *zRbu; /* Database containing RBU */
- char zBuf[200]; /* Buffer for printf() */
- char *zErrmsg; /* Error message, if any */
- sqlite3rbu *pRbu; /* RBU handle */
- int nStep = 0; /* Maximum number of step() calls */
- int nStatStep = 0; /* Report stats after this many step calls */
- int bVacuum = 0;
- const char *zPreSql = 0;
- int rc;
- sqlite3_int64 nProgress = 0;
- int nArgc = argc-2;
-
- if( argc<3 ) usage(argv[0]);
- for(i=1; i<nArgc; i++){
- const char *zArg = argv[i];
- int nArg = strlen(zArg);
- if( nArg>1 && nArg<=8 && 0==memcmp(zArg, "-vacuum", nArg) ){
- bVacuum = 1;
- }else if( nArg>1 && nArg<=7
- && 0==memcmp(zArg, "-presql", nArg) && i<nArg-1 ){
- i++;
- zPreSql = argv[i];
- }else if( nArg>1 && nArg<=5 && 0==memcmp(zArg, "-step", nArg) && i<nArg-1 ){
- i++;
- nStep = atoi(argv[i]);
- }else if( nArg>1 && nArg<=9
- && 0==memcmp(zArg, "-statstep", nArg) && i<nArg-1
- ){
- i++;
- nStatStep = atoi(argv[i]);
- }else{
- usage(argv[0]);
- }
- }
-
- zTarget = argv[argc-2];
- zRbu = argv[argc-1];
-
- report_default_vfs();
-
- /* Open an RBU handle. A vacuum handle if -vacuum was specified, or a
- ** regular RBU update handle otherwise. */
- if( bVacuum ){
- pRbu = sqlite3rbu_vacuum(zTarget, zRbu);
- }else{
- pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
- }
- report_rbu_vfs(pRbu);
-
- if( zPreSql && pRbu ){
- sqlite3 *db = sqlite3rbu_db(pRbu, 0);
- rc = sqlite3_exec(db, zPreSql, 0, 0, 0);
- if( rc==SQLITE_OK ){
- sqlite3 *db = sqlite3rbu_db(pRbu, 1);
- rc = sqlite3_exec(db, zPreSql, 0, 0, 0);
- }
- }
-
- /* If nStep is less than or equal to zero, call
- ** sqlite3rbu_step() until either the RBU has been completely applied
- ** or an error occurs. Or, if nStep is greater than zero, call
- ** sqlite3rbu_step() a maximum of nStep times. */
- if( rc==SQLITE_OK ){
- for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++){
- if( nStatStep>0 && (i % nStatStep)==0 ){
- sqlite3_int64 nUsed;
- sqlite3_int64 nHighwater;
- sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &nUsed, &nHighwater, 0);
- fprintf(stdout, "memory used=%lld highwater=%lld", nUsed, nHighwater);
- if( bVacuum==0 ){
- int one;
- int two;
- sqlite3rbu_bp_progress(pRbu, &one, &two);
- fprintf(stdout, " progress=%d/%d\n", one, two);
- }else{
- fprintf(stdout, "\n");
- }
- fflush(stdout);
- }
- }
- nProgress = sqlite3rbu_progress(pRbu);
- rc = sqlite3rbu_close(pRbu, &zErrmsg);
- }
-
- /* Let the user know what happened. */
- switch( rc ){
- case SQLITE_OK:
- sqlite3_snprintf(sizeof(zBuf), zBuf,
- "SQLITE_OK: rbu update incomplete (%lld operations so far)\n",
- nProgress
- );
- fprintf(stdout, "%s", zBuf);
- break;
-
- case SQLITE_DONE:
- sqlite3_snprintf(sizeof(zBuf), zBuf,
- "SQLITE_DONE: rbu update completed (%lld operations)\n",
- nProgress
- );
- fprintf(stdout, "%s", zBuf);
- break;
-
- default:
- fprintf(stderr, "error=%d: %s\n", rc, zErrmsg);
- break;
- }
-
- sqlite3_free(zErrmsg);
- return (rc==SQLITE_OK || rc==SQLITE_DONE) ? 0 : 1;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu1.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu1.test
deleted file mode 100644
index 1d16c1cd0a8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu1.test
+++ /dev/null
@@ -1,673 +0,0 @@
-# 2014 August 30
-#
-# 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.
-#
-#***********************************************************************
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbu1
-
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-
-# Create a simple RBU database. That expects to write to a table:
-#
-# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
-#
-proc create_rbu1 {filename} {
- forcedelete $filename
- sqlite3 rbu1 $filename
- rbu1 eval {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 2, 3, 0);
- INSERT INTO data_t1 VALUES(2, 'two', 'three', 0);
- INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0);
- }
- rbu1 close
- return $filename
-}
-
-# Create a simple RBU database. That expects to write to a table:
-#
-# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
-#
-# This RBU includes both insert and delete operations.
-#
-proc create_rbu4 {filename} {
- forcedelete $filename
- sqlite3 rbu1 $filename
- rbu1 eval {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 2, 3, 0);
- INSERT INTO data_t1 VALUES(2, NULL, 5, 1);
- INSERT INTO data_t1 VALUES(3, 8, 9, 0);
- INSERT INTO data_t1 VALUES(4, NULL, 11, 1);
- }
- rbu1 close
- return $filename
-}
-#
-# Create a simple RBU database. That expects to write to a table:
-#
-# CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY);
-#
-# This RBU includes both insert and delete operations.
-#
-proc create_rbu4b {filename} {
- forcedelete $filename
- sqlite3 rbu1 $filename
- rbu1 eval {
- CREATE TABLE data_t1(c, b, '(a)', rbu_control);
- INSERT INTO data_t1 VALUES(3, 2, 1, 0);
- INSERT INTO data_t1 VALUES(5, NULL, 2, 1);
- INSERT INTO data_t1 VALUES(9, 8, 3, 0);
- INSERT INTO data_t1 VALUES(11, NULL, 4, 1);
- }
- rbu1 close
- return $filename
-}
-
-# Create a simple RBU database. That expects to write to a table:
-#
-# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
-#
-# This RBU includes update statements.
-#
-proc create_rbu5 {filename} {
- forcedelete $filename
- sqlite3 rbu5 $filename
- rbu5 eval {
- CREATE TABLE data_t1(a, b, c, d, rbu_control);
- INSERT INTO data_t1 VALUES(1, NULL, NULL, 5, '...x'); -- SET d = 5
- INSERT INTO data_t1 VALUES(2, NULL, 10, 5, '..xx'); -- SET c=10, d = 5
- INSERT INTO data_t1 VALUES(3, 11, NULL, NULL, '.x..'); -- SET b=11
- }
- rbu5 close
- return $filename
-}
-
-
-# Same as [step_rbu], except using a URI to open the target db.
-#
-proc step_rbu_uri {target rbu} {
- while 1 {
- sqlite3rbu rbu file:$target?xyz=&abc=123 $rbu
- set rc [rbu step]
- rbu close
- if {$rc != "SQLITE_OK"} break
- }
- set rc
-}
-
-# Same as [step_rbu], except using an external state database - "state.db"
-#
-proc step_rbu_state {target rbu} {
- while 1 {
- sqlite3rbu rbu $target $rbu state.db
- set rc [rbu step]
- rbu close
- if {$rc != "SQLITE_OK"} break
- }
- set rc
-}
-
-proc dbfilecksum {file} {
- sqlite3 ck $file
- set cksum [dbcksum ck main]
- ck close
- set cksum
-}
-
-foreach {tn3 create_vfs destroy_vfs} {
- 1 {} {}
- 2 {
- sqlite3rbu_create_vfs -default myrbu ""
- } {
- sqlite3rbu_destroy_vfs myrbu
- }
-} {
-
- eval $create_vfs
-
- foreach {tn2 cmd} {
- 1 run_rbu
- 2 step_rbu 3 step_rbu_uri 4 step_rbu_state
- 5 step_rbu_legacy
- } {
- foreach {tn schema} {
- 1 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- }
- 2 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- }
- 3 {
- CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
- }
- 4 {
- CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b);
- }
- 5 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b);
- }
- 6 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(c)) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b, a);
- }
- 7 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b, c);
- CREATE INDEX i2 ON t1(c, b);
- CREATE INDEX i3 ON t1(a, b, c, a, b, c);
- }
-
- 8 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b, c);
- CREATE INDEX i2 ON t1(c, b);
- CREATE INDEX i3 ON t1(a, b, c, a, b, c);
- }
-
- 9 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c));
- CREATE INDEX i1 ON t1(b);
- }
-
- 10 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b DESC);
- }
-
- 11 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b DESC, a ASC, c DESC);
- }
-
- 12 {
- CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID;
- }
-
- 13 {
- CREATE TABLE t1(a INT, b, c, PRIMARY KEY(a DESC)) WITHOUT ROWID;
- }
-
- 14 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a DESC, c)) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b);
- }
-
- 15 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c DESC)) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b);
- }
-
- 16 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(c DESC, a)) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b DESC, c, a);
- }
- } {
- reset_db
- execsql $schema
- create_rbu1 rbu.db
- set check [dbfilecksum rbu.db]
- forcedelete state.db
-
- do_test $tn3.1.$tn2.$tn.1 {
- $cmd test.db rbu.db
- } {SQLITE_DONE}
-
- do_execsql_test $tn3.1.$tn2.$tn.2 { SELECT * FROM t1 ORDER BY a ASC } {
- 1 2 3
- 2 two three
- 3 {} 8.2
- }
- do_execsql_test $tn3.1.$tn2.$tn.3 { SELECT * FROM t1 ORDER BY b ASC } {
- 3 {} 8.2
- 1 2 3
- 2 two three
- }
- do_execsql_test $tn3.1.$tn2.$tn.4 { SELECT * FROM t1 ORDER BY c ASC } {
- 1 2 3
- 3 {} 8.2
- 2 two three
- }
-
- do_execsql_test $tn3.1.$tn2.$tn.5 { PRAGMA integrity_check } ok
-
- if {$cmd=="step_rbu_state"} {
- do_test $tn3.1.$tn2.$tn.6 { file exists state.db } 1
- do_test $tn3.1.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 1
- } else {
- do_test $tn3.1.$tn2.$tn.8 { file exists state.db } 0
- do_test $tn3.1.$tn2.$tn.9 { expr {$check == [dbfilecksum rbu.db]} } 0
- }
- }
- }
-
- #-------------------------------------------------------------------------
- # Check that an RBU cannot be applied to a table that has no PK.
- #
- # UPDATE: At one point RBU required that all tables featured either
- # explicit IPK columns or were declared WITHOUT ROWID. This has been
- # relaxed so that external PRIMARY KEYs on tables with automatic rowids
- # are now allowed.
- #
- # UPDATE 2: Tables without any PRIMARY KEY declaration are now allowed.
- # However the input table must feature an "rbu_rowid" column.
- #
- reset_db
- create_rbu1 rbu.db
- do_execsql_test $tn3.2.1 { CREATE TABLE t1(a, b, c) }
- do_test $tn3.2.2 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_ERROR}
- do_test $tn3.2.3 {
- list [catch { rbu close } msg] $msg
- } {1 {SQLITE_ERROR - table data_t1 requires rbu_rowid column}}
- reset_db
- do_execsql_test $tn3.2.4 { CREATE TABLE t1(a PRIMARY KEY, b, c) }
- do_test $tn3.2.5 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_OK}
- do_test $tn3.2.6 {
- list [catch { rbu close } msg] $msg
- } {0 SQLITE_OK}
-
- #-------------------------------------------------------------------------
- # Check that if a UNIQUE constraint is violated the current and all
- # subsequent [rbu step] calls return SQLITE_CONSTRAINT. And that the RBU
- # transaction is rolled back by the [rbu close] that deletes the rbu
- # handle.
- #
- foreach {tn errcode errmsg schema} {
- 1 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.a" {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- INSERT INTO t1 VALUES(3, 2, 1);
- }
-
- 2 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.c" {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE);
- INSERT INTO t1 VALUES(4, 2, 'three');
- }
-
- 3 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.a" {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- INSERT INTO t1 VALUES(3, 2, 1);
- }
-
- 4 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.c" {
- CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
- INSERT INTO t1 VALUES(4, 2, 'three');
- }
-
- } {
- reset_db
- execsql $schema
- set cksum [dbcksum db main]
-
- do_test $tn3.3.$tn.1 {
- create_rbu1 rbu.db
- sqlite3rbu rbu test.db rbu.db
- while {[set res [rbu step]]=="SQLITE_OK"} {}
- set res
- } $errcode
-
- do_test $tn3.3.$tn.2 { rbu step } $errcode
-
- do_test $tn3.3.$tn.3 {
- list [catch { rbu close } msg] $msg
- } [list 1 "$errcode - $errmsg"]
-
- do_test $tn3.3.$tn.4 { dbcksum db main } $cksum
- }
-
- #-------------------------------------------------------------------------
- #
- foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state } {
- foreach {tn schema} {
- 1 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- }
- 2 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- }
- 3 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- CREATE INDEX i2 ON t1(c, b);
- CREATE INDEX i3 ON t1(c, b, c);
- }
- 4 {
- CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b);
- CREATE INDEX i2 ON t1(c, b);
- CREATE INDEX i3 ON t1(c, b, c);
- }
- 5 {
- CREATE TABLE t1(a INT PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- CREATE INDEX i2 ON t1(c, b);
- CREATE INDEX i3 ON t1(c, b, c);
- }
-
- 6 {
- CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c);
- CREATE INDEX i1 ON t1(b DESC);
- CREATE INDEX i2 ON t1(c, b);
- CREATE INDEX i3 ON t1(c DESC, b, c);
- }
- 7 {
- CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b);
- CREATE INDEX i2 ON t1(c, b);
- CREATE INDEX i3 ON t1(c, b, c);
- }
- } {
- reset_db
- execsql $schema
- execsql {
- INSERT INTO t1 VALUES(2, 'hello', 'world');
- INSERT INTO t1 VALUES(4, 'hello', 'planet');
- INSERT INTO t1 VALUES(6, 'hello', 'xyz');
- }
-
- create_rbu4 rbu.db
- set check [dbfilecksum rbu.db]
- forcedelete state.db
-
- do_test $tn3.4.$tn2.$tn.1 {
- $cmd test.db rbu.db
- } {SQLITE_DONE}
-
- do_execsql_test $tn3.4.$tn2.$tn.2 {
- SELECT * FROM t1 ORDER BY a ASC;
- } {
- 1 2 3
- 3 8 9
- 6 hello xyz
- }
-
- do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok
-
- if {$cmd=="step_rbu_state"} {
- do_test $tn3.4.$tn2.$tn.4 { file exists state.db } 1
- do_test $tn3.4.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1
- } else {
- do_test $tn3.4.$tn2.$tn.6 { file exists state.db } 0
- do_test $tn3.4.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0
- }
- }
- }
-
- foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state} {
- foreach {tn schema} {
- 1 {
- CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY);
- CREATE INDEX i1 ON t1(c, b);
- }
- 2 {
- CREATE TABLE t1(c, b, '(a)' PRIMARY KEY);
- }
- 3 {
- CREATE TABLE t1(c, b, '(a)' PRIMARY KEY) WITHOUT ROWID;
- }
- } {
- reset_db
- execsql $schema
- execsql {
- INSERT INTO t1('(a)', b, c) VALUES(2, 'hello', 'world');
- INSERT INTO t1('(a)', b, c) VALUES(4, 'hello', 'planet');
- INSERT INTO t1('(a)', b, c) VALUES(6, 'hello', 'xyz');
- }
-
- create_rbu4b rbu.db
- set check [dbfilecksum rbu.db]
- forcedelete state.db
-
- do_test $tn3.5.$tn2.$tn.1 {
- $cmd test.db rbu.db
- } {SQLITE_DONE}
-
- do_execsql_test $tn3.5.$tn2.$tn.2 {
- SELECT * FROM t1 ORDER BY "(a)" ASC;
- } {
- 3 2 1
- 9 8 3
- xyz hello 6
- }
-
- do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok
-
- if {$cmd=="step_rbu_state"} {
- do_test $tn3.5.$tn2.$tn.4 { file exists state.db } 1
- do_test $tn3.5.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1
- } else {
- do_test $tn3.5.$tn2.$tn.6 { file exists state.db } 0
- do_test $tn3.5.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0
- }
- }
- }
-
- #-------------------------------------------------------------------------
- #
- foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state} {
- foreach {tn schema} {
- 1 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
- }
- 2 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
- CREATE INDEX i1 ON t1(d);
- CREATE INDEX i2 ON t1(d, c);
- CREATE INDEX i3 ON t1(d, c, b);
- CREATE INDEX i4 ON t1(b);
- CREATE INDEX i5 ON t1(c);
- CREATE INDEX i6 ON t1(c, b);
- }
- 3 {
- CREATE TABLE t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(d);
- CREATE INDEX i2 ON t1(d, c);
- CREATE INDEX i3 ON t1(d, c, b);
- CREATE INDEX i4 ON t1(b);
- CREATE INDEX i5 ON t1(c);
- CREATE INDEX i6 ON t1(c, b);
- }
- 4 {
- CREATE TABLE t1(a PRIMARY KEY, b, c, d);
- CREATE INDEX i1 ON t1(d);
- CREATE INDEX i2 ON t1(d, c);
- CREATE INDEX i3 ON t1(d, c, b);
- CREATE INDEX i4 ON t1(b);
- CREATE INDEX i5 ON t1(c);
- CREATE INDEX i6 ON t1(c, b);
- }
- } {
- reset_db
- execsql $schema
- execsql {
- INSERT INTO t1 VALUES(1, 2, 3, 4);
- INSERT INTO t1 VALUES(2, 5, 6, 7);
- INSERT INTO t1 VALUES(3, 8, 9, 10);
- }
-
- create_rbu5 rbu.db
- set check [dbfilecksum rbu.db]
- forcedelete state.db
-
- do_test $tn3.5.$tn2.$tn.1 {
- $cmd test.db rbu.db
- } {SQLITE_DONE}
-
- do_execsql_test $tn3.5.$tn2.$tn.2 {
- SELECT * FROM t1 ORDER BY a ASC;
- } {
- 1 2 3 5
- 2 5 10 5
- 3 11 9 10
- }
-
- do_execsql_test $tn3.6.$tn2.$tn.3 { PRAGMA integrity_check } ok
-
- if {$cmd=="step_rbu_state"} {
- do_test $tn3.6.$tn2.$tn.4 { file exists state.db } 1
- do_test $tn3.6.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1
- } else {
- do_test $tn3.6.$tn2.$tn.6 { file exists state.db } 0
- do_test $tn3.6.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0
- }
- }
- }
-
- #-------------------------------------------------------------------------
- # Test some error cases:
- #
- # * A virtual table with no rbu_rowid column.
- # * A no-PK table with no rbu_rowid column.
- # * A PK table with an rbu_rowid column.
- #
- # 6: An update string of the wrong length
- #
- ifcapable fts3 {
- foreach {tn schema error} {
- 1 {
- CREATE TABLE t1(a, b);
- CREATE TABLE rbu.data_t1(a, b, rbu_control);
- } {SQLITE_ERROR - table data_t1 requires rbu_rowid column}
-
- 2 {
- CREATE VIRTUAL TABLE t1 USING fts4(a, b);
- CREATE TABLE rbu.data_t1(a, b, rbu_control);
- } {SQLITE_ERROR - table data_t1 requires rbu_rowid column}
-
- 3 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control);
- } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column}
-
- 4 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control);
- } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column}
-
- 5 {
- CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
- CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control);
- } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column}
-
- 6 {
- CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
- CREATE TABLE rbu.data_t1(a, b, rbu_control);
- INSERT INTO rbu.data_t1 VALUES(1, 2, 'x.x');
- } {SQLITE_ERROR - invalid rbu_control value}
-
- 7 {
- CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
- CREATE TABLE rbu.data_t1(a, b, rbu_control);
- INSERT INTO rbu.data_t1 VALUES(1, 2, NULL);
- } {SQLITE_ERROR - invalid rbu_control value}
-
- 8 {
- CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
- CREATE TABLE rbu.data_t1(a, b, rbu_control);
- INSERT INTO rbu.data_t1 VALUES(1, 2, 4);
- } {SQLITE_ERROR - invalid rbu_control value}
-
- 9 {
- CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
- CREATE TABLE rbu.data_t1(a, b, rbu_control);
- INSERT INTO rbu.data_t1 VALUES(1, 2, 3);
- } {SQLITE_ERROR - invalid rbu_control value}
-
- 10 {
- CREATE TABLE t2(a, b);
- CREATE TABLE rbu.data_t1(a, b, rbu_control);
- INSERT INTO rbu.data_t1 VALUES(1, 2, 2);
- } {SQLITE_ERROR - no such table: t1}
-
- 11 {
- CREATE TABLE rbu.data_t2(a, b, rbu_control);
- INSERT INTO rbu.data_t2 VALUES(1, 2, 2);
- } {SQLITE_ERROR - no such table: t2}
-
- } {
- reset_db
- forcedelete rbu.db
- execsql { ATTACH 'rbu.db' AS rbu }
- execsql $schema
-
- do_test $tn3.7.$tn {
- list [catch { run_rbu test.db rbu.db } msg] $msg
- } [list 1 $error]
- }
- }
-
- # Test that an RBU database containing no input tables is handled
- # correctly.
- reset_db
- forcedelete rbu.db
- do_test $tn3.8.1 {
- list [catch { run_rbu test.db rbu.db } msg] $msg
- } {0 SQLITE_DONE}
-
- # Test that an RBU database containing only empty data_xxx tables is
- # also handled correctly.
- reset_db
- forcedelete rbu.db
- do_execsql_test $tn3.8.2.1 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 2);
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE data_t1(a, b, rbu_control);
- DETACH rbu;
- }
- do_test $tn3.8.2.1 {
- list [catch { run_rbu test.db rbu.db } msg] $msg
- } {0 SQLITE_DONE}
-
- # Test that RBU can update indexes containing NULL values.
- #
- reset_db
- forcedelete rbu.db
- do_execsql_test $tn3.9.1 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b, c);
- INSERT INTO t1 VALUES(1, 1, NULL);
- INSERT INTO t1 VALUES(2, NULL, 2);
- INSERT INTO t1 VALUES(3, NULL, NULL);
-
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, NULL, NULL, 1);
- INSERT INTO data_t1 VALUES(3, NULL, NULL, 1);
- } {}
-
- do_test $tn3.9.2 {
- list [catch { run_rbu test.db rbu.db } msg] $msg
- } {0 SQLITE_DONE}
-
- do_execsql_test $tn3.9.3 {
- SELECT * FROM t1
- } {2 {} 2}
- do_execsql_test $tn3.9.4 { PRAGMA integrity_check } {ok}
-
- catch { db close }
- eval $destroy_vfs
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu10.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu10.test
deleted file mode 100644
index 4b398b6ab39..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu10.test
+++ /dev/null
@@ -1,188 +0,0 @@
-# 2014 August 30
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbu10
-
-
-#--------------------------------------------------------------------
-# Test that UPDATE commands work even if the input columns are in a
-# different order to the output columns.
-#
-do_execsql_test 1.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- INSERT INTO t1 VALUES(1, 'b', 'c');
-}
-
-proc apply_rbu {sql} {
- forcedelete rbu.db
- sqlite3 db2 rbu.db
- db2 eval $sql
- db2 close
- sqlite3rbu rbu test.db rbu.db
- while { [rbu step]=="SQLITE_OK" } {}
- rbu close
-}
-
-do_test 1.1 {
- apply_rbu {
- CREATE TABLE data_t1(a, c, b, rbu_control);
- INSERT INTO data_t1 VALUES(1, 'xxx', NULL, '.x.');
- }
- db eval { SELECT * FROM t1 }
-} {1 b xxx}
-
-#--------------------------------------------------------------------
-# Test that the hidden languageid column of an fts4 table can be
-# written.
-#
-ifcapable fts3 {
- do_execsql_test 2.0 {
- CREATE VIRTUAL TABLE ft USING fts4(a, b, languageid='langid');
- }
- do_test 2.1 {
- apply_rbu {
- CREATE TABLE data_ft(a, b, rbu_rowid, langid, rbu_control);
- INSERT INTO data_ft VALUES('a', 'b', 22, 1, 0); -- insert
- INSERT INTO data_ft VALUES('a', 'b', 23, 10, 0); -- insert
- INSERT INTO data_ft VALUES('a', 'b', 24, 100, 0); -- insert
- }
- db eval { SELECT a, b, rowid, langid FROM ft }
- } [list {*}{
- a b 22 1
- a b 23 10
- a b 24 100
- }]
-
- # Or not - this data_xxx table has no langid column, so langid
- # defaults to 0.
- #
- do_test 2.2 {
- apply_rbu {
- CREATE TABLE data_ft(a, b, rbu_rowid, rbu_control);
- INSERT INTO data_ft VALUES('a', 'b', 25, 0); -- insert
- }
- db eval { SELECT a, b, rowid, langid FROM ft }
- } [list {*}{
- a b 22 1
- a b 23 10
- a b 24 100
- a b 25 0
- }]
-
- # Update langid.
- #
- do_test 2.3 {
- apply_rbu {
- CREATE TABLE data_ft(a, b, rbu_rowid, langid, rbu_control);
- INSERT INTO data_ft VALUES(NULL, NULL, 23, 50, '..x');
- INSERT INTO data_ft VALUES(NULL, NULL, 25, 500, '..x');
- }
- db eval { SELECT a, b, rowid, langid FROM ft }
- } [list {*}{
- a b 22 1
- a b 23 50
- a b 24 100
- a b 25 500
- }]
-}
-
-#--------------------------------------------------------------------
-# Test that if writing a hidden virtual table column is an error,
-# attempting to do so via rbu is also an error.
-#
-ifcapable fts3 {
- do_execsql_test 3.0 {
- CREATE VIRTUAL TABLE xt USING fts4(a);
- }
- do_test 3.1 {
- list [catch {
- apply_rbu {
- CREATE TABLE data_xt(a, xt, rbu_rowid, rbu_control);
- INSERT INTO data_xt VALUES('a', 'b', 1, 0);
- }
- } msg] $msg
- } {1 {SQLITE_ERROR - SQL logic error}}
-}
-
-#--------------------------------------------------------------------
-# Test that it is not possible to violate a NOT NULL constraint by
-# applying an RBU update.
-#
-do_execsql_test 4.1 {
- CREATE TABLE t2(a INTEGER NOT NULL, b TEXT NOT NULL, c PRIMARY KEY);
- CREATE TABLE t3(a INTEGER NOT NULL, b TEXT NOT NULL, c INTEGER PRIMARY KEY);
- CREATE TABLE t4(a, b, PRIMARY KEY(a, b)) WITHOUT ROWID;
-
- INSERT INTO t2 VALUES(10, 10, 10);
- INSERT INTO t3 VALUES(10, 10, 10);
- INSERT INTO t4 VALUES(10, 10);
-}
-
-foreach {tn error rbu} {
- 2 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.a} {
- INSERT INTO data_t2 VALUES(NULL, 'abc', 1, 0);
- }
- 3 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.b} {
- INSERT INTO data_t2 VALUES(2, NULL, 1, 0);
- }
- 4 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.c} {
- INSERT INTO data_t2 VALUES(1, 'abc', NULL, 0);
- }
-
- 5 {SQLITE_MISMATCH - datatype mismatch} {
- INSERT INTO data_t3 VALUES(1, 'abc', NULL, 0);
- }
-
- 6 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t4.b} {
- INSERT INTO data_t4 VALUES('a', NULL, 0);
- }
- 7 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t4.a} {
- INSERT INTO data_t4 VALUES(NULL, 'a', 0);
- }
- 8 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.a} {
- INSERT INTO data_t2 VALUES(NULL, 0, 10, 'x..');
- }
- 9 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t3.b} {
- INSERT INTO data_t3 VALUES(10, NULL, 10, '.x.');
- }
-
- 10 {SQLITE_MISMATCH - datatype mismatch} {
- INSERT INTO data_t3 VALUES(1, 'abc', 'text', 0);
- }
-} {
- set rbu "
- CREATE TABLE data_t2(a, b, c, rbu_control);
- CREATE TABLE data_t3(a, b, c, rbu_control);
- CREATE TABLE data_t4(a, b, rbu_control);
- $rbu
- "
- do_test 4.2.$tn {
- list [catch { apply_rbu $rbu } msg] $msg
- } [list 1 $error]
-}
-
-do_test 4.3 {
- set rbu {
- CREATE TABLE data_t3(a, b, c, rbu_control);
- INSERT INTO data_t3 VALUES(1, 'abc', '5', 0);
- INSERT INTO data_t3 VALUES(1, 'abc', '-6.0', 0);
- }
- list [catch { apply_rbu $rbu } msg] $msg
-} {0 SQLITE_DONE}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu11.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu11.test
deleted file mode 100644
index fdc701aceb3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu11.test
+++ /dev/null
@@ -1,198 +0,0 @@
-# 2015 February 16
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbu11
-
-
-#--------------------------------------------------------------------
-# Test that the xAccess() method of an rbu vfs handles queries other
-# than SQLITE_ACCESS_EXISTS correctly. The test code below causes
-# SQLite to call xAccess(SQLITE_ACCESS_READWRITE) on the directory
-# path argument passed to "PRAGMA temp_store_directory".
-#
-do_test 1.1 {
- sqlite3rbu_create_vfs -default rbu ""
- reset_db
- catchsql { PRAGMA temp_store_directory = '/no/such/directory' }
-} {1 {not a writable directory}}
-
-do_test 1.2 {
- catchsql " PRAGMA temp_store_directory = '[pwd]' "
-} {0 {}}
-
-do_test 1.3 {
- catchsql " PRAGMA temp_store_directory = '' "
-} {0 {}}
-
-do_test 1.4 {
- db close
- sqlite3rbu_destroy_vfs rbu
-} {}
-
-#--------------------------------------------------------------------
-# Try to trick rbu into operating on a database opened in wal mode.
-#
-reset_db
-do_execsql_test 2.1 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- INSERT INTO t1 VALUES(1, 2, 3);
- PRAGMA journal_mode = 'wal';
- CREATE TABLE t2(d PRIMARY KEY, e, f);
-} {wal}
-
-do_test 2.2 {
- db_save
- db close
-
- forcedelete rbu.db
- sqlite3 dbo rbu.db
- dbo eval {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(4, 5, 6, 0);
- INSERT INTO data_t1 VALUES(7, 8, 9, 0);
- }
- dbo close
-
- db_restore
- hexio_write test.db 18 0101
- file exists test.db-wal
-} {1}
-
-do_test 2.3 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
-} {SQLITE_ERROR}
-
-do_test 2.4 {
- list [catch {rbu close} msg] $msg
-} {1 {SQLITE_ERROR - cannot update wal mode database}}
-
-#--------------------------------------------------------------------
-# Test a constraint violation message with an unusual table name.
-# Specifically, one for which the first character is a codepoint
-# smaller than 30 (character '0').
-#
-reset_db
-do_execsql_test 3.1 {
- CREATE TABLE "(t1)"(a PRIMARY KEY, b, c);
- INSERT INTO "(t1)" VALUES(1, 2, 3);
- INSERT INTO "(t1)" VALUES(4, 5, 6);
-}
-db close
-
-do_test 3.2 {
- forcedelete rbu.db
- sqlite3 dbo rbu.db
- dbo eval {
- CREATE TABLE "data_(t1)"(a, b, c, rbu_control);
- INSERT INTO "data_(t1)" VALUES(4, 8, 9, 0);
- }
- dbo close
-
- sqlite3rbu rbu test.db rbu.db
- rbu step
- rbu step
-} {SQLITE_CONSTRAINT}
-
-do_test 3.3 {
- list [catch {rbu close} msg] $msg
-} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: (t1).a}}
-
-#--------------------------------------------------------------------
-# Check that once an RBU update has been applied, attempting to apply
-# it a second time is a no-op (as the state stored in the RBU database is
-# "all steps completed").
-#
-reset_db
-do_execsql_test 4.1 {
- CREATE TABLE "(t1)"(a, b, c, PRIMARY KEY(c, b, a));
- INSERT INTO "(t1)" VALUES(1, 2, 3);
- INSERT INTO "(t1)" VALUES(4, 5, 6);
-}
-db close
-
-do_test 4.2 {
- forcedelete rbu.db
- sqlite3 dbo rbu.db
- dbo eval {
- CREATE TABLE "data_(t1)"(a, b, c, rbu_control);
- INSERT INTO "data_(t1)" VALUES(7, 8, 9, 0);
- INSERT INTO "data_(t1)" VALUES(1, 2, 3, 1);
- }
- dbo close
-
- sqlite3rbu rbu test.db rbu.db
- while {[rbu step]=="SQLITE_OK"} { }
- rbu close
-} {SQLITE_DONE}
-
-do_test 4.3 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
-} {SQLITE_DONE}
-
-do_test 4.4 {
- rbu close
-} {SQLITE_DONE}
-
-do_test 4.5.1 {
- sqlite3 dbo rbu.db
- dbo eval { INSERT INTO rbu_state VALUES(100, 100) }
- dbo close
- sqlite3rbu rbu test.db rbu.db
- rbu step
-} {SQLITE_CORRUPT}
-do_test 4.5.2 {
- list [catch {rbu close} msg] $msg
-} {1 SQLITE_CORRUPT}
-do_test 4.5.3 {
- sqlite3 dbo rbu.db
- dbo eval { DELETE FROM rbu_state WHERE k = 100 }
- dbo close
-} {}
-
-# Also, check that an invalid state value in the rbu_state table is
-# detected and reported as corruption.
-do_test 4.6.1 {
- sqlite3 dbo rbu.db
- dbo eval { UPDATE rbu_state SET v = v*-1 WHERE k = 1 }
- dbo close
- sqlite3rbu rbu test.db rbu.db
- rbu step
-} {SQLITE_CORRUPT}
-do_test 4.6.2 {
- list [catch {rbu close} msg] $msg
-} {1 SQLITE_CORRUPT}
-do_test 4.6.3 {
- sqlite3 dbo rbu.db
- dbo eval { UPDATE rbu_state SET v = v*-1 WHERE k = 1 }
- dbo close
-} {}
-
-do_test 4.7.1 {
- sqlite3 dbo rbu.db
- dbo eval { UPDATE rbu_state SET v = 1 WHERE k = 1 }
- dbo eval { UPDATE rbu_state SET v = 'nosuchtable' WHERE k = 2 }
- dbo close
- sqlite3rbu rbu test.db rbu.db
- rbu step
-} {SQLITE_ERROR}
-do_test 4.7.2 {
- list [catch {rbu close} msg] $msg
-} {1 {SQLITE_ERROR - rbu_state mismatch error}}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu12.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu12.test
deleted file mode 100644
index a83d0891a30..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu12.test
+++ /dev/null
@@ -1,235 +0,0 @@
-# 2015 February 16
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-source $testdir/lock_common.tcl
-set ::testprefix rbu12
-
-set setup_sql {
- DROP TABLE IF EXISTS xx;
- DROP TABLE IF EXISTS xy;
- CREATE TABLE xx(a, b, c PRIMARY KEY);
- INSERT INTO xx VALUES(1, 2, 3);
- CREATE TABLE xy(a, b, c PRIMARY KEY);
-
- ATTACH 'rbu.db' AS rbu;
- DROP TABLE IF EXISTS data_xx;
- CREATE TABLE rbu.data_xx(a, b, c, rbu_control);
- INSERT INTO data_xx VALUES(4, 5, 6, 0);
- INSERT INTO data_xx VALUES(7, 8, 9, 0);
- CREATE TABLE rbu.data_xy(a, b, c, rbu_control);
- INSERT INTO data_xy VALUES(10, 11, 12, 0);
- DETACH rbu;
-}
-
-do_multiclient_test tn {
-
- # Initialize a target (test.db) and rbu (rbu.db) database.
- #
- forcedelete rbu.db
- sql1 $setup_sql
-
- # Using connection 2, open a read transaction on the target database.
- # RBU will still be able to generate "test.db-oal", but it will not be
- # able to rename it to "test.db-wal".
- #
- do_test 1.$tn.1 {
- sql2 { BEGIN; SELECT * FROM xx; }
- } {1 2 3}
- do_test 1.$tn.2 {
- sqlite3rbu rbu test.db rbu.db
- while 1 {
- set res [rbu step]
- if {$res!="SQLITE_OK"} break
- }
- set res
- } {SQLITE_BUSY}
-
- do_test 1.$tn.3 { sql2 { SELECT * FROM xx; } } {1 2 3}
- do_test 1.$tn.4 { sql2 { SELECT * FROM xy; } } {}
- do_test 1.$tn.5 {
- list [file exists test.db-wal] [file exists test.db-oal]
- } {0 1}
- do_test 1.$tn.6 { sql2 COMMIT } {}
-
- # The rbu object that hit the SQLITE_BUSY error above cannot be reused.
- # It is stuck in a permanent SQLITE_BUSY state at this point.
- #
- do_test 1.$tn.7 { rbu step } {SQLITE_BUSY}
- do_test 1.$tn.8 {
- list [catch { rbu close } msg] $msg
- } {1 SQLITE_BUSY}
-
- do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {}
- do_test 1.$tn.9.2 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_BUSY}
- do_test 1.$tn.9.3 {
- list [catch { rbu close } msg] $msg
- } {1 {SQLITE_BUSY - database is locked}}
- do_test 1.$tn.9.4 { sql2 COMMIT } {}
-
- sqlite3rbu rbu test.db rbu.db
- do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {}
- do_test 1.$tn.10.2 {
- rbu step
- } {SQLITE_BUSY}
- do_test 1.$tn.10.3 {
- list [catch { rbu close } msg] $msg
- } {1 SQLITE_BUSY}
- do_test 1.$tn.10.4 { sql2 COMMIT } {}
-
- # A new rbu object can finish the work though.
- #
- do_test 1.$tn.11 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_OK}
- do_test 1.$tn.12 {
- list [file exists test.db-wal] [file exists test.db-oal]
- } {1 0}
- do_test 1.$tn.13 {
- while 1 {
- set res [rbu step]
- if {$res!="SQLITE_OK"} break
- }
- set res
- } {SQLITE_DONE}
-
- do_test 1.$tn.14 {
- rbu close
- } {SQLITE_DONE}
-}
-
-do_multiclient_test tn {
-
- # Initialize a target (test.db) and rbu (rbu.db) database.
- #
- forcedelete rbu.db
- sql1 $setup_sql
-
- do_test 2.$tn.1 {
- sqlite3rbu rbu test.db rbu.db
- while {[file exists test.db-wal]==0} {
- if {[rbu step]!="SQLITE_OK"} {error "problem here...."}
- }
- rbu close
- } {SQLITE_OK}
-
-
- do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {}
-
- do_test 2.$tn.3 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_BUSY}
-
- do_test 2.$tn.4 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
-
- do_test 2.$tn.5 {
- sql2 { SELECT * FROM xx ; COMMIT }
- } {1 2 3 4 5 6 7 8 9}
-
- do_test 2.$tn.6 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- rbu close
- } {SQLITE_OK}
-
- do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {}
-
- do_test 2.$tn.8 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_BUSY}
- do_test 2.$tn.9 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
- do_test 2.$tn.10 {
- sql2 { SELECT * FROM xx ; COMMIT }
- } {1 2 3 4 5 6 7 8 9}
-
- do_test 2.$tn.11 {
- sqlite3rbu rbu test.db rbu.db
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
- } {SQLITE_DONE}
-
-}
-
-#-------------------------------------------------------------------------
-# Test that "PRAGMA data_version" works when an RBU client writes the
-# database.
-#
-do_multiclient_test tn {
-
- # Initialize a target (test.db) and rbu (rbu.db) database.
- #
- forcedelete rbu.db
- sql1 $setup_sql
-
- # Check the initial database contains table "xx" with a single row.
- # Also save the current values of "PRAGMA data-version" for [db1]
- # and [db2].
- #
- do_test 2.$tn.1 {
- list [sql1 { SELECT count(*) FROM xx }] [sql2 { SELECT count(*) FROM xx }]
- } {1 1}
- set V1 [sql1 {PRAGMA data_version}]
- set V2 [sql2 {PRAGMA data_version}]
-
- # Check the values of data-version have not magically changed.
- #
- do_test 2.$tn.2 {
- list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
- } [list $V1 $V2]
-
- # Start stepping the RBU. From the point of view of [db1] and [db2], the
- # data-version values remain unchanged until the database contents are
- # modified. At which point the values are incremented.
- #
- sqlite3rbu rbu test.db rbu.db
- set x 0
- while {[db one {SELECT count(*) FROM xx}]==1} {
- do_test 2.$tn.3.[incr x] {
- list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
- } [list $V1 $V2]
- rbu step
- }
- do_test 2.$tn.5.1 { expr {$V1 < [sql1 {PRAGMA data_version}]} } 1
- do_test 2.$tn.5.2 { expr {$V2 < [sql2 {PRAGMA data_version}]} } 1
-
- # Check the db contents is as expected.
- #
- do_test 2.$tn.4 {
- list [sql1 {SELECT count(*) FROM xx}] [sql2 {SELECT count(*) FROM xx}]
- } {3 3}
-
- set V1 [sql1 {PRAGMA data_version}]
- set V2 [sql2 {PRAGMA data_version}]
-
- # Finish applying the RBU (i.e. do the incremental checkpoint). Check that
- # this does not cause the data-version values to change.
- #
- while {[rbu step]=="SQLITE_OK"} { }
- rbu close
-
- do_test 2.$tn.6 {
- list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
- } [list $V1 $V2]
-
-}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu13.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu13.test
deleted file mode 100644
index ad67a98f802..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu13.test
+++ /dev/null
@@ -1,65 +0,0 @@
-# 2015 February 16
-#
-# 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.
-#
-#***********************************************************************
-#
-# Test an RBU update that features lots of different rbu_control strings
-# for UPDATE statements. This tests RBU's internal UPDATE statement cache.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-source $testdir/lock_common.tcl
-set ::testprefix rbu13
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b, c, d, e, f, g, h);
- WITH ii(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM ii WHERE i<127)
- INSERT INTO t1 SELECT i, 0, 0, 0, 0, 0, 0, 0 FROM ii;
-}
-
-forcedelete rbu.db
-do_execsql_test 1.1 {
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE rbu.data_t1(a, b, c, d, e, f, g, h, rbu_control);
-}
-
-do_test 1.2 {
- for {set i 0} {$i<128} {incr i} {
- set control "."
- for {set bit 6} {$bit>=0} {incr bit -1} {
- if { $i & (1<<$bit) } {
- append control "x"
- } else {
- append control "."
- }
- }
- execsql { INSERT INTO data_t1 VALUES($i, 1, 1, 1, 1, 1, 1, 1, $control) }
- }
-} {}
-
-do_test 1.3 {
- sqlite3rbu rbu test.db rbu.db
- while 1 {
- set rc [rbu step]
- if {$rc!="SQLITE_OK"} break
- }
- rbu close
-} {SQLITE_DONE}
-
-do_execsql_test 1.4 {
- SELECT count(*) FROM t1 WHERE
- a == ( (b<<6) + (c<<5) + (d<<4) + (e<<3) + (f<<2) + (g<<1) + (h<<0) )
-} {128}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu14.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu14.test
deleted file mode 100644
index d4f97ac32c2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu14.test
+++ /dev/null
@@ -1,95 +0,0 @@
-# 2015 July 25
-#
-# 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.
-#
-#***********************************************************************
-#
-# Test that an RBU data_xxx table may be a view instead of a regular
-# table.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-source $testdir/lock_common.tcl
-set ::testprefix rbu14
-
-
-foreach {tn schema} {
- 1 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE TABLE t2(a PRIMARY KEY, b, c);
- }
- 2 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE TABLE t2(a PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b, c);
- CREATE INDEX i2 ON t2(b, c);
- }
- 3 {
- CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
- CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
- }
- 4 {
- CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
- CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
- CREATE INDEX i1 ON t1(b, c);
- CREATE INDEX i2 ON t2(b, c);
- }
-} {
- reset_db
-
- execsql $schema
- execsql {
- INSERT INTO t1 VALUES(50, 50, 50);
- INSERT INTO t1 VALUES(51, 51, 51);
- INSERT INTO t2 VALUES(50, 50, 50);
- INSERT INTO t2 VALUES(51, 51, 51);
- }
-
- forcedelete rbu.db
- do_execsql_test $tn.1 {
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE rbu.stuff(tbl, a, b, c, rbu_control);
- INSERT INTO stuff VALUES
- ('t1', 1, 2, 3, 0), -- insert into t1
- ('t2', 4, 5, 6, 0), -- insert into t2
- ('t1', 50, NULL, NULL, 1), -- delete from t1
- ('t2', 51, NULL, NULL, 1); -- delete from t2
-
- CREATE VIEW rbu.data_t1 AS
- SELECT a, b, c, rbu_control FROM stuff WHERE tbl='t1';
- CREATE VIEW rbu.data_t2 AS
- SELECT a, b, c, rbu_control FROM stuff WHERE tbl='t2';
- }
-
- do_test $tn.2 {
- while 1 {
- sqlite3rbu rbu test.db rbu.db
- set rc [rbu step]
- rbu close
- if {$rc != "SQLITE_OK"} break
- }
- set rc
- } {SQLITE_DONE}
-
- do_execsql_test $tn.3.1 {
- SELECT * FROM t1 ORDER BY a;
- } {1 2 3 51 51 51}
-
- do_execsql_test $tn.3.2 {
- SELECT * FROM t2 ORDER BY a;
- } {4 5 6 50 50 50}
-
- integrity_check $tn.4
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu3.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu3.test
deleted file mode 100644
index 995b3123fd0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu3.test
+++ /dev/null
@@ -1,207 +0,0 @@
-# 2014 August 30
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbu3
-
-
-# Run the RBU in file $rbu on target database $target until completion.
-#
-proc run_rbu {target rbu} {
- sqlite3rbu rbu $target $rbu
- while { [rbu step]=="SQLITE_OK" } {}
- rbu close
-}
-
-forcedelete test.db-oal rbu.db
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-reset_db
-
-#--------------------------------------------------------------------
-# Test that for an RBU to be applied, no corruption results if the
-# affinities on the source and target table do not match.
-#
-do_execsql_test 1.0 {
- CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL);
- CREATE INDEX i1 ON x1(b, c);
-} {}
-
-do_test 1.1 {
- sqlite3 db2 rbu.db
- db2 eval {
- CREATE TABLE data_x1(a, b, c, rbu_control);
- INSERT INTO data_x1 VALUES(1, '123', '123', 0);
- INSERT INTO data_x1 VALUES(2, 123, 123, 0);
- }
- db2 close
- run_rbu test.db rbu.db
-} {SQLITE_DONE}
-
-do_execsql_test 1.2 {
- PRAGMA integrity_check;
-} {ok}
-
-#--------------------------------------------------------------------
-# Test that NULL values may not be inserted into INTEGER PRIMARY KEY
-# columns.
-#
-forcedelete rbu.db
-reset_db
-
-do_execsql_test 2.0 {
- CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL);
- CREATE INDEX i1 ON x1(b, c);
-} {}
-
-foreach {tn rbudb} {
- 1 {
- CREATE TABLE data_x1(a, b, c, rbu_control);
- INSERT INTO data_x1 VALUES(NULL, 'a', 'b', 0);
- }
-
- 2 {
- CREATE TABLE data_x1(c, b, a, rbu_control);
- INSERT INTO data_x1 VALUES('b', 'a', NULL, 0);
- }
-} {
- do_test 2.$tn.1 {
- forcedelete rbu.db
- sqlite3 db2 rbu.db
- db2 eval $rbudb
- db2 close
- list [catch { run_rbu test.db rbu.db } msg] $msg
- } {1 {SQLITE_MISMATCH - datatype mismatch}}
-
- do_execsql_test 2.1.2 {
- PRAGMA integrity_check;
- } {ok}
-}
-
-#--------------------------------------------------------------------
-# Test that missing columns are detected.
-#
-forcedelete rbu.db
-reset_db
-
-do_execsql_test 2.0 {
- CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON x1(b, c);
-} {}
-
-do_test 2.1 {
- sqlite3 db2 rbu.db
- db2 eval {
- CREATE TABLE data_x1(a, b, rbu_control);
- INSERT INTO data_x1 VALUES(1, 'a', 0);
- }
- db2 close
- list [catch { run_rbu test.db rbu.db } msg] $msg
-} {1 {SQLITE_ERROR - column missing from data_x1: c}}
-
-do_execsql_test 2.2 {
- PRAGMA integrity_check;
-} {ok}
-
-# Also extra columns.
-#
-do_execsql_test 2.3 {
- CREATE TABLE x2(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i2 ON x2(b, c);
-} {}
-
-do_test 2.4 {
- forcedelete rbu.db
- sqlite3 db2 rbu.db
- db2 eval {
- CREATE TABLE data_x2(a, b, c, d, rbu_control);
- INSERT INTO data_x2 VALUES(1, 'a', 2, 3, 0);
- }
- db2 close
- list [catch { run_rbu test.db rbu.db } msg] $msg
-} {1 SQLITE_ERROR}
-
-do_execsql_test 2.5 {
- PRAGMA integrity_check;
-} {ok}
-
-
-#-------------------------------------------------------------------------
-# Test that sqlite3rbu_create_vfs() returns an error if the requested
-# parent VFS is unknown.
-#
-# And that nothing disasterous happens if a VFS name passed to
-# sqlite3rbu_destroy_vfs() is unknown or not an RBU vfs.
-#
-do_test 3.1 {
- list [catch {sqlite3rbu_create_vfs xyz nosuchparent} msg] $msg
-} {1 SQLITE_NOTFOUND}
-
-do_test 3.2 {
- sqlite3rbu_destroy_vfs nosuchvfs
- sqlite3rbu_destroy_vfs unix
- sqlite3rbu_destroy_vfs win32
-} {}
-
-#-------------------------------------------------------------------------
-# Test that it is an error to specify an explicit VFS that does not
-# include rbu VFS functionality.
-#
-do_test 4.1 {
- testvfs tvfs
- sqlite3rbu rbu file:test.db?vfs=tvfs rbu.db
- list [catch { rbu step } msg] $msg
-} {0 SQLITE_ERROR}
-do_test 4.2 {
- list [catch { rbu close } msg] $msg
-} {1 {SQLITE_ERROR - rbu vfs not found}}
-tvfs delete
-
-#-------------------------------------------------------------------------
-# Test a large rbu update to ensure that wal_autocheckpoint does not get
-# in the way.
-#
-forcedelete rbu.db
-reset_db
-do_execsql_test 5.1 {
- CREATE TABLE x1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
- CREATE INDEX i1 ON x1(a);
-
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE rbu.data_x1(a, b, c, rbu_control);
- WITH s(a, b, c) AS (
- SELECT randomblob(300), randomblob(300), 1
- UNION ALL
- SELECT randomblob(300), randomblob(300), c+1 FROM s WHERE c<2000
- )
- INSERT INTO data_x1 SELECT a, b, c, 0 FROM s;
-}
-
-do_test 5.2 {
- sqlite3rbu rbu test.db rbu.db
- while {[rbu step]=="SQLITE_OK" && [file exists test.db-wal]==0} {}
- rbu close
-} {SQLITE_OK}
-
-do_test 5.3 {
- expr {[file size test.db-wal] > (1024 * 1200)}
-} 1
-
-do_test 6.1 { sqlite3rbu_internal_test } {}
-
-finish_test
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu5.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu5.test
deleted file mode 100644
index 8e4ae8cb695..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu5.test
+++ /dev/null
@@ -1,306 +0,0 @@
-# 2014 August 30
-#
-# 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.
-#
-#***********************************************************************
-#
-# Test some properties of the pager_rbu_mode and rbu_mode pragmas.
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbu5
-
-
-# Return a list of the primary key columns for table $tbl in the database
-# opened by database handle $db.
-#
-proc pkcols {db tbl} {
- set ret [list]
- $db eval "PRAGMA table_info = '$tbl'" {
- if {$pk} { lappend ret $name }
- }
- return $ret
-}
-
-# Return a list of all columns for table $tbl in the database opened by
-# database handle $db.
-#
-proc allcols {db tbl} {
- set ret [list]
- $db eval "PRAGMA table_info = '$tbl'" {
- lappend ret $name
- }
- return $ret
-}
-
-# Return a checksum on all tables and data in the main database attached
-# to database handle $db. It is possible to add indexes without changing
-# the checksum.
-#
-proc datacksum {db} {
-
- $db eval { SELECT name FROM sqlite_master WHERE type='table' } {
- append txt $name
- set cols [list]
- set order [list]
- set cnt 0
- $db eval "PRAGMA table_info = $name" x {
- lappend cols "quote($x(name))"
- lappend order [incr cnt]
- }
- set cols [join $cols ,]
- set order [join $order ,]
- append txt [$db eval "SELECT $cols FROM $name ORDER BY $order"]
- }
- return "[string length $txt]-[md5 $txt]"
-}
-
-proc ucontrol {args} {
- set ret ""
- foreach a $args {
- if {$a} {
- append ret .
- } else {
- append ret x
- }
- }
- return $ret
-}
-
-# Argument $target is the name of an SQLite database file. $sql is an SQL
-# script containing INSERT, UPDATE and DELETE statements to execute against
-# it. This command creates an RBU update database in file $rbu that has
-# the same effect as the script. The target database is not modified by
-# this command.
-#
-proc generate_rbu_db {target rbu sql} {
-
- forcedelete $rbu
- forcecopy $target copy.db
-
- # Evaluate the SQL script to modify the contents of copy.db.
- #
- sqlite3 dbRbu copy.db
- dbRbu eval $sql
-
- dbRbu function ucontrol ucontrol
-
- # Evaluate the SQL script to modify the contents of copy.db.
- set ret [datacksum dbRbu]
-
- dbRbu eval { ATTACH $rbu AS rbu }
- dbRbu eval { ATTACH $target AS orig }
-
- dbRbu eval { SELECT name AS tbl FROM sqlite_master WHERE type = 'table' } {
- set pk [pkcols dbRbu $tbl]
- set cols [allcols dbRbu $tbl]
-
- # A WHERE clause to test that the PK columns match.
- #
- set where [list]
- foreach c $pk { lappend where "main.$tbl.$c IS orig.$tbl.$c" }
- set where [join $where " AND "]
-
- # A WHERE clause to test that all columns match.
- #
- set where2 [list]
- foreach c $cols { lappend where2 "main.$tbl.$c IS orig.$tbl.$c" }
- set ucontrol "ucontrol([join $where2 ,])"
- set where2 [join $where2 " AND "]
-
- # Create a data_xxx table in the RBU update database.
- dbRbu eval "
- CREATE TABLE rbu.data_$tbl AS SELECT *, '' AS rbu_control
- FROM main.$tbl LIMIT 0
- "
-
- # Find all new rows INSERTed by the script.
- dbRbu eval "
- INSERT INTO rbu.data_$tbl
- SELECT *, 0 AS rbu_control FROM main.$tbl
- WHERE NOT EXISTS (
- SELECT 1 FROM orig.$tbl WHERE $where
- )
- "
-
- # Find all old rows DELETEd by the script.
- dbRbu eval "
- INSERT INTO rbu.data_$tbl
- SELECT *, 1 AS rbu_control FROM orig.$tbl
- WHERE NOT EXISTS (
- SELECT 1 FROM main.$tbl WHERE $where
- )
- "
-
- # Find all rows UPDATEd by the script.
- set origcols [list]
- foreach c $cols { lappend origcols "main.$tbl.$c" }
- set origcols [join $origcols ,]
- dbRbu eval "
- INSERT INTO rbu.data_$tbl
- SELECT $origcols, $ucontrol AS rbu_control
- FROM orig.$tbl, main.$tbl
- WHERE $where AND NOT ($where2)
- "
-
- }
-
- dbRbu close
- forcedelete copy.db
-
- return $ret
-}
-
-#-------------------------------------------------------------------------
-#
-do_execsql_test 1.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE TABLE t2(x, y, z, PRIMARY KEY(y, z)) WITHOUT ROWID;
-
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(2, 4, 6);
- INSERT INTO t1 VALUES(3, 6, 9);
-
- INSERT INTO t2 VALUES(1, 2, 3);
- INSERT INTO t2 VALUES(2, 4, 6);
- INSERT INTO t2 VALUES(3, 6, 9);
-}
-db close
-
-set cksum [generate_rbu_db test.db rbu.db {
- INSERT INTO t1 VALUES(4, 8, 12);
- DELETE FROM t1 WHERE a = 2;
- UPDATE t1 SET c = 15 WHERE a=3;
-
- INSERT INTO t2 VALUES(4, 8, 12);
- DELETE FROM t2 WHERE x = 2;
- UPDATE t2 SET x = 15 WHERE z=9;
-}]
-
-foreach {tn idx} {
- 1 {
- }
- 2 {
- CREATE INDEX i1 ON t1(a, b, c);
- CREATE INDEX i2 ON t2(x, y, z);
- }
-} {
- foreach cmd {run step} {
- forcecopy test.db test.db2
- forcecopy rbu.db rbu.db2
-
- sqlite3 db test.db2
- db eval $idx
-
- do_test 1.$tn.$cmd.1 {
- ${cmd}_rbu test.db2 rbu.db2
- datacksum db
- } $cksum
-
- do_test 1.$tn.$cmd.2 {
- db eval { PRAGMA integrity_check }
- } {ok}
-
- db close
- }
-}
-
-#-------------------------------------------------------------------------
-#
-reset_db
-do_execsql_test 2.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e);
- INSERT INTO t1 VALUES(-750250,'fyetckfaagjkzqjx',-185831,X'FEAD',444258.29);
- INSERT INTO t1 VALUES(649081,NULL,X'7DF25BF78778',-342324.63,'akvspktocwozo');
- INSERT INTO t1 VALUES(-133045,-44822.31,X'',287935,NULL);
- INSERT INTO t1 VALUES(202132,NULL,X'5399','cujsjtspryqeyovcdpz','m');
- INSERT INTO t1 VALUES(302910,NULL,'dvdhivtfkaedzhdcnn',-717113.41,688487);
- INSERT INTO t1 VALUES(-582327,X'7A267A',X'7E6B3CFE5CB9','zacuzilrok',-196478);
- INSERT INTO t1 VALUES(-190462,X'D1A087E7D68D9578','lsmleti',NULL,-928094);
- INSERT INTO t1 VALUES(-467665,176344.57,-536684.23,828876.22,X'903E');
- INSERT INTO t1 VALUES(-629138,632630.29,X'28D6',-774501,X'819BBBFC65');
- INSERT INTO t1 VALUES(-828110,-54379.24,-881121.44,X'',X'8D5A894F0D');
-
- CREATE TABLE t2(a PRIMARY KEY, b, c, d, e) WITHOUT ROWID;
- INSERT INTO t2 VALUES(-65174,X'AC1DBFFE27310F',-194471.08,347988,X'84041BA6F9BDDE86A8');
- INSERT INTO t2 VALUES('bzbpi',-952693.69,811628.25,NULL,-817434);
- INSERT INTO t2 VALUES(-643830,NULL,'n',NULL,'dio');
- INSERT INTO t2 VALUES('rovoenxxj',NULL,'owupbtdcoxxnvg',-119676,X'55431DFA');
- INSERT INTO t2 VALUES(899770,'jlygdl',X'DBCA4D1A',NULL,-631773);
- INSERT INTO t2 VALUES(334698.80,NULL,-697585.58,-89277,-817352);
- INSERT INTO t2 VALUES(X'1A9EB7547A4AAF38','aiprdhkpzdz','anw','szvjbwdvzucybpwwqjt',X'53');
- INSERT INTO t2 VALUES(713220,NULL,'hfcqhqzjuqplvkum',X'20B076075649DE','fthgpvqdyy');
- INSERT INTO t2 VALUES(763908,NULL,'xgslzcpvwfknbr',X'75',X'668146');
- INSERT INTO t2 VALUES(X'E1BA2B6BA27278','wjbpd',NULL,139341,-290086.15);
-}
-db close
-
-set cksum [generate_rbu_db test.db rbu.db {
-INSERT INTO t2 VALUES(222916.23,'idh',X'472C517405',X'E3',X'7C4F31824669');
-INSERT INTO t2 VALUES('xcndjwafcoxwxizoktd',-319567.21,NULL,-720906.43,-577170);
-INSERT INTO t2 VALUES(376369.99,-536058,'yoaiurfqupdscwc',X'29EC8A2542EC3953E9',-740485.22);
-INSERT INTO t2 VALUES(X'0EFB4DC50693',-175590.83,X'1779E253CAB5B1789E',X'BC6903',NULL);
-INSERT INTO t2 VALUES(-288299,'hfrp',NULL,528477,730676.77);
-DELETE FROM t2 WHERE a < -60000;
-
-UPDATE t2 SET b = 'pgnnaaoflnw' WHERE a = 'bzbpi';
-UPDATE t2 SET c = -675583 WHERE a = 'rovoenxxj';
-UPDATE t2 SET d = X'09CDF2B2C241' WHERE a = 713220;
-
-INSERT INTO t1 VALUES(224938,'bmruycvfznhhnfmgqys','fr',854381,789143);
-INSERT INTO t1 VALUES(-863931,-1386.26,X'2A058540C2FB5C',NULL,X'F9D5990A');
-INSERT INTO t1 VALUES(673696,X'97301F0AC5735F44B5',X'440C',227999.92,-709599.79);
-INSERT INTO t1 VALUES(-243640,NULL,-71718.11,X'1EEFEB38',X'8CC7C55D95E142FBA5');
-INSERT INTO t1 VALUES(275893,X'',375606.30,X'0AF9EC334711FB',-468194);
-DELETE FROM t1 WHERE a > 200000;
-
-UPDATE t1 SET b = 'pgnnaaoflnw' WHERE a = -190462;
-UPDATE t1 SET c = -675583 WHERE a = -467665;
-UPDATE t1 SET d = X'09CDF2B2C241' WHERE a = -133045;
-
-}]
-
-foreach {tn idx} {
- 1 {
- }
- 2 {
- CREATE UNIQUE INDEX i1 ON t1(b, c, d);
- CREATE UNIQUE INDEX i2 ON t1(d, e, a);
- CREATE UNIQUE INDEX i3 ON t1(e, d, c, b);
-
- CREATE UNIQUE INDEX i4 ON t2(b, c, d);
- CREATE UNIQUE INDEX i5 ON t2(d, e, a);
- CREATE UNIQUE INDEX i6 ON t2(e, d, c, b);
- }
-} {
- foreach cmd {run step} {
- forcecopy test.db test.db2
- forcecopy rbu.db rbu.db2
-
- sqlite3 db test.db2
- db eval $idx
-
- do_test 2.$tn.$cmd.1 {
- ${cmd}_rbu test.db2 rbu.db2
- datacksum db
- } $cksum
-
- do_test 2.$tn.$cmd.2 {
- db eval { PRAGMA integrity_check }
- } {ok}
-
- db close
- }
-}
-
-
-finish_test
-
-
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu6.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu6.test
deleted file mode 100644
index f05721574ad..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu6.test
+++ /dev/null
@@ -1,103 +0,0 @@
-# 2014 October 21
-#
-# 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 contains tests for the RBU module. Specifically, it tests the
-# outcome of some other client writing to the database while an RBU update
-# is being applied.
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbu6
-
-proc setup_test {} {
- reset_db
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
- CREATE TABLE t2(a INTEGER PRIMARY KEY, b UNIQUE);
- CREATE TABLE t3(a INTEGER PRIMARY KEY, b UNIQUE);
- }
- db close
-
- forcedelete rbu.db
- sqlite3 rbu rbu.db
- rbu eval {
- CREATE TABLE data_t1(a, b, rbu_control);
- CREATE TABLE data_t2(a, b, rbu_control);
- CREATE TABLE data_t3(a, b, rbu_control);
- INSERT INTO data_t1 VALUES(1, 't1', 0);
- INSERT INTO data_t2 VALUES(2, 't2', 0);
- INSERT INTO data_t3 VALUES(3, 't3', 0);
- }
- rbu close
-}
-
-# Test the outcome of some other client writing the db while the *-oal
-# file is being generated. Once this has happened, the update cannot be
-# progressed.
-#
-for {set nStep 1} {$nStep < 8} {incr nStep} {
- do_test 1.$nStep.1 {
- setup_test
- sqlite3rbu rbu test.db rbu.db
- for {set i 0} {$i<$nStep} {incr i} {rbu step}
-
- rbu close
- sqlite3 db test.db
- execsql { INSERT INTO t1 VALUES(5, 'hello') }
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_BUSY}
- do_test 1.$nStep.2 {
- rbu step
- } {SQLITE_BUSY}
- do_test 1.$nStep.3 {
- list [file exists test.db-oal] [file exists test.db-wal]
- } {1 0}
- do_test 1.$nStep.4 {
- list [catch { rbu close } msg] $msg
- } {1 {SQLITE_BUSY - database modified during rbu update}}
-}
-
-# Test the outcome of some other client writing the db after the *-oal
-# file has been copied to the *-wal path. Once this has happened, any
-# other client writing to the db causes RBU to consider its job finished.
-#
-for {set nStep 8} {$nStep < 20} {incr nStep} {
- do_test 1.$nStep.1 {
- setup_test
- sqlite3rbu rbu test.db rbu.db
- for {set i 0} {$i<$nStep} {incr i} {rbu step}
- rbu close
- sqlite3 db test.db
- execsql { INSERT INTO t1 VALUES(5, 'hello') }
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_DONE}
- do_test 1.$nStep.2 {
- rbu step
- } {SQLITE_DONE}
- do_test 1.$nStep.3 {
- file exists test.db-oal
- } {0}
- do_test 1.$nStep.4 {
- list [catch { rbu close } msg] $msg
- } {0 SQLITE_DONE}
-
- do_execsql_test 1.$nStep.5 {
- SELECT * FROM t1;
- } {1 t1 5 hello}
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu7.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu7.test
deleted file mode 100644
index f773c9e5a9f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu7.test
+++ /dev/null
@@ -1,110 +0,0 @@
-# 2014 October 21
-#
-# 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 contains tests for the RBU module.
-#
-
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbu7
-
-# Test index:
-#
-# 1.*: That affinities are correctly applied to values within the
-# RBU database.
-#
-# 2.*: Tests for multi-column primary keys.
-#
-
-do_test 1.0 {
- execsql {
- CREATE TABLE t1(a INT PRIMARY KEY, b) WITHOUT ROWID;
- INSERT INTO t1 VALUES(1, 'abc');
- INSERT INTO t1 VALUES(2, 'def');
- }
-
- forcedelete rbu.db
- sqlite3 rbu rbu.db
- rbu eval {
- CREATE TABLE data_t1(a, b, rbu_control);
- INSERT INTO data_t1 VALUES('1', NULL, 1);
- }
- rbu close
-} {}
-
-do_test 1.1 {
- sqlite3rbu rbu test.db rbu.db
- while { [rbu step]=="SQLITE_OK" } {}
- rbu close
-} {SQLITE_DONE}
-
-sqlite3 db test.db
-do_execsql_test 1.2 {
- SELECT * FROM t1
-} {2 def}
-
-#-------------------------------------------------------------------------
-#
-foreach {tn tbl} {
- 1 { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID }
- 2 { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)) }
-} {
- reset_db
-
- execsql $tbl
- do_execsql_test 2.$tn.1 {
- CREATE INDEX t1c ON t1(c);
- INSERT INTO t1 VALUES(1, 1, 'a');
- INSERT INTO t1 VALUES(1, 2, 'b');
- INSERT INTO t1 VALUES(2, 1, 'c');
- INSERT INTO t1 VALUES(2, 2, 'd');
- }
-
- do_test 2.$tn.2 {
- forcedelete rbu.db
- sqlite3 rbu rbu.db
- execsql {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(3, 1, 'e', 0);
- INSERT INTO data_t1 VALUES(3, 2, 'f', 0);
- INSERT INTO data_t1 VALUES(1, 2, NULL, 1);
- INSERT INTO data_t1 VALUES(2, 1, 'X', '..x');
- } rbu
- rbu close
- } {}
-
- do_test 2.$tn.3 {
- set rc "SQLITE_OK"
- while {$rc == "SQLITE_OK"} {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- set rc [rbu close]
- }
- set rc
- } {SQLITE_DONE}
-
- do_execsql_test 2.$tn.1 {
- SELECT * FROM t1 ORDER BY a, b
- } {
- 1 1 a
- 2 1 X
- 2 2 d
- 3 1 e
- 3 2 f
- }
-}
-
-finish_test
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu8.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu8.test
deleted file mode 100644
index 75edd4efbaf..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu8.test
+++ /dev/null
@@ -1,75 +0,0 @@
-# 2014 November 20
-#
-# 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.
-#
-#***********************************************************************
-#
-# Test the rbu_delta() feature.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbu8
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(x, y PRIMARY KEY, z);
- INSERT INTO t1 VALUES(NULL, 1, 'one');
- INSERT INTO t1 VALUES(NULL, 2, 'two');
- INSERT INTO t1 VALUES(NULL, 3, 'three');
- CREATE INDEX i1z ON t1(z, x);
-}
-
-do_test 1.1 {
- forcedelete rbu.db
- sqlite3 db2 rbu.db
- db2 eval {
- CREATE TABLE data_t1(x, y, z, rbu_control);
- INSERT INTO data_t1 VALUES('a', 1, '_i' , 'x.d');
- INSERT INTO data_t1 VALUES('b', 2, 2 , '..x');
- INSERT INTO data_t1 VALUES('_iii', 3, '-III' , 'd.d');
- }
- db2 close
-} {}
-
-do_test 1.2.1 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
-} {SQLITE_ERROR}
-do_test 1.2.2 {
- list [catch {rbu close} msg] $msg
-} {1 {SQLITE_ERROR - no such function: rbu_delta}}
-
-proc rbu_delta {orig new} {
- return "${orig}${new}"
-}
-
-do_test 1.3.1 {
- while 1 {
- sqlite3rbu rbu test.db rbu.db
- rbu create_rbu_delta
- set rc [rbu step]
- if {$rc != "SQLITE_OK"} break
- rbu close
- }
- rbu close
-} {SQLITE_DONE}
-
-do_execsql_test 1.3.2 {
- SELECT * FROM t1
-} {
- a 1 one_i
- {} 2 2
- _iii 3 three-III
-}
-integrity_check 1.3.3
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu9.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu9.test
deleted file mode 100644
index 3ce649d2504..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu9.test
+++ /dev/null
@@ -1,128 +0,0 @@
-# 2014 November 21
-#
-# 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.
-#
-#***********************************************************************
-#
-# Test RBU with virtual tables. And tables with no PRIMARY KEY declarations.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbu9
-
-ifcapable !fts3 {
- finish_test
- return
-}
-
-do_execsql_test 1.1 {
- CREATE VIRTUAL TABLE f1 USING fts4(a, b, c);
- INSERT INTO f1(rowid, a, b, c) VALUES(11, 'a', 'b', 'c');
- INSERT INTO f1(rowid, a, b, c) VALUES(12, 'd', 'e', 'f');
- INSERT INTO f1(rowid, a, b, c) VALUES(13, 'g', 'h', 'i');
-}
-
-do_test 1.1 {
- forcedelete rbu.db
- sqlite3 db2 rbu.db
- db2 eval {
- CREATE TABLE data_f1(rbu_rowid, a, b, c, rbu_control);
- INSERT INTO data_f1 VALUES(14, 'x', 'y', 'z', 0); -- INSERT
- INSERT INTO data_f1 VALUES(11, NULL, NULL, NULL, 1); -- DELETE
- INSERT INTO data_f1 VALUES(13, NULL, NULL, 'X', '..x'); -- UPDATE
- }
- db2 close
-} {}
-
-do_test 1.2.1 {
- while 1 {
- sqlite3rbu rbu test.db rbu.db
- set rc [rbu step]
- if {$rc != "SQLITE_OK"} break
- rbu close
- }
- rbu close
-} {SQLITE_DONE}
-
-do_execsql_test 1.2.2 { SELECT rowid, * FROM f1 } {
- 12 d e f
- 13 g h X
- 14 x y z
-}
-do_execsql_test 1.2.3 { INSERT INTO f1(f1) VALUES('integrity-check') }
-integrity_check 1.2.4
-
-#-------------------------------------------------------------------------
-# Tables with no PK declaration.
-#
-
-# Run the RBU in file $rbu on target database $target until completion.
-#
-proc run_rbu {target rbu} {
- sqlite3rbu rbu $target $rbu
- while { [rbu step]=="SQLITE_OK" } {}
- rbu close
-}
-
-foreach {tn idx} {
- 1 { }
- 2 {
- CREATE INDEX i1 ON t1(a);
- }
- 3 {
- CREATE INDEX i1 ON t1(b, c);
- CREATE INDEX i2 ON t1(c, b);
- CREATE INDEX i3 ON t1(a, a, a, b, b, b, c, c, c);
- }
-} {
-
- reset_db
- do_execsql_test 2.$tn.1 {
- CREATE TABLE t1(a, b, c);
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t1(rowid, a, b, c) VALUES(-1, 'a', 'b', 'c');
- INSERT INTO t1(rowid, a, b, c) VALUES(-2, 'd', 'e', 'f');
- }
-
- db eval $idx
-
- do_test 2.$tn.2 {
- forcedelete rbu.db
- sqlite3 db2 rbu.db
- db2 eval {
- CREATE TABLE data_t1(rbu_rowid, a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(3, 'x', 'y', 'z', 0);
- INSERT INTO data_t1 VALUES(NULL, 'X', 'Y', 'Z', 0);
- INSERT INTO data_t1 VALUES('1', NULL, NULL, NULL, 1);
- INSERT INTO data_t1 VALUES(-2, NULL, NULL, 'fff', '..x');
- }
- db2 close
- } {}
-
- run_rbu test.db rbu.db
-
- do_execsql_test 2.$tn.3 {
- SELECT rowid, a, b, c FROM t1 ORDER BY rowid;
- } {
- -2 d e fff
- -1 a b c
- 2 4 5 6
- 3 x y z
- 4 X Y Z
- }
-
- integrity_check 2.$tn.4
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuA.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuA.test
deleted file mode 100644
index 286194c4fc1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuA.test
+++ /dev/null
@@ -1,83 +0,0 @@
-# 2014 August 30
-#
-# 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 contains tests for the RBU module. More specifically, it
-# contains tests to ensure that it is an error to attempt to update
-# a wal mode database via RBU.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbuA
-
-set db_sql {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
-}
-set rbu_sql {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 2, 3, 0);
- INSERT INTO data_t1 VALUES(4, 5, 6, 0);
- INSERT INTO data_t1 VALUES(7, 8, 9, 0);
-}
-
-do_test 1.0 {
- db close
- forcedelete test.db rbu.db
-
- sqlite3 db test.db
- db eval $db_sql
- db eval { PRAGMA journal_mode = wal }
- db close
-
- sqlite3 db rbu.db
- db eval $rbu_sql
- db close
-
- sqlite3rbu rbu test.db rbu.db
- rbu step
-} {SQLITE_ERROR}
-do_test 1.1 {
- list [catch { rbu close } msg] $msg
-} {1 {SQLITE_ERROR - cannot update wal mode database}}
-
-do_test 2.0 {
- forcedelete test.db rbu.db
-
- sqlite3 db test.db
- db eval $db_sql
- db close
-
- sqlite3 db rbu.db
- db eval $rbu_sql
- db close
-
- sqlite3rbu rbu test.db rbu.db
- rbu step
- rbu close
-} {SQLITE_OK}
-
-do_test 2.1 {
- sqlite3 db test.db
- db eval {PRAGMA journal_mode = wal}
- db close
- sqlite3rbu rbu test.db rbu.db
- rbu step
-} {SQLITE_ERROR}
-
-do_test 2.2 {
- list [catch { rbu close } msg] $msg
-} {1 {SQLITE_ERROR - cannot update wal mode database}}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuB.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuB.test
deleted file mode 100644
index c007fb7d9a2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuB.test
+++ /dev/null
@@ -1,62 +0,0 @@
-# 2014 August 30
-#
-# 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.
-#
-#***********************************************************************
-#
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbuB
-
-db close
-sqlite3_shutdown
-test_sqlite3_log xLog
-reset_db
-
-proc xLog {args} { }
-
-set db_sql {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
-}
-set rbu_sql {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 2, 3, 0);
- INSERT INTO data_t1 VALUES(4, 5, 6, 0);
- INSERT INTO data_t1 VALUES(7, 8, 9, 0);
-}
-
-do_test 1.1 {
- forcedelete rbu.db
- sqlite3 rbu rbu.db
- rbu eval $rbu_sql
- rbu close
-
- db eval $db_sql
-} {}
-
-set ::errlog [list]
-proc xLog {err msg} { lappend ::errlog $err }
-do_test 1.2 {
- run_rbu test.db rbu.db
-} {SQLITE_DONE}
-
-do_test 1.3 {
- set ::errlog
-} {SQLITE_NOTICE_RECOVER_WAL SQLITE_INTERNAL}
-
-do_execsql_test 1.4 {
- SELECT * FROM t1
-} {1 2 3 4 5 6 7 8 9}
-
-db close
-sqlite3_shutdown
-test_sqlite3_log
-sqlite3_initialize
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuC.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuC.test
deleted file mode 100644
index 89fd01518f0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuC.test
+++ /dev/null
@@ -1,142 +0,0 @@
-# 2016 March 7
-#
-# 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.
-#
-#***********************************************************************
-# Tests for RBU focused on the REPLACE operation (rbu_control column
-# contains integer value 2).
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbuC
-
-#-------------------------------------------------------------------------
-# This test is actually of an UPDATE directive. Just to establish that
-# these work with UNIQUE indexes before preceding to REPLACE.
-#
-do_execsql_test 1.0 {
- CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b, c UNIQUE);
- INSERT INTO t1 VALUES(1, 'a', 'b', 'c');
-}
-
-forcedelete rbu.db
-do_execsql_test 1.1 {
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE rbu.data_t1(i, a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 'a', 'b', 'c', '.xxx');
-}
-
-do_test 1.2 {
- step_rbu test.db rbu.db
-} {SQLITE_DONE}
-
-do_execsql_test 1.3 {
- SELECT * FROM t1
-} {
- 1 a b c
-}
-
-#-------------------------------------------------------------------------
-#
-foreach {tn schema} {
- 1 {
- CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b, c UNIQUE);
- CREATE INDEX t1a ON t1(a);
- }
- 2 {
- CREATE TABLE t1(i PRIMARY KEY, a, b, c UNIQUE);
- CREATE INDEX t1a ON t1(a);
- }
- 3 {
- CREATE TABLE t1(i PRIMARY KEY, a, b, c UNIQUE) WITHOUT ROWID;
- CREATE INDEX t1a ON t1(a);
- }
-} {
- reset_db
- forcedelete rbu.db
- execsql $schema
-
- do_execsql_test 2.$tn.0 {
- INSERT INTO t1 VALUES(1, 'a', 'b', 'c');
- INSERT INTO t1 VALUES(2, 'b', 'c', 'd');
- INSERT INTO t1 VALUES(3, 'c', 'd', 'e');
- }
-
- do_execsql_test 2.$tn.1 {
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE rbu.data_t1(i, a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 1, 2, 3, 2);
- INSERT INTO data_t1 VALUES(3, 'c', 'd', 'e', 2);
- INSERT INTO data_t1 VALUES(4, 'd', 'e', 'f', 2);
- }
-
- do_test 2.$tn.2 {
- step_rbu test.db rbu.db
- } {SQLITE_DONE}
-
- do_execsql_test 2.$tn.3 {
- SELECT * FROM t1 ORDER BY i
- } {
- 1 1 2 3
- 2 b c d
- 3 c d e
- 4 d e f
- }
-
- integrity_check 2.$tn.4
-}
-
-foreach {tn schema} {
- 1 {
- CREATE TABLE t1(a, b, c UNIQUE);
- CREATE INDEX t1a ON t1(a);
- }
-
- 2 {
- CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
- }
-} {
- if {$tn==2} { ifcapable !fts5 break }
- reset_db
- forcedelete rbu.db
- execsql $schema
-
- do_execsql_test 3.$tn.0 {
- INSERT INTO t1 VALUES('a', 'b', 'c');
- INSERT INTO t1 VALUES('b', 'c', 'd');
- INSERT INTO t1 VALUES('c', 'd', 'e');
- }
-
- do_execsql_test 3.$tn.1 {
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE rbu.data_t1(rbu_rowid, a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 1, 2, 3, 2);
- INSERT INTO data_t1 VALUES(3, 'c', 'd', 'e', 2);
- INSERT INTO data_t1 VALUES(4, 'd', 'e', 'f', 2);
- }
-
- do_test 3.$tn.2 {
- step_rbu test.db rbu.db
- } {SQLITE_DONE}
-
- do_execsql_test 3.$tn.3 {
- SELECT rowid, * FROM t1 ORDER BY 1
- } {
- 1 1 2 3
- 2 b c d
- 3 c d e
- 4 d e f
- }
-
- integrity_check 3.$tn.4
-}
-
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu_common.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu_common.tcl
deleted file mode 100644
index 2b263b7660d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbu_common.tcl
+++ /dev/null
@@ -1,109 +0,0 @@
-# 2015 Aug 8
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-
-proc check_prestep_state {target state} {
- set oal_exists [file exists $target-oal]
- set wal_exists [file exists $target-wal]
- set progress [rbu progress]
-
- if {($progress==0 && $state!="oal" && $state!="done")
- || ($oal_exists && $wal_exists)
- || ($progress>0 && $state=="oal" && (!$oal_exists || $wal_exists))
- || ($state=="move" && (!$oal_exists || $wal_exists))
- || ($state=="checkpoint" && ($oal_exists || !$wal_exists))
- || ($state=="done" && ($oal_exists && $progress!=0))
- } {
- error "B: state=$state progress=$progress oal=$oal_exists wal=$wal_exists"
- }
-}
-
-proc check_poststep_state {rc target state} {
- if {$rc=="SQLITE_OK" || $rc=="SQLITE_DONE"} {
- set oal_exists [file exists $target-oal]
- set wal_exists [file exists $target-wal]
- if {$state=="move" && ($oal_exists || !$wal_exists)} {
- error "A: state=$state progress=$progress oal=$oal_exists wal=$wal_exists"
- }
- }
-}
-
-# Run the RBU in file $rbu on target database $target until completion.
-#
-proc run_rbu {target rbu} {
- sqlite3rbu rbu $target $rbu
- while 1 {
- set state [rbu state]
-
- check_prestep_state $target $state
- set rc [rbu step]
- check_poststep_state $rc $target $state
-
- if {$rc!="SQLITE_OK"} break
- }
- rbu close
-}
-
-proc step_rbu {target rbu} {
- while 1 {
- sqlite3rbu rbu $target $rbu
- set state [rbu state]
- check_prestep_state $target $state
- set rc [rbu step]
- check_poststep_state $rc $target $state
- rbu close
- if {$rc != "SQLITE_OK"} break
- }
- set rc
-}
-
-proc step_rbu_legacy {target rbu} {
- while 1 {
- sqlite3rbu rbu $target $rbu
- set state [rbu state]
- check_prestep_state $target $state
- set rc [rbu step]
- check_poststep_state $rc $target $state
- rbu close
- if {$rc != "SQLITE_OK"} break
- sqlite3 tmpdb $rbu
- tmpdb eval { DELETE FROM rbu_state WHERE k==10 }
- tmpdb close
- }
- set rc
-}
-
-proc do_rbu_vacuum_test {tn step} {
- forcedelete state.db
- uplevel [list do_test $tn.1 {
- if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
- while 1 {
- if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
- set state [rbu state]
- check_prestep_state test.db $state
- set rc [rbu step]
- check_poststep_state $rc test.db $state
- if {$rc!="SQLITE_OK"} break
- if {$step==1} { rbu close }
- }
- rbu close
- } {SQLITE_DONE}]
-
- uplevel [list do_execsql_test $tn.2 {
- PRAGMA integrity_check
- } ok]
-}
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucollate.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucollate.test
deleted file mode 100644
index 3b3b022a5b1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucollate.test
+++ /dev/null
@@ -1,63 +0,0 @@
-# 2018 March 22
-#
-# 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.
-#
-#***********************************************************************
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbucollate
-
-ifcapable !icu_collations {
- finish_test
- return
-}
-
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-reset_db
-
-# Create a simple RBU database. That expects to write to a table:
-#
-# CREATE TABLE t1(a PRIMARY KEY, b, c);
-#
-proc create_rbu1 {filename} {
- forcedelete $filename
- sqlite3 rbu1 $filename
- rbu1 eval {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES('a', 'one', 1, 0);
- INSERT INTO data_t1 VALUES('b', 'two', 2, 0);
- INSERT INTO data_t1 VALUES('c', 'three', 3, 0);
- }
- rbu1 close
- return $filename
-}
-
-do_execsql_test 1.0 {
- SELECT icu_load_collation('en_US', 'my-collate');
- CREATE TABLE t1(a COLLATE "my-collate" PRIMARY KEY, b, c);
-} {{}}
-
-do_test 1.2 {
- create_rbu1 testrbu.db
- sqlite3rbu rbu test.db testrbu.db
- rbu dbMain_eval { SELECT icu_load_collation('en_US', 'my-collate') }
- rbu dbRbu_eval { SELECT icu_load_collation('en_US', 'my-collate') }
- while 1 {
- set rc [rbu step]
- if {$rc!="SQLITE_OK"} break
- }
- rbu close
- db eval { SELECT * FROM t1 }
-} {a one 1 b two 2 c three 3}
-
-#forcedelete testrbu.db
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucrash.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucrash.test
deleted file mode 100644
index f42218105bc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucrash.test
+++ /dev/null
@@ -1,148 +0,0 @@
-# 2014 October 22
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbucrash
-
-db close
-forcedelete test.db-oal rbu.db
-sqlite3_shutdown
-sqlite3_config_uri 1
-reset_db
-
-# Set up a target database and an rbu update database. The target
-# db is the usual "test.db", the rbu db is "test.db2".
-#
-forcedelete test.db2
-do_execsql_test 1.0 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a), UNIQUE(b));
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t1 VALUES(7, 8, 9);
-
- ATTACH 'test.db2' AS rbu;
- CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(10, 11, 12, 0);
- INSERT INTO data_t1 VALUES(13, 14, 15, 0);
- INSERT INTO data_t1 VALUES(4, NULL, NULL, 1);
- INSERT INTO data_t1 VALUES(1, NULL, 100, '..x');
-}
-db_save_and_close
-
-
-# Determine the number of steps in applying the rbu update to the test
-# target database created above. Set $::rbu_num_steps accordingly
-#
-# Check that the same number of steps are required to apply the rbu
-# update using many calls to sqlite3rbu_step() on a single rbu handle
-# as required to apply it using a series of rbu handles, on each of
-# which sqlite3rbu_step() is called once.
-#
-do_test 1.1 {
- db_restore
- sqlite3rbu rbu test.db test.db2
- set nStep 0
- while {[rbu step]=="SQLITE_OK"} { incr nStep }
- rbu close
-} {SQLITE_DONE}
-set rbu_num_steps $nStep
-do_test 1.2 {
- db_restore
- set nStep 0
- while {1} {
- sqlite3rbu rbu test.db test.db2
- rbu step
- if {[rbu close]=="SQLITE_DONE"} break
- incr nStep
- }
- set nStep
-} $rbu_num_steps
-
-
-# Run one or more tests using the target (test.db) and rbu (test.db2)
-# databases created above. As follows:
-#
-# 1. This process starts the rbu update and calls sqlite3rbu_step()
-# $nPre times. Then closes the rbu update handle.
-#
-# 2. A second process resumes the rbu update and attempts to call
-# sqlite3rbu_step() $nStep times before closing the handle. A
-# crash is simulated during each xSync() of file test.db2.
-#
-# 3. This process attempts to resume the rbu update from whatever
-# state it was left in by step (2). Test that it is successful
-# in doing so and that the final target database is as expected.
-#
-# In total (nSync+1) tests are run, where nSync is the number of times
-# xSync() is called on test.db2.
-#
-proc do_rbu_crash_test {tn nPre nStep} {
-
- set script [subst -nocommands {
- sqlite3rbu rbu test.db file:test.db2?vfs=crash
- set i 0
- while {[set i] < $nStep} {
- if {[rbu step]!="SQLITE_OK"} break
- incr i
- }
- rbu close
- }]
-
- set bDone 0
- for {set iDelay 1} {$bDone==0} {incr iDelay} {
- forcedelete test.db2 test.db2-journal test.db test.db-oal test.db-wal
- db_restore
-
- if {$nPre>0} {
- sqlite3rbu rbu test.db file:test.db2
- set i 0
- for {set i 0} {$i < $nPre} {incr i} {
- if {[rbu step]!="SQLITE_OK"} break
- }
- rbu close
- }
-
- set res [
- crashsql -file test.db2 -delay $iDelay -tclbody $script -opendb {} {}
- ]
-
- set bDone 1
- if {$res == "1 {child process exited abnormally}"} {
- set bDone 0
- } elseif {$res != "0 {}"} {
- error "unexected catchsql result: $res"
- }
-
- sqlite3rbu rbu test.db test.db2
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
-
- sqlite3 db test.db
- do_execsql_test $tn.delay=$iDelay {
- SELECT * FROM t1;
- PRAGMA integrity_check;
- } {1 2 100 7 8 9 10 11 12 13 14 15 ok}
- db close
- }
-}
-
-for {set nPre 0} {$nPre < $rbu_num_steps} {incr nPre} {
- for {set is 1} {$is <= ($rbu_num_steps - $nPre)} {incr is} {
- do_rbu_crash_test 2.pre=$nPre.step=$is $nPre $is
- }
-}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucrash2.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucrash2.test
deleted file mode 100644
index 5f2ba604d12..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbucrash2.test
+++ /dev/null
@@ -1,106 +0,0 @@
-# 2017 March 02
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbucrash2
-
-db close
-forcedelete test.db-oal rbu.db
-sqlite3_shutdown
-sqlite3_config_uri 1
-reset_db
-
-# Set up a target database and an rbu update database. The target
-# db is the usual "test.db", the rbu db is "test.db2".
-#
-forcedelete test.db2
-do_execsql_test 1.0 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a), UNIQUE(b));
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t1 VALUES(7, 8, 9);
-
- ATTACH 'test.db2' AS rbu;
- CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES('one', randomblob(3500), NULL, 0);
- INSERT INTO data_t1 VALUES('two', randomblob(3500), NULL, 0);
- INSERT INTO data_t1 VALUES('three', randomblob(3500), NULL, 0);
- INSERT INTO data_t1 VALUES('four', randomblob(3500), NULL, 0);
- INSERT INTO data_t1 VALUES('five', randomblob(3500), NULL, 0);
- INSERT INTO data_t1 VALUES('six', randomblob(3500), NULL, 0);
-}
-db_save_and_close
-
-proc do_rbu_crash_test2 {tn script} {
-
- foreach {f blksz} {
- test.db 512
- test.db2 512
- test.db 4096
- test.db2 4096
- } {
- set bDone 0
- for {set iDelay 1} {$bDone==0} {incr iDelay} {
- forcedelete test.db2 test.db2-journal test.db test.db-oal test.db-wal
- db_restore
-
- set res [
- crashsql -file $f -delay $iDelay -tclbody $script -dflt 1 -opendb {} \
- -blocksize $blksz {}
- ]
-
- set bDone 1
- if {$res == "1 {child process exited abnormally}"} {
- set bDone 0
- } elseif {$res != "0 {}"} {
- error "unexected catchsql result: $res"
- }
-
- sqlite3rbu rbu test.db test.db2
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
-
- sqlite3 db test.db
- do_execsql_test $tn.delay=$iDelay.f=$f.blksz=$blksz {
- PRAGMA integrity_check;
- } {ok}
- db close
- }
- }
-}
-
-for {set x 1} {$x < 10} {incr x} {
- do_rbu_crash_test2 1.$x {
- sqlite3rbu rbu test.db test.db2
- while {[rbu step]=="SQLITE_OK"} {
- rbu savestate
- }
- rbu close
- }
-}
-
-for {set x 1} {$x < 2} {incr x} {
- do_rbu_crash_test2 2.$x {
- sqlite3rbu rbu test.db test.db2
- while {[rbu step]=="SQLITE_OK"} {
- rbu close
- sqlite3rbu rbu test.db test.db2
- }
- rbu close
- }
-}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbudiff.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbudiff.test
deleted file mode 100644
index 6f6af828047..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbudiff.test
+++ /dev/null
@@ -1,303 +0,0 @@
-# 2015-07-31
-#
-# 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.
-#
-#***********************************************************************
-#
-# Tests for the [sqldiff --rbu] command.
-#
-#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set testprefix rbudiff
-
-set PROG [test_find_sqldiff]
-db close
-
-proc get_rbudiff_sql {db1 db2} {
- exec $::PROG --rbu $db1 $db2
-}
-
-proc get_vtab_rbudiff_sql {db1 db2} {
- exec $::PROG --vtab --rbu $db1 $db2
-}
-
-proc step_rbu {target rbu} {
- while 1 {
- sqlite3rbu rbu $target $rbu
- set rc [rbu step]
- rbu close
- if {$rc != "SQLITE_OK"} break
- }
- set rc
-}
-
-proc apply_rbudiff {sql target} {
- test_rbucount $sql
- forcedelete rbu.db
- sqlite3 rbudb rbu.db
- rbudb eval $sql
- rbudb close
- step_rbu $target rbu.db
-}
-
-proc sqlesc {id} {
- set ret "'[string map {' ''} $id]'"
- set ret
-}
-
-# The only argument is the output of an [sqldiff -rbu] run. This command
-# tests that the contents of the rbu_count table is correct. An exception
-# is thrown if it is not.
-#
-proc test_rbucount {sql} {
- sqlite3 tmpdb ""
- tmpdb eval $sql
- tmpdb eval {
- SELECT name FROM sqlite_master WHERE name LIKE 'data%' AND type='table'
- } {
- set a [tmpdb eval "SELECT count(*) FROM [sqlesc $name]"]
- set b [tmpdb eval {SELECT cnt FROM rbu_count WHERE tbl = $name}]
- if {$a != $b} {
- tmpdb close
- error "rbu_count error - tbl = $name"
- }
- }
- tmpdb close
- return ""
-}
-
-proc rbudiff_cksum {db1} {
- set txt ""
-
- sqlite3 dbtmp $db1
- foreach tbl [dbtmp eval {SELECT name FROM sqlite_master WHERE type='table'}] {
- set cols [list]
- dbtmp eval "PRAGMA table_info = [sqlesc $tbl]" {
- lappend cols "quote( $name )"
- }
- append txt [dbtmp eval \
- "SELECT [join $cols {||'.'||}] FROM [sqlesc $tbl] ORDER BY 1"
- ]
- }
- dbtmp close
-
- md5 $txt
-}
-
-foreach {tn init mod} {
- 1 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
-
- CREATE TABLE t2(a, b, c, PRIMARY KEY(b, c));
- INSERT INTO t2 VALUES(1, 2, 3);
- INSERT INTO t2 VALUES(4, 5, 6);
- } {
- INSERT INTO t1 VALUES(7, 8, 9);
- DELETE FROM t1 WHERE a=4;
- UPDATE t1 SET c = 11 WHERE a = 1;
-
- INSERT INTO t2 VALUES(7, 8, 9);
- DELETE FROM t2 WHERE a=4;
- UPDATE t2 SET c = 11 WHERE a = 1;
- }
-
- 2 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b, c));
- INSERT INTO t1 VALUES('u', 'v', 'w');
- INSERT INTO t1 VALUES('x', 'y', 'z');
- } {
- DELETE FROM t1 WHERE a='u';
- INSERT INTO t1 VALUES('a', 'b', 'c');
- }
-
- 3 {
- CREATE TABLE t1(i INTEGER PRIMARY KEY, x);
- INSERT INTO t1 VALUES(1,
- X'0000000000000000111111111111111122222222222222223333333333333333'
- );
- CREATE TABLE t2(y INTEGER PRIMARY KEY, x);
- INSERT INTO t2 VALUES(1,
- X'0000000000000000111111111111111122222222222222223333333333333333'
- );
- } {
- DELETE FROM t1;
- INSERT INTO t1 VALUES(1,
- X'0000000000000000111111111111111122222555555552223333333333333333'
- );
- DELETE FROM t2;
- INSERT INTO t2 VALUES(1,
- X'0000000000000000111111111111111122222222222222223333333FFF333333'
- );
- }
-
- 4 {
- CREATE TABLE x1(a, b, c, PRIMARY KEY(a, b, c));
- INSERT INTO x1 VALUES('u', 'v', NULL);
- INSERT INTO x1 VALUES('x', 'y', 'z');
- INSERT INTO x1 VALUES('a', NULL, 'b');
- } {
- INSERT INTO x1 VALUES('a', 'b', 'c');
- }
-
- 5 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, NULL);
- INSERT INTO t1 VALUES(2, X'');
- } {
- UPDATE t1 SET b = X'' WHERE a=1;
- UPDATE t1 SET b = NULL WHERE a=2;
- }
-
-} {
- catch { db close }
-
- forcedelete test.db test.db2
- sqlite3 db test.db
- db eval "$init"
- sqlite3 db test.db2
- db eval "$init ; $mod"
- db close
-
- do_test 1.$tn.2 {
- set sql [get_rbudiff_sql test.db test.db2]
- apply_rbudiff $sql test.db
- } {SQLITE_DONE}
- do_test 1.$tn.3 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
-
- forcedelete test.db test.db2
- sqlite3 db test.db
- db eval "$init ; $mod"
- sqlite3 db test.db2
- db eval "$init"
- db close
-
- do_test 1.$tn.4 {
- set sql [get_rbudiff_sql test.db test.db2]
- apply_rbudiff $sql test.db
- } {SQLITE_DONE}
- do_test 1.$tn.5 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
-}
-
-#-------------------------------------------------------------------------
-# Test that if the --vtab switch is present, [sqldiff] handles virtual
-# table types fts[345] and rtree correctly.
-#
-ifcapable fts3&&fts5&&rtree {
-
-foreach {tn init mod} {
- 1 {
- CREATE VIRTUAL TABLE t1 USING fts5(c);
- INSERT INTO t1 VALUES('a b c');
- INSERT INTO t1 VALUES('a b c');
- } {
- DELETE FROM t1 WHERE rowid = 1;
- INSERT INTO t1 VALUES('a b c');
- }
-
- 2 {
- CREATE VIRTUAL TABLE "x y" USING 'rtree'(id, x1, x2);
- INSERT INTO "x y" VALUES(1, 2, 3);
- INSERT INTO "x y" VALUES(2, 4, 6);
- } {
- DELETE FROM "x y" WHERE rowid = 1;
- INSERT INTO "x y" VALUES(3, 6, 9);
- }
-
- 3 {
- CREATE VIRTUAL TABLE 'x''y' USING fts3;
- INSERT INTO 'x''y' VALUES('one two three');
- INSERT INTO 'x''y' VALUES('four five six');
- } {
- DELETE FROM 'x''y' WHERE rowid = 1;
- INSERT INTO 'x''y' VALUES('one two three');
- }
-} {
-
- forcedelete test.db test.db2
- sqlite3 db test.db
- db eval "$init"
- sqlite3 db test.db2
- db eval "$init ; $mod"
- db close
-
- do_test 2.$tn.1 {
- set sql [get_vtab_rbudiff_sql test.db test.db2]
- apply_rbudiff $sql test.db
- } {SQLITE_DONE}
- do_test 2.$tn.2 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
-}
-
-}
-
-ifcapable fts5 {
- foreach {tn init mod} {
- 1 {
- CREATE VIRTUAL TABLE t1 USING fts5(c);
- INSERT INTO t1 VALUES('a b c');
- INSERT INTO t1 VALUES('a b c');
- } {
- DELETE FROM t1 WHERE rowid = 1;
- INSERT INTO t1 VALUES('a b c');
- }
-
- 2 {
- CREATE VIRTUAL TABLE t1 USING FTs5(c);
- INSERT INTO t1 VALUES('a b c');
- INSERT INTO t1 VALUES('a b c');
- } {
- DELETE FROM t1 WHERE rowid = 1;
- INSERT INTO t1 VALUES('a b c');
- }
-
- 3 {
- creAte virTUal
-tablE t1 USING FTs5(c);
- INSERT INTO t1 VALUES('a b c');
- INSERT INTO t1 VALUES('a b c');
- } {
- DELETE FROM t1 WHERE rowid = 1;
- INSERT INTO t1 VALUES('a b c');
- }
-
- } {
- forcedelete test.db test.db2
- sqlite3 db test.db
- db eval "$init"
- sqlite3 db test.db2
- db eval "$init ; $mod"
- db eval { INSERT INTO t1(t1) VALUES('optimize') }
- db close
-
- do_test 3.$tn.1 {
- set sql [get_vtab_rbudiff_sql test.db test.db2]
- apply_rbudiff $sql test.db
- } {SQLITE_DONE}
-
- sqlite3 db test.db
- sqlite3 db2 test.db2
- do_test 3.$tn.2 {
- db2 eval { SELECT * FROM t1 ORDER BY rowid }
- } [db eval { SELECT * FROM t1 ORDER BY rowid }]
-
- do_test 3.$tn.3 {
- db2 eval { INSERT INTO t1(t1) VALUES('integrity-check') }
- } {}
-
- db close
- db2 close
- }
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbudor.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbudor.test
deleted file mode 100644
index dcee7ac381e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbudor.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# 2016 October 21
-#
-# 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 test file focuses on interactions between RBU and the feature
-# enabled by SQLITE_DIRECT_OVERFLOW_READ - Direct Overflow Read.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbudor
-
-set bigA [string repeat a 5000]
-set bigB [string repeat b 5000]
-do_execsql_test 1.0 {
- PRAGMA page_size = 1024;
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);
- INSERT INTO t1 VALUES(1, $bigA);
-} {}
-
-do_test 1.1 {
- forcedelete rbu.db
- sqlite3 rbu rbu.db
- rbu eval {
- CREATE TABLE data_t1(a, b, rbu_control);
- INSERT INTO data_t1 VALUES(2, $bigB, 0);
- }
- rbu close
-} {}
-
-do_test 1.2 {
- sqlite3rbu rbu test.db rbu.db
- while {[rbu state]!="checkpoint"} {
- rbu step
- }
- rbu step
- db eval { SELECT * FROM t1 }
-} [list 1 $bigA 2 $bigB]
-
-do_test 1.3 {
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
-} {SQLITE_DONE}
-
-do_execsql_test 1.4 {
- SELECT * FROM t1
-} [list 1 $bigA 2 $bigB]
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault.test
deleted file mode 100644
index 3e78b6e09ea..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault.test
+++ /dev/null
@@ -1,237 +0,0 @@
-# 2014 October 22
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-source $testdir/malloc_common.tcl
-set ::testprefix rbufault
-
-proc copy_if_exists {src target} {
- if {[file exists $src]} {
- forcecopy $src $target
- } else {
- forcedelete $target
- }
-}
-
-foreach {tn2 setup sql expect} {
- 1 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX t1cb ON t1(c, b);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
-
- CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
- INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.');
- INSERT INTO data_t1 VALUES(4, 4, 4, 0);
- } {
- SELECT * FROM t1
- } {1 1 1 3 three 3 4 4 4}
-
- 2 {
- CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
- CREATE INDEX t2cb ON t2(c, b);
- INSERT INTO t2 VALUES('a', 'a', 'a');
- INSERT INTO t2 VALUES('b', 'b', 'b');
- INSERT INTO t2 VALUES('c', 'c', 'c');
-
- CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
- INSERT INTO data_t2 VALUES('b', NULL, NULL, 1);
- INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.');
- INSERT INTO data_t2 VALUES('d', 'd', 'd', 0);
- } {
- SELECT * FROM t2
- } {a a a c see c d d d}
-
- 3 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
- CREATE INDEX t1cb ON t1(c, b);
- CREATE INDEX t2cb ON t2(c, b);
-
- CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
- CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 2, 3, 0);
- INSERT INTO data_t2 VALUES(4, 5, 6, 0);
- } {
- SELECT * FROM t1 UNION ALL SELECT * FROM t2
- } {1 2 3 4 5 6}
-
- 4 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE INDEX t1c ON t1(c);
- INSERT INTO t1 VALUES('A', 'B', 'C');
- INSERT INTO t1 VALUES('D', 'E', 'F');
-
- CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES('D', NULL, NULL, 1);
- INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.');
- INSERT INTO data_t1 VALUES('G', 'H', 'I', 0);
- } {
- SELECT * FROM t1 ORDER BY a;
- } {A Z C G H I}
-
- 5 {
- CREATE TABLE t1(a, b, c);
- CREATE INDEX t1c ON t1(c, b);
-
- CREATE TABLE rbu.data_t1(a, b, c, rbu_rowid, rbu_control);
- INSERT INTO data_t1 VALUES('a', 'b', 'c', 1, 0);
- INSERT INTO data_t1 VALUES('d', 'e', 'f', '2', 0);
- } {
- SELECT * FROM t1 ORDER BY a;
- } {a b c d e f}
-
-} {
- catch {db close}
- forcedelete rbu.db test.db
- sqlite3 db test.db
- execsql {
- PRAGMA encoding = utf16;
- ATTACH 'rbu.db' AS rbu;
- }
- execsql $setup
- db close
-
- forcecopy test.db test.db.bak
- forcecopy rbu.db rbu.db.bak
-
- foreach {tn f reslist} {
- 1 oom-tra* {
- {0 SQLITE_DONE}
- {1 {SQLITE_NOMEM - out of memory}}
- {1 SQLITE_NOMEM}
- {1 SQLITE_IOERR_NOMEM}
- {1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}}
- }
-
- 2 ioerr-* {
- {0 SQLITE_DONE}
- {1 {SQLITE_IOERR - disk I/O error}}
- {1 SQLITE_IOERR}
- {1 SQLITE_IOERR_WRITE}
- {1 SQLITE_IOERR_READ}
- {1 SQLITE_IOERR_FSYNC}
- {1 {SQLITE_ERROR - SQL logic error}}
- {1 {SQLITE_ERROR - unable to open database: rbu.db}}
- {1 {SQLITE_IOERR - unable to open database: rbu.db}}
- }
-
- 3 shmerr-* {
- {0 SQLITE_DONE}
- {1 {SQLITE_IOERR - disk I/O error}}
- {1 SQLITE_IOERR}
- }
- } {
-
- catch {db close}
- sqlite3_shutdown
- set lookaside_config [sqlite3_config_lookaside 0 0]
- sqlite3_initialize
- autoinstall_test_functions
-
- do_faultsim_test 2.$tn2 -faults $::f -prep {
- catch { db close }
- forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
- forcecopy test.db.bak test.db
- forcecopy rbu.db.bak rbu.db
- } -body {
- sqlite3rbu rbu test.db rbu.db
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
- } -test {
- faultsim_test_result {*}$::reslist
- if {$testrc==0} {
- sqlite3 db test.db
- faultsim_integrity_check
- set res [db eval $::sql]
- if {$res != [list {*}$::expect]} {
- puts ""
- puts "res: $res"
- puts "exp: $expect"
- error "data not as expected!"
- }
- }
- }
-
- catch {db close}
- sqlite3_shutdown
- sqlite3_config_lookaside {*}$lookaside_config
- sqlite3_initialize
- autoinstall_test_functions
-
-
- for {set iStep 0} {$iStep<=21} {incr iStep} {
-
- forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
-
- copy_if_exists test.db.bak test.db
- copy_if_exists rbu.db.bak rbu.db
-
- sqlite3rbu rbu test.db rbu.db
- for {set x 0} {$x < $::iStep} {incr x} { rbu step }
- rbu close
-
-# sqlite3 x rbu.db ; puts "XYZ [x eval { SELECT * FROM rbu_state } ]" ; x close
-
- copy_if_exists test.db test.db.bak.2
- copy_if_exists test.db-wal test.db.bak.2-wal
- copy_if_exists test.db-oal test.db.bak.2-oal
- copy_if_exists rbu.db rbu.db.bak.2
-
- do_faultsim_test 3.$tn.$iStep -faults $::f -prep {
- catch { db close }
- forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
- copy_if_exists test.db.bak.2 test.db
- copy_if_exists test.db.bak.2-wal test.db-wal
- copy_if_exists test.db.bak.2-oal test.db-oal
- copy_if_exists rbu.db.bak.2 rbu.db
- } -body {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- rbu close
- } -test {
-
- if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"}
- faultsim_test_result {*}$::reslist
-
- if {$testrc==0} {
- # No error occurred. If the RBU has not already been fully applied,
- # apply the rest of it now. Then ensure that the final state of the
- # target db is as expected. And that "PRAGMA integrity_check"
- # passes.
- sqlite3rbu rbu test.db rbu.db
- while {[rbu step] == "SQLITE_OK"} {}
- rbu close
-
- sqlite3 db test.db
- faultsim_integrity_check
-
- set res [db eval $::sql]
- if {$res != [list {*}$::expect]} {
- puts ""
- puts "res: $res"
- puts "exp: $::expect"
- error "data not as expected!"
- }
- }
- }
- }
- }
-}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault2.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault2.test
deleted file mode 100644
index ec89397fdc9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault2.test
+++ /dev/null
@@ -1,58 +0,0 @@
-# 2014 October 22
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-source $testdir/malloc_common.tcl
-set ::testprefix rbufault2
-
-forcedelete rbu.db
-do_execsql_test 1.0 {
- CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y));
- INSERT INTO target VALUES(1, 2, 3);
- INSERT INTO target VALUES(4, 5, 6);
-
- ATTACH 'rbu.db' AS rbu;
- CREATE TABLE rbu.data_target(x, y, z, rbu_control);
- INSERT INTO data_target VALUES(7, 8, 9, 0);
- INSERT INTO data_target VALUES(1, 11, 12, 0);
- DETACH rbu;
-}
-db close
-
-forcecopy test.db test.db-bak
-forcecopy rbu.db rbu.db-bak
-
-do_faultsim_test 1 -faults oom* -prep {
- forcecopy test.db-bak test.db
- forcecopy rbu.db-bak rbu.db
- forcedelete test.db-oal test.db-wal rbu.db-journal
- sqlite3rbu rbu test.db rbu.db
-} -body {
- while {[rbu step]=="SQLITE_OK"} { }
- rbu close
-} -test {
- faultsim_test_result \
- {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: target.x}} \
- {1 SQLITE_CONSTRAINT} \
- {1 SQLITE_NOMEM} \
- {1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}} \
- {1 {SQLITE_NOMEM - out of memory}}
-}
-
-
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault3.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault3.test
deleted file mode 100644
index 4fd202d0b7a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault3.test
+++ /dev/null
@@ -1,98 +0,0 @@
-# 2016 April 20
-#
-# 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 contains fault injection tests for RBU vacuum operations.
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-source $testdir/malloc_common.tcl
-set ::testprefix rbufault3
-
-foreach {fault errlist} {
- oom-* {
- {1 SQLITE_NOMEM}
- {1 SQLITE_IOERR_NOMEM}
- {1 {SQLITE_NOMEM - out of memory}}
- }
-
- ioerr-* {
- {1 {SQLITE_IOERR - disk I/O error}}
- {1 SQLITE_IOERR}
- {1 SQLITE_IOERR_WRITE}
- {1 SQLITE_IOERR_FSYNC}
- {1 SQLITE_IOERR_READ}
- {1 {SQLITE_IOERR - unable to open database: test.db2}}
- {1 {SQLITE_ERROR - unable to open database: test.db2}}
- {1 {SQLITE_ERROR - SQL logic error}}
- }
-
- cantopen* {
- {1 {SQLITE_CANTOPEN - unable to open database: test.db2}}
- {1 {SQLITE_CANTOPEN - unable to open database: test.db2}}
- {1 {SQLITE_CANTOPEN - unable to open database file}}
- {1 SQLITE_CANTOPEN}
- }
-
-} {
-
- reset_db
- do_execsql_test 0 {
- CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y));
- INSERT INTO target VALUES(1, 2, 3);
- INSERT INTO target VALUES(4, 5, 6);
- INSERT INTO target VALUES(7, 8, 9);
- CREATE INDEX i1 ON target(z);
- }
- faultsim_save_and_close
-
- do_faultsim_test 1 -faults $fault -prep {
- faultsim_restore_and_reopen
- forcedelete test.db2
- } -body {
- sqlite3rbu_vacuum rbu test.db test.db2
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
- } -test {
- eval [list faultsim_test_result {0 SQLITE_DONE} {*}$::errlist]
- }
-
- do_faultsim_test 2 -faults $fault -prep {
- faultsim_restore_and_reopen
- forcedelete test.db2
- } -body {
- sqlite3rbu_vacuum rbu test.db test.db2
- rbu step
- rbu close
- } -test {
- eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
- }
-
- forcedelete test.db2
- sqlite3rbu_vacuum rbu test.db test.db2
- rbu step
- rbu close
- faultsim_save_and_close
-
- do_faultsim_test 3 -faults $fault -prep {
- faultsim_restore_and_reopen
- forcedelete test.db2
- } -body {
- sqlite3rbu_vacuum rbu test.db test.db2
- rbu step
- rbu close
- } -test {
- eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
- }
-
-}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault4.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault4.test
deleted file mode 100644
index fe6cc90dc93..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufault4.test
+++ /dev/null
@@ -1,66 +0,0 @@
-# 2014 October 22
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-source $testdir/malloc_common.tcl
-set ::testprefix rbufault4
-
-for {set tn 1} {1} {incr tn} {
- reset_db
- do_execsql_test 1.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1b ON t1(b);
- CREATE INDEX i1c ON t1(c);
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- }
-
- forcedelete test.db2
- sqlite3rbu_vacuum rbu test.db test.db2
- for {set i 0} {$i < $tn} {incr i} { rbu step }
- set rc [rbu close]
- if {$rc!="SQLITE_OK"} {
- if {$rc!="SQLITE_DONE"} {error $rc}
- break
- }
- faultsim_save
-
- do_faultsim_test $tn -faults oom-t* -prep {
- faultsim_restore
- } -body {
- sqlite3rbu_vacuum rbu test.db test.db2
- while 1 {
- set rc [rbu step]
- if {$rc=="SQLITE_DONE"} break
- if {$rc!="SQLITE_OK"} { error $rc }
- }
- } -test {
- catch {rbu close}
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM} {1 SQLITE_IOERR_NOMEM}
-
- sqlite3rbu_vacuum rbu test.db test.db2
- while {[rbu step]=="SQLITE_OK"} {}
- set trc [rbu close]
- if {$trc!="SQLITE_DONE"} { error "Got $trc instead of SQLITE_DONE!" }
-
- set rc [db one {PRAGMA integrity_check}]
- if {$rc!="ok"} { error "Got $rc instead of ok!" }
- }
-}
-
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufts.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufts.test
deleted file mode 100644
index c2821a95558..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbufts.test
+++ /dev/null
@@ -1,134 +0,0 @@
-# 2014 August 30
-#
-# 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 contains tests for the RBU module. More specifically, it
-# contains tests to ensure that RBU works with FTS tables.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbufts
-
-ifcapable !fts3 {
- finish_test
- return
-}
-
-proc step_rbu {target rbu} {
- while 1 {
- sqlite3rbu rbu $target $rbu
- set rc [rbu step]
- rbu close
- if {$rc != "SQLITE_OK"} break
- }
- set rc
-}
-
-proc apply_rbu_update {target sql} {
- forcedelete rbu.db
- sqlite3 dbrbu rbu.db
- execsql $sql dbrbu
- dbrbu close
-
- step_rbu $target rbu.db
-}
-
-do_execsql_test 1.1.0 {
- CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b);
- CREATE VIRTUAL TABLE xx USING fts4(content=t1, a, b);
- INSERT INTO t1(rowid, a, b) VALUES(10, 'a b c', 'c b a');
- INSERT INTO t1(rowid, a, b) VALUES(20, 'a b c', 'd e f');
- INSERT INTO t1(rowid, a, b) VALUES(30, 'd e f', 'a b c');
- INSERT INTO t1(rowid, a, b) VALUES(40, 'd e f', 'd e f');
-}
-
-do_execsql_test 1.1.1 {
- INSERT INTO xx(xx) VALUES('rebuild');
- INSERT INTO xx(xx) VALUES('integrity-check');
-}
-
-do_test 1.1.2 {
- apply_rbu_update test.db {
- CREATE TABLE data_t1(i, a, b, rbu_control);
- INSERT INTO data_t1 VALUES(20, NULL, NULL, 1); -- delete
- INSERT INTO data_t1 VALUES(30, 'x y z', NULL, '.x.'); -- update
- INSERT INTO data_t1 VALUES(50, '1 2 3', 'x y z', 0); -- insert
-
- CREATE VIEW data0_xx AS
- SELECT i AS rbu_rowid, a, b,
- CASE WHEN rbu_control IN (0, 1)
- THEN rbu_control ELSE substr(rbu_control, 2) END AS rbu_control
- FROM data_t1;
- }
-} {SQLITE_DONE}
-
-do_execsql_test 1.1.3 {
- INSERT INTO xx(xx) VALUES('integrity-check');
-}
-
-reset_db
-do_execsql_test 1.2.1 {
- CREATE TABLE ccc(addr, text);
- CREATE VIRTUAL TABLE ccc_fts USING fts4(addr, text, content=ccc);
- INSERT INTO ccc VALUES('a b c', 'd e f');
- INSERT INTO ccc VALUES('a b c', 'd e f');
- INSERT INTO ccc_fts(ccc_fts) VALUES('rebuild');
- INSERT INTO ccc_fts(ccc_fts) VALUES('integrity-check');
-}
-
-do_test 1.2.2 {
- apply_rbu_update test.db {
- CREATE TABLE data_ccc(addr, text, rbu_rowid, rbu_control);
- CREATE VIEW data0_ccc_fts AS SELECT * FROM data_ccc;
- INSERT INTO data_ccc VALUES(NULL, NULL, 1, 1);
- INSERT INTO data_ccc VALUES('x y z', NULL, 2, 'x.');
- INSERT INTO data_ccc VALUES('y y y', '1 1 1', 3, 0);
- }
-} {SQLITE_DONE}
-
-do_execsql_test 1.2.3 {
- INSERT INTO ccc_fts(ccc_fts) VALUES('integrity-check');
-}
-do_execsql_test 1.2.4 {
- SELECT rowid, * FROM ccc_fts;
-} {2 {x y z} {d e f} 3 {y y y} {1 1 1}}
-
-#-------------------------------------------------------------------------
-# Test the outcome of attempting to delete or update a row within a
-# contentless FTS table using RBU. An error.
-#
-reset_db
-do_execsql_test 3.1 {
- CREATE VIRTUAL TABLE ft USING fts4(x, content=);
- INSERT INTO ft(rowid, x) VALUES(1, '1 2 3');
- INSERT INTO ft(rowid, x) VALUES(2, '4 5 6');
-}
-
-do_test 3.2 {
- list [catch { apply_rbu_update test.db {
- CREATE TABLE data_ft(x, rbu_rowid, rbu_control);
- INSERT INTO data_ft VALUES(NULL, 2, 1);
- } } msg] $msg]
-} {1 {SQLITE_ERROR - SQL logic error]}}
-
-do_test 3.3 {
- list [catch { apply_rbu_update test.db {
- CREATE TABLE data_ft(x, rbu_rowid, rbu_control);
- INSERT INTO data_ft VALUES('7 8 9', 1, 'x');
- } } msg] $msg]
-} {1 {SQLITE_ERROR - SQL logic error]}}
-
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbumulti.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbumulti.test
deleted file mode 100644
index 59c6538c6ca..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbumulti.test
+++ /dev/null
@@ -1,175 +0,0 @@
-# 2018 January 11
-#
-# 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 contains tests of multiple RBU operations running
-# concurrently within the same process.
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbumulti
-
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-
-autoinstall_test_functions
-
-proc build_db {db} {
- $db eval {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- CREATE INDEX i2 ON t1(c);
-
- WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<500 )
- INSERT INTO t1
- SELECT randomblob(10), randomblob(100), randomblob(100) FROM s;
- }
-}
-
-proc build_rbu {db} {
- $db eval {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100 )
- INSERT INTO data_t1
- SELECT randomblob(10), randomblob(100), randomblob(100), 0 FROM s;
- }
-}
-
-proc step_rbu2 {bOpenClose openr1 openr2} {
-
- forcedelete teststate.db1
- forcedelete teststate.db2
-
- if {$bOpenClose!=0 && $bOpenClose!=1} { error $bOpenClose }
- if {$bOpenClose==0} {
- eval $openr1
- eval $openr2
- }
-
- set b1 0
- set b2 0
-
- while {$b1==0 || $b2==0} {
- if {$bOpenClose==1} {
- if {$b1==0} { eval $openr1 teststate.db1 }
- if {$b2==0} { eval $openr2 teststate.db2 }
- }
- if {$b1==0} {
- set rc1 [r1 step]
- if {$rc1 != "SQLITE_OK"} { set b1 1 }
- }
- if {$b2==0} {
- set rc2 [r2 step]
- if {$rc2 != "SQLITE_OK"} { set b2 1 }
- }
- if {$bOpenClose==1} {
- if {$b1==0} { r1 close }
- if {$b2==0} { r2 close }
- }
- }
-
- set rc1 [r1 close]
- set rc2 [r2 close]
-
- list $rc1 $rc2
-}
-
-
-for {set i 0} {$i<=3} {incr i} {
-
- if {$i & 0x01} {
- sqlite3rbu_create_vfs -default myrbu ""
- }
- set bOpenClose [expr $i>>1]
-
- forcedelete test.db
- forcedelete test.db2
- forcedelete rbu.db
- forcedelete rbu.db2
-
- do_test 1.$i.0 {
- sqlite3 db test.db
- sqlite3 db2 test.db2
- build_db db
- build_db db2
-
- sqlite3 rbu1 rbu.db
- sqlite3 rbu2 rbu.db2
-
- build_rbu rbu1
- build_rbu rbu2
-
- rbu1 close
- rbu2 close
- } {}
-
- set m1 [db eval {SELECT md5sum(a, b, c) FROM t1}]
- set m2 [db2 eval {SELECT md5sum(a, b, c) FROM t1}]
-
- do_test 1.$i.1 {
- step_rbu2 $bOpenClose {
- sqlite3rbu r1 test.db rbu.db
- } {
- sqlite3rbu r2 test.db2 rbu.db2
- }
- } {SQLITE_DONE SQLITE_DONE}
-
- do_execsql_test -db db 1.$i.2.1 { PRAGMA integrity_check } ok
- do_execsql_test -db db2 1.$i.2.2 { PRAGMA integrity_check } ok
-
- do_execsql_test -db db 1.$i.3.1 { SELECT md5sum(a, b, c)==$m1 FROM t1 } 0
- do_execsql_test -db db2 1.$i.3.2 { SELECT md5sum(a, b, c)==$m2 FROM t1 } 0
-
- catch { db close }
- catch { db2 close }
- #-----------------------------------------------------------------------
- forcedelete test.db2
- forcedelete test.db
- forcedelete rbu.db2
-
- do_test 1.$i.4 {
- sqlite3 db test.db
- sqlite3 db2 test.db2
- build_db db
- build_db db2
- sqlite3 rbu2 rbu.db2
- build_rbu rbu2
- rbu2 close
- } {}
-
- set m1 [db eval {SELECT md5sum(a, b, c) FROM t1}]
- set m2 [db2 eval {SELECT md5sum(a, b, c) FROM t1}]
-
- do_test 1.$i.5 {
- step_rbu2 $bOpenClose {
- sqlite3rbu_vacuum r1 test.db
- } {
- sqlite3rbu r2 test.db2 rbu.db2
- }
- } {SQLITE_DONE SQLITE_DONE}
-
- do_execsql_test -db db 1.$i.6.1 { SELECT md5sum(a, b, c)==$m1 FROM t1 } 1
- do_execsql_test -db db2 1.$i.6.2 { SELECT md5sum(a, b, c)==$m2 FROM t1 } 0
-
- do_execsql_test -db db 1.$i.7.1 { PRAGMA integrity_check } ok
- do_execsql_test -db db2 1.$i.7.2 { PRAGMA integrity_check } ok
-
- catch { db close }
- catch { db2 close }
- if {$i & 0x01} {
- sqlite3rbu_destroy_vfs myrbu
- }
-
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuprogress.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuprogress.test
deleted file mode 100644
index 078b3b0d300..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuprogress.test
+++ /dev/null
@@ -1,419 +0,0 @@
-# 2016 March 18
-#
-# 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.
-#
-#***********************************************************************
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbuprogress
-
-
-proc create_db_file {filename sql} {
- forcedelete $filename
- sqlite3 tmpdb $filename
- tmpdb eval $sql
- tmpdb close
-}
-
-# Create a simple RBU database. That expects to write to a table:
-#
-# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
-#
-proc create_rbu1 {filename} {
- create_db_file $filename {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(1, 2, 3, 0);
- INSERT INTO data_t1 VALUES(2, 'two', 'three', 0);
- INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0);
-
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data_t1', 3);
- }
- return $filename
-}
-
-
-do_execsql_test 1.0 {
- PRAGMA page_size = 4096;
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
-}
-
-do_test 1.1 {
- create_rbu1 rbu.db
- sqlite3rbu rbu test.db rbu.db
- rbu bp_progress
-} {0 0}
-do_test 1.2 { rbu step ; rbu bp_progress } {3333 0}
-do_test 1.3 { rbu step ; rbu bp_progress } {6666 0}
-do_test 1.4 { rbu step ; rbu bp_progress } {10000 0}
-do_test 1.5 { rbu step ; rbu bp_progress } {10000 0}
-do_test 1.6 { rbu step ; rbu bp_progress } {10000 0}
-do_test 1.7 { rbu step ; rbu bp_progress } {10000 5000}
-do_test 1.8 { rbu step ; rbu bp_progress } {10000 10000}
-do_test 1.9 { rbu step ; rbu bp_progress } {10000 10000}
-
-do_test 1.10 {
- rbu close
-} {SQLITE_DONE}
-
-#-------------------------------------------------------------------------
-#
-proc do_sp_test {tn bReopen target rbu reslist} {
- uplevel [list do_test $tn [subst -nocommands {
- if {$bReopen==0} { sqlite3rbu rbu $target $rbu }
- set res [list]
- while 1 {
- if {$bReopen} { sqlite3rbu rbu $target $rbu }
- set rc [rbu step]
- if {[set rc] != "SQLITE_OK"} { rbu close ; error "error 1" }
- lappend res [lindex [rbu bp_progress] 0]
- if {[lindex [set res] end]==10000} break
- if {$bReopen} { rbu close }
- }
- if {[set res] != [list $reslist]} {
- rbu close
- error "1. reslist incorrect (expect=$reslist got=[set res])"
- }
-
- # One step to clean up the temporary tables used to update the only
- # target table in the rbu database. And one more to move the *-oal
- # file to *-wal. After each of these steps, the progress remains
- # at "10000 0".
- #
- if {[lindex [list $reslist] 0]!=-1} {
- rbu step
- set res [rbu bp_progress]
- if {[set res] != [list 10000 0]} {
- rbu close
- error "2. reslist incorrect (expect=10000 0 got=[set res])"
- }
- }
-
- rbu step
- set res [rbu bp_progress]
- if {[set res] != [list 10000 0]} {
- rbu close
- error "3. reslist incorrect (expect=10000 0 got=[set res])"
- }
-
- # Do the checkpoint.
- while {[rbu step]=="SQLITE_OK"} {
- foreach {a b} [rbu bp_progress] {}
- if {[set a]!=10000 || [set b]<=0 || [set b]>10000} {
- rbu close
- error "4. reslist incorrect (expect=10000 1..10000 got=[set a] [set b])"
- }
- }
-
- set res [rbu bp_progress]
- if {[set res] != [list 10000 10000]} {
- rbu close
- error "5. reslist is incorrect (expect=10000 10000 got=[set res])"
- }
-
- rbu close
- }] {SQLITE_DONE}]
-}
-
-foreach {bReopen} { 0 1 } {
- reset_db
- do_test 2.$bReopen.1.0 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- }
- create_db_file rbu.db {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(4, 4, 4, 0);
- INSERT INTO data_t1 VALUES(5, 5, 5, 0);
-
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data_t1', 2);
- }
- } {}
- do_sp_test 2.$bReopen.1.1 $bReopen test.db rbu.db {5000 10000}
-
- reset_db
- do_test 2.$bReopen.2.0 {
- execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) }
- create_rbu1 rbu.db
- } {rbu.db}
- do_sp_test 2.$bReopen.2.1 $bReopen test.db rbu.db {3333 6666 10000}
-
- reset_db
- do_test 2.$bReopen.3.0 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
- }
- create_db_file rbu.db {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(4, 4, 4, 0);
- INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
- INSERT INTO data_t1 VALUES(5, NULL, NULL, 1);
-
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data_t1', 3);
- }
- } {}
- do_sp_test 2.$bReopen.3.1 $bReopen test.db rbu.db {1666 3333 6000 8000 10000}
-
- reset_db
- do_test 2.$bReopen.4.0 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
- }
- create_db_file rbu.db {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(2, 4, 4, '.xx');
-
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data_t1', 1);
- }
- } {}
- do_sp_test 2.$bReopen.4.1 $bReopen test.db rbu.db {3333 6666 10000}
-
- reset_db
- do_test 2.$bReopen.5.0 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
- }
- create_db_file rbu.db {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(4, NULL, 4, '.xx');
-
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data_t1', 1);
- }
- } {}
- do_sp_test 2.$bReopen.5.1 $bReopen test.db rbu.db {10000}
-
- reset_db
- do_test 2.$bReopen.6.0 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
- }
- create_db_file rbu.db {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(4, 4, 4, 0);
- INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
- INSERT INTO data_t1 VALUES(5, NULL, NULL, 1);
- }
- } {}
- do_sp_test 2.$bReopen.6.1 $bReopen test.db rbu.db {-1 -1 -1 -1 -1 10000}
-}
-
-#-------------------------------------------------------------------------
-# The following tests verify that the API works when resuming an update
-# during the incremental checkpoint stage.
-#
-proc do_phase2_test {tn bReopen target rbu nStep} {
- uplevel [list do_test $tn [subst -nocommands {
-
- # Build the OAL/WAL file:
- sqlite3rbu rbu $target $rbu
- while {[lindex [rbu bp_progress] 0]<10000} {
- set rc [rbu step]
- if {"SQLITE_OK" != [set rc]} { rbu close }
- }
-
- # Clean up the temp tables and move the *-oal file to *-wal.
- rbu step
- rbu step
-
- for {set i 0} {[set i] < $nStep} {incr i} {
- if {$bReopen} {
- rbu close
- sqlite3rbu rbu $target $rbu
- }
- rbu step
- set res [rbu bp_progress]
- set expect [expr (1 + [set i]) * 10000 / $nStep]
- if {[lindex [set res] 1] != [set expect]} {
- error "Have [set res], expected 10000 [set expect]"
- }
- }
-
- set rc [rbu step]
- if {[set rc] != "SQLITE_DONE"} {
- error "Have [set rc], expected SQLITE_DONE"
- }
-
- rbu close
- }] {SQLITE_DONE}]
-}
-
-foreach bReopen {0 1} {
- do_test 3.$bReopen.1.0 {
- reset_db
- execsql {
- PRAGMA page_size = 4096;
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
- }
- create_db_file rbu.db {
- CREATE TABLE data_t1(a, b, rbu_control);
- CREATE TABLE data_t2(a, b, rbu_control);
- CREATE TABLE data_t3(a, b, rbu_control);
- CREATE TABLE data_t4(a, b, rbu_control);
- INSERT INTO data_t1 VALUES(1, 2, 0);
- INSERT INTO data_t2 VALUES(1, 2, 0);
- INSERT INTO data_t3 VALUES(1, 2, 0);
- INSERT INTO data_t4 VALUES(1, 2, 0);
-
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data_t1', 1);
- INSERT INTO rbu_count VALUES('data_t2', 1);
- INSERT INTO rbu_count VALUES('data_t3', 1);
- INSERT INTO rbu_count VALUES('data_t4', 1);
- }
- } {}
- do_phase2_test 3.$bReopen.1.1 $bReopen test.db rbu.db 5
-}
-
-
-foreach {bReopen} { 0 1 } {
- foreach {tn tbl} {
- ipk { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) }
- wr { CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID }
- pk { CREATE TABLE t1(a INT PRIMARY KEY, b, c) }
- } {
-
- foreach {tn2 rbusql r1 r3} {
- 1 {
- CREATE TABLE data0_t1(a, b, c, rbu_control);
- INSERT INTO data0_t1 VALUES(15, 15, 15, 0);
- INSERT INTO data0_t1 VALUES(20, 20, 20, 0);
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data0_t1', 2);
- }
- {2500 5000 7500 10000}
- {1666 3333 5000 6666 8333 10000}
-
- 2 {
- CREATE TABLE data0_t1(a, b, c, rbu_control);
- INSERT INTO data0_t1 VALUES(10, 10, 10, 2);
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data0_t1', 1);
- }
- {3333 6666 10000}
- {2000 4000 6000 8000 10000}
-
- 3 {
- CREATE TABLE data0_t1(a, b, c, rbu_control);
- INSERT INTO data0_t1 VALUES(7, 7, 7, 2);
- INSERT INTO data0_t1 VALUES(10, 10, 10, 2);
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data0_t1', 2);
- }
- {2500 4000 6000 8000 10000}
- {1666 2500 3750 5000 6250 7500 8750 10000}
-
- } {
-
- reset_db ; execsql $tbl
- do_test 4.$tn.$bReopen.$tn2.0 {
- execsql {
- CREATE INDEX t1c ON t1(c);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(5, 5, 5);
- INSERT INTO t1 VALUES(10, 10, 10);
- }
- create_db_file rbu.db $rbusql
- } {}
-
- set R(ipk) $r1
- set R(wr) $r1
- set R(pk) $r3
- do_sp_test 4.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn)
- }
- }
-}
-
-foreach {bReopen} { 0 1 } {
- foreach {tn tbl} {
- nopk {
- CREATE TABLE t1(a, b, c);
- CREATE INDEX t1c ON t1(c);
- }
- vtab {
- CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
- }
- } {
-
- if {$tn=="vtab"} { ifcapable !fts5 break }
-
- foreach {tn2 rbusql r1 r2} {
- 1 {
- CREATE TABLE data0_t1(a, b, c, rbu_rowid, rbu_control);
- INSERT INTO data0_t1 VALUES(15, 15, 15, 4, 0);
- INSERT INTO data0_t1 VALUES(20, 20, 20, 5, 0);
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data0_t1', 2);
- }
- {2500 5000 7500 10000}
- {5000 10000}
-
- 2 {
- CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control);
- INSERT INTO data0_t1 VALUES(0, 7, 7, 7, 2);
- INSERT INTO data0_t1 VALUES(2, 10, 10, 10, 2);
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data0_t1', 2);
- }
- {2500 4000 6000 8000 10000}
- {5000 10000}
-
- 3 {
- CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control);
- INSERT INTO data0_t1 VALUES(1, NULL, NULL, NULL, 1);
- INSERT INTO data0_t1 VALUES(2, NULL, NULL, 7, '..x');
- CREATE TABLE rbu_count(tbl, cnt);
- INSERT INTO rbu_count VALUES('data0_t1', 2);
- }
- {2500 4000 6000 8000 10000}
- {5000 10000}
- } {
-
- reset_db ; execsql $tbl
- do_test 5.$tn.$bReopen.$tn2.0 {
- execsql {
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(5, 5, 5);
- INSERT INTO t1 VALUES(10, 10, 10);
- }
- create_db_file rbu.db $rbusql
- } {}
-
- set R(nopk) $r1
- set R(vtab) $r2
- do_sp_test 5.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn)
- }
- }
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rburesume.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rburesume.test
deleted file mode 100644
index d03894e1353..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rburesume.test
+++ /dev/null
@@ -1,254 +0,0 @@
-# 2017 January 13
-#
-# 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 contains tests for resumption of RBU operations in the
-# case where the previous RBU process crashed.
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rburesume
-
-forcedelete test.db-shm test.db-oal
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE INDEX t1a ON t1(a);
- CREATE INDEX t1b ON t1(b);
- CREATE INDEX t1c ON t1(c);
- WITH s(i) AS (
- VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<50
- )
- INSERT INTO t1 SELECT randomblob(50), randomblob(75), randomblob(100) FROM s;
-}
-db_save_and_close
-
-do_test 1.1 {
- list [file exists test.db] \
- [file exists test.db-wal] \
- [file exists test.db-shm] \
- [file exists test.db-oal]
-} {1 0 0 0}
-
-# Each iteration of the following loop:
-#
-# 1. Restores the db to the state it was in following test case 1.0
-# 2. Opens an RBU vacuum and steps it $n times.
-# 3. Closes the RBU vacuum handled opened in (2).
-# 4. Opens a second RBU vacuum handle, resumes and completes the vacuum op.
-#
-# The loop runs until $n is large enough that step (2) vacuums the entire
-# database.
-#
-for {set n 1} {$n < 5000} {incr n} {
- db_restore
- forcedelete state.db
- sqlite3rbu_vacuum rbu test.db state.db
- for {set i 0} {$i<$n} {incr i} {
- set rc [rbu step]
- if {$rc == "SQLITE_DONE"} break
- }
- rbu close
- if {$rc == "SQLITE_DONE"} break
-
- do_test 1.2.$n.1 {
- sqlite3rbu_vacuum rbu test.db state.db
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
- } {SQLITE_DONE}
-
- do_test 1.2.$n.2 {
- sqlite3 db2 test.db
- db2 eval {
- SELECT count(*) FROM t1;
- PRAGMA integrity_check;
- }
- } {50 ok}
- db2 close
-}
-
-# Each iteration of this loop:
-#
-# 1. Restores the db to the state it was in following test case 1.0
-# 2. Opens an RBU vacuum and steps it $n times.
-# 3. Takes a copy of all database files and the state db.
-# 4. Opens a second RBU vacuum handle on the copy, resumes and completes the
-# vacuum op.
-#
-# The loop runs until $n is large enough that step (2) vacuums the entire
-# database.
-#
-for {set n 1} {$n < 5000} {incr n} {
- db_restore
- forcedelete state.db state.db-shm state.db-oal state.db-wal
- sqlite3rbu_vacuum rbu test.db state.db
- for {set i 0} {$i<$n} {incr i} {
- set rc [rbu step]
- if {$rc == "SQLITE_DONE"} break
- }
- if {$rc == "SQLITE_DONE"} {
- rbu close
- break
- }
-
- foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
- set f2 [string map [list test.db test.db2] $f]
- if {[file exists $f]} {
- forcecopy $f $f2
- } else {
- forcedelete $f2
- }
- }
- forcecopy state.db state.db2
- rbu close
-
- do_test 1.3.$n.1 {
- sqlite3rbu_vacuum rbu test.db2 state.db2
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
- } {SQLITE_DONE}
-
- do_test 1.3.$n.2 {
- sqlite3 db2 test.db2
- db2 eval {
- SELECT count(*) FROM t1;
- PRAGMA integrity_check;
- }
- } {50 ok}
- db2 close
-}
-
-# Each iteration of this loop:
-#
-# 1. Restores the db to the state it was in following test case 1.0
-# 2. Opens an RBU vacuum and steps it 10 times. Then closes it.
-# 2. Opens an RBU vacuum and steps it $n times.
-# 3. Takes a copy of all database files and the state db.
-# 4. Opens a second RBU vacuum handle on the copy, resumes and completes the
-# vacuum op.
-#
-# The loop runs until $n is large enough that step (3) vacuums the entire
-# database.
-#
-for {set n 1} {$n < 5000} {incr n} {
- db_restore
- forcedelete state.db state.db-shm state.db-oal state.db-wal
-
- sqlite3rbu_vacuum rbu test.db state.db
- for {set i 0} {$i<10} {incr i} {
- rbu step
- }
- rbu close
-
- sqlite3rbu_vacuum rbu test.db state.db
- for {set i 0} {$i<$n} {incr i} {
- set rc [rbu step]
- if {$rc == "SQLITE_DONE"} break
- }
- if {$rc == "SQLITE_DONE"} {
- rbu close
- break
- }
-
- foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
- set f2 [string map [list test.db test.db2] $f]
- if {[file exists $f]} {
- forcecopy $f $f2
- } else {
- forcedelete $f2
- }
- }
- forcecopy state.db state.db2
- rbu close
-
- do_test 1.4.$n.1 {
- sqlite3rbu_vacuum rbu test.db2 state.db2
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
- } {SQLITE_DONE}
-
- do_test 1.4.$n.2 {
- sqlite3 db2 test.db2
- db2 eval {
- SELECT count(*) FROM t1;
- PRAGMA integrity_check;
- }
- } {50 ok}
- db2 close
-}
-
-forcedelete rbu.db
-do_test 2.0 {
- sqlite3 db2 rbu.db
- db2 eval {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- WITH s(i) AS (
- VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10
- )
- INSERT INTO data_t1
- SELECT randomblob(50), randomblob(75), randomblob(100), 0 FROM s;
- }
- db2 close
-} {}
-
-# Each iteration of this loop:
-#
-# 1. Restores the db to the state it was in following test case 1.0
-# 2. Opens an RBU handle to apply the RBU update created in test case 2.0.
-# 3. Steps the RBU handle $n times.
-# 4. Takes a copy of all database files and the state db.
-# 5. Opens a second RBU handle on the copy, resumes and completes the
-# RBU op. Checks it worked as expected.
-#
-# The loop runs until $n is large enough that step (3) applies the entire
-# update.
-#
-for {set n 1} {$n < 5000} {incr n} {
- db_restore
- forcedelete state.db state.db-shm state.db-oal state.db-wal
- sqlite3rbu rbu test.db rbu.db state.db
-
- for {set i 0} {$i<$n} {incr i} {
- set rc [rbu step]
- if {$rc == "SQLITE_DONE"} break
- }
- if {$rc == "SQLITE_DONE"} {
- rbu close
- break
- }
-
- foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
- set f2 [string map [list test.db test.db2] $f]
- if {[file exists $f]} {
- forcecopy $f $f2
- } else {
- forcedelete $f2
- }
- }
- forcecopy state.db state.db2
- rbu close
-
- do_test 2.$n.1 {
- sqlite3rbu rbu test.db2 rbu.db state.db2
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
- } {SQLITE_DONE}
-
- do_test 2.$n.2 {
- sqlite3 db2 test.db2
- db2 eval {
- SELECT count(*) FROM t1;
- PRAGMA integrity_check;
- }
- } {60 ok}
- db2 close
-}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbusave.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbusave.test
deleted file mode 100644
index 1bb71a8e052..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbusave.test
+++ /dev/null
@@ -1,105 +0,0 @@
-# 2015 August 14
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set ::testprefix rbusave
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
- CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1 ON t1(b);
- CREATE INDEX i2 ON t2(c, b);
-
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
-
- INSERT INTO t2 VALUES(1, 1, 1);
- INSERT INTO t2 VALUES(2, 2, 2);
- INSERT INTO t2 VALUES(3, 3, 3);
-}
-
-do_test 1.1 {
- forcedelete test.db2
- sqlite3 db2 test.db2
- db2 eval {
- CREATE TABLE data_t1(a, b, c, rbu_control);
- INSERT INTO data_t1 VALUES(4, 4, 4, 0);
- INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
- INSERT INTO data_t1 VALUES(1, 'one', NULL, '.x.');
-
- CREATE TABLE data_t2(a, b, c, rbu_control);
- INSERT INTO data_t2 VALUES(4, 4, 4, 0);
- INSERT INTO data_t2 VALUES(2, NULL, NULL, 1);
- INSERT INTO data_t2 VALUES(1, 'one', NULL, '.x.');
- }
-} {}
-
-proc test_to_bak {} {
- foreach f {
- test.db test.db-wal test.db-oal test.db-journal
- test.db2 test.db2-wal test.db2-oal test.db2-journal
- } {
- set t [string map {test bak} $f]
- forcedelete $t
- if {[file exists $f]} { forcecopy $f $t }
- }
-}
-
-do_test 1.2 {
- test_to_bak
- sqlite3rbu rrr bak.db bak.db2
- set nStep 0
- while {[rrr step]=="SQLITE_OK"} {incr nStep}
- set res2 [rrr close]
-} {SQLITE_DONE}
-
-
-sqlite3rbu rbu test.db test.db2
-set res "SQLITE_OK"
-for {set i 1} {$res=="SQLITE_OK"} {incr i} {
- set res [rbu step]
-
- do_test 1.3.$i.1 {
- rbu savestate
- test_to_bak
- sqlite3rbu rrr bak.db bak.db2
- set nRem 0
- while {[rrr step]=="SQLITE_OK"} {incr nRem}
- set res2 [rrr close]
- } {SQLITE_DONE}
-
- do_test 1.3.$i.3 { expr $nRem+$i } [expr {$nStep + ($res=="SQLITE_DONE")}]
-
- do_test 1.3.$i.3 {
- sqlite3 bak bak.db
- bak eval {
- SELECT * FROM t1;
- SELECT * FROM t2;
- }
- } {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4}
-
- bak close
-}
-
-do_test 1.4 { rbu close } {SQLITE_DONE}
-
-do_execsql_test 1.5 {
- SELECT * FROM t1;
- SELECT * FROM t2;
-} {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbusplit.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbusplit.test
deleted file mode 100644
index 678f388dcff..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbusplit.test
+++ /dev/null
@@ -1,95 +0,0 @@
-# 2018 April 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.
-#
-#***********************************************************************
-#
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbusplit
-
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-
-autoinstall_test_functions
-
-proc build_db {db} {
- $db eval {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE TABLE t2(a PRIMARY KEY, b, c);
-
- CREATE INDEX t1c ON t1(c);
- }
-}
-
-proc build_rbu {filename} {
- forcedelete $filename
- sqlite3 dbRbu $filename
- dbRbu eval {
- CREATE TABLE data0_t1(a, b, c, rbu_control);
- CREATE TABLE data1_t1(a, b, c, rbu_control);
- CREATE TABLE data2_t1(a, b, c, rbu_control);
- CREATE TABLE data3_t1(a, b, c, rbu_control);
-
- CREATE TABLE data_t2(a, b, c, rbu_control);
-
- INSERT INTO data0_t1 VALUES(1, 1, 1, 0);
- INSERT INTO data0_t1 VALUES(2, 2, 2, 0);
- INSERT INTO data0_t1 VALUES(3, 3, 3, 0);
- INSERT INTO data0_t1 VALUES(4, 4, 4, 0);
- INSERT INTO data1_t1 VALUES(5, 5, 5, 0);
- INSERT INTO data1_t1 VALUES(6, 6, 6, 0);
- INSERT INTO data1_t1 VALUES(7, 7, 7, 0);
- INSERT INTO data1_t1 VALUES(8, 8, 8, 0);
- INSERT INTO data3_t1 VALUES(9, 9, 9, 0);
-
- INSERT INTO data_t2 VALUES(1, 1, 1, 0);
- INSERT INTO data_t2 VALUES(2, 2, 2, 0);
- INSERT INTO data_t2 VALUES(3, 3, 3, 0);
- INSERT INTO data_t2 VALUES(4, 4, 4, 0);
- INSERT INTO data_t2 VALUES(5, 5, 5, 0);
- INSERT INTO data_t2 VALUES(6, 6, 6, 0);
- INSERT INTO data_t2 VALUES(7, 7, 7, 0);
- INSERT INTO data_t2 VALUES(8, 8, 8, 0);
- INSERT INTO data_t2 VALUES(9, 9, 9, 0);
- }
-
- dbRbu close
-}
-
-foreach {tn cmd} {
- 1 run_rbu
- 2 step_rbu
-} {
- reset_db
- build_db db
- build_rbu testrbu.db
-
- do_test 1.$tn.1 {
- $cmd test.db testrbu.db
- } {SQLITE_DONE}
- do_execsql_test 1.$tn.1 {
- SELECT * FROM t1;
- } {
- 1 1 1 2 2 2 3 3 3 4 4 4
- 5 5 5 6 6 6 7 7 7 8 8 8
- 9 9 9
- }
- do_execsql_test 1.$tn.2 {
- SELECT * FROM t2;
- } {
- 1 1 1 2 2 2 3 3 3 4 4 4
- 5 5 5 6 6 6 7 7 7 8 8 8
- 9 9 9
- }
-}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbutemplimit.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbutemplimit.test
deleted file mode 100644
index 274f870b73e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbutemplimit.test
+++ /dev/null
@@ -1,129 +0,0 @@
-# 2014 August 30
-#
-# 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.
-#
-#***********************************************************************
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbutemplimit
-
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-
-proc setup_databases {} {
- forcedelete test.db2
- forcedelete test.db
- sqlite3 db test.db
- execsql {
- -- Create target database schema.
- --
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB(100), c BLOB(100));
- CREATE TABLE t2(a INTEGER PRIMARY KEY, b BLOB(100), c BLOB(100));
- CREATE INDEX i1b ON t1(b);
- CREATE INDEX i1c ON t1(c);
- CREATE INDEX i2b ON t2(b);
- CREATE INDEX i2c ON t2(c);
-
- -- Create a large RBU database.
- --
- ATTACH 'test.db2' AS rbu;
- CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
- WITH s(i) AS (
- VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10000
- )
- INSERT INTO data_t1 SELECT i, randomblob(100), randomblob(100), 0 FROM s;
- CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
- WITH s(i) AS (
- VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<15000
- )
- INSERT INTO data_t2 SELECT i, randomblob(100), randomblob(100), 0 FROM s;
- }
- db close
-}
-
-proc run_rbu_cachesize {target rbu cachesize temp_limit} {
- sqlite3rbu rbu $target $rbu
- rbu temp_size_limit $temp_limit
- sqlite3_exec_nr [rbu db 1] "PRAGMA cache_size = $cachesize"
- while 1 {
- set rc [rbu step]
- set ::A([rbu temp_size]) 1
- if {$rc!="SQLITE_OK"} break
- }
- list [catch {rbu close} msg] $msg
-}
-
-proc step_rbu_cachesize {target rbu stepsize cachesize temp_limit} {
- set res ""
- while 1 {
- sqlite3rbu rbu $target $rbu
- rbu temp_size_limit $temp_limit
- sqlite3_exec_nr [rbu db 1] "PRAGMA cache_size = $cachesize"
- for {set i 0} {$i < $stepsize} {incr i} {
- set rc [rbu step]
- set ::A([rbu temp_size]) 1
- if {$rc!="SQLITE_OK"} break
- }
- set res [list [catch {rbu close} msg] $msg]
- if {$res != "0 SQLITE_OK"} break
- }
- set res
-}
-
-do_test 1.1.0 { setup_databases } {}
-
-do_test 1.1.1 {
- unset -nocomplain ::A
- run_rbu_cachesize test.db test.db2 10 0
-} {0 SQLITE_DONE}
-
-do_test 1.1.2 { llength [array names ::A] } 3
-
-do_test 1.1.3 {
- foreach {a0 a1 a2} [lsort -integer [array names ::A]] {}
- list [expr $a0==0] \
- [expr $a1>1048576] [expr $a1<1200000] \
- [expr $a2>1500000] [expr $a2<1700000]
-} {1 1 1 1 1}
-
-do_test 1.2.1 {
- setup_databases
- run_rbu_cachesize test.db test.db2 10 1000000
-} {1 SQLITE_FULL}
-do_test 1.2.2 { info commands rbu } {}
-
-do_test 1.3.1 {
- setup_databases
- run_rbu_cachesize test.db test.db2 10 1300000
-} {1 SQLITE_FULL}
-do_test 1.3.2 { info commands rbu } {}
-
-do_test 1.4.1 {
- setup_databases
- run_rbu_cachesize test.db test.db2 10 1800000
-} {0 SQLITE_DONE}
-do_test 1.4.2 { info commands rbu } {}
-
-do_test 1.5.1 {
- setup_databases
- unset -nocomplain ::A
- step_rbu_cachesize test.db test.db2 1000 10 2400000
-} {0 SQLITE_DONE}
-do_test 1.5.2 { info commands rbu } {}
-
-do_test 1.6.1 {
- setup_databases
- unset -nocomplain ::A
- step_rbu_cachesize test.db test.db2 1000 10 1400000
-} {1 SQLITE_FULL}
-do_test 1.6.2 { info commands rbu } {}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuvacuum.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuvacuum.test
deleted file mode 100644
index dba0ef37e0d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuvacuum.test
+++ /dev/null
@@ -1,400 +0,0 @@
-# 2016 April 15
-#
-# 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 contains tests for the RBU module. More specifically, it
-# contains tests to ensure that the sqlite3rbu_vacuum() API works as
-# expected.
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-set ::testprefix rbuvacuum
-
-foreach step {0 1} {
-
- set ::testprefix rbuvacuum-step=$step
- reset_db
-
- # Simplest possible vacuum.
- do_execsql_test 1.0 {
- PRAGMA page_size = 1024;
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t1 VALUES(7, 8, 9);
- PRAGMA integrity_check;
- } {ok}
- do_rbu_vacuum_test 1.1 $step
-
- # A vacuum that actually reclaims space.
- do_execsql_test 1.2.1 {
- INSERT INTO t1 VALUES(8, randomblob(900), randomblob(900));
- INSERT INTO t1 VALUES(9, randomblob(900), randomblob(900));
- INSERT INTO t1 VALUES(10, randomblob(900), randomblob(900));
- INSERT INTO t1 VALUES(11, randomblob(900), randomblob(900));
- INSERT INTO t1 VALUES(12, randomblob(900), randomblob(900));
- PRAGMA page_count;
- } {12}
- do_execsql_test 1.2.2 {
- DELETE FROM t1 WHERE rowid BETWEEN 8 AND 11;
- PRAGMA page_count;
- } {12}
- do_rbu_vacuum_test 1.2.3 $step
- do_execsql_test 1.2.4 {
- PRAGMA page_count;
- } {3}
-
- # Add an index to the table.
- do_execsql_test 1.3.1 {
- CREATE INDEX t1b ON t1(b);
- INSERT INTO t1 VALUES(13, randomblob(900), randomblob(900));
- INSERT INTO t1 VALUES(14, randomblob(900), randomblob(900));
- INSERT INTO t1 VALUES(15, randomblob(900), randomblob(900));
- INSERT INTO t1 VALUES(16, randomblob(900), randomblob(900));
- PRAGMA page_count;
- } {18}
- do_execsql_test 1.3.2 {
- DELETE FROM t1 WHERE rowid BETWEEN 12 AND 15;
- PRAGMA page_count;
- } {18}
- do_rbu_vacuum_test 1.3.3 $step
- do_execsql_test 1.3.4 {
- PRAGMA page_count;
- } {5}
-
- # WITHOUT ROWID table.
- do_execsql_test 1.4.1 {
- CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
-
- INSERT INTO t2 VALUES(randomblob(900), 1, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 2, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 3, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 4, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 6, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 7, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 8, randomblob(900));
-
- DELETE FROM t2 WHERE b BETWEEN 2 AND 7;
- PRAGMA page_count;
- } {20}
- do_rbu_vacuum_test 1.4.2 $step
- do_execsql_test 1.4.3 {
- PRAGMA page_count;
- } {10}
-
- # WITHOUT ROWID table with an index.
- do_execsql_test 1.4.1 {
- CREATE INDEX t2c ON t2(c);
-
- INSERT INTO t2 VALUES(randomblob(900), 9, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 10, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 11, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 12, randomblob(900));
- INSERT INTO t2 VALUES(randomblob(900), 13, randomblob(900));
-
- DELETE FROM t2 WHERE b BETWEEN 8 AND 12;
- PRAGMA page_count;
- } {35}
- do_rbu_vacuum_test 1.4.2 $step
- do_execsql_test 1.4.3 {
- PRAGMA page_count;
- } {15}
- do_execsql_test 1.4.4 {
- VACUUM;
- PRAGMA page_count;
- } {15}
-
- do_execsql_test 1.5.1 {
- CREATE TABLE t3(a, b, c);
- INSERT INTO t3 VALUES('a', 'b', 'c');
- INSERT INTO t3 VALUES('d', 'e', 'f');
- INSERT INTO t3 VALUES('g', 'h', 'i');
- }
- do_rbu_vacuum_test 1.5.2 $step
- do_execsql_test 1.5.3 {
- SELECT * FROM t3
- } {a b c d e f g h i}
- do_execsql_test 1.5.4 {
- CREATE INDEX t3a ON t3(a);
- CREATE INDEX t3b ON t3(b);
- CREATE INDEX t3c ON t3(c);
- INSERT INTO t3 VALUES('j', 'k', 'l');
- DELETE FROM t3 WHERE a = 'g';
- }
- do_rbu_vacuum_test 1.5.5 $step
- do_execsql_test 1.5.6 {
- SELECT rowid, * FROM t3 ORDER BY b
- } {1 a b c 2 d e f 4 j k l}
-
- do_execsql_test 1.6.1 {
- CREATE TABLE t4(a PRIMARY KEY, b, c);
- INSERT INTO t4 VALUES('a', 'b', 'c');
- INSERT INTO t4 VALUES('d', 'e', 'f');
- INSERT INTO t4 VALUES('g', 'h', 'i');
- }
- do_rbu_vacuum_test 1.6.2 $step
- do_execsql_test 1.6.3 {
- SELECT * FROM t4
- } {a b c d e f g h i}
- do_execsql_test 1.6.4 {
- CREATE INDEX t4a ON t4(a);
- CREATE INDEX t4b ON t4(b);
- CREATE INDEX t4c ON t4(c);
-
- INSERT INTO t4 VALUES('j', 'k', 'l');
- DELETE FROM t4 WHERE a='g';
- }
- do_rbu_vacuum_test 1.6.5 $step
- do_execsql_test 1.6.6 {
- SELECT * FROM t4 ORDER BY b
- } {a b c d e f j k l}
-
- reset_db
- do_execsql_test 1.7.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
- INSERT INTO t1 VALUES(NULL, 'one');
- INSERT INTO t1 VALUES(NULL, 'two');
- DELETE FROM t1 WHERE a=2;
- INSERT INTO t1 VALUES(NULL, 'three');
- INSERT INTO t1 VALUES(NULL, 'four');
- DELETE FROM t1 WHERE a=4;
- INSERT INTO t1 VALUES(NULL, 'five');
- INSERT INTO t1 VALUES(NULL, 'six');
- DELETE FROM t1 WHERE a=6;
- SELECT * FROM t1;
- } {1 one 3 three 5 five}
- do_rbu_vacuum_test 1.7.1 $step
- do_execsql_test 1.7.2 {
- INSERT INTO t1 VALUES(NULL, 'seven');
- SELECT * FROM t1;
- } {1 one 3 three 5 five 7 seven}
-
- reset_db
- do_execsql_test 1.8.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
- CREATE INDEX i1 ON t1(b);
- INSERT INTO t1 VALUES(NULL, 'one');
- INSERT INTO t1 VALUES(NULL, 'two');
- INSERT INTO t1 VALUES(NULL, 'three');
- INSERT INTO t1 VALUES(NULL, 'four');
- INSERT INTO t1 VALUES(NULL, 'five');
- INSERT INTO t1 VALUES(NULL, 'six');
- ANALYZE;
- SELECT * FROM sqlite_stat1;
- } {t1 i1 {6 1}}
- do_rbu_vacuum_test 1.8.1 $step
- do_execsql_test 1.7.2 {
- SELECT * FROM sqlite_stat1;
- } {t1 i1 {6 1}}
-
- reset_db
- do_execsql_test 1.9.0 {
- PRAGMA page_size = 8192;
- PRAGMA auto_vacuum = 2;
- PRAGMA user_version = 412;
- PRAGMA application_id = 413;
-
- CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
- CREATE INDEX i1 ON t1(b);
- INSERT INTO t1 VALUES(NULL, 'one');
- INSERT INTO t1 VALUES(NULL, 'two');
- INSERT INTO t1 VALUES(NULL, 'three');
- INSERT INTO t1 VALUES(NULL, 'four');
- INSERT INTO t1 VALUES(NULL, 'five');
- INSERT INTO t1 VALUES(NULL, 'six');
-
- PRAGMA main.page_size;
- PRAGMA main.auto_vacuum;
- PRAGMA main.user_version;
- PRAGMA main.application_id;
- } {8192 2 412 413}
-
- do_rbu_vacuum_test 1.9.1 $step
- do_execsql_test 1.9.2 {
- PRAGMA main.page_size;
- PRAGMA main.auto_vacuum;
- PRAGMA main.user_version;
- PRAGMA main.application_id;
- } {8192 2 412 413}
-
- # Vacuum a database with a large sqlite_master table.
- #
- reset_db
- do_test 1.10.1 {
- for {set i 1} {$i < 50} {incr i} {
- execsql "PRAGMA page_size = 1024"
- execsql "CREATE TABLE t$i (a, b, c, PRIMARY KEY(a, b));"
- execsql "
- INSERT INTO t$i VALUES(1, 2, 3);
- INSERT INTO t$i VALUES(4, 5, 6);
- "
- }
- } {}
- do_rbu_vacuum_test 1.10.2 $step
-
- # Database with empty tables.
- #
- reset_db
- do_execsql_test 1.11.1 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
- INSERT INTO t4 VALUES(1, 2);
- }
- do_rbu_vacuum_test 1.11.2 $step
- do_execsql_test 1.11.3 {
- SELECT * FROM t1;
- SELECT * FROM t2;
- SELECT * FROM t3;
- SELECT * FROM t4;
- } {1 2}
- reset_db
- do_execsql_test 1.12.1 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
- CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 2);
- }
- do_rbu_vacuum_test 1.12.2 $step
- do_execsql_test 1.12.3 {
- SELECT * FROM t1;
- SELECT * FROM t2;
- SELECT * FROM t3;
- SELECT * FROM t4;
- } {1 2}
-}
-set ::testprefix rbuvacuum
-
-#-------------------------------------------------------------------------
-# Test some error cases:
-#
-# 2.1.* the db being vacuumed being in wal mode already.
-# 2.2.* database modified mid vacuum.
-#
-reset_db
-do_execsql_test 2.1.0 {
- CREATE TABLE t1(a, b);
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t1 VALUES(3, 4);
- INSERT INTO t1 VALUES(5, 6);
- INSERT INTO t1 VALUES(7, 8);
- PRAGMA journal_mode = wal;
- INSERT INTO t1 VALUES(9, 10);
-} wal
-do_test 2.1.1 {
- sqlite3rbu_vacuum rbu test.db state.db
- rbu step
-} {SQLITE_ERROR}
-do_test 2.1.2 {
- list [catch { rbu close } msg] $msg
-} {1 {SQLITE_ERROR - cannot vacuum wal mode database}}
-
-do_test 2.1.3 {
- sqlite3rbu_vacuum rbu test.db state.db
- rbu step
-} {SQLITE_ERROR}
-do_test 2.1.4 {
- list [catch { rbu close_no_error } msg] $msg
-} {1 SQLITE_ERROR}
-
-reset_db
-do_execsql_test 2.2.0 {
- CREATE TABLE tx(a PRIMARY KEY, b BLOB);
- INSERT INTO tx VALUES(1, randomblob(900));
- INSERT INTO tx SELECT a+1, randomblob(900) FROM tx;
- INSERT INTO tx SELECT a+2, randomblob(900) FROM tx;
- INSERT INTO tx SELECT a+4, randomblob(900) FROM tx;
- INSERT INTO tx SELECT a+8, randomblob(900) FROM tx;
-}
-db_save_and_close
-for {set i 1} 1 {incr i} {
- db_restore_and_reopen
-
- sqlite3rbu_vacuum rbu test.db state.db
- for {set step 0} {$step<$i} {incr step} { rbu step }
- rbu close
- if {[file exists test.db-wal]} break
-
- execsql { INSERT INTO tx VALUES(20, 20) }
-
- do_test 2.2.$i.1 {
- sqlite3rbu_vacuum rbu test.db state.db
- rbu step
- } {SQLITE_BUSY}
- do_test 2.2.$i.2 {
- list [catch { rbu close } msg] $msg
- } {1 {SQLITE_BUSY - database modified during rbu vacuum}}
-}
-
-#-------------------------------------------------------------------------
-# Test that a database that uses custom collation sequences can be RBU
-# vacuumed.
-#
-reset_db
-forcedelete state.db
-proc noop {args} {}
-proc length_cmp {x y} {
- set n1 [string length $x]
- set n2 [string length $y]
- return [expr $n1 - $n2]
-}
-sqlite3_create_collation_v2 db length length_cmp noop
-
-do_execsql_test 3.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 'i');
- INSERT INTO t1 VALUES(2, 'iiii');
- INSERT INTO t1 VALUES(3, 'ii');
- INSERT INTO t1 VALUES(4, 'iii');
- SELECT a FROM t1 ORDER BY b COLLATE length;
-} {1 3 4 2}
-do_execsql_test 3.1 {
- CREATE INDEX i1 ON t1(b COLLATE length);
-}
-
-do_test 3.2 {
- sqlite3rbu_vacuum rbu test.db state.db
- while {[rbu step]=="SQLITE_OK"} {}
- list [catch { rbu close } msg] $msg
-} {1 {SQLITE_ERROR - no such collation sequence: length}}
-
-do_test 3.3 {
- sqlite3rbu_vacuum rbu test.db state.db
- set db1 [rbu db 0]
- sqlite3_create_collation_v2 $db1 length length_cmp noop
- while {[rbu step]=="SQLITE_OK"} {}
- list [catch { rbu close } msg] $msg
-} {1 {SQLITE_ERROR - no such collation sequence: length}}
-
-do_test 3.4 {
- sqlite3rbu_vacuum rbu test.db state.db
- set db1 [rbu db 1]
- sqlite3_create_collation_v2 $db1 length length_cmp noop
- while {[rbu step]=="SQLITE_OK"} {}
- list [catch { rbu close } msg] $msg
-} {1 {SQLITE_ERROR - no such collation sequence: length}}
-
-do_test 3.5 {
- sqlite3rbu_vacuum rbu test.db state.db
- set db1 [rbu db 0]
- set db2 [rbu db 1]
-
- sqlite3_create_collation_v2 $db1 length length_cmp noop
- sqlite3_create_collation_v2 $db2 length length_cmp noop
-
- while {[rbu step]=="SQLITE_OK"} {}
- list [catch { rbu close } msg] $msg
-} {0 SQLITE_DONE}
-
-catch { db close }
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuvacuum2.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuvacuum2.test
deleted file mode 100644
index 0a1fe3da94a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/rbuvacuum2.test
+++ /dev/null
@@ -1,235 +0,0 @@
-# 2016 June 1
-#
-# 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 contains tests for the RBU module. More specifically, it
-# contains tests to ensure that the sqlite3rbu_vacuum() API works as
-# expected.
-#
-
-source [file join [file dirname [info script]] rbu_common.tcl]
-
-foreach step {0 1} {
- set ::testprefix rbuvacuum2-$step
-
- #-------------------------------------------------------------------------
- # Test that a database that contains fts3 tables can be vacuumed.
- #
- ifcapable fts3 {
- reset_db
- do_execsql_test 1.1 {
- CREATE VIRTUAL TABLE t1 USING fts3(z, y);
- INSERT INTO t1 VALUES('fix this issue', 'at some point');
- }
-
- do_rbu_vacuum_test 1.2 $step
-
- do_execsql_test 1.3 {
- SELECT * FROM t1;
- } {{fix this issue} {at some point}}
-
- do_execsql_test 1.4 {
- SELECT rowid FROM t1 WHERE t1 MATCH 'fix';
- } {1}
-
- do_execsql_test 1.5 {
- INSERT INTO t1 VALUES('a b c', 'd e f');
- INSERT INTO t1 VALUES('l h i', 'd e f');
- DELETE FROM t1 WHERE docid = 2;
- INSERT INTO t1 VALUES('a b c', 'x y z');
- }
-
- do_rbu_vacuum_test 1.6 $step
- do_execsql_test 1.7 {
- INSERT INTO t1(t1) VALUES('integrity-check');
- SELECT * FROM t1;
- } {
- {fix this issue} {at some point}
- {l h i} {d e f}
- {a b c} {x y z}
- }
- }
-
- #-------------------------------------------------------------------------
- # Test that a database that contains fts5 tables can be vacuumed.
- #
- ifcapable fts5 {
- reset_db
- do_execsql_test 2.1 {
- CREATE VIRTUAL TABLE t1 USING fts5(z, y);
- INSERT INTO t1 VALUES('fix this issue', 'at some point');
- }
-
- do_rbu_vacuum_test 2.2 $step
-
- do_execsql_test 2.3 {
- SELECT * FROM t1;
- } {{fix this issue} {at some point}}
-
- do_execsql_test 2.4 {
- SELECT rowid FROM t1 ('fix');
- } {1}
-
- do_execsql_test 2.5 {
- INSERT INTO t1 VALUES('a b c', 'd e f');
- INSERT INTO t1 VALUES('l h i', 'd e f');
- DELETE FROM t1 WHERE rowid = 2;
- INSERT INTO t1 VALUES('a b c', 'x y z');
- }
-
- do_rbu_vacuum_test 2.6 $step
- do_execsql_test 2.7 {
- INSERT INTO t1(t1) VALUES('integrity-check');
- SELECT * FROM t1;
- } {
- {fix this issue} {at some point}
- {l h i} {d e f}
- {a b c} {x y z}
- }
- }
-
- #-------------------------------------------------------------------------
- # Test that a database that contains an rtree table can be vacuumed.
- #
- ifcapable rtree {
- reset_db
- do_execsql_test 3.1 {
- CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
- INSERT INTO rt VALUES(1, 45, 55);
- INSERT INTO rt VALUES(2, 50, 60);
- INSERT INTO rt VALUES(3, 55, 65);
- }
-
- do_rbu_vacuum_test 3.2 $step
-
- do_execsql_test 3.3 {
- SELECT * FROM rt;
- } {1 45.0 55.0 2 50.0 60.0 3 55.0 65.0}
-
- do_execsql_test 3.4.1 {
- SELECT rowid FROM rt WHERE x2>51 AND x1 < 51
- } {1 2}
- do_execsql_test 3.4.2 {
- SELECT rowid FROM rt WHERE x2>59 AND x1 < 59
- } {2 3}
-
- do_rbu_vacuum_test 3.5 $step
-
- do_execsql_test 3.6.1 {
- SELECT rowid FROM rt WHERE x2>51 AND x1 < 51
- } {1 2}
- do_execsql_test 3.6.2 {
- SELECT rowid FROM rt WHERE x2>59 AND x1 < 59
- } {2 3}
- }
-
- ifcapable trigger {
- reset_db
- do_execsql_test 4.1 {
- CREATE TABLE t1(a, b, c);
- INSERT INTO t1 VALUES(1, 2, 3);
- CREATE VIEW v1 AS SELECT * FROM t1;
- CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END;
- }
-
- do_execsql_test 4.2 {
- SELECT * FROM sqlite_master;
- } {
- table t1 t1 2 {CREATE TABLE t1(a, b, c)}
- view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t1}
- trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
- }
-
- do_rbu_vacuum_test 4.3 $step
- do_execsql_test 4.4 {
- SELECT * FROM sqlite_master;
- } {
- table t1 t1 2 {CREATE TABLE t1(a, b, c)}
- view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t1}
- trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
- }
- }
-}
-
-#-------------------------------------------------------------------------
-# Test that passing a NULL value as the second argument to
-# sqlite3rbu_vacuum() causes it to:
-#
-# * Use <database>-vacuum as the state db, and
-# * Set the state db permissions to the same as those on the db file.
-#
-db close
-if {$::tcl_platform(platform)=="unix"} {
- forcedelete test.db
-
- sqlite3 db test.db
- do_execsql_test 5.0 {
- CREATE TABLE t1(a, b);
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t1 VALUES(3, 4);
- INSERT INTO t1 VALUES(5, 6);
- INSERT INTO t1 VALUES(7, 8);
- }
- db close
-
- foreach {tn perm} {
- 1 00755
- 2 00666
- 3 00644
- 4 00444
- } {
- forcedelete test.db-vacuum
-
- do_test 5.$tn.1 {
- file attributes test.db -permissions $perm
- sqlite3rbu_vacuum rbu test.db
- rbu step
- } {SQLITE_OK}
-
- do_test 5.$tn.2 { file exists test.db-vacuum } 1
- do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} $perm
- rbu close
- }
-}
-
-#-------------------------------------------------------------------------
-# Test the outcome of some other connection running a checkpoint while
-# the incremental checkpoint is suspended.
-#
-reset_db
-do_execsql_test 6.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
- CREATE INDEX i1b ON t1(b);
- CREATE INDEX i1c ON t1(c);
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
-}
-forcedelete test.db2
-
-do_test 6.1 {
- sqlite3rbu_vacuum rbu test.db test.db2
- while {[rbu state]!="checkpoint"} { rbu step }
- rbu close
-} {SQLITE_OK}
-
-do_execsql_test 6.2 {
- SELECT 1 FROM sqlite_master LIMIT 1;
- PRAGMA wal_checkpoint;
-} {1 0 4 4}
-
-do_test 6.3 {
- sqlite3rbu_vacuum rbu test.db test.db2
- while {[rbu step]!="SQLITE_DONE"} { rbu step }
- rbu close
- execsql { PRAGMA integrity_check }
-} {ok}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/sqlite3rbu.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/sqlite3rbu.c
deleted file mode 100644
index 065b13c7fa6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/sqlite3rbu.c
+++ /dev/null
@@ -1,4888 +0,0 @@
-/*
-** 2014 August 30
-**
-** 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.
-**
-*************************************************************************
-**
-**
-** OVERVIEW
-**
-** The RBU extension requires that the RBU update be packaged as an
-** SQLite database. The tables it expects to find are described in
-** sqlite3rbu.h. Essentially, for each table xyz in the target database
-** that the user wishes to write to, a corresponding data_xyz table is
-** created in the RBU database and populated with one row for each row to
-** update, insert or delete from the target table.
-**
-** The update proceeds in three stages:
-**
-** 1) The database is updated. The modified database pages are written
-** to a *-oal file. A *-oal file is just like a *-wal file, except
-** that it is named "<database>-oal" instead of "<database>-wal".
-** Because regular SQLite clients do not look for file named
-** "<database>-oal", they go on using the original database in
-** rollback mode while the *-oal file is being generated.
-**
-** During this stage RBU does not update the database by writing
-** directly to the target tables. Instead it creates "imposter"
-** tables using the SQLITE_TESTCTRL_IMPOSTER interface that it uses
-** to update each b-tree individually. All updates required by each
-** b-tree are completed before moving on to the next, and all
-** updates are done in sorted key order.
-**
-** 2) The "<database>-oal" file is moved to the equivalent "<database>-wal"
-** location using a call to rename(2). Before doing this the RBU
-** module takes an EXCLUSIVE lock on the database file, ensuring
-** that there are no other active readers.
-**
-** Once the EXCLUSIVE lock is released, any other database readers
-** detect the new *-wal file and read the database in wal mode. At
-** this point they see the new version of the database - including
-** the updates made as part of the RBU update.
-**
-** 3) The new *-wal file is checkpointed. This proceeds in the same way
-** as a regular database checkpoint, except that a single frame is
-** checkpointed each time sqlite3rbu_step() is called. If the RBU
-** handle is closed before the entire *-wal file is checkpointed,
-** the checkpoint progress is saved in the RBU database and the
-** checkpoint can be resumed by another RBU client at some point in
-** the future.
-**
-** POTENTIAL PROBLEMS
-**
-** The rename() call might not be portable. And RBU is not currently
-** syncing the directory after renaming the file.
-**
-** When state is saved, any commit to the *-oal file and the commit to
-** the RBU update database are not atomic. So if the power fails at the
-** wrong moment they might get out of sync. As the main database will be
-** committed before the RBU update database this will likely either just
-** pass unnoticed, or result in SQLITE_CONSTRAINT errors (due to UNIQUE
-** constraint violations).
-**
-** If some client does modify the target database mid RBU update, or some
-** other error occurs, the RBU extension will keep throwing errors. It's
-** not really clear how to get out of this state. The system could just
-** by delete the RBU update database and *-oal file and have the device
-** download the update again and start over.
-**
-** At present, for an UPDATE, both the new.* and old.* records are
-** collected in the rbu_xyz table. And for both UPDATEs and DELETEs all
-** fields are collected. This means we're probably writing a lot more
-** data to disk when saving the state of an ongoing update to the RBU
-** update database than is strictly necessary.
-**
-*/
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "sqlite3.h"
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU)
-#include "sqlite3rbu.h"
-
-#if defined(_WIN32_WCE)
-#include "windows.h"
-#endif
-
-/* Maximum number of prepared UPDATE statements held by this module */
-#define SQLITE_RBU_UPDATE_CACHESIZE 16
-
-/* Delta checksums disabled by default. Compile with -DRBU_ENABLE_DELTA_CKSUM
-** to enable checksum verification.
-*/
-#ifndef RBU_ENABLE_DELTA_CKSUM
-# define RBU_ENABLE_DELTA_CKSUM 0
-#endif
-
-/*
-** Swap two objects of type TYPE.
-*/
-#if !defined(SQLITE_AMALGAMATION)
-# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
-#endif
-
-/*
-** The rbu_state table is used to save the state of a partially applied
-** update so that it can be resumed later. The table consists of integer
-** keys mapped to values as follows:
-**
-** RBU_STATE_STAGE:
-** May be set to integer values 1, 2, 4 or 5. As follows:
-** 1: the *-rbu file is currently under construction.
-** 2: the *-rbu file has been constructed, but not yet moved
-** to the *-wal path.
-** 4: the checkpoint is underway.
-** 5: the rbu update has been checkpointed.
-**
-** RBU_STATE_TBL:
-** Only valid if STAGE==1. The target database name of the table
-** currently being written.
-**
-** RBU_STATE_IDX:
-** Only valid if STAGE==1. The target database name of the index
-** currently being written, or NULL if the main table is currently being
-** updated.
-**
-** RBU_STATE_ROW:
-** Only valid if STAGE==1. Number of rows already processed for the current
-** table/index.
-**
-** RBU_STATE_PROGRESS:
-** Trbul number of sqlite3rbu_step() calls made so far as part of this
-** rbu update.
-**
-** RBU_STATE_CKPT:
-** Valid if STAGE==4. The 64-bit checksum associated with the wal-index
-** header created by recovering the *-wal file. This is used to detect
-** cases when another client appends frames to the *-wal file in the
-** middle of an incremental checkpoint (an incremental checkpoint cannot
-** be continued if this happens).
-**
-** RBU_STATE_COOKIE:
-** Valid if STAGE==1. The current change-counter cookie value in the
-** target db file.
-**
-** RBU_STATE_OALSZ:
-** Valid if STAGE==1. The size in bytes of the *-oal file.
-**
-** RBU_STATE_DATATBL:
-** Only valid if STAGE==1. The RBU database name of the table
-** currently being read.
-*/
-#define RBU_STATE_STAGE 1
-#define RBU_STATE_TBL 2
-#define RBU_STATE_IDX 3
-#define RBU_STATE_ROW 4
-#define RBU_STATE_PROGRESS 5
-#define RBU_STATE_CKPT 6
-#define RBU_STATE_COOKIE 7
-#define RBU_STATE_OALSZ 8
-#define RBU_STATE_PHASEONESTEP 9
-#define RBU_STATE_DATATBL 10
-
-#define RBU_STAGE_OAL 1
-#define RBU_STAGE_MOVE 2
-#define RBU_STAGE_CAPTURE 3
-#define RBU_STAGE_CKPT 4
-#define RBU_STAGE_DONE 5
-
-
-#define RBU_CREATE_STATE \
- "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)"
-
-typedef struct RbuFrame RbuFrame;
-typedef struct RbuObjIter RbuObjIter;
-typedef struct RbuState RbuState;
-typedef struct rbu_vfs rbu_vfs;
-typedef struct rbu_file rbu_file;
-typedef struct RbuUpdateStmt RbuUpdateStmt;
-
-#if !defined(SQLITE_AMALGAMATION)
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-typedef sqlite3_int64 i64;
-#endif
-
-/*
-** These values must match the values defined in wal.c for the equivalent
-** locks. These are not magic numbers as they are part of the SQLite file
-** format.
-*/
-#define WAL_LOCK_WRITE 0
-#define WAL_LOCK_CKPT 1
-#define WAL_LOCK_READ0 3
-
-#define SQLITE_FCNTL_RBUCNT 5149216
-
-/*
-** A structure to store values read from the rbu_state table in memory.
-*/
-struct RbuState {
- int eStage;
- char *zTbl;
- char *zDataTbl;
- char *zIdx;
- i64 iWalCksum;
- int nRow;
- i64 nProgress;
- u32 iCookie;
- i64 iOalSz;
- i64 nPhaseOneStep;
-};
-
-struct RbuUpdateStmt {
- char *zMask; /* Copy of update mask used with pUpdate */
- sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */
- RbuUpdateStmt *pNext;
-};
-
-/*
-** An iterator of this type is used to iterate through all objects in
-** the target database that require updating. For each such table, the
-** iterator visits, in order:
-**
-** * the table itself,
-** * each index of the table (zero or more points to visit), and
-** * a special "cleanup table" state.
-**
-** abIndexed:
-** If the table has no indexes on it, abIndexed is set to NULL. Otherwise,
-** it points to an array of flags nTblCol elements in size. The flag is
-** set for each column that is either a part of the PK or a part of an
-** index. Or clear otherwise.
-**
-*/
-struct RbuObjIter {
- sqlite3_stmt *pTblIter; /* Iterate through tables */
- sqlite3_stmt *pIdxIter; /* Index iterator */
- int nTblCol; /* Size of azTblCol[] array */
- char **azTblCol; /* Array of unquoted target column names */
- char **azTblType; /* Array of target column types */
- int *aiSrcOrder; /* src table col -> target table col */
- u8 *abTblPk; /* Array of flags, set on target PK columns */
- u8 *abNotNull; /* Array of flags, set on NOT NULL columns */
- u8 *abIndexed; /* Array of flags, set on indexed & PK cols */
- int eType; /* Table type - an RBU_PK_XXX value */
-
- /* Output variables. zTbl==0 implies EOF. */
- int bCleanup; /* True in "cleanup" state */
- const char *zTbl; /* Name of target db table */
- const char *zDataTbl; /* Name of rbu db table (or null) */
- const char *zIdx; /* Name of target db index (or null) */
- int iTnum; /* Root page of current object */
- int iPkTnum; /* If eType==EXTERNAL, root of PK index */
- int bUnique; /* Current index is unique */
- int nIndex; /* Number of aux. indexes on table zTbl */
-
- /* Statements created by rbuObjIterPrepareAll() */
- int nCol; /* Number of columns in current object */
- sqlite3_stmt *pSelect; /* Source data */
- sqlite3_stmt *pInsert; /* Statement for INSERT operations */
- sqlite3_stmt *pDelete; /* Statement for DELETE ops */
- sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */
-
- /* Last UPDATE used (for PK b-tree updates only), or NULL. */
- RbuUpdateStmt *pRbuUpdate;
-};
-
-/*
-** Values for RbuObjIter.eType
-**
-** 0: Table does not exist (error)
-** 1: Table has an implicit rowid.
-** 2: Table has an explicit IPK column.
-** 3: Table has an external PK index.
-** 4: Table is WITHOUT ROWID.
-** 5: Table is a virtual table.
-*/
-#define RBU_PK_NOTABLE 0
-#define RBU_PK_NONE 1
-#define RBU_PK_IPK 2
-#define RBU_PK_EXTERNAL 3
-#define RBU_PK_WITHOUT_ROWID 4
-#define RBU_PK_VTAB 5
-
-
-/*
-** Within the RBU_STAGE_OAL stage, each call to sqlite3rbu_step() performs
-** one of the following operations.
-*/
-#define RBU_INSERT 1 /* Insert on a main table b-tree */
-#define RBU_DELETE 2 /* Delete a row from a main table b-tree */
-#define RBU_REPLACE 3 /* Delete and then insert a row */
-#define RBU_IDX_DELETE 4 /* Delete a row from an aux. index b-tree */
-#define RBU_IDX_INSERT 5 /* Insert on an aux. index b-tree */
-
-#define RBU_UPDATE 6 /* Update a row in a main table b-tree */
-
-/*
-** A single step of an incremental checkpoint - frame iWalFrame of the wal
-** file should be copied to page iDbPage of the database file.
-*/
-struct RbuFrame {
- u32 iDbPage;
- u32 iWalFrame;
-};
-
-/*
-** RBU handle.
-**
-** nPhaseOneStep:
-** If the RBU database contains an rbu_count table, this value is set to
-** a running estimate of the number of b-tree operations required to
-** finish populating the *-oal file. This allows the sqlite3_bp_progress()
-** API to calculate the permyriadage progress of populating the *-oal file
-** using the formula:
-**
-** permyriadage = (10000 * nProgress) / nPhaseOneStep
-**
-** nPhaseOneStep is initialized to the sum of:
-**
-** nRow * (nIndex + 1)
-**
-** for all source tables in the RBU database, where nRow is the number
-** of rows in the source table and nIndex the number of indexes on the
-** corresponding target database table.
-**
-** This estimate is accurate if the RBU update consists entirely of
-** INSERT operations. However, it is inaccurate if:
-**
-** * the RBU update contains any UPDATE operations. If the PK specified
-** for an UPDATE operation does not exist in the target table, then
-** no b-tree operations are required on index b-trees. Or if the
-** specified PK does exist, then (nIndex*2) such operations are
-** required (one delete and one insert on each index b-tree).
-**
-** * the RBU update contains any DELETE operations for which the specified
-** PK does not exist. In this case no operations are required on index
-** b-trees.
-**
-** * the RBU update contains REPLACE operations. These are similar to
-** UPDATE operations.
-**
-** nPhaseOneStep is updated to account for the conditions above during the
-** first pass of each source table. The updated nPhaseOneStep value is
-** stored in the rbu_state table if the RBU update is suspended.
-*/
-struct sqlite3rbu {
- int eStage; /* Value of RBU_STATE_STAGE field */
- sqlite3 *dbMain; /* target database handle */
- sqlite3 *dbRbu; /* rbu database handle */
- char *zTarget; /* Path to target db */
- char *zRbu; /* Path to rbu db */
- char *zState; /* Path to state db (or NULL if zRbu) */
- char zStateDb[5]; /* Db name for state ("stat" or "main") */
- int rc; /* Value returned by last rbu_step() call */
- char *zErrmsg; /* Error message if rc!=SQLITE_OK */
- int nStep; /* Rows processed for current object */
- int nProgress; /* Rows processed for all objects */
- RbuObjIter objiter; /* Iterator for skipping through tbl/idx */
- const char *zVfsName; /* Name of automatically created rbu vfs */
- rbu_file *pTargetFd; /* File handle open on target db */
- int nPagePerSector; /* Pages per sector for pTargetFd */
- i64 iOalSz;
- i64 nPhaseOneStep;
-
- /* The following state variables are used as part of the incremental
- ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding
- ** function rbuSetupCheckpoint() for details. */
- u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */
- u32 mLock;
- int nFrame; /* Entries in aFrame[] array */
- int nFrameAlloc; /* Allocated size of aFrame[] array */
- RbuFrame *aFrame;
- int pgsz;
- u8 *aBuf;
- i64 iWalCksum;
- i64 szTemp; /* Current size of all temp files in use */
- i64 szTempLimit; /* Total size limit for temp files */
-
- /* Used in RBU vacuum mode only */
- int nRbu; /* Number of RBU VFS in the stack */
- rbu_file *pRbuFd; /* Fd for main db of dbRbu */
-};
-
-/*
-** An rbu VFS is implemented using an instance of this structure.
-**
-** Variable pRbu is only non-NULL for automatically created RBU VFS objects.
-** It is NULL for RBU VFS objects created explicitly using
-** sqlite3rbu_create_vfs(). It is used to track the total amount of temp
-** space used by the RBU handle.
-*/
-struct rbu_vfs {
- sqlite3_vfs base; /* rbu VFS shim methods */
- sqlite3_vfs *pRealVfs; /* Underlying VFS */
- sqlite3_mutex *mutex; /* Mutex to protect pMain */
- sqlite3rbu *pRbu; /* Owner RBU object */
- rbu_file *pMain; /* Linked list of main db files */
-};
-
-/*
-** Each file opened by an rbu VFS is represented by an instance of
-** the following structure.
-**
-** If this is a temporary file (pRbu!=0 && flags&DELETE_ON_CLOSE), variable
-** "sz" is set to the current size of the database file.
-*/
-struct rbu_file {
- sqlite3_file base; /* sqlite3_file methods */
- sqlite3_file *pReal; /* Underlying file handle */
- rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */
- sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */
- i64 sz; /* Size of file in bytes (temp only) */
-
- int openFlags; /* Flags this file was opened with */
- u32 iCookie; /* Cookie value for main db files */
- u8 iWriteVer; /* "write-version" value for main db files */
- u8 bNolock; /* True to fail EXCLUSIVE locks */
-
- int nShm; /* Number of entries in apShm[] array */
- char **apShm; /* Array of mmap'd *-shm regions */
- char *zDel; /* Delete this when closing file */
-
- const char *zWal; /* Wal filename for this main db file */
- rbu_file *pWalFd; /* Wal file descriptor for this main db */
- rbu_file *pMainNext; /* Next MAIN_DB file */
-};
-
-/*
-** True for an RBU vacuum handle, or false otherwise.
-*/
-#define rbuIsVacuum(p) ((p)->zTarget==0)
-
-
-/*************************************************************************
-** The following three functions, found below:
-**
-** rbuDeltaGetInt()
-** rbuDeltaChecksum()
-** rbuDeltaApply()
-**
-** are lifted from the fossil source code (http://fossil-scm.org). They
-** are used to implement the scalar SQL function rbu_fossil_delta().
-*/
-
-/*
-** Read bytes from *pz and convert them into a positive integer. When
-** finished, leave *pz pointing to the first character past the end of
-** the integer. The *pLen parameter holds the length of the string
-** in *pz and is decremented once for each character in the integer.
-*/
-static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
- static const signed char zValue[] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
- -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36,
- -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,
- };
- unsigned int v = 0;
- int c;
- unsigned char *z = (unsigned char*)*pz;
- unsigned char *zStart = z;
- while( (c = zValue[0x7f&*(z++)])>=0 ){
- v = (v<<6) + c;
- }
- z--;
- *pLen -= z - zStart;
- *pz = (char*)z;
- return v;
-}
-
-#if RBU_ENABLE_DELTA_CKSUM
-/*
-** Compute a 32-bit checksum on the N-byte buffer. Return the result.
-*/
-static unsigned int rbuDeltaChecksum(const char *zIn, size_t N){
- const unsigned char *z = (const unsigned char *)zIn;
- unsigned sum0 = 0;
- unsigned sum1 = 0;
- unsigned sum2 = 0;
- unsigned sum3 = 0;
- while(N >= 16){
- sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]);
- sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]);
- sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]);
- sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]);
- z += 16;
- N -= 16;
- }
- while(N >= 4){
- sum0 += z[0];
- sum1 += z[1];
- sum2 += z[2];
- sum3 += z[3];
- z += 4;
- N -= 4;
- }
- sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
- switch(N){
- case 3: sum3 += (z[2] << 8);
- case 2: sum3 += (z[1] << 16);
- case 1: sum3 += (z[0] << 24);
- default: ;
- }
- return sum3;
-}
-#endif
-
-/*
-** Apply a delta.
-**
-** The output buffer should be big enough to hold the whole output
-** file and a NUL terminator at the end. The delta_output_size()
-** routine will determine this size for you.
-**
-** The delta string should be null-terminated. But the delta string
-** may contain embedded NUL characters (if the input and output are
-** binary files) so we also have to pass in the length of the delta in
-** the lenDelta parameter.
-**
-** This function returns the size of the output file in bytes (excluding
-** the final NUL terminator character). Except, if the delta string is
-** malformed or intended for use with a source file other than zSrc,
-** then this routine returns -1.
-**
-** Refer to the delta_create() documentation above for a description
-** of the delta file format.
-*/
-static int rbuDeltaApply(
- const char *zSrc, /* The source or pattern file */
- int lenSrc, /* Length of the source file */
- const char *zDelta, /* Delta to apply to the pattern */
- int lenDelta, /* Length of the delta */
- char *zOut /* Write the output into this preallocated buffer */
-){
- unsigned int limit;
- unsigned int total = 0;
-#if RBU_ENABLE_DELTA_CKSUM
- char *zOrigOut = zOut;
-#endif
-
- limit = rbuDeltaGetInt(&zDelta, &lenDelta);
- if( *zDelta!='\n' ){
- /* ERROR: size integer not terminated by "\n" */
- return -1;
- }
- zDelta++; lenDelta--;
- while( *zDelta && lenDelta>0 ){
- unsigned int cnt, ofst;
- cnt = rbuDeltaGetInt(&zDelta, &lenDelta);
- switch( zDelta[0] ){
- case '@': {
- zDelta++; lenDelta--;
- ofst = rbuDeltaGetInt(&zDelta, &lenDelta);
- if( lenDelta>0 && zDelta[0]!=',' ){
- /* ERROR: copy command not terminated by ',' */
- return -1;
- }
- zDelta++; lenDelta--;
- total += cnt;
- if( total>limit ){
- /* ERROR: copy exceeds output file size */
- return -1;
- }
- if( (int)(ofst+cnt) > lenSrc ){
- /* ERROR: copy extends past end of input */
- return -1;
- }
- memcpy(zOut, &zSrc[ofst], cnt);
- zOut += cnt;
- break;
- }
- case ':': {
- zDelta++; lenDelta--;
- total += cnt;
- if( total>limit ){
- /* ERROR: insert command gives an output larger than predicted */
- return -1;
- }
- if( (int)cnt>lenDelta ){
- /* ERROR: insert count exceeds size of delta */
- return -1;
- }
- memcpy(zOut, zDelta, cnt);
- zOut += cnt;
- zDelta += cnt;
- lenDelta -= cnt;
- break;
- }
- case ';': {
- zDelta++; lenDelta--;
- zOut[0] = 0;
-#if RBU_ENABLE_DELTA_CKSUM
- if( cnt!=rbuDeltaChecksum(zOrigOut, total) ){
- /* ERROR: bad checksum */
- return -1;
- }
-#endif
- if( total!=limit ){
- /* ERROR: generated size does not match predicted size */
- return -1;
- }
- return total;
- }
- default: {
- /* ERROR: unknown delta operator */
- return -1;
- }
- }
- }
- /* ERROR: unterminated delta */
- return -1;
-}
-
-static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){
- int size;
- size = rbuDeltaGetInt(&zDelta, &lenDelta);
- if( *zDelta!='\n' ){
- /* ERROR: size integer not terminated by "\n" */
- return -1;
- }
- return size;
-}
-
-/*
-** End of code taken from fossil.
-*************************************************************************/
-
-/*
-** Implementation of SQL scalar function rbu_fossil_delta().
-**
-** This function applies a fossil delta patch to a blob. Exactly two
-** arguments must be passed to this function. The first is the blob to
-** patch and the second the patch to apply. If no error occurs, this
-** function returns the patched blob.
-*/
-static void rbuFossilDeltaFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *aDelta;
- int nDelta;
- const char *aOrig;
- int nOrig;
-
- int nOut;
- int nOut2;
- char *aOut;
-
- assert( argc==2 );
-
- nOrig = sqlite3_value_bytes(argv[0]);
- aOrig = (const char*)sqlite3_value_blob(argv[0]);
- nDelta = sqlite3_value_bytes(argv[1]);
- aDelta = (const char*)sqlite3_value_blob(argv[1]);
-
- /* Figure out the size of the output */
- nOut = rbuDeltaOutputSize(aDelta, nDelta);
- if( nOut<0 ){
- sqlite3_result_error(context, "corrupt fossil delta", -1);
- return;
- }
-
- aOut = sqlite3_malloc(nOut+1);
- if( aOut==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut);
- if( nOut2!=nOut ){
- sqlite3_result_error(context, "corrupt fossil delta", -1);
- }else{
- sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
- }
- }
-}
-
-
-/*
-** Prepare the SQL statement in buffer zSql against database handle db.
-** If successful, set *ppStmt to point to the new statement and return
-** SQLITE_OK.
-**
-** Otherwise, if an error does occur, set *ppStmt to NULL and return
-** an SQLite error code. Additionally, set output variable *pzErrmsg to
-** point to a buffer containing an error message. It is the responsibility
-** of the caller to (eventually) free this buffer using sqlite3_free().
-*/
-static int prepareAndCollectError(
- sqlite3 *db,
- sqlite3_stmt **ppStmt,
- char **pzErrmsg,
- const char *zSql
-){
- int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
- if( rc!=SQLITE_OK ){
- *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- *ppStmt = 0;
- }
- return rc;
-}
-
-/*
-** Reset the SQL statement passed as the first argument. Return a copy
-** of the value returned by sqlite3_reset().
-**
-** If an error has occurred, then set *pzErrmsg to point to a buffer
-** containing an error message. It is the responsibility of the caller
-** to eventually free this buffer using sqlite3_free().
-*/
-static int resetAndCollectError(sqlite3_stmt *pStmt, char **pzErrmsg){
- int rc = sqlite3_reset(pStmt);
- if( rc!=SQLITE_OK ){
- *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt)));
- }
- return rc;
-}
-
-/*
-** Unless it is NULL, argument zSql points to a buffer allocated using
-** sqlite3_malloc containing an SQL statement. This function prepares the SQL
-** statement against database db and frees the buffer. If statement
-** compilation is successful, *ppStmt is set to point to the new statement
-** handle and SQLITE_OK is returned.
-**
-** Otherwise, if an error occurs, *ppStmt is set to NULL and an error code
-** returned. In this case, *pzErrmsg may also be set to point to an error
-** message. It is the responsibility of the caller to free this error message
-** buffer using sqlite3_free().
-**
-** If argument zSql is NULL, this function assumes that an OOM has occurred.
-** In this case SQLITE_NOMEM is returned and *ppStmt set to NULL.
-*/
-static int prepareFreeAndCollectError(
- sqlite3 *db,
- sqlite3_stmt **ppStmt,
- char **pzErrmsg,
- char *zSql
-){
- int rc;
- assert( *pzErrmsg==0 );
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- *ppStmt = 0;
- }else{
- rc = prepareAndCollectError(db, ppStmt, pzErrmsg, zSql);
- sqlite3_free(zSql);
- }
- return rc;
-}
-
-/*
-** Free the RbuObjIter.azTblCol[] and RbuObjIter.abTblPk[] arrays allocated
-** by an earlier call to rbuObjIterCacheTableInfo().
-*/
-static void rbuObjIterFreeCols(RbuObjIter *pIter){
- int i;
- for(i=0; i<pIter->nTblCol; i++){
- sqlite3_free(pIter->azTblCol[i]);
- sqlite3_free(pIter->azTblType[i]);
- }
- sqlite3_free(pIter->azTblCol);
- pIter->azTblCol = 0;
- pIter->azTblType = 0;
- pIter->aiSrcOrder = 0;
- pIter->abTblPk = 0;
- pIter->abNotNull = 0;
- pIter->nTblCol = 0;
- pIter->eType = 0; /* Invalid value */
-}
-
-/*
-** Finalize all statements and free all allocations that are specific to
-** the current object (table/index pair).
-*/
-static void rbuObjIterClearStatements(RbuObjIter *pIter){
- RbuUpdateStmt *pUp;
-
- sqlite3_finalize(pIter->pSelect);
- sqlite3_finalize(pIter->pInsert);
- sqlite3_finalize(pIter->pDelete);
- sqlite3_finalize(pIter->pTmpInsert);
- pUp = pIter->pRbuUpdate;
- while( pUp ){
- RbuUpdateStmt *pTmp = pUp->pNext;
- sqlite3_finalize(pUp->pUpdate);
- sqlite3_free(pUp);
- pUp = pTmp;
- }
-
- pIter->pSelect = 0;
- pIter->pInsert = 0;
- pIter->pDelete = 0;
- pIter->pRbuUpdate = 0;
- pIter->pTmpInsert = 0;
- pIter->nCol = 0;
-}
-
-/*
-** Clean up any resources allocated as part of the iterator object passed
-** as the only argument.
-*/
-static void rbuObjIterFinalize(RbuObjIter *pIter){
- rbuObjIterClearStatements(pIter);
- sqlite3_finalize(pIter->pTblIter);
- sqlite3_finalize(pIter->pIdxIter);
- rbuObjIterFreeCols(pIter);
- memset(pIter, 0, sizeof(RbuObjIter));
-}
-
-/*
-** Advance the iterator to the next position.
-**
-** If no error occurs, SQLITE_OK is returned and the iterator is left
-** pointing to the next entry. Otherwise, an error code and message is
-** left in the RBU handle passed as the first argument. A copy of the
-** error code is returned.
-*/
-static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){
- int rc = p->rc;
- if( rc==SQLITE_OK ){
-
- /* Free any SQLite statements used while processing the previous object */
- rbuObjIterClearStatements(pIter);
- if( pIter->zIdx==0 ){
- rc = sqlite3_exec(p->dbMain,
- "DROP TRIGGER IF EXISTS temp.rbu_insert_tr;"
- "DROP TRIGGER IF EXISTS temp.rbu_update1_tr;"
- "DROP TRIGGER IF EXISTS temp.rbu_update2_tr;"
- "DROP TRIGGER IF EXISTS temp.rbu_delete_tr;"
- , 0, 0, &p->zErrmsg
- );
- }
-
- if( rc==SQLITE_OK ){
- if( pIter->bCleanup ){
- rbuObjIterFreeCols(pIter);
- pIter->bCleanup = 0;
- rc = sqlite3_step(pIter->pTblIter);
- if( rc!=SQLITE_ROW ){
- rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg);
- pIter->zTbl = 0;
- }else{
- pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0);
- pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1);
- rc = (pIter->zDataTbl && pIter->zTbl) ? SQLITE_OK : SQLITE_NOMEM;
- }
- }else{
- if( pIter->zIdx==0 ){
- sqlite3_stmt *pIdx = pIter->pIdxIter;
- rc = sqlite3_bind_text(pIdx, 1, pIter->zTbl, -1, SQLITE_STATIC);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_step(pIter->pIdxIter);
- if( rc!=SQLITE_ROW ){
- rc = resetAndCollectError(pIter->pIdxIter, &p->zErrmsg);
- pIter->bCleanup = 1;
- pIter->zIdx = 0;
- }else{
- pIter->zIdx = (const char*)sqlite3_column_text(pIter->pIdxIter, 0);
- pIter->iTnum = sqlite3_column_int(pIter->pIdxIter, 1);
- pIter->bUnique = sqlite3_column_int(pIter->pIdxIter, 2);
- rc = pIter->zIdx ? SQLITE_OK : SQLITE_NOMEM;
- }
- }
- }
- }
- }
-
- if( rc!=SQLITE_OK ){
- rbuObjIterFinalize(pIter);
- p->rc = rc;
- }
- return rc;
-}
-
-
-/*
-** The implementation of the rbu_target_name() SQL function. This function
-** accepts one or two arguments. The first argument is the name of a table -
-** the name of a table in the RBU database. The second, if it is present, is 1
-** for a view or 0 for a table.
-**
-** For a non-vacuum RBU handle, if the table name matches the pattern:
-**
-** data[0-9]_<name>
-**
-** where <name> is any sequence of 1 or more characters, <name> is returned.
-** Otherwise, if the only argument does not match the above pattern, an SQL
-** NULL is returned.
-**
-** "data_t1" -> "t1"
-** "data0123_t2" -> "t2"
-** "dataAB_t3" -> NULL
-**
-** For an rbu vacuum handle, a copy of the first argument is returned if
-** the second argument is either missing or 0 (not a view).
-*/
-static void rbuTargetNameFunc(
- sqlite3_context *pCtx,
- int argc,
- sqlite3_value **argv
-){
- sqlite3rbu *p = sqlite3_user_data(pCtx);
- const char *zIn;
- assert( argc==1 || argc==2 );
-
- zIn = (const char*)sqlite3_value_text(argv[0]);
- if( zIn ){
- if( rbuIsVacuum(p) ){
- if( argc==1 || 0==sqlite3_value_int(argv[1]) ){
- sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC);
- }
- }else{
- if( strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){
- int i;
- for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++);
- if( zIn[i]=='_' && zIn[i+1] ){
- sqlite3_result_text(pCtx, &zIn[i+1], -1, SQLITE_STATIC);
- }
- }
- }
- }
-}
-
-/*
-** Initialize the iterator structure passed as the second argument.
-**
-** If no error occurs, SQLITE_OK is returned and the iterator is left
-** pointing to the first entry. Otherwise, an error code and message is
-** left in the RBU handle passed as the first argument. A copy of the
-** error code is returned.
-*/
-static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){
- int rc;
- memset(pIter, 0, sizeof(RbuObjIter));
-
- rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg,
- sqlite3_mprintf(
- "SELECT rbu_target_name(name, type='view') AS target, name "
- "FROM sqlite_master "
- "WHERE type IN ('table', 'view') AND target IS NOT NULL "
- " %s "
- "ORDER BY name"
- , rbuIsVacuum(p) ? "AND rootpage!=0 AND rootpage IS NOT NULL" : ""));
-
- if( rc==SQLITE_OK ){
- rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg,
- "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' "
- " FROM main.sqlite_master "
- " WHERE type='index' AND tbl_name = ?"
- );
- }
-
- pIter->bCleanup = 1;
- p->rc = rc;
- return rbuObjIterNext(p, pIter);
-}
-
-/*
-** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs,
-** an error code is stored in the RBU handle passed as the first argument.
-**
-** If an error has already occurred (p->rc is already set to something other
-** than SQLITE_OK), then this function returns NULL without modifying the
-** stored error code. In this case it still calls sqlite3_free() on any
-** printf() parameters associated with %z conversions.
-*/
-static char *rbuMPrintf(sqlite3rbu *p, const char *zFmt, ...){
- char *zSql = 0;
- va_list ap;
- va_start(ap, zFmt);
- zSql = sqlite3_vmprintf(zFmt, ap);
- if( p->rc==SQLITE_OK ){
- if( zSql==0 ) p->rc = SQLITE_NOMEM;
- }else{
- sqlite3_free(zSql);
- zSql = 0;
- }
- va_end(ap);
- return zSql;
-}
-
-/*
-** Argument zFmt is a sqlite3_mprintf() style format string. The trailing
-** arguments are the usual subsitution values. This function performs
-** the printf() style substitutions and executes the result as an SQL
-** statement on the RBU handles database.
-**
-** If an error occurs, an error code and error message is stored in the
-** RBU handle. If an error has already occurred when this function is
-** called, it is a no-op.
-*/
-static int rbuMPrintfExec(sqlite3rbu *p, sqlite3 *db, const char *zFmt, ...){
- va_list ap;
- char *zSql;
- va_start(ap, zFmt);
- zSql = sqlite3_vmprintf(zFmt, ap);
- if( p->rc==SQLITE_OK ){
- if( zSql==0 ){
- p->rc = SQLITE_NOMEM;
- }else{
- p->rc = sqlite3_exec(db, zSql, 0, 0, &p->zErrmsg);
- }
- }
- sqlite3_free(zSql);
- va_end(ap);
- return p->rc;
-}
-
-/*
-** Attempt to allocate and return a pointer to a zeroed block of nByte
-** bytes.
-**
-** If an error (i.e. an OOM condition) occurs, return NULL and leave an
-** error code in the rbu handle passed as the first argument. Or, if an
-** error has already occurred when this function is called, return NULL
-** immediately without attempting the allocation or modifying the stored
-** error code.
-*/
-static void *rbuMalloc(sqlite3rbu *p, int nByte){
- void *pRet = 0;
- if( p->rc==SQLITE_OK ){
- assert( nByte>0 );
- pRet = sqlite3_malloc64(nByte);
- if( pRet==0 ){
- p->rc = SQLITE_NOMEM;
- }else{
- memset(pRet, 0, nByte);
- }
- }
- return pRet;
-}
-
-
-/*
-** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that
-** there is room for at least nCol elements. If an OOM occurs, store an
-** error code in the RBU handle passed as the first argument.
-*/
-static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){
- int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol;
- char **azNew;
-
- azNew = (char**)rbuMalloc(p, nByte);
- if( azNew ){
- pIter->azTblCol = azNew;
- pIter->azTblType = &azNew[nCol];
- pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol];
- pIter->abTblPk = (u8*)&pIter->aiSrcOrder[nCol];
- pIter->abNotNull = (u8*)&pIter->abTblPk[nCol];
- pIter->abIndexed = (u8*)&pIter->abNotNull[nCol];
- }
-}
-
-/*
-** The first argument must be a nul-terminated string. This function
-** returns a copy of the string in memory obtained from sqlite3_malloc().
-** It is the responsibility of the caller to eventually free this memory
-** using sqlite3_free().
-**
-** If an OOM condition is encountered when attempting to allocate memory,
-** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise,
-** if the allocation succeeds, (*pRc) is left unchanged.
-*/
-static char *rbuStrndup(const char *zStr, int *pRc){
- char *zRet = 0;
-
- assert( *pRc==SQLITE_OK );
- if( zStr ){
- size_t nCopy = strlen(zStr) + 1;
- zRet = (char*)sqlite3_malloc64(nCopy);
- if( zRet ){
- memcpy(zRet, zStr, nCopy);
- }else{
- *pRc = SQLITE_NOMEM;
- }
- }
-
- return zRet;
-}
-
-/*
-** Finalize the statement passed as the second argument.
-**
-** If the sqlite3_finalize() call indicates that an error occurs, and the
-** rbu handle error code is not already set, set the error code and error
-** message accordingly.
-*/
-static void rbuFinalize(sqlite3rbu *p, sqlite3_stmt *pStmt){
- sqlite3 *db = sqlite3_db_handle(pStmt);
- int rc = sqlite3_finalize(pStmt);
- if( p->rc==SQLITE_OK && rc!=SQLITE_OK ){
- p->rc = rc;
- p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }
-}
-
-/* Determine the type of a table.
-**
-** peType is of type (int*), a pointer to an output parameter of type
-** (int). This call sets the output parameter as follows, depending
-** on the type of the table specified by parameters dbName and zTbl.
-**
-** RBU_PK_NOTABLE: No such table.
-** RBU_PK_NONE: Table has an implicit rowid.
-** RBU_PK_IPK: Table has an explicit IPK column.
-** RBU_PK_EXTERNAL: Table has an external PK index.
-** RBU_PK_WITHOUT_ROWID: Table is WITHOUT ROWID.
-** RBU_PK_VTAB: Table is a virtual table.
-**
-** Argument *piPk is also of type (int*), and also points to an output
-** parameter. Unless the table has an external primary key index
-** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or,
-** if the table does have an external primary key index, then *piPk
-** is set to the root page number of the primary key index before
-** returning.
-**
-** ALGORITHM:
-**
-** if( no entry exists in sqlite_master ){
-** return RBU_PK_NOTABLE
-** }else if( sql for the entry starts with "CREATE VIRTUAL" ){
-** return RBU_PK_VTAB
-** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){
-** if( the index that is the pk exists in sqlite_master ){
-** *piPK = rootpage of that index.
-** return RBU_PK_EXTERNAL
-** }else{
-** return RBU_PK_WITHOUT_ROWID
-** }
-** }else if( "PRAGMA table_info()" lists one or more "pk" columns ){
-** return RBU_PK_IPK
-** }else{
-** return RBU_PK_NONE
-** }
-*/
-static void rbuTableType(
- sqlite3rbu *p,
- const char *zTab,
- int *peType,
- int *piTnum,
- int *piPk
-){
- /*
- ** 0) SELECT count(*) FROM sqlite_master where name=%Q AND IsVirtual(%Q)
- ** 1) PRAGMA index_list = ?
- ** 2) SELECT count(*) FROM sqlite_master where name=%Q
- ** 3) PRAGMA table_info = ?
- */
- sqlite3_stmt *aStmt[4] = {0, 0, 0, 0};
-
- *peType = RBU_PK_NOTABLE;
- *piPk = 0;
-
- assert( p->rc==SQLITE_OK );
- p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg,
- sqlite3_mprintf(
- "SELECT (sql LIKE 'create virtual%%'), rootpage"
- " FROM sqlite_master"
- " WHERE name=%Q", zTab
- ));
- if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){
- /* Either an error, or no such table. */
- goto rbuTableType_end;
- }
- if( sqlite3_column_int(aStmt[0], 0) ){
- *peType = RBU_PK_VTAB; /* virtual table */
- goto rbuTableType_end;
- }
- *piTnum = sqlite3_column_int(aStmt[0], 1);
-
- p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[1], &p->zErrmsg,
- sqlite3_mprintf("PRAGMA index_list=%Q",zTab)
- );
- if( p->rc ) goto rbuTableType_end;
- while( sqlite3_step(aStmt[1])==SQLITE_ROW ){
- const u8 *zOrig = sqlite3_column_text(aStmt[1], 3);
- const u8 *zIdx = sqlite3_column_text(aStmt[1], 1);
- if( zOrig && zIdx && zOrig[0]=='p' ){
- p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg,
- sqlite3_mprintf(
- "SELECT rootpage FROM sqlite_master WHERE name = %Q", zIdx
- ));
- if( p->rc==SQLITE_OK ){
- if( sqlite3_step(aStmt[2])==SQLITE_ROW ){
- *piPk = sqlite3_column_int(aStmt[2], 0);
- *peType = RBU_PK_EXTERNAL;
- }else{
- *peType = RBU_PK_WITHOUT_ROWID;
- }
- }
- goto rbuTableType_end;
- }
- }
-
- p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[3], &p->zErrmsg,
- sqlite3_mprintf("PRAGMA table_info=%Q",zTab)
- );
- if( p->rc==SQLITE_OK ){
- while( sqlite3_step(aStmt[3])==SQLITE_ROW ){
- if( sqlite3_column_int(aStmt[3],5)>0 ){
- *peType = RBU_PK_IPK; /* explicit IPK column */
- goto rbuTableType_end;
- }
- }
- *peType = RBU_PK_NONE;
- }
-
-rbuTableType_end: {
- unsigned int i;
- for(i=0; i<sizeof(aStmt)/sizeof(aStmt[0]); i++){
- rbuFinalize(p, aStmt[i]);
- }
- }
-}
-
-/*
-** This is a helper function for rbuObjIterCacheTableInfo(). It populates
-** the pIter->abIndexed[] array.
-*/
-static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){
- sqlite3_stmt *pList = 0;
- int bIndex = 0;
-
- if( p->rc==SQLITE_OK ){
- memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol);
- p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl)
- );
- }
-
- pIter->nIndex = 0;
- while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){
- const char *zIdx = (const char*)sqlite3_column_text(pList, 1);
- sqlite3_stmt *pXInfo = 0;
- if( zIdx==0 ) break;
- p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx)
- );
- while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
- int iCid = sqlite3_column_int(pXInfo, 1);
- if( iCid>=0 ) pIter->abIndexed[iCid] = 1;
- }
- rbuFinalize(p, pXInfo);
- bIndex = 1;
- pIter->nIndex++;
- }
-
- if( pIter->eType==RBU_PK_WITHOUT_ROWID ){
- /* "PRAGMA index_list" includes the main PK b-tree */
- pIter->nIndex--;
- }
-
- rbuFinalize(p, pList);
- if( bIndex==0 ) pIter->abIndexed = 0;
-}
-
-
-/*
-** If they are not already populated, populate the pIter->azTblCol[],
-** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to
-** the table (not index) that the iterator currently points to.
-**
-** Return SQLITE_OK if successful, or an SQLite error code otherwise. If
-** an error does occur, an error code and error message are also left in
-** the RBU handle.
-*/
-static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){
- if( pIter->azTblCol==0 ){
- sqlite3_stmt *pStmt = 0;
- int nCol = 0;
- int i; /* for() loop iterator variable */
- int bRbuRowid = 0; /* If input table has column "rbu_rowid" */
- int iOrder = 0;
- int iTnum = 0;
-
- /* Figure out the type of table this step will deal with. */
- assert( pIter->eType==0 );
- rbuTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum);
- if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_NOTABLE ){
- p->rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl);
- }
- if( p->rc ) return p->rc;
- if( pIter->zIdx==0 ) pIter->iTnum = iTnum;
-
- assert( pIter->eType==RBU_PK_NONE || pIter->eType==RBU_PK_IPK
- || pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_WITHOUT_ROWID
- || pIter->eType==RBU_PK_VTAB
- );
-
- /* Populate the azTblCol[] and nTblCol variables based on the columns
- ** of the input table. Ignore any input table columns that begin with
- ** "rbu_". */
- p->rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg,
- sqlite3_mprintf("SELECT * FROM '%q'", pIter->zDataTbl)
- );
- if( p->rc==SQLITE_OK ){
- nCol = sqlite3_column_count(pStmt);
- rbuAllocateIterArrays(p, pIter, nCol);
- }
- for(i=0; p->rc==SQLITE_OK && i<nCol; i++){
- const char *zName = (const char*)sqlite3_column_name(pStmt, i);
- if( sqlite3_strnicmp("rbu_", zName, 4) ){
- char *zCopy = rbuStrndup(zName, &p->rc);
- pIter->aiSrcOrder[pIter->nTblCol] = pIter->nTblCol;
- pIter->azTblCol[pIter->nTblCol++] = zCopy;
- }
- else if( 0==sqlite3_stricmp("rbu_rowid", zName) ){
- bRbuRowid = 1;
- }
- }
- sqlite3_finalize(pStmt);
- pStmt = 0;
-
- if( p->rc==SQLITE_OK
- && rbuIsVacuum(p)==0
- && bRbuRowid!=(pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE)
- ){
- p->rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf(
- "table %q %s rbu_rowid column", pIter->zDataTbl,
- (bRbuRowid ? "may not have" : "requires")
- );
- }
-
- /* Check that all non-HIDDEN columns in the destination table are also
- ** present in the input table. Populate the abTblPk[], azTblType[] and
- ** aiTblOrder[] arrays at the same time. */
- if( p->rc==SQLITE_OK ){
- p->rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA table_info(%Q)", pIter->zTbl)
- );
- }
- while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
- if( zName==0 ) break; /* An OOM - finalize() below returns S_NOMEM */
- for(i=iOrder; i<pIter->nTblCol; i++){
- if( 0==strcmp(zName, pIter->azTblCol[i]) ) break;
- }
- if( i==pIter->nTblCol ){
- p->rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf("column missing from %q: %s",
- pIter->zDataTbl, zName
- );
- }else{
- int iPk = sqlite3_column_int(pStmt, 5);
- int bNotNull = sqlite3_column_int(pStmt, 3);
- const char *zType = (const char*)sqlite3_column_text(pStmt, 2);
-
- if( i!=iOrder ){
- SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]);
- SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]);
- }
-
- pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc);
- pIter->abTblPk[iOrder] = (iPk!=0);
- pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0);
- iOrder++;
- }
- }
-
- rbuFinalize(p, pStmt);
- rbuObjIterCacheIndexedCols(p, pIter);
- assert( pIter->eType!=RBU_PK_VTAB || pIter->abIndexed==0 );
- assert( pIter->eType!=RBU_PK_VTAB || pIter->nIndex==0 );
- }
-
- return p->rc;
-}
-
-/*
-** This function constructs and returns a pointer to a nul-terminated
-** string containing some SQL clause or list based on one or more of the
-** column names currently stored in the pIter->azTblCol[] array.
-*/
-static char *rbuObjIterGetCollist(
- sqlite3rbu *p, /* RBU object */
- RbuObjIter *pIter /* Object iterator for column names */
-){
- char *zList = 0;
- const char *zSep = "";
- int i;
- for(i=0; i<pIter->nTblCol; i++){
- const char *z = pIter->azTblCol[i];
- zList = rbuMPrintf(p, "%z%s\"%w\"", zList, zSep, z);
- zSep = ", ";
- }
- return zList;
-}
-
-/*
-** This function is used to create a SELECT list (the list of SQL
-** expressions that follows a SELECT keyword) for a SELECT statement
-** used to read from an data_xxx or rbu_tmp_xxx table while updating the
-** index object currently indicated by the iterator object passed as the
-** second argument. A "PRAGMA index_xinfo = <idxname>" statement is used
-** to obtain the required information.
-**
-** If the index is of the following form:
-**
-** CREATE INDEX i1 ON t1(c, b COLLATE nocase);
-**
-** and "t1" is a table with an explicit INTEGER PRIMARY KEY column
-** "ipk", the returned string is:
-**
-** "`c` COLLATE 'BINARY', `b` COLLATE 'NOCASE', `ipk` COLLATE 'BINARY'"
-**
-** As well as the returned string, three other malloc'd strings are
-** returned via output parameters. As follows:
-**
-** pzImposterCols: ...
-** pzImposterPk: ...
-** pzWhere: ...
-*/
-static char *rbuObjIterGetIndexCols(
- sqlite3rbu *p, /* RBU object */
- RbuObjIter *pIter, /* Object iterator for column names */
- char **pzImposterCols, /* OUT: Columns for imposter table */
- char **pzImposterPk, /* OUT: Imposter PK clause */
- char **pzWhere, /* OUT: WHERE clause */
- int *pnBind /* OUT: Trbul number of columns */
-){
- int rc = p->rc; /* Error code */
- int rc2; /* sqlite3_finalize() return code */
- char *zRet = 0; /* String to return */
- char *zImpCols = 0; /* String to return via *pzImposterCols */
- char *zImpPK = 0; /* String to return via *pzImposterPK */
- char *zWhere = 0; /* String to return via *pzWhere */
- int nBind = 0; /* Value to return via *pnBind */
- const char *zCom = ""; /* Set to ", " later on */
- const char *zAnd = ""; /* Set to " AND " later on */
- sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = ? */
-
- if( rc==SQLITE_OK ){
- assert( p->zErrmsg==0 );
- rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx)
- );
- }
-
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
- int iCid = sqlite3_column_int(pXInfo, 1);
- int bDesc = sqlite3_column_int(pXInfo, 3);
- const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
- const char *zCol;
- const char *zType;
-
- if( iCid<0 ){
- /* An integer primary key. If the table has an explicit IPK, use
- ** its name. Otherwise, use "rbu_rowid". */
- if( pIter->eType==RBU_PK_IPK ){
- int i;
- for(i=0; pIter->abTblPk[i]==0; i++);
- assert( i<pIter->nTblCol );
- zCol = pIter->azTblCol[i];
- }else if( rbuIsVacuum(p) ){
- zCol = "_rowid_";
- }else{
- zCol = "rbu_rowid";
- }
- zType = "INTEGER";
- }else{
- zCol = pIter->azTblCol[iCid];
- zType = pIter->azTblType[iCid];
- }
-
- zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate);
- if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){
- const char *zOrder = (bDesc ? " DESC" : "");
- zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s",
- zImpPK, zCom, nBind, zCol, zOrder
- );
- }
- zImpCols = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\" %s COLLATE %Q",
- zImpCols, zCom, nBind, zCol, zType, zCollate
- );
- zWhere = sqlite3_mprintf(
- "%z%s\"rbu_imp_%d%w\" IS ?", zWhere, zAnd, nBind, zCol
- );
- if( zRet==0 || zImpPK==0 || zImpCols==0 || zWhere==0 ) rc = SQLITE_NOMEM;
- zCom = ", ";
- zAnd = " AND ";
- nBind++;
- }
-
- rc2 = sqlite3_finalize(pXInfo);
- if( rc==SQLITE_OK ) rc = rc2;
-
- if( rc!=SQLITE_OK ){
- sqlite3_free(zRet);
- sqlite3_free(zImpCols);
- sqlite3_free(zImpPK);
- sqlite3_free(zWhere);
- zRet = 0;
- zImpCols = 0;
- zImpPK = 0;
- zWhere = 0;
- p->rc = rc;
- }
-
- *pzImposterCols = zImpCols;
- *pzImposterPk = zImpPK;
- *pzWhere = zWhere;
- *pnBind = nBind;
- return zRet;
-}
-
-/*
-** Assuming the current table columns are "a", "b" and "c", and the zObj
-** paramter is passed "old", return a string of the form:
-**
-** "old.a, old.b, old.b"
-**
-** With the column names escaped.
-**
-** For tables with implicit rowids - RBU_PK_EXTERNAL and RBU_PK_NONE, append
-** the text ", old._rowid_" to the returned value.
-*/
-static char *rbuObjIterGetOldlist(
- sqlite3rbu *p,
- RbuObjIter *pIter,
- const char *zObj
-){
- char *zList = 0;
- if( p->rc==SQLITE_OK && pIter->abIndexed ){
- const char *zS = "";
- int i;
- for(i=0; i<pIter->nTblCol; i++){
- if( pIter->abIndexed[i] ){
- const char *zCol = pIter->azTblCol[i];
- zList = sqlite3_mprintf("%z%s%s.\"%w\"", zList, zS, zObj, zCol);
- }else{
- zList = sqlite3_mprintf("%z%sNULL", zList, zS);
- }
- zS = ", ";
- if( zList==0 ){
- p->rc = SQLITE_NOMEM;
- break;
- }
- }
-
- /* For a table with implicit rowids, append "old._rowid_" to the list. */
- if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){
- zList = rbuMPrintf(p, "%z, %s._rowid_", zList, zObj);
- }
- }
- return zList;
-}
-
-/*
-** Return an expression that can be used in a WHERE clause to match the
-** primary key of the current table. For example, if the table is:
-**
-** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c));
-**
-** Return the string:
-**
-** "b = ?1 AND c = ?2"
-*/
-static char *rbuObjIterGetWhere(
- sqlite3rbu *p,
- RbuObjIter *pIter
-){
- char *zList = 0;
- if( pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE ){
- zList = rbuMPrintf(p, "_rowid_ = ?%d", pIter->nTblCol+1);
- }else if( pIter->eType==RBU_PK_EXTERNAL ){
- const char *zSep = "";
- int i;
- for(i=0; i<pIter->nTblCol; i++){
- if( pIter->abTblPk[i] ){
- zList = rbuMPrintf(p, "%z%sc%d=?%d", zList, zSep, i, i+1);
- zSep = " AND ";
- }
- }
- zList = rbuMPrintf(p,
- "_rowid_ = (SELECT id FROM rbu_imposter2 WHERE %z)", zList
- );
-
- }else{
- const char *zSep = "";
- int i;
- for(i=0; i<pIter->nTblCol; i++){
- if( pIter->abTblPk[i] ){
- const char *zCol = pIter->azTblCol[i];
- zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", zList, zSep, zCol, i+1);
- zSep = " AND ";
- }
- }
- }
- return zList;
-}
-
-/*
-** The SELECT statement iterating through the keys for the current object
-** (p->objiter.pSelect) currently points to a valid row. However, there
-** is something wrong with the rbu_control value in the rbu_control value
-** stored in the (p->nCol+1)'th column. Set the error code and error message
-** of the RBU handle to something reflecting this.
-*/
-static void rbuBadControlError(sqlite3rbu *p){
- p->rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf("invalid rbu_control value");
-}
-
-
-/*
-** Return a nul-terminated string containing the comma separated list of
-** assignments that should be included following the "SET" keyword of
-** an UPDATE statement used to update the table object that the iterator
-** passed as the second argument currently points to if the rbu_control
-** column of the data_xxx table entry is set to zMask.
-**
-** The memory for the returned string is obtained from sqlite3_malloc().
-** It is the responsibility of the caller to eventually free it using
-** sqlite3_free().
-**
-** If an OOM error is encountered when allocating space for the new
-** string, an error code is left in the rbu handle passed as the first
-** argument and NULL is returned. Or, if an error has already occurred
-** when this function is called, NULL is returned immediately, without
-** attempting the allocation or modifying the stored error code.
-*/
-static char *rbuObjIterGetSetlist(
- sqlite3rbu *p,
- RbuObjIter *pIter,
- const char *zMask
-){
- char *zList = 0;
- if( p->rc==SQLITE_OK ){
- int i;
-
- if( (int)strlen(zMask)!=pIter->nTblCol ){
- rbuBadControlError(p);
- }else{
- const char *zSep = "";
- for(i=0; i<pIter->nTblCol; i++){
- char c = zMask[pIter->aiSrcOrder[i]];
- if( c=='x' ){
- zList = rbuMPrintf(p, "%z%s\"%w\"=?%d",
- zList, zSep, pIter->azTblCol[i], i+1
- );
- zSep = ", ";
- }
- else if( c=='d' ){
- zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_delta(\"%w\", ?%d)",
- zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1
- );
- zSep = ", ";
- }
- else if( c=='f' ){
- zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_fossil_delta(\"%w\", ?%d)",
- zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1
- );
- zSep = ", ";
- }
- }
- }
- }
- return zList;
-}
-
-/*
-** Return a nul-terminated string consisting of nByte comma separated
-** "?" expressions. For example, if nByte is 3, return a pointer to
-** a buffer containing the string "?,?,?".
-**
-** The memory for the returned string is obtained from sqlite3_malloc().
-** It is the responsibility of the caller to eventually free it using
-** sqlite3_free().
-**
-** If an OOM error is encountered when allocating space for the new
-** string, an error code is left in the rbu handle passed as the first
-** argument and NULL is returned. Or, if an error has already occurred
-** when this function is called, NULL is returned immediately, without
-** attempting the allocation or modifying the stored error code.
-*/
-static char *rbuObjIterGetBindlist(sqlite3rbu *p, int nBind){
- char *zRet = 0;
- int nByte = nBind*2 + 1;
-
- zRet = (char*)rbuMalloc(p, nByte);
- if( zRet ){
- int i;
- for(i=0; i<nBind; i++){
- zRet[i*2] = '?';
- zRet[i*2+1] = (i+1==nBind) ? '\0' : ',';
- }
- }
- return zRet;
-}
-
-/*
-** The iterator currently points to a table (not index) of type
-** RBU_PK_WITHOUT_ROWID. This function creates the PRIMARY KEY
-** declaration for the corresponding imposter table. For example,
-** if the iterator points to a table created as:
-**
-** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, a DESC)) WITHOUT ROWID
-**
-** this function returns:
-**
-** PRIMARY KEY("b", "a" DESC)
-*/
-static char *rbuWithoutRowidPK(sqlite3rbu *p, RbuObjIter *pIter){
- char *z = 0;
- assert( pIter->zIdx==0 );
- if( p->rc==SQLITE_OK ){
- const char *zSep = "PRIMARY KEY(";
- sqlite3_stmt *pXList = 0; /* PRAGMA index_list = (pIter->zTbl) */
- sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = <pk-index> */
-
- p->rc = prepareFreeAndCollectError(p->dbMain, &pXList, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl)
- );
- while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXList) ){
- const char *zOrig = (const char*)sqlite3_column_text(pXList,3);
- if( zOrig && strcmp(zOrig, "pk")==0 ){
- const char *zIdx = (const char*)sqlite3_column_text(pXList,1);
- if( zIdx ){
- p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx)
- );
- }
- break;
- }
- }
- rbuFinalize(p, pXList);
-
- while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
- if( sqlite3_column_int(pXInfo, 5) ){
- /* int iCid = sqlite3_column_int(pXInfo, 0); */
- const char *zCol = (const char*)sqlite3_column_text(pXInfo, 2);
- const char *zDesc = sqlite3_column_int(pXInfo, 3) ? " DESC" : "";
- z = rbuMPrintf(p, "%z%s\"%w\"%s", z, zSep, zCol, zDesc);
- zSep = ", ";
- }
- }
- z = rbuMPrintf(p, "%z)", z);
- rbuFinalize(p, pXInfo);
- }
- return z;
-}
-
-/*
-** This function creates the second imposter table used when writing to
-** a table b-tree where the table has an external primary key. If the
-** iterator passed as the second argument does not currently point to
-** a table (not index) with an external primary key, this function is a
-** no-op.
-**
-** Assuming the iterator does point to a table with an external PK, this
-** function creates a WITHOUT ROWID imposter table named "rbu_imposter2"
-** used to access that PK index. For example, if the target table is
-** declared as follows:
-**
-** CREATE TABLE t1(a, b TEXT, c REAL, PRIMARY KEY(b, c));
-**
-** then the imposter table schema is:
-**
-** CREATE TABLE rbu_imposter2(c1 TEXT, c2 REAL, id INTEGER) WITHOUT ROWID;
-**
-*/
-static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){
- if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_EXTERNAL ){
- int tnum = pIter->iPkTnum; /* Root page of PK index */
- sqlite3_stmt *pQuery = 0; /* SELECT name ... WHERE rootpage = $tnum */
- const char *zIdx = 0; /* Name of PK index */
- sqlite3_stmt *pXInfo = 0; /* PRAGMA main.index_xinfo = $zIdx */
- const char *zComma = "";
- char *zCols = 0; /* Used to build up list of table cols */
- char *zPk = 0; /* Used to build up table PK declaration */
-
- /* Figure out the name of the primary key index for the current table.
- ** This is needed for the argument to "PRAGMA index_xinfo". Set
- ** zIdx to point to a nul-terminated string containing this name. */
- p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg,
- "SELECT name FROM sqlite_master WHERE rootpage = ?"
- );
- if( p->rc==SQLITE_OK ){
- sqlite3_bind_int(pQuery, 1, tnum);
- if( SQLITE_ROW==sqlite3_step(pQuery) ){
- zIdx = (const char*)sqlite3_column_text(pQuery, 0);
- }
- }
- if( zIdx ){
- p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx)
- );
- }
- rbuFinalize(p, pQuery);
-
- while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
- int bKey = sqlite3_column_int(pXInfo, 5);
- if( bKey ){
- int iCid = sqlite3_column_int(pXInfo, 1);
- int bDesc = sqlite3_column_int(pXInfo, 3);
- const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
- zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma,
- iCid, pIter->azTblType[iCid], zCollate
- );
- zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":"");
- zComma = ", ";
- }
- }
- zCols = rbuMPrintf(p, "%z, id INTEGER", zCols);
- rbuFinalize(p, pXInfo);
-
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum);
- rbuMPrintfExec(p, p->dbMain,
- "CREATE TABLE rbu_imposter2(%z, PRIMARY KEY(%z)) WITHOUT ROWID",
- zCols, zPk
- );
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0);
- }
-}
-
-/*
-** If an error has already occurred when this function is called, it
-** immediately returns zero (without doing any work). Or, if an error
-** occurs during the execution of this function, it sets the error code
-** in the sqlite3rbu object indicated by the first argument and returns
-** zero.
-**
-** The iterator passed as the second argument is guaranteed to point to
-** a table (not an index) when this function is called. This function
-** attempts to create any imposter table required to write to the main
-** table b-tree of the table before returning. Non-zero is returned if
-** an imposter table are created, or zero otherwise.
-**
-** An imposter table is required in all cases except RBU_PK_VTAB. Only
-** virtual tables are written to directly. The imposter table has the
-** same schema as the actual target table (less any UNIQUE constraints).
-** More precisely, the "same schema" means the same columns, types,
-** collation sequences. For tables that do not have an external PRIMARY
-** KEY, it also means the same PRIMARY KEY declaration.
-*/
-static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){
- if( p->rc==SQLITE_OK && pIter->eType!=RBU_PK_VTAB ){
- int tnum = pIter->iTnum;
- const char *zComma = "";
- char *zSql = 0;
- int iCol;
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1);
-
- for(iCol=0; p->rc==SQLITE_OK && iCol<pIter->nTblCol; iCol++){
- const char *zPk = "";
- const char *zCol = pIter->azTblCol[iCol];
- const char *zColl = 0;
-
- p->rc = sqlite3_table_column_metadata(
- p->dbMain, "main", pIter->zTbl, zCol, 0, &zColl, 0, 0, 0
- );
-
- if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){
- /* If the target table column is an "INTEGER PRIMARY KEY", add
- ** "PRIMARY KEY" to the imposter table column declaration. */
- zPk = "PRIMARY KEY ";
- }
- zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s",
- zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl,
- (pIter->abNotNull[iCol] ? " NOT NULL" : "")
- );
- zComma = ", ";
- }
-
- if( pIter->eType==RBU_PK_WITHOUT_ROWID ){
- char *zPk = rbuWithoutRowidPK(p, pIter);
- if( zPk ){
- zSql = rbuMPrintf(p, "%z, %z", zSql, zPk);
- }
- }
-
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum);
- rbuMPrintfExec(p, p->dbMain, "CREATE TABLE \"rbu_imp_%w\"(%z)%s",
- pIter->zTbl, zSql,
- (pIter->eType==RBU_PK_WITHOUT_ROWID ? " WITHOUT ROWID" : "")
- );
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0);
- }
-}
-
-/*
-** Prepare a statement used to insert rows into the "rbu_tmp_xxx" table.
-** Specifically a statement of the form:
-**
-** INSERT INTO rbu_tmp_xxx VALUES(?, ?, ? ...);
-**
-** The number of bound variables is equal to the number of columns in
-** the target table, plus one (for the rbu_control column), plus one more
-** (for the rbu_rowid column) if the target table is an implicit IPK or
-** virtual table.
-*/
-static void rbuObjIterPrepareTmpInsert(
- sqlite3rbu *p,
- RbuObjIter *pIter,
- const char *zCollist,
- const char *zRbuRowid
-){
- int bRbuRowid = (pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE);
- char *zBind = rbuObjIterGetBindlist(p, pIter->nTblCol + 1 + bRbuRowid);
- if( zBind ){
- assert( pIter->pTmpInsert==0 );
- p->rc = prepareFreeAndCollectError(
- p->dbRbu, &pIter->pTmpInsert, &p->zErrmsg, sqlite3_mprintf(
- "INSERT INTO %s.'rbu_tmp_%q'(rbu_control,%s%s) VALUES(%z)",
- p->zStateDb, pIter->zDataTbl, zCollist, zRbuRowid, zBind
- ));
- }
-}
-
-static void rbuTmpInsertFunc(
- sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal
-){
- sqlite3rbu *p = sqlite3_user_data(pCtx);
- int rc = SQLITE_OK;
- int i;
-
- assert( sqlite3_value_int(apVal[0])!=0
- || p->objiter.eType==RBU_PK_EXTERNAL
- || p->objiter.eType==RBU_PK_NONE
- );
- if( sqlite3_value_int(apVal[0])!=0 ){
- p->nPhaseOneStep += p->objiter.nIndex;
- }
-
- for(i=0; rc==SQLITE_OK && i<nVal; i++){
- rc = sqlite3_bind_value(p->objiter.pTmpInsert, i+1, apVal[i]);
- }
- if( rc==SQLITE_OK ){
- sqlite3_step(p->objiter.pTmpInsert);
- rc = sqlite3_reset(p->objiter.pTmpInsert);
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_result_error_code(pCtx, rc);
- }
-}
-
-/*
-** Ensure that the SQLite statement handles required to update the
-** target database object currently indicated by the iterator passed
-** as the second argument are available.
-*/
-static int rbuObjIterPrepareAll(
- sqlite3rbu *p,
- RbuObjIter *pIter,
- int nOffset /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */
-){
- assert( pIter->bCleanup==0 );
- if( pIter->pSelect==0 && rbuObjIterCacheTableInfo(p, pIter)==SQLITE_OK ){
- const int tnum = pIter->iTnum;
- char *zCollist = 0; /* List of indexed columns */
- char **pz = &p->zErrmsg;
- const char *zIdx = pIter->zIdx;
- char *zLimit = 0;
-
- if( nOffset ){
- zLimit = sqlite3_mprintf(" LIMIT -1 OFFSET %d", nOffset);
- if( !zLimit ) p->rc = SQLITE_NOMEM;
- }
-
- if( zIdx ){
- const char *zTbl = pIter->zTbl;
- char *zImposterCols = 0; /* Columns for imposter table */
- char *zImposterPK = 0; /* Primary key declaration for imposter */
- char *zWhere = 0; /* WHERE clause on PK columns */
- char *zBind = 0;
- int nBind = 0;
-
- assert( pIter->eType!=RBU_PK_VTAB );
- zCollist = rbuObjIterGetIndexCols(
- p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind
- );
- zBind = rbuObjIterGetBindlist(p, nBind);
-
- /* Create the imposter table used to write to this index. */
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1);
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1,tnum);
- rbuMPrintfExec(p, p->dbMain,
- "CREATE TABLE \"rbu_imp_%w\"( %s, PRIMARY KEY( %s ) ) WITHOUT ROWID",
- zTbl, zImposterCols, zImposterPK
- );
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0);
-
- /* Create the statement to insert index entries */
- pIter->nCol = nBind;
- if( p->rc==SQLITE_OK ){
- p->rc = prepareFreeAndCollectError(
- p->dbMain, &pIter->pInsert, &p->zErrmsg,
- sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind)
- );
- }
-
- /* And to delete index entries */
- if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){
- p->rc = prepareFreeAndCollectError(
- p->dbMain, &pIter->pDelete, &p->zErrmsg,
- sqlite3_mprintf("DELETE FROM \"rbu_imp_%w\" WHERE %s", zTbl, zWhere)
- );
- }
-
- /* Create the SELECT statement to read keys in sorted order */
- if( p->rc==SQLITE_OK ){
- char *zSql;
- if( rbuIsVacuum(p) ){
- zSql = sqlite3_mprintf(
- "SELECT %s, 0 AS rbu_control FROM '%q' ORDER BY %s%s",
- zCollist,
- pIter->zDataTbl,
- zCollist, zLimit
- );
- }else
-
- if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){
- zSql = sqlite3_mprintf(
- "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s",
- zCollist, p->zStateDb, pIter->zDataTbl,
- zCollist, zLimit
- );
- }else{
- zSql = sqlite3_mprintf(
- "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' "
- "UNION ALL "
- "SELECT %s, rbu_control FROM '%q' "
- "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 "
- "ORDER BY %s%s",
- zCollist, p->zStateDb, pIter->zDataTbl,
- zCollist, pIter->zDataTbl,
- zCollist, zLimit
- );
- }
- p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql);
- }
-
- sqlite3_free(zImposterCols);
- sqlite3_free(zImposterPK);
- sqlite3_free(zWhere);
- sqlite3_free(zBind);
- }else{
- int bRbuRowid = (pIter->eType==RBU_PK_VTAB)
- ||(pIter->eType==RBU_PK_NONE)
- ||(pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p));
- const char *zTbl = pIter->zTbl; /* Table this step applies to */
- const char *zWrite; /* Imposter table name */
-
- char *zBindings = rbuObjIterGetBindlist(p, pIter->nTblCol + bRbuRowid);
- char *zWhere = rbuObjIterGetWhere(p, pIter);
- char *zOldlist = rbuObjIterGetOldlist(p, pIter, "old");
- char *zNewlist = rbuObjIterGetOldlist(p, pIter, "new");
-
- zCollist = rbuObjIterGetCollist(p, pIter);
- pIter->nCol = pIter->nTblCol;
-
- /* Create the imposter table or tables (if required). */
- rbuCreateImposterTable(p, pIter);
- rbuCreateImposterTable2(p, pIter);
- zWrite = (pIter->eType==RBU_PK_VTAB ? "" : "rbu_imp_");
-
- /* Create the INSERT statement to write to the target PK b-tree */
- if( p->rc==SQLITE_OK ){
- p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz,
- sqlite3_mprintf(
- "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)",
- zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings
- )
- );
- }
-
- /* Create the DELETE statement to write to the target PK b-tree.
- ** Because it only performs INSERT operations, this is not required for
- ** an rbu vacuum handle. */
- if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){
- p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz,
- sqlite3_mprintf(
- "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere
- )
- );
- }
-
- if( rbuIsVacuum(p)==0 && pIter->abIndexed ){
- const char *zRbuRowid = "";
- if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){
- zRbuRowid = ", rbu_rowid";
- }
-
- /* Create the rbu_tmp_xxx table and the triggers to populate it. */
- rbuMPrintfExec(p, p->dbRbu,
- "CREATE TABLE IF NOT EXISTS %s.'rbu_tmp_%q' AS "
- "SELECT *%s FROM '%q' WHERE 0;"
- , p->zStateDb, pIter->zDataTbl
- , (pIter->eType==RBU_PK_EXTERNAL ? ", 0 AS rbu_rowid" : "")
- , pIter->zDataTbl
- );
-
- rbuMPrintfExec(p, p->dbMain,
- "CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" "
- "BEGIN "
- " SELECT rbu_tmp_insert(3, %s);"
- "END;"
-
- "CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" "
- "BEGIN "
- " SELECT rbu_tmp_insert(3, %s);"
- "END;"
-
- "CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" "
- "BEGIN "
- " SELECT rbu_tmp_insert(4, %s);"
- "END;",
- zWrite, zTbl, zOldlist,
- zWrite, zTbl, zOldlist,
- zWrite, zTbl, zNewlist
- );
-
- if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){
- rbuMPrintfExec(p, p->dbMain,
- "CREATE TEMP TRIGGER rbu_insert_tr AFTER INSERT ON \"%s%w\" "
- "BEGIN "
- " SELECT rbu_tmp_insert(0, %s);"
- "END;",
- zWrite, zTbl, zNewlist
- );
- }
-
- rbuObjIterPrepareTmpInsert(p, pIter, zCollist, zRbuRowid);
- }
-
- /* Create the SELECT statement to read keys from data_xxx */
- if( p->rc==SQLITE_OK ){
- const char *zRbuRowid = "";
- if( bRbuRowid ){
- zRbuRowid = rbuIsVacuum(p) ? ",_rowid_ " : ",rbu_rowid";
- }
- p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz,
- sqlite3_mprintf(
- "SELECT %s,%s rbu_control%s FROM '%q'%s",
- zCollist,
- (rbuIsVacuum(p) ? "0 AS " : ""),
- zRbuRowid,
- pIter->zDataTbl, zLimit
- )
- );
- }
-
- sqlite3_free(zWhere);
- sqlite3_free(zOldlist);
- sqlite3_free(zNewlist);
- sqlite3_free(zBindings);
- }
- sqlite3_free(zCollist);
- sqlite3_free(zLimit);
- }
-
- return p->rc;
-}
-
-/*
-** Set output variable *ppStmt to point to an UPDATE statement that may
-** be used to update the imposter table for the main table b-tree of the
-** table object that pIter currently points to, assuming that the
-** rbu_control column of the data_xyz table contains zMask.
-**
-** If the zMask string does not specify any columns to update, then this
-** is not an error. Output variable *ppStmt is set to NULL in this case.
-*/
-static int rbuGetUpdateStmt(
- sqlite3rbu *p, /* RBU handle */
- RbuObjIter *pIter, /* Object iterator */
- const char *zMask, /* rbu_control value ('x.x.') */
- sqlite3_stmt **ppStmt /* OUT: UPDATE statement handle */
-){
- RbuUpdateStmt **pp;
- RbuUpdateStmt *pUp = 0;
- int nUp = 0;
-
- /* In case an error occurs */
- *ppStmt = 0;
-
- /* Search for an existing statement. If one is found, shift it to the front
- ** of the LRU queue and return immediately. Otherwise, leave nUp pointing
- ** to the number of statements currently in the cache and pUp to the
- ** last object in the list. */
- for(pp=&pIter->pRbuUpdate; *pp; pp=&((*pp)->pNext)){
- pUp = *pp;
- if( strcmp(pUp->zMask, zMask)==0 ){
- *pp = pUp->pNext;
- pUp->pNext = pIter->pRbuUpdate;
- pIter->pRbuUpdate = pUp;
- *ppStmt = pUp->pUpdate;
- return SQLITE_OK;
- }
- nUp++;
- }
- assert( pUp==0 || pUp->pNext==0 );
-
- if( nUp>=SQLITE_RBU_UPDATE_CACHESIZE ){
- for(pp=&pIter->pRbuUpdate; *pp!=pUp; pp=&((*pp)->pNext));
- *pp = 0;
- sqlite3_finalize(pUp->pUpdate);
- pUp->pUpdate = 0;
- }else{
- pUp = (RbuUpdateStmt*)rbuMalloc(p, sizeof(RbuUpdateStmt)+pIter->nTblCol+1);
- }
-
- if( pUp ){
- char *zWhere = rbuObjIterGetWhere(p, pIter);
- char *zSet = rbuObjIterGetSetlist(p, pIter, zMask);
- char *zUpdate = 0;
-
- pUp->zMask = (char*)&pUp[1];
- memcpy(pUp->zMask, zMask, pIter->nTblCol);
- pUp->pNext = pIter->pRbuUpdate;
- pIter->pRbuUpdate = pUp;
-
- if( zSet ){
- const char *zPrefix = "";
-
- if( pIter->eType!=RBU_PK_VTAB ) zPrefix = "rbu_imp_";
- zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s",
- zPrefix, pIter->zTbl, zSet, zWhere
- );
- p->rc = prepareFreeAndCollectError(
- p->dbMain, &pUp->pUpdate, &p->zErrmsg, zUpdate
- );
- *ppStmt = pUp->pUpdate;
- }
- sqlite3_free(zWhere);
- sqlite3_free(zSet);
- }
-
- return p->rc;
-}
-
-static sqlite3 *rbuOpenDbhandle(
- sqlite3rbu *p,
- const char *zName,
- int bUseVfs
-){
- sqlite3 *db = 0;
- if( p->rc==SQLITE_OK ){
- const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI;
- p->rc = sqlite3_open_v2(zName, &db, flags, bUseVfs ? p->zVfsName : 0);
- if( p->rc ){
- p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- sqlite3_close(db);
- db = 0;
- }
- }
- return db;
-}
-
-/*
-** Free an RbuState object allocated by rbuLoadState().
-*/
-static void rbuFreeState(RbuState *p){
- if( p ){
- sqlite3_free(p->zTbl);
- sqlite3_free(p->zDataTbl);
- sqlite3_free(p->zIdx);
- sqlite3_free(p);
- }
-}
-
-/*
-** Allocate an RbuState object and load the contents of the rbu_state
-** table into it. Return a pointer to the new object. It is the
-** responsibility of the caller to eventually free the object using
-** sqlite3_free().
-**
-** If an error occurs, leave an error code and message in the rbu handle
-** and return NULL.
-*/
-static RbuState *rbuLoadState(sqlite3rbu *p){
- RbuState *pRet = 0;
- sqlite3_stmt *pStmt = 0;
- int rc;
- int rc2;
-
- pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState));
- if( pRet==0 ) return 0;
-
- rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg,
- sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb)
- );
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- switch( sqlite3_column_int(pStmt, 0) ){
- case RBU_STATE_STAGE:
- pRet->eStage = sqlite3_column_int(pStmt, 1);
- if( pRet->eStage!=RBU_STAGE_OAL
- && pRet->eStage!=RBU_STAGE_MOVE
- && pRet->eStage!=RBU_STAGE_CKPT
- ){
- p->rc = SQLITE_CORRUPT;
- }
- break;
-
- case RBU_STATE_TBL:
- pRet->zTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc);
- break;
-
- case RBU_STATE_IDX:
- pRet->zIdx = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc);
- break;
-
- case RBU_STATE_ROW:
- pRet->nRow = sqlite3_column_int(pStmt, 1);
- break;
-
- case RBU_STATE_PROGRESS:
- pRet->nProgress = sqlite3_column_int64(pStmt, 1);
- break;
-
- case RBU_STATE_CKPT:
- pRet->iWalCksum = sqlite3_column_int64(pStmt, 1);
- break;
-
- case RBU_STATE_COOKIE:
- pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1);
- break;
-
- case RBU_STATE_OALSZ:
- pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1);
- break;
-
- case RBU_STATE_PHASEONESTEP:
- pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1);
- break;
-
- case RBU_STATE_DATATBL:
- pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc);
- break;
-
- default:
- rc = SQLITE_CORRUPT;
- break;
- }
- }
- rc2 = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) rc = rc2;
-
- p->rc = rc;
- return pRet;
-}
-
-
-/*
-** Open the database handle and attach the RBU database as "rbu". If an
-** error occurs, leave an error code and message in the RBU handle.
-*/
-static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
- assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
- assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
-
- /* Open the RBU database */
- p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1);
-
- if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
- sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
- if( p->zState==0 ){
- const char *zFile = sqlite3_db_filename(p->dbRbu, "main");
- p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile);
- }
- }
-
- /* If using separate RBU and state databases, attach the state database to
- ** the RBU db handle now. */
- if( p->zState ){
- rbuMPrintfExec(p, p->dbRbu, "ATTACH %Q AS stat", p->zState);
- memcpy(p->zStateDb, "stat", 4);
- }else{
- memcpy(p->zStateDb, "main", 4);
- }
-
-#if 0
- if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
- p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, 0);
- }
-#endif
-
- /* If it has not already been created, create the rbu_state table */
- rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb);
-
-#if 0
- if( rbuIsVacuum(p) ){
- if( p->rc==SQLITE_OK ){
- int rc2;
- int bOk = 0;
- sqlite3_stmt *pCnt = 0;
- p->rc = prepareAndCollectError(p->dbRbu, &pCnt, &p->zErrmsg,
- "SELECT count(*) FROM stat.sqlite_master"
- );
- if( p->rc==SQLITE_OK
- && sqlite3_step(pCnt)==SQLITE_ROW
- && 1==sqlite3_column_int(pCnt, 0)
- ){
- bOk = 1;
- }
- rc2 = sqlite3_finalize(pCnt);
- if( p->rc==SQLITE_OK ) p->rc = rc2;
-
- if( p->rc==SQLITE_OK && bOk==0 ){
- p->rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf("invalid state database");
- }
-
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0);
- }
- }
- }
-#endif
-
- if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
- int bOpen = 0;
- int rc;
- p->nRbu = 0;
- p->pRbuFd = 0;
- rc = sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
- if( rc!=SQLITE_NOTFOUND ) p->rc = rc;
- if( p->eStage>=RBU_STAGE_MOVE ){
- bOpen = 1;
- }else{
- RbuState *pState = rbuLoadState(p);
- if( pState ){
- bOpen = (pState->eStage>=RBU_STAGE_MOVE);
- rbuFreeState(pState);
- }
- }
- if( bOpen ) p->dbMain = rbuOpenDbhandle(p, p->zRbu, p->nRbu<=1);
- }
-
- p->eStage = 0;
- if( p->rc==SQLITE_OK && p->dbMain==0 ){
- if( !rbuIsVacuum(p) ){
- p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1);
- }else if( p->pRbuFd->pWalFd ){
- if( pbRetry ){
- p->pRbuFd->bNolock = 0;
- sqlite3_close(p->dbRbu);
- sqlite3_close(p->dbMain);
- p->dbMain = 0;
- p->dbRbu = 0;
- *pbRetry = 1;
- return;
- }
- p->rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database");
- }else{
- char *zTarget;
- char *zExtra = 0;
- if( strlen(p->zRbu)>=5 && 0==memcmp("file:", p->zRbu, 5) ){
- zExtra = &p->zRbu[5];
- while( *zExtra ){
- if( *zExtra++=='?' ) break;
- }
- if( *zExtra=='\0' ) zExtra = 0;
- }
-
- zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s",
- sqlite3_db_filename(p->dbRbu, "main"),
- (zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra)
- );
-
- if( zTarget==0 ){
- p->rc = SQLITE_NOMEM;
- return;
- }
- p->dbMain = rbuOpenDbhandle(p, zTarget, p->nRbu<=1);
- sqlite3_free(zTarget);
- }
- }
-
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_create_function(p->dbMain,
- "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0
- );
- }
-
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_create_function(p->dbMain,
- "rbu_fossil_delta", 2, SQLITE_UTF8, 0, rbuFossilDeltaFunc, 0, 0
- );
- }
-
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_create_function(p->dbRbu,
- "rbu_target_name", -1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0
- );
- }
-
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p);
- }
- rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master");
-
- /* Mark the database file just opened as an RBU target database. If
- ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use.
- ** This is an error. */
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p);
- }
-
- if( p->rc==SQLITE_NOTFOUND ){
- p->rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf("rbu vfs not found");
- }
-}
-
-/*
-** This routine is a copy of the sqlite3FileSuffix3() routine from the core.
-** It is a no-op unless SQLITE_ENABLE_8_3_NAMES is defined.
-**
-** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
-** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
-** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
-** three characters, then shorten the suffix on z[] to be the last three
-** characters of the original suffix.
-**
-** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
-** do the suffix shortening regardless of URI parameter.
-**
-** Examples:
-**
-** test.db-journal => test.nal
-** test.db-wal => test.wal
-** test.db-shm => test.shm
-** test.db-mj7f3319fa => test.9fa
-*/
-static void rbuFileSuffix3(const char *zBase, char *z){
-#ifdef SQLITE_ENABLE_8_3_NAMES
-#if SQLITE_ENABLE_8_3_NAMES<2
- if( sqlite3_uri_boolean(zBase, "8_3_names", 0) )
-#endif
- {
- int i, sz;
- sz = (int)strlen(z)&0xffffff;
- for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
- if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4);
- }
-#endif
-}
-
-/*
-** Return the current wal-index header checksum for the target database
-** as a 64-bit integer.
-**
-** The checksum is store in the first page of xShmMap memory as an 8-byte
-** blob starting at byte offset 40.
-*/
-static i64 rbuShmChecksum(sqlite3rbu *p){
- i64 iRet = 0;
- if( p->rc==SQLITE_OK ){
- sqlite3_file *pDb = p->pTargetFd->pReal;
- u32 volatile *ptr;
- p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr);
- if( p->rc==SQLITE_OK ){
- iRet = ((i64)ptr[10] << 32) + ptr[11];
- }
- }
- return iRet;
-}
-
-/*
-** This function is called as part of initializing or reinitializing an
-** incremental checkpoint.
-**
-** It populates the sqlite3rbu.aFrame[] array with the set of
-** (wal frame -> db page) copy operations required to checkpoint the
-** current wal file, and obtains the set of shm locks required to safely
-** perform the copy operations directly on the file-system.
-**
-** If argument pState is not NULL, then the incremental checkpoint is
-** being resumed. In this case, if the checksum of the wal-index-header
-** following recovery is not the same as the checksum saved in the RbuState
-** object, then the rbu handle is set to DONE state. This occurs if some
-** other client appends a transaction to the wal file in the middle of
-** an incremental checkpoint.
-*/
-static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){
-
- /* If pState is NULL, then the wal file may not have been opened and
- ** recovered. Running a read-statement here to ensure that doing so
- ** does not interfere with the "capture" process below. */
- if( pState==0 ){
- p->eStage = 0;
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_master", 0, 0, 0);
- }
- }
-
- /* Assuming no error has occurred, run a "restart" checkpoint with the
- ** sqlite3rbu.eStage variable set to CAPTURE. This turns on the following
- ** special behaviour in the rbu VFS:
- **
- ** * If the exclusive shm WRITER or READ0 lock cannot be obtained,
- ** the checkpoint fails with SQLITE_BUSY (normally SQLite would
- ** proceed with running a passive checkpoint instead of failing).
- **
- ** * Attempts to read from the *-wal file or write to the database file
- ** do not perform any IO. Instead, the frame/page combinations that
- ** would be read/written are recorded in the sqlite3rbu.aFrame[]
- ** array.
- **
- ** * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER,
- ** READ0 and CHECKPOINT locks taken as part of the checkpoint are
- ** no-ops. These locks will not be released until the connection
- ** is closed.
- **
- ** * Attempting to xSync() the database file causes an SQLITE_INTERNAL
- ** error.
- **
- ** As a result, unless an error (i.e. OOM or SQLITE_BUSY) occurs, the
- ** checkpoint below fails with SQLITE_INTERNAL, and leaves the aFrame[]
- ** array populated with a set of (frame -> page) mappings. Because the
- ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy
- ** data from the wal file into the database file according to the
- ** contents of aFrame[].
- */
- if( p->rc==SQLITE_OK ){
- int rc2;
- p->eStage = RBU_STAGE_CAPTURE;
- rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0);
- if( rc2!=SQLITE_INTERNAL ) p->rc = rc2;
- }
-
- if( p->rc==SQLITE_OK && p->nFrame>0 ){
- p->eStage = RBU_STAGE_CKPT;
- p->nStep = (pState ? pState->nRow : 0);
- p->aBuf = rbuMalloc(p, p->pgsz);
- p->iWalCksum = rbuShmChecksum(p);
- }
-
- if( p->rc==SQLITE_OK ){
- if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){
- p->rc = SQLITE_DONE;
- p->eStage = RBU_STAGE_DONE;
- }else{
- int nSectorSize;
- sqlite3_file *pDb = p->pTargetFd->pReal;
- sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal;
- assert( p->nPagePerSector==0 );
- nSectorSize = pDb->pMethods->xSectorSize(pDb);
- if( nSectorSize>p->pgsz ){
- p->nPagePerSector = nSectorSize / p->pgsz;
- }else{
- p->nPagePerSector = 1;
- }
-
- /* Call xSync() on the wal file. This causes SQLite to sync the
- ** directory in which the target database and the wal file reside, in
- ** case it has not been synced since the rename() call in
- ** rbuMoveOalFile(). */
- p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL);
- }
- }
-}
-
-/*
-** Called when iAmt bytes are read from offset iOff of the wal file while
-** the rbu object is in capture mode. Record the frame number of the frame
-** being read in the aFrame[] array.
-*/
-static int rbuCaptureWalRead(sqlite3rbu *pRbu, i64 iOff, int iAmt){
- const u32 mReq = (1<<WAL_LOCK_WRITE)|(1<<WAL_LOCK_CKPT)|(1<<WAL_LOCK_READ0);
- u32 iFrame;
-
- if( pRbu->mLock!=mReq ){
- pRbu->rc = SQLITE_BUSY;
- return SQLITE_INTERNAL;
- }
-
- pRbu->pgsz = iAmt;
- if( pRbu->nFrame==pRbu->nFrameAlloc ){
- int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2;
- RbuFrame *aNew;
- aNew = (RbuFrame*)sqlite3_realloc64(pRbu->aFrame, nNew * sizeof(RbuFrame));
- if( aNew==0 ) return SQLITE_NOMEM;
- pRbu->aFrame = aNew;
- pRbu->nFrameAlloc = nNew;
- }
-
- iFrame = (u32)((iOff-32) / (i64)(iAmt+24)) + 1;
- if( pRbu->iMaxFrame<iFrame ) pRbu->iMaxFrame = iFrame;
- pRbu->aFrame[pRbu->nFrame].iWalFrame = iFrame;
- pRbu->aFrame[pRbu->nFrame].iDbPage = 0;
- pRbu->nFrame++;
- return SQLITE_OK;
-}
-
-/*
-** Called when a page of data is written to offset iOff of the database
-** file while the rbu handle is in capture mode. Record the page number
-** of the page being written in the aFrame[] array.
-*/
-static int rbuCaptureDbWrite(sqlite3rbu *pRbu, i64 iOff){
- pRbu->aFrame[pRbu->nFrame-1].iDbPage = (u32)(iOff / pRbu->pgsz) + 1;
- return SQLITE_OK;
-}
-
-/*
-** This is called as part of an incremental checkpoint operation. Copy
-** a single frame of data from the wal file into the database file, as
-** indicated by the RbuFrame object.
-*/
-static void rbuCheckpointFrame(sqlite3rbu *p, RbuFrame *pFrame){
- sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal;
- sqlite3_file *pDb = p->pTargetFd->pReal;
- i64 iOff;
-
- assert( p->rc==SQLITE_OK );
- iOff = (i64)(pFrame->iWalFrame-1) * (p->pgsz + 24) + 32 + 24;
- p->rc = pWal->pMethods->xRead(pWal, p->aBuf, p->pgsz, iOff);
- if( p->rc ) return;
-
- iOff = (i64)(pFrame->iDbPage-1) * p->pgsz;
- p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff);
-}
-
-
-/*
-** Take an EXCLUSIVE lock on the database file.
-*/
-static void rbuLockDatabase(sqlite3rbu *p){
- sqlite3_file *pReal = p->pTargetFd->pReal;
- assert( p->rc==SQLITE_OK );
- p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED);
- if( p->rc==SQLITE_OK ){
- p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE);
- }
-}
-
-#if defined(_WIN32_WCE)
-static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){
- int nChar;
- LPWSTR zWideFilename;
-
- nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
- if( nChar==0 ){
- return 0;
- }
- zWideFilename = sqlite3_malloc64( nChar*sizeof(zWideFilename[0]) );
- if( zWideFilename==0 ){
- return 0;
- }
- memset(zWideFilename, 0, nChar*sizeof(zWideFilename[0]));
- nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
- nChar);
- if( nChar==0 ){
- sqlite3_free(zWideFilename);
- zWideFilename = 0;
- }
- return zWideFilename;
-}
-#endif
-
-/*
-** The RBU handle is currently in RBU_STAGE_OAL state, with a SHARED lock
-** on the database file. This proc moves the *-oal file to the *-wal path,
-** then reopens the database file (this time in vanilla, non-oal, WAL mode).
-** If an error occurs, leave an error code and error message in the rbu
-** handle.
-*/
-static void rbuMoveOalFile(sqlite3rbu *p){
- const char *zBase = sqlite3_db_filename(p->dbMain, "main");
- const char *zMove = zBase;
- char *zOal;
- char *zWal;
-
- if( rbuIsVacuum(p) ){
- zMove = sqlite3_db_filename(p->dbRbu, "main");
- }
- zOal = sqlite3_mprintf("%s-oal", zMove);
- zWal = sqlite3_mprintf("%s-wal", zMove);
-
- assert( p->eStage==RBU_STAGE_MOVE );
- assert( p->rc==SQLITE_OK && p->zErrmsg==0 );
- if( zWal==0 || zOal==0 ){
- p->rc = SQLITE_NOMEM;
- }else{
- /* Move the *-oal file to *-wal. At this point connection p->db is
- ** holding a SHARED lock on the target database file (because it is
- ** in WAL mode). So no other connection may be writing the db.
- **
- ** In order to ensure that there are no database readers, an EXCLUSIVE
- ** lock is obtained here before the *-oal is moved to *-wal.
- */
- rbuLockDatabase(p);
- if( p->rc==SQLITE_OK ){
- rbuFileSuffix3(zBase, zWal);
- rbuFileSuffix3(zBase, zOal);
-
- /* Re-open the databases. */
- rbuObjIterFinalize(&p->objiter);
- sqlite3_close(p->dbRbu);
- sqlite3_close(p->dbMain);
- p->dbMain = 0;
- p->dbRbu = 0;
-
-#if defined(_WIN32_WCE)
- {
- LPWSTR zWideOal;
- LPWSTR zWideWal;
-
- zWideOal = rbuWinUtf8ToUnicode(zOal);
- if( zWideOal ){
- zWideWal = rbuWinUtf8ToUnicode(zWal);
- if( zWideWal ){
- if( MoveFileW(zWideOal, zWideWal) ){
- p->rc = SQLITE_OK;
- }else{
- p->rc = SQLITE_IOERR;
- }
- sqlite3_free(zWideWal);
- }else{
- p->rc = SQLITE_IOERR_NOMEM;
- }
- sqlite3_free(zWideOal);
- }else{
- p->rc = SQLITE_IOERR_NOMEM;
- }
- }
-#else
- p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
-#endif
-
- if( p->rc==SQLITE_OK ){
- rbuOpenDatabase(p, 0);
- rbuSetupCheckpoint(p, 0);
- }
- }
- }
-
- sqlite3_free(zWal);
- sqlite3_free(zOal);
-}
-
-/*
-** The SELECT statement iterating through the keys for the current object
-** (p->objiter.pSelect) currently points to a valid row. This function
-** determines the type of operation requested by this row and returns
-** one of the following values to indicate the result:
-**
-** * RBU_INSERT
-** * RBU_DELETE
-** * RBU_IDX_DELETE
-** * RBU_UPDATE
-**
-** If RBU_UPDATE is returned, then output variable *pzMask is set to
-** point to the text value indicating the columns to update.
-**
-** If the rbu_control field contains an invalid value, an error code and
-** message are left in the RBU handle and zero returned.
-*/
-static int rbuStepType(sqlite3rbu *p, const char **pzMask){
- int iCol = p->objiter.nCol; /* Index of rbu_control column */
- int res = 0; /* Return value */
-
- switch( sqlite3_column_type(p->objiter.pSelect, iCol) ){
- case SQLITE_INTEGER: {
- int iVal = sqlite3_column_int(p->objiter.pSelect, iCol);
- switch( iVal ){
- case 0: res = RBU_INSERT; break;
- case 1: res = RBU_DELETE; break;
- case 2: res = RBU_REPLACE; break;
- case 3: res = RBU_IDX_DELETE; break;
- case 4: res = RBU_IDX_INSERT; break;
- }
- break;
- }
-
- case SQLITE_TEXT: {
- const unsigned char *z = sqlite3_column_text(p->objiter.pSelect, iCol);
- if( z==0 ){
- p->rc = SQLITE_NOMEM;
- }else{
- *pzMask = (const char*)z;
- }
- res = RBU_UPDATE;
-
- break;
- }
-
- default:
- break;
- }
-
- if( res==0 ){
- rbuBadControlError(p);
- }
- return res;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** Assert that column iCol of statement pStmt is named zName.
-*/
-static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){
- const char *zCol = sqlite3_column_name(pStmt, iCol);
- assert( 0==sqlite3_stricmp(zName, zCol) );
-}
-#else
-# define assertColumnName(x,y,z)
-#endif
-
-/*
-** Argument eType must be one of RBU_INSERT, RBU_DELETE, RBU_IDX_INSERT or
-** RBU_IDX_DELETE. This function performs the work of a single
-** sqlite3rbu_step() call for the type of operation specified by eType.
-*/
-static void rbuStepOneOp(sqlite3rbu *p, int eType){
- RbuObjIter *pIter = &p->objiter;
- sqlite3_value *pVal;
- sqlite3_stmt *pWriter;
- int i;
-
- assert( p->rc==SQLITE_OK );
- assert( eType!=RBU_DELETE || pIter->zIdx==0 );
- assert( eType==RBU_DELETE || eType==RBU_IDX_DELETE
- || eType==RBU_INSERT || eType==RBU_IDX_INSERT
- );
-
- /* If this is a delete, decrement nPhaseOneStep by nIndex. If the DELETE
- ** statement below does actually delete a row, nPhaseOneStep will be
- ** incremented by the same amount when SQL function rbu_tmp_insert()
- ** is invoked by the trigger. */
- if( eType==RBU_DELETE ){
- p->nPhaseOneStep -= p->objiter.nIndex;
- }
-
- if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){
- pWriter = pIter->pDelete;
- }else{
- pWriter = pIter->pInsert;
- }
-
- for(i=0; i<pIter->nCol; i++){
- /* If this is an INSERT into a table b-tree and the table has an
- ** explicit INTEGER PRIMARY KEY, check that this is not an attempt
- ** to write a NULL into the IPK column. That is not permitted. */
- if( eType==RBU_INSERT
- && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i]
- && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL
- ){
- p->rc = SQLITE_MISMATCH;
- p->zErrmsg = sqlite3_mprintf("datatype mismatch");
- return;
- }
-
- if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){
- continue;
- }
-
- pVal = sqlite3_column_value(pIter->pSelect, i);
- p->rc = sqlite3_bind_value(pWriter, i+1, pVal);
- if( p->rc ) return;
- }
- if( pIter->zIdx==0 ){
- if( pIter->eType==RBU_PK_VTAB
- || pIter->eType==RBU_PK_NONE
- || (pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p))
- ){
- /* For a virtual table, or a table with no primary key, the
- ** SELECT statement is:
- **
- ** SELECT <cols>, rbu_control, rbu_rowid FROM ....
- **
- ** Hence column_value(pIter->nCol+1).
- */
- assertColumnName(pIter->pSelect, pIter->nCol+1,
- rbuIsVacuum(p) ? "rowid" : "rbu_rowid"
- );
- pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1);
- p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal);
- }
- }
- if( p->rc==SQLITE_OK ){
- sqlite3_step(pWriter);
- p->rc = resetAndCollectError(pWriter, &p->zErrmsg);
- }
-}
-
-/*
-** This function does the work for an sqlite3rbu_step() call.
-**
-** The object-iterator (p->objiter) currently points to a valid object,
-** and the input cursor (p->objiter.pSelect) currently points to a valid
-** input row. Perform whatever processing is required and return.
-**
-** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
-** and message is left in the RBU handle and a copy of the error code
-** returned.
-*/
-static int rbuStep(sqlite3rbu *p){
- RbuObjIter *pIter = &p->objiter;
- const char *zMask = 0;
- int eType = rbuStepType(p, &zMask);
-
- if( eType ){
- assert( eType==RBU_INSERT || eType==RBU_DELETE
- || eType==RBU_REPLACE || eType==RBU_IDX_DELETE
- || eType==RBU_IDX_INSERT || eType==RBU_UPDATE
- );
- assert( eType!=RBU_UPDATE || pIter->zIdx==0 );
-
- if( pIter->zIdx==0 && (eType==RBU_IDX_DELETE || eType==RBU_IDX_INSERT) ){
- rbuBadControlError(p);
- }
- else if( eType==RBU_REPLACE ){
- if( pIter->zIdx==0 ){
- p->nPhaseOneStep += p->objiter.nIndex;
- rbuStepOneOp(p, RBU_DELETE);
- }
- if( p->rc==SQLITE_OK ) rbuStepOneOp(p, RBU_INSERT);
- }
- else if( eType!=RBU_UPDATE ){
- rbuStepOneOp(p, eType);
- }
- else{
- sqlite3_value *pVal;
- sqlite3_stmt *pUpdate = 0;
- assert( eType==RBU_UPDATE );
- p->nPhaseOneStep -= p->objiter.nIndex;
- rbuGetUpdateStmt(p, pIter, zMask, &pUpdate);
- if( pUpdate ){
- int i;
- for(i=0; p->rc==SQLITE_OK && i<pIter->nCol; i++){
- char c = zMask[pIter->aiSrcOrder[i]];
- pVal = sqlite3_column_value(pIter->pSelect, i);
- if( pIter->abTblPk[i] || c!='.' ){
- p->rc = sqlite3_bind_value(pUpdate, i+1, pVal);
- }
- }
- if( p->rc==SQLITE_OK
- && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE)
- ){
- /* Bind the rbu_rowid value to column _rowid_ */
- assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid");
- pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1);
- p->rc = sqlite3_bind_value(pUpdate, pIter->nCol+1, pVal);
- }
- if( p->rc==SQLITE_OK ){
- sqlite3_step(pUpdate);
- p->rc = resetAndCollectError(pUpdate, &p->zErrmsg);
- }
- }
- }
- }
- return p->rc;
-}
-
-/*
-** Increment the schema cookie of the main database opened by p->dbMain.
-**
-** Or, if this is an RBU vacuum, set the schema cookie of the main db
-** opened by p->dbMain to one more than the schema cookie of the main
-** db opened by p->dbRbu.
-*/
-static void rbuIncrSchemaCookie(sqlite3rbu *p){
- if( p->rc==SQLITE_OK ){
- sqlite3 *dbread = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);
- int iCookie = 1000000;
- sqlite3_stmt *pStmt;
-
- p->rc = prepareAndCollectError(dbread, &pStmt, &p->zErrmsg,
- "PRAGMA schema_version"
- );
- if( p->rc==SQLITE_OK ){
- /* Coverage: it may be that this sqlite3_step() cannot fail. There
- ** is already a transaction open, so the prepared statement cannot
- ** throw an SQLITE_SCHEMA exception. The only database page the
- ** statement reads is page 1, which is guaranteed to be in the cache.
- ** And no memory allocations are required. */
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- iCookie = sqlite3_column_int(pStmt, 0);
- }
- rbuFinalize(p, pStmt);
- }
- if( p->rc==SQLITE_OK ){
- rbuMPrintfExec(p, p->dbMain, "PRAGMA schema_version = %d", iCookie+1);
- }
- }
-}
-
-/*
-** Update the contents of the rbu_state table within the rbu database. The
-** value stored in the RBU_STATE_STAGE column is eStage. All other values
-** are determined by inspecting the rbu handle passed as the first argument.
-*/
-static void rbuSaveState(sqlite3rbu *p, int eStage){
- if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){
- sqlite3_stmt *pInsert = 0;
- rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd);
- int rc;
-
- assert( p->zErrmsg==0 );
- rc = prepareFreeAndCollectError(p->dbRbu, &pInsert, &p->zErrmsg,
- sqlite3_mprintf(
- "INSERT OR REPLACE INTO %s.rbu_state(k, v) VALUES "
- "(%d, %d), "
- "(%d, %Q), "
- "(%d, %Q), "
- "(%d, %d), "
- "(%d, %d), "
- "(%d, %lld), "
- "(%d, %lld), "
- "(%d, %lld), "
- "(%d, %lld), "
- "(%d, %Q) ",
- p->zStateDb,
- RBU_STATE_STAGE, eStage,
- RBU_STATE_TBL, p->objiter.zTbl,
- RBU_STATE_IDX, p->objiter.zIdx,
- RBU_STATE_ROW, p->nStep,
- RBU_STATE_PROGRESS, p->nProgress,
- RBU_STATE_CKPT, p->iWalCksum,
- RBU_STATE_COOKIE, (i64)pFd->iCookie,
- RBU_STATE_OALSZ, p->iOalSz,
- RBU_STATE_PHASEONESTEP, p->nPhaseOneStep,
- RBU_STATE_DATATBL, p->objiter.zDataTbl
- )
- );
- assert( pInsert==0 || rc==SQLITE_OK );
-
- if( rc==SQLITE_OK ){
- sqlite3_step(pInsert);
- rc = sqlite3_finalize(pInsert);
- }
- if( rc!=SQLITE_OK ) p->rc = rc;
- }
-}
-
-
-/*
-** The second argument passed to this function is the name of a PRAGMA
-** setting - "page_size", "auto_vacuum", "user_version" or "application_id".
-** This function executes the following on sqlite3rbu.dbRbu:
-**
-** "PRAGMA main.$zPragma"
-**
-** where $zPragma is the string passed as the second argument, then
-** on sqlite3rbu.dbMain:
-**
-** "PRAGMA main.$zPragma = $val"
-**
-** where $val is the value returned by the first PRAGMA invocation.
-**
-** In short, it copies the value of the specified PRAGMA setting from
-** dbRbu to dbMain.
-*/
-static void rbuCopyPragma(sqlite3rbu *p, const char *zPragma){
- if( p->rc==SQLITE_OK ){
- sqlite3_stmt *pPragma = 0;
- p->rc = prepareFreeAndCollectError(p->dbRbu, &pPragma, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA main.%s", zPragma)
- );
- if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPragma) ){
- p->rc = rbuMPrintfExec(p, p->dbMain, "PRAGMA main.%s = %d",
- zPragma, sqlite3_column_int(pPragma, 0)
- );
- }
- rbuFinalize(p, pPragma);
- }
-}
-
-/*
-** The RBU handle passed as the only argument has just been opened and
-** the state database is empty. If this RBU handle was opened for an
-** RBU vacuum operation, create the schema in the target db.
-*/
-static void rbuCreateTargetSchema(sqlite3rbu *p){
- sqlite3_stmt *pSql = 0;
- sqlite3_stmt *pInsert = 0;
-
- assert( rbuIsVacuum(p) );
- p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=1", 0,0, &p->zErrmsg);
- if( p->rc==SQLITE_OK ){
- p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg,
- "SELECT sql FROM sqlite_master WHERE sql!='' AND rootpage!=0"
- " AND name!='sqlite_sequence' "
- " ORDER BY type DESC"
- );
- }
-
- while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
- const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
- p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg);
- }
- rbuFinalize(p, pSql);
- if( p->rc!=SQLITE_OK ) return;
-
- if( p->rc==SQLITE_OK ){
- p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg,
- "SELECT * FROM sqlite_master WHERE rootpage=0 OR rootpage IS NULL"
- );
- }
-
- if( p->rc==SQLITE_OK ){
- p->rc = prepareAndCollectError(p->dbMain, &pInsert, &p->zErrmsg,
- "INSERT INTO sqlite_master VALUES(?,?,?,?,?)"
- );
- }
-
- while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
- int i;
- for(i=0; i<5; i++){
- sqlite3_bind_value(pInsert, i+1, sqlite3_column_value(pSql, i));
- }
- sqlite3_step(pInsert);
- p->rc = sqlite3_reset(pInsert);
- }
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=0",0,0,&p->zErrmsg);
- }
-
- rbuFinalize(p, pSql);
- rbuFinalize(p, pInsert);
-}
-
-/*
-** Step the RBU object.
-*/
-int sqlite3rbu_step(sqlite3rbu *p){
- if( p ){
- switch( p->eStage ){
- case RBU_STAGE_OAL: {
- RbuObjIter *pIter = &p->objiter;
-
- /* If this is an RBU vacuum operation and the state table was empty
- ** when this handle was opened, create the target database schema. */
- if( rbuIsVacuum(p) && p->nProgress==0 && p->rc==SQLITE_OK ){
- rbuCreateTargetSchema(p);
- rbuCopyPragma(p, "user_version");
- rbuCopyPragma(p, "application_id");
- }
-
- while( p->rc==SQLITE_OK && pIter->zTbl ){
-
- if( pIter->bCleanup ){
- /* Clean up the rbu_tmp_xxx table for the previous table. It
- ** cannot be dropped as there are currently active SQL statements.
- ** But the contents can be deleted. */
- if( rbuIsVacuum(p)==0 && pIter->abIndexed ){
- rbuMPrintfExec(p, p->dbRbu,
- "DELETE FROM %s.'rbu_tmp_%q'", p->zStateDb, pIter->zDataTbl
- );
- }
- }else{
- rbuObjIterPrepareAll(p, pIter, 0);
-
- /* Advance to the next row to process. */
- if( p->rc==SQLITE_OK ){
- int rc = sqlite3_step(pIter->pSelect);
- if( rc==SQLITE_ROW ){
- p->nProgress++;
- p->nStep++;
- return rbuStep(p);
- }
- p->rc = sqlite3_reset(pIter->pSelect);
- p->nStep = 0;
- }
- }
-
- rbuObjIterNext(p, pIter);
- }
-
- if( p->rc==SQLITE_OK ){
- assert( pIter->zTbl==0 );
- rbuSaveState(p, RBU_STAGE_MOVE);
- rbuIncrSchemaCookie(p);
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg);
- }
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg);
- }
- p->eStage = RBU_STAGE_MOVE;
- }
- break;
- }
-
- case RBU_STAGE_MOVE: {
- if( p->rc==SQLITE_OK ){
- rbuMoveOalFile(p);
- p->nProgress++;
- }
- break;
- }
-
- case RBU_STAGE_CKPT: {
- if( p->rc==SQLITE_OK ){
- if( p->nStep>=p->nFrame ){
- sqlite3_file *pDb = p->pTargetFd->pReal;
-
- /* Sync the db file */
- p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL);
-
- /* Update nBackfill */
- if( p->rc==SQLITE_OK ){
- void volatile *ptr;
- p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, &ptr);
- if( p->rc==SQLITE_OK ){
- ((u32 volatile*)ptr)[24] = p->iMaxFrame;
- }
- }
-
- if( p->rc==SQLITE_OK ){
- p->eStage = RBU_STAGE_DONE;
- p->rc = SQLITE_DONE;
- }
- }else{
- /* At one point the following block copied a single frame from the
- ** wal file to the database file. So that one call to sqlite3rbu_step()
- ** checkpointed a single frame.
- **
- ** However, if the sector-size is larger than the page-size, and the
- ** application calls sqlite3rbu_savestate() or close() immediately
- ** after this step, then rbu_step() again, then a power failure occurs,
- ** then the database page written here may be damaged. Work around
- ** this by checkpointing frames until the next page in the aFrame[]
- ** lies on a different disk sector to the current one. */
- u32 iSector;
- do{
- RbuFrame *pFrame = &p->aFrame[p->nStep];
- iSector = (pFrame->iDbPage-1) / p->nPagePerSector;
- rbuCheckpointFrame(p, pFrame);
- p->nStep++;
- }while( p->nStep<p->nFrame
- && iSector==((p->aFrame[p->nStep].iDbPage-1) / p->nPagePerSector)
- && p->rc==SQLITE_OK
- );
- }
- p->nProgress++;
- }
- break;
- }
-
- default:
- break;
- }
- return p->rc;
- }else{
- return SQLITE_NOMEM;
- }
-}
-
-/*
-** Compare strings z1 and z2, returning 0 if they are identical, or non-zero
-** otherwise. Either or both argument may be NULL. Two NULL values are
-** considered equal, and NULL is considered distinct from all other values.
-*/
-static int rbuStrCompare(const char *z1, const char *z2){
- if( z1==0 && z2==0 ) return 0;
- if( z1==0 || z2==0 ) return 1;
- return (sqlite3_stricmp(z1, z2)!=0);
-}
-
-/*
-** This function is called as part of sqlite3rbu_open() when initializing
-** an rbu handle in OAL stage. If the rbu update has not started (i.e.
-** the rbu_state table was empty) it is a no-op. Otherwise, it arranges
-** things so that the next call to sqlite3rbu_step() continues on from
-** where the previous rbu handle left off.
-**
-** If an error occurs, an error code and error message are left in the
-** rbu handle passed as the first argument.
-*/
-static void rbuSetupOal(sqlite3rbu *p, RbuState *pState){
- assert( p->rc==SQLITE_OK );
- if( pState->zTbl ){
- RbuObjIter *pIter = &p->objiter;
- int rc = SQLITE_OK;
-
- while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup
- || rbuStrCompare(pIter->zIdx, pState->zIdx)
- || (pState->zDataTbl==0 && rbuStrCompare(pIter->zTbl, pState->zTbl))
- || (pState->zDataTbl && rbuStrCompare(pIter->zDataTbl, pState->zDataTbl))
- )){
- rc = rbuObjIterNext(p, pIter);
- }
-
- if( rc==SQLITE_OK && !pIter->zTbl ){
- rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf("rbu_state mismatch error");
- }
-
- if( rc==SQLITE_OK ){
- p->nStep = pState->nRow;
- rc = rbuObjIterPrepareAll(p, &p->objiter, p->nStep);
- }
-
- p->rc = rc;
- }
-}
-
-/*
-** If there is a "*-oal" file in the file-system corresponding to the
-** target database in the file-system, delete it. If an error occurs,
-** leave an error code and error message in the rbu handle.
-*/
-static void rbuDeleteOalFile(sqlite3rbu *p){
- char *zOal = rbuMPrintf(p, "%s-oal", p->zTarget);
- if( zOal ){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
- assert( pVfs && p->rc==SQLITE_OK && p->zErrmsg==0 );
- pVfs->xDelete(pVfs, zOal, 0);
- sqlite3_free(zOal);
- }
-}
-
-/*
-** Allocate a private rbu VFS for the rbu handle passed as the only
-** argument. This VFS will be used unless the call to sqlite3rbu_open()
-** specified a URI with a vfs=? option in place of a target database
-** file name.
-*/
-static void rbuCreateVfs(sqlite3rbu *p){
- int rnd;
- char zRnd[64];
-
- assert( p->rc==SQLITE_OK );
- sqlite3_randomness(sizeof(int), (void*)&rnd);
- sqlite3_snprintf(sizeof(zRnd), zRnd, "rbu_vfs_%d", rnd);
- p->rc = sqlite3rbu_create_vfs(zRnd, 0);
- if( p->rc==SQLITE_OK ){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd);
- assert( pVfs );
- p->zVfsName = pVfs->zName;
- ((rbu_vfs*)pVfs)->pRbu = p;
- }
-}
-
-/*
-** Destroy the private VFS created for the rbu handle passed as the only
-** argument by an earlier call to rbuCreateVfs().
-*/
-static void rbuDeleteVfs(sqlite3rbu *p){
- if( p->zVfsName ){
- sqlite3rbu_destroy_vfs(p->zVfsName);
- p->zVfsName = 0;
- }
-}
-
-/*
-** This user-defined SQL function is invoked with a single argument - the
-** name of a table expected to appear in the target database. It returns
-** the number of auxilliary indexes on the table.
-*/
-static void rbuIndexCntFunc(
- sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal
-){
- sqlite3rbu *p = (sqlite3rbu*)sqlite3_user_data(pCtx);
- sqlite3_stmt *pStmt = 0;
- char *zErrmsg = 0;
- int rc;
-
- assert( nVal==1 );
-
- rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg,
- sqlite3_mprintf("SELECT count(*) FROM sqlite_master "
- "WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0]))
- );
- if( rc!=SQLITE_OK ){
- sqlite3_result_error(pCtx, zErrmsg, -1);
- }else{
- int nIndex = 0;
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- nIndex = sqlite3_column_int(pStmt, 0);
- }
- rc = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ){
- sqlite3_result_int(pCtx, nIndex);
- }else{
- sqlite3_result_error(pCtx, sqlite3_errmsg(p->dbMain), -1);
- }
- }
-
- sqlite3_free(zErrmsg);
-}
-
-/*
-** If the RBU database contains the rbu_count table, use it to initialize
-** the sqlite3rbu.nPhaseOneStep variable. The schema of the rbu_count table
-** is assumed to contain the same columns as:
-**
-** CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID;
-**
-** There should be one row in the table for each data_xxx table in the
-** database. The 'tbl' column should contain the name of a data_xxx table,
-** and the cnt column the number of rows it contains.
-**
-** sqlite3rbu.nPhaseOneStep is initialized to the sum of (1 + nIndex) * cnt
-** for all rows in the rbu_count table, where nIndex is the number of
-** indexes on the corresponding target database table.
-*/
-static void rbuInitPhaseOneSteps(sqlite3rbu *p){
- if( p->rc==SQLITE_OK ){
- sqlite3_stmt *pStmt = 0;
- int bExists = 0; /* True if rbu_count exists */
-
- p->nPhaseOneStep = -1;
-
- p->rc = sqlite3_create_function(p->dbRbu,
- "rbu_index_cnt", 1, SQLITE_UTF8, (void*)p, rbuIndexCntFunc, 0, 0
- );
-
- /* Check for the rbu_count table. If it does not exist, or if an error
- ** occurs, nPhaseOneStep will be left set to -1. */
- if( p->rc==SQLITE_OK ){
- p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg,
- "SELECT 1 FROM sqlite_master WHERE tbl_name = 'rbu_count'"
- );
- }
- if( p->rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- bExists = 1;
- }
- p->rc = sqlite3_finalize(pStmt);
- }
-
- if( p->rc==SQLITE_OK && bExists ){
- p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg,
- "SELECT sum(cnt * (1 + rbu_index_cnt(rbu_target_name(tbl))))"
- "FROM rbu_count"
- );
- if( p->rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- p->nPhaseOneStep = sqlite3_column_int64(pStmt, 0);
- }
- p->rc = sqlite3_finalize(pStmt);
- }
- }
- }
-}
-
-
-static sqlite3rbu *openRbuHandle(
- const char *zTarget,
- const char *zRbu,
- const char *zState
-){
- sqlite3rbu *p;
- size_t nTarget = zTarget ? strlen(zTarget) : 0;
- size_t nRbu = strlen(zRbu);
- size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1;
-
- p = (sqlite3rbu*)sqlite3_malloc64(nByte);
- if( p ){
- RbuState *pState = 0;
-
- /* Create the custom VFS. */
- memset(p, 0, sizeof(sqlite3rbu));
- rbuCreateVfs(p);
-
- /* Open the target, RBU and state databases */
- if( p->rc==SQLITE_OK ){
- char *pCsr = (char*)&p[1];
- int bRetry = 0;
- if( zTarget ){
- p->zTarget = pCsr;
- memcpy(p->zTarget, zTarget, nTarget+1);
- pCsr += nTarget+1;
- }
- p->zRbu = pCsr;
- memcpy(p->zRbu, zRbu, nRbu+1);
- pCsr += nRbu+1;
- if( zState ){
- p->zState = rbuMPrintf(p, "%s", zState);
- }
-
- /* If the first attempt to open the database file fails and the bRetry
- ** flag it set, this means that the db was not opened because it seemed
- ** to be a wal-mode db. But, this may have happened due to an earlier
- ** RBU vacuum operation leaving an old wal file in the directory.
- ** If this is the case, it will have been checkpointed and deleted
- ** when the handle was closed and a second attempt to open the
- ** database may succeed. */
- rbuOpenDatabase(p, &bRetry);
- if( bRetry ){
- rbuOpenDatabase(p, 0);
- }
- }
-
- if( p->rc==SQLITE_OK ){
- pState = rbuLoadState(p);
- assert( pState || p->rc!=SQLITE_OK );
- if( p->rc==SQLITE_OK ){
-
- if( pState->eStage==0 ){
- rbuDeleteOalFile(p);
- rbuInitPhaseOneSteps(p);
- p->eStage = RBU_STAGE_OAL;
- }else{
- p->eStage = pState->eStage;
- p->nPhaseOneStep = pState->nPhaseOneStep;
- }
- p->nProgress = pState->nProgress;
- p->iOalSz = pState->iOalSz;
- }
- }
- assert( p->rc!=SQLITE_OK || p->eStage!=0 );
-
- if( p->rc==SQLITE_OK && p->pTargetFd->pWalFd ){
- if( p->eStage==RBU_STAGE_OAL ){
- p->rc = SQLITE_ERROR;
- p->zErrmsg = sqlite3_mprintf("cannot update wal mode database");
- }else if( p->eStage==RBU_STAGE_MOVE ){
- p->eStage = RBU_STAGE_CKPT;
- p->nStep = 0;
- }
- }
-
- if( p->rc==SQLITE_OK
- && (p->eStage==RBU_STAGE_OAL || p->eStage==RBU_STAGE_MOVE)
- && pState->eStage!=0
- ){
- rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd);
- if( pFd->iCookie!=pState->iCookie ){
- /* At this point (pTargetFd->iCookie) contains the value of the
- ** change-counter cookie (the thing that gets incremented when a
- ** transaction is committed in rollback mode) currently stored on
- ** page 1 of the database file. */
- p->rc = SQLITE_BUSY;
- p->zErrmsg = sqlite3_mprintf("database modified during rbu %s",
- (rbuIsVacuum(p) ? "vacuum" : "update")
- );
- }
- }
-
- if( p->rc==SQLITE_OK ){
- if( p->eStage==RBU_STAGE_OAL ){
- sqlite3 *db = p->dbMain;
- p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, &p->zErrmsg);
-
- /* Point the object iterator at the first object */
- if( p->rc==SQLITE_OK ){
- p->rc = rbuObjIterFirst(p, &p->objiter);
- }
-
- /* If the RBU database contains no data_xxx tables, declare the RBU
- ** update finished. */
- if( p->rc==SQLITE_OK && p->objiter.zTbl==0 ){
- p->rc = SQLITE_DONE;
- p->eStage = RBU_STAGE_DONE;
- }else{
- if( p->rc==SQLITE_OK && pState->eStage==0 && rbuIsVacuum(p) ){
- rbuCopyPragma(p, "page_size");
- rbuCopyPragma(p, "auto_vacuum");
- }
-
- /* Open transactions both databases. The *-oal file is opened or
- ** created at this point. */
- if( p->rc==SQLITE_OK ){
- p->rc = sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg);
- }
-
- /* Check if the main database is a zipvfs db. If it is, set the upper
- ** level pager to use "journal_mode=off". This prevents it from
- ** generating a large journal using a temp file. */
- if( p->rc==SQLITE_OK ){
- int frc = sqlite3_file_control(db, "main", SQLITE_FCNTL_ZIPVFS, 0);
- if( frc==SQLITE_OK ){
- p->rc = sqlite3_exec(
- db, "PRAGMA journal_mode=off",0,0,&p->zErrmsg);
- }
- }
-
- if( p->rc==SQLITE_OK ){
- rbuSetupOal(p, pState);
- }
- }
- }else if( p->eStage==RBU_STAGE_MOVE ){
- /* no-op */
- }else if( p->eStage==RBU_STAGE_CKPT ){
- rbuSetupCheckpoint(p, pState);
- }else if( p->eStage==RBU_STAGE_DONE ){
- p->rc = SQLITE_DONE;
- }else{
- p->rc = SQLITE_CORRUPT;
- }
- }
-
- rbuFreeState(pState);
- }
-
- return p;
-}
-
-/*
-** Allocate and return an RBU handle with all fields zeroed except for the
-** error code, which is set to SQLITE_MISUSE.
-*/
-static sqlite3rbu *rbuMisuseError(void){
- sqlite3rbu *pRet;
- pRet = sqlite3_malloc64(sizeof(sqlite3rbu));
- if( pRet ){
- memset(pRet, 0, sizeof(sqlite3rbu));
- pRet->rc = SQLITE_MISUSE;
- }
- return pRet;
-}
-
-/*
-** Open and return a new RBU handle.
-*/
-sqlite3rbu *sqlite3rbu_open(
- const char *zTarget,
- const char *zRbu,
- const char *zState
-){
- if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); }
- /* TODO: Check that zTarget and zRbu are non-NULL */
- return openRbuHandle(zTarget, zRbu, zState);
-}
-
-/*
-** Open a handle to begin or resume an RBU VACUUM operation.
-*/
-sqlite3rbu *sqlite3rbu_vacuum(
- const char *zTarget,
- const char *zState
-){
- if( zTarget==0 ){ return rbuMisuseError(); }
- /* TODO: Check that both arguments are non-NULL */
- return openRbuHandle(0, zTarget, zState);
-}
-
-/*
-** Return the database handle used by pRbu.
-*/
-sqlite3 *sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){
- sqlite3 *db = 0;
- if( pRbu ){
- db = (bRbu ? pRbu->dbRbu : pRbu->dbMain);
- }
- return db;
-}
-
-
-/*
-** If the error code currently stored in the RBU handle is SQLITE_CONSTRAINT,
-** then edit any error message string so as to remove all occurrences of
-** the pattern "rbu_imp_[0-9]*".
-*/
-static void rbuEditErrmsg(sqlite3rbu *p){
- if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){
- unsigned int i;
- size_t nErrmsg = strlen(p->zErrmsg);
- for(i=0; i<(nErrmsg-8); i++){
- if( memcmp(&p->zErrmsg[i], "rbu_imp_", 8)==0 ){
- int nDel = 8;
- while( p->zErrmsg[i+nDel]>='0' && p->zErrmsg[i+nDel]<='9' ) nDel++;
- memmove(&p->zErrmsg[i], &p->zErrmsg[i+nDel], nErrmsg + 1 - i - nDel);
- nErrmsg -= nDel;
- }
- }
- }
-}
-
-/*
-** Close the RBU handle.
-*/
-int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
- int rc;
- if( p ){
-
- /* Commit the transaction to the *-oal file. */
- if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){
- p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg);
- }
-
- /* Sync the db file if currently doing an incremental checkpoint */
- if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){
- sqlite3_file *pDb = p->pTargetFd->pReal;
- p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL);
- }
-
- rbuSaveState(p, p->eStage);
-
- if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){
- p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg);
- }
-
- /* Close any open statement handles. */
- rbuObjIterFinalize(&p->objiter);
-
- /* If this is an RBU vacuum handle and the vacuum has either finished
- ** successfully or encountered an error, delete the contents of the
- ** state table. This causes the next call to sqlite3rbu_vacuum()
- ** specifying the current target and state databases to start a new
- ** vacuum from scratch. */
- if( rbuIsVacuum(p) && p->rc!=SQLITE_OK && p->dbRbu ){
- int rc2 = sqlite3_exec(p->dbRbu, "DELETE FROM stat.rbu_state", 0, 0, 0);
- if( p->rc==SQLITE_DONE && rc2!=SQLITE_OK ) p->rc = rc2;
- }
-
- /* Close the open database handle and VFS object. */
- sqlite3_close(p->dbRbu);
- sqlite3_close(p->dbMain);
- assert( p->szTemp==0 );
- rbuDeleteVfs(p);
- sqlite3_free(p->aBuf);
- sqlite3_free(p->aFrame);
-
- rbuEditErrmsg(p);
- rc = p->rc;
- if( pzErrmsg ){
- *pzErrmsg = p->zErrmsg;
- }else{
- sqlite3_free(p->zErrmsg);
- }
- sqlite3_free(p->zState);
- sqlite3_free(p);
- }else{
- rc = SQLITE_NOMEM;
- *pzErrmsg = 0;
- }
- return rc;
-}
-
-/*
-** Return the total number of key-value operations (inserts, deletes or
-** updates) that have been performed on the target database since the
-** current RBU update was started.
-*/
-sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu){
- return pRbu->nProgress;
-}
-
-/*
-** Return permyriadage progress indications for the two main stages of
-** an RBU update.
-*/
-void sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){
- const int MAX_PROGRESS = 10000;
- switch( p->eStage ){
- case RBU_STAGE_OAL:
- if( p->nPhaseOneStep>0 ){
- *pnOne = (int)(MAX_PROGRESS * (i64)p->nProgress/(i64)p->nPhaseOneStep);
- }else{
- *pnOne = -1;
- }
- *pnTwo = 0;
- break;
-
- case RBU_STAGE_MOVE:
- *pnOne = MAX_PROGRESS;
- *pnTwo = 0;
- break;
-
- case RBU_STAGE_CKPT:
- *pnOne = MAX_PROGRESS;
- *pnTwo = (int)(MAX_PROGRESS * (i64)p->nStep / (i64)p->nFrame);
- break;
-
- case RBU_STAGE_DONE:
- *pnOne = MAX_PROGRESS;
- *pnTwo = MAX_PROGRESS;
- break;
-
- default:
- assert( 0 );
- }
-}
-
-/*
-** Return the current state of the RBU vacuum or update operation.
-*/
-int sqlite3rbu_state(sqlite3rbu *p){
- int aRes[] = {
- 0, SQLITE_RBU_STATE_OAL, SQLITE_RBU_STATE_MOVE,
- 0, SQLITE_RBU_STATE_CHECKPOINT, SQLITE_RBU_STATE_DONE
- };
-
- assert( RBU_STAGE_OAL==1 );
- assert( RBU_STAGE_MOVE==2 );
- assert( RBU_STAGE_CKPT==4 );
- assert( RBU_STAGE_DONE==5 );
- assert( aRes[RBU_STAGE_OAL]==SQLITE_RBU_STATE_OAL );
- assert( aRes[RBU_STAGE_MOVE]==SQLITE_RBU_STATE_MOVE );
- assert( aRes[RBU_STAGE_CKPT]==SQLITE_RBU_STATE_CHECKPOINT );
- assert( aRes[RBU_STAGE_DONE]==SQLITE_RBU_STATE_DONE );
-
- if( p->rc!=SQLITE_OK && p->rc!=SQLITE_DONE ){
- return SQLITE_RBU_STATE_ERROR;
- }else{
- assert( p->rc!=SQLITE_DONE || p->eStage==RBU_STAGE_DONE );
- assert( p->eStage==RBU_STAGE_OAL
- || p->eStage==RBU_STAGE_MOVE
- || p->eStage==RBU_STAGE_CKPT
- || p->eStage==RBU_STAGE_DONE
- );
- return aRes[p->eStage];
- }
-}
-
-int sqlite3rbu_savestate(sqlite3rbu *p){
- int rc = p->rc;
- if( rc==SQLITE_DONE ) return SQLITE_OK;
-
- assert( p->eStage>=RBU_STAGE_OAL && p->eStage<=RBU_STAGE_DONE );
- if( p->eStage==RBU_STAGE_OAL ){
- assert( rc!=SQLITE_DONE );
- if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0);
- }
-
- /* Sync the db file */
- if( rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){
- sqlite3_file *pDb = p->pTargetFd->pReal;
- rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL);
- }
-
- p->rc = rc;
- rbuSaveState(p, p->eStage);
- rc = p->rc;
-
- if( p->eStage==RBU_STAGE_OAL ){
- assert( rc!=SQLITE_DONE );
- if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0);
- if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, 0);
- if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0,0);
- }
-
- p->rc = rc;
- return rc;
-}
-
-/**************************************************************************
-** Beginning of RBU VFS shim methods. The VFS shim modifies the behaviour
-** of a standard VFS in the following ways:
-**
-** 1. Whenever the first page of a main database file is read or
-** written, the value of the change-counter cookie is stored in
-** rbu_file.iCookie. Similarly, the value of the "write-version"
-** database header field is stored in rbu_file.iWriteVer. This ensures
-** that the values are always trustworthy within an open transaction.
-**
-** 2. Whenever an SQLITE_OPEN_WAL file is opened, the (rbu_file.pWalFd)
-** member variable of the associated database file descriptor is set
-** to point to the new file. A mutex protected linked list of all main
-** db fds opened using a particular RBU VFS is maintained at
-** rbu_vfs.pMain to facilitate this.
-**
-** 3. Using a new file-control "SQLITE_FCNTL_RBU", a main db rbu_file
-** object can be marked as the target database of an RBU update. This
-** turns on the following extra special behaviour:
-**
-** 3a. If xAccess() is called to check if there exists a *-wal file
-** associated with an RBU target database currently in RBU_STAGE_OAL
-** stage (preparing the *-oal file), the following special handling
-** applies:
-**
-** * if the *-wal file does exist, return SQLITE_CANTOPEN. An RBU
-** target database may not be in wal mode already.
-**
-** * if the *-wal file does not exist, set the output parameter to
-** non-zero (to tell SQLite that it does exist) anyway.
-**
-** Then, when xOpen() is called to open the *-wal file associated with
-** the RBU target in RBU_STAGE_OAL stage, instead of opening the *-wal
-** file, the rbu vfs opens the corresponding *-oal file instead.
-**
-** 3b. The *-shm pages returned by xShmMap() for a target db file in
-** RBU_STAGE_OAL mode are actually stored in heap memory. This is to
-** avoid creating a *-shm file on disk. Additionally, xShmLock() calls
-** are no-ops on target database files in RBU_STAGE_OAL mode. This is
-** because assert() statements in some VFS implementations fail if
-** xShmLock() is called before xShmMap().
-**
-** 3c. If an EXCLUSIVE lock is attempted on a target database file in any
-** mode except RBU_STAGE_DONE (all work completed and checkpointed), it
-** fails with an SQLITE_BUSY error. This is to stop RBU connections
-** from automatically checkpointing a *-wal (or *-oal) file from within
-** sqlite3_close().
-**
-** 3d. In RBU_STAGE_CAPTURE mode, all xRead() calls on the wal file, and
-** all xWrite() calls on the target database file perform no IO.
-** Instead the frame and page numbers that would be read and written
-** are recorded. Additionally, successful attempts to obtain exclusive
-** xShmLock() WRITER, CHECKPOINTER and READ0 locks on the target
-** database file are recorded. xShmLock() calls to unlock the same
-** locks are no-ops (so that once obtained, these locks are never
-** relinquished). Finally, calls to xSync() on the target database
-** file fail with SQLITE_INTERNAL errors.
-*/
-
-static void rbuUnlockShm(rbu_file *p){
- assert( p->openFlags & SQLITE_OPEN_MAIN_DB );
- if( p->pRbu ){
- int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock;
- int i;
- for(i=0; i<SQLITE_SHM_NLOCK;i++){
- if( (1<<i) & p->pRbu->mLock ){
- xShmLock(p->pReal, i, 1, SQLITE_SHM_UNLOCK|SQLITE_SHM_EXCLUSIVE);
- }
- }
- p->pRbu->mLock = 0;
- }
-}
-
-/*
-*/
-static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){
- sqlite3rbu *pRbu = pFd->pRbu;
- i64 nDiff = nNew - pFd->sz;
- pRbu->szTemp += nDiff;
- pFd->sz = nNew;
- assert( pRbu->szTemp>=0 );
- if( pRbu->szTempLimit && pRbu->szTemp>pRbu->szTempLimit ) return SQLITE_FULL;
- return SQLITE_OK;
-}
-
-/*
-** Close an rbu file.
-*/
-static int rbuVfsClose(sqlite3_file *pFile){
- rbu_file *p = (rbu_file*)pFile;
- int rc;
- int i;
-
- /* Free the contents of the apShm[] array. And the array itself. */
- for(i=0; i<p->nShm; i++){
- sqlite3_free(p->apShm[i]);
- }
- sqlite3_free(p->apShm);
- p->apShm = 0;
- sqlite3_free(p->zDel);
-
- if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
- rbu_file **pp;
- sqlite3_mutex_enter(p->pRbuVfs->mutex);
- for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext));
- *pp = p->pMainNext;
- sqlite3_mutex_leave(p->pRbuVfs->mutex);
- rbuUnlockShm(p);
- p->pReal->pMethods->xShmUnmap(p->pReal, 0);
- }
- else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
- rbuUpdateTempSize(p, 0);
- }
-
- /* Close the underlying file handle */
- rc = p->pReal->pMethods->xClose(p->pReal);
- return rc;
-}
-
-
-/*
-** Read and return an unsigned 32-bit big-endian integer from the buffer
-** passed as the only argument.
-*/
-static u32 rbuGetU32(u8 *aBuf){
- return ((u32)aBuf[0] << 24)
- + ((u32)aBuf[1] << 16)
- + ((u32)aBuf[2] << 8)
- + ((u32)aBuf[3]);
-}
-
-/*
-** Write an unsigned 32-bit value in big-endian format to the supplied
-** buffer.
-*/
-static void rbuPutU32(u8 *aBuf, u32 iVal){
- aBuf[0] = (iVal >> 24) & 0xFF;
- aBuf[1] = (iVal >> 16) & 0xFF;
- aBuf[2] = (iVal >> 8) & 0xFF;
- aBuf[3] = (iVal >> 0) & 0xFF;
-}
-
-static void rbuPutU16(u8 *aBuf, u16 iVal){
- aBuf[0] = (iVal >> 8) & 0xFF;
- aBuf[1] = (iVal >> 0) & 0xFF;
-}
-
-/*
-** Read data from an rbuVfs-file.
-*/
-static int rbuVfsRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- rbu_file *p = (rbu_file*)pFile;
- sqlite3rbu *pRbu = p->pRbu;
- int rc;
-
- if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){
- assert( p->openFlags & SQLITE_OPEN_WAL );
- rc = rbuCaptureWalRead(p->pRbu, iOfst, iAmt);
- }else{
- if( pRbu && pRbu->eStage==RBU_STAGE_OAL
- && (p->openFlags & SQLITE_OPEN_WAL)
- && iOfst>=pRbu->iOalSz
- ){
- rc = SQLITE_OK;
- memset(zBuf, 0, iAmt);
- }else{
- rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
-#if 1
- /* If this is being called to read the first page of the target
- ** database as part of an rbu vacuum operation, synthesize the
- ** contents of the first page if it does not yet exist. Otherwise,
- ** SQLite will not check for a *-wal file. */
- if( pRbu && rbuIsVacuum(pRbu)
- && rc==SQLITE_IOERR_SHORT_READ && iOfst==0
- && (p->openFlags & SQLITE_OPEN_MAIN_DB)
- && pRbu->rc==SQLITE_OK
- ){
- sqlite3_file *pFd = (sqlite3_file*)pRbu->pRbuFd;
- rc = pFd->pMethods->xRead(pFd, zBuf, iAmt, iOfst);
- if( rc==SQLITE_OK ){
- u8 *aBuf = (u8*)zBuf;
- u32 iRoot = rbuGetU32(&aBuf[52]) ? 1 : 0;
- rbuPutU32(&aBuf[52], iRoot); /* largest root page number */
- rbuPutU32(&aBuf[36], 0); /* number of free pages */
- rbuPutU32(&aBuf[32], 0); /* first page on free list trunk */
- rbuPutU32(&aBuf[28], 1); /* size of db file in pages */
- rbuPutU32(&aBuf[24], pRbu->pRbuFd->iCookie+1); /* Change counter */
-
- if( iAmt>100 ){
- memset(&aBuf[100], 0, iAmt-100);
- rbuPutU16(&aBuf[105], iAmt & 0xFFFF);
- aBuf[100] = 0x0D;
- }
- }
- }
-#endif
- }
- if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){
- /* These look like magic numbers. But they are stable, as they are part
- ** of the definition of the SQLite file format, which may not change. */
- u8 *pBuf = (u8*)zBuf;
- p->iCookie = rbuGetU32(&pBuf[24]);
- p->iWriteVer = pBuf[19];
- }
- }
- return rc;
-}
-
-/*
-** Write data to an rbuVfs-file.
-*/
-static int rbuVfsWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- rbu_file *p = (rbu_file*)pFile;
- sqlite3rbu *pRbu = p->pRbu;
- int rc;
-
- if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){
- assert( p->openFlags & SQLITE_OPEN_MAIN_DB );
- rc = rbuCaptureDbWrite(p->pRbu, iOfst);
- }else{
- if( pRbu ){
- if( pRbu->eStage==RBU_STAGE_OAL
- && (p->openFlags & SQLITE_OPEN_WAL)
- && iOfst>=pRbu->iOalSz
- ){
- pRbu->iOalSz = iAmt + iOfst;
- }else if( p->openFlags & SQLITE_OPEN_DELETEONCLOSE ){
- i64 szNew = iAmt+iOfst;
- if( szNew>p->sz ){
- rc = rbuUpdateTempSize(p, szNew);
- if( rc!=SQLITE_OK ) return rc;
- }
- }
- }
- rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
- if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){
- /* These look like magic numbers. But they are stable, as they are part
- ** of the definition of the SQLite file format, which may not change. */
- u8 *pBuf = (u8*)zBuf;
- p->iCookie = rbuGetU32(&pBuf[24]);
- p->iWriteVer = pBuf[19];
- }
- }
- return rc;
-}
-
-/*
-** Truncate an rbuVfs-file.
-*/
-static int rbuVfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
- rbu_file *p = (rbu_file*)pFile;
- if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
- int rc = rbuUpdateTempSize(p, size);
- if( rc!=SQLITE_OK ) return rc;
- }
- return p->pReal->pMethods->xTruncate(p->pReal, size);
-}
-
-/*
-** Sync an rbuVfs-file.
-*/
-static int rbuVfsSync(sqlite3_file *pFile, int flags){
- rbu_file *p = (rbu_file *)pFile;
- if( p->pRbu && p->pRbu->eStage==RBU_STAGE_CAPTURE ){
- if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
- return SQLITE_INTERNAL;
- }
- return SQLITE_OK;
- }
- return p->pReal->pMethods->xSync(p->pReal, flags);
-}
-
-/*
-** Return the current file-size of an rbuVfs-file.
-*/
-static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- rbu_file *p = (rbu_file *)pFile;
- int rc;
- rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
-
- /* If this is an RBU vacuum operation and this is the target database,
- ** pretend that it has at least one page. Otherwise, SQLite will not
- ** check for the existance of a *-wal file. rbuVfsRead() contains
- ** similar logic. */
- if( rc==SQLITE_OK && *pSize==0
- && p->pRbu && rbuIsVacuum(p->pRbu)
- && (p->openFlags & SQLITE_OPEN_MAIN_DB)
- ){
- *pSize = 1024;
- }
- return rc;
-}
-
-/*
-** Lock an rbuVfs-file.
-*/
-static int rbuVfsLock(sqlite3_file *pFile, int eLock){
- rbu_file *p = (rbu_file*)pFile;
- sqlite3rbu *pRbu = p->pRbu;
- int rc = SQLITE_OK;
-
- assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
- if( eLock==SQLITE_LOCK_EXCLUSIVE
- && (p->bNolock || (pRbu && pRbu->eStage!=RBU_STAGE_DONE))
- ){
- /* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this
- ** prevents it from checkpointing the database from sqlite3_close(). */
- rc = SQLITE_BUSY;
- }else{
- rc = p->pReal->pMethods->xLock(p->pReal, eLock);
- }
-
- return rc;
-}
-
-/*
-** Unlock an rbuVfs-file.
-*/
-static int rbuVfsUnlock(sqlite3_file *pFile, int eLock){
- rbu_file *p = (rbu_file *)pFile;
- return p->pReal->pMethods->xUnlock(p->pReal, eLock);
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an rbuVfs-file.
-*/
-static int rbuVfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- rbu_file *p = (rbu_file *)pFile;
- return p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
-}
-
-/*
-** File control method. For custom operations on an rbuVfs-file.
-*/
-static int rbuVfsFileControl(sqlite3_file *pFile, int op, void *pArg){
- rbu_file *p = (rbu_file *)pFile;
- int (*xControl)(sqlite3_file*,int,void*) = p->pReal->pMethods->xFileControl;
- int rc;
-
- assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB)
- || p->openFlags & (SQLITE_OPEN_TRANSIENT_DB|SQLITE_OPEN_TEMP_JOURNAL)
- );
- if( op==SQLITE_FCNTL_RBU ){
- sqlite3rbu *pRbu = (sqlite3rbu*)pArg;
-
- /* First try to find another RBU vfs lower down in the vfs stack. If
- ** one is found, this vfs will operate in pass-through mode. The lower
- ** level vfs will do the special RBU handling. */
- rc = xControl(p->pReal, op, pArg);
-
- if( rc==SQLITE_NOTFOUND ){
- /* Now search for a zipvfs instance lower down in the VFS stack. If
- ** one is found, this is an error. */
- void *dummy = 0;
- rc = xControl(p->pReal, SQLITE_FCNTL_ZIPVFS, &dummy);
- if( rc==SQLITE_OK ){
- rc = SQLITE_ERROR;
- pRbu->zErrmsg = sqlite3_mprintf("rbu/zipvfs setup error");
- }else if( rc==SQLITE_NOTFOUND ){
- pRbu->pTargetFd = p;
- p->pRbu = pRbu;
- if( p->pWalFd ) p->pWalFd->pRbu = pRbu;
- rc = SQLITE_OK;
- }
- }
- return rc;
- }
- else if( op==SQLITE_FCNTL_RBUCNT ){
- sqlite3rbu *pRbu = (sqlite3rbu*)pArg;
- pRbu->nRbu++;
- pRbu->pRbuFd = p;
- p->bNolock = 1;
- }
-
- rc = xControl(p->pReal, op, pArg);
- if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
- rbu_vfs *pRbuVfs = p->pRbuVfs;
- char *zIn = *(char**)pArg;
- char *zOut = sqlite3_mprintf("rbu(%s)/%z", pRbuVfs->base.zName, zIn);
- *(char**)pArg = zOut;
- if( zOut==0 ) rc = SQLITE_NOMEM;
- }
-
- return rc;
-}
-
-/*
-** Return the sector-size in bytes for an rbuVfs-file.
-*/
-static int rbuVfsSectorSize(sqlite3_file *pFile){
- rbu_file *p = (rbu_file *)pFile;
- return p->pReal->pMethods->xSectorSize(p->pReal);
-}
-
-/*
-** Return the device characteristic flags supported by an rbuVfs-file.
-*/
-static int rbuVfsDeviceCharacteristics(sqlite3_file *pFile){
- rbu_file *p = (rbu_file *)pFile;
- return p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
-}
-
-/*
-** Take or release a shared-memory lock.
-*/
-static int rbuVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
- rbu_file *p = (rbu_file*)pFile;
- sqlite3rbu *pRbu = p->pRbu;
- int rc = SQLITE_OK;
-
-#ifdef SQLITE_AMALGAMATION
- assert( WAL_CKPT_LOCK==1 );
-#endif
-
- assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
- if( pRbu && (pRbu->eStage==RBU_STAGE_OAL || pRbu->eStage==RBU_STAGE_MOVE) ){
- /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from
- ** taking this lock also prevents any checkpoints from occurring.
- ** todo: really, it's not clear why this might occur, as
- ** wal_autocheckpoint ought to be turned off. */
- if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY;
- }else{
- int bCapture = 0;
- if( n==1 && (flags & SQLITE_SHM_EXCLUSIVE)
- && pRbu && pRbu->eStage==RBU_STAGE_CAPTURE
- && (ofst==WAL_LOCK_WRITE || ofst==WAL_LOCK_CKPT || ofst==WAL_LOCK_READ0)
- ){
- bCapture = 1;
- }
-
- if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){
- rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
- if( bCapture && rc==SQLITE_OK ){
- pRbu->mLock |= (1 << ofst);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Obtain a pointer to a mapping of a single 32KiB page of the *-shm file.
-*/
-static int rbuVfsShmMap(
- sqlite3_file *pFile,
- int iRegion,
- int szRegion,
- int isWrite,
- void volatile **pp
-){
- rbu_file *p = (rbu_file*)pFile;
- int rc = SQLITE_OK;
- int eStage = (p->pRbu ? p->pRbu->eStage : 0);
-
- /* If not in RBU_STAGE_OAL, allow this call to pass through. Or, if this
- ** rbu is in the RBU_STAGE_OAL state, use heap memory for *-shm space
- ** instead of a file on disk. */
- assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
- if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){
- if( iRegion<=p->nShm ){
- int nByte = (iRegion+1) * sizeof(char*);
- char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte);
- if( apNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm));
- p->apShm = apNew;
- p->nShm = iRegion+1;
- }
- }
-
- if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){
- char *pNew = (char*)sqlite3_malloc64(szRegion);
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pNew, 0, szRegion);
- p->apShm[iRegion] = pNew;
- }
- }
-
- if( rc==SQLITE_OK ){
- *pp = p->apShm[iRegion];
- }else{
- *pp = 0;
- }
- }else{
- assert( p->apShm==0 );
- rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
- }
-
- return rc;
-}
-
-/*
-** Memory barrier.
-*/
-static void rbuVfsShmBarrier(sqlite3_file *pFile){
- rbu_file *p = (rbu_file *)pFile;
- p->pReal->pMethods->xShmBarrier(p->pReal);
-}
-
-/*
-** The xShmUnmap method.
-*/
-static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){
- rbu_file *p = (rbu_file*)pFile;
- int rc = SQLITE_OK;
- int eStage = (p->pRbu ? p->pRbu->eStage : 0);
-
- assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
- if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){
- /* no-op */
- }else{
- /* Release the checkpointer and writer locks */
- rbuUnlockShm(p);
- rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
- }
- return rc;
-}
-
-/*
-** Given that zWal points to a buffer containing a wal file name passed to
-** either the xOpen() or xAccess() VFS method, return a pointer to the
-** file-handle opened by the same database connection on the corresponding
-** database file.
-*/
-static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){
- rbu_file *pDb;
- sqlite3_mutex_enter(pRbuVfs->mutex);
- for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
- sqlite3_mutex_leave(pRbuVfs->mutex);
- return pDb;
-}
-
-/*
-** A main database named zName has just been opened. The following
-** function returns a pointer to a buffer owned by SQLite that contains
-** the name of the *-wal file this db connection will use. SQLite
-** happens to pass a pointer to this buffer when using xAccess()
-** or xOpen() to operate on the *-wal file.
-*/
-static const char *rbuMainToWal(const char *zName, int flags){
- int n = (int)strlen(zName);
- const char *z = &zName[n];
- if( flags & SQLITE_OPEN_URI ){
- int odd = 0;
- while( 1 ){
- if( z[0]==0 ){
- odd = 1 - odd;
- if( odd && z[1]==0 ) break;
- }
- z++;
- }
- z += 2;
- }else{
- while( *z==0 ) z++;
- }
- z += (n + 8 + 1);
- return z;
-}
-
-/*
-** Open an rbu file handle.
-*/
-static int rbuVfsOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- static sqlite3_io_methods rbuvfs_io_methods = {
- 2, /* iVersion */
- rbuVfsClose, /* xClose */
- rbuVfsRead, /* xRead */
- rbuVfsWrite, /* xWrite */
- rbuVfsTruncate, /* xTruncate */
- rbuVfsSync, /* xSync */
- rbuVfsFileSize, /* xFileSize */
- rbuVfsLock, /* xLock */
- rbuVfsUnlock, /* xUnlock */
- rbuVfsCheckReservedLock, /* xCheckReservedLock */
- rbuVfsFileControl, /* xFileControl */
- rbuVfsSectorSize, /* xSectorSize */
- rbuVfsDeviceCharacteristics, /* xDeviceCharacteristics */
- rbuVfsShmMap, /* xShmMap */
- rbuVfsShmLock, /* xShmLock */
- rbuVfsShmBarrier, /* xShmBarrier */
- rbuVfsShmUnmap, /* xShmUnmap */
- 0, 0 /* xFetch, xUnfetch */
- };
- rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs;
- sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs;
- rbu_file *pFd = (rbu_file *)pFile;
- int rc = SQLITE_OK;
- const char *zOpen = zName;
- int oflags = flags;
-
- memset(pFd, 0, sizeof(rbu_file));
- pFd->pReal = (sqlite3_file*)&pFd[1];
- pFd->pRbuVfs = pRbuVfs;
- pFd->openFlags = flags;
- if( zName ){
- if( flags & SQLITE_OPEN_MAIN_DB ){
- /* A main database has just been opened. The following block sets
- ** (pFd->zWal) to point to a buffer owned by SQLite that contains
- ** the name of the *-wal file this db connection will use. SQLite
- ** happens to pass a pointer to this buffer when using xAccess()
- ** or xOpen() to operate on the *-wal file. */
- pFd->zWal = rbuMainToWal(zName, flags);
- }
- else if( flags & SQLITE_OPEN_WAL ){
- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName);
- if( pDb ){
- if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
- /* This call is to open a *-wal file. Intead, open the *-oal. This
- ** code ensures that the string passed to xOpen() is terminated by a
- ** pair of '\0' bytes in case the VFS attempts to extract a URI
- ** parameter from it. */
- const char *zBase = zName;
- size_t nCopy;
- char *zCopy;
- if( rbuIsVacuum(pDb->pRbu) ){
- zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
- zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI);
- }
- nCopy = strlen(zBase);
- zCopy = sqlite3_malloc64(nCopy+2);
- if( zCopy ){
- memcpy(zCopy, zBase, nCopy);
- zCopy[nCopy-3] = 'o';
- zCopy[nCopy] = '\0';
- zCopy[nCopy+1] = '\0';
- zOpen = (const char*)(pFd->zDel = zCopy);
- }else{
- rc = SQLITE_NOMEM;
- }
- pFd->pRbu = pDb->pRbu;
- }
- pDb->pWalFd = pFd;
- }
- }
- }else{
- pFd->pRbu = pRbuVfs->pRbu;
- }
-
- if( oflags & SQLITE_OPEN_MAIN_DB
- && sqlite3_uri_boolean(zName, "rbu_memory", 0)
- ){
- assert( oflags & SQLITE_OPEN_MAIN_DB );
- oflags = SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
- SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
- zOpen = 0;
- }
-
- if( rc==SQLITE_OK ){
- rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, oflags, pOutFlags);
- }
- if( pFd->pReal->pMethods ){
- /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods
- ** pointer and, if the file is a main database file, link it into the
- ** mutex protected linked list of all such files. */
- pFile->pMethods = &rbuvfs_io_methods;
- if( flags & SQLITE_OPEN_MAIN_DB ){
- sqlite3_mutex_enter(pRbuVfs->mutex);
- pFd->pMainNext = pRbuVfs->pMain;
- pRbuVfs->pMain = pFd;
- sqlite3_mutex_leave(pRbuVfs->mutex);
- }
- }else{
- sqlite3_free(pFd->zDel);
- }
-
- return rc;
-}
-
-/*
-** Delete the file located at zPath.
-*/
-static int rbuVfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- return pRealVfs->xDelete(pRealVfs, zPath, dirSync);
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int rbuVfsAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs;
- sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs;
- int rc;
-
- rc = pRealVfs->xAccess(pRealVfs, zPath, flags, pResOut);
-
- /* If this call is to check if a *-wal file associated with an RBU target
- ** database connection exists, and the RBU update is in RBU_STAGE_OAL,
- ** the following special handling is activated:
- **
- ** a) if the *-wal file does exist, return SQLITE_CANTOPEN. This
- ** ensures that the RBU extension never tries to update a database
- ** in wal mode, even if the first page of the database file has
- ** been damaged.
- **
- ** b) if the *-wal file does not exist, claim that it does anyway,
- ** causing SQLite to call xOpen() to open it. This call will also
- ** be intercepted (see the rbuVfsOpen() function) and the *-oal
- ** file opened instead.
- */
- if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath);
- if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
- if( *pResOut ){
- rc = SQLITE_CANTOPEN;
- }else{
- sqlite3_int64 sz = 0;
- rc = rbuVfsFileSize(&pDb->base, &sz);
- *pResOut = (sz>0);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
-*/
-static int rbuVfsFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- return pRealVfs->xFullPathname(pRealVfs, zPath, nOut, zOut);
-}
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *rbuVfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- return pRealVfs->xDlOpen(pRealVfs, zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void rbuVfsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- pRealVfs->xDlError(pRealVfs, nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*rbuVfsDlSym(
- sqlite3_vfs *pVfs,
- void *pArg,
- const char *zSym
-))(void){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- return pRealVfs->xDlSym(pRealVfs, pArg, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void rbuVfsDlClose(sqlite3_vfs *pVfs, void *pHandle){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- pRealVfs->xDlClose(pRealVfs, pHandle);
-}
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int rbuVfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- return pRealVfs->xRandomness(pRealVfs, nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int rbuVfsSleep(sqlite3_vfs *pVfs, int nMicro){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- return pRealVfs->xSleep(pRealVfs, nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int rbuVfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs;
- return pRealVfs->xCurrentTime(pRealVfs, pTimeOut);
-}
-
-/*
-** No-op.
-*/
-static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){
- return 0;
-}
-
-/*
-** Deregister and destroy an RBU vfs created by an earlier call to
-** sqlite3rbu_create_vfs().
-*/
-void sqlite3rbu_destroy_vfs(const char *zName){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
- if( pVfs && pVfs->xOpen==rbuVfsOpen ){
- sqlite3_mutex_free(((rbu_vfs*)pVfs)->mutex);
- sqlite3_vfs_unregister(pVfs);
- sqlite3_free(pVfs);
- }
-}
-
-/*
-** Create an RBU VFS named zName that accesses the underlying file-system
-** via existing VFS zParent. The new object is registered as a non-default
-** VFS with SQLite before returning.
-*/
-int sqlite3rbu_create_vfs(const char *zName, const char *zParent){
-
- /* Template for VFS */
- static sqlite3_vfs vfs_template = {
- 1, /* iVersion */
- 0, /* szOsFile */
- 0, /* mxPathname */
- 0, /* pNext */
- 0, /* zName */
- 0, /* pAppData */
- rbuVfsOpen, /* xOpen */
- rbuVfsDelete, /* xDelete */
- rbuVfsAccess, /* xAccess */
- rbuVfsFullPathname, /* xFullPathname */
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- rbuVfsDlOpen, /* xDlOpen */
- rbuVfsDlError, /* xDlError */
- rbuVfsDlSym, /* xDlSym */
- rbuVfsDlClose, /* xDlClose */
-#else
- 0, 0, 0, 0,
-#endif
-
- rbuVfsRandomness, /* xRandomness */
- rbuVfsSleep, /* xSleep */
- rbuVfsCurrentTime, /* xCurrentTime */
- rbuVfsGetLastError, /* xGetLastError */
- 0, /* xCurrentTimeInt64 (version 2) */
- 0, 0, 0 /* Unimplemented version 3 methods */
- };
-
- rbu_vfs *pNew = 0; /* Newly allocated VFS */
- int rc = SQLITE_OK;
- size_t nName;
- size_t nByte;
-
- nName = strlen(zName);
- nByte = sizeof(rbu_vfs) + nName + 1;
- pNew = (rbu_vfs*)sqlite3_malloc64(nByte);
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_vfs *pParent; /* Parent VFS */
- memset(pNew, 0, nByte);
- pParent = sqlite3_vfs_find(zParent);
- if( pParent==0 ){
- rc = SQLITE_NOTFOUND;
- }else{
- char *zSpace;
- memcpy(&pNew->base, &vfs_template, sizeof(sqlite3_vfs));
- pNew->base.mxPathname = pParent->mxPathname;
- pNew->base.szOsFile = sizeof(rbu_file) + pParent->szOsFile;
- pNew->pRealVfs = pParent;
- pNew->base.zName = (const char*)(zSpace = (char*)&pNew[1]);
- memcpy(zSpace, zName, nName);
-
- /* Allocate the mutex and register the new VFS (not as the default) */
- pNew->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
- if( pNew->mutex==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_vfs_register(&pNew->base, 0);
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_mutex_free(pNew->mutex);
- sqlite3_free(pNew);
- }
- }
-
- return rc;
-}
-
-/*
-** Configure the aggregate temp file size limit for this RBU handle.
-*/
-sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu *pRbu, sqlite3_int64 n){
- if( n>=0 ){
- pRbu->szTempLimit = n;
- }
- return pRbu->szTempLimit;
-}
-
-sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu *pRbu){
- return pRbu->szTemp;
-}
-
-
-/**************************************************************************/
-
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/sqlite3rbu.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/sqlite3rbu.h
deleted file mode 100644
index 1acbcca4695..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/sqlite3rbu.h
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
-** 2014 August 30
-**
-** 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 contains the public interface for the RBU extension.
-*/
-
-/*
-** SUMMARY
-**
-** Writing a transaction containing a large number of operations on
-** b-tree indexes that are collectively larger than the available cache
-** memory can be very inefficient.
-**
-** The problem is that in order to update a b-tree, the leaf page (at least)
-** containing the entry being inserted or deleted must be modified. If the
-** working set of leaves is larger than the available cache memory, then a
-** single leaf that is modified more than once as part of the transaction
-** may be loaded from or written to the persistent media multiple times.
-** Additionally, because the index updates are likely to be applied in
-** random order, access to pages within the database is also likely to be in
-** random order, which is itself quite inefficient.
-**
-** One way to improve the situation is to sort the operations on each index
-** by index key before applying them to the b-tree. This leads to an IO
-** pattern that resembles a single linear scan through the index b-tree,
-** and all but guarantees each modified leaf page is loaded and stored
-** exactly once. SQLite uses this trick to improve the performance of
-** CREATE INDEX commands. This extension allows it to be used to improve
-** the performance of large transactions on existing databases.
-**
-** Additionally, this extension allows the work involved in writing the
-** large transaction to be broken down into sub-transactions performed
-** sequentially by separate processes. This is useful if the system cannot
-** guarantee that a single update process will run for long enough to apply
-** the entire update, for example because the update is being applied on a
-** mobile device that is frequently rebooted. Even after the writer process
-** has committed one or more sub-transactions, other database clients continue
-** to read from the original database snapshot. In other words, partially
-** applied transactions are not visible to other clients.
-**
-** "RBU" stands for "Resumable Bulk Update". As in a large database update
-** transmitted via a wireless network to a mobile device. A transaction
-** applied using this extension is hence refered to as an "RBU update".
-**
-**
-** LIMITATIONS
-**
-** An "RBU update" transaction is subject to the following limitations:
-**
-** * The transaction must consist of INSERT, UPDATE and DELETE operations
-** only.
-**
-** * INSERT statements may not use any default values.
-**
-** * UPDATE and DELETE statements must identify their target rows by
-** non-NULL PRIMARY KEY values. Rows with NULL values stored in PRIMARY
-** KEY fields may not be updated or deleted. If the table being written
-** has no PRIMARY KEY, affected rows must be identified by rowid.
-**
-** * UPDATE statements may not modify PRIMARY KEY columns.
-**
-** * No triggers will be fired.
-**
-** * No foreign key violations are detected or reported.
-**
-** * CHECK constraints are not enforced.
-**
-** * No constraint handling mode except for "OR ROLLBACK" is supported.
-**
-**
-** PREPARATION
-**
-** An "RBU update" is stored as a separate SQLite database. A database
-** containing an RBU update is an "RBU database". For each table in the
-** target database to be updated, the RBU database should contain a table
-** named "data_<target name>" containing the same set of columns as the
-** target table, and one more - "rbu_control". The data_% table should
-** have no PRIMARY KEY or UNIQUE constraints, but each column should have
-** the same type as the corresponding column in the target database.
-** The "rbu_control" column should have no type at all. For example, if
-** the target database contains:
-**
-** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE);
-**
-** Then the RBU database should contain:
-**
-** CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control);
-**
-** The order of the columns in the data_% table does not matter.
-**
-** Instead of a regular table, the RBU database may also contain virtual
-** tables or view named using the data_<target> naming scheme.
-**
-** Instead of the plain data_<target> naming scheme, RBU database tables
-** may also be named data<integer>_<target>, where <integer> is any sequence
-** of zero or more numeric characters (0-9). This can be significant because
-** tables within the RBU database are always processed in order sorted by
-** name. By judicious selection of the <integer> portion of the names
-** of the RBU tables the user can therefore control the order in which they
-** are processed. This can be useful, for example, to ensure that "external
-** content" FTS4 tables are updated before their underlying content tables.
-**
-** If the target database table is a virtual table or a table that has no
-** PRIMARY KEY declaration, the data_% table must also contain a column
-** named "rbu_rowid". This column is mapped to the tables implicit primary
-** key column - "rowid". Virtual tables for which the "rowid" column does
-** not function like a primary key value cannot be updated using RBU. For
-** example, if the target db contains either of the following:
-**
-** CREATE VIRTUAL TABLE x1 USING fts3(a, b);
-** CREATE TABLE x1(a, b)
-**
-** then the RBU database should contain:
-**
-** CREATE TABLE data_x1(a, b, rbu_rowid, rbu_control);
-**
-** All non-hidden columns (i.e. all columns matched by "SELECT *") of the
-** target table must be present in the input table. For virtual tables,
-** hidden columns are optional - they are updated by RBU if present in
-** the input table, or not otherwise. For example, to write to an fts4
-** table with a hidden languageid column such as:
-**
-** CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid');
-**
-** Either of the following input table schemas may be used:
-**
-** CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control);
-** CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control);
-**
-** For each row to INSERT into the target database as part of the RBU
-** update, the corresponding data_% table should contain a single record
-** with the "rbu_control" column set to contain integer value 0. The
-** other columns should be set to the values that make up the new record
-** to insert.
-**
-** If the target database table has an INTEGER PRIMARY KEY, it is not
-** possible to insert a NULL value into the IPK column. Attempting to
-** do so results in an SQLITE_MISMATCH error.
-**
-** For each row to DELETE from the target database as part of the RBU
-** update, the corresponding data_% table should contain a single record
-** with the "rbu_control" column set to contain integer value 1. The
-** real primary key values of the row to delete should be stored in the
-** corresponding columns of the data_% table. The values stored in the
-** other columns are not used.
-**
-** For each row to UPDATE from the target database as part of the RBU
-** update, the corresponding data_% table should contain a single record
-** with the "rbu_control" column set to contain a value of type text.
-** The real primary key values identifying the row to update should be
-** stored in the corresponding columns of the data_% table row, as should
-** the new values of all columns being update. The text value in the
-** "rbu_control" column must contain the same number of characters as
-** there are columns in the target database table, and must consist entirely
-** of 'x' and '.' characters (or in some special cases 'd' - see below). For
-** each column that is being updated, the corresponding character is set to
-** 'x'. For those that remain as they are, the corresponding character of the
-** rbu_control value should be set to '.'. For example, given the tables
-** above, the update statement:
-**
-** UPDATE t1 SET c = 'usa' WHERE a = 4;
-**
-** is represented by the data_t1 row created by:
-**
-** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..x');
-**
-** Instead of an 'x' character, characters of the rbu_control value specified
-** for UPDATEs may also be set to 'd'. In this case, instead of updating the
-** target table with the value stored in the corresponding data_% column, the
-** user-defined SQL function "rbu_delta()" is invoked and the result stored in
-** the target table column. rbu_delta() is invoked with two arguments - the
-** original value currently stored in the target table column and the
-** value specified in the data_xxx table.
-**
-** For example, this row:
-**
-** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d');
-**
-** is similar to an UPDATE statement such as:
-**
-** UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4;
-**
-** Finally, if an 'f' character appears in place of a 'd' or 's' in an
-** ota_control string, the contents of the data_xxx table column is assumed
-** to be a "fossil delta" - a patch to be applied to a blob value in the
-** format used by the fossil source-code management system. In this case
-** the existing value within the target database table must be of type BLOB.
-** It is replaced by the result of applying the specified fossil delta to
-** itself.
-**
-** If the target database table is a virtual table or a table with no PRIMARY
-** KEY, the rbu_control value should not include a character corresponding
-** to the rbu_rowid value. For example, this:
-**
-** INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control)
-** VALUES(NULL, 'usa', 12, '.x');
-**
-** causes a result similar to:
-**
-** UPDATE ft1 SET b = 'usa' WHERE rowid = 12;
-**
-** The data_xxx tables themselves should have no PRIMARY KEY declarations.
-** However, RBU is more efficient if reading the rows in from each data_xxx
-** table in "rowid" order is roughly the same as reading them sorted by
-** the PRIMARY KEY of the corresponding target database table. In other
-** words, rows should be sorted using the destination table PRIMARY KEY
-** fields before they are inserted into the data_xxx tables.
-**
-** USAGE
-**
-** The API declared below allows an application to apply an RBU update
-** stored on disk to an existing target database. Essentially, the
-** application:
-**
-** 1) Opens an RBU handle using the sqlite3rbu_open() function.
-**
-** 2) Registers any required virtual table modules with the database
-** handle returned by sqlite3rbu_db(). Also, if required, register
-** the rbu_delta() implementation.
-**
-** 3) Calls the sqlite3rbu_step() function one or more times on
-** the new handle. Each call to sqlite3rbu_step() performs a single
-** b-tree operation, so thousands of calls may be required to apply
-** a complete update.
-**
-** 4) Calls sqlite3rbu_close() to close the RBU update handle. If
-** sqlite3rbu_step() has been called enough times to completely
-** apply the update to the target database, then the RBU database
-** is marked as fully applied. Otherwise, the state of the RBU
-** update application is saved in the RBU database for later
-** resumption.
-**
-** See comments below for more detail on APIs.
-**
-** If an update is only partially applied to the target database by the
-** time sqlite3rbu_close() is called, various state information is saved
-** within the RBU database. This allows subsequent processes to automatically
-** resume the RBU update from where it left off.
-**
-** To remove all RBU extension state information, returning an RBU database
-** to its original contents, it is sufficient to drop all tables that begin
-** with the prefix "rbu_"
-**
-** DATABASE LOCKING
-**
-** An RBU update may not be applied to a database in WAL mode. Attempting
-** to do so is an error (SQLITE_ERROR).
-**
-** While an RBU handle is open, a SHARED lock may be held on the target
-** database file. This means it is possible for other clients to read the
-** database, but not to write it.
-**
-** If an RBU update is started and then suspended before it is completed,
-** then an external client writes to the database, then attempting to resume
-** the suspended RBU update is also an error (SQLITE_BUSY).
-*/
-
-#ifndef _SQLITE3RBU_H
-#define _SQLITE3RBU_H
-
-#include "sqlite3.h" /* Required for error code definitions */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct sqlite3rbu sqlite3rbu;
-
-/*
-** Open an RBU handle.
-**
-** Argument zTarget is the path to the target database. Argument zRbu is
-** the path to the RBU database. Each call to this function must be matched
-** by a call to sqlite3rbu_close(). When opening the databases, RBU passes
-** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget
-** or zRbu begin with "file:", it will be interpreted as an SQLite
-** database URI, not a regular file name.
-**
-** If the zState argument is passed a NULL value, the RBU extension stores
-** the current state of the update (how many rows have been updated, which
-** indexes are yet to be updated etc.) within the RBU database itself. This
-** can be convenient, as it means that the RBU application does not need to
-** organize removing a separate state file after the update is concluded.
-** Or, if zState is non-NULL, it must be a path to a database file in which
-** the RBU extension can store the state of the update.
-**
-** When resuming an RBU update, the zState argument must be passed the same
-** value as when the RBU update was started.
-**
-** Once the RBU update is finished, the RBU extension does not
-** automatically remove any zState database file, even if it created it.
-**
-** By default, RBU uses the default VFS to access the files on disk. To
-** use a VFS other than the default, an SQLite "file:" URI containing a
-** "vfs=..." option may be passed as the zTarget option.
-**
-** IMPORTANT NOTE FOR ZIPVFS USERS: The RBU extension works with all of
-** SQLite's built-in VFSs, including the multiplexor VFS. However it does
-** not work out of the box with zipvfs. Refer to the comment describing
-** the zipvfs_create_vfs() API below for details on using RBU with zipvfs.
-*/
-SQLITE_API sqlite3rbu *sqlite3rbu_open(
- const char *zTarget,
- const char *zRbu,
- const char *zState
-);
-
-/*
-** Open an RBU handle to perform an RBU vacuum on database file zTarget.
-** An RBU vacuum is similar to SQLite's built-in VACUUM command, except
-** that it can be suspended and resumed like an RBU update.
-**
-** The second argument to this function identifies a database in which
-** to store the state of the RBU vacuum operation if it is suspended. The
-** first time sqlite3rbu_vacuum() is called, to start an RBU vacuum
-** operation, the state database should either not exist or be empty
-** (contain no tables). If an RBU vacuum is suspended by calling
-** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has
-** returned SQLITE_DONE, the vacuum state is stored in the state database.
-** The vacuum can be resumed by calling this function to open a new RBU
-** handle specifying the same target and state databases.
-**
-** If the second argument passed to this function is NULL, then the
-** name of the state database is "<database>-vacuum", where <database>
-** is the name of the target database file. In this case, on UNIX, if the
-** state database is not already present in the file-system, it is created
-** with the same permissions as the target db is made.
-**
-** This function does not delete the state database after an RBU vacuum
-** is completed, even if it created it. However, if the call to
-** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
-** of the state tables within the state database are zeroed. This way,
-** the next call to sqlite3rbu_vacuum() opens a handle that starts a
-** new RBU vacuum operation.
-**
-** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
-** describing the sqlite3rbu_create_vfs() API function below for
-** a description of the complications associated with using RBU with
-** zipvfs databases.
-*/
-SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
- const char *zTarget,
- const char *zState
-);
-
-/*
-** Configure a limit for the amount of temp space that may be used by
-** the RBU handle passed as the first argument. The new limit is specified
-** in bytes by the second parameter. If it is positive, the limit is updated.
-** If the second parameter to this function is passed zero, then the limit
-** is removed entirely. If the second parameter is negative, the limit is
-** not modified (this is useful for querying the current limit).
-**
-** In all cases the returned value is the current limit in bytes (zero
-** indicates unlimited).
-**
-** If the temp space limit is exceeded during operation, an SQLITE_FULL
-** error is returned.
-*/
-SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu*, sqlite3_int64);
-
-/*
-** Return the current amount of temp file space, in bytes, currently used by
-** the RBU handle passed as the only argument.
-*/
-SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu*);
-
-/*
-** Internally, each RBU connection uses a separate SQLite database
-** connection to access the target and rbu update databases. This
-** API allows the application direct access to these database handles.
-**
-** The first argument passed to this function must be a valid, open, RBU
-** handle. The second argument should be passed zero to access the target
-** database handle, or non-zero to access the rbu update database handle.
-** Accessing the underlying database handles may be useful in the
-** following scenarios:
-**
-** * If any target tables are virtual tables, it may be necessary to
-** call sqlite3_create_module() on the target database handle to
-** register the required virtual table implementations.
-**
-** * If the data_xxx tables in the RBU source database are virtual
-** tables, the application may need to call sqlite3_create_module() on
-** the rbu update db handle to any required virtual table
-** implementations.
-**
-** * If the application uses the "rbu_delta()" feature described above,
-** it must use sqlite3_create_function() or similar to register the
-** rbu_delta() implementation with the target database handle.
-**
-** If an error has occurred, either while opening or stepping the RBU object,
-** this function may return NULL. The error code and message may be collected
-** when sqlite3rbu_close() is called.
-**
-** Database handles returned by this function remain valid until the next
-** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db().
-*/
-SQLITE_API sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu);
-
-/*
-** Do some work towards applying the RBU update to the target db.
-**
-** Return SQLITE_DONE if the update has been completely applied, or
-** SQLITE_OK if no error occurs but there remains work to do to apply
-** the RBU update. If an error does occur, some other error code is
-** returned.
-**
-** Once a call to sqlite3rbu_step() has returned a value other than
-** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops
-** that immediately return the same value.
-*/
-SQLITE_API int sqlite3rbu_step(sqlite3rbu *pRbu);
-
-/*
-** Force RBU to save its state to disk.
-**
-** If a power failure or application crash occurs during an update, following
-** system recovery RBU may resume the update from the point at which the state
-** was last saved. In other words, from the most recent successful call to
-** sqlite3rbu_close() or this function.
-**
-** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
-*/
-SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu);
-
-/*
-** Close an RBU handle.
-**
-** If the RBU update has been completely applied, mark the RBU database
-** as fully applied. Otherwise, assuming no error has occurred, save the
-** current state of the RBU update appliation to the RBU database.
-**
-** If an error has already occurred as part of an sqlite3rbu_step()
-** or sqlite3rbu_open() call, or if one occurs within this function, an
-** SQLite error code is returned. Additionally, if pzErrmsg is not NULL,
-** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted
-** English language error message. It is the responsibility of the caller to
-** eventually free any such buffer using sqlite3_free().
-**
-** Otherwise, if no error occurs, this function returns SQLITE_OK if the
-** update has been partially applied, or SQLITE_DONE if it has been
-** completely applied.
-*/
-SQLITE_API int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg);
-
-/*
-** Return the total number of key-value operations (inserts, deletes or
-** updates) that have been performed on the target database since the
-** current RBU update was started.
-*/
-SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu);
-
-/*
-** Obtain permyriadage (permyriadage is to 10000 as percentage is to 100)
-** progress indications for the two stages of an RBU update. This API may
-** be useful for driving GUI progress indicators and similar.
-**
-** An RBU update is divided into two stages:
-**
-** * Stage 1, in which changes are accumulated in an oal/wal file, and
-** * Stage 2, in which the contents of the wal file are copied into the
-** main database.
-**
-** The update is visible to non-RBU clients during stage 2. During stage 1
-** non-RBU reader clients may see the original database.
-**
-** If this API is called during stage 2 of the update, output variable
-** (*pnOne) is set to 10000 to indicate that stage 1 has finished and (*pnTwo)
-** to a value between 0 and 10000 to indicate the permyriadage progress of
-** stage 2. A value of 5000 indicates that stage 2 is half finished,
-** 9000 indicates that it is 90% finished, and so on.
-**
-** If this API is called during stage 1 of the update, output variable
-** (*pnTwo) is set to 0 to indicate that stage 2 has not yet started. The
-** value to which (*pnOne) is set depends on whether or not the RBU
-** database contains an "rbu_count" table. The rbu_count table, if it
-** exists, must contain the same columns as the following:
-**
-** CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID;
-**
-** There must be one row in the table for each source (data_xxx) table within
-** the RBU database. The 'tbl' column should contain the name of the source
-** table. The 'cnt' column should contain the number of rows within the
-** source table.
-**
-** If the rbu_count table is present and populated correctly and this
-** API is called during stage 1, the *pnOne output variable is set to the
-** permyriadage progress of the same stage. If the rbu_count table does
-** not exist, then (*pnOne) is set to -1 during stage 1. If the rbu_count
-** table exists but is not correctly populated, the value of the *pnOne
-** output variable during stage 1 is undefined.
-*/
-SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int*pnTwo);
-
-/*
-** Obtain an indication as to the current stage of an RBU update or vacuum.
-** This function always returns one of the SQLITE_RBU_STATE_XXX constants
-** defined in this file. Return values should be interpreted as follows:
-**
-** SQLITE_RBU_STATE_OAL:
-** RBU is currently building a *-oal file. The next call to sqlite3rbu_step()
-** may either add further data to the *-oal file, or compute data that will
-** be added by a subsequent call.
-**
-** SQLITE_RBU_STATE_MOVE:
-** RBU has finished building the *-oal file. The next call to sqlite3rbu_step()
-** will move the *-oal file to the equivalent *-wal path. If the current
-** operation is an RBU update, then the updated version of the database
-** file will become visible to ordinary SQLite clients following the next
-** call to sqlite3rbu_step().
-**
-** SQLITE_RBU_STATE_CHECKPOINT:
-** RBU is currently performing an incremental checkpoint. The next call to
-** sqlite3rbu_step() will copy a page of data from the *-wal file into
-** the target database file.
-**
-** SQLITE_RBU_STATE_DONE:
-** The RBU operation has finished. Any subsequent calls to sqlite3rbu_step()
-** will immediately return SQLITE_DONE.
-**
-** SQLITE_RBU_STATE_ERROR:
-** An error has occurred. Any subsequent calls to sqlite3rbu_step() will
-** immediately return the SQLite error code associated with the error.
-*/
-#define SQLITE_RBU_STATE_OAL 1
-#define SQLITE_RBU_STATE_MOVE 2
-#define SQLITE_RBU_STATE_CHECKPOINT 3
-#define SQLITE_RBU_STATE_DONE 4
-#define SQLITE_RBU_STATE_ERROR 5
-
-SQLITE_API int sqlite3rbu_state(sqlite3rbu *pRbu);
-
-/*
-** Create an RBU VFS named zName that accesses the underlying file-system
-** via existing VFS zParent. Or, if the zParent parameter is passed NULL,
-** then the new RBU VFS uses the default system VFS to access the file-system.
-** The new object is registered as a non-default VFS with SQLite before
-** returning.
-**
-** Part of the RBU implementation uses a custom VFS object. Usually, this
-** object is created and deleted automatically by RBU.
-**
-** The exception is for applications that also use zipvfs. In this case,
-** the custom VFS must be explicitly created by the user before the RBU
-** handle is opened. The RBU VFS should be installed so that the zipvfs
-** VFS uses the RBU VFS, which in turn uses any other VFS layers in use
-** (for example multiplexor) to access the file-system. For example,
-** to assemble an RBU enabled VFS stack that uses both zipvfs and
-** multiplexor (error checking omitted):
-**
-** // Create a VFS named "multiplex" (not the default).
-** sqlite3_multiplex_initialize(0, 0);
-**
-** // Create an rbu VFS named "rbu" that uses multiplexor. If the
-** // second argument were replaced with NULL, the "rbu" VFS would
-** // access the file-system via the system default VFS, bypassing the
-** // multiplexor.
-** sqlite3rbu_create_vfs("rbu", "multiplex");
-**
-** // Create a zipvfs VFS named "zipvfs" that uses rbu.
-** zipvfs_create_vfs_v3("zipvfs", "rbu", 0, xCompressorAlgorithmDetector);
-**
-** // Make zipvfs the default VFS.
-** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1);
-**
-** Because the default VFS created above includes a RBU functionality, it
-** may be used by RBU clients. Attempting to use RBU with a zipvfs VFS stack
-** that does not include the RBU layer results in an error.
-**
-** The overhead of adding the "rbu" VFS to the system is negligible for
-** non-RBU users. There is no harm in an application accessing the
-** file-system via "rbu" all the time, even if it only uses RBU functionality
-** occasionally.
-*/
-SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent);
-
-/*
-** Deregister and destroy an RBU vfs created by an earlier call to
-** sqlite3rbu_create_vfs().
-**
-** VFS objects are not reference counted. If a VFS object is destroyed
-** before all database handles that use it have been closed, the results
-** are undefined.
-*/
-SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName);
-
-#ifdef __cplusplus
-} /* end of the 'extern "C"' block */
-#endif
-
-#endif /* _SQLITE3RBU_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/test_rbu.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/test_rbu.c
deleted file mode 100644
index e0b4d77af0a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rbu/test_rbu.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
-** 2015 February 16
-**
-** 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.
-**
-*************************************************************************
-*/
-
-#include "sqlite3.h"
-
-#if defined(SQLITE_TEST)
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU)
-
-#include "sqlite3rbu.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-#include <assert.h>
-
-/* From main.c */
-extern const char *sqlite3ErrName(int);
-extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
-
-void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
- Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
- Tcl_Obj *pScript;
- int i;
-
- pScript = Tcl_NewObj();
- Tcl_IncrRefCount(pScript);
- Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("rbu_delta", -1));
- for(i=0; i<nArg; i++){
- sqlite3_value *pIn = apVal[i];
- const char *z = (const char*)sqlite3_value_text(pIn);
- Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1));
- }
-
- if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){
- const char *z = Tcl_GetStringResult(interp);
- sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
- }else{
- Tcl_BackgroundError(interp);
- }
-
- Tcl_DecrRefCount(pScript);
-}
-
-
-static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int ret = TCL_OK;
- sqlite3rbu *pRbu = (sqlite3rbu*)clientData;
- struct RbuCmd {
- const char *zName;
- int nArg;
- const char *zUsage;
- } aCmd[] = {
- {"step", 2, ""}, /* 0 */
- {"close", 2, ""}, /* 1 */
- {"create_rbu_delta", 2, ""}, /* 2 */
- {"savestate", 2, ""}, /* 3 */
- {"dbMain_eval", 3, "SQL"}, /* 4 */
- {"bp_progress", 2, ""}, /* 5 */
- {"db", 3, "RBU"}, /* 6 */
- {"state", 2, ""}, /* 7 */
- {"progress", 2, ""}, /* 8 */
- {"close_no_error", 2, ""}, /* 9 */
- {"temp_size_limit", 3, "LIMIT"}, /* 10 */
- {"temp_size", 2, ""}, /* 11 */
- {"dbRbu_eval", 3, "SQL"}, /* 12 */
- {0,0,0}
- };
- int iCmd;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
- return TCL_ERROR;
- }
- ret = Tcl_GetIndexFromObjStruct(
- interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd
- );
- if( ret ) return TCL_ERROR;
- if( objc!=aCmd[iCmd].nArg ){
- Tcl_WrongNumArgs(interp, 1, objv, aCmd[iCmd].zUsage);
- return TCL_ERROR;
- }
-
- switch( iCmd ){
- case 0: /* step */ {
- int rc = sqlite3rbu_step(pRbu);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- break;
- }
-
- case 9: /* close_no_error */
- case 1: /* close */ {
- char *zErrmsg = 0;
- int rc;
- Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
- if( iCmd==1 ){
- rc = sqlite3rbu_close(pRbu, &zErrmsg);
- }else{
- rc = sqlite3rbu_close(pRbu, 0);
- }
- if( rc==SQLITE_OK || rc==SQLITE_DONE ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- assert( zErrmsg==0 );
- }else{
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- if( zErrmsg ){
- Tcl_AppendResult(interp, " - ", zErrmsg, 0);
- sqlite3_free(zErrmsg);
- }
- ret = TCL_ERROR;
- }
- break;
- }
-
- case 2: /* create_rbu_delta */ {
- sqlite3 *db = sqlite3rbu_db(pRbu, 0);
- int rc = sqlite3_create_function(
- db, "rbu_delta", -1, SQLITE_UTF8, (void*)interp, test_rbu_delta, 0, 0
- );
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
- break;
- }
-
- case 3: /* savestate */ {
- int rc = sqlite3rbu_savestate(pRbu);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
- break;
- }
-
- case 12: /* dbRbu_eval */
- case 4: /* dbMain_eval */ {
- sqlite3 *db = sqlite3rbu_db(pRbu, (iCmd==12));
- int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0);
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1));
- ret = TCL_ERROR;
- }
- break;
- }
-
- case 5: /* bp_progress */ {
- int one, two;
- Tcl_Obj *pObj;
- sqlite3rbu_bp_progress(pRbu, &one, &two);
-
- pObj = Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(one));
- Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(two));
- Tcl_SetObjResult(interp, pObj);
- break;
- }
-
- case 6: /* db */ {
- int bArg;
- if( Tcl_GetBooleanFromObj(interp, objv[2], &bArg) ){
- ret = TCL_ERROR;
- }else{
- char zBuf[50];
- sqlite3 *db = sqlite3rbu_db(pRbu, bArg);
- if( sqlite3TestMakePointerStr(interp, zBuf, (void*)db) ){
- ret = TCL_ERROR;
- }else{
- Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
- }
- }
- break;
- }
- case 7: /* state */ {
- const char *aRes[] = { 0, "oal", "move", "checkpoint", "done", "error" };
- int eState = sqlite3rbu_state(pRbu);
- assert( eState>0 && eState<=5 );
- Tcl_SetResult(interp, (char*)aRes[eState], TCL_STATIC);
- break;
- }
- case 8: /* progress */ {
- sqlite3_int64 nStep = sqlite3rbu_progress(pRbu);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nStep));
- break;
- }
-
- case 10: /* temp_size_limit */ {
- sqlite3_int64 nLimit;
- if( Tcl_GetWideIntFromObj(interp, objv[2], &nLimit) ){
- ret = TCL_ERROR;
- }else{
- nLimit = sqlite3rbu_temp_size_limit(pRbu, nLimit);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nLimit));
- }
- break;
- }
- case 11: /* temp_size */ {
- sqlite3_int64 sz = sqlite3rbu_temp_size(pRbu);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sz));
- break;
- }
-
- default: /* seems unlikely */
- assert( !"cannot happen" );
- break;
- }
-
- return ret;
-}
-
-/*
-** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>?
-*/
-static int SQLITE_TCLAPI test_sqlite3rbu(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3rbu *pRbu = 0;
- const char *zCmd;
- const char *zTarget;
- const char *zRbu;
- const char *zStateDb = 0;
-
- if( objc!=4 && objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB RBU-DB ?STATE-DB?");
- return TCL_ERROR;
- }
- zCmd = Tcl_GetString(objv[1]);
- zTarget = Tcl_GetString(objv[2]);
- zRbu = Tcl_GetString(objv[3]);
- if( objc==5 ) zStateDb = Tcl_GetString(objv[4]);
-
- pRbu = sqlite3rbu_open(zTarget, zRbu, zStateDb);
- Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
- Tcl_SetObjResult(interp, objv[1]);
- return TCL_OK;
-}
-
-/*
-** Tclcmd: sqlite3rbu_vacuum CMD <target-db> <state-db>
-*/
-static int SQLITE_TCLAPI test_sqlite3rbu_vacuum(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3rbu *pRbu = 0;
- const char *zCmd;
- const char *zTarget;
- const char *zStateDb = 0;
-
- if( objc!=3 && objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB ?STATE-DB?");
- return TCL_ERROR;
- }
- zCmd = Tcl_GetString(objv[1]);
- zTarget = Tcl_GetString(objv[2]);
- if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
-
- pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
- Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
- Tcl_SetObjResult(interp, objv[1]);
- return TCL_OK;
-}
-
-/*
-** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT
-*/
-static int SQLITE_TCLAPI test_sqlite3rbu_create_vfs(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zName;
- const char *zParent;
- int rc;
-
- if( objc!=3 && objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT");
- return TCL_ERROR;
- }
-
- zName = Tcl_GetString(objv[objc-2]);
- zParent = Tcl_GetString(objv[objc-1]);
- if( zParent[0]=='\0' ) zParent = 0;
-
- rc = sqlite3rbu_create_vfs(zName, zParent);
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }else if( objc==4 ){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
- sqlite3_vfs_register(pVfs, 1);
- }
-
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/*
-** Tclcmd: sqlite3rbu_destroy_vfs NAME
-*/
-static int SQLITE_TCLAPI test_sqlite3rbu_destroy_vfs(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zName;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME");
- return TCL_ERROR;
- }
-
- zName = Tcl_GetString(objv[1]);
- sqlite3rbu_destroy_vfs(zName);
- return TCL_OK;
-}
-
-/*
-** Tclcmd: sqlite3rbu_internal_test
-*/
-static int SQLITE_TCLAPI test_sqlite3rbu_internal_test(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- db = sqlite3rbu_db(0, 0);
- if( db!=0 ){
- Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-int SqliteRbu_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aObjCmd[] = {
- { "sqlite3rbu", test_sqlite3rbu },
- { "sqlite3rbu_vacuum", test_sqlite3rbu_vacuum },
- { "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs },
- { "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs },
- { "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
- }
- return TCL_OK;
-}
-
-#else
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-int SqliteRbu_Init(Tcl_Interp *interp){ return TCL_OK; }
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */
-#endif /* defined(SQLITE_TEST) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/README.md b/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/README.md
deleted file mode 100644
index 927ceb7c440..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-This folder contains extensions and utility programs intended to analyze
-live database files, detect problems, and possibly fix them.
-
-As SQLite is being used on larger and larger databases, database sizes
-are growing into the terabyte range. At that size, hardware malfunctions
-and/or cosmic rays will occasionally corrupt a database file. Detecting
-problems and fixing errors a terabyte-sized databases can take hours or days,
-and it is undesirable to take applications that depend on the databases
-off-line for such a long time.
-The utilities in the folder are intended to provide mechanisms for
-detecting and fixing problems in large databases while those databases
-are in active use.
-
-The utilities and extensions in this folder are experimental and under
-active development at the time of this writing (2017-10-12). If and when
-they stabilize, this README will be updated to reflect that fact.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/checkfreelist.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/checkfreelist.c
deleted file mode 100644
index 990be4afa7b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/checkfreelist.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
-** 2017 October 11
-**
-** 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 module exports a single C function:
-**
-** int sqlite3_check_freelist(sqlite3 *db, const char *zDb);
-**
-** This function checks the free-list in database zDb (one of "main",
-** "temp", etc.) and reports any errors by invoking the sqlite3_log()
-** function. It returns SQLITE_OK if successful, or an SQLite error
-** code otherwise. It is not an error if the free-list is corrupted but
-** no IO or OOM errors occur.
-**
-** If this file is compiled and loaded as an SQLite loadable extension,
-** it adds an SQL function "checkfreelist" to the database handle, to
-** be invoked as follows:
-**
-** SELECT checkfreelist(<database-name>);
-**
-** This function performs the same checks as sqlite3_check_freelist(),
-** except that it returns all error messages as a single text value,
-** separated by newline characters. If the freelist is not corrupted
-** in any way, an empty string is returned.
-**
-** To compile this module for use as an SQLite loadable extension:
-**
-** gcc -Os -fPIC -shared checkfreelist.c -o checkfreelist.so
-*/
-
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-#ifndef SQLITE_AMALGAMATION
-# include <string.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <assert.h>
-# define ALWAYS(X) 1
-# define NEVER(X) 0
- typedef unsigned char u8;
- typedef unsigned short u16;
- typedef unsigned int u32;
-#define get4byte(x) ( \
- ((u32)((x)[0])<<24) + \
- ((u32)((x)[1])<<16) + \
- ((u32)((x)[2])<<8) + \
- ((u32)((x)[3])) \
-)
-#endif
-
-/*
-** Execute a single PRAGMA statement and return the integer value returned
-** via output parameter (*pnOut).
-**
-** The SQL statement passed as the third argument should be a printf-style
-** format string containing a single "%s" which will be replace by the
-** value passed as the second argument. e.g.
-**
-** sqlGetInteger(db, "main", "PRAGMA %s.page_count", pnOut)
-**
-** executes "PRAGMA main.page_count" and stores the results in (*pnOut).
-*/
-static int sqlGetInteger(
- sqlite3 *db, /* Database handle */
- const char *zDb, /* Database name ("main", "temp" etc.) */
- const char *zFmt, /* SQL statement format */
- u32 *pnOut /* OUT: Integer value */
-){
- int rc, rc2;
- char *zSql;
- sqlite3_stmt *pStmt = 0;
- int bOk = 0;
-
- zSql = sqlite3_mprintf(zFmt, zDb);
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- }
-
- if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- *pnOut = (u32)sqlite3_column_int(pStmt, 0);
- bOk = 1;
- }
-
- rc2 = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) rc = rc2;
- if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_ERROR;
- return rc;
-}
-
-/*
-** Argument zFmt must be a printf-style format string and must be
-** followed by its required arguments. If argument pzOut is NULL,
-** then the results of printf()ing the format string are passed to
-** sqlite3_log(). Otherwise, they are appended to the string
-** at (*pzOut).
-*/
-static int checkFreelistError(char **pzOut, const char *zFmt, ...){
- int rc = SQLITE_OK;
- char *zErr = 0;
- va_list ap;
-
- va_start(ap, zFmt);
- zErr = sqlite3_vmprintf(zFmt, ap);
- if( zErr==0 ){
- rc = SQLITE_NOMEM;
- }else{
- if( pzOut ){
- *pzOut = sqlite3_mprintf("%s%z%s", *pzOut?"\n":"", *pzOut, zErr);
- if( *pzOut==0 ) rc = SQLITE_NOMEM;
- }else{
- sqlite3_log(SQLITE_ERROR, "checkfreelist: %s", zErr);
- }
- sqlite3_free(zErr);
- }
- va_end(ap);
- return rc;
-}
-
-static int checkFreelist(
- sqlite3 *db,
- const char *zDb,
- char **pzOut
-){
- /* This query returns one row for each page on the free list. Each row has
- ** two columns - the page number and page content. */
- const char *zTrunk =
- "WITH freelist_trunk(i, d, n) AS ("
- "SELECT 1, NULL, sqlite_readint32(data, 32) "
- "FROM sqlite_dbpage(:1) WHERE pgno=1 "
- "UNION ALL "
- "SELECT n, data, sqlite_readint32(data) "
- "FROM freelist_trunk, sqlite_dbpage(:1) WHERE pgno=n "
- ")"
- "SELECT i, d FROM freelist_trunk WHERE i!=1;";
-
- int rc, rc2; /* Return code */
- sqlite3_stmt *pTrunk = 0; /* Compilation of zTrunk */
- u32 nPage = 0; /* Number of pages in db */
- u32 nExpected = 0; /* Expected number of free pages */
- u32 nFree = 0; /* Number of pages on free list */
-
- if( zDb==0 ) zDb = "main";
-
- if( (rc = sqlGetInteger(db, zDb, "PRAGMA %s.page_count", &nPage))
- || (rc = sqlGetInteger(db, zDb, "PRAGMA %s.freelist_count", &nExpected))
- ){
- return rc;
- }
-
- rc = sqlite3_prepare_v2(db, zTrunk, -1, &pTrunk, 0);
- if( rc!=SQLITE_OK ) return rc;
- sqlite3_bind_text(pTrunk, 1, zDb, -1, SQLITE_STATIC);
- while( rc==SQLITE_OK && sqlite3_step(pTrunk)==SQLITE_ROW ){
- u32 i;
- u32 iTrunk = (u32)sqlite3_column_int(pTrunk, 0);
- const u8 *aData = (const u8*)sqlite3_column_blob(pTrunk, 1);
- u32 nData = (u32)sqlite3_column_bytes(pTrunk, 1);
- u32 iNext = get4byte(&aData[0]);
- u32 nLeaf = get4byte(&aData[4]);
-
- if( nLeaf>((nData/4)-2-6) ){
- rc = checkFreelistError(pzOut,
- "leaf count out of range (%d) on trunk page %d",
- (int)nLeaf, (int)iTrunk
- );
- nLeaf = (nData/4) - 2 - 6;
- }
-
- nFree += 1+nLeaf;
- if( iNext>nPage ){
- rc = checkFreelistError(pzOut,
- "trunk page %d is out of range", (int)iNext
- );
- }
-
- for(i=0; rc==SQLITE_OK && i<nLeaf; i++){
- u32 iLeaf = get4byte(&aData[8 + 4*i]);
- if( iLeaf==0 || iLeaf>nPage ){
- rc = checkFreelistError(pzOut,
- "leaf page %d is out of range (child %d of trunk page %d)",
- (int)iLeaf, (int)i, (int)iTrunk
- );
- }
- }
- }
-
- if( rc==SQLITE_OK && nFree!=nExpected ){
- rc = checkFreelistError(pzOut,
- "free-list count mismatch: actual=%d header=%d",
- (int)nFree, (int)nExpected
- );
- }
-
- rc2 = sqlite3_finalize(pTrunk);
- if( rc==SQLITE_OK ) rc = rc2;
- return rc;
-}
-
-int sqlite3_check_freelist(sqlite3 *db, const char *zDb){
- return checkFreelist(db, zDb, 0);
-}
-
-static void checkfreelist_function(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **apArg
-){
- const char *zDb;
- int rc;
- char *zOut = 0;
- sqlite3 *db = sqlite3_context_db_handle(pCtx);
-
- assert( nArg==1 );
- zDb = (const char*)sqlite3_value_text(apArg[0]);
- rc = checkFreelist(db, zDb, &zOut);
- if( rc==SQLITE_OK ){
- sqlite3_result_text(pCtx, zOut?zOut:"ok", -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_error_code(pCtx, rc);
- }
-
- sqlite3_free(zOut);
-}
-
-/*
-** An SQL function invoked as follows:
-**
-** sqlite_readint32(BLOB) -- Decode 32-bit integer from start of blob
-*/
-static void readint_function(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **apArg
-){
- const u8 *zBlob;
- int nBlob;
- int iOff = 0;
- u32 iRet = 0;
-
- if( nArg!=1 && nArg!=2 ){
- sqlite3_result_error(
- pCtx, "wrong number of arguments to function sqlite_readint32()", -1
- );
- return;
- }
- if( nArg==2 ){
- iOff = sqlite3_value_int(apArg[1]);
- }
-
- zBlob = sqlite3_value_blob(apArg[0]);
- nBlob = sqlite3_value_bytes(apArg[0]);
-
- if( nBlob>=(iOff+4) ){
- iRet = get4byte(&zBlob[iOff]);
- }
-
- sqlite3_result_int64(pCtx, (sqlite3_int64)iRet);
-}
-
-/*
-** Register the SQL functions.
-*/
-static int cflRegister(sqlite3 *db){
- int rc = sqlite3_create_function(
- db, "sqlite_readint32", -1, SQLITE_UTF8, 0, readint_function, 0, 0
- );
- if( rc!=SQLITE_OK ) return rc;
- rc = sqlite3_create_function(
- db, "checkfreelist", 1, SQLITE_UTF8, 0, checkfreelist_function, 0, 0
- );
- return rc;
-}
-
-/*
-** Extension load function.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_checkfreelist_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- return cflRegister(db);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/checkindex.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/checkindex.c
deleted file mode 100644
index 58706c1aab4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/checkindex.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
-** 2017 October 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.
-**
-*************************************************************************
-*/
-
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-/*
-** Stuff that is available inside the amalgamation, but which we need to
-** declare ourselves if this module is compiled separately.
-*/
-#ifndef SQLITE_AMALGAMATION
-# include <string.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <assert.h>
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-#define get4byte(x) ( \
- ((u32)((x)[0])<<24) + \
- ((u32)((x)[1])<<16) + \
- ((u32)((x)[2])<<8) + \
- ((u32)((x)[3])) \
-)
-#endif
-
-typedef struct CidxTable CidxTable;
-typedef struct CidxCursor CidxCursor;
-
-struct CidxTable {
- sqlite3_vtab base; /* Base class. Must be first */
- sqlite3 *db;
-};
-
-struct CidxCursor {
- sqlite3_vtab_cursor base; /* Base class. Must be first */
- sqlite3_int64 iRowid; /* Row number of the output */
- char *zIdxName; /* Copy of the index_name parameter */
- char *zAfterKey; /* Copy of the after_key parameter */
- sqlite3_stmt *pStmt; /* SQL statement that generates the output */
-};
-
-typedef struct CidxColumn CidxColumn;
-struct CidxColumn {
- char *zExpr; /* Text for indexed expression */
- int bDesc; /* True for DESC columns, otherwise false */
- int bKey; /* Part of index, not PK */
-};
-
-typedef struct CidxIndex CidxIndex;
-struct CidxIndex {
- char *zWhere; /* WHERE clause, if any */
- int nCol; /* Elements in aCol[] array */
- CidxColumn aCol[1]; /* Array of indexed columns */
-};
-
-static void *cidxMalloc(int *pRc, int n){
- void *pRet = 0;
- assert( n!=0 );
- if( *pRc==SQLITE_OK ){
- pRet = sqlite3_malloc(n);
- if( pRet ){
- memset(pRet, 0, n);
- }else{
- *pRc = SQLITE_NOMEM;
- }
- }
- return pRet;
-}
-
-static void cidxCursorError(CidxCursor *pCsr, const char *zFmt, ...){
- va_list ap;
- va_start(ap, zFmt);
- assert( pCsr->base.pVtab->zErrMsg==0 );
- pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
-}
-
-/*
-** Connect to the incremental_index_check virtual table.
-*/
-static int cidxConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- int rc = SQLITE_OK;
- CidxTable *pRet;
-
-#define IIC_ERRMSG 0
-#define IIC_CURRENT_KEY 1
-#define IIC_INDEX_NAME 2
-#define IIC_AFTER_KEY 3
-#define IIC_SCANNER_SQL 4
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE xyz("
- " errmsg TEXT," /* Error message or NULL if everything is ok */
- " current_key TEXT," /* SQLite quote() text of key values */
- " index_name HIDDEN," /* IN: name of the index being scanned */
- " after_key HIDDEN," /* IN: Start scanning after this key */
- " scanner_sql HIDDEN" /* debuggingn info: SQL used for scanner */
- ")"
- );
- pRet = cidxMalloc(&rc, sizeof(CidxTable));
- if( pRet ){
- pRet->db = db;
- }
-
- *ppVtab = (sqlite3_vtab*)pRet;
- return rc;
-}
-
-/*
-** Disconnect from or destroy an incremental_index_check virtual table.
-*/
-static int cidxDisconnect(sqlite3_vtab *pVtab){
- CidxTable *pTab = (CidxTable*)pVtab;
- sqlite3_free(pTab);
- return SQLITE_OK;
-}
-
-/*
-** idxNum and idxStr are not used. There are only three possible plans,
-** which are all distinguished by the number of parameters.
-**
-** No parameters: A degenerate plan. The result is zero rows.
-** 1 Parameter: Scan all of the index starting with first entry
-** 2 parameters: Scan the index starting after the "after_key".
-**
-** Provide successively smaller costs for each of these plans to encourage
-** the query planner to select the one with the most parameters.
-*/
-static int cidxBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pInfo){
- int iIdxName = -1;
- int iAfterKey = -1;
- int i;
-
- for(i=0; i<pInfo->nConstraint; i++){
- struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
- if( p->usable==0 ) continue;
- if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
-
- if( p->iColumn==IIC_INDEX_NAME ){
- iIdxName = i;
- }
- if( p->iColumn==IIC_AFTER_KEY ){
- iAfterKey = i;
- }
- }
-
- if( iIdxName<0 ){
- pInfo->estimatedCost = 1000000000.0;
- }else{
- pInfo->aConstraintUsage[iIdxName].argvIndex = 1;
- pInfo->aConstraintUsage[iIdxName].omit = 1;
- if( iAfterKey<0 ){
- pInfo->estimatedCost = 1000000.0;
- }else{
- pInfo->aConstraintUsage[iAfterKey].argvIndex = 2;
- pInfo->aConstraintUsage[iAfterKey].omit = 1;
- pInfo->estimatedCost = 1000.0;
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Open a new btreeinfo cursor.
-*/
-static int cidxOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- CidxCursor *pRet;
- int rc = SQLITE_OK;
-
- pRet = cidxMalloc(&rc, sizeof(CidxCursor));
-
- *ppCursor = (sqlite3_vtab_cursor*)pRet;
- return rc;
-}
-
-/*
-** Close a btreeinfo cursor.
-*/
-static int cidxClose(sqlite3_vtab_cursor *pCursor){
- CidxCursor *pCsr = (CidxCursor*)pCursor;
- sqlite3_finalize(pCsr->pStmt);
- sqlite3_free(pCsr->zIdxName);
- sqlite3_free(pCsr->zAfterKey);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Move a btreeinfo cursor to the next entry in the file.
-*/
-static int cidxNext(sqlite3_vtab_cursor *pCursor){
- CidxCursor *pCsr = (CidxCursor*)pCursor;
- int rc = sqlite3_step(pCsr->pStmt);
- if( rc!=SQLITE_ROW ){
- rc = sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- if( rc!=SQLITE_OK ){
- sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
- cidxCursorError(pCsr, "Cursor error: %s", sqlite3_errmsg(db));
- }
- }else{
- pCsr->iRowid++;
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-/* We have reached EOF if previous sqlite3_step() returned
-** anything other than SQLITE_ROW;
-*/
-static int cidxEof(sqlite3_vtab_cursor *pCursor){
- CidxCursor *pCsr = (CidxCursor*)pCursor;
- return pCsr->pStmt==0;
-}
-
-static char *cidxMprintf(int *pRc, const char *zFmt, ...){
- char *zRet = 0;
- va_list ap;
- va_start(ap, zFmt);
- zRet = sqlite3_vmprintf(zFmt, ap);
- if( *pRc==SQLITE_OK ){
- if( zRet==0 ){
- *pRc = SQLITE_NOMEM;
- }
- }else{
- sqlite3_free(zRet);
- zRet = 0;
- }
- va_end(ap);
- return zRet;
-}
-
-static sqlite3_stmt *cidxPrepare(
- int *pRc, CidxCursor *pCsr, const char *zFmt, ...
-){
- sqlite3_stmt *pRet = 0;
- char *zSql;
- va_list ap; /* ... printf arguments */
- va_start(ap, zFmt);
-
- zSql = sqlite3_vmprintf(zFmt, ap);
- if( *pRc==SQLITE_OK ){
- if( zSql==0 ){
- *pRc = SQLITE_NOMEM;
- }else{
- sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
- *pRc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
- if( *pRc!=SQLITE_OK ){
- cidxCursorError(pCsr, "SQL error: %s", sqlite3_errmsg(db));
- }
- }
- }
- sqlite3_free(zSql);
- va_end(ap);
-
- return pRet;
-}
-
-static void cidxFinalize(int *pRc, sqlite3_stmt *pStmt){
- int rc = sqlite3_finalize(pStmt);
- if( *pRc==SQLITE_OK ) *pRc = rc;
-}
-
-char *cidxStrdup(int *pRc, const char *zStr){
- char *zRet = 0;
- if( *pRc==SQLITE_OK ){
- int n = (int)strlen(zStr);
- zRet = cidxMalloc(pRc, n+1);
- if( zRet ) memcpy(zRet, zStr, n+1);
- }
- return zRet;
-}
-
-static void cidxFreeIndex(CidxIndex *pIdx){
- if( pIdx ){
- int i;
- for(i=0; i<pIdx->nCol; i++){
- sqlite3_free(pIdx->aCol[i].zExpr);
- }
- sqlite3_free(pIdx->zWhere);
- sqlite3_free(pIdx);
- }
-}
-
-static int cidx_isspace(char c){
- return c==' ' || c=='\t' || c=='\r' || c=='\n';
-}
-
-static int cidx_isident(char c){
- return c<0
- || (c>='0' && c<='9') || (c>='a' && c<='z')
- || (c>='A' && c<='Z') || c=='_';
-}
-
-#define CIDX_PARSE_EOF 0
-#define CIDX_PARSE_COMMA 1 /* "," */
-#define CIDX_PARSE_OPEN 2 /* "(" */
-#define CIDX_PARSE_CLOSE 3 /* ")" */
-
-/*
-** Argument zIn points into the start, middle or end of a CREATE INDEX
-** statement. If argument pbDoNotTrim is non-NULL, then this function
-** scans the input until it finds EOF, a comma (",") or an open or
-** close parenthesis character. It then sets (*pzOut) to point to said
-** character and returns a CIDX_PARSE_XXX constant as appropriate. The
-** parser is smart enough that special characters inside SQL strings
-** or comments are not returned for.
-**
-** Or, if argument pbDoNotTrim is NULL, then this function sets *pzOut
-** to point to the first character of the string that is not whitespace
-** or part of an SQL comment and returns CIDX_PARSE_EOF.
-**
-** Additionally, if pbDoNotTrim is not NULL and the element immediately
-** before (*pzOut) is an SQL comment of the form "-- comment", then
-** (*pbDoNotTrim) is set before returning. In all other cases it is
-** cleared.
-*/
-static int cidxFindNext(
- const char *zIn,
- const char **pzOut,
- int *pbDoNotTrim /* OUT: True if prev is -- comment */
-){
- const char *z = zIn;
-
- while( 1 ){
- while( cidx_isspace(*z) ) z++;
- if( z[0]=='-' && z[1]=='-' ){
- z += 2;
- while( z[0]!='\n' ){
- if( z[0]=='\0' ) return CIDX_PARSE_EOF;
- z++;
- }
- while( cidx_isspace(*z) ) z++;
- if( pbDoNotTrim ) *pbDoNotTrim = 1;
- }else
- if( z[0]=='/' && z[1]=='*' ){
- z += 2;
- while( z[0]!='*' || z[1]!='/' ){
- if( z[1]=='\0' ) return CIDX_PARSE_EOF;
- z++;
- }
- z += 2;
- }else{
- *pzOut = z;
- if( pbDoNotTrim==0 ) return CIDX_PARSE_EOF;
- switch( *z ){
- case '\0':
- return CIDX_PARSE_EOF;
- case '(':
- return CIDX_PARSE_OPEN;
- case ')':
- return CIDX_PARSE_CLOSE;
- case ',':
- return CIDX_PARSE_COMMA;
-
- case '"':
- case '\'':
- case '`': {
- char q = *z;
- z++;
- while( *z ){
- if( *z==q ){
- z++;
- if( *z!=q ) break;
- }
- z++;
- }
- break;
- }
-
- case '[':
- while( *z++!=']' );
- break;
-
- default:
- z++;
- break;
- }
- *pbDoNotTrim = 0;
- }
- }
-
- assert( 0 );
- return -1;
-}
-
-static int cidxParseSQL(CidxCursor *pCsr, CidxIndex *pIdx, const char *zSql){
- const char *z = zSql;
- const char *z1;
- int e;
- int rc = SQLITE_OK;
- int nParen = 1;
- int bDoNotTrim = 0;
- CidxColumn *pCol = pIdx->aCol;
-
- e = cidxFindNext(z, &z, &bDoNotTrim);
- if( e!=CIDX_PARSE_OPEN ) goto parse_error;
- z1 = z+1;
- z++;
- while( nParen>0 ){
- e = cidxFindNext(z, &z, &bDoNotTrim);
- if( e==CIDX_PARSE_EOF ) goto parse_error;
- if( (e==CIDX_PARSE_COMMA || e==CIDX_PARSE_CLOSE) && nParen==1 ){
- const char *z2 = z;
- if( pCol->zExpr ) goto parse_error;
-
- if( bDoNotTrim==0 ){
- while( cidx_isspace(z[-1]) ) z--;
- if( !sqlite3_strnicmp(&z[-3], "asc", 3) && 0==cidx_isident(z[-4]) ){
- z -= 3;
- while( cidx_isspace(z[-1]) ) z--;
- }else
- if( !sqlite3_strnicmp(&z[-4], "desc", 4) && 0==cidx_isident(z[-5]) ){
- z -= 4;
- while( cidx_isspace(z[-1]) ) z--;
- }
- while( cidx_isspace(z1[0]) ) z1++;
- }
-
- pCol->zExpr = cidxMprintf(&rc, "%.*s", z-z1, z1);
- pCol++;
- z = z1 = z2+1;
- }
- if( e==CIDX_PARSE_OPEN ) nParen++;
- if( e==CIDX_PARSE_CLOSE ) nParen--;
- z++;
- }
-
- /* Search for a WHERE clause */
- cidxFindNext(z, &z, 0);
- if( 0==sqlite3_strnicmp(z, "where", 5) ){
- pIdx->zWhere = cidxMprintf(&rc, "%s\n", &z[5]);
- }else if( z[0]!='\0' ){
- goto parse_error;
- }
-
- return rc;
-
- parse_error:
- cidxCursorError(pCsr, "Parse error in: %s", zSql);
- return SQLITE_ERROR;
-}
-
-static int cidxLookupIndex(
- CidxCursor *pCsr, /* Cursor object */
- const char *zIdx, /* Name of index to look up */
- CidxIndex **ppIdx, /* OUT: Description of columns */
- char **pzTab /* OUT: Table name */
-){
- int rc = SQLITE_OK;
- char *zTab = 0;
- CidxIndex *pIdx = 0;
-
- sqlite3_stmt *pFindTab = 0;
- sqlite3_stmt *pInfo = 0;
-
- /* Find the table for this index. */
- pFindTab = cidxPrepare(&rc, pCsr,
- "SELECT tbl_name, sql FROM sqlite_master WHERE name=%Q AND type='index'",
- zIdx
- );
- if( rc==SQLITE_OK && sqlite3_step(pFindTab)==SQLITE_ROW ){
- const char *zSql = (const char*)sqlite3_column_text(pFindTab, 1);
- zTab = cidxStrdup(&rc, (const char*)sqlite3_column_text(pFindTab, 0));
-
- pInfo = cidxPrepare(&rc, pCsr, "PRAGMA index_xinfo(%Q)", zIdx);
- if( rc==SQLITE_OK ){
- int nAlloc = 0;
- int iCol = 0;
-
- while( sqlite3_step(pInfo)==SQLITE_ROW ){
- const char *zName = (const char*)sqlite3_column_text(pInfo, 2);
- const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
- CidxColumn *p;
- if( zName==0 ) zName = "rowid";
- if( iCol==nAlloc ){
- int nByte = sizeof(CidxIndex) + sizeof(CidxColumn)*(nAlloc+8);
- pIdx = (CidxIndex*)sqlite3_realloc(pIdx, nByte);
- nAlloc += 8;
- }
- p = &pIdx->aCol[iCol++];
- p->bDesc = sqlite3_column_int(pInfo, 3);
- p->bKey = sqlite3_column_int(pInfo, 5);
- if( zSql==0 || p->bKey==0 ){
- p->zExpr = cidxMprintf(&rc, "\"%w\" COLLATE %s",zName,zColl);
- }else{
- p->zExpr = 0;
- }
- pIdx->nCol = iCol;
- pIdx->zWhere = 0;
- }
- cidxFinalize(&rc, pInfo);
- }
-
- if( rc==SQLITE_OK && zSql ){
- rc = cidxParseSQL(pCsr, pIdx, zSql);
- }
- }
-
- cidxFinalize(&rc, pFindTab);
- if( rc==SQLITE_OK && zTab==0 ){
- rc = SQLITE_ERROR;
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_free(zTab);
- cidxFreeIndex(pIdx);
- }else{
- *pzTab = zTab;
- *ppIdx = pIdx;
- }
-
- return rc;
-}
-
-static int cidxDecodeAfter(
- CidxCursor *pCsr,
- int nCol,
- const char *zAfterKey,
- char ***pazAfter
-){
- char **azAfter;
- int rc = SQLITE_OK;
- int nAfterKey = (int)strlen(zAfterKey);
-
- azAfter = cidxMalloc(&rc, sizeof(char*)*nCol + nAfterKey+1);
- if( rc==SQLITE_OK ){
- int i;
- char *zCopy = (char*)&azAfter[nCol];
- char *p = zCopy;
- memcpy(zCopy, zAfterKey, nAfterKey+1);
- for(i=0; i<nCol; i++){
- while( *p==' ' ) p++;
-
- /* Check NULL values */
- if( *p=='N' ){
- if( memcmp(p, "NULL", 4) ) goto parse_error;
- p += 4;
- }
-
- /* Check strings and blob literals */
- else if( *p=='X' || *p=='\'' ){
- azAfter[i] = p;
- if( *p=='X' ) p++;
- if( *p!='\'' ) goto parse_error;
- p++;
- while( 1 ){
- if( *p=='\0' ) goto parse_error;
- if( *p=='\'' ){
- p++;
- if( *p!='\'' ) break;
- }
- p++;
- }
- }
-
- /* Check numbers */
- else{
- azAfter[i] = p;
- while( (*p>='0' && *p<='9')
- || *p=='.' || *p=='+' || *p=='-' || *p=='e' || *p=='E'
- ){
- p++;
- }
- }
-
- while( *p==' ' ) p++;
- if( *p!=(i==(nCol-1) ? '\0' : ',') ){
- goto parse_error;
- }
- *p++ = '\0';
- }
- }
-
- *pazAfter = azAfter;
- return rc;
-
- parse_error:
- sqlite3_free(azAfter);
- *pazAfter = 0;
- cidxCursorError(pCsr, "%s", "error parsing after value");
- return SQLITE_ERROR;
-}
-
-static char *cidxWhere(
- int *pRc, CidxColumn *aCol, char **azAfter, int iGt, int bLastIsNull
-){
- char *zRet = 0;
- const char *zSep = "";
- int i;
-
- for(i=0; i<iGt; i++){
- zRet = cidxMprintf(pRc, "%z%s(%s) IS %s", zRet,
- zSep, aCol[i].zExpr, (azAfter[i] ? azAfter[i] : "NULL")
- );
- zSep = " AND ";
- }
-
- if( bLastIsNull ){
- zRet = cidxMprintf(pRc, "%z%s(%s) IS NULL", zRet, zSep, aCol[iGt].zExpr);
- }
- else if( azAfter[iGt] ){
- zRet = cidxMprintf(pRc, "%z%s(%s) %s %s", zRet,
- zSep, aCol[iGt].zExpr, (aCol[iGt].bDesc ? "<" : ">"),
- azAfter[iGt]
- );
- }else{
- zRet = cidxMprintf(pRc, "%z%s(%s) IS NOT NULL", zRet, zSep,aCol[iGt].zExpr);
- }
-
- return zRet;
-}
-
-#define CIDX_CLIST_ALL 0
-#define CIDX_CLIST_ORDERBY 1
-#define CIDX_CLIST_CURRENT_KEY 2
-#define CIDX_CLIST_SUBWHERE 3
-#define CIDX_CLIST_SUBEXPR 4
-
-/*
-** This function returns various strings based on the contents of the
-** CidxIndex structure and the eType parameter.
-*/
-static char *cidxColumnList(
- int *pRc, /* IN/OUT: Error code */
- const char *zIdx,
- CidxIndex *pIdx, /* Indexed columns */
- int eType /* True to include ASC/DESC */
-){
- char *zRet = 0;
- if( *pRc==SQLITE_OK ){
- const char *aDir[2] = {"", " DESC"};
- int i;
- const char *zSep = "";
-
- for(i=0; i<pIdx->nCol; i++){
- CidxColumn *p = &pIdx->aCol[i];
- assert( pIdx->aCol[i].bDesc==0 || pIdx->aCol[i].bDesc==1 );
- switch( eType ){
-
- case CIDX_CLIST_ORDERBY:
- zRet = cidxMprintf(pRc, "%z%s%d%s", zRet, zSep, i+1, aDir[p->bDesc]);
- zSep = ",";
- break;
-
- case CIDX_CLIST_CURRENT_KEY:
- zRet = cidxMprintf(pRc, "%z%squote(i%d)", zRet, zSep, i);
- zSep = "||','||";
- break;
-
- case CIDX_CLIST_SUBWHERE:
- if( p->bKey==0 ){
- zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet,
- zSep, p->zExpr, i
- );
- zSep = " AND ";
- }
- break;
-
- case CIDX_CLIST_SUBEXPR:
- if( p->bKey==1 ){
- zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet,
- zSep, p->zExpr, i
- );
- zSep = " AND ";
- }
- break;
-
- default:
- assert( eType==CIDX_CLIST_ALL );
- zRet = cidxMprintf(pRc, "%z%s(%s) AS i%d", zRet, zSep, p->zExpr, i);
- zSep = ", ";
- break;
- }
- }
- }
-
- return zRet;
-}
-
-/*
-** Generate SQL (in memory obtained from sqlite3_malloc()) that will
-** continue the index scan for zIdxName starting after zAfterKey.
-*/
-int cidxGenerateScanSql(
- CidxCursor *pCsr, /* The cursor which needs the new statement */
- const char *zIdxName, /* index to be scanned */
- const char *zAfterKey, /* start after this key, if not NULL */
- char **pzSqlOut /* OUT: Write the generated SQL here */
-){
- int rc;
- char *zTab = 0;
- char *zCurrentKey = 0;
- char *zOrderBy = 0;
- char *zSubWhere = 0;
- char *zSubExpr = 0;
- char *zSrcList = 0;
- char **azAfter = 0;
- CidxIndex *pIdx = 0;
-
- *pzSqlOut = 0;
- rc = cidxLookupIndex(pCsr, zIdxName, &pIdx, &zTab);
-
- zOrderBy = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ORDERBY);
- zCurrentKey = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_CURRENT_KEY);
- zSubWhere = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBWHERE);
- zSubExpr = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBEXPR);
- zSrcList = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ALL);
-
- if( rc==SQLITE_OK && zAfterKey ){
- rc = cidxDecodeAfter(pCsr, pIdx->nCol, zAfterKey, &azAfter);
- }
-
- if( rc==SQLITE_OK ){
- if( zAfterKey==0 ){
- *pzSqlOut = cidxMprintf(&rc,
- "SELECT (SELECT %s FROM %Q AS t WHERE %s), %s "
- "FROM (SELECT %s FROM %Q INDEXED BY %Q %s%sORDER BY %s) AS i",
- zSubExpr, zTab, zSubWhere, zCurrentKey,
- zSrcList, zTab, zIdxName,
- (pIdx->zWhere ? "WHERE " : ""), (pIdx->zWhere ? pIdx->zWhere : ""),
- zOrderBy
- );
- }else{
- const char *zSep = "";
- char *zSql;
- int i;
-
- zSql = cidxMprintf(&rc,
- "SELECT (SELECT %s FROM %Q WHERE %s), %s FROM (",
- zSubExpr, zTab, zSubWhere, zCurrentKey
- );
- for(i=pIdx->nCol-1; i>=0; i--){
- int j;
- if( pIdx->aCol[i].bDesc && azAfter[i]==0 ) continue;
- for(j=0; j<2; j++){
- char *zWhere = cidxWhere(&rc, pIdx->aCol, azAfter, i, j);
- zSql = cidxMprintf(&rc, "%z"
- "%sSELECT * FROM ("
- "SELECT %s FROM %Q INDEXED BY %Q WHERE %s%s%z ORDER BY %s"
- ")",
- zSql, zSep, zSrcList, zTab, zIdxName,
- pIdx->zWhere ? pIdx->zWhere : "",
- pIdx->zWhere ? " AND " : "",
- zWhere, zOrderBy
- );
- zSep = " UNION ALL ";
- if( pIdx->aCol[i].bDesc==0 ) break;
- }
- }
- *pzSqlOut = cidxMprintf(&rc, "%z) AS i", zSql);
- }
- }
-
- sqlite3_free(zTab);
- sqlite3_free(zCurrentKey);
- sqlite3_free(zOrderBy);
- sqlite3_free(zSubWhere);
- sqlite3_free(zSubExpr);
- sqlite3_free(zSrcList);
- cidxFreeIndex(pIdx);
- sqlite3_free(azAfter);
- return rc;
-}
-
-
-/*
-** Position a cursor back to the beginning.
-*/
-static int cidxFilter(
- sqlite3_vtab_cursor *pCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- int rc = SQLITE_OK;
- CidxCursor *pCsr = (CidxCursor*)pCursor;
- const char *zIdxName = 0;
- const char *zAfterKey = 0;
-
- sqlite3_free(pCsr->zIdxName);
- pCsr->zIdxName = 0;
- sqlite3_free(pCsr->zAfterKey);
- pCsr->zAfterKey = 0;
- sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
-
- if( argc>0 ){
- zIdxName = (const char*)sqlite3_value_text(argv[0]);
- if( argc>1 ){
- zAfterKey = (const char*)sqlite3_value_text(argv[1]);
- }
- }
-
- if( zIdxName ){
- char *zSql = 0;
- pCsr->zIdxName = sqlite3_mprintf("%s", zIdxName);
- pCsr->zAfterKey = zAfterKey ? sqlite3_mprintf("%s", zAfterKey) : 0;
- rc = cidxGenerateScanSql(pCsr, zIdxName, zAfterKey, &zSql);
- if( zSql ){
- pCsr->pStmt = cidxPrepare(&rc, pCsr, "%z", zSql);
- }
- }
-
- if( pCsr->pStmt ){
- assert( rc==SQLITE_OK );
- rc = cidxNext(pCursor);
- }
- pCsr->iRowid = 1;
- return rc;
-}
-
-/*
-** Return a column value.
-*/
-static int cidxColumn(
- sqlite3_vtab_cursor *pCursor,
- sqlite3_context *ctx,
- int iCol
-){
- CidxCursor *pCsr = (CidxCursor*)pCursor;
- assert( iCol>=IIC_ERRMSG && iCol<=IIC_SCANNER_SQL );
- switch( iCol ){
- case IIC_ERRMSG: {
- const char *zVal = 0;
- if( sqlite3_column_type(pCsr->pStmt, 0)==SQLITE_INTEGER ){
- if( sqlite3_column_int(pCsr->pStmt, 0)==0 ){
- zVal = "row data mismatch";
- }
- }else{
- zVal = "row missing";
- }
- sqlite3_result_text(ctx, zVal, -1, SQLITE_STATIC);
- break;
- }
- case IIC_CURRENT_KEY: {
- sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, 1));
- break;
- }
- case IIC_INDEX_NAME: {
- sqlite3_result_text(ctx, pCsr->zIdxName, -1, SQLITE_TRANSIENT);
- break;
- }
- case IIC_AFTER_KEY: {
- sqlite3_result_text(ctx, pCsr->zAfterKey, -1, SQLITE_TRANSIENT);
- break;
- }
- case IIC_SCANNER_SQL: {
- char *zSql = 0;
- cidxGenerateScanSql(pCsr, pCsr->zIdxName, pCsr->zAfterKey, &zSql);
- sqlite3_result_text(ctx, zSql, -1, sqlite3_free);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/* Return the ROWID for the sqlite_btreeinfo table */
-static int cidxRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- CidxCursor *pCsr = (CidxCursor*)pCursor;
- *pRowid = pCsr->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Register the virtual table modules with the database handle passed
-** as the only argument.
-*/
-static int ciInit(sqlite3 *db){
- static sqlite3_module cidx_module = {
- 0, /* iVersion */
- 0, /* xCreate */
- cidxConnect, /* xConnect */
- cidxBestIndex, /* xBestIndex */
- cidxDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- cidxOpen, /* xOpen - open a cursor */
- cidxClose, /* xClose - close a cursor */
- cidxFilter, /* xFilter - configure scan constraints */
- cidxNext, /* xNext - advance a cursor */
- cidxEof, /* xEof - check for end of scan */
- cidxColumn, /* xColumn - read data */
- cidxRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
- };
- return sqlite3_create_module(db, "incremental_index_check", &cidx_module, 0);
-}
-
-/*
-** Extension load function.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_checkindex_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- return ciInit(db);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/sqlite3_checker.c.in b/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/sqlite3_checker.c.in
deleted file mode 100644
index 76e9708787d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/sqlite3_checker.c.in
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-** Read an SQLite database file and analyze its space utilization. Generate
-** text on standard output.
-*/
-#define TCLSH_INIT_PROC sqlite3_checker_init_proc
-#define SQLITE_ENABLE_DBPAGE_VTAB 1
-#define SQLITE_ENABLE_JSON1 1
-#undef SQLITE_THREADSAFE
-#define SQLITE_THREADSAFE 0
-#undef SQLITE_ENABLE_COLUMN_METADATA
-#define SQLITE_OMIT_DECLTYPE 1
-#define SQLITE_OMIT_DEPRECATED 1
-#define SQLITE_OMIT_PROGRESS_CALLBACK 1
-#define SQLITE_OMIT_SHARED_CACHE 1
-#define SQLITE_DEFAULT_MEMSTATUS 0
-#define SQLITE_MAX_EXPR_DEPTH 0
-INCLUDE sqlite3.c
-INCLUDE $ROOT/src/tclsqlite.c
-INCLUDE $ROOT/ext/misc/btreeinfo.c
-INCLUDE $ROOT/ext/repair/checkindex.c
-INCLUDE $ROOT/ext/repair/checkfreelist.c
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
- struct SqliteDb *p;
- Tcl_CmdInfo cmdInfo;
- if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
- p = (struct SqliteDb*)cmdInfo.objClientData;
- *ppDb = p->db;
- return TCL_OK;
- }else{
- *ppDb = 0;
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** sqlite3_imposter db main rootpage {CREATE TABLE...} ;# setup an imposter
-** sqlite3_imposter db main ;# rm all imposters
-*/
-static int sqlite3_imposter(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- const char *zSchema;
- int iRoot;
- const char *zSql;
-
- if( objc!=3 && objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB SCHEMA [ROOTPAGE SQL]");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zSchema = Tcl_GetString(objv[2]);
- if( objc==3 ){
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 1);
- }else{
- if( Tcl_GetIntFromObj(interp, objv[3], &iRoot) ) return TCL_ERROR;
- zSql = Tcl_GetString(objv[4]);
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 1, iRoot);
- sqlite3_exec(db, zSql, 0, 0, 0);
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 0);
- }
- return TCL_OK;
-}
-
-#include <stdio.h>
-
-const char *sqlite3_checker_init_proc(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "sqlite3_imposter",
- (Tcl_ObjCmdProc*)sqlite3_imposter, 0, 0);
- sqlite3_auto_extension((void(*)(void))sqlite3_btreeinfo_init);
- sqlite3_auto_extension((void(*)(void))sqlite3_checkindex_init);
- sqlite3_auto_extension((void(*)(void))sqlite3_checkfreelist_init);
- return
-BEGIN_STRING
-INCLUDE $ROOT/ext/repair/sqlite3_checker.tcl
-END_STRING
-;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/sqlite3_checker.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/sqlite3_checker.tcl
deleted file mode 100644
index 2ae6e15b123..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/repair/sqlite3_checker.tcl
+++ /dev/null
@@ -1,264 +0,0 @@
-# This TCL script is the main driver script for the sqlite3_checker utility
-# program.
-#
-
-# Special case:
-#
-# sqlite3_checker --test FILENAME ARGS
-#
-# uses FILENAME in place of this script.
-#
-if {[lindex $argv 0]=="--test" && [llength $argv]>1} {
- set ::argv0 [lindex $argv 1]
- set argv [lrange $argv 2 end]
- source $argv0
- exit 0
-}
-
-# Emulate a TCL shell
-#
-proc tclsh {} {
- set line {}
- while {![eof stdin]} {
- if {$line!=""} {
- puts -nonewline "> "
- } else {
- puts -nonewline "% "
- }
- flush stdout
- append line [gets stdin]
- if {[info complete $line]} {
- if {[catch {uplevel #0 $line} result]} {
- puts stderr "Error: $result"
- } elseif {$result!=""} {
- puts $result
- }
- set line {}
- } else {
- append line \n
- }
- }
-}
-
-# Do an incremental integrity check of a single index
-#
-proc check_index {idxname batchsize bTrace} {
- set i 0
- set more 1
- set nerr 0
- set pct 00.0
- set max [db one {SELECT nEntry FROM sqlite_btreeinfo('main')
- WHERE name=$idxname}]
- puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
- flush stdout
- if {$bTrace} {
- set sql {SELECT errmsg, current_key AS key,
- CASE WHEN rowid=1 THEN scanner_sql END AS traceOut
- FROM incremental_index_check($idxname)
- WHERE after_key=$key
- LIMIT $batchsize}
- } else {
- set sql {SELECT errmsg, current_key AS key, NULL AS traceOut
- FROM incremental_index_check($idxname)
- WHERE after_key=$key
- LIMIT $batchsize}
- }
- while {$more} {
- set more 0
- db eval $sql {
- set more 1
- if {$errmsg!=""} {
- incr nerr
- puts "$idxname: key($key): $errmsg"
- } elseif {$traceOut!=""} {
- puts "$idxname: $traceOut"
- }
- incr i
-
- }
- set x [format {%.1f} [expr {($i*100.0)/$max}]]
- if {$x!=$pct} {
- puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
- flush stdout
- set pct $x
- }
- }
- puts "$idxname: $nerr errors out of $i entries"
-}
-
-# Print a usage message on standard error, then quit.
-#
-proc usage {} {
- set argv0 [file rootname [file tail [info nameofexecutable]]]
- puts stderr "Usage: $argv0 OPTIONS database-filename"
- puts stderr {
-Do sanity checking on a live SQLite3 database file specified by the
-"database-filename" argument.
-
-Options:
-
- --batchsize N Number of rows to check per transaction
-
- --freelist Perform a freelist check
-
- --index NAME Run a check of the index NAME
-
- --summary Print summary information about the database
-
- --table NAME Run a check of all indexes for table NAME
-
- --tclsh Run the built-in TCL interpreter (for debugging)
-
- --trace (Debugging only:) Output trace information on the scan
-
- --version Show the version number of SQLite
-}
- exit 1
-}
-
-set file_to_analyze {}
-append argv {}
-set bFreelistCheck 0
-set bSummary 0
-set zIndex {}
-set zTable {}
-set batchsize 1000
-set bAll 1
-set bTrace 0
-set argc [llength $argv]
-for {set i 0} {$i<$argc} {incr i} {
- set arg [lindex $argv $i]
- if {[regexp {^-+tclsh$} $arg]} {
- tclsh
- exit 0
- }
- if {[regexp {^-+version$} $arg]} {
- sqlite3 mem :memory:
- puts [mem one {SELECT sqlite_version()||' '||sqlite_source_id()}]
- mem close
- exit 0
- }
- if {[regexp {^-+freelist$} $arg]} {
- set bFreelistCheck 1
- set bAll 0
- continue
- }
- if {[regexp {^-+summary$} $arg]} {
- set bSummary 1
- set bAll 0
- continue
- }
- if {[regexp {^-+trace$} $arg]} {
- set bTrace 1
- continue
- }
- if {[regexp {^-+batchsize$} $arg]} {
- incr i
- if {$i>=$argc} {
- puts stderr "missing argument on $arg"
- exit 1
- }
- set batchsize [lindex $argv $i]
- continue
- }
- if {[regexp {^-+index$} $arg]} {
- incr i
- if {$i>=$argc} {
- puts stderr "missing argument on $arg"
- exit 1
- }
- set zIndex [lindex $argv $i]
- set bAll 0
- continue
- }
- if {[regexp {^-+table$} $arg]} {
- incr i
- if {$i>=$argc} {
- puts stderr "missing argument on $arg"
- exit 1
- }
- set zTable [lindex $argv $i]
- set bAll 0
- continue
- }
- if {[regexp {^-} $arg]} {
- puts stderr "Unknown option: $arg"
- usage
- }
- if {$file_to_analyze!=""} {
- usage
- } else {
- set file_to_analyze $arg
- }
-}
-if {$file_to_analyze==""} usage
-
-# If a TCL script is specified on the command-line, then run that
-# script.
-#
-if {[file extension $file_to_analyze]==".tcl"} {
- source $file_to_analyze
- exit 0
-}
-
-set root_filename $file_to_analyze
-regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename
-if {![file exists $root_filename]} {
- puts stderr "No such file: $root_filename"
- exit 1
-}
-if {![file readable $root_filename]} {
- puts stderr "File is not readable: $root_filename"
- exit 1
-}
-
-if {[catch {sqlite3 db $file_to_analyze} res]} {
- puts stderr "Cannot open datababase $root_filename: $res"
- exit 1
-}
-
-if {$bFreelistCheck || $bAll} {
- puts -nonewline "freelist-check: "
- flush stdout
- db eval BEGIN
- puts [db one {SELECT checkfreelist('main')}]
- db eval END
-}
-if {$bSummary} {
- set scale 0
- set pgsz [db one {PRAGMA page_size}]
- db eval {SELECT nPage*$pgsz AS sz, name, tbl_name
- FROM sqlite_btreeinfo
- WHERE type='index'
- ORDER BY 1 DESC, name} {
- if {$scale==0} {
- if {$sz>10000000} {
- set scale 1000000.0
- set unit MB
- } else {
- set scale 1000.0
- set unit KB
- }
- }
- puts [format {%7.1f %s index %s of table %s} \
- [expr {$sz/$scale}] $unit $name $tbl_name]
- }
-}
-if {$zIndex!=""} {
- check_index $zIndex $batchsize $bTrace
-}
-if {$zTable!=""} {
- foreach idx [db eval {SELECT name FROM sqlite_master
- WHERE type='index' AND rootpage>0
- AND tbl_name=$zTable}] {
- check_index $idx $batchsize $bTrace
- }
-}
-if {$bAll} {
- set allidx [db eval {SELECT name FROM sqlite_btreeinfo('main')
- WHERE type='index' AND rootpage>0
- ORDER BY nEntry}]
- foreach idx $allidx {
- check_index $idx $batchsize $bTrace
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/README b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/README
deleted file mode 100644
index 3736f45c5fd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/README
+++ /dev/null
@@ -1,120 +0,0 @@
-
-This directory contains an SQLite extension that implements a virtual
-table type that allows users to create, query and manipulate r-tree[1]
-data structures inside of SQLite databases. Users create, populate
-and query r-tree structures using ordinary SQL statements.
-
- 1. SQL Interface
-
- 1.1 Table Creation
- 1.2 Data Manipulation
- 1.3 Data Querying
- 1.4 Introspection and Analysis
-
- 2. Compilation and Deployment
-
- 3. References
-
-
-1. SQL INTERFACE
-
- 1.1 Table Creation.
-
- All r-tree virtual tables have an odd number of columns between
- 3 and 11. Unlike regular SQLite tables, r-tree tables are strongly
- typed.
-
- The leftmost column is always the pimary key and contains 64-bit
- integer values. Each subsequent column contains a 32-bit real
- value. For each pair of real values, the first (leftmost) must be
- less than or equal to the second. R-tree tables may be
- constructed using the following syntax:
-
- CREATE VIRTUAL TABLE <name> USING rtree(<column-names>)
-
- For example:
-
- CREATE VIRTUAL TABLE boxes USING rtree(boxno, xmin, xmax, ymin, ymax);
- INSERT INTO boxes VALUES(1, 1.0, 3.0, 2.0, 4.0);
-
- Constructing a virtual r-tree table <name> creates the following three
- real tables in the database to store the data structure:
-
- <name>_node
- <name>_rowid
- <name>_parent
-
- Dropping or modifying the contents of these tables directly will
- corrupt the r-tree structure. To delete an r-tree from a database,
- use a regular DROP TABLE statement:
-
- DROP TABLE <name>;
-
- Dropping the main r-tree table automatically drops the automatically
- created tables.
-
- 1.2 Data Manipulation (INSERT, UPDATE, DELETE).
-
- The usual INSERT, UPDATE or DELETE syntax is used to manipulate data
- stored in an r-tree table. Please note the following:
-
- * Inserting a NULL value into the primary key column has the
- same effect as inserting a NULL into an INTEGER PRIMARY KEY
- column of a regular table. The system automatically assigns
- an unused integer key value to the new record. Usually, this
- is one greater than the largest primary key value currently
- present in the table.
-
- * Attempting to insert a duplicate primary key value fails with
- an SQLITE_CONSTRAINT error.
-
- * Attempting to insert or modify a record such that the value
- stored in the (N*2)th column is greater than that stored in
- the (N*2+1)th column fails with an SQLITE_CONSTRAINT error.
-
- * When a record is inserted, values are always converted to
- the required type (64-bit integer or 32-bit real) as if they
- were part of an SQL CAST expression. Non-numeric strings are
- converted to zero.
-
- 1.3 Queries.
-
- R-tree tables may be queried using all of the same SQL syntax supported
- by regular tables. However, some query patterns are more efficient
- than others.
-
- R-trees support fast lookup by primary key value (O(logN), like
- regular tables).
-
- Any combination of equality and range (<, <=, >, >=) constraints
- on spatial data columns may be used to optimize other queries. This
- is the key advantage to using r-tree tables instead of creating
- indices on regular tables.
-
- 1.4 Introspection and Analysis.
-
- TODO: Describe rtreenode() and rtreedepth() functions.
-
-
-2. COMPILATION AND USAGE
-
- The easiest way to compile and use the RTREE extension is to build
- and use it as a dynamically loadable SQLite extension. To do this
- using gcc on *nix:
-
- gcc -shared rtree.c -o libSqliteRtree.so
-
- You may need to add "-I" flags so that gcc can find sqlite3ext.h
- and sqlite3.h. The resulting shared lib, libSqliteRtree.so, may be
- loaded into sqlite in the same way as any other dynamicly loadable
- extension.
-
-
-3. REFERENCES
-
- [1] Atonin Guttman, "R-trees - A Dynamic Index Structure For Spatial
- Searching", University of California Berkeley, 1984.
-
- [2] Norbert Beckmann, Hans-Peter Kriegel, Ralf Schneider, Bernhard Seeger,
- "The R*-tree: An Efficient and Robust Access Method for Points and
- Rectangles", Universitaet Bremen, 1990.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree.c
deleted file mode 100644
index e1b16ec0f5d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree.c
+++ /dev/null
@@ -1,4394 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains code for implementations of the r-tree and r*-tree
-** algorithms packaged as an SQLite virtual table module.
-*/
-
-/*
-** Database Format of R-Tree Tables
-** --------------------------------
-**
-** The data structure for a single virtual r-tree table is stored in three
-** native SQLite tables declared as follows. In each case, the '%' character
-** in the table name is replaced with the user-supplied name of the r-tree
-** table.
-**
-** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB)
-** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
-** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...)
-**
-** The data for each node of the r-tree structure is stored in the %_node
-** table. For each node that is not the root node of the r-tree, there is
-** an entry in the %_parent table associating the node with its parent.
-** And for each row of data in the table, there is an entry in the %_rowid
-** table that maps from the entries rowid to the id of the node that it
-** is stored on. If the r-tree contains auxiliary columns, those are stored
-** on the end of the %_rowid table.
-**
-** The root node of an r-tree always exists, even if the r-tree table is
-** empty. The nodeno of the root node is always 1. All other nodes in the
-** table must be the same size as the root node. The content of each node
-** is formatted as follows:
-**
-** 1. If the node is the root node (node 1), then the first 2 bytes
-** of the node contain the tree depth as a big-endian integer.
-** For non-root nodes, the first 2 bytes are left unused.
-**
-** 2. The next 2 bytes contain the number of entries currently
-** stored in the node.
-**
-** 3. The remainder of the node contains the node entries. Each entry
-** consists of a single 8-byte integer followed by an even number
-** of 4-byte coordinates. For leaf nodes the integer is the rowid
-** of a record. For internal nodes it is the node number of a
-** child page.
-*/
-
-#if !defined(SQLITE_CORE) \
- || (defined(SQLITE_ENABLE_RTREE) && !defined(SQLITE_OMIT_VIRTUALTABLE))
-
-#ifndef SQLITE_CORE
- #include "sqlite3ext.h"
- SQLITE_EXTENSION_INIT1
-#else
- #include "sqlite3.h"
-#endif
-
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#ifndef SQLITE_AMALGAMATION
-#include "sqlite3rtree.h"
-typedef sqlite3_int64 i64;
-typedef sqlite3_uint64 u64;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-#endif
-
-/* The following macro is used to suppress compiler warnings.
-*/
-#ifndef UNUSED_PARAMETER
-# define UNUSED_PARAMETER(x) (void)(x)
-#endif
-
-typedef struct Rtree Rtree;
-typedef struct RtreeCursor RtreeCursor;
-typedef struct RtreeNode RtreeNode;
-typedef struct RtreeCell RtreeCell;
-typedef struct RtreeConstraint RtreeConstraint;
-typedef struct RtreeMatchArg RtreeMatchArg;
-typedef struct RtreeGeomCallback RtreeGeomCallback;
-typedef union RtreeCoord RtreeCoord;
-typedef struct RtreeSearchPoint RtreeSearchPoint;
-
-/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
-#define RTREE_MAX_DIMENSIONS 5
-
-/* Maximum number of auxiliary columns */
-#define RTREE_MAX_AUX_COLUMN 100
-
-/* Size of hash table Rtree.aHash. This hash table is not expected to
-** ever contain very many entries, so a fixed number of buckets is
-** used.
-*/
-#define HASHSIZE 97
-
-/* The xBestIndex method of this virtual table requires an estimate of
-** the number of rows in the virtual table to calculate the costs of
-** various strategies. If possible, this estimate is loaded from the
-** sqlite_stat1 table (with RTREE_MIN_ROWEST as a hard-coded minimum).
-** Otherwise, if no sqlite_stat1 entry is available, use
-** RTREE_DEFAULT_ROWEST.
-*/
-#define RTREE_DEFAULT_ROWEST 1048576
-#define RTREE_MIN_ROWEST 100
-
-/*
-** An rtree virtual-table object.
-*/
-struct Rtree {
- sqlite3_vtab base; /* Base class. Must be first */
- sqlite3 *db; /* Host database connection */
- int iNodeSize; /* Size in bytes of each node in the node table */
- u8 nDim; /* Number of dimensions */
- u8 nDim2; /* Twice the number of dimensions */
- u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
- u8 nBytesPerCell; /* Bytes consumed per cell */
- u8 inWrTrans; /* True if inside write transaction */
- u8 nAux; /* # of auxiliary columns in %_rowid */
- int iDepth; /* Current depth of the r-tree structure */
- char *zDb; /* Name of database containing r-tree table */
- char *zName; /* Name of r-tree table */
- u32 nBusy; /* Current number of users of this structure */
- i64 nRowEst; /* Estimated number of rows in this table */
- u32 nCursor; /* Number of open cursors */
- u32 nNodeRef; /* Number RtreeNodes with positive nRef */
- char *zReadAuxSql; /* SQL for statement to read aux data */
-
- /* List of nodes removed during a CondenseTree operation. List is
- ** linked together via the pointer normally used for hash chains -
- ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree
- ** headed by the node (leaf nodes have RtreeNode.iNode==0).
- */
- RtreeNode *pDeleted;
- int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */
-
- /* Blob I/O on xxx_node */
- sqlite3_blob *pNodeBlob;
-
- /* Statements to read/write/delete a record from xxx_node */
- sqlite3_stmt *pWriteNode;
- sqlite3_stmt *pDeleteNode;
-
- /* Statements to read/write/delete a record from xxx_rowid */
- sqlite3_stmt *pReadRowid;
- sqlite3_stmt *pWriteRowid;
- sqlite3_stmt *pDeleteRowid;
-
- /* Statements to read/write/delete a record from xxx_parent */
- sqlite3_stmt *pReadParent;
- sqlite3_stmt *pWriteParent;
- sqlite3_stmt *pDeleteParent;
-
- /* Statement for writing to the "aux:" fields, if there are any */
- sqlite3_stmt *pWriteAux;
-
- RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
-};
-
-/* Possible values for Rtree.eCoordType: */
-#define RTREE_COORD_REAL32 0
-#define RTREE_COORD_INT32 1
-
-/*
-** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will
-** only deal with integer coordinates. No floating point operations
-** will be done.
-*/
-#ifdef SQLITE_RTREE_INT_ONLY
- typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */
- typedef int RtreeValue; /* Low accuracy coordinate */
-# define RTREE_ZERO 0
-#else
- typedef double RtreeDValue; /* High accuracy coordinate */
- typedef float RtreeValue; /* Low accuracy coordinate */
-# define RTREE_ZERO 0.0
-#endif
-
-/*
-** When doing a search of an r-tree, instances of the following structure
-** record intermediate results from the tree walk.
-**
-** The id is always a node-id. For iLevel>=1 the id is the node-id of
-** the node that the RtreeSearchPoint represents. When iLevel==0, however,
-** the id is of the parent node and the cell that RtreeSearchPoint
-** represents is the iCell-th entry in the parent node.
-*/
-struct RtreeSearchPoint {
- RtreeDValue rScore; /* The score for this node. Smallest goes first. */
- sqlite3_int64 id; /* Node ID */
- u8 iLevel; /* 0=entries. 1=leaf node. 2+ for higher */
- u8 eWithin; /* PARTLY_WITHIN or FULLY_WITHIN */
- u8 iCell; /* Cell index within the node */
-};
-
-/*
-** The minimum number of cells allowed for a node is a third of the
-** maximum. In Gutman's notation:
-**
-** m = M/3
-**
-** If an R*-tree "Reinsert" operation is required, the same number of
-** cells are removed from the overfull node and reinserted into the tree.
-*/
-#define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3)
-#define RTREE_REINSERT(p) RTREE_MINCELLS(p)
-#define RTREE_MAXCELLS 51
-
-/*
-** The smallest possible node-size is (512-64)==448 bytes. And the largest
-** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates).
-** Therefore all non-root nodes must contain at least 3 entries. Since
-** 3^40 is greater than 2^64, an r-tree structure always has a depth of
-** 40 or less.
-*/
-#define RTREE_MAX_DEPTH 40
-
-
-/*
-** Number of entries in the cursor RtreeNode cache. The first entry is
-** used to cache the RtreeNode for RtreeCursor.sPoint. The remaining
-** entries cache the RtreeNode for the first elements of the priority queue.
-*/
-#define RTREE_CACHE_SZ 5
-
-/*
-** An rtree cursor object.
-*/
-struct RtreeCursor {
- sqlite3_vtab_cursor base; /* Base class. Must be first */
- u8 atEOF; /* True if at end of search */
- u8 bPoint; /* True if sPoint is valid */
- u8 bAuxValid; /* True if pReadAux is valid */
- int iStrategy; /* Copy of idxNum search parameter */
- int nConstraint; /* Number of entries in aConstraint */
- RtreeConstraint *aConstraint; /* Search constraints. */
- int nPointAlloc; /* Number of slots allocated for aPoint[] */
- int nPoint; /* Number of slots used in aPoint[] */
- int mxLevel; /* iLevel value for root of the tree */
- RtreeSearchPoint *aPoint; /* Priority queue for search points */
- sqlite3_stmt *pReadAux; /* Statement to read aux-data */
- RtreeSearchPoint sPoint; /* Cached next search point */
- RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */
- u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */
-};
-
-/* Return the Rtree of a RtreeCursor */
-#define RTREE_OF_CURSOR(X) ((Rtree*)((X)->base.pVtab))
-
-/*
-** A coordinate can be either a floating point number or a integer. All
-** coordinates within a single R-Tree are always of the same time.
-*/
-union RtreeCoord {
- RtreeValue f; /* Floating point value */
- int i; /* Integer value */
- u32 u; /* Unsigned for byte-order conversions */
-};
-
-/*
-** The argument is an RtreeCoord. Return the value stored within the RtreeCoord
-** formatted as a RtreeDValue (double or int64). This macro assumes that local
-** variable pRtree points to the Rtree structure associated with the
-** RtreeCoord.
-*/
-#ifdef SQLITE_RTREE_INT_ONLY
-# define DCOORD(coord) ((RtreeDValue)coord.i)
-#else
-# define DCOORD(coord) ( \
- (pRtree->eCoordType==RTREE_COORD_REAL32) ? \
- ((double)coord.f) : \
- ((double)coord.i) \
- )
-#endif
-
-/*
-** A search constraint.
-*/
-struct RtreeConstraint {
- int iCoord; /* Index of constrained coordinate */
- int op; /* Constraining operation */
- union {
- RtreeDValue rValue; /* Constraint value. */
- int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*);
- int (*xQueryFunc)(sqlite3_rtree_query_info*);
- } u;
- sqlite3_rtree_query_info *pInfo; /* xGeom and xQueryFunc argument */
-};
-
-/* Possible values for RtreeConstraint.op */
-#define RTREE_EQ 0x41 /* A */
-#define RTREE_LE 0x42 /* B */
-#define RTREE_LT 0x43 /* C */
-#define RTREE_GE 0x44 /* D */
-#define RTREE_GT 0x45 /* E */
-#define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */
-#define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */
-
-
-/*
-** An rtree structure node.
-*/
-struct RtreeNode {
- RtreeNode *pParent; /* Parent node */
- i64 iNode; /* The node number */
- int nRef; /* Number of references to this node */
- int isDirty; /* True if the node needs to be written to disk */
- u8 *zData; /* Content of the node, as should be on disk */
- RtreeNode *pNext; /* Next node in this hash collision chain */
-};
-
-/* Return the number of cells in a node */
-#define NCELL(pNode) readInt16(&(pNode)->zData[2])
-
-/*
-** A single cell from a node, deserialized
-*/
-struct RtreeCell {
- i64 iRowid; /* Node or entry ID */
- RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; /* Bounding box coordinates */
-};
-
-
-/*
-** This object becomes the sqlite3_user_data() for the SQL functions
-** that are created by sqlite3_rtree_geometry_callback() and
-** sqlite3_rtree_query_callback() and which appear on the right of MATCH
-** operators in order to constrain a search.
-**
-** xGeom and xQueryFunc are the callback functions. Exactly one of
-** xGeom and xQueryFunc fields is non-NULL, depending on whether the
-** SQL function was created using sqlite3_rtree_geometry_callback() or
-** sqlite3_rtree_query_callback().
-**
-** This object is deleted automatically by the destructor mechanism in
-** sqlite3_create_function_v2().
-*/
-struct RtreeGeomCallback {
- int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
- int (*xQueryFunc)(sqlite3_rtree_query_info*);
- void (*xDestructor)(void*);
- void *pContext;
-};
-
-/*
-** An instance of this structure (in the form of a BLOB) is returned by
-** the SQL functions that sqlite3_rtree_geometry_callback() and
-** sqlite3_rtree_query_callback() create, and is read as the right-hand
-** operand to the MATCH operator of an R-Tree.
-*/
-struct RtreeMatchArg {
- u32 iSize; /* Size of this object */
- RtreeGeomCallback cb; /* Info about the callback functions */
- int nParam; /* Number of parameters to the SQL function */
- sqlite3_value **apSqlParam; /* Original SQL parameter values */
- RtreeDValue aParam[1]; /* Values for parameters to the SQL function */
-};
-
-#ifndef MAX
-# define MAX(x,y) ((x) < (y) ? (y) : (x))
-#endif
-#ifndef MIN
-# define MIN(x,y) ((x) > (y) ? (y) : (x))
-#endif
-
-/* What version of GCC is being used. 0 means GCC is not being used .
-** Note that the GCC_VERSION macro will also be set correctly when using
-** clang, since clang works hard to be gcc compatible. So the gcc
-** optimizations will also work when compiling with clang.
-*/
-#ifndef GCC_VERSION
-#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
-# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
-#else
-# define GCC_VERSION 0
-#endif
-#endif
-
-/* The testcase() macro should already be defined in the amalgamation. If
-** it is not, make it a no-op.
-*/
-#ifndef SQLITE_AMALGAMATION
-# define testcase(X)
-#endif
-
-/*
-** Macros to determine whether the machine is big or little endian,
-** and whether or not that determination is run-time or compile-time.
-**
-** For best performance, an attempt is made to guess at the byte-order
-** using C-preprocessor macros. If that is unsuccessful, or if
-** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
-** at run-time.
-*/
-#ifndef SQLITE_BYTEORDER
-#if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
- defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)
-# define SQLITE_BYTEORDER 1234
-#elif defined(sparc) || defined(__ppc__)
-# define SQLITE_BYTEORDER 4321
-#else
-# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
-#endif
-#endif
-
-
-/* What version of MSVC is being used. 0 means MSVC is not being used */
-#ifndef MSVC_VERSION
-#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
-# define MSVC_VERSION _MSC_VER
-#else
-# define MSVC_VERSION 0
-#endif
-#endif
-
-/*
-** Functions to deserialize a 16 bit integer, 32 bit real number and
-** 64 bit integer. The deserialized value is returned.
-*/
-static int readInt16(u8 *p){
- return (p[0]<<8) + p[1];
-}
-static void readCoord(u8 *p, RtreeCoord *pCoord){
- assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */
-#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
- pCoord->u = _byteswap_ulong(*(u32*)p);
-#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
- pCoord->u = __builtin_bswap32(*(u32*)p);
-#elif SQLITE_BYTEORDER==4321
- pCoord->u = *(u32*)p;
-#else
- pCoord->u = (
- (((u32)p[0]) << 24) +
- (((u32)p[1]) << 16) +
- (((u32)p[2]) << 8) +
- (((u32)p[3]) << 0)
- );
-#endif
-}
-static i64 readInt64(u8 *p){
-#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
- u64 x;
- memcpy(&x, p, 8);
- return (i64)_byteswap_uint64(x);
-#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
- u64 x;
- memcpy(&x, p, 8);
- return (i64)__builtin_bswap64(x);
-#elif SQLITE_BYTEORDER==4321
- i64 x;
- memcpy(&x, p, 8);
- return x;
-#else
- return (i64)(
- (((u64)p[0]) << 56) +
- (((u64)p[1]) << 48) +
- (((u64)p[2]) << 40) +
- (((u64)p[3]) << 32) +
- (((u64)p[4]) << 24) +
- (((u64)p[5]) << 16) +
- (((u64)p[6]) << 8) +
- (((u64)p[7]) << 0)
- );
-#endif
-}
-
-/*
-** Functions to serialize a 16 bit integer, 32 bit real number and
-** 64 bit integer. The value returned is the number of bytes written
-** to the argument buffer (always 2, 4 and 8 respectively).
-*/
-static void writeInt16(u8 *p, int i){
- p[0] = (i>> 8)&0xFF;
- p[1] = (i>> 0)&0xFF;
-}
-static int writeCoord(u8 *p, RtreeCoord *pCoord){
- u32 i;
- assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */
- assert( sizeof(RtreeCoord)==4 );
- assert( sizeof(u32)==4 );
-#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
- i = __builtin_bswap32(pCoord->u);
- memcpy(p, &i, 4);
-#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
- i = _byteswap_ulong(pCoord->u);
- memcpy(p, &i, 4);
-#elif SQLITE_BYTEORDER==4321
- i = pCoord->u;
- memcpy(p, &i, 4);
-#else
- i = pCoord->u;
- p[0] = (i>>24)&0xFF;
- p[1] = (i>>16)&0xFF;
- p[2] = (i>> 8)&0xFF;
- p[3] = (i>> 0)&0xFF;
-#endif
- return 4;
-}
-static int writeInt64(u8 *p, i64 i){
-#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
- i = (i64)__builtin_bswap64((u64)i);
- memcpy(p, &i, 8);
-#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
- i = (i64)_byteswap_uint64((u64)i);
- memcpy(p, &i, 8);
-#elif SQLITE_BYTEORDER==4321
- memcpy(p, &i, 8);
-#else
- p[0] = (i>>56)&0xFF;
- p[1] = (i>>48)&0xFF;
- p[2] = (i>>40)&0xFF;
- p[3] = (i>>32)&0xFF;
- p[4] = (i>>24)&0xFF;
- p[5] = (i>>16)&0xFF;
- p[6] = (i>> 8)&0xFF;
- p[7] = (i>> 0)&0xFF;
-#endif
- return 8;
-}
-
-/*
-** Increment the reference count of node p.
-*/
-static void nodeReference(RtreeNode *p){
- if( p ){
- assert( p->nRef>0 );
- p->nRef++;
- }
-}
-
-/*
-** Clear the content of node p (set all bytes to 0x00).
-*/
-static void nodeZero(Rtree *pRtree, RtreeNode *p){
- memset(&p->zData[2], 0, pRtree->iNodeSize-2);
- p->isDirty = 1;
-}
-
-/*
-** Given a node number iNode, return the corresponding key to use
-** in the Rtree.aHash table.
-*/
-static int nodeHash(i64 iNode){
- return iNode % HASHSIZE;
-}
-
-/*
-** Search the node hash table for node iNode. If found, return a pointer
-** to it. Otherwise, return 0.
-*/
-static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){
- RtreeNode *p;
- for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext);
- return p;
-}
-
-/*
-** Add node pNode to the node hash table.
-*/
-static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){
- int iHash;
- assert( pNode->pNext==0 );
- iHash = nodeHash(pNode->iNode);
- pNode->pNext = pRtree->aHash[iHash];
- pRtree->aHash[iHash] = pNode;
-}
-
-/*
-** Remove node pNode from the node hash table.
-*/
-static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){
- RtreeNode **pp;
- if( pNode->iNode!=0 ){
- pp = &pRtree->aHash[nodeHash(pNode->iNode)];
- for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); }
- *pp = pNode->pNext;
- pNode->pNext = 0;
- }
-}
-
-/*
-** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0),
-** indicating that node has not yet been assigned a node number. It is
-** assigned a node number when nodeWrite() is called to write the
-** node contents out to the database.
-*/
-static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
- RtreeNode *pNode;
- pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize);
- if( pNode ){
- memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
- pNode->zData = (u8 *)&pNode[1];
- pNode->nRef = 1;
- pRtree->nNodeRef++;
- pNode->pParent = pParent;
- pNode->isDirty = 1;
- nodeReference(pParent);
- }
- return pNode;
-}
-
-/*
-** Clear the Rtree.pNodeBlob object
-*/
-static void nodeBlobReset(Rtree *pRtree){
- if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){
- sqlite3_blob *pBlob = pRtree->pNodeBlob;
- pRtree->pNodeBlob = 0;
- sqlite3_blob_close(pBlob);
- }
-}
-
-/*
-** Obtain a reference to an r-tree node.
-*/
-static int nodeAcquire(
- Rtree *pRtree, /* R-tree structure */
- i64 iNode, /* Node number to load */
- RtreeNode *pParent, /* Either the parent node or NULL */
- RtreeNode **ppNode /* OUT: Acquired node */
-){
- int rc = SQLITE_OK;
- RtreeNode *pNode = 0;
-
- /* Check if the requested node is already in the hash table. If so,
- ** increase its reference count and return it.
- */
- if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
- assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
- if( pParent && !pNode->pParent ){
- pParent->nRef++;
- pNode->pParent = pParent;
- }
- pNode->nRef++;
- *ppNode = pNode;
- return SQLITE_OK;
- }
-
- if( pRtree->pNodeBlob ){
- sqlite3_blob *pBlob = pRtree->pNodeBlob;
- pRtree->pNodeBlob = 0;
- rc = sqlite3_blob_reopen(pBlob, iNode);
- pRtree->pNodeBlob = pBlob;
- if( rc ){
- nodeBlobReset(pRtree);
- if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM;
- }
- }
- if( pRtree->pNodeBlob==0 ){
- char *zTab = sqlite3_mprintf("%s_node", pRtree->zName);
- if( zTab==0 ) return SQLITE_NOMEM;
- rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, zTab, "data", iNode, 0,
- &pRtree->pNodeBlob);
- sqlite3_free(zTab);
- }
- if( rc ){
- nodeBlobReset(pRtree);
- *ppNode = 0;
- /* If unable to open an sqlite3_blob on the desired row, that can only
- ** be because the shadow tables hold erroneous data. */
- if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB;
- }else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
- pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
- if( !pNode ){
- rc = SQLITE_NOMEM;
- }else{
- pNode->pParent = pParent;
- pNode->zData = (u8 *)&pNode[1];
- pNode->nRef = 1;
- pRtree->nNodeRef++;
- pNode->iNode = iNode;
- pNode->isDirty = 0;
- pNode->pNext = 0;
- rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
- pRtree->iNodeSize, 0);
- nodeReference(pParent);
- }
- }
-
- /* If the root node was just loaded, set pRtree->iDepth to the height
- ** of the r-tree structure. A height of zero means all data is stored on
- ** the root node. A height of one means the children of the root node
- ** are the leaves, and so on. If the depth as specified on the root node
- ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
- */
- if( pNode && iNode==1 ){
- pRtree->iDepth = readInt16(pNode->zData);
- if( pRtree->iDepth>RTREE_MAX_DEPTH ){
- rc = SQLITE_CORRUPT_VTAB;
- }
- }
-
- /* If no error has occurred so far, check if the "number of entries"
- ** field on the node is too large. If so, set the return code to
- ** SQLITE_CORRUPT_VTAB.
- */
- if( pNode && rc==SQLITE_OK ){
- if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
- rc = SQLITE_CORRUPT_VTAB;
- }
- }
-
- if( rc==SQLITE_OK ){
- if( pNode!=0 ){
- nodeHashInsert(pRtree, pNode);
- }else{
- rc = SQLITE_CORRUPT_VTAB;
- }
- *ppNode = pNode;
- }else{
- if( pNode ){
- pRtree->nNodeRef--;
- sqlite3_free(pNode);
- }
- *ppNode = 0;
- }
-
- return rc;
-}
-
-/*
-** Overwrite cell iCell of node pNode with the contents of pCell.
-*/
-static void nodeOverwriteCell(
- Rtree *pRtree, /* The overall R-Tree */
- RtreeNode *pNode, /* The node into which the cell is to be written */
- RtreeCell *pCell, /* The cell to write */
- int iCell /* Index into pNode into which pCell is written */
-){
- int ii;
- u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
- p += writeInt64(p, pCell->iRowid);
- for(ii=0; ii<pRtree->nDim2; ii++){
- p += writeCoord(p, &pCell->aCoord[ii]);
- }
- pNode->isDirty = 1;
-}
-
-/*
-** Remove the cell with index iCell from node pNode.
-*/
-static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){
- u8 *pDst = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
- u8 *pSrc = &pDst[pRtree->nBytesPerCell];
- int nByte = (NCELL(pNode) - iCell - 1) * pRtree->nBytesPerCell;
- memmove(pDst, pSrc, nByte);
- writeInt16(&pNode->zData[2], NCELL(pNode)-1);
- pNode->isDirty = 1;
-}
-
-/*
-** Insert the contents of cell pCell into node pNode. If the insert
-** is successful, return SQLITE_OK.
-**
-** If there is not enough free space in pNode, return SQLITE_FULL.
-*/
-static int nodeInsertCell(
- Rtree *pRtree, /* The overall R-Tree */
- RtreeNode *pNode, /* Write new cell into this node */
- RtreeCell *pCell /* The cell to be inserted */
-){
- int nCell; /* Current number of cells in pNode */
- int nMaxCell; /* Maximum number of cells for pNode */
-
- nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell;
- nCell = NCELL(pNode);
-
- assert( nCell<=nMaxCell );
- if( nCell<nMaxCell ){
- nodeOverwriteCell(pRtree, pNode, pCell, nCell);
- writeInt16(&pNode->zData[2], nCell+1);
- pNode->isDirty = 1;
- }
-
- return (nCell==nMaxCell);
-}
-
-/*
-** If the node is dirty, write it out to the database.
-*/
-static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){
- int rc = SQLITE_OK;
- if( pNode->isDirty ){
- sqlite3_stmt *p = pRtree->pWriteNode;
- if( pNode->iNode ){
- sqlite3_bind_int64(p, 1, pNode->iNode);
- }else{
- sqlite3_bind_null(p, 1);
- }
- sqlite3_bind_blob(p, 2, pNode->zData, pRtree->iNodeSize, SQLITE_STATIC);
- sqlite3_step(p);
- pNode->isDirty = 0;
- rc = sqlite3_reset(p);
- sqlite3_bind_null(p, 2);
- if( pNode->iNode==0 && rc==SQLITE_OK ){
- pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
- nodeHashInsert(pRtree, pNode);
- }
- }
- return rc;
-}
-
-/*
-** Release a reference to a node. If the node is dirty and the reference
-** count drops to zero, the node data is written to the database.
-*/
-static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){
- int rc = SQLITE_OK;
- if( pNode ){
- assert( pNode->nRef>0 );
- assert( pRtree->nNodeRef>0 );
- pNode->nRef--;
- if( pNode->nRef==0 ){
- pRtree->nNodeRef--;
- if( pNode->iNode==1 ){
- pRtree->iDepth = -1;
- }
- if( pNode->pParent ){
- rc = nodeRelease(pRtree, pNode->pParent);
- }
- if( rc==SQLITE_OK ){
- rc = nodeWrite(pRtree, pNode);
- }
- nodeHashDelete(pRtree, pNode);
- sqlite3_free(pNode);
- }
- }
- return rc;
-}
-
-/*
-** Return the 64-bit integer value associated with cell iCell of
-** node pNode. If pNode is a leaf node, this is a rowid. If it is
-** an internal node, then the 64-bit integer is a child page number.
-*/
-static i64 nodeGetRowid(
- Rtree *pRtree, /* The overall R-Tree */
- RtreeNode *pNode, /* The node from which to extract the ID */
- int iCell /* The cell index from which to extract the ID */
-){
- assert( iCell<NCELL(pNode) );
- return readInt64(&pNode->zData[4 + pRtree->nBytesPerCell*iCell]);
-}
-
-/*
-** Return coordinate iCoord from cell iCell in node pNode.
-*/
-static void nodeGetCoord(
- Rtree *pRtree, /* The overall R-Tree */
- RtreeNode *pNode, /* The node from which to extract a coordinate */
- int iCell, /* The index of the cell within the node */
- int iCoord, /* Which coordinate to extract */
- RtreeCoord *pCoord /* OUT: Space to write result to */
-){
- readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
-}
-
-/*
-** Deserialize cell iCell of node pNode. Populate the structure pointed
-** to by pCell with the results.
-*/
-static void nodeGetCell(
- Rtree *pRtree, /* The overall R-Tree */
- RtreeNode *pNode, /* The node containing the cell to be read */
- int iCell, /* Index of the cell within the node */
- RtreeCell *pCell /* OUT: Write the cell contents here */
-){
- u8 *pData;
- RtreeCoord *pCoord;
- int ii = 0;
- pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
- pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell);
- pCoord = pCell->aCoord;
- do{
- readCoord(pData, &pCoord[ii]);
- readCoord(pData+4, &pCoord[ii+1]);
- pData += 8;
- ii += 2;
- }while( ii<pRtree->nDim2 );
-}
-
-
-/* Forward declaration for the function that does the work of
-** the virtual table module xCreate() and xConnect() methods.
-*/
-static int rtreeInit(
- sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int
-);
-
-/*
-** Rtree virtual table module xCreate method.
-*/
-static int rtreeCreate(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
-}
-
-/*
-** Rtree virtual table module xConnect method.
-*/
-static int rtreeConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0);
-}
-
-/*
-** Increment the r-tree reference count.
-*/
-static void rtreeReference(Rtree *pRtree){
- pRtree->nBusy++;
-}
-
-/*
-** Decrement the r-tree reference count. When the reference count reaches
-** zero the structure is deleted.
-*/
-static void rtreeRelease(Rtree *pRtree){
- pRtree->nBusy--;
- if( pRtree->nBusy==0 ){
- pRtree->inWrTrans = 0;
- assert( pRtree->nCursor==0 );
- nodeBlobReset(pRtree);
- assert( pRtree->nNodeRef==0 );
- sqlite3_finalize(pRtree->pWriteNode);
- sqlite3_finalize(pRtree->pDeleteNode);
- sqlite3_finalize(pRtree->pReadRowid);
- sqlite3_finalize(pRtree->pWriteRowid);
- sqlite3_finalize(pRtree->pDeleteRowid);
- sqlite3_finalize(pRtree->pReadParent);
- sqlite3_finalize(pRtree->pWriteParent);
- sqlite3_finalize(pRtree->pDeleteParent);
- sqlite3_finalize(pRtree->pWriteAux);
- sqlite3_free(pRtree->zReadAuxSql);
- sqlite3_free(pRtree);
- }
-}
-
-/*
-** Rtree virtual table module xDisconnect method.
-*/
-static int rtreeDisconnect(sqlite3_vtab *pVtab){
- rtreeRelease((Rtree *)pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Rtree virtual table module xDestroy method.
-*/
-static int rtreeDestroy(sqlite3_vtab *pVtab){
- Rtree *pRtree = (Rtree *)pVtab;
- int rc;
- char *zCreate = sqlite3_mprintf(
- "DROP TABLE '%q'.'%q_node';"
- "DROP TABLE '%q'.'%q_rowid';"
- "DROP TABLE '%q'.'%q_parent';",
- pRtree->zDb, pRtree->zName,
- pRtree->zDb, pRtree->zName,
- pRtree->zDb, pRtree->zName
- );
- if( !zCreate ){
- rc = SQLITE_NOMEM;
- }else{
- nodeBlobReset(pRtree);
- rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0);
- sqlite3_free(zCreate);
- }
- if( rc==SQLITE_OK ){
- rtreeRelease(pRtree);
- }
-
- return rc;
-}
-
-/*
-** Rtree virtual table module xOpen method.
-*/
-static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- int rc = SQLITE_NOMEM;
- Rtree *pRtree = (Rtree *)pVTab;
- RtreeCursor *pCsr;
-
- pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
- if( pCsr ){
- memset(pCsr, 0, sizeof(RtreeCursor));
- pCsr->base.pVtab = pVTab;
- rc = SQLITE_OK;
- pRtree->nCursor++;
- }
- *ppCursor = (sqlite3_vtab_cursor *)pCsr;
-
- return rc;
-}
-
-
-/*
-** Free the RtreeCursor.aConstraint[] array and its contents.
-*/
-static void freeCursorConstraints(RtreeCursor *pCsr){
- if( pCsr->aConstraint ){
- int i; /* Used to iterate through constraint array */
- for(i=0; i<pCsr->nConstraint; i++){
- sqlite3_rtree_query_info *pInfo = pCsr->aConstraint[i].pInfo;
- if( pInfo ){
- if( pInfo->xDelUser ) pInfo->xDelUser(pInfo->pUser);
- sqlite3_free(pInfo);
- }
- }
- sqlite3_free(pCsr->aConstraint);
- pCsr->aConstraint = 0;
- }
-}
-
-/*
-** Rtree virtual table module xClose method.
-*/
-static int rtreeClose(sqlite3_vtab_cursor *cur){
- Rtree *pRtree = (Rtree *)(cur->pVtab);
- int ii;
- RtreeCursor *pCsr = (RtreeCursor *)cur;
- assert( pRtree->nCursor>0 );
- freeCursorConstraints(pCsr);
- sqlite3_finalize(pCsr->pReadAux);
- sqlite3_free(pCsr->aPoint);
- for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
- sqlite3_free(pCsr);
- pRtree->nCursor--;
- nodeBlobReset(pRtree);
- return SQLITE_OK;
-}
-
-/*
-** Rtree virtual table module xEof method.
-**
-** Return non-zero if the cursor does not currently point to a valid
-** record (i.e if the scan has finished), or zero otherwise.
-*/
-static int rtreeEof(sqlite3_vtab_cursor *cur){
- RtreeCursor *pCsr = (RtreeCursor *)cur;
- return pCsr->atEOF;
-}
-
-/*
-** Convert raw bits from the on-disk RTree record into a coordinate value.
-** The on-disk format is big-endian and needs to be converted for little-
-** endian platforms. The on-disk record stores integer coordinates if
-** eInt is true and it stores 32-bit floating point records if eInt is
-** false. a[] is the four bytes of the on-disk record to be decoded.
-** Store the results in "r".
-**
-** There are five versions of this macro. The last one is generic. The
-** other four are various architectures-specific optimizations.
-*/
-#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
-#define RTREE_DECODE_COORD(eInt, a, r) { \
- RtreeCoord c; /* Coordinate decoded */ \
- c.u = _byteswap_ulong(*(u32*)a); \
- r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
-}
-#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
-#define RTREE_DECODE_COORD(eInt, a, r) { \
- RtreeCoord c; /* Coordinate decoded */ \
- c.u = __builtin_bswap32(*(u32*)a); \
- r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
-}
-#elif SQLITE_BYTEORDER==1234
-#define RTREE_DECODE_COORD(eInt, a, r) { \
- RtreeCoord c; /* Coordinate decoded */ \
- memcpy(&c.u,a,4); \
- c.u = ((c.u>>24)&0xff)|((c.u>>8)&0xff00)| \
- ((c.u&0xff)<<24)|((c.u&0xff00)<<8); \
- r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
-}
-#elif SQLITE_BYTEORDER==4321
-#define RTREE_DECODE_COORD(eInt, a, r) { \
- RtreeCoord c; /* Coordinate decoded */ \
- memcpy(&c.u,a,4); \
- r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
-}
-#else
-#define RTREE_DECODE_COORD(eInt, a, r) { \
- RtreeCoord c; /* Coordinate decoded */ \
- c.u = ((u32)a[0]<<24) + ((u32)a[1]<<16) \
- +((u32)a[2]<<8) + a[3]; \
- r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
-}
-#endif
-
-/*
-** Check the RTree node or entry given by pCellData and p against the MATCH
-** constraint pConstraint.
-*/
-static int rtreeCallbackConstraint(
- RtreeConstraint *pConstraint, /* The constraint to test */
- int eInt, /* True if RTree holding integer coordinates */
- u8 *pCellData, /* Raw cell content */
- RtreeSearchPoint *pSearch, /* Container of this cell */
- sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */
- int *peWithin /* OUT: visibility of the cell */
-){
- sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */
- int nCoord = pInfo->nCoord; /* No. of coordinates */
- int rc; /* Callback return code */
- RtreeCoord c; /* Translator union */
- sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */
-
- assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY );
- assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 );
-
- if( pConstraint->op==RTREE_QUERY && pSearch->iLevel==1 ){
- pInfo->iRowid = readInt64(pCellData);
- }
- pCellData += 8;
-#ifndef SQLITE_RTREE_INT_ONLY
- if( eInt==0 ){
- switch( nCoord ){
- case 10: readCoord(pCellData+36, &c); aCoord[9] = c.f;
- readCoord(pCellData+32, &c); aCoord[8] = c.f;
- case 8: readCoord(pCellData+28, &c); aCoord[7] = c.f;
- readCoord(pCellData+24, &c); aCoord[6] = c.f;
- case 6: readCoord(pCellData+20, &c); aCoord[5] = c.f;
- readCoord(pCellData+16, &c); aCoord[4] = c.f;
- case 4: readCoord(pCellData+12, &c); aCoord[3] = c.f;
- readCoord(pCellData+8, &c); aCoord[2] = c.f;
- default: readCoord(pCellData+4, &c); aCoord[1] = c.f;
- readCoord(pCellData, &c); aCoord[0] = c.f;
- }
- }else
-#endif
- {
- switch( nCoord ){
- case 10: readCoord(pCellData+36, &c); aCoord[9] = c.i;
- readCoord(pCellData+32, &c); aCoord[8] = c.i;
- case 8: readCoord(pCellData+28, &c); aCoord[7] = c.i;
- readCoord(pCellData+24, &c); aCoord[6] = c.i;
- case 6: readCoord(pCellData+20, &c); aCoord[5] = c.i;
- readCoord(pCellData+16, &c); aCoord[4] = c.i;
- case 4: readCoord(pCellData+12, &c); aCoord[3] = c.i;
- readCoord(pCellData+8, &c); aCoord[2] = c.i;
- default: readCoord(pCellData+4, &c); aCoord[1] = c.i;
- readCoord(pCellData, &c); aCoord[0] = c.i;
- }
- }
- if( pConstraint->op==RTREE_MATCH ){
- int eWithin = 0;
- rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo,
- nCoord, aCoord, &eWithin);
- if( eWithin==0 ) *peWithin = NOT_WITHIN;
- *prScore = RTREE_ZERO;
- }else{
- pInfo->aCoord = aCoord;
- pInfo->iLevel = pSearch->iLevel - 1;
- pInfo->rScore = pInfo->rParentScore = pSearch->rScore;
- pInfo->eWithin = pInfo->eParentWithin = pSearch->eWithin;
- rc = pConstraint->u.xQueryFunc(pInfo);
- if( pInfo->eWithin<*peWithin ) *peWithin = pInfo->eWithin;
- if( pInfo->rScore<*prScore || *prScore<RTREE_ZERO ){
- *prScore = pInfo->rScore;
- }
- }
- return rc;
-}
-
-/*
-** Check the internal RTree node given by pCellData against constraint p.
-** If this constraint cannot be satisfied by any child within the node,
-** set *peWithin to NOT_WITHIN.
-*/
-static void rtreeNonleafConstraint(
- RtreeConstraint *p, /* The constraint to test */
- int eInt, /* True if RTree holds integer coordinates */
- u8 *pCellData, /* Raw cell content as appears on disk */
- int *peWithin /* Adjust downward, as appropriate */
-){
- sqlite3_rtree_dbl val; /* Coordinate value convert to a double */
-
- /* p->iCoord might point to either a lower or upper bound coordinate
- ** in a coordinate pair. But make pCellData point to the lower bound.
- */
- pCellData += 8 + 4*(p->iCoord&0xfe);
-
- assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
- || p->op==RTREE_GT || p->op==RTREE_EQ );
- assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
- switch( p->op ){
- case RTREE_LE:
- case RTREE_LT:
- case RTREE_EQ:
- RTREE_DECODE_COORD(eInt, pCellData, val);
- /* val now holds the lower bound of the coordinate pair */
- if( p->u.rValue>=val ) return;
- if( p->op!=RTREE_EQ ) break; /* RTREE_LE and RTREE_LT end here */
- /* Fall through for the RTREE_EQ case */
-
- default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */
- pCellData += 4;
- RTREE_DECODE_COORD(eInt, pCellData, val);
- /* val now holds the upper bound of the coordinate pair */
- if( p->u.rValue<=val ) return;
- }
- *peWithin = NOT_WITHIN;
-}
-
-/*
-** Check the leaf RTree cell given by pCellData against constraint p.
-** If this constraint is not satisfied, set *peWithin to NOT_WITHIN.
-** If the constraint is satisfied, leave *peWithin unchanged.
-**
-** The constraint is of the form: xN op $val
-**
-** The op is given by p->op. The xN is p->iCoord-th coordinate in
-** pCellData. $val is given by p->u.rValue.
-*/
-static void rtreeLeafConstraint(
- RtreeConstraint *p, /* The constraint to test */
- int eInt, /* True if RTree holds integer coordinates */
- u8 *pCellData, /* Raw cell content as appears on disk */
- int *peWithin /* Adjust downward, as appropriate */
-){
- RtreeDValue xN; /* Coordinate value converted to a double */
-
- assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
- || p->op==RTREE_GT || p->op==RTREE_EQ );
- pCellData += 8 + p->iCoord*4;
- assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
- RTREE_DECODE_COORD(eInt, pCellData, xN);
- switch( p->op ){
- case RTREE_LE: if( xN <= p->u.rValue ) return; break;
- case RTREE_LT: if( xN < p->u.rValue ) return; break;
- case RTREE_GE: if( xN >= p->u.rValue ) return; break;
- case RTREE_GT: if( xN > p->u.rValue ) return; break;
- default: if( xN == p->u.rValue ) return; break;
- }
- *peWithin = NOT_WITHIN;
-}
-
-/*
-** One of the cells in node pNode is guaranteed to have a 64-bit
-** integer value equal to iRowid. Return the index of this cell.
-*/
-static int nodeRowidIndex(
- Rtree *pRtree,
- RtreeNode *pNode,
- i64 iRowid,
- int *piIndex
-){
- int ii;
- int nCell = NCELL(pNode);
- assert( nCell<200 );
- for(ii=0; ii<nCell; ii++){
- if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
- *piIndex = ii;
- return SQLITE_OK;
- }
- }
- return SQLITE_CORRUPT_VTAB;
-}
-
-/*
-** Return the index of the cell containing a pointer to node pNode
-** in its parent. If pNode is the root node, return -1.
-*/
-static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
- RtreeNode *pParent = pNode->pParent;
- if( pParent ){
- return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
- }
- *piIndex = -1;
- return SQLITE_OK;
-}
-
-/*
-** Compare two search points. Return negative, zero, or positive if the first
-** is less than, equal to, or greater than the second.
-**
-** The rScore is the primary key. Smaller rScore values come first.
-** If the rScore is a tie, then use iLevel as the tie breaker with smaller
-** iLevel values coming first. In this way, if rScore is the same for all
-** SearchPoints, then iLevel becomes the deciding factor and the result
-** is a depth-first search, which is the desired default behavior.
-*/
-static int rtreeSearchPointCompare(
- const RtreeSearchPoint *pA,
- const RtreeSearchPoint *pB
-){
- if( pA->rScore<pB->rScore ) return -1;
- if( pA->rScore>pB->rScore ) return +1;
- if( pA->iLevel<pB->iLevel ) return -1;
- if( pA->iLevel>pB->iLevel ) return +1;
- return 0;
-}
-
-/*
-** Interchange two search points in a cursor.
-*/
-static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){
- RtreeSearchPoint t = p->aPoint[i];
- assert( i<j );
- p->aPoint[i] = p->aPoint[j];
- p->aPoint[j] = t;
- i++; j++;
- if( i<RTREE_CACHE_SZ ){
- if( j>=RTREE_CACHE_SZ ){
- nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]);
- p->aNode[i] = 0;
- }else{
- RtreeNode *pTemp = p->aNode[i];
- p->aNode[i] = p->aNode[j];
- p->aNode[j] = pTemp;
- }
- }
-}
-
-/*
-** Return the search point with the lowest current score.
-*/
-static RtreeSearchPoint *rtreeSearchPointFirst(RtreeCursor *pCur){
- return pCur->bPoint ? &pCur->sPoint : pCur->nPoint ? pCur->aPoint : 0;
-}
-
-/*
-** Get the RtreeNode for the search point with the lowest score.
-*/
-static RtreeNode *rtreeNodeOfFirstSearchPoint(RtreeCursor *pCur, int *pRC){
- sqlite3_int64 id;
- int ii = 1 - pCur->bPoint;
- assert( ii==0 || ii==1 );
- assert( pCur->bPoint || pCur->nPoint );
- if( pCur->aNode[ii]==0 ){
- assert( pRC!=0 );
- id = ii ? pCur->aPoint[0].id : pCur->sPoint.id;
- *pRC = nodeAcquire(RTREE_OF_CURSOR(pCur), id, 0, &pCur->aNode[ii]);
- }
- return pCur->aNode[ii];
-}
-
-/*
-** Push a new element onto the priority queue
-*/
-static RtreeSearchPoint *rtreeEnqueue(
- RtreeCursor *pCur, /* The cursor */
- RtreeDValue rScore, /* Score for the new search point */
- u8 iLevel /* Level for the new search point */
-){
- int i, j;
- RtreeSearchPoint *pNew;
- if( pCur->nPoint>=pCur->nPointAlloc ){
- int nNew = pCur->nPointAlloc*2 + 8;
- pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
- if( pNew==0 ) return 0;
- pCur->aPoint = pNew;
- pCur->nPointAlloc = nNew;
- }
- i = pCur->nPoint++;
- pNew = pCur->aPoint + i;
- pNew->rScore = rScore;
- pNew->iLevel = iLevel;
- assert( iLevel<=RTREE_MAX_DEPTH );
- while( i>0 ){
- RtreeSearchPoint *pParent;
- j = (i-1)/2;
- pParent = pCur->aPoint + j;
- if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break;
- rtreeSearchPointSwap(pCur, j, i);
- i = j;
- pNew = pParent;
- }
- return pNew;
-}
-
-/*
-** Allocate a new RtreeSearchPoint and return a pointer to it. Return
-** NULL if malloc fails.
-*/
-static RtreeSearchPoint *rtreeSearchPointNew(
- RtreeCursor *pCur, /* The cursor */
- RtreeDValue rScore, /* Score for the new search point */
- u8 iLevel /* Level for the new search point */
-){
- RtreeSearchPoint *pNew, *pFirst;
- pFirst = rtreeSearchPointFirst(pCur);
- pCur->anQueue[iLevel]++;
- if( pFirst==0
- || pFirst->rScore>rScore
- || (pFirst->rScore==rScore && pFirst->iLevel>iLevel)
- ){
- if( pCur->bPoint ){
- int ii;
- pNew = rtreeEnqueue(pCur, rScore, iLevel);
- if( pNew==0 ) return 0;
- ii = (int)(pNew - pCur->aPoint) + 1;
- if( ii<RTREE_CACHE_SZ ){
- assert( pCur->aNode[ii]==0 );
- pCur->aNode[ii] = pCur->aNode[0];
- }else{
- nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]);
- }
- pCur->aNode[0] = 0;
- *pNew = pCur->sPoint;
- }
- pCur->sPoint.rScore = rScore;
- pCur->sPoint.iLevel = iLevel;
- pCur->bPoint = 1;
- return &pCur->sPoint;
- }else{
- return rtreeEnqueue(pCur, rScore, iLevel);
- }
-}
-
-#if 0
-/* Tracing routines for the RtreeSearchPoint queue */
-static void tracePoint(RtreeSearchPoint *p, int idx, RtreeCursor *pCur){
- if( idx<0 ){ printf(" s"); }else{ printf("%2d", idx); }
- printf(" %d.%05lld.%02d %g %d",
- p->iLevel, p->id, p->iCell, p->rScore, p->eWithin
- );
- idx++;
- if( idx<RTREE_CACHE_SZ ){
- printf(" %p\n", pCur->aNode[idx]);
- }else{
- printf("\n");
- }
-}
-static void traceQueue(RtreeCursor *pCur, const char *zPrefix){
- int ii;
- printf("=== %9s ", zPrefix);
- if( pCur->bPoint ){
- tracePoint(&pCur->sPoint, -1, pCur);
- }
- for(ii=0; ii<pCur->nPoint; ii++){
- if( ii>0 || pCur->bPoint ) printf(" ");
- tracePoint(&pCur->aPoint[ii], ii, pCur);
- }
-}
-# define RTREE_QUEUE_TRACE(A,B) traceQueue(A,B)
-#else
-# define RTREE_QUEUE_TRACE(A,B) /* no-op */
-#endif
-
-/* Remove the search point with the lowest current score.
-*/
-static void rtreeSearchPointPop(RtreeCursor *p){
- int i, j, k, n;
- i = 1 - p->bPoint;
- assert( i==0 || i==1 );
- if( p->aNode[i] ){
- nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]);
- p->aNode[i] = 0;
- }
- if( p->bPoint ){
- p->anQueue[p->sPoint.iLevel]--;
- p->bPoint = 0;
- }else if( p->nPoint ){
- p->anQueue[p->aPoint[0].iLevel]--;
- n = --p->nPoint;
- p->aPoint[0] = p->aPoint[n];
- if( n<RTREE_CACHE_SZ-1 ){
- p->aNode[1] = p->aNode[n+1];
- p->aNode[n+1] = 0;
- }
- i = 0;
- while( (j = i*2+1)<n ){
- k = j+1;
- if( k<n && rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[j])<0 ){
- if( rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[i])<0 ){
- rtreeSearchPointSwap(p, i, k);
- i = k;
- }else{
- break;
- }
- }else{
- if( rtreeSearchPointCompare(&p->aPoint[j], &p->aPoint[i])<0 ){
- rtreeSearchPointSwap(p, i, j);
- i = j;
- }else{
- break;
- }
- }
- }
- }
-}
-
-
-/*
-** Continue the search on cursor pCur until the front of the queue
-** contains an entry suitable for returning as a result-set row,
-** or until the RtreeSearchPoint queue is empty, indicating that the
-** query has completed.
-*/
-static int rtreeStepToLeaf(RtreeCursor *pCur){
- RtreeSearchPoint *p;
- Rtree *pRtree = RTREE_OF_CURSOR(pCur);
- RtreeNode *pNode;
- int eWithin;
- int rc = SQLITE_OK;
- int nCell;
- int nConstraint = pCur->nConstraint;
- int ii;
- int eInt;
- RtreeSearchPoint x;
-
- eInt = pRtree->eCoordType==RTREE_COORD_INT32;
- while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
- pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
- if( rc ) return rc;
- nCell = NCELL(pNode);
- assert( nCell<200 );
- while( p->iCell<nCell ){
- sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
- u8 *pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
- eWithin = FULLY_WITHIN;
- for(ii=0; ii<nConstraint; ii++){
- RtreeConstraint *pConstraint = pCur->aConstraint + ii;
- if( pConstraint->op>=RTREE_MATCH ){
- rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p,
- &rScore, &eWithin);
- if( rc ) return rc;
- }else if( p->iLevel==1 ){
- rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin);
- }else{
- rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin);
- }
- if( eWithin==NOT_WITHIN ) break;
- }
- p->iCell++;
- if( eWithin==NOT_WITHIN ) continue;
- x.iLevel = p->iLevel - 1;
- if( x.iLevel ){
- x.id = readInt64(pCellData);
- x.iCell = 0;
- }else{
- x.id = p->id;
- x.iCell = p->iCell - 1;
- }
- if( p->iCell>=nCell ){
- RTREE_QUEUE_TRACE(pCur, "POP-S:");
- rtreeSearchPointPop(pCur);
- }
- if( rScore<RTREE_ZERO ) rScore = RTREE_ZERO;
- p = rtreeSearchPointNew(pCur, rScore, x.iLevel);
- if( p==0 ) return SQLITE_NOMEM;
- p->eWithin = (u8)eWithin;
- p->id = x.id;
- p->iCell = x.iCell;
- RTREE_QUEUE_TRACE(pCur, "PUSH-S:");
- break;
- }
- if( p->iCell>=nCell ){
- RTREE_QUEUE_TRACE(pCur, "POP-Se:");
- rtreeSearchPointPop(pCur);
- }
- }
- pCur->atEOF = p==0;
- return SQLITE_OK;
-}
-
-/*
-** Rtree virtual table module xNext method.
-*/
-static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
- RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
- int rc = SQLITE_OK;
-
- /* Move to the next entry that matches the configured constraints. */
- RTREE_QUEUE_TRACE(pCsr, "POP-Nx:");
- if( pCsr->bAuxValid ){
- pCsr->bAuxValid = 0;
- sqlite3_reset(pCsr->pReadAux);
- }
- rtreeSearchPointPop(pCsr);
- rc = rtreeStepToLeaf(pCsr);
- return rc;
-}
-
-/*
-** Rtree virtual table module xRowid method.
-*/
-static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
- RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
- RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
- int rc = SQLITE_OK;
- RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
- if( rc==SQLITE_OK && p ){
- *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
- }
- return rc;
-}
-
-/*
-** Rtree virtual table module xColumn method.
-*/
-static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- Rtree *pRtree = (Rtree *)cur->pVtab;
- RtreeCursor *pCsr = (RtreeCursor *)cur;
- RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
- RtreeCoord c;
- int rc = SQLITE_OK;
- RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
-
- if( rc ) return rc;
- if( p==0 ) return SQLITE_OK;
- if( i==0 ){
- sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
- }else if( i<=pRtree->nDim2 ){
- nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
-#ifndef SQLITE_RTREE_INT_ONLY
- if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
- sqlite3_result_double(ctx, c.f);
- }else
-#endif
- {
- assert( pRtree->eCoordType==RTREE_COORD_INT32 );
- sqlite3_result_int(ctx, c.i);
- }
- }else{
- if( !pCsr->bAuxValid ){
- if( pCsr->pReadAux==0 ){
- rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0,
- &pCsr->pReadAux, 0);
- if( rc ) return rc;
- }
- sqlite3_bind_int64(pCsr->pReadAux, 1,
- nodeGetRowid(pRtree, pNode, p->iCell));
- rc = sqlite3_step(pCsr->pReadAux);
- if( rc==SQLITE_ROW ){
- pCsr->bAuxValid = 1;
- }else{
- sqlite3_reset(pCsr->pReadAux);
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- return rc;
- }
- }
- sqlite3_result_value(ctx,
- sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1));
- }
- return SQLITE_OK;
-}
-
-/*
-** Use nodeAcquire() to obtain the leaf node containing the record with
-** rowid iRowid. If successful, set *ppLeaf to point to the node and
-** return SQLITE_OK. If there is no such record in the table, set
-** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf
-** to zero and return an SQLite error code.
-*/
-static int findLeafNode(
- Rtree *pRtree, /* RTree to search */
- i64 iRowid, /* The rowid searching for */
- RtreeNode **ppLeaf, /* Write the node here */
- sqlite3_int64 *piNode /* Write the node-id here */
-){
- int rc;
- *ppLeaf = 0;
- sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid);
- if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){
- i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0);
- if( piNode ) *piNode = iNode;
- rc = nodeAcquire(pRtree, iNode, 0, ppLeaf);
- sqlite3_reset(pRtree->pReadRowid);
- }else{
- rc = sqlite3_reset(pRtree->pReadRowid);
- }
- return rc;
-}
-
-/*
-** This function is called to configure the RtreeConstraint object passed
-** as the second argument for a MATCH constraint. The value passed as the
-** first argument to this function is the right-hand operand to the MATCH
-** operator.
-*/
-static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
- RtreeMatchArg *pBlob, *pSrc; /* BLOB returned by geometry function */
- sqlite3_rtree_query_info *pInfo; /* Callback information */
-
- pSrc = sqlite3_value_pointer(pValue, "RtreeMatchArg");
- if( pSrc==0 ) return SQLITE_ERROR;
- pInfo = (sqlite3_rtree_query_info*)
- sqlite3_malloc64( sizeof(*pInfo)+pSrc->iSize );
- if( !pInfo ) return SQLITE_NOMEM;
- memset(pInfo, 0, sizeof(*pInfo));
- pBlob = (RtreeMatchArg*)&pInfo[1];
- memcpy(pBlob, pSrc, pSrc->iSize);
- pInfo->pContext = pBlob->cb.pContext;
- pInfo->nParam = pBlob->nParam;
- pInfo->aParam = pBlob->aParam;
- pInfo->apSqlParam = pBlob->apSqlParam;
-
- if( pBlob->cb.xGeom ){
- pCons->u.xGeom = pBlob->cb.xGeom;
- }else{
- pCons->op = RTREE_QUERY;
- pCons->u.xQueryFunc = pBlob->cb.xQueryFunc;
- }
- pCons->pInfo = pInfo;
- return SQLITE_OK;
-}
-
-/*
-** Rtree virtual table module xFilter method.
-*/
-static int rtreeFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
- RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
- RtreeNode *pRoot = 0;
- int ii;
- int rc = SQLITE_OK;
- int iCell = 0;
- sqlite3_stmt *pStmt;
-
- rtreeReference(pRtree);
-
- /* Reset the cursor to the same state as rtreeOpen() leaves it in. */
- freeCursorConstraints(pCsr);
- sqlite3_free(pCsr->aPoint);
- pStmt = pCsr->pReadAux;
- memset(pCsr, 0, sizeof(RtreeCursor));
- pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
- pCsr->pReadAux = pStmt;
-
- pCsr->iStrategy = idxNum;
- if( idxNum==1 ){
- /* Special case - lookup by rowid. */
- RtreeNode *pLeaf; /* Leaf on which the required cell resides */
- RtreeSearchPoint *p; /* Search point for the leaf */
- i64 iRowid = sqlite3_value_int64(argv[0]);
- i64 iNode = 0;
- rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
- if( rc==SQLITE_OK && pLeaf!=0 ){
- p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
- assert( p!=0 ); /* Always returns pCsr->sPoint */
- pCsr->aNode[0] = pLeaf;
- p->id = iNode;
- p->eWithin = PARTLY_WITHIN;
- rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
- p->iCell = (u8)iCell;
- RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
- }else{
- pCsr->atEOF = 1;
- }
- }else{
- /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
- ** with the configured constraints.
- */
- rc = nodeAcquire(pRtree, 1, 0, &pRoot);
- if( rc==SQLITE_OK && argc>0 ){
- pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
- pCsr->nConstraint = argc;
- if( !pCsr->aConstraint ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc);
- memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1));
- assert( (idxStr==0 && argc==0)
- || (idxStr && (int)strlen(idxStr)==argc*2) );
- for(ii=0; ii<argc; ii++){
- RtreeConstraint *p = &pCsr->aConstraint[ii];
- p->op = idxStr[ii*2];
- p->iCoord = idxStr[ii*2+1]-'0';
- if( p->op>=RTREE_MATCH ){
- /* A MATCH operator. The right-hand-side must be a blob that
- ** can be cast into an RtreeMatchArg object. One created using
- ** an sqlite3_rtree_geometry_callback() SQL user function.
- */
- rc = deserializeGeometry(argv[ii], p);
- if( rc!=SQLITE_OK ){
- break;
- }
- p->pInfo->nCoord = pRtree->nDim2;
- p->pInfo->anQueue = pCsr->anQueue;
- p->pInfo->mxLevel = pRtree->iDepth + 1;
- }else{
-#ifdef SQLITE_RTREE_INT_ONLY
- p->u.rValue = sqlite3_value_int64(argv[ii]);
-#else
- p->u.rValue = sqlite3_value_double(argv[ii]);
-#endif
- }
- }
- }
- }
- if( rc==SQLITE_OK ){
- RtreeSearchPoint *pNew;
- pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
- if( pNew==0 ) return SQLITE_NOMEM;
- pNew->id = 1;
- pNew->iCell = 0;
- pNew->eWithin = PARTLY_WITHIN;
- assert( pCsr->bPoint==1 );
- pCsr->aNode[0] = pRoot;
- pRoot = 0;
- RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:");
- rc = rtreeStepToLeaf(pCsr);
- }
- }
-
- nodeRelease(pRtree, pRoot);
- rtreeRelease(pRtree);
- return rc;
-}
-
-/*
-** Rtree virtual table module xBestIndex method. There are three
-** table scan strategies to choose from (in order from most to
-** least desirable):
-**
-** idxNum idxStr Strategy
-** ------------------------------------------------
-** 1 Unused Direct lookup by rowid.
-** 2 See below R-tree query or full-table scan.
-** ------------------------------------------------
-**
-** If strategy 1 is used, then idxStr is not meaningful. If strategy
-** 2 is used, idxStr is formatted to contain 2 bytes for each
-** constraint used. The first two bytes of idxStr correspond to
-** the constraint in sqlite3_index_info.aConstraintUsage[] with
-** (argvIndex==1) etc.
-**
-** The first of each pair of bytes in idxStr identifies the constraint
-** operator as follows:
-**
-** Operator Byte Value
-** ----------------------
-** = 0x41 ('A')
-** <= 0x42 ('B')
-** < 0x43 ('C')
-** >= 0x44 ('D')
-** > 0x45 ('E')
-** MATCH 0x46 ('F')
-** ----------------------
-**
-** The second of each pair of bytes identifies the coordinate column
-** to which the constraint applies. The leftmost coordinate column
-** is 'a', the second from the left 'b' etc.
-*/
-static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- Rtree *pRtree = (Rtree*)tab;
- int rc = SQLITE_OK;
- int ii;
- int bMatch = 0; /* True if there exists a MATCH constraint */
- i64 nRow; /* Estimated rows returned by this scan */
-
- int iIdx = 0;
- char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];
- memset(zIdxStr, 0, sizeof(zIdxStr));
-
- /* Check if there exists a MATCH constraint - even an unusable one. If there
- ** is, do not consider the lookup-by-rowid plan as using such a plan would
- ** require the VDBE to evaluate the MATCH constraint, which is not currently
- ** possible. */
- for(ii=0; ii<pIdxInfo->nConstraint; ii++){
- if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){
- bMatch = 1;
- }
- }
-
- assert( pIdxInfo->idxStr==0 );
- for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
- struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
-
- if( bMatch==0 && p->usable
- && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
- ){
- /* We have an equality constraint on the rowid. Use strategy 1. */
- int jj;
- for(jj=0; jj<ii; jj++){
- pIdxInfo->aConstraintUsage[jj].argvIndex = 0;
- pIdxInfo->aConstraintUsage[jj].omit = 0;
- }
- pIdxInfo->idxNum = 1;
- pIdxInfo->aConstraintUsage[ii].argvIndex = 1;
- pIdxInfo->aConstraintUsage[jj].omit = 1;
-
- /* This strategy involves a two rowid lookups on an B-Tree structures
- ** and then a linear search of an R-Tree node. This should be
- ** considered almost as quick as a direct rowid lookup (for which
- ** sqlite uses an internal cost of 0.0). It is expected to return
- ** a single row.
- */
- pIdxInfo->estimatedCost = 30.0;
- pIdxInfo->estimatedRows = 1;
- pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
- return SQLITE_OK;
- }
-
- if( p->usable
- && ((p->iColumn>0 && p->iColumn<=pRtree->nDim2)
- || p->op==SQLITE_INDEX_CONSTRAINT_MATCH)
- ){
- u8 op;
- switch( p->op ){
- case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
- case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
- case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
- case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
- case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
- default:
- assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
- op = RTREE_MATCH;
- break;
- }
- zIdxStr[iIdx++] = op;
- zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
- pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
- pIdxInfo->aConstraintUsage[ii].omit = 1;
- }
- }
-
- pIdxInfo->idxNum = 2;
- pIdxInfo->needToFreeIdxStr = 1;
- if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
- return SQLITE_NOMEM;
- }
-
- nRow = pRtree->nRowEst >> (iIdx/2);
- pIdxInfo->estimatedCost = (double)6.0 * (double)nRow;
- pIdxInfo->estimatedRows = nRow;
-
- return rc;
-}
-
-/*
-** Return the N-dimensional volumn of the cell stored in *p.
-*/
-static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
- RtreeDValue area = (RtreeDValue)1;
- assert( pRtree->nDim>=1 && pRtree->nDim<=5 );
-#ifndef SQLITE_RTREE_INT_ONLY
- if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
- switch( pRtree->nDim ){
- case 5: area = p->aCoord[9].f - p->aCoord[8].f;
- case 4: area *= p->aCoord[7].f - p->aCoord[6].f;
- case 3: area *= p->aCoord[5].f - p->aCoord[4].f;
- case 2: area *= p->aCoord[3].f - p->aCoord[2].f;
- default: area *= p->aCoord[1].f - p->aCoord[0].f;
- }
- }else
-#endif
- {
- switch( pRtree->nDim ){
- case 5: area = p->aCoord[9].i - p->aCoord[8].i;
- case 4: area *= p->aCoord[7].i - p->aCoord[6].i;
- case 3: area *= p->aCoord[5].i - p->aCoord[4].i;
- case 2: area *= p->aCoord[3].i - p->aCoord[2].i;
- default: area *= p->aCoord[1].i - p->aCoord[0].i;
- }
- }
- return area;
-}
-
-/*
-** Return the margin length of cell p. The margin length is the sum
-** of the objects size in each dimension.
-*/
-static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){
- RtreeDValue margin = 0;
- int ii = pRtree->nDim2 - 2;
- do{
- margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
- ii -= 2;
- }while( ii>=0 );
- return margin;
-}
-
-/*
-** Store the union of cells p1 and p2 in p1.
-*/
-static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
- int ii = 0;
- if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
- do{
- p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f);
- p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f);
- ii += 2;
- }while( ii<pRtree->nDim2 );
- }else{
- do{
- p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);
- p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);
- ii += 2;
- }while( ii<pRtree->nDim2 );
- }
-}
-
-/*
-** Return true if the area covered by p2 is a subset of the area covered
-** by p1. False otherwise.
-*/
-static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
- int ii;
- int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
- for(ii=0; ii<pRtree->nDim2; ii+=2){
- RtreeCoord *a1 = &p1->aCoord[ii];
- RtreeCoord *a2 = &p2->aCoord[ii];
- if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
- || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
- ){
- return 0;
- }
- }
- return 1;
-}
-
-/*
-** Return the amount cell p would grow by if it were unioned with pCell.
-*/
-static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){
- RtreeDValue area;
- RtreeCell cell;
- memcpy(&cell, p, sizeof(RtreeCell));
- area = cellArea(pRtree, &cell);
- cellUnion(pRtree, &cell, pCell);
- return (cellArea(pRtree, &cell)-area);
-}
-
-static RtreeDValue cellOverlap(
- Rtree *pRtree,
- RtreeCell *p,
- RtreeCell *aCell,
- int nCell
-){
- int ii;
- RtreeDValue overlap = RTREE_ZERO;
- for(ii=0; ii<nCell; ii++){
- int jj;
- RtreeDValue o = (RtreeDValue)1;
- for(jj=0; jj<pRtree->nDim2; jj+=2){
- RtreeDValue x1, x2;
- x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
- x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
- if( x2<x1 ){
- o = (RtreeDValue)0;
- break;
- }else{
- o = o * (x2-x1);
- }
- }
- overlap += o;
- }
- return overlap;
-}
-
-
-/*
-** This function implements the ChooseLeaf algorithm from Gutman[84].
-** ChooseSubTree in r*tree terminology.
-*/
-static int ChooseLeaf(
- Rtree *pRtree, /* Rtree table */
- RtreeCell *pCell, /* Cell to insert into rtree */
- int iHeight, /* Height of sub-tree rooted at pCell */
- RtreeNode **ppLeaf /* OUT: Selected leaf page */
-){
- int rc;
- int ii;
- RtreeNode *pNode = 0;
- rc = nodeAcquire(pRtree, 1, 0, &pNode);
-
- for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){
- int iCell;
- sqlite3_int64 iBest = 0;
-
- RtreeDValue fMinGrowth = RTREE_ZERO;
- RtreeDValue fMinArea = RTREE_ZERO;
-
- int nCell = NCELL(pNode);
- RtreeCell cell;
- RtreeNode *pChild;
-
- RtreeCell *aCell = 0;
-
- /* Select the child node which will be enlarged the least if pCell
- ** is inserted into it. Resolve ties by choosing the entry with
- ** the smallest area.
- */
- for(iCell=0; iCell<nCell; iCell++){
- int bBest = 0;
- RtreeDValue growth;
- RtreeDValue area;
- nodeGetCell(pRtree, pNode, iCell, &cell);
- growth = cellGrowth(pRtree, &cell, pCell);
- area = cellArea(pRtree, &cell);
- if( iCell==0||growth<fMinGrowth||(growth==fMinGrowth && area<fMinArea) ){
- bBest = 1;
- }
- if( bBest ){
- fMinGrowth = growth;
- fMinArea = area;
- iBest = cell.iRowid;
- }
- }
-
- sqlite3_free(aCell);
- rc = nodeAcquire(pRtree, iBest, pNode, &pChild);
- nodeRelease(pRtree, pNode);
- pNode = pChild;
- }
-
- *ppLeaf = pNode;
- return rc;
-}
-
-/*
-** A cell with the same content as pCell has just been inserted into
-** the node pNode. This function updates the bounding box cells in
-** all ancestor elements.
-*/
-static int AdjustTree(
- Rtree *pRtree, /* Rtree table */
- RtreeNode *pNode, /* Adjust ancestry of this node. */
- RtreeCell *pCell /* This cell was just inserted */
-){
- RtreeNode *p = pNode;
- while( p->pParent ){
- RtreeNode *pParent = p->pParent;
- RtreeCell cell;
- int iCell;
-
- if( nodeParentIndex(pRtree, p, &iCell) ){
- return SQLITE_CORRUPT_VTAB;
- }
-
- nodeGetCell(pRtree, pParent, iCell, &cell);
- if( !cellContains(pRtree, &cell, pCell) ){
- cellUnion(pRtree, &cell, pCell);
- nodeOverwriteCell(pRtree, pParent, &cell, iCell);
- }
-
- p = pParent;
- }
- return SQLITE_OK;
-}
-
-/*
-** Write mapping (iRowid->iNode) to the <rtree>_rowid table.
-*/
-static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){
- sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid);
- sqlite3_bind_int64(pRtree->pWriteRowid, 2, iNode);
- sqlite3_step(pRtree->pWriteRowid);
- return sqlite3_reset(pRtree->pWriteRowid);
-}
-
-/*
-** Write mapping (iNode->iPar) to the <rtree>_parent table.
-*/
-static int parentWrite(Rtree *pRtree, sqlite3_int64 iNode, sqlite3_int64 iPar){
- sqlite3_bind_int64(pRtree->pWriteParent, 1, iNode);
- sqlite3_bind_int64(pRtree->pWriteParent, 2, iPar);
- sqlite3_step(pRtree->pWriteParent);
- return sqlite3_reset(pRtree->pWriteParent);
-}
-
-static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int);
-
-
-/*
-** Arguments aIdx, aDistance and aSpare all point to arrays of size
-** nIdx. The aIdx array contains the set of integers from 0 to
-** (nIdx-1) in no particular order. This function sorts the values
-** in aIdx according to the indexed values in aDistance. For
-** example, assuming the inputs:
-**
-** aIdx = { 0, 1, 2, 3 }
-** aDistance = { 5.0, 2.0, 7.0, 6.0 }
-**
-** this function sets the aIdx array to contain:
-**
-** aIdx = { 0, 1, 2, 3 }
-**
-** The aSpare array is used as temporary working space by the
-** sorting algorithm.
-*/
-static void SortByDistance(
- int *aIdx,
- int nIdx,
- RtreeDValue *aDistance,
- int *aSpare
-){
- if( nIdx>1 ){
- int iLeft = 0;
- int iRight = 0;
-
- int nLeft = nIdx/2;
- int nRight = nIdx-nLeft;
- int *aLeft = aIdx;
- int *aRight = &aIdx[nLeft];
-
- SortByDistance(aLeft, nLeft, aDistance, aSpare);
- SortByDistance(aRight, nRight, aDistance, aSpare);
-
- memcpy(aSpare, aLeft, sizeof(int)*nLeft);
- aLeft = aSpare;
-
- while( iLeft<nLeft || iRight<nRight ){
- if( iLeft==nLeft ){
- aIdx[iLeft+iRight] = aRight[iRight];
- iRight++;
- }else if( iRight==nRight ){
- aIdx[iLeft+iRight] = aLeft[iLeft];
- iLeft++;
- }else{
- RtreeDValue fLeft = aDistance[aLeft[iLeft]];
- RtreeDValue fRight = aDistance[aRight[iRight]];
- if( fLeft<fRight ){
- aIdx[iLeft+iRight] = aLeft[iLeft];
- iLeft++;
- }else{
- aIdx[iLeft+iRight] = aRight[iRight];
- iRight++;
- }
- }
- }
-
-#if 0
- /* Check that the sort worked */
- {
- int jj;
- for(jj=1; jj<nIdx; jj++){
- RtreeDValue left = aDistance[aIdx[jj-1]];
- RtreeDValue right = aDistance[aIdx[jj]];
- assert( left<=right );
- }
- }
-#endif
- }
-}
-
-/*
-** Arguments aIdx, aCell and aSpare all point to arrays of size
-** nIdx. The aIdx array contains the set of integers from 0 to
-** (nIdx-1) in no particular order. This function sorts the values
-** in aIdx according to dimension iDim of the cells in aCell. The
-** minimum value of dimension iDim is considered first, the
-** maximum used to break ties.
-**
-** The aSpare array is used as temporary working space by the
-** sorting algorithm.
-*/
-static void SortByDimension(
- Rtree *pRtree,
- int *aIdx,
- int nIdx,
- int iDim,
- RtreeCell *aCell,
- int *aSpare
-){
- if( nIdx>1 ){
-
- int iLeft = 0;
- int iRight = 0;
-
- int nLeft = nIdx/2;
- int nRight = nIdx-nLeft;
- int *aLeft = aIdx;
- int *aRight = &aIdx[nLeft];
-
- SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare);
- SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare);
-
- memcpy(aSpare, aLeft, sizeof(int)*nLeft);
- aLeft = aSpare;
- while( iLeft<nLeft || iRight<nRight ){
- RtreeDValue xleft1 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2]);
- RtreeDValue xleft2 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2+1]);
- RtreeDValue xright1 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2]);
- RtreeDValue xright2 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2+1]);
- if( (iLeft!=nLeft) && ((iRight==nRight)
- || (xleft1<xright1)
- || (xleft1==xright1 && xleft2<xright2)
- )){
- aIdx[iLeft+iRight] = aLeft[iLeft];
- iLeft++;
- }else{
- aIdx[iLeft+iRight] = aRight[iRight];
- iRight++;
- }
- }
-
-#if 0
- /* Check that the sort worked */
- {
- int jj;
- for(jj=1; jj<nIdx; jj++){
- RtreeDValue xleft1 = aCell[aIdx[jj-1]].aCoord[iDim*2];
- RtreeDValue xleft2 = aCell[aIdx[jj-1]].aCoord[iDim*2+1];
- RtreeDValue xright1 = aCell[aIdx[jj]].aCoord[iDim*2];
- RtreeDValue xright2 = aCell[aIdx[jj]].aCoord[iDim*2+1];
- assert( xleft1<=xright1 && (xleft1<xright1 || xleft2<=xright2) );
- }
- }
-#endif
- }
-}
-
-/*
-** Implementation of the R*-tree variant of SplitNode from Beckman[1990].
-*/
-static int splitNodeStartree(
- Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- RtreeNode *pLeft,
- RtreeNode *pRight,
- RtreeCell *pBboxLeft,
- RtreeCell *pBboxRight
-){
- int **aaSorted;
- int *aSpare;
- int ii;
-
- int iBestDim = 0;
- int iBestSplit = 0;
- RtreeDValue fBestMargin = RTREE_ZERO;
-
- int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
-
- aaSorted = (int **)sqlite3_malloc(nByte);
- if( !aaSorted ){
- return SQLITE_NOMEM;
- }
-
- aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell];
- memset(aaSorted, 0, nByte);
- for(ii=0; ii<pRtree->nDim; ii++){
- int jj;
- aaSorted[ii] = &((int *)&aaSorted[pRtree->nDim])[ii*nCell];
- for(jj=0; jj<nCell; jj++){
- aaSorted[ii][jj] = jj;
- }
- SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare);
- }
-
- for(ii=0; ii<pRtree->nDim; ii++){
- RtreeDValue margin = RTREE_ZERO;
- RtreeDValue fBestOverlap = RTREE_ZERO;
- RtreeDValue fBestArea = RTREE_ZERO;
- int iBestLeft = 0;
- int nLeft;
-
- for(
- nLeft=RTREE_MINCELLS(pRtree);
- nLeft<=(nCell-RTREE_MINCELLS(pRtree));
- nLeft++
- ){
- RtreeCell left;
- RtreeCell right;
- int kk;
- RtreeDValue overlap;
- RtreeDValue area;
-
- memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell));
- memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell));
- for(kk=1; kk<(nCell-1); kk++){
- if( kk<nLeft ){
- cellUnion(pRtree, &left, &aCell[aaSorted[ii][kk]]);
- }else{
- cellUnion(pRtree, &right, &aCell[aaSorted[ii][kk]]);
- }
- }
- margin += cellMargin(pRtree, &left);
- margin += cellMargin(pRtree, &right);
- overlap = cellOverlap(pRtree, &left, &right, 1);
- area = cellArea(pRtree, &left) + cellArea(pRtree, &right);
- if( (nLeft==RTREE_MINCELLS(pRtree))
- || (overlap<fBestOverlap)
- || (overlap==fBestOverlap && area<fBestArea)
- ){
- iBestLeft = nLeft;
- fBestOverlap = overlap;
- fBestArea = area;
- }
- }
-
- if( ii==0 || margin<fBestMargin ){
- iBestDim = ii;
- fBestMargin = margin;
- iBestSplit = iBestLeft;
- }
- }
-
- memcpy(pBboxLeft, &aCell[aaSorted[iBestDim][0]], sizeof(RtreeCell));
- memcpy(pBboxRight, &aCell[aaSorted[iBestDim][iBestSplit]], sizeof(RtreeCell));
- for(ii=0; ii<nCell; ii++){
- RtreeNode *pTarget = (ii<iBestSplit)?pLeft:pRight;
- RtreeCell *pBbox = (ii<iBestSplit)?pBboxLeft:pBboxRight;
- RtreeCell *pCell = &aCell[aaSorted[iBestDim][ii]];
- nodeInsertCell(pRtree, pTarget, pCell);
- cellUnion(pRtree, pBbox, pCell);
- }
-
- sqlite3_free(aaSorted);
- return SQLITE_OK;
-}
-
-
-static int updateMapping(
- Rtree *pRtree,
- i64 iRowid,
- RtreeNode *pNode,
- int iHeight
-){
- int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64);
- xSetMapping = ((iHeight==0)?rowidWrite:parentWrite);
- if( iHeight>0 ){
- RtreeNode *pChild = nodeHashLookup(pRtree, iRowid);
- if( pChild ){
- nodeRelease(pRtree, pChild->pParent);
- nodeReference(pNode);
- pChild->pParent = pNode;
- }
- }
- return xSetMapping(pRtree, iRowid, pNode->iNode);
-}
-
-static int SplitNode(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell,
- int iHeight
-){
- int i;
- int newCellIsRight = 0;
-
- int rc = SQLITE_OK;
- int nCell = NCELL(pNode);
- RtreeCell *aCell;
- int *aiUsed;
-
- RtreeNode *pLeft = 0;
- RtreeNode *pRight = 0;
-
- RtreeCell leftbbox;
- RtreeCell rightbbox;
-
- /* Allocate an array and populate it with a copy of pCell and
- ** all cells from node pLeft. Then zero the original node.
- */
- aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
- if( !aCell ){
- rc = SQLITE_NOMEM;
- goto splitnode_out;
- }
- aiUsed = (int *)&aCell[nCell+1];
- memset(aiUsed, 0, sizeof(int)*(nCell+1));
- for(i=0; i<nCell; i++){
- nodeGetCell(pRtree, pNode, i, &aCell[i]);
- }
- nodeZero(pRtree, pNode);
- memcpy(&aCell[nCell], pCell, sizeof(RtreeCell));
- nCell++;
-
- if( pNode->iNode==1 ){
- pRight = nodeNew(pRtree, pNode);
- pLeft = nodeNew(pRtree, pNode);
- pRtree->iDepth++;
- pNode->isDirty = 1;
- writeInt16(pNode->zData, pRtree->iDepth);
- }else{
- pLeft = pNode;
- pRight = nodeNew(pRtree, pLeft->pParent);
- pLeft->nRef++;
- }
-
- if( !pLeft || !pRight ){
- rc = SQLITE_NOMEM;
- goto splitnode_out;
- }
-
- memset(pLeft->zData, 0, pRtree->iNodeSize);
- memset(pRight->zData, 0, pRtree->iNodeSize);
-
- rc = splitNodeStartree(pRtree, aCell, nCell, pLeft, pRight,
- &leftbbox, &rightbbox);
- if( rc!=SQLITE_OK ){
- goto splitnode_out;
- }
-
- /* Ensure both child nodes have node numbers assigned to them by calling
- ** nodeWrite(). Node pRight always needs a node number, as it was created
- ** by nodeNew() above. But node pLeft sometimes already has a node number.
- ** In this case avoid the all to nodeWrite().
- */
- if( SQLITE_OK!=(rc = nodeWrite(pRtree, pRight))
- || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft)))
- ){
- goto splitnode_out;
- }
-
- rightbbox.iRowid = pRight->iNode;
- leftbbox.iRowid = pLeft->iNode;
-
- if( pNode->iNode==1 ){
- rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1);
- if( rc!=SQLITE_OK ){
- goto splitnode_out;
- }
- }else{
- RtreeNode *pParent = pLeft->pParent;
- int iCell;
- rc = nodeParentIndex(pRtree, pLeft, &iCell);
- if( rc==SQLITE_OK ){
- nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);
- rc = AdjustTree(pRtree, pParent, &leftbbox);
- }
- if( rc!=SQLITE_OK ){
- goto splitnode_out;
- }
- }
- if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){
- goto splitnode_out;
- }
-
- for(i=0; i<NCELL(pRight); i++){
- i64 iRowid = nodeGetRowid(pRtree, pRight, i);
- rc = updateMapping(pRtree, iRowid, pRight, iHeight);
- if( iRowid==pCell->iRowid ){
- newCellIsRight = 1;
- }
- if( rc!=SQLITE_OK ){
- goto splitnode_out;
- }
- }
- if( pNode->iNode==1 ){
- for(i=0; i<NCELL(pLeft); i++){
- i64 iRowid = nodeGetRowid(pRtree, pLeft, i);
- rc = updateMapping(pRtree, iRowid, pLeft, iHeight);
- if( rc!=SQLITE_OK ){
- goto splitnode_out;
- }
- }
- }else if( newCellIsRight==0 ){
- rc = updateMapping(pRtree, pCell->iRowid, pLeft, iHeight);
- }
-
- if( rc==SQLITE_OK ){
- rc = nodeRelease(pRtree, pRight);
- pRight = 0;
- }
- if( rc==SQLITE_OK ){
- rc = nodeRelease(pRtree, pLeft);
- pLeft = 0;
- }
-
-splitnode_out:
- nodeRelease(pRtree, pRight);
- nodeRelease(pRtree, pLeft);
- sqlite3_free(aCell);
- return rc;
-}
-
-/*
-** If node pLeaf is not the root of the r-tree and its pParent pointer is
-** still NULL, load all ancestor nodes of pLeaf into memory and populate
-** the pLeaf->pParent chain all the way up to the root node.
-**
-** This operation is required when a row is deleted (or updated - an update
-** is implemented as a delete followed by an insert). SQLite provides the
-** rowid of the row to delete, which can be used to find the leaf on which
-** the entry resides (argument pLeaf). Once the leaf is located, this
-** function is called to determine its ancestry.
-*/
-static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
- int rc = SQLITE_OK;
- RtreeNode *pChild = pLeaf;
- while( rc==SQLITE_OK && pChild->iNode!=1 && pChild->pParent==0 ){
- int rc2 = SQLITE_OK; /* sqlite3_reset() return code */
- sqlite3_bind_int64(pRtree->pReadParent, 1, pChild->iNode);
- rc = sqlite3_step(pRtree->pReadParent);
- if( rc==SQLITE_ROW ){
- RtreeNode *pTest; /* Used to test for reference loops */
- i64 iNode; /* Node number of parent node */
-
- /* Before setting pChild->pParent, test that we are not creating a
- ** loop of references (as we would if, say, pChild==pParent). We don't
- ** want to do this as it leads to a memory leak when trying to delete
- ** the referenced counted node structures.
- */
- iNode = sqlite3_column_int64(pRtree->pReadParent, 0);
- for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
- if( !pTest ){
- rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
- }
- }
- rc = sqlite3_reset(pRtree->pReadParent);
- if( rc==SQLITE_OK ) rc = rc2;
- if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
- pChild = pChild->pParent;
- }
- return rc;
-}
-
-static int deleteCell(Rtree *, RtreeNode *, int, int);
-
-static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
- int rc;
- int rc2;
- RtreeNode *pParent = 0;
- int iCell;
-
- assert( pNode->nRef==1 );
-
- /* Remove the entry in the parent cell. */
- rc = nodeParentIndex(pRtree, pNode, &iCell);
- if( rc==SQLITE_OK ){
- pParent = pNode->pParent;
- pNode->pParent = 0;
- rc = deleteCell(pRtree, pParent, iCell, iHeight+1);
- }
- rc2 = nodeRelease(pRtree, pParent);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Remove the xxx_node entry. */
- sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode);
- sqlite3_step(pRtree->pDeleteNode);
- if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){
- return rc;
- }
-
- /* Remove the xxx_parent entry. */
- sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode);
- sqlite3_step(pRtree->pDeleteParent);
- if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){
- return rc;
- }
-
- /* Remove the node from the in-memory hash table and link it into
- ** the Rtree.pDeleted list. Its contents will be re-inserted later on.
- */
- nodeHashDelete(pRtree, pNode);
- pNode->iNode = iHeight;
- pNode->pNext = pRtree->pDeleted;
- pNode->nRef++;
- pRtree->pDeleted = pNode;
-
- return SQLITE_OK;
-}
-
-static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){
- RtreeNode *pParent = pNode->pParent;
- int rc = SQLITE_OK;
- if( pParent ){
- int ii;
- int nCell = NCELL(pNode);
- RtreeCell box; /* Bounding box for pNode */
- nodeGetCell(pRtree, pNode, 0, &box);
- for(ii=1; ii<nCell; ii++){
- RtreeCell cell;
- nodeGetCell(pRtree, pNode, ii, &cell);
- cellUnion(pRtree, &box, &cell);
- }
- box.iRowid = pNode->iNode;
- rc = nodeParentIndex(pRtree, pNode, &ii);
- if( rc==SQLITE_OK ){
- nodeOverwriteCell(pRtree, pParent, &box, ii);
- rc = fixBoundingBox(pRtree, pParent);
- }
- }
- return rc;
-}
-
-/*
-** Delete the cell at index iCell of node pNode. After removing the
-** cell, adjust the r-tree data structure if required.
-*/
-static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){
- RtreeNode *pParent;
- int rc;
-
- if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){
- return rc;
- }
-
- /* Remove the cell from the node. This call just moves bytes around
- ** the in-memory node image, so it cannot fail.
- */
- nodeDeleteCell(pRtree, pNode, iCell);
-
- /* If the node is not the tree root and now has less than the minimum
- ** number of cells, remove it from the tree. Otherwise, update the
- ** cell in the parent node so that it tightly contains the updated
- ** node.
- */
- pParent = pNode->pParent;
- assert( pParent || pNode->iNode==1 );
- if( pParent ){
- if( NCELL(pNode)<RTREE_MINCELLS(pRtree) ){
- rc = removeNode(pRtree, pNode, iHeight);
- }else{
- rc = fixBoundingBox(pRtree, pNode);
- }
- }
-
- return rc;
-}
-
-static int Reinsert(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell,
- int iHeight
-){
- int *aOrder;
- int *aSpare;
- RtreeCell *aCell;
- RtreeDValue *aDistance;
- int nCell;
- RtreeDValue aCenterCoord[RTREE_MAX_DIMENSIONS];
- int iDim;
- int ii;
- int rc = SQLITE_OK;
- int n;
-
- memset(aCenterCoord, 0, sizeof(RtreeDValue)*RTREE_MAX_DIMENSIONS);
-
- nCell = NCELL(pNode)+1;
- n = (nCell+1)&(~1);
-
- /* Allocate the buffers used by this operation. The allocation is
- ** relinquished before this function returns.
- */
- aCell = (RtreeCell *)sqlite3_malloc(n * (
- sizeof(RtreeCell) + /* aCell array */
- sizeof(int) + /* aOrder array */
- sizeof(int) + /* aSpare array */
- sizeof(RtreeDValue) /* aDistance array */
- ));
- if( !aCell ){
- return SQLITE_NOMEM;
- }
- aOrder = (int *)&aCell[n];
- aSpare = (int *)&aOrder[n];
- aDistance = (RtreeDValue *)&aSpare[n];
-
- for(ii=0; ii<nCell; ii++){
- if( ii==(nCell-1) ){
- memcpy(&aCell[ii], pCell, sizeof(RtreeCell));
- }else{
- nodeGetCell(pRtree, pNode, ii, &aCell[ii]);
- }
- aOrder[ii] = ii;
- for(iDim=0; iDim<pRtree->nDim; iDim++){
- aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]);
- aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]);
- }
- }
- for(iDim=0; iDim<pRtree->nDim; iDim++){
- aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2));
- }
-
- for(ii=0; ii<nCell; ii++){
- aDistance[ii] = RTREE_ZERO;
- for(iDim=0; iDim<pRtree->nDim; iDim++){
- RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) -
- DCOORD(aCell[ii].aCoord[iDim*2]));
- aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
- }
- }
-
- SortByDistance(aOrder, nCell, aDistance, aSpare);
- nodeZero(pRtree, pNode);
-
- for(ii=0; rc==SQLITE_OK && ii<(nCell-(RTREE_MINCELLS(pRtree)+1)); ii++){
- RtreeCell *p = &aCell[aOrder[ii]];
- nodeInsertCell(pRtree, pNode, p);
- if( p->iRowid==pCell->iRowid ){
- if( iHeight==0 ){
- rc = rowidWrite(pRtree, p->iRowid, pNode->iNode);
- }else{
- rc = parentWrite(pRtree, p->iRowid, pNode->iNode);
- }
- }
- }
- if( rc==SQLITE_OK ){
- rc = fixBoundingBox(pRtree, pNode);
- }
- for(; rc==SQLITE_OK && ii<nCell; ii++){
- /* Find a node to store this cell in. pNode->iNode currently contains
- ** the height of the sub-tree headed by the cell.
- */
- RtreeNode *pInsert;
- RtreeCell *p = &aCell[aOrder[ii]];
- rc = ChooseLeaf(pRtree, p, iHeight, &pInsert);
- if( rc==SQLITE_OK ){
- int rc2;
- rc = rtreeInsertCell(pRtree, pInsert, p, iHeight);
- rc2 = nodeRelease(pRtree, pInsert);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
- }
-
- sqlite3_free(aCell);
- return rc;
-}
-
-/*
-** Insert cell pCell into node pNode. Node pNode is the head of a
-** subtree iHeight high (leaf nodes have iHeight==0).
-*/
-static int rtreeInsertCell(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell,
- int iHeight
-){
- int rc = SQLITE_OK;
- if( iHeight>0 ){
- RtreeNode *pChild = nodeHashLookup(pRtree, pCell->iRowid);
- if( pChild ){
- nodeRelease(pRtree, pChild->pParent);
- nodeReference(pNode);
- pChild->pParent = pNode;
- }
- }
- if( nodeInsertCell(pRtree, pNode, pCell) ){
- if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){
- rc = SplitNode(pRtree, pNode, pCell, iHeight);
- }else{
- pRtree->iReinsertHeight = iHeight;
- rc = Reinsert(pRtree, pNode, pCell, iHeight);
- }
- }else{
- rc = AdjustTree(pRtree, pNode, pCell);
- if( rc==SQLITE_OK ){
- if( iHeight==0 ){
- rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
- }else{
- rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode);
- }
- }
- }
- return rc;
-}
-
-static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){
- int ii;
- int rc = SQLITE_OK;
- int nCell = NCELL(pNode);
-
- for(ii=0; rc==SQLITE_OK && ii<nCell; ii++){
- RtreeNode *pInsert;
- RtreeCell cell;
- nodeGetCell(pRtree, pNode, ii, &cell);
-
- /* Find a node to store this cell in. pNode->iNode currently contains
- ** the height of the sub-tree headed by the cell.
- */
- rc = ChooseLeaf(pRtree, &cell, (int)pNode->iNode, &pInsert);
- if( rc==SQLITE_OK ){
- int rc2;
- rc = rtreeInsertCell(pRtree, pInsert, &cell, (int)pNode->iNode);
- rc2 = nodeRelease(pRtree, pInsert);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
- }
- return rc;
-}
-
-/*
-** Select a currently unused rowid for a new r-tree record.
-*/
-static int newRowid(Rtree *pRtree, i64 *piRowid){
- int rc;
- sqlite3_bind_null(pRtree->pWriteRowid, 1);
- sqlite3_bind_null(pRtree->pWriteRowid, 2);
- sqlite3_step(pRtree->pWriteRowid);
- rc = sqlite3_reset(pRtree->pWriteRowid);
- *piRowid = sqlite3_last_insert_rowid(pRtree->db);
- return rc;
-}
-
-/*
-** Remove the entry with rowid=iDelete from the r-tree structure.
-*/
-static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
- int rc; /* Return code */
- RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */
- int iCell; /* Index of iDelete cell in pLeaf */
- RtreeNode *pRoot = 0; /* Root node of rtree structure */
-
-
- /* Obtain a reference to the root node to initialize Rtree.iDepth */
- rc = nodeAcquire(pRtree, 1, 0, &pRoot);
-
- /* Obtain a reference to the leaf node that contains the entry
- ** about to be deleted.
- */
- if( rc==SQLITE_OK ){
- rc = findLeafNode(pRtree, iDelete, &pLeaf, 0);
- }
-
- /* Delete the cell in question from the leaf node. */
- if( rc==SQLITE_OK ){
- int rc2;
- rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
- if( rc==SQLITE_OK ){
- rc = deleteCell(pRtree, pLeaf, iCell, 0);
- }
- rc2 = nodeRelease(pRtree, pLeaf);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
-
- /* Delete the corresponding entry in the <rtree>_rowid table. */
- if( rc==SQLITE_OK ){
- sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
- sqlite3_step(pRtree->pDeleteRowid);
- rc = sqlite3_reset(pRtree->pDeleteRowid);
- }
-
- /* Check if the root node now has exactly one child. If so, remove
- ** it, schedule the contents of the child for reinsertion and
- ** reduce the tree height by one.
- **
- ** This is equivalent to copying the contents of the child into
- ** the root node (the operation that Gutman's paper says to perform
- ** in this scenario).
- */
- if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
- int rc2;
- RtreeNode *pChild = 0;
- i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
- rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
- if( rc==SQLITE_OK ){
- rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
- }
- rc2 = nodeRelease(pRtree, pChild);
- if( rc==SQLITE_OK ) rc = rc2;
- if( rc==SQLITE_OK ){
- pRtree->iDepth--;
- writeInt16(pRoot->zData, pRtree->iDepth);
- pRoot->isDirty = 1;
- }
- }
-
- /* Re-insert the contents of any underfull nodes removed from the tree. */
- for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
- if( rc==SQLITE_OK ){
- rc = reinsertNodeContent(pRtree, pLeaf);
- }
- pRtree->pDeleted = pLeaf->pNext;
- pRtree->nNodeRef--;
- sqlite3_free(pLeaf);
- }
-
- /* Release the reference to the root node. */
- if( rc==SQLITE_OK ){
- rc = nodeRelease(pRtree, pRoot);
- }else{
- nodeRelease(pRtree, pRoot);
- }
-
- return rc;
-}
-
-/*
-** Rounding constants for float->double conversion.
-*/
-#define RNDTOWARDS (1.0 - 1.0/8388608.0) /* Round towards zero */
-#define RNDAWAY (1.0 + 1.0/8388608.0) /* Round away from zero */
-
-#if !defined(SQLITE_RTREE_INT_ONLY)
-/*
-** Convert an sqlite3_value into an RtreeValue (presumably a float)
-** while taking care to round toward negative or positive, respectively.
-*/
-static RtreeValue rtreeValueDown(sqlite3_value *v){
- double d = sqlite3_value_double(v);
- float f = (float)d;
- if( f>d ){
- f = (float)(d*(d<0 ? RNDAWAY : RNDTOWARDS));
- }
- return f;
-}
-static RtreeValue rtreeValueUp(sqlite3_value *v){
- double d = sqlite3_value_double(v);
- float f = (float)d;
- if( f<d ){
- f = (float)(d*(d<0 ? RNDTOWARDS : RNDAWAY));
- }
- return f;
-}
-#endif /* !defined(SQLITE_RTREE_INT_ONLY) */
-
-/*
-** A constraint has failed while inserting a row into an rtree table.
-** Assuming no OOM error occurs, this function sets the error message
-** (at pRtree->base.zErrMsg) to an appropriate value and returns
-** SQLITE_CONSTRAINT.
-**
-** Parameter iCol is the index of the leftmost column involved in the
-** constraint failure. If it is 0, then the constraint that failed is
-** the unique constraint on the id column. Otherwise, it is the rtree
-** (c1<=c2) constraint on columns iCol and iCol+1 that has failed.
-**
-** If an OOM occurs, SQLITE_NOMEM is returned instead of SQLITE_CONSTRAINT.
-*/
-static int rtreeConstraintError(Rtree *pRtree, int iCol){
- sqlite3_stmt *pStmt = 0;
- char *zSql;
- int rc;
-
- assert( iCol==0 || iCol%2 );
- zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", pRtree->zDb, pRtree->zName);
- if( zSql ){
- rc = sqlite3_prepare_v2(pRtree->db, zSql, -1, &pStmt, 0);
- }else{
- rc = SQLITE_NOMEM;
- }
- sqlite3_free(zSql);
-
- if( rc==SQLITE_OK ){
- if( iCol==0 ){
- const char *zCol = sqlite3_column_name(pStmt, 0);
- pRtree->base.zErrMsg = sqlite3_mprintf(
- "UNIQUE constraint failed: %s.%s", pRtree->zName, zCol
- );
- }else{
- const char *zCol1 = sqlite3_column_name(pStmt, iCol);
- const char *zCol2 = sqlite3_column_name(pStmt, iCol+1);
- pRtree->base.zErrMsg = sqlite3_mprintf(
- "rtree constraint failed: %s.(%s<=%s)", pRtree->zName, zCol1, zCol2
- );
- }
- }
-
- sqlite3_finalize(pStmt);
- return (rc==SQLITE_OK ? SQLITE_CONSTRAINT : rc);
-}
-
-
-
-/*
-** The xUpdate method for rtree module virtual tables.
-*/
-static int rtreeUpdate(
- sqlite3_vtab *pVtab,
- int nData,
- sqlite3_value **aData,
- sqlite_int64 *pRowid
-){
- Rtree *pRtree = (Rtree *)pVtab;
- int rc = SQLITE_OK;
- RtreeCell cell; /* New cell to insert if nData>1 */
- int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
-
- if( pRtree->nNodeRef ){
- /* Unable to write to the btree while another cursor is reading from it,
- ** since the write might do a rebalance which would disrupt the read
- ** cursor. */
- return SQLITE_LOCKED_VTAB;
- }
- rtreeReference(pRtree);
- assert(nData>=1);
-
- cell.iRowid = 0; /* Used only to suppress a compiler warning */
-
- /* Constraint handling. A write operation on an r-tree table may return
- ** SQLITE_CONSTRAINT for two reasons:
- **
- ** 1. A duplicate rowid value, or
- ** 2. The supplied data violates the "x2>=x1" constraint.
- **
- ** In the first case, if the conflict-handling mode is REPLACE, then
- ** the conflicting row can be removed before proceeding. In the second
- ** case, SQLITE_CONSTRAINT must be returned regardless of the
- ** conflict-handling mode specified by the user.
- */
- if( nData>1 ){
- int ii;
- int nn = nData - 4;
-
- if( nn > pRtree->nDim2 ) nn = pRtree->nDim2;
- /* Populate the cell.aCoord[] array. The first coordinate is aData[3].
- **
- ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
- ** with "column" that are interpreted as table constraints.
- ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
- ** This problem was discovered after years of use, so we silently ignore
- ** these kinds of misdeclared tables to avoid breaking any legacy.
- */
-
-#ifndef SQLITE_RTREE_INT_ONLY
- if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
- for(ii=0; ii<nn; ii+=2){
- cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]);
- cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]);
- if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
- rc = rtreeConstraintError(pRtree, ii+1);
- goto constraint;
- }
- }
- }else
-#endif
- {
- for(ii=0; ii<nn; ii+=2){
- cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]);
- cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]);
- if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
- rc = rtreeConstraintError(pRtree, ii+1);
- goto constraint;
- }
- }
- }
-
- /* If a rowid value was supplied, check if it is already present in
- ** the table. If so, the constraint has failed. */
- if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){
- cell.iRowid = sqlite3_value_int64(aData[2]);
- if( sqlite3_value_type(aData[0])==SQLITE_NULL
- || sqlite3_value_int64(aData[0])!=cell.iRowid
- ){
- int steprc;
- sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
- steprc = sqlite3_step(pRtree->pReadRowid);
- rc = sqlite3_reset(pRtree->pReadRowid);
- if( SQLITE_ROW==steprc ){
- if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){
- rc = rtreeDeleteRowid(pRtree, cell.iRowid);
- }else{
- rc = rtreeConstraintError(pRtree, 0);
- goto constraint;
- }
- }
- }
- bHaveRowid = 1;
- }
- }
-
- /* If aData[0] is not an SQL NULL value, it is the rowid of a
- ** record to delete from the r-tree table. The following block does
- ** just that.
- */
- if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){
- rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0]));
- }
-
- /* If the aData[] array contains more than one element, elements
- ** (aData[2]..aData[argc-1]) contain a new record to insert into
- ** the r-tree structure.
- */
- if( rc==SQLITE_OK && nData>1 ){
- /* Insert the new record into the r-tree */
- RtreeNode *pLeaf = 0;
-
- /* Figure out the rowid of the new row. */
- if( bHaveRowid==0 ){
- rc = newRowid(pRtree, &cell.iRowid);
- }
- *pRowid = cell.iRowid;
-
- if( rc==SQLITE_OK ){
- rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf);
- }
- if( rc==SQLITE_OK ){
- int rc2;
- pRtree->iReinsertHeight = -1;
- rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0);
- rc2 = nodeRelease(pRtree, pLeaf);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
- if( pRtree->nAux ){
- sqlite3_stmt *pUp = pRtree->pWriteAux;
- int jj;
- sqlite3_bind_int64(pUp, 1, *pRowid);
- for(jj=0; jj<pRtree->nAux; jj++){
- sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]);
- }
- sqlite3_step(pUp);
- rc = sqlite3_reset(pUp);
- }
- }
-
-constraint:
- rtreeRelease(pRtree);
- return rc;
-}
-
-/*
-** Called when a transaction starts.
-*/
-static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
- Rtree *pRtree = (Rtree *)pVtab;
- assert( pRtree->inWrTrans==0 );
- pRtree->inWrTrans++;
- return SQLITE_OK;
-}
-
-/*
-** Called when a transaction completes (either by COMMIT or ROLLBACK).
-** The sqlite3_blob object should be released at this point.
-*/
-static int rtreeEndTransaction(sqlite3_vtab *pVtab){
- Rtree *pRtree = (Rtree *)pVtab;
- pRtree->inWrTrans = 0;
- nodeBlobReset(pRtree);
- return SQLITE_OK;
-}
-
-/*
-** The xRename method for rtree module virtual tables.
-*/
-static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
- Rtree *pRtree = (Rtree *)pVtab;
- int rc = SQLITE_NOMEM;
- char *zSql = sqlite3_mprintf(
- "ALTER TABLE %Q.'%q_node' RENAME TO \"%w_node\";"
- "ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";"
- "ALTER TABLE %Q.'%q_rowid' RENAME TO \"%w_rowid\";"
- , pRtree->zDb, pRtree->zName, zNewName
- , pRtree->zDb, pRtree->zName, zNewName
- , pRtree->zDb, pRtree->zName, zNewName
- );
- if( zSql ){
- nodeBlobReset(pRtree);
- rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
- return rc;
-}
-
-/*
-** The xSavepoint method.
-**
-** This module does not need to do anything to support savepoints. However,
-** it uses this hook to close any open blob handle. This is done because a
-** DROP TABLE command - which fortunately always opens a savepoint - cannot
-** succeed if there are any open blob handles. i.e. if the blob handle were
-** not closed here, the following would fail:
-**
-** BEGIN;
-** INSERT INTO rtree...
-** DROP TABLE <tablename>; -- Would fail with SQLITE_LOCKED
-** COMMIT;
-*/
-static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){
- Rtree *pRtree = (Rtree *)pVtab;
- int iwt = pRtree->inWrTrans;
- UNUSED_PARAMETER(iSavepoint);
- pRtree->inWrTrans = 0;
- nodeBlobReset(pRtree);
- pRtree->inWrTrans = iwt;
- return SQLITE_OK;
-}
-
-/*
-** This function populates the pRtree->nRowEst variable with an estimate
-** of the number of rows in the virtual table. If possible, this is based
-** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
-*/
-static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
- const char *zFmt = "SELECT stat FROM %Q.sqlite_stat1 WHERE tbl = '%q_rowid'";
- char *zSql;
- sqlite3_stmt *p;
- int rc;
- i64 nRow = 0;
-
- rc = sqlite3_table_column_metadata(
- db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
- );
- if( rc!=SQLITE_OK ){
- pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
- return rc==SQLITE_ERROR ? SQLITE_OK : rc;
- }
- zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
- if( rc==SQLITE_OK ){
- if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
- rc = sqlite3_finalize(p);
- }else if( rc!=SQLITE_NOMEM ){
- rc = SQLITE_OK;
- }
-
- if( rc==SQLITE_OK ){
- if( nRow==0 ){
- pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
- }else{
- pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
- }
- }
- sqlite3_free(zSql);
- }
-
- return rc;
-}
-
-static sqlite3_module rtreeModule = {
- 2, /* iVersion */
- rtreeCreate, /* xCreate - create a table */
- rtreeConnect, /* xConnect - connect to an existing table */
- rtreeBestIndex, /* xBestIndex - Determine search strategy */
- rtreeDisconnect, /* xDisconnect - Disconnect from a table */
- rtreeDestroy, /* xDestroy - Drop a table */
- rtreeOpen, /* xOpen - open a cursor */
- rtreeClose, /* xClose - close a cursor */
- rtreeFilter, /* xFilter - configure scan constraints */
- rtreeNext, /* xNext - advance a cursor */
- rtreeEof, /* xEof */
- rtreeColumn, /* xColumn - read data */
- rtreeRowid, /* xRowid - read data */
- rtreeUpdate, /* xUpdate - write data */
- rtreeBeginTransaction, /* xBegin - begin transaction */
- rtreeEndTransaction, /* xSync - sync transaction */
- rtreeEndTransaction, /* xCommit - commit transaction */
- rtreeEndTransaction, /* xRollback - rollback transaction */
- 0, /* xFindFunction - function overloading */
- rtreeRename, /* xRename - rename the table */
- rtreeSavepoint, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
-};
-
-static int rtreeSqlInit(
- Rtree *pRtree,
- sqlite3 *db,
- const char *zDb,
- const char *zPrefix,
- int isCreate
-){
- int rc = SQLITE_OK;
-
- #define N_STATEMENT 8
- static const char *azSql[N_STATEMENT] = {
- /* Write the xxx_node table */
- "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(?1, ?2)",
- "DELETE FROM '%q'.'%q_node' WHERE nodeno = ?1",
-
- /* Read and write the xxx_rowid table */
- "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = ?1",
- "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(?1, ?2)",
- "DELETE FROM '%q'.'%q_rowid' WHERE rowid = ?1",
-
- /* Read and write the xxx_parent table */
- "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1",
- "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)",
- "DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1"
- };
- sqlite3_stmt **appStmt[N_STATEMENT];
- int i;
-
- pRtree->db = db;
-
- if( isCreate ){
- char *zCreate;
- sqlite3_str *p = sqlite3_str_new(db);
- int ii;
- sqlite3_str_appendf(p,
- "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno",
- zDb, zPrefix);
- for(ii=0; ii<pRtree->nAux; ii++){
- sqlite3_str_appendf(p,",a%d",ii);
- }
- sqlite3_str_appendf(p,
- ");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);",
- zDb, zPrefix);
- sqlite3_str_appendf(p,
- "CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);",
- zDb, zPrefix);
- sqlite3_str_appendf(p,
- "INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))",
- zDb, zPrefix, pRtree->iNodeSize);
- zCreate = sqlite3_str_finish(p);
- if( !zCreate ){
- return SQLITE_NOMEM;
- }
- rc = sqlite3_exec(db, zCreate, 0, 0, 0);
- sqlite3_free(zCreate);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
-
- appStmt[0] = &pRtree->pWriteNode;
- appStmt[1] = &pRtree->pDeleteNode;
- appStmt[2] = &pRtree->pReadRowid;
- appStmt[3] = &pRtree->pWriteRowid;
- appStmt[4] = &pRtree->pDeleteRowid;
- appStmt[5] = &pRtree->pReadParent;
- appStmt[6] = &pRtree->pWriteParent;
- appStmt[7] = &pRtree->pDeleteParent;
-
- rc = rtreeQueryStat1(db, pRtree);
- for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
- char *zSql;
- const char *zFormat;
- if( i!=3 || pRtree->nAux==0 ){
- zFormat = azSql[i];
- }else {
- /* An UPSERT is very slightly slower than REPLACE, but it is needed
- ** if there are auxiliary columns */
- zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)"
- "ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno";
- }
- zSql = sqlite3_mprintf(zFormat, zDb, zPrefix);
- if( zSql ){
- rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
- appStmt[i], 0);
- }else{
- rc = SQLITE_NOMEM;
- }
- sqlite3_free(zSql);
- }
- if( pRtree->nAux ){
- pRtree->zReadAuxSql = sqlite3_mprintf(
- "SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1",
- zDb, zPrefix);
- if( pRtree->zReadAuxSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_str *p = sqlite3_str_new(db);
- int ii;
- char *zSql;
- sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
- for(ii=0; ii<pRtree->nAux; ii++){
- if( ii ) sqlite3_str_append(p, ",", 1);
- sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
- }
- sqlite3_str_appendf(p, " WHERE rowid=?1");
- zSql = sqlite3_str_finish(p);
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
- &pRtree->pWriteAux, 0);
- sqlite3_free(zSql);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** The second argument to this function contains the text of an SQL statement
-** that returns a single integer value. The statement is compiled and executed
-** using database connection db. If successful, the integer value returned
-** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error
-** code is returned and the value of *piVal after returning is not defined.
-*/
-static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
- int rc = SQLITE_NOMEM;
- if( zSql ){
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- *piVal = sqlite3_column_int(pStmt, 0);
- }
- rc = sqlite3_finalize(pStmt);
- }
- }
- return rc;
-}
-
-/*
-** This function is called from within the xConnect() or xCreate() method to
-** determine the node-size used by the rtree table being created or connected
-** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned.
-** Otherwise, an SQLite error code is returned.
-**
-** If this function is being called as part of an xConnect(), then the rtree
-** table already exists. In this case the node-size is determined by inspecting
-** the root node of the tree.
-**
-** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
-** This ensures that each node is stored on a single database page. If the
-** database page-size is so large that more than RTREE_MAXCELLS entries
-** would fit in a single node, use a smaller node-size.
-*/
-static int getNodeSize(
- sqlite3 *db, /* Database handle */
- Rtree *pRtree, /* Rtree handle */
- int isCreate, /* True for xCreate, false for xConnect */
- char **pzErr /* OUT: Error message, if any */
-){
- int rc;
- char *zSql;
- if( isCreate ){
- int iPageSize = 0;
- zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
- rc = getIntFromStmt(db, zSql, &iPageSize);
- if( rc==SQLITE_OK ){
- pRtree->iNodeSize = iPageSize-64;
- if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
- pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
- }
- }else{
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }
- }else{
- zSql = sqlite3_mprintf(
- "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
- pRtree->zDb, pRtree->zName
- );
- rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
- if( rc!=SQLITE_OK ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }else if( pRtree->iNodeSize<(512-64) ){
- rc = SQLITE_CORRUPT_VTAB;
- *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
- pRtree->zName);
- }
- }
-
- sqlite3_free(zSql);
- return rc;
-}
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the r-tree virtual table.
-**
-** argv[0] -> module name
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> column names...
-*/
-static int rtreeInit(
- sqlite3 *db, /* Database connection */
- void *pAux, /* One of the RTREE_COORD_* constants */
- int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */
- sqlite3_vtab **ppVtab, /* OUT: New virtual table */
- char **pzErr, /* OUT: Error message, if any */
- int isCreate /* True for xCreate, false for xConnect */
-){
- int rc = SQLITE_OK;
- Rtree *pRtree;
- int nDb; /* Length of string argv[1] */
- int nName; /* Length of string argv[2] */
- int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32);
- sqlite3_str *pSql;
- char *zSql;
- int ii = 4;
- int iErr;
-
- const char *aErrMsg[] = {
- 0, /* 0 */
- "Wrong number of columns for an rtree table", /* 1 */
- "Too few columns for an rtree table", /* 2 */
- "Too many columns for an rtree table", /* 3 */
- "Auxiliary rtree columns must be last" /* 4 */
- };
-
- assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
- if( argc>RTREE_MAX_AUX_COLUMN+3 ){
- *pzErr = sqlite3_mprintf("%s", aErrMsg[3]);
- return SQLITE_ERROR;
- }
-
- sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
-
- /* Allocate the sqlite3_vtab structure */
- nDb = (int)strlen(argv[1]);
- nName = (int)strlen(argv[2]);
- pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
- if( !pRtree ){
- return SQLITE_NOMEM;
- }
- memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
- pRtree->nBusy = 1;
- pRtree->base.pModule = &rtreeModule;
- pRtree->zDb = (char *)&pRtree[1];
- pRtree->zName = &pRtree->zDb[nDb+1];
- pRtree->eCoordType = (u8)eCoordType;
- memcpy(pRtree->zDb, argv[1], nDb);
- memcpy(pRtree->zName, argv[2], nName);
-
-
- /* Create/Connect to the underlying relational database schema. If
- ** that is successful, call sqlite3_declare_vtab() to configure
- ** the r-tree table schema.
- */
- pSql = sqlite3_str_new(db);
- sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
- for(ii=4; ii<argc; ii++){
- if( argv[ii][0]=='+' ){
- pRtree->nAux++;
- sqlite3_str_appendf(pSql, ",%s", argv[ii]+1);
- }else if( pRtree->nAux>0 ){
- break;
- }else{
- pRtree->nDim2++;
- sqlite3_str_appendf(pSql, ",%s", argv[ii]);
- }
- }
- sqlite3_str_appendf(pSql, ");");
- zSql = sqlite3_str_finish(pSql);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else if( ii<argc ){
- *pzErr = sqlite3_mprintf("%s", aErrMsg[4]);
- rc = SQLITE_ERROR;
- }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }
- sqlite3_free(zSql);
- if( rc ) goto rtreeInit_fail;
- pRtree->nDim = pRtree->nDim2/2;
- if( pRtree->nDim<1 ){
- iErr = 2;
- }else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){
- iErr = 3;
- }else if( pRtree->nDim2 % 2 ){
- iErr = 1;
- }else{
- iErr = 0;
- }
- if( iErr ){
- *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
- goto rtreeInit_fail;
- }
- pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
-
- /* Figure out the node size to use. */
- rc = getNodeSize(db, pRtree, isCreate, pzErr);
- if( rc ) goto rtreeInit_fail;
- rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate);
- if( rc ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- goto rtreeInit_fail;
- }
-
- *ppVtab = (sqlite3_vtab *)pRtree;
- return SQLITE_OK;
-
-rtreeInit_fail:
- if( rc==SQLITE_OK ) rc = SQLITE_ERROR;
- assert( *ppVtab==0 );
- assert( pRtree->nBusy==1 );
- rtreeRelease(pRtree);
- return rc;
-}
-
-
-/*
-** Implementation of a scalar function that decodes r-tree nodes to
-** human readable strings. This can be used for debugging and analysis.
-**
-** The scalar function takes two arguments: (1) the number of dimensions
-** to the rtree (between 1 and 5, inclusive) and (2) a blob of data containing
-** an r-tree node. For a two-dimensional r-tree structure called "rt", to
-** deserialize all nodes, a statement like:
-**
-** SELECT rtreenode(2, data) FROM rt_node;
-**
-** The human readable string takes the form of a Tcl list with one
-** entry for each cell in the r-tree node. Each entry is itself a
-** list, containing the 8-byte rowid/pageno followed by the
-** <num-dimension>*2 coordinates.
-*/
-static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
- char *zText = 0;
- RtreeNode node;
- Rtree tree;
- int ii;
-
- UNUSED_PARAMETER(nArg);
- memset(&node, 0, sizeof(RtreeNode));
- memset(&tree, 0, sizeof(Rtree));
- tree.nDim = (u8)sqlite3_value_int(apArg[0]);
- tree.nDim2 = tree.nDim*2;
- tree.nBytesPerCell = 8 + 8 * tree.nDim;
- node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
-
- for(ii=0; ii<NCELL(&node); ii++){
- char zCell[512];
- int nCell = 0;
- RtreeCell cell;
- int jj;
-
- nodeGetCell(&tree, &node, ii, &cell);
- sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
- nCell = (int)strlen(zCell);
- for(jj=0; jj<tree.nDim2; jj++){
-#ifndef SQLITE_RTREE_INT_ONLY
- sqlite3_snprintf(512-nCell,&zCell[nCell], " %g",
- (double)cell.aCoord[jj].f);
-#else
- sqlite3_snprintf(512-nCell,&zCell[nCell], " %d",
- cell.aCoord[jj].i);
-#endif
- nCell = (int)strlen(zCell);
- }
-
- if( zText ){
- char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell);
- sqlite3_free(zText);
- zText = zTextNew;
- }else{
- zText = sqlite3_mprintf("{%s}", zCell);
- }
- }
-
- sqlite3_result_text(ctx, zText, -1, sqlite3_free);
-}
-
-/* This routine implements an SQL function that returns the "depth" parameter
-** from the front of a blob that is an r-tree node. For example:
-**
-** SELECT rtreedepth(data) FROM rt_node WHERE nodeno=1;
-**
-** The depth value is 0 for all nodes other than the root node, and the root
-** node always has nodeno=1, so the example above is the primary use for this
-** routine. This routine is intended for testing and analysis only.
-*/
-static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
- UNUSED_PARAMETER(nArg);
- if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
- || sqlite3_value_bytes(apArg[0])<2
- ){
- sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
- }else{
- u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
- sqlite3_result_int(ctx, readInt16(zBlob));
- }
-}
-
-/*
-** Context object passed between the various routines that make up the
-** implementation of integrity-check function rtreecheck().
-*/
-typedef struct RtreeCheck RtreeCheck;
-struct RtreeCheck {
- sqlite3 *db; /* Database handle */
- const char *zDb; /* Database containing rtree table */
- const char *zTab; /* Name of rtree table */
- int bInt; /* True for rtree_i32 table */
- int nDim; /* Number of dimensions for this rtree tbl */
- sqlite3_stmt *pGetNode; /* Statement used to retrieve nodes */
- sqlite3_stmt *aCheckMapping[2]; /* Statements to query %_parent/%_rowid */
- int nLeaf; /* Number of leaf cells in table */
- int nNonLeaf; /* Number of non-leaf cells in table */
- int rc; /* Return code */
- char *zReport; /* Message to report */
- int nErr; /* Number of lines in zReport */
-};
-
-#define RTREE_CHECK_MAX_ERROR 100
-
-/*
-** Reset SQL statement pStmt. If the sqlite3_reset() call returns an error,
-** and RtreeCheck.rc==SQLITE_OK, set RtreeCheck.rc to the error code.
-*/
-static void rtreeCheckReset(RtreeCheck *pCheck, sqlite3_stmt *pStmt){
- int rc = sqlite3_reset(pStmt);
- if( pCheck->rc==SQLITE_OK ) pCheck->rc = rc;
-}
-
-/*
-** The second and subsequent arguments to this function are a format string
-** and printf style arguments. This function formats the string and attempts
-** to compile it as an SQL statement.
-**
-** If successful, a pointer to the new SQL statement is returned. Otherwise,
-** NULL is returned and an error code left in RtreeCheck.rc.
-*/
-static sqlite3_stmt *rtreeCheckPrepare(
- RtreeCheck *pCheck, /* RtreeCheck object */
- const char *zFmt, ... /* Format string and trailing args */
-){
- va_list ap;
- char *z;
- sqlite3_stmt *pRet = 0;
-
- va_start(ap, zFmt);
- z = sqlite3_vmprintf(zFmt, ap);
-
- if( pCheck->rc==SQLITE_OK ){
- if( z==0 ){
- pCheck->rc = SQLITE_NOMEM;
- }else{
- pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0);
- }
- }
-
- sqlite3_free(z);
- va_end(ap);
- return pRet;
-}
-
-/*
-** The second and subsequent arguments to this function are a printf()
-** style format string and arguments. This function formats the string and
-** appends it to the report being accumuated in pCheck.
-*/
-static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
- va_list ap;
- va_start(ap, zFmt);
- if( pCheck->rc==SQLITE_OK && pCheck->nErr<RTREE_CHECK_MAX_ERROR ){
- char *z = sqlite3_vmprintf(zFmt, ap);
- if( z==0 ){
- pCheck->rc = SQLITE_NOMEM;
- }else{
- pCheck->zReport = sqlite3_mprintf("%z%s%z",
- pCheck->zReport, (pCheck->zReport ? "\n" : ""), z
- );
- if( pCheck->zReport==0 ){
- pCheck->rc = SQLITE_NOMEM;
- }
- }
- pCheck->nErr++;
- }
- va_end(ap);
-}
-
-/*
-** This function is a no-op if there is already an error code stored
-** in the RtreeCheck object indicated by the first argument. NULL is
-** returned in this case.
-**
-** Otherwise, the contents of rtree table node iNode are loaded from
-** the database and copied into a buffer obtained from sqlite3_malloc().
-** If no error occurs, a pointer to the buffer is returned and (*pnNode)
-** is set to the size of the buffer in bytes.
-**
-** Or, if an error does occur, NULL is returned and an error code left
-** in the RtreeCheck object. The final value of *pnNode is undefined in
-** this case.
-*/
-static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
- u8 *pRet = 0; /* Return value */
-
- assert( pCheck->rc==SQLITE_OK );
- if( pCheck->pGetNode==0 ){
- pCheck->pGetNode = rtreeCheckPrepare(pCheck,
- "SELECT data FROM %Q.'%q_node' WHERE nodeno=?",
- pCheck->zDb, pCheck->zTab
- );
- }
-
- if( pCheck->rc==SQLITE_OK ){
- sqlite3_bind_int64(pCheck->pGetNode, 1, iNode);
- if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){
- int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0);
- const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0);
- pRet = sqlite3_malloc(nNode);
- if( pRet==0 ){
- pCheck->rc = SQLITE_NOMEM;
- }else{
- memcpy(pRet, pNode, nNode);
- *pnNode = nNode;
- }
- }
- rtreeCheckReset(pCheck, pCheck->pGetNode);
- if( pCheck->rc==SQLITE_OK && pRet==0 ){
- rtreeCheckAppendMsg(pCheck, "Node %lld missing from database", iNode);
- }
- }
-
- return pRet;
-}
-
-/*
-** This function is used to check that the %_parent (if bLeaf==0) or %_rowid
-** (if bLeaf==1) table contains a specified entry. The schemas of the
-** two tables are:
-**
-** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
-** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...)
-**
-** In both cases, this function checks that there exists an entry with
-** IPK value iKey and the second column set to iVal.
-**
-*/
-static void rtreeCheckMapping(
- RtreeCheck *pCheck, /* RtreeCheck object */
- int bLeaf, /* True for a leaf cell, false for interior */
- i64 iKey, /* Key for mapping */
- i64 iVal /* Expected value for mapping */
-){
- int rc;
- sqlite3_stmt *pStmt;
- const char *azSql[2] = {
- "SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1",
- "SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1"
- };
-
- assert( bLeaf==0 || bLeaf==1 );
- if( pCheck->aCheckMapping[bLeaf]==0 ){
- pCheck->aCheckMapping[bLeaf] = rtreeCheckPrepare(pCheck,
- azSql[bLeaf], pCheck->zDb, pCheck->zTab
- );
- }
- if( pCheck->rc!=SQLITE_OK ) return;
-
- pStmt = pCheck->aCheckMapping[bLeaf];
- sqlite3_bind_int64(pStmt, 1, iKey);
- rc = sqlite3_step(pStmt);
- if( rc==SQLITE_DONE ){
- rtreeCheckAppendMsg(pCheck, "Mapping (%lld -> %lld) missing from %s table",
- iKey, iVal, (bLeaf ? "%_rowid" : "%_parent")
- );
- }else if( rc==SQLITE_ROW ){
- i64 ii = sqlite3_column_int64(pStmt, 0);
- if( ii!=iVal ){
- rtreeCheckAppendMsg(pCheck,
- "Found (%lld -> %lld) in %s table, expected (%lld -> %lld)",
- iKey, ii, (bLeaf ? "%_rowid" : "%_parent"), iKey, iVal
- );
- }
- }
- rtreeCheckReset(pCheck, pStmt);
-}
-
-/*
-** Argument pCell points to an array of coordinates stored on an rtree page.
-** This function checks that the coordinates are internally consistent (no
-** x1>x2 conditions) and adds an error message to the RtreeCheck object
-** if they are not.
-**
-** Additionally, if pParent is not NULL, then it is assumed to point to
-** the array of coordinates on the parent page that bound the page
-** containing pCell. In this case it is also verified that the two
-** sets of coordinates are mutually consistent and an error message added
-** to the RtreeCheck object if they are not.
-*/
-static void rtreeCheckCellCoord(
- RtreeCheck *pCheck,
- i64 iNode, /* Node id to use in error messages */
- int iCell, /* Cell number to use in error messages */
- u8 *pCell, /* Pointer to cell coordinates */
- u8 *pParent /* Pointer to parent coordinates */
-){
- RtreeCoord c1, c2;
- RtreeCoord p1, p2;
- int i;
-
- for(i=0; i<pCheck->nDim; i++){
- readCoord(&pCell[4*2*i], &c1);
- readCoord(&pCell[4*(2*i + 1)], &c2);
-
- /* printf("%e, %e\n", c1.u.f, c2.u.f); */
- if( pCheck->bInt ? c1.i>c2.i : c1.f>c2.f ){
- rtreeCheckAppendMsg(pCheck,
- "Dimension %d of cell %d on node %lld is corrupt", i, iCell, iNode
- );
- }
-
- if( pParent ){
- readCoord(&pParent[4*2*i], &p1);
- readCoord(&pParent[4*(2*i + 1)], &p2);
-
- if( (pCheck->bInt ? c1.i<p1.i : c1.f<p1.f)
- || (pCheck->bInt ? c2.i>p2.i : c2.f>p2.f)
- ){
- rtreeCheckAppendMsg(pCheck,
- "Dimension %d of cell %d on node %lld is corrupt relative to parent"
- , i, iCell, iNode
- );
- }
- }
- }
-}
-
-/*
-** Run rtreecheck() checks on node iNode, which is at depth iDepth within
-** the r-tree structure. Argument aParent points to the array of coordinates
-** that bound node iNode on the parent node.
-**
-** If any problems are discovered, an error message is appended to the
-** report accumulated in the RtreeCheck object.
-*/
-static void rtreeCheckNode(
- RtreeCheck *pCheck,
- int iDepth, /* Depth of iNode (0==leaf) */
- u8 *aParent, /* Buffer containing parent coords */
- i64 iNode /* Node to check */
-){
- u8 *aNode = 0;
- int nNode = 0;
-
- assert( iNode==1 || aParent!=0 );
- assert( pCheck->nDim>0 );
-
- aNode = rtreeCheckGetNode(pCheck, iNode, &nNode);
- if( aNode ){
- if( nNode<4 ){
- rtreeCheckAppendMsg(pCheck,
- "Node %lld is too small (%d bytes)", iNode, nNode
- );
- }else{
- int nCell; /* Number of cells on page */
- int i; /* Used to iterate through cells */
- if( aParent==0 ){
- iDepth = readInt16(aNode);
- if( iDepth>RTREE_MAX_DEPTH ){
- rtreeCheckAppendMsg(pCheck, "Rtree depth out of range (%d)", iDepth);
- sqlite3_free(aNode);
- return;
- }
- }
- nCell = readInt16(&aNode[2]);
- if( (4 + nCell*(8 + pCheck->nDim*2*4))>nNode ){
- rtreeCheckAppendMsg(pCheck,
- "Node %lld is too small for cell count of %d (%d bytes)",
- iNode, nCell, nNode
- );
- }else{
- for(i=0; i<nCell; i++){
- u8 *pCell = &aNode[4 + i*(8 + pCheck->nDim*2*4)];
- i64 iVal = readInt64(pCell);
- rtreeCheckCellCoord(pCheck, iNode, i, &pCell[8], aParent);
-
- if( iDepth>0 ){
- rtreeCheckMapping(pCheck, 0, iVal, iNode);
- rtreeCheckNode(pCheck, iDepth-1, &pCell[8], iVal);
- pCheck->nNonLeaf++;
- }else{
- rtreeCheckMapping(pCheck, 1, iVal, iNode);
- pCheck->nLeaf++;
- }
- }
- }
- }
- sqlite3_free(aNode);
- }
-}
-
-/*
-** The second argument to this function must be either "_rowid" or
-** "_parent". This function checks that the number of entries in the
-** %_rowid or %_parent table is exactly nExpect. If not, it adds
-** an error message to the report in the RtreeCheck object indicated
-** by the first argument.
-*/
-static void rtreeCheckCount(RtreeCheck *pCheck, const char *zTbl, i64 nExpect){
- if( pCheck->rc==SQLITE_OK ){
- sqlite3_stmt *pCount;
- pCount = rtreeCheckPrepare(pCheck, "SELECT count(*) FROM %Q.'%q%s'",
- pCheck->zDb, pCheck->zTab, zTbl
- );
- if( pCount ){
- if( sqlite3_step(pCount)==SQLITE_ROW ){
- i64 nActual = sqlite3_column_int64(pCount, 0);
- if( nActual!=nExpect ){
- rtreeCheckAppendMsg(pCheck, "Wrong number of entries in %%%s table"
- " - expected %lld, actual %lld" , zTbl, nExpect, nActual
- );
- }
- }
- pCheck->rc = sqlite3_finalize(pCount);
- }
- }
-}
-
-/*
-** This function does the bulk of the work for the rtree integrity-check.
-** It is called by rtreecheck(), which is the SQL function implementation.
-*/
-static int rtreeCheckTable(
- sqlite3 *db, /* Database handle to access db through */
- const char *zDb, /* Name of db ("main", "temp" etc.) */
- const char *zTab, /* Name of rtree table to check */
- char **pzReport /* OUT: sqlite3_malloc'd report text */
-){
- RtreeCheck check; /* Common context for various routines */
- sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */
- int bEnd = 0; /* True if transaction should be closed */
- int nAux = 0; /* Number of extra columns. */
-
- /* Initialize the context object */
- memset(&check, 0, sizeof(check));
- check.db = db;
- check.zDb = zDb;
- check.zTab = zTab;
-
- /* If there is not already an open transaction, open one now. This is
- ** to ensure that the queries run as part of this integrity-check operate
- ** on a consistent snapshot. */
- if( sqlite3_get_autocommit(db) ){
- check.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
- bEnd = 1;
- }
-
- /* Find the number of auxiliary columns */
- if( check.rc==SQLITE_OK ){
- pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab);
- if( pStmt ){
- nAux = sqlite3_column_count(pStmt) - 2;
- sqlite3_finalize(pStmt);
- }
- check.rc = SQLITE_OK;
- }
-
- /* Find number of dimensions in the rtree table. */
- pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab);
- if( pStmt ){
- int rc;
- check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2;
- if( check.nDim<1 ){
- rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree");
- }else if( SQLITE_ROW==sqlite3_step(pStmt) ){
- check.bInt = (sqlite3_column_type(pStmt, 1)==SQLITE_INTEGER);
- }
- rc = sqlite3_finalize(pStmt);
- if( rc!=SQLITE_CORRUPT ) check.rc = rc;
- }
-
- /* Do the actual integrity-check */
- if( check.nDim>=1 ){
- if( check.rc==SQLITE_OK ){
- rtreeCheckNode(&check, 0, 0, 1);
- }
- rtreeCheckCount(&check, "_rowid", check.nLeaf);
- rtreeCheckCount(&check, "_parent", check.nNonLeaf);
- }
-
- /* Finalize SQL statements used by the integrity-check */
- sqlite3_finalize(check.pGetNode);
- sqlite3_finalize(check.aCheckMapping[0]);
- sqlite3_finalize(check.aCheckMapping[1]);
-
- /* If one was opened, close the transaction */
- if( bEnd ){
- int rc = sqlite3_exec(db, "END", 0, 0, 0);
- if( check.rc==SQLITE_OK ) check.rc = rc;
- }
- *pzReport = check.zReport;
- return check.rc;
-}
-
-/*
-** Usage:
-**
-** rtreecheck(<rtree-table>);
-** rtreecheck(<database>, <rtree-table>);
-**
-** Invoking this SQL function runs an integrity-check on the named rtree
-** table. The integrity-check verifies the following:
-**
-** 1. For each cell in the r-tree structure (%_node table), that:
-**
-** a) for each dimension, (coord1 <= coord2).
-**
-** b) unless the cell is on the root node, that the cell is bounded
-** by the parent cell on the parent node.
-**
-** c) for leaf nodes, that there is an entry in the %_rowid
-** table corresponding to the cell's rowid value that
-** points to the correct node.
-**
-** d) for cells on non-leaf nodes, that there is an entry in the
-** %_parent table mapping from the cell's child node to the
-** node that it resides on.
-**
-** 2. That there are the same number of entries in the %_rowid table
-** as there are leaf cells in the r-tree structure, and that there
-** is a leaf cell that corresponds to each entry in the %_rowid table.
-**
-** 3. That there are the same number of entries in the %_parent table
-** as there are non-leaf cells in the r-tree structure, and that
-** there is a non-leaf cell that corresponds to each entry in the
-** %_parent table.
-*/
-static void rtreecheck(
- sqlite3_context *ctx,
- int nArg,
- sqlite3_value **apArg
-){
- if( nArg!=1 && nArg!=2 ){
- sqlite3_result_error(ctx,
- "wrong number of arguments to function rtreecheck()", -1
- );
- }else{
- int rc;
- char *zReport = 0;
- const char *zDb = (const char*)sqlite3_value_text(apArg[0]);
- const char *zTab;
- if( nArg==1 ){
- zTab = zDb;
- zDb = "main";
- }else{
- zTab = (const char*)sqlite3_value_text(apArg[1]);
- }
- rc = rtreeCheckTable(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport);
- if( rc==SQLITE_OK ){
- sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_error_code(ctx, rc);
- }
- sqlite3_free(zReport);
- }
-}
-
-
-/*
-** Register the r-tree module with database handle db. This creates the
-** virtual table module "rtree" and the debugging/analysis scalar
-** function "rtreenode".
-*/
-int sqlite3RtreeInit(sqlite3 *db){
- const int utf8 = SQLITE_UTF8;
- int rc;
-
- rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "rtreecheck", -1, utf8, 0,rtreecheck, 0,0);
- }
- if( rc==SQLITE_OK ){
-#ifdef SQLITE_RTREE_INT_ONLY
- void *c = (void *)RTREE_COORD_INT32;
-#else
- void *c = (void *)RTREE_COORD_REAL32;
-#endif
- rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0);
- }
- if( rc==SQLITE_OK ){
- void *c = (void *)RTREE_COORD_INT32;
- rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0);
- }
-
- return rc;
-}
-
-/*
-** This routine deletes the RtreeGeomCallback object that was attached
-** one of the SQL functions create by sqlite3_rtree_geometry_callback()
-** or sqlite3_rtree_query_callback(). In other words, this routine is the
-** destructor for an RtreeGeomCallback objecct. This routine is called when
-** the corresponding SQL function is deleted.
-*/
-static void rtreeFreeCallback(void *p){
- RtreeGeomCallback *pInfo = (RtreeGeomCallback*)p;
- if( pInfo->xDestructor ) pInfo->xDestructor(pInfo->pContext);
- sqlite3_free(p);
-}
-
-/*
-** This routine frees the BLOB that is returned by geomCallback().
-*/
-static void rtreeMatchArgFree(void *pArg){
- int i;
- RtreeMatchArg *p = (RtreeMatchArg*)pArg;
- for(i=0; i<p->nParam; i++){
- sqlite3_value_free(p->apSqlParam[i]);
- }
- sqlite3_free(p);
-}
-
-/*
-** Each call to sqlite3_rtree_geometry_callback() or
-** sqlite3_rtree_query_callback() creates an ordinary SQLite
-** scalar function that is implemented by this routine.
-**
-** All this function does is construct an RtreeMatchArg object that
-** contains the geometry-checking callback routines and a list of
-** parameters to this function, then return that RtreeMatchArg object
-** as a BLOB.
-**
-** The R-Tree MATCH operator will read the returned BLOB, deserialize
-** the RtreeMatchArg object, and use the RtreeMatchArg object to figure
-** out which elements of the R-Tree should be returned by the query.
-*/
-static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
- RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
- RtreeMatchArg *pBlob;
- int nBlob;
- int memErr = 0;
-
- nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
- + nArg*sizeof(sqlite3_value*);
- pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
- if( !pBlob ){
- sqlite3_result_error_nomem(ctx);
- }else{
- int i;
- pBlob->iSize = nBlob;
- pBlob->cb = pGeomCtx[0];
- pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg];
- pBlob->nParam = nArg;
- for(i=0; i<nArg; i++){
- pBlob->apSqlParam[i] = sqlite3_value_dup(aArg[i]);
- if( pBlob->apSqlParam[i]==0 ) memErr = 1;
-#ifdef SQLITE_RTREE_INT_ONLY
- pBlob->aParam[i] = sqlite3_value_int64(aArg[i]);
-#else
- pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
-#endif
- }
- if( memErr ){
- sqlite3_result_error_nomem(ctx);
- rtreeMatchArgFree(pBlob);
- }else{
- sqlite3_result_pointer(ctx, pBlob, "RtreeMatchArg", rtreeMatchArgFree);
- }
- }
-}
-
-/*
-** Register a new geometry function for use with the r-tree MATCH operator.
-*/
-int sqlite3_rtree_geometry_callback(
- sqlite3 *db, /* Register SQL function on this connection */
- const char *zGeom, /* Name of the new SQL function */
- int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */
- void *pContext /* Extra data associated with the callback */
-){
- RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */
-
- /* Allocate and populate the context object. */
- pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
- if( !pGeomCtx ) return SQLITE_NOMEM;
- pGeomCtx->xGeom = xGeom;
- pGeomCtx->xQueryFunc = 0;
- pGeomCtx->xDestructor = 0;
- pGeomCtx->pContext = pContext;
- return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY,
- (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback
- );
-}
-
-/*
-** Register a new 2nd-generation geometry function for use with the
-** r-tree MATCH operator.
-*/
-int sqlite3_rtree_query_callback(
- sqlite3 *db, /* Register SQL function on this connection */
- const char *zQueryFunc, /* Name of new SQL function */
- int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */
- void *pContext, /* Extra data passed into the callback */
- void (*xDestructor)(void*) /* Destructor for the extra data */
-){
- RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */
-
- /* Allocate and populate the context object. */
- pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
- if( !pGeomCtx ) return SQLITE_NOMEM;
- pGeomCtx->xGeom = 0;
- pGeomCtx->xQueryFunc = xQueryFunc;
- pGeomCtx->xDestructor = xDestructor;
- pGeomCtx->pContext = pContext;
- return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY,
- (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback
- );
-}
-
-#if !SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_rtree_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi)
- return sqlite3RtreeInit(db);
-}
-#endif
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree.h
deleted file mode 100644
index 8f41500db1a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-** 2008 May 26
-**
-** 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 header file is used by programs that want to link against the
-** RTREE library. All it does is declare the sqlite3RtreeInit() interface.
-*/
-#include "sqlite3.h"
-
-#ifdef SQLITE_OMIT_VIRTUALTABLE
-# undef SQLITE_ENABLE_RTREE
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int sqlite3RtreeInit(sqlite3 *db);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree1.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree1.test
deleted file mode 100644
index bdaad542d29..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree1.test
+++ /dev/null
@@ -1,651 +0,0 @@
-# 2008 Feb 19
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the r-tree extension.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-set testprefix rtree1
-
-# Test plan:
-#
-# rtree-1.*: Creating/destroying r-tree tables.
-# rtree-2.*: Test the implicit constraints - unique rowid and
-# (coord[N]<=coord[N+1]) for even values of N. Also
-# automatic assigning of rowid values.
-# rtree-3.*: Linear scans of r-tree data.
-# rtree-4.*: Test INSERT
-# rtree-5.*: Test DELETE
-# rtree-6.*: Test UPDATE
-# rtree-7.*: Test renaming an r-tree table.
-# rtree-8.*: Test constrained scans of r-tree data.
-#
-# rtree-12.*: Test that on-conflict clauses are supported.
-# rtree-13.*: Test that bug [d2889096e7bdeac6d] has been fixed.
-# rtree-14.*: Test if a non-integer is inserted into the PK column of an
-# r-tree table, it is converted to an integer before being
-# inserted. Also that if a non-numeric is inserted into one
-# of the min/max dimension columns, it is converted to the
-# required type before being inserted.
-# rtree-15.*: Check that DROP TABLE works within a transaction that
-# writes to an r-tree table.
-#
-
-ifcapable !rtree {
- finish_test
- return
-}
-
-#----------------------------------------------------------------------------
-# Test cases rtree-1.* test CREATE and DROP table statements.
-#
-
-# Test creating and dropping an rtree table.
-#
-do_test rtree-1.1.1 {
- execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2) }
-} {}
-do_test rtree-1.1.2 {
- execsql { SELECT name FROM sqlite_master ORDER BY name }
-} {t1 t1_node t1_parent t1_rowid}
-do_test rtree-1.1.3 {
- execsql {
- DROP TABLE t1;
- SELECT name FROM sqlite_master ORDER BY name;
- }
-} {}
-
-# Test creating and dropping an rtree table with an odd name in
-# an attached database.
-#
-do_test rtree-1.2.1 {
- file delete -force test2.db
- execsql {
- ATTACH 'test2.db' AS aux;
- CREATE VIRTUAL TABLE aux.'a" "b' USING rtree(ii, x1, x2, y1, y2);
- }
-} {}
-do_test rtree-1.2.2 {
- execsql { SELECT name FROM sqlite_master ORDER BY name }
-} {}
-do_test rtree-1.2.3 {
- execsql { SELECT name FROM aux.sqlite_master ORDER BY name }
-} {{a" "b} {a" "b_node} {a" "b_parent} {a" "b_rowid}}
-do_test rtree-1.2.4 {
- execsql {
- DROP TABLE aux.'a" "b';
- SELECT name FROM aux.sqlite_master ORDER BY name;
- }
-} {}
-
-# Test that the logic for checking the number of columns specified
-# for an rtree table. Acceptable values are odd numbers between 3 and
-# 11, inclusive.
-#
-set cols [list i1 i2 i3 i4 i5 i6 i7 i8 i9 iA iB iC iD iE iF iG iH iI iJ iK]
-for {set nCol 1} {$nCol<[llength $cols]} {incr nCol} {
-
- set columns [join [lrange $cols 0 [expr {$nCol-1}]] ,]
-
- set X {0 {}}
- if {$nCol%2 == 0} { set X {1 {Wrong number of columns for an rtree table}} }
- if {$nCol < 3} { set X {1 {Too few columns for an rtree table}} }
- if {$nCol > 11} { set X {1 {Too many columns for an rtree table}} }
-
- do_test rtree-1.3.$nCol {
- catchsql "
- CREATE VIRTUAL TABLE t1 USING rtree($columns);
- "
- } $X
-
- catchsql { DROP TABLE t1 }
-}
-
-# Like execsql except display output as integer where that can be
-# done without loss of information.
-#
-proc execsql_intout {sql} {
- set out {}
- foreach term [execsql $sql] {
- regsub {\.0$} $term {} term
- lappend out $term
- }
- return $out
-}
-
-# Test that it is possible to open an existing database that contains
-# r-tree tables.
-#
-do_execsql_test rtree-1.4.1a {
- CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2);
- INSERT INTO t1 VALUES(1, 5.0, 10.0);
- SELECT substr(hex(data),1,40) FROM t1_node;
-} {00000001000000000000000140A0000041200000}
-do_execsql_test rtree-1.4.1b {
- INSERT INTO t1 VALUES(2, 15.0, 20.0);
-} {}
-do_test rtree-1.4.2 {
- db close
- sqlite3 db test.db
- execsql_intout { SELECT * FROM t1 ORDER BY ii }
-} {1 5 10 2 15 20}
-do_test rtree-1.4.3 {
- execsql { DROP TABLE t1 }
-} {}
-
-# Test that it is possible to create an r-tree table with ridiculous
-# column names.
-#
-do_test rtree-1.5.1 {
- execsql_intout {
- CREATE VIRTUAL TABLE t1 USING rtree("the key", "x dim.", "x2'dim");
- INSERT INTO t1 VALUES(1, 2, 3);
- SELECT "the key", "x dim.", "x2'dim" FROM t1;
- }
-} {1 2 3}
-do_test rtree-1.5.1 {
- execsql { DROP TABLE t1 }
-} {}
-
-# Force the r-tree constructor to fail.
-#
-do_test rtree-1.6.1 {
- execsql { CREATE TABLE t1_rowid(a); }
- catchsql {
- CREATE VIRTUAL TABLE t1 USING rtree("the key", "x dim.", "x2'dim");
- }
-} {1 {table "t1_rowid" already exists}}
-do_test rtree-1.6.1 {
- execsql { DROP TABLE t1_rowid }
-} {}
-
-#----------------------------------------------------------------------------
-# Test cases rtree-2.*
-#
-do_test rtree-2.1.1 {
- execsql {
- CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2);
- SELECT * FROM t1;
- }
-} {}
-
-do_test rtree-2.1.2 {
- execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) }
- execsql_intout { SELECT * FROM t1 }
-} {1 1 3 2 4}
-do_test rtree-2.1.3 {
- execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) }
- execsql { SELECT rowid FROM t1 ORDER BY rowid }
-} {1 2}
-do_test rtree-2.1.3 {
- execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) }
- execsql { SELECT ii FROM t1 ORDER BY ii }
-} {1 2 3}
-
-do_test rtree-2.2.1 {
- catchsql { INSERT INTO t1 VALUES(2, 1, 3, 2, 4) }
-} {1 {UNIQUE constraint failed: t1.ii}}
-do_test rtree-2.2.2 {
- catchsql { INSERT INTO t1 VALUES(4, 1, 3, 4, 2) }
-} {1 {rtree constraint failed: t1.(y1<=y2)}}
-do_test rtree-2.2.3 {
- catchsql { INSERT INTO t1 VALUES(4, 3, 1, 2, 4) }
-} {1 {rtree constraint failed: t1.(x1<=x2)}}
-do_test rtree-2.2.4 {
- execsql { SELECT ii FROM t1 ORDER BY ii }
-} {1 2 3}
-
-do_test rtree-2.X {
- execsql { DROP TABLE t1 }
-} {}
-
-#----------------------------------------------------------------------------
-# Test cases rtree-3.* test linear scans of r-tree table data. To test
-# this we have to insert some data into an r-tree, but that is not the
-# focus of these tests.
-#
-do_test rtree-3.1.1 {
- execsql {
- CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2);
- SELECT * FROM t1;
- }
-} {}
-do_test rtree-3.1.2 {
- execsql_intout {
- INSERT INTO t1 VALUES(5, 1, 3, 2, 4);
- SELECT * FROM t1;
- }
-} {5 1 3 2 4}
-do_test rtree-3.1.3 {
- execsql_intout {
- INSERT INTO t1 VALUES(6, 2, 6, 4, 8);
- SELECT * FROM t1;
- }
-} {5 1 3 2 4 6 2 6 4 8}
-
-# Test the constraint on the coordinates (c[i]<=c[i+1] where (i%2==0)):
-do_test rtree-3.2.1 {
- catchsql { INSERT INTO t1 VALUES(7, 2, 6, 4, 3) }
-} {1 {rtree constraint failed: t1.(y1<=y2)}}
-do_test rtree-3.2.2 {
- catchsql { INSERT INTO t1 VALUES(8, 2, 6, 3, 3) }
-} {0 {}}
-
-#----------------------------------------------------------------------------
-# Test cases rtree-5.* test DELETE operations.
-#
-do_test rtree-5.1.1 {
- execsql { CREATE VIRTUAL TABLE t2 USING rtree(ii, x1, x2) }
-} {}
-do_test rtree-5.1.2 {
- execsql_intout {
- INSERT INTO t2 VALUES(1, 10, 20);
- INSERT INTO t2 VALUES(2, 30, 40);
- INSERT INTO t2 VALUES(3, 50, 60);
- SELECT * FROM t2 ORDER BY ii;
- }
-} {1 10 20 2 30 40 3 50 60}
-do_test rtree-5.1.3 {
- execsql_intout {
- DELETE FROM t2 WHERE ii=2;
- SELECT * FROM t2 ORDER BY ii;
- }
-} {1 10 20 3 50 60}
-do_test rtree-5.1.4 {
- execsql_intout {
- DELETE FROM t2 WHERE ii=1;
- SELECT * FROM t2 ORDER BY ii;
- }
-} {3 50 60}
-do_test rtree-5.1.5 {
- execsql {
- DELETE FROM t2 WHERE ii=3;
- SELECT * FROM t2 ORDER BY ii;
- }
-} {}
-do_test rtree-5.1.6 {
- execsql { SELECT * FROM t2_rowid }
-} {}
-
-#----------------------------------------------------------------------------
-# Test cases rtree-5.* test UPDATE operations.
-#
-do_test rtree-6.1.1 {
- execsql { CREATE VIRTUAL TABLE t3 USING rtree(ii, x1, x2, y1, y2) }
-} {}
-do_test rtree-6.1.2 {
- execsql_intout {
- INSERT INTO t3 VALUES(1, 2, 3, 4, 5);
- UPDATE t3 SET x2=5;
- SELECT * FROM t3;
- }
-} {1 2 5 4 5}
-do_test rtree-6.1.3 {
- execsql { UPDATE t3 SET ii = 2 }
- execsql_intout { SELECT * FROM t3 }
-} {2 2 5 4 5}
-
-#----------------------------------------------------------------------------
-# Test cases rtree-7.* test rename operations.
-#
-do_test rtree-7.1.1 {
- execsql {
- CREATE VIRTUAL TABLE t4 USING rtree(ii, x1, x2, y1, y2, z1, z2);
- INSERT INTO t4 VALUES(1, 2, 3, 4, 5, 6, 7);
- }
-} {}
-do_test rtree-7.1.2 {
- execsql { ALTER TABLE t4 RENAME TO t5 }
- execsql_intout { SELECT * FROM t5 }
-} {1 2 3 4 5 6 7}
-do_test rtree-7.1.3 {
- db close
- sqlite3 db test.db
- execsql_intout { SELECT * FROM t5 }
-} {1 2 3 4 5 6 7}
-do_test rtree-7.1.4 {
- execsql { ALTER TABLE t5 RENAME TO 'raisara "one"'''}
- execsql_intout { SELECT * FROM "raisara ""one""'" }
-} {1 2 3 4 5 6 7}
-do_test rtree-7.1.5 {
- execsql_intout { SELECT * FROM 'raisara "one"''' }
-} {1 2 3 4 5 6 7}
-do_test rtree-7.1.6 {
- execsql { ALTER TABLE "raisara ""one""'" RENAME TO "abc 123" }
- execsql_intout { SELECT * FROM "abc 123" }
-} {1 2 3 4 5 6 7}
-do_test rtree-7.1.7 {
- db close
- sqlite3 db test.db
- execsql_intout { SELECT * FROM "abc 123" }
-} {1 2 3 4 5 6 7}
-
-# An error midway through a rename operation.
-do_test rtree-7.2.1 {
- execsql {
- CREATE TABLE t4_node(a);
- }
- catchsql { ALTER TABLE "abc 123" RENAME TO t4 }
-} {1 {SQL logic error}}
-do_test rtree-7.2.2 {
- execsql_intout { SELECT * FROM "abc 123" }
-} {1 2 3 4 5 6 7}
-do_test rtree-7.2.3 {
- execsql {
- DROP TABLE t4_node;
- CREATE TABLE t4_rowid(a);
- }
- catchsql { ALTER TABLE "abc 123" RENAME TO t4 }
-} {1 {SQL logic error}}
-do_test rtree-7.2.4 {
- db close
- sqlite3 db test.db
- execsql_intout { SELECT * FROM "abc 123" }
-} {1 2 3 4 5 6 7}
-do_test rtree-7.2.5 {
- execsql { DROP TABLE t4_rowid }
- execsql { ALTER TABLE "abc 123" RENAME TO t4 }
- execsql_intout { SELECT * FROM t4 }
-} {1 2 3 4 5 6 7}
-
-
-#----------------------------------------------------------------------------
-# Test cases rtree-8.*
-#
-
-# Test that the function to determine if a leaf cell is part of the
-# result set works.
-do_test rtree-8.1.1 {
- execsql {
- CREATE VIRTUAL TABLE t6 USING rtree(ii, x1, x2);
- INSERT INTO t6 VALUES(1, 3, 7);
- INSERT INTO t6 VALUES(2, 4, 6);
- }
-} {}
-do_test rtree-8.1.2 { execsql { SELECT ii FROM t6 WHERE x1>2 } } {1 2}
-do_test rtree-8.1.3 { execsql { SELECT ii FROM t6 WHERE x1>3 } } {2}
-do_test rtree-8.1.4 { execsql { SELECT ii FROM t6 WHERE x1>4 } } {}
-do_test rtree-8.1.5 { execsql { SELECT ii FROM t6 WHERE x1>5 } } {}
-do_test rtree-8.1.6 { execsql { SELECT ii FROM t6 WHERE x1<3 } } {}
-do_test rtree-8.1.7 { execsql { SELECT ii FROM t6 WHERE x1<4 } } {1}
-do_test rtree-8.1.8 { execsql { SELECT ii FROM t6 WHERE x1<5 } } {1 2}
-
-#----------------------------------------------------------------------------
-# Test cases rtree-9.*
-#
-# Test that ticket #3549 is fixed.
-do_test rtree-9.1 {
- execsql {
- CREATE TABLE foo (id INTEGER PRIMARY KEY);
- CREATE VIRTUAL TABLE bar USING rtree (id, minX, maxX, minY, maxY);
- INSERT INTO foo VALUES (null);
- INSERT INTO foo SELECT null FROM foo;
- INSERT INTO foo SELECT null FROM foo;
- INSERT INTO foo SELECT null FROM foo;
- INSERT INTO foo SELECT null FROM foo;
- INSERT INTO foo SELECT null FROM foo;
- INSERT INTO foo SELECT null FROM foo;
- DELETE FROM foo WHERE id > 40;
- INSERT INTO bar SELECT NULL, 0, 0, 0, 0 FROM foo;
- }
-} {}
-
-# This used to crash.
-do_test rtree-9.2 {
- execsql {
- SELECT count(*) FROM bar b1, bar b2, foo s1 WHERE s1.id = b1.id;
- }
-} {1600}
-do_test rtree-9.3 {
- execsql {
- SELECT count(*) FROM bar b1, bar b2, foo s1
- WHERE b1.minX <= b2.maxX AND s1.id = b1.id;
- }
-} {1600}
-
-#-------------------------------------------------------------------------
-# Ticket #3970: Check that the error message is meaningful when a
-# keyword is used as a column name.
-#
-do_test rtree-10.1 {
- catchsql { CREATE VIRTUAL TABLE t7 USING rtree(index, x1, y1, x2, y2) }
-} {1 {near "index": syntax error}}
-
-#-------------------------------------------------------------------------
-# Test last_insert_rowid().
-#
-do_test rtree-11.1 {
- execsql {
- CREATE VIRTUAL TABLE t8 USING rtree(idx, x1, x2, y1, y2);
- INSERT INTO t8 VALUES(1, 1.0, 1.0, 2.0, 2.0);
- SELECT last_insert_rowid();
- }
-} {1}
-do_test rtree-11.2 {
- execsql {
- INSERT INTO t8 VALUES(NULL, 1.0, 1.0, 2.0, 2.0);
- SELECT last_insert_rowid();
- }
-} {2}
-
-#-------------------------------------------------------------------------
-# Test on-conflict clause handling.
-#
-db_delete_and_reopen
-do_execsql_test 12.0.1 {
- CREATE VIRTUAL TABLE t1 USING rtree_i32(idx, x1, x2, y1, y2);
- INSERT INTO t1 VALUES(1, 1, 2, 3, 4);
- SELECT substr(hex(data),1,56) FROM t1_node;
-} {00000001000000000000000100000001000000020000000300000004}
-do_execsql_test 12.0.2 {
- INSERT INTO t1 VALUES(2, 2, 3, 4, 5);
- INSERT INTO t1 VALUES(3, 3, 4, 5, 6);
-
- CREATE TABLE source(idx, x1, x2, y1, y2);
- INSERT INTO source VALUES(5, 8, 8, 8, 8);
- INSERT INTO source VALUES(2, 7, 7, 7, 7);
-}
-db_save_and_close
-foreach {tn sql_template testdata} {
- 1 "INSERT %CONF% INTO t1 VALUES(2, 7, 7, 7, 7)" {
- ROLLBACK 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
- ABORT 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- IGNORE 0 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- FAIL 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- REPLACE 0 0 {1 1 2 3 4 2 7 7 7 7 3 3 4 5 6 4 4 5 6 7}
- }
-
- 2 "INSERT %CONF% INTO t1 SELECT * FROM source" {
- ROLLBACK 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
- ABORT 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- IGNORE 1 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7 5 8 8 8 8}
- FAIL 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7 5 8 8 8 8}
- REPLACE 1 0 {1 1 2 3 4 2 7 7 7 7 3 3 4 5 6 4 4 5 6 7 5 8 8 8 8}
- }
-
- 3 "UPDATE %CONF% t1 SET idx = 2 WHERE idx = 4" {
- ROLLBACK 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
- ABORT 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- IGNORE 0 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- FAIL 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- REPLACE 0 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6}
- }
-
- 3 "UPDATE %CONF% t1 SET idx = ((idx+1)%5)+1 WHERE idx > 2" {
- ROLLBACK 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
- ABORT 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- IGNORE 1 0 {1 1 2 3 4 2 2 3 4 5 4 4 5 6 7 5 3 4 5 6}
- FAIL 1 1 {1 1 2 3 4 2 2 3 4 5 4 4 5 6 7 5 3 4 5 6}
- REPLACE 1 0 {1 4 5 6 7 2 2 3 4 5 5 3 4 5 6}
- }
-
- 4 "INSERT %CONF% INTO t1 VALUES(2, 7, 6, 7, 7)" {
- ROLLBACK 0 2 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
- ABORT 0 2 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- IGNORE 0 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- FAIL 0 2 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- REPLACE 0 2 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
- }
-
-} {
- foreach {mode uses error data} $testdata {
- db_restore_and_reopen
-
- set sql [string map [list %CONF% "OR $mode"] $sql_template]
- set testname "12.$tn.[string tolower $mode]"
-
- execsql {
- BEGIN;
- INSERT INTO t1 VALUES(4, 4, 5, 6, 7);
- }
-
- set res(0) {0 {}}
- set res(1) {1 {UNIQUE constraint failed: t1.idx}}
- set res(2) {1 {rtree constraint failed: t1.(x1<=x2)}}
-
- do_catchsql_test $testname.1 $sql $res($error)
- do_test $testname.2 [list sql_uses_stmt db $sql] $uses
- do_execsql_test $testname.3 { SELECT * FROM t1 ORDER BY idx } $data
-
- do_rtree_integrity_test $testname.4 t1
- db close
- }
-}
-
-#-------------------------------------------------------------------------
-# Test that bug [d2889096e7bdeac6d] has been fixed.
-#
-reset_db
-do_execsql_test 13.1 {
- CREATE VIRTUAL TABLE t9 USING rtree(id, xmin, xmax);
- INSERT INTO t9 VALUES(1,0,0);
- INSERT INTO t9 VALUES(2,0,0);
- SELECT * FROM t9 WHERE id IN (1, 2);
-} {1 0.0 0.0 2 0.0 0.0}
-
-do_execsql_test 13.2 {
- WITH r(x) AS (
- SELECT 1 UNION ALL
- SELECT 2 UNION ALL
- SELECT 3
- )
- SELECT * FROM r CROSS JOIN t9 WHERE id=x;
-} {1 1 0.0 0.0 2 2 0.0 0.0}
-
-#-------------------------------------------------------------------------
-# Test if a non-integer is inserted into the PK column of an r-tree
-# table, it is converted to an integer before being inserted. Also
-# that if a non-numeric is inserted into one of the min/max dimension
-# columns, it is converted to the required type before being inserted.
-#
-do_execsql_test 14.1 {
- CREATE VIRTUAL TABLE t10 USING rtree(ii, x1, x2);
-}
-
-do_execsql_test 14.2 {
- INSERT INTO t10 VALUES(NULL, 1, 2);
- INSERT INTO t10 VALUES(NULL, 2, 3);
- INSERT INTO t10 VALUES('4xxx', 3, 4);
- INSERT INTO t10 VALUES(5.0, 4, 5);
- INSERT INTO t10 VALUES(6.4, 5, 6);
-}
-do_execsql_test 14.3 {
- SELECT * FROM t10;
-} {
- 1 1.0 2.0 2 2.0 3.0 4 3.0 4.0 5 4.0 5.0 6 5.0 6.0
-}
-
-do_execsql_test 14.4 {
- DELETE FROM t10;
- INSERT INTO t10 VALUES(1, 'one', 'two');
- INSERT INTO t10 VALUES(2, '52xyz', '81...');
-}
-do_execsql_test 14.5 {
- SELECT * FROM t10;
-} {
- 1 0.0 0.0
- 2 52.0 81.0
-}
-
-do_execsql_test 14.4 {
- DROP TABLE t10;
- CREATE VIRTUAL TABLE t10 USING rtree_i32(ii, x1, x2);
- INSERT INTO t10 VALUES(1, 'one', 'two');
- INSERT INTO t10 VALUES(2, '52xyz', '81...');
- INSERT INTO t10 VALUES(3, 42.3, 49.9);
-}
-do_execsql_test 14.5 {
- SELECT * FROM t10;
-} {
- 1 0 0
- 2 52 81
- 3 42 49
-}
-
-#-------------------------------------------------------------------------
-#
-do_execsql_test 15.0 {
- CREATE VIRTUAL TABLE rt USING rtree(id, x1,x2, y1,y2);
- CREATE TEMP TABLE t13(a, b, c);
-}
-do_execsql_test 15.1 {
- BEGIN;
- INSERT INTO rt VALUES(1,2,3,4,5);
-}
-do_execsql_test 15.2 {
- DROP TABLE t13;
- COMMIT;
-}
-
-# Test cases for the new auxiliary columns feature
-#
-do_catchsql_test 16.100 {
- CREATE VIRTUAL TABLE t16 USING rtree(id,x0,x1,y0,+aux1,x1);
-} {1 {Auxiliary rtree columns must be last}}
-do_test 16.110 {
- set sql {
- CREATE VIRTUAL TABLE t16 USING rtree(
- id, x00, x01, x10, x11, x20, x21, x30, x31, x40, x41
- }
- for {set i 12} {$i<=100} {incr i} {
- append sql ", +a$i"
- }
- append sql ");"
- execsql $sql
-} {}
-do_test 16.120 {
- set sql {
- CREATE VIRTUAL TABLE t16b USING rtree(
- id, x00, x01, x10, x11, x20, x21, x30, x31, x40, x41
- }
- for {set i 12} {$i<=101} {incr i} {
- append sql ", +a$i"
- }
- append sql ");"
- catchsql $sql
-} {1 {Too many columns for an rtree table}}
-
-do_execsql_test 16.130 {
- DROP TABLE IF EXISTS rt1;
- CREATE VIRTUAL TABLE rt1 USING rtree(id, x1, x2, +aux);
- INSERT INTO rt1 VALUES(1, 1, 2, 'aux1');
- INSERT INTO rt1 VALUES(2, 2, 3, 'aux2');
- INSERT INTO rt1 VALUES(3, 3, 4, 'aux3');
- INSERT INTO rt1 VALUES(4, 4, 5, 'aux4');
- SELECT * FROM rt1 WHERE id IN (1, 2, 3, 4);
-} {1 1.0 2.0 aux1 2 2.0 3.0 aux2 3 3.0 4.0 aux3 4 4.0 5.0 aux4}
-
-expand_all_sql db
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree2.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree2.test
deleted file mode 100644
index 853737b9c7d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree2.test
+++ /dev/null
@@ -1,146 +0,0 @@
-# 2008 Feb 19
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the r-tree extension.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-
-ifcapable !rtree {
- finish_test
- return
-}
-
-set ::NROW 1000
-set ::NDEL 10
-set ::NSELECT 100
-
-if {[info exists G(isquick)] && $G(isquick)} {
- set ::NROW 100
- set ::NSELECT 10
-}
-
-foreach module {rtree_i32 rtree} {
- for {set nDim 1} {$nDim <= 5} {incr nDim} {
-
- do_test rtree2-$module.$nDim.1 {
- set cols [list]
- foreach c [list c0 c1 c2 c3 c4 c5 c6 c7 c8 c9] {
- lappend cols "$c REAL"
- }
- set cols [join [lrange $cols 0 [expr {$nDim*2-1}]] ", "]
- execsql "
- CREATE VIRTUAL TABLE t1 USING ${module}(ii, $cols);
- CREATE TABLE t2 (ii, $cols);
- "
- } {}
-
- do_test rtree2-$module.$nDim.2 {
- db transaction {
- for {set ii 0} {$ii < $::NROW} {incr ii} {
- #puts "Row $ii"
- set values [list]
- for {set jj 0} {$jj<$nDim*2} {incr jj} {
- lappend values [expr int(rand()*1000)]
- }
- set values [join $values ,]
- #puts [rtree_treedump db t1]
- #puts "INSERT INTO t2 VALUES($ii, $values)"
- set rc [catch {db eval "INSERT INTO t1 VALUES($ii, $values)"}]
- if {$rc} {
- incr ii -1
- } else {
- db eval "INSERT INTO t2 VALUES($ii, $values)"
- }
- #if {[rtree_check db t1]} {
- #puts [rtree_treedump db t1]
- #exit
- #}
- }
- }
-
- set t1 [execsql {SELECT * FROM t1 ORDER BY ii}]
- set t2 [execsql {SELECT * FROM t2 ORDER BY ii}]
- set rc [expr {$t1 eq $t2}]
- if {$rc != 1} {
- puts $t1
- puts $t2
- }
- set rc
- } {1}
-
- do_rtree_integrity_test rtree2-$module.$nDim.3 t1
-
- set OPS [list < > <= >= =]
- for {set ii 0} {$ii < $::NSELECT} {incr ii} {
- do_test rtree2-$module.$nDim.4.$ii.1 {
- set where [list]
- foreach look_three_dots! {. . .} {
- set colidx [expr int(rand()*($nDim*2+1))-1]
- if {$colidx<0} {
- set col ii
- } else {
- set col "c$colidx"
- }
- set op [lindex $OPS [expr int(rand()*[llength $OPS])]]
- set val [expr int(rand()*1000)]
- lappend where "$col $op $val"
- }
- set where [join $where " AND "]
-
- set t1 [execsql "SELECT * FROM t1 WHERE $where ORDER BY ii"]
- set t2 [execsql "SELECT * FROM t2 WHERE $where ORDER BY ii"]
- set rc [expr {$t1 eq $t2}]
- if {$rc != 1} {
- #puts $where
- puts $t1
- puts $t2
- #puts [rtree_treedump db t1]
- #breakpoint
- #set t1 [execsql "SELECT * FROM t1 WHERE $where ORDER BY ii"]
- #exit
- }
- set rc
- } {1}
- }
-
- for {set ii 0} {$ii < $::NROW} {incr ii $::NDEL} {
- #puts [rtree_treedump db t1]
- do_test rtree2-$module.$nDim.5.$ii.1 {
- execsql "DELETE FROM t2 WHERE ii <= $::ii"
- execsql "DELETE FROM t1 WHERE ii <= $::ii"
-
- set t1 [execsql {SELECT * FROM t1 ORDER BY ii}]
- set t2 [execsql {SELECT * FROM t2 ORDER BY ii}]
- set rc [expr {$t1 eq $t2}]
- if {$rc != 1} {
- puts $t1
- puts $t2
- }
- set rc
- } {1}
- do_rtree_integrity_test rtree2-$module.$nDim.5.$ii.2 t1
- }
-
- do_test rtree2-$module.$nDim.6 {
- execsql {
- DROP TABLE t1;
- DROP TABLE t2;
- }
- } {}
- }
-}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree3.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree3.test
deleted file mode 100644
index e37d18ee847..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree3.test
+++ /dev/null
@@ -1,266 +0,0 @@
-# 2008 Feb 19
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing that the r-tree correctly handles
-# out-of-memory conditions.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-source $testdir/malloc_common.tcl
-ifcapable !rtree {
- finish_test
- return
-}
-
-# Test summary:
-#
-# rtree3-1: Test OOM in simple CREATE TABLE, INSERT, DELETE and SELECT
-# commands on an almost empty table.
-#
-# rtree3-2: Test OOM in a DROP TABLE command.
-#
-# rtree3-3a: Test OOM during a transaction to insert 100 pseudo-random rows.
-#
-# rtree3-3b: Test OOM during a transaction deleting all entries in the
-# database constructed in [rtree3-3a] in pseudo-random order.
-#
-# rtree3-4a: OOM during "SELECT count(*) FROM ..." on a big table.
-#
-# rtree3-4b: OOM while deleting rows from a big table.
-#
-# rtree3-5: Test OOM while inserting rows into a big table.
-#
-# rtree3-6: Test OOM while deleting all rows of a table, one at a time.
-#
-# rtree3-7: OOM during an ALTER TABLE RENAME TABLE command.
-#
-# rtree3-8: Test OOM while registering the r-tree module with sqlite.
-#
-# rtree3-11: OOM following a constraint failure
-#
-do_faultsim_test rtree3-1 -faults oom* -prep {
- faultsim_delete_and_reopen
-} -body {
- execsql {
- BEGIN TRANSACTION;
- CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
- INSERT INTO rt VALUES(NULL, 3, 5, 7, 9);
- INSERT INTO rt VALUES(NULL, 13, 15, 17, 19);
- DELETE FROM rt WHERE ii = 1;
- SELECT * FROM rt;
- SELECT ii FROM rt WHERE ii = 2;
- COMMIT;
- }
-}
-
-do_test rtree3-2.prep {
- faultsim_delete_and_reopen
- execsql {
- CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
- INSERT INTO rt VALUES(NULL, 3, 5, 7, 9);
- }
- faultsim_save_and_close
-} {}
-do_faultsim_test rtree3-2 -faults oom* -prep {
- faultsim_restore_and_reopen
-} -body {
- execsql { DROP TABLE rt }
-}
-
-do_malloc_test rtree3-3.prep {
- faultsim_delete_and_reopen
- execsql {
- CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2, +a1, +a2);
- INSERT INTO rt VALUES(NULL, 3, 5, 7, 9);
- }
- faultsim_save_and_close
-} {}
-
-do_faultsim_test rtree3-3a -faults oom* -prep {
- faultsim_restore_and_reopen
-} -body {
- db eval BEGIN
- for {set ii 0} {$ii < 100} {incr ii} {
- set f [expr rand()]
- db eval {INSERT INTO rt VALUES(NULL, $f*10.0, $f*10.0, $f*15.0, $f*15.0)}
- }
- db eval COMMIT
-}
-faultsim_save_and_close
-
-do_faultsim_test rtree3-3b -faults oom* -prep {
- faultsim_restore_and_reopen
-} -body {
- db eval BEGIN
- for {set ii 0} {$ii < 100} {incr ii} {
- set f [expr rand()]
- db eval { DELETE FROM rt WHERE x1<($f*10.0) AND x1>($f*10.5) }
- }
- db eval COMMIT
-}
-
-do_test rtree3-4.prep {
- faultsim_delete_and_reopen
- execsql {
- BEGIN;
- PRAGMA page_size = 512;
- CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
- }
- for {set i 0} {$i < 1500} {incr i} {
- execsql { INSERT INTO rt VALUES($i, $i, $i+1, $i, $i+1) }
- }
- execsql { COMMIT }
- faultsim_save_and_close
-} {}
-
-do_faultsim_test rtree3-4a -faults oom-* -prep {
- faultsim_restore_and_reopen
-} -body {
- db eval { SELECT count(*) FROM rt }
-} -test {
- faultsim_test_result {0 1500}
-}
-
-do_faultsim_test rtree3-4b -faults oom-transient -prep {
- faultsim_restore_and_reopen
-} -body {
- db eval { DELETE FROM rt WHERE ii BETWEEN 1 AND 100 }
-} -test {
- faultsim_test_result {0 {}}
-}
-
-do_test rtree3-5.prep {
- faultsim_delete_and_reopen
- execsql {
- BEGIN;
- PRAGMA page_size = 512;
- CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
- }
- for {set i 0} {$i < 100} {incr i} {
- execsql { INSERT INTO rt VALUES($i, $i, $i+1, $i, $i+1) }
- }
- execsql { COMMIT }
- faultsim_save_and_close
-} {}
-do_faultsim_test rtree3-5 -faults oom-* -prep {
- faultsim_restore_and_reopen
-} -body {
- for {set i 100} {$i < 110} {incr i} {
- execsql { INSERT INTO rt VALUES($i, $i, $i+1, $i, $i+1) }
- }
-} -test {
- faultsim_test_result {0 {}}
-}
-
-do_test rtree3-6.prep {
- faultsim_delete_and_reopen
- execsql {
- BEGIN;
- PRAGMA page_size = 512;
- CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
- }
- for {set i 0} {$i < 50} {incr i} {
- execsql { INSERT INTO rt VALUES($i, $i, $i+1, $i, $i+1) }
- }
- execsql { COMMIT }
- faultsim_save_and_close
-} {}
-do_faultsim_test rtree3-6 -faults oom-* -prep {
- faultsim_restore_and_reopen
-} -body {
- execsql BEGIN
- for {set i 0} {$i < 50} {incr i} {
- execsql { DELETE FROM rt WHERE ii=$i }
- }
- execsql COMMIT
-} -test {
- faultsim_test_result {0 {}}
-}
-
-do_test rtree3-7.prep {
- faultsim_delete_and_reopen
- execsql { CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2) }
- faultsim_save_and_close
-} {}
-do_faultsim_test rtree3-7 -faults oom-* -prep {
- faultsim_restore_and_reopen
-} -body {
- execsql { ALTER TABLE rt RENAME TO rt2 }
-} -test {
- faultsim_test_result {0 {}}
-}
-
-do_faultsim_test rtree3-8 -faults oom-* -prep {
- catch { db close }
-} -body {
- sqlite3 db test.db
-}
-
-do_faultsim_test rtree3-9 -faults oom-* -prep {
- sqlite3 db :memory:
-} -body {
- set rc [register_cube_geom db]
- if {$rc != "SQLITE_OK"} { error $rc }
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
-}
-
-do_test rtree3-10.prep {
- faultsim_delete_and_reopen
- execsql {
- CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2, z1, z2);
- INSERT INTO rt VALUES(1, 10, 10, 10, 11, 11, 11);
- INSERT INTO rt VALUES(2, 5, 6, 6, 7, 7, 8);
- }
- faultsim_save_and_close
-} {}
-do_faultsim_test rtree3-10 -faults oom-* -prep {
- faultsim_restore_and_reopen
- register_cube_geom db
- execsql { SELECT * FROM rt }
-} -body {
- execsql { SELECT ii FROM rt WHERE ii MATCH cube(4.5, 5.5, 6.5, 1, 1, 1) }
-} -test {
- faultsim_test_result {0 2}
-}
-
-
-do_test rtree3-11.prep {
- faultsim_delete_and_reopen
- execsql {
- CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
- INSERT INTO rt VALUES(1, 2, 3, 4, 5);
- }
- faultsim_save_and_close
-} {}
-do_faultsim_test rtree3-10.1 -faults oom-* -prep {
- faultsim_restore_and_reopen
- execsql { SELECT * FROM rt }
-} -body {
- execsql { INSERT INTO rt VALUES(1, 2, 3, 4, 5) }
-} -test {
- faultsim_test_result {1 {UNIQUE constraint failed: rt.ii}} \
- {1 {constraint failed}}
-}
-do_faultsim_test rtree3-10.2 -faults oom-* -prep {
- faultsim_restore_and_reopen
- execsql { SELECT * FROM rt }
-} -body {
- execsql { INSERT INTO rt VALUES(2, 2, 3, 5, 4) }
-} -test {
- faultsim_test_result {1 {rtree constraint failed: rt.(y1<=y2)}} \
- {1 {constraint failed}}
-}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree4.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree4.test
deleted file mode 100644
index a73921d8d57..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree4.test
+++ /dev/null
@@ -1,254 +0,0 @@
-# 2008 May 23
-#
-# 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.
-#
-#***********************************************************************
-#
-# Randomized test cases for the rtree extension.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-
-ifcapable !rtree {
- finish_test
- return
-}
-
-set ::NROW 2500
-if {[info exists G(isquick)] && $G(isquick)} {
- set ::NROW 250
-}
-
-ifcapable !rtree_int_only {
- # Return a floating point number between -X and X.
- #
- proc rand {X} {
- return [expr {int((rand()-0.5)*1024.0*$X)/512.0}]
- }
-
- # Return a positive floating point number less than or equal to X
- #
- proc randincr {X} {
- while 1 {
- set r [expr {int(rand()*$X*32.0)/32.0}]
- if {$r>0.0} {return $r}
- }
- }
-} else {
- # For rtree_int_only, return an number between -X and X.
- #
- proc rand {X} {
- return [expr {int((rand()-0.5)*2*$X)}]
- }
-
- # Return a positive integer less than or equal to X
- #
- proc randincr {X} {
- while 1 {
- set r [expr {int(rand()*$X)+1}]
- if {$r>0} {return $r}
- }
- }
-}
-
-# Scramble the $inlist into a random order.
-#
-proc scramble {inlist} {
- set y {}
- foreach x $inlist {
- lappend y [list [expr {rand()}] $x]
- }
- set y [lsort $y]
- set outlist {}
- foreach x $y {
- lappend outlist [lindex $x 1]
- }
- return $outlist
-}
-
-# Always use the same random seed so that the sequence of tests
-# is repeatable.
-#
-expr {srand(1234)}
-
-# Run these tests for all number of dimensions between 1 and 5.
-#
-for {set nDim 1} {$nDim<=5} {incr nDim} {
-
- # Construct an rtree virtual table and an ordinary btree table
- # to mirror it. The ordinary table should be much slower (since
- # it has to do a full table scan) but should give the exact same
- # answers.
- #
- do_test rtree4-$nDim.1 {
- set clist {}
- set cklist {}
- for {set i 0} {$i<$nDim} {incr i} {
- lappend clist mn$i mx$i
- lappend cklist "mn$i<mx$i"
- }
- db eval "DROP TABLE IF EXISTS rx"
- db eval "DROP TABLE IF EXISTS bx"
- db eval "CREATE VIRTUAL TABLE rx USING rtree(id, [join $clist ,])"
- db eval "CREATE TABLE bx(id INTEGER PRIMARY KEY,\
- [join $clist ,], CHECK( [join $cklist { AND }] ))"
- } {}
-
- # Do many insertions of small objects. Do both overlapping and
- # contained-within queries after each insert to verify that all
- # is well.
- #
- unset -nocomplain where
- for {set i 1} {$i<$::NROW} {incr i} {
- # Do a random insert
- #
- do_test rtree4-$nDim.2.$i.1 {
- set vlist {}
- for {set j 0} {$j<$nDim} {incr j} {
- set mn [rand 10000]
- set mx [expr {$mn+[randincr 50]}]
- lappend vlist $mn $mx
- }
- db eval "INSERT INTO rx VALUES(NULL, [join $vlist ,])"
- db eval "INSERT INTO bx VALUES(NULL, [join $vlist ,])"
- } {}
-
- # Do a contained-in query on all dimensions
- #
- set where {}
- for {set j 0} {$j<$nDim} {incr j} {
- set mn [rand 10000]
- set mx [expr {$mn+[randincr 500]}]
- lappend where mn$j>=$mn mx$j<=$mx
- }
- set where "WHERE [join $where { AND }]"
- do_test rtree4-$nDim.2.$i.2 {
- list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
- } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
-
- # Do an overlaps query on all dimensions
- #
- set where {}
- for {set j 0} {$j<$nDim} {incr j} {
- set mn [rand 10000]
- set mx [expr {$mn+[randincr 500]}]
- lappend where mx$j>=$mn mn$j<=$mx
- }
- set where "WHERE [join $where { AND }]"
- do_test rtree4-$nDim.2.$i.3 {
- list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
- } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
-
- # Do a contained-in query with surplus contraints at the beginning.
- # This should force a full-table scan on the rtree.
- #
- set where {}
- for {set j 0} {$j<$nDim} {incr j} {
- lappend where mn$j>-10000 mx$j<10000
- }
- for {set j 0} {$j<$nDim} {incr j} {
- set mn [rand 10000]
- set mx [expr {$mn+[randincr 500]}]
- lappend where mn$j>=$mn mx$j<=$mx
- }
- set where "WHERE [join $where { AND }]"
- do_test rtree4-$nDim.2.$i.3 {
- list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
- } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
-
- # Do an overlaps query with surplus contraints at the beginning.
- # This should force a full-table scan on the rtree.
- #
- set where {}
- for {set j 0} {$j<$nDim} {incr j} {
- lappend where mn$j>=-10000 mx$j<=10000
- }
- for {set j 0} {$j<$nDim} {incr j} {
- set mn [rand 10000]
- set mx [expr {$mn+[randincr 500]}]
- lappend where mx$j>$mn mn$j<$mx
- }
- set where "WHERE [join $where { AND }]"
- do_test rtree4-$nDim.2.$i.4 {
- list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
- } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
-
- # Do a contained-in query with surplus contraints at the end
- #
- set where {}
- for {set j 0} {$j<$nDim} {incr j} {
- set mn [rand 10000]
- set mx [expr {$mn+[randincr 500]}]
- lappend where mn$j>=$mn mx$j<$mx
- }
- for {set j [expr {$nDim-1}]} {$j>=0} {incr j -1} {
- lappend where mn$j>=-10000 mx$j<10000
- }
- set where "WHERE [join $where { AND }]"
- do_test rtree4-$nDim.2.$i.5 {
- list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
- } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
-
- # Do an overlaps query with surplus contraints at the end
- #
- set where {}
- for {set j [expr {$nDim-1}]} {$j>=0} {incr j -1} {
- set mn [rand 10000]
- set mx [expr {$mn+[randincr 500]}]
- lappend where mx$j>$mn mn$j<=$mx
- }
- for {set j 0} {$j<$nDim} {incr j} {
- lappend where mx$j>-10000 mn$j<=10000
- }
- set where "WHERE [join $where { AND }]"
- do_test rtree4-$nDim.2.$i.6 {
- list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
- } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
-
- # Do a contained-in query with surplus contraints where the
- # constraints appear in a random order.
- #
- set where {}
- for {set j 0} {$j<$nDim} {incr j} {
- set mn1 [rand 10000]
- set mn2 [expr {$mn1+[randincr 100]}]
- set mx1 [expr {$mn2+[randincr 400]}]
- set mx2 [expr {$mx1+[randincr 100]}]
- lappend where mn$j>=$mn1 mn$j>$mn2 mx$j<$mx1 mx$j<=$mx2
- }
- set where "WHERE [join [scramble $where] { AND }]"
- do_test rtree4-$nDim.2.$i.7 {
- list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
- } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
-
- # Do an overlaps query with surplus contraints where the
- # constraints appear in a random order.
- #
- set where {}
- for {set j 0} {$j<$nDim} {incr j} {
- set mn1 [rand 10000]
- set mn2 [expr {$mn1+[randincr 100]}]
- set mx1 [expr {$mn2+[randincr 400]}]
- set mx2 [expr {$mx1+[randincr 100]}]
- lappend where mx$j>=$mn1 mx$j>$mn2 mn$j<$mx1 mn$j<=$mx2
- }
- set where "WHERE [join [scramble $where] { AND }]"
- do_test rtree4-$nDim.2.$i.8 {
- list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
- } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
- }
-
- do_rtree_integrity_test rtree4-$nDim.3 rx
-}
-
-expand_all_sql db
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree5.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree5.test
deleted file mode 100644
index 92bb6905c7e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree5.test
+++ /dev/null
@@ -1,83 +0,0 @@
-# 2008 Jul 14
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the r-tree extension when it is
-# configured to store values as 32 bit integers.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-
-ifcapable !rtree {
- finish_test
- return
-}
-
-do_test rtree5-1.0 {
- execsql { CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2, y1, y2) }
-} {}
-do_test rtree5-1.1 {
- execsql { INSERT INTO t1 VALUES(1, 5, 10, 4, 11.2) }
-} {}
-do_test rtree5-1.2 {
- execsql { SELECT * FROM t1 }
-} {1 5 10 4 11}
-do_test rtree5-1.3 {
- execsql { SELECT typeof(x1) FROM t1 }
-} {integer}
-
-do_test rtree5-1.4 {
- execsql { SELECT x1==5 FROM t1 }
-} {1}
-do_test rtree5-1.5 {
- execsql { SELECT x1==5.2 FROM t1 }
-} {0}
-do_test rtree5-1.6 {
- execsql { SELECT x1==5.0 FROM t1 }
-} {1}
-
-do_test rtree5-1.7 {
- execsql { SELECT count(*) FROM t1 WHERE x1==5 }
-} {1}
-ifcapable !rtree_int_only {
- do_test rtree5-1.8 {
- execsql { SELECT count(*) FROM t1 WHERE x1==5.2 }
- } {0}
-}
-do_test rtree5-1.9 {
- execsql { SELECT count(*) FROM t1 WHERE x1==5.0 }
-} {1}
-
-do_test rtree5-1.10 {
- execsql { SELECT (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5 }
-} {2147483643 2147483647 -2147483648 -2147483643}
-do_test rtree5-1.11 {
- execsql {
- INSERT INTO t1 VALUES(2, (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5)
- }
-} {}
-do_test rtree5-1.12 {
- execsql { SELECT * FROM t1 WHERE id=2 }
-} {2 2147483643 2147483647 -2147483648 -2147483643}
-do_test rtree5-1.13 {
- execsql {
- SELECT * FROM t1 WHERE
- x1=2147483643 AND x2=2147483647 AND
- y1=-2147483648 AND y2=-2147483643
- }
-} {2 2147483643 2147483647 -2147483648 -2147483643}
-do_rtree_integrity_test rtree5-1.14 t1
-
-expand_all_sql db
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree6.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree6.test
deleted file mode 100644
index 6800b4bb102..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree6.test
+++ /dev/null
@@ -1,168 +0,0 @@
-# 2008 Sep 1
-#
-# 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.
-#
-#***********************************************************************
-#
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-
-ifcapable {!rtree || rtree_int_only} {
- finish_test
- return
-}
-
-# Operator Byte Value
-# ----------------------
-# = 0x41 ('A')
-# <= 0x42 ('B')
-# < 0x43 ('C')
-# >= 0x44 ('D')
-# > 0x45 ('E')
-# ----------------------
-
-proc rtree_strategy {sql} {
- set ret [list]
- db eval "explain $sql" a {
- if {$a(opcode) eq "VFilter"} {
- lappend ret $a(p4)
- }
- }
- set ret
-}
-
-proc query_plan {sql} {
- set ret [list]
- db eval "explain query plan $sql" a {
- lappend ret $a(detail)
- }
- set ret
-}
-
-do_test rtree6-1.1 {
- execsql {
- CREATE TABLE t2(k INTEGER PRIMARY KEY, v);
- CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2);
- }
-} {}
-
-do_test rtree6-1.2 {
- rtree_strategy {SELECT * FROM t1 WHERE x1>10}
-} {E0}
-
-do_test rtree6-1.3 {
- rtree_strategy {SELECT * FROM t1 WHERE x1<10}
-} {C0}
-
-do_test rtree6-1.4 {
- rtree_strategy {SELECT * FROM t1,t2 WHERE k=ii AND x1<10}
-} {C0}
-
-do_test rtree6-1.5 {
- rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10}
-} {C0}
-
-do_eqp_test rtree6.2.1 {
- SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
-} {
- QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
-}
-
-do_eqp_test rtree6.2.2 {
- SELECT * FROM t1,t2 WHERE k=ii AND x1<10
-} {
- QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
-}
-
-do_eqp_test rtree6.2.3 {
- SELECT * FROM t1,t2 WHERE k=ii
-} {
- QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
-}
-
-do_eqp_test rtree6.2.4.1 {
- SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10
-} {
- QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
- `--SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)
-}
-do_eqp_test rtree6.2.4.2 {
- SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
-} {
- QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
- `--SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
-}
-
-do_eqp_test rtree6.2.5 {
- SELECT * FROM t1,t2 WHERE k=ii AND x1<v
-} {
- QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
-}
-
-do_execsql_test rtree6-3.1 {
- CREATE VIRTUAL TABLE t3 USING rtree(id, x1, x2, y1, y2);
- INSERT INTO t3 VALUES(NULL, 1, 1, 2, 2);
- SELECT * FROM t3 WHERE
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5;
-} {1 1.0 1.0 2.0 2.0}
-
-do_test rtree6.3.2 {
- rtree_strategy {
- SELECT * FROM t3 WHERE
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
- }
-} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0}
-do_test rtree6.3.3 {
- rtree_strategy {
- SELECT * FROM t3 WHERE
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
- }
-} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0}
-
-do_execsql_test rtree6-3.4 {
- SELECT * FROM t3 WHERE x1>0.5 AND x1>0.8 AND x1>1.1
-} {}
-do_execsql_test rtree6-3.5 {
- SELECT * FROM t3 WHERE
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
- x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>1.1
-} {}
-
-expand_all_sql db
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree7.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree7.test
deleted file mode 100644
index 1556179c4f5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree7.test
+++ /dev/null
@@ -1,73 +0,0 @@
-# 2010 February 16
-#
-# 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.
-#
-#***********************************************************************
-#
-# Test that nothing goes wrong if an rtree table is created, then the
-# database page-size is modified. At one point (3.6.22), this was causing
-# malfunctions.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-
-ifcapable !rtree||!vacuum {
- finish_test
- return
-}
-
-# Like execsql except display output as integer where that can be
-# done without loss of information.
-#
-proc execsql_intout {sql} {
- set out {}
- foreach term [execsql $sql] {
- regsub {\.0$} $term {} term
- lappend out $term
- }
- return $out
-}
-
-do_test rtree7-1.1 {
- execsql {
- PRAGMA page_size = 1024;
- CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2);
- INSERT INTO rt VALUES(1, 1, 2, 3, 4);
- }
-} {}
-do_test rtree7-1.2 {
- execsql_intout { SELECT * FROM rt }
-} {1 1 2 3 4}
-do_test rtree7-1.3 {
- execsql_intout {
- PRAGMA page_size = 2048;
- VACUUM;
- SELECT * FROM rt;
- }
-} {1 1 2 3 4}
-do_test rtree7-1.4 {
- for {set i 2} {$i <= 51} {incr i} {
- execsql { INSERT INTO rt VALUES($i, 1, 2, 3, 4) }
- }
- execsql_intout { SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt }
-} {51 102 153 204}
-do_test rtree7-1.5 {
- execsql_intout {
- PRAGMA page_size = 512;
- VACUUM;
- SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt
- }
-} {51 102 153 204}
-
-do_rtree_integrity_test rtree7-1.6 rt
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree8.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree8.test
deleted file mode 100644
index 68b68c45fdc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree8.test
+++ /dev/null
@@ -1,207 +0,0 @@
-# 2010 February 16
-#
-# 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.
-#
-#***********************************************************************
-#
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-
-#-------------------------------------------------------------------------
-# The following block of tests - rtree8-1.* - feature reading and writing
-# an r-tree table while there exist open cursors on it.
-#
-proc populate_t1 {n} {
- execsql { DELETE FROM t1 }
- for {set i 1} {$i <= $n} {incr i} {
- execsql { INSERT INTO t1 VALUES($i, $i, $i+2) }
- }
-}
-
-# A DELETE while a cursor is reading the table.
-#
-do_test rtree8-1.1.1 {
- execsql { PRAGMA page_size = 512 }
- execsql { CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2) }
- populate_t1 5
-} {}
-do_test rtree8-1.1.2 {
- set res [list]
- set rc [catch {
- db eval { SELECT * FROM t1 } {
- lappend res $x1 $x2
- if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
- }
- } msg];
- lappend rc $msg
- set rc
-} {1 {database table is locked}}
-do_test rtree8-1.1.2b {
- db eval { SELECT * FROM t1 ORDER BY +id } {
- if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
- }
- db eval {SELECT x1, x2 FROM t1}
-} {1 3 2 4 3 5}
-do_test rtree8-1.1.3 {
- execsql { SELECT * FROM t1 }
-} {1 1 3 2 2 4 3 3 5}
-
-# Many SELECTs on the same small table.
-#
-proc nested_select {n} {
- set ::max $n
- db eval { SELECT * FROM t1 } {
- if {$id == $n} { nested_select [expr $n+1] }
- }
- return $::max
-}
-do_test rtree8-1.2.1 { populate_t1 50 } {}
-do_test rtree8-1.2.2 { nested_select 1 } {51}
-
-# This test runs many SELECT queries simultaneously against a large
-# table, causing a collision in the hash-table used to store r-tree
-# nodes internally.
-#
-populate_t1 1500
-do_rtree_integrity_test rtree8-1.3.0 t1
-do_execsql_test rtree8-1.3.1 { SELECT max(nodeno) FROM t1_node } {164}
-do_test rtree8-1.3.2 {
- set rowids [execsql {SELECT min(rowid) FROM t1_rowid GROUP BY nodeno}]
- set stmt_list [list]
- foreach row $rowids {
- set stmt [sqlite3_prepare db "SELECT * FROM t1 WHERE id = $row" -1 tail]
- sqlite3_step $stmt
- lappend res_list [sqlite3_column_int $stmt 0]
- lappend stmt_list $stmt
- }
-} {}
-do_test rtree8-1.3.3 { set res_list } $rowids
-do_execsql_test rtree8-1.3.4 { SELECT count(*) FROM t1 } {1500}
-do_test rtree8-1.3.5 {
- foreach stmt $stmt_list { sqlite3_finalize $stmt }
-} {}
-
-
-#-------------------------------------------------------------------------
-# The following block of tests - rtree8-2.* - test a couple of database
-# corruption cases. In this case things are not corrupted at the b-tree
-# level, but the contents of the various tables used internally by an
-# r-tree table are inconsistent.
-#
-populate_t1 50
-do_execsql_test rtree8-2.1.1 { SELECT max(nodeno) FROM t1_node } {5}
-do_execsql_test rtree8-2.1.2 { DELETE FROM t1_node } {}
-for {set i 1} {$i <= 50} {incr i} {
- do_catchsql_test rtree8-2.1.3.$i {
- SELECT * FROM t1 WHERE id = $i
- } {1 {database disk image is malformed}}
-}
-do_catchsql_test rtree8-2.1.4 {
- SELECT * FROM t1
-} {1 {database disk image is malformed}}
-do_catchsql_test rtree8-2.1.5 {
- DELETE FROM t1
-} {1 {database disk image is malformed}}
-
-do_execsql_test rtree8-2.1.6 {
- DROP TABLE t1;
- CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2);
-} {}
-
-
-populate_t1 50
-do_execsql_test rtree8-2.2.1 {
- DELETE FROM t1_parent
-} {}
-do_catchsql_test rtree8-2.2.2 {
- DELETE FROM t1 WHERE id=25
-} {1 {database disk image is malformed}}
-do_execsql_test rtree8-2.2.3 {
- DROP TABLE t1;
- CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2);
-} {}
-
-
-#-------------------------------------------------------------------------
-# Test that trying to use the MATCH operator with the r-tree module does
-# not confuse it.
-#
-populate_t1 10
-do_catchsql_test rtree8-3.1 {
- SELECT * FROM t1 WHERE x1 MATCH '1234'
-} {1 {SQL logic error}}
-
-#-------------------------------------------------------------------------
-# Test a couple of invalid arguments to rtreedepth().
-#
-do_catchsql_test rtree8-4.1 {
- SELECT rtreedepth('hello world')
-} {1 {Invalid argument to rtreedepth()}}
-do_catchsql_test rtree8-4.2 {
- SELECT rtreedepth(X'00')
-} {1 {Invalid argument to rtreedepth()}}
-
-
-#-------------------------------------------------------------------------
-# Delete half of a lopsided tree.
-#
-do_execsql_test rtree8-5.1 {
- CREATE VIRTUAL TABLE t2 USING rtree_i32(id, x1, x2)
-} {}
-do_test rtree8-5.2 {
- execsql BEGIN
- for {set i 0} {$i < 100} {incr i} {
- execsql { INSERT INTO t2 VALUES($i, 100, 101) }
- }
- for {set i 100} {$i < 200} {incr i} {
- execsql { INSERT INTO t2 VALUES($i, 1000, 1001) }
- }
- execsql COMMIT
-} {}
-do_rtree_integrity_test rtree8-5.3 t2
-do_test rtree8-5.4 {
- execsql BEGIN
- for {set i 0} {$i < 200} {incr i} {
- execsql { DELETE FROM t2 WHERE id = $i }
- }
- execsql COMMIT
-} {}
-do_rtree_integrity_test rtree8-5.5 t2
-
-# 2018-05-24
-# The following script caused an assertion fault and/or segfault
-# prior to the fix that prevents simultaneous reads and writes on
-# the same rtree virtual table.
-#
-do_test rtree8-6.1 {
- db close
- sqlite3 db :memory:
- db eval {
- PRAGMA page_size=512;
- CREATE VIRTUAL TABLE t1 USING rtree(id,x1,x2,y1,y2);
- WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<49)
- INSERT INTO t1 SELECT x, x, x+1, x, x+1 FROM c;
- }
- set rc [catch {
- db eval {SELECT id FROM t1} x {
- db eval {DELETE FROM t1 WHERE id=$x(id)}
- }
- } msg]
- lappend rc $msg
-} {1 {database table is locked}}
-
-
-
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree9.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree9.test
deleted file mode 100644
index a7cd344d765..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree9.test
+++ /dev/null
@@ -1,129 +0,0 @@
-# 2010 August 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 contains tests for the r-tree module. Specifically, it tests
-# that custom r-tree queries (geometry callbacks) work.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-ifcapable rtree_int_only { finish_test; return }
-
-register_cube_geom db
-
-do_execsql_test rtree9-1.1 {
- CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2, z1, z2);
- INSERT INTO rt VALUES(1, 1, 2, 1, 2, 1, 2);
-} {}
-do_execsql_test rtree9-1.2 {
- SELECT * FROM rt WHERE id MATCH cube(0, 0, 0, 2, 2, 2);
-} {1 1.0 2.0 1.0 2.0 1.0 2.0}
-do_execsql_test rtree9-1.3 {
- SELECT * FROM rt WHERE id MATCH cube(3, 3, 3, 2, 2, 2);
-} {}
-do_execsql_test rtree9-1.4 {
- DELETE FROM rt;
-} {}
-
-
-for {set i 0} {$i < 1000} {incr i} {
- set x [expr $i%10]
- set y [expr ($i/10)%10]
- set z [expr ($i/100)%10]
- execsql { INSERT INTO rt VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) }
-}
-do_rtree_integrity_test rtree9-2.0 rt
-do_execsql_test rtree9-2.1 {
- SELECT id FROM rt WHERE id MATCH cube(2.5, 2.5, 2.5, 1, 1, 1) ORDER BY id;
-} {222 223 232 233 322 323 332 333}
-do_execsql_test rtree9-2.2 {
- SELECT id FROM rt WHERE id MATCH cube(5.5, 5.5, 5.5, 1, 1, 1) ORDER BY id;
-} {555 556 565 566 655 656 665 666}
-
-
-do_execsql_test rtree9-3.0 {
- CREATE VIRTUAL TABLE rt32 USING rtree_i32(id, x1, x2, y1, y2, z1, z2);
-} {}
-for {set i 0} {$i < 1000} {incr i} {
- set x [expr $i%10]
- set y [expr ($i/10)%10]
- set z [expr ($i/100)%10]
- execsql { INSERT INTO rt32 VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) }
-}
-do_rtree_integrity_test rtree9-3.1 rt32
-do_execsql_test rtree9-3.2 {
- SELECT id FROM rt32 WHERE id MATCH cube(3, 3, 3, 1, 1, 1) ORDER BY id;
-} {222 223 224 232 233 234 242 243 244 322 323 324 332 333 334 342 343 344 422 423 424 432 433 434 442 443 444}
-do_execsql_test rtree9-3.3 {
- SELECT id FROM rt32 WHERE id MATCH cube(5.5, 5.5, 5.5, 1, 1, 1) ORDER BY id;
-} {555 556 565 566 655 656 665 666}
-
-
-do_catchsql_test rtree9-4.1 {
- SELECT id FROM rt32 WHERE id MATCH cube(5.5, 5.5, 1, 1, 1) ORDER BY id;
-} {1 {SQL logic error}}
-for {set x 2} {$x<200} {incr x 2} {
- do_catchsql_test rtree9-4.2.[expr $x/2] {
- SELECT id FROM rt WHERE id MATCH randomblob($x)
- } {1 {SQL logic error}}
-}
-do_catchsql_test rtree9-4.3 {
- SELECT id FROM rt WHERE id MATCH CAST(
- (cube(5.5, 5.5, 5.5, 1, 1, 1) || X'1234567812345678') AS blob
- )
-} {1 {SQL logic error}}
-
-
-#-------------------------------------------------------------------------
-# Test the example 2d "circle" geometry callback.
-#
-register_circle_geom db
-
-do_execsql_test rtree9-5.1 {
- CREATE VIRTUAL TABLE rt2 USING rtree(id, xmin, xmax, ymin, ymax);
-
- INSERT INTO rt2 VALUES(1, 1, 2, 1, 2);
- INSERT INTO rt2 VALUES(2, 1, 2, -2, -1);
- INSERT INTO rt2 VALUES(3, -2, -1, -2, -1);
- INSERT INTO rt2 VALUES(4, -2, -1, 1, 2);
-
- INSERT INTO rt2 VALUES(5, 2, 3, 2, 3);
- INSERT INTO rt2 VALUES(6, 2, 3, -3, -2);
- INSERT INTO rt2 VALUES(7, -3, -2, -3, -2);
- INSERT INTO rt2 VALUES(8, -3, -2, 2, 3);
-
- INSERT INTO rt2 VALUES(9, 1.8, 3, 1.8, 3);
- INSERT INTO rt2 VALUES(10, 1.8, 3, -3, -1.8);
- INSERT INTO rt2 VALUES(11, -3, -1.8, -3, -1.8);
- INSERT INTO rt2 VALUES(12, -3, -1.8, 1.8, 3);
-
- INSERT INTO rt2 VALUES(13, -15, 15, 1.8, 2.2);
- INSERT INTO rt2 VALUES(14, -15, 15, -2.2, -1.8);
- INSERT INTO rt2 VALUES(15, 1.8, 2.2, -15, 15);
- INSERT INTO rt2 VALUES(16, -2.2, -1.8, -15, 15);
-
- INSERT INTO rt2 VALUES(17, -100, 100, -100, 100);
-} {}
-
-do_execsql_test rtree9-5.2 {
- SELECT id FROM rt2 WHERE id MATCH circle(0.0, 0.0, 2.0);
-} {1 2 3 4 13 14 15 16 17}
-
-do_execsql_test rtree9-5.3 {
- UPDATE rt2 SET xmin=xmin+5, ymin=ymin+5, xmax=xmax+5, ymax=ymax+5;
- SELECT id FROM rt2 WHERE id MATCH circle(5.0, 5.0, 2.0);
-} {1 2 3 4 13 14 15 16 17}
-do_rtree_integrity_test rtree9-5.4 rt2
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeA.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeA.test
deleted file mode 100644
index 190d7d75320..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeA.test
+++ /dev/null
@@ -1,261 +0,0 @@
-# 2010 September 22
-#
-# 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 contains tests for the r-tree module. Specifically, it tests
-# that corrupt or inconsistent databases do not cause crashes in the r-tree
-# module.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-
-proc create_t1 {} {
- db close
- forcedelete test.db
- sqlite3 db test.db
- execsql {
- PRAGMA page_size = 1024;
- CREATE VIRTUAL TABLE t1 USING rtree(id, x1, x2, y1, y2);
- }
-}
-proc populate_t1 {} {
- execsql BEGIN
- for {set i 0} {$i < 500} {incr i} {
- set x2 [expr $i+5]
- set y2 [expr $i+5]
- execsql { INSERT INTO t1 VALUES($i, $i, $x2, $i, $y2) }
- }
- execsql COMMIT
-}
-
-proc truncate_node {nodeno nTrunc} {
- set blob [db one {SELECT data FROM t1_node WHERE nodeno=$nodeno}]
- if {$nTrunc<0} {set nTrunc "end-$nTrunc"}
- set blob [string range $blob 0 $nTrunc]
- db eval { UPDATE t1_node SET data = $blob WHERE nodeno=$nodeno }
-}
-
-proc set_tree_depth {tbl {newvalue ""}} {
- set blob [db one "SELECT data FROM ${tbl}_node WHERE nodeno=1"]
-
- if {$newvalue == ""} {
- binary scan $blob Su oldvalue
- return $oldvalue
- }
-
- set blob [binary format Sua* $newvalue [string range $blob 2 end]]
- db eval "UPDATE ${tbl}_node SET data = \$blob WHERE nodeno=1"
- return [set_tree_depth $tbl]
-}
-
-proc set_entry_count {tbl nodeno {newvalue ""}} {
- set blob [db one "SELECT data FROM ${tbl}_node WHERE nodeno=$nodeno"]
-
- if {$newvalue == ""} {
- binary scan [string range $blob 2 end] Su oldvalue
- return $oldvalue
- }
-
- set blob [binary format a*Sua* \
- [string range $blob 0 1] $newvalue [string range $blob 4 end]
- ]
- db eval "UPDATE ${tbl}_node SET data = \$blob WHERE nodeno=$nodeno"
- return [set_entry_count $tbl $nodeno]
-}
-
-
-proc do_corruption_tests {prefix args} {
- set testarray [lindex $args end]
- set errormsg {database disk image is malformed}
-
- foreach {z value} [lrange $args 0 end-1] {
- set n [string length $z]
- if {$n>=2 && [string equal -length $n $z "-error"]} {
- set errormsg $value
- }
- }
-
- foreach {tn sql} $testarray {
- do_catchsql_test $prefix.$tn $sql [list 1 $errormsg]
- }
-}
-
-#-------------------------------------------------------------------------
-# Test the libraries response if the %_node table is completely empty
-# (i.e. the root node is missing), or has been removed from the database
-# entirely.
-#
-create_t1
-populate_t1
-do_execsql_test rtreeA-1.0 {
- DELETE FROM t1_node;
-} {}
-
-do_corruption_tests rtreeA-1.1 {
- 1 "SELECT * FROM t1"
- 2 "SELECT * FROM t1 WHERE rowid=5"
- 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
- 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
-}
-
-do_execsql_test rtreeA-1.1.1 {
- SELECT rtreecheck('main', 't1')
-} {{Node 1 missing from database
-Wrong number of entries in %_rowid table - expected 0, actual 500
-Wrong number of entries in %_parent table - expected 0, actual 23}}
-
-do_execsql_test rtreeA-1.2.0 { DROP TABLE t1_node } {}
-do_corruption_tests rtreeA-1.2 -error "database disk image is malformed" {
- 1 "SELECT * FROM t1"
- 2 "SELECT * FROM t1 WHERE rowid=5"
- 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
- 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
-}
-
-#-------------------------------------------------------------------------
-# Test the libraries response if some of the entries in the %_node table
-# are the wrong size.
-#
-create_t1
-populate_t1
-do_test rtreeA-2.1.0 {
- set nodes [db eval {select nodeno FROM t1_node}]
- foreach {a b c} $nodes { truncate_node $c 200 }
-} {}
-do_corruption_tests rtreeA-2.1 {
- 1 "SELECT * FROM t1"
- 2 "SELECT * FROM t1 WHERE rowid=5"
- 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
- 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
-}
-
-create_t1
-populate_t1
-do_test rtreeA-2.2.0 { truncate_node 1 200 } {}
-do_corruption_tests rtreeA-2.2 {
- 1 "SELECT * FROM t1"
- 2 "SELECT * FROM t1 WHERE rowid=5"
- 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
- 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
-}
-
-#-------------------------------------------------------------------------
-# Set the "depth" of the tree stored on the root node incorrectly. Test
-# that this does not cause any problems.
-#
-create_t1
-populate_t1
-do_test rtreeA-3.1.0.1 { set_tree_depth t1 } {1}
-do_test rtreeA-3.1.0.2 { set_tree_depth t1 3 } {3}
-do_corruption_tests rtreeA-3.1 {
- 1 "SELECT * FROM t1"
- 2 "SELECT * FROM t1 WHERE rowid=5"
- 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
-}
-
-do_execsql_test rtreeA-3.1.0.3 {
- SELECT rtreecheck('main', 't1')!="ok"
-} {1}
-
-do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000}
-do_corruption_tests rtreeA-3.2 {
- 1 "SELECT * FROM t1"
- 2 "SELECT * FROM t1 WHERE rowid=5"
- 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
-}
-
-create_t1
-populate_t1
-do_test rtreeA-3.3.0 {
- execsql { DELETE FROM t1 WHERE rowid = 0 }
- set_tree_depth t1 65535
-} {65535}
-do_corruption_tests rtreeA-3.3 {
- 1 "SELECT * FROM t1"
- 2 "SELECT * FROM t1 WHERE rowid=5"
- 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
-}
-
-do_execsql_test rtreeA-3.3.3.4 {
- SELECT rtreecheck('main', 't1')
-} {{Rtree depth out of range (65535)
-Wrong number of entries in %_rowid table - expected 0, actual 499
-Wrong number of entries in %_parent table - expected 0, actual 23}}
-
-#-------------------------------------------------------------------------
-# Set the "number of entries" field on some nodes incorrectly.
-#
-create_t1
-populate_t1
-do_test rtreeA-4.1.0 {
- set_entry_count t1 1 4000
-} {4000}
-do_corruption_tests rtreeA-4.1 {
- 1 "SELECT * FROM t1"
- 2 "SELECT * FROM t1 WHERE rowid=5"
- 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
- 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
-}
-
-#-------------------------------------------------------------------------
-# Remove entries from the %_parent table and check that this does not
-# cause a crash.
-#
-create_t1
-populate_t1
-do_execsql_test rtreeA-5.1.0 { DELETE FROM t1_parent } {}
-do_corruption_tests rtreeA-5.1 {
- 1 "DELETE FROM t1 WHERE rowid = 5"
- 2 "DELETE FROM t1"
-}
-
-do_execsql_test rtreeA-5.2 {
- SELECT rtreecheck('main', 't1')!="ok"
-} {1}
-
-#-------------------------------------------------------------------------
-# Add some bad entries to the %_parent table.
-#
-create_t1
-populate_t1
-do_execsql_test rtreeA-6.1.0 {
- UPDATE t1_parent set parentnode = parentnode+1
-} {}
-do_corruption_tests rtreeA-6.1 {
- 1 "DELETE FROM t1 WHERE rowid = 5"
- 2 "UPDATE t1 SET x1=x1+1, x2=x2+1"
-}
-
-do_execsql_test rtreeA-6.2 {
- SELECT rtreecheck('main', 't1')!="ok"
-} {1}
-
-#-------------------------------------------------------------------------
-# Truncated blobs in the _node table.
-#
-create_t1
-populate_t1
-sqlite3 db test.db
-do_execsql_test rtreeA-7.100 {
- UPDATE t1_node SET data=x'' WHERE rowid=1;
-} {}
-do_catchsql_test rtreeA-7.110 {
- SELECT * FROM t1 WHERE x1>0 AND x1<100 AND x2>0 AND x2<100;
-} {1 {undersize RTree blobs in "t1_node"}}
-do_test rtreeA-7.120 {
- sqlite3_extended_errcode db
-} {SQLITE_CORRUPT_VTAB}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeB.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeB.test
deleted file mode 100644
index 6fc31042ca9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeB.test
+++ /dev/null
@@ -1,50 +0,0 @@
-# 2011 March 2
-#
-# 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.
-#
-#***********************************************************************
-# Make sure the rtreenode() testing function can handle entries with
-# 64-bit rowids.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-
-ifcapable rtree_int_only {
- do_test rtreeB-1.1-intonly {
- db eval {
- CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1);
- INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0);
- INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0);
- INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0);
- INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0);
- INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400);
- SELECT rtreenode(2, data) FROM t1_node;
- }
- } {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}}
-} else {
- do_test rtreeB-1.1 {
- db eval {
- CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1);
- INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0);
- INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0);
- INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0);
- INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0);
- INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400);
- SELECT rtreenode(2, data) FROM t1_node;
- }
- } {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}}
-}
-
-do_rtree_integrity_test rtreeB-1.2 t1
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeC.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeC.test
deleted file mode 100644
index 19a1f7fe6c2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeC.test
+++ /dev/null
@@ -1,378 +0,0 @@
-# 2011 March 2
-#
-# 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.
-#
-#***********************************************************************
-# Make sure the rtreenode() testing function can handle entries with
-# 64-bit rowids.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-set testprefix rtreeC
-
-do_execsql_test 1.0 {
- CREATE VIRTUAL TABLE r_tree USING rtree(id, min_x, max_x, min_y, max_y);
- CREATE TABLE t(x, y);
-}
-
-do_eqp_test 1.1 {
- SELECT * FROM r_tree, t
- WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
-} {
- QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
-}
-
-do_eqp_test 1.2 {
- SELECT * FROM t, r_tree
- WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
-} {
- QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
-}
-
-do_eqp_test 1.3 {
- SELECT * FROM t, r_tree
- WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
-} {
- QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
-}
-
-do_eqp_test 1.5 {
- SELECT * FROM t, r_tree
-} {
- QUERY PLAN
- |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t
-}
-
-do_execsql_test 2.0 {
- INSERT INTO t VALUES(0, 0);
- INSERT INTO t VALUES(0, 1);
- INSERT INTO t VALUES(0, 2);
- INSERT INTO t VALUES(0, 3);
- INSERT INTO t VALUES(0, 4);
- INSERT INTO t VALUES(0, 5);
- INSERT INTO t VALUES(0, 6);
- INSERT INTO t VALUES(0, 7);
- INSERT INTO t VALUES(0, 8);
- INSERT INTO t VALUES(0, 9);
-
- INSERT INTO t SELECT x+1, y FROM t;
- INSERT INTO t SELECT x+2, y FROM t;
- INSERT INTO t SELECT x+4, y FROM t;
- INSERT INTO r_tree SELECT NULL, x-1, x+1, y-1, y+1 FROM t;
- ANALYZE;
-}
-
-db close
-sqlite3 db test.db
-
-do_eqp_test 2.1 {
- SELECT * FROM r_tree, t
- WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
-} {
- QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
-}
-
-do_eqp_test 2.2 {
- SELECT * FROM t, r_tree
- WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
-} {
- QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
-}
-
-do_eqp_test 2.3 {
- SELECT * FROM t, r_tree
- WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
-} {
- QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
-}
-
-do_eqp_test 2.5 {
- SELECT * FROM t, r_tree
-} {
- QUERY PLAN
- |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t
-}
-
-#-------------------------------------------------------------------------
-# Test that the special CROSS JOIN handling works with rtree tables.
-#
-do_execsql_test 3.1 {
- CREATE TABLE t1(x);
- CREATE TABLE t2(y);
- CREATE VIRTUAL TABLE t3 USING rtree(z, x1,x2, y1,y2);
-}
-
-do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } {
- QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE t2
-}
-do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
- QUERY PLAN
- |--SCAN TABLE t2
- `--SCAN TABLE t1
-}
-
-do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } {
- QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
-}
-do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
- QUERY PLAN
- |--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t1
-}
-
-#--------------------------------------------------------------------
-# Test that LEFT JOINs are not reordered if the right-hand-side is
-# a virtual table.
-#
-reset_db
-do_execsql_test 4.1 {
- CREATE TABLE t1(a);
- CREATE VIRTUAL TABLE t2 USING rtree(b, x1,x2);
-
- INSERT INTO t1 VALUES(1);
- INSERT INTO t1 VALUES(2);
-
- INSERT INTO t2 VALUES(1, 0.0, 0.1);
- INSERT INTO t2 VALUES(3, 0.0, 0.1);
-}
-
-do_execsql_test 4.2 {
- SELECT a, b FROM t1 LEFT JOIN t2 ON (+a = +b);
-} {1 1 2 {}}
-
-do_execsql_test 4.3 {
- SELECT b, a FROM t2 LEFT JOIN t1 ON (+a = +b);
-} {1 1 3 {}}
-
-#--------------------------------------------------------------------
-# Test that the sqlite_stat1 data is used correctly.
-#
-reset_db
-do_execsql_test 5.1 {
- CREATE TABLE t1(x PRIMARY KEY, y);
- CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, +d1);
-
- INSERT INTO t1(x) VALUES(1);
- INSERT INTO t1(x) SELECT x+1 FROM t1; -- 2
- INSERT INTO t1(x) SELECT x+2 FROM t1; -- 4
- INSERT INTO t1(x) SELECT x+4 FROM t1; -- 8
- INSERT INTO t1(x) SELECT x+8 FROM t1; -- 16
- INSERT INTO t1(x) SELECT x+16 FROM t1; -- 32
- INSERT INTO t1(x) SELECT x+32 FROM t1; -- 64
- INSERT INTO t1(x) SELECT x+64 FROM t1; -- 128
- INSERT INTO t1(x) SELECT x+128 FROM t1; -- 256
- INSERT INTO t1(x) SELECT x+256 FROM t1; -- 512
- INSERT INTO t1(x) SELECT x+512 FROM t1; --1024
-
- INSERT INTO rt SELECT x, x, x+1, printf('x%04xy',x) FROM t1 WHERE x<=5;
-}
-do_rtree_integrity_test 5.1.1 rt
-
-# First test a query with no ANALYZE data at all. The outer loop is
-# real table "t1".
-#
-do_eqp_test 5.2 {
- SELECT * FROM t1, rt WHERE x==id;
-} {
- QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
-}
-
-# Now create enough ANALYZE data to tell SQLite that virtual table "rt"
-# contains very few rows. This causes it to move "rt" to the outer loop.
-#
-do_execsql_test 5.3 {
- ANALYZE;
- DELETE FROM sqlite_stat1 WHERE tbl='t1';
-}
-db close
-sqlite3 db test.db
-do_eqp_test 5.4 {
- SELECT * FROM t1, rt WHERE x==id;
-} {
- QUERY PLAN
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:
- `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
-}
-
-# Delete the ANALYZE data. "t1" should be the outer loop again.
-#
-do_execsql_test 5.5 { DROP TABLE sqlite_stat1; }
-db close
-sqlite3 db test.db
-do_eqp_test 5.6 {
- SELECT * FROM t1, rt WHERE x==id;
-} {
- QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
-}
-
-# This time create and attach a database that contains ANALYZE data for
-# tables of the same names as those used internally by virtual table
-# "rt". Check that the rtree module is not fooled into using this data.
-# Table "t1" should remain the outer loop.
-#
-do_test 5.7 {
- db backup test.db2
- sqlite3 db2 test.db2
- db2 eval {
- ANALYZE;
- DELETE FROM sqlite_stat1 WHERE tbl='t1';
- }
- db2 close
- db close
- sqlite3 db test.db
- execsql { ATTACH 'test.db2' AS aux; }
-} {}
-do_eqp_test 5.8 {
- SELECT * FROM t1, rt WHERE x==id;
-} {
- QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
-}
-
-#--------------------------------------------------------------------
-# Test that having a second connection drop the sqlite_stat1 table
-# before it is required by rtreeConnect() does not cause problems.
-#
-ifcapable rtree {
- reset_db
- do_execsql_test 6.1 {
- CREATE TABLE t1(x);
- CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
- INSERT INTO t1 VALUES(1);
- INSERT INTO rt VALUES(1,2,3);
- ANALYZE;
- }
- db close
- sqlite3 db test.db
- do_execsql_test 6.2 { SELECT * FROM t1 } {1}
-
- do_test 6.3 {
- sqlite3 db2 test.db
- db2 eval { DROP TABLE sqlite_stat1 }
- db2 close
- execsql { SELECT * FROM rt }
- } {1 2.0 3.0}
- db close
-}
-
-#--------------------------------------------------------------------
-# Test that queries featuring LEFT or CROSS JOINS are handled correctly.
-# Handled correctly in this case means:
-#
-# * Terms with prereqs that appear to the left of a LEFT JOIN against
-# the virtual table are always available to xBestIndex.
-#
-# * Terms with prereqs that appear to the right of a LEFT JOIN against
-# the virtual table are never available to xBestIndex.
-#
-# And the same behaviour for CROSS joins.
-#
-reset_db
-do_execsql_test 7.0 {
- CREATE TABLE xdir(x1);
- CREATE TABLE ydir(y1);
- CREATE VIRTUAL TABLE rt USING rtree_i32(id, xmin, xmax, ymin, ymax);
-
- INSERT INTO xdir VALUES(5);
- INSERT INTO ydir VALUES(10);
-
- INSERT INTO rt VALUES(1, 2, 7, 12, 14); -- Not a hit
- INSERT INTO rt VALUES(2, 2, 7, 8, 12); -- A hit!
- INSERT INTO rt VALUES(3, 7, 11, 8, 12); -- Not a hit!
- INSERT INTO rt VALUES(4, 5, 5, 10, 10); -- A hit!
-
-}
-
-proc do_eqp_execsql_test {tn sql res1 res2} {
- do_eqp_test $tn.1 $sql $res1
- do_execsql_test $tn.2 $sql $res2
-}
-
-do_eqp_execsql_test 7.1 {
- SELECT id FROM xdir, rt, ydir
- ON (y1 BETWEEN ymin AND ymax)
- WHERE (x1 BETWEEN xmin AND xmax);
-} {
- QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE ydir
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1
-} {
- 2 4
-}
-
-do_eqp_execsql_test 7.2 {
- SELECT * FROM xdir, rt LEFT JOIN ydir
- ON (y1 BETWEEN ymin AND ymax)
- WHERE (x1 BETWEEN xmin AND xmax);
-} {
- QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
-} {
- 5 1 2 7 12 14 {}
- 5 2 2 7 8 12 10
- 5 4 5 5 10 10 10
-}
-
-do_eqp_execsql_test 7.3 {
- SELECT id FROM xdir, rt CROSS JOIN ydir
- ON (y1 BETWEEN ymin AND ymax)
- WHERE (x1 BETWEEN xmin AND xmax);
-} {
- QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
-} {
- 2 4
-}
-
-do_eqp_execsql_test 7.4 {
- SELECT id FROM rt, xdir CROSS JOIN ydir
- ON (y1 BETWEEN ymin AND ymax)
- WHERE (x1 BETWEEN xmin AND xmax);
-} {
- QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
-} {
- 2 4
-}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeD.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeD.test
deleted file mode 100644
index 7f92898b0ab..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeD.test
+++ /dev/null
@@ -1,55 +0,0 @@
-# 2014 March 11
-#
-# 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.
-#
-#***********************************************************************
-#
-# Miscellaneous tests for errors in the rtree constructor.
-#
-
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-source $testdir/lock_common.tcl
-ifcapable !rtree||!builtin_test {
- finish_test
- return
-}
-set testprefix rtreeD
-
-#-------------------------------------------------------------------------
-# Test that if an SQLITE_BUSY is encountered within the vtable
-# constructor, a relevant error message is returned.
-#
-do_multiclient_test tn {
- do_test 1.$tn.1 {
- sql1 {
- CREATE TABLE t1(a, b);
- INSERT INTO t1 VALUES(1,2);
- CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy);
- INSERT INTO rt VALUES(1,2,3,4,5);
- }
- } {}
-
- do_test 1.$tn.2 {
- sql2 { SELECT * FROM t1; }
- } {1 2}
-
- do_test 1.$tn.3 {
- sql1 { BEGIN EXCLUSIVE; INSERT INTO t1 VALUES(3, 4); }
- } {}
-
- do_test 1.$tn.4 {
- list [catch { sql2 { SELECT * FROM rt } } msg] $msg
- } {1 {database is locked}}
-}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeE.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeE.test
deleted file mode 100644
index 72dcc94c9f4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeE.test
+++ /dev/null
@@ -1,143 +0,0 @@
-# 2010 August 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 contains tests for the r-tree module. Specifically, it tests
-# that new-style custom r-tree queries (geometry callbacks) work.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-ifcapable rtree_int_only { finish_test; return }
-
-
-#-------------------------------------------------------------------------
-# Test the example 2d "circle" geometry callback.
-#
-register_circle_geom db
-
-do_execsql_test rtreeE-1.0.0 {
- PRAGMA page_size=512;
- CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1);
-
- /* A tight pattern of small boxes near 0,0 */
- WITH RECURSIVE
- x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
- y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
- INSERT INTO rt1 SELECT x+5*y, x, x+2, y, y+2 FROM x, y;
-
- /* A looser pattern of small boxes near 100, 0 */
- WITH RECURSIVE
- x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
- y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
- INSERT INTO rt1 SELECT 100+x+5*y, x*3+100, x*3+102, y*3, y*3+2 FROM x, y;
-
- /* A looser pattern of larger boxes near 0, 200 */
- WITH RECURSIVE
- x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
- y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
- INSERT INTO rt1 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y;
-} {}
-do_rtree_integrity_test rtreeE-1.0.1 rt1
-
-# Queries against each of the three clusters */
-do_execsql_test rtreeE-1.1 {
- SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 0.0, 50.0, 3) ORDER BY id;
-} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24}
-do_execsql_test rtreeE-1.1x {
- SELECT id FROM rt1 WHERE id MATCH Qcircle('x:0 y:0 r:50.0 e:3') ORDER BY id;
-} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24}
-do_execsql_test rtreeE-1.2 {
- SELECT id FROM rt1 WHERE id MATCH Qcircle(100.0, 0.0, 50.0, 3) ORDER BY id;
-} {100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124}
-do_execsql_test rtreeE-1.3 {
- SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 200.0, 50.0, 3) ORDER BY id;
-} {200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224}
-
-# The Qcircle geometry function gives a lower score to larger leaf-nodes.
-# This causes the 200s to sort before the 100s and the 0s to sort before
-# last.
-#
-do_execsql_test rtreeE-1.4 {
- SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:3') AND id%100==0
-} {200 100 0}
-
-# Exclude odd rowids on a depth-first search
-do_execsql_test rtreeE-1.5 {
- SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:4') ORDER BY +id
-} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224}
-
-# Exclude odd rowids on a breadth-first search.
-do_execsql_test rtreeE-1.6 {
- SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id
-} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224}
-
-# Test that rtree prefers MATCH to lookup-by-rowid.
-#
-do_execsql_test rtreeE-1.7 {
- SELECT id FROM rt1 WHERE id=18 AND id MATCH Qcircle(0,0,1000,5)
-} {18}
-
-
-# Construct a large 2-D RTree with thousands of random entries.
-#
-do_test rtreeE-2.1 {
- db eval {
- CREATE TABLE t2(id,x0,x1,y0,y1);
- CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1);
- BEGIN;
- }
- expr srand(0)
- for {set i 1} {$i<=10000} {incr i} {
- set dx [expr {int(rand()*40)+1}]
- set dy [expr {int(rand()*40)+1}]
- set x0 [expr {int(rand()*(10000 - $dx))}]
- set x1 [expr {$x0+$dx}]
- set y0 [expr {int(rand()*(10000 - $dy))}]
- set y1 [expr {$y0+$dy}]
- set id [expr {$i+10000}]
- db eval {INSERT INTO t2 VALUES($id,$x0,$x1,$y0,$y1)}
- }
- db eval {
- INSERT INTO rt2 SELECT * FROM t2;
- COMMIT;
- }
-} {}
-do_rtree_integrity_test rtreeE-2.1.1 rt2
-
-for {set i 1} {$i<=200} {incr i} {
- set dx [expr {int(rand()*100)}]
- set dy [expr {int(rand()*100)}]
- set x0 [expr {int(rand()*(10000 - $dx))}]
- set x1 [expr {$x0+$dx}]
- set y0 [expr {int(rand()*(10000 - $dy))}]
- set y1 [expr {$y0+$dy}]
- set ans [db eval {SELECT id FROM t2 WHERE x1>=$x0 AND x0<=$x1 AND y1>=$y0 AND y0<=$y1 ORDER BY id}]
- do_execsql_test rtreeE-2.2.$i {
- SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch($x0,$x1,$y0,$y1) ORDER BY id
- } $ans
-}
-
-# Run query that have very deep priority queues
-#
-set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=5000 AND y1>=0 AND y0<=5000 ORDER BY id}]
-do_execsql_test rtreeE-2.3 {
- SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id
-} $ans
-set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}]
-do_execsql_test rtreeE-2.4 {
- SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id
-} $ans
-
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeF.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeF.test
deleted file mode 100644
index 561770d085b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeF.test
+++ /dev/null
@@ -1,84 +0,0 @@
-# 2014-08-21
-#
-# 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 contains tests for the r-tree module.
-#
-# This file contains test cases for the ticket
-# [369d57fb8e5ccdff06f197a37147a88f9de95cda] (2014-08-21)
-#
-# The following SQL causes an assertion fault while running
-# sqlite3_prepare() on the DELETE statement:
-#
-# CREATE TABLE t1(x);
-# CREATE TABLE t2(y);
-# CREATE VIRTUAL TABLE t3 USING rtree(a,b,c);
-# CREATE TRIGGER t2del AFTER DELETE ON t2 WHEN (SELECT 1 from t1) BEGIN
-# DELETE FROM t3 WHERE a=old.y;
-# END;
-# DELETE FROM t2 WHERE y=1;
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-
-do_execsql_test rtreeF-1.1 {
- CREATE TABLE t1(x);
- CREATE TABLE t2(y);
- CREATE VIRTUAL TABLE t3 USING rtree(a,b,c);
- CREATE TRIGGER t2dwl AFTER DELETE ON t2 WHEN (SELECT 1 from t1) BEGIN
- DELETE FROM t3 WHERE a=old.y;
- END;
-
- INSERT INTO t1(x) VALUES(999);
- INSERT INTO t2(y) VALUES(1),(2),(3),(4),(5);
- INSERT INTO t3(a,b,c) VALUES(1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7);
-
- SELECT a FROM t3 ORDER BY a;
- SELECT '|';
- SELECT y FROM t2 ORDER BY y;
-} {1 2 3 4 5 | 1 2 3 4 5}
-do_execsql_test rtreeF-1.2 {
- DELETE FROM t2 WHERE y=3;
-
- SELECT a FROM t3 ORDER BY a;
- SELECT '|';
- SELECT y FROM t2 ORDER BY y;
-} {1 2 4 5 | 1 2 4 5}
-do_execsql_test rtreeF-1.3 {
- DELETE FROM t1;
- DELETE FROM t2 WHERE y=5;
-
- SELECT a FROM t3 ORDER BY a;
- SELECT '|';
- SELECT y FROM t2 ORDER BY y;
-} {1 2 4 5 | 1 2 4}
-do_execsql_test rtreeF-1.4 {
- INSERT INTO t1 DEFAULT VALUES;
- DELETE FROM t2 WHERE y=5;
-
- SELECT a FROM t3 ORDER BY a;
- SELECT '|';
- SELECT y FROM t2 ORDER BY y;
-} {1 2 4 5 | 1 2 4}
-do_execsql_test rtreeF-1.5 {
- DELETE FROM t2 WHERE y=2;
-
- SELECT a FROM t3 ORDER BY a;
- SELECT '|';
- SELECT y FROM t2 ORDER BY y;
-} {1 4 5 | 1 4}
-
-do_rtree_integrity_test rtreeF-1.6 t3
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeG.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeG.test
deleted file mode 100644
index 12225d5832e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeG.test
+++ /dev/null
@@ -1,69 +0,0 @@
-# 2016-05-32
-#
-# 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 contains tests for the r-tree module.
-#
-# Verify that no invalid SQL is run during initialization
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-
-db close
-sqlite3_shutdown
-test_sqlite3_log [list lappend ::log]
-set ::log [list]
-sqlite3 db test.db
-
-
-set ::log {}
-do_execsql_test rtreeG-1.1 {
- CREATE VIRTUAL TABLE t1 USING rtree(id,x0,x1,y0,y1);
-} {}
-do_test rtreeG-1.1log {
- set ::log
-} {}
-
-do_execsql_test rtreeG-1.2 {
- INSERT INTO t1 VALUES(1,10,15,5,23),(2,20,21,5,23),(3,10,15,20,30);
- SELECT id from t1 WHERE x0>8 AND x1<16 AND y0>2 AND y1<25;
-} {1}
-do_rtree_integrity_test rtreeG-1.2.integrity t1
-do_test rtreeG-1.2log {
- set ::log
-} {}
-
-db close
-sqlite3 db test.db
-do_execsql_test rtreeG-1.3 {
- SELECT id from t1 WHERE x0>8 AND x1<16 AND y0>2 AND y1<25;
-} {1}
-do_test rtreeG-1.3log {
- set ::log
-} {}
-
-do_execsql_test rtreeG-1.4 {
- DROP TABLE t1;
-} {}
-do_test rtreeG-1.4log {
- set ::log
-} {}
-
-expand_all_sql db
-db close
-sqlite3_shutdown
-test_sqlite3_log
-sqlite3_initialize
-sqlite3 db test.db
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeH.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeH.test
deleted file mode 100644
index bff765d5309..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeH.test
+++ /dev/null
@@ -1,80 +0,0 @@
-# 2018-05-16
-#
-# 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 contains tests for the r-tree module, specifically the
-# auxiliary column mechanism.
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-ifcapable !rtree { finish_test ; return }
-
-do_execsql_test rtreeH-100 {
- CREATE VIRTUAL TABLE t1 USING rtree(id,x0,x1,y0,y1,+label,+other);
- INSERT INTO t1(x0,x1,y0,y1,label) VALUES
- (0,10,0,10,'lower-left corner'),
- (0,10,90,100,'upper-left corner'),
- (90,100,0,10,'lower-right corner'),
- (90,100,90,100,'upper-right corner'),
- (40,60,40,60,'center'),
- (0,5,0,100,'left edge'),
- (95,100,0,100,'right edge'),
- (0,100,0,5,'bottom edge'),
- (0,100,95,100,'top edge'),
- (0,100,0,100,'the whole thing'),
- (0,50,0,100,'left half'),
- (51,100,0,100,'right half'),
- (0,100,0,50,'bottom half'),
- (0,100,51,100,'top half');
-} {}
-do_execsql_test rtreeH-101 {
- SELECT * FROM t1_rowid ORDER BY rowid
-} {1 1 {lower-left corner} {} 2 1 {upper-left corner} {} 3 1 {lower-right corner} {} 4 1 {upper-right corner} {} 5 1 center {} 6 1 {left edge} {} 7 1 {right edge} {} 8 1 {bottom edge} {} 9 1 {top edge} {} 10 1 {the whole thing} {} 11 1 {left half} {} 12 1 {right half} {} 13 1 {bottom half} {} 14 1 {top half} {}}
-
-do_execsql_test rtreeH-102 {
- SELECT * FROM t1 WHERE rowid=5;
-} {5 40.0 60.0 40.0 60.0 center {}}
-do_execsql_test rtreeH-103 {
- SELECT * FROM t1 WHERE label='center';
-} {5 40.0 60.0 40.0 60.0 center {}}
-
-do_rtree_integrity_test rtreeH-110 t1
-
-do_execsql_test rtreeH-120 {
- SELECT label FROM t1 WHERE x1<=50 ORDER BY id
-} {{lower-left corner} {upper-left corner} {left edge} {left half}}
-do_execsql_test rtreeH-121 {
- SELECT label FROM t1 WHERE x1<=50 AND label NOT LIKE '%corner%' ORDER BY id
-} {{left edge} {left half}}
-
-do_execsql_test rtreeH-200 {
- WITH RECURSIVE
- c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<99),
- c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<99)
- INSERT INTO t1(id, x0,x1,y0,y1,label)
- SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
-} {}
-
-do_execsql_test rtreeH-210 {
- SELECT label FROM t1 WHERE x0>=48 AND x1<=50 AND y0>=48 AND y1<=50
- ORDER BY id;
-} {box-48,48 box-49,48 box-48,49 box-49,49}
-
-do_execsql_test rtreeH-300 {
- UPDATE t1 SET label='x'||label
- WHERE x0>=49 AND x1<=50 AND y0>=49 AND y1<=50;
- SELECT label FROM t1 WHERE x0>=48 AND x1<=50 AND y0>=48 AND y1<=50
- ORDER BY id;
-} {box-48,48 box-49,48 box-48,49 xbox-49,49}
-
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree_perf.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree_perf.tcl
deleted file mode 100644
index e42e6855061..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree_perf.tcl
+++ /dev/null
@@ -1,74 +0,0 @@
-
-set testdir [file join [file dirname $argv0] .. .. test]
-source $testdir/tester.tcl
-
-ifcapable !rtree {
- finish_test
- return
-}
-
-set NROW 10000
-set NQUERY 500
-
-puts "Generating $NROW rows of data..."
-set data [list]
-for {set ii 0} {$ii < $NROW} {incr ii} {
- set x1 [expr {rand()*1000}]
- set x2 [expr {$x1+rand()*50}]
- set y1 [expr {rand()*1000}]
- set y2 [expr {$y1+rand()*50}]
- lappend data $x1 $x2 $y1 $y2
-}
-puts "Finished generating data"
-
-
-set sql1 {CREATE TABLE btree(ii INTEGER PRIMARY KEY, x1, x2, y1, y2)}
-set sql2 {CREATE VIRTUAL TABLE rtree USING rtree(ii, x1, x2, y1, y2)}
-puts "Creating tables:"
-puts " $sql1"
-puts " $sql2"
-db eval $sql1
-db eval $sql2
-
-db eval "pragma cache_size=100"
-
-puts -nonewline "Inserting into btree... "
-flush stdout
-set btree_time [time {db transaction {
- set ii 1
- foreach {x1 x2 y1 y2} $data {
- db eval {INSERT INTO btree VALUES($ii, $x1, $x2, $y1, $y2)}
- incr ii
- }
-}}]
-puts "$btree_time"
-
-puts -nonewline "Inserting into rtree... "
-flush stdout
-set rtree_time [time {db transaction {
- set ii 1
- foreach {x1 x2 y1 y2} $data {
- incr ii
- db eval {INSERT INTO rtree VALUES($ii, $x1, $x2, $y1, $y2)}
- }
-}}]
-puts "$rtree_time"
-
-
-puts -nonewline "Selecting from btree... "
-flush stdout
-set btree_select_time [time {
- foreach {x1 x2 y1 y2} [lrange $data 0 [expr $NQUERY*4-1]] {
- db eval {SELECT * FROM btree WHERE x1<$x1 AND x2>$x2 AND y1<$y1 AND y2>$y2}
- }
-}]
-puts "$btree_select_time"
-
-puts -nonewline "Selecting from rtree... "
-flush stdout
-set rtree_select_time [time {
- foreach {x1 x2 y1 y2} [lrange $data 0 [expr $NQUERY*4-1]] {
- db eval {SELECT * FROM rtree WHERE x1<$x1 AND x2>$x2 AND y1<$y1 AND y2>$y2}
- }
-}]
-puts "$rtree_select_time"
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree_util.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree_util.tcl
deleted file mode 100644
index afa588e4e9a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtree_util.tcl
+++ /dev/null
@@ -1,197 +0,0 @@
-# 2008 Feb 19
-#
-# 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 contains Tcl code that may be useful for testing or
-# analyzing r-tree structures created with this module. It is
-# used by both test procedures and the r-tree viewer application.
-#
-
-
-#--------------------------------------------------------------------------
-# PUBLIC API:
-#
-# rtree_depth
-# rtree_ndim
-# rtree_node
-# rtree_mincells
-# rtree_check
-# rtree_dump
-# rtree_treedump
-#
-
-proc rtree_depth {db zTab} {
- $db one "SELECT rtreedepth(data) FROM ${zTab}_node WHERE nodeno=1"
-}
-
-proc rtree_nodedepth {db zTab iNode} {
- set iDepth [rtree_depth $db $zTab]
-
- set ii $iNode
- while {$ii != 1} {
- set sql "SELECT parentnode FROM ${zTab}_parent WHERE nodeno = $ii"
- set ii [db one $sql]
- incr iDepth -1
- }
-
- return $iDepth
-}
-
-# Return the number of dimensions of the rtree.
-#
-proc rtree_ndim {db zTab} {
- set nDim [expr {(([llength [$db eval "pragma table_info($zTab)"]]/6)-1)/2}]
-}
-
-# Return the contents of rtree node $iNode.
-#
-proc rtree_node {db zTab iNode {iPrec 6}} {
- set nDim [rtree_ndim $db $zTab]
- set sql "
- SELECT rtreenode($nDim, data) FROM ${zTab}_node WHERE nodeno = $iNode
- "
- set node [db one $sql]
-
- set nCell [llength $node]
- set nCoord [expr $nDim*2]
- for {set ii 0} {$ii < $nCell} {incr ii} {
- for {set jj 1} {$jj <= $nCoord} {incr jj} {
- set newval [format "%.${iPrec}f" [lindex $node $ii $jj]]
- lset node $ii $jj $newval
- }
- }
- set node
-}
-
-proc rtree_mincells {db zTab} {
- set n [$db one "select length(data) FROM ${zTab}_node LIMIT 1"]
- set nMax [expr {int(($n-4)/(8+[rtree_ndim $db $zTab]*2*4))}]
- return [expr {int($nMax/3)}]
-}
-
-# An integrity check for the rtree $zTab accessible via database
-# connection $db.
-#
-proc rtree_check {db zTab} {
- array unset ::checked
-
- # Check each r-tree node.
- set rc [catch {
- rtree_node_check $db $zTab 1 [rtree_depth $db $zTab]
- } msg]
- if {$rc && $msg ne ""} { error $msg }
-
- # Check that the _rowid and _parent tables have the right
- # number of entries.
- set nNode [$db one "SELECT count(*) FROM ${zTab}_node"]
- set nRow [$db one "SELECT count(*) FROM ${zTab}"]
- set nRowid [$db one "SELECT count(*) FROM ${zTab}_rowid"]
- set nParent [$db one "SELECT count(*) FROM ${zTab}_parent"]
-
- if {$nNode != ($nParent+1)} {
- error "Wrong number of entries in ${zTab}_parent"
- }
- if {$nRow != $nRowid} {
- error "Wrong number of entries in ${zTab}_rowid"
- }
-
- return $rc
-}
-
-proc rtree_node_check {db zTab iNode iDepth} {
- if {[info exists ::checked($iNode)]} { error "Second ref to $iNode" }
- set ::checked($iNode) 1
-
- set node [rtree_node $db $zTab $iNode]
- if {$iNode!=1 && [llength $node]==0} { error "No such node: $iNode" }
-
- if {$iNode != 1 && [llength $node]<[rtree_mincells $db $zTab]} {
- puts "Node $iNode: Has only [llength $node] cells"
- error ""
- }
- if {$iNode == 1 && [llength $node]==1 && [rtree_depth $db $zTab]>0} {
- set depth [rtree_depth $db $zTab]
- puts "Node $iNode: Has only 1 child (tree depth is $depth)"
- error ""
- }
-
- set nDim [expr {([llength [lindex $node 0]]-1)/2}]
-
- if {$iDepth > 0} {
- set d [expr $iDepth-1]
- foreach cell $node {
- set shouldbe [rtree_node_check $db $zTab [lindex $cell 0] $d]
- if {$cell ne $shouldbe} {
- puts "Node $iNode: Cell is: {$cell}, should be {$shouldbe}"
- error ""
- }
- }
- }
-
- set mapping_table "${zTab}_parent"
- set mapping_sql "SELECT parentnode FROM $mapping_table WHERE rowid = \$rowid"
- if {$iDepth==0} {
- set mapping_table "${zTab}_rowid"
- set mapping_sql "SELECT nodeno FROM $mapping_table WHERE rowid = \$rowid"
- }
- foreach cell $node {
- set rowid [lindex $cell 0]
- set mapping [db one $mapping_sql]
- if {$mapping != $iNode} {
- puts "Node $iNode: $mapping_table entry for cell $rowid is $mapping"
- error ""
- }
- }
-
- set ret [list $iNode]
- for {set ii 1} {$ii <= $nDim*2} {incr ii} {
- set f [lindex $node 0 $ii]
- foreach cell $node {
- set f2 [lindex $cell $ii]
- if {($ii%2)==1 && $f2<$f} {set f $f2}
- if {($ii%2)==0 && $f2>$f} {set f $f2}
- }
- lappend ret $f
- }
- return $ret
-}
-
-proc rtree_dump {db zTab} {
- set zRet ""
- set nDim [expr {(([llength [$db eval "pragma table_info($zTab)"]]/6)-1)/2}]
- set sql "SELECT nodeno, rtreenode($nDim, data) AS node FROM ${zTab}_node"
- $db eval $sql {
- append zRet [format "% -10s %s\n" $nodeno $node]
- }
- set zRet
-}
-
-proc rtree_nodetreedump {db zTab zIndent iDepth iNode} {
- set ret ""
- set node [rtree_node $db $zTab $iNode 1]
- append ret [format "%-3d %s%s\n" $iNode $zIndent $node]
- if {$iDepth>0} {
- foreach cell $node {
- set i [lindex $cell 0]
- append ret [rtree_nodetreedump $db $zTab "$zIndent " [expr $iDepth-1] $i]
- }
- }
- set ret
-}
-
-proc rtree_treedump {db zTab} {
- set d [rtree_depth $db $zTab]
- rtree_nodetreedump $db $zTab "" $d 1
-}
-
-proc do_rtree_integrity_test {tn tbl} {
- uplevel [list do_execsql_test $tn "SELECT rtreecheck('$tbl')" ok]
-}
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreecheck.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreecheck.test
deleted file mode 100644
index cbe8b513c91..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreecheck.test
+++ /dev/null
@@ -1,158 +0,0 @@
-# 2017 August 17
-#
-# 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.
-#
-#***********************************************************************
-#
-#
-
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set testprefix rtreecheck
-
-ifcapable !rtree {
- finish_test
- return
-}
-
-proc swap_int32 {blob i0 i1} {
- binary scan $blob I* L
-
- set a [lindex $L $i0]
- set b [lindex $L $i1]
-
- lset L $i0 $b
- lset L $i1 $a
-
- binary format I* $L
-}
-
-proc set_int32 {blob idx val} {
- binary scan $blob I* L
- lset L $idx $val
- binary format I* $L
-}
-
-do_catchsql_test 1.0 {
- SELECT rtreecheck();
-} {1 {wrong number of arguments to function rtreecheck()}}
-
-do_catchsql_test 1.1 {
- SELECT rtreecheck(0,0,0);
-} {1 {wrong number of arguments to function rtreecheck()}}
-
-
-proc setup_simple_db {{module rtree}} {
- reset_db
- db func swap_int32 swap_int32
- execsql "
- CREATE VIRTUAL TABLE r1 USING $module (id, x1, x2, y1, y2);
- INSERT INTO r1 VALUES(1, 5, 5, 5, 5); -- 3
- INSERT INTO r1 VALUES(2, 6, 6, 6, 6); -- 9
- INSERT INTO r1 VALUES(3, 7, 7, 7, 7); -- 15
- INSERT INTO r1 VALUES(4, 8, 8, 8, 8); -- 21
- INSERT INTO r1 VALUES(5, 9, 9, 9, 9); -- 27
- "
-}
-
-setup_simple_db
-do_execsql_test 2.1 {
- SELECT rtreecheck('r1')
-} {ok}
-
-do_execsql_test 2.2 {
- UPDATE r1_node SET data = swap_int32(data, 3, 9);
- UPDATE r1_node SET data = swap_int32(data, 23, 29);
-}
-
-do_execsql_test 2.3 {
- SELECT rtreecheck('r1')
-} {{Dimension 0 of cell 0 on node 1 is corrupt
-Dimension 1 of cell 3 on node 1 is corrupt}}
-
-setup_simple_db
-do_execsql_test 2.4 {
- DELETE FROM r1_rowid WHERE rowid = 3;
- SELECT rtreecheck('r1')
-} {{Mapping (3 -> 1) missing from %_rowid table
-Wrong number of entries in %_rowid table - expected 5, actual 4}}
-
-setup_simple_db
-do_execsql_test 2.5 {
- UPDATE r1_rowid SET nodeno=2 WHERE rowid=3;
- SELECT rtreecheck('r1')
-} {{Found (3 -> 2) in %_rowid table, expected (3 -> 1)}}
-
-reset_db
-do_execsql_test 3.0 {
- CREATE VIRTUAL TABLE r1 USING rtree_i32(id, x1, x2);
- INSERT INTO r1 VALUES(1, 0x7FFFFFFF*-1, 0x7FFFFFFF);
- INSERT INTO r1 VALUES(2, 0x7FFFFFFF*-1, 5);
- INSERT INTO r1 VALUES(3, -5, 5);
- INSERT INTO r1 VALUES(4, 5, 0x11111111);
- INSERT INTO r1 VALUES(5, 5, 0x00800000);
- INSERT INTO r1 VALUES(6, 5, 0x00008000);
- INSERT INTO r1 VALUES(7, 5, 0x00000080);
- INSERT INTO r1 VALUES(8, 5, 0x40490fdb);
- INSERT INTO r1 VALUES(9, 0x7f800000, 0x7f900000);
- SELECT rtreecheck('r1')
-} {ok}
-
-do_execsql_test 3.1 {
- CREATE VIRTUAL TABLE r2 USING rtree_i32(id, x1, x2);
- INSERT INTO r2 VALUES(2, -1*(1<<31), -1*(1<<31)+5);
- SELECT rtreecheck('r2')
-} {ok}
-
-do_execsql_test 3.2 {
- BEGIN;
- UPDATE r2_node SET data = X'123456';
- SELECT rtreecheck('r2')!="ok";
-} {1}
-
-do_execsql_test 3.3 {
- ROLLBACK;
- UPDATE r2_node SET data = X'00001234';
- SELECT rtreecheck('r2')!="ok";
-} {1}
-
-do_execsql_test 4.0 {
- CREATE TABLE notanrtree(i);
- SELECT rtreecheck('notanrtree');
-} {{Schema corrupt or not an rtree}}
-
-#-------------------------------------------------------------------------
-#
-reset_db
-db func set_int32 set_int32
-do_execsql_test 5.0 {
- CREATE VIRTUAL TABLE r3 USING rtree_i32(id, x1, x2, y1, y2);
- WITH x(i) AS (
- SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000
- )
- INSERT INTO r3 SELECT i, i, i, i, i FROM x;
-}
-do_execsql_test 5.1 {
- BEGIN;
- UPDATE r3_node SET data = set_int32(data, 3, 5000);
- UPDATE r3_node SET data = set_int32(data, 4, 5000);
- SELECT rtreecheck('r3')=='ok'
-} 0
-do_execsql_test 5.2 {
- ROLLBACK;
- BEGIN;
- UPDATE r3_node SET data = set_int32(data, 3, 0);
- UPDATE r3_node SET data = set_int32(data, 4, 0);
- SELECT rtreecheck('r3')=='ok'
-} 0
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeconnect.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeconnect.test
deleted file mode 100644
index 16d04d9a047..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/rtreeconnect.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# 2017 August 17
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the r-tree extension. Specifically,
-# the impact of an SQLITE_SCHEMA error within the rtree module xConnect
-# callback.
-#
-
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-set testprefix rtreeconnect
-
-ifcapable !rtree {
- finish_test
- return
-}
-
-do_execsql_test 1.0 {
- CREATE VIRTUAL TABLE r1 USING rtree(id, x1, x2, y1, y2);
- CREATE TABLE t1(id, x1, x2, y1, y2);
- CREATE TABLE log(l);
-
- CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
- INSERT INTO r1 VALUES(new.id, new.x1, new.x2, new.y1, new.y2);
- INSERT INTO log VALUES('r1: ' || new.id);
- END;
-}
-
-db close
-sqlite3 db test.db
-sqlite3 db2 test.db
-
-do_test 1.1 {
- db eval { INSERT INTO log VALUES('startup'); }
- db2 eval { CREATE TABLE newtable(x,y); }
-} {}
-
-do_execsql_test 1.2 {
- INSERT INTO t1 VALUES(1, 2, 3, 4, 5);
-}
-
-db2 close
-db close
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/sqlite3rtree.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/sqlite3rtree.h
deleted file mode 100644
index f683fc610af..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/sqlite3rtree.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-** 2010 August 30
-**
-** 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.
-**
-*************************************************************************
-*/
-
-#ifndef _SQLITE3RTREE_H_
-#define _SQLITE3RTREE_H_
-
-#include <sqlite3.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
-typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
-
-/* The double-precision datatype used by RTree depends on the
-** SQLITE_RTREE_INT_ONLY compile-time option.
-*/
-#ifdef SQLITE_RTREE_INT_ONLY
- typedef sqlite3_int64 sqlite3_rtree_dbl;
-#else
- typedef double sqlite3_rtree_dbl;
-#endif
-
-/*
-** Register a geometry callback named zGeom that can be used as part of an
-** R-Tree geometry query as follows:
-**
-** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
-*/
-int sqlite3_rtree_geometry_callback(
- sqlite3 *db,
- const char *zGeom,
- int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
- void *pContext
-);
-
-
-/*
-** A pointer to a structure of the following type is passed as the first
-** argument to callbacks registered using rtree_geometry_callback().
-*/
-struct sqlite3_rtree_geometry {
- void *pContext; /* Copy of pContext passed to s_r_g_c() */
- int nParam; /* Size of array aParam[] */
- sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */
- void *pUser; /* Callback implementation user data */
- void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
-};
-
-/*
-** Register a 2nd-generation geometry callback named zScore that can be
-** used as part of an R-Tree geometry query as follows:
-**
-** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
-*/
-int sqlite3_rtree_query_callback(
- sqlite3 *db,
- const char *zQueryFunc,
- int (*xQueryFunc)(sqlite3_rtree_query_info*),
- void *pContext,
- void (*xDestructor)(void*)
-);
-
-
-/*
-** A pointer to a structure of the following type is passed as the
-** argument to scored geometry callback registered using
-** sqlite3_rtree_query_callback().
-**
-** Note that the first 5 fields of this structure are identical to
-** sqlite3_rtree_geometry. This structure is a subclass of
-** sqlite3_rtree_geometry.
-*/
-struct sqlite3_rtree_query_info {
- void *pContext; /* pContext from when function registered */
- int nParam; /* Number of function parameters */
- sqlite3_rtree_dbl *aParam; /* value of function parameters */
- void *pUser; /* callback can use this, if desired */
- void (*xDelUser)(void*); /* function to free pUser */
- sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
- unsigned int *anQueue; /* Number of pending entries in the queue */
- int nCoord; /* Number of coordinates */
- int iLevel; /* Level of current node or entry */
- int mxLevel; /* The largest iLevel value in the tree */
- sqlite3_int64 iRowid; /* Rowid for current entry */
- sqlite3_rtree_dbl rParentScore; /* Score of parent node */
- int eParentWithin; /* Visibility of parent node */
- int eWithin; /* OUT: Visiblity */
- sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
- /* The following fields are only available in 3.8.11 and later */
- sqlite3_value **apSqlParam; /* Original SQL values of parameters */
-};
-
-/*
-** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
-*/
-#define NOT_WITHIN 0 /* Object completely outside of query region */
-#define PARTLY_WITHIN 1 /* Object partially overlaps query region */
-#define FULLY_WITHIN 2 /* Object fully contained within query region */
-
-
-#ifdef __cplusplus
-} /* end of the 'extern "C"' block */
-#endif
-
-#endif /* ifndef _SQLITE3RTREE_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/tkt3363.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/tkt3363.test
deleted file mode 100644
index db05ed527a1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/tkt3363.test
+++ /dev/null
@@ -1,50 +0,0 @@
-# 2008 Sep 08
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing that ticket #3363 is fixed.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] rtree_util.tcl]
-source $testdir/tester.tcl
-
-ifcapable !rtree {
- finish_test
- return
-}
-
-do_test tkt3363.1.1 {
- execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2) }
-} {}
-
-do_test tkt3363.1.2 {
- for {set ii 1} {$ii < 50} {incr ii} {
- set x 1000000
- set y [expr 4000000 + $ii*10]
- execsql { INSERT INTO t1 VALUES($ii, $x, $x, $y, $y) }
- }
-} {}
-
-do_test tkt3363.1.3 {
- execsql {
- SELECT count(*) FROM t1 WHERE +y2>4000425.0;
- }
-} {7}
-
-do_test tkt3363.1.4 {
- execsql {
- SELECT count(*) FROM t1 WHERE y2>4000425.0;
- }
-} {7}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/viewrtree.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/viewrtree.tcl
deleted file mode 100644
index 794677f5a37..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/rtree/viewrtree.tcl
+++ /dev/null
@@ -1,188 +0,0 @@
-
-load ./libsqlite3.dylib
-#package require sqlite3
-source [file join [file dirname $argv0] rtree_util.tcl]
-
-wm title . "SQLite r-tree viewer"
-
-if {[llength $argv]!=1} {
- puts stderr "Usage: $argv0 <database-file>"
- puts stderr ""
- exit
-}
-sqlite3 db [lindex $argv 0]
-
-canvas .c -background white -width 400 -height 300 -highlightthickness 0
-
-button .b -text "Parent Node" -command {
- set sql "SELECT parentnode FROM $::O(zTab)_parent WHERE nodeno = $::O(iNode)"
- set ::O(iNode) [db one $sql]
- if {$::O(iNode) eq ""} {set ::O(iNode) 1}
- view_node
-}
-
-set O(iNode) 1
-set O(zTab) ""
-set O(listbox_captions) [list]
-set O(listbox_itemmap) [list]
-set O(listbox_highlight) -1
-
-listbox .l -listvariable ::O(listbox_captions) -yscrollcommand {.ls set}
-scrollbar .ls -command {.l yview}
-label .status -font courier -anchor w
-label .title -anchor w -text "Node 1:" -background white -borderwidth 0
-
-
-set rtree_tables [list]
-db eval {
- SELECT name
- FROM sqlite_master
- WHERE type='table' AND sql LIKE '%virtual%table%using%rtree%'
-} {
- set nCol [expr [llength [db eval "pragma table_info($name)"]]/6]
- if {$nCol != 5} {
- puts stderr "Not viewing $name - is not 2-dimensional"
- } else {
- lappend rtree_tables [list Table $name]
- }
-}
-if {$rtree_tables eq ""} {
- puts stderr "Cannot find an r-tree table in database [lindex $argv 0]"
- puts stderr ""
- exit
-}
-eval tk_optionMenu .select option_var $rtree_tables
-trace add variable option_var write set_option_var
-proc set_option_var {args} {
- set ::O(zTab) [lindex $::option_var 1]
- set ::O(iNode) 1
- view_node
-}
-set ::O(zTab) [lindex $::rtree_tables 0 1]
-
-bind .l <1> {listbox_click [.l nearest %y]}
-bind .l <Motion> {listbox_mouseover [.l nearest %y]}
-bind .l <Leave> {listbox_mouseover -1}
-
-proc listbox_click {sel} {
- if {$sel ne ""} {
- set ::O(iNode) [lindex $::O(listbox_captions) $sel 1]
- view_node
- }
-}
-proc listbox_mouseover {i} {
- set oldid [lindex $::O(listbox_itemmap) $::O(listbox_highlight)]
- .c itemconfigure $oldid -fill ""
-
- .l selection clear 0 end
- .status configure -text ""
- if {$i>=0} {
- set id [lindex $::O(listbox_itemmap) $i]
- .c itemconfigure $id -fill grey
- .c lower $id
- set ::O(listbox_highlight) $i
- .l selection set $i
- .status configure -text [cell_report db $::O(zTab) $::O(iNode) $i]
- }
-}
-
-grid configure .select -row 0 -column 0 -columnspan 2 -sticky nsew
-grid configure .b -row 1 -column 0 -columnspan 2 -sticky nsew
-grid configure .l -row 2 -column 0 -sticky nsew
-grid configure .status -row 3 -column 0 -columnspan 3 -sticky nsew
-
-grid configure .title -row 0 -column 2 -sticky nsew
-grid configure .c -row 1 -column 2 -rowspan 2 -sticky nsew
-grid configure .ls -row 2 -column 1 -sticky nsew
-
-grid columnconfigure . 2 -weight 1
-grid rowconfigure . 2 -weight 1
-
-proc node_bbox {data} {
- set xmin 0
- set xmax 0
- set ymin 0
- set ymax 0
- foreach {rowid xmin xmax ymin ymax} [lindex $data 0] break
- foreach cell [lrange $data 1 end] {
- foreach {rowid x1 x2 y1 y2} $cell break
- if {$x1 < $xmin} {set xmin $x1}
- if {$x2 > $xmax} {set xmax $x2}
- if {$y1 < $ymin} {set ymin $y1}
- if {$y2 > $ymax} {set ymax $y2}
- }
- list $xmin $xmax $ymin $ymax
-}
-
-proc view_node {} {
- set iNode $::O(iNode)
- set zTab $::O(zTab)
-
- set data [rtree_node db $zTab $iNode 12]
- set depth [rtree_nodedepth db $zTab $iNode]
-
- .c delete all
- set ::O(listbox_captions) [list]
- set ::O(listbox_itemmap) [list]
- set $::O(listbox_highlight) -1
-
- .b configure -state normal
- if {$iNode == 1} {.b configure -state disabled}
- .title configure -text "Node $iNode: [cell_report db $zTab $iNode -1]"
-
- foreach {xmin xmax ymin ymax} [node_bbox $data] break
- set total_area 0.0
-
- set xscale [expr {double([winfo width .c]-20)/($xmax-$xmin)}]
- set yscale [expr {double([winfo height .c]-20)/($ymax-$ymin)}]
-
- set xoff [expr {10.0 - $xmin*$xscale}]
- set yoff [expr {10.0 - $ymin*$yscale}]
-
- foreach cell $data {
- foreach {rowid x1 x2 y1 y2} $cell break
- set total_area [expr {$total_area + ($x2-$x1)*($y2-$y1)}]
- set x1 [expr {$x1*$xscale + $xoff}]
- set x2 [expr {$x2*$xscale + $xoff}]
- set y1 [expr {$y1*$yscale + $yoff}]
- set y2 [expr {$y2*$yscale + $yoff}]
-
- set id [.c create rectangle $x1 $y1 $x2 $y2]
- if {$depth>0} {
- lappend ::O(listbox_captions) "Node $rowid"
- lappend ::O(listbox_itemmap) $id
- }
- }
-}
-
-proc cell_report {db zTab iParent iCell} {
- set data [rtree_node db $zTab $iParent 12]
- set cell [lindex $data $iCell]
-
- foreach {xmin xmax ymin ymax} [node_bbox $data] break
- set total_area [expr ($xmax-$xmin)*($ymax-$ymin)]
-
- if {$cell eq ""} {
- set cell_area 0.0
- foreach cell $data {
- foreach {rowid x1 x2 y1 y2} $cell break
- set cell_area [expr $cell_area+($x2-$x1)*($y2-$y1)]
- }
- set cell_area [expr $cell_area/[llength $data]]
- set zReport [format "Size = %.1f x %.1f Average child area = %.1f%%" \
- [expr $xmax-$xmin] [expr $ymax-$ymin] [expr 100.0*$cell_area/$total_area]\
- ]
- append zReport " Sub-tree height: [rtree_nodedepth db $zTab $iParent]"
- } else {
- foreach {rowid x1 x2 y1 y2} $cell break
- set cell_area [expr ($x2-$x1)*($y2-$y1)]
- set zReport [format "Size = %.1f x %.1f Area = %.1f%%" \
- [expr $x2-$x1] [expr $y2-$y1] [expr 100.0*$cell_area/$total_area]
- ]
- }
-
- return $zReport
-}
-
-view_node
-bind .c <Configure> view_node
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/changeset.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/changeset.c
deleted file mode 100644
index edb43ff8e52..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/changeset.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
-** 2014-08-18
-**
-** 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 contains code to implement the "changeset" command line
-** utility for displaying and transforming changesets generated by
-** the Sessions extension.
-*/
-#include "sqlite3.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-
-
-/*
-** Show a usage message on stderr then quit.
-*/
-static void usage(const char *argv0){
- fprintf(stderr, "Usage: %s FILENAME COMMAND ...\n", argv0);
- fprintf(stderr,
- "COMMANDs:\n"
- " apply DB Apply the changeset to database file DB\n"
- " concat FILE2 OUT Concatenate FILENAME and FILE2 into OUT\n"
- " dump Show the complete content of the changeset\n"
- " invert OUT Write an inverted changeset into file OUT\n"
- " sql Give a pseudo-SQL rendering of the changeset\n"
- );
- exit(1);
-}
-
-/*
-** Read the content of a disk file into an in-memory buffer
-*/
-static void readFile(const char *zFilename, int *pSz, void **ppBuf){
- FILE *f;
- int sz;
- void *pBuf;
- f = fopen(zFilename, "rb");
- if( f==0 ){
- fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
- exit(1);
- }
- fseek(f, 0, SEEK_END);
- sz = (int)ftell(f);
- rewind(f);
- pBuf = sqlite3_malloc( sz ? sz : 1 );
- if( pBuf==0 ){
- fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
- sz, zFilename);
- exit(1);
- }
- if( sz>0 ){
- if( fread(pBuf, sz, 1, f)!=1 ){
- fprintf(stderr, "cannot read all %d bytes of \"%s\"\n", sz, zFilename);
- exit(1);
- }
- fclose(f);
- }
- *pSz = sz;
- *ppBuf = pBuf;
-}
-
-/* Array for converting from half-bytes (nybbles) into ASCII hex
-** digits. */
-static const char hexdigits[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
-};
-
-/*
-** Render an sqlite3_value as an SQL string.
-*/
-static void renderValue(sqlite3_value *pVal){
- switch( sqlite3_value_type(pVal) ){
- case SQLITE_FLOAT: {
- double r1;
- char zBuf[50];
- r1 = sqlite3_value_double(pVal);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
- printf("%s", zBuf);
- break;
- }
- case SQLITE_INTEGER: {
- printf("%lld", sqlite3_value_int64(pVal));
- break;
- }
- case SQLITE_BLOB: {
- char const *zBlob = sqlite3_value_blob(pVal);
- int nBlob = sqlite3_value_bytes(pVal);
- int i;
- printf("x'");
- for(i=0; i<nBlob; i++){
- putchar(hexdigits[(zBlob[i]>>4)&0x0F]);
- putchar(hexdigits[(zBlob[i])&0x0F]);
- }
- putchar('\'');
- break;
- }
- case SQLITE_TEXT: {
- const unsigned char *zArg = sqlite3_value_text(pVal);
- putchar('\'');
- while( zArg[0] ){
- putchar(zArg[0]);
- if( zArg[0]=='\'' ) putchar(zArg[0]);
- zArg++;
- }
- putchar('\'');
- break;
- }
- default: {
- assert( sqlite3_value_type(pVal)==SQLITE_NULL );
- printf("NULL");
- break;
- }
- }
-}
-
-/*
-** Number of conflicts seen
-*/
-static int nConflict = 0;
-
-/*
-** The conflict callback
-*/
-static int conflictCallback(
- void *pCtx,
- int eConflict,
- sqlite3_changeset_iter *pIter
-){
- int op, bIndirect, nCol, i;
- const char *zTab;
- unsigned char *abPK;
- const char *zType = "";
- const char *zOp = "";
- const char *zSep = " ";
-
- nConflict++;
- sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
- sqlite3changeset_pk(pIter, &abPK, 0);
- switch( eConflict ){
- case SQLITE_CHANGESET_DATA: zType = "DATA"; break;
- case SQLITE_CHANGESET_NOTFOUND: zType = "NOTFOUND"; break;
- case SQLITE_CHANGESET_CONFLICT: zType = "PRIMARY KEY"; break;
- case SQLITE_CHANGESET_FOREIGN_KEY: zType = "FOREIGN KEY"; break;
- case SQLITE_CHANGESET_CONSTRAINT: zType = "CONSTRAINT"; break;
- }
- switch( op ){
- case SQLITE_UPDATE: zOp = "UPDATE of"; break;
- case SQLITE_INSERT: zOp = "INSERT into"; break;
- case SQLITE_DELETE: zOp = "DELETE from"; break;
- }
- printf("%s conflict on %s table %s with primary key", zType, zOp, zTab);
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- if( abPK[i]==0 ) continue;
- printf("%s", zSep);
- if( op==SQLITE_INSERT ){
- sqlite3changeset_new(pIter, i, &pVal);
- }else{
- sqlite3changeset_old(pIter, i, &pVal);
- }
- renderValue(pVal);
- zSep = ",";
- }
- printf("\n");
- return SQLITE_CHANGESET_OMIT;
-}
-
-int main(int argc, char **argv){
- int sz, rc;
- void *pBuf = 0;
- if( argc<3 ) usage(argv[0]);
- readFile(argv[1], &sz, &pBuf);
-
- /* changeset FILENAME apply DB
- ** Apply the changeset in FILENAME to the database file DB
- */
- if( strcmp(argv[2],"apply")==0 ){
- sqlite3 *db;
- if( argc!=4 ) usage(argv[0]);
- rc = sqlite3_open(argv[3], &db);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "unable to open database file \"%s\": %s\n",
- argv[3], sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
- sqlite3_exec(db, "BEGIN", 0, 0, 0);
- nConflict = 0;
- rc = sqlite3changeset_apply(db, sz, pBuf, 0, conflictCallback, 0);
- if( rc ){
- fprintf(stderr, "sqlite3changeset_apply() returned %d\n", rc);
- }
- if( nConflict ){
- fprintf(stderr, "%d conflicts - no changes applied\n", nConflict);
- sqlite3_exec(db, "ROLLBACK", 0, 0, 0);
- }else if( rc ){
- fprintf(stderr, "sqlite3changeset_apply() returns %d "
- "- no changes applied\n", rc);
- sqlite3_exec(db, "ROLLBACK", 0, 0, 0);
- }else{
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
- }
- sqlite3_close(db);
- }else
-
- /* changeset FILENAME concat FILE2 OUT
- ** Add changeset FILE2 onto the end of the changeset in FILENAME
- ** and write the result into OUT.
- */
- if( strcmp(argv[2],"concat")==0 ){
- int szB;
- void *pB;
- int szOut;
- void *pOutBuf;
- FILE *out;
- const char *zOut = argv[4];
- if( argc!=5 ) usage(argv[0]);
- out = fopen(zOut, "wb");
- if( out==0 ){
- fprintf(stderr, "cannot open \"%s\" for writing\n", zOut);
- exit(1);
- }
- readFile(argv[3], &szB, &pB);
- rc = sqlite3changeset_concat(sz, pBuf, szB, pB, &szOut, &pOutBuf);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "sqlite3changeset_concat() returns %d\n", rc);
- }else if( szOut>0 && fwrite(pOutBuf, szOut, 1, out)!=1 ){
- fprintf(stderr, "unable to write all %d bytes of output to \"%s\"\n",
- szOut, zOut);
- }
- fclose(out);
- sqlite3_free(pOutBuf);
- sqlite3_free(pB);
- }else
-
- /* changeset FILENAME dump
- ** Show the complete content of the changeset in FILENAME
- */
- if( strcmp(argv[2],"dump")==0 ){
- int cnt = 0;
- int i;
- sqlite3_changeset_iter *pIter;
- rc = sqlite3changeset_start(&pIter, sz, pBuf);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "sqlite3changeset_start() returns %d\n", rc);
- exit(1);
- }
- while( sqlite3changeset_next(pIter)==SQLITE_ROW ){
- int op, bIndirect, nCol;
- const char *zTab;
- unsigned char *abPK;
- sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
- cnt++;
- printf("%d: %s table=[%s] indirect=%d nColumn=%d\n",
- cnt, op==SQLITE_INSERT ? "INSERT" :
- op==SQLITE_UPDATE ? "UPDATE" : "DELETE",
- zTab, bIndirect, nCol);
- sqlite3changeset_pk(pIter, &abPK, 0);
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- pVal = 0;
- sqlite3changeset_old(pIter, i, &pVal);
- if( pVal ){
- printf(" old[%d]%s = ", i, abPK[i] ? "pk" : " ");
- renderValue(pVal);
- printf("\n");
- }
- pVal = 0;
- sqlite3changeset_new(pIter, i, &pVal);
- if( pVal ){
- printf(" new[%d]%s = ", i, abPK[i] ? "pk" : " ");
- renderValue(pVal);
- printf("\n");
- }
- }
- }
- sqlite3changeset_finalize(pIter);
- }else
-
- /* changeset FILENAME invert OUT
- ** Invert the changes in FILENAME and writes the result on OUT
- */
- if( strcmp(argv[2],"invert")==0 ){
- FILE *out;
- int szOut = 0;
- void *pOutBuf = 0;
- const char *zOut = argv[3];
- if( argc!=4 ) usage(argv[0]);
- out = fopen(zOut, "wb");
- if( out==0 ){
- fprintf(stderr, "cannot open \"%s\" for writing\n", zOut);
- exit(1);
- }
- rc = sqlite3changeset_invert(sz, pBuf, &szOut, &pOutBuf);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "sqlite3changeset_invert() returns %d\n", rc);
- }else if( szOut>0 && fwrite(pOutBuf, szOut, 1, out)!=1 ){
- fprintf(stderr, "unable to write all %d bytes of output to \"%s\"\n",
- szOut, zOut);
- }
- fclose(out);
- sqlite3_free(pOutBuf);
- }else
-
- /* changeset FILE sql
- ** Show the content of the changeset as pseudo-SQL
- */
- if( strcmp(argv[2],"sql")==0 ){
- int cnt = 0;
- char *zPrevTab = 0;
- char *zSQLTabName = 0;
- sqlite3_changeset_iter *pIter = 0;
- rc = sqlite3changeset_start(&pIter, sz, pBuf);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "sqlite3changeset_start() returns %d\n", rc);
- exit(1);
- }
- printf("BEGIN;\n");
- while( sqlite3changeset_next(pIter)==SQLITE_ROW ){
- int op, bIndirect, nCol;
- const char *zTab;
- sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
- cnt++;
- if( zPrevTab==0 || strcmp(zPrevTab,zTab)!=0 ){
- sqlite3_free(zPrevTab);
- sqlite3_free(zSQLTabName);
- zPrevTab = sqlite3_mprintf("%s", zTab);
- if( !isalnum(zTab[0]) || sqlite3_strglob("*[^a-zA-Z0-9]*",zTab)==0 ){
- zSQLTabName = sqlite3_mprintf("\"%w\"", zTab);
- }else{
- zSQLTabName = sqlite3_mprintf("%s", zTab);
- }
- printf("/****** Changes for table %s ***************/\n", zSQLTabName);
- }
- switch( op ){
- case SQLITE_DELETE: {
- unsigned char *abPK;
- int i;
- const char *zSep = " ";
- sqlite3changeset_pk(pIter, &abPK, 0);
- printf("/* %d */ DELETE FROM %s WHERE", cnt, zSQLTabName);
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- if( abPK[i]==0 ) continue;
- printf("%sc%d=", zSep, i+1);
- zSep = " AND ";
- sqlite3changeset_old(pIter, i, &pVal);
- renderValue(pVal);
- }
- printf(";\n");
- break;
- }
- case SQLITE_UPDATE: {
- unsigned char *abPK;
- int i;
- const char *zSep = " ";
- sqlite3changeset_pk(pIter, &abPK, 0);
- printf("/* %d */ UPDATE %s SET", cnt, zSQLTabName);
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal = 0;
- sqlite3changeset_new(pIter, i, &pVal);
- if( pVal ){
- printf("%sc%d=", zSep, i+1);
- zSep = ", ";
- renderValue(pVal);
- }
- }
- printf(" WHERE");
- zSep = " ";
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- if( abPK[i]==0 ) continue;
- printf("%sc%d=", zSep, i+1);
- zSep = " AND ";
- sqlite3changeset_old(pIter, i, &pVal);
- renderValue(pVal);
- }
- printf(";\n");
- break;
- }
- case SQLITE_INSERT: {
- int i;
- printf("/* %d */ INSERT INTO %s VALUES", cnt, zSQLTabName);
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- printf("%c", i==0 ? '(' : ',');
- sqlite3changeset_new(pIter, i, &pVal);
- renderValue(pVal);
- }
- printf(");\n");
- break;
- }
- }
- }
- printf("COMMIT;\n");
- sqlite3changeset_finalize(pIter);
- sqlite3_free(zPrevTab);
- sqlite3_free(zSQLTabName);
- }else
-
- /* If nothing else matches, show the usage comment */
- usage(argv[0]);
- sqlite3_free(pBuf);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session1.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session1.test
deleted file mode 100644
index f423a0cf4b4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session1.test
+++ /dev/null
@@ -1,662 +0,0 @@
-# 2011 March 07
-#
-# 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 regression tests for SQLite library.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix session1
-
-# Run all tests in this file twice. Once with "WITHOUT ROWID", and once
-# with regular rowid tables.
-#
-foreach {tn trailing} {
- 1 ""
- 2 " WITHOUT ROWID "
-} {
-eval [string map [list %WR% $trailing] {
-
-db close
-forcedelete test.db test.db2
-reset_db
-
-do_execsql_test $tn.1.0 {
- CREATE TABLE t1(x PRIMARY KEY, y) %WR%;
- INSERT INTO t1 VALUES('abc', 'def');
-}
-
-#-------------------------------------------------------------------------
-# Test creating, attaching tables to and deleting session objects.
-#
-do_test $tn.1.1 { sqlite3session S db main } {S}
-do_test $tn.1.2 { S delete } {}
-do_test $tn.1.3 { sqlite3session S db main } {S}
-do_test $tn.1.4 { S attach t1 } {}
-do_test $tn.1.5 { S delete } {}
-do_test $tn.1.6 { sqlite3session S db main } {S}
-do_test $tn.1.7 { S attach t1 ; S attach t2 ; S attach t3 } {}
-do_test $tn.1.8 { S attach t1 ; S attach t2 ; S attach t3 } {}
-do_test $tn.1.9 { S delete } {}
-do_test $tn.1.10 {
- sqlite3session S db main
- S attach t1
- execsql { INSERT INTO t1 VALUES('ghi', 'jkl') }
-} {}
-do_test $tn.1.11 { S delete } {}
-if {$tn==1} {
- do_test $tn.1.12 {
- sqlite3session S db main
- S attach t1
- execsql { INSERT INTO t1 VALUES('mno', 'pqr') }
- execsql { UPDATE t1 SET x = 111 WHERE rowid = 1 }
- execsql { DELETE FROM t1 WHERE rowid = 2 }
- } {}
- do_test $tn.1.13 {
- S changeset
- S delete
- } {}
-}
-
-#-------------------------------------------------------------------------
-# Simple changeset tests. Also test the sqlite3changeset_invert()
-# function.
-#
-do_test $tn.2.1.1 {
- execsql { DELETE FROM t1 }
- sqlite3session S db main
- S attach t1
- execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') }
- execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') }
- execsql { INSERT INTO t1 VALUES(3, 'Thonburi') }
-} {}
-do_changeset_test $tn.2.1.2 S {
- {INSERT t1 0 X. {} {i 1 t Sukhothai}}
- {INSERT t1 0 X. {} {i 2 t Ayutthaya}}
- {INSERT t1 0 X. {} {i 3 t Thonburi}}
-}
-do_changeset_invert_test $tn.2.1.3 S {
- {DELETE t1 0 X. {i 1 t Sukhothai} {}}
- {DELETE t1 0 X. {i 2 t Ayutthaya} {}}
- {DELETE t1 0 X. {i 3 t Thonburi} {}}
-}
-do_test $tn.2.1.4 { S delete } {}
-
-do_test $tn.2.2.1 {
- sqlite3session S db main
- S attach t1
- execsql { DELETE FROM t1 WHERE 1 }
-} {}
-do_changeset_test $tn.2.2.2 S {
- {DELETE t1 0 X. {i 1 t Sukhothai} {}}
- {DELETE t1 0 X. {i 2 t Ayutthaya} {}}
- {DELETE t1 0 X. {i 3 t Thonburi} {}}
-}
-do_changeset_invert_test $tn.2.2.3 S {
- {INSERT t1 0 X. {} {i 1 t Sukhothai}}
- {INSERT t1 0 X. {} {i 2 t Ayutthaya}}
- {INSERT t1 0 X. {} {i 3 t Thonburi}}
-}
-do_test $tn.2.2.4 { S delete } {}
-
-do_test $tn.2.3.1 {
- execsql { DELETE FROM t1 }
- sqlite3session S db main
- execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') }
- execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') }
- execsql { INSERT INTO t1 VALUES(3, 'Thonburi') }
- S attach t1
- execsql {
- UPDATE t1 SET x = 10 WHERE x = 1;
- UPDATE t1 SET y = 'Surin' WHERE x = 2;
- UPDATE t1 SET x = 20, y = 'Thapae' WHERE x = 3;
- }
-} {}
-
-do_changeset_test $tn.2.3.2 S {
- {INSERT t1 0 X. {} {i 10 t Sukhothai}}
- {DELETE t1 0 X. {i 1 t Sukhothai} {}}
- {UPDATE t1 0 X. {i 2 t Ayutthaya} {{} {} t Surin}}
- {DELETE t1 0 X. {i 3 t Thonburi} {}}
- {INSERT t1 0 X. {} {i 20 t Thapae}}
-}
-
-do_changeset_invert_test $tn.2.3.3 S {
- {DELETE t1 0 X. {i 10 t Sukhothai} {}}
- {INSERT t1 0 X. {} {i 1 t Sukhothai}}
- {UPDATE t1 0 X. {i 2 t Surin} {{} {} t Ayutthaya}}
- {INSERT t1 0 X. {} {i 3 t Thonburi}}
- {DELETE t1 0 X. {i 20 t Thapae} {}}
-}
-do_test $tn.2.3.4 { S delete } {}
-
-do_test $tn.2.4.1 {
- sqlite3session S db main
- S attach t1
- execsql { INSERT INTO t1 VALUES(100, 'Bangkok') }
- execsql { DELETE FROM t1 WHERE x = 100 }
-} {}
-do_changeset_test $tn.2.4.2 S {}
-do_changeset_invert_test $tn.2.4.3 S {}
-do_test $tn.2.4.4 { S delete } {}
-
-#-------------------------------------------------------------------------
-# Test the application of simple changesets. These tests also test that
-# the conflict callback is invoked correctly. For these tests, the
-# conflict callback always returns OMIT.
-#
-db close
-forcedelete test.db test.db2
-sqlite3 db test.db
-sqlite3 db2 test.db2
-
-proc xConflict {args} {
- lappend ::xConflict $args
- return ""
-}
-
-proc bgerror {args} { set ::background_error $args }
-
-proc do_conflict_test {tn args} {
- set O(-tables) [list]
- set O(-sql) [list]
- set O(-conflicts) [list]
-
- array set V $args
- foreach key [array names V] {
- if {![info exists O($key)]} {error "no such option: $key"}
- }
- array set O $args
-
- sqlite3session S db main
- foreach t $O(-tables) { S attach $t }
- execsql $O(-sql)
- set ::xConflict [list]
- sqlite3changeset_apply db2 [S changeset] xConflict
-
- set conflicts [list]
- foreach c $O(-conflicts) {
- lappend conflicts $c
- }
-
- after 1 {set go 1}
- vwait go
-
- uplevel do_test $tn [list { set ::xConflict }] [list $conflicts]
- S delete
-}
-
-proc do_db2_test {testname sql {result {}}} {
- uplevel do_test $testname [list "execsql {$sql} db2"] [list [list {*}$result]]
-}
-
-# Test INSERT changesets.
-#
-do_test $tn.3.1.0 {
- execsql { CREATE TABLE t1(a PRIMARY KEY, b NOT NULL) %WR% } db2
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b) %WR%;
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
- } db
-} {}
-do_db2_test $tn.3.1.1 "INSERT INTO t1 VALUES(6, 'VI')"
-do_conflict_test $tn.3.1.2 -tables t1 -sql {
- INSERT INTO t1 VALUES(3, 'three');
- INSERT INTO t1 VALUES(4, 'four');
- INSERT INTO t1 VALUES(5, 'five');
- INSERT INTO t1 VALUES(6, 'six');
- INSERT INTO t1 VALUES(7, 'seven');
- INSERT INTO t1 VALUES(8, NULL);
-} -conflicts {
- {INSERT t1 CONFLICT {i 6 t six} {i 6 t VI}}
- {INSERT t1 CONSTRAINT {i 8 n {}}}
-}
-
-do_db2_test $tn.3.1.3 "SELECT * FROM t1 ORDER BY a" {
- 3 three 4 four 5 five 6 VI 7 seven
-}
-do_execsql_test $tn.3.1.4 "SELECT * FROM t1" {
- 1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 {}
-}
-
-# Test DELETE changesets.
-#
-do_execsql_test $tn.3.2.1 {
- PRAGMA foreign_keys = on;
- CREATE TABLE t2(a PRIMARY KEY, b)%WR%;
- CREATE TABLE t3(c, d REFERENCES t2);
- INSERT INTO t2 VALUES(1, 'one');
- INSERT INTO t2 VALUES(2, 'two');
- INSERT INTO t2 VALUES(3, 'three');
- INSERT INTO t2 VALUES(4, 'four');
-}
-do_db2_test $tn.3.2.2 {
- PRAGMA foreign_keys = on;
- CREATE TABLE t2(a PRIMARY KEY, b)%WR%;
- CREATE TABLE t3(c, d REFERENCES t2);
- INSERT INTO t2 VALUES(1, 'one');
- INSERT INTO t2 VALUES(2, 'two');
- INSERT INTO t2 VALUES(4, 'five');
- INSERT INTO t3 VALUES('i', 1);
-}
-do_conflict_test $tn.3.2.3 -tables t2 -sql {
- DELETE FROM t2 WHERE a = 1;
- DELETE FROM t2 WHERE a = 2;
- DELETE FROM t2 WHERE a = 3;
- DELETE FROM t2 WHERE a = 4;
-} -conflicts {
- {DELETE t2 NOTFOUND {i 3 t three}}
- {DELETE t2 DATA {i 4 t four} {i 4 t five}}
- {FOREIGN_KEY 1}
-}
-do_execsql_test $tn.3.2.4 "SELECT * FROM t2" {}
-do_db2_test $tn.3.2.5 "SELECT * FROM t2" {4 five}
-
-# Test UPDATE changesets.
-#
-do_execsql_test $tn.3.3.1 {
- CREATE TABLE t4(a, b, c, PRIMARY KEY(b, c))%WR%;
- INSERT INTO t4 VALUES(1, 2, 3);
- INSERT INTO t4 VALUES(4, 5, 6);
- INSERT INTO t4 VALUES(7, 8, 9);
- INSERT INTO t4 VALUES(10, 11, 12);
-}
-do_db2_test $tn.3.3.2 {
- CREATE TABLE t4(a NOT NULL, b, c, PRIMARY KEY(b, c))%WR%;
- INSERT INTO t4 VALUES(0, 2, 3);
- INSERT INTO t4 VALUES(4, 5, 7);
- INSERT INTO t4 VALUES(7, 8, 9);
- INSERT INTO t4 VALUES(10, 11, 12);
-}
-do_conflict_test $tn.3.3.3 -tables t4 -sql {
- UPDATE t4 SET a = -1 WHERE b = 2;
- UPDATE t4 SET a = -1 WHERE b = 5;
- UPDATE t4 SET a = NULL WHERE c = 9;
- UPDATE t4 SET a = 'x' WHERE b = 11;
-} -conflicts {
- {UPDATE t4 DATA {i 1 i 2 i 3} {i -1 {} {} {} {}} {i 0 i 2 i 3}}
- {UPDATE t4 NOTFOUND {i 4 i 5 i 6} {i -1 {} {} {} {}}}
- {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}}
-}
-do_db2_test $tn.3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12}
-do_execsql_test $tn.3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12}
-
-#-------------------------------------------------------------------------
-# This next block of tests verifies that values returned by the conflict
-# handler are intepreted correctly.
-#
-
-proc test_reset {} {
- db close
- db2 close
- forcedelete test.db test.db2
- sqlite3 db test.db
- sqlite3 db2 test.db2
-}
-
-proc xConflict {args} {
- lappend ::xConflict $args
- return $::conflict_return
-}
-
-foreach {tn2 conflict_return after} {
- 1 OMIT {1 2 value1 4 5 7 10 x x}
- 2 REPLACE {1 2 value1 4 5 value2 10 8 9}
-} {
- test_reset
-
- do_test $tn.4.$tn2.1 {
- foreach db {db db2} {
- execsql {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a))%WR%;
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t1 VALUES(7, 8, 9);
- } $db
- }
- execsql {
- REPLACE INTO t1 VALUES(4, 5, 7);
- REPLACE INTO t1 VALUES(10, 'x', 'x');
- } db2
- } {}
-
- do_conflict_test $tn.4.$tn2.2 -tables t1 -sql {
- UPDATE t1 SET c = 'value1' WHERE a = 1; -- no conflict
- UPDATE t1 SET c = 'value2' WHERE a = 4; -- DATA conflict
- UPDATE t1 SET a = 10 WHERE a = 7; -- CONFLICT conflict
- } -conflicts {
- {INSERT t1 CONFLICT {i 10 i 8 i 9} {i 10 t x t x}}
- {UPDATE t1 DATA {i 4 {} {} i 6} {{} {} {} {} t value2} {i 4 i 5 i 7}}
- }
-
- do_db2_test $tn.4.$tn2.3 "SELECT * FROM t1 ORDER BY a" $after
-}
-
-foreach {tn2 conflict_return} {
- 1 OMIT
- 2 REPLACE
-} {
- test_reset
-
- do_test $tn.5.$tn2.1 {
- # Create an identical schema in both databases.
- set schema {
- CREATE TABLE "'foolish name'"(x, y, z, PRIMARY KEY(x, y))%WR%;
- }
- execsql $schema db
- execsql $schema db2
-
- # Add some rows to [db2]. These rows will cause conflicts later
- # on when the changeset from [db] is applied to it.
- execsql {
- INSERT INTO "'foolish name'" VALUES('one', 'one', 'ii');
- INSERT INTO "'foolish name'" VALUES('one', 'two', 'i');
- INSERT INTO "'foolish name'" VALUES('two', 'two', 'ii');
- } db2
-
- } {}
-
- do_conflict_test $tn.5.$tn2.2 -tables {{'foolish name'}} -sql {
- INSERT INTO "'foolish name'" VALUES('one', 'two', 2);
- } -conflicts {
- {INSERT {'foolish name'} CONFLICT {t one t two i 2} {t one t two t i}}
- }
-
- set res(REPLACE) {one one ii one two 2 two two ii}
- set res(OMIT) {one one ii one two i two two ii}
- do_db2_test $tn.5.$tn2.3 {
- SELECT * FROM "'foolish name'" ORDER BY x, y
- } $res($conflict_return)
-
-
- do_test $tn.5.$tn2.1 {
- set schema {
- CREATE TABLE d1("z""z" PRIMARY KEY, y)%WR%;
- INSERT INTO d1 VALUES(1, 'one');
- INSERT INTO d1 VALUES(2, 'two');
- }
- execsql $schema db
- execsql $schema db2
-
- execsql {
- UPDATE d1 SET y = 'TWO' WHERE "z""z" = 2;
- } db2
-
- } {}
-
- do_conflict_test $tn.5.$tn2.2 -tables d1 -sql {
- DELETE FROM d1 WHERE "z""z" = 2;
- } -conflicts {
- {DELETE d1 DATA {i 2 t two} {i 2 t TWO}}
- }
-
- set res(REPLACE) {1 one}
- set res(OMIT) {1 one 2 TWO}
- do_db2_test $tn.5.$tn2.3 "SELECT * FROM d1" $res($conflict_return)
-}
-
-#-------------------------------------------------------------------------
-# Test that two tables can be monitored by a single session object.
-#
-test_reset
-set schema {
- CREATE TABLE t1(a COLLATE nocase PRIMARY KEY, b)%WR%;
- CREATE TABLE t2(a, b PRIMARY KEY)%WR%;
-}
-do_test $tn.6.0 {
- execsql $schema db
- execsql $schema db2
- execsql {
- INSERT INTO t1 VALUES('a', 'b');
- INSERT INTO t2 VALUES('a', 'b');
- } db2
-} {}
-
-set conflict_return ""
-do_conflict_test $tn.6.1 -tables {t1 t2} -sql {
- INSERT INTO t1 VALUES('1', '2');
- INSERT INTO t1 VALUES('A', 'B');
- INSERT INTO t2 VALUES('A', 'B');
-} -conflicts {
- {INSERT t1 CONFLICT {t A t B} {t a t b}}
-}
-
-do_db2_test $tn.6.2 "SELECT * FROM t1 ORDER BY a" {1 2 a b}
-do_db2_test $tn.6.3 "SELECT * FROM t2 ORDER BY a" {A B a b}
-
-#-------------------------------------------------------------------------
-# Test that session objects are not confused by changes to table in
-# other databases.
-#
-catch { db2 close }
-drop_all_tables
-forcedelete test.db2
-do_iterator_test $tn.7.1 * {
- ATTACH 'test.db2' AS aux;
- CREATE TABLE main.t1(x PRIMARY KEY, y)%WR%;
- CREATE TABLE aux.t1(x PRIMARY KEY, y)%WR%;
-
- INSERT INTO main.t1 VALUES('one', 1);
- INSERT INTO main.t1 VALUES('two', 2);
- INSERT INTO aux.t1 VALUES('three', 3);
- INSERT INTO aux.t1 VALUES('four', 4);
-} {
- {INSERT t1 0 X. {} {t two i 2}}
- {INSERT t1 0 X. {} {t one i 1}}
-}
-
-#-------------------------------------------------------------------------
-# Test the sqlite3session_isempty() function.
-#
-do_test $tn.8.1 {
- execsql {
- CREATE TABLE t5(x PRIMARY KEY, y)%WR%;
- CREATE TABLE t6(x PRIMARY KEY, y)%WR%;
- INSERT INTO t5 VALUES('a', 'b');
- INSERT INTO t6 VALUES('a', 'b');
- }
- sqlite3session S db main
- S attach *
-
- S isempty
-} {1}
-do_test $tn.8.2 {
- execsql { DELETE FROM t5 }
- S isempty
-} {0}
-do_test $tn.8.3 {
- S delete
- sqlite3session S db main
- S attach t5
- execsql { DELETE FROM t5 }
- S isempty
-} {1}
-do_test $tn.8.4 { S delete } {}
-
-do_test $tn.8.5 {
- sqlite3session S db main
- S attach t5
- S attach t6
- execsql { INSERT INTO t5 VALUES(1, 2) }
- S isempty
-} {0}
-
-do_test $tn.8.6 {
- S delete
- sqlite3session S db main
- S attach t5
- S attach t6
- execsql { INSERT INTO t6 VALUES(1, 2) }
- S isempty
-} {0}
-do_test $tn.8.7 { S delete } {}
-
-#-------------------------------------------------------------------------
-#
-do_execsql_test $tn.9.1 {
- CREATE TABLE t7(a, b, c, d, e PRIMARY KEY, f, g)%WR%;
- INSERT INTO t7 VALUES(1, 1, 1, 1, 1, 1, 1);
-}
-do_test $tn.9.2 {
- sqlite3session S db main
- S attach *
- execsql { UPDATE t7 SET b=2, d=2 }
-} {}
-do_changeset_test $tn.9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}}
-S delete
-catch { db2 close }
-
-#-------------------------------------------------------------------------
-# Test a really long table name.
-#
-reset_db
-set tblname [string repeat tblname123 100]
-do_test $tn.10.1.1 {
- execsql "
- CREATE TABLE $tblname (a PRIMARY KEY, b)%WR%;
- INSERT INTO $tblname VALUES('xyz', 'def');
- "
- sqlite3session S db main
- S attach $tblname
- execsql "
- INSERT INTO $tblname VALUES('uvw', 'abc');
- DELETE FROM $tblname WHERE a = 'xyz';
- "
-} {}
-do_changeset_test $tn.10.1.2 S "
- {INSERT $tblname 0 X. {} {t uvw t abc}}
- {DELETE $tblname 0 X. {t xyz t def} {}}
-"
-do_test $tn.10.1.4 { S delete } {}
-
-#---------------------------------------------------------------
-reset_db
-do_execsql_test $tn.11.1 {
- CREATE TABLE t1(a, b);
-}
-do_test $tn.11.2 {
- sqlite3session S db main
- S attach t1
- execsql {
- INSERT INTO t1 VALUES(1, 2);
- }
- S changeset
-} {}
-
-S delete
-
-
-#-------------------------------------------------------------------------
-# Test a really long table name.
-#
-reset_db
-set tblname [string repeat tblname123 100]
-do_test $tn.10.1.1 {
- execsql "
- CREATE TABLE $tblname (a PRIMARY KEY, b)%WR%;
- INSERT INTO $tblname VALUES('xyz', 'def');
- "
- sqlite3session S db main
- S attach $tblname
- execsql "
- INSERT INTO $tblname VALUES('uvw', 'abc');
- DELETE FROM $tblname WHERE a = 'xyz';
- "
-} {}
-do_changeset_test $tn.10.1.2 S "
- {INSERT $tblname 0 X. {} {t uvw t abc}}
- {DELETE $tblname 0 X. {t xyz t def} {}}
-"
-do_test $tn.10.1.4 { S delete } {}
-
-#-------------------------------------------------------------------------
-# Test the effect of updating a column from 0.0 to 0.0.
-#
-reset_db
-do_execsql_test $tn.11.1 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b REAL)%WR%;
- INSERT INTO t1 VALUES(1, 0.0);
-}
-do_iterator_test $tn.11.2 * {
- UPDATE t1 SET b = 0.0;
-} {
-}
-
-reset_db
-do_execsql_test $tn.12.1 {
- CREATE TABLE t1(r INTEGER PRIMARY KEY, a, b)%WR%;
- CREATE INDEX i1 ON t1(a);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 1, 2);
- INSERT INTO t1 VALUES(3, 1, 3);
-}
-
-do_iterator_test $tn.12.2 * {
- UPDATE t1 SET b='one' WHERE a=1;
-} {
- {UPDATE t1 0 X.. {i 1 {} {} i 1} {{} {} {} {} t one}}
- {UPDATE t1 0 X.. {i 2 {} {} i 2} {{} {} {} {} t one}}
- {UPDATE t1 0 X.. {i 3 {} {} i 3} {{} {} {} {} t one}}
-}
-
-#-------------------------------------------------------------------------
-# Test that no savepoint is used if -nosavepoint is specified.
-#
-do_execsql_test $tn.13.1 {
- CREATE TABLE x1(a INTEGER PRIMARY KEY, b)%WR%;
-}
-do_test $tn.13.2 {
- execsql BEGIN
- set C [changeset_from_sql {
- INSERT INTO x1 VALUES(1, 'one');
- INSERT INTO x1 VALUES(2, 'two');
- INSERT INTO x1 VALUES(3, 'three');
- }]
- execsql ROLLBACK
- execsql {
- INSERT INTO x1 VALUES(1, 'i');
- INSERT INTO x1 VALUES(2, 'ii');
- INSERT INTO x1 VALUES(3, 'iii');
- }
-} {}
-
-proc xConflict {args} {
- set ret [lindex $::CONFLICT_HANDLERS 0]
- set ::CONFLICT_HANDLERS [lrange $::CONFLICT_HANDLERS 1 end]
- set ret
-}
-do_test $tn.13.3 {
- set CONFLICT_HANDLERS [list REPLACE REPLACE ABORT]
- execsql BEGIN
- catch { sqlite3changeset_apply_v2 db $C xConflict } msg
- execsql {
- SELECT * FROM x1
- }
-} {1 i 2 ii 3 iii}
-do_test $tn.13.3 {
- set CONFLICT_HANDLERS [list REPLACE REPLACE ABORT]
- execsql ROLLBACK
- execsql BEGIN
- catch { sqlite3changeset_apply_v2 -nosavepoint db $C xConflict } msg
- execsql { SELECT * FROM x1 }
-} {1 one 2 two 3 iii}
-execsql ROLLBACK
-
-}]
-}
-
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session2.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session2.test
deleted file mode 100644
index cd8c2869e79..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session2.test
+++ /dev/null
@@ -1,591 +0,0 @@
-# 2011 Mar 16
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the session module.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix session2
-
-proc test_reset {} {
- catch { db close }
- catch { db2 close }
- forcedelete test.db test.db2
- sqlite3 db test.db
- sqlite3 db2 test.db2
-}
-
-##########################################################################
-# End of proc definitions. Start of tests.
-##########################################################################
-
-test_reset
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES('i', 'one');
-}
-do_iterator_test 1.1 t1 {
- DELETE FROM t1 WHERE a = 'i';
- INSERT INTO t1 VALUES('ii', 'two');
-} {
- {DELETE t1 0 X. {t i t one} {}}
- {INSERT t1 0 X. {} {t ii t two}}
-}
-
-do_iterator_test 1.2 t1 {
- INSERT INTO t1 VALUES(1.5, 99.9)
-} {
- {INSERT t1 0 X. {} {f 1.5 f 99.9}}
-}
-
-do_iterator_test 1.3 t1 {
- UPDATE t1 SET b = 100.1 WHERE a = 1.5;
- UPDATE t1 SET b = 99.9 WHERE a = 1.5;
-} { }
-
-do_iterator_test 1.4 t1 {
- UPDATE t1 SET b = 100.1 WHERE a = 1.5;
-} {
- {UPDATE t1 0 X. {f 1.5 f 99.9} {{} {} f 100.1}}
-}
-
-
-# Execute each of the following blocks of SQL on database [db1]. Collect
-# changes using a session object. Apply the resulting changeset to
-# database [db2]. Then check that the contents of the two databases are
-# identical.
-#
-
-set set_of_tests {
- 1 { INSERT INTO %T1% VALUES(1, 2) }
-
- 2 {
- INSERT INTO %T2% VALUES(1, NULL);
- INSERT INTO %T2% VALUES(2, NULL);
- INSERT INTO %T2% VALUES(3, NULL);
- DELETE FROM %T2% WHERE a = 2;
- INSERT INTO %T2% VALUES(4, NULL);
- UPDATE %T2% SET b=0 WHERE b=1;
- }
-
- 3 { INSERT INTO %T3% SELECT *, NULL FROM %T2% }
-
- 4 {
- INSERT INTO %T3% SELECT a||a, b||b, NULL FROM %T3%;
- DELETE FROM %T3% WHERE rowid%2;
- }
-
- 5 { UPDATE %T3% SET c = a||b }
-
- 6 { UPDATE %T1% SET a = 32 }
-
- 7 {
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- DELETE FROM %T1% WHERE (rowid%3)==0;
- }
-
- 8 {
- BEGIN;
- INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
- ROLLBACK;
- }
- 9 {
- BEGIN;
- UPDATE %T1% SET b = 'xxx';
- ROLLBACK;
- }
- 10 {
- BEGIN;
- DELETE FROM %T1% WHERE 1;
- ROLLBACK;
- }
- 11 {
- INSERT INTO %T1% VALUES(randomblob(21000), randomblob(0));
- INSERT INTO %T1% VALUES(1.5, 1.5);
- INSERT INTO %T1% VALUES(4.56, -99.999999999999999999999);
- }
- 12 {
- INSERT INTO %T2% VALUES(NULL, NULL);
- }
-
- 13 {
- DELETE FROM %T1% WHERE 1;
-
- -- Insert many rows with real primary keys. Enough to force the session
- -- objects hash table to resize.
- INSERT INTO %T1% VALUES(0.1, 0.1);
- INSERT INTO %T1% SELECT a+0.1, b+0.1 FROM %T1%;
- INSERT INTO %T1% SELECT a+0.2, b+0.2 FROM %T1%;
- INSERT INTO %T1% SELECT a+0.4, b+0.4 FROM %T1%;
- INSERT INTO %T1% SELECT a+0.8, b+0.8 FROM %T1%;
- INSERT INTO %T1% SELECT a+1.6, b+1.6 FROM %T1%;
- INSERT INTO %T1% SELECT a+3.2, b+3.2 FROM %T1%;
- INSERT INTO %T1% SELECT a+6.4, b+6.4 FROM %T1%;
- INSERT INTO %T1% SELECT a+12.8, b+12.8 FROM %T1%;
- INSERT INTO %T1% SELECT a+25.6, b+25.6 FROM %T1%;
- INSERT INTO %T1% SELECT a+51.2, b+51.2 FROM %T1%;
- INSERT INTO %T1% SELECT a+102.4, b+102.4 FROM %T1%;
- INSERT INTO %T1% SELECT a+204.8, b+204.8 FROM %T1%;
- }
-
- 14 {
- DELETE FROM %T1% WHERE 1;
- }
-
- 15 {
- INSERT INTO %T1% VALUES(1, 1);
- INSERT INTO %T1% SELECT a+2, b+2 FROM %T1%;
- INSERT INTO %T1% SELECT a+4, b+4 FROM %T1%;
- INSERT INTO %T1% SELECT a+8, b+8 FROM %T1%;
- INSERT INTO %T1% SELECT a+256, b+256 FROM %T1%;
- }
-
- 16 {
- INSERT INTO %T4% VALUES('abc', 'def');
- INSERT INTO %T4% VALUES('def', 'abc');
- }
- 17 { UPDATE %T4% SET b = 1 }
-
- 18 { DELETE FROM %T4% WHERE 1 }
-
- 19 {
- INSERT INTO t1 VALUES('', '');
- INSERT INTO t1 VALUES(X'', X'');
- }
- 20 {
- DELETE FROM t1;
- INSERT INTO t1 VALUES('', NULL);
- }
-}
-
-test_reset
-do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
- CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
- CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
-}
-
-foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3 %T4% t4} $set_of_tests] {
- do_then_apply_sql $sql
- do_test 2.$tn { compare_db db db2 } {}
-}
-
-# The following block of tests is similar to the last, except that the
-# session object is recording changes made to an attached database. The
-# main database contains a table of the same name as the table being
-# modified within the attached db.
-#
-test_reset
-forcedelete test.db3
-sqlite3 db3 test.db3
-do_test 3.0 {
- execsql {
- ATTACH 'test.db3' AS 'aux';
- CREATE TABLE t1(a, b PRIMARY KEY);
- CREATE TABLE t2(x, y, z);
- CREATE TABLE t3(a);
-
- CREATE TABLE aux.t1(a PRIMARY KEY, b);
- CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY);
- CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b));
- CREATE TABLE aux.t4(a, b, PRIMARY KEY(b, a));
- }
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
- CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
- CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
- } db2
-} {}
-
-proc xTrace {args} { puts $args }
-
-foreach {tn sql} [
- string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3 %T4% aux.t4} $set_of_tests
-] {
- do_then_apply_sql $sql aux
- do_test 3.$tn { compare_db db2 db3 } {}
-}
-catch {db3 close}
-
-
-#-------------------------------------------------------------------------
-# The following tests verify that NULL values in primary key columns are
-# handled correctly by the session module.
-#
-test_reset
-do_execsql_test 4.0 {
- CREATE TABLE t1(a PRIMARY KEY);
- CREATE TABLE t2(a, b, c, PRIMARY KEY(c, b));
- CREATE TABLE t3(a, b INTEGER PRIMARY KEY);
-}
-
-foreach {tn sql changeset} {
- 1 {
- INSERT INTO t1 VALUES(123);
- INSERT INTO t1 VALUES(NULL);
- INSERT INTO t1 VALUES(456);
- } {
- {INSERT t1 0 X {} {i 456}}
- {INSERT t1 0 X {} {i 123}}
- }
-
- 2 {
- UPDATE t1 SET a = NULL;
- } {
- {DELETE t1 0 X {i 456} {}}
- {DELETE t1 0 X {i 123} {}}
- }
-
- 3 { DELETE FROM t1 } { }
-
- 4 {
- INSERT INTO t3 VALUES(NULL, NULL)
- } {
- {INSERT t3 0 .X {} {n {} i 1}}
- }
-
- 5 { INSERT INTO t2 VALUES(1, 2, NULL) } { }
- 6 { INSERT INTO t2 VALUES(1, NULL, 3) } { }
- 7 { INSERT INTO t2 VALUES(1, NULL, NULL) } { }
- 8 { INSERT INTO t2 VALUES(1, 2, 3) } { {INSERT t2 0 .XX {} {i 1 i 2 i 3}} }
- 9 { DELETE FROM t2 WHERE 1 } { {DELETE t2 0 .XX {i 1 i 2 i 3} {}} }
-
-} {
- do_iterator_test 4.$tn {t1 t2 t3} $sql $changeset
-}
-
-
-#-------------------------------------------------------------------------
-# Test that if NULL is passed to sqlite3session_attach(), all database
-# tables are attached to the session object.
-#
-test_reset
-do_execsql_test 5.0 {
- CREATE TABLE t1(a PRIMARY KEY);
- CREATE TABLE t2(x, y PRIMARY KEY);
-}
-
-foreach {tn sql changeset} {
- 1 { INSERT INTO t1 VALUES(35) } { {INSERT t1 0 X {} {i 35}} }
- 2 { INSERT INTO t2 VALUES(36, 37) } { {INSERT t2 0 .X {} {i 36 i 37}} }
- 3 {
- DELETE FROM t1 WHERE 1;
- UPDATE t2 SET x = 34;
- } {
- {DELETE t1 0 X {i 35} {}}
- {UPDATE t2 0 .X {i 36 i 37} {i 34 {} {}}}
- }
-} {
- do_iterator_test 5.$tn * $sql $changeset
-}
-
-#-------------------------------------------------------------------------
-# The next block of tests verify that the "indirect" flag is set
-# correctly within changesets. The indirect flag is set for a change
-# if either of the following are true:
-#
-# * The sqlite3session_indirect() API has been used to set the session
-# indirect flag to true, or
-# * The change was made by a trigger.
-#
-# If the same row is updated more than once during a session, then the
-# change is considered indirect only if all changes meet the criteria
-# above.
-#
-test_reset
-db function indirect [list S indirect]
-
-do_execsql_test 6.0 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
-
- CREATE TABLE t2(x PRIMARY KEY, y);
- CREATE TRIGGER AFTER INSERT ON t2 WHEN new.x%2 BEGIN
- INSERT INTO t2 VALUES(new.x+1, NULL);
- END;
-}
-
-do_iterator_test 6.1.1 * {
- INSERT INTO t1 VALUES(1, 'one', 'i');
- SELECT indirect(1);
- INSERT INTO t1 VALUES(2, 'two', 'ii');
- SELECT indirect(0);
- INSERT INTO t1 VALUES(3, 'three', 'iii');
-} {
- {INSERT t1 0 X.. {} {i 1 t one t i}}
- {INSERT t1 1 X.. {} {i 2 t two t ii}}
- {INSERT t1 0 X.. {} {i 3 t three t iii}}
-}
-
-do_iterator_test 6.1.2 * {
- SELECT indirect(1);
- UPDATE t1 SET c = 'I' WHERE a = 1;
- SELECT indirect(0);
-} {
- {UPDATE t1 1 X.. {i 1 {} {} t i} {{} {} {} {} t I}}
-}
-do_iterator_test 6.1.3 * {
- SELECT indirect(1);
- UPDATE t1 SET c = '.' WHERE a = 1;
- SELECT indirect(0);
- UPDATE t1 SET c = 'o' WHERE a = 1;
-} {
- {UPDATE t1 0 X.. {i 1 {} {} t I} {{} {} {} {} t o}}
-}
-do_iterator_test 6.1.4 * {
- SELECT indirect(0);
- UPDATE t1 SET c = 'x' WHERE a = 1;
- SELECT indirect(1);
- UPDATE t1 SET c = 'i' WHERE a = 1;
-} {
- {UPDATE t1 0 X.. {i 1 {} {} t o} {{} {} {} {} t i}}
-}
-do_iterator_test 6.1.4 * {
- SELECT indirect(1);
- UPDATE t1 SET c = 'y' WHERE a = 1;
- SELECT indirect(1);
- UPDATE t1 SET c = 'I' WHERE a = 1;
-} {
- {UPDATE t1 1 X.. {i 1 {} {} t i} {{} {} {} {} t I}}
-}
-
-do_iterator_test 6.1.5 * {
- INSERT INTO t2 VALUES(1, 'x');
-} {
- {INSERT t2 0 X. {} {i 1 t x}}
- {INSERT t2 1 X. {} {i 2 n {}}}
-}
-
-do_iterator_test 6.1.6 * {
- SELECT indirect(1);
- INSERT INTO t2 VALUES(3, 'x');
- SELECT indirect(0);
- UPDATE t2 SET y = 'y' WHERE x>2;
-} {
- {INSERT t2 0 X. {} {i 3 t y}}
- {INSERT t2 0 X. {} {i 4 t y}}
-}
-
-do_iterator_test 6.1.7 * {
- SELECT indirect(1);
- DELETE FROM t2 WHERE x = 4;
- SELECT indirect(0);
- INSERT INTO t2 VALUES(4, 'new');
-} {
- {UPDATE t2 0 X. {i 4 t y} {{} {} t new}}
-}
-
-do_iterator_test 6.1.8 * {
- CREATE TABLE t3(a, b PRIMARY KEY);
- CREATE TABLE t4(a, b PRIMARY KEY);
- CREATE TRIGGER t4t AFTER UPDATE ON t4 BEGIN
- UPDATE t3 SET a = new.a WHERE b = new.b;
- END;
-
- SELECT indirect(1);
- INSERT INTO t3 VALUES('one', 1);
- INSERT INTO t4 VALUES('one', 1);
- SELECT indirect(0);
- UPDATE t4 SET a = 'two' WHERE b = 1;
-} {
- {INSERT t3 1 .X {} {t two i 1}}
- {INSERT t4 0 .X {} {t two i 1}}
-}
-
-sqlite3session S db main
-do_execsql_test 6.2.1 {
- SELECT indirect(0);
- SELECT indirect(-1);
- SELECT indirect(45);
- SELECT indirect(-100);
-} {0 0 1 1}
-S delete
-
-#-------------------------------------------------------------------------
-# Test that if a conflict-handler that has been passed either NOTFOUND or
-# CONSTRAINT returns REPLACE - the sqlite3changeset_apply() call returns
-# MISUSE and rolls back any changes made so far.
-#
-# 7.1.*: NOTFOUND conflict-callback.
-# 7.2.*: CONSTRAINT conflict-callback.
-#
-proc xConflict {args} {return REPLACE}
-test_reset
-
-do_execsql_test 7.1.1 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
-}
-do_test 7.1.2 {
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b NOT NULL);
- INSERT INTO t1 VALUES(1, 'one');
- } db2
-} {}
-do_test 7.1.3 {
- set changeset [changeset_from_sql {
- UPDATE t1 SET b = 'five' WHERE a = 1;
- UPDATE t1 SET b = 'six' WHERE a = 2;
- }]
- set x [list]
- sqlite3session_foreach c $changeset { lappend x $c }
- set x
-} [list \
- {UPDATE t1 0 X. {i 1 t one} {{} {} t five}} \
- {UPDATE t1 0 X. {i 2 t two} {{} {} t six}} \
-]
-do_test 7.1.4 {
- list [catch {sqlite3changeset_apply db2 $changeset xConflict} msg] $msg
-} {1 SQLITE_MISUSE}
-do_test 7.1.5 { execsql { SELECT * FROM t1 } db2 } {1 one}
-
-do_test 7.2.1 {
- set changeset [changeset_from_sql { UPDATE t1 SET b = NULL WHERE a = 1 }]
-
- set x [list]
- sqlite3session_foreach c $changeset { lappend x $c }
- set x
-} [list \
- {UPDATE t1 0 X. {i 1 t five} {{} {} n {}}} \
-]
-do_test 7.2.2 {
- list [catch {sqlite3changeset_apply db2 $changeset xConflict} msg] $msg
-} {1 SQLITE_MISUSE}
-do_test 7.2.3 { execsql { SELECT * FROM t1 } db2 } {1 one}
-
-#-------------------------------------------------------------------------
-# Test that if a conflict-handler returns ABORT, application of the
-# changeset is rolled back and the sqlite3changeset_apply() method returns
-# SQLITE_ABORT.
-#
-# Also test that the same thing happens if a conflict handler returns an
-# unrecognized integer value. Except, in this case SQLITE_MISUSE is returned
-# instead of SQLITE_ABORT.
-#
-foreach {tn conflict_return apply_return} {
- 1 ABORT SQLITE_ABORT
- 2 567 SQLITE_MISUSE
-} {
- test_reset
- proc xConflict {args} [list return $conflict_return]
-
- do_test 8.$tn.0 {
- do_common_sql {
- CREATE TABLE t1(x, y, PRIMARY KEY(x, y));
- INSERT INTO t1 VALUES('x', 'y');
- }
- execsql { INSERT INTO t1 VALUES('w', 'w') }
-
- set changeset [changeset_from_sql { DELETE FROM t1 WHERE 1 }]
-
- set x [list]
- sqlite3session_foreach c $changeset { lappend x $c }
- set x
- } [list \
- {DELETE t1 0 XX {t w t w} {}} \
- {DELETE t1 0 XX {t x t y} {}} \
- ]
-
- do_test 8.$tn.1 {
- list [catch {sqlite3changeset_apply db2 $changeset xConflict} msg] $msg
- } [list 1 $apply_return]
-
- do_test 8.$tn.2 {
- execsql {SELECT * FROM t1} db2
- } {x y}
-}
-
-
-#-------------------------------------------------------------------------
-# Try to cause an infinite loop as follows:
-#
-# 1. Have a changeset insert a row that causes a CONFLICT callback,
-# 2. Have the conflict handler return REPLACE,
-# 3. After the session module deletes the conflicting row, have a trigger
-# re-insert it.
-# 4. Goto step 1...
-#
-# This doesn't work, as the second invocation of the conflict handler is a
-# CONSTRAINT, not a CONFLICT. There is at most one CONFLICT callback for
-# each change in the changeset.
-#
-test_reset
-proc xConflict {type args} {
- if {$type == "CONFLICT"} { return REPLACE }
- return OMIT
-}
-do_test 9.1 {
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- }
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES('x', 2);
- CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN
- INSERT INTO t1 VALUES(old.a, old.b);
- END;
- } db2
-} {}
-do_test 9.2 {
- set changeset [changeset_from_sql { INSERT INTO t1 VALUES('x', 1) }]
- sqlite3changeset_apply db2 $changeset xConflict
-} {}
-do_test 9.3 {
- execsql { SELECT * FROM t1 } db2
-} {x 2}
-
-#-------------------------------------------------------------------------
-#
-test_reset
-db function enable [list S enable]
-
-do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES('x', 'X');
-}
-
-do_iterator_test 10.1 t1 {
- INSERT INTO t1 VALUES('y', 'Y');
- SELECT enable(0);
- INSERT INTO t1 VALUES('z', 'Z');
- SELECT enable(1);
-} {
- {INSERT t1 0 X. {} {t y t Y}}
-}
-
-sqlite3session S db main
-do_execsql_test 10.2 {
- SELECT enable(0);
- SELECT enable(-1);
- SELECT enable(1);
- SELECT enable(-1);
-} {0 0 1 1}
-S delete
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session3.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session3.test
deleted file mode 100644
index ba316348ef2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session3.test
+++ /dev/null
@@ -1,214 +0,0 @@
-# 2011 March 24
-#
-# 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 regression tests for the session module. More
-# specifically, it focuses on testing the session modules response to
-# database schema modifications and mismatches.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix session3
-
-#-------------------------------------------------------------------------
-# These tests - session3-1.* - verify that the session module behaves
-# correctly when confronted with a schema mismatch when applying a
-# changeset (in function sqlite3changeset_apply()).
-#
-# session3-1.1.*: Table does not exist in target db.
-# session3-1.2.*: Table has wrong number of columns in target db.
-# session3-1.3.*: Table has wrong PK columns in target db.
-#
-db close
-sqlite3_shutdown
-test_sqlite3_log log
-sqlite3 db test.db
-
-proc log {code msg} { lappend ::log $code $msg }
-
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b);
-}
-do_test 1.1 {
- set ::log {}
- do_then_apply_sql {
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t1 VALUES(3, 4);
- }
- set ::log
-} {SQLITE_SCHEMA {sqlite3changeset_apply(): no such table: t1}}
-
-do_test 1.2.0 {
- execsql { CREATE TABLE t1(a PRIMARY KEY, b, c) } db2
-} {}
-do_test 1.2.1 {
- set ::log {}
- do_then_apply_sql {
- INSERT INTO t1 VALUES(5, 6);
- INSERT INTO t1 VALUES(7, 8);
- }
- set ::log
-} {}
-do_test 1.2.2 {
- db2 eval { SELECT * FROM t1 }
-} {5 6 {} 7 8 {}}
-
-do_test 1.3.0 {
- execsql {
- DROP TABLE t1;
- CREATE TABLE t1(a, b PRIMARY KEY);
- } db2
-} {}
-do_test 1.3.1 {
- set ::log {}
- do_then_apply_sql {
- INSERT INTO t1 VALUES(9, 10);
- INSERT INTO t1 VALUES(11, 12);
- }
- set ::log
-} {SQLITE_SCHEMA {sqlite3changeset_apply(): primary key mismatch for table t1}}
-
-#-------------------------------------------------------------------------
-# These tests - session3-2.* - verify that the session module behaves
-# correctly when the schema of an attached table is modified during the
-# session.
-#
-# session3-2.1.*: Table is dropped midway through the session.
-# session3-2.2.*: Table is dropped and recreated with a different # cols.
-# session3-2.3.*: Table is dropped and recreated with a different PK.
-#
-# In all of these scenarios, the call to sqlite3session_changeset() will
-# return SQLITE_SCHEMA. Also:
-#
-# session3-2.4.*: Table is dropped and recreated with an identical schema.
-# In this case sqlite3session_changeset() returns SQLITE_OK.
-#
-
-do_test 2.1 {
- execsql { CREATE TABLE t2(a, b PRIMARY KEY) }
- sqlite3session S db main
- S attach t2
- execsql {
- INSERT INTO t2 VALUES(1, 2);
- DROP TABLE t2;
- }
- list [catch { S changeset } msg] $msg
-} {1 SQLITE_SCHEMA}
-
-do_test 2.2.1 {
- S delete
- sqlite3session S db main
- execsql { CREATE TABLE t2(a, b PRIMARY KEY, c) }
- S attach t2
- execsql {
- INSERT INTO t2 VALUES(1, 2, 3);
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY);
- }
- list [catch { S changeset } msg] $msg
-} {1 SQLITE_SCHEMA}
-do_test 2.2.2 {
- S delete
- sqlite3session S db main
- execsql {
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY, c);
- }
- S attach t2
- execsql {
- INSERT INTO t2 VALUES(1, 2, 3);
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY, c, d);
- }
- list [catch { S changeset } msg] $msg
-} {1 SQLITE_SCHEMA}
-do_test 2.2.3 {
- S delete
- sqlite3session S db main
- execsql {
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY, c);
- }
- S attach t2
- execsql {
- INSERT INTO t2 VALUES(1, 2, 3);
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY);
- INSERT INTO t2 VALUES(4, 5);
- }
- list [catch { S changeset } msg] $msg
-} {1 SQLITE_SCHEMA}
-do_test 2.2.4 {
- S delete
- sqlite3session S db main
- execsql {
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY, c);
- }
- S attach t2
- execsql {
- INSERT INTO t2 VALUES(1, 2, 3);
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY, c, d);
- INSERT INTO t2 VALUES(4, 5, 6, 7);
- }
- list [catch { S changeset } msg] $msg
-} {1 SQLITE_SCHEMA}
-
-do_test 2.3 {
- S delete
- sqlite3session S db main
- execsql {
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY);
- }
- S attach t2
- execsql {
- INSERT INTO t2 VALUES(1, 2);
- DROP TABLE t2;
- CREATE TABLE t2(a PRIMARY KEY, b);
- }
- list [catch { S changeset } msg] $msg
-} {1 SQLITE_SCHEMA}
-
-do_test 2.4 {
- S delete
- sqlite3session S db main
- execsql {
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY);
- }
- S attach t2
- execsql {
- INSERT INTO t2 VALUES(1, 2);
- DROP TABLE t2;
- CREATE TABLE t2(a, b PRIMARY KEY);
- }
- list [catch { S changeset } msg] $msg
-} {0 {}}
-
-S delete
-
-
-catch { db close }
-catch { db2 close }
-sqlite3_shutdown
-test_sqlite3_log
-sqlite3_initialize
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session4.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session4.test
deleted file mode 100644
index de183a69a0a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session4.test
+++ /dev/null
@@ -1,146 +0,0 @@
-# 2011 March 25
-#
-# 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 regression tests for the session module.
-#
-
-package require Tcl 8.6
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix session4
-
-do_test 1.0 {
- execsql {
- CREATE TABLE x(a, b, c, d, e, PRIMARY KEY(c, e));
- INSERT INTO x VALUES(65.21, X'28B0', 16.35, NULL, 'doers');
- INSERT INTO x VALUES(NULL, 78.49, 2, X'60', -66);
- INSERT INTO x VALUES('cathedral', NULL, 35, NULL, X'B220937E80A2D8');
- INSERT INTO x VALUES(NULL, 'masking', -91.37, NULL, X'596D');
- INSERT INTO x VALUES(19, 'domains', 'espouse', -94, 'throw');
- }
-
- set changeset [changeset_from_sql {
- DELETE FROM x WHERE e = -66;
- UPDATE x SET a = 'parameterizable', b = 31.8 WHERE c = 35;
- INSERT INTO x VALUES(-75.61, -17, 16.85, NULL, X'D73DB02678');
- }]
- set {} {}
-} {}
-
-
-# This currently causes crashes. sqlite3changeset_invert() does not handle
-# corrupt changesets well.
-if 0 {
- do_test 1.1 {
- for {set i 0} {$i < [string length $changeset]} {incr i} {
- set before [string range $changeset 0 [expr $i-1]]
- set after [string range $changeset [expr $i+1] end]
- for {set j 10} {$j < 260} {incr j} {
- set x [binary format "a*ca*" $before $j $after]
- catch { sqlite3changeset_invert $x }
- }
- }
- } {}
-}
-
-do_test 1.2 {
- set x [binary format "ca*" 0 [string range $changeset 1 end]]
- list [catch { sqlite3changeset_invert $x } msg] $msg
-} {1 SQLITE_CORRUPT}
-
-do_test 1.3 {
- set x [binary format "ca*" 0 [string range $changeset 1 end]]
- list [catch { sqlite3changeset_apply db $x xConflict } msg] $msg
-} {1 SQLITE_CORRUPT}
-
-#-------------------------------------------------------------------------
-reset_db
-do_execsql_test 2.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d);
- CREATE TABLE t2(e TEXT PRIMARY KEY NOT NULL,f,g);
- CREATE TABLE t3(w REAL PRIMARY KEY NOT NULL,x,y);
- CREATE TABLE t4(z PRIMARY KEY) WITHOUT ROWID;
-}
-
-foreach {tn blob} {
- 1 54010174340012000000
- 2 54fefe8bcb0012000300
- 3 5480809280808001017434001200fb
- 4 50af9c939c9c9cb09c9c6400b09c9c6400
- 5 12000300
- 6 09847304
- 7 5401017434001208
- 8 54010174340012fc0386868600
- 9 54010174340012FC0386868600
- 10 548894FEFE
- 11 54010171340012E703ABFA7433FD1200
- 12 540101743400120003FFED00010000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
- 13 540101743400120003001200010000000000000002120002400C0000000000005404010000007431001700010000000000000005010000000000000003010000000000000004000001000000000000000401000000000000000300170001000000000000000703FC87797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
- 14 540101743400120003001200010000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F03FC87797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
- 15 540101743400120003001200010000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A005403010000743200090003FC8738790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
- 16 540101743400120003001200010000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A00540301000074320009000303783879010000000080000000020000000000000000090003FC87327902400C0000000000000304666F7572
- 17 540101743400120003FFE3000412F7010000E600000000021202120002400C0000000000005B0401000000743100171C0304646F750002400C000000000000540401000000D3310017000100000000000000050100000000000378797A405403000002F10100000100000000000004090001000100000007030378797A0100000000000D0007000001000000002300000F1B0378797A405403013900743200090003038C3879010000000000000000000002120002400C0000000000005B0401000000743117170003047C5E00FF
- 18 54010174340012000300120001000000E6FF100000120002401E00000000000054040100000074310017000100040000010000000000000004FFFF7FFF0000000000010000010000001000000007030378797A01000000000000000F000000000000FA0304666F7572
- 19 540101743400120003001200010000000000000002121B02400C00000000000054040000000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378817A01000000000000000F000001000000000100000F030378797A005403010000743200090003FFE809000303780000000000000304666F7572
- 20 5401017D3400120003001200010000000000000002120002400CFC00000000005404010000007431001700010000000000000005010000000000000003010000000000000004000001000000000000000401000000000000000300170001000000000000000703FFFF797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378326C02400C0000000000000304666F7572
- 21 5401017434001200030012000100FFE20000000002120002400C00000000000054040100E0007431001700010000E99D000000020000000003FFE70009000303783279020004000001030000000000002117000003001700012701000100000000743100000100000000008000090003037F387901000000008000000002000000000400000009005303010A00FF7FFFFF00000000000304664F6572
- 22 540101743400120003FFFF7FFF0000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100010000000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
- 23 540101742700120100120003F5FF0300
- 24 5401017434E312540101743400120003FFFC00
- 25 540101743400540101743D3D3D3D3D3D3D3D3D3D3D3D3D3400120003FFED000300
- 26 5401017446EA5301743D1D3D3D01743D1D3D3DCF3D3D3D1A3D3D3D3D3400120003FFFF000000
- 27 540101743400540101743D3D3D3D3D3D3D3D3D3D251000120003FF81000000000000
- 28 540101340012000397FF3D7F3D3400120003001200540101743D3D3D3D3D3D393D3D3D12000300
- 29 500174340050010F74340012000300120003FFE5
- 30 5004007233E900177FEF0054257F0002EF001200031E12000300
- 31 5001015001015252525250010174340012EF039A9A0100E351525D52525252525252525252525252525252525250010174340012EF039A0100009A9A9A9A9A9BA3B200120003010040743400
- 32 5401017400123400120003FFFC00
- 33 540101743400120003001200010000000000004002120002400C0000000000005404010000007431001700010000000000000005010000000000000003010000000000000004000001000000000000000401000000000000000300170001000000000000000703FC87797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
- 34 54040100000074310017000100000002000015050100000000000000030100000000140000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A0054030100007432000900030378387901000000008E000000020000000000000000090003FFFF000002400C0000000000000304666F7572
- 35 540101743400120003001200010000000000000002120002400C00000000000050060100000074310017000100000000000000050100000000000000030100000003001700010000666F7572
- 36 540101743400120003001200010000000000000002120002400C00000000000050050100000074310017000100000000000000050100000000000000030100000003001700010000666F7572
- 37 540101743400120003001200010000000000000002120002400C00000000000050040100008074310017000100000000000000050100000000000000030100000003001700010000666F7572
- 38 540101743400120003001200010000000000000002120002400C00000000000050040100000074310017000000000000000000050100000000000000030100000003001700010000666F7572
- 39 540101743400120003001200010000000000000002120002400C00000000000050040100018074310017000100000000000000050100000000000000030100000003001700010000666F7572
- 40 540101743400120003001200010000000000000002120002400C0000000000005004FEFFFFFF74310017000100000000000000050100000000000000030100000003001700010000666F7572
- 41 540101743400120003001200010000000000000002120002400C00000000000050040100000074310017000004000000000000050100000000000000030100000003001700010000666F7572
- 42 540101743400120003001200010000000000000002120002400C0000000000005005FFFF050074310017000100000000000000050100000000000000030100000003001700010000666F7572
- 43 540101743400120003001200010000000000000002120002400C000000000000500401006E0074310017000300000000001221050100000000000000030100000003001700010000666F7572
- 44 540101743400120003001200010000000000020000120002400C00000000000050050100000074310017000100000000000000050100004000000000030100000025001700010000666F7572
- 45 540101743400120003001200010000000000ECFF02120002400C000000000000500401F9FF00743100170001000000000000000500E1000000000000030100000003000000000000666F7572
- 46 54010174340B0B0B0B0B0B0B0B0B0B0B0B0B0B0B00120003001200010000000000000002120002400C00000000000050040100000074310017010000000000000000050100FFE900000000030100000003007F00000000666F7572
- 47 54010103001200010000000000020002120002400C0000000000005004010000F374310017000100000000000000050100000000000000030100000003001700010000666F8E72
- 48 540101743400120003001200010000000000000002120002400C00000000000050030012000174310017000700000000000000050100002000000001000000000003001700010000666F7572
- 49 540101743400120004001200010000000000000002120002400C0000000000005004010000FC733100170001000000000000000501000000000000000301000000F6FF17000100007C6F7572
- 50 54010174FFDDFF8003001200010000100000000002120002400C000000000000500401000000743100170000000005010000000000000000000003010072
- 51 540101743200120003001200010000000000000002120002400C00000000000050040100001074310017000000000003010000120300170100000000000000050100000000000000030100000003001700010000666F7572
- 52 540101745401017434001200010000000000001702120002400C00000000000050040100001A74310017000100000000000100000100000000000000030100000003001700010000666F7572
- 53 540101743400120003001200010000000000000002120002400C000000000000500401000000743100170001000002400C00000000000050040110000074310017000000000000050100000000000000030100000003001700010000666F7572
- 54 540101743400120003001200010000000000000002120002400C000000000002120002400C00000000000050040100000074310017FF0050040100000074310017FF7F00000000000000050100000000000000030100000003001700010000666F7572
- 55 540101743400120003001200010000000000000002120002400C00000000000050040100000074310017000100010080000001000000020003010100000300170100000003001700010000666F7572
- 56 5487ffffff7f
-} {
- do_test 2.$tn {
- set changeset [binary decode hex $blob]
-#set fd [open x.change w+]
-#fconfigure $fd -encoding binary -translation binary
-#puts -nonewline $fd $changeset
-#close $fd
- list [catch { sqlite3changeset_apply db $changeset xConflict } msg] $msg
- } {1 SQLITE_CORRUPT}
-}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session5.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session5.test
deleted file mode 100644
index 9b8f9ffe12f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session5.test
+++ /dev/null
@@ -1,408 +0,0 @@
-# 2011 April 13
-#
-# 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 regression tests for the session module.
-# Specifically, for the sqlite3changeset_concat() command.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix session5
-
-# Organization of tests:
-#
-# session5-1.*: Simple tests to check the concat() function produces
-# correct results.
-#
-# session5-2.*: More complicated tests.
-#
-# session5-3.*: Schema mismatch errors.
-#
-# session5-4.*: Test the concat cases that indicate that the database
-# was modified in between recording of the two changesets
-# being concatenated (i.e. two changesets that INSERT rows
-# with the same PK values).
-#
-
-proc do_concat_test {tn args} {
-
- set subtest 0
- foreach sql $args {
- incr subtest
- sqlite3session S db main ; S attach *
- execsql $sql
-
- set c [S changeset]
- if {[info commands s_prev] != ""} {
- set c_concat [sqlite3changeset_concat $c_prev $c]
- set c_two [s_prev changeset]
- s_prev delete
-
- set h_concat [changeset_to_list $c_concat]
- set h_two [changeset_to_list $c_two]
-
- do_test $tn.$subtest [list set {} $h_concat] $h_two
- }
- set c_prev $c
- rename S s_prev
- }
-
- catch { s_prev delete }
-}
-
-#-------------------------------------------------------------------------
-# Test cases session5-1.* - simple tests.
-#
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b);
-}
-
-do_concat_test 1.1.1 {
- INSERT INTO t1 VALUES(1, 'one');
-} {
- INSERT INTO t1 VALUES(2, 'two');
-}
-
-do_concat_test 1.1.2 {
- UPDATE t1 SET b = 'five' WHERE a = 1;
-} {
- UPDATE t1 SET b = 'six' WHERE a = 2;
-}
-
-do_concat_test 1.1.3 {
- DELETE FROM t1 WHERE a = 1;
-} {
- DELETE FROM t1 WHERE a = 2;
-}
-
-
-# 1.2.1: INSERT + DELETE -> (none)
-# 1.2.2: INSERT + UPDATE -> INSERT
-#
-# 1.2.3: DELETE + INSERT (matching data) -> (none)
-# 1.2.4: DELETE + INSERT (non-matching data) -> UPDATE
-#
-# 1.2.5: UPDATE + UPDATE (matching data) -> (none)
-# 1.2.6: UPDATE + UPDATE (non-matching data) -> UPDATE
-# 1.2.7: UPDATE + DELETE -> DELETE
-#
-do_concat_test 1.2.1 {
- INSERT INTO t1 VALUES('x', 'y');
-} {
- DELETE FROM t1 WHERE a = 'x';
-}
-do_concat_test 1.2.2 {
- INSERT INTO t1 VALUES(5.0, 'five');
-} {
- UPDATE t1 SET b = 'six' WHERE a = 5.0;
-}
-
-do_execsql_test 1.2.3.1 "INSERT INTO t1 VALUES('I', 'one')"
-do_concat_test 1.2.3.2 {
- DELETE FROM t1 WHERE a = 'I';
-} {
- INSERT INTO t1 VALUES('I', 'one');
-}
-do_concat_test 1.2.4 {
- DELETE FROM t1 WHERE a = 'I';
-} {
- INSERT INTO t1 VALUES('I', 'two');
-}
-do_concat_test 1.2.5 {
- UPDATE t1 SET b = 'five' WHERE a = 'I';
-} {
- UPDATE t1 SET b = 'two' WHERE a = 'I';
-}
-do_concat_test 1.2.6 {
- UPDATE t1 SET b = 'six' WHERE a = 'I';
-} {
- UPDATE t1 SET b = 'seven' WHERE a = 'I';
-}
-do_concat_test 1.2.7 {
- UPDATE t1 SET b = 'eight' WHERE a = 'I';
-} {
- DELETE FROM t1 WHERE a = 'I';
-}
-
-
-#-------------------------------------------------------------------------
-# Test cases session5-2.* - more complex tests.
-#
-db function indirect indirect
-proc indirect {{x -1}} {
- S indirect $x
- s_prev indirect $x
-}
-do_concat_test 2.1 {
- CREATE TABLE abc(a, b, c PRIMARY KEY);
- INSERT INTO abc VALUES(NULL, NULL, 1);
- INSERT INTO abc VALUES('abcdefghijkl', NULL, 2);
-} {
- DELETE FROM abc WHERE c = 1;
- UPDATE abc SET c = 1 WHERE c = 2;
-} {
- INSERT INTO abc VALUES('abcdefghijkl', NULL, 2);
- INSERT INTO abc VALUES(1.0, 2.0, 3);
-} {
- UPDATE abc SET a = a-1;
-} {
- CREATE TABLE def(d, e, f, PRIMARY KEY(e, f));
- INSERT INTO def VALUES('x', randomblob(11000), 67);
- INSERT INTO def SELECT d, e, f+1 FROM def;
- INSERT INTO def SELECT d, e, f+2 FROM def;
- INSERT INTO def SELECT d, e, f+4 FROM def;
-} {
- DELETE FROM def WHERE rowid>4;
-} {
- INSERT INTO def SELECT d, e, f+4 FROM def;
-} {
- INSERT INTO abc VALUES(22, 44, -1);
-} {
- UPDATE abc SET c=-2 WHERE c=-1;
- UPDATE abc SET c=-3 WHERE c=-2;
-} {
- UPDATE abc SET c=-4 WHERE c=-3;
-} {
- UPDATE abc SET a=a+1 WHERE c=-3;
- UPDATE abc SET a=a+1 WHERE c=-3;
-} {
- UPDATE abc SET a=a+1 WHERE c=-3;
- UPDATE abc SET a=a+1 WHERE c=-3;
-} {
- INSERT INTO abc VALUES('one', 'two', 'three');
-} {
- SELECT indirect(1);
- UPDATE abc SET a='one point five' WHERE c = 'three';
-} {
- SELECT indirect(0);
- UPDATE abc SET a='one point six' WHERE c = 'three';
-} {
- CREATE TABLE x1(a, b, PRIMARY KEY(a));
- SELECT indirect(1);
- INSERT INTO x1 VALUES(1, 2);
-} {
- SELECT indirect(1);
- UPDATE x1 SET b = 3 WHERE a = 1;
-}
-
-catch {db close}
-forcedelete test.db
-sqlite3 db test.db
-do_concat_test 2.2 {
- CREATE TABLE t1(a, b, PRIMARY KEY(b));
- CREATE TABLE t2(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES('string', 1);
- INSERT INTO t1 VALUES(4, 2);
- INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3);
-} {
- INSERT INTO t2 VALUES('one', 'two');
- INSERT INTO t2 VALUES(1, NULL);
- UPDATE t1 SET a = 5 WHERE a = 2;
-} {
- DELETE FROM t2 WHERE a = 1;
- UPDATE t1 SET a = 4 WHERE a = 2;
- INSERT INTO t2 VALUES('x', 'y');
-}
-
-do_test 2.3.0 {
- catch {db close}
- forcedelete test.db
- sqlite3 db test.db
-
- set sql1 ""
- set sql2 ""
- for {set i 1} {$i < 120} {incr i} {
- append sql1 "INSERT INTO x1 VALUES($i*4, $i);"
- }
- for {set i 1} {$i < 120} {incr i} {
- append sql2 "DELETE FROM x1 WHERE a = $i*4;"
- }
- set {} {}
-} {}
-do_concat_test 2.3 {
- CREATE TABLE x1(a PRIMARY KEY, b)
-} $sql1 $sql2 $sql1 $sql2
-
-do_concat_test 2.4 {
- CREATE TABLE x2(a PRIMARY KEY, b);
- CREATE TABLE x3(a PRIMARY KEY, b);
-
- INSERT INTO x2 VALUES('a', 'b');
- INSERT INTO x2 VALUES('x', 'y');
- INSERT INTO x3 VALUES('a', 'b');
-} {
- INSERT INTO x2 VALUES('c', 'd');
- INSERT INTO x3 VALUES('e', 'f');
- INSERT INTO x3 VALUES('x', 'y');
-}
-
-do_concat_test 2.5 {
- UPDATE x3 SET b = 'Y' WHERE a = 'x'
-} {
- DELETE FROM x3 WHERE a = 'x'
-} {
- DELETE FROM x2 WHERE a = 'a'
-} {
- INSERT INTO x2 VALUES('a', 'B');
-}
-
-for {set k 1} {$k <=10} {incr k} {
- do_test 2.6.$k.1 {
- drop_all_tables
- set sql1 ""
- set sql2 ""
- for {set i 1} {$i < 120} {incr i} {
- append sql1 "INSERT INTO x1 VALUES(randomblob(20+(random()%10)), $i);"
- }
- for {set i 1} {$i < 120} {incr i} {
- append sql2 "DELETE FROM x1 WHERE rowid = $i;"
- }
- set {} {}
- } {}
- do_concat_test 2.6.$k {
- CREATE TABLE x1(a PRIMARY KEY, b)
- } $sql1 $sql2 $sql1 $sql2
-}
-
-for {set k 1} {$k <=10} {incr k} {
- do_test 2.7.$k.1 {
- drop_all_tables
- set sql1 ""
- set sql2 ""
- for {set i 1} {$i < 120} {incr i} {
- append sql1 {
- INSERT INTO x1 VALUES(
- CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END,
- CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END
- );
- }
- }
- for {set i 1} {$i < 120} {incr i} {
- append sql2 "DELETE FROM x1 WHERE rowid = $i;"
- }
- set {} {}
- } {}
- do_concat_test 2.7.$k {
- CREATE TABLE x1(a PRIMARY KEY, b)
- } $sql1 $sql2 $sql1 $sql2
-}
-
-
-#-------------------------------------------------------------------------
-# Test that schema incompatibilities are detected correctly.
-#
-# session5-3.1: Incompatible number of columns.
-# session5-3.2: Incompatible PK definition.
-#
-
-do_test 3.1 {
- db close
- forcedelete test.db
- sqlite3 db test.db
-
- execsql { CREATE TABLE t1(a PRIMARY KEY, b) }
- set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }]
- execsql {
- DROP TABLE t1;
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- }
- set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3, 4) }]
-
- list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg
-} {1 SQLITE_SCHEMA}
-
-do_test 3.2 {
- db close
- forcedelete test.db
- sqlite3 db test.db
-
- execsql { CREATE TABLE t1(a PRIMARY KEY, b) }
- set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }]
- execsql {
- DROP TABLE t1;
- CREATE TABLE t1(a, b PRIMARY KEY);
- }
- set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3) }]
-
- list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg
-} {1 SQLITE_SCHEMA}
-
-#-------------------------------------------------------------------------
-# Test that concat() handles these properly:
-#
-# session5-4.1: INSERT + INSERT
-# session5-4.2: UPDATE + INSERT
-# session5-4.3: DELETE + UPDATE
-# session5-4.4: DELETE + DELETE
-#
-
-proc do_concat_test2 {tn sql1 sqlX sql2 expected} {
- sqlite3session S db main ; S attach *
- execsql $sql1
- set ::c1 [S changeset]
- S delete
-
- execsql $sqlX
-
- sqlite3session S db main ; S attach *
- execsql $sql2
- set ::c2 [S changeset]
- S delete
-
- uplevel do_test $tn [list {
- changeset_to_list [sqlite3changeset_concat $::c1 $::c2]
- }] [list [normalize_list $expected]]
-}
-
-drop_all_tables db
-do_concat_test2 4.1 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES('key', 'value');
-} {
- DELETE FROM t1 WHERE a = 'key';
-} {
- INSERT INTO t1 VALUES('key', 'xxx');
-} {
- {INSERT t1 0 X. {} {t key t value}}
-}
-do_concat_test2 4.2 {
- UPDATE t1 SET b = 'yyy';
-} {
- DELETE FROM t1 WHERE a = 'key';
-} {
- INSERT INTO t1 VALUES('key', 'value');
-} {
- {UPDATE t1 0 X. {t key t xxx} {{} {} t yyy}}
-}
-do_concat_test2 4.3 {
- DELETE FROM t1 WHERE a = 'key';
-} {
- INSERT INTO t1 VALUES('key', 'www');
-} {
- UPDATE t1 SET b = 'valueX' WHERE a = 'key';
-} {
- {DELETE t1 0 X. {t key t value} {}}
-}
-do_concat_test2 4.4 {
- DELETE FROM t1 WHERE a = 'key';
-} {
- INSERT INTO t1 VALUES('key', 'ttt');
-} {
- DELETE FROM t1 WHERE a = 'key';
-} {
- {DELETE t1 0 X. {t key t valueX} {}}
-}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session6.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session6.test
deleted file mode 100644
index 8a1f172cde6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session6.test
+++ /dev/null
@@ -1,90 +0,0 @@
-# 2011 July 11
-#
-# 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 regression tests for SQLite sessions extension.
-# Specifically, it tests that sessions work when the database is modified
-# using incremental blob handles.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix session6
-
-proc do_then_apply_tcl {tcl {dbname main}} {
- proc xConflict args { return "OMIT" }
- set rc [catch {
- sqlite3session S db $dbname
- db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
- S attach $name
- }
- eval $tcl
- sqlite3changeset_apply db2 [S changeset] xConflict
- } msg]
-
- catch { S delete }
- if {$rc} {error $msg}
-}
-
-test_sqlite3_log x
-proc x {args} {puts $args}
-
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(c PRIMARY KEY, d);
-}
-
-# Test a blob update.
-#
-do_test 1.1 {
- do_then_apply_tcl {
- db eval { INSERT INTO t1 VALUES(1, 'helloworld') }
- db eval { INSERT INTO t2 VALUES(2, 'onetwothree') }
- }
- compare_db db db2
-} {}
-do_test 1.2 {
- do_then_apply_tcl {
- set fd [db incrblob t1 b 1]
- puts -nonewline $fd 1234567890
- close $fd
- }
- compare_db db db2
-} {}
-
-# Test an attached database.
-#
-do_test 2.1 {
- forcedelete test.db3
- file copy test.db2 test.db3
- execsql { ATTACH 'test.db3' AS aux; }
-
- do_then_apply_tcl {
- set fd [db incrblob aux t2 d 1]
- puts -nonewline $fd fourfivesix
- close $fd
- } aux
-
- sqlite3 db3 test.db3
- compare_db db2 db3
-} {}
-
-
-db3 close
-db2 close
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session8.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session8.test
deleted file mode 100644
index 9f70fe2829b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session8.test
+++ /dev/null
@@ -1,91 +0,0 @@
-# 2011 July 13
-#
-# 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 regression tests for SQLite library.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix session8
-
-proc noop {args} {}
-
-# Like [dbcksum] in tester.tcl. Except this version is not sensitive
-# to changes in the value of implicit IPK columns.
-#
-proc udbcksum {db dbname} {
- if {$dbname=="temp"} {
- set master sqlite_temp_master
- } else {
- set master $dbname.sqlite_master
- }
- set alltab [$db eval "SELECT name FROM $master WHERE type='table'"]
- set txt [$db eval "SELECT * FROM $master"]\n
- foreach tab $alltab {
- append txt [lsort [$db eval "SELECT * FROM $dbname.$tab"]]\n
- }
- return [md5 $txt]
-}
-
-proc do_then_undo {tn sql} {
- set ck1 [udbcksum db main]
-
- sqlite3session S db main
- S attach *
- db eval $sql
-
- set ck2 [udbcksum db main]
-
- set invert [sqlite3changeset_invert [S changeset]]
- S delete
- sqlite3changeset_apply db $invert noop
-
- set ck3 [udbcksum db main]
-
- set a [expr {$ck1==$ck2}]
- set b [expr {$ck1==$ck3}]
- uplevel [list do_test $tn.1 "set {} $a" 0]
- uplevel [list do_test $tn.2 "set {} $b" 1]
-}
-
-do_execsql_test 1.1 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t1 VALUES("abc", "xyz");
-}
-do_then_undo 1.2 { INSERT INTO t1 VALUES(3, 4); }
-do_then_undo 1.3 { DELETE FROM t1 WHERE b=2; }
-do_then_undo 1.4 { UPDATE t1 SET b = 3 WHERE a = 1; }
-
-do_execsql_test 2.1 {
- CREATE TABLE t2(a, b PRIMARY KEY);
- INSERT INTO t2 VALUES(1, 2);
- INSERT INTO t2 VALUES('abc', 'xyz');
-}
-do_then_undo 1.2 { INSERT INTO t2 VALUES(3, 4); }
-do_then_undo 1.3 { DELETE FROM t2 WHERE b=2; }
-do_then_undo 1.4 { UPDATE t1 SET a = '123' WHERE b = 'xyz'; }
-
-do_execsql_test 3.1 {
- CREATE TABLE t3(a, b, c, d, e, PRIMARY KEY(c, e));
- INSERT INTO t3 VALUES('x', 45, 0.0, 'abcdef', 12);
- INSERT INTO t3 VALUES(45, 0.0, 'abcdef', 12, 'x');
- INSERT INTO t3 VALUES(0.0, 'abcdef', 12, 'x', 45);
-}
-
-do_then_undo 3.2 { UPDATE t3 SET b=b||b WHERE e!='x' }
-do_then_undo 3.3 { UPDATE t3 SET a = 46 }
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session9.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session9.test
deleted file mode 100644
index ebb88ffade7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session9.test
+++ /dev/null
@@ -1,287 +0,0 @@
-# 2013 July 04
-#
-# 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 tests that the sessions module handles foreign key constraint
-# violations when applying changesets as required.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-set testprefix session9
-
-
-#--------------------------------------------------------------------
-# Basic tests.
-#
-proc populate_db {} {
- drop_all_tables
- execsql {
- PRAGMA foreign_keys = 1;
- CREATE TABLE p1(a PRIMARY KEY, b);
- CREATE TABLE c1(a PRIMARY KEY, b REFERENCES p1);
- CREATE TABLE c2(a PRIMARY KEY,
- b REFERENCES p1 DEFERRABLE INITIALLY DEFERRED
- );
-
- INSERT INTO p1 VALUES(1, 'one');
- INSERT INTO p1 VALUES(2, 'two');
- INSERT INTO p1 VALUES(3, 'three');
- INSERT INTO p1 VALUES(4, 'four');
- }
-}
-
-proc capture_changeset {sql} {
- sqlite3session S db main
-
- foreach t [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
- S attach $t
- }
- execsql $sql
- set ret [S changeset]
- S delete
-
- return $ret
-}
-
-do_test 1.1 {
- populate_db
- set cc [capture_changeset {
- INSERT INTO c1 VALUES('ii', 2);
- INSERT INTO c2 VALUES('iii', 3);
- }]
- set {} {}
-} {}
-
-proc xConflict {args} {
- lappend ::xConflict {*}$args
- return $::conflictret
-}
-
-foreach {tn delrow trans conflictargs conflictret} {
- 1 2 0 {FOREIGN_KEY 1} OMIT
- 2 3 0 {FOREIGN_KEY 1} OMIT
- 3 2 1 {FOREIGN_KEY 1} OMIT
- 4 3 1 {FOREIGN_KEY 1} OMIT
- 5 2 0 {FOREIGN_KEY 1} ABORT
- 6 3 0 {FOREIGN_KEY 1} ABORT
- 7 2 1 {FOREIGN_KEY 1} ABORT
- 8 3 1 {FOREIGN_KEY 1} ABORT
-} {
-
- set A(OMIT) {0 {}}
- set A(ABORT) {1 SQLITE_CONSTRAINT}
- do_test 1.2.$tn.1 {
- populate_db
- execsql { DELETE FROM p1 WHERE a=($delrow+0) }
- if {$trans} { execsql BEGIN }
-
- set ::xConflict [list]
- list [catch {sqlite3changeset_apply db $::cc xConflict} msg] $msg
- } $A($conflictret)
-
- do_test 1.2.$tn.2 { set ::xConflict } $conflictargs
-
- set A(OMIT) {1 1}
- set A(ABORT) {0 0}
- do_test 1.2.$tn.3 {
- execsql { SELECT count(*) FROM c1 UNION ALL SELECT count(*) FROM c2 }
- } $A($conflictret)
-
- do_test 1.2.$tn.4 { expr ![sqlite3_get_autocommit db] } $trans
- do_test 1.2.$tn.5 {
- if { $trans } { execsql COMMIT }
- } {}
-}
-
-#--------------------------------------------------------------------
-# Test that closing a transaction clears the defer_foreign_keys flag.
-#
-foreach {tn open noclose close} {
- 1 BEGIN {} COMMIT
- 2 BEGIN {} ROLLBACK
-
- 3 {SAVEPOINT one} {} {RELEASE one}
- 4 {SAVEPOINT one} {ROLLBACK TO one} {RELEASE one}
-} {
- execsql $open
- do_execsql_test 2.$tn.1 { PRAGMA defer_foreign_keys } {0}
-
- do_execsql_test 2.$tn.2 {
- PRAGMA defer_foreign_keys = 1;
- PRAGMA defer_foreign_keys;
- } {1}
-
- execsql $noclose
- do_execsql_test 2.$tn.3 { PRAGMA defer_foreign_keys } {1}
-
- execsql $close
- do_execsql_test 2.$tn.4 { PRAGMA defer_foreign_keys } {0}
-}
-
-#--------------------------------------------------------------------
-# Test that a cyclic relationship can be inserted and deleted.
-#
-# This situation does not come up in practice, but testing it serves to
-# show that it does not matter which order parent and child keys
-# are processed in internally when applying a changeset.
-#
-drop_all_tables
-
-do_execsql_test 3.1 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(x PRIMARY KEY, y);
-}
-
-# Create changesets as follows:
-#
-# $cc1 - Insert a row into t1.
-# $cc2 - Insert a row into t2.
-# $cc - Combination of $cc1 and $cc2.
-#
-# $ccdel1 - Delete the row from t1.
-# $ccdel2 - Delete the row from t2.
-# $ccdel - Combination of $cc1 and $cc2.
-#
-do_test 3.2 {
- set cc1 [capture_changeset {
- INSERT INTO t1 VALUES('one', 'value one');
- }]
- set ccdel1 [capture_changeset { DELETE FROM t1; }]
- set cc2 [capture_changeset {
- INSERT INTO t2 VALUES('value one', 'one');
- }]
- set ccdel2 [capture_changeset { DELETE FROM t2; }]
- set cc [capture_changeset {
- INSERT INTO t1 VALUES('one', 'value one');
- INSERT INTO t2 VALUES('value one', 'one');
- }]
- set ccdel [capture_changeset {
- DELETE FROM t1;
- DELETE FROM t2;
- }]
- set {} {}
-} {}
-
-# Now modify the database schema to create a cyclic foreign key dependency
-# between tables t1 and t2. This means that although changesets $cc and
-# $ccdel can be applied, none of the others may without violating the
-# foreign key constraints.
-#
-do_test 3.3 {
-
- drop_all_tables
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t2);
- CREATE TABLE t2(x PRIMARY KEY, y REFERENCES t1);
- }
-
-
- proc conflict_handler {args} { return "ABORT" }
- sqlite3changeset_apply db $cc conflict_handler
-
- execsql {
- SELECT * FROM t1;
- SELECT * FROM t2;
- }
-} {one {value one} {value one} one}
-
-do_test 3.3.1 {
- list [catch {sqlite3changeset_apply db $::ccdel1 conflict_handler} msg] $msg
-} {1 SQLITE_CONSTRAINT}
-
-do_test 3.3.2 {
- list [catch {sqlite3changeset_apply db $::ccdel2 conflict_handler} msg] $msg
-} {1 SQLITE_CONSTRAINT}
-
-do_test 3.3.4.1 {
- list [catch {sqlite3changeset_apply db $::ccdel conflict_handler} msg] $msg
-} {0 {}}
-do_execsql_test 3.3.4.2 {
- SELECT * FROM t1;
- SELECT * FROM t2;
-} {}
-
-do_test 3.5.1 {
- list [catch {sqlite3changeset_apply db $::cc1 conflict_handler} msg] $msg
-} {1 SQLITE_CONSTRAINT}
-do_test 3.5.2 {
- list [catch {sqlite3changeset_apply db $::cc2 conflict_handler} msg] $msg
-} {1 SQLITE_CONSTRAINT}
-
-#--------------------------------------------------------------------
-# Test that if a change that affects FK processing is not applied
-# due to a separate constraint, SQLite does not get confused and
-# increment FK counters anyway.
-#
-drop_all_tables
-do_execsql_test 4.1 {
- CREATE TABLE p1(x PRIMARY KEY, y);
- CREATE TABLE c1(a PRIMARY KEY, b REFERENCES p1);
- INSERT INTO p1 VALUES(1,1);
-}
-
-do_execsql_test 4.2.1 {
- BEGIN;
- PRAGMA defer_foreign_keys = 1;
- INSERT INTO c1 VALUES('x', 'x');
-}
-do_catchsql_test 4.2.2 { COMMIT } {1 {FOREIGN KEY constraint failed}}
-do_catchsql_test 4.2.3 { ROLLBACK } {0 {}}
-
-do_execsql_test 4.3.1 {
- BEGIN;
- PRAGMA defer_foreign_keys = 1;
- INSERT INTO c1 VALUES(1, 1);
-}
-do_catchsql_test 4.3.2 {
- INSERT INTO c1 VALUES(1, 'x')
-} {1 {UNIQUE constraint failed: c1.a}}
-
-do_catchsql_test 4.3.3 { COMMIT } {0 {}}
-do_catchsql_test 4.3.4 { BEGIN ; COMMIT } {0 {}}
-
-#--------------------------------------------------------------------
-# Test that if a DELETE change cannot be applied due to an
-# SQLITE_CONSTRAINT error thrown by a trigger program, things do not
-# go awry.
-
-drop_all_tables
-reset_db
-do_execsql_test 5.1 {
- CREATE TABLE x1(x PRIMARY KEY, y);
- CREATE TABLE x2(x PRIMARY KEY, y);
- INSERT INTO x2 VALUES(1, 1);
- INSERT INTO x1 VALUES(1, 1);
-}
-
-set ::cc [changeset_from_sql { DELETE FROM x1; }]
-
-do_execsql_test 5.2 {
- INSERT INTO x1 VALUES(1, 1);
- CREATE TRIGGER tr1 AFTER DELETE ON x1 BEGIN
- INSERT INTO x2 VALUES(old.x, old.y);
- END;
-} {}
-
-proc conflict_handler {args} { return "ABORT" }
-do_test 5.3 {
- list [catch {sqlite3changeset_apply db $::cc conflict_handler} msg] $msg
-} {1 SQLITE_ABORT}
-
-do_execsql_test 5.4 {
- SELECT * FROM X1;
-} {1 1}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionA.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionA.test
deleted file mode 100644
index 0e0a14e38a9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionA.test
+++ /dev/null
@@ -1,106 +0,0 @@
-# 2013 July 04
-#
-# 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 tests that filter callbacks work as required.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-set testprefix sessionA
-
-
-forcedelete test.db2
-sqlite3 db2 test.db2
-foreach {tn db} {1 db 2 db2} {
- do_test 1.$tn.1 {
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(a PRIMARY KEY, b);
- CREATE TABLE t3(a PRIMARY KEY, b);
- } $db
- } {}
-}
-
-proc tbl_filter {zTbl} {
- return $::table_filter($zTbl)
-}
-
-do_test 2.1 {
- set ::table_filter(t1) 1
- set ::table_filter(t2) 0
- set ::table_filter(t3) 1
-
- sqlite3session S db main
- S table_filter tbl_filter
-
- execsql {
- INSERT INTO t1 VALUES('a', 'b');
- INSERT INTO t2 VALUES('c', 'd');
- INSERT INTO t3 VALUES('e', 'f');
- }
-
- set changeset [S changeset]
- S delete
- sqlite3changeset_apply db2 $changeset xConflict
-
- execsql {
- SELECT * FROM t1;
- SELECT * FROM t2;
- SELECT * FROM t3;
- } db2
-} {a b e f}
-
-#-------------------------------------------------------------------------
-# Test that filter callbacks passed to sqlite3changeset_apply() are
-# invoked correctly.
-#
-reset_db
-do_execsql_test 3.1 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(x PRIMARY KEY, y);
-}
-
-do_test 3.2 {
- execsql BEGIN
- set ::cs [changeset_from_sql {
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t2 VALUES('x', 'y');
- }]
- execsql ROLLBACK
- set {} {}
-} {}
-
-proc filter {x y} {
- return [string equal $x $y]
-}
-
-do_test 3.3 {
- sqlite3changeset_apply db $::cs {} [list filter t1]
- execsql {
- SELECT * FROM t1;
- SELECT * FROM t2;
- }
-} {1 2}
-
-do_test 3.4 {
- execsql { DELETE FROM t1 }
- sqlite3changeset_apply db $::cs {} [list filter t2]
- execsql {
- SELECT * FROM t1;
- SELECT * FROM t2;
- }
-} {x y}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionB.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionB.test
deleted file mode 100644
index eae41f76ad1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionB.test
+++ /dev/null
@@ -1,508 +0,0 @@
-# 2014 August 16
-#
-# 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 regression tests for sessions SQLite extension.
-# Specifically, this file contains tests for "patchset" changes.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix sessionB
-
-#
-# 1.*: Test that the blobs returned by the session_patchset() API are
-# as expected. Also the sqlite3_changeset_iter functions.
-#
-# 2.*: Test that patchset blobs are handled by sqlite3changeset_apply().
-#
-# 3.*: Test that sqlite3changeset_invert() works with patchset blobs.
-# Correct behaviour is to return SQLITE_CORRUPT.
-
-proc do_sql2patchset_test {tn sql res} {
- sqlite3session S db main
- S attach *
- execsql $sql
- uplevel [list do_patchset_test $tn S $res]
- S delete
-}
-
-#-------------------------------------------------------------------------
-# Run simple tests of the _patchset() API.
-#
-do_execsql_test 1.0 {
- CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, a));
- INSERT INTO t1 VALUES(1, 2, 3, 4);
- INSERT INTO t1 VALUES(5, 6, 7, 8);
- INSERT INTO t1 VALUES(9, 10, 11, 12);
-}
-
-do_test 1.1 {
- sqlite3session S db main
- S attach t1
- execsql {
- INSERT INTO t1 VALUES('w', 'x', 'y', 'z');
- DELETE FROM t1 WHERE d=4;
- UPDATE t1 SET c = 14 WHERE a=5;
- }
-} {}
-
-do_patchset_test 1.2 S {
- {UPDATE t1 0 X..X {i 5 {} {} {} {} i 8} {{} {} {} {} i 14 {} {}}}
- {INSERT t1 0 X..X {} {t w t x t y t z}}
- {DELETE t1 0 X..X {i 1 {} {} {} {} i 4} {}}
-}
-
-do_test 1.3 {
- S delete
-} {}
-
-do_sql2patchset_test 1.4 {
- DELETE FROM t1;
-} {
- {DELETE t1 0 X..X {i 5 {} {} {} {} i 8} {}}
- {DELETE t1 0 X..X {t w {} {} {} {} t z} {}}
- {DELETE t1 0 X..X {i 9 {} {} {} {} i 12} {}}
-}
-
-do_sql2patchset_test 1.5 {
- INSERT INTO t1 VALUES(X'61626364', NULL, NULL, 4.2);
- INSERT INTO t1 VALUES(4.2, NULL, NULL, X'61626364');
-} {
- {INSERT t1 0 X..X {} {f 4.2 n {} n {} b abcd}}
- {INSERT t1 0 X..X {} {b abcd n {} n {} f 4.2}}
-}
-
-do_sql2patchset_test 1.6 {
- UPDATE t1 SET b=45 WHERE typeof(a)=='blob';
- UPDATE t1 SET c='zzzz' WHERE typeof(a)!='blob';
-} {
- {UPDATE t1 0 X..X {f 4.2 {} {} {} {} b abcd} {{} {} {} {} t zzzz {} {}}}
- {UPDATE t1 0 X..X {b abcd {} {} {} {} f 4.2} {{} {} i 45 {} {} {} {}}}
-}
-
-do_sql2patchset_test 1.7 {
- UPDATE t1 SET b='xyz' WHERE typeof(a)=='blob';
- UPDATE t1 SET c='xyz' WHERE typeof(a)!='blob';
- UPDATE t1 SET b=45 WHERE typeof(a)=='blob';
- UPDATE t1 SET c='zzzz' WHERE typeof(a)!='blob';
-} {
-}
-
-do_sql2patchset_test 1.8 {
- DELETE FROM t1;
-} {
- {DELETE t1 0 X..X {f 4.2 {} {} {} {} b abcd} {}}
- {DELETE t1 0 X..X {b abcd {} {} {} {} f 4.2} {}}
-}
-
-#-------------------------------------------------------------------------
-# Run simple tests of _apply() with patchset objects.
-#
-reset_db
-
-proc noop {args} { error $args }
-proc exec_rollback_replay {sql} {
- sqlite3session S db main
- S attach *
- execsql BEGIN
- execsql $sql
- set patchset [S patchset]
- S delete
- execsql ROLLBACK
- sqlite3changeset_apply db $patchset noop
-}
-
-do_execsql_test 2.0 {
- CREATE TABLE t2(a, b, c, d, PRIMARY KEY(b,c));
- CREATE TABLE t3(w, x, y, z, PRIMARY KEY(w));
-}
-
-do_test 2.1 {
- exec_rollback_replay {
- INSERT INTO t2 VALUES(1, 2, 3, 4);
- INSERT INTO t2 VALUES('w', 'x', 'y', 'z');
- }
- execsql { SELECT * FROM t2 }
-} {1 2 3 4 w x y z}
-
-do_test 2.2 {
- exec_rollback_replay {
- DELETE FROM t2 WHERE a=1;
- UPDATE t2 SET d = 'a';
- }
- execsql { SELECT * FROM t2 }
-} {w x y a}
-
-#-------------------------------------------------------------------------
-# sqlite3changeset_invert()
-#
-reset_db
-
-do_execsql_test 3.1 { CREATE TABLE t1(x PRIMARY KEY, y) }
-do_test 3.2 {
- sqlite3session S db main
- S attach *
- execsql { INSERT INTO t1 VALUES(1, 2) }
- set patchset [S patchset]
- S delete
- list [catch { sqlite3changeset_invert $patchset } msg] [set msg]
-} {1 SQLITE_CORRUPT}
-
-
-#-------------------------------------------------------------------------
-# sqlite3changeset_concat()
-#
-reset_db
-
-proc do_patchconcat_test {tn args} {
- set bRevert 0
- if {[lindex $args 0] == "-revert"} {
- set bRevert 1
- set args [lrange $args 1 end]
- }
- set nSql [expr [llength $args]-1]
- set res [lindex $args $nSql]
- set patchlist [list]
-
- execsql BEGIN
- if {$bRevert} { execsql { SAVEPOINT x } }
- foreach sql [lrange $args 0 end-1] {
- sqlite3session S db main
- S attach *
- execsql $sql
- lappend patchlist [S patchset]
- S delete
- if {$bRevert} { execsql { ROLLBACK TO x } }
- }
- execsql ROLLBACK
-
- set patch [lindex $patchlist 0]
- foreach p [lrange $patchlist 1 end] {
- set patch [sqlite3changeset_concat $patch $p]
- }
-
- set x [list]
- sqlite3session_foreach c $patch { lappend x $c }
-
- uplevel [list do_test $tn [list set {} $x] [list {*}$res]]
-}
-
-do_execsql_test 4.1.1 {
- CREATE TABLE t1(x PRIMARY KEY, y, z);
-}
-do_patchconcat_test 4.1.2 {
- INSERT INTO t1 VALUES(1, 2, 3);
-} {
- INSERT INTO t1 VALUES(4, 5, 6);
-} {
- {INSERT t1 0 X.. {} {i 1 i 2 i 3}}
- {INSERT t1 0 X.. {} {i 4 i 5 i 6}}
-}
-
-do_execsql_test 4.2.1 {
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
-}
-
-do_patchconcat_test 4.2.2 {
- UPDATE t1 SET z = 'abc' WHERE x=1
-} {
- UPDATE t1 SET z = 'def' WHERE x=4
-} {
- {UPDATE t1 0 X.. {i 1 {} {} {} {}} {{} {} {} {} t abc}}
- {UPDATE t1 0 X.. {i 4 {} {} {} {}} {{} {} {} {} t def}}
-}
-
-do_patchconcat_test 4.2.3 {
- DELETE FROM t1 WHERE x=1;
-} {
- DELETE FROM t1 WHERE x=4;
-} {
- {DELETE t1 0 X.. {i 1 {} {} {} {}} {}}
- {DELETE t1 0 X.. {i 4 {} {} {} {}} {}}
-}
-
-
-do_execsql_test 4.3.1 {
- CREATE TABLE t2(a, b, c, d, PRIMARY KEY(c, b));
- INSERT INTO t2 VALUES('.', 1, 1, '.');
- INSERT INTO t2 VALUES('.', 1, 2, '.');
- INSERT INTO t2 VALUES('.', 2, 1, '.');
- INSERT INTO t2 VALUES('.', 2, 2, '.');
-}
-
-# INSERT + INSERT
-do_patchconcat_test 4.3.2 -revert {
- INSERT INTO t2 VALUES('a', 'a', 'a', 'a');
-} {
- INSERT INTO t2 VALUES('b', 'a', 'a', 'b');
-} {
- {INSERT t2 0 .XX. {} {t a t a t a t a}}
-}
-
-# INSERT + DELETE
-do_patchconcat_test 4.3.3 {
- INSERT INTO t2 VALUES('a', 'a', 'a', 'a');
-} {
- DELETE FROM t2 WHERE c = 'a';
-} {
-}
-
-# INSERT + UPDATE
-do_patchconcat_test 4.3.4 {
- INSERT INTO t2 VALUES('a', 'a', 'a', 'a');
-} {
- UPDATE t2 SET d = 'b' WHERE c='a';
-} {
- {INSERT t2 0 .XX. {} {t a t a t a t b}}
-}
-
-# UPDATE + UPDATE
-do_patchconcat_test 4.3.5 {
- UPDATE t2 SET a = 'a' WHERE c=1 AND b=2;
-} {
- UPDATE t2 SET d = 'd' WHERE c=1 AND b=2;
-} {
- {UPDATE t2 0 .XX. {{} {} i 2 i 1 {} {}} {t a {} {} {} {} t d}}
-}
-
-# UPDATE + DELETE
-do_patchconcat_test 4.3.6 {
- UPDATE t2 SET a = 'a' WHERE c=1 AND b=2;
-} {
- DELETE FROM t2 WHERE c=1 AND b=2;
-} {
- {DELETE t2 0 .XX. {{} {} i 2 i 1 {} {}} {}}
-}
-
-# DELETE + INSERT
-do_patchconcat_test 4.3.7 {
- DELETE FROM t2 WHERE b=1;
-} {
- INSERT INTO t2 VALUES('x', 1, 2, '.');
-} {
- {DELETE t2 0 .XX. {{} {} i 1 i 1 {} {}} {}}
- {UPDATE t2 0 .XX. {{} {} i 1 i 2 {} {}} {t x {} {} {} {} t .}}
-}
-
-# DELETE + UPDATE
-do_patchconcat_test 4.3.8 -revert {
- DELETE FROM t2 WHERE b=1 AND c=2;
-} {
- UPDATE t2 SET a=5 WHERE b=1 AND c=2;
-} {
- {DELETE t2 0 .XX. {{} {} i 1 i 2 {} {}} {}}
-}
-
-# DELETE + UPDATE
-do_patchconcat_test 4.3.9 -revert {
- DELETE FROM t2 WHERE b=1 AND c=2;
-} {
- DELETE FROM t2 WHERE b=1;
-} {
- {DELETE t2 0 .XX. {{} {} i 1 i 1 {} {}} {}}
- {DELETE t2 0 .XX. {{} {} i 1 i 2 {} {}} {}}
-}
-
-#-------------------------------------------------------------------------
-# More rigorous testing of the _patchset(), _apply and _concat() APIs.
-#
-# The inputs to each test are a populate database and a list of DML
-# statements. This test determines that the final database is the same
-# if:
-#
-# 1) the statements are executed directly on the database.
-#
-# 2) a single patchset is collected while executing the statements and
-# then applied to a copy of the original database file.
-#
-# 3) individual patchsets are collected for statement while executing
-# them and concatenated together before being applied to a copy of
-# the original database. The concatenation is done in a couple of
-# different ways - linear, pairwise etc.
-#
-# All tests, as it happens, are run with both changesets and patchsets.
-# But the focus is on patchset capabilities.
-#
-
-# Return a checksum of the contents of the database file. Implicit IPK
-# columns are not included in the checksum - just modifying rowids does
-# not change the database checksum.
-#
-proc databasecksum {db} {
- set alltab [$db eval {SELECT name FROM sqlite_master WHERE type='table'}]
- foreach tab $alltab {
- $db eval "SELECT * FROM $tab LIMIT 1" res { }
- set slist [list]
- foreach col [lsort $res(*)] {
- lappend slist "quote($col)"
- }
- set sql "SELECT [join $slist ,] FROM $tab"
- append txt "[lsort [$db eval $sql]]\n"
- }
- return [md5 $txt]
-}
-
-proc do_patchset_test {tn tstcmd lSql} {
- if {$tstcmd != "patchset" && $tstcmd != "changeset"} {
- error "have $tstcmd: must be patchset or changeset"
- }
-
- foreach fname {test.db2 test.db3 test.db4 test.db5} {
- forcedelete $fname
- forcecopy test.db $fname
- }
-
- # Execute the SQL statements on [db]. Collect a patchset for each
- # individual statement, as well as a single patchset for the entire
- # operation.
- sqlite3session S db main
- S attach *
- foreach sql $lSql {
- sqlite3session T db main
- T attach *
- db eval $sql
- lappend lPatch [T $tstcmd]
- T delete
- }
- set patchset [S $tstcmd]
- S delete
-
- # Calculate a checksum for the final database.
- set cksum [databasecksum db]
-
- # 1. Apply the single large patchset to test.db2
- sqlite3 db2 test.db2
- sqlite3changeset_apply db2 $patchset noop
- uplevel [list do_test $tn.1 { databasecksum db2 } $cksum ]
- db2 close
-
- # 2. Apply each of the single-statement patchsets to test.db3
- sqlite3 db2 test.db3
- foreach p $lPatch {
- sqlite3changeset_apply db2 $p noop
- }
- uplevel [list do_test $tn.2 { databasecksum db2 } $cksum ]
- db2 close
-
- # 3. Concatenate all single-statement patchsets into a single large
- # patchset, then apply it to test.db4.
- #
- sqlite3 db2 test.db4
- set big ""
- foreach p $lPatch {
- set big [sqlite3changeset_concat $big $p]
- }
- sqlite3changeset_apply db2 $big noop
- uplevel [list do_test $tn.3 { databasecksum db2 } $cksum ]
- db2 close
-
- # 4. Concatenate all single-statement patchsets pairwise into a single
- # large patchset, then apply it to test.db5. Pairwise concatenation:
- #
- # a b c d e f g h i j k
- # -> {a b} {c d} {e f} {g h} {i j} k
- # -> {a b c d} {e f g h} {i j k}
- # -> {a b c d e f g h} {i j k}
- # -> {a b c d e f g h i j k}
- # -> APPLY!
- #
- sqlite3 db2 test.db5
- set L $lPatch
- while {[llength $L] > 1} {
- set O [list]
- for {set i 0} {$i < [llength $L]} {incr i 2} {
- if {$i==[llength $L]-1} {
- lappend O [lindex $L $i]
- } else {
- set i1 [expr $i+1]
- lappend O [sqlite3changeset_concat [lindex $L $i] [lindex $L $i1]]
- }
- }
- set L $O
- }
- sqlite3changeset_apply db2 [lindex $L 0] noop
- uplevel [list do_test $tn.4 { databasecksum db2 } $cksum ]
- db2 close
-}
-
-proc do_patchset_changeset_test {tn initsql args} {
- foreach tstcmd {patchset changeset} {
- reset_db
- execsql $initsql
- set x 0
- foreach sql $args {
- incr x
- set lSql [split $sql ";"]
- uplevel [list do_patchset_test $tn.$tstcmd.$x $tstcmd $lSql]
- }
- }
-}
-
-do_patchset_changeset_test 5.1 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- INSERT INTO t1 VALUES(1, 2, 3);
-} {
- INSERT INTO t1 VALUES(4, 5, 6);
- DELETE FROM t1 WHERE a=1;
-} {
- INSERT INTO t1 VALUES(7, 8, 9);
- UPDATE t1 SET c = 5;
- INSERT INTO t1 VALUES(10, 11, 12);
- UPDATE t1 SET c = 6;
- INSERT INTO t1 VALUES(13, 14, 15);
-} {
- UPDATE t1 SET c=c+1;
- DELETE FROM t1 WHERE (a%2);
-}
-
-do_patchset_changeset_test 5.2 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE TABLE t2(a, b, c, d, PRIMARY KEY(c, b));
-} {
- INSERT INTO t1 VALUES(x'00', 0, 'zero');
- INSERT INTO t1 VALUES(x'01', 1, 'one');
- INSERT INTO t1 VALUES(x'02', 4, 'four');
- INSERT INTO t1 VALUES(x'03', 9, 'nine');
- INSERT INTO t1 VALUES(x'04', 16, 'sixteen');
- INSERT INTO t1 VALUES(x'05', 25, 'twenty-five');
-} {
- UPDATE t1 SET a = b WHERE b<=4;
- INSERT INTO t2 SELECT NULL, * FROM t1;
- DELETE FROM t1 WHERE b=25;
-} {
- DELETE FROM t2;
- INSERT INTO t2 SELECT NULL, * FROM t1;
- DELETE FROM t1;
- INSERT INTO t1 SELECT b, c, d FROM t2;
- UPDATE t1 SET b = b+1;
- UPDATE t1 SET b = b+1;
- UPDATE t1 SET b = b+1;
-}
-
-set initsql { CREATE TABLE t1(a, b, c, PRIMARY KEY(c, b)); }
-for {set i 0} {$i < 1000} {incr i} {
- append insert "INSERT INTO t1 VALUES($i, $i, $i);"
- append delete "DELETE FROM t1 WHERE b=$i;"
-}
-do_patchset_changeset_test 5.3 \
- $initsql $insert $delete \
- $insert $delete \
- "$insert $delete" \
- $delete
-
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionC.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionC.test
deleted file mode 100644
index 390a31deb63..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionC.test
+++ /dev/null
@@ -1,198 +0,0 @@
-# 2014 August 16
-#
-# 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.
-#
-#***********************************************************************
-#
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix sessionC
-
-#-------------------------------------------------------------------------
-# Test the outcome of a DELETE operation made as part of applying a
-# changeset failing with SQLITE_CONSTRAINT. This may happen if an
-# ON DELETE RESTRICT foreign key action is triggered, or if a trigger
-# program raises a constraint somehow.
-#
-# UPDATE: The above is no longer true, as "PRAGMA defer_foreign_keys"
-# now disables "RESTRICT" processing. The test below has been rewritten
-# to use a trigger instead of a foreign key to test this case.
-#
-do_execsql_test 1.0 {
- PRAGMA foreign_keys = 1;
-
- CREATE TABLE p(a PRIMARY KEY, b, c);
- CREATE TABLE c(d PRIMARY KEY, e /* REFERENCES p ON DELETE RESTRICT */);
-
- CREATE TRIGGER restrict_trig BEFORE DELETE ON p BEGIN
- SELECT raise(ABORT, 'error!') FROM c WHERE e=old.a;
- END;
-
- INSERT INTO p VALUES('one', 1, 1);
- INSERT INTO p VALUES('two', 2, 2);
- INSERT INTO p VALUES('three', 3, 3);
-
- INSERT INTO c VALUES(1, 'one');
- INSERT INTO c VALUES(3, 'three');
-}
-
-do_test 1.1 {
- execsql BEGIN
- set C [changeset_from_sql {
- INSERT INTO c VALUES(4, 'one');
- DELETE FROM p WHERE a='two';
- }]
- execsql ROLLBACK
- execsql {
- INSERT INTO c VALUES(2, 'two');
- }
-} {}
-
-do_test 1.2.1 {
- proc xConflict {args} { return "ABORT" }
- catch { sqlite3changeset_apply db $C xConflict } msg
- set msg
-} {SQLITE_ABORT}
-do_execsql_test 1.2.2 { SELECT * FROM c } {1 one 3 three 2 two}
-
-do_test 1.3.1 {
- proc xConflict {args} { return "OMIT" }
- catch { sqlite3changeset_apply db $C xConflict } msg
- set msg
-} {}
-do_execsql_test 1.3.2 { SELECT * FROM c } {1 one 3 three 2 two 4 one}
-do_execsql_test 1.3.3 {
- SELECT * FROM p;
-} {one 1 1 two 2 2 three 3 3}
-
-
-#-------------------------------------------------------------------------
-# Test that concatenating a changeset with a patchset does not work.
-# Any attempt to do so returns SQLITE_ERROR.
-#
-reset_db
-do_execsql_test 2.0 {
- CREATE TABLE x1(t, v PRIMARY KEY);
- INSERT INTO x1 VALUES(12, 55);
- INSERT INTO x1 VALUES(55, 14);
-}
-
-do_test 2.1 {
- execsql BEGIN
-
- sqlite3session S1 db main
- S1 attach *
- execsql {
- UPDATE x1 SET t=13 WHERE v=55;
- INSERT INTO x1 VALUES(99, 123);
- }
- set patchset [S1 patchset]
- S1 delete
-
- sqlite3session S1 db main
- S1 attach *
- execsql {
- UPDATE x1 SET t=56 WHERE v=14;
- INSERT INTO x1 VALUES(22, 998);
- }
- set changeset [S1 changeset]
- S1 delete
-
- execsql ROLLBACK
-} {}
-
-do_test 2.2 {
- set rc [catch { sqlite3changeset_concat $patchset $changeset } msg]
- list $rc $msg
-} {1 SQLITE_ERROR}
-
-do_test 2.3 {
- set rc [catch { sqlite3changeset_concat $changeset $patchset } msg]
- list $rc $msg
-} {1 SQLITE_ERROR}
-
-do_test 2.4 {
- set rc [catch { sqlite3changeset_concat {} $patchset } msg]
- list $rc $msg
-} [list 0 $patchset]
-
-do_test 2.5 {
- set rc [catch { sqlite3changeset_concat $patchset {} } msg]
- list $rc $msg
-} [list 0 $patchset]
-
-do_test 2.6 {
- set rc [catch { sqlite3changeset_concat {} $changeset } msg]
- list $rc $msg
-} [list 0 $changeset]
-
-do_test 2.7 {
- set rc [catch { sqlite3changeset_concat $changeset {} } msg]
- list $rc $msg
-} [list 0 $changeset]
-
-do_test 2.8 {
- set rc [catch { sqlite3changeset_concat {} {} } msg]
- list $rc $msg
-} [list 0 {}]
-
-
-#-------------------------------------------------------------------------
-# Test that the xFilter argument to sqlite3changeset_apply() works.
-#
-reset_db
-do_execsql_test 3.0 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(a PRIMARY KEY, b);
- CREATE TABLE t3(a PRIMARY KEY, b);
-}
-do_test 3.1 {
- execsql BEGIN
- set changeset [changeset_from_sql {
- INSERT INTO t1 VALUES(1, 1);
- INSERT INTO t2 VALUES(2, 2);
- INSERT INTO t3 VALUES(3, 3);
- }]
- execsql ROLLBACK
-} {}
-do_test 3.2 {
- proc xFilter {zName} {
- if {$zName == "t1"} { return 1 }
- return 0
- }
- sqlite3changeset_apply db $changeset noop xFilter
- execsql {
- SELECT * FROM t1;
- SELECT * FROM t2;
- SELECT * FROM t3;
- }
-} {1 1}
-do_test 3.3 {
- proc xFilter {zName} {
- if {$zName == "t3"} { return 1 }
- return 0
- }
- sqlite3changeset_apply db $changeset noop xFilter
- execsql {
- SELECT * FROM t1;
- SELECT * FROM t2;
- SELECT * FROM t3;
- }
-} {1 1 3 3}
-
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionD.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionD.test
deleted file mode 100644
index 84c31cbc2f2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionD.test
+++ /dev/null
@@ -1,258 +0,0 @@
-# 2014 August 16
-#
-# 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 focuses on the sqlite3session_diff() function.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix sessionD
-
-proc scksum {db dbname} {
-
- if {$dbname=="temp"} {
- set master sqlite_temp_master
- } else {
- set master $dbname.sqlite_master
- }
-
- set alltab [$db eval "SELECT name FROM $master WHERE type='table'"]
- set txt [$db eval "SELECT * FROM $master ORDER BY type,name,sql"]
- foreach tab $alltab {
- set cols [list]
- db eval "PRAGMA $dbname.table_info = $tab" x {
- lappend cols "quote($x(name))"
- }
- set cols [join $cols ,]
- append txt [db eval "SELECT $cols FROM $tab ORDER BY $cols"]
- }
- return [md5 $txt]
-}
-
-proc do_diff_test {tn setup} {
- reset_db
- forcedelete test.db2
- execsql { ATTACH 'test.db2' AS aux }
- execsql $setup
-
- sqlite3session S db main
- foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
- S attach $tbl
- S diff aux $tbl
- }
-
- set C [S changeset]
- S delete
-
- sqlite3 db2 test.db2
- sqlite3changeset_apply db2 $C ""
- uplevel do_test $tn.1 [list {execsql { PRAGMA integrity_check } db2}] ok
- db2 close
-
- set cksum [scksum db main]
- uplevel do_test $tn.2 [list {scksum db aux}] [list $cksum]
-}
-
-# Ensure that the diff produced by comparing the current contents of [db]
-# with itself is empty.
-proc do_empty_diff_test {tn} {
- forcedelete test.db2
- forcecopy test.db test.db2
-
- execsql { ATTACH 'test.db2' AS aux }
- sqlite3session S db main
- foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
- S attach $tbl
- S diff aux $tbl
- }
-
- set ::C [S changeset]
- S delete
-
- uplevel [list do_test $tn {string length $::C} 0]
-}
-
-
-forcedelete test.db2
-do_execsql_test 1.0 {
- CREATE TABLE t2(a PRIMARY KEY, b);
- INSERT INTO t2 VALUES(1, 'one');
- INSERT INTO t2 VALUES(2, 'two');
-
- ATTACH 'test.db2' AS aux;
- CREATE TABLE aux.t2(a PRIMARY KEY, b);
-}
-
-do_test 1.1 {
- sqlite3session S db main
- S attach t2
- S diff aux t2
- set C [S changeset]
- S delete
-} {}
-
-do_test 1.2 {
- sqlite3 db2 test.db2
- sqlite3changeset_apply db2 $C ""
- db2 close
- db eval { SELECT * FROM aux.t2 }
-} {1 one 2 two}
-
-do_diff_test 2.1 {
- CREATE TABLE aux.t1(x, y, PRIMARY KEY(y));
- CREATE TABLE t1(x, y, PRIMARY KEY(y));
-
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t1 VALUES(NULL, 'xyz');
- INSERT INTO t1 VALUES(4.5, 5.5);
-}
-
-do_diff_test 2.2 {
- CREATE TABLE aux.t1(x, y, PRIMARY KEY(y));
- CREATE TABLE t1(x, y, PRIMARY KEY(y));
-
- INSERT INTO aux.t1 VALUES(1, 2);
- INSERT INTO aux.t1 VALUES(NULL, 'xyz');
- INSERT INTO aux.t1 VALUES(4.5, 5.5);
-}
-
-do_diff_test 2.3 {
- CREATE TABLE aux.t1(a PRIMARY KEY, b TEXT);
- CREATE TABLE t1(a PRIMARY KEY, b TEXT);
-
- INSERT INTO aux.t1 VALUES(1, 'one');
- INSERT INTO aux.t1 VALUES(2, 'two');
- INSERT INTO aux.t1 VALUES(3, 'three');
-
- INSERT INTO t1 VALUES(1, 'I');
- INSERT INTO t1 VALUES(2, 'two');
- INSERT INTO t1 VALUES(3, 'III');
-}
-
-do_diff_test 2.4 {
- CREATE TABLE aux.t1(a, b, c, d, PRIMARY KEY(c, b, a));
- CREATE TABLE t1(a, b, c, d, PRIMARY KEY(c, b, a));
-
- INSERT INTO t1 VALUES('hvkzyipambwdqlvwv','',-458331.50,X'DA51ED5E84');
- INSERT INTO t1 VALUES(X'C5C6B5DD','jjxrath',40917,830244);
- INSERT INTO t1 VALUES(-204877.54,X'1704C253D5F3AFA8',155120.88,NULL);
- INSERT INTO t1
- VALUES('ckmqmzoeuvxisxqy',X'EB5A5D3A1DD22FD1','tidhjcbvbppdt',-642987.37);
- INSERT INTO t1 VALUES(-851726,-161992,-469943,-159541);
- INSERT INTO t1 VALUES(X'4A6A667F858938',185083,X'7A',NULL);
-
- INSERT INTO aux.t1 VALUES(415075.74,'auawczkb',X'',X'57B4FAAF2595');
- INSERT INTO aux.t1 VALUES(727637,711560,-181340,'hphuo');
- INSERT INTO aux.t1
- VALUES(-921322.81,662959,'lvlgwdgxaurr','ajjrzrbhqflsutnymgc');
- INSERT INTO aux.t1 VALUES(-146061,-377892,X'4E','gepvpvvuhszpxabbb');
- INSERT INTO aux.t1 VALUES(-851726,-161992,-469943,-159541);
- INSERT INTO aux.t1 VALUES(X'4A6A667F858938',185083,X'7A',NULL);
- INSERT INTO aux.t1 VALUES(-204877.54,X'1704C253D5F3AFA8',155120.88, 4);
- INSERT INTO aux.t1
- VALUES('ckmqmzoeuvxisxqy',X'EB5A5D3A1DD22FD1','tidgtsplhjcbvbppdt',-642987.3);
-}
-
-reset_db
-do_execsql_test 3.0 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a));
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t1 VALUES(7, 8, 9);
-
- CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b));
- INSERT INTO t2 VALUES(1, 2, 3);
- INSERT INTO t2 VALUES(4, 5, 6);
- INSERT INTO t2 VALUES(7, 8, 9);
-
- CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b, c));
- INSERT INTO t3 VALUES(1, 2, 3);
- INSERT INTO t3 VALUES(4, 5, 6);
- INSERT INTO t3 VALUES(7, 8, 9);
-}
-do_empty_diff_test 3.1
-
-
-#-------------------------------------------------------------------------
-# Test some error cases:
-#
-# 1) schema mismatches between the two dbs, and
-# 2) tables with no primary keys. This is not actually an error, but
-# should not add any changes to the session object.
-#
-reset_db
-forcedelete test.db2
-do_execsql_test 4.0 {
- ATTACH 'test.db2' AS ixua;
- CREATE TABLE ixua.t1(a, b, c);
- CREATE TABLE main.t1(a, b, c);
- INSERT INTO main.t1 VALUES(1, 2, 3);
-
- CREATE TABLE ixua.t2(a PRIMARY KEY, b, c);
- CREATE TABLE main.t2(a PRIMARY KEY, b, x);
-}
-
-do_test 4.1.1 {
- sqlite3session S db main
- S attach t1
- list [catch { S diff ixua t1 } msg] $msg
-} {0 {}}
-do_test 4.1.2 {
- string length [S changeset]
-} {0}
-S delete
-
-do_test 4.2.2 {
- sqlite3session S db main
- S attach t2
- list [catch { S diff ixua t2 } msg] $msg
-} {1 {SQLITE_SCHEMA - table schemas do not match}}
-S delete
-
-do_test 4.3.1 {
- sqlite3session S db main
- S attach t4
- execsql { CREATE TABLE t4(i PRIMARY KEY, b) }
- list [catch { S diff ixua t4 } msg] $msg
-} {1 {SQLITE_SCHEMA - table schemas do not match}}
-S delete
-do_catchsql_test 4.3.2 {
- SELECT * FROM ixua.t4;
-} {1 {no such table: ixua.t4}}
-
-do_test 4.4.1 {
- sqlite3session S db main
- S attach sqlite_stat1
- execsql { ANALYZE }
- execsql { DROP TABLE ixua.sqlite_stat1 }
- list [catch { S diff ixua sqlite_stat1 } msg] $msg
-} {1 {SQLITE_SCHEMA - table schemas do not match}}
-S delete
-do_catchsql_test 4.4.2 {
- SELECT * FROM ixua.sqlite_stat1;
-} {1 {no such table: ixua.sqlite_stat1}}
-
-do_test 4.5.1 {
- sqlite3session S db main
- S attach t8
- list [catch { S diff ixua t8 } msg] $msg
-} {0 {}}
-S delete
-do_catchsql_test 4.5.2 {
- SELECT * FROM ixua.i8;
-} {1 {no such table: ixua.i8}}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionE.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionE.test
deleted file mode 100644
index 9821dde816a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionE.test
+++ /dev/null
@@ -1,115 +0,0 @@
-# 2015 June 02
-#
-# 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 regression tests for the sessions module.
-# Specifically, it tests that operations on tables without primary keys
-# are ignored.
-#
-
-
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-set testprefix sessionE
-
-#
-# Test plan:
-#
-# 1.*: Test that non-PK tables are not auto-attached.
-# 2.*: Test that explicitly attaching a non-PK table is a no-op.
-# 3.*: Test that sqlite3session_diff() on a non-PK table is a no-op.
-#
-
-
-#--------------------------------------------------------------------------
-reset_db
-do_execsql_test 1.0 {
- CREATE TABLE t1(a, b);
- CREATE TABLE t2(a PRIMARY KEY, b);
-}
-do_test 1.1 {
- sqlite3session S db main
- S attach *
- execsql {
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t2 VALUES(1, 2);
- }
-} {}
-do_changeset_test 1.2 S {
- {INSERT t2 0 X. {} {i 1 i 2}}
-}
-S delete
-
-reset_db
-do_execsql_test 2.0 {
- CREATE TABLE t1(a, b);
- CREATE TABLE t2(a PRIMARY KEY, b);
-}
-do_test 2.1 {
- sqlite3session S db main
- S attach t1
- S attach t2
- execsql {
- INSERT INTO t1 VALUES(3, 4);
- INSERT INTO t2 VALUES(3, 4);
- INSERT INTO t1 VALUES(5, 6);
- INSERT INTO t2 VALUES(5, 6);
- }
-} {}
-do_changeset_test 2.2 S {
- {INSERT t2 0 X. {} {i 3 i 4}}
- {INSERT t2 0 X. {} {i 5 i 6}}
-}
-S delete
-
-reset_db
-forcedelete test.db2
-do_execsql_test 3.0 {
- ATTACH 'test.db2' AS aux;
- CREATE TABLE aux.t1(a, b);
- CREATE TABLE aux.t2(a PRIMARY KEY, b);
-
- CREATE TABLE t1(a, b);
- CREATE TABLE t2(a PRIMARY KEY, b);
-
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t2 VALUES(3, 4);
-}
-do_test 3.1 {
- sqlite3session S db main
- S attach t1
- S diff aux t1
-
- S attach t2
- S diff aux t2
-} {}
-do_changeset_test 3.2 S {
- {INSERT t2 0 X. {} {i 3 i 4}}
-}
-do_execsql_test 3.3 {
- INSERT INTO t1 VALUES(5, 6);
- INSERT INTO t2 VALUES(7, 8);
-}
-do_changeset_test 3.4 S {
- {INSERT t2 0 X. {} {i 3 i 4}}
- {INSERT t2 0 X. {} {i 7 i 8}}
-}
-
-
-S delete
-
-finish_test
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionF.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionF.test
deleted file mode 100644
index ba57bf85ec9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionF.test
+++ /dev/null
@@ -1,295 +0,0 @@
-# 2015 June 02
-#
-# 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 regression tests for the sessions module.
-# Specifically, it tests that tables appear in the correct order
-# within changesets and patchsets.
-#
-
-
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-set testprefix sessionF
-
-#
-# Test plan:
-#
-# 1.*: Test that sqlite3session_changeset() and sqlite3session_patchset()
-# output tables in the right order.
-#
-# 2.*: Test that sqlite3session_invert() does not modify the order of
-# tables within a changeset.
-#
-# 3.*: Test that sqlite3session_concat outputs tables in the right order.
-#
-
-# Create a db schema to use.
-#
-do_execsql_test 1.0 {
- CREATE TABLE t3(e PRIMARY KEY, f);
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(c PRIMARY KEY, d);
-}
-
-#-----------------------------------------------------------------------
-# 1.* - changeset() and patchset().
-#
-
-foreach {tn setup result} {
- 1 {
- S attach *
- } {
- {INSERT t2 0 X. {} {i 2 t two}}
- {INSERT t1 0 X. {} {i 1 t one}}
- {INSERT t3 0 X. {} {i 3 t three}}
- }
-
- 2 {
- S attach t1
- S attach *
- } {
- {INSERT t1 0 X. {} {i 1 t one}}
- {INSERT t2 0 X. {} {i 2 t two}}
- {INSERT t3 0 X. {} {i 3 t three}}
- }
-
- 3 {
- S attach t3
- S attach t2
- S attach t1
- } {
- {INSERT t3 0 X. {} {i 3 t three}}
- {INSERT t2 0 X. {} {i 2 t two}}
- {INSERT t1 0 X. {} {i 1 t one}}
- }
-} {
- execsql {
- DELETE FROM t1;
- DELETE FROM t2;
- DELETE FROM t3;
- }
- sqlite3session S db main
- eval $setup
-
- do_execsql_test 1.$tn.1 {
- INSERT INTO t2 VALUES(2, 'two');
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t3 VALUES(3, 'three');
- }
-
- do_changeset_test 1.1.$tn.2 S $result
- do_patchset_test 1.1.$tn.3 S $result
-
- S delete
-}
-
-foreach {tn setup result} {
- 1 {
- S attach *
- } {
- {INSERT t2 0 X. {} {i 4 t four}}
- {INSERT t2 0 X. {} {i 5 t five}}
- {INSERT t1 0 X. {} {i 1 t one}}
- {INSERT t3 0 X. {} {i 6 t six}}
- }
-
- 2 {
- S attach t1
- S attach *
- } {
- {INSERT t1 0 X. {} {i 1 t one}}
- {INSERT t2 0 X. {} {i 4 t four}}
- {INSERT t2 0 X. {} {i 5 t five}}
- {INSERT t3 0 X. {} {i 6 t six}}
- }
-
- 3 {
- S attach t3
- S attach t2
- S attach t1
- } {
- {INSERT t3 0 X. {} {i 6 t six}}
- {INSERT t2 0 X. {} {i 4 t four}}
- {INSERT t2 0 X. {} {i 5 t five}}
- {INSERT t1 0 X. {} {i 1 t one}}
- }
-} {
- execsql {
- DELETE FROM t1;
- DELETE FROM t2;
- DELETE FROM t3;
- }
- sqlite3session S db main
- eval $setup
-
- do_execsql_test 1.$tn.1 {
- INSERT INTO t2 VALUES(2, 'two');
- INSERT INTO t1 VALUES(1, 'one');
- DELETE FROM t2;
- INSERT INTO t2 VALUES(4, 'four');
- INSERT INTO t2 VALUES(5, 'five');
- INSERT INTO t3 VALUES(6, 'six');
- }
-
- do_changeset_test 1.2.$tn.2 S $result
- do_patchset_test 1.2.$tn.2 S $result
-
- S delete
-}
-
-#-------------------------------------------------------------------------
-# 2.* - invert()
-#
-
-foreach {tn setup result} {
- 1 {
- S attach *
- } {
- {DELETE t2 0 X. {i 4 t four} {}}
- {DELETE t2 0 X. {i 5 t five} {}}
- {DELETE t1 0 X. {i 1 t one} {}}
- {DELETE t3 0 X. {i 6 t six} {}}
- }
-
- 2 {
- S attach t1
- S attach *
- } {
- {DELETE t1 0 X. {i 1 t one} {}}
- {DELETE t2 0 X. {i 4 t four} {}}
- {DELETE t2 0 X. {i 5 t five} {}}
- {DELETE t3 0 X. {i 6 t six} {}}
- }
-
- 3 {
- S attach t3
- S attach t2
- S attach t1
- } {
- {DELETE t3 0 X. {i 6 t six} {}}
- {DELETE t2 0 X. {i 4 t four} {}}
- {DELETE t2 0 X. {i 5 t five} {}}
- {DELETE t1 0 X. {i 1 t one} {}}
- }
-} {
- execsql {
- DELETE FROM t1;
- DELETE FROM t2;
- DELETE FROM t3;
- }
- sqlite3session S db main
- eval $setup
-
- do_execsql_test 1.$tn.1 {
- INSERT INTO t2 VALUES(2, 'two');
- INSERT INTO t1 VALUES(1, 'one');
- DELETE FROM t2;
- INSERT INTO t2 VALUES(4, 'four');
- INSERT INTO t2 VALUES(5, 'five');
- INSERT INTO t3 VALUES(6, 'six');
- }
-
- do_changeset_invert_test 2.$tn.2 S $result
-
- S delete
-}
-
-#-------------------------------------------------------------------------
-# 3.* - concat()
-#
-foreach {tn setup1 sql1 setup2 sql2 result} {
- 1 {
- S attach *
- } {
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t2 VALUES(2, 'two');
- } {
- S attach t2
- S attach t1
- } {
- INSERT INTO t1 VALUES(3, 'three');
- INSERT INTO t2 VALUES(4, 'four');
- } {
- {INSERT t1 0 X. {} {i 1 t one}}
- {INSERT t1 0 X. {} {i 3 t three}}
- {INSERT t2 0 X. {} {i 2 t two}}
- {INSERT t2 0 X. {} {i 4 t four}}
- }
-
- 1 {
- S attach t2
- S attach t1
- } {
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t2 VALUES(2, 'two');
- } {
- S attach *
- } {
- INSERT INTO t1 VALUES(3, 'three');
- INSERT INTO t2 VALUES(4, 'four');
- } {
- {INSERT t2 0 X. {} {i 2 t two}}
- {INSERT t2 0 X. {} {i 4 t four}}
- {INSERT t1 0 X. {} {i 1 t one}}
- {INSERT t1 0 X. {} {i 3 t three}}
- }
-
- 1 {
- S attach *
- } {
- INSERT INTO t2 VALUES(2, 'two');
- } {
- S attach *
- } {
- INSERT INTO t1 VALUES(3, 'three');
- INSERT INTO t2 VALUES(4, 'four');
- INSERT INTO t3 VALUES(5, 'five');
- } {
- {INSERT t2 0 X. {} {i 2 t two}}
- {INSERT t2 0 X. {} {i 4 t four}}
- {INSERT t1 0 X. {} {i 3 t three}}
- {INSERT t3 0 X. {} {i 5 t five}}
- }
-
-} {
- execsql {
- DELETE FROM t1;
- DELETE FROM t2;
- DELETE FROM t3;
- }
- sqlite3session S db main
- eval $setup1
- execsql $sql1
- set c1 [S changeset]
- S delete
-
- sqlite3session S db main
- eval $setup2
- execsql $sql2
- set c2 [S changeset]
- S delete
-
- set res [list]
- sqlite3session_foreach x [sqlite3changeset_concat $c1 $c2] {
- lappend res $x
- }
-
- do_test 3.$tn { set res } [list {*}$result]
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionG.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionG.test
deleted file mode 100644
index 1b5f5473f02..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionG.test
+++ /dev/null
@@ -1,251 +0,0 @@
-# 2016 March 30
-#
-# 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 regression tests for the sessions module.
-# Specifically, it tests that UNIQUE constraints are dealt with correctly.
-#
-
-
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-set testprefix sessionG
-
-
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_test 1.0 {
- do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
- INSERT INTO t1 VALUES(3, 'three');
- }
- do_then_apply_sql {
- DELETE FROM t1 WHERE a=1;
- INSERT INTO t1 VALUES(4, 'one');
- }
- compare_db db db2
-} {}
-
-do_test 1.1 {
- do_then_apply_sql {
- DELETE FROM t1 WHERE a=4;
- INSERT INTO t1 VALUES(1, 'one');
- }
- compare_db db db2
-} {}
-
-do_test 1.2 {
- execsql { INSERT INTO t1 VALUES(5, 'five') } db2
- do_then_apply_sql {
- INSERT INTO t1 VALUES(11, 'eleven');
- INSERT INTO t1 VALUES(12, 'five');
- }
- execsql { SELECT * FROM t1 } db2
-} {2 two 3 three 1 one 5 five 11 eleven}
-
-do_test 1.3 {
- execsql { SELECT * FROM t1 }
-} {2 two 3 three 1 one 11 eleven 12 five}
-
-#-------------------------------------------------------------------------
-#
-reset_db
-db2 close
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_test 2.1 {
- do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
- }
-} {}
-
-do_test 2.2.1 {
- # It is not possible to apply the changeset generated by the following
- # SQL, as none of the three updated rows may be updated as part of the
- # first pass.
- do_then_apply_sql {
- UPDATE t1 SET b=0 WHERE a=1;
- UPDATE t1 SET b=1 WHERE a=2;
- UPDATE t1 SET b=2 WHERE a=3;
- UPDATE t1 SET b=3 WHERE a=1;
- }
- db2 eval { SELECT a, b FROM t1 }
-} {1 1 2 2 3 3}
-do_test 2.2.2 { db eval { SELECT a, b FROM t1 } } {1 3 2 1 3 2}
-
-#-------------------------------------------------------------------------
-#
-reset_db
-db2 close
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_test 3.1 {
- do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE);
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
- }
-} {}
-
-do_test 3.3 {
- do_then_apply_sql {
- UPDATE t1 SET b=4 WHERE a=3;
- UPDATE t1 SET b=3 WHERE a=2;
- UPDATE t1 SET b=2 WHERE a=1;
- }
- compare_db db db2
-} {}
-
-do_test 3.4 {
- do_then_apply_sql {
- UPDATE t1 SET b=1 WHERE a=1;
- UPDATE t1 SET b=2 WHERE a=2;
- UPDATE t1 SET b=3 WHERE a=3;
- }
- compare_db db db2
-} {}
-
-#-------------------------------------------------------------------------
-#
-reset_db
-db2 close
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_test 4.1 {
- do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
- INSERT INTO t1 VALUES(1, 1);
- INSERT INTO t1 VALUES(2, 2);
- INSERT INTO t1 VALUES(3, 3);
-
- CREATE TABLE t2(a PRIMARY KEY, b UNIQUE);
- INSERT INTO t2 VALUES(1, 1);
- INSERT INTO t2 VALUES(2, 2);
- INSERT INTO t2 VALUES(3, 3);
- }
-} {}
-
-do_test 4.2 {
- do_then_apply_sql {
- UPDATE t1 SET b=4 WHERE a=3;
- UPDATE t1 SET b=3 WHERE a=2;
- UPDATE t1 SET b=2 WHERE a=1;
-
- UPDATE t2 SET b=0 WHERE a=1;
- UPDATE t2 SET b=1 WHERE a=2;
- UPDATE t2 SET b=2 WHERE a=3;
- }
- compare_db db db2
-} {}
-
-do_test 4.3 {
- do_then_apply_sql {
- UPDATE t1 SET b=1 WHERE a=1;
- UPDATE t1 SET b=2 WHERE a=2;
- UPDATE t1 SET b=3 WHERE a=3;
-
- UPDATE t2 SET b=3 WHERE a=3;
- UPDATE t2 SET b=2 WHERE a=2;
- UPDATE t2 SET b=1 WHERE a=1;
- }
- compare_db db db2
-} {}
-
-#-------------------------------------------------------------------------
-reset_db
-catch { db2 close }
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_execsql_test 5.0.1 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE TABLE t2(a, b, c PRIMARY KEY);
- CREATE TABLE t3(a, b PRIMARY KEY, c);
-}
-do_execsql_test -db db2 5.0.2 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE TABLE t2(a, b, c);
- CREATE TABLE t3(a, b PRIMARY KEY, c);
-}
-
-do_test 5.1 {
- do_then_apply_sql {
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t2 VALUES(4, 5, 6);
- INSERT INTO t3 VALUES(7, 8, 9);
- }
-
- db2 eval {
- SELECT * FROM t1;
- SELECT * FROM t2;
- SELECT * FROM t3;
- }
-} {1 2 3 7 8 9}
-
-#-------------------------------------------------------------------------
-
-reset_db
-db func number_name number_name
-do_execsql_test 6.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- CREATE UNIQUE INDEX t1b ON t1(b);
- WITH s(i) AS (
- SELECT 1
- UNION ALL
- SELECT i+1 FROM s WHERE i<1000
- )
- INSERT INTO t1 SELECT i, number_name(i) FROM s;
-}
-
-do_test 6.1 {
- db eval BEGIN
- set ::C [changeset_from_sql {
- DELETE FROM t1;
- WITH s(i) AS (
- SELECT 1
- UNION ALL
- SELECT i+1 FROM s WHERE i<1000
- )
- INSERT INTO t1 SELECT i, number_name(i+1) FROM s;
- }]
- db eval ROLLBACK
- execsql { SELECT count(*) FROM t1 WHERE number_name(a) IS NOT b }
-} {0}
-
-proc xConflict {args} { exit ; return "OMIT" }
-do_test 6.2 {
- sqlite3changeset_apply db $C xConflict
-} {}
-
-do_execsql_test 6.3 { SELECT count(*) FROM t1; } {1000}
-do_execsql_test 6.4 {
- SELECT count(*) FROM t1 WHERE number_name(a+1) IS NOT b;
-} {0}
-
-# db eval { SELECT * FROM t1 } { puts "$a || $b" }
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionH.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionH.test
deleted file mode 100644
index 643fdb3fbe9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionH.test
+++ /dev/null
@@ -1,39 +0,0 @@
-# 2018 January 18
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-set testprefix sessionH
-
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_test 1.0 {
- do_common_sql {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
- }
- do_then_apply_sql {
- WITH s(i) AS (
- VALUES(1) UNION ALL SELECT i+1 FROM s WHERe i<10000
- )
- INSERT INTO t1 SELECT 'abcde', randomblob(16), i FROM s;
- }
- compare_db db db2
-} {}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session_common.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session_common.tcl
deleted file mode 100644
index 543b9703277..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session_common.tcl
+++ /dev/null
@@ -1,198 +0,0 @@
-
-proc do_changeset_test {tn session res} {
- set r [list]
- foreach x $res {lappend r $x}
- uplevel do_test $tn [list [subst -nocommands {
- set x [list]
- sqlite3session_foreach c [$session changeset] { lappend x [set c] }
- set x
- }]] [list $r]
-}
-
-proc do_patchset_test {tn session res} {
- set r [list]
- foreach x $res {lappend r $x}
- uplevel do_test $tn [list [subst -nocommands {
- set x [list]
- sqlite3session_foreach c [$session patchset] { lappend x [set c] }
- set x
- }]] [list $r]
-}
-
-
-proc do_changeset_invert_test {tn session res} {
- set r [list]
- foreach x $res {lappend r $x}
- uplevel do_test $tn [list [subst -nocommands {
- set x [list]
- set changeset [sqlite3changeset_invert [$session changeset]]
- sqlite3session_foreach c [set changeset] { lappend x [set c] }
- set x
- }]] [list $r]
-}
-
-
-proc do_conflict_test {tn args} {
-
- set O(-tables) [list]
- set O(-sql) [list]
- set O(-conflicts) [list]
- set O(-policy) "OMIT"
-
- array set V $args
- foreach key [array names V] {
- if {![info exists O($key)]} {error "no such option: $key"}
- }
- array set O $args
-
- proc xConflict {args} [subst -nocommands {
- lappend ::xConflict [set args]
- return $O(-policy)
- }]
- proc bgerror {args} { set ::background_error $args }
-
- sqlite3session S db main
- foreach t $O(-tables) { S attach $t }
- execsql $O(-sql)
-
- set ::xConflict [list]
- sqlite3changeset_apply db2 [S changeset] xConflict
-
- set conflicts [list]
- foreach c $O(-conflicts) {
- lappend conflicts $c
- }
-
- after 1 {set go 1}
- vwait go
-
- uplevel do_test $tn [list { set ::xConflict }] [list $conflicts]
- S delete
-}
-
-proc do_common_sql {sql} {
- execsql $sql db
- execsql $sql db2
-}
-
-proc changeset_from_sql {sql {dbname main}} {
- if {$dbname == "main"} {
- return [sql_exec_changeset db $sql]
- }
- set rc [catch {
- sqlite3session S db $dbname
- db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
- S attach $name
- }
- db eval $sql
- S changeset
- } changeset]
- catch { S delete }
-
- if {$rc} {
- error $changeset
- }
- return $changeset
-}
-
-proc do_then_apply_sql {sql {dbname main}} {
- proc xConflict args { return "OMIT" }
- set rc [catch {
- sqlite3session S db $dbname
- db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
- S attach $name
- }
- db eval $sql
- sqlite3changeset_apply db2 [S changeset] xConflict
- } msg]
-
- catch { S delete }
-
- if {$rc} {error $msg}
-}
-
-proc do_iterator_test {tn tbl_list sql res} {
- sqlite3session S db main
- if {[llength $tbl_list]==0} { S attach * }
- foreach t $tbl_list {S attach $t}
-
- execsql $sql
-
- set r [list]
- foreach v $res { lappend r $v }
-
- set x [list]
- sqlite3session_foreach c [S changeset] { lappend x $c }
- uplevel do_test $tn [list [list set {} $x]] [list $r]
-
- S delete
-}
-
-# Compare the contents of all tables in [db1] and [db2]. Throw an error if
-# they are not identical, or return an empty string if they are.
-#
-proc compare_db {db1 db2} {
-
- set sql {SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name}
- set lot1 [$db1 eval $sql]
- set lot2 [$db2 eval $sql]
-
- if {$lot1 != $lot2} {
- puts $lot1
- puts $lot2
- error "databases contain different tables"
- }
-
- foreach tbl $lot1 {
- set col1 [list]
- set col2 [list]
-
- $db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name }
- $db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name }
- if {$col1 != $col2} { error "table $tbl schema mismatch" }
-
- set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]"
- set data1 [$db1 eval $sql]
- set data2 [$db2 eval $sql]
- if {$data1 != $data2} {
- puts "$data1"
- puts "$data2"
- error "table $tbl data mismatch"
- }
- }
-
- return ""
-}
-
-proc changeset_to_list {c} {
- set list [list]
- sqlite3session_foreach elem $c { lappend list $elem }
- lsort $list
-}
-
-set ones {zero one two three four five six seven eight nine
- ten eleven twelve thirteen fourteen fifteen sixteen seventeen
- eighteen nineteen}
-set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
-proc number_name {n} {
- if {$n>=1000} {
- set txt "[number_name [expr {$n/1000}]] thousand"
- set n [expr {$n%1000}]
- } else {
- set txt {}
- }
- if {$n>=100} {
- append txt " [lindex $::ones [expr {$n/100}]] hundred"
- set n [expr {$n%100}]
- }
- if {$n>=20} {
- append txt " [lindex $::tens [expr {$n/10}]]"
- set n [expr {$n%10}]
- }
- if {$n>0} {
- append txt " [lindex $::ones $n]"
- }
- set txt [string trim $txt]
- if {$txt==""} {set txt zero}
- return $txt
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session_speed_test.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session_speed_test.c
deleted file mode 100644
index 14b97ea07b6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/session_speed_test.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
-** 2017 January 31
-**
-** 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 contains the source code for a standalone program used to
-** test the performance of the sessions module. Compile and run:
-**
-** ./session_speed_test -help
-**
-** for details.
-*/
-
-#include "sqlite3.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stddef.h>
-#include <unistd.h>
-
-/*************************************************************************
-** Start of generic command line parser.
-*/
-#define CMDLINE_BARE 0
-#define CMDLINE_INTEGER 1
-#define CMDLINE_STRING 2
-#define CMDLINE_BOOLEAN 3
-
-typedef struct CmdLineOption CmdLineOption;
-struct CmdLineOption {
- const char *zText; /* Name of command line option */
- const char *zHelp; /* Help text for option */
- int eType; /* One of the CMDLINE_* values */
- int iOff; /* Offset of output variable */
-};
-
-#define CMDLINE_INT32(x,y,z) {x, y, CMDLINE_INTEGER, z}
-#define CMDLINE_BOOL(x,y,z) {x, y, CMDLINE_BOOLEAN, z}
-#define CMDLINE_TEXT(x,y,z) {x, y, CMDLINE_STRING, z}
-#define CMDLINE_NONE(x,y,z) {x, y, CMDLINE_BARE, z}
-
-static void option_requires_argument_error(CmdLineOption *pOpt){
- fprintf(stderr, "Option requires a%s argument: %s\n",
- pOpt->eType==CMDLINE_INTEGER ? "n integer" :
- pOpt->eType==CMDLINE_STRING ? " string" : " boolean",
- pOpt->zText
- );
- exit(1);
-}
-
-static void ambiguous_option_error(const char *zArg){
- fprintf(stderr, "Option is ambiguous: %s\n", zArg);
- exit(1);
-}
-
-static void unknown_option_error(
- const char *zArg,
- CmdLineOption *aOpt,
- const char *zHelp
-){
- int i;
- fprintf(stderr, "Unknown option: %s\n", zArg);
- fprintf(stderr, "\nOptions are:\n");
- fprintf(stderr, " % -30sEcho command line options\n", "-cmdline:verbose");
- for(i=0; aOpt[i].zText; i++){
- int eType = aOpt[i].eType;
- char *zOpt = sqlite3_mprintf("%s %s", aOpt[i].zText,
- eType==CMDLINE_BARE ? "" :
- eType==CMDLINE_INTEGER ? "N" :
- eType==CMDLINE_BOOLEAN ? "BOOLEAN" : "TEXT"
- );
- fprintf(stderr, " % -30s%s\n", zOpt, aOpt[i].zHelp);
- sqlite3_free(zOpt);
- }
- if( zHelp ){
- fprintf(stderr, "\n%s\n", zHelp);
- }
- exit(1);
-}
-
-static int get_integer_option(CmdLineOption *pOpt, const char *zArg){
- int i = 0;
- int iRet = 0;
- int bSign = 1;
- if( zArg[0]=='-' ){
- bSign = -1;
- i = 1;
- }
- while( zArg[i] ){
- if( zArg[i]<'0' || zArg[i]>'9' ) option_requires_argument_error(pOpt);
- iRet = iRet*10 + (zArg[i] - '0');
- i++;
- }
- return (iRet*bSign);
-}
-
-static int get_boolean_option(CmdLineOption *pOpt, const char *zArg){
- if( 0==sqlite3_stricmp(zArg, "true") ) return 1;
- if( 0==sqlite3_stricmp(zArg, "1") ) return 1;
- if( 0==sqlite3_stricmp(zArg, "0") ) return 0;
- if( 0==sqlite3_stricmp(zArg, "false") ) return 0;
- option_requires_argument_error(pOpt);
- return 0;
-}
-
-static void parse_command_line(
- int argc,
- char **argv,
- int iStart,
- CmdLineOption *aOpt,
- void *pStruct,
- const char *zHelp
-){
- char *pOut = (char*)pStruct;
- int bVerbose = 0;
- int iArg;
-
- for(iArg=iStart; iArg<argc; iArg++){
- const char *zArg = argv[iArg];
- int nArg = strlen(zArg);
- int nMatch = 0;
- int iOpt;
-
- for(iOpt=0; aOpt[iOpt].zText; iOpt++){
- CmdLineOption *pOpt = &aOpt[iOpt];
- if( 0==sqlite3_strnicmp(pOpt->zText, zArg, nArg) ){
- if( nMatch ){
- ambiguous_option_error(zArg);
- }
- nMatch++;
- if( pOpt->eType==CMDLINE_BARE ){
- *(int*)(&pOut[pOpt->iOff]) = 1;
- }else{
- iArg++;
- if( iArg==argc ){
- option_requires_argument_error(pOpt);
- }
- switch( pOpt->eType ){
- case CMDLINE_INTEGER:
- *(int*)(&pOut[pOpt->iOff]) = get_integer_option(pOpt, argv[iArg]);
- break;
- case CMDLINE_STRING:
- *(const char**)(&pOut[pOpt->iOff]) = argv[iArg];
- break;
- case CMDLINE_BOOLEAN:
- *(int*)(&pOut[pOpt->iOff]) = get_boolean_option(pOpt, argv[iArg]);
- break;
- }
- }
- }
- }
-
- if( nMatch==0 && 0==sqlite3_strnicmp("-cmdline:verbose", zArg, nArg) ){
- bVerbose = 1;
- nMatch = 1;
- }
-
- if( nMatch==0 ){
- unknown_option_error(zArg, aOpt, zHelp);
- }
- }
-
- if( bVerbose ){
- int iOpt;
- fprintf(stdout, "Options are: ");
- for(iOpt=0; aOpt[iOpt].zText; iOpt++){
- CmdLineOption *pOpt = &aOpt[iOpt];
- if( pOpt->eType!=CMDLINE_BARE || *(int*)(&pOut[pOpt->iOff]) ){
- fprintf(stdout, "%s ", pOpt->zText);
- }
- switch( pOpt->eType ){
- case CMDLINE_INTEGER:
- fprintf(stdout, "%d ", *(int*)(&pOut[pOpt->iOff]));
- break;
- case CMDLINE_BOOLEAN:
- fprintf(stdout, "%d ", *(int*)(&pOut[pOpt->iOff]));
- break;
- case CMDLINE_STRING:
- fprintf(stdout, "%s ", *(const char**)(&pOut[pOpt->iOff]));
- break;
- }
- }
- fprintf(stdout, "\n");
- }
-}
-/*
-** End of generic command line parser.
-*************************************************************************/
-
-static void abort_due_to_error(int rc){
- fprintf(stderr, "Error: %d\n");
- exit(-1);
-}
-
-static void execsql(sqlite3 *db, const char *zSql){
- int rc = sqlite3_exec(db, zSql, 0, 0, 0);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
-}
-
-static int xConflict(void *pCtx, int eConflict, sqlite3_changeset_iter *p){
- return SQLITE_CHANGESET_ABORT;
-}
-
-static void run_test(
- sqlite3 *db,
- sqlite3 *db2,
- int nRow,
- const char *zSql
-){
- sqlite3_session *pSession = 0;
- sqlite3_stmt *pStmt = 0;
- int rc;
- int i;
- int nChangeset;
- void *pChangeset;
-
- /* Attach a session object to database db */
- rc = sqlite3session_create(db, "main", &pSession);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
-
- /* Configure the session to capture changes on all tables */
- rc = sqlite3session_attach(pSession, 0);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
-
- /* Prepare the SQL statement */
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
-
- /* Open a transaction */
- execsql(db, "BEGIN");
-
- /* Execute the SQL statement nRow times */
- for(i=0; i<nRow; i++){
- sqlite3_bind_int(pStmt, 1, i);
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
- }
- sqlite3_finalize(pStmt);
-
- /* Extract a changeset from the sessions object */
- rc = sqlite3session_changeset(pSession, &nChangeset, &pChangeset);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
- execsql(db, "COMMIT");
-
- /* Apply the changeset to the second db */
- rc = sqlite3changeset_apply(db2, nChangeset, pChangeset, 0, xConflict, 0);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
-
- /* Cleanup */
- sqlite3_free(pChangeset);
- sqlite3session_delete(pSession);
-}
-
-int main(int argc, char **argv){
- struct Options {
- int nRow;
- int bWithoutRowid;
- int bInteger;
- int bAll;
- const char *zDb;
- };
- struct Options o = { 2500, 0, 0, 0, "session_speed_test.db" };
-
- CmdLineOption aOpt[] = {
- CMDLINE_INT32( "-rows", "number of rows in test",
- offsetof(struct Options, nRow) ),
- CMDLINE_BOOL("-without-rowid", "use WITHOUT ROWID tables",
- offsetof(struct Options, bWithoutRowid) ),
- CMDLINE_BOOL("-integer", "use integer data (instead of text/blobs)",
- offsetof(struct Options, bInteger) ),
- CMDLINE_NONE("-all", "Run all 4 combos of -without-rowid and -integer",
- offsetof(struct Options, bAll) ),
- CMDLINE_TEXT("-database", "prefix for database files to use",
- offsetof(struct Options, zDb) ),
- {0, 0, 0, 0}
- };
-
- const char *azCreate[] = {
- "CREATE TABLE t1(a PRIMARY KEY, b, c, d)",
- "CREATE TABLE t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID",
- };
-
- const char *azInsert[] = {
- "INSERT INTO t1 VALUES("
- "printf('%.8d',?), randomblob(50), randomblob(50), randomblob(50))",
- "INSERT INTO t1 VALUES(?, random(), random(), random())"
- };
-
- const char *azUpdate[] = {
- "UPDATE t1 SET d = randomblob(50) WHERE a = printf('%.8d',?)",
- "UPDATE t1 SET d = random() WHERE a = ?"
- };
-
- const char *azDelete[] = {
- "DELETE FROM t1 WHERE a = printf('%.8d',?)",
- "DELETE FROM t1 WHERE a = ?"
- };
-
- int rc;
- sqlite3 *db;
- sqlite3 *db2;
- char *zDb2;
- int bWithoutRowid;
- int bInteger;
-
- parse_command_line(argc, argv, 1, aOpt, (void*)&o,
- "This program creates two new, empty, databases each containing a single\n"
- "table. It then does the following:\n\n"
- " 1. Inserts -rows rows into the first database\n"
- " 2. Updates each row in the first db\n"
- " 3. Delete each row from the first db\n\n"
- "The modifications made by each step are captured in a changeset and\n"
- "applied to the second database.\n"
- );
- zDb2 = sqlite3_mprintf("%s2", o.zDb);
-
- for(bWithoutRowid=0; bWithoutRowid<2; bWithoutRowid++){
- for(bInteger=0; bInteger<2; bInteger++){
- if( o.bAll || (o.bWithoutRowid==bWithoutRowid && o.bInteger==bInteger) ){
- fprintf(stdout, "Testing %s data with %s table\n",
- bInteger ? "integer" : "blob/text",
- bWithoutRowid ? "WITHOUT ROWID" : "rowid"
- );
-
- /* Open new database handles on two empty databases */
- unlink(o.zDb);
- rc = sqlite3_open(o.zDb, &db);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
- unlink(zDb2);
- rc = sqlite3_open(zDb2, &db2);
- if( rc!=SQLITE_OK ) abort_due_to_error(rc);
-
- /* Create the schema in both databases. */
- execsql(db, azCreate[o.bWithoutRowid]);
- execsql(db2, azCreate[o.bWithoutRowid]);
-
- /* Run the three tests */
- run_test(db, db2, o.nRow, azInsert[o.bInteger]);
- run_test(db, db2, o.nRow, azUpdate[o.bInteger]);
- run_test(db, db2, o.nRow, azDelete[o.bInteger]);
-
- /* Close the db handles */
- sqlite3_close(db);
- sqlite3_close(db2);
- }
- }
- }
-
-
- return 0;
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionat.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionat.test
deleted file mode 100644
index 4a3f59a4415..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionat.test
+++ /dev/null
@@ -1,249 +0,0 @@
-# 2017 February 04
-#
-# 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.
-#
-#***********************************************************************
-#
-# Tests for the sessions module. Specifically, that a changeset can
-# be applied after ALTER TABLE ADD COLUMN has been used to add
-# columns to tables.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix sessionat
-
-db close
-sqlite3_shutdown
-test_sqlite3_log log
-proc log {code msg} { lappend ::log $code $msg }
-
-proc reset_test {} {
- catch { db close }
- catch { db2 close }
- forcedelete test.db test.db2
- sqlite3 db test.db
- sqlite3 db2 test.db2
-}
-
-
-# Run all tests in this file twice. Once with "WITHOUT ROWID", and once
-# with regular rowid tables.
-#
-# ?.1.*: Test that PK inconsistencies are detected if one or more of the PK
-# columns are not present in the changeset.
-#
-# ?.2.*: Test that it is not possible to apply a changeset with N columns
-# to a db with fewer than N columns.
-#
-# ?.3.*: Test some INSERT, UPDATE and DELETE operations that do not
-# require conflict handling.
-#
-# ?.4.*: Test some INSERT, UPDATE and DELETE operations that do require
-# conflict handling.
-#
-# ?.5.*: Test that attempting to concat two changesets with different
-# numbers of columns for the same table is an error.
-#
-foreach {tn trailing} {
- sessionat-ipk ""
- sessionat-wor " WITHOUT ROWID "
-} {
-eval [string map [list %WR% $trailing] {
- reset_test
-
- #-----------------------------------------------------------------------
- do_execsql_test $tn.1.0 {
- CREATE TABLE t1(a, b, PRIMARY KEY(a)) %WR%;
- }
- do_execsql_test -db db2 $tn.1.1 {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)) %WR%;
- }
- do_test $tn.1.2 {
- set ::log {}
- do_then_apply_sql { INSERT INTO t1 VALUES('one', 'two') }
- set ::log
- } [list \
- SQLITE_SCHEMA {sqlite3changeset_apply(): primary key mismatch for table t1}
- ]
- do_execsql_test $tn.1.3 { SELECT * FROM t1 } {one two}
- do_execsql_test -db db2 $tn.1.4 { SELECT * FROM t1 } {}
-
- #-----------------------------------------------------------------------
- do_execsql_test $tn.2.0 {
- CREATE TABLE t2(x, y, z, PRIMARY KEY(x)) %WR%;
- }
- do_execsql_test -db db2 $tn.2.1 {
- CREATE TABLE t2(x, y, PRIMARY KEY(x)) %WR%;
- }
- do_test $tn.2.2 {
- db cache flush
- set ::log {}
- do_then_apply_sql { INSERT INTO t2 VALUES(1, 2, 3) }
- set ::log
- } [list SQLITE_SCHEMA \
- {sqlite3changeset_apply(): table t2 has 2 columns, expected 3 or more}
- ]
- do_execsql_test $tn.2.3 { SELECT * FROM t2 } {1 2 3}
- do_execsql_test -db db2 $tn.2.4 { SELECT * FROM t2 } {}
-
- #-----------------------------------------------------------------------
- do_execsql_test $tn.3.0 {
- CREATE TABLE t3(a, b, PRIMARY KEY(b)) %WR%;
- }
- do_execsql_test -db db2 $tn.3.1 {
- CREATE TABLE t3(a, b, c DEFAULT 'D', PRIMARY KEY(b)) %WR%;
- }
- do_test $tn.3.2 {
- do_then_apply_sql {
- INSERT INTO t3 VALUES(1, 2);
- INSERT INTO t3 VALUES(3, 4);
- INSERT INTO t3 VALUES(5, 6);
- };
- db2 eval {SELECT * FROM t3}
- } {1 2 D 3 4 D 5 6 D}
- do_test $tn.3.3 {
- do_then_apply_sql {
- UPDATE t3 SET a=45 WHERE b=4;
- DELETE FROM t3 WHERE a=5;
- };
- db2 eval {SELECT * FROM t3}
- } {1 2 D 45 4 D}
-
- #-----------------------------------------------------------------------
- # 4.1: INSERT statements
- # 4.2: DELETE statements
- # 4.3: UPDATE statements
- #
- do_execsql_test $tn.4.1.0 {
- CREATE TABLE t4(x INTEGER PRIMARY KEY, y) %WR%;
- }
- do_execsql_test -db db2 $tn.4.1.1 {
- CREATE TABLE t4(x INTEGER PRIMARY KEY, y, z) %WR%;
- INSERT INTO t4 VALUES(1, 2, 3);
- INSERT INTO t4 VALUES(4, 5, 6);
- }
- do_conflict_test $tn.4.1.2 -tables t4 -sql {
- INSERT INTO t4 VALUES(10, 20);
- INSERT INTO t4 VALUES(4, 11);
- } -conflicts {
- {INSERT t4 CONFLICT {i 4 i 11} {i 4 i 5}}
- }
- do_execsql_test -db db2 $tn.4.1.3 {
- SELECT * FROM t4 ORDER BY x
- } {1 2 3 4 5 6 10 20 {}}
- do_conflict_test $tn.4.1.4 -policy REPLACE -tables t4 -sql {
- INSERT INTO t4 VALUES(1, 11);
- } -conflicts {
- {INSERT t4 CONFLICT {i 1 i 11} {i 1 i 2}}
- }
- do_execsql_test -db db2 $tn.4.1.5 {
- SELECT * FROM t4 ORDER BY x
- } {1 11 {} 4 5 6 10 20 {}}
-
- do_execsql_test $tn.4.2.0 {
- DELETE FROM t4;
- INSERT INTO t4 VALUES(1, 'A');
- INSERT INTO t4 VALUES(2, 'B');
- INSERT INTO t4 VALUES(3, 'C');
- INSERT INTO t4 VALUES(4, 'D');
- }
- do_execsql_test -db db2 $tn.4.2.1 {
- DELETE FROM t4;
- INSERT INTO t4 VALUES(1, 'A', 'a');
- INSERT INTO t4 VALUES(3, 'C', 'c');
- INSERT INTO t4 VALUES(4, 'E', 'd');
- }
- do_conflict_test $tn.4.2.2 -tables t4 -sql {
- DELETE FROM t4 WHERE x=2;
- DELETE FROM t4 WHERE x=4;
- } -conflicts {
- {DELETE t4 NOTFOUND {i 2 t B}}
- {DELETE t4 DATA {i 4 t D} {i 4 t E}}
- }
-
- do_execsql_test $tn.4.3.0 {
- CREATE TABLE t5(a, b, c PRIMARY KEY) %WR%;
- INSERT INTO t5 VALUES(1,1,1), (2,2,2), (3,3,3), (4,4,4);
- }
- do_execsql_test -db db2 $tn.4.3.1 {
- CREATE TABLE t5(a, b, c PRIMARY KEY, d CHECK(b!=10)) %WR%;
- INSERT INTO t5 VALUES (2,2,2,2), (3,8,3,3), (4,4,4,4);
- }
- do_conflict_test $tn.4.3.2 -tables t5 -sql {
- UPDATE t5 SET a=4 WHERE c=1;
- UPDATE t5 SET b=9 WHERE c=3;
- UPDATE t5 SET b=10 WHERE c=2;
- } -conflicts {
- {UPDATE t5 NOTFOUND {i 1 {} {} i 1} {i 4 {} {} {} {}}}
- {UPDATE t5 DATA {{} {} i 3 i 3} {{} {} i 9 {} {}} {i 3 i 8 i 3}}
- {UPDATE t5 CONSTRAINT {{} {} i 2 i 2} {{} {} i 10 {} {}}}
- }
-
- #-----------------------------------------------------------------------
- do_execsql_test $tn.5.0 {
- CREATE TABLE t6(a, b, c, PRIMARY KEY(a, b)) %WR%;
- }
- do_execsql_test -db db2 $tn.5.1 {
- CREATE TABLE t6(a, b, c, d, e, PRIMARY KEY(a, b)) %WR%;
- }
- do_test $tn.5.2 {
- set c1 [sql_exec_changeset db {
- INSERT INTO t6 VALUES(1, 1, 1);
- INSERT INTO t6 VALUES(2, 2, 2);
- }]
- set c2 [sql_exec_changeset db2 {
- INSERT INTO t6 VALUES(3, 3, 3, 3, 3);
- INSERT INTO t6 VALUES(4, 4, 4, 4, 4);
- }]
- list [catch { sqlite3changeset_concat $c1 $c2} msg] $msg
- } {1 SQLITE_SCHEMA}
-
- #-----------------------------------------------------------------------
- db2 close
- sqlite3 db2 test.db
- do_execsql_test $tn.6.0 {
- CREATE TABLE t7(a INTEGER PRIMARY KEY, b) %WR%;
- INSERT INTO t7 VALUES(1, 1);
- INSERT INTO t7 VALUES(2, 2);
- INSERT INTO t7 VALUES(3, 3);
- }
-
- do_test $tn.6.1 {
- set c1 [sql_exec_changeset db {
- INSERT INTO t7 VALUES(4, 4);
- DELETE FROM t7 WHERE a=1;
- UPDATE t7 SET b=222 WHERE a=2;
- }]
- set cinv [sqlite3changeset_invert $c1]
- execsql { SELECT * FROM t7 }
- } {2 222 3 3 4 4}
-
- do_execsql_test -db db2 $tn.6.2 {
- ALTER TABLE t7 ADD COLUMN c DEFAULT 'ccc'
- }
-
- proc xConfict {args} { return "OMIT" }
- do_test $tn.6.3 {
- sqlite3changeset_apply db $cinv xConflict
- execsql { SELECT * FROM t7 }
- } {1 1 ccc 2 2 ccc 3 3 ccc}
-}]
-}
-
-catch { db close }
-catch { db2 close }
-sqlite3_shutdown
-test_sqlite3_log
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessiondiff.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessiondiff.test
deleted file mode 100644
index b00af0eb3b8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessiondiff.test
+++ /dev/null
@@ -1,114 +0,0 @@
-# 2015-07-31
-#
-# 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.
-#
-#***********************************************************************
-#
-# Tests for the [sqldiff --changeset] command.
-#
-#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-set testprefix sessiondiff
-
-set PROG [test_find_sqldiff]
-db close
-
-proc sqlesc {id} {
- set ret "'[string map {' ''} $id]'"
- set ret
-}
-
-proc database_cksum {db1} {
- set txt ""
-
- sqlite3 dbtmp $db1
- foreach tbl [dbtmp eval {SELECT name FROM sqlite_master WHERE type='table'}] {
- set cols [list]
- dbtmp eval "PRAGMA table_info = [sqlesc $tbl]" {
- lappend cols "quote( $name )"
- }
- append txt [dbtmp eval \
- "SELECT [join $cols {||'.'||}] FROM [sqlesc $tbl] ORDER BY 1"
- ]
- }
- dbtmp close
-
- md5 $txt
-}
-
-proc readfile {filename} {
- set fd [open $filename]
- fconfigure $fd -translation binary -encoding binary
- set data [read $fd]
- close $fd
- set data
-}
-
-proc get_changeset {db1 db2} {
- exec $::PROG --changeset changeset.bin $db1 $db2
- set bin [readfile changeset.bin]
- return $bin
-}
-
-proc xConflict {args} {
- return ""
-}
-
-proc do_changeset_test {tn sql1 sql2} {
- forcedelete test.db123 test.db124
-
- sqlite3 db test.db123
- db eval $sql1
- db close
-
- sqlite3 db test.db124
- db eval $sql2
-
- set cs [get_changeset test.db124 test.db123]
- sqlite3changeset_apply db $cs xConflict
- db close
-
- set database_cksum1 [database_cksum test.db123]
- set database_cksum2 [database_cksum test.db124]
-
- uplevel [list \
- do_test $tn [list string compare $database_cksum1 $database_cksum2] 0
- ]
-}
-
-do_changeset_test 1.0 {
- CREATE TABLE t1(x PRIMARY KEY);
-} {
- CREATE TABLE t1(x PRIMARY KEY);
-}
-
-do_changeset_test 1.1 {
- CREATE TABLE t1(x PRIMARY KEY);
- CREATE TABLE t2(x PRIMARY KEY, y);
- INSERT INTO t2 VALUES(1, 2);
-} {
- CREATE TABLE t1(x PRIMARY KEY);
- CREATE TABLE t2(x PRIMARY KEY, y);
- INSERT INTO t2 VALUES(3, 4);
-}
-
-do_changeset_test 1.2 {
- CREATE TABLE t2(a, b, c, PRIMARY KEY(b, c));
- INSERT INTO t2 VALUES(1, 2, 3);
- INSERT INTO t2 VALUES(4, 5, 6);
-} {
- CREATE TABLE t2(a, b, c, PRIMARY KEY(b, c));
- INSERT INTO t2 VALUES(1, 2, 11);
- INSERT INTO t2 VALUES(7, 8, 9);
-}
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionfault.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionfault.test
deleted file mode 100644
index be6c4568ce6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionfault.test
+++ /dev/null
@@ -1,589 +0,0 @@
-# 2011 Mar 21
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the session module.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix sessionfault
-
-forcedelete test.db2
-sqlite3 db2 test.db2
-do_common_sql {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
-}
-faultsim_save_and_close
-db2 close
-
-#-------------------------------------------------------------------------
-# Test OOM error handling when collecting and applying a simple changeset.
-#
-# Test 1.1 attaches tables individually by name to the session object.
-# Whereas test 1.2 passes NULL to sqlite3session_attach() to attach all
-# tables.
-#
-do_faultsim_test 1.1 -faults oom-* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- sqlite3 db2 test.db2
-} -body {
- do_then_apply_sql {
- INSERT INTO t1 VALUES('a string value', 8, 9);
- UPDATE t1 SET c = 10 WHERE a = 1;
- DELETE FROM t1 WHERE a = 4;
- }
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- faultsim_integrity_check
- if {$testrc==0} { compare_db db db2 }
-}
-
-do_faultsim_test 1.2 -faults oom-* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
-} -body {
- sqlite3session S db main
- S attach *
- execsql {
- INSERT INTO t1 VALUES('a string value', 8, 9);
- UPDATE t1 SET c = 10 WHERE a = 1;
- DELETE FROM t1 WHERE a = 4;
- }
- set ::changeset [S changeset]
- set {} {}
-} -test {
- catch { S delete }
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- faultsim_integrity_check
- if {$testrc==0} {
- proc xConflict {args} { return "OMIT" }
- sqlite3 db2 test.db2
- sqlite3changeset_apply db2 $::changeset xConflict
- compare_db db db2
- }
-}
-
-#-------------------------------------------------------------------------
-# The following block of tests - 2.* - are designed to check
-# the handling of faults in the sqlite3changeset_apply() function.
-#
-catch {db close}
-catch {db2 close}
-forcedelete test.db2 test.db
-sqlite3 db2 test.db2
-sqlite3 db test.db
-do_common_sql {
- CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
- INSERT INTO t1 VALUES('apple', 'orange', 'pear');
-
- CREATE TABLE t2(x PRIMARY KEY, y);
-}
-db2 close
-faultsim_save_and_close
-
-
-foreach {tn conflict_policy sql sql2} {
- 1 OMIT { INSERT INTO t1 VALUES('one text', 'two text', X'00ff00') } {}
- 2 OMIT { DELETE FROM t1 WHERE a = 'apple' } {}
- 3 OMIT { UPDATE t1 SET c = 'banana' WHERE b = 'orange' } {}
- 4 REPLACE { INSERT INTO t2 VALUES('keyvalue', 'value 1') } {
- INSERT INTO t2 VALUES('keyvalue', 'value 2');
- }
-} {
- proc xConflict args [list return $conflict_policy]
-
- do_faultsim_test 2.$tn -faults oom-transient -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- set ::changeset [changeset_from_sql $::sql]
- sqlite3 db2 test.db2
- sqlite3_db_config_lookaside db2 0 0 0
- execsql $::sql2 db2
- } -body {
- sqlite3changeset_apply db2 $::changeset xConflict
- } -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- faultsim_integrity_check
- if {$testrc==0} { compare_db db db2 }
- }
-}
-
-#-------------------------------------------------------------------------
-# This test case is designed so that a malloc() failure occurs while
-# resizing the session object hash-table from 256 to 512 buckets. This
-# is not an error, just a sub-optimal condition.
-#
-do_faultsim_test 3 -faults oom-* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- sqlite3 db2 test.db2
-
- sqlite3session S db main
- S attach t1
- execsql { BEGIN }
- for {set i 0} {$i < 125} {incr i} {
- execsql {INSERT INTO t1 VALUES(10+$i, 10+$i, 10+$i)}
- }
-} -body {
- for {set i 125} {$i < 133} {incr i} {
- execsql {INSERT INTO t1 VALUES(10+$i, 10+$i, 1-+$i)}
- }
- S changeset
- set {} {}
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} {
- sqlite3changeset_apply db2 [S changeset] xConflict
- compare_db db db2
- }
- catch { S delete }
- faultsim_integrity_check
-}
-
-catch { db close }
-catch { db2 close }
-forcedelete test.db2 test.db
-sqlite3 db2 test.db2
-sqlite3 db test.db
-
-proc xConflict {op tbl type args} {
- if { $type=="CONFLICT" || $type=="DATA" } {
- return "REPLACE"
- }
- return "OMIT"
-}
-
-do_test 4.0 {
- execsql {
- PRAGMA encoding = 'utf16';
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES(5, 32);
- }
- execsql {
- PRAGMA encoding = 'utf16';
- CREATE TABLE t1(a PRIMARY KEY, b NOT NULL);
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t1 VALUES(2, 4);
- INSERT INTO t1 VALUES(4, 16);
- } db2
-} {}
-
-faultsim_save_and_close
-db2 close
-
-do_faultsim_test 4 -faults oom-* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- sqlite3 db2 test.db2
- sqlite3session S db main
- S attach t1
- execsql {
- INSERT INTO t1 VALUES(1, 45);
- INSERT INTO t1 VALUES(2, 55);
- INSERT INTO t1 VALUES(3, 55);
- UPDATE t1 SET a = 4 WHERE a = 5;
- }
-} -body {
- sqlite3changeset_apply db2 [S changeset] xConflict
-} -test {
- catch { S delete }
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} { compare_db db db2 }
-}
-
-#-------------------------------------------------------------------------
-# This block of tests verifies that OOM faults in the
-# sqlite3changeset_invert() function are handled correctly.
-#
-catch {db close}
-catch {db2 close}
-forcedelete test.db
-sqlite3 db test.db
-execsql {
- CREATE TABLE t1(a, b, PRIMARY KEY(b));
- CREATE TABLE t2(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES('string', 1);
- INSERT INTO t1 VALUES(4, 2);
- INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3);
-}
-set changeset [changeset_from_sql {
- INSERT INTO t1 VALUES('xxx', 'yyy');
- DELETE FROM t1 WHERE a = 'string';
- UPDATE t1 SET a = 20 WHERE b = 2;
-}]
-db close
-
-do_faultsim_test 5.1 -faults oom* -body {
- set ::inverse [sqlite3changeset_invert $::changeset]
- set {} {}
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} {
- set x [list]
- sqlite3session_foreach c $::inverse { lappend x $c }
- foreach c {
- {DELETE t1 0 .X {t xxx t yyy} {}}
- {INSERT t1 0 .X {} {t string i 1}}
- {UPDATE t1 0 .X {i 20 i 2} {i 4 {} {}}}
- } { lappend y $c }
- if {$x != $y} { error "changeset no good" }
- }
-}
-
-catch {db close}
-catch {db2 close}
-forcedelete test.db
-sqlite3 db test.db
-execsql {
- CREATE TABLE t2(a PRIMARY KEY, b);
- INSERT INTO t2 VALUES(1, 'abc');
- INSERT INTO t2 VALUES(2, 'def');
-}
-set changeset [changeset_from_sql {
- UPDATE t2 SET b = (b || b || b || b);
- UPDATE t2 SET b = (b || b || b || b);
- UPDATE t2 SET b = (b || b || b || b);
- UPDATE t2 SET b = (b || b || b || b);
-}]
-db close
-set abc [string repeat abc 256]
-set def [string repeat def 256]
-
-do_faultsim_test 5.2 -faults oom-tra* -body {
- set ::inverse [sqlite3changeset_invert $::changeset]
- set {} {}
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} {
- set x [list]
- sqlite3session_foreach c $::inverse { lappend x $c }
- foreach c "
- {UPDATE t2 0 X. {i 1 t $::abc} {{} {} t abc}}
- {UPDATE t2 0 X. {i 2 t $::def} {{} {} t def}}
- " { lappend y $c }
- if {$x != $y} { error "changeset no good" }
- }
-}
-
-catch {db close}
-catch {db2 close}
-forcedelete test.db
-sqlite3 db test.db
-set abc [string repeat abc 256]
-set def [string repeat def 256]
-execsql "
- CREATE TABLE t2(a PRIMARY KEY, b);
- INSERT INTO t2 VALUES(1, '$abc');
-"
-set changeset [changeset_from_sql "
- INSERT INTO t2 VALUES(2, '$def');
- DELETE FROM t2 WHERE a = 1;
-"]
-db close
-
-do_faultsim_test 5.3 -faults oom-tra* -body {
- set ::inverse [sqlite3changeset_invert $::changeset]
- set {} {}
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} {
- set x [list]
- sqlite3session_foreach c $::inverse { lappend x $c }
- foreach c "
- {INSERT t2 0 X. {} {i 1 t $::abc}}
- {DELETE t2 0 X. {i 2 t $::def} {}}
- " { lappend y $c }
- if {$x != $y} { error "changeset no good" }
- }
-}
-
-#-------------------------------------------------------------------------
-# Test that OOM errors in sqlite3changeset_concat() are handled correctly.
-#
-catch {db close}
-forcedelete test.db
-sqlite3 db test.db
-do_execsql_test 5.prep1 {
- CREATE TABLE t1(a, b, PRIMARY KEY(b));
- CREATE TABLE t2(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES('string', 1);
- INSERT INTO t1 VALUES(4, 2);
- INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3);
-}
-
-do_test 6.prep2 {
- sqlite3session M db main
- M attach *
- set ::c2 [changeset_from_sql {
- INSERT INTO t2 VALUES(randomblob(1000), randomblob(1000));
- INSERT INTO t2 VALUES('one', 'two');
- INSERT INTO t2 VALUES(1, NULL);
- UPDATE t1 SET a = 5 WHERE a = 2;
- }]
- set ::c1 [changeset_from_sql {
- DELETE FROM t2 WHERE a = 1;
- UPDATE t1 SET a = 4 WHERE a = 2;
- INSERT INTO t2 VALUES('x', 'y');
- }]
- set ::total [changeset_to_list [M changeset]]
- M delete
-} {}
-
-do_faultsim_test 6 -faults oom-* -body {
- set ::result [sqlite3changeset_concat $::c1 $::c2]
- set {} {}
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} {
- set v [changeset_to_list $::result]
- if {$v != $::total} { error "result no good" }
- }
-}
-
-faultsim_delete_and_reopen
-do_execsql_test 7.prep1 {
- CREATE TABLE t1(a, b, PRIMARY KEY(a));
-}
-faultsim_save_and_close
-
-set res [list]
-for {set ::i 0} {$::i < 480} {incr ::i 4} {
- lappend res "INSERT t1 0 X. {} {i $::i i $::i}"
-}
-set res [lsort $res]
-do_faultsim_test 7 -faults oom-transient -prep {
- catch { S delete }
- faultsim_restore_and_reopen
- sqlite3session S db main
- S attach *
-} -body {
- for {set ::i 0} {$::i < 480} {incr ::i 4} {
- execsql {INSERT INTO t1 VALUES($::i, $::i)}
- }
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} {
- set cres [list [catch {changeset_to_list [S changeset]} msg] $msg]
- S delete
- if {$cres != "1 SQLITE_NOMEM" && $cres != "0 {$::res}"} {
- error "Expected {0 $::res} Got {$cres}"
- }
- } else {
- catch { S changeset }
- catch { S delete }
- }
-}
-
-faultsim_delete_and_reopen
-do_test 8.prep {
- sqlite3session S db main
- S attach *
- execsql {
- CREATE TABLE t1(a, b, PRIMARY KEY(a));
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t1 VALUES(3, 4);
- INSERT INTO t1 VALUES(5, 6);
- }
- set ::changeset [S changeset]
- S delete
-} {}
-
-set expected [normalize_list {
- {INSERT t1 0 X. {} {i 1 i 2}}
- {INSERT t1 0 X. {} {i 3 i 4}}
- {INSERT t1 0 X. {} {i 5 i 6}}
-}]
-do_faultsim_test 8.1 -faults oom* -body {
- set ::res [list]
- sqlite3session_foreach -next v $::changeset { lappend ::res $v }
- normalize_list $::res
-} -test {
- faultsim_test_result [list 0 $::expected] {1 SQLITE_NOMEM}
-}
-do_faultsim_test 8.2 -faults oom* -body {
- set ::res [list]
- sqlite3session_foreach v $::changeset { lappend ::res $v }
- normalize_list $::res
-} -test {
- faultsim_test_result [list 0 $::expected] {1 SQLITE_NOMEM}
-}
-
-faultsim_delete_and_reopen
-do_test 9.1.prep {
- execsql {
- PRAGMA encoding = 'utf16';
- CREATE TABLE t1(a PRIMARY KEY, b);
- }
-} {}
-faultsim_save_and_close
-
-set answers [list {0 {}} {1 SQLITE_NOMEM} \
- {1 {callback requested query abort}} \
- {1 {abort due to ROLLBACK}}]
-do_faultsim_test 9.1 -faults oom-transient -prep {
- catch { unset ::c }
- faultsim_restore_and_reopen
- sqlite3session S db main
- S attach *
-} -body {
- execsql {
- INSERT INTO t1 VALUES('abcdefghijklmnopqrstuv', 'ABCDEFGHIJKLMNOPQRSTUV');
- }
- set ::c [S changeset]
- set {} {}
-} -test {
- S delete
- eval faultsim_test_result $::answers
- if {[info exists ::c]} {
- set expected [normalize_list {
- {INSERT t1 0 X. {} {t abcdefghijklmnopqrstuv t ABCDEFGHIJKLMNOPQRSTUV}}
- }]
- if { [changeset_to_list $::c] != $expected } {
- error "changeset mismatch"
- }
- }
-}
-
-faultsim_delete_and_reopen
-do_test 9.2.prep {
- execsql {
- PRAGMA encoding = 'utf16';
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES('abcdefghij', 'ABCDEFGHIJKLMNOPQRSTUV');
- }
-} {}
-faultsim_save_and_close
-
-set answers [list {0 {}} {1 SQLITE_NOMEM} \
- {1 {callback requested query abort}} \
- {1 {abort due to ROLLBACK}}]
-do_faultsim_test 9.2 -faults oom-transient -prep {
- catch { unset ::c }
- faultsim_restore_and_reopen
- sqlite3session S db main
- S attach *
-} -body {
- execsql {
- UPDATE t1 SET b = 'xyz';
- }
- set ::c [S changeset]
- set {} {}
-} -test {
- S delete
- eval faultsim_test_result $::answers
- if {[info exists ::c]} {
- set expected [normalize_list {
- {UPDATE t1 0 X. {t abcdefghij t ABCDEFGHIJKLMNOPQRSTUV} {{} {} t xyz}}
- }]
- if { [changeset_to_list $::c] != $expected } {
- error "changeset mismatch"
- }
- }
-}
-
-#-------------------------------------------------------------------------
-# Test that if a conflict-handler encounters an OOM in
-# sqlite3_value_text() but goes on to return SQLITE_CHANGESET_REPLACE
-# anyway, the OOM is picked up by the sessions module.
-set bigstr [string repeat abcdefghij 100]
-faultsim_delete_and_reopen
-do_test 10.prep.1 {
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES($bigstr, $bigstr);
- }
-
- sqlite3session S db main
- S attach *
- execsql { UPDATE t1 SET b = b||'x' }
- set C [S changeset]
- S delete
- execsql { UPDATE t1 SET b = b||'xyz' }
-} {}
-faultsim_save_and_close
-
-faultsim_restore_and_reopen
-do_test 10.prep.2 {
- proc xConflict {args} { return "ABORT" }
- list [catch { sqlite3changeset_apply db $C xConflict } msg] $msg
-} {1 SQLITE_ABORT}
-do_execsql_test 10.prep.3 { SELECT b=$bigstr||'x' FROM t1 } 0
-do_test 10.prep.4 {
- proc xConflict {args} { return "REPLACE" }
- list [catch { sqlite3changeset_apply db $C xConflict } msg] $msg
-} {0 {}}
-do_execsql_test 10.prep.5 { SELECT b=$bigstr||'x' FROM t1 } 1
-db close
-
-do_faultsim_test 10 -faults oom-tra* -prep {
- faultsim_restore_and_reopen
-} -body {
- sqlite3changeset_apply_replace_all db $::C
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} {
- if {[db one {SELECT b=$bigstr||'x' FROM t1}]==0} {
- error "data does not look right"
- }
- }
-}
-
-#-------------------------------------------------------------------------
-# Test an OOM with an sqlite3changeset_apply() filter callback.
-#
-reset_db
-do_test 11.prep {
- execsql {
- CREATE TABLE t1(a PRIMARY KEY, b);
- CREATE TABLE t2(x PRIMARY KEY, y);
- BEGIN;
- }
-
- set ::cs [changeset_from_sql {
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t2 VALUES('x', 'y');
- }]
-
- execsql ROLLBACK
- set {} {}
-} {}
-
-proc filter {x} { return [string equal t1 $x] }
-faultsim_save_and_close
-
-do_faultsim_test 11 -faults oom-tra* -prep {
- faultsim_restore_and_reopen
-} -body {
- sqlite3changeset_apply db $::cs {} filter
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- if {$testrc==0} {
- if {[db eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2}] != "1 2"} {
- error "data does not look right"
- }
- }
-}
-
-
-finish_test
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionfault2.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionfault2.test
deleted file mode 100644
index fb848e1935b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionfault2.test
+++ /dev/null
@@ -1,285 +0,0 @@
-# 2016 March 31
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the session module.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-set testprefix sessionfault2
-
-if 1 {
-
-do_execsql_test 1.0.0 {
- CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
- INSERT INTO t1 VALUES(1, 1);
- INSERT INTO t1 VALUES(2, 2);
- INSERT INTO t1 VALUES(3, 3);
-
- CREATE TABLE t2(a PRIMARY KEY, b UNIQUE);
- INSERT INTO t2 VALUES(1, 1);
- INSERT INTO t2 VALUES(2, 2);
- INSERT INTO t2 VALUES(3, 3);
-}
-faultsim_save_and_close
-
-faultsim_restore_and_reopen
-do_test 1.0.1 {
- set ::C [changeset_from_sql {
- UPDATE t1 SET b=4 WHERE a=3;
- UPDATE t1 SET b=3 WHERE a=2;
- UPDATE t1 SET b=2 WHERE a=1;
- UPDATE t2 SET b=0 WHERE a=1;
- UPDATE t2 SET b=1 WHERE a=2;
- UPDATE t2 SET b=2 WHERE a=3;
- }]
- set {} {}
-} {}
-
-proc xConflict args { return "OMIT" }
-
-do_faultsim_test 1 -faults oom-p* -prep {
- faultsim_restore_and_reopen
-} -body {
- sqlite3changeset_apply db $::C xConflict
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- faultsim_integrity_check
-
- catch { db eval ROLLBACK }
- set res [db eval {
- SELECT * FROM t1;
- SELECT * FROM t2;
- }]
-
- if {$testrc==0} {
- if {$res != "1 2 2 3 3 4 1 0 2 1 3 2"} { error "data error" }
- } else {
- if {
- $res != "1 2 2 3 3 4 1 0 2 1 3 2"
- && $res != "1 1 2 2 3 3 1 1 2 2 3 3"
- } { error "data error!! $res" }
- }
-}
-
-#-------------------------------------------------------------------------
-# OOM when applying a changeset for which one of the tables has a name
-# 99 bytes in size. This happens to cause an extra malloc in within the
-# sessions_strm permutation.
-#
-reset_db
-set nm [string repeat t 99]
-do_execsql_test 2.0.0 [string map "%TBL% $nm" {
- CREATE TABLE %TBL%(a PRIMARY KEY, b UNIQUE);
-}]
-faultsim_save_and_close
-
-faultsim_restore_and_reopen
-do_test 1.0.1 {
- set ::C [changeset_from_sql [string map "%TBL% $nm" {
- INSERT INTO %TBL% VALUES(1, 2);
- INSERT INTO %TBL% VALUES(3, 4);
- }]]
- set {} {}
-} {}
-
-proc xConflict args { return "OMIT" }
-do_faultsim_test 2 -faults oom-p* -prep {
- faultsim_restore_and_reopen
-} -body {
- sqlite3changeset_apply db $::C xConflict
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- faultsim_integrity_check
-}
-
-#-------------------------------------------------------------------------
-# OOM when collecting and apply a changeset that uses sqlite_stat1.
-#
-reset_db
-forcedelete test.db2
-sqlite3 db2 test.db2
-do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c);
- CREATE INDEX i1 ON t1(c);
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t1 VALUES(7, 8, 9);
- CREATE TABLE t2(a, b, c);
- INSERT INTO t2 VALUES(1, 2, 3);
- INSERT INTO t2 VALUES(4, 5, 6);
- INSERT INTO t2 VALUES(7, 8, 9);
- ANALYZE;
-}
-faultsim_save_and_close
-db2 close
-
-do_faultsim_test 1.1 -faults oom-* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- sqlite3 db2 test.db2
-} -body {
- do_then_apply_sql {
- INSERT INTO sqlite_stat1 VALUES('x', 'y', 45);
- UPDATE sqlite_stat1 SET stat = 123 WHERE tbl='t1' AND idx='i1';
- UPDATE sqlite_stat1 SET stat = 456 WHERE tbl='t2';
- }
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
- faultsim_integrity_check
- if {$testrc==0} { compare_db db db2 }
-}
-
-#-------------------------------------------------------------------------
-# OOM when collecting and using a rebase changeset.
-#
-reset_db
-do_execsql_test 2.0 {
- CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c));
- CREATE TABLE t4(x PRIMARY KEY, y, z);
-
- INSERT INTO t3 VALUES(1, 2, 3);
- INSERT INTO t3 VALUES(4, 2, 5);
- INSERT INTO t3 VALUES(7, 2, 9);
-
- INSERT INTO t4 VALUES('a', 'b', 'c');
- INSERT INTO t4 VALUES('d', 'e', 'f');
- INSERT INTO t4 VALUES('g', 'h', 'i');
-}
-faultsim_save_and_close
-db2 close
-
-proc xConflict {ret args} { return $ret }
-
-do_test 2.1 {
- faultsim_restore_and_reopen
- set C1 [changeset_from_sql {
- INSERT INTO t3 VALUES(10, 11, 12);
- UPDATE t4 SET y='j' WHERE x='g';
- DELETE FROM t4 WHERE x='a';
- }]
-
- faultsim_restore_and_reopen
- set C2 [changeset_from_sql {
- INSERT INTO t3 VALUES(1000, 11, 12);
- DELETE FROM t4 WHERE x='g';
- }]
-
- faultsim_restore_and_reopen
- sqlite3changeset_apply db $C1 [list xConflict OMIT]
- faultsim_save_and_close
-} {}
-
-do_faultsim_test 2.2 -faults oom* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- sqlite3 db2 test.db2
-} -body {
- set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
- set {} {}
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
-}
-do_faultsim_test 2.3 -faults oom* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- sqlite3 db2 test.db2
-} -body {
- set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]]
- set {} {}
-} -test {
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
-}
-do_faultsim_test 2.4 -faults oom* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]]
-} -body {
- sqlite3rebaser_create R
- R configure $::rebase
- R rebase $::C1
- set {} {}
-} -test {
- catch { R delete }
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
-}
-do_faultsim_test 2.5 -faults oom* -prep {
- catch {db2 close}
- catch {db close}
- faultsim_restore_and_reopen
- set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
-} -body {
- sqlite3rebaser_create R
- R configure $::rebase
- R rebase $::C1
- set {} {}
-} -test {
- catch { R delete }
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
-}
-
-}
-
-reset_db
-do_execsql_test 3.0 {
- CREATE TABLE t1(x PRIMARY KEY, y, z);
- INSERT INTO t1 VALUES(3, 1, 4);
- INSERT INTO t1 VALUES(1, 5, 9);
-}
-faultsim_save_and_close
-
-proc xConflict {ret args} { return $ret }
-
-do_test 3.1 {
- faultsim_restore_and_reopen
-
- execsql { BEGIN; UPDATE t1 SET z=11; }
- set C1 [changeset_from_sql {
- UPDATE t1 SET z=10 WHERE x=1;
- }]
- execsql { ROLLBACK }
-
- execsql { BEGIN; UPDATE t1 SET z=11; }
- set C2 [changeset_from_sql {
- UPDATE t1 SET z=55 WHERE x=1;
- }]
- execsql { ROLLBACK }
-
- set ::rebase1 [sqlite3changeset_apply_v2 db $::C1 [list xConflict OMIT]]
- set ::rebase2 [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
- set {} {}
- execsql { SELECT * FROM t1 }
-} {3 1 4 1 5 9}
-
-
-do_faultsim_test 3.2 -faults oom* -prep {
- faultsim_restore_and_reopen
-} -body {
- sqlite3rebaser_create R
- R configure $::rebase1
- R configure $::rebase2
- set {} {}
-} -test {
- catch { R delete }
- faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
-}
-
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionrebase.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionrebase.test
deleted file mode 100644
index ced9f2240df..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionrebase.test
+++ /dev/null
@@ -1,477 +0,0 @@
-# 2018 March 14
-#
-# 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 regression tests for SQLite library.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix sessionrebase
-
-set ::lConflict [list]
-proc xConflict {args} {
- set res [lindex $::lConflict 0]
- set ::lConflict [lrange $::lConflict 1 end]
- return $res
-}
-
-#-------------------------------------------------------------------------
-# The following test cases - 1.* - test that the rebase blobs output by
-# sqlite3_changeset_apply_v2 look correct in some simple cases. The blob
-# is itself a changeset, containing records determined as follows:
-#
-# * For each conflict resolved with REPLACE, the rebase blob contains
-# a DELETE record. All fields other than the PK fields are undefined.
-#
-# * For each conflict resolved with OMIT, the rebase blob contains an
-# INSERT record. For an INSERT or UPDATE operation, the indirect flag
-# is clear and all updated fields are defined. For a DELETE operation,
-# the indirect flag is set and all non-PK fields left undefined.
-#
-proc do_apply_v2_test {tn sql modsql conflict_handler res} {
-
- execsql BEGIN
- sqlite3session S db main
- S attach *
- execsql $sql
- set changeset [S changeset]
- S delete
- execsql ROLLBACK
-
- execsql BEGIN
- execsql $modsql
- set ::lConflict $conflict_handler
- set blob [sqlite3changeset_apply_v2 db $changeset xConflict]
- execsql ROLLBACK
-
- uplevel [list do_test $tn [list changeset_to_list $blob] [list {*}$res]]
-}
-
-
-set ::lConflict [list]
-proc xConflict {args} {
- set res [lindex $::lConflict 0]
- set ::lConflict [lrange $::lConflict 1 end]
- return $res
-}
-
-# Take a copy of database test.db in file test.db2. Execute $sql1
-# against test.db and $sql2 against test.db2. Capture a changeset
-# for each. Then send the test.db2 changeset to test.db and apply
-# it with the conflict handlers in $conflict_handler. Patch the
-# test.db changeset and then execute it against test.db2. Test that
-# the two databases come out the same.
-#
-proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} {
-
- for {set i 1} {$i <= 2} {incr i} {
- forcedelete test.db2 test.db2-journal test.db2-wal
- forcecopy test.db test.db2
- sqlite3 db2 test.db2
-
- db eval BEGIN
-
- sqlite3session S1 db main
- S1 attach *
- execsql $sql1 db
- set c1 [S1 changeset]
- S1 delete
-
- if {$i==1} {
- sqlite3session S2 db2 main
- S2 attach *
- execsql $sql2 db2
- set c2 [S2 changeset]
- S2 delete
- } else {
- set c2 [list]
- foreach sql [split $sql2 ";"] {
- if {[string is space $sql]} continue
- sqlite3session S2 db2 main
- S2 attach *
- execsql $sql db2
- lappend c2 [S2 changeset]
- S2 delete
- }
- }
-
- set ::lConflict $conflict_handler
- set rebase [list]
- if {$i==1} {
- lappend rebase [sqlite3changeset_apply_v2 db $c2 xConflict]
- } else {
- foreach c $c2 {
-#puts "apply_v2: [changeset_to_list $c]"
- lappend rebase [sqlite3changeset_apply_v2 db $c xConflict]
- }
- #puts "llength: [llength $rebase]"
- }
- #if {$tn=="2.1.4"} { puts [changeset_to_list $rebase] ; breakpoint }
- #puts [changeset_to_list [lindex $rebase 0]] ; breakpoint
- #puts [llength $rebase]
-
- sqlite3rebaser_create R
- foreach r $rebase {
-#puts [changeset_to_list $r]
- R configure $r
- }
- set c1r [R rebase $c1]
- R delete
- #if {$tn=="2.1.4"} { puts [changeset_to_list $c1r] }
-
- sqlite3changeset_apply_v2 db2 $c1r xConflictAbort
-
- if {[string range $tn end end]!="*"} {
- uplevel [list do_test $tn.$i.1 [list compare_db db db2] {}]
- }
- db2 close
-
- if {$testsql!=""} {
- uplevel [list do_execsql_test $tn.$i.2 $testsql $testres]
- }
-
- db eval ROLLBACK
- }
-}
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 'value A');
-}
-
-do_apply_v2_test 1.1.1 {
- UPDATE t1 SET b = 'value B' WHERE a=1;
-} {
- UPDATE t1 SET b = 'value C' WHERE a=1;
-} {
- OMIT
-} {
- {INSERT t1 0 X. {} {i 1 t {value B}}}
-}
-
-do_apply_v2_test 1.1.2 {
- UPDATE t1 SET b = 'value B' WHERE a=1;
-} {
- UPDATE t1 SET b = 'value C' WHERE a=1;
-} {
- REPLACE
-} {
- {INSERT t1 1 X. {} {i 1 t {value B}}}
-}
-
-do_apply_v2_test 1.2.1 {
- INSERT INTO t1 VALUES(2, 'first');
-} {
- INSERT INTO t1 VALUES(2, 'second');
-} {
- OMIT
-} {
- {INSERT t1 0 X. {} {i 2 t first}}
-}
-do_apply_v2_test 1.2.2 {
- INSERT INTO t1 VALUES(2, 'first');
-} {
- INSERT INTO t1 VALUES(2, 'second');
-} {
- REPLACE
-} {
- {INSERT t1 1 X. {} {i 2 t first}}
-}
-
-do_apply_v2_test 1.3.1 {
- DELETE FROM t1 WHERE a=1;
-} {
- UPDATE t1 SET b='value D' WHERE a=1;
-} {
- OMIT
-} {
- {DELETE t1 0 X. {i 1 t {value A}} {}}
-}
-do_apply_v2_test 1.3.2 {
- DELETE FROM t1 WHERE a=1;
-} {
- UPDATE t1 SET b='value D' WHERE a=1;
-} {
- REPLACE
-} {
- {DELETE t1 1 X. {i 1 t {value A}} {}}
-}
-
-#-------------------------------------------------------------------------
-# Test cases 2.* - simple tests of rebasing actual changesets.
-#
-# 2.1.1 - 1u2u1r
-# 2.1.2 - 1u2u2r
-# 2.1.3 - 1d2d
-# 2.1.4 - 1d2u1r
-# 2.1.5 - 1d2u2r !!
-# 2.1.6 - 1u2d1r
-# 2.1.7 - 1u2d2r
-#
-# 2.1.8 - 1i2i2r
-# 2.1.9 - 1i2i1r
-#
-
-proc xConflictAbort {args} {
- return "ABORT"
-}
-
-reset_db
-do_execsql_test 2.1.0 {
- CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT);
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
- INSERT INTO t1 VALUES(3, 'three');
-}
-do_rebase_test 2.1.1 {
- UPDATE t1 SET b = 'two.1' WHERE a=2
-} {
- UPDATE t1 SET b = 'two.2' WHERE a=2;
-} {
- OMIT
-} { SELECT * FROM t1 } {1 one 2 two.1 3 three}
-
-do_rebase_test 2.1.2 {
- UPDATE t1 SET b = 'two.1' WHERE a=2
-} {
- UPDATE t1 SET b = 'two.2' WHERE a=2;
-} {
- REPLACE
-} { SELECT * FROM t1 } {1 one 2 two.2 3 three}
-
-do_rebase_test 2.1.3 {
- DELETE FROM t1 WHERE a=3
-} {
- DELETE FROM t1 WHERE a=3;
-} {
- OMIT
-} { SELECT * FROM t1 } {1 one 2 two}
-
-do_rebase_test 2.1.4 {
- DELETE FROM t1 WHERE a=1
-} {
- UPDATE t1 SET b='one.2' WHERE a=1
-} {
- OMIT
-} { SELECT * FROM t1 } {2 two 3 three}
-
-#do_rebase_test 2.1.5 {
-# DELETE FROM t1 WHERE a=1;
-#} {
-# UPDATE t1 SET b='one.2' WHERE a=1
-#} {
-# REPLACE
-#} { SELECT * FROM t1 } {2 two 3 three}
-
-do_rebase_test 2.1.6 {
- UPDATE t1 SET b='three.1' WHERE a=3
-} {
- DELETE FROM t1 WHERE a=3;
-} {
- OMIT
-} { SELECT * FROM t1 } {1 one 2 two 3 three.1}
-
-do_rebase_test 2.1.7 {
- UPDATE t1 SET b='three.1' WHERE a=3
-} {
- DELETE FROM t1 WHERE a=3;
-} {
- REPLACE
-} { SELECT * FROM t1 } {1 one 2 two}
-
-do_rebase_test 2.1.8 {
- INSERT INTO t1 VALUES(4, 'four.1')
-} {
- INSERT INTO t1 VALUES(4, 'four.2');
-} {
- REPLACE
-} { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.2}
-
-do_rebase_test 2.1.9 {
- INSERT INTO t1 VALUES(4, 'four.1')
-} {
- INSERT INTO t1 VALUES(4, 'four.2');
-} {
- OMIT
-} { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.1}
-
-do_execsql_test 2.2.0 {
- CREATE TABLE t2(x, y, z PRIMARY KEY);
- INSERT INTO t2 VALUES('i', 'a', 'A');
- INSERT INTO t2 VALUES('ii', 'b', 'B');
- INSERT INTO t2 VALUES('iii', 'c', 'C');
-
- CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c);
- INSERT INTO t3 VALUES(-1, 'z', 'Z');
- INSERT INTO t3 VALUES(-2, 'y', 'Y');
-}
-
-do_rebase_test 2.2.1 {
- UPDATE t2 SET x=1 WHERE z='A'
-} {
- UPDATE t2 SET y='one' WHERE z='A';
-} {
-} { SELECT * FROM t2 WHERE z='A' } { 1 one A }
-
-do_rebase_test 2.2.2 {
- UPDATE t2 SET x=1, y='one' WHERE z='B'
-} {
- UPDATE t2 SET y='two' WHERE z='B';
-} {
- REPLACE
-} { SELECT * FROM t2 WHERE z='B' } { 1 two B }
-
-do_rebase_test 2.2.3 {
- UPDATE t2 SET x=1, y='one' WHERE z='B'
-} {
- UPDATE t2 SET y='two' WHERE z='B';
-} {
- OMIT
-} { SELECT * FROM t2 WHERE z='B' } { 1 one B }
-
-#-------------------------------------------------------------------------
-reset_db
-do_execsql_test 3.0 {
- CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c));
- CREATE TABLE abcdefghijkl(x PRIMARY KEY, y, z);
-
- INSERT INTO t3 VALUES(1, 2, 3);
- INSERT INTO t3 VALUES(4, 2, 5);
- INSERT INTO t3 VALUES(7, 2, 9);
-
- INSERT INTO abcdefghijkl VALUES('a', 'b', 'c');
- INSERT INTO abcdefghijkl VALUES('d', 'e', 'f');
- INSERT INTO abcdefghijkl VALUES('g', 'h', 'i');
-}
-
-breakpoint
-# do_rebase_test 3.6.tn {
-# UPDATE abcdefghijkl SET z='X', y='X' WHERE x='d';
-# } {
-# UPDATE abcdefghijkl SET y=1 WHERE x='d';
-# UPDATE abcdefghijkl SET z=1 WHERE x='d';
-# } [list REPLACE REPLACE REPLACE]
-
-foreach {tn p} {
- 1 OMIT 2 REPLACE
-} {
- do_rebase_test 3.1.$tn {
- INSERT INTO t3 VALUES(1, 1, 1);
- UPDATE abcdefghijkl SET y=2;
- } {
- INSERT INTO t3 VALUES(4, 1, 1);
- DELETE FROM abcdefghijkl;
- } [list $p $p $p $p $p $p $p $p]
-
- do_rebase_test 3.2.$tn {
- INSERT INTO abcdefghijkl SELECT * FROM t3;
- UPDATE t3 SET b=b+1;
- } {
- INSERT INTO t3 VALUES(3, 3, 3);
- INSERT INTO abcdefghijkl SELECT * FROM t3;
- } [list $p $p $p $p $p $p $p $p]
-
- do_rebase_test 3.3.$tn {
- INSERT INTO abcdefghijkl VALUES(22, 23, 24);
- } {
- INSERT INTO abcdefghijkl VALUES(22, 25, 26);
- UPDATE abcdefghijkl SET y=400 WHERE x=22;
- } [list $p $p $p $p $p $p $p $p]
-
- do_rebase_test 3.4.$tn {
- INSERT INTO abcdefghijkl VALUES(22, 23, 24);
- } {
- INSERT INTO abcdefghijkl VALUES(22, 25, 26);
- UPDATE abcdefghijkl SET y=400 WHERE x=22;
- } [list REPLACE $p]
-
- do_rebase_test 3.5.$tn* {
- UPDATE abcdefghijkl SET y='X' WHERE x='d';
- } {
- DELETE FROM abcdefghijkl WHERE x='d';
- INSERT INTO abcdefghijkl VALUES('d', NULL, NULL);
- } [list $p $p $p]
- do_rebase_test 3.5.$tn {
- UPDATE abcdefghijkl SET y='X' WHERE x='d';
- } {
- DELETE FROM abcdefghijkl WHERE x='d';
- INSERT INTO abcdefghijkl VALUES('d', NULL, NULL);
- } [list REPLACE $p $p]
-
- do_rebase_test 3.6.$tn {
- UPDATE abcdefghijkl SET z='X', y='X' WHERE x='d';
- } {
- UPDATE abcdefghijkl SET y=1 WHERE x='d';
- UPDATE abcdefghijkl SET z=1 WHERE x='d';
- } [list REPLACE $p $p]
-}
-
-#-------------------------------------------------------------------------
-# Check that apply_v2() does not create a rebase buffer for a patchset.
-# And that it is not possible to rebase a patchset.
-#
-do_execsql_test 4.0 {
- CREATE TABLE t5(o PRIMARY KEY, p, q);
- INSERT INTO t5 VALUES(1, 2, 3);
- INSERT INTO t5 VALUES(4, 5, 6);
-}
-foreach {tn cmd rebasable} {
- 1 patchset 0
- 2 changeset 1
-} {
- proc xConflict {args} { return "OMIT" }
- do_test 4.1.$tn {
- execsql {
- BEGIN;
- DELETE FROM t5 WHERE o=4;
- }
-
- sqlite3session S db main
- S attach *
- execsql {
- INSERT INTO t5 VALUES(4, 'five', 'six');
- }
- set P [S $cmd]
- S delete
-
- execsql ROLLBACK;
-
- set ::rebase [sqlite3changeset_apply_v2 db $P xConflict]
- expr [llength $::rebase]>0
- } $rebasable
-}
-
-foreach {tn cmd rebasable} {
- 1 patchset 0
- 2 changeset 1
-} {
- do_test 4.2.$tn {
- sqlite3session S db main
- S attach *
- execsql {
- INSERT INTO t5 VALUES(5+$tn, 'five', 'six');
- }
- set P [S $cmd]
- S delete
-
- sqlite3rebaser_create R
- R configure $::rebase
- expr [catch {R rebase $P}]==0
- } $rebasable
-
- catch { R delete }
-}
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionstat1.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionstat1.test
deleted file mode 100644
index 082c02bcf19..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionstat1.test
+++ /dev/null
@@ -1,311 +0,0 @@
-# 2018 January 12
-#
-# 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.
-#
-#***********************************************************************
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix sessionstat1
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE INDEX t1b ON t1(b);
- CREATE INDEX t1c ON t1(c);
-
- WITH s(i) AS (
- SELECT 0 UNION ALL SELECT i+1 FROM s WHERE (i+1)<32
- )
- INSERT INTO t1 SELECT i, i%8, i%2 FROM s;
-}
-
-do_iterator_test 1.1 {} {
- ANALYZE
-} {
- {INSERT sqlite_stat1 0 XX. {} {t t1 t sqlite_autoindex_t1_1 t {32 1}}}
- {INSERT sqlite_stat1 0 XX. {} {t t1 t t1b t {32 4}}}
- {INSERT sqlite_stat1 0 XX. {} {t t1 t t1c t {32 16}}}
-}
-
-do_execsql_test 1.2 {
- WITH s(i) AS (
- SELECT 32 UNION ALL SELECT i+1 FROM s WHERE (i+1)<64
- )
- INSERT INTO t1 SELECT i, i%8, i%2 FROM s;
-}
-
-do_iterator_test 1.3 {} {
- ANALYZE
-} {
- {UPDATE sqlite_stat1 0 XX. {t t1 t sqlite_autoindex_t1_1 t {32 1}} {{} {} {} {} t {64 1}}}
- {UPDATE sqlite_stat1 0 XX. {t t1 t t1b t {32 4}} {{} {} {} {} t {64 8}}}
- {UPDATE sqlite_stat1 0 XX. {t t1 t t1c t {32 16}} {{} {} {} {} t {64 32}}}
-}
-
-do_iterator_test 1.5 {} {
- DROP INDEX t1b;
-} {
- {DELETE sqlite_stat1 0 XX. {t t1 t t1b t {64 8}} {}}
-}
-
-do_iterator_test 1.6 {} {
- DROP TABLE t1;
-} {
- {DELETE sqlite_stat1 0 XX. {t t1 t sqlite_autoindex_t1_1 t {64 1}} {}}
- {DELETE sqlite_stat1 0 XX. {t t1 t t1c t {64 32}} {}}
-}
-
-#-------------------------------------------------------------------------
-#
-catch { db2 close }
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_test 2.0 {
- do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b, c);
- CREATE INDEX t1b ON t1(b);
- CREATE INDEX t1c ON t1(c);
- ANALYZE;
- }
-} {}
-
-do_test 2.1 {
- do_then_apply_sql {
- WITH s(i) AS (
- SELECT 0 UNION ALL SELECT i+1 FROM s WHERE (i+1)<32
- )
- INSERT INTO t1 SELECT i, i%8, i%2 FROM s;
- ANALYZE;
- }
-} {}
-
-do_execsql_test -db db2 2.2 {
- SELECT * FROM sqlite_stat1
-} {
- t1 sqlite_autoindex_t1_1 {32 1}
- t1 t1b {32 4}
- t1 t1c {32 16}
-}
-
-do_test 2.3 {
- do_then_apply_sql { DROP INDEX t1c }
-} {}
-
-do_execsql_test -db db2 2.4 {
- SELECT * FROM sqlite_stat1
-} {
- t1 sqlite_autoindex_t1_1 {32 1}
- t1 t1b {32 4}
-}
-
-do_test 2.3 {
- do_then_apply_sql { DROP TABLE t1 }
-} {}
-
-do_execsql_test -db db2 2.4 {
- SELECT * FROM sqlite_stat1
-} {
-}
-
-do_execsql_test -db db2 2.5 { SELECT count(*) FROM t1 } 32
-
-#-------------------------------------------------------------------------
-db2 close
-forcedelete test.db2
-reset_db
-sqlite3 db2 test.db2
-
-do_test 3.0 {
- do_common_sql {
- CREATE TABLE t1(a, b, c);
- ANALYZE;
- DELETE FROM sqlite_stat1;
- }
- execsql {
- INSERT INTO t1 VALUES(1, 1, 1);
- INSERT INTO t1 VALUES(2, 2, 2);
- INSERT INTO t1 VALUES(3, 3, 3);
- INSERT INTO t1 VALUES(4, 4, 4);
- }
-} {}
-
-do_iterator_test 3.1 {} {
- ANALYZE
-} {
- {INSERT sqlite_stat1 0 XX. {} {t t1 b {} t 4}}
-}
-db null null
-db2 null null
-do_execsql_test 3.2 {
- SELECT * FROM sqlite_stat1;
-} {t1 null 4}
-do_test 3.3 {
- execsql { DELETE FROM sqlite_stat1 }
- do_then_apply_sql { ANALYZE }
- execsql { SELECT * FROM sqlite_stat1 } db2
-} {t1 null 4}
-do_test 3.4 {
- execsql { INSERT INTO t1 VALUES(5,5,5) }
- do_then_apply_sql { ANALYZE }
- execsql { SELECT * FROM sqlite_stat1 } db2
-} {t1 null 5}
-do_test 3.5 {
- do_then_apply_sql { DROP TABLE t1 }
- execsql { SELECT * FROM sqlite_stat1 } db2
-} {}
-
-do_test 3.6.1 {
- execsql {
- CREATE TABLE t1(a, b, c);
- CREATE TABLE t2(x, y, z);
- INSERT INTO t1 VALUES(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5);
- INSERT INTO t2 SELECT * FROM t1;
- DELETE FROM sqlite_stat1;
- }
- sqlite3session S db main
- S attach sqlite_stat1
- execsql { ANALYZE }
-} {}
-do_changeset_test 3.6.2 S {
- {INSERT sqlite_stat1 0 XX. {} {t t2 b {} t 5}}
- {INSERT sqlite_stat1 0 XX. {} {t t1 b {} t 5}}
-}
-do_changeset_invert_test 3.6.3 S {
- {DELETE sqlite_stat1 0 XX. {t t2 b {} t 5} {}}
- {DELETE sqlite_stat1 0 XX. {t t1 b {} t 5} {}}
-}
-do_test 3.6.4 { S delete } {}
-
-proc sql_changeset_concat {args} {
- foreach sql $args {
- sqlite3session S db main
- S attach sqlite_stat1
- execsql $sql
- set change [S changeset]
- S delete
-
- if {[info vars ret]!=""} {
- set ret [sqlite3changeset_concat $ret $change]
- } else {
- set ret $change
- }
- }
-
- changeset_to_list $ret
-}
-
-proc do_scc_test {tn args} {
- uplevel [list \
- do_test $tn [concat sql_changeset_concat [lrange $args 0 end-1]] \
- [list {*}[ lindex $args end ]]
- ]
-}
-
-do_execsql_test 3.7.0 {
- DELETE FROM sqlite_stat1;
-}
-do_scc_test 3.7.1 {
- ANALYZE;
-} {
- INSERT INTO t2 VALUES(6,6,6);
- ANALYZE;
-} {
- {INSERT sqlite_stat1 0 XX. {} {t t1 b {} t 5}}
- {INSERT sqlite_stat1 0 XX. {} {t t2 b {} t 6}}
-}
-
-#-------------------------------------------------------------------------
-catch { db2 close }
-reset_db
-forcedelete test.db2
-sqlite3 db2 test.db2
-
-do_test 4.1.0 {
- do_common_sql {
- CREATE TABLE t1(a, b);
- CREATE INDEX i1 ON t1(a);
- CREATE INDEX i2 ON t1(b);
- INSERT INTO t1 VALUES(1,1), (2,2);
- ANALYZE;
- }
- execsql { DELETE FROM sqlite_stat1 }
-} {}
-
-do_test 4.1.1 {
- execsql { INSERT INTO t1 VALUES(3,3); }
- set C [changeset_from_sql {ANALYZE}]
- set ::c [list]
- proc xConflict {args} {
- lappend ::c $args
- return "OMIT"
- }
- sqlite3changeset_apply db2 $C xConflict
- set ::c
-} [list {*}{
- {INSERT sqlite_stat1 CONFLICT {t t1 t i1 t {3 1}} {t t1 t i1 t {2 1}}}
- {INSERT sqlite_stat1 CONFLICT {t t1 t i2 t {3 1}} {t t1 t i2 t {2 1}}}
-}]
-
-do_execsql_test -db db2 4.1.2 {
- SELECT * FROM sqlite_stat1 ORDER BY 1,2;
-} {t1 i1 {2 1} t1 i2 {2 1}}
-
-do_test 4.1.3 {
- proc xConflict {args} {
- return "REPLACE"
- }
- sqlite3changeset_apply db2 $C xConflict
- execsql { SELECT * FROM sqlite_stat1 ORDER BY 1,2 } db2
-} {t1 i1 {3 1} t1 i2 {3 1}}
-
-do_test 4.2.0 {
- do_common_sql {
- DROP TABLE t1;
- CREATE TABLE t3(x,y);
- INSERT INTO t3 VALUES('a','a');
- INSERT INTO t3 VALUES('b','b');
- ANALYZE;
- }
- execsql { DELETE FROM sqlite_stat1 }
-} {}
-do_test 4.2.1 {
- execsql { INSERT INTO t3 VALUES('c','c'); }
- set C [changeset_from_sql {ANALYZE}]
- set ::c [list]
- proc xConflict {args} {
- lappend ::c $args
- return "OMIT"
- }
- sqlite3changeset_apply db2 $C xConflict
- set ::c
-} [list {*}{
- {INSERT sqlite_stat1 CONFLICT {t t3 b {} t 3} {t t3 b {} t 2}}
-}]
-
-db2 null null
-do_execsql_test -db db2 4.2.2 {
- SELECT * FROM sqlite_stat1 ORDER BY 1,2;
-} {t3 null 2}
-
-do_test 4.2.3 {
- proc xConflict {args} {
- return "REPLACE"
- }
- sqlite3changeset_apply db2 $C xConflict
- execsql { SELECT * FROM sqlite_stat1 ORDER BY 1,2 } db2
-} {t3 null 3}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionwor.test b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionwor.test
deleted file mode 100644
index d906a92b621..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sessionwor.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# 2017 Jan 31
-#
-# 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.
-#
-#***********************************************************************
-#
-# The focus of this file is testing the session module. Specifically,
-# testing support for WITHOUT ROWID tables.
-#
-
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source [file join [file dirname [info script]] session_common.tcl]
-source $testdir/tester.tcl
-ifcapable !session {finish_test; return}
-
-set testprefix sessionwor
-
-proc test_reset {} {
- catch { db close }
- catch { db2 close }
- forcedelete test.db test.db2
- sqlite3 db test.db
- sqlite3 db2 test.db2
-}
-
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT ROWID;
-}
-
-do_iterator_test 1.1 t1 {
- INSERT INTO t1 VALUES('one', 'two');
-} {
- {INSERT t1 0 X. {} {t one t two}}
-}
-
-do_iterator_test 1.2 t1 {
- UPDATE t1 SET b='three'
-} {
- {UPDATE t1 0 X. {t one t two} {{} {} t three}}
-}
-
-do_iterator_test 1.3 t1 {
- DELETE FROM t1;
-} {
- {DELETE t1 0 X. {t one t three} {}}
-}
-
-finish_test
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sqlite3session.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sqlite3session.c
deleted file mode 100644
index e432b894ca5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sqlite3session.c
+++ /dev/null
@@ -1,5377 +0,0 @@
-
-#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
-#include "sqlite3session.h"
-#include <assert.h>
-#include <string.h>
-
-#ifndef SQLITE_AMALGAMATION
-# include "sqliteInt.h"
-# include "vdbeInt.h"
-#endif
-
-typedef struct SessionTable SessionTable;
-typedef struct SessionChange SessionChange;
-typedef struct SessionBuffer SessionBuffer;
-typedef struct SessionInput SessionInput;
-
-/*
-** Minimum chunk size used by streaming versions of functions.
-*/
-#ifndef SESSIONS_STRM_CHUNK_SIZE
-# ifdef SQLITE_TEST
-# define SESSIONS_STRM_CHUNK_SIZE 64
-# else
-# define SESSIONS_STRM_CHUNK_SIZE 1024
-# endif
-#endif
-
-typedef struct SessionHook SessionHook;
-struct SessionHook {
- void *pCtx;
- int (*xOld)(void*,int,sqlite3_value**);
- int (*xNew)(void*,int,sqlite3_value**);
- int (*xCount)(void*);
- int (*xDepth)(void*);
-};
-
-/*
-** Session handle structure.
-*/
-struct sqlite3_session {
- sqlite3 *db; /* Database handle session is attached to */
- char *zDb; /* Name of database session is attached to */
- int bEnable; /* True if currently recording */
- int bIndirect; /* True if all changes are indirect */
- int bAutoAttach; /* True to auto-attach tables */
- int rc; /* Non-zero if an error has occurred */
- void *pFilterCtx; /* First argument to pass to xTableFilter */
- int (*xTableFilter)(void *pCtx, const char *zTab);
- sqlite3_value *pZeroBlob; /* Value containing X'' */
- sqlite3_session *pNext; /* Next session object on same db. */
- SessionTable *pTable; /* List of attached tables */
- SessionHook hook; /* APIs to grab new and old data with */
-};
-
-/*
-** Instances of this structure are used to build strings or binary records.
-*/
-struct SessionBuffer {
- u8 *aBuf; /* Pointer to changeset buffer */
- int nBuf; /* Size of buffer aBuf */
- int nAlloc; /* Size of allocation containing aBuf */
-};
-
-/*
-** An object of this type is used internally as an abstraction for
-** input data. Input data may be supplied either as a single large buffer
-** (e.g. sqlite3changeset_start()) or using a stream function (e.g.
-** sqlite3changeset_start_strm()).
-*/
-struct SessionInput {
- int bNoDiscard; /* If true, do not discard in InputBuffer() */
- int iCurrent; /* Offset in aData[] of current change */
- int iNext; /* Offset in aData[] of next change */
- u8 *aData; /* Pointer to buffer containing changeset */
- int nData; /* Number of bytes in aData */
-
- SessionBuffer buf; /* Current read buffer */
- int (*xInput)(void*, void*, int*); /* Input stream call (or NULL) */
- void *pIn; /* First argument to xInput */
- int bEof; /* Set to true after xInput finished */
-};
-
-/*
-** Structure for changeset iterators.
-*/
-struct sqlite3_changeset_iter {
- SessionInput in; /* Input buffer or stream */
- SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */
- int bPatchset; /* True if this is a patchset */
- int rc; /* Iterator error code */
- sqlite3_stmt *pConflict; /* Points to conflicting row, if any */
- char *zTab; /* Current table */
- int nCol; /* Number of columns in zTab */
- int op; /* Current operation */
- int bIndirect; /* True if current change was indirect */
- u8 *abPK; /* Primary key array */
- sqlite3_value **apValue; /* old.* and new.* values */
-};
-
-/*
-** Each session object maintains a set of the following structures, one
-** for each table the session object is monitoring. The structures are
-** stored in a linked list starting at sqlite3_session.pTable.
-**
-** The keys of the SessionTable.aChange[] hash table are all rows that have
-** been modified in any way since the session object was attached to the
-** table.
-**
-** The data associated with each hash-table entry is a structure containing
-** a subset of the initial values that the modified row contained at the
-** start of the session. Or no initial values if the row was inserted.
-*/
-struct SessionTable {
- SessionTable *pNext;
- char *zName; /* Local name of table */
- int nCol; /* Number of columns in table zName */
- int bStat1; /* True if this is sqlite_stat1 */
- const char **azCol; /* Column names */
- u8 *abPK; /* Array of primary key flags */
- int nEntry; /* Total number of entries in hash table */
- int nChange; /* Size of apChange[] array */
- SessionChange **apChange; /* Hash table buckets */
-};
-
-/*
-** RECORD FORMAT:
-**
-** The following record format is similar to (but not compatible with) that
-** used in SQLite database files. This format is used as part of the
-** change-set binary format, and so must be architecture independent.
-**
-** Unlike the SQLite database record format, each field is self-contained -
-** there is no separation of header and data. Each field begins with a
-** single byte describing its type, as follows:
-**
-** 0x00: Undefined value.
-** 0x01: Integer value.
-** 0x02: Real value.
-** 0x03: Text value.
-** 0x04: Blob value.
-** 0x05: SQL NULL value.
-**
-** Note that the above match the definitions of SQLITE_INTEGER, SQLITE_TEXT
-** and so on in sqlite3.h. For undefined and NULL values, the field consists
-** only of the single type byte. For other types of values, the type byte
-** is followed by:
-**
-** Text values:
-** A varint containing the number of bytes in the value (encoded using
-** UTF-8). Followed by a buffer containing the UTF-8 representation
-** of the text value. There is no nul terminator.
-**
-** Blob values:
-** A varint containing the number of bytes in the value, followed by
-** a buffer containing the value itself.
-**
-** Integer values:
-** An 8-byte big-endian integer value.
-**
-** Real values:
-** An 8-byte big-endian IEEE 754-2008 real value.
-**
-** Varint values are encoded in the same way as varints in the SQLite
-** record format.
-**
-** CHANGESET FORMAT:
-**
-** A changeset is a collection of DELETE, UPDATE and INSERT operations on
-** one or more tables. Operations on a single table are grouped together,
-** but may occur in any order (i.e. deletes, updates and inserts are all
-** mixed together).
-**
-** Each group of changes begins with a table header:
-**
-** 1 byte: Constant 0x54 (capital 'T')
-** Varint: Number of columns in the table.
-** nCol bytes: 0x01 for PK columns, 0x00 otherwise.
-** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated.
-**
-** Followed by one or more changes to the table.
-**
-** 1 byte: Either SQLITE_INSERT (0x12), UPDATE (0x17) or DELETE (0x09).
-** 1 byte: The "indirect-change" flag.
-** old.* record: (delete and update only)
-** new.* record: (insert and update only)
-**
-** The "old.*" and "new.*" records, if present, are N field records in the
-** format described above under "RECORD FORMAT", where N is the number of
-** columns in the table. The i'th field of each record is associated with
-** the i'th column of the table, counting from left to right in the order
-** in which columns were declared in the CREATE TABLE statement.
-**
-** The new.* record that is part of each INSERT change contains the values
-** that make up the new row. Similarly, the old.* record that is part of each
-** DELETE change contains the values that made up the row that was deleted
-** from the database. In the changeset format, the records that are part
-** of INSERT or DELETE changes never contain any undefined (type byte 0x00)
-** fields.
-**
-** Within the old.* record associated with an UPDATE change, all fields
-** associated with table columns that are not PRIMARY KEY columns and are
-** not modified by the UPDATE change are set to "undefined". Other fields
-** are set to the values that made up the row before the UPDATE that the
-** change records took place. Within the new.* record, fields associated
-** with table columns modified by the UPDATE change contain the new
-** values. Fields associated with table columns that are not modified
-** are set to "undefined".
-**
-** PATCHSET FORMAT:
-**
-** A patchset is also a collection of changes. It is similar to a changeset,
-** but leaves undefined those fields that are not useful if no conflict
-** resolution is required when applying the changeset.
-**
-** Each group of changes begins with a table header:
-**
-** 1 byte: Constant 0x50 (capital 'P')
-** Varint: Number of columns in the table.
-** nCol bytes: 0x01 for PK columns, 0x00 otherwise.
-** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated.
-**
-** Followed by one or more changes to the table.
-**
-** 1 byte: Either SQLITE_INSERT (0x12), UPDATE (0x17) or DELETE (0x09).
-** 1 byte: The "indirect-change" flag.
-** single record: (PK fields for DELETE, PK and modified fields for UPDATE,
-** full record for INSERT).
-**
-** As in the changeset format, each field of the single record that is part
-** of a patchset change is associated with the correspondingly positioned
-** table column, counting from left to right within the CREATE TABLE
-** statement.
-**
-** For a DELETE change, all fields within the record except those associated
-** with PRIMARY KEY columns are omitted. The PRIMARY KEY fields contain the
-** values identifying the row to delete.
-**
-** For an UPDATE change, all fields except those associated with PRIMARY KEY
-** columns and columns that are modified by the UPDATE are set to "undefined".
-** PRIMARY KEY fields contain the values identifying the table row to update,
-** and fields associated with modified columns contain the new column values.
-**
-** The records associated with INSERT changes are in the same format as for
-** changesets. It is not possible for a record associated with an INSERT
-** change to contain a field set to "undefined".
-*/
-
-/*
-** For each row modified during a session, there exists a single instance of
-** this structure stored in a SessionTable.aChange[] hash table.
-*/
-struct SessionChange {
- int op; /* One of UPDATE, DELETE, INSERT */
- int bIndirect; /* True if this change is "indirect" */
- int nRecord; /* Number of bytes in buffer aRecord[] */
- u8 *aRecord; /* Buffer containing old.* record */
- SessionChange *pNext; /* For hash-table collisions */
-};
-
-/*
-** Write a varint with value iVal into the buffer at aBuf. Return the
-** number of bytes written.
-*/
-static int sessionVarintPut(u8 *aBuf, int iVal){
- return putVarint32(aBuf, iVal);
-}
-
-/*
-** Return the number of bytes required to store value iVal as a varint.
-*/
-static int sessionVarintLen(int iVal){
- return sqlite3VarintLen(iVal);
-}
-
-/*
-** Read a varint value from aBuf[] into *piVal. Return the number of
-** bytes read.
-*/
-static int sessionVarintGet(u8 *aBuf, int *piVal){
- return getVarint32(aBuf, *piVal);
-}
-
-/* Load an unaligned and unsigned 32-bit integer */
-#define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
-
-/*
-** Read a 64-bit big-endian integer value from buffer aRec[]. Return
-** the value read.
-*/
-static sqlite3_int64 sessionGetI64(u8 *aRec){
- u64 x = SESSION_UINT32(aRec);
- u32 y = SESSION_UINT32(aRec+4);
- x = (x<<32) + y;
- return (sqlite3_int64)x;
-}
-
-/*
-** Write a 64-bit big-endian integer value to the buffer aBuf[].
-*/
-static void sessionPutI64(u8 *aBuf, sqlite3_int64 i){
- aBuf[0] = (i>>56) & 0xFF;
- aBuf[1] = (i>>48) & 0xFF;
- aBuf[2] = (i>>40) & 0xFF;
- aBuf[3] = (i>>32) & 0xFF;
- aBuf[4] = (i>>24) & 0xFF;
- aBuf[5] = (i>>16) & 0xFF;
- aBuf[6] = (i>> 8) & 0xFF;
- aBuf[7] = (i>> 0) & 0xFF;
-}
-
-/*
-** This function is used to serialize the contents of value pValue (see
-** comment titled "RECORD FORMAT" above).
-**
-** If it is non-NULL, the serialized form of the value is written to
-** buffer aBuf. *pnWrite is set to the number of bytes written before
-** returning. Or, if aBuf is NULL, the only thing this function does is
-** set *pnWrite.
-**
-** If no error occurs, SQLITE_OK is returned. Or, if an OOM error occurs
-** within a call to sqlite3_value_text() (may fail if the db is utf-16))
-** SQLITE_NOMEM is returned.
-*/
-static int sessionSerializeValue(
- u8 *aBuf, /* If non-NULL, write serialized value here */
- sqlite3_value *pValue, /* Value to serialize */
- int *pnWrite /* IN/OUT: Increment by bytes written */
-){
- int nByte; /* Size of serialized value in bytes */
-
- if( pValue ){
- int eType; /* Value type (SQLITE_NULL, TEXT etc.) */
-
- eType = sqlite3_value_type(pValue);
- if( aBuf ) aBuf[0] = eType;
-
- switch( eType ){
- case SQLITE_NULL:
- nByte = 1;
- break;
-
- case SQLITE_INTEGER:
- case SQLITE_FLOAT:
- if( aBuf ){
- /* TODO: SQLite does something special to deal with mixed-endian
- ** floating point values (e.g. ARM7). This code probably should
- ** too. */
- u64 i;
- if( eType==SQLITE_INTEGER ){
- i = (u64)sqlite3_value_int64(pValue);
- }else{
- double r;
- assert( sizeof(double)==8 && sizeof(u64)==8 );
- r = sqlite3_value_double(pValue);
- memcpy(&i, &r, 8);
- }
- sessionPutI64(&aBuf[1], i);
- }
- nByte = 9;
- break;
-
- default: {
- u8 *z;
- int n;
- int nVarint;
-
- assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
- if( eType==SQLITE_TEXT ){
- z = (u8 *)sqlite3_value_text(pValue);
- }else{
- z = (u8 *)sqlite3_value_blob(pValue);
- }
- n = sqlite3_value_bytes(pValue);
- if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM;
- nVarint = sessionVarintLen(n);
-
- if( aBuf ){
- sessionVarintPut(&aBuf[1], n);
- if( n ) memcpy(&aBuf[nVarint + 1], z, n);
- }
-
- nByte = 1 + nVarint + n;
- break;
- }
- }
- }else{
- nByte = 1;
- if( aBuf ) aBuf[0] = '\0';
- }
-
- if( pnWrite ) *pnWrite += nByte;
- return SQLITE_OK;
-}
-
-
-/*
-** This macro is used to calculate hash key values for data structures. In
-** order to use this macro, the entire data structure must be represented
-** as a series of unsigned integers. In order to calculate a hash-key value
-** for a data structure represented as three such integers, the macro may
-** then be used as follows:
-**
-** int hash_key_value;
-** hash_key_value = HASH_APPEND(0, <value 1>);
-** hash_key_value = HASH_APPEND(hash_key_value, <value 2>);
-** hash_key_value = HASH_APPEND(hash_key_value, <value 3>);
-**
-** In practice, the data structures this macro is used for are the primary
-** key values of modified rows.
-*/
-#define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (unsigned int)(add)
-
-/*
-** Append the hash of the 64-bit integer passed as the second argument to the
-** hash-key value passed as the first. Return the new hash-key value.
-*/
-static unsigned int sessionHashAppendI64(unsigned int h, i64 i){
- h = HASH_APPEND(h, i & 0xFFFFFFFF);
- return HASH_APPEND(h, (i>>32)&0xFFFFFFFF);
-}
-
-/*
-** Append the hash of the blob passed via the second and third arguments to
-** the hash-key value passed as the first. Return the new hash-key value.
-*/
-static unsigned int sessionHashAppendBlob(unsigned int h, int n, const u8 *z){
- int i;
- for(i=0; i<n; i++) h = HASH_APPEND(h, z[i]);
- return h;
-}
-
-/*
-** Append the hash of the data type passed as the second argument to the
-** hash-key value passed as the first. Return the new hash-key value.
-*/
-static unsigned int sessionHashAppendType(unsigned int h, int eType){
- return HASH_APPEND(h, eType);
-}
-
-/*
-** This function may only be called from within a pre-update callback.
-** It calculates a hash based on the primary key values of the old.* or
-** new.* row currently available and, assuming no error occurs, writes it to
-** *piHash before returning. If the primary key contains one or more NULL
-** values, *pbNullPK is set to true before returning.
-**
-** If an error occurs, an SQLite error code is returned and the final values
-** of *piHash asn *pbNullPK are undefined. Otherwise, SQLITE_OK is returned
-** and the output variables are set as described above.
-*/
-static int sessionPreupdateHash(
- sqlite3_session *pSession, /* Session object that owns pTab */
- SessionTable *pTab, /* Session table handle */
- int bNew, /* True to hash the new.* PK */
- int *piHash, /* OUT: Hash value */
- int *pbNullPK /* OUT: True if there are NULL values in PK */
-){
- unsigned int h = 0; /* Hash value to return */
- int i; /* Used to iterate through columns */
-
- assert( *pbNullPK==0 );
- assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) );
- for(i=0; i<pTab->nCol; i++){
- if( pTab->abPK[i] ){
- int rc;
- int eType;
- sqlite3_value *pVal;
-
- if( bNew ){
- rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal);
- }else{
- rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal);
- }
- if( rc!=SQLITE_OK ) return rc;
-
- eType = sqlite3_value_type(pVal);
- h = sessionHashAppendType(h, eType);
- if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- i64 iVal;
- if( eType==SQLITE_INTEGER ){
- iVal = sqlite3_value_int64(pVal);
- }else{
- double rVal = sqlite3_value_double(pVal);
- assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
- memcpy(&iVal, &rVal, 8);
- }
- h = sessionHashAppendI64(h, iVal);
- }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
- const u8 *z;
- int n;
- if( eType==SQLITE_TEXT ){
- z = (const u8 *)sqlite3_value_text(pVal);
- }else{
- z = (const u8 *)sqlite3_value_blob(pVal);
- }
- n = sqlite3_value_bytes(pVal);
- if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM;
- h = sessionHashAppendBlob(h, n, z);
- }else{
- assert( eType==SQLITE_NULL );
- assert( pTab->bStat1==0 || i!=1 );
- *pbNullPK = 1;
- }
- }
- }
-
- *piHash = (h % pTab->nChange);
- return SQLITE_OK;
-}
-
-/*
-** The buffer that the argument points to contains a serialized SQL value.
-** Return the number of bytes of space occupied by the value (including
-** the type byte).
-*/
-static int sessionSerialLen(u8 *a){
- int e = *a;
- int n;
- if( e==0 || e==0xFF ) return 1;
- if( e==SQLITE_NULL ) return 1;
- if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
- return sessionVarintGet(&a[1], &n) + 1 + n;
-}
-
-/*
-** Based on the primary key values stored in change aRecord, calculate a
-** hash key. Assume the has table has nBucket buckets. The hash keys
-** calculated by this function are compatible with those calculated by
-** sessionPreupdateHash().
-**
-** The bPkOnly argument is non-zero if the record at aRecord[] is from
-** a patchset DELETE. In this case the non-PK fields are omitted entirely.
-*/
-static unsigned int sessionChangeHash(
- SessionTable *pTab, /* Table handle */
- int bPkOnly, /* Record consists of PK fields only */
- u8 *aRecord, /* Change record */
- int nBucket /* Assume this many buckets in hash table */
-){
- unsigned int h = 0; /* Value to return */
- int i; /* Used to iterate through columns */
- u8 *a = aRecord; /* Used to iterate through change record */
-
- for(i=0; i<pTab->nCol; i++){
- int eType = *a;
- int isPK = pTab->abPK[i];
- if( bPkOnly && isPK==0 ) continue;
-
- /* It is not possible for eType to be SQLITE_NULL here. The session
- ** module does not record changes for rows with NULL values stored in
- ** primary key columns. */
- assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
- || eType==SQLITE_TEXT || eType==SQLITE_BLOB
- || eType==SQLITE_NULL || eType==0
- );
- assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) );
-
- if( isPK ){
- a++;
- h = sessionHashAppendType(h, eType);
- if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- h = sessionHashAppendI64(h, sessionGetI64(a));
- a += 8;
- }else{
- int n;
- a += sessionVarintGet(a, &n);
- h = sessionHashAppendBlob(h, n, a);
- a += n;
- }
- }else{
- a += sessionSerialLen(a);
- }
- }
- return (h % nBucket);
-}
-
-/*
-** Arguments aLeft and aRight are pointers to change records for table pTab.
-** This function returns true if the two records apply to the same row (i.e.
-** have the same values stored in the primary key columns), or false
-** otherwise.
-*/
-static int sessionChangeEqual(
- SessionTable *pTab, /* Table used for PK definition */
- int bLeftPkOnly, /* True if aLeft[] contains PK fields only */
- u8 *aLeft, /* Change record */
- int bRightPkOnly, /* True if aRight[] contains PK fields only */
- u8 *aRight /* Change record */
-){
- u8 *a1 = aLeft; /* Cursor to iterate through aLeft */
- u8 *a2 = aRight; /* Cursor to iterate through aRight */
- int iCol; /* Used to iterate through table columns */
-
- for(iCol=0; iCol<pTab->nCol; iCol++){
- if( pTab->abPK[iCol] ){
- int n1 = sessionSerialLen(a1);
- int n2 = sessionSerialLen(a2);
-
- if( n1!=n2 || memcmp(a1, a2, n1) ){
- return 0;
- }
- a1 += n1;
- a2 += n2;
- }else{
- if( bLeftPkOnly==0 ) a1 += sessionSerialLen(a1);
- if( bRightPkOnly==0 ) a2 += sessionSerialLen(a2);
- }
- }
-
- return 1;
-}
-
-/*
-** Arguments aLeft and aRight both point to buffers containing change
-** records with nCol columns. This function "merges" the two records into
-** a single records which is written to the buffer at *paOut. *paOut is
-** then set to point to one byte after the last byte written before
-** returning.
-**
-** The merging of records is done as follows: For each column, if the
-** aRight record contains a value for the column, copy the value from
-** their. Otherwise, if aLeft contains a value, copy it. If neither
-** record contains a value for a given column, then neither does the
-** output record.
-*/
-static void sessionMergeRecord(
- u8 **paOut,
- int nCol,
- u8 *aLeft,
- u8 *aRight
-){
- u8 *a1 = aLeft; /* Cursor used to iterate through aLeft */
- u8 *a2 = aRight; /* Cursor used to iterate through aRight */
- u8 *aOut = *paOut; /* Output cursor */
- int iCol; /* Used to iterate from 0 to nCol */
-
- for(iCol=0; iCol<nCol; iCol++){
- int n1 = sessionSerialLen(a1);
- int n2 = sessionSerialLen(a2);
- if( *a2 ){
- memcpy(aOut, a2, n2);
- aOut += n2;
- }else{
- memcpy(aOut, a1, n1);
- aOut += n1;
- }
- a1 += n1;
- a2 += n2;
- }
-
- *paOut = aOut;
-}
-
-/*
-** This is a helper function used by sessionMergeUpdate().
-**
-** When this function is called, both *paOne and *paTwo point to a value
-** within a change record. Before it returns, both have been advanced so
-** as to point to the next value in the record.
-**
-** If, when this function is called, *paTwo points to a valid value (i.e.
-** *paTwo[0] is not 0x00 - the "no value" placeholder), a copy of the *paTwo
-** pointer is returned and *pnVal is set to the number of bytes in the
-** serialized value. Otherwise, a copy of *paOne is returned and *pnVal
-** set to the number of bytes in the value at *paOne. If *paOne points
-** to the "no value" placeholder, *pnVal is set to 1. In other words:
-**
-** if( *paTwo is valid ) return *paTwo;
-** return *paOne;
-**
-*/
-static u8 *sessionMergeValue(
- u8 **paOne, /* IN/OUT: Left-hand buffer pointer */
- u8 **paTwo, /* IN/OUT: Right-hand buffer pointer */
- int *pnVal /* OUT: Bytes in returned value */
-){
- u8 *a1 = *paOne;
- u8 *a2 = *paTwo;
- u8 *pRet = 0;
- int n1;
-
- assert( a1 );
- if( a2 ){
- int n2 = sessionSerialLen(a2);
- if( *a2 ){
- *pnVal = n2;
- pRet = a2;
- }
- *paTwo = &a2[n2];
- }
-
- n1 = sessionSerialLen(a1);
- if( pRet==0 ){
- *pnVal = n1;
- pRet = a1;
- }
- *paOne = &a1[n1];
-
- return pRet;
-}
-
-/*
-** This function is used by changeset_concat() to merge two UPDATE changes
-** on the same row.
-*/
-static int sessionMergeUpdate(
- u8 **paOut, /* IN/OUT: Pointer to output buffer */
- SessionTable *pTab, /* Table change pertains to */
- int bPatchset, /* True if records are patchset records */
- u8 *aOldRecord1, /* old.* record for first change */
- u8 *aOldRecord2, /* old.* record for second change */
- u8 *aNewRecord1, /* new.* record for first change */
- u8 *aNewRecord2 /* new.* record for second change */
-){
- u8 *aOld1 = aOldRecord1;
- u8 *aOld2 = aOldRecord2;
- u8 *aNew1 = aNewRecord1;
- u8 *aNew2 = aNewRecord2;
-
- u8 *aOut = *paOut;
- int i;
-
- if( bPatchset==0 ){
- int bRequired = 0;
-
- assert( aOldRecord1 && aNewRecord1 );
-
- /* Write the old.* vector first. */
- for(i=0; i<pTab->nCol; i++){
- int nOld;
- u8 *aOld;
- int nNew;
- u8 *aNew;
-
- aOld = sessionMergeValue(&aOld1, &aOld2, &nOld);
- aNew = sessionMergeValue(&aNew1, &aNew2, &nNew);
- if( pTab->abPK[i] || nOld!=nNew || memcmp(aOld, aNew, nNew) ){
- if( pTab->abPK[i]==0 ) bRequired = 1;
- memcpy(aOut, aOld, nOld);
- aOut += nOld;
- }else{
- *(aOut++) = '\0';
- }
- }
-
- if( !bRequired ) return 0;
- }
-
- /* Write the new.* vector */
- aOld1 = aOldRecord1;
- aOld2 = aOldRecord2;
- aNew1 = aNewRecord1;
- aNew2 = aNewRecord2;
- for(i=0; i<pTab->nCol; i++){
- int nOld;
- u8 *aOld;
- int nNew;
- u8 *aNew;
-
- aOld = sessionMergeValue(&aOld1, &aOld2, &nOld);
- aNew = sessionMergeValue(&aNew1, &aNew2, &nNew);
- if( bPatchset==0
- && (pTab->abPK[i] || (nOld==nNew && 0==memcmp(aOld, aNew, nNew)))
- ){
- *(aOut++) = '\0';
- }else{
- memcpy(aOut, aNew, nNew);
- aOut += nNew;
- }
- }
-
- *paOut = aOut;
- return 1;
-}
-
-/*
-** This function is only called from within a pre-update-hook callback.
-** It determines if the current pre-update-hook change affects the same row
-** as the change stored in argument pChange. If so, it returns true. Otherwise
-** if the pre-update-hook does not affect the same row as pChange, it returns
-** false.
-*/
-static int sessionPreupdateEqual(
- sqlite3_session *pSession, /* Session object that owns SessionTable */
- SessionTable *pTab, /* Table associated with change */
- SessionChange *pChange, /* Change to compare to */
- int op /* Current pre-update operation */
-){
- int iCol; /* Used to iterate through columns */
- u8 *a = pChange->aRecord; /* Cursor used to scan change record */
-
- assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
- for(iCol=0; iCol<pTab->nCol; iCol++){
- if( !pTab->abPK[iCol] ){
- a += sessionSerialLen(a);
- }else{
- sqlite3_value *pVal; /* Value returned by preupdate_new/old */
- int rc; /* Error code from preupdate_new/old */
- int eType = *a++; /* Type of value from change record */
-
- /* The following calls to preupdate_new() and preupdate_old() can not
- ** fail. This is because they cache their return values, and by the
- ** time control flows to here they have already been called once from
- ** within sessionPreupdateHash(). The first two asserts below verify
- ** this (that the method has already been called). */
- if( op==SQLITE_INSERT ){
- /* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */
- rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal);
- }else{
- /* assert( db->pPreUpdate->pUnpacked ); */
- rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal);
- }
- assert( rc==SQLITE_OK );
- if( sqlite3_value_type(pVal)!=eType ) return 0;
-
- /* A SessionChange object never has a NULL value in a PK column */
- assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
- || eType==SQLITE_BLOB || eType==SQLITE_TEXT
- );
-
- if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- i64 iVal = sessionGetI64(a);
- a += 8;
- if( eType==SQLITE_INTEGER ){
- if( sqlite3_value_int64(pVal)!=iVal ) return 0;
- }else{
- double rVal;
- assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
- memcpy(&rVal, &iVal, 8);
- if( sqlite3_value_double(pVal)!=rVal ) return 0;
- }
- }else{
- int n;
- const u8 *z;
- a += sessionVarintGet(a, &n);
- if( sqlite3_value_bytes(pVal)!=n ) return 0;
- if( eType==SQLITE_TEXT ){
- z = sqlite3_value_text(pVal);
- }else{
- z = sqlite3_value_blob(pVal);
- }
- if( n>0 && memcmp(a, z, n) ) return 0;
- a += n;
- }
- }
- }
-
- return 1;
-}
-
-/*
-** If required, grow the hash table used to store changes on table pTab
-** (part of the session pSession). If a fatal OOM error occurs, set the
-** session object to failed and return SQLITE_ERROR. Otherwise, return
-** SQLITE_OK.
-**
-** It is possible that a non-fatal OOM error occurs in this function. In
-** that case the hash-table does not grow, but SQLITE_OK is returned anyway.
-** Growing the hash table in this case is a performance optimization only,
-** it is not required for correct operation.
-*/
-static int sessionGrowHash(int bPatchset, SessionTable *pTab){
- if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){
- int i;
- SessionChange **apNew;
- int nNew = (pTab->nChange ? pTab->nChange : 128) * 2;
-
- apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew);
- if( apNew==0 ){
- if( pTab->nChange==0 ){
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
- }
- memset(apNew, 0, sizeof(SessionChange *) * nNew);
-
- for(i=0; i<pTab->nChange; i++){
- SessionChange *p;
- SessionChange *pNext;
- for(p=pTab->apChange[i]; p; p=pNext){
- int bPkOnly = (p->op==SQLITE_DELETE && bPatchset);
- int iHash = sessionChangeHash(pTab, bPkOnly, p->aRecord, nNew);
- pNext = p->pNext;
- p->pNext = apNew[iHash];
- apNew[iHash] = p;
- }
- }
-
- sqlite3_free(pTab->apChange);
- pTab->nChange = nNew;
- pTab->apChange = apNew;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** This function queries the database for the names of the columns of table
-** zThis, in schema zDb.
-**
-** Otherwise, if they are not NULL, variable *pnCol is set to the number
-** of columns in the database table and variable *pzTab is set to point to a
-** nul-terminated copy of the table name. *pazCol (if not NULL) is set to
-** point to an array of pointers to column names. And *pabPK (again, if not
-** NULL) is set to point to an array of booleans - true if the corresponding
-** column is part of the primary key.
-**
-** For example, if the table is declared as:
-**
-** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z));
-**
-** Then the four output variables are populated as follows:
-**
-** *pnCol = 4
-** *pzTab = "tbl1"
-** *pazCol = {"w", "x", "y", "z"}
-** *pabPK = {1, 0, 0, 1}
-**
-** All returned buffers are part of the same single allocation, which must
-** be freed using sqlite3_free() by the caller
-*/
-static int sessionTableInfo(
- sqlite3 *db, /* Database connection */
- const char *zDb, /* Name of attached database (e.g. "main") */
- const char *zThis, /* Table name */
- int *pnCol, /* OUT: number of columns */
- const char **pzTab, /* OUT: Copy of zThis */
- const char ***pazCol, /* OUT: Array of column names for table */
- u8 **pabPK /* OUT: Array of booleans - true for PK col */
-){
- char *zPragma;
- sqlite3_stmt *pStmt;
- int rc;
- int nByte;
- int nDbCol = 0;
- int nThis;
- int i;
- u8 *pAlloc = 0;
- char **azCol = 0;
- u8 *abPK = 0;
-
- assert( pazCol && pabPK );
-
- nThis = sqlite3Strlen30(zThis);
- if( nThis==12 && 0==sqlite3_stricmp("sqlite_stat1", zThis) ){
- rc = sqlite3_table_column_metadata(db, zDb, zThis, 0, 0, 0, 0, 0, 0);
- if( rc==SQLITE_OK ){
- /* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */
- zPragma = sqlite3_mprintf(
- "SELECT 0, 'tbl', '', 0, '', 1 UNION ALL "
- "SELECT 1, 'idx', '', 0, '', 2 UNION ALL "
- "SELECT 2, 'stat', '', 0, '', 0"
- );
- }else if( rc==SQLITE_ERROR ){
- zPragma = sqlite3_mprintf("");
- }else{
- return rc;
- }
- }else{
- zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
- }
- if( !zPragma ) return SQLITE_NOMEM;
-
- rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0);
- sqlite3_free(zPragma);
- if( rc!=SQLITE_OK ) return rc;
-
- nByte = nThis + 1;
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- nByte += sqlite3_column_bytes(pStmt, 1);
- nDbCol++;
- }
- rc = sqlite3_reset(pStmt);
-
- if( rc==SQLITE_OK ){
- nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
- pAlloc = sqlite3_malloc(nByte);
- if( pAlloc==0 ){
- rc = SQLITE_NOMEM;
- }
- }
- if( rc==SQLITE_OK ){
- azCol = (char **)pAlloc;
- pAlloc = (u8 *)&azCol[nDbCol];
- abPK = (u8 *)pAlloc;
- pAlloc = &abPK[nDbCol];
- if( pzTab ){
- memcpy(pAlloc, zThis, nThis+1);
- *pzTab = (char *)pAlloc;
- pAlloc += nThis+1;
- }
-
- i = 0;
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- int nName = sqlite3_column_bytes(pStmt, 1);
- const unsigned char *zName = sqlite3_column_text(pStmt, 1);
- if( zName==0 ) break;
- memcpy(pAlloc, zName, nName+1);
- azCol[i] = (char *)pAlloc;
- pAlloc += nName+1;
- abPK[i] = sqlite3_column_int(pStmt, 5);
- i++;
- }
- rc = sqlite3_reset(pStmt);
-
- }
-
- /* If successful, populate the output variables. Otherwise, zero them and
- ** free any allocation made. An error code will be returned in this case.
- */
- if( rc==SQLITE_OK ){
- *pazCol = (const char **)azCol;
- *pabPK = abPK;
- *pnCol = nDbCol;
- }else{
- *pazCol = 0;
- *pabPK = 0;
- *pnCol = 0;
- if( pzTab ) *pzTab = 0;
- sqlite3_free(azCol);
- }
- sqlite3_finalize(pStmt);
- return rc;
-}
-
-/*
-** This function is only called from within a pre-update handler for a
-** write to table pTab, part of session pSession. If this is the first
-** write to this table, initalize the SessionTable.nCol, azCol[] and
-** abPK[] arrays accordingly.
-**
-** If an error occurs, an error code is stored in sqlite3_session.rc and
-** non-zero returned. Or, if no error occurs but the table has no primary
-** key, sqlite3_session.rc is left set to SQLITE_OK and non-zero returned to
-** indicate that updates on this table should be ignored. SessionTable.abPK
-** is set to NULL in this case.
-*/
-static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
- if( pTab->nCol==0 ){
- u8 *abPK;
- assert( pTab->azCol==0 || pTab->abPK==0 );
- pSession->rc = sessionTableInfo(pSession->db, pSession->zDb,
- pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK
- );
- if( pSession->rc==SQLITE_OK ){
- int i;
- for(i=0; i<pTab->nCol; i++){
- if( abPK[i] ){
- pTab->abPK = abPK;
- break;
- }
- }
- if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
- pTab->bStat1 = 1;
- }
- }
- }
- return (pSession->rc || pTab->abPK==0);
-}
-
-/*
-** Versions of the four methods in object SessionHook for use with the
-** sqlite_stat1 table. The purpose of this is to substitute a zero-length
-** blob each time a NULL value is read from the "idx" column of the
-** sqlite_stat1 table.
-*/
-typedef struct SessionStat1Ctx SessionStat1Ctx;
-struct SessionStat1Ctx {
- SessionHook hook;
- sqlite3_session *pSession;
-};
-static int sessionStat1Old(void *pCtx, int iCol, sqlite3_value **ppVal){
- SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
- sqlite3_value *pVal = 0;
- int rc = p->hook.xOld(p->hook.pCtx, iCol, &pVal);
- if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){
- pVal = p->pSession->pZeroBlob;
- }
- *ppVal = pVal;
- return rc;
-}
-static int sessionStat1New(void *pCtx, int iCol, sqlite3_value **ppVal){
- SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
- sqlite3_value *pVal = 0;
- int rc = p->hook.xNew(p->hook.pCtx, iCol, &pVal);
- if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){
- pVal = p->pSession->pZeroBlob;
- }
- *ppVal = pVal;
- return rc;
-}
-static int sessionStat1Count(void *pCtx){
- SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
- return p->hook.xCount(p->hook.pCtx);
-}
-static int sessionStat1Depth(void *pCtx){
- SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
- return p->hook.xDepth(p->hook.pCtx);
-}
-
-
-/*
-** This function is only called from with a pre-update-hook reporting a
-** change on table pTab (attached to session pSession). The type of change
-** (UPDATE, INSERT, DELETE) is specified by the first argument.
-**
-** Unless one is already present or an error occurs, an entry is added
-** to the changed-rows hash table associated with table pTab.
-*/
-static void sessionPreupdateOneChange(
- int op, /* One of SQLITE_UPDATE, INSERT, DELETE */
- sqlite3_session *pSession, /* Session object pTab is attached to */
- SessionTable *pTab /* Table that change applies to */
-){
- int iHash;
- int bNull = 0;
- int rc = SQLITE_OK;
- SessionStat1Ctx stat1 = {0};
-
- if( pSession->rc ) return;
-
- /* Load table details if required */
- if( sessionInitTable(pSession, pTab) ) return;
-
- /* Check the number of columns in this xPreUpdate call matches the
- ** number of columns in the table. */
- if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){
- pSession->rc = SQLITE_SCHEMA;
- return;
- }
-
- /* Grow the hash table if required */
- if( sessionGrowHash(0, pTab) ){
- pSession->rc = SQLITE_NOMEM;
- return;
- }
-
- if( pTab->bStat1 ){
- stat1.hook = pSession->hook;
- stat1.pSession = pSession;
- pSession->hook.pCtx = (void*)&stat1;
- pSession->hook.xNew = sessionStat1New;
- pSession->hook.xOld = sessionStat1Old;
- pSession->hook.xCount = sessionStat1Count;
- pSession->hook.xDepth = sessionStat1Depth;
- if( pSession->pZeroBlob==0 ){
- sqlite3_value *p = sqlite3ValueNew(0);
- if( p==0 ){
- rc = SQLITE_NOMEM;
- goto error_out;
- }
- sqlite3ValueSetStr(p, 0, "", 0, SQLITE_STATIC);
- pSession->pZeroBlob = p;
- }
- }
-
- /* Calculate the hash-key for this change. If the primary key of the row
- ** includes a NULL value, exit early. Such changes are ignored by the
- ** session module. */
- rc = sessionPreupdateHash(pSession, pTab, op==SQLITE_INSERT, &iHash, &bNull);
- if( rc!=SQLITE_OK ) goto error_out;
-
- if( bNull==0 ){
- /* Search the hash table for an existing record for this row. */
- SessionChange *pC;
- for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){
- if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break;
- }
-
- if( pC==0 ){
- /* Create a new change object containing all the old values (if
- ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
- ** values (if this is an INSERT). */
- SessionChange *pChange; /* New change object */
- int nByte; /* Number of bytes to allocate */
- int i; /* Used to iterate through columns */
-
- assert( rc==SQLITE_OK );
- pTab->nEntry++;
-
- /* Figure out how large an allocation is required */
- nByte = sizeof(SessionChange);
- for(i=0; i<pTab->nCol; i++){
- sqlite3_value *p = 0;
- if( op!=SQLITE_INSERT ){
- TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p);
- assert( trc==SQLITE_OK );
- }else if( pTab->abPK[i] ){
- TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p);
- assert( trc==SQLITE_OK );
- }
-
- /* This may fail if SQLite value p contains a utf-16 string that must
- ** be converted to utf-8 and an OOM error occurs while doing so. */
- rc = sessionSerializeValue(0, p, &nByte);
- if( rc!=SQLITE_OK ) goto error_out;
- }
-
- /* Allocate the change object */
- pChange = (SessionChange *)sqlite3_malloc(nByte);
- if( !pChange ){
- rc = SQLITE_NOMEM;
- goto error_out;
- }else{
- memset(pChange, 0, sizeof(SessionChange));
- pChange->aRecord = (u8 *)&pChange[1];
- }
-
- /* Populate the change object. None of the preupdate_old(),
- ** preupdate_new() or SerializeValue() calls below may fail as all
- ** required values and encodings have already been cached in memory.
- ** It is not possible for an OOM to occur in this block. */
- nByte = 0;
- for(i=0; i<pTab->nCol; i++){
- sqlite3_value *p = 0;
- if( op!=SQLITE_INSERT ){
- pSession->hook.xOld(pSession->hook.pCtx, i, &p);
- }else if( pTab->abPK[i] ){
- pSession->hook.xNew(pSession->hook.pCtx, i, &p);
- }
- sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte);
- }
-
- /* Add the change to the hash-table */
- if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){
- pChange->bIndirect = 1;
- }
- pChange->nRecord = nByte;
- pChange->op = op;
- pChange->pNext = pTab->apChange[iHash];
- pTab->apChange[iHash] = pChange;
-
- }else if( pC->bIndirect ){
- /* If the existing change is considered "indirect", but this current
- ** change is "direct", mark the change object as direct. */
- if( pSession->hook.xDepth(pSession->hook.pCtx)==0
- && pSession->bIndirect==0
- ){
- pC->bIndirect = 0;
- }
- }
- }
-
- /* If an error has occurred, mark the session object as failed. */
- error_out:
- if( pTab->bStat1 ){
- pSession->hook = stat1.hook;
- }
- if( rc!=SQLITE_OK ){
- pSession->rc = rc;
- }
-}
-
-static int sessionFindTable(
- sqlite3_session *pSession,
- const char *zName,
- SessionTable **ppTab
-){
- int rc = SQLITE_OK;
- int nName = sqlite3Strlen30(zName);
- SessionTable *pRet;
-
- /* Search for an existing table */
- for(pRet=pSession->pTable; pRet; pRet=pRet->pNext){
- if( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ) break;
- }
-
- if( pRet==0 && pSession->bAutoAttach ){
- /* If there is a table-filter configured, invoke it. If it returns 0,
- ** do not automatically add the new table. */
- if( pSession->xTableFilter==0
- || pSession->xTableFilter(pSession->pFilterCtx, zName)
- ){
- rc = sqlite3session_attach(pSession, zName);
- if( rc==SQLITE_OK ){
- for(pRet=pSession->pTable; pRet->pNext; pRet=pRet->pNext);
- assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) );
- }
- }
- }
-
- assert( rc==SQLITE_OK || pRet==0 );
- *ppTab = pRet;
- return rc;
-}
-
-/*
-** The 'pre-update' hook registered by this module with SQLite databases.
-*/
-static void xPreUpdate(
- void *pCtx, /* Copy of third arg to preupdate_hook() */
- sqlite3 *db, /* Database handle */
- int op, /* SQLITE_UPDATE, DELETE or INSERT */
- char const *zDb, /* Database name */
- char const *zName, /* Table name */
- sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
- sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
-){
- sqlite3_session *pSession;
- int nDb = sqlite3Strlen30(zDb);
-
- assert( sqlite3_mutex_held(db->mutex) );
-
- for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){
- SessionTable *pTab;
-
- /* If this session is attached to a different database ("main", "temp"
- ** etc.), or if it is not currently enabled, there is nothing to do. Skip
- ** to the next session object attached to this database. */
- if( pSession->bEnable==0 ) continue;
- if( pSession->rc ) continue;
- if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue;
-
- pSession->rc = sessionFindTable(pSession, zName, &pTab);
- if( pTab ){
- assert( pSession->rc==SQLITE_OK );
- sessionPreupdateOneChange(op, pSession, pTab);
- if( op==SQLITE_UPDATE ){
- sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab);
- }
- }
- }
-}
-
-/*
-** The pre-update hook implementations.
-*/
-static int sessionPreupdateOld(void *pCtx, int iVal, sqlite3_value **ppVal){
- return sqlite3_preupdate_old((sqlite3*)pCtx, iVal, ppVal);
-}
-static int sessionPreupdateNew(void *pCtx, int iVal, sqlite3_value **ppVal){
- return sqlite3_preupdate_new((sqlite3*)pCtx, iVal, ppVal);
-}
-static int sessionPreupdateCount(void *pCtx){
- return sqlite3_preupdate_count((sqlite3*)pCtx);
-}
-static int sessionPreupdateDepth(void *pCtx){
- return sqlite3_preupdate_depth((sqlite3*)pCtx);
-}
-
-/*
-** Install the pre-update hooks on the session object passed as the only
-** argument.
-*/
-static void sessionPreupdateHooks(
- sqlite3_session *pSession
-){
- pSession->hook.pCtx = (void*)pSession->db;
- pSession->hook.xOld = sessionPreupdateOld;
- pSession->hook.xNew = sessionPreupdateNew;
- pSession->hook.xCount = sessionPreupdateCount;
- pSession->hook.xDepth = sessionPreupdateDepth;
-}
-
-typedef struct SessionDiffCtx SessionDiffCtx;
-struct SessionDiffCtx {
- sqlite3_stmt *pStmt;
- int nOldOff;
-};
-
-/*
-** The diff hook implementations.
-*/
-static int sessionDiffOld(void *pCtx, int iVal, sqlite3_value **ppVal){
- SessionDiffCtx *p = (SessionDiffCtx*)pCtx;
- *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff);
- return SQLITE_OK;
-}
-static int sessionDiffNew(void *pCtx, int iVal, sqlite3_value **ppVal){
- SessionDiffCtx *p = (SessionDiffCtx*)pCtx;
- *ppVal = sqlite3_column_value(p->pStmt, iVal);
- return SQLITE_OK;
-}
-static int sessionDiffCount(void *pCtx){
- SessionDiffCtx *p = (SessionDiffCtx*)pCtx;
- return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt);
-}
-static int sessionDiffDepth(void *pCtx){
- return 0;
-}
-
-/*
-** Install the diff hooks on the session object passed as the only
-** argument.
-*/
-static void sessionDiffHooks(
- sqlite3_session *pSession,
- SessionDiffCtx *pDiffCtx
-){
- pSession->hook.pCtx = (void*)pDiffCtx;
- pSession->hook.xOld = sessionDiffOld;
- pSession->hook.xNew = sessionDiffNew;
- pSession->hook.xCount = sessionDiffCount;
- pSession->hook.xDepth = sessionDiffDepth;
-}
-
-static char *sessionExprComparePK(
- int nCol,
- const char *zDb1, const char *zDb2,
- const char *zTab,
- const char **azCol, u8 *abPK
-){
- int i;
- const char *zSep = "";
- char *zRet = 0;
-
- for(i=0; i<nCol; i++){
- if( abPK[i] ){
- zRet = sqlite3_mprintf("%z%s\"%w\".\"%w\".\"%w\"=\"%w\".\"%w\".\"%w\"",
- zRet, zSep, zDb1, zTab, azCol[i], zDb2, zTab, azCol[i]
- );
- zSep = " AND ";
- if( zRet==0 ) break;
- }
- }
-
- return zRet;
-}
-
-static char *sessionExprCompareOther(
- int nCol,
- const char *zDb1, const char *zDb2,
- const char *zTab,
- const char **azCol, u8 *abPK
-){
- int i;
- const char *zSep = "";
- char *zRet = 0;
- int bHave = 0;
-
- for(i=0; i<nCol; i++){
- if( abPK[i]==0 ){
- bHave = 1;
- zRet = sqlite3_mprintf(
- "%z%s\"%w\".\"%w\".\"%w\" IS NOT \"%w\".\"%w\".\"%w\"",
- zRet, zSep, zDb1, zTab, azCol[i], zDb2, zTab, azCol[i]
- );
- zSep = " OR ";
- if( zRet==0 ) break;
- }
- }
-
- if( bHave==0 ){
- assert( zRet==0 );
- zRet = sqlite3_mprintf("0");
- }
-
- return zRet;
-}
-
-static char *sessionSelectFindNew(
- int nCol,
- const char *zDb1, /* Pick rows in this db only */
- const char *zDb2, /* But not in this one */
- const char *zTbl, /* Table name */
- const char *zExpr
-){
- char *zRet = sqlite3_mprintf(
- "SELECT * FROM \"%w\".\"%w\" WHERE NOT EXISTS ("
- " SELECT 1 FROM \"%w\".\"%w\" WHERE %s"
- ")",
- zDb1, zTbl, zDb2, zTbl, zExpr
- );
- return zRet;
-}
-
-static int sessionDiffFindNew(
- int op,
- sqlite3_session *pSession,
- SessionTable *pTab,
- const char *zDb1,
- const char *zDb2,
- char *zExpr
-){
- int rc = SQLITE_OK;
- char *zStmt = sessionSelectFindNew(pTab->nCol, zDb1, zDb2, pTab->zName,zExpr);
-
- if( zStmt==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_stmt *pStmt;
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
- pDiffCtx->pStmt = pStmt;
- pDiffCtx->nOldOff = 0;
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- sessionPreupdateOneChange(op, pSession, pTab);
- }
- rc = sqlite3_finalize(pStmt);
- }
- sqlite3_free(zStmt);
- }
-
- return rc;
-}
-
-static int sessionDiffFindModified(
- sqlite3_session *pSession,
- SessionTable *pTab,
- const char *zFrom,
- const char *zExpr
-){
- int rc = SQLITE_OK;
-
- char *zExpr2 = sessionExprCompareOther(pTab->nCol,
- pSession->zDb, zFrom, pTab->zName, pTab->azCol, pTab->abPK
- );
- if( zExpr2==0 ){
- rc = SQLITE_NOMEM;
- }else{
- char *zStmt = sqlite3_mprintf(
- "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)",
- pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2
- );
- if( zStmt==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_stmt *pStmt;
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
-
- if( rc==SQLITE_OK ){
- SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
- pDiffCtx->pStmt = pStmt;
- pDiffCtx->nOldOff = pTab->nCol;
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- sessionPreupdateOneChange(SQLITE_UPDATE, pSession, pTab);
- }
- rc = sqlite3_finalize(pStmt);
- }
- sqlite3_free(zStmt);
- }
- }
-
- return rc;
-}
-
-int sqlite3session_diff(
- sqlite3_session *pSession,
- const char *zFrom,
- const char *zTbl,
- char **pzErrMsg
-){
- const char *zDb = pSession->zDb;
- int rc = pSession->rc;
- SessionDiffCtx d;
-
- memset(&d, 0, sizeof(d));
- sessionDiffHooks(pSession, &d);
-
- sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));
- if( pzErrMsg ) *pzErrMsg = 0;
- if( rc==SQLITE_OK ){
- char *zExpr = 0;
- sqlite3 *db = pSession->db;
- SessionTable *pTo; /* Table zTbl */
-
- /* Locate and if necessary initialize the target table object */
- rc = sessionFindTable(pSession, zTbl, &pTo);
- if( pTo==0 ) goto diff_out;
- if( sessionInitTable(pSession, pTo) ){
- rc = pSession->rc;
- goto diff_out;
- }
-
- /* Check the table schemas match */
- if( rc==SQLITE_OK ){
- int bHasPk = 0;
- int bMismatch = 0;
- int nCol; /* Columns in zFrom.zTbl */
- u8 *abPK;
- const char **azCol = 0;
- rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
- if( rc==SQLITE_OK ){
- if( pTo->nCol!=nCol ){
- bMismatch = 1;
- }else{
- int i;
- for(i=0; i<nCol; i++){
- if( pTo->abPK[i]!=abPK[i] ) bMismatch = 1;
- if( sqlite3_stricmp(azCol[i], pTo->azCol[i]) ) bMismatch = 1;
- if( abPK[i] ) bHasPk = 1;
- }
- }
- }
- sqlite3_free((char*)azCol);
- if( bMismatch ){
- *pzErrMsg = sqlite3_mprintf("table schemas do not match");
- rc = SQLITE_SCHEMA;
- }
- if( bHasPk==0 ){
- /* Ignore tables with no primary keys */
- goto diff_out;
- }
- }
-
- if( rc==SQLITE_OK ){
- zExpr = sessionExprComparePK(pTo->nCol,
- zDb, zFrom, pTo->zName, pTo->azCol, pTo->abPK
- );
- }
-
- /* Find new rows */
- if( rc==SQLITE_OK ){
- rc = sessionDiffFindNew(SQLITE_INSERT, pSession, pTo, zDb, zFrom, zExpr);
- }
-
- /* Find old rows */
- if( rc==SQLITE_OK ){
- rc = sessionDiffFindNew(SQLITE_DELETE, pSession, pTo, zFrom, zDb, zExpr);
- }
-
- /* Find modified rows */
- if( rc==SQLITE_OK ){
- rc = sessionDiffFindModified(pSession, pTo, zFrom, zExpr);
- }
-
- sqlite3_free(zExpr);
- }
-
- diff_out:
- sessionPreupdateHooks(pSession);
- sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
- return rc;
-}
-
-/*
-** Create a session object. This session object will record changes to
-** database zDb attached to connection db.
-*/
-int sqlite3session_create(
- sqlite3 *db, /* Database handle */
- const char *zDb, /* Name of db (e.g. "main") */
- sqlite3_session **ppSession /* OUT: New session object */
-){
- sqlite3_session *pNew; /* Newly allocated session object */
- sqlite3_session *pOld; /* Session object already attached to db */
- int nDb = sqlite3Strlen30(zDb); /* Length of zDb in bytes */
-
- /* Zero the output value in case an error occurs. */
- *ppSession = 0;
-
- /* Allocate and populate the new session object. */
- pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1);
- if( !pNew ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(sqlite3_session));
- pNew->db = db;
- pNew->zDb = (char *)&pNew[1];
- pNew->bEnable = 1;
- memcpy(pNew->zDb, zDb, nDb+1);
- sessionPreupdateHooks(pNew);
-
- /* Add the new session object to the linked list of session objects
- ** attached to database handle $db. Do this under the cover of the db
- ** handle mutex. */
- sqlite3_mutex_enter(sqlite3_db_mutex(db));
- pOld = (sqlite3_session*)sqlite3_preupdate_hook(db, xPreUpdate, (void*)pNew);
- pNew->pNext = pOld;
- sqlite3_mutex_leave(sqlite3_db_mutex(db));
-
- *ppSession = pNew;
- return SQLITE_OK;
-}
-
-/*
-** Free the list of table objects passed as the first argument. The contents
-** of the changed-rows hash tables are also deleted.
-*/
-static void sessionDeleteTable(SessionTable *pList){
- SessionTable *pNext;
- SessionTable *pTab;
-
- for(pTab=pList; pTab; pTab=pNext){
- int i;
- pNext = pTab->pNext;
- for(i=0; i<pTab->nChange; i++){
- SessionChange *p;
- SessionChange *pNextChange;
- for(p=pTab->apChange[i]; p; p=pNextChange){
- pNextChange = p->pNext;
- sqlite3_free(p);
- }
- }
- sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */
- sqlite3_free(pTab->apChange);
- sqlite3_free(pTab);
- }
-}
-
-/*
-** Delete a session object previously allocated using sqlite3session_create().
-*/
-void sqlite3session_delete(sqlite3_session *pSession){
- sqlite3 *db = pSession->db;
- sqlite3_session *pHead;
- sqlite3_session **pp;
-
- /* Unlink the session from the linked list of sessions attached to the
- ** database handle. Hold the db mutex while doing so. */
- sqlite3_mutex_enter(sqlite3_db_mutex(db));
- pHead = (sqlite3_session*)sqlite3_preupdate_hook(db, 0, 0);
- for(pp=&pHead; ALWAYS((*pp)!=0); pp=&((*pp)->pNext)){
- if( (*pp)==pSession ){
- *pp = (*pp)->pNext;
- if( pHead ) sqlite3_preupdate_hook(db, xPreUpdate, (void*)pHead);
- break;
- }
- }
- sqlite3_mutex_leave(sqlite3_db_mutex(db));
- sqlite3ValueFree(pSession->pZeroBlob);
-
- /* Delete all attached table objects. And the contents of their
- ** associated hash-tables. */
- sessionDeleteTable(pSession->pTable);
-
- /* Free the session object itself. */
- sqlite3_free(pSession);
-}
-
-/*
-** Set a table filter on a Session Object.
-*/
-void sqlite3session_table_filter(
- sqlite3_session *pSession,
- int(*xFilter)(void*, const char*),
- void *pCtx /* First argument passed to xFilter */
-){
- pSession->bAutoAttach = 1;
- pSession->pFilterCtx = pCtx;
- pSession->xTableFilter = xFilter;
-}
-
-/*
-** Attach a table to a session. All subsequent changes made to the table
-** while the session object is enabled will be recorded.
-**
-** Only tables that have a PRIMARY KEY defined may be attached. It does
-** not matter if the PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias)
-** or not.
-*/
-int sqlite3session_attach(
- sqlite3_session *pSession, /* Session object */
- const char *zName /* Table name */
-){
- int rc = SQLITE_OK;
- sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));
-
- if( !zName ){
- pSession->bAutoAttach = 1;
- }else{
- SessionTable *pTab; /* New table object (if required) */
- int nName; /* Number of bytes in string zName */
-
- /* First search for an existing entry. If one is found, this call is
- ** a no-op. Return early. */
- nName = sqlite3Strlen30(zName);
- for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){
- if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break;
- }
-
- if( !pTab ){
- /* Allocate new SessionTable object. */
- pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);
- if( !pTab ){
- rc = SQLITE_NOMEM;
- }else{
- /* Populate the new SessionTable object and link it into the list.
- ** The new object must be linked onto the end of the list, not
- ** simply added to the start of it in order to ensure that tables
- ** appear in the correct order when a changeset or patchset is
- ** eventually generated. */
- SessionTable **ppTab;
- memset(pTab, 0, sizeof(SessionTable));
- pTab->zName = (char *)&pTab[1];
- memcpy(pTab->zName, zName, nName+1);
- for(ppTab=&pSession->pTable; *ppTab; ppTab=&(*ppTab)->pNext);
- *ppTab = pTab;
- }
- }
- }
-
- sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
- return rc;
-}
-
-/*
-** Ensure that there is room in the buffer to append nByte bytes of data.
-** If not, use sqlite3_realloc() to grow the buffer so that there is.
-**
-** If successful, return zero. Otherwise, if an OOM condition is encountered,
-** set *pRc to SQLITE_NOMEM and return non-zero.
-*/
-static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){
- if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){
- u8 *aNew;
- int nNew = p->nAlloc ? p->nAlloc : 128;
- do {
- nNew = nNew*2;
- }while( nNew<(p->nBuf+nByte) );
-
- aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew);
- if( 0==aNew ){
- *pRc = SQLITE_NOMEM;
- }else{
- p->aBuf = aNew;
- p->nAlloc = nNew;
- }
- }
- return (*pRc!=SQLITE_OK);
-}
-
-/*
-** Append the value passed as the second argument to the buffer passed
-** as the first.
-**
-** This function is a no-op if *pRc is non-zero when it is called.
-** Otherwise, if an error occurs, *pRc is set to an SQLite error code
-** before returning.
-*/
-static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){
- int rc = *pRc;
- if( rc==SQLITE_OK ){
- int nByte = 0;
- rc = sessionSerializeValue(0, pVal, &nByte);
- sessionBufferGrow(p, nByte, &rc);
- if( rc==SQLITE_OK ){
- rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0);
- p->nBuf += nByte;
- }else{
- *pRc = rc;
- }
- }
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. Otherwise, append a single byte to the buffer.
-**
-** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
-** returning.
-*/
-static void sessionAppendByte(SessionBuffer *p, u8 v, int *pRc){
- if( 0==sessionBufferGrow(p, 1, pRc) ){
- p->aBuf[p->nBuf++] = v;
- }
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. Otherwise, append a single varint to the buffer.
-**
-** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
-** returning.
-*/
-static void sessionAppendVarint(SessionBuffer *p, int v, int *pRc){
- if( 0==sessionBufferGrow(p, 9, pRc) ){
- p->nBuf += sessionVarintPut(&p->aBuf[p->nBuf], v);
- }
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. Otherwise, append a blob of data to the buffer.
-**
-** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
-** returning.
-*/
-static void sessionAppendBlob(
- SessionBuffer *p,
- const u8 *aBlob,
- int nBlob,
- int *pRc
-){
- if( nBlob>0 && 0==sessionBufferGrow(p, nBlob, pRc) ){
- memcpy(&p->aBuf[p->nBuf], aBlob, nBlob);
- p->nBuf += nBlob;
- }
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. Otherwise, append a string to the buffer. All bytes in the string
-** up to (but not including) the nul-terminator are written to the buffer.
-**
-** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
-** returning.
-*/
-static void sessionAppendStr(
- SessionBuffer *p,
- const char *zStr,
- int *pRc
-){
- int nStr = sqlite3Strlen30(zStr);
- if( 0==sessionBufferGrow(p, nStr, pRc) ){
- memcpy(&p->aBuf[p->nBuf], zStr, nStr);
- p->nBuf += nStr;
- }
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. Otherwise, append the string representation of integer iVal
-** to the buffer. No nul-terminator is written.
-**
-** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
-** returning.
-*/
-static void sessionAppendInteger(
- SessionBuffer *p, /* Buffer to append to */
- int iVal, /* Value to write the string rep. of */
- int *pRc /* IN/OUT: Error code */
-){
- char aBuf[24];
- sqlite3_snprintf(sizeof(aBuf)-1, aBuf, "%d", iVal);
- sessionAppendStr(p, aBuf, pRc);
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. Otherwise, append the string zStr enclosed in quotes (") and
-** with any embedded quote characters escaped to the buffer. No
-** nul-terminator byte is written.
-**
-** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
-** returning.
-*/
-static void sessionAppendIdent(
- SessionBuffer *p, /* Buffer to a append to */
- const char *zStr, /* String to quote, escape and append */
- int *pRc /* IN/OUT: Error code */
-){
- int nStr = sqlite3Strlen30(zStr)*2 + 2 + 1;
- if( 0==sessionBufferGrow(p, nStr, pRc) ){
- char *zOut = (char *)&p->aBuf[p->nBuf];
- const char *zIn = zStr;
- *zOut++ = '"';
- while( *zIn ){
- if( *zIn=='"' ) *zOut++ = '"';
- *zOut++ = *(zIn++);
- }
- *zOut++ = '"';
- p->nBuf = (int)((u8 *)zOut - p->aBuf);
- }
-}
-
-/*
-** This function is a no-op if *pRc is other than SQLITE_OK when it is
-** called. Otherwse, it appends the serialized version of the value stored
-** in column iCol of the row that SQL statement pStmt currently points
-** to to the buffer.
-*/
-static void sessionAppendCol(
- SessionBuffer *p, /* Buffer to append to */
- sqlite3_stmt *pStmt, /* Handle pointing to row containing value */
- int iCol, /* Column to read value from */
- int *pRc /* IN/OUT: Error code */
-){
- if( *pRc==SQLITE_OK ){
- int eType = sqlite3_column_type(pStmt, iCol);
- sessionAppendByte(p, (u8)eType, pRc);
- if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- sqlite3_int64 i;
- u8 aBuf[8];
- if( eType==SQLITE_INTEGER ){
- i = sqlite3_column_int64(pStmt, iCol);
- }else{
- double r = sqlite3_column_double(pStmt, iCol);
- memcpy(&i, &r, 8);
- }
- sessionPutI64(aBuf, i);
- sessionAppendBlob(p, aBuf, 8, pRc);
- }
- if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){
- u8 *z;
- int nByte;
- if( eType==SQLITE_BLOB ){
- z = (u8 *)sqlite3_column_blob(pStmt, iCol);
- }else{
- z = (u8 *)sqlite3_column_text(pStmt, iCol);
- }
- nByte = sqlite3_column_bytes(pStmt, iCol);
- if( z || (eType==SQLITE_BLOB && nByte==0) ){
- sessionAppendVarint(p, nByte, pRc);
- sessionAppendBlob(p, z, nByte, pRc);
- }else{
- *pRc = SQLITE_NOMEM;
- }
- }
- }
-}
-
-/*
-**
-** This function appends an update change to the buffer (see the comments
-** under "CHANGESET FORMAT" at the top of the file). An update change
-** consists of:
-**
-** 1 byte: SQLITE_UPDATE (0x17)
-** n bytes: old.* record (see RECORD FORMAT)
-** m bytes: new.* record (see RECORD FORMAT)
-**
-** The SessionChange object passed as the third argument contains the
-** values that were stored in the row when the session began (the old.*
-** values). The statement handle passed as the second argument points
-** at the current version of the row (the new.* values).
-**
-** If all of the old.* values are equal to their corresponding new.* value
-** (i.e. nothing has changed), then no data at all is appended to the buffer.
-**
-** Otherwise, the old.* record contains all primary key values and the
-** original values of any fields that have been modified. The new.* record
-** contains the new values of only those fields that have been modified.
-*/
-static int sessionAppendUpdate(
- SessionBuffer *pBuf, /* Buffer to append to */
- int bPatchset, /* True for "patchset", 0 for "changeset" */
- sqlite3_stmt *pStmt, /* Statement handle pointing at new row */
- SessionChange *p, /* Object containing old values */
- u8 *abPK /* Boolean array - true for PK columns */
-){
- int rc = SQLITE_OK;
- SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */
- int bNoop = 1; /* Set to zero if any values are modified */
- int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */
- int i; /* Used to iterate through columns */
- u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */
-
- sessionAppendByte(pBuf, SQLITE_UPDATE, &rc);
- sessionAppendByte(pBuf, p->bIndirect, &rc);
- for(i=0; i<sqlite3_column_count(pStmt); i++){
- int bChanged = 0;
- int nAdvance;
- int eType = *pCsr;
- switch( eType ){
- case SQLITE_NULL:
- nAdvance = 1;
- if( sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){
- bChanged = 1;
- }
- break;
-
- case SQLITE_FLOAT:
- case SQLITE_INTEGER: {
- nAdvance = 9;
- if( eType==sqlite3_column_type(pStmt, i) ){
- sqlite3_int64 iVal = sessionGetI64(&pCsr[1]);
- if( eType==SQLITE_INTEGER ){
- if( iVal==sqlite3_column_int64(pStmt, i) ) break;
- }else{
- double dVal;
- memcpy(&dVal, &iVal, 8);
- if( dVal==sqlite3_column_double(pStmt, i) ) break;
- }
- }
- bChanged = 1;
- break;
- }
-
- default: {
- int n;
- int nHdr = 1 + sessionVarintGet(&pCsr[1], &n);
- assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
- nAdvance = nHdr + n;
- if( eType==sqlite3_column_type(pStmt, i)
- && n==sqlite3_column_bytes(pStmt, i)
- && (n==0 || 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), n))
- ){
- break;
- }
- bChanged = 1;
- }
- }
-
- /* If at least one field has been modified, this is not a no-op. */
- if( bChanged ) bNoop = 0;
-
- /* Add a field to the old.* record. This is omitted if this modules is
- ** currently generating a patchset. */
- if( bPatchset==0 ){
- if( bChanged || abPK[i] ){
- sessionAppendBlob(pBuf, pCsr, nAdvance, &rc);
- }else{
- sessionAppendByte(pBuf, 0, &rc);
- }
- }
-
- /* Add a field to the new.* record. Or the only record if currently
- ** generating a patchset. */
- if( bChanged || (bPatchset && abPK[i]) ){
- sessionAppendCol(&buf2, pStmt, i, &rc);
- }else{
- sessionAppendByte(&buf2, 0, &rc);
- }
-
- pCsr += nAdvance;
- }
-
- if( bNoop ){
- pBuf->nBuf = nRewind;
- }else{
- sessionAppendBlob(pBuf, buf2.aBuf, buf2.nBuf, &rc);
- }
- sqlite3_free(buf2.aBuf);
-
- return rc;
-}
-
-/*
-** Append a DELETE change to the buffer passed as the first argument. Use
-** the changeset format if argument bPatchset is zero, or the patchset
-** format otherwise.
-*/
-static int sessionAppendDelete(
- SessionBuffer *pBuf, /* Buffer to append to */
- int bPatchset, /* True for "patchset", 0 for "changeset" */
- SessionChange *p, /* Object containing old values */
- int nCol, /* Number of columns in table */
- u8 *abPK /* Boolean array - true for PK columns */
-){
- int rc = SQLITE_OK;
-
- sessionAppendByte(pBuf, SQLITE_DELETE, &rc);
- sessionAppendByte(pBuf, p->bIndirect, &rc);
-
- if( bPatchset==0 ){
- sessionAppendBlob(pBuf, p->aRecord, p->nRecord, &rc);
- }else{
- int i;
- u8 *a = p->aRecord;
- for(i=0; i<nCol; i++){
- u8 *pStart = a;
- int eType = *a++;
-
- switch( eType ){
- case 0:
- case SQLITE_NULL:
- assert( abPK[i]==0 );
- break;
-
- case SQLITE_FLOAT:
- case SQLITE_INTEGER:
- a += 8;
- break;
-
- default: {
- int n;
- a += sessionVarintGet(a, &n);
- a += n;
- break;
- }
- }
- if( abPK[i] ){
- sessionAppendBlob(pBuf, pStart, (int)(a-pStart), &rc);
- }
- }
- assert( (a - p->aRecord)==p->nRecord );
- }
-
- return rc;
-}
-
-/*
-** Formulate and prepare a SELECT statement to retrieve a row from table
-** zTab in database zDb based on its primary key. i.e.
-**
-** SELECT * FROM zDb.zTab WHERE pk1 = ? AND pk2 = ? AND ...
-*/
-static int sessionSelectStmt(
- sqlite3 *db, /* Database handle */
- const char *zDb, /* Database name */
- const char *zTab, /* Table name */
- int nCol, /* Number of columns in table */
- const char **azCol, /* Names of table columns */
- u8 *abPK, /* PRIMARY KEY array */
- sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */
-){
- int rc = SQLITE_OK;
- char *zSql = 0;
- int nSql = -1;
-
- if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){
- zSql = sqlite3_mprintf(
- "SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND "
- "idx IS (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", zDb
- );
- if( zSql==0 ) rc = SQLITE_NOMEM;
- }else{
- int i;
- const char *zSep = "";
- SessionBuffer buf = {0, 0, 0};
-
- sessionAppendStr(&buf, "SELECT * FROM ", &rc);
- sessionAppendIdent(&buf, zDb, &rc);
- sessionAppendStr(&buf, ".", &rc);
- sessionAppendIdent(&buf, zTab, &rc);
- sessionAppendStr(&buf, " WHERE ", &rc);
- for(i=0; i<nCol; i++){
- if( abPK[i] ){
- sessionAppendStr(&buf, zSep, &rc);
- sessionAppendIdent(&buf, azCol[i], &rc);
- sessionAppendStr(&buf, " IS ?", &rc);
- sessionAppendInteger(&buf, i+1, &rc);
- zSep = " AND ";
- }
- }
- zSql = (char*)buf.aBuf;
- nSql = buf.nBuf;
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0);
- }
- sqlite3_free(zSql);
- return rc;
-}
-
-/*
-** Bind the PRIMARY KEY values from the change passed in argument pChange
-** to the SELECT statement passed as the first argument. The SELECT statement
-** is as prepared by function sessionSelectStmt().
-**
-** Return SQLITE_OK if all PK values are successfully bound, or an SQLite
-** error code (e.g. SQLITE_NOMEM) otherwise.
-*/
-static int sessionSelectBind(
- sqlite3_stmt *pSelect, /* SELECT from sessionSelectStmt() */
- int nCol, /* Number of columns in table */
- u8 *abPK, /* PRIMARY KEY array */
- SessionChange *pChange /* Change structure */
-){
- int i;
- int rc = SQLITE_OK;
- u8 *a = pChange->aRecord;
-
- for(i=0; i<nCol && rc==SQLITE_OK; i++){
- int eType = *a++;
-
- switch( eType ){
- case 0:
- case SQLITE_NULL:
- assert( abPK[i]==0 );
- break;
-
- case SQLITE_INTEGER: {
- if( abPK[i] ){
- i64 iVal = sessionGetI64(a);
- rc = sqlite3_bind_int64(pSelect, i+1, iVal);
- }
- a += 8;
- break;
- }
-
- case SQLITE_FLOAT: {
- if( abPK[i] ){
- double rVal;
- i64 iVal = sessionGetI64(a);
- memcpy(&rVal, &iVal, 8);
- rc = sqlite3_bind_double(pSelect, i+1, rVal);
- }
- a += 8;
- break;
- }
-
- case SQLITE_TEXT: {
- int n;
- a += sessionVarintGet(a, &n);
- if( abPK[i] ){
- rc = sqlite3_bind_text(pSelect, i+1, (char *)a, n, SQLITE_TRANSIENT);
- }
- a += n;
- break;
- }
-
- default: {
- int n;
- assert( eType==SQLITE_BLOB );
- a += sessionVarintGet(a, &n);
- if( abPK[i] ){
- rc = sqlite3_bind_blob(pSelect, i+1, a, n, SQLITE_TRANSIENT);
- }
- a += n;
- break;
- }
- }
- }
-
- return rc;
-}
-
-/*
-** This function is a no-op if *pRc is set to other than SQLITE_OK when it
-** is called. Otherwise, append a serialized table header (part of the binary
-** changeset format) to buffer *pBuf. If an error occurs, set *pRc to an
-** SQLite error code before returning.
-*/
-static void sessionAppendTableHdr(
- SessionBuffer *pBuf, /* Append header to this buffer */
- int bPatchset, /* Use the patchset format if true */
- SessionTable *pTab, /* Table object to append header for */
- int *pRc /* IN/OUT: Error code */
-){
- /* Write a table header */
- sessionAppendByte(pBuf, (bPatchset ? 'P' : 'T'), pRc);
- sessionAppendVarint(pBuf, pTab->nCol, pRc);
- sessionAppendBlob(pBuf, pTab->abPK, pTab->nCol, pRc);
- sessionAppendBlob(pBuf, (u8 *)pTab->zName, (int)strlen(pTab->zName)+1, pRc);
-}
-
-/*
-** Generate either a changeset (if argument bPatchset is zero) or a patchset
-** (if it is non-zero) based on the current contents of the session object
-** passed as the first argument.
-**
-** If no error occurs, SQLITE_OK is returned and the new changeset/patchset
-** stored in output variables *pnChangeset and *ppChangeset. Or, if an error
-** occurs, an SQLite error code is returned and both output variables set
-** to 0.
-*/
-static int sessionGenerateChangeset(
- sqlite3_session *pSession, /* Session object */
- int bPatchset, /* True for patchset, false for changeset */
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut, /* First argument for xOutput */
- int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
- void **ppChangeset /* OUT: Buffer containing changeset */
-){
- sqlite3 *db = pSession->db; /* Source database handle */
- SessionTable *pTab; /* Used to iterate through attached tables */
- SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
- int rc; /* Return code */
-
- assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0 ) );
-
- /* Zero the output variables in case an error occurs. If this session
- ** object is already in the error state (sqlite3_session.rc != SQLITE_OK),
- ** this call will be a no-op. */
- if( xOutput==0 ){
- *pnChangeset = 0;
- *ppChangeset = 0;
- }
-
- if( pSession->rc ) return pSession->rc;
- rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
- if( rc!=SQLITE_OK ) return rc;
-
- sqlite3_mutex_enter(sqlite3_db_mutex(db));
-
- for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
- if( pTab->nEntry ){
- const char *zName = pTab->zName;
- int nCol; /* Number of columns in table */
- u8 *abPK; /* Primary key array */
- const char **azCol = 0; /* Table columns */
- int i; /* Used to iterate through hash buckets */
- sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */
- int nRewind = buf.nBuf; /* Initial size of write buffer */
- int nNoop; /* Size of buffer after writing tbl header */
-
- /* Check the table schema is still Ok. */
- rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK);
- if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){
- rc = SQLITE_SCHEMA;
- }
-
- /* Write a table header */
- sessionAppendTableHdr(&buf, bPatchset, pTab, &rc);
-
- /* Build and compile a statement to execute: */
- if( rc==SQLITE_OK ){
- rc = sessionSelectStmt(
- db, pSession->zDb, zName, nCol, azCol, abPK, &pSel);
- }
-
- nNoop = buf.nBuf;
- for(i=0; i<pTab->nChange && rc==SQLITE_OK; i++){
- SessionChange *p; /* Used to iterate through changes */
-
- for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){
- rc = sessionSelectBind(pSel, nCol, abPK, p);
- if( rc!=SQLITE_OK ) continue;
- if( sqlite3_step(pSel)==SQLITE_ROW ){
- if( p->op==SQLITE_INSERT ){
- int iCol;
- sessionAppendByte(&buf, SQLITE_INSERT, &rc);
- sessionAppendByte(&buf, p->bIndirect, &rc);
- for(iCol=0; iCol<nCol; iCol++){
- sessionAppendCol(&buf, pSel, iCol, &rc);
- }
- }else{
- rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK);
- }
- }else if( p->op!=SQLITE_INSERT ){
- rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_reset(pSel);
- }
-
- /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass
- ** its contents to the xOutput() callback. */
- if( xOutput
- && rc==SQLITE_OK
- && buf.nBuf>nNoop
- && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE
- ){
- rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf);
- nNoop = -1;
- buf.nBuf = 0;
- }
-
- }
- }
-
- sqlite3_finalize(pSel);
- if( buf.nBuf==nNoop ){
- buf.nBuf = nRewind;
- }
- sqlite3_free((char*)azCol); /* cast works around VC++ bug */
- }
- }
-
- if( rc==SQLITE_OK ){
- if( xOutput==0 ){
- *pnChangeset = buf.nBuf;
- *ppChangeset = buf.aBuf;
- buf.aBuf = 0;
- }else if( buf.nBuf>0 ){
- rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf);
- }
- }
-
- sqlite3_free(buf.aBuf);
- sqlite3_exec(db, "RELEASE changeset", 0, 0, 0);
- sqlite3_mutex_leave(sqlite3_db_mutex(db));
- return rc;
-}
-
-/*
-** Obtain a changeset object containing all changes recorded by the
-** session object passed as the first argument.
-**
-** It is the responsibility of the caller to eventually free the buffer
-** using sqlite3_free().
-*/
-int sqlite3session_changeset(
- sqlite3_session *pSession, /* Session object */
- int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
- void **ppChangeset /* OUT: Buffer containing changeset */
-){
- return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset);
-}
-
-/*
-** Streaming version of sqlite3session_changeset().
-*/
-int sqlite3session_changeset_strm(
- sqlite3_session *pSession,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-){
- return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0);
-}
-
-/*
-** Streaming version of sqlite3session_patchset().
-*/
-int sqlite3session_patchset_strm(
- sqlite3_session *pSession,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-){
- return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0);
-}
-
-/*
-** Obtain a patchset object containing all changes recorded by the
-** session object passed as the first argument.
-**
-** It is the responsibility of the caller to eventually free the buffer
-** using sqlite3_free().
-*/
-int sqlite3session_patchset(
- sqlite3_session *pSession, /* Session object */
- int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */
- void **ppPatchset /* OUT: Buffer containing changeset */
-){
- return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset);
-}
-
-/*
-** Enable or disable the session object passed as the first argument.
-*/
-int sqlite3session_enable(sqlite3_session *pSession, int bEnable){
- int ret;
- sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));
- if( bEnable>=0 ){
- pSession->bEnable = bEnable;
- }
- ret = pSession->bEnable;
- sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
- return ret;
-}
-
-/*
-** Enable or disable the session object passed as the first argument.
-*/
-int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect){
- int ret;
- sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));
- if( bIndirect>=0 ){
- pSession->bIndirect = bIndirect;
- }
- ret = pSession->bIndirect;
- sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
- return ret;
-}
-
-/*
-** Return true if there have been no changes to monitored tables recorded
-** by the session object passed as the only argument.
-*/
-int sqlite3session_isempty(sqlite3_session *pSession){
- int ret = 0;
- SessionTable *pTab;
-
- sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));
- for(pTab=pSession->pTable; pTab && ret==0; pTab=pTab->pNext){
- ret = (pTab->nEntry>0);
- }
- sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
-
- return (ret==0);
-}
-
-/*
-** Do the work for either sqlite3changeset_start() or start_strm().
-*/
-static int sessionChangesetStart(
- sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn,
- int nChangeset, /* Size of buffer pChangeset in bytes */
- void *pChangeset /* Pointer to buffer containing changeset */
-){
- sqlite3_changeset_iter *pRet; /* Iterator to return */
- int nByte; /* Number of bytes to allocate for iterator */
-
- assert( xInput==0 || (pChangeset==0 && nChangeset==0) );
-
- /* Zero the output variable in case an error occurs. */
- *pp = 0;
-
- /* Allocate and initialize the iterator structure. */
- nByte = sizeof(sqlite3_changeset_iter);
- pRet = (sqlite3_changeset_iter *)sqlite3_malloc(nByte);
- if( !pRet ) return SQLITE_NOMEM;
- memset(pRet, 0, sizeof(sqlite3_changeset_iter));
- pRet->in.aData = (u8 *)pChangeset;
- pRet->in.nData = nChangeset;
- pRet->in.xInput = xInput;
- pRet->in.pIn = pIn;
- pRet->in.bEof = (xInput ? 0 : 1);
-
- /* Populate the output variable and return success. */
- *pp = pRet;
- return SQLITE_OK;
-}
-
-/*
-** Create an iterator used to iterate through the contents of a changeset.
-*/
-int sqlite3changeset_start(
- sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
- int nChangeset, /* Size of buffer pChangeset in bytes */
- void *pChangeset /* Pointer to buffer containing changeset */
-){
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset);
-}
-
-/*
-** Streaming version of sqlite3changeset_start().
-*/
-int sqlite3changeset_start_strm(
- sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn
-){
- return sessionChangesetStart(pp, xInput, pIn, 0, 0);
-}
-
-/*
-** If the SessionInput object passed as the only argument is a streaming
-** object and the buffer is full, discard some data to free up space.
-*/
-static void sessionDiscardData(SessionInput *pIn){
- if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){
- int nMove = pIn->buf.nBuf - pIn->iNext;
- assert( nMove>=0 );
- if( nMove>0 ){
- memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove);
- }
- pIn->buf.nBuf -= pIn->iNext;
- pIn->iNext = 0;
- pIn->nData = pIn->buf.nBuf;
- }
-}
-
-/*
-** Ensure that there are at least nByte bytes available in the buffer. Or,
-** if there are not nByte bytes remaining in the input, that all available
-** data is in the buffer.
-**
-** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
-*/
-static int sessionInputBuffer(SessionInput *pIn, int nByte){
- int rc = SQLITE_OK;
- if( pIn->xInput ){
- while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){
- int nNew = SESSIONS_STRM_CHUNK_SIZE;
-
- if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn);
- if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){
- rc = pIn->xInput(pIn->pIn, &pIn->buf.aBuf[pIn->buf.nBuf], &nNew);
- if( nNew==0 ){
- pIn->bEof = 1;
- }else{
- pIn->buf.nBuf += nNew;
- }
- }
-
- pIn->aData = pIn->buf.aBuf;
- pIn->nData = pIn->buf.nBuf;
- }
- }
- return rc;
-}
-
-/*
-** When this function is called, *ppRec points to the start of a record
-** that contains nCol values. This function advances the pointer *ppRec
-** until it points to the byte immediately following that record.
-*/
-static void sessionSkipRecord(
- u8 **ppRec, /* IN/OUT: Record pointer */
- int nCol /* Number of values in record */
-){
- u8 *aRec = *ppRec;
- int i;
- for(i=0; i<nCol; i++){
- int eType = *aRec++;
- if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
- int nByte;
- aRec += sessionVarintGet((u8*)aRec, &nByte);
- aRec += nByte;
- }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- aRec += 8;
- }
- }
-
- *ppRec = aRec;
-}
-
-/*
-** This function sets the value of the sqlite3_value object passed as the
-** first argument to a copy of the string or blob held in the aData[]
-** buffer. SQLITE_OK is returned if successful, or SQLITE_NOMEM if an OOM
-** error occurs.
-*/
-static int sessionValueSetStr(
- sqlite3_value *pVal, /* Set the value of this object */
- u8 *aData, /* Buffer containing string or blob data */
- int nData, /* Size of buffer aData[] in bytes */
- u8 enc /* String encoding (0 for blobs) */
-){
- /* In theory this code could just pass SQLITE_TRANSIENT as the final
- ** argument to sqlite3ValueSetStr() and have the copy created
- ** automatically. But doing so makes it difficult to detect any OOM
- ** error. Hence the code to create the copy externally. */
- u8 *aCopy = sqlite3_malloc(nData+1);
- if( aCopy==0 ) return SQLITE_NOMEM;
- memcpy(aCopy, aData, nData);
- sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free);
- return SQLITE_OK;
-}
-
-/*
-** Deserialize a single record from a buffer in memory. See "RECORD FORMAT"
-** for details.
-**
-** When this function is called, *paChange points to the start of the record
-** to deserialize. Assuming no error occurs, *paChange is set to point to
-** one byte after the end of the same record before this function returns.
-** If the argument abPK is NULL, then the record contains nCol values. Or,
-** if abPK is other than NULL, then the record contains only the PK fields
-** (in other words, it is a patchset DELETE record).
-**
-** If successful, each element of the apOut[] array (allocated by the caller)
-** is set to point to an sqlite3_value object containing the value read
-** from the corresponding position in the record. If that value is not
-** included in the record (i.e. because the record is part of an UPDATE change
-** and the field was not modified), the corresponding element of apOut[] is
-** set to NULL.
-**
-** It is the responsibility of the caller to free all sqlite_value structures
-** using sqlite3_free().
-**
-** If an error occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
-** The apOut[] array may have been partially populated in this case.
-*/
-static int sessionReadRecord(
- SessionInput *pIn, /* Input data */
- int nCol, /* Number of values in record */
- u8 *abPK, /* Array of primary key flags, or NULL */
- sqlite3_value **apOut /* Write values to this array */
-){
- int i; /* Used to iterate through columns */
- int rc = SQLITE_OK;
-
- for(i=0; i<nCol && rc==SQLITE_OK; i++){
- int eType = 0; /* Type of value (SQLITE_NULL, TEXT etc.) */
- if( abPK && abPK[i]==0 ) continue;
- rc = sessionInputBuffer(pIn, 9);
- if( rc==SQLITE_OK ){
- if( pIn->iNext>=pIn->nData ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- eType = pIn->aData[pIn->iNext++];
- assert( apOut[i]==0 );
- if( eType ){
- apOut[i] = sqlite3ValueNew(0);
- if( !apOut[i] ) rc = SQLITE_NOMEM;
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- u8 *aVal = &pIn->aData[pIn->iNext];
- if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
- int nByte;
- pIn->iNext += sessionVarintGet(aVal, &nByte);
- rc = sessionInputBuffer(pIn, nByte);
- if( rc==SQLITE_OK ){
- if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
- rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
- pIn->iNext += nByte;
- }
- }
- }
- if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- sqlite3_int64 v = sessionGetI64(aVal);
- if( eType==SQLITE_INTEGER ){
- sqlite3VdbeMemSetInt64(apOut[i], v);
- }else{
- double d;
- memcpy(&d, &v, 8);
- sqlite3VdbeMemSetDouble(apOut[i], d);
- }
- pIn->iNext += 8;
- }
- }
- }
-
- return rc;
-}
-
-/*
-** The input pointer currently points to the second byte of a table-header.
-** Specifically, to the following:
-**
-** + number of columns in table (varint)
-** + array of PK flags (1 byte per column),
-** + table name (nul terminated).
-**
-** This function ensures that all of the above is present in the input
-** buffer (i.e. that it can be accessed without any calls to xInput()).
-** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
-** The input pointer is not moved.
-*/
-static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){
- int rc = SQLITE_OK;
- int nCol = 0;
- int nRead = 0;
-
- rc = sessionInputBuffer(pIn, 9);
- if( rc==SQLITE_OK ){
- nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol);
- /* The hard upper limit for the number of columns in an SQLite
- ** database table is, according to sqliteLimit.h, 32676. So
- ** consider any table-header that purports to have more than 65536
- ** columns to be corrupt. This is convenient because otherwise,
- ** if the (nCol>65536) condition below were omitted, a sufficiently
- ** large value for nCol may cause nRead to wrap around and become
- ** negative. Leading to a crash. */
- if( nCol<0 || nCol>65536 ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- rc = sessionInputBuffer(pIn, nRead+nCol+100);
- nRead += nCol;
- }
- }
-
- while( rc==SQLITE_OK ){
- while( (pIn->iNext + nRead)<pIn->nData && pIn->aData[pIn->iNext + nRead] ){
- nRead++;
- }
- if( (pIn->iNext + nRead)<pIn->nData ) break;
- rc = sessionInputBuffer(pIn, nRead + 100);
- }
- *pnByte = nRead+1;
- return rc;
-}
-
-/*
-** The input pointer currently points to the first byte of the first field
-** of a record consisting of nCol columns. This function ensures the entire
-** record is buffered. It does not move the input pointer.
-**
-** If successful, SQLITE_OK is returned and *pnByte is set to the size of
-** the record in bytes. Otherwise, an SQLite error code is returned. The
-** final value of *pnByte is undefined in this case.
-*/
-static int sessionChangesetBufferRecord(
- SessionInput *pIn, /* Input data */
- int nCol, /* Number of columns in record */
- int *pnByte /* OUT: Size of record in bytes */
-){
- int rc = SQLITE_OK;
- int nByte = 0;
- int i;
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- int eType;
- rc = sessionInputBuffer(pIn, nByte + 10);
- if( rc==SQLITE_OK ){
- eType = pIn->aData[pIn->iNext + nByte++];
- if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
- int n;
- nByte += sessionVarintGet(&pIn->aData[pIn->iNext+nByte], &n);
- nByte += n;
- rc = sessionInputBuffer(pIn, nByte);
- }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- nByte += 8;
- }
- }
- }
- *pnByte = nByte;
- return rc;
-}
-
-/*
-** The input pointer currently points to the second byte of a table-header.
-** Specifically, to the following:
-**
-** + number of columns in table (varint)
-** + array of PK flags (1 byte per column),
-** + table name (nul terminated).
-**
-** This function decodes the table-header and populates the p->nCol,
-** p->zTab and p->abPK[] variables accordingly. The p->apValue[] array is
-** also allocated or resized according to the new value of p->nCol. The
-** input pointer is left pointing to the byte following the table header.
-**
-** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code
-** is returned and the final values of the various fields enumerated above
-** are undefined.
-*/
-static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
- int rc;
- int nCopy;
- assert( p->rc==SQLITE_OK );
-
- rc = sessionChangesetBufferTblhdr(&p->in, &nCopy);
- if( rc==SQLITE_OK ){
- int nByte;
- int nVarint;
- nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol);
- if( p->nCol>0 ){
- nCopy -= nVarint;
- p->in.iNext += nVarint;
- nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy;
- p->tblhdr.nBuf = 0;
- sessionBufferGrow(&p->tblhdr, nByte, &rc);
- }else{
- rc = SQLITE_CORRUPT_BKPT;
- }
- }
-
- if( rc==SQLITE_OK ){
- int iPK = sizeof(sqlite3_value*)*p->nCol*2;
- memset(p->tblhdr.aBuf, 0, iPK);
- memcpy(&p->tblhdr.aBuf[iPK], &p->in.aData[p->in.iNext], nCopy);
- p->in.iNext += nCopy;
- }
-
- p->apValue = (sqlite3_value**)p->tblhdr.aBuf;
- p->abPK = (u8*)&p->apValue[p->nCol*2];
- p->zTab = (char*)&p->abPK[p->nCol];
- return (p->rc = rc);
-}
-
-/*
-** Advance the changeset iterator to the next change.
-**
-** If both paRec and pnRec are NULL, then this function works like the public
-** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the
-** sqlite3changeset_new() and old() APIs may be used to query for values.
-**
-** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
-** record is written to *paRec before returning and the number of bytes in
-** the record to *pnRec.
-**
-** Either way, this function returns SQLITE_ROW if the iterator is
-** successfully advanced to the next change in the changeset, an SQLite
-** error code if an error occurs, or SQLITE_DONE if there are no further
-** changes in the changeset.
-*/
-static int sessionChangesetNext(
- sqlite3_changeset_iter *p, /* Changeset iterator */
- u8 **paRec, /* If non-NULL, store record pointer here */
- int *pnRec, /* If non-NULL, store size of record here */
- int *pbNew /* If non-NULL, true if new table */
-){
- int i;
- u8 op;
-
- assert( (paRec==0 && pnRec==0) || (paRec && pnRec) );
-
- /* If the iterator is in the error-state, return immediately. */
- if( p->rc!=SQLITE_OK ) return p->rc;
-
- /* Free the current contents of p->apValue[], if any. */
- if( p->apValue ){
- for(i=0; i<p->nCol*2; i++){
- sqlite3ValueFree(p->apValue[i]);
- }
- memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2);
- }
-
- /* Make sure the buffer contains at least 10 bytes of input data, or all
- ** remaining data if there are less than 10 bytes available. This is
- ** sufficient either for the 'T' or 'P' byte and the varint that follows
- ** it, or for the two single byte values otherwise. */
- p->rc = sessionInputBuffer(&p->in, 2);
- if( p->rc!=SQLITE_OK ) return p->rc;
-
- /* If the iterator is already at the end of the changeset, return DONE. */
- if( p->in.iNext>=p->in.nData ){
- return SQLITE_DONE;
- }
-
- sessionDiscardData(&p->in);
- p->in.iCurrent = p->in.iNext;
-
- op = p->in.aData[p->in.iNext++];
- while( op=='T' || op=='P' ){
- if( pbNew ) *pbNew = 1;
- p->bPatchset = (op=='P');
- if( sessionChangesetReadTblhdr(p) ) return p->rc;
- if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc;
- p->in.iCurrent = p->in.iNext;
- if( p->in.iNext>=p->in.nData ) return SQLITE_DONE;
- op = p->in.aData[p->in.iNext++];
- }
-
- if( p->zTab==0 ){
- /* The first record in the changeset is not a table header. Must be a
- ** corrupt changeset. */
- assert( p->in.iNext==1 );
- return (p->rc = SQLITE_CORRUPT_BKPT);
- }
-
- p->op = op;
- p->bIndirect = p->in.aData[p->in.iNext++];
- if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){
- return (p->rc = SQLITE_CORRUPT_BKPT);
- }
-
- if( paRec ){
- int nVal; /* Number of values to buffer */
- if( p->bPatchset==0 && op==SQLITE_UPDATE ){
- nVal = p->nCol * 2;
- }else if( p->bPatchset && op==SQLITE_DELETE ){
- nVal = 0;
- for(i=0; i<p->nCol; i++) if( p->abPK[i] ) nVal++;
- }else{
- nVal = p->nCol;
- }
- p->rc = sessionChangesetBufferRecord(&p->in, nVal, pnRec);
- if( p->rc!=SQLITE_OK ) return p->rc;
- *paRec = &p->in.aData[p->in.iNext];
- p->in.iNext += *pnRec;
- }else{
-
- /* If this is an UPDATE or DELETE, read the old.* record. */
- if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){
- u8 *abPK = p->bPatchset ? p->abPK : 0;
- p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue);
- if( p->rc!=SQLITE_OK ) return p->rc;
- }
-
- /* If this is an INSERT or UPDATE, read the new.* record. */
- if( p->op!=SQLITE_DELETE ){
- p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]);
- if( p->rc!=SQLITE_OK ) return p->rc;
- }
-
- if( p->bPatchset && p->op==SQLITE_UPDATE ){
- /* If this is an UPDATE that is part of a patchset, then all PK and
- ** modified fields are present in the new.* record. The old.* record
- ** is currently completely empty. This block shifts the PK fields from
- ** new.* to old.*, to accommodate the code that reads these arrays. */
- for(i=0; i<p->nCol; i++){
- assert( p->apValue[i]==0 );
- if( p->abPK[i] ){
- p->apValue[i] = p->apValue[i+p->nCol];
- if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT);
- p->apValue[i+p->nCol] = 0;
- }
- }
- }
- }
-
- return SQLITE_ROW;
-}
-
-/*
-** Advance an iterator created by sqlite3changeset_start() to the next
-** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE
-** or SQLITE_CORRUPT.
-**
-** This function may not be called on iterators passed to a conflict handler
-** callback by changeset_apply().
-*/
-int sqlite3changeset_next(sqlite3_changeset_iter *p){
- return sessionChangesetNext(p, 0, 0, 0);
-}
-
-/*
-** The following function extracts information on the current change
-** from a changeset iterator. It may only be called after changeset_next()
-** has returned SQLITE_ROW.
-*/
-int sqlite3changeset_op(
- sqlite3_changeset_iter *pIter, /* Iterator handle */
- const char **pzTab, /* OUT: Pointer to table name */
- int *pnCol, /* OUT: Number of columns in table */
- int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */
- int *pbIndirect /* OUT: True if change is indirect */
-){
- *pOp = pIter->op;
- *pnCol = pIter->nCol;
- *pzTab = pIter->zTab;
- if( pbIndirect ) *pbIndirect = pIter->bIndirect;
- return SQLITE_OK;
-}
-
-/*
-** Return information regarding the PRIMARY KEY and number of columns in
-** the database table affected by the change that pIter currently points
-** to. This function may only be called after changeset_next() returns
-** SQLITE_ROW.
-*/
-int sqlite3changeset_pk(
- sqlite3_changeset_iter *pIter, /* Iterator object */
- unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */
- int *pnCol /* OUT: Number of entries in output array */
-){
- *pabPK = pIter->abPK;
- if( pnCol ) *pnCol = pIter->nCol;
- return SQLITE_OK;
-}
-
-/*
-** This function may only be called while the iterator is pointing to an
-** SQLITE_UPDATE or SQLITE_DELETE change (see sqlite3changeset_op()).
-** Otherwise, SQLITE_MISUSE is returned.
-**
-** It sets *ppValue to point to an sqlite3_value structure containing the
-** iVal'th value in the old.* record. Or, if that particular value is not
-** included in the record (because the change is an UPDATE and the field
-** was not modified and is not a PK column), set *ppValue to NULL.
-**
-** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is
-** not modified. Otherwise, SQLITE_OK.
-*/
-int sqlite3changeset_old(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int iVal, /* Index of old.* value to retrieve */
- sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */
-){
- if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_DELETE ){
- return SQLITE_MISUSE;
- }
- if( iVal<0 || iVal>=pIter->nCol ){
- return SQLITE_RANGE;
- }
- *ppValue = pIter->apValue[iVal];
- return SQLITE_OK;
-}
-
-/*
-** This function may only be called while the iterator is pointing to an
-** SQLITE_UPDATE or SQLITE_INSERT change (see sqlite3changeset_op()).
-** Otherwise, SQLITE_MISUSE is returned.
-**
-** It sets *ppValue to point to an sqlite3_value structure containing the
-** iVal'th value in the new.* record. Or, if that particular value is not
-** included in the record (because the change is an UPDATE and the field
-** was not modified), set *ppValue to NULL.
-**
-** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is
-** not modified. Otherwise, SQLITE_OK.
-*/
-int sqlite3changeset_new(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int iVal, /* Index of new.* value to retrieve */
- sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */
-){
- if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_INSERT ){
- return SQLITE_MISUSE;
- }
- if( iVal<0 || iVal>=pIter->nCol ){
- return SQLITE_RANGE;
- }
- *ppValue = pIter->apValue[pIter->nCol+iVal];
- return SQLITE_OK;
-}
-
-/*
-** The following two macros are used internally. They are similar to the
-** sqlite3changeset_new() and sqlite3changeset_old() functions, except that
-** they omit all error checking and return a pointer to the requested value.
-*/
-#define sessionChangesetNew(pIter, iVal) (pIter)->apValue[(pIter)->nCol+(iVal)]
-#define sessionChangesetOld(pIter, iVal) (pIter)->apValue[(iVal)]
-
-/*
-** This function may only be called with a changeset iterator that has been
-** passed to an SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT
-** conflict-handler function. Otherwise, SQLITE_MISUSE is returned.
-**
-** If successful, *ppValue is set to point to an sqlite3_value structure
-** containing the iVal'th value of the conflicting record.
-**
-** If value iVal is out-of-range or some other error occurs, an SQLite error
-** code is returned. Otherwise, SQLITE_OK.
-*/
-int sqlite3changeset_conflict(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int iVal, /* Index of conflict record value to fetch */
- sqlite3_value **ppValue /* OUT: Value from conflicting row */
-){
- if( !pIter->pConflict ){
- return SQLITE_MISUSE;
- }
- if( iVal<0 || iVal>=pIter->nCol ){
- return SQLITE_RANGE;
- }
- *ppValue = sqlite3_column_value(pIter->pConflict, iVal);
- return SQLITE_OK;
-}
-
-/*
-** This function may only be called with an iterator passed to an
-** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case
-** it sets the output variable to the total number of known foreign key
-** violations in the destination database and returns SQLITE_OK.
-**
-** In all other cases this function returns SQLITE_MISUSE.
-*/
-int sqlite3changeset_fk_conflicts(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int *pnOut /* OUT: Number of FK violations */
-){
- if( pIter->pConflict || pIter->apValue ){
- return SQLITE_MISUSE;
- }
- *pnOut = pIter->nCol;
- return SQLITE_OK;
-}
-
-
-/*
-** Finalize an iterator allocated with sqlite3changeset_start().
-**
-** This function may not be called on iterators passed to a conflict handler
-** callback by changeset_apply().
-*/
-int sqlite3changeset_finalize(sqlite3_changeset_iter *p){
- int rc = SQLITE_OK;
- if( p ){
- int i; /* Used to iterate through p->apValue[] */
- rc = p->rc;
- if( p->apValue ){
- for(i=0; i<p->nCol*2; i++) sqlite3ValueFree(p->apValue[i]);
- }
- sqlite3_free(p->tblhdr.aBuf);
- sqlite3_free(p->in.buf.aBuf);
- sqlite3_free(p);
- }
- return rc;
-}
-
-static int sessionChangesetInvert(
- SessionInput *pInput, /* Input changeset */
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut,
- int *pnInverted, /* OUT: Number of bytes in output changeset */
- void **ppInverted /* OUT: Inverse of pChangeset */
-){
- int rc = SQLITE_OK; /* Return value */
- SessionBuffer sOut; /* Output buffer */
- int nCol = 0; /* Number of cols in current table */
- u8 *abPK = 0; /* PK array for current table */
- sqlite3_value **apVal = 0; /* Space for values for UPDATE inversion */
- SessionBuffer sPK = {0, 0, 0}; /* PK array for current table */
-
- /* Initialize the output buffer */
- memset(&sOut, 0, sizeof(SessionBuffer));
-
- /* Zero the output variables in case an error occurs. */
- if( ppInverted ){
- *ppInverted = 0;
- *pnInverted = 0;
- }
-
- while( 1 ){
- u8 eType;
-
- /* Test for EOF. */
- if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert;
- if( pInput->iNext>=pInput->nData ) break;
- eType = pInput->aData[pInput->iNext];
-
- switch( eType ){
- case 'T': {
- /* A 'table' record consists of:
- **
- ** * A constant 'T' character,
- ** * Number of columns in said table (a varint),
- ** * An array of nCol bytes (sPK),
- ** * A nul-terminated table name.
- */
- int nByte;
- int nVar;
- pInput->iNext++;
- if( (rc = sessionChangesetBufferTblhdr(pInput, &nByte)) ){
- goto finished_invert;
- }
- nVar = sessionVarintGet(&pInput->aData[pInput->iNext], &nCol);
- sPK.nBuf = 0;
- sessionAppendBlob(&sPK, &pInput->aData[pInput->iNext+nVar], nCol, &rc);
- sessionAppendByte(&sOut, eType, &rc);
- sessionAppendBlob(&sOut, &pInput->aData[pInput->iNext], nByte, &rc);
- if( rc ) goto finished_invert;
-
- pInput->iNext += nByte;
- sqlite3_free(apVal);
- apVal = 0;
- abPK = sPK.aBuf;
- break;
- }
-
- case SQLITE_INSERT:
- case SQLITE_DELETE: {
- int nByte;
- int bIndirect = pInput->aData[pInput->iNext+1];
- int eType2 = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE);
- pInput->iNext += 2;
- assert( rc==SQLITE_OK );
- rc = sessionChangesetBufferRecord(pInput, nCol, &nByte);
- sessionAppendByte(&sOut, eType2, &rc);
- sessionAppendByte(&sOut, bIndirect, &rc);
- sessionAppendBlob(&sOut, &pInput->aData[pInput->iNext], nByte, &rc);
- pInput->iNext += nByte;
- if( rc ) goto finished_invert;
- break;
- }
-
- case SQLITE_UPDATE: {
- int iCol;
-
- if( 0==apVal ){
- apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2);
- if( 0==apVal ){
- rc = SQLITE_NOMEM;
- goto finished_invert;
- }
- memset(apVal, 0, sizeof(apVal[0])*nCol*2);
- }
-
- /* Write the header for the new UPDATE change. Same as the original. */
- sessionAppendByte(&sOut, eType, &rc);
- sessionAppendByte(&sOut, pInput->aData[pInput->iNext+1], &rc);
-
- /* Read the old.* and new.* records for the update change. */
- pInput->iNext += 2;
- rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]);
- if( rc==SQLITE_OK ){
- rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]);
- }
-
- /* Write the new old.* record. Consists of the PK columns from the
- ** original old.* record, and the other values from the original
- ** new.* record. */
- for(iCol=0; iCol<nCol; iCol++){
- sqlite3_value *pVal = apVal[iCol + (abPK[iCol] ? 0 : nCol)];
- sessionAppendValue(&sOut, pVal, &rc);
- }
-
- /* Write the new new.* record. Consists of a copy of all values
- ** from the original old.* record, except for the PK columns, which
- ** are set to "undefined". */
- for(iCol=0; iCol<nCol; iCol++){
- sqlite3_value *pVal = (abPK[iCol] ? 0 : apVal[iCol]);
- sessionAppendValue(&sOut, pVal, &rc);
- }
-
- for(iCol=0; iCol<nCol*2; iCol++){
- sqlite3ValueFree(apVal[iCol]);
- }
- memset(apVal, 0, sizeof(apVal[0])*nCol*2);
- if( rc!=SQLITE_OK ){
- goto finished_invert;
- }
-
- break;
- }
-
- default:
- rc = SQLITE_CORRUPT_BKPT;
- goto finished_invert;
- }
-
- assert( rc==SQLITE_OK );
- if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
- rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
- sOut.nBuf = 0;
- if( rc!=SQLITE_OK ) goto finished_invert;
- }
- }
-
- assert( rc==SQLITE_OK );
- if( pnInverted ){
- *pnInverted = sOut.nBuf;
- *ppInverted = sOut.aBuf;
- sOut.aBuf = 0;
- }else if( sOut.nBuf>0 ){
- rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
- }
-
- finished_invert:
- sqlite3_free(sOut.aBuf);
- sqlite3_free(apVal);
- sqlite3_free(sPK.aBuf);
- return rc;
-}
-
-
-/*
-** Invert a changeset object.
-*/
-int sqlite3changeset_invert(
- int nChangeset, /* Number of bytes in input */
- const void *pChangeset, /* Input changeset */
- int *pnInverted, /* OUT: Number of bytes in output changeset */
- void **ppInverted /* OUT: Inverse of pChangeset */
-){
- SessionInput sInput;
-
- /* Set up the input stream */
- memset(&sInput, 0, sizeof(SessionInput));
- sInput.nData = nChangeset;
- sInput.aData = (u8*)pChangeset;
-
- return sessionChangesetInvert(&sInput, 0, 0, pnInverted, ppInverted);
-}
-
-/*
-** Streaming version of sqlite3changeset_invert().
-*/
-int sqlite3changeset_invert_strm(
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-){
- SessionInput sInput;
- int rc;
-
- /* Set up the input stream */
- memset(&sInput, 0, sizeof(SessionInput));
- sInput.xInput = xInput;
- sInput.pIn = pIn;
-
- rc = sessionChangesetInvert(&sInput, xOutput, pOut, 0, 0);
- sqlite3_free(sInput.buf.aBuf);
- return rc;
-}
-
-typedef struct SessionApplyCtx SessionApplyCtx;
-struct SessionApplyCtx {
- sqlite3 *db;
- sqlite3_stmt *pDelete; /* DELETE statement */
- sqlite3_stmt *pUpdate; /* UPDATE statement */
- sqlite3_stmt *pInsert; /* INSERT statement */
- sqlite3_stmt *pSelect; /* SELECT statement */
- int nCol; /* Size of azCol[] and abPK[] arrays */
- const char **azCol; /* Array of column names */
- u8 *abPK; /* Boolean array - true if column is in PK */
- int bStat1; /* True if table is sqlite_stat1 */
- int bDeferConstraints; /* True to defer constraints */
- SessionBuffer constraints; /* Deferred constraints are stored here */
- SessionBuffer rebase; /* Rebase information (if any) here */
- int bRebaseStarted; /* If table header is already in rebase */
-};
-
-/*
-** Formulate a statement to DELETE a row from database db. Assuming a table
-** structure like this:
-**
-** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
-**
-** The DELETE statement looks like this:
-**
-** DELETE FROM x WHERE a = :1 AND c = :3 AND (:5 OR b IS :2 AND d IS :4)
-**
-** Variable :5 (nCol+1) is a boolean. It should be set to 0 if we require
-** matching b and d values, or 1 otherwise. The second case comes up if the
-** conflict handler is invoked with NOTFOUND and returns CHANGESET_REPLACE.
-**
-** If successful, SQLITE_OK is returned and SessionApplyCtx.pDelete is left
-** pointing to the prepared version of the SQL statement.
-*/
-static int sessionDeleteRow(
- sqlite3 *db, /* Database handle */
- const char *zTab, /* Table name */
- SessionApplyCtx *p /* Session changeset-apply context */
-){
- int i;
- const char *zSep = "";
- int rc = SQLITE_OK;
- SessionBuffer buf = {0, 0, 0};
- int nPk = 0;
-
- sessionAppendStr(&buf, "DELETE FROM ", &rc);
- sessionAppendIdent(&buf, zTab, &rc);
- sessionAppendStr(&buf, " WHERE ", &rc);
-
- for(i=0; i<p->nCol; i++){
- if( p->abPK[i] ){
- nPk++;
- sessionAppendStr(&buf, zSep, &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = ?", &rc);
- sessionAppendInteger(&buf, i+1, &rc);
- zSep = " AND ";
- }
- }
-
- if( nPk<p->nCol ){
- sessionAppendStr(&buf, " AND (?", &rc);
- sessionAppendInteger(&buf, p->nCol+1, &rc);
- sessionAppendStr(&buf, " OR ", &rc);
-
- zSep = "";
- for(i=0; i<p->nCol; i++){
- if( !p->abPK[i] ){
- sessionAppendStr(&buf, zSep, &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " IS ?", &rc);
- sessionAppendInteger(&buf, i+1, &rc);
- zSep = "AND ";
- }
- }
- sessionAppendStr(&buf, ")", &rc);
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0);
- }
- sqlite3_free(buf.aBuf);
-
- return rc;
-}
-
-/*
-** Formulate and prepare a statement to UPDATE a row from database db.
-** Assuming a table structure like this:
-**
-** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
-**
-** The UPDATE statement looks like this:
-**
-** UPDATE x SET
-** a = CASE WHEN ?2 THEN ?3 ELSE a END,
-** b = CASE WHEN ?5 THEN ?6 ELSE b END,
-** c = CASE WHEN ?8 THEN ?9 ELSE c END,
-** d = CASE WHEN ?11 THEN ?12 ELSE d END
-** WHERE a = ?1 AND c = ?7 AND (?13 OR
-** (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND
-** )
-**
-** For each column in the table, there are three variables to bind:
-**
-** ?(i*3+1) The old.* value of the column, if any.
-** ?(i*3+2) A boolean flag indicating that the value is being modified.
-** ?(i*3+3) The new.* value of the column, if any.
-**
-** Also, a boolean flag that, if set to true, causes the statement to update
-** a row even if the non-PK values do not match. This is required if the
-** conflict-handler is invoked with CHANGESET_DATA and returns
-** CHANGESET_REPLACE. This is variable "?(nCol*3+1)".
-**
-** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left
-** pointing to the prepared version of the SQL statement.
-*/
-static int sessionUpdateRow(
- sqlite3 *db, /* Database handle */
- const char *zTab, /* Table name */
- SessionApplyCtx *p /* Session changeset-apply context */
-){
- int rc = SQLITE_OK;
- int i;
- const char *zSep = "";
- SessionBuffer buf = {0, 0, 0};
-
- /* Append "UPDATE tbl SET " */
- sessionAppendStr(&buf, "UPDATE ", &rc);
- sessionAppendIdent(&buf, zTab, &rc);
- sessionAppendStr(&buf, " SET ", &rc);
-
- /* Append the assignments */
- for(i=0; i<p->nCol; i++){
- sessionAppendStr(&buf, zSep, &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = CASE WHEN ?", &rc);
- sessionAppendInteger(&buf, i*3+2, &rc);
- sessionAppendStr(&buf, " THEN ?", &rc);
- sessionAppendInteger(&buf, i*3+3, &rc);
- sessionAppendStr(&buf, " ELSE ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " END", &rc);
- zSep = ", ";
- }
-
- /* Append the PK part of the WHERE clause */
- sessionAppendStr(&buf, " WHERE ", &rc);
- for(i=0; i<p->nCol; i++){
- if( p->abPK[i] ){
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = ?", &rc);
- sessionAppendInteger(&buf, i*3+1, &rc);
- sessionAppendStr(&buf, " AND ", &rc);
- }
- }
-
- /* Append the non-PK part of the WHERE clause */
- sessionAppendStr(&buf, " (?", &rc);
- sessionAppendInteger(&buf, p->nCol*3+1, &rc);
- sessionAppendStr(&buf, " OR 1", &rc);
- for(i=0; i<p->nCol; i++){
- if( !p->abPK[i] ){
- sessionAppendStr(&buf, " AND (?", &rc);
- sessionAppendInteger(&buf, i*3+2, &rc);
- sessionAppendStr(&buf, "=0 OR ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " IS ?", &rc);
- sessionAppendInteger(&buf, i*3+1, &rc);
- sessionAppendStr(&buf, ")", &rc);
- }
- }
- sessionAppendStr(&buf, ")", &rc);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0);
- }
- sqlite3_free(buf.aBuf);
-
- return rc;
-}
-
-
-/*
-** Formulate and prepare an SQL statement to query table zTab by primary
-** key. Assuming the following table structure:
-**
-** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
-**
-** The SELECT statement looks like this:
-**
-** SELECT * FROM x WHERE a = ?1 AND c = ?3
-**
-** If successful, SQLITE_OK is returned and SessionApplyCtx.pSelect is left
-** pointing to the prepared version of the SQL statement.
-*/
-static int sessionSelectRow(
- sqlite3 *db, /* Database handle */
- const char *zTab, /* Table name */
- SessionApplyCtx *p /* Session changeset-apply context */
-){
- return sessionSelectStmt(
- db, "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect);
-}
-
-/*
-** Formulate and prepare an INSERT statement to add a record to table zTab.
-** For example:
-**
-** INSERT INTO main."zTab" VALUES(?1, ?2, ?3 ...);
-**
-** If successful, SQLITE_OK is returned and SessionApplyCtx.pInsert is left
-** pointing to the prepared version of the SQL statement.
-*/
-static int sessionInsertRow(
- sqlite3 *db, /* Database handle */
- const char *zTab, /* Table name */
- SessionApplyCtx *p /* Session changeset-apply context */
-){
- int rc = SQLITE_OK;
- int i;
- SessionBuffer buf = {0, 0, 0};
-
- sessionAppendStr(&buf, "INSERT INTO main.", &rc);
- sessionAppendIdent(&buf, zTab, &rc);
- sessionAppendStr(&buf, "(", &rc);
- for(i=0; i<p->nCol; i++){
- if( i!=0 ) sessionAppendStr(&buf, ", ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- }
-
- sessionAppendStr(&buf, ") VALUES(?", &rc);
- for(i=1; i<p->nCol; i++){
- sessionAppendStr(&buf, ", ?", &rc);
- }
- sessionAppendStr(&buf, ")", &rc);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pInsert, 0);
- }
- sqlite3_free(buf.aBuf);
- return rc;
-}
-
-static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){
- return sqlite3_prepare_v2(db, zSql, -1, pp, 0);
-}
-
-/*
-** Prepare statements for applying changes to the sqlite_stat1 table.
-** These are similar to those created by sessionSelectRow(),
-** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for
-** other tables.
-*/
-static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){
- int rc = sessionSelectRow(db, "sqlite_stat1", p);
- if( rc==SQLITE_OK ){
- rc = sessionPrepare(db, &p->pInsert,
- "INSERT INTO main.sqlite_stat1 VALUES(?1, "
- "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, "
- "?3)"
- );
- }
- if( rc==SQLITE_OK ){
- rc = sessionPrepare(db, &p->pUpdate,
- "UPDATE main.sqlite_stat1 SET "
- "tbl = CASE WHEN ?2 THEN ?3 ELSE tbl END, "
- "idx = CASE WHEN ?5 THEN ?6 ELSE idx END, "
- "stat = CASE WHEN ?8 THEN ?9 ELSE stat END "
- "WHERE tbl=?1 AND idx IS "
- "CASE WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL ELSE ?4 END "
- "AND (?10 OR ?8=0 OR stat IS ?7)"
- );
- }
- if( rc==SQLITE_OK ){
- rc = sessionPrepare(db, &p->pDelete,
- "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS "
- "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END "
- "AND (?4 OR stat IS ?3)"
- );
- }
- return rc;
-}
-
-/*
-** A wrapper around sqlite3_bind_value() that detects an extra problem.
-** See comments in the body of this function for details.
-*/
-static int sessionBindValue(
- sqlite3_stmt *pStmt, /* Statement to bind value to */
- int i, /* Parameter number to bind to */
- sqlite3_value *pVal /* Value to bind */
-){
- int eType = sqlite3_value_type(pVal);
- /* COVERAGE: The (pVal->z==0) branch is never true using current versions
- ** of SQLite. If a malloc fails in an sqlite3_value_xxx() function, either
- ** the (pVal->z) variable remains as it was or the type of the value is
- ** set to SQLITE_NULL. */
- if( (eType==SQLITE_TEXT || eType==SQLITE_BLOB) && pVal->z==0 ){
- /* This condition occurs when an earlier OOM in a call to
- ** sqlite3_value_text() or sqlite3_value_blob() (perhaps from within
- ** a conflict-handler) has zeroed the pVal->z pointer. Return NOMEM. */
- return SQLITE_NOMEM;
- }
- return sqlite3_bind_value(pStmt, i, pVal);
-}
-
-/*
-** Iterator pIter must point to an SQLITE_INSERT entry. This function
-** transfers new.* values from the current iterator entry to statement
-** pStmt. The table being inserted into has nCol columns.
-**
-** New.* value $i from the iterator is bound to variable ($i+1) of
-** statement pStmt. If parameter abPK is NULL, all values from 0 to (nCol-1)
-** are transfered to the statement. Otherwise, if abPK is not NULL, it points
-** to an array nCol elements in size. In this case only those values for
-** which abPK[$i] is true are read from the iterator and bound to the
-** statement.
-**
-** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK.
-*/
-static int sessionBindRow(
- sqlite3_changeset_iter *pIter, /* Iterator to read values from */
- int(*xValue)(sqlite3_changeset_iter *, int, sqlite3_value **),
- int nCol, /* Number of columns */
- u8 *abPK, /* If not NULL, bind only if true */
- sqlite3_stmt *pStmt /* Bind values to this statement */
-){
- int i;
- int rc = SQLITE_OK;
-
- /* Neither sqlite3changeset_old or sqlite3changeset_new can fail if the
- ** argument iterator points to a suitable entry. Make sure that xValue
- ** is one of these to guarantee that it is safe to ignore the return
- ** in the code below. */
- assert( xValue==sqlite3changeset_old || xValue==sqlite3changeset_new );
-
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- if( !abPK || abPK[i] ){
- sqlite3_value *pVal;
- (void)xValue(pIter, i, &pVal);
- if( pVal==0 ){
- /* The value in the changeset was "undefined". This indicates a
- ** corrupt changeset blob. */
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- rc = sessionBindValue(pStmt, i+1, pVal);
- }
- }
- }
- return rc;
-}
-
-/*
-** SQL statement pSelect is as generated by the sessionSelectRow() function.
-** This function binds the primary key values from the change that changeset
-** iterator pIter points to to the SELECT and attempts to seek to the table
-** entry. If a row is found, the SELECT statement left pointing at the row
-** and SQLITE_ROW is returned. Otherwise, if no row is found and no error
-** has occured, the statement is reset and SQLITE_OK is returned. If an
-** error occurs, the statement is reset and an SQLite error code is returned.
-**
-** If this function returns SQLITE_ROW, the caller must eventually reset()
-** statement pSelect. If any other value is returned, the statement does
-** not require a reset().
-**
-** If the iterator currently points to an INSERT record, bind values from the
-** new.* record to the SELECT statement. Or, if it points to a DELETE or
-** UPDATE, bind values from the old.* record.
-*/
-static int sessionSeekToRow(
- sqlite3 *db, /* Database handle */
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- u8 *abPK, /* Primary key flags array */
- sqlite3_stmt *pSelect /* SELECT statement from sessionSelectRow() */
-){
- int rc; /* Return code */
- int nCol; /* Number of columns in table */
- int op; /* Changset operation (SQLITE_UPDATE etc.) */
- const char *zDummy; /* Unused */
-
- sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0);
- rc = sessionBindRow(pIter,
- op==SQLITE_INSERT ? sqlite3changeset_new : sqlite3changeset_old,
- nCol, abPK, pSelect
- );
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_step(pSelect);
- if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect);
- }
-
- return rc;
-}
-
-/*
-** This function is called from within sqlite3changset_apply_v2() when
-** a conflict is encountered and resolved using conflict resolution
-** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE)..
-** It adds a conflict resolution record to the buffer in
-** SessionApplyCtx.rebase, which will eventually be returned to the caller
-** of apply_v2() as the "rebase" buffer.
-**
-** Return SQLITE_OK if successful, or an SQLite error code otherwise.
-*/
-static int sessionRebaseAdd(
- SessionApplyCtx *p, /* Apply context */
- int eType, /* Conflict resolution (OMIT or REPLACE) */
- sqlite3_changeset_iter *pIter /* Iterator pointing at current change */
-){
- int rc = SQLITE_OK;
- int i;
- int eOp = pIter->op;
- if( p->bRebaseStarted==0 ){
- /* Append a table-header to the rebase buffer */
- const char *zTab = pIter->zTab;
- sessionAppendByte(&p->rebase, 'T', &rc);
- sessionAppendVarint(&p->rebase, p->nCol, &rc);
- sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc);
- sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc);
- p->bRebaseStarted = 1;
- }
-
- assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT );
- assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE );
-
- sessionAppendByte(&p->rebase,
- (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc
- );
- sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc);
- for(i=0; i<p->nCol; i++){
- sqlite3_value *pVal = 0;
- if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){
- sqlite3changeset_old(pIter, i, &pVal);
- }else{
- sqlite3changeset_new(pIter, i, &pVal);
- }
- sessionAppendValue(&p->rebase, pVal, &rc);
- }
-
- return rc;
-}
-
-/*
-** Invoke the conflict handler for the change that the changeset iterator
-** currently points to.
-**
-** Argument eType must be either CHANGESET_DATA or CHANGESET_CONFLICT.
-** If argument pbReplace is NULL, then the type of conflict handler invoked
-** depends solely on eType, as follows:
-**
-** eType value Value passed to xConflict
-** -------------------------------------------------
-** CHANGESET_DATA CHANGESET_NOTFOUND
-** CHANGESET_CONFLICT CHANGESET_CONSTRAINT
-**
-** Or, if pbReplace is not NULL, then an attempt is made to find an existing
-** record with the same primary key as the record about to be deleted, updated
-** or inserted. If such a record can be found, it is available to the conflict
-** handler as the "conflicting" record. In this case the type of conflict
-** handler invoked is as follows:
-**
-** eType value PK Record found? Value passed to xConflict
-** ----------------------------------------------------------------
-** CHANGESET_DATA Yes CHANGESET_DATA
-** CHANGESET_DATA No CHANGESET_NOTFOUND
-** CHANGESET_CONFLICT Yes CHANGESET_CONFLICT
-** CHANGESET_CONFLICT No CHANGESET_CONSTRAINT
-**
-** If pbReplace is not NULL, and a record with a matching PK is found, and
-** the conflict handler function returns SQLITE_CHANGESET_REPLACE, *pbReplace
-** is set to non-zero before returning SQLITE_OK.
-**
-** If the conflict handler returns SQLITE_CHANGESET_ABORT, SQLITE_ABORT is
-** returned. Or, if the conflict handler returns an invalid value,
-** SQLITE_MISUSE. If the conflict handler returns SQLITE_CHANGESET_OMIT,
-** this function returns SQLITE_OK.
-*/
-static int sessionConflictHandler(
- int eType, /* Either CHANGESET_DATA or CONFLICT */
- SessionApplyCtx *p, /* changeset_apply() context */
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int(*xConflict)(void *, int, sqlite3_changeset_iter*),
- void *pCtx, /* First argument for conflict handler */
- int *pbReplace /* OUT: Set to true if PK row is found */
-){
- int res = 0; /* Value returned by conflict handler */
- int rc;
- int nCol;
- int op;
- const char *zDummy;
-
- sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0);
-
- assert( eType==SQLITE_CHANGESET_CONFLICT || eType==SQLITE_CHANGESET_DATA );
- assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT );
- assert( SQLITE_CHANGESET_DATA+1==SQLITE_CHANGESET_NOTFOUND );
-
- /* Bind the new.* PRIMARY KEY values to the SELECT statement. */
- if( pbReplace ){
- rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect);
- }else{
- rc = SQLITE_OK;
- }
-
- if( rc==SQLITE_ROW ){
- /* There exists another row with the new.* primary key. */
- pIter->pConflict = p->pSelect;
- res = xConflict(pCtx, eType, pIter);
- pIter->pConflict = 0;
- rc = sqlite3_reset(p->pSelect);
- }else if( rc==SQLITE_OK ){
- if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){
- /* Instead of invoking the conflict handler, append the change blob
- ** to the SessionApplyCtx.constraints buffer. */
- u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
- int nBlob = pIter->in.iNext - pIter->in.iCurrent;
- sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
- return SQLITE_OK;
- }else{
- /* No other row with the new.* primary key. */
- res = xConflict(pCtx, eType+1, pIter);
- if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE;
- }
- }
-
- if( rc==SQLITE_OK ){
- switch( res ){
- case SQLITE_CHANGESET_REPLACE:
- assert( pbReplace );
- *pbReplace = 1;
- break;
-
- case SQLITE_CHANGESET_OMIT:
- break;
-
- case SQLITE_CHANGESET_ABORT:
- rc = SQLITE_ABORT;
- break;
-
- default:
- rc = SQLITE_MISUSE;
- break;
- }
- if( rc==SQLITE_OK ){
- rc = sessionRebaseAdd(p, res, pIter);
- }
- }
-
- return rc;
-}
-
-/*
-** Attempt to apply the change that the iterator passed as the first argument
-** currently points to to the database. If a conflict is encountered, invoke
-** the conflict handler callback.
-**
-** If argument pbRetry is NULL, then ignore any CHANGESET_DATA conflict. If
-** one is encountered, update or delete the row with the matching primary key
-** instead. Or, if pbRetry is not NULL and a CHANGESET_DATA conflict occurs,
-** invoke the conflict handler. If it returns CHANGESET_REPLACE, set *pbRetry
-** to true before returning. In this case the caller will invoke this function
-** again, this time with pbRetry set to NULL.
-**
-** If argument pbReplace is NULL and a CHANGESET_CONFLICT conflict is
-** encountered invoke the conflict handler with CHANGESET_CONSTRAINT instead.
-** Or, if pbReplace is not NULL, invoke it with CHANGESET_CONFLICT. If such
-** an invocation returns SQLITE_CHANGESET_REPLACE, set *pbReplace to true
-** before retrying. In this case the caller attempts to remove the conflicting
-** row before invoking this function again, this time with pbReplace set
-** to NULL.
-**
-** If any conflict handler returns SQLITE_CHANGESET_ABORT, this function
-** returns SQLITE_ABORT. Otherwise, if no error occurs, SQLITE_OK is
-** returned.
-*/
-static int sessionApplyOneOp(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- SessionApplyCtx *p, /* changeset_apply() context */
- int(*xConflict)(void *, int, sqlite3_changeset_iter *),
- void *pCtx, /* First argument for the conflict handler */
- int *pbReplace, /* OUT: True to remove PK row and retry */
- int *pbRetry /* OUT: True to retry. */
-){
- const char *zDummy;
- int op;
- int nCol;
- int rc = SQLITE_OK;
-
- assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect );
- assert( p->azCol && p->abPK );
- assert( !pbReplace || *pbReplace==0 );
-
- sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0);
-
- if( op==SQLITE_DELETE ){
-
- /* Bind values to the DELETE statement. If conflict handling is required,
- ** bind values for all columns and set bound variable (nCol+1) to true.
- ** Or, if conflict handling is not required, bind just the PK column
- ** values and, if it exists, set (nCol+1) to false. Conflict handling
- ** is not required if:
- **
- ** * this is a patchset, or
- ** * (pbRetry==0), or
- ** * all columns of the table are PK columns (in this case there is
- ** no (nCol+1) variable to bind to).
- */
- u8 *abPK = (pIter->bPatchset ? p->abPK : 0);
- rc = sessionBindRow(pIter, sqlite3changeset_old, nCol, abPK, p->pDelete);
- if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){
- rc = sqlite3_bind_int(p->pDelete, nCol+1, (pbRetry==0 || abPK));
- }
- if( rc!=SQLITE_OK ) return rc;
-
- sqlite3_step(p->pDelete);
- rc = sqlite3_reset(p->pDelete);
- if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){
- rc = sessionConflictHandler(
- SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry
- );
- }else if( (rc&0xff)==SQLITE_CONSTRAINT ){
- rc = sessionConflictHandler(
- SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0
- );
- }
-
- }else if( op==SQLITE_UPDATE ){
- int i;
-
- /* Bind values to the UPDATE statement. */
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- sqlite3_value *pOld = sessionChangesetOld(pIter, i);
- sqlite3_value *pNew = sessionChangesetNew(pIter, i);
-
- sqlite3_bind_int(p->pUpdate, i*3+2, !!pNew);
- if( pOld ){
- rc = sessionBindValue(p->pUpdate, i*3+1, pOld);
- }
- if( rc==SQLITE_OK && pNew ){
- rc = sessionBindValue(p->pUpdate, i*3+3, pNew);
- }
- }
- if( rc==SQLITE_OK ){
- sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset);
- }
- if( rc!=SQLITE_OK ) return rc;
-
- /* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict,
- ** the result will be SQLITE_OK with 0 rows modified. */
- sqlite3_step(p->pUpdate);
- rc = sqlite3_reset(p->pUpdate);
-
- if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){
- /* A NOTFOUND or DATA error. Search the table to see if it contains
- ** a row with a matching primary key. If so, this is a DATA conflict.
- ** Otherwise, if there is no primary key match, it is a NOTFOUND. */
-
- rc = sessionConflictHandler(
- SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry
- );
-
- }else if( (rc&0xff)==SQLITE_CONSTRAINT ){
- /* This is always a CONSTRAINT conflict. */
- rc = sessionConflictHandler(
- SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0
- );
- }
-
- }else{
- assert( op==SQLITE_INSERT );
- if( p->bStat1 ){
- /* Check if there is a conflicting row. For sqlite_stat1, this needs
- ** to be done using a SELECT, as there is no PRIMARY KEY in the
- ** database schema to throw an exception if a duplicate is inserted. */
- rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect);
- if( rc==SQLITE_ROW ){
- rc = SQLITE_CONSTRAINT;
- sqlite3_reset(p->pSelect);
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert);
- if( rc!=SQLITE_OK ) return rc;
-
- sqlite3_step(p->pInsert);
- rc = sqlite3_reset(p->pInsert);
- }
-
- if( (rc&0xff)==SQLITE_CONSTRAINT ){
- rc = sessionConflictHandler(
- SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace
- );
- }
- }
-
- return rc;
-}
-
-/*
-** Attempt to apply the change that the iterator passed as the first argument
-** currently points to to the database. If a conflict is encountered, invoke
-** the conflict handler callback.
-**
-** The difference between this function and sessionApplyOne() is that this
-** function handles the case where the conflict-handler is invoked and
-** returns SQLITE_CHANGESET_REPLACE - indicating that the change should be
-** retried in some manner.
-*/
-static int sessionApplyOneWithRetry(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- sqlite3_changeset_iter *pIter, /* Changeset iterator to read change from */
- SessionApplyCtx *pApply, /* Apply context */
- int(*xConflict)(void*, int, sqlite3_changeset_iter*),
- void *pCtx /* First argument passed to xConflict */
-){
- int bReplace = 0;
- int bRetry = 0;
- int rc;
-
- rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry);
- if( rc==SQLITE_OK ){
- /* If the bRetry flag is set, the change has not been applied due to an
- ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and
- ** a row with the correct PK is present in the db, but one or more other
- ** fields do not contain the expected values) and the conflict handler
- ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation,
- ** but pass NULL as the final argument so that sessionApplyOneOp() ignores
- ** the SQLITE_CHANGESET_DATA problem. */
- if( bRetry ){
- assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE );
- rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0);
- }
-
- /* If the bReplace flag is set, the change is an INSERT that has not
- ** been performed because the database already contains a row with the
- ** specified primary key and the conflict handler returned
- ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row
- ** before reattempting the INSERT. */
- else if( bReplace ){
- assert( pIter->op==SQLITE_INSERT );
- rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sessionBindRow(pIter,
- sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete);
- sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
- }
- if( rc==SQLITE_OK ){
- sqlite3_step(pApply->pDelete);
- rc = sqlite3_reset(pApply->pDelete);
- }
- if( rc==SQLITE_OK ){
- rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Retry the changes accumulated in the pApply->constraints buffer.
-*/
-static int sessionRetryConstraints(
- sqlite3 *db,
- int bPatchset,
- const char *zTab,
- SessionApplyCtx *pApply,
- int(*xConflict)(void*, int, sqlite3_changeset_iter*),
- void *pCtx /* First argument passed to xConflict */
-){
- int rc = SQLITE_OK;
-
- while( pApply->constraints.nBuf ){
- sqlite3_changeset_iter *pIter2 = 0;
- SessionBuffer cons = pApply->constraints;
- memset(&pApply->constraints, 0, sizeof(SessionBuffer));
-
- rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf);
- if( rc==SQLITE_OK ){
- int nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
- int rc2;
- pIter2->bPatchset = bPatchset;
- pIter2->zTab = (char*)zTab;
- pIter2->nCol = pApply->nCol;
- pIter2->abPK = pApply->abPK;
- sessionBufferGrow(&pIter2->tblhdr, nByte, &rc);
- pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf;
- if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte);
-
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){
- rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx);
- }
-
- rc2 = sqlite3changeset_finalize(pIter2);
- if( rc==SQLITE_OK ) rc = rc2;
- }
- assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
-
- sqlite3_free(cons.aBuf);
- if( rc!=SQLITE_OK ) break;
- if( pApply->constraints.nBuf>=cons.nBuf ){
- /* No progress was made on the last round. */
- pApply->bDeferConstraints = 0;
- }
- }
-
- return rc;
-}
-
-/*
-** Argument pIter is a changeset iterator that has been initialized, but
-** not yet passed to sqlite3changeset_next(). This function applies the
-** changeset to the main database attached to handle "db". The supplied
-** conflict handler callback is invoked to resolve any conflicts encountered
-** while applying the change.
-*/
-static int sessionChangesetApply(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- sqlite3_changeset_iter *pIter, /* Changeset to apply */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of fifth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx, /* First argument passed to xConflict */
- void **ppRebase, int *pnRebase, /* OUT: Rebase information */
- int flags /* SESSION_APPLY_XXX flags */
-){
- int schemaMismatch = 0;
- int rc = SQLITE_OK; /* Return code */
- const char *zTab = 0; /* Name of current table */
- int nTab = 0; /* Result of sqlite3Strlen30(zTab) */
- SessionApplyCtx sApply; /* changeset_apply() context object */
- int bPatchset;
-
- assert( xConflict!=0 );
-
- pIter->in.bNoDiscard = 1;
- memset(&sApply, 0, sizeof(sApply));
- sqlite3_mutex_enter(sqlite3_db_mutex(db));
- if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
- rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0);
- }
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){
- int nCol;
- int op;
- const char *zNew;
-
- sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0);
-
- if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){
- u8 *abPK;
-
- rc = sessionRetryConstraints(
- db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx
- );
- if( rc!=SQLITE_OK ) break;
-
- sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
- sqlite3_finalize(sApply.pDelete);
- sqlite3_finalize(sApply.pUpdate);
- sqlite3_finalize(sApply.pInsert);
- sqlite3_finalize(sApply.pSelect);
- sApply.db = db;
- sApply.pDelete = 0;
- sApply.pUpdate = 0;
- sApply.pInsert = 0;
- sApply.pSelect = 0;
- sApply.nCol = 0;
- sApply.azCol = 0;
- sApply.abPK = 0;
- sApply.bStat1 = 0;
- sApply.bDeferConstraints = 1;
- sApply.bRebaseStarted = 0;
- memset(&sApply.constraints, 0, sizeof(SessionBuffer));
-
- /* If an xFilter() callback was specified, invoke it now. If the
- ** xFilter callback returns zero, skip this table. If it returns
- ** non-zero, proceed. */
- schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew)));
- if( schemaMismatch ){
- zTab = sqlite3_mprintf("%s", zNew);
- if( zTab==0 ){
- rc = SQLITE_NOMEM;
- break;
- }
- nTab = (int)strlen(zTab);
- sApply.azCol = (const char **)zTab;
- }else{
- int nMinCol = 0;
- int i;
-
- sqlite3changeset_pk(pIter, &abPK, 0);
- rc = sessionTableInfo(
- db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
- );
- if( rc!=SQLITE_OK ) break;
- for(i=0; i<sApply.nCol; i++){
- if( sApply.abPK[i] ) nMinCol = i+1;
- }
-
- if( sApply.nCol==0 ){
- schemaMismatch = 1;
- sqlite3_log(SQLITE_SCHEMA,
- "sqlite3changeset_apply(): no such table: %s", zTab
- );
- }
- else if( sApply.nCol<nCol ){
- schemaMismatch = 1;
- sqlite3_log(SQLITE_SCHEMA,
- "sqlite3changeset_apply(): table %s has %d columns, "
- "expected %d or more",
- zTab, sApply.nCol, nCol
- );
- }
- else if( nCol<nMinCol || memcmp(sApply.abPK, abPK, nCol)!=0 ){
- schemaMismatch = 1;
- sqlite3_log(SQLITE_SCHEMA, "sqlite3changeset_apply(): "
- "primary key mismatch for table %s", zTab
- );
- }
- else{
- sApply.nCol = nCol;
- if( 0==sqlite3_stricmp(zTab, "sqlite_stat1") ){
- if( (rc = sessionStat1Sql(db, &sApply) ) ){
- break;
- }
- sApply.bStat1 = 1;
- }else{
- if((rc = sessionSelectRow(db, zTab, &sApply))
- || (rc = sessionUpdateRow(db, zTab, &sApply))
- || (rc = sessionDeleteRow(db, zTab, &sApply))
- || (rc = sessionInsertRow(db, zTab, &sApply))
- ){
- break;
- }
- sApply.bStat1 = 0;
- }
- }
- nTab = sqlite3Strlen30(zTab);
- }
- }
-
- /* If there is a schema mismatch on the current table, proceed to the
- ** next change. A log message has already been issued. */
- if( schemaMismatch ) continue;
-
- rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx);
- }
-
- bPatchset = pIter->bPatchset;
- if( rc==SQLITE_OK ){
- rc = sqlite3changeset_finalize(pIter);
- }else{
- sqlite3changeset_finalize(pIter);
- }
-
- if( rc==SQLITE_OK ){
- rc = sessionRetryConstraints(db, bPatchset, zTab, &sApply, xConflict, pCtx);
- }
-
- if( rc==SQLITE_OK ){
- int nFk, notUsed;
- sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, &nFk, &notUsed, 0);
- if( nFk!=0 ){
- int res = SQLITE_CHANGESET_ABORT;
- sqlite3_changeset_iter sIter;
- memset(&sIter, 0, sizeof(sIter));
- sIter.nCol = nFk;
- res = xConflict(pCtx, SQLITE_CHANGESET_FOREIGN_KEY, &sIter);
- if( res!=SQLITE_CHANGESET_OMIT ){
- rc = SQLITE_CONSTRAINT;
- }
- }
- }
- sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);
-
- if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
- }else{
- sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
- sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
- }
- }
-
- if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){
- *ppRebase = (void*)sApply.rebase.aBuf;
- *pnRebase = sApply.rebase.nBuf;
- sApply.rebase.aBuf = 0;
- }
- sqlite3_finalize(sApply.pInsert);
- sqlite3_finalize(sApply.pDelete);
- sqlite3_finalize(sApply.pUpdate);
- sqlite3_finalize(sApply.pSelect);
- sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
- sqlite3_free((char*)sApply.constraints.aBuf);
- sqlite3_free((char*)sApply.rebase.aBuf);
- sqlite3_mutex_leave(sqlite3_db_mutex(db));
- return rc;
-}
-
-/*
-** Apply the changeset passed via pChangeset/nChangeset to the main
-** database attached to handle "db".
-*/
-int sqlite3changeset_apply_v2(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- int nChangeset, /* Size of changeset in bytes */
- void *pChangeset, /* Changeset blob */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx, /* First argument passed to xConflict */
- void **ppRebase, int *pnRebase,
- int flags
-){
- sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
- if( rc==SQLITE_OK ){
- rc = sessionChangesetApply(
- db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
- );
- }
- return rc;
-}
-
-/*
-** Apply the changeset passed via pChangeset/nChangeset to the main database
-** attached to handle "db". Invoke the supplied conflict handler callback
-** to resolve any conflicts encountered while applying the change.
-*/
-int sqlite3changeset_apply(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- int nChangeset, /* Size of changeset in bytes */
- void *pChangeset, /* Changeset blob */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of fifth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx /* First argument passed to xConflict */
-){
- return sqlite3changeset_apply_v2(
- db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0
- );
-}
-
-/*
-** Apply the changeset passed via xInput/pIn to the main database
-** attached to handle "db". Invoke the supplied conflict handler callback
-** to resolve any conflicts encountered while applying the change.
-*/
-int sqlite3changeset_apply_v2_strm(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
- void *pIn, /* First arg for xInput */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx, /* First argument passed to xConflict */
- void **ppRebase, int *pnRebase,
- int flags
-){
- sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn);
- if( rc==SQLITE_OK ){
- rc = sessionChangesetApply(
- db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
- );
- }
- return rc;
-}
-int sqlite3changeset_apply_strm(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
- void *pIn, /* First arg for xInput */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx /* First argument passed to xConflict */
-){
- return sqlite3changeset_apply_v2_strm(
- db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0, 0
- );
-}
-
-/*
-** sqlite3_changegroup handle.
-*/
-struct sqlite3_changegroup {
- int rc; /* Error code */
- int bPatch; /* True to accumulate patchsets */
- SessionTable *pList; /* List of tables in current patch */
-};
-
-/*
-** This function is called to merge two changes to the same row together as
-** part of an sqlite3changeset_concat() operation. A new change object is
-** allocated and a pointer to it stored in *ppNew.
-*/
-static int sessionChangeMerge(
- SessionTable *pTab, /* Table structure */
- int bRebase, /* True for a rebase hash-table */
- int bPatchset, /* True for patchsets */
- SessionChange *pExist, /* Existing change */
- int op2, /* Second change operation */
- int bIndirect, /* True if second change is indirect */
- u8 *aRec, /* Second change record */
- int nRec, /* Number of bytes in aRec */
- SessionChange **ppNew /* OUT: Merged change */
-){
- SessionChange *pNew = 0;
- int rc = SQLITE_OK;
-
- if( !pExist ){
- pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec);
- if( !pNew ){
- return SQLITE_NOMEM;
- }
- memset(pNew, 0, sizeof(SessionChange));
- pNew->op = op2;
- pNew->bIndirect = bIndirect;
- pNew->aRecord = (u8*)&pNew[1];
- if( bIndirect==0 || bRebase==0 ){
- pNew->nRecord = nRec;
- memcpy(pNew->aRecord, aRec, nRec);
- }else{
- int i;
- u8 *pIn = aRec;
- u8 *pOut = pNew->aRecord;
- for(i=0; i<pTab->nCol; i++){
- int nIn = sessionSerialLen(pIn);
- if( *pIn==0 ){
- *pOut++ = 0;
- }else if( pTab->abPK[i]==0 ){
- *pOut++ = 0xFF;
- }else{
- memcpy(pOut, pIn, nIn);
- pOut += nIn;
- }
- pIn += nIn;
- }
- pNew->nRecord = pOut - pNew->aRecord;
- }
- }else if( bRebase ){
- if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){
- *ppNew = pExist;
- }else{
- int nByte = nRec + pExist->nRecord + sizeof(SessionChange);
- pNew = (SessionChange*)sqlite3_malloc(nByte);
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int i;
- u8 *a1 = pExist->aRecord;
- u8 *a2 = aRec;
- u8 *pOut;
-
- memset(pNew, 0, nByte);
- pNew->bIndirect = bIndirect || pExist->bIndirect;
- pNew->op = op2;
- pOut = pNew->aRecord = (u8*)&pNew[1];
-
- for(i=0; i<pTab->nCol; i++){
- int n1 = sessionSerialLen(a1);
- int n2 = sessionSerialLen(a2);
- if( *a1==0xFF || (pTab->abPK[i]==0 && bIndirect) ){
- *pOut++ = 0xFF;
- }else if( *a2==0 ){
- memcpy(pOut, a1, n1);
- pOut += n1;
- }else{
- memcpy(pOut, a2, n2);
- pOut += n2;
- }
- a1 += n1;
- a2 += n2;
- }
- pNew->nRecord = pOut - pNew->aRecord;
- }
- sqlite3_free(pExist);
- }
- }else{
- int op1 = pExist->op;
-
- /*
- ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2.
- ** op1=INSERT, op2=UPDATE -> INSERT.
- ** op1=INSERT, op2=DELETE -> (none)
- **
- ** op1=UPDATE, op2=INSERT -> Unsupported. Discard op2.
- ** op1=UPDATE, op2=UPDATE -> UPDATE.
- ** op1=UPDATE, op2=DELETE -> DELETE.
- **
- ** op1=DELETE, op2=INSERT -> UPDATE.
- ** op1=DELETE, op2=UPDATE -> Unsupported. Discard op2.
- ** op1=DELETE, op2=DELETE -> Unsupported. Discard op2.
- */
- if( (op1==SQLITE_INSERT && op2==SQLITE_INSERT)
- || (op1==SQLITE_UPDATE && op2==SQLITE_INSERT)
- || (op1==SQLITE_DELETE && op2==SQLITE_UPDATE)
- || (op1==SQLITE_DELETE && op2==SQLITE_DELETE)
- ){
- pNew = pExist;
- }else if( op1==SQLITE_INSERT && op2==SQLITE_DELETE ){
- sqlite3_free(pExist);
- assert( pNew==0 );
- }else{
- u8 *aExist = pExist->aRecord;
- int nByte;
- u8 *aCsr;
-
- /* Allocate a new SessionChange object. Ensure that the aRecord[]
- ** buffer of the new object is large enough to hold any record that
- ** may be generated by combining the input records. */
- nByte = sizeof(SessionChange) + pExist->nRecord + nRec;
- pNew = (SessionChange *)sqlite3_malloc(nByte);
- if( !pNew ){
- sqlite3_free(pExist);
- return SQLITE_NOMEM;
- }
- memset(pNew, 0, sizeof(SessionChange));
- pNew->bIndirect = (bIndirect && pExist->bIndirect);
- aCsr = pNew->aRecord = (u8 *)&pNew[1];
-
- if( op1==SQLITE_INSERT ){ /* INSERT + UPDATE */
- u8 *a1 = aRec;
- assert( op2==SQLITE_UPDATE );
- pNew->op = SQLITE_INSERT;
- if( bPatchset==0 ) sessionSkipRecord(&a1, pTab->nCol);
- sessionMergeRecord(&aCsr, pTab->nCol, aExist, a1);
- }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */
- assert( op2==SQLITE_INSERT );
- pNew->op = SQLITE_UPDATE;
- if( bPatchset ){
- memcpy(aCsr, aRec, nRec);
- aCsr += nRec;
- }else{
- if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aExist, 0,aRec,0) ){
- sqlite3_free(pNew);
- pNew = 0;
- }
- }
- }else if( op2==SQLITE_UPDATE ){ /* UPDATE + UPDATE */
- u8 *a1 = aExist;
- u8 *a2 = aRec;
- assert( op1==SQLITE_UPDATE );
- if( bPatchset==0 ){
- sessionSkipRecord(&a1, pTab->nCol);
- sessionSkipRecord(&a2, pTab->nCol);
- }
- pNew->op = SQLITE_UPDATE;
- if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aRec, aExist,a1,a2) ){
- sqlite3_free(pNew);
- pNew = 0;
- }
- }else{ /* UPDATE + DELETE */
- assert( op1==SQLITE_UPDATE && op2==SQLITE_DELETE );
- pNew->op = SQLITE_DELETE;
- if( bPatchset ){
- memcpy(aCsr, aRec, nRec);
- aCsr += nRec;
- }else{
- sessionMergeRecord(&aCsr, pTab->nCol, aRec, aExist);
- }
- }
-
- if( pNew ){
- pNew->nRecord = (int)(aCsr - pNew->aRecord);
- }
- sqlite3_free(pExist);
- }
- }
-
- *ppNew = pNew;
- return rc;
-}
-
-/*
-** Add all changes in the changeset traversed by the iterator passed as
-** the first argument to the changegroup hash tables.
-*/
-static int sessionChangesetToHash(
- sqlite3_changeset_iter *pIter, /* Iterator to read from */
- sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */
- int bRebase /* True if hash table is for rebasing */
-){
- u8 *aRec;
- int nRec;
- int rc = SQLITE_OK;
- SessionTable *pTab = 0;
-
- while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){
- const char *zNew;
- int nCol;
- int op;
- int iHash;
- int bIndirect;
- SessionChange *pChange;
- SessionChange *pExist = 0;
- SessionChange **pp;
-
- if( pGrp->pList==0 ){
- pGrp->bPatch = pIter->bPatchset;
- }else if( pIter->bPatchset!=pGrp->bPatch ){
- rc = SQLITE_ERROR;
- break;
- }
-
- sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect);
- if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){
- /* Search the list for a matching table */
- int nNew = (int)strlen(zNew);
- u8 *abPK;
-
- sqlite3changeset_pk(pIter, &abPK, 0);
- for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
- if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break;
- }
- if( !pTab ){
- SessionTable **ppTab;
-
- pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1);
- if( !pTab ){
- rc = SQLITE_NOMEM;
- break;
- }
- memset(pTab, 0, sizeof(SessionTable));
- pTab->nCol = nCol;
- pTab->abPK = (u8*)&pTab[1];
- memcpy(pTab->abPK, abPK, nCol);
- pTab->zName = (char*)&pTab->abPK[nCol];
- memcpy(pTab->zName, zNew, nNew+1);
-
- /* The new object must be linked on to the end of the list, not
- ** simply added to the start of it. This is to ensure that the
- ** tables within the output of sqlite3changegroup_output() are in
- ** the right order. */
- for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext);
- *ppTab = pTab;
- }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){
- rc = SQLITE_SCHEMA;
- break;
- }
- }
-
- if( sessionGrowHash(pIter->bPatchset, pTab) ){
- rc = SQLITE_NOMEM;
- break;
- }
- iHash = sessionChangeHash(
- pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange
- );
-
- /* Search for existing entry. If found, remove it from the hash table.
- ** Code below may link it back in.
- */
- for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){
- int bPkOnly1 = 0;
- int bPkOnly2 = 0;
- if( pIter->bPatchset ){
- bPkOnly1 = (*pp)->op==SQLITE_DELETE;
- bPkOnly2 = op==SQLITE_DELETE;
- }
- if( sessionChangeEqual(pTab, bPkOnly1, (*pp)->aRecord, bPkOnly2, aRec) ){
- pExist = *pp;
- *pp = (*pp)->pNext;
- pTab->nEntry--;
- break;
- }
- }
-
- rc = sessionChangeMerge(pTab, bRebase,
- pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange
- );
- if( rc ) break;
- if( pChange ){
- pChange->pNext = pTab->apChange[iHash];
- pTab->apChange[iHash] = pChange;
- pTab->nEntry++;
- }
- }
-
- if( rc==SQLITE_OK ) rc = pIter->rc;
- return rc;
-}
-
-/*
-** Serialize a changeset (or patchset) based on all changesets (or patchsets)
-** added to the changegroup object passed as the first argument.
-**
-** If xOutput is not NULL, then the changeset/patchset is returned to the
-** user via one or more calls to xOutput, as with the other streaming
-** interfaces.
-**
-** Or, if xOutput is NULL, then (*ppOut) is populated with a pointer to a
-** buffer containing the output changeset before this function returns. In
-** this case (*pnOut) is set to the size of the output buffer in bytes. It
-** is the responsibility of the caller to free the output buffer using
-** sqlite3_free() when it is no longer required.
-**
-** If successful, SQLITE_OK is returned. Or, if an error occurs, an SQLite
-** error code. If an error occurs and xOutput is NULL, (*ppOut) and (*pnOut)
-** are both set to 0 before returning.
-*/
-static int sessionChangegroupOutput(
- sqlite3_changegroup *pGrp,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut,
- int *pnOut,
- void **ppOut
-){
- int rc = SQLITE_OK;
- SessionBuffer buf = {0, 0, 0};
- SessionTable *pTab;
- assert( xOutput==0 || (ppOut==0 && pnOut==0) );
-
- /* Create the serialized output changeset based on the contents of the
- ** hash tables attached to the SessionTable objects in list p->pList.
- */
- for(pTab=pGrp->pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
- int i;
- if( pTab->nEntry==0 ) continue;
-
- sessionAppendTableHdr(&buf, pGrp->bPatch, pTab, &rc);
- for(i=0; i<pTab->nChange; i++){
- SessionChange *p;
- for(p=pTab->apChange[i]; p; p=p->pNext){
- sessionAppendByte(&buf, p->op, &rc);
- sessionAppendByte(&buf, p->bIndirect, &rc);
- sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
- }
- }
-
- if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
- rc = xOutput(pOut, buf.aBuf, buf.nBuf);
- buf.nBuf = 0;
- }
- }
-
- if( rc==SQLITE_OK ){
- if( xOutput ){
- if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf);
- }else{
- *ppOut = buf.aBuf;
- *pnOut = buf.nBuf;
- buf.aBuf = 0;
- }
- }
- sqlite3_free(buf.aBuf);
-
- return rc;
-}
-
-/*
-** Allocate a new, empty, sqlite3_changegroup.
-*/
-int sqlite3changegroup_new(sqlite3_changegroup **pp){
- int rc = SQLITE_OK; /* Return code */
- sqlite3_changegroup *p; /* New object */
- p = (sqlite3_changegroup*)sqlite3_malloc(sizeof(sqlite3_changegroup));
- if( p==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(p, 0, sizeof(sqlite3_changegroup));
- }
- *pp = p;
- return rc;
-}
-
-/*
-** Add the changeset currently stored in buffer pData, size nData bytes,
-** to changeset-group p.
-*/
-int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){
- sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */
- int rc; /* Return code */
-
- rc = sqlite3changeset_start(&pIter, nData, pData);
- if( rc==SQLITE_OK ){
- rc = sessionChangesetToHash(pIter, pGrp, 0);
- }
- sqlite3changeset_finalize(pIter);
- return rc;
-}
-
-/*
-** Obtain a buffer containing a changeset representing the concatenation
-** of all changesets added to the group so far.
-*/
-int sqlite3changegroup_output(
- sqlite3_changegroup *pGrp,
- int *pnData,
- void **ppData
-){
- return sessionChangegroupOutput(pGrp, 0, 0, pnData, ppData);
-}
-
-/*
-** Streaming versions of changegroup_add().
-*/
-int sqlite3changegroup_add_strm(
- sqlite3_changegroup *pGrp,
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn
-){
- sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */
- int rc; /* Return code */
-
- rc = sqlite3changeset_start_strm(&pIter, xInput, pIn);
- if( rc==SQLITE_OK ){
- rc = sessionChangesetToHash(pIter, pGrp, 0);
- }
- sqlite3changeset_finalize(pIter);
- return rc;
-}
-
-/*
-** Streaming versions of changegroup_output().
-*/
-int sqlite3changegroup_output_strm(
- sqlite3_changegroup *pGrp,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-){
- return sessionChangegroupOutput(pGrp, xOutput, pOut, 0, 0);
-}
-
-/*
-** Delete a changegroup object.
-*/
-void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
- if( pGrp ){
- sessionDeleteTable(pGrp->pList);
- sqlite3_free(pGrp);
- }
-}
-
-/*
-** Combine two changesets together.
-*/
-int sqlite3changeset_concat(
- int nLeft, /* Number of bytes in lhs input */
- void *pLeft, /* Lhs input changeset */
- int nRight /* Number of bytes in rhs input */,
- void *pRight, /* Rhs input changeset */
- int *pnOut, /* OUT: Number of bytes in output changeset */
- void **ppOut /* OUT: changeset (left <concat> right) */
-){
- sqlite3_changegroup *pGrp;
- int rc;
-
- rc = sqlite3changegroup_new(&pGrp);
- if( rc==SQLITE_OK ){
- rc = sqlite3changegroup_add(pGrp, nLeft, pLeft);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3changegroup_add(pGrp, nRight, pRight);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3changegroup_output(pGrp, pnOut, ppOut);
- }
- sqlite3changegroup_delete(pGrp);
-
- return rc;
-}
-
-/*
-** Streaming version of sqlite3changeset_concat().
-*/
-int sqlite3changeset_concat_strm(
- int (*xInputA)(void *pIn, void *pData, int *pnData),
- void *pInA,
- int (*xInputB)(void *pIn, void *pData, int *pnData),
- void *pInB,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-){
- sqlite3_changegroup *pGrp;
- int rc;
-
- rc = sqlite3changegroup_new(&pGrp);
- if( rc==SQLITE_OK ){
- rc = sqlite3changegroup_add_strm(pGrp, xInputA, pInA);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3changegroup_add_strm(pGrp, xInputB, pInB);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3changegroup_output_strm(pGrp, xOutput, pOut);
- }
- sqlite3changegroup_delete(pGrp);
-
- return rc;
-}
-
-/*
-** Changeset rebaser handle.
-*/
-struct sqlite3_rebaser {
- sqlite3_changegroup grp; /* Hash table */
-};
-
-/*
-** Buffers a1 and a2 must both contain a sessions module record nCol
-** fields in size. This function appends an nCol sessions module
-** record to buffer pBuf that is a copy of a1, except that for
-** each field that is undefined in a1[], swap in the field from a2[].
-*/
-static void sessionAppendRecordMerge(
- SessionBuffer *pBuf, /* Buffer to append to */
- int nCol, /* Number of columns in each record */
- u8 *a1, int n1, /* Record 1 */
- u8 *a2, int n2, /* Record 2 */
- int *pRc /* IN/OUT: error code */
-){
- sessionBufferGrow(pBuf, n1+n2, pRc);
- if( *pRc==SQLITE_OK ){
- int i;
- u8 *pOut = &pBuf->aBuf[pBuf->nBuf];
- for(i=0; i<nCol; i++){
- int nn1 = sessionSerialLen(a1);
- int nn2 = sessionSerialLen(a2);
- if( *a1==0 || *a1==0xFF ){
- memcpy(pOut, a2, nn2);
- pOut += nn2;
- }else{
- memcpy(pOut, a1, nn1);
- pOut += nn1;
- }
- a1 += nn1;
- a2 += nn2;
- }
-
- pBuf->nBuf = pOut-pBuf->aBuf;
- assert( pBuf->nBuf<=pBuf->nAlloc );
- }
-}
-
-/*
-** This function is called when rebasing a local UPDATE change against one
-** or more remote UPDATE changes. The aRec/nRec buffer contains the current
-** old.* and new.* records for the change. The rebase buffer (a single
-** record) is in aChange/nChange. The rebased change is appended to buffer
-** pBuf.
-**
-** Rebasing the UPDATE involves:
-**
-** * Removing any changes to fields for which the corresponding field
-** in the rebase buffer is set to "replaced" (type 0xFF). If this
-** means the UPDATE change updates no fields, nothing is appended
-** to the output buffer.
-**
-** * For each field modified by the local change for which the
-** corresponding field in the rebase buffer is not "undefined" (0x00)
-** or "replaced" (0xFF), the old.* value is replaced by the value
-** in the rebase buffer.
-*/
-static void sessionAppendPartialUpdate(
- SessionBuffer *pBuf, /* Append record here */
- sqlite3_changeset_iter *pIter, /* Iterator pointed at local change */
- u8 *aRec, int nRec, /* Local change */
- u8 *aChange, int nChange, /* Record to rebase against */
- int *pRc /* IN/OUT: Return Code */
-){
- sessionBufferGrow(pBuf, 2+nRec+nChange, pRc);
- if( *pRc==SQLITE_OK ){
- int bData = 0;
- u8 *pOut = &pBuf->aBuf[pBuf->nBuf];
- int i;
- u8 *a1 = aRec;
- u8 *a2 = aChange;
-
- *pOut++ = SQLITE_UPDATE;
- *pOut++ = pIter->bIndirect;
- for(i=0; i<pIter->nCol; i++){
- int n1 = sessionSerialLen(a1);
- int n2 = sessionSerialLen(a2);
- if( pIter->abPK[i] || a2[0]==0 ){
- if( !pIter->abPK[i] ) bData = 1;
- memcpy(pOut, a1, n1);
- pOut += n1;
- }else if( a2[0]!=0xFF ){
- bData = 1;
- memcpy(pOut, a2, n2);
- pOut += n2;
- }else{
- *pOut++ = '\0';
- }
- a1 += n1;
- a2 += n2;
- }
- if( bData ){
- a2 = aChange;
- for(i=0; i<pIter->nCol; i++){
- int n1 = sessionSerialLen(a1);
- int n2 = sessionSerialLen(a2);
- if( pIter->abPK[i] || a2[0]!=0xFF ){
- memcpy(pOut, a1, n1);
- pOut += n1;
- }else{
- *pOut++ = '\0';
- }
- a1 += n1;
- a2 += n2;
- }
- pBuf->nBuf = (pOut - pBuf->aBuf);
- }
- }
-}
-
-/*
-** pIter is configured to iterate through a changeset. This function rebases
-** that changeset according to the current configuration of the rebaser
-** object passed as the first argument. If no error occurs and argument xOutput
-** is not NULL, then the changeset is returned to the caller by invoking
-** xOutput zero or more times and SQLITE_OK returned. Or, if xOutput is NULL,
-** then (*ppOut) is set to point to a buffer containing the rebased changeset
-** before this function returns. In this case (*pnOut) is set to the size of
-** the buffer in bytes. It is the responsibility of the caller to eventually
-** free the (*ppOut) buffer using sqlite3_free().
-**
-** If an error occurs, an SQLite error code is returned. If ppOut and
-** pnOut are not NULL, then the two output parameters are set to 0 before
-** returning.
-*/
-static int sessionRebase(
- sqlite3_rebaser *p, /* Rebaser hash table */
- sqlite3_changeset_iter *pIter, /* Input data */
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut, /* Context for xOutput callback */
- int *pnOut, /* OUT: Number of bytes in output changeset */
- void **ppOut /* OUT: Inverse of pChangeset */
-){
- int rc = SQLITE_OK;
- u8 *aRec = 0;
- int nRec = 0;
- int bNew = 0;
- SessionTable *pTab = 0;
- SessionBuffer sOut = {0,0,0};
-
- while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){
- SessionChange *pChange = 0;
- int bDone = 0;
-
- if( bNew ){
- const char *zTab = pIter->zTab;
- for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){
- if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break;
- }
- bNew = 0;
-
- /* A patchset may not be rebased */
- if( pIter->bPatchset ){
- rc = SQLITE_ERROR;
- }
-
- /* Append a table header to the output for this new table */
- sessionAppendByte(&sOut, pIter->bPatchset ? 'P' : 'T', &rc);
- sessionAppendVarint(&sOut, pIter->nCol, &rc);
- sessionAppendBlob(&sOut, pIter->abPK, pIter->nCol, &rc);
- sessionAppendBlob(&sOut,(u8*)pIter->zTab,(int)strlen(pIter->zTab)+1,&rc);
- }
-
- if( pTab && rc==SQLITE_OK ){
- int iHash = sessionChangeHash(pTab, 0, aRec, pTab->nChange);
-
- for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){
- if( sessionChangeEqual(pTab, 0, aRec, 0, pChange->aRecord) ){
- break;
- }
- }
- }
-
- if( pChange ){
- assert( pChange->op==SQLITE_DELETE || pChange->op==SQLITE_INSERT );
- switch( pIter->op ){
- case SQLITE_INSERT:
- if( pChange->op==SQLITE_INSERT ){
- bDone = 1;
- if( pChange->bIndirect==0 ){
- sessionAppendByte(&sOut, SQLITE_UPDATE, &rc);
- sessionAppendByte(&sOut, pIter->bIndirect, &rc);
- sessionAppendBlob(&sOut, pChange->aRecord, pChange->nRecord, &rc);
- sessionAppendBlob(&sOut, aRec, nRec, &rc);
- }
- }
- break;
-
- case SQLITE_UPDATE:
- bDone = 1;
- if( pChange->op==SQLITE_DELETE ){
- if( pChange->bIndirect==0 ){
- u8 *pCsr = aRec;
- sessionSkipRecord(&pCsr, pIter->nCol);
- sessionAppendByte(&sOut, SQLITE_INSERT, &rc);
- sessionAppendByte(&sOut, pIter->bIndirect, &rc);
- sessionAppendRecordMerge(&sOut, pIter->nCol,
- pCsr, nRec-(pCsr-aRec),
- pChange->aRecord, pChange->nRecord, &rc
- );
- }
- }else{
- sessionAppendPartialUpdate(&sOut, pIter,
- aRec, nRec, pChange->aRecord, pChange->nRecord, &rc
- );
- }
- break;
-
- default:
- assert( pIter->op==SQLITE_DELETE );
- bDone = 1;
- if( pChange->op==SQLITE_INSERT ){
- sessionAppendByte(&sOut, SQLITE_DELETE, &rc);
- sessionAppendByte(&sOut, pIter->bIndirect, &rc);
- sessionAppendRecordMerge(&sOut, pIter->nCol,
- pChange->aRecord, pChange->nRecord, aRec, nRec, &rc
- );
- }
- break;
- }
- }
-
- if( bDone==0 ){
- sessionAppendByte(&sOut, pIter->op, &rc);
- sessionAppendByte(&sOut, pIter->bIndirect, &rc);
- sessionAppendBlob(&sOut, aRec, nRec, &rc);
- }
- if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){
- rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
- sOut.nBuf = 0;
- }
- if( rc ) break;
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_free(sOut.aBuf);
- memset(&sOut, 0, sizeof(sOut));
- }
-
- if( rc==SQLITE_OK ){
- if( xOutput ){
- if( sOut.nBuf>0 ){
- rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
- }
- }else{
- *ppOut = (void*)sOut.aBuf;
- *pnOut = sOut.nBuf;
- sOut.aBuf = 0;
- }
- }
- sqlite3_free(sOut.aBuf);
- return rc;
-}
-
-/*
-** Create a new rebaser object.
-*/
-int sqlite3rebaser_create(sqlite3_rebaser **ppNew){
- int rc = SQLITE_OK;
- sqlite3_rebaser *pNew;
-
- pNew = sqlite3_malloc(sizeof(sqlite3_rebaser));
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pNew, 0, sizeof(sqlite3_rebaser));
- }
- *ppNew = pNew;
- return rc;
-}
-
-/*
-** Call this one or more times to configure a rebaser.
-*/
-int sqlite3rebaser_configure(
- sqlite3_rebaser *p,
- int nRebase, const void *pRebase
-){
- sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */
- int rc; /* Return code */
- rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase);
- if( rc==SQLITE_OK ){
- rc = sessionChangesetToHash(pIter, &p->grp, 1);
- }
- sqlite3changeset_finalize(pIter);
- return rc;
-}
-
-/*
-** Rebase a changeset according to current rebaser configuration
-*/
-int sqlite3rebaser_rebase(
- sqlite3_rebaser *p,
- int nIn, const void *pIn,
- int *pnOut, void **ppOut
-){
- sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */
- int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn);
-
- if( rc==SQLITE_OK ){
- rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut);
- sqlite3changeset_finalize(pIter);
- }
-
- return rc;
-}
-
-/*
-** Rebase a changeset according to current rebaser configuration
-*/
-int sqlite3rebaser_rebase_strm(
- sqlite3_rebaser *p,
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-){
- sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */
- int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn);
-
- if( rc==SQLITE_OK ){
- rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0);
- sqlite3changeset_finalize(pIter);
- }
-
- return rc;
-}
-
-/*
-** Destroy a rebaser object
-*/
-void sqlite3rebaser_delete(sqlite3_rebaser *p){
- if( p ){
- sessionDeleteTable(p->grp.pList);
- sqlite3_free(p);
- }
-}
-
-#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sqlite3session.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sqlite3session.h
deleted file mode 100644
index a3def5f1df1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/sqlite3session.h
+++ /dev/null
@@ -1,1583 +0,0 @@
-
-#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION)
-#define __SQLITESESSION_H_ 1
-
-/*
-** Make sure we can call this stuff from C++.
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "sqlite3.h"
-
-/*
-** CAPI3REF: Session Object Handle
-**
-** An instance of this object is a [session] that can be used to
-** record changes to a database.
-*/
-typedef struct sqlite3_session sqlite3_session;
-
-/*
-** CAPI3REF: Changeset Iterator Handle
-**
-** An instance of this object acts as a cursor for iterating
-** over the elements of a [changeset] or [patchset].
-*/
-typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
-
-/*
-** CAPI3REF: Create A New Session Object
-** CONSTRUCTOR: sqlite3_session
-**
-** Create a new session object attached to database handle db. If successful,
-** a pointer to the new object is written to *ppSession and SQLITE_OK is
-** returned. If an error occurs, *ppSession is set to NULL and an SQLite
-** error code (e.g. SQLITE_NOMEM) is returned.
-**
-** It is possible to create multiple session objects attached to a single
-** database handle.
-**
-** Session objects created using this function should be deleted using the
-** [sqlite3session_delete()] function before the database handle that they
-** are attached to is itself closed. If the database handle is closed before
-** the session object is deleted, then the results of calling any session
-** module function, including [sqlite3session_delete()] on the session object
-** are undefined.
-**
-** Because the session module uses the [sqlite3_preupdate_hook()] API, it
-** is not possible for an application to register a pre-update hook on a
-** database handle that has one or more session objects attached. Nor is
-** it possible to create a session object attached to a database handle for
-** which a pre-update hook is already defined. The results of attempting
-** either of these things are undefined.
-**
-** The session object will be used to create changesets for tables in
-** database zDb, where zDb is either "main", or "temp", or the name of an
-** attached database. It is not an error if database zDb is not attached
-** to the database when the session object is created.
-*/
-int sqlite3session_create(
- sqlite3 *db, /* Database handle */
- const char *zDb, /* Name of db (e.g. "main") */
- sqlite3_session **ppSession /* OUT: New session object */
-);
-
-/*
-** CAPI3REF: Delete A Session Object
-** DESTRUCTOR: sqlite3_session
-**
-** Delete a session object previously allocated using
-** [sqlite3session_create()]. Once a session object has been deleted, the
-** results of attempting to use pSession with any other session module
-** function are undefined.
-**
-** Session objects must be deleted before the database handle to which they
-** are attached is closed. Refer to the documentation for
-** [sqlite3session_create()] for details.
-*/
-void sqlite3session_delete(sqlite3_session *pSession);
-
-
-/*
-** CAPI3REF: Enable Or Disable A Session Object
-** METHOD: sqlite3_session
-**
-** Enable or disable the recording of changes by a session object. When
-** enabled, a session object records changes made to the database. When
-** disabled - it does not. A newly created session object is enabled.
-** Refer to the documentation for [sqlite3session_changeset()] for further
-** details regarding how enabling and disabling a session object affects
-** the eventual changesets.
-**
-** Passing zero to this function disables the session. Passing a value
-** greater than zero enables it. Passing a value less than zero is a
-** no-op, and may be used to query the current state of the session.
-**
-** The return value indicates the final state of the session object: 0 if
-** the session is disabled, or 1 if it is enabled.
-*/
-int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
-
-/*
-** CAPI3REF: Set Or Clear the Indirect Change Flag
-** METHOD: sqlite3_session
-**
-** Each change recorded by a session object is marked as either direct or
-** indirect. A change is marked as indirect if either:
-**
-** <ul>
-** <li> The session object "indirect" flag is set when the change is
-** made, or
-** <li> The change is made by an SQL trigger or foreign key action
-** instead of directly as a result of a users SQL statement.
-** </ul>
-**
-** If a single row is affected by more than one operation within a session,
-** then the change is considered indirect if all operations meet the criteria
-** for an indirect change above, or direct otherwise.
-**
-** This function is used to set, clear or query the session object indirect
-** flag. If the second argument passed to this function is zero, then the
-** indirect flag is cleared. If it is greater than zero, the indirect flag
-** is set. Passing a value less than zero does not modify the current value
-** of the indirect flag, and may be used to query the current state of the
-** indirect flag for the specified session object.
-**
-** The return value indicates the final state of the indirect flag: 0 if
-** it is clear, or 1 if it is set.
-*/
-int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
-
-/*
-** CAPI3REF: Attach A Table To A Session Object
-** METHOD: sqlite3_session
-**
-** If argument zTab is not NULL, then it is the name of a table to attach
-** to the session object passed as the first argument. All subsequent changes
-** made to the table while the session object is enabled will be recorded. See
-** documentation for [sqlite3session_changeset()] for further details.
-**
-** Or, if argument zTab is NULL, then changes are recorded for all tables
-** in the database. If additional tables are added to the database (by
-** executing "CREATE TABLE" statements) after this call is made, changes for
-** the new tables are also recorded.
-**
-** Changes can only be recorded for tables that have a PRIMARY KEY explicitly
-** defined as part of their CREATE TABLE statement. It does not matter if the
-** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY
-** KEY may consist of a single column, or may be a composite key.
-**
-** It is not an error if the named table does not exist in the database. Nor
-** is it an error if the named table does not have a PRIMARY KEY. However,
-** no changes will be recorded in either of these scenarios.
-**
-** Changes are not recorded for individual rows that have NULL values stored
-** in one or more of their PRIMARY KEY columns.
-**
-** SQLITE_OK is returned if the call completes without error. Or, if an error
-** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
-**
-** <h3>Special sqlite_stat1 Handling</h3>
-**
-** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to
-** some of the rules above. In SQLite, the schema of sqlite_stat1 is:
-** <pre>
-** &nbsp; CREATE TABLE sqlite_stat1(tbl,idx,stat)
-** </pre>
-**
-** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are
-** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes
-** are recorded for rows for which (idx IS NULL) is true. However, for such
-** rows a zero-length blob (SQL value X'') is stored in the changeset or
-** patchset instead of a NULL value. This allows such changesets to be
-** manipulated by legacy implementations of sqlite3changeset_invert(),
-** concat() and similar.
-**
-** The sqlite3changeset_apply() function automatically converts the
-** zero-length blob back to a NULL value when updating the sqlite_stat1
-** table. However, if the application calls sqlite3changeset_new(),
-** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset
-** iterator directly (including on a changeset iterator passed to a
-** conflict-handler callback) then the X'' value is returned. The application
-** must translate X'' to NULL itself if required.
-**
-** Legacy (older than 3.22.0) versions of the sessions module cannot capture
-** changes made to the sqlite_stat1 table. Legacy versions of the
-** sqlite3changeset_apply() function silently ignore any modifications to the
-** sqlite_stat1 table that are part of a changeset or patchset.
-*/
-int sqlite3session_attach(
- sqlite3_session *pSession, /* Session object */
- const char *zTab /* Table name */
-);
-
-/*
-** CAPI3REF: Set a table filter on a Session Object.
-** METHOD: sqlite3_session
-**
-** The second argument (xFilter) is the "filter callback". For changes to rows
-** in tables that are not attached to the Session object, the filter is called
-** to determine whether changes to the table's rows should be tracked or not.
-** If xFilter returns 0, changes is not tracked. Note that once a table is
-** attached, xFilter will not be called again.
-*/
-void sqlite3session_table_filter(
- sqlite3_session *pSession, /* Session object */
- int(*xFilter)(
- void *pCtx, /* Copy of third arg to _filter_table() */
- const char *zTab /* Table name */
- ),
- void *pCtx /* First argument passed to xFilter */
-);
-
-/*
-** CAPI3REF: Generate A Changeset From A Session Object
-** METHOD: sqlite3_session
-**
-** Obtain a changeset containing changes to the tables attached to the
-** session object passed as the first argument. If successful,
-** set *ppChangeset to point to a buffer containing the changeset
-** and *pnChangeset to the size of the changeset in bytes before returning
-** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to
-** zero and return an SQLite error code.
-**
-** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes,
-** each representing a change to a single row of an attached table. An INSERT
-** change contains the values of each field of a new database row. A DELETE
-** contains the original values of each field of a deleted database row. An
-** UPDATE change contains the original values of each field of an updated
-** database row along with the updated values for each updated non-primary-key
-** column. It is not possible for an UPDATE change to represent a change that
-** modifies the values of primary key columns. If such a change is made, it
-** is represented in a changeset as a DELETE followed by an INSERT.
-**
-** Changes are not recorded for rows that have NULL values stored in one or
-** more of their PRIMARY KEY columns. If such a row is inserted or deleted,
-** no corresponding change is present in the changesets returned by this
-** function. If an existing row with one or more NULL values stored in
-** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL,
-** only an INSERT is appears in the changeset. Similarly, if an existing row
-** with non-NULL PRIMARY KEY values is updated so that one or more of its
-** PRIMARY KEY columns are set to NULL, the resulting changeset contains a
-** DELETE change only.
-**
-** The contents of a changeset may be traversed using an iterator created
-** using the [sqlite3changeset_start()] API. A changeset may be applied to
-** a database with a compatible schema using the [sqlite3changeset_apply()]
-** API.
-**
-** Within a changeset generated by this function, all changes related to a
-** single table are grouped together. In other words, when iterating through
-** a changeset or when applying a changeset to a database, all changes related
-** to a single table are processed before moving on to the next table. Tables
-** are sorted in the same order in which they were attached (or auto-attached)
-** to the sqlite3_session object. The order in which the changes related to
-** a single table are stored is undefined.
-**
-** Following a successful call to this function, it is the responsibility of
-** the caller to eventually free the buffer that *ppChangeset points to using
-** [sqlite3_free()].
-**
-** <h3>Changeset Generation</h3>
-**
-** Once a table has been attached to a session object, the session object
-** records the primary key values of all new rows inserted into the table.
-** It also records the original primary key and other column values of any
-** deleted or updated rows. For each unique primary key value, data is only
-** recorded once - the first time a row with said primary key is inserted,
-** updated or deleted in the lifetime of the session.
-**
-** There is one exception to the previous paragraph: when a row is inserted,
-** updated or deleted, if one or more of its primary key columns contain a
-** NULL value, no record of the change is made.
-**
-** The session object therefore accumulates two types of records - those
-** that consist of primary key values only (created when the user inserts
-** a new record) and those that consist of the primary key values and the
-** original values of other table columns (created when the users deletes
-** or updates a record).
-**
-** When this function is called, the requested changeset is created using
-** both the accumulated records and the current contents of the database
-** file. Specifically:
-**
-** <ul>
-** <li> For each record generated by an insert, the database is queried
-** for a row with a matching primary key. If one is found, an INSERT
-** change is added to the changeset. If no such row is found, no change
-** is added to the changeset.
-**
-** <li> For each record generated by an update or delete, the database is
-** queried for a row with a matching primary key. If such a row is
-** found and one or more of the non-primary key fields have been
-** modified from their original values, an UPDATE change is added to
-** the changeset. Or, if no such row is found in the table, a DELETE
-** change is added to the changeset. If there is a row with a matching
-** primary key in the database, but all fields contain their original
-** values, no change is added to the changeset.
-** </ul>
-**
-** This means, amongst other things, that if a row is inserted and then later
-** deleted while a session object is active, neither the insert nor the delete
-** will be present in the changeset. Or if a row is deleted and then later a
-** row with the same primary key values inserted while a session object is
-** active, the resulting changeset will contain an UPDATE change instead of
-** a DELETE and an INSERT.
-**
-** When a session object is disabled (see the [sqlite3session_enable()] API),
-** it does not accumulate records when rows are inserted, updated or deleted.
-** This may appear to have some counter-intuitive effects if a single row
-** is written to more than once during a session. For example, if a row
-** is inserted while a session object is enabled, then later deleted while
-** the same session object is disabled, no INSERT record will appear in the
-** changeset, even though the delete took place while the session was disabled.
-** Or, if one field of a row is updated while a session is disabled, and
-** another field of the same row is updated while the session is enabled, the
-** resulting changeset will contain an UPDATE change that updates both fields.
-*/
-int sqlite3session_changeset(
- sqlite3_session *pSession, /* Session object */
- int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
- void **ppChangeset /* OUT: Buffer containing changeset */
-);
-
-/*
-** CAPI3REF: Load The Difference Between Tables Into A Session
-** METHOD: sqlite3_session
-**
-** If it is not already attached to the session object passed as the first
-** argument, this function attaches table zTbl in the same manner as the
-** [sqlite3session_attach()] function. If zTbl does not exist, or if it
-** does not have a primary key, this function is a no-op (but does not return
-** an error).
-**
-** Argument zFromDb must be the name of a database ("main", "temp" etc.)
-** attached to the same database handle as the session object that contains
-** a table compatible with the table attached to the session by this function.
-** A table is considered compatible if it:
-**
-** <ul>
-** <li> Has the same name,
-** <li> Has the same set of columns declared in the same order, and
-** <li> Has the same PRIMARY KEY definition.
-** </ul>
-**
-** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables
-** are compatible but do not have any PRIMARY KEY columns, it is not an error
-** but no changes are added to the session object. As with other session
-** APIs, tables without PRIMARY KEYs are simply ignored.
-**
-** This function adds a set of changes to the session object that could be
-** used to update the table in database zFrom (call this the "from-table")
-** so that its content is the same as the table attached to the session
-** object (call this the "to-table"). Specifically:
-**
-** <ul>
-** <li> For each row (primary key) that exists in the to-table but not in
-** the from-table, an INSERT record is added to the session object.
-**
-** <li> For each row (primary key) that exists in the to-table but not in
-** the from-table, a DELETE record is added to the session object.
-**
-** <li> For each row (primary key) that exists in both tables, but features
-** different non-PK values in each, an UPDATE record is added to the
-** session.
-** </ul>
-**
-** To clarify, if this function is called and then a changeset constructed
-** using [sqlite3session_changeset()], then after applying that changeset to
-** database zFrom the contents of the two compatible tables would be
-** identical.
-**
-** It an error if database zFrom does not exist or does not contain the
-** required compatible table.
-**
-** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite
-** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
-** may be set to point to a buffer containing an English language error
-** message. It is the responsibility of the caller to free this buffer using
-** sqlite3_free().
-*/
-int sqlite3session_diff(
- sqlite3_session *pSession,
- const char *zFromDb,
- const char *zTbl,
- char **pzErrMsg
-);
-
-
-/*
-** CAPI3REF: Generate A Patchset From A Session Object
-** METHOD: sqlite3_session
-**
-** The differences between a patchset and a changeset are that:
-**
-** <ul>
-** <li> DELETE records consist of the primary key fields only. The
-** original values of other fields are omitted.
-** <li> The original values of any modified fields are omitted from
-** UPDATE records.
-** </ul>
-**
-** A patchset blob may be used with up to date versions of all
-** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(),
-** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly,
-** attempting to use a patchset blob with old versions of the
-** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error.
-**
-** Because the non-primary key "old.*" fields are omitted, no
-** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset
-** is passed to the sqlite3changeset_apply() API. Other conflict types work
-** in the same way as for changesets.
-**
-** Changes within a patchset are ordered in the same way as for changesets
-** generated by the sqlite3session_changeset() function (i.e. all changes for
-** a single table are grouped together, tables appear in the order in which
-** they were attached to the session object).
-*/
-int sqlite3session_patchset(
- sqlite3_session *pSession, /* Session object */
- int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */
- void **ppPatchset /* OUT: Buffer containing patchset */
-);
-
-/*
-** CAPI3REF: Test if a changeset has recorded any changes.
-**
-** Return non-zero if no changes to attached tables have been recorded by
-** the session object passed as the first argument. Otherwise, if one or
-** more changes have been recorded, return zero.
-**
-** Even if this function returns zero, it is possible that calling
-** [sqlite3session_changeset()] on the session handle may still return a
-** changeset that contains no changes. This can happen when a row in
-** an attached table is modified and then later on the original values
-** are restored. However, if this function returns non-zero, then it is
-** guaranteed that a call to sqlite3session_changeset() will return a
-** changeset containing zero changes.
-*/
-int sqlite3session_isempty(sqlite3_session *pSession);
-
-/*
-** CAPI3REF: Create An Iterator To Traverse A Changeset
-** CONSTRUCTOR: sqlite3_changeset_iter
-**
-** Create an iterator used to iterate through the contents of a changeset.
-** If successful, *pp is set to point to the iterator handle and SQLITE_OK
-** is returned. Otherwise, if an error occurs, *pp is set to zero and an
-** SQLite error code is returned.
-**
-** The following functions can be used to advance and query a changeset
-** iterator created by this function:
-**
-** <ul>
-** <li> [sqlite3changeset_next()]
-** <li> [sqlite3changeset_op()]
-** <li> [sqlite3changeset_new()]
-** <li> [sqlite3changeset_old()]
-** </ul>
-**
-** It is the responsibility of the caller to eventually destroy the iterator
-** by passing it to [sqlite3changeset_finalize()]. The buffer containing the
-** changeset (pChangeset) must remain valid until after the iterator is
-** destroyed.
-**
-** Assuming the changeset blob was created by one of the
-** [sqlite3session_changeset()], [sqlite3changeset_concat()] or
-** [sqlite3changeset_invert()] functions, all changes within the changeset
-** that apply to a single table are grouped together. This means that when
-** an application iterates through a changeset using an iterator created by
-** this function, all changes that relate to a single table are visited
-** consecutively. There is no chance that the iterator will visit a change
-** the applies to table X, then one for table Y, and then later on visit
-** another change for table X.
-*/
-int sqlite3changeset_start(
- sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
- int nChangeset, /* Size of changeset blob in bytes */
- void *pChangeset /* Pointer to blob containing changeset */
-);
-
-
-/*
-** CAPI3REF: Advance A Changeset Iterator
-** METHOD: sqlite3_changeset_iter
-**
-** This function may only be used with iterators created by function
-** [sqlite3changeset_start()]. If it is called on an iterator passed to
-** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
-** is returned and the call has no effect.
-**
-** Immediately after an iterator is created by sqlite3changeset_start(), it
-** does not point to any change in the changeset. Assuming the changeset
-** is not empty, the first call to this function advances the iterator to
-** point to the first change in the changeset. Each subsequent call advances
-** the iterator to point to the next change in the changeset (if any). If
-** no error occurs and the iterator points to a valid change after a call
-** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned.
-** Otherwise, if all changes in the changeset have already been visited,
-** SQLITE_DONE is returned.
-**
-** If an error occurs, an SQLite error code is returned. Possible error
-** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or
-** SQLITE_NOMEM.
-*/
-int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
-
-/*
-** CAPI3REF: Obtain The Current Operation From A Changeset Iterator
-** METHOD: sqlite3_changeset_iter
-**
-** The pIter argument passed to this function may either be an iterator
-** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
-** created by [sqlite3changeset_start()]. In the latter case, the most recent
-** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
-** is not the case, this function returns [SQLITE_MISUSE].
-**
-** If argument pzTab is not NULL, then *pzTab is set to point to a
-** nul-terminated utf-8 encoded string containing the name of the table
-** affected by the current change. The buffer remains valid until either
-** sqlite3changeset_next() is called on the iterator or until the
-** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
-** set to the number of columns in the table affected by the change. If
-** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change
-** is an indirect change, or false (0) otherwise. See the documentation for
-** [sqlite3session_indirect()] for a description of direct and indirect
-** changes. Finally, if pOp is not NULL, then *pOp is set to one of
-** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
-** type of change that the iterator currently points to.
-**
-** If no error occurs, SQLITE_OK is returned. If an error does occur, an
-** SQLite error code is returned. The values of the output variables may not
-** be trusted in this case.
-*/
-int sqlite3changeset_op(
- sqlite3_changeset_iter *pIter, /* Iterator object */
- const char **pzTab, /* OUT: Pointer to table name */
- int *pnCol, /* OUT: Number of columns in table */
- int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */
- int *pbIndirect /* OUT: True for an 'indirect' change */
-);
-
-/*
-** CAPI3REF: Obtain The Primary Key Definition Of A Table
-** METHOD: sqlite3_changeset_iter
-**
-** For each modified table, a changeset includes the following:
-**
-** <ul>
-** <li> The number of columns in the table, and
-** <li> Which of those columns make up the tables PRIMARY KEY.
-** </ul>
-**
-** This function is used to find which columns comprise the PRIMARY KEY of
-** the table modified by the change that iterator pIter currently points to.
-** If successful, *pabPK is set to point to an array of nCol entries, where
-** nCol is the number of columns in the table. Elements of *pabPK are set to
-** 0x01 if the corresponding column is part of the tables primary key, or
-** 0x00 if it is not.
-**
-** If argument pnCol is not NULL, then *pnCol is set to the number of columns
-** in the table.
-**
-** If this function is called when the iterator does not point to a valid
-** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise,
-** SQLITE_OK is returned and the output variables populated as described
-** above.
-*/
-int sqlite3changeset_pk(
- sqlite3_changeset_iter *pIter, /* Iterator object */
- unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */
- int *pnCol /* OUT: Number of entries in output array */
-);
-
-/*
-** CAPI3REF: Obtain old.* Values From A Changeset Iterator
-** METHOD: sqlite3_changeset_iter
-**
-** The pIter argument passed to this function may either be an iterator
-** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
-** created by [sqlite3changeset_start()]. In the latter case, the most recent
-** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
-** Furthermore, it may only be called if the type of change that the iterator
-** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise,
-** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL.
-**
-** Argument iVal must be greater than or equal to 0, and less than the number
-** of columns in the table affected by the current change. Otherwise,
-** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
-**
-** If successful, this function sets *ppValue to point to a protected
-** sqlite3_value object containing the iVal'th value from the vector of
-** original row values stored as part of the UPDATE or DELETE change and
-** returns SQLITE_OK. The name of the function comes from the fact that this
-** is similar to the "old.*" columns available to update or delete triggers.
-**
-** If some other error occurs (e.g. an OOM condition), an SQLite error code
-** is returned and *ppValue is set to NULL.
-*/
-int sqlite3changeset_old(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int iVal, /* Column number */
- sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */
-);
-
-/*
-** CAPI3REF: Obtain new.* Values From A Changeset Iterator
-** METHOD: sqlite3_changeset_iter
-**
-** The pIter argument passed to this function may either be an iterator
-** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
-** created by [sqlite3changeset_start()]. In the latter case, the most recent
-** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
-** Furthermore, it may only be called if the type of change that the iterator
-** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise,
-** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL.
-**
-** Argument iVal must be greater than or equal to 0, and less than the number
-** of columns in the table affected by the current change. Otherwise,
-** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
-**
-** If successful, this function sets *ppValue to point to a protected
-** sqlite3_value object containing the iVal'th value from the vector of
-** new row values stored as part of the UPDATE or INSERT change and
-** returns SQLITE_OK. If the change is an UPDATE and does not include
-** a new value for the requested column, *ppValue is set to NULL and
-** SQLITE_OK returned. The name of the function comes from the fact that
-** this is similar to the "new.*" columns available to update or delete
-** triggers.
-**
-** If some other error occurs (e.g. an OOM condition), an SQLite error code
-** is returned and *ppValue is set to NULL.
-*/
-int sqlite3changeset_new(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int iVal, /* Column number */
- sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */
-);
-
-/*
-** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator
-** METHOD: sqlite3_changeset_iter
-**
-** This function should only be used with iterator objects passed to a
-** conflict-handler callback by [sqlite3changeset_apply()] with either
-** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function
-** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue
-** is set to NULL.
-**
-** Argument iVal must be greater than or equal to 0, and less than the number
-** of columns in the table affected by the current change. Otherwise,
-** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
-**
-** If successful, this function sets *ppValue to point to a protected
-** sqlite3_value object containing the iVal'th value from the
-** "conflicting row" associated with the current conflict-handler callback
-** and returns SQLITE_OK.
-**
-** If some other error occurs (e.g. an OOM condition), an SQLite error code
-** is returned and *ppValue is set to NULL.
-*/
-int sqlite3changeset_conflict(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int iVal, /* Column number */
- sqlite3_value **ppValue /* OUT: Value from conflicting row */
-);
-
-/*
-** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations
-** METHOD: sqlite3_changeset_iter
-**
-** This function may only be called with an iterator passed to an
-** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case
-** it sets the output variable to the total number of known foreign key
-** violations in the destination database and returns SQLITE_OK.
-**
-** In all other cases this function returns SQLITE_MISUSE.
-*/
-int sqlite3changeset_fk_conflicts(
- sqlite3_changeset_iter *pIter, /* Changeset iterator */
- int *pnOut /* OUT: Number of FK violations */
-);
-
-
-/*
-** CAPI3REF: Finalize A Changeset Iterator
-** METHOD: sqlite3_changeset_iter
-**
-** This function is used to finalize an iterator allocated with
-** [sqlite3changeset_start()].
-**
-** This function should only be called on iterators created using the
-** [sqlite3changeset_start()] function. If an application calls this
-** function with an iterator passed to a conflict-handler by
-** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the
-** call has no effect.
-**
-** If an error was encountered within a call to an sqlite3changeset_xxx()
-** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an
-** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding
-** to that error is returned by this function. Otherwise, SQLITE_OK is
-** returned. This is to allow the following pattern (pseudo-code):
-**
-** <pre>
-** sqlite3changeset_start();
-** while( SQLITE_ROW==sqlite3changeset_next() ){
-** // Do something with change.
-** }
-** rc = sqlite3changeset_finalize();
-** if( rc!=SQLITE_OK ){
-** // An error has occurred
-** }
-** </pre>
-*/
-int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
-
-/*
-** CAPI3REF: Invert A Changeset
-**
-** This function is used to "invert" a changeset object. Applying an inverted
-** changeset to a database reverses the effects of applying the uninverted
-** changeset. Specifically:
-**
-** <ul>
-** <li> Each DELETE change is changed to an INSERT, and
-** <li> Each INSERT change is changed to a DELETE, and
-** <li> For each UPDATE change, the old.* and new.* values are exchanged.
-** </ul>
-**
-** This function does not change the order in which changes appear within
-** the changeset. It merely reverses the sense of each individual change.
-**
-** If successful, a pointer to a buffer containing the inverted changeset
-** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and
-** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are
-** zeroed and an SQLite error code returned.
-**
-** It is the responsibility of the caller to eventually call sqlite3_free()
-** on the *ppOut pointer to free the buffer allocation following a successful
-** call to this function.
-**
-** WARNING/TODO: This function currently assumes that the input is a valid
-** changeset. If it is not, the results are undefined.
-*/
-int sqlite3changeset_invert(
- int nIn, const void *pIn, /* Input changeset */
- int *pnOut, void **ppOut /* OUT: Inverse of input */
-);
-
-/*
-** CAPI3REF: Concatenate Two Changeset Objects
-**
-** This function is used to concatenate two changesets, A and B, into a
-** single changeset. The result is a changeset equivalent to applying
-** changeset A followed by changeset B.
-**
-** This function combines the two input changesets using an
-** sqlite3_changegroup object. Calling it produces similar results as the
-** following code fragment:
-**
-** <pre>
-** sqlite3_changegroup *pGrp;
-** rc = sqlite3_changegroup_new(&pGrp);
-** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
-** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB);
-** if( rc==SQLITE_OK ){
-** rc = sqlite3changegroup_output(pGrp, pnOut, ppOut);
-** }else{
-** *ppOut = 0;
-** *pnOut = 0;
-** }
-** </pre>
-**
-** Refer to the sqlite3_changegroup documentation below for details.
-*/
-int sqlite3changeset_concat(
- int nA, /* Number of bytes in buffer pA */
- void *pA, /* Pointer to buffer containing changeset A */
- int nB, /* Number of bytes in buffer pB */
- void *pB, /* Pointer to buffer containing changeset B */
- int *pnOut, /* OUT: Number of bytes in output changeset */
- void **ppOut /* OUT: Buffer containing output changeset */
-);
-
-
-/*
-** CAPI3REF: Changegroup Handle
-**
-** A changegroup is an object used to combine two or more
-** [changesets] or [patchsets]
-*/
-typedef struct sqlite3_changegroup sqlite3_changegroup;
-
-/*
-** CAPI3REF: Create A New Changegroup Object
-** CONSTRUCTOR: sqlite3_changegroup
-**
-** An sqlite3_changegroup object is used to combine two or more changesets
-** (or patchsets) into a single changeset (or patchset). A single changegroup
-** object may combine changesets or patchsets, but not both. The output is
-** always in the same format as the input.
-**
-** If successful, this function returns SQLITE_OK and populates (*pp) with
-** a pointer to a new sqlite3_changegroup object before returning. The caller
-** should eventually free the returned object using a call to
-** sqlite3changegroup_delete(). If an error occurs, an SQLite error code
-** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL.
-**
-** The usual usage pattern for an sqlite3_changegroup object is as follows:
-**
-** <ul>
-** <li> It is created using a call to sqlite3changegroup_new().
-**
-** <li> Zero or more changesets (or patchsets) are added to the object
-** by calling sqlite3changegroup_add().
-**
-** <li> The result of combining all input changesets together is obtained
-** by the application via a call to sqlite3changegroup_output().
-**
-** <li> The object is deleted using a call to sqlite3changegroup_delete().
-** </ul>
-**
-** Any number of calls to add() and output() may be made between the calls to
-** new() and delete(), and in any order.
-**
-** As well as the regular sqlite3changegroup_add() and
-** sqlite3changegroup_output() functions, also available are the streaming
-** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
-*/
-int sqlite3changegroup_new(sqlite3_changegroup **pp);
-
-/*
-** CAPI3REF: Add A Changeset To A Changegroup
-** METHOD: sqlite3_changegroup
-**
-** Add all changes within the changeset (or patchset) in buffer pData (size
-** nData bytes) to the changegroup.
-**
-** If the buffer contains a patchset, then all prior calls to this function
-** on the same changegroup object must also have specified patchsets. Or, if
-** the buffer contains a changeset, so must have the earlier calls to this
-** function. Otherwise, SQLITE_ERROR is returned and no changes are added
-** to the changegroup.
-**
-** Rows within the changeset and changegroup are identified by the values in
-** their PRIMARY KEY columns. A change in the changeset is considered to
-** apply to the same row as a change already present in the changegroup if
-** the two rows have the same primary key.
-**
-** Changes to rows that do not already appear in the changegroup are
-** simply copied into it. Or, if both the new changeset and the changegroup
-** contain changes that apply to a single row, the final contents of the
-** changegroup depends on the type of each change, as follows:
-**
-** <table border=1 style="margin-left:8ex;margin-right:8ex">
-** <tr><th style="white-space:pre">Existing Change </th>
-** <th style="white-space:pre">New Change </th>
-** <th>Output Change
-** <tr><td>INSERT <td>INSERT <td>
-** The new change is ignored. This case does not occur if the new
-** changeset was recorded immediately after the changesets already
-** added to the changegroup.
-** <tr><td>INSERT <td>UPDATE <td>
-** The INSERT change remains in the changegroup. The values in the
-** INSERT change are modified as if the row was inserted by the
-** existing change and then updated according to the new change.
-** <tr><td>INSERT <td>DELETE <td>
-** The existing INSERT is removed from the changegroup. The DELETE is
-** not added.
-** <tr><td>UPDATE <td>INSERT <td>
-** The new change is ignored. This case does not occur if the new
-** changeset was recorded immediately after the changesets already
-** added to the changegroup.
-** <tr><td>UPDATE <td>UPDATE <td>
-** The existing UPDATE remains within the changegroup. It is amended
-** so that the accompanying values are as if the row was updated once
-** by the existing change and then again by the new change.
-** <tr><td>UPDATE <td>DELETE <td>
-** The existing UPDATE is replaced by the new DELETE within the
-** changegroup.
-** <tr><td>DELETE <td>INSERT <td>
-** If one or more of the column values in the row inserted by the
-** new change differ from those in the row deleted by the existing
-** change, the existing DELETE is replaced by an UPDATE within the
-** changegroup. Otherwise, if the inserted row is exactly the same
-** as the deleted row, the existing DELETE is simply discarded.
-** <tr><td>DELETE <td>UPDATE <td>
-** The new change is ignored. This case does not occur if the new
-** changeset was recorded immediately after the changesets already
-** added to the changegroup.
-** <tr><td>DELETE <td>DELETE <td>
-** The new change is ignored. This case does not occur if the new
-** changeset was recorded immediately after the changesets already
-** added to the changegroup.
-** </table>
-**
-** If the new changeset contains changes to a table that is already present
-** in the changegroup, then the number of columns and the position of the
-** primary key columns for the table must be consistent. If this is not the
-** case, this function fails with SQLITE_SCHEMA. If the input changeset
-** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
-** returned. Or, if an out-of-memory condition occurs during processing, this
-** function returns SQLITE_NOMEM. In all cases, if an error occurs the
-** final contents of the changegroup is undefined.
-**
-** If no error occurs, SQLITE_OK is returned.
-*/
-int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
-
-/*
-** CAPI3REF: Obtain A Composite Changeset From A Changegroup
-** METHOD: sqlite3_changegroup
-**
-** Obtain a buffer containing a changeset (or patchset) representing the
-** current contents of the changegroup. If the inputs to the changegroup
-** were themselves changesets, the output is a changeset. Or, if the
-** inputs were patchsets, the output is also a patchset.
-**
-** As with the output of the sqlite3session_changeset() and
-** sqlite3session_patchset() functions, all changes related to a single
-** table are grouped together in the output of this function. Tables appear
-** in the same order as for the very first changeset added to the changegroup.
-** If the second or subsequent changesets added to the changegroup contain
-** changes for tables that do not appear in the first changeset, they are
-** appended onto the end of the output changeset, again in the order in
-** which they are first encountered.
-**
-** If an error occurs, an SQLite error code is returned and the output
-** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK
-** is returned and the output variables are set to the size of and a
-** pointer to the output buffer, respectively. In this case it is the
-** responsibility of the caller to eventually free the buffer using a
-** call to sqlite3_free().
-*/
-int sqlite3changegroup_output(
- sqlite3_changegroup*,
- int *pnData, /* OUT: Size of output buffer in bytes */
- void **ppData /* OUT: Pointer to output buffer */
-);
-
-/*
-** CAPI3REF: Delete A Changegroup Object
-** DESTRUCTOR: sqlite3_changegroup
-*/
-void sqlite3changegroup_delete(sqlite3_changegroup*);
-
-/*
-** CAPI3REF: Apply A Changeset To A Database
-**
-** Apply a changeset or patchset to a database. These functions attempt to
-** update the "main" database attached to handle db with the changes found in
-** the changeset passed via the second and third arguments.
-**
-** The fourth argument (xFilter) passed to these functions is the "filter
-** callback". If it is not NULL, then for each table affected by at least one
-** change in the changeset, the filter callback is invoked with
-** the table name as the second argument, and a copy of the context pointer
-** passed as the sixth argument as the first. If the "filter callback"
-** returns zero, then no attempt is made to apply any changes to the table.
-** Otherwise, if the return value is non-zero or the xFilter argument to
-** is NULL, all changes related to the table are attempted.
-**
-** For each table that is not excluded by the filter callback, this function
-** tests that the target database contains a compatible table. A table is
-** considered compatible if all of the following are true:
-**
-** <ul>
-** <li> The table has the same name as the name recorded in the
-** changeset, and
-** <li> The table has at least as many columns as recorded in the
-** changeset, and
-** <li> The table has primary key columns in the same position as
-** recorded in the changeset.
-** </ul>
-**
-** If there is no compatible table, it is not an error, but none of the
-** changes associated with the table are applied. A warning message is issued
-** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most
-** one such warning is issued for each table in the changeset.
-**
-** For each change for which there is a compatible table, an attempt is made
-** to modify the table contents according to the UPDATE, INSERT or DELETE
-** change. If a change cannot be applied cleanly, the conflict handler
-** function passed as the fifth argument to sqlite3changeset_apply() may be
-** invoked. A description of exactly when the conflict handler is invoked for
-** each type of change is below.
-**
-** Unlike the xFilter argument, xConflict may not be passed NULL. The results
-** of passing anything other than a valid function pointer as the xConflict
-** argument are undefined.
-**
-** Each time the conflict handler function is invoked, it must return one
-** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or
-** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned
-** if the second argument passed to the conflict handler is either
-** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler
-** returns an illegal value, any changes already made are rolled back and
-** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different
-** actions are taken by sqlite3changeset_apply() depending on the value
-** returned by each invocation of the conflict-handler function. Refer to
-** the documentation for the three
-** [SQLITE_CHANGESET_OMIT|available return values] for details.
-**
-** <dl>
-** <dt>DELETE Changes<dd>
-** For each DELETE change, the function checks if the target database
-** contains a row with the same primary key value (or values) as the
-** original row values stored in the changeset. If it does, and the values
-** stored in all non-primary key columns also match the values stored in
-** the changeset the row is deleted from the target database.
-**
-** If a row with matching primary key values is found, but one or more of
-** the non-primary key fields contains a value different from the original
-** row value stored in the changeset, the conflict-handler function is
-** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the
-** database table has more columns than are recorded in the changeset,
-** only the values of those non-primary key fields are compared against
-** the current database contents - any trailing database table columns
-** are ignored.
-**
-** If no row with matching primary key values is found in the database,
-** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
-** passed as the second argument.
-**
-** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT
-** (which can only happen if a foreign key constraint is violated), the
-** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT]
-** passed as the second argument. This includes the case where the DELETE
-** operation is attempted because an earlier call to the conflict handler
-** function returned [SQLITE_CHANGESET_REPLACE].
-**
-** <dt>INSERT Changes<dd>
-** For each INSERT change, an attempt is made to insert the new row into
-** the database. If the changeset row contains fewer fields than the
-** database table, the trailing fields are populated with their default
-** values.
-**
-** If the attempt to insert the row fails because the database already
-** contains a row with the same primary key values, the conflict handler
-** function is invoked with the second argument set to
-** [SQLITE_CHANGESET_CONFLICT].
-**
-** If the attempt to insert the row fails because of some other constraint
-** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is
-** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT].
-** This includes the case where the INSERT operation is re-attempted because
-** an earlier call to the conflict handler function returned
-** [SQLITE_CHANGESET_REPLACE].
-**
-** <dt>UPDATE Changes<dd>
-** For each UPDATE change, the function checks if the target database
-** contains a row with the same primary key value (or values) as the
-** original row values stored in the changeset. If it does, and the values
-** stored in all modified non-primary key columns also match the values
-** stored in the changeset the row is updated within the target database.
-**
-** If a row with matching primary key values is found, but one or more of
-** the modified non-primary key fields contains a value different from an
-** original row value stored in the changeset, the conflict-handler function
-** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
-** UPDATE changes only contain values for non-primary key fields that are
-** to be modified, only those fields need to match the original values to
-** avoid the SQLITE_CHANGESET_DATA conflict-handler callback.
-**
-** If no row with matching primary key values is found in the database,
-** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
-** passed as the second argument.
-**
-** If the UPDATE operation is attempted, but SQLite returns
-** SQLITE_CONSTRAINT, the conflict-handler function is invoked with
-** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument.
-** This includes the case where the UPDATE operation is attempted after
-** an earlier call to the conflict handler function returned
-** [SQLITE_CHANGESET_REPLACE].
-** </dl>
-**
-** It is safe to execute SQL statements, including those that write to the
-** table that the callback related to, from within the xConflict callback.
-** This can be used to further customize the applications conflict
-** resolution strategy.
-**
-** All changes made by these functions are enclosed in a savepoint transaction.
-** If any other error (aside from a constraint failure when attempting to
-** write to the target database) occurs, then the savepoint transaction is
-** rolled back, restoring the target database to its original state, and an
-** SQLite error code returned.
-**
-** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
-** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
-** may set (*ppRebase) to point to a "rebase" that may be used with the
-** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
-** is set to the size of the buffer in bytes. It is the responsibility of the
-** caller to eventually free any such buffer using sqlite3_free(). The buffer
-** is only allocated and populated if one or more conflicts were encountered
-** while applying the patchset. See comments surrounding the sqlite3_rebaser
-** APIs for further details.
-**
-** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent
-** may be modified by passing a combination of
-** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter.
-**
-** Note that the sqlite3changeset_apply_v2() API is still <b>experimental</b>
-** and therefore subject to change.
-*/
-int sqlite3changeset_apply(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- int nChangeset, /* Size of changeset in bytes */
- void *pChangeset, /* Changeset blob */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx /* First argument passed to xConflict */
-);
-int sqlite3changeset_apply_v2(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- int nChangeset, /* Size of changeset in bytes */
- void *pChangeset, /* Changeset blob */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx, /* First argument passed to xConflict */
- void **ppRebase, int *pnRebase, /* OUT: Rebase data */
- int flags /* Combination of SESSION_APPLY_* flags */
-);
-
-/*
-** CAPI3REF: Flags for sqlite3changeset_apply_v2
-**
-** The following flags may passed via the 9th parameter to
-** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]:
-**
-** <dl>
-** <dt>SQLITE_CHANGESETAPPLY_NOSAVEPOINT <dd>
-** Usually, the sessions module encloses all operations performed by
-** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The
-** SAVEPOINT is committed if the changeset or patchset is successfully
-** applied, or rolled back if an error occurs. Specifying this flag
-** causes the sessions module to omit this savepoint. In this case, if the
-** caller has an open transaction or savepoint when apply_v2() is called,
-** it may revert the partially applied changeset by rolling it back.
-*/
-#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
-
-/*
-** CAPI3REF: Constants Passed To The Conflict Handler
-**
-** Values that may be passed as the second argument to a conflict-handler.
-**
-** <dl>
-** <dt>SQLITE_CHANGESET_DATA<dd>
-** The conflict handler is invoked with CHANGESET_DATA as the second argument
-** when processing a DELETE or UPDATE change if a row with the required
-** PRIMARY KEY fields is present in the database, but one or more other
-** (non primary-key) fields modified by the update do not contain the
-** expected "before" values.
-**
-** The conflicting row, in this case, is the database row with the matching
-** primary key.
-**
-** <dt>SQLITE_CHANGESET_NOTFOUND<dd>
-** The conflict handler is invoked with CHANGESET_NOTFOUND as the second
-** argument when processing a DELETE or UPDATE change if a row with the
-** required PRIMARY KEY fields is not present in the database.
-**
-** There is no conflicting row in this case. The results of invoking the
-** sqlite3changeset_conflict() API are undefined.
-**
-** <dt>SQLITE_CHANGESET_CONFLICT<dd>
-** CHANGESET_CONFLICT is passed as the second argument to the conflict
-** handler while processing an INSERT change if the operation would result
-** in duplicate primary key values.
-**
-** The conflicting row in this case is the database row with the matching
-** primary key.
-**
-** <dt>SQLITE_CHANGESET_FOREIGN_KEY<dd>
-** If foreign key handling is enabled, and applying a changeset leaves the
-** database in a state containing foreign key violations, the conflict
-** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument
-** exactly once before the changeset is committed. If the conflict handler
-** returns CHANGESET_OMIT, the changes, including those that caused the
-** foreign key constraint violation, are committed. Or, if it returns
-** CHANGESET_ABORT, the changeset is rolled back.
-**
-** No current or conflicting row information is provided. The only function
-** it is possible to call on the supplied sqlite3_changeset_iter handle
-** is sqlite3changeset_fk_conflicts().
-**
-** <dt>SQLITE_CHANGESET_CONSTRAINT<dd>
-** If any other constraint violation occurs while applying a change (i.e.
-** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is
-** invoked with CHANGESET_CONSTRAINT as the second argument.
-**
-** There is no conflicting row in this case. The results of invoking the
-** sqlite3changeset_conflict() API are undefined.
-**
-** </dl>
-*/
-#define SQLITE_CHANGESET_DATA 1
-#define SQLITE_CHANGESET_NOTFOUND 2
-#define SQLITE_CHANGESET_CONFLICT 3
-#define SQLITE_CHANGESET_CONSTRAINT 4
-#define SQLITE_CHANGESET_FOREIGN_KEY 5
-
-/*
-** CAPI3REF: Constants Returned By The Conflict Handler
-**
-** A conflict handler callback must return one of the following three values.
-**
-** <dl>
-** <dt>SQLITE_CHANGESET_OMIT<dd>
-** If a conflict handler returns this value no special action is taken. The
-** change that caused the conflict is not applied. The session module
-** continues to the next change in the changeset.
-**
-** <dt>SQLITE_CHANGESET_REPLACE<dd>
-** This value may only be returned if the second argument to the conflict
-** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this
-** is not the case, any changes applied so far are rolled back and the
-** call to sqlite3changeset_apply() returns SQLITE_MISUSE.
-**
-** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict
-** handler, then the conflicting row is either updated or deleted, depending
-** on the type of change.
-**
-** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_CONFLICT conflict
-** handler, then the conflicting row is removed from the database and a
-** second attempt to apply the change is made. If this second attempt fails,
-** the original row is restored to the database before continuing.
-**
-** <dt>SQLITE_CHANGESET_ABORT<dd>
-** If this value is returned, any changes applied so far are rolled back
-** and the call to sqlite3changeset_apply() returns SQLITE_ABORT.
-** </dl>
-*/
-#define SQLITE_CHANGESET_OMIT 0
-#define SQLITE_CHANGESET_REPLACE 1
-#define SQLITE_CHANGESET_ABORT 2
-
-/*
-** CAPI3REF: Rebasing changesets
-** EXPERIMENTAL
-**
-** Suppose there is a site hosting a database in state S0. And that
-** modifications are made that move that database to state S1 and a
-** changeset recorded (the "local" changeset). Then, a changeset based
-** on S0 is received from another site (the "remote" changeset) and
-** applied to the database. The database is then in state
-** (S1+"remote"), where the exact state depends on any conflict
-** resolution decisions (OMIT or REPLACE) made while applying "remote".
-** Rebasing a changeset is to update it to take those conflict
-** resolution decisions into account, so that the same conflicts
-** do not have to be resolved elsewhere in the network.
-**
-** For example, if both the local and remote changesets contain an
-** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)":
-**
-** local: INSERT INTO t1 VALUES(1, 'v1');
-** remote: INSERT INTO t1 VALUES(1, 'v2');
-**
-** and the conflict resolution is REPLACE, then the INSERT change is
-** removed from the local changeset (it was overridden). Or, if the
-** conflict resolution was "OMIT", then the local changeset is modified
-** to instead contain:
-**
-** UPDATE t1 SET b = 'v2' WHERE a=1;
-**
-** Changes within the local changeset are rebased as follows:
-**
-** <dl>
-** <dt>Local INSERT<dd>
-** This may only conflict with a remote INSERT. If the conflict
-** resolution was OMIT, then add an UPDATE change to the rebased
-** changeset. Or, if the conflict resolution was REPLACE, add
-** nothing to the rebased changeset.
-**
-** <dt>Local DELETE<dd>
-** This may conflict with a remote UPDATE or DELETE. In both cases the
-** only possible resolution is OMIT. If the remote operation was a
-** DELETE, then add no change to the rebased changeset. If the remote
-** operation was an UPDATE, then the old.* fields of change are updated
-** to reflect the new.* values in the UPDATE.
-**
-** <dt>Local UPDATE<dd>
-** This may conflict with a remote UPDATE or DELETE. If it conflicts
-** with a DELETE, and the conflict resolution was OMIT, then the update
-** is changed into an INSERT. Any undefined values in the new.* record
-** from the update change are filled in using the old.* values from
-** the conflicting DELETE. Or, if the conflict resolution was REPLACE,
-** the UPDATE change is simply omitted from the rebased changeset.
-**
-** If conflict is with a remote UPDATE and the resolution is OMIT, then
-** the old.* values are rebased using the new.* values in the remote
-** change. Or, if the resolution is REPLACE, then the change is copied
-** into the rebased changeset with updates to columns also updated by
-** the conflicting remote UPDATE removed. If this means no columns would
-** be updated, the change is omitted.
-** </dl>
-**
-** A local change may be rebased against multiple remote changes
-** simultaneously. If a single key is modified by multiple remote
-** changesets, they are combined as follows before the local changeset
-** is rebased:
-**
-** <ul>
-** <li> If there has been one or more REPLACE resolutions on a
-** key, it is rebased according to a REPLACE.
-**
-** <li> If there have been no REPLACE resolutions on a key, then
-** the local changeset is rebased according to the most recent
-** of the OMIT resolutions.
-** </ul>
-**
-** Note that conflict resolutions from multiple remote changesets are
-** combined on a per-field basis, not per-row. This means that in the
-** case of multiple remote UPDATE operations, some fields of a single
-** local change may be rebased for REPLACE while others are rebased for
-** OMIT.
-**
-** In order to rebase a local changeset, the remote changeset must first
-** be applied to the local database using sqlite3changeset_apply_v2() and
-** the buffer of rebase information captured. Then:
-**
-** <ol>
-** <li> An sqlite3_rebaser object is created by calling
-** sqlite3rebaser_create().
-** <li> The new object is configured with the rebase buffer obtained from
-** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure().
-** If the local changeset is to be rebased against multiple remote
-** changesets, then sqlite3rebaser_configure() should be called
-** multiple times, in the same order that the multiple
-** sqlite3changeset_apply_v2() calls were made.
-** <li> Each local changeset is rebased by calling sqlite3rebaser_rebase().
-** <li> The sqlite3_rebaser object is deleted by calling
-** sqlite3rebaser_delete().
-** </ol>
-*/
-typedef struct sqlite3_rebaser sqlite3_rebaser;
-
-/*
-** CAPI3REF: Create a changeset rebaser object.
-** EXPERIMENTAL
-**
-** Allocate a new changeset rebaser object. If successful, set (*ppNew) to
-** point to the new object and return SQLITE_OK. Otherwise, if an error
-** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew)
-** to NULL.
-*/
-int sqlite3rebaser_create(sqlite3_rebaser **ppNew);
-
-/*
-** CAPI3REF: Configure a changeset rebaser object.
-** EXPERIMENTAL
-**
-** Configure the changeset rebaser object to rebase changesets according
-** to the conflict resolutions described by buffer pRebase (size nRebase
-** bytes), which must have been obtained from a previous call to
-** sqlite3changeset_apply_v2().
-*/
-int sqlite3rebaser_configure(
- sqlite3_rebaser*,
- int nRebase, const void *pRebase
-);
-
-/*
-** CAPI3REF: Rebase a changeset
-** EXPERIMENTAL
-**
-** Argument pIn must point to a buffer containing a changeset nIn bytes
-** in size. This function allocates and populates a buffer with a copy
-** of the changeset rebased rebased according to the configuration of the
-** rebaser object passed as the first argument. If successful, (*ppOut)
-** is set to point to the new buffer containing the rebased changset and
-** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
-** responsibility of the caller to eventually free the new buffer using
-** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut)
-** are set to zero and an SQLite error code returned.
-*/
-int sqlite3rebaser_rebase(
- sqlite3_rebaser*,
- int nIn, const void *pIn,
- int *pnOut, void **ppOut
-);
-
-/*
-** CAPI3REF: Delete a changeset rebaser object.
-** EXPERIMENTAL
-**
-** Delete the changeset rebaser object and all associated resources. There
-** should be one call to this function for each successful invocation
-** of sqlite3rebaser_create().
-*/
-void sqlite3rebaser_delete(sqlite3_rebaser *p);
-
-/*
-** CAPI3REF: Streaming Versions of API functions.
-**
-** The six streaming API xxx_strm() functions serve similar purposes to the
-** corresponding non-streaming API functions:
-**
-** <table border=1 style="margin-left:8ex;margin-right:8ex">
-** <tr><th>Streaming function<th>Non-streaming equivalent</th>
-** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply]
-** <tr><td>sqlite3changeset_apply_strm_v2<td>[sqlite3changeset_apply_v2]
-** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat]
-** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert]
-** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start]
-** <tr><td>sqlite3session_changeset_strm<td>[sqlite3session_changeset]
-** <tr><td>sqlite3session_patchset_strm<td>[sqlite3session_patchset]
-** </table>
-**
-** Non-streaming functions that accept changesets (or patchsets) as input
-** require that the entire changeset be stored in a single buffer in memory.
-** Similarly, those that return a changeset or patchset do so by returning
-** a pointer to a single large buffer allocated using sqlite3_malloc().
-** Normally this is convenient. However, if an application running in a
-** low-memory environment is required to handle very large changesets, the
-** large contiguous memory allocations required can become onerous.
-**
-** In order to avoid this problem, instead of a single large buffer, input
-** is passed to a streaming API functions by way of a callback function that
-** the sessions module invokes to incrementally request input data as it is
-** required. In all cases, a pair of API function parameters such as
-**
-** <pre>
-** &nbsp; int nChangeset,
-** &nbsp; void *pChangeset,
-** </pre>
-**
-** Is replaced by:
-**
-** <pre>
-** &nbsp; int (*xInput)(void *pIn, void *pData, int *pnData),
-** &nbsp; void *pIn,
-** </pre>
-**
-** Each time the xInput callback is invoked by the sessions module, the first
-** argument passed is a copy of the supplied pIn context pointer. The second
-** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no
-** error occurs the xInput method should copy up to (*pnData) bytes of data
-** into the buffer and set (*pnData) to the actual number of bytes copied
-** before returning SQLITE_OK. If the input is completely exhausted, (*pnData)
-** should be set to zero to indicate this. Or, if an error occurs, an SQLite
-** error code should be returned. In all cases, if an xInput callback returns
-** an error, all processing is abandoned and the streaming API function
-** returns a copy of the error code to the caller.
-**
-** In the case of sqlite3changeset_start_strm(), the xInput callback may be
-** invoked by the sessions module at any point during the lifetime of the
-** iterator. If such an xInput callback returns an error, the iterator enters
-** an error state, whereby all subsequent calls to iterator functions
-** immediately fail with the same error code as returned by xInput.
-**
-** Similarly, streaming API functions that return changesets (or patchsets)
-** return them in chunks by way of a callback function instead of via a
-** pointer to a single large buffer. In this case, a pair of parameters such
-** as:
-**
-** <pre>
-** &nbsp; int *pnChangeset,
-** &nbsp; void **ppChangeset,
-** </pre>
-**
-** Is replaced by:
-**
-** <pre>
-** &nbsp; int (*xOutput)(void *pOut, const void *pData, int nData),
-** &nbsp; void *pOut
-** </pre>
-**
-** The xOutput callback is invoked zero or more times to return data to
-** the application. The first parameter passed to each call is a copy of the
-** pOut pointer supplied by the application. The second parameter, pData,
-** points to a buffer nData bytes in size containing the chunk of output
-** data being returned. If the xOutput callback successfully processes the
-** supplied data, it should return SQLITE_OK to indicate success. Otherwise,
-** it should return some other SQLite error code. In this case processing
-** is immediately abandoned and the streaming API function returns a copy
-** of the xOutput error code to the application.
-**
-** The sessions module never invokes an xOutput callback with the third
-** parameter set to a value less than or equal to zero. Other than this,
-** no guarantees are made as to the size of the chunks of data returned.
-*/
-int sqlite3changeset_apply_strm(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
- void *pIn, /* First arg for xInput */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx /* First argument passed to xConflict */
-);
-int sqlite3changeset_apply_v2_strm(
- sqlite3 *db, /* Apply change to "main" db of this handle */
- int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
- void *pIn, /* First arg for xInput */
- int(*xFilter)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- const char *zTab /* Table name */
- ),
- int(*xConflict)(
- void *pCtx, /* Copy of sixth arg to _apply() */
- int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *p /* Handle describing change and conflict */
- ),
- void *pCtx, /* First argument passed to xConflict */
- void **ppRebase, int *pnRebase,
- int flags
-);
-int sqlite3changeset_concat_strm(
- int (*xInputA)(void *pIn, void *pData, int *pnData),
- void *pInA,
- int (*xInputB)(void *pIn, void *pData, int *pnData),
- void *pInB,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-);
-int sqlite3changeset_invert_strm(
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-);
-int sqlite3changeset_start_strm(
- sqlite3_changeset_iter **pp,
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn
-);
-int sqlite3session_changeset_strm(
- sqlite3_session *pSession,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-);
-int sqlite3session_patchset_strm(
- sqlite3_session *pSession,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-);
-int sqlite3changegroup_add_strm(sqlite3_changegroup*,
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn
-);
-int sqlite3changegroup_output_strm(sqlite3_changegroup*,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-);
-int sqlite3rebaser_rebase_strm(
- sqlite3_rebaser *pRebaser,
- int (*xInput)(void *pIn, void *pData, int *pnData),
- void *pIn,
- int (*xOutput)(void *pOut, const void *pData, int nData),
- void *pOut
-);
-
-
-/*
-** Make sure we can call this stuff from C++.
-*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/test_session.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/test_session.c
deleted file mode 100644
index 3b6c24fd118..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/session/test_session.c
+++ /dev/null
@@ -1,1231 +0,0 @@
-
-#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_SESSION) \
- && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
-
-#include "sqlite3session.h"
-#include <assert.h>
-#include <string.h>
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-#ifndef SQLITE_AMALGAMATION
- typedef unsigned char u8;
-#endif
-
-typedef struct TestSession TestSession;
-struct TestSession {
- sqlite3_session *pSession;
- Tcl_Interp *interp;
- Tcl_Obj *pFilterScript;
-};
-
-typedef struct TestStreamInput TestStreamInput;
-struct TestStreamInput {
- int nStream; /* Maximum chunk size */
- unsigned char *aData; /* Pointer to buffer containing data */
- int nData; /* Size of buffer aData in bytes */
- int iData; /* Bytes of data already read by sessions */
-};
-
-/*
-** Extract an sqlite3* db handle from the object passed as the second
-** argument. If successful, set *pDb to point to the db handle and return
-** TCL_OK. Otherwise, return TCL_ERROR.
-*/
-static int dbHandleFromObj(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
- Tcl_CmdInfo info;
- if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(pObj), &info) ){
- Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
- return TCL_ERROR;
- }
-
- *pDb = *(sqlite3 **)info.objClientData;
- return TCL_OK;
-}
-
-/*************************************************************************
-** The following code is copied byte-for-byte from the sessions module
-** documentation. It is used by some of the sessions modules tests to
-** ensure that the example in the documentation does actually work.
-*/
-/*
-** Argument zSql points to a buffer containing an SQL script to execute
-** against the database handle passed as the first argument. As well as
-** executing the SQL script, this function collects a changeset recording
-** all changes made to the "main" database file. Assuming no error occurs,
-** output variables (*ppChangeset) and (*pnChangeset) are set to point
-** to a buffer containing the changeset and the size of the changeset in
-** bytes before returning SQLITE_OK. In this case it is the responsibility
-** of the caller to eventually free the changeset blob by passing it to
-** the sqlite3_free function.
-**
-** Or, if an error does occur, return an SQLite error code. The final
-** value of (*pChangeset) and (*pnChangeset) are undefined in this case.
-*/
-int sql_exec_changeset(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL script to execute */
- int *pnChangeset, /* OUT: Size of changeset blob in bytes */
- void **ppChangeset /* OUT: Pointer to changeset blob */
-){
- sqlite3_session *pSession = 0;
- int rc;
-
- /* Create a new session object */
- rc = sqlite3session_create(db, "main", &pSession);
-
- /* Configure the session object to record changes to all tables */
- if( rc==SQLITE_OK ) rc = sqlite3session_attach(pSession, NULL);
-
- /* Execute the SQL script */
- if( rc==SQLITE_OK ) rc = sqlite3_exec(db, zSql, 0, 0, 0);
-
- /* Collect the changeset */
- if( rc==SQLITE_OK ){
- rc = sqlite3session_changeset(pSession, pnChangeset, ppChangeset);
- }
-
- /* Delete the session object */
- sqlite3session_delete(pSession);
-
- return rc;
-}
-/************************************************************************/
-
-/*
-** Tclcmd: sql_exec_changeset DB SQL
-*/
-static int SQLITE_TCLAPI test_sql_exec_changeset(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zSql;
- sqlite3 *db;
- void *pChangeset;
- int nChangeset;
- int rc;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB SQL");
- return TCL_ERROR;
- }
- if( dbHandleFromObj(interp, objv[1], &db) ) return TCL_ERROR;
- zSql = (const char*)Tcl_GetString(objv[2]);
-
- rc = sql_exec_changeset(db, zSql, &nChangeset, &pChangeset);
- if( rc!=SQLITE_OK ){
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "error in sql_exec_changeset()", 0);
- return TCL_ERROR;
- }
-
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pChangeset, nChangeset));
- sqlite3_free(pChangeset);
- return TCL_OK;
-}
-
-
-
-#define SESSION_STREAM_TCL_VAR "sqlite3session_streams"
-
-/*
-** Attempt to find the global variable zVar within interpreter interp
-** and extract an integer value from it. Return this value.
-**
-** If the named variable cannot be found, or if it cannot be interpreted
-** as a integer, return 0.
-*/
-static int test_tcl_integer(Tcl_Interp *interp, const char *zVar){
- Tcl_Obj *pObj;
- int iVal = 0;
- pObj = Tcl_ObjGetVar2(interp, Tcl_NewStringObj(zVar, -1), 0, TCL_GLOBAL_ONLY);
- if( pObj ) Tcl_GetIntFromObj(0, pObj, &iVal);
- return iVal;
-}
-
-static int test_session_error(Tcl_Interp *interp, int rc, char *zErr){
- extern const char *sqlite3ErrName(int);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- if( zErr ){
- Tcl_AppendResult(interp, " - ", zErr, 0);
- sqlite3_free(zErr);
- }
- return TCL_ERROR;
-}
-
-static int test_table_filter(void *pCtx, const char *zTbl){
- TestSession *p = (TestSession*)pCtx;
- Tcl_Obj *pEval;
- int rc;
- int bRes = 0;
-
- pEval = Tcl_DuplicateObj(p->pFilterScript);
- Tcl_IncrRefCount(pEval);
- rc = Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zTbl, -1));
- if( rc==TCL_OK ){
- rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
- }
- if( rc==TCL_OK ){
- rc = Tcl_GetBooleanFromObj(p->interp, Tcl_GetObjResult(p->interp), &bRes);
- }
- if( rc!=TCL_OK ){
- /* printf("error: %s\n", Tcl_GetStringResult(p->interp)); */
- Tcl_BackgroundError(p->interp);
- }
- Tcl_DecrRefCount(pEval);
-
- return bRes;
-}
-
-struct TestSessionsBlob {
- void *p;
- int n;
-};
-typedef struct TestSessionsBlob TestSessionsBlob;
-
-static int testStreamOutput(
- void *pCtx,
- const void *pData,
- int nData
-){
- TestSessionsBlob *pBlob = (TestSessionsBlob*)pCtx;
- char *pNew;
-
- assert( nData>0 );
- pNew = (char*)sqlite3_realloc(pBlob->p, pBlob->n + nData);
- if( pNew==0 ){
- return SQLITE_NOMEM;
- }
- pBlob->p = (void*)pNew;
- memcpy(&pNew[pBlob->n], pData, nData);
- pBlob->n += nData;
- return SQLITE_OK;
-}
-
-/*
-** Tclcmd: $session attach TABLE
-** $session changeset
-** $session delete
-** $session enable BOOL
-** $session indirect INTEGER
-** $session patchset
-** $session table_filter SCRIPT
-*/
-static int SQLITE_TCLAPI test_session_cmd(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- TestSession *p = (TestSession*)clientData;
- sqlite3_session *pSession = p->pSession;
- struct SessionSubcmd {
- const char *zSub;
- int nArg;
- const char *zMsg;
- int iSub;
- } aSub[] = {
- { "attach", 1, "TABLE", }, /* 0 */
- { "changeset", 0, "", }, /* 1 */
- { "delete", 0, "", }, /* 2 */
- { "enable", 1, "BOOL", }, /* 3 */
- { "indirect", 1, "BOOL", }, /* 4 */
- { "isempty", 0, "", }, /* 5 */
- { "table_filter", 1, "SCRIPT", }, /* 6 */
- { "patchset", 0, "", }, /* 7 */
- { "diff", 2, "FROMDB TBL", }, /* 8 */
- { 0 }
- };
- int iSub;
- int rc;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
- return TCL_ERROR;
- }
- rc = Tcl_GetIndexFromObjStruct(interp,
- objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
- );
- if( rc!=TCL_OK ) return rc;
- if( objc!=2+aSub[iSub].nArg ){
- Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg);
- return TCL_ERROR;
- }
-
- switch( iSub ){
- case 0: { /* attach */
- char *zArg = Tcl_GetString(objv[2]);
- if( zArg[0]=='*' && zArg[1]=='\0' ) zArg = 0;
- rc = sqlite3session_attach(pSession, zArg);
- if( rc!=SQLITE_OK ){
- return test_session_error(interp, rc, 0);
- }
- break;
- }
-
- case 7: /* patchset */
- case 1: { /* changeset */
- TestSessionsBlob o = {0, 0};
- if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
- void *pCtx = (void*)&o;
- if( iSub==7 ){
- rc = sqlite3session_patchset_strm(pSession, testStreamOutput, pCtx);
- }else{
- rc = sqlite3session_changeset_strm(pSession, testStreamOutput, pCtx);
- }
- }else{
- if( iSub==7 ){
- rc = sqlite3session_patchset(pSession, &o.n, &o.p);
- }else{
- rc = sqlite3session_changeset(pSession, &o.n, &o.p);
- }
- }
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(o.p, o.n));
- }
- sqlite3_free(o.p);
- if( rc!=SQLITE_OK ){
- return test_session_error(interp, rc, 0);
- }
- break;
- }
-
- case 2: /* delete */
- Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
- break;
-
- case 3: { /* enable */
- int val;
- if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR;
- val = sqlite3session_enable(pSession, val);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val));
- break;
- }
-
- case 4: { /* indirect */
- int val;
- if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR;
- val = sqlite3session_indirect(pSession, val);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val));
- break;
- }
-
- case 5: { /* isempty */
- int val;
- val = sqlite3session_isempty(pSession);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val));
- break;
- }
-
- case 6: { /* table_filter */
- if( p->pFilterScript ) Tcl_DecrRefCount(p->pFilterScript);
- p->interp = interp;
- p->pFilterScript = Tcl_DuplicateObj(objv[2]);
- Tcl_IncrRefCount(p->pFilterScript);
- sqlite3session_table_filter(pSession, test_table_filter, clientData);
- break;
- }
-
- case 8: { /* diff */
- char *zErr = 0;
- rc = sqlite3session_diff(pSession,
- Tcl_GetString(objv[2]),
- Tcl_GetString(objv[3]),
- &zErr
- );
- assert( rc!=SQLITE_OK || zErr==0 );
- if( rc ){
- return test_session_error(interp, rc, zErr);
- }
- break;
- }
- }
-
- return TCL_OK;
-}
-
-static void SQLITE_TCLAPI test_session_del(void *clientData){
- TestSession *p = (TestSession*)clientData;
- if( p->pFilterScript ) Tcl_DecrRefCount(p->pFilterScript);
- sqlite3session_delete(p->pSession);
- ckfree((char*)p);
-}
-
-/*
-** Tclcmd: sqlite3session CMD DB-HANDLE DB-NAME
-*/
-static int SQLITE_TCLAPI test_sqlite3session(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- Tcl_CmdInfo info;
- int rc; /* sqlite3session_create() return code */
- TestSession *p; /* New wrapper object */
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "CMD DB-HANDLE DB-NAME");
- return TCL_ERROR;
- }
-
- if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ){
- Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[2]), 0);
- return TCL_ERROR;
- }
- db = *(sqlite3 **)info.objClientData;
-
- p = (TestSession*)ckalloc(sizeof(TestSession));
- memset(p, 0, sizeof(TestSession));
- rc = sqlite3session_create(db, Tcl_GetString(objv[3]), &p->pSession);
- if( rc!=SQLITE_OK ){
- ckfree((char*)p);
- return test_session_error(interp, rc, 0);
- }
-
- Tcl_CreateObjCommand(
- interp, Tcl_GetString(objv[1]), test_session_cmd, (ClientData)p,
- test_session_del
- );
- Tcl_SetObjResult(interp, objv[1]);
- return TCL_OK;
-}
-
-static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){
- if( pVal==0 ){
- Tcl_ListObjAppendElement(0, pList, Tcl_NewObj());
- Tcl_ListObjAppendElement(0, pList, Tcl_NewObj());
- }else{
- Tcl_Obj *pObj;
- switch( sqlite3_value_type(pVal) ){
- case SQLITE_NULL:
- Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("n", 1));
- pObj = Tcl_NewObj();
- break;
- case SQLITE_INTEGER:
- Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("i", 1));
- pObj = Tcl_NewWideIntObj(sqlite3_value_int64(pVal));
- break;
- case SQLITE_FLOAT:
- Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("f", 1));
- pObj = Tcl_NewDoubleObj(sqlite3_value_double(pVal));
- break;
- case SQLITE_TEXT: {
- const char *z = (char*)sqlite3_value_blob(pVal);
- int n = sqlite3_value_bytes(pVal);
- Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("t", 1));
- pObj = Tcl_NewStringObj(z, n);
- break;
- }
- default:
- assert( sqlite3_value_type(pVal)==SQLITE_BLOB );
- Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("b", 1));
- pObj = Tcl_NewByteArrayObj(
- sqlite3_value_blob(pVal),
- sqlite3_value_bytes(pVal)
- );
- break;
- }
- Tcl_ListObjAppendElement(0, pList, pObj);
- }
-}
-
-typedef struct TestConflictHandler TestConflictHandler;
-struct TestConflictHandler {
- Tcl_Interp *interp;
- Tcl_Obj *pConflictScript;
- Tcl_Obj *pFilterScript;
-};
-
-static int test_obj_eq_string(Tcl_Obj *p, const char *z){
- int n;
- int nObj;
- char *zObj;
-
- n = (int)strlen(z);
- zObj = Tcl_GetStringFromObj(p, &nObj);
-
- return (nObj==n && (n==0 || 0==memcmp(zObj, z, n)));
-}
-
-static int test_filter_handler(
- void *pCtx, /* Pointer to TestConflictHandler structure */
- const char *zTab /* Table name */
-){
- TestConflictHandler *p = (TestConflictHandler *)pCtx;
- int res = 1;
- Tcl_Obj *pEval;
- Tcl_Interp *interp = p->interp;
-
- pEval = Tcl_DuplicateObj(p->pFilterScript);
- Tcl_IncrRefCount(pEval);
-
- if( TCL_OK!=Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(zTab, -1))
- || TCL_OK!=Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL)
- || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &res)
- ){
- Tcl_BackgroundError(interp);
- }
-
- Tcl_DecrRefCount(pEval);
- return res;
-}
-
-static int test_conflict_handler(
- void *pCtx, /* Pointer to TestConflictHandler structure */
- int eConf, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *pIter /* Handle describing change and conflict */
-){
- TestConflictHandler *p = (TestConflictHandler *)pCtx;
- Tcl_Obj *pEval;
- Tcl_Interp *interp = p->interp;
- int ret = 0; /* Return value */
-
- int op; /* SQLITE_UPDATE, DELETE or INSERT */
- const char *zTab; /* Name of table conflict is on */
- int nCol; /* Number of columns in table zTab */
-
- pEval = Tcl_DuplicateObj(p->pConflictScript);
- Tcl_IncrRefCount(pEval);
-
- sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0);
-
- if( eConf==SQLITE_CHANGESET_FOREIGN_KEY ){
- int nFk;
- sqlite3changeset_fk_conflicts(pIter, &nFk);
- Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj("FOREIGN_KEY", -1));
- Tcl_ListObjAppendElement(0, pEval, Tcl_NewIntObj(nFk));
- }else{
-
- /* Append the operation type. */
- Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(
- op==SQLITE_INSERT ? "INSERT" :
- op==SQLITE_UPDATE ? "UPDATE" :
- "DELETE", -1
- ));
-
- /* Append the table name. */
- Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(zTab, -1));
-
- /* Append the conflict type. */
- switch( eConf ){
- case SQLITE_CHANGESET_DATA:
- Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("DATA",-1));
- break;
- case SQLITE_CHANGESET_NOTFOUND:
- Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("NOTFOUND",-1));
- break;
- case SQLITE_CHANGESET_CONFLICT:
- Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("CONFLICT",-1));
- break;
- case SQLITE_CHANGESET_CONSTRAINT:
- Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("CONSTRAINT",-1));
- break;
- }
-
- /* If this is not an INSERT, append the old row */
- if( op!=SQLITE_INSERT ){
- int i;
- Tcl_Obj *pOld = Tcl_NewObj();
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- sqlite3changeset_old(pIter, i, &pVal);
- test_append_value(pOld, pVal);
- }
- Tcl_ListObjAppendElement(0, pEval, pOld);
- }
-
- /* If this is not a DELETE, append the new row */
- if( op!=SQLITE_DELETE ){
- int i;
- Tcl_Obj *pNew = Tcl_NewObj();
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- sqlite3changeset_new(pIter, i, &pVal);
- test_append_value(pNew, pVal);
- }
- Tcl_ListObjAppendElement(0, pEval, pNew);
- }
-
- /* If this is a CHANGESET_DATA or CHANGESET_CONFLICT conflict, append
- ** the conflicting row. */
- if( eConf==SQLITE_CHANGESET_DATA || eConf==SQLITE_CHANGESET_CONFLICT ){
- int i;
- Tcl_Obj *pConflict = Tcl_NewObj();
- for(i=0; i<nCol; i++){
- int rc;
- sqlite3_value *pVal;
- rc = sqlite3changeset_conflict(pIter, i, &pVal);
- assert( rc==SQLITE_OK );
- test_append_value(pConflict, pVal);
- }
- Tcl_ListObjAppendElement(0, pEval, pConflict);
- }
-
- /***********************************************************************
- ** This block is purely for testing some error conditions.
- */
- if( eConf==SQLITE_CHANGESET_CONSTRAINT
- || eConf==SQLITE_CHANGESET_NOTFOUND
- ){
- sqlite3_value *pVal;
- int rc = sqlite3changeset_conflict(pIter, 0, &pVal);
- assert( rc==SQLITE_MISUSE );
- }else{
- sqlite3_value *pVal;
- int rc = sqlite3changeset_conflict(pIter, -1, &pVal);
- assert( rc==SQLITE_RANGE );
- rc = sqlite3changeset_conflict(pIter, nCol, &pVal);
- assert( rc==SQLITE_RANGE );
- }
- if( op==SQLITE_DELETE ){
- sqlite3_value *pVal;
- int rc = sqlite3changeset_new(pIter, 0, &pVal);
- assert( rc==SQLITE_MISUSE );
- }else{
- sqlite3_value *pVal;
- int rc = sqlite3changeset_new(pIter, -1, &pVal);
- assert( rc==SQLITE_RANGE );
- rc = sqlite3changeset_new(pIter, nCol, &pVal);
- assert( rc==SQLITE_RANGE );
- }
- if( op==SQLITE_INSERT ){
- sqlite3_value *pVal;
- int rc = sqlite3changeset_old(pIter, 0, &pVal);
- assert( rc==SQLITE_MISUSE );
- }else{
- sqlite3_value *pVal;
- int rc = sqlite3changeset_old(pIter, -1, &pVal);
- assert( rc==SQLITE_RANGE );
- rc = sqlite3changeset_old(pIter, nCol, &pVal);
- assert( rc==SQLITE_RANGE );
- }
- if( eConf!=SQLITE_CHANGESET_FOREIGN_KEY ){
- /* eConf!=FOREIGN_KEY is always true at this point. The condition is
- ** just there to make it clearer what is being tested. */
- int nDummy;
- int rc = sqlite3changeset_fk_conflicts(pIter, &nDummy);
- assert( rc==SQLITE_MISUSE );
- }
- /* End of testing block
- ***********************************************************************/
- }
-
- if( TCL_OK!=Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL) ){
- Tcl_BackgroundError(interp);
- }else{
- Tcl_Obj *pRes = Tcl_GetObjResult(interp);
- if( test_obj_eq_string(pRes, "OMIT") || test_obj_eq_string(pRes, "") ){
- ret = SQLITE_CHANGESET_OMIT;
- }else if( test_obj_eq_string(pRes, "REPLACE") ){
- ret = SQLITE_CHANGESET_REPLACE;
- }else if( test_obj_eq_string(pRes, "ABORT") ){
- ret = SQLITE_CHANGESET_ABORT;
- }else{
- Tcl_GetIntFromObj(0, pRes, &ret);
- }
- }
-
- Tcl_DecrRefCount(pEval);
- return ret;
-}
-
-/*
-** The conflict handler used by sqlite3changeset_apply_replace_all().
-** This conflict handler calls sqlite3_value_text16() on all available
-** sqlite3_value objects and then returns CHANGESET_REPLACE, or
-** CHANGESET_OMIT if REPLACE is not applicable. This is used to test the
-** effect of a malloc failure within an sqlite3_value_xxx() function
-** invoked by a conflict-handler callback.
-*/
-static int replace_handler(
- void *pCtx, /* Pointer to TestConflictHandler structure */
- int eConf, /* DATA, MISSING, CONFLICT, CONSTRAINT */
- sqlite3_changeset_iter *pIter /* Handle describing change and conflict */
-){
- int op; /* SQLITE_UPDATE, DELETE or INSERT */
- const char *zTab; /* Name of table conflict is on */
- int nCol; /* Number of columns in table zTab */
- int i;
- int x = 0;
-
- sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0);
-
- if( op!=SQLITE_INSERT ){
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- sqlite3changeset_old(pIter, i, &pVal);
- sqlite3_value_text16(pVal);
- x++;
- }
- }
-
- if( op!=SQLITE_DELETE ){
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- sqlite3changeset_new(pIter, i, &pVal);
- sqlite3_value_text16(pVal);
- x++;
- }
- }
-
- if( eConf==SQLITE_CHANGESET_DATA ){
- return SQLITE_CHANGESET_REPLACE;
- }
- return SQLITE_CHANGESET_OMIT;
-}
-
-static int testStreamInput(
- void *pCtx, /* Context pointer */
- void *pData, /* Buffer to populate */
- int *pnData /* IN/OUT: Bytes requested/supplied */
-){
- TestStreamInput *p = (TestStreamInput*)pCtx;
- int nReq = *pnData; /* Bytes of data requested */
- int nRem = p->nData - p->iData; /* Bytes of data available */
- int nRet = p->nStream; /* Bytes actually returned */
-
- /* Allocate and free some space. There is no point to this, other than
- ** that it allows the regular OOM fault-injection tests to cause an error
- ** in this function. */
- void *pAlloc = sqlite3_malloc(10);
- if( pAlloc==0 ) return SQLITE_NOMEM;
- sqlite3_free(pAlloc);
-
- if( nRet>nReq ) nRet = nReq;
- if( nRet>nRem ) nRet = nRem;
-
- assert( nRet>=0 );
- if( nRet>0 ){
- memcpy(pData, &p->aData[p->iData], nRet);
- p->iData += nRet;
- }
-
- *pnData = nRet;
- return SQLITE_OK;
-}
-
-
-static int SQLITE_TCLAPI testSqlite3changesetApply(
- int bV2,
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db; /* Database handle */
- Tcl_CmdInfo info; /* Database Tcl command (objv[1]) info */
- int rc; /* Return code from changeset_invert() */
- void *pChangeset; /* Buffer containing changeset */
- int nChangeset; /* Size of buffer aChangeset in bytes */
- TestConflictHandler ctx;
- TestStreamInput sStr;
- void *pRebase = 0;
- int nRebase = 0;
- int flags = 0; /* Flags for apply_v2() */
-
- memset(&sStr, 0, sizeof(sStr));
- sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
-
- /* Check for the -nosavepoint flag */
- if( bV2 && objc>1 ){
- const char *z1 = Tcl_GetString(objv[1]);
- int n = strlen(z1);
- if( n>1 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){
- flags = SQLITE_CHANGESETAPPLY_NOSAVEPOINT;
- objc--;
- objv++;
- }
- }
-
- if( objc!=4 && objc!=5 ){
- const char *zMsg;
- if( bV2 ){
- zMsg = "?-nosavepoint? DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
- }else{
- zMsg = "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
- }
- Tcl_WrongNumArgs(interp, 1, objv, zMsg);
- return TCL_ERROR;
- }
- if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) ){
- Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[1]), 0);
- return TCL_ERROR;
- }
- db = *(sqlite3 **)info.objClientData;
- pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[2], &nChangeset);
- ctx.pConflictScript = objv[3];
- ctx.pFilterScript = objc==5 ? objv[4] : 0;
- ctx.interp = interp;
-
- if( sStr.nStream==0 ){
- if( bV2==0 ){
- rc = sqlite3changeset_apply(db, nChangeset, pChangeset,
- (objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx
- );
- }else{
- rc = sqlite3changeset_apply_v2(db, nChangeset, pChangeset,
- (objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx,
- &pRebase, &nRebase, flags
- );
- }
- }else{
- sStr.aData = (unsigned char*)pChangeset;
- sStr.nData = nChangeset;
- if( bV2==0 ){
- rc = sqlite3changeset_apply_strm(db, testStreamInput, (void*)&sStr,
- (objc==5) ? test_filter_handler : 0,
- test_conflict_handler, (void *)&ctx
- );
- }else{
- rc = sqlite3changeset_apply_v2_strm(db, testStreamInput, (void*)&sStr,
- (objc==5) ? test_filter_handler : 0,
- test_conflict_handler, (void *)&ctx,
- &pRebase, &nRebase, flags
- );
- }
- }
-
- if( rc!=SQLITE_OK ){
- return test_session_error(interp, rc, 0);
- }else{
- Tcl_ResetResult(interp);
- if( bV2 && pRebase ){
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pRebase, nRebase));
- }
- }
- sqlite3_free(pRebase);
- return TCL_OK;
-}
-
-/*
-** sqlite3changeset_apply DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?
-*/
-static int SQLITE_TCLAPI test_sqlite3changeset_apply(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- return testSqlite3changesetApply(0, clientData, interp, objc, objv);
-}
-/*
-** sqlite3changeset_apply_v2 DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?
-*/
-static int SQLITE_TCLAPI test_sqlite3changeset_apply_v2(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- return testSqlite3changesetApply(1, clientData, interp, objc, objv);
-}
-
-/*
-** sqlite3changeset_apply_replace_all DB CHANGESET
-*/
-static int SQLITE_TCLAPI test_sqlite3changeset_apply_replace_all(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db; /* Database handle */
- Tcl_CmdInfo info; /* Database Tcl command (objv[1]) info */
- int rc; /* Return code from changeset_invert() */
- void *pChangeset; /* Buffer containing changeset */
- int nChangeset; /* Size of buffer aChangeset in bytes */
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB CHANGESET");
- return TCL_ERROR;
- }
- if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) ){
- Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[2]), 0);
- return TCL_ERROR;
- }
- db = *(sqlite3 **)info.objClientData;
- pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[2], &nChangeset);
-
- rc = sqlite3changeset_apply(db, nChangeset, pChangeset, 0, replace_handler,0);
- if( rc!=SQLITE_OK ){
- return test_session_error(interp, rc, 0);
- }
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-
-/*
-** sqlite3changeset_invert CHANGESET
-*/
-static int SQLITE_TCLAPI test_sqlite3changeset_invert(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc; /* Return code from changeset_invert() */
- TestStreamInput sIn; /* Input stream */
- TestSessionsBlob sOut; /* Output blob */
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "CHANGESET");
- return TCL_ERROR;
- }
-
- memset(&sIn, 0, sizeof(sIn));
- memset(&sOut, 0, sizeof(sOut));
- sIn.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
- sIn.aData = Tcl_GetByteArrayFromObj(objv[1], &sIn.nData);
-
- if( sIn.nStream ){
- rc = sqlite3changeset_invert_strm(
- testStreamInput, (void*)&sIn, testStreamOutput, (void*)&sOut
- );
- }else{
- rc = sqlite3changeset_invert(sIn.nData, sIn.aData, &sOut.n, &sOut.p);
- }
- if( rc!=SQLITE_OK ){
- rc = test_session_error(interp, rc, 0);
- }else{
- Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n));
- }
- sqlite3_free(sOut.p);
- return rc;
-}
-
-/*
-** sqlite3changeset_concat LEFT RIGHT
-*/
-static int SQLITE_TCLAPI test_sqlite3changeset_concat(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc; /* Return code from changeset_invert() */
-
- TestStreamInput sLeft; /* Input stream */
- TestStreamInput sRight; /* Input stream */
- TestSessionsBlob sOut = {0,0}; /* Output blob */
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "LEFT RIGHT");
- return TCL_ERROR;
- }
-
- memset(&sLeft, 0, sizeof(sLeft));
- memset(&sRight, 0, sizeof(sRight));
- sLeft.aData = Tcl_GetByteArrayFromObj(objv[1], &sLeft.nData);
- sRight.aData = Tcl_GetByteArrayFromObj(objv[2], &sRight.nData);
- sLeft.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
- sRight.nStream = sLeft.nStream;
-
- if( sLeft.nStream>0 ){
- rc = sqlite3changeset_concat_strm(
- testStreamInput, (void*)&sLeft,
- testStreamInput, (void*)&sRight,
- testStreamOutput, (void*)&sOut
- );
- }else{
- rc = sqlite3changeset_concat(
- sLeft.nData, sLeft.aData, sRight.nData, sRight.aData, &sOut.n, &sOut.p
- );
- }
-
- if( rc!=SQLITE_OK ){
- rc = test_session_error(interp, rc, 0);
- }else{
- Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n));
- }
- sqlite3_free(sOut.p);
- return rc;
-}
-
-/*
-** sqlite3session_foreach VARNAME CHANGESET SCRIPT
-*/
-static int SQLITE_TCLAPI test_sqlite3session_foreach(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void *pChangeset;
- int nChangeset;
- sqlite3_changeset_iter *pIter;
- int rc;
- Tcl_Obj *pVarname;
- Tcl_Obj *pCS;
- Tcl_Obj *pScript;
- int isCheckNext = 0;
-
- TestStreamInput sStr;
- memset(&sStr, 0, sizeof(sStr));
-
- if( objc>1 ){
- char *zOpt = Tcl_GetString(objv[1]);
- isCheckNext = (strcmp(zOpt, "-next")==0);
- }
- if( objc!=4+isCheckNext ){
- Tcl_WrongNumArgs(interp, 1, objv, "?-next? VARNAME CHANGESET SCRIPT");
- return TCL_ERROR;
- }
-
- pVarname = objv[1+isCheckNext];
- pCS = objv[2+isCheckNext];
- pScript = objv[3+isCheckNext];
-
- pChangeset = (void *)Tcl_GetByteArrayFromObj(pCS, &nChangeset);
- sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
- if( sStr.nStream==0 ){
- rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
- }else{
- sStr.aData = (unsigned char*)pChangeset;
- sStr.nData = nChangeset;
- rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr);
- }
- if( rc!=SQLITE_OK ){
- return test_session_error(interp, rc, 0);
- }
-
- while( SQLITE_ROW==sqlite3changeset_next(pIter) ){
- int nCol; /* Number of columns in table */
- int nCol2; /* Number of columns in table */
- int op; /* SQLITE_INSERT, UPDATE or DELETE */
- const char *zTab; /* Name of table change applies to */
- Tcl_Obj *pVar; /* Tcl value to set $VARNAME to */
- Tcl_Obj *pOld; /* Vector of old.* values */
- Tcl_Obj *pNew; /* Vector of new.* values */
- int bIndirect;
-
- char *zPK;
- unsigned char *abPK;
- int i;
-
- /* Test that _fk_conflicts() returns SQLITE_MISUSE if called on this
- ** iterator. */
- int nDummy;
- if( SQLITE_MISUSE!=sqlite3changeset_fk_conflicts(pIter, &nDummy) ){
- sqlite3changeset_finalize(pIter);
- return TCL_ERROR;
- }
-
- sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
- pVar = Tcl_NewObj();
- Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(
- op==SQLITE_INSERT ? "INSERT" :
- op==SQLITE_UPDATE ? "UPDATE" :
- "DELETE", -1
- ));
-
- Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1));
- Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect));
-
- zPK = ckalloc(nCol+1);
- memset(zPK, 0, nCol+1);
- sqlite3changeset_pk(pIter, &abPK, &nCol2);
- assert( nCol==nCol2 );
- for(i=0; i<nCol; i++){
- zPK[i] = (abPK[i] ? 'X' : '.');
- }
- Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1));
- ckfree(zPK);
-
- pOld = Tcl_NewObj();
- if( op!=SQLITE_INSERT ){
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- sqlite3changeset_old(pIter, i, &pVal);
- test_append_value(pOld, pVal);
- }
- }
- pNew = Tcl_NewObj();
- if( op!=SQLITE_DELETE ){
- for(i=0; i<nCol; i++){
- sqlite3_value *pVal;
- sqlite3changeset_new(pIter, i, &pVal);
- test_append_value(pNew, pVal);
- }
- }
- Tcl_ListObjAppendElement(0, pVar, pOld);
- Tcl_ListObjAppendElement(0, pVar, pNew);
-
- Tcl_ObjSetVar2(interp, pVarname, 0, pVar, 0);
- rc = Tcl_EvalObjEx(interp, pScript, 0);
- if( rc!=TCL_OK && rc!=TCL_CONTINUE ){
- sqlite3changeset_finalize(pIter);
- return rc==TCL_BREAK ? TCL_OK : rc;
- }
- }
-
- if( isCheckNext ){
- int rc2 = sqlite3changeset_next(pIter);
- rc = sqlite3changeset_finalize(pIter);
- assert( (rc2==SQLITE_DONE && rc==SQLITE_OK) || rc2==rc );
- }else{
- rc = sqlite3changeset_finalize(pIter);
- }
- if( rc!=SQLITE_OK ){
- return test_session_error(interp, rc, 0);
- }
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: CMD configure REBASE-BLOB
-** tclcmd: CMD rebase CHANGESET
-** tclcmd: CMD delete
-*/
-static int SQLITE_TCLAPI test_rebaser_cmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- struct RebaseSubcmd {
- const char *zSub;
- int nArg;
- const char *zMsg;
- int iSub;
- } aSub[] = {
- { "configure", 1, "REBASE-BLOB" }, /* 0 */
- { "delete", 0, "" }, /* 1 */
- { "rebase", 1, "CHANGESET" }, /* 2 */
- { 0 }
- };
-
- sqlite3_rebaser *p = (sqlite3_rebaser*)clientData;
- int iSub;
- int rc;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
- return TCL_ERROR;
- }
- rc = Tcl_GetIndexFromObjStruct(interp,
- objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
- );
- if( rc!=TCL_OK ) return rc;
- if( objc!=2+aSub[iSub].nArg ){
- Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg);
- return TCL_ERROR;
- }
-
- assert( iSub==0 || iSub==1 || iSub==2 );
- assert( rc==SQLITE_OK );
- switch( iSub ){
- case 0: { /* configure */
- int nRebase = 0;
- unsigned char *pRebase = Tcl_GetByteArrayFromObj(objv[2], &nRebase);
- rc = sqlite3rebaser_configure(p, nRebase, pRebase);
- break;
- }
-
- case 1: /* delete */
- Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
- break;
-
- default: { /* rebase */
- TestStreamInput sStr; /* Input stream */
- TestSessionsBlob sOut; /* Output blob */
-
- memset(&sStr, 0, sizeof(sStr));
- memset(&sOut, 0, sizeof(sOut));
- sStr.aData = Tcl_GetByteArrayFromObj(objv[2], &sStr.nData);
- sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
-
- if( sStr.nStream ){
- rc = sqlite3rebaser_rebase_strm(p,
- testStreamInput, (void*)&sStr,
- testStreamOutput, (void*)&sOut
- );
- }else{
- rc = sqlite3rebaser_rebase(p, sStr.nData, sStr.aData, &sOut.n, &sOut.p);
- }
-
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(sOut.p, sOut.n));
- }
- sqlite3_free(sOut.p);
- break;
- }
- }
-
- if( rc!=SQLITE_OK ){
- return test_session_error(interp, rc, 0);
- }
- return TCL_OK;
-}
-
-static void SQLITE_TCLAPI test_rebaser_del(void *clientData){
- sqlite3_rebaser *p = (sqlite3_rebaser*)clientData;
- sqlite3rebaser_delete(p);
-}
-
-/*
-** tclcmd: sqlite3rebaser_create NAME
-*/
-static int SQLITE_TCLAPI test_sqlite3rebaser_create(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3_rebaser *pNew = 0;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME");
- return SQLITE_ERROR;
- }
-
- rc = sqlite3rebaser_create(&pNew);
- if( rc!=SQLITE_OK ){
- return test_session_error(interp, rc, 0);
- }
-
- Tcl_CreateObjCommand(interp, Tcl_GetString(objv[1]), test_rebaser_cmd,
- (ClientData)pNew, test_rebaser_del
- );
- Tcl_SetObjResult(interp, objv[1]);
- return TCL_OK;
-}
-
-int TestSession_Init(Tcl_Interp *interp){
- struct Cmd {
- const char *zCmd;
- Tcl_ObjCmdProc *xProc;
- } aCmd[] = {
- { "sqlite3session", test_sqlite3session },
- { "sqlite3session_foreach", test_sqlite3session_foreach },
- { "sqlite3changeset_invert", test_sqlite3changeset_invert },
- { "sqlite3changeset_concat", test_sqlite3changeset_concat },
- { "sqlite3changeset_apply", test_sqlite3changeset_apply },
- { "sqlite3changeset_apply_v2", test_sqlite3changeset_apply_v2 },
- { "sqlite3changeset_apply_replace_all",
- test_sqlite3changeset_apply_replace_all },
- { "sql_exec_changeset", test_sql_exec_changeset },
- { "sqlite3rebaser_create", test_sqlite3rebaser_create },
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){
- struct Cmd *p = &aCmd[i];
- Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, 0, 0);
- }
-
- return TCL_OK;
-}
-
-#endif /* SQLITE_TEST && SQLITE_SESSION && SQLITE_PREUPDATE_HOOK */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/sqlite3userauth.h b/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/sqlite3userauth.h
deleted file mode 100644
index c7d23b93999..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/sqlite3userauth.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-** 2014-09-08
-**
-** 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 contains the application interface definitions for the
-** user-authentication extension feature.
-**
-** To compile with the user-authentication feature, append this file to
-** end of an SQLite amalgamation header file ("sqlite3.h"), then add
-** the SQLITE_USER_AUTHENTICATION compile-time option. See the
-** user-auth.txt file in the same source directory as this file for
-** additional information.
-*/
-#ifdef SQLITE_USER_AUTHENTICATION
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** If a database contains the SQLITE_USER table, then the
-** sqlite3_user_authenticate() interface must be invoked with an
-** appropriate username and password prior to enable read and write
-** access to the database.
-**
-** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
-** combination is incorrect or unknown.
-**
-** If the SQLITE_USER table is not present in the database file, then
-** this interface is a harmless no-op returnning SQLITE_OK.
-*/
-int sqlite3_user_authenticate(
- sqlite3 *db, /* The database connection */
- const char *zUsername, /* Username */
- const char *aPW, /* Password or credentials */
- int nPW /* Number of bytes in aPW[] */
-);
-
-/*
-** The sqlite3_user_add() interface can be used (by an admin user only)
-** to create a new user. When called on a no-authentication-required
-** database, this routine converts the database into an authentication-
-** required database, automatically makes the added user an
-** administrator, and logs in the current connection as that user.
-** The sqlite3_user_add() interface only works for the "main" database, not
-** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
-** non-admin user results in an error.
-*/
-int sqlite3_user_add(
- sqlite3 *db, /* Database connection */
- const char *zUsername, /* Username to be added */
- const char *aPW, /* Password or credentials */
- int nPW, /* Number of bytes in aPW[] */
- int isAdmin /* True to give new user admin privilege */
-);
-
-/*
-** The sqlite3_user_change() interface can be used to change a users
-** login credentials or admin privilege. Any user can change their own
-** login credentials. Only an admin user can change another users login
-** credentials or admin privilege setting. No user may change their own
-** admin privilege setting.
-*/
-int sqlite3_user_change(
- sqlite3 *db, /* Database connection */
- const char *zUsername, /* Username to change */
- const char *aPW, /* New password or credentials */
- int nPW, /* Number of bytes in aPW[] */
- int isAdmin /* Modified admin privilege for the user */
-);
-
-/*
-** The sqlite3_user_delete() interface can be used (by an admin user only)
-** to delete a user. The currently logged-in user cannot be deleted,
-** which guarantees that there is always an admin user and hence that
-** the database cannot be converted into a no-authentication-required
-** database.
-*/
-int sqlite3_user_delete(
- sqlite3 *db, /* Database connection */
- const char *zUsername /* Username to remove */
-);
-
-#ifdef __cplusplus
-} /* end of the 'extern "C"' block */
-#endif
-
-#endif /* SQLITE_USER_AUTHENTICATION */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/user-auth.txt b/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/user-auth.txt
deleted file mode 100644
index ba4eabc1370..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/user-auth.txt
+++ /dev/null
@@ -1,164 +0,0 @@
-Activate the user authentication logic by including the
-ext/userauth/userauth.c source code file in the build and
-adding the -DSQLITE_USER_AUTHENTICATION compile-time option.
-The ext/userauth/sqlite3userauth.h header file is available to
-applications to define the interface.
-
-When using the SQLite amalgamation, it is sufficient to append
-the ext/userauth/userauth.c source file onto the end of the
-amalgamation.
-
-The following new APIs are available when user authentication is
-activated:
-
- int sqlite3_user_authenticate(
- sqlite3 *db, /* The database connection */
- const char *zUsername, /* Username */
- const char *aPW, /* Password or credentials */
- int nPW /* Number of bytes in aPW[] */
- );
-
- int sqlite3_user_add(
- sqlite3 *db, /* Database connection */
- const char *zUsername, /* Username to be added */
- const char *aPW, /* Password or credentials */
- int nPW, /* Number of bytes in aPW[] */
- int isAdmin /* True to give new user admin privilege */
- );
-
- int sqlite3_user_change(
- sqlite3 *db, /* Database connection */
- const char *zUsername, /* Username to change */
- const void *aPW, /* Modified password or credentials */
- int nPW, /* Number of bytes in aPW[] */
- int isAdmin /* Modified admin privilege for the user */
- );
-
- int sqlite3_user_delete(
- sqlite3 *db, /* Database connection */
- const char *zUsername /* Username to remove */
- );
-
-With this extension, a database can be marked as requiring authentication.
-By default a database does not require authentication.
-
-The sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
-work as before: they open a new database connection. However, if the
-database being opened requires authentication, then attempts to read
-or write from the database will fail with an SQLITE_AUTH error until
-after sqlite3_user_authenticate() has been called successfully. The
-sqlite3_user_authenticate() call will return SQLITE_OK if the
-authentication credentials are accepted and SQLITE_ERROR if not.
-
-Calling sqlite3_user_authenticate() on a no-authentication-required
-database connection is a harmless no-op.
-
-If the database is encrypted, then sqlite3_key_v2() must be called first,
-with the correct decryption key, prior to invoking sqlite3_user_authenticate().
-
-To recapitulate: When opening an existing unencrypted authentication-
-required database, the call sequence is:
-
- sqlite3_open_v2()
- sqlite3_user_authenticate();
- /* Database is now usable */
-
-To open an existing, encrypted, authentication-required database, the
-call sequence is:
-
- sqlite3_open_v2();
- sqlite3_key_v2();
- sqlite3_user_authenticate();
- /* Database is now usable */
-
-When opening a no-authentication-required database, the database
-connection is treated as if it was authenticated as an admin user.
-
-When ATTACH-ing new database files to a connection, each newly attached
-database that is an authentication-required database is checked using
-the same username and password as supplied to the main database. If that
-check fails, then the ATTACH command fails with an SQLITE_AUTH error.
-
-The sqlite3_user_add() interface can be used (by an admin user only)
-to create a new user. When called on a no-authentication-required
-database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
-converts the database into an authentication-required database and
-logs in the database connection D as user U with password P,N.
-To convert a no-authentication-required database into an authentication-
-required database, the isAdmin parameter must be true. If
-sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
-database and A is false, then the call fails with an SQLITE_AUTH error.
-
-Any call to sqlite3_user_add() by a non-admin user results in an error.
-
-Hence, to create a new, unencrypted, authentication-required database,
-the call sequence is:
-
- sqlite3_open_v2();
- sqlite3_user_add();
-
-And to create a new, encrypted, authentication-required database, the call
-sequence is:
-
- sqlite3_open_v2();
- sqlite3_key_v2();
- sqlite3_user_add();
-
-The sqlite3_user_delete() interface can be used (by an admin user only)
-to delete a user. The currently logged-in user cannot be deleted,
-which guarantees that there is always an admin user and hence that
-the database cannot be converted into a no-authentication-required
-database.
-
-The sqlite3_user_change() interface can be used to change a users
-login credentials or admin privilege. Any user can change their own
-password. Only an admin user can change another users login
-credentials or admin privilege setting. No user may change their own
-admin privilege setting.
-
-The sqlite3_set_authorizer() callback is modified to take a 7th parameter
-which is the username of the currently logged in user, or NULL for a
-no-authentication-required database.
-
------------------------------------------------------------------------------
-Implementation notes:
-
-An authentication-required database is identified by the presence of a
-new table:
-
- CREATE TABLE sqlite_user(
- uname TEXT PRIMARY KEY,
- isAdmin BOOLEAN,
- pw BLOB
- ) WITHOUT ROWID;
-
-The sqlite_user table is inaccessible (unreadable and unwriteable) to
-non-admin users and is read-only for admin users. However, if the same
-database file is opened by a version of SQLite that omits
-the -DSQLITE_USER_AUTHENTICATION compile-time option, then the sqlite_user
-table will be readable by anybody and writeable by anybody if
-the "PRAGMA writable_schema=ON" statement is run first.
-
-The sqlite_user.pw field is encoded by a built-in SQL function
-"sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
-is the plaintext password supplied to the sqlite3_user_authenticate()
-interface. The second argument is the sqlite_user.pw value and is supplied
-so that the function can extract the "salt" used by the password encoder.
-The result of sqlite_crypt(X,Y) is another blob which is the value that
-ends up being stored in sqlite_user.pw. To verify credentials X supplied
-by the sqlite3_user_authenticate() routine, SQLite runs:
-
- sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
-
-To compute an appropriate sqlite_user.pw value from a new or modified
-password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
-when the second argument is NULL.
-
-The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
-which prevents passwords from being revealed by searching the raw database
-for ASCII text, but is otherwise trivally broken. For better password
-security, the database should be encrypted using the SQLite Encryption
-Extension or similar technology. Or, the application can use the
-sqlite3_create_function() interface to provide an alternative
-implementation of sqlite_crypt() that computes a stronger password hash,
-perhaps using a cryptographic hash function like SHA1.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/userauth.c b/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/userauth.c
deleted file mode 100644
index a3d346c05c6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ext/userauth/userauth.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
-** 2014-09-08
-**
-** 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 contains the bulk of the implementation of the
-** user-authentication extension feature. Some parts of the user-
-** authentication code are contained within the SQLite core (in the
-** src/ subdirectory of the main source code tree) but those parts
-** that could reasonable be separated out are moved into this file.
-**
-** To compile with the user-authentication feature, append this file to
-** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
-** compile-time option. See the user-auth.txt file in the same source
-** directory as this file for additional information.
-*/
-#ifdef SQLITE_USER_AUTHENTICATION
-#ifndef SQLITEINT_H
-# include "sqliteInt.h"
-#endif
-
-/*
-** Prepare an SQL statement for use by the user authentication logic.
-** Return a pointer to the prepared statement on success. Return a
-** NULL pointer if there is an error of any kind.
-*/
-static sqlite3_stmt *sqlite3UserAuthPrepare(
- sqlite3 *db,
- const char *zFormat,
- ...
-){
- sqlite3_stmt *pStmt;
- char *zSql;
- int rc;
- va_list ap;
- int savedFlags = db->flags;
-
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- if( zSql==0 ) return 0;
- db->flags |= SQLITE_WriteSchema;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- db->flags = savedFlags;
- sqlite3_free(zSql);
- if( rc ){
- sqlite3_finalize(pStmt);
- pStmt = 0;
- }
- return pStmt;
-}
-
-/*
-** Check to see if the sqlite_user table exists in database zDb.
-*/
-static int userTableExists(sqlite3 *db, const char *zDb){
- int rc;
- sqlite3_mutex_enter(db->mutex);
- sqlite3BtreeEnterAll(db);
- if( db->init.busy==0 ){
- char *zErr = 0;
- sqlite3Init(db, &zErr);
- sqlite3DbFree(db, zErr);
- }
- rc = sqlite3FindTable(db, "sqlite_user", zDb)!=0;
- sqlite3BtreeLeaveAll(db);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** Check to see if database zDb has a "sqlite_user" table and if it does
-** whether that table can authenticate zUser with nPw,zPw. Write one of
-** the UAUTH_* user authorization level codes into *peAuth and return a
-** result code.
-*/
-static int userAuthCheckLogin(
- sqlite3 *db, /* The database connection to check */
- const char *zDb, /* Name of specific database to check */
- u8 *peAuth /* OUT: One of UAUTH_* constants */
-){
- sqlite3_stmt *pStmt;
- int rc;
-
- *peAuth = UAUTH_Unknown;
- if( !userTableExists(db, "main") ){
- *peAuth = UAUTH_Admin; /* No sqlite_user table. Everybody is admin. */
- return SQLITE_OK;
- }
- if( db->auth.zAuthUser==0 ){
- *peAuth = UAUTH_Fail;
- return SQLITE_OK;
- }
- pStmt = sqlite3UserAuthPrepare(db,
- "SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
- " WHERE uname=?2", zDb);
- if( pStmt==0 ) return SQLITE_NOMEM;
- sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
- sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
- rc = sqlite3_step(pStmt);
- if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
- *peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
- }else{
- *peAuth = UAUTH_Fail;
- }
- return sqlite3_finalize(pStmt);
-}
-int sqlite3UserAuthCheckLogin(
- sqlite3 *db, /* The database connection to check */
- const char *zDb, /* Name of specific database to check */
- u8 *peAuth /* OUT: One of UAUTH_* constants */
-){
- int rc;
- u8 savedAuthLevel;
- assert( zDb!=0 );
- assert( peAuth!=0 );
- savedAuthLevel = db->auth.authLevel;
- db->auth.authLevel = UAUTH_Admin;
- rc = userAuthCheckLogin(db, zDb, peAuth);
- db->auth.authLevel = savedAuthLevel;
- return rc;
-}
-
-/*
-** If the current authLevel is UAUTH_Unknown, the take actions to figure
-** out what authLevel should be
-*/
-void sqlite3UserAuthInit(sqlite3 *db){
- if( db->auth.authLevel==UAUTH_Unknown ){
- u8 authLevel = UAUTH_Fail;
- sqlite3UserAuthCheckLogin(db, "main", &authLevel);
- db->auth.authLevel = authLevel;
- if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema;
- }
-}
-
-/*
-** Implementation of the sqlite_crypt(X,Y) function.
-**
-** If Y is NULL then generate a new hash for password X and return that
-** hash. If Y is not null, then generate a hash for password X using the
-** same salt as the previous hash Y and return the new hash.
-*/
-void sqlite3CryptFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- const char *zIn;
- int nIn, ii;
- u8 *zOut;
- char zSalt[8];
- zIn = sqlite3_value_blob(argv[0]);
- nIn = sqlite3_value_bytes(argv[0]);
- if( sqlite3_value_type(argv[1])==SQLITE_BLOB
- && sqlite3_value_bytes(argv[1])==nIn+sizeof(zSalt)
- ){
- memcpy(zSalt, sqlite3_value_blob(argv[1]), sizeof(zSalt));
- }else{
- sqlite3_randomness(sizeof(zSalt), zSalt);
- }
- zOut = sqlite3_malloc( nIn+sizeof(zSalt) );
- if( zOut==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- memcpy(zOut, zSalt, sizeof(zSalt));
- for(ii=0; ii<nIn; ii++){
- zOut[ii+sizeof(zSalt)] = zIn[ii]^zSalt[ii&0x7];
- }
- sqlite3_result_blob(context, zOut, nIn+sizeof(zSalt), sqlite3_free);
- }
-}
-
-/*
-** If a database contains the SQLITE_USER table, then the
-** sqlite3_user_authenticate() interface must be invoked with an
-** appropriate username and password prior to enable read and write
-** access to the database.
-**
-** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
-** combination is incorrect or unknown.
-**
-** If the SQLITE_USER table is not present in the database file, then
-** this interface is a harmless no-op returnning SQLITE_OK.
-*/
-int sqlite3_user_authenticate(
- sqlite3 *db, /* The database connection */
- const char *zUsername, /* Username */
- const char *zPW, /* Password or credentials */
- int nPW /* Number of bytes in aPW[] */
-){
- int rc;
- u8 authLevel = UAUTH_Fail;
- db->auth.authLevel = UAUTH_Unknown;
- sqlite3_free(db->auth.zAuthUser);
- sqlite3_free(db->auth.zAuthPW);
- memset(&db->auth, 0, sizeof(db->auth));
- db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
- if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
- db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
- if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
- memcpy(db->auth.zAuthPW,zPW,nPW);
- db->auth.nAuthPW = nPW;
- rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
- db->auth.authLevel = authLevel;
- sqlite3ExpirePreparedStatements(db);
- if( rc ){
- return rc; /* OOM error, I/O error, etc. */
- }
- if( authLevel<UAUTH_User ){
- return SQLITE_AUTH; /* Incorrect username and/or password */
- }
- return SQLITE_OK; /* Successful login */
-}
-
-/*
-** The sqlite3_user_add() interface can be used (by an admin user only)
-** to create a new user. When called on a no-authentication-required
-** database, this routine converts the database into an authentication-
-** required database, automatically makes the added user an
-** administrator, and logs in the current connection as that user.
-** The sqlite3_user_add() interface only works for the "main" database, not
-** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
-** non-admin user results in an error.
-*/
-int sqlite3_user_add(
- sqlite3 *db, /* Database connection */
- const char *zUsername, /* Username to be added */
- const char *aPW, /* Password or credentials */
- int nPW, /* Number of bytes in aPW[] */
- int isAdmin /* True to give new user admin privilege */
-){
- sqlite3_stmt *pStmt;
- int rc;
- sqlite3UserAuthInit(db);
- if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
- if( !userTableExists(db, "main") ){
- if( !isAdmin ) return SQLITE_AUTH;
- pStmt = sqlite3UserAuthPrepare(db,
- "CREATE TABLE sqlite_user(\n"
- " uname TEXT PRIMARY KEY,\n"
- " isAdmin BOOLEAN,\n"
- " pw BLOB\n"
- ") WITHOUT ROWID;");
- if( pStmt==0 ) return SQLITE_NOMEM;
- sqlite3_step(pStmt);
- rc = sqlite3_finalize(pStmt);
- if( rc ) return rc;
- }
- pStmt = sqlite3UserAuthPrepare(db,
- "INSERT INTO sqlite_user(uname,isAdmin,pw)"
- " VALUES(%Q,%d,sqlite_crypt(?1,NULL))",
- zUsername, isAdmin!=0);
- if( pStmt==0 ) return SQLITE_NOMEM;
- sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
- sqlite3_step(pStmt);
- rc = sqlite3_finalize(pStmt);
- if( rc ) return rc;
- if( db->auth.zAuthUser==0 ){
- assert( isAdmin!=0 );
- sqlite3_user_authenticate(db, zUsername, aPW, nPW);
- }
- return SQLITE_OK;
-}
-
-/*
-** The sqlite3_user_change() interface can be used to change a users
-** login credentials or admin privilege. Any user can change their own
-** login credentials. Only an admin user can change another users login
-** credentials or admin privilege setting. No user may change their own
-** admin privilege setting.
-*/
-int sqlite3_user_change(
- sqlite3 *db, /* Database connection */
- const char *zUsername, /* Username to change */
- const char *aPW, /* Modified password or credentials */
- int nPW, /* Number of bytes in aPW[] */
- int isAdmin /* Modified admin privilege for the user */
-){
- sqlite3_stmt *pStmt;
- int rc;
- u8 authLevel;
-
- authLevel = db->auth.authLevel;
- if( authLevel<UAUTH_User ){
- /* Must be logged in to make a change */
- return SQLITE_AUTH;
- }
- if( strcmp(db->auth.zAuthUser, zUsername)!=0 ){
- if( db->auth.authLevel<UAUTH_Admin ){
- /* Must be an administrator to change a different user */
- return SQLITE_AUTH;
- }
- }else if( isAdmin!=(authLevel==UAUTH_Admin) ){
- /* Cannot change the isAdmin setting for self */
- return SQLITE_AUTH;
- }
- db->auth.authLevel = UAUTH_Admin;
- if( !userTableExists(db, "main") ){
- /* This routine is a no-op if the user to be modified does not exist */
- }else{
- pStmt = sqlite3UserAuthPrepare(db,
- "UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)"
- " WHERE uname=%Q", isAdmin, zUsername);
- if( pStmt==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
- sqlite3_step(pStmt);
- rc = sqlite3_finalize(pStmt);
- }
- }
- db->auth.authLevel = authLevel;
- return rc;
-}
-
-/*
-** The sqlite3_user_delete() interface can be used (by an admin user only)
-** to delete a user. The currently logged-in user cannot be deleted,
-** which guarantees that there is always an admin user and hence that
-** the database cannot be converted into a no-authentication-required
-** database.
-*/
-int sqlite3_user_delete(
- sqlite3 *db, /* Database connection */
- const char *zUsername /* Username to remove */
-){
- sqlite3_stmt *pStmt;
- if( db->auth.authLevel<UAUTH_Admin ){
- /* Must be an administrator to delete a user */
- return SQLITE_AUTH;
- }
- if( strcmp(db->auth.zAuthUser, zUsername)==0 ){
- /* Cannot delete self */
- return SQLITE_AUTH;
- }
- if( !userTableExists(db, "main") ){
- /* This routine is a no-op if the user to be deleted does not exist */
- return SQLITE_OK;
- }
- pStmt = sqlite3UserAuthPrepare(db,
- "DELETE FROM sqlite_user WHERE uname=%Q", zUsername);
- if( pStmt==0 ) return SQLITE_NOMEM;
- sqlite3_step(pStmt);
- return sqlite3_finalize(pStmt);
-}
-
-#endif /* SQLITE_USER_AUTHENTICATION */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/install-sh b/chromium/third_party/sqlite/sqlite-src-3240000/install-sh
deleted file mode 100755
index e9de23842dc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/install-sh
+++ /dev/null
@@ -1,251 +0,0 @@
-#!/bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
-#
-# Copyright 1991 by the Massachusetts Institute of Technology
-#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission. M.I.T. makes no representations about the
-# suitability of this software for any purpose. It is provided "as is"
-# without express or implied warranty.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch. It can only install one file at a time, a restriction
-# shared with many OS's install programs.
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
-
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
-else
- true
-fi
-
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
-
- if [ -d $dst ]; then
- instcmd=:
- chmodcmd=""
- else
- instcmd=mkdir
- fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
-
- if [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
-
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-'
-IFS="${IFS-${defaultIFS}}"
-
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
-
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
-
- pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
-
-# don't allow the sed command to completely eliminate the filename
-
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
-
-# Make a temp file name in the proper directory.
-
- dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
- $doit $instcmd $src $dsttmp &&
-
- trap "rm -f ${dsttmp}" 0 &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing. If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
-
-fi &&
-
-
-exit 0
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/ltmain.sh b/chromium/third_party/sqlite/sqlite-src-3240000/ltmain.sh
deleted file mode 100644
index 0634c4bccce..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/ltmain.sh
+++ /dev/null
@@ -1,8461 +0,0 @@
-# Generated from ltmain.m4sh.
-
-# ltmain.sh (GNU libtool) 2.2.6
-# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc.
-# This is free software; see the source for copying conditions. There is NO
-# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-# GNU Libtool is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# As a special exception to the GNU General Public License,
-# if you distribute this file as part of a program or library that
-# is built using GNU Libtool, you may include this file under the
-# same distribution terms that you use for the rest of that program.
-#
-# GNU Libtool is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Libtool; see the file COPYING. If not, a copy
-# can be downloaded from http://www.gnu.org/licenses/gpl.html,
-# or obtained by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-# Usage: $progname [OPTION]... [MODE-ARG]...
-#
-# Provide generalized library-building support services.
-#
-# --config show all configuration variables
-# --debug enable verbose shell tracing
-# -n, --dry-run display commands without modifying any files
-# --features display basic configuration information and exit
-# --mode=MODE use operation mode MODE
-# --preserve-dup-deps don't remove duplicate dependency libraries
-# --quiet, --silent don't print informational messages
-# --tag=TAG use configuration variables from tag TAG
-# -v, --verbose print informational messages (default)
-# --version print version information
-# -h, --help print short or long help message
-#
-# MODE must be one of the following:
-#
-# clean remove files from the build directory
-# compile compile a source file into a libtool object
-# execute automatically set library path, then run a program
-# finish complete the installation of libtool libraries
-# install install libraries or executables
-# link create a library or an executable
-# uninstall remove libraries from an installed directory
-#
-# MODE-ARGS vary depending on the MODE.
-# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
-#
-# When reporting a bug, please describe a test case to reproduce it and
-# include the following information:
-#
-# host-triplet: $host
-# shell: $SHELL
-# compiler: $LTCC
-# compiler flags: $LTCFLAGS
-# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.2.6
-# automake: $automake_version
-# autoconf: $autoconf_version
-#
-# Report bugs to <bug-libtool@gnu.org>.
-
-PROGRAM=ltmain.sh
-PACKAGE=libtool
-VERSION=2.2.6
-TIMESTAMP=""
-package_revision=1.3012
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
-fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# NLS nuisances: We save the old values to restore during execute mode.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-lt_user_locale=
-lt_safe_locale=
-for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
-do
- eval "if test \"\${$lt_var+set}\" = set; then
- save_$lt_var=\$$lt_var
- $lt_var=C
- export $lt_var
- lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
- lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
- fi"
-done
-
-$lt_unset CDPATH
-
-
-
-
-
-: ${CP="cp -f"}
-: ${ECHO="echo"}
-: ${EGREP="/usr/bin/grep -E"}
-: ${FGREP="/usr/bin/grep -F"}
-: ${GREP="/usr/bin/grep"}
-: ${LN_S="ln -s"}
-: ${MAKE="make"}
-: ${MKDIR="mkdir"}
-: ${MV="mv -f"}
-: ${RM="rm -f"}
-: ${SED="/opt/local/bin/gsed"}
-: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
-: ${Xsed="$SED -e 1s/^X//"}
-
-# Global variables:
-EXIT_SUCCESS=0
-EXIT_FAILURE=1
-EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing.
-EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
-
-exit_status=$EXIT_SUCCESS
-
-# Make sure IFS has a sensible default
-lt_nl='
-'
-IFS=" $lt_nl"
-
-dirname="s,/[^/]*$,,"
-basename="s,^.*/,,"
-
-# func_dirname_and_basename file append nondir_replacement
-# perform func_basename and func_dirname in a single function
-# call:
-# dirname: Compute the dirname of FILE. If nonempty,
-# add APPEND to the result, otherwise set result
-# to NONDIR_REPLACEMENT.
-# value returned in "$func_dirname_result"
-# basename: Compute filename of FILE.
-# value retuned in "$func_basename_result"
-# Implementation must be kept synchronized with func_dirname
-# and func_basename. For efficiency, we do not delegate to
-# those functions but instead duplicate the functionality here.
-func_dirname_and_basename ()
-{
- # Extract subdirectory from the argument.
- func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
- if test "X$func_dirname_result" = "X${1}"; then
- func_dirname_result="${3}"
- else
- func_dirname_result="$func_dirname_result${2}"
- fi
- func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
-}
-
-# Generated shell functions inserted here.
-
-# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
-# is ksh but when the shell is invoked as "sh" and the current value of
-# the _XPG environment variable is not equal to 1 (one), the special
-# positional parameter $0, within a function call, is the name of the
-# function.
-progpath="$0"
-
-# The name of this program:
-# In the unlikely event $progname began with a '-', it would play havoc with
-# func_echo (imagine progname=-n), so we prepend ./ in that case:
-func_dirname_and_basename "$progpath"
-progname=$func_basename_result
-case $progname in
- -*) progname=./$progname ;;
-esac
-
-# Make sure we have an absolute path for reexecution:
-case $progpath in
- [\\/]*|[A-Za-z]:\\*) ;;
- *[\\/]*)
- progdir=$func_dirname_result
- progdir=`cd "$progdir" && pwd`
- progpath="$progdir/$progname"
- ;;
- *)
- save_IFS="$IFS"
- IFS=:
- for progdir in $PATH; do
- IFS="$save_IFS"
- test -x "$progdir/$progname" && break
- done
- IFS="$save_IFS"
- test -n "$progdir" || progdir=`pwd`
- progpath="$progdir/$progname"
- ;;
-esac
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed="${SED}"' -e 1s/^X//'
-sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\(["`\\]\)/\\\1/g'
-
-# Re-`\' parameter expansions in output of double_quote_subst that were
-# `\'-ed in input to the same. If an odd number of `\' preceded a '$'
-# in input to double_quote_subst, that '$' was protected from expansion.
-# Since each input `\' is now two `\'s, look for any number of runs of
-# four `\'s followed by two `\'s and then a '$'. `\' that '$'.
-bs='\\'
-bs2='\\\\'
-bs4='\\\\\\\\'
-dollar='\$'
-sed_double_backslash="\
- s/$bs4/&\\
-/g
- s/^$bs2$dollar/$bs&/
- s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
- s/\n//g"
-
-# Standard options:
-opt_dry_run=false
-opt_help=false
-opt_quiet=false
-opt_verbose=false
-opt_warning=:
-
-# func_echo arg...
-# Echo program name prefixed message, along with the current mode
-# name if it has been set yet.
-func_echo ()
-{
- $ECHO "$progname${mode+: }$mode: $*"
-}
-
-# func_verbose arg...
-# Echo program name prefixed message in verbose mode only.
-func_verbose ()
-{
- $opt_verbose && func_echo ${1+"$@"}
-
- # A bug in bash halts the script if the last line of a function
- # fails when set -e is in force, so we need another command to
- # work around that:
- :
-}
-
-# func_error arg...
-# Echo program name prefixed message to standard error.
-func_error ()
-{
- $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
-}
-
-# func_warning arg...
-# Echo program name prefixed warning message to standard error.
-func_warning ()
-{
- $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
-
- # bash bug again:
- :
-}
-
-# func_fatal_error arg...
-# Echo program name prefixed message to standard error, and exit.
-func_fatal_error ()
-{
- func_error ${1+"$@"}
- exit $EXIT_FAILURE
-}
-
-# func_fatal_help arg...
-# Echo program name prefixed message to standard error, followed by
-# a help hint, and exit.
-func_fatal_help ()
-{
- func_error ${1+"$@"}
- func_fatal_error "$help"
-}
-help="Try \`$progname --help' for more information." ## default
-
-
-# func_grep expression filename
-# Check whether EXPRESSION matches any line of FILENAME, without output.
-func_grep ()
-{
- $GREP "$1" "$2" >/dev/null 2>&1
-}
-
-
-# func_mkdir_p directory-path
-# Make sure the entire path to DIRECTORY-PATH is available.
-func_mkdir_p ()
-{
- my_directory_path="$1"
- my_dir_list=
-
- if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
-
- # Protect directory names starting with `-'
- case $my_directory_path in
- -*) my_directory_path="./$my_directory_path" ;;
- esac
-
- # While some portion of DIR does not yet exist...
- while test ! -d "$my_directory_path"; do
- # ...make a list in topmost first order. Use a colon delimited
- # list incase some portion of path contains whitespace.
- my_dir_list="$my_directory_path:$my_dir_list"
-
- # If the last portion added has no slash in it, the list is done
- case $my_directory_path in */*) ;; *) break ;; esac
-
- # ...otherwise throw away the child directory and loop
- my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"`
- done
- my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'`
-
- save_mkdir_p_IFS="$IFS"; IFS=':'
- for my_dir in $my_dir_list; do
- IFS="$save_mkdir_p_IFS"
- # mkdir can fail with a `File exist' error if two processes
- # try to create one of the directories concurrently. Don't
- # stop in that case!
- $MKDIR "$my_dir" 2>/dev/null || :
- done
- IFS="$save_mkdir_p_IFS"
-
- # Bail out if we (or some other process) failed to create a directory.
- test -d "$my_directory_path" || \
- func_fatal_error "Failed to create \`$1'"
- fi
-}
-
-
-# func_mktempdir [string]
-# Make a temporary directory that won't clash with other running
-# libtool processes, and avoids race conditions if possible. If
-# given, STRING is the basename for that directory.
-func_mktempdir ()
-{
- my_template="${TMPDIR-/tmp}/${1-$progname}"
-
- if test "$opt_dry_run" = ":"; then
- # Return a directory name, but don't create it in dry-run mode
- my_tmpdir="${my_template}-$$"
- else
-
- # If mktemp works, use that first and foremost
- my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
-
- if test ! -d "$my_tmpdir"; then
- # Failing that, at least try and use $RANDOM to avoid a race
- my_tmpdir="${my_template}-${RANDOM-0}$$"
-
- save_mktempdir_umask=`umask`
- umask 0077
- $MKDIR "$my_tmpdir"
- umask $save_mktempdir_umask
- fi
-
- # If we're not in dry-run mode, bomb out on failure
- test -d "$my_tmpdir" || \
- func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
- fi
-
- $ECHO "X$my_tmpdir" | $Xsed
-}
-
-
-# func_quote_for_eval arg
-# Aesthetically quote ARG to be evaled later.
-# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
-# is double-quoted, suitable for a subsequent eval, whereas
-# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
-# which are still active within double quotes backslashified.
-func_quote_for_eval ()
-{
- case $1 in
- *[\\\`\"\$]*)
- func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;;
- *)
- func_quote_for_eval_unquoted_result="$1" ;;
- esac
-
- case $func_quote_for_eval_unquoted_result in
- # Double-quote args containing shell metacharacters to delay
- # word splitting, command substitution and and variable
- # expansion for a subsequent eval.
- # Many Bourne shells cannot handle close brackets correctly
- # in scan sets, so we specify it separately.
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
- ;;
- *)
- func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
- esac
-}
-
-
-# func_quote_for_expand arg
-# Aesthetically quote ARG to be evaled later; same as above,
-# but do not quote variable references.
-func_quote_for_expand ()
-{
- case $1 in
- *[\\\`\"]*)
- my_arg=`$ECHO "X$1" | $Xsed \
- -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
- *)
- my_arg="$1" ;;
- esac
-
- case $my_arg in
- # Double-quote args containing shell metacharacters to delay
- # word splitting and command substitution for a subsequent eval.
- # Many Bourne shells cannot handle close brackets correctly
- # in scan sets, so we specify it separately.
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- my_arg="\"$my_arg\""
- ;;
- esac
-
- func_quote_for_expand_result="$my_arg"
-}
-
-
-# func_show_eval cmd [fail_exp]
-# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is
-# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
-# is given, then evaluate it.
-func_show_eval ()
-{
- my_cmd="$1"
- my_fail_exp="${2-:}"
-
- ${opt_silent-false} || {
- func_quote_for_expand "$my_cmd"
- eval "func_echo $func_quote_for_expand_result"
- }
-
- if ${opt_dry_run-false}; then :; else
- eval "$my_cmd"
- my_status=$?
- if test "$my_status" -eq 0; then :; else
- eval "(exit $my_status); $my_fail_exp"
- fi
- fi
-}
-
-
-# func_show_eval_locale cmd [fail_exp]
-# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is
-# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
-# is given, then evaluate it. Use the saved locale for evaluation.
-func_show_eval_locale ()
-{
- my_cmd="$1"
- my_fail_exp="${2-:}"
-
- ${opt_silent-false} || {
- func_quote_for_expand "$my_cmd"
- eval "func_echo $func_quote_for_expand_result"
- }
-
- if ${opt_dry_run-false}; then :; else
- eval "$lt_user_locale
- $my_cmd"
- my_status=$?
- eval "$lt_safe_locale"
- if test "$my_status" -eq 0; then :; else
- eval "(exit $my_status); $my_fail_exp"
- fi
- fi
-}
-
-
-
-
-
-# func_version
-# Echo version message to standard output and exit.
-func_version ()
-{
- $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / {
- s/^# //
- s/^# *$//
- s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
- p
- }' < "$progpath"
- exit $?
-}
-
-# func_usage
-# Echo short help message to standard output and exit.
-func_usage ()
-{
- $SED -n '/^# Usage:/,/# -h/ {
- s/^# //
- s/^# *$//
- s/\$progname/'$progname'/
- p
- }' < "$progpath"
- $ECHO
- $ECHO "run \`$progname --help | more' for full usage"
- exit $?
-}
-
-# func_help
-# Echo long help message to standard output and exit.
-func_help ()
-{
- $SED -n '/^# Usage:/,/# Report bugs to/ {
- s/^# //
- s/^# *$//
- s*\$progname*'$progname'*
- s*\$host*'"$host"'*
- s*\$SHELL*'"$SHELL"'*
- s*\$LTCC*'"$LTCC"'*
- s*\$LTCFLAGS*'"$LTCFLAGS"'*
- s*\$LD*'"$LD"'*
- s/\$with_gnu_ld/'"$with_gnu_ld"'/
- s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
- s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
- p
- }' < "$progpath"
- exit $?
-}
-
-# func_missing_arg argname
-# Echo program name prefixed message to standard error and set global
-# exit_cmd.
-func_missing_arg ()
-{
- func_error "missing argument for $1"
- exit_cmd=exit
-}
-
-exit_cmd=:
-
-
-
-
-
-# Check that we have a working $ECHO.
-if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X$1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
- # Yippee, $ECHO works!
- :
-else
- # Restart under the correct shell, and then maybe $ECHO will work.
- exec $SHELL "$progpath" --no-reexec ${1+"$@"}
-fi
-# Same for EGREP, and just to be sure, do LTCC as well
-if test "x$EGREP" = x ; then
- EGREP=egrep
-fi
-if test "x$LTCC" = x ; then
- LTCC=${CC-gcc}
-fi
-
-if test "X$1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<EOF
-$*
-EOF
- exit $EXIT_SUCCESS
-fi
-
-magic="%%%MAGIC variable%%%"
-magic_exe="%%%MAGIC EXE variable%%%"
-
-# Global variables.
-# $mode is unset
-nonopt=
-execute_dlfiles=
-preserve_args=
-lo2o="s/\\.lo\$/.${objext}/"
-o2lo="s/\\.${objext}\$/.lo/"
-extracted_archives=
-extracted_serial=0
-
-opt_dry_run=false
-opt_duplicate_deps=false
-opt_silent=false
-opt_debug=:
-
-# If this variable is set in any of the actions, the command in it
-# will be execed at the end. This prevents here-documents from being
-# left over by shells.
-exec_cmd=
-
-# func_fatal_configuration arg...
-# Echo program name prefixed message to standard error, followed by
-# a configuration failure hint, and exit.
-func_fatal_configuration ()
-{
- func_error ${1+"$@"}
- func_error "See the $PACKAGE documentation for more information."
- func_fatal_error "Fatal configuration error."
-}
-
-
-# func_config
-# Display the configuration for all the tags in this script.
-func_config ()
-{
- re_begincf='^# ### BEGIN LIBTOOL'
- re_endcf='^# ### END LIBTOOL'
-
- # Default configuration.
- $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
-
- # Now print the configurations for the tags.
- for tagname in $taglist; do
- $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
- done
-
- exit $?
-}
-
-# func_features
-# Display the features supported by this script.
-func_features ()
-{
- $ECHO "host: $host"
- if test "$build_libtool_libs" = yes; then
- $ECHO "enable shared libraries"
- else
- $ECHO "disable shared libraries"
- fi
- if test "$build_old_libs" = yes; then
- $ECHO "enable static libraries"
- else
- $ECHO "disable static libraries"
- fi
-
- exit $?
-}
-
-# func_enable_tag tagname
-# Verify that TAGNAME is valid, and either flag an error and exit, or
-# enable the TAGNAME tag. We also add TAGNAME to the global $taglist
-# variable here.
-func_enable_tag ()
-{
- # Global variable:
- tagname="$1"
-
- re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
- re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
- sed_extractcf="/$re_begincf/,/$re_endcf/p"
-
- # Validate tagname.
- case $tagname in
- *[!-_A-Za-z0-9,/]*)
- func_fatal_error "invalid tag name: $tagname"
- ;;
- esac
-
- # Don't test for the "default" C tag, as we know it's
- # there but not specially marked.
- case $tagname in
- CC) ;;
- *)
- if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
- taglist="$taglist $tagname"
-
- # Evaluate the configuration. Be careful to quote the path
- # and the sed script, to avoid splitting on whitespace, but
- # also don't use non-portable quotes within backquotes within
- # quotes we have to do it in 2 steps:
- extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
- eval "$extractedcf"
- else
- func_error "ignoring unknown tag $tagname"
- fi
- ;;
- esac
-}
-
-# Parse options once, thoroughly. This comes as soon as possible in
-# the script to make things like `libtool --version' happen quickly.
-{
-
- # Shorthand for --mode=foo, only valid as the first argument
- case $1 in
- clean|clea|cle|cl)
- shift; set dummy --mode clean ${1+"$@"}; shift
- ;;
- compile|compil|compi|comp|com|co|c)
- shift; set dummy --mode compile ${1+"$@"}; shift
- ;;
- execute|execut|execu|exec|exe|ex|e)
- shift; set dummy --mode execute ${1+"$@"}; shift
- ;;
- finish|finis|fini|fin|fi|f)
- shift; set dummy --mode finish ${1+"$@"}; shift
- ;;
- install|instal|insta|inst|ins|in|i)
- shift; set dummy --mode install ${1+"$@"}; shift
- ;;
- link|lin|li|l)
- shift; set dummy --mode link ${1+"$@"}; shift
- ;;
- uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
- shift; set dummy --mode uninstall ${1+"$@"}; shift
- ;;
- esac
-
- # Parse non-mode specific arguments:
- while test "$#" -gt 0; do
- opt="$1"
- shift
-
- case $opt in
- --config) func_config ;;
-
- --debug) preserve_args="$preserve_args $opt"
- func_echo "enabling shell trace mode"
- opt_debug='set -x'
- $opt_debug
- ;;
-
- -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break
- execute_dlfiles="$execute_dlfiles $1"
- shift
- ;;
-
- --dry-run | -n) opt_dry_run=: ;;
- --features) func_features ;;
- --finish) mode="finish" ;;
-
- --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break
- case $1 in
- # Valid mode arguments:
- clean) ;;
- compile) ;;
- execute) ;;
- finish) ;;
- install) ;;
- link) ;;
- relink) ;;
- uninstall) ;;
-
- # Catch anything else as an error
- *) func_error "invalid argument for $opt"
- exit_cmd=exit
- break
- ;;
- esac
-
- mode="$1"
- shift
- ;;
-
- --preserve-dup-deps)
- opt_duplicate_deps=: ;;
-
- --quiet|--silent) preserve_args="$preserve_args $opt"
- opt_silent=:
- ;;
-
- --verbose| -v) preserve_args="$preserve_args $opt"
- opt_silent=false
- ;;
-
- --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break
- preserve_args="$preserve_args $opt $1"
- func_enable_tag "$1" # tagname is set here
- shift
- ;;
-
- # Separate optargs to long options:
- -dlopen=*|--mode=*|--tag=*)
- func_opt_split "$opt"
- set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
- shift
- ;;
-
- -\?|-h) func_usage ;;
- --help) opt_help=: ;;
- --version) func_version ;;
-
- -*) func_fatal_help "unrecognized option \`$opt'" ;;
-
- *) nonopt="$opt"
- break
- ;;
- esac
- done
-
-
- case $host in
- *cygwin* | *mingw* | *pw32* | *cegcc*)
- # don't eliminate duplications in $postdeps and $predeps
- opt_duplicate_compiler_generated_deps=:
- ;;
- *)
- opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
- ;;
- esac
-
- # Having warned about all mis-specified options, bail out if
- # anything was wrong.
- $exit_cmd $EXIT_FAILURE
-}
-
-# func_check_version_match
-# Ensure that we are using m4 macros, and libtool script from the same
-# release of libtool.
-func_check_version_match ()
-{
- if test "$package_revision" != "$macro_revision"; then
- if test "$VERSION" != "$macro_version"; then
- if test -z "$macro_version"; then
- cat >&2 <<_LT_EOF
-$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
-$progname: definition of this LT_INIT comes from an older release.
-$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
-$progname: and run autoconf again.
-_LT_EOF
- else
- cat >&2 <<_LT_EOF
-$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
-$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
-$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
-$progname: and run autoconf again.
-_LT_EOF
- fi
- else
- cat >&2 <<_LT_EOF
-$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision,
-$progname: but the definition of this LT_INIT comes from revision $macro_revision.
-$progname: You should recreate aclocal.m4 with macros from revision $package_revision
-$progname: of $PACKAGE $VERSION and run autoconf again.
-_LT_EOF
- fi
-
- exit $EXIT_MISMATCH
- fi
-}
-
-
-## ----------- ##
-## Main. ##
-## ----------- ##
-
-$opt_help || {
- # Sanity checks first:
- func_check_version_match
-
- if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
- func_fatal_configuration "not configured to build any kind of library"
- fi
-
- test -z "$mode" && func_fatal_error "error: you must specify a MODE."
-
-
- # Darwin sucks
- eval std_shrext=\"$shrext_cmds\"
-
-
- # Only execute mode is allowed to have -dlopen flags.
- if test -n "$execute_dlfiles" && test "$mode" != execute; then
- func_error "unrecognized option \`-dlopen'"
- $ECHO "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Change the help message to a mode-specific one.
- generic_help="$help"
- help="Try \`$progname --help --mode=$mode' for more information."
-}
-
-
-# func_lalib_p file
-# True iff FILE is a libtool `.la' library or `.lo' object file.
-# This function is only a basic sanity check; it will hardly flush out
-# determined imposters.
-func_lalib_p ()
-{
- test -f "$1" &&
- $SED -e 4q "$1" 2>/dev/null \
- | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
-}
-
-# func_lalib_unsafe_p file
-# True iff FILE is a libtool `.la' library or `.lo' object file.
-# This function implements the same check as func_lalib_p without
-# resorting to external programs. To this end, it redirects stdin and
-# closes it afterwards, without saving the original file descriptor.
-# As a safety measure, use it only where a negative result would be
-# fatal anyway. Works if `file' does not exist.
-func_lalib_unsafe_p ()
-{
- lalib_p=no
- if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
- for lalib_p_l in 1 2 3 4
- do
- read lalib_p_line
- case "$lalib_p_line" in
- \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
- esac
- done
- exec 0<&5 5<&-
- fi
- test "$lalib_p" = yes
-}
-
-# func_ltwrapper_script_p file
-# True iff FILE is a libtool wrapper script
-# This function is only a basic sanity check; it will hardly flush out
-# determined imposters.
-func_ltwrapper_script_p ()
-{
- func_lalib_p "$1"
-}
-
-# func_ltwrapper_executable_p file
-# True iff FILE is a libtool wrapper executable
-# This function is only a basic sanity check; it will hardly flush out
-# determined imposters.
-func_ltwrapper_executable_p ()
-{
- func_ltwrapper_exec_suffix=
- case $1 in
- *.exe) ;;
- *) func_ltwrapper_exec_suffix=.exe ;;
- esac
- $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
-}
-
-# func_ltwrapper_scriptname file
-# Assumes file is an ltwrapper_executable
-# uses $file to determine the appropriate filename for a
-# temporary ltwrapper_script.
-func_ltwrapper_scriptname ()
-{
- func_ltwrapper_scriptname_result=""
- if func_ltwrapper_executable_p "$1"; then
- func_dirname_and_basename "$1" "" "."
- func_stripname '' '.exe' "$func_basename_result"
- func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
- fi
-}
-
-# func_ltwrapper_p file
-# True iff FILE is a libtool wrapper script or wrapper executable
-# This function is only a basic sanity check; it will hardly flush out
-# determined imposters.
-func_ltwrapper_p ()
-{
- func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
-}
-
-
-# func_execute_cmds commands fail_cmd
-# Execute tilde-delimited COMMANDS.
-# If FAIL_CMD is given, eval that upon failure.
-# FAIL_CMD may read-access the current command in variable CMD!
-func_execute_cmds ()
-{
- $opt_debug
- save_ifs=$IFS; IFS='~'
- for cmd in $1; do
- IFS=$save_ifs
- eval cmd=\"$cmd\"
- func_show_eval "$cmd" "${2-:}"
- done
- IFS=$save_ifs
-}
-
-
-# func_source file
-# Source FILE, adding directory component if necessary.
-# Note that it is not necessary on cygwin/mingw to append a dot to
-# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
-# behavior happens only for exec(3), not for open(2)! Also, sourcing
-# `FILE.' does not work on cygwin managed mounts.
-func_source ()
-{
- $opt_debug
- case $1 in
- */* | *\\*) . "$1" ;;
- *) . "./$1" ;;
- esac
-}
-
-
-# func_infer_tag arg
-# Infer tagged configuration to use if any are available and
-# if one wasn't chosen via the "--tag" command line option.
-# Only attempt this if the compiler in the base compile
-# command doesn't match the default compiler.
-# arg is usually of the form 'gcc ...'
-func_infer_tag ()
-{
- $opt_debug
- if test -n "$available_tags" && test -z "$tagname"; then
- CC_quoted=
- for arg in $CC; do
- func_quote_for_eval "$arg"
- CC_quoted="$CC_quoted $func_quote_for_eval_result"
- done
- case $@ in
- # Blanks in the command may have been stripped by the calling shell,
- # but not from the CC environment variable when configure was run.
- " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;;
- # Blanks at the start of $base_compile will cause this to fail
- # if we don't check for them as well.
- *)
- for z in $available_tags; do
- if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
- # Evaluate the configuration.
- eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
- CC_quoted=
- for arg in $CC; do
- # Double-quote args containing other shell metacharacters.
- func_quote_for_eval "$arg"
- CC_quoted="$CC_quoted $func_quote_for_eval_result"
- done
- case "$@ " in
- " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*)
- # The compiler in the base compile command matches
- # the one in the tagged configuration.
- # Assume this is the tagged configuration we want.
- tagname=$z
- break
- ;;
- esac
- fi
- done
- # If $tagname still isn't set, then no tagged configuration
- # was found and let the user know that the "--tag" command
- # line option must be used.
- if test -z "$tagname"; then
- func_echo "unable to infer tagged configuration"
- func_fatal_error "specify a tag with \`--tag'"
-# else
-# func_verbose "using $tagname tagged configuration"
- fi
- ;;
- esac
- fi
-}
-
-
-
-# func_write_libtool_object output_name pic_name nonpic_name
-# Create a libtool object file (analogous to a ".la" file),
-# but don't create it if we're doing a dry run.
-func_write_libtool_object ()
-{
- write_libobj=${1}
- if test "$build_libtool_libs" = yes; then
- write_lobj=\'${2}\'
- else
- write_lobj=none
- fi
-
- if test "$build_old_libs" = yes; then
- write_oldobj=\'${3}\'
- else
- write_oldobj=none
- fi
-
- $opt_dry_run || {
- cat >${write_libobj}T <<EOF
-# $write_libobj - a libtool object file
-# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# Name of the PIC object.
-pic_object=$write_lobj
-
-# Name of the non-PIC object
-non_pic_object=$write_oldobj
-
-EOF
- $MV "${write_libobj}T" "${write_libobj}"
- }
-}
-
-# func_mode_compile arg...
-func_mode_compile ()
-{
- $opt_debug
- # Get the compilation command and the source file.
- base_compile=
- srcfile="$nonopt" # always keep a non-empty value in "srcfile"
- suppress_opt=yes
- suppress_output=
- arg_mode=normal
- libobj=
- later=
- pie_flag=
-
- for arg
- do
- case $arg_mode in
- arg )
- # do not "continue". Instead, add this to base_compile
- lastarg="$arg"
- arg_mode=normal
- ;;
-
- target )
- libobj="$arg"
- arg_mode=normal
- continue
- ;;
-
- normal )
- # Accept any command-line options.
- case $arg in
- -o)
- test -n "$libobj" && \
- func_fatal_error "you cannot specify \`-o' more than once"
- arg_mode=target
- continue
- ;;
-
- -pie | -fpie | -fPIE)
- pie_flag="$pie_flag $arg"
- continue
- ;;
-
- -shared | -static | -prefer-pic | -prefer-non-pic)
- later="$later $arg"
- continue
- ;;
-
- -no-suppress)
- suppress_opt=no
- continue
- ;;
-
- -Xcompiler)
- arg_mode=arg # the next one goes into the "base_compile" arg list
- continue # The current "srcfile" will either be retained or
- ;; # replaced later. I would guess that would be a bug.
-
- -Wc,*)
- func_stripname '-Wc,' '' "$arg"
- args=$func_stripname_result
- lastarg=
- save_ifs="$IFS"; IFS=','
- for arg in $args; do
- IFS="$save_ifs"
- func_quote_for_eval "$arg"
- lastarg="$lastarg $func_quote_for_eval_result"
- done
- IFS="$save_ifs"
- func_stripname ' ' '' "$lastarg"
- lastarg=$func_stripname_result
-
- # Add the arguments to base_compile.
- base_compile="$base_compile $lastarg"
- continue
- ;;
-
- *)
- # Accept the current argument as the source file.
- # The previous "srcfile" becomes the current argument.
- #
- lastarg="$srcfile"
- srcfile="$arg"
- ;;
- esac # case $arg
- ;;
- esac # case $arg_mode
-
- # Aesthetically quote the previous argument.
- func_quote_for_eval "$lastarg"
- base_compile="$base_compile $func_quote_for_eval_result"
- done # for arg
-
- case $arg_mode in
- arg)
- func_fatal_error "you must specify an argument for -Xcompile"
- ;;
- target)
- func_fatal_error "you must specify a target with \`-o'"
- ;;
- *)
- # Get the name of the library object.
- test -z "$libobj" && {
- func_basename "$srcfile"
- libobj="$func_basename_result"
- }
- ;;
- esac
-
- # Recognize several different file suffixes.
- # If the user specifies -o file.o, it is replaced with file.lo
- case $libobj in
- *.[cCFSifmso] | \
- *.ada | *.adb | *.ads | *.asm | \
- *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
- *.[fF][09]? | *.for | *.java | *.obj | *.sx)
- func_xform "$libobj"
- libobj=$func_xform_result
- ;;
- esac
-
- case $libobj in
- *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
- *)
- func_fatal_error "cannot determine name of library object from \`$libobj'"
- ;;
- esac
-
- func_infer_tag $base_compile
-
- for arg in $later; do
- case $arg in
- -shared)
- test "$build_libtool_libs" != yes && \
- func_fatal_configuration "can not build a shared library"
- build_old_libs=no
- continue
- ;;
-
- -static)
- build_libtool_libs=no
- build_old_libs=yes
- continue
- ;;
-
- -prefer-pic)
- pic_mode=yes
- continue
- ;;
-
- -prefer-non-pic)
- pic_mode=no
- continue
- ;;
- esac
- done
-
- func_quote_for_eval "$libobj"
- test "X$libobj" != "X$func_quote_for_eval_result" \
- && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \
- && func_warning "libobj name \`$libobj' may not contain shell special characters."
- func_dirname_and_basename "$obj" "/" ""
- objname="$func_basename_result"
- xdir="$func_dirname_result"
- lobj=${xdir}$objdir/$objname
-
- test -z "$base_compile" && \
- func_fatal_help "you must specify a compilation command"
-
- # Delete any leftover library objects.
- if test "$build_old_libs" = yes; then
- removelist="$obj $lobj $libobj ${libobj}T"
- else
- removelist="$lobj $libobj ${libobj}T"
- fi
-
- # On Cygwin there's no "real" PIC flag so we must build both object types
- case $host_os in
- cygwin* | mingw* | pw32* | os2* | cegcc*)
- pic_mode=default
- ;;
- esac
- if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
- # non-PIC code in shared libraries is not supported
- pic_mode=default
- fi
-
- # Calculate the filename of the output object if compiler does
- # not support -o with -c
- if test "$compiler_c_o" = no; then
- output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
- lockfile="$output_obj.lock"
- else
- output_obj=
- need_locks=no
- lockfile=
- fi
-
- # Lock this critical section if it is needed
- # We use this script file to make the link, it avoids creating a new file
- if test "$need_locks" = yes; then
- until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
- func_echo "Waiting for $lockfile to be removed"
- sleep 2
- done
- elif test "$need_locks" = warn; then
- if test -f "$lockfile"; then
- $ECHO "\
-*** ERROR, $lockfile exists and contains:
-`cat $lockfile 2>/dev/null`
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $opt_dry_run || $RM $removelist
- exit $EXIT_FAILURE
- fi
- removelist="$removelist $output_obj"
- $ECHO "$srcfile" > "$lockfile"
- fi
-
- $opt_dry_run || $RM $removelist
- removelist="$removelist $lockfile"
- trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
-
- if test -n "$fix_srcfile_path"; then
- eval srcfile=\"$fix_srcfile_path\"
- fi
- func_quote_for_eval "$srcfile"
- qsrcfile=$func_quote_for_eval_result
-
- # Only build a PIC object if we are building libtool libraries.
- if test "$build_libtool_libs" = yes; then
- # Without this assignment, base_compile gets emptied.
- fbsd_hideous_sh_bug=$base_compile
-
- if test "$pic_mode" != no; then
- command="$base_compile $qsrcfile $pic_flag"
- else
- # Don't build PIC code
- command="$base_compile $qsrcfile"
- fi
-
- func_mkdir_p "$xdir$objdir"
-
- if test -z "$output_obj"; then
- # Place PIC objects in $objdir
- command="$command -o $lobj"
- fi
-
- func_show_eval_locale "$command" \
- 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
-
- if test "$need_locks" = warn &&
- test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
- $ECHO "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $opt_dry_run || $RM $removelist
- exit $EXIT_FAILURE
- fi
-
- # Just move the object if needed, then go on to compile the next one
- if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
- func_show_eval '$MV "$output_obj" "$lobj"' \
- 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
- fi
-
- # Allow error messages only from the first compilation.
- if test "$suppress_opt" = yes; then
- suppress_output=' >/dev/null 2>&1'
- fi
- fi
-
- # Only build a position-dependent object if we build old libraries.
- if test "$build_old_libs" = yes; then
- if test "$pic_mode" != yes; then
- # Don't build PIC code
- command="$base_compile $qsrcfile$pie_flag"
- else
- command="$base_compile $qsrcfile $pic_flag"
- fi
- if test "$compiler_c_o" = yes; then
- command="$command -o $obj"
- fi
-
- # Suppress compiler output if we already did a PIC compilation.
- command="$command$suppress_output"
- func_show_eval_locale "$command" \
- '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
-
- if test "$need_locks" = warn &&
- test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
- $ECHO "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $opt_dry_run || $RM $removelist
- exit $EXIT_FAILURE
- fi
-
- # Just move the object if needed
- if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
- func_show_eval '$MV "$output_obj" "$obj"' \
- 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
- fi
- fi
-
- $opt_dry_run || {
- func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
-
- # Unlock the critical section if it was locked
- if test "$need_locks" != no; then
- removelist=$lockfile
- $RM "$lockfile"
- fi
- }
-
- exit $EXIT_SUCCESS
-}
-
-$opt_help || {
-test "$mode" = compile && func_mode_compile ${1+"$@"}
-}
-
-func_mode_help ()
-{
- # We need to display help for each of the modes.
- case $mode in
- "")
- # Generic help is extracted from the usage comments
- # at the start of this file.
- func_help
- ;;
-
- clean)
- $ECHO \
-"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
-
-Remove files from the build directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, object or program, all the files associated
-with it are deleted. Otherwise, only FILE itself is deleted using RM."
- ;;
-
- compile)
- $ECHO \
-"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
-
-Compile a source file into a libtool library object.
-
-This mode accepts the following additional options:
-
- -o OUTPUT-FILE set the output file name to OUTPUT-FILE
- -no-suppress do not suppress compiler output for multiple passes
- -prefer-pic try to building PIC objects only
- -prefer-non-pic try to building non-PIC objects only
- -shared do not build a \`.o' file suitable for static linking
- -static only build a \`.o' file suitable for static linking
-
-COMPILE-COMMAND is a command to be used in creating a \`standard' object file
-from the given SOURCEFILE.
-
-The output file name is determined by removing the directory component from
-SOURCEFILE, then substituting the C source code suffix \`.c' with the
-library object suffix, \`.lo'."
- ;;
-
- execute)
- $ECHO \
-"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
-
-Automatically set library path, then run a program.
-
-This mode accepts the following additional options:
-
- -dlopen FILE add the directory containing FILE to the library path
-
-This mode sets the library path environment variable according to \`-dlopen'
-flags.
-
-If any of the ARGS are libtool executable wrappers, then they are translated
-into their corresponding uninstalled binary, and any of their required library
-directories are added to the library path.
-
-Then, COMMAND is executed, with ARGS as arguments."
- ;;
-
- finish)
- $ECHO \
-"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
-
-Complete the installation of libtool libraries.
-
-Each LIBDIR is a directory that contains libtool libraries.
-
-The commands that this mode executes may require superuser privileges. Use
-the \`--dry-run' option if you just want to see what would be executed."
- ;;
-
- install)
- $ECHO \
-"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
-
-Install executables or libraries.
-
-INSTALL-COMMAND is the installation command. The first component should be
-either the \`install' or \`cp' program.
-
-The following components of INSTALL-COMMAND are treated specially:
-
- -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation
-
-The rest of the components are interpreted as arguments to that command (only
-BSD-compatible install options are recognized)."
- ;;
-
- link)
- $ECHO \
-"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
-
-Link object files or libraries together to form another library, or to
-create an executable program.
-
-LINK-COMMAND is a command using the C compiler that you would use to create
-a program from several object files.
-
-The following components of LINK-COMMAND are treated specially:
-
- -all-static do not do any dynamic linking at all
- -avoid-version do not add a version suffix if possible
- -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
- -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
- -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
- -export-symbols SYMFILE
- try to export only the symbols listed in SYMFILE
- -export-symbols-regex REGEX
- try to export only the symbols matching REGEX
- -LLIBDIR search LIBDIR for required installed libraries
- -lNAME OUTPUT-FILE requires the installed library libNAME
- -module build a library that can dlopened
- -no-fast-install disable the fast-install mode
- -no-install link a not-installable executable
- -no-undefined declare that a library does not refer to external symbols
- -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
- -objectlist FILE Use a list of object files found in FILE to specify objects
- -precious-files-regex REGEX
- don't remove output files matching REGEX
- -release RELEASE specify package release information
- -rpath LIBDIR the created library will eventually be installed in LIBDIR
- -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
- -shared only do dynamic linking of libtool libraries
- -shrext SUFFIX override the standard shared library file extension
- -static do not do any dynamic linking of uninstalled libtool libraries
- -static-libtool-libs
- do not do any dynamic linking of libtool libraries
- -version-info CURRENT[:REVISION[:AGE]]
- specify library version info [each variable defaults to 0]
- -weak LIBNAME declare that the target provides the LIBNAME interface
-
-All other options (arguments beginning with \`-') are ignored.
-
-Every other argument is treated as a filename. Files ending in \`.la' are
-treated as uninstalled libtool libraries, other files are standard or library
-object files.
-
-If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
-only library objects (\`.lo' files) may be specified, and \`-rpath' is
-required, except when creating a convenience library.
-
-If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
-using \`ar' and \`ranlib', or on Windows using \`lib'.
-
-If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
-is created, otherwise an executable program is created."
- ;;
-
- uninstall)
- $ECHO \
-"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
-
-Remove libraries from an installation directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, all the files associated with it are deleted.
-Otherwise, only FILE itself is deleted using RM."
- ;;
-
- *)
- func_fatal_help "invalid operation mode \`$mode'"
- ;;
- esac
-
- $ECHO
- $ECHO "Try \`$progname --help' for more information about other modes."
-
- exit $?
-}
-
- # Now that we've collected a possible --mode arg, show help if necessary
- $opt_help && func_mode_help
-
-
-# func_mode_execute arg...
-func_mode_execute ()
-{
- $opt_debug
- # The first argument is the command name.
- cmd="$nonopt"
- test -z "$cmd" && \
- func_fatal_help "you must specify a COMMAND"
-
- # Handle -dlopen flags immediately.
- for file in $execute_dlfiles; do
- test -f "$file" \
- || func_fatal_help "\`$file' is not a file"
-
- dir=
- case $file in
- *.la)
- # Check to see that this really is a libtool archive.
- func_lalib_unsafe_p "$file" \
- || func_fatal_help "\`$lib' is not a valid libtool archive"
-
- # Read the libtool library.
- dlname=
- library_names=
- func_source "$file"
-
- # Skip this library if it cannot be dlopened.
- if test -z "$dlname"; then
- # Warn if it was a shared library.
- test -n "$library_names" && \
- func_warning "\`$file' was not linked with \`-export-dynamic'"
- continue
- fi
-
- func_dirname "$file" "" "."
- dir="$func_dirname_result"
-
- if test -f "$dir/$objdir/$dlname"; then
- dir="$dir/$objdir"
- else
- if test ! -f "$dir/$dlname"; then
- func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
- fi
- fi
- ;;
-
- *.lo)
- # Just add the directory containing the .lo file.
- func_dirname "$file" "" "."
- dir="$func_dirname_result"
- ;;
-
- *)
- func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
- continue
- ;;
- esac
-
- # Get the absolute pathname.
- absdir=`cd "$dir" && pwd`
- test -n "$absdir" && dir="$absdir"
-
- # Now add the directory to shlibpath_var.
- if eval "test -z \"\$$shlibpath_var\""; then
- eval "$shlibpath_var=\"\$dir\""
- else
- eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
- fi
- done
-
- # This variable tells wrapper scripts just to set shlibpath_var
- # rather than running their programs.
- libtool_execute_magic="$magic"
-
- # Check if any of the arguments is a wrapper script.
- args=
- for file
- do
- case $file in
- -*) ;;
- *)
- # Do a test to see if this is really a libtool program.
- if func_ltwrapper_script_p "$file"; then
- func_source "$file"
- # Transform arg to wrapped name.
- file="$progdir/$program"
- elif func_ltwrapper_executable_p "$file"; then
- func_ltwrapper_scriptname "$file"
- func_source "$func_ltwrapper_scriptname_result"
- # Transform arg to wrapped name.
- file="$progdir/$program"
- fi
- ;;
- esac
- # Quote arguments (to preserve shell metacharacters).
- func_quote_for_eval "$file"
- args="$args $func_quote_for_eval_result"
- done
-
- if test "X$opt_dry_run" = Xfalse; then
- if test -n "$shlibpath_var"; then
- # Export the shlibpath_var.
- eval "export $shlibpath_var"
- fi
-
- # Restore saved environment variables
- for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
- do
- eval "if test \"\${save_$lt_var+set}\" = set; then
- $lt_var=\$save_$lt_var; export $lt_var
- else
- $lt_unset $lt_var
- fi"
- done
-
- # Now prepare to actually exec the command.
- exec_cmd="\$cmd$args"
- else
- # Display what would be done.
- if test -n "$shlibpath_var"; then
- eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
- $ECHO "export $shlibpath_var"
- fi
- $ECHO "$cmd$args"
- exit $EXIT_SUCCESS
- fi
-}
-
-test "$mode" = execute && func_mode_execute ${1+"$@"}
-
-
-# func_mode_finish arg...
-func_mode_finish ()
-{
- $opt_debug
- libdirs="$nonopt"
- admincmds=
-
- if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
- for dir
- do
- libdirs="$libdirs $dir"
- done
-
- for libdir in $libdirs; do
- if test -n "$finish_cmds"; then
- # Do each command in the finish commands.
- func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
-'"$cmd"'"'
- fi
- if test -n "$finish_eval"; then
- # Do the single finish_eval.
- eval cmds=\"$finish_eval\"
- $opt_dry_run || eval "$cmds" || admincmds="$admincmds
- $cmds"
- fi
- done
- fi
-
- # Exit here if they wanted silent mode.
- $opt_silent && exit $EXIT_SUCCESS
-
- $ECHO "X----------------------------------------------------------------------" | $Xsed
- $ECHO "Libraries have been installed in:"
- for libdir in $libdirs; do
- $ECHO " $libdir"
- done
- $ECHO
- $ECHO "If you ever happen to want to link against installed libraries"
- $ECHO "in a given directory, LIBDIR, you must either use libtool, and"
- $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'"
- $ECHO "flag during linking and do at least one of the following:"
- if test -n "$shlibpath_var"; then
- $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable"
- $ECHO " during execution"
- fi
- if test -n "$runpath_var"; then
- $ECHO " - add LIBDIR to the \`$runpath_var' environment variable"
- $ECHO " during linking"
- fi
- if test -n "$hardcode_libdir_flag_spec"; then
- libdir=LIBDIR
- eval flag=\"$hardcode_libdir_flag_spec\"
-
- $ECHO " - use the \`$flag' linker flag"
- fi
- if test -n "$admincmds"; then
- $ECHO " - have your system administrator run these commands:$admincmds"
- fi
- if test -f /etc/ld.so.conf; then
- $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
- fi
- $ECHO
-
- $ECHO "See any operating system documentation about shared libraries for"
- case $host in
- solaris2.[6789]|solaris2.1[0-9])
- $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual"
- $ECHO "pages."
- ;;
- *)
- $ECHO "more information, such as the ld(1) and ld.so(8) manual pages."
- ;;
- esac
- $ECHO "X----------------------------------------------------------------------" | $Xsed
- exit $EXIT_SUCCESS
-}
-
-test "$mode" = finish && func_mode_finish ${1+"$@"}
-
-
-# func_mode_install arg...
-func_mode_install ()
-{
- $opt_debug
- # There may be an optional sh(1) argument at the beginning of
- # install_prog (especially on Windows NT).
- if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
- # Allow the use of GNU shtool's install command.
- $ECHO "X$nonopt" | $GREP shtool >/dev/null; then
- # Aesthetically quote it.
- func_quote_for_eval "$nonopt"
- install_prog="$func_quote_for_eval_result "
- arg=$1
- shift
- else
- install_prog=
- arg=$nonopt
- fi
-
- # The real first argument should be the name of the installation program.
- # Aesthetically quote it.
- func_quote_for_eval "$arg"
- install_prog="$install_prog$func_quote_for_eval_result"
-
- # We need to accept at least all the BSD install flags.
- dest=
- files=
- opts=
- prev=
- install_type=
- isdir=no
- stripme=
- for arg
- do
- if test -n "$dest"; then
- files="$files $dest"
- dest=$arg
- continue
- fi
-
- case $arg in
- -d) isdir=yes ;;
- -f)
- case " $install_prog " in
- *[\\\ /]cp\ *) ;;
- *) prev=$arg ;;
- esac
- ;;
- -g | -m | -o)
- prev=$arg
- ;;
- -s)
- stripme=" -s"
- continue
- ;;
- -*)
- ;;
- *)
- # If the previous option needed an argument, then skip it.
- if test -n "$prev"; then
- prev=
- else
- dest=$arg
- continue
- fi
- ;;
- esac
-
- # Aesthetically quote the argument.
- func_quote_for_eval "$arg"
- install_prog="$install_prog $func_quote_for_eval_result"
- done
-
- test -z "$install_prog" && \
- func_fatal_help "you must specify an install program"
-
- test -n "$prev" && \
- func_fatal_help "the \`$prev' option requires an argument"
-
- if test -z "$files"; then
- if test -z "$dest"; then
- func_fatal_help "no file or destination specified"
- else
- func_fatal_help "you must specify a destination"
- fi
- fi
-
- # Strip any trailing slash from the destination.
- func_stripname '' '/' "$dest"
- dest=$func_stripname_result
-
- # Check to see that the destination is a directory.
- test -d "$dest" && isdir=yes
- if test "$isdir" = yes; then
- destdir="$dest"
- destname=
- else
- func_dirname_and_basename "$dest" "" "."
- destdir="$func_dirname_result"
- destname="$func_basename_result"
-
- # Not a directory, so check to see that there is only one file specified.
- set dummy $files; shift
- test "$#" -gt 1 && \
- func_fatal_help "\`$dest' is not a directory"
- fi
- case $destdir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- for file in $files; do
- case $file in
- *.lo) ;;
- *)
- func_fatal_help "\`$destdir' must be an absolute directory name"
- ;;
- esac
- done
- ;;
- esac
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- staticlibs=
- future_libdirs=
- current_libdirs=
- for file in $files; do
-
- # Do each installation.
- case $file in
- *.$libext)
- # Do the static libraries later.
- staticlibs="$staticlibs $file"
- ;;
-
- *.la)
- # Check to see that this really is a libtool archive.
- func_lalib_unsafe_p "$file" \
- || func_fatal_help "\`$file' is not a valid libtool archive"
-
- library_names=
- old_library=
- relink_command=
- func_source "$file"
-
- # Add the libdir to current_libdirs if it is the destination.
- if test "X$destdir" = "X$libdir"; then
- case "$current_libdirs " in
- *" $libdir "*) ;;
- *) current_libdirs="$current_libdirs $libdir" ;;
- esac
- else
- # Note the libdir as a future libdir.
- case "$future_libdirs " in
- *" $libdir "*) ;;
- *) future_libdirs="$future_libdirs $libdir" ;;
- esac
- fi
-
- func_dirname "$file" "/" ""
- dir="$func_dirname_result"
- dir="$dir$objdir"
-
- if test -n "$relink_command"; then
- # Determine the prefix the user has applied to our future dir.
- inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"`
-
- # Don't allow the user to place us outside of our expected
- # location b/c this prevents finding dependent libraries that
- # are installed to the same prefix.
- # At present, this check doesn't affect windows .dll's that
- # are installed into $libdir/../bin (currently, that works fine)
- # but it's something to keep an eye on.
- test "$inst_prefix_dir" = "$destdir" && \
- func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
-
- if test -n "$inst_prefix_dir"; then
- # Stick the inst_prefix_dir data into the link command.
- relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
- else
- relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"`
- fi
-
- func_warning "relinking \`$file'"
- func_show_eval "$relink_command" \
- 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
- fi
-
- # See the names of the shared library.
- set dummy $library_names; shift
- if test -n "$1"; then
- realname="$1"
- shift
-
- srcname="$realname"
- test -n "$relink_command" && srcname="$realname"T
-
- # Install the shared library and build the symlinks.
- func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \
- 'exit $?'
- tstripme="$stripme"
- case $host_os in
- cygwin* | mingw* | pw32* | cegcc*)
- case $realname in
- *.dll.a)
- tstripme=""
- ;;
- esac
- ;;
- esac
- if test -n "$tstripme" && test -n "$striplib"; then
- func_show_eval "$striplib $destdir/$realname" 'exit $?'
- fi
-
- if test "$#" -gt 0; then
- # Delete the old symlinks, and create new ones.
- # Try `ln -sf' first, because the `ln' binary might depend on
- # the symlink we replace! Solaris /bin/ln does not understand -f,
- # so we also need to try rm && ln -s.
- for linkname
- do
- test "$linkname" != "$realname" \
- && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
- done
- fi
-
- # Do each command in the postinstall commands.
- lib="$destdir/$realname"
- func_execute_cmds "$postinstall_cmds" 'exit $?'
- fi
-
- # Install the pseudo-library for information purposes.
- func_basename "$file"
- name="$func_basename_result"
- instname="$dir/$name"i
- func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
-
- # Maybe install the static library, too.
- test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
- ;;
-
- *.lo)
- # Install (i.e. copy) a libtool object.
-
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- func_basename "$file"
- destfile="$func_basename_result"
- destfile="$destdir/$destfile"
- fi
-
- # Deduce the name of the destination old-style object file.
- case $destfile in
- *.lo)
- func_lo2o "$destfile"
- staticdest=$func_lo2o_result
- ;;
- *.$objext)
- staticdest="$destfile"
- destfile=
- ;;
- *)
- func_fatal_help "cannot copy a libtool object to \`$destfile'"
- ;;
- esac
-
- # Install the libtool object if requested.
- test -n "$destfile" && \
- func_show_eval "$install_prog $file $destfile" 'exit $?'
-
- # Install the old object if enabled.
- if test "$build_old_libs" = yes; then
- # Deduce the name of the old-style object file.
- func_lo2o "$file"
- staticobj=$func_lo2o_result
- func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
- fi
- exit $EXIT_SUCCESS
- ;;
-
- *)
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- func_basename "$file"
- destfile="$func_basename_result"
- destfile="$destdir/$destfile"
- fi
-
- # If the file is missing, and there is a .exe on the end, strip it
- # because it is most likely a libtool script we actually want to
- # install
- stripped_ext=""
- case $file in
- *.exe)
- if test ! -f "$file"; then
- func_stripname '' '.exe' "$file"
- file=$func_stripname_result
- stripped_ext=".exe"
- fi
- ;;
- esac
-
- # Do a test to see if this is really a libtool program.
- case $host in
- *cygwin* | *mingw*)
- if func_ltwrapper_executable_p "$file"; then
- func_ltwrapper_scriptname "$file"
- wrapper=$func_ltwrapper_scriptname_result
- else
- func_stripname '' '.exe' "$file"
- wrapper=$func_stripname_result
- fi
- ;;
- *)
- wrapper=$file
- ;;
- esac
- if func_ltwrapper_script_p "$wrapper"; then
- notinst_deplibs=
- relink_command=
-
- func_source "$wrapper"
-
- # Check the variables that should have been set.
- test -z "$generated_by_libtool_version" && \
- func_fatal_error "invalid libtool wrapper script \`$wrapper'"
-
- finalize=yes
- for lib in $notinst_deplibs; do
- # Check to see that each library is installed.
- libdir=
- if test -f "$lib"; then
- func_source "$lib"
- fi
- libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
- if test -n "$libdir" && test ! -f "$libfile"; then
- func_warning "\`$lib' has not been installed in \`$libdir'"
- finalize=no
- fi
- done
-
- relink_command=
- func_source "$wrapper"
-
- outputname=
- if test "$fast_install" = no && test -n "$relink_command"; then
- $opt_dry_run || {
- if test "$finalize" = yes; then
- tmpdir=`func_mktempdir`
- func_basename "$file$stripped_ext"
- file="$func_basename_result"
- outputname="$tmpdir/$file"
- # Replace the output file specification.
- relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-
- $opt_silent || {
- func_quote_for_expand "$relink_command"
- eval "func_echo $func_quote_for_expand_result"
- }
- if eval "$relink_command"; then :
- else
- func_error "error: relink \`$file' with the above command before installing it"
- $opt_dry_run || ${RM}r "$tmpdir"
- continue
- fi
- file="$outputname"
- else
- func_warning "cannot relink \`$file'"
- fi
- }
- else
- # Install the binary that we compiled earlier.
- file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
- fi
- fi
-
- # remove .exe since cygwin /usr/bin/install will append another
- # one anyway
- case $install_prog,$host in
- */usr/bin/install*,*cygwin*)
- case $file:$destfile in
- *.exe:*.exe)
- # this is ok
- ;;
- *.exe:*)
- destfile=$destfile.exe
- ;;
- *:*.exe)
- func_stripname '' '.exe' "$destfile"
- destfile=$func_stripname_result
- ;;
- esac
- ;;
- esac
- func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
- $opt_dry_run || if test -n "$outputname"; then
- ${RM}r "$tmpdir"
- fi
- ;;
- esac
- done
-
- for file in $staticlibs; do
- func_basename "$file"
- name="$func_basename_result"
-
- # Set up the ranlib parameters.
- oldlib="$destdir/$name"
-
- func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
-
- if test -n "$stripme" && test -n "$old_striplib"; then
- func_show_eval "$old_striplib $oldlib" 'exit $?'
- fi
-
- # Do each command in the postinstall commands.
- func_execute_cmds "$old_postinstall_cmds" 'exit $?'
- done
-
- test -n "$future_libdirs" && \
- func_warning "remember to run \`$progname --finish$future_libdirs'"
-
- if test -n "$current_libdirs"; then
- # Maybe just do a dry run.
- $opt_dry_run && current_libdirs=" -n$current_libdirs"
- exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
- else
- exit $EXIT_SUCCESS
- fi
-}
-
-test "$mode" = install && func_mode_install ${1+"$@"}
-
-
-# func_generate_dlsyms outputname originator pic_p
-# Extract symbols from dlprefiles and create ${outputname}S.o with
-# a dlpreopen symbol table.
-func_generate_dlsyms ()
-{
- $opt_debug
- my_outputname="$1"
- my_originator="$2"
- my_pic_p="${3-no}"
- my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
- my_dlsyms=
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- if test -n "$NM" && test -n "$global_symbol_pipe"; then
- my_dlsyms="${my_outputname}S.c"
- else
- func_error "not configured to extract global symbols from dlpreopened files"
- fi
- fi
-
- if test -n "$my_dlsyms"; then
- case $my_dlsyms in
- "") ;;
- *.c)
- # Discover the nlist of each of the dlfiles.
- nlist="$output_objdir/${my_outputname}.nm"
-
- func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
-
- # Parse the name list into a source file.
- func_verbose "creating $output_objdir/$my_dlsyms"
-
- $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
-/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
-/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
-
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-
-/* External symbol declarations for the compiler. */\
-"
-
- if test "$dlself" = yes; then
- func_verbose "generating symbol list for \`$output'"
-
- $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
-
- # Add our own program objects to the symbol list.
- progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- for progfile in $progfiles; do
- func_verbose "extracting global C symbols from \`$progfile'"
- $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -n "$exclude_expsyms"; then
- $opt_dry_run || {
- eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
- eval '$MV "$nlist"T "$nlist"'
- }
- fi
-
- if test -n "$export_symbols_regex"; then
- $opt_dry_run || {
- eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
- eval '$MV "$nlist"T "$nlist"'
- }
- fi
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- export_symbols="$output_objdir/$outputname.exp"
- $opt_dry_run || {
- $RM $export_symbols
- eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
- case $host in
- *cygwin* | *mingw* | *cegcc* )
- eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
- eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
- ;;
- esac
- }
- else
- $opt_dry_run || {
- eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
- eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
- eval '$MV "$nlist"T "$nlist"'
- case $host in
- *cygwin | *mingw* | *cegcc* )
- eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
- eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
- ;;
- esac
- }
- fi
- fi
-
- for dlprefile in $dlprefiles; do
- func_verbose "extracting global C symbols from \`$dlprefile'"
- func_basename "$dlprefile"
- name="$func_basename_result"
- $opt_dry_run || {
- eval '$ECHO ": $name " >> "$nlist"'
- eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
- }
- done
-
- $opt_dry_run || {
- # Make sure we have at least an empty file.
- test -f "$nlist" || : > "$nlist"
-
- if test -n "$exclude_expsyms"; then
- $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
- $MV "$nlist"T "$nlist"
- fi
-
- # Try sorting and uniquifying the output.
- if $GREP -v "^: " < "$nlist" |
- if sort -k 3 </dev/null >/dev/null 2>&1; then
- sort -k 3
- else
- sort +2
- fi |
- uniq > "$nlist"S; then
- :
- else
- $GREP -v "^: " < "$nlist" > "$nlist"S
- fi
-
- if test -f "$nlist"S; then
- eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
- else
- $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms"
- fi
-
- $ECHO >> "$output_objdir/$my_dlsyms" "\
-
-/* The mapping between symbol names and symbols. */
-typedef struct {
- const char *name;
- void *address;
-} lt_dlsymlist;
-"
- case $host in
- *cygwin* | *mingw* | *cegcc* )
- $ECHO >> "$output_objdir/$my_dlsyms" "\
-/* DATA imports from DLLs on WIN32 con't be const, because
- runtime relocations are performed -- see ld's documentation
- on pseudo-relocs. */"
- lt_dlsym_const= ;;
- *osf5*)
- echo >> "$output_objdir/$my_dlsyms" "\
-/* This system does not cope well with relocations in const data */"
- lt_dlsym_const= ;;
- *)
- lt_dlsym_const=const ;;
- esac
-
- $ECHO >> "$output_objdir/$my_dlsyms" "\
-extern $lt_dlsym_const lt_dlsymlist
-lt_${my_prefix}_LTX_preloaded_symbols[];
-$lt_dlsym_const lt_dlsymlist
-lt_${my_prefix}_LTX_preloaded_symbols[] =
-{\
- { \"$my_originator\", (void *) 0 },"
-
- case $need_lib_prefix in
- no)
- eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
- ;;
- *)
- eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
- ;;
- esac
- $ECHO >> "$output_objdir/$my_dlsyms" "\
- {0, (void *) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
- return lt_${my_prefix}_LTX_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif\
-"
- } # !$opt_dry_run
-
- pic_flag_for_symtable=
- case "$compile_command " in
- *" -static "*) ;;
- *)
- case $host in
- # compiling the symbol table file with pic_flag works around
- # a FreeBSD bug that causes programs to crash when -lm is
- # linked before any other PIC object. But we must not use
- # pic_flag when linking with -static. The problem exists in
- # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
- *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
- pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
- *-*-hpux*)
- pic_flag_for_symtable=" $pic_flag" ;;
- *)
- if test "X$my_pic_p" != Xno; then
- pic_flag_for_symtable=" $pic_flag"
- fi
- ;;
- esac
- ;;
- esac
- symtab_cflags=
- for arg in $LTCFLAGS; do
- case $arg in
- -pie | -fpie | -fPIE) ;;
- *) symtab_cflags="$symtab_cflags $arg" ;;
- esac
- done
-
- # Now compile the dynamic symbol file.
- func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
-
- # Clean up the generated files.
- func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
-
- # Transform the symbol file into the correct name.
- symfileobj="$output_objdir/${my_outputname}S.$objext"
- case $host in
- *cygwin* | *mingw* | *cegcc* )
- if test -f "$output_objdir/$my_outputname.def"; then
- compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
- finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
- else
- compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
- finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
- fi
- ;;
- *)
- compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
- finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
- ;;
- esac
- ;;
- *)
- func_fatal_error "unknown suffix for \`$my_dlsyms'"
- ;;
- esac
- else
- # We keep going just in case the user didn't refer to
- # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
- # really was required.
-
- # Nullify the symbol file.
- compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
- finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
- fi
-}
-
-# func_win32_libid arg
-# return the library type of file 'arg'
-#
-# Need a lot of goo to handle *both* DLLs and import libs
-# Has to be a shell function in order to 'eat' the argument
-# that is supplied when $file_magic_command is called.
-func_win32_libid ()
-{
- $opt_debug
- win32_libid_type="unknown"
- win32_fileres=`file -L $1 2>/dev/null`
- case $win32_fileres in
- *ar\ archive\ import\ library*) # definitely import
- win32_libid_type="x86 archive import"
- ;;
- *ar\ archive*) # could be an import, or static
- if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
- $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
- win32_nmres=`eval $NM -f posix -A $1 |
- $SED -n -e '
- 1,100{
- / I /{
- s,.*,import,
- p
- q
- }
- }'`
- case $win32_nmres in
- import*) win32_libid_type="x86 archive import";;
- *) win32_libid_type="x86 archive static";;
- esac
- fi
- ;;
- *DLL*)
- win32_libid_type="x86 DLL"
- ;;
- *executable*) # but shell scripts are "executable" too...
- case $win32_fileres in
- *MS\ Windows\ PE\ Intel*)
- win32_libid_type="x86 DLL"
- ;;
- esac
- ;;
- esac
- $ECHO "$win32_libid_type"
-}
-
-
-
-# func_extract_an_archive dir oldlib
-func_extract_an_archive ()
-{
- $opt_debug
- f_ex_an_ar_dir="$1"; shift
- f_ex_an_ar_oldlib="$1"
- func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?'
- if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
- fi
-}
-
-
-# func_extract_archives gentop oldlib ...
-func_extract_archives ()
-{
- $opt_debug
- my_gentop="$1"; shift
- my_oldlibs=${1+"$@"}
- my_oldobjs=""
- my_xlib=""
- my_xabs=""
- my_xdir=""
-
- for my_xlib in $my_oldlibs; do
- # Extract the objects.
- case $my_xlib in
- [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
- *) my_xabs=`pwd`"/$my_xlib" ;;
- esac
- func_basename "$my_xlib"
- my_xlib="$func_basename_result"
- my_xlib_u=$my_xlib
- while :; do
- case " $extracted_archives " in
- *" $my_xlib_u "*)
- func_arith $extracted_serial + 1
- extracted_serial=$func_arith_result
- my_xlib_u=lt$extracted_serial-$my_xlib ;;
- *) break ;;
- esac
- done
- extracted_archives="$extracted_archives $my_xlib_u"
- my_xdir="$my_gentop/$my_xlib_u"
-
- func_mkdir_p "$my_xdir"
-
- case $host in
- *-darwin*)
- func_verbose "Extracting $my_xabs"
- # Do not bother doing anything if just a dry run
- $opt_dry_run || {
- darwin_orig_dir=`pwd`
- cd $my_xdir || exit $?
- darwin_archive=$my_xabs
- darwin_curdir=`pwd`
- darwin_base_archive=`basename "$darwin_archive"`
- darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
- if test -n "$darwin_arches"; then
- darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
- darwin_arch=
- func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
- for darwin_arch in $darwin_arches ; do
- func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
- $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
- cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
- func_extract_an_archive "`pwd`" "${darwin_base_archive}"
- cd "$darwin_curdir"
- $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
- done # $darwin_arches
- ## Okay now we've a bunch of thin objects, gotta fatten them up :)
- darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
- darwin_file=
- darwin_files=
- for darwin_file in $darwin_filelist; do
- darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
- $LIPO -create -output "$darwin_file" $darwin_files
- done # $darwin_filelist
- $RM -rf unfat-$$
- cd "$darwin_orig_dir"
- else
- cd $darwin_orig_dir
- func_extract_an_archive "$my_xdir" "$my_xabs"
- fi # $darwin_arches
- } # !$opt_dry_run
- ;;
- *)
- func_extract_an_archive "$my_xdir" "$my_xabs"
- ;;
- esac
- my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
- done
-
- func_extract_archives_result="$my_oldobjs"
-}
-
-
-
-# func_emit_wrapper_part1 [arg=no]
-#
-# Emit the first part of a libtool wrapper script on stdout.
-# For more information, see the description associated with
-# func_emit_wrapper(), below.
-func_emit_wrapper_part1 ()
-{
- func_emit_wrapper_part1_arg1=no
- if test -n "$1" ; then
- func_emit_wrapper_part1_arg1=$1
- fi
-
- $ECHO "\
-#! $SHELL
-
-# $output - temporary wrapper script for $objdir/$outputname
-# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
-#
-# The $output program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='${SED} -e 1s/^X//'
-sed_quote_subst='$sed_quote_subst'
-
-# Be Bourne compatible
-if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '\${1+\"\$@\"}'='\"\$@\"'
- setopt NO_GLOB_SUBST
-else
- case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
-fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-relink_command=\"$relink_command\"
-
-# This environment variable determines our operation mode.
-if test \"\$libtool_install_magic\" = \"$magic\"; then
- # install mode needs the following variables:
- generated_by_libtool_version='$macro_version'
- notinst_deplibs='$notinst_deplibs'
-else
- # When we are sourced in execute mode, \$file and \$ECHO are already set.
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- ECHO=\"$qecho\"
- file=\"\$0\"
- # Make sure echo works.
- if test \"X\$1\" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
- elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then
- # Yippee, \$ECHO works!
- :
- else
- # Restart under the correct shell, and then maybe \$ECHO will work.
- exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
- fi
- fi\
-"
- $ECHO "\
-
- # Find the directory that this script lives in.
- thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
- test \"x\$thisdir\" = \"x\$file\" && thisdir=.
-
- # Follow symbolic links until we get to the real thisdir.
- file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
- while test -n \"\$file\"; do
- destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
-
- # If there was a directory component, then change thisdir.
- if test \"x\$destdir\" != \"x\$file\"; then
- case \"\$destdir\" in
- [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
- *) thisdir=\"\$thisdir/\$destdir\" ;;
- esac
- fi
-
- file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
- file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
- done
-"
-}
-# end: func_emit_wrapper_part1
-
-# func_emit_wrapper_part2 [arg=no]
-#
-# Emit the second part of a libtool wrapper script on stdout.
-# For more information, see the description associated with
-# func_emit_wrapper(), below.
-func_emit_wrapper_part2 ()
-{
- func_emit_wrapper_part2_arg1=no
- if test -n "$1" ; then
- func_emit_wrapper_part2_arg1=$1
- fi
-
- $ECHO "\
-
- # Usually 'no', except on cygwin/mingw when embedded into
- # the cwrapper.
- WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1
- if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
- # special case for '.'
- if test \"\$thisdir\" = \".\"; then
- thisdir=\`pwd\`
- fi
- # remove .libs from thisdir
- case \"\$thisdir\" in
- *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;;
- $objdir ) thisdir=. ;;
- esac
- fi
-
- # Try to get the absolute directory name.
- absdir=\`cd \"\$thisdir\" && pwd\`
- test -n \"\$absdir\" && thisdir=\"\$absdir\"
-"
-
- if test "$fast_install" = yes; then
- $ECHO "\
- program=lt-'$outputname'$exeext
- progdir=\"\$thisdir/$objdir\"
-
- if test ! -f \"\$progdir/\$program\" ||
- { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
- test \"X\$file\" != \"X\$progdir/\$program\"; }; then
-
- file=\"\$\$-\$program\"
-
- if test ! -d \"\$progdir\"; then
- $MKDIR \"\$progdir\"
- else
- $RM \"\$progdir/\$file\"
- fi"
-
- $ECHO "\
-
- # relink executable if necessary
- if test -n \"\$relink_command\"; then
- if relink_command_output=\`eval \$relink_command 2>&1\`; then :
- else
- $ECHO \"\$relink_command_output\" >&2
- $RM \"\$progdir/\$file\"
- exit 1
- fi
- fi
-
- $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
- { $RM \"\$progdir/\$program\";
- $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
- $RM \"\$progdir/\$file\"
- fi"
- else
- $ECHO "\
- program='$outputname'
- progdir=\"\$thisdir/$objdir\"
-"
- fi
-
- $ECHO "\
-
- if test -f \"\$progdir/\$program\"; then"
-
- # Export our shlibpath_var if we have one.
- if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
- $ECHO "\
- # Add our own library path to $shlibpath_var
- $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
- # Some systems cannot cope with colon-terminated $shlibpath_var
- # The second colon is a workaround for a bug in BeOS R4 sed
- $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
- export $shlibpath_var
-"
- fi
-
- # fixup the dll searchpath if we need to.
- if test -n "$dllsearchpath"; then
- $ECHO "\
- # Add the dll search path components to the executable PATH
- PATH=$dllsearchpath:\$PATH
-"
- fi
-
- $ECHO "\
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- # Run the actual program with our arguments.
-"
- case $host in
- # Backslashes separate directories on plain windows
- *-*-mingw | *-*-os2* | *-cegcc*)
- $ECHO "\
- exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
-"
- ;;
-
- *)
- $ECHO "\
- exec \"\$progdir/\$program\" \${1+\"\$@\"}
-"
- ;;
- esac
- $ECHO "\
- \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
- exit 1
- fi
- else
- # The program doesn't exist.
- \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
- \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
- $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
- exit 1
- fi
-fi\
-"
-}
-# end: func_emit_wrapper_part2
-
-
-# func_emit_wrapper [arg=no]
-#
-# Emit a libtool wrapper script on stdout.
-# Don't directly open a file because we may want to
-# incorporate the script contents within a cygwin/mingw
-# wrapper executable. Must ONLY be called from within
-# func_mode_link because it depends on a number of variables
-# set therein.
-#
-# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
-# variable will take. If 'yes', then the emitted script
-# will assume that the directory in which it is stored is
-# the $objdir directory. This is a cygwin/mingw-specific
-# behavior.
-func_emit_wrapper ()
-{
- func_emit_wrapper_arg1=no
- if test -n "$1" ; then
- func_emit_wrapper_arg1=$1
- fi
-
- # split this up so that func_emit_cwrapperexe_src
- # can call each part independently.
- func_emit_wrapper_part1 "${func_emit_wrapper_arg1}"
- func_emit_wrapper_part2 "${func_emit_wrapper_arg1}"
-}
-
-
-# func_to_host_path arg
-#
-# Convert paths to host format when used with build tools.
-# Intended for use with "native" mingw (where libtool itself
-# is running under the msys shell), or in the following cross-
-# build environments:
-# $build $host
-# mingw (msys) mingw [e.g. native]
-# cygwin mingw
-# *nix + wine mingw
-# where wine is equipped with the `winepath' executable.
-# In the native mingw case, the (msys) shell automatically
-# converts paths for any non-msys applications it launches,
-# but that facility isn't available from inside the cwrapper.
-# Similar accommodations are necessary for $host mingw and
-# $build cygwin. Calling this function does no harm for other
-# $host/$build combinations not listed above.
-#
-# ARG is the path (on $build) that should be converted to
-# the proper representation for $host. The result is stored
-# in $func_to_host_path_result.
-func_to_host_path ()
-{
- func_to_host_path_result="$1"
- if test -n "$1" ; then
- case $host in
- *mingw* )
- lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
- case $build in
- *mingw* ) # actually, msys
- # awkward: cmd appends spaces to result
- lt_sed_strip_trailing_spaces="s/[ ]*\$//"
- func_to_host_path_tmp1=`( cmd //c echo "$1" |\
- $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
- func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
- $SED -e "$lt_sed_naive_backslashify"`
- ;;
- *cygwin* )
- func_to_host_path_tmp1=`cygpath -w "$1"`
- func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
- $SED -e "$lt_sed_naive_backslashify"`
- ;;
- * )
- # Unfortunately, winepath does not exit with a non-zero
- # error code, so we are forced to check the contents of
- # stdout. On the other hand, if the command is not
- # found, the shell will set an exit code of 127 and print
- # *an error message* to stdout. So we must check for both
- # error code of zero AND non-empty stdout, which explains
- # the odd construction:
- func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null`
- if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then
- func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
- $SED -e "$lt_sed_naive_backslashify"`
- else
- # Allow warning below.
- func_to_host_path_result=""
- fi
- ;;
- esac
- if test -z "$func_to_host_path_result" ; then
- func_error "Could not determine host path corresponding to"
- func_error " '$1'"
- func_error "Continuing, but uninstalled executables may not work."
- # Fallback:
- func_to_host_path_result="$1"
- fi
- ;;
- esac
- fi
-}
-# end: func_to_host_path
-
-# func_to_host_pathlist arg
-#
-# Convert pathlists to host format when used with build tools.
-# See func_to_host_path(), above. This function supports the
-# following $build/$host combinations (but does no harm for
-# combinations not listed here):
-# $build $host
-# mingw (msys) mingw [e.g. native]
-# cygwin mingw
-# *nix + wine mingw
-#
-# Path separators are also converted from $build format to
-# $host format. If ARG begins or ends with a path separator
-# character, it is preserved (but converted to $host format)
-# on output.
-#
-# ARG is a pathlist (on $build) that should be converted to
-# the proper representation on $host. The result is stored
-# in $func_to_host_pathlist_result.
-func_to_host_pathlist ()
-{
- func_to_host_pathlist_result="$1"
- if test -n "$1" ; then
- case $host in
- *mingw* )
- lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
- # Remove leading and trailing path separator characters from
- # ARG. msys behavior is inconsistent here, cygpath turns them
- # into '.;' and ';.', and winepath ignores them completely.
- func_to_host_pathlist_tmp2="$1"
- # Once set for this call, this variable should not be
- # reassigned. It is used in tha fallback case.
- func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\
- $SED -e 's|^:*||' -e 's|:*$||'`
- case $build in
- *mingw* ) # Actually, msys.
- # Awkward: cmd appends spaces to result.
- lt_sed_strip_trailing_spaces="s/[ ]*\$//"
- func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\
- $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
- func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
- $SED -e "$lt_sed_naive_backslashify"`
- ;;
- *cygwin* )
- func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"`
- func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
- $SED -e "$lt_sed_naive_backslashify"`
- ;;
- * )
- # unfortunately, winepath doesn't convert pathlists
- func_to_host_pathlist_result=""
- func_to_host_pathlist_oldIFS=$IFS
- IFS=:
- for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do
- IFS=$func_to_host_pathlist_oldIFS
- if test -n "$func_to_host_pathlist_f" ; then
- func_to_host_path "$func_to_host_pathlist_f"
- if test -n "$func_to_host_path_result" ; then
- if test -z "$func_to_host_pathlist_result" ; then
- func_to_host_pathlist_result="$func_to_host_path_result"
- else
- func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result"
- fi
- fi
- fi
- IFS=:
- done
- IFS=$func_to_host_pathlist_oldIFS
- ;;
- esac
- if test -z "$func_to_host_pathlist_result" ; then
- func_error "Could not determine the host path(s) corresponding to"
- func_error " '$1'"
- func_error "Continuing, but uninstalled executables may not work."
- # Fallback. This may break if $1 contains DOS-style drive
- # specifications. The fix is not to complicate the expression
- # below, but for the user to provide a working wine installation
- # with winepath so that path translation in the cross-to-mingw
- # case works properly.
- lt_replace_pathsep_nix_to_dos="s|:|;|g"
- func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\
- $SED -e "$lt_replace_pathsep_nix_to_dos"`
- fi
- # Now, add the leading and trailing path separators back
- case "$1" in
- :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result"
- ;;
- esac
- case "$1" in
- *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;"
- ;;
- esac
- ;;
- esac
- fi
-}
-# end: func_to_host_pathlist
-
-# func_emit_cwrapperexe_src
-# emit the source code for a wrapper executable on stdout
-# Must ONLY be called from within func_mode_link because
-# it depends on a number of variable set therein.
-func_emit_cwrapperexe_src ()
-{
- cat <<EOF
-
-/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
- Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
-
- The $output program cannot be directly executed until all the libtool
- libraries that it depends on are installed.
-
- This wrapper executable should never be moved out of the build directory.
- If it is, it will not operate correctly.
-
- Currently, it simply execs the wrapper *script* "$SHELL $output",
- but could eventually absorb all of the scripts functionality and
- exec $objdir/$outputname directly.
-*/
-EOF
- cat <<"EOF"
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef _MSC_VER
-# include <direct.h>
-# include <process.h>
-# include <io.h>
-# define setmode _setmode
-#else
-# include <unistd.h>
-# include <stdint.h>
-# ifdef __CYGWIN__
-# include <io.h>
-# define HAVE_SETENV
-# ifdef __STRICT_ANSI__
-char *realpath (const char *, char *);
-int putenv (char *);
-int setenv (const char *, const char *, int);
-# endif
-# endif
-#endif
-#include <malloc.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#if defined(PATH_MAX)
-# define LT_PATHMAX PATH_MAX
-#elif defined(MAXPATHLEN)
-# define LT_PATHMAX MAXPATHLEN
-#else
-# define LT_PATHMAX 1024
-#endif
-
-#ifndef S_IXOTH
-# define S_IXOTH 0
-#endif
-#ifndef S_IXGRP
-# define S_IXGRP 0
-#endif
-
-#ifdef _MSC_VER
-# define S_IXUSR _S_IEXEC
-# define stat _stat
-# ifndef _INTPTR_T_DEFINED
-# define intptr_t int
-# endif
-#endif
-
-#ifndef DIR_SEPARATOR
-# define DIR_SEPARATOR '/'
-# define PATH_SEPARATOR ':'
-#endif
-
-#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
- defined (__OS2__)
-# define HAVE_DOS_BASED_FILE_SYSTEM
-# define FOPEN_WB "wb"
-# ifndef DIR_SEPARATOR_2
-# define DIR_SEPARATOR_2 '\\'
-# endif
-# ifndef PATH_SEPARATOR_2
-# define PATH_SEPARATOR_2 ';'
-# endif
-#endif
-
-#ifndef DIR_SEPARATOR_2
-# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
-#else /* DIR_SEPARATOR_2 */
-# define IS_DIR_SEPARATOR(ch) \
- (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
-#endif /* DIR_SEPARATOR_2 */
-
-#ifndef PATH_SEPARATOR_2
-# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
-#else /* PATH_SEPARATOR_2 */
-# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
-#endif /* PATH_SEPARATOR_2 */
-
-#ifdef __CYGWIN__
-# define FOPEN_WB "wb"
-#endif
-
-#ifndef FOPEN_WB
-# define FOPEN_WB "w"
-#endif
-#ifndef _O_BINARY
-# define _O_BINARY 0
-#endif
-
-#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
-#define XFREE(stale) do { \
- if (stale) { free ((void *) stale); stale = 0; } \
-} while (0)
-
-#undef LTWRAPPER_DEBUGPRINTF
-#if defined DEBUGWRAPPER
-# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
-static void
-ltwrapper_debugprintf (const char *fmt, ...)
-{
- va_list args;
- va_start (args, fmt);
- (void) vfprintf (stderr, fmt, args);
- va_end (args);
-}
-#else
-# define LTWRAPPER_DEBUGPRINTF(args)
-#endif
-
-const char *program_name = NULL;
-
-void *xmalloc (size_t num);
-char *xstrdup (const char *string);
-const char *base_name (const char *name);
-char *find_executable (const char *wrapper);
-char *chase_symlinks (const char *pathspec);
-int make_executable (const char *path);
-int check_executable (const char *path);
-char *strendzap (char *str, const char *pat);
-void lt_fatal (const char *message, ...);
-void lt_setenv (const char *name, const char *value);
-char *lt_extend_str (const char *orig_value, const char *add, int to_end);
-void lt_opt_process_env_set (const char *arg);
-void lt_opt_process_env_prepend (const char *arg);
-void lt_opt_process_env_append (const char *arg);
-int lt_split_name_value (const char *arg, char** name, char** value);
-void lt_update_exe_path (const char *name, const char *value);
-void lt_update_lib_path (const char *name, const char *value);
-
-static const char *script_text_part1 =
-EOF
-
- func_emit_wrapper_part1 yes |
- $SED -e 's/\([\\"]\)/\\\1/g' \
- -e 's/^/ "/' -e 's/$/\\n"/'
- echo ";"
- cat <<EOF
-
-static const char *script_text_part2 =
-EOF
- func_emit_wrapper_part2 yes |
- $SED -e 's/\([\\"]\)/\\\1/g' \
- -e 's/^/ "/' -e 's/$/\\n"/'
- echo ";"
-
- cat <<EOF
-const char * MAGIC_EXE = "$magic_exe";
-const char * LIB_PATH_VARNAME = "$shlibpath_var";
-EOF
-
- if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
- func_to_host_pathlist "$temp_rpath"
- cat <<EOF
-const char * LIB_PATH_VALUE = "$func_to_host_pathlist_result";
-EOF
- else
- cat <<"EOF"
-const char * LIB_PATH_VALUE = "";
-EOF
- fi
-
- if test -n "$dllsearchpath"; then
- func_to_host_pathlist "$dllsearchpath:"
- cat <<EOF
-const char * EXE_PATH_VARNAME = "PATH";
-const char * EXE_PATH_VALUE = "$func_to_host_pathlist_result";
-EOF
- else
- cat <<"EOF"
-const char * EXE_PATH_VARNAME = "";
-const char * EXE_PATH_VALUE = "";
-EOF
- fi
-
- if test "$fast_install" = yes; then
- cat <<EOF
-const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
-EOF
- else
- cat <<EOF
-const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
-EOF
- fi
-
-
- cat <<"EOF"
-
-#define LTWRAPPER_OPTION_PREFIX "--lt-"
-#define LTWRAPPER_OPTION_PREFIX_LENGTH 5
-
-static const size_t opt_prefix_len = LTWRAPPER_OPTION_PREFIX_LENGTH;
-static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
-
-static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script";
-
-static const size_t env_set_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 7;
-static const char *env_set_opt = LTWRAPPER_OPTION_PREFIX "env-set";
- /* argument is putenv-style "foo=bar", value of foo is set to bar */
-
-static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11;
-static const char *env_prepend_opt = LTWRAPPER_OPTION_PREFIX "env-prepend";
- /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
-
-static const size_t env_append_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 10;
-static const char *env_append_opt = LTWRAPPER_OPTION_PREFIX "env-append";
- /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
-
-int
-main (int argc, char *argv[])
-{
- char **newargz;
- int newargc;
- char *tmp_pathspec;
- char *actual_cwrapper_path;
- char *actual_cwrapper_name;
- char *target_name;
- char *lt_argv_zero;
- intptr_t rval = 127;
-
- int i;
-
- program_name = (char *) xstrdup (base_name (argv[0]));
- LTWRAPPER_DEBUGPRINTF (("(main) argv[0] : %s\n", argv[0]));
- LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
-
- /* very simple arg parsing; don't want to rely on getopt */
- for (i = 1; i < argc; i++)
- {
- if (strcmp (argv[i], dumpscript_opt) == 0)
- {
-EOF
- case "$host" in
- *mingw* | *cygwin* )
- # make stdout use "unix" line endings
- echo " setmode(1,_O_BINARY);"
- ;;
- esac
-
- cat <<"EOF"
- printf ("%s", script_text_part1);
- printf ("%s", script_text_part2);
- return 0;
- }
- }
-
- newargz = XMALLOC (char *, argc + 1);
- tmp_pathspec = find_executable (argv[0]);
- if (tmp_pathspec == NULL)
- lt_fatal ("Couldn't find %s", argv[0]);
- LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
- tmp_pathspec));
-
- actual_cwrapper_path = chase_symlinks (tmp_pathspec);
- LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
- actual_cwrapper_path));
- XFREE (tmp_pathspec);
-
- actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
- strendzap (actual_cwrapper_path, actual_cwrapper_name);
-
- /* wrapper name transforms */
- strendzap (actual_cwrapper_name, ".exe");
- tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
- XFREE (actual_cwrapper_name);
- actual_cwrapper_name = tmp_pathspec;
- tmp_pathspec = 0;
-
- /* target_name transforms -- use actual target program name; might have lt- prefix */
- target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
- strendzap (target_name, ".exe");
- tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
- XFREE (target_name);
- target_name = tmp_pathspec;
- tmp_pathspec = 0;
-
- LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
- target_name));
-EOF
-
- cat <<EOF
- newargz[0] =
- XMALLOC (char, (strlen (actual_cwrapper_path) +
- strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
- strcpy (newargz[0], actual_cwrapper_path);
- strcat (newargz[0], "$objdir");
- strcat (newargz[0], "/");
-EOF
-
- cat <<"EOF"
- /* stop here, and copy so we don't have to do this twice */
- tmp_pathspec = xstrdup (newargz[0]);
-
- /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
- strcat (newargz[0], actual_cwrapper_name);
-
- /* DO want the lt- prefix here if it exists, so use target_name */
- lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
- XFREE (tmp_pathspec);
- tmp_pathspec = NULL;
-EOF
-
- case $host_os in
- mingw*)
- cat <<"EOF"
- {
- char* p;
- while ((p = strchr (newargz[0], '\\')) != NULL)
- {
- *p = '/';
- }
- while ((p = strchr (lt_argv_zero, '\\')) != NULL)
- {
- *p = '/';
- }
- }
-EOF
- ;;
- esac
-
- cat <<"EOF"
- XFREE (target_name);
- XFREE (actual_cwrapper_path);
- XFREE (actual_cwrapper_name);
-
- lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
- lt_setenv ("DUALCASE", "1"); /* for MSK sh */
- lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
- lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
-
- newargc=0;
- for (i = 1; i < argc; i++)
- {
- if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0)
- {
- if (argv[i][env_set_opt_len] == '=')
- {
- const char *p = argv[i] + env_set_opt_len + 1;
- lt_opt_process_env_set (p);
- }
- else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc)
- {
- lt_opt_process_env_set (argv[++i]); /* don't copy */
- }
- else
- lt_fatal ("%s missing required argument", env_set_opt);
- continue;
- }
- if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0)
- {
- if (argv[i][env_prepend_opt_len] == '=')
- {
- const char *p = argv[i] + env_prepend_opt_len + 1;
- lt_opt_process_env_prepend (p);
- }
- else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc)
- {
- lt_opt_process_env_prepend (argv[++i]); /* don't copy */
- }
- else
- lt_fatal ("%s missing required argument", env_prepend_opt);
- continue;
- }
- if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0)
- {
- if (argv[i][env_append_opt_len] == '=')
- {
- const char *p = argv[i] + env_append_opt_len + 1;
- lt_opt_process_env_append (p);
- }
- else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc)
- {
- lt_opt_process_env_append (argv[++i]); /* don't copy */
- }
- else
- lt_fatal ("%s missing required argument", env_append_opt);
- continue;
- }
- if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
- {
- /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
- namespace, but it is not one of the ones we know about and
- have already dealt with, above (inluding dump-script), then
- report an error. Otherwise, targets might begin to believe
- they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
- namespace. The first time any user complains about this, we'll
- need to make LTWRAPPER_OPTION_PREFIX a configure-time option
- or a configure.ac-settable value.
- */
- lt_fatal ("Unrecognized option in %s namespace: '%s'",
- ltwrapper_option_prefix, argv[i]);
- }
- /* otherwise ... */
- newargz[++newargc] = xstrdup (argv[i]);
- }
- newargz[++newargc] = NULL;
-
- LTWRAPPER_DEBUGPRINTF (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
- for (i = 0; i < newargc; i++)
- {
- LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
- }
-
-EOF
-
- case $host_os in
- mingw*)
- cat <<"EOF"
- /* execv doesn't actually work on mingw as expected on unix */
- rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
- if (rval == -1)
- {
- /* failed to start process */
- LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno));
- return 127;
- }
- return rval;
-EOF
- ;;
- *)
- cat <<"EOF"
- execv (lt_argv_zero, newargz);
- return rval; /* =127, but avoids unused variable warning */
-EOF
- ;;
- esac
-
- cat <<"EOF"
-}
-
-void *
-xmalloc (size_t num)
-{
- void *p = (void *) malloc (num);
- if (!p)
- lt_fatal ("Memory exhausted");
-
- return p;
-}
-
-char *
-xstrdup (const char *string)
-{
- return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
- string) : NULL;
-}
-
-const char *
-base_name (const char *name)
-{
- const char *base;
-
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- /* Skip over the disk name in MSDOS pathnames. */
- if (isalpha ((unsigned char) name[0]) && name[1] == ':')
- name += 2;
-#endif
-
- for (base = name; *name; name++)
- if (IS_DIR_SEPARATOR (*name))
- base = name + 1;
- return base;
-}
-
-int
-check_executable (const char *path)
-{
- struct stat st;
-
- LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n",
- path ? (*path ? path : "EMPTY!") : "NULL!"));
- if ((!path) || (!*path))
- return 0;
-
- if ((stat (path, &st) >= 0)
- && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
- return 1;
- else
- return 0;
-}
-
-int
-make_executable (const char *path)
-{
- int rval = 0;
- struct stat st;
-
- LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n",
- path ? (*path ? path : "EMPTY!") : "NULL!"));
- if ((!path) || (!*path))
- return 0;
-
- if (stat (path, &st) >= 0)
- {
- rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
- }
- return rval;
-}
-
-/* Searches for the full path of the wrapper. Returns
- newly allocated full path name if found, NULL otherwise
- Does not chase symlinks, even on platforms that support them.
-*/
-char *
-find_executable (const char *wrapper)
-{
- int has_slash = 0;
- const char *p;
- const char *p_next;
- /* static buffer for getcwd */
- char tmp[LT_PATHMAX + 1];
- int tmp_len;
- char *concat_name;
-
- LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n",
- wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
-
- if ((wrapper == NULL) || (*wrapper == '\0'))
- return NULL;
-
- /* Absolute path? */
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
- {
- concat_name = xstrdup (wrapper);
- if (check_executable (concat_name))
- return concat_name;
- XFREE (concat_name);
- }
- else
- {
-#endif
- if (IS_DIR_SEPARATOR (wrapper[0]))
- {
- concat_name = xstrdup (wrapper);
- if (check_executable (concat_name))
- return concat_name;
- XFREE (concat_name);
- }
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- }
-#endif
-
- for (p = wrapper; *p; p++)
- if (*p == '/')
- {
- has_slash = 1;
- break;
- }
- if (!has_slash)
- {
- /* no slashes; search PATH */
- const char *path = getenv ("PATH");
- if (path != NULL)
- {
- for (p = path; *p; p = p_next)
- {
- const char *q;
- size_t p_len;
- for (q = p; *q; q++)
- if (IS_PATH_SEPARATOR (*q))
- break;
- p_len = q - p;
- p_next = (*q == '\0' ? q : q + 1);
- if (p_len == 0)
- {
- /* empty path: current directory */
- if (getcwd (tmp, LT_PATHMAX) == NULL)
- lt_fatal ("getcwd failed");
- tmp_len = strlen (tmp);
- concat_name =
- XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
- memcpy (concat_name, tmp, tmp_len);
- concat_name[tmp_len] = '/';
- strcpy (concat_name + tmp_len + 1, wrapper);
- }
- else
- {
- concat_name =
- XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
- memcpy (concat_name, p, p_len);
- concat_name[p_len] = '/';
- strcpy (concat_name + p_len + 1, wrapper);
- }
- if (check_executable (concat_name))
- return concat_name;
- XFREE (concat_name);
- }
- }
- /* not found in PATH; assume curdir */
- }
- /* Relative path | not found in path: prepend cwd */
- if (getcwd (tmp, LT_PATHMAX) == NULL)
- lt_fatal ("getcwd failed");
- tmp_len = strlen (tmp);
- concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
- memcpy (concat_name, tmp, tmp_len);
- concat_name[tmp_len] = '/';
- strcpy (concat_name + tmp_len + 1, wrapper);
-
- if (check_executable (concat_name))
- return concat_name;
- XFREE (concat_name);
- return NULL;
-}
-
-char *
-chase_symlinks (const char *pathspec)
-{
-#ifndef S_ISLNK
- return xstrdup (pathspec);
-#else
- char buf[LT_PATHMAX];
- struct stat s;
- char *tmp_pathspec = xstrdup (pathspec);
- char *p;
- int has_symlinks = 0;
- while (strlen (tmp_pathspec) && !has_symlinks)
- {
- LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n",
- tmp_pathspec));
- if (lstat (tmp_pathspec, &s) == 0)
- {
- if (S_ISLNK (s.st_mode) != 0)
- {
- has_symlinks = 1;
- break;
- }
-
- /* search backwards for last DIR_SEPARATOR */
- p = tmp_pathspec + strlen (tmp_pathspec) - 1;
- while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
- p--;
- if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
- {
- /* no more DIR_SEPARATORS left */
- break;
- }
- *p = '\0';
- }
- else
- {
- char *errstr = strerror (errno);
- lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
- }
- }
- XFREE (tmp_pathspec);
-
- if (!has_symlinks)
- {
- return xstrdup (pathspec);
- }
-
- tmp_pathspec = realpath (pathspec, buf);
- if (tmp_pathspec == 0)
- {
- lt_fatal ("Could not follow symlinks for %s", pathspec);
- }
- return xstrdup (tmp_pathspec);
-#endif
-}
-
-char *
-strendzap (char *str, const char *pat)
-{
- size_t len, patlen;
-
- assert (str != NULL);
- assert (pat != NULL);
-
- len = strlen (str);
- patlen = strlen (pat);
-
- if (patlen <= len)
- {
- str += len - patlen;
- if (strcmp (str, pat) == 0)
- *str = '\0';
- }
- return str;
-}
-
-static void
-lt_error_core (int exit_status, const char *mode,
- const char *message, va_list ap)
-{
- fprintf (stderr, "%s: %s: ", program_name, mode);
- vfprintf (stderr, message, ap);
- fprintf (stderr, ".\n");
-
- if (exit_status >= 0)
- exit (exit_status);
-}
-
-void
-lt_fatal (const char *message, ...)
-{
- va_list ap;
- va_start (ap, message);
- lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
- va_end (ap);
-}
-
-void
-lt_setenv (const char *name, const char *value)
-{
- LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
- (name ? name : "<NULL>"),
- (value ? value : "<NULL>")));
- {
-#ifdef HAVE_SETENV
- /* always make a copy, for consistency with !HAVE_SETENV */
- char *str = xstrdup (value);
- setenv (name, str, 1);
-#else
- int len = strlen (name) + 1 + strlen (value) + 1;
- char *str = XMALLOC (char, len);
- sprintf (str, "%s=%s", name, value);
- if (putenv (str) != EXIT_SUCCESS)
- {
- XFREE (str);
- }
-#endif
- }
-}
-
-char *
-lt_extend_str (const char *orig_value, const char *add, int to_end)
-{
- char *new_value;
- if (orig_value && *orig_value)
- {
- int orig_value_len = strlen (orig_value);
- int add_len = strlen (add);
- new_value = XMALLOC (char, add_len + orig_value_len + 1);
- if (to_end)
- {
- strcpy (new_value, orig_value);
- strcpy (new_value + orig_value_len, add);
- }
- else
- {
- strcpy (new_value, add);
- strcpy (new_value + add_len, orig_value);
- }
- }
- else
- {
- new_value = xstrdup (add);
- }
- return new_value;
-}
-
-int
-lt_split_name_value (const char *arg, char** name, char** value)
-{
- const char *p;
- int len;
- if (!arg || !*arg)
- return 1;
-
- p = strchr (arg, (int)'=');
-
- if (!p)
- return 1;
-
- *value = xstrdup (++p);
-
- len = strlen (arg) - strlen (*value);
- *name = XMALLOC (char, len);
- strncpy (*name, arg, len-1);
- (*name)[len - 1] = '\0';
-
- return 0;
-}
-
-void
-lt_opt_process_env_set (const char *arg)
-{
- char *name = NULL;
- char *value = NULL;
-
- if (lt_split_name_value (arg, &name, &value) != 0)
- {
- XFREE (name);
- XFREE (value);
- lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg);
- }
-
- lt_setenv (name, value);
- XFREE (name);
- XFREE (value);
-}
-
-void
-lt_opt_process_env_prepend (const char *arg)
-{
- char *name = NULL;
- char *value = NULL;
- char *new_value = NULL;
-
- if (lt_split_name_value (arg, &name, &value) != 0)
- {
- XFREE (name);
- XFREE (value);
- lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg);
- }
-
- new_value = lt_extend_str (getenv (name), value, 0);
- lt_setenv (name, new_value);
- XFREE (new_value);
- XFREE (name);
- XFREE (value);
-}
-
-void
-lt_opt_process_env_append (const char *arg)
-{
- char *name = NULL;
- char *value = NULL;
- char *new_value = NULL;
-
- if (lt_split_name_value (arg, &name, &value) != 0)
- {
- XFREE (name);
- XFREE (value);
- lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg);
- }
-
- new_value = lt_extend_str (getenv (name), value, 1);
- lt_setenv (name, new_value);
- XFREE (new_value);
- XFREE (name);
- XFREE (value);
-}
-
-void
-lt_update_exe_path (const char *name, const char *value)
-{
- LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
- (name ? name : "<NULL>"),
- (value ? value : "<NULL>")));
-
- if (name && *name && value && *value)
- {
- char *new_value = lt_extend_str (getenv (name), value, 0);
- /* some systems can't cope with a ':'-terminated path #' */
- int len = strlen (new_value);
- while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
- {
- new_value[len-1] = '\0';
- }
- lt_setenv (name, new_value);
- XFREE (new_value);
- }
-}
-
-void
-lt_update_lib_path (const char *name, const char *value)
-{
- LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
- (name ? name : "<NULL>"),
- (value ? value : "<NULL>")));
-
- if (name && *name && value && *value)
- {
- char *new_value = lt_extend_str (getenv (name), value, 0);
- lt_setenv (name, new_value);
- XFREE (new_value);
- }
-}
-
-
-EOF
-}
-# end: func_emit_cwrapperexe_src
-
-# func_mode_link arg...
-func_mode_link ()
-{
- $opt_debug
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
- # It is impossible to link a dll without this setting, and
- # we shouldn't force the makefile maintainer to figure out
- # which system we are compiling for in order to pass an extra
- # flag for every libtool invocation.
- # allow_undefined=no
-
- # FIXME: Unfortunately, there are problems with the above when trying
- # to make a dll which has undefined symbols, in which case not
- # even a static library is built. For now, we need to specify
- # -no-undefined on the libtool link line when we can be certain
- # that all symbols are satisfied, otherwise we get a static library.
- allow_undefined=yes
- ;;
- *)
- allow_undefined=yes
- ;;
- esac
- libtool_args=$nonopt
- base_compile="$nonopt $@"
- compile_command=$nonopt
- finalize_command=$nonopt
-
- compile_rpath=
- finalize_rpath=
- compile_shlibpath=
- finalize_shlibpath=
- convenience=
- old_convenience=
- deplibs=
- old_deplibs=
- compiler_flags=
- linker_flags=
- dllsearchpath=
- lib_search_path=`pwd`
- inst_prefix_dir=
- new_inherited_linker_flags=
-
- avoid_version=no
- dlfiles=
- dlprefiles=
- dlself=no
- export_dynamic=no
- export_symbols=
- export_symbols_regex=
- generated=
- libobjs=
- ltlibs=
- module=no
- no_install=no
- objs=
- non_pic_objects=
- precious_files_regex=
- prefer_static_libs=no
- preload=no
- prev=
- prevarg=
- release=
- rpath=
- xrpath=
- perm_rpath=
- temp_rpath=
- thread_safe=no
- vinfo=
- vinfo_number=no
- weak_libs=
- single_module="${wl}-single_module"
- func_infer_tag $base_compile
-
- # We need to know -static, to get the right output filenames.
- for arg
- do
- case $arg in
- -shared)
- test "$build_libtool_libs" != yes && \
- func_fatal_configuration "can not build a shared library"
- build_old_libs=no
- break
- ;;
- -all-static | -static | -static-libtool-libs)
- case $arg in
- -all-static)
- if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
- func_warning "complete static linking is impossible in this configuration"
- fi
- if test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- prefer_static_libs=yes
- ;;
- -static)
- if test -z "$pic_flag" && test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- prefer_static_libs=built
- ;;
- -static-libtool-libs)
- if test -z "$pic_flag" && test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- prefer_static_libs=yes
- ;;
- esac
- build_libtool_libs=no
- build_old_libs=yes
- break
- ;;
- esac
- done
-
- # See if our shared archives depend on static archives.
- test -n "$old_archive_from_new_cmds" && build_old_libs=yes
-
- # Go through the arguments, transforming them on the way.
- while test "$#" -gt 0; do
- arg="$1"
- shift
- func_quote_for_eval "$arg"
- qarg=$func_quote_for_eval_unquoted_result
- func_append libtool_args " $func_quote_for_eval_result"
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- case $prev in
- output)
- func_append compile_command " @OUTPUT@"
- func_append finalize_command " @OUTPUT@"
- ;;
- esac
-
- case $prev in
- dlfiles|dlprefiles)
- if test "$preload" = no; then
- # Add the symbol object into the linking commands.
- func_append compile_command " @SYMFILE@"
- func_append finalize_command " @SYMFILE@"
- preload=yes
- fi
- case $arg in
- *.la | *.lo) ;; # We handle these cases below.
- force)
- if test "$dlself" = no; then
- dlself=needless
- export_dynamic=yes
- fi
- prev=
- continue
- ;;
- self)
- if test "$prev" = dlprefiles; then
- dlself=yes
- elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
- dlself=yes
- else
- dlself=needless
- export_dynamic=yes
- fi
- prev=
- continue
- ;;
- *)
- if test "$prev" = dlfiles; then
- dlfiles="$dlfiles $arg"
- else
- dlprefiles="$dlprefiles $arg"
- fi
- prev=
- continue
- ;;
- esac
- ;;
- expsyms)
- export_symbols="$arg"
- test -f "$arg" \
- || func_fatal_error "symbol file \`$arg' does not exist"
- prev=
- continue
- ;;
- expsyms_regex)
- export_symbols_regex="$arg"
- prev=
- continue
- ;;
- framework)
- case $host in
- *-*-darwin*)
- case "$deplibs " in
- *" $qarg.ltframework "*) ;;
- *) deplibs="$deplibs $qarg.ltframework" # this is fixed later
- ;;
- esac
- ;;
- esac
- prev=
- continue
- ;;
- inst_prefix)
- inst_prefix_dir="$arg"
- prev=
- continue
- ;;
- objectlist)
- if test -f "$arg"; then
- save_arg=$arg
- moreargs=
- for fil in `cat "$save_arg"`
- do
-# moreargs="$moreargs $fil"
- arg=$fil
- # A libtool-controlled object.
-
- # Check to see that this really is a libtool object.
- if func_lalib_unsafe_p "$arg"; then
- pic_object=
- non_pic_object=
-
- # Read the .lo file
- func_source "$arg"
-
- if test -z "$pic_object" ||
- test -z "$non_pic_object" ||
- test "$pic_object" = none &&
- test "$non_pic_object" = none; then
- func_fatal_error "cannot find name of object for \`$arg'"
- fi
-
- # Extract subdirectory from the argument.
- func_dirname "$arg" "/" ""
- xdir="$func_dirname_result"
-
- if test "$pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- pic_object="$xdir$pic_object"
-
- if test "$prev" = dlfiles; then
- if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
- dlfiles="$dlfiles $pic_object"
- prev=
- continue
- else
- # If libtool objects are unsupported, then we need to preload.
- prev=dlprefiles
- fi
- fi
-
- # CHECK ME: I think I busted this. -Ossama
- if test "$prev" = dlprefiles; then
- # Preload the old-style object.
- dlprefiles="$dlprefiles $pic_object"
- prev=
- fi
-
- # A PIC object.
- func_append libobjs " $pic_object"
- arg="$pic_object"
- fi
-
- # Non-PIC object.
- if test "$non_pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- non_pic_object="$xdir$non_pic_object"
-
- # A standard non-PIC object
- func_append non_pic_objects " $non_pic_object"
- if test -z "$pic_object" || test "$pic_object" = none ; then
- arg="$non_pic_object"
- fi
- else
- # If the PIC object exists, use it instead.
- # $xdir was prepended to $pic_object above.
- non_pic_object="$pic_object"
- func_append non_pic_objects " $non_pic_object"
- fi
- else
- # Only an error if not doing a dry-run.
- if $opt_dry_run; then
- # Extract subdirectory from the argument.
- func_dirname "$arg" "/" ""
- xdir="$func_dirname_result"
-
- func_lo2o "$arg"
- pic_object=$xdir$objdir/$func_lo2o_result
- non_pic_object=$xdir$func_lo2o_result
- func_append libobjs " $pic_object"
- func_append non_pic_objects " $non_pic_object"
- else
- func_fatal_error "\`$arg' is not a valid libtool object"
- fi
- fi
- done
- else
- func_fatal_error "link input file \`$arg' does not exist"
- fi
- arg=$save_arg
- prev=
- continue
- ;;
- precious_regex)
- precious_files_regex="$arg"
- prev=
- continue
- ;;
- release)
- release="-$arg"
- prev=
- continue
- ;;
- rpath | xrpath)
- # We need an absolute path.
- case $arg in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- func_fatal_error "only absolute run-paths are allowed"
- ;;
- esac
- if test "$prev" = rpath; then
- case "$rpath " in
- *" $arg "*) ;;
- *) rpath="$rpath $arg" ;;
- esac
- else
- case "$xrpath " in
- *" $arg "*) ;;
- *) xrpath="$xrpath $arg" ;;
- esac
- fi
- prev=
- continue
- ;;
- shrext)
- shrext_cmds="$arg"
- prev=
- continue
- ;;
- weak)
- weak_libs="$weak_libs $arg"
- prev=
- continue
- ;;
- xcclinker)
- linker_flags="$linker_flags $qarg"
- compiler_flags="$compiler_flags $qarg"
- prev=
- func_append compile_command " $qarg"
- func_append finalize_command " $qarg"
- continue
- ;;
- xcompiler)
- compiler_flags="$compiler_flags $qarg"
- prev=
- func_append compile_command " $qarg"
- func_append finalize_command " $qarg"
- continue
- ;;
- xlinker)
- linker_flags="$linker_flags $qarg"
- compiler_flags="$compiler_flags $wl$qarg"
- prev=
- func_append compile_command " $wl$qarg"
- func_append finalize_command " $wl$qarg"
- continue
- ;;
- *)
- eval "$prev=\"\$arg\""
- prev=
- continue
- ;;
- esac
- fi # test -n "$prev"
-
- prevarg="$arg"
-
- case $arg in
- -all-static)
- if test -n "$link_static_flag"; then
- # See comment for -static flag below, for more details.
- func_append compile_command " $link_static_flag"
- func_append finalize_command " $link_static_flag"
- fi
- continue
- ;;
-
- -allow-undefined)
- # FIXME: remove this flag sometime in the future.
- func_fatal_error "\`-allow-undefined' must not be used because it is the default"
- ;;
-
- -avoid-version)
- avoid_version=yes
- continue
- ;;
-
- -dlopen)
- prev=dlfiles
- continue
- ;;
-
- -dlpreopen)
- prev=dlprefiles
- continue
- ;;
-
- -export-dynamic)
- export_dynamic=yes
- continue
- ;;
-
- -export-symbols | -export-symbols-regex)
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- func_fatal_error "more than one -exported-symbols argument is not allowed"
- fi
- if test "X$arg" = "X-export-symbols"; then
- prev=expsyms
- else
- prev=expsyms_regex
- fi
- continue
- ;;
-
- -framework)
- prev=framework
- continue
- ;;
-
- -inst-prefix-dir)
- prev=inst_prefix
- continue
- ;;
-
- # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
- # so, if we see these flags be careful not to treat them like -L
- -L[A-Z][A-Z]*:*)
- case $with_gcc/$host in
- no/*-*-irix* | /*-*-irix*)
- func_append compile_command " $arg"
- func_append finalize_command " $arg"
- ;;
- esac
- continue
- ;;
-
- -L*)
- func_stripname '-L' '' "$arg"
- dir=$func_stripname_result
- if test -z "$dir"; then
- if test "$#" -gt 0; then
- func_fatal_error "require no space between \`-L' and \`$1'"
- else
- func_fatal_error "need path for \`-L' option"
- fi
- fi
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- absdir=`cd "$dir" && pwd`
- test -z "$absdir" && \
- func_fatal_error "cannot determine absolute directory name of \`$dir'"
- dir="$absdir"
- ;;
- esac
- case "$deplibs " in
- *" -L$dir "*) ;;
- *)
- deplibs="$deplibs -L$dir"
- lib_search_path="$lib_search_path $dir"
- ;;
- esac
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
- testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'`
- case :$dllsearchpath: in
- *":$dir:"*) ;;
- ::) dllsearchpath=$dir;;
- *) dllsearchpath="$dllsearchpath:$dir";;
- esac
- case :$dllsearchpath: in
- *":$testbindir:"*) ;;
- ::) dllsearchpath=$testbindir;;
- *) dllsearchpath="$dllsearchpath:$testbindir";;
- esac
- ;;
- esac
- continue
- ;;
-
- -l*)
- if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*)
- # These systems don't actually have a C or math library (as such)
- continue
- ;;
- *-*-os2*)
- # These systems don't actually have a C library (as such)
- test "X$arg" = "X-lc" && continue
- ;;
- *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc due to us having libc/libc_r.
- test "X$arg" = "X-lc" && continue
- ;;
- *-*-rhapsody* | *-*-darwin1.[012])
- # Rhapsody C and math libraries are in the System framework
- deplibs="$deplibs System.ltframework"
- continue
- ;;
- *-*-sco3.2v5* | *-*-sco5v6*)
- # Causes problems with __ctype
- test "X$arg" = "X-lc" && continue
- ;;
- *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
- # Compiler inserts libc in the correct place for threads to work
- test "X$arg" = "X-lc" && continue
- ;;
- esac
- elif test "X$arg" = "X-lc_r"; then
- case $host in
- *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc_r directly, use -pthread flag.
- continue
- ;;
- esac
- fi
- deplibs="$deplibs $arg"
- continue
- ;;
-
- -module)
- module=yes
- continue
- ;;
-
- # Tru64 UNIX uses -model [arg] to determine the layout of C++
- # classes, name mangling, and exception handling.
- # Darwin uses the -arch flag to determine output architecture.
- -model|-arch|-isysroot)
- compiler_flags="$compiler_flags $arg"
- func_append compile_command " $arg"
- func_append finalize_command " $arg"
- prev=xcompiler
- continue
- ;;
-
- -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
- compiler_flags="$compiler_flags $arg"
- func_append compile_command " $arg"
- func_append finalize_command " $arg"
- case "$new_inherited_linker_flags " in
- *" $arg "*) ;;
- * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;;
- esac
- continue
- ;;
-
- -multi_module)
- single_module="${wl}-multi_module"
- continue
- ;;
-
- -no-fast-install)
- fast_install=no
- continue
- ;;
-
- -no-install)
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
- # The PATH hackery in wrapper scripts is required on Windows
- # and Darwin in order for the loader to find any dlls it needs.
- func_warning "\`-no-install' is ignored for $host"
- func_warning "assuming \`-no-fast-install' instead"
- fast_install=no
- ;;
- *) no_install=yes ;;
- esac
- continue
- ;;
-
- -no-undefined)
- allow_undefined=no
- continue
- ;;
-
- -objectlist)
- prev=objectlist
- continue
- ;;
-
- -o) prev=output ;;
-
- -precious-files-regex)
- prev=precious_regex
- continue
- ;;
-
- -release)
- prev=release
- continue
- ;;
-
- -rpath)
- prev=rpath
- continue
- ;;
-
- -R)
- prev=xrpath
- continue
- ;;
-
- -R*)
- func_stripname '-R' '' "$arg"
- dir=$func_stripname_result
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- func_fatal_error "only absolute run-paths are allowed"
- ;;
- esac
- case "$xrpath " in
- *" $dir "*) ;;
- *) xrpath="$xrpath $dir" ;;
- esac
- continue
- ;;
-
- -shared)
- # The effects of -shared are defined in a previous loop.
- continue
- ;;
-
- -shrext)
- prev=shrext
- continue
- ;;
-
- -static | -static-libtool-libs)
- # The effects of -static are defined in a previous loop.
- # We used to do the same as -all-static on platforms that
- # didn't have a PIC flag, but the assumption that the effects
- # would be equivalent was wrong. It would break on at least
- # Digital Unix and AIX.
- continue
- ;;
-
- -thread-safe)
- thread_safe=yes
- continue
- ;;
-
- -version-info)
- prev=vinfo
- continue
- ;;
-
- -version-number)
- prev=vinfo
- vinfo_number=yes
- continue
- ;;
-
- -weak)
- prev=weak
- continue
- ;;
-
- -Wc,*)
- func_stripname '-Wc,' '' "$arg"
- args=$func_stripname_result
- arg=
- save_ifs="$IFS"; IFS=','
- for flag in $args; do
- IFS="$save_ifs"
- func_quote_for_eval "$flag"
- arg="$arg $wl$func_quote_for_eval_result"
- compiler_flags="$compiler_flags $func_quote_for_eval_result"
- done
- IFS="$save_ifs"
- func_stripname ' ' '' "$arg"
- arg=$func_stripname_result
- ;;
-
- -Wl,*)
- func_stripname '-Wl,' '' "$arg"
- args=$func_stripname_result
- arg=
- save_ifs="$IFS"; IFS=','
- for flag in $args; do
- IFS="$save_ifs"
- func_quote_for_eval "$flag"
- arg="$arg $wl$func_quote_for_eval_result"
- compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
- linker_flags="$linker_flags $func_quote_for_eval_result"
- done
- IFS="$save_ifs"
- func_stripname ' ' '' "$arg"
- arg=$func_stripname_result
- ;;
-
- -Xcompiler)
- prev=xcompiler
- continue
- ;;
-
- -Xlinker)
- prev=xlinker
- continue
- ;;
-
- -XCClinker)
- prev=xcclinker
- continue
- ;;
-
- # -msg_* for osf cc
- -msg_*)
- func_quote_for_eval "$arg"
- arg="$func_quote_for_eval_result"
- ;;
-
- # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
- # -r[0-9][0-9]* specifies the processor on the SGI compiler
- # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
- # +DA*, +DD* enable 64-bit mode on the HP compiler
- # -q* pass through compiler args for the IBM compiler
- # -m*, -t[45]*, -txscale* pass through architecture-specific
- # compiler args for GCC
- # -F/path gives path to uninstalled frameworks, gcc on darwin
- # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
- # @file GCC response files
- -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
- -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
- func_quote_for_eval "$arg"
- arg="$func_quote_for_eval_result"
- func_append compile_command " $arg"
- func_append finalize_command " $arg"
- compiler_flags="$compiler_flags $arg"
- continue
- ;;
-
- # Some other compiler flag.
- -* | +*)
- func_quote_for_eval "$arg"
- arg="$func_quote_for_eval_result"
- ;;
-
- *.$objext)
- # A standard object.
- objs="$objs $arg"
- ;;
-
- *.lo)
- # A libtool-controlled object.
-
- # Check to see that this really is a libtool object.
- if func_lalib_unsafe_p "$arg"; then
- pic_object=
- non_pic_object=
-
- # Read the .lo file
- func_source "$arg"
-
- if test -z "$pic_object" ||
- test -z "$non_pic_object" ||
- test "$pic_object" = none &&
- test "$non_pic_object" = none; then
- func_fatal_error "cannot find name of object for \`$arg'"
- fi
-
- # Extract subdirectory from the argument.
- func_dirname "$arg" "/" ""
- xdir="$func_dirname_result"
-
- if test "$pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- pic_object="$xdir$pic_object"
-
- if test "$prev" = dlfiles; then
- if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
- dlfiles="$dlfiles $pic_object"
- prev=
- continue
- else
- # If libtool objects are unsupported, then we need to preload.
- prev=dlprefiles
- fi
- fi
-
- # CHECK ME: I think I busted this. -Ossama
- if test "$prev" = dlprefiles; then
- # Preload the old-style object.
- dlprefiles="$dlprefiles $pic_object"
- prev=
- fi
-
- # A PIC object.
- func_append libobjs " $pic_object"
- arg="$pic_object"
- fi
-
- # Non-PIC object.
- if test "$non_pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- non_pic_object="$xdir$non_pic_object"
-
- # A standard non-PIC object
- func_append non_pic_objects " $non_pic_object"
- if test -z "$pic_object" || test "$pic_object" = none ; then
- arg="$non_pic_object"
- fi
- else
- # If the PIC object exists, use it instead.
- # $xdir was prepended to $pic_object above.
- non_pic_object="$pic_object"
- func_append non_pic_objects " $non_pic_object"
- fi
- else
- # Only an error if not doing a dry-run.
- if $opt_dry_run; then
- # Extract subdirectory from the argument.
- func_dirname "$arg" "/" ""
- xdir="$func_dirname_result"
-
- func_lo2o "$arg"
- pic_object=$xdir$objdir/$func_lo2o_result
- non_pic_object=$xdir$func_lo2o_result
- func_append libobjs " $pic_object"
- func_append non_pic_objects " $non_pic_object"
- else
- func_fatal_error "\`$arg' is not a valid libtool object"
- fi
- fi
- ;;
-
- *.$libext)
- # An archive.
- deplibs="$deplibs $arg"
- old_deplibs="$old_deplibs $arg"
- continue
- ;;
-
- *.la)
- # A libtool-controlled library.
-
- if test "$prev" = dlfiles; then
- # This library was specified with -dlopen.
- dlfiles="$dlfiles $arg"
- prev=
- elif test "$prev" = dlprefiles; then
- # The library was specified with -dlpreopen.
- dlprefiles="$dlprefiles $arg"
- prev=
- else
- deplibs="$deplibs $arg"
- fi
- continue
- ;;
-
- # Some other compiler argument.
- *)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- func_quote_for_eval "$arg"
- arg="$func_quote_for_eval_result"
- ;;
- esac # arg
-
- # Now actually substitute the argument into the commands.
- if test -n "$arg"; then
- func_append compile_command " $arg"
- func_append finalize_command " $arg"
- fi
- done # argument parsing loop
-
- test -n "$prev" && \
- func_fatal_help "the \`$prevarg' option requires an argument"
-
- if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
- eval arg=\"$export_dynamic_flag_spec\"
- func_append compile_command " $arg"
- func_append finalize_command " $arg"
- fi
-
- oldlibs=
- # calculate the name of the file, without its directory
- func_basename "$output"
- outputname="$func_basename_result"
- libobjs_save="$libobjs"
-
- if test -n "$shlibpath_var"; then
- # get the directories listed in $shlibpath_var
- eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
- else
- shlib_search_path=
- fi
- eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
- eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
-
- func_dirname "$output" "/" ""
- output_objdir="$func_dirname_result$objdir"
- # Create the object directory.
- func_mkdir_p "$output_objdir"
-
- # Determine the type of output
- case $output in
- "")
- func_fatal_help "you must specify an output file"
- ;;
- *.$libext) linkmode=oldlib ;;
- *.lo | *.$objext) linkmode=obj ;;
- *.la) linkmode=lib ;;
- *) linkmode=prog ;; # Anything else should be a program.
- esac
-
- specialdeplibs=
-
- libs=
- # Find all interdependent deplibs by searching for libraries
- # that are linked more than once (e.g. -la -lb -la)
- for deplib in $deplibs; do
- if $opt_duplicate_deps ; then
- case "$libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- libs="$libs $deplib"
- done
-
- if test "$linkmode" = lib; then
- libs="$predeps $libs $compiler_lib_search_path $postdeps"
-
- # Compute libraries that are listed more than once in $predeps
- # $postdeps and mark them as special (i.e., whose duplicates are
- # not to be eliminated).
- pre_post_deps=
- if $opt_duplicate_compiler_generated_deps; then
- for pre_post_dep in $predeps $postdeps; do
- case "$pre_post_deps " in
- *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
- esac
- pre_post_deps="$pre_post_deps $pre_post_dep"
- done
- fi
- pre_post_deps=
- fi
-
- deplibs=
- newdependency_libs=
- newlib_search_path=
- need_relink=no # whether we're linking any uninstalled libtool libraries
- notinst_deplibs= # not-installed libtool libraries
- notinst_path= # paths that contain not-installed libtool libraries
-
- case $linkmode in
- lib)
- passes="conv dlpreopen link"
- for file in $dlfiles $dlprefiles; do
- case $file in
- *.la) ;;
- *)
- func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
- ;;
- esac
- done
- ;;
- prog)
- compile_deplibs=
- finalize_deplibs=
- alldeplibs=no
- newdlfiles=
- newdlprefiles=
- passes="conv scan dlopen dlpreopen link"
- ;;
- *) passes="conv"
- ;;
- esac
-
- for pass in $passes; do
- # The preopen pass in lib mode reverses $deplibs; put it back here
- # so that -L comes before libs that need it for instance...
- if test "$linkmode,$pass" = "lib,link"; then
- ## FIXME: Find the place where the list is rebuilt in the wrong
- ## order, and fix it there properly
- tmp_deplibs=
- for deplib in $deplibs; do
- tmp_deplibs="$deplib $tmp_deplibs"
- done
- deplibs="$tmp_deplibs"
- fi
-
- if test "$linkmode,$pass" = "lib,link" ||
- test "$linkmode,$pass" = "prog,scan"; then
- libs="$deplibs"
- deplibs=
- fi
- if test "$linkmode" = prog; then
- case $pass in
- dlopen) libs="$dlfiles" ;;
- dlpreopen) libs="$dlprefiles" ;;
- link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
- esac
- fi
- if test "$linkmode,$pass" = "lib,dlpreopen"; then
- # Collect and forward deplibs of preopened libtool libs
- for lib in $dlprefiles; do
- # Ignore non-libtool-libs
- dependency_libs=
- case $lib in
- *.la) func_source "$lib" ;;
- esac
-
- # Collect preopened libtool deplibs, except any this library
- # has declared as weak libs
- for deplib in $dependency_libs; do
- deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"`
- case " $weak_libs " in
- *" $deplib_base "*) ;;
- *) deplibs="$deplibs $deplib" ;;
- esac
- done
- done
- libs="$dlprefiles"
- fi
- if test "$pass" = dlopen; then
- # Collect dlpreopened libraries
- save_deplibs="$deplibs"
- deplibs=
- fi
-
- for deplib in $libs; do
- lib=
- found=no
- case $deplib in
- -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- compiler_flags="$compiler_flags $deplib"
- if test "$linkmode" = lib ; then
- case "$new_inherited_linker_flags " in
- *" $deplib "*) ;;
- * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
- esac
- fi
- fi
- continue
- ;;
- -l*)
- if test "$linkmode" != lib && test "$linkmode" != prog; then
- func_warning "\`-l' is ignored for archives/objects"
- continue
- fi
- func_stripname '-l' '' "$deplib"
- name=$func_stripname_result
- if test "$linkmode" = lib; then
- searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
- else
- searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
- fi
- for searchdir in $searchdirs; do
- for search_ext in .la $std_shrext .so .a; do
- # Search the libtool library
- lib="$searchdir/lib${name}${search_ext}"
- if test -f "$lib"; then
- if test "$search_ext" = ".la"; then
- found=yes
- else
- found=no
- fi
- break 2
- fi
- done
- done
- if test "$found" != yes; then
- # deplib doesn't seem to be a libtool library
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- deplibs="$deplib $deplibs"
- test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
- fi
- continue
- else # deplib is a libtool library
- # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
- # We need to do some special things here, and not later.
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $deplib "*)
- if func_lalib_p "$lib"; then
- library_names=
- old_library=
- func_source "$lib"
- for l in $old_library $library_names; do
- ll="$l"
- done
- if test "X$ll" = "X$old_library" ; then # only static version available
- found=no
- func_dirname "$lib" "" "."
- ladir="$func_dirname_result"
- lib=$ladir/$old_library
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- deplibs="$deplib $deplibs"
- test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
- fi
- continue
- fi
- fi
- ;;
- *) ;;
- esac
- fi
- fi
- ;; # -l
- *.ltframework)
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- deplibs="$deplib $deplibs"
- if test "$linkmode" = lib ; then
- case "$new_inherited_linker_flags " in
- *" $deplib "*) ;;
- * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
- esac
- fi
- fi
- continue
- ;;
- -L*)
- case $linkmode in
- lib)
- deplibs="$deplib $deplibs"
- test "$pass" = conv && continue
- newdependency_libs="$deplib $newdependency_libs"
- func_stripname '-L' '' "$deplib"
- newlib_search_path="$newlib_search_path $func_stripname_result"
- ;;
- prog)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- if test "$pass" = scan; then
- deplibs="$deplib $deplibs"
- else
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- fi
- func_stripname '-L' '' "$deplib"
- newlib_search_path="$newlib_search_path $func_stripname_result"
- ;;
- *)
- func_warning "\`-L' is ignored for archives/objects"
- ;;
- esac # linkmode
- continue
- ;; # -L
- -R*)
- if test "$pass" = link; then
- func_stripname '-R' '' "$deplib"
- dir=$func_stripname_result
- # Make sure the xrpath contains only unique directories.
- case "$xrpath " in
- *" $dir "*) ;;
- *) xrpath="$xrpath $dir" ;;
- esac
- fi
- deplibs="$deplib $deplibs"
- continue
- ;;
- *.la) lib="$deplib" ;;
- *.$libext)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- case $linkmode in
- lib)
- # Linking convenience modules into shared libraries is allowed,
- # but linking other static libraries is non-portable.
- case " $dlpreconveniencelibs " in
- *" $deplib "*) ;;
- *)
- valid_a_lib=no
- case $deplibs_check_method in
- match_pattern*)
- set dummy $deplibs_check_method; shift
- match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
- if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \
- | $EGREP "$match_pattern_regex" > /dev/null; then
- valid_a_lib=yes
- fi
- ;;
- pass_all)
- valid_a_lib=yes
- ;;
- esac
- if test "$valid_a_lib" != yes; then
- $ECHO
- $ECHO "*** Warning: Trying to link with static lib archive $deplib."
- $ECHO "*** I have the capability to make that library automatically link in when"
- $ECHO "*** you link to this library. But I can only do this if you have a"
- $ECHO "*** shared version of the library, which you do not appear to have"
- $ECHO "*** because the file extensions .$libext of this argument makes me believe"
- $ECHO "*** that it is just a static archive that I should not use here."
- else
- $ECHO
- $ECHO "*** Warning: Linking the shared library $output against the"
- $ECHO "*** static library $deplib is not portable!"
- deplibs="$deplib $deplibs"
- fi
- ;;
- esac
- continue
- ;;
- prog)
- if test "$pass" != link; then
- deplibs="$deplib $deplibs"
- else
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- fi
- continue
- ;;
- esac # linkmode
- ;; # *.$libext
- *.lo | *.$objext)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- elif test "$linkmode" = prog; then
- if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
- # If there is no dlopen support or we're linking statically,
- # we need to preload.
- newdlprefiles="$newdlprefiles $deplib"
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- newdlfiles="$newdlfiles $deplib"
- fi
- fi
- continue
- ;;
- %DEPLIBS%)
- alldeplibs=yes
- continue
- ;;
- esac # case $deplib
-
- if test "$found" = yes || test -f "$lib"; then :
- else
- func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
- fi
-
- # Check to see that this really is a libtool archive.
- func_lalib_unsafe_p "$lib" \
- || func_fatal_error "\`$lib' is not a valid libtool archive"
-
- func_dirname "$lib" "" "."
- ladir="$func_dirname_result"
-
- dlname=
- dlopen=
- dlpreopen=
- libdir=
- library_names=
- old_library=
- inherited_linker_flags=
- # If the library was installed with an old release of libtool,
- # it will not redefine variables installed, or shouldnotlink
- installed=yes
- shouldnotlink=no
- avoidtemprpath=
-
-
- # Read the .la file
- func_source "$lib"
-
- # Convert "-framework foo" to "foo.ltframework"
- if test -n "$inherited_linker_flags"; then
- tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'`
- for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
- case " $new_inherited_linker_flags " in
- *" $tmp_inherited_linker_flag "*) ;;
- *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
- esac
- done
- fi
- dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
- if test "$linkmode,$pass" = "lib,link" ||
- test "$linkmode,$pass" = "prog,scan" ||
- { test "$linkmode" != prog && test "$linkmode" != lib; }; then
- test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
- test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
- fi
-
- if test "$pass" = conv; then
- # Only check for convenience libraries
- deplibs="$lib $deplibs"
- if test -z "$libdir"; then
- if test -z "$old_library"; then
- func_fatal_error "cannot find name of link library for \`$lib'"
- fi
- # It is a libtool convenience library, so add in its objects.
- convenience="$convenience $ladir/$objdir/$old_library"
- old_convenience="$old_convenience $ladir/$objdir/$old_library"
- elif test "$linkmode" != prog && test "$linkmode" != lib; then
- func_fatal_error "\`$lib' is not a convenience library"
- fi
- tmp_libs=
- for deplib in $dependency_libs; do
- deplibs="$deplib $deplibs"
- if $opt_duplicate_deps ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done
- continue
- fi # $pass = conv
-
-
- # Get the name of the library we link against.
- linklib=
- for l in $old_library $library_names; do
- linklib="$l"
- done
- if test -z "$linklib"; then
- func_fatal_error "cannot find name of link library for \`$lib'"
- fi
-
- # This library was specified with -dlopen.
- if test "$pass" = dlopen; then
- if test -z "$libdir"; then
- func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
- fi
- if test -z "$dlname" ||
- test "$dlopen_support" != yes ||
- test "$build_libtool_libs" = no; then
- # If there is no dlname, no dlopen support or we're linking
- # statically, we need to preload. We also need to preload any
- # dependent libraries so libltdl's deplib preloader doesn't
- # bomb out in the load deplibs phase.
- dlprefiles="$dlprefiles $lib $dependency_libs"
- else
- newdlfiles="$newdlfiles $lib"
- fi
- continue
- fi # $pass = dlopen
-
- # We need an absolute path.
- case $ladir in
- [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
- *)
- abs_ladir=`cd "$ladir" && pwd`
- if test -z "$abs_ladir"; then
- func_warning "cannot determine absolute directory name of \`$ladir'"
- func_warning "passing it literally to the linker, although it might fail"
- abs_ladir="$ladir"
- fi
- ;;
- esac
- func_basename "$lib"
- laname="$func_basename_result"
-
- # Find the relevant object directory and library name.
- if test "X$installed" = Xyes; then
- if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
- func_warning "library \`$lib' was moved."
- dir="$ladir"
- absdir="$abs_ladir"
- libdir="$abs_ladir"
- else
- dir="$libdir"
- absdir="$libdir"
- fi
- test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
- else
- if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
- dir="$ladir"
- absdir="$abs_ladir"
- # Remove this search path later
- notinst_path="$notinst_path $abs_ladir"
- else
- dir="$ladir/$objdir"
- absdir="$abs_ladir/$objdir"
- # Remove this search path later
- notinst_path="$notinst_path $abs_ladir"
- fi
- fi # $installed = yes
- func_stripname 'lib' '.la' "$laname"
- name=$func_stripname_result
-
- # This library was specified with -dlpreopen.
- if test "$pass" = dlpreopen; then
- if test -z "$libdir" && test "$linkmode" = prog; then
- func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
- fi
- # Prefer using a static library (so that no silly _DYNAMIC symbols
- # are required to link).
- if test -n "$old_library"; then
- newdlprefiles="$newdlprefiles $dir/$old_library"
- # Keep a list of preopened convenience libraries to check
- # that they are being used correctly in the link pass.
- test -z "$libdir" && \
- dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
- # Otherwise, use the dlname, so that lt_dlopen finds it.
- elif test -n "$dlname"; then
- newdlprefiles="$newdlprefiles $dir/$dlname"
- else
- newdlprefiles="$newdlprefiles $dir/$linklib"
- fi
- fi # $pass = dlpreopen
-
- if test -z "$libdir"; then
- # Link the convenience library
- if test "$linkmode" = lib; then
- deplibs="$dir/$old_library $deplibs"
- elif test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$dir/$old_library $compile_deplibs"
- finalize_deplibs="$dir/$old_library $finalize_deplibs"
- else
- deplibs="$lib $deplibs" # used for prog,scan pass
- fi
- continue
- fi
-
-
- if test "$linkmode" = prog && test "$pass" != link; then
- newlib_search_path="$newlib_search_path $ladir"
- deplibs="$lib $deplibs"
-
- linkalldeplibs=no
- if test "$link_all_deplibs" != no || test -z "$library_names" ||
- test "$build_libtool_libs" = no; then
- linkalldeplibs=yes
- fi
-
- tmp_libs=
- for deplib in $dependency_libs; do
- case $deplib in
- -L*) func_stripname '-L' '' "$deplib"
- newlib_search_path="$newlib_search_path $func_stripname_result"
- ;;
- esac
- # Need to link against all dependency_libs?
- if test "$linkalldeplibs" = yes; then
- deplibs="$deplib $deplibs"
- else
- # Need to hardcode shared library paths
- # or/and link against static libraries
- newdependency_libs="$deplib $newdependency_libs"
- fi
- if $opt_duplicate_deps ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done # for deplib
- continue
- fi # $linkmode = prog...
-
- if test "$linkmode,$pass" = "prog,link"; then
- if test -n "$library_names" &&
- { { test "$prefer_static_libs" = no ||
- test "$prefer_static_libs,$installed" = "built,yes"; } ||
- test -z "$old_library"; }; then
- # We need to hardcode the library path
- if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
- # Make sure the rpath contains only unique directories.
- case "$temp_rpath:" in
- *"$absdir:"*) ;;
- *) temp_rpath="$temp_rpath$absdir:" ;;
- esac
- fi
-
- # Hardcode the library path.
- # Skip directories that are in the system default run-time
- # search path.
- case " $sys_lib_dlsearch_path " in
- *" $absdir "*) ;;
- *)
- case "$compile_rpath " in
- *" $absdir "*) ;;
- *) compile_rpath="$compile_rpath $absdir"
- esac
- ;;
- esac
- case " $sys_lib_dlsearch_path " in
- *" $libdir "*) ;;
- *)
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir"
- esac
- ;;
- esac
- fi # $linkmode,$pass = prog,link...
-
- if test "$alldeplibs" = yes &&
- { test "$deplibs_check_method" = pass_all ||
- { test "$build_libtool_libs" = yes &&
- test -n "$library_names"; }; }; then
- # We only need to search for static libraries
- continue
- fi
- fi
-
- link_static=no # Whether the deplib will be linked statically
- use_static_libs=$prefer_static_libs
- if test "$use_static_libs" = built && test "$installed" = yes; then
- use_static_libs=no
- fi
- if test -n "$library_names" &&
- { test "$use_static_libs" = no || test -z "$old_library"; }; then
- case $host in
- *cygwin* | *mingw* | *cegcc*)
- # No point in relinking DLLs because paths are not encoded
- notinst_deplibs="$notinst_deplibs $lib"
- need_relink=no
- ;;
- *)
- if test "$installed" = no; then
- notinst_deplibs="$notinst_deplibs $lib"
- need_relink=yes
- fi
- ;;
- esac
- # This is a shared library
-
- # Warn about portability, can't link against -module's on some
- # systems (darwin). Don't bleat about dlopened modules though!
- dlopenmodule=""
- for dlpremoduletest in $dlprefiles; do
- if test "X$dlpremoduletest" = "X$lib"; then
- dlopenmodule="$dlpremoduletest"
- break
- fi
- done
- if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
- $ECHO
- if test "$linkmode" = prog; then
- $ECHO "*** Warning: Linking the executable $output against the loadable module"
- else
- $ECHO "*** Warning: Linking the shared library $output against the loadable module"
- fi
- $ECHO "*** $linklib is not portable!"
- fi
- if test "$linkmode" = lib &&
- test "$hardcode_into_libs" = yes; then
- # Hardcode the library path.
- # Skip directories that are in the system default run-time
- # search path.
- case " $sys_lib_dlsearch_path " in
- *" $absdir "*) ;;
- *)
- case "$compile_rpath " in
- *" $absdir "*) ;;
- *) compile_rpath="$compile_rpath $absdir"
- esac
- ;;
- esac
- case " $sys_lib_dlsearch_path " in
- *" $libdir "*) ;;
- *)
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir"
- esac
- ;;
- esac
- fi
-
- if test -n "$old_archive_from_expsyms_cmds"; then
- # figure out the soname
- set dummy $library_names
- shift
- realname="$1"
- shift
- libname=`eval "\\$ECHO \"$libname_spec\""`
- # use dlname if we got it. it's perfectly good, no?
- if test -n "$dlname"; then
- soname="$dlname"
- elif test -n "$soname_spec"; then
- # bleh windows
- case $host in
- *cygwin* | mingw* | *cegcc*)
- func_arith $current - $age
- major=$func_arith_result
- versuffix="-$major"
- ;;
- esac
- eval soname=\"$soname_spec\"
- else
- soname="$realname"
- fi
-
- # Make a new name for the extract_expsyms_cmds to use
- soroot="$soname"
- func_basename "$soroot"
- soname="$func_basename_result"
- func_stripname 'lib' '.dll' "$soname"
- newlib=libimp-$func_stripname_result.a
-
- # If the library has no export list, then create one now
- if test -f "$output_objdir/$soname-def"; then :
- else
- func_verbose "extracting exported symbol list from \`$soname'"
- func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
- fi
-
- # Create $newlib
- if test -f "$output_objdir/$newlib"; then :; else
- func_verbose "generating import library for \`$soname'"
- func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
- fi
- # make sure the library variables are pointing to the new library
- dir=$output_objdir
- linklib=$newlib
- fi # test -n "$old_archive_from_expsyms_cmds"
-
- if test "$linkmode" = prog || test "$mode" != relink; then
- add_shlibpath=
- add_dir=
- add=
- lib_linked=yes
- case $hardcode_action in
- immediate | unsupported)
- if test "$hardcode_direct" = no; then
- add="$dir/$linklib"
- case $host in
- *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
- *-*-sysv4*uw2*) add_dir="-L$dir" ;;
- *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
- *-*-unixware7*) add_dir="-L$dir" ;;
- *-*-darwin* )
- # if the lib is a (non-dlopened) module then we can not
- # link against it, someone is ignoring the earlier warnings
- if /usr/bin/file -L $add 2> /dev/null |
- $GREP ": [^:]* bundle" >/dev/null ; then
- if test "X$dlopenmodule" != "X$lib"; then
- $ECHO "*** Warning: lib $linklib is a module, not a shared library"
- if test -z "$old_library" ; then
- $ECHO
- $ECHO "*** And there doesn't seem to be a static archive available"
- $ECHO "*** The link will probably fail, sorry"
- else
- add="$dir/$old_library"
- fi
- elif test -n "$old_library"; then
- add="$dir/$old_library"
- fi
- fi
- esac
- elif test "$hardcode_minus_L" = no; then
- case $host in
- *-*-sunos*) add_shlibpath="$dir" ;;
- esac
- add_dir="-L$dir"
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = no; then
- add_shlibpath="$dir"
- add="-l$name"
- else
- lib_linked=no
- fi
- ;;
- relink)
- if test "$hardcode_direct" = yes &&
- test "$hardcode_direct_absolute" = no; then
- add="$dir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- add_dir="-L$dir"
- # Try looking first in the location we're being installed to.
- if test -n "$inst_prefix_dir"; then
- case $libdir in
- [\\/]*)
- add_dir="$add_dir -L$inst_prefix_dir$libdir"
- ;;
- esac
- fi
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- add_shlibpath="$dir"
- add="-l$name"
- else
- lib_linked=no
- fi
- ;;
- *) lib_linked=no ;;
- esac
-
- if test "$lib_linked" != yes; then
- func_fatal_configuration "unsupported hardcode properties"
- fi
-
- if test -n "$add_shlibpath"; then
- case :$compile_shlibpath: in
- *":$add_shlibpath:"*) ;;
- *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
- esac
- fi
- if test "$linkmode" = prog; then
- test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
- test -n "$add" && compile_deplibs="$add $compile_deplibs"
- else
- test -n "$add_dir" && deplibs="$add_dir $deplibs"
- test -n "$add" && deplibs="$add $deplibs"
- if test "$hardcode_direct" != yes &&
- test "$hardcode_minus_L" != yes &&
- test "$hardcode_shlibpath_var" = yes; then
- case :$finalize_shlibpath: in
- *":$libdir:"*) ;;
- *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
- esac
- fi
- fi
- fi
-
- if test "$linkmode" = prog || test "$mode" = relink; then
- add_shlibpath=
- add_dir=
- add=
- # Finalize command for both is simple: just hardcode it.
- if test "$hardcode_direct" = yes &&
- test "$hardcode_direct_absolute" = no; then
- add="$libdir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- add_dir="-L$libdir"
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- case :$finalize_shlibpath: in
- *":$libdir:"*) ;;
- *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
- esac
- add="-l$name"
- elif test "$hardcode_automatic" = yes; then
- if test -n "$inst_prefix_dir" &&
- test -f "$inst_prefix_dir$libdir/$linklib" ; then
- add="$inst_prefix_dir$libdir/$linklib"
- else
- add="$libdir/$linklib"
- fi
- else
- # We cannot seem to hardcode it, guess we'll fake it.
- add_dir="-L$libdir"
- # Try looking first in the location we're being installed to.
- if test -n "$inst_prefix_dir"; then
- case $libdir in
- [\\/]*)
- add_dir="$add_dir -L$inst_prefix_dir$libdir"
- ;;
- esac
- fi
- add="-l$name"
- fi
-
- if test "$linkmode" = prog; then
- test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
- test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
- else
- test -n "$add_dir" && deplibs="$add_dir $deplibs"
- test -n "$add" && deplibs="$add $deplibs"
- fi
- fi
- elif test "$linkmode" = prog; then
- # Here we assume that one of hardcode_direct or hardcode_minus_L
- # is not unsupported. This is valid on all known static and
- # shared platforms.
- if test "$hardcode_direct" != unsupported; then
- test -n "$old_library" && linklib="$old_library"
- compile_deplibs="$dir/$linklib $compile_deplibs"
- finalize_deplibs="$dir/$linklib $finalize_deplibs"
- else
- compile_deplibs="-l$name -L$dir $compile_deplibs"
- finalize_deplibs="-l$name -L$dir $finalize_deplibs"
- fi
- elif test "$build_libtool_libs" = yes; then
- # Not a shared library
- if test "$deplibs_check_method" != pass_all; then
- # We're trying link a shared library against a static one
- # but the system doesn't support it.
-
- # Just print a warning and add the library to dependency_libs so
- # that the program can be linked against the static library.
- $ECHO
- $ECHO "*** Warning: This system can not link to static lib archive $lib."
- $ECHO "*** I have the capability to make that library automatically link in when"
- $ECHO "*** you link to this library. But I can only do this if you have a"
- $ECHO "*** shared version of the library, which you do not appear to have."
- if test "$module" = yes; then
- $ECHO "*** But as you try to build a module library, libtool will still create "
- $ECHO "*** a static module, that should work as long as the dlopening application"
- $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime."
- if test -z "$global_symbol_pipe"; then
- $ECHO
- $ECHO "*** However, this would only work if libtool was able to extract symbol"
- $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
- $ECHO "*** not find such a program. So, this module is probably useless."
- $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- fi
- else
- deplibs="$dir/$old_library $deplibs"
- link_static=yes
- fi
- fi # link shared/static library?
-
- if test "$linkmode" = lib; then
- if test -n "$dependency_libs" &&
- { test "$hardcode_into_libs" != yes ||
- test "$build_old_libs" = yes ||
- test "$link_static" = yes; }; then
- # Extract -R from dependency_libs
- temp_deplibs=
- for libdir in $dependency_libs; do
- case $libdir in
- -R*) func_stripname '-R' '' "$libdir"
- temp_xrpath=$func_stripname_result
- case " $xrpath " in
- *" $temp_xrpath "*) ;;
- *) xrpath="$xrpath $temp_xrpath";;
- esac;;
- *) temp_deplibs="$temp_deplibs $libdir";;
- esac
- done
- dependency_libs="$temp_deplibs"
- fi
-
- newlib_search_path="$newlib_search_path $absdir"
- # Link against this library
- test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
- # ... and its dependency_libs
- tmp_libs=
- for deplib in $dependency_libs; do
- newdependency_libs="$deplib $newdependency_libs"
- if $opt_duplicate_deps ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done
-
- if test "$link_all_deplibs" != no; then
- # Add the search paths of all dependency libraries
- for deplib in $dependency_libs; do
- case $deplib in
- -L*) path="$deplib" ;;
- *.la)
- func_dirname "$deplib" "" "."
- dir="$func_dirname_result"
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- func_warning "cannot determine absolute directory name of \`$dir'"
- absdir="$dir"
- fi
- ;;
- esac
- if $GREP "^installed=no" $deplib > /dev/null; then
- case $host in
- *-*-darwin*)
- depdepl=
- eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
- if test -n "$deplibrary_names" ; then
- for tmp in $deplibrary_names ; do
- depdepl=$tmp
- done
- if test -f "$absdir/$objdir/$depdepl" ; then
- depdepl="$absdir/$objdir/$depdepl"
- darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
- if test -z "$darwin_install_name"; then
- darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
- fi
- compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
- linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}"
- path=
- fi
- fi
- ;;
- *)
- path="-L$absdir/$objdir"
- ;;
- esac
- else
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- test -z "$libdir" && \
- func_fatal_error "\`$deplib' is not a valid libtool archive"
- test "$absdir" != "$libdir" && \
- func_warning "\`$deplib' seems to be moved"
-
- path="-L$absdir"
- fi
- ;;
- esac
- case " $deplibs " in
- *" $path "*) ;;
- *) deplibs="$path $deplibs" ;;
- esac
- done
- fi # link_all_deplibs != no
- fi # linkmode = lib
- done # for deplib in $libs
- if test "$pass" = link; then
- if test "$linkmode" = "prog"; then
- compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
- finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
- else
- compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
- fi
- fi
- dependency_libs="$newdependency_libs"
- if test "$pass" = dlpreopen; then
- # Link the dlpreopened libraries before other libraries
- for deplib in $save_deplibs; do
- deplibs="$deplib $deplibs"
- done
- fi
- if test "$pass" != dlopen; then
- if test "$pass" != conv; then
- # Make sure lib_search_path contains only unique directories.
- lib_search_path=
- for dir in $newlib_search_path; do
- case "$lib_search_path " in
- *" $dir "*) ;;
- *) lib_search_path="$lib_search_path $dir" ;;
- esac
- done
- newlib_search_path=
- fi
-
- if test "$linkmode,$pass" != "prog,link"; then
- vars="deplibs"
- else
- vars="compile_deplibs finalize_deplibs"
- fi
- for var in $vars dependency_libs; do
- # Add libraries to $var in reverse order
- eval tmp_libs=\"\$$var\"
- new_libs=
- for deplib in $tmp_libs; do
- # FIXME: Pedantically, this is the right thing to do, so
- # that some nasty dependency loop isn't accidentally
- # broken:
- #new_libs="$deplib $new_libs"
- # Pragmatically, this seems to cause very few problems in
- # practice:
- case $deplib in
- -L*) new_libs="$deplib $new_libs" ;;
- -R*) ;;
- *)
- # And here is the reason: when a library appears more
- # than once as an explicit dependence of a library, or
- # is implicitly linked in more than once by the
- # compiler, it is considered special, and multiple
- # occurrences thereof are not removed. Compare this
- # with having the same library being listed as a
- # dependency of multiple other libraries: in this case,
- # we know (pedantically, we assume) the library does not
- # need to be listed more than once, so we keep only the
- # last copy. This is not always right, but it is rare
- # enough that we require users that really mean to play
- # such unportable linking tricks to link the library
- # using -Wl,-lname, so that libtool does not consider it
- # for duplicate removal.
- case " $specialdeplibs " in
- *" $deplib "*) new_libs="$deplib $new_libs" ;;
- *)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$deplib $new_libs" ;;
- esac
- ;;
- esac
- ;;
- esac
- done
- tmp_libs=
- for deplib in $new_libs; do
- case $deplib in
- -L*)
- case " $tmp_libs " in
- *" $deplib "*) ;;
- *) tmp_libs="$tmp_libs $deplib" ;;
- esac
- ;;
- *) tmp_libs="$tmp_libs $deplib" ;;
- esac
- done
- eval $var=\"$tmp_libs\"
- done # for var
- fi
- # Last step: remove runtime libs from dependency_libs
- # (they stay in deplibs)
- tmp_libs=
- for i in $dependency_libs ; do
- case " $predeps $postdeps $compiler_lib_search_path " in
- *" $i "*)
- i=""
- ;;
- esac
- if test -n "$i" ; then
- tmp_libs="$tmp_libs $i"
- fi
- done
- dependency_libs=$tmp_libs
- done # for pass
- if test "$linkmode" = prog; then
- dlfiles="$newdlfiles"
- fi
- if test "$linkmode" = prog || test "$linkmode" = lib; then
- dlprefiles="$newdlprefiles"
- fi
-
- case $linkmode in
- oldlib)
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- func_warning "\`-dlopen' is ignored for archives"
- fi
-
- case " $deplibs" in
- *\ -l* | *\ -L*)
- func_warning "\`-l' and \`-L' are ignored for archives" ;;
- esac
-
- test -n "$rpath" && \
- func_warning "\`-rpath' is ignored for archives"
-
- test -n "$xrpath" && \
- func_warning "\`-R' is ignored for archives"
-
- test -n "$vinfo" && \
- func_warning "\`-version-info/-version-number' is ignored for archives"
-
- test -n "$release" && \
- func_warning "\`-release' is ignored for archives"
-
- test -n "$export_symbols$export_symbols_regex" && \
- func_warning "\`-export-symbols' is ignored for archives"
-
- # Now set the variables for building old libraries.
- build_libtool_libs=no
- oldlibs="$output"
- objs="$objs$old_deplibs"
- ;;
-
- lib)
- # Make sure we only generate libraries of the form `libNAME.la'.
- case $outputname in
- lib*)
- func_stripname 'lib' '.la' "$outputname"
- name=$func_stripname_result
- eval shared_ext=\"$shrext_cmds\"
- eval libname=\"$libname_spec\"
- ;;
- *)
- test "$module" = no && \
- func_fatal_help "libtool library \`$output' must begin with \`lib'"
-
- if test "$need_lib_prefix" != no; then
- # Add the "lib" prefix for modules if required
- func_stripname '' '.la' "$outputname"
- name=$func_stripname_result
- eval shared_ext=\"$shrext_cmds\"
- eval libname=\"$libname_spec\"
- else
- func_stripname '' '.la' "$outputname"
- libname=$func_stripname_result
- fi
- ;;
- esac
-
- if test -n "$objs"; then
- if test "$deplibs_check_method" != pass_all; then
- func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
- else
- $ECHO
- $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
- $ECHO "*** objects $objs is not portable!"
- libobjs="$libobjs $objs"
- fi
- fi
-
- test "$dlself" != no && \
- func_warning "\`-dlopen self' is ignored for libtool libraries"
-
- set dummy $rpath
- shift
- test "$#" -gt 1 && \
- func_warning "ignoring multiple \`-rpath's for a libtool library"
-
- install_libdir="$1"
-
- oldlibs=
- if test -z "$rpath"; then
- if test "$build_libtool_libs" = yes; then
- # Building a libtool convenience library.
- # Some compilers have problems with a `.al' extension so
- # convenience libraries should have the same extension an
- # archive normally would.
- oldlibs="$output_objdir/$libname.$libext $oldlibs"
- build_libtool_libs=convenience
- build_old_libs=yes
- fi
-
- test -n "$vinfo" && \
- func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
-
- test -n "$release" && \
- func_warning "\`-release' is ignored for convenience libraries"
- else
-
- # Parse the version information argument.
- save_ifs="$IFS"; IFS=':'
- set dummy $vinfo 0 0 0
- shift
- IFS="$save_ifs"
-
- test -n "$7" && \
- func_fatal_help "too many parameters to \`-version-info'"
-
- # convert absolute version numbers to libtool ages
- # this retains compatibility with .la files and attempts
- # to make the code below a bit more comprehensible
-
- case $vinfo_number in
- yes)
- number_major="$1"
- number_minor="$2"
- number_revision="$3"
- #
- # There are really only two kinds -- those that
- # use the current revision as the major version
- # and those that subtract age and use age as
- # a minor version. But, then there is irix
- # which has an extra 1 added just for fun
- #
- case $version_type in
- darwin|linux|osf|windows|none)
- func_arith $number_major + $number_minor
- current=$func_arith_result
- age="$number_minor"
- revision="$number_revision"
- ;;
- freebsd-aout|freebsd-elf|sunos)
- current="$number_major"
- revision="$number_minor"
- age="0"
- ;;
- irix|nonstopux)
- func_arith $number_major + $number_minor
- current=$func_arith_result
- age="$number_minor"
- revision="$number_minor"
- lt_irix_increment=no
- ;;
- esac
- ;;
- no)
- current="$1"
- revision="$2"
- age="$3"
- ;;
- esac
-
- # Check that each of the things are valid numbers.
- case $current in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- func_error "CURRENT \`$current' must be a nonnegative integer"
- func_fatal_error "\`$vinfo' is not valid version information"
- ;;
- esac
-
- case $revision in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- func_error "REVISION \`$revision' must be a nonnegative integer"
- func_fatal_error "\`$vinfo' is not valid version information"
- ;;
- esac
-
- case $age in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- func_error "AGE \`$age' must be a nonnegative integer"
- func_fatal_error "\`$vinfo' is not valid version information"
- ;;
- esac
-
- if test "$age" -gt "$current"; then
- func_error "AGE \`$age' is greater than the current interface number \`$current'"
- func_fatal_error "\`$vinfo' is not valid version information"
- fi
-
- # Calculate the version variables.
- major=
- versuffix=
- verstring=
- case $version_type in
- none) ;;
-
- darwin)
- # Like Linux, but with the current version available in
- # verstring for coding it into the library header
- func_arith $current - $age
- major=.$func_arith_result
- versuffix="$major.$age.$revision"
- # Darwin ld doesn't like 0 for these options...
- func_arith $current + 1
- minor_current=$func_arith_result
- xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
- verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
- ;;
-
- freebsd-aout)
- major=".$current"
- versuffix=".$current.$revision";
- ;;
-
- freebsd-elf)
- major=".$current"
- versuffix=".$current"
- ;;
-
- irix | nonstopux)
- if test "X$lt_irix_increment" = "Xno"; then
- func_arith $current - $age
- else
- func_arith $current - $age + 1
- fi
- major=$func_arith_result
-
- case $version_type in
- nonstopux) verstring_prefix=nonstopux ;;
- *) verstring_prefix=sgi ;;
- esac
- verstring="$verstring_prefix$major.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$revision
- while test "$loop" -ne 0; do
- func_arith $revision - $loop
- iface=$func_arith_result
- func_arith $loop - 1
- loop=$func_arith_result
- verstring="$verstring_prefix$major.$iface:$verstring"
- done
-
- # Before this point, $major must not contain `.'.
- major=.$major
- versuffix="$major.$revision"
- ;;
-
- linux)
- func_arith $current - $age
- major=.$func_arith_result
- versuffix="$major.$age.$revision"
- ;;
-
- osf)
- func_arith $current - $age
- major=.$func_arith_result
- versuffix=".$current.$age.$revision"
- verstring="$current.$age.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$age
- while test "$loop" -ne 0; do
- func_arith $current - $loop
- iface=$func_arith_result
- func_arith $loop - 1
- loop=$func_arith_result
- verstring="$verstring:${iface}.0"
- done
-
- # Make executables depend on our current version.
- verstring="$verstring:${current}.0"
- ;;
-
- qnx)
- major=".$current"
- versuffix=".$current"
- ;;
-
- sunos)
- major=".$current"
- versuffix=".$current.$revision"
- ;;
-
- windows)
- # Use '-' rather than '.', since we only want one
- # extension on DOS 8.3 filesystems.
- func_arith $current - $age
- major=$func_arith_result
- versuffix="-$major"
- ;;
-
- *)
- func_fatal_configuration "unknown library version type \`$version_type'"
- ;;
- esac
-
- # Clear the version info if we defaulted, and they specified a release.
- if test -z "$vinfo" && test -n "$release"; then
- major=
- case $version_type in
- darwin)
- # we can't check for "0.0" in archive_cmds due to quoting
- # problems, so we reset it completely
- verstring=
- ;;
- *)
- verstring="0.0"
- ;;
- esac
- if test "$need_version" = no; then
- versuffix=
- else
- versuffix=".0.0"
- fi
- fi
-
- # Remove version info from name if versioning should be avoided
- if test "$avoid_version" = yes && test "$need_version" = no; then
- major=
- versuffix=
- verstring=""
- fi
-
- # Check to see if the archive will have undefined symbols.
- if test "$allow_undefined" = yes; then
- if test "$allow_undefined_flag" = unsupported; then
- func_warning "undefined symbols not allowed in $host shared libraries"
- build_libtool_libs=no
- build_old_libs=yes
- fi
- else
- # Don't allow undefined symbols.
- allow_undefined_flag="$no_undefined_flag"
- fi
-
- fi
-
- func_generate_dlsyms "$libname" "$libname" "yes"
- libobjs="$libobjs $symfileobj"
- test "X$libobjs" = "X " && libobjs=
-
- if test "$mode" != relink; then
- # Remove our outputs, but don't remove object files since they
- # may have been created when compiling PIC objects.
- removelist=
- tempremovelist=`$ECHO "$output_objdir/*"`
- for p in $tempremovelist; do
- case $p in
- *.$objext | *.gcno)
- ;;
- $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
- if test "X$precious_files_regex" != "X"; then
- if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
- then
- continue
- fi
- fi
- removelist="$removelist $p"
- ;;
- *) ;;
- esac
- done
- test -n "$removelist" && \
- func_show_eval "${RM}r \$removelist"
- fi
-
- # Now set the variables for building old libraries.
- if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
- oldlibs="$oldlibs $output_objdir/$libname.$libext"
-
- # Transform .lo files to .o files.
- oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
- fi
-
- # Eliminate all temporary directories.
- #for path in $notinst_path; do
- # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"`
- # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"`
- # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"`
- #done
-
- if test -n "$xrpath"; then
- # If the user specified any rpath flags, then add them.
- temp_xrpath=
- for libdir in $xrpath; do
- temp_xrpath="$temp_xrpath -R$libdir"
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
- dependency_libs="$temp_xrpath $dependency_libs"
- fi
- fi
-
- # Make sure dlfiles contains only unique files that won't be dlpreopened
- old_dlfiles="$dlfiles"
- dlfiles=
- for lib in $old_dlfiles; do
- case " $dlprefiles $dlfiles " in
- *" $lib "*) ;;
- *) dlfiles="$dlfiles $lib" ;;
- esac
- done
-
- # Make sure dlprefiles contains only unique files
- old_dlprefiles="$dlprefiles"
- dlprefiles=
- for lib in $old_dlprefiles; do
- case "$dlprefiles " in
- *" $lib "*) ;;
- *) dlprefiles="$dlprefiles $lib" ;;
- esac
- done
-
- if test "$build_libtool_libs" = yes; then
- if test -n "$rpath"; then
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*)
- # these systems don't actually have a c library (as such)!
- ;;
- *-*-rhapsody* | *-*-darwin1.[012])
- # Rhapsody C library is in the System framework
- deplibs="$deplibs System.ltframework"
- ;;
- *-*-netbsd*)
- # Don't link with libc until the a.out ld.so is fixed.
- ;;
- *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc due to us having libc/libc_r.
- ;;
- *-*-sco3.2v5* | *-*-sco5v6*)
- # Causes problems with __ctype
- ;;
- *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
- # Compiler inserts libc in the correct place for threads to work
- ;;
- *)
- # Add libc to deplibs on all other systems if necessary.
- if test "$build_libtool_need_lc" = "yes"; then
- deplibs="$deplibs -lc"
- fi
- ;;
- esac
- fi
-
- # Transform deplibs into only deplibs that can be linked in shared.
- name_save=$name
- libname_save=$libname
- release_save=$release
- versuffix_save=$versuffix
- major_save=$major
- # I'm not sure if I'm treating the release correctly. I think
- # release should show up in the -l (ie -lgmp5) so we don't want to
- # add it in twice. Is that correct?
- release=""
- versuffix=""
- major=""
- newdeplibs=
- droppeddeps=no
- case $deplibs_check_method in
- pass_all)
- # Don't check for shared/static. Everything works.
- # This might be a little naive. We might want to check
- # whether the library exists or not. But this is on
- # osf3 & osf4 and I'm not really sure... Just
- # implementing what was already the behavior.
- newdeplibs=$deplibs
- ;;
- test_compile)
- # This code stresses the "libraries are programs" paradigm to its
- # limits. Maybe even breaks it. We compile a program, linking it
- # against the deplibs as a proxy for the library. Then we can check
- # whether they linked in statically or dynamically with ldd.
- $opt_dry_run || $RM conftest.c
- cat > conftest.c <<EOF
- int main() { return 0; }
-EOF
- $opt_dry_run || $RM conftest
- if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
- ldd_output=`ldd conftest`
- for i in $deplibs; do
- case $i in
- -l*)
- func_stripname -l '' "$i"
- name=$func_stripname_result
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $i "*)
- newdeplibs="$newdeplibs $i"
- i=""
- ;;
- esac
- fi
- if test -n "$i" ; then
- libname=`eval "\\$ECHO \"$libname_spec\""`
- deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
- set dummy $deplib_matches; shift
- deplib_match=$1
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- $ECHO
- $ECHO "*** Warning: dynamic linker does not accept needed library $i."
- $ECHO "*** I have the capability to make that library automatically link in when"
- $ECHO "*** you link to this library. But I can only do this if you have a"
- $ECHO "*** shared version of the library, which I believe you do not have"
- $ECHO "*** because a test_compile did reveal that the linker did not use it for"
- $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
- fi
- fi
- ;;
- *)
- newdeplibs="$newdeplibs $i"
- ;;
- esac
- done
- else
- # Error occurred in the first compile. Let's try to salvage
- # the situation: Compile a separate program for each library.
- for i in $deplibs; do
- case $i in
- -l*)
- func_stripname -l '' "$i"
- name=$func_stripname_result
- $opt_dry_run || $RM conftest
- if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
- ldd_output=`ldd conftest`
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $i "*)
- newdeplibs="$newdeplibs $i"
- i=""
- ;;
- esac
- fi
- if test -n "$i" ; then
- libname=`eval "\\$ECHO \"$libname_spec\""`
- deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
- set dummy $deplib_matches; shift
- deplib_match=$1
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- $ECHO
- $ECHO "*** Warning: dynamic linker does not accept needed library $i."
- $ECHO "*** I have the capability to make that library automatically link in when"
- $ECHO "*** you link to this library. But I can only do this if you have a"
- $ECHO "*** shared version of the library, which you do not appear to have"
- $ECHO "*** because a test_compile did reveal that the linker did not use this one"
- $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
- fi
- fi
- else
- droppeddeps=yes
- $ECHO
- $ECHO "*** Warning! Library $i is needed by this library but I was not able to"
- $ECHO "*** make it link in! You will probably need to install it or some"
- $ECHO "*** library that it depends on before this library will be fully"
- $ECHO "*** functional. Installing it before continuing would be even better."
- fi
- ;;
- *)
- newdeplibs="$newdeplibs $i"
- ;;
- esac
- done
- fi
- ;;
- file_magic*)
- set dummy $deplibs_check_method; shift
- file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
- for a_deplib in $deplibs; do
- case $a_deplib in
- -l*)
- func_stripname -l '' "$a_deplib"
- name=$func_stripname_result
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $a_deplib "*)
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- ;;
- esac
- fi
- if test -n "$a_deplib" ; then
- libname=`eval "\\$ECHO \"$libname_spec\""`
- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- # Follow soft links.
- if ls -lLd "$potent_lib" 2>/dev/null |
- $GREP " -> " >/dev/null; then
- continue
- fi
- # The statement above tries to avoid entering an
- # endless loop below, in case of cyclic links.
- # We might still enter an endless loop, since a link
- # loop can be closed while we follow links,
- # but so what?
- potlib="$potent_lib"
- while test -h "$potlib" 2>/dev/null; do
- potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
- case $potliblink in
- [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
- *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
- esac
- done
- if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
- $SED -e 10q |
- $EGREP "$file_magic_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- $ECHO
- $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
- $ECHO "*** I have the capability to make that library automatically link in when"
- $ECHO "*** you link to this library. But I can only do this if you have a"
- $ECHO "*** shared version of the library, which you do not appear to have"
- $ECHO "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
- $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
- else
- $ECHO "*** with $libname and none of the candidates passed a file format test"
- $ECHO "*** using a file magic. Last file checked: $potlib"
- fi
- fi
- ;;
- *)
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- ;;
- esac
- done # Gone through all deplibs.
- ;;
- match_pattern*)
- set dummy $deplibs_check_method; shift
- match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
- for a_deplib in $deplibs; do
- case $a_deplib in
- -l*)
- func_stripname -l '' "$a_deplib"
- name=$func_stripname_result
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $a_deplib "*)
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- ;;
- esac
- fi
- if test -n "$a_deplib" ; then
- libname=`eval "\\$ECHO \"$libname_spec\""`
- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- potlib="$potent_lib" # see symlink-check above in file_magic test
- if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \
- $EGREP "$match_pattern_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- $ECHO
- $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
- $ECHO "*** I have the capability to make that library automatically link in when"
- $ECHO "*** you link to this library. But I can only do this if you have a"
- $ECHO "*** shared version of the library, which you do not appear to have"
- $ECHO "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
- $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
- else
- $ECHO "*** with $libname and none of the candidates passed a file format test"
- $ECHO "*** using a regex pattern. Last file checked: $potlib"
- fi
- fi
- ;;
- *)
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- ;;
- esac
- done # Gone through all deplibs.
- ;;
- none | unknown | *)
- newdeplibs=""
- tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \
- -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'`
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- for i in $predeps $postdeps ; do
- # can't use Xsed below, because $i might contain '/'
- tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"`
- done
- fi
- if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' |
- $GREP . >/dev/null; then
- $ECHO
- if test "X$deplibs_check_method" = "Xnone"; then
- $ECHO "*** Warning: inter-library dependencies are not supported in this platform."
- else
- $ECHO "*** Warning: inter-library dependencies are not known to be supported."
- fi
- $ECHO "*** All declared inter-library dependencies are being dropped."
- droppeddeps=yes
- fi
- ;;
- esac
- versuffix=$versuffix_save
- major=$major_save
- release=$release_save
- libname=$libname_save
- name=$name_save
-
- case $host in
- *-*-rhapsody* | *-*-darwin1.[012])
- # On Rhapsody replace the C library with the System framework
- newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
- ;;
- esac
-
- if test "$droppeddeps" = yes; then
- if test "$module" = yes; then
- $ECHO
- $ECHO "*** Warning: libtool could not satisfy all declared inter-library"
- $ECHO "*** dependencies of module $libname. Therefore, libtool will create"
- $ECHO "*** a static module, that should work as long as the dlopening"
- $ECHO "*** application is linked with the -dlopen flag."
- if test -z "$global_symbol_pipe"; then
- $ECHO
- $ECHO "*** However, this would only work if libtool was able to extract symbol"
- $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
- $ECHO "*** not find such a program. So, this module is probably useless."
- $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- else
- $ECHO "*** The inter-library dependencies that have been dropped here will be"
- $ECHO "*** automatically added whenever a program is linked with this library"
- $ECHO "*** or is declared to -dlopen it."
-
- if test "$allow_undefined" = no; then
- $ECHO
- $ECHO "*** Since this library must not contain undefined symbols,"
- $ECHO "*** because either the platform does not support them or"
- $ECHO "*** it was explicitly requested with -no-undefined,"
- $ECHO "*** libtool will only create a static version of it."
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- fi
- fi
- fi
- # Done checking deplibs!
- deplibs=$newdeplibs
- fi
- # Time to change all our "foo.ltframework" stuff back to "-framework foo"
- case $host in
- *-*-darwin*)
- newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
- new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
- deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
- ;;
- esac
-
- # move library search paths that coincide with paths to not yet
- # installed libraries to the beginning of the library search list
- new_libs=
- for path in $notinst_path; do
- case " $new_libs " in
- *" -L$path/$objdir "*) ;;
- *)
- case " $deplibs " in
- *" -L$path/$objdir "*)
- new_libs="$new_libs -L$path/$objdir" ;;
- esac
- ;;
- esac
- done
- for deplib in $deplibs; do
- case $deplib in
- -L*)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- done
- deplibs="$new_libs"
-
- # All the library-specific variables (install_libdir is set above).
- library_names=
- old_library=
- dlname=
-
- # Test again, we may have decided not to build it any more
- if test "$build_libtool_libs" = yes; then
- if test "$hardcode_into_libs" = yes; then
- # Hardcode the library paths
- hardcode_libdirs=
- dep_rpath=
- rpath="$finalize_rpath"
- test "$mode" != relink && rpath="$compile_rpath$rpath"
- for libdir in $rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- dep_rpath="$dep_rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- if test -n "$hardcode_libdir_flag_spec_ld"; then
- eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
- else
- eval dep_rpath=\"$hardcode_libdir_flag_spec\"
- fi
- fi
- if test -n "$runpath_var" && test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
- fi
- test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
- fi
-
- shlibpath="$finalize_shlibpath"
- test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
- if test -n "$shlibpath"; then
- eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
- fi
-
- # Get the real and link names of the library.
- eval shared_ext=\"$shrext_cmds\"
- eval library_names=\"$library_names_spec\"
- set dummy $library_names
- shift
- realname="$1"
- shift
-
- if test -n "$soname_spec"; then
- eval soname=\"$soname_spec\"
- else
- soname="$realname"
- fi
- if test -z "$dlname"; then
- dlname=$soname
- fi
-
- lib="$output_objdir/$realname"
- linknames=
- for link
- do
- linknames="$linknames $link"
- done
-
- # Use standard objects if they are pic
- test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- test "X$libobjs" = "X " && libobjs=
-
- delfiles=
- if test -n "$export_symbols" && test -n "$include_expsyms"; then
- $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
- export_symbols="$output_objdir/$libname.uexp"
- delfiles="$delfiles $export_symbols"
- fi
-
- orig_export_symbols=
- case $host_os in
- cygwin* | mingw* | cegcc*)
- if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
- # exporting using user supplied symfile
- if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
- # and it's NOT already a .def file. Must figure out
- # which of the given symbols are data symbols and tag
- # them as such. So, trigger use of export_symbols_cmds.
- # export_symbols gets reassigned inside the "prepare
- # the list of exported symbols" if statement, so the
- # include_expsyms logic still works.
- orig_export_symbols="$export_symbols"
- export_symbols=
- always_export_symbols=yes
- fi
- fi
- ;;
- esac
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
- func_verbose "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $opt_dry_run || $RM $export_symbols
- cmds=$export_symbols_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- func_len " $cmd"
- len=$func_len_result
- if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- func_show_eval "$cmd" 'exit $?'
- skipped_export=false
- else
- # The command line is too long to execute in one step.
- func_verbose "using reloadable object file for export list..."
- skipped_export=:
- # Break out early, otherwise skipped_export may be
- # set to false by a later but shorter cmd.
- break
- fi
- done
- IFS="$save_ifs"
- if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
- func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
- func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
- fi
- fi
- fi
-
- if test -n "$export_symbols" && test -n "$include_expsyms"; then
- tmp_export_symbols="$export_symbols"
- test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
- $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
- fi
-
- if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
- # The given exports_symbols file has to be filtered, so filter it.
- func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
- # FIXME: $output_objdir/$libname.filter potentially contains lots of
- # 's' commands which not all seds can handle. GNU sed should be fine
- # though. Also, the filter scales superlinearly with the number of
- # global variables. join(1) would be nice here, but unfortunately
- # isn't a blessed tool.
- $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
- delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
- export_symbols=$output_objdir/$libname.def
- $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
- fi
-
- tmp_deplibs=
- for test_deplib in $deplibs; do
- case " $convenience " in
- *" $test_deplib "*) ;;
- *)
- tmp_deplibs="$tmp_deplibs $test_deplib"
- ;;
- esac
- done
- deplibs="$tmp_deplibs"
-
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec" &&
- test "$compiler_needs_object" = yes &&
- test -z "$libobjs"; then
- # extract the archives, so we have objects to list.
- # TODO: could optimize this to just extract one archive.
- whole_archive_flag_spec=
- fi
- if test -n "$whole_archive_flag_spec"; then
- save_libobjs=$libobjs
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- test "X$libobjs" = "X " && libobjs=
- else
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $convenience
- libobjs="$libobjs $func_extract_archives_result"
- test "X$libobjs" = "X " && libobjs=
- fi
- fi
-
- if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
- eval flag=\"$thread_safe_flag_spec\"
- linker_flags="$linker_flags $flag"
- fi
-
- # Make a backup of the uninstalled library when relinking
- if test "$mode" = relink; then
- $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
- fi
-
- # Do each of the archive commands.
- if test "$module" = yes && test -n "$module_cmds" ; then
- if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
- eval test_cmds=\"$module_expsym_cmds\"
- cmds=$module_expsym_cmds
- else
- eval test_cmds=\"$module_cmds\"
- cmds=$module_cmds
- fi
- else
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- eval test_cmds=\"$archive_expsym_cmds\"
- cmds=$archive_expsym_cmds
- else
- eval test_cmds=\"$archive_cmds\"
- cmds=$archive_cmds
- fi
- fi
-
- if test "X$skipped_export" != "X:" &&
- func_len " $test_cmds" &&
- len=$func_len_result &&
- test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- :
- else
- # The command line is too long to link in one step, link piecewise
- # or, if using GNU ld and skipped_export is not :, use a linker
- # script.
-
- # Save the value of $output and $libobjs because we want to
- # use them later. If we have whole_archive_flag_spec, we
- # want to use save_libobjs as it was before
- # whole_archive_flag_spec was expanded, because we can't
- # assume the linker understands whole_archive_flag_spec.
- # This may have to be revisited, in case too many
- # convenience libraries get linked in and end up exceeding
- # the spec.
- if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
- save_libobjs=$libobjs
- fi
- save_output=$output
- output_la=`$ECHO "X$output" | $Xsed -e "$basename"`
-
- # Clear the reloadable object creation command queue and
- # initialize k to one.
- test_cmds=
- concat_cmds=
- objlist=
- last_robj=
- k=1
-
- if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
- output=${output_objdir}/${output_la}.lnkscript
- func_verbose "creating GNU ld script: $output"
- $ECHO 'INPUT (' > $output
- for obj in $save_libobjs
- do
- $ECHO "$obj" >> $output
- done
- $ECHO ')' >> $output
- delfiles="$delfiles $output"
- elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
- output=${output_objdir}/${output_la}.lnk
- func_verbose "creating linker input file list: $output"
- : > $output
- set x $save_libobjs
- shift
- firstobj=
- if test "$compiler_needs_object" = yes; then
- firstobj="$1 "
- shift
- fi
- for obj
- do
- $ECHO "$obj" >> $output
- done
- delfiles="$delfiles $output"
- output=$firstobj\"$file_list_spec$output\"
- else
- if test -n "$save_libobjs"; then
- func_verbose "creating reloadable object files..."
- output=$output_objdir/$output_la-${k}.$objext
- eval test_cmds=\"$reload_cmds\"
- func_len " $test_cmds"
- len0=$func_len_result
- len=$len0
-
- # Loop over the list of objects to be linked.
- for obj in $save_libobjs
- do
- func_len " $obj"
- func_arith $len + $func_len_result
- len=$func_arith_result
- if test "X$objlist" = X ||
- test "$len" -lt "$max_cmd_len"; then
- func_append objlist " $obj"
- else
- # The command $test_cmds is almost too long, add a
- # command to the queue.
- if test "$k" -eq 1 ; then
- # The first file doesn't have a previous command to add.
- eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
- else
- # All subsequent reloadable object files will link in
- # the last one created.
- eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\"
- fi
- last_robj=$output_objdir/$output_la-${k}.$objext
- func_arith $k + 1
- k=$func_arith_result
- output=$output_objdir/$output_la-${k}.$objext
- objlist=$obj
- func_len " $last_robj"
- func_arith $len0 + $func_len_result
- len=$func_arith_result
- fi
- done
- # Handle the remaining objects by creating one last
- # reloadable object file. All subsequent reloadable object
- # files will link in the last one created.
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
- if test -n "$last_robj"; then
- eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
- fi
- delfiles="$delfiles $output"
-
- else
- output=
- fi
-
- if ${skipped_export-false}; then
- func_verbose "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $opt_dry_run || $RM $export_symbols
- libobjs=$output
- # Append the command to create the export file.
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
- if test -n "$last_robj"; then
- eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
- fi
- fi
-
- test -n "$save_libobjs" &&
- func_verbose "creating a temporary reloadable object file: $output"
-
- # Loop through the commands generated above and execute them.
- save_ifs="$IFS"; IFS='~'
- for cmd in $concat_cmds; do
- IFS="$save_ifs"
- $opt_silent || {
- func_quote_for_expand "$cmd"
- eval "func_echo $func_quote_for_expand_result"
- }
- $opt_dry_run || eval "$cmd" || {
- lt_exit=$?
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- ( cd "$output_objdir" && \
- $RM "${realname}T" && \
- $MV "${realname}U" "$realname" )
- fi
-
- exit $lt_exit
- }
- done
- IFS="$save_ifs"
-
- if test -n "$export_symbols_regex" && ${skipped_export-false}; then
- func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
- func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
- fi
- fi
-
- if ${skipped_export-false}; then
- if test -n "$export_symbols" && test -n "$include_expsyms"; then
- tmp_export_symbols="$export_symbols"
- test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
- $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
- fi
-
- if test -n "$orig_export_symbols"; then
- # The given exports_symbols file has to be filtered, so filter it.
- func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
- # FIXME: $output_objdir/$libname.filter potentially contains lots of
- # 's' commands which not all seds can handle. GNU sed should be fine
- # though. Also, the filter scales superlinearly with the number of
- # global variables. join(1) would be nice here, but unfortunately
- # isn't a blessed tool.
- $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
- delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
- export_symbols=$output_objdir/$libname.def
- $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
- fi
- fi
-
- libobjs=$output
- # Restore the value of output.
- output=$save_output
-
- if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- test "X$libobjs" = "X " && libobjs=
- fi
- # Expand the library linking commands again to reset the
- # value of $libobjs for piecewise linking.
-
- # Do each of the archive commands.
- if test "$module" = yes && test -n "$module_cmds" ; then
- if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
- cmds=$module_expsym_cmds
- else
- cmds=$module_cmds
- fi
- else
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- cmds=$archive_expsym_cmds
- else
- cmds=$archive_cmds
- fi
- fi
- fi
-
- if test -n "$delfiles"; then
- # Append the command to remove temporary files to $cmds.
- eval cmds=\"\$cmds~\$RM $delfiles\"
- fi
-
- # Add any objects from preloaded convenience libraries
- if test -n "$dlprefiles"; then
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $dlprefiles
- libobjs="$libobjs $func_extract_archives_result"
- test "X$libobjs" = "X " && libobjs=
- fi
-
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $opt_silent || {
- func_quote_for_expand "$cmd"
- eval "func_echo $func_quote_for_expand_result"
- }
- $opt_dry_run || eval "$cmd" || {
- lt_exit=$?
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- ( cd "$output_objdir" && \
- $RM "${realname}T" && \
- $MV "${realname}U" "$realname" )
- fi
-
- exit $lt_exit
- }
- done
- IFS="$save_ifs"
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
-
- if test -n "$convenience"; then
- if test -z "$whole_archive_flag_spec"; then
- func_show_eval '${RM}r "$gentop"'
- fi
- fi
-
- exit $EXIT_SUCCESS
- fi
-
- # Create links to the real library.
- for linkname in $linknames; do
- if test "$realname" != "$linkname"; then
- func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
- fi
- done
-
- # If -module or -export-dynamic was specified, set the dlname.
- if test "$module" = yes || test "$export_dynamic" = yes; then
- # On all known operating systems, these are identical.
- dlname="$soname"
- fi
- fi
- ;;
-
- obj)
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- func_warning "\`-dlopen' is ignored for objects"
- fi
-
- case " $deplibs" in
- *\ -l* | *\ -L*)
- func_warning "\`-l' and \`-L' are ignored for objects" ;;
- esac
-
- test -n "$rpath" && \
- func_warning "\`-rpath' is ignored for objects"
-
- test -n "$xrpath" && \
- func_warning "\`-R' is ignored for objects"
-
- test -n "$vinfo" && \
- func_warning "\`-version-info' is ignored for objects"
-
- test -n "$release" && \
- func_warning "\`-release' is ignored for objects"
-
- case $output in
- *.lo)
- test -n "$objs$old_deplibs" && \
- func_fatal_error "cannot build library object \`$output' from non-libtool objects"
-
- libobj=$output
- func_lo2o "$libobj"
- obj=$func_lo2o_result
- ;;
- *)
- libobj=
- obj="$output"
- ;;
- esac
-
- # Delete the old objects.
- $opt_dry_run || $RM $obj $libobj
-
- # Objects from convenience libraries. This assumes
- # single-version convenience libraries. Whenever we create
- # different ones for PIC/non-PIC, this we'll have to duplicate
- # the extraction.
- reload_conv_objs=
- gentop=
- # reload_cmds runs $LD directly, so let us get rid of
- # -Wl from whole_archive_flag_spec and hope we can get by with
- # turning comma into space..
- wl=
-
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec"; then
- eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
- reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
- else
- gentop="$output_objdir/${obj}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $convenience
- reload_conv_objs="$reload_objs $func_extract_archives_result"
- fi
- fi
-
- # Create the old-style object.
- reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
-
- output="$obj"
- func_execute_cmds "$reload_cmds" 'exit $?'
-
- # Exit if we aren't doing a library object file.
- if test -z "$libobj"; then
- if test -n "$gentop"; then
- func_show_eval '${RM}r "$gentop"'
- fi
-
- exit $EXIT_SUCCESS
- fi
-
- if test "$build_libtool_libs" != yes; then
- if test -n "$gentop"; then
- func_show_eval '${RM}r "$gentop"'
- fi
-
- # Create an invalid libtool object if no PIC, so that we don't
- # accidentally link it into a program.
- # $show "echo timestamp > $libobj"
- # $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
- exit $EXIT_SUCCESS
- fi
-
- if test -n "$pic_flag" || test "$pic_mode" != default; then
- # Only do commands if we really have different PIC objects.
- reload_objs="$libobjs $reload_conv_objs"
- output="$libobj"
- func_execute_cmds "$reload_cmds" 'exit $?'
- fi
-
- if test -n "$gentop"; then
- func_show_eval '${RM}r "$gentop"'
- fi
-
- exit $EXIT_SUCCESS
- ;;
-
- prog)
- case $host in
- *cygwin*) func_stripname '' '.exe' "$output"
- output=$func_stripname_result.exe;;
- esac
- test -n "$vinfo" && \
- func_warning "\`-version-info' is ignored for programs"
-
- test -n "$release" && \
- func_warning "\`-release' is ignored for programs"
-
- test "$preload" = yes \
- && test "$dlopen_support" = unknown \
- && test "$dlopen_self" = unknown \
- && test "$dlopen_self_static" = unknown && \
- func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
-
- case $host in
- *-*-rhapsody* | *-*-darwin1.[012])
- # On Rhapsody replace the C library is the System framework
- compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
- finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
- ;;
- esac
-
- case $host in
- *-*-darwin*)
- # Don't allow lazy linking, it breaks C++ global constructors
- # But is supposedly fixed on 10.4 or later (yay!).
- if test "$tagname" = CXX ; then
- case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
- 10.[0123])
- compile_command="$compile_command ${wl}-bind_at_load"
- finalize_command="$finalize_command ${wl}-bind_at_load"
- ;;
- esac
- fi
- # Time to change all our "foo.ltframework" stuff back to "-framework foo"
- compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
- finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
- ;;
- esac
-
-
- # move library search paths that coincide with paths to not yet
- # installed libraries to the beginning of the library search list
- new_libs=
- for path in $notinst_path; do
- case " $new_libs " in
- *" -L$path/$objdir "*) ;;
- *)
- case " $compile_deplibs " in
- *" -L$path/$objdir "*)
- new_libs="$new_libs -L$path/$objdir" ;;
- esac
- ;;
- esac
- done
- for deplib in $compile_deplibs; do
- case $deplib in
- -L*)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- done
- compile_deplibs="$new_libs"
-
-
- compile_command="$compile_command $compile_deplibs"
- finalize_command="$finalize_command $finalize_deplibs"
-
- if test -n "$rpath$xrpath"; then
- # If the user specified any rpath flags, then add them.
- for libdir in $rpath $xrpath; do
- # This is the magic to use -rpath.
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- fi
-
- # Now hardcode the library paths
- rpath=
- hardcode_libdirs=
- for libdir in $compile_rpath $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
- testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
- case :$dllsearchpath: in
- *":$libdir:"*) ;;
- ::) dllsearchpath=$libdir;;
- *) dllsearchpath="$dllsearchpath:$libdir";;
- esac
- case :$dllsearchpath: in
- *":$testbindir:"*) ;;
- ::) dllsearchpath=$testbindir;;
- *) dllsearchpath="$dllsearchpath:$testbindir";;
- esac
- ;;
- esac
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- compile_rpath="$rpath"
-
- rpath=
- hardcode_libdirs=
- for libdir in $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$finalize_perm_rpath " in
- *" $libdir "*) ;;
- *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- finalize_rpath="$rpath"
-
- if test -n "$libobjs" && test "$build_old_libs" = yes; then
- # Transform all the library objects into standard objects.
- compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- fi
-
- func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
-
- # template prelinking step
- if test -n "$prelink_cmds"; then
- func_execute_cmds "$prelink_cmds" 'exit $?'
- fi
-
- wrappers_required=yes
- case $host in
- *cygwin* | *mingw* )
- if test "$build_libtool_libs" != yes; then
- wrappers_required=no
- fi
- ;;
- *cegcc)
- # Disable wrappers for cegcc, we are cross compiling anyway.
- wrappers_required=no
- ;;
- *)
- if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
- wrappers_required=no
- fi
- ;;
- esac
- if test "$wrappers_required" = no; then
- # Replace the output file specification.
- compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- link_command="$compile_command$compile_rpath"
-
- # We have no uninstalled library dependencies, so finalize right now.
- exit_status=0
- func_show_eval "$link_command" 'exit_status=$?'
-
- # Delete the generated files.
- if test -f "$output_objdir/${outputname}S.${objext}"; then
- func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
- fi
-
- exit $exit_status
- fi
-
- if test -n "$compile_shlibpath$finalize_shlibpath"; then
- compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
- fi
- if test -n "$finalize_shlibpath"; then
- finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
- fi
-
- compile_var=
- finalize_var=
- if test -n "$runpath_var"; then
- if test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- if test -n "$finalize_perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $finalize_perm_rpath; do
- rpath="$rpath$dir:"
- done
- finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- fi
-
- if test "$no_install" = yes; then
- # We don't need to create a wrapper script.
- link_command="$compile_var$compile_command$compile_rpath"
- # Replace the output file specification.
- link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- # Delete the old output file.
- $opt_dry_run || $RM $output
- # Link the executable and exit
- func_show_eval "$link_command" 'exit $?'
- exit $EXIT_SUCCESS
- fi
-
- if test "$hardcode_action" = relink; then
- # Fast installation is not supported
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
-
- func_warning "this platform does not like uninstalled shared libraries"
- func_warning "\`$output' will be relinked during installation"
- else
- if test "$fast_install" != no; then
- link_command="$finalize_var$compile_command$finalize_rpath"
- if test "$fast_install" = yes; then
- relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
- else
- # fast_install is set to needless
- relink_command=
- fi
- else
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
- fi
- fi
-
- # Replace the output file specification.
- link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-
- # Delete the old output files.
- $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
-
- func_show_eval "$link_command" 'exit $?'
-
- # Now create the wrapper script.
- func_verbose "creating $output"
-
- # Quote the relink command for shipping.
- if test -n "$relink_command"; then
- # Preserve any variables that may affect compiler behavior
- for var in $variables_saved_for_relink; do
- if eval test -z \"\${$var+set}\"; then
- relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
- elif eval var_value=\$$var; test -z "$var_value"; then
- relink_command="$var=; export $var; $relink_command"
- else
- func_quote_for_eval "$var_value"
- relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
- fi
- done
- relink_command="(cd `pwd`; $relink_command)"
- relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Quote $ECHO for shipping.
- if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then
- case $progpath in
- [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
- *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
- esac
- qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"`
- else
- qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Only actually do things if not in dry run mode.
- $opt_dry_run || {
- # win32 will think the script is a binary if it has
- # a .exe suffix, so we strip it off here.
- case $output in
- *.exe) func_stripname '' '.exe' "$output"
- output=$func_stripname_result ;;
- esac
- # test for cygwin because mv fails w/o .exe extensions
- case $host in
- *cygwin*)
- exeext=.exe
- func_stripname '' '.exe' "$outputname"
- outputname=$func_stripname_result ;;
- *) exeext= ;;
- esac
- case $host in
- *cygwin* | *mingw* )
- func_dirname_and_basename "$output" "" "."
- output_name=$func_basename_result
- output_path=$func_dirname_result
- cwrappersource="$output_path/$objdir/lt-$output_name.c"
- cwrapper="$output_path/$output_name.exe"
- $RM $cwrappersource $cwrapper
- trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
-
- func_emit_cwrapperexe_src > $cwrappersource
-
- # The wrapper executable is built using the $host compiler,
- # because it contains $host paths and files. If cross-
- # compiling, it, like the target executable, must be
- # executed on the $host or under an emulation environment.
- $opt_dry_run || {
- $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
- $STRIP $cwrapper
- }
-
- # Now, create the wrapper script for func_source use:
- func_ltwrapper_scriptname $cwrapper
- $RM $func_ltwrapper_scriptname_result
- trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
- $opt_dry_run || {
- # note: this script will not be executed, so do not chmod.
- if test "x$build" = "x$host" ; then
- $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
- else
- func_emit_wrapper no > $func_ltwrapper_scriptname_result
- fi
- }
- ;;
- * )
- $RM $output
- trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
-
- func_emit_wrapper no > $output
- chmod +x $output
- ;;
- esac
- }
- exit $EXIT_SUCCESS
- ;;
- esac
-
- # See if we need to build an old-fashioned archive.
- for oldlib in $oldlibs; do
-
- if test "$build_libtool_libs" = convenience; then
- oldobjs="$libobjs_save $symfileobj"
- addlibs="$convenience"
- build_libtool_libs=no
- else
- if test "$build_libtool_libs" = module; then
- oldobjs="$libobjs_save"
- build_libtool_libs=no
- else
- oldobjs="$old_deplibs $non_pic_objects"
- if test "$preload" = yes && test -f "$symfileobj"; then
- oldobjs="$oldobjs $symfileobj"
- fi
- fi
- addlibs="$old_convenience"
- fi
-
- if test -n "$addlibs"; then
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $addlibs
- oldobjs="$oldobjs $func_extract_archives_result"
- fi
-
- # Do each command in the archive commands.
- if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
- cmds=$old_archive_from_new_cmds
- else
-
- # Add any objects from preloaded convenience libraries
- if test -n "$dlprefiles"; then
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $dlprefiles
- oldobjs="$oldobjs $func_extract_archives_result"
- fi
-
- # POSIX demands no paths to be encoded in archives. We have
- # to avoid creating archives with duplicate basenames if we
- # might have to extract them afterwards, e.g., when creating a
- # static archive out of a convenience library, or when linking
- # the entirety of a libtool archive into another (currently
- # not supported by libtool).
- if (for obj in $oldobjs
- do
- func_basename "$obj"
- $ECHO "$func_basename_result"
- done | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $ECHO "copying selected object files to avoid basename conflicts..."
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
- func_mkdir_p "$gentop"
- save_oldobjs=$oldobjs
- oldobjs=
- counter=1
- for obj in $save_oldobjs
- do
- func_basename "$obj"
- objbase="$func_basename_result"
- case " $oldobjs " in
- " ") oldobjs=$obj ;;
- *[\ /]"$objbase "*)
- while :; do
- # Make sure we don't pick an alternate name that also
- # overlaps.
- newobj=lt$counter-$objbase
- func_arith $counter + 1
- counter=$func_arith_result
- case " $oldobjs " in
- *[\ /]"$newobj "*) ;;
- *) if test ! -f "$gentop/$newobj"; then break; fi ;;
- esac
- done
- func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
- oldobjs="$oldobjs $gentop/$newobj"
- ;;
- *) oldobjs="$oldobjs $obj" ;;
- esac
- done
- fi
- eval cmds=\"$old_archive_cmds\"
-
- func_len " $cmds"
- len=$func_len_result
- if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- cmds=$old_archive_cmds
- else
- # the command line is too long to link in one step, link in parts
- func_verbose "using piecewise archive linking..."
- save_RANLIB=$RANLIB
- RANLIB=:
- objlist=
- concat_cmds=
- save_oldobjs=$oldobjs
- oldobjs=
- # Is there a better way of finding the last object in the list?
- for obj in $save_oldobjs
- do
- last_oldobj=$obj
- done
- eval test_cmds=\"$old_archive_cmds\"
- func_len " $test_cmds"
- len0=$func_len_result
- len=$len0
- for obj in $save_oldobjs
- do
- func_len " $obj"
- func_arith $len + $func_len_result
- len=$func_arith_result
- func_append objlist " $obj"
- if test "$len" -lt "$max_cmd_len"; then
- :
- else
- # the above command should be used before it gets too long
- oldobjs=$objlist
- if test "$obj" = "$last_oldobj" ; then
- RANLIB=$save_RANLIB
- fi
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
- objlist=
- len=$len0
- fi
- done
- RANLIB=$save_RANLIB
- oldobjs=$objlist
- if test "X$oldobjs" = "X" ; then
- eval cmds=\"\$concat_cmds\"
- else
- eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
- fi
- fi
- fi
- func_execute_cmds "$cmds" 'exit $?'
- done
-
- test -n "$generated" && \
- func_show_eval "${RM}r$generated"
-
- # Now create the libtool archive.
- case $output in
- *.la)
- old_library=
- test "$build_old_libs" = yes && old_library="$libname.$libext"
- func_verbose "creating $output"
-
- # Preserve any variables that may affect compiler behavior
- for var in $variables_saved_for_relink; do
- if eval test -z \"\${$var+set}\"; then
- relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
- elif eval var_value=\$$var; test -z "$var_value"; then
- relink_command="$var=; export $var; $relink_command"
- else
- func_quote_for_eval "$var_value"
- relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
- fi
- done
- # Quote the link command for shipping.
- relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
- relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
- if test "$hardcode_automatic" = yes ; then
- relink_command=
- fi
-
- # Only create the output if not a dry run.
- $opt_dry_run || {
- for installed in no yes; do
- if test "$installed" = yes; then
- if test -z "$install_libdir"; then
- break
- fi
- output="$output_objdir/$outputname"i
- # Replace all uninstalled libtool libraries with the installed ones
- newdependency_libs=
- for deplib in $dependency_libs; do
- case $deplib in
- *.la)
- func_basename "$deplib"
- name="$func_basename_result"
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- test -z "$libdir" && \
- func_fatal_error "\`$deplib' is not a valid libtool archive"
- if test "x$EGREP" = x ; then
- EGREP=egrep
- fi
- # We do not want portage's install root ($D) present. Check only for
- # this if the .la is being installed.
- if test "$installed" = yes && test "$D"; then
- eval mynewdependency_lib=`echo "$libdir/$name" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
- else
- mynewdependency_lib="$libdir/$name"
- fi
- # Do not add duplicates
- if test "$mynewdependency_lib"; then
- my_little_ninja_foo_1=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"`
- if test -z "$my_little_ninja_foo_1"; then
- newdependency_libs="$newdependency_libs $mynewdependency_lib"
- fi
- fi
- ;;
- *)
- if test "$installed" = yes; then
- # Rather use S=WORKDIR if our version of portage supports it.
- # This is because some ebuild (gcc) do not use $S as buildroot.
- if test "$PWORKDIR"; then
- S="$PWORKDIR"
- fi
- # We do not want portage's build root ($S) present.
- my_little_ninja_foo_2=`echo $deplib |$EGREP -e "$S"`
- # We do not want portage's install root ($D) present.
- my_little_ninja_foo_3=`echo $deplib |$EGREP -e "$D"`
- if test -n "$my_little_ninja_foo_2" && test "$S"; then
- mynewdependency_lib=""
- elif test -n "$my_little_ninja_foo_3" && test "$D"; then
- eval mynewdependency_lib=`echo "$deplib" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
- else
- mynewdependency_lib="$deplib"
- fi
- else
- mynewdependency_lib="$deplib"
- fi
- # Do not add duplicates
- if test "$mynewdependency_lib"; then
- my_little_ninja_foo_4=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"`
- if test -z "$my_little_ninja_foo_4"; then
- newdependency_libs="$newdependency_libs $mynewdependency_lib"
- fi
- fi
- ;;
- esac
- done
- dependency_libs="$newdependency_libs"
- newdlfiles=
-
- for lib in $dlfiles; do
- case $lib in
- *.la)
- func_basename "$lib"
- name="$func_basename_result"
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- test -z "$libdir" && \
- func_fatal_error "\`$lib' is not a valid libtool archive"
- newdlfiles="$newdlfiles $libdir/$name"
- ;;
- *) newdlfiles="$newdlfiles $lib" ;;
- esac
- done
- dlfiles="$newdlfiles"
- newdlprefiles=
- for lib in $dlprefiles; do
- case $lib in
- *.la)
- # Only pass preopened files to the pseudo-archive (for
- # eventual linking with the app. that links it) if we
- # didn't already link the preopened objects directly into
- # the library:
- func_basename "$lib"
- name="$func_basename_result"
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- test -z "$libdir" && \
- func_fatal_error "\`$lib' is not a valid libtool archive"
- newdlprefiles="$newdlprefiles $libdir/$name"
- ;;
- esac
- done
- dlprefiles="$newdlprefiles"
- else
- newdlfiles=
- for lib in $dlfiles; do
- case $lib in
- [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
- *) abs=`pwd`"/$lib" ;;
- esac
- newdlfiles="$newdlfiles $abs"
- done
- dlfiles="$newdlfiles"
- newdlprefiles=
- for lib in $dlprefiles; do
- case $lib in
- [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
- *) abs=`pwd`"/$lib" ;;
- esac
- newdlprefiles="$newdlprefiles $abs"
- done
- dlprefiles="$newdlprefiles"
- fi
- $RM $output
- # place dlname in correct position for cygwin
- tdlname=$dlname
- case $host,$output,$installed,$module,$dlname in
- *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
- esac
- # Do not add duplicates
- if test "$installed" = yes && test "$D"; then
- install_libdir=`echo "$install_libdir" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
- fi
- $ECHO > $output "\
-# $outputname - a libtool library file
-# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# The name that we can dlopen(3).
-dlname='$tdlname'
-
-# Names of this library.
-library_names='$library_names'
-
-# The name of the static archive.
-old_library='$old_library'
-
-# Linker flags that can not go in dependency_libs.
-inherited_linker_flags='$new_inherited_linker_flags'
-
-# Libraries that this one depends upon.
-dependency_libs='$dependency_libs'
-
-# Names of additional weak libraries provided by this library
-weak_library_names='$weak_libs'
-
-# Version information for $libname.
-current=$current
-age=$age
-revision=$revision
-
-# Is this an already installed library?
-installed=$installed
-
-# Should we warn about portability when linking against -modules?
-shouldnotlink=$module
-
-# Files to dlopen/dlpreopen
-dlopen='$dlfiles'
-dlpreopen='$dlprefiles'
-
-# Directory that this library needs to be installed in:
-libdir='$install_libdir'"
- if test "$installed" = no && test "$need_relink" = yes; then
- $ECHO >> $output "\
-relink_command=\"$relink_command\""
- fi
- done
- }
-
- # Do a symbolic link so that the libtool archive can be found in
- # LD_LIBRARY_PATH before the program is installed.
- func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
- ;;
- esac
- exit $EXIT_SUCCESS
-}
-
-{ test "$mode" = link || test "$mode" = relink; } &&
- func_mode_link ${1+"$@"}
-
-
-# func_mode_uninstall arg...
-func_mode_uninstall ()
-{
- $opt_debug
- RM="$nonopt"
- files=
- rmforce=
- exit_status=0
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- for arg
- do
- case $arg in
- -f) RM="$RM $arg"; rmforce=yes ;;
- -*) RM="$RM $arg" ;;
- *) files="$files $arg" ;;
- esac
- done
-
- test -z "$RM" && \
- func_fatal_help "you must specify an RM program"
-
- rmdirs=
-
- origobjdir="$objdir"
- for file in $files; do
- func_dirname "$file" "" "."
- dir="$func_dirname_result"
- if test "X$dir" = X.; then
- objdir="$origobjdir"
- else
- objdir="$dir/$origobjdir"
- fi
- func_basename "$file"
- name="$func_basename_result"
- test "$mode" = uninstall && objdir="$dir"
-
- # Remember objdir for removal later, being careful to avoid duplicates
- if test "$mode" = clean; then
- case " $rmdirs " in
- *" $objdir "*) ;;
- *) rmdirs="$rmdirs $objdir" ;;
- esac
- fi
-
- # Don't error if the file doesn't exist and rm -f was used.
- if { test -L "$file"; } >/dev/null 2>&1 ||
- { test -h "$file"; } >/dev/null 2>&1 ||
- test -f "$file"; then
- :
- elif test -d "$file"; then
- exit_status=1
- continue
- elif test "$rmforce" = yes; then
- continue
- fi
-
- rmfiles="$file"
-
- case $name in
- *.la)
- # Possibly a libtool archive, so verify it.
- if func_lalib_p "$file"; then
- func_source $dir/$name
-
- # Delete the libtool libraries and symlinks.
- for n in $library_names; do
- rmfiles="$rmfiles $objdir/$n"
- done
- test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
-
- case "$mode" in
- clean)
- case " $library_names " in
- # " " in the beginning catches empty $dlname
- *" $dlname "*) ;;
- *) rmfiles="$rmfiles $objdir/$dlname" ;;
- esac
- test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
- ;;
- uninstall)
- if test -n "$library_names"; then
- # Do each command in the postuninstall commands.
- func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
- fi
-
- if test -n "$old_library"; then
- # Do each command in the old_postuninstall commands.
- func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
- fi
- # FIXME: should reinstall the best remaining shared library.
- ;;
- esac
- fi
- ;;
-
- *.lo)
- # Possibly a libtool object, so verify it.
- if func_lalib_p "$file"; then
-
- # Read the .lo file
- func_source $dir/$name
-
- # Add PIC object to the list of files to remove.
- if test -n "$pic_object" &&
- test "$pic_object" != none; then
- rmfiles="$rmfiles $dir/$pic_object"
- fi
-
- # Add non-PIC object to the list of files to remove.
- if test -n "$non_pic_object" &&
- test "$non_pic_object" != none; then
- rmfiles="$rmfiles $dir/$non_pic_object"
- fi
- fi
- ;;
-
- *)
- if test "$mode" = clean ; then
- noexename=$name
- case $file in
- *.exe)
- func_stripname '' '.exe' "$file"
- file=$func_stripname_result
- func_stripname '' '.exe' "$name"
- noexename=$func_stripname_result
- # $file with .exe has already been added to rmfiles,
- # add $file without .exe
- rmfiles="$rmfiles $file"
- ;;
- esac
- # Do a test to see if this is a libtool program.
- if func_ltwrapper_p "$file"; then
- if func_ltwrapper_executable_p "$file"; then
- func_ltwrapper_scriptname "$file"
- relink_command=
- func_source $func_ltwrapper_scriptname_result
- rmfiles="$rmfiles $func_ltwrapper_scriptname_result"
- else
- relink_command=
- func_source $dir/$noexename
- fi
-
- # note $name still contains .exe if it was in $file originally
- # as does the version of $file that was added into $rmfiles
- rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
- if test "$fast_install" = yes && test -n "$relink_command"; then
- rmfiles="$rmfiles $objdir/lt-$name"
- fi
- if test "X$noexename" != "X$name" ; then
- rmfiles="$rmfiles $objdir/lt-${noexename}.c"
- fi
- fi
- fi
- ;;
- esac
- func_show_eval "$RM $rmfiles" 'exit_status=1'
- done
- objdir="$origobjdir"
-
- # Try to remove the ${objdir}s in the directories where we deleted files
- for dir in $rmdirs; do
- if test -d "$dir"; then
- func_show_eval "rmdir $dir >/dev/null 2>&1"
- fi
- done
-
- exit $exit_status
-}
-
-{ test "$mode" = uninstall || test "$mode" = clean; } &&
- func_mode_uninstall ${1+"$@"}
-
-test -z "$mode" && {
- help="$generic_help"
- func_fatal_help "you must specify a MODE"
-}
-
-test -z "$exec_cmd" && \
- func_fatal_help "invalid operation mode \`$mode'"
-
-if test -n "$exec_cmd"; then
- eval exec "$exec_cmd"
- exit $EXIT_FAILURE
-fi
-
-exit $exit_status
-
-
-# The TAGs below are defined such that we never get into a situation
-# in which we disable both kinds of libraries. Given conflicting
-# choices, we go for a static library, that is the most portable,
-# since we can't tell whether shared libraries were disabled because
-# the user asked for that or because the platform doesn't support
-# them. This is particularly important on AIX, because we don't
-# support having both static and shared libraries enabled at the same
-# time on that platform, so we default to a shared-only configuration.
-# If a disable-shared tag is given, we'll fallback to a static-only
-# configuration. But we'll never go from static-only to shared-only.
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
-build_libtool_libs=no
-build_old_libs=yes
-# ### END LIBTOOL TAG CONFIG: disable-shared
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-static
-build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
-# ### END LIBTOOL TAG CONFIG: disable-static
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
-# vi:sw=2
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/magic.txt b/chromium/third_party/sqlite/sqlite-src-3240000/magic.txt
deleted file mode 100644
index 65622687cc4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/magic.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-# This file contains suggested magic(5) text for the unix file(1)
-# utility for recognizing SQLite3 databases.
-#
-# When SQLite is used as an application file format, it is desirable to
-# have file(1) recognize the database file as being with the specific
-# application. You can set the application_id for a database file
-# using:
-#
-# PRAGMA application_id = INTEGER;
-#
-# INTEGER can be any signed 32-bit integer. That integer is written as
-# a 4-byte big-endian integer into offset 68 of the database header.
-#
-# The Monotone application used "PRAGMA user_version=1598903374;" to set
-# its identifier long before "PRAGMA application_id" became available.
-# The user_version is very similar to application_id except that it is
-# stored at offset 68 instead of offset 60. The application_id pragma
-# is preferred. The rule using offset 60 for Monotone is for historical
-# compatibility only.
-#
-0 string =SQLite\ format\ 3
->68 belong =0x0f055112 Fossil checkout -
->68 belong =0x0f055113 Fossil global configuration -
->68 belong =0x0f055111 Fossil repository -
->68 belong =0x42654462 Bentley Systems BeSQLite Database -
->68 belong =0x42654c6e Bentley Systems Localization File -
->60 belong =0x5f4d544e Monotone source repository -
->68 belong =0x47504b47 OGC GeoPackage file -
->68 belong =0x47503130 OGC GeoPackage version 1.0 file -
->68 belong =0x45737269 Esri Spatially-Enabled Database -
->68 belong =0x4d504258 MBTiles tileset -
->0 string =SQLite SQLite3 database
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/main.mk b/chromium/third_party/sqlite/sqlite-src-3240000/main.mk
deleted file mode 100644
index 8dc423c5b51..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/main.mk
+++ /dev/null
@@ -1,1080 +0,0 @@
-###############################################################################
-# The following macros should be defined before this script is
-# invoked:
-#
-# TOP The toplevel directory of the source tree. This is the
-# directory that contains this "Makefile.in" and the
-# "configure.in" script.
-#
-# BCC C Compiler and options for use in building executables that
-# will run on the platform that is doing the build.
-#
-# THREADLIB Specify any extra linker options needed to make the library
-# thread safe
-#
-# LIBS Extra libraries options
-#
-# OPTS Extra compiler command-line options.
-#
-# EXE The suffix to add to executable files. ".exe" for windows
-# and "" for Unix.
-#
-# TCC C Compiler and options for use in building executables that
-# will run on the target platform. This is usually the same
-# as BCC, unless you are cross-compiling.
-#
-# AR Tools used to build a static library.
-# RANLIB
-#
-# TCL_FLAGS Extra compiler options needed for programs that use the
-# TCL library.
-#
-# LIBTCL Linker options needed to link against the TCL library.
-#
-# READLINE_FLAGS Compiler options needed for programs that use the
-# readline() library.
-#
-# LIBREADLINE Linker options needed by programs using readline() must
-# link against.
-#
-# Once the macros above are defined, the rest of this make script will
-# build the SQLite library and testing tools.
-################################################################################
-
-# This is how we compile
-#
-TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
-TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3
-TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth
-TCCX += -I$(TOP)/ext/session
-TCCX += -I$(TOP)/ext/fts5
-THREADLIB += $(LIBS)
-
-# Object files for the SQLite library.
-#
-LIBOBJ+= vdbe.o parse.o \
- alter.o analyze.o attach.o auth.o \
- backup.o bitvec.o btmutex.o btree.o build.o \
- callback.o complete.o ctime.o \
- date.o dbpage.o dbstat.o delete.o expr.o \
- fault.o fkey.o \
- fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
- fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
- fts3_tokenize_vtab.o \
- fts3_unicode.o fts3_unicode2.o \
- fts3_write.o fts5.o func.o global.o hash.o \
- icu.o insert.o json1.o legacy.o loadext.o \
- main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
- memdb.o memjournal.o \
- mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
- notify.o opcodes.o os.o os_unix.o os_win.o \
- pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
- random.o resolve.o rowset.o rtree.o \
- select.o sqlite3rbu.o status.o stmt.o \
- table.o threads.o tokenize.o treeview.o trigger.o \
- update.o upsert.o userauth.o util.o vacuum.o \
- vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
- vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \
- utf.o vtab.o
-
-LIBOBJ += sqlite3session.o
-
-# All of the source code files.
-#
-SRC = \
- $(TOP)/src/alter.c \
- $(TOP)/src/analyze.c \
- $(TOP)/src/attach.c \
- $(TOP)/src/auth.c \
- $(TOP)/src/backup.c \
- $(TOP)/src/bitvec.c \
- $(TOP)/src/btmutex.c \
- $(TOP)/src/btree.c \
- $(TOP)/src/btree.h \
- $(TOP)/src/btreeInt.h \
- $(TOP)/src/build.c \
- $(TOP)/src/callback.c \
- $(TOP)/src/complete.c \
- $(TOP)/src/ctime.c \
- $(TOP)/src/date.c \
- $(TOP)/src/dbpage.c \
- $(TOP)/src/dbstat.c \
- $(TOP)/src/delete.c \
- $(TOP)/src/expr.c \
- $(TOP)/src/fault.c \
- $(TOP)/src/fkey.c \
- $(TOP)/src/func.c \
- $(TOP)/src/global.c \
- $(TOP)/src/hash.c \
- $(TOP)/src/hash.h \
- $(TOP)/src/hwtime.h \
- $(TOP)/src/insert.c \
- $(TOP)/src/legacy.c \
- $(TOP)/src/loadext.c \
- $(TOP)/src/main.c \
- $(TOP)/src/malloc.c \
- $(TOP)/src/mem0.c \
- $(TOP)/src/mem1.c \
- $(TOP)/src/mem2.c \
- $(TOP)/src/mem3.c \
- $(TOP)/src/mem5.c \
- $(TOP)/src/memdb.c \
- $(TOP)/src/memjournal.c \
- $(TOP)/src/msvc.h \
- $(TOP)/src/mutex.c \
- $(TOP)/src/mutex.h \
- $(TOP)/src/mutex_noop.c \
- $(TOP)/src/mutex_unix.c \
- $(TOP)/src/mutex_w32.c \
- $(TOP)/src/notify.c \
- $(TOP)/src/os.c \
- $(TOP)/src/os.h \
- $(TOP)/src/os_common.h \
- $(TOP)/src/os_setup.h \
- $(TOP)/src/os_unix.c \
- $(TOP)/src/os_win.c \
- $(TOP)/src/os_win.h \
- $(TOP)/src/pager.c \
- $(TOP)/src/pager.h \
- $(TOP)/src/parse.y \
- $(TOP)/src/pcache.c \
- $(TOP)/src/pcache.h \
- $(TOP)/src/pcache1.c \
- $(TOP)/src/pragma.c \
- $(TOP)/src/pragma.h \
- $(TOP)/src/prepare.c \
- $(TOP)/src/printf.c \
- $(TOP)/src/random.c \
- $(TOP)/src/resolve.c \
- $(TOP)/src/rowset.c \
- $(TOP)/src/select.c \
- $(TOP)/src/status.c \
- $(TOP)/src/shell.c.in \
- $(TOP)/src/sqlite.h.in \
- $(TOP)/src/sqlite3ext.h \
- $(TOP)/src/sqliteInt.h \
- $(TOP)/src/sqliteLimit.h \
- $(TOP)/src/table.c \
- $(TOP)/src/tclsqlite.c \
- $(TOP)/src/threads.c \
- $(TOP)/src/tokenize.c \
- $(TOP)/src/treeview.c \
- $(TOP)/src/trigger.c \
- $(TOP)/src/utf.c \
- $(TOP)/src/update.c \
- $(TOP)/src/upsert.c \
- $(TOP)/src/util.c \
- $(TOP)/src/vacuum.c \
- $(TOP)/src/vdbe.c \
- $(TOP)/src/vdbe.h \
- $(TOP)/src/vdbeapi.c \
- $(TOP)/src/vdbeaux.c \
- $(TOP)/src/vdbeblob.c \
- $(TOP)/src/vdbemem.c \
- $(TOP)/src/vdbesort.c \
- $(TOP)/src/vdbetrace.c \
- $(TOP)/src/vdbeInt.h \
- $(TOP)/src/vtab.c \
- $(TOP)/src/vxworks.h \
- $(TOP)/src/wal.c \
- $(TOP)/src/wal.h \
- $(TOP)/src/walker.c \
- $(TOP)/src/where.c \
- $(TOP)/src/wherecode.c \
- $(TOP)/src/whereexpr.c \
- $(TOP)/src/whereInt.h
-
-# Source code for extensions
-#
-SRC += \
- $(TOP)/ext/fts1/fts1.c \
- $(TOP)/ext/fts1/fts1.h \
- $(TOP)/ext/fts1/fts1_hash.c \
- $(TOP)/ext/fts1/fts1_hash.h \
- $(TOP)/ext/fts1/fts1_porter.c \
- $(TOP)/ext/fts1/fts1_tokenizer.h \
- $(TOP)/ext/fts1/fts1_tokenizer1.c
-SRC += \
- $(TOP)/ext/fts2/fts2.c \
- $(TOP)/ext/fts2/fts2.h \
- $(TOP)/ext/fts2/fts2_hash.c \
- $(TOP)/ext/fts2/fts2_hash.h \
- $(TOP)/ext/fts2/fts2_icu.c \
- $(TOP)/ext/fts2/fts2_porter.c \
- $(TOP)/ext/fts2/fts2_tokenizer.h \
- $(TOP)/ext/fts2/fts2_tokenizer.c \
- $(TOP)/ext/fts2/fts2_tokenizer1.c
-SRC += \
- $(TOP)/ext/fts3/fts3.c \
- $(TOP)/ext/fts3/fts3.h \
- $(TOP)/ext/fts3/fts3Int.h \
- $(TOP)/ext/fts3/fts3_aux.c \
- $(TOP)/ext/fts3/fts3_expr.c \
- $(TOP)/ext/fts3/fts3_hash.c \
- $(TOP)/ext/fts3/fts3_hash.h \
- $(TOP)/ext/fts3/fts3_icu.c \
- $(TOP)/ext/fts3/fts3_porter.c \
- $(TOP)/ext/fts3/fts3_snippet.c \
- $(TOP)/ext/fts3/fts3_tokenizer.h \
- $(TOP)/ext/fts3/fts3_tokenizer.c \
- $(TOP)/ext/fts3/fts3_tokenizer1.c \
- $(TOP)/ext/fts3/fts3_tokenize_vtab.c \
- $(TOP)/ext/fts3/fts3_unicode.c \
- $(TOP)/ext/fts3/fts3_unicode2.c \
- $(TOP)/ext/fts3/fts3_write.c
-SRC += \
- $(TOP)/ext/icu/sqliteicu.h \
- $(TOP)/ext/icu/icu.c
-SRC += \
- $(TOP)/ext/rtree/sqlite3rtree.h \
- $(TOP)/ext/rtree/rtree.h \
- $(TOP)/ext/rtree/rtree.c
-SRC += \
- $(TOP)/ext/session/sqlite3session.c \
- $(TOP)/ext/session/sqlite3session.h
-SRC += \
- $(TOP)/ext/userauth/userauth.c \
- $(TOP)/ext/userauth/sqlite3userauth.h
-SRC += \
- $(TOP)/ext/rbu/sqlite3rbu.c \
- $(TOP)/ext/rbu/sqlite3rbu.h
-SRC += \
- $(TOP)/ext/misc/json1.c \
- $(TOP)/ext/misc/stmt.c
-
-
-# FTS5 things
-#
-FTS5_HDR = \
- $(TOP)/ext/fts5/fts5.h \
- $(TOP)/ext/fts5/fts5Int.h \
- fts5parse.h
-
-FTS5_SRC = \
- $(TOP)/ext/fts5/fts5_aux.c \
- $(TOP)/ext/fts5/fts5_buffer.c \
- $(TOP)/ext/fts5/fts5_main.c \
- $(TOP)/ext/fts5/fts5_config.c \
- $(TOP)/ext/fts5/fts5_expr.c \
- $(TOP)/ext/fts5/fts5_hash.c \
- $(TOP)/ext/fts5/fts5_index.c \
- fts5parse.c \
- $(TOP)/ext/fts5/fts5_storage.c \
- $(TOP)/ext/fts5/fts5_tokenize.c \
- $(TOP)/ext/fts5/fts5_unicode2.c \
- $(TOP)/ext/fts5/fts5_varint.c \
- $(TOP)/ext/fts5/fts5_vocab.c \
-
-LSM1_SRC = \
- $(TOP)/ext/lsm1/lsm.h \
- $(TOP)/ext/lsm1/lsmInt.h \
- $(TOP)/ext/lsm1/lsm_ckpt.c \
- $(TOP)/ext/lsm1/lsm_file.c \
- $(TOP)/ext/lsm1/lsm_log.c \
- $(TOP)/ext/lsm1/lsm_main.c \
- $(TOP)/ext/lsm1/lsm_mem.c \
- $(TOP)/ext/lsm1/lsm_mutex.c \
- $(TOP)/ext/lsm1/lsm_shared.c \
- $(TOP)/ext/lsm1/lsm_sorted.c \
- $(TOP)/ext/lsm1/lsm_str.c \
- $(TOP)/ext/lsm1/lsm_tree.c \
- $(TOP)/ext/lsm1/lsm_unix.c \
- $(TOP)/ext/lsm1/lsm_varint.c \
- $(TOP)/ext/lsm1/lsm_vtab.c \
- $(TOP)/ext/lsm1/lsm_win32.c
-
-
-# Generated source code files
-#
-SRC += \
- keywordhash.h \
- opcodes.c \
- opcodes.h \
- parse.c \
- parse.h \
- shell.c \
- sqlite3.h
-
-
-# Source code to the test files.
-#
-TESTSRC = \
- $(TOP)/ext/expert/sqlite3expert.c \
- $(TOP)/ext/expert/test_expert.c \
- $(TOP)/ext/fts3/fts3_term.c \
- $(TOP)/ext/fts3/fts3_test.c \
- $(TOP)/ext/rbu/test_rbu.c \
- $(TOP)/src/test1.c \
- $(TOP)/src/test2.c \
- $(TOP)/src/test3.c \
- $(TOP)/src/test4.c \
- $(TOP)/src/test5.c \
- $(TOP)/src/test6.c \
- $(TOP)/src/test7.c \
- $(TOP)/src/test8.c \
- $(TOP)/src/test9.c \
- $(TOP)/src/test_autoext.c \
- $(TOP)/src/test_async.c \
- $(TOP)/src/test_backup.c \
- $(TOP)/src/test_bestindex.c \
- $(TOP)/src/test_blob.c \
- $(TOP)/src/test_btree.c \
- $(TOP)/src/test_config.c \
- $(TOP)/src/test_delete.c \
- $(TOP)/src/test_demovfs.c \
- $(TOP)/src/test_devsym.c \
- $(TOP)/src/test_fs.c \
- $(TOP)/src/test_func.c \
- $(TOP)/src/test_hexio.c \
- $(TOP)/src/test_init.c \
- $(TOP)/src/test_intarray.c \
- $(TOP)/src/test_journal.c \
- $(TOP)/src/test_malloc.c \
- $(TOP)/src/test_md5.c \
- $(TOP)/src/test_multiplex.c \
- $(TOP)/src/test_mutex.c \
- $(TOP)/src/test_onefile.c \
- $(TOP)/src/test_osinst.c \
- $(TOP)/src/test_pcache.c \
- $(TOP)/src/test_quota.c \
- $(TOP)/src/test_rtree.c \
- $(TOP)/src/test_schema.c \
- $(TOP)/src/test_server.c \
- $(TOP)/src/test_sqllog.c \
- $(TOP)/src/test_superlock.c \
- $(TOP)/src/test_syscall.c \
- $(TOP)/src/test_tclsh.c \
- $(TOP)/src/test_tclvar.c \
- $(TOP)/src/test_thread.c \
- $(TOP)/src/test_vfs.c \
- $(TOP)/src/test_windirent.c \
- $(TOP)/src/test_wsd.c
-
-# Extensions to be statically loaded.
-#
-TESTSRC += \
- $(TOP)/ext/misc/amatch.c \
- $(TOP)/ext/misc/carray.c \
- $(TOP)/ext/misc/closure.c \
- $(TOP)/ext/misc/csv.c \
- $(TOP)/ext/misc/eval.c \
- $(TOP)/ext/misc/fileio.c \
- $(TOP)/ext/misc/fuzzer.c \
- $(TOP)/ext/misc/ieee754.c \
- $(TOP)/ext/misc/mmapwarm.c \
- $(TOP)/ext/misc/nextchar.c \
- $(TOP)/ext/misc/normalize.c \
- $(TOP)/ext/misc/percentile.c \
- $(TOP)/ext/misc/regexp.c \
- $(TOP)/ext/misc/remember.c \
- $(TOP)/ext/misc/series.c \
- $(TOP)/ext/misc/spellfix.c \
- $(TOP)/ext/misc/totype.c \
- $(TOP)/ext/misc/unionvtab.c \
- $(TOP)/ext/misc/wholenumber.c \
- $(TOP)/ext/misc/vfslog.c \
- $(TOP)/ext/misc/zipfile.c \
- $(TOP)/ext/fts5/fts5_tcl.c \
- $(TOP)/ext/fts5/fts5_test_mi.c \
- $(TOP)/ext/fts5/fts5_test_tok.c
-
-
-#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
-#TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c
-
-TESTSRC2 = \
- $(TOP)/src/attach.c \
- $(TOP)/src/backup.c \
- $(TOP)/src/btree.c \
- $(TOP)/src/build.c \
- $(TOP)/src/date.c \
- $(TOP)/src/dbpage.c \
- $(TOP)/src/dbstat.c \
- $(TOP)/src/expr.c \
- $(TOP)/src/func.c \
- $(TOP)/src/insert.c \
- $(TOP)/src/wal.c \
- $(TOP)/src/main.c \
- $(TOP)/src/mem5.c \
- $(TOP)/src/os.c \
- $(TOP)/src/os_unix.c \
- $(TOP)/src/os_win.c \
- $(TOP)/src/pager.c \
- $(TOP)/src/pragma.c \
- $(TOP)/src/prepare.c \
- $(TOP)/src/printf.c \
- $(TOP)/src/random.c \
- $(TOP)/src/pcache.c \
- $(TOP)/src/pcache1.c \
- $(TOP)/src/select.c \
- $(TOP)/src/threads.c \
- $(TOP)/src/tokenize.c \
- $(TOP)/src/utf.c \
- $(TOP)/src/util.c \
- $(TOP)/src/vdbeapi.c \
- $(TOP)/src/vdbeaux.c \
- $(TOP)/src/vdbe.c \
- $(TOP)/src/vdbemem.c \
- $(TOP)/src/where.c \
- $(TOP)/src/wherecode.c \
- $(TOP)/src/whereexpr.c \
- parse.c \
- $(TOP)/ext/fts3/fts3.c \
- $(TOP)/ext/fts3/fts3_aux.c \
- $(TOP)/ext/fts3/fts3_expr.c \
- $(TOP)/ext/fts3/fts3_tokenizer.c \
- $(TOP)/ext/fts3/fts3_write.c \
- $(TOP)/ext/async/sqlite3async.c \
- $(TOP)/ext/misc/stmt.c \
- $(TOP)/ext/session/sqlite3session.c \
- $(TOP)/ext/session/test_session.c
-
-# Header files used by all library source files.
-#
-HDR = \
- $(TOP)/src/btree.h \
- $(TOP)/src/btreeInt.h \
- $(TOP)/src/hash.h \
- $(TOP)/src/hwtime.h \
- keywordhash.h \
- $(TOP)/src/msvc.h \
- $(TOP)/src/mutex.h \
- opcodes.h \
- $(TOP)/src/os.h \
- $(TOP)/src/os_common.h \
- $(TOP)/src/os_setup.h \
- $(TOP)/src/os_win.h \
- $(TOP)/src/pager.h \
- $(TOP)/src/pcache.h \
- parse.h \
- $(TOP)/src/pragma.h \
- sqlite3.h \
- $(TOP)/src/sqlite3ext.h \
- $(TOP)/src/sqliteInt.h \
- $(TOP)/src/sqliteLimit.h \
- $(TOP)/src/vdbe.h \
- $(TOP)/src/vdbeInt.h \
- $(TOP)/src/vxworks.h \
- $(TOP)/src/whereInt.h
-
-# Header files used by extensions
-#
-EXTHDR += \
- $(TOP)/ext/fts1/fts1.h \
- $(TOP)/ext/fts1/fts1_hash.h \
- $(TOP)/ext/fts1/fts1_tokenizer.h
-EXTHDR += \
- $(TOP)/ext/fts2/fts2.h \
- $(TOP)/ext/fts2/fts2_hash.h \
- $(TOP)/ext/fts2/fts2_tokenizer.h
-EXTHDR += \
- $(TOP)/ext/fts3/fts3.h \
- $(TOP)/ext/fts3/fts3Int.h \
- $(TOP)/ext/fts3/fts3_hash.h \
- $(TOP)/ext/fts3/fts3_tokenizer.h
-EXTHDR += \
- $(TOP)/ext/rtree/rtree.h
-EXTHDR += \
- $(TOP)/ext/icu/sqliteicu.h
-EXTHDR += \
- $(TOP)/ext/fts5/fts5Int.h \
- fts5parse.h \
- $(TOP)/ext/fts5/fts5.h
-EXTHDR += \
- $(TOP)/ext/userauth/sqlite3userauth.h
-
-# executables needed for testing
-#
-TESTPROGS = \
- testfixture$(EXE) \
- sqlite3$(EXE) \
- sqlite3_analyzer$(EXE) \
- sqlite3_checker$(EXE) \
- sqldiff$(EXE) \
- dbhash$(EXE) \
- sqltclsh$(EXE)
-
-# Databases containing fuzzer test cases
-#
-FUZZDATA = \
- $(TOP)/test/fuzzdata1.db \
- $(TOP)/test/fuzzdata2.db \
- $(TOP)/test/fuzzdata3.db \
- $(TOP)/test/fuzzdata4.db \
- $(TOP)/test/fuzzdata5.db \
- $(TOP)/test/fuzzdata6.db
-
-# Standard options to testfixture
-#
-TESTOPTS = --verbose=file --output=test-out.txt
-
-# Extra compiler options for various shell tools
-#
-SHELL_OPT += -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
-SHELL_OPT += -DSQLITE_ENABLE_RTREE
-SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
-SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
-SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
-SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
-SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
-SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
-SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
-FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
-FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
-FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
-FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-DBFUZZ_OPT =
-KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
-ST_OPT = -DSQLITE_THREADSAFE=0
-
-# This is the default Makefile target. The objects listed here
-# are what get build when you type just "make" with no arguments.
-#
-all: sqlite3.h libsqlite3.a sqlite3$(EXE)
-
-libsqlite3.a: $(LIBOBJ)
- $(AR) libsqlite3.a $(LIBOBJ)
- $(RANLIB) libsqlite3.a
-
-sqlite3$(EXE): shell.c libsqlite3.a sqlite3.h
- $(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
- shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
-
-sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
- $(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
- $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
-
-dbhash$(EXE): $(TOP)/tool/dbhash.c sqlite3.c sqlite3.h
- $(TCCX) -o dbhash$(EXE) -DSQLITE_THREADSAFE=0 \
- $(TOP)/tool/dbhash.c sqlite3.c $(TLIBS) $(THREADLIB)
-
-scrub$(EXE): $(TOP)/ext/misc/scrub.c sqlite3.o
- $(TCC) -I. -DSCRUB_STANDALONE -o scrub$(EXE) $(TOP)/ext/misc/scrub.c sqlite3.o $(THREADLIB)
-
-srcck1$(EXE): $(TOP)/tool/srcck1.c
- $(BCC) -o srcck1$(EXE) $(TOP)/tool/srcck1.c
-
-sourcetest: srcck1$(EXE) sqlite3.c
- ./srcck1 sqlite3.c
-
-fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
- $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \
- $(TLIBS) $(THREADLIB)
-
-dbfuzz$(EXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
- $(TCCX) -o dbfuzz$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c \
- $(TLIBS) $(THREADLIB)
-
-fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c
- $(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
- $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) $(THREADLIB)
-
-ossshell$(EXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
- $(TCCX) -o ossshell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \
- $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c $(TLIBS) $(THREADLIB)
-
-sessionfuzz$(EXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
- $(TCC) -o sessionfuzz$(EXE) $(TOP)/test/sessionfuzz.c -lz $(TLIBS) $(THREADLIB)
-
-mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
- $(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
- $(TLIBS) $(THREADLIB)
-
-MPTEST1=./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test --repeat 20
-MPTEST2=./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test --repeat 20
-mptest: mptester$(EXE)
- $(MPTEST1) --journalmode DELETE
- $(MPTEST2) --journalmode WAL
- $(MPTEST1) --journalmode WAL
- $(MPTEST2) --journalmode PERSIST
- $(MPTEST1) --journalmode PERSIST
- $(MPTEST2) --journalmode TRUNCATE
- $(MPTEST1) --journalmode TRUNCATE
- $(MPTEST2) --journalmode DELETE
-
-sqlite3.o: sqlite3.c
- $(TCCX) -I. -c sqlite3.c
-
-# This target creates a directory named "tsrc" and fills it with
-# copies of all of the C source code and header files needed to
-# build on the target system. Some of the C source code and header
-# files are automatically generated. This target takes care of
-# all that automatic generation.
-#
-target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl fts5.c
- rm -rf tsrc
- mkdir tsrc
- cp -f $(SRC) tsrc
- rm tsrc/sqlite.h.in tsrc/parse.y
- tclsh $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
- mv vdbe.new tsrc/vdbe.c
- cp fts5.c fts5.h tsrc
- touch target_source
-
-sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl
- tclsh $(TOP)/tool/mksqlite3c.tcl
- cp tsrc/sqlite3ext.h .
- cp $(TOP)/ext/session/sqlite3session.h .
- echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
- cat sqlite3.c >>tclsqlite3.c
- echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
- cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
-
-sqlite3ext.h: target_source
- cp tsrc/sqlite3ext.h .
-
-sqlite3.c-debug: target_source $(TOP)/tool/mksqlite3c.tcl
- tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros
- echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
- cat sqlite3.c >>tclsqlite3.c
- echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
- echo '#line 1 "tclsqlite.c"' >>tclsqlite3.c
- cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
-
-sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl
- tclsh $(TOP)/tool/split-sqlite3c.tcl
-
-fts2amal.c: target_source $(TOP)/ext/fts2/mkfts2amal.tcl
- tclsh $(TOP)/ext/fts2/mkfts2amal.tcl
-
-fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl
- tclsh $(TOP)/ext/fts3/mkfts3amal.tcl
-
-# Rules to build the LEMON compiler generator
-#
-lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
- $(BCC) -o lemon $(TOP)/tool/lemon.c
- cp $(TOP)/tool/lempar.c .
-
-# A tool to generate the source-id
-#
-mksourceid: $(TOP)/tool/mksourceid.c
- $(BCC) -o mksourceid $(TOP)/tool/mksourceid.c
-
-# Rules to build individual *.o files from generated *.c files. This
-# applies to:
-#
-# parse.o
-# opcodes.o
-#
-%.o: %.c $(HDR)
- $(TCCX) -c $<
-
-# Rules to build individual *.o files from files in the src directory.
-#
-%.o: $(TOP)/src/%.c $(HDR)
- $(TCCX) -c $<
-
-tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
- $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c
-
-
-
-# Rules to build opcodes.c and opcodes.h
-#
-opcodes.c: opcodes.h $(TOP)/tool/mkopcodec.tcl
- tclsh $(TOP)/tool/mkopcodec.tcl opcodes.h >opcodes.c
-
-opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl
- cat parse.h $(TOP)/src/vdbe.c | \
- tclsh $(TOP)/tool/mkopcodeh.tcl >opcodes.h
-
-# Rules to build parse.c and parse.h - the outputs of lemon.
-#
-parse.h: parse.c
-
-parse.c: $(TOP)/src/parse.y lemon $(TOP)/tool/addopcodes.tcl
- cp $(TOP)/src/parse.y .
- rm -f parse.h
- ./lemon -s $(OPTS) parse.y
- mv parse.h parse.h.temp
- tclsh $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
-
-sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
- tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
-
-keywordhash.h: $(TOP)/tool/mkkeywordhash.c
- $(BCC) -o mkkeywordhash $(OPTS) $(TOP)/tool/mkkeywordhash.c
- ./mkkeywordhash >keywordhash.h
-
-# Source files that go into making shell.c
-SHELL_SRC = \
- $(TOP)/src/shell.c.in \
- $(TOP)/ext/misc/appendvfs.c \
- $(TOP)/ext/misc/shathree.c \
- $(TOP)/ext/misc/fileio.c \
- $(TOP)/ext/misc/completion.c \
- $(TOP)/ext/misc/sqlar.c \
- $(TOP)/ext/expert/sqlite3expert.c \
- $(TOP)/ext/expert/sqlite3expert.h \
- $(TOP)/ext/misc/zipfile.c \
- $(TOP)/src/test_windirent.c
-
-shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
- tclsh $(TOP)/tool/mkshellc.tcl >shell.c
-
-
-
-# Rules to build the extension objects.
-#
-icu.o: $(TOP)/ext/icu/icu.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/icu/icu.c
-
-fts2.o: $(TOP)/ext/fts2/fts2.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2.c
-
-fts2_hash.o: $(TOP)/ext/fts2/fts2_hash.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_hash.c
-
-fts2_icu.o: $(TOP)/ext/fts2/fts2_icu.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_icu.c
-
-fts2_porter.o: $(TOP)/ext/fts2/fts2_porter.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_porter.c
-
-fts2_tokenizer.o: $(TOP)/ext/fts2/fts2_tokenizer.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer.c
-
-fts2_tokenizer1.o: $(TOP)/ext/fts2/fts2_tokenizer1.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer1.c
-
-fts3.o: $(TOP)/ext/fts3/fts3.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3.c
-
-fts3_aux.o: $(TOP)/ext/fts3/fts3_aux.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_aux.c
-
-fts3_expr.o: $(TOP)/ext/fts3/fts3_expr.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_expr.c
-
-fts3_hash.o: $(TOP)/ext/fts3/fts3_hash.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_hash.c
-
-fts3_icu.o: $(TOP)/ext/fts3/fts3_icu.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_icu.c
-
-fts3_snippet.o: $(TOP)/ext/fts3/fts3_snippet.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_snippet.c
-
-fts3_porter.o: $(TOP)/ext/fts3/fts3_porter.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c
-
-fts3_tokenizer.o: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c
-
-fts3_tokenizer1.o: $(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c
-
-fts3_tokenize_vtab.o: $(TOP)/ext/fts3/fts3_tokenize_vtab.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenize_vtab.c
-
-fts3_unicode.o: $(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c
-
-fts3_unicode2.o: $(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c
-
-fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
-
-fts5.o: fts5.c
- $(TCCX) -DSQLITE_CORE -c fts5.c
-
-json1.o: $(TOP)/ext/misc/json1.c
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
-
-stmt.o: $(TOP)/ext/misc/stmt.c
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
-
-rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
-
-
-
-fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
- cp $(TOP)/ext/fts5/fts5parse.y .
- rm -f fts5parse.h
- ./lemon $(OPTS) fts5parse.y
-
-fts5parse.h: fts5parse.c
-
-fts5.c: $(FTS5_SRC) $(FTS5_HDR)
- tclsh $(TOP)/ext/fts5/tool/mkfts5c.tcl
- cp $(TOP)/ext/fts5/fts5.h .
-
-lsm1.c: $(LSM1_SRC)
- tclsh $(TOP)/ext/lsm1/tool/mklsm1c.tcl
- cp $(TOP)/ext/lsm1/lsm.h .
-
-userauth.o: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
-
-sqlite3session.o: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
-
-sqlite3rbu.o: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
- $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rbu/sqlite3rbu.c
-
-# Rules for building test programs and for running tests
-#
-tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a
- $(TCCX) $(TCL_FLAGS) -DTCLSH -o tclsqlite3 \
- $(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)
-
-sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/sqlite3_analyzer.c.in $(TOP)/tool/mkccode.tcl
- tclsh $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
-
-sqlite3_analyzer$(EXE): sqlite3_analyzer.c
- $(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB)
-
-sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl
- tclsh $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in >sqltclsh.c
-
-sqltclsh$(EXE): sqltclsh.c
- $(TCCX) $(TCL_FLAGS) sqltclsh.c -o $@ $(LIBTCL) $(THREADLIB)
-
-sqlite3_expert$(EXE): $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c
- $(TCCX) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c -o sqlite3_expert$(EXE) $(THREADLIB)
-
-CHECKER_DEPS =\
- $(TOP)/tool/mkccode.tcl \
- sqlite3.c \
- $(TOP)/src/tclsqlite.c \
- $(TOP)/ext/repair/sqlite3_checker.tcl \
- $(TOP)/ext/repair/checkindex.c \
- $(TOP)/ext/repair/checkfreelist.c \
- $(TOP)/ext/misc/btreeinfo.c \
- $(TOP)/ext/repair/sqlite3_checker.c.in
-
-sqlite3_checker.c: $(CHECKER_DEPS)
- tclsh $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
-
-sqlite3_checker$(TEXE): sqlite3_checker.c
- $(TCCX) $(TCL_FLAGS) sqlite3_checker.c -o $@ $(LIBTCL) $(THREADLIB)
-
-dbdump$(EXE): $(TOP)/ext/misc/dbdump.c sqlite3.o
- $(TCCX) -DDBDUMP_STANDALONE -o dbdump$(EXE) \
- $(TOP)/ext/misc/dbdump.c sqlite3.o $(THREADLIB)
-
-# Rules to build the 'testfixture' application.
-#
-TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
-TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
-TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
-TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
-TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
-TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
-TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
-
-testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
- $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
- $(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \
- -o testfixture$(EXE) $(LIBTCL) libsqlite3.a $(THREADLIB)
-
-amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c \
- $(TOP)/ext/session/test_session.c
- $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
- $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \
- $(TOP)/ext/session/test_session.c \
- -o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
-
-fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
- $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
- -DSQLITE_ENABLE_FTS3=1 \
- $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \
- -o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
-
-fulltest: $(TESTPROGS) fuzztest
- ./testfixture$(EXE) $(TOP)/test/all.test $(TESTOPTS)
-
-soaktest: $(TESTPROGS)
- ./testfixture$(EXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)
-
-fulltestonly: $(TESTPROGS) fuzztest
- ./testfixture$(EXE) $(TOP)/test/full.test $(TESTOPTS)
-
-queryplantest: testfixture$(EXE) sqlite3$(EXE)
- ./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner $(TESTOPTS)
-
-fuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
- ./fuzzcheck$(EXE) $(FUZZDATA)
- ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
-
-fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
- ./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA)
- ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
-
-valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
- valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
- valgrind ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
-
-# The veryquick.test TCL tests.
-#
-tcltest: ./testfixture$(EXE)
- ./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS)
-
-# A very quick test using only testfixture and omitting all the slower
-# tests. Designed to run in under 3 minutes on a workstation.
-#
-quicktest: ./testfixture$(EXE)
- ./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)
-
-# The default test case. Runs most of the faster standard TCL tests,
-# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
-test: fastfuzztest sourcetest $(TESTPROGS) tcltest
-
-# Run a test using valgrind. This can take a really long time
-# because valgrind is so much slower than a native machine.
-#
-valgrindtest: $(TESTPROGS) valgrindfuzz
- OMIT_MISUSE=1 valgrind -v \
- ./testfixture$(EXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)
-
-# A very fast test that checks basic sanity. The name comes from
-# the 60s-era electronics testing: "Turn it on and see if smoke
-# comes out."
-#
-smoketest: $(TESTPROGS) fuzzcheck$(EXE)
- ./testfixture$(EXE) $(TOP)/test/main.test $(TESTOPTS)
-
-# The next two rules are used to support the "threadtest" target. Building
-# threadtest runs a few thread-safety tests that are implemented in C. This
-# target is invoked by the releasetest.tcl script.
-#
-THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
- $(TOP)/test/tt3_checkpoint.c \
- $(TOP)/test/tt3_index.c \
- $(TOP)/test/tt3_vacuum.c \
- $(TOP)/test/tt3_stress.c \
- $(TOP)/test/tt3_lookaside1.c
-
-threadtest3$(EXE): sqlite3.o $(THREADTEST3_SRC) $(TOP)/src/test_multiplex.c
- $(TCCX) $(TOP)/test/threadtest3.c $(TOP)/src/test_multiplex.c sqlite3.o -o $@ $(THREADLIB)
-
-threadtest: threadtest3$(EXE)
- ./threadtest3$(EXE)
-
-TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO)
-$(TEST_EXTENSION): $(TOP)/src/test_loadext.c
- $(MKSHLIB) $(TOP)/src/test_loadext.c -o $(TEST_EXTENSION)
-
-extensiontest: testfixture$(EXE) $(TEST_EXTENSION)
- ./testfixture$(EXE) $(TOP)/test/loadext.test
-
-showdb$(EXE): $(TOP)/tool/showdb.c sqlite3.o
- $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showdb$(EXE) \
- $(TOP)/tool/showdb.c sqlite3.o $(THREADLIB)
-
-showstat4$(EXE): $(TOP)/tool/showstat4.c sqlite3.o
- $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showstat4$(EXE) \
- $(TOP)/tool/showstat4.c sqlite3.o $(THREADLIB)
-
-showjournal$(EXE): $(TOP)/tool/showjournal.c sqlite3.o
- $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showjournal$(EXE) \
- $(TOP)/tool/showjournal.c sqlite3.o $(THREADLIB)
-
-showwal$(EXE): $(TOP)/tool/showwal.c sqlite3.o
- $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showwal$(EXE) \
- $(TOP)/tool/showwal.c sqlite3.o $(THREADLIB)
-
-showshm$(EXE): $(TOP)/tool/showshm.c
- $(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c
-
-changeset$(EXE): $(TOP)/ext/session/changeset.c sqlite3.o
- $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \
- $(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB)
-
-fts3view$(EXE): $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o
- $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o fts3view$(EXE) \
- $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(THREADLIB)
-
-rollback-test$(EXE): $(TOP)/tool/rollback-test.c sqlite3.o
- $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o rollback-test$(EXE) \
- $(TOP)/tool/rollback-test.c sqlite3.o $(THREADLIB)
-
-LogEst$(EXE): $(TOP)/tool/logest.c sqlite3.h
- $(TCC) -o LogEst$(EXE) $(TOP)/tool/logest.c
-
-wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c
- $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \
- $(TOP)/test/wordcount.c sqlite3.c
-
-speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.c
- $(TCCX) -I. $(ST_OPT) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.c $(THREADLIB)
-
-kvtest$(EXE): $(TOP)/test/kvtest.c sqlite3.c
- $(TCCX) -I. $(KV_OPT) -o kvtest$(EXE) $(TOP)/test/kvtest.c sqlite3.c $(THREADLIB)
-
-rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o
- $(TCC) -I. -o rbu$(EXE) $(TOP)/ext/rbu/rbu.c sqlite3.o \
- $(THREADLIB)
-
-loadfts: $(TOP)/tool/loadfts.c libsqlite3.a
- $(TCC) $(TOP)/tool/loadfts.c libsqlite3.a -o loadfts $(THREADLIB)
-
-# This target will fail if the SQLite amalgamation contains any exported
-# symbols that do not begin with "sqlite3_". It is run as part of the
-# releasetest.tcl script.
-#
-checksymbols: sqlite3.o
- nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0
-
-# Build the amalgamation-autoconf package. The amalamgation-tarball target builds
-# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz.
-# The snapshot-tarball target builds a tarball named by the SHA1 hash
-#
-amalgamation-tarball: sqlite3.c
- TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal
-
-snapshot-tarball: sqlite3.c
- TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot
-
-
-# Standard install and cleanup targets
-#
-install: sqlite3 libsqlite3.a sqlite3.h
- mv sqlite3 /usr/bin
- mv libsqlite3.a /usr/lib
- mv sqlite3.h /usr/include
-
-clean:
- rm -f *.o sqlite3 sqlite3.exe libsqlite3.a sqlite3.h opcodes.*
- rm -f lemon lemon.exe lempar.c parse.* sqlite*.tar.gz
- rm -f mkkeywordhash mkkeywordhash.exe keywordhash.h
- rm -f $(PUBLISH)
- rm -f *.da *.bb *.bbg gmon.out
- rm -rf tsrc target_source
- rm -f testloadext.dll libtestloadext.so
- rm -f amalgamation-testfixture amalgamation-testfixture.exe
- rm -f fts3-testfixture fts3-testfixture.exe
- rm -f testfixture testfixture.exe
- rm -f threadtest3 threadtest3.exe
- rm -f LogEst LogEst.exe
- rm -f fts3view fts3view.exe
- rm -f rollback-test rollback-test.exe
- rm -f showdb showdb.exe
- rm -f showjournal showjournal.exe
- rm -f showstat4 showstat4.exe
- rm -f showwal showwal.exe
- rm -f changeset changeset.exe
- rm -f speedtest1 speedtest1.exe
- rm -f wordcount wordcount.exe
- rm -f rbu rbu.exe
- rm -f srcck1 srcck1.exe
- rm -f sqlite3.c sqlite3-*.c fts?amal.c tclsqlite3.c
- rm -f sqlite3rc.h
- rm -f shell.c sqlite3ext.h
- rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
- rm -f sqlite3_expert sqlite3_expert.exe
- rm -f sqlite-*-output.vsix
- rm -f mptester mptester.exe
- rm -f fuzzershell fuzzershell.exe
- rm -f fuzzcheck fuzzcheck.exe
- rm -f sessionfuzz
- rm -f sqldiff sqldiff.exe
- rm -f fts5.* fts5parse.*
- rm -f lsm.h lsm1.c
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/manifest b/chromium/third_party/sqlite/sqlite-src-3240000/manifest
deleted file mode 100644
index b1ee444d205..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/manifest
+++ /dev/null
@@ -1,1740 +0,0 @@
-C Version\s3.24.0
-D 2018-06-04T19:24:41.225
-F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
-F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
-F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
-F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
-F Makefile.msc 681fb88cccf1fd58c0b9648f6a09b75332206ef72ca76012ad11699c320cec5f
-F README.md 7764d56778d567913ef11c82da9ab94aefa0826f7c243351e4e2d7adaef6f373
-F VERSION b7c9d1d11cb70ef8e90cfcf3c944aa58a9f801cc2ad487eebb0a110c16dfc2df
-F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
-F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
-F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
-F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
-F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
-F autoconf/Makefile.am 465fb475ee5a4b8a63d26c889cb36a4edbff0325b6859eb29a13cdf5c91b005c
-F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.msc 6a46d0659d6e4a25346102bcba40a7fb4b0b8b2dc4faabdf0187488c6dd580d6
-F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
-F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
-F autoconf/configure.ac 5f6cf281ae675685335ce7f43f8c2d59d3ac8ba4174a57b8e83097c5e10dcf4e
-F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
-F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
-F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
-F autoconf/tea/configure.ac 8aa16e3f0a5ca7959d4af198f46934ec187d395f
-F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
-F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
-F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
-F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00
-F autoconf/tea/tclconfig/tcl.m4 66ddf0a5d5e4b1d29bff472c0985fd7fa89d0fb5
-F autoconf/tea/win/makefile.vc f89d0184d0eee5f7e356ea407964dcd139939928
-F autoconf/tea/win/nmakehlp.c 247538ad8e8c508f33c03ec1fbd67d3a07ef6291
-F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
-F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
-F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
-F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
-F configure 80e2dcad8ab88aacc58b55eb0e395f79184b45fcfaa3f36fc20d2e71cfa0a7e4 x
-F configure.ac d4529ebb26ae046269334f1dac65f2b1d6927c2efe22b2ec24dce24dfe4f83dd
-F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
-F doc/lemon.html ac63db056bce24b7368e29319cd1a7eb5f1798cc85922d96a80b6c3a4ff9f51b
-F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
-F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
-F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
-F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
-F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
-F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
-F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
-F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
-F ext/expert/expert1.test baa05800dc1c569faa7ce6232cead0fcedc07fea038b3a2489eaaf710831d546
-F ext/expert/sqlite3expert.c 89b7b59be610b929958db02416539a46ac088fd84f81623c4190aff62e92c3c4
-F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
-F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
-F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
-F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
-F ext/fts1/ft_hash.h 06df7bba40dadd19597aa400a875dbc2fed705ea
-F ext/fts1/fts1.c a39f7d21c2994d27c959ef9c3505c81542c81432
-F ext/fts1/fts1.h 6060b8f62c1d925ea8356cb1a6598073eb9159a6
-F ext/fts1/fts1_hash.c 3196cee866edbebb1c0521e21672e6d599965114
-F ext/fts1/fts1_hash.h e7f0d761353996a8175eda351104acfde23afcb0
-F ext/fts1/fts1_porter.c b1c7304b8988ba3f764a147cdd32043b4913ea7b
-F ext/fts1/fts1_tokenizer.h fdea722c38a9f82ed921642981234f666e47919c
-F ext/fts1/fts1_tokenizer1.c fd00d1fe4dc30dfc5c64cba695ce34f4af20d2fa
-F ext/fts1/fulltext.c 37698e1909584f6d8ea67d1485e3ad39dbf42d19
-F ext/fts1/fulltext.h 08525a47852d1d62a0be81d3fc3fe2d23b094efd
-F ext/fts1/simple_tokenizer.c bbfa4e3b2a26ef17d4edc6d98cd4a3f5396d998a
-F ext/fts1/tokenizer.h 0c53421b832366d20d720d21ea3e1f6e66a36ef9
-F ext/fts2/README.tokenizers 21e3684ea5a095b55d70f6878b4ce6af5932dfb7
-F ext/fts2/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts2/fts2.c 72c816a9ae448049fbbe8f18a85698765fc7956c
-F ext/fts2/fts2.h da5f76c65163301d1068a971fd32f4119e3c95fa
-F ext/fts2/fts2_hash.c 011a1d32de45bb1b519a1fd0048e857d6a843558
-F ext/fts2/fts2_hash.h 1824b99dfd8d0225facbdb26a2c87289b2e7dcf8
-F ext/fts2/fts2_icu.c 51c5cd3c04954badd329fa738c95fcdb717b5188
-F ext/fts2/fts2_porter.c 2cd4a507bf3c3085fe66f59b0f2a325f65aaacf5
-F ext/fts2/fts2_tokenizer.c b529493d55e55497213c37e1f31680a77746be26
-F ext/fts2/fts2_tokenizer.h 27a1a99ca2d615cf7e142839b8d79e8751b4529e
-F ext/fts2/fts2_tokenizer1.c 07e223eecb483d448313b5f1553a4f299a7fb7a1
-F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
-F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
-F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
-F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
-F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c b577921c7e56ea27893da06691f15721801375ebd411a0e24ec5f6fec3c572c3
-F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5
-F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
-F ext/fts3/fts3_expr.c 3b1dbceddd8622599f3cc2626897667fe40487aaa1676707d6c37ec5a8422fc1
-F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
-F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
-F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
-F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
-F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
-F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
-F ext/fts3/fts3_test.c 79f2a7fbb3f672fa032e5a432ca274ea3ee93c34
-F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
-F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7
-F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
-F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
-F ext/fts3/fts3_unicode.c 525a3bd9a7564603c5c061b7de55403a565307758a94600e8a2f6b00d1c40d9d
-F ext/fts3/fts3_unicode2.c cc04fc672bfd42b1e650398cb0bf71f64f9aae032cfe75bbcfe75b9cf966029c
-F ext/fts3/fts3_write.c b583dede85eb0c3c3026f8d7ccb781ea4e845ae583754fecb2ca425b5907d87d
-F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
-F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
-F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
-F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
-F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
-F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
-F ext/fts3/unicode/mkunicode.tcl ab0543a3b2399092ea2dd75df1bef333405b0d7f6b8c4951a0fbb60e780cb69f
-F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
-F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
-F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7
-F ext/fts5/fts5Int.h eda28e3a0a5d87c412e8355fe35da875b04cb389908c8eb0d867ad662adbc491
-F ext/fts5/fts5_aux.c ca666a3bbe07c5a3bbe9fffaea19c935a1efaf337333e28bad7bdd1971ffd093
-F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff
-F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
-F ext/fts5/fts5_expr.c c23a2e4c14c401a147c4a730460e5b37057627bf4be95515ee281cd87f4d277c
-F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
-F ext/fts5/fts5_index.c 22b71d0e9e4b3ddd123a39ae27174e0012da2806f91b64087a68584f13f189de
-F ext/fts5/fts5_main.c da46761a7e9b582083fcb9f5a3ee50086205fb91f4e68d984a9946e64218e297
-F ext/fts5/fts5_storage.c 4bec8a1b3905978b22a67bca5f4a3cfdb94af234cf51efb36f4f2d733d278634
-F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
-F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
-F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086abacd66c2a9b26
-F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
-F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf
-F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
-F ext/fts5/fts5_vocab.c 1cd79854cb21543e66507b25b0578bc1b20aa6a1349b7feceb8e8fed0e7a77a6
-F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
-F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
-F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
-F ext/fts5/test/fts5aa.test 87f4b50e755b52c6192c76ceccf4247d462bb44b52fa17358f273d8ce5d975f0
-F ext/fts5/test/fts5ab.test 9205c839332c908aaad2b01ab8670ece8b161e8f2ec8a9fabf18ca9385880bb7
-F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
-F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
-F ext/fts5/test/fts5ae.test 1142d16d9cc193894dc13cc8f9c7a8a21411ac61b5567a878514df6f9f0d7bb7
-F ext/fts5/test/fts5af.test 724247405b13f8f06cc6ce464dc4f152dc5dd4e86b12c2099685d8f19747bf7b
-F ext/fts5/test/fts5ag.test 7816f25a0707578f08145ab539fc0ca025f8951e788b28a6a18a06b2099469dd
-F ext/fts5/test/fts5ah.test 27b5a33bfd0363ca8a4dc659e6e2a5df3dea1c3c5b04bc51ca6aeb1277bd9b21
-F ext/fts5/test/fts5ai.test d837c42249c0d8ad1a2912270e22cf2f303790a611f85c0be3a58e42a3696e3d
-F ext/fts5/test/fts5aj.test 745020852d85f5dd49d11cb7ad11d3cc6dafc4fe6d6d24bc0875ac8f43ee4149
-F ext/fts5/test/fts5ak.test 0d41cbf04e70249c84670e1782aa8972e4f67d91c9bc6205d0ba7c34e159481b
-F ext/fts5/test/fts5al.test 00c4c1c6a1366b73aa48ce2068c634520867c3cf7f5d1676ebbb775ee1f35734
-F ext/fts5/test/fts5alter.test 5565f7e4605512b69171ac18ca84398603f9f6456dbe377beeca97e83cc242cd
-F ext/fts5/test/fts5auto.test 78989e6527ce69c9eddbef7392fea5c10b0010cd2b2ae68eec7bc869c471e691
-F ext/fts5/test/fts5aux.test 8e7f9c96f8570f48402f2fd7b74e1ccfadd319fa56ef677321880000f9739846
-F ext/fts5/test/fts5auxdata.test eacc97ff04892f1a5f3d4df5a73f8bcbc3955ea1d12c9f24137eb1fc079e7611
-F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a664fe1e7a8f5fd3
-F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
-F ext/fts5/test/fts5colset.test a30473451321bbf0b6218af62e96b4ae5fa99931cfdb210b5ecc804623b30f75
-F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f348ca8c1630f9edbf5482
-F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
-F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d
-F ext/fts5/test/fts5connect.test b12a2a8b02af3c31c18abbc33aa8100d364de19a888a44457484d21dbccb18a7
-F ext/fts5/test/fts5content.test 688d5ac7af194ebc67495daea76a69e3cd5480122c2320e72d41241b423b4116
-F ext/fts5/test/fts5corrupt.test 8957f0f7e57e0f8a102c5b6e1a7326d6a1966b28e1d99c5883822af1e6038e9e
-F ext/fts5/test/fts5corrupt2.test 6deaf9f9606b3c957529db9881622bb3a7829b19bb3cdf8f276f074d684ede56
-F ext/fts5/test/fts5corrupt3.test 1b489101212206da1f27d0d03b9667e54571cba72db7e70b195fdf39f867b48c
-F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775
-F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
-F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
-F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e
-F ext/fts5/test/fts5doclist.test e39a6001495f1dc68e20323586ac965787986c2bf6f515b9b0285627b089d9e6
-F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
-F ext/fts5/test/fts5eb.test e5fe57b4141db456f06094afca45541fb0c13b30032eccae05100b4dbec11955
-F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
-F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421c20a0756251fe344
-F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522
-F ext/fts5/test/fts5fault4.test 1c1db5fcfe59401e7833146100f1d8de284a0a686fac31ddac9fb56c459f725b
-F ext/fts5/test/fts5fault5.test a336e4e11847de24c9497f80cce18e00bb3fab7fb11f97d04eb9af898900a762
-F ext/fts5/test/fts5fault6.test a0fc0a8f99e4b16500c31dfc7e38e1defe0f1693ac47650517ac7b723b1956f8
-F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd164090be139e9e97ed4c
-F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2
-F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119
-F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
-F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e
-F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
-F ext/fts5/test/fts5first.test 707a591b1b7d893fcfcb2366cbfe56aefab5d9c7cfa58bef35eba73a1dbf3b29
-F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2
-F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
-F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b
-F ext/fts5/test/fts5integrity.test 6c4aad7f7380ec459a0c27ebbc0cb314fa67f3a3dad0cc820f612d33aa887166
-F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
-F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
-F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8975d15c279374e82e35
-F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
-F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
-F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
-F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
-F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
-F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
-F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
-F ext/fts5/test/fts5plan.test 00dc4c974938b509db7cb3680407f068ee6e9cc824f492f68cb741a7b679fe41
-F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
-F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
-F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
-F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728
-F ext/fts5/test/fts5rank.test 6e149da77a269923a8439aaa52366e49b85be4721902662da39a5ded16ed85d9
-F ext/fts5/test/fts5rebuild.test 6d09fd54b1170a1e54fe17b808bbf17fba3154956cc2f065dd94bf1e3d254f63
-F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415
-F ext/fts5/test/fts5rowid.test 365997f5aebd619df3ae46c2a4bfc8edba361899bc4e52cebfba0dbcbf720522
-F ext/fts5/test/fts5simple.test 313ad28ef38ebe25f0a1673dd18f2fac446e25feb15bbb0c223a65ea00594f72
-F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
-F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
-F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb
-F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947ec60b6fadbc4b3fb17a
-F ext/fts5/test/fts5tok1.test ce6551e41ff56f30b69963577324624733bed0d1753589f06120d664d9cd45c9
-F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
-F ext/fts5/test/fts5tokenizer.test 6aeb5e8061ffc0ff9a5299f27beaee3b2b4b8b336d4f107262bca338bea8f8e9
-F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
-F ext/fts5/test/fts5unicode2.test 9b3df486de05fb4bde4aa7ee8de2e6dae1df6eb90e3f2e242c9383b95d314e3e
-F ext/fts5/test/fts5unicode3.test c3caecbe8264629ffe653b43ca5790b9793eba4422f92203e5247558e5a534e7
-F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d
-F ext/fts5/test/fts5update.test 0737876e20e97a6a6abf45de19fc99315727bcee6a83fadcada1cc080b9aa8f0
-F ext/fts5/test/fts5version.test 99b81372630fbf359107c96580fa761e41cdfb1dafc9966e148629ca72efee71
-F ext/fts5/test/fts5vocab.test 2ba98bcef0fcab3e5fead8eaabd6c0efb7e57bfe707a5cfcc18572ca9b277360
-F ext/fts5/test/fts5vocab2.test 2beeec974a305a1d79b91426622cc922c87065874437d22b400de7438979959e
-F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
-F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59
-F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
-F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
-F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
-F ext/icu/README.txt a295e91db742b153e8dce8f7efd31d28ad1eea4df31ef4daa3eedc85be2f5138
-F ext/icu/icu.c c2c7592574c08cd1270d909b8fb8797f6ea1f49e931e71dbcc25506b9b224580
-F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
-F ext/lsm1/Makefile 98b0a24b45e248283d6bea4b6cb3e58d7b394edd8e96a0ac28c5fa5104813bad
-F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
-F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86
-F ext/lsm1/lsm-test/lsmtest.h cf58528ffe0cfe535e91b44584e2ec5fb1caacdabecef0d8dcf83bf83168bf28
-F ext/lsm1/lsm-test/lsmtest1.c 33158978327f800e82b6a47c09b86ace809f56a9ff10b0162273ec1186cc3153
-F ext/lsm1/lsm-test/lsmtest2.c 188b09aec776516aeedcfd13b9c6faf85ba16b3671a0897a2c740ee00a5dc4f8
-F ext/lsm1/lsm-test/lsmtest3.c 9ab87528a36dbf4a61d7c8ad954f5ee368c0878c127b84b942b2e2abe522de26
-F ext/lsm1/lsm-test/lsmtest4.c d258d6a245db5d8eaede096e2368d23f859c5e92c80ab9122463f708514fe10c
-F ext/lsm1/lsm-test/lsmtest5.c 8d5242a0f870d65eeada191c8945781fed9cb8ece3886573790ebd373b62dac5
-F ext/lsm1/lsm-test/lsmtest6.c 869cb4a172cd07d1a75b3aeaecd61d0a477787b3b8668bad0d3ff0f43b642b7c
-F ext/lsm1/lsm-test/lsmtest7.c 7a917455a0f956a8ed3f44f5c9387ec0ea6627714874464cc3fa5c5a9cabb2f2
-F ext/lsm1/lsm-test/lsmtest8.c 589b68c44531a0f04d5e879bb1e211be5f7100f48eed7e8631e07ed5cbd68f94
-F ext/lsm1/lsm-test/lsmtest9.c dd1a0ebf41134933a744d1e00e60429a2a21fc50d587ae7dd6bdb6e96d805bdc
-F ext/lsm1/lsm-test/lsmtest_bt.c d70d9a9be5eef9360af1251dd083948d74fd30137a08f61bef995f7ac04e037f
-F ext/lsm1/lsm-test/lsmtest_datasource.c 5d770be191d0ca51315926723009b2c25c0b4b8136840494ef710ac324aa916c
-F ext/lsm1/lsm-test/lsmtest_func.c 159aa401bc8032bfa3d8cf2977bd687abebab880255895a5eb45770d626fa38d
-F ext/lsm1/lsm-test/lsmtest_io.c cf11b27b129c6bd5818fa1d440176502dc27229f0db892b4479118d61993ea20
-F ext/lsm1/lsm-test/lsmtest_main.c a9bc647738c0dcaebf205d6d194b3ce4a6ef3925801cd2d919f0a4ea33a15aeb
-F ext/lsm1/lsm-test/lsmtest_mem.c 4e63c764345ab1df59d4f13a77980c6f3643798210b10d6cdbd785b4b888fda5
-F ext/lsm1/lsm-test/lsmtest_tdb.c 618a8619183fda4f5540fcde15f9068293c5e3180e1a246e34409b0c148758b3
-F ext/lsm1/lsm-test/lsmtest_tdb.h 8733eee249b12956a9df8322994b43d19bd8c02ad2e8b0bb5164db4d6ccc1735
-F ext/lsm1/lsm-test/lsmtest_tdb2.cc 99ea7f2dd9c7536c8fb9bdd329e4cfeb76899f3ddf6f48bdd3926e016922b715
-F ext/lsm1/lsm-test/lsmtest_tdb3.c b4e46b1d2fec553fe4efb44e341b43abd20556fde610db0cfffdc2300b72defe
-F ext/lsm1/lsm-test/lsmtest_tdb4.c 47e8bb5eba266472d690fb8264f1855ebdba0ae5a0e541e35fcda61ebf1d277f
-F ext/lsm1/lsm-test/lsmtest_util.c 241622db5a332a09c8e6e7606b617d288a37b557f7d3bce0bb97809f67cc2806
-F ext/lsm1/lsm-test/lsmtest_win32.c 0e0a224674c4d3170631c41b026b56c7e1672b151f5261e1b4cc19068641da2d
-F ext/lsm1/lsm.h 0f6f64ff071471cb87bf98beb8386566f30ea001
-F ext/lsm1/lsmInt.h 5983690e05e83653cc01ba9d8fbf8455e534ddf8349ed9adedbf46a7549760b0
-F ext/lsm1/lsm_ckpt.c 0eabfaf812ddb4ea43add38f05e430694cd054eb622c3e35af4c43118a2d5321
-F ext/lsm1/lsm_file.c 3c51841d5b3e7da162693cbac9a9f47eeedf6bcbbe2969a4d25e30c428c9fe36
-F ext/lsm1/lsm_log.c a8bf334532109bba05b09a504ee45fc393828b0d034ca61ab45e3940709d9a7c
-F ext/lsm1/lsm_main.c b5703f8042e71d3a2d65e671f6832e077e79e89e9975818f67f969922618db63
-F ext/lsm1/lsm_mem.c 4c51ea9fa285ee6e35301b33491642d071740a0a
-F ext/lsm1/lsm_mutex.c 378edf0a2b142b4f7640ee982df06d50b98788ea
-F ext/lsm1/lsm_shared.c 76adfc1ed9ffebaf92746dde4b370ccc48143ca8b05b563816eadd2aadf1c525
-F ext/lsm1/lsm_sorted.c df7b393d9e4b85e6ad07181c6434d58a69a9145ee925d89c3ee1d2a210adaf9a
-F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678bca82
-F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb
-F ext/lsm1/lsm_unix.c 57361bcf5b1a1a028f5d66571ee490e9064d2cfb145a2cc9e5ddade467bb551b
-F ext/lsm1/lsm_varint.c 43f954af668a66c7928b81597c14d6ad4be9fedbc276bbd80f52fa28a02fdb62
-F ext/lsm1/lsm_vtab.c 529255dc704289001b225d97e57e0cfa14b29c3f281c7349cfa8fdb655de79ae
-F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c
-F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82
-F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422
-F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0
-F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
-F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
-F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
-F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7
-F ext/misc/btreeinfo.c 78c8c57d325185ccc04b7679e5b020e34a4d9c87453e6b7ac943d0a26cee3256
-F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005
-F ext/misc/closure.c fe928228e8dfb2f00227311c203ccba9c2e5561f4f6de6da87e5b4a30cd8af15
-F ext/misc/completion.c e75b8886a2531f9a7ec02dab5f179bb37e6bd46b5da7665a6cbf2dfbe2daa483
-F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
-F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657
-F ext/misc/dbdump.c 69ef1be5b210538f77dfcc6fcb55b4b5f5e98b1e0bcfd67d818711e10761db4d
-F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
-F ext/misc/fileio.c 48c7751c78fc4cdd29d8c862fd2f3f98bbfefa2a3cf1ca1496df4bf02eb8cded
-F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
-F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
-F ext/misc/json1.c 02f5f0d9c131df79f4ee168d2b426f0f0d273b7771fc0bb5293c4e7692d9a2ee
-F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
-F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
-F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
-F ext/misc/normalize.c 19262ef3ef29d4de2f281b423326865c8916c63d0cb09f1dc98d24d5c1e8ba64
-F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
-F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
-F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
-F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
-F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
-F ext/misc/series.c c7197db304f7009b08d6459a9de02e7f51ad0e1a3fdacbc1ebf5252a9a346959
-F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
-F ext/misc/shathree.c 9e960ba50483214c6a7a4b1517f8d8cef799e9db381195178c3fd3ad207e10c0
-F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
-F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5
-F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74
-F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
-F ext/misc/templatevtab.c 8251b31011dd00fc38e739c78c234c930be42b3b274bbe0493b79cd40db02a9e
-F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
-F ext/misc/unionvtab.c 0b3173f69b8899da640a13a345dc5ef1400199405f738abe6145b2454195b8ff
-F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
-F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
-F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
-F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
-F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
-F ext/misc/zipfile.c c4de8f0ad446ce4a49aae11ff7b771cd7af60d7136c0bcfb53da1475b9075e79
-F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
-F ext/rbu/rbu.c 4ae41f01d78dfae2204a63bcf39d5eb3548d039b094c29eec9a8d6683a66a5d3
-F ext/rbu/rbu1.test 41123c64e8c88bd14eb7d3f8562f37fa87aaeb154b1eade2881de21d3504be55
-F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
-F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702
-F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16
-F ext/rbu/rbu13.test 462ff799c4afedc3ef8a47ff818c0ffbf14ae4f2
-F ext/rbu/rbu14.test 01f5dcba904aecadbaea69d4ccdc2ea43dd30560
-F ext/rbu/rbu3.test 8bd4c6b87367c358981b6a47dc3d654fa60bff90
-F ext/rbu/rbu5.test cf1fa84d6107efd73e292a7be8e1fb31953ca45c
-F ext/rbu/rbu6.test 32e8ed60631b6facdb6366bd2b5f5f25245e7edb
-F ext/rbu/rbu7.test fd025d5ba440fcfe151fbb0e3835e1e7fe964fa1
-F ext/rbu/rbu8.test 3bbf2c35d71a843c463efe93946f14ad10c3ede0
-F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af
-F ext/rbu/rbuA.test 4e58e46e60d4064248614c43303d71f1b18cc804dd834ce6a913b3861828b28d
-F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2
-F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831
-F ext/rbu/rbu_common.tcl acfb7fbbaf8d46a9f6f6a5ec795616c84d705e1565d918afe43f0ff53ea0efa5
-F ext/rbu/rbucollate.test 86d6fc9b8f59a27b7b5a6e20b5e29816d338a0dbdea8c54bfcc549a0d437f3ea
-F ext/rbu/rbucrash.test 61470d977a06a0abc2ec35b05d82a1d7d87d10f4ffabad14c1c231edc942ad66
-F ext/rbu/rbucrash2.test b2ecbdd7bb72c88bd217c65bd00dafa07f7f2d4d
-F ext/rbu/rbudiff.test 3e605cf624d00d04d0fb1316a3acec4fbe3b3ac5
-F ext/rbu/rbudor.test 99b05cc0df613e962c2c8085cfb05686a09cf315
-F ext/rbu/rbufault.test 2654aef20f8ee7de37c9c1997a44f2773dc7bf24887adea39fb19314ef32cb90
-F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
-F ext/rbu/rbufault3.test 0913c1aeaee266d9c36c33179341a5a504aad7d423d1979cfec43c8346a29899
-F ext/rbu/rbufault4.test 34e70701cbec51571ffbd9fbf9d4e0f2ec495ca7
-F ext/rbu/rbufts.test a2bbd202c9321fba15fb4a62a90add7d70e07bd8404e1e598135adbfff8a0508
-F ext/rbu/rbumulti.test 2cf153ab3d5861ff26517dc6cbaec430787a59f1d50e8771fe7a7529a0551cf1
-F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
-F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
-F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
-F ext/rbu/rbusplit.test 69271c790732b28bd465551d80b0a9a3f074e189896ee8490ce56d22078c124d
-F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1
-F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
-F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
-F ext/rbu/sqlite3rbu.c f438fea899d15d13ff3e3133242b9e378c37b5a3d76add8c342c68bdd65c6819
-F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
-F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90
-F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
-F ext/repair/checkfreelist.c 0dbae18c1b552f58d64f8969e4fb1e7f11930c60a8c2a9a8d50b7f15bdfd54bd
-F ext/repair/checkindex.c 7d28c01a2e012ac64257d230fc452b2cafb78311a91a343633d01d95220f66f3
-F ext/repair/sqlite3_checker.c.in 4a5a3af3f450fe503e5a2985e98516dc2a6b9ad247449e284c1cf140fc91720f
-F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
-F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
-F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
-F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
-F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
-F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/rtree.c cb6d4bd43c118354fe5b5213843da058259467ecdbac0c6f71ead0fd89acf4ec
-F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
-F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
-F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
-F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
-F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
-F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
-F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4
-F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
-F ext/rtree/rtree8.test 924926d7c64ac59fcca0809de472d9dd73c612f54daae1cf992bdd7dac90305b
-F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
-F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776
-F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
-F ext/rtree/rtreeC.test 128928549d22b65c381ab1366760d08703cd75e34f6a7a506ece38f9330b7282
-F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
-F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
-F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
-F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e0184939c
-F ext/rtree/rtreeH.test aa08cc4fa8005b4c67446c7110205055b4d6da90e760e6f44b82dfa4cdf8d87a
-F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
-F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
-F ext/rtree/rtreecheck.test 4d29103d1e16fcbf90135d1c637b833688492b063b2971dfb5dc6ba76555cfee
-F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
-F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
-F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
-F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
-F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
-F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc
-F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
-F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
-F ext/session/session4.test 6778997065b44d99c51ff9cece047ff9244a32856b328735ae27ddef68979c40
-F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
-F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26
-F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b
-F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069
-F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
-F ext/session/sessionB.test 886252dcb7e692e62ef7e357456200912e367823
-F ext/session/sessionC.test 97556f5164ac29f2344b24bd7de6a3a35a95c390
-F ext/session/sessionD.test d3617e29aa15c9413aee5286d99587633245d58d2ad28f3f331c822735418a22
-F ext/session/sessionE.test 0a616c4ad8fd2c05f23217ebb6212ef80b7fef30f5f086a6633a081f93e84637
-F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
-F ext/session/sessionG.test 3edde849c4071078d92bd682c836186f6e4e5a3fb6bcf3fc1de1a7caa5e4427d
-F ext/session/sessionH.test 332b60e4c2e0a680105e11936201cabe378216f307e2747803cea56fa7d9ebae
-F ext/session/session_common.tcl ee925e0d233677e45e395fb1f559b84068ce7baa8aa1034441739d3e87ee249c
-F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723
-F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec
-F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
-F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
-F ext/session/sessionfault2.test 555a8504de03d59b369ef20209585da5aeb2671dedabc4584e9ffe6269689185
-F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8
-F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e
-F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
-F ext/session/sqlite3session.c 2d29bbd888599b94b2c8b31ff433675e008273a4d225b336508b18e6187fec1d
-F ext/session/sqlite3session.h c01820d5b6e73e86d88008f4d1c1c7dfb83422963018292b864028a0400ceccf
-F ext/session/test_session.c dba36c6c0153b22501112d3e8882b5c946cf617c955153b6712bd2f8ba1428c0
-F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
-F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
-F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
-F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
-F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
-F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 3f50dfe5cb4257c1aca96e417636ed51bc2561e71d31a21e9ccdf66feb912f43
-F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
-F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
-F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
-F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
-F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
-F mptest/mptest.c aa41ace6dbc5050d76b02548d3521e6bbccae4f0
-F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
-F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
-F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
-F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
-F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
-F src/analyze.c 71fbbeb7b25417592f54d869fe90c28b48e4cecb9926ef9b06d90fb0aec48941
-F src/attach.c 4a3138bd771d5426ae4344d8d5e900440af29fabc5ec2f39f69a45010dfbccd7
-F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8
-F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
-F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
-F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c 44405d03a05496e13b40b3a208bcf941c42c815da90d6ff4b04267a6985e5eb7
-F src/btree.h 448f15b98ea85dcf7e4eb76f731cadb89636c676ad25dfaac6de77cd66556598
-F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
-F src/build.c 5fc41458505331bfb0c175f40b9a13cb335f826bed3ae311aaae000c132d7b16
-F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
-F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
-F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48
-F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
-F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6
-F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
-F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f
-F src/expr.c 16f90ae2af2a100bc430a89184afde54878d82f18267e8d00bc4f33e695a7c57
-F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee
-F src/func.c e2e3c02621a528a472933fd4733a5da635676f1461be73293f6e9f62f18d4eaa
-F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
-F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
-F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
-F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
-F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 76b1dc902e4c3930d9a17a40cd8ee2e94b1fd8cce766672caef164a6d5d4df1d
-F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
-F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
-F src/main.c 0402e234155e0aad75fe6cd204864f492495be8605a50b4b3d4d72895cced3ce
-F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
-F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
-F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
-F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
-F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
-F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memdb.c e94c478a757c4307fd170fe0a7650ef4cf722c59e5a95a8a7896ffedc1679139
-F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
-F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
-F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604
-F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
-F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
-F src/mutex_unix.c aaf9ebc3f89df28483c52208497a99a02cc3650011422fc9d4c57e4392f7fe58
-F src/mutex_w32.c 7670d770c94bbfe8289bec9d7f1394c5a00a57c37f892aab6b6612d085255235
-F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
-F src/os.c 1cb0d1d1b3a4267966dee6e292d2b2cdf88e47c0c59cebff27ecafac052dd165
-F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
-F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
-F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9
-F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354
-F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
-F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
-F src/parse.y 0b81472496809693a139067fea1fe3f14a7be8aa26c8f18bb327034d1252a06a
-F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
-F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
-F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
-F src/pragma.c c0d13c0e82a9197aef5533d63300c5b0c8a216ae1fd14ada64e1f12f398d7e82
-F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
-F src/prepare.c 95a9dba7a5d032039a77775188cb3b6fb17f2fa1a0b7cd915b30b4b823383ffa
-F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
-F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 14602f46800ba182ea6a490e0f304127d29ac1f724bdadcc639e25d3223fcf6e
-F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
-F src/select.c 3291892add3a8f01dc3754e40ef9e30ad22c78e3404a388ae58f0390a1fb29eb
-F src/shell.c.in c29cb307d6275131e6f9874e0fa73f87acf40a22c4a82faba2059a93b4d294d1
-F src/sqlite.h.in 63b07f76731f2b1e55c48fdb9f0508dcc6fbe3971010b8612ffd847c3c56d9a1
-F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
-F src/sqliteInt.h d2bd297dba08f2390a91c31ff775e0964e9663df5b2910a569fe6f830b8b2beb
-F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
-F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
-F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
-F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce
-F src/test1.c 51aa5f3030217ca45eb62e90944838794d4faaae7a8f60e0330ae01f30bc997b
-F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
-F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
-F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
-F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
-F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
-F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
-F src/test8.c 3f7d0cc4e12e06832ba3db4455cb16867ccadafa602eb6ff5fcf097bffce56ed
-F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
-F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
-F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
-F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
-F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
-F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
-F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
-F src/test_config.c 097c6189803886a1fb26ec37d8bc62b90512cb53ab79a1fb6d35196c1ec42ded
-F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
-F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
-F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
-F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
-F src/test_func.c d12d805953bcb3bb19f71d29cdc93383b7b7a3369504d2b7e398a1bd77376294
-F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
-F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
-F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
-F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
-F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
-F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
-F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242
-F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
-F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
-F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
-F src/test_mutex.c 7f4337ba23ee6b1d2ec81c189653608cb069926a
-F src/test_onefile.c 416f87a28d6d673352d33fc4b1c7d39db878e50f
-F src/test_osinst.c 98ef31ff03d55497829ca0f6c74a9f4e1aa48690
-F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
-F src/test_quota.c 6cb9297115b551f433a9ad1741817a9831abed99
-F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
-F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b
-F src/test_schema.c f575932cb6274d12147a77e13ea4b49d52408513
-F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
-F src/test_sqllog.c 11e6ce7575f489155c604ac4b439f2ac1d3d5aef
-F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
-F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
-F src/test_tclsh.c 58052fe48efe8f579834f4648d239569f2efc6285f5019ebdf0040f58d16238d
-F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
-F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858
-F src/test_vfs.c f0186261a24de2671d080bcd8050732f0cb64f6e
-F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
-F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
-F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215
-F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
-F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
-F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97
-F src/treeview.c 2c5c4bc0a443401db5fd621542150452ddf5055d38edd4eef868bc2b6bfb0260
-F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995
-F src/update.c 46dc24c6158446aaab45caee09b6d99327cb479268b83ffeb5b701823da3b67b
-F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88
-F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
-F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
-F src/vacuum.c 37730af7540033135909ecaee3667dddec043293428d8718546d0d64ba4a5025
-F src/vdbe.c 71e5a72d89eabf7f88ef0ad4a429d3c3ee5d10de76af3818c47b275a6b3a9097
-F src/vdbe.h e3f43bcc27ff30b0f25a6104d0cb5657e1c4b5e1b5cd2dd2216d5bcc2156a746
-F src/vdbeInt.h 42d3e65ea0c664f6d9bc9a53de645c0baf8566ff0188409ff3b8d2abc327bc17
-F src/vdbeapi.c 765a0bbe01311626417de6cb743f7f25f9f98435c98a9df4bb0714d11014633d
-F src/vdbeaux.c b00d35805a2b326d1371ab7ce8f3a95c8af35b1431367ffe482fc2c735d69fb1
-F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
-F src/vdbemem.c 803323406d8623a7619ea5d5f74016697eeaed19c02b98ce9c3013e77dbe1c38
-F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
-F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
-F src/vtab.c 10ea07dec111de6fb0a4fc87a7ffa4c65fdc088a19dbfaf7d6f2b128f2e8eb7b
-F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0
-F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
-F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
-F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1
-F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
-F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
-F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
-F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
-F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
-F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
-F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
-F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
-F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
-F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
-F test/alter.test b820ab9dcf85f8e3a65bc8326accb2f0c7be64ef
-F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
-F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
-F test/alter4.test b6d7b86860111864f6cddb54af313f5862dda23b
-F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
-F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
-F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df
-F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8
-F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e
-F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
-F test/analyze6.test 7b2667b879976ac4b90d8df80d5456328684f1f6f6fdef9469d6e53401f2f469
-F test/analyze7.test a37f4d9cb699a8af068ae02df1bb08bf844df8e98a92a8126cbff89e226879d8
-F test/analyze8.test e32a970564271114786703750e6939cf81dea4b8580874e38e9213ee092f6936
-F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54
-F test/analyzeA.test 22a892d67bd2223126335b99774cce56ba91122cfe82446d2927afc43ad667dc
-F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70
-F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
-F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c
-F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
-F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb
-F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49
-F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
-F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
-F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
-F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
-F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
-F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd
-F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
-F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be8281c
-F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
-F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
-F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
-F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
-F test/auth.test 3d6cd8f3978ba55b1202574e6ecd79c6e00914ca44b9bfd6c1fe6fb873fcac88
-F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
-F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
-F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
-F test/autoinc.test 9d202b7dce6571e52b744138eff12610214501acd635abdd72d18736cd06fd22
-F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0
-F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
-F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
-F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
-F test/autoindex5.test 5f0135dc3b266277b8c1904624439097d8e8020dd7197eda13fda23c35c21a05
-F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
-F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
-F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
-F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
-F test/backup.test dd4a5ff756e3df3931dacb1791db0584d4bad989
-F test/backup2.test 1fd1ad8c5b3d2d5b9c0cce4143a4fc610d51ddc6ae16a7a122973d43e6b50bbd
-F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
-F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
-F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
-F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
-F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
-F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
-F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
-F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a
-F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
-F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
-F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
-F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b
-F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
-F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
-F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
-F test/bigmmap.test 31dad31573638bd32de866cdefd11843f75685be4ba6aec1a47918f098f1899b
-F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
-F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
-F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483
-F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
-F test/bitvec.test 75894a880520164d73b1305c1c3f96882615e142
-F test/blob.test e7ac6c7d3a985cc4678c64f325292529a69ae252
-F test/boundary1.tcl 6421b2d920d8b09539503a8673339d32f7609eb1
-F test/boundary1.test 66d7f4706ccdb42d58eafdb081de07b0eb42d77b
-F test/boundary2.tcl e34ef4e930cf1083150d4d2c603e146bd3b76bcb
-F test/boundary2.test 9ae758d7dab7e882c8b6cc4a6a10278385bff8fa
-F test/boundary3.tcl 23361e108a125dca9c4080c2feb884fe54d69243
-F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45
-F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
-F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
-F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
-F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99
-F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
-F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
-F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
-F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
-F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
-F test/capi2.test 34a1a9a96d543a2ec2c209696b11b164444f57253b1f2cba1c2e53fadede6c7b
-F test/capi3.test 36f5c859c91a9bb0075d6ddcfcf2476cad629b09f7bfd135776fb94b06c04706
-F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
-F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098
-F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
-F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
-F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857
-F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
-F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a
-F test/close.test 799ea4599d2f5704b0a30f477d17c2c760d8523fa5d0c8be4a7df2a8cad787d8
-F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0
-F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
-F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846
-F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
-F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5
-F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd
-F test/collate5.test 65d928034d30d2d263a80f6359f7549ee1598ec6
-F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907
-F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868
-F test/collate8.test cd9b3d3f999b8520ffaa7cc1647061fc5bab1334
-F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
-F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
-F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
-F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
-F test/colname.test fb28b3687e03625425bc216edf8b186ce974aa71008e2aa1f426a7dcb75a601d
-F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db
-F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
-F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9
-F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
-F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97
-F test/corrupt2.test b6281ceadd6114d55e89b25e01c617af930dda71567f6a0996a719c385ac142e
-F test/corrupt3.test e676f478fe602915d721472811f6f410b75ddc7e
-F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a
-F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107
-F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
-F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543
-F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
-F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
-F test/corruptA.test 112f4b2ae0b95ebf3ea63718642fb969a93acea557ace3a307234d19c245989b
-F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
-F test/corruptC.test 138ecb02188ed1a719b533d4a139568204039f72f00e07a8d30d920bd83122db
-F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
-F test/corruptE.test 82ccf4f8f543fdbedd4aa42c709cb077f7374c62
-F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
-F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51
-F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
-F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4
-F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
-F test/corruptK.test 91550557849244a9904f4e090052e3f2c1c3f1106840d58b00ffaa3a8c2d3fc0
-F test/cost.test b37db8a10d467a69e71a9f3d40bbb266c2f587742b37c6912f6e3f7185a0e216
-F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
-F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
-F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
-F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
-F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
-F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
-F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219
-F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
-F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
-F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
-F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
-F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
-F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
-F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
-F test/csv01.test 6e1445b3207d574cff22fc41a8e549dfcf2466ee90546ada97d22a90fa89eb58
-F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
-F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
-F test/cursorhint2.test 0078ae1ded4afcf5eb80d06e3a72b6e1c3f1a646aab26eeb583b0a9ec6f0d56e
-F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
-F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
-F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
-F test/dbpage.test dbf50a4d361f9e45a979432c727506065113124478a7d2db12074fa655e65d6c
-F test/dbstatus.test c15fa97f743dac7ce996814c84b56317e138895ee15ce27f15b608aa6924c90a
-F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
-F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
-F test/delete.test 31832b0c45ecb51a54348c68db173be462985901e6ed7f403d6d7a8f70ab4ef0
-F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
-F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
-F test/delete4.test 21d2113217eeaacac2d99defe14fe6611615ae86
-F test/delete_db.test 096d828493c7907f9ea11a7098ea6a0f73edba89406487d5d6cc2228dc4ab8b0
-F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
-F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
-F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
-F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
-F test/distinct.test a1783b960ad8c15a77cd9f207be072898db1026c
-F test/distinct2.test df0bb52b754661ea84ec9ff488d48913c97bd31d83ca17ce0bf1334645e660cf
-F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
-F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
-F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
-F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145
-F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14
-F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
-F test/e_createtable.test e1c4512b9e15fe7bedbbfc0c6daac8a4af65f32dc3c48310b0135b5735857b26
-F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
-F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
-F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
-F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89
-F test/e_fkey.test 9778696ef9fceacebed8d482d02b47287981faaedf6f73db563ea8a7afb546da
-F test/e_fts3.test 8cf40550bb088a6aa187c818c00fabe26ef82900a4cd5c66b427ccafe28bedaa
-F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
-F test/e_reindex.test 2bebf7b393e519198b7c654407221cf171a439b8
-F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
-F test/e_select.test 6fd45fd4a59ec82b6dda7468699dcc0ec1a72538577750b4f90357a62c1d2723
-F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
-F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
-F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
-F test/e_uri.test 47eeb2960e74613f0f8722b2f13aef08fde69daa16e5380ac93df84dac8b1f72
-F test/e_vacuum.test 1b8b4772d05374aa1b8958669138bbb4213ee26a
-F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
-F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
-F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
-F test/e_walhook.test 01b494287ba9e60b70f6ebf3c6c62e0ffe01788e344a4846b08e5de0b344cb66
-F test/emptytable.test a38110becbdfa6325cd65cb588dca658cd885f62
-F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
-F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
-F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
-F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
-F test/eqp.test 4fd69d25f21d8679f5fce13e639975879d89abf6acce4bd9cede133b7482aba7
-F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
-F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
-F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3
-F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
-F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
-F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
-F test/expr.test 7cb55e80aeb41d65fec968c08212505123063fea60bdc355d764d747670e9eea
-F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
-F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
-F test/fallocate.test 07416bd593a116d5893cb244f45a94d5c6fe030561df3bd972e6135f8106e509
-F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
-F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
-F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768
-F test/fkey2.test 155809016fad6b2a1491facf2ac53a551bc57c2c
-F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
-F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
-F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a
-F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0
-F test/fkey7.test 24076d43d3449f12f25503909ca4bfb5fc5fefd5af1f930723a496343eb28454
-F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c
-F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
-F test/fordelete.test eb93a2f34137bb87bdab88fcab06c0bd92719aff
-F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
-F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
-F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
-F test/fts1b.test 5d8a01aefbecc8b7442b36c94c05eb7a845462d5
-F test/fts1c.test 85a525ce7428907469b4cce13d5563ce542ce64c
-F test/fts1d.test a73deace5c18df4a549b12908bade4f05dcf1a2f
-F test/fts1e.test 77244843e925560b5a0b70069c3e7ab62f181ed2
-F test/fts1f.test 2d6cb10d8b7a4e6edc321bbdb3982f1f48774714
-F test/fts1i.test 6bfe08cdfdced063a39a50c8601da65e6274d879
-F test/fts1j.test e3797475796043a161e348c46a309664cac83f7f
-F test/fts1k.test 65d3b41487b9f738d11b0f00eca375c0ca6bd970
-F test/fts1l.test 15c119ed2362b2b28d5300c0540a6a43eab66c36
-F test/fts1m.test 2d9ca67b095d49f037a914087cc0a61e89da4f0c
-F test/fts1n.test a2317dcd27b1d087ee3878b30e0a59c593c98b7a
-F test/fts1o.test d1554caede42bba2c82fe613bcc921856c196b752449ead0470fac52a20fd3b8
-F test/fts1porter.test d86e9c3e0c7f8ff95add6582b4b585fb4e02b96d
-F test/fts2.test e3fb95f96a650411574efc136f3fb10eef479ed7
-F test/fts2a.test 473a5c8b473a4e21a8e3fddaed1e59666e0c6ab7
-F test/fts2b.test 964abc0236c849c07ca1ae496bb25c268ae94816
-F test/fts2c.test ffb5a35230ac72c4354535c547965ce6824537c0
-F test/fts2d.test b7eaa671ca9a16997f3e5b158ee777ae21052b0b
-F test/fts2e.test 2da13dbc2d009105f42196845c1e1ce136c03d38
-F test/fts2f.test cf84096235991709c1e61caa389632aa0a4f976d
-F test/fts2g.test 3d26fe171bda6133ebf5a380731d70eaa2ef2f6f73d79769cf8946e622b6d597
-F test/fts2h.test 223af921323b409d4b5b18ff4e51619541b174bb
-F test/fts2i.test 1b22451d1f13f7c509baec620dc3a4a754885dd6
-F test/fts2j.test 298fa1670aa21cd445b282d139b70c72e7ade12b
-F test/fts2k.test c7ebf4a4937594aa07459e3e1bca1251c1be8659
-F test/fts2l.test 3333336621524cf7d60bb62d6ef6ab69647866ed
-F test/fts2m.test 4b30142ead6f3ed076e880a2a464064c5ad58c51
-F test/fts2n.test 12b9c5352128cebd1c6b8395e43788d4b09087c2
-F test/fts2o.test 4054ac7433eb5440f1b1d200cfa449342dc4aabd991759139813e17c73e5bf9a
-F test/fts2p.test 4b48c35c91e6a7dbf5ac8d1e5691823cc999aafb
-F test/fts2q.test b2fbbe038b7a31a52a6079b215e71226d8c6a682
-F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
-F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
-F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
-F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
-F test/fts3aa.test f267fcd6aca30fc70b81e5d82b68b34b38f581896020b57ed49e9777c7ebd85f
-F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
-F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
-F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
-F test/fts3ae.test ce32a13b34b0260928e4213b4481acf801533bda
-F test/fts3af.test d394978c534eabf22dd0837e718b913fd66b499c
-F test/fts3ag.test c003672a215124df7fc6000036d896f498b26b53
-F test/fts3ah.test dc9f66c32c296f1bc8bcc4535126bddfeca62894
-F test/fts3ai.test 24058fdc6e9e5102c1fd8459591b114b6a85d285
-F test/fts3aj.test 0ed71e1dd9b03b843a857dc3eb9b15630e0104fc
-F test/fts3ak.test bd14deafe9d1586e8e9bf032411026ac4f8c925d
-F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
-F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
-F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
-F test/fts3ao.test c416d50c4fdb6f32a15205b3d0a49eb74fcea92feb66b531a83c904770de5ff1
-F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1
-F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
-F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6
-F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
-F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
-F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
-F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
-F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b
-F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
-F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
-F test/fts3corrupt3.test 56e0ee83e90b57f5f3644cb7d1b36a067b7b8b19cdf0dedce45e5e13cf752f65
-F test/fts3cov.test 9c3681325b9a850bca8dd75cc29dde73e9a87972bb75204e97d826f13c7181f9
-F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708
-F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
-F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468
-F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
-F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
-F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
-F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c77e526
-F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
-F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8
-F test/fts3expr4.test cac5dd815fe6b5921741abdccdde3b7f50b86394de91e13308ee7986859c4a9f
-F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
-F test/fts3fault.test 9fb7d6266a38806de841f7244bac1b0fe3a1477184bbb10b172d19d2ca6ad692
-F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0
-F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
-F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
-F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
-F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a
-F test/fts3misc.test ba03a83b831555cfd18c6c862b24b70a53ce7497fe55077f7c4b7c9ce83c2eed
-F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
-F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
-F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
-F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
-F test/fts3query.test ca5dffabdfe9aef2ebcc89e02ce515898f86f8c30a365283831c53e0e08e5821
-F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99
-F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
-F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
-F test/fts3snippet.test 01a4231816e03a0660ae53ba2404fe69012fe0db
-F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
-F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
-F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
-F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
-F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
-F test/fts4check.test c3056eab9524232e4c9bdcd119912947e07bcc1c
-F test/fts4content.test 1518195a9f92b711d94419f76409a31cc78755854fb0abb1da2b74b9e0cf843e
-F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
-F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a
-F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
-F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
-F test/fts4langid.test 2168ba330af34f8a1c8832de0aab4c4b6fa195a16419c9c0c8aad59ceb6ff714
-F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7
-F test/fts4merge.test 10b55f410fade8691a455210b0b9302ef178a4f06fba0ad1941801caab82f5a9
-F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
-F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
-F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
-F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
-F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
-F test/fts4opt.test fd6a11684b965e1999564ae763797b7fb9e34c96
-F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
-F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
-F test/func.test 09dda479bcfc568f99f3070413e9672a8eeedc1be9c5d819bf55d4788c2583b7
-F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
-F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c
-F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
-F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
-F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
-F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
-F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
-F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
-F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
-F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
-F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79
-F test/fuzzcheck.c 3885207dc217c4dcdb2de4a3cb169a263afeef51ab9bd0ba8567289f0a19a470
-F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
-F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
-F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
-F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21
-F test/fuzzdata5.db 117d821cde02e30a687f6361a34b98e6e0b05062df523cfee163c58564403b68
-F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
-F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
-F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
-F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
-F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
-F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
-F test/having.test e4098a4b8962f9596035c3b87a8928a10648acc509f1bb8d6f96413bbf79a1b3
-F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
-F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
-F test/hook.test 1604b3b2f5931430087540404555c1b6be3618600b81558657c66b533ed70b13
-F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
-F test/icu.test 41aa8847745a879b897a7febea0f8f9efc8e67fe8bf680589b6e07c7b0a1569a
-F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
-F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
-F test/in.test 2fa2dfba1afe30eb830f327e7131dfadaa7a701d677de0eb65f9303d99e18fe0
-F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
-F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
-F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
-F test/in5.test 7ae37fcd4a5e198291c6ab5f31a5bb3d15397efe8b75a6736d7a95a7b8dd9e08
-F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
-F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
-F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
-F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
-F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
-F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758
-F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
-F test/incrvacuum.test b729aab1d4983037da57e66c20dfd7458561a85626dcf824f60175e35f4ce152
-F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
-F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
-F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
-F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238
-F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
-F test/index3.test 81bc47890b8abfb181bc35f8d10b56c069803386
-F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
-F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
-F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a617d
-F test/index7.test 72b59b8ddc5c13f4962886b4011eb9975014317d17ef36c6297921362fb7dd98
-F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
-F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
-F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
-F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
-F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216
-F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
-F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
-F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
-F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
-F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
-F test/insert4.test 46bead5f39e181850ee56adcf49d3a3157c460c52249211714612ac89fe34835
-F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
-F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba
-F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a
-F test/intarray.test 46d95b457916638c5d8b1af21fb174804b3acf8b
-F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
-F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
-F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8
-F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
-F test/ioerr.test 470fcc78e9cd352d162baf782fe301ea807d764241f58a48fc58109c2dfcdb6b
-F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26
-F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
-F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
-F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
-F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
-F test/istrue.test 62372ad3ddcc5d0eb8ff9097dcb0aad8961bf1b9cb45ba634f6e284695126f9a
-F test/join.test 2ad9d7fe10e0cc06bc7803c22e5533be11cdadbc592f5f95d789a873b57a5a66
-F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417
-F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
-F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
-F test/join5.test 5a2da0c3ea852a7063d3e72fc7d5a04a6de5ef6e6d85092582f69033f7459adc
-F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
-F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
-F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
-F test/journal3.test c9c29883f5bf535ae82ae21c472df6263806a22e467b6db7cd0d6d545305b4f6
-F test/jrnlmode.test a6693f2bed4541a21e703aaa37bb3e10de154130645952933b82b2dec0a8b539
-F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
-F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
-F test/json101.test b40a9f5395d8e669b0bc3eb550ad2ae9e5ada01fbce23c446c2a30a305a6d575
-F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
-F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
-F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
-F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
-F test/kvtest.c 94da54bb66aae7a54e47cf7e4ea4acecc0f217560f79ad3abfcc0361d6d557ba
-F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
-F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
-F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6
-F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
-F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
-F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
-F test/limit2.test 360982809e03211636d2b18ddbc97d5da06826941370607e4b00e113f827cb5a
-F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9
-F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
-F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
-F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
-F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
-F test/lock4.test 27143363eda1622f03c133efc8db808fc331afd973486cb571ea71cd717d37b8
-F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
-F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
-F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
-F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
-F test/lookaside.test b17c99ae3aef96a8c9fa6f6be33cc75b93d657cb791d3827302b6835b71941f7
-F test/main.test 6bbb3999fd461eb8fb335cbab97409a3d7f91bbb8da60635e8be3e4a04a77772
-F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
-F test/malloc.test 18dd1c4188c81ca79cf123527c71b19ee0c31feb9947fdffb0dc6ceb1436816a
-F test/malloc3.test 6e88bae6312854a4adb4ecc2a6a5ea8c59b4db778b724ba718e1c43fc8c3c136
-F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
-F test/malloc5.test 2e4ad7684a13389a44a840499cd47173a8d05f22f082d7d083eece433a7a64eb
-F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
-F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
-F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
-F test/malloc9.test 2307c6ee3703b0a21391f3ea92388b4b73f9105e
-F test/mallocA.test 672cd7dedb63771bade3a6f557f851a4ad161d4a
-F test/mallocAll.test 98f1be74bc9f49a858bc4f361fc58e26486798be
-F test/mallocB.test bc475ab850cda896142ab935bbfbc74c24e51ed6
-F test/mallocC.test 3dffe16532f109293ce1ccecd0c31dca55ef08c4
-F test/mallocD.test f78c295e8e18ea3029e65ca08278690e00c22100
-F test/mallocE.test db1ed69d7eded1b080952e2a7c37f364ad241b08
-F test/mallocF.test 2d5c590ebc2fc7f0dcebdf5aa8498b9aed69107e
-F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f
-F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
-F test/mallocI.test 6c23a71df077fa5d387be90e7e669c5b368ca38a
-F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
-F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c083707ab
-F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
-F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
-F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
-F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
-F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
-F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
-F test/memdb1.test 61aa1dbdeea6320791d2ff42a9a6149d5716be674bf06ee0ffa0aad1bf3eb5f8
-F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
-F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
-F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
-F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
-F test/minmax2.test dae92964ac87c1d2ef978c582e81a95e11c00f1cbef68980bfb2abaf10315063
-F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
-F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
-F test/misc1.test 704ea2cc7e7b9deb622b37953f0e77d0879826e8c3bfc1d7a691528035405061
-F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
-F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
-F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
-F test/misc5.test 60e1fc758a93cacd19eb2fafcd1d40d150a05047546c7a92389c98047d621901
-F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
-F test/misc7.test 349855706310f0de6b91645d199f6874f518627fd057743fa4e3689b60d06efc
-F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca
-F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
-F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795
-F test/mmap1.test d2cfc1635171c434dcff0ece2f1c8e0a658807ce
-F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
-F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
-F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
-F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
-F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
-F test/multiplex.test dc0d67b66f84b484a83cb8bbdf3f0a7f49562ccd
-F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
-F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
-F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
-F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f
-F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
-F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
-F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
-F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
-F test/normalize.test 501630ab49b0b26b65c74124bf03e3374c1b57fa97aae750f84803609141d167
-F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
-F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
-F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
-F test/notnull.test b6999231221df3534827e45e2005dd7a815fdd5f2c2e1afb9be21ead410816f8
-F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
-F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
-F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
-F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
-F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
-F test/optfuzz-db01.c a0c256905c8ac79f9a5de2f374a3d9f757bef0dca2a238dc7c10cc8a38031834
-F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041
-F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1
-F test/orderby1.test e4501f54721f804ca56922e253403ac6775f88e9f07569994ce99212b3ca5b10
-F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
-F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
-F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
-F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
-F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
-F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
-F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
-F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
-F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace
-F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03
-F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
-F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
-F test/pager1.test a32ce299ed01ffb06e84a3af467ae1f3389786b316f40c4359f442c79144736b
-F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
-F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
-F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
-F test/pagerfault.test 63c5da625562c66345ab4528790327ca63db2f6f9cbae2aba8cb7c51de3d1628
-F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
-F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
-F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
-F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
-F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
-F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
-F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
-F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test 10793f1de89a226fa22dde9ba9398de22571fee1bfb53a935a11be4aa014704f
-F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d
-F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
-F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
-F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c
-F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
-F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
-F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
-F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
-F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
-F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
-F test/pushdown.test 5e72c51c5e33253ed639ccee1e01ce62d62b6eee5ca893cd82334e4ee7b1d7fc
-F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
-F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
-F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
-F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
-F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
-F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
-F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
-F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
-F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
-F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
-F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
-F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
-F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
-F test/releasetest.tcl 5f15ab8056799e9a6e26a310d49236d2e774d6a30d0ec74601e18d4ce146b79c x
-F test/resetdb.test 2107b34a8c437183f48eb833905df43818160a55f4ac69bbaf54f356fb2b27bd
-F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
-F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
-F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
-F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
-F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
-F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
-F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d
-F test/rowvalue.test ef851a80f7e6de93b51caca9e4b6b7d2dcd540bbcca7d51860e80435b8b4c0de
-F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
-F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
-F test/rowvalue4.test cbd1cead27a797d11ec93301fd801c89e97eb1809b3d984b7f16a3876e362eac
-F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
-F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
-F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8
-F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
-F test/rowvalue9.test d8dd2c6ecac432dadaa79e41dc2434f007be1b6b
-F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504
-F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
-F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
-F test/savepoint.test 1f8a6b1aea9a0d05837adc463d4bf47bd9d0f1c842f1c2a9caccd639baf34bf9
-F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
-F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
-F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
-F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
-F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
-F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
-F test/scanstatus.test d14842d0a2757ee059bcffa365746453d60952ba1077980c9a348a9fefbd232a
-F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
-F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
-F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
-F test/schema4.test 3b26c9fa916abb6dadf894137adcf41b7796f7b9
-F test/schema5.test 29699b4421f183c8f0e88bd28ce7d75d13ea653e
-F test/schema6.test e4bd1f23d368695eb9e7b51ef6e02ca0642ea2ab4a52579959826b5e7dce1f9b
-F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2ff09384
-F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
-F test/select1.test 2e760bab8f3658b3b97debcf52860d0d2e20aa6cbe8b40e678ddb99871a15491
-F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
-F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
-F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
-F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
-F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
-F test/select7.test f659f231489349e8c5734e610803d7654207318f
-F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
-F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
-F test/selectA.test b8a590f6493cad5b0bb4dfe1709bf7dcda0b6c40bb4caf32d1e36a89eebc8fc5
-F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
-F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
-F test/selectD.test cfa9f27dbdbeaf2d021d26c79b6c790d8f26e5506d50117c7696d3e136d6d9e7
-F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
-F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
-F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840
-F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
-F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
-F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
-F test/sessionfuzz.c b0fcdcf757451957e17396a3af5171f1fdf9b2babc81da9fa35675df46c4729a
-F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
-F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
-F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38
-F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
-F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
-F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
-F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
-F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
-F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69e281
-F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
-F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
-F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
-F test/shell1.test 50154b0c4779df435b9e60ca60104b05f1cc217eab1aa383131359329e73d939
-F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
-F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
-F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
-F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
-F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
-F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
-F test/shell8.test 96be02ea0c21f05b24c1883d7b711a1fa8525a68ab7b636aacf6057876941013
-F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
-F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
-F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
-F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
-F test/skipscan1.test 8ab5d2c7c5cd3fe7f172d366e6e74e887cb33cb4
-F test/skipscan2.test ef143c6e4a5ba4f19c1d1e3f517811f7942bdf2142736cc568feb34e0b5fb763
-F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
-F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
-F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7
-F test/snapshot.test 85735bd997a4f6d710140c28fd860519a299649f
-F test/snapshot2.test 925e42427e923262db63c9d7155183f889e3e99feaedec4075f659e51608344f
-F test/snapshot3.test 9719443594a04778861bd20d12596c5f880af177d6cd62f111da3198cafc6096
-F test/snapshot_fault.test 52c5e97ebd218846a8ae2da4d147d3e77d71f963
-F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
-F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
-F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b
-F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0
-F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5
-F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c
-F test/sort5.test 6b43ae0e2169b5ceed441844492e55ba7f1ae0790528395ddf7888ab3094525d
-F test/sorterref.test a13ed207a0eea3c7898f308f979bfb518f68c598ec737d2c494dfd3deaa83506
-F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66
-F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
-F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
-F test/speed1p.test b180e98609c7677382cf618c0ec9b69f789033a8
-F test/speed2.test 53177056baf6556dcbdcf032bbdfc41c1aa74ded
-F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
-F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
-F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
-F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
-F test/speedtest1.c cc7e6b4a7c9f3e3d1a497ae3f75236a832a2ce0f6a9b017f95d996c821605bfb
-F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
-F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
-F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
-F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
-F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e
-F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
-F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
-F test/stat.test f8f1279ffffabe6df825723af18cc6e0ae70a893
-F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
-F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
-F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
-F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
-F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
-F test/subquery2.test 8250dfd6a773b04c7a5c37ac63276f62b329157ce171244d0cbe1acc365e3303
-F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
-F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
-F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
-F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
-F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33bab6cdaf
-F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
-F test/swarmvtab3.test 6cb664669630fcec4102a09333e52068734858fd2761eee3b0465c14cdbcee29
-F test/swarmvtabfault.test 00aec54665909490f5c383f3cae3b5d18bd97c12490b429ff8752a3027acfa42
-F test/symlink.test 0d816670325536b8973ec08d32b45136baddb80bd45fd178e0ce7a9e8153f3e7
-F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d4333092
-F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
-F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
-F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
-F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51
-F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
-F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
-F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
-F test/tclsqlite.test 5337e8890b96dad1ee541b15fbeec32e6bac2fe7fa096f91089057385aadba9b
-F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
-F test/tempdb2.test 4749545409c6d7438b435c3f05cdd139cf4145a954a6908d19e3443ffd8724b3
-F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
-F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
-F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
-F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
-F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl aa7558f20fcf7dd9151325f849d9103bd450235093bc078073bf0f080991e3c4
-F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
-F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
-F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
-F test/thread004.test f51dfc3936184aaf73ee85f315224baad272a87f
-F test/thread005.test 50d10b5684399676174bd96c94ad4250b1a2c8b6
-F test/thread1.test df115faa10a4ba1d456e9d4d9ec165016903eae4
-F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
-F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
-F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
-F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
-F test/threadtest3.c 38a612ea62854349ed66372f330a40d73c5cf956
-F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
-F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
-F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
-F test/tkt-26ff0c2d1e.test c15bec890c4d226c0da2f35ff30f9e84c169cfef90e73a8cb5cec11d723dfa96
-F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2
-F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0
-F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
-F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58
-F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d
-F test/tkt-385a5b56b9.test 5204a7cba0e28c99df0acbf95af5e1af4d32965a7a14de6eccebf949607618b1
-F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
-F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
-F test/tkt-3a77c9714e.test b08bca26de1140bdf004a37716582a43d7bd8be8
-F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70
-F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0
-F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
-F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407
-F test/tkt-4ef7e3cfca.test 3965ae11cc9cf6e334f9d7d3c1e20bf8d56254b1
-F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
-F test/tkt-5d863f876e.test 726e76d725f6fe0eb2fc8a522b721b79807380ee
-F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
-F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
-F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
-F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
-F test/tkt-78e04e52ea.test 1b5be1bac961833a9fd70fe50738cb4064822c61f82c54f7d488435ec806ea62
-F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f
-F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18
-F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
-F test/tkt-80e031a00f.test 9ee36348b761bf7c14261e002b75a4c0d5a04d4c
-F test/tkt-8454a207b9.test c583a9f814a82a2b5ba95207f55001c9f0cd816c
-F test/tkt-868145d012.test a5f941107ece6a64410ca4755c6329b7eb57a356
-F test/tkt-8c63ff0ec.test 258b7fc8d7e4e1cb5362c7d65c143528b9c4cbed
-F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5
-F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223
-F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667
-F test/tkt-9d68c883.test 16f7cb96781ba579bc2e19bb14b4ad609d9774b6
-F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8
-F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
-F test/tkt-a8a0d2996a.test 76662ff0622c90e7ce7bbcb4d9e1129acddf877d17c3489f2da7f17ddfaad1f4
-F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
-F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
-F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
-F test/tkt-b75a9ca6b0.test 1bc0381538fd21f96a10dbabc10ffc51b5b2e5f412d34bae571273ca784003d7
-F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877
-F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
-F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
-F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
-F test/tkt-cbd054fa6b.test 06ccd57af3c0c7895d0f7dc844f13c51f8258885
-F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d
-F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
-F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
-F test/tkt-f3e5abed55.test d5a0126118142d13e27f6ce9f4c47096e9321c00
-F test/tkt-f67b41381a.test a23bc124c981662db712167bacd0ed8ad11abac9
-F test/tkt-f777251dc7a.test d1a8fc3eefb7a9e64d19ff24d5c8c94c34a632fb
-F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
-F test/tkt-f973c7ac31.test 28ef85c7f015477916795246d8286aeda39d4ead
-F test/tkt-fa7bf5ec.test 9102dfea58aa371d78969da735f9392c57e2e035
-F test/tkt-fc62af4523.test 72825d3febdedcd5593a27989fc05accdbfc2bb4
-F test/tkt-fc7bd6358f.test 634bb4af7d661e82d6b61b80c86727bad698e08f
-F test/tkt1435.test f8c52c41de6e5ca02f1845f3a46e18e25cadac00
-F test/tkt1443.test bacc311da5c96a227bf8c167e77a30c99f8e8368
-F test/tkt1444.test a9d72f9e942708bd82dde6c707da61c489e213e9
-F test/tkt1449.test 93584a449752d52b07d2cfc280a69842b6e16ed5
-F test/tkt1473.test 9d000af3e11a4450d4c596f5e58b4b0d24eb0f8b
-F test/tkt1501.test 2064f98e00871848af4b2f517e46c1a7fb2e32db
-F test/tkt1512.test a1df1f66caf0b9122d6220c15dcee230298c2c2f
-F test/tkt1514.test ddef38e34fea72eb1ab935ded9f17a3fb71dd9df
-F test/tkt1536.test 83ff7a7b6e248016f8d682d4f7a4ae114070d466
-F test/tkt1537.test e3a14332de9770be8ff14bd15c19a49cbec10808
-F test/tkt1567.test 52f329386ac77e59260d4af1c58490d61377db20
-F test/tkt1644.test 80b6a2bb17885f3cf1cb886d97cdad13232bb869
-F test/tkt1667.test 4700d931ed19ea3983e8e703becb28079250b460
-F test/tkt1873.test 0e1b8c023050a430c2525179ed4022ddc7c31264
-F test/tkt2141.test f543d96f50d5a5dc0bc744f7db74ea166720ce46
-F test/tkt2192.test ff40157e5f42e65f844255d220fc6b290470942f
-F test/tkt2213.test a9702175601a57b61aba095a233b001d6f362474
-F test/tkt2251.test 5aab8c7898cd2df2a68fe19289cc29e8f5cf8c82
-F test/tkt2285.test cca17be61cf600b397188e77e7143844d2b977e9
-F test/tkt2332.test fc955609b958ca86dfa102832243370a0cc84070
-F test/tkt2339.test 73bd17818924cd2ac442e5fd9916b58565739450
-F test/tkt2391.test ab7a11be7402da8b51a5be603425367aa0684567
-F test/tkt2409.test be0d60e7d283f639dccea4b0b5e1cd3a4851fb5b
-F test/tkt2450.test 77ed94863f2049c1420288ddfea2d41e5e0971d6
-F test/tkt2565.test 8be666e927cb207aae88188f31c331870878b650
-F test/tkt2640.test 28134f5d1e05658ef182520cf0b680fa3de5211b
-F test/tkt2643.test 3f3ebb743da00d4fed4fcf6daed92a0e18e57813
-F test/tkt2686.test 6ee01c9b9e9c48f6d3a1fdd553b1cc4258f903d6
-F test/tkt2767.test 569000d842678f9cf2db7e0d1b27cbc9011381b0
-F test/tkt2817.test f31839e01f4243cff7399ef654d3af3558cb8d8d
-F test/tkt2820.test 39940276b3436d125deb7d8ebeee053e4cf13213
-F test/tkt2822.test f391776423a7c0d0949edfce375708bfb0f3141e
-F test/tkt2832.test a9b0b74a02dca166a04d9e37739c414b10929caa
-F test/tkt2854.test e432965db29e27e16f539b2ba7f502eb2ccc49af
-F test/tkt2920.test a8737380e4ae6424e00c0273dc12775704efbebf
-F test/tkt2927.test 4752868b9eeeb07a217f7f19f4cbaac98d6d086d
-F test/tkt2942.test c5c87d179799ca6d1fbe83c815510b87cd5ec7ce
-F test/tkt3080.test 1bca7579260920a66b4dd7e196e807c0f25ff804
-F test/tkt3093.test fbdbc5b4969244ad11f540759003e361fcaf391f
-F test/tkt3121.test 536df66a02838c26a12fe98639354ca1290ca68b
-F test/tkt3201.test f1500ccecc0d578dc4cde7d3242008297c4d59b3
-F test/tkt3292.test 962465a0984a3b8c757efe59c2c59144871ee1dd
-F test/tkt3298.test 20fd8773b825cb602e033aa04f8602e1ebdcd93c
-F test/tkt3334.test 9756631e3c4aa3c416362c279e3c0953a83b7ca8274cb81a13264bb56296d8b0
-F test/tkt3346.test 6f67c3ed7db94dfc5df4f5f0b63809a1f611e01a
-F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed
-F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b
-F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812
-F test/tkt3442.test a1fc47c669e651d16494de3ff349bcb53281456f2ca02c8bc14220b6044bbfe8
-F test/tkt3457.test 5651e2cbb94645b677ec663160b9e192b87b7d365aecdfb24e19f749575a6fc2
-F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19
-F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218
-F test/tkt3508.test d75704db9501625c7f7deec119fcaf1696aefb7d
-F test/tkt3522.test 22ce2ebbcb04a6be56c0977d405c207967318fd6
-F test/tkt3527.test 1a6a48441b560bdc53aec581a868eb576234874d
-F test/tkt3541.test 5dc257bde9bc833ab9cc6844bf170b998dbb950a
-F test/tkt3554.test f599967f279077bace39220cbe76085c7b423725
-F test/tkt3581.test 1966b7193f1e3f14951cce8c66907ae69454e9a3
-F test/tkt35xx.test f38c1b03713179d414969187c941466e44945b35
-F test/tkt3630.test 9a934c58c259f89a0ae6bb6bb846c56285a6fd0f
-F test/tkt3718.test 3b59dcb5c4e7754dacd91e7fd353a61492cc402a
-F test/tkt3731.test 0c5f4cbffe102d43c3b2188af91a9e36348f974b
-F test/tkt3757.test 10cd679a88675c880533083fc79ac04324525595
-F test/tkt3761.test b95ea9c98f21cf91325f18a984887e62caceab33
-F test/tkt3762.test 4d439ff7abdc8d9323150269d182c37c2d514576
-F test/tkt3773.test 7bca904d2a647a6a4a291bd86d7fd7c73855b789
-F test/tkt3791.test a6624b9a80b216a26cf473607f42f3e51898c267
-F test/tkt3793.test d90ffd75c52413908d15e1c44fc2ea9c80fcc449
-F test/tkt3810.test 09608d81c63a6ff3aaf7bc70717909c51f5f4048
-F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
-F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
-F test/tkt3838.test 292e72489101cd1320d7278dc111c173ebf334d4
-F test/tkt3841.test 4659845bc53f809a5932c61c6ce8c5bb9d6b947f
-F test/tkt3871.test d921703d07c68f4fd5312073215a17fa34b0401d
-F test/tkt3879.test 2ad5bef2c87e9991ce941e054c31abe26ef7fb90
-F test/tkt3911.test 74cd324f3ba653040cc6d94cc4857b290d12d633
-F test/tkt3918.test ea78bf164e4d55cbde0d83c671ef6fbe930a0032
-F test/tkt3922.test f26be40ab4fe6c00795629bd2006d96e270d9b1a
-F test/tkt3929.test cdf67acf5aa936ec4ffead81db87f8a71fe40e59
-F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767
-F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
-F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
-F test/tkt4018.test 18dbc6617f7a4b90e938d1bd6d26ad18daafaf08
-F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
-F test/tpch01.test 7c4eb8cdd79c568f46d344b3e789c9fdb8a766d112871352704861f3fca32a2a
-F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
-F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
-F test/trace3.test 1dff966888773ff1bfea01c080caf15417892b3f998408fe920c4791f7337144
-F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
-F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
-F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
-F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
-F test/trigger1.test 17e4b43e656c4b354df2357634a6ba887990f510c43629f4feca30e3338d2a61
-F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
-F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
-F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
-F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
-F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
-F test/trigger7.test 799c9d2561facef70340cc9e0dee98aee9b5bdfe
-F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
-F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
-F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
-F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
-F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
-F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
-F test/triggerE.test d9e9b364dfd527c84ac0de53045406325487feecb32888d482eca64421a50d99
-F test/triggerF.test 6a8c22bd058cf467f0c7d112afe87f7a8c579c0c4681b914b8f19020f48528a4
-F test/triggerG.test d5caeef6144ede2426dd13211fd72248241ff2ebc68e12a4c0bf30f5faa21499
-F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
-F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
-F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
-F test/tt3_stress.c c57d804716165811d979d4a719e05baccd79277f
-F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
-F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
-F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
-F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
-F test/unionvtab.test 595fb601de00188ca5e7c6dbe266c17a0faf234cf434ce85eccec1a929ef9baf
-F test/unionvtabfault.test 26b6854d5aef9005cd630513025690bff1b7378ae9c97b81e2a3cbe84eee0f58
-F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
-F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
-F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
-F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981
-F test/update.test 1148de8d913e9817717990603aadeca07aab9ddbb10a30f167cbfd8d3a3ccb60
-F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e
-F test/upsert1.test d587db593f131e112a98a05685c418e0eacc28df5905403e4ca04cd74c39a3fc
-F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
-F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
-F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
-F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
-F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
-F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
-F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
-F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
-F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
-F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
-F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
-F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7c010
-F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
-F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
-F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
-F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
-F test/view.test 765802c7a66d37fabd5ac8e2f2dbe572b43eb9ab
-F test/vtab1.test 8f91b9538d1404c3932293a588c4344218a0c94792d4289bb55e41020e7b3fff
-F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
-F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
-F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
-F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
-F test/vtab6.test 8e789f526e6594cf7ae933d1adee0caa87dc9f78
-F test/vtab7.test 70c6f4a1d6177144a8236e4172d5fba92e683440374664ad1f04851fbb335d3c
-F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
-F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
-F test/vtabA.test 1317f06a03597eee29f40a49b6c21e1aaba4285f
-F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796
-F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
-F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
-F test/vtabE.test 2a143fe75a11275781d1fd1988d86b66a3f69cb98f4add62e3da8fd0f637b45f
-F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b
-F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be450
-F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
-F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f
-F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
-F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
-F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
-F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
-F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918
-F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
-F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
-F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
-F test/wal6.test b602704e4b066199bc89d91ca9000f335dcf4572
-F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
-F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
-F test/wal8.test d9df3fba4caad5854ed69ed673c68482514203c8
-F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
-F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
-F test/walbak.test 018d4e5a3d45c6298d11b99f09a8ef6876527946
-F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434
-F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d
-F test/walcksum.test bb234a1bb42248b3515d992b719708015c384278
-F test/walcrash.test 21038858cc552077b0522f50b0fa87e38139306a
-F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
-F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af
-F test/walcrash4.test e7b6e7639a950a0cca8e210e248c8dad4d63bf20
-F test/walfault.test 09b8ad7e52d2f54bce50e31aa7ea51412bb9f70ac13c74e669ddcd8b48b0d98d
-F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
-F test/walmode.test cd6e7cff618eaaa5910ce57c3657aa50110397f86213886a2400afb9bfec7b7b
-F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
-F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03
-F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
-F test/walprotocol.test a112aba0b79e3adeaa485fed09484b32c654e97df58e454aa8489ac2cd57bf84
-F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
-F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768
-F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
-F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
-F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
-F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
-F test/where.test f19ea3fa31c425b04af42c8b192a5b595ee84498df8d27dcd79ec043b25fbbfb
-F test/where2.test 478d2170637b9211f593120648858593bf2445a1
-F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
-F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
-F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
-F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
-F test/where7.test e579da972eb3372edc9de850efc221848c763f9e4feafc8426d84a4453b92b23
-F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
-F test/where9.test ad2ddb339d10d324763c3da60502b8631f15a2397b869192fbd4e82f40e167d3
-F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4
-F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
-F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
-F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
-F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
-F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
-F test/whereG.test 0158783235a6dd82fc0e37652b8522b186b9510594ac0a4bff0c4101b4396a52
-F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
-F test/whereI.test b7769ee8dbefd987fb266715fee887f05f9ff180016b06fca7fa402df739193b
-F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
-F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
-F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
-F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
-F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0
-F test/wherelimit2.test be78ba3aa1831c6358fd7d5b9809bfd520f0c2a7d63a295e8f182e140ff137c3
-F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
-F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
-F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
-F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
-F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
-F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
-F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
-F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
-F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
-F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f
-F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
-F test/without_rowid3.test 2724c787a51a5dce09d078453a758117b4b728f1
-F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
-F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
-F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
-F test/wordcount.c d721a4b6fae93e6e33449700bce1686bc23257c27425bc3ef1599dc912adec66
-F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
-F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
-F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
-F test/zipfile.test a61f6ba6dbaaf4983849df84a31df140c7ddd1362e2fa9ecd3cdf5cd123b7f18
-F test/zipfile2.test 8a18965530258140ce301b2c2f4245bc505ffead2e17a97fa34c7ace379ea5e0
-F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
-F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
-F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d
-F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
-F tool/addopcodes.tcl 0288d5b26b9b35f4cb5affb76eec63f1dfce117bbc2020066708069ef60b86ff
-F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
-F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
-F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
-F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
-F tool/dbhash.c a06228aa21ebc4e6ea8daa486601d938499238a5
-F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
-F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
-F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
-F tool/fuzzershell.c e1d90a03ca790d7c331c2aae08ca46ff435f1ae1faa6cb9cc48f4687c18fdc6e
-F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
-F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
-F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
-F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 33892e2a243865f73e6c6e7cecce3c6eb4bb95db4a3d9d86d146c8064feb92fd
-F tool/lempar.c bf7db78e7213f1d51516710483eab506fd52bf632c7abfb3e2e9b885c90c03e1
-F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
-F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
-F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
-F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
-F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
-F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
-F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
-F tool/mkkeywordhash.c 20f366ad3794e1db42e333a6f35fa41a024f2e3528579c9d58eb13eaa3ab4913
-F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
-F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
-F tool/mkopcodeh.tcl 17d1ccc05a926e19e3a9679ea3e4d1aaa15ba753e2fa7363e6e81c80e0ef8b86
-F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
-F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
-F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
-F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
-F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
-F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
-F tool/mksqlite3c.tcl d532ccbe81234f766bab6e5c0451c99529debcea138caccc1862a9645b2d54f2
-F tool/mksqlite3h.tcl 080873e3856eceb9d289a08a00c4b30f875ea3feadcbece796bd509b1532792c
-F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
-F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
-F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
-F tool/omittest.tcl dfc8b18a23e9e5289104145b712cdb887c2d840c2d70dc09ce5dbeba8ed8d47c
-F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
-F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
-F tool/replace.tcl 60f91e8dd06ab81f74d213ecbd9c9945f32ac048
-F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
-F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
-F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
-F tool/showdb.c e6bc9dba233bf1b57ca0a525a2bba762db4e223de84990739db3f09c46151b1e
-F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
-F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
-F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
-F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c2a1
-F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
-F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
-F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec
-F tool/speed-check.sh 27c7fe178d5b2f7c90a04a127907acda0bfe637fa85b13c43e03e5ed39b008b6
-F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
-F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
-F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
-F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
-F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
-F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
-F tool/sqldiff.c 579d7e4e42c30a963781654c87d2868823120b55d59e16ca77b0edbab0218713
-F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968
-F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
-F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
-F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
-F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
-F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
-F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148
-F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
-F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
-F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
-F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
-F tool/warnings.sh 8a4acea31e0f9c562949a2d767329533c0930d699ea19c6704c0ca0aa9154068
-F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85
-F vsixtest/App.xaml.cpp c465147f50871165c60ca16955219f6c5812d6d8
-F vsixtest/App.xaml.h 4a9768e2983d05600ad1e1c2f1b00a132967da9f
-F vsixtest/Assets/LockScreenLogo.scale-200.png e820c9a3deb909197081b0bf3216c06e13905f0a
-F vsixtest/Assets/SplashScreen.scale-200.png cab70988ca71bebec7bfeb3b6dbafe17b9ab0b4a
-F vsixtest/Assets/Square150x150Logo.scale-200.png e17b40817db7a239fc239d83efcc951fb824e3ff
-F vsixtest/Assets/Square44x44Logo.scale-200.png 2f166237094dea94d952d10b9eeae81806844f1c
-F vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png 5f6a6d391b95a3061ccca6e6fdd6955ede63b4ed
-F vsixtest/Assets/StoreLogo.png 0828b7257db74a4ecd5eeb6b7b4971f0fdc4d9d1
-F vsixtest/Assets/Wide310x150Logo.scale-200.png 04ddefe5bc5f43ae12a7433f6f236ddab101ac42
-F vsixtest/MainPage.xaml 34f49897e3ca533a7e74506ba0759b66eebce151
-F vsixtest/MainPage.xaml.cpp 7f31fc6de751b64676c0924c97a5485d950a91d7
-F vsixtest/MainPage.xaml.h cc05cca10d50a003f6c6e4448b701cdd07f52f29
-F vsixtest/Package.appxmanifest 6b6db1eb7df3a315c5d681059754d5f0e0c47a93
-F vsixtest/pch.cpp cb823cfac36f1a39a7eb0acbd7e9a0b0de8f23af
-F vsixtest/pch.h 9cab7980f2ac4baa40807d8b5e52af32a21cf78c
-F vsixtest/vsixtest.sln 77cadbe4e96c1fe1bf51cd77de9e9b0a12ada547
-F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
-F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
-F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
-F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 1ecb3aa13de5c8dc611b814ff34010de0bd90aae73d88aa37a59c4627be4cc2d
-R 2db4b8b40a57a71d528932145db72c5a
-T +bgcolor * #d0c0ff
-T +sym-release *
-T +sym-version-3.24.0 *
-U drh
-Z 1c60c6ad1e28023fcabbb88fe23d7708
-# Remove this line to create a well-formed manifest.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/manifest.uuid b/chromium/third_party/sqlite/sqlite-src-3240000/manifest.uuid
deleted file mode 100644
index 25ed4595279..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/manifest.uuid
+++ /dev/null
@@ -1 +0,0 @@
-c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/mkso.sh b/chromium/third_party/sqlite/sqlite-src-3240000/mkso.sh
deleted file mode 100644
index 6f2e8e25edf..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/mkso.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-#
-# This script is used to compile SQLite into a shared library on Linux.
-#
-# Two separate shared libraries are generated. "sqlite3.so" is the core
-# library. "tclsqlite3.so" contains the TCL bindings and is the
-# library that is loaded into TCL in order to run SQLite.
-#
-make target_source
-cd tsrc
-rm shell.c
-TCLDIR=/home/drh/tcltk/846/linux/846linux
-TCLSTUBLIB=$TCLDIR/libtclstub8.4g.a
-OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1 -DHAVE_DLOPEN=1'
-OPTS="$OPTS -DSQLITE_THREADSAFE=1"
-OPTS="$OPTS -DSQLITE_ENABLE_FTS3=1"
-OPTS="$OPTS -DSQLITE_ENABLE_COLUMN_METADATA=1"
-for i in *.c; do
- if test $i != 'keywordhash.c'; then
- CMD="cc -fPIC $OPTS -O2 -I. -I$TCLDIR -c $i"
- echo $CMD
- $CMD
- fi
-done
-echo gcc -shared *.o $TCLSTUBLIB -o tclsqlite3.so
-gcc -shared *.o $TCLSTUBLIB -o tclsqlite3.so
-strip tclsqlite3.so
-rm tclsqlite.c tclsqlite.o
-echo gcc -shared *.o -o sqlite3.so
-gcc -shared *.o -o sqlite3.so
-strip sqlite3.so
-cd ..
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/config01.test b/chromium/third_party/sqlite/sqlite-src-3240000/mptest/config01.test
deleted file mode 100644
index 683ee911431..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/config01.test
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-** Configure five tasks in different ways, then run tests.
-*/
---if vfsname() GLOB 'unix'
-PRAGMA page_size=8192;
---task 1
- PRAGMA journal_mode=PERSIST;
- PRAGMA mmap_size=0;
---end
---task 2
- PRAGMA journal_mode=TRUNCATE;
- PRAGMA mmap_size=28672;
---end
---task 3
- PRAGMA journal_mode=MEMORY;
---end
---task 4
- PRAGMA journal_mode=OFF;
---end
---task 4
- PRAGMA mmap_size(268435456);
---end
---source multiwrite01.test
---wait all
-PRAGMA page_size=16384;
-VACUUM;
-CREATE TABLE pgsz(taskid, sz INTEGER);
---task 1
- INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
---end
---task 2
- INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
---end
---task 3
- INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
---end
---task 4
- INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
---end
---task 5
- INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
---end
---source multiwrite01.test
---wait all
-SELECT sz FROM pgsz;
---match 16384 16384 16384 16384 16384
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/config02.test b/chromium/third_party/sqlite/sqlite-src-3240000/mptest/config02.test
deleted file mode 100644
index 7d4b27898b4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/config02.test
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-** Configure five tasks in different ways, then run tests.
-*/
-PRAGMA page_size=512;
---task 1
- PRAGMA mmap_size=0;
---end
---task 2
- PRAGMA mmap_size=28672;
---end
---task 3
- PRAGMA mmap_size=8192;
---end
---task 4
- PRAGMA mmap_size=65536;
---end
---task 5
- PRAGMA mmap_size=268435456;
---end
---source multiwrite01.test
---source crash02.subtest
-PRAGMA page_size=1024;
-VACUUM;
-CREATE TABLE pgsz(taskid, sz INTEGER);
---task 1
- INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
---end
---task 2
- INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
---end
---task 3
- INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
---end
---task 4
- INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
---end
---task 5
- INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
---end
---source multiwrite01.test
---source crash02.subtest
---wait all
-SELECT sz FROM pgsz;
---match 1024 1024 1024 1024 1024
-PRAGMA page_size=2048;
-VACUUM;
-DELETE FROM pgsz;
---task 1
- INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
---end
---task 2
- INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
---end
---task 3
- INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
---end
---task 4
- INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
---end
---task 5
- INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
---end
---source multiwrite01.test
---source crash02.subtest
---wait all
-SELECT sz FROM pgsz;
---match 2048 2048 2048 2048 2048
-PRAGMA page_size=8192;
-VACUUM;
-DELETE FROM pgsz;
---task 1
- INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
---end
---task 2
- INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
---end
---task 3
- INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
---end
---task 4
- INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
---end
---task 5
- INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
---end
---source multiwrite01.test
---source crash02.subtest
---wait all
-SELECT sz FROM pgsz;
---match 8192 8192 8192 8192 8192
-PRAGMA page_size=16384;
-VACUUM;
-DELETE FROM pgsz;
---task 1
- INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
---end
---task 2
- INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
---end
---task 3
- INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
---end
---task 4
- INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
---end
---task 5
- INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
---end
---source multiwrite01.test
---source crash02.subtest
---wait all
-SELECT sz FROM pgsz;
---match 16384 16384 16384 16384 16384
-PRAGMA auto_vacuum=FULL;
-VACUUM;
---source multiwrite01.test
---source crash02.subtest
---wait all
-PRAGMA auto_vacuum=FULL;
-PRAGMA page_size=512;
-VACUUM;
---source multiwrite01.test
---source crash02.subtest
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/crash01.test b/chromium/third_party/sqlite/sqlite-src-3240000/mptest/crash01.test
deleted file mode 100644
index f1483dfa1d3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/crash01.test
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Test cases involving incomplete transactions that must be rolled back.
-*/
---task 1
- DROP TABLE IF EXISTS t1;
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- --sleep 1
- INSERT INTO t1 VALUES(1, randomblob(2000));
- INSERT INTO t1 VALUES(2, randomblob(1000));
- --sleep 1
- INSERT INTO t1 SELECT a+2, randomblob(1500) FROM t1;
- INSERT INTO t1 SELECT a+4, randomblob(1500) FROM t1;
- INSERT INTO t1 SELECT a+8, randomblob(1500) FROM t1;
- --sleep 1
- INSERT INTO t1 SELECT a+16, randomblob(1500) FROM t1;
- --sleep 1
- INSERT INTO t1 SELECT a+32, randomblob(1500) FROM t1;
- SELECT count(*) FROM t1;
- --match 64
- SELECT avg(length(b)) FROM t1;
- --match 1500.0
- --sleep 2
- UPDATE t1 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t1;
- --match 247
- SELECT a FROM t1 WHERE b='x17y';
- --match 17
- CREATE INDEX t1b ON t1(b);
- SELECT a FROM t1 WHERE b='x17y';
- --match 17
- SELECT a FROM t1 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
---wait 1
---task 2
- DROP TABLE IF EXISTS t2;
- CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
- INSERT INTO t2 SELECT a, b FROM t1;
- UPDATE t1 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t2;
- --match 247
- SELECT a FROM t2 WHERE b='x17y';
- --match 17
- CREATE INDEX t2b ON t2(b);
- SELECT a FROM t2 WHERE b='x17y';
- --match 17
- SELECT a FROM t2 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
---task 3
- DROP TABLE IF EXISTS t3;
- CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
- INSERT INTO t3 SELECT a, b FROM t1;
- UPDATE t1 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t3;
- --match 247
- SELECT a FROM t3 WHERE b='x17y';
- --match 17
- CREATE INDEX t3b ON t3(b);
- SELECT a FROM t3 WHERE b='x17y';
- --match 17
- SELECT a FROM t3 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
---task 4
- DROP TABLE IF EXISTS t4;
- CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
- INSERT INTO t4 SELECT a, b FROM t1;
- UPDATE t1 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t4;
- --match 247
- SELECT a FROM t4 WHERE b='x17y';
- --match 17
- CREATE INDEX t4b ON t4(b);
- SELECT a FROM t4 WHERE b='x17y';
- --match 17
- SELECT a FROM t4 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
---task 5
- DROP TABLE IF EXISTS t5;
- CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
- INSERT INTO t5 SELECT a, b FROM t1;
- UPDATE t1 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t5;
- --match 247
- SELECT a FROM t5 WHERE b='x17y';
- --match 17
- CREATE INDEX t5b ON t5(b);
- SELECT a FROM t5 WHERE b='x17y';
- --match 17
- SELECT a FROM t5 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
-
---wait all
-/* After the database file has been set up, run the crash2 subscript
-** multiple times. */
---source crash02.subtest
---source crash02.subtest
---source crash02.subtest
---source crash02.subtest
---source crash02.subtest
---source crash02.subtest
---source crash02.subtest
---source crash02.subtest
---source crash02.subtest
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/crash02.subtest b/chromium/third_party/sqlite/sqlite-src-3240000/mptest/crash02.subtest
deleted file mode 100644
index 86f64ddbe77..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/crash02.subtest
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-** This script is called from crash01.test and config02.test and perhaps other
-** script. After the database file has been set up, make a big rollback
-** journal in client 1, then crash client 1.
-** Then in the other clients, do an integrity check.
-*/
---task 1 leave-hot-journal
- --sleep 5
- --finish
- PRAGMA cache_size=10;
- BEGIN;
- UPDATE t1 SET b=randomblob(20000);
- UPDATE t2 SET b=randomblob(20000);
- UPDATE t3 SET b=randomblob(20000);
- UPDATE t4 SET b=randomblob(20000);
- UPDATE t5 SET b=randomblob(20000);
- UPDATE t1 SET b=NULL;
- UPDATE t2 SET b=NULL;
- UPDATE t3 SET b=NULL;
- UPDATE t4 SET b=NULL;
- UPDATE t5 SET b=NULL;
- --print Task one crashing an incomplete transaction
- --exit 1
---end
---task 2 integrity_check-2
- SELECT count(*) FROM t1;
- --match 64
- --sleep 100
- PRAGMA integrity_check(10);
- --match ok
---end
---task 3 integrity_check-3
- SELECT count(*) FROM t1;
- --match 64
- --sleep 100
- PRAGMA integrity_check(10);
- --match ok
---end
---task 4 integrity_check-4
- SELECT count(*) FROM t1;
- --match 64
- --sleep 100
- PRAGMA integrity_check(10);
- --match ok
---end
---task 5 integrity_check-5
- SELECT count(*) FROM t1;
- --match 64
- --sleep 100
- PRAGMA integrity_check(10);
- --match ok
---end
---wait all
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/mptest.c b/chromium/third_party/sqlite/sqlite-src-3240000/mptest/mptest.c
deleted file mode 100644
index 5022b009e6b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/mptest.c
+++ /dev/null
@@ -1,1470 +0,0 @@
-/*
-** 2013-04-05
-**
-** 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 is a program used for testing SQLite, and specifically for testing
-** the ability of independent processes to access the same SQLite database
-** concurrently.
-**
-** Compile this program as follows:
-**
-** gcc -g -c -Wall sqlite3.c $(OPTS)
-** gcc -g -o mptest mptest.c sqlite3.o $(LIBS)
-**
-** Recommended options:
-**
-** -DHAVE_USLEEP
-** -DSQLITE_NO_SYNC
-** -DSQLITE_THREADSAFE=0
-** -DSQLITE_OMIT_LOAD_EXTENSION
-**
-** Run like this:
-**
-** ./mptest $database $script
-**
-** where $database is the database to use for testing and $script is a
-** test script.
-*/
-#include "sqlite3.h"
-#include <stdio.h>
-#if defined(_WIN32)
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#else
-# include <unistd.h>
-#endif
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-
-#define ISSPACE(X) isspace((unsigned char)(X))
-#define ISDIGIT(X) isdigit((unsigned char)(X))
-
-/* The suffix to append to the child command lines, if any */
-#if defined(_WIN32)
-# define GETPID (int)GetCurrentProcessId
-#else
-# define GETPID getpid
-#endif
-
-/* The directory separator character(s) */
-#if defined(_WIN32)
-# define isDirSep(c) (((c) == '/') || ((c) == '\\'))
-#else
-# define isDirSep(c) ((c) == '/')
-#endif
-
-/* Mark a parameter as unused to suppress compiler warnings */
-#define UNUSED_PARAMETER(x) (void)x
-
-/* Global data
-*/
-static struct Global {
- char *argv0; /* Name of the executable */
- const char *zVfs; /* Name of VFS to use. Often NULL meaning "default" */
- char *zDbFile; /* Name of the database */
- sqlite3 *db; /* Open connection to database */
- char *zErrLog; /* Filename for error log */
- FILE *pErrLog; /* Where to write errors */
- char *zLog; /* Name of output log file */
- FILE *pLog; /* Where to write log messages */
- char zName[32]; /* Symbolic name of this process */
- int taskId; /* Task ID. 0 means supervisor. */
- int iTrace; /* Tracing level */
- int bSqlTrace; /* True to trace SQL commands */
- int bIgnoreSqlErrors; /* Ignore errors in SQL statements */
- int nError; /* Number of errors */
- int nTest; /* Number of --match operators */
- int iTimeout; /* Milliseconds until a busy timeout */
- int bSync; /* Call fsync() */
-} g;
-
-/* Default timeout */
-#define DEFAULT_TIMEOUT 10000
-
-/*
-** Print a message adding zPrefix[] to the beginning of every line.
-*/
-static void printWithPrefix(FILE *pOut, const char *zPrefix, const char *zMsg){
- while( zMsg && zMsg[0] ){
- int i;
- for(i=0; zMsg[i] && zMsg[i]!='\n' && zMsg[i]!='\r'; i++){}
- fprintf(pOut, "%s%.*s\n", zPrefix, i, zMsg);
- zMsg += i;
- while( zMsg[0]=='\n' || zMsg[0]=='\r' ) zMsg++;
- }
-}
-
-/*
-** Compare two pointers to strings, where the pointers might be NULL.
-*/
-static int safe_strcmp(const char *a, const char *b){
- if( a==b ) return 0;
- if( a==0 ) return -1;
- if( b==0 ) return 1;
- return strcmp(a,b);
-}
-
-/*
-** Return TRUE if string z[] matches glob pattern zGlob[].
-** Return FALSE if the pattern does not match.
-**
-** Globbing rules:
-**
-** '*' Matches any sequence of zero or more characters.
-**
-** '?' Matches exactly one character.
-**
-** [...] Matches one character from the enclosed list of
-** characters.
-**
-** [^...] Matches one character not in the enclosed list.
-**
-** '#' Matches any sequence of one or more digits with an
-** optional + or - sign in front
-*/
-int strglob(const char *zGlob, const char *z){
- int c, c2;
- int invert;
- int seen;
-
- while( (c = (*(zGlob++)))!=0 ){
- if( c=='*' ){
- while( (c=(*(zGlob++))) == '*' || c=='?' ){
- if( c=='?' && (*(z++))==0 ) return 0;
- }
- if( c==0 ){
- return 1;
- }else if( c=='[' ){
- while( *z && strglob(zGlob-1,z) ){
- z++;
- }
- return (*z)!=0;
- }
- while( (c2 = (*(z++)))!=0 ){
- while( c2!=c ){
- c2 = *(z++);
- if( c2==0 ) return 0;
- }
- if( strglob(zGlob,z) ) return 1;
- }
- return 0;
- }else if( c=='?' ){
- if( (*(z++))==0 ) return 0;
- }else if( c=='[' ){
- int prior_c = 0;
- seen = 0;
- invert = 0;
- c = *(z++);
- if( c==0 ) return 0;
- c2 = *(zGlob++);
- if( c2=='^' ){
- invert = 1;
- c2 = *(zGlob++);
- }
- if( c2==']' ){
- if( c==']' ) seen = 1;
- c2 = *(zGlob++);
- }
- while( c2 && c2!=']' ){
- if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
- c2 = *(zGlob++);
- if( c>=prior_c && c<=c2 ) seen = 1;
- prior_c = 0;
- }else{
- if( c==c2 ){
- seen = 1;
- }
- prior_c = c2;
- }
- c2 = *(zGlob++);
- }
- if( c2==0 || (seen ^ invert)==0 ) return 0;
- }else if( c=='#' ){
- if( (z[0]=='-' || z[0]=='+') && ISDIGIT(z[1]) ) z++;
- if( !ISDIGIT(z[0]) ) return 0;
- z++;
- while( ISDIGIT(z[0]) ){ z++; }
- }else{
- if( c!=(*(z++)) ) return 0;
- }
- }
- return *z==0;
-}
-
-/*
-** Close output stream pOut if it is not stdout or stderr
-*/
-static void maybeClose(FILE *pOut){
- if( pOut!=stdout && pOut!=stderr ) fclose(pOut);
-}
-
-/*
-** Print an error message
-*/
-static void errorMessage(const char *zFormat, ...){
- va_list ap;
- char *zMsg;
- char zPrefix[30];
- va_start(ap, zFormat);
- zMsg = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:ERROR: ", g.zName);
- if( g.pLog ){
- printWithPrefix(g.pLog, zPrefix, zMsg);
- fflush(g.pLog);
- }
- if( g.pErrLog && safe_strcmp(g.zErrLog,g.zLog) ){
- printWithPrefix(g.pErrLog, zPrefix, zMsg);
- fflush(g.pErrLog);
- }
- sqlite3_free(zMsg);
- g.nError++;
-}
-
-/* Forward declaration */
-static int trySql(const char*, ...);
-
-/*
-** Print an error message and then quit.
-*/
-static void fatalError(const char *zFormat, ...){
- va_list ap;
- char *zMsg;
- char zPrefix[30];
- va_start(ap, zFormat);
- zMsg = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:FATAL: ", g.zName);
- if( g.pLog ){
- printWithPrefix(g.pLog, zPrefix, zMsg);
- fflush(g.pLog);
- maybeClose(g.pLog);
- }
- if( g.pErrLog && safe_strcmp(g.zErrLog,g.zLog) ){
- printWithPrefix(g.pErrLog, zPrefix, zMsg);
- fflush(g.pErrLog);
- maybeClose(g.pErrLog);
- }
- sqlite3_free(zMsg);
- if( g.db ){
- int nTry = 0;
- g.iTimeout = 0;
- while( trySql("UPDATE client SET wantHalt=1;")==SQLITE_BUSY
- && (nTry++)<100 ){
- sqlite3_sleep(10);
- }
- }
- sqlite3_close(g.db);
- exit(1);
-}
-
-
-/*
-** Print a log message
-*/
-static void logMessage(const char *zFormat, ...){
- va_list ap;
- char *zMsg;
- char zPrefix[30];
- va_start(ap, zFormat);
- zMsg = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s: ", g.zName);
- if( g.pLog ){
- printWithPrefix(g.pLog, zPrefix, zMsg);
- fflush(g.pLog);
- }
- sqlite3_free(zMsg);
-}
-
-/*
-** Return the length of a string omitting trailing whitespace
-*/
-static int clipLength(const char *z){
- int n = (int)strlen(z);
- while( n>0 && ISSPACE(z[n-1]) ){ n--; }
- return n;
-}
-
-/*
-** Auxiliary SQL function to return the name of the VFS
-*/
-static void vfsNameFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- char *zVfs = 0;
- UNUSED_PARAMETER(argc);
- UNUSED_PARAMETER(argv);
- sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zVfs);
- if( zVfs ){
- sqlite3_result_text(context, zVfs, -1, sqlite3_free);
- }
-}
-
-/*
-** Busy handler with a g.iTimeout-millisecond timeout
-*/
-static int busyHandler(void *pCD, int count){
- UNUSED_PARAMETER(pCD);
- if( count*10>g.iTimeout ){
- if( g.iTimeout>0 ) errorMessage("timeout after %dms", g.iTimeout);
- return 0;
- }
- sqlite3_sleep(10);
- return 1;
-}
-
-/*
-** SQL Trace callback
-*/
-static void sqlTraceCallback(void *NotUsed1, const char *zSql){
- UNUSED_PARAMETER(NotUsed1);
- logMessage("[%.*s]", clipLength(zSql), zSql);
-}
-
-/*
-** SQL error log callback
-*/
-static void sqlErrorCallback(void *pArg, int iErrCode, const char *zMsg){
- UNUSED_PARAMETER(pArg);
- if( iErrCode==SQLITE_ERROR && g.bIgnoreSqlErrors ) return;
- if( (iErrCode&0xff)==SQLITE_SCHEMA && g.iTrace<3 ) return;
- if( g.iTimeout==0 && (iErrCode&0xff)==SQLITE_BUSY && g.iTrace<3 ) return;
- if( (iErrCode&0xff)==SQLITE_NOTICE ){
- logMessage("(info) %s", zMsg);
- }else{
- errorMessage("(errcode=%d) %s", iErrCode, zMsg);
- }
-}
-
-/*
-** Prepare an SQL statement. Issue a fatal error if unable.
-*/
-static sqlite3_stmt *prepareSql(const char *zFormat, ...){
- va_list ap;
- char *zSql;
- int rc;
- sqlite3_stmt *pStmt = 0;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- sqlite3_finalize(pStmt);
- fatalError("%s\n%s\n", sqlite3_errmsg(g.db), zSql);
- }
- sqlite3_free(zSql);
- return pStmt;
-}
-
-/*
-** Run arbitrary SQL. Issue a fatal error on failure.
-*/
-static void runSql(const char *zFormat, ...){
- va_list ap;
- char *zSql;
- int rc;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- rc = sqlite3_exec(g.db, zSql, 0, 0, 0);
- if( rc!=SQLITE_OK ){
- fatalError("%s\n%s\n", sqlite3_errmsg(g.db), zSql);
- }
- sqlite3_free(zSql);
-}
-
-/*
-** Try to run arbitrary SQL. Return success code.
-*/
-static int trySql(const char *zFormat, ...){
- va_list ap;
- char *zSql;
- int rc;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- rc = sqlite3_exec(g.db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- return rc;
-}
-
-/* Structure for holding an arbitrary length string
-*/
-typedef struct String String;
-struct String {
- char *z; /* the string */
- int n; /* Slots of z[] used */
- int nAlloc; /* Slots of z[] allocated */
-};
-
-/* Free a string */
-static void stringFree(String *p){
- if( p->z ) sqlite3_free(p->z);
- memset(p, 0, sizeof(*p));
-}
-
-/* Append n bytes of text to a string. If n<0 append the entire string. */
-static void stringAppend(String *p, const char *z, int n){
- if( n<0 ) n = (int)strlen(z);
- if( p->n+n>=p->nAlloc ){
- int nAlloc = p->nAlloc*2 + n + 100;
- char *zNew = sqlite3_realloc(p->z, nAlloc);
- if( zNew==0 ) fatalError("out of memory");
- p->z = zNew;
- p->nAlloc = nAlloc;
- }
- memcpy(p->z+p->n, z, n);
- p->n += n;
- p->z[p->n] = 0;
-}
-
-/* Reset a string to an empty string */
-static void stringReset(String *p){
- if( p->z==0 ) stringAppend(p, " ", 1);
- p->n = 0;
- p->z[0] = 0;
-}
-
-/* Append a new token onto the end of the string */
-static void stringAppendTerm(String *p, const char *z){
- int i;
- if( p->n ) stringAppend(p, " ", 1);
- if( z==0 ){
- stringAppend(p, "nil", 3);
- return;
- }
- for(i=0; z[i] && !ISSPACE(z[i]); i++){}
- if( i>0 && z[i]==0 ){
- stringAppend(p, z, i);
- return;
- }
- stringAppend(p, "'", 1);
- while( z[0] ){
- for(i=0; z[i] && z[i]!='\''; i++){}
- if( z[i] ){
- stringAppend(p, z, i+1);
- stringAppend(p, "'", 1);
- z += i+1;
- }else{
- stringAppend(p, z, i);
- break;
- }
- }
- stringAppend(p, "'", 1);
-}
-
-/*
-** Callback function for evalSql()
-*/
-static int evalCallback(void *pCData, int argc, char **argv, char **azCol){
- String *p = (String*)pCData;
- int i;
- UNUSED_PARAMETER(azCol);
- for(i=0; i<argc; i++) stringAppendTerm(p, argv[i]);
- return 0;
-}
-
-/*
-** Run arbitrary SQL and record the results in an output string
-** given by the first parameter.
-*/
-static int evalSql(String *p, const char *zFormat, ...){
- va_list ap;
- char *zSql;
- int rc;
- char *zErrMsg = 0;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- assert( g.iTimeout>0 );
- rc = sqlite3_exec(g.db, zSql, evalCallback, p, &zErrMsg);
- sqlite3_free(zSql);
- if( rc ){
- char zErr[30];
- sqlite3_snprintf(sizeof(zErr), zErr, "error(%d)", rc);
- stringAppendTerm(p, zErr);
- if( zErrMsg ){
- stringAppendTerm(p, zErrMsg);
- sqlite3_free(zErrMsg);
- }
- }
- return rc;
-}
-
-/*
-** Auxiliary SQL function to recursively evaluate SQL.
-*/
-static void evalFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- const char *zSql = (const char*)sqlite3_value_text(argv[0]);
- String res;
- char *zErrMsg = 0;
- int rc;
- UNUSED_PARAMETER(argc);
- memset(&res, 0, sizeof(res));
- rc = sqlite3_exec(db, zSql, evalCallback, &res, &zErrMsg);
- if( zErrMsg ){
- sqlite3_result_error(context, zErrMsg, -1);
- sqlite3_free(zErrMsg);
- }else if( rc ){
- sqlite3_result_error_code(context, rc);
- }else{
- sqlite3_result_text(context, res.z, -1, SQLITE_TRANSIENT);
- }
- stringFree(&res);
-}
-
-/*
-** Look up the next task for client iClient in the database.
-** Return the task script and the task number and mark that
-** task as being under way.
-*/
-static int startScript(
- int iClient, /* The client number */
- char **pzScript, /* Write task script here */
- int *pTaskId, /* Write task number here */
- char **pzTaskName /* Name of the task */
-){
- sqlite3_stmt *pStmt = 0;
- int taskId;
- int rc;
- int totalTime = 0;
-
- *pzScript = 0;
- g.iTimeout = 0;
- while(1){
- rc = trySql("BEGIN IMMEDIATE");
- if( rc==SQLITE_BUSY ){
- sqlite3_sleep(10);
- totalTime += 10;
- continue;
- }
- if( rc!=SQLITE_OK ){
- fatalError("in startScript: %s", sqlite3_errmsg(g.db));
- }
- if( g.nError || g.nTest ){
- runSql("UPDATE counters SET nError=nError+%d, nTest=nTest+%d",
- g.nError, g.nTest);
- g.nError = 0;
- g.nTest = 0;
- }
- pStmt = prepareSql("SELECT 1 FROM client WHERE id=%d AND wantHalt",iClient);
- rc = sqlite3_step(pStmt);
- sqlite3_finalize(pStmt);
- if( rc==SQLITE_ROW ){
- runSql("DELETE FROM client WHERE id=%d", iClient);
- g.iTimeout = DEFAULT_TIMEOUT;
- runSql("COMMIT TRANSACTION;");
- return SQLITE_DONE;
- }
- pStmt = prepareSql(
- "SELECT script, id, name FROM task"
- " WHERE client=%d AND starttime IS NULL"
- " ORDER BY id LIMIT 1", iClient);
- rc = sqlite3_step(pStmt);
- if( rc==SQLITE_ROW ){
- int n = sqlite3_column_bytes(pStmt, 0);
- *pzScript = sqlite3_malloc(n+1);
- strcpy(*pzScript, (const char*)sqlite3_column_text(pStmt, 0));
- *pTaskId = taskId = sqlite3_column_int(pStmt, 1);
- *pzTaskName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 2));
- sqlite3_finalize(pStmt);
- runSql("UPDATE task"
- " SET starttime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')"
- " WHERE id=%d;", taskId);
- g.iTimeout = DEFAULT_TIMEOUT;
- runSql("COMMIT TRANSACTION;");
- return SQLITE_OK;
- }
- sqlite3_finalize(pStmt);
- if( rc==SQLITE_DONE ){
- if( totalTime>30000 ){
- errorMessage("Waited over 30 seconds with no work. Giving up.");
- runSql("DELETE FROM client WHERE id=%d; COMMIT;", iClient);
- sqlite3_close(g.db);
- exit(1);
- }
- while( trySql("COMMIT")==SQLITE_BUSY ){
- sqlite3_sleep(10);
- totalTime += 10;
- }
- sqlite3_sleep(100);
- totalTime += 100;
- continue;
- }
- fatalError("%s", sqlite3_errmsg(g.db));
- }
- g.iTimeout = DEFAULT_TIMEOUT;
-}
-
-/*
-** Mark a script as having finished. Remove the CLIENT table entry
-** if bShutdown is true.
-*/
-static int finishScript(int iClient, int taskId, int bShutdown){
- runSql("UPDATE task"
- " SET endtime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')"
- " WHERE id=%d;", taskId);
- if( bShutdown ){
- runSql("DELETE FROM client WHERE id=%d", iClient);
- }
- return SQLITE_OK;
-}
-
-/*
-** Start up a client process for iClient, if it is not already
-** running. If the client is already running, then this routine
-** is a no-op.
-*/
-static void startClient(int iClient){
- runSql("INSERT OR IGNORE INTO client VALUES(%d,0)", iClient);
- if( sqlite3_changes(g.db) ){
- char *zSys;
- int rc;
- zSys = sqlite3_mprintf("%s \"%s\" --client %d --trace %d",
- g.argv0, g.zDbFile, iClient, g.iTrace);
- if( g.bSqlTrace ){
- zSys = sqlite3_mprintf("%z --sqltrace", zSys);
- }
- if( g.bSync ){
- zSys = sqlite3_mprintf("%z --sync", zSys);
- }
- if( g.zVfs ){
- zSys = sqlite3_mprintf("%z --vfs \"%s\"", zSys, g.zVfs);
- }
- if( g.iTrace>=2 ) logMessage("system('%q')", zSys);
-#if !defined(_WIN32)
- zSys = sqlite3_mprintf("%z &", zSys);
- rc = system(zSys);
- if( rc ) errorMessage("system() fails with error code %d", rc);
-#else
- {
- STARTUPINFOA startupInfo;
- PROCESS_INFORMATION processInfo;
- memset(&startupInfo, 0, sizeof(startupInfo));
- startupInfo.cb = sizeof(startupInfo);
- memset(&processInfo, 0, sizeof(processInfo));
- rc = CreateProcessA(NULL, zSys, NULL, NULL, FALSE, 0, NULL, NULL,
- &startupInfo, &processInfo);
- if( rc ){
- CloseHandle(processInfo.hThread);
- CloseHandle(processInfo.hProcess);
- }else{
- errorMessage("CreateProcessA() fails with error code %lu",
- GetLastError());
- }
- }
-#endif
- sqlite3_free(zSys);
- }
-}
-
-/*
-** Read the entire content of a file into memory
-*/
-static char *readFile(const char *zFilename){
- FILE *in = fopen(zFilename, "rb");
- long sz;
- char *z;
- if( in==0 ){
- fatalError("cannot open \"%s\" for reading", zFilename);
- }
- fseek(in, 0, SEEK_END);
- sz = ftell(in);
- rewind(in);
- z = sqlite3_malloc( sz+1 );
- sz = (long)fread(z, 1, sz, in);
- z[sz] = 0;
- fclose(in);
- return z;
-}
-
-/*
-** Return the length of the next token.
-*/
-static int tokenLength(const char *z, int *pnLine){
- int n = 0;
- if( ISSPACE(z[0]) || (z[0]=='/' && z[1]=='*') ){
- int inC = 0;
- int c;
- if( z[0]=='/' ){
- inC = 1;
- n = 2;
- }
- while( (c = z[n++])!=0 ){
- if( c=='\n' ) (*pnLine)++;
- if( ISSPACE(c) ) continue;
- if( inC && c=='*' && z[n]=='/' ){
- n++;
- inC = 0;
- }else if( !inC && c=='/' && z[n]=='*' ){
- n++;
- inC = 1;
- }else if( !inC ){
- break;
- }
- }
- n--;
- }else if( z[0]=='-' && z[1]=='-' ){
- for(n=2; z[n] && z[n]!='\n'; n++){}
- if( z[n] ){ (*pnLine)++; n++; }
- }else if( z[0]=='"' || z[0]=='\'' ){
- int delim = z[0];
- for(n=1; z[n]; n++){
- if( z[n]=='\n' ) (*pnLine)++;
- if( z[n]==delim ){
- n++;
- if( z[n+1]!=delim ) break;
- }
- }
- }else{
- int c;
- for(n=1; (c = z[n])!=0 && !ISSPACE(c) && c!='"' && c!='\'' && c!=';'; n++){}
- }
- return n;
-}
-
-/*
-** Copy a single token into a string buffer.
-*/
-static int extractToken(const char *zIn, int nIn, char *zOut, int nOut){
- int i;
- if( nIn<=0 ){
- zOut[0] = 0;
- return 0;
- }
- for(i=0; i<nIn && i<nOut-1 && !ISSPACE(zIn[i]); i++){ zOut[i] = zIn[i]; }
- zOut[i] = 0;
- return i;
-}
-
-/*
-** Find the number of characters up to the start of the next "--end" token.
-*/
-static int findEnd(const char *z, int *pnLine){
- int n = 0;
- while( z[n] && (strncmp(z+n,"--end",5) || !ISSPACE(z[n+5])) ){
- n += tokenLength(z+n, pnLine);
- }
- return n;
-}
-
-/*
-** Find the number of characters up to the first character past the
-** of the next "--endif" or "--else" token. Nested --if commands are
-** also skipped.
-*/
-static int findEndif(const char *z, int stopAtElse, int *pnLine){
- int n = 0;
- while( z[n] ){
- int len = tokenLength(z+n, pnLine);
- if( (strncmp(z+n,"--endif",7)==0 && ISSPACE(z[n+7]))
- || (stopAtElse && strncmp(z+n,"--else",6)==0 && ISSPACE(z[n+6]))
- ){
- return n+len;
- }
- if( strncmp(z+n,"--if",4)==0 && ISSPACE(z[n+4]) ){
- int skip = findEndif(z+n+len, 0, pnLine);
- n += skip + len;
- }else{
- n += len;
- }
- }
- return n;
-}
-
-/*
-** Wait for a client process to complete all its tasks
-*/
-static void waitForClient(int iClient, int iTimeout, char *zErrPrefix){
- sqlite3_stmt *pStmt;
- int rc;
- if( iClient>0 ){
- pStmt = prepareSql(
- "SELECT 1 FROM task"
- " WHERE client=%d"
- " AND client IN (SELECT id FROM client)"
- " AND endtime IS NULL",
- iClient);
- }else{
- pStmt = prepareSql(
- "SELECT 1 FROM task"
- " WHERE client IN (SELECT id FROM client)"
- " AND endtime IS NULL");
- }
- g.iTimeout = 0;
- while( ((rc = sqlite3_step(pStmt))==SQLITE_BUSY || rc==SQLITE_ROW)
- && iTimeout>0
- ){
- sqlite3_reset(pStmt);
- sqlite3_sleep(50);
- iTimeout -= 50;
- }
- sqlite3_finalize(pStmt);
- g.iTimeout = DEFAULT_TIMEOUT;
- if( rc!=SQLITE_DONE ){
- if( zErrPrefix==0 ) zErrPrefix = "";
- if( iClient>0 ){
- errorMessage("%stimeout waiting for client %d", zErrPrefix, iClient);
- }else{
- errorMessage("%stimeout waiting for all clients", zErrPrefix);
- }
- }
-}
-
-/* Return a pointer to the tail of a filename
-*/
-static char *filenameTail(char *z){
- int i, j;
- for(i=j=0; z[i]; i++) if( isDirSep(z[i]) ) j = i+1;
- return z+j;
-}
-
-/*
-** Interpret zArg as a boolean value. Return either 0 or 1.
-*/
-static int booleanValue(char *zArg){
- int i;
- if( zArg==0 ) return 0;
- for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
- if( i>0 && zArg[i]==0 ) return atoi(zArg);
- if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
- return 1;
- }
- if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
- return 0;
- }
- errorMessage("unknown boolean: [%s]", zArg);
- return 0;
-}
-
-
-/* This routine exists as a convenient place to set a debugger
-** breakpoint.
-*/
-static void test_breakpoint(void){ static volatile int cnt = 0; cnt++; }
-
-/* Maximum number of arguments to a --command */
-#define MX_ARG 2
-
-/*
-** Run a script.
-*/
-static void runScript(
- int iClient, /* The client number, or 0 for the master */
- int taskId, /* The task ID for clients. 0 for master */
- char *zScript, /* Text of the script */
- char *zFilename /* File from which script was read. */
-){
- int lineno = 1;
- int prevLine = 1;
- int ii = 0;
- int iBegin = 0;
- int n, c, j;
- int len;
- int nArg;
- String sResult;
- char zCmd[30];
- char zError[1000];
- char azArg[MX_ARG][100];
-
- memset(&sResult, 0, sizeof(sResult));
- stringReset(&sResult);
- while( (c = zScript[ii])!=0 ){
- prevLine = lineno;
- len = tokenLength(zScript+ii, &lineno);
- if( ISSPACE(c) || (c=='/' && zScript[ii+1]=='*') ){
- ii += len;
- continue;
- }
- if( c!='-' || zScript[ii+1]!='-' || !isalpha(zScript[ii+2]) ){
- ii += len;
- continue;
- }
-
- /* Run any prior SQL before processing the new --command */
- if( ii>iBegin ){
- char *zSql = sqlite3_mprintf("%.*s", ii-iBegin, zScript+iBegin);
- evalSql(&sResult, zSql);
- sqlite3_free(zSql);
- iBegin = ii + len;
- }
-
- /* Parse the --command */
- if( g.iTrace>=2 ) logMessage("%.*s", len, zScript+ii);
- n = extractToken(zScript+ii+2, len-2, zCmd, sizeof(zCmd));
- for(nArg=0; n<len-2 && nArg<MX_ARG; nArg++){
- while( n<len-2 && ISSPACE(zScript[ii+2+n]) ){ n++; }
- if( n>=len-2 ) break;
- n += extractToken(zScript+ii+2+n, len-2-n,
- azArg[nArg], sizeof(azArg[nArg]));
- }
- for(j=nArg; j<MX_ARG; j++) azArg[j++][0] = 0;
-
- /*
- ** --sleep N
- **
- ** Pause for N milliseconds
- */
- if( strcmp(zCmd, "sleep")==0 ){
- sqlite3_sleep(atoi(azArg[0]));
- }else
-
- /*
- ** --exit N
- **
- ** Exit this process. If N>0 then exit without shutting down
- ** SQLite. (In other words, simulate a crash.)
- */
- if( strcmp(zCmd, "exit")==0 ){
- int rc = atoi(azArg[0]);
- finishScript(iClient, taskId, 1);
- if( rc==0 ) sqlite3_close(g.db);
- exit(rc);
- }else
-
- /*
- ** --testcase NAME
- **
- ** Begin a new test case. Announce in the log that the test case
- ** has begun.
- */
- if( strcmp(zCmd, "testcase")==0 ){
- if( g.iTrace==1 ) logMessage("%.*s", len - 1, zScript+ii);
- stringReset(&sResult);
- }else
-
- /*
- ** --finish
- **
- ** Mark the current task as having finished, even if it is not.
- ** This can be used in conjunction with --exit to simulate a crash.
- */
- if( strcmp(zCmd, "finish")==0 && iClient>0 ){
- finishScript(iClient, taskId, 1);
- }else
-
- /*
- ** --reset
- **
- ** Reset accumulated results back to an empty string
- */
- if( strcmp(zCmd, "reset")==0 ){
- stringReset(&sResult);
- }else
-
- /*
- ** --match ANSWER...
- **
- ** Check to see if output matches ANSWER. Report an error if not.
- */
- if( strcmp(zCmd, "match")==0 ){
- int jj;
- char *zAns = zScript+ii;
- for(jj=7; jj<len-1 && ISSPACE(zAns[jj]); jj++){}
- zAns += jj;
- if( len-jj-1!=sResult.n || strncmp(sResult.z, zAns, len-jj-1) ){
- errorMessage("line %d of %s:\nExpected [%.*s]\n Got [%s]",
- prevLine, zFilename, len-jj-1, zAns, sResult.z);
- }
- g.nTest++;
- stringReset(&sResult);
- }else
-
- /*
- ** --glob ANSWER...
- ** --notglob ANSWER....
- **
- ** Check to see if output does or does not match the glob pattern
- ** ANSWER.
- */
- if( strcmp(zCmd, "glob")==0 || strcmp(zCmd, "notglob")==0 ){
- int jj;
- char *zAns = zScript+ii;
- char *zCopy;
- int isGlob = (zCmd[0]=='g');
- for(jj=9-3*isGlob; jj<len-1 && ISSPACE(zAns[jj]); jj++){}
- zAns += jj;
- zCopy = sqlite3_mprintf("%.*s", len-jj-1, zAns);
- if( (sqlite3_strglob(zCopy, sResult.z)==0)^isGlob ){
- errorMessage("line %d of %s:\nExpected [%s]\n Got [%s]",
- prevLine, zFilename, zCopy, sResult.z);
- }
- sqlite3_free(zCopy);
- g.nTest++;
- stringReset(&sResult);
- }else
-
- /*
- ** --output
- **
- ** Output the result of the previous SQL.
- */
- if( strcmp(zCmd, "output")==0 ){
- logMessage("%s", sResult.z);
- }else
-
- /*
- ** --source FILENAME
- **
- ** Run a subscript from a separate file.
- */
- if( strcmp(zCmd, "source")==0 ){
- char *zNewFile, *zNewScript;
- char *zToDel = 0;
- zNewFile = azArg[0];
- if( !isDirSep(zNewFile[0]) ){
- int k;
- for(k=(int)strlen(zFilename)-1; k>=0 && !isDirSep(zFilename[k]); k--){}
- if( k>0 ){
- zNewFile = zToDel = sqlite3_mprintf("%.*s/%s", k,zFilename,zNewFile);
- }
- }
- zNewScript = readFile(zNewFile);
- if( g.iTrace ) logMessage("begin script [%s]\n", zNewFile);
- runScript(0, 0, zNewScript, zNewFile);
- sqlite3_free(zNewScript);
- if( g.iTrace ) logMessage("end script [%s]\n", zNewFile);
- sqlite3_free(zToDel);
- }else
-
- /*
- ** --print MESSAGE....
- **
- ** Output the remainder of the line to the log file
- */
- if( strcmp(zCmd, "print")==0 ){
- int jj;
- for(jj=7; jj<len && ISSPACE(zScript[ii+jj]); jj++){}
- logMessage("%.*s", len-jj, zScript+ii+jj);
- }else
-
- /*
- ** --if EXPR
- **
- ** Skip forward to the next matching --endif or --else if EXPR is false.
- */
- if( strcmp(zCmd, "if")==0 ){
- int jj, rc;
- sqlite3_stmt *pStmt;
- for(jj=4; jj<len && ISSPACE(zScript[ii+jj]); jj++){}
- pStmt = prepareSql("SELECT %.*s", len-jj, zScript+ii+jj);
- rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW || sqlite3_column_int(pStmt, 0)==0 ){
- ii += findEndif(zScript+ii+len, 1, &lineno);
- }
- sqlite3_finalize(pStmt);
- }else
-
- /*
- ** --else
- **
- ** This command can only be encountered if currently inside an --if that
- ** is true. Skip forward to the next matching --endif.
- */
- if( strcmp(zCmd, "else")==0 ){
- ii += findEndif(zScript+ii+len, 0, &lineno);
- }else
-
- /*
- ** --endif
- **
- ** This command can only be encountered if currently inside an --if that
- ** is true or an --else of a false if. This is a no-op.
- */
- if( strcmp(zCmd, "endif")==0 ){
- /* no-op */
- }else
-
- /*
- ** --start CLIENT
- **
- ** Start up the given client.
- */
- if( strcmp(zCmd, "start")==0 && iClient==0 ){
- int iNewClient = atoi(azArg[0]);
- if( iNewClient>0 ){
- startClient(iNewClient);
- }
- }else
-
- /*
- ** --wait CLIENT TIMEOUT
- **
- ** Wait until all tasks complete for the given client. If CLIENT is
- ** "all" then wait for all clients to complete. Wait no longer than
- ** TIMEOUT milliseconds (default 10,000)
- */
- if( strcmp(zCmd, "wait")==0 && iClient==0 ){
- int iTimeout = nArg>=2 ? atoi(azArg[1]) : 10000;
- sqlite3_snprintf(sizeof(zError),zError,"line %d of %s\n",
- prevLine, zFilename);
- waitForClient(atoi(azArg[0]), iTimeout, zError);
- }else
-
- /*
- ** --task CLIENT
- ** <task-content-here>
- ** --end
- **
- ** Assign work to a client. Start the client if it is not running
- ** already.
- */
- if( strcmp(zCmd, "task")==0 && iClient==0 ){
- int iTarget = atoi(azArg[0]);
- int iEnd;
- char *zTask;
- char *zTName;
- iEnd = findEnd(zScript+ii+len, &lineno);
- if( iTarget<0 ){
- errorMessage("line %d of %s: bad client number: %d",
- prevLine, zFilename, iTarget);
- }else{
- zTask = sqlite3_mprintf("%.*s", iEnd, zScript+ii+len);
- if( nArg>1 ){
- zTName = sqlite3_mprintf("%s", azArg[1]);
- }else{
- zTName = sqlite3_mprintf("%s:%d", filenameTail(zFilename), prevLine);
- }
- startClient(iTarget);
- runSql("INSERT INTO task(client,script,name)"
- " VALUES(%d,'%q',%Q)", iTarget, zTask, zTName);
- sqlite3_free(zTask);
- sqlite3_free(zTName);
- }
- iEnd += tokenLength(zScript+ii+len+iEnd, &lineno);
- len += iEnd;
- iBegin = ii+len;
- }else
-
- /*
- ** --breakpoint
- **
- ** This command calls "test_breakpoint()" which is a routine provided
- ** as a convenient place to set a debugger breakpoint.
- */
- if( strcmp(zCmd, "breakpoint")==0 ){
- test_breakpoint();
- }else
-
- /*
- ** --show-sql-errors BOOLEAN
- **
- ** Turn display of SQL errors on and off.
- */
- if( strcmp(zCmd, "show-sql-errors")==0 ){
- g.bIgnoreSqlErrors = nArg>=1 ? !booleanValue(azArg[0]) : 1;
- }else
-
-
- /* error */{
- errorMessage("line %d of %s: unknown command --%s",
- prevLine, zFilename, zCmd);
- }
- ii += len;
- }
- if( iBegin<ii ){
- char *zSql = sqlite3_mprintf("%.*s", ii-iBegin, zScript+iBegin);
- runSql(zSql);
- sqlite3_free(zSql);
- }
- stringFree(&sResult);
-}
-
-/*
-** Look for a command-line option. If present, return a pointer.
-** Return NULL if missing.
-**
-** hasArg==0 means the option is a flag. It is either present or not.
-** hasArg==1 means the option has an argument. Return a pointer to the
-** argument.
-*/
-static char *findOption(
- char **azArg,
- int *pnArg,
- const char *zOption,
- int hasArg
-){
- int i, j;
- char *zReturn = 0;
- int nArg = *pnArg;
-
- assert( hasArg==0 || hasArg==1 );
- for(i=0; i<nArg; i++){
- const char *z;
- if( i+hasArg >= nArg ) break;
- z = azArg[i];
- if( z[0]!='-' ) continue;
- z++;
- if( z[0]=='-' ){
- if( z[1]==0 ) break;
- z++;
- }
- if( strcmp(z,zOption)==0 ){
- if( hasArg && i==nArg-1 ){
- fatalError("command-line option \"--%s\" requires an argument", z);
- }
- if( hasArg ){
- zReturn = azArg[i+1];
- }else{
- zReturn = azArg[i];
- }
- j = i+1+(hasArg!=0);
- while( j<nArg ) azArg[i++] = azArg[j++];
- *pnArg = i;
- return zReturn;
- }
- }
- return zReturn;
-}
-
-/* Print a usage message for the program and exit */
-static void usage(const char *argv0){
- int i;
- const char *zTail = argv0;
- for(i=0; argv0[i]; i++){
- if( isDirSep(argv0[i]) ) zTail = argv0+i+1;
- }
- fprintf(stderr,"Usage: %s DATABASE ?OPTIONS? ?SCRIPT?\n", zTail);
- fprintf(stderr,
- "Options:\n"
- " --errlog FILENAME Write errors to FILENAME\n"
- " --journalmode MODE Use MODE as the journal_mode\n"
- " --log FILENAME Log messages to FILENAME\n"
- " --quiet Suppress unnecessary output\n"
- " --vfs NAME Use NAME as the VFS\n"
- " --repeat N Repeat the test N times\n"
- " --sqltrace Enable SQL tracing\n"
- " --sync Enable synchronous disk writes\n"
- " --timeout MILLISEC Busy timeout is MILLISEC\n"
- " --trace BOOLEAN Enable or disable tracing\n"
- );
- exit(1);
-}
-
-/* Report on unrecognized arguments */
-static void unrecognizedArguments(
- const char *argv0,
- int nArg,
- char **azArg
-){
- int i;
- fprintf(stderr,"%s: unrecognized arguments:", argv0);
- for(i=0; i<nArg; i++){
- fprintf(stderr," %s", azArg[i]);
- }
- fprintf(stderr,"\n");
- exit(1);
-}
-
-int SQLITE_CDECL main(int argc, char **argv){
- const char *zClient;
- int iClient;
- int n, i;
- int openFlags = SQLITE_OPEN_READWRITE;
- int rc;
- char *zScript;
- int taskId;
- const char *zTrace;
- const char *zCOption;
- const char *zJMode;
- const char *zNRep;
- int nRep = 1, iRep;
- int iTmout = 0; /* Default: no timeout */
- const char *zTmout;
-
- g.argv0 = argv[0];
- g.iTrace = 1;
- if( argc<2 ) usage(argv[0]);
- g.zDbFile = argv[1];
- if( strglob("*.test", g.zDbFile) ) usage(argv[0]);
- if( strcmp(sqlite3_sourceid(), SQLITE_SOURCE_ID)!=0 ){
- fprintf(stderr, "SQLite library and header mismatch\n"
- "Library: %s\n"
- "Header: %s\n",
- sqlite3_sourceid(), SQLITE_SOURCE_ID);
- exit(1);
- }
- n = argc-2;
- sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.mptest", GETPID());
- zJMode = findOption(argv+2, &n, "journalmode", 1);
- zNRep = findOption(argv+2, &n, "repeat", 1);
- if( zNRep ) nRep = atoi(zNRep);
- if( nRep<1 ) nRep = 1;
- g.zVfs = findOption(argv+2, &n, "vfs", 1);
- zClient = findOption(argv+2, &n, "client", 1);
- g.zErrLog = findOption(argv+2, &n, "errlog", 1);
- g.zLog = findOption(argv+2, &n, "log", 1);
- zTrace = findOption(argv+2, &n, "trace", 1);
- if( zTrace ) g.iTrace = atoi(zTrace);
- if( findOption(argv+2, &n, "quiet", 0)!=0 ) g.iTrace = 0;
- zTmout = findOption(argv+2, &n, "timeout", 1);
- if( zTmout ) iTmout = atoi(zTmout);
- g.bSqlTrace = findOption(argv+2, &n, "sqltrace", 0)!=0;
- g.bSync = findOption(argv+2, &n, "sync", 0)!=0;
- if( g.zErrLog ){
- g.pErrLog = fopen(g.zErrLog, "a");
- }else{
- g.pErrLog = stderr;
- }
- if( g.zLog ){
- g.pLog = fopen(g.zLog, "a");
- }else{
- g.pLog = stdout;
- }
-
- sqlite3_config(SQLITE_CONFIG_LOG, sqlErrorCallback, 0);
- if( zClient ){
- iClient = atoi(zClient);
- if( iClient<1 ) fatalError("illegal client number: %d\n", iClient);
- sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.client%02d",
- GETPID(), iClient);
- }else{
- int nTry = 0;
- if( g.iTrace>0 ){
- printf("BEGIN: %s", argv[0]);
- for(i=1; i<argc; i++) printf(" %s", argv[i]);
- printf("\n");
- printf("With SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\n" );
- for(i=0; (zCOption = sqlite3_compileoption_get(i))!=0; i++){
- printf("-DSQLITE_%s\n", zCOption);
- }
- fflush(stdout);
- }
- iClient = 0;
- do{
- if( (nTry%5)==4 ) printf("... %strying to unlink '%s'\n",
- nTry>5 ? "still " : "", g.zDbFile);
- rc = unlink(g.zDbFile);
- if( rc && errno==ENOENT ) rc = 0;
- }while( rc!=0 && (++nTry)<60 && sqlite3_sleep(1000)>0 );
- if( rc!=0 ){
- fatalError("unable to unlink '%s' after %d attempts\n",
- g.zDbFile, nTry);
- }
- openFlags |= SQLITE_OPEN_CREATE;
- }
- rc = sqlite3_open_v2(g.zDbFile, &g.db, openFlags, g.zVfs);
- if( rc ) fatalError("cannot open [%s]", g.zDbFile);
- if( iTmout>0 ) sqlite3_busy_timeout(g.db, iTmout);
-
- if( zJMode ){
-#if defined(_WIN32)
- if( sqlite3_stricmp(zJMode,"persist")==0
- || sqlite3_stricmp(zJMode,"truncate")==0
- ){
- printf("Changing journal mode to DELETE from %s", zJMode);
- zJMode = "DELETE";
- }
-#endif
- runSql("PRAGMA journal_mode=%Q;", zJMode);
- }
- if( !g.bSync ) trySql("PRAGMA synchronous=OFF");
- sqlite3_enable_load_extension(g.db, 1);
- sqlite3_busy_handler(g.db, busyHandler, 0);
- sqlite3_create_function(g.db, "vfsname", 0, SQLITE_UTF8, 0,
- vfsNameFunc, 0, 0);
- sqlite3_create_function(g.db, "eval", 1, SQLITE_UTF8, 0,
- evalFunc, 0, 0);
- g.iTimeout = DEFAULT_TIMEOUT;
- if( g.bSqlTrace ) sqlite3_trace(g.db, sqlTraceCallback, 0);
- if( iClient>0 ){
- if( n>0 ) unrecognizedArguments(argv[0], n, argv+2);
- if( g.iTrace ) logMessage("start-client");
- while(1){
- char *zTaskName = 0;
- rc = startScript(iClient, &zScript, &taskId, &zTaskName);
- if( rc==SQLITE_DONE ) break;
- if( g.iTrace ) logMessage("begin %s (%d)", zTaskName, taskId);
- runScript(iClient, taskId, zScript, zTaskName);
- if( g.iTrace ) logMessage("end %s (%d)", zTaskName, taskId);
- finishScript(iClient, taskId, 0);
- sqlite3_free(zTaskName);
- sqlite3_sleep(10);
- }
- if( g.iTrace ) logMessage("end-client");
- }else{
- sqlite3_stmt *pStmt;
- int iTimeout;
- if( n==0 ){
- fatalError("missing script filename");
- }
- if( n>1 ) unrecognizedArguments(argv[0], n, argv+2);
- runSql(
- "DROP TABLE IF EXISTS task;\n"
- "DROP TABLE IF EXISTS counters;\n"
- "DROP TABLE IF EXISTS client;\n"
- "CREATE TABLE task(\n"
- " id INTEGER PRIMARY KEY,\n"
- " name TEXT,\n"
- " client INTEGER,\n"
- " starttime DATE,\n"
- " endtime DATE,\n"
- " script TEXT\n"
- ");"
- "CREATE INDEX task_i1 ON task(client, starttime);\n"
- "CREATE INDEX task_i2 ON task(client, endtime);\n"
- "CREATE TABLE counters(nError,nTest);\n"
- "INSERT INTO counters VALUES(0,0);\n"
- "CREATE TABLE client(id INTEGER PRIMARY KEY, wantHalt);\n"
- );
- zScript = readFile(argv[2]);
- for(iRep=1; iRep<=nRep; iRep++){
- if( g.iTrace ) logMessage("begin script [%s] cycle %d\n", argv[2], iRep);
- runScript(0, 0, zScript, argv[2]);
- if( g.iTrace ) logMessage("end script [%s] cycle %d\n", argv[2], iRep);
- }
- sqlite3_free(zScript);
- waitForClient(0, 2000, "during shutdown...\n");
- trySql("UPDATE client SET wantHalt=1");
- sqlite3_sleep(10);
- g.iTimeout = 0;
- iTimeout = 1000;
- while( ((rc = trySql("SELECT 1 FROM client"))==SQLITE_BUSY
- || rc==SQLITE_ROW) && iTimeout>0 ){
- sqlite3_sleep(10);
- iTimeout -= 10;
- }
- sqlite3_sleep(100);
- pStmt = prepareSql("SELECT nError, nTest FROM counters");
- iTimeout = 1000;
- while( (rc = sqlite3_step(pStmt))==SQLITE_BUSY && iTimeout>0 ){
- sqlite3_sleep(10);
- iTimeout -= 10;
- }
- if( rc==SQLITE_ROW ){
- g.nError += sqlite3_column_int(pStmt, 0);
- g.nTest += sqlite3_column_int(pStmt, 1);
- }
- sqlite3_finalize(pStmt);
- }
- sqlite3_close(g.db);
- maybeClose(g.pLog);
- maybeClose(g.pErrLog);
- if( iClient==0 ){
- printf("Summary: %d errors out of %d tests\n", g.nError, g.nTest);
- printf("END: %s", argv[0]);
- for(i=1; i<argc; i++) printf(" %s", argv[i]);
- printf("\n");
- }
- return g.nError>0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/multiwrite01.test b/chromium/third_party/sqlite/sqlite-src-3240000/mptest/multiwrite01.test
deleted file mode 100644
index 7062ae0d51b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/mptest/multiwrite01.test
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
-** This script sets up five different tasks all writing and updating
-** the database at the same time, but each in its own table.
-*/
---task 1 build-t1
- DROP TABLE IF EXISTS t1;
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- --sleep 1
- INSERT INTO t1 VALUES(1, randomblob(2000));
- INSERT INTO t1 VALUES(2, randomblob(1000));
- --sleep 1
- INSERT INTO t1 SELECT a+2, randomblob(1500) FROM t1;
- INSERT INTO t1 SELECT a+4, randomblob(1500) FROM t1;
- INSERT INTO t1 SELECT a+8, randomblob(1500) FROM t1;
- --sleep 1
- INSERT INTO t1 SELECT a+16, randomblob(1500) FROM t1;
- --sleep 1
- INSERT INTO t1 SELECT a+32, randomblob(1500) FROM t1;
- SELECT count(*) FROM t1;
- --match 64
- SELECT avg(length(b)) FROM t1;
- --match 1500.0
- --sleep 2
- UPDATE t1 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t1;
- --match 247
- SELECT a FROM t1 WHERE b='x17y';
- --match 17
- CREATE INDEX t1b ON t1(b);
- SELECT a FROM t1 WHERE b='x17y';
- --match 17
- SELECT a FROM t1 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
-
-
---task 2 build-t2
- DROP TABLE IF EXISTS t2;
- CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
- --sleep 1
- INSERT INTO t2 VALUES(1, randomblob(2000));
- INSERT INTO t2 VALUES(2, randomblob(1000));
- --sleep 1
- INSERT INTO t2 SELECT a+2, randomblob(1500) FROM t2;
- INSERT INTO t2 SELECT a+4, randomblob(1500) FROM t2;
- INSERT INTO t2 SELECT a+8, randomblob(1500) FROM t2;
- --sleep 1
- INSERT INTO t2 SELECT a+16, randomblob(1500) FROM t2;
- --sleep 1
- INSERT INTO t2 SELECT a+32, randomblob(1500) FROM t2;
- SELECT count(*) FROM t2;
- --match 64
- SELECT avg(length(b)) FROM t2;
- --match 1500.0
- --sleep 2
- UPDATE t2 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t2;
- --match 247
- SELECT a FROM t2 WHERE b='x17y';
- --match 17
- CREATE INDEX t2b ON t2(b);
- SELECT a FROM t2 WHERE b='x17y';
- --match 17
- SELECT a FROM t2 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
-
---task 3 build-t3
- DROP TABLE IF EXISTS t3;
- CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
- --sleep 1
- INSERT INTO t3 VALUES(1, randomblob(2000));
- INSERT INTO t3 VALUES(2, randomblob(1000));
- --sleep 1
- INSERT INTO t3 SELECT a+2, randomblob(1500) FROM t3;
- INSERT INTO t3 SELECT a+4, randomblob(1500) FROM t3;
- INSERT INTO t3 SELECT a+8, randomblob(1500) FROM t3;
- --sleep 1
- INSERT INTO t3 SELECT a+16, randomblob(1500) FROM t3;
- --sleep 1
- INSERT INTO t3 SELECT a+32, randomblob(1500) FROM t3;
- SELECT count(*) FROM t3;
- --match 64
- SELECT avg(length(b)) FROM t3;
- --match 1500.0
- --sleep 2
- UPDATE t3 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t3;
- --match 247
- SELECT a FROM t3 WHERE b='x17y';
- --match 17
- CREATE INDEX t3b ON t3(b);
- SELECT a FROM t3 WHERE b='x17y';
- --match 17
- SELECT a FROM t3 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
-
---task 4 build-t4
- DROP TABLE IF EXISTS t4;
- CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
- --sleep 1
- INSERT INTO t4 VALUES(1, randomblob(2000));
- INSERT INTO t4 VALUES(2, randomblob(1000));
- --sleep 1
- INSERT INTO t4 SELECT a+2, randomblob(1500) FROM t4;
- INSERT INTO t4 SELECT a+4, randomblob(1500) FROM t4;
- INSERT INTO t4 SELECT a+8, randomblob(1500) FROM t4;
- --sleep 1
- INSERT INTO t4 SELECT a+16, randomblob(1500) FROM t4;
- --sleep 1
- INSERT INTO t4 SELECT a+32, randomblob(1500) FROM t4;
- SELECT count(*) FROM t4;
- --match 64
- SELECT avg(length(b)) FROM t4;
- --match 1500.0
- --sleep 2
- UPDATE t4 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t4;
- --match 247
- SELECT a FROM t4 WHERE b='x17y';
- --match 17
- CREATE INDEX t4b ON t4(b);
- SELECT a FROM t4 WHERE b='x17y';
- --match 17
- SELECT a FROM t4 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
-
---task 5 build-t5
- DROP TABLE IF EXISTS t5;
- CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
- --sleep 1
- INSERT INTO t5 VALUES(1, randomblob(2000));
- INSERT INTO t5 VALUES(2, randomblob(1000));
- --sleep 1
- INSERT INTO t5 SELECT a+2, randomblob(1500) FROM t5;
- INSERT INTO t5 SELECT a+4, randomblob(1500) FROM t5;
- INSERT INTO t5 SELECT a+8, randomblob(1500) FROM t5;
- --sleep 1
- INSERT INTO t5 SELECT a+16, randomblob(1500) FROM t5;
- --sleep 1
- INSERT INTO t5 SELECT a+32, randomblob(1500) FROM t5;
- SELECT count(*) FROM t5;
- --match 64
- SELECT avg(length(b)) FROM t5;
- --match 1500.0
- --sleep 2
- UPDATE t5 SET b='x'||a||'y';
- SELECT sum(length(b)) FROM t5;
- --match 247
- SELECT a FROM t5 WHERE b='x17y';
- --match 17
- CREATE INDEX t5b ON t5(b);
- SELECT a FROM t5 WHERE b='x17y';
- --match 17
- SELECT a FROM t5 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
- --match 29 28 27 26 25
---end
-
---wait all
-SELECT count(*), sum(length(b)) FROM t1;
---match 64 247
-SELECT count(*), sum(length(b)) FROM t2;
---match 64 247
-SELECT count(*), sum(length(b)) FROM t3;
---match 64 247
-SELECT count(*), sum(length(b)) FROM t4;
---match 64 247
-SELECT count(*), sum(length(b)) FROM t5;
---match 64 247
-
---task 1
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---task 5
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---task 3
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---task 2
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---task 4
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---wait all
-
---task 5
- DROP INDEX t5b;
- --sleep 5
- PRAGMA integrity_check(10);
- --match ok
- CREATE INDEX t5b ON t5(b DESC);
---end
---task 3
- DROP INDEX t3b;
- --sleep 5
- PRAGMA integrity_check(10);
- --match ok
- CREATE INDEX t3b ON t3(b DESC);
---end
---task 1
- DROP INDEX t1b;
- --sleep 5
- PRAGMA integrity_check(10);
- --match ok
- CREATE INDEX t1b ON t1(b DESC);
---end
---task 2
- DROP INDEX t2b;
- --sleep 5
- PRAGMA integrity_check(10);
- --match ok
- CREATE INDEX t2b ON t2(b DESC);
---end
---task 4
- DROP INDEX t4b;
- --sleep 5
- PRAGMA integrity_check(10);
- --match ok
- CREATE INDEX t4b ON t4(b DESC);
---end
---wait all
-
---task 1
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---task 5
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---task 3
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---task 2
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---task 4
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
---end
---wait all
-
-VACUUM;
-PRAGMA integrity_check(10);
---match ok
-
---task 1
- UPDATE t1 SET b=randomblob(20000);
- --sleep 5
- UPDATE t1 SET b='x'||a||'y';
- SELECT a FROM t1 WHERE b='x63y';
- --match 63
---end
---task 2
- UPDATE t2 SET b=randomblob(20000);
- --sleep 5
- UPDATE t2 SET b='x'||a||'y';
- SELECT a FROM t2 WHERE b='x63y';
- --match 63
---end
---task 3
- UPDATE t3 SET b=randomblob(20000);
- --sleep 5
- UPDATE t3 SET b='x'||a||'y';
- SELECT a FROM t3 WHERE b='x63y';
- --match 63
---end
---task 4
- UPDATE t4 SET b=randomblob(20000);
- --sleep 5
- UPDATE t4 SET b='x'||a||'y';
- SELECT a FROM t4 WHERE b='x63y';
- --match 63
---end
---task 5
- UPDATE t5 SET b=randomblob(20000);
- --sleep 5
- UPDATE t5 SET b='x'||a||'y';
- SELECT a FROM t5 WHERE b='x63y';
- --match 63
---end
---wait all
-
---task 1
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
- PRAGMA integrity_check;
- --match ok
---end
---task 5
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
- PRAGMA integrity_check;
- --match ok
---end
---task 3
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
- PRAGMA integrity_check;
- --match ok
---end
---task 2
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
- PRAGMA integrity_check;
- --match ok
---end
---task 4
- SELECT t1.a FROM t1, t2
- WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
- ORDER BY t1.a LIMIT 4
- --match 33 34 35 36
- SELECT t3.a FROM t3, t4
- WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
- ORDER BY t3.a LIMIT 7
- --match 45 46 47 48 49 50 51
- PRAGMA integrity_check;
- --match ok
---end
---wait all
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/spec.template b/chromium/third_party/sqlite/sqlite-src-3240000/spec.template
deleted file mode 100644
index 6cc7ab2eabe..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/spec.template
+++ /dev/null
@@ -1,67 +0,0 @@
-%define name sqlite
-%define version SQLITE_VERSION
-%define release 1
-
-Name: %{name}
-Summary: SQLite is a C library that implements an embeddable SQL database engine
-Version: %{version}
-Release: %{release}
-Source: %{name}-%{version}.tar.gz
-Group: System/Libraries
-URL: http://www.sqlite.org/
-License: Public Domain
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-
-%description
-SQLite is a software library that implements a self-contained, serverless,
-zero-configuration, transactional SQL database engine.
-Programs that link with the SQLite library can have SQL database access
-without running a separate RDBMS process. The distribution comes with a
-standalone command-line access program (sqlite) that can be used to
-administer an SQLite database and which serves as an example of how to
-use the SQLite library.
-
-%package -n %{name}-devel
-Summary: Header files and libraries for developing apps which will use sqlite
-Group: Development/C
-Requires: %{name} = %{version}-%{release}
-
-%description -n %{name}-devel
-The sqlite-devel package contains the header files and libraries needed
-to develop programs that use the SQLite database library.
-
-%prep
-%setup -q -n %{name}
-
-%build
-CFLAGS="%optflags -DNDEBUG=1" CXXFLAGS="%optflags -DNDEBUG=1" ./configure --prefix=%{_prefix}
-
-make
-make doc
-
-%install
-install -d $RPM_BUILD_ROOT/%{_prefix}
-install -d $RPM_BUILD_ROOT/%{_prefix}/bin
-install -d $RPM_BUILD_ROOT/%{_prefix}/include
-install -d $RPM_BUILD_ROOT/%{_prefix}/lib
-make install prefix=$RPM_BUILD_ROOT/%{_prefix}
-
-%post -p /sbin/ldconfig
-
-%postun -p /sbin/ldconfig
-
-%clean
-rm -fr $RPM_BUILD_ROOT
-
-%files
-%defattr(-, root, root)
-%{_libdir}/*.so*
-%{_bindir}/*
-
-%files -n %{name}-devel
-%defattr(-, root, root)
-%{_libdir}/pkgconfig/sqlite3.pc
-%{_libdir}/*.a
-%{_libdir}/*.la
-%{_includedir}/*
-%doc doc/*
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/sqlite.pc.in b/chromium/third_party/sqlite/sqlite-src-3240000/sqlite.pc.in
deleted file mode 100644
index d3c944928bc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/sqlite.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-# Package Information for pkg-config
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: SQLite
-Description: SQL database engine
-Version: @RELEASE@
-Libs: -L${libdir} -lsqlite
-Libs.private: @LIBS@
-Cflags: -I${includedir}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/sqlite3.1 b/chromium/third_party/sqlite/sqlite-src-3240000/sqlite3.1
deleted file mode 100644
index 80353b0eecd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/sqlite3.1
+++ /dev/null
@@ -1,286 +0,0 @@
-.\" Hey, EMACS: -*- nroff -*-
-.\" First parameter, NAME, should be all caps
-.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
-.\" other parameters are allowed: see man(7), man(1)
-.TH SQLITE3 1 "Fri Oct 31 10:41:31 EDT 2014"
-.\" Please adjust this date whenever revising the manpage.
-.\"
-.\" Some roff macros, for reference:
-.\" .nh disable hyphenation
-.\" .hy enable hyphenation
-.\" .ad l left justify
-.\" .ad b justify to both left and right margins
-.\" .nf disable filling
-.\" .fi enable filling
-.\" .br insert line break
-.\" .sp <n> insert n+1 empty lines
-.\" for manpage-specific macros, see man(7)
-.SH NAME
-.B sqlite3
-\- A command line interface for SQLite version 3
-
-.SH SYNOPSIS
-.B sqlite3
-.RI [ options ]
-.RI [ databasefile ]
-.RI [ SQL ]
-
-.SH SUMMARY
-.PP
-.B sqlite3
-is a terminal-based front-end to the SQLite library that can evaluate
-queries interactively and display the results in multiple formats.
-.B sqlite3
-can also be used within shell scripts and other applications to provide
-batch processing features.
-
-.SH DESCRIPTION
-To start a
-.B sqlite3
-interactive session, invoke the
-.B sqlite3
-command and optionally provide the name of a database file. If the
-database file does not exist, it will be created. If the database file
-does exist, it will be opened.
-
-For example, to create a new database file named "mydata.db", create
-a table named "memos" and insert a couple of records into that table:
-.sp
-$
-.B sqlite3 mydata.db
-.br
-SQLite version 3.8.8
-.br
-Enter ".help" for instructions
-.br
-sqlite>
-.B create table memos(text, priority INTEGER);
-.br
-sqlite>
-.B insert into memos values('deliver project description', 10);
-.br
-sqlite>
-.B insert into memos values('lunch with Christine', 100);
-.br
-sqlite>
-.B select * from memos;
-.br
-deliver project description|10
-.br
-lunch with Christine|100
-.br
-sqlite>
-.sp
-
-If no database name is supplied, the ATTACH sql command can be used
-to attach to existing or create new database files. ATTACH can also
-be used to attach to multiple databases within the same interactive
-session. This is useful for migrating data between databases,
-possibly changing the schema along the way.
-
-Optionally, a SQL statement or set of SQL statements can be supplied as
-a single argument. Multiple statements should be separated by
-semi-colons.
-
-For example:
-.sp
-$
-.B sqlite3 -line mydata.db 'select * from memos where priority > 20;'
-.br
- text = lunch with Christine
-.br
-priority = 100
-.br
-.sp
-
-.SS SQLITE META-COMMANDS
-.PP
-The interactive interpreter offers a set of meta-commands that can be
-used to control the output format, examine the currently attached
-database files, or perform administrative operations upon the
-attached databases (such as rebuilding indices). Meta-commands are
-always prefixed with a dot (.).
-
-A list of available meta-commands can be viewed at any time by issuing
-the '.help' command. For example:
-.sp
-sqlite>
-.B .help
-.nf
-.tr %.
-%backup ?DB? FILE Backup DB (default "main") to FILE
-%bail on|off Stop after hitting an error. Default OFF
-%clone NEWDB Clone data into NEWDB from the existing database
-%databases List names and files of attached databases
-%dump ?TABLE? ... Dump the database in an SQL text format
- If TABLE specified, only dump tables matching
- LIKE pattern TABLE.
-%echo on|off Turn command echo on or off
-%eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN
-%exit Exit this program
-%explain ?on|off? Turn output mode suitable for EXPLAIN on or off.
- With no args, it turns EXPLAIN on.
-%fullschema Show schema and the content of sqlite_stat tables
-%headers on|off Turn display of headers on or off
-%help Show this message
-%import FILE TABLE Import data from FILE into TABLE
-%indices ?TABLE? Show names of all indices
- If TABLE specified, only show indices for tables
- matching LIKE pattern TABLE.
-%load FILE ?ENTRY? Load an extension library
-%log FILE|off Turn logging on or off. FILE can be stderr/stdout
-%mode MODE ?TABLE? Set output mode where MODE is one of:
- csv Comma-separated values
- column Left-aligned columns. (See .width)
- html HTML <table> code
- insert SQL insert statements for TABLE
- line One value per line
- list Values delimited by .separator string
- tabs Tab-separated values
- tcl TCL list elements
-%nullvalue STRING Use STRING in place of NULL values
-%once FILENAME Output for the next SQL command only to FILENAME
-%open ?FILENAME? Close existing database and reopen FILENAME
-%output ?FILENAME? Send output to FILENAME or stdout
-%print STRING... Print literal STRING
-%prompt MAIN CONTINUE Replace the standard prompts
-%quit Exit this program
-%read FILENAME Execute SQL in FILENAME
-%restore ?DB? FILE Restore content of DB (default "main") from FILE
-%save FILE Write in-memory database into FILE
-%schema ?TABLE? Show the CREATE statements
- If TABLE specified, only show tables matching
- LIKE pattern TABLE.
-%separator STRING ?NL? Change separator used by output mode and .import
- NL is the end-of-line mark for CSV
-%shell CMD ARGS... Run CMD ARGS... in a system shell
-%show Show the current values for various settings
-%stats on|off Turn stats on or off
-%system CMD ARGS... Run CMD ARGS... in a system shell
-%tables ?TABLE? List names of tables
- If TABLE specified, only list tables matching
- LIKE pattern TABLE.
-%timeout MS Try opening locked tables for MS milliseconds
-%timer on|off Turn SQL timer on or off
-%trace FILE|off Output each SQL statement as it is run
-%vfsname ?AUX? Print the name of the VFS stack
-%width NUM1 NUM2 ... Set column widths for "column" mode
- Negative values right-justify
-sqlite>
-.sp
-.fi
-.SH OPTIONS
-.B sqlite3
-has the following options:
-.TP
-.B \-bail
-Stop after hitting an error.
-.TP
-.B \-batch
-Force batch I/O.
-.TP
-.B \-column
-Query results will be displayed in a table like form, using
-whitespace characters to separate the columns and align the
-output.
-.TP
-.BI \-cmd\ command
-run
-.I command
-before reading stdin
-.TP
-.B \-csv
-Set output mode to CSV (comma separated values).
-.TP
-.B \-echo
-Print commands before execution.
-.TP
-.BI \-init\ file
-Read and execute commands from
-.I file
-, which can contain a mix of SQL statements and meta-commands.
-.TP
-.B \-[no]header
-Turn headers on or off.
-.TP
-.B \-help
-Show help on options and exit.
-.TP
-.B \-html
-Query results will be output as simple HTML tables.
-.TP
-.B \-interactive
-Force interactive I/O.
-.TP
-.B \-line
-Query results will be displayed with one value per line, rows
-separated by a blank line. Designed to be easily parsed by
-scripts or other programs
-.TP
-.B \-list
-Query results will be displayed with the separator (|, by default)
-character between each field value. The default.
-.TP
-.BI \-mmap\ N
-Set default mmap size to
-.I N
-\.
-.TP
-.BI \-nullvalue\ string
-Set string used to represent NULL values. Default is ''
-(empty string).
-.TP
-.BI \-separator\ separator
-Set output field separator. Default is '|'.
-.TP
-.B \-stats
-Print memory stats before each finalize.
-.TP
-.B \-version
-Show SQLite version.
-.TP
-.BI \-vfs\ name
-Use
-.I name
-as the default VFS.
-
-
-.SH INIT FILE
-.B sqlite3
-reads an initialization file to set the configuration of the
-interactive environment. Throughout initialization, any previously
-specified setting can be overridden. The sequence of initialization is
-as follows:
-
-o The default configuration is established as follows:
-
-.sp
-.nf
-.cc |
-mode = LIST
-separator = "|"
-main prompt = "sqlite> "
-continue prompt = " ...> "
-|cc .
-.sp
-.fi
-
-o If the file
-.B ~/.sqliterc
-exists, it is processed first.
-can be found in the user's home directory, it is
-read and processed. It should generally only contain meta-commands.
-
-o If the -init option is present, the specified file is processed.
-
-o All other command line options are processed.
-
-.SH SEE ALSO
-http://www.sqlite.org/cli.html
-.br
-The sqlite3-doc package.
-.SH AUTHOR
-This manual page was originally written by Andreas Rottmann
-<rotty@debian.org>, for the Debian GNU/Linux system (but may be used
-by others). It was subsequently revised by Bill Bumgarner <bbum@mac.com> and
-further updated by Laszlo Boszormenyi <gcs@debian.hu> .
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/sqlite3.pc.in b/chromium/third_party/sqlite/sqlite-src-3240000/sqlite3.pc.in
deleted file mode 100644
index 3799671e613..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/sqlite3.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-# Package Information for pkg-config
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: SQLite
-Description: SQL database engine
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -lsqlite3
-Libs.private: @LIBS@
-Cflags: -I${includedir}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/alter.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/alter.c
deleted file mode 100644
index 51d4a40067e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/alter.c
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
-** 2005 February 15
-**
-** 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 contains C code routines that used to generate VDBE code
-** that implements the ALTER TABLE command.
-*/
-#include "sqliteInt.h"
-
-/*
-** The code in this file only exists if we are not omitting the
-** ALTER TABLE logic from the build.
-*/
-#ifndef SQLITE_OMIT_ALTERTABLE
-
-
-/*
-** This function is used by SQL generated to implement the
-** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
-** CREATE INDEX command. The second is a table name. The table name in
-** the CREATE TABLE or CREATE INDEX statement is replaced with the third
-** argument and the result returned. Examples:
-**
-** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
-** -> 'CREATE TABLE def(a, b, c)'
-**
-** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
-** -> 'CREATE INDEX i ON def(a, b, c)'
-*/
-static void renameTableFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- unsigned char const *zSql = sqlite3_value_text(argv[0]);
- unsigned char const *zTableName = sqlite3_value_text(argv[1]);
-
- int token;
- Token tname;
- unsigned char const *zCsr = zSql;
- int len = 0;
- char *zRet;
-
- sqlite3 *db = sqlite3_context_db_handle(context);
-
- UNUSED_PARAMETER(NotUsed);
-
- /* The principle used to locate the table name in the CREATE TABLE
- ** statement is that the table name is the first non-space token that
- ** is immediately followed by a TK_LP or TK_USING token.
- */
- if( zSql ){
- do {
- if( !*zCsr ){
- /* Ran out of input before finding an opening bracket. Return NULL. */
- return;
- }
-
- /* Store the token that zCsr points to in tname. */
- tname.z = (char*)zCsr;
- tname.n = len;
-
- /* Advance zCsr to the next token. Store that token type in 'token',
- ** and its length in 'len' (to be used next iteration of this loop).
- */
- do {
- zCsr += len;
- len = sqlite3GetToken(zCsr, &token);
- } while( token==TK_SPACE );
- assert( len>0 );
- } while( token!=TK_LP && token!=TK_USING );
-
- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
- zSql, zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
- }
-}
-
-/*
-** This C function implements an SQL user function that is used by SQL code
-** generated by the ALTER TABLE ... RENAME command to modify the definition
-** of any foreign key constraints that use the table being renamed as the
-** parent table. It is passed three arguments:
-**
-** 1) The complete text of the CREATE TABLE statement being modified,
-** 2) The old name of the table being renamed, and
-** 3) The new name of the table being renamed.
-**
-** It returns the new CREATE TABLE statement. For example:
-**
-** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3')
-** -> 'CREATE TABLE t1(a REFERENCES t3)'
-*/
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-static void renameParentFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- char *zOutput = 0;
- char *zResult;
- unsigned char const *zInput = sqlite3_value_text(argv[0]);
- unsigned char const *zOld = sqlite3_value_text(argv[1]);
- unsigned char const *zNew = sqlite3_value_text(argv[2]);
-
- unsigned const char *z; /* Pointer to token */
- int n; /* Length of token z */
- int token; /* Type of token */
-
- UNUSED_PARAMETER(NotUsed);
- if( zInput==0 || zOld==0 ) return;
- for(z=zInput; *z; z=z+n){
- n = sqlite3GetToken(z, &token);
- if( token==TK_REFERENCES ){
- char *zParent;
- do {
- z += n;
- n = sqlite3GetToken(z, &token);
- }while( token==TK_SPACE );
-
- if( token==TK_ILLEGAL ) break;
- zParent = sqlite3DbStrNDup(db, (const char *)z, n);
- if( zParent==0 ) break;
- sqlite3Dequote(zParent);
- if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){
- char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
- (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew
- );
- sqlite3DbFree(db, zOutput);
- zOutput = zOut;
- zInput = &z[n];
- }
- sqlite3DbFree(db, zParent);
- }
- }
-
- zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
- sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC);
- sqlite3DbFree(db, zOutput);
-}
-#endif
-
-#ifndef SQLITE_OMIT_TRIGGER
-/* This function is used by SQL generated to implement the
-** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
-** statement. The second is a table name. The table name in the CREATE
-** TRIGGER statement is replaced with the third argument and the result
-** returned. This is analagous to renameTableFunc() above, except for CREATE
-** TRIGGER, not CREATE INDEX and CREATE TABLE.
-*/
-static void renameTriggerFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- unsigned char const *zSql = sqlite3_value_text(argv[0]);
- unsigned char const *zTableName = sqlite3_value_text(argv[1]);
-
- int token;
- Token tname;
- int dist = 3;
- unsigned char const *zCsr = zSql;
- int len = 0;
- char *zRet;
- sqlite3 *db = sqlite3_context_db_handle(context);
-
- UNUSED_PARAMETER(NotUsed);
-
- /* The principle used to locate the table name in the CREATE TRIGGER
- ** statement is that the table name is the first token that is immediately
- ** preceded by either TK_ON or TK_DOT and immediately followed by one
- ** of TK_WHEN, TK_BEGIN or TK_FOR.
- */
- if( zSql ){
- do {
-
- if( !*zCsr ){
- /* Ran out of input before finding the table name. Return NULL. */
- return;
- }
-
- /* Store the token that zCsr points to in tname. */
- tname.z = (char*)zCsr;
- tname.n = len;
-
- /* Advance zCsr to the next token. Store that token type in 'token',
- ** and its length in 'len' (to be used next iteration of this loop).
- */
- do {
- zCsr += len;
- len = sqlite3GetToken(zCsr, &token);
- }while( token==TK_SPACE );
- assert( len>0 );
-
- /* Variable 'dist' stores the number of tokens read since the most
- ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
- ** token is read and 'dist' equals 2, the condition stated above
- ** to be met.
- **
- ** Note that ON cannot be a database, table or column name, so
- ** there is no need to worry about syntax like
- ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
- */
- dist++;
- if( token==TK_DOT || token==TK_ON ){
- dist = 0;
- }
- } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
-
- /* Variable tname now contains the token that is the old table-name
- ** in the CREATE TRIGGER statement.
- */
- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
- zSql, zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
- }
-}
-#endif /* !SQLITE_OMIT_TRIGGER */
-
-/*
-** Register built-in functions used to help implement ALTER TABLE
-*/
-void sqlite3AlterFunctions(void){
- static FuncDef aAlterTableFuncs[] = {
- FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc),
-#ifndef SQLITE_OMIT_TRIGGER
- FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
-#endif
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc),
-#endif
- };
- sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
-}
-
-/*
-** This function is used to create the text of expressions of the form:
-**
-** name=<constant1> OR name=<constant2> OR ...
-**
-** If argument zWhere is NULL, then a pointer string containing the text
-** "name=<constant>" is returned, where <constant> is the quoted version
-** of the string passed as argument zConstant. The returned buffer is
-** allocated using sqlite3DbMalloc(). It is the responsibility of the
-** caller to ensure that it is eventually freed.
-**
-** If argument zWhere is not NULL, then the string returned is
-** "<where> OR name=<constant>", where <where> is the contents of zWhere.
-** In this case zWhere is passed to sqlite3DbFree() before returning.
-**
-*/
-static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){
- char *zNew;
- if( !zWhere ){
- zNew = sqlite3MPrintf(db, "name=%Q", zConstant);
- }else{
- zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant);
- sqlite3DbFree(db, zWhere);
- }
- return zNew;
-}
-
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-/*
-** Generate the text of a WHERE expression which can be used to select all
-** tables that have foreign key constraints that refer to table pTab (i.e.
-** constraints for which pTab is the parent table) from the sqlite_master
-** table.
-*/
-static char *whereForeignKeys(Parse *pParse, Table *pTab){
- FKey *p;
- char *zWhere = 0;
- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName);
- }
- return zWhere;
-}
-#endif
-
-/*
-** Generate the text of a WHERE expression which can be used to select all
-** temporary triggers on table pTab from the sqlite_temp_master table. If
-** table pTab has no temporary triggers, or is itself stored in the
-** temporary database, NULL is returned.
-*/
-static char *whereTempTriggers(Parse *pParse, Table *pTab){
- Trigger *pTrig;
- char *zWhere = 0;
- const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
-
- /* If the table is not located in the temp-db (in which case NULL is
- ** returned, loop through the tables list of triggers. For each trigger
- ** that is not part of the temp-db schema, add a clause to the WHERE
- ** expression being built up in zWhere.
- */
- if( pTab->pSchema!=pTempSchema ){
- sqlite3 *db = pParse->db;
- for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
- if( pTrig->pSchema==pTempSchema ){
- zWhere = whereOrName(db, zWhere, pTrig->zName);
- }
- }
- }
- if( zWhere ){
- char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere);
- sqlite3DbFree(pParse->db, zWhere);
- zWhere = zNew;
- }
- return zWhere;
-}
-
-/*
-** Generate code to drop and reload the internal representation of table
-** pTab from the database, including triggers and temporary triggers.
-** Argument zName is the name of the table in the database schema at
-** the time the generated code is executed. This can be different from
-** pTab->zName if this function is being called to code part of an
-** "ALTER TABLE RENAME TO" statement.
-*/
-static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
- Vdbe *v;
- char *zWhere;
- int iDb; /* Index of database containing pTab */
-#ifndef SQLITE_OMIT_TRIGGER
- Trigger *pTrig;
-#endif
-
- v = sqlite3GetVdbe(pParse);
- if( NEVER(v==0) ) return;
- assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 );
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* Drop any table triggers from the internal schema. */
- for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
- int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
- assert( iTrigDb==iDb || iTrigDb==1 );
- sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0);
- }
-#endif
-
- /* Drop the table and index from the internal schema. */
- sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
-
- /* Reload the table, index and permanent trigger schemas. */
- zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
- if( !zWhere ) return;
- sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* Now, if the table is not stored in the temp database, reload any temp
- ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
- */
- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3VdbeAddParseSchemaOp(v, 1, zWhere);
- }
-#endif
-}
-
-/*
-** Parameter zName is the name of a table that is about to be altered
-** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
-** If the table is a system table, this function leaves an error message
-** in pParse->zErr (system tables may not be altered) and returns non-zero.
-**
-** Or, if zName is not a system table, zero is returned.
-*/
-static int isSystemTable(Parse *pParse, const char *zName){
- if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
- sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
- return 1;
- }
- return 0;
-}
-
-/*
-** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
-** command.
-*/
-void sqlite3AlterRenameTable(
- Parse *pParse, /* Parser context. */
- SrcList *pSrc, /* The table to rename. */
- Token *pName /* The new table name. */
-){
- int iDb; /* Database that contains the table */
- char *zDb; /* Name of database iDb */
- Table *pTab; /* Table being renamed */
- char *zName = 0; /* NULL-terminated version of pName */
- sqlite3 *db = pParse->db; /* Database connection */
- int nTabName; /* Number of UTF-8 characters in zTabName */
- const char *zTabName; /* Original name of the table */
- Vdbe *v;
-#ifndef SQLITE_OMIT_TRIGGER
- char *zWhere = 0; /* Where clause to locate temp triggers */
-#endif
- VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
- u32 savedDbFlags; /* Saved value of db->mDbFlags */
-
- savedDbFlags = db->mDbFlags;
- if( NEVER(db->mallocFailed) ) goto exit_rename_table;
- assert( pSrc->nSrc==1 );
- assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
-
- pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
- if( !pTab ) goto exit_rename_table;
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- zDb = db->aDb[iDb].zDbSName;
- db->mDbFlags |= DBFLAG_PreferBuiltin;
-
- /* Get a NULL terminated version of the new table name. */
- zName = sqlite3NameFromToken(db, pName);
- if( !zName ) goto exit_rename_table;
-
- /* Check that a table or index named 'zName' does not already exist
- ** in database iDb. If so, this is an error.
- */
- if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
- sqlite3ErrorMsg(pParse,
- "there is already another table or index with this name: %s", zName);
- goto exit_rename_table;
- }
-
- /* Make sure it is not a system table being altered, or a reserved name
- ** that the table is being renamed to.
- */
- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
- goto exit_rename_table;
- }
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
- exit_rename_table;
- }
-
-#ifndef SQLITE_OMIT_VIEW
- if( pTab->pSelect ){
- sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
- goto exit_rename_table;
- }
-#endif
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- /* Invoke the authorization callback. */
- if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
- goto exit_rename_table;
- }
-#endif
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( sqlite3ViewGetColumnNames(pParse, pTab) ){
- goto exit_rename_table;
- }
- if( IsVirtual(pTab) ){
- pVTab = sqlite3GetVTable(db, pTab);
- if( pVTab->pVtab->pModule->xRename==0 ){
- pVTab = 0;
- }
- }
-#endif
-
- /* Begin a transaction for database iDb.
- ** Then modify the schema cookie (since the ALTER TABLE modifies the
- ** schema). Open a statement transaction if the table is a virtual
- ** table.
- */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ){
- goto exit_rename_table;
- }
- sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb);
- sqlite3ChangeCookie(pParse, iDb);
-
- /* If this is a virtual table, invoke the xRename() function if
- ** one is defined. The xRename() callback will modify the names
- ** of any resources used by the v-table implementation (including other
- ** SQLite tables) that are identified by the name of the virtual table.
- */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pVTab ){
- int i = ++pParse->nMem;
- sqlite3VdbeLoadString(v, i, zName);
- sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
- sqlite3MayAbort(pParse);
- }
-#endif
-
- /* figure out how many UTF-8 characters are in zName */
- zTabName = pTab->zName;
- nTabName = sqlite3Utf8CharLen(zTabName, -1);
-
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- if( db->flags&SQLITE_ForeignKeys ){
- /* If foreign-key support is enabled, rewrite the CREATE TABLE
- ** statements corresponding to all child tables of foreign key constraints
- ** for which the renamed table is the parent table. */
- if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
- "UPDATE \"%w\".%s SET "
- "sql = sqlite_rename_parent(sql, %Q, %Q) "
- "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere);
- sqlite3DbFree(db, zWhere);
- }
- }
-#endif
-
- /* Modify the sqlite_master table to use the new table name. */
- sqlite3NestedParse(pParse,
- "UPDATE %Q.%s SET "
-#ifdef SQLITE_OMIT_TRIGGER
- "sql = sqlite_rename_table(sql, %Q), "
-#else
- "sql = CASE "
- "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
- "ELSE sqlite_rename_table(sql, %Q) END, "
-#endif
- "tbl_name = %Q, "
- "name = CASE "
- "WHEN type='table' THEN %Q "
- "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
- "'sqlite_autoindex_' || %Q || substr(name,%d+18) "
- "ELSE name END "
- "WHERE tbl_name=%Q COLLATE nocase AND "
- "(type='table' OR type='index' OR type='trigger');",
- zDb, MASTER_NAME, zName, zName, zName,
-#ifndef SQLITE_OMIT_TRIGGER
- zName,
-#endif
- zName, nTabName, zTabName
- );
-
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- /* If the sqlite_sequence table exists in this database, then update
- ** it with the new table name.
- */
- if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
- sqlite3NestedParse(pParse,
- "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q",
- zDb, zName, pTab->zName);
- }
-#endif
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* If there are TEMP triggers on this table, modify the sqlite_temp_master
- ** table. Don't do this if the table being ALTERed is itself located in
- ** the temp database.
- */
- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
- "UPDATE sqlite_temp_master SET "
- "sql = sqlite_rename_trigger(sql, %Q), "
- "tbl_name = %Q "
- "WHERE %s;", zName, zName, zWhere);
- sqlite3DbFree(db, zWhere);
- }
-#endif
-
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- if( db->flags&SQLITE_ForeignKeys ){
- FKey *p;
- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- Table *pFrom = p->pFrom;
- if( pFrom!=pTab ){
- reloadTableSchema(pParse, p->pFrom, pFrom->zName);
- }
- }
- }
-#endif
-
- /* Drop and reload the internal table schema. */
- reloadTableSchema(pParse, pTab, zName);
-
-exit_rename_table:
- sqlite3SrcListDelete(db, pSrc);
- sqlite3DbFree(db, zName);
- db->mDbFlags = savedDbFlags;
-}
-
-/*
-** This function is called after an "ALTER TABLE ... ADD" statement
-** has been parsed. Argument pColDef contains the text of the new
-** column definition.
-**
-** The Table structure pParse->pNewTable was extended to include
-** the new column during parsing.
-*/
-void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
- Table *pNew; /* Copy of pParse->pNewTable */
- Table *pTab; /* Table being altered */
- int iDb; /* Database number */
- const char *zDb; /* Database name */
- const char *zTab; /* Table name */
- char *zCol; /* Null-terminated column definition */
- Column *pCol; /* The new column */
- Expr *pDflt; /* Default value for the new column */
- sqlite3 *db; /* The database connection; */
- Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
- int r1; /* Temporary registers */
-
- db = pParse->db;
- if( pParse->nErr || db->mallocFailed ) return;
- assert( v!=0 );
- pNew = pParse->pNewTable;
- assert( pNew );
-
- assert( sqlite3BtreeHoldsAllMutexes(db) );
- iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
- zDb = db->aDb[iDb].zDbSName;
- zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
- pCol = &pNew->aCol[pNew->nCol-1];
- pDflt = pCol->pDflt;
- pTab = sqlite3FindTable(db, zTab, zDb);
- assert( pTab );
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- /* Invoke the authorization callback. */
- if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
- return;
- }
-#endif
-
- /* If the default value for the new column was specified with a
- ** literal NULL, then set pDflt to 0. This simplifies checking
- ** for an SQL NULL default below.
- */
- assert( pDflt==0 || pDflt->op==TK_SPAN );
- if( pDflt && pDflt->pLeft->op==TK_NULL ){
- pDflt = 0;
- }
-
- /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
- ** If there is a NOT NULL constraint, then the default value for the
- ** column must not be NULL.
- */
- if( pCol->colFlags & COLFLAG_PRIMKEY ){
- sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
- return;
- }
- if( pNew->pIndex ){
- sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
- return;
- }
- if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
- sqlite3ErrorMsg(pParse,
- "Cannot add a REFERENCES column with non-NULL default value");
- return;
- }
- if( pCol->notNull && !pDflt ){
- sqlite3ErrorMsg(pParse,
- "Cannot add a NOT NULL column with default value NULL");
- return;
- }
-
- /* Ensure the default expression is something that sqlite3ValueFromExpr()
- ** can handle (i.e. not CURRENT_TIME etc.)
- */
- if( pDflt ){
- sqlite3_value *pVal = 0;
- int rc;
- rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
- if( rc!=SQLITE_OK ){
- assert( db->mallocFailed == 1 );
- return;
- }
- if( !pVal ){
- sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
- return;
- }
- sqlite3ValueFree(pVal);
- }
-
- /* Modify the CREATE TABLE statement. */
- zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
- if( zCol ){
- char *zEnd = &zCol[pColDef->n-1];
- u32 savedDbFlags = db->mDbFlags;
- while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
- *zEnd-- = '\0';
- }
- db->mDbFlags |= DBFLAG_PreferBuiltin;
- sqlite3NestedParse(pParse,
- "UPDATE \"%w\".%s SET "
- "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
- "WHERE type = 'table' AND name = %Q",
- zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1,
- zTab
- );
- sqlite3DbFree(db, zCol);
- db->mDbFlags = savedDbFlags;
- }
-
- /* Make sure the schema version is at least 3. But do not upgrade
- ** from less than 3 to 4, as that will corrupt any preexisting DESC
- ** index.
- */
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
- sqlite3VdbeUsesBtree(v, iDb);
- sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
- sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
- sqlite3ReleaseTempReg(pParse, r1);
-
- /* Reload the schema of the modified table. */
- reloadTableSchema(pParse, pTab, pTab->zName);
-}
-
-/*
-** This function is called by the parser after the table-name in
-** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
-** pSrc is the full-name of the table being altered.
-**
-** This routine makes a (partial) copy of the Table structure
-** for the table being altered and sets Parse.pNewTable to point
-** to it. Routines called by the parser as the column definition
-** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
-** the copy. The copy of the Table structure is deleted by tokenize.c
-** after parsing is finished.
-**
-** Routine sqlite3AlterFinishAddColumn() will be called to complete
-** coding the "ALTER TABLE ... ADD" statement.
-*/
-void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
- Table *pNew;
- Table *pTab;
- Vdbe *v;
- int iDb;
- int i;
- int nAlloc;
- sqlite3 *db = pParse->db;
-
- /* Look up the table being altered. */
- assert( pParse->pNewTable==0 );
- assert( sqlite3BtreeHoldsAllMutexes(db) );
- if( db->mallocFailed ) goto exit_begin_add_column;
- pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
- if( !pTab ) goto exit_begin_add_column;
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab) ){
- sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
- goto exit_begin_add_column;
- }
-#endif
-
- /* Make sure this is not an attempt to ALTER a view. */
- if( pTab->pSelect ){
- sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
- goto exit_begin_add_column;
- }
- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
- goto exit_begin_add_column;
- }
-
- assert( pTab->addColOffset>0 );
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
-
- /* Put a copy of the Table struct in Parse.pNewTable for the
- ** sqlite3AddColumn() function and friends to modify. But modify
- ** the name by adding an "sqlite_altertab_" prefix. By adding this
- ** prefix, we insure that the name will not collide with an existing
- ** table because user table are not allowed to have the "sqlite_"
- ** prefix on their name.
- */
- pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
- if( !pNew ) goto exit_begin_add_column;
- pParse->pNewTable = pNew;
- pNew->nTabRef = 1;
- pNew->nCol = pTab->nCol;
- assert( pNew->nCol>0 );
- nAlloc = (((pNew->nCol-1)/8)*8)+8;
- assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
- pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
- pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
- if( !pNew->aCol || !pNew->zName ){
- assert( db->mallocFailed );
- goto exit_begin_add_column;
- }
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
- for(i=0; i<pNew->nCol; i++){
- Column *pCol = &pNew->aCol[i];
- pCol->zName = sqlite3DbStrDup(db, pCol->zName);
- pCol->zColl = 0;
- pCol->pDflt = 0;
- }
- pNew->pSchema = db->aDb[iDb].pSchema;
- pNew->addColOffset = pTab->addColOffset;
- pNew->nTabRef = 1;
-
- /* Begin a transaction and increment the schema cookie. */
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- v = sqlite3GetVdbe(pParse);
- if( !v ) goto exit_begin_add_column;
- sqlite3ChangeCookie(pParse, iDb);
-
-exit_begin_add_column:
- sqlite3SrcListDelete(db, pSrc);
- return;
-}
-#endif /* SQLITE_ALTER_TABLE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/analyze.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/analyze.c
deleted file mode 100644
index 48fd4951c45..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/analyze.c
+++ /dev/null
@@ -1,1936 +0,0 @@
-/*
-** 2005-07-08
-**
-** 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 contains code associated with the ANALYZE command.
-**
-** The ANALYZE command gather statistics about the content of tables
-** and indices. These statistics are made available to the query planner
-** to help it make better decisions about how to perform queries.
-**
-** The following system tables are or have been supported:
-**
-** CREATE TABLE sqlite_stat1(tbl, idx, stat);
-** CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample);
-** CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
-** CREATE TABLE sqlite_stat4(tbl, idx, nEq, nLt, nDLt, sample);
-**
-** Additional tables might be added in future releases of SQLite.
-** The sqlite_stat2 table is not created or used unless the SQLite version
-** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
-** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated.
-** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
-** created and used by SQLite versions 3.7.9 and later and with
-** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
-** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
-** version of sqlite_stat3 and is only available when compiled with
-** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is
-** not possible to enable both STAT3 and STAT4 at the same time. If they
-** are both enabled, then STAT4 takes precedence.
-**
-** For most applications, sqlite_stat1 provides all the statistics required
-** for the query planner to make good choices.
-**
-** Format of sqlite_stat1:
-**
-** There is normally one row per index, with the index identified by the
-** name in the idx column. The tbl column is the name of the table to
-** which the index belongs. In each such row, the stat column will be
-** a string consisting of a list of integers. The first integer in this
-** list is the number of rows in the index. (This is the same as the
-** number of rows in the table, except for partial indices.) The second
-** integer is the average number of rows in the index that have the same
-** value in the first column of the index. The third integer is the average
-** number of rows in the index that have the same value for the first two
-** columns. The N-th integer (for N>1) is the average number of rows in
-** the index which have the same value for the first N-1 columns. For
-** a K-column index, there will be K+1 integers in the stat column. If
-** the index is unique, then the last integer will be 1.
-**
-** The list of integers in the stat column can optionally be followed
-** by the keyword "unordered". The "unordered" keyword, if it is present,
-** must be separated from the last integer by a single space. If the
-** "unordered" keyword is present, then the query planner assumes that
-** the index is unordered and will not use the index for a range query.
-**
-** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
-** column contains a single integer which is the (estimated) number of
-** rows in the table identified by sqlite_stat1.tbl.
-**
-** Format of sqlite_stat2:
-**
-** The sqlite_stat2 is only created and is only used if SQLite is compiled
-** with SQLITE_ENABLE_STAT2 and if the SQLite version number is between
-** 3.6.18 and 3.7.8. The "stat2" table contains additional information
-** about the distribution of keys within an index. The index is identified by
-** the "idx" column and the "tbl" column is the name of the table to which
-** the index belongs. There are usually 10 rows in the sqlite_stat2
-** table for each index.
-**
-** The sqlite_stat2 entries for an index that have sampleno between 0 and 9
-** inclusive are samples of the left-most key value in the index taken at
-** evenly spaced points along the index. Let the number of samples be S
-** (10 in the standard build) and let C be the number of rows in the index.
-** Then the sampled rows are given by:
-**
-** rownumber = (i*C*2 + C)/(S*2)
-**
-** For i between 0 and S-1. Conceptually, the index space is divided into
-** S uniform buckets and the samples are the middle row from each bucket.
-**
-** The format for sqlite_stat2 is recorded here for legacy reference. This
-** version of SQLite does not support sqlite_stat2. It neither reads nor
-** writes the sqlite_stat2 table. This version of SQLite only supports
-** sqlite_stat3.
-**
-** Format for sqlite_stat3:
-**
-** The sqlite_stat3 format is a subset of sqlite_stat4. Hence, the
-** sqlite_stat4 format will be described first. Further information
-** about sqlite_stat3 follows the sqlite_stat4 description.
-**
-** Format for sqlite_stat4:
-**
-** As with sqlite_stat2, the sqlite_stat4 table contains histogram data
-** to aid the query planner in choosing good indices based on the values
-** that indexed columns are compared against in the WHERE clauses of
-** queries.
-**
-** The sqlite_stat4 table contains multiple entries for each index.
-** The idx column names the index and the tbl column is the table of the
-** index. If the idx and tbl columns are the same, then the sample is
-** of the INTEGER PRIMARY KEY. The sample column is a blob which is the
-** binary encoding of a key from the index. The nEq column is a
-** list of integers. The first integer is the approximate number
-** of entries in the index whose left-most column exactly matches
-** the left-most column of the sample. The second integer in nEq
-** is the approximate number of entries in the index where the
-** first two columns match the first two columns of the sample.
-** And so forth. nLt is another list of integers that show the approximate
-** number of entries that are strictly less than the sample. The first
-** integer in nLt contains the number of entries in the index where the
-** left-most column is less than the left-most column of the sample.
-** The K-th integer in the nLt entry is the number of index entries
-** where the first K columns are less than the first K columns of the
-** sample. The nDLt column is like nLt except that it contains the
-** number of distinct entries in the index that are less than the
-** sample.
-**
-** There can be an arbitrary number of sqlite_stat4 entries per index.
-** The ANALYZE command will typically generate sqlite_stat4 tables
-** that contain between 10 and 40 samples which are distributed across
-** the key space, though not uniformly, and which include samples with
-** large nEq values.
-**
-** Format for sqlite_stat3 redux:
-**
-** The sqlite_stat3 table is like sqlite_stat4 except that it only
-** looks at the left-most column of the index. The sqlite_stat3.sample
-** column contains the actual value of the left-most column instead
-** of a blob encoding of the complete index key as is found in
-** sqlite_stat4.sample. The nEq, nLt, and nDLt entries of sqlite_stat3
-** all contain just a single integer which is the same as the first
-** integer in the equivalent columns in sqlite_stat4.
-*/
-#ifndef SQLITE_OMIT_ANALYZE
-#include "sqliteInt.h"
-
-#if defined(SQLITE_ENABLE_STAT4)
-# define IsStat4 1
-# define IsStat3 0
-#elif defined(SQLITE_ENABLE_STAT3)
-# define IsStat4 0
-# define IsStat3 1
-#else
-# define IsStat4 0
-# define IsStat3 0
-# undef SQLITE_STAT4_SAMPLES
-# define SQLITE_STAT4_SAMPLES 1
-#endif
-#define IsStat34 (IsStat3+IsStat4) /* 1 for STAT3 or STAT4. 0 otherwise */
-
-/*
-** This routine generates code that opens the sqlite_statN tables.
-** The sqlite_stat1 table is always relevant. sqlite_stat2 is now
-** obsolete. sqlite_stat3 and sqlite_stat4 are only opened when
-** appropriate compile-time options are provided.
-**
-** If the sqlite_statN tables do not previously exist, it is created.
-**
-** Argument zWhere may be a pointer to a buffer containing a table name,
-** or it may be a NULL pointer. If it is not NULL, then all entries in
-** the sqlite_statN tables associated with the named table are deleted.
-** If zWhere==0, then code is generated to delete all stat table entries.
-*/
-static void openStatTable(
- Parse *pParse, /* Parsing context */
- int iDb, /* The database we are looking in */
- int iStatCur, /* Open the sqlite_stat1 table on this cursor */
- const char *zWhere, /* Delete entries for this table or index */
- const char *zWhereType /* Either "tbl" or "idx" */
-){
- static const struct {
- const char *zName;
- const char *zCols;
- } aTable[] = {
- { "sqlite_stat1", "tbl,idx,stat" },
-#if defined(SQLITE_ENABLE_STAT4)
- { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
- { "sqlite_stat3", 0 },
-#elif defined(SQLITE_ENABLE_STAT3)
- { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
- { "sqlite_stat4", 0 },
-#else
- { "sqlite_stat3", 0 },
- { "sqlite_stat4", 0 },
-#endif
- };
- int i;
- sqlite3 *db = pParse->db;
- Db *pDb;
- Vdbe *v = sqlite3GetVdbe(pParse);
- int aRoot[ArraySize(aTable)];
- u8 aCreateTbl[ArraySize(aTable)];
-
- if( v==0 ) return;
- assert( sqlite3BtreeHoldsAllMutexes(db) );
- assert( sqlite3VdbeDb(v)==db );
- pDb = &db->aDb[iDb];
-
- /* Create new statistic tables if they do not exist, or clear them
- ** if they do already exist.
- */
- for(i=0; i<ArraySize(aTable); i++){
- const char *zTab = aTable[i].zName;
- Table *pStat;
- if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
- if( aTable[i].zCols ){
- /* The sqlite_statN table does not exist. Create it. Note that a
- ** side-effect of the CREATE TABLE statement is to leave the rootpage
- ** of the new table in register pParse->regRoot. This is important
- ** because the OpenWrite opcode below will be needing it. */
- sqlite3NestedParse(pParse,
- "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
- );
- aRoot[i] = pParse->regRoot;
- aCreateTbl[i] = OPFLAG_P2ISREG;
- }
- }else{
- /* The table already exists. If zWhere is not NULL, delete all entries
- ** associated with the table zWhere. If zWhere is NULL, delete the
- ** entire contents of the table. */
- aRoot[i] = pStat->tnum;
- aCreateTbl[i] = 0;
- sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
- if( zWhere ){
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE %s=%Q",
- pDb->zDbSName, zTab, zWhereType, zWhere
- );
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- }else if( db->xPreUpdateCallback ){
- sqlite3NestedParse(pParse, "DELETE FROM %Q.%s", pDb->zDbSName, zTab);
-#endif
- }else{
- /* The sqlite_stat[134] table already exists. Delete all rows. */
- sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
- }
- }
- }
-
- /* Open the sqlite_stat[134] tables for writing. */
- for(i=0; aTable[i].zCols; i++){
- assert( i<ArraySize(aTable) );
- sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
- sqlite3VdbeChangeP5(v, aCreateTbl[i]);
- VdbeComment((v, aTable[i].zName));
- }
-}
-
-/*
-** Recommended number of samples for sqlite_stat4
-*/
-#ifndef SQLITE_STAT4_SAMPLES
-# define SQLITE_STAT4_SAMPLES 24
-#endif
-
-/*
-** Three SQL functions - stat_init(), stat_push(), and stat_get() -
-** share an instance of the following structure to hold their state
-** information.
-*/
-typedef struct Stat4Accum Stat4Accum;
-typedef struct Stat4Sample Stat4Sample;
-struct Stat4Sample {
- tRowcnt *anEq; /* sqlite_stat4.nEq */
- tRowcnt *anDLt; /* sqlite_stat4.nDLt */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- tRowcnt *anLt; /* sqlite_stat4.nLt */
- union {
- i64 iRowid; /* Rowid in main table of the key */
- u8 *aRowid; /* Key for WITHOUT ROWID tables */
- } u;
- u32 nRowid; /* Sizeof aRowid[] */
- u8 isPSample; /* True if a periodic sample */
- int iCol; /* If !isPSample, the reason for inclusion */
- u32 iHash; /* Tiebreaker hash */
-#endif
-};
-struct Stat4Accum {
- tRowcnt nRow; /* Number of rows in the entire table */
- tRowcnt nPSample; /* How often to do a periodic sample */
- int nCol; /* Number of columns in index + pk/rowid */
- int nKeyCol; /* Number of index columns w/o the pk/rowid */
- int mxSample; /* Maximum number of samples to accumulate */
- Stat4Sample current; /* Current row as a Stat4Sample */
- u32 iPrn; /* Pseudo-random number used for sampling */
- Stat4Sample *aBest; /* Array of nCol best samples */
- int iMin; /* Index in a[] of entry with minimum score */
- int nSample; /* Current number of samples */
- int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */
- int iGet; /* Index of current sample accessed by stat_get() */
- Stat4Sample *a; /* Array of mxSample Stat4Sample objects */
- sqlite3 *db; /* Database connection, for malloc() */
-};
-
-/* Reclaim memory used by a Stat4Sample
-*/
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-static void sampleClear(sqlite3 *db, Stat4Sample *p){
- assert( db!=0 );
- if( p->nRowid ){
- sqlite3DbFree(db, p->u.aRowid);
- p->nRowid = 0;
- }
-}
-#endif
-
-/* Initialize the BLOB value of a ROWID
-*/
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
- assert( db!=0 );
- if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
- p->u.aRowid = sqlite3DbMallocRawNN(db, n);
- if( p->u.aRowid ){
- p->nRowid = n;
- memcpy(p->u.aRowid, pData, n);
- }else{
- p->nRowid = 0;
- }
-}
-#endif
-
-/* Initialize the INTEGER value of a ROWID.
-*/
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
- assert( db!=0 );
- if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
- p->nRowid = 0;
- p->u.iRowid = iRowid;
-}
-#endif
-
-
-/*
-** Copy the contents of object (*pFrom) into (*pTo).
-*/
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
- pTo->isPSample = pFrom->isPSample;
- pTo->iCol = pFrom->iCol;
- pTo->iHash = pFrom->iHash;
- memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol);
- memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol);
- memcpy(pTo->anDLt, pFrom->anDLt, sizeof(tRowcnt)*p->nCol);
- if( pFrom->nRowid ){
- sampleSetRowid(p->db, pTo, pFrom->nRowid, pFrom->u.aRowid);
- }else{
- sampleSetRowidInt64(p->db, pTo, pFrom->u.iRowid);
- }
-}
-#endif
-
-/*
-** Reclaim all memory of a Stat4Accum structure.
-*/
-static void stat4Destructor(void *pOld){
- Stat4Accum *p = (Stat4Accum*)pOld;
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- int i;
- for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
- for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
- sampleClear(p->db, &p->current);
-#endif
- sqlite3DbFree(p->db, p);
-}
-
-/*
-** Implementation of the stat_init(N,K,C) SQL function. The three parameters
-** are:
-** N: The number of columns in the index including the rowid/pk (note 1)
-** K: The number of columns in the index excluding the rowid/pk.
-** C: The number of rows in the index (note 2)
-**
-** Note 1: In the special case of the covering index that implements a
-** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
-** total number of columns in the table.
-**
-** Note 2: C is only used for STAT3 and STAT4.
-**
-** For indexes on ordinary rowid tables, N==K+1. But for indexes on
-** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
-** PRIMARY KEY of the table. The covering index that implements the
-** original WITHOUT ROWID table as N==K as a special case.
-**
-** This routine allocates the Stat4Accum object in heap memory. The return
-** value is a pointer to the Stat4Accum object. The datatype of the
-** return value is BLOB, but it is really just a pointer to the Stat4Accum
-** object.
-*/
-static void statInit(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- Stat4Accum *p;
- int nCol; /* Number of columns in index being sampled */
- int nKeyCol; /* Number of key columns */
- int nColUp; /* nCol rounded up for alignment */
- int n; /* Bytes of space to allocate */
- sqlite3 *db; /* Database connection */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- int mxSample = SQLITE_STAT4_SAMPLES;
-#endif
-
- /* Decode the three function arguments */
- UNUSED_PARAMETER(argc);
- nCol = sqlite3_value_int(argv[0]);
- assert( nCol>0 );
- nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol;
- nKeyCol = sqlite3_value_int(argv[1]);
- assert( nKeyCol<=nCol );
- assert( nKeyCol>0 );
-
- /* Allocate the space required for the Stat4Accum object */
- n = sizeof(*p)
- + sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */
- + sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- + sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */
- + sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */
- + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
-#endif
- ;
- db = sqlite3_context_db_handle(context);
- p = sqlite3DbMallocZero(db, n);
- if( p==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
-
- p->db = db;
- p->nRow = 0;
- p->nCol = nCol;
- p->nKeyCol = nKeyCol;
- p->current.anDLt = (tRowcnt*)&p[1];
- p->current.anEq = &p->current.anDLt[nColUp];
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- {
- u8 *pSpace; /* Allocated space not yet assigned */
- int i; /* Used to iterate through p->aSample[] */
-
- p->iGet = -1;
- p->mxSample = mxSample;
- p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
- p->current.anLt = &p->current.anEq[nColUp];
- p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
-
- /* Set up the Stat4Accum.a[] and aBest[] arrays */
- p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
- p->aBest = &p->a[mxSample];
- pSpace = (u8*)(&p->a[mxSample+nCol]);
- for(i=0; i<(mxSample+nCol); i++){
- p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
- p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
- p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
- }
- assert( (pSpace - (u8*)p)==n );
-
- for(i=0; i<nCol; i++){
- p->aBest[i].iCol = i;
- }
- }
-#endif
-
- /* Return a pointer to the allocated object to the caller. Note that
- ** only the pointer (the 2nd parameter) matters. The size of the object
- ** (given by the 3rd parameter) is never used and can be any positive
- ** value. */
- sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor);
-}
-static const FuncDef statInitFuncdef = {
- 2+IsStat34, /* nArg */
- SQLITE_UTF8, /* funcFlags */
- 0, /* pUserData */
- 0, /* pNext */
- statInit, /* xSFunc */
- 0, /* xFinalize */
- "stat_init", /* zName */
- {0}
-};
-
-#ifdef SQLITE_ENABLE_STAT4
-/*
-** pNew and pOld are both candidate non-periodic samples selected for
-** the same column (pNew->iCol==pOld->iCol). Ignoring this column and
-** considering only any trailing columns and the sample hash value, this
-** function returns true if sample pNew is to be preferred over pOld.
-** In other words, if we assume that the cardinalities of the selected
-** column for pNew and pOld are equal, is pNew to be preferred over pOld.
-**
-** This function assumes that for each argument sample, the contents of
-** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid.
-*/
-static int sampleIsBetterPost(
- Stat4Accum *pAccum,
- Stat4Sample *pNew,
- Stat4Sample *pOld
-){
- int nCol = pAccum->nCol;
- int i;
- assert( pNew->iCol==pOld->iCol );
- for(i=pNew->iCol+1; i<nCol; i++){
- if( pNew->anEq[i]>pOld->anEq[i] ) return 1;
- if( pNew->anEq[i]<pOld->anEq[i] ) return 0;
- }
- if( pNew->iHash>pOld->iHash ) return 1;
- return 0;
-}
-#endif
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** Return true if pNew is to be preferred over pOld.
-**
-** This function assumes that for each argument sample, the contents of
-** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid.
-*/
-static int sampleIsBetter(
- Stat4Accum *pAccum,
- Stat4Sample *pNew,
- Stat4Sample *pOld
-){
- tRowcnt nEqNew = pNew->anEq[pNew->iCol];
- tRowcnt nEqOld = pOld->anEq[pOld->iCol];
-
- assert( pOld->isPSample==0 && pNew->isPSample==0 );
- assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) );
-
- if( (nEqNew>nEqOld) ) return 1;
-#ifdef SQLITE_ENABLE_STAT4
- if( nEqNew==nEqOld ){
- if( pNew->iCol<pOld->iCol ) return 1;
- return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld));
- }
- return 0;
-#else
- return (nEqNew==nEqOld && pNew->iHash>pOld->iHash);
-#endif
-}
-
-/*
-** Copy the contents of sample *pNew into the p->a[] array. If necessary,
-** remove the least desirable sample from p->a[] to make room.
-*/
-static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
- Stat4Sample *pSample = 0;
- int i;
-
- assert( IsStat4 || nEqZero==0 );
-
-#ifdef SQLITE_ENABLE_STAT4
- /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
- ** values in the anEq[] array of any sample in Stat4Accum.a[]. In
- ** other words, if nMaxEqZero is n, then it is guaranteed that there
- ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
- if( nEqZero>p->nMaxEqZero ){
- p->nMaxEqZero = nEqZero;
- }
- if( pNew->isPSample==0 ){
- Stat4Sample *pUpgrade = 0;
- assert( pNew->anEq[pNew->iCol]>0 );
-
- /* This sample is being added because the prefix that ends in column
- ** iCol occurs many times in the table. However, if we have already
- ** added a sample that shares this prefix, there is no need to add
- ** this one. Instead, upgrade the priority of the highest priority
- ** existing sample that shares this prefix. */
- for(i=p->nSample-1; i>=0; i--){
- Stat4Sample *pOld = &p->a[i];
- if( pOld->anEq[pNew->iCol]==0 ){
- if( pOld->isPSample ) return;
- assert( pOld->iCol>pNew->iCol );
- assert( sampleIsBetter(p, pNew, pOld) );
- if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){
- pUpgrade = pOld;
- }
- }
- }
- if( pUpgrade ){
- pUpgrade->iCol = pNew->iCol;
- pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol];
- goto find_new_min;
- }
- }
-#endif
-
- /* If necessary, remove sample iMin to make room for the new sample. */
- if( p->nSample>=p->mxSample ){
- Stat4Sample *pMin = &p->a[p->iMin];
- tRowcnt *anEq = pMin->anEq;
- tRowcnt *anLt = pMin->anLt;
- tRowcnt *anDLt = pMin->anDLt;
- sampleClear(p->db, pMin);
- memmove(pMin, &pMin[1], sizeof(p->a[0])*(p->nSample-p->iMin-1));
- pSample = &p->a[p->nSample-1];
- pSample->nRowid = 0;
- pSample->anEq = anEq;
- pSample->anDLt = anDLt;
- pSample->anLt = anLt;
- p->nSample = p->mxSample-1;
- }
-
- /* The "rows less-than" for the rowid column must be greater than that
- ** for the last sample in the p->a[] array. Otherwise, the samples would
- ** be out of order. */
-#ifdef SQLITE_ENABLE_STAT4
- assert( p->nSample==0
- || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] );
-#endif
-
- /* Insert the new sample */
- pSample = &p->a[p->nSample];
- sampleCopy(p, pSample, pNew);
- p->nSample++;
-
- /* Zero the first nEqZero entries in the anEq[] array. */
- memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero);
-
-#ifdef SQLITE_ENABLE_STAT4
- find_new_min:
-#endif
- if( p->nSample>=p->mxSample ){
- int iMin = -1;
- for(i=0; i<p->mxSample; i++){
- if( p->a[i].isPSample ) continue;
- if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){
- iMin = i;
- }
- }
- assert( iMin>=0 );
- p->iMin = iMin;
- }
-}
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-
-/*
-** Field iChng of the index being scanned has changed. So at this point
-** p->current contains a sample that reflects the previous row of the
-** index. The value of anEq[iChng] and subsequent anEq[] elements are
-** correct at this point.
-*/
-static void samplePushPrevious(Stat4Accum *p, int iChng){
-#ifdef SQLITE_ENABLE_STAT4
- int i;
-
- /* Check if any samples from the aBest[] array should be pushed
- ** into IndexSample.a[] at this point. */
- for(i=(p->nCol-2); i>=iChng; i--){
- Stat4Sample *pBest = &p->aBest[i];
- pBest->anEq[i] = p->current.anEq[i];
- if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){
- sampleInsert(p, pBest, i);
- }
- }
-
- /* Check that no sample contains an anEq[] entry with an index of
- ** p->nMaxEqZero or greater set to zero. */
- for(i=p->nSample-1; i>=0; i--){
- int j;
- for(j=p->nMaxEqZero; j<p->nCol; j++) assert( p->a[i].anEq[j]>0 );
- }
-
- /* Update the anEq[] fields of any samples already collected. */
- if( iChng<p->nMaxEqZero ){
- for(i=p->nSample-1; i>=0; i--){
- int j;
- for(j=iChng; j<p->nCol; j++){
- if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
- }
- }
- p->nMaxEqZero = iChng;
- }
-#endif
-
-#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
- if( iChng==0 ){
- tRowcnt nLt = p->current.anLt[0];
- tRowcnt nEq = p->current.anEq[0];
-
- /* Check if this is to be a periodic sample. If so, add it. */
- if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){
- p->current.isPSample = 1;
- sampleInsert(p, &p->current, 0);
- p->current.isPSample = 0;
- }else
-
- /* Or if it is a non-periodic sample. Add it in this case too. */
- if( p->nSample<p->mxSample
- || sampleIsBetter(p, &p->current, &p->a[p->iMin])
- ){
- sampleInsert(p, &p->current, 0);
- }
- }
-#endif
-
-#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
- UNUSED_PARAMETER( p );
- UNUSED_PARAMETER( iChng );
-#endif
-}
-
-/*
-** Implementation of the stat_push SQL function: stat_push(P,C,R)
-** Arguments:
-**
-** P Pointer to the Stat4Accum object created by stat_init()
-** C Index of left-most column to differ from previous row
-** R Rowid for the current row. Might be a key record for
-** WITHOUT ROWID tables.
-**
-** This SQL function always returns NULL. It's purpose it to accumulate
-** statistical data and/or samples in the Stat4Accum object about the
-** index being analyzed. The stat_get() SQL function will later be used to
-** extract relevant information for constructing the sqlite_statN tables.
-**
-** The R parameter is only used for STAT3 and STAT4
-*/
-static void statPush(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int i;
-
- /* The three function arguments */
- Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
- int iChng = sqlite3_value_int(argv[1]);
-
- UNUSED_PARAMETER( argc );
- UNUSED_PARAMETER( context );
- assert( p->nCol>0 );
- assert( iChng<p->nCol );
-
- if( p->nRow==0 ){
- /* This is the first call to this function. Do initialization. */
- for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
- }else{
- /* Second and subsequent calls get processed here */
- samplePushPrevious(p, iChng);
-
- /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
- ** to the current row of the index. */
- for(i=0; i<iChng; i++){
- p->current.anEq[i]++;
- }
- for(i=iChng; i<p->nCol; i++){
- p->current.anDLt[i]++;
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- p->current.anLt[i] += p->current.anEq[i];
-#endif
- p->current.anEq[i] = 1;
- }
- }
- p->nRow++;
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
- sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
- }else{
- sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
- sqlite3_value_blob(argv[2]));
- }
- p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
-#endif
-
-#ifdef SQLITE_ENABLE_STAT4
- {
- tRowcnt nLt = p->current.anLt[p->nCol-1];
-
- /* Check if this is to be a periodic sample. If so, add it. */
- if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
- p->current.isPSample = 1;
- p->current.iCol = 0;
- sampleInsert(p, &p->current, p->nCol-1);
- p->current.isPSample = 0;
- }
-
- /* Update the aBest[] array. */
- for(i=0; i<(p->nCol-1); i++){
- p->current.iCol = i;
- if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){
- sampleCopy(p, &p->aBest[i], &p->current);
- }
- }
- }
-#endif
-}
-static const FuncDef statPushFuncdef = {
- 2+IsStat34, /* nArg */
- SQLITE_UTF8, /* funcFlags */
- 0, /* pUserData */
- 0, /* pNext */
- statPush, /* xSFunc */
- 0, /* xFinalize */
- "stat_push", /* zName */
- {0}
-};
-
-#define STAT_GET_STAT1 0 /* "stat" column of stat1 table */
-#define STAT_GET_ROWID 1 /* "rowid" column of stat[34] entry */
-#define STAT_GET_NEQ 2 /* "neq" column of stat[34] entry */
-#define STAT_GET_NLT 3 /* "nlt" column of stat[34] entry */
-#define STAT_GET_NDLT 4 /* "ndlt" column of stat[34] entry */
-
-/*
-** Implementation of the stat_get(P,J) SQL function. This routine is
-** used to query statistical information that has been gathered into
-** the Stat4Accum object by prior calls to stat_push(). The P parameter
-** has type BLOB but it is really just a pointer to the Stat4Accum object.
-** The content to returned is determined by the parameter J
-** which is one of the STAT_GET_xxxx values defined above.
-**
-** The stat_get(P,J) function is not available to generic SQL. It is
-** inserted as part of a manually constructed bytecode program. (See
-** the callStatGet() routine below.) It is guaranteed that the P
-** parameter will always be a poiner to a Stat4Accum object, never a
-** NULL.
-**
-** If neither STAT3 nor STAT4 are enabled, then J is always
-** STAT_GET_STAT1 and is hence omitted and this routine becomes
-** a one-parameter function, stat_get(P), that always returns the
-** stat1 table entry information.
-*/
-static void statGet(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- /* STAT3 and STAT4 have a parameter on this routine. */
- int eCall = sqlite3_value_int(argv[1]);
- assert( argc==2 );
- assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ
- || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
- || eCall==STAT_GET_NDLT
- );
- if( eCall==STAT_GET_STAT1 )
-#else
- assert( argc==1 );
-#endif
- {
- /* Return the value to store in the "stat" column of the sqlite_stat1
- ** table for this index.
- **
- ** The value is a string composed of a list of integers describing
- ** the index. The first integer in the list is the total number of
- ** entries in the index. There is one additional integer in the list
- ** for each indexed column. This additional integer is an estimate of
- ** the number of rows matched by a stabbing query on the index using
- ** a key with the corresponding number of fields. In other words,
- ** if the index is on columns (a,b) and the sqlite_stat1 value is
- ** "100 10 2", then SQLite estimates that:
- **
- ** * the index contains 100 rows,
- ** * "WHERE a=?" matches 10 rows, and
- ** * "WHERE a=? AND b=?" matches 2 rows.
- **
- ** If D is the count of distinct values and K is the total number of
- ** rows, then each estimate is computed as:
- **
- ** I = (K+D-1)/D
- */
- char *z;
- int i;
-
- char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 );
- if( zRet==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
-
- sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
- z = zRet + sqlite3Strlen30(zRet);
- for(i=0; i<p->nKeyCol; i++){
- u64 nDistinct = p->current.anDLt[i] + 1;
- u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
- sqlite3_snprintf(24, z, " %llu", iVal);
- z += sqlite3Strlen30(z);
- assert( p->current.anEq[i] );
- }
- assert( z[0]=='\0' && z>zRet );
-
- sqlite3_result_text(context, zRet, -1, sqlite3_free);
- }
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- else if( eCall==STAT_GET_ROWID ){
- if( p->iGet<0 ){
- samplePushPrevious(p, 0);
- p->iGet = 0;
- }
- if( p->iGet<p->nSample ){
- Stat4Sample *pS = p->a + p->iGet;
- if( pS->nRowid==0 ){
- sqlite3_result_int64(context, pS->u.iRowid);
- }else{
- sqlite3_result_blob(context, pS->u.aRowid, pS->nRowid,
- SQLITE_TRANSIENT);
- }
- }
- }else{
- tRowcnt *aCnt = 0;
-
- assert( p->iGet<p->nSample );
- switch( eCall ){
- case STAT_GET_NEQ: aCnt = p->a[p->iGet].anEq; break;
- case STAT_GET_NLT: aCnt = p->a[p->iGet].anLt; break;
- default: {
- aCnt = p->a[p->iGet].anDLt;
- p->iGet++;
- break;
- }
- }
-
- if( IsStat3 ){
- sqlite3_result_int64(context, (i64)aCnt[0]);
- }else{
- char *zRet = sqlite3MallocZero(p->nCol * 25);
- if( zRet==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- int i;
- char *z = zRet;
- for(i=0; i<p->nCol; i++){
- sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
- z += sqlite3Strlen30(z);
- }
- assert( z[0]=='\0' && z>zRet );
- z[-1] = '\0';
- sqlite3_result_text(context, zRet, -1, sqlite3_free);
- }
- }
- }
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-#ifndef SQLITE_DEBUG
- UNUSED_PARAMETER( argc );
-#endif
-}
-static const FuncDef statGetFuncdef = {
- 1+IsStat34, /* nArg */
- SQLITE_UTF8, /* funcFlags */
- 0, /* pUserData */
- 0, /* pNext */
- statGet, /* xSFunc */
- 0, /* xFinalize */
- "stat_get", /* zName */
- {0}
-};
-
-static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
- assert( regOut!=regStat4 && regOut!=regStat4+1 );
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
-#elif SQLITE_DEBUG
- assert( iParam==STAT_GET_STAT1 );
-#else
- UNUSED_PARAMETER( iParam );
-#endif
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut,
- (char*)&statGetFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 1 + IsStat34);
-}
-
-/*
-** Generate code to do an analysis of all indices associated with
-** a single table.
-*/
-static void analyzeOneTable(
- Parse *pParse, /* Parser context */
- Table *pTab, /* Table whose indices are to be analyzed */
- Index *pOnlyIdx, /* If not NULL, only analyze this one index */
- int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */
- int iMem, /* Available memory locations begin here */
- int iTab /* Next available cursor */
-){
- sqlite3 *db = pParse->db; /* Database handle */
- Index *pIdx; /* An index to being analyzed */
- int iIdxCur; /* Cursor open on index being analyzed */
- int iTabCur; /* Table cursor */
- Vdbe *v; /* The virtual machine being built up */
- int i; /* Loop counter */
- int jZeroRows = -1; /* Jump from here if number of rows is zero */
- int iDb; /* Index of database containing pTab */
- u8 needTableCnt = 1; /* True to count the table */
- int regNewRowid = iMem++; /* Rowid for the inserted record */
- int regStat4 = iMem++; /* Register to hold Stat4Accum object */
- int regChng = iMem++; /* Index of changed index field */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- int regRowid = iMem++; /* Rowid argument passed to stat_push() */
-#endif
- int regTemp = iMem++; /* Temporary use register */
- int regTabname = iMem++; /* Register containing table name */
- int regIdxname = iMem++; /* Register containing index name */
- int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
- int regPrev = iMem; /* MUST BE LAST (see below) */
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- Table *pStat1 = 0;
-#endif
-
- pParse->nMem = MAX(pParse->nMem, iMem);
- v = sqlite3GetVdbe(pParse);
- if( v==0 || NEVER(pTab==0) ){
- return;
- }
- if( pTab->tnum==0 ){
- /* Do not gather statistics on views or virtual tables */
- return;
- }
- if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){
- /* Do not gather statistics on system tables */
- return;
- }
- assert( sqlite3BtreeHoldsAllMutexes(db) );
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDb>=0 );
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
- db->aDb[iDb].zDbSName ) ){
- return;
- }
-#endif
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- if( db->xPreUpdateCallback ){
- pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13);
- if( pStat1==0 ) return;
- pStat1->zName = (char*)&pStat1[1];
- memcpy(pStat1->zName, "sqlite_stat1", 13);
- pStat1->nCol = 3;
- pStat1->iPKey = -1;
- sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB);
- }
-#endif
-
- /* Establish a read-lock on the table at the shared-cache level.
- ** Open a read-only cursor on the table. Also allocate a cursor number
- ** to use for scanning indexes (iIdxCur). No index cursor is opened at
- ** this time though. */
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
- iTabCur = iTab++;
- iIdxCur = iTab++;
- pParse->nTab = MAX(pParse->nTab, iTab);
- sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
- sqlite3VdbeLoadString(v, regTabname, pTab->zName);
-
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int nCol; /* Number of columns in pIdx. "N" */
- int addrRewind; /* Address of "OP_Rewind iIdxCur" */
- int addrNextRow; /* Address of "next_row:" */
- const char *zIdxName; /* Name of the index */
- int nColTest; /* Number of columns to test for changes */
-
- if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
- if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
- if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){
- nCol = pIdx->nKeyCol;
- zIdxName = pTab->zName;
- nColTest = nCol - 1;
- }else{
- nCol = pIdx->nColumn;
- zIdxName = pIdx->zName;
- nColTest = pIdx->uniqNotNull ? pIdx->nKeyCol-1 : nCol-1;
- }
-
- /* Populate the register containing the index name. */
- sqlite3VdbeLoadString(v, regIdxname, zIdxName);
- VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
-
- /*
- ** Pseudo-code for loop that calls stat_push():
- **
- ** Rewind csr
- ** if eof(csr) goto end_of_scan;
- ** regChng = 0
- ** goto chng_addr_0;
- **
- ** next_row:
- ** regChng = 0
- ** if( idx(0) != regPrev(0) ) goto chng_addr_0
- ** regChng = 1
- ** if( idx(1) != regPrev(1) ) goto chng_addr_1
- ** ...
- ** regChng = N
- ** goto chng_addr_N
- **
- ** chng_addr_0:
- ** regPrev(0) = idx(0)
- ** chng_addr_1:
- ** regPrev(1) = idx(1)
- ** ...
- **
- ** endDistinctTest:
- ** regRowid = idx(rowid)
- ** stat_push(P, regChng, regRowid)
- ** Next csr
- ** if !eof(csr) goto next_row;
- **
- ** end_of_scan:
- */
-
- /* Make sure there are enough memory cells allocated to accommodate
- ** the regPrev array and a trailing rowid (the rowid slot is required
- ** when building a record to insert into the sample column of
- ** the sqlite_stat4 table. */
- pParse->nMem = MAX(pParse->nMem, regPrev+nColTest);
-
- /* Open a read-only cursor on the index being analyzed. */
- assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
- sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
- sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
- VdbeComment((v, "%s", pIdx->zName));
-
- /* Invoke the stat_init() function. The arguments are:
- **
- ** (1) the number of columns in the index including the rowid
- ** (or for a WITHOUT ROWID table, the number of PK columns),
- ** (2) the number of columns in the key without the rowid/pk
- ** (3) the number of rows in the index,
- **
- **
- ** The third argument is only used for STAT3 and STAT4
- */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
-#endif
- sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4,
- (char*)&statInitFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 2+IsStat34);
-
- /* Implementation of the following:
- **
- ** Rewind csr
- ** if eof(csr) goto end_of_scan;
- ** regChng = 0
- ** goto next_push_0;
- **
- */
- addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
- VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
- addrNextRow = sqlite3VdbeCurrentAddr(v);
-
- if( nColTest>0 ){
- int endDistinctTest = sqlite3VdbeMakeLabel(v);
- int *aGotoChng; /* Array of jump instruction addresses */
- aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest);
- if( aGotoChng==0 ) continue;
-
- /*
- ** next_row:
- ** regChng = 0
- ** if( idx(0) != regPrev(0) ) goto chng_addr_0
- ** regChng = 1
- ** if( idx(1) != regPrev(1) ) goto chng_addr_1
- ** ...
- ** regChng = N
- ** goto endDistinctTest
- */
- sqlite3VdbeAddOp0(v, OP_Goto);
- addrNextRow = sqlite3VdbeCurrentAddr(v);
- if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){
- /* For a single-column UNIQUE index, once we have found a non-NULL
- ** row, we know that all the rest will be distinct, so skip
- ** subsequent distinctness tests. */
- sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest);
- VdbeCoverage(v);
- }
- for(i=0; i<nColTest; i++){
- char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
- sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
- aGotoChng[i] =
- sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
- sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
- VdbeCoverage(v);
- }
- sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng);
- sqlite3VdbeGoto(v, endDistinctTest);
-
-
- /*
- ** chng_addr_0:
- ** regPrev(0) = idx(0)
- ** chng_addr_1:
- ** regPrev(1) = idx(1)
- ** ...
- */
- sqlite3VdbeJumpHere(v, addrNextRow-1);
- for(i=0; i<nColTest; i++){
- sqlite3VdbeJumpHere(v, aGotoChng[i]);
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
- }
- sqlite3VdbeResolveLabel(v, endDistinctTest);
- sqlite3DbFree(db, aGotoChng);
- }
-
- /*
- ** chng_addr_N:
- ** regRowid = idx(rowid) // STAT34 only
- ** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only
- ** Next csr
- ** if !eof(csr) goto next_row;
- */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- assert( regRowid==(regStat4+2) );
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
- }else{
- Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
- int j, k, regKey;
- regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
- for(j=0; j<pPk->nKeyCol; j++){
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
- assert( k>=0 && k<pIdx->nColumn );
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
- VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
- }
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
- sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
- }
-#endif
- assert( regChng==(regStat4+1) );
- sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp,
- (char*)&statPushFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 2+IsStat34);
- sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
-
- /* Add the entry to the stat1 table. */
- callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
- assert( "BBB"[0]==SQLITE_AFF_TEXT );
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE);
-#endif
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
-
- /* Add the entries to the stat3 or stat4 table. */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- {
- int regEq = regStat1;
- int regLt = regStat1+1;
- int regDLt = regStat1+2;
- int regSample = regStat1+3;
- int regCol = regStat1+4;
- int regSampleRowid = regCol + nCol;
- int addrNext;
- int addrIsNull;
- u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
-
- pParse->nMem = MAX(pParse->nMem, regCol+nCol);
-
- addrNext = sqlite3VdbeCurrentAddr(v);
- callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
- addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
- VdbeCoverage(v);
- callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
- callStatGet(v, regStat4, STAT_GET_NLT, regLt);
- callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
- sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
- /* We know that the regSampleRowid row exists because it was read by
- ** the previous loop. Thus the not-found jump of seekOp will never
- ** be taken */
- VdbeCoverageNeverTaken(v);
-#ifdef SQLITE_ENABLE_STAT3
- sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample);
-#else
- for(i=0; i<nCol; i++){
- sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i);
- }
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample);
-#endif
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
- sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */
- sqlite3VdbeJumpHere(v, addrIsNull);
- }
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-
- /* End of analysis */
- sqlite3VdbeJumpHere(v, addrRewind);
- }
-
-
- /* Create a single sqlite_stat1 entry containing NULL as the index
- ** name and the row count as the content.
- */
- if( pOnlyIdx==0 && needTableCnt ){
- VdbeComment((v, "%s", pTab->zName));
- sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1);
- jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
- assert( "BBB"[0]==SQLITE_AFF_TEXT );
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE);
-#endif
- sqlite3VdbeJumpHere(v, jZeroRows);
- }
-}
-
-
-/*
-** Generate code that will cause the most recent index analysis to
-** be loaded into internal hash tables where is can be used.
-*/
-static void loadAnalysis(Parse *pParse, int iDb){
- Vdbe *v = sqlite3GetVdbe(pParse);
- if( v ){
- sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb);
- }
-}
-
-/*
-** Generate code that will do an analysis of an entire database
-*/
-static void analyzeDatabase(Parse *pParse, int iDb){
- sqlite3 *db = pParse->db;
- Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */
- HashElem *k;
- int iStatCur;
- int iMem;
- int iTab;
-
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- iStatCur = pParse->nTab;
- pParse->nTab += 3;
- openStatTable(pParse, iDb, iStatCur, 0, 0);
- iMem = pParse->nMem+1;
- iTab = pParse->nTab;
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
- Table *pTab = (Table*)sqliteHashData(k);
- analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab);
- }
- loadAnalysis(pParse, iDb);
-}
-
-/*
-** Generate code that will do an analysis of a single table in
-** a database. If pOnlyIdx is not NULL then it is a single index
-** in pTab that should be analyzed.
-*/
-static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){
- int iDb;
- int iStatCur;
-
- assert( pTab!=0 );
- assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- iStatCur = pParse->nTab;
- pParse->nTab += 3;
- if( pOnlyIdx ){
- openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx");
- }else{
- openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl");
- }
- analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur,pParse->nMem+1,pParse->nTab);
- loadAnalysis(pParse, iDb);
-}
-
-/*
-** Generate code for the ANALYZE command. The parser calls this routine
-** when it recognizes an ANALYZE command.
-**
-** ANALYZE -- 1
-** ANALYZE <database> -- 2
-** ANALYZE ?<database>.?<tablename> -- 3
-**
-** Form 1 causes all indices in all attached databases to be analyzed.
-** Form 2 analyzes all indices the single database named.
-** Form 3 analyzes all indices associated with the named table.
-*/
-void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
- sqlite3 *db = pParse->db;
- int iDb;
- int i;
- char *z, *zDb;
- Table *pTab;
- Index *pIdx;
- Token *pTableName;
- Vdbe *v;
-
- /* Read the database schema. If an error occurs, leave an error message
- ** and code in pParse and return NULL. */
- assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- return;
- }
-
- assert( pName2!=0 || pName1==0 );
- if( pName1==0 ){
- /* Form 1: Analyze everything */
- for(i=0; i<db->nDb; i++){
- if( i==1 ) continue; /* Do not analyze the TEMP database */
- analyzeDatabase(pParse, i);
- }
- }else if( pName2->n==0 && (iDb = sqlite3FindDb(db, pName1))>=0 ){
- /* Analyze the schema named as the argument */
- analyzeDatabase(pParse, iDb);
- }else{
- /* Form 3: Analyze the table or index named as an argument */
- iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
- if( iDb>=0 ){
- zDb = pName2->n ? db->aDb[iDb].zDbSName : 0;
- z = sqlite3NameFromToken(db, pTableName);
- if( z ){
- if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
- analyzeTable(pParse, pIdx->pTable, pIdx);
- }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){
- analyzeTable(pParse, pTab, 0);
- }
- sqlite3DbFree(db, z);
- }
- }
- }
- if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){
- sqlite3VdbeAddOp0(v, OP_Expire);
- }
-}
-
-/*
-** Used to pass information from the analyzer reader through to the
-** callback routine.
-*/
-typedef struct analysisInfo analysisInfo;
-struct analysisInfo {
- sqlite3 *db;
- const char *zDatabase;
-};
-
-/*
-** The first argument points to a nul-terminated string containing a
-** list of space separated integers. Read the first nOut of these into
-** the array aOut[].
-*/
-static void decodeIntArray(
- char *zIntArray, /* String containing int array to decode */
- int nOut, /* Number of slots in aOut[] */
- tRowcnt *aOut, /* Store integers here */
- LogEst *aLog, /* Or, if aOut==0, here */
- Index *pIndex /* Handle extra flags for this index, if not NULL */
-){
- char *z = zIntArray;
- int c;
- int i;
- tRowcnt v;
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( z==0 ) z = "";
-#else
- assert( z!=0 );
-#endif
- for(i=0; *z && i<nOut; i++){
- v = 0;
- while( (c=z[0])>='0' && c<='9' ){
- v = v*10 + c - '0';
- z++;
- }
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( aOut ) aOut[i] = v;
- if( aLog ) aLog[i] = sqlite3LogEst(v);
-#else
- assert( aOut==0 );
- UNUSED_PARAMETER(aOut);
- assert( aLog!=0 );
- aLog[i] = sqlite3LogEst(v);
-#endif
- if( *z==' ' ) z++;
- }
-#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
- assert( pIndex!=0 ); {
-#else
- if( pIndex ){
-#endif
- pIndex->bUnordered = 0;
- pIndex->noSkipScan = 0;
- while( z[0] ){
- if( sqlite3_strglob("unordered*", z)==0 ){
- pIndex->bUnordered = 1;
- }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
- pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
- }else if( sqlite3_strglob("noskipscan*", z)==0 ){
- pIndex->noSkipScan = 1;
- }
-#ifdef SQLITE_ENABLE_COSTMULT
- else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
- pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
- }
-#endif
- while( z[0]!=0 && z[0]!=' ' ) z++;
- while( z[0]==' ' ) z++;
- }
- }
-}
-
-/*
-** This callback is invoked once for each index when reading the
-** sqlite_stat1 table.
-**
-** argv[0] = name of the table
-** argv[1] = name of the index (might be NULL)
-** argv[2] = results of analysis - on integer for each column
-**
-** Entries for which argv[1]==NULL simply record the number of rows in
-** the table.
-*/
-static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
- analysisInfo *pInfo = (analysisInfo*)pData;
- Index *pIndex;
- Table *pTable;
- const char *z;
-
- assert( argc==3 );
- UNUSED_PARAMETER2(NotUsed, argc);
-
- if( argv==0 || argv[0]==0 || argv[2]==0 ){
- return 0;
- }
- pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase);
- if( pTable==0 ){
- return 0;
- }
- if( argv[1]==0 ){
- pIndex = 0;
- }else if( sqlite3_stricmp(argv[0],argv[1])==0 ){
- pIndex = sqlite3PrimaryKeyIndex(pTable);
- }else{
- pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
- }
- z = argv[2];
-
- if( pIndex ){
- tRowcnt *aiRowEst = 0;
- int nCol = pIndex->nKeyCol+1;
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- /* Index.aiRowEst may already be set here if there are duplicate
- ** sqlite_stat1 entries for this index. In that case just clobber
- ** the old data with the new instead of allocating a new array. */
- if( pIndex->aiRowEst==0 ){
- pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol);
- if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db);
- }
- aiRowEst = pIndex->aiRowEst;
-#endif
- pIndex->bUnordered = 0;
- decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
- pIndex->hasStat1 = 1;
- if( pIndex->pPartIdxWhere==0 ){
- pTable->nRowLogEst = pIndex->aiRowLogEst[0];
- pTable->tabFlags |= TF_HasStat1;
- }
- }else{
- Index fakeIdx;
- fakeIdx.szIdxRow = pTable->szTabRow;
-#ifdef SQLITE_ENABLE_COSTMULT
- fakeIdx.pTable = pTable;
-#endif
- decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
- pTable->szTabRow = fakeIdx.szIdxRow;
- pTable->tabFlags |= TF_HasStat1;
- }
-
- return 0;
-}
-
-/*
-** If the Index.aSample variable is not NULL, delete the aSample[] array
-** and its contents.
-*/
-void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( pIdx->aSample ){
- int j;
- for(j=0; j<pIdx->nSample; j++){
- IndexSample *p = &pIdx->aSample[j];
- sqlite3DbFree(db, p->p);
- }
- sqlite3DbFree(db, pIdx->aSample);
- }
- if( db && db->pnBytesFreed==0 ){
- pIdx->nSample = 0;
- pIdx->aSample = 0;
- }
-#else
- UNUSED_PARAMETER(db);
- UNUSED_PARAMETER(pIdx);
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-}
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** Populate the pIdx->aAvgEq[] array based on the samples currently
-** stored in pIdx->aSample[].
-*/
-static void initAvgEq(Index *pIdx){
- if( pIdx ){
- IndexSample *aSample = pIdx->aSample;
- IndexSample *pFinal = &aSample[pIdx->nSample-1];
- int iCol;
- int nCol = 1;
- if( pIdx->nSampleCol>1 ){
- /* If this is stat4 data, then calculate aAvgEq[] values for all
- ** sample columns except the last. The last is always set to 1, as
- ** once the trailing PK fields are considered all index keys are
- ** unique. */
- nCol = pIdx->nSampleCol-1;
- pIdx->aAvgEq[nCol] = 1;
- }
- for(iCol=0; iCol<nCol; iCol++){
- int nSample = pIdx->nSample;
- int i; /* Used to iterate through samples */
- tRowcnt sumEq = 0; /* Sum of the nEq values */
- tRowcnt avgEq = 0;
- tRowcnt nRow; /* Number of rows in index */
- i64 nSum100 = 0; /* Number of terms contributing to sumEq */
- i64 nDist100; /* Number of distinct values in index */
-
- if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){
- nRow = pFinal->anLt[iCol];
- nDist100 = (i64)100 * pFinal->anDLt[iCol];
- nSample--;
- }else{
- nRow = pIdx->aiRowEst[0];
- nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1];
- }
- pIdx->nRowEst0 = nRow;
-
- /* Set nSum to the number of distinct (iCol+1) field prefixes that
- ** occur in the stat4 table for this index. Set sumEq to the sum of
- ** the nEq values for column iCol for the same set (adding the value
- ** only once where there exist duplicate prefixes). */
- for(i=0; i<nSample; i++){
- if( i==(pIdx->nSample-1)
- || aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol]
- ){
- sumEq += aSample[i].anEq[iCol];
- nSum100 += 100;
- }
- }
-
- if( nDist100>nSum100 && sumEq<nRow ){
- avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100);
- }
- if( avgEq==0 ) avgEq = 1;
- pIdx->aAvgEq[iCol] = avgEq;
- }
- }
-}
-
-/*
-** Look up an index by name. Or, if the name of a WITHOUT ROWID table
-** is supplied instead, find the PRIMARY KEY index for that table.
-*/
-static Index *findIndexOrPrimaryKey(
- sqlite3 *db,
- const char *zName,
- const char *zDb
-){
- Index *pIdx = sqlite3FindIndex(db, zName, zDb);
- if( pIdx==0 ){
- Table *pTab = sqlite3FindTable(db, zName, zDb);
- if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab);
- }
- return pIdx;
-}
-
-/*
-** Load the content from either the sqlite_stat4 or sqlite_stat3 table
-** into the relevant Index.aSample[] arrays.
-**
-** Arguments zSql1 and zSql2 must point to SQL statements that return
-** data equivalent to the following (statements are different for stat3,
-** see the caller of this function for details):
-**
-** zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx
-** zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4
-**
-** where %Q is replaced with the database name before the SQL is executed.
-*/
-static int loadStatTbl(
- sqlite3 *db, /* Database handle */
- int bStat3, /* Assume single column records only */
- const char *zSql1, /* SQL statement 1 (see above) */
- const char *zSql2, /* SQL statement 2 (see above) */
- const char *zDb /* Database name (e.g. "main") */
-){
- int rc; /* Result codes from subroutines */
- sqlite3_stmt *pStmt = 0; /* An SQL statement being run */
- char *zSql; /* Text of the SQL statement */
- Index *pPrevIdx = 0; /* Previous index in the loop */
- IndexSample *pSample; /* A slot in pIdx->aSample[] */
-
- assert( db->lookaside.bDisable );
- zSql = sqlite3MPrintf(db, zSql1, zDb);
- if( !zSql ){
- return SQLITE_NOMEM_BKPT;
- }
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- sqlite3DbFree(db, zSql);
- if( rc ) return rc;
-
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- int nIdxCol = 1; /* Number of columns in stat4 records */
-
- char *zIndex; /* Index name */
- Index *pIdx; /* Pointer to the index object */
- int nSample; /* Number of samples */
- int nByte; /* Bytes of space required */
- int i; /* Bytes of space required */
- tRowcnt *pSpace;
-
- zIndex = (char *)sqlite3_column_text(pStmt, 0);
- if( zIndex==0 ) continue;
- nSample = sqlite3_column_int(pStmt, 1);
- pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
- assert( pIdx==0 || bStat3 || pIdx->nSample==0 );
- /* Index.nSample is non-zero at this point if data has already been
- ** loaded from the stat4 table. In this case ignore stat3 data. */
- if( pIdx==0 || pIdx->nSample ) continue;
- if( bStat3==0 ){
- assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
- if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
- nIdxCol = pIdx->nKeyCol;
- }else{
- nIdxCol = pIdx->nColumn;
- }
- }
- pIdx->nSampleCol = nIdxCol;
- nByte = sizeof(IndexSample) * nSample;
- nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
- nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
-
- pIdx->aSample = sqlite3DbMallocZero(db, nByte);
- if( pIdx->aSample==0 ){
- sqlite3_finalize(pStmt);
- return SQLITE_NOMEM_BKPT;
- }
- pSpace = (tRowcnt*)&pIdx->aSample[nSample];
- pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
- for(i=0; i<nSample; i++){
- pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
- pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
- pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol;
- }
- assert( ((u8*)pSpace)-nByte==(u8*)(pIdx->aSample) );
- }
- rc = sqlite3_finalize(pStmt);
- if( rc ) return rc;
-
- zSql = sqlite3MPrintf(db, zSql2, zDb);
- if( !zSql ){
- return SQLITE_NOMEM_BKPT;
- }
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- sqlite3DbFree(db, zSql);
- if( rc ) return rc;
-
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- char *zIndex; /* Index name */
- Index *pIdx; /* Pointer to the index object */
- int nCol = 1; /* Number of columns in index */
-
- zIndex = (char *)sqlite3_column_text(pStmt, 0);
- if( zIndex==0 ) continue;
- pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
- if( pIdx==0 ) continue;
- /* This next condition is true if data has already been loaded from
- ** the sqlite_stat4 table. In this case ignore stat3 data. */
- nCol = pIdx->nSampleCol;
- if( bStat3 && nCol>1 ) continue;
- if( pIdx!=pPrevIdx ){
- initAvgEq(pPrevIdx);
- pPrevIdx = pIdx;
- }
- pSample = &pIdx->aSample[pIdx->nSample];
- decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0);
- decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0);
- decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0);
-
- /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer.
- ** This is in case the sample record is corrupted. In that case, the
- ** sqlite3VdbeRecordCompare() may read up to two varints past the
- ** end of the allocated buffer before it realizes it is dealing with
- ** a corrupt record. Adding the two 0x00 bytes prevents this from causing
- ** a buffer overread. */
- pSample->n = sqlite3_column_bytes(pStmt, 4);
- pSample->p = sqlite3DbMallocZero(db, pSample->n + 2);
- if( pSample->p==0 ){
- sqlite3_finalize(pStmt);
- return SQLITE_NOMEM_BKPT;
- }
- if( pSample->n ){
- memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
- }
- pIdx->nSample++;
- }
- rc = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) initAvgEq(pPrevIdx);
- return rc;
-}
-
-/*
-** Load content from the sqlite_stat4 and sqlite_stat3 tables into
-** the Index.aSample[] arrays of all indices.
-*/
-static int loadStat4(sqlite3 *db, const char *zDb){
- int rc = SQLITE_OK; /* Result codes from subroutines */
-
- assert( db->lookaside.bDisable );
- if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
- rc = loadStatTbl(db, 0,
- "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx",
- "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
- zDb
- );
- }
-
- if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){
- rc = loadStatTbl(db, 1,
- "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx",
- "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3",
- zDb
- );
- }
-
- return rc;
-}
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-
-/*
-** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The
-** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
-** arrays. The contents of sqlite_stat3/4 are used to populate the
-** Index.aSample[] arrays.
-**
-** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
-** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined
-** during compilation and the sqlite_stat3/4 table is present, no data is
-** read from it.
-**
-** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the
-** sqlite_stat4 table is not present in the database, SQLITE_ERROR is
-** returned. However, in this case, data is read from the sqlite_stat1
-** table (if it is present) before returning.
-**
-** If an OOM error occurs, this function always sets db->mallocFailed.
-** This means if the caller does not care about other errors, the return
-** code may be ignored.
-*/
-int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
- analysisInfo sInfo;
- HashElem *i;
- char *zSql;
- int rc = SQLITE_OK;
- Schema *pSchema = db->aDb[iDb].pSchema;
-
- assert( iDb>=0 && iDb<db->nDb );
- assert( db->aDb[iDb].pBt!=0 );
-
- /* Clear any prior statistics */
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){
- Table *pTab = sqliteHashData(i);
- pTab->tabFlags &= ~TF_HasStat1;
- }
- for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
- Index *pIdx = sqliteHashData(i);
- pIdx->hasStat1 = 0;
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- sqlite3DeleteIndexSamples(db, pIdx);
- pIdx->aSample = 0;
-#endif
- }
-
- /* Load new statistics out of the sqlite_stat1 table */
- sInfo.db = db;
- sInfo.zDatabase = db->aDb[iDb].zDbSName;
- if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){
- zSql = sqlite3MPrintf(db,
- "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
- if( zSql==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
- sqlite3DbFree(db, zSql);
- }
- }
-
- /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
- Index *pIdx = sqliteHashData(i);
- if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx);
- }
-
- /* Load the statistics from the sqlite_stat4 table. */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){
- db->lookaside.bDisable++;
- rc = loadStat4(db, sInfo.zDatabase);
- db->lookaside.bDisable--;
- }
- for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
- Index *pIdx = sqliteHashData(i);
- sqlite3_free(pIdx->aiRowEst);
- pIdx->aiRowEst = 0;
- }
-#endif
-
- if( rc==SQLITE_NOMEM ){
- sqlite3OomFault(db);
- }
- return rc;
-}
-
-
-#endif /* SQLITE_OMIT_ANALYZE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/attach.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/attach.c
deleted file mode 100644
index ca0fd9fd1fd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/attach.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
-** 2003 April 6
-**
-** 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 contains code used to implement the ATTACH and DETACH commands.
-*/
-#include "sqliteInt.h"
-
-#ifndef SQLITE_OMIT_ATTACH
-/*
-** Resolve an expression that was part of an ATTACH or DETACH statement. This
-** is slightly different from resolving a normal SQL expression, because simple
-** identifiers are treated as strings, not possible column names or aliases.
-**
-** i.e. if the parser sees:
-**
-** ATTACH DATABASE abc AS def
-**
-** it treats the two expressions as literal strings 'abc' and 'def' instead of
-** looking for columns of the same name.
-**
-** This only applies to the root node of pExpr, so the statement:
-**
-** ATTACH DATABASE abc||def AS 'db2'
-**
-** will fail because neither abc or def can be resolved.
-*/
-static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
-{
- int rc = SQLITE_OK;
- if( pExpr ){
- if( pExpr->op!=TK_ID ){
- rc = sqlite3ResolveExprNames(pName, pExpr);
- }else{
- pExpr->op = TK_STRING;
- }
- }
- return rc;
-}
-
-/*
-** An SQL user-function registered to do the work of an ATTACH statement. The
-** three arguments to the function come directly from an attach statement:
-**
-** ATTACH DATABASE x AS y KEY z
-**
-** SELECT sqlite_attach(x, y, z)
-**
-** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
-** third argument.
-**
-** If the db->init.reopenMemdb flags is set, then instead of attaching a
-** new database, close the database on db->init.iDb and reopen it as an
-** empty MemDB.
-*/
-static void attachFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- int i;
- int rc = 0;
- sqlite3 *db = sqlite3_context_db_handle(context);
- const char *zName;
- const char *zFile;
- char *zPath = 0;
- char *zErr = 0;
- unsigned int flags;
- Db *aNew; /* New array of Db pointers */
- Db *pNew; /* Db object for the newly attached database */
- char *zErrDyn = 0;
- sqlite3_vfs *pVfs;
-
- UNUSED_PARAMETER(NotUsed);
- zFile = (const char *)sqlite3_value_text(argv[0]);
- zName = (const char *)sqlite3_value_text(argv[1]);
- if( zFile==0 ) zFile = "";
- if( zName==0 ) zName = "";
-
-#ifdef SQLITE_ENABLE_DESERIALIZE
-# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
-#else
-# define REOPEN_AS_MEMDB(db) (0)
-#endif
-
- if( REOPEN_AS_MEMDB(db) ){
- /* This is not a real ATTACH. Instead, this routine is being called
- ** from sqlite3_deserialize() to close database db->init.iDb and
- ** reopen it as a MemDB */
- pVfs = sqlite3_vfs_find("memdb");
- if( pVfs==0 ) return;
- pNew = &db->aDb[db->init.iDb];
- if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt);
- pNew->pBt = 0;
- pNew->pSchema = 0;
- rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB);
- }else{
- /* This is a real ATTACH
- **
- ** Check for the following errors:
- **
- ** * Too many attached databases,
- ** * Transaction currently open
- ** * Specified database name already being used.
- */
- if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
- zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
- db->aLimit[SQLITE_LIMIT_ATTACHED]
- );
- goto attach_error;
- }
- for(i=0; i<db->nDb; i++){
- char *z = db->aDb[i].zDbSName;
- assert( z && zName );
- if( sqlite3StrICmp(z, zName)==0 ){
- zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
- goto attach_error;
- }
- }
-
- /* Allocate the new entry in the db->aDb[] array and initialize the schema
- ** hash tables.
- */
- if( db->aDb==db->aDbStatic ){
- aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 );
- if( aNew==0 ) return;
- memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
- }else{
- aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
- if( aNew==0 ) return;
- }
- db->aDb = aNew;
- pNew = &db->aDb[db->nDb];
- memset(pNew, 0, sizeof(*pNew));
-
- /* Open the database file. If the btree is successfully opened, use
- ** it to obtain the database schema. At this point the schema may
- ** or may not be initialized.
- */
- flags = db->openFlags;
- rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- return;
- }
- assert( pVfs );
- flags |= SQLITE_OPEN_MAIN_DB;
- rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
- sqlite3_free( zPath );
- db->nDb++;
- }
- db->noSharedCache = 0;
- if( rc==SQLITE_CONSTRAINT ){
- rc = SQLITE_ERROR;
- zErrDyn = sqlite3MPrintf(db, "database is already attached");
- }else if( rc==SQLITE_OK ){
- Pager *pPager;
- pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt);
- if( !pNew->pSchema ){
- rc = SQLITE_NOMEM_BKPT;
- }else if( pNew->pSchema->file_format && pNew->pSchema->enc!=ENC(db) ){
- zErrDyn = sqlite3MPrintf(db,
- "attached databases must use the same text encoding as main database");
- rc = SQLITE_ERROR;
- }
- sqlite3BtreeEnter(pNew->pBt);
- pPager = sqlite3BtreePager(pNew->pBt);
- sqlite3PagerLockingMode(pPager, db->dfltLockMode);
- sqlite3BtreeSecureDelete(pNew->pBt,
- sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
- sqlite3BtreeSetPagerFlags(pNew->pBt,
- PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK));
-#endif
- sqlite3BtreeLeave(pNew->pBt);
- }
- pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName);
- if( rc==SQLITE_OK && pNew->zDbSName==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }
-
-
-#ifdef SQLITE_HAS_CODEC
- if( rc==SQLITE_OK ){
- extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
- extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
- int nKey;
- char *zKey;
- int t = sqlite3_value_type(argv[2]);
- switch( t ){
- case SQLITE_INTEGER:
- case SQLITE_FLOAT:
- zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
- rc = SQLITE_ERROR;
- break;
-
- case SQLITE_TEXT:
- case SQLITE_BLOB:
- nKey = sqlite3_value_bytes(argv[2]);
- zKey = (char *)sqlite3_value_blob(argv[2]);
- rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
- break;
-
- case SQLITE_NULL:
- /* No key specified. Use the key from the main database */
- sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
- if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
- rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
- }
- break;
- }
- }
-#endif
-
- /* If the file was opened successfully, read the schema for the new database.
- ** If this fails, or if opening the file failed, then close the file and
- ** remove the entry from the db->aDb[] array. i.e. put everything back the
- ** way we found it.
- */
- if( rc==SQLITE_OK ){
- sqlite3BtreeEnterAll(db);
- db->init.iDb = 0;
- db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
- rc = sqlite3Init(db, &zErrDyn);
- sqlite3BtreeLeaveAll(db);
- assert( zErrDyn==0 || rc!=SQLITE_OK );
- }
-#ifdef SQLITE_USER_AUTHENTICATION
- if( rc==SQLITE_OK ){
- u8 newAuth = 0;
- rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
- if( newAuth<db->auth.authLevel ){
- rc = SQLITE_AUTH_USER;
- }
- }
-#endif
- if( rc ){
- if( !REOPEN_AS_MEMDB(db) ){
- int iDb = db->nDb - 1;
- assert( iDb>=2 );
- if( db->aDb[iDb].pBt ){
- sqlite3BtreeClose(db->aDb[iDb].pBt);
- db->aDb[iDb].pBt = 0;
- db->aDb[iDb].pSchema = 0;
- }
- sqlite3ResetAllSchemasOfConnection(db);
- db->nDb = iDb;
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
- sqlite3OomFault(db);
- sqlite3DbFree(db, zErrDyn);
- zErrDyn = sqlite3MPrintf(db, "out of memory");
- }else if( zErrDyn==0 ){
- zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
- }
- }
- goto attach_error;
- }
-
- return;
-
-attach_error:
- /* Return an error if we get here */
- if( zErrDyn ){
- sqlite3_result_error(context, zErrDyn, -1);
- sqlite3DbFree(db, zErrDyn);
- }
- if( rc ) sqlite3_result_error_code(context, rc);
-}
-
-/*
-** An SQL user-function registered to do the work of an DETACH statement. The
-** three arguments to the function come directly from a detach statement:
-**
-** DETACH DATABASE x
-**
-** SELECT sqlite_detach(x)
-*/
-static void detachFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- const char *zName = (const char *)sqlite3_value_text(argv[0]);
- sqlite3 *db = sqlite3_context_db_handle(context);
- int i;
- Db *pDb = 0;
- char zErr[128];
-
- UNUSED_PARAMETER(NotUsed);
-
- if( zName==0 ) zName = "";
- for(i=0; i<db->nDb; i++){
- pDb = &db->aDb[i];
- if( pDb->pBt==0 ) continue;
- if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break;
- }
-
- if( i>=db->nDb ){
- sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
- goto detach_error;
- }
- if( i<2 ){
- sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
- goto detach_error;
- }
- if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
- sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
- goto detach_error;
- }
-
- sqlite3BtreeClose(pDb->pBt);
- pDb->pBt = 0;
- pDb->pSchema = 0;
- sqlite3CollapseDatabaseArray(db);
- return;
-
-detach_error:
- sqlite3_result_error(context, zErr, -1);
-}
-
-/*
-** This procedure generates VDBE code for a single invocation of either the
-** sqlite_detach() or sqlite_attach() SQL user functions.
-*/
-static void codeAttach(
- Parse *pParse, /* The parser context */
- int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */
- FuncDef const *pFunc,/* FuncDef wrapper for detachFunc() or attachFunc() */
- Expr *pAuthArg, /* Expression to pass to authorization callback */
- Expr *pFilename, /* Name of database file */
- Expr *pDbname, /* Name of the database to use internally */
- Expr *pKey /* Database key for encryption extension */
-){
- int rc;
- NameContext sName;
- Vdbe *v;
- sqlite3* db = pParse->db;
- int regArgs;
-
- if( pParse->nErr ) goto attach_end;
- memset(&sName, 0, sizeof(NameContext));
- sName.pParse = pParse;
-
- if(
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
- ){
- goto attach_end;
- }
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( pAuthArg ){
- char *zAuthArg;
- if( pAuthArg->op==TK_STRING ){
- zAuthArg = pAuthArg->u.zToken;
- }else{
- zAuthArg = 0;
- }
- rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
- if(rc!=SQLITE_OK ){
- goto attach_end;
- }
- }
-#endif /* SQLITE_OMIT_AUTHORIZATION */
-
-
- v = sqlite3GetVdbe(pParse);
- regArgs = sqlite3GetTempRange(pParse, 4);
- sqlite3ExprCode(pParse, pFilename, regArgs);
- sqlite3ExprCode(pParse, pDbname, regArgs+1);
- sqlite3ExprCode(pParse, pKey, regArgs+2);
-
- assert( v || db->mallocFailed );
- if( v ){
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3,
- (char *)pFunc, P4_FUNCDEF);
- assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
- sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
-
- /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
- ** statement only). For DETACH, set it to false (expire all existing
- ** statements).
- */
- sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH));
- }
-
-attach_end:
- sqlite3ExprDelete(db, pFilename);
- sqlite3ExprDelete(db, pDbname);
- sqlite3ExprDelete(db, pKey);
-}
-
-/*
-** Called by the parser to compile a DETACH statement.
-**
-** DETACH pDbname
-*/
-void sqlite3Detach(Parse *pParse, Expr *pDbname){
- static const FuncDef detach_func = {
- 1, /* nArg */
- SQLITE_UTF8, /* funcFlags */
- 0, /* pUserData */
- 0, /* pNext */
- detachFunc, /* xSFunc */
- 0, /* xFinalize */
- "sqlite_detach", /* zName */
- {0}
- };
- codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname);
-}
-
-/*
-** Called by the parser to compile an ATTACH statement.
-**
-** ATTACH p AS pDbname KEY pKey
-*/
-void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
- static const FuncDef attach_func = {
- 3, /* nArg */
- SQLITE_UTF8, /* funcFlags */
- 0, /* pUserData */
- 0, /* pNext */
- attachFunc, /* xSFunc */
- 0, /* xFinalize */
- "sqlite_attach", /* zName */
- {0}
- };
- codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey);
-}
-#endif /* SQLITE_OMIT_ATTACH */
-
-/*
-** Initialize a DbFixer structure. This routine must be called prior
-** to passing the structure to one of the sqliteFixAAAA() routines below.
-*/
-void sqlite3FixInit(
- DbFixer *pFix, /* The fixer to be initialized */
- Parse *pParse, /* Error messages will be written here */
- int iDb, /* This is the database that must be used */
- const char *zType, /* "view", "trigger", or "index" */
- const Token *pName /* Name of the view, trigger, or index */
-){
- sqlite3 *db;
-
- db = pParse->db;
- assert( db->nDb>iDb );
- pFix->pParse = pParse;
- pFix->zDb = db->aDb[iDb].zDbSName;
- pFix->pSchema = db->aDb[iDb].pSchema;
- pFix->zType = zType;
- pFix->pName = pName;
- pFix->bVarOnly = (iDb==1);
-}
-
-/*
-** The following set of routines walk through the parse tree and assign
-** a specific database to all table references where the database name
-** was left unspecified in the original SQL statement. The pFix structure
-** must have been initialized by a prior call to sqlite3FixInit().
-**
-** These routines are used to make sure that an index, trigger, or
-** view in one database does not refer to objects in a different database.
-** (Exception: indices, triggers, and views in the TEMP database are
-** allowed to refer to anything.) If a reference is explicitly made
-** to an object in a different database, an error message is added to
-** pParse->zErrMsg and these routines return non-zero. If everything
-** checks out, these routines return 0.
-*/
-int sqlite3FixSrcList(
- DbFixer *pFix, /* Context of the fixation */
- SrcList *pList /* The Source list to check and modify */
-){
- int i;
- const char *zDb;
- struct SrcList_item *pItem;
-
- if( NEVER(pList==0) ) return 0;
- zDb = pFix->zDb;
- for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pFix->bVarOnly==0 ){
- if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
- sqlite3ErrorMsg(pFix->pParse,
- "%s %T cannot reference objects in database %s",
- pFix->zType, pFix->pName, pItem->zDatabase);
- return 1;
- }
- sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
- pItem->zDatabase = 0;
- pItem->pSchema = pFix->pSchema;
- }
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
- if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
- if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
-#endif
- if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){
- return 1;
- }
- }
- return 0;
-}
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
-int sqlite3FixSelect(
- DbFixer *pFix, /* Context of the fixation */
- Select *pSelect /* The SELECT statement to be fixed to one database */
-){
- while( pSelect ){
- if( sqlite3FixExprList(pFix, pSelect->pEList) ){
- return 1;
- }
- if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
- return 1;
- }
- if( pSelect->pWith ){
- int i;
- for(i=0; i<pSelect->pWith->nCte; i++){
- if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){
- return 1;
- }
- }
- }
- pSelect = pSelect->pPrior;
- }
- return 0;
-}
-int sqlite3FixExpr(
- DbFixer *pFix, /* Context of the fixation */
- Expr *pExpr /* The expression to be fixed to one database */
-){
- while( pExpr ){
- if( pExpr->op==TK_VARIABLE ){
- if( pFix->pParse->db->init.busy ){
- pExpr->op = TK_NULL;
- }else{
- sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
- return 1;
- }
- }
- if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
- }else{
- if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
- }
- if( sqlite3FixExpr(pFix, pExpr->pRight) ){
- return 1;
- }
- pExpr = pExpr->pLeft;
- }
- return 0;
-}
-int sqlite3FixExprList(
- DbFixer *pFix, /* Context of the fixation */
- ExprList *pList /* The expression to be fixed to one database */
-){
- int i;
- struct ExprList_item *pItem;
- if( pList==0 ) return 0;
- for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
- if( sqlite3FixExpr(pFix, pItem->pExpr) ){
- return 1;
- }
- }
- return 0;
-}
-#endif
-
-#ifndef SQLITE_OMIT_TRIGGER
-int sqlite3FixTriggerStep(
- DbFixer *pFix, /* Context of the fixation */
- TriggerStep *pStep /* The trigger step be fixed to one database */
-){
- while( pStep ){
- if( sqlite3FixSelect(pFix, pStep->pSelect) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pStep->pWhere) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pStep->pExprList) ){
- return 1;
- }
-#ifndef SQLITE_OMIT_UPSERT
- if( pStep->pUpsert ){
- Upsert *pUp = pStep->pUpsert;
- if( sqlite3FixExprList(pFix, pUp->pUpsertTarget)
- || sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere)
- || sqlite3FixExprList(pFix, pUp->pUpsertSet)
- || sqlite3FixExpr(pFix, pUp->pUpsertWhere)
- ){
- return 1;
- }
- }
-#endif
- pStep = pStep->pNext;
- }
- return 0;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/auth.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/auth.c
deleted file mode 100644
index 03e4cf9f543..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/auth.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
-** 2003 January 11
-**
-** 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 contains code used to implement the sqlite3_set_authorizer()
-** API. This facility is an optional feature of the library. Embedded
-** systems that do not need this facility may omit it by recompiling
-** the library with -DSQLITE_OMIT_AUTHORIZATION=1
-*/
-#include "sqliteInt.h"
-
-/*
-** All of the code in this file may be omitted by defining a single
-** macro.
-*/
-#ifndef SQLITE_OMIT_AUTHORIZATION
-
-/*
-** Set or clear the access authorization function.
-**
-** The access authorization function is be called during the compilation
-** phase to verify that the user has read and/or write access permission on
-** various fields of the database. The first argument to the auth function
-** is a copy of the 3rd argument to this routine. The second argument
-** to the auth function is one of these constants:
-**
-** SQLITE_CREATE_INDEX
-** SQLITE_CREATE_TABLE
-** SQLITE_CREATE_TEMP_INDEX
-** SQLITE_CREATE_TEMP_TABLE
-** SQLITE_CREATE_TEMP_TRIGGER
-** SQLITE_CREATE_TEMP_VIEW
-** SQLITE_CREATE_TRIGGER
-** SQLITE_CREATE_VIEW
-** SQLITE_DELETE
-** SQLITE_DROP_INDEX
-** SQLITE_DROP_TABLE
-** SQLITE_DROP_TEMP_INDEX
-** SQLITE_DROP_TEMP_TABLE
-** SQLITE_DROP_TEMP_TRIGGER
-** SQLITE_DROP_TEMP_VIEW
-** SQLITE_DROP_TRIGGER
-** SQLITE_DROP_VIEW
-** SQLITE_INSERT
-** SQLITE_PRAGMA
-** SQLITE_READ
-** SQLITE_SELECT
-** SQLITE_TRANSACTION
-** SQLITE_UPDATE
-**
-** The third and fourth arguments to the auth function are the name of
-** the table and the column that are being accessed. The auth function
-** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If
-** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY
-** means that the SQL statement will never-run - the sqlite3_exec() call
-** will return with an error. SQLITE_IGNORE means that the SQL statement
-** should run but attempts to read the specified column will return NULL
-** and attempts to write the column will be ignored.
-**
-** Setting the auth function to NULL disables this hook. The default
-** setting of the auth function is NULL.
-*/
-int sqlite3_set_authorizer(
- sqlite3 *db,
- int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
- void *pArg
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- db->xAuth = (sqlite3_xauth)xAuth;
- db->pAuthArg = pArg;
- sqlite3ExpirePreparedStatements(db);
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
-}
-
-/*
-** Write an error message into pParse->zErrMsg that explains that the
-** user-supplied authorization function returned an illegal value.
-*/
-static void sqliteAuthBadReturnCode(Parse *pParse){
- sqlite3ErrorMsg(pParse, "authorizer malfunction");
- pParse->rc = SQLITE_ERROR;
-}
-
-/*
-** Invoke the authorization callback for permission to read column zCol from
-** table zTab in database zDb. This function assumes that an authorization
-** callback has been registered (i.e. that sqlite3.xAuth is not NULL).
-**
-** If SQLITE_IGNORE is returned and pExpr is not NULL, then pExpr is changed
-** to an SQL NULL expression. Otherwise, if pExpr is NULL, then SQLITE_IGNORE
-** is treated as SQLITE_DENY. In this case an error is left in pParse.
-*/
-int sqlite3AuthReadCol(
- Parse *pParse, /* The parser context */
- const char *zTab, /* Table name */
- const char *zCol, /* Column name */
- int iDb /* Index of containing database. */
-){
- sqlite3 *db = pParse->db; /* Database handle */
- char *zDb = db->aDb[iDb].zDbSName; /* Schema name of attached database */
- int rc; /* Auth callback return code */
-
- if( db->init.busy ) return SQLITE_OK;
- rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
-#ifdef SQLITE_USER_AUTHENTICATION
- ,db->auth.zAuthUser
-#endif
- );
- if( rc==SQLITE_DENY ){
- char *z = sqlite3_mprintf("%s.%s", zTab, zCol);
- if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z);
- sqlite3ErrorMsg(pParse, "access to %z is prohibited", z);
- pParse->rc = SQLITE_AUTH;
- }else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){
- sqliteAuthBadReturnCode(pParse);
- }
- return rc;
-}
-
-/*
-** The pExpr should be a TK_COLUMN expression. The table referred to
-** is in pTabList or else it is the NEW or OLD table of a trigger.
-** Check to see if it is OK to read this particular column.
-**
-** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
-** instruction into a TK_NULL. If the auth function returns SQLITE_DENY,
-** then generate an error.
-*/
-void sqlite3AuthRead(
- Parse *pParse, /* The parser context */
- Expr *pExpr, /* The expression to check authorization on */
- Schema *pSchema, /* The schema of the expression */
- SrcList *pTabList /* All table that pExpr might refer to */
-){
- sqlite3 *db = pParse->db;
- Table *pTab = 0; /* The table being read */
- const char *zCol; /* Name of the column of the table */
- int iSrc; /* Index in pTabList->a[] of table being read */
- int iDb; /* The index of the database the expression refers to */
- int iCol; /* Index of column in table */
-
- assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
- if( db->xAuth==0 ) return;
- iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
- if( iDb<0 ){
- /* An attempt to read a column out of a subquery or other
- ** temporary table. */
- return;
- }
-
- if( pExpr->op==TK_TRIGGER ){
- pTab = pParse->pTriggerTab;
- }else{
- assert( pTabList );
- for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){
- if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
- pTab = pTabList->a[iSrc].pTab;
- break;
- }
- }
- }
- iCol = pExpr->iColumn;
- if( NEVER(pTab==0) ) return;
-
- if( iCol>=0 ){
- assert( iCol<pTab->nCol );
- zCol = pTab->aCol[iCol].zName;
- }else if( pTab->iPKey>=0 ){
- assert( pTab->iPKey<pTab->nCol );
- zCol = pTab->aCol[pTab->iPKey].zName;
- }else{
- zCol = "ROWID";
- }
- assert( iDb>=0 && iDb<db->nDb );
- if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
- pExpr->op = TK_NULL;
- }
-}
-
-/*
-** Do an authorization check using the code and arguments given. Return
-** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
-** is returned, then the error count and error message in pParse are
-** modified appropriately.
-*/
-int sqlite3AuthCheck(
- Parse *pParse,
- int code,
- const char *zArg1,
- const char *zArg2,
- const char *zArg3
-){
- sqlite3 *db = pParse->db;
- int rc;
-
- /* Don't do any authorization checks if the database is initialising
- ** or if the parser is being invoked from within sqlite3_declare_vtab.
- */
- if( db->init.busy || IN_DECLARE_VTAB ){
- return SQLITE_OK;
- }
-
- if( db->xAuth==0 ){
- return SQLITE_OK;
- }
-
- /* EVIDENCE-OF: R-43249-19882 The third through sixth parameters to the
- ** callback are either NULL pointers or zero-terminated strings that
- ** contain additional details about the action to be authorized.
- **
- ** The following testcase() macros show that any of the 3rd through 6th
- ** parameters can be either NULL or a string. */
- testcase( zArg1==0 );
- testcase( zArg2==0 );
- testcase( zArg3==0 );
- testcase( pParse->zAuthContext==0 );
-
- rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
-#ifdef SQLITE_USER_AUTHENTICATION
- ,db->auth.zAuthUser
-#endif
- );
- if( rc==SQLITE_DENY ){
- sqlite3ErrorMsg(pParse, "not authorized");
- pParse->rc = SQLITE_AUTH;
- }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
- rc = SQLITE_DENY;
- sqliteAuthBadReturnCode(pParse);
- }
- return rc;
-}
-
-/*
-** Push an authorization context. After this routine is called, the
-** zArg3 argument to authorization callbacks will be zContext until
-** popped. Or if pParse==0, this routine is a no-op.
-*/
-void sqlite3AuthContextPush(
- Parse *pParse,
- AuthContext *pContext,
- const char *zContext
-){
- assert( pParse );
- pContext->pParse = pParse;
- pContext->zAuthContext = pParse->zAuthContext;
- pParse->zAuthContext = zContext;
-}
-
-/*
-** Pop an authorization context that was previously pushed
-** by sqlite3AuthContextPush
-*/
-void sqlite3AuthContextPop(AuthContext *pContext){
- if( pContext->pParse ){
- pContext->pParse->zAuthContext = pContext->zAuthContext;
- pContext->pParse = 0;
- }
-}
-
-#endif /* SQLITE_OMIT_AUTHORIZATION */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/backup.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/backup.c
deleted file mode 100644
index 165144d9657..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/backup.c
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
-** 2009 January 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 contains the implementation of the sqlite3_backup_XXX()
-** API functions and the related features.
-*/
-#include "sqliteInt.h"
-#include "btreeInt.h"
-
-/*
-** Structure allocated for each backup operation.
-*/
-struct sqlite3_backup {
- sqlite3* pDestDb; /* Destination database handle */
- Btree *pDest; /* Destination b-tree file */
- u32 iDestSchema; /* Original schema cookie in destination */
- int bDestLocked; /* True once a write-transaction is open on pDest */
-
- Pgno iNext; /* Page number of the next source page to copy */
- sqlite3* pSrcDb; /* Source database handle */
- Btree *pSrc; /* Source b-tree file */
-
- int rc; /* Backup process error code */
-
- /* These two variables are set by every call to backup_step(). They are
- ** read by calls to backup_remaining() and backup_pagecount().
- */
- Pgno nRemaining; /* Number of pages left to copy */
- Pgno nPagecount; /* Total number of pages to copy */
-
- int isAttached; /* True once backup has been registered with pager */
- sqlite3_backup *pNext; /* Next backup associated with source pager */
-};
-
-/*
-** THREAD SAFETY NOTES:
-**
-** Once it has been created using backup_init(), a single sqlite3_backup
-** structure may be accessed via two groups of thread-safe entry points:
-**
-** * Via the sqlite3_backup_XXX() API function backup_step() and
-** backup_finish(). Both these functions obtain the source database
-** handle mutex and the mutex associated with the source BtShared
-** structure, in that order.
-**
-** * Via the BackupUpdate() and BackupRestart() functions, which are
-** invoked by the pager layer to report various state changes in
-** the page cache associated with the source database. The mutex
-** associated with the source database BtShared structure will always
-** be held when either of these functions are invoked.
-**
-** The other sqlite3_backup_XXX() API functions, backup_remaining() and
-** backup_pagecount() are not thread-safe functions. If they are called
-** while some other thread is calling backup_step() or backup_finish(),
-** the values returned may be invalid. There is no way for a call to
-** BackupUpdate() or BackupRestart() to interfere with backup_remaining()
-** or backup_pagecount().
-**
-** Depending on the SQLite configuration, the database handles and/or
-** the Btree objects may have their own mutexes that require locking.
-** Non-sharable Btrees (in-memory databases for example), do not have
-** associated mutexes.
-*/
-
-/*
-** Return a pointer corresponding to database zDb (i.e. "main", "temp")
-** in connection handle pDb. If such a database cannot be found, return
-** a NULL pointer and write an error message to pErrorDb.
-**
-** If the "temp" database is requested, it may need to be opened by this
-** function. If an error occurs while doing so, return 0 and write an
-** error message to pErrorDb.
-*/
-static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
- int i = sqlite3FindDbName(pDb, zDb);
-
- if( i==1 ){
- Parse sParse;
- int rc = 0;
- memset(&sParse, 0, sizeof(sParse));
- sParse.db = pDb;
- if( sqlite3OpenTempDatabase(&sParse) ){
- sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
- rc = SQLITE_ERROR;
- }
- sqlite3DbFree(pErrorDb, sParse.zErrMsg);
- sqlite3ParserReset(&sParse);
- if( rc ){
- return 0;
- }
- }
-
- if( i<0 ){
- sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb);
- return 0;
- }
-
- return pDb->aDb[i].pBt;
-}
-
-/*
-** Attempt to set the page size of the destination to match the page size
-** of the source.
-*/
-static int setDestPgsz(sqlite3_backup *p){
- int rc;
- rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0);
- return rc;
-}
-
-/*
-** Check that there is no open read-transaction on the b-tree passed as the
-** second argument. If there is not, return SQLITE_OK. Otherwise, if there
-** is an open read-transaction, return SQLITE_ERROR and leave an error
-** message in database handle db.
-*/
-static int checkReadTransaction(sqlite3 *db, Btree *p){
- if( sqlite3BtreeIsInReadTrans(p) ){
- sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-
-/*
-** Create an sqlite3_backup process to copy the contents of zSrcDb from
-** connection handle pSrcDb to zDestDb in pDestDb. If successful, return
-** a pointer to the new sqlite3_backup object.
-**
-** If an error occurs, NULL is returned and an error code and error message
-** stored in database handle pDestDb.
-*/
-sqlite3_backup *sqlite3_backup_init(
- sqlite3* pDestDb, /* Database to write to */
- const char *zDestDb, /* Name of database within pDestDb */
- sqlite3* pSrcDb, /* Database connection to read from */
- const char *zSrcDb /* Name of database within pSrcDb */
-){
- sqlite3_backup *p; /* Value to return */
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-
- /* Lock the source database handle. The destination database
- ** handle is not locked in this routine, but it is locked in
- ** sqlite3_backup_step(). The user is required to ensure that no
- ** other thread accesses the destination handle for the duration
- ** of the backup operation. Any attempt to use the destination
- ** database connection while a backup is in progress may cause
- ** a malfunction or a deadlock.
- */
- sqlite3_mutex_enter(pSrcDb->mutex);
- sqlite3_mutex_enter(pDestDb->mutex);
-
- if( pSrcDb==pDestDb ){
- sqlite3ErrorWithMsg(
- pDestDb, SQLITE_ERROR, "source and destination must be distinct"
- );
- p = 0;
- }else {
- /* Allocate space for a new sqlite3_backup object...
- ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
- ** call to sqlite3_backup_init() and is destroyed by a call to
- ** sqlite3_backup_finish(). */
- p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
- if( !p ){
- sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT);
- }
- }
-
- /* If the allocation succeeded, populate the new object. */
- if( p ){
- p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
- p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
- p->pDestDb = pDestDb;
- p->pSrcDb = pSrcDb;
- p->iNext = 1;
- p->isAttached = 0;
-
- if( 0==p->pSrc || 0==p->pDest
- || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
- ){
- /* One (or both) of the named databases did not exist or an OOM
- ** error was hit. Or there is a transaction open on the destination
- ** database. The error has already been written into the pDestDb
- ** handle. All that is left to do here is free the sqlite3_backup
- ** structure. */
- sqlite3_free(p);
- p = 0;
- }
- }
- if( p ){
- p->pSrc->nBackup++;
- }
-
- sqlite3_mutex_leave(pDestDb->mutex);
- sqlite3_mutex_leave(pSrcDb->mutex);
- return p;
-}
-
-/*
-** Argument rc is an SQLite error code. Return true if this error is
-** considered fatal if encountered during a backup operation. All errors
-** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED.
-*/
-static int isFatalError(int rc){
- return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED));
-}
-
-/*
-** Parameter zSrcData points to a buffer containing the data for
-** page iSrcPg from the source database. Copy this data into the
-** destination database.
-*/
-static int backupOnePage(
- sqlite3_backup *p, /* Backup handle */
- Pgno iSrcPg, /* Source database page to backup */
- const u8 *zSrcData, /* Source database page data */
- int bUpdate /* True for an update, false otherwise */
-){
- Pager * const pDestPager = sqlite3BtreePager(p->pDest);
- const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
- int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
- const int nCopy = MIN(nSrcPgsz, nDestPgsz);
- const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
-#ifdef SQLITE_HAS_CODEC
- /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
- ** guaranteed that the shared-mutex is held by this thread, handle
- ** p->pSrc may not actually be the owner. */
- int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
- int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest);
-#endif
- int rc = SQLITE_OK;
- i64 iOff;
-
- assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
- assert( p->bDestLocked );
- assert( !isFatalError(p->rc) );
- assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
- assert( zSrcData );
-
- /* Catch the case where the destination is an in-memory database and the
- ** page sizes of the source and destination differ.
- */
- if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
- rc = SQLITE_READONLY;
- }
-
-#ifdef SQLITE_HAS_CODEC
- /* Backup is not possible if the page size of the destination is changing
- ** and a codec is in use.
- */
- if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
- rc = SQLITE_READONLY;
- }
-
- /* Backup is not possible if the number of bytes of reserve space differ
- ** between source and destination. If there is a difference, try to
- ** fix the destination to agree with the source. If that is not possible,
- ** then the backup cannot proceed.
- */
- if( nSrcReserve!=nDestReserve ){
- u32 newPgsz = nSrcPgsz;
- rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve);
- if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY;
- }
-#endif
-
- /* This loop runs once for each destination page spanned by the source
- ** page. For each iteration, variable iOff is set to the byte offset
- ** of the destination page.
- */
- for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
- DbPage *pDestPg = 0;
- Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
- if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
- if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
- && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
- ){
- const u8 *zIn = &zSrcData[iOff%nSrcPgsz];
- u8 *zDestData = sqlite3PagerGetData(pDestPg);
- u8 *zOut = &zDestData[iOff%nDestPgsz];
-
- /* Copy the data from the source page into the destination page.
- ** Then clear the Btree layer MemPage.isInit flag. Both this module
- ** and the pager code use this trick (clearing the first byte
- ** of the page 'extra' space to invalidate the Btree layers
- ** cached parse of the page). MemPage.isInit is marked
- ** "MUST BE FIRST" for this purpose.
- */
- memcpy(zOut, zIn, nCopy);
- ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
- if( iOff==0 && bUpdate==0 ){
- sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
- }
- }
- sqlite3PagerUnref(pDestPg);
- }
-
- return rc;
-}
-
-/*
-** If pFile is currently larger than iSize bytes, then truncate it to
-** exactly iSize bytes. If pFile is not larger than iSize bytes, then
-** this function is a no-op.
-**
-** Return SQLITE_OK if everything is successful, or an SQLite error
-** code if an error occurs.
-*/
-static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
- i64 iCurrent;
- int rc = sqlite3OsFileSize(pFile, &iCurrent);
- if( rc==SQLITE_OK && iCurrent>iSize ){
- rc = sqlite3OsTruncate(pFile, iSize);
- }
- return rc;
-}
-
-/*
-** Register this backup object with the associated source pager for
-** callbacks when pages are changed or the cache invalidated.
-*/
-static void attachBackupObject(sqlite3_backup *p){
- sqlite3_backup **pp;
- assert( sqlite3BtreeHoldsMutex(p->pSrc) );
- pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
- p->pNext = *pp;
- *pp = p;
- p->isAttached = 1;
-}
-
-/*
-** Copy nPage pages from the source b-tree to the destination.
-*/
-int sqlite3_backup_step(sqlite3_backup *p, int nPage){
- int rc;
- int destMode; /* Destination journal mode */
- int pgszSrc = 0; /* Source page size */
- int pgszDest = 0; /* Destination page size */
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( p==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(p->pSrcDb->mutex);
- sqlite3BtreeEnter(p->pSrc);
- if( p->pDestDb ){
- sqlite3_mutex_enter(p->pDestDb->mutex);
- }
-
- rc = p->rc;
- if( !isFatalError(rc) ){
- Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
- Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
- int ii; /* Iterator variable */
- int nSrcPage = -1; /* Size of source db in pages */
- int bCloseTrans = 0; /* True if src db requires unlocking */
-
- /* If the source pager is currently in a write-transaction, return
- ** SQLITE_BUSY immediately.
- */
- if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
- rc = SQLITE_BUSY;
- }else{
- rc = SQLITE_OK;
- }
-
- /* If there is no open read-transaction on the source database, open
- ** one now. If a transaction is opened here, then it will be closed
- ** before this function exits.
- */
- if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
- rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
- bCloseTrans = 1;
- }
-
- /* If the destination database has not yet been locked (i.e. if this
- ** is the first call to backup_step() for the current backup operation),
- ** try to set its page size to the same as the source database. This
- ** is especially important on ZipVFS systems, as in that case it is
- ** not possible to create a database file that uses one page size by
- ** writing to it with another. */
- if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
- rc = SQLITE_NOMEM;
- }
-
- /* Lock the destination database, if it is not locked already. */
- if( SQLITE_OK==rc && p->bDestLocked==0
- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
- ){
- p->bDestLocked = 1;
- sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
- }
-
- /* Do not allow backup if the destination database is in WAL mode
- ** and the page sizes are different between source and destination */
- pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
- pgszDest = sqlite3BtreeGetPageSize(p->pDest);
- destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
- if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
- rc = SQLITE_READONLY;
- }
-
- /* Now that there is a read-lock on the source database, query the
- ** source pager for the number of pages in the database.
- */
- nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
- assert( nSrcPage>=0 );
- for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
- const Pgno iSrcPg = p->iNext; /* Source page number */
- if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
- DbPage *pSrcPg; /* Source page object */
- rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY);
- if( rc==SQLITE_OK ){
- rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
- sqlite3PagerUnref(pSrcPg);
- }
- }
- p->iNext++;
- }
- if( rc==SQLITE_OK ){
- p->nPagecount = nSrcPage;
- p->nRemaining = nSrcPage+1-p->iNext;
- if( p->iNext>(Pgno)nSrcPage ){
- rc = SQLITE_DONE;
- }else if( !p->isAttached ){
- attachBackupObject(p);
- }
- }
-
- /* Update the schema version field in the destination database. This
- ** is to make sure that the schema-version really does change in
- ** the case where the source and destination databases have the
- ** same schema version.
- */
- if( rc==SQLITE_DONE ){
- if( nSrcPage==0 ){
- rc = sqlite3BtreeNewDb(p->pDest);
- nSrcPage = 1;
- }
- if( rc==SQLITE_OK || rc==SQLITE_DONE ){
- rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
- }
- if( rc==SQLITE_OK ){
- if( p->pDestDb ){
- sqlite3ResetAllSchemasOfConnection(p->pDestDb);
- }
- if( destMode==PAGER_JOURNALMODE_WAL ){
- rc = sqlite3BtreeSetVersion(p->pDest, 2);
- }
- }
- if( rc==SQLITE_OK ){
- int nDestTruncate;
- /* Set nDestTruncate to the final number of pages in the destination
- ** database. The complication here is that the destination page
- ** size may be different to the source page size.
- **
- ** If the source page size is smaller than the destination page size,
- ** round up. In this case the call to sqlite3OsTruncate() below will
- ** fix the size of the file. However it is important to call
- ** sqlite3PagerTruncateImage() here so that any pages in the
- ** destination file that lie beyond the nDestTruncate page mark are
- ** journalled by PagerCommitPhaseOne() before they are destroyed
- ** by the file truncation.
- */
- assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
- assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
- if( pgszSrc<pgszDest ){
- int ratio = pgszDest/pgszSrc;
- nDestTruncate = (nSrcPage+ratio-1)/ratio;
- if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
- nDestTruncate--;
- }
- }else{
- nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
- }
- assert( nDestTruncate>0 );
-
- if( pgszSrc<pgszDest ){
- /* If the source page-size is smaller than the destination page-size,
- ** two extra things may need to happen:
- **
- ** * The destination may need to be truncated, and
- **
- ** * Data stored on the pages immediately following the
- ** pending-byte page in the source database may need to be
- ** copied into the destination database.
- */
- const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
- sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
- Pgno iPg;
- int nDstPage;
- i64 iOff;
- i64 iEnd;
-
- assert( pFile );
- assert( nDestTruncate==0
- || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
- nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
- && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
- ));
-
- /* This block ensures that all data required to recreate the original
- ** database has been stored in the journal for pDestPager and the
- ** journal synced to disk. So at this point we may safely modify
- ** the database file in any way, knowing that if a power failure
- ** occurs, the original database will be reconstructed from the
- ** journal file. */
- sqlite3PagerPagecount(pDestPager, &nDstPage);
- for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
- if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
- DbPage *pPg;
- rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pPg);
- sqlite3PagerUnref(pPg);
- }
- }
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
- }
-
- /* Write the extra pages and truncate the database file as required */
- iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
- for(
- iOff=PENDING_BYTE+pgszSrc;
- rc==SQLITE_OK && iOff<iEnd;
- iOff+=pgszSrc
- ){
- PgHdr *pSrcPg = 0;
- const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
- rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0);
- if( rc==SQLITE_OK ){
- u8 *zData = sqlite3PagerGetData(pSrcPg);
- rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
- }
- sqlite3PagerUnref(pSrcPg);
- }
- if( rc==SQLITE_OK ){
- rc = backupTruncateFile(pFile, iSize);
- }
-
- /* Sync the database file to disk. */
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerSync(pDestPager, 0);
- }
- }else{
- sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
- rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
- }
-
- /* Finish committing the transaction to the destination database. */
- if( SQLITE_OK==rc
- && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
- ){
- rc = SQLITE_DONE;
- }
- }
- }
-
- /* If bCloseTrans is true, then this function opened a read transaction
- ** on the source database. Close the read transaction here. There is
- ** no need to check the return values of the btree methods here, as
- ** "committing" a read-only transaction cannot fail.
- */
- if( bCloseTrans ){
- TESTONLY( int rc2 );
- TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
- TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
- assert( rc2==SQLITE_OK );
- }
-
- if( rc==SQLITE_IOERR_NOMEM ){
- rc = SQLITE_NOMEM_BKPT;
- }
- p->rc = rc;
- }
- if( p->pDestDb ){
- sqlite3_mutex_leave(p->pDestDb->mutex);
- }
- sqlite3BtreeLeave(p->pSrc);
- sqlite3_mutex_leave(p->pSrcDb->mutex);
- return rc;
-}
-
-/*
-** Release all resources associated with an sqlite3_backup* handle.
-*/
-int sqlite3_backup_finish(sqlite3_backup *p){
- sqlite3_backup **pp; /* Ptr to head of pagers backup list */
- sqlite3 *pSrcDb; /* Source database connection */
- int rc; /* Value to return */
-
- /* Enter the mutexes */
- if( p==0 ) return SQLITE_OK;
- pSrcDb = p->pSrcDb;
- sqlite3_mutex_enter(pSrcDb->mutex);
- sqlite3BtreeEnter(p->pSrc);
- if( p->pDestDb ){
- sqlite3_mutex_enter(p->pDestDb->mutex);
- }
-
- /* Detach this backup from the source pager. */
- if( p->pDestDb ){
- p->pSrc->nBackup--;
- }
- if( p->isAttached ){
- pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
- while( *pp!=p ){
- pp = &(*pp)->pNext;
- }
- *pp = p->pNext;
- }
-
- /* If a transaction is still open on the Btree, roll it back. */
- sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
-
- /* Set the error code of the destination database handle. */
- rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
- if( p->pDestDb ){
- sqlite3Error(p->pDestDb, rc);
-
- /* Exit the mutexes and free the backup context structure. */
- sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
- }
- sqlite3BtreeLeave(p->pSrc);
- if( p->pDestDb ){
- /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
- ** call to sqlite3_backup_init() and is destroyed by a call to
- ** sqlite3_backup_finish(). */
- sqlite3_free(p);
- }
- sqlite3LeaveMutexAndCloseZombie(pSrcDb);
- return rc;
-}
-
-/*
-** Return the number of pages still to be backed up as of the most recent
-** call to sqlite3_backup_step().
-*/
-int sqlite3_backup_remaining(sqlite3_backup *p){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( p==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- return p->nRemaining;
-}
-
-/*
-** Return the total number of pages in the source database as of the most
-** recent call to sqlite3_backup_step().
-*/
-int sqlite3_backup_pagecount(sqlite3_backup *p){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( p==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- return p->nPagecount;
-}
-
-/*
-** This function is called after the contents of page iPage of the
-** source database have been modified. If page iPage has already been
-** copied into the destination database, then the data written to the
-** destination is now invalidated. The destination copy of iPage needs
-** to be updated with the new data before the backup operation is
-** complete.
-**
-** It is assumed that the mutex associated with the BtShared object
-** corresponding to the source database is held when this function is
-** called.
-*/
-static SQLITE_NOINLINE void backupUpdate(
- sqlite3_backup *p,
- Pgno iPage,
- const u8 *aData
-){
- assert( p!=0 );
- do{
- assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
- if( !isFatalError(p->rc) && iPage<p->iNext ){
- /* The backup process p has already copied page iPage. But now it
- ** has been modified by a transaction on the source pager. Copy
- ** the new data into the backup.
- */
- int rc;
- assert( p->pDestDb );
- sqlite3_mutex_enter(p->pDestDb->mutex);
- rc = backupOnePage(p, iPage, aData, 1);
- sqlite3_mutex_leave(p->pDestDb->mutex);
- assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
- if( rc!=SQLITE_OK ){
- p->rc = rc;
- }
- }
- }while( (p = p->pNext)!=0 );
-}
-void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
- if( pBackup ) backupUpdate(pBackup, iPage, aData);
-}
-
-/*
-** Restart the backup process. This is called when the pager layer
-** detects that the database has been modified by an external database
-** connection. In this case there is no way of knowing which of the
-** pages that have been copied into the destination database are still
-** valid and which are not, so the entire process needs to be restarted.
-**
-** It is assumed that the mutex associated with the BtShared object
-** corresponding to the source database is held when this function is
-** called.
-*/
-void sqlite3BackupRestart(sqlite3_backup *pBackup){
- sqlite3_backup *p; /* Iterator variable */
- for(p=pBackup; p; p=p->pNext){
- assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
- p->iNext = 1;
- }
-}
-
-#ifndef SQLITE_OMIT_VACUUM
-/*
-** Copy the complete content of pBtFrom into pBtTo. A transaction
-** must be active for both files.
-**
-** The size of file pTo may be reduced by this operation. If anything
-** goes wrong, the transaction on pTo is rolled back. If successful, the
-** transaction is committed before returning.
-*/
-int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
- int rc;
- sqlite3_file *pFd; /* File descriptor for database pTo */
- sqlite3_backup b;
- sqlite3BtreeEnter(pTo);
- sqlite3BtreeEnter(pFrom);
-
- assert( sqlite3BtreeIsInTrans(pTo) );
- pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
- if( pFd->pMethods ){
- i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
- rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte);
- if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
- if( rc ) goto copy_finished;
- }
-
- /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set
- ** to 0. This is used by the implementations of sqlite3_backup_step()
- ** and sqlite3_backup_finish() to detect that they are being called
- ** from this function, not directly by the user.
- */
- memset(&b, 0, sizeof(b));
- b.pSrcDb = pFrom->db;
- b.pSrc = pFrom;
- b.pDest = pTo;
- b.iNext = 1;
-
-#ifdef SQLITE_HAS_CODEC
- sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom));
-#endif
-
- /* 0x7FFFFFFF is the hard limit for the number of pages in a database
- ** file. By passing this as the number of pages to copy to
- ** sqlite3_backup_step(), we can guarantee that the copy finishes
- ** within a single call (unless an error occurs). The assert() statement
- ** checks this assumption - (p->rc) should be set to either SQLITE_DONE
- ** or an error code. */
- sqlite3_backup_step(&b, 0x7FFFFFFF);
- assert( b.rc!=SQLITE_OK );
-
- rc = sqlite3_backup_finish(&b);
- if( rc==SQLITE_OK ){
- pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
- }else{
- sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
- }
-
- assert( sqlite3BtreeIsInTrans(pTo)==0 );
-copy_finished:
- sqlite3BtreeLeave(pFrom);
- sqlite3BtreeLeave(pTo);
- return rc;
-}
-#endif /* SQLITE_OMIT_VACUUM */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/bitvec.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/bitvec.c
deleted file mode 100644
index bd4a09429b2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/bitvec.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-** 2008 February 16
-**
-** 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 an object that represents a fixed-length
-** bitmap. Bits are numbered starting with 1.
-**
-** A bitmap is used to record which pages of a database file have been
-** journalled during a transaction, or which pages have the "dont-write"
-** property. Usually only a few pages are meet either condition.
-** So the bitmap is usually sparse and has low cardinality.
-** But sometimes (for example when during a DROP of a large table) most
-** or all of the pages in a database can get journalled. In those cases,
-** the bitmap becomes dense with high cardinality. The algorithm needs
-** to handle both cases well.
-**
-** The size of the bitmap is fixed when the object is created.
-**
-** All bits are clear when the bitmap is created. Individual bits
-** may be set or cleared one at a time.
-**
-** Test operations are about 100 times more common that set operations.
-** Clear operations are exceedingly rare. There are usually between
-** 5 and 500 set operations per Bitvec object, though the number of sets can
-** sometimes grow into tens of thousands or larger. The size of the
-** Bitvec object is the number of pages in the database file at the
-** start of a transaction, and is thus usually less than a few thousand,
-** but can be as large as 2 billion for a really big database.
-*/
-#include "sqliteInt.h"
-
-/* Size of the Bitvec structure in bytes. */
-#define BITVEC_SZ 512
-
-/* Round the union size down to the nearest pointer boundary, since that's how
-** it will be aligned within the Bitvec struct. */
-#define BITVEC_USIZE \
- (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
-
-/* Type of the array "element" for the bitmap representation.
-** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE.
-** Setting this to the "natural word" size of your CPU may improve
-** performance. */
-#define BITVEC_TELEM u8
-/* Size, in bits, of the bitmap element. */
-#define BITVEC_SZELEM 8
-/* Number of elements in a bitmap array. */
-#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM))
-/* Number of bits in the bitmap array. */
-#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM)
-
-/* Number of u32 values in hash table. */
-#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
-/* Maximum number of entries in hash table before
-** sub-dividing and re-hashing. */
-#define BITVEC_MXHASH (BITVEC_NINT/2)
-/* Hashing function for the aHash representation.
-** Empirical testing showed that the *37 multiplier
-** (an arbitrary prime)in the hash function provided
-** no fewer collisions than the no-op *1. */
-#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
-
-#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
-
-
-/*
-** A bitmap is an instance of the following structure.
-**
-** This bitmap records the existence of zero or more bits
-** with values between 1 and iSize, inclusive.
-**
-** There are three possible representations of the bitmap.
-** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
-** bitmap. The least significant bit is bit 1.
-**
-** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
-** a hash table that will hold up to BITVEC_MXHASH distinct values.
-**
-** Otherwise, the value i is redirected into one of BITVEC_NPTR
-** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap
-** handles up to iDivisor separate values of i. apSub[0] holds
-** values between 1 and iDivisor. apSub[1] holds values between
-** iDivisor+1 and 2*iDivisor. apSub[N] holds values between
-** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized
-** to hold deal with values between 1 and iDivisor.
-*/
-struct Bitvec {
- u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */
- u32 nSet; /* Number of bits that are set - only valid for aHash
- ** element. Max is BITVEC_NINT. For BITVEC_SZ of 512,
- ** this would be 125. */
- u32 iDivisor; /* Number of bits handled by each apSub[] entry. */
- /* Should >=0 for apSub element. */
- /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */
- /* For a BITVEC_SZ of 512, this would be 34,359,739. */
- union {
- BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */
- u32 aHash[BITVEC_NINT]; /* Hash table representation */
- Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
- } u;
-};
-
-/*
-** Create a new bitmap object able to handle bits between 0 and iSize,
-** inclusive. Return a pointer to the new object. Return NULL if
-** malloc fails.
-*/
-Bitvec *sqlite3BitvecCreate(u32 iSize){
- Bitvec *p;
- assert( sizeof(*p)==BITVEC_SZ );
- p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
- p->iSize = iSize;
- }
- return p;
-}
-
-/*
-** Check to see if the i-th bit is set. Return true or false.
-** If p is NULL (if the bitmap has not been created) or if
-** i is out of range, then return false.
-*/
-int sqlite3BitvecTestNotNull(Bitvec *p, u32 i){
- assert( p!=0 );
- i--;
- if( i>=p->iSize ) return 0;
- while( p->iDivisor ){
- u32 bin = i/p->iDivisor;
- i = i%p->iDivisor;
- p = p->u.apSub[bin];
- if (!p) {
- return 0;
- }
- }
- if( p->iSize<=BITVEC_NBIT ){
- return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
- } else{
- u32 h = BITVEC_HASH(i++);
- while( p->u.aHash[h] ){
- if( p->u.aHash[h]==i ) return 1;
- h = (h+1) % BITVEC_NINT;
- }
- return 0;
- }
-}
-int sqlite3BitvecTest(Bitvec *p, u32 i){
- return p!=0 && sqlite3BitvecTestNotNull(p,i);
-}
-
-/*
-** Set the i-th bit. Return 0 on success and an error code if
-** anything goes wrong.
-**
-** This routine might cause sub-bitmaps to be allocated. Failing
-** to get the memory needed to hold the sub-bitmap is the only
-** that can go wrong with an insert, assuming p and i are valid.
-**
-** The calling function must ensure that p is a valid Bitvec object
-** and that the value for "i" is within range of the Bitvec object.
-** Otherwise the behavior is undefined.
-*/
-int sqlite3BitvecSet(Bitvec *p, u32 i){
- u32 h;
- if( p==0 ) return SQLITE_OK;
- assert( i>0 );
- assert( i<=p->iSize );
- i--;
- while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
- u32 bin = i/p->iDivisor;
- i = i%p->iDivisor;
- if( p->u.apSub[bin]==0 ){
- p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
- if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM_BKPT;
- }
- p = p->u.apSub[bin];
- }
- if( p->iSize<=BITVEC_NBIT ){
- p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
- return SQLITE_OK;
- }
- h = BITVEC_HASH(i++);
- /* if there wasn't a hash collision, and this doesn't */
- /* completely fill the hash, then just add it without */
- /* worring about sub-dividing and re-hashing. */
- if( !p->u.aHash[h] ){
- if (p->nSet<(BITVEC_NINT-1)) {
- goto bitvec_set_end;
- } else {
- goto bitvec_set_rehash;
- }
- }
- /* there was a collision, check to see if it's already */
- /* in hash, if not, try to find a spot for it */
- do {
- if( p->u.aHash[h]==i ) return SQLITE_OK;
- h++;
- if( h>=BITVEC_NINT ) h = 0;
- } while( p->u.aHash[h] );
- /* we didn't find it in the hash. h points to the first */
- /* available free spot. check to see if this is going to */
- /* make our hash too "full". */
-bitvec_set_rehash:
- if( p->nSet>=BITVEC_MXHASH ){
- unsigned int j;
- int rc;
- u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash));
- if( aiValues==0 ){
- return SQLITE_NOMEM_BKPT;
- }else{
- memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
- memset(p->u.apSub, 0, sizeof(p->u.apSub));
- p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
- rc = sqlite3BitvecSet(p, i);
- for(j=0; j<BITVEC_NINT; j++){
- if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
- }
- sqlite3StackFree(0, aiValues);
- return rc;
- }
- }
-bitvec_set_end:
- p->nSet++;
- p->u.aHash[h] = i;
- return SQLITE_OK;
-}
-
-/*
-** Clear the i-th bit.
-**
-** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage
-** that BitvecClear can use to rebuilt its hash table.
-*/
-void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
- if( p==0 ) return;
- assert( i>0 );
- i--;
- while( p->iDivisor ){
- u32 bin = i/p->iDivisor;
- i = i%p->iDivisor;
- p = p->u.apSub[bin];
- if (!p) {
- return;
- }
- }
- if( p->iSize<=BITVEC_NBIT ){
- p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
- }else{
- unsigned int j;
- u32 *aiValues = pBuf;
- memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
- memset(p->u.aHash, 0, sizeof(p->u.aHash));
- p->nSet = 0;
- for(j=0; j<BITVEC_NINT; j++){
- if( aiValues[j] && aiValues[j]!=(i+1) ){
- u32 h = BITVEC_HASH(aiValues[j]-1);
- p->nSet++;
- while( p->u.aHash[h] ){
- h++;
- if( h>=BITVEC_NINT ) h = 0;
- }
- p->u.aHash[h] = aiValues[j];
- }
- }
- }
-}
-
-/*
-** Destroy a bitmap object. Reclaim all memory used.
-*/
-void sqlite3BitvecDestroy(Bitvec *p){
- if( p==0 ) return;
- if( p->iDivisor ){
- unsigned int i;
- for(i=0; i<BITVEC_NPTR; i++){
- sqlite3BitvecDestroy(p->u.apSub[i]);
- }
- }
- sqlite3_free(p);
-}
-
-/*
-** Return the value of the iSize parameter specified when Bitvec *p
-** was created.
-*/
-u32 sqlite3BitvecSize(Bitvec *p){
- return p->iSize;
-}
-
-#ifndef SQLITE_UNTESTABLE
-/*
-** Let V[] be an array of unsigned characters sufficient to hold
-** up to N bits. Let I be an integer between 0 and N. 0<=I<N.
-** Then the following macros can be used to set, clear, or test
-** individual bits within V.
-*/
-#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
-#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
-#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
-
-/*
-** This routine runs an extensive test of the Bitvec code.
-**
-** The input is an array of integers that acts as a program
-** to test the Bitvec. The integers are opcodes followed
-** by 0, 1, or 3 operands, depending on the opcode. Another
-** opcode follows immediately after the last operand.
-**
-** There are 6 opcodes numbered from 0 through 5. 0 is the
-** "halt" opcode and causes the test to end.
-**
-** 0 Halt and return the number of errors
-** 1 N S X Set N bits beginning with S and incrementing by X
-** 2 N S X Clear N bits beginning with S and incrementing by X
-** 3 N Set N randomly chosen bits
-** 4 N Clear N randomly chosen bits
-** 5 N S X Set N bits from S increment X in array only, not in bitvec
-**
-** The opcodes 1 through 4 perform set and clear operations are performed
-** on both a Bitvec object and on a linear array of bits obtained from malloc.
-** Opcode 5 works on the linear array only, not on the Bitvec.
-** Opcode 5 is used to deliberately induce a fault in order to
-** confirm that error detection works.
-**
-** At the conclusion of the test the linear array is compared
-** against the Bitvec object. If there are any differences,
-** an error is returned. If they are the same, zero is returned.
-**
-** If a memory allocation error occurs, return -1.
-*/
-int sqlite3BitvecBuiltinTest(int sz, int *aOp){
- Bitvec *pBitvec = 0;
- unsigned char *pV = 0;
- int rc = -1;
- int i, nx, pc, op;
- void *pTmpSpace;
-
- /* Allocate the Bitvec to be tested and a linear array of
- ** bits to act as the reference */
- pBitvec = sqlite3BitvecCreate( sz );
- pV = sqlite3MallocZero( (sz+7)/8 + 1 );
- pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
- if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
-
- /* NULL pBitvec tests */
- sqlite3BitvecSet(0, 1);
- sqlite3BitvecClear(0, 1, pTmpSpace);
-
- /* Run the program */
- pc = 0;
- while( (op = aOp[pc])!=0 ){
- switch( op ){
- case 1:
- case 2:
- case 5: {
- nx = 4;
- i = aOp[pc+2] - 1;
- aOp[pc+2] += aOp[pc+3];
- break;
- }
- case 3:
- case 4:
- default: {
- nx = 2;
- sqlite3_randomness(sizeof(i), &i);
- break;
- }
- }
- if( (--aOp[pc+1]) > 0 ) nx = 0;
- pc += nx;
- i = (i & 0x7fffffff)%sz;
- if( (op & 1)!=0 ){
- SETBIT(pV, (i+1));
- if( op!=5 ){
- if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
- }
- }else{
- CLEARBIT(pV, (i+1));
- sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
- }
- }
-
- /* Test to make sure the linear array exactly matches the
- ** Bitvec object. Start with the assumption that they do
- ** match (rc==0). Change rc to non-zero if a discrepancy
- ** is found.
- */
- rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
- + sqlite3BitvecTest(pBitvec, 0)
- + (sqlite3BitvecSize(pBitvec) - sz);
- for(i=1; i<=sz; i++){
- if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
- rc = i;
- break;
- }
- }
-
- /* Free allocated structure */
-bitvec_end:
- sqlite3_free(pTmpSpace);
- sqlite3_free(pV);
- sqlite3BitvecDestroy(pBitvec);
- return rc;
-}
-#endif /* SQLITE_UNTESTABLE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/btmutex.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/btmutex.c
deleted file mode 100644
index 275a93ff21c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/btmutex.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
-** 2007 August 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 contains code used to implement mutexes on Btree objects.
-** This code really belongs in btree.c. But btree.c is getting too
-** big and we want to break it down some. This packaged seemed like
-** a good breakout.
-*/
-#include "btreeInt.h"
-#ifndef SQLITE_OMIT_SHARED_CACHE
-#if SQLITE_THREADSAFE
-
-/*
-** Obtain the BtShared mutex associated with B-Tree handle p. Also,
-** set BtShared.db to the database handle associated with p and the
-** p->locked boolean to true.
-*/
-static void lockBtreeMutex(Btree *p){
- assert( p->locked==0 );
- assert( sqlite3_mutex_notheld(p->pBt->mutex) );
- assert( sqlite3_mutex_held(p->db->mutex) );
-
- sqlite3_mutex_enter(p->pBt->mutex);
- p->pBt->db = p->db;
- p->locked = 1;
-}
-
-/*
-** Release the BtShared mutex associated with B-Tree handle p and
-** clear the p->locked boolean.
-*/
-static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){
- BtShared *pBt = p->pBt;
- assert( p->locked==1 );
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( sqlite3_mutex_held(p->db->mutex) );
- assert( p->db==pBt->db );
-
- sqlite3_mutex_leave(pBt->mutex);
- p->locked = 0;
-}
-
-/* Forward reference */
-static void SQLITE_NOINLINE btreeLockCarefully(Btree *p);
-
-/*
-** Enter a mutex on the given BTree object.
-**
-** If the object is not sharable, then no mutex is ever required
-** and this routine is a no-op. The underlying mutex is non-recursive.
-** But we keep a reference count in Btree.wantToLock so the behavior
-** of this interface is recursive.
-**
-** To avoid deadlocks, multiple Btrees are locked in the same order
-** by all database connections. The p->pNext is a list of other
-** Btrees belonging to the same database connection as the p Btree
-** which need to be locked after p. If we cannot get a lock on
-** p, then first unlock all of the others on p->pNext, then wait
-** for the lock to become available on p, then relock all of the
-** subsequent Btrees that desire a lock.
-*/
-void sqlite3BtreeEnter(Btree *p){
- /* Some basic sanity checking on the Btree. The list of Btrees
- ** connected by pNext and pPrev should be in sorted order by
- ** Btree.pBt value. All elements of the list should belong to
- ** the same connection. Only shared Btrees are on the list. */
- assert( p->pNext==0 || p->pNext->pBt>p->pBt );
- assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
- assert( p->pNext==0 || p->pNext->db==p->db );
- assert( p->pPrev==0 || p->pPrev->db==p->db );
- assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
-
- /* Check for locking consistency */
- assert( !p->locked || p->wantToLock>0 );
- assert( p->sharable || p->wantToLock==0 );
-
- /* We should already hold a lock on the database connection */
- assert( sqlite3_mutex_held(p->db->mutex) );
-
- /* Unless the database is sharable and unlocked, then BtShared.db
- ** should already be set correctly. */
- assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db );
-
- if( !p->sharable ) return;
- p->wantToLock++;
- if( p->locked ) return;
- btreeLockCarefully(p);
-}
-
-/* This is a helper function for sqlite3BtreeLock(). By moving
-** complex, but seldom used logic, out of sqlite3BtreeLock() and
-** into this routine, we avoid unnecessary stack pointer changes
-** and thus help the sqlite3BtreeLock() routine to run much faster
-** in the common case.
-*/
-static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){
- Btree *pLater;
-
- /* In most cases, we should be able to acquire the lock we
- ** want without having to go through the ascending lock
- ** procedure that follows. Just be sure not to block.
- */
- if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
- p->pBt->db = p->db;
- p->locked = 1;
- return;
- }
-
- /* To avoid deadlock, first release all locks with a larger
- ** BtShared address. Then acquire our lock. Then reacquire
- ** the other BtShared locks that we used to hold in ascending
- ** order.
- */
- for(pLater=p->pNext; pLater; pLater=pLater->pNext){
- assert( pLater->sharable );
- assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
- assert( !pLater->locked || pLater->wantToLock>0 );
- if( pLater->locked ){
- unlockBtreeMutex(pLater);
- }
- }
- lockBtreeMutex(p);
- for(pLater=p->pNext; pLater; pLater=pLater->pNext){
- if( pLater->wantToLock ){
- lockBtreeMutex(pLater);
- }
- }
-}
-
-
-/*
-** Exit the recursive mutex on a Btree.
-*/
-void sqlite3BtreeLeave(Btree *p){
- assert( sqlite3_mutex_held(p->db->mutex) );
- if( p->sharable ){
- assert( p->wantToLock>0 );
- p->wantToLock--;
- if( p->wantToLock==0 ){
- unlockBtreeMutex(p);
- }
- }
-}
-
-#ifndef NDEBUG
-/*
-** Return true if the BtShared mutex is held on the btree, or if the
-** B-Tree is not marked as sharable.
-**
-** This routine is used only from within assert() statements.
-*/
-int sqlite3BtreeHoldsMutex(Btree *p){
- assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 );
- assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db );
- assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) );
- assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) );
-
- return (p->sharable==0 || p->locked);
-}
-#endif
-
-
-/*
-** Enter the mutex on every Btree associated with a database
-** connection. This is needed (for example) prior to parsing
-** a statement since we will be comparing table and column names
-** against all schemas and we do not want those schemas being
-** reset out from under us.
-**
-** There is a corresponding leave-all procedures.
-**
-** Enter the mutexes in accending order by BtShared pointer address
-** to avoid the possibility of deadlock when two threads with
-** two or more btrees in common both try to lock all their btrees
-** at the same instant.
-*/
-static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
- int i;
- int skipOk = 1;
- Btree *p;
- assert( sqlite3_mutex_held(db->mutex) );
- for(i=0; i<db->nDb; i++){
- p = db->aDb[i].pBt;
- if( p && p->sharable ){
- sqlite3BtreeEnter(p);
- skipOk = 0;
- }
- }
- db->noSharedCache = skipOk;
-}
-void sqlite3BtreeEnterAll(sqlite3 *db){
- if( db->noSharedCache==0 ) btreeEnterAll(db);
-}
-static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){
- int i;
- Btree *p;
- assert( sqlite3_mutex_held(db->mutex) );
- for(i=0; i<db->nDb; i++){
- p = db->aDb[i].pBt;
- if( p ) sqlite3BtreeLeave(p);
- }
-}
-void sqlite3BtreeLeaveAll(sqlite3 *db){
- if( db->noSharedCache==0 ) btreeLeaveAll(db);
-}
-
-#ifndef NDEBUG
-/*
-** Return true if the current thread holds the database connection
-** mutex and all required BtShared mutexes.
-**
-** This routine is used inside assert() statements only.
-*/
-int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
- int i;
- if( !sqlite3_mutex_held(db->mutex) ){
- return 0;
- }
- for(i=0; i<db->nDb; i++){
- Btree *p;
- p = db->aDb[i].pBt;
- if( p && p->sharable &&
- (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
- return 0;
- }
- }
- return 1;
-}
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/*
-** Return true if the correct mutexes are held for accessing the
-** db->aDb[iDb].pSchema structure. The mutexes required for schema
-** access are:
-**
-** (1) The mutex on db
-** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt.
-**
-** If pSchema is not NULL, then iDb is computed from pSchema and
-** db using sqlite3SchemaToIndex().
-*/
-int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
- Btree *p;
- assert( db!=0 );
- if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
- assert( iDb>=0 && iDb<db->nDb );
- if( !sqlite3_mutex_held(db->mutex) ) return 0;
- if( iDb==1 ) return 1;
- p = db->aDb[iDb].pBt;
- assert( p!=0 );
- return p->sharable==0 || p->locked==1;
-}
-#endif /* NDEBUG */
-
-#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */
-/*
-** The following are special cases for mutex enter routines for use
-** in single threaded applications that use shared cache. Except for
-** these two routines, all mutex operations are no-ops in that case and
-** are null #defines in btree.h.
-**
-** If shared cache is disabled, then all btree mutex routines, including
-** the ones below, are no-ops and are null #defines in btree.h.
-*/
-
-void sqlite3BtreeEnter(Btree *p){
- p->pBt->db = p->db;
-}
-void sqlite3BtreeEnterAll(sqlite3 *db){
- int i;
- for(i=0; i<db->nDb; i++){
- Btree *p = db->aDb[i].pBt;
- if( p ){
- p->pBt->db = p->db;
- }
- }
-}
-#endif /* if SQLITE_THREADSAFE */
-
-#ifndef SQLITE_OMIT_INCRBLOB
-/*
-** Enter a mutex on a Btree given a cursor owned by that Btree.
-**
-** These entry points are used by incremental I/O only. Enter() is required
-** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not
-** the build is threadsafe. Leave() is only required by threadsafe builds.
-*/
-void sqlite3BtreeEnterCursor(BtCursor *pCur){
- sqlite3BtreeEnter(pCur->pBtree);
-}
-# if SQLITE_THREADSAFE
-void sqlite3BtreeLeaveCursor(BtCursor *pCur){
- sqlite3BtreeLeave(pCur->pBtree);
-}
-# endif
-#endif /* ifndef SQLITE_OMIT_INCRBLOB */
-
-#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/btree.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/btree.c
deleted file mode 100644
index fb3b89fe139..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/btree.c
+++ /dev/null
@@ -1,10143 +0,0 @@
-/*
-** 2004 April 6
-**
-** 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 an external (disk-based) database using BTrees.
-** See the header comment on "btreeInt.h" for additional information.
-** Including a description of file format and an overview of operation.
-*/
-#include "btreeInt.h"
-
-/*
-** The header string that appears at the beginning of every
-** SQLite database.
-*/
-static const char zMagicHeader[] = SQLITE_FILE_HEADER;
-
-/*
-** Set this global variable to 1 to enable tracing using the TRACE
-** macro.
-*/
-#if 0
-int sqlite3BtreeTrace=1; /* True to enable tracing */
-# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);}
-#else
-# define TRACE(X)
-#endif
-
-/*
-** Extract a 2-byte big-endian integer from an array of unsigned bytes.
-** But if the value is zero, make it 65536.
-**
-** This routine is used to extract the "offset to cell content area" value
-** from the header of a btree page. If the page size is 65536 and the page
-** is empty, the offset should be 65536, but the 2-byte value stores zero.
-** This routine makes the necessary adjustment to 65536.
-*/
-#define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1)
-
-/*
-** Values passed as the 5th argument to allocateBtreePage()
-*/
-#define BTALLOC_ANY 0 /* Allocate any page */
-#define BTALLOC_EXACT 1 /* Allocate exact page if possible */
-#define BTALLOC_LE 2 /* Allocate any page <= the parameter */
-
-/*
-** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not
-** defined, or 0 if it is. For example:
-**
-** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum);
-*/
-#ifndef SQLITE_OMIT_AUTOVACUUM
-#define IfNotOmitAV(expr) (expr)
-#else
-#define IfNotOmitAV(expr) 0
-#endif
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/*
-** A list of BtShared objects that are eligible for participation
-** in shared cache. This variable has file scope during normal builds,
-** but the test harness needs to access it so we make it global for
-** test builds.
-**
-** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER.
-*/
-#ifdef SQLITE_TEST
-BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
-#else
-static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
-#endif
-#endif /* SQLITE_OMIT_SHARED_CACHE */
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/*
-** Enable or disable the shared pager and schema features.
-**
-** This routine has no effect on existing database connections.
-** The shared cache setting effects only future calls to
-** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2().
-*/
-int sqlite3_enable_shared_cache(int enable){
- sqlite3GlobalConfig.sharedCacheEnabled = enable;
- return SQLITE_OK;
-}
-#endif
-
-
-
-#ifdef SQLITE_OMIT_SHARED_CACHE
- /*
- ** The functions querySharedCacheTableLock(), setSharedCacheTableLock(),
- ** and clearAllSharedCacheTableLocks()
- ** manipulate entries in the BtShared.pLock linked list used to store
- ** shared-cache table level locks. If the library is compiled with the
- ** shared-cache feature disabled, then there is only ever one user
- ** of each BtShared structure and so this locking is not necessary.
- ** So define the lock related functions as no-ops.
- */
- #define querySharedCacheTableLock(a,b,c) SQLITE_OK
- #define setSharedCacheTableLock(a,b,c) SQLITE_OK
- #define clearAllSharedCacheTableLocks(a)
- #define downgradeAllSharedCacheTableLocks(a)
- #define hasSharedCacheTableLock(a,b,c,d) 1
- #define hasReadConflicts(a, b) 0
-#endif
-
-/*
-** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single
-** (MemPage*) as an argument. The (MemPage*) must not be NULL.
-**
-** If SQLITE_DEBUG is not defined, then this macro is equivalent to
-** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message
-** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented
-** with the page number and filename associated with the (MemPage*).
-*/
-#ifdef SQLITE_DEBUG
-int corruptPageError(int lineno, MemPage *p){
- char *zMsg;
- sqlite3BeginBenignMalloc();
- zMsg = sqlite3_mprintf("database corruption page %d of %s",
- (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0)
- );
- sqlite3EndBenignMalloc();
- if( zMsg ){
- sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
- }
- sqlite3_free(zMsg);
- return SQLITE_CORRUPT_BKPT;
-}
-# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage)
-#else
-# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno)
-#endif
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-
-#ifdef SQLITE_DEBUG
-/*
-**** This function is only used as part of an assert() statement. ***
-**
-** Check to see if pBtree holds the required locks to read or write to the
-** table with root page iRoot. Return 1 if it does and 0 if not.
-**
-** For example, when writing to a table with root-page iRoot via
-** Btree connection pBtree:
-**
-** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) );
-**
-** When writing to an index that resides in a sharable database, the
-** caller should have first obtained a lock specifying the root page of
-** the corresponding table. This makes things a bit more complicated,
-** as this module treats each table as a separate structure. To determine
-** the table corresponding to the index being written, this
-** function has to search through the database schema.
-**
-** Instead of a lock on the table/index rooted at page iRoot, the caller may
-** hold a write-lock on the schema table (root page 1). This is also
-** acceptable.
-*/
-static int hasSharedCacheTableLock(
- Btree *pBtree, /* Handle that must hold lock */
- Pgno iRoot, /* Root page of b-tree */
- int isIndex, /* True if iRoot is the root of an index b-tree */
- int eLockType /* Required lock type (READ_LOCK or WRITE_LOCK) */
-){
- Schema *pSchema = (Schema *)pBtree->pBt->pSchema;
- Pgno iTab = 0;
- BtLock *pLock;
-
- /* If this database is not shareable, or if the client is reading
- ** and has the read-uncommitted flag set, then no lock is required.
- ** Return true immediately.
- */
- if( (pBtree->sharable==0)
- || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommit))
- ){
- return 1;
- }
-
- /* If the client is reading or writing an index and the schema is
- ** not loaded, then it is too difficult to actually check to see if
- ** the correct locks are held. So do not bother - just return true.
- ** This case does not come up very often anyhow.
- */
- if( isIndex && (!pSchema || (pSchema->schemaFlags&DB_SchemaLoaded)==0) ){
- return 1;
- }
-
- /* Figure out the root-page that the lock should be held on. For table
- ** b-trees, this is just the root page of the b-tree being read or
- ** written. For index b-trees, it is the root page of the associated
- ** table. */
- if( isIndex ){
- HashElem *p;
- for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
- Index *pIdx = (Index *)sqliteHashData(p);
- if( pIdx->tnum==(int)iRoot ){
- if( iTab ){
- /* Two or more indexes share the same root page. There must
- ** be imposter tables. So just return true. The assert is not
- ** useful in that case. */
- return 1;
- }
- iTab = pIdx->pTable->tnum;
- }
- }
- }else{
- iTab = iRoot;
- }
-
- /* Search for the required lock. Either a write-lock on root-page iTab, a
- ** write-lock on the schema table, or (if the client is reading) a
- ** read-lock on iTab will suffice. Return 1 if any of these are found. */
- for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){
- if( pLock->pBtree==pBtree
- && (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1))
- && pLock->eLock>=eLockType
- ){
- return 1;
- }
- }
-
- /* Failed to find the required lock. */
- return 0;
-}
-#endif /* SQLITE_DEBUG */
-
-#ifdef SQLITE_DEBUG
-/*
-**** This function may be used as part of assert() statements only. ****
-**
-** Return true if it would be illegal for pBtree to write into the
-** table or index rooted at iRoot because other shared connections are
-** simultaneously reading that same table or index.
-**
-** It is illegal for pBtree to write if some other Btree object that
-** shares the same BtShared object is currently reading or writing
-** the iRoot table. Except, if the other Btree object has the
-** read-uncommitted flag set, then it is OK for the other object to
-** have a read cursor.
-**
-** For example, before writing to any part of the table or index
-** rooted at page iRoot, one should call:
-**
-** assert( !hasReadConflicts(pBtree, iRoot) );
-*/
-static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
- BtCursor *p;
- for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- if( p->pgnoRoot==iRoot
- && p->pBtree!=pBtree
- && 0==(p->pBtree->db->flags & SQLITE_ReadUncommit)
- ){
- return 1;
- }
- }
- return 0;
-}
-#endif /* #ifdef SQLITE_DEBUG */
-
-/*
-** Query to see if Btree handle p may obtain a lock of type eLock
-** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
-** SQLITE_OK if the lock may be obtained (by calling
-** setSharedCacheTableLock()), or SQLITE_LOCKED if not.
-*/
-static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
- BtShared *pBt = p->pBt;
- BtLock *pIter;
-
- assert( sqlite3BtreeHoldsMutex(p) );
- assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
- assert( p->db!=0 );
- assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 );
-
- /* If requesting a write-lock, then the Btree must have an open write
- ** transaction on this file. And, obviously, for this to be so there
- ** must be an open write transaction on the file itself.
- */
- assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) );
- assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE );
-
- /* This routine is a no-op if the shared-cache is not enabled */
- if( !p->sharable ){
- return SQLITE_OK;
- }
-
- /* If some other connection is holding an exclusive lock, the
- ** requested lock may not be obtained.
- */
- if( pBt->pWriter!=p && (pBt->btsFlags & BTS_EXCLUSIVE)!=0 ){
- sqlite3ConnectionBlocked(p->db, pBt->pWriter->db);
- return SQLITE_LOCKED_SHAREDCACHE;
- }
-
- for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
- /* The condition (pIter->eLock!=eLock) in the following if(...)
- ** statement is a simplification of:
- **
- ** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
- **
- ** since we know that if eLock==WRITE_LOCK, then no other connection
- ** may hold a WRITE_LOCK on any table in this file (since there can
- ** only be a single writer).
- */
- assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK );
- assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK);
- if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){
- sqlite3ConnectionBlocked(p->db, pIter->pBtree->db);
- if( eLock==WRITE_LOCK ){
- assert( p==pBt->pWriter );
- pBt->btsFlags |= BTS_PENDING;
- }
- return SQLITE_LOCKED_SHAREDCACHE;
- }
- }
- return SQLITE_OK;
-}
-#endif /* !SQLITE_OMIT_SHARED_CACHE */
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/*
-** Add a lock on the table with root-page iTable to the shared-btree used
-** by Btree handle p. Parameter eLock must be either READ_LOCK or
-** WRITE_LOCK.
-**
-** This function assumes the following:
-**
-** (a) The specified Btree object p is connected to a sharable
-** database (one with the BtShared.sharable flag set), and
-**
-** (b) No other Btree objects hold a lock that conflicts
-** with the requested lock (i.e. querySharedCacheTableLock() has
-** already been called and returned SQLITE_OK).
-**
-** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM
-** is returned if a malloc attempt fails.
-*/
-static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
- BtShared *pBt = p->pBt;
- BtLock *pLock = 0;
- BtLock *pIter;
-
- assert( sqlite3BtreeHoldsMutex(p) );
- assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
- assert( p->db!=0 );
-
- /* A connection with the read-uncommitted flag set will never try to
- ** obtain a read-lock using this function. The only read-lock obtained
- ** by a connection in read-uncommitted mode is on the sqlite_master
- ** table, and that lock is obtained in BtreeBeginTrans(). */
- assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK );
-
- /* This function should only be called on a sharable b-tree after it
- ** has been determined that no other b-tree holds a conflicting lock. */
- assert( p->sharable );
- assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) );
-
- /* First search the list for an existing lock on this table. */
- for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
- if( pIter->iTable==iTable && pIter->pBtree==p ){
- pLock = pIter;
- break;
- }
- }
-
- /* If the above search did not find a BtLock struct associating Btree p
- ** with table iTable, allocate one and link it into the list.
- */
- if( !pLock ){
- pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock));
- if( !pLock ){
- return SQLITE_NOMEM_BKPT;
- }
- pLock->iTable = iTable;
- pLock->pBtree = p;
- pLock->pNext = pBt->pLock;
- pBt->pLock = pLock;
- }
-
- /* Set the BtLock.eLock variable to the maximum of the current lock
- ** and the requested lock. This means if a write-lock was already held
- ** and a read-lock requested, we don't incorrectly downgrade the lock.
- */
- assert( WRITE_LOCK>READ_LOCK );
- if( eLock>pLock->eLock ){
- pLock->eLock = eLock;
- }
-
- return SQLITE_OK;
-}
-#endif /* !SQLITE_OMIT_SHARED_CACHE */
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/*
-** Release all the table locks (locks obtained via calls to
-** the setSharedCacheTableLock() procedure) held by Btree object p.
-**
-** This function assumes that Btree p has an open read or write
-** transaction. If it does not, then the BTS_PENDING flag
-** may be incorrectly cleared.
-*/
-static void clearAllSharedCacheTableLocks(Btree *p){
- BtShared *pBt = p->pBt;
- BtLock **ppIter = &pBt->pLock;
-
- assert( sqlite3BtreeHoldsMutex(p) );
- assert( p->sharable || 0==*ppIter );
- assert( p->inTrans>0 );
-
- while( *ppIter ){
- BtLock *pLock = *ppIter;
- assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree );
- assert( pLock->pBtree->inTrans>=pLock->eLock );
- if( pLock->pBtree==p ){
- *ppIter = pLock->pNext;
- assert( pLock->iTable!=1 || pLock==&p->lock );
- if( pLock->iTable!=1 ){
- sqlite3_free(pLock);
- }
- }else{
- ppIter = &pLock->pNext;
- }
- }
-
- assert( (pBt->btsFlags & BTS_PENDING)==0 || pBt->pWriter );
- if( pBt->pWriter==p ){
- pBt->pWriter = 0;
- pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
- }else if( pBt->nTransaction==2 ){
- /* This function is called when Btree p is concluding its
- ** transaction. If there currently exists a writer, and p is not
- ** that writer, then the number of locks held by connections other
- ** than the writer must be about to drop to zero. In this case
- ** set the BTS_PENDING flag to 0.
- **
- ** If there is not currently a writer, then BTS_PENDING must
- ** be zero already. So this next line is harmless in that case.
- */
- pBt->btsFlags &= ~BTS_PENDING;
- }
-}
-
-/*
-** This function changes all write-locks held by Btree p into read-locks.
-*/
-static void downgradeAllSharedCacheTableLocks(Btree *p){
- BtShared *pBt = p->pBt;
- if( pBt->pWriter==p ){
- BtLock *pLock;
- pBt->pWriter = 0;
- pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
- for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){
- assert( pLock->eLock==READ_LOCK || pLock->pBtree==p );
- pLock->eLock = READ_LOCK;
- }
- }
-}
-
-#endif /* SQLITE_OMIT_SHARED_CACHE */
-
-static void releasePage(MemPage *pPage); /* Forward reference */
-static void releasePageOne(MemPage *pPage); /* Forward reference */
-static void releasePageNotNull(MemPage *pPage); /* Forward reference */
-
-/*
-***** This routine is used inside of assert() only ****
-**
-** Verify that the cursor holds the mutex on its BtShared
-*/
-#ifdef SQLITE_DEBUG
-static int cursorHoldsMutex(BtCursor *p){
- return sqlite3_mutex_held(p->pBt->mutex);
-}
-
-/* Verify that the cursor and the BtShared agree about what is the current
-** database connetion. This is important in shared-cache mode. If the database
-** connection pointers get out-of-sync, it is possible for routines like
-** btreeInitPage() to reference an stale connection pointer that references a
-** a connection that has already closed. This routine is used inside assert()
-** statements only and for the purpose of double-checking that the btree code
-** does keep the database connection pointers up-to-date.
-*/
-static int cursorOwnsBtShared(BtCursor *p){
- assert( cursorHoldsMutex(p) );
- return (p->pBtree->db==p->pBt->db);
-}
-#endif
-
-/*
-** Invalidate the overflow cache of the cursor passed as the first argument.
-** on the shared btree structure pBt.
-*/
-#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl)
-
-/*
-** Invalidate the overflow page-list cache for all cursors opened
-** on the shared btree structure pBt.
-*/
-static void invalidateAllOverflowCache(BtShared *pBt){
- BtCursor *p;
- assert( sqlite3_mutex_held(pBt->mutex) );
- for(p=pBt->pCursor; p; p=p->pNext){
- invalidateOverflowCache(p);
- }
-}
-
-#ifndef SQLITE_OMIT_INCRBLOB
-/*
-** This function is called before modifying the contents of a table
-** to invalidate any incrblob cursors that are open on the
-** row or one of the rows being modified.
-**
-** If argument isClearTable is true, then the entire contents of the
-** table is about to be deleted. In this case invalidate all incrblob
-** cursors open on any row within the table with root-page pgnoRoot.
-**
-** Otherwise, if argument isClearTable is false, then the row with
-** rowid iRow is being replaced or deleted. In this case invalidate
-** only those incrblob cursors open on that specific row.
-*/
-static void invalidateIncrblobCursors(
- Btree *pBtree, /* The database file to check */
- Pgno pgnoRoot, /* The table that might be changing */
- i64 iRow, /* The rowid that might be changing */
- int isClearTable /* True if all rows are being deleted */
-){
- BtCursor *p;
- if( pBtree->hasIncrblobCur==0 ) return;
- assert( sqlite3BtreeHoldsMutex(pBtree) );
- pBtree->hasIncrblobCur = 0;
- for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- if( (p->curFlags & BTCF_Incrblob)!=0 ){
- pBtree->hasIncrblobCur = 1;
- if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
- p->eState = CURSOR_INVALID;
- }
- }
- }
-}
-
-#else
- /* Stub function when INCRBLOB is omitted */
- #define invalidateIncrblobCursors(w,x,y,z)
-#endif /* SQLITE_OMIT_INCRBLOB */
-
-/*
-** Set bit pgno of the BtShared.pHasContent bitvec. This is called
-** when a page that previously contained data becomes a free-list leaf
-** page.
-**
-** The BtShared.pHasContent bitvec exists to work around an obscure
-** bug caused by the interaction of two useful IO optimizations surrounding
-** free-list leaf pages:
-**
-** 1) When all data is deleted from a page and the page becomes
-** a free-list leaf page, the page is not written to the database
-** (as free-list leaf pages contain no meaningful data). Sometimes
-** such a page is not even journalled (as it will not be modified,
-** why bother journalling it?).
-**
-** 2) When a free-list leaf page is reused, its content is not read
-** from the database or written to the journal file (why should it
-** be, if it is not at all meaningful?).
-**
-** By themselves, these optimizations work fine and provide a handy
-** performance boost to bulk delete or insert operations. However, if
-** a page is moved to the free-list and then reused within the same
-** transaction, a problem comes up. If the page is not journalled when
-** it is moved to the free-list and it is also not journalled when it
-** is extracted from the free-list and reused, then the original data
-** may be lost. In the event of a rollback, it may not be possible
-** to restore the database to its original configuration.
-**
-** The solution is the BtShared.pHasContent bitvec. Whenever a page is
-** moved to become a free-list leaf page, the corresponding bit is
-** set in the bitvec. Whenever a leaf page is extracted from the free-list,
-** optimization 2 above is omitted if the corresponding bit is already
-** set in BtShared.pHasContent. The contents of the bitvec are cleared
-** at the end of every transaction.
-*/
-static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
- int rc = SQLITE_OK;
- if( !pBt->pHasContent ){
- assert( pgno<=pBt->nPage );
- pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
- if( !pBt->pHasContent ){
- rc = SQLITE_NOMEM_BKPT;
- }
- }
- if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
- rc = sqlite3BitvecSet(pBt->pHasContent, pgno);
- }
- return rc;
-}
-
-/*
-** Query the BtShared.pHasContent vector.
-**
-** This function is called when a free-list leaf page is removed from the
-** free-list for reuse. It returns false if it is safe to retrieve the
-** page from the pager layer with the 'no-content' flag set. True otherwise.
-*/
-static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
- Bitvec *p = pBt->pHasContent;
- return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
-}
-
-/*
-** Clear (destroy) the BtShared.pHasContent bitvec. This should be
-** invoked at the conclusion of each write-transaction.
-*/
-static void btreeClearHasContent(BtShared *pBt){
- sqlite3BitvecDestroy(pBt->pHasContent);
- pBt->pHasContent = 0;
-}
-
-/*
-** Release all of the apPage[] pages for a cursor.
-*/
-static void btreeReleaseAllCursorPages(BtCursor *pCur){
- int i;
- if( pCur->iPage>=0 ){
- for(i=0; i<pCur->iPage; i++){
- releasePageNotNull(pCur->apPage[i]);
- }
- releasePageNotNull(pCur->pPage);
- pCur->iPage = -1;
- }
-}
-
-/*
-** The cursor passed as the only argument must point to a valid entry
-** when this function is called (i.e. have eState==CURSOR_VALID). This
-** function saves the current cursor key in variables pCur->nKey and
-** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error
-** code otherwise.
-**
-** If the cursor is open on an intkey table, then the integer key
-** (the rowid) is stored in pCur->nKey and pCur->pKey is left set to
-** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is
-** set to point to a malloced buffer pCur->nKey bytes in size containing
-** the key.
-*/
-static int saveCursorKey(BtCursor *pCur){
- int rc = SQLITE_OK;
- assert( CURSOR_VALID==pCur->eState );
- assert( 0==pCur->pKey );
- assert( cursorHoldsMutex(pCur) );
-
- if( pCur->curIntKey ){
- /* Only the rowid is required for a table btree */
- pCur->nKey = sqlite3BtreeIntegerKey(pCur);
- }else{
- /* For an index btree, save the complete key content */
- void *pKey;
- pCur->nKey = sqlite3BtreePayloadSize(pCur);
- pKey = sqlite3Malloc( pCur->nKey );
- if( pKey ){
- rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
- if( rc==SQLITE_OK ){
- pCur->pKey = pKey;
- }else{
- sqlite3_free(pKey);
- }
- }else{
- rc = SQLITE_NOMEM_BKPT;
- }
- }
- assert( !pCur->curIntKey || !pCur->pKey );
- return rc;
-}
-
-/*
-** Save the current cursor position in the variables BtCursor.nKey
-** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
-**
-** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
-** prior to calling this routine.
-*/
-static int saveCursorPosition(BtCursor *pCur){
- int rc;
-
- assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState );
- assert( 0==pCur->pKey );
- assert( cursorHoldsMutex(pCur) );
-
- if( pCur->eState==CURSOR_SKIPNEXT ){
- pCur->eState = CURSOR_VALID;
- }else{
- pCur->skipNext = 0;
- }
-
- rc = saveCursorKey(pCur);
- if( rc==SQLITE_OK ){
- btreeReleaseAllCursorPages(pCur);
- pCur->eState = CURSOR_REQUIRESEEK;
- }
-
- pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast);
- return rc;
-}
-
-/* Forward reference */
-static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*);
-
-/*
-** Save the positions of all cursors (except pExcept) that are open on
-** the table with root-page iRoot. "Saving the cursor position" means that
-** the location in the btree is remembered in such a way that it can be
-** moved back to the same spot after the btree has been modified. This
-** routine is called just before cursor pExcept is used to modify the
-** table, for example in BtreeDelete() or BtreeInsert().
-**
-** If there are two or more cursors on the same btree, then all such
-** cursors should have their BTCF_Multiple flag set. The btreeCursor()
-** routine enforces that rule. This routine only needs to be called in
-** the uncommon case when pExpect has the BTCF_Multiple flag set.
-**
-** If pExpect!=NULL and if no other cursors are found on the same root-page,
-** then the BTCF_Multiple flag on pExpect is cleared, to avoid another
-** pointless call to this routine.
-**
-** Implementation note: This routine merely checks to see if any cursors
-** need to be saved. It calls out to saveCursorsOnList() in the (unusual)
-** event that cursors are in need to being saved.
-*/
-static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
- BtCursor *p;
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pExcept==0 || pExcept->pBt==pBt );
- for(p=pBt->pCursor; p; p=p->pNext){
- if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break;
- }
- if( p ) return saveCursorsOnList(p, iRoot, pExcept);
- if( pExcept ) pExcept->curFlags &= ~BTCF_Multiple;
- return SQLITE_OK;
-}
-
-/* This helper routine to saveAllCursors does the actual work of saving
-** the cursors if and when a cursor is found that actually requires saving.
-** The common case is that no cursors need to be saved, so this routine is
-** broken out from its caller to avoid unnecessary stack pointer movement.
-*/
-static int SQLITE_NOINLINE saveCursorsOnList(
- BtCursor *p, /* The first cursor that needs saving */
- Pgno iRoot, /* Only save cursor with this iRoot. Save all if zero */
- BtCursor *pExcept /* Do not save this cursor */
-){
- do{
- if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
- if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
- int rc = saveCursorPosition(p);
- if( SQLITE_OK!=rc ){
- return rc;
- }
- }else{
- testcase( p->iPage>=0 );
- btreeReleaseAllCursorPages(p);
- }
- }
- p = p->pNext;
- }while( p );
- return SQLITE_OK;
-}
-
-/*
-** Clear the current cursor position.
-*/
-void sqlite3BtreeClearCursor(BtCursor *pCur){
- assert( cursorHoldsMutex(pCur) );
- sqlite3_free(pCur->pKey);
- pCur->pKey = 0;
- pCur->eState = CURSOR_INVALID;
-}
-
-/*
-** In this version of BtreeMoveto, pKey is a packed index record
-** such as is generated by the OP_MakeRecord opcode. Unpack the
-** record and then call BtreeMovetoUnpacked() to do the work.
-*/
-static int btreeMoveto(
- BtCursor *pCur, /* Cursor open on the btree to be searched */
- const void *pKey, /* Packed key if the btree is an index */
- i64 nKey, /* Integer key for tables. Size of pKey for indices */
- int bias, /* Bias search to the high end */
- int *pRes /* Write search results here */
-){
- int rc; /* Status code */
- UnpackedRecord *pIdxKey; /* Unpacked index key */
-
- if( pKey ){
- assert( nKey==(i64)(int)nKey );
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
- if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
- if( pIdxKey->nField==0 ){
- rc = SQLITE_CORRUPT_BKPT;
- goto moveto_done;
- }
- }else{
- pIdxKey = 0;
- }
- rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
-moveto_done:
- if( pIdxKey ){
- sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
- }
- return rc;
-}
-
-/*
-** Restore the cursor to the position it was in (or as close to as possible)
-** when saveCursorPosition() was called. Note that this call deletes the
-** saved position info stored by saveCursorPosition(), so there can be
-** at most one effective restoreCursorPosition() call after each
-** saveCursorPosition().
-*/
-static int btreeRestoreCursorPosition(BtCursor *pCur){
- int rc;
- int skipNext;
- assert( cursorOwnsBtShared(pCur) );
- assert( pCur->eState>=CURSOR_REQUIRESEEK );
- if( pCur->eState==CURSOR_FAULT ){
- return pCur->skipNext;
- }
- pCur->eState = CURSOR_INVALID;
- rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
- if( rc==SQLITE_OK ){
- sqlite3_free(pCur->pKey);
- pCur->pKey = 0;
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
- pCur->skipNext |= skipNext;
- if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
- pCur->eState = CURSOR_SKIPNEXT;
- }
- }
- return rc;
-}
-
-#define restoreCursorPosition(p) \
- (p->eState>=CURSOR_REQUIRESEEK ? \
- btreeRestoreCursorPosition(p) : \
- SQLITE_OK)
-
-/*
-** Determine whether or not a cursor has moved from the position where
-** it was last placed, or has been invalidated for any other reason.
-** Cursors can move when the row they are pointing at is deleted out
-** from under them, for example. Cursor might also move if a btree
-** is rebalanced.
-**
-** Calling this routine with a NULL cursor pointer returns false.
-**
-** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor
-** back to where it ought to be if this routine returns true.
-*/
-int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
- assert( EIGHT_BYTE_ALIGNMENT(pCur)
- || pCur==sqlite3BtreeFakeValidCursor() );
- assert( offsetof(BtCursor, eState)==0 );
- assert( sizeof(pCur->eState)==1 );
- return CURSOR_VALID != *(u8*)pCur;
-}
-
-/*
-** Return a pointer to a fake BtCursor object that will always answer
-** false to the sqlite3BtreeCursorHasMoved() routine above. The fake
-** cursor returned must not be used with any other Btree interface.
-*/
-BtCursor *sqlite3BtreeFakeValidCursor(void){
- static u8 fakeCursor = CURSOR_VALID;
- assert( offsetof(BtCursor, eState)==0 );
- return (BtCursor*)&fakeCursor;
-}
-
-/*
-** This routine restores a cursor back to its original position after it
-** has been moved by some outside activity (such as a btree rebalance or
-** a row having been deleted out from under the cursor).
-**
-** On success, the *pDifferentRow parameter is false if the cursor is left
-** pointing at exactly the same row. *pDifferntRow is the row the cursor
-** was pointing to has been deleted, forcing the cursor to point to some
-** nearby row.
-**
-** This routine should only be called for a cursor that just returned
-** TRUE from sqlite3BtreeCursorHasMoved().
-*/
-int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
- int rc;
-
- assert( pCur!=0 );
- assert( pCur->eState!=CURSOR_VALID );
- rc = restoreCursorPosition(pCur);
- if( rc ){
- *pDifferentRow = 1;
- return rc;
- }
- if( pCur->eState!=CURSOR_VALID ){
- *pDifferentRow = 1;
- }else{
- assert( pCur->skipNext==0 );
- *pDifferentRow = 0;
- }
- return SQLITE_OK;
-}
-
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
-/*
-** Provide hints to the cursor. The particular hint given (and the type
-** and number of the varargs parameters) is determined by the eHintType
-** parameter. See the definitions of the BTREE_HINT_* macros for details.
-*/
-void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
- /* Used only by system that substitute their own storage engine */
-}
-#endif
-
-/*
-** Provide flag hints to the cursor.
-*/
-void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
- assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
- pCur->hints = x;
-}
-
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
-/*
-** Given a page number of a regular database page, return the page
-** number for the pointer-map page that contains the entry for the
-** input page number.
-**
-** Return 0 (not a valid page) for pgno==1 since there is
-** no pointer map associated with page 1. The integrity_check logic
-** requires that ptrmapPageno(*,1)!=1.
-*/
-static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
- int nPagesPerMapPage;
- Pgno iPtrMap, ret;
- assert( sqlite3_mutex_held(pBt->mutex) );
- if( pgno<2 ) return 0;
- nPagesPerMapPage = (pBt->usableSize/5)+1;
- iPtrMap = (pgno-2)/nPagesPerMapPage;
- ret = (iPtrMap*nPagesPerMapPage) + 2;
- if( ret==PENDING_BYTE_PAGE(pBt) ){
- ret++;
- }
- return ret;
-}
-
-/*
-** Write an entry into the pointer map.
-**
-** This routine updates the pointer map entry for page number 'key'
-** so that it maps to type 'eType' and parent page number 'pgno'.
-**
-** If *pRC is initially non-zero (non-SQLITE_OK) then this routine is
-** a no-op. If an error occurs, the appropriate error code is written
-** into *pRC.
-*/
-static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
- DbPage *pDbPage; /* The pointer map page */
- u8 *pPtrmap; /* The pointer map data */
- Pgno iPtrmap; /* The pointer map page number */
- int offset; /* Offset in pointer map page */
- int rc; /* Return code from subfunctions */
-
- if( *pRC ) return;
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- /* The master-journal page number must never be used as a pointer map page */
- assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );
-
- assert( pBt->autoVacuum );
- if( key==0 ){
- *pRC = SQLITE_CORRUPT_BKPT;
- return;
- }
- iPtrmap = PTRMAP_PAGENO(pBt, key);
- rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
- if( rc!=SQLITE_OK ){
- *pRC = rc;
- return;
- }
- offset = PTRMAP_PTROFFSET(iPtrmap, key);
- if( offset<0 ){
- *pRC = SQLITE_CORRUPT_BKPT;
- goto ptrmap_exit;
- }
- assert( offset <= (int)pBt->usableSize-5 );
- pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
-
- if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
- TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));
- *pRC= rc = sqlite3PagerWrite(pDbPage);
- if( rc==SQLITE_OK ){
- pPtrmap[offset] = eType;
- put4byte(&pPtrmap[offset+1], parent);
- }
- }
-
-ptrmap_exit:
- sqlite3PagerUnref(pDbPage);
-}
-
-/*
-** Read an entry from the pointer map.
-**
-** This routine retrieves the pointer map entry for page 'key', writing
-** the type and parent page number to *pEType and *pPgno respectively.
-** An error code is returned if something goes wrong, otherwise SQLITE_OK.
-*/
-static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
- DbPage *pDbPage; /* The pointer map page */
- int iPtrmap; /* Pointer map page index */
- u8 *pPtrmap; /* Pointer map page data */
- int offset; /* Offset of entry in pointer map */
- int rc;
-
- assert( sqlite3_mutex_held(pBt->mutex) );
-
- iPtrmap = PTRMAP_PAGENO(pBt, key);
- rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
- if( rc!=0 ){
- return rc;
- }
- pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
-
- offset = PTRMAP_PTROFFSET(iPtrmap, key);
- if( offset<0 ){
- sqlite3PagerUnref(pDbPage);
- return SQLITE_CORRUPT_BKPT;
- }
- assert( offset <= (int)pBt->usableSize-5 );
- assert( pEType!=0 );
- *pEType = pPtrmap[offset];
- if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
-
- sqlite3PagerUnref(pDbPage);
- if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap);
- return SQLITE_OK;
-}
-
-#else /* if defined SQLITE_OMIT_AUTOVACUUM */
- #define ptrmapPut(w,x,y,z,rc)
- #define ptrmapGet(w,x,y,z) SQLITE_OK
- #define ptrmapPutOvflPtr(x, y, rc)
-#endif
-
-/*
-** Given a btree page and a cell index (0 means the first cell on
-** the page, 1 means the second cell, and so forth) return a pointer
-** to the cell content.
-**
-** findCellPastPtr() does the same except it skips past the initial
-** 4-byte child pointer found on interior pages, if there is one.
-**
-** This routine works only for pages that do not contain overflow cells.
-*/
-#define findCell(P,I) \
- ((P)->aData + ((P)->maskPage & get2byteAligned(&(P)->aCellIdx[2*(I)])))
-#define findCellPastPtr(P,I) \
- ((P)->aDataOfst + ((P)->maskPage & get2byteAligned(&(P)->aCellIdx[2*(I)])))
-
-
-/*
-** This is common tail processing for btreeParseCellPtr() and
-** btreeParseCellPtrIndex() for the case when the cell does not fit entirely
-** on a single B-tree page. Make necessary adjustments to the CellInfo
-** structure.
-*/
-static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
- MemPage *pPage, /* Page containing the cell */
- u8 *pCell, /* Pointer to the cell text. */
- CellInfo *pInfo /* Fill in this structure */
-){
- /* If the payload will not fit completely on the local page, we have
- ** to decide how much to store locally and how much to spill onto
- ** overflow pages. The strategy is to minimize the amount of unused
- ** space on overflow pages while keeping the amount of local storage
- ** in between minLocal and maxLocal.
- **
- ** Warning: changing the way overflow payload is distributed in any
- ** way will result in an incompatible file format.
- */
- int minLocal; /* Minimum amount of payload held locally */
- int maxLocal; /* Maximum amount of payload held locally */
- int surplus; /* Overflow payload available for local storage */
-
- minLocal = pPage->minLocal;
- maxLocal = pPage->maxLocal;
- surplus = minLocal + (pInfo->nPayload - minLocal)%(pPage->pBt->usableSize-4);
- testcase( surplus==maxLocal );
- testcase( surplus==maxLocal+1 );
- if( surplus <= maxLocal ){
- pInfo->nLocal = (u16)surplus;
- }else{
- pInfo->nLocal = (u16)minLocal;
- }
- pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
-}
-
-/*
-** The following routines are implementations of the MemPage.xParseCell()
-** method.
-**
-** Parse a cell content block and fill in the CellInfo structure.
-**
-** btreeParseCellPtr() => table btree leaf nodes
-** btreeParseCellNoPayload() => table btree internal nodes
-** btreeParseCellPtrIndex() => index btree nodes
-**
-** There is also a wrapper function btreeParseCell() that works for
-** all MemPage types and that references the cell by index rather than
-** by pointer.
-*/
-static void btreeParseCellPtrNoPayload(
- MemPage *pPage, /* Page containing the cell */
- u8 *pCell, /* Pointer to the cell text. */
- CellInfo *pInfo /* Fill in this structure */
-){
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- assert( pPage->leaf==0 );
- assert( pPage->childPtrSize==4 );
-#ifndef SQLITE_DEBUG
- UNUSED_PARAMETER(pPage);
-#endif
- pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
- pInfo->nPayload = 0;
- pInfo->nLocal = 0;
- pInfo->pPayload = 0;
- return;
-}
-static void btreeParseCellPtr(
- MemPage *pPage, /* Page containing the cell */
- u8 *pCell, /* Pointer to the cell text. */
- CellInfo *pInfo /* Fill in this structure */
-){
- u8 *pIter; /* For scanning through pCell */
- u32 nPayload; /* Number of bytes of cell payload */
- u64 iKey; /* Extracted Key value */
-
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- assert( pPage->leaf==0 || pPage->leaf==1 );
- assert( pPage->intKeyLeaf );
- assert( pPage->childPtrSize==0 );
- pIter = pCell;
-
- /* The next block of code is equivalent to:
- **
- ** pIter += getVarint32(pIter, nPayload);
- **
- ** The code is inlined to avoid a function call.
- */
- nPayload = *pIter;
- if( nPayload>=0x80 ){
- u8 *pEnd = &pIter[8];
- nPayload &= 0x7f;
- do{
- nPayload = (nPayload<<7) | (*++pIter & 0x7f);
- }while( (*pIter)>=0x80 && pIter<pEnd );
- }
- pIter++;
-
- /* The next block of code is equivalent to:
- **
- ** pIter += getVarint(pIter, (u64*)&pInfo->nKey);
- **
- ** The code is inlined to avoid a function call.
- */
- iKey = *pIter;
- if( iKey>=0x80 ){
- u8 *pEnd = &pIter[7];
- iKey &= 0x7f;
- while(1){
- iKey = (iKey<<7) | (*++pIter & 0x7f);
- if( (*pIter)<0x80 ) break;
- if( pIter>=pEnd ){
- iKey = (iKey<<8) | *++pIter;
- break;
- }
- }
- }
- pIter++;
-
- pInfo->nKey = *(i64*)&iKey;
- pInfo->nPayload = nPayload;
- pInfo->pPayload = pIter;
- testcase( nPayload==pPage->maxLocal );
- testcase( nPayload==pPage->maxLocal+1 );
- if( nPayload<=pPage->maxLocal ){
- /* This is the (easy) common case where the entire payload fits
- ** on the local page. No overflow is required.
- */
- pInfo->nSize = nPayload + (u16)(pIter - pCell);
- if( pInfo->nSize<4 ) pInfo->nSize = 4;
- pInfo->nLocal = (u16)nPayload;
- }else{
- btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
- }
-}
-static void btreeParseCellPtrIndex(
- MemPage *pPage, /* Page containing the cell */
- u8 *pCell, /* Pointer to the cell text. */
- CellInfo *pInfo /* Fill in this structure */
-){
- u8 *pIter; /* For scanning through pCell */
- u32 nPayload; /* Number of bytes of cell payload */
-
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- assert( pPage->leaf==0 || pPage->leaf==1 );
- assert( pPage->intKeyLeaf==0 );
- pIter = pCell + pPage->childPtrSize;
- nPayload = *pIter;
- if( nPayload>=0x80 ){
- u8 *pEnd = &pIter[8];
- nPayload &= 0x7f;
- do{
- nPayload = (nPayload<<7) | (*++pIter & 0x7f);
- }while( *(pIter)>=0x80 && pIter<pEnd );
- }
- pIter++;
- pInfo->nKey = nPayload;
- pInfo->nPayload = nPayload;
- pInfo->pPayload = pIter;
- testcase( nPayload==pPage->maxLocal );
- testcase( nPayload==pPage->maxLocal+1 );
- if( nPayload<=pPage->maxLocal ){
- /* This is the (easy) common case where the entire payload fits
- ** on the local page. No overflow is required.
- */
- pInfo->nSize = nPayload + (u16)(pIter - pCell);
- if( pInfo->nSize<4 ) pInfo->nSize = 4;
- pInfo->nLocal = (u16)nPayload;
- }else{
- btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
- }
-}
-static void btreeParseCell(
- MemPage *pPage, /* Page containing the cell */
- int iCell, /* The cell index. First cell is 0 */
- CellInfo *pInfo /* Fill in this structure */
-){
- pPage->xParseCell(pPage, findCell(pPage, iCell), pInfo);
-}
-
-/*
-** The following routines are implementations of the MemPage.xCellSize
-** method.
-**
-** Compute the total number of bytes that a Cell needs in the cell
-** data area of the btree-page. The return number includes the cell
-** data header and the local payload, but not any overflow page or
-** the space used by the cell pointer.
-**
-** cellSizePtrNoPayload() => table internal nodes
-** cellSizePtr() => all index nodes & table leaf nodes
-*/
-static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
- u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */
- u8 *pEnd; /* End mark for a varint */
- u32 nSize; /* Size value to return */
-
-#ifdef SQLITE_DEBUG
- /* The value returned by this function should always be the same as
- ** the (CellInfo.nSize) value found by doing a full parse of the
- ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
- ** this function verifies that this invariant is not violated. */
- CellInfo debuginfo;
- pPage->xParseCell(pPage, pCell, &debuginfo);
-#endif
-
- nSize = *pIter;
- if( nSize>=0x80 ){
- pEnd = &pIter[8];
- nSize &= 0x7f;
- do{
- nSize = (nSize<<7) | (*++pIter & 0x7f);
- }while( *(pIter)>=0x80 && pIter<pEnd );
- }
- pIter++;
- if( pPage->intKey ){
- /* pIter now points at the 64-bit integer key value, a variable length
- ** integer. The following block moves pIter to point at the first byte
- ** past the end of the key value. */
- pEnd = &pIter[9];
- while( (*pIter++)&0x80 && pIter<pEnd );
- }
- testcase( nSize==pPage->maxLocal );
- testcase( nSize==pPage->maxLocal+1 );
- if( nSize<=pPage->maxLocal ){
- nSize += (u32)(pIter - pCell);
- if( nSize<4 ) nSize = 4;
- }else{
- int minLocal = pPage->minLocal;
- nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
- testcase( nSize==pPage->maxLocal );
- testcase( nSize==pPage->maxLocal+1 );
- if( nSize>pPage->maxLocal ){
- nSize = minLocal;
- }
- nSize += 4 + (u16)(pIter - pCell);
- }
- assert( nSize==debuginfo.nSize || CORRUPT_DB );
- return (u16)nSize;
-}
-static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){
- u8 *pIter = pCell + 4; /* For looping over bytes of pCell */
- u8 *pEnd; /* End mark for a varint */
-
-#ifdef SQLITE_DEBUG
- /* The value returned by this function should always be the same as
- ** the (CellInfo.nSize) value found by doing a full parse of the
- ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
- ** this function verifies that this invariant is not violated. */
- CellInfo debuginfo;
- pPage->xParseCell(pPage, pCell, &debuginfo);
-#else
- UNUSED_PARAMETER(pPage);
-#endif
-
- assert( pPage->childPtrSize==4 );
- pEnd = pIter + 9;
- while( (*pIter++)&0x80 && pIter<pEnd );
- assert( debuginfo.nSize==(u16)(pIter - pCell) || CORRUPT_DB );
- return (u16)(pIter - pCell);
-}
-
-
-#ifdef SQLITE_DEBUG
-/* This variation on cellSizePtr() is used inside of assert() statements
-** only. */
-static u16 cellSize(MemPage *pPage, int iCell){
- return pPage->xCellSize(pPage, findCell(pPage, iCell));
-}
-#endif
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
-/*
-** If the cell pCell, part of page pPage contains a pointer
-** to an overflow page, insert an entry into the pointer-map
-** for the overflow page.
-*/
-static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
- CellInfo info;
- if( *pRC ) return;
- assert( pCell!=0 );
- pPage->xParseCell(pPage, pCell, &info);
- if( info.nLocal<info.nPayload ){
- Pgno ovfl = get4byte(&pCell[info.nSize-4]);
- ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
- }
-}
-#endif
-
-
-/*
-** Defragment the page given. This routine reorganizes cells within the
-** page so that there are no free-blocks on the free-block list.
-**
-** Parameter nMaxFrag is the maximum amount of fragmented space that may be
-** present in the page after this routine returns.
-**
-** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a
-** b-tree page so that there are no freeblocks or fragment bytes, all
-** unused bytes are contained in the unallocated space region, and all
-** cells are packed tightly at the end of the page.
-*/
-static int defragmentPage(MemPage *pPage, int nMaxFrag){
- int i; /* Loop counter */
- int pc; /* Address of the i-th cell */
- int hdr; /* Offset to the page header */
- int size; /* Size of a cell */
- int usableSize; /* Number of usable bytes on a page */
- int cellOffset; /* Offset to the cell pointer array */
- int cbrk; /* Offset to the cell content area */
- int nCell; /* Number of cells on the page */
- unsigned char *data; /* The page data */
- unsigned char *temp; /* Temp area for cell content */
- unsigned char *src; /* Source of content */
- int iCellFirst; /* First allowable cell index */
- int iCellLast; /* Last possible cell index */
-
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- assert( pPage->pBt!=0 );
- assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
- assert( pPage->nOverflow==0 );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- temp = 0;
- src = data = pPage->aData;
- hdr = pPage->hdrOffset;
- cellOffset = pPage->cellOffset;
- nCell = pPage->nCell;
- assert( nCell==get2byte(&data[hdr+3]) );
- iCellFirst = cellOffset + 2*nCell;
- usableSize = pPage->pBt->usableSize;
-
- /* This block handles pages with two or fewer free blocks and nMaxFrag
- ** or fewer fragmented bytes. In this case it is faster to move the
- ** two (or one) blocks of cells using memmove() and add the required
- ** offsets to each pointer in the cell-pointer array than it is to
- ** reconstruct the entire page. */
- if( (int)data[hdr+7]<=nMaxFrag ){
- int iFree = get2byte(&data[hdr+1]);
- if( iFree ){
- int iFree2 = get2byte(&data[iFree]);
-
- /* pageFindSlot() has already verified that free blocks are sorted
- ** in order of offset within the page, and that no block extends
- ** past the end of the page. Provided the two free slots do not
- ** overlap, this guarantees that the memmove() calls below will not
- ** overwrite the usableSize byte buffer, even if the database page
- ** is corrupt. */
- assert( iFree2==0 || iFree2>iFree );
- assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
- assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
-
- if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
- u8 *pEnd = &data[cellOffset + nCell*2];
- u8 *pAddr;
- int sz2 = 0;
- int sz = get2byte(&data[iFree+2]);
- int top = get2byte(&data[hdr+5]);
- if( top>=iFree ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- if( iFree2 ){
- assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
- sz2 = get2byte(&data[iFree2+2]);
- assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
- memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
- sz += sz2;
- }
- cbrk = top+sz;
- assert( cbrk+(iFree-top) <= usableSize );
- memmove(&data[cbrk], &data[top], iFree-top);
- for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){
- pc = get2byte(pAddr);
- if( pc<iFree ){ put2byte(pAddr, pc+sz); }
- else if( pc<iFree2 ){ put2byte(pAddr, pc+sz2); }
- }
- goto defragment_out;
- }
- }
- }
-
- cbrk = usableSize;
- iCellLast = usableSize - 4;
- for(i=0; i<nCell; i++){
- u8 *pAddr; /* The i-th cell pointer */
- pAddr = &data[cellOffset + i*2];
- pc = get2byte(pAddr);
- testcase( pc==iCellFirst );
- testcase( pc==iCellLast );
- /* These conditions have already been verified in btreeInitPage()
- ** if PRAGMA cell_size_check=ON.
- */
- if( pc<iCellFirst || pc>iCellLast ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- assert( pc>=iCellFirst && pc<=iCellLast );
- size = pPage->xCellSize(pPage, &src[pc]);
- cbrk -= size;
- if( cbrk<iCellFirst || pc+size>usableSize ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
- testcase( cbrk+size==usableSize );
- testcase( pc+size==usableSize );
- put2byte(pAddr, cbrk);
- if( temp==0 ){
- int x;
- if( cbrk==pc ) continue;
- temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
- x = get2byte(&data[hdr+5]);
- memcpy(&temp[x], &data[x], (cbrk+size) - x);
- src = temp;
- }
- memcpy(&data[cbrk], &src[pc], size);
- }
- data[hdr+7] = 0;
-
- defragment_out:
- if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- assert( cbrk>=iCellFirst );
- put2byte(&data[hdr+5], cbrk);
- data[hdr+1] = 0;
- data[hdr+2] = 0;
- memset(&data[iCellFirst], 0, cbrk-iCellFirst);
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- return SQLITE_OK;
-}
-
-/*
-** Search the free-list on page pPg for space to store a cell nByte bytes in
-** size. If one can be found, return a pointer to the space and remove it
-** from the free-list.
-**
-** If no suitable space can be found on the free-list, return NULL.
-**
-** This function may detect corruption within pPg. If corruption is
-** detected then *pRc is set to SQLITE_CORRUPT and NULL is returned.
-**
-** Slots on the free list that are between 1 and 3 bytes larger than nByte
-** will be ignored if adding the extra space to the fragmentation count
-** causes the fragmentation count to exceed 60.
-*/
-static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
- const int hdr = pPg->hdrOffset;
- u8 * const aData = pPg->aData;
- int iAddr = hdr + 1;
- int pc = get2byte(&aData[iAddr]);
- int x;
- int usableSize = pPg->pBt->usableSize;
- int size; /* Size of the free slot */
-
- assert( pc>0 );
- while( pc<=usableSize-4 ){
- /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
- ** freeblock form a big-endian integer which is the size of the freeblock
- ** in bytes, including the 4-byte header. */
- size = get2byte(&aData[pc+2]);
- if( (x = size - nByte)>=0 ){
- testcase( x==4 );
- testcase( x==3 );
- if( size+pc > usableSize ){
- *pRc = SQLITE_CORRUPT_PAGE(pPg);
- return 0;
- }else if( x<4 ){
- /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
- ** number of bytes in fragments may not exceed 60. */
- if( aData[hdr+7]>57 ) return 0;
-
- /* Remove the slot from the free-list. Update the number of
- ** fragmented bytes within the page. */
- memcpy(&aData[iAddr], &aData[pc], 2);
- aData[hdr+7] += (u8)x;
- }else{
- /* The slot remains on the free-list. Reduce its size to account
- ** for the portion used by the new allocation. */
- put2byte(&aData[pc+2], x);
- }
- return &aData[pc + x];
- }
- iAddr = pc;
- pc = get2byte(&aData[pc]);
- if( pc<iAddr+size ) break;
- }
- if( pc ){
- *pRc = SQLITE_CORRUPT_PAGE(pPg);
- }
-
- return 0;
-}
-
-/*
-** Allocate nByte bytes of space from within the B-Tree page passed
-** as the first argument. Write into *pIdx the index into pPage->aData[]
-** of the first byte of allocated space. Return either SQLITE_OK or
-** an error code (usually SQLITE_CORRUPT).
-**
-** The caller guarantees that there is sufficient space to make the
-** allocation. This routine might need to defragment in order to bring
-** all the space together, however. This routine will avoid using
-** the first two bytes past the cell pointer area since presumably this
-** allocation is being made in order to insert a new cell, so we will
-** also end up needing a new cell pointer.
-*/
-static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
- const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */
- u8 * const data = pPage->aData; /* Local cache of pPage->aData */
- int top; /* First byte of cell content area */
- int rc = SQLITE_OK; /* Integer return code */
- int gap; /* First byte of gap between cell pointers and cell content */
-
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- assert( pPage->pBt );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- assert( nByte>=0 ); /* Minimum cell size is 4 */
- assert( pPage->nFree>=nByte );
- assert( pPage->nOverflow==0 );
- assert( nByte < (int)(pPage->pBt->usableSize-8) );
-
- assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf );
- gap = pPage->cellOffset + 2*pPage->nCell;
- assert( gap<=65536 );
- /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size
- ** and the reserved space is zero (the usual value for reserved space)
- ** then the cell content offset of an empty page wants to be 65536.
- ** However, that integer is too large to be stored in a 2-byte unsigned
- ** integer, so a value of 0 is used in its place. */
- top = get2byte(&data[hdr+5]);
- assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */
- if( gap>top ){
- if( top==0 && pPage->pBt->usableSize==65536 ){
- top = 65536;
- }else{
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- }
-
- /* If there is enough space between gap and top for one more cell pointer
- ** array entry offset, and if the freelist is not empty, then search the
- ** freelist looking for a free slot big enough to satisfy the request.
- */
- testcase( gap+2==top );
- testcase( gap+1==top );
- testcase( gap==top );
- if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
- u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
- if( pSpace ){
- assert( pSpace>=data && (pSpace - data)<65536 );
- *pIdx = (int)(pSpace - data);
- return SQLITE_OK;
- }else if( rc ){
- return rc;
- }
- }
-
- /* The request could not be fulfilled using a freelist slot. Check
- ** to see if defragmentation is necessary.
- */
- testcase( gap+2+nByte==top );
- if( gap+2+nByte>top ){
- assert( pPage->nCell>0 || CORRUPT_DB );
- rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
- if( rc ) return rc;
- top = get2byteNotZero(&data[hdr+5]);
- assert( gap+2+nByte<=top );
- }
-
-
- /* Allocate memory from the gap in between the cell pointer array
- ** and the cell content area. The btreeInitPage() call has already
- ** validated the freelist. Given that the freelist is valid, there
- ** is no way that the allocation can extend off the end of the page.
- ** The assert() below verifies the previous sentence.
- */
- top -= nByte;
- put2byte(&data[hdr+5], top);
- assert( top+nByte <= (int)pPage->pBt->usableSize );
- *pIdx = top;
- return SQLITE_OK;
-}
-
-/*
-** Return a section of the pPage->aData to the freelist.
-** The first byte of the new free block is pPage->aData[iStart]
-** and the size of the block is iSize bytes.
-**
-** Adjacent freeblocks are coalesced.
-**
-** Note that even though the freeblock list was checked by btreeInitPage(),
-** that routine will not detect overlap between cells or freeblocks. Nor
-** does it detect cells or freeblocks that encrouch into the reserved bytes
-** at the end of the page. So do additional corruption checks inside this
-** routine and return SQLITE_CORRUPT if any problems are found.
-*/
-static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
- u16 iPtr; /* Address of ptr to next freeblock */
- u16 iFreeBlk; /* Address of the next freeblock */
- u8 hdr; /* Page header size. 0 or 100 */
- u8 nFrag = 0; /* Reduction in fragmentation */
- u16 iOrigSize = iSize; /* Original value of iSize */
- u16 x; /* Offset to cell content area */
- u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
- unsigned char *data = pPage->aData; /* Page content */
-
- assert( pPage->pBt!=0 );
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize );
- assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- assert( iSize>=4 ); /* Minimum cell size is 4 */
- assert( iStart<=pPage->pBt->usableSize-4 );
-
- /* The list of freeblocks must be in ascending order. Find the
- ** spot on the list where iStart should be inserted.
- */
- hdr = pPage->hdrOffset;
- iPtr = hdr + 1;
- if( data[iPtr+1]==0 && data[iPtr]==0 ){
- iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */
- }else{
- while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
- if( iFreeBlk<iPtr+4 ){
- if( iFreeBlk==0 ) break;
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- iPtr = iFreeBlk;
- }
- if( iFreeBlk>pPage->pBt->usableSize-4 ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- assert( iFreeBlk>iPtr || iFreeBlk==0 );
-
- /* At this point:
- ** iFreeBlk: First freeblock after iStart, or zero if none
- ** iPtr: The address of a pointer to iFreeBlk
- **
- ** Check to see if iFreeBlk should be coalesced onto the end of iStart.
- */
- if( iFreeBlk && iEnd+3>=iFreeBlk ){
- nFrag = iFreeBlk - iEnd;
- if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage);
- iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
- if( iEnd > pPage->pBt->usableSize ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- iSize = iEnd - iStart;
- iFreeBlk = get2byte(&data[iFreeBlk]);
- }
-
- /* If iPtr is another freeblock (that is, if iPtr is not the freelist
- ** pointer in the page header) then check to see if iStart should be
- ** coalesced onto the end of iPtr.
- */
- if( iPtr>hdr+1 ){
- int iPtrEnd = iPtr + get2byte(&data[iPtr+2]);
- if( iPtrEnd+3>=iStart ){
- if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage);
- nFrag += iStart - iPtrEnd;
- iSize = iEnd - iPtr;
- iStart = iPtr;
- }
- }
- if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage);
- data[hdr+7] -= nFrag;
- }
- x = get2byte(&data[hdr+5]);
- if( iStart<=x ){
- /* The new freeblock is at the beginning of the cell content area,
- ** so just extend the cell content area rather than create another
- ** freelist entry */
- if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
- put2byte(&data[hdr+1], iFreeBlk);
- put2byte(&data[hdr+5], iEnd);
- }else{
- /* Insert the new freeblock into the freelist */
- put2byte(&data[iPtr], iStart);
- }
- if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
- /* Overwrite deleted information with zeros when the secure_delete
- ** option is enabled */
- memset(&data[iStart], 0, iSize);
- }
- put2byte(&data[iStart], iFreeBlk);
- put2byte(&data[iStart+2], iSize);
- pPage->nFree += iOrigSize;
- return SQLITE_OK;
-}
-
-/*
-** Decode the flags byte (the first byte of the header) for a page
-** and initialize fields of the MemPage structure accordingly.
-**
-** Only the following combinations are supported. Anything different
-** indicates a corrupt database files:
-**
-** PTF_ZERODATA
-** PTF_ZERODATA | PTF_LEAF
-** PTF_LEAFDATA | PTF_INTKEY
-** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF
-*/
-static int decodeFlags(MemPage *pPage, int flagByte){
- BtShared *pBt; /* A copy of pPage->pBt */
-
- assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
- flagByte &= ~PTF_LEAF;
- pPage->childPtrSize = 4-4*pPage->leaf;
- pPage->xCellSize = cellSizePtr;
- pBt = pPage->pBt;
- if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
- /* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an
- ** interior table b-tree page. */
- assert( (PTF_LEAFDATA|PTF_INTKEY)==5 );
- /* EVIDENCE-OF: R-26900-09176 A value of 13 (0x0d) means the page is a
- ** leaf table b-tree page. */
- assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
- pPage->intKey = 1;
- if( pPage->leaf ){
- pPage->intKeyLeaf = 1;
- pPage->xParseCell = btreeParseCellPtr;
- }else{
- pPage->intKeyLeaf = 0;
- pPage->xCellSize = cellSizePtrNoPayload;
- pPage->xParseCell = btreeParseCellPtrNoPayload;
- }
- pPage->maxLocal = pBt->maxLeaf;
- pPage->minLocal = pBt->minLeaf;
- }else if( flagByte==PTF_ZERODATA ){
- /* EVIDENCE-OF: R-43316-37308 A value of 2 (0x02) means the page is an
- ** interior index b-tree page. */
- assert( (PTF_ZERODATA)==2 );
- /* EVIDENCE-OF: R-59615-42828 A value of 10 (0x0a) means the page is a
- ** leaf index b-tree page. */
- assert( (PTF_ZERODATA|PTF_LEAF)==10 );
- pPage->intKey = 0;
- pPage->intKeyLeaf = 0;
- pPage->xParseCell = btreeParseCellPtrIndex;
- pPage->maxLocal = pBt->maxLocal;
- pPage->minLocal = pBt->minLocal;
- }else{
- /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
- ** an error. */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- pPage->max1bytePayload = pBt->max1bytePayload;
- return SQLITE_OK;
-}
-
-/*
-** Initialize the auxiliary information for a disk block.
-**
-** Return SQLITE_OK on success. If we see that the page does
-** not contain a well-formed database page, then return
-** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not
-** guarantee that the page is well-formed. It only shows that
-** we failed to detect any corruption.
-*/
-static int btreeInitPage(MemPage *pPage){
- int pc; /* Address of a freeblock within pPage->aData[] */
- u8 hdr; /* Offset to beginning of page header */
- u8 *data; /* Equal to pPage->aData */
- BtShared *pBt; /* The main btree structure */
- int usableSize; /* Amount of usable space on each page */
- u16 cellOffset; /* Offset from start of page to first cell pointer */
- int nFree; /* Number of unused bytes on the page */
- int top; /* First byte of the cell content area */
- int iCellFirst; /* First allowable cell or freeblock offset */
- int iCellLast; /* Last possible cell or freeblock offset */
-
- assert( pPage->pBt!=0 );
- assert( pPage->pBt->db!=0 );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
- assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
- assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
- assert( pPage->isInit==0 );
-
- pBt = pPage->pBt;
- hdr = pPage->hdrOffset;
- data = pPage->aData;
- /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
- ** the b-tree page type. */
- if( decodeFlags(pPage, data[hdr]) ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
- pPage->maskPage = (u16)(pBt->pageSize - 1);
- pPage->nOverflow = 0;
- usableSize = pBt->usableSize;
- pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
- pPage->aDataEnd = &data[usableSize];
- pPage->aCellIdx = &data[cellOffset];
- pPage->aDataOfst = &data[pPage->childPtrSize];
- /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
- ** the start of the cell content area. A zero value for this integer is
- ** interpreted as 65536. */
- top = get2byteNotZero(&data[hdr+5]);
- /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
- ** number of cells on the page. */
- pPage->nCell = get2byte(&data[hdr+3]);
- if( pPage->nCell>MX_CELL(pBt) ){
- /* To many cells for a single page. The page must be corrupt */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- testcase( pPage->nCell==MX_CELL(pBt) );
- /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
- ** possible for a root page of a table that contains no rows) then the
- ** offset to the cell content area will equal the page size minus the
- ** bytes of reserved space. */
- assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
-
- /* A malformed database page might cause us to read past the end
- ** of page when parsing a cell.
- **
- ** The following block of code checks early to see if a cell extends
- ** past the end of a page boundary and causes SQLITE_CORRUPT to be
- ** returned if it does.
- */
- iCellFirst = cellOffset + 2*pPage->nCell;
- iCellLast = usableSize - 4;
- if( pBt->db->flags & SQLITE_CellSizeCk ){
- int i; /* Index into the cell pointer array */
- int sz; /* Size of a cell */
-
- if( !pPage->leaf ) iCellLast--;
- for(i=0; i<pPage->nCell; i++){
- pc = get2byteAligned(&data[cellOffset+i*2]);
- testcase( pc==iCellFirst );
- testcase( pc==iCellLast );
- if( pc<iCellFirst || pc>iCellLast ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- sz = pPage->xCellSize(pPage, &data[pc]);
- testcase( pc+sz==usableSize );
- if( pc+sz>usableSize ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- }
- if( !pPage->leaf ) iCellLast++;
- }
-
- /* Compute the total free space on the page
- ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
- ** start of the first freeblock on the page, or is zero if there are no
- ** freeblocks. */
- pc = get2byte(&data[hdr+1]);
- nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
- if( pc>0 ){
- u32 next, size;
- if( pc<iCellFirst ){
- /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
- ** always be at least one cell before the first freeblock.
- */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- while( 1 ){
- if( pc>iCellLast ){
- /* Freeblock off the end of the page */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- next = get2byte(&data[pc]);
- size = get2byte(&data[pc+2]);
- nFree = nFree + size;
- if( next<=pc+size+3 ) break;
- pc = next;
- }
- if( next>0 ){
- /* Freeblock not in ascending order */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- if( pc+size>(unsigned int)usableSize ){
- /* Last freeblock extends past page end */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- }
-
- /* At this point, nFree contains the sum of the offset to the start
- ** of the cell-content area plus the number of free bytes within
- ** the cell-content area. If this is greater than the usable-size
- ** of the page, then the page must be corrupted. This check also
- ** serves to verify that the offset to the start of the cell-content
- ** area, according to the page header, lies within the page.
- */
- if( nFree>usableSize ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- pPage->nFree = (u16)(nFree - iCellFirst);
- pPage->isInit = 1;
- return SQLITE_OK;
-}
-
-/*
-** Set up a raw page so that it looks like a database page holding
-** no entries.
-*/
-static void zeroPage(MemPage *pPage, int flags){
- unsigned char *data = pPage->aData;
- BtShared *pBt = pPage->pBt;
- u8 hdr = pPage->hdrOffset;
- u16 first;
-
- assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
- assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
- assert( sqlite3PagerGetData(pPage->pDbPage) == data );
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- assert( sqlite3_mutex_held(pBt->mutex) );
- if( pBt->btsFlags & BTS_FAST_SECURE ){
- memset(&data[hdr], 0, pBt->usableSize - hdr);
- }
- data[hdr] = (char)flags;
- first = hdr + ((flags&PTF_LEAF)==0 ? 12 : 8);
- memset(&data[hdr+1], 0, 4);
- data[hdr+7] = 0;
- put2byte(&data[hdr+5], pBt->usableSize);
- pPage->nFree = (u16)(pBt->usableSize - first);
- decodeFlags(pPage, flags);
- pPage->cellOffset = first;
- pPage->aDataEnd = &data[pBt->usableSize];
- pPage->aCellIdx = &data[first];
- pPage->aDataOfst = &data[pPage->childPtrSize];
- pPage->nOverflow = 0;
- assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
- pPage->maskPage = (u16)(pBt->pageSize - 1);
- pPage->nCell = 0;
- pPage->isInit = 1;
-}
-
-
-/*
-** Convert a DbPage obtained from the pager into a MemPage used by
-** the btree layer.
-*/
-static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
- MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
- if( pgno!=pPage->pgno ){
- pPage->aData = sqlite3PagerGetData(pDbPage);
- pPage->pDbPage = pDbPage;
- pPage->pBt = pBt;
- pPage->pgno = pgno;
- pPage->hdrOffset = pgno==1 ? 100 : 0;
- }
- assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
- return pPage;
-}
-
-/*
-** Get a page from the pager. Initialize the MemPage.pBt and
-** MemPage.aData elements if needed. See also: btreeGetUnusedPage().
-**
-** If the PAGER_GET_NOCONTENT flag is set, it means that we do not care
-** about the content of the page at this time. So do not go to the disk
-** to fetch the content. Just fill in the content with zeros for now.
-** If in the future we call sqlite3PagerWrite() on this page, that
-** means we have started to be concerned about content and the disk
-** read should occur at that point.
-*/
-static int btreeGetPage(
- BtShared *pBt, /* The btree */
- Pgno pgno, /* Number of the page to fetch */
- MemPage **ppPage, /* Return the page in this parameter */
- int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */
-){
- int rc;
- DbPage *pDbPage;
-
- assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY );
- assert( sqlite3_mutex_held(pBt->mutex) );
- rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
- if( rc ) return rc;
- *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
- return SQLITE_OK;
-}
-
-/*
-** Retrieve a page from the pager cache. If the requested page is not
-** already in the pager cache return NULL. Initialize the MemPage.pBt and
-** MemPage.aData elements if needed.
-*/
-static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
- DbPage *pDbPage;
- assert( sqlite3_mutex_held(pBt->mutex) );
- pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
- if( pDbPage ){
- return btreePageFromDbPage(pDbPage, pgno, pBt);
- }
- return 0;
-}
-
-/*
-** Return the size of the database file in pages. If there is any kind of
-** error, return ((unsigned int)-1).
-*/
-static Pgno btreePagecount(BtShared *pBt){
- return pBt->nPage;
-}
-u32 sqlite3BtreeLastPage(Btree *p){
- assert( sqlite3BtreeHoldsMutex(p) );
- assert( ((p->pBt->nPage)&0x80000000)==0 );
- return btreePagecount(p->pBt);
-}
-
-/*
-** Get a page from the pager and initialize it.
-**
-** If pCur!=0 then the page is being fetched as part of a moveToChild()
-** call. Do additional sanity checking on the page in this case.
-** And if the fetch fails, this routine must decrement pCur->iPage.
-**
-** The page is fetched as read-write unless pCur is not NULL and is
-** a read-only cursor.
-**
-** If an error occurs, then *ppPage is undefined. It
-** may remain unchanged, or it may be set to an invalid value.
-*/
-static int getAndInitPage(
- BtShared *pBt, /* The database file */
- Pgno pgno, /* Number of the page to get */
- MemPage **ppPage, /* Write the page pointer here */
- BtCursor *pCur, /* Cursor to receive the page, or NULL */
- int bReadOnly /* True for a read-only page */
-){
- int rc;
- DbPage *pDbPage;
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pCur==0 || ppPage==&pCur->pPage );
- assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
- assert( pCur==0 || pCur->iPage>0 );
-
- if( pgno>btreePagecount(pBt) ){
- rc = SQLITE_CORRUPT_BKPT;
- goto getAndInitPage_error;
- }
- rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
- if( rc ){
- goto getAndInitPage_error;
- }
- *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
- if( (*ppPage)->isInit==0 ){
- btreePageFromDbPage(pDbPage, pgno, pBt);
- rc = btreeInitPage(*ppPage);
- if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
- goto getAndInitPage_error;
- }
- }
- assert( (*ppPage)->pgno==pgno );
- assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
-
- /* If obtaining a child page for a cursor, we must verify that the page is
- ** compatible with the root page. */
- if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
- rc = SQLITE_CORRUPT_PGNO(pgno);
- releasePage(*ppPage);
- goto getAndInitPage_error;
- }
- return SQLITE_OK;
-
-getAndInitPage_error:
- if( pCur ){
- pCur->iPage--;
- pCur->pPage = pCur->apPage[pCur->iPage];
- }
- testcase( pgno==0 );
- assert( pgno!=0 || rc==SQLITE_CORRUPT );
- return rc;
-}
-
-/*
-** Release a MemPage. This should be called once for each prior
-** call to btreeGetPage.
-**
-** Page1 is a special case and must be released using releasePageOne().
-*/
-static void releasePageNotNull(MemPage *pPage){
- assert( pPage->aData );
- assert( pPage->pBt );
- assert( pPage->pDbPage!=0 );
- assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
- assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- sqlite3PagerUnrefNotNull(pPage->pDbPage);
-}
-static void releasePage(MemPage *pPage){
- if( pPage ) releasePageNotNull(pPage);
-}
-static void releasePageOne(MemPage *pPage){
- assert( pPage!=0 );
- assert( pPage->aData );
- assert( pPage->pBt );
- assert( pPage->pDbPage!=0 );
- assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
- assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- sqlite3PagerUnrefPageOne(pPage->pDbPage);
-}
-
-/*
-** Get an unused page.
-**
-** This works just like btreeGetPage() with the addition:
-**
-** * If the page is already in use for some other purpose, immediately
-** release it and return an SQLITE_CURRUPT error.
-** * Make sure the isInit flag is clear
-*/
-static int btreeGetUnusedPage(
- BtShared *pBt, /* The btree */
- Pgno pgno, /* Number of the page to fetch */
- MemPage **ppPage, /* Return the page in this parameter */
- int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */
-){
- int rc = btreeGetPage(pBt, pgno, ppPage, flags);
- if( rc==SQLITE_OK ){
- if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
- releasePage(*ppPage);
- *ppPage = 0;
- return SQLITE_CORRUPT_BKPT;
- }
- (*ppPage)->isInit = 0;
- }else{
- *ppPage = 0;
- }
- return rc;
-}
-
-
-/*
-** During a rollback, when the pager reloads information into the cache
-** so that the cache is restored to its original state at the start of
-** the transaction, for each page restored this routine is called.
-**
-** This routine needs to reset the extra data section at the end of the
-** page to agree with the restored data.
-*/
-static void pageReinit(DbPage *pData){
- MemPage *pPage;
- pPage = (MemPage *)sqlite3PagerGetExtra(pData);
- assert( sqlite3PagerPageRefcount(pData)>0 );
- if( pPage->isInit ){
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->isInit = 0;
- if( sqlite3PagerPageRefcount(pData)>1 ){
- /* pPage might not be a btree page; it might be an overflow page
- ** or ptrmap page or a free page. In those cases, the following
- ** call to btreeInitPage() will likely return SQLITE_CORRUPT.
- ** But no harm is done by this. And it is very important that
- ** btreeInitPage() be called on every btree page so we make
- ** the call for every page that comes in for re-initing. */
- btreeInitPage(pPage);
- }
- }
-}
-
-/*
-** Invoke the busy handler for a btree.
-*/
-static int btreeInvokeBusyHandler(void *pArg){
- BtShared *pBt = (BtShared*)pArg;
- assert( pBt->db );
- assert( sqlite3_mutex_held(pBt->db->mutex) );
- return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
- sqlite3PagerFile(pBt->pPager));
-}
-
-/*
-** Open a database file.
-**
-** zFilename is the name of the database file. If zFilename is NULL
-** then an ephemeral database is created. The ephemeral database might
-** be exclusively in memory, or it might use a disk-based memory cache.
-** Either way, the ephemeral database will be automatically deleted
-** when sqlite3BtreeClose() is called.
-**
-** If zFilename is ":memory:" then an in-memory database is created
-** that is automatically destroyed when it is closed.
-**
-** The "flags" parameter is a bitmask that might contain bits like
-** BTREE_OMIT_JOURNAL and/or BTREE_MEMORY.
-**
-** If the database is already opened in the same database connection
-** and we are in shared cache mode, then the open will fail with an
-** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
-** objects in the same database connection since doing so will lead
-** to problems with locking.
-*/
-int sqlite3BtreeOpen(
- sqlite3_vfs *pVfs, /* VFS to use for this b-tree */
- const char *zFilename, /* Name of the file containing the BTree database */
- sqlite3 *db, /* Associated database handle */
- Btree **ppBtree, /* Pointer to new Btree object written here */
- int flags, /* Options */
- int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */
-){
- BtShared *pBt = 0; /* Shared part of btree structure */
- Btree *p; /* Handle to return */
- sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */
- int rc = SQLITE_OK; /* Result code from this function */
- u8 nReserve; /* Byte of unused space on each page */
- unsigned char zDbHeader[100]; /* Database header content */
-
- /* True if opening an ephemeral, temporary database */
- const int isTempDb = zFilename==0 || zFilename[0]==0;
-
- /* Set the variable isMemdb to true for an in-memory database, or
- ** false for a file-based database.
- */
-#ifdef SQLITE_OMIT_MEMORYDB
- const int isMemdb = 0;
-#else
- const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
- || (isTempDb && sqlite3TempInMemory(db))
- || (vfsFlags & SQLITE_OPEN_MEMORY)!=0;
-#endif
-
- assert( db!=0 );
- assert( pVfs!=0 );
- assert( sqlite3_mutex_held(db->mutex) );
- assert( (flags&0xff)==flags ); /* flags fit in 8 bits */
-
- /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
- assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
-
- /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
- assert( (flags & BTREE_SINGLE)==0 || isTempDb );
-
- if( isMemdb ){
- flags |= BTREE_MEMORY;
- }
- if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
- vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
- }
- p = sqlite3MallocZero(sizeof(Btree));
- if( !p ){
- return SQLITE_NOMEM_BKPT;
- }
- p->inTrans = TRANS_NONE;
- p->db = db;
-#ifndef SQLITE_OMIT_SHARED_CACHE
- p->lock.pBtree = p;
- p->lock.iTable = 1;
-#endif
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
- /*
- ** If this Btree is a candidate for shared cache, try to find an
- ** existing BtShared object that we can share with
- */
- if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
- if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
- int nFilename = sqlite3Strlen30(zFilename)+1;
- int nFullPathname = pVfs->mxPathname+1;
- char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename));
- MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
-
- p->sharable = 1;
- if( !zFullPathname ){
- sqlite3_free(p);
- return SQLITE_NOMEM_BKPT;
- }
- if( isMemdb ){
- memcpy(zFullPathname, zFilename, nFilename);
- }else{
- rc = sqlite3OsFullPathname(pVfs, zFilename,
- nFullPathname, zFullPathname);
- if( rc ){
- sqlite3_free(zFullPathname);
- sqlite3_free(p);
- return rc;
- }
- }
-#if SQLITE_THREADSAFE
- mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
- sqlite3_mutex_enter(mutexOpen);
- mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
- sqlite3_mutex_enter(mutexShared);
-#endif
- for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
- assert( pBt->nRef>0 );
- if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0))
- && sqlite3PagerVfs(pBt->pPager)==pVfs ){
- int iDb;
- for(iDb=db->nDb-1; iDb>=0; iDb--){
- Btree *pExisting = db->aDb[iDb].pBt;
- if( pExisting && pExisting->pBt==pBt ){
- sqlite3_mutex_leave(mutexShared);
- sqlite3_mutex_leave(mutexOpen);
- sqlite3_free(zFullPathname);
- sqlite3_free(p);
- return SQLITE_CONSTRAINT;
- }
- }
- p->pBt = pBt;
- pBt->nRef++;
- break;
- }
- }
- sqlite3_mutex_leave(mutexShared);
- sqlite3_free(zFullPathname);
- }
-#ifdef SQLITE_DEBUG
- else{
- /* In debug mode, we mark all persistent databases as sharable
- ** even when they are not. This exercises the locking code and
- ** gives more opportunity for asserts(sqlite3_mutex_held())
- ** statements to find locking problems.
- */
- p->sharable = 1;
- }
-#endif
- }
-#endif
- if( pBt==0 ){
- /*
- ** The following asserts make sure that structures used by the btree are
- ** the right size. This is to guard against size changes that result
- ** when compiling on a different architecture.
- */
- assert( sizeof(i64)==8 );
- assert( sizeof(u64)==8 );
- assert( sizeof(u32)==4 );
- assert( sizeof(u16)==2 );
- assert( sizeof(Pgno)==4 );
-
- pBt = sqlite3MallocZero( sizeof(*pBt) );
- if( pBt==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto btree_open_out;
- }
- rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
- sizeof(MemPage), flags, vfsFlags, pageReinit);
- if( rc==SQLITE_OK ){
- sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
- rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
- }
- if( rc!=SQLITE_OK ){
- goto btree_open_out;
- }
- pBt->openFlags = (u8)flags;
- pBt->db = db;
- sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
- p->pBt = pBt;
-
- pBt->pCursor = 0;
- pBt->pPage1 = 0;
- if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY;
-#if defined(SQLITE_SECURE_DELETE)
- pBt->btsFlags |= BTS_SECURE_DELETE;
-#elif defined(SQLITE_FAST_SECURE_DELETE)
- pBt->btsFlags |= BTS_OVERWRITE;
-#endif
- /* EVIDENCE-OF: R-51873-39618 The page size for a database file is
- ** determined by the 2-byte integer located at an offset of 16 bytes from
- ** the beginning of the database file. */
- pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16);
- if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
- || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
- pBt->pageSize = 0;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- /* If the magic name ":memory:" will create an in-memory database, then
- ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
- ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if
- ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a
- ** regular file-name. In this case the auto-vacuum applies as per normal.
- */
- if( zFilename && !isMemdb ){
- pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0);
- pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0);
- }
-#endif
- nReserve = 0;
- }else{
- /* EVIDENCE-OF: R-37497-42412 The size of the reserved region is
- ** determined by the one-byte unsigned integer found at an offset of 20
- ** into the database file header. */
- nReserve = zDbHeader[20];
- pBt->btsFlags |= BTS_PAGESIZE_FIXED;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
- pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0);
-#endif
- }
- rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
- if( rc ) goto btree_open_out;
- pBt->usableSize = pBt->pageSize - nReserve;
- assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
- /* Add the new BtShared object to the linked list sharable BtShareds.
- */
- pBt->nRef = 1;
- if( p->sharable ){
- MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
- MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
- if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
- pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
- if( pBt->mutex==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto btree_open_out;
- }
- }
- sqlite3_mutex_enter(mutexShared);
- pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList);
- GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt;
- sqlite3_mutex_leave(mutexShared);
- }
-#endif
- }
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
- /* If the new Btree uses a sharable pBtShared, then link the new
- ** Btree into the list of all sharable Btrees for the same connection.
- ** The list is kept in ascending order by pBt address.
- */
- if( p->sharable ){
- int i;
- Btree *pSib;
- for(i=0; i<db->nDb; i++){
- if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){
- while( pSib->pPrev ){ pSib = pSib->pPrev; }
- if( (uptr)p->pBt<(uptr)pSib->pBt ){
- p->pNext = pSib;
- p->pPrev = 0;
- pSib->pPrev = p;
- }else{
- while( pSib->pNext && (uptr)pSib->pNext->pBt<(uptr)p->pBt ){
- pSib = pSib->pNext;
- }
- p->pNext = pSib->pNext;
- p->pPrev = pSib;
- if( p->pNext ){
- p->pNext->pPrev = p;
- }
- pSib->pNext = p;
- }
- break;
- }
- }
- }
-#endif
- *ppBtree = p;
-
-btree_open_out:
- if( rc!=SQLITE_OK ){
- if( pBt && pBt->pPager ){
- sqlite3PagerClose(pBt->pPager, 0);
- }
- sqlite3_free(pBt);
- sqlite3_free(p);
- *ppBtree = 0;
- }else{
- sqlite3_file *pFile;
-
- /* If the B-Tree was successfully opened, set the pager-cache size to the
- ** default value. Except, when opening on an existing shared pager-cache,
- ** do not change the pager-cache size.
- */
- if( sqlite3BtreeSchema(p, 0, 0)==0 ){
- sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
- }
-
- pFile = sqlite3PagerFile(pBt->pPager);
- if( pFile->pMethods ){
- sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db);
- }
- }
- if( mutexOpen ){
- assert( sqlite3_mutex_held(mutexOpen) );
- sqlite3_mutex_leave(mutexOpen);
- }
- assert( rc!=SQLITE_OK || sqlite3BtreeConnectionCount(*ppBtree)>0 );
- return rc;
-}
-
-/*
-** Decrement the BtShared.nRef counter. When it reaches zero,
-** remove the BtShared structure from the sharing list. Return
-** true if the BtShared.nRef counter reaches zero and return
-** false if it is still positive.
-*/
-static int removeFromSharingList(BtShared *pBt){
-#ifndef SQLITE_OMIT_SHARED_CACHE
- MUTEX_LOGIC( sqlite3_mutex *pMaster; )
- BtShared *pList;
- int removed = 0;
-
- assert( sqlite3_mutex_notheld(pBt->mutex) );
- MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
- sqlite3_mutex_enter(pMaster);
- pBt->nRef--;
- if( pBt->nRef<=0 ){
- if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
- GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;
- }else{
- pList = GLOBAL(BtShared*,sqlite3SharedCacheList);
- while( ALWAYS(pList) && pList->pNext!=pBt ){
- pList=pList->pNext;
- }
- if( ALWAYS(pList) ){
- pList->pNext = pBt->pNext;
- }
- }
- if( SQLITE_THREADSAFE ){
- sqlite3_mutex_free(pBt->mutex);
- }
- removed = 1;
- }
- sqlite3_mutex_leave(pMaster);
- return removed;
-#else
- return 1;
-#endif
-}
-
-/*
-** Make sure pBt->pTmpSpace points to an allocation of
-** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
-** pointer.
-*/
-static void allocateTempSpace(BtShared *pBt){
- if( !pBt->pTmpSpace ){
- pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
-
- /* One of the uses of pBt->pTmpSpace is to format cells before
- ** inserting them into a leaf page (function fillInCell()). If
- ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
- ** by the various routines that manipulate binary cells. Which
- ** can mean that fillInCell() only initializes the first 2 or 3
- ** bytes of pTmpSpace, but that the first 4 bytes are copied from
- ** it into a database page. This is not actually a problem, but it
- ** does cause a valgrind error when the 1 or 2 bytes of unitialized
- ** data is passed to system call write(). So to avoid this error,
- ** zero the first 4 bytes of temp space here.
- **
- ** Also: Provide four bytes of initialized space before the
- ** beginning of pTmpSpace as an area available to prepend the
- ** left-child pointer to the beginning of a cell.
- */
- if( pBt->pTmpSpace ){
- memset(pBt->pTmpSpace, 0, 8);
- pBt->pTmpSpace += 4;
- }
- }
-}
-
-/*
-** Free the pBt->pTmpSpace allocation
-*/
-static void freeTempSpace(BtShared *pBt){
- if( pBt->pTmpSpace ){
- pBt->pTmpSpace -= 4;
- sqlite3PageFree(pBt->pTmpSpace);
- pBt->pTmpSpace = 0;
- }
-}
-
-/*
-** Close an open database and invalidate all cursors.
-*/
-int sqlite3BtreeClose(Btree *p){
- BtShared *pBt = p->pBt;
- BtCursor *pCur;
-
- /* Close all cursors opened via this handle. */
- assert( sqlite3_mutex_held(p->db->mutex) );
- sqlite3BtreeEnter(p);
- pCur = pBt->pCursor;
- while( pCur ){
- BtCursor *pTmp = pCur;
- pCur = pCur->pNext;
- if( pTmp->pBtree==p ){
- sqlite3BtreeCloseCursor(pTmp);
- }
- }
-
- /* Rollback any active transaction and free the handle structure.
- ** The call to sqlite3BtreeRollback() drops any table-locks held by
- ** this handle.
- */
- sqlite3BtreeRollback(p, SQLITE_OK, 0);
- sqlite3BtreeLeave(p);
-
- /* If there are still other outstanding references to the shared-btree
- ** structure, return now. The remainder of this procedure cleans
- ** up the shared-btree.
- */
- assert( p->wantToLock==0 && p->locked==0 );
- if( !p->sharable || removeFromSharingList(pBt) ){
- /* The pBt is no longer on the sharing list, so we can access
- ** it without having to hold the mutex.
- **
- ** Clean out and delete the BtShared object.
- */
- assert( !pBt->pCursor );
- sqlite3PagerClose(pBt->pPager, p->db);
- if( pBt->xFreeSchema && pBt->pSchema ){
- pBt->xFreeSchema(pBt->pSchema);
- }
- sqlite3DbFree(0, pBt->pSchema);
- freeTempSpace(pBt);
- sqlite3_free(pBt);
- }
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
- assert( p->wantToLock==0 );
- assert( p->locked==0 );
- if( p->pPrev ) p->pPrev->pNext = p->pNext;
- if( p->pNext ) p->pNext->pPrev = p->pPrev;
-#endif
-
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Change the "soft" limit on the number of pages in the cache.
-** Unused and unmodified pages will be recycled when the number of
-** pages in the cache exceeds this soft limit. But the size of the
-** cache is allowed to grow larger than this limit if it contains
-** dirty pages or pages still in active use.
-*/
-int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
- BtShared *pBt = p->pBt;
- assert( sqlite3_mutex_held(p->db->mutex) );
- sqlite3BtreeEnter(p);
- sqlite3PagerSetCachesize(pBt->pPager, mxPage);
- sqlite3BtreeLeave(p);
- return SQLITE_OK;
-}
-
-/*
-** Change the "spill" limit on the number of pages in the cache.
-** If the number of pages exceeds this limit during a write transaction,
-** the pager might attempt to "spill" pages to the journal early in
-** order to free up memory.
-**
-** The value returned is the current spill size. If zero is passed
-** as an argument, no changes are made to the spill size setting, so
-** using mxPage of 0 is a way to query the current spill size.
-*/
-int sqlite3BtreeSetSpillSize(Btree *p, int mxPage){
- BtShared *pBt = p->pBt;
- int res;
- assert( sqlite3_mutex_held(p->db->mutex) );
- sqlite3BtreeEnter(p);
- res = sqlite3PagerSetSpillsize(pBt->pPager, mxPage);
- sqlite3BtreeLeave(p);
- return res;
-}
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/*
-** Change the limit on the amount of the database file that may be
-** memory mapped.
-*/
-int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
- BtShared *pBt = p->pBt;
- assert( sqlite3_mutex_held(p->db->mutex) );
- sqlite3BtreeEnter(p);
- sqlite3PagerSetMmapLimit(pBt->pPager, szMmap);
- sqlite3BtreeLeave(p);
- return SQLITE_OK;
-}
-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-
-/*
-** Change the way data is synced to disk in order to increase or decrease
-** how well the database resists damage due to OS crashes and power
-** failures. Level 1 is the same as asynchronous (no syncs() occur and
-** there is a high probability of damage) Level 2 is the default. There
-** is a very low but non-zero probability of damage. Level 3 reduces the
-** probability of damage to near zero but with a write performance reduction.
-*/
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-int sqlite3BtreeSetPagerFlags(
- Btree *p, /* The btree to set the safety level on */
- unsigned pgFlags /* Various PAGER_* flags */
-){
- BtShared *pBt = p->pBt;
- assert( sqlite3_mutex_held(p->db->mutex) );
- sqlite3BtreeEnter(p);
- sqlite3PagerSetFlags(pBt->pPager, pgFlags);
- sqlite3BtreeLeave(p);
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Change the default pages size and the number of reserved bytes per page.
-** Or, if the page size has already been fixed, return SQLITE_READONLY
-** without changing anything.
-**
-** The page size must be a power of 2 between 512 and 65536. If the page
-** size supplied does not meet this constraint then the page size is not
-** changed.
-**
-** Page sizes are constrained to be a power of two so that the region
-** of the database file used for locking (beginning at PENDING_BYTE,
-** the first byte past the 1GB boundary, 0x40000000) needs to occur
-** at the beginning of a page.
-**
-** If parameter nReserve is less than zero, then the number of reserved
-** bytes per page is left unchanged.
-**
-** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size
-** and autovacuum mode can no longer be changed.
-*/
-int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
- int rc = SQLITE_OK;
- BtShared *pBt = p->pBt;
- assert( nReserve>=-1 && nReserve<=255 );
- sqlite3BtreeEnter(p);
-#if SQLITE_HAS_CODEC
- if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve;
-#endif
- if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
- sqlite3BtreeLeave(p);
- return SQLITE_READONLY;
- }
- if( nReserve<0 ){
- nReserve = pBt->pageSize - pBt->usableSize;
- }
- assert( nReserve>=0 && nReserve<=255 );
- if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
- ((pageSize-1)&pageSize)==0 ){
- assert( (pageSize & 7)==0 );
- assert( !pBt->pCursor );
- pBt->pageSize = (u32)pageSize;
- freeTempSpace(pBt);
- }
- rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
- pBt->usableSize = pBt->pageSize - (u16)nReserve;
- if( iFix ) pBt->btsFlags |= BTS_PAGESIZE_FIXED;
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
-** Return the currently defined page size
-*/
-int sqlite3BtreeGetPageSize(Btree *p){
- return p->pBt->pageSize;
-}
-
-/*
-** This function is similar to sqlite3BtreeGetReserve(), except that it
-** may only be called if it is guaranteed that the b-tree mutex is already
-** held.
-**
-** This is useful in one special case in the backup API code where it is
-** known that the shared b-tree mutex is held, but the mutex on the
-** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
-** were to be called, it might collide with some other operation on the
-** database handle that owns *p, causing undefined behavior.
-*/
-int sqlite3BtreeGetReserveNoMutex(Btree *p){
- int n;
- assert( sqlite3_mutex_held(p->pBt->mutex) );
- n = p->pBt->pageSize - p->pBt->usableSize;
- return n;
-}
-
-/*
-** Return the number of bytes of space at the end of every page that
-** are intentually left unused. This is the "reserved" space that is
-** sometimes used by extensions.
-**
-** If SQLITE_HAS_MUTEX is defined then the number returned is the
-** greater of the current reserved space and the maximum requested
-** reserve space.
-*/
-int sqlite3BtreeGetOptimalReserve(Btree *p){
- int n;
- sqlite3BtreeEnter(p);
- n = sqlite3BtreeGetReserveNoMutex(p);
-#ifdef SQLITE_HAS_CODEC
- if( n<p->pBt->optimalReserve ) n = p->pBt->optimalReserve;
-#endif
- sqlite3BtreeLeave(p);
- return n;
-}
-
-
-/*
-** Set the maximum page count for a database if mxPage is positive.
-** No changes are made if mxPage is 0 or negative.
-** Regardless of the value of mxPage, return the maximum page count.
-*/
-int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
- int n;
- sqlite3BtreeEnter(p);
- n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
- sqlite3BtreeLeave(p);
- return n;
-}
-
-/*
-** Change the values for the BTS_SECURE_DELETE and BTS_OVERWRITE flags:
-**
-** newFlag==0 Both BTS_SECURE_DELETE and BTS_OVERWRITE are cleared
-** newFlag==1 BTS_SECURE_DELETE set and BTS_OVERWRITE is cleared
-** newFlag==2 BTS_SECURE_DELETE cleared and BTS_OVERWRITE is set
-** newFlag==(-1) No changes
-**
-** This routine acts as a query if newFlag is less than zero
-**
-** With BTS_OVERWRITE set, deleted content is overwritten by zeros, but
-** freelist leaf pages are not written back to the database. Thus in-page
-** deleted content is cleared, but freelist deleted content is not.
-**
-** With BTS_SECURE_DELETE, operation is like BTS_OVERWRITE with the addition
-** that freelist leaf pages are written back into the database, increasing
-** the amount of disk I/O.
-*/
-int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
- int b;
- if( p==0 ) return 0;
- sqlite3BtreeEnter(p);
- assert( BTS_OVERWRITE==BTS_SECURE_DELETE*2 );
- assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) );
- if( newFlag>=0 ){
- p->pBt->btsFlags &= ~BTS_FAST_SECURE;
- p->pBt->btsFlags |= BTS_SECURE_DELETE*newFlag;
- }
- b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE;
- sqlite3BtreeLeave(p);
- return b;
-}
-
-/*
-** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
-** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
-** is disabled. The default value for the auto-vacuum property is
-** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
-*/
-int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
-#ifdef SQLITE_OMIT_AUTOVACUUM
- return SQLITE_READONLY;
-#else
- BtShared *pBt = p->pBt;
- int rc = SQLITE_OK;
- u8 av = (u8)autoVacuum;
-
- sqlite3BtreeEnter(p);
- if( (pBt->btsFlags & BTS_PAGESIZE_FIXED)!=0 && (av ?1:0)!=pBt->autoVacuum ){
- rc = SQLITE_READONLY;
- }else{
- pBt->autoVacuum = av ?1:0;
- pBt->incrVacuum = av==2 ?1:0;
- }
- sqlite3BtreeLeave(p);
- return rc;
-#endif
-}
-
-/*
-** Return the value of the 'auto-vacuum' property. If auto-vacuum is
-** enabled 1 is returned. Otherwise 0.
-*/
-int sqlite3BtreeGetAutoVacuum(Btree *p){
-#ifdef SQLITE_OMIT_AUTOVACUUM
- return BTREE_AUTOVACUUM_NONE;
-#else
- int rc;
- sqlite3BtreeEnter(p);
- rc = (
- (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE:
- (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL:
- BTREE_AUTOVACUUM_INCR
- );
- sqlite3BtreeLeave(p);
- return rc;
-#endif
-}
-
-/*
-** If the user has not set the safety-level for this database connection
-** using "PRAGMA synchronous", and if the safety-level is not already
-** set to the value passed to this function as the second parameter,
-** set it so.
-*/
-#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS \
- && !defined(SQLITE_OMIT_WAL)
-static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
- sqlite3 *db;
- Db *pDb;
- if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
- while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
- if( pDb->bSyncSet==0
- && pDb->safety_level!=safety_level
- && pDb!=&db->aDb[1]
- ){
- pDb->safety_level = safety_level;
- sqlite3PagerSetFlags(pBt->pPager,
- pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
- }
- }
-}
-#else
-# define setDefaultSyncFlag(pBt,safety_level)
-#endif
-
-/* Forward declaration */
-static int newDatabase(BtShared*);
-
-
-/*
-** Get a reference to pPage1 of the database file. This will
-** also acquire a readlock on that file.
-**
-** SQLITE_OK is returned on success. If the file is not a
-** well-formed database file, then SQLITE_CORRUPT is returned.
-** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
-** is returned if we run out of memory.
-*/
-static int lockBtree(BtShared *pBt){
- int rc; /* Result code from subfunctions */
- MemPage *pPage1; /* Page 1 of the database file */
- int nPage; /* Number of pages in the database */
- int nPageFile = 0; /* Number of pages in the database file */
- int nPageHeader; /* Number of pages in the database according to hdr */
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pBt->pPage1==0 );
- rc = sqlite3PagerSharedLock(pBt->pPager);
- if( rc!=SQLITE_OK ) return rc;
- rc = btreeGetPage(pBt, 1, &pPage1, 0);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Do some checking to help insure the file we opened really is
- ** a valid database file.
- */
- nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
- sqlite3PagerPagecount(pBt->pPager, &nPageFile);
- if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
- nPage = nPageFile;
- }
- if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){
- nPage = 0;
- }
- if( nPage>0 ){
- u32 pageSize;
- u32 usableSize;
- u8 *page1 = pPage1->aData;
- rc = SQLITE_NOTADB;
- /* EVIDENCE-OF: R-43737-39999 Every valid SQLite database file begins
- ** with the following 16 bytes (in hex): 53 51 4c 69 74 65 20 66 6f 72 6d
- ** 61 74 20 33 00. */
- if( memcmp(page1, zMagicHeader, 16)!=0 ){
- goto page1_init_failed;
- }
-
-#ifdef SQLITE_OMIT_WAL
- if( page1[18]>1 ){
- pBt->btsFlags |= BTS_READ_ONLY;
- }
- if( page1[19]>1 ){
- goto page1_init_failed;
- }
-#else
- if( page1[18]>2 ){
- pBt->btsFlags |= BTS_READ_ONLY;
- }
- if( page1[19]>2 ){
- goto page1_init_failed;
- }
-
- /* If the write version is set to 2, this database should be accessed
- ** in WAL mode. If the log is not already open, open it now. Then
- ** return SQLITE_OK and return without populating BtShared.pPage1.
- ** The caller detects this and calls this function again. This is
- ** required as the version of page 1 currently in the page1 buffer
- ** may not be the latest version - there may be a newer one in the log
- ** file.
- */
- if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
- int isOpen = 0;
- rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
- if( rc!=SQLITE_OK ){
- goto page1_init_failed;
- }else{
- setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
- if( isOpen==0 ){
- releasePageOne(pPage1);
- return SQLITE_OK;
- }
- }
- rc = SQLITE_NOTADB;
- }else{
- setDefaultSyncFlag(pBt, SQLITE_DEFAULT_SYNCHRONOUS+1);
- }
-#endif
-
- /* EVIDENCE-OF: R-15465-20813 The maximum and minimum embedded payload
- ** fractions and the leaf payload fraction values must be 64, 32, and 32.
- **
- ** The original design allowed these amounts to vary, but as of
- ** version 3.6.0, we require them to be fixed.
- */
- if( memcmp(&page1[21], "\100\040\040",3)!=0 ){
- goto page1_init_failed;
- }
- /* EVIDENCE-OF: R-51873-39618 The page size for a database file is
- ** determined by the 2-byte integer located at an offset of 16 bytes from
- ** the beginning of the database file. */
- pageSize = (page1[16]<<8) | (page1[17]<<16);
- /* EVIDENCE-OF: R-25008-21688 The size of a page is a power of two
- ** between 512 and 65536 inclusive. */
- if( ((pageSize-1)&pageSize)!=0
- || pageSize>SQLITE_MAX_PAGE_SIZE
- || pageSize<=256
- ){
- goto page1_init_failed;
- }
- assert( (pageSize & 7)==0 );
- /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte
- ** integer at offset 20 is the number of bytes of space at the end of
- ** each page to reserve for extensions.
- **
- ** EVIDENCE-OF: R-37497-42412 The size of the reserved region is
- ** determined by the one-byte unsigned integer found at an offset of 20
- ** into the database file header. */
- usableSize = pageSize - page1[20];
- if( (u32)pageSize!=pBt->pageSize ){
- /* After reading the first page of the database assuming a page size
- ** of BtShared.pageSize, we have discovered that the page-size is
- ** actually pageSize. Unlock the database, leave pBt->pPage1 at
- ** zero and return SQLITE_OK. The caller will call this function
- ** again with the correct page-size.
- */
- releasePageOne(pPage1);
- pBt->usableSize = usableSize;
- pBt->pageSize = pageSize;
- freeTempSpace(pBt);
- rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize,
- pageSize-usableSize);
- return rc;
- }
- if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){
- rc = SQLITE_CORRUPT_BKPT;
- goto page1_init_failed;
- }
- /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to
- ** be less than 480. In other words, if the page size is 512, then the
- ** reserved space size cannot exceed 32. */
- if( usableSize<480 ){
- goto page1_init_failed;
- }
- pBt->pageSize = pageSize;
- pBt->usableSize = usableSize;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0);
- pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0);
-#endif
- }
-
- /* maxLocal is the maximum amount of payload to store locally for
- ** a cell. Make sure it is small enough so that at least minFanout
- ** cells can will fit on one page. We assume a 10-byte page header.
- ** Besides the payload, the cell must store:
- ** 2-byte pointer to the cell
- ** 4-byte child pointer
- ** 9-byte nKey value
- ** 4-byte nData value
- ** 4-byte overflow page pointer
- ** So a cell consists of a 2-byte pointer, a header which is as much as
- ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow
- ** page pointer.
- */
- pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23);
- pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23);
- pBt->maxLeaf = (u16)(pBt->usableSize - 35);
- pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23);
- if( pBt->maxLocal>127 ){
- pBt->max1bytePayload = 127;
- }else{
- pBt->max1bytePayload = (u8)pBt->maxLocal;
- }
- assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
- pBt->pPage1 = pPage1;
- pBt->nPage = nPage;
- return SQLITE_OK;
-
-page1_init_failed:
- releasePageOne(pPage1);
- pBt->pPage1 = 0;
- return rc;
-}
-
-#ifndef NDEBUG
-/*
-** Return the number of cursors open on pBt. This is for use
-** in assert() expressions, so it is only compiled if NDEBUG is not
-** defined.
-**
-** Only write cursors are counted if wrOnly is true. If wrOnly is
-** false then all cursors are counted.
-**
-** For the purposes of this routine, a cursor is any cursor that
-** is capable of reading or writing to the database. Cursors that
-** have been tripped into the CURSOR_FAULT state are not counted.
-*/
-static int countValidCursors(BtShared *pBt, int wrOnly){
- BtCursor *pCur;
- int r = 0;
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
- && pCur->eState!=CURSOR_FAULT ) r++;
- }
- return r;
-}
-#endif
-
-/*
-** If there are no outstanding cursors and we are not in the middle
-** of a transaction but there is a read lock on the database, then
-** this routine unrefs the first page of the database file which
-** has the effect of releasing the read lock.
-**
-** If there is a transaction in progress, this routine is a no-op.
-*/
-static void unlockBtreeIfUnused(BtShared *pBt){
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE );
- if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
- MemPage *pPage1 = pBt->pPage1;
- assert( pPage1->aData );
- assert( sqlite3PagerRefcount(pBt->pPager)==1 );
- pBt->pPage1 = 0;
- releasePageOne(pPage1);
- }
-}
-
-/*
-** If pBt points to an empty file then convert that empty file
-** into a new empty database by initializing the first page of
-** the database.
-*/
-static int newDatabase(BtShared *pBt){
- MemPage *pP1;
- unsigned char *data;
- int rc;
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- if( pBt->nPage>0 ){
- return SQLITE_OK;
- }
- pP1 = pBt->pPage1;
- assert( pP1!=0 );
- data = pP1->aData;
- rc = sqlite3PagerWrite(pP1->pDbPage);
- if( rc ) return rc;
- memcpy(data, zMagicHeader, sizeof(zMagicHeader));
- assert( sizeof(zMagicHeader)==16 );
- data[16] = (u8)((pBt->pageSize>>8)&0xff);
- data[17] = (u8)((pBt->pageSize>>16)&0xff);
- data[18] = 1;
- data[19] = 1;
- assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize);
- data[20] = (u8)(pBt->pageSize - pBt->usableSize);
- data[21] = 64;
- data[22] = 32;
- data[23] = 32;
- memset(&data[24], 0, 100-24);
- zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
- pBt->btsFlags |= BTS_PAGESIZE_FIXED;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
- assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
- put4byte(&data[36 + 4*4], pBt->autoVacuum);
- put4byte(&data[36 + 7*4], pBt->incrVacuum);
-#endif
- pBt->nPage = 1;
- data[31] = 1;
- return SQLITE_OK;
-}
-
-/*
-** Initialize the first page of the database file (creating a database
-** consisting of a single page and no schema objects). Return SQLITE_OK
-** if successful, or an SQLite error code otherwise.
-*/
-int sqlite3BtreeNewDb(Btree *p){
- int rc;
- sqlite3BtreeEnter(p);
- p->pBt->nPage = 0;
- rc = newDatabase(p->pBt);
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
-** Attempt to start a new transaction. A write-transaction
-** is started if the second argument is nonzero, otherwise a read-
-** transaction. If the second argument is 2 or more and exclusive
-** transaction is started, meaning that no other process is allowed
-** to access the database. A preexisting transaction may not be
-** upgraded to exclusive by calling this routine a second time - the
-** exclusivity flag only works for a new transaction.
-**
-** A write-transaction must be started before attempting any
-** changes to the database. None of the following routines
-** will work unless a transaction is started first:
-**
-** sqlite3BtreeCreateTable()
-** sqlite3BtreeCreateIndex()
-** sqlite3BtreeClearTable()
-** sqlite3BtreeDropTable()
-** sqlite3BtreeInsert()
-** sqlite3BtreeDelete()
-** sqlite3BtreeUpdateMeta()
-**
-** If an initial attempt to acquire the lock fails because of lock contention
-** and the database was previously unlocked, then invoke the busy handler
-** if there is one. But if there was previously a read-lock, do not
-** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
-** returned when there is already a read-lock in order to avoid a deadlock.
-**
-** Suppose there are two processes A and B. A has a read lock and B has
-** a reserved lock. B tries to promote to exclusive but is blocked because
-** of A's read lock. A tries to promote to reserved but is blocked by B.
-** One or the other of the two processes must give way or there can be
-** no progress. By returning SQLITE_BUSY and not invoking the busy callback
-** when A already has a read lock, we encourage A to give up and let B
-** proceed.
-*/
-int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
- BtShared *pBt = p->pBt;
- int rc = SQLITE_OK;
-
- sqlite3BtreeEnter(p);
- btreeIntegrity(p);
-
- /* If the btree is already in a write-transaction, or it
- ** is already in a read-transaction and a read-transaction
- ** is requested, this is a no-op.
- */
- if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
- goto trans_begun;
- }
- assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
-
- /* Write transactions are not possible on a read-only database */
- if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
- rc = SQLITE_READONLY;
- goto trans_begun;
- }
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
- {
- sqlite3 *pBlock = 0;
- /* If another database handle has already opened a write transaction
- ** on this shared-btree structure and a second write transaction is
- ** requested, return SQLITE_LOCKED.
- */
- if( (wrflag && pBt->inTransaction==TRANS_WRITE)
- || (pBt->btsFlags & BTS_PENDING)!=0
- ){
- pBlock = pBt->pWriter->db;
- }else if( wrflag>1 ){
- BtLock *pIter;
- for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
- if( pIter->pBtree!=p ){
- pBlock = pIter->pBtree->db;
- break;
- }
- }
- }
- if( pBlock ){
- sqlite3ConnectionBlocked(p->db, pBlock);
- rc = SQLITE_LOCKED_SHAREDCACHE;
- goto trans_begun;
- }
- }
-#endif
-
- /* Any read-only or read-write transaction implies a read-lock on
- ** page 1. So if some other shared-cache client already has a write-lock
- ** on page 1, the transaction cannot be opened. */
- rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
- if( SQLITE_OK!=rc ) goto trans_begun;
-
- pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
- if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
- do {
- /* Call lockBtree() until either pBt->pPage1 is populated or
- ** lockBtree() returns something other than SQLITE_OK. lockBtree()
- ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
- ** reading page 1 it discovers that the page-size of the database
- ** file is not pBt->pageSize. In this case lockBtree() will update
- ** pBt->pageSize to the page-size of the file on disk.
- */
- while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) );
-
- if( rc==SQLITE_OK && wrflag ){
- if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
- rc = SQLITE_READONLY;
- }else{
- rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
- if( rc==SQLITE_OK ){
- rc = newDatabase(pBt);
- }
- }
- }
-
- if( rc!=SQLITE_OK ){
- unlockBtreeIfUnused(pBt);
- }
- }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
- btreeInvokeBusyHandler(pBt) );
- sqlite3PagerResetLockTimeout(pBt->pPager);
-
- if( rc==SQLITE_OK ){
- if( p->inTrans==TRANS_NONE ){
- pBt->nTransaction++;
-#ifndef SQLITE_OMIT_SHARED_CACHE
- if( p->sharable ){
- assert( p->lock.pBtree==p && p->lock.iTable==1 );
- p->lock.eLock = READ_LOCK;
- p->lock.pNext = pBt->pLock;
- pBt->pLock = &p->lock;
- }
-#endif
- }
- p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ);
- if( p->inTrans>pBt->inTransaction ){
- pBt->inTransaction = p->inTrans;
- }
- if( wrflag ){
- MemPage *pPage1 = pBt->pPage1;
-#ifndef SQLITE_OMIT_SHARED_CACHE
- assert( !pBt->pWriter );
- pBt->pWriter = p;
- pBt->btsFlags &= ~BTS_EXCLUSIVE;
- if( wrflag>1 ) pBt->btsFlags |= BTS_EXCLUSIVE;
-#endif
-
- /* If the db-size header field is incorrect (as it may be if an old
- ** client has been writing the database file), update it now. Doing
- ** this sooner rather than later means the database size can safely
- ** re-read the database size from page 1 if a savepoint or transaction
- ** rollback occurs within the transaction.
- */
- if( pBt->nPage!=get4byte(&pPage1->aData[28]) ){
- rc = sqlite3PagerWrite(pPage1->pDbPage);
- if( rc==SQLITE_OK ){
- put4byte(&pPage1->aData[28], pBt->nPage);
- }
- }
- }
- }
-
-
-trans_begun:
- if( rc==SQLITE_OK && wrflag ){
- /* This call makes sure that the pager has the correct number of
- ** open savepoints. If the second parameter is greater than 0 and
- ** the sub-journal is not already open, then it will be opened here.
- */
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
- }
-
- btreeIntegrity(p);
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
-
-/*
-** Set the pointer-map entries for all children of page pPage. Also, if
-** pPage contains cells that point to overflow pages, set the pointer
-** map entries for the overflow pages as well.
-*/
-static int setChildPtrmaps(MemPage *pPage){
- int i; /* Counter variable */
- int nCell; /* Number of cells in page pPage */
- int rc; /* Return code */
- BtShared *pBt = pPage->pBt;
- Pgno pgno = pPage->pgno;
-
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
- if( rc!=SQLITE_OK ) return rc;
- nCell = pPage->nCell;
-
- for(i=0; i<nCell; i++){
- u8 *pCell = findCell(pPage, i);
-
- ptrmapPutOvflPtr(pPage, pCell, &rc);
-
- if( !pPage->leaf ){
- Pgno childPgno = get4byte(pCell);
- ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc);
- }
- }
-
- if( !pPage->leaf ){
- Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc);
- }
-
- return rc;
-}
-
-/*
-** Somewhere on pPage is a pointer to page iFrom. Modify this pointer so
-** that it points to iTo. Parameter eType describes the type of pointer to
-** be modified, as follows:
-**
-** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
-** page of pPage.
-**
-** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
-** page pointed to by one of the cells on pPage.
-**
-** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next
-** overflow page in the list.
-*/
-static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- if( eType==PTRMAP_OVERFLOW2 ){
- /* The pointer is always the first 4 bytes of the page in this case. */
- if( get4byte(pPage->aData)!=iFrom ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- put4byte(pPage->aData, iTo);
- }else{
- int i;
- int nCell;
- int rc;
-
- rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
- if( rc ) return rc;
- nCell = pPage->nCell;
-
- for(i=0; i<nCell; i++){
- u8 *pCell = findCell(pPage, i);
- if( eType==PTRMAP_OVERFLOW1 ){
- CellInfo info;
- pPage->xParseCell(pPage, pCell, &info);
- if( info.nLocal<info.nPayload ){
- if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- if( iFrom==get4byte(pCell+info.nSize-4) ){
- put4byte(pCell+info.nSize-4, iTo);
- break;
- }
- }
- }else{
- if( get4byte(pCell)==iFrom ){
- put4byte(pCell, iTo);
- break;
- }
- }
- }
-
- if( i==nCell ){
- if( eType!=PTRMAP_BTREE ||
- get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
- }
- }
- return SQLITE_OK;
-}
-
-
-/*
-** Move the open database page pDbPage to location iFreePage in the
-** database. The pDbPage reference remains valid.
-**
-** The isCommit flag indicates that there is no need to remember that
-** the journal needs to be sync()ed before database page pDbPage->pgno
-** can be written to. The caller has already promised not to write to that
-** page.
-*/
-static int relocatePage(
- BtShared *pBt, /* Btree */
- MemPage *pDbPage, /* Open page to move */
- u8 eType, /* Pointer map 'type' entry for pDbPage */
- Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */
- Pgno iFreePage, /* The location to move pDbPage to */
- int isCommit /* isCommit flag passed to sqlite3PagerMovepage */
-){
- MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */
- Pgno iDbPage = pDbPage->pgno;
- Pager *pPager = pBt->pPager;
- int rc;
-
- assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
- eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pDbPage->pBt==pBt );
-
- /* Move page iDbPage from its current location to page number iFreePage */
- TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
- iDbPage, iFreePage, iPtrPage, eType));
- rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pDbPage->pgno = iFreePage;
-
- /* If pDbPage was a btree-page, then it may have child pages and/or cells
- ** that point to overflow pages. The pointer map entries for all these
- ** pages need to be changed.
- **
- ** If pDbPage is an overflow page, then the first 4 bytes may store a
- ** pointer to a subsequent overflow page. If this is the case, then
- ** the pointer map needs to be updated for the subsequent overflow page.
- */
- if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){
- rc = setChildPtrmaps(pDbPage);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }else{
- Pgno nextOvfl = get4byte(pDbPage->aData);
- if( nextOvfl!=0 ){
- ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage, &rc);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- }
-
- /* Fix the database pointer on page iPtrPage that pointed at iDbPage so
- ** that it points at iFreePage. Also fix the pointer map entry for
- ** iPtrPage.
- */
- if( eType!=PTRMAP_ROOTPAGE ){
- rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- rc = sqlite3PagerWrite(pPtrPage->pDbPage);
- if( rc!=SQLITE_OK ){
- releasePage(pPtrPage);
- return rc;
- }
- rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
- releasePage(pPtrPage);
- if( rc==SQLITE_OK ){
- ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc);
- }
- }
- return rc;
-}
-
-/* Forward declaration required by incrVacuumStep(). */
-static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
-
-/*
-** Perform a single step of an incremental-vacuum. If successful, return
-** SQLITE_OK. If there is no work to do (and therefore no point in
-** calling this function again), return SQLITE_DONE. Or, if an error
-** occurs, return some other error code.
-**
-** More specifically, this function attempts to re-organize the database so
-** that the last page of the file currently in use is no longer in use.
-**
-** Parameter nFin is the number of pages that this database would contain
-** were this function called until it returns SQLITE_DONE.
-**
-** If the bCommit parameter is non-zero, this function assumes that the
-** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
-** or an error. bCommit is passed true for an auto-vacuum-on-commit
-** operation, or false for an incremental vacuum.
-*/
-static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
- Pgno nFreeList; /* Number of pages still on the free-list */
- int rc;
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( iLastPg>nFin );
-
- if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
- u8 eType;
- Pgno iPtrPage;
-
- nFreeList = get4byte(&pBt->pPage1->aData[36]);
- if( nFreeList==0 ){
- return SQLITE_DONE;
- }
-
- rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- if( eType==PTRMAP_ROOTPAGE ){
- return SQLITE_CORRUPT_BKPT;
- }
-
- if( eType==PTRMAP_FREEPAGE ){
- if( bCommit==0 ){
- /* Remove the page from the files free-list. This is not required
- ** if bCommit is non-zero. In that case, the free-list will be
- ** truncated to zero after this function returns, so it doesn't
- ** matter if it still contains some garbage entries.
- */
- Pgno iFreePg;
- MemPage *pFreePg;
- rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- assert( iFreePg==iLastPg );
- releasePage(pFreePg);
- }
- } else {
- Pgno iFreePg; /* Index of free page to move pLastPg to */
- MemPage *pLastPg;
- u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */
- Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */
-
- rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* If bCommit is zero, this loop runs exactly once and page pLastPg
- ** is swapped with the first free page pulled off the free list.
- **
- ** On the other hand, if bCommit is greater than zero, then keep
- ** looping until a free-page located within the first nFin pages
- ** of the file is found.
- */
- if( bCommit==0 ){
- eMode = BTALLOC_LE;
- iNear = nFin;
- }
- do {
- MemPage *pFreePg;
- rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
- if( rc!=SQLITE_OK ){
- releasePage(pLastPg);
- return rc;
- }
- releasePage(pFreePg);
- }while( bCommit && iFreePg>nFin );
- assert( iFreePg<iLastPg );
-
- rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
- releasePage(pLastPg);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- }
-
- if( bCommit==0 ){
- do {
- iLastPg--;
- }while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) );
- pBt->bDoTruncate = 1;
- pBt->nPage = iLastPg;
- }
- return SQLITE_OK;
-}
-
-/*
-** The database opened by the first argument is an auto-vacuum database
-** nOrig pages in size containing nFree free pages. Return the expected
-** size of the database in pages following an auto-vacuum operation.
-*/
-static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
- int nEntry; /* Number of entries on one ptrmap page */
- Pgno nPtrmap; /* Number of PtrMap pages to be freed */
- Pgno nFin; /* Return value */
-
- nEntry = pBt->usableSize/5;
- nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
- nFin = nOrig - nFree - nPtrmap;
- if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
- nFin--;
- }
- while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
- nFin--;
- }
-
- return nFin;
-}
-
-/*
-** A write-transaction must be opened before calling this function.
-** It performs a single unit of work towards an incremental vacuum.
-**
-** If the incremental vacuum is finished after this function has run,
-** SQLITE_DONE is returned. If it is not finished, but no error occurred,
-** SQLITE_OK is returned. Otherwise an SQLite error code.
-*/
-int sqlite3BtreeIncrVacuum(Btree *p){
- int rc;
- BtShared *pBt = p->pBt;
-
- sqlite3BtreeEnter(p);
- assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE );
- if( !pBt->autoVacuum ){
- rc = SQLITE_DONE;
- }else{
- Pgno nOrig = btreePagecount(pBt);
- Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
- Pgno nFin = finalDbSize(pBt, nOrig, nFree);
-
- if( nOrig<nFin ){
- rc = SQLITE_CORRUPT_BKPT;
- }else if( nFree>0 ){
- rc = saveAllCursors(pBt, 0, 0);
- if( rc==SQLITE_OK ){
- invalidateAllOverflowCache(pBt);
- rc = incrVacuumStep(pBt, nFin, nOrig, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- put4byte(&pBt->pPage1->aData[28], pBt->nPage);
- }
- }else{
- rc = SQLITE_DONE;
- }
- }
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
-** This routine is called prior to sqlite3PagerCommit when a transaction
-** is committed for an auto-vacuum database.
-**
-** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
-** the database file should be truncated to during the commit process.
-** i.e. the database has been reorganized so that only the first *pnTrunc
-** pages are in use.
-*/
-static int autoVacuumCommit(BtShared *pBt){
- int rc = SQLITE_OK;
- Pager *pPager = pBt->pPager;
- VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); )
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- invalidateAllOverflowCache(pBt);
- assert(pBt->autoVacuum);
- if( !pBt->incrVacuum ){
- Pgno nFin; /* Number of pages in database after autovacuuming */
- Pgno nFree; /* Number of pages on the freelist initially */
- Pgno iFree; /* The next page to be freed */
- Pgno nOrig; /* Database size before freeing */
-
- nOrig = btreePagecount(pBt);
- if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){
- /* It is not possible to create a database for which the final page
- ** is either a pointer-map page or the pending-byte page. If one
- ** is encountered, this indicates corruption.
- */
- return SQLITE_CORRUPT_BKPT;
- }
-
- nFree = get4byte(&pBt->pPage1->aData[36]);
- nFin = finalDbSize(pBt, nOrig, nFree);
- if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
- if( nFin<nOrig ){
- rc = saveAllCursors(pBt, 0, 0);
- }
- for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
- rc = incrVacuumStep(pBt, nFin, iFree, 1);
- }
- if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- put4byte(&pBt->pPage1->aData[32], 0);
- put4byte(&pBt->pPage1->aData[36], 0);
- put4byte(&pBt->pPage1->aData[28], nFin);
- pBt->bDoTruncate = 1;
- pBt->nPage = nFin;
- }
- if( rc!=SQLITE_OK ){
- sqlite3PagerRollback(pPager);
- }
- }
-
- assert( nRef>=sqlite3PagerRefcount(pPager) );
- return rc;
-}
-
-#else /* ifndef SQLITE_OMIT_AUTOVACUUM */
-# define setChildPtrmaps(x) SQLITE_OK
-#endif
-
-/*
-** This routine does the first phase of a two-phase commit. This routine
-** causes a rollback journal to be created (if it does not already exist)
-** and populated with enough information so that if a power loss occurs
-** the database can be restored to its original state by playing back
-** the journal. Then the contents of the journal are flushed out to
-** the disk. After the journal is safely on oxide, the changes to the
-** database are written into the database file and flushed to oxide.
-** At the end of this call, the rollback journal still exists on the
-** disk and we are still holding all locks, so the transaction has not
-** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the
-** commit process.
-**
-** This call is a no-op if no write-transaction is currently active on pBt.
-**
-** Otherwise, sync the database file for the btree pBt. zMaster points to
-** the name of a master journal file that should be written into the
-** individual journal file, or is NULL, indicating no master journal file
-** (single database transaction).
-**
-** When this is called, the master journal should already have been
-** created, populated with this journal pointer and synced to disk.
-**
-** Once this is routine has returned, the only thing required to commit
-** the write-transaction for this database file is to delete the journal.
-*/
-int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
- int rc = SQLITE_OK;
- if( p->inTrans==TRANS_WRITE ){
- BtShared *pBt = p->pBt;
- sqlite3BtreeEnter(p);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- rc = autoVacuumCommit(pBt);
- if( rc!=SQLITE_OK ){
- sqlite3BtreeLeave(p);
- return rc;
- }
- }
- if( pBt->bDoTruncate ){
- sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
- }
-#endif
- rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
- sqlite3BtreeLeave(p);
- }
- return rc;
-}
-
-/*
-** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback()
-** at the conclusion of a transaction.
-*/
-static void btreeEndTransaction(Btree *p){
- BtShared *pBt = p->pBt;
- sqlite3 *db = p->db;
- assert( sqlite3BtreeHoldsMutex(p) );
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
- pBt->bDoTruncate = 0;
-#endif
- if( p->inTrans>TRANS_NONE && db->nVdbeRead>1 ){
- /* If there are other active statements that belong to this database
- ** handle, downgrade to a read-only transaction. The other statements
- ** may still be reading from the database. */
- downgradeAllSharedCacheTableLocks(p);
- p->inTrans = TRANS_READ;
- }else{
- /* If the handle had any kind of transaction open, decrement the
- ** transaction count of the shared btree. If the transaction count
- ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused()
- ** call below will unlock the pager. */
- if( p->inTrans!=TRANS_NONE ){
- clearAllSharedCacheTableLocks(p);
- pBt->nTransaction--;
- if( 0==pBt->nTransaction ){
- pBt->inTransaction = TRANS_NONE;
- }
- }
-
- /* Set the current transaction state to TRANS_NONE and unlock the
- ** pager if this call closed the only read or write transaction. */
- p->inTrans = TRANS_NONE;
- unlockBtreeIfUnused(pBt);
- }
-
- btreeIntegrity(p);
-}
-
-/*
-** Commit the transaction currently in progress.
-**
-** This routine implements the second phase of a 2-phase commit. The
-** sqlite3BtreeCommitPhaseOne() routine does the first phase and should
-** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne()
-** routine did all the work of writing information out to disk and flushing the
-** contents so that they are written onto the disk platter. All this
-** routine has to do is delete or truncate or zero the header in the
-** the rollback journal (which causes the transaction to commit) and
-** drop locks.
-**
-** Normally, if an error occurs while the pager layer is attempting to
-** finalize the underlying journal file, this function returns an error and
-** the upper layer will attempt a rollback. However, if the second argument
-** is non-zero then this b-tree transaction is part of a multi-file
-** transaction. In this case, the transaction has already been committed
-** (by deleting a master journal file) and the caller will ignore this
-** functions return code. So, even if an error occurs in the pager layer,
-** reset the b-tree objects internal state to indicate that the write
-** transaction has been closed. This is quite safe, as the pager will have
-** transitioned to the error state.
-**
-** This will release the write lock on the database file. If there
-** are no active cursors, it also releases the read lock.
-*/
-int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
-
- if( p->inTrans==TRANS_NONE ) return SQLITE_OK;
- sqlite3BtreeEnter(p);
- btreeIntegrity(p);
-
- /* If the handle has a write-transaction open, commit the shared-btrees
- ** transaction and set the shared state to TRANS_READ.
- */
- if( p->inTrans==TRANS_WRITE ){
- int rc;
- BtShared *pBt = p->pBt;
- assert( pBt->inTransaction==TRANS_WRITE );
- assert( pBt->nTransaction>0 );
- rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
- if( rc!=SQLITE_OK && bCleanup==0 ){
- sqlite3BtreeLeave(p);
- return rc;
- }
- p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
- pBt->inTransaction = TRANS_READ;
- btreeClearHasContent(pBt);
- }
-
- btreeEndTransaction(p);
- sqlite3BtreeLeave(p);
- return SQLITE_OK;
-}
-
-/*
-** Do both phases of a commit.
-*/
-int sqlite3BtreeCommit(Btree *p){
- int rc;
- sqlite3BtreeEnter(p);
- rc = sqlite3BtreeCommitPhaseOne(p, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeCommitPhaseTwo(p, 0);
- }
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
-** This routine sets the state to CURSOR_FAULT and the error
-** code to errCode for every cursor on any BtShared that pBtree
-** references. Or if the writeOnly flag is set to 1, then only
-** trip write cursors and leave read cursors unchanged.
-**
-** Every cursor is a candidate to be tripped, including cursors
-** that belong to other database connections that happen to be
-** sharing the cache with pBtree.
-**
-** This routine gets called when a rollback occurs. If the writeOnly
-** flag is true, then only write-cursors need be tripped - read-only
-** cursors save their current positions so that they may continue
-** following the rollback. Or, if writeOnly is false, all cursors are
-** tripped. In general, writeOnly is false if the transaction being
-** rolled back modified the database schema. In this case b-tree root
-** pages may be moved or deleted from the database altogether, making
-** it unsafe for read cursors to continue.
-**
-** If the writeOnly flag is true and an error is encountered while
-** saving the current position of a read-only cursor, all cursors,
-** including all read-cursors are tripped.
-**
-** SQLITE_OK is returned if successful, or if an error occurs while
-** saving a cursor position, an SQLite error code.
-*/
-int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
- BtCursor *p;
- int rc = SQLITE_OK;
-
- assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 );
- if( pBtree ){
- sqlite3BtreeEnter(pBtree);
- for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
- if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
- rc = saveCursorPosition(p);
- if( rc!=SQLITE_OK ){
- (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
- break;
- }
- }
- }else{
- sqlite3BtreeClearCursor(p);
- p->eState = CURSOR_FAULT;
- p->skipNext = errCode;
- }
- btreeReleaseAllCursorPages(p);
- }
- sqlite3BtreeLeave(pBtree);
- }
- return rc;
-}
-
-/*
-** Rollback the transaction in progress.
-**
-** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped).
-** Only write cursors are tripped if writeOnly is true but all cursors are
-** tripped if writeOnly is false. Any attempt to use
-** a tripped cursor will result in an error.
-**
-** This will release the write lock on the database file. If there
-** are no active cursors, it also releases the read lock.
-*/
-int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
- int rc;
- BtShared *pBt = p->pBt;
- MemPage *pPage1;
-
- assert( writeOnly==1 || writeOnly==0 );
- assert( tripCode==SQLITE_ABORT_ROLLBACK || tripCode==SQLITE_OK );
- sqlite3BtreeEnter(p);
- if( tripCode==SQLITE_OK ){
- rc = tripCode = saveAllCursors(pBt, 0, 0);
- if( rc ) writeOnly = 0;
- }else{
- rc = SQLITE_OK;
- }
- if( tripCode ){
- int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly);
- assert( rc==SQLITE_OK || (writeOnly==0 && rc2==SQLITE_OK) );
- if( rc2!=SQLITE_OK ) rc = rc2;
- }
- btreeIntegrity(p);
-
- if( p->inTrans==TRANS_WRITE ){
- int rc2;
-
- assert( TRANS_WRITE==pBt->inTransaction );
- rc2 = sqlite3PagerRollback(pBt->pPager);
- if( rc2!=SQLITE_OK ){
- rc = rc2;
- }
-
- /* The rollback may have destroyed the pPage1->aData value. So
- ** call btreeGetPage() on page 1 again to make
- ** sure pPage1->aData is set correctly. */
- if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
- int nPage = get4byte(28+(u8*)pPage1->aData);
- testcase( nPage==0 );
- if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
- testcase( pBt->nPage!=nPage );
- pBt->nPage = nPage;
- releasePageOne(pPage1);
- }
- assert( countValidCursors(pBt, 1)==0 );
- pBt->inTransaction = TRANS_READ;
- btreeClearHasContent(pBt);
- }
-
- btreeEndTransaction(p);
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
-** Start a statement subtransaction. The subtransaction can be rolled
-** back independently of the main transaction. You must start a transaction
-** before starting a subtransaction. The subtransaction is ended automatically
-** if the main transaction commits or rolls back.
-**
-** Statement subtransactions are used around individual SQL statements
-** that are contained within a BEGIN...COMMIT block. If a constraint
-** error occurs within the statement, the effect of that one statement
-** can be rolled back without having to rollback the entire transaction.
-**
-** A statement sub-transaction is implemented as an anonymous savepoint. The
-** value passed as the second parameter is the total number of savepoints,
-** including the new anonymous savepoint, open on the B-Tree. i.e. if there
-** are no active savepoints and no other statement-transactions open,
-** iStatement is 1. This anonymous savepoint can be released or rolled back
-** using the sqlite3BtreeSavepoint() function.
-*/
-int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
- int rc;
- BtShared *pBt = p->pBt;
- sqlite3BtreeEnter(p);
- assert( p->inTrans==TRANS_WRITE );
- assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
- assert( iStatement>0 );
- assert( iStatement>p->db->nSavepoint );
- assert( pBt->inTransaction==TRANS_WRITE );
- /* At the pager level, a statement transaction is a savepoint with
- ** an index greater than all savepoints created explicitly using
- ** SQL statements. It is illegal to open, release or rollback any
- ** such savepoints while the statement transaction savepoint is active.
- */
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
-** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
-** or SAVEPOINT_RELEASE. This function either releases or rolls back the
-** savepoint identified by parameter iSavepoint, depending on the value
-** of op.
-**
-** Normally, iSavepoint is greater than or equal to zero. However, if op is
-** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
-** contents of the entire transaction are rolled back. This is different
-** from a normal transaction rollback, as no locks are released and the
-** transaction remains open.
-*/
-int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
- int rc = SQLITE_OK;
- if( p && p->inTrans==TRANS_WRITE ){
- BtShared *pBt = p->pBt;
- assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
- assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
- sqlite3BtreeEnter(p);
- if( op==SAVEPOINT_ROLLBACK ){
- rc = saveAllCursors(pBt, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
- }
- if( rc==SQLITE_OK ){
- if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
- pBt->nPage = 0;
- }
- rc = newDatabase(pBt);
- pBt->nPage = get4byte(28 + pBt->pPage1->aData);
-
- /* The database size was written into the offset 28 of the header
- ** when the transaction started, so we know that the value at offset
- ** 28 is nonzero. */
- assert( pBt->nPage>0 );
- }
- sqlite3BtreeLeave(p);
- }
- return rc;
-}
-
-/*
-** Create a new cursor for the BTree whose root is on the page
-** iTable. If a read-only cursor is requested, it is assumed that
-** the caller already has at least a read-only transaction open
-** on the database already. If a write-cursor is requested, then
-** the caller is assumed to have an open write transaction.
-**
-** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only
-** be used for reading. If the BTREE_WRCSR bit is set, then the cursor
-** can be used for reading or for writing if other conditions for writing
-** are also met. These are the conditions that must be met in order
-** for writing to be allowed:
-**
-** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR
-**
-** 2: Other database connections that share the same pager cache
-** but which are not in the READ_UNCOMMITTED state may not have
-** cursors open with wrFlag==0 on the same table. Otherwise
-** the changes made by this write cursor would be visible to
-** the read cursors in the other database connection.
-**
-** 3: The database must be writable (not on read-only media)
-**
-** 4: There must be an active transaction.
-**
-** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR
-** is set. If FORDELETE is set, that is a hint to the implementation that
-** this cursor will only be used to seek to and delete entries of an index
-** as part of a larger DELETE statement. The FORDELETE hint is not used by
-** this implementation. But in a hypothetical alternative storage engine
-** in which index entries are automatically deleted when corresponding table
-** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE
-** operations on this cursor can be no-ops and all READ operations can
-** return a null row (2-bytes: 0x01 0x00).
-**
-** No checking is done to make sure that page iTable really is the
-** root page of a b-tree. If it is not, then the cursor acquired
-** will not work correctly.
-**
-** It is assumed that the sqlite3BtreeCursorZero() has been called
-** on pCur to initialize the memory space prior to invoking this routine.
-*/
-static int btreeCursor(
- Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
- int wrFlag, /* 1 to write. 0 read-only */
- struct KeyInfo *pKeyInfo, /* First arg to comparison function */
- BtCursor *pCur /* Space for new cursor */
-){
- BtShared *pBt = p->pBt; /* Shared b-tree handle */
- BtCursor *pX; /* Looping over other all cursors */
-
- assert( sqlite3BtreeHoldsMutex(p) );
- assert( wrFlag==0
- || wrFlag==BTREE_WRCSR
- || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
- );
-
- /* The following assert statements verify that if this is a sharable
- ** b-tree database, the connection is holding the required table locks,
- ** and that no other connection has any open cursor that conflicts with
- ** this lock. */
- assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
- assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
-
- /* Assert that the caller has opened the required transaction. */
- assert( p->inTrans>TRANS_NONE );
- assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
- assert( pBt->pPage1 && pBt->pPage1->aData );
- assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 );
-
- if( wrFlag ){
- allocateTempSpace(pBt);
- if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
- }
- if( iTable==1 && btreePagecount(pBt)==0 ){
- assert( wrFlag==0 );
- iTable = 0;
- }
-
- /* Now that no other errors can occur, finish filling in the BtCursor
- ** variables and link the cursor into the BtShared list. */
- pCur->pgnoRoot = (Pgno)iTable;
- pCur->iPage = -1;
- pCur->pKeyInfo = pKeyInfo;
- pCur->pBtree = p;
- pCur->pBt = pBt;
- pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0;
- pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY;
- /* If there are two or more cursors on the same btree, then all such
- ** cursors *must* have the BTCF_Multiple flag set. */
- for(pX=pBt->pCursor; pX; pX=pX->pNext){
- if( pX->pgnoRoot==(Pgno)iTable ){
- pX->curFlags |= BTCF_Multiple;
- pCur->curFlags |= BTCF_Multiple;
- }
- }
- pCur->pNext = pBt->pCursor;
- pBt->pCursor = pCur;
- pCur->eState = CURSOR_INVALID;
- return SQLITE_OK;
-}
-int sqlite3BtreeCursor(
- Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
- int wrFlag, /* 1 to write. 0 read-only */
- struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
- BtCursor *pCur /* Write new cursor here */
-){
- int rc;
- if( iTable<1 ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- sqlite3BtreeEnter(p);
- rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
- sqlite3BtreeLeave(p);
- }
- return rc;
-}
-
-/*
-** Return the size of a BtCursor object in bytes.
-**
-** This interfaces is needed so that users of cursors can preallocate
-** sufficient storage to hold a cursor. The BtCursor object is opaque
-** to users so they cannot do the sizeof() themselves - they must call
-** this routine.
-*/
-int sqlite3BtreeCursorSize(void){
- return ROUND8(sizeof(BtCursor));
-}
-
-/*
-** Initialize memory that will be converted into a BtCursor object.
-**
-** The simple approach here would be to memset() the entire object
-** to zero. But it turns out that the apPage[] and aiIdx[] arrays
-** do not need to be zeroed and they are large, so we can save a lot
-** of run-time by skipping the initialization of those elements.
-*/
-void sqlite3BtreeCursorZero(BtCursor *p){
- memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT));
-}
-
-/*
-** Close a cursor. The read lock on the database file is released
-** when the last cursor is closed.
-*/
-int sqlite3BtreeCloseCursor(BtCursor *pCur){
- Btree *pBtree = pCur->pBtree;
- if( pBtree ){
- BtShared *pBt = pCur->pBt;
- sqlite3BtreeEnter(pBtree);
- assert( pBt->pCursor!=0 );
- if( pBt->pCursor==pCur ){
- pBt->pCursor = pCur->pNext;
- }else{
- BtCursor *pPrev = pBt->pCursor;
- do{
- if( pPrev->pNext==pCur ){
- pPrev->pNext = pCur->pNext;
- break;
- }
- pPrev = pPrev->pNext;
- }while( ALWAYS(pPrev) );
- }
- btreeReleaseAllCursorPages(pCur);
- unlockBtreeIfUnused(pBt);
- sqlite3_free(pCur->aOverflow);
- sqlite3_free(pCur->pKey);
- sqlite3BtreeLeave(pBtree);
- }
- return SQLITE_OK;
-}
-
-/*
-** Make sure the BtCursor* given in the argument has a valid
-** BtCursor.info structure. If it is not already valid, call
-** btreeParseCell() to fill it in.
-**
-** BtCursor.info is a cache of the information in the current cell.
-** Using this cache reduces the number of calls to btreeParseCell().
-*/
-#ifndef NDEBUG
- static int cellInfoEqual(CellInfo *a, CellInfo *b){
- if( a->nKey!=b->nKey ) return 0;
- if( a->pPayload!=b->pPayload ) return 0;
- if( a->nPayload!=b->nPayload ) return 0;
- if( a->nLocal!=b->nLocal ) return 0;
- if( a->nSize!=b->nSize ) return 0;
- return 1;
- }
- static void assertCellInfo(BtCursor *pCur){
- CellInfo info;
- memset(&info, 0, sizeof(info));
- btreeParseCell(pCur->pPage, pCur->ix, &info);
- assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) );
- }
-#else
- #define assertCellInfo(x)
-#endif
-static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){
- if( pCur->info.nSize==0 ){
- pCur->curFlags |= BTCF_ValidNKey;
- btreeParseCell(pCur->pPage,pCur->ix,&pCur->info);
- }else{
- assertCellInfo(pCur);
- }
-}
-
-#ifndef NDEBUG /* The next routine used only within assert() statements */
-/*
-** Return true if the given BtCursor is valid. A valid cursor is one
-** that is currently pointing to a row in a (non-empty) table.
-** This is a verification routine is used only within assert() statements.
-*/
-int sqlite3BtreeCursorIsValid(BtCursor *pCur){
- return pCur && pCur->eState==CURSOR_VALID;
-}
-#endif /* NDEBUG */
-int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){
- assert( pCur!=0 );
- return pCur->eState==CURSOR_VALID;
-}
-
-/*
-** Return the value of the integer key or "rowid" for a table btree.
-** This routine is only valid for a cursor that is pointing into a
-** ordinary table btree. If the cursor points to an index btree or
-** is invalid, the result of this routine is undefined.
-*/
-i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
- assert( cursorHoldsMutex(pCur) );
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->curIntKey );
- getCellInfo(pCur);
- return pCur->info.nKey;
-}
-
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
-/*
-** Return the offset into the database file for the start of the
-** payload to which the cursor is pointing.
-*/
-i64 sqlite3BtreeOffset(BtCursor *pCur){
- assert( cursorHoldsMutex(pCur) );
- assert( pCur->eState==CURSOR_VALID );
- getCellInfo(pCur);
- return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) +
- (i64)(pCur->info.pPayload - pCur->pPage->aData);
-}
-#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
-
-/*
-** Return the number of bytes of payload for the entry that pCur is
-** currently pointing to. For table btrees, this will be the amount
-** of data. For index btrees, this will be the size of the key.
-**
-** The caller must guarantee that the cursor is pointing to a non-NULL
-** valid entry. In other words, the calling procedure must guarantee
-** that the cursor has Cursor.eState==CURSOR_VALID.
-*/
-u32 sqlite3BtreePayloadSize(BtCursor *pCur){
- assert( cursorHoldsMutex(pCur) );
- assert( pCur->eState==CURSOR_VALID );
- getCellInfo(pCur);
- return pCur->info.nPayload;
-}
-
-/*
-** Given the page number of an overflow page in the database (parameter
-** ovfl), this function finds the page number of the next page in the
-** linked list of overflow pages. If possible, it uses the auto-vacuum
-** pointer-map data instead of reading the content of page ovfl to do so.
-**
-** If an error occurs an SQLite error code is returned. Otherwise:
-**
-** The page number of the next overflow page in the linked list is
-** written to *pPgnoNext. If page ovfl is the last page in its linked
-** list, *pPgnoNext is set to zero.
-**
-** If ppPage is not NULL, and a reference to the MemPage object corresponding
-** to page number pOvfl was obtained, then *ppPage is set to point to that
-** reference. It is the responsibility of the caller to call releasePage()
-** on *ppPage to free the reference. In no reference was obtained (because
-** the pointer-map was used to obtain the value for *pPgnoNext), then
-** *ppPage is set to zero.
-*/
-static int getOverflowPage(
- BtShared *pBt, /* The database file */
- Pgno ovfl, /* Current overflow page number */
- MemPage **ppPage, /* OUT: MemPage handle (may be NULL) */
- Pgno *pPgnoNext /* OUT: Next overflow page number */
-){
- Pgno next = 0;
- MemPage *pPage = 0;
- int rc = SQLITE_OK;
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert(pPgnoNext);
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
- /* Try to find the next page in the overflow list using the
- ** autovacuum pointer-map pages. Guess that the next page in
- ** the overflow list is page number (ovfl+1). If that guess turns
- ** out to be wrong, fall back to loading the data of page
- ** number ovfl to determine the next page number.
- */
- if( pBt->autoVacuum ){
- Pgno pgno;
- Pgno iGuess = ovfl+1;
- u8 eType;
-
- while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){
- iGuess++;
- }
-
- if( iGuess<=btreePagecount(pBt) ){
- rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
- if( rc==SQLITE_OK && eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){
- next = iGuess;
- rc = SQLITE_DONE;
- }
- }
- }
-#endif
-
- assert( next==0 || rc==SQLITE_DONE );
- if( rc==SQLITE_OK ){
- rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? PAGER_GET_READONLY : 0);
- assert( rc==SQLITE_OK || pPage==0 );
- if( rc==SQLITE_OK ){
- next = get4byte(pPage->aData);
- }
- }
-
- *pPgnoNext = next;
- if( ppPage ){
- *ppPage = pPage;
- }else{
- releasePage(pPage);
- }
- return (rc==SQLITE_DONE ? SQLITE_OK : rc);
-}
-
-/*
-** Copy data from a buffer to a page, or from a page to a buffer.
-**
-** pPayload is a pointer to data stored on database page pDbPage.
-** If argument eOp is false, then nByte bytes of data are copied
-** from pPayload to the buffer pointed at by pBuf. If eOp is true,
-** then sqlite3PagerWrite() is called on pDbPage and nByte bytes
-** of data are copied from the buffer pBuf to pPayload.
-**
-** SQLITE_OK is returned on success, otherwise an error code.
-*/
-static int copyPayload(
- void *pPayload, /* Pointer to page data */
- void *pBuf, /* Pointer to buffer */
- int nByte, /* Number of bytes to copy */
- int eOp, /* 0 -> copy from page, 1 -> copy to page */
- DbPage *pDbPage /* Page containing pPayload */
-){
- if( eOp ){
- /* Copy data from buffer to page (a write operation) */
- int rc = sqlite3PagerWrite(pDbPage);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- memcpy(pPayload, pBuf, nByte);
- }else{
- /* Copy data from page to buffer (a read operation) */
- memcpy(pBuf, pPayload, nByte);
- }
- return SQLITE_OK;
-}
-
-/*
-** This function is used to read or overwrite payload information
-** for the entry that the pCur cursor is pointing to. The eOp
-** argument is interpreted as follows:
-**
-** 0: The operation is a read. Populate the overflow cache.
-** 1: The operation is a write. Populate the overflow cache.
-**
-** A total of "amt" bytes are read or written beginning at "offset".
-** Data is read to or from the buffer pBuf.
-**
-** The content being read or written might appear on the main page
-** or be scattered out on multiple overflow pages.
-**
-** If the current cursor entry uses one or more overflow pages
-** this function may allocate space for and lazily populate
-** the overflow page-list cache array (BtCursor.aOverflow).
-** Subsequent calls use this cache to make seeking to the supplied offset
-** more efficient.
-**
-** Once an overflow page-list cache has been allocated, it must be
-** invalidated if some other cursor writes to the same table, or if
-** the cursor is moved to a different row. Additionally, in auto-vacuum
-** mode, the following events may invalidate an overflow page-list cache.
-**
-** * An incremental vacuum,
-** * A commit in auto_vacuum="full" mode,
-** * Creating a table (may require moving an overflow page).
-*/
-static int accessPayload(
- BtCursor *pCur, /* Cursor pointing to entry to read from */
- u32 offset, /* Begin reading this far into payload */
- u32 amt, /* Read this many bytes */
- unsigned char *pBuf, /* Write the bytes into this buffer */
- int eOp /* zero to read. non-zero to write. */
-){
- unsigned char *aPayload;
- int rc = SQLITE_OK;
- int iIdx = 0;
- MemPage *pPage = pCur->pPage; /* Btree page of current entry */
- BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- unsigned char * const pBufStart = pBuf; /* Start of original out buffer */
-#endif
-
- assert( pPage );
- assert( eOp==0 || eOp==1 );
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->ix<pPage->nCell );
- assert( cursorHoldsMutex(pCur) );
-
- getCellInfo(pCur);
- aPayload = pCur->info.pPayload;
- assert( offset+amt <= pCur->info.nPayload );
-
- assert( aPayload > pPage->aData );
- if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
- /* Trying to read or write past the end of the data is an error. The
- ** conditional above is really:
- ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
- ** but is recast into its current form to avoid integer overflow problems
- */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
-
- /* Check if data must be read/written to/from the btree page itself. */
- if( offset<pCur->info.nLocal ){
- int a = amt;
- if( a+offset>pCur->info.nLocal ){
- a = pCur->info.nLocal - offset;
- }
- rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
- offset = 0;
- pBuf += a;
- amt -= a;
- }else{
- offset -= pCur->info.nLocal;
- }
-
-
- if( rc==SQLITE_OK && amt>0 ){
- const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
- Pgno nextPage;
-
- nextPage = get4byte(&aPayload[pCur->info.nLocal]);
-
- /* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
- **
- ** The aOverflow[] array is sized at one entry for each overflow page
- ** in the overflow chain. The page number of the first overflow page is
- ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
- ** means "not yet known" (the cache is lazily populated).
- */
- if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
- int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
- if( pCur->aOverflow==0
- || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
- ){
- Pgno *aNew = (Pgno*)sqlite3Realloc(
- pCur->aOverflow, nOvfl*2*sizeof(Pgno)
- );
- if( aNew==0 ){
- return SQLITE_NOMEM_BKPT;
- }else{
- pCur->aOverflow = aNew;
- }
- }
- memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
- pCur->curFlags |= BTCF_ValidOvfl;
- }else{
- /* If the overflow page-list cache has been allocated and the
- ** entry for the first required overflow page is valid, skip
- ** directly to it.
- */
- if( pCur->aOverflow[offset/ovflSize] ){
- iIdx = (offset/ovflSize);
- nextPage = pCur->aOverflow[iIdx];
- offset = (offset%ovflSize);
- }
- }
-
- assert( rc==SQLITE_OK && amt>0 );
- while( nextPage ){
- /* If required, populate the overflow page-list cache. */
- assert( pCur->aOverflow[iIdx]==0
- || pCur->aOverflow[iIdx]==nextPage
- || CORRUPT_DB );
- pCur->aOverflow[iIdx] = nextPage;
-
- if( offset>=ovflSize ){
- /* The only reason to read this page is to obtain the page
- ** number for the next page in the overflow chain. The page
- ** data is not required. So first try to lookup the overflow
- ** page-list cache, if any, then fall back to the getOverflowPage()
- ** function.
- */
- assert( pCur->curFlags & BTCF_ValidOvfl );
- assert( pCur->pBtree->db==pBt->db );
- if( pCur->aOverflow[iIdx+1] ){
- nextPage = pCur->aOverflow[iIdx+1];
- }else{
- rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
- }
- offset -= ovflSize;
- }else{
- /* Need to read this page properly. It contains some of the
- ** range of data that is being read (eOp==0) or written (eOp!=0).
- */
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- sqlite3_file *fd; /* File from which to do direct overflow read */
-#endif
- int a = amt;
- if( a + offset > ovflSize ){
- a = ovflSize - offset;
- }
-
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- /* If all the following are true:
- **
- ** 1) this is a read operation, and
- ** 2) data is required from the start of this overflow page, and
- ** 3) there is no open write-transaction, and
- ** 4) the database is file-backed, and
- ** 5) the page is not in the WAL file
- ** 6) at least 4 bytes have already been read into the output buffer
- **
- ** then data can be read directly from the database file into the
- ** output buffer, bypassing the page-cache altogether. This speeds
- ** up loading large records that span many overflow pages.
- */
- if( eOp==0 /* (1) */
- && offset==0 /* (2) */
- && pBt->inTransaction==TRANS_READ /* (3) */
- && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
- && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
- && &pBuf[-4]>=pBufStart /* (6) */
- ){
- u8 aSave[4];
- u8 *aWrite = &pBuf[-4];
- assert( aWrite>=pBufStart ); /* due to (6) */
- memcpy(aSave, aWrite, 4);
- rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
- nextPage = get4byte(aWrite);
- memcpy(aWrite, aSave, 4);
- }else
-#endif
-
- {
- DbPage *pDbPage;
- rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
- (eOp==0 ? PAGER_GET_READONLY : 0)
- );
- if( rc==SQLITE_OK ){
- aPayload = sqlite3PagerGetData(pDbPage);
- nextPage = get4byte(aPayload);
- rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
- sqlite3PagerUnref(pDbPage);
- offset = 0;
- }
- }
- amt -= a;
- if( amt==0 ) return rc;
- pBuf += a;
- }
- if( rc ) break;
- iIdx++;
- }
- }
-
- if( rc==SQLITE_OK && amt>0 ){
- /* Overflow chain ends prematurely */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- return rc;
-}
-
-/*
-** Read part of the payload for the row at which that cursor pCur is currently
-** pointing. "amt" bytes will be transferred into pBuf[]. The transfer
-** begins at "offset".
-**
-** pCur can be pointing to either a table or an index b-tree.
-** If pointing to a table btree, then the content section is read. If
-** pCur is pointing to an index b-tree then the key section is read.
-**
-** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing
-** to a valid row in the table. For sqlite3BtreePayloadChecked(), the
-** cursor might be invalid or might need to be restored before being read.
-**
-** Return SQLITE_OK on success or an error code if anything goes
-** wrong. An error is returned if "offset+amt" is larger than
-** the available payload.
-*/
-int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
- assert( cursorHoldsMutex(pCur) );
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>=0 && pCur->pPage );
- assert( pCur->ix<pCur->pPage->nCell );
- return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
-}
-
-/*
-** This variant of sqlite3BtreePayload() works even if the cursor has not
-** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read()
-** interface.
-*/
-#ifndef SQLITE_OMIT_INCRBLOB
-static SQLITE_NOINLINE int accessPayloadChecked(
- BtCursor *pCur,
- u32 offset,
- u32 amt,
- void *pBuf
-){
- int rc;
- if ( pCur->eState==CURSOR_INVALID ){
- return SQLITE_ABORT;
- }
- assert( cursorOwnsBtShared(pCur) );
- rc = btreeRestoreCursorPosition(pCur);
- return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
-}
-int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
- if( pCur->eState==CURSOR_VALID ){
- assert( cursorOwnsBtShared(pCur) );
- return accessPayload(pCur, offset, amt, pBuf, 0);
- }else{
- return accessPayloadChecked(pCur, offset, amt, pBuf);
- }
-}
-#endif /* SQLITE_OMIT_INCRBLOB */
-
-/*
-** Return a pointer to payload information from the entry that the
-** pCur cursor is pointing to. The pointer is to the beginning of
-** the key if index btrees (pPage->intKey==0) and is the data for
-** table btrees (pPage->intKey==1). The number of bytes of available
-** key/data is written into *pAmt. If *pAmt==0, then the value
-** returned will not be a valid pointer.
-**
-** This routine is an optimization. It is common for the entire key
-** and data to fit on the local page and for there to be no overflow
-** pages. When that is so, this routine can be used to access the
-** key and data without making a copy. If the key and/or data spills
-** onto overflow pages, then accessPayload() must be used to reassemble
-** the key/data and copy it into a preallocated buffer.
-**
-** The pointer returned by this routine looks directly into the cached
-** page of the database. The data might change or move the next time
-** any btree routine is called.
-*/
-static const void *fetchPayload(
- BtCursor *pCur, /* Cursor pointing to entry to read from */
- u32 *pAmt /* Write the number of available bytes here */
-){
- int amt;
- assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
- assert( pCur->eState==CURSOR_VALID );
- assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
- assert( cursorOwnsBtShared(pCur) );
- assert( pCur->ix<pCur->pPage->nCell );
- assert( pCur->info.nSize>0 );
- assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
- assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB);
- amt = pCur->info.nLocal;
- if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
- /* There is too little space on the page for the expected amount
- ** of local content. Database must be corrupt. */
- assert( CORRUPT_DB );
- amt = MAX(0, (int)(pCur->pPage->aDataEnd - pCur->info.pPayload));
- }
- *pAmt = (u32)amt;
- return (void*)pCur->info.pPayload;
-}
-
-
-/*
-** For the entry that cursor pCur is point to, return as
-** many bytes of the key or data as are available on the local
-** b-tree page. Write the number of available bytes into *pAmt.
-**
-** The pointer returned is ephemeral. The key/data may move
-** or be destroyed on the next call to any Btree routine,
-** including calls from other threads against the same cache.
-** Hence, a mutex on the BtShared should be held prior to calling
-** this routine.
-**
-** These routines is used to get quick access to key and data
-** in the common case where no overflow pages are used.
-*/
-const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
- return fetchPayload(pCur, pAmt);
-}
-
-
-/*
-** Move the cursor down to a new child page. The newPgno argument is the
-** page number of the child page to move to.
-**
-** This function returns SQLITE_CORRUPT if the page-header flags field of
-** the new child page does not match the flags field of the parent (i.e.
-** if an intkey page appears to be the parent of a non-intkey page, or
-** vice-versa).
-*/
-static int moveToChild(BtCursor *pCur, u32 newPgno){
- BtShared *pBt = pCur->pBt;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
- assert( pCur->iPage>=0 );
- if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
- return SQLITE_CORRUPT_BKPT;
- }
- pCur->info.nSize = 0;
- pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
- pCur->aiIdx[pCur->iPage] = pCur->ix;
- pCur->apPage[pCur->iPage] = pCur->pPage;
- pCur->ix = 0;
- pCur->iPage++;
- return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags);
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** Page pParent is an internal (non-leaf) tree page. This function
-** asserts that page number iChild is the left-child if the iIdx'th
-** cell in page pParent. Or, if iIdx is equal to the total number of
-** cells in pParent, that page number iChild is the right-child of
-** the page.
-*/
-static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
- if( CORRUPT_DB ) return; /* The conditions tested below might not be true
- ** in a corrupt database */
- assert( iIdx<=pParent->nCell );
- if( iIdx==pParent->nCell ){
- assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild );
- }else{
- assert( get4byte(findCell(pParent, iIdx))==iChild );
- }
-}
-#else
-# define assertParentIndex(x,y,z)
-#endif
-
-/*
-** Move the cursor up to the parent page.
-**
-** pCur->idx is set to the cell index that contains the pointer
-** to the page we are coming from. If we are coming from the
-** right-most child page then pCur->idx is set to one more than
-** the largest cell index.
-*/
-static void moveToParent(BtCursor *pCur){
- MemPage *pLeaf;
- assert( cursorOwnsBtShared(pCur) );
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>0 );
- assert( pCur->pPage );
- assertParentIndex(
- pCur->apPage[pCur->iPage-1],
- pCur->aiIdx[pCur->iPage-1],
- pCur->pPage->pgno
- );
- testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
- pCur->info.nSize = 0;
- pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
- pCur->ix = pCur->aiIdx[pCur->iPage-1];
- pLeaf = pCur->pPage;
- pCur->pPage = pCur->apPage[--pCur->iPage];
- releasePageNotNull(pLeaf);
-}
-
-/*
-** Move the cursor to point to the root page of its b-tree structure.
-**
-** If the table has a virtual root page, then the cursor is moved to point
-** to the virtual root page instead of the actual root page. A table has a
-** virtual root page when the actual root page contains no cells and a
-** single child page. This can only happen with the table rooted at page 1.
-**
-** If the b-tree structure is empty, the cursor state is set to
-** CURSOR_INVALID and this routine returns SQLITE_EMPTY. Otherwise,
-** the cursor is set to point to the first cell located on the root
-** (or virtual root) page and the cursor state is set to CURSOR_VALID.
-**
-** If this function returns successfully, it may be assumed that the
-** page-header flags indicate that the [virtual] root-page is the expected
-** kind of b-tree page (i.e. if when opening the cursor the caller did not
-** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D,
-** indicating a table b-tree, or if the caller did specify a KeyInfo
-** structure the flags byte is set to 0x02 or 0x0A, indicating an index
-** b-tree).
-*/
-static int moveToRoot(BtCursor *pCur){
- MemPage *pRoot;
- int rc = SQLITE_OK;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
- assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
- assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
- assert( pCur->eState < CURSOR_REQUIRESEEK || pCur->iPage<0 );
- assert( pCur->pgnoRoot>0 || pCur->iPage<0 );
-
- if( pCur->iPage>=0 ){
- if( pCur->iPage ){
- releasePageNotNull(pCur->pPage);
- while( --pCur->iPage ){
- releasePageNotNull(pCur->apPage[pCur->iPage]);
- }
- pCur->pPage = pCur->apPage[0];
- goto skip_init;
- }
- }else if( pCur->pgnoRoot==0 ){
- pCur->eState = CURSOR_INVALID;
- return SQLITE_EMPTY;
- }else{
- assert( pCur->iPage==(-1) );
- if( pCur->eState>=CURSOR_REQUIRESEEK ){
- if( pCur->eState==CURSOR_FAULT ){
- assert( pCur->skipNext!=SQLITE_OK );
- return pCur->skipNext;
- }
- sqlite3BtreeClearCursor(pCur);
- }
- rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage,
- 0, pCur->curPagerFlags);
- if( rc!=SQLITE_OK ){
- pCur->eState = CURSOR_INVALID;
- return rc;
- }
- pCur->iPage = 0;
- pCur->curIntKey = pCur->pPage->intKey;
- }
- pRoot = pCur->pPage;
- assert( pRoot->pgno==pCur->pgnoRoot );
-
- /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
- ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
- ** NULL, the caller expects a table b-tree. If this is not the case,
- ** return an SQLITE_CORRUPT error.
- **
- ** Earlier versions of SQLite assumed that this test could not fail
- ** if the root page was already loaded when this function was called (i.e.
- ** if pCur->iPage>=0). But this is not so if the database is corrupted
- ** in such a way that page pRoot is linked into a second b-tree table
- ** (or the freelist). */
- assert( pRoot->intKey==1 || pRoot->intKey==0 );
- if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
- return SQLITE_CORRUPT_PAGE(pCur->pPage);
- }
-
-skip_init:
- pCur->ix = 0;
- pCur->info.nSize = 0;
- pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
-
- pRoot = pCur->pPage;
- if( pRoot->nCell>0 ){
- pCur->eState = CURSOR_VALID;
- }else if( !pRoot->leaf ){
- Pgno subpage;
- if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
- subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
- pCur->eState = CURSOR_VALID;
- rc = moveToChild(pCur, subpage);
- }else{
- pCur->eState = CURSOR_INVALID;
- rc = SQLITE_EMPTY;
- }
- return rc;
-}
-
-/*
-** Move the cursor down to the left-most leaf entry beneath the
-** entry to which it is currently pointing.
-**
-** The left-most leaf is the one with the smallest key - the first
-** in ascending order.
-*/
-static int moveToLeftmost(BtCursor *pCur){
- Pgno pgno;
- int rc = SQLITE_OK;
- MemPage *pPage;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( pCur->eState==CURSOR_VALID );
- while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
- assert( pCur->ix<pPage->nCell );
- pgno = get4byte(findCell(pPage, pCur->ix));
- rc = moveToChild(pCur, pgno);
- }
- return rc;
-}
-
-/*
-** Move the cursor down to the right-most leaf entry beneath the
-** page to which it is currently pointing. Notice the difference
-** between moveToLeftmost() and moveToRightmost(). moveToLeftmost()
-** finds the left-most entry beneath the *entry* whereas moveToRightmost()
-** finds the right-most entry beneath the *page*.
-**
-** The right-most entry is the one with the largest key - the last
-** key in ascending order.
-*/
-static int moveToRightmost(BtCursor *pCur){
- Pgno pgno;
- int rc = SQLITE_OK;
- MemPage *pPage = 0;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( pCur->eState==CURSOR_VALID );
- while( !(pPage = pCur->pPage)->leaf ){
- pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- pCur->ix = pPage->nCell;
- rc = moveToChild(pCur, pgno);
- if( rc ) return rc;
- }
- pCur->ix = pPage->nCell-1;
- assert( pCur->info.nSize==0 );
- assert( (pCur->curFlags & BTCF_ValidNKey)==0 );
- return SQLITE_OK;
-}
-
-/* Move the cursor to the first entry in the table. Return SQLITE_OK
-** on success. Set *pRes to 0 if the cursor actually points to something
-** or set *pRes to 1 if the table is empty.
-*/
-int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
- int rc;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
- rc = moveToRoot(pCur);
- if( rc==SQLITE_OK ){
- assert( pCur->pPage->nCell>0 );
- *pRes = 0;
- rc = moveToLeftmost(pCur);
- }else if( rc==SQLITE_EMPTY ){
- assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
- *pRes = 1;
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-/* Move the cursor to the last entry in the table. Return SQLITE_OK
-** on success. Set *pRes to 0 if the cursor actually points to something
-** or set *pRes to 1 if the table is empty.
-*/
-int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
- int rc;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
-
- /* If the cursor already points to the last entry, this is a no-op. */
- if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
-#ifdef SQLITE_DEBUG
- /* This block serves to assert() that the cursor really does point
- ** to the last entry in the b-tree. */
- int ii;
- for(ii=0; ii<pCur->iPage; ii++){
- assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
- }
- assert( pCur->ix==pCur->pPage->nCell-1 );
- assert( pCur->pPage->leaf );
-#endif
- return SQLITE_OK;
- }
-
- rc = moveToRoot(pCur);
- if( rc==SQLITE_OK ){
- assert( pCur->eState==CURSOR_VALID );
- *pRes = 0;
- rc = moveToRightmost(pCur);
- if( rc==SQLITE_OK ){
- pCur->curFlags |= BTCF_AtLast;
- }else{
- pCur->curFlags &= ~BTCF_AtLast;
- }
- }else if( rc==SQLITE_EMPTY ){
- assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
- *pRes = 1;
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-/* Move the cursor so that it points to an entry near the key
-** specified by pIdxKey or intKey. Return a success code.
-**
-** For INTKEY tables, the intKey parameter is used. pIdxKey
-** must be NULL. For index tables, pIdxKey is used and intKey
-** is ignored.
-**
-** If an exact match is not found, then the cursor is always
-** left pointing at a leaf page which would hold the entry if it
-** were present. The cursor might point to an entry that comes
-** before or after the key.
-**
-** An integer is written into *pRes which is the result of
-** comparing the key with the entry to which the cursor is
-** pointing. The meaning of the integer written into
-** *pRes is as follows:
-**
-** *pRes<0 The cursor is left pointing at an entry that
-** is smaller than intKey/pIdxKey or if the table is empty
-** and the cursor is therefore left point to nothing.
-**
-** *pRes==0 The cursor is left pointing at an entry that
-** exactly matches intKey/pIdxKey.
-**
-** *pRes>0 The cursor is left pointing at an entry that
-** is larger than intKey/pIdxKey.
-**
-** For index tables, the pIdxKey->eqSeen field is set to 1 if there
-** exists an entry in the table that exactly matches pIdxKey.
-*/
-int sqlite3BtreeMovetoUnpacked(
- BtCursor *pCur, /* The cursor to be moved */
- UnpackedRecord *pIdxKey, /* Unpacked index key */
- i64 intKey, /* The table key */
- int biasRight, /* If true, bias the search to the high end */
- int *pRes /* Write search results here */
-){
- int rc;
- RecordCompare xRecordCompare;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
- assert( pRes );
- assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
- assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) );
-
- /* If the cursor is already positioned at the point we are trying
- ** to move to, then just return without doing any work */
- if( pIdxKey==0
- && pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
- ){
- if( pCur->info.nKey==intKey ){
- *pRes = 0;
- return SQLITE_OK;
- }
- if( pCur->info.nKey<intKey ){
- if( (pCur->curFlags & BTCF_AtLast)!=0 ){
- *pRes = -1;
- return SQLITE_OK;
- }
- /* If the requested key is one more than the previous key, then
- ** try to get there using sqlite3BtreeNext() rather than a full
- ** binary search. This is an optimization only. The correct answer
- ** is still obtained without this case, only a little more slowely */
- if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
- *pRes = 0;
- rc = sqlite3BtreeNext(pCur, 0);
- if( rc==SQLITE_OK ){
- getCellInfo(pCur);
- if( pCur->info.nKey==intKey ){
- return SQLITE_OK;
- }
- }else if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- }else{
- return rc;
- }
- }
- }
- }
-
- if( pIdxKey ){
- xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
- pIdxKey->errCode = 0;
- assert( pIdxKey->default_rc==1
- || pIdxKey->default_rc==0
- || pIdxKey->default_rc==-1
- );
- }else{
- xRecordCompare = 0; /* All keys are integers */
- }
-
- rc = moveToRoot(pCur);
- if( rc ){
- if( rc==SQLITE_EMPTY ){
- assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
- *pRes = -1;
- return SQLITE_OK;
- }
- return rc;
- }
- assert( pCur->pPage );
- assert( pCur->pPage->isInit );
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->pPage->nCell > 0 );
- assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
- assert( pCur->curIntKey || pIdxKey );
- for(;;){
- int lwr, upr, idx, c;
- Pgno chldPg;
- MemPage *pPage = pCur->pPage;
- u8 *pCell; /* Pointer to current cell in pPage */
-
- /* pPage->nCell must be greater than zero. If this is the root-page
- ** the cursor would have been INVALID above and this for(;;) loop
- ** not run. If this is not the root-page, then the moveToChild() routine
- ** would have already detected db corruption. Similarly, pPage must
- ** be the right kind (index or table) of b-tree page. Otherwise
- ** a moveToChild() or moveToRoot() call would have detected corruption. */
- assert( pPage->nCell>0 );
- assert( pPage->intKey==(pIdxKey==0) );
- lwr = 0;
- upr = pPage->nCell-1;
- assert( biasRight==0 || biasRight==1 );
- idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
- pCur->ix = (u16)idx;
- if( xRecordCompare==0 ){
- for(;;){
- i64 nCellKey;
- pCell = findCellPastPtr(pPage, idx);
- if( pPage->intKeyLeaf ){
- while( 0x80 <= *(pCell++) ){
- if( pCell>=pPage->aDataEnd ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- }
- }
- getVarint(pCell, (u64*)&nCellKey);
- if( nCellKey<intKey ){
- lwr = idx+1;
- if( lwr>upr ){ c = -1; break; }
- }else if( nCellKey>intKey ){
- upr = idx-1;
- if( lwr>upr ){ c = +1; break; }
- }else{
- assert( nCellKey==intKey );
- pCur->ix = (u16)idx;
- if( !pPage->leaf ){
- lwr = idx;
- goto moveto_next_layer;
- }else{
- pCur->curFlags |= BTCF_ValidNKey;
- pCur->info.nKey = nCellKey;
- pCur->info.nSize = 0;
- *pRes = 0;
- return SQLITE_OK;
- }
- }
- assert( lwr+upr>=0 );
- idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
- }
- }else{
- for(;;){
- int nCell; /* Size of the pCell cell in bytes */
- pCell = findCellPastPtr(pPage, idx);
-
- /* The maximum supported page-size is 65536 bytes. This means that
- ** the maximum number of record bytes stored on an index B-Tree
- ** page is less than 16384 bytes and may be stored as a 2-byte
- ** varint. This information is used to attempt to avoid parsing
- ** the entire cell by checking for the cases where the record is
- ** stored entirely within the b-tree page by inspecting the first
- ** 2 bytes of the cell.
- */
- nCell = pCell[0];
- if( nCell<=pPage->max1bytePayload ){
- /* This branch runs if the record-size field of the cell is a
- ** single byte varint and the record fits entirely on the main
- ** b-tree page. */
- testcase( pCell+nCell+1==pPage->aDataEnd );
- c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
- }else if( !(pCell[1] & 0x80)
- && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
- ){
- /* The record-size field is a 2 byte varint and the record
- ** fits entirely on the main b-tree page. */
- testcase( pCell+nCell+2==pPage->aDataEnd );
- c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
- }else{
- /* The record flows over onto one or more overflow pages. In
- ** this case the whole cell needs to be parsed, a buffer allocated
- ** and accessPayload() used to retrieve the record into the
- ** buffer before VdbeRecordCompare() can be called.
- **
- ** If the record is corrupt, the xRecordCompare routine may read
- ** up to two varints past the end of the buffer. An extra 18
- ** bytes of padding is allocated at the end of the buffer in
- ** case this happens. */
- void *pCellKey;
- u8 * const pCellBody = pCell - pPage->childPtrSize;
- pPage->xParseCell(pPage, pCellBody, &pCur->info);
- nCell = (int)pCur->info.nKey;
- testcase( nCell<0 ); /* True if key size is 2^32 or more */
- testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
- testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
- testcase( nCell==2 ); /* Minimum legal index key size */
- if( nCell<2 ){
- rc = SQLITE_CORRUPT_PAGE(pPage);
- goto moveto_finish;
- }
- pCellKey = sqlite3Malloc( nCell+18 );
- if( pCellKey==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto moveto_finish;
- }
- pCur->ix = (u16)idx;
- rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
- pCur->curFlags &= ~BTCF_ValidOvfl;
- if( rc ){
- sqlite3_free(pCellKey);
- goto moveto_finish;
- }
- c = xRecordCompare(nCell, pCellKey, pIdxKey);
- sqlite3_free(pCellKey);
- }
- assert(
- (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
- && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
- );
- if( c<0 ){
- lwr = idx+1;
- }else if( c>0 ){
- upr = idx-1;
- }else{
- assert( c==0 );
- *pRes = 0;
- rc = SQLITE_OK;
- pCur->ix = (u16)idx;
- if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
- goto moveto_finish;
- }
- if( lwr>upr ) break;
- assert( lwr+upr>=0 );
- idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
- }
- }
- assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
- assert( pPage->isInit );
- if( pPage->leaf ){
- assert( pCur->ix<pCur->pPage->nCell );
- pCur->ix = (u16)idx;
- *pRes = c;
- rc = SQLITE_OK;
- goto moveto_finish;
- }
-moveto_next_layer:
- if( lwr>=pPage->nCell ){
- chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- }else{
- chldPg = get4byte(findCell(pPage, lwr));
- }
- pCur->ix = (u16)lwr;
- rc = moveToChild(pCur, chldPg);
- if( rc ) break;
- }
-moveto_finish:
- pCur->info.nSize = 0;
- assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
- return rc;
-}
-
-
-/*
-** Return TRUE if the cursor is not pointing at an entry of the table.
-**
-** TRUE will be returned after a call to sqlite3BtreeNext() moves
-** past the last entry in the table or sqlite3BtreePrev() moves past
-** the first entry. TRUE is also returned if the table is empty.
-*/
-int sqlite3BtreeEof(BtCursor *pCur){
- /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries
- ** have been deleted? This API will need to change to return an error code
- ** as well as the boolean result value.
- */
- return (CURSOR_VALID!=pCur->eState);
-}
-
-/*
-** Return an estimate for the number of rows in the table that pCur is
-** pointing to. Return a negative number if no estimate is currently
-** available.
-*/
-i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
- i64 n;
- u8 i;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
-
- /* Currently this interface is only called by the OP_IfSmaller
- ** opcode, and it that case the cursor will always be valid and
- ** will always point to a leaf node. */
- if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1;
- if( NEVER(pCur->pPage->leaf==0) ) return -1;
-
- n = pCur->pPage->nCell;
- for(i=0; i<pCur->iPage; i++){
- n *= pCur->apPage[i]->nCell;
- }
- return n;
-}
-
-/*
-** Advance the cursor to the next entry in the database.
-** Return value:
-**
-** SQLITE_OK success
-** SQLITE_DONE cursor is already pointing at the last element
-** otherwise some kind of error occurred
-**
-** The main entry point is sqlite3BtreeNext(). That routine is optimized
-** for the common case of merely incrementing the cell counter BtCursor.aiIdx
-** to the next cell on the current page. The (slower) btreeNext() helper
-** routine is called when it is necessary to move to a different page or
-** to restore the cursor.
-**
-** If bit 0x01 of the F argument in sqlite3BtreeNext(C,F) is 1, then the
-** cursor corresponds to an SQL index and this routine could have been
-** skipped if the SQL index had been a unique index. The F argument
-** is a hint to the implement. SQLite btree implementation does not use
-** this hint, but COMDB2 does.
-*/
-static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
- int rc;
- int idx;
- MemPage *pPage;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
- if( pCur->eState!=CURSOR_VALID ){
- assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
- rc = restoreCursorPosition(pCur);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- if( CURSOR_INVALID==pCur->eState ){
- return SQLITE_DONE;
- }
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
- pCur->eState = CURSOR_VALID;
- if( pCur->skipNext>0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
- }
- }
-
- pPage = pCur->pPage;
- idx = ++pCur->ix;
- assert( pPage->isInit );
-
- /* If the database file is corrupt, it is possible for the value of idx
- ** to be invalid here. This can only occur if a second cursor modifies
- ** the page while cursor pCur is holding a reference to it. Which can
- ** only happen if the database is corrupt in such a way as to link the
- ** page into more than one b-tree structure. */
- testcase( idx>pPage->nCell );
-
- if( idx>=pPage->nCell ){
- if( !pPage->leaf ){
- rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
- if( rc ) return rc;
- return moveToLeftmost(pCur);
- }
- do{
- if( pCur->iPage==0 ){
- pCur->eState = CURSOR_INVALID;
- return SQLITE_DONE;
- }
- moveToParent(pCur);
- pPage = pCur->pPage;
- }while( pCur->ix>=pPage->nCell );
- if( pPage->intKey ){
- return sqlite3BtreeNext(pCur, 0);
- }else{
- return SQLITE_OK;
- }
- }
- if( pPage->leaf ){
- return SQLITE_OK;
- }else{
- return moveToLeftmost(pCur);
- }
-}
-int sqlite3BtreeNext(BtCursor *pCur, int flags){
- MemPage *pPage;
- UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
- assert( cursorOwnsBtShared(pCur) );
- assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
- pCur->info.nSize = 0;
- pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
- if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
- pPage = pCur->pPage;
- if( (++pCur->ix)>=pPage->nCell ){
- pCur->ix--;
- return btreeNext(pCur);
- }
- if( pPage->leaf ){
- return SQLITE_OK;
- }else{
- return moveToLeftmost(pCur);
- }
-}
-
-/*
-** Step the cursor to the back to the previous entry in the database.
-** Return values:
-**
-** SQLITE_OK success
-** SQLITE_DONE the cursor is already on the first element of the table
-** otherwise some kind of error occurred
-**
-** The main entry point is sqlite3BtreePrevious(). That routine is optimized
-** for the common case of merely decrementing the cell counter BtCursor.aiIdx
-** to the previous cell on the current page. The (slower) btreePrevious()
-** helper routine is called when it is necessary to move to a different page
-** or to restore the cursor.
-**
-** If bit 0x01 of the F argument to sqlite3BtreePrevious(C,F) is 1, then
-** the cursor corresponds to an SQL index and this routine could have been
-** skipped if the SQL index had been a unique index. The F argument is a
-** hint to the implement. The native SQLite btree implementation does not
-** use this hint, but COMDB2 does.
-*/
-static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
- int rc;
- MemPage *pPage;
-
- assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
- assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
- assert( pCur->info.nSize==0 );
- if( pCur->eState!=CURSOR_VALID ){
- rc = restoreCursorPosition(pCur);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- if( CURSOR_INVALID==pCur->eState ){
- return SQLITE_DONE;
- }
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
- pCur->eState = CURSOR_VALID;
- if( pCur->skipNext<0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
- }
- }
-
- pPage = pCur->pPage;
- assert( pPage->isInit );
- if( !pPage->leaf ){
- int idx = pCur->ix;
- rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
- if( rc ) return rc;
- rc = moveToRightmost(pCur);
- }else{
- while( pCur->ix==0 ){
- if( pCur->iPage==0 ){
- pCur->eState = CURSOR_INVALID;
- return SQLITE_DONE;
- }
- moveToParent(pCur);
- }
- assert( pCur->info.nSize==0 );
- assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 );
-
- pCur->ix--;
- pPage = pCur->pPage;
- if( pPage->intKey && !pPage->leaf ){
- rc = sqlite3BtreePrevious(pCur, 0);
- }else{
- rc = SQLITE_OK;
- }
- }
- return rc;
-}
-int sqlite3BtreePrevious(BtCursor *pCur, int flags){
- assert( cursorOwnsBtShared(pCur) );
- assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
- UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
- pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
- pCur->info.nSize = 0;
- if( pCur->eState!=CURSOR_VALID
- || pCur->ix==0
- || pCur->pPage->leaf==0
- ){
- return btreePrevious(pCur);
- }
- pCur->ix--;
- return SQLITE_OK;
-}
-
-/*
-** Allocate a new page from the database file.
-**
-** The new page is marked as dirty. (In other words, sqlite3PagerWrite()
-** has already been called on the new page.) The new page has also
-** been referenced and the calling routine is responsible for calling
-** sqlite3PagerUnref() on the new page when it is done.
-**
-** SQLITE_OK is returned on success. Any other return value indicates
-** an error. *ppPage is set to NULL in the event of an error.
-**
-** If the "nearby" parameter is not 0, then an effort is made to
-** locate a page close to the page number "nearby". This can be used in an
-** attempt to keep related pages close to each other in the database file,
-** which in turn can make database access faster.
-**
-** If the eMode parameter is BTALLOC_EXACT and the nearby page exists
-** anywhere on the free-list, then it is guaranteed to be returned. If
-** eMode is BTALLOC_LT then the page returned will be less than or equal
-** to nearby if any such page exists. If eMode is BTALLOC_ANY then there
-** are no restrictions on which page is returned.
-*/
-static int allocateBtreePage(
- BtShared *pBt, /* The btree */
- MemPage **ppPage, /* Store pointer to the allocated page here */
- Pgno *pPgno, /* Store the page number here */
- Pgno nearby, /* Search for a page near this one */
- u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
-){
- MemPage *pPage1;
- int rc;
- u32 n; /* Number of pages on the freelist */
- u32 k; /* Number of leaves on the trunk of the freelist */
- MemPage *pTrunk = 0;
- MemPage *pPrevTrunk = 0;
- Pgno mxPage; /* Total size of the database file */
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) );
- pPage1 = pBt->pPage1;
- mxPage = btreePagecount(pBt);
- /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36
- ** stores stores the total number of pages on the freelist. */
- n = get4byte(&pPage1->aData[36]);
- testcase( n==mxPage-1 );
- if( n>=mxPage ){
- return SQLITE_CORRUPT_BKPT;
- }
- if( n>0 ){
- /* There are pages on the freelist. Reuse one of those pages. */
- Pgno iTrunk;
- u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
- u32 nSearch = 0; /* Count of the number of search attempts */
-
- /* If eMode==BTALLOC_EXACT and a query of the pointer-map
- ** shows that the page 'nearby' is somewhere on the free-list, then
- ** the entire-list will be searched for that page.
- */
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( eMode==BTALLOC_EXACT ){
- if( nearby<=mxPage ){
- u8 eType;
- assert( nearby>0 );
- assert( pBt->autoVacuum );
- rc = ptrmapGet(pBt, nearby, &eType, 0);
- if( rc ) return rc;
- if( eType==PTRMAP_FREEPAGE ){
- searchList = 1;
- }
- }
- }else if( eMode==BTALLOC_LE ){
- searchList = 1;
- }
-#endif
-
- /* Decrement the free-list count by 1. Set iTrunk to the index of the
- ** first free-list trunk page. iPrevTrunk is initially 1.
- */
- rc = sqlite3PagerWrite(pPage1->pDbPage);
- if( rc ) return rc;
- put4byte(&pPage1->aData[36], n-1);
-
- /* The code within this loop is run only once if the 'searchList' variable
- ** is not true. Otherwise, it runs once for each trunk-page on the
- ** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT)
- ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT)
- */
- do {
- pPrevTrunk = pTrunk;
- if( pPrevTrunk ){
- /* EVIDENCE-OF: R-01506-11053 The first integer on a freelist trunk page
- ** is the page number of the next freelist trunk page in the list or
- ** zero if this is the last freelist trunk page. */
- iTrunk = get4byte(&pPrevTrunk->aData[0]);
- }else{
- /* EVIDENCE-OF: R-59841-13798 The 4-byte big-endian integer at offset 32
- ** stores the page number of the first page of the freelist, or zero if
- ** the freelist is empty. */
- iTrunk = get4byte(&pPage1->aData[32]);
- }
- testcase( iTrunk==mxPage );
- if( iTrunk>mxPage || nSearch++ > n ){
- rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1);
- }else{
- rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0);
- }
- if( rc ){
- pTrunk = 0;
- goto end_allocate_page;
- }
- assert( pTrunk!=0 );
- assert( pTrunk->aData!=0 );
- /* EVIDENCE-OF: R-13523-04394 The second integer on a freelist trunk page
- ** is the number of leaf page pointers to follow. */
- k = get4byte(&pTrunk->aData[4]);
- if( k==0 && !searchList ){
- /* The trunk has no leaves and the list is not being searched.
- ** So extract the trunk page itself and use it as the newly
- ** allocated page */
- assert( pPrevTrunk==0 );
- rc = sqlite3PagerWrite(pTrunk->pDbPage);
- if( rc ){
- goto end_allocate_page;
- }
- *pPgno = iTrunk;
- memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
- *ppPage = pTrunk;
- pTrunk = 0;
- TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
- }else if( k>(u32)(pBt->usableSize/4 - 2) ){
- /* Value of k is out of range. Database corruption */
- rc = SQLITE_CORRUPT_PGNO(iTrunk);
- goto end_allocate_page;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- }else if( searchList
- && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE))
- ){
- /* The list is being searched and this trunk page is the page
- ** to allocate, regardless of whether it has leaves.
- */
- *pPgno = iTrunk;
- *ppPage = pTrunk;
- searchList = 0;
- rc = sqlite3PagerWrite(pTrunk->pDbPage);
- if( rc ){
- goto end_allocate_page;
- }
- if( k==0 ){
- if( !pPrevTrunk ){
- memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
- }else{
- rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
- if( rc!=SQLITE_OK ){
- goto end_allocate_page;
- }
- memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
- }
- }else{
- /* The trunk page is required by the caller but it contains
- ** pointers to free-list leaves. The first leaf becomes a trunk
- ** page in this case.
- */
- MemPage *pNewTrunk;
- Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
- if( iNewTrunk>mxPage ){
- rc = SQLITE_CORRUPT_PGNO(iTrunk);
- goto end_allocate_page;
- }
- testcase( iNewTrunk==mxPage );
- rc = btreeGetUnusedPage(pBt, iNewTrunk, &pNewTrunk, 0);
- if( rc!=SQLITE_OK ){
- goto end_allocate_page;
- }
- rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
- if( rc!=SQLITE_OK ){
- releasePage(pNewTrunk);
- goto end_allocate_page;
- }
- memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
- put4byte(&pNewTrunk->aData[4], k-1);
- memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
- releasePage(pNewTrunk);
- if( !pPrevTrunk ){
- assert( sqlite3PagerIswriteable(pPage1->pDbPage) );
- put4byte(&pPage1->aData[32], iNewTrunk);
- }else{
- rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
- if( rc ){
- goto end_allocate_page;
- }
- put4byte(&pPrevTrunk->aData[0], iNewTrunk);
- }
- }
- pTrunk = 0;
- TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
-#endif
- }else if( k>0 ){
- /* Extract a leaf from the trunk */
- u32 closest;
- Pgno iPage;
- unsigned char *aData = pTrunk->aData;
- if( nearby>0 ){
- u32 i;
- closest = 0;
- if( eMode==BTALLOC_LE ){
- for(i=0; i<k; i++){
- iPage = get4byte(&aData[8+i*4]);
- if( iPage<=nearby ){
- closest = i;
- break;
- }
- }
- }else{
- int dist;
- dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
- for(i=1; i<k; i++){
- int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
- if( d2<dist ){
- closest = i;
- dist = d2;
- }
- }
- }
- }else{
- closest = 0;
- }
-
- iPage = get4byte(&aData[8+closest*4]);
- testcase( iPage==mxPage );
- if( iPage>mxPage ){
- rc = SQLITE_CORRUPT_PGNO(iTrunk);
- goto end_allocate_page;
- }
- testcase( iPage==mxPage );
- if( !searchList
- || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE))
- ){
- int noContent;
- *pPgno = iPage;
- TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
- ": %d more free pages\n",
- *pPgno, closest+1, k, pTrunk->pgno, n-1));
- rc = sqlite3PagerWrite(pTrunk->pDbPage);
- if( rc ) goto end_allocate_page;
- if( closest<k-1 ){
- memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
- }
- put4byte(&aData[4], k-1);
- noContent = !btreeGetHasContent(pBt, *pPgno)? PAGER_GET_NOCONTENT : 0;
- rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, noContent);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite((*ppPage)->pDbPage);
- if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
- *ppPage = 0;
- }
- }
- searchList = 0;
- }
- }
- releasePage(pPrevTrunk);
- pPrevTrunk = 0;
- }while( searchList );
- }else{
- /* There are no pages on the freelist, so append a new page to the
- ** database image.
- **
- ** Normally, new pages allocated by this block can be requested from the
- ** pager layer with the 'no-content' flag set. This prevents the pager
- ** from trying to read the pages content from disk. However, if the
- ** current transaction has already run one or more incremental-vacuum
- ** steps, then the page we are about to allocate may contain content
- ** that is required in the event of a rollback. In this case, do
- ** not set the no-content flag. This causes the pager to load and journal
- ** the current page content before overwriting it.
- **
- ** Note that the pager will not actually attempt to load or journal
- ** content for any page that really does lie past the end of the database
- ** file on disk. So the effects of disabling the no-content optimization
- ** here are confined to those pages that lie between the end of the
- ** database image and the end of the database file.
- */
- int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate))? PAGER_GET_NOCONTENT:0;
-
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- if( rc ) return rc;
- pBt->nPage++;
- if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){
- /* If *pPgno refers to a pointer-map page, allocate two new pages
- ** at the end of the file instead of one. The first allocated page
- ** becomes a new pointer-map page, the second is used by the caller.
- */
- MemPage *pPg = 0;
- TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
- assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pPg->pDbPage);
- releasePage(pPg);
- }
- if( rc ) return rc;
- pBt->nPage++;
- if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
- }
-#endif
- put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
- *pPgno = pBt->nPage;
-
- assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent);
- if( rc ) return rc;
- rc = sqlite3PagerWrite((*ppPage)->pDbPage);
- if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
- *ppPage = 0;
- }
- TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
- }
-
- assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
-
-end_allocate_page:
- releasePage(pTrunk);
- releasePage(pPrevTrunk);
- assert( rc!=SQLITE_OK || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 );
- assert( rc!=SQLITE_OK || (*ppPage)->isInit==0 );
- return rc;
-}
-
-/*
-** This function is used to add page iPage to the database file free-list.
-** It is assumed that the page is not already a part of the free-list.
-**
-** The value passed as the second argument to this function is optional.
-** If the caller happens to have a pointer to the MemPage object
-** corresponding to page iPage handy, it may pass it as the second value.
-** Otherwise, it may pass NULL.
-**
-** If a pointer to a MemPage object is passed as the second argument,
-** its reference count is not altered by this function.
-*/
-static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
- MemPage *pTrunk = 0; /* Free-list trunk page */
- Pgno iTrunk = 0; /* Page number of free-list trunk page */
- MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */
- MemPage *pPage; /* Page being freed. May be NULL. */
- int rc; /* Return Code */
- int nFree; /* Initial number of pages on free-list */
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( CORRUPT_DB || iPage>1 );
- assert( !pMemPage || pMemPage->pgno==iPage );
-
- if( iPage<2 ) return SQLITE_CORRUPT_BKPT;
- if( pMemPage ){
- pPage = pMemPage;
- sqlite3PagerRef(pPage->pDbPage);
- }else{
- pPage = btreePageLookup(pBt, iPage);
- }
-
- /* Increment the free page count on pPage1 */
- rc = sqlite3PagerWrite(pPage1->pDbPage);
- if( rc ) goto freepage_out;
- nFree = get4byte(&pPage1->aData[36]);
- put4byte(&pPage1->aData[36], nFree+1);
-
- if( pBt->btsFlags & BTS_SECURE_DELETE ){
- /* If the secure_delete option is enabled, then
- ** always fully overwrite deleted information with zeros.
- */
- if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
- || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
- ){
- goto freepage_out;
- }
- memset(pPage->aData, 0, pPage->pBt->pageSize);
- }
-
- /* If the database supports auto-vacuum, write an entry in the pointer-map
- ** to indicate that the page is free.
- */
- if( ISAUTOVACUUM ){
- ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc);
- if( rc ) goto freepage_out;
- }
-
- /* Now manipulate the actual database free-list structure. There are two
- ** possibilities. If the free-list is currently empty, or if the first
- ** trunk page in the free-list is full, then this page will become a
- ** new free-list trunk page. Otherwise, it will become a leaf of the
- ** first trunk page in the current free-list. This block tests if it
- ** is possible to add the page as a new free-list leaf.
- */
- if( nFree!=0 ){
- u32 nLeaf; /* Initial number of leaf cells on trunk page */
-
- iTrunk = get4byte(&pPage1->aData[32]);
- rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
- if( rc!=SQLITE_OK ){
- goto freepage_out;
- }
-
- nLeaf = get4byte(&pTrunk->aData[4]);
- assert( pBt->usableSize>32 );
- if( nLeaf > (u32)pBt->usableSize/4 - 2 ){
- rc = SQLITE_CORRUPT_BKPT;
- goto freepage_out;
- }
- if( nLeaf < (u32)pBt->usableSize/4 - 8 ){
- /* In this case there is room on the trunk page to insert the page
- ** being freed as a new leaf.
- **
- ** Note that the trunk page is not really full until it contains
- ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have
- ** coded. But due to a coding error in versions of SQLite prior to
- ** 3.6.0, databases with freelist trunk pages holding more than
- ** usableSize/4 - 8 entries will be reported as corrupt. In order
- ** to maintain backwards compatibility with older versions of SQLite,
- ** we will continue to restrict the number of entries to usableSize/4 - 8
- ** for now. At some point in the future (once everyone has upgraded
- ** to 3.6.0 or later) we should consider fixing the conditional above
- ** to read "usableSize/4-2" instead of "usableSize/4-8".
- **
- ** EVIDENCE-OF: R-19920-11576 However, newer versions of SQLite still
- ** avoid using the last six entries in the freelist trunk page array in
- ** order that database files created by newer versions of SQLite can be
- ** read by older versions of SQLite.
- */
- rc = sqlite3PagerWrite(pTrunk->pDbPage);
- if( rc==SQLITE_OK ){
- put4byte(&pTrunk->aData[4], nLeaf+1);
- put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
- if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){
- sqlite3PagerDontWrite(pPage->pDbPage);
- }
- rc = btreeSetHasContent(pBt, iPage);
- }
- TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
- goto freepage_out;
- }
- }
-
- /* If control flows to this point, then it was not possible to add the
- ** the page being freed as a leaf page of the first trunk in the free-list.
- ** Possibly because the free-list is empty, or possibly because the
- ** first trunk in the free-list is full. Either way, the page being freed
- ** will become the new first trunk page in the free-list.
- */
- if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
- goto freepage_out;
- }
- rc = sqlite3PagerWrite(pPage->pDbPage);
- if( rc!=SQLITE_OK ){
- goto freepage_out;
- }
- put4byte(pPage->aData, iTrunk);
- put4byte(&pPage->aData[4], 0);
- put4byte(&pPage1->aData[32], iPage);
- TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk));
-
-freepage_out:
- if( pPage ){
- pPage->isInit = 0;
- }
- releasePage(pPage);
- releasePage(pTrunk);
- return rc;
-}
-static void freePage(MemPage *pPage, int *pRC){
- if( (*pRC)==SQLITE_OK ){
- *pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
- }
-}
-
-/*
-** Free any overflow pages associated with the given Cell. Store
-** size information about the cell in pInfo.
-*/
-static int clearCell(
- MemPage *pPage, /* The page that contains the Cell */
- unsigned char *pCell, /* First byte of the Cell */
- CellInfo *pInfo /* Size information about the cell */
-){
- BtShared *pBt;
- Pgno ovflPgno;
- int rc;
- int nOvfl;
- u32 ovflPageSize;
-
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->xParseCell(pPage, pCell, pInfo);
- if( pInfo->nLocal==pInfo->nPayload ){
- return SQLITE_OK; /* No overflow pages. Return without doing anything */
- }
- testcase( pCell + pInfo->nSize == pPage->aDataEnd );
- testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
- if( pCell + pInfo->nSize > pPage->aDataEnd ){
- /* Cell extends past end of page */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- ovflPgno = get4byte(pCell + pInfo->nSize - 4);
- pBt = pPage->pBt;
- assert( pBt->usableSize > 4 );
- ovflPageSize = pBt->usableSize - 4;
- nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
- assert( nOvfl>0 ||
- (CORRUPT_DB && (pInfo->nPayload + ovflPageSize)<ovflPageSize)
- );
- while( nOvfl-- ){
- Pgno iNext = 0;
- MemPage *pOvfl = 0;
- if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){
- /* 0 is not a legal page number and page 1 cannot be an
- ** overflow page. Therefore if ovflPgno<2 or past the end of the
- ** file the database must be corrupt. */
- return SQLITE_CORRUPT_BKPT;
- }
- if( nOvfl ){
- rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
- if( rc ) return rc;
- }
-
- if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
- && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
- ){
- /* There is no reason any cursor should have an outstanding reference
- ** to an overflow page belonging to a cell that is being deleted/updated.
- ** So if there exists more than one reference to this page, then it
- ** must not really be an overflow page and the database must be corrupt.
- ** It is helpful to detect this before calling freePage2(), as
- ** freePage2() may zero the page contents if secure-delete mode is
- ** enabled. If this 'overflow' page happens to be a page that the
- ** caller is iterating through or using in some other way, this
- ** can be problematic.
- */
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- rc = freePage2(pBt, pOvfl, ovflPgno);
- }
-
- if( pOvfl ){
- sqlite3PagerUnref(pOvfl->pDbPage);
- }
- if( rc ) return rc;
- ovflPgno = iNext;
- }
- return SQLITE_OK;
-}
-
-/*
-** Create the byte sequence used to represent a cell on page pPage
-** and write that byte sequence into pCell[]. Overflow pages are
-** allocated and filled in as necessary. The calling procedure
-** is responsible for making sure sufficient space has been allocated
-** for pCell[].
-**
-** Note that pCell does not necessary need to point to the pPage->aData
-** area. pCell might point to some temporary storage. The cell will
-** be constructed in this temporary area then copied into pPage->aData
-** later.
-*/
-static int fillInCell(
- MemPage *pPage, /* The page that contains the cell */
- unsigned char *pCell, /* Complete text of the cell */
- const BtreePayload *pX, /* Payload with which to construct the cell */
- int *pnSize /* Write cell size here */
-){
- int nPayload;
- const u8 *pSrc;
- int nSrc, n, rc, mn;
- int spaceLeft;
- MemPage *pToRelease;
- unsigned char *pPrior;
- unsigned char *pPayload;
- BtShared *pBt;
- Pgno pgnoOvfl;
- int nHeader;
-
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
-
- /* pPage is not necessarily writeable since pCell might be auxiliary
- ** buffer space that is separate from the pPage buffer area */
- assert( pCell<pPage->aData || pCell>=&pPage->aData[pPage->pBt->pageSize]
- || sqlite3PagerIswriteable(pPage->pDbPage) );
-
- /* Fill in the header. */
- nHeader = pPage->childPtrSize;
- if( pPage->intKey ){
- nPayload = pX->nData + pX->nZero;
- pSrc = pX->pData;
- nSrc = pX->nData;
- assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */
- nHeader += putVarint32(&pCell[nHeader], nPayload);
- nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey);
- }else{
- assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
- nSrc = nPayload = (int)pX->nKey;
- pSrc = pX->pKey;
- nHeader += putVarint32(&pCell[nHeader], nPayload);
- }
-
- /* Fill in the payload */
- pPayload = &pCell[nHeader];
- if( nPayload<=pPage->maxLocal ){
- /* This is the common case where everything fits on the btree page
- ** and no overflow pages are required. */
- n = nHeader + nPayload;
- testcase( n==3 );
- testcase( n==4 );
- if( n<4 ) n = 4;
- *pnSize = n;
- assert( nSrc<=nPayload );
- testcase( nSrc<nPayload );
- memcpy(pPayload, pSrc, nSrc);
- memset(pPayload+nSrc, 0, nPayload-nSrc);
- return SQLITE_OK;
- }
-
- /* If we reach this point, it means that some of the content will need
- ** to spill onto overflow pages.
- */
- mn = pPage->minLocal;
- n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
- testcase( n==pPage->maxLocal );
- testcase( n==pPage->maxLocal+1 );
- if( n > pPage->maxLocal ) n = mn;
- spaceLeft = n;
- *pnSize = n + nHeader + 4;
- pPrior = &pCell[nHeader+n];
- pToRelease = 0;
- pgnoOvfl = 0;
- pBt = pPage->pBt;
-
- /* At this point variables should be set as follows:
- **
- ** nPayload Total payload size in bytes
- ** pPayload Begin writing payload here
- ** spaceLeft Space available at pPayload. If nPayload>spaceLeft,
- ** that means content must spill into overflow pages.
- ** *pnSize Size of the local cell (not counting overflow pages)
- ** pPrior Where to write the pgno of the first overflow page
- **
- ** Use a call to btreeParseCellPtr() to verify that the values above
- ** were computed correctly.
- */
-#ifdef SQLITE_DEBUG
- {
- CellInfo info;
- pPage->xParseCell(pPage, pCell, &info);
- assert( nHeader==(int)(info.pPayload - pCell) );
- assert( info.nKey==pX->nKey );
- assert( *pnSize == info.nSize );
- assert( spaceLeft == info.nLocal );
- }
-#endif
-
- /* Write the payload into the local Cell and any extra into overflow pages */
- while( 1 ){
- n = nPayload;
- if( n>spaceLeft ) n = spaceLeft;
-
- /* If pToRelease is not zero than pPayload points into the data area
- ** of pToRelease. Make sure pToRelease is still writeable. */
- assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
-
- /* If pPayload is part of the data area of pPage, then make sure pPage
- ** is still writeable */
- assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
- || sqlite3PagerIswriteable(pPage->pDbPage) );
-
- if( nSrc>=n ){
- memcpy(pPayload, pSrc, n);
- }else if( nSrc>0 ){
- n = nSrc;
- memcpy(pPayload, pSrc, n);
- }else{
- memset(pPayload, 0, n);
- }
- nPayload -= n;
- if( nPayload<=0 ) break;
- pPayload += n;
- pSrc += n;
- nSrc -= n;
- spaceLeft -= n;
- if( spaceLeft==0 ){
- MemPage *pOvfl = 0;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
- if( pBt->autoVacuum ){
- do{
- pgnoOvfl++;
- } while(
- PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
- );
- }
-#endif
- rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- /* If the database supports auto-vacuum, and the second or subsequent
- ** overflow page is being allocated, add an entry to the pointer-map
- ** for that page now.
- **
- ** If this is the first overflow page, then write a partial entry
- ** to the pointer-map. If we write nothing to this pointer-map slot,
- ** then the optimistic overflow chain processing in clearCell()
- ** may misinterpret the uninitialized values and delete the
- ** wrong pages from the database.
- */
- if( pBt->autoVacuum && rc==SQLITE_OK ){
- u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1);
- ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc);
- if( rc ){
- releasePage(pOvfl);
- }
- }
-#endif
- if( rc ){
- releasePage(pToRelease);
- return rc;
- }
-
- /* If pToRelease is not zero than pPrior points into the data area
- ** of pToRelease. Make sure pToRelease is still writeable. */
- assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
-
- /* If pPrior is part of the data area of pPage, then make sure pPage
- ** is still writeable */
- assert( pPrior<pPage->aData || pPrior>=&pPage->aData[pBt->pageSize]
- || sqlite3PagerIswriteable(pPage->pDbPage) );
-
- put4byte(pPrior, pgnoOvfl);
- releasePage(pToRelease);
- pToRelease = pOvfl;
- pPrior = pOvfl->aData;
- put4byte(pPrior, 0);
- pPayload = &pOvfl->aData[4];
- spaceLeft = pBt->usableSize - 4;
- }
- }
- releasePage(pToRelease);
- return SQLITE_OK;
-}
-
-/*
-** Remove the i-th cell from pPage. This routine effects pPage only.
-** The cell content is not freed or deallocated. It is assumed that
-** the cell content has been copied someplace else. This routine just
-** removes the reference to the cell from pPage.
-**
-** "sz" must be the number of bytes in the cell.
-*/
-static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
- u32 pc; /* Offset to cell content of cell being deleted */
- u8 *data; /* pPage->aData */
- u8 *ptr; /* Used to move bytes around within data[] */
- int rc; /* The return code */
- int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
-
- if( *pRC ) return;
- assert( idx>=0 && idx<pPage->nCell );
- assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- data = pPage->aData;
- ptr = &pPage->aCellIdx[2*idx];
- pc = get2byte(ptr);
- hdr = pPage->hdrOffset;
- testcase( pc==get2byte(&data[hdr+5]) );
- testcase( pc+sz==pPage->pBt->usableSize );
- if( pc+sz > pPage->pBt->usableSize ){
- *pRC = SQLITE_CORRUPT_BKPT;
- return;
- }
- rc = freeSpace(pPage, pc, sz);
- if( rc ){
- *pRC = rc;
- return;
- }
- pPage->nCell--;
- if( pPage->nCell==0 ){
- memset(&data[hdr+1], 0, 4);
- data[hdr+7] = 0;
- put2byte(&data[hdr+5], pPage->pBt->usableSize);
- pPage->nFree = pPage->pBt->usableSize - pPage->hdrOffset
- - pPage->childPtrSize - 8;
- }else{
- memmove(ptr, ptr+2, 2*(pPage->nCell - idx));
- put2byte(&data[hdr+3], pPage->nCell);
- pPage->nFree += 2;
- }
-}
-
-/*
-** Insert a new cell on pPage at cell index "i". pCell points to the
-** content of the cell.
-**
-** If the cell content will fit on the page, then put it there. If it
-** will not fit, then make a copy of the cell content into pTemp if
-** pTemp is not null. Regardless of pTemp, allocate a new entry
-** in pPage->apOvfl[] and make it point to the cell content (either
-** in pTemp or the original pCell) and also record its index.
-** Allocating a new entry in pPage->aCell[] implies that
-** pPage->nOverflow is incremented.
-**
-** *pRC must be SQLITE_OK when this routine is called.
-*/
-static void insertCell(
- MemPage *pPage, /* Page into which we are copying */
- int i, /* New cell becomes the i-th cell of the page */
- u8 *pCell, /* Content of the new cell */
- int sz, /* Bytes of content in pCell */
- u8 *pTemp, /* Temp storage space for pCell, if needed */
- Pgno iChild, /* If non-zero, replace first 4 bytes with this value */
- int *pRC /* Read and write return code from here */
-){
- int idx = 0; /* Where to write new cell content in data[] */
- int j; /* Loop counter */
- u8 *data; /* The content of the whole page */
- u8 *pIns; /* The point in pPage->aCellIdx[] where no cell inserted */
-
- assert( *pRC==SQLITE_OK );
- assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
- assert( MX_CELL(pPage->pBt)<=10921 );
- assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB );
- assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
- assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- /* The cell should normally be sized correctly. However, when moving a
- ** malformed cell from a leaf page to an interior page, if the cell size
- ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
- ** might be less than 8 (leaf-size + pointer) on the interior node. Hence
- ** the term after the || in the following assert(). */
- assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
- if( pPage->nOverflow || sz+2>pPage->nFree ){
- if( pTemp ){
- memcpy(pTemp, pCell, sz);
- pCell = pTemp;
- }
- if( iChild ){
- put4byte(pCell, iChild);
- }
- j = pPage->nOverflow++;
- /* Comparison against ArraySize-1 since we hold back one extra slot
- ** as a contingency. In other words, never need more than 3 overflow
- ** slots but 4 are allocated, just to be safe. */
- assert( j < ArraySize(pPage->apOvfl)-1 );
- pPage->apOvfl[j] = pCell;
- pPage->aiOvfl[j] = (u16)i;
-
- /* When multiple overflows occur, they are always sequential and in
- ** sorted order. This invariants arise because multiple overflows can
- ** only occur when inserting divider cells into the parent page during
- ** balancing, and the dividers are adjacent and sorted.
- */
- assert( j==0 || pPage->aiOvfl[j-1]<(u16)i ); /* Overflows in sorted order */
- assert( j==0 || i==pPage->aiOvfl[j-1]+1 ); /* Overflows are sequential */
- }else{
- int rc = sqlite3PagerWrite(pPage->pDbPage);
- if( rc!=SQLITE_OK ){
- *pRC = rc;
- return;
- }
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- data = pPage->aData;
- assert( &data[pPage->cellOffset]==pPage->aCellIdx );
- rc = allocateSpace(pPage, sz, &idx);
- if( rc ){ *pRC = rc; return; }
- /* The allocateSpace() routine guarantees the following properties
- ** if it returns successfully */
- assert( idx >= 0 );
- assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB );
- assert( idx+sz <= (int)pPage->pBt->usableSize );
- pPage->nFree -= (u16)(2 + sz);
- memcpy(&data[idx], pCell, sz);
- if( iChild ){
- put4byte(&data[idx], iChild);
- }
- pIns = pPage->aCellIdx + i*2;
- memmove(pIns+2, pIns, 2*(pPage->nCell - i));
- put2byte(pIns, idx);
- pPage->nCell++;
- /* increment the cell count */
- if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++;
- assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell );
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pPage->pBt->autoVacuum ){
- /* The cell may contain a pointer to an overflow page. If so, write
- ** the entry for the overflow page into the pointer map.
- */
- ptrmapPutOvflPtr(pPage, pCell, pRC);
- }
-#endif
- }
-}
-
-/*
-** A CellArray object contains a cache of pointers and sizes for a
-** consecutive sequence of cells that might be held on multiple pages.
-*/
-typedef struct CellArray CellArray;
-struct CellArray {
- int nCell; /* Number of cells in apCell[] */
- MemPage *pRef; /* Reference page */
- u8 **apCell; /* All cells begin balanced */
- u16 *szCell; /* Local size of all cells in apCell[] */
-};
-
-/*
-** Make sure the cell sizes at idx, idx+1, ..., idx+N-1 have been
-** computed.
-*/
-static void populateCellCache(CellArray *p, int idx, int N){
- assert( idx>=0 && idx+N<=p->nCell );
- while( N>0 ){
- assert( p->apCell[idx]!=0 );
- if( p->szCell[idx]==0 ){
- p->szCell[idx] = p->pRef->xCellSize(p->pRef, p->apCell[idx]);
- }else{
- assert( CORRUPT_DB ||
- p->szCell[idx]==p->pRef->xCellSize(p->pRef, p->apCell[idx]) );
- }
- idx++;
- N--;
- }
-}
-
-/*
-** Return the size of the Nth element of the cell array
-*/
-static SQLITE_NOINLINE u16 computeCellSize(CellArray *p, int N){
- assert( N>=0 && N<p->nCell );
- assert( p->szCell[N]==0 );
- p->szCell[N] = p->pRef->xCellSize(p->pRef, p->apCell[N]);
- return p->szCell[N];
-}
-static u16 cachedCellSize(CellArray *p, int N){
- assert( N>=0 && N<p->nCell );
- if( p->szCell[N] ) return p->szCell[N];
- return computeCellSize(p, N);
-}
-
-/*
-** Array apCell[] contains pointers to nCell b-tree page cells. The
-** szCell[] array contains the size in bytes of each cell. This function
-** replaces the current contents of page pPg with the contents of the cell
-** array.
-**
-** Some of the cells in apCell[] may currently be stored in pPg. This
-** function works around problems caused by this by making a copy of any
-** such cells before overwriting the page data.
-**
-** The MemPage.nFree field is invalidated by this function. It is the
-** responsibility of the caller to set it correctly.
-*/
-static int rebuildPage(
- MemPage *pPg, /* Edit this page */
- int nCell, /* Final number of cells on page */
- u8 **apCell, /* Array of cells */
- u16 *szCell /* Array of cell sizes */
-){
- const int hdr = pPg->hdrOffset; /* Offset of header on pPg */
- u8 * const aData = pPg->aData; /* Pointer to data for pPg */
- const int usableSize = pPg->pBt->usableSize;
- u8 * const pEnd = &aData[usableSize];
- int i;
- u8 *pCellptr = pPg->aCellIdx;
- u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
- u8 *pData;
-
- i = get2byte(&aData[hdr+5]);
- memcpy(&pTmp[i], &aData[i], usableSize - i);
-
- pData = pEnd;
- for(i=0; i<nCell; i++){
- u8 *pCell = apCell[i];
- if( SQLITE_WITHIN(pCell,aData,pEnd) ){
- pCell = &pTmp[pCell - aData];
- }
- pData -= szCell[i];
- put2byte(pCellptr, (pData - aData));
- pCellptr += 2;
- if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
- memcpy(pData, pCell, szCell[i]);
- assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
- testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
- }
-
- /* The pPg->nFree field is now set incorrectly. The caller will fix it. */
- pPg->nCell = nCell;
- pPg->nOverflow = 0;
-
- put2byte(&aData[hdr+1], 0);
- put2byte(&aData[hdr+3], pPg->nCell);
- put2byte(&aData[hdr+5], pData - aData);
- aData[hdr+7] = 0x00;
- return SQLITE_OK;
-}
-
-/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function attempts to
-** add the cells stored in the array to page pPg. If it cannot (because
-** the page needs to be defragmented before the cells will fit), non-zero
-** is returned. Otherwise, if the cells are added successfully, zero is
-** returned.
-**
-** Argument pCellptr points to the first entry in the cell-pointer array
-** (part of page pPg) to populate. After cell apCell[0] is written to the
-** page body, a 16-bit offset is written to pCellptr. And so on, for each
-** cell in the array. It is the responsibility of the caller to ensure
-** that it is safe to overwrite this part of the cell-pointer array.
-**
-** When this function is called, *ppData points to the start of the
-** content area on page pPg. If the size of the content area is extended,
-** *ppData is updated to point to the new start of the content area
-** before returning.
-**
-** Finally, argument pBegin points to the byte immediately following the
-** end of the space required by this page for the cell-pointer area (for
-** all cells - not just those inserted by the current call). If the content
-** area must be extended to before this point in order to accomodate all
-** cells in apCell[], then the cells do not fit and non-zero is returned.
-*/
-static int pageInsertArray(
- MemPage *pPg, /* Page to add cells to */
- u8 *pBegin, /* End of cell-pointer array */
- u8 **ppData, /* IN/OUT: Page content -area pointer */
- u8 *pCellptr, /* Pointer to cell-pointer area */
- int iFirst, /* Index of first cell to add */
- int nCell, /* Number of cells to add to pPg */
- CellArray *pCArray /* Array of cells */
-){
- int i;
- u8 *aData = pPg->aData;
- u8 *pData = *ppData;
- int iEnd = iFirst + nCell;
- assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
- for(i=iFirst; i<iEnd; i++){
- int sz, rc;
- u8 *pSlot;
- sz = cachedCellSize(pCArray, i);
- if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
- if( (pData - pBegin)<sz ) return 1;
- pData -= sz;
- pSlot = pData;
- }
- /* pSlot and pCArray->apCell[i] will never overlap on a well-formed
- ** database. But they might for a corrupt database. Hence use memmove()
- ** since memcpy() sends SIGABORT with overlapping buffers on OpenBSD */
- assert( (pSlot+sz)<=pCArray->apCell[i]
- || pSlot>=(pCArray->apCell[i]+sz)
- || CORRUPT_DB );
- memmove(pSlot, pCArray->apCell[i], sz);
- put2byte(pCellptr, (pSlot - aData));
- pCellptr += 2;
- }
- *ppData = pData;
- return 0;
-}
-
-/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function adds the
-** space associated with each cell in the array that is currently stored
-** within the body of pPg to the pPg free-list. The cell-pointers and other
-** fields of the page are not updated.
-**
-** This function returns the total number of cells added to the free-list.
-*/
-static int pageFreeArray(
- MemPage *pPg, /* Page to edit */
- int iFirst, /* First cell to delete */
- int nCell, /* Cells to delete */
- CellArray *pCArray /* Array of cells */
-){
- u8 * const aData = pPg->aData;
- u8 * const pEnd = &aData[pPg->pBt->usableSize];
- u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize];
- int nRet = 0;
- int i;
- int iEnd = iFirst + nCell;
- u8 *pFree = 0;
- int szFree = 0;
-
- for(i=iFirst; i<iEnd; i++){
- u8 *pCell = pCArray->apCell[i];
- if( SQLITE_WITHIN(pCell, pStart, pEnd) ){
- int sz;
- /* No need to use cachedCellSize() here. The sizes of all cells that
- ** are to be freed have already been computing while deciding which
- ** cells need freeing */
- sz = pCArray->szCell[i]; assert( sz>0 );
- if( pFree!=(pCell + sz) ){
- if( pFree ){
- assert( pFree>aData && (pFree - aData)<65536 );
- freeSpace(pPg, (u16)(pFree - aData), szFree);
- }
- pFree = pCell;
- szFree = sz;
- if( pFree+sz>pEnd ) return 0;
- }else{
- pFree = pCell;
- szFree += sz;
- }
- nRet++;
- }
- }
- if( pFree ){
- assert( pFree>aData && (pFree - aData)<65536 );
- freeSpace(pPg, (u16)(pFree - aData), szFree);
- }
- return nRet;
-}
-
-/*
-** apCell[] and szCell[] contains pointers to and sizes of all cells in the
-** pages being balanced. The current page, pPg, has pPg->nCell cells starting
-** with apCell[iOld]. After balancing, this page should hold nNew cells
-** starting at apCell[iNew].
-**
-** This routine makes the necessary adjustments to pPg so that it contains
-** the correct cells after being balanced.
-**
-** The pPg->nFree field is invalid when this function returns. It is the
-** responsibility of the caller to set it correctly.
-*/
-static int editPage(
- MemPage *pPg, /* Edit this page */
- int iOld, /* Index of first cell currently on page */
- int iNew, /* Index of new first cell on page */
- int nNew, /* Final number of cells on page */
- CellArray *pCArray /* Array of cells and sizes */
-){
- u8 * const aData = pPg->aData;
- const int hdr = pPg->hdrOffset;
- u8 *pBegin = &pPg->aCellIdx[nNew * 2];
- int nCell = pPg->nCell; /* Cells stored on pPg */
- u8 *pData;
- u8 *pCellptr;
- int i;
- int iOldEnd = iOld + pPg->nCell + pPg->nOverflow;
- int iNewEnd = iNew + nNew;
-
-#ifdef SQLITE_DEBUG
- u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
- memcpy(pTmp, aData, pPg->pBt->usableSize);
-#endif
-
- /* Remove cells from the start and end of the page */
- if( iOld<iNew ){
- int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
- memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
- nCell -= nShift;
- }
- if( iNewEnd < iOldEnd ){
- nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
- }
-
- pData = &aData[get2byteNotZero(&aData[hdr+5])];
- if( pData<pBegin ) goto editpage_fail;
-
- /* Add cells to the start of the page */
- if( iNew<iOld ){
- int nAdd = MIN(nNew,iOld-iNew);
- assert( (iOld-iNew)<nNew || nCell==0 || CORRUPT_DB );
- pCellptr = pPg->aCellIdx;
- memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
- if( pageInsertArray(
- pPg, pBegin, &pData, pCellptr,
- iNew, nAdd, pCArray
- ) ) goto editpage_fail;
- nCell += nAdd;
- }
-
- /* Add any overflow cells */
- for(i=0; i<pPg->nOverflow; i++){
- int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
- if( iCell>=0 && iCell<nNew ){
- pCellptr = &pPg->aCellIdx[iCell * 2];
- memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
- nCell++;
- if( pageInsertArray(
- pPg, pBegin, &pData, pCellptr,
- iCell+iNew, 1, pCArray
- ) ) goto editpage_fail;
- }
- }
-
- /* Append cells to the end of the page */
- pCellptr = &pPg->aCellIdx[nCell*2];
- if( pageInsertArray(
- pPg, pBegin, &pData, pCellptr,
- iNew+nCell, nNew-nCell, pCArray
- ) ) goto editpage_fail;
-
- pPg->nCell = nNew;
- pPg->nOverflow = 0;
-
- put2byte(&aData[hdr+3], pPg->nCell);
- put2byte(&aData[hdr+5], pData - aData);
-
-#ifdef SQLITE_DEBUG
- for(i=0; i<nNew && !CORRUPT_DB; i++){
- u8 *pCell = pCArray->apCell[i+iNew];
- int iOff = get2byteAligned(&pPg->aCellIdx[i*2]);
- if( SQLITE_WITHIN(pCell, aData, &aData[pPg->pBt->usableSize]) ){
- pCell = &pTmp[pCell - aData];
- }
- assert( 0==memcmp(pCell, &aData[iOff],
- pCArray->pRef->xCellSize(pCArray->pRef, pCArray->apCell[i+iNew])) );
- }
-#endif
-
- return SQLITE_OK;
- editpage_fail:
- /* Unable to edit this page. Rebuild it from scratch instead. */
- populateCellCache(pCArray, iNew, nNew);
- return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
-}
-
-/*
-** The following parameters determine how many adjacent pages get involved
-** in a balancing operation. NN is the number of neighbors on either side
-** of the page that participate in the balancing operation. NB is the
-** total number of pages that participate, including the target page and
-** NN neighbors on either side.
-**
-** The minimum value of NN is 1 (of course). Increasing NN above 1
-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-** in exchange for a larger degradation in INSERT and UPDATE performance.
-** The value of NN appears to give the best results overall.
-*/
-#define NN 1 /* Number of neighbors on either side of pPage */
-#define NB (NN*2+1) /* Total pages involved in the balance */
-
-
-#ifndef SQLITE_OMIT_QUICKBALANCE
-/*
-** This version of balance() handles the common special case where
-** a new entry is being inserted on the extreme right-end of the
-** tree, in other words, when the new entry will become the largest
-** entry in the tree.
-**
-** Instead of trying to balance the 3 right-most leaf pages, just add
-** a new page to the right-hand side and put the one new entry in
-** that page. This leaves the right side of the tree somewhat
-** unbalanced. But odds are that we will be inserting new entries
-** at the end soon afterwards so the nearly empty page will quickly
-** fill up. On average.
-**
-** pPage is the leaf page which is the right-most page in the tree.
-** pParent is its parent. pPage must have a single overflow entry
-** which is also the right-most entry on the page.
-**
-** The pSpace buffer is used to store a temporary copy of the divider
-** cell that will be inserted into pParent. Such a cell consists of a 4
-** byte page number followed by a variable length integer. In other
-** words, at most 13 bytes. Hence the pSpace buffer must be at
-** least 13 bytes in size.
-*/
-static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
- BtShared *const pBt = pPage->pBt; /* B-Tree Database */
- MemPage *pNew; /* Newly allocated page */
- int rc; /* Return Code */
- Pgno pgnoNew; /* Page number of pNew */
-
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
- assert( pPage->nOverflow==1 );
-
- /* This error condition is now caught prior to reaching this function */
- if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT;
-
- /* Allocate a new page. This page will become the right-sibling of
- ** pPage. Make the parent page writable, so that the new divider cell
- ** may be inserted. If both these operations are successful, proceed.
- */
- rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
-
- if( rc==SQLITE_OK ){
-
- u8 *pOut = &pSpace[4];
- u8 *pCell = pPage->apOvfl[0];
- u16 szCell = pPage->xCellSize(pPage, pCell);
- u8 *pStop;
-
- assert( sqlite3PagerIswriteable(pNew->pDbPage) );
- assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
- zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
- rc = rebuildPage(pNew, 1, &pCell, &szCell);
- if( NEVER(rc) ) return rc;
- pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
-
- /* If this is an auto-vacuum database, update the pointer map
- ** with entries for the new page, and any pointer from the
- ** cell on the page to an overflow page. If either of these
- ** operations fails, the return code is set, but the contents
- ** of the parent page are still manipulated by thh code below.
- ** That is Ok, at this point the parent page is guaranteed to
- ** be marked as dirty. Returning an error code will cause a
- ** rollback, undoing any changes made to the parent page.
- */
- if( ISAUTOVACUUM ){
- ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc);
- if( szCell>pNew->minLocal ){
- ptrmapPutOvflPtr(pNew, pCell, &rc);
- }
- }
-
- /* Create a divider cell to insert into pParent. The divider cell
- ** consists of a 4-byte page number (the page number of pPage) and
- ** a variable length key value (which must be the same value as the
- ** largest key on pPage).
- **
- ** To find the largest key value on pPage, first find the right-most
- ** cell on pPage. The first two fields of this cell are the
- ** record-length (a variable length integer at most 32-bits in size)
- ** and the key value (a variable length integer, may have any value).
- ** The first of the while(...) loops below skips over the record-length
- ** field. The second while(...) loop copies the key value from the
- ** cell on pPage into the pSpace buffer.
- */
- pCell = findCell(pPage, pPage->nCell-1);
- pStop = &pCell[9];
- while( (*(pCell++)&0x80) && pCell<pStop );
- pStop = &pCell[9];
- while( ((*(pOut++) = *(pCell++))&0x80) && pCell<pStop );
-
- /* Insert the new divider cell into pParent. */
- if( rc==SQLITE_OK ){
- insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace),
- 0, pPage->pgno, &rc);
- }
-
- /* Set the right-child pointer of pParent to point to the new page. */
- put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
-
- /* Release the reference to the new page. */
- releasePage(pNew);
- }
-
- return rc;
-}
-#endif /* SQLITE_OMIT_QUICKBALANCE */
-
-#if 0
-/*
-** This function does not contribute anything to the operation of SQLite.
-** it is sometimes activated temporarily while debugging code responsible
-** for setting pointer-map entries.
-*/
-static int ptrmapCheckPages(MemPage **apPage, int nPage){
- int i, j;
- for(i=0; i<nPage; i++){
- Pgno n;
- u8 e;
- MemPage *pPage = apPage[i];
- BtShared *pBt = pPage->pBt;
- assert( pPage->isInit );
-
- for(j=0; j<pPage->nCell; j++){
- CellInfo info;
- u8 *z;
-
- z = findCell(pPage, j);
- pPage->xParseCell(pPage, z, &info);
- if( info.nLocal<info.nPayload ){
- Pgno ovfl = get4byte(&z[info.nSize-4]);
- ptrmapGet(pBt, ovfl, &e, &n);
- assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 );
- }
- if( !pPage->leaf ){
- Pgno child = get4byte(z);
- ptrmapGet(pBt, child, &e, &n);
- assert( n==pPage->pgno && e==PTRMAP_BTREE );
- }
- }
- if( !pPage->leaf ){
- Pgno child = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- ptrmapGet(pBt, child, &e, &n);
- assert( n==pPage->pgno && e==PTRMAP_BTREE );
- }
- }
- return 1;
-}
-#endif
-
-/*
-** This function is used to copy the contents of the b-tree node stored
-** on page pFrom to page pTo. If page pFrom was not a leaf page, then
-** the pointer-map entries for each child page are updated so that the
-** parent page stored in the pointer map is page pTo. If pFrom contained
-** any cells with overflow page pointers, then the corresponding pointer
-** map entries are also updated so that the parent page is page pTo.
-**
-** If pFrom is currently carrying any overflow cells (entries in the
-** MemPage.apOvfl[] array), they are not copied to pTo.
-**
-** Before returning, page pTo is reinitialized using btreeInitPage().
-**
-** The performance of this function is not critical. It is only used by
-** the balance_shallower() and balance_deeper() procedures, neither of
-** which are called often under normal circumstances.
-*/
-static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
- if( (*pRC)==SQLITE_OK ){
- BtShared * const pBt = pFrom->pBt;
- u8 * const aFrom = pFrom->aData;
- u8 * const aTo = pTo->aData;
- int const iFromHdr = pFrom->hdrOffset;
- int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
- int rc;
- int iData;
-
-
- assert( pFrom->isInit );
- assert( pFrom->nFree>=iToHdr );
- assert( get2byte(&aFrom[iFromHdr+5]) <= (int)pBt->usableSize );
-
- /* Copy the b-tree node content from page pFrom to page pTo. */
- iData = get2byte(&aFrom[iFromHdr+5]);
- memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
- memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
-
- /* Reinitialize page pTo so that the contents of the MemPage structure
- ** match the new data. The initialization of pTo can actually fail under
- ** fairly obscure circumstances, even though it is a copy of initialized
- ** page pFrom.
- */
- pTo->isInit = 0;
- rc = btreeInitPage(pTo);
- if( rc!=SQLITE_OK ){
- *pRC = rc;
- return;
- }
-
- /* If this is an auto-vacuum database, update the pointer-map entries
- ** for any b-tree or overflow pages that pTo now contains the pointers to.
- */
- if( ISAUTOVACUUM ){
- *pRC = setChildPtrmaps(pTo);
- }
- }
-}
-
-/*
-** This routine redistributes cells on the iParentIdx'th child of pParent
-** (hereafter "the page") and up to 2 siblings so that all pages have about the
-** same amount of free space. Usually a single sibling on either side of the
-** page are used in the balancing, though both siblings might come from one
-** side if the page is the first or last child of its parent. If the page
-** has fewer than 2 siblings (something which can only happen if the page
-** is a root page or a child of a root page) then all available siblings
-** participate in the balancing.
-**
-** The number of siblings of the page might be increased or decreased by
-** one or two in an effort to keep pages nearly full but not over full.
-**
-** Note that when this routine is called, some of the cells on the page
-** might not actually be stored in MemPage.aData[]. This can happen
-** if the page is overfull. This routine ensures that all cells allocated
-** to the page and its siblings fit into MemPage.aData[] before returning.
-**
-** In the course of balancing the page and its siblings, cells may be
-** inserted into or removed from the parent page (pParent). Doing so
-** may cause the parent page to become overfull or underfull. If this
-** happens, it is the responsibility of the caller to invoke the correct
-** balancing routine to fix this problem (see the balance() routine).
-**
-** If this routine fails for any reason, it might leave the database
-** in a corrupted state. So if this routine fails, the database should
-** be rolled back.
-**
-** The third argument to this function, aOvflSpace, is a pointer to a
-** buffer big enough to hold one page. If while inserting cells into the parent
-** page (pParent) the parent page becomes overfull, this buffer is
-** used to store the parent's overflow cells. Because this function inserts
-** a maximum of four divider cells into the parent page, and the maximum
-** size of a cell stored within an internal node is always less than 1/4
-** of the page-size, the aOvflSpace[] buffer is guaranteed to be large
-** enough for all overflow cells.
-**
-** If aOvflSpace is set to a null pointer, this function returns
-** SQLITE_NOMEM.
-*/
-static int balance_nonroot(
- MemPage *pParent, /* Parent page of siblings being balanced */
- int iParentIdx, /* Index of "the page" in pParent */
- u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */
- int isRoot, /* True if pParent is a root-page */
- int bBulk /* True if this call is part of a bulk load */
-){
- BtShared *pBt; /* The whole database */
- int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */
- int nNew = 0; /* Number of pages in apNew[] */
- int nOld; /* Number of pages in apOld[] */
- int i, j, k; /* Loop counters */
- int nxDiv; /* Next divider slot in pParent->aCell[] */
- int rc = SQLITE_OK; /* The return code */
- u16 leafCorrection; /* 4 if pPage is a leaf. 0 if not */
- int leafData; /* True if pPage is a leaf of a LEAFDATA tree */
- int usableSpace; /* Bytes in pPage beyond the header */
- int pageFlags; /* Value of pPage->aData[0] */
- int iSpace1 = 0; /* First unused byte of aSpace1[] */
- int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */
- int szScratch; /* Size of scratch memory requested */
- MemPage *apOld[NB]; /* pPage and up to two siblings */
- MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */
- u8 *pRight; /* Location in parent of right-sibling pointer */
- u8 *apDiv[NB-1]; /* Divider cells in pParent */
- int cntNew[NB+2]; /* Index in b.paCell[] of cell after i-th page */
- int cntOld[NB+2]; /* Old index in b.apCell[] */
- int szNew[NB+2]; /* Combined size of cells placed on i-th page */
- u8 *aSpace1; /* Space for copies of dividers cells */
- Pgno pgno; /* Temp var to store a page number in */
- u8 abDone[NB+2]; /* True after i'th new page is populated */
- Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */
- Pgno aPgOrder[NB+2]; /* Copy of aPgno[] used for sorting pages */
- u16 aPgFlags[NB+2]; /* flags field of new pages before shuffling */
- CellArray b; /* Parsed information on cells being balanced */
-
- memset(abDone, 0, sizeof(abDone));
- b.nCell = 0;
- b.apCell = 0;
- pBt = pParent->pBt;
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
-
-#if 0
- TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
-#endif
-
- /* At this point pParent may have at most one overflow cell. And if
- ** this overflow cell is present, it must be the cell with
- ** index iParentIdx. This scenario comes about when this function
- ** is called (indirectly) from sqlite3BtreeDelete().
- */
- assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
- assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );
-
- if( !aOvflSpace ){
- return SQLITE_NOMEM_BKPT;
- }
-
- /* Find the sibling pages to balance. Also locate the cells in pParent
- ** that divide the siblings. An attempt is made to find NN siblings on
- ** either side of pPage. More siblings are taken from one side, however,
- ** if there are fewer than NN siblings on the other side. If pParent
- ** has NB or fewer children then all children of pParent are taken.
- **
- ** This loop also drops the divider cells from the parent page. This
- ** way, the remainder of the function does not have to deal with any
- ** overflow cells in the parent page, since if any existed they will
- ** have already been removed.
- */
- i = pParent->nOverflow + pParent->nCell;
- if( i<2 ){
- nxDiv = 0;
- }else{
- assert( bBulk==0 || bBulk==1 );
- if( iParentIdx==0 ){
- nxDiv = 0;
- }else if( iParentIdx==i ){
- nxDiv = i-2+bBulk;
- }else{
- nxDiv = iParentIdx-1;
- }
- i = 2-bBulk;
- }
- nOld = i+1;
- if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
- pRight = &pParent->aData[pParent->hdrOffset+8];
- }else{
- pRight = findCell(pParent, i+nxDiv-pParent->nOverflow);
- }
- pgno = get4byte(pRight);
- while( 1 ){
- rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
- if( rc ){
- memset(apOld, 0, (i+1)*sizeof(MemPage*));
- goto balance_cleanup;
- }
- nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
- if( (i--)==0 ) break;
-
- if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
- apDiv[i] = pParent->apOvfl[0];
- pgno = get4byte(apDiv[i]);
- szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
- pParent->nOverflow = 0;
- }else{
- apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow);
- pgno = get4byte(apDiv[i]);
- szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
-
- /* Drop the cell from the parent page. apDiv[i] still points to
- ** the cell within the parent, even though it has been dropped.
- ** This is safe because dropping a cell only overwrites the first
- ** four bytes of it, and this function does not need the first
- ** four bytes of the divider cell. So the pointer is safe to use
- ** later on.
- **
- ** But not if we are in secure-delete mode. In secure-delete mode,
- ** the dropCell() routine will overwrite the entire cell with zeroes.
- ** In this case, temporarily copy the cell into the aOvflSpace[]
- ** buffer. It will be copied out again as soon as the aSpace[] buffer
- ** is allocated. */
- if( pBt->btsFlags & BTS_FAST_SECURE ){
- int iOff;
-
- iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
- if( (iOff+szNew[i])>(int)pBt->usableSize ){
- rc = SQLITE_CORRUPT_BKPT;
- memset(apOld, 0, (i+1)*sizeof(MemPage*));
- goto balance_cleanup;
- }else{
- memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
- apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
- }
- }
- dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
- }
- }
-
- /* Make nMaxCells a multiple of 4 in order to preserve 8-byte
- ** alignment */
- nMaxCells = (nMaxCells + 3)&~3;
-
- /*
- ** Allocate space for memory structures
- */
- szScratch =
- nMaxCells*sizeof(u8*) /* b.apCell */
- + nMaxCells*sizeof(u16) /* b.szCell */
- + pBt->pageSize; /* aSpace1 */
-
- assert( szScratch<=6*(int)pBt->pageSize );
- b.apCell = sqlite3StackAllocRaw(0, szScratch );
- if( b.apCell==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto balance_cleanup;
- }
- b.szCell = (u16*)&b.apCell[nMaxCells];
- aSpace1 = (u8*)&b.szCell[nMaxCells];
- assert( EIGHT_BYTE_ALIGNMENT(aSpace1) );
-
- /*
- ** Load pointers to all cells on sibling pages and the divider cells
- ** into the local b.apCell[] array. Make copies of the divider cells
- ** into space obtained from aSpace1[]. The divider cells have already
- ** been removed from pParent.
- **
- ** If the siblings are on leaf pages, then the child pointers of the
- ** divider cells are stripped from the cells before they are copied
- ** into aSpace1[]. In this way, all cells in b.apCell[] are without
- ** child pointers. If siblings are not leaves, then all cell in
- ** b.apCell[] include child pointers. Either way, all cells in b.apCell[]
- ** are alike.
- **
- ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf.
- ** leafData: 1 if pPage holds key+data and pParent holds only keys.
- */
- b.pRef = apOld[0];
- leafCorrection = b.pRef->leaf*4;
- leafData = b.pRef->intKeyLeaf;
- for(i=0; i<nOld; i++){
- MemPage *pOld = apOld[i];
- int limit = pOld->nCell;
- u8 *aData = pOld->aData;
- u16 maskPage = pOld->maskPage;
- u8 *piCell = aData + pOld->cellOffset;
- u8 *piEnd;
-
- /* Verify that all sibling pages are of the same "type" (table-leaf,
- ** table-interior, index-leaf, or index-interior).
- */
- if( pOld->aData[0]!=apOld[0]->aData[0] ){
- rc = SQLITE_CORRUPT_BKPT;
- goto balance_cleanup;
- }
-
- /* Load b.apCell[] with pointers to all cells in pOld. If pOld
- ** contains overflow cells, include them in the b.apCell[] array
- ** in the correct spot.
- **
- ** Note that when there are multiple overflow cells, it is always the
- ** case that they are sequential and adjacent. This invariant arises
- ** because multiple overflows can only occurs when inserting divider
- ** cells into a parent on a prior balance, and divider cells are always
- ** adjacent and are inserted in order. There is an assert() tagged
- ** with "NOTE 1" in the overflow cell insertion loop to prove this
- ** invariant.
- **
- ** This must be done in advance. Once the balance starts, the cell
- ** offset section of the btree page will be overwritten and we will no
- ** long be able to find the cells if a pointer to each cell is not saved
- ** first.
- */
- memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
- if( pOld->nOverflow>0 ){
- limit = pOld->aiOvfl[0];
- for(j=0; j<limit; j++){
- b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell));
- piCell += 2;
- b.nCell++;
- }
- for(k=0; k<pOld->nOverflow; k++){
- assert( k==0 || pOld->aiOvfl[k-1]+1==pOld->aiOvfl[k] );/* NOTE 1 */
- b.apCell[b.nCell] = pOld->apOvfl[k];
- b.nCell++;
- }
- }
- piEnd = aData + pOld->cellOffset + 2*pOld->nCell;
- while( piCell<piEnd ){
- assert( b.nCell<nMaxCells );
- b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell));
- piCell += 2;
- b.nCell++;
- }
-
- cntOld[i] = b.nCell;
- if( i<nOld-1 && !leafData){
- u16 sz = (u16)szNew[i];
- u8 *pTemp;
- assert( b.nCell<nMaxCells );
- b.szCell[b.nCell] = sz;
- pTemp = &aSpace1[iSpace1];
- iSpace1 += sz;
- assert( sz<=pBt->maxLocal+23 );
- assert( iSpace1 <= (int)pBt->pageSize );
- memcpy(pTemp, apDiv[i], sz);
- b.apCell[b.nCell] = pTemp+leafCorrection;
- assert( leafCorrection==0 || leafCorrection==4 );
- b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
- if( !pOld->leaf ){
- assert( leafCorrection==0 );
- assert( pOld->hdrOffset==0 );
- /* The right pointer of the child page pOld becomes the left
- ** pointer of the divider cell */
- memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
- }else{
- assert( leafCorrection==4 );
- while( b.szCell[b.nCell]<4 ){
- /* Do not allow any cells smaller than 4 bytes. If a smaller cell
- ** does exist, pad it with 0x00 bytes. */
- assert( b.szCell[b.nCell]==3 || CORRUPT_DB );
- assert( b.apCell[b.nCell]==&aSpace1[iSpace1-3] || CORRUPT_DB );
- aSpace1[iSpace1++] = 0x00;
- b.szCell[b.nCell]++;
- }
- }
- b.nCell++;
- }
- }
-
- /*
- ** Figure out the number of pages needed to hold all b.nCell cells.
- ** Store this number in "k". Also compute szNew[] which is the total
- ** size of all cells on the i-th page and cntNew[] which is the index
- ** in b.apCell[] of the cell that divides page i from page i+1.
- ** cntNew[k] should equal b.nCell.
- **
- ** Values computed by this block:
- **
- ** k: The total number of sibling pages
- ** szNew[i]: Spaced used on the i-th sibling page.
- ** cntNew[i]: Index in b.apCell[] and b.szCell[] for the first cell to
- ** the right of the i-th sibling page.
- ** usableSpace: Number of bytes of space available on each sibling.
- **
- */
- usableSpace = pBt->usableSize - 12 + leafCorrection;
- for(i=0; i<nOld; i++){
- MemPage *p = apOld[i];
- szNew[i] = usableSpace - p->nFree;
- for(j=0; j<p->nOverflow; j++){
- szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
- }
- cntNew[i] = cntOld[i];
- }
- k = nOld;
- for(i=0; i<k; i++){
- int sz;
- while( szNew[i]>usableSpace ){
- if( i+1>=k ){
- k = i+2;
- if( k>NB+2 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
- szNew[k-1] = 0;
- cntNew[k-1] = b.nCell;
- }
- sz = 2 + cachedCellSize(&b, cntNew[i]-1);
- szNew[i] -= sz;
- if( !leafData ){
- if( cntNew[i]<b.nCell ){
- sz = 2 + cachedCellSize(&b, cntNew[i]);
- }else{
- sz = 0;
- }
- }
- szNew[i+1] += sz;
- cntNew[i]--;
- }
- while( cntNew[i]<b.nCell ){
- sz = 2 + cachedCellSize(&b, cntNew[i]);
- if( szNew[i]+sz>usableSpace ) break;
- szNew[i] += sz;
- cntNew[i]++;
- if( !leafData ){
- if( cntNew[i]<b.nCell ){
- sz = 2 + cachedCellSize(&b, cntNew[i]);
- }else{
- sz = 0;
- }
- }
- szNew[i+1] -= sz;
- }
- if( cntNew[i]>=b.nCell ){
- k = i+1;
- }else if( cntNew[i] <= (i>0 ? cntNew[i-1] : 0) ){
- rc = SQLITE_CORRUPT_BKPT;
- goto balance_cleanup;
- }
- }
-
- /*
- ** The packing computed by the previous block is biased toward the siblings
- ** on the left side (siblings with smaller keys). The left siblings are
- ** always nearly full, while the right-most sibling might be nearly empty.
- ** The next block of code attempts to adjust the packing of siblings to
- ** get a better balance.
- **
- ** This adjustment is more than an optimization. The packing above might
- ** be so out of balance as to be illegal. For example, the right-most
- ** sibling might be completely empty. This adjustment is not optional.
- */
- for(i=k-1; i>0; i--){
- int szRight = szNew[i]; /* Size of sibling on the right */
- int szLeft = szNew[i-1]; /* Size of sibling on the left */
- int r; /* Index of right-most cell in left sibling */
- int d; /* Index of first cell to the left of right sibling */
-
- r = cntNew[i-1] - 1;
- d = r + 1 - leafData;
- (void)cachedCellSize(&b, d);
- do{
- assert( d<nMaxCells );
- assert( r<nMaxCells );
- (void)cachedCellSize(&b, r);
- if( szRight!=0
- && (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+(i==k-1?0:2)))){
- break;
- }
- szRight += b.szCell[d] + 2;
- szLeft -= b.szCell[r] + 2;
- cntNew[i-1] = r;
- r--;
- d--;
- }while( r>=0 );
- szNew[i] = szRight;
- szNew[i-1] = szLeft;
- if( cntNew[i-1] <= (i>1 ? cntNew[i-2] : 0) ){
- rc = SQLITE_CORRUPT_BKPT;
- goto balance_cleanup;
- }
- }
-
- /* Sanity check: For a non-corrupt database file one of the follwing
- ** must be true:
- ** (1) We found one or more cells (cntNew[0])>0), or
- ** (2) pPage is a virtual root page. A virtual root page is when
- ** the real root page is page 1 and we are the only child of
- ** that page.
- */
- assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || CORRUPT_DB);
- TRACE(("BALANCE: old: %d(nc=%d) %d(nc=%d) %d(nc=%d)\n",
- apOld[0]->pgno, apOld[0]->nCell,
- nOld>=2 ? apOld[1]->pgno : 0, nOld>=2 ? apOld[1]->nCell : 0,
- nOld>=3 ? apOld[2]->pgno : 0, nOld>=3 ? apOld[2]->nCell : 0
- ));
-
- /*
- ** Allocate k new pages. Reuse old pages where possible.
- */
- pageFlags = apOld[0]->aData[0];
- for(i=0; i<k; i++){
- MemPage *pNew;
- if( i<nOld ){
- pNew = apNew[i] = apOld[i];
- apOld[i] = 0;
- rc = sqlite3PagerWrite(pNew->pDbPage);
- nNew++;
- if( rc ) goto balance_cleanup;
- }else{
- assert( i>0 );
- rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
- if( rc ) goto balance_cleanup;
- zeroPage(pNew, pageFlags);
- apNew[i] = pNew;
- nNew++;
- cntOld[i] = b.nCell;
-
- /* Set the pointer-map entry for the new sibling page. */
- if( ISAUTOVACUUM ){
- ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc);
- if( rc!=SQLITE_OK ){
- goto balance_cleanup;
- }
- }
- }
- }
-
- /*
- ** Reassign page numbers so that the new pages are in ascending order.
- ** This helps to keep entries in the disk file in order so that a scan
- ** of the table is closer to a linear scan through the file. That in turn
- ** helps the operating system to deliver pages from the disk more rapidly.
- **
- ** An O(n^2) insertion sort algorithm is used, but since n is never more
- ** than (NB+2) (a small constant), that should not be a problem.
- **
- ** When NB==3, this one optimization makes the database about 25% faster
- ** for large insertions and deletions.
- */
- for(i=0; i<nNew; i++){
- aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
- aPgFlags[i] = apNew[i]->pDbPage->flags;
- for(j=0; j<i; j++){
- if( aPgno[j]==aPgno[i] ){
- /* This branch is taken if the set of sibling pages somehow contains
- ** duplicate entries. This can happen if the database is corrupt.
- ** It would be simpler to detect this as part of the loop below, but
- ** we do the detection here in order to avoid populating the pager
- ** cache with two separate objects associated with the same
- ** page number. */
- assert( CORRUPT_DB );
- rc = SQLITE_CORRUPT_BKPT;
- goto balance_cleanup;
- }
- }
- }
- for(i=0; i<nNew; i++){
- int iBest = 0; /* aPgno[] index of page number to use */
- for(j=1; j<nNew; j++){
- if( aPgOrder[j]<aPgOrder[iBest] ) iBest = j;
- }
- pgno = aPgOrder[iBest];
- aPgOrder[iBest] = 0xffffffff;
- if( iBest!=i ){
- if( iBest>i ){
- sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0);
- }
- sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]);
- apNew[i]->pgno = pgno;
- }
- }
-
- TRACE(("BALANCE: new: %d(%d nc=%d) %d(%d nc=%d) %d(%d nc=%d) "
- "%d(%d nc=%d) %d(%d nc=%d)\n",
- apNew[0]->pgno, szNew[0], cntNew[0],
- nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0,
- nNew>=2 ? cntNew[1] - cntNew[0] - !leafData : 0,
- nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0,
- nNew>=3 ? cntNew[2] - cntNew[1] - !leafData : 0,
- nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0,
- nNew>=4 ? cntNew[3] - cntNew[2] - !leafData : 0,
- nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0,
- nNew>=5 ? cntNew[4] - cntNew[3] - !leafData : 0
- ));
-
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
- put4byte(pRight, apNew[nNew-1]->pgno);
-
- /* If the sibling pages are not leaves, ensure that the right-child pointer
- ** of the right-most new sibling page is set to the value that was
- ** originally in the same field of the right-most old sibling page. */
- if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){
- MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1];
- memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4);
- }
-
- /* Make any required updates to pointer map entries associated with
- ** cells stored on sibling pages following the balance operation. Pointer
- ** map entries associated with divider cells are set by the insertCell()
- ** routine. The associated pointer map entries are:
- **
- ** a) if the cell contains a reference to an overflow chain, the
- ** entry associated with the first page in the overflow chain, and
- **
- ** b) if the sibling pages are not leaves, the child page associated
- ** with the cell.
- **
- ** If the sibling pages are not leaves, then the pointer map entry
- ** associated with the right-child of each sibling may also need to be
- ** updated. This happens below, after the sibling pages have been
- ** populated, not here.
- */
- if( ISAUTOVACUUM ){
- MemPage *pNew = apNew[0];
- u8 *aOld = pNew->aData;
- int cntOldNext = pNew->nCell + pNew->nOverflow;
- int usableSize = pBt->usableSize;
- int iNew = 0;
- int iOld = 0;
-
- for(i=0; i<b.nCell; i++){
- u8 *pCell = b.apCell[i];
- if( i==cntOldNext ){
- MemPage *pOld = (++iOld)<nNew ? apNew[iOld] : apOld[iOld];
- cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;
- aOld = pOld->aData;
- }
- if( i==cntNew[iNew] ){
- pNew = apNew[++iNew];
- if( !leafData ) continue;
- }
-
- /* Cell pCell is destined for new sibling page pNew. Originally, it
- ** was either part of sibling page iOld (possibly an overflow cell),
- ** or else the divider cell to the left of sibling page iOld. So,
- ** if sibling page iOld had the same page number as pNew, and if
- ** pCell really was a part of sibling page iOld (not a divider or
- ** overflow cell), we can skip updating the pointer map entries. */
- if( iOld>=nNew
- || pNew->pgno!=aPgno[iOld]
- || !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize])
- ){
- if( !leafCorrection ){
- ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
- }
- if( cachedCellSize(&b,i)>pNew->minLocal ){
- ptrmapPutOvflPtr(pNew, pCell, &rc);
- }
- if( rc ) goto balance_cleanup;
- }
- }
- }
-
- /* Insert new divider cells into pParent. */
- for(i=0; i<nNew-1; i++){
- u8 *pCell;
- u8 *pTemp;
- int sz;
- MemPage *pNew = apNew[i];
- j = cntNew[i];
-
- assert( j<nMaxCells );
- assert( b.apCell[j]!=0 );
- pCell = b.apCell[j];
- sz = b.szCell[j] + leafCorrection;
- pTemp = &aOvflSpace[iOvflSpace];
- if( !pNew->leaf ){
- memcpy(&pNew->aData[8], pCell, 4);
- }else if( leafData ){
- /* If the tree is a leaf-data tree, and the siblings are leaves,
- ** then there is no divider cell in b.apCell[]. Instead, the divider
- ** cell consists of the integer key for the right-most cell of
- ** the sibling-page assembled above only.
- */
- CellInfo info;
- j--;
- pNew->xParseCell(pNew, b.apCell[j], &info);
- pCell = pTemp;
- sz = 4 + putVarint(&pCell[4], info.nKey);
- pTemp = 0;
- }else{
- pCell -= 4;
- /* Obscure case for non-leaf-data trees: If the cell at pCell was
- ** previously stored on a leaf node, and its reported size was 4
- ** bytes, then it may actually be smaller than this
- ** (see btreeParseCellPtr(), 4 bytes is the minimum size of
- ** any cell). But it is important to pass the correct size to
- ** insertCell(), so reparse the cell now.
- **
- ** This can only happen for b-trees used to evaluate "IN (SELECT ...)"
- ** and WITHOUT ROWID tables with exactly one column which is the
- ** primary key.
- */
- if( b.szCell[j]==4 ){
- assert(leafCorrection==4);
- sz = pParent->xCellSize(pParent, pCell);
- }
- }
- iOvflSpace += sz;
- assert( sz<=pBt->maxLocal+23 );
- assert( iOvflSpace <= (int)pBt->pageSize );
- insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
- if( rc!=SQLITE_OK ) goto balance_cleanup;
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
- }
-
- /* Now update the actual sibling pages. The order in which they are updated
- ** is important, as this code needs to avoid disrupting any page from which
- ** cells may still to be read. In practice, this means:
- **
- ** (1) If cells are moving left (from apNew[iPg] to apNew[iPg-1])
- ** then it is not safe to update page apNew[iPg] until after
- ** the left-hand sibling apNew[iPg-1] has been updated.
- **
- ** (2) If cells are moving right (from apNew[iPg] to apNew[iPg+1])
- ** then it is not safe to update page apNew[iPg] until after
- ** the right-hand sibling apNew[iPg+1] has been updated.
- **
- ** If neither of the above apply, the page is safe to update.
- **
- ** The iPg value in the following loop starts at nNew-1 goes down
- ** to 0, then back up to nNew-1 again, thus making two passes over
- ** the pages. On the initial downward pass, only condition (1) above
- ** needs to be tested because (2) will always be true from the previous
- ** step. On the upward pass, both conditions are always true, so the
- ** upwards pass simply processes pages that were missed on the downward
- ** pass.
- */
- for(i=1-nNew; i<nNew; i++){
- int iPg = i<0 ? -i : i;
- assert( iPg>=0 && iPg<nNew );
- if( abDone[iPg] ) continue; /* Skip pages already processed */
- if( i>=0 /* On the upwards pass, or... */
- || cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */
- ){
- int iNew;
- int iOld;
- int nNewCell;
-
- /* Verify condition (1): If cells are moving left, update iPg
- ** only after iPg-1 has already been updated. */
- assert( iPg==0 || cntOld[iPg-1]>=cntNew[iPg-1] || abDone[iPg-1] );
-
- /* Verify condition (2): If cells are moving right, update iPg
- ** only after iPg+1 has already been updated. */
- assert( cntNew[iPg]>=cntOld[iPg] || abDone[iPg+1] );
-
- if( iPg==0 ){
- iNew = iOld = 0;
- nNewCell = cntNew[0];
- }else{
- iOld = iPg<nOld ? (cntOld[iPg-1] + !leafData) : b.nCell;
- iNew = cntNew[iPg-1] + !leafData;
- nNewCell = cntNew[iPg] - iNew;
- }
-
- rc = editPage(apNew[iPg], iOld, iNew, nNewCell, &b);
- if( rc ) goto balance_cleanup;
- abDone[iPg]++;
- apNew[iPg]->nFree = usableSpace-szNew[iPg];
- assert( apNew[iPg]->nOverflow==0 );
- assert( apNew[iPg]->nCell==nNewCell );
- }
- }
-
- /* All pages have been processed exactly once */
- assert( memcmp(abDone, "\01\01\01\01\01", nNew)==0 );
-
- assert( nOld>0 );
- assert( nNew>0 );
-
- if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){
- /* The root page of the b-tree now contains no cells. The only sibling
- ** page is the right-child of the parent. Copy the contents of the
- ** child page into the parent, decreasing the overall height of the
- ** b-tree structure by one. This is described as the "balance-shallower"
- ** sub-algorithm in some documentation.
- **
- ** If this is an auto-vacuum database, the call to copyNodeContent()
- ** sets all pointer-map entries corresponding to database image pages
- ** for which the pointer is stored within the content being copied.
- **
- ** It is critical that the child page be defragmented before being
- ** copied into the parent, because if the parent is page 1 then it will
- ** by smaller than the child due to the database header, and so all the
- ** free space needs to be up front.
- */
- assert( nNew==1 || CORRUPT_DB );
- rc = defragmentPage(apNew[0], -1);
- testcase( rc!=SQLITE_OK );
- assert( apNew[0]->nFree ==
- (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
- || rc!=SQLITE_OK
- );
- copyNodeContent(apNew[0], pParent, &rc);
- freePage(apNew[0], &rc);
- }else if( ISAUTOVACUUM && !leafCorrection ){
- /* Fix the pointer map entries associated with the right-child of each
- ** sibling page. All other pointer map entries have already been taken
- ** care of. */
- for(i=0; i<nNew; i++){
- u32 key = get4byte(&apNew[i]->aData[8]);
- ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc);
- }
- }
-
- assert( pParent->isInit );
- TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n",
- nOld, nNew, b.nCell));
-
- /* Free any old pages that were not reused as new pages.
- */
- for(i=nNew; i<nOld; i++){
- freePage(apOld[i], &rc);
- }
-
-#if 0
- if( ISAUTOVACUUM && rc==SQLITE_OK && apNew[0]->isInit ){
- /* The ptrmapCheckPages() contains assert() statements that verify that
- ** all pointer map pages are set correctly. This is helpful while
- ** debugging. This is usually disabled because a corrupt database may
- ** cause an assert() statement to fail. */
- ptrmapCheckPages(apNew, nNew);
- ptrmapCheckPages(&pParent, 1);
- }
-#endif
-
- /*
- ** Cleanup before returning.
- */
-balance_cleanup:
- sqlite3StackFree(0, b.apCell);
- for(i=0; i<nOld; i++){
- releasePage(apOld[i]);
- }
- for(i=0; i<nNew; i++){
- releasePage(apNew[i]);
- }
-
- return rc;
-}
-
-
-/*
-** This function is called when the root page of a b-tree structure is
-** overfull (has one or more overflow pages).
-**
-** A new child page is allocated and the contents of the current root
-** page, including overflow cells, are copied into the child. The root
-** page is then overwritten to make it an empty page with the right-child
-** pointer pointing to the new page.
-**
-** Before returning, all pointer-map entries corresponding to pages
-** that the new child-page now contains pointers to are updated. The
-** entry corresponding to the new right-child pointer of the root
-** page is also updated.
-**
-** If successful, *ppChild is set to contain a reference to the child
-** page and SQLITE_OK is returned. In this case the caller is required
-** to call releasePage() on *ppChild exactly once. If an error occurs,
-** an error code is returned and *ppChild is set to 0.
-*/
-static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
- int rc; /* Return value from subprocedures */
- MemPage *pChild = 0; /* Pointer to a new child page */
- Pgno pgnoChild = 0; /* Page number of the new child page */
- BtShared *pBt = pRoot->pBt; /* The BTree */
-
- assert( pRoot->nOverflow>0 );
- assert( sqlite3_mutex_held(pBt->mutex) );
-
- /* Make pRoot, the root page of the b-tree, writable. Allocate a new
- ** page that will become the new right-child of pPage. Copy the contents
- ** of the node stored on pRoot into the new child page.
- */
- rc = sqlite3PagerWrite(pRoot->pDbPage);
- if( rc==SQLITE_OK ){
- rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
- copyNodeContent(pRoot, pChild, &rc);
- if( ISAUTOVACUUM ){
- ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc);
- }
- }
- if( rc ){
- *ppChild = 0;
- releasePage(pChild);
- return rc;
- }
- assert( sqlite3PagerIswriteable(pChild->pDbPage) );
- assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
- assert( pChild->nCell==pRoot->nCell );
-
- TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));
-
- /* Copy the overflow cells from pRoot to pChild */
- memcpy(pChild->aiOvfl, pRoot->aiOvfl,
- pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
- memcpy(pChild->apOvfl, pRoot->apOvfl,
- pRoot->nOverflow*sizeof(pRoot->apOvfl[0]));
- pChild->nOverflow = pRoot->nOverflow;
-
- /* Zero the contents of pRoot. Then install pChild as the right-child. */
- zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF);
- put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);
-
- *ppChild = pChild;
- return SQLITE_OK;
-}
-
-/*
-** The page that pCur currently points to has just been modified in
-** some way. This function figures out if this modification means the
-** tree needs to be balanced, and if so calls the appropriate balancing
-** routine. Balancing routines are:
-**
-** balance_quick()
-** balance_deeper()
-** balance_nonroot()
-*/
-static int balance(BtCursor *pCur){
- int rc = SQLITE_OK;
- const int nMin = pCur->pBt->usableSize * 2 / 3;
- u8 aBalanceQuickSpace[13];
- u8 *pFree = 0;
-
- VVA_ONLY( int balance_quick_called = 0 );
- VVA_ONLY( int balance_deeper_called = 0 );
-
- do {
- int iPage = pCur->iPage;
- MemPage *pPage = pCur->pPage;
-
- if( iPage==0 ){
- if( pPage->nOverflow ){
- /* The root page of the b-tree is overfull. In this case call the
- ** balance_deeper() function to create a new child for the root-page
- ** and copy the current contents of the root-page to it. The
- ** next iteration of the do-loop will balance the child page.
- */
- assert( balance_deeper_called==0 );
- VVA_ONLY( balance_deeper_called++ );
- rc = balance_deeper(pPage, &pCur->apPage[1]);
- if( rc==SQLITE_OK ){
- pCur->iPage = 1;
- pCur->ix = 0;
- pCur->aiIdx[0] = 0;
- pCur->apPage[0] = pPage;
- pCur->pPage = pCur->apPage[1];
- assert( pCur->pPage->nOverflow );
- }
- }else{
- break;
- }
- }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
- break;
- }else{
- MemPage * const pParent = pCur->apPage[iPage-1];
- int const iIdx = pCur->aiIdx[iPage-1];
-
- rc = sqlite3PagerWrite(pParent->pDbPage);
- if( rc==SQLITE_OK ){
-#ifndef SQLITE_OMIT_QUICKBALANCE
- if( pPage->intKeyLeaf
- && pPage->nOverflow==1
- && pPage->aiOvfl[0]==pPage->nCell
- && pParent->pgno!=1
- && pParent->nCell==iIdx
- ){
- /* Call balance_quick() to create a new sibling of pPage on which
- ** to store the overflow cell. balance_quick() inserts a new cell
- ** into pParent, which may cause pParent overflow. If this
- ** happens, the next iteration of the do-loop will balance pParent
- ** use either balance_nonroot() or balance_deeper(). Until this
- ** happens, the overflow cell is stored in the aBalanceQuickSpace[]
- ** buffer.
- **
- ** The purpose of the following assert() is to check that only a
- ** single call to balance_quick() is made for each call to this
- ** function. If this were not verified, a subtle bug involving reuse
- ** of the aBalanceQuickSpace[] might sneak in.
- */
- assert( balance_quick_called==0 );
- VVA_ONLY( balance_quick_called++ );
- rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
- }else
-#endif
- {
- /* In this case, call balance_nonroot() to redistribute cells
- ** between pPage and up to 2 of its sibling pages. This involves
- ** modifying the contents of pParent, which may cause pParent to
- ** become overfull or underfull. The next iteration of the do-loop
- ** will balance the parent page to correct this.
- **
- ** If the parent page becomes overfull, the overflow cell or cells
- ** are stored in the pSpace buffer allocated immediately below.
- ** A subsequent iteration of the do-loop will deal with this by
- ** calling balance_nonroot() (balance_deeper() may be called first,
- ** but it doesn't deal with overflow cells - just moves them to a
- ** different page). Once this subsequent call to balance_nonroot()
- ** has completed, it is safe to release the pSpace buffer used by
- ** the previous call, as the overflow cell data will have been
- ** copied either into the body of a database page or into the new
- ** pSpace buffer passed to the latter call to balance_nonroot().
- */
- u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
- rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1,
- pCur->hints&BTREE_BULKLOAD);
- if( pFree ){
- /* If pFree is not NULL, it points to the pSpace buffer used
- ** by a previous call to balance_nonroot(). Its contents are
- ** now stored either on real database pages or within the
- ** new pSpace buffer, so it may be safely freed here. */
- sqlite3PageFree(pFree);
- }
-
- /* The pSpace buffer will be freed after the next call to
- ** balance_nonroot(), or just before this function returns, whichever
- ** comes first. */
- pFree = pSpace;
- }
- }
-
- pPage->nOverflow = 0;
-
- /* The next iteration of the do-loop balances the parent page. */
- releasePage(pPage);
- pCur->iPage--;
- assert( pCur->iPage>=0 );
- pCur->pPage = pCur->apPage[pCur->iPage];
- }
- }while( rc==SQLITE_OK );
-
- if( pFree ){
- sqlite3PageFree(pFree);
- }
- return rc;
-}
-
-/* Overwrite content from pX into pDest. Only do the write if the
-** content is different from what is already there.
-*/
-static int btreeOverwriteContent(
- MemPage *pPage, /* MemPage on which writing will occur */
- u8 *pDest, /* Pointer to the place to start writing */
- const BtreePayload *pX, /* Source of data to write */
- int iOffset, /* Offset of first byte to write */
- int iAmt /* Number of bytes to be written */
-){
- int nData = pX->nData - iOffset;
- if( nData<=0 ){
- /* Overwritting with zeros */
- int i;
- for(i=0; i<iAmt && pDest[i]==0; i++){}
- if( i<iAmt ){
- int rc = sqlite3PagerWrite(pPage->pDbPage);
- if( rc ) return rc;
- memset(pDest + i, 0, iAmt - i);
- }
- }else{
- if( nData<iAmt ){
- /* Mixed read data and zeros at the end. Make a recursive call
- ** to write the zeros then fall through to write the real data */
- int rc = btreeOverwriteContent(pPage, pDest+nData, pX, iOffset+nData,
- iAmt-nData);
- if( rc ) return rc;
- iAmt = nData;
- }
- if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
- int rc = sqlite3PagerWrite(pPage->pDbPage);
- if( rc ) return rc;
- memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Overwrite the cell that cursor pCur is pointing to with fresh content
-** contained in pX.
-*/
-static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
- int iOffset; /* Next byte of pX->pData to write */
- int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
- int rc; /* Return code */
- MemPage *pPage = pCur->pPage; /* Page being written */
- BtShared *pBt; /* Btree */
- Pgno ovflPgno; /* Next overflow page to write */
- u32 ovflPageSize; /* Size to write on overflow page */
-
- if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
- return SQLITE_CORRUPT_BKPT;
- }
- /* Overwrite the local portion first */
- rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
- 0, pCur->info.nLocal);
- if( rc ) return rc;
- if( pCur->info.nLocal==nTotal ) return SQLITE_OK;
-
- /* Now overwrite the overflow pages */
- iOffset = pCur->info.nLocal;
- assert( nTotal>=0 );
- assert( iOffset>=0 );
- ovflPgno = get4byte(pCur->info.pPayload + iOffset);
- pBt = pPage->pBt;
- ovflPageSize = pBt->usableSize - 4;
- do{
- rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
- if( rc ) return rc;
- if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- if( iOffset+ovflPageSize<(u32)nTotal ){
- ovflPgno = get4byte(pPage->aData);
- }else{
- ovflPageSize = nTotal - iOffset;
- }
- rc = btreeOverwriteContent(pPage, pPage->aData+4, pX,
- iOffset, ovflPageSize);
- }
- sqlite3PagerUnref(pPage->pDbPage);
- if( rc ) return rc;
- iOffset += ovflPageSize;
- }while( iOffset<nTotal );
- return SQLITE_OK;
-}
-
-
-/*
-** Insert a new record into the BTree. The content of the new record
-** is described by the pX object. The pCur cursor is used only to
-** define what table the record should be inserted into, and is left
-** pointing at a random location.
-**
-** For a table btree (used for rowid tables), only the pX.nKey value of
-** the key is used. The pX.pKey value must be NULL. The pX.nKey is the
-** rowid or INTEGER PRIMARY KEY of the row. The pX.nData,pData,nZero fields
-** hold the content of the row.
-**
-** For an index btree (used for indexes and WITHOUT ROWID tables), the
-** key is an arbitrary byte sequence stored in pX.pKey,nKey. The
-** pX.pData,nData,nZero fields must be zero.
-**
-** If the seekResult parameter is non-zero, then a successful call to
-** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already
-** been performed. In other words, if seekResult!=0 then the cursor
-** is currently pointing to a cell that will be adjacent to the cell
-** to be inserted. If seekResult<0 then pCur points to a cell that is
-** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell
-** that is larger than (pKey,nKey).
-**
-** If seekResult==0, that means pCur is pointing at some unknown location.
-** In that case, this routine must seek the cursor to the correct insertion
-** point for (pKey,nKey) before doing the insertion. For index btrees,
-** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked
-** key values and pX->aMem can be used instead of pX->pKey to avoid having
-** to decode the key.
-*/
-int sqlite3BtreeInsert(
- BtCursor *pCur, /* Insert data into the table of this cursor */
- const BtreePayload *pX, /* Content of the row to be inserted */
- int flags, /* True if this is likely an append */
- int seekResult /* Result of prior MovetoUnpacked() call */
-){
- int rc;
- int loc = seekResult; /* -1: before desired location +1: after */
- int szNew = 0;
- int idx;
- MemPage *pPage;
- Btree *p = pCur->pBtree;
- BtShared *pBt = p->pBt;
- unsigned char *oldCell;
- unsigned char *newCell = 0;
-
- assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
-
- if( pCur->eState==CURSOR_FAULT ){
- assert( pCur->skipNext!=SQLITE_OK );
- return pCur->skipNext;
- }
-
- assert( cursorOwnsBtShared(pCur) );
- assert( (pCur->curFlags & BTCF_WriteFlag)!=0
- && pBt->inTransaction==TRANS_WRITE
- && (pBt->btsFlags & BTS_READ_ONLY)==0 );
- assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
-
- /* Assert that the caller has been consistent. If this cursor was opened
- ** expecting an index b-tree, then the caller should be inserting blob
- ** keys with no associated data. If the cursor was opened expecting an
- ** intkey table, the caller should be inserting integer keys with a
- ** blob of associated data. */
- assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
-
- /* Save the positions of any other cursors open on this table.
- **
- ** In some cases, the call to btreeMoveto() below is a no-op. For
- ** example, when inserting data into a table with auto-generated integer
- ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
- ** integer key to use. It then calls this function to actually insert the
- ** data into the intkey B-Tree. In this case btreeMoveto() recognizes
- ** that the cursor is already where it needs to be and returns without
- ** doing any work. To avoid thwarting these optimizations, it is important
- ** not to clear the cursor here.
- */
- if( pCur->curFlags & BTCF_Multiple ){
- rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
- if( rc ) return rc;
- }
-
- if( pCur->pKeyInfo==0 ){
- assert( pX->pKey==0 );
- /* If this is an insert into a table b-tree, invalidate any incrblob
- ** cursors open on the row being replaced */
- invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
-
- /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
- ** to a row with the same key as the new entry being inserted.
- */
-#ifdef SQLITE_DEBUG
- if( flags & BTREE_SAVEPOSITION ){
- assert( pCur->curFlags & BTCF_ValidNKey );
- assert( pX->nKey==pCur->info.nKey );
- assert( pCur->info.nSize!=0 );
- assert( loc==0 );
- }
-#endif
-
- /* On the other hand, BTREE_SAVEPOSITION==0 does not imply
- ** that the cursor is not pointing to a row to be overwritten.
- ** So do a complete check.
- */
- if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){
- /* The cursor is pointing to the entry that is to be
- ** overwritten */
- assert( pX->nData>=0 && pX->nZero>=0 );
- if( pCur->info.nSize!=0
- && pCur->info.nPayload==(u32)pX->nData+pX->nZero
- ){
- /* New entry is the same size as the old. Do an overwrite */
- return btreeOverwriteCell(pCur, pX);
- }
- assert( loc==0 );
- }else if( loc==0 ){
- /* The cursor is *not* pointing to the cell to be overwritten, nor
- ** to an adjacent cell. Move the cursor so that it is pointing either
- ** to the cell to be overwritten or an adjacent cell.
- */
- rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
- if( rc ) return rc;
- }
- }else{
- /* This is an index or a WITHOUT ROWID table */
-
- /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
- ** to a row with the same key as the new entry being inserted.
- */
- assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 );
-
- /* If the cursor is not already pointing either to the cell to be
- ** overwritten, or if a new cell is being inserted, if the cursor is
- ** not pointing to an immediately adjacent cell, then move the cursor
- ** so that it does.
- */
- if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
- if( pX->nMem ){
- UnpackedRecord r;
- r.pKeyInfo = pCur->pKeyInfo;
- r.aMem = pX->aMem;
- r.nField = pX->nMem;
- r.default_rc = 0;
- r.errCode = 0;
- r.r1 = 0;
- r.r2 = 0;
- r.eqSeen = 0;
- rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
- }else{
- rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
- }
- if( rc ) return rc;
- }
-
- /* If the cursor is currently pointing to an entry to be overwritten
- ** and the new content is the same as as the old, then use the
- ** overwrite optimization.
- */
- if( loc==0 ){
- getCellInfo(pCur);
- if( pCur->info.nKey==pX->nKey ){
- BtreePayload x2;
- x2.pData = pX->pKey;
- x2.nData = pX->nKey;
- x2.nZero = 0;
- return btreeOverwriteCell(pCur, &x2);
- }
- }
-
- }
- assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
-
- pPage = pCur->pPage;
- assert( pPage->intKey || pX->nKey>=0 );
- assert( pPage->leaf || !pPage->intKey );
-
- TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
- pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
- loc==0 ? "overwrite" : "new entry"));
- assert( pPage->isInit );
- newCell = pBt->pTmpSpace;
- assert( newCell!=0 );
- rc = fillInCell(pPage, newCell, pX, &szNew);
- if( rc ) goto end_insert;
- assert( szNew==pPage->xCellSize(pPage, newCell) );
- assert( szNew <= MX_CELL_SIZE(pBt) );
- idx = pCur->ix;
- if( loc==0 ){
- CellInfo info;
- assert( idx<pPage->nCell );
- rc = sqlite3PagerWrite(pPage->pDbPage);
- if( rc ){
- goto end_insert;
- }
- oldCell = findCell(pPage, idx);
- if( !pPage->leaf ){
- memcpy(newCell, oldCell, 4);
- }
- rc = clearCell(pPage, oldCell, &info);
- if( info.nSize==szNew && info.nLocal==info.nPayload
- && (!ISAUTOVACUUM || szNew<pPage->minLocal)
- ){
- /* Overwrite the old cell with the new if they are the same size.
- ** We could also try to do this if the old cell is smaller, then add
- ** the leftover space to the free list. But experiments show that
- ** doing that is no faster then skipping this optimization and just
- ** calling dropCell() and insertCell().
- **
- ** This optimization cannot be used on an autovacuum database if the
- ** new entry uses overflow pages, as the insertCell() call below is
- ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
- assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
- if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
- memcpy(oldCell, newCell, szNew);
- return SQLITE_OK;
- }
- dropCell(pPage, idx, info.nSize, &rc);
- if( rc ) goto end_insert;
- }else if( loc<0 && pPage->nCell>0 ){
- assert( pPage->leaf );
- idx = ++pCur->ix;
- pCur->curFlags &= ~BTCF_ValidNKey;
- }else{
- assert( pPage->leaf );
- }
- insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
- assert( pPage->nOverflow==0 || rc==SQLITE_OK );
- assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
-
- /* If no error has occurred and pPage has an overflow cell, call balance()
- ** to redistribute the cells within the tree. Since balance() may move
- ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
- ** variables.
- **
- ** Previous versions of SQLite called moveToRoot() to move the cursor
- ** back to the root page as balance() used to invalidate the contents
- ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that,
- ** set the cursor state to "invalid". This makes common insert operations
- ** slightly faster.
- **
- ** There is a subtle but important optimization here too. When inserting
- ** multiple records into an intkey b-tree using a single cursor (as can
- ** happen while processing an "INSERT INTO ... SELECT" statement), it
- ** is advantageous to leave the cursor pointing to the last entry in
- ** the b-tree if possible. If the cursor is left pointing to the last
- ** entry in the table, and the next row inserted has an integer key
- ** larger than the largest existing key, it is possible to insert the
- ** row without seeking the cursor. This can be a big performance boost.
- */
- pCur->info.nSize = 0;
- if( pPage->nOverflow ){
- assert( rc==SQLITE_OK );
- pCur->curFlags &= ~(BTCF_ValidNKey);
- rc = balance(pCur);
-
- /* Must make sure nOverflow is reset to zero even if the balance()
- ** fails. Internal data structure corruption will result otherwise.
- ** Also, set the cursor state to invalid. This stops saveCursorPosition()
- ** from trying to save the current position of the cursor. */
- pCur->pPage->nOverflow = 0;
- pCur->eState = CURSOR_INVALID;
- if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){
- btreeReleaseAllCursorPages(pCur);
- if( pCur->pKeyInfo ){
- assert( pCur->pKey==0 );
- pCur->pKey = sqlite3Malloc( pX->nKey );
- if( pCur->pKey==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memcpy(pCur->pKey, pX->pKey, pX->nKey);
- }
- }
- pCur->eState = CURSOR_REQUIRESEEK;
- pCur->nKey = pX->nKey;
- }
- }
- assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 );
-
-end_insert:
- return rc;
-}
-
-/*
-** Delete the entry that the cursor is pointing to.
-**
-** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
-** the cursor is left pointing at an arbitrary location after the delete.
-** But if that bit is set, then the cursor is left in a state such that
-** the next call to BtreeNext() or BtreePrev() moves it to the same row
-** as it would have been on if the call to BtreeDelete() had been omitted.
-**
-** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes
-** associated with a single table entry and its indexes. Only one of those
-** deletes is considered the "primary" delete. The primary delete occurs
-** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete
-** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag.
-** The BTREE_AUXDELETE bit is a hint that is not used by this implementation,
-** but which might be used by alternative storage engines.
-*/
-int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
- Btree *p = pCur->pBtree;
- BtShared *pBt = p->pBt;
- int rc; /* Return code */
- MemPage *pPage; /* Page to delete cell from */
- unsigned char *pCell; /* Pointer to cell to delete */
- int iCellIdx; /* Index of cell to delete */
- int iCellDepth; /* Depth of node containing pCell */
- CellInfo info; /* Size of the cell being deleted */
- int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
- u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
-
- assert( cursorOwnsBtShared(pCur) );
- assert( pBt->inTransaction==TRANS_WRITE );
- assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
- assert( pCur->curFlags & BTCF_WriteFlag );
- assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
- assert( !hasReadConflicts(p, pCur->pgnoRoot) );
- assert( pCur->ix<pCur->pPage->nCell );
- assert( pCur->eState==CURSOR_VALID );
- assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
-
- iCellDepth = pCur->iPage;
- iCellIdx = pCur->ix;
- pPage = pCur->pPage;
- pCell = findCell(pPage, iCellIdx);
-
- /* If the bPreserve flag is set to true, then the cursor position must
- ** be preserved following this delete operation. If the current delete
- ** will cause a b-tree rebalance, then this is done by saving the cursor
- ** key and leaving the cursor in CURSOR_REQUIRESEEK state before
- ** returning.
- **
- ** Or, if the current delete will not cause a rebalance, then the cursor
- ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
- ** before or after the deleted entry. In this case set bSkipnext to true. */
- if( bPreserve ){
- if( !pPage->leaf
- || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
- ){
- /* A b-tree rebalance will be required after deleting this entry.
- ** Save the cursor key. */
- rc = saveCursorKey(pCur);
- if( rc ) return rc;
- }else{
- bSkipnext = 1;
- }
- }
-
- /* If the page containing the entry to delete is not a leaf page, move
- ** the cursor to the largest entry in the tree that is smaller than
- ** the entry being deleted. This cell will replace the cell being deleted
- ** from the internal node. The 'previous' entry is used for this instead
- ** of the 'next' entry, as the previous entry is always a part of the
- ** sub-tree headed by the child page of the cell being deleted. This makes
- ** balancing the tree following the delete operation easier. */
- if( !pPage->leaf ){
- rc = sqlite3BtreePrevious(pCur, 0);
- assert( rc!=SQLITE_DONE );
- if( rc ) return rc;
- }
-
- /* Save the positions of any other cursors open on this table before
- ** making any modifications. */
- if( pCur->curFlags & BTCF_Multiple ){
- rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
- if( rc ) return rc;
- }
-
- /* If this is a delete operation to remove a row from a table b-tree,
- ** invalidate any incrblob cursors open on the row being deleted. */
- if( pCur->pKeyInfo==0 ){
- invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
- }
-
- /* Make the page containing the entry to be deleted writable. Then free any
- ** overflow pages associated with the entry and finally remove the cell
- ** itself from within the page. */
- rc = sqlite3PagerWrite(pPage->pDbPage);
- if( rc ) return rc;
- rc = clearCell(pPage, pCell, &info);
- dropCell(pPage, iCellIdx, info.nSize, &rc);
- if( rc ) return rc;
-
- /* If the cell deleted was not located on a leaf page, then the cursor
- ** is currently pointing to the largest entry in the sub-tree headed
- ** by the child-page of the cell that was just deleted from an internal
- ** node. The cell from the leaf node needs to be moved to the internal
- ** node to replace the deleted cell. */
- if( !pPage->leaf ){
- MemPage *pLeaf = pCur->pPage;
- int nCell;
- Pgno n;
- unsigned char *pTmp;
-
- if( iCellDepth<pCur->iPage-1 ){
- n = pCur->apPage[iCellDepth+1]->pgno;
- }else{
- n = pCur->pPage->pgno;
- }
- pCell = findCell(pLeaf, pLeaf->nCell-1);
- if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
- nCell = pLeaf->xCellSize(pLeaf, pCell);
- assert( MX_CELL_SIZE(pBt) >= nCell );
- pTmp = pBt->pTmpSpace;
- assert( pTmp!=0 );
- rc = sqlite3PagerWrite(pLeaf->pDbPage);
- if( rc==SQLITE_OK ){
- insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
- }
- dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
- if( rc ) return rc;
- }
-
- /* Balance the tree. If the entry deleted was located on a leaf page,
- ** then the cursor still points to that page. In this case the first
- ** call to balance() repairs the tree, and the if(...) condition is
- ** never true.
- **
- ** Otherwise, if the entry deleted was on an internal node page, then
- ** pCur is pointing to the leaf page from which a cell was removed to
- ** replace the cell deleted from the internal node. This is slightly
- ** tricky as the leaf node may be underfull, and the internal node may
- ** be either under or overfull. In this case run the balancing algorithm
- ** on the leaf node first. If the balance proceeds far enough up the
- ** tree that we can be sure that any problem in the internal node has
- ** been corrected, so be it. Otherwise, after balancing the leaf node,
- ** walk the cursor up the tree to the internal node and balance it as
- ** well. */
- rc = balance(pCur);
- if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
- releasePageNotNull(pCur->pPage);
- pCur->iPage--;
- while( pCur->iPage>iCellDepth ){
- releasePage(pCur->apPage[pCur->iPage--]);
- }
- pCur->pPage = pCur->apPage[pCur->iPage];
- rc = balance(pCur);
- }
-
- if( rc==SQLITE_OK ){
- if( bSkipnext ){
- assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
- assert( pPage==pCur->pPage || CORRUPT_DB );
- assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
- pCur->eState = CURSOR_SKIPNEXT;
- if( iCellIdx>=pPage->nCell ){
- pCur->skipNext = -1;
- pCur->ix = pPage->nCell-1;
- }else{
- pCur->skipNext = 1;
- }
- }else{
- rc = moveToRoot(pCur);
- if( bPreserve ){
- btreeReleaseAllCursorPages(pCur);
- pCur->eState = CURSOR_REQUIRESEEK;
- }
- if( rc==SQLITE_EMPTY ) rc = SQLITE_OK;
- }
- }
- return rc;
-}
-
-/*
-** Create a new BTree table. Write into *piTable the page
-** number for the root page of the new table.
-**
-** The type of type is determined by the flags parameter. Only the
-** following values of flags are currently in use. Other values for
-** flags might not work:
-**
-** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys
-** BTREE_ZERODATA Used for SQL indices
-*/
-static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
- BtShared *pBt = p->pBt;
- MemPage *pRoot;
- Pgno pgnoRoot;
- int rc;
- int ptfFlags; /* Page-type flage for the root page of new table */
-
- assert( sqlite3BtreeHoldsMutex(p) );
- assert( pBt->inTransaction==TRANS_WRITE );
- assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
-
-#ifdef SQLITE_OMIT_AUTOVACUUM
- rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
- if( rc ){
- return rc;
- }
-#else
- if( pBt->autoVacuum ){
- Pgno pgnoMove; /* Move a page here to make room for the root-page */
- MemPage *pPageMove; /* The page to move to. */
-
- /* Creating a new table may probably require moving an existing database
- ** to make room for the new tables root page. In case this page turns
- ** out to be an overflow page, delete all overflow page-map caches
- ** held by open cursors.
- */
- invalidateAllOverflowCache(pBt);
-
- /* Read the value of meta[3] from the database to determine where the
- ** root page of the new table should go. meta[3] is the largest root-page
- ** created so far, so the new root-page is (meta[3]+1).
- */
- sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot);
- pgnoRoot++;
-
- /* The new root-page may not be allocated on a pointer-map page, or the
- ** PENDING_BYTE page.
- */
- while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) ||
- pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
- pgnoRoot++;
- }
- assert( pgnoRoot>=3 || CORRUPT_DB );
- testcase( pgnoRoot<3 );
-
- /* Allocate a page. The page that currently resides at pgnoRoot will
- ** be moved to the allocated page (unless the allocated page happens
- ** to reside at pgnoRoot).
- */
- rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- if( pgnoMove!=pgnoRoot ){
- /* pgnoRoot is the page that will be used for the root-page of
- ** the new table (assuming an error did not occur). But we were
- ** allocated pgnoMove. If required (i.e. if it was not allocated
- ** by extending the file), the current page at position pgnoMove
- ** is already journaled.
- */
- u8 eType = 0;
- Pgno iPtrPage = 0;
-
- /* Save the positions of any open cursors. This is required in
- ** case they are holding a reference to an xFetch reference
- ** corresponding to page pgnoRoot. */
- rc = saveAllCursors(pBt, 0, 0);
- releasePage(pPageMove);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Move the page currently at pgnoRoot to pgnoMove. */
- rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
- if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
- rc = SQLITE_CORRUPT_BKPT;
- }
- if( rc!=SQLITE_OK ){
- releasePage(pRoot);
- return rc;
- }
- assert( eType!=PTRMAP_ROOTPAGE );
- assert( eType!=PTRMAP_FREEPAGE );
- rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
- releasePage(pRoot);
-
- /* Obtain the page at pgnoRoot */
- if( rc!=SQLITE_OK ){
- return rc;
- }
- rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- rc = sqlite3PagerWrite(pRoot->pDbPage);
- if( rc!=SQLITE_OK ){
- releasePage(pRoot);
- return rc;
- }
- }else{
- pRoot = pPageMove;
- }
-
- /* Update the pointer-map and meta-data with the new root-page number. */
- ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc);
- if( rc ){
- releasePage(pRoot);
- return rc;
- }
-
- /* When the new root page was allocated, page 1 was made writable in
- ** order either to increase the database filesize, or to decrement the
- ** freelist count. Hence, the sqlite3BtreeUpdateMeta() call cannot fail.
- */
- assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) );
- rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot);
- if( NEVER(rc) ){
- releasePage(pRoot);
- return rc;
- }
-
- }else{
- rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
- if( rc ) return rc;
- }
-#endif
- assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
- if( createTabFlags & BTREE_INTKEY ){
- ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF;
- }else{
- ptfFlags = PTF_ZERODATA | PTF_LEAF;
- }
- zeroPage(pRoot, ptfFlags);
- sqlite3PagerUnref(pRoot->pDbPage);
- assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 );
- *piTable = (int)pgnoRoot;
- return SQLITE_OK;
-}
-int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
- int rc;
- sqlite3BtreeEnter(p);
- rc = btreeCreateTable(p, piTable, flags);
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
-** Erase the given database page and all its children. Return
-** the page to the freelist.
-*/
-static int clearDatabasePage(
- BtShared *pBt, /* The BTree that contains the table */
- Pgno pgno, /* Page number to clear */
- int freePageFlag, /* Deallocate page if true */
- int *pnChange /* Add number of Cells freed to this counter */
-){
- MemPage *pPage;
- int rc;
- unsigned char *pCell;
- int i;
- int hdr;
- CellInfo info;
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- if( pgno>btreePagecount(pBt) ){
- return SQLITE_CORRUPT_BKPT;
- }
- rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
- if( rc ) return rc;
- if( pPage->bBusy ){
- rc = SQLITE_CORRUPT_BKPT;
- goto cleardatabasepage_out;
- }
- pPage->bBusy = 1;
- hdr = pPage->hdrOffset;
- for(i=0; i<pPage->nCell; i++){
- pCell = findCell(pPage, i);
- if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
- if( rc ) goto cleardatabasepage_out;
- }
- rc = clearCell(pPage, pCell, &info);
- if( rc ) goto cleardatabasepage_out;
- }
- if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
- if( rc ) goto cleardatabasepage_out;
- }else if( pnChange ){
- assert( pPage->intKey || CORRUPT_DB );
- testcase( !pPage->intKey );
- *pnChange += pPage->nCell;
- }
- if( freePageFlag ){
- freePage(pPage, &rc);
- }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
- zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
- }
-
-cleardatabasepage_out:
- pPage->bBusy = 0;
- releasePage(pPage);
- return rc;
-}
-
-/*
-** Delete all information from a single table in the database. iTable is
-** the page number of the root of the table. After this routine returns,
-** the root page is empty, but still exists.
-**
-** This routine will fail with SQLITE_LOCKED if there are any open
-** read cursors on the table. Open write cursors are moved to the
-** root of the table.
-**
-** If pnChange is not NULL, then table iTable must be an intkey table. The
-** integer value pointed to by pnChange is incremented by the number of
-** entries in the table.
-*/
-int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
- int rc;
- BtShared *pBt = p->pBt;
- sqlite3BtreeEnter(p);
- assert( p->inTrans==TRANS_WRITE );
-
- rc = saveAllCursors(pBt, (Pgno)iTable, 0);
-
- if( SQLITE_OK==rc ){
- /* Invalidate all incrblob cursors open on table iTable (assuming iTable
- ** is the root of a table b-tree - if it is not, the following call is
- ** a no-op). */
- invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
- rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
- }
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
-** Delete all information from the single table that pCur is open on.
-**
-** This routine only work for pCur on an ephemeral table.
-*/
-int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
- return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0);
-}
-
-/*
-** Erase all information in a table and add the root of the table to
-** the freelist. Except, the root of the principle table (the one on
-** page 1) is never added to the freelist.
-**
-** This routine will fail with SQLITE_LOCKED if there are any open
-** cursors on the table.
-**
-** If AUTOVACUUM is enabled and the page at iTable is not the last
-** root page in the database file, then the last root page
-** in the database file is moved into the slot formerly occupied by
-** iTable and that last slot formerly occupied by the last root page
-** is added to the freelist instead of iTable. In this say, all
-** root pages are kept at the beginning of the database file, which
-** is necessary for AUTOVACUUM to work right. *piMoved is set to the
-** page number that used to be the last root page in the file before
-** the move. If no page gets moved, *piMoved is set to 0.
-** The last root page is recorded in meta[3] and the value of
-** meta[3] is updated by this procedure.
-*/
-static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
- int rc;
- MemPage *pPage = 0;
- BtShared *pBt = p->pBt;
-
- assert( sqlite3BtreeHoldsMutex(p) );
- assert( p->inTrans==TRANS_WRITE );
- assert( iTable>=2 );
-
- rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
- if( rc ) return rc;
- rc = sqlite3BtreeClearTable(p, iTable, 0);
- if( rc ){
- releasePage(pPage);
- return rc;
- }
-
- *piMoved = 0;
-
-#ifdef SQLITE_OMIT_AUTOVACUUM
- freePage(pPage, &rc);
- releasePage(pPage);
-#else
- if( pBt->autoVacuum ){
- Pgno maxRootPgno;
- sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno);
-
- if( iTable==maxRootPgno ){
- /* If the table being dropped is the table with the largest root-page
- ** number in the database, put the root page on the free list.
- */
- freePage(pPage, &rc);
- releasePage(pPage);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }else{
- /* The table being dropped does not have the largest root-page
- ** number in the database. So move the page that does into the
- ** gap left by the deleted root-page.
- */
- MemPage *pMove;
- releasePage(pPage);
- rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
- releasePage(pMove);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pMove = 0;
- rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
- freePage(pMove, &rc);
- releasePage(pMove);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- *piMoved = maxRootPgno;
- }
-
- /* Set the new 'max-root-page' value in the database header. This
- ** is the old value less one, less one more if that happens to
- ** be a root-page number, less one again if that is the
- ** PENDING_BYTE_PAGE.
- */
- maxRootPgno--;
- while( maxRootPgno==PENDING_BYTE_PAGE(pBt)
- || PTRMAP_ISPAGE(pBt, maxRootPgno) ){
- maxRootPgno--;
- }
- assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
-
- rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
- }else{
- freePage(pPage, &rc);
- releasePage(pPage);
- }
-#endif
- return rc;
-}
-int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
- int rc;
- sqlite3BtreeEnter(p);
- rc = btreeDropTable(p, iTable, piMoved);
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-
-/*
-** This function may only be called if the b-tree connection already
-** has a read or write transaction open on the database.
-**
-** Read the meta-information out of a database file. Meta[0]
-** is the number of free pages currently in the database. Meta[1]
-** through meta[15] are available for use by higher layers. Meta[0]
-** is read-only, the others are read/write.
-**
-** The schema layer numbers meta values differently. At the schema
-** layer (and the SetCookie and ReadCookie opcodes) the number of
-** free pages is not visible. So Cookie[0] is the same as Meta[1].
-**
-** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead
-** of reading the value out of the header, it instead loads the "DataVersion"
-** from the pager. The BTREE_DATA_VERSION value is not actually stored in the
-** database file. It is a number computed by the pager. But its access
-** pattern is the same as header meta values, and so it is convenient to
-** read it from this routine.
-*/
-void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
- BtShared *pBt = p->pBt;
-
- sqlite3BtreeEnter(p);
- assert( p->inTrans>TRANS_NONE );
- assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
- assert( pBt->pPage1 );
- assert( idx>=0 && idx<=15 );
-
- if( idx==BTREE_DATA_VERSION ){
- *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
- }else{
- *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
- }
-
- /* If auto-vacuum is disabled in this build and this is an auto-vacuum
- ** database, mark the database as read-only. */
-#ifdef SQLITE_OMIT_AUTOVACUUM
- if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
- pBt->btsFlags |= BTS_READ_ONLY;
- }
-#endif
-
- sqlite3BtreeLeave(p);
-}
-
-/*
-** Write meta-information back into the database. Meta[0] is
-** read-only and may not be written.
-*/
-int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
- BtShared *pBt = p->pBt;
- unsigned char *pP1;
- int rc;
- assert( idx>=1 && idx<=15 );
- sqlite3BtreeEnter(p);
- assert( p->inTrans==TRANS_WRITE );
- assert( pBt->pPage1!=0 );
- pP1 = pBt->pPage1->aData;
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- if( rc==SQLITE_OK ){
- put4byte(&pP1[36 + idx*4], iMeta);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( idx==BTREE_INCR_VACUUM ){
- assert( pBt->autoVacuum || iMeta==0 );
- assert( iMeta==0 || iMeta==1 );
- pBt->incrVacuum = (u8)iMeta;
- }
-#endif
- }
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-#ifndef SQLITE_OMIT_BTREECOUNT
-/*
-** The first argument, pCur, is a cursor opened on some b-tree. Count the
-** number of entries in the b-tree and write the result to *pnEntry.
-**
-** SQLITE_OK is returned if the operation is successfully executed.
-** Otherwise, if an error is encountered (i.e. an IO error or database
-** corruption) an SQLite error code is returned.
-*/
-int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
- i64 nEntry = 0; /* Value to return in *pnEntry */
- int rc; /* Return code */
-
- rc = moveToRoot(pCur);
- if( rc==SQLITE_EMPTY ){
- *pnEntry = 0;
- return SQLITE_OK;
- }
-
- /* Unless an error occurs, the following loop runs one iteration for each
- ** page in the B-Tree structure (not including overflow pages).
- */
- while( rc==SQLITE_OK ){
- int iIdx; /* Index of child node in parent */
- MemPage *pPage; /* Current page of the b-tree */
-
- /* If this is a leaf page or the tree is not an int-key tree, then
- ** this page contains countable entries. Increment the entry counter
- ** accordingly.
- */
- pPage = pCur->pPage;
- if( pPage->leaf || !pPage->intKey ){
- nEntry += pPage->nCell;
- }
-
- /* pPage is a leaf node. This loop navigates the cursor so that it
- ** points to the first interior cell that it points to the parent of
- ** the next page in the tree that has not yet been visited. The
- ** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell
- ** of the page, or to the number of cells in the page if the next page
- ** to visit is the right-child of its parent.
- **
- ** If all pages in the tree have been visited, return SQLITE_OK to the
- ** caller.
- */
- if( pPage->leaf ){
- do {
- if( pCur->iPage==0 ){
- /* All pages of the b-tree have been visited. Return successfully. */
- *pnEntry = nEntry;
- return moveToRoot(pCur);
- }
- moveToParent(pCur);
- }while ( pCur->ix>=pCur->pPage->nCell );
-
- pCur->ix++;
- pPage = pCur->pPage;
- }
-
- /* Descend to the child node of the cell that the cursor currently
- ** points at. This is the right-child if (iIdx==pPage->nCell).
- */
- iIdx = pCur->ix;
- if( iIdx==pPage->nCell ){
- rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
- }else{
- rc = moveToChild(pCur, get4byte(findCell(pPage, iIdx)));
- }
- }
-
- /* An error has occurred. Return an error code. */
- return rc;
-}
-#endif
-
-/*
-** Return the pager associated with a BTree. This routine is used for
-** testing and debugging only.
-*/
-Pager *sqlite3BtreePager(Btree *p){
- return p->pBt->pPager;
-}
-
-#ifndef SQLITE_OMIT_INTEGRITY_CHECK
-/*
-** Append a message to the error message string.
-*/
-static void checkAppendMsg(
- IntegrityCk *pCheck,
- const char *zFormat,
- ...
-){
- va_list ap;
- if( !pCheck->mxErr ) return;
- pCheck->mxErr--;
- pCheck->nErr++;
- va_start(ap, zFormat);
- if( pCheck->errMsg.nChar ){
- sqlite3_str_append(&pCheck->errMsg, "\n", 1);
- }
- if( pCheck->zPfx ){
- sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
- }
- sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
- va_end(ap);
- if( pCheck->errMsg.accError==SQLITE_NOMEM ){
- pCheck->mallocFailed = 1;
- }
-}
-#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
-
-#ifndef SQLITE_OMIT_INTEGRITY_CHECK
-
-/*
-** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that
-** corresponds to page iPg is already set.
-*/
-static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){
- assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 );
- return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07)));
-}
-
-/*
-** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg.
-*/
-static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){
- assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 );
- pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07));
-}
-
-
-/*
-** Add 1 to the reference count for page iPage. If this is the second
-** reference to the page, add an error message to pCheck->zErrMsg.
-** Return 1 if there are 2 or more references to the page and 0 if
-** if this is the first reference to the page.
-**
-** Also check that the page number is in bounds.
-*/
-static int checkRef(IntegrityCk *pCheck, Pgno iPage){
- if( iPage==0 ) return 1;
- if( iPage>pCheck->nPage ){
- checkAppendMsg(pCheck, "invalid page number %d", iPage);
- return 1;
- }
- if( getPageReferenced(pCheck, iPage) ){
- checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
- return 1;
- }
- setPageReferenced(pCheck, iPage);
- return 0;
-}
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
-/*
-** Check that the entry in the pointer-map for page iChild maps to
-** page iParent, pointer type ptrType. If not, append an error message
-** to pCheck.
-*/
-static void checkPtrmap(
- IntegrityCk *pCheck, /* Integrity check context */
- Pgno iChild, /* Child page number */
- u8 eType, /* Expected pointer map type */
- Pgno iParent /* Expected pointer map parent page number */
-){
- int rc;
- u8 ePtrmapType;
- Pgno iPtrmapParent;
-
- rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
- checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
- return;
- }
-
- if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
- checkAppendMsg(pCheck,
- "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
- iChild, eType, iParent, ePtrmapType, iPtrmapParent);
- }
-}
-#endif
-
-/*
-** Check the integrity of the freelist or of an overflow page list.
-** Verify that the number of pages on the list is N.
-*/
-static void checkList(
- IntegrityCk *pCheck, /* Integrity checking context */
- int isFreeList, /* True for a freelist. False for overflow page list */
- int iPage, /* Page number for first page in the list */
- int N /* Expected number of pages in the list */
-){
- int i;
- int expected = N;
- int iFirst = iPage;
- while( N-- > 0 && pCheck->mxErr ){
- DbPage *pOvflPage;
- unsigned char *pOvflData;
- if( iPage<1 ){
- checkAppendMsg(pCheck,
- "%d of %d pages missing from overflow list starting at %d",
- N+1, expected, iFirst);
- break;
- }
- if( checkRef(pCheck, iPage) ) break;
- if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
- checkAppendMsg(pCheck, "failed to get page %d", iPage);
- break;
- }
- pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
- if( isFreeList ){
- int n = get4byte(&pOvflData[4]);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pCheck->pBt->autoVacuum ){
- checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0);
- }
-#endif
- if( n>(int)pCheck->pBt->usableSize/4-2 ){
- checkAppendMsg(pCheck,
- "freelist leaf count too big on page %d", iPage);
- N--;
- }else{
- for(i=0; i<n; i++){
- Pgno iFreePage = get4byte(&pOvflData[8+i*4]);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pCheck->pBt->autoVacuum ){
- checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0);
- }
-#endif
- checkRef(pCheck, iFreePage);
- }
- N -= n;
- }
- }
-#ifndef SQLITE_OMIT_AUTOVACUUM
- else{
- /* If this database supports auto-vacuum and iPage is not the last
- ** page in this overflow list, check that the pointer-map entry for
- ** the following page matches iPage.
- */
- if( pCheck->pBt->autoVacuum && N>0 ){
- i = get4byte(pOvflData);
- checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage);
- }
- }
-#endif
- iPage = get4byte(pOvflData);
- sqlite3PagerUnref(pOvflPage);
-
- if( isFreeList && N<(iPage!=0) ){
- checkAppendMsg(pCheck, "free-page count in header is too small");
- }
- }
-}
-#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
-
-/*
-** An implementation of a min-heap.
-**
-** aHeap[0] is the number of elements on the heap. aHeap[1] is the
-** root element. The daughter nodes of aHeap[N] are aHeap[N*2]
-** and aHeap[N*2+1].
-**
-** The heap property is this: Every node is less than or equal to both
-** of its daughter nodes. A consequence of the heap property is that the
-** root node aHeap[1] is always the minimum value currently in the heap.
-**
-** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto
-** the heap, preserving the heap property. The btreeHeapPull() routine
-** removes the root element from the heap (the minimum value in the heap)
-** and then moves other nodes around as necessary to preserve the heap
-** property.
-**
-** This heap is used for cell overlap and coverage testing. Each u32
-** entry represents the span of a cell or freeblock on a btree page.
-** The upper 16 bits are the index of the first byte of a range and the
-** lower 16 bits are the index of the last byte of that range.
-*/
-static void btreeHeapInsert(u32 *aHeap, u32 x){
- u32 j, i = ++aHeap[0];
- aHeap[i] = x;
- while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
- x = aHeap[j];
- aHeap[j] = aHeap[i];
- aHeap[i] = x;
- i = j;
- }
-}
-static int btreeHeapPull(u32 *aHeap, u32 *pOut){
- u32 j, i, x;
- if( (x = aHeap[0])==0 ) return 0;
- *pOut = aHeap[1];
- aHeap[1] = aHeap[x];
- aHeap[x] = 0xffffffff;
- aHeap[0]--;
- i = 1;
- while( (j = i*2)<=aHeap[0] ){
- if( aHeap[j]>aHeap[j+1] ) j++;
- if( aHeap[i]<aHeap[j] ) break;
- x = aHeap[i];
- aHeap[i] = aHeap[j];
- aHeap[j] = x;
- i = j;
- }
- return 1;
-}
-
-#ifndef SQLITE_OMIT_INTEGRITY_CHECK
-/*
-** Do various sanity checks on a single page of a tree. Return
-** the tree depth. Root pages return 0. Parents of root pages
-** return 1, and so forth.
-**
-** These checks are done:
-**
-** 1. Make sure that cells and freeblocks do not overlap
-** but combine to completely cover the page.
-** 2. Make sure integer cell keys are in order.
-** 3. Check the integrity of overflow pages.
-** 4. Recursively call checkTreePage on all children.
-** 5. Verify that the depth of all children is the same.
-*/
-static int checkTreePage(
- IntegrityCk *pCheck, /* Context for the sanity check */
- int iPage, /* Page number of the page to check */
- i64 *piMinKey, /* Write minimum integer primary key here */
- i64 maxKey /* Error if integer primary key greater than this */
-){
- MemPage *pPage = 0; /* The page being analyzed */
- int i; /* Loop counter */
- int rc; /* Result code from subroutine call */
- int depth = -1, d2; /* Depth of a subtree */
- int pgno; /* Page number */
- int nFrag; /* Number of fragmented bytes on the page */
- int hdr; /* Offset to the page header */
- int cellStart; /* Offset to the start of the cell pointer array */
- int nCell; /* Number of cells */
- int doCoverageCheck = 1; /* True if cell coverage checking should be done */
- int keyCanBeEqual = 1; /* True if IPK can be equal to maxKey
- ** False if IPK must be strictly less than maxKey */
- u8 *data; /* Page content */
- u8 *pCell; /* Cell content */
- u8 *pCellIdx; /* Next element of the cell pointer array */
- BtShared *pBt; /* The BtShared object that owns pPage */
- u32 pc; /* Address of a cell */
- u32 usableSize; /* Usable size of the page */
- u32 contentOffset; /* Offset to the start of the cell content area */
- u32 *heap = 0; /* Min-heap used for checking cell coverage */
- u32 x, prev = 0; /* Next and previous entry on the min-heap */
- const char *saved_zPfx = pCheck->zPfx;
- int saved_v1 = pCheck->v1;
- int saved_v2 = pCheck->v2;
- u8 savedIsInit = 0;
-
- /* Check that the page exists
- */
- pBt = pCheck->pBt;
- usableSize = pBt->usableSize;
- if( iPage==0 ) return 0;
- if( checkRef(pCheck, iPage) ) return 0;
- pCheck->zPfx = "Page %d: ";
- pCheck->v1 = iPage;
- if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
- checkAppendMsg(pCheck,
- "unable to get the page. error code=%d", rc);
- goto end_of_check;
- }
-
- /* Clear MemPage.isInit to make sure the corruption detection code in
- ** btreeInitPage() is executed. */
- savedIsInit = pPage->isInit;
- pPage->isInit = 0;
- if( (rc = btreeInitPage(pPage))!=0 ){
- assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */
- checkAppendMsg(pCheck,
- "btreeInitPage() returns error code %d", rc);
- goto end_of_check;
- }
- data = pPage->aData;
- hdr = pPage->hdrOffset;
-
- /* Set up for cell analysis */
- pCheck->zPfx = "On tree page %d cell %d: ";
- contentOffset = get2byteNotZero(&data[hdr+5]);
- assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
-
- /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
- ** number of cells on the page. */
- nCell = get2byte(&data[hdr+3]);
- assert( pPage->nCell==nCell );
-
- /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page
- ** immediately follows the b-tree page header. */
- cellStart = hdr + 12 - 4*pPage->leaf;
- assert( pPage->aCellIdx==&data[cellStart] );
- pCellIdx = &data[cellStart + 2*(nCell-1)];
-
- if( !pPage->leaf ){
- /* Analyze the right-child page of internal pages */
- pgno = get4byte(&data[hdr+8]);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- pCheck->zPfx = "On page %d at right child: ";
- checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
- }
-#endif
- depth = checkTreePage(pCheck, pgno, &maxKey, maxKey);
- keyCanBeEqual = 0;
- }else{
- /* For leaf pages, the coverage check will occur in the same loop
- ** as the other cell checks, so initialize the heap. */
- heap = pCheck->heap;
- heap[0] = 0;
- }
-
- /* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte
- ** integer offsets to the cell contents. */
- for(i=nCell-1; i>=0 && pCheck->mxErr; i--){
- CellInfo info;
-
- /* Check cell size */
- pCheck->v2 = i;
- assert( pCellIdx==&data[cellStart + i*2] );
- pc = get2byteAligned(pCellIdx);
- pCellIdx -= 2;
- if( pc<contentOffset || pc>usableSize-4 ){
- checkAppendMsg(pCheck, "Offset %d out of range %d..%d",
- pc, contentOffset, usableSize-4);
- doCoverageCheck = 0;
- continue;
- }
- pCell = &data[pc];
- pPage->xParseCell(pPage, pCell, &info);
- if( pc+info.nSize>usableSize ){
- checkAppendMsg(pCheck, "Extends off end of page");
- doCoverageCheck = 0;
- continue;
- }
-
- /* Check for integer primary key out of range */
- if( pPage->intKey ){
- if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){
- checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
- }
- maxKey = info.nKey;
- keyCanBeEqual = 0; /* Only the first key on the page may ==maxKey */
- }
-
- /* Check the content overflow list */
- if( info.nPayload>info.nLocal ){
- int nPage; /* Number of pages on the overflow chain */
- Pgno pgnoOvfl; /* First page of the overflow chain */
- assert( pc + info.nSize - 4 <= usableSize );
- nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
- pgnoOvfl = get4byte(&pCell[info.nSize - 4]);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
- }
-#endif
- checkList(pCheck, 0, pgnoOvfl, nPage);
- }
-
- if( !pPage->leaf ){
- /* Check sanity of left child page for internal pages */
- pgno = get4byte(pCell);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
- }
-#endif
- d2 = checkTreePage(pCheck, pgno, &maxKey, maxKey);
- keyCanBeEqual = 0;
- if( d2!=depth ){
- checkAppendMsg(pCheck, "Child page depth differs");
- depth = d2;
- }
- }else{
- /* Populate the coverage-checking heap for leaf pages */
- btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1));
- }
- }
- *piMinKey = maxKey;
-
- /* Check for complete coverage of the page
- */
- pCheck->zPfx = 0;
- if( doCoverageCheck && pCheck->mxErr>0 ){
- /* For leaf pages, the min-heap has already been initialized and the
- ** cells have already been inserted. But for internal pages, that has
- ** not yet been done, so do it now */
- if( !pPage->leaf ){
- heap = pCheck->heap;
- heap[0] = 0;
- for(i=nCell-1; i>=0; i--){
- u32 size;
- pc = get2byteAligned(&data[cellStart+i*2]);
- size = pPage->xCellSize(pPage, &data[pc]);
- btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
- }
- }
- /* Add the freeblocks to the min-heap
- **
- ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
- ** is the offset of the first freeblock, or zero if there are no
- ** freeblocks on the page.
- */
- i = get2byte(&data[hdr+1]);
- while( i>0 ){
- int size, j;
- assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */
- size = get2byte(&data[i+2]);
- assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */
- btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
- /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
- ** big-endian integer which is the offset in the b-tree page of the next
- ** freeblock in the chain, or zero if the freeblock is the last on the
- ** chain. */
- j = get2byte(&data[i]);
- /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
- ** increasing offset. */
- assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */
- assert( (u32)j<=usableSize-4 ); /* Enforced by btreeInitPage() */
- i = j;
- }
- /* Analyze the min-heap looking for overlap between cells and/or
- ** freeblocks, and counting the number of untracked bytes in nFrag.
- **
- ** Each min-heap entry is of the form: (start_address<<16)|end_address.
- ** There is an implied first entry the covers the page header, the cell
- ** pointer index, and the gap between the cell pointer index and the start
- ** of cell content.
- **
- ** The loop below pulls entries from the min-heap in order and compares
- ** the start_address against the previous end_address. If there is an
- ** overlap, that means bytes are used multiple times. If there is a gap,
- ** that gap is added to the fragmentation count.
- */
- nFrag = 0;
- prev = contentOffset - 1; /* Implied first min-heap entry */
- while( btreeHeapPull(heap,&x) ){
- if( (prev&0xffff)>=(x>>16) ){
- checkAppendMsg(pCheck,
- "Multiple uses for byte %u of page %d", x>>16, iPage);
- break;
- }else{
- nFrag += (x>>16) - (prev&0xffff) - 1;
- prev = x;
- }
- }
- nFrag += usableSize - (prev&0xffff) - 1;
- /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
- ** is stored in the fifth field of the b-tree page header.
- ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
- ** number of fragmented free bytes within the cell content area.
- */
- if( heap[0]==0 && nFrag!=data[hdr+7] ){
- checkAppendMsg(pCheck,
- "Fragmentation of %d bytes reported as %d on page %d",
- nFrag, data[hdr+7], iPage);
- }
- }
-
-end_of_check:
- if( !doCoverageCheck ) pPage->isInit = savedIsInit;
- releasePage(pPage);
- pCheck->zPfx = saved_zPfx;
- pCheck->v1 = saved_v1;
- pCheck->v2 = saved_v2;
- return depth+1;
-}
-#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
-
-#ifndef SQLITE_OMIT_INTEGRITY_CHECK
-/*
-** This routine does a complete check of the given BTree file. aRoot[] is
-** an array of pages numbers were each page number is the root page of
-** a table. nRoot is the number of entries in aRoot.
-**
-** A read-only or read-write transaction must be opened before calling
-** this function.
-**
-** Write the number of error seen in *pnErr. Except for some memory
-** allocation errors, an error message held in memory obtained from
-** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is
-** returned. If a memory allocation error occurs, NULL is returned.
-*/
-char *sqlite3BtreeIntegrityCheck(
- Btree *p, /* The btree to be checked */
- int *aRoot, /* An array of root pages numbers for individual trees */
- int nRoot, /* Number of entries in aRoot[] */
- int mxErr, /* Stop reporting errors after this many */
- int *pnErr /* Write number of errors seen to this variable */
-){
- Pgno i;
- IntegrityCk sCheck;
- BtShared *pBt = p->pBt;
- int savedDbFlags = pBt->db->flags;
- char zErr[100];
- VVA_ONLY( int nRef );
-
- sqlite3BtreeEnter(p);
- assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
- VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
- assert( nRef>=0 );
- sCheck.pBt = pBt;
- sCheck.pPager = pBt->pPager;
- sCheck.nPage = btreePagecount(sCheck.pBt);
- sCheck.mxErr = mxErr;
- sCheck.nErr = 0;
- sCheck.mallocFailed = 0;
- sCheck.zPfx = 0;
- sCheck.v1 = 0;
- sCheck.v2 = 0;
- sCheck.aPgRef = 0;
- sCheck.heap = 0;
- sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
- sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL;
- if( sCheck.nPage==0 ){
- goto integrity_ck_cleanup;
- }
-
- sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
- if( !sCheck.aPgRef ){
- sCheck.mallocFailed = 1;
- goto integrity_ck_cleanup;
- }
- sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
- if( sCheck.heap==0 ){
- sCheck.mallocFailed = 1;
- goto integrity_ck_cleanup;
- }
-
- i = PENDING_BYTE_PAGE(pBt);
- if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
-
- /* Check the integrity of the freelist
- */
- sCheck.zPfx = "Main freelist: ";
- checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
- get4byte(&pBt->pPage1->aData[36]));
- sCheck.zPfx = 0;
-
- /* Check all the tables.
- */
- testcase( pBt->db->flags & SQLITE_CellSizeCk );
- pBt->db->flags &= ~SQLITE_CellSizeCk;
- for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
- i64 notUsed;
- if( aRoot[i]==0 ) continue;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum && aRoot[i]>1 ){
- checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
- }
-#endif
- checkTreePage(&sCheck, aRoot[i], &notUsed, LARGEST_INT64);
- }
- pBt->db->flags = savedDbFlags;
-
- /* Make sure every page in the file is referenced
- */
- for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
-#ifdef SQLITE_OMIT_AUTOVACUUM
- if( getPageReferenced(&sCheck, i)==0 ){
- checkAppendMsg(&sCheck, "Page %d is never used", i);
- }
-#else
- /* If the database supports auto-vacuum, make sure no tables contain
- ** references to pointer-map pages.
- */
- if( getPageReferenced(&sCheck, i)==0 &&
- (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
- checkAppendMsg(&sCheck, "Page %d is never used", i);
- }
- if( getPageReferenced(&sCheck, i)!=0 &&
- (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
- checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
- }
-#endif
- }
-
- /* Clean up and report errors.
- */
-integrity_ck_cleanup:
- sqlite3PageFree(sCheck.heap);
- sqlite3_free(sCheck.aPgRef);
- if( sCheck.mallocFailed ){
- sqlite3_str_reset(&sCheck.errMsg);
- sCheck.nErr++;
- }
- *pnErr = sCheck.nErr;
- if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg);
- /* Make sure this analysis did not leave any unref() pages. */
- assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
- sqlite3BtreeLeave(p);
- return sqlite3StrAccumFinish(&sCheck.errMsg);
-}
-#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
-
-/*
-** Return the full pathname of the underlying database file. Return
-** an empty string if the database is in-memory or a TEMP database.
-**
-** The pager filename is invariant as long as the pager is
-** open so it is safe to access without the BtShared mutex.
-*/
-const char *sqlite3BtreeGetFilename(Btree *p){
- assert( p->pBt->pPager!=0 );
- return sqlite3PagerFilename(p->pBt->pPager, 1);
-}
-
-/*
-** Return the pathname of the journal file for this database. The return
-** value of this routine is the same regardless of whether the journal file
-** has been created or not.
-**
-** The pager journal filename is invariant as long as the pager is
-** open so it is safe to access without the BtShared mutex.
-*/
-const char *sqlite3BtreeGetJournalname(Btree *p){
- assert( p->pBt->pPager!=0 );
- return sqlite3PagerJournalname(p->pBt->pPager);
-}
-
-/*
-** Return non-zero if a transaction is active.
-*/
-int sqlite3BtreeIsInTrans(Btree *p){
- assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
- return (p && (p->inTrans==TRANS_WRITE));
-}
-
-#ifndef SQLITE_OMIT_WAL
-/*
-** Run a checkpoint on the Btree passed as the first argument.
-**
-** Return SQLITE_LOCKED if this or any other connection has an open
-** transaction on the shared-cache the argument Btree is connected to.
-**
-** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
-*/
-int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){
- int rc = SQLITE_OK;
- if( p ){
- BtShared *pBt = p->pBt;
- sqlite3BtreeEnter(p);
- if( pBt->inTransaction!=TRANS_NONE ){
- rc = SQLITE_LOCKED;
- }else{
- rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
- }
- sqlite3BtreeLeave(p);
- }
- return rc;
-}
-#endif
-
-/*
-** Return non-zero if a read (or write) transaction is active.
-*/
-int sqlite3BtreeIsInReadTrans(Btree *p){
- assert( p );
- assert( sqlite3_mutex_held(p->db->mutex) );
- return p->inTrans!=TRANS_NONE;
-}
-
-int sqlite3BtreeIsInBackup(Btree *p){
- assert( p );
- assert( sqlite3_mutex_held(p->db->mutex) );
- return p->nBackup!=0;
-}
-
-/*
-** This function returns a pointer to a blob of memory associated with
-** a single shared-btree. The memory is used by client code for its own
-** purposes (for example, to store a high-level schema associated with
-** the shared-btree). The btree layer manages reference counting issues.
-**
-** The first time this is called on a shared-btree, nBytes bytes of memory
-** are allocated, zeroed, and returned to the caller. For each subsequent
-** call the nBytes parameter is ignored and a pointer to the same blob
-** of memory returned.
-**
-** If the nBytes parameter is 0 and the blob of memory has not yet been
-** allocated, a null pointer is returned. If the blob has already been
-** allocated, it is returned as normal.
-**
-** Just before the shared-btree is closed, the function passed as the
-** xFree argument when the memory allocation was made is invoked on the
-** blob of allocated memory. The xFree function should not call sqlite3_free()
-** on the memory, the btree layer does that.
-*/
-void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
- BtShared *pBt = p->pBt;
- sqlite3BtreeEnter(p);
- if( !pBt->pSchema && nBytes ){
- pBt->pSchema = sqlite3DbMallocZero(0, nBytes);
- pBt->xFreeSchema = xFree;
- }
- sqlite3BtreeLeave(p);
- return pBt->pSchema;
-}
-
-/*
-** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
-** btree as the argument handle holds an exclusive lock on the
-** sqlite_master table. Otherwise SQLITE_OK.
-*/
-int sqlite3BtreeSchemaLocked(Btree *p){
- int rc;
- assert( sqlite3_mutex_held(p->db->mutex) );
- sqlite3BtreeEnter(p);
- rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
- assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE );
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/*
-** Obtain a lock on the table whose root page is iTab. The
-** lock is a write lock if isWritelock is true or a read lock
-** if it is false.
-*/
-int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
- int rc = SQLITE_OK;
- assert( p->inTrans!=TRANS_NONE );
- if( p->sharable ){
- u8 lockType = READ_LOCK + isWriteLock;
- assert( READ_LOCK+1==WRITE_LOCK );
- assert( isWriteLock==0 || isWriteLock==1 );
-
- sqlite3BtreeEnter(p);
- rc = querySharedCacheTableLock(p, iTab, lockType);
- if( rc==SQLITE_OK ){
- rc = setSharedCacheTableLock(p, iTab, lockType);
- }
- sqlite3BtreeLeave(p);
- }
- return rc;
-}
-#endif
-
-#ifndef SQLITE_OMIT_INCRBLOB
-/*
-** Argument pCsr must be a cursor opened for writing on an
-** INTKEY table currently pointing at a valid table entry.
-** This function modifies the data stored as part of that entry.
-**
-** Only the data content may only be modified, it is not possible to
-** change the length of the data stored. If this function is called with
-** parameters that attempt to write past the end of the existing data,
-** no modifications are made and SQLITE_CORRUPT is returned.
-*/
-int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
- int rc;
- assert( cursorOwnsBtShared(pCsr) );
- assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
- assert( pCsr->curFlags & BTCF_Incrblob );
-
- rc = restoreCursorPosition(pCsr);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- assert( pCsr->eState!=CURSOR_REQUIRESEEK );
- if( pCsr->eState!=CURSOR_VALID ){
- return SQLITE_ABORT;
- }
-
- /* Save the positions of all other cursors open on this table. This is
- ** required in case any of them are holding references to an xFetch
- ** version of the b-tree page modified by the accessPayload call below.
- **
- ** Note that pCsr must be open on a INTKEY table and saveCursorPosition()
- ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence
- ** saveAllCursors can only return SQLITE_OK.
- */
- VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
- assert( rc==SQLITE_OK );
-
- /* Check some assumptions:
- ** (a) the cursor is open for writing,
- ** (b) there is a read/write transaction open,
- ** (c) the connection holds a write-lock on the table (if required),
- ** (d) there are no conflicting read-locks, and
- ** (e) the cursor points at a valid row of an intKey table.
- */
- if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){
- return SQLITE_READONLY;
- }
- assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
- && pCsr->pBt->inTransaction==TRANS_WRITE );
- assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
- assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
- assert( pCsr->pPage->intKey );
-
- return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
-}
-
-/*
-** Mark this cursor as an incremental blob cursor.
-*/
-void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
- pCur->curFlags |= BTCF_Incrblob;
- pCur->pBtree->hasIncrblobCur = 1;
-}
-#endif
-
-/*
-** Set both the "read version" (single byte at byte offset 18) and
-** "write version" (single byte at byte offset 19) fields in the database
-** header to iVersion.
-*/
-int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
- BtShared *pBt = pBtree->pBt;
- int rc; /* Return code */
-
- assert( iVersion==1 || iVersion==2 );
-
- /* If setting the version fields to 1, do not automatically open the
- ** WAL connection, even if the version fields are currently set to 2.
- */
- pBt->btsFlags &= ~BTS_NO_WAL;
- if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
-
- rc = sqlite3BtreeBeginTrans(pBtree, 0);
- if( rc==SQLITE_OK ){
- u8 *aData = pBt->pPage1->aData;
- if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
- rc = sqlite3BtreeBeginTrans(pBtree, 2);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- if( rc==SQLITE_OK ){
- aData[18] = (u8)iVersion;
- aData[19] = (u8)iVersion;
- }
- }
- }
- }
-
- pBt->btsFlags &= ~BTS_NO_WAL;
- return rc;
-}
-
-/*
-** Return true if the cursor has a hint specified. This routine is
-** only used from within assert() statements
-*/
-int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
- return (pCsr->hints & mask)!=0;
-}
-
-/*
-** Return true if the given Btree is read-only.
-*/
-int sqlite3BtreeIsReadonly(Btree *p){
- return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
-}
-
-/*
-** Return the size of the header added to each page by this module.
-*/
-int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE)
-/*
-** Return true if the Btree passed as the only argument is sharable.
-*/
-int sqlite3BtreeSharable(Btree *p){
- return p->sharable;
-}
-
-/*
-** Return the number of connections to the BtShared object accessed by
-** the Btree handle passed as the only argument. For private caches
-** this is always 1. For shared caches it may be 1 or greater.
-*/
-int sqlite3BtreeConnectionCount(Btree *p){
- testcase( p->sharable );
- return p->pBt->nRef;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/btree.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/btree.h
deleted file mode 100644
index b5bf9f7564c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/btree.h
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 header file defines the interface that the sqlite B-Tree file
-** subsystem. See comments in the source code for a detailed description
-** of what each interface routine does.
-*/
-#ifndef SQLITE_BTREE_H
-#define SQLITE_BTREE_H
-
-/* TODO: This definition is just included so other modules compile. It
-** needs to be revisited.
-*/
-#define SQLITE_N_BTREE_META 16
-
-/*
-** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
-** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
-*/
-#ifndef SQLITE_DEFAULT_AUTOVACUUM
- #define SQLITE_DEFAULT_AUTOVACUUM 0
-#endif
-
-#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */
-#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */
-#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */
-
-/*
-** Forward declarations of structure
-*/
-typedef struct Btree Btree;
-typedef struct BtCursor BtCursor;
-typedef struct BtShared BtShared;
-typedef struct BtreePayload BtreePayload;
-
-
-int sqlite3BtreeOpen(
- sqlite3_vfs *pVfs, /* VFS to use with this b-tree */
- const char *zFilename, /* Name of database file to open */
- sqlite3 *db, /* Associated database connection */
- Btree **ppBtree, /* Return open Btree* here */
- int flags, /* Flags */
- int vfsFlags /* Flags passed through to VFS open */
-);
-
-/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
-** following values.
-**
-** NOTE: These values must match the corresponding PAGER_ values in
-** pager.h.
-*/
-#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
-#define BTREE_MEMORY 2 /* This is an in-memory DB */
-#define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */
-#define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */
-
-int sqlite3BtreeClose(Btree*);
-int sqlite3BtreeSetCacheSize(Btree*,int);
-int sqlite3BtreeSetSpillSize(Btree*,int);
-#if SQLITE_MAX_MMAP_SIZE>0
- int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
-#endif
-int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
-int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
-int sqlite3BtreeGetPageSize(Btree*);
-int sqlite3BtreeMaxPageCount(Btree*,int);
-u32 sqlite3BtreeLastPage(Btree*);
-int sqlite3BtreeSecureDelete(Btree*,int);
-int sqlite3BtreeGetOptimalReserve(Btree*);
-int sqlite3BtreeGetReserveNoMutex(Btree *p);
-int sqlite3BtreeSetAutoVacuum(Btree *, int);
-int sqlite3BtreeGetAutoVacuum(Btree *);
-int sqlite3BtreeBeginTrans(Btree*,int);
-int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
-int sqlite3BtreeCommitPhaseTwo(Btree*, int);
-int sqlite3BtreeCommit(Btree*);
-int sqlite3BtreeRollback(Btree*,int,int);
-int sqlite3BtreeBeginStmt(Btree*,int);
-int sqlite3BtreeCreateTable(Btree*, int*, int flags);
-int sqlite3BtreeIsInTrans(Btree*);
-int sqlite3BtreeIsInReadTrans(Btree*);
-int sqlite3BtreeIsInBackup(Btree*);
-void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
-int sqlite3BtreeSchemaLocked(Btree *pBtree);
-#ifndef SQLITE_OMIT_SHARED_CACHE
-int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
-#endif
-int sqlite3BtreeSavepoint(Btree *, int, int);
-
-const char *sqlite3BtreeGetFilename(Btree *);
-const char *sqlite3BtreeGetJournalname(Btree *);
-int sqlite3BtreeCopyFile(Btree *, Btree *);
-
-int sqlite3BtreeIncrVacuum(Btree *);
-
-/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
-** of the flags shown below.
-**
-** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set.
-** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data
-** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With
-** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored
-** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL
-** indices.)
-*/
-#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
-#define BTREE_BLOBKEY 2 /* Table has keys only - no data */
-
-int sqlite3BtreeDropTable(Btree*, int, int*);
-int sqlite3BtreeClearTable(Btree*, int, int*);
-int sqlite3BtreeClearTableOfCursor(BtCursor*);
-int sqlite3BtreeTripAllCursors(Btree*, int, int);
-
-void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
-int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
-
-int sqlite3BtreeNewDb(Btree *p);
-
-/*
-** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
-** should be one of the following values. The integer values are assigned
-** to constants so that the offset of the corresponding field in an
-** SQLite database header may be found using the following formula:
-**
-** offset = 36 + (idx * 4)
-**
-** For example, the free-page-count field is located at byte offset 36 of
-** the database file header. The incr-vacuum-flag field is located at
-** byte offset 64 (== 36+4*7).
-**
-** The BTREE_DATA_VERSION value is not really a value stored in the header.
-** It is a read-only number computed by the pager. But we merge it with
-** the header value access routines since its access pattern is the same.
-** Call it a "virtual meta value".
-*/
-#define BTREE_FREE_PAGE_COUNT 0
-#define BTREE_SCHEMA_VERSION 1
-#define BTREE_FILE_FORMAT 2
-#define BTREE_DEFAULT_CACHE_SIZE 3
-#define BTREE_LARGEST_ROOT_PAGE 4
-#define BTREE_TEXT_ENCODING 5
-#define BTREE_USER_VERSION 6
-#define BTREE_INCR_VACUUM 7
-#define BTREE_APPLICATION_ID 8
-#define BTREE_DATA_VERSION 15 /* A virtual meta-value */
-
-/*
-** Kinds of hints that can be passed into the sqlite3BtreeCursorHint()
-** interface.
-**
-** BTREE_HINT_RANGE (arguments: Expr*, Mem*)
-**
-** The first argument is an Expr* (which is guaranteed to be constant for
-** the lifetime of the cursor) that defines constraints on which rows
-** might be fetched with this cursor. The Expr* tree may contain
-** TK_REGISTER nodes that refer to values stored in the array of registers
-** passed as the second parameter. In other words, if Expr.op==TK_REGISTER
-** then the value of the node is the value in Mem[pExpr.iTable]. Any
-** TK_COLUMN node in the expression tree refers to the Expr.iColumn-th
-** column of the b-tree of the cursor. The Expr tree will not contain
-** any function calls nor subqueries nor references to b-trees other than
-** the cursor being hinted.
-**
-** The design of the _RANGE hint is aid b-tree implementations that try
-** to prefetch content from remote machines - to provide those
-** implementations with limits on what needs to be prefetched and thereby
-** reduce network bandwidth.
-**
-** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by
-** standard SQLite. The other hints are provided for extentions that use
-** the SQLite parser and code generator but substitute their own storage
-** engine.
-*/
-#define BTREE_HINT_RANGE 0 /* Range constraints on queries */
-
-/*
-** Values that may be OR'd together to form the argument to the
-** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint():
-**
-** The BTREE_BULKLOAD flag is set on index cursors when the index is going
-** to be filled with content that is already in sorted order.
-**
-** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or
-** OP_SeekLE opcodes for a range search, but where the range of entries
-** selected will all have the same key. In other words, the cursor will
-** be used only for equality key searches.
-**
-*/
-#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
-#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
-
-/*
-** Flags passed as the third argument to sqlite3BtreeCursor().
-**
-** For read-only cursors the wrFlag argument is always zero. For read-write
-** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or just
-** (BTREE_WRCSR). If the BTREE_FORDELETE bit is set, then the cursor will
-** only be used by SQLite for the following:
-**
-** * to seek to and then delete specific entries, and/or
-**
-** * to read values that will be used to create keys that other
-** BTREE_FORDELETE cursors will seek to and delete.
-**
-** The BTREE_FORDELETE flag is an optimization hint. It is not used by
-** by this, the native b-tree engine of SQLite, but it is available to
-** alternative storage engines that might be substituted in place of this
-** b-tree system. For alternative storage engines in which a delete of
-** the main table row automatically deletes corresponding index rows,
-** the FORDELETE flag hint allows those alternative storage engines to
-** skip a lot of work. Namely: FORDELETE cursors may treat all SEEK
-** and DELETE operations as no-ops, and any READ operation against a
-** FORDELETE cursor may return a null row: 0x01 0x00.
-*/
-#define BTREE_WRCSR 0x00000004 /* read-write cursor */
-#define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */
-
-int sqlite3BtreeCursor(
- Btree*, /* BTree containing table to open */
- int iTable, /* Index of root page */
- int wrFlag, /* 1 for writing. 0 for read-only */
- struct KeyInfo*, /* First argument to compare function */
- BtCursor *pCursor /* Space to write cursor structure */
-);
-BtCursor *sqlite3BtreeFakeValidCursor(void);
-int sqlite3BtreeCursorSize(void);
-void sqlite3BtreeCursorZero(BtCursor*);
-void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
-void sqlite3BtreeCursorHint(BtCursor*, int, ...);
-#endif
-
-int sqlite3BtreeCloseCursor(BtCursor*);
-int sqlite3BtreeMovetoUnpacked(
- BtCursor*,
- UnpackedRecord *pUnKey,
- i64 intKey,
- int bias,
- int *pRes
-);
-int sqlite3BtreeCursorHasMoved(BtCursor*);
-int sqlite3BtreeCursorRestore(BtCursor*, int*);
-int sqlite3BtreeDelete(BtCursor*, u8 flags);
-
-/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */
-#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
-#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
-#define BTREE_APPEND 0x08 /* Insert is likely an append */
-
-/* An instance of the BtreePayload object describes the content of a single
-** entry in either an index or table btree.
-**
-** Index btrees (used for indexes and also WITHOUT ROWID tables) contain
-** an arbitrary key and no data. These btrees have pKey,nKey set to the
-** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem
-** fields give an array of Mem objects that are a decomposition of the key.
-** The nMem field might be zero, indicating that no decomposition is available.
-**
-** Table btrees (used for rowid tables) contain an integer rowid used as
-** the key and passed in the nKey field. The pKey field is zero.
-** pData,nData hold the content of the new entry. nZero extra zero bytes
-** are appended to the end of the content when constructing the entry.
-** The aMem,nMem fields are uninitialized for table btrees.
-**
-** Field usage summary:
-**
-** Table BTrees Index Btrees
-**
-** pKey always NULL encoded key
-** nKey the ROWID length of pKey
-** pData data not used
-** aMem not used decomposed key value
-** nMem not used entries in aMem
-** nData length of pData not used
-** nZero extra zeros after pData not used
-**
-** This object is used to pass information into sqlite3BtreeInsert(). The
-** same information used to be passed as five separate parameters. But placing
-** the information into this object helps to keep the interface more
-** organized and understandable, and it also helps the resulting code to
-** run a little faster by using fewer registers for parameter passing.
-*/
-struct BtreePayload {
- const void *pKey; /* Key content for indexes. NULL for tables */
- sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */
- const void *pData; /* Data for tables. */
- sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */
- u16 nMem; /* Number of aMem[] value. Might be zero */
- int nData; /* Size of pData. 0 if none. */
- int nZero; /* Extra zero data appended after pData,nData */
-};
-
-int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
- int flags, int seekResult);
-int sqlite3BtreeFirst(BtCursor*, int *pRes);
-int sqlite3BtreeLast(BtCursor*, int *pRes);
-int sqlite3BtreeNext(BtCursor*, int flags);
-int sqlite3BtreeEof(BtCursor*);
-int sqlite3BtreePrevious(BtCursor*, int flags);
-i64 sqlite3BtreeIntegerKey(BtCursor*);
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
-i64 sqlite3BtreeOffset(BtCursor*);
-#endif
-int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
-const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
-u32 sqlite3BtreePayloadSize(BtCursor*);
-
-char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
-struct Pager *sqlite3BtreePager(Btree*);
-i64 sqlite3BtreeRowCountEst(BtCursor*);
-
-#ifndef SQLITE_OMIT_INCRBLOB
-int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
-int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
-void sqlite3BtreeIncrblobCursor(BtCursor *);
-#endif
-void sqlite3BtreeClearCursor(BtCursor *);
-int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
-int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
-int sqlite3BtreeIsReadonly(Btree *pBt);
-int sqlite3HeaderSizeBtree(void);
-
-#ifndef NDEBUG
-int sqlite3BtreeCursorIsValid(BtCursor*);
-#endif
-int sqlite3BtreeCursorIsValidNN(BtCursor*);
-
-#ifndef SQLITE_OMIT_BTREECOUNT
-int sqlite3BtreeCount(BtCursor *, i64 *);
-#endif
-
-#ifdef SQLITE_TEST
-int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
-void sqlite3BtreeCursorList(Btree*);
-#endif
-
-#ifndef SQLITE_OMIT_WAL
- int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
-#endif
-
-/*
-** If we are not using shared cache, then there is no need to
-** use mutexes to access the BtShared structures. So make the
-** Enter and Leave procedures no-ops.
-*/
-#ifndef SQLITE_OMIT_SHARED_CACHE
- void sqlite3BtreeEnter(Btree*);
- void sqlite3BtreeEnterAll(sqlite3*);
- int sqlite3BtreeSharable(Btree*);
- void sqlite3BtreeEnterCursor(BtCursor*);
- int sqlite3BtreeConnectionCount(Btree*);
-#else
-# define sqlite3BtreeEnter(X)
-# define sqlite3BtreeEnterAll(X)
-# define sqlite3BtreeSharable(X) 0
-# define sqlite3BtreeEnterCursor(X)
-# define sqlite3BtreeConnectionCount(X) 1
-#endif
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
- void sqlite3BtreeLeave(Btree*);
- void sqlite3BtreeLeaveCursor(BtCursor*);
- void sqlite3BtreeLeaveAll(sqlite3*);
-#ifndef NDEBUG
- /* These routines are used inside assert() statements only. */
- int sqlite3BtreeHoldsMutex(Btree*);
- int sqlite3BtreeHoldsAllMutexes(sqlite3*);
- int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
-#endif
-#else
-
-# define sqlite3BtreeLeave(X)
-# define sqlite3BtreeLeaveCursor(X)
-# define sqlite3BtreeLeaveAll(X)
-
-# define sqlite3BtreeHoldsMutex(X) 1
-# define sqlite3BtreeHoldsAllMutexes(X) 1
-# define sqlite3SchemaMutexHeld(X,Y,Z) 1
-#endif
-
-
-#endif /* SQLITE_BTREE_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/btreeInt.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/btreeInt.h
deleted file mode 100644
index d1e2c08d18f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/btreeInt.h
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
-** 2004 April 6
-**
-** 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 an external (disk-based) database using BTrees.
-** For a detailed discussion of BTrees, refer to
-**
-** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
-** "Sorting And Searching", pages 473-480. Addison-Wesley
-** Publishing Company, Reading, Massachusetts.
-**
-** The basic idea is that each page of the file contains N database
-** entries and N+1 pointers to subpages.
-**
-** ----------------------------------------------------------------
-** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) |
-** ----------------------------------------------------------------
-**
-** All of the keys on the page that Ptr(0) points to have values less
-** than Key(0). All of the keys on page Ptr(1) and its subpages have
-** values greater than Key(0) and less than Key(1). All of the keys
-** on Ptr(N) and its subpages have values greater than Key(N-1). And
-** so forth.
-**
-** Finding a particular key requires reading O(log(M)) pages from the
-** disk where M is the number of entries in the tree.
-**
-** In this implementation, a single file can hold one or more separate
-** BTrees. Each BTree is identified by the index of its root page. The
-** key and data for any entry are combined to form the "payload". A
-** fixed amount of payload can be carried directly on the database
-** page. If the payload is larger than the preset amount then surplus
-** bytes are stored on overflow pages. The payload for an entry
-** and the preceding pointer are combined to form a "Cell". Each
-** page has a small header which contains the Ptr(N) pointer and other
-** information such as the size of key and data.
-**
-** FORMAT DETAILS
-**
-** The file is divided into pages. The first page is called page 1,
-** the second is page 2, and so forth. A page number of zero indicates
-** "no such page". The page size can be any power of 2 between 512 and 65536.
-** Each page can be either a btree page, a freelist page, an overflow
-** page, or a pointer-map page.
-**
-** The first page is always a btree page. The first 100 bytes of the first
-** page contain a special header (the "file header") that describes the file.
-** The format of the file header is as follows:
-**
-** OFFSET SIZE DESCRIPTION
-** 0 16 Header string: "SQLite format 3\000"
-** 16 2 Page size in bytes. (1 means 65536)
-** 18 1 File format write version
-** 19 1 File format read version
-** 20 1 Bytes of unused space at the end of each page
-** 21 1 Max embedded payload fraction (must be 64)
-** 22 1 Min embedded payload fraction (must be 32)
-** 23 1 Min leaf payload fraction (must be 32)
-** 24 4 File change counter
-** 28 4 Reserved for future use
-** 32 4 First freelist page
-** 36 4 Number of freelist pages in the file
-** 40 60 15 4-byte meta values passed to higher layers
-**
-** 40 4 Schema cookie
-** 44 4 File format of schema layer
-** 48 4 Size of page cache
-** 52 4 Largest root-page (auto/incr_vacuum)
-** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
-** 60 4 User version
-** 64 4 Incremental vacuum mode
-** 68 4 Application-ID
-** 72 20 unused
-** 92 4 The version-valid-for number
-** 96 4 SQLITE_VERSION_NUMBER
-**
-** All of the integer values are big-endian (most significant byte first).
-**
-** The file change counter is incremented when the database is changed
-** This counter allows other processes to know when the file has changed
-** and thus when they need to flush their cache.
-**
-** The max embedded payload fraction is the amount of the total usable
-** space in a page that can be consumed by a single cell for standard
-** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default
-** is to limit the maximum cell size so that at least 4 cells will fit
-** on one page. Thus the default max embedded payload fraction is 64.
-**
-** If the payload for a cell is larger than the max payload, then extra
-** payload is spilled to overflow pages. Once an overflow page is allocated,
-** as many bytes as possible are moved into the overflow pages without letting
-** the cell size drop below the min embedded payload fraction.
-**
-** The min leaf payload fraction is like the min embedded payload fraction
-** except that it applies to leaf nodes in a LEAFDATA tree. The maximum
-** payload fraction for a LEAFDATA tree is always 100% (or 255) and it
-** not specified in the header.
-**
-** Each btree pages is divided into three sections: The header, the
-** cell pointer array, and the cell content area. Page 1 also has a 100-byte
-** file header that occurs before the page header.
-**
-** |----------------|
-** | file header | 100 bytes. Page 1 only.
-** |----------------|
-** | page header | 8 bytes for leaves. 12 bytes for interior nodes
-** |----------------|
-** | cell pointer | | 2 bytes per cell. Sorted order.
-** | array | | Grows downward
-** | | v
-** |----------------|
-** | unallocated |
-** | space |
-** |----------------| ^ Grows upwards
-** | cell content | | Arbitrary order interspersed with freeblocks.
-** | area | | and free space fragments.
-** |----------------|
-**
-** The page headers looks like this:
-**
-** OFFSET SIZE DESCRIPTION
-** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf
-** 1 2 byte offset to the first freeblock
-** 3 2 number of cells on this page
-** 5 2 first byte of the cell content area
-** 7 1 number of fragmented free bytes
-** 8 4 Right child (the Ptr(N) value). Omitted on leaves.
-**
-** The flags define the format of this btree page. The leaf flag means that
-** this page has no children. The zerodata flag means that this page carries
-** only keys and no data. The intkey flag means that the key is an integer
-** which is stored in the key size entry of the cell header rather than in
-** the payload area.
-**
-** The cell pointer array begins on the first byte after the page header.
-** The cell pointer array contains zero or more 2-byte numbers which are
-** offsets from the beginning of the page to the cell content in the cell
-** content area. The cell pointers occur in sorted order. The system strives
-** to keep free space after the last cell pointer so that new cells can
-** be easily added without having to defragment the page.
-**
-** Cell content is stored at the very end of the page and grows toward the
-** beginning of the page.
-**
-** Unused space within the cell content area is collected into a linked list of
-** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset
-** to the first freeblock is given in the header. Freeblocks occur in
-** increasing order. Because a freeblock must be at least 4 bytes in size,
-** any group of 3 or fewer unused bytes in the cell content area cannot
-** exist on the freeblock chain. A group of 3 or fewer free bytes is called
-** a fragment. The total number of bytes in all fragments is recorded.
-** in the page header at offset 7.
-**
-** SIZE DESCRIPTION
-** 2 Byte offset of the next freeblock
-** 2 Bytes in this freeblock
-**
-** Cells are of variable length. Cells are stored in the cell content area at
-** the end of the page. Pointers to the cells are in the cell pointer array
-** that immediately follows the page header. Cells is not necessarily
-** contiguous or in order, but cell pointers are contiguous and in order.
-**
-** Cell content makes use of variable length integers. A variable
-** length integer is 1 to 9 bytes where the lower 7 bits of each
-** byte are used. The integer consists of all bytes that have bit 8 set and
-** the first byte with bit 8 clear. The most significant byte of the integer
-** appears first. A variable-length integer may not be more than 9 bytes long.
-** As a special case, all 8 bytes of the 9th byte are used as data. This
-** allows a 64-bit integer to be encoded in 9 bytes.
-**
-** 0x00 becomes 0x00000000
-** 0x7f becomes 0x0000007f
-** 0x81 0x00 becomes 0x00000080
-** 0x82 0x00 becomes 0x00000100
-** 0x80 0x7f becomes 0x0000007f
-** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678
-** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081
-**
-** Variable length integers are used for rowids and to hold the number of
-** bytes of key and data in a btree cell.
-**
-** The content of a cell looks like this:
-**
-** SIZE DESCRIPTION
-** 4 Page number of the left child. Omitted if leaf flag is set.
-** var Number of bytes of data. Omitted if the zerodata flag is set.
-** var Number of bytes of key. Or the key itself if intkey flag is set.
-** * Payload
-** 4 First page of the overflow chain. Omitted if no overflow
-**
-** Overflow pages form a linked list. Each page except the last is completely
-** filled with data (pagesize - 4 bytes). The last page can have as little
-** as 1 byte of data.
-**
-** SIZE DESCRIPTION
-** 4 Page number of next overflow page
-** * Data
-**
-** Freelist pages come in two subtypes: trunk pages and leaf pages. The
-** file header points to the first in a linked list of trunk page. Each trunk
-** page points to multiple leaf pages. The content of a leaf page is
-** unspecified. A trunk page looks like this:
-**
-** SIZE DESCRIPTION
-** 4 Page number of next trunk page
-** 4 Number of leaf pointers on this page
-** * zero or more pages numbers of leaves
-*/
-#include "sqliteInt.h"
-
-
-/* The following value is the maximum cell size assuming a maximum page
-** size give above.
-*/
-#define MX_CELL_SIZE(pBt) ((int)(pBt->pageSize-8))
-
-/* The maximum number of cells on a single page of the database. This
-** assumes a minimum cell size of 6 bytes (4 bytes for the cell itself
-** plus 2 bytes for the index to the cell in the page header). Such
-** small cells will be rare, but they are possible.
-*/
-#define MX_CELL(pBt) ((pBt->pageSize-8)/6)
-
-/* Forward declarations */
-typedef struct MemPage MemPage;
-typedef struct BtLock BtLock;
-typedef struct CellInfo CellInfo;
-
-/*
-** This is a magic string that appears at the beginning of every
-** SQLite database in order to identify the file as a real database.
-**
-** You can change this value at compile-time by specifying a
-** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
-** header must be exactly 16 bytes including the zero-terminator so
-** the string itself should be 15 characters long. If you change
-** the header, then your custom library will not be able to read
-** databases generated by the standard tools and the standard tools
-** will not be able to read databases created by your custom library.
-*/
-#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
-# define SQLITE_FILE_HEADER "SQLite format 3"
-#endif
-
-/*
-** Page type flags. An ORed combination of these flags appear as the
-** first byte of on-disk image of every BTree page.
-*/
-#define PTF_INTKEY 0x01
-#define PTF_ZERODATA 0x02
-#define PTF_LEAFDATA 0x04
-#define PTF_LEAF 0x08
-
-/*
-** An instance of this object stores information about each a single database
-** page that has been loaded into memory. The information in this object
-** is derived from the raw on-disk page content.
-**
-** As each database page is loaded into memory, the pager allocats an
-** instance of this object and zeros the first 8 bytes. (This is the
-** "extra" information associated with each page of the pager.)
-**
-** Access to all fields of this structure is controlled by the mutex
-** stored in MemPage.pBt->mutex.
-*/
-struct MemPage {
- u8 isInit; /* True if previously initialized. MUST BE FIRST! */
- u8 bBusy; /* Prevent endless loops on corrupt database files */
- u8 intKey; /* True if table b-trees. False for index b-trees */
- u8 intKeyLeaf; /* True if the leaf of an intKey table */
- Pgno pgno; /* Page number for this page */
- /* Only the first 8 bytes (above) are zeroed by pager.c when a new page
- ** is allocated. All fields that follow must be initialized before use */
- u8 leaf; /* True if a leaf page */
- u8 hdrOffset; /* 100 for page 1. 0 otherwise */
- u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
- u8 max1bytePayload; /* min(maxLocal,127) */
- u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
- u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
- u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
- u16 cellOffset; /* Index in aData of first cell pointer */
- u16 nFree; /* Number of free bytes on the page */
- u16 nCell; /* Number of cells on this page, local and ovfl */
- u16 maskPage; /* Mask for page offset */
- u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th
- ** non-overflow cell */
- u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
- BtShared *pBt; /* Pointer to BtShared that this page is part of */
- u8 *aData; /* Pointer to disk image of the page data */
- u8 *aDataEnd; /* One byte past the end of usable data */
- u8 *aCellIdx; /* The cell index area */
- u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */
- DbPage *pDbPage; /* Pager page handle */
- u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */
- void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */
-};
-
-/*
-** A linked list of the following structures is stored at BtShared.pLock.
-** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
-** is opened on the table with root page BtShared.iTable. Locks are removed
-** from this list when a transaction is committed or rolled back, or when
-** a btree handle is closed.
-*/
-struct BtLock {
- Btree *pBtree; /* Btree handle holding this lock */
- Pgno iTable; /* Root page of table */
- u8 eLock; /* READ_LOCK or WRITE_LOCK */
- BtLock *pNext; /* Next in BtShared.pLock list */
-};
-
-/* Candidate values for BtLock.eLock */
-#define READ_LOCK 1
-#define WRITE_LOCK 2
-
-/* A Btree handle
-**
-** A database connection contains a pointer to an instance of
-** this object for every database file that it has open. This structure
-** is opaque to the database connection. The database connection cannot
-** see the internals of this structure and only deals with pointers to
-** this structure.
-**
-** For some database files, the same underlying database cache might be
-** shared between multiple connections. In that case, each connection
-** has it own instance of this object. But each instance of this object
-** points to the same BtShared object. The database cache and the
-** schema associated with the database file are all contained within
-** the BtShared object.
-**
-** All fields in this structure are accessed under sqlite3.mutex.
-** The pBt pointer itself may not be changed while there exists cursors
-** in the referenced BtShared that point back to this Btree since those
-** cursors have to go through this Btree to find their BtShared and
-** they often do so without holding sqlite3.mutex.
-*/
-struct Btree {
- sqlite3 *db; /* The database connection holding this btree */
- BtShared *pBt; /* Sharable content of this btree */
- u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
- u8 sharable; /* True if we can share pBt with another db */
- u8 locked; /* True if db currently has pBt locked */
- u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
- int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
- int nBackup; /* Number of backup operations reading this btree */
- u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
- Btree *pNext; /* List of other sharable Btrees from the same db */
- Btree *pPrev; /* Back pointer of the same list */
-#ifndef SQLITE_OMIT_SHARED_CACHE
- BtLock lock; /* Object used to lock page 1 */
-#endif
-};
-
-/*
-** Btree.inTrans may take one of the following values.
-**
-** If the shared-data extension is enabled, there may be multiple users
-** of the Btree structure. At most one of these may open a write transaction,
-** but any number may have active read transactions.
-*/
-#define TRANS_NONE 0
-#define TRANS_READ 1
-#define TRANS_WRITE 2
-
-/*
-** An instance of this object represents a single database file.
-**
-** A single database file can be in use at the same time by two
-** or more database connections. When two or more connections are
-** sharing the same database file, each connection has it own
-** private Btree object for the file and each of those Btrees points
-** to this one BtShared object. BtShared.nRef is the number of
-** connections currently sharing this database file.
-**
-** Fields in this structure are accessed under the BtShared.mutex
-** mutex, except for nRef and pNext which are accessed under the
-** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field
-** may not be modified once it is initially set as long as nRef>0.
-** The pSchema field may be set once under BtShared.mutex and
-** thereafter is unchanged as long as nRef>0.
-**
-** isPending:
-**
-** If a BtShared client fails to obtain a write-lock on a database
-** table (because there exists one or more read-locks on the table),
-** the shared-cache enters 'pending-lock' state and isPending is
-** set to true.
-**
-** The shared-cache leaves the 'pending lock' state when either of
-** the following occur:
-**
-** 1) The current writer (BtShared.pWriter) concludes its transaction, OR
-** 2) The number of locks held by other connections drops to zero.
-**
-** while in the 'pending-lock' state, no connection may start a new
-** transaction.
-**
-** This feature is included to help prevent writer-starvation.
-*/
-struct BtShared {
- Pager *pPager; /* The page cache */
- sqlite3 *db; /* Database connection currently using this Btree */
- BtCursor *pCursor; /* A list of all open cursors */
- MemPage *pPage1; /* First page of the database */
- u8 openFlags; /* Flags to sqlite3BtreeOpen() */
-#ifndef SQLITE_OMIT_AUTOVACUUM
- u8 autoVacuum; /* True if auto-vacuum is enabled */
- u8 incrVacuum; /* True if incr-vacuum is enabled */
- u8 bDoTruncate; /* True to truncate db on commit */
-#endif
- u8 inTransaction; /* Transaction state */
- u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
-#ifdef SQLITE_HAS_CODEC
- u8 optimalReserve; /* Desired amount of reserved space per page */
-#endif
- u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
- u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
- u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
- u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
- u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
- u32 pageSize; /* Total number of bytes on a page */
- u32 usableSize; /* Number of usable bytes on each page */
- int nTransaction; /* Number of open transactions (read + write) */
- u32 nPage; /* Number of pages in the database */
- void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
- void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
- sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */
- Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */
-#ifndef SQLITE_OMIT_SHARED_CACHE
- int nRef; /* Number of references to this structure */
- BtShared *pNext; /* Next on a list of sharable BtShared structs */
- BtLock *pLock; /* List of locks held on this shared-btree struct */
- Btree *pWriter; /* Btree with currently open write transaction */
-#endif
- u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
-};
-
-/*
-** Allowed values for BtShared.btsFlags
-*/
-#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
-#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
-#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
-#define BTS_OVERWRITE 0x0008 /* Overwrite deleted content with zeros */
-#define BTS_FAST_SECURE 0x000c /* Combination of the previous two */
-#define BTS_INITIALLY_EMPTY 0x0010 /* Database was empty at trans start */
-#define BTS_NO_WAL 0x0020 /* Do not open write-ahead-log files */
-#define BTS_EXCLUSIVE 0x0040 /* pWriter has an exclusive lock */
-#define BTS_PENDING 0x0080 /* Waiting for read-locks to clear */
-
-/*
-** An instance of the following structure is used to hold information
-** about a cell. The parseCellPtr() function fills in this structure
-** based on information extract from the raw disk page.
-*/
-struct CellInfo {
- i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
- u8 *pPayload; /* Pointer to the start of payload */
- u32 nPayload; /* Bytes of payload */
- u16 nLocal; /* Amount of payload held locally, not on overflow */
- u16 nSize; /* Size of the cell content on the main b-tree page */
-};
-
-/*
-** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
-** this will be declared corrupt. This value is calculated based on a
-** maximum database size of 2^31 pages a minimum fanout of 2 for a
-** root-node and 3 for all other internal nodes.
-**
-** If a tree that appears to be taller than this is encountered, it is
-** assumed that the database is corrupt.
-*/
-#define BTCURSOR_MAX_DEPTH 20
-
-/*
-** A cursor is a pointer to a particular entry within a particular
-** b-tree within a database file.
-**
-** The entry is identified by its MemPage and the index in
-** MemPage.aCell[] of the entry.
-**
-** A single database file can be shared by two more database connections,
-** but cursors cannot be shared. Each cursor is associated with a
-** particular database connection identified BtCursor.pBtree.db.
-**
-** Fields in this structure are accessed under the BtShared.mutex
-** found at self->pBt->mutex.
-**
-** skipNext meaning:
-** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op.
-** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op.
-** eState==FAULT: Cursor fault with skipNext as error code.
-*/
-struct BtCursor {
- u8 eState; /* One of the CURSOR_XXX constants (see below) */
- u8 curFlags; /* zero or more BTCF_* flags defined below */
- u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
- u8 hints; /* As configured by CursorSetHints() */
- int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
- ** Error code if eState==CURSOR_FAULT */
- Btree *pBtree; /* The Btree to which this cursor belongs */
- Pgno *aOverflow; /* Cache of overflow page locations */
- void *pKey; /* Saved key that was cursor last known position */
- /* All fields above are zeroed when the cursor is allocated. See
- ** sqlite3BtreeCursorZero(). Fields that follow must be manually
- ** initialized. */
-#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */
- BtShared *pBt; /* The BtShared this cursor points to */
- BtCursor *pNext; /* Forms a linked list of all cursors */
- CellInfo info; /* A parse of the cell we are pointing at */
- i64 nKey; /* Size of pKey, or last integer key */
- Pgno pgnoRoot; /* The root page of this tree */
- i8 iPage; /* Index of current page in apPage */
- u8 curIntKey; /* Value of apPage[0]->intKey */
- u16 ix; /* Current index for apPage[iPage] */
- u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */
- struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */
- MemPage *pPage; /* Current page */
- MemPage *apPage[BTCURSOR_MAX_DEPTH-1]; /* Stack of parents of current page */
-};
-
-/*
-** Legal values for BtCursor.curFlags
-*/
-#define BTCF_WriteFlag 0x01 /* True if a write cursor */
-#define BTCF_ValidNKey 0x02 /* True if info.nKey is valid */
-#define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */
-#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */
-#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
-#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */
-
-/*
-** Potential values for BtCursor.eState.
-**
-** CURSOR_INVALID:
-** Cursor does not point to a valid entry. This can happen (for example)
-** because the table is empty or because BtreeCursorFirst() has not been
-** called.
-**
-** CURSOR_VALID:
-** Cursor points to a valid entry. getPayload() etc. may be called.
-**
-** CURSOR_SKIPNEXT:
-** Cursor is valid except that the Cursor.skipNext field is non-zero
-** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
-** operation should be a no-op.
-**
-** CURSOR_REQUIRESEEK:
-** The table that this cursor was opened on still exists, but has been
-** modified since the cursor was last used. The cursor position is saved
-** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
-** this state, restoreCursorPosition() can be called to attempt to
-** seek the cursor to the saved position.
-**
-** CURSOR_FAULT:
-** An unrecoverable error (an I/O error or a malloc failure) has occurred
-** on a different connection that shares the BtShared cache with this
-** cursor. The error has left the cache in an inconsistent state.
-** Do nothing else with this cursor. Any attempt to use the cursor
-** should return the error code stored in BtCursor.skipNext
-*/
-#define CURSOR_VALID 0
-#define CURSOR_INVALID 1
-#define CURSOR_SKIPNEXT 2
-#define CURSOR_REQUIRESEEK 3
-#define CURSOR_FAULT 4
-
-/*
-** The database page the PENDING_BYTE occupies. This page is never used.
-*/
-# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
-
-/*
-** These macros define the location of the pointer-map entry for a
-** database page. The first argument to each is the number of usable
-** bytes on each page of the database (often 1024). The second is the
-** page number to look up in the pointer map.
-**
-** PTRMAP_PAGENO returns the database page number of the pointer-map
-** page that stores the required pointer. PTRMAP_PTROFFSET returns
-** the offset of the requested map entry.
-**
-** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
-** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
-** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
-** this test.
-*/
-#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno)
-#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1))
-#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno))
-
-/*
-** The pointer map is a lookup table that identifies the parent page for
-** each child page in the database file. The parent page is the page that
-** contains a pointer to the child. Every page in the database contains
-** 0 or 1 parent pages. (In this context 'database page' refers
-** to any page that is not part of the pointer map itself.) Each pointer map
-** entry consists of a single byte 'type' and a 4 byte parent page number.
-** The PTRMAP_XXX identifiers below are the valid types.
-**
-** The purpose of the pointer map is to facility moving pages from one
-** position in the file to another as part of autovacuum. When a page
-** is moved, the pointer in its parent must be updated to point to the
-** new location. The pointer map is used to locate the parent page quickly.
-**
-** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
-** used in this case.
-**
-** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
-** is not used in this case.
-**
-** PTRMAP_OVERFLOW1: The database page is the first page in a list of
-** overflow pages. The page number identifies the page that
-** contains the cell with a pointer to this overflow page.
-**
-** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
-** overflow pages. The page-number identifies the previous
-** page in the overflow page list.
-**
-** PTRMAP_BTREE: The database page is a non-root btree page. The page number
-** identifies the parent page in the btree.
-*/
-#define PTRMAP_ROOTPAGE 1
-#define PTRMAP_FREEPAGE 2
-#define PTRMAP_OVERFLOW1 3
-#define PTRMAP_OVERFLOW2 4
-#define PTRMAP_BTREE 5
-
-/* A bunch of assert() statements to check the transaction state variables
-** of handle p (type Btree*) are internally consistent.
-*/
-#define btreeIntegrity(p) \
- assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
- assert( p->pBt->inTransaction>=p->inTrans );
-
-
-/*
-** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
-** if the database supports auto-vacuum or not. Because it is used
-** within an expression that is an argument to another macro
-** (sqliteMallocRaw), it is not possible to use conditional compilation.
-** So, this macro is defined instead.
-*/
-#ifndef SQLITE_OMIT_AUTOVACUUM
-#define ISAUTOVACUUM (pBt->autoVacuum)
-#else
-#define ISAUTOVACUUM 0
-#endif
-
-
-/*
-** This structure is passed around through all the sanity checking routines
-** in order to keep track of some global state information.
-**
-** The aRef[] array is allocated so that there is 1 bit for each page in
-** the database. As the integrity-check proceeds, for each page used in
-** the database the corresponding bit is set. This allows integrity-check to
-** detect pages that are used twice and orphaned pages (both of which
-** indicate corruption).
-*/
-typedef struct IntegrityCk IntegrityCk;
-struct IntegrityCk {
- BtShared *pBt; /* The tree being checked out */
- Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
- u8 *aPgRef; /* 1 bit per page in the db (see above) */
- Pgno nPage; /* Number of pages in the database */
- int mxErr; /* Stop accumulating errors when this reaches zero */
- int nErr; /* Number of messages written to zErrMsg so far */
- int mallocFailed; /* A memory allocation error has occurred */
- const char *zPfx; /* Error message prefix */
- int v1, v2; /* Values for up to two %d fields in zPfx */
- StrAccum errMsg; /* Accumulate the error message text here */
- u32 *heap; /* Min-heap used for analyzing cell coverage */
-};
-
-/*
-** Routines to read or write a two- and four-byte big-endian integer values.
-*/
-#define get2byte(x) ((x)[0]<<8 | (x)[1])
-#define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v))
-#define get4byte sqlite3Get4byte
-#define put4byte sqlite3Put4byte
-
-/*
-** get2byteAligned(), unlike get2byte(), requires that its argument point to a
-** two-byte aligned address. get2bytea() is only used for accessing the
-** cell addresses in a btree header.
-*/
-#if SQLITE_BYTEORDER==4321
-# define get2byteAligned(x) (*(u16*)(x))
-#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000
-# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x))
-#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
-# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x))
-#else
-# define get2byteAligned(x) ((x)[0]<<8 | (x)[1])
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/build.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/build.c
deleted file mode 100644
index 3d982f72ea5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/build.c
+++ /dev/null
@@ -1,4495 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains C code routines that are called by the SQLite parser
-** when syntax rules are reduced. The routines in this file handle the
-** following kinds of SQL syntax:
-**
-** CREATE TABLE
-** DROP TABLE
-** CREATE INDEX
-** DROP INDEX
-** creating ID lists
-** BEGIN TRANSACTION
-** COMMIT
-** ROLLBACK
-*/
-#include "sqliteInt.h"
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/*
-** The TableLock structure is only used by the sqlite3TableLock() and
-** codeTableLocks() functions.
-*/
-struct TableLock {
- int iDb; /* The database containing the table to be locked */
- int iTab; /* The root page of the table to be locked */
- u8 isWriteLock; /* True for write lock. False for a read lock */
- const char *zLockName; /* Name of the table */
-};
-
-/*
-** Record the fact that we want to lock a table at run-time.
-**
-** The table to be locked has root page iTab and is found in database iDb.
-** A read or a write lock can be taken depending on isWritelock.
-**
-** This routine just records the fact that the lock is desired. The
-** code to make the lock occur is generated by a later call to
-** codeTableLocks() which occurs during sqlite3FinishCoding().
-*/
-void sqlite3TableLock(
- Parse *pParse, /* Parsing context */
- int iDb, /* Index of the database containing the table to lock */
- int iTab, /* Root page number of the table to be locked */
- u8 isWriteLock, /* True for a write lock */
- const char *zName /* Name of the table to be locked */
-){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
- int i;
- int nBytes;
- TableLock *p;
- assert( iDb>=0 );
-
- if( iDb==1 ) return;
- if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
- for(i=0; i<pToplevel->nTableLock; i++){
- p = &pToplevel->aTableLock[i];
- if( p->iDb==iDb && p->iTab==iTab ){
- p->isWriteLock = (p->isWriteLock || isWriteLock);
- return;
- }
- }
-
- nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1);
- pToplevel->aTableLock =
- sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
- if( pToplevel->aTableLock ){
- p = &pToplevel->aTableLock[pToplevel->nTableLock++];
- p->iDb = iDb;
- p->iTab = iTab;
- p->isWriteLock = isWriteLock;
- p->zLockName = zName;
- }else{
- pToplevel->nTableLock = 0;
- sqlite3OomFault(pToplevel->db);
- }
-}
-
-/*
-** Code an OP_TableLock instruction for each table locked by the
-** statement (configured by calls to sqlite3TableLock()).
-*/
-static void codeTableLocks(Parse *pParse){
- int i;
- Vdbe *pVdbe;
-
- pVdbe = sqlite3GetVdbe(pParse);
- assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
-
- for(i=0; i<pParse->nTableLock; i++){
- TableLock *p = &pParse->aTableLock[i];
- int p1 = p->iDb;
- sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
- p->zLockName, P4_STATIC);
- }
-}
-#else
- #define codeTableLocks(x)
-#endif
-
-/*
-** Return TRUE if the given yDbMask object is empty - if it contains no
-** 1 bits. This routine is used by the DbMaskAllZero() and DbMaskNotZero()
-** macros when SQLITE_MAX_ATTACHED is greater than 30.
-*/
-#if SQLITE_MAX_ATTACHED>30
-int sqlite3DbMaskAllZero(yDbMask m){
- int i;
- for(i=0; i<sizeof(yDbMask); i++) if( m[i] ) return 0;
- return 1;
-}
-#endif
-
-/*
-** This routine is called after a single SQL statement has been
-** parsed and a VDBE program to execute that statement has been
-** prepared. This routine puts the finishing touches on the
-** VDBE program and resets the pParse structure for the next
-** parse.
-**
-** Note that if an error occurred, it might be the case that
-** no VDBE code was generated.
-*/
-void sqlite3FinishCoding(Parse *pParse){
- sqlite3 *db;
- Vdbe *v;
-
- assert( pParse->pToplevel==0 );
- db = pParse->db;
- if( pParse->nested ) return;
- if( db->mallocFailed || pParse->nErr ){
- if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
- return;
- }
-
- /* Begin by generating some termination code at the end of the
- ** vdbe program
- */
- v = sqlite3GetVdbe(pParse);
- assert( !pParse->isMultiWrite
- || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
- if( v ){
- sqlite3VdbeAddOp0(v, OP_Halt);
-
-#if SQLITE_USER_AUTHENTICATION
- if( pParse->nTableLock>0 && db->init.busy==0 ){
- sqlite3UserAuthInit(db);
- if( db->auth.authLevel<UAUTH_User ){
- sqlite3ErrorMsg(pParse, "user not authenticated");
- pParse->rc = SQLITE_AUTH_USER;
- return;
- }
- }
-#endif
-
- /* The cookie mask contains one bit for each database file open.
- ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
- ** set for each database that is used. Generate code to start a
- ** transaction on each used database and to verify the schema cookie
- ** on each used database.
- */
- if( db->mallocFailed==0
- && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
- ){
- int iDb, i;
- assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
- sqlite3VdbeJumpHere(v, 0);
- for(iDb=0; iDb<db->nDb; iDb++){
- Schema *pSchema;
- if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
- sqlite3VdbeUsesBtree(v, iDb);
- pSchema = db->aDb[iDb].pSchema;
- sqlite3VdbeAddOp4Int(v,
- OP_Transaction, /* Opcode */
- iDb, /* P1 */
- DbMaskTest(pParse->writeMask,iDb), /* P2 */
- pSchema->schema_cookie, /* P3 */
- pSchema->iGeneration /* P4 */
- );
- if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
- VdbeComment((v,
- "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- for(i=0; i<pParse->nVtabLock; i++){
- char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
- sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
- }
- pParse->nVtabLock = 0;
-#endif
-
- /* Once all the cookies have been verified and transactions opened,
- ** obtain the required table-locks. This is a no-op unless the
- ** shared-cache feature is enabled.
- */
- codeTableLocks(pParse);
-
- /* Initialize any AUTOINCREMENT data structures required.
- */
- sqlite3AutoincrementBegin(pParse);
-
- /* Code constant expressions that where factored out of inner loops */
- if( pParse->pConstExpr ){
- ExprList *pEL = pParse->pConstExpr;
- pParse->okConstFactor = 0;
- for(i=0; i<pEL->nExpr; i++){
- sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
- }
- }
-
- /* Finally, jump back to the beginning of the executable code. */
- sqlite3VdbeGoto(v, 1);
- }
- }
-
-
- /* Get the VDBE program ready for execution
- */
- if( v && pParse->nErr==0 && !db->mallocFailed ){
- assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
- /* A minimum of one cursor is required if autoincrement is used
- * See ticket [a696379c1f08866] */
- if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
- sqlite3VdbeMakeReady(v, pParse);
- pParse->rc = SQLITE_DONE;
- }else{
- pParse->rc = SQLITE_ERROR;
- }
-}
-
-/*
-** Run the parser and code generator recursively in order to generate
-** code for the SQL statement given onto the end of the pParse context
-** currently under construction. When the parser is run recursively
-** this way, the final OP_Halt is not appended and other initialization
-** and finalization steps are omitted because those are handling by the
-** outermost parser.
-**
-** Not everything is nestable. This facility is designed to permit
-** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use
-** care if you decide to try to use this routine for some other purposes.
-*/
-void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
- va_list ap;
- char *zSql;
- char *zErrMsg = 0;
- sqlite3 *db = pParse->db;
- char saveBuf[PARSE_TAIL_SZ];
-
- if( pParse->nErr ) return;
- assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
- va_start(ap, zFormat);
- zSql = sqlite3VMPrintf(db, zFormat, ap);
- va_end(ap);
- if( zSql==0 ){
- return; /* A malloc must have failed */
- }
- pParse->nested++;
- memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
- memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
- sqlite3RunParser(pParse, zSql, &zErrMsg);
- sqlite3DbFree(db, zErrMsg);
- sqlite3DbFree(db, zSql);
- memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
- pParse->nested--;
-}
-
-#if SQLITE_USER_AUTHENTICATION
-/*
-** Return TRUE if zTable is the name of the system table that stores the
-** list of users and their access credentials.
-*/
-int sqlite3UserAuthTable(const char *zTable){
- return sqlite3_stricmp(zTable, "sqlite_user")==0;
-}
-#endif
-
-/*
-** Locate the in-memory structure that describes a particular database
-** table given the name of that table and (optionally) the name of the
-** database containing the table. Return NULL if not found.
-**
-** If zDatabase is 0, all databases are searched for the table and the
-** first matching table is returned. (No checking for duplicate table
-** names is done.) The search order is TEMP first, then MAIN, then any
-** auxiliary databases added using the ATTACH command.
-**
-** See also sqlite3LocateTable().
-*/
-Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
- Table *p = 0;
- int i;
-
- /* All mutexes are required for schema access. Make sure we hold them. */
- assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
-#if SQLITE_USER_AUTHENTICATION
- /* Only the admin user is allowed to know that the sqlite_user table
- ** exists */
- if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
- return 0;
- }
-#endif
- while(1){
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
- if( p ) return p;
- }
- }
- /* Not found. If the name we were looking for was temp.sqlite_master
- ** then change the name to sqlite_temp_master and try again. */
- if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
- if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
- zName = TEMP_MASTER_NAME;
- }
- return 0;
-}
-
-/*
-** Locate the in-memory structure that describes a particular database
-** table given the name of that table and (optionally) the name of the
-** database containing the table. Return NULL if not found. Also leave an
-** error message in pParse->zErrMsg.
-**
-** The difference between this routine and sqlite3FindTable() is that this
-** routine leaves an error message in pParse->zErrMsg where
-** sqlite3FindTable() does not.
-*/
-Table *sqlite3LocateTable(
- Parse *pParse, /* context in which to report errors */
- u32 flags, /* LOCATE_VIEW or LOCATE_NOERR */
- const char *zName, /* Name of the table we are looking for */
- const char *zDbase /* Name of the database. Might be NULL */
-){
- Table *p;
- sqlite3 *db = pParse->db;
-
- /* Read the database schema. If an error occurs, leave an error message
- ** and code in pParse and return NULL. */
- if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0
- && SQLITE_OK!=sqlite3ReadSchema(pParse)
- ){
- return 0;
- }
-
- p = sqlite3FindTable(db, zName, zDbase);
- if( p==0 ){
- const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( sqlite3FindDbName(db, zDbase)<1 ){
- /* If zName is the not the name of a table in the schema created using
- ** CREATE, then check to see if it is the name of an virtual table that
- ** can be an eponymous virtual table. */
- Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
- if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
- pMod = sqlite3PragmaVtabRegister(db, zName);
- }
- if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
- return pMod->pEpoTab;
- }
- }
-#endif
- if( (flags & LOCATE_NOERR)==0 ){
- if( zDbase ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
- }else{
- sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
- }
- pParse->checkSchema = 1;
- }
- }
-
- return p;
-}
-
-/*
-** Locate the table identified by *p.
-**
-** This is a wrapper around sqlite3LocateTable(). The difference between
-** sqlite3LocateTable() and this function is that this function restricts
-** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
-** non-NULL if it is part of a view or trigger program definition. See
-** sqlite3FixSrcList() for details.
-*/
-Table *sqlite3LocateTableItem(
- Parse *pParse,
- u32 flags,
- struct SrcList_item *p
-){
- const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
- if( p->pSchema ){
- int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
- zDb = pParse->db->aDb[iDb].zDbSName;
- }else{
- zDb = p->zDatabase;
- }
- return sqlite3LocateTable(pParse, flags, p->zName, zDb);
-}
-
-/*
-** Locate the in-memory structure that describes
-** a particular index given the name of that index
-** and the name of the database that contains the index.
-** Return NULL if not found.
-**
-** If zDatabase is 0, all databases are searched for the
-** table and the first matching index is returned. (No checking
-** for duplicate index names is done.) The search order is
-** TEMP first, then MAIN, then any auxiliary databases added
-** using the ATTACH command.
-*/
-Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
- Index *p = 0;
- int i;
- /* All mutexes are required for schema access. Make sure we hold them. */
- assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- Schema *pSchema = db->aDb[j].pSchema;
- assert( pSchema );
- if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue;
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
- p = sqlite3HashFind(&pSchema->idxHash, zName);
- if( p ) break;
- }
- return p;
-}
-
-/*
-** Reclaim the memory used by an index
-*/
-static void freeIndex(sqlite3 *db, Index *p){
-#ifndef SQLITE_OMIT_ANALYZE
- sqlite3DeleteIndexSamples(db, p);
-#endif
- sqlite3ExprDelete(db, p->pPartIdxWhere);
- sqlite3ExprListDelete(db, p->aColExpr);
- sqlite3DbFree(db, p->zColAff);
- if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl);
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- sqlite3_free(p->aiRowEst);
-#endif
- sqlite3DbFree(db, p);
-}
-
-/*
-** For the index called zIdxName which is found in the database iDb,
-** unlike that index from its Table then remove the index from
-** the index hash table and free all memory structures associated
-** with the index.
-*/
-void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
- Index *pIndex;
- Hash *pHash;
-
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pHash = &db->aDb[iDb].pSchema->idxHash;
- pIndex = sqlite3HashInsert(pHash, zIdxName, 0);
- if( ALWAYS(pIndex) ){
- if( pIndex->pTable->pIndex==pIndex ){
- pIndex->pTable->pIndex = pIndex->pNext;
- }else{
- Index *p;
- /* Justification of ALWAYS(); The index must be on the list of
- ** indices. */
- p = pIndex->pTable->pIndex;
- while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; }
- if( ALWAYS(p && p->pNext==pIndex) ){
- p->pNext = pIndex->pNext;
- }
- }
- freeIndex(db, pIndex);
- }
- db->mDbFlags |= DBFLAG_SchemaChange;
-}
-
-/*
-** Look through the list of open database files in db->aDb[] and if
-** any have been closed, remove them from the list. Reallocate the
-** db->aDb[] structure to a smaller size, if possible.
-**
-** Entry 0 (the "main" database) and entry 1 (the "temp" database)
-** are never candidates for being collapsed.
-*/
-void sqlite3CollapseDatabaseArray(sqlite3 *db){
- int i, j;
- for(i=j=2; i<db->nDb; i++){
- struct Db *pDb = &db->aDb[i];
- if( pDb->pBt==0 ){
- sqlite3DbFree(db, pDb->zDbSName);
- pDb->zDbSName = 0;
- continue;
- }
- if( j<i ){
- db->aDb[j] = db->aDb[i];
- }
- j++;
- }
- db->nDb = j;
- if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
- memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
- sqlite3DbFree(db, db->aDb);
- db->aDb = db->aDbStatic;
- }
-}
-
-/*
-** Reset the schema for the database at index iDb. Also reset the
-** TEMP schema. The reset is deferred if db->nSchemaLock is not zero.
-** Deferred resets may be run by calling with iDb<0.
-*/
-void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
- int i;
- assert( iDb<db->nDb );
-
- if( iDb>=0 ){
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- DbSetProperty(db, iDb, DB_ResetWanted);
- DbSetProperty(db, 1, DB_ResetWanted);
- db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
- }
-
- if( db->nSchemaLock==0 ){
- for(i=0; i<db->nDb; i++){
- if( DbHasProperty(db, i, DB_ResetWanted) ){
- sqlite3SchemaClear(db->aDb[i].pSchema);
- }
- }
- }
-}
-
-/*
-** Erase all schema information from all attached databases (including
-** "main" and "temp") for a single database connection.
-*/
-void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
- int i;
- sqlite3BtreeEnterAll(db);
- assert( db->nSchemaLock==0 );
- for(i=0; i<db->nDb; i++){
- Db *pDb = &db->aDb[i];
- if( pDb->pSchema ){
- sqlite3SchemaClear(pDb->pSchema);
- }
- }
- db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk);
- sqlite3VtabUnlockList(db);
- sqlite3BtreeLeaveAll(db);
- sqlite3CollapseDatabaseArray(db);
-}
-
-/*
-** This routine is called when a commit occurs.
-*/
-void sqlite3CommitInternalChanges(sqlite3 *db){
- db->mDbFlags &= ~DBFLAG_SchemaChange;
-}
-
-/*
-** Delete memory allocated for the column names of a table or view (the
-** Table.aCol[] array).
-*/
-void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
- int i;
- Column *pCol;
- assert( pTable!=0 );
- if( (pCol = pTable->aCol)!=0 ){
- for(i=0; i<pTable->nCol; i++, pCol++){
- sqlite3DbFree(db, pCol->zName);
- sqlite3ExprDelete(db, pCol->pDflt);
- sqlite3DbFree(db, pCol->zColl);
- }
- sqlite3DbFree(db, pTable->aCol);
- }
-}
-
-/*
-** Remove the memory data structures associated with the given
-** Table. No changes are made to disk by this routine.
-**
-** This routine just deletes the data structure. It does not unlink
-** the table data structure from the hash table. But it does destroy
-** memory structures of the indices and foreign keys associated with
-** the table.
-**
-** The db parameter is optional. It is needed if the Table object
-** contains lookaside memory. (Table objects in the schema do not use
-** lookaside memory, but some ephemeral Table objects do.) Or the
-** db parameter can be used with db->pnBytesFreed to measure the memory
-** used by the Table object.
-*/
-static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
- Index *pIndex, *pNext;
-
-#ifdef SQLITE_DEBUG
- /* Record the number of outstanding lookaside allocations in schema Tables
- ** prior to doing any free() operations. Since schema Tables do not use
- ** lookaside, this number should not change. */
- int nLookaside = 0;
- if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){
- nLookaside = sqlite3LookasideUsed(db, 0);
- }
-#endif
-
- /* Delete all indices associated with this table. */
- for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
- pNext = pIndex->pNext;
- assert( pIndex->pSchema==pTable->pSchema
- || (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) );
- if( (db==0 || db->pnBytesFreed==0) && !IsVirtual(pTable) ){
- char *zName = pIndex->zName;
- TESTONLY ( Index *pOld = ) sqlite3HashInsert(
- &pIndex->pSchema->idxHash, zName, 0
- );
- assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
- assert( pOld==pIndex || pOld==0 );
- }
- freeIndex(db, pIndex);
- }
-
- /* Delete any foreign keys attached to this table. */
- sqlite3FkDelete(db, pTable);
-
- /* Delete the Table structure itself.
- */
- sqlite3DeleteColumnNames(db, pTable);
- sqlite3DbFree(db, pTable->zName);
- sqlite3DbFree(db, pTable->zColAff);
- sqlite3SelectDelete(db, pTable->pSelect);
- sqlite3ExprListDelete(db, pTable->pCheck);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3VtabClear(db, pTable);
-#endif
- sqlite3DbFree(db, pTable);
-
- /* Verify that no lookaside memory was used by schema tables */
- assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
-}
-void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
- /* Do not delete the table until the reference count reaches zero. */
- if( !pTable ) return;
- if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return;
- deleteTable(db, pTable);
-}
-
-
-/*
-** Unlink the given table from the hash tables and the delete the
-** table structure with all its indices and foreign keys.
-*/
-void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
- Table *p;
- Db *pDb;
-
- assert( db!=0 );
- assert( iDb>=0 && iDb<db->nDb );
- assert( zTabName );
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */
- pDb = &db->aDb[iDb];
- p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0);
- sqlite3DeleteTable(db, p);
- db->mDbFlags |= DBFLAG_SchemaChange;
-}
-
-/*
-** Given a token, return a string that consists of the text of that
-** token. Space to hold the returned string
-** is obtained from sqliteMalloc() and must be freed by the calling
-** function.
-**
-** Any quotation marks (ex: "name", 'name', [name], or `name`) that
-** surround the body of the token are removed.
-**
-** Tokens are often just pointers into the original SQL text and so
-** are not \000 terminated and are not persistent. The returned string
-** is \000 terminated and is persistent.
-*/
-char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
- char *zName;
- if( pName ){
- zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n);
- sqlite3Dequote(zName);
- }else{
- zName = 0;
- }
- return zName;
-}
-
-/*
-** Open the sqlite_master table stored in database number iDb for
-** writing. The table is opened using cursor 0.
-*/
-void sqlite3OpenMasterTable(Parse *p, int iDb){
- Vdbe *v = sqlite3GetVdbe(p);
- sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME);
- sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
- if( p->nTab==0 ){
- p->nTab = 1;
- }
-}
-
-/*
-** Parameter zName points to a nul-terminated buffer containing the name
-** of a database ("main", "temp" or the name of an attached db). This
-** function returns the index of the named database in db->aDb[], or
-** -1 if the named db cannot be found.
-*/
-int sqlite3FindDbName(sqlite3 *db, const char *zName){
- int i = -1; /* Database number */
- if( zName ){
- Db *pDb;
- for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
- if( 0==sqlite3_stricmp(pDb->zDbSName, zName) ) break;
- /* "main" is always an acceptable alias for the primary database
- ** even if it has been renamed using SQLITE_DBCONFIG_MAINDBNAME. */
- if( i==0 && 0==sqlite3_stricmp("main", zName) ) break;
- }
- }
- return i;
-}
-
-/*
-** The token *pName contains the name of a database (either "main" or
-** "temp" or the name of an attached db). This routine returns the
-** index of the named database in db->aDb[], or -1 if the named db
-** does not exist.
-*/
-int sqlite3FindDb(sqlite3 *db, Token *pName){
- int i; /* Database number */
- char *zName; /* Name we are searching for */
- zName = sqlite3NameFromToken(db, pName);
- i = sqlite3FindDbName(db, zName);
- sqlite3DbFree(db, zName);
- return i;
-}
-
-/* The table or view or trigger name is passed to this routine via tokens
-** pName1 and pName2. If the table name was fully qualified, for example:
-**
-** CREATE TABLE xxx.yyy (...);
-**
-** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
-** the table name is not fully qualified, i.e.:
-**
-** CREATE TABLE yyy(...);
-**
-** Then pName1 is set to "yyy" and pName2 is "".
-**
-** This routine sets the *ppUnqual pointer to point at the token (pName1 or
-** pName2) that stores the unqualified table name. The index of the
-** database "xxx" is returned.
-*/
-int sqlite3TwoPartName(
- Parse *pParse, /* Parsing and code generating context */
- Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */
- Token *pName2, /* The "yyy" in the name "xxx.yyy" */
- Token **pUnqual /* Write the unqualified object name here */
-){
- int iDb; /* Database holding the object */
- sqlite3 *db = pParse->db;
-
- assert( pName2!=0 );
- if( pName2->n>0 ){
- if( db->init.busy ) {
- sqlite3ErrorMsg(pParse, "corrupt database");
- return -1;
- }
- *pUnqual = pName2;
- iDb = sqlite3FindDb(db, pName1);
- if( iDb<0 ){
- sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
- return -1;
- }
- }else{
- assert( db->init.iDb==0 || db->init.busy
- || (db->mDbFlags & DBFLAG_Vacuum)!=0);
- iDb = db->init.iDb;
- *pUnqual = pName1;
- }
- return iDb;
-}
-
-/*
-** This routine is used to check if the UTF-8 string zName is a legal
-** unqualified name for a new schema object (table, index, view or
-** trigger). All names are legal except those that begin with the string
-** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
-** is reserved for internal use.
-*/
-int sqlite3CheckObjectName(Parse *pParse, const char *zName){
- if( !pParse->db->init.busy && pParse->nested==0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
- && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
- sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-
-/*
-** Return the PRIMARY KEY index of a table
-*/
-Index *sqlite3PrimaryKeyIndex(Table *pTab){
- Index *p;
- for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){}
- return p;
-}
-
-/*
-** Return the column of index pIdx that corresponds to table
-** column iCol. Return -1 if not found.
-*/
-i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
- int i;
- for(i=0; i<pIdx->nColumn; i++){
- if( iCol==pIdx->aiColumn[i] ) return i;
- }
- return -1;
-}
-
-/*
-** Begin constructing a new table representation in memory. This is
-** the first of several action routines that get called in response
-** to a CREATE TABLE statement. In particular, this routine is called
-** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp
-** flag is true if the table should be stored in the auxiliary database
-** file instead of in the main database file. This is normally the case
-** when the "TEMP" or "TEMPORARY" keyword occurs in between
-** CREATE and TABLE.
-**
-** The new table record is initialized and put in pParse->pNewTable.
-** As more of the CREATE TABLE statement is parsed, additional action
-** routines will be called to add more information to this record.
-** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine
-** is called to complete the construction of the new table record.
-*/
-void sqlite3StartTable(
- Parse *pParse, /* Parser context */
- Token *pName1, /* First part of the name of the table or view */
- Token *pName2, /* Second part of the name of the table or view */
- int isTemp, /* True if this is a TEMP table */
- int isView, /* True if this is a VIEW */
- int isVirtual, /* True if this is a VIRTUAL table */
- int noErr /* Do nothing if table already exists */
-){
- Table *pTable;
- char *zName = 0; /* The name of the new table */
- sqlite3 *db = pParse->db;
- Vdbe *v;
- int iDb; /* Database number to create the table in */
- Token *pName; /* Unqualified name of the table to create */
-
- if( db->init.busy && db->init.newTnum==1 ){
- /* Special case: Parsing the sqlite_master or sqlite_temp_master schema */
- iDb = db->init.iDb;
- zName = sqlite3DbStrDup(db, SCHEMA_TABLE(iDb));
- pName = pName1;
- }else{
- /* The common case */
- iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
- if( iDb<0 ) return;
- if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){
- /* If creating a temp table, the name may not be qualified. Unless
- ** the database name is "temp" anyway. */
- sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
- return;
- }
- if( !OMIT_TEMPDB && isTemp ) iDb = 1;
- zName = sqlite3NameFromToken(db, pName);
- }
- pParse->sNameToken = *pName;
- if( zName==0 ) return;
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
- goto begin_table_error;
- }
- if( db->init.iDb==1 ) isTemp = 1;
-#ifndef SQLITE_OMIT_AUTHORIZATION
- assert( isTemp==0 || isTemp==1 );
- assert( isView==0 || isView==1 );
- {
- static const u8 aCode[] = {
- SQLITE_CREATE_TABLE,
- SQLITE_CREATE_TEMP_TABLE,
- SQLITE_CREATE_VIEW,
- SQLITE_CREATE_TEMP_VIEW
- };
- char *zDb = db->aDb[iDb].zDbSName;
- if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
- goto begin_table_error;
- }
- if( !isVirtual && sqlite3AuthCheck(pParse, (int)aCode[isTemp+2*isView],
- zName, 0, zDb) ){
- goto begin_table_error;
- }
- }
-#endif
-
- /* Make sure the new table name does not collide with an existing
- ** index or table name in the same database. Issue an error message if
- ** it does. The exception is if the statement being parsed was passed
- ** to an sqlite3_declare_vtab() call. In that case only the column names
- ** and types will be used, so there is no need to test for namespace
- ** collisions.
- */
- if( !IN_DECLARE_VTAB ){
- char *zDb = db->aDb[iDb].zDbSName;
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- goto begin_table_error;
- }
- pTable = sqlite3FindTable(db, zName, zDb);
- if( pTable ){
- if( !noErr ){
- sqlite3ErrorMsg(pParse, "table %T already exists", pName);
- }else{
- assert( !db->init.busy || CORRUPT_DB );
- sqlite3CodeVerifySchema(pParse, iDb);
- }
- goto begin_table_error;
- }
- if( sqlite3FindIndex(db, zName, zDb)!=0 ){
- sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
- goto begin_table_error;
- }
- }
-
- pTable = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTable==0 ){
- assert( db->mallocFailed );
- pParse->rc = SQLITE_NOMEM_BKPT;
- pParse->nErr++;
- goto begin_table_error;
- }
- pTable->zName = zName;
- pTable->iPKey = -1;
- pTable->pSchema = db->aDb[iDb].pSchema;
- pTable->nTabRef = 1;
-#ifdef SQLITE_DEFAULT_ROWEST
- pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST);
-#else
- pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
-#endif
- assert( pParse->pNewTable==0 );
- pParse->pNewTable = pTable;
-
- /* If this is the magic sqlite_sequence table used by autoincrement,
- ** then record a pointer to this table in the main database structure
- ** so that INSERT can find the table easily.
- */
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pTable->pSchema->pSeqTab = pTable;
- }
-#endif
-
- /* Begin generating the code that will insert the table record into
- ** the SQLITE_MASTER table. Note in particular that we must go ahead
- ** and allocate the record number for the table entry now. Before any
- ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
- ** indices to be created and the table record must come before the
- ** indices. Hence, the record number for the table must be allocated
- ** now.
- */
- if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
- int addr1;
- int fileFormat;
- int reg1, reg2, reg3;
- /* nullRow[] is an OP_Record encoding of a row containing 5 NULLs */
- static const char nullRow[] = { 6, 0, 0, 0, 0, 0 };
- sqlite3BeginWriteOperation(pParse, 1, iDb);
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( isVirtual ){
- sqlite3VdbeAddOp0(v, OP_VBegin);
- }
-#endif
-
- /* If the file format and encoding in the database have not been set,
- ** set them now.
- */
- reg1 = pParse->regRowid = ++pParse->nMem;
- reg2 = pParse->regRoot = ++pParse->nMem;
- reg3 = ++pParse->nMem;
- sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT);
- sqlite3VdbeUsesBtree(v, iDb);
- addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v);
- fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
- 1 : SQLITE_MAX_FILE_FORMAT;
- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, fileFormat);
- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db));
- sqlite3VdbeJumpHere(v, addr1);
-
- /* This just creates a place-holder record in the sqlite_master table.
- ** The record created does not contain anything yet. It will be replaced
- ** by the real entry in code generated at sqlite3EndTable().
- **
- ** The rowid for the new entry is left in register pParse->regRowid.
- ** The root page number of the new table is left in reg pParse->regRoot.
- ** The rowid and root page number values are needed by the code that
- ** sqlite3EndTable will generate.
- */
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
- if( isView || isVirtual ){
- sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2);
- }else
-#endif
- {
- pParse->addrCrTab =
- sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
- }
- sqlite3OpenMasterTable(pParse, iDb);
- sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
- sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC);
- sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
- sqlite3VdbeAddOp0(v, OP_Close);
- }
-
- /* Normal (non-error) return. */
- return;
-
- /* If an error occurs, we jump here */
-begin_table_error:
- sqlite3DbFree(db, zName);
- return;
-}
-
-/* Set properties of a table column based on the (magical)
-** name of the column.
-*/
-#if SQLITE_ENABLE_HIDDEN_COLUMNS
-void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
- if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
- pCol->colFlags |= COLFLAG_HIDDEN;
- }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
- pTab->tabFlags |= TF_OOOHidden;
- }
-}
-#endif
-
-
-/*
-** Add a new column to the table currently being constructed.
-**
-** The parser calls this routine once for each column declaration
-** in a CREATE TABLE statement. sqlite3StartTable() gets called
-** first to get things going. Then this routine is called for each
-** column.
-*/
-void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
- Table *p;
- int i;
- char *z;
- char *zType;
- Column *pCol;
- sqlite3 *db = pParse->db;
- if( (p = pParse->pNewTable)==0 ) return;
- if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
- return;
- }
- z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
- if( z==0 ) return;
- memcpy(z, pName->z, pName->n);
- z[pName->n] = 0;
- sqlite3Dequote(z);
- for(i=0; i<p->nCol; i++){
- if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
- sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
- sqlite3DbFree(db, z);
- return;
- }
- }
- if( (p->nCol & 0x7)==0 ){
- Column *aNew;
- aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
- if( aNew==0 ){
- sqlite3DbFree(db, z);
- return;
- }
- p->aCol = aNew;
- }
- pCol = &p->aCol[p->nCol];
- memset(pCol, 0, sizeof(p->aCol[0]));
- pCol->zName = z;
- sqlite3ColumnPropertiesFromName(p, pCol);
-
- if( pType->n==0 ){
- /* If there is no type specified, columns have the default affinity
- ** 'BLOB' with a default size of 4 bytes. */
- pCol->affinity = SQLITE_AFF_BLOB;
- pCol->szEst = 1;
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( 4>=sqlite3GlobalConfig.szSorterRef ){
- pCol->colFlags |= COLFLAG_SORTERREF;
- }
-#endif
- }else{
- zType = z + sqlite3Strlen30(z) + 1;
- memcpy(zType, pType->z, pType->n);
- zType[pType->n] = 0;
- sqlite3Dequote(zType);
- pCol->affinity = sqlite3AffinityType(zType, pCol);
- pCol->colFlags |= COLFLAG_HASTYPE;
- }
- p->nCol++;
- pParse->constraintName.n = 0;
-}
-
-/*
-** This routine is called by the parser while in the middle of
-** parsing a CREATE TABLE statement. A "NOT NULL" constraint has
-** been seen on a column. This routine sets the notNull flag on
-** the column currently under construction.
-*/
-void sqlite3AddNotNull(Parse *pParse, int onError){
- Table *p;
- Column *pCol;
- p = pParse->pNewTable;
- if( p==0 || NEVER(p->nCol<1) ) return;
- pCol = &p->aCol[p->nCol-1];
- pCol->notNull = (u8)onError;
- p->tabFlags |= TF_HasNotNull;
-
- /* Set the uniqNotNull flag on any UNIQUE or PK indexes already created
- ** on this column. */
- if( pCol->colFlags & COLFLAG_UNIQUE ){
- Index *pIdx;
- for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
- assert( pIdx->nKeyCol==1 && pIdx->onError!=OE_None );
- if( pIdx->aiColumn[0]==p->nCol-1 ){
- pIdx->uniqNotNull = 1;
- }
- }
- }
-}
-
-/*
-** Scan the column type name zType (length nType) and return the
-** associated affinity type.
-**
-** This routine does a case-independent search of zType for the
-** substrings in the following table. If one of the substrings is
-** found, the corresponding affinity is returned. If zType contains
-** more than one of the substrings, entries toward the top of
-** the table take priority. For example, if zType is 'BLOBINT',
-** SQLITE_AFF_INTEGER is returned.
-**
-** Substring | Affinity
-** --------------------------------
-** 'INT' | SQLITE_AFF_INTEGER
-** 'CHAR' | SQLITE_AFF_TEXT
-** 'CLOB' | SQLITE_AFF_TEXT
-** 'TEXT' | SQLITE_AFF_TEXT
-** 'BLOB' | SQLITE_AFF_BLOB
-** 'REAL' | SQLITE_AFF_REAL
-** 'FLOA' | SQLITE_AFF_REAL
-** 'DOUB' | SQLITE_AFF_REAL
-**
-** If none of the substrings in the above table are found,
-** SQLITE_AFF_NUMERIC is returned.
-*/
-char sqlite3AffinityType(const char *zIn, Column *pCol){
- u32 h = 0;
- char aff = SQLITE_AFF_NUMERIC;
- const char *zChar = 0;
-
- assert( zIn!=0 );
- while( zIn[0] ){
- h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
- zIn++;
- if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
- aff = SQLITE_AFF_TEXT;
- zChar = zIn;
- }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
- aff = SQLITE_AFF_TEXT;
- }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
- aff = SQLITE_AFF_TEXT;
- }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
- && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
- aff = SQLITE_AFF_BLOB;
- if( zIn[0]=='(' ) zChar = zIn;
-#ifndef SQLITE_OMIT_FLOATING_POINT
- }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
- && aff==SQLITE_AFF_NUMERIC ){
- aff = SQLITE_AFF_REAL;
- }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
- && aff==SQLITE_AFF_NUMERIC ){
- aff = SQLITE_AFF_REAL;
- }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */
- && aff==SQLITE_AFF_NUMERIC ){
- aff = SQLITE_AFF_REAL;
-#endif
- }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */
- aff = SQLITE_AFF_INTEGER;
- break;
- }
- }
-
- /* If pCol is not NULL, store an estimate of the field size. The
- ** estimate is scaled so that the size of an integer is 1. */
- if( pCol ){
- int v = 0; /* default size is approx 4 bytes */
- if( aff<SQLITE_AFF_NUMERIC ){
- if( zChar ){
- while( zChar[0] ){
- if( sqlite3Isdigit(zChar[0]) ){
- /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */
- sqlite3GetInt32(zChar, &v);
- break;
- }
- zChar++;
- }
- }else{
- v = 16; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/
- }
- }
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( v>=sqlite3GlobalConfig.szSorterRef ){
- pCol->colFlags |= COLFLAG_SORTERREF;
- }
-#endif
- v = v/4 + 1;
- if( v>255 ) v = 255;
- pCol->szEst = v;
- }
- return aff;
-}
-
-/*
-** The expression is the default value for the most recently added column
-** of the table currently under construction.
-**
-** Default value expressions must be constant. Raise an exception if this
-** is not the case.
-**
-** This routine is called by the parser while in the middle of
-** parsing a CREATE TABLE statement.
-*/
-void sqlite3AddDefaultValue(
- Parse *pParse, /* Parsing context */
- Expr *pExpr, /* The parsed expression of the default value */
- const char *zStart, /* Start of the default value text */
- const char *zEnd /* First character past end of defaut value text */
-){
- Table *p;
- Column *pCol;
- sqlite3 *db = pParse->db;
- p = pParse->pNewTable;
- if( p!=0 ){
- pCol = &(p->aCol[p->nCol-1]);
- if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
- sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
- pCol->zName);
- }else{
- /* A copy of pExpr is used instead of the original, as pExpr contains
- ** tokens that point to volatile memory.
- */
- Expr x;
- sqlite3ExprDelete(db, pCol->pDflt);
- memset(&x, 0, sizeof(x));
- x.op = TK_SPAN;
- x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
- x.pLeft = pExpr;
- x.flags = EP_Skip;
- pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
- sqlite3DbFree(db, x.u.zToken);
- }
- }
- sqlite3ExprDelete(db, pExpr);
-}
-
-/*
-** Backwards Compatibility Hack:
-**
-** Historical versions of SQLite accepted strings as column names in
-** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example:
-**
-** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim)
-** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC);
-**
-** This is goofy. But to preserve backwards compatibility we continue to
-** accept it. This routine does the necessary conversion. It converts
-** the expression given in its argument from a TK_STRING into a TK_ID
-** if the expression is just a TK_STRING with an optional COLLATE clause.
-** If the epxression is anything other than TK_STRING, the expression is
-** unchanged.
-*/
-static void sqlite3StringToId(Expr *p){
- if( p->op==TK_STRING ){
- p->op = TK_ID;
- }else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){
- p->pLeft->op = TK_ID;
- }
-}
-
-/*
-** Designate the PRIMARY KEY for the table. pList is a list of names
-** of columns that form the primary key. If pList is NULL, then the
-** most recently added column of the table is the primary key.
-**
-** A table can have at most one primary key. If the table already has
-** a primary key (and this is the second primary key) then create an
-** error.
-**
-** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
-** then we will try to use that column as the rowid. Set the Table.iPKey
-** field of the table under construction to be the index of the
-** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is
-** no INTEGER PRIMARY KEY.
-**
-** If the key is not an INTEGER PRIMARY KEY, then create a unique
-** index for the key. No index is created for INTEGER PRIMARY KEYs.
-*/
-void sqlite3AddPrimaryKey(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* List of field names to be indexed */
- int onError, /* What to do with a uniqueness conflict */
- int autoInc, /* True if the AUTOINCREMENT keyword is present */
- int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */
-){
- Table *pTab = pParse->pNewTable;
- Column *pCol = 0;
- int iCol = -1, i;
- int nTerm;
- if( pTab==0 ) goto primary_key_exit;
- if( pTab->tabFlags & TF_HasPrimaryKey ){
- sqlite3ErrorMsg(pParse,
- "table \"%s\" has more than one primary key", pTab->zName);
- goto primary_key_exit;
- }
- pTab->tabFlags |= TF_HasPrimaryKey;
- if( pList==0 ){
- iCol = pTab->nCol - 1;
- pCol = &pTab->aCol[iCol];
- pCol->colFlags |= COLFLAG_PRIMKEY;
- nTerm = 1;
- }else{
- nTerm = pList->nExpr;
- for(i=0; i<nTerm; i++){
- Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr);
- assert( pCExpr!=0 );
- sqlite3StringToId(pCExpr);
- if( pCExpr->op==TK_ID ){
- const char *zCName = pCExpr->u.zToken;
- for(iCol=0; iCol<pTab->nCol; iCol++){
- if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
- pCol = &pTab->aCol[iCol];
- pCol->colFlags |= COLFLAG_PRIMKEY;
- break;
- }
- }
- }
- }
- }
- if( nTerm==1
- && pCol
- && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0
- && sortOrder!=SQLITE_SO_DESC
- ){
- pTab->iPKey = iCol;
- pTab->keyConf = (u8)onError;
- assert( autoInc==0 || autoInc==1 );
- pTab->tabFlags |= autoInc*TF_Autoincrement;
- if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
- }else if( autoInc ){
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
- "INTEGER PRIMARY KEY");
-#endif
- }else{
- sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
- 0, sortOrder, 0, SQLITE_IDXTYPE_PRIMARYKEY);
- pList = 0;
- }
-
-primary_key_exit:
- sqlite3ExprListDelete(pParse->db, pList);
- return;
-}
-
-/*
-** Add a new CHECK constraint to the table currently under construction.
-*/
-void sqlite3AddCheckConstraint(
- Parse *pParse, /* Parsing context */
- Expr *pCheckExpr /* The check expression */
-){
-#ifndef SQLITE_OMIT_CHECK
- Table *pTab = pParse->pNewTable;
- sqlite3 *db = pParse->db;
- if( pTab && !IN_DECLARE_VTAB
- && !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
- ){
- pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
- if( pParse->constraintName.n ){
- sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
- }
- }else
-#endif
- {
- sqlite3ExprDelete(pParse->db, pCheckExpr);
- }
-}
-
-/*
-** Set the collation function of the most recently parsed table column
-** to the CollSeq given.
-*/
-void sqlite3AddCollateType(Parse *pParse, Token *pToken){
- Table *p;
- int i;
- char *zColl; /* Dequoted name of collation sequence */
- sqlite3 *db;
-
- if( (p = pParse->pNewTable)==0 ) return;
- i = p->nCol-1;
- db = pParse->db;
- zColl = sqlite3NameFromToken(db, pToken);
- if( !zColl ) return;
-
- if( sqlite3LocateCollSeq(pParse, zColl) ){
- Index *pIdx;
- sqlite3DbFree(db, p->aCol[i].zColl);
- p->aCol[i].zColl = zColl;
-
- /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
- ** then an index may have been created on this column before the
- ** collation type was added. Correct this if it is the case.
- */
- for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
- assert( pIdx->nKeyCol==1 );
- if( pIdx->aiColumn[0]==i ){
- pIdx->azColl[0] = p->aCol[i].zColl;
- }
- }
- }else{
- sqlite3DbFree(db, zColl);
- }
-}
-
-/*
-** This function returns the collation sequence for database native text
-** encoding identified by the string zName, length nName.
-**
-** If the requested collation sequence is not available, or not available
-** in the database native encoding, the collation factory is invoked to
-** request it. If the collation factory does not supply such a sequence,
-** and the sequence is available in another text encoding, then that is
-** returned instead.
-**
-** If no versions of the requested collations sequence are available, or
-** another error occurs, NULL is returned and an error message written into
-** pParse.
-**
-** This routine is a wrapper around sqlite3FindCollSeq(). This routine
-** invokes the collation factory if the named collation cannot be found
-** and generates an error message.
-**
-** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
-*/
-CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
- sqlite3 *db = pParse->db;
- u8 enc = ENC(db);
- u8 initbusy = db->init.busy;
- CollSeq *pColl;
-
- pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
- if( !initbusy && (!pColl || !pColl->xCmp) ){
- pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
- }
-
- return pColl;
-}
-
-
-/*
-** Generate code that will increment the schema cookie.
-**
-** The schema cookie is used to determine when the schema for the
-** database changes. After each schema change, the cookie value
-** changes. When a process first reads the schema it records the
-** cookie. Thereafter, whenever it goes to access the database,
-** it checks the cookie to make sure the schema has not changed
-** since it was last read.
-**
-** This plan is not completely bullet-proof. It is possible for
-** the schema to change multiple times and for the cookie to be
-** set back to prior value. But schema changes are infrequent
-** and the probability of hitting the same cookie value is only
-** 1 chance in 2^32. So we're safe enough.
-**
-** IMPLEMENTATION-OF: R-34230-56049 SQLite automatically increments
-** the schema-version whenever the schema changes.
-*/
-void sqlite3ChangeCookie(Parse *pParse, int iDb){
- sqlite3 *db = pParse->db;
- Vdbe *v = pParse->pVdbe;
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION,
- (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie));
-}
-
-/*
-** Measure the number of characters needed to output the given
-** identifier. The number returned includes any quotes used
-** but does not include the null terminator.
-**
-** The estimate is conservative. It might be larger that what is
-** really needed.
-*/
-static int identLength(const char *z){
- int n;
- for(n=0; *z; n++, z++){
- if( *z=='"' ){ n++; }
- }
- return n + 2;
-}
-
-/*
-** The first parameter is a pointer to an output buffer. The second
-** parameter is a pointer to an integer that contains the offset at
-** which to write into the output buffer. This function copies the
-** nul-terminated string pointed to by the third parameter, zSignedIdent,
-** to the specified offset in the buffer and updates *pIdx to refer
-** to the first byte after the last byte written before returning.
-**
-** If the string zSignedIdent consists entirely of alpha-numeric
-** characters, does not begin with a digit and is not an SQL keyword,
-** then it is copied to the output buffer exactly as it is. Otherwise,
-** it is quoted using double-quotes.
-*/
-static void identPut(char *z, int *pIdx, char *zSignedIdent){
- unsigned char *zIdent = (unsigned char*)zSignedIdent;
- int i, j, needQuote;
- i = *pIdx;
-
- for(j=0; zIdent[j]; j++){
- if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
- }
- needQuote = sqlite3Isdigit(zIdent[0])
- || sqlite3KeywordCode(zIdent, j)!=TK_ID
- || zIdent[j]!=0
- || j==0;
-
- if( needQuote ) z[i++] = '"';
- for(j=0; zIdent[j]; j++){
- z[i++] = zIdent[j];
- if( zIdent[j]=='"' ) z[i++] = '"';
- }
- if( needQuote ) z[i++] = '"';
- z[i] = 0;
- *pIdx = i;
-}
-
-/*
-** Generate a CREATE TABLE statement appropriate for the given
-** table. Memory to hold the text of the statement is obtained
-** from sqliteMalloc() and must be freed by the calling function.
-*/
-static char *createTableStmt(sqlite3 *db, Table *p){
- int i, k, n;
- char *zStmt;
- char *zSep, *zSep2, *zEnd;
- Column *pCol;
- n = 0;
- for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
- n += identLength(pCol->zName) + 5;
- }
- n += identLength(p->zName);
- if( n<50 ){
- zSep = "";
- zSep2 = ",";
- zEnd = ")";
- }else{
- zSep = "\n ";
- zSep2 = ",\n ";
- zEnd = "\n)";
- }
- n += 35 + 6*p->nCol;
- zStmt = sqlite3DbMallocRaw(0, n);
- if( zStmt==0 ){
- sqlite3OomFault(db);
- return 0;
- }
- sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
- k = sqlite3Strlen30(zStmt);
- identPut(zStmt, &k, p->zName);
- zStmt[k++] = '(';
- for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
- static const char * const azType[] = {
- /* SQLITE_AFF_BLOB */ "",
- /* SQLITE_AFF_TEXT */ " TEXT",
- /* SQLITE_AFF_NUMERIC */ " NUM",
- /* SQLITE_AFF_INTEGER */ " INT",
- /* SQLITE_AFF_REAL */ " REAL"
- };
- int len;
- const char *zType;
-
- sqlite3_snprintf(n-k, &zStmt[k], zSep);
- k += sqlite3Strlen30(&zStmt[k]);
- zSep = zSep2;
- identPut(zStmt, &k, pCol->zName);
- assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
- assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
- testcase( pCol->affinity==SQLITE_AFF_BLOB );
- testcase( pCol->affinity==SQLITE_AFF_TEXT );
- testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
- testcase( pCol->affinity==SQLITE_AFF_INTEGER );
- testcase( pCol->affinity==SQLITE_AFF_REAL );
-
- zType = azType[pCol->affinity - SQLITE_AFF_BLOB];
- len = sqlite3Strlen30(zType);
- assert( pCol->affinity==SQLITE_AFF_BLOB
- || pCol->affinity==sqlite3AffinityType(zType, 0) );
- memcpy(&zStmt[k], zType, len);
- k += len;
- assert( k<=n );
- }
- sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
- return zStmt;
-}
-
-/*
-** Resize an Index object to hold N columns total. Return SQLITE_OK
-** on success and SQLITE_NOMEM on an OOM error.
-*/
-static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
- char *zExtra;
- int nByte;
- if( pIdx->nColumn>=N ) return SQLITE_OK;
- assert( pIdx->isResized==0 );
- nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
- zExtra = sqlite3DbMallocZero(db, nByte);
- if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
- memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
- pIdx->azColl = (const char**)zExtra;
- zExtra += sizeof(char*)*N;
- memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
- pIdx->aiColumn = (i16*)zExtra;
- zExtra += sizeof(i16)*N;
- memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
- pIdx->aSortOrder = (u8*)zExtra;
- pIdx->nColumn = N;
- pIdx->isResized = 1;
- return SQLITE_OK;
-}
-
-/*
-** Estimate the total row width for a table.
-*/
-static void estimateTableWidth(Table *pTab){
- unsigned wTable = 0;
- const Column *pTabCol;
- int i;
- for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){
- wTable += pTabCol->szEst;
- }
- if( pTab->iPKey<0 ) wTable++;
- pTab->szTabRow = sqlite3LogEst(wTable*4);
-}
-
-/*
-** Estimate the average size of a row for an index.
-*/
-static void estimateIndexWidth(Index *pIdx){
- unsigned wIndex = 0;
- int i;
- const Column *aCol = pIdx->pTable->aCol;
- for(i=0; i<pIdx->nColumn; i++){
- i16 x = pIdx->aiColumn[i];
- assert( x<pIdx->pTable->nCol );
- wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst;
- }
- pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
-}
-
-/* Return true if value x is found any of the first nCol entries of aiCol[]
-*/
-static int hasColumn(const i16 *aiCol, int nCol, int x){
- while( nCol-- > 0 ) if( x==*(aiCol++) ) return 1;
- return 0;
-}
-
-/*
-** This routine runs at the end of parsing a CREATE TABLE statement that
-** has a WITHOUT ROWID clause. The job of this routine is to convert both
-** internal schema data structures and the generated VDBE code so that they
-** are appropriate for a WITHOUT ROWID table instead of a rowid table.
-** Changes include:
-**
-** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL.
-** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY
-** into BTREE_BLOBKEY.
-** (3) Bypass the creation of the sqlite_master table entry
-** for the PRIMARY KEY as the primary key index is now
-** identified by the sqlite_master table entry of the table itself.
-** (4) Set the Index.tnum of the PRIMARY KEY Index object in the
-** schema to the rootpage from the main table.
-** (5) Add all table columns to the PRIMARY KEY Index object
-** so that the PRIMARY KEY is a covering index. The surplus
-** columns are part of KeyInfo.nAllField and are not used for
-** sorting or lookup or uniqueness checks.
-** (6) Replace the rowid tail on all automatically generated UNIQUE
-** indices with the PRIMARY KEY columns.
-**
-** For virtual tables, only (1) is performed.
-*/
-static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
- Index *pIdx;
- Index *pPk;
- int nPk;
- int i, j;
- sqlite3 *db = pParse->db;
- Vdbe *v = pParse->pVdbe;
-
- /* Mark every PRIMARY KEY column as NOT NULL (except for imposter tables)
- */
- if( !db->init.imposterTable ){
- for(i=0; i<pTab->nCol; i++){
- if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){
- pTab->aCol[i].notNull = OE_Abort;
- }
- }
- }
-
- /* The remaining transformations only apply to b-tree tables, not to
- ** virtual tables */
- if( IN_DECLARE_VTAB ) return;
-
- /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
- ** into BTREE_BLOBKEY.
- */
- if( pParse->addrCrTab ){
- assert( v );
- sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY);
- }
-
- /* Locate the PRIMARY KEY index. Or, if this table was originally
- ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
- */
- if( pTab->iPKey>=0 ){
- ExprList *pList;
- Token ipkToken;
- sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
- pList = sqlite3ExprListAppend(pParse, 0,
- sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
- if( pList==0 ) return;
- pList->a[0].sortOrder = pParse->iPkSortOrder;
- assert( pParse->pNewTable==pTab );
- sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
- SQLITE_IDXTYPE_PRIMARYKEY);
- if( db->mallocFailed ) return;
- pPk = sqlite3PrimaryKeyIndex(pTab);
- pTab->iPKey = -1;
- }else{
- pPk = sqlite3PrimaryKeyIndex(pTab);
-
- /*
- ** Remove all redundant columns from the PRIMARY KEY. For example, change
- ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
- ** code assumes the PRIMARY KEY contains no repeated columns.
- */
- for(i=j=1; i<pPk->nKeyCol; i++){
- if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){
- pPk->nColumn--;
- }else{
- pPk->aiColumn[j++] = pPk->aiColumn[i];
- }
- }
- pPk->nKeyCol = j;
- }
- assert( pPk!=0 );
- pPk->isCovering = 1;
- if( !db->init.imposterTable ) pPk->uniqNotNull = 1;
- nPk = pPk->nKeyCol;
-
- /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
- ** table entry. This is only required if currently generating VDBE
- ** code for a CREATE TABLE (not when parsing one as part of reading
- ** a database schema). */
- if( v && pPk->tnum>0 ){
- assert( db->init.busy==0 );
- sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto);
- }
-
- /* The root page of the PRIMARY KEY is the table root page */
- pPk->tnum = pTab->tnum;
-
- /* Update the in-memory representation of all UNIQUE indices by converting
- ** the final rowid column into one or more columns of the PRIMARY KEY.
- */
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int n;
- if( IsPrimaryKeyIndex(pIdx) ) continue;
- for(i=n=0; i<nPk; i++){
- if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
- }
- if( n==0 ){
- /* This index is a superset of the primary key */
- pIdx->nColumn = pIdx->nKeyCol;
- continue;
- }
- if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
- for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
- if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ){
- pIdx->aiColumn[j] = pPk->aiColumn[i];
- pIdx->azColl[j] = pPk->azColl[i];
- j++;
- }
- }
- assert( pIdx->nColumn>=pIdx->nKeyCol+n );
- assert( pIdx->nColumn>=j );
- }
-
- /* Add all table columns to the PRIMARY KEY index
- */
- if( nPk<pTab->nCol ){
- if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
- for(i=0, j=nPk; i<pTab->nCol; i++){
- if( !hasColumn(pPk->aiColumn, j, i) ){
- assert( j<pPk->nColumn );
- pPk->aiColumn[j] = i;
- pPk->azColl[j] = sqlite3StrBINARY;
- j++;
- }
- }
- assert( pPk->nColumn==j );
- assert( pTab->nCol==j );
- }else{
- pPk->nColumn = pTab->nCol;
- }
-}
-
-/*
-** This routine is called to report the final ")" that terminates
-** a CREATE TABLE statement.
-**
-** The table structure that other action routines have been building
-** is added to the internal hash tables, assuming no errors have
-** occurred.
-**
-** An entry for the table is made in the master table on disk, unless
-** this is a temporary table or db->init.busy==1. When db->init.busy==1
-** it means we are reading the sqlite_master table because we just
-** connected to the database or because the sqlite_master table has
-** recently changed, so the entry for this table already exists in
-** the sqlite_master table. We do not want to create it again.
-**
-** If the pSelect argument is not NULL, it means that this routine
-** was called to create a table generated from a
-** "CREATE TABLE ... AS SELECT ..." statement. The column names of
-** the new table will match the result set of the SELECT.
-*/
-void sqlite3EndTable(
- Parse *pParse, /* Parse context */
- Token *pCons, /* The ',' token after the last column defn. */
- Token *pEnd, /* The ')' before options in the CREATE TABLE */
- u8 tabOpts, /* Extra table options. Usually 0. */
- Select *pSelect /* Select from a "CREATE ... AS SELECT" */
-){
- Table *p; /* The new table */
- sqlite3 *db = pParse->db; /* The database connection */
- int iDb; /* Database in which the table lives */
- Index *pIdx; /* An implied index of the table */
-
- if( pEnd==0 && pSelect==0 ){
- return;
- }
- assert( !db->mallocFailed );
- p = pParse->pNewTable;
- if( p==0 ) return;
-
- /* If the db->init.busy is 1 it means we are reading the SQL off the
- ** "sqlite_master" or "sqlite_temp_master" table on the disk.
- ** So do not write to the disk again. Extract the root page number
- ** for the table from the db->init.newTnum field. (The page number
- ** should have been put there by the sqliteOpenCb routine.)
- **
- ** If the root page number is 1, that means this is the sqlite_master
- ** table itself. So mark it read-only.
- */
- if( db->init.busy ){
- if( pSelect ){
- sqlite3ErrorMsg(pParse, "");
- return;
- }
- p->tnum = db->init.newTnum;
- if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
- }
-
- /* Special processing for WITHOUT ROWID Tables */
- if( tabOpts & TF_WithoutRowid ){
- if( (p->tabFlags & TF_Autoincrement) ){
- sqlite3ErrorMsg(pParse,
- "AUTOINCREMENT not allowed on WITHOUT ROWID tables");
- return;
- }
- if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
- sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
- }else{
- p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
- convertToWithoutRowidTable(pParse, p);
- }
- }
-
- iDb = sqlite3SchemaToIndex(db, p->pSchema);
-
-#ifndef SQLITE_OMIT_CHECK
- /* Resolve names in all CHECK constraint expressions.
- */
- if( p->pCheck ){
- sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
- }
-#endif /* !defined(SQLITE_OMIT_CHECK) */
-
- /* Estimate the average row size for the table and for all implied indices */
- estimateTableWidth(p);
- for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
- estimateIndexWidth(pIdx);
- }
-
- /* If not initializing, then create a record for the new table
- ** in the SQLITE_MASTER table of the database.
- **
- ** If this is a TEMPORARY table, write the entry into the auxiliary
- ** file instead of into the main database file.
- */
- if( !db->init.busy ){
- int n;
- Vdbe *v;
- char *zType; /* "view" or "table" */
- char *zType2; /* "VIEW" or "TABLE" */
- char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */
-
- v = sqlite3GetVdbe(pParse);
- if( NEVER(v==0) ) return;
-
- sqlite3VdbeAddOp1(v, OP_Close, 0);
-
- /*
- ** Initialize zType for the new view or table.
- */
- if( p->pSelect==0 ){
- /* A regular table */
- zType = "table";
- zType2 = "TABLE";
-#ifndef SQLITE_OMIT_VIEW
- }else{
- /* A view */
- zType = "view";
- zType2 = "VIEW";
-#endif
- }
-
- /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
- ** statement to populate the new table. The root-page number for the
- ** new table is in register pParse->regRoot.
- **
- ** Once the SELECT has been coded by sqlite3Select(), it is in a
- ** suitable state to query for the column names and types to be used
- ** by the new table.
- **
- ** A shared-cache write-lock is not required to write to the new table,
- ** as a schema-lock must have already been obtained to create it. Since
- ** a schema-lock excludes all other database users, the write-lock would
- ** be redundant.
- */
- if( pSelect ){
- SelectDest dest; /* Where the SELECT should store results */
- int regYield; /* Register holding co-routine entry-point */
- int addrTop; /* Top of the co-routine */
- int regRec; /* A record to be insert into the new table */
- int regRowid; /* Rowid of the next row to insert */
- int addrInsLoop; /* Top of the loop for inserting rows */
- Table *pSelTab; /* A table that describes the SELECT results */
-
- regYield = ++pParse->nMem;
- regRec = ++pParse->nMem;
- regRowid = ++pParse->nMem;
- assert(pParse->nTab==1);
- sqlite3MayAbort(pParse);
- sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
- sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
- pParse->nTab = 2;
- addrTop = sqlite3VdbeCurrentAddr(v) + 1;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
- if( pParse->nErr ) return;
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
- if( pSelTab==0 ) return;
- assert( p->aCol==0 );
- p->nCol = pSelTab->nCol;
- p->aCol = pSelTab->aCol;
- pSelTab->nCol = 0;
- pSelTab->aCol = 0;
- sqlite3DeleteTable(db, pSelTab);
- sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
- sqlite3Select(pParse, pSelect, &dest);
- if( pParse->nErr ) return;
- sqlite3VdbeEndCoroutine(v, regYield);
- sqlite3VdbeJumpHere(v, addrTop - 1);
- addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec);
- sqlite3TableAffinity(v, p, 0);
- sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid);
- sqlite3VdbeGoto(v, addrInsLoop);
- sqlite3VdbeJumpHere(v, addrInsLoop);
- sqlite3VdbeAddOp1(v, OP_Close, 1);
- }
-
- /* Compute the complete text of the CREATE statement */
- if( pSelect ){
- zStmt = createTableStmt(db, p);
- }else{
- Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd;
- n = (int)(pEnd2->z - pParse->sNameToken.z);
- if( pEnd2->z[0]!=';' ) n += pEnd2->n;
- zStmt = sqlite3MPrintf(db,
- "CREATE %s %.*s", zType2, n, pParse->sNameToken.z
- );
- }
-
- /* A slot for the record has already been allocated in the
- ** SQLITE_MASTER table. We just need to update that slot with all
- ** the information we've collected.
- */
- sqlite3NestedParse(pParse,
- "UPDATE %Q.%s "
- "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
- "WHERE rowid=#%d",
- db->aDb[iDb].zDbSName, MASTER_NAME,
- zType,
- p->zName,
- p->zName,
- pParse->regRoot,
- zStmt,
- pParse->regRowid
- );
- sqlite3DbFree(db, zStmt);
- sqlite3ChangeCookie(pParse, iDb);
-
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- /* Check to see if we need to create an sqlite_sequence table for
- ** keeping track of autoincrement keys.
- */
- if( (p->tabFlags & TF_Autoincrement)!=0 ){
- Db *pDb = &db->aDb[iDb];
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- if( pDb->pSchema->pSeqTab==0 ){
- sqlite3NestedParse(pParse,
- "CREATE TABLE %Q.sqlite_sequence(name,seq)",
- pDb->zDbSName
- );
- }
- }
-#endif
-
- /* Reparse everything to update our internal data structures */
- sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
- }
-
-
- /* Add the table to the in-memory representation of the database.
- */
- if( db->init.busy ){
- Table *pOld;
- Schema *pSchema = p->pSchema;
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
- if( pOld ){
- assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
- sqlite3OomFault(db);
- return;
- }
- pParse->pNewTable = 0;
- db->mDbFlags |= DBFLAG_SchemaChange;
-
-#ifndef SQLITE_OMIT_ALTERTABLE
- if( !p->pSelect ){
- const char *zName = (const char *)pParse->sNameToken.z;
- int nName;
- assert( !pSelect && pCons && pEnd );
- if( pCons->z==0 ){
- pCons = pEnd;
- }
- nName = (int)((const char *)pCons->z - zName);
- p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);
- }
-#endif
- }
-}
-
-#ifndef SQLITE_OMIT_VIEW
-/*
-** The parser calls this routine in order to create a new VIEW
-*/
-void sqlite3CreateView(
- Parse *pParse, /* The parsing context */
- Token *pBegin, /* The CREATE token that begins the statement */
- Token *pName1, /* The token that holds the name of the view */
- Token *pName2, /* The token that holds the name of the view */
- ExprList *pCNames, /* Optional list of view column names */
- Select *pSelect, /* A SELECT statement that will become the new view */
- int isTemp, /* TRUE for a TEMPORARY view */
- int noErr /* Suppress error messages if VIEW already exists */
-){
- Table *p;
- int n;
- const char *z;
- Token sEnd;
- DbFixer sFix;
- Token *pName = 0;
- int iDb;
- sqlite3 *db = pParse->db;
-
- if( pParse->nVar>0 ){
- sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
- goto create_view_fail;
- }
- sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
- p = pParse->pNewTable;
- if( p==0 || pParse->nErr ) goto create_view_fail;
- sqlite3TwoPartName(pParse, pName1, pName2, &pName);
- iDb = sqlite3SchemaToIndex(db, p->pSchema);
- sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
- if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
-
- /* Make a copy of the entire SELECT statement that defines the view.
- ** This will force all the Expr.token.z values to be dynamically
- ** allocated rather than point to the input string - which means that
- ** they will persist after the current sqlite3_exec() call returns.
- */
- p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
- p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
- if( db->mallocFailed ) goto create_view_fail;
-
- /* Locate the end of the CREATE VIEW statement. Make sEnd point to
- ** the end.
- */
- sEnd = pParse->sLastToken;
- assert( sEnd.z[0]!=0 || sEnd.n==0 );
- if( sEnd.z[0]!=';' ){
- sEnd.z += sEnd.n;
- }
- sEnd.n = 0;
- n = (int)(sEnd.z - pBegin->z);
- assert( n>0 );
- z = pBegin->z;
- while( sqlite3Isspace(z[n-1]) ){ n--; }
- sEnd.z = &z[n-1];
- sEnd.n = 1;
-
- /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
- sqlite3EndTable(pParse, 0, &sEnd, 0, 0);
-
-create_view_fail:
- sqlite3SelectDelete(db, pSelect);
- sqlite3ExprListDelete(db, pCNames);
- return;
-}
-#endif /* SQLITE_OMIT_VIEW */
-
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
-/*
-** The Table structure pTable is really a VIEW. Fill in the names of
-** the columns of the view in the pTable structure. Return the number
-** of errors. If an error is seen leave an error message in pParse->zErrMsg.
-*/
-int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
- Table *pSelTab; /* A fake table from which we get the result set */
- Select *pSel; /* Copy of the SELECT that implements the view */
- int nErr = 0; /* Number of errors encountered */
- int n; /* Temporarily holds the number of cursors assigned */
- sqlite3 *db = pParse->db; /* Database connection for malloc errors */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- int rc;
-#endif
-#ifndef SQLITE_OMIT_AUTHORIZATION
- sqlite3_xauth xAuth; /* Saved xAuth pointer */
-#endif
-
- assert( pTable );
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- db->nSchemaLock++;
- rc = sqlite3VtabCallConnect(pParse, pTable);
- db->nSchemaLock--;
- if( rc ){
- return 1;
- }
- if( IsVirtual(pTable) ) return 0;
-#endif
-
-#ifndef SQLITE_OMIT_VIEW
- /* A positive nCol means the columns names for this view are
- ** already known.
- */
- if( pTable->nCol>0 ) return 0;
-
- /* A negative nCol is a special marker meaning that we are currently
- ** trying to compute the column names. If we enter this routine with
- ** a negative nCol, it means two or more views form a loop, like this:
- **
- ** CREATE VIEW one AS SELECT * FROM two;
- ** CREATE VIEW two AS SELECT * FROM one;
- **
- ** Actually, the error above is now caught prior to reaching this point.
- ** But the following test is still important as it does come up
- ** in the following:
- **
- ** CREATE TABLE main.ex1(a);
- ** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
- ** SELECT * FROM temp.ex1;
- */
- if( pTable->nCol<0 ){
- sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
- return 1;
- }
- assert( pTable->nCol>=0 );
-
- /* If we get this far, it means we need to compute the table names.
- ** Note that the call to sqlite3ResultSetOfSelect() will expand any
- ** "*" elements in the results set of the view and will assign cursors
- ** to the elements of the FROM clause. But we do not want these changes
- ** to be permanent. So the computation is done on a copy of the SELECT
- ** statement that defines the view.
- */
- assert( pTable->pSelect );
- pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
- if( pSel ){
- n = pParse->nTab;
- sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
- pTable->nCol = -1;
- db->lookaside.bDisable++;
-#ifndef SQLITE_OMIT_AUTHORIZATION
- xAuth = db->xAuth;
- db->xAuth = 0;
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
- db->xAuth = xAuth;
-#else
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
-#endif
- pParse->nTab = n;
- if( pTable->pCheck ){
- /* CREATE VIEW name(arglist) AS ...
- ** The names of the columns in the table are taken from
- ** arglist which is stored in pTable->pCheck. The pCheck field
- ** normally holds CHECK constraints on an ordinary table, but for
- ** a VIEW it holds the list of column names.
- */
- sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
- &pTable->nCol, &pTable->aCol);
- if( db->mallocFailed==0
- && pParse->nErr==0
- && pTable->nCol==pSel->pEList->nExpr
- ){
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel);
- }
- }else if( pSelTab ){
- /* CREATE VIEW name AS... without an argument list. Construct
- ** the column names from the SELECT statement that defines the view.
- */
- assert( pTable->aCol==0 );
- pTable->nCol = pSelTab->nCol;
- pTable->aCol = pSelTab->aCol;
- pSelTab->nCol = 0;
- pSelTab->aCol = 0;
- assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
- }else{
- pTable->nCol = 0;
- nErr++;
- }
- sqlite3DeleteTable(db, pSelTab);
- sqlite3SelectDelete(db, pSel);
- db->lookaside.bDisable--;
- } else {
- nErr++;
- }
- pTable->pSchema->schemaFlags |= DB_UnresetViews;
-#endif /* SQLITE_OMIT_VIEW */
- return nErr;
-}
-#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
-
-#ifndef SQLITE_OMIT_VIEW
-/*
-** Clear the column names from every VIEW in database idx.
-*/
-static void sqliteViewResetAll(sqlite3 *db, int idx){
- HashElem *i;
- assert( sqlite3SchemaMutexHeld(db, idx, 0) );
- if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
- for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
- Table *pTab = sqliteHashData(i);
- if( pTab->pSelect ){
- sqlite3DeleteColumnNames(db, pTab);
- pTab->aCol = 0;
- pTab->nCol = 0;
- }
- }
- DbClearProperty(db, idx, DB_UnresetViews);
-}
-#else
-# define sqliteViewResetAll(A,B)
-#endif /* SQLITE_OMIT_VIEW */
-
-/*
-** This function is called by the VDBE to adjust the internal schema
-** used by SQLite when the btree layer moves a table root page. The
-** root-page of a table or index in database iDb has changed from iFrom
-** to iTo.
-**
-** Ticket #1728: The symbol table might still contain information
-** on tables and/or indices that are the process of being deleted.
-** If you are unlucky, one of those deleted indices or tables might
-** have the same rootpage number as the real table or index that is
-** being moved. So we cannot stop searching after the first match
-** because the first match might be for one of the deleted indices
-** or tables and not the table/index that is actually being moved.
-** We must continue looping until all tables and indices with
-** rootpage==iFrom have been converted to have a rootpage of iTo
-** in order to be certain that we got the right one.
-*/
-#ifndef SQLITE_OMIT_AUTOVACUUM
-void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
- HashElem *pElem;
- Hash *pHash;
- Db *pDb;
-
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pDb = &db->aDb[iDb];
- pHash = &pDb->pSchema->tblHash;
- for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
- Table *pTab = sqliteHashData(pElem);
- if( pTab->tnum==iFrom ){
- pTab->tnum = iTo;
- }
- }
- pHash = &pDb->pSchema->idxHash;
- for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
- Index *pIdx = sqliteHashData(pElem);
- if( pIdx->tnum==iFrom ){
- pIdx->tnum = iTo;
- }
- }
-}
-#endif
-
-/*
-** Write code to erase the table with root-page iTable from database iDb.
-** Also write code to modify the sqlite_master table and internal schema
-** if a root-page of another table is moved by the btree-layer whilst
-** erasing iTable (this can happen with an auto-vacuum database).
-*/
-static void destroyRootPage(Parse *pParse, int iTable, int iDb){
- Vdbe *v = sqlite3GetVdbe(pParse);
- int r1 = sqlite3GetTempReg(pParse);
- assert( iTable>1 );
- sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
- sqlite3MayAbort(pParse);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- /* OP_Destroy stores an in integer r1. If this integer
- ** is non-zero, then it is the root page number of a table moved to
- ** location iTable. The following code modifies the sqlite_master table to
- ** reflect this.
- **
- ** The "#NNN" in the SQL is a special constant that means whatever value
- ** is in register NNN. See grammar rules associated with the TK_REGISTER
- ** token for additional information.
- */
- sqlite3NestedParse(pParse,
- "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
- pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1);
-#endif
- sqlite3ReleaseTempReg(pParse, r1);
-}
-
-/*
-** Write VDBE code to erase table pTab and all associated indices on disk.
-** Code to update the sqlite_master tables and internal schema definitions
-** in case a root-page belonging to another table is moved by the btree layer
-** is also added (this can happen with an auto-vacuum database).
-*/
-static void destroyTable(Parse *pParse, Table *pTab){
- /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
- ** is not defined), then it is important to call OP_Destroy on the
- ** table and index root-pages in order, starting with the numerically
- ** largest root-page number. This guarantees that none of the root-pages
- ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
- ** following were coded:
- **
- ** OP_Destroy 4 0
- ** ...
- ** OP_Destroy 5 0
- **
- ** and root page 5 happened to be the largest root-page number in the
- ** database, then root page 5 would be moved to page 4 by the
- ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
- ** a free-list page.
- */
- int iTab = pTab->tnum;
- int iDestroyed = 0;
-
- while( 1 ){
- Index *pIdx;
- int iLargest = 0;
-
- if( iDestroyed==0 || iTab<iDestroyed ){
- iLargest = iTab;
- }
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int iIdx = pIdx->tnum;
- assert( pIdx->pSchema==pTab->pSchema );
- if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
- iLargest = iIdx;
- }
- }
- if( iLargest==0 ){
- return;
- }else{
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 && iDb<pParse->db->nDb );
- destroyRootPage(pParse, iLargest, iDb);
- iDestroyed = iLargest;
- }
- }
-}
-
-/*
-** Remove entries from the sqlite_statN tables (for N in (1,2,3))
-** after a DROP INDEX or DROP TABLE command.
-*/
-static void sqlite3ClearStatTables(
- Parse *pParse, /* The parsing context */
- int iDb, /* The database number */
- const char *zType, /* "idx" or "tbl" */
- const char *zName /* Name of index or table */
-){
- int i;
- const char *zDbName = pParse->db->aDb[iDb].zDbSName;
- for(i=1; i<=4; i++){
- char zTab[24];
- sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
- if( sqlite3FindTable(pParse->db, zTab, zDbName) ){
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE %s=%Q",
- zDbName, zTab, zType, zName
- );
- }
- }
-}
-
-/*
-** Generate code to drop a table.
-*/
-void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
- Vdbe *v;
- sqlite3 *db = pParse->db;
- Trigger *pTrigger;
- Db *pDb = &db->aDb[iDb];
-
- v = sqlite3GetVdbe(pParse);
- assert( v!=0 );
- sqlite3BeginWriteOperation(pParse, 1, iDb);
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab) ){
- sqlite3VdbeAddOp0(v, OP_VBegin);
- }
-#endif
-
- /* Drop all triggers associated with the table being dropped. Code
- ** is generated to remove entries from sqlite_master and/or
- ** sqlite_temp_master if required.
- */
- pTrigger = sqlite3TriggerList(pParse, pTab);
- while( pTrigger ){
- assert( pTrigger->pSchema==pTab->pSchema ||
- pTrigger->pSchema==db->aDb[1].pSchema );
- sqlite3DropTriggerPtr(pParse, pTrigger);
- pTrigger = pTrigger->pNext;
- }
-
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- /* Remove any entries of the sqlite_sequence table associated with
- ** the table being dropped. This is done before the table is dropped
- ** at the btree level, in case the sqlite_sequence table needs to
- ** move as a result of the drop (can happen in auto-vacuum mode).
- */
- if( pTab->tabFlags & TF_Autoincrement ){
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.sqlite_sequence WHERE name=%Q",
- pDb->zDbSName, pTab->zName
- );
- }
-#endif
-
- /* Drop all SQLITE_MASTER table and index entries that refer to the
- ** table. The program name loops through the master table and deletes
- ** every row that refers to a table of the same name as the one being
- ** dropped. Triggers are handled separately because a trigger can be
- ** created in the temp database that refers to a table in another
- ** database.
- */
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
- pDb->zDbSName, MASTER_NAME, pTab->zName);
- if( !isView && !IsVirtual(pTab) ){
- destroyTable(pParse, pTab);
- }
-
- /* Remove the table entry from SQLite's internal schema and modify
- ** the schema cookie.
- */
- if( IsVirtual(pTab) ){
- sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
- }
- sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
- sqlite3ChangeCookie(pParse, iDb);
- sqliteViewResetAll(db, iDb);
-}
-
-/*
-** This routine is called to do the work of a DROP TABLE statement.
-** pName is the name of the table to be dropped.
-*/
-void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
- Table *pTab;
- Vdbe *v;
- sqlite3 *db = pParse->db;
- int iDb;
-
- if( db->mallocFailed ){
- goto exit_drop_table;
- }
- assert( pParse->nErr==0 );
- assert( pName->nSrc==1 );
- if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
- if( noErr ) db->suppressErr++;
- assert( isView==0 || isView==LOCATE_VIEW );
- pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
- if( noErr ) db->suppressErr--;
-
- if( pTab==0 ){
- if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
- goto exit_drop_table;
- }
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDb>=0 && iDb<db->nDb );
-
- /* If pTab is a virtual table, call ViewGetColumnNames() to ensure
- ** it is initialized.
- */
- if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){
- goto exit_drop_table;
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int code;
- const char *zTab = SCHEMA_TABLE(iDb);
- const char *zDb = db->aDb[iDb].zDbSName;
- const char *zArg2 = 0;
- if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
- goto exit_drop_table;
- }
- if( isView ){
- if( !OMIT_TEMPDB && iDb==1 ){
- code = SQLITE_DROP_TEMP_VIEW;
- }else{
- code = SQLITE_DROP_VIEW;
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- }else if( IsVirtual(pTab) ){
- code = SQLITE_DROP_VTABLE;
- zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName;
-#endif
- }else{
- if( !OMIT_TEMPDB && iDb==1 ){
- code = SQLITE_DROP_TEMP_TABLE;
- }else{
- code = SQLITE_DROP_TABLE;
- }
- }
- if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){
- goto exit_drop_table;
- }
- if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
- goto exit_drop_table;
- }
- }
-#endif
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
- && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
- sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
- goto exit_drop_table;
- }
-
-#ifndef SQLITE_OMIT_VIEW
- /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
- ** on a table.
- */
- if( isView && pTab->pSelect==0 ){
- sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
- goto exit_drop_table;
- }
- if( !isView && pTab->pSelect ){
- sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
- goto exit_drop_table;
- }
-#endif
-
- /* Generate code to remove the table from the master table
- ** on disk.
- */
- v = sqlite3GetVdbe(pParse);
- if( v ){
- sqlite3BeginWriteOperation(pParse, 1, iDb);
- sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
- sqlite3FkDropTable(pParse, pName, pTab);
- sqlite3CodeDropTable(pParse, pTab, iDb, isView);
- }
-
-exit_drop_table:
- sqlite3SrcListDelete(db, pName);
-}
-
-/*
-** This routine is called to create a new foreign key on the table
-** currently under construction. pFromCol determines which columns
-** in the current table point to the foreign key. If pFromCol==0 then
-** connect the key to the last column inserted. pTo is the name of
-** the table referred to (a.k.a the "parent" table). pToCol is a list
-** of tables in the parent pTo table. flags contains all
-** information about the conflict resolution algorithms specified
-** in the ON DELETE, ON UPDATE and ON INSERT clauses.
-**
-** An FKey structure is created and added to the table currently
-** under construction in the pParse->pNewTable field.
-**
-** The foreign key is set for IMMEDIATE processing. A subsequent call
-** to sqlite3DeferForeignKey() might change this to DEFERRED.
-*/
-void sqlite3CreateForeignKey(
- Parse *pParse, /* Parsing context */
- ExprList *pFromCol, /* Columns in this table that point to other table */
- Token *pTo, /* Name of the other table */
- ExprList *pToCol, /* Columns in the other table */
- int flags /* Conflict resolution algorithms. */
-){
- sqlite3 *db = pParse->db;
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- FKey *pFKey = 0;
- FKey *pNextTo;
- Table *p = pParse->pNewTable;
- int nByte;
- int i;
- int nCol;
- char *z;
-
- assert( pTo!=0 );
- if( p==0 || IN_DECLARE_VTAB ) goto fk_end;
- if( pFromCol==0 ){
- int iCol = p->nCol-1;
- if( NEVER(iCol<0) ) goto fk_end;
- if( pToCol && pToCol->nExpr!=1 ){
- sqlite3ErrorMsg(pParse, "foreign key on %s"
- " should reference only one column of table %T",
- p->aCol[iCol].zName, pTo);
- goto fk_end;
- }
- nCol = 1;
- }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){
- sqlite3ErrorMsg(pParse,
- "number of columns in foreign key does not match the number of "
- "columns in the referenced table");
- goto fk_end;
- }else{
- nCol = pFromCol->nExpr;
- }
- nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
- if( pToCol ){
- for(i=0; i<pToCol->nExpr; i++){
- nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
- }
- }
- pFKey = sqlite3DbMallocZero(db, nByte );
- if( pFKey==0 ){
- goto fk_end;
- }
- pFKey->pFrom = p;
- pFKey->pNextFrom = p->pFKey;
- z = (char*)&pFKey->aCol[nCol];
- pFKey->zTo = z;
- memcpy(z, pTo->z, pTo->n);
- z[pTo->n] = 0;
- sqlite3Dequote(z);
- z += pTo->n+1;
- pFKey->nCol = nCol;
- if( pFromCol==0 ){
- pFKey->aCol[0].iFrom = p->nCol-1;
- }else{
- for(i=0; i<nCol; i++){
- int j;
- for(j=0; j<p->nCol; j++){
- if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
- pFKey->aCol[i].iFrom = j;
- break;
- }
- }
- if( j>=p->nCol ){
- sqlite3ErrorMsg(pParse,
- "unknown column \"%s\" in foreign key definition",
- pFromCol->a[i].zName);
- goto fk_end;
- }
- }
- }
- if( pToCol ){
- for(i=0; i<nCol; i++){
- int n = sqlite3Strlen30(pToCol->a[i].zName);
- pFKey->aCol[i].zCol = z;
- memcpy(z, pToCol->a[i].zName, n);
- z[n] = 0;
- z += n+1;
- }
- }
- pFKey->isDeferred = 0;
- pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */
- pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */
-
- assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
- pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
- pFKey->zTo, (void *)pFKey
- );
- if( pNextTo==pFKey ){
- sqlite3OomFault(db);
- goto fk_end;
- }
- if( pNextTo ){
- assert( pNextTo->pPrevTo==0 );
- pFKey->pNextTo = pNextTo;
- pNextTo->pPrevTo = pFKey;
- }
-
- /* Link the foreign key to the table as the last step.
- */
- p->pFKey = pFKey;
- pFKey = 0;
-
-fk_end:
- sqlite3DbFree(db, pFKey);
-#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
- sqlite3ExprListDelete(db, pFromCol);
- sqlite3ExprListDelete(db, pToCol);
-}
-
-/*
-** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
-** clause is seen as part of a foreign key definition. The isDeferred
-** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
-** The behavior of the most recently created foreign key is adjusted
-** accordingly.
-*/
-void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- Table *pTab;
- FKey *pFKey;
- if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
- assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
- pFKey->isDeferred = (u8)isDeferred;
-#endif
-}
-
-/*
-** Generate code that will erase and refill index *pIdx. This is
-** used to initialize a newly created index or to recompute the
-** content of an index in response to a REINDEX command.
-**
-** if memRootPage is not negative, it means that the index is newly
-** created. The register specified by memRootPage contains the
-** root page number of the index. If memRootPage is negative, then
-** the index already exists and must be cleared before being refilled and
-** the root page number of the index is taken from pIndex->tnum.
-*/
-static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
- Table *pTab = pIndex->pTable; /* The table that is indexed */
- int iTab = pParse->nTab++; /* Btree cursor used for pTab */
- int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
- int iSorter; /* Cursor opened by OpenSorter (if in use) */
- int addr1; /* Address of top of loop */
- int addr2; /* Address to jump to for next iteration */
- int tnum; /* Root page of index */
- int iPartIdxLabel; /* Jump to this label to skip a row */
- Vdbe *v; /* Generate code into this virtual machine */
- KeyInfo *pKey; /* KeyInfo for index */
- int regRecord; /* Register holding assembled index record */
- sqlite3 *db = pParse->db; /* The database connection */
- int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
- db->aDb[iDb].zDbSName ) ){
- return;
- }
-#endif
-
- /* Require a write-lock on the table to perform this operation */
- sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
-
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) return;
- if( memRootPage>=0 ){
- tnum = memRootPage;
- }else{
- tnum = pIndex->tnum;
- }
- pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
- assert( pKey!=0 || db->mallocFailed || pParse->nErr );
-
- /* Open the sorter cursor if we are to use one. */
- iSorter = pParse->nTab++;
- sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*)
- sqlite3KeyInfoRef(pKey), P4_KEYINFO);
-
- /* Open the table. Loop through all rows of the table, inserting index
- ** records into the sorter. */
- sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
- addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
- regRecord = sqlite3GetTempReg(pParse);
- sqlite3MultiWrite(pParse);
-
- sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
- sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
- sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
- sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addr1);
- if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
- sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
- (char *)pKey, P4_KEYINFO);
- sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
-
- addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
- if( IsUniqueIndex(pIndex) ){
- int j2 = sqlite3VdbeGoto(v, 1);
- addr2 = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeVerifyAbortable(v, OE_Abort);
- sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
- pIndex->nKeyCol); VdbeCoverage(v);
- sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
- sqlite3VdbeJumpHere(v, j2);
- }else{
- addr2 = sqlite3VdbeCurrentAddr(v);
- }
- sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
- sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- sqlite3ReleaseTempReg(pParse, regRecord);
- sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addr1);
-
- sqlite3VdbeAddOp1(v, OP_Close, iTab);
- sqlite3VdbeAddOp1(v, OP_Close, iIdx);
- sqlite3VdbeAddOp1(v, OP_Close, iSorter);
-}
-
-/*
-** Allocate heap space to hold an Index object with nCol columns.
-**
-** Increase the allocation size to provide an extra nExtra bytes
-** of 8-byte aligned space after the Index object and return a
-** pointer to this extra space in *ppExtra.
-*/
-Index *sqlite3AllocateIndexObject(
- sqlite3 *db, /* Database connection */
- i16 nCol, /* Total number of columns in the index */
- int nExtra, /* Number of bytes of extra space to alloc */
- char **ppExtra /* Pointer to the "extra" space */
-){
- Index *p; /* Allocated index object */
- int nByte; /* Bytes of space for Index object + arrays */
-
- nByte = ROUND8(sizeof(Index)) + /* Index structure */
- ROUND8(sizeof(char*)*nCol) + /* Index.azColl */
- ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */
- sizeof(i16)*nCol + /* Index.aiColumn */
- sizeof(u8)*nCol); /* Index.aSortOrder */
- p = sqlite3DbMallocZero(db, nByte + nExtra);
- if( p ){
- char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
- p->azColl = (const char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
- p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
- p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
- p->aSortOrder = (u8*)pExtra;
- p->nColumn = nCol;
- p->nKeyCol = nCol - 1;
- *ppExtra = ((char*)p) + nByte;
- }
- return p;
-}
-
-/*
-** Create a new index for an SQL table. pName1.pName2 is the name of the index
-** and pTblList is the name of the table that is to be indexed. Both will
-** be NULL for a primary key or an index that is created to satisfy a
-** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable
-** as the table to be indexed. pParse->pNewTable is a table that is
-** currently being constructed by a CREATE TABLE statement.
-**
-** pList is a list of columns to be indexed. pList will be NULL if this
-** is a primary key or unique-constraint on the most recent column added
-** to the table currently under construction.
-*/
-void sqlite3CreateIndex(
- Parse *pParse, /* All information about this parse */
- Token *pName1, /* First part of index name. May be NULL */
- Token *pName2, /* Second part of index name. May be NULL */
- SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */
- ExprList *pList, /* A list of columns to be indexed */
- int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- Token *pStart, /* The CREATE token that begins this statement */
- Expr *pPIWhere, /* WHERE clause for partial indices */
- int sortOrder, /* Sort order of primary key when pList==NULL */
- int ifNotExist, /* Omit error if index already exists */
- u8 idxType /* The index type */
-){
- Table *pTab = 0; /* Table to be indexed */
- Index *pIndex = 0; /* The index to be created */
- char *zName = 0; /* Name of the index */
- int nName; /* Number of characters in zName */
- int i, j;
- DbFixer sFix; /* For assigning database names to pTable */
- int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */
- sqlite3 *db = pParse->db;
- Db *pDb; /* The specific table containing the indexed database */
- int iDb; /* Index of the database that is being written */
- Token *pName = 0; /* Unqualified name of the index to create */
- struct ExprList_item *pListItem; /* For looping over pList */
- int nExtra = 0; /* Space allocated for zExtra[] */
- int nExtraCol; /* Number of extra columns needed */
- char *zExtra = 0; /* Extra space after the Index object */
- Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
-
- if( db->mallocFailed || pParse->nErr>0 ){
- goto exit_create_index;
- }
- if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
- goto exit_create_index;
- }
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- goto exit_create_index;
- }
-
- /*
- ** Find the table that is to be indexed. Return early if not found.
- */
- if( pTblName!=0 ){
-
- /* Use the two-part index name to determine the database
- ** to search for the table. 'Fix' the table name to this db
- ** before looking up the table.
- */
- assert( pName1 && pName2 );
- iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
- if( iDb<0 ) goto exit_create_index;
- assert( pName && pName->z );
-
-#ifndef SQLITE_OMIT_TEMPDB
- /* If the index name was unqualified, check if the table
- ** is a temp table. If so, set the database to 1. Do not do this
- ** if initialising a database schema.
- */
- if( !db->init.busy ){
- pTab = sqlite3SrcListLookup(pParse, pTblName);
- if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
- iDb = 1;
- }
- }
-#endif
-
- sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
- if( sqlite3FixSrcList(&sFix, pTblName) ){
- /* Because the parser constructs pTblName from a single identifier,
- ** sqlite3FixSrcList can never fail. */
- assert(0);
- }
- pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
- assert( db->mallocFailed==0 || pTab==0 );
- if( pTab==0 ) goto exit_create_index;
- if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){
- sqlite3ErrorMsg(pParse,
- "cannot create a TEMP index on non-TEMP table \"%s\"",
- pTab->zName);
- goto exit_create_index;
- }
- if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab);
- }else{
- assert( pName==0 );
- assert( pStart==0 );
- pTab = pParse->pNewTable;
- if( !pTab ) goto exit_create_index;
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- }
- pDb = &db->aDb[iDb];
-
- assert( pTab!=0 );
- assert( pParse->nErr==0 );
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
- && db->init.busy==0
-#if SQLITE_USER_AUTHENTICATION
- && sqlite3UserAuthTable(pTab->zName)==0
-#endif
-#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX
- && sqlite3StrICmp(&pTab->zName[7],"master")!=0
-#endif
- && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0
- ){
- sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
- goto exit_create_index;
- }
-#ifndef SQLITE_OMIT_VIEW
- if( pTab->pSelect ){
- sqlite3ErrorMsg(pParse, "views may not be indexed");
- goto exit_create_index;
- }
-#endif
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab) ){
- sqlite3ErrorMsg(pParse, "virtual tables may not be indexed");
- goto exit_create_index;
- }
-#endif
-
- /*
- ** Find the name of the index. Make sure there is not already another
- ** index or table with the same name.
- **
- ** Exception: If we are reading the names of permanent indices from the
- ** sqlite_master table (because some other process changed the schema) and
- ** one of the index names collides with the name of a temporary table or
- ** index, then we will continue to process this index.
- **
- ** If pName==0 it means that we are
- ** dealing with a primary key or UNIQUE constraint. We have to invent our
- ** own name.
- */
- if( pName ){
- zName = sqlite3NameFromToken(db, pName);
- if( zName==0 ) goto exit_create_index;
- assert( pName->z!=0 );
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
- goto exit_create_index;
- }
- if( !db->init.busy ){
- if( sqlite3FindTable(db, zName, 0)!=0 ){
- sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
- goto exit_create_index;
- }
- }
- if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
- if( !ifNotExist ){
- sqlite3ErrorMsg(pParse, "index %s already exists", zName);
- }else{
- assert( !db->init.busy );
- sqlite3CodeVerifySchema(pParse, iDb);
- }
- goto exit_create_index;
- }
- }else{
- int n;
- Index *pLoop;
- for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
- zName = sqlite3MPrintf(db, "sqlite_autoindex_%s_%d", pTab->zName, n);
- if( zName==0 ){
- goto exit_create_index;
- }
-
- /* Automatic index names generated from within sqlite3_declare_vtab()
- ** must have names that are distinct from normal automatic index names.
- ** The following statement converts "sqlite3_autoindex..." into
- ** "sqlite3_butoindex..." in order to make the names distinct.
- ** The "vtab_err.test" test demonstrates the need of this statement. */
- if( IN_DECLARE_VTAB ) zName[7]++;
- }
-
- /* Check for authorization to create an index.
- */
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- const char *zDb = pDb->zDbSName;
- if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
- goto exit_create_index;
- }
- i = SQLITE_CREATE_INDEX;
- if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX;
- if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){
- goto exit_create_index;
- }
- }
-#endif
-
- /* If pList==0, it means this routine was called to make a primary
- ** key out of the last column added to the table under construction.
- ** So create a fake list to simulate this.
- */
- if( pList==0 ){
- Token prevCol;
- Column *pCol = &pTab->aCol[pTab->nCol-1];
- pCol->colFlags |= COLFLAG_UNIQUE;
- sqlite3TokenInit(&prevCol, pCol->zName);
- pList = sqlite3ExprListAppend(pParse, 0,
- sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
- if( pList==0 ) goto exit_create_index;
- assert( pList->nExpr==1 );
- sqlite3ExprListSetSortOrder(pList, sortOrder);
- }else{
- sqlite3ExprListCheckLength(pParse, pList, "index");
- }
-
- /* Figure out how many bytes of space are required to store explicitly
- ** specified collation sequence names.
- */
- for(i=0; i<pList->nExpr; i++){
- Expr *pExpr = pList->a[i].pExpr;
- assert( pExpr!=0 );
- if( pExpr->op==TK_COLLATE ){
- nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken));
- }
- }
-
- /*
- ** Allocate the index structure.
- */
- nName = sqlite3Strlen30(zName);
- nExtraCol = pPk ? pPk->nKeyCol : 1;
- pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol,
- nName + nExtra + 1, &zExtra);
- if( db->mallocFailed ){
- goto exit_create_index;
- }
- assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowLogEst) );
- assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
- pIndex->zName = zExtra;
- zExtra += nName + 1;
- memcpy(pIndex->zName, zName, nName+1);
- pIndex->pTable = pTab;
- pIndex->onError = (u8)onError;
- pIndex->uniqNotNull = onError!=OE_None;
- pIndex->idxType = idxType;
- pIndex->pSchema = db->aDb[iDb].pSchema;
- pIndex->nKeyCol = pList->nExpr;
- if( pPIWhere ){
- sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0);
- pIndex->pPartIdxWhere = pPIWhere;
- pPIWhere = 0;
- }
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
-
- /* Check to see if we should honor DESC requests on index columns
- */
- if( pDb->pSchema->file_format>=4 ){
- sortOrderMask = -1; /* Honor DESC */
- }else{
- sortOrderMask = 0; /* Ignore DESC */
- }
-
- /* Analyze the list of expressions that form the terms of the index and
- ** report any errors. In the common case where the expression is exactly
- ** a table column, store that column in aiColumn[]. For general expressions,
- ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[].
- **
- ** TODO: Issue a warning if two or more columns of the index are identical.
- ** TODO: Issue a warning if the table primary key is used as part of the
- ** index key.
- */
- for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
- Expr *pCExpr; /* The i-th index expression */
- int requestedSortOrder; /* ASC or DESC on the i-th expression */
- const char *zColl; /* Collation sequence name */
-
- sqlite3StringToId(pListItem->pExpr);
- sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr, pListItem->pExpr, 0);
- if( pParse->nErr ) goto exit_create_index;
- pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr);
- if( pCExpr->op!=TK_COLUMN ){
- if( pTab==pParse->pNewTable ){
- sqlite3ErrorMsg(pParse, "expressions prohibited in PRIMARY KEY and "
- "UNIQUE constraints");
- goto exit_create_index;
- }
- if( pIndex->aColExpr==0 ){
- ExprList *pCopy = sqlite3ExprListDup(db, pList, 0);
- pIndex->aColExpr = pCopy;
- if( !db->mallocFailed ){
- assert( pCopy!=0 );
- pListItem = &pCopy->a[i];
- }
- }
- j = XN_EXPR;
- pIndex->aiColumn[i] = XN_EXPR;
- pIndex->uniqNotNull = 0;
- }else{
- j = pCExpr->iColumn;
- assert( j<=0x7fff );
- if( j<0 ){
- j = pTab->iPKey;
- }else if( pTab->aCol[j].notNull==0 ){
- pIndex->uniqNotNull = 0;
- }
- pIndex->aiColumn[i] = (i16)j;
- }
- zColl = 0;
- if( pListItem->pExpr->op==TK_COLLATE ){
- int nColl;
- zColl = pListItem->pExpr->u.zToken;
- nColl = sqlite3Strlen30(zColl) + 1;
- assert( nExtra>=nColl );
- memcpy(zExtra, zColl, nColl);
- zColl = zExtra;
- zExtra += nColl;
- nExtra -= nColl;
- }else if( j>=0 ){
- zColl = pTab->aCol[j].zColl;
- }
- if( !zColl ) zColl = sqlite3StrBINARY;
- if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
- goto exit_create_index;
- }
- pIndex->azColl[i] = zColl;
- requestedSortOrder = pListItem->sortOrder & sortOrderMask;
- pIndex->aSortOrder[i] = (u8)requestedSortOrder;
- }
-
- /* Append the table key to the end of the index. For WITHOUT ROWID
- ** tables (when pPk!=0) this will be the declared PRIMARY KEY. For
- ** normal tables (when pPk==0) this will be the rowid.
- */
- if( pPk ){
- for(j=0; j<pPk->nKeyCol; j++){
- int x = pPk->aiColumn[j];
- assert( x>=0 );
- if( hasColumn(pIndex->aiColumn, pIndex->nKeyCol, x) ){
- pIndex->nColumn--;
- }else{
- pIndex->aiColumn[i] = x;
- pIndex->azColl[i] = pPk->azColl[j];
- pIndex->aSortOrder[i] = pPk->aSortOrder[j];
- i++;
- }
- }
- assert( i==pIndex->nColumn );
- }else{
- pIndex->aiColumn[i] = XN_ROWID;
- pIndex->azColl[i] = sqlite3StrBINARY;
- }
- sqlite3DefaultRowEst(pIndex);
- if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
-
- /* If this index contains every column of its table, then mark
- ** it as a covering index */
- assert( HasRowid(pTab)
- || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 );
- if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){
- pIndex->isCovering = 1;
- for(j=0; j<pTab->nCol; j++){
- if( j==pTab->iPKey ) continue;
- if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue;
- pIndex->isCovering = 0;
- break;
- }
- }
-
- if( pTab==pParse->pNewTable ){
- /* This routine has been called to create an automatic index as a
- ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
- ** a PRIMARY KEY or UNIQUE clause following the column definitions.
- ** i.e. one of:
- **
- ** CREATE TABLE t(x PRIMARY KEY, y);
- ** CREATE TABLE t(x, y, UNIQUE(x, y));
- **
- ** Either way, check to see if the table already has such an index. If
- ** so, don't bother creating this one. This only applies to
- ** automatically created indices. Users can do as they wish with
- ** explicit indices.
- **
- ** Two UNIQUE or PRIMARY KEY constraints are considered equivalent
- ** (and thus suppressing the second one) even if they have different
- ** sort orders.
- **
- ** If there are different collating sequences or if the columns of
- ** the constraint occur in different orders, then the constraints are
- ** considered distinct and both result in separate indices.
- */
- Index *pIdx;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int k;
- assert( IsUniqueIndex(pIdx) );
- assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
- assert( IsUniqueIndex(pIndex) );
-
- if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
- for(k=0; k<pIdx->nKeyCol; k++){
- const char *z1;
- const char *z2;
- assert( pIdx->aiColumn[k]>=0 );
- if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
- z1 = pIdx->azColl[k];
- z2 = pIndex->azColl[k];
- if( sqlite3StrICmp(z1, z2) ) break;
- }
- if( k==pIdx->nKeyCol ){
- if( pIdx->onError!=pIndex->onError ){
- /* This constraint creates the same index as a previous
- ** constraint specified somewhere in the CREATE TABLE statement.
- ** However the ON CONFLICT clauses are different. If both this
- ** constraint and the previous equivalent constraint have explicit
- ** ON CONFLICT clauses this is an error. Otherwise, use the
- ** explicitly specified behavior for the index.
- */
- if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
- sqlite3ErrorMsg(pParse,
- "conflicting ON CONFLICT clauses specified", 0);
- }
- if( pIdx->onError==OE_Default ){
- pIdx->onError = pIndex->onError;
- }
- }
- if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType;
- goto exit_create_index;
- }
- }
- }
-
- /* Link the new Index structure to its table and to the other
- ** in-memory database structures.
- */
- assert( pParse->nErr==0 );
- if( db->init.busy ){
- Index *p;
- assert( !IN_DECLARE_VTAB );
- assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
- p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
- pIndex->zName, pIndex);
- if( p ){
- assert( p==pIndex ); /* Malloc must have failed */
- sqlite3OomFault(db);
- goto exit_create_index;
- }
- db->mDbFlags |= DBFLAG_SchemaChange;
- if( pTblName!=0 ){
- pIndex->tnum = db->init.newTnum;
- }
- }
-
- /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
- ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
- ** emit code to allocate the index rootpage on disk and make an entry for
- ** the index in the sqlite_master table and populate the index with
- ** content. But, do not do this if we are simply reading the sqlite_master
- ** table to parse the schema, or if this index is the PRIMARY KEY index
- ** of a WITHOUT ROWID table.
- **
- ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY
- ** or UNIQUE index in a CREATE TABLE statement. Since the table
- ** has just been created, it contains no data and the index initialization
- ** step can be skipped.
- */
- else if( HasRowid(pTab) || pTblName!=0 ){
- Vdbe *v;
- char *zStmt;
- int iMem = ++pParse->nMem;
-
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto exit_create_index;
-
- sqlite3BeginWriteOperation(pParse, 1, iDb);
-
- /* Create the rootpage for the index using CreateIndex. But before
- ** doing so, code a Noop instruction and store its address in
- ** Index.tnum. This is required in case this index is actually a
- ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In
- ** that case the convertToWithoutRowidTable() routine will replace
- ** the Noop with a Goto to jump over the VDBE code generated below. */
- pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
- sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
-
- /* Gather the complete text of the CREATE INDEX statement into
- ** the zStmt variable
- */
- if( pStart ){
- int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
- if( pName->z[n-1]==';' ) n--;
- /* A named index with an explicit CREATE INDEX statement */
- zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
- onError==OE_None ? "" : " UNIQUE", n, pName->z);
- }else{
- /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
- /* zStmt = sqlite3MPrintf(""); */
- zStmt = 0;
- }
-
- /* Add an entry in sqlite_master for this index
- */
- sqlite3NestedParse(pParse,
- "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
- db->aDb[iDb].zDbSName, MASTER_NAME,
- pIndex->zName,
- pTab->zName,
- iMem,
- zStmt
- );
- sqlite3DbFree(db, zStmt);
-
- /* Fill the index with data and reparse the schema. Code an OP_Expire
- ** to invalidate all pre-compiled statements.
- */
- if( pTblName ){
- sqlite3RefillIndex(pParse, pIndex, iMem);
- sqlite3ChangeCookie(pParse, iDb);
- sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
- sqlite3VdbeAddOp0(v, OP_Expire);
- }
-
- sqlite3VdbeJumpHere(v, pIndex->tnum);
- }
-
- /* When adding an index to the list of indices for a table, make
- ** sure all indices labeled OE_Replace come after all those labeled
- ** OE_Ignore. This is necessary for the correct constraint check
- ** processing (in sqlite3GenerateConstraintChecks()) as part of
- ** UPDATE and INSERT statements.
- */
- if( db->init.busy || pTblName==0 ){
- if( onError!=OE_Replace || pTab->pIndex==0
- || pTab->pIndex->onError==OE_Replace){
- pIndex->pNext = pTab->pIndex;
- pTab->pIndex = pIndex;
- }else{
- Index *pOther = pTab->pIndex;
- while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
- pOther = pOther->pNext;
- }
- pIndex->pNext = pOther->pNext;
- pOther->pNext = pIndex;
- }
- pIndex = 0;
- }
-
- /* Clean up before exiting */
-exit_create_index:
- if( pIndex ) freeIndex(db, pIndex);
- sqlite3ExprDelete(db, pPIWhere);
- sqlite3ExprListDelete(db, pList);
- sqlite3SrcListDelete(db, pTblName);
- sqlite3DbFree(db, zName);
-}
-
-/*
-** Fill the Index.aiRowEst[] array with default information - information
-** to be used when we have not run the ANALYZE command.
-**
-** aiRowEst[0] is supposed to contain the number of elements in the index.
-** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
-** number of rows in the table that match any particular value of the
-** first column of the index. aiRowEst[2] is an estimate of the number
-** of rows that match any particular combination of the first 2 columns
-** of the index. And so forth. It must always be the case that
-*
-** aiRowEst[N]<=aiRowEst[N-1]
-** aiRowEst[N]>=1
-**
-** Apart from that, we have little to go on besides intuition as to
-** how aiRowEst[] should be initialized. The numbers generated here
-** are based on typical values found in actual indices.
-*/
-void sqlite3DefaultRowEst(Index *pIdx){
- /* 10, 9, 8, 7, 6 */
- LogEst aVal[] = { 33, 32, 30, 28, 26 };
- LogEst *a = pIdx->aiRowLogEst;
- int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
- int i;
-
- /* Indexes with default row estimates should not have stat1 data */
- assert( !pIdx->hasStat1 );
-
- /* Set the first entry (number of rows in the index) to the estimated
- ** number of rows in the table, or half the number of rows in the table
- ** for a partial index. But do not let the estimate drop below 10. */
- a[0] = pIdx->pTable->nRowLogEst;
- if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) );
- if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) );
-
- /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
- ** 6 and each subsequent value (if any) is 5. */
- memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
- for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
- a[i] = 23; assert( 23==sqlite3LogEst(5) );
- }
-
- assert( 0==sqlite3LogEst(1) );
- if( IsUniqueIndex(pIdx) ) a[pIdx->nKeyCol] = 0;
-}
-
-/*
-** This routine will drop an existing named index. This routine
-** implements the DROP INDEX statement.
-*/
-void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
- Index *pIndex;
- Vdbe *v;
- sqlite3 *db = pParse->db;
- int iDb;
-
- assert( pParse->nErr==0 ); /* Never called with prior errors */
- if( db->mallocFailed ){
- goto exit_drop_index;
- }
- assert( pName->nSrc==1 );
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- goto exit_drop_index;
- }
- pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
- if( pIndex==0 ){
- if( !ifExists ){
- sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
- }else{
- sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
- }
- pParse->checkSchema = 1;
- goto exit_drop_index;
- }
- if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
- sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
- "or PRIMARY KEY constraint cannot be dropped", 0);
- goto exit_drop_index;
- }
- iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int code = SQLITE_DROP_INDEX;
- Table *pTab = pIndex->pTable;
- const char *zDb = db->aDb[iDb].zDbSName;
- const char *zTab = SCHEMA_TABLE(iDb);
- if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
- goto exit_drop_index;
- }
- if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX;
- if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
- goto exit_drop_index;
- }
- }
-#endif
-
- /* Generate code to remove the index and from the master table */
- v = sqlite3GetVdbe(pParse);
- if( v ){
- sqlite3BeginWriteOperation(pParse, 1, iDb);
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
- db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName
- );
- sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
- sqlite3ChangeCookie(pParse, iDb);
- destroyRootPage(pParse, pIndex->tnum, iDb);
- sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
- }
-
-exit_drop_index:
- sqlite3SrcListDelete(db, pName);
-}
-
-/*
-** pArray is a pointer to an array of objects. Each object in the
-** array is szEntry bytes in size. This routine uses sqlite3DbRealloc()
-** to extend the array so that there is space for a new object at the end.
-**
-** When this function is called, *pnEntry contains the current size of
-** the array (in entries - so the allocation is ((*pnEntry) * szEntry) bytes
-** in total).
-**
-** If the realloc() is successful (i.e. if no OOM condition occurs), the
-** space allocated for the new object is zeroed, *pnEntry updated to
-** reflect the new size of the array and a pointer to the new allocation
-** returned. *pIdx is set to the index of the new array entry in this case.
-**
-** Otherwise, if the realloc() fails, *pIdx is set to -1, *pnEntry remains
-** unchanged and a copy of pArray returned.
-*/
-void *sqlite3ArrayAllocate(
- sqlite3 *db, /* Connection to notify of malloc failures */
- void *pArray, /* Array of objects. Might be reallocated */
- int szEntry, /* Size of each object in the array */
- int *pnEntry, /* Number of objects currently in use */
- int *pIdx /* Write the index of a new slot here */
-){
- char *z;
- int n = *pnEntry;
- if( (n & (n-1))==0 ){
- int sz = (n==0) ? 1 : 2*n;
- void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry);
- if( pNew==0 ){
- *pIdx = -1;
- return pArray;
- }
- pArray = pNew;
- }
- z = (char*)pArray;
- memset(&z[n * szEntry], 0, szEntry);
- *pIdx = n;
- ++*pnEntry;
- return pArray;
-}
-
-/*
-** Append a new element to the given IdList. Create a new IdList if
-** need be.
-**
-** A new IdList is returned, or NULL if malloc() fails.
-*/
-IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){
- int i;
- if( pList==0 ){
- pList = sqlite3DbMallocZero(db, sizeof(IdList) );
- if( pList==0 ) return 0;
- }
- pList->a = sqlite3ArrayAllocate(
- db,
- pList->a,
- sizeof(pList->a[0]),
- &pList->nId,
- &i
- );
- if( i<0 ){
- sqlite3IdListDelete(db, pList);
- return 0;
- }
- pList->a[i].zName = sqlite3NameFromToken(db, pToken);
- return pList;
-}
-
-/*
-** Delete an IdList.
-*/
-void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
- int i;
- if( pList==0 ) return;
- for(i=0; i<pList->nId; i++){
- sqlite3DbFree(db, pList->a[i].zName);
- }
- sqlite3DbFree(db, pList->a);
- sqlite3DbFreeNN(db, pList);
-}
-
-/*
-** Return the index in pList of the identifier named zId. Return -1
-** if not found.
-*/
-int sqlite3IdListIndex(IdList *pList, const char *zName){
- int i;
- if( pList==0 ) return -1;
- for(i=0; i<pList->nId; i++){
- if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
- }
- return -1;
-}
-
-/*
-** Expand the space allocated for the given SrcList object by
-** creating nExtra new slots beginning at iStart. iStart is zero based.
-** New slots are zeroed.
-**
-** For example, suppose a SrcList initially contains two entries: A,B.
-** To append 3 new entries onto the end, do this:
-**
-** sqlite3SrcListEnlarge(db, pSrclist, 3, 2);
-**
-** After the call above it would contain: A, B, nil, nil, nil.
-** If the iStart argument had been 1 instead of 2, then the result
-** would have been: A, nil, nil, nil, B. To prepend the new slots,
-** the iStart value would be 0. The result then would
-** be: nil, nil, nil, A, B.
-**
-** If a memory allocation fails the SrcList is unchanged. The
-** db->mallocFailed flag will be set to true.
-*/
-SrcList *sqlite3SrcListEnlarge(
- sqlite3 *db, /* Database connection to notify of OOM errors */
- SrcList *pSrc, /* The SrcList to be enlarged */
- int nExtra, /* Number of new slots to add to pSrc->a[] */
- int iStart /* Index in pSrc->a[] of first new slot */
-){
- int i;
-
- /* Sanity checking on calling parameters */
- assert( iStart>=0 );
- assert( nExtra>=1 );
- assert( pSrc!=0 );
- assert( iStart<=pSrc->nSrc );
-
- /* Allocate additional space if needed */
- if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
- SrcList *pNew;
- int nAlloc = pSrc->nSrc*2+nExtra;
- int nGot;
- pNew = sqlite3DbRealloc(db, pSrc,
- sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
- if( pNew==0 ){
- assert( db->mallocFailed );
- return pSrc;
- }
- pSrc = pNew;
- nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
- pSrc->nAlloc = nGot;
- }
-
- /* Move existing slots that come after the newly inserted slots
- ** out of the way */
- for(i=pSrc->nSrc-1; i>=iStart; i--){
- pSrc->a[i+nExtra] = pSrc->a[i];
- }
- pSrc->nSrc += nExtra;
-
- /* Zero the newly allocated slots */
- memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
- for(i=iStart; i<iStart+nExtra; i++){
- pSrc->a[i].iCursor = -1;
- }
-
- /* Return a pointer to the enlarged SrcList */
- return pSrc;
-}
-
-
-/*
-** Append a new table name to the given SrcList. Create a new SrcList if
-** need be. A new entry is created in the SrcList even if pTable is NULL.
-**
-** A SrcList is returned, or NULL if there is an OOM error. The returned
-** SrcList might be the same as the SrcList that was input or it might be
-** a new one. If an OOM error does occurs, then the prior value of pList
-** that is input to this routine is automatically freed.
-**
-** If pDatabase is not null, it means that the table has an optional
-** database name prefix. Like this: "database.table". The pDatabase
-** points to the table name and the pTable points to the database name.
-** The SrcList.a[].zName field is filled with the table name which might
-** come from pTable (if pDatabase is NULL) or from pDatabase.
-** SrcList.a[].zDatabase is filled with the database name from pTable,
-** or with NULL if no database is specified.
-**
-** In other words, if call like this:
-**
-** sqlite3SrcListAppend(D,A,B,0);
-**
-** Then B is a table name and the database name is unspecified. If called
-** like this:
-**
-** sqlite3SrcListAppend(D,A,B,C);
-**
-** Then C is the table name and B is the database name. If C is defined
-** then so is B. In other words, we never have a case where:
-**
-** sqlite3SrcListAppend(D,A,0,C);
-**
-** Both pTable and pDatabase are assumed to be quoted. They are dequoted
-** before being added to the SrcList.
-*/
-SrcList *sqlite3SrcListAppend(
- sqlite3 *db, /* Connection to notify of malloc failures */
- SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */
- Token *pTable, /* Table to append */
- Token *pDatabase /* Database of the table */
-){
- struct SrcList_item *pItem;
- assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
- assert( db!=0 );
- if( pList==0 ){
- pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
- if( pList==0 ) return 0;
- pList->nAlloc = 1;
- pList->nSrc = 1;
- memset(&pList->a[0], 0, sizeof(pList->a[0]));
- pList->a[0].iCursor = -1;
- }else{
- pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
- }
- if( db->mallocFailed ){
- sqlite3SrcListDelete(db, pList);
- return 0;
- }
- pItem = &pList->a[pList->nSrc-1];
- if( pDatabase && pDatabase->z==0 ){
- pDatabase = 0;
- }
- if( pDatabase ){
- pItem->zName = sqlite3NameFromToken(db, pDatabase);
- pItem->zDatabase = sqlite3NameFromToken(db, pTable);
- }else{
- pItem->zName = sqlite3NameFromToken(db, pTable);
- pItem->zDatabase = 0;
- }
- return pList;
-}
-
-/*
-** Assign VdbeCursor index numbers to all tables in a SrcList
-*/
-void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
- int i;
- struct SrcList_item *pItem;
- assert(pList || pParse->db->mallocFailed );
- if( pList ){
- for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pItem->iCursor>=0 ) break;
- pItem->iCursor = pParse->nTab++;
- if( pItem->pSelect ){
- sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
- }
- }
- }
-}
-
-/*
-** Delete an entire SrcList including all its substructure.
-*/
-void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
- int i;
- struct SrcList_item *pItem;
- if( pList==0 ) return;
- for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
- sqlite3DbFree(db, pItem->zDatabase);
- sqlite3DbFree(db, pItem->zName);
- sqlite3DbFree(db, pItem->zAlias);
- if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
- if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
- sqlite3DeleteTable(db, pItem->pTab);
- sqlite3SelectDelete(db, pItem->pSelect);
- sqlite3ExprDelete(db, pItem->pOn);
- sqlite3IdListDelete(db, pItem->pUsing);
- }
- sqlite3DbFreeNN(db, pList);
-}
-
-/*
-** This routine is called by the parser to add a new term to the
-** end of a growing FROM clause. The "p" parameter is the part of
-** the FROM clause that has already been constructed. "p" is NULL
-** if this is the first term of the FROM clause. pTable and pDatabase
-** are the name of the table and database named in the FROM clause term.
-** pDatabase is NULL if the database name qualifier is missing - the
-** usual case. If the term has an alias, then pAlias points to the
-** alias token. If the term is a subquery, then pSubquery is the
-** SELECT statement that the subquery encodes. The pTable and
-** pDatabase parameters are NULL for subqueries. The pOn and pUsing
-** parameters are the content of the ON and USING clauses.
-**
-** Return a new SrcList which encodes is the FROM with the new
-** term added.
-*/
-SrcList *sqlite3SrcListAppendFromTerm(
- Parse *pParse, /* Parsing context */
- SrcList *p, /* The left part of the FROM clause already seen */
- Token *pTable, /* Name of the table to add to the FROM clause */
- Token *pDatabase, /* Name of the database containing pTable */
- Token *pAlias, /* The right-hand side of the AS subexpression */
- Select *pSubquery, /* A subquery used in place of a table name */
- Expr *pOn, /* The ON clause of a join */
- IdList *pUsing /* The USING clause of a join */
-){
- struct SrcList_item *pItem;
- sqlite3 *db = pParse->db;
- if( !p && (pOn || pUsing) ){
- sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
- (pOn ? "ON" : "USING")
- );
- goto append_from_error;
- }
- p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
- if( p==0 ){
- goto append_from_error;
- }
- assert( p->nSrc>0 );
- pItem = &p->a[p->nSrc-1];
- assert( pAlias!=0 );
- if( pAlias->n ){
- pItem->zAlias = sqlite3NameFromToken(db, pAlias);
- }
- pItem->pSelect = pSubquery;
- pItem->pOn = pOn;
- pItem->pUsing = pUsing;
- return p;
-
- append_from_error:
- assert( p==0 );
- sqlite3ExprDelete(db, pOn);
- sqlite3IdListDelete(db, pUsing);
- sqlite3SelectDelete(db, pSubquery);
- return 0;
-}
-
-/*
-** Add an INDEXED BY or NOT INDEXED clause to the most recently added
-** element of the source-list passed as the second argument.
-*/
-void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
- assert( pIndexedBy!=0 );
- if( p && pIndexedBy->n>0 ){
- struct SrcList_item *pItem;
- assert( p->nSrc>0 );
- pItem = &p->a[p->nSrc-1];
- assert( pItem->fg.notIndexed==0 );
- assert( pItem->fg.isIndexedBy==0 );
- assert( pItem->fg.isTabFunc==0 );
- if( pIndexedBy->n==1 && !pIndexedBy->z ){
- /* A "NOT INDEXED" clause was supplied. See parse.y
- ** construct "indexed_opt" for details. */
- pItem->fg.notIndexed = 1;
- }else{
- pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
- pItem->fg.isIndexedBy = 1;
- }
- }
-}
-
-/*
-** Add the list of function arguments to the SrcList entry for a
-** table-valued-function.
-*/
-void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
- if( p ){
- struct SrcList_item *pItem = &p->a[p->nSrc-1];
- assert( pItem->fg.notIndexed==0 );
- assert( pItem->fg.isIndexedBy==0 );
- assert( pItem->fg.isTabFunc==0 );
- pItem->u1.pFuncArg = pList;
- pItem->fg.isTabFunc = 1;
- }else{
- sqlite3ExprListDelete(pParse->db, pList);
- }
-}
-
-/*
-** When building up a FROM clause in the parser, the join operator
-** is initially attached to the left operand. But the code generator
-** expects the join operator to be on the right operand. This routine
-** Shifts all join operators from left to right for an entire FROM
-** clause.
-**
-** Example: Suppose the join is like this:
-**
-** A natural cross join B
-**
-** The operator is "natural cross join". The A and B operands are stored
-** in p->a[0] and p->a[1], respectively. The parser initially stores the
-** operator with A. This routine shifts that operator over to B.
-*/
-void sqlite3SrcListShiftJoinType(SrcList *p){
- if( p ){
- int i;
- for(i=p->nSrc-1; i>0; i--){
- p->a[i].fg.jointype = p->a[i-1].fg.jointype;
- }
- p->a[0].fg.jointype = 0;
- }
-}
-
-/*
-** Generate VDBE code for a BEGIN statement.
-*/
-void sqlite3BeginTransaction(Parse *pParse, int type){
- sqlite3 *db;
- Vdbe *v;
- int i;
-
- assert( pParse!=0 );
- db = pParse->db;
- assert( db!=0 );
- if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){
- return;
- }
- v = sqlite3GetVdbe(pParse);
- if( !v ) return;
- if( type!=TK_DEFERRED ){
- for(i=0; i<db->nDb; i++){
- sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
- sqlite3VdbeUsesBtree(v, i);
- }
- }
- sqlite3VdbeAddOp0(v, OP_AutoCommit);
-}
-
-/*
-** Generate VDBE code for a COMMIT or ROLLBACK statement.
-** Code for ROLLBACK is generated if eType==TK_ROLLBACK. Otherwise
-** code is generated for a COMMIT.
-*/
-void sqlite3EndTransaction(Parse *pParse, int eType){
- Vdbe *v;
- int isRollback;
-
- assert( pParse!=0 );
- assert( pParse->db!=0 );
- assert( eType==TK_COMMIT || eType==TK_END || eType==TK_ROLLBACK );
- isRollback = eType==TK_ROLLBACK;
- if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION,
- isRollback ? "ROLLBACK" : "COMMIT", 0, 0) ){
- return;
- }
- v = sqlite3GetVdbe(pParse);
- if( v ){
- sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, isRollback);
- }
-}
-
-/*
-** This function is called by the parser when it parses a command to create,
-** release or rollback an SQL savepoint.
-*/
-void sqlite3Savepoint(Parse *pParse, int op, Token *pName){
- char *zName = sqlite3NameFromToken(pParse->db, pName);
- if( zName ){
- Vdbe *v = sqlite3GetVdbe(pParse);
-#ifndef SQLITE_OMIT_AUTHORIZATION
- static const char * const az[] = { "BEGIN", "RELEASE", "ROLLBACK" };
- assert( !SAVEPOINT_BEGIN && SAVEPOINT_RELEASE==1 && SAVEPOINT_ROLLBACK==2 );
-#endif
- if( !v || sqlite3AuthCheck(pParse, SQLITE_SAVEPOINT, az[op], zName, 0) ){
- sqlite3DbFree(pParse->db, zName);
- return;
- }
- sqlite3VdbeAddOp4(v, OP_Savepoint, op, 0, 0, zName, P4_DYNAMIC);
- }
-}
-
-/*
-** Make sure the TEMP database is open and available for use. Return
-** the number of errors. Leave any error messages in the pParse structure.
-*/
-int sqlite3OpenTempDatabase(Parse *pParse){
- sqlite3 *db = pParse->db;
- if( db->aDb[1].pBt==0 && !pParse->explain ){
- int rc;
- Btree *pBt;
- static const int flags =
- SQLITE_OPEN_READWRITE |
- SQLITE_OPEN_CREATE |
- SQLITE_OPEN_EXCLUSIVE |
- SQLITE_OPEN_DELETEONCLOSE |
- SQLITE_OPEN_TEMP_DB;
-
- rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
- if( rc!=SQLITE_OK ){
- sqlite3ErrorMsg(pParse, "unable to open a temporary database "
- "file for storing temporary tables");
- pParse->rc = rc;
- return 1;
- }
- db->aDb[1].pBt = pBt;
- assert( db->aDb[1].pSchema );
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
- sqlite3OomFault(db);
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** Record the fact that the schema cookie will need to be verified
-** for database iDb. The code to actually verify the schema cookie
-** will occur at the end of the top-level VDBE and will be generated
-** later, by sqlite3FinishCoding().
-*/
-void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
-
- assert( iDb>=0 && iDb<pParse->db->nDb );
- assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
- assert( iDb<SQLITE_MAX_ATTACHED+2 );
- assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
- if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
- DbMaskSet(pToplevel->cookieMask, iDb);
- if( !OMIT_TEMPDB && iDb==1 ){
- sqlite3OpenTempDatabase(pToplevel);
- }
- }
-}
-
-/*
-** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
-** attached database. Otherwise, invoke it for the database named zDb only.
-*/
-void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
- sqlite3 *db = pParse->db;
- int i;
- for(i=0; i<db->nDb; i++){
- Db *pDb = &db->aDb[i];
- if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zDbSName)) ){
- sqlite3CodeVerifySchema(pParse, i);
- }
- }
-}
-
-/*
-** Generate VDBE code that prepares for doing an operation that
-** might change the database.
-**
-** This routine starts a new transaction if we are not already within
-** a transaction. If we are already within a transaction, then a checkpoint
-** is set if the setStatement parameter is true. A checkpoint should
-** be set for operations that might fail (due to a constraint) part of
-** the way through and which will need to undo some writes without having to
-** rollback the whole transaction. For operations where all constraints
-** can be checked before any changes are made to the database, it is never
-** necessary to undo a write and the checkpoint should not be set.
-*/
-void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
- sqlite3CodeVerifySchema(pParse, iDb);
- DbMaskSet(pToplevel->writeMask, iDb);
- pToplevel->isMultiWrite |= setStatement;
-}
-
-/*
-** Indicate that the statement currently under construction might write
-** more than one entry (example: deleting one row then inserting another,
-** inserting multiple rows in a table, or inserting a row and index entries.)
-** If an abort occurs after some of these writes have completed, then it will
-** be necessary to undo the completed writes.
-*/
-void sqlite3MultiWrite(Parse *pParse){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
- pToplevel->isMultiWrite = 1;
-}
-
-/*
-** The code generator calls this routine if is discovers that it is
-** possible to abort a statement prior to completion. In order to
-** perform this abort without corrupting the database, we need to make
-** sure that the statement is protected by a statement transaction.
-**
-** Technically, we only need to set the mayAbort flag if the
-** isMultiWrite flag was previously set. There is a time dependency
-** such that the abort must occur after the multiwrite. This makes
-** some statements involving the REPLACE conflict resolution algorithm
-** go a little faster. But taking advantage of this time dependency
-** makes it more difficult to prove that the code is correct (in
-** particular, it prevents us from writing an effective
-** implementation of sqlite3AssertMayAbort()) and so we have chosen
-** to take the safe route and skip the optimization.
-*/
-void sqlite3MayAbort(Parse *pParse){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
- pToplevel->mayAbort = 1;
-}
-
-/*
-** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT
-** error. The onError parameter determines which (if any) of the statement
-** and/or current transaction is rolled back.
-*/
-void sqlite3HaltConstraint(
- Parse *pParse, /* Parsing context */
- int errCode, /* extended error code */
- int onError, /* Constraint type */
- char *p4, /* Error message */
- i8 p4type, /* P4_STATIC or P4_TRANSIENT */
- u8 p5Errmsg /* P5_ErrMsg type */
-){
- Vdbe *v = sqlite3GetVdbe(pParse);
- assert( (errCode&0xff)==SQLITE_CONSTRAINT );
- if( onError==OE_Abort ){
- sqlite3MayAbort(pParse);
- }
- sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
- sqlite3VdbeChangeP5(v, p5Errmsg);
-}
-
-/*
-** Code an OP_Halt due to UNIQUE or PRIMARY KEY constraint violation.
-*/
-void sqlite3UniqueConstraint(
- Parse *pParse, /* Parsing context */
- int onError, /* Constraint type */
- Index *pIdx /* The index that triggers the constraint */
-){
- char *zErr;
- int j;
- StrAccum errMsg;
- Table *pTab = pIdx->pTable;
-
- sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200);
- if( pIdx->aColExpr ){
- sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName);
- }else{
- for(j=0; j<pIdx->nKeyCol; j++){
- char *zCol;
- assert( pIdx->aiColumn[j]>=0 );
- zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
- if( j ) sqlite3_str_append(&errMsg, ", ", 2);
- sqlite3_str_appendall(&errMsg, pTab->zName);
- sqlite3_str_append(&errMsg, ".", 1);
- sqlite3_str_appendall(&errMsg, zCol);
- }
- }
- zErr = sqlite3StrAccumFinish(&errMsg);
- sqlite3HaltConstraint(pParse,
- IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY
- : SQLITE_CONSTRAINT_UNIQUE,
- onError, zErr, P4_DYNAMIC, P5_ConstraintUnique);
-}
-
-
-/*
-** Code an OP_Halt due to non-unique rowid.
-*/
-void sqlite3RowidConstraint(
- Parse *pParse, /* Parsing context */
- int onError, /* Conflict resolution algorithm */
- Table *pTab /* The table with the non-unique rowid */
-){
- char *zMsg;
- int rc;
- if( pTab->iPKey>=0 ){
- zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName,
- pTab->aCol[pTab->iPKey].zName);
- rc = SQLITE_CONSTRAINT_PRIMARYKEY;
- }else{
- zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName);
- rc = SQLITE_CONSTRAINT_ROWID;
- }
- sqlite3HaltConstraint(pParse, rc, onError, zMsg, P4_DYNAMIC,
- P5_ConstraintUnique);
-}
-
-/*
-** Check to see if pIndex uses the collating sequence pColl. Return
-** true if it does and false if it does not.
-*/
-#ifndef SQLITE_OMIT_REINDEX
-static int collationMatch(const char *zColl, Index *pIndex){
- int i;
- assert( zColl!=0 );
- for(i=0; i<pIndex->nColumn; i++){
- const char *z = pIndex->azColl[i];
- assert( z!=0 || pIndex->aiColumn[i]<0 );
- if( pIndex->aiColumn[i]>=0 && 0==sqlite3StrICmp(z, zColl) ){
- return 1;
- }
- }
- return 0;
-}
-#endif
-
-/*
-** Recompute all indices of pTab that use the collating sequence pColl.
-** If pColl==0 then recompute all indices of pTab.
-*/
-#ifndef SQLITE_OMIT_REINDEX
-static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
- Index *pIndex; /* An index associated with pTab */
-
- for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
- if( zColl==0 || collationMatch(zColl, pIndex) ){
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- sqlite3RefillIndex(pParse, pIndex, -1);
- }
- }
-}
-#endif
-
-/*
-** Recompute all indices of all tables in all databases where the
-** indices use the collating sequence pColl. If pColl==0 then recompute
-** all indices everywhere.
-*/
-#ifndef SQLITE_OMIT_REINDEX
-static void reindexDatabases(Parse *pParse, char const *zColl){
- Db *pDb; /* A single database */
- int iDb; /* The database index number */
- sqlite3 *db = pParse->db; /* The database connection */
- HashElem *k; /* For looping over tables in pDb */
- Table *pTab; /* A table in the database */
-
- assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */
- for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
- assert( pDb!=0 );
- for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
- pTab = (Table*)sqliteHashData(k);
- reindexTable(pParse, pTab, zColl);
- }
- }
-}
-#endif
-
-/*
-** Generate code for the REINDEX command.
-**
-** REINDEX -- 1
-** REINDEX <collation> -- 2
-** REINDEX ?<database>.?<tablename> -- 3
-** REINDEX ?<database>.?<indexname> -- 4
-**
-** Form 1 causes all indices in all attached databases to be rebuilt.
-** Form 2 rebuilds all indices in all databases that use the named
-** collating function. Forms 3 and 4 rebuild the named index or all
-** indices associated with the named table.
-*/
-#ifndef SQLITE_OMIT_REINDEX
-void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
- CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */
- char *z; /* Name of a table or index */
- const char *zDb; /* Name of the database */
- Table *pTab; /* A table in the database */
- Index *pIndex; /* An index associated with pTab */
- int iDb; /* The database index number */
- sqlite3 *db = pParse->db; /* The database connection */
- Token *pObjName; /* Name of the table or index to be reindexed */
-
- /* Read the database schema. If an error occurs, leave an error message
- ** and code in pParse and return NULL. */
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- return;
- }
-
- if( pName1==0 ){
- reindexDatabases(pParse, 0);
- return;
- }else if( NEVER(pName2==0) || pName2->z==0 ){
- char *zColl;
- assert( pName1->z );
- zColl = sqlite3NameFromToken(pParse->db, pName1);
- if( !zColl ) return;
- pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
- if( pColl ){
- reindexDatabases(pParse, zColl);
- sqlite3DbFree(db, zColl);
- return;
- }
- sqlite3DbFree(db, zColl);
- }
- iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
- if( iDb<0 ) return;
- z = sqlite3NameFromToken(db, pObjName);
- if( z==0 ) return;
- zDb = db->aDb[iDb].zDbSName;
- pTab = sqlite3FindTable(db, z, zDb);
- if( pTab ){
- reindexTable(pParse, pTab, 0);
- sqlite3DbFree(db, z);
- return;
- }
- pIndex = sqlite3FindIndex(db, z, zDb);
- sqlite3DbFree(db, z);
- if( pIndex ){
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- sqlite3RefillIndex(pParse, pIndex, -1);
- return;
- }
- sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
-}
-#endif
-
-/*
-** Return a KeyInfo structure that is appropriate for the given Index.
-**
-** The caller should invoke sqlite3KeyInfoUnref() on the returned object
-** when it has finished using it.
-*/
-KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
- int i;
- int nCol = pIdx->nColumn;
- int nKey = pIdx->nKeyCol;
- KeyInfo *pKey;
- if( pParse->nErr ) return 0;
- if( pIdx->uniqNotNull ){
- pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
- }else{
- pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
- }
- if( pKey ){
- assert( sqlite3KeyInfoIsWriteable(pKey) );
- for(i=0; i<nCol; i++){
- const char *zColl = pIdx->azColl[i];
- pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
- sqlite3LocateCollSeq(pParse, zColl);
- pKey->aSortOrder[i] = pIdx->aSortOrder[i];
- }
- if( pParse->nErr ){
- assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
- if( pIdx->bNoQuery==0 ){
- /* Deactivate the index because it contains an unknown collating
- ** sequence. The only way to reactive the index is to reload the
- ** schema. Adding the missing collating sequence later does not
- ** reactive the index. The application had the chance to register
- ** the missing index using the collation-needed callback. For
- ** simplicity, SQLite will not give the application a second chance.
- */
- pIdx->bNoQuery = 1;
- pParse->rc = SQLITE_ERROR_RETRY;
- }
- sqlite3KeyInfoUnref(pKey);
- pKey = 0;
- }
- }
- return pKey;
-}
-
-#ifndef SQLITE_OMIT_CTE
-/*
-** This routine is invoked once per CTE by the parser while parsing a
-** WITH clause.
-*/
-With *sqlite3WithAdd(
- Parse *pParse, /* Parsing context */
- With *pWith, /* Existing WITH clause, or NULL */
- Token *pName, /* Name of the common-table */
- ExprList *pArglist, /* Optional column name list for the table */
- Select *pQuery /* Query used to initialize the table */
-){
- sqlite3 *db = pParse->db;
- With *pNew;
- char *zName;
-
- /* Check that the CTE name is unique within this WITH clause. If
- ** not, store an error in the Parse structure. */
- zName = sqlite3NameFromToken(pParse->db, pName);
- if( zName && pWith ){
- int i;
- for(i=0; i<pWith->nCte; i++){
- if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){
- sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName);
- }
- }
- }
-
- if( pWith ){
- int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
- pNew = sqlite3DbRealloc(db, pWith, nByte);
- }else{
- pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
- }
- assert( (pNew!=0 && zName!=0) || db->mallocFailed );
-
- if( db->mallocFailed ){
- sqlite3ExprListDelete(db, pArglist);
- sqlite3SelectDelete(db, pQuery);
- sqlite3DbFree(db, zName);
- pNew = pWith;
- }else{
- pNew->a[pNew->nCte].pSelect = pQuery;
- pNew->a[pNew->nCte].pCols = pArglist;
- pNew->a[pNew->nCte].zName = zName;
- pNew->a[pNew->nCte].zCteErr = 0;
- pNew->nCte++;
- }
-
- return pNew;
-}
-
-/*
-** Free the contents of the With object passed as the second argument.
-*/
-void sqlite3WithDelete(sqlite3 *db, With *pWith){
- if( pWith ){
- int i;
- for(i=0; i<pWith->nCte; i++){
- struct Cte *pCte = &pWith->a[i];
- sqlite3ExprListDelete(db, pCte->pCols);
- sqlite3SelectDelete(db, pCte->pSelect);
- sqlite3DbFree(db, pCte->zName);
- }
- sqlite3DbFree(db, pWith);
- }
-}
-#endif /* !defined(SQLITE_OMIT_CTE) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/callback.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/callback.c
deleted file mode 100644
index a629b6825ed..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/callback.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
-** 2005 May 23
-**
-** 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 contains functions used to access the internal hash tables
-** of user defined functions and collation sequences.
-*/
-
-#include "sqliteInt.h"
-
-/*
-** Invoke the 'collation needed' callback to request a collation sequence
-** in the encoding enc of name zName, length nName.
-*/
-static void callCollNeeded(sqlite3 *db, int enc, const char *zName){
- assert( !db->xCollNeeded || !db->xCollNeeded16 );
- if( db->xCollNeeded ){
- char *zExternal = sqlite3DbStrDup(db, zName);
- if( !zExternal ) return;
- db->xCollNeeded(db->pCollNeededArg, db, enc, zExternal);
- sqlite3DbFree(db, zExternal);
- }
-#ifndef SQLITE_OMIT_UTF16
- if( db->xCollNeeded16 ){
- char const *zExternal;
- sqlite3_value *pTmp = sqlite3ValueNew(db);
- sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC);
- zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
- if( zExternal ){
- db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal);
- }
- sqlite3ValueFree(pTmp);
- }
-#endif
-}
-
-/*
-** This routine is called if the collation factory fails to deliver a
-** collation function in the best encoding but there may be other versions
-** of this collation function (for other text encodings) available. Use one
-** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if
-** possible.
-*/
-static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
- CollSeq *pColl2;
- char *z = pColl->zName;
- int i;
- static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };
- for(i=0; i<3; i++){
- pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0);
- if( pColl2->xCmp!=0 ){
- memcpy(pColl, pColl2, sizeof(CollSeq));
- pColl->xDel = 0; /* Do not copy the destructor */
- return SQLITE_OK;
- }
- }
- return SQLITE_ERROR;
-}
-
-/*
-** This function is responsible for invoking the collation factory callback
-** or substituting a collation sequence of a different encoding when the
-** requested collation sequence is not available in the desired encoding.
-**
-** If it is not NULL, then pColl must point to the database native encoding
-** collation sequence with name zName, length nName.
-**
-** The return value is either the collation sequence to be used in database
-** db for collation type name zName, length nName, or NULL, if no collation
-** sequence can be found. If no collation is found, leave an error message.
-**
-** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
-*/
-CollSeq *sqlite3GetCollSeq(
- Parse *pParse, /* Parsing context */
- u8 enc, /* The desired encoding for the collating sequence */
- CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
- const char *zName /* Collating sequence name */
-){
- CollSeq *p;
- sqlite3 *db = pParse->db;
-
- p = pColl;
- if( !p ){
- p = sqlite3FindCollSeq(db, enc, zName, 0);
- }
- if( !p || !p->xCmp ){
- /* No collation sequence of this type for this encoding is registered.
- ** Call the collation factory to see if it can supply us with one.
- */
- callCollNeeded(db, enc, zName);
- p = sqlite3FindCollSeq(db, enc, zName, 0);
- }
- if( p && !p->xCmp && synthCollSeq(db, p) ){
- p = 0;
- }
- assert( !p || p->xCmp );
- if( p==0 ){
- sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
- pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
- }
- return p;
-}
-
-/*
-** This routine is called on a collation sequence before it is used to
-** check that it is defined. An undefined collation sequence exists when
-** a database is loaded that contains references to collation sequences
-** that have not been defined by sqlite3_create_collation() etc.
-**
-** If required, this routine calls the 'collation needed' callback to
-** request a definition of the collating sequence. If this doesn't work,
-** an equivalent collating sequence that uses a text encoding different
-** from the main database is substituted, if one is available.
-*/
-int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
- if( pColl && pColl->xCmp==0 ){
- const char *zName = pColl->zName;
- sqlite3 *db = pParse->db;
- CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);
- if( !p ){
- return SQLITE_ERROR;
- }
- assert( p==pColl );
- }
- return SQLITE_OK;
-}
-
-
-
-/*
-** Locate and return an entry from the db.aCollSeq hash table. If the entry
-** specified by zName and nName is not found and parameter 'create' is
-** true, then create a new entry. Otherwise return NULL.
-**
-** Each pointer stored in the sqlite3.aCollSeq hash table contains an
-** array of three CollSeq structures. The first is the collation sequence
-** preferred for UTF-8, the second UTF-16le, and the third UTF-16be.
-**
-** Stored immediately after the three collation sequences is a copy of
-** the collation sequence name. A pointer to this string is stored in
-** each collation sequence structure.
-*/
-static CollSeq *findCollSeqEntry(
- sqlite3 *db, /* Database connection */
- const char *zName, /* Name of the collating sequence */
- int create /* Create a new entry if true */
-){
- CollSeq *pColl;
- pColl = sqlite3HashFind(&db->aCollSeq, zName);
-
- if( 0==pColl && create ){
- int nName = sqlite3Strlen30(zName) + 1;
- pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName);
- if( pColl ){
- CollSeq *pDel = 0;
- pColl[0].zName = (char*)&pColl[3];
- pColl[0].enc = SQLITE_UTF8;
- pColl[1].zName = (char*)&pColl[3];
- pColl[1].enc = SQLITE_UTF16LE;
- pColl[2].zName = (char*)&pColl[3];
- pColl[2].enc = SQLITE_UTF16BE;
- memcpy(pColl[0].zName, zName, nName);
- pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl);
-
- /* If a malloc() failure occurred in sqlite3HashInsert(), it will
- ** return the pColl pointer to be deleted (because it wasn't added
- ** to the hash table).
- */
- assert( pDel==0 || pDel==pColl );
- if( pDel!=0 ){
- sqlite3OomFault(db);
- sqlite3DbFree(db, pDel);
- pColl = 0;
- }
- }
- }
- return pColl;
-}
-
-/*
-** Parameter zName points to a UTF-8 encoded string nName bytes long.
-** Return the CollSeq* pointer for the collation sequence named zName
-** for the encoding 'enc' from the database 'db'.
-**
-** If the entry specified is not found and 'create' is true, then create a
-** new entry. Otherwise return NULL.
-**
-** A separate function sqlite3LocateCollSeq() is a wrapper around
-** this routine. sqlite3LocateCollSeq() invokes the collation factory
-** if necessary and generates an error message if the collating sequence
-** cannot be found.
-**
-** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()
-*/
-CollSeq *sqlite3FindCollSeq(
- sqlite3 *db,
- u8 enc,
- const char *zName,
- int create
-){
- CollSeq *pColl;
- if( zName ){
- pColl = findCollSeqEntry(db, zName, create);
- }else{
- pColl = db->pDfltColl;
- }
- assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
- assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
- if( pColl ) pColl += enc-1;
- return pColl;
-}
-
-/* During the search for the best function definition, this procedure
-** is called to test how well the function passed as the first argument
-** matches the request for a function with nArg arguments in a system
-** that uses encoding enc. The value returned indicates how well the
-** request is matched. A higher value indicates a better match.
-**
-** If nArg is -1 that means to only return a match (non-zero) if p->nArg
-** is also -1. In other words, we are searching for a function that
-** takes a variable number of arguments.
-**
-** If nArg is -2 that means that we are searching for any function
-** regardless of the number of arguments it uses, so return a positive
-** match score for any
-**
-** The returned value is always between 0 and 6, as follows:
-**
-** 0: Not a match.
-** 1: UTF8/16 conversion required and function takes any number of arguments.
-** 2: UTF16 byte order change required and function takes any number of args.
-** 3: encoding matches and function takes any number of arguments
-** 4: UTF8/16 conversion required - argument count matches exactly
-** 5: UTF16 byte order conversion required - argument count matches exactly
-** 6: Perfect match: encoding and argument count match exactly.
-**
-** If nArg==(-2) then any function with a non-null xSFunc is
-** a perfect match and any function with xSFunc NULL is
-** a non-match.
-*/
-#define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */
-static int matchQuality(
- FuncDef *p, /* The function we are evaluating for match quality */
- int nArg, /* Desired number of arguments. (-1)==any */
- u8 enc /* Desired text encoding */
-){
- int match;
-
- /* nArg of -2 is a special case */
- if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
-
- /* Wrong number of arguments means "no match" */
- if( p->nArg!=nArg && p->nArg>=0 ) return 0;
-
- /* Give a better score to a function with a specific number of arguments
- ** than to function that accepts any number of arguments. */
- if( p->nArg==nArg ){
- match = 4;
- }else{
- match = 1;
- }
-
- /* Bonus points if the text encoding matches */
- if( enc==(p->funcFlags & SQLITE_FUNC_ENCMASK) ){
- match += 2; /* Exact encoding match */
- }else if( (enc & p->funcFlags & 2)!=0 ){
- match += 1; /* Both are UTF16, but with different byte orders */
- }
-
- return match;
-}
-
-/*
-** Search a FuncDefHash for a function with the given name. Return
-** a pointer to the matching FuncDef if found, or 0 if there is no match.
-*/
-static FuncDef *functionSearch(
- int h, /* Hash of the name */
- const char *zFunc /* Name of function */
-){
- FuncDef *p;
- for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
- if( sqlite3StrICmp(p->zName, zFunc)==0 ){
- return p;
- }
- }
- return 0;
-}
-
-/*
-** Insert a new FuncDef into a FuncDefHash hash table.
-*/
-void sqlite3InsertBuiltinFuncs(
- FuncDef *aDef, /* List of global functions to be inserted */
- int nDef /* Length of the apDef[] list */
-){
- int i;
- for(i=0; i<nDef; i++){
- FuncDef *pOther;
- const char *zName = aDef[i].zName;
- int nName = sqlite3Strlen30(zName);
- int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ;
- assert( zName[0]>='a' && zName[0]<='z' );
- pOther = functionSearch(h, zName);
- if( pOther ){
- assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
- aDef[i].pNext = pOther->pNext;
- pOther->pNext = &aDef[i];
- }else{
- aDef[i].pNext = 0;
- aDef[i].u.pHash = sqlite3BuiltinFunctions.a[h];
- sqlite3BuiltinFunctions.a[h] = &aDef[i];
- }
- }
-}
-
-
-
-/*
-** Locate a user function given a name, a number of arguments and a flag
-** indicating whether the function prefers UTF-16 over UTF-8. Return a
-** pointer to the FuncDef structure that defines that function, or return
-** NULL if the function does not exist.
-**
-** If the createFlag argument is true, then a new (blank) FuncDef
-** structure is created and liked into the "db" structure if a
-** no matching function previously existed.
-**
-** If nArg is -2, then the first valid function found is returned. A
-** function is valid if xSFunc is non-zero. The nArg==(-2)
-** case is used to see if zName is a valid function name for some number
-** of arguments. If nArg is -2, then createFlag must be 0.
-**
-** If createFlag is false, then a function with the required name and
-** number of arguments may be returned even if the eTextRep flag does not
-** match that requested.
-*/
-FuncDef *sqlite3FindFunction(
- sqlite3 *db, /* An open database */
- const char *zName, /* Name of the function. zero-terminated */
- int nArg, /* Number of arguments. -1 means any number */
- u8 enc, /* Preferred text encoding */
- u8 createFlag /* Create new entry if true and does not otherwise exist */
-){
- FuncDef *p; /* Iterator variable */
- FuncDef *pBest = 0; /* Best match found so far */
- int bestScore = 0; /* Score of best match */
- int h; /* Hash value */
- int nName; /* Length of the name */
-
- assert( nArg>=(-2) );
- assert( nArg>=(-1) || createFlag==0 );
- nName = sqlite3Strlen30(zName);
-
- /* First search for a match amongst the application-defined functions.
- */
- p = (FuncDef*)sqlite3HashFind(&db->aFunc, zName);
- while( p ){
- int score = matchQuality(p, nArg, enc);
- if( score>bestScore ){
- pBest = p;
- bestScore = score;
- }
- p = p->pNext;
- }
-
- /* If no match is found, search the built-in functions.
- **
- ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in
- ** functions even if a prior app-defined function was found. And give
- ** priority to built-in functions.
- **
- ** Except, if createFlag is true, that means that we are trying to
- ** install a new function. Whatever FuncDef structure is returned it will
- ** have fields overwritten with new information appropriate for the
- ** new function. But the FuncDefs for built-in functions are read-only.
- ** So we must not search for built-ins when creating a new function.
- */
- if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
- bestScore = 0;
- h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
- p = functionSearch(h, zName);
- while( p ){
- int score = matchQuality(p, nArg, enc);
- if( score>bestScore ){
- pBest = p;
- bestScore = score;
- }
- p = p->pNext;
- }
- }
-
- /* If the createFlag parameter is true and the search did not reveal an
- ** exact match for the name, number of arguments and encoding, then add a
- ** new entry to the hash table and return it.
- */
- if( createFlag && bestScore<FUNC_PERFECT_MATCH &&
- (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
- FuncDef *pOther;
- u8 *z;
- pBest->zName = (const char*)&pBest[1];
- pBest->nArg = (u16)nArg;
- pBest->funcFlags = enc;
- memcpy((char*)&pBest[1], zName, nName+1);
- for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z];
- pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest);
- if( pOther==pBest ){
- sqlite3DbFree(db, pBest);
- sqlite3OomFault(db);
- return 0;
- }else{
- pBest->pNext = pOther;
- }
- }
-
- if( pBest && (pBest->xSFunc || createFlag) ){
- return pBest;
- }
- return 0;
-}
-
-/*
-** Free all resources held by the schema structure. The void* argument points
-** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the
-** pointer itself, it just cleans up subsidiary resources (i.e. the contents
-** of the schema hash tables).
-**
-** The Schema.cache_size variable is not cleared.
-*/
-void sqlite3SchemaClear(void *p){
- Hash temp1;
- Hash temp2;
- HashElem *pElem;
- Schema *pSchema = (Schema *)p;
-
- temp1 = pSchema->tblHash;
- temp2 = pSchema->trigHash;
- sqlite3HashInit(&pSchema->trigHash);
- sqlite3HashClear(&pSchema->idxHash);
- for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
- sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
- }
- sqlite3HashClear(&temp2);
- sqlite3HashInit(&pSchema->tblHash);
- for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
- Table *pTab = sqliteHashData(pElem);
- sqlite3DeleteTable(0, pTab);
- }
- sqlite3HashClear(&temp1);
- sqlite3HashClear(&pSchema->fkeyHash);
- pSchema->pSeqTab = 0;
- if( pSchema->schemaFlags & DB_SchemaLoaded ){
- pSchema->iGeneration++;
- }
- pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted);
-}
-
-/*
-** Find and return the schema associated with a BTree. Create
-** a new one if necessary.
-*/
-Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
- Schema * p;
- if( pBt ){
- p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
- }else{
- p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));
- }
- if( !p ){
- sqlite3OomFault(db);
- }else if ( 0==p->file_format ){
- sqlite3HashInit(&p->tblHash);
- sqlite3HashInit(&p->idxHash);
- sqlite3HashInit(&p->trigHash);
- sqlite3HashInit(&p->fkeyHash);
- p->enc = SQLITE_UTF8;
- }
- return p;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/complete.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/complete.c
deleted file mode 100644
index bb2c03098e7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/complete.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** An tokenizer for SQL
-**
-** This file contains C code that implements the sqlite3_complete() API.
-** This code used to be part of the tokenizer.c source file. But by
-** separating it out, the code will be automatically omitted from
-** static links that do not use it.
-*/
-#include "sqliteInt.h"
-#ifndef SQLITE_OMIT_COMPLETE
-
-/*
-** This is defined in tokenize.c. We just have to import the definition.
-*/
-#ifndef SQLITE_AMALGAMATION
-#ifdef SQLITE_ASCII
-#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
-#endif
-#ifdef SQLITE_EBCDIC
-extern const char sqlite3IsEbcdicIdChar[];
-#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
-#endif
-#endif /* SQLITE_AMALGAMATION */
-
-
-/*
-** Token types used by the sqlite3_complete() routine. See the header
-** comments on that procedure for additional information.
-*/
-#define tkSEMI 0
-#define tkWS 1
-#define tkOTHER 2
-#ifndef SQLITE_OMIT_TRIGGER
-#define tkEXPLAIN 3
-#define tkCREATE 4
-#define tkTEMP 5
-#define tkTRIGGER 6
-#define tkEND 7
-#endif
-
-/*
-** Return TRUE if the given SQL string ends in a semicolon.
-**
-** Special handling is require for CREATE TRIGGER statements.
-** Whenever the CREATE TRIGGER keywords are seen, the statement
-** must end with ";END;".
-**
-** This implementation uses a state machine with 8 states:
-**
-** (0) INVALID We have not yet seen a non-whitespace character.
-**
-** (1) START At the beginning or end of an SQL statement. This routine
-** returns 1 if it ends in the START state and 0 if it ends
-** in any other state.
-**
-** (2) NORMAL We are in the middle of statement which ends with a single
-** semicolon.
-**
-** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
-** a statement.
-**
-** (4) CREATE The keyword CREATE has been seen at the beginning of a
-** statement, possibly preceded by EXPLAIN and/or followed by
-** TEMP or TEMPORARY
-**
-** (5) TRIGGER We are in the middle of a trigger definition that must be
-** ended by a semicolon, the keyword END, and another semicolon.
-**
-** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at
-** the end of a trigger definition.
-**
-** (7) END We've seen the ";END" of the ";END;" that occurs at the end
-** of a trigger definition.
-**
-** Transitions between states above are determined by tokens extracted
-** from the input. The following tokens are significant:
-**
-** (0) tkSEMI A semicolon.
-** (1) tkWS Whitespace.
-** (2) tkOTHER Any other SQL token.
-** (3) tkEXPLAIN The "explain" keyword.
-** (4) tkCREATE The "create" keyword.
-** (5) tkTEMP The "temp" or "temporary" keyword.
-** (6) tkTRIGGER The "trigger" keyword.
-** (7) tkEND The "end" keyword.
-**
-** Whitespace never causes a state transition and is always ignored.
-** This means that a SQL string of all whitespace is invalid.
-**
-** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
-** to recognize the end of a trigger can be omitted. All we have to do
-** is look for a semicolon that is not part of an string or comment.
-*/
-int sqlite3_complete(const char *zSql){
- u8 state = 0; /* Current state, using numbers defined in header comment */
- u8 token; /* Value of the next token */
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* A complex statement machine used to detect the end of a CREATE TRIGGER
- ** statement. This is the normal case.
- */
- static const u8 trans[8][8] = {
- /* Token: */
- /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
- /* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, },
- /* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, },
- /* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, },
- /* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, },
- /* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, },
- /* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, },
- /* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, },
- /* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, },
- };
-#else
- /* If triggers are not supported by this compile then the statement machine
- ** used to detect the end of a statement is much simpler
- */
- static const u8 trans[3][3] = {
- /* Token: */
- /* State: ** SEMI WS OTHER */
- /* 0 INVALID: */ { 1, 0, 2, },
- /* 1 START: */ { 1, 1, 2, },
- /* 2 NORMAL: */ { 1, 2, 2, },
- };
-#endif /* SQLITE_OMIT_TRIGGER */
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( zSql==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-
- while( *zSql ){
- switch( *zSql ){
- case ';': { /* A semicolon */
- token = tkSEMI;
- break;
- }
- case ' ':
- case '\r':
- case '\t':
- case '\n':
- case '\f': { /* White space is ignored */
- token = tkWS;
- break;
- }
- case '/': { /* C-style comments */
- if( zSql[1]!='*' ){
- token = tkOTHER;
- break;
- }
- zSql += 2;
- while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
- if( zSql[0]==0 ) return 0;
- zSql++;
- token = tkWS;
- break;
- }
- case '-': { /* SQL-style comments from "--" to end of line */
- if( zSql[1]!='-' ){
- token = tkOTHER;
- break;
- }
- while( *zSql && *zSql!='\n' ){ zSql++; }
- if( *zSql==0 ) return state==1;
- token = tkWS;
- break;
- }
- case '[': { /* Microsoft-style identifiers in [...] */
- zSql++;
- while( *zSql && *zSql!=']' ){ zSql++; }
- if( *zSql==0 ) return 0;
- token = tkOTHER;
- break;
- }
- case '`': /* Grave-accent quoted symbols used by MySQL */
- case '"': /* single- and double-quoted strings */
- case '\'': {
- int c = *zSql;
- zSql++;
- while( *zSql && *zSql!=c ){ zSql++; }
- if( *zSql==0 ) return 0;
- token = tkOTHER;
- break;
- }
- default: {
-#ifdef SQLITE_EBCDIC
- unsigned char c;
-#endif
- if( IdChar((u8)*zSql) ){
- /* Keywords and unquoted identifiers */
- int nId;
- for(nId=1; IdChar(zSql[nId]); nId++){}
-#ifdef SQLITE_OMIT_TRIGGER
- token = tkOTHER;
-#else
- switch( *zSql ){
- case 'c': case 'C': {
- if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
- token = tkCREATE;
- }else{
- token = tkOTHER;
- }
- break;
- }
- case 't': case 'T': {
- if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
- token = tkTRIGGER;
- }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
- token = tkTEMP;
- }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
- token = tkTEMP;
- }else{
- token = tkOTHER;
- }
- break;
- }
- case 'e': case 'E': {
- if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
- token = tkEND;
- }else
-#ifndef SQLITE_OMIT_EXPLAIN
- if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
- token = tkEXPLAIN;
- }else
-#endif
- {
- token = tkOTHER;
- }
- break;
- }
- default: {
- token = tkOTHER;
- break;
- }
- }
-#endif /* SQLITE_OMIT_TRIGGER */
- zSql += nId-1;
- }else{
- /* Operators and special symbols */
- token = tkOTHER;
- }
- break;
- }
- }
- state = trans[state][token];
- zSql++;
- }
- return state==1;
-}
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** This routine is the same as the sqlite3_complete() routine described
-** above, except that the parameter is required to be UTF-16 encoded, not
-** UTF-8.
-*/
-int sqlite3_complete16(const void *zSql){
- sqlite3_value *pVal;
- char const *zSql8;
- int rc;
-
-#ifndef SQLITE_OMIT_AUTOINIT
- rc = sqlite3_initialize();
- if( rc ) return rc;
-#endif
- pVal = sqlite3ValueNew(0);
- sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
- zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
- if( zSql8 ){
- rc = sqlite3_complete(zSql8);
- }else{
- rc = SQLITE_NOMEM_BKPT;
- }
- sqlite3ValueFree(pVal);
- return rc & 0xff;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-#endif /* SQLITE_OMIT_COMPLETE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/ctime.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/ctime.c
deleted file mode 100644
index da79f3a3505..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/ctime.c
+++ /dev/null
@@ -1,755 +0,0 @@
-/*
-** 2010 February 23
-**
-** 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 routines used to report what compile-time options
-** SQLite was built with.
-*/
-
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-
-/*
-** Include the configuration header output by 'configure' if we're using the
-** autoconf-based build
-*/
-#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
-#include "config.h"
-#define SQLITECONFIG_H 1
-#endif
-
-/* These macros are provided to "stringify" the value of the define
-** for those options in which the value is meaningful. */
-#define CTIMEOPT_VAL_(opt) #opt
-#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
-
-/*
-** An array of names of all compile-time options. This array should
-** be sorted A-Z.
-**
-** This array looks large, but in a typical installation actually uses
-** only a handful of compile-time options, so most times this array is usually
-** rather short and uses little memory space.
-*/
-static const char * const sqlite3azCompileOpt[] = {
-
-/*
-** BEGIN CODE GENERATED BY tool/mkctime.tcl
-*/
-#if SQLITE_32BIT_ROWID
- "32BIT_ROWID",
-#endif
-#if SQLITE_4_BYTE_ALIGNED_MALLOC
- "4_BYTE_ALIGNED_MALLOC",
-#endif
-#if SQLITE_64BIT_STATS
- "64BIT_STATS",
-#endif
-#if SQLITE_ALLOW_COVERING_INDEX_SCAN
- "ALLOW_COVERING_INDEX_SCAN",
-#endif
-#if SQLITE_ALLOW_URI_AUTHORITY
- "ALLOW_URI_AUTHORITY",
-#endif
-#ifdef SQLITE_BITMASK_TYPE
- "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
-#endif
-#if SQLITE_BUG_COMPATIBLE_20160819
- "BUG_COMPATIBLE_20160819",
-#endif
-#if SQLITE_CASE_SENSITIVE_LIKE
- "CASE_SENSITIVE_LIKE",
-#endif
-#if SQLITE_CHECK_PAGES
- "CHECK_PAGES",
-#endif
-#if defined(__clang__) && defined(__clang_major__)
- "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
- CTIMEOPT_VAL(__clang_minor__) "."
- CTIMEOPT_VAL(__clang_patchlevel__),
-#elif defined(_MSC_VER)
- "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
-#elif defined(__GNUC__) && defined(__VERSION__)
- "COMPILER=gcc-" __VERSION__,
-#endif
-#if SQLITE_COVERAGE_TEST
- "COVERAGE_TEST",
-#endif
-#if SQLITE_DEBUG
- "DEBUG",
-#endif
-#if SQLITE_DEFAULT_AUTOMATIC_INDEX
- "DEFAULT_AUTOMATIC_INDEX",
-#endif
-#if SQLITE_DEFAULT_AUTOVACUUM
- "DEFAULT_AUTOVACUUM",
-#endif
-#ifdef SQLITE_DEFAULT_CACHE_SIZE
- "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
-#endif
-#if SQLITE_DEFAULT_CKPTFULLFSYNC
- "DEFAULT_CKPTFULLFSYNC",
-#endif
-#ifdef SQLITE_DEFAULT_FILE_FORMAT
- "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
-#endif
-#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
- "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
-#endif
-#if SQLITE_DEFAULT_FOREIGN_KEYS
- "DEFAULT_FOREIGN_KEYS",
-#endif
-#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
- "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
-#endif
-#ifdef SQLITE_DEFAULT_LOCKING_MODE
- "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
-#endif
-#ifdef SQLITE_DEFAULT_LOOKASIDE
- "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE),
-#endif
-#if SQLITE_DEFAULT_MEMSTATUS
- "DEFAULT_MEMSTATUS",
-#endif
-#ifdef SQLITE_DEFAULT_MMAP_SIZE
- "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
-#endif
-#ifdef SQLITE_DEFAULT_PAGE_SIZE
- "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
-#endif
-#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
- "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
-#endif
-#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
- "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
-#endif
-#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
- "DEFAULT_RECURSIVE_TRIGGERS",
-#endif
-#ifdef SQLITE_DEFAULT_ROWEST
- "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
-#endif
-#ifdef SQLITE_DEFAULT_SECTOR_SIZE
- "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
-#endif
-#ifdef SQLITE_DEFAULT_SYNCHRONOUS
- "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
-#endif
-#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
- "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
-#endif
-#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
- "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
-#endif
-#ifdef SQLITE_DEFAULT_WORKER_THREADS
- "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
-#endif
-#if SQLITE_DIRECT_OVERFLOW_READ
- "DIRECT_OVERFLOW_READ",
-#endif
-#if SQLITE_DISABLE_DIRSYNC
- "DISABLE_DIRSYNC",
-#endif
-#if SQLITE_DISABLE_FTS3_UNICODE
- "DISABLE_FTS3_UNICODE",
-#endif
-#if SQLITE_DISABLE_FTS4_DEFERRED
- "DISABLE_FTS4_DEFERRED",
-#endif
-#if SQLITE_DISABLE_INTRINSIC
- "DISABLE_INTRINSIC",
-#endif
-#if SQLITE_DISABLE_LFS
- "DISABLE_LFS",
-#endif
-#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
- "DISABLE_PAGECACHE_OVERFLOW_STATS",
-#endif
-#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
- "DISABLE_SKIPAHEAD_DISTINCT",
-#endif
-#ifdef SQLITE_ENABLE_8_3_NAMES
- "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
-#endif
-#if SQLITE_ENABLE_API_ARMOR
- "ENABLE_API_ARMOR",
-#endif
-#if SQLITE_ENABLE_ATOMIC_WRITE
- "ENABLE_ATOMIC_WRITE",
-#endif
-#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- "ENABLE_BATCH_ATOMIC_WRITE",
-#endif
-#if SQLITE_ENABLE_CEROD
- "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
-#endif
-#if SQLITE_ENABLE_COLUMN_METADATA
- "ENABLE_COLUMN_METADATA",
-#endif
-#if SQLITE_ENABLE_COLUMN_USED_MASK
- "ENABLE_COLUMN_USED_MASK",
-#endif
-#if SQLITE_ENABLE_COSTMULT
- "ENABLE_COSTMULT",
-#endif
-#if SQLITE_ENABLE_CURSOR_HINTS
- "ENABLE_CURSOR_HINTS",
-#endif
-#if SQLITE_ENABLE_DBSTAT_VTAB
- "ENABLE_DBSTAT_VTAB",
-#endif
-#if SQLITE_ENABLE_EXPENSIVE_ASSERT
- "ENABLE_EXPENSIVE_ASSERT",
-#endif
-#if SQLITE_ENABLE_FTS1
- "ENABLE_FTS1",
-#endif
-#if SQLITE_ENABLE_FTS2
- "ENABLE_FTS2",
-#endif
-#if SQLITE_ENABLE_FTS3
- "ENABLE_FTS3",
-#endif
-#if SQLITE_ENABLE_FTS3_PARENTHESIS
- "ENABLE_FTS3_PARENTHESIS",
-#endif
-#if SQLITE_ENABLE_FTS3_TOKENIZER
- "ENABLE_FTS3_TOKENIZER",
-#endif
-#if SQLITE_ENABLE_FTS4
- "ENABLE_FTS4",
-#endif
-#if SQLITE_ENABLE_FTS5
- "ENABLE_FTS5",
-#endif
-#if SQLITE_ENABLE_HIDDEN_COLUMNS
- "ENABLE_HIDDEN_COLUMNS",
-#endif
-#if SQLITE_ENABLE_ICU
- "ENABLE_ICU",
-#endif
-#if SQLITE_ENABLE_IOTRACE
- "ENABLE_IOTRACE",
-#endif
-#if SQLITE_ENABLE_JSON1
- "ENABLE_JSON1",
-#endif
-#if SQLITE_ENABLE_LOAD_EXTENSION
- "ENABLE_LOAD_EXTENSION",
-#endif
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
- "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
-#endif
-#if SQLITE_ENABLE_MEMORY_MANAGEMENT
- "ENABLE_MEMORY_MANAGEMENT",
-#endif
-#if SQLITE_ENABLE_MEMSYS3
- "ENABLE_MEMSYS3",
-#endif
-#if SQLITE_ENABLE_MEMSYS5
- "ENABLE_MEMSYS5",
-#endif
-#if SQLITE_ENABLE_MULTIPLEX
- "ENABLE_MULTIPLEX",
-#endif
-#if SQLITE_ENABLE_NULL_TRIM
- "ENABLE_NULL_TRIM",
-#endif
-#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
- "ENABLE_OVERSIZE_CELL_CHECK",
-#endif
-#if SQLITE_ENABLE_PREUPDATE_HOOK
- "ENABLE_PREUPDATE_HOOK",
-#endif
-#if SQLITE_ENABLE_QPSG
- "ENABLE_QPSG",
-#endif
-#if SQLITE_ENABLE_RBU
- "ENABLE_RBU",
-#endif
-#if SQLITE_ENABLE_RTREE
- "ENABLE_RTREE",
-#endif
-#if SQLITE_ENABLE_SELECTTRACE
- "ENABLE_SELECTTRACE",
-#endif
-#if SQLITE_ENABLE_SESSION
- "ENABLE_SESSION",
-#endif
-#if SQLITE_ENABLE_SNAPSHOT
- "ENABLE_SNAPSHOT",
-#endif
-#if SQLITE_ENABLE_SORTER_REFERENCES
- "ENABLE_SORTER_REFERENCES",
-#endif
-#if SQLITE_ENABLE_SQLLOG
- "ENABLE_SQLLOG",
-#endif
-#if defined(SQLITE_ENABLE_STAT4)
- "ENABLE_STAT4",
-#elif defined(SQLITE_ENABLE_STAT3)
- "ENABLE_STAT3",
-#endif
-#if SQLITE_ENABLE_STMTVTAB
- "ENABLE_STMTVTAB",
-#endif
-#if SQLITE_ENABLE_STMT_SCANSTATUS
- "ENABLE_STMT_SCANSTATUS",
-#endif
-#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- "ENABLE_UNKNOWN_SQL_FUNCTION",
-#endif
-#if SQLITE_ENABLE_UNLOCK_NOTIFY
- "ENABLE_UNLOCK_NOTIFY",
-#endif
-#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- "ENABLE_UPDATE_DELETE_LIMIT",
-#endif
-#if SQLITE_ENABLE_URI_00_ERROR
- "ENABLE_URI_00_ERROR",
-#endif
-#if SQLITE_ENABLE_VFSTRACE
- "ENABLE_VFSTRACE",
-#endif
-#if SQLITE_ENABLE_WHERETRACE
- "ENABLE_WHERETRACE",
-#endif
-#if SQLITE_ENABLE_ZIPVFS
- "ENABLE_ZIPVFS",
-#endif
-#if SQLITE_EXPLAIN_ESTIMATED_ROWS
- "EXPLAIN_ESTIMATED_ROWS",
-#endif
-#if SQLITE_EXTRA_IFNULLROW
- "EXTRA_IFNULLROW",
-#endif
-#ifdef SQLITE_EXTRA_INIT
- "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
-#endif
-#ifdef SQLITE_EXTRA_SHUTDOWN
- "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
-#endif
-#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
- "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
-#endif
-#if SQLITE_FTS5_ENABLE_TEST_MI
- "FTS5_ENABLE_TEST_MI",
-#endif
-#if SQLITE_FTS5_NO_WITHOUT_ROWID
- "FTS5_NO_WITHOUT_ROWID",
-#endif
-#if SQLITE_HAS_CODEC
- "HAS_CODEC",
-#endif
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
- "HAVE_ISNAN",
-#endif
-#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- "HOMEGROWN_RECURSIVE_MUTEX",
-#endif
-#if SQLITE_IGNORE_AFP_LOCK_ERRORS
- "IGNORE_AFP_LOCK_ERRORS",
-#endif
-#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- "IGNORE_FLOCK_LOCK_ERRORS",
-#endif
-#if SQLITE_INLINE_MEMCPY
- "INLINE_MEMCPY",
-#endif
-#if SQLITE_INT64_TYPE
- "INT64_TYPE",
-#endif
-#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
- "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
-#endif
-#if SQLITE_LIKE_DOESNT_MATCH_BLOBS
- "LIKE_DOESNT_MATCH_BLOBS",
-#endif
-#if SQLITE_LOCK_TRACE
- "LOCK_TRACE",
-#endif
-#if SQLITE_LOG_CACHE_SPILL
- "LOG_CACHE_SPILL",
-#endif
-#ifdef SQLITE_MALLOC_SOFT_LIMIT
- "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
-#endif
-#ifdef SQLITE_MAX_ATTACHED
- "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
-#endif
-#ifdef SQLITE_MAX_COLUMN
- "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
-#endif
-#ifdef SQLITE_MAX_COMPOUND_SELECT
- "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
-#endif
-#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
- "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
-#endif
-#ifdef SQLITE_MAX_EXPR_DEPTH
- "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
-#endif
-#ifdef SQLITE_MAX_FUNCTION_ARG
- "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
-#endif
-#ifdef SQLITE_MAX_LENGTH
- "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
-#endif
-#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
- "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
-#endif
-#ifdef SQLITE_MAX_MEMORY
- "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
-#endif
-#ifdef SQLITE_MAX_MMAP_SIZE
- "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
-#endif
-#ifdef SQLITE_MAX_MMAP_SIZE_
- "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
-#endif
-#ifdef SQLITE_MAX_PAGE_COUNT
- "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
-#endif
-#ifdef SQLITE_MAX_PAGE_SIZE
- "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
-#endif
-#ifdef SQLITE_MAX_SCHEMA_RETRY
- "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
-#endif
-#ifdef SQLITE_MAX_SQL_LENGTH
- "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
-#endif
-#ifdef SQLITE_MAX_TRIGGER_DEPTH
- "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
-#endif
-#ifdef SQLITE_MAX_VARIABLE_NUMBER
- "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
-#endif
-#ifdef SQLITE_MAX_VDBE_OP
- "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
-#endif
-#ifdef SQLITE_MAX_WORKER_THREADS
- "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
-#endif
-#if SQLITE_MEMDEBUG
- "MEMDEBUG",
-#endif
-#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
- "MIXED_ENDIAN_64BIT_FLOAT",
-#endif
-#if SQLITE_MMAP_READWRITE
- "MMAP_READWRITE",
-#endif
-#if SQLITE_MUTEX_NOOP
- "MUTEX_NOOP",
-#endif
-#if SQLITE_MUTEX_NREF
- "MUTEX_NREF",
-#endif
-#if SQLITE_MUTEX_OMIT
- "MUTEX_OMIT",
-#endif
-#if SQLITE_MUTEX_PTHREADS
- "MUTEX_PTHREADS",
-#endif
-#if SQLITE_MUTEX_W32
- "MUTEX_W32",
-#endif
-#if SQLITE_NEED_ERR_NAME
- "NEED_ERR_NAME",
-#endif
-#if SQLITE_NOINLINE
- "NOINLINE",
-#endif
-#if SQLITE_NO_SYNC
- "NO_SYNC",
-#endif
-#if SQLITE_OMIT_ALTERTABLE
- "OMIT_ALTERTABLE",
-#endif
-#if SQLITE_OMIT_ANALYZE
- "OMIT_ANALYZE",
-#endif
-#if SQLITE_OMIT_ATTACH
- "OMIT_ATTACH",
-#endif
-#if SQLITE_OMIT_AUTHORIZATION
- "OMIT_AUTHORIZATION",
-#endif
-#if SQLITE_OMIT_AUTOINCREMENT
- "OMIT_AUTOINCREMENT",
-#endif
-#if SQLITE_OMIT_AUTOINIT
- "OMIT_AUTOINIT",
-#endif
-#if SQLITE_OMIT_AUTOMATIC_INDEX
- "OMIT_AUTOMATIC_INDEX",
-#endif
-#if SQLITE_OMIT_AUTORESET
- "OMIT_AUTORESET",
-#endif
-#if SQLITE_OMIT_AUTOVACUUM
- "OMIT_AUTOVACUUM",
-#endif
-#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
- "OMIT_BETWEEN_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_BLOB_LITERAL
- "OMIT_BLOB_LITERAL",
-#endif
-#if SQLITE_OMIT_BTREECOUNT
- "OMIT_BTREECOUNT",
-#endif
-#if SQLITE_OMIT_CAST
- "OMIT_CAST",
-#endif
-#if SQLITE_OMIT_CHECK
- "OMIT_CHECK",
-#endif
-#if SQLITE_OMIT_COMPLETE
- "OMIT_COMPLETE",
-#endif
-#if SQLITE_OMIT_COMPOUND_SELECT
- "OMIT_COMPOUND_SELECT",
-#endif
-#if SQLITE_OMIT_CONFLICT_CLAUSE
- "OMIT_CONFLICT_CLAUSE",
-#endif
-#if SQLITE_OMIT_CTE
- "OMIT_CTE",
-#endif
-#if SQLITE_OMIT_DATETIME_FUNCS
- "OMIT_DATETIME_FUNCS",
-#endif
-#if SQLITE_OMIT_DECLTYPE
- "OMIT_DECLTYPE",
-#endif
-#if SQLITE_OMIT_DEPRECATED
- "OMIT_DEPRECATED",
-#endif
-#if SQLITE_OMIT_DISKIO
- "OMIT_DISKIO",
-#endif
-#if SQLITE_OMIT_EXPLAIN
- "OMIT_EXPLAIN",
-#endif
-#if SQLITE_OMIT_FLAG_PRAGMAS
- "OMIT_FLAG_PRAGMAS",
-#endif
-#if SQLITE_OMIT_FLOATING_POINT
- "OMIT_FLOATING_POINT",
-#endif
-#if SQLITE_OMIT_FOREIGN_KEY
- "OMIT_FOREIGN_KEY",
-#endif
-#if SQLITE_OMIT_GET_TABLE
- "OMIT_GET_TABLE",
-#endif
-#if SQLITE_OMIT_HEX_INTEGER
- "OMIT_HEX_INTEGER",
-#endif
-#if SQLITE_OMIT_INCRBLOB
- "OMIT_INCRBLOB",
-#endif
-#if SQLITE_OMIT_INTEGRITY_CHECK
- "OMIT_INTEGRITY_CHECK",
-#endif
-#if SQLITE_OMIT_LIKE_OPTIMIZATION
- "OMIT_LIKE_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_LOAD_EXTENSION
- "OMIT_LOAD_EXTENSION",
-#endif
-#if SQLITE_OMIT_LOCALTIME
- "OMIT_LOCALTIME",
-#endif
-#if SQLITE_OMIT_LOOKASIDE
- "OMIT_LOOKASIDE",
-#endif
-#if SQLITE_OMIT_MEMORYDB
- "OMIT_MEMORYDB",
-#endif
-#if SQLITE_OMIT_OR_OPTIMIZATION
- "OMIT_OR_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_PAGER_PRAGMAS
- "OMIT_PAGER_PRAGMAS",
-#endif
-#if SQLITE_OMIT_PARSER_TRACE
- "OMIT_PARSER_TRACE",
-#endif
-#if SQLITE_OMIT_POPEN
- "OMIT_POPEN",
-#endif
-#if SQLITE_OMIT_PRAGMA
- "OMIT_PRAGMA",
-#endif
-#if SQLITE_OMIT_PROGRESS_CALLBACK
- "OMIT_PROGRESS_CALLBACK",
-#endif
-#if SQLITE_OMIT_QUICKBALANCE
- "OMIT_QUICKBALANCE",
-#endif
-#if SQLITE_OMIT_REINDEX
- "OMIT_REINDEX",
-#endif
-#if SQLITE_OMIT_SCHEMA_PRAGMAS
- "OMIT_SCHEMA_PRAGMAS",
-#endif
-#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
- "OMIT_SCHEMA_VERSION_PRAGMAS",
-#endif
-#if SQLITE_OMIT_SHARED_CACHE
- "OMIT_SHARED_CACHE",
-#endif
-#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
- "OMIT_SHUTDOWN_DIRECTORIES",
-#endif
-#if SQLITE_OMIT_SUBQUERY
- "OMIT_SUBQUERY",
-#endif
-#if SQLITE_OMIT_TCL_VARIABLE
- "OMIT_TCL_VARIABLE",
-#endif
-#if SQLITE_OMIT_TEMPDB
- "OMIT_TEMPDB",
-#endif
-#if SQLITE_OMIT_TEST_CONTROL
- "OMIT_TEST_CONTROL",
-#endif
-#if SQLITE_OMIT_TRACE
- "OMIT_TRACE",
-#endif
-#if SQLITE_OMIT_TRIGGER
- "OMIT_TRIGGER",
-#endif
-#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
- "OMIT_TRUNCATE_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_UTF16
- "OMIT_UTF16",
-#endif
-#if SQLITE_OMIT_VACUUM
- "OMIT_VACUUM",
-#endif
-#if SQLITE_OMIT_VIEW
- "OMIT_VIEW",
-#endif
-#if SQLITE_OMIT_VIRTUALTABLE
- "OMIT_VIRTUALTABLE",
-#endif
-#if SQLITE_OMIT_WAL
- "OMIT_WAL",
-#endif
-#if SQLITE_OMIT_WSD
- "OMIT_WSD",
-#endif
-#if SQLITE_OMIT_XFER_OPT
- "OMIT_XFER_OPT",
-#endif
-#if SQLITE_PCACHE_SEPARATE_HEADER
- "PCACHE_SEPARATE_HEADER",
-#endif
-#if SQLITE_PERFORMANCE_TRACE
- "PERFORMANCE_TRACE",
-#endif
-#if SQLITE_POWERSAFE_OVERWRITE
- "POWERSAFE_OVERWRITE",
-#endif
-#if SQLITE_PREFER_PROXY_LOCKING
- "PREFER_PROXY_LOCKING",
-#endif
-#if SQLITE_PROXY_DEBUG
- "PROXY_DEBUG",
-#endif
-#if SQLITE_REVERSE_UNORDERED_SELECTS
- "REVERSE_UNORDERED_SELECTS",
-#endif
-#if SQLITE_RTREE_INT_ONLY
- "RTREE_INT_ONLY",
-#endif
-#if SQLITE_SECURE_DELETE
- "SECURE_DELETE",
-#endif
-#if SQLITE_SMALL_STACK
- "SMALL_STACK",
-#endif
-#ifdef SQLITE_SORTER_PMASZ
- "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
-#endif
-#if SQLITE_SOUNDEX
- "SOUNDEX",
-#endif
-#ifdef SQLITE_STAT4_SAMPLES
- "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
-#endif
-#ifdef SQLITE_STMTJRNL_SPILL
- "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
-#endif
-#if SQLITE_SUBSTR_COMPATIBILITY
- "SUBSTR_COMPATIBILITY",
-#endif
-#if SQLITE_SYSTEM_MALLOC
- "SYSTEM_MALLOC",
-#endif
-#if SQLITE_TCL
- "TCL",
-#endif
-#ifdef SQLITE_TEMP_STORE
- "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
-#endif
-#if SQLITE_TEST
- "TEST",
-#endif
-#if defined(SQLITE_THREADSAFE)
- "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
-#elif defined(THREADSAFE)
- "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
-#else
- "THREADSAFE=1",
-#endif
-#if SQLITE_UNLINK_AFTER_CLOSE
- "UNLINK_AFTER_CLOSE",
-#endif
-#if SQLITE_UNTESTABLE
- "UNTESTABLE",
-#endif
-#if SQLITE_USER_AUTHENTICATION
- "USER_AUTHENTICATION",
-#endif
-#if SQLITE_USE_ALLOCA
- "USE_ALLOCA",
-#endif
-#if SQLITE_USE_FCNTL_TRACE
- "USE_FCNTL_TRACE",
-#endif
-#if SQLITE_USE_URI
- "USE_URI",
-#endif
-#if SQLITE_VDBE_COVERAGE
- "VDBE_COVERAGE",
-#endif
-#if SQLITE_WIN32_MALLOC
- "WIN32_MALLOC",
-#endif
-#if SQLITE_ZERO_MALLOC
- "ZERO_MALLOC",
-#endif
-/*
-** END CODE GENERATED BY tool/mkctime.tcl
-*/
-};
-
-const char **sqlite3CompileOptions(int *pnOpt){
- *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
- return (const char**)sqlite3azCompileOpt;
-}
-
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/date.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/date.c
deleted file mode 100644
index 313c7f91372..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/date.c
+++ /dev/null
@@ -1,1249 +0,0 @@
-/*
-** 2003 October 31
-**
-** 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 contains the C functions that implement date and time
-** functions for SQLite.
-**
-** There is only one exported symbol in this file - the function
-** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
-** All other code has file scope.
-**
-** SQLite processes all times and dates as julian day numbers. The
-** dates and times are stored as the number of days since noon
-** in Greenwich on November 24, 4714 B.C. according to the Gregorian
-** calendar system.
-**
-** 1970-01-01 00:00:00 is JD 2440587.5
-** 2000-01-01 00:00:00 is JD 2451544.5
-**
-** This implementation requires years to be expressed as a 4-digit number
-** which means that only dates between 0000-01-01 and 9999-12-31 can
-** be represented, even though julian day numbers allow a much wider
-** range of dates.
-**
-** The Gregorian calendar system is used for all dates and times,
-** even those that predate the Gregorian calendar. Historians usually
-** use the julian calendar for dates prior to 1582-10-15 and for some
-** dates afterwards, depending on locale. Beware of this difference.
-**
-** The conversion algorithms are implemented based on descriptions
-** in the following text:
-**
-** Jean Meeus
-** Astronomical Algorithms, 2nd Edition, 1998
-** ISBN 0-943396-61-1
-** Willmann-Bell, Inc
-** Richmond, Virginia (USA)
-*/
-#include "sqliteInt.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <time.h>
-
-#ifndef SQLITE_OMIT_DATETIME_FUNCS
-
-/*
-** The MSVC CRT on Windows CE may not have a localtime() function.
-** So declare a substitute. The substitute function itself is
-** defined in "os_win.c".
-*/
-#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \
- (!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API)
-struct tm *__cdecl localtime(const time_t *);
-#endif
-
-/*
-** A structure for holding a single date and time.
-*/
-typedef struct DateTime DateTime;
-struct DateTime {
- sqlite3_int64 iJD; /* The julian day number times 86400000 */
- int Y, M, D; /* Year, month, and day */
- int h, m; /* Hour and minutes */
- int tz; /* Timezone offset in minutes */
- double s; /* Seconds */
- char validJD; /* True (1) if iJD is valid */
- char rawS; /* Raw numeric value stored in s */
- char validYMD; /* True (1) if Y,M,D are valid */
- char validHMS; /* True (1) if h,m,s are valid */
- char validTZ; /* True (1) if tz is valid */
- char tzSet; /* Timezone was set explicitly */
- char isError; /* An overflow has occurred */
-};
-
-
-/*
-** Convert zDate into one or more integers according to the conversion
-** specifier zFormat.
-**
-** zFormat[] contains 4 characters for each integer converted, except for
-** the last integer which is specified by three characters. The meaning
-** of a four-character format specifiers ABCD is:
-**
-** A: number of digits to convert. Always "2" or "4".
-** B: minimum value. Always "0" or "1".
-** C: maximum value, decoded as:
-** a: 12
-** b: 14
-** c: 24
-** d: 31
-** e: 59
-** f: 9999
-** D: the separator character, or \000 to indicate this is the
-** last number to convert.
-**
-** Example: To translate an ISO-8601 date YYYY-MM-DD, the format would
-** be "40f-21a-20c". The "40f-" indicates the 4-digit year followed by "-".
-** The "21a-" indicates the 2-digit month followed by "-". The "20c" indicates
-** the 2-digit day which is the last integer in the set.
-**
-** The function returns the number of successful conversions.
-*/
-static int getDigits(const char *zDate, const char *zFormat, ...){
- /* The aMx[] array translates the 3rd character of each format
- ** spec into a max size: a b c d e f */
- static const u16 aMx[] = { 12, 14, 24, 31, 59, 9999 };
- va_list ap;
- int cnt = 0;
- char nextC;
- va_start(ap, zFormat);
- do{
- char N = zFormat[0] - '0';
- char min = zFormat[1] - '0';
- int val = 0;
- u16 max;
-
- assert( zFormat[2]>='a' && zFormat[2]<='f' );
- max = aMx[zFormat[2] - 'a'];
- nextC = zFormat[3];
- val = 0;
- while( N-- ){
- if( !sqlite3Isdigit(*zDate) ){
- goto end_getDigits;
- }
- val = val*10 + *zDate - '0';
- zDate++;
- }
- if( val<(int)min || val>(int)max || (nextC!=0 && nextC!=*zDate) ){
- goto end_getDigits;
- }
- *va_arg(ap,int*) = val;
- zDate++;
- cnt++;
- zFormat += 4;
- }while( nextC );
-end_getDigits:
- va_end(ap);
- return cnt;
-}
-
-/*
-** Parse a timezone extension on the end of a date-time.
-** The extension is of the form:
-**
-** (+/-)HH:MM
-**
-** Or the "zulu" notation:
-**
-** Z
-**
-** If the parse is successful, write the number of minutes
-** of change in p->tz and return 0. If a parser error occurs,
-** return non-zero.
-**
-** A missing specifier is not considered an error.
-*/
-static int parseTimezone(const char *zDate, DateTime *p){
- int sgn = 0;
- int nHr, nMn;
- int c;
- while( sqlite3Isspace(*zDate) ){ zDate++; }
- p->tz = 0;
- c = *zDate;
- if( c=='-' ){
- sgn = -1;
- }else if( c=='+' ){
- sgn = +1;
- }else if( c=='Z' || c=='z' ){
- zDate++;
- goto zulu_time;
- }else{
- return c!=0;
- }
- zDate++;
- if( getDigits(zDate, "20b:20e", &nHr, &nMn)!=2 ){
- return 1;
- }
- zDate += 5;
- p->tz = sgn*(nMn + nHr*60);
-zulu_time:
- while( sqlite3Isspace(*zDate) ){ zDate++; }
- p->tzSet = 1;
- return *zDate!=0;
-}
-
-/*
-** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
-** The HH, MM, and SS must each be exactly 2 digits. The
-** fractional seconds FFFF can be one or more digits.
-**
-** Return 1 if there is a parsing error and 0 on success.
-*/
-static int parseHhMmSs(const char *zDate, DateTime *p){
- int h, m, s;
- double ms = 0.0;
- if( getDigits(zDate, "20c:20e", &h, &m)!=2 ){
- return 1;
- }
- zDate += 5;
- if( *zDate==':' ){
- zDate++;
- if( getDigits(zDate, "20e", &s)!=1 ){
- return 1;
- }
- zDate += 2;
- if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){
- double rScale = 1.0;
- zDate++;
- while( sqlite3Isdigit(*zDate) ){
- ms = ms*10.0 + *zDate - '0';
- rScale *= 10.0;
- zDate++;
- }
- ms /= rScale;
- }
- }else{
- s = 0;
- }
- p->validJD = 0;
- p->rawS = 0;
- p->validHMS = 1;
- p->h = h;
- p->m = m;
- p->s = s + ms;
- if( parseTimezone(zDate, p) ) return 1;
- p->validTZ = (p->tz!=0)?1:0;
- return 0;
-}
-
-/*
-** Put the DateTime object into its error state.
-*/
-static void datetimeError(DateTime *p){
- memset(p, 0, sizeof(*p));
- p->isError = 1;
-}
-
-/*
-** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
-** that the YYYY-MM-DD is according to the Gregorian calendar.
-**
-** Reference: Meeus page 61
-*/
-static void computeJD(DateTime *p){
- int Y, M, D, A, B, X1, X2;
-
- if( p->validJD ) return;
- if( p->validYMD ){
- Y = p->Y;
- M = p->M;
- D = p->D;
- }else{
- Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */
- M = 1;
- D = 1;
- }
- if( Y<-4713 || Y>9999 || p->rawS ){
- datetimeError(p);
- return;
- }
- if( M<=2 ){
- Y--;
- M += 12;
- }
- A = Y/100;
- B = 2 - A + (A/4);
- X1 = 36525*(Y+4716)/100;
- X2 = 306001*(M+1)/10000;
- p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
- p->validJD = 1;
- if( p->validHMS ){
- p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
- if( p->validTZ ){
- p->iJD -= p->tz*60000;
- p->validYMD = 0;
- p->validHMS = 0;
- p->validTZ = 0;
- }
- }
-}
-
-/*
-** Parse dates of the form
-**
-** YYYY-MM-DD HH:MM:SS.FFF
-** YYYY-MM-DD HH:MM:SS
-** YYYY-MM-DD HH:MM
-** YYYY-MM-DD
-**
-** Write the result into the DateTime structure and return 0
-** on success and 1 if the input string is not a well-formed
-** date.
-*/
-static int parseYyyyMmDd(const char *zDate, DateTime *p){
- int Y, M, D, neg;
-
- if( zDate[0]=='-' ){
- zDate++;
- neg = 1;
- }else{
- neg = 0;
- }
- if( getDigits(zDate, "40f-21a-21d", &Y, &M, &D)!=3 ){
- return 1;
- }
- zDate += 10;
- while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; }
- if( parseHhMmSs(zDate, p)==0 ){
- /* We got the time */
- }else if( *zDate==0 ){
- p->validHMS = 0;
- }else{
- return 1;
- }
- p->validJD = 0;
- p->validYMD = 1;
- p->Y = neg ? -Y : Y;
- p->M = M;
- p->D = D;
- if( p->validTZ ){
- computeJD(p);
- }
- return 0;
-}
-
-/*
-** Set the time to the current time reported by the VFS.
-**
-** Return the number of errors.
-*/
-static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
- p->iJD = sqlite3StmtCurrentTime(context);
- if( p->iJD>0 ){
- p->validJD = 1;
- return 0;
- }else{
- return 1;
- }
-}
-
-/*
-** Input "r" is a numeric quantity which might be a julian day number,
-** or the number of seconds since 1970. If the value if r is within
-** range of a julian day number, install it as such and set validJD.
-** If the value is a valid unix timestamp, put it in p->s and set p->rawS.
-*/
-static void setRawDateNumber(DateTime *p, double r){
- p->s = r;
- p->rawS = 1;
- if( r>=0.0 && r<5373484.5 ){
- p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
- p->validJD = 1;
- }
-}
-
-/*
-** Attempt to parse the given string into a julian day number. Return
-** the number of errors.
-**
-** The following are acceptable forms for the input string:
-**
-** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM
-** DDDD.DD
-** now
-**
-** In the first form, the +/-HH:MM is always optional. The fractional
-** seconds extension (the ".FFF") is optional. The seconds portion
-** (":SS.FFF") is option. The year and date can be omitted as long
-** as there is a time string. The time string can be omitted as long
-** as there is a year and date.
-*/
-static int parseDateOrTime(
- sqlite3_context *context,
- const char *zDate,
- DateTime *p
-){
- double r;
- if( parseYyyyMmDd(zDate,p)==0 ){
- return 0;
- }else if( parseHhMmSs(zDate, p)==0 ){
- return 0;
- }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
- return setDateTimeToCurrent(context, p);
- }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
- setRawDateNumber(p, r);
- return 0;
- }
- return 1;
-}
-
-/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999.
-** Multiplying this by 86400000 gives 464269060799999 as the maximum value
-** for DateTime.iJD.
-**
-** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with
-** such a large integer literal, so we have to encode it.
-*/
-#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff)
-
-/*
-** Return TRUE if the given julian day number is within range.
-**
-** The input is the JulianDay times 86400000.
-*/
-static int validJulianDay(sqlite3_int64 iJD){
- return iJD>=0 && iJD<=INT_464269060799999;
-}
-
-/*
-** Compute the Year, Month, and Day from the julian day number.
-*/
-static void computeYMD(DateTime *p){
- int Z, A, B, C, D, E, X1;
- if( p->validYMD ) return;
- if( !p->validJD ){
- p->Y = 2000;
- p->M = 1;
- p->D = 1;
- }else if( !validJulianDay(p->iJD) ){
- datetimeError(p);
- return;
- }else{
- Z = (int)((p->iJD + 43200000)/86400000);
- A = (int)((Z - 1867216.25)/36524.25);
- A = Z + 1 + A - (A/4);
- B = A + 1524;
- C = (int)((B - 122.1)/365.25);
- D = (36525*(C&32767))/100;
- E = (int)((B-D)/30.6001);
- X1 = (int)(30.6001*E);
- p->D = B - D - X1;
- p->M = E<14 ? E-1 : E-13;
- p->Y = p->M>2 ? C - 4716 : C - 4715;
- }
- p->validYMD = 1;
-}
-
-/*
-** Compute the Hour, Minute, and Seconds from the julian day number.
-*/
-static void computeHMS(DateTime *p){
- int s;
- if( p->validHMS ) return;
- computeJD(p);
- s = (int)((p->iJD + 43200000) % 86400000);
- p->s = s/1000.0;
- s = (int)p->s;
- p->s -= s;
- p->h = s/3600;
- s -= p->h*3600;
- p->m = s/60;
- p->s += s - p->m*60;
- p->rawS = 0;
- p->validHMS = 1;
-}
-
-/*
-** Compute both YMD and HMS
-*/
-static void computeYMD_HMS(DateTime *p){
- computeYMD(p);
- computeHMS(p);
-}
-
-/*
-** Clear the YMD and HMS and the TZ
-*/
-static void clearYMD_HMS_TZ(DateTime *p){
- p->validYMD = 0;
- p->validHMS = 0;
- p->validTZ = 0;
-}
-
-#ifndef SQLITE_OMIT_LOCALTIME
-/*
-** On recent Windows platforms, the localtime_s() function is available
-** as part of the "Secure CRT". It is essentially equivalent to
-** localtime_r() available under most POSIX platforms, except that the
-** order of the parameters is reversed.
-**
-** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
-**
-** If the user has not indicated to use localtime_r() or localtime_s()
-** already, check for an MSVC build environment that provides
-** localtime_s().
-*/
-#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \
- && defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
-#undef HAVE_LOCALTIME_S
-#define HAVE_LOCALTIME_S 1
-#endif
-
-/*
-** The following routine implements the rough equivalent of localtime_r()
-** using whatever operating-system specific localtime facility that
-** is available. This routine returns 0 on success and
-** non-zero on any kind of error.
-**
-** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
-** routine will always fail.
-**
-** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
-** library function localtime_r() is used to assist in the calculation of
-** local time.
-*/
-static int osLocaltime(time_t *t, struct tm *pTm){
- int rc;
-#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S
- struct tm *pX;
-#if SQLITE_THREADSAFE>0
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
- sqlite3_mutex_enter(mutex);
- pX = localtime(t);
-#ifndef SQLITE_UNTESTABLE
- if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
-#endif
- if( pX ) *pTm = *pX;
- sqlite3_mutex_leave(mutex);
- rc = pX==0;
-#else
-#ifndef SQLITE_UNTESTABLE
- if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
-#endif
-#if HAVE_LOCALTIME_R
- rc = localtime_r(t, pTm)==0;
-#else
- rc = localtime_s(pTm, t);
-#endif /* HAVE_LOCALTIME_R */
-#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
- return rc;
-}
-#endif /* SQLITE_OMIT_LOCALTIME */
-
-
-#ifndef SQLITE_OMIT_LOCALTIME
-/*
-** Compute the difference (in milliseconds) between localtime and UTC
-** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
-** return this value and set *pRc to SQLITE_OK.
-**
-** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
-** is undefined in this case.
-*/
-static sqlite3_int64 localtimeOffset(
- DateTime *p, /* Date at which to calculate offset */
- sqlite3_context *pCtx, /* Write error here if one occurs */
- int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
-){
- DateTime x, y;
- time_t t;
- struct tm sLocal;
-
- /* Initialize the contents of sLocal to avoid a compiler warning. */
- memset(&sLocal, 0, sizeof(sLocal));
-
- x = *p;
- computeYMD_HMS(&x);
- if( x.Y<1971 || x.Y>=2038 ){
- /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
- ** works for years between 1970 and 2037. For dates outside this range,
- ** SQLite attempts to map the year into an equivalent year within this
- ** range, do the calculation, then map the year back.
- */
- x.Y = 2000;
- x.M = 1;
- x.D = 1;
- x.h = 0;
- x.m = 0;
- x.s = 0.0;
- } else {
- int s = (int)(x.s + 0.5);
- x.s = s;
- }
- x.tz = 0;
- x.validJD = 0;
- computeJD(&x);
- t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
- if( osLocaltime(&t, &sLocal) ){
- sqlite3_result_error(pCtx, "local time unavailable", -1);
- *pRc = SQLITE_ERROR;
- return 0;
- }
- y.Y = sLocal.tm_year + 1900;
- y.M = sLocal.tm_mon + 1;
- y.D = sLocal.tm_mday;
- y.h = sLocal.tm_hour;
- y.m = sLocal.tm_min;
- y.s = sLocal.tm_sec;
- y.validYMD = 1;
- y.validHMS = 1;
- y.validJD = 0;
- y.rawS = 0;
- y.validTZ = 0;
- y.isError = 0;
- computeJD(&y);
- *pRc = SQLITE_OK;
- return y.iJD - x.iJD;
-}
-#endif /* SQLITE_OMIT_LOCALTIME */
-
-/*
-** The following table defines various date transformations of the form
-**
-** 'NNN days'
-**
-** Where NNN is an arbitrary floating-point number and "days" can be one
-** of several units of time.
-*/
-static const struct {
- u8 eType; /* Transformation type code */
- u8 nName; /* Length of th name */
- char *zName; /* Name of the transformation */
- double rLimit; /* Maximum NNN value for this transform */
- double rXform; /* Constant used for this transform */
-} aXformType[] = {
- { 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) },
- { 0, 6, "minute", 7737817680.0, 86400000.0/(24.0*60.0) },
- { 0, 4, "hour", 128963628.0, 86400000.0/24.0 },
- { 0, 3, "day", 5373485.0, 86400000.0 },
- { 1, 5, "month", 176546.0, 30.0*86400000.0 },
- { 2, 4, "year", 14713.0, 365.0*86400000.0 },
-};
-
-/*
-** Process a modifier to a date-time stamp. The modifiers are
-** as follows:
-**
-** NNN days
-** NNN hours
-** NNN minutes
-** NNN.NNNN seconds
-** NNN months
-** NNN years
-** start of month
-** start of year
-** start of week
-** start of day
-** weekday N
-** unixepoch
-** localtime
-** utc
-**
-** Return 0 on success and 1 if there is any kind of error. If the error
-** is in a system call (i.e. localtime()), then an error message is written
-** to context pCtx. If the error is an unrecognized modifier, no error is
-** written to pCtx.
-*/
-static int parseModifier(
- sqlite3_context *pCtx, /* Function context */
- const char *z, /* The text of the modifier */
- int n, /* Length of zMod in bytes */
- DateTime *p /* The date/time value to be modified */
-){
- int rc = 1;
- double r;
- switch(sqlite3UpperToLower[(u8)z[0]] ){
-#ifndef SQLITE_OMIT_LOCALTIME
- case 'l': {
- /* localtime
- **
- ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
- ** show local time.
- */
- if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
- computeJD(p);
- p->iJD += localtimeOffset(p, pCtx, &rc);
- clearYMD_HMS_TZ(p);
- }
- break;
- }
-#endif
- case 'u': {
- /*
- ** unixepoch
- **
- ** Treat the current value of p->s as the number of
- ** seconds since 1970. Convert to a real julian day number.
- */
- if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
- r = p->s*1000.0 + 210866760000000.0;
- if( r>=0.0 && r<464269060800000.0 ){
- clearYMD_HMS_TZ(p);
- p->iJD = (sqlite3_int64)r;
- p->validJD = 1;
- p->rawS = 0;
- rc = 0;
- }
- }
-#ifndef SQLITE_OMIT_LOCALTIME
- else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
- if( p->tzSet==0 ){
- sqlite3_int64 c1;
- computeJD(p);
- c1 = localtimeOffset(p, pCtx, &rc);
- if( rc==SQLITE_OK ){
- p->iJD -= c1;
- clearYMD_HMS_TZ(p);
- p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
- }
- p->tzSet = 1;
- }else{
- rc = SQLITE_OK;
- }
- }
-#endif
- break;
- }
- case 'w': {
- /*
- ** weekday N
- **
- ** Move the date to the same time on the next occurrence of
- ** weekday N where 0==Sunday, 1==Monday, and so forth. If the
- ** date is already on the appropriate weekday, this is a no-op.
- */
- if( sqlite3_strnicmp(z, "weekday ", 8)==0
- && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
- && (n=(int)r)==r && n>=0 && r<7 ){
- sqlite3_int64 Z;
- computeYMD_HMS(p);
- p->validTZ = 0;
- p->validJD = 0;
- computeJD(p);
- Z = ((p->iJD + 129600000)/86400000) % 7;
- if( Z>n ) Z -= 7;
- p->iJD += (n - Z)*86400000;
- clearYMD_HMS_TZ(p);
- rc = 0;
- }
- break;
- }
- case 's': {
- /*
- ** start of TTTTT
- **
- ** Move the date backwards to the beginning of the current day,
- ** or month or year.
- */
- if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break;
- if( !p->validJD && !p->validYMD && !p->validHMS ) break;
- z += 9;
- computeYMD(p);
- p->validHMS = 1;
- p->h = p->m = 0;
- p->s = 0.0;
- p->rawS = 0;
- p->validTZ = 0;
- p->validJD = 0;
- if( sqlite3_stricmp(z,"month")==0 ){
- p->D = 1;
- rc = 0;
- }else if( sqlite3_stricmp(z,"year")==0 ){
- p->M = 1;
- p->D = 1;
- rc = 0;
- }else if( sqlite3_stricmp(z,"day")==0 ){
- rc = 0;
- }
- break;
- }
- case '+':
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': {
- double rRounder;
- int i;
- for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
- if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
- rc = 1;
- break;
- }
- if( z[n]==':' ){
- /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
- ** specified number of hours, minutes, seconds, and fractional seconds
- ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
- ** omitted.
- */
- const char *z2 = z;
- DateTime tx;
- sqlite3_int64 day;
- if( !sqlite3Isdigit(*z2) ) z2++;
- memset(&tx, 0, sizeof(tx));
- if( parseHhMmSs(z2, &tx) ) break;
- computeJD(&tx);
- tx.iJD -= 43200000;
- day = tx.iJD/86400000;
- tx.iJD -= day*86400000;
- if( z[0]=='-' ) tx.iJD = -tx.iJD;
- computeJD(p);
- clearYMD_HMS_TZ(p);
- p->iJD += tx.iJD;
- rc = 0;
- break;
- }
-
- /* If control reaches this point, it means the transformation is
- ** one of the forms like "+NNN days". */
- z += n;
- while( sqlite3Isspace(*z) ) z++;
- n = sqlite3Strlen30(z);
- if( n>10 || n<3 ) break;
- if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--;
- computeJD(p);
- rc = 1;
- rRounder = r<0 ? -0.5 : +0.5;
- for(i=0; i<ArraySize(aXformType); i++){
- if( aXformType[i].nName==n
- && sqlite3_strnicmp(aXformType[i].zName, z, n)==0
- && r>-aXformType[i].rLimit && r<aXformType[i].rLimit
- ){
- switch( aXformType[i].eType ){
- case 1: { /* Special processing to add months */
- int x;
- computeYMD_HMS(p);
- p->M += (int)r;
- x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
- p->Y += x;
- p->M -= x*12;
- p->validJD = 0;
- r -= (int)r;
- break;
- }
- case 2: { /* Special processing to add years */
- int y = (int)r;
- computeYMD_HMS(p);
- p->Y += y;
- p->validJD = 0;
- r -= (int)r;
- break;
- }
- }
- computeJD(p);
- p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder);
- rc = 0;
- break;
- }
- }
- clearYMD_HMS_TZ(p);
- break;
- }
- default: {
- break;
- }
- }
- return rc;
-}
-
-/*
-** Process time function arguments. argv[0] is a date-time stamp.
-** argv[1] and following are modifiers. Parse them all and write
-** the resulting time into the DateTime structure p. Return 0
-** on success and 1 if there are any errors.
-**
-** If there are zero parameters (if even argv[0] is undefined)
-** then assume a default value of "now" for argv[0].
-*/
-static int isDate(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv,
- DateTime *p
-){
- int i, n;
- const unsigned char *z;
- int eType;
- memset(p, 0, sizeof(*p));
- if( argc==0 ){
- return setDateTimeToCurrent(context, p);
- }
- if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
- || eType==SQLITE_INTEGER ){
- setRawDateNumber(p, sqlite3_value_double(argv[0]));
- }else{
- z = sqlite3_value_text(argv[0]);
- if( !z || parseDateOrTime(context, (char*)z, p) ){
- return 1;
- }
- }
- for(i=1; i<argc; i++){
- z = sqlite3_value_text(argv[i]);
- n = sqlite3_value_bytes(argv[i]);
- if( z==0 || parseModifier(context, (char*)z, n, p) ) return 1;
- }
- computeJD(p);
- if( p->isError || !validJulianDay(p->iJD) ) return 1;
- return 0;
-}
-
-
-/*
-** The following routines implement the various date and time functions
-** of SQLite.
-*/
-
-/*
-** julianday( TIMESTRING, MOD, MOD, ...)
-**
-** Return the julian day number of the date specified in the arguments
-*/
-static void juliandayFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- DateTime x;
- if( isDate(context, argc, argv, &x)==0 ){
- computeJD(&x);
- sqlite3_result_double(context, x.iJD/86400000.0);
- }
-}
-
-/*
-** datetime( TIMESTRING, MOD, MOD, ...)
-**
-** Return YYYY-MM-DD HH:MM:SS
-*/
-static void datetimeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- DateTime x;
- if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
- computeYMD_HMS(&x);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
- x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- }
-}
-
-/*
-** time( TIMESTRING, MOD, MOD, ...)
-**
-** Return HH:MM:SS
-*/
-static void timeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- DateTime x;
- if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
- computeHMS(&x);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- }
-}
-
-/*
-** date( TIMESTRING, MOD, MOD, ...)
-**
-** Return YYYY-MM-DD
-*/
-static void dateFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- DateTime x;
- if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
- computeYMD(&x);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- }
-}
-
-/*
-** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
-**
-** Return a string described by FORMAT. Conversions as follows:
-**
-** %d day of month
-** %f ** fractional seconds SS.SSS
-** %H hour 00-24
-** %j day of year 000-366
-** %J ** julian day number
-** %m month 01-12
-** %M minute 00-59
-** %s seconds since 1970-01-01
-** %S seconds 00-59
-** %w day of week 0-6 sunday==0
-** %W week of year 00-53
-** %Y year 0000-9999
-** %% %
-*/
-static void strftimeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- DateTime x;
- u64 n;
- size_t i,j;
- char *z;
- sqlite3 *db;
- const char *zFmt;
- char zBuf[100];
- if( argc==0 ) return;
- zFmt = (const char*)sqlite3_value_text(argv[0]);
- if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
- db = sqlite3_context_db_handle(context);
- for(i=0, n=1; zFmt[i]; i++, n++){
- if( zFmt[i]=='%' ){
- switch( zFmt[i+1] ){
- case 'd':
- case 'H':
- case 'm':
- case 'M':
- case 'S':
- case 'W':
- n++;
- /* fall thru */
- case 'w':
- case '%':
- break;
- case 'f':
- n += 8;
- break;
- case 'j':
- n += 3;
- break;
- case 'Y':
- n += 8;
- break;
- case 's':
- case 'J':
- n += 50;
- break;
- default:
- return; /* ERROR. return a NULL */
- }
- i++;
- }
- }
- testcase( n==sizeof(zBuf)-1 );
- testcase( n==sizeof(zBuf) );
- testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
- testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
- if( n<sizeof(zBuf) ){
- z = zBuf;
- }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
- sqlite3_result_error_toobig(context);
- return;
- }else{
- z = sqlite3DbMallocRawNN(db, (int)n);
- if( z==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- }
- computeJD(&x);
- computeYMD_HMS(&x);
- for(i=j=0; zFmt[i]; i++){
- if( zFmt[i]!='%' ){
- z[j++] = zFmt[i];
- }else{
- i++;
- switch( zFmt[i] ){
- case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
- case 'f': {
- double s = x.s;
- if( s>59.999 ) s = 59.999;
- sqlite3_snprintf(7, &z[j],"%06.3f", s);
- j += sqlite3Strlen30(&z[j]);
- break;
- }
- case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
- case 'W': /* Fall thru */
- case 'j': {
- int nDay; /* Number of days since 1st day of year */
- DateTime y = x;
- y.validJD = 0;
- y.M = 1;
- y.D = 1;
- computeJD(&y);
- nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
- if( zFmt[i]=='W' ){
- int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
- wd = (int)(((x.iJD+43200000)/86400000)%7);
- sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
- j += 2;
- }else{
- sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
- j += 3;
- }
- break;
- }
- case 'J': {
- sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
- j+=sqlite3Strlen30(&z[j]);
- break;
- }
- case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
- case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
- case 's': {
- sqlite3_snprintf(30,&z[j],"%lld",
- (i64)(x.iJD/1000 - 21086676*(i64)10000));
- j += sqlite3Strlen30(&z[j]);
- break;
- }
- case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
- case 'w': {
- z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
- break;
- }
- case 'Y': {
- sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
- break;
- }
- default: z[j++] = '%'; break;
- }
- }
- }
- z[j] = 0;
- sqlite3_result_text(context, z, -1,
- z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
-}
-
-/*
-** current_time()
-**
-** This function returns the same value as time('now').
-*/
-static void ctimeFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- timeFunc(context, 0, 0);
-}
-
-/*
-** current_date()
-**
-** This function returns the same value as date('now').
-*/
-static void cdateFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- dateFunc(context, 0, 0);
-}
-
-/*
-** current_timestamp()
-**
-** This function returns the same value as datetime('now').
-*/
-static void ctimestampFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- datetimeFunc(context, 0, 0);
-}
-#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
-
-#ifdef SQLITE_OMIT_DATETIME_FUNCS
-/*
-** If the library is compiled to omit the full-scale date and time
-** handling (to get a smaller binary), the following minimal version
-** of the functions current_time(), current_date() and current_timestamp()
-** are included instead. This is to support column declarations that
-** include "DEFAULT CURRENT_TIME" etc.
-**
-** This function uses the C-library functions time(), gmtime()
-** and strftime(). The format string to pass to strftime() is supplied
-** as the user-data for the function.
-*/
-static void currentTimeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- time_t t;
- char *zFormat = (char *)sqlite3_user_data(context);
- sqlite3_int64 iT;
- struct tm *pTm;
- struct tm sNow;
- char zBuf[20];
-
- UNUSED_PARAMETER(argc);
- UNUSED_PARAMETER(argv);
-
- iT = sqlite3StmtCurrentTime(context);
- if( iT<=0 ) return;
- t = iT/1000 - 10000*(sqlite3_int64)21086676;
-#if HAVE_GMTIME_R
- pTm = gmtime_r(&t, &sNow);
-#else
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- pTm = gmtime(&t);
- if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-#endif
- if( pTm ){
- strftime(zBuf, 20, zFormat, &sNow);
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- }
-}
-#endif
-
-/*
-** This function registered all of the above C functions as SQL
-** functions. This should be the only routine in this file with
-** external linkage.
-*/
-void sqlite3RegisterDateTimeFunctions(void){
- static FuncDef aDateTimeFuncs[] = {
-#ifndef SQLITE_OMIT_DATETIME_FUNCS
- PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
- PURE_DATE(date, -1, 0, 0, dateFunc ),
- PURE_DATE(time, -1, 0, 0, timeFunc ),
- PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
- PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
- DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
- DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
- DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
-#else
- STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
- STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
- STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
-#endif
- };
- sqlite3InsertBuiltinFuncs(aDateTimeFuncs, ArraySize(aDateTimeFuncs));
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/dbpage.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/dbpage.c
deleted file mode 100644
index c38de3b39fc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/dbpage.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-** 2017-10-11
-**
-** 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 contains an implementation of the "sqlite_dbpage" virtual table.
-**
-** The sqlite_dbpage virtual table is used to read or write whole raw
-** pages of the database file. The pager interface is used so that
-** uncommitted changes and changes recorded in the WAL file are correctly
-** retrieved.
-**
-** Usage example:
-**
-** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123;
-**
-** This is an eponymous virtual table so it does not need to be created before
-** use. The optional argument to the sqlite_dbpage() table name is the
-** schema for the database file that is to be read. The default schema is
-** "main".
-**
-** The data field of sqlite_dbpage table can be updated. The new
-** value must be a BLOB which is the correct page size, otherwise the
-** update fails. Rows may not be deleted or inserted.
-*/
-
-#include "sqliteInt.h" /* Requires access to internal data structures */
-#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
- && !defined(SQLITE_OMIT_VIRTUALTABLE)
-
-typedef struct DbpageTable DbpageTable;
-typedef struct DbpageCursor DbpageCursor;
-
-struct DbpageCursor {
- sqlite3_vtab_cursor base; /* Base class. Must be first */
- int pgno; /* Current page number */
- int mxPgno; /* Last page to visit on this scan */
- Pager *pPager; /* Pager being read/written */
- DbPage *pPage1; /* Page 1 of the database */
- int iDb; /* Index of database to analyze */
- int szPage; /* Size of each page in bytes */
-};
-
-struct DbpageTable {
- sqlite3_vtab base; /* Base class. Must be first */
- sqlite3 *db; /* The database */
-};
-
-/* Columns */
-#define DBPAGE_COLUMN_PGNO 0
-#define DBPAGE_COLUMN_DATA 1
-#define DBPAGE_COLUMN_SCHEMA 2
-
-
-
-/*
-** Connect to or create a dbpagevfs virtual table.
-*/
-static int dbpageConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- DbpageTable *pTab = 0;
- int rc = SQLITE_OK;
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
- if( rc==SQLITE_OK ){
- pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable));
- if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
- }
-
- assert( rc==SQLITE_OK || pTab==0 );
- if( rc==SQLITE_OK ){
- memset(pTab, 0, sizeof(DbpageTable));
- pTab->db = db;
- }
-
- *ppVtab = (sqlite3_vtab*)pTab;
- return rc;
-}
-
-/*
-** Disconnect from or destroy a dbpagevfs virtual table.
-*/
-static int dbpageDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** idxNum:
-**
-** 0 schema=main, full table scan
-** 1 schema=main, pgno=?1
-** 2 schema=?1, full table scan
-** 3 schema=?1, pgno=?2
-*/
-static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int i;
- int iPlan = 0;
-
- /* If there is a schema= constraint, it must be honored. Report a
- ** ridiculously large estimated cost if the schema= constraint is
- ** unavailable
- */
- for(i=0; i<pIdxInfo->nConstraint; i++){
- struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
- if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue;
- if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- if( !p->usable ){
- /* No solution. Use the default SQLITE_BIG_DBL cost */
- pIdxInfo->estimatedRows = 0x7fffffff;
- return SQLITE_OK;
- }
- iPlan = 2;
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- break;
- }
-
- /* If we reach this point, it means that either there is no schema=
- ** constraint (in which case we use the "main" schema) or else the
- ** schema constraint was accepted. Lower the estimated cost accordingly
- */
- pIdxInfo->estimatedCost = 1.0e6;
-
- /* Check for constraints against pgno */
- for(i=0; i<pIdxInfo->nConstraint; i++){
- struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
- if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
- pIdxInfo->estimatedRows = 1;
- pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
- pIdxInfo->estimatedCost = 1.0;
- pIdxInfo->aConstraintUsage[i].argvIndex = iPlan ? 2 : 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- iPlan |= 1;
- break;
- }
- }
- pIdxInfo->idxNum = iPlan;
-
- if( pIdxInfo->nOrderBy>=1
- && pIdxInfo->aOrderBy[0].iColumn<=0
- && pIdxInfo->aOrderBy[0].desc==0
- ){
- pIdxInfo->orderByConsumed = 1;
- }
- return SQLITE_OK;
-}
-
-/*
-** Open a new dbpagevfs cursor.
-*/
-static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- DbpageCursor *pCsr;
-
- pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor));
- if( pCsr==0 ){
- return SQLITE_NOMEM_BKPT;
- }else{
- memset(pCsr, 0, sizeof(DbpageCursor));
- pCsr->base.pVtab = pVTab;
- pCsr->pgno = -1;
- }
-
- *ppCursor = (sqlite3_vtab_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** Close a dbpagevfs cursor.
-*/
-static int dbpageClose(sqlite3_vtab_cursor *pCursor){
- DbpageCursor *pCsr = (DbpageCursor *)pCursor;
- if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Move a dbpagevfs cursor to the next entry in the file.
-*/
-static int dbpageNext(sqlite3_vtab_cursor *pCursor){
- int rc = SQLITE_OK;
- DbpageCursor *pCsr = (DbpageCursor *)pCursor;
- pCsr->pgno++;
- return rc;
-}
-
-static int dbpageEof(sqlite3_vtab_cursor *pCursor){
- DbpageCursor *pCsr = (DbpageCursor *)pCursor;
- return pCsr->pgno > pCsr->mxPgno;
-}
-
-/*
-** idxNum:
-**
-** 0 schema=main, full table scan
-** 1 schema=main, pgno=?1
-** 2 schema=?1, full table scan
-** 3 schema=?1, pgno=?2
-**
-** idxStr is not used
-*/
-static int dbpageFilter(
- sqlite3_vtab_cursor *pCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- DbpageCursor *pCsr = (DbpageCursor *)pCursor;
- DbpageTable *pTab = (DbpageTable *)pCursor->pVtab;
- int rc;
- sqlite3 *db = pTab->db;
- Btree *pBt;
-
- /* Default setting is no rows of result */
- pCsr->pgno = 1;
- pCsr->mxPgno = 0;
-
- if( idxNum & 2 ){
- const char *zSchema;
- assert( argc>=1 );
- zSchema = (const char*)sqlite3_value_text(argv[0]);
- pCsr->iDb = sqlite3FindDbName(db, zSchema);
- if( pCsr->iDb<0 ) return SQLITE_OK;
- }else{
- pCsr->iDb = 0;
- }
- pBt = db->aDb[pCsr->iDb].pBt;
- if( pBt==0 ) return SQLITE_OK;
- pCsr->pPager = sqlite3BtreePager(pBt);
- pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
- pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
- if( idxNum & 1 ){
- assert( argc>(idxNum>>1) );
- pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
- if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
- pCsr->pgno = 1;
- pCsr->mxPgno = 0;
- }else{
- pCsr->mxPgno = pCsr->pgno;
- }
- }else{
- assert( pCsr->pgno==1 );
- }
- if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
- rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0);
- return rc;
-}
-
-static int dbpageColumn(
- sqlite3_vtab_cursor *pCursor,
- sqlite3_context *ctx,
- int i
-){
- DbpageCursor *pCsr = (DbpageCursor *)pCursor;
- int rc = SQLITE_OK;
- switch( i ){
- case 0: { /* pgno */
- sqlite3_result_int(ctx, pCsr->pgno);
- break;
- }
- case 1: { /* data */
- DbPage *pDbPage = 0;
- rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
- if( rc==SQLITE_OK ){
- sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
- SQLITE_TRANSIENT);
- }
- sqlite3PagerUnref(pDbPage);
- break;
- }
- default: { /* schema */
- sqlite3 *db = sqlite3_context_db_handle(ctx);
- sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- DbpageCursor *pCsr = (DbpageCursor *)pCursor;
- *pRowid = pCsr->pgno;
- return SQLITE_OK;
-}
-
-static int dbpageUpdate(
- sqlite3_vtab *pVtab,
- int argc,
- sqlite3_value **argv,
- sqlite_int64 *pRowid
-){
- DbpageTable *pTab = (DbpageTable *)pVtab;
- Pgno pgno;
- DbPage *pDbPage = 0;
- int rc = SQLITE_OK;
- char *zErr = 0;
- const char *zSchema;
- int iDb;
- Btree *pBt;
- Pager *pPager;
- int szPage;
-
- if( argc==1 ){
- zErr = "cannot delete";
- goto update_fail;
- }
- pgno = sqlite3_value_int(argv[0]);
- if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
- zErr = "cannot insert";
- goto update_fail;
- }
- zSchema = (const char*)sqlite3_value_text(argv[4]);
- iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1;
- if( iDb<0 ){
- zErr = "no such schema";
- goto update_fail;
- }
- pBt = pTab->db->aDb[iDb].pBt;
- if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){
- zErr = "bad page number";
- goto update_fail;
- }
- szPage = sqlite3BtreeGetPageSize(pBt);
- if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
- || sqlite3_value_bytes(argv[3])!=szPage
- ){
- zErr = "bad page value";
- goto update_fail;
- }
- pPager = sqlite3BtreePager(pBt);
- rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pDbPage);
- if( rc==SQLITE_OK ){
- memcpy(sqlite3PagerGetData(pDbPage),
- sqlite3_value_blob(argv[3]),
- szPage);
- }
- }
- sqlite3PagerUnref(pDbPage);
- return rc;
-
-update_fail:
- sqlite3_free(pVtab->zErrMsg);
- pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
- return SQLITE_ERROR;
-}
-
-/* Since we do not know in advance which database files will be
-** written by the sqlite_dbpage virtual table, start a write transaction
-** on them all.
-*/
-static int dbpageBegin(sqlite3_vtab *pVtab){
- DbpageTable *pTab = (DbpageTable *)pVtab;
- sqlite3 *db = pTab->db;
- int i;
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ) sqlite3BtreeBeginTrans(pBt, 1);
- }
- return SQLITE_OK;
-}
-
-
-/*
-** Invoke this routine to register the "dbpage" virtual table module
-*/
-int sqlite3DbpageRegister(sqlite3 *db){
- static sqlite3_module dbpage_module = {
- 0, /* iVersion */
- dbpageConnect, /* xCreate */
- dbpageConnect, /* xConnect */
- dbpageBestIndex, /* xBestIndex */
- dbpageDisconnect, /* xDisconnect */
- dbpageDisconnect, /* xDestroy */
- dbpageOpen, /* xOpen - open a cursor */
- dbpageClose, /* xClose - close a cursor */
- dbpageFilter, /* xFilter - configure scan constraints */
- dbpageNext, /* xNext - advance a cursor */
- dbpageEof, /* xEof - check for end of scan */
- dbpageColumn, /* xColumn - read data */
- dbpageRowid, /* xRowid - read data */
- dbpageUpdate, /* xUpdate */
- dbpageBegin, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
- };
- return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0);
-}
-#elif defined(SQLITE_ENABLE_DBPAGE_VTAB)
-int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; }
-#endif /* SQLITE_ENABLE_DBSTAT_VTAB */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/dbstat.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/dbstat.c
deleted file mode 100644
index 0f1fd0a70c9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/dbstat.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
-** 2010 July 12
-**
-** 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 contains an implementation of the "dbstat" virtual table.
-**
-** The dbstat virtual table is used to extract low-level formatting
-** information from an SQLite database in order to implement the
-** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script
-** for an example implementation.
-**
-** Additional information is available on the "dbstat.html" page of the
-** official SQLite documentation.
-*/
-
-#include "sqliteInt.h" /* Requires access to internal data structures */
-#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \
- && !defined(SQLITE_OMIT_VIRTUALTABLE)
-
-/*
-** Page paths:
-**
-** The value of the 'path' column describes the path taken from the
-** root-node of the b-tree structure to each page. The value of the
-** root-node path is '/'.
-**
-** The value of the path for the left-most child page of the root of
-** a b-tree is '/000/'. (Btrees store content ordered from left to right
-** so the pages to the left have smaller keys than the pages to the right.)
-** The next to left-most child of the root page is
-** '/001', and so on, each sibling page identified by a 3-digit hex
-** value. The children of the 451st left-most sibling have paths such
-** as '/1c2/000/, '/1c2/001/' etc.
-**
-** Overflow pages are specified by appending a '+' character and a
-** six-digit hexadecimal value to the path to the cell they are linked
-** from. For example, the three overflow pages in a chain linked from
-** the left-most cell of the 450th child of the root page are identified
-** by the paths:
-**
-** '/1c2/000+000000' // First page in overflow chain
-** '/1c2/000+000001' // Second page in overflow chain
-** '/1c2/000+000002' // Third page in overflow chain
-**
-** If the paths are sorted using the BINARY collation sequence, then
-** the overflow pages associated with a cell will appear earlier in the
-** sort-order than its child page:
-**
-** '/1c2/000/' // Left-most child of 451st child of root
-*/
-#define VTAB_SCHEMA \
- "CREATE TABLE xx( " \
- " name TEXT, /* Name of table or index */" \
- " path TEXT, /* Path to page from root */" \
- " pageno INTEGER, /* Page number */" \
- " pagetype TEXT, /* 'internal', 'leaf' or 'overflow' */" \
- " ncell INTEGER, /* Cells on page (0 for overflow) */" \
- " payload INTEGER, /* Bytes of payload on this page */" \
- " unused INTEGER, /* Bytes of unused space on this page */" \
- " mx_payload INTEGER, /* Largest payload size of all cells */" \
- " pgoffset INTEGER, /* Offset of page in file */" \
- " pgsize INTEGER, /* Size of the page */" \
- " schema TEXT HIDDEN /* Database schema being analyzed */" \
- ");"
-
-
-typedef struct StatTable StatTable;
-typedef struct StatCursor StatCursor;
-typedef struct StatPage StatPage;
-typedef struct StatCell StatCell;
-
-struct StatCell {
- int nLocal; /* Bytes of local payload */
- u32 iChildPg; /* Child node (or 0 if this is a leaf) */
- int nOvfl; /* Entries in aOvfl[] */
- u32 *aOvfl; /* Array of overflow page numbers */
- int nLastOvfl; /* Bytes of payload on final overflow page */
- int iOvfl; /* Iterates through aOvfl[] */
-};
-
-struct StatPage {
- u32 iPgno;
- DbPage *pPg;
- int iCell;
-
- char *zPath; /* Path to this page */
-
- /* Variables populated by statDecodePage(): */
- u8 flags; /* Copy of flags byte */
- int nCell; /* Number of cells on page */
- int nUnused; /* Number of unused bytes on page */
- StatCell *aCell; /* Array of parsed cells */
- u32 iRightChildPg; /* Right-child page number (or 0) */
- int nMxPayload; /* Largest payload of any cell on this page */
-};
-
-struct StatCursor {
- sqlite3_vtab_cursor base;
- sqlite3_stmt *pStmt; /* Iterates through set of root pages */
- int isEof; /* After pStmt has returned SQLITE_DONE */
- int iDb; /* Schema used for this query */
-
- StatPage aPage[32];
- int iPage; /* Current entry in aPage[] */
-
- /* Values to return. */
- char *zName; /* Value of 'name' column */
- char *zPath; /* Value of 'path' column */
- u32 iPageno; /* Value of 'pageno' column */
- char *zPagetype; /* Value of 'pagetype' column */
- int nCell; /* Value of 'ncell' column */
- int nPayload; /* Value of 'payload' column */
- int nUnused; /* Value of 'unused' column */
- int nMxPayload; /* Value of 'mx_payload' column */
- i64 iOffset; /* Value of 'pgOffset' column */
- int szPage; /* Value of 'pgSize' column */
-};
-
-struct StatTable {
- sqlite3_vtab base;
- sqlite3 *db;
- int iDb; /* Index of database to analyze */
-};
-
-#ifndef get2byte
-# define get2byte(x) ((x)[0]<<8 | (x)[1])
-#endif
-
-/*
-** Connect to or create a statvfs virtual table.
-*/
-static int statConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- StatTable *pTab = 0;
- int rc = SQLITE_OK;
- int iDb;
-
- if( argc>=4 ){
- Token nm;
- sqlite3TokenInit(&nm, (char*)argv[3]);
- iDb = sqlite3FindDb(db, &nm);
- if( iDb<0 ){
- *pzErr = sqlite3_mprintf("no such database: %s", argv[3]);
- return SQLITE_ERROR;
- }
- }else{
- iDb = 0;
- }
- rc = sqlite3_declare_vtab(db, VTAB_SCHEMA);
- if( rc==SQLITE_OK ){
- pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable));
- if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
- }
-
- assert( rc==SQLITE_OK || pTab==0 );
- if( rc==SQLITE_OK ){
- memset(pTab, 0, sizeof(StatTable));
- pTab->db = db;
- pTab->iDb = iDb;
- }
-
- *ppVtab = (sqlite3_vtab*)pTab;
- return rc;
-}
-
-/*
-** Disconnect from or destroy a statvfs virtual table.
-*/
-static int statDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** There is no "best-index". This virtual table always does a linear
-** scan. However, a schema=? constraint should cause this table to
-** operate on a different database schema, so check for it.
-**
-** idxNum is normally 0, but will be 1 if a schema=? constraint exists.
-*/
-static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int i;
-
- pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */
-
- /* Look for a valid schema=? constraint. If found, change the idxNum to
- ** 1 and request the value of that constraint be sent to xFilter. And
- ** lower the cost estimate to encourage the constrained version to be
- ** used.
- */
- for(i=0; i<pIdxInfo->nConstraint; i++){
- if( pIdxInfo->aConstraint[i].usable==0 ) continue;
- if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue;
- pIdxInfo->idxNum = 1;
- pIdxInfo->estimatedCost = 1.0;
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- break;
- }
-
-
- /* Records are always returned in ascending order of (name, path).
- ** If this will satisfy the client, set the orderByConsumed flag so that
- ** SQLite does not do an external sort.
- */
- if( ( pIdxInfo->nOrderBy==1
- && pIdxInfo->aOrderBy[0].iColumn==0
- && pIdxInfo->aOrderBy[0].desc==0
- ) ||
- ( pIdxInfo->nOrderBy==2
- && pIdxInfo->aOrderBy[0].iColumn==0
- && pIdxInfo->aOrderBy[0].desc==0
- && pIdxInfo->aOrderBy[1].iColumn==1
- && pIdxInfo->aOrderBy[1].desc==0
- )
- ){
- pIdxInfo->orderByConsumed = 1;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Open a new statvfs cursor.
-*/
-static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- StatTable *pTab = (StatTable *)pVTab;
- StatCursor *pCsr;
-
- pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor));
- if( pCsr==0 ){
- return SQLITE_NOMEM_BKPT;
- }else{
- memset(pCsr, 0, sizeof(StatCursor));
- pCsr->base.pVtab = pVTab;
- pCsr->iDb = pTab->iDb;
- }
-
- *ppCursor = (sqlite3_vtab_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-static void statClearPage(StatPage *p){
- int i;
- if( p->aCell ){
- for(i=0; i<p->nCell; i++){
- sqlite3_free(p->aCell[i].aOvfl);
- }
- sqlite3_free(p->aCell);
- }
- sqlite3PagerUnref(p->pPg);
- sqlite3_free(p->zPath);
- memset(p, 0, sizeof(StatPage));
-}
-
-static void statResetCsr(StatCursor *pCsr){
- int i;
- sqlite3_reset(pCsr->pStmt);
- for(i=0; i<ArraySize(pCsr->aPage); i++){
- statClearPage(&pCsr->aPage[i]);
- }
- pCsr->iPage = 0;
- sqlite3_free(pCsr->zPath);
- pCsr->zPath = 0;
- pCsr->isEof = 0;
-}
-
-/*
-** Close a statvfs cursor.
-*/
-static int statClose(sqlite3_vtab_cursor *pCursor){
- StatCursor *pCsr = (StatCursor *)pCursor;
- statResetCsr(pCsr);
- sqlite3_finalize(pCsr->pStmt);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-static void getLocalPayload(
- int nUsable, /* Usable bytes per page */
- u8 flags, /* Page flags */
- int nTotal, /* Total record (payload) size */
- int *pnLocal /* OUT: Bytes stored locally */
-){
- int nLocal;
- int nMinLocal;
- int nMaxLocal;
-
- if( flags==0x0D ){ /* Table leaf node */
- nMinLocal = (nUsable - 12) * 32 / 255 - 23;
- nMaxLocal = nUsable - 35;
- }else{ /* Index interior and leaf nodes */
- nMinLocal = (nUsable - 12) * 32 / 255 - 23;
- nMaxLocal = (nUsable - 12) * 64 / 255 - 23;
- }
-
- nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4);
- if( nLocal>nMaxLocal ) nLocal = nMinLocal;
- *pnLocal = nLocal;
-}
-
-static int statDecodePage(Btree *pBt, StatPage *p){
- int nUnused;
- int iOff;
- int nHdr;
- int isLeaf;
- int szPage;
-
- u8 *aData = sqlite3PagerGetData(p->pPg);
- u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];
-
- p->flags = aHdr[0];
- p->nCell = get2byte(&aHdr[3]);
- p->nMxPayload = 0;
-
- isLeaf = (p->flags==0x0A || p->flags==0x0D);
- nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100;
-
- nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell;
- nUnused += (int)aHdr[7];
- iOff = get2byte(&aHdr[1]);
- while( iOff ){
- nUnused += get2byte(&aData[iOff+2]);
- iOff = get2byte(&aData[iOff]);
- }
- p->nUnused = nUnused;
- p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]);
- szPage = sqlite3BtreeGetPageSize(pBt);
-
- if( p->nCell ){
- int i; /* Used to iterate through cells */
- int nUsable; /* Usable bytes per page */
-
- sqlite3BtreeEnter(pBt);
- nUsable = szPage - sqlite3BtreeGetReserveNoMutex(pBt);
- sqlite3BtreeLeave(pBt);
- p->aCell = sqlite3_malloc64((p->nCell+1) * sizeof(StatCell));
- if( p->aCell==0 ) return SQLITE_NOMEM_BKPT;
- memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell));
-
- for(i=0; i<p->nCell; i++){
- StatCell *pCell = &p->aCell[i];
-
- iOff = get2byte(&aData[nHdr+i*2]);
- if( !isLeaf ){
- pCell->iChildPg = sqlite3Get4byte(&aData[iOff]);
- iOff += 4;
- }
- if( p->flags==0x05 ){
- /* A table interior node. nPayload==0. */
- }else{
- u32 nPayload; /* Bytes of payload total (local+overflow) */
- int nLocal; /* Bytes of payload stored locally */
- iOff += getVarint32(&aData[iOff], nPayload);
- if( p->flags==0x0D ){
- u64 dummy;
- iOff += sqlite3GetVarint(&aData[iOff], &dummy);
- }
- if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload;
- getLocalPayload(nUsable, p->flags, nPayload, &nLocal);
- pCell->nLocal = nLocal;
- assert( nLocal>=0 );
- assert( nPayload>=(u32)nLocal );
- assert( nLocal<=(nUsable-35) );
- if( nPayload>(u32)nLocal ){
- int j;
- int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
- pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
- pCell->nOvfl = nOvfl;
- pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
- if( pCell->aOvfl==0 ) return SQLITE_NOMEM_BKPT;
- pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]);
- for(j=1; j<nOvfl; j++){
- int rc;
- u32 iPrev = pCell->aOvfl[j-1];
- DbPage *pPg = 0;
- rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg, 0);
- if( rc!=SQLITE_OK ){
- assert( pPg==0 );
- return rc;
- }
- pCell->aOvfl[j] = sqlite3Get4byte(sqlite3PagerGetData(pPg));
- sqlite3PagerUnref(pPg);
- }
- }
- }
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on
-** the current value of pCsr->iPageno.
-*/
-static void statSizeAndOffset(StatCursor *pCsr){
- StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab;
- Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
- Pager *pPager = sqlite3BtreePager(pBt);
- sqlite3_file *fd;
- sqlite3_int64 x[2];
-
- /* The default page size and offset */
- pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
- pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
-
- /* If connected to a ZIPVFS backend, override the page size and
- ** offset with actual values obtained from ZIPVFS.
- */
- fd = sqlite3PagerFile(pPager);
- x[0] = pCsr->iPageno;
- if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
- pCsr->iOffset = x[0];
- pCsr->szPage = (int)x[1];
- }
-}
-
-/*
-** Move a statvfs cursor to the next entry in the file.
-*/
-static int statNext(sqlite3_vtab_cursor *pCursor){
- int rc;
- int nPayload;
- char *z;
- StatCursor *pCsr = (StatCursor *)pCursor;
- StatTable *pTab = (StatTable *)pCursor->pVtab;
- Btree *pBt = pTab->db->aDb[pCsr->iDb].pBt;
- Pager *pPager = sqlite3BtreePager(pBt);
-
- sqlite3_free(pCsr->zPath);
- pCsr->zPath = 0;
-
-statNextRestart:
- if( pCsr->aPage[0].pPg==0 ){
- rc = sqlite3_step(pCsr->pStmt);
- if( rc==SQLITE_ROW ){
- int nPage;
- u32 iRoot = (u32)sqlite3_column_int64(pCsr->pStmt, 1);
- sqlite3PagerPagecount(pPager, &nPage);
- if( nPage==0 ){
- pCsr->isEof = 1;
- return sqlite3_reset(pCsr->pStmt);
- }
- rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0);
- pCsr->aPage[0].iPgno = iRoot;
- pCsr->aPage[0].iCell = 0;
- pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
- pCsr->iPage = 0;
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
- }else{
- pCsr->isEof = 1;
- return sqlite3_reset(pCsr->pStmt);
- }
- }else{
-
- /* Page p itself has already been visited. */
- StatPage *p = &pCsr->aPage[pCsr->iPage];
-
- while( p->iCell<p->nCell ){
- StatCell *pCell = &p->aCell[p->iCell];
- if( pCell->iOvfl<pCell->nOvfl ){
- int nUsable;
- sqlite3BtreeEnter(pBt);
- nUsable = sqlite3BtreeGetPageSize(pBt) -
- sqlite3BtreeGetReserveNoMutex(pBt);
- sqlite3BtreeLeave(pBt);
- pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
- pCsr->iPageno = pCell->aOvfl[pCell->iOvfl];
- pCsr->zPagetype = "overflow";
- pCsr->nCell = 0;
- pCsr->nMxPayload = 0;
- pCsr->zPath = z = sqlite3_mprintf(
- "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl
- );
- if( pCell->iOvfl<pCell->nOvfl-1 ){
- pCsr->nUnused = 0;
- pCsr->nPayload = nUsable - 4;
- }else{
- pCsr->nPayload = pCell->nLastOvfl;
- pCsr->nUnused = nUsable - 4 - pCsr->nPayload;
- }
- pCell->iOvfl++;
- statSizeAndOffset(pCsr);
- return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
- }
- if( p->iRightChildPg ) break;
- p->iCell++;
- }
-
- if( !p->iRightChildPg || p->iCell>p->nCell ){
- statClearPage(p);
- if( pCsr->iPage==0 ) return statNext(pCursor);
- pCsr->iPage--;
- goto statNextRestart; /* Tail recursion */
- }
- pCsr->iPage++;
- assert( p==&pCsr->aPage[pCsr->iPage-1] );
-
- if( p->iCell==p->nCell ){
- p[1].iPgno = p->iRightChildPg;
- }else{
- p[1].iPgno = p->aCell[p->iCell].iChildPg;
- }
- rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0);
- p[1].iCell = 0;
- p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
- p->iCell++;
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
- }
-
-
- /* Populate the StatCursor fields with the values to be returned
- ** by the xColumn() and xRowid() methods.
- */
- if( rc==SQLITE_OK ){
- int i;
- StatPage *p = &pCsr->aPage[pCsr->iPage];
- pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
- pCsr->iPageno = p->iPgno;
-
- rc = statDecodePage(pBt, p);
- if( rc==SQLITE_OK ){
- statSizeAndOffset(pCsr);
-
- switch( p->flags ){
- case 0x05: /* table internal */
- case 0x02: /* index internal */
- pCsr->zPagetype = "internal";
- break;
- case 0x0D: /* table leaf */
- case 0x0A: /* index leaf */
- pCsr->zPagetype = "leaf";
- break;
- default:
- pCsr->zPagetype = "corrupted";
- break;
- }
- pCsr->nCell = p->nCell;
- pCsr->nUnused = p->nUnused;
- pCsr->nMxPayload = p->nMxPayload;
- pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
- nPayload = 0;
- for(i=0; i<p->nCell; i++){
- nPayload += p->aCell[i].nLocal;
- }
- pCsr->nPayload = nPayload;
- }
- }
-
- return rc;
-}
-
-static int statEof(sqlite3_vtab_cursor *pCursor){
- StatCursor *pCsr = (StatCursor *)pCursor;
- return pCsr->isEof;
-}
-
-static int statFilter(
- sqlite3_vtab_cursor *pCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- StatCursor *pCsr = (StatCursor *)pCursor;
- StatTable *pTab = (StatTable*)(pCursor->pVtab);
- char *zSql;
- int rc = SQLITE_OK;
- char *zMaster;
-
- if( idxNum==1 ){
- const char *zDbase = (const char*)sqlite3_value_text(argv[0]);
- pCsr->iDb = sqlite3FindDbName(pTab->db, zDbase);
- if( pCsr->iDb<0 ){
- sqlite3_free(pCursor->pVtab->zErrMsg);
- pCursor->pVtab->zErrMsg = sqlite3_mprintf("no such schema: %s", zDbase);
- return pCursor->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM_BKPT;
- }
- }else{
- pCsr->iDb = pTab->iDb;
- }
- statResetCsr(pCsr);
- sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- zMaster = pCsr->iDb==1 ? "sqlite_temp_master" : "sqlite_master";
- zSql = sqlite3_mprintf(
- "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
- " UNION ALL "
- "SELECT name, rootpage, type"
- " FROM \"%w\".%s WHERE rootpage!=0"
- " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster);
- if( zSql==0 ){
- return SQLITE_NOMEM_BKPT;
- }else{
- rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
- sqlite3_free(zSql);
- }
-
- if( rc==SQLITE_OK ){
- rc = statNext(pCursor);
- }
- return rc;
-}
-
-static int statColumn(
- sqlite3_vtab_cursor *pCursor,
- sqlite3_context *ctx,
- int i
-){
- StatCursor *pCsr = (StatCursor *)pCursor;
- switch( i ){
- case 0: /* name */
- sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
- break;
- case 1: /* path */
- sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
- break;
- case 2: /* pageno */
- sqlite3_result_int64(ctx, pCsr->iPageno);
- break;
- case 3: /* pagetype */
- sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
- break;
- case 4: /* ncell */
- sqlite3_result_int(ctx, pCsr->nCell);
- break;
- case 5: /* payload */
- sqlite3_result_int(ctx, pCsr->nPayload);
- break;
- case 6: /* unused */
- sqlite3_result_int(ctx, pCsr->nUnused);
- break;
- case 7: /* mx_payload */
- sqlite3_result_int(ctx, pCsr->nMxPayload);
- break;
- case 8: /* pgoffset */
- sqlite3_result_int64(ctx, pCsr->iOffset);
- break;
- case 9: /* pgsize */
- sqlite3_result_int(ctx, pCsr->szPage);
- break;
- default: { /* schema */
- sqlite3 *db = sqlite3_context_db_handle(ctx);
- int iDb = pCsr->iDb;
- sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- StatCursor *pCsr = (StatCursor *)pCursor;
- *pRowid = pCsr->iPageno;
- return SQLITE_OK;
-}
-
-/*
-** Invoke this routine to register the "dbstat" virtual table module
-*/
-int sqlite3DbstatRegister(sqlite3 *db){
- static sqlite3_module dbstat_module = {
- 0, /* iVersion */
- statConnect, /* xCreate */
- statConnect, /* xConnect */
- statBestIndex, /* xBestIndex */
- statDisconnect, /* xDisconnect */
- statDisconnect, /* xDestroy */
- statOpen, /* xOpen - open a cursor */
- statClose, /* xClose - close a cursor */
- statFilter, /* xFilter - configure scan constraints */
- statNext, /* xNext - advance a cursor */
- statEof, /* xEof - check for end of scan */
- statColumn, /* xColumn - read data */
- statRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
- };
- return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
-}
-#elif defined(SQLITE_ENABLE_DBSTAT_VTAB)
-int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; }
-#endif /* SQLITE_ENABLE_DBSTAT_VTAB */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/delete.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/delete.c
deleted file mode 100644
index b682658e513..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/delete.c
+++ /dev/null
@@ -1,950 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains C code routines that are called by the parser
-** in order to generate code for DELETE FROM statements.
-*/
-#include "sqliteInt.h"
-
-/*
-** While a SrcList can in general represent multiple tables and subqueries
-** (as in the FROM clause of a SELECT statement) in this case it contains
-** the name of a single table, as one might find in an INSERT, DELETE,
-** or UPDATE statement. Look up that table in the symbol table and
-** return a pointer. Set an error message and return NULL if the table
-** name is not found or if any other error occurs.
-**
-** The following fields are initialized appropriate in pSrc:
-**
-** pSrc->a[0].pTab Pointer to the Table object
-** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
-**
-*/
-Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
- struct SrcList_item *pItem = pSrc->a;
- Table *pTab;
- assert( pItem && pSrc->nSrc==1 );
- pTab = sqlite3LocateTableItem(pParse, 0, pItem);
- sqlite3DeleteTable(pParse->db, pItem->pTab);
- pItem->pTab = pTab;
- if( pTab ){
- pTab->nTabRef++;
- }
- if( sqlite3IndexedByLookup(pParse, pItem) ){
- pTab = 0;
- }
- return pTab;
-}
-
-/*
-** Check to make sure the given table is writable. If it is not
-** writable, generate an error message and return 1. If it is
-** writable return 0;
-*/
-int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
- /* A table is not writable under the following circumstances:
- **
- ** 1) It is a virtual table and no implementation of the xUpdate method
- ** has been provided, or
- ** 2) It is a system table (i.e. sqlite_master), this call is not
- ** part of a nested parse and writable_schema pragma has not
- ** been specified.
- **
- ** In either case leave an error message in pParse and return non-zero.
- */
- if( ( IsVirtual(pTab)
- && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
- || ( (pTab->tabFlags & TF_Readonly)!=0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
- && pParse->nested==0 )
- ){
- sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
- return 1;
- }
-
-#ifndef SQLITE_OMIT_VIEW
- if( !viewOk && pTab->pSelect ){
- sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
- return 1;
- }
-#endif
- return 0;
-}
-
-
-#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
-/*
-** Evaluate a view and store its result in an ephemeral table. The
-** pWhere argument is an optional WHERE clause that restricts the
-** set of rows in the view that are to be added to the ephemeral table.
-*/
-void sqlite3MaterializeView(
- Parse *pParse, /* Parsing context */
- Table *pView, /* View definition */
- Expr *pWhere, /* Optional WHERE clause to be added */
- ExprList *pOrderBy, /* Optional ORDER BY clause */
- Expr *pLimit, /* Optional LIMIT clause */
- int iCur /* Cursor number for ephemeral table */
-){
- SelectDest dest;
- Select *pSel;
- SrcList *pFrom;
- sqlite3 *db = pParse->db;
- int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
- pWhere = sqlite3ExprDup(db, pWhere, 0);
- pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pFrom ){
- assert( pFrom->nSrc==1 );
- pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
- pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
- assert( pFrom->a[0].pOn==0 );
- assert( pFrom->a[0].pUsing==0 );
- }
- pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
- SF_IncludeHidden, pLimit);
- sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
- sqlite3Select(pParse, pSel, &dest);
- sqlite3SelectDelete(db, pSel);
-}
-#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
-
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-/*
-** Generate an expression tree to implement the WHERE, ORDER BY,
-** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
-**
-** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
-** \__________________________/
-** pLimitWhere (pInClause)
-*/
-Expr *sqlite3LimitWhere(
- Parse *pParse, /* The parser context */
- SrcList *pSrc, /* the FROM clause -- which tables to scan */
- Expr *pWhere, /* The WHERE clause. May be null */
- ExprList *pOrderBy, /* The ORDER BY clause. May be null */
- Expr *pLimit, /* The LIMIT clause. May be null */
- char *zStmtType /* Either DELETE or UPDATE. For err msgs. */
-){
- sqlite3 *db = pParse->db;
- Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */
- Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
- ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */
- SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */
- Select *pSelect = NULL; /* Complete SELECT tree */
- Table *pTab;
-
- /* Check that there isn't an ORDER BY without a LIMIT clause.
- */
- if( pOrderBy && pLimit==0 ) {
- sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
- sqlite3ExprDelete(pParse->db, pWhere);
- sqlite3ExprListDelete(pParse->db, pOrderBy);
- return 0;
- }
-
- /* We only need to generate a select expression if there
- ** is a limit/offset term to enforce.
- */
- if( pLimit == 0 ) {
- return pWhere;
- }
-
- /* Generate a select expression tree to enforce the limit/offset
- ** term for the DELETE or UPDATE statement. For example:
- ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
- ** becomes:
- ** DELETE FROM table_a WHERE rowid IN (
- ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
- ** );
- */
-
- pTab = pSrc->a[0].pTab;
- if( HasRowid(pTab) ){
- pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0);
- pEList = sqlite3ExprListAppend(
- pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0)
- );
- }else{
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- if( pPk->nKeyCol==1 ){
- const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
- pLhs = sqlite3Expr(db, TK_ID, zName);
- pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
- }else{
- int i;
- for(i=0; i<pPk->nKeyCol; i++){
- Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
- pEList = sqlite3ExprListAppend(pParse, pEList, p);
- }
- pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( pLhs ){
- pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
- }
- }
- }
-
- /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
- ** and the SELECT subtree. */
- pSrc->a[0].pTab = 0;
- pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
- pSrc->a[0].pTab = pTab;
- pSrc->a[0].pIBIndex = 0;
-
- /* generate the SELECT expression tree. */
- pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0,
- pOrderBy,0,pLimit
- );
-
- /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
- pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0);
- sqlite3PExprAddSelect(pParse, pInClause, pSelect);
- return pInClause;
-}
-#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
- /* && !defined(SQLITE_OMIT_SUBQUERY) */
-
-/*
-** Generate code for a DELETE FROM statement.
-**
-** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
-** \________/ \________________/
-** pTabList pWhere
-*/
-void sqlite3DeleteFrom(
- Parse *pParse, /* The parser context */
- SrcList *pTabList, /* The table from which we should delete things */
- Expr *pWhere, /* The WHERE clause. May be null */
- ExprList *pOrderBy, /* ORDER BY clause. May be null */
- Expr *pLimit /* LIMIT clause. May be null */
-){
- Vdbe *v; /* The virtual database engine */
- Table *pTab; /* The table from which records will be deleted */
- int i; /* Loop counter */
- WhereInfo *pWInfo; /* Information about the WHERE clause */
- Index *pIdx; /* For looping over indices of the table */
- int iTabCur; /* Cursor number for the table */
- int iDataCur = 0; /* VDBE cursor for the canonical data source */
- int iIdxCur = 0; /* Cursor number of the first index */
- int nIdx; /* Number of indices */
- sqlite3 *db; /* Main database structure */
- AuthContext sContext; /* Authorization context */
- NameContext sNC; /* Name context to resolve expressions in */
- int iDb; /* Database number */
- int memCnt = 0; /* Memory cell used for change counting */
- int rcauth; /* Value returned by authorization callback */
- int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */
- int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
- u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
- Index *pPk; /* The PRIMARY KEY index on the table */
- int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */
- i16 nPk = 1; /* Number of columns in the PRIMARY KEY */
- int iKey; /* Memory cell holding key of row to be deleted */
- i16 nKey; /* Number of memory cells in the row key */
- int iEphCur = 0; /* Ephemeral table holding all primary key values */
- int iRowSet = 0; /* Register for rowset of rows to delete */
- int addrBypass = 0; /* Address of jump over the delete logic */
- int addrLoop = 0; /* Top of the delete loop */
- int addrEphOpen = 0; /* Instruction to open the Ephemeral table */
- int bComplex; /* True if there are triggers or FKs or
- ** subqueries in the WHERE clause */
-
-#ifndef SQLITE_OMIT_TRIGGER
- int isView; /* True if attempting to delete from a view */
- Trigger *pTrigger; /* List of table triggers, if required */
-#endif
-
- memset(&sContext, 0, sizeof(sContext));
- db = pParse->db;
- if( pParse->nErr || db->mallocFailed ){
- goto delete_from_cleanup;
- }
- assert( pTabList->nSrc==1 );
-
-
- /* Locate the table which we want to delete. This table has to be
- ** put in an SrcList structure because some of the subroutines we
- ** will be calling are designed to work with multiple tables and expect
- ** an SrcList* parameter instead of just a Table* parameter.
- */
- pTab = sqlite3SrcListLookup(pParse, pTabList);
- if( pTab==0 ) goto delete_from_cleanup;
-
- /* Figure out if we have any triggers and if the table being
- ** deleted from is a view
- */
-#ifndef SQLITE_OMIT_TRIGGER
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
- isView = pTab->pSelect!=0;
-#else
-# define pTrigger 0
-# define isView 0
-#endif
- bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
-#ifdef SQLITE_OMIT_VIEW
-# undef isView
-# define isView 0
-#endif
-
-#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- if( !isView ){
- pWhere = sqlite3LimitWhere(
- pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE"
- );
- pOrderBy = 0;
- pLimit = 0;
- }
-#endif
-
- /* If pTab is really a view, make sure it has been initialized.
- */
- if( sqlite3ViewGetColumnNames(pParse, pTab) ){
- goto delete_from_cleanup;
- }
-
- if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
- goto delete_from_cleanup;
- }
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDb<db->nDb );
- rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0,
- db->aDb[iDb].zDbSName);
- assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
- if( rcauth==SQLITE_DENY ){
- goto delete_from_cleanup;
- }
- assert(!isView || pTrigger);
-
- /* Assign cursor numbers to the table and all its indices.
- */
- assert( pTabList->nSrc==1 );
- iTabCur = pTabList->a[0].iCursor = pParse->nTab++;
- for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
- pParse->nTab++;
- }
-
- /* Start the view context
- */
- if( isView ){
- sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
- }
-
- /* Begin generating code.
- */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ){
- goto delete_from_cleanup;
- }
- if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
- sqlite3BeginWriteOperation(pParse, bComplex, iDb);
-
- /* If we are trying to delete from a view, realize that view into
- ** an ephemeral table.
- */
-#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
- if( isView ){
- sqlite3MaterializeView(pParse, pTab,
- pWhere, pOrderBy, pLimit, iTabCur
- );
- iDataCur = iIdxCur = iTabCur;
- pOrderBy = 0;
- pLimit = 0;
- }
-#endif
-
- /* Resolve the column names in the WHERE clause.
- */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- sNC.pSrcList = pTabList;
- if( sqlite3ResolveExprNames(&sNC, pWhere) ){
- goto delete_from_cleanup;
- }
-
- /* Initialize the counter of the number of rows deleted, if
- ** we are counting rows.
- */
- if( (db->flags & SQLITE_CountRows)!=0
- && !pParse->nested
- && !pParse->pTriggerTab
- ){
- memCnt = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
- }
-
-#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
- /* Special case: A DELETE without a WHERE clause deletes everything.
- ** It is easier just to erase the whole table. Prior to version 3.6.5,
- ** this optimization caused the row change count (the value returned by
- ** API function sqlite3_count_changes) to be set incorrectly.
- **
- ** The "rcauth==SQLITE_OK" terms is the
- ** IMPLEMENTATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and
- ** the callback returns SQLITE_IGNORE then the DELETE operation proceeds but
- ** the truncate optimization is disabled and all rows are deleted
- ** individually.
- */
- if( rcauth==SQLITE_OK
- && pWhere==0
- && !bComplex
- && !IsVirtual(pTab)
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- && db->xPreUpdateCallback==0
-#endif
- ){
- assert( !isView );
- sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1,
- pTab->zName, P4_STATIC);
- }
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- assert( pIdx->pSchema==pTab->pSchema );
- sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
- }
- }else
-#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
- {
- u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE;
- if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
- wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
- if( HasRowid(pTab) ){
- /* For a rowid table, initialize the RowSet to an empty set */
- pPk = 0;
- nPk = 1;
- iRowSet = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
- }else{
- /* For a WITHOUT ROWID table, create an ephemeral table used to
- ** hold all primary keys for rows to be deleted. */
- pPk = sqlite3PrimaryKeyIndex(pTab);
- assert( pPk!=0 );
- nPk = pPk->nKeyCol;
- iPk = pParse->nMem+1;
- pParse->nMem += nPk;
- iEphCur = pParse->nTab++;
- addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk);
- sqlite3VdbeSetP4KeyInfo(pParse, pPk);
- }
-
- /* Construct a query to find the rowid or primary key for every row
- ** to be deleted, based on the WHERE clause. Set variable eOnePass
- ** to indicate the strategy used to implement this delete:
- **
- ** ONEPASS_OFF: Two-pass approach - use a FIFO for rowids/PK values.
- ** ONEPASS_SINGLE: One-pass approach - at most one row deleted.
- ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted.
- */
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
- if( pWInfo==0 ) goto delete_from_cleanup;
- eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
- assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
- assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
- if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse);
-
- /* Keep track of the number of rows to be deleted */
- if( memCnt ){
- sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
- }
-
- /* Extract the rowid or primary key for the current row */
- if( pPk ){
- for(i=0; i<nPk; i++){
- assert( pPk->aiColumn[i]>=0 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
- pPk->aiColumn[i], iPk+i);
- }
- iKey = iPk;
- }else{
- iKey = pParse->nMem + 1;
- iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
- if( iKey>pParse->nMem ) pParse->nMem = iKey;
- }
-
- if( eOnePass!=ONEPASS_OFF ){
- /* For ONEPASS, no need to store the rowid/primary-key. There is only
- ** one, so just keep it in its register(s) and fall through to the
- ** delete code. */
- nKey = nPk; /* OP_Found will use an unpacked key */
- aToOpen = sqlite3DbMallocRawNN(db, nIdx+2);
- if( aToOpen==0 ){
- sqlite3WhereEnd(pWInfo);
- goto delete_from_cleanup;
- }
- memset(aToOpen, 1, nIdx+1);
- aToOpen[nIdx+1] = 0;
- if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
- if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
- if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
- }else{
- if( pPk ){
- /* Add the PK key for this row to the temporary table */
- iKey = ++pParse->nMem;
- nKey = 0; /* Zero tells OP_Found to use a composite key */
- sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
- sqlite3IndexAffinityStr(pParse->db, pPk), nPk);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk);
- }else{
- /* Add the rowid of the row to be deleted to the RowSet */
- nKey = 1; /* OP_DeferredSeek always uses a single rowid */
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
- }
- }
-
- /* If this DELETE cannot use the ONEPASS strategy, this is the
- ** end of the WHERE loop */
- if( eOnePass!=ONEPASS_OFF ){
- addrBypass = sqlite3VdbeMakeLabel(v);
- }else{
- sqlite3WhereEnd(pWInfo);
- }
-
- /* Unless this is a view, open cursors for the table we are
- ** deleting from and all its indices. If this is a view, then the
- ** only effect this statement has is to fire the INSTEAD OF
- ** triggers.
- */
- if( !isView ){
- int iAddrOnce = 0;
- if( eOnePass==ONEPASS_MULTI ){
- iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- }
- testcase( IsVirtual(pTab) );
- sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE,
- iTabCur, aToOpen, &iDataCur, &iIdxCur);
- assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
- assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
- if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
- }
-
- /* Set up a loop over the rowids/primary-keys that were found in the
- ** where-clause loop above.
- */
- if( eOnePass!=ONEPASS_OFF ){
- assert( nKey==nPk ); /* OP_Found will use an unpacked key */
- if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
- assert( pPk!=0 || pTab->pSelect!=0 );
- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
- VdbeCoverage(v);
- }
- }else if( pPk ){
- addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
- if( IsVirtual(pTab) ){
- sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey);
- }else{
- sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey);
- }
- assert( nKey==0 ); /* OP_Found will use a composite key */
- }else{
- addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
- VdbeCoverage(v);
- assert( nKey==1 );
- }
-
- /* Delete the row */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab) ){
- const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
- sqlite3VtabMakeWritable(pParse, pTab);
- assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
- sqlite3MayAbort(pParse);
- if( eOnePass==ONEPASS_SINGLE ){
- sqlite3VdbeAddOp1(v, OP_Close, iTabCur);
- if( sqlite3IsToplevel(pParse) ){
- pParse->isMultiWrite = 0;
- }
- }
- sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
- sqlite3VdbeChangeP5(v, OE_Abort);
- }else
-#endif
- {
- int count = (pParse->nested==0); /* True to count changes */
- sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]);
- }
-
- /* End of the loop over all rowids/primary-keys. */
- if( eOnePass!=ONEPASS_OFF ){
- sqlite3VdbeResolveLabel(v, addrBypass);
- sqlite3WhereEnd(pWInfo);
- }else if( pPk ){
- sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addrLoop);
- }else{
- sqlite3VdbeGoto(v, addrLoop);
- sqlite3VdbeJumpHere(v, addrLoop);
- }
- } /* End non-truncate path */
-
- /* Update the sqlite_sequence table by storing the content of the
- ** maximum rowid counter values recorded while inserting into
- ** autoincrement tables.
- */
- if( pParse->nested==0 && pParse->pTriggerTab==0 ){
- sqlite3AutoincrementEnd(pParse);
- }
-
- /* Return the number of rows that were deleted. If this routine is
- ** generating code because of a call to sqlite3NestedParse(), do not
- ** invoke the callback function.
- */
- if( memCnt ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
- }
-
-delete_from_cleanup:
- sqlite3AuthContextPop(&sContext);
- sqlite3SrcListDelete(db, pTabList);
- sqlite3ExprDelete(db, pWhere);
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
- sqlite3ExprListDelete(db, pOrderBy);
- sqlite3ExprDelete(db, pLimit);
-#endif
- sqlite3DbFree(db, aToOpen);
- return;
-}
-/* Make sure "isView" and other macros defined above are undefined. Otherwise
-** they may interfere with compilation of other functions in this file
-** (or in another file, if this file becomes part of the amalgamation). */
-#ifdef isView
- #undef isView
-#endif
-#ifdef pTrigger
- #undef pTrigger
-#endif
-
-/*
-** This routine generates VDBE code that causes a single row of a
-** single table to be deleted. Both the original table entry and
-** all indices are removed.
-**
-** Preconditions:
-**
-** 1. iDataCur is an open cursor on the btree that is the canonical data
-** store for the table. (This will be either the table itself,
-** in the case of a rowid table, or the PRIMARY KEY index in the case
-** of a WITHOUT ROWID table.)
-**
-** 2. Read/write cursors for all indices of pTab must be open as
-** cursor number iIdxCur+i for the i-th index.
-**
-** 3. The primary key for the row to be deleted must be stored in a
-** sequence of nPk memory cells starting at iPk. If nPk==0 that means
-** that a search record formed from OP_MakeRecord is contained in the
-** single memory location iPk.
-**
-** eMode:
-** Parameter eMode may be passed either ONEPASS_OFF (0), ONEPASS_SINGLE, or
-** ONEPASS_MULTI. If eMode is not ONEPASS_OFF, then the cursor
-** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF
-** then this function must seek iDataCur to the entry identified by iPk
-** and nPk before reading from it.
-**
-** If eMode is ONEPASS_MULTI, then this call is being made as part
-** of a ONEPASS delete that affects multiple rows. In this case, if
-** iIdxNoSeek is a valid cursor number (>=0) and is not the same as
-** iDataCur, then its position should be preserved following the delete
-** operation. Or, if iIdxNoSeek is not a valid cursor number, the
-** position of iDataCur should be preserved instead.
-**
-** iIdxNoSeek:
-** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur,
-** then it identifies an index cursor (from within array of cursors
-** starting at iIdxCur) that already points to the index entry to be deleted.
-** Except, this optimization is disabled if there are BEFORE triggers since
-** the trigger body might have moved the cursor.
-*/
-void sqlite3GenerateRowDelete(
- Parse *pParse, /* Parsing context */
- Table *pTab, /* Table containing the row to be deleted */
- Trigger *pTrigger, /* List of triggers to (potentially) fire */
- int iDataCur, /* Cursor from which column data is extracted */
- int iIdxCur, /* First index cursor */
- int iPk, /* First memory cell containing the PRIMARY KEY */
- i16 nPk, /* Number of PRIMARY KEY memory cells */
- u8 count, /* If non-zero, increment the row change counter */
- u8 onconf, /* Default ON CONFLICT policy for triggers */
- u8 eMode, /* ONEPASS_OFF, _SINGLE, or _MULTI. See above */
- int iIdxNoSeek /* Cursor number of cursor that does not need seeking */
-){
- Vdbe *v = pParse->pVdbe; /* Vdbe */
- int iOld = 0; /* First register in OLD.* array */
- int iLabel; /* Label resolved to end of generated code */
- u8 opSeek; /* Seek opcode */
-
- /* Vdbe is guaranteed to have been allocated by this stage. */
- assert( v );
- VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)",
- iDataCur, iIdxCur, iPk, (int)nPk));
-
- /* Seek cursor iCur to the row to delete. If this row no longer exists
- ** (this can happen if a trigger program has already deleted it), do
- ** not attempt to delete it or fire any DELETE triggers. */
- iLabel = sqlite3VdbeMakeLabel(v);
- opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
- if( eMode==ONEPASS_OFF ){
- sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
- VdbeCoverageIf(v, opSeek==OP_NotExists);
- VdbeCoverageIf(v, opSeek==OP_NotFound);
- }
-
- /* If there are any triggers to fire, allocate a range of registers to
- ** use for the old.* references in the triggers. */
- if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
- u32 mask; /* Mask of OLD.* columns in use */
- int iCol; /* Iterator used while populating OLD.* */
- int addrStart; /* Start of BEFORE trigger programs */
-
- /* TODO: Could use temporary registers here. Also could attempt to
- ** avoid copying the contents of the rowid register. */
- mask = sqlite3TriggerColmask(
- pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
- );
- mask |= sqlite3FkOldmask(pParse, pTab);
- iOld = pParse->nMem+1;
- pParse->nMem += (1 + pTab->nCol);
-
- /* Populate the OLD.* pseudo-table register array. These values will be
- ** used by any BEFORE and AFTER triggers that exist. */
- sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
- for(iCol=0; iCol<pTab->nCol; iCol++){
- testcase( mask!=0xffffffff && iCol==31 );
- testcase( mask!=0xffffffff && iCol==32 );
- if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
- }
- }
-
- /* Invoke BEFORE DELETE trigger programs. */
- addrStart = sqlite3VdbeCurrentAddr(v);
- sqlite3CodeRowTrigger(pParse, pTrigger,
- TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
- );
-
- /* If any BEFORE triggers were coded, then seek the cursor to the
- ** row to be deleted again. It may be that the BEFORE triggers moved
- ** the cursor or already deleted the row that the cursor was
- ** pointing to.
- **
- ** Also disable the iIdxNoSeek optimization since the BEFORE trigger
- ** may have moved that cursor.
- */
- if( addrStart<sqlite3VdbeCurrentAddr(v) ){
- sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
- VdbeCoverageIf(v, opSeek==OP_NotExists);
- VdbeCoverageIf(v, opSeek==OP_NotFound);
- testcase( iIdxNoSeek>=0 );
- iIdxNoSeek = -1;
- }
-
- /* Do FK processing. This call checks that any FK constraints that
- ** refer to this table (i.e. constraints attached to other tables)
- ** are not violated by deleting this row. */
- sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0);
- }
-
- /* Delete the index and table entries. Skip this step if pTab is really
- ** a view (in which case the only effect of the DELETE statement is to
- ** fire the INSTEAD OF triggers).
- **
- ** If variable 'count' is non-zero, then this OP_Delete instruction should
- ** invoke the update-hook. The pre-update-hook, on the other hand should
- ** be invoked unless table pTab is a system table. The difference is that
- ** the update-hook is not invoked for rows removed by REPLACE, but the
- ** pre-update-hook is.
- */
- if( pTab->pSelect==0 ){
- u8 p5 = 0;
- sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
- sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
- if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
- sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
- }
- if( eMode!=ONEPASS_OFF ){
- sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE);
- }
- if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){
- sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
- }
- if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION;
- sqlite3VdbeChangeP5(v, p5);
- }
-
- /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
- ** handle rows (possibly in other tables) that refer via a foreign key
- ** to the row just deleted. */
- sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0);
-
- /* Invoke AFTER DELETE trigger programs. */
- sqlite3CodeRowTrigger(pParse, pTrigger,
- TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
- );
-
- /* Jump here if the row had already been deleted before any BEFORE
- ** trigger programs were invoked. Or if a trigger program throws a
- ** RAISE(IGNORE) exception. */
- sqlite3VdbeResolveLabel(v, iLabel);
- VdbeModuleComment((v, "END: GenRowDel()"));
-}
-
-/*
-** This routine generates VDBE code that causes the deletion of all
-** index entries associated with a single row of a single table, pTab
-**
-** Preconditions:
-**
-** 1. A read/write cursor "iDataCur" must be open on the canonical storage
-** btree for the table pTab. (This will be either the table itself
-** for rowid tables or to the primary key index for WITHOUT ROWID
-** tables.)
-**
-** 2. Read/write cursors for all indices of pTab must be open as
-** cursor number iIdxCur+i for the i-th index. (The pTab->pIndex
-** index is the 0-th index.)
-**
-** 3. The "iDataCur" cursor must be already be positioned on the row
-** that is to be deleted.
-*/
-void sqlite3GenerateRowIndexDelete(
- Parse *pParse, /* Parsing and code generating context */
- Table *pTab, /* Table containing the row to be deleted */
- int iDataCur, /* Cursor of table holding data. */
- int iIdxCur, /* First index cursor */
- int *aRegIdx, /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
- int iIdxNoSeek /* Do not delete from this cursor */
-){
- int i; /* Index loop counter */
- int r1 = -1; /* Register holding an index key */
- int iPartIdxLabel; /* Jump destination for skipping partial index entries */
- Index *pIdx; /* Current index */
- Index *pPrior = 0; /* Prior index */
- Vdbe *v; /* The prepared statement under construction */
- Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
-
- v = pParse->pVdbe;
- pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
- for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- assert( iIdxCur+i!=iDataCur || pPk==pIdx );
- if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
- if( pIdx==pPk ) continue;
- if( iIdxCur+i==iIdxNoSeek ) continue;
- VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
- &iPartIdxLabel, pPrior, r1);
- sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
- pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
- sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
- pPrior = pIdx;
- }
-}
-
-/*
-** Generate code that will assemble an index key and stores it in register
-** regOut. The key with be for index pIdx which is an index on pTab.
-** iCur is the index of a cursor open on the pTab table and pointing to
-** the entry that needs indexing. If pTab is a WITHOUT ROWID table, then
-** iCur must be the cursor of the PRIMARY KEY index.
-**
-** Return a register number which is the first in a block of
-** registers that holds the elements of the index key. The
-** block of registers has already been deallocated by the time
-** this routine returns.
-**
-** If *piPartIdxLabel is not NULL, fill it in with a label and jump
-** to that label if pIdx is a partial index that should be skipped.
-** The label should be resolved using sqlite3ResolvePartIdxLabel().
-** A partial index should be skipped if its WHERE clause evaluates
-** to false or null. If pIdx is not a partial index, *piPartIdxLabel
-** will be set to zero which is an empty label that is ignored by
-** sqlite3ResolvePartIdxLabel().
-**
-** The pPrior and regPrior parameters are used to implement a cache to
-** avoid unnecessary register loads. If pPrior is not NULL, then it is
-** a pointer to a different index for which an index key has just been
-** computed into register regPrior. If the current pIdx index is generating
-** its key into the same sequence of registers and if pPrior and pIdx share
-** a column in common, then the register corresponding to that column already
-** holds the correct value and the loading of that register is skipped.
-** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK
-** on a table with multiple indices, and especially with the ROWID or
-** PRIMARY KEY columns of the index.
-*/
-int sqlite3GenerateIndexKey(
- Parse *pParse, /* Parsing context */
- Index *pIdx, /* The index for which to generate a key */
- int iDataCur, /* Cursor number from which to take column data */
- int regOut, /* Put the new key into this register if not 0 */
- int prefixOnly, /* Compute only a unique prefix of the key */
- int *piPartIdxLabel, /* OUT: Jump to this label to skip partial index */
- Index *pPrior, /* Previously generated index key */
- int regPrior /* Register holding previous generated key */
-){
- Vdbe *v = pParse->pVdbe;
- int j;
- int regBase;
- int nCol;
-
- if( piPartIdxLabel ){
- if( pIdx->pPartIdxWhere ){
- *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
- pParse->iSelfTab = iDataCur + 1;
- sqlite3ExprCachePush(pParse);
- sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
- SQLITE_JUMPIFNULL);
- pParse->iSelfTab = 0;
- }else{
- *piPartIdxLabel = 0;
- }
- }
- nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
- regBase = sqlite3GetTempRange(pParse, nCol);
- if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0;
- for(j=0; j<nCol; j++){
- if( pPrior
- && pPrior->aiColumn[j]==pIdx->aiColumn[j]
- && pPrior->aiColumn[j]!=XN_EXPR
- ){
- /* This column was already computed by the previous index */
- continue;
- }
- sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j);
- /* If the column affinity is REAL but the number is an integer, then it
- ** might be stored in the table as an integer (using a compact
- ** representation) then converted to REAL by an OP_RealAffinity opcode.
- ** But we are getting ready to store this value back into an index, where
- ** it should be converted by to INTEGER again. So omit the OP_RealAffinity
- ** opcode if it is present */
- sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
- }
- if( regOut ){
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
- if( pIdx->pTable->pSelect ){
- const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
- sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
- }
- }
- sqlite3ReleaseTempRange(pParse, regBase, nCol);
- return regBase;
-}
-
-/*
-** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label
-** because it was a partial index, then this routine should be called to
-** resolve that label.
-*/
-void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
- if( iLabel ){
- sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel);
- sqlite3ExprCachePop(pParse);
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/expr.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/expr.c
deleted file mode 100644
index 91eb44b8eba..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/expr.c
+++ /dev/null
@@ -1,5519 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains routines used for analyzing expressions and
-** for generating VDBE code that evaluates expressions in SQLite.
-*/
-#include "sqliteInt.h"
-
-/* Forward declarations */
-static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int);
-static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree);
-
-/*
-** Return the affinity character for a single column of a table.
-*/
-char sqlite3TableColumnAffinity(Table *pTab, int iCol){
- assert( iCol<pTab->nCol );
- return iCol>=0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
-}
-
-/*
-** Return the 'affinity' of the expression pExpr if any.
-**
-** If pExpr is a column, a reference to a column via an 'AS' alias,
-** or a sub-select with a column as the return value, then the
-** affinity of that column is returned. Otherwise, 0x00 is returned,
-** indicating no affinity for the expression.
-**
-** i.e. the WHERE clause expressions in the following statements all
-** have an affinity:
-**
-** CREATE TABLE t1(a);
-** SELECT * FROM t1 WHERE a;
-** SELECT a AS b FROM t1 WHERE b;
-** SELECT * FROM t1 WHERE (select a from t1);
-*/
-char sqlite3ExprAffinity(Expr *pExpr){
- int op;
- pExpr = sqlite3ExprSkipCollate(pExpr);
- if( pExpr->flags & EP_Generic ) return 0;
- op = pExpr->op;
- if( op==TK_SELECT ){
- assert( pExpr->flags&EP_xIsSelect );
- return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
- }
- if( op==TK_REGISTER ) op = pExpr->op2;
-#ifndef SQLITE_OMIT_CAST
- if( op==TK_CAST ){
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- return sqlite3AffinityType(pExpr->u.zToken, 0);
- }
-#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
- return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
- }
- if( op==TK_SELECT_COLUMN ){
- assert( pExpr->pLeft->flags&EP_xIsSelect );
- return sqlite3ExprAffinity(
- pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
- );
- }
- return pExpr->affinity;
-}
-
-/*
-** Set the collating sequence for expression pExpr to be the collating
-** sequence named by pToken. Return a pointer to a new Expr node that
-** implements the COLLATE operator.
-**
-** If a memory allocation error occurs, that fact is recorded in pParse->db
-** and the pExpr parameter is returned unchanged.
-*/
-Expr *sqlite3ExprAddCollateToken(
- Parse *pParse, /* Parsing context */
- Expr *pExpr, /* Add the "COLLATE" clause to this expression */
- const Token *pCollName, /* Name of collating sequence */
- int dequote /* True to dequote pCollName */
-){
- if( pCollName->n>0 ){
- Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
- if( pNew ){
- pNew->pLeft = pExpr;
- pNew->flags |= EP_Collate|EP_Skip;
- pExpr = pNew;
- }
- }
- return pExpr;
-}
-Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
- Token s;
- assert( zC!=0 );
- sqlite3TokenInit(&s, (char*)zC);
- return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0);
-}
-
-/*
-** Skip over any TK_COLLATE operators and any unlikely()
-** or likelihood() function at the root of an expression.
-*/
-Expr *sqlite3ExprSkipCollate(Expr *pExpr){
- while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
- if( ExprHasProperty(pExpr, EP_Unlikely) ){
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- assert( pExpr->x.pList->nExpr>0 );
- assert( pExpr->op==TK_FUNCTION );
- pExpr = pExpr->x.pList->a[0].pExpr;
- }else{
- assert( pExpr->op==TK_COLLATE );
- pExpr = pExpr->pLeft;
- }
- }
- return pExpr;
-}
-
-/*
-** Return the collation sequence for the expression pExpr. If
-** there is no defined collating sequence, return NULL.
-**
-** See also: sqlite3ExprNNCollSeq()
-**
-** The sqlite3ExprNNCollSeq() works the same exact that it returns the
-** default collation if pExpr has no defined collation.
-**
-** The collating sequence might be determined by a COLLATE operator
-** or by the presence of a column with a defined collating sequence.
-** COLLATE operators take first precedence. Left operands take
-** precedence over right operands.
-*/
-CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
- sqlite3 *db = pParse->db;
- CollSeq *pColl = 0;
- Expr *p = pExpr;
- while( p ){
- int op = p->op;
- if( p->flags & EP_Generic ) break;
- if( op==TK_CAST || op==TK_UPLUS ){
- p = p->pLeft;
- continue;
- }
- if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
- pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
- break;
- }
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN
- || op==TK_REGISTER || op==TK_TRIGGER)
- && p->pTab!=0
- ){
- /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
- ** a TK_COLUMN but was previously evaluated and cached in a register */
- int j = p->iColumn;
- if( j>=0 ){
- const char *zColl = p->pTab->aCol[j].zColl;
- pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
- }
- break;
- }
- if( p->flags & EP_Collate ){
- if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
- p = p->pLeft;
- }else{
- Expr *pNext = p->pRight;
- /* The Expr.x union is never used at the same time as Expr.pRight */
- assert( p->x.pList==0 || p->pRight==0 );
- /* p->flags holds EP_Collate and p->pLeft->flags does not. And
- ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
- ** least one EP_Collate. Thus the following two ALWAYS. */
- if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
- int i;
- for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
- if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
- pNext = p->x.pList->a[i].pExpr;
- break;
- }
- }
- }
- p = pNext;
- }
- }else{
- break;
- }
- }
- if( sqlite3CheckCollSeq(pParse, pColl) ){
- pColl = 0;
- }
- return pColl;
-}
-
-/*
-** Return the collation sequence for the expression pExpr. If
-** there is no defined collating sequence, return a pointer to the
-** defautl collation sequence.
-**
-** See also: sqlite3ExprCollSeq()
-**
-** The sqlite3ExprCollSeq() routine works the same except that it
-** returns NULL if there is no defined collation.
-*/
-CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
- CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
- if( p==0 ) p = pParse->db->pDfltColl;
- assert( p!=0 );
- return p;
-}
-
-/*
-** Return TRUE if the two expressions have equivalent collating sequences.
-*/
-int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
- CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
- CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
- return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
-}
-
-/*
-** pExpr is an operand of a comparison operator. aff2 is the
-** type affinity of the other operand. This routine returns the
-** type affinity that should be used for the comparison operator.
-*/
-char sqlite3CompareAffinity(Expr *pExpr, char aff2){
- char aff1 = sqlite3ExprAffinity(pExpr);
- if( aff1 && aff2 ){
- /* Both sides of the comparison are columns. If one has numeric
- ** affinity, use that. Otherwise use no affinity.
- */
- if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
- return SQLITE_AFF_NUMERIC;
- }else{
- return SQLITE_AFF_BLOB;
- }
- }else if( !aff1 && !aff2 ){
- /* Neither side of the comparison is a column. Compare the
- ** results directly.
- */
- return SQLITE_AFF_BLOB;
- }else{
- /* One side is a column, the other is not. Use the columns affinity. */
- assert( aff1==0 || aff2==0 );
- return (aff1 + aff2);
- }
-}
-
-/*
-** pExpr is a comparison operator. Return the type affinity that should
-** be applied to both operands prior to doing the comparison.
-*/
-static char comparisonAffinity(Expr *pExpr){
- char aff;
- assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
- pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
- pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
- assert( pExpr->pLeft );
- aff = sqlite3ExprAffinity(pExpr->pLeft);
- if( pExpr->pRight ){
- aff = sqlite3CompareAffinity(pExpr->pRight, aff);
- }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
- }else if( aff==0 ){
- aff = SQLITE_AFF_BLOB;
- }
- return aff;
-}
-
-/*
-** pExpr is a comparison expression, eg. '=', '<', IN(...) etc.
-** idx_affinity is the affinity of an indexed column. Return true
-** if the index with affinity idx_affinity may be used to implement
-** the comparison in pExpr.
-*/
-int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
- char aff = comparisonAffinity(pExpr);
- switch( aff ){
- case SQLITE_AFF_BLOB:
- return 1;
- case SQLITE_AFF_TEXT:
- return idx_affinity==SQLITE_AFF_TEXT;
- default:
- return sqlite3IsNumericAffinity(idx_affinity);
- }
-}
-
-/*
-** Return the P5 value that should be used for a binary comparison
-** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
-*/
-static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
- u8 aff = (char)sqlite3ExprAffinity(pExpr2);
- aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
- return aff;
-}
-
-/*
-** Return a pointer to the collation sequence that should be used by
-** a binary comparison operator comparing pLeft and pRight.
-**
-** If the left hand expression has a collating sequence type, then it is
-** used. Otherwise the collation sequence for the right hand expression
-** is used, or the default (BINARY) if neither expression has a collating
-** type.
-**
-** Argument pRight (but not pLeft) may be a null pointer. In this case,
-** it is not considered.
-*/
-CollSeq *sqlite3BinaryCompareCollSeq(
- Parse *pParse,
- Expr *pLeft,
- Expr *pRight
-){
- CollSeq *pColl;
- assert( pLeft );
- if( pLeft->flags & EP_Collate ){
- pColl = sqlite3ExprCollSeq(pParse, pLeft);
- }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
- pColl = sqlite3ExprCollSeq(pParse, pRight);
- }else{
- pColl = sqlite3ExprCollSeq(pParse, pLeft);
- if( !pColl ){
- pColl = sqlite3ExprCollSeq(pParse, pRight);
- }
- }
- return pColl;
-}
-
-/*
-** Generate code for a comparison operator.
-*/
-static int codeCompare(
- Parse *pParse, /* The parsing (and code generating) context */
- Expr *pLeft, /* The left operand */
- Expr *pRight, /* The right operand */
- int opcode, /* The comparison opcode */
- int in1, int in2, /* Register holding operands */
- int dest, /* Jump here if true. */
- int jumpIfNull /* If true, jump if either operand is NULL */
-){
- int p5;
- int addr;
- CollSeq *p4;
-
- p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
- p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
- addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
- (void*)p4, P4_COLLSEQ);
- sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
- return addr;
-}
-
-/*
-** Return true if expression pExpr is a vector, or false otherwise.
-**
-** A vector is defined as any expression that results in two or more
-** columns of result. Every TK_VECTOR node is an vector because the
-** parser will not generate a TK_VECTOR with fewer than two entries.
-** But a TK_SELECT might be either a vector or a scalar. It is only
-** considered a vector if it has two or more result columns.
-*/
-int sqlite3ExprIsVector(Expr *pExpr){
- return sqlite3ExprVectorSize(pExpr)>1;
-}
-
-/*
-** If the expression passed as the only argument is of type TK_VECTOR
-** return the number of expressions in the vector. Or, if the expression
-** is a sub-select, return the number of columns in the sub-select. For
-** any other type of expression, return 1.
-*/
-int sqlite3ExprVectorSize(Expr *pExpr){
- u8 op = pExpr->op;
- if( op==TK_REGISTER ) op = pExpr->op2;
- if( op==TK_VECTOR ){
- return pExpr->x.pList->nExpr;
- }else if( op==TK_SELECT ){
- return pExpr->x.pSelect->pEList->nExpr;
- }else{
- return 1;
- }
-}
-
-/*
-** Return a pointer to a subexpression of pVector that is the i-th
-** column of the vector (numbered starting with 0). The caller must
-** ensure that i is within range.
-**
-** If pVector is really a scalar (and "scalar" here includes subqueries
-** that return a single column!) then return pVector unmodified.
-**
-** pVector retains ownership of the returned subexpression.
-**
-** If the vector is a (SELECT ...) then the expression returned is
-** just the expression for the i-th term of the result set, and may
-** not be ready for evaluation because the table cursor has not yet
-** been positioned.
-*/
-Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
- assert( i<sqlite3ExprVectorSize(pVector) );
- if( sqlite3ExprIsVector(pVector) ){
- assert( pVector->op2==0 || pVector->op==TK_REGISTER );
- if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){
- return pVector->x.pSelect->pEList->a[i].pExpr;
- }else{
- return pVector->x.pList->a[i].pExpr;
- }
- }
- return pVector;
-}
-
-/*
-** Compute and return a new Expr object which when passed to
-** sqlite3ExprCode() will generate all necessary code to compute
-** the iField-th column of the vector expression pVector.
-**
-** It is ok for pVector to be a scalar (as long as iField==0).
-** In that case, this routine works like sqlite3ExprDup().
-**
-** The caller owns the returned Expr object and is responsible for
-** ensuring that the returned value eventually gets freed.
-**
-** The caller retains ownership of pVector. If pVector is a TK_SELECT,
-** then the returned object will reference pVector and so pVector must remain
-** valid for the life of the returned object. If pVector is a TK_VECTOR
-** or a scalar expression, then it can be deleted as soon as this routine
-** returns.
-**
-** A trick to cause a TK_SELECT pVector to be deleted together with
-** the returned Expr object is to attach the pVector to the pRight field
-** of the returned TK_SELECT_COLUMN Expr object.
-*/
-Expr *sqlite3ExprForVectorField(
- Parse *pParse, /* Parsing context */
- Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
- int iField /* Which column of the vector to return */
-){
- Expr *pRet;
- if( pVector->op==TK_SELECT ){
- assert( pVector->flags & EP_xIsSelect );
- /* The TK_SELECT_COLUMN Expr node:
- **
- ** pLeft: pVector containing TK_SELECT. Not deleted.
- ** pRight: not used. But recursively deleted.
- ** iColumn: Index of a column in pVector
- ** iTable: 0 or the number of columns on the LHS of an assignment
- ** pLeft->iTable: First in an array of register holding result, or 0
- ** if the result is not yet computed.
- **
- ** sqlite3ExprDelete() specifically skips the recursive delete of
- ** pLeft on TK_SELECT_COLUMN nodes. But pRight is followed, so pVector
- ** can be attached to pRight to cause this node to take ownership of
- ** pVector. Typically there will be multiple TK_SELECT_COLUMN nodes
- ** with the same pLeft pointer to the pVector, but only one of them
- ** will own the pVector.
- */
- pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0);
- if( pRet ){
- pRet->iColumn = iField;
- pRet->pLeft = pVector;
- }
- assert( pRet==0 || pRet->iTable==0 );
- }else{
- if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
- pRet = sqlite3ExprDup(pParse->db, pVector, 0);
- }
- return pRet;
-}
-
-/*
-** If expression pExpr is of type TK_SELECT, generate code to evaluate
-** it. Return the register in which the result is stored (or, if the
-** sub-select returns more than one column, the first in an array
-** of registers in which the result is stored).
-**
-** If pExpr is not a TK_SELECT expression, return 0.
-*/
-static int exprCodeSubselect(Parse *pParse, Expr *pExpr){
- int reg = 0;
-#ifndef SQLITE_OMIT_SUBQUERY
- if( pExpr->op==TK_SELECT ){
- reg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
- }
-#endif
- return reg;
-}
-
-/*
-** Argument pVector points to a vector expression - either a TK_VECTOR
-** or TK_SELECT that returns more than one column. This function returns
-** the register number of a register that contains the value of
-** element iField of the vector.
-**
-** If pVector is a TK_SELECT expression, then code for it must have
-** already been generated using the exprCodeSubselect() routine. In this
-** case parameter regSelect should be the first in an array of registers
-** containing the results of the sub-select.
-**
-** If pVector is of type TK_VECTOR, then code for the requested field
-** is generated. In this case (*pRegFree) may be set to the number of
-** a temporary register to be freed by the caller before returning.
-**
-** Before returning, output parameter (*ppExpr) is set to point to the
-** Expr object corresponding to element iElem of the vector.
-*/
-static int exprVectorRegister(
- Parse *pParse, /* Parse context */
- Expr *pVector, /* Vector to extract element from */
- int iField, /* Field to extract from pVector */
- int regSelect, /* First in array of registers */
- Expr **ppExpr, /* OUT: Expression element */
- int *pRegFree /* OUT: Temp register to free */
-){
- u8 op = pVector->op;
- assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT );
- if( op==TK_REGISTER ){
- *ppExpr = sqlite3VectorFieldSubexpr(pVector, iField);
- return pVector->iTable+iField;
- }
- if( op==TK_SELECT ){
- *ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr;
- return regSelect+iField;
- }
- *ppExpr = pVector->x.pList->a[iField].pExpr;
- return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
-}
-
-/*
-** Expression pExpr is a comparison between two vector values. Compute
-** the result of the comparison (1, 0, or NULL) and write that
-** result into register dest.
-**
-** The caller must satisfy the following preconditions:
-**
-** if pExpr->op==TK_IS: op==TK_EQ and p5==SQLITE_NULLEQ
-** if pExpr->op==TK_ISNOT: op==TK_NE and p5==SQLITE_NULLEQ
-** otherwise: op==pExpr->op and p5==0
-*/
-static void codeVectorCompare(
- Parse *pParse, /* Code generator context */
- Expr *pExpr, /* The comparison operation */
- int dest, /* Write results into this register */
- u8 op, /* Comparison operator */
- u8 p5 /* SQLITE_NULLEQ or zero */
-){
- Vdbe *v = pParse->pVdbe;
- Expr *pLeft = pExpr->pLeft;
- Expr *pRight = pExpr->pRight;
- int nLeft = sqlite3ExprVectorSize(pLeft);
- int i;
- int regLeft = 0;
- int regRight = 0;
- u8 opx = op;
- int addrDone = sqlite3VdbeMakeLabel(v);
-
- if( nLeft!=sqlite3ExprVectorSize(pRight) ){
- sqlite3ErrorMsg(pParse, "row value misused");
- return;
- }
- assert( pExpr->op==TK_EQ || pExpr->op==TK_NE
- || pExpr->op==TK_IS || pExpr->op==TK_ISNOT
- || pExpr->op==TK_LT || pExpr->op==TK_GT
- || pExpr->op==TK_LE || pExpr->op==TK_GE
- );
- assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ)
- || (pExpr->op==TK_ISNOT && op==TK_NE) );
- assert( p5==0 || pExpr->op!=op );
- assert( p5==SQLITE_NULLEQ || pExpr->op==op );
-
- p5 |= SQLITE_STOREP2;
- if( opx==TK_LE ) opx = TK_LT;
- if( opx==TK_GE ) opx = TK_GT;
-
- regLeft = exprCodeSubselect(pParse, pLeft);
- regRight = exprCodeSubselect(pParse, pRight);
-
- for(i=0; 1 /*Loop exits by "break"*/; i++){
- int regFree1 = 0, regFree2 = 0;
- Expr *pL, *pR;
- int r1, r2;
- assert( i>=0 && i<nLeft );
- if( i>0 ) sqlite3ExprCachePush(pParse);
- r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
- r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
- codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
- testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
- testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
- testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
- testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
- testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
- testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
- sqlite3ReleaseTempReg(pParse, regFree1);
- sqlite3ReleaseTempReg(pParse, regFree2);
- if( i>0 ) sqlite3ExprCachePop(pParse);
- if( i==nLeft-1 ){
- break;
- }
- if( opx==TK_EQ ){
- sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v);
- p5 |= SQLITE_KEEPNULL;
- }else if( opx==TK_NE ){
- sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v);
- p5 |= SQLITE_KEEPNULL;
- }else{
- assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE );
- sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone);
- VdbeCoverageIf(v, op==TK_LT);
- VdbeCoverageIf(v, op==TK_GT);
- VdbeCoverageIf(v, op==TK_LE);
- VdbeCoverageIf(v, op==TK_GE);
- if( i==nLeft-2 ) opx = op;
- }
- }
- sqlite3VdbeResolveLabel(v, addrDone);
-}
-
-#if SQLITE_MAX_EXPR_DEPTH>0
-/*
-** Check that argument nHeight is less than or equal to the maximum
-** expression depth allowed. If it is not, leave an error message in
-** pParse.
-*/
-int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
- int rc = SQLITE_OK;
- int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
- if( nHeight>mxHeight ){
- sqlite3ErrorMsg(pParse,
- "Expression tree is too large (maximum depth %d)", mxHeight
- );
- rc = SQLITE_ERROR;
- }
- return rc;
-}
-
-/* The following three functions, heightOfExpr(), heightOfExprList()
-** and heightOfSelect(), are used to determine the maximum height
-** of any expression tree referenced by the structure passed as the
-** first argument.
-**
-** If this maximum height is greater than the current value pointed
-** to by pnHeight, the second parameter, then set *pnHeight to that
-** value.
-*/
-static void heightOfExpr(Expr *p, int *pnHeight){
- if( p ){
- if( p->nHeight>*pnHeight ){
- *pnHeight = p->nHeight;
- }
- }
-}
-static void heightOfExprList(ExprList *p, int *pnHeight){
- if( p ){
- int i;
- for(i=0; i<p->nExpr; i++){
- heightOfExpr(p->a[i].pExpr, pnHeight);
- }
- }
-}
-static void heightOfSelect(Select *pSelect, int *pnHeight){
- Select *p;
- for(p=pSelect; p; p=p->pPrior){
- heightOfExpr(p->pWhere, pnHeight);
- heightOfExpr(p->pHaving, pnHeight);
- heightOfExpr(p->pLimit, pnHeight);
- heightOfExprList(p->pEList, pnHeight);
- heightOfExprList(p->pGroupBy, pnHeight);
- heightOfExprList(p->pOrderBy, pnHeight);
- }
-}
-
-/*
-** Set the Expr.nHeight variable in the structure passed as an
-** argument. An expression with no children, Expr.pList or
-** Expr.pSelect member has a height of 1. Any other expression
-** has a height equal to the maximum height of any other
-** referenced Expr plus one.
-**
-** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags,
-** if appropriate.
-*/
-static void exprSetHeight(Expr *p){
- int nHeight = 0;
- heightOfExpr(p->pLeft, &nHeight);
- heightOfExpr(p->pRight, &nHeight);
- if( ExprHasProperty(p, EP_xIsSelect) ){
- heightOfSelect(p->x.pSelect, &nHeight);
- }else if( p->x.pList ){
- heightOfExprList(p->x.pList, &nHeight);
- p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
- }
- p->nHeight = nHeight + 1;
-}
-
-/*
-** Set the Expr.nHeight variable using the exprSetHeight() function. If
-** the height is greater than the maximum allowed expression depth,
-** leave an error in pParse.
-**
-** Also propagate all EP_Propagate flags from the Expr.x.pList into
-** Expr.flags.
-*/
-void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
- if( pParse->nErr ) return;
- exprSetHeight(p);
- sqlite3ExprCheckHeight(pParse, p->nHeight);
-}
-
-/*
-** Return the maximum height of any expression tree referenced
-** by the select statement passed as an argument.
-*/
-int sqlite3SelectExprHeight(Select *p){
- int nHeight = 0;
- heightOfSelect(p, &nHeight);
- return nHeight;
-}
-#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */
-/*
-** Propagate all EP_Propagate flags from the Expr.x.pList into
-** Expr.flags.
-*/
-void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
- if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
- p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
- }
-}
-#define exprSetHeight(y)
-#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
-
-/*
-** This routine is the core allocator for Expr nodes.
-**
-** Construct a new expression node and return a pointer to it. Memory
-** for this node and for the pToken argument is a single allocation
-** obtained from sqlite3DbMalloc(). The calling function
-** is responsible for making sure the node eventually gets freed.
-**
-** If dequote is true, then the token (if it exists) is dequoted.
-** If dequote is false, no dequoting is performed. The deQuote
-** parameter is ignored if pToken is NULL or if the token does not
-** appear to be quoted. If the quotes were of the form "..." (double-quotes)
-** then the EP_DblQuoted flag is set on the expression node.
-**
-** Special case: If op==TK_INTEGER and pToken points to a string that
-** can be translated into a 32-bit integer, then the token is not
-** stored in u.zToken. Instead, the integer values is written
-** into u.iValue and the EP_IntValue flag is set. No extra storage
-** is allocated to hold the integer text and the dequote flag is ignored.
-*/
-Expr *sqlite3ExprAlloc(
- sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */
- int op, /* Expression opcode */
- const Token *pToken, /* Token argument. Might be NULL */
- int dequote /* True to dequote */
-){
- Expr *pNew;
- int nExtra = 0;
- int iValue = 0;
-
- assert( db!=0 );
- if( pToken ){
- if( op!=TK_INTEGER || pToken->z==0
- || sqlite3GetInt32(pToken->z, &iValue)==0 ){
- nExtra = pToken->n+1;
- assert( iValue>=0 );
- }
- }
- pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra);
- if( pNew ){
- memset(pNew, 0, sizeof(Expr));
- pNew->op = (u8)op;
- pNew->iAgg = -1;
- if( pToken ){
- if( nExtra==0 ){
- pNew->flags |= EP_IntValue|EP_Leaf;
- pNew->u.iValue = iValue;
- }else{
- pNew->u.zToken = (char*)&pNew[1];
- assert( pToken->z!=0 || pToken->n==0 );
- if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
- pNew->u.zToken[pToken->n] = 0;
- if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){
- if( pNew->u.zToken[0]=='"' ) pNew->flags |= EP_DblQuoted;
- sqlite3Dequote(pNew->u.zToken);
- }
- }
- }
-#if SQLITE_MAX_EXPR_DEPTH>0
- pNew->nHeight = 1;
-#endif
- }
- return pNew;
-}
-
-/*
-** Allocate a new expression node from a zero-terminated token that has
-** already been dequoted.
-*/
-Expr *sqlite3Expr(
- sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
- int op, /* Expression opcode */
- const char *zToken /* Token argument. Might be NULL */
-){
- Token x;
- x.z = zToken;
- x.n = sqlite3Strlen30(zToken);
- return sqlite3ExprAlloc(db, op, &x, 0);
-}
-
-/*
-** Attach subtrees pLeft and pRight to the Expr node pRoot.
-**
-** If pRoot==NULL that means that a memory allocation error has occurred.
-** In that case, delete the subtrees pLeft and pRight.
-*/
-void sqlite3ExprAttachSubtrees(
- sqlite3 *db,
- Expr *pRoot,
- Expr *pLeft,
- Expr *pRight
-){
- if( pRoot==0 ){
- assert( db->mallocFailed );
- sqlite3ExprDelete(db, pLeft);
- sqlite3ExprDelete(db, pRight);
- }else{
- if( pRight ){
- pRoot->pRight = pRight;
- pRoot->flags |= EP_Propagate & pRight->flags;
- }
- if( pLeft ){
- pRoot->pLeft = pLeft;
- pRoot->flags |= EP_Propagate & pLeft->flags;
- }
- exprSetHeight(pRoot);
- }
-}
-
-/*
-** Allocate an Expr node which joins as many as two subtrees.
-**
-** One or both of the subtrees can be NULL. Return a pointer to the new
-** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed,
-** free the subtrees and return NULL.
-*/
-Expr *sqlite3PExpr(
- Parse *pParse, /* Parsing context */
- int op, /* Expression opcode */
- Expr *pLeft, /* Left operand */
- Expr *pRight /* Right operand */
-){
- Expr *p;
- if( op==TK_AND && pParse->nErr==0 ){
- /* Take advantage of short-circuit false optimization for AND */
- p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
- }else{
- p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr));
- if( p ){
- memset(p, 0, sizeof(Expr));
- p->op = op & TKFLG_MASK;
- p->iAgg = -1;
- }
- sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
- }
- if( p ) {
- sqlite3ExprCheckHeight(pParse, p->nHeight);
- }
- return p;
-}
-
-/*
-** Add pSelect to the Expr.x.pSelect field. Or, if pExpr is NULL (due
-** do a memory allocation failure) then delete the pSelect object.
-*/
-void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
- if( pExpr ){
- pExpr->x.pSelect = pSelect;
- ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery);
- sqlite3ExprSetHeightAndFlags(pParse, pExpr);
- }else{
- assert( pParse->db->mallocFailed );
- sqlite3SelectDelete(pParse->db, pSelect);
- }
-}
-
-
-/*
-** If the expression is always either TRUE or FALSE (respectively),
-** then return 1. If one cannot determine the truth value of the
-** expression at compile-time return 0.
-**
-** This is an optimization. If is OK to return 0 here even if
-** the expression really is always false or false (a false negative).
-** But it is a bug to return 1 if the expression might have different
-** boolean values in different circumstances (a false positive.)
-**
-** Note that if the expression is part of conditional for a
-** LEFT JOIN, then we cannot determine at compile-time whether or not
-** is it true or false, so always return 0.
-*/
-static int exprAlwaysTrue(Expr *p){
- int v = 0;
- if( ExprHasProperty(p, EP_FromJoin) ) return 0;
- if( !sqlite3ExprIsInteger(p, &v) ) return 0;
- return v!=0;
-}
-static int exprAlwaysFalse(Expr *p){
- int v = 0;
- if( ExprHasProperty(p, EP_FromJoin) ) return 0;
- if( !sqlite3ExprIsInteger(p, &v) ) return 0;
- return v==0;
-}
-
-/*
-** Join two expressions using an AND operator. If either expression is
-** NULL, then just return the other expression.
-**
-** If one side or the other of the AND is known to be false, then instead
-** of returning an AND expression, just return a constant expression with
-** a value of false.
-*/
-Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
- if( pLeft==0 ){
- return pRight;
- }else if( pRight==0 ){
- return pLeft;
- }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){
- sqlite3ExprDelete(db, pLeft);
- sqlite3ExprDelete(db, pRight);
- return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
- }else{
- Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
- sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
- return pNew;
- }
-}
-
-/*
-** Construct a new expression node for a function with multiple
-** arguments.
-*/
-Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
- Expr *pNew;
- sqlite3 *db = pParse->db;
- assert( pToken );
- pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
- if( pNew==0 ){
- sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
- return 0;
- }
- pNew->x.pList = pList;
- ExprSetProperty(pNew, EP_HasFunc);
- assert( !ExprHasProperty(pNew, EP_xIsSelect) );
- sqlite3ExprSetHeightAndFlags(pParse, pNew);
- return pNew;
-}
-
-/*
-** Assign a variable number to an expression that encodes a wildcard
-** in the original SQL statement.
-**
-** Wildcards consisting of a single "?" are assigned the next sequential
-** variable number.
-**
-** Wildcards of the form "?nnn" are assigned the number "nnn". We make
-** sure "nnn" is not too big to avoid a denial of service attack when
-** the SQL statement comes from an external source.
-**
-** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
-** as the previous instance of the same wildcard. Or if this is the first
-** instance of the wildcard, the next sequential variable number is
-** assigned.
-*/
-void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
- sqlite3 *db = pParse->db;
- const char *z;
- ynVar x;
-
- if( pExpr==0 ) return;
- assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
- z = pExpr->u.zToken;
- assert( z!=0 );
- assert( z[0]!=0 );
- assert( n==(u32)sqlite3Strlen30(z) );
- if( z[1]==0 ){
- /* Wildcard of the form "?". Assign the next variable number */
- assert( z[0]=='?' );
- x = (ynVar)(++pParse->nVar);
- }else{
- int doAdd = 0;
- if( z[0]=='?' ){
- /* Wildcard of the form "?nnn". Convert "nnn" to an integer and
- ** use it as the variable number */
- i64 i;
- int bOk;
- if( n==2 ){ /*OPTIMIZATION-IF-TRUE*/
- i = z[1]-'0'; /* The common case of ?N for a single digit N */
- bOk = 1;
- }else{
- bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
- }
- testcase( i==0 );
- testcase( i==1 );
- testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
- testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
- if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
- sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
- db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
- return;
- }
- x = (ynVar)i;
- if( x>pParse->nVar ){
- pParse->nVar = (int)x;
- doAdd = 1;
- }else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){
- doAdd = 1;
- }
- }else{
- /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
- ** number as the prior appearance of the same name, or if the name
- ** has never appeared before, reuse the same variable number
- */
- x = (ynVar)sqlite3VListNameToNum(pParse->pVList, z, n);
- if( x==0 ){
- x = (ynVar)(++pParse->nVar);
- doAdd = 1;
- }
- }
- if( doAdd ){
- pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x);
- }
- }
- pExpr->iColumn = x;
- if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
- sqlite3ErrorMsg(pParse, "too many SQL variables");
- }
-}
-
-/*
-** Recursively delete an expression tree.
-*/
-static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
- assert( p!=0 );
- /* Sanity check: Assert that the IntValue is non-negative if it exists */
- assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
-#ifdef SQLITE_DEBUG
- if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
- assert( p->pLeft==0 );
- assert( p->pRight==0 );
- assert( p->x.pSelect==0 );
- }
-#endif
- if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
- /* The Expr.x union is never used at the same time as Expr.pRight */
- assert( p->x.pList==0 || p->pRight==0 );
- if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
- if( p->pRight ){
- sqlite3ExprDeleteNN(db, p->pRight);
- }else if( ExprHasProperty(p, EP_xIsSelect) ){
- sqlite3SelectDelete(db, p->x.pSelect);
- }else{
- sqlite3ExprListDelete(db, p->x.pList);
- }
- }
- if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
- if( !ExprHasProperty(p, EP_Static) ){
- sqlite3DbFreeNN(db, p);
- }
-}
-void sqlite3ExprDelete(sqlite3 *db, Expr *p){
- if( p ) sqlite3ExprDeleteNN(db, p);
-}
-
-/*
-** Return the number of bytes allocated for the expression structure
-** passed as the first argument. This is always one of EXPR_FULLSIZE,
-** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
-*/
-static int exprStructSize(Expr *p){
- if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
- if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
- return EXPR_FULLSIZE;
-}
-
-/*
-** The dupedExpr*Size() routines each return the number of bytes required
-** to store a copy of an expression or expression tree. They differ in
-** how much of the tree is measured.
-**
-** dupedExprStructSize() Size of only the Expr structure
-** dupedExprNodeSize() Size of Expr + space for token
-** dupedExprSize() Expr + token + subtree components
-**
-***************************************************************************
-**
-** The dupedExprStructSize() function returns two values OR-ed together:
-** (1) the space required for a copy of the Expr structure only and
-** (2) the EP_xxx flags that indicate what the structure size should be.
-** The return values is always one of:
-**
-** EXPR_FULLSIZE
-** EXPR_REDUCEDSIZE | EP_Reduced
-** EXPR_TOKENONLYSIZE | EP_TokenOnly
-**
-** The size of the structure can be found by masking the return value
-** of this routine with 0xfff. The flags can be found by masking the
-** return value with EP_Reduced|EP_TokenOnly.
-**
-** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size
-** (unreduced) Expr objects as they or originally constructed by the parser.
-** During expression analysis, extra information is computed and moved into
-** later parts of teh Expr object and that extra information might get chopped
-** off if the expression is reduced. Note also that it does not work to
-** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal
-** to reduce a pristine expression tree from the parser. The implementation
-** of dupedExprStructSize() contain multiple assert() statements that attempt
-** to enforce this constraint.
-*/
-static int dupedExprStructSize(Expr *p, int flags){
- int nSize;
- assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
- assert( EXPR_FULLSIZE<=0xfff );
- assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
- if( 0==flags || p->op==TK_SELECT_COLUMN ){
- nSize = EXPR_FULLSIZE;
- }else{
- assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
- assert( !ExprHasProperty(p, EP_FromJoin) );
- assert( !ExprHasProperty(p, EP_MemToken) );
- assert( !ExprHasProperty(p, EP_NoReduce) );
- if( p->pLeft || p->x.pList ){
- nSize = EXPR_REDUCEDSIZE | EP_Reduced;
- }else{
- assert( p->pRight==0 );
- nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
- }
- }
- return nSize;
-}
-
-/*
-** This function returns the space in bytes required to store the copy
-** of the Expr structure and a copy of the Expr.u.zToken string (if that
-** string is defined.)
-*/
-static int dupedExprNodeSize(Expr *p, int flags){
- int nByte = dupedExprStructSize(p, flags) & 0xfff;
- if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
- nByte += sqlite3Strlen30(p->u.zToken)+1;
- }
- return ROUND8(nByte);
-}
-
-/*
-** Return the number of bytes required to create a duplicate of the
-** expression passed as the first argument. The second argument is a
-** mask containing EXPRDUP_XXX flags.
-**
-** The value returned includes space to create a copy of the Expr struct
-** itself and the buffer referred to by Expr.u.zToken, if any.
-**
-** If the EXPRDUP_REDUCE flag is set, then the return value includes
-** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
-** and Expr.pRight variables (but not for any structures pointed to or
-** descended from the Expr.x.pList or Expr.x.pSelect variables).
-*/
-static int dupedExprSize(Expr *p, int flags){
- int nByte = 0;
- if( p ){
- nByte = dupedExprNodeSize(p, flags);
- if( flags&EXPRDUP_REDUCE ){
- nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
- }
- }
- return nByte;
-}
-
-/*
-** This function is similar to sqlite3ExprDup(), except that if pzBuffer
-** is not NULL then *pzBuffer is assumed to point to a buffer large enough
-** to store the copy of expression p, the copies of p->u.zToken
-** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
-** if any. Before returning, *pzBuffer is set to the first byte past the
-** portion of the buffer copied into by this function.
-*/
-static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
- Expr *pNew; /* Value to return */
- u8 *zAlloc; /* Memory space from which to build Expr object */
- u32 staticFlag; /* EP_Static if space not obtained from malloc */
-
- assert( db!=0 );
- assert( p );
- assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE );
- assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE );
-
- /* Figure out where to write the new Expr structure. */
- if( pzBuffer ){
- zAlloc = *pzBuffer;
- staticFlag = EP_Static;
- }else{
- zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
- staticFlag = 0;
- }
- pNew = (Expr *)zAlloc;
-
- if( pNew ){
- /* Set nNewSize to the size allocated for the structure pointed to
- ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
- ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
- ** by the copy of the p->u.zToken string (if any).
- */
- const unsigned nStructSize = dupedExprStructSize(p, dupFlags);
- const int nNewSize = nStructSize & 0xfff;
- int nToken;
- if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
- nToken = sqlite3Strlen30(p->u.zToken) + 1;
- }else{
- nToken = 0;
- }
- if( dupFlags ){
- assert( ExprHasProperty(p, EP_Reduced)==0 );
- memcpy(zAlloc, p, nNewSize);
- }else{
- u32 nSize = (u32)exprStructSize(p);
- memcpy(zAlloc, p, nSize);
- if( nSize<EXPR_FULLSIZE ){
- memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
- }
- }
-
- /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
- pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
- pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
- pNew->flags |= staticFlag;
-
- /* Copy the p->u.zToken string, if any. */
- if( nToken ){
- char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
- memcpy(zToken, p->u.zToken, nToken);
- }
-
- if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){
- /* Fill in the pNew->x.pSelect or pNew->x.pList member. */
- if( ExprHasProperty(p, EP_xIsSelect) ){
- pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
- }else{
- pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
- }
- }
-
- /* Fill in pNew->pLeft and pNew->pRight. */
- if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
- zAlloc += dupedExprNodeSize(p, dupFlags);
- if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
- pNew->pLeft = p->pLeft ?
- exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
- pNew->pRight = p->pRight ?
- exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
- }
- if( pzBuffer ){
- *pzBuffer = zAlloc;
- }
- }else{
- if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
- if( pNew->op==TK_SELECT_COLUMN ){
- pNew->pLeft = p->pLeft;
- assert( p->iColumn==0 || p->pRight==0 );
- assert( p->pRight==0 || p->pRight==p->pLeft );
- }else{
- pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
- }
- pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
- }
- }
- }
- return pNew;
-}
-
-/*
-** Create and return a deep copy of the object passed as the second
-** argument. If an OOM condition is encountered, NULL is returned
-** and the db->mallocFailed flag set.
-*/
-#ifndef SQLITE_OMIT_CTE
-static With *withDup(sqlite3 *db, With *p){
- With *pRet = 0;
- if( p ){
- int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
- pRet = sqlite3DbMallocZero(db, nByte);
- if( pRet ){
- int i;
- pRet->nCte = p->nCte;
- for(i=0; i<p->nCte; i++){
- pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0);
- pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0);
- pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName);
- }
- }
- }
- return pRet;
-}
-#else
-# define withDup(x,y) 0
-#endif
-
-/*
-** The following group of routines make deep copies of expressions,
-** expression lists, ID lists, and select statements. The copies can
-** be deleted (by being passed to their respective ...Delete() routines)
-** without effecting the originals.
-**
-** The expression list, ID, and source lists return by sqlite3ExprListDup(),
-** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
-** by subsequent calls to sqlite*ListAppend() routines.
-**
-** Any tables that the SrcList might point to are not duplicated.
-**
-** The flags parameter contains a combination of the EXPRDUP_XXX flags.
-** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
-** truncated version of the usual Expr structure that will be stored as
-** part of the in-memory representation of the database schema.
-*/
-Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
- assert( flags==0 || flags==EXPRDUP_REDUCE );
- return p ? exprDup(db, p, flags, 0) : 0;
-}
-ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
- ExprList *pNew;
- struct ExprList_item *pItem, *pOldItem;
- int i;
- Expr *pPriorSelectCol = 0;
- assert( db!=0 );
- if( p==0 ) return 0;
- pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
- if( pNew==0 ) return 0;
- pNew->nExpr = p->nExpr;
- pItem = pNew->a;
- pOldItem = p->a;
- for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
- Expr *pOldExpr = pOldItem->pExpr;
- Expr *pNewExpr;
- pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
- if( pOldExpr
- && pOldExpr->op==TK_SELECT_COLUMN
- && (pNewExpr = pItem->pExpr)!=0
- ){
- assert( pNewExpr->iColumn==0 || i>0 );
- if( pNewExpr->iColumn==0 ){
- assert( pOldExpr->pLeft==pOldExpr->pRight );
- pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
- }else{
- assert( i>0 );
- assert( pItem[-1].pExpr!=0 );
- assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
- assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
- pNewExpr->pLeft = pPriorSelectCol;
- }
- }
- pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
- pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
- pItem->sortOrder = pOldItem->sortOrder;
- pItem->done = 0;
- pItem->bSpanIsTab = pOldItem->bSpanIsTab;
- pItem->bSorterRef = pOldItem->bSorterRef;
- pItem->u = pOldItem->u;
- }
- return pNew;
-}
-
-/*
-** If cursors, triggers, views and subqueries are all omitted from
-** the build, then none of the following routines, except for
-** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
-** called with a NULL argument.
-*/
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
- || !defined(SQLITE_OMIT_SUBQUERY)
-SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
- SrcList *pNew;
- int i;
- int nByte;
- assert( db!=0 );
- if( p==0 ) return 0;
- nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
- pNew = sqlite3DbMallocRawNN(db, nByte );
- if( pNew==0 ) return 0;
- pNew->nSrc = pNew->nAlloc = p->nSrc;
- for(i=0; i<p->nSrc; i++){
- struct SrcList_item *pNewItem = &pNew->a[i];
- struct SrcList_item *pOldItem = &p->a[i];
- Table *pTab;
- pNewItem->pSchema = pOldItem->pSchema;
- pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
- pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
- pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
- pNewItem->fg = pOldItem->fg;
- pNewItem->iCursor = pOldItem->iCursor;
- pNewItem->addrFillSub = pOldItem->addrFillSub;
- pNewItem->regReturn = pOldItem->regReturn;
- if( pNewItem->fg.isIndexedBy ){
- pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
- }
- pNewItem->pIBIndex = pOldItem->pIBIndex;
- if( pNewItem->fg.isTabFunc ){
- pNewItem->u1.pFuncArg =
- sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
- }
- pTab = pNewItem->pTab = pOldItem->pTab;
- if( pTab ){
- pTab->nTabRef++;
- }
- pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
- pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
- pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
- pNewItem->colUsed = pOldItem->colUsed;
- }
- return pNew;
-}
-IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
- IdList *pNew;
- int i;
- assert( db!=0 );
- if( p==0 ) return 0;
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
- if( pNew==0 ) return 0;
- pNew->nId = p->nId;
- pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) );
- if( pNew->a==0 ){
- sqlite3DbFreeNN(db, pNew);
- return 0;
- }
- /* Note that because the size of the allocation for p->a[] is not
- ** necessarily a power of two, sqlite3IdListAppend() may not be called
- ** on the duplicate created by this function. */
- for(i=0; i<p->nId; i++){
- struct IdList_item *pNewItem = &pNew->a[i];
- struct IdList_item *pOldItem = &p->a[i];
- pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
- pNewItem->idx = pOldItem->idx;
- }
- return pNew;
-}
-Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
- Select *pRet = 0;
- Select *pNext = 0;
- Select **pp = &pRet;
- Select *p;
-
- assert( db!=0 );
- for(p=pDup; p; p=p->pPrior){
- Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
- if( pNew==0 ) break;
- pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
- pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
- pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
- pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
- pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
- pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
- pNew->op = p->op;
- pNew->pNext = pNext;
- pNew->pPrior = 0;
- pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
- pNew->iLimit = 0;
- pNew->iOffset = 0;
- pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
- pNew->addrOpenEphm[0] = -1;
- pNew->addrOpenEphm[1] = -1;
- pNew->nSelectRow = p->nSelectRow;
- pNew->pWith = withDup(db, p->pWith);
- sqlite3SelectSetName(pNew, p->zSelName);
- *pp = pNew;
- pp = &pNew->pPrior;
- pNext = pNew;
- }
-
- return pRet;
-}
-#else
-Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
- assert( p==0 );
- return 0;
-}
-#endif
-
-
-/*
-** Add a new element to the end of an expression list. If pList is
-** initially NULL, then create a new expression list.
-**
-** The pList argument must be either NULL or a pointer to an ExprList
-** obtained from a prior call to sqlite3ExprListAppend(). This routine
-** may not be used with an ExprList obtained from sqlite3ExprListDup().
-** Reason: This routine assumes that the number of slots in pList->a[]
-** is a power of two. That is true for sqlite3ExprListAppend() returns
-** but is not necessarily true from the return value of sqlite3ExprListDup().
-**
-** If a memory allocation error occurs, the entire list is freed and
-** NULL is returned. If non-NULL is returned, then it is guaranteed
-** that the new entry was successfully appended.
-*/
-ExprList *sqlite3ExprListAppend(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* List to which to append. Might be NULL */
- Expr *pExpr /* Expression to be appended. Might be NULL */
-){
- struct ExprList_item *pItem;
- sqlite3 *db = pParse->db;
- assert( db!=0 );
- if( pList==0 ){
- pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) );
- if( pList==0 ){
- goto no_mem;
- }
- pList->nExpr = 0;
- }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
- ExprList *pNew;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0]));
- if( pNew==0 ){
- goto no_mem;
- }
- pList = pNew;
- }
- pItem = &pList->a[pList->nExpr++];
- assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
- assert( offsetof(struct ExprList_item,pExpr)==0 );
- memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
- pItem->pExpr = pExpr;
- return pList;
-
-no_mem:
- /* Avoid leaking memory if malloc has failed. */
- sqlite3ExprDelete(db, pExpr);
- sqlite3ExprListDelete(db, pList);
- return 0;
-}
-
-/*
-** pColumns and pExpr form a vector assignment which is part of the SET
-** clause of an UPDATE statement. Like this:
-**
-** (a,b,c) = (expr1,expr2,expr3)
-** Or: (a,b,c) = (SELECT x,y,z FROM ....)
-**
-** For each term of the vector assignment, append new entries to the
-** expression list pList. In the case of a subquery on the RHS, append
-** TK_SELECT_COLUMN expressions.
-*/
-ExprList *sqlite3ExprListAppendVector(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* List to which to append. Might be NULL */
- IdList *pColumns, /* List of names of LHS of the assignment */
- Expr *pExpr /* Vector expression to be appended. Might be NULL */
-){
- sqlite3 *db = pParse->db;
- int n;
- int i;
- int iFirst = pList ? pList->nExpr : 0;
- /* pColumns can only be NULL due to an OOM but an OOM will cause an
- ** exit prior to this routine being invoked */
- if( NEVER(pColumns==0) ) goto vector_append_error;
- if( pExpr==0 ) goto vector_append_error;
-
- /* If the RHS is a vector, then we can immediately check to see that
- ** the size of the RHS and LHS match. But if the RHS is a SELECT,
- ** wildcards ("*") in the result set of the SELECT must be expanded before
- ** we can do the size check, so defer the size check until code generation.
- */
- if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){
- sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
- pColumns->nId, n);
- goto vector_append_error;
- }
-
- for(i=0; i<pColumns->nId; i++){
- Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
- pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
- if( pList ){
- assert( pList->nExpr==iFirst+i+1 );
- pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
- pColumns->a[i].zName = 0;
- }
- }
-
- if( !db->mallocFailed && pExpr->op==TK_SELECT && ALWAYS(pList!=0) ){
- Expr *pFirst = pList->a[iFirst].pExpr;
- assert( pFirst!=0 );
- assert( pFirst->op==TK_SELECT_COLUMN );
-
- /* Store the SELECT statement in pRight so it will be deleted when
- ** sqlite3ExprListDelete() is called */
- pFirst->pRight = pExpr;
- pExpr = 0;
-
- /* Remember the size of the LHS in iTable so that we can check that
- ** the RHS and LHS sizes match during code generation. */
- pFirst->iTable = pColumns->nId;
- }
-
-vector_append_error:
- sqlite3ExprDelete(db, pExpr);
- sqlite3IdListDelete(db, pColumns);
- return pList;
-}
-
-/*
-** Set the sort order for the last element on the given ExprList.
-*/
-void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){
- if( p==0 ) return;
- assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 );
- assert( p->nExpr>0 );
- if( iSortOrder<0 ){
- assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC );
- return;
- }
- p->a[p->nExpr-1].sortOrder = (u8)iSortOrder;
-}
-
-/*
-** Set the ExprList.a[].zName element of the most recently added item
-** on the expression list.
-**
-** pList might be NULL following an OOM error. But pName should never be
-** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
-** is set.
-*/
-void sqlite3ExprListSetName(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* List to which to add the span. */
- Token *pName, /* Name to be added */
- int dequote /* True to cause the name to be dequoted */
-){
- assert( pList!=0 || pParse->db->mallocFailed!=0 );
- if( pList ){
- struct ExprList_item *pItem;
- assert( pList->nExpr>0 );
- pItem = &pList->a[pList->nExpr-1];
- assert( pItem->zName==0 );
- pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
- if( dequote ) sqlite3Dequote(pItem->zName);
- }
-}
-
-/*
-** Set the ExprList.a[].zSpan element of the most recently added item
-** on the expression list.
-**
-** pList might be NULL following an OOM error. But pSpan should never be
-** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
-** is set.
-*/
-void sqlite3ExprListSetSpan(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* List to which to add the span. */
- const char *zStart, /* Start of the span */
- const char *zEnd /* End of the span */
-){
- sqlite3 *db = pParse->db;
- assert( pList!=0 || db->mallocFailed!=0 );
- if( pList ){
- struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
- assert( pList->nExpr>0 );
- sqlite3DbFree(db, pItem->zSpan);
- pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd);
- }
-}
-
-/*
-** If the expression list pEList contains more than iLimit elements,
-** leave an error message in pParse.
-*/
-void sqlite3ExprListCheckLength(
- Parse *pParse,
- ExprList *pEList,
- const char *zObject
-){
- int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
- testcase( pEList && pEList->nExpr==mx );
- testcase( pEList && pEList->nExpr==mx+1 );
- if( pEList && pEList->nExpr>mx ){
- sqlite3ErrorMsg(pParse, "too many columns in %s", zObject);
- }
-}
-
-/*
-** Delete an entire expression list.
-*/
-static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
- int i = pList->nExpr;
- struct ExprList_item *pItem = pList->a;
- assert( pList->nExpr>0 );
- do{
- sqlite3ExprDelete(db, pItem->pExpr);
- sqlite3DbFree(db, pItem->zName);
- sqlite3DbFree(db, pItem->zSpan);
- pItem++;
- }while( --i>0 );
- sqlite3DbFreeNN(db, pList);
-}
-void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
- if( pList ) exprListDeleteNN(db, pList);
-}
-
-/*
-** Return the bitwise-OR of all Expr.flags fields in the given
-** ExprList.
-*/
-u32 sqlite3ExprListFlags(const ExprList *pList){
- int i;
- u32 m = 0;
- assert( pList!=0 );
- for(i=0; i<pList->nExpr; i++){
- Expr *pExpr = pList->a[i].pExpr;
- assert( pExpr!=0 );
- m |= pExpr->flags;
- }
- return m;
-}
-
-/*
-** This is a SELECT-node callback for the expression walker that
-** always "fails". By "fail" in this case, we mean set
-** pWalker->eCode to zero and abort.
-**
-** This callback is used by multiple expression walkers.
-*/
-int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- pWalker->eCode = 0;
- return WRC_Abort;
-}
-
-/*
-** If the input expression is an ID with the name "true" or "false"
-** then convert it into an TK_TRUEFALSE term. Return non-zero if
-** the conversion happened, and zero if the expression is unaltered.
-*/
-int sqlite3ExprIdToTrueFalse(Expr *pExpr){
- assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
- if( sqlite3StrICmp(pExpr->u.zToken, "true")==0
- || sqlite3StrICmp(pExpr->u.zToken, "false")==0
- ){
- pExpr->op = TK_TRUEFALSE;
- return 1;
- }
- return 0;
-}
-
-/*
-** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE
-** and 0 if it is FALSE.
-*/
-int sqlite3ExprTruthValue(const Expr *pExpr){
- assert( pExpr->op==TK_TRUEFALSE );
- assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0
- || sqlite3StrICmp(pExpr->u.zToken,"false")==0 );
- return pExpr->u.zToken[4]==0;
-}
-
-
-/*
-** These routines are Walker callbacks used to check expressions to
-** see if they are "constant" for some definition of constant. The
-** Walker.eCode value determines the type of "constant" we are looking
-** for.
-**
-** These callback routines are used to implement the following:
-**
-** sqlite3ExprIsConstant() pWalker->eCode==1
-** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
-** sqlite3ExprIsTableConstant() pWalker->eCode==3
-** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
-**
-** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
-** is found to not be a constant.
-**
-** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
-** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing
-** an existing schema and 4 when processing a new statement. A bound
-** parameter raises an error for new statements, but is silently converted
-** to NULL for existing schemas. This allows sqlite_master tables that
-** contain a bound parameter because they were generated by older versions
-** of SQLite to be parsed by newer versions of SQLite without raising a
-** malformed schema error.
-*/
-static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
-
- /* If pWalker->eCode is 2 then any term of the expression that comes from
- ** the ON or USING clauses of a left join disqualifies the expression
- ** from being considered constant. */
- if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
- pWalker->eCode = 0;
- return WRC_Abort;
- }
-
- switch( pExpr->op ){
- /* Consider functions to be constant if all their arguments are constant
- ** and either pWalker->eCode==4 or 5 or the function has the
- ** SQLITE_FUNC_CONST flag. */
- case TK_FUNCTION:
- if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){
- return WRC_Continue;
- }else{
- pWalker->eCode = 0;
- return WRC_Abort;
- }
- case TK_ID:
- /* Convert "true" or "false" in a DEFAULT clause into the
- ** appropriate TK_TRUEFALSE operator */
- if( sqlite3ExprIdToTrueFalse(pExpr) ){
- return WRC_Prune;
- }
- /* Fall thru */
- case TK_COLUMN:
- case TK_AGG_FUNCTION:
- case TK_AGG_COLUMN:
- testcase( pExpr->op==TK_ID );
- testcase( pExpr->op==TK_COLUMN );
- testcase( pExpr->op==TK_AGG_FUNCTION );
- testcase( pExpr->op==TK_AGG_COLUMN );
- if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
- return WRC_Continue;
- }
- /* Fall through */
- case TK_IF_NULL_ROW:
- case TK_REGISTER:
- testcase( pExpr->op==TK_REGISTER );
- testcase( pExpr->op==TK_IF_NULL_ROW );
- pWalker->eCode = 0;
- return WRC_Abort;
- case TK_VARIABLE:
- if( pWalker->eCode==5 ){
- /* Silently convert bound parameters that appear inside of CREATE
- ** statements into a NULL when parsing the CREATE statement text out
- ** of the sqlite_master table */
- pExpr->op = TK_NULL;
- }else if( pWalker->eCode==4 ){
- /* A bound parameter in a CREATE statement that originates from
- ** sqlite3_prepare() causes an error */
- pWalker->eCode = 0;
- return WRC_Abort;
- }
- /* Fall through */
- default:
- testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */
- testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */
- return WRC_Continue;
- }
-}
-static int exprIsConst(Expr *p, int initFlag, int iCur){
- Walker w;
- w.eCode = initFlag;
- w.xExprCallback = exprNodeIsConstant;
- w.xSelectCallback = sqlite3SelectWalkFail;
-#ifdef SQLITE_DEBUG
- w.xSelectCallback2 = sqlite3SelectWalkAssert2;
-#endif
- w.u.iCur = iCur;
- sqlite3WalkExpr(&w, p);
- return w.eCode;
-}
-
-/*
-** Walk an expression tree. Return non-zero if the expression is constant
-** and 0 if it involves variables or function calls.
-**
-** For the purposes of this function, a double-quoted string (ex: "abc")
-** is considered a variable but a single-quoted string (ex: 'abc') is
-** a constant.
-*/
-int sqlite3ExprIsConstant(Expr *p){
- return exprIsConst(p, 1, 0);
-}
-
-/*
-** Walk an expression tree. Return non-zero if the expression is constant
-** that does no originate from the ON or USING clauses of a join.
-** Return 0 if it involves variables or function calls or terms from
-** an ON or USING clause.
-*/
-int sqlite3ExprIsConstantNotJoin(Expr *p){
- return exprIsConst(p, 2, 0);
-}
-
-/*
-** Walk an expression tree. Return non-zero if the expression is constant
-** for any single row of the table with cursor iCur. In other words, the
-** expression must not refer to any non-deterministic function nor any
-** table other than iCur.
-*/
-int sqlite3ExprIsTableConstant(Expr *p, int iCur){
- return exprIsConst(p, 3, iCur);
-}
-
-
-/*
-** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
-*/
-static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
- ExprList *pGroupBy = pWalker->u.pGroupBy;
- int i;
-
- /* Check if pExpr is identical to any GROUP BY term. If so, consider
- ** it constant. */
- for(i=0; i<pGroupBy->nExpr; i++){
- Expr *p = pGroupBy->a[i].pExpr;
- if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
- CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p);
- if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){
- return WRC_Prune;
- }
- }
- }
-
- /* Check if pExpr is a sub-select. If so, consider it variable. */
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- pWalker->eCode = 0;
- return WRC_Abort;
- }
-
- return exprNodeIsConstant(pWalker, pExpr);
-}
-
-/*
-** Walk the expression tree passed as the first argument. Return non-zero
-** if the expression consists entirely of constants or copies of terms
-** in pGroupBy that sort with the BINARY collation sequence.
-**
-** This routine is used to determine if a term of the HAVING clause can
-** be promoted into the WHERE clause. In order for such a promotion to work,
-** the value of the HAVING clause term must be the same for all members of
-** a "group". The requirement that the GROUP BY term must be BINARY
-** assumes that no other collating sequence will have a finer-grained
-** grouping than binary. In other words (A=B COLLATE binary) implies
-** A=B in every other collating sequence. The requirement that the
-** GROUP BY be BINARY is stricter than necessary. It would also work
-** to promote HAVING clauses that use the same alternative collating
-** sequence as the GROUP BY term, but that is much harder to check,
-** alternative collating sequences are uncommon, and this is only an
-** optimization, so we take the easy way out and simply require the
-** GROUP BY to use the BINARY collating sequence.
-*/
-int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
- Walker w;
- w.eCode = 1;
- w.xExprCallback = exprNodeIsConstantOrGroupBy;
- w.xSelectCallback = 0;
- w.u.pGroupBy = pGroupBy;
- w.pParse = pParse;
- sqlite3WalkExpr(&w, p);
- return w.eCode;
-}
-
-/*
-** Walk an expression tree. Return non-zero if the expression is constant
-** or a function call with constant arguments. Return and 0 if there
-** are any variables.
-**
-** For the purposes of this function, a double-quoted string (ex: "abc")
-** is considered a variable but a single-quoted string (ex: 'abc') is
-** a constant.
-*/
-int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
- assert( isInit==0 || isInit==1 );
- return exprIsConst(p, 4+isInit, 0);
-}
-
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
-/*
-** Walk an expression tree. Return 1 if the expression contains a
-** subquery of some kind. Return 0 if there are no subqueries.
-*/
-int sqlite3ExprContainsSubquery(Expr *p){
- Walker w;
- w.eCode = 1;
- w.xExprCallback = sqlite3ExprWalkNoop;
- w.xSelectCallback = sqlite3SelectWalkFail;
-#ifdef SQLITE_DEBUG
- w.xSelectCallback2 = sqlite3SelectWalkAssert2;
-#endif
- sqlite3WalkExpr(&w, p);
- return w.eCode==0;
-}
-#endif
-
-/*
-** If the expression p codes a constant integer that is small enough
-** to fit in a 32-bit integer, return 1 and put the value of the integer
-** in *pValue. If the expression is not an integer or if it is too big
-** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
-*/
-int sqlite3ExprIsInteger(Expr *p, int *pValue){
- int rc = 0;
- if( p==0 ) return 0; /* Can only happen following on OOM */
-
- /* If an expression is an integer literal that fits in a signed 32-bit
- ** integer, then the EP_IntValue flag will have already been set */
- assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0
- || sqlite3GetInt32(p->u.zToken, &rc)==0 );
-
- if( p->flags & EP_IntValue ){
- *pValue = p->u.iValue;
- return 1;
- }
- switch( p->op ){
- case TK_UPLUS: {
- rc = sqlite3ExprIsInteger(p->pLeft, pValue);
- break;
- }
- case TK_UMINUS: {
- int v;
- if( sqlite3ExprIsInteger(p->pLeft, &v) ){
- assert( v!=(-2147483647-1) );
- *pValue = -v;
- rc = 1;
- }
- break;
- }
- default: break;
- }
- return rc;
-}
-
-/*
-** Return FALSE if there is no chance that the expression can be NULL.
-**
-** If the expression might be NULL or if the expression is too complex
-** to tell return TRUE.
-**
-** This routine is used as an optimization, to skip OP_IsNull opcodes
-** when we know that a value cannot be NULL. Hence, a false positive
-** (returning TRUE when in fact the expression can never be NULL) might
-** be a small performance hit but is otherwise harmless. On the other
-** hand, a false negative (returning FALSE when the result could be NULL)
-** will likely result in an incorrect answer. So when in doubt, return
-** TRUE.
-*/
-int sqlite3ExprCanBeNull(const Expr *p){
- u8 op;
- while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
- op = p->op;
- if( op==TK_REGISTER ) op = p->op2;
- switch( op ){
- case TK_INTEGER:
- case TK_STRING:
- case TK_FLOAT:
- case TK_BLOB:
- return 0;
- case TK_COLUMN:
- return ExprHasProperty(p, EP_CanBeNull) ||
- p->pTab==0 || /* Reference to column of index on expression */
- (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
- default:
- return 1;
- }
-}
-
-/*
-** Return TRUE if the given expression is a constant which would be
-** unchanged by OP_Affinity with the affinity given in the second
-** argument.
-**
-** This routine is used to determine if the OP_Affinity operation
-** can be omitted. When in doubt return FALSE. A false negative
-** is harmless. A false positive, however, can result in the wrong
-** answer.
-*/
-int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
- u8 op;
- if( aff==SQLITE_AFF_BLOB ) return 1;
- while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
- op = p->op;
- if( op==TK_REGISTER ) op = p->op2;
- switch( op ){
- case TK_INTEGER: {
- return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC;
- }
- case TK_FLOAT: {
- return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC;
- }
- case TK_STRING: {
- return aff==SQLITE_AFF_TEXT;
- }
- case TK_BLOB: {
- return 1;
- }
- case TK_COLUMN: {
- assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */
- return p->iColumn<0
- && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC);
- }
- default: {
- return 0;
- }
- }
-}
-
-/*
-** Return TRUE if the given string is a row-id column name.
-*/
-int sqlite3IsRowid(const char *z){
- if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1;
- if( sqlite3StrICmp(z, "ROWID")==0 ) return 1;
- if( sqlite3StrICmp(z, "OID")==0 ) return 1;
- return 0;
-}
-
-/*
-** pX is the RHS of an IN operator. If pX is a SELECT statement
-** that can be simplified to a direct table access, then return
-** a pointer to the SELECT statement. If pX is not a SELECT statement,
-** or if the SELECT statement needs to be manifested into a transient
-** table, then return NULL.
-*/
-#ifndef SQLITE_OMIT_SUBQUERY
-static Select *isCandidateForInOpt(Expr *pX){
- Select *p;
- SrcList *pSrc;
- ExprList *pEList;
- Table *pTab;
- int i;
- if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */
- if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */
- p = pX->x.pSelect;
- if( p->pPrior ) return 0; /* Not a compound SELECT */
- if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
- testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
- testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
- return 0; /* No DISTINCT keyword and no aggregate functions */
- }
- assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */
- if( p->pLimit ) return 0; /* Has no LIMIT clause */
- if( p->pWhere ) return 0; /* Has no WHERE clause */
- pSrc = p->pSrc;
- assert( pSrc!=0 );
- if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
- if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
- pTab = pSrc->a[0].pTab;
- assert( pTab!=0 );
- assert( pTab->pSelect==0 ); /* FROM clause is not a view */
- if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
- pEList = p->pEList;
- assert( pEList!=0 );
- /* All SELECT results must be columns. */
- for(i=0; i<pEList->nExpr; i++){
- Expr *pRes = pEList->a[i].pExpr;
- if( pRes->op!=TK_COLUMN ) return 0;
- assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */
- }
- return p;
-}
-#endif /* SQLITE_OMIT_SUBQUERY */
-
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** Generate code that checks the left-most column of index table iCur to see if
-** it contains any NULL entries. Cause the register at regHasNull to be set
-** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull
-** to be set to NULL if iCur contains one or more NULL values.
-*/
-static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
- int addr1;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull);
- addr1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull);
- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
- VdbeComment((v, "first_entry_in(%d)", iCur));
- sqlite3VdbeJumpHere(v, addr1);
-}
-#endif
-
-
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** The argument is an IN operator with a list (not a subquery) on the
-** right-hand side. Return TRUE if that list is constant.
-*/
-static int sqlite3InRhsIsConstant(Expr *pIn){
- Expr *pLHS;
- int res;
- assert( !ExprHasProperty(pIn, EP_xIsSelect) );
- pLHS = pIn->pLeft;
- pIn->pLeft = 0;
- res = sqlite3ExprIsConstant(pIn);
- pIn->pLeft = pLHS;
- return res;
-}
-#endif
-
-/*
-** This function is used by the implementation of the IN (...) operator.
-** The pX parameter is the expression on the RHS of the IN operator, which
-** might be either a list of expressions or a subquery.
-**
-** The job of this routine is to find or create a b-tree object that can
-** be used either to test for membership in the RHS set or to iterate through
-** all members of the RHS set, skipping duplicates.
-**
-** A cursor is opened on the b-tree object that is the RHS of the IN operator
-** and pX->iTable is set to the index of that cursor.
-**
-** The returned value of this function indicates the b-tree type, as follows:
-**
-** IN_INDEX_ROWID - The cursor was opened on a database table.
-** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
-** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
-** IN_INDEX_EPH - The cursor was opened on a specially created and
-** populated epheremal table.
-** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be
-** implemented as a sequence of comparisons.
-**
-** An existing b-tree might be used if the RHS expression pX is a simple
-** subquery such as:
-**
-** SELECT <column1>, <column2>... FROM <table>
-**
-** If the RHS of the IN operator is a list or a more complex subquery, then
-** an ephemeral table might need to be generated from the RHS and then
-** pX->iTable made to point to the ephemeral table instead of an
-** existing table.
-**
-** The inFlags parameter must contain, at a minimum, one of the bits
-** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains
-** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast
-** membership test. When the IN_INDEX_LOOP bit is set, the IN index will
-** be used to loop over all values of the RHS of the IN operator.
-**
-** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
-** through the set members) then the b-tree must not contain duplicates.
-** An epheremal table will be created unless the selected columns are guaranteed
-** to be unique - either because it is an INTEGER PRIMARY KEY or due to
-** a UNIQUE constraint or index.
-**
-** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used
-** for fast set membership tests) then an epheremal table must
-** be used unless <columns> is a single INTEGER PRIMARY KEY column or an
-** index can be found with the specified <columns> as its left-most.
-**
-** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
-** if the RHS of the IN operator is a list (not a subquery) then this
-** routine might decide that creating an ephemeral b-tree for membership
-** testing is too expensive and return IN_INDEX_NOOP. In that case, the
-** calling routine should implement the IN operator using a sequence
-** of Eq or Ne comparison operations.
-**
-** When the b-tree is being used for membership tests, the calling function
-** might need to know whether or not the RHS side of the IN operator
-** contains a NULL. If prRhsHasNull is not a NULL pointer and
-** if there is any chance that the (...) might contain a NULL value at
-** runtime, then a register is allocated and the register number written
-** to *prRhsHasNull. If there is no chance that the (...) contains a
-** NULL value, then *prRhsHasNull is left unchanged.
-**
-** If a register is allocated and its location stored in *prRhsHasNull, then
-** the value in that register will be NULL if the b-tree contains one or more
-** NULL values, and it will be some non-NULL value if the b-tree contains no
-** NULL values.
-**
-** If the aiMap parameter is not NULL, it must point to an array containing
-** one element for each column returned by the SELECT statement on the RHS
-** of the IN(...) operator. The i'th entry of the array is populated with the
-** offset of the index column that matches the i'th column returned by the
-** SELECT. For example, if the expression and selected index are:
-**
-** (?,?,?) IN (SELECT a, b, c FROM t1)
-** CREATE INDEX i1 ON t1(b, c, a);
-**
-** then aiMap[] is populated with {2, 0, 1}.
-*/
-#ifndef SQLITE_OMIT_SUBQUERY
-int sqlite3FindInIndex(
- Parse *pParse, /* Parsing context */
- Expr *pX, /* The right-hand side (RHS) of the IN operator */
- u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
- int *prRhsHasNull, /* Register holding NULL status. See notes */
- int *aiMap /* Mapping from Index fields to RHS fields */
-){
- Select *p; /* SELECT to the right of IN operator */
- int eType = 0; /* Type of RHS table. IN_INDEX_* */
- int iTab = pParse->nTab++; /* Cursor of the RHS table */
- int mustBeUnique; /* True if RHS must be unique */
- Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
-
- assert( pX->op==TK_IN );
- mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
-
- /* If the RHS of this IN(...) operator is a SELECT, and if it matters
- ** whether or not the SELECT result contains NULL values, check whether
- ** or not NULL is actually possible (it may not be, for example, due
- ** to NOT NULL constraints in the schema). If no NULL values are possible,
- ** set prRhsHasNull to 0 before continuing. */
- if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){
- int i;
- ExprList *pEList = pX->x.pSelect->pEList;
- for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break;
- }
- if( i==pEList->nExpr ){
- prRhsHasNull = 0;
- }
- }
-
- /* Check to see if an existing table or index can be used to
- ** satisfy the query. This is preferable to generating a new
- ** ephemeral table. */
- if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
- sqlite3 *db = pParse->db; /* Database connection */
- Table *pTab; /* Table <table>. */
- i16 iDb; /* Database idx for pTab */
- ExprList *pEList = p->pEList;
- int nExpr = pEList->nExpr;
-
- assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
- assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
- assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
- pTab = p->pSrc->a[0].pTab;
-
- /* Code an OP_Transaction and OP_TableLock for <table>. */
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- sqlite3CodeVerifySchema(pParse, iDb);
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
-
- assert(v); /* sqlite3GetVdbe() has always been previously called */
- if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){
- /* The "x IN (SELECT rowid FROM table)" case */
- int iAddr = sqlite3VdbeAddOp0(v, OP_Once);
- VdbeCoverage(v);
-
- sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
- eType = IN_INDEX_ROWID;
-
- sqlite3VdbeJumpHere(v, iAddr);
- }else{
- Index *pIdx; /* Iterator variable */
- int affinity_ok = 1;
- int i;
-
- /* Check that the affinity that will be used to perform each
- ** comparison is the same as the affinity of each column in table
- ** on the RHS of the IN operator. If it not, it is not possible to
- ** use any index of the RHS table. */
- for(i=0; i<nExpr && affinity_ok; i++){
- Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
- int iCol = pEList->a[i].pExpr->iColumn;
- char idxaff = sqlite3TableColumnAffinity(pTab,iCol); /* RHS table */
- char cmpaff = sqlite3CompareAffinity(pLhs, idxaff);
- testcase( cmpaff==SQLITE_AFF_BLOB );
- testcase( cmpaff==SQLITE_AFF_TEXT );
- switch( cmpaff ){
- case SQLITE_AFF_BLOB:
- break;
- case SQLITE_AFF_TEXT:
- /* sqlite3CompareAffinity() only returns TEXT if one side or the
- ** other has no affinity and the other side is TEXT. Hence,
- ** the only way for cmpaff to be TEXT is for idxaff to be TEXT
- ** and for the term on the LHS of the IN to have no affinity. */
- assert( idxaff==SQLITE_AFF_TEXT );
- break;
- default:
- affinity_ok = sqlite3IsNumericAffinity(idxaff);
- }
- }
-
- if( affinity_ok ){
- /* Search for an existing index that will work for this IN operator */
- for(pIdx=pTab->pIndex; pIdx && eType==0; pIdx=pIdx->pNext){
- Bitmask colUsed; /* Columns of the index used */
- Bitmask mCol; /* Mask for the current column */
- if( pIdx->nColumn<nExpr ) continue;
- /* Maximum nColumn is BMS-2, not BMS-1, so that we can compute
- ** BITMASK(nExpr) without overflowing */
- testcase( pIdx->nColumn==BMS-2 );
- testcase( pIdx->nColumn==BMS-1 );
- if( pIdx->nColumn>=BMS-1 ) continue;
- if( mustBeUnique ){
- if( pIdx->nKeyCol>nExpr
- ||(pIdx->nColumn>nExpr && !IsUniqueIndex(pIdx))
- ){
- continue; /* This index is not unique over the IN RHS columns */
- }
- }
-
- colUsed = 0; /* Columns of index used so far */
- for(i=0; i<nExpr; i++){
- Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
- Expr *pRhs = pEList->a[i].pExpr;
- CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
- int j;
-
- assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr );
- for(j=0; j<nExpr; j++){
- if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue;
- assert( pIdx->azColl[j] );
- if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){
- continue;
- }
- break;
- }
- if( j==nExpr ) break;
- mCol = MASKBIT(j);
- if( mCol & colUsed ) break; /* Each column used only once */
- colUsed |= mCol;
- if( aiMap ) aiMap[i] = j;
- }
-
- assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) );
- if( colUsed==(MASKBIT(nExpr)-1) ){
- /* If we reach this point, that means the index pIdx is usable */
- int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- ExplainQueryPlan((pParse, 0,
- "USING INDEX %s FOR IN-OPERATOR",pIdx->zName));
- sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
- sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
- VdbeComment((v, "%s", pIdx->zName));
- assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
- eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
-
- if( prRhsHasNull ){
-#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
- i64 mask = (1<<nExpr)-1;
- sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed,
- iTab, 0, 0, (u8*)&mask, P4_INT64);
-#endif
- *prRhsHasNull = ++pParse->nMem;
- if( nExpr==1 ){
- sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull);
- }
- }
- sqlite3VdbeJumpHere(v, iAddr);
- }
- } /* End loop over indexes */
- } /* End if( affinity_ok ) */
- } /* End if not an rowid index */
- } /* End attempt to optimize using an index */
-
- /* If no preexisting index is available for the IN clause
- ** and IN_INDEX_NOOP is an allowed reply
- ** and the RHS of the IN operator is a list, not a subquery
- ** and the RHS is not constant or has two or fewer terms,
- ** then it is not worth creating an ephemeral table to evaluate
- ** the IN operator so return IN_INDEX_NOOP.
- */
- if( eType==0
- && (inFlags & IN_INDEX_NOOP_OK)
- && !ExprHasProperty(pX, EP_xIsSelect)
- && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
- ){
- eType = IN_INDEX_NOOP;
- }
-
- if( eType==0 ){
- /* Could not find an existing table or index to use as the RHS b-tree.
- ** We will have to generate an ephemeral table to do the job.
- */
- u32 savedNQueryLoop = pParse->nQueryLoop;
- int rMayHaveNull = 0;
- eType = IN_INDEX_EPH;
- if( inFlags & IN_INDEX_LOOP ){
- pParse->nQueryLoop = 0;
- if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
- eType = IN_INDEX_ROWID;
- }
- }else if( prRhsHasNull ){
- *prRhsHasNull = rMayHaveNull = ++pParse->nMem;
- }
- sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
- pParse->nQueryLoop = savedNQueryLoop;
- }else{
- pX->iTable = iTab;
- }
-
- if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){
- int i, n;
- n = sqlite3ExprVectorSize(pX->pLeft);
- for(i=0; i<n; i++) aiMap[i] = i;
- }
- return eType;
-}
-#endif
-
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** Argument pExpr is an (?, ?...) IN(...) expression. This
-** function allocates and returns a nul-terminated string containing
-** the affinities to be used for each column of the comparison.
-**
-** It is the responsibility of the caller to ensure that the returned
-** string is eventually freed using sqlite3DbFree().
-*/
-static char *exprINAffinity(Parse *pParse, Expr *pExpr){
- Expr *pLeft = pExpr->pLeft;
- int nVal = sqlite3ExprVectorSize(pLeft);
- Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0;
- char *zRet;
-
- assert( pExpr->op==TK_IN );
- zRet = sqlite3DbMallocRaw(pParse->db, nVal+1);
- if( zRet ){
- int i;
- for(i=0; i<nVal; i++){
- Expr *pA = sqlite3VectorFieldSubexpr(pLeft, i);
- char a = sqlite3ExprAffinity(pA);
- if( pSelect ){
- zRet[i] = sqlite3CompareAffinity(pSelect->pEList->a[i].pExpr, a);
- }else{
- zRet[i] = a;
- }
- }
- zRet[nVal] = '\0';
- }
- return zRet;
-}
-#endif
-
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** Load the Parse object passed as the first argument with an error
-** message of the form:
-**
-** "sub-select returns N columns - expected M"
-*/
-void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){
- const char *zFmt = "sub-select returns %d columns - expected %d";
- sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
-}
-#endif
-
-/*
-** Expression pExpr is a vector that has been used in a context where
-** it is not permitted. If pExpr is a sub-select vector, this routine
-** loads the Parse object with a message of the form:
-**
-** "sub-select returns N columns - expected 1"
-**
-** Or, if it is a regular scalar vector:
-**
-** "row value misused"
-*/
-void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
-#ifndef SQLITE_OMIT_SUBQUERY
- if( pExpr->flags & EP_xIsSelect ){
- sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
- }else
-#endif
- {
- sqlite3ErrorMsg(pParse, "row value misused");
- }
-}
-
-/*
-** Generate code for scalar subqueries used as a subquery expression, EXISTS,
-** or IN operators. Examples:
-**
-** (SELECT a FROM b) -- subquery
-** EXISTS (SELECT a FROM b) -- EXISTS subquery
-** x IN (4,5,11) -- IN operator with list on right-hand side
-** x IN (SELECT a FROM b) -- IN operator with subquery on the right
-**
-** The pExpr parameter describes the expression that contains the IN
-** operator or subquery.
-**
-** If parameter isRowid is non-zero, then expression pExpr is guaranteed
-** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
-** to some integer key column of a table B-Tree. In this case, use an
-** intkey B-Tree to store the set of IN(...) values instead of the usual
-** (slower) variable length keys B-Tree.
-**
-** If rMayHaveNull is non-zero, that means that the operation is an IN
-** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
-** All this routine does is initialize the register given by rMayHaveNull
-** to NULL. Calling routines will take care of changing this register
-** value to non-NULL if the RHS is NULL-free.
-**
-** For a SELECT or EXISTS operator, return the register that holds the
-** result. For a multi-column SELECT, the result is stored in a contiguous
-** array of registers and the return value is the register of the left-most
-** result column. Return 0 for IN operators or if an error occurs.
-*/
-#ifndef SQLITE_OMIT_SUBQUERY
-int sqlite3CodeSubselect(
- Parse *pParse, /* Parsing context */
- Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
- int rHasNullFlag, /* Register that records whether NULLs exist in RHS */
- int isRowid /* If true, LHS of IN operator is a rowid */
-){
- int jmpIfDynamic = -1; /* One-time test address */
- int rReg = 0; /* Register storing resulting */
- Vdbe *v = sqlite3GetVdbe(pParse);
- if( NEVER(v==0) ) return 0;
- sqlite3ExprCachePush(pParse);
-
- /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it
- ** is encountered if any of the following is true:
- **
- ** * The right-hand side is a correlated subquery
- ** * The right-hand side is an expression list containing variables
- ** * We are inside a trigger
- **
- ** If all of the above are false, then we can run this code just once
- ** save the results, and reuse the same result on subsequent invocations.
- */
- if( !ExprHasProperty(pExpr, EP_VarSelect) ){
- jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- }
-
- switch( pExpr->op ){
- case TK_IN: {
- int addr; /* Address of OP_OpenEphemeral instruction */
- Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
- KeyInfo *pKeyInfo = 0; /* Key information */
- int nVal; /* Size of vector pLeft */
-
- nVal = sqlite3ExprVectorSize(pLeft);
- assert( !isRowid || nVal==1 );
-
- /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
- ** expression it is handled the same way. An ephemeral table is
- ** filled with index keys representing the results from the
- ** SELECT or the <exprlist>.
- **
- ** If the 'x' expression is a column value, or the SELECT...
- ** statement returns a column value, then the affinity of that
- ** column is used to build the index keys. If both 'x' and the
- ** SELECT... statement are columns, then numeric affinity is used
- ** if either column has NUMERIC or INTEGER affinity. If neither
- ** 'x' nor the SELECT... statement are columns, then numeric affinity
- ** is used.
- */
- pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral,
- pExpr->iTable, (isRowid?0:nVal));
- pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
-
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- /* Case 1: expr IN (SELECT ...)
- **
- ** Generate code to write the results of the select into the temporary
- ** table allocated and opened above.
- */
- Select *pSelect = pExpr->x.pSelect;
- ExprList *pEList = pSelect->pEList;
-
- ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY",
- jmpIfDynamic>=0?"":"CORRELATED "
- ));
- assert( !isRowid );
- /* If the LHS and RHS of the IN operator do not match, that
- ** error will have been caught long before we reach this point. */
- if( ALWAYS(pEList->nExpr==nVal) ){
- SelectDest dest;
- int i;
- sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
- dest.zAffSdst = exprINAffinity(pParse, pExpr);
- pSelect->iLimit = 0;
- testcase( pSelect->selFlags & SF_Distinct );
- testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
- if( sqlite3Select(pParse, pSelect, &dest) ){
- sqlite3DbFree(pParse->db, dest.zAffSdst);
- sqlite3KeyInfoUnref(pKeyInfo);
- return 0;
- }
- sqlite3DbFree(pParse->db, dest.zAffSdst);
- assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
- assert( pEList!=0 );
- assert( pEList->nExpr>0 );
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- for(i=0; i<nVal; i++){
- Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
- pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
- pParse, p, pEList->a[i].pExpr
- );
- }
- }
- }else if( ALWAYS(pExpr->x.pList!=0) ){
- /* Case 2: expr IN (exprlist)
- **
- ** For each expression, build an index key from the evaluation and
- ** store it in the temporary table. If <expr> is a column, then use
- ** that columns affinity when building index keys. If <expr> is not
- ** a column, use numeric affinity.
- */
- char affinity; /* Affinity of the LHS of the IN */
- int i;
- ExprList *pList = pExpr->x.pList;
- struct ExprList_item *pItem;
- int r1, r2, r3;
- affinity = sqlite3ExprAffinity(pLeft);
- if( !affinity ){
- affinity = SQLITE_AFF_BLOB;
- }
- if( pKeyInfo ){
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- }
-
- /* Loop through each expression in <exprlist>. */
- r1 = sqlite3GetTempReg(pParse);
- r2 = sqlite3GetTempReg(pParse);
- if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
- for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
- Expr *pE2 = pItem->pExpr;
- int iValToIns;
-
- /* If the expression is not constant then we will need to
- ** disable the test that was generated above that makes sure
- ** this code only executes once. Because for a non-constant
- ** expression we need to rerun this code each time.
- */
- if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){
- sqlite3VdbeChangeToNoop(v, jmpIfDynamic);
- jmpIfDynamic = -1;
- }
-
- /* Evaluate the expression and insert it into the temp table */
- if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
- sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
- }else{
- r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
- if( isRowid ){
- sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
- sqlite3VdbeCurrentAddr(v)+2);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
- }else{
- sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
- sqlite3ExprCacheAffinityChange(pParse, r3, 1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
- }
- }
- }
- sqlite3ReleaseTempReg(pParse, r1);
- sqlite3ReleaseTempReg(pParse, r2);
- }
- if( pKeyInfo ){
- sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
- }
- break;
- }
-
- case TK_EXISTS:
- case TK_SELECT:
- default: {
- /* Case 3: (SELECT ... FROM ...)
- ** or: EXISTS(SELECT ... FROM ...)
- **
- ** For a SELECT, generate code to put the values for all columns of
- ** the first row into an array of registers and return the index of
- ** the first register.
- **
- ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists)
- ** into a register and return that register number.
- **
- ** In both cases, the query is augmented with "LIMIT 1". Any
- ** preexisting limit is discarded in place of the new LIMIT 1.
- */
- Select *pSel; /* SELECT statement to encode */
- SelectDest dest; /* How to deal with SELECT result */
- int nReg; /* Registers to allocate */
- Expr *pLimit; /* New limit expression */
-
- testcase( pExpr->op==TK_EXISTS );
- testcase( pExpr->op==TK_SELECT );
- assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
- assert( ExprHasProperty(pExpr, EP_xIsSelect) );
-
- pSel = pExpr->x.pSelect;
- ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
- jmpIfDynamic>=0?"":"CORRELATED "));
- nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
- sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
- pParse->nMem += nReg;
- if( pExpr->op==TK_SELECT ){
- dest.eDest = SRT_Mem;
- dest.iSdst = dest.iSDParm;
- dest.nSdst = nReg;
- sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
- VdbeComment((v, "Init subquery result"));
- }else{
- dest.eDest = SRT_Exists;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
- VdbeComment((v, "Init EXISTS result"));
- }
- pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
- if( pSel->pLimit ){
- sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
- pSel->pLimit->pLeft = pLimit;
- }else{
- pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
- }
- pSel->iLimit = 0;
- if( sqlite3Select(pParse, pSel, &dest) ){
- return 0;
- }
- rReg = dest.iSDParm;
- ExprSetVVAProperty(pExpr, EP_NoReduce);
- break;
- }
- }
-
- if( rHasNullFlag ){
- sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag);
- }
-
- if( jmpIfDynamic>=0 ){
- sqlite3VdbeJumpHere(v, jmpIfDynamic);
- }
- sqlite3ExprCachePop(pParse);
-
- return rReg;
-}
-#endif /* SQLITE_OMIT_SUBQUERY */
-
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** Expr pIn is an IN(...) expression. This function checks that the
-** sub-select on the RHS of the IN() operator has the same number of
-** columns as the vector on the LHS. Or, if the RHS of the IN() is not
-** a sub-query, that the LHS is a vector of size 1.
-*/
-int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
- int nVector = sqlite3ExprVectorSize(pIn->pLeft);
- if( (pIn->flags & EP_xIsSelect) ){
- if( nVector!=pIn->x.pSelect->pEList->nExpr ){
- sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
- return 1;
- }
- }else if( nVector!=1 ){
- sqlite3VectorErrorMsg(pParse, pIn->pLeft);
- return 1;
- }
- return 0;
-}
-#endif
-
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** Generate code for an IN expression.
-**
-** x IN (SELECT ...)
-** x IN (value, value, ...)
-**
-** The left-hand side (LHS) is a scalar or vector expression. The
-** right-hand side (RHS) is an array of zero or more scalar values, or a
-** subquery. If the RHS is a subquery, the number of result columns must
-** match the number of columns in the vector on the LHS. If the RHS is
-** a list of values, the LHS must be a scalar.
-**
-** The IN operator is true if the LHS value is contained within the RHS.
-** The result is false if the LHS is definitely not in the RHS. The
-** result is NULL if the presence of the LHS in the RHS cannot be
-** determined due to NULLs.
-**
-** This routine generates code that jumps to destIfFalse if the LHS is not
-** contained within the RHS. If due to NULLs we cannot determine if the LHS
-** is contained in the RHS then jump to destIfNull. If the LHS is contained
-** within the RHS then fall through.
-**
-** See the separate in-operator.md documentation file in the canonical
-** SQLite source tree for additional information.
-*/
-static void sqlite3ExprCodeIN(
- Parse *pParse, /* Parsing and code generating context */
- Expr *pExpr, /* The IN expression */
- int destIfFalse, /* Jump here if LHS is not contained in the RHS */
- int destIfNull /* Jump here if the results are unknown due to NULLs */
-){
- int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
- int eType; /* Type of the RHS */
- int rLhs; /* Register(s) holding the LHS values */
- int rLhsOrig; /* LHS values prior to reordering by aiMap[] */
- Vdbe *v; /* Statement under construction */
- int *aiMap = 0; /* Map from vector field to index column */
- char *zAff = 0; /* Affinity string for comparisons */
- int nVector; /* Size of vectors for this IN operator */
- int iDummy; /* Dummy parameter to exprCodeVector() */
- Expr *pLeft; /* The LHS of the IN operator */
- int i; /* loop counter */
- int destStep2; /* Where to jump when NULLs seen in step 2 */
- int destStep6 = 0; /* Start of code for Step 6 */
- int addrTruthOp; /* Address of opcode that determines the IN is true */
- int destNotNull; /* Jump here if a comparison is not true in step 6 */
- int addrTop; /* Top of the step-6 loop */
-
- pLeft = pExpr->pLeft;
- if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
- zAff = exprINAffinity(pParse, pExpr);
- nVector = sqlite3ExprVectorSize(pExpr->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(
- pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
- );
- if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
-
- /* Attempt to compute the RHS. After this step, if anything other than
- ** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable
- ** contains the values that make up the RHS. If IN_INDEX_NOOP is returned,
- ** the RHS has not yet been coded. */
- v = pParse->pVdbe;
- assert( v!=0 ); /* OOM detected prior to this routine */
- VdbeNoopComment((v, "begin IN expr"));
- eType = sqlite3FindInIndex(pParse, pExpr,
- IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
- destIfFalse==destIfNull ? 0 : &rRhsHasNull, aiMap);
-
- assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH
- || eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC
- );
-#ifdef SQLITE_DEBUG
- /* Confirm that aiMap[] contains nVector integer values between 0 and
- ** nVector-1. */
- for(i=0; i<nVector; i++){
- int j, cnt;
- for(cnt=j=0; j<nVector; j++) if( aiMap[j]==i ) cnt++;
- assert( cnt==1 );
- }
-#endif
-
- /* Code the LHS, the <expr> from "<expr> IN (...)". If the LHS is a
- ** vector, then it is stored in an array of nVector registers starting
- ** at r1.
- **
- ** sqlite3FindInIndex() might have reordered the fields of the LHS vector
- ** so that the fields are in the same order as an existing index. The
- ** aiMap[] array contains a mapping from the original LHS field order to
- ** the field order that matches the RHS index.
- */
- sqlite3ExprCachePush(pParse);
- rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
- for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
- if( i==nVector ){
- /* LHS fields are not reordered */
- rLhs = rLhsOrig;
- }else{
- /* Need to reorder the LHS fields according to aiMap */
- rLhs = sqlite3GetTempRange(pParse, nVector);
- for(i=0; i<nVector; i++){
- sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0);
- }
- }
-
- /* If sqlite3FindInIndex() did not find or create an index that is
- ** suitable for evaluating the IN operator, then evaluate using a
- ** sequence of comparisons.
- **
- ** This is step (1) in the in-operator.md optimized algorithm.
- */
- if( eType==IN_INDEX_NOOP ){
- ExprList *pList = pExpr->x.pList;
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- int labelOk = sqlite3VdbeMakeLabel(v);
- int r2, regToFree;
- int regCkNull = 0;
- int ii;
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- if( destIfNull!=destIfFalse ){
- regCkNull = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
- }
- for(ii=0; ii<pList->nExpr; ii++){
- r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, &regToFree);
- if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
- sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
- }
- if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
- sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2,
- (void*)pColl, P4_COLLSEQ);
- VdbeCoverageIf(v, ii<pList->nExpr-1);
- VdbeCoverageIf(v, ii==pList->nExpr-1);
- sqlite3VdbeChangeP5(v, zAff[0]);
- }else{
- assert( destIfNull==destIfFalse );
- sqlite3VdbeAddOp4(v, OP_Ne, rLhs, destIfFalse, r2,
- (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
- sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL);
- }
- sqlite3ReleaseTempReg(pParse, regToFree);
- }
- if( regCkNull ){
- sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
- sqlite3VdbeGoto(v, destIfFalse);
- }
- sqlite3VdbeResolveLabel(v, labelOk);
- sqlite3ReleaseTempReg(pParse, regCkNull);
- goto sqlite3ExprCodeIN_finished;
- }
-
- /* Step 2: Check to see if the LHS contains any NULL columns. If the
- ** LHS does contain NULLs then the result must be either FALSE or NULL.
- ** We will then skip the binary search of the RHS.
- */
- if( destIfNull==destIfFalse ){
- destStep2 = destIfFalse;
- }else{
- destStep2 = destStep6 = sqlite3VdbeMakeLabel(v);
- }
- for(i=0; i<nVector; i++){
- Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
- if( sqlite3ExprCanBeNull(p) ){
- sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
- VdbeCoverage(v);
- }
- }
-
- /* Step 3. The LHS is now known to be non-NULL. Do the binary search
- ** of the RHS using the LHS as a probe. If found, the result is
- ** true.
- */
- if( eType==IN_INDEX_ROWID ){
- /* In this case, the RHS is the ROWID of table b-tree and so we also
- ** know that the RHS is non-NULL. Hence, we combine steps 3 and 4
- ** into a single opcode. */
- sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, rLhs);
- VdbeCoverage(v);
- addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */
- }else{
- sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
- if( destIfFalse==destIfNull ){
- /* Combine Step 3 and Step 5 into a single opcode */
- sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse,
- rLhs, nVector); VdbeCoverage(v);
- goto sqlite3ExprCodeIN_finished;
- }
- /* Ordinary Step 3, for the case where FALSE and NULL are distinct */
- addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0,
- rLhs, nVector); VdbeCoverage(v);
- }
-
- /* Step 4. If the RHS is known to be non-NULL and we did not find
- ** an match on the search above, then the result must be FALSE.
- */
- if( rRhsHasNull && nVector==1 ){
- sqlite3VdbeAddOp2(v, OP_NotNull, rRhsHasNull, destIfFalse);
- VdbeCoverage(v);
- }
-
- /* Step 5. If we do not care about the difference between NULL and
- ** FALSE, then just return false.
- */
- if( destIfFalse==destIfNull ) sqlite3VdbeGoto(v, destIfFalse);
-
- /* Step 6: Loop through rows of the RHS. Compare each row to the LHS.
- ** If any comparison is NULL, then the result is NULL. If all
- ** comparisons are FALSE then the final result is FALSE.
- **
- ** For a scalar LHS, it is sufficient to check just the first row
- ** of the RHS.
- */
- if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6);
- addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
- VdbeCoverage(v);
- if( nVector>1 ){
- destNotNull = sqlite3VdbeMakeLabel(v);
- }else{
- /* For nVector==1, combine steps 6 and 7 by immediately returning
- ** FALSE if the first comparison is not NULL */
- destNotNull = destIfFalse;
- }
- for(i=0; i<nVector; i++){
- Expr *p;
- CollSeq *pColl;
- int r3 = sqlite3GetTempReg(pParse);
- p = sqlite3VectorFieldSubexpr(pLeft, i);
- pColl = sqlite3ExprCollSeq(pParse, p);
- sqlite3VdbeAddOp3(v, OP_Column, pExpr->iTable, i, r3);
- sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
- (void*)pColl, P4_COLLSEQ);
- VdbeCoverage(v);
- sqlite3ReleaseTempReg(pParse, r3);
- }
- sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
- if( nVector>1 ){
- sqlite3VdbeResolveLabel(v, destNotNull);
- sqlite3VdbeAddOp2(v, OP_Next, pExpr->iTable, addrTop+1);
- VdbeCoverage(v);
-
- /* Step 7: If we reach this point, we know that the result must
- ** be false. */
- sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
- }
-
- /* Jumps here in order to return true. */
- sqlite3VdbeJumpHere(v, addrTruthOp);
-
-sqlite3ExprCodeIN_finished:
- if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs);
- sqlite3ExprCachePop(pParse);
- VdbeComment((v, "end IN expr"));
-sqlite3ExprCodeIN_oom_error:
- sqlite3DbFree(pParse->db, aiMap);
- sqlite3DbFree(pParse->db, zAff);
-}
-#endif /* SQLITE_OMIT_SUBQUERY */
-
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/*
-** Generate an instruction that will put the floating point
-** value described by z[0..n-1] into register iMem.
-**
-** The z[] string will probably not be zero-terminated. But the
-** z[n] character is guaranteed to be something that does not look
-** like the continuation of the number.
-*/
-static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
- if( ALWAYS(z!=0) ){
- double value;
- sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
- assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
- if( negateFlag ) value = -value;
- sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL);
- }
-}
-#endif
-
-
-/*
-** Generate an instruction that will put the integer describe by
-** text z[0..n-1] into register iMem.
-**
-** Expr.u.zToken is always UTF8 and zero-terminated.
-*/
-static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
- Vdbe *v = pParse->pVdbe;
- if( pExpr->flags & EP_IntValue ){
- int i = pExpr->u.iValue;
- assert( i>=0 );
- if( negFlag ) i = -i;
- sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
- }else{
- int c;
- i64 value;
- const char *z = pExpr->u.zToken;
- assert( z!=0 );
- c = sqlite3DecOrHexToI64(z, &value);
- if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
-#ifdef SQLITE_OMIT_FLOATING_POINT
- sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
-#else
-#ifndef SQLITE_OMIT_HEX_INTEGER
- if( sqlite3_strnicmp(z,"0x",2)==0 ){
- sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z);
- }else
-#endif
- {
- codeReal(v, z, negFlag, iMem);
- }
-#endif
- }else{
- if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; }
- sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
- }
- }
-}
-
-/*
-** Erase column-cache entry number i
-*/
-static void cacheEntryClear(Parse *pParse, int i){
- if( pParse->aColCache[i].tempReg ){
- if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
- pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
- }
- }
- pParse->nColCache--;
- if( i<pParse->nColCache ){
- pParse->aColCache[i] = pParse->aColCache[pParse->nColCache];
- }
-}
-
-
-/*
-** Record in the column cache that a particular column from a
-** particular table is stored in a particular register.
-*/
-void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
- int i;
- int minLru;
- int idxLru;
- struct yColCache *p;
-
- /* Unless an error has occurred, register numbers are always positive. */
- assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed );
- assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
-
- /* The SQLITE_ColumnCache flag disables the column cache. This is used
- ** for testing only - to verify that SQLite always gets the same answer
- ** with and without the column cache.
- */
- if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
-
- /* First replace any existing entry.
- **
- ** Actually, the way the column cache is currently used, we are guaranteed
- ** that the object will never already be in cache. Verify this guarantee.
- */
-#ifndef NDEBUG
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- assert( p->iTable!=iTab || p->iColumn!=iCol );
- }
-#endif
-
- /* If the cache is already full, delete the least recently used entry */
- if( pParse->nColCache>=SQLITE_N_COLCACHE ){
- minLru = 0x7fffffff;
- idxLru = -1;
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
- if( p->lru<minLru ){
- idxLru = i;
- minLru = p->lru;
- }
- }
- p = &pParse->aColCache[idxLru];
- }else{
- p = &pParse->aColCache[pParse->nColCache++];
- }
-
- /* Add the new entry to the end of the cache */
- p->iLevel = pParse->iCacheLevel;
- p->iTable = iTab;
- p->iColumn = iCol;
- p->iReg = iReg;
- p->tempReg = 0;
- p->lru = pParse->iCacheCnt++;
-}
-
-/*
-** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
-** Purge the range of registers from the column cache.
-*/
-void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
- int i = 0;
- while( i<pParse->nColCache ){
- struct yColCache *p = &pParse->aColCache[i];
- if( p->iReg >= iReg && p->iReg < iReg+nReg ){
- cacheEntryClear(pParse, i);
- }else{
- i++;
- }
- }
-}
-
-/*
-** Remember the current column cache context. Any new entries added
-** added to the column cache after this call are removed when the
-** corresponding pop occurs.
-*/
-void sqlite3ExprCachePush(Parse *pParse){
- pParse->iCacheLevel++;
-#ifdef SQLITE_DEBUG
- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
- printf("PUSH to %d\n", pParse->iCacheLevel);
- }
-#endif
-}
-
-/*
-** Remove from the column cache any entries that were added since the
-** the previous sqlite3ExprCachePush operation. In other words, restore
-** the cache to the state it was in prior the most recent Push.
-*/
-void sqlite3ExprCachePop(Parse *pParse){
- int i = 0;
- assert( pParse->iCacheLevel>=1 );
- pParse->iCacheLevel--;
-#ifdef SQLITE_DEBUG
- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
- printf("POP to %d\n", pParse->iCacheLevel);
- }
-#endif
- while( i<pParse->nColCache ){
- if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){
- cacheEntryClear(pParse, i);
- }else{
- i++;
- }
- }
-}
-
-/*
-** When a cached column is reused, make sure that its register is
-** no longer available as a temp register. ticket #3879: that same
-** register might be in the cache in multiple places, so be sure to
-** get them all.
-*/
-static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
- int i;
- struct yColCache *p;
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- if( p->iReg==iReg ){
- p->tempReg = 0;
- }
- }
-}
-
-/* Generate code that will load into register regOut a value that is
-** appropriate for the iIdxCol-th column of index pIdx.
-*/
-void sqlite3ExprCodeLoadIndexColumn(
- Parse *pParse, /* The parsing context */
- Index *pIdx, /* The index whose column is to be loaded */
- int iTabCur, /* Cursor pointing to a table row */
- int iIdxCol, /* The column of the index to be loaded */
- int regOut /* Store the index column value in this register */
-){
- i16 iTabCol = pIdx->aiColumn[iIdxCol];
- if( iTabCol==XN_EXPR ){
- assert( pIdx->aColExpr );
- assert( pIdx->aColExpr->nExpr>iIdxCol );
- pParse->iSelfTab = iTabCur + 1;
- sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
- pParse->iSelfTab = 0;
- }else{
- sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
- iTabCol, regOut);
- }
-}
-
-/*
-** Generate code to extract the value of the iCol-th column of a table.
-*/
-void sqlite3ExprCodeGetColumnOfTable(
- Vdbe *v, /* The VDBE under construction */
- Table *pTab, /* The table containing the value */
- int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */
- int iCol, /* Index of the column to extract */
- int regOut /* Extract the value into this register */
-){
- if( pTab==0 ){
- sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
- return;
- }
- if( iCol<0 || iCol==pTab->iPKey ){
- sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
- }else{
- int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
- int x = iCol;
- if( !HasRowid(pTab) && !IsVirtual(pTab) ){
- x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
- }
- sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
- }
- if( iCol>=0 ){
- sqlite3ColumnDefault(v, pTab, iCol, regOut);
- }
-}
-
-/*
-** Generate code that will extract the iColumn-th column from
-** table pTab and store the column value in a register.
-**
-** An effort is made to store the column value in register iReg. This
-** is not garanteeed for GetColumn() - the result can be stored in
-** any register. But the result is guaranteed to land in register iReg
-** for GetColumnToReg().
-**
-** There must be an open cursor to pTab in iTable when this routine
-** is called. If iColumn<0 then code is generated that extracts the rowid.
-*/
-int sqlite3ExprCodeGetColumn(
- Parse *pParse, /* Parsing and code generating context */
- Table *pTab, /* Description of the table we are reading from */
- int iColumn, /* Index of the table column */
- int iTable, /* The cursor pointing to the table */
- int iReg, /* Store results here */
- u8 p5 /* P5 value for OP_Column + FLAGS */
-){
- Vdbe *v = pParse->pVdbe;
- int i;
- struct yColCache *p;
-
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- if( p->iTable==iTable && p->iColumn==iColumn ){
- p->lru = pParse->iCacheCnt++;
- sqlite3ExprCachePinRegister(pParse, p->iReg);
- return p->iReg;
- }
- }
- assert( v!=0 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
- if( p5 ){
- sqlite3VdbeChangeP5(v, p5);
- }else{
- sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
- }
- return iReg;
-}
-void sqlite3ExprCodeGetColumnToReg(
- Parse *pParse, /* Parsing and code generating context */
- Table *pTab, /* Description of the table we are reading from */
- int iColumn, /* Index of the table column */
- int iTable, /* The cursor pointing to the table */
- int iReg /* Store results here */
-){
- int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0);
- if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg);
-}
-
-
-/*
-** Clear all column cache entries.
-*/
-void sqlite3ExprCacheClear(Parse *pParse){
- int i;
-
-#ifdef SQLITE_DEBUG
- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
- printf("CLEAR\n");
- }
-#endif
- for(i=0; i<pParse->nColCache; i++){
- if( pParse->aColCache[i].tempReg
- && pParse->nTempReg<ArraySize(pParse->aTempReg)
- ){
- pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
- }
- }
- pParse->nColCache = 0;
-}
-
-/*
-** Record the fact that an affinity change has occurred on iCount
-** registers starting with iStart.
-*/
-void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
- sqlite3ExprCacheRemove(pParse, iStart, iCount);
-}
-
-/*
-** Generate code to move content from registers iFrom...iFrom+nReg-1
-** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
-*/
-void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
- assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
- sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
- sqlite3ExprCacheRemove(pParse, iFrom, nReg);
-}
-
-#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
-/*
-** Return true if any register in the range iFrom..iTo (inclusive)
-** is used as part of the column cache.
-**
-** This routine is used within assert() and testcase() macros only
-** and does not appear in a normal build.
-*/
-static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
- int i;
- struct yColCache *p;
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- int r = p->iReg;
- if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
- }
- return 0;
-}
-#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
-
-
-/*
-** Convert a scalar expression node to a TK_REGISTER referencing
-** register iReg. The caller must ensure that iReg already contains
-** the correct value for the expression.
-*/
-static void exprToRegister(Expr *p, int iReg){
- p->op2 = p->op;
- p->op = TK_REGISTER;
- p->iTable = iReg;
- ExprClearProperty(p, EP_Skip);
-}
-
-/*
-** Evaluate an expression (either a vector or a scalar expression) and store
-** the result in continguous temporary registers. Return the index of
-** the first register used to store the result.
-**
-** If the returned result register is a temporary scalar, then also write
-** that register number into *piFreeable. If the returned result register
-** is not a temporary or if the expression is a vector set *piFreeable
-** to 0.
-*/
-static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
- int iResult;
- int nResult = sqlite3ExprVectorSize(p);
- if( nResult==1 ){
- iResult = sqlite3ExprCodeTemp(pParse, p, piFreeable);
- }else{
- *piFreeable = 0;
- if( p->op==TK_SELECT ){
-#if SQLITE_OMIT_SUBQUERY
- iResult = 0;
-#else
- iResult = sqlite3CodeSubselect(pParse, p, 0, 0);
-#endif
- }else{
- int i;
- iResult = pParse->nMem+1;
- pParse->nMem += nResult;
- for(i=0; i<nResult; i++){
- sqlite3ExprCodeFactorable(pParse, p->x.pList->a[i].pExpr, i+iResult);
- }
- }
- }
- return iResult;
-}
-
-
-/*
-** Generate code into the current Vdbe to evaluate the given
-** expression. Attempt to store the results in register "target".
-** Return the register where results are stored.
-**
-** With this routine, there is no guarantee that results will
-** be stored in target. The result might be stored in some other
-** register if it is convenient to do so. The calling function
-** must check the return code and move the results to the desired
-** register.
-*/
-int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
- Vdbe *v = pParse->pVdbe; /* The VM under construction */
- int op; /* The opcode being coded */
- int inReg = target; /* Results stored in register inReg */
- int regFree1 = 0; /* If non-zero free this temporary register */
- int regFree2 = 0; /* If non-zero free this temporary register */
- int r1, r2; /* Various register numbers */
- Expr tempX; /* Temporary expression node */
- int p5 = 0;
-
- assert( target>0 && target<=pParse->nMem );
- if( v==0 ){
- assert( pParse->db->mallocFailed );
- return 0;
- }
-
-expr_code_doover:
- if( pExpr==0 ){
- op = TK_NULL;
- }else{
- op = pExpr->op;
- }
- switch( op ){
- case TK_AGG_COLUMN: {
- AggInfo *pAggInfo = pExpr->pAggInfo;
- struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
- if( !pAggInfo->directMode ){
- assert( pCol->iMem>0 );
- return pCol->iMem;
- }else if( pAggInfo->useSortingIdx ){
- sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
- pCol->iSorterColumn, target);
- return target;
- }
- /* Otherwise, fall thru into the TK_COLUMN case */
- }
- case TK_COLUMN: {
- int iTab = pExpr->iTable;
- if( iTab<0 ){
- if( pParse->iSelfTab<0 ){
- /* Generating CHECK constraints or inserting into partial index */
- return pExpr->iColumn - pParse->iSelfTab;
- }else{
- /* Coding an expression that is part of an index where column names
- ** in the index refer to the table to which the index belongs */
- iTab = pParse->iSelfTab - 1;
- }
- }
- return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
- pExpr->iColumn, iTab, target,
- pExpr->op2);
- }
- case TK_INTEGER: {
- codeInteger(pParse, pExpr, 0, target);
- return target;
- }
- case TK_TRUEFALSE: {
- sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target);
- return target;
- }
-#ifndef SQLITE_OMIT_FLOATING_POINT
- case TK_FLOAT: {
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- codeReal(v, pExpr->u.zToken, 0, target);
- return target;
- }
-#endif
- case TK_STRING: {
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
- return target;
- }
- case TK_NULL: {
- sqlite3VdbeAddOp2(v, OP_Null, 0, target);
- return target;
- }
-#ifndef SQLITE_OMIT_BLOB_LITERAL
- case TK_BLOB: {
- int n;
- const char *z;
- char *zBlob;
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
- assert( pExpr->u.zToken[1]=='\'' );
- z = &pExpr->u.zToken[2];
- n = sqlite3Strlen30(z) - 1;
- assert( z[n]=='\'' );
- zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
- sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
- return target;
- }
-#endif
- case TK_VARIABLE: {
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- assert( pExpr->u.zToken!=0 );
- assert( pExpr->u.zToken[0]!=0 );
- sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
- if( pExpr->u.zToken[1]!=0 ){
- const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
- assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 );
- pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
- sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
- }
- return target;
- }
- case TK_REGISTER: {
- return pExpr->iTable;
- }
-#ifndef SQLITE_OMIT_CAST
- case TK_CAST: {
- /* Expressions of the form: CAST(pLeft AS token) */
- inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
- if( inReg!=target ){
- sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
- inReg = target;
- }
- sqlite3VdbeAddOp2(v, OP_Cast, target,
- sqlite3AffinityType(pExpr->u.zToken, 0));
- testcase( usedAsColumnCache(pParse, inReg, inReg) );
- sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
- return inReg;
- }
-#endif /* SQLITE_OMIT_CAST */
- case TK_IS:
- case TK_ISNOT:
- op = (op==TK_IS) ? TK_EQ : TK_NE;
- p5 = SQLITE_NULLEQ;
- /* fall-through */
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_NE:
- case TK_EQ: {
- Expr *pLeft = pExpr->pLeft;
- if( sqlite3ExprIsVector(pLeft) ){
- codeVectorCompare(pParse, pExpr, target, op, p5);
- }else{
- r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
- codeCompare(pParse, pLeft, pExpr->pRight, op,
- r1, r2, inReg, SQLITE_STOREP2 | p5);
- assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
- assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
- assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
- assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
- assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
- assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
- testcase( regFree1==0 );
- testcase( regFree2==0 );
- }
- break;
- }
- case TK_AND:
- case TK_OR:
- case TK_PLUS:
- case TK_STAR:
- case TK_MINUS:
- case TK_REM:
- case TK_BITAND:
- case TK_BITOR:
- case TK_SLASH:
- case TK_LSHIFT:
- case TK_RSHIFT:
- case TK_CONCAT: {
- assert( TK_AND==OP_And ); testcase( op==TK_AND );
- assert( TK_OR==OP_Or ); testcase( op==TK_OR );
- assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS );
- assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS );
- assert( TK_REM==OP_Remainder ); testcase( op==TK_REM );
- assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND );
- assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR );
- assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH );
- assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT );
- assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
- assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
- sqlite3VdbeAddOp3(v, op, r2, r1, target);
- testcase( regFree1==0 );
- testcase( regFree2==0 );
- break;
- }
- case TK_UMINUS: {
- Expr *pLeft = pExpr->pLeft;
- assert( pLeft );
- if( pLeft->op==TK_INTEGER ){
- codeInteger(pParse, pLeft, 1, target);
- return target;
-#ifndef SQLITE_OMIT_FLOATING_POINT
- }else if( pLeft->op==TK_FLOAT ){
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- codeReal(v, pLeft->u.zToken, 1, target);
- return target;
-#endif
- }else{
- tempX.op = TK_INTEGER;
- tempX.flags = EP_IntValue|EP_TokenOnly;
- tempX.u.iValue = 0;
- r1 = sqlite3ExprCodeTemp(pParse, &tempX, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
- sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
- testcase( regFree2==0 );
- }
- break;
- }
- case TK_BITNOT:
- case TK_NOT: {
- assert( TK_BITNOT==OP_BitNot ); testcase( op==TK_BITNOT );
- assert( TK_NOT==OP_Not ); testcase( op==TK_NOT );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- testcase( regFree1==0 );
- sqlite3VdbeAddOp2(v, op, r1, inReg);
- break;
- }
- case TK_TRUTH: {
- int isTrue; /* IS TRUE or IS NOT TRUE */
- int bNormal; /* IS TRUE or IS FALSE */
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- testcase( regFree1==0 );
- isTrue = sqlite3ExprTruthValue(pExpr->pRight);
- bNormal = pExpr->op2==TK_IS;
- testcase( isTrue && bNormal);
- testcase( !isTrue && bNormal);
- sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal);
- break;
- }
- case TK_ISNULL:
- case TK_NOTNULL: {
- int addr;
- assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
- assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
- sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- testcase( regFree1==0 );
- addr = sqlite3VdbeAddOp1(v, op, r1);
- VdbeCoverageIf(v, op==TK_ISNULL);
- VdbeCoverageIf(v, op==TK_NOTNULL);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
- sqlite3VdbeJumpHere(v, addr);
- break;
- }
- case TK_AGG_FUNCTION: {
- AggInfo *pInfo = pExpr->pAggInfo;
- if( pInfo==0 ){
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
- }else{
- return pInfo->aFunc[pExpr->iAgg].iMem;
- }
- break;
- }
- case TK_FUNCTION: {
- ExprList *pFarg; /* List of function arguments */
- int nFarg; /* Number of function arguments */
- FuncDef *pDef; /* The function definition object */
- const char *zId; /* The function name */
- u32 constMask = 0; /* Mask of function arguments that are constant */
- int i; /* Loop counter */
- sqlite3 *db = pParse->db; /* The database connection */
- u8 enc = ENC(db); /* The text encoding used by this database */
- CollSeq *pColl = 0; /* A collating sequence */
-
- if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
- /* SQL functions can be expensive. So try to move constant functions
- ** out of the inner loop, even if that means an extra OP_Copy. */
- return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
- }
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- if( ExprHasProperty(pExpr, EP_TokenOnly) ){
- pFarg = 0;
- }else{
- pFarg = pExpr->x.pList;
- }
- nFarg = pFarg ? pFarg->nExpr : 0;
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- zId = pExpr->u.zToken;
- pDef = sqlite3FindFunction(db, zId, nFarg, enc, 0);
-#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- if( pDef==0 && pParse->explain ){
- pDef = sqlite3FindFunction(db, "unknown", nFarg, enc, 0);
- }
-#endif
- if( pDef==0 || pDef->xFinalize!=0 ){
- sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
- break;
- }
-
- /* Attempt a direct implementation of the built-in COALESCE() and
- ** IFNULL() functions. This avoids unnecessary evaluation of
- ** arguments past the first non-NULL argument.
- */
- if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
- int endCoalesce = sqlite3VdbeMakeLabel(v);
- assert( nFarg>=2 );
- sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
- for(i=1; i<nFarg; i++){
- sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
- VdbeCoverage(v);
- sqlite3ExprCacheRemove(pParse, target, 1);
- sqlite3ExprCachePush(pParse);
- sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
- sqlite3ExprCachePop(pParse);
- }
- sqlite3VdbeResolveLabel(v, endCoalesce);
- break;
- }
-
- /* The UNLIKELY() function is a no-op. The result is the value
- ** of the first argument.
- */
- if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
- assert( nFarg>=1 );
- return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
- }
-
-#ifdef SQLITE_DEBUG
- /* The AFFINITY() function evaluates to a string that describes
- ** the type affinity of the argument. This is used for testing of
- ** the SQLite type logic.
- */
- if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
- const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
- char aff;
- assert( nFarg==1 );
- aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
- sqlite3VdbeLoadString(v, target,
- aff ? azAff[aff-SQLITE_AFF_BLOB] : "none");
- return target;
- }
-#endif
-
- for(i=0; i<nFarg; i++){
- if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
- testcase( i==31 );
- constMask |= MASKBIT32(i);
- }
- if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
- pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
- }
- }
- if( pFarg ){
- if( constMask ){
- r1 = pParse->nMem+1;
- pParse->nMem += nFarg;
- }else{
- r1 = sqlite3GetTempRange(pParse, nFarg);
- }
-
- /* For length() and typeof() functions with a column argument,
- ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
- ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
- ** loading.
- */
- if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
- u8 exprOp;
- assert( nFarg==1 );
- assert( pFarg->a[0].pExpr!=0 );
- exprOp = pFarg->a[0].pExpr->op;
- if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
- assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
- assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
- testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
- pFarg->a[0].pExpr->op2 =
- pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
- }
- }
-
- sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
- sqlite3ExprCodeExprList(pParse, pFarg, r1, 0,
- SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
- sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */
- }else{
- r1 = 0;
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- /* Possibly overload the function if the first argument is
- ** a virtual table column.
- **
- ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the
- ** second argument, not the first, as the argument to test to
- ** see if it is a column in a virtual table. This is done because
- ** the left operand of infix functions (the operand we want to
- ** control overloading) ends up as the second argument to the
- ** function. The expression "A glob B" is equivalent to
- ** "glob(B,A). We want to use the A in "A glob B" to test
- ** for function overloading. But we use the B term in "glob(B,A)".
- */
- if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){
- pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr);
- }else if( nFarg>0 ){
- pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
- }
-#endif
- if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
- if( !pColl ) pColl = db->pDfltColl;
- sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
- }
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
- if( pDef->funcFlags & SQLITE_FUNC_OFFSET ){
- Expr *pArg = pFarg->a[0].pExpr;
- if( pArg->op==TK_COLUMN ){
- sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
- }else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, target);
- }
- }else
-#endif
- {
- sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0,
- constMask, r1, target, (char*)pDef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nFarg);
- }
- if( nFarg && constMask==0 ){
- sqlite3ReleaseTempRange(pParse, r1, nFarg);
- }
- return target;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_EXISTS:
- case TK_SELECT: {
- int nCol;
- testcase( op==TK_EXISTS );
- testcase( op==TK_SELECT );
- if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
- sqlite3SubselectError(pParse, nCol, 1);
- }else{
- return sqlite3CodeSubselect(pParse, pExpr, 0, 0);
- }
- break;
- }
- case TK_SELECT_COLUMN: {
- int n;
- if( pExpr->pLeft->iTable==0 ){
- pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
- }
- assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
- if( pExpr->iTable
- && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
- ){
- sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
- pExpr->iTable, n);
- }
- return pExpr->pLeft->iTable + pExpr->iColumn;
- }
- case TK_IN: {
- int destIfFalse = sqlite3VdbeMakeLabel(v);
- int destIfNull = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp2(v, OP_Null, 0, target);
- sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
- sqlite3VdbeResolveLabel(v, destIfFalse);
- sqlite3VdbeAddOp2(v, OP_AddImm, target, 0);
- sqlite3VdbeResolveLabel(v, destIfNull);
- return target;
- }
-#endif /* SQLITE_OMIT_SUBQUERY */
-
-
- /*
- ** x BETWEEN y AND z
- **
- ** This is equivalent to
- **
- ** x>=y AND x<=z
- **
- ** X is stored in pExpr->pLeft.
- ** Y is stored in pExpr->pList->a[0].pExpr.
- ** Z is stored in pExpr->pList->a[1].pExpr.
- */
- case TK_BETWEEN: {
- exprCodeBetween(pParse, pExpr, target, 0, 0);
- return target;
- }
- case TK_SPAN:
- case TK_COLLATE:
- case TK_UPLUS: {
- pExpr = pExpr->pLeft;
- goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */
- }
-
- case TK_TRIGGER: {
- /* If the opcode is TK_TRIGGER, then the expression is a reference
- ** to a column in the new.* or old.* pseudo-tables available to
- ** trigger programs. In this case Expr.iTable is set to 1 for the
- ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
- ** is set to the column of the pseudo-table to read, or to -1 to
- ** read the rowid field.
- **
- ** The expression is implemented using an OP_Param opcode. The p1
- ** parameter is set to 0 for an old.rowid reference, or to (i+1)
- ** to reference another column of the old.* pseudo-table, where
- ** i is the index of the column. For a new.rowid reference, p1 is
- ** set to (n+1), where n is the number of columns in each pseudo-table.
- ** For a reference to any other column in the new.* pseudo-table, p1
- ** is set to (n+2+i), where n and i are as defined previously. For
- ** example, if the table on which triggers are being fired is
- ** declared as:
- **
- ** CREATE TABLE t1(a, b);
- **
- ** Then p1 is interpreted as follows:
- **
- ** p1==0 -> old.rowid p1==3 -> new.rowid
- ** p1==1 -> old.a p1==4 -> new.a
- ** p1==2 -> old.b p1==5 -> new.b
- */
- Table *pTab = pExpr->pTab;
- int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
-
- assert( pExpr->iTable==0 || pExpr->iTable==1 );
- assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
- assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey );
- assert( p1>=0 && p1<(pTab->nCol*2+2) );
-
- sqlite3VdbeAddOp2(v, OP_Param, p1, target);
- VdbeComment((v, "r[%d]=%s.%s", target,
- (pExpr->iTable ? "new" : "old"),
- (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
- ));
-
-#ifndef SQLITE_OMIT_FLOATING_POINT
- /* If the column has REAL affinity, it may currently be stored as an
- ** integer. Use OP_RealAffinity to make sure it is really real.
- **
- ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to
- ** floating point when extracting it from the record. */
- if( pExpr->iColumn>=0
- && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
- ){
- sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
- }
-#endif
- break;
- }
-
- case TK_VECTOR: {
- sqlite3ErrorMsg(pParse, "row value misused");
- break;
- }
-
- case TK_IF_NULL_ROW: {
- int addrINR;
- addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
- sqlite3ExprCachePush(pParse);
- inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
- sqlite3ExprCachePop(pParse);
- sqlite3VdbeJumpHere(v, addrINR);
- sqlite3VdbeChangeP3(v, addrINR, inReg);
- break;
- }
-
- /*
- ** Form A:
- ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
- **
- ** Form B:
- ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
- **
- ** Form A is can be transformed into the equivalent form B as follows:
- ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ...
- ** WHEN x=eN THEN rN ELSE y END
- **
- ** X (if it exists) is in pExpr->pLeft.
- ** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is
- ** odd. The Y is also optional. If the number of elements in x.pList
- ** is even, then Y is omitted and the "otherwise" result is NULL.
- ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
- **
- ** The result of the expression is the Ri for the first matching Ei,
- ** or if there is no matching Ei, the ELSE term Y, or if there is
- ** no ELSE term, NULL.
- */
- default: assert( op==TK_CASE ); {
- int endLabel; /* GOTO label for end of CASE stmt */
- int nextCase; /* GOTO label for next WHEN clause */
- int nExpr; /* 2x number of WHEN terms */
- int i; /* Loop counter */
- ExprList *pEList; /* List of WHEN terms */
- struct ExprList_item *aListelem; /* Array of WHEN terms */
- Expr opCompare; /* The X==Ei expression */
- Expr *pX; /* The X expression */
- Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
- VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
-
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
- assert(pExpr->x.pList->nExpr > 0);
- pEList = pExpr->x.pList;
- aListelem = pEList->a;
- nExpr = pEList->nExpr;
- endLabel = sqlite3VdbeMakeLabel(v);
- if( (pX = pExpr->pLeft)!=0 ){
- tempX = *pX;
- testcase( pX->op==TK_COLUMN );
- exprToRegister(&tempX, exprCodeVector(pParse, &tempX, &regFree1));
- testcase( regFree1==0 );
- memset(&opCompare, 0, sizeof(opCompare));
- opCompare.op = TK_EQ;
- opCompare.pLeft = &tempX;
- pTest = &opCompare;
- /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
- ** The value in regFree1 might get SCopy-ed into the file result.
- ** So make sure that the regFree1 register is not reused for other
- ** purposes and possibly overwritten. */
- regFree1 = 0;
- }
- for(i=0; i<nExpr-1; i=i+2){
- sqlite3ExprCachePush(pParse);
- if( pX ){
- assert( pTest!=0 );
- opCompare.pRight = aListelem[i].pExpr;
- }else{
- pTest = aListelem[i].pExpr;
- }
- nextCase = sqlite3VdbeMakeLabel(v);
- testcase( pTest->op==TK_COLUMN );
- sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
- testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
- sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
- sqlite3VdbeGoto(v, endLabel);
- sqlite3ExprCachePop(pParse);
- sqlite3VdbeResolveLabel(v, nextCase);
- }
- if( (nExpr&1)!=0 ){
- sqlite3ExprCachePush(pParse);
- sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
- sqlite3ExprCachePop(pParse);
- }else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, target);
- }
- assert( pParse->db->mallocFailed || pParse->nErr>0
- || pParse->iCacheLevel==iCacheLevel );
- sqlite3VdbeResolveLabel(v, endLabel);
- break;
- }
-#ifndef SQLITE_OMIT_TRIGGER
- case TK_RAISE: {
- assert( pExpr->affinity==OE_Rollback
- || pExpr->affinity==OE_Abort
- || pExpr->affinity==OE_Fail
- || pExpr->affinity==OE_Ignore
- );
- if( !pParse->pTriggerTab ){
- sqlite3ErrorMsg(pParse,
- "RAISE() may only be used within a trigger-program");
- return 0;
- }
- if( pExpr->affinity==OE_Abort ){
- sqlite3MayAbort(pParse);
- }
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- if( pExpr->affinity==OE_Ignore ){
- sqlite3VdbeAddOp4(
- v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
- VdbeCoverage(v);
- }else{
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
- pExpr->affinity, pExpr->u.zToken, 0, 0);
- }
-
- break;
- }
-#endif
- }
- sqlite3ReleaseTempReg(pParse, regFree1);
- sqlite3ReleaseTempReg(pParse, regFree2);
- return inReg;
-}
-
-/*
-** Factor out the code of the given expression to initialization time.
-**
-** If regDest>=0 then the result is always stored in that register and the
-** result is not reusable. If regDest<0 then this routine is free to
-** store the value whereever it wants. The register where the expression
-** is stored is returned. When regDest<0, two identical expressions will
-** code to the same register.
-*/
-int sqlite3ExprCodeAtInit(
- Parse *pParse, /* Parsing context */
- Expr *pExpr, /* The expression to code when the VDBE initializes */
- int regDest /* Store the value in this register */
-){
- ExprList *p;
- assert( ConstFactorOk(pParse) );
- p = pParse->pConstExpr;
- if( regDest<0 && p ){
- struct ExprList_item *pItem;
- int i;
- for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
- if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){
- return pItem->u.iConstExprReg;
- }
- }
- }
- pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
- p = sqlite3ExprListAppend(pParse, p, pExpr);
- if( p ){
- struct ExprList_item *pItem = &p->a[p->nExpr-1];
- pItem->reusable = regDest<0;
- if( regDest<0 ) regDest = ++pParse->nMem;
- pItem->u.iConstExprReg = regDest;
- }
- pParse->pConstExpr = p;
- return regDest;
-}
-
-/*
-** Generate code to evaluate an expression and store the results
-** into a register. Return the register number where the results
-** are stored.
-**
-** If the register is a temporary register that can be deallocated,
-** then write its number into *pReg. If the result register is not
-** a temporary, then set *pReg to zero.
-**
-** If pExpr is a constant, then this routine might generate this
-** code to fill the register in the initialization section of the
-** VDBE program, in order to factor it out of the evaluation loop.
-*/
-int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
- int r2;
- pExpr = sqlite3ExprSkipCollate(pExpr);
- if( ConstFactorOk(pParse)
- && pExpr->op!=TK_REGISTER
- && sqlite3ExprIsConstantNotJoin(pExpr)
- ){
- *pReg = 0;
- r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1);
- }else{
- int r1 = sqlite3GetTempReg(pParse);
- r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
- if( r2==r1 ){
- *pReg = r1;
- }else{
- sqlite3ReleaseTempReg(pParse, r1);
- *pReg = 0;
- }
- }
- return r2;
-}
-
-/*
-** Generate code that will evaluate expression pExpr and store the
-** results in register target. The results are guaranteed to appear
-** in register target.
-*/
-void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
- int inReg;
-
- assert( target>0 && target<=pParse->nMem );
- if( pExpr && pExpr->op==TK_REGISTER ){
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
- }else{
- inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
- assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
- if( inReg!=target && pParse->pVdbe ){
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
- }
- }
-}
-
-/*
-** Make a transient copy of expression pExpr and then code it using
-** sqlite3ExprCode(). This routine works just like sqlite3ExprCode()
-** except that the input expression is guaranteed to be unchanged.
-*/
-void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
- sqlite3 *db = pParse->db;
- pExpr = sqlite3ExprDup(db, pExpr, 0);
- if( !db->mallocFailed ) sqlite3ExprCode(pParse, pExpr, target);
- sqlite3ExprDelete(db, pExpr);
-}
-
-/*
-** Generate code that will evaluate expression pExpr and store the
-** results in register target. The results are guaranteed to appear
-** in register target. If the expression is constant, then this routine
-** might choose to code the expression at initialization time.
-*/
-void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
- if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){
- sqlite3ExprCodeAtInit(pParse, pExpr, target);
- }else{
- sqlite3ExprCode(pParse, pExpr, target);
- }
-}
-
-/*
-** Generate code that evaluates the given expression and puts the result
-** in register target.
-**
-** Also make a copy of the expression results into another "cache" register
-** and modify the expression so that the next time it is evaluated,
-** the result is a copy of the cache register.
-**
-** This routine is used for expressions that are used multiple
-** times. They are evaluated once and the results of the expression
-** are reused.
-*/
-void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
- Vdbe *v = pParse->pVdbe;
- int iMem;
-
- assert( target>0 );
- assert( pExpr->op!=TK_REGISTER );
- sqlite3ExprCode(pParse, pExpr, target);
- iMem = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
- exprToRegister(pExpr, iMem);
-}
-
-/*
-** Generate code that pushes the value of every element of the given
-** expression list into a sequence of registers beginning at target.
-**
-** Return the number of elements evaluated. The number returned will
-** usually be pList->nExpr but might be reduced if SQLITE_ECEL_OMITREF
-** is defined.
-**
-** The SQLITE_ECEL_DUP flag prevents the arguments from being
-** filled using OP_SCopy. OP_Copy must be used instead.
-**
-** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
-** factored out into initialization code.
-**
-** The SQLITE_ECEL_REF flag means that expressions in the list with
-** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored
-** in registers at srcReg, and so the value can be copied from there.
-** If SQLITE_ECEL_OMITREF is also set, then the values with u.x.iOrderByCol>0
-** are simply omitted rather than being copied from srcReg.
-*/
-int sqlite3ExprCodeExprList(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* The expression list to be coded */
- int target, /* Where to write results */
- int srcReg, /* Source registers if SQLITE_ECEL_REF */
- u8 flags /* SQLITE_ECEL_* flags */
-){
- struct ExprList_item *pItem;
- int i, j, n;
- u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
- Vdbe *v = pParse->pVdbe;
- assert( pList!=0 );
- assert( target>0 );
- assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */
- n = pList->nExpr;
- if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
- for(pItem=pList->a, i=0; i<n; i++, pItem++){
- Expr *pExpr = pItem->pExpr;
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( pItem->bSorterRef ){
- i--;
- n--;
- }else
-#endif
- if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){
- if( flags & SQLITE_ECEL_OMITREF ){
- i--;
- n--;
- }else{
- sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
- }
- }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
- sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
- }else{
- int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
- if( inReg!=target+i ){
- VdbeOp *pOp;
- if( copyOp==OP_Copy
- && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
- && pOp->p1+pOp->p3+1==inReg
- && pOp->p2+pOp->p3+1==target+i
- ){
- pOp->p3++;
- }else{
- sqlite3VdbeAddOp2(v, copyOp, inReg, target+i);
- }
- }
- }
- }
- return n;
-}
-
-/*
-** Generate code for a BETWEEN operator.
-**
-** x BETWEEN y AND z
-**
-** The above is equivalent to
-**
-** x>=y AND x<=z
-**
-** Code it as such, taking care to do the common subexpression
-** elimination of x.
-**
-** The xJumpIf parameter determines details:
-**
-** NULL: Store the boolean result in reg[dest]
-** sqlite3ExprIfTrue: Jump to dest if true
-** sqlite3ExprIfFalse: Jump to dest if false
-**
-** The jumpIfNull parameter is ignored if xJumpIf is NULL.
-*/
-static void exprCodeBetween(
- Parse *pParse, /* Parsing and code generating context */
- Expr *pExpr, /* The BETWEEN expression */
- int dest, /* Jump destination or storage location */
- void (*xJump)(Parse*,Expr*,int,int), /* Action to take */
- int jumpIfNull /* Take the jump if the BETWEEN is NULL */
-){
- Expr exprAnd; /* The AND operator in x>=y AND x<=z */
- Expr compLeft; /* The x>=y term */
- Expr compRight; /* The x<=z term */
- Expr exprX; /* The x subexpression */
- int regFree1 = 0; /* Temporary use register */
-
-
- memset(&compLeft, 0, sizeof(Expr));
- memset(&compRight, 0, sizeof(Expr));
- memset(&exprAnd, 0, sizeof(Expr));
-
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- exprX = *pExpr->pLeft;
- exprAnd.op = TK_AND;
- exprAnd.pLeft = &compLeft;
- exprAnd.pRight = &compRight;
- compLeft.op = TK_GE;
- compLeft.pLeft = &exprX;
- compLeft.pRight = pExpr->x.pList->a[0].pExpr;
- compRight.op = TK_LE;
- compRight.pLeft = &exprX;
- compRight.pRight = pExpr->x.pList->a[1].pExpr;
- exprToRegister(&exprX, exprCodeVector(pParse, &exprX, &regFree1));
- if( xJump ){
- xJump(pParse, &exprAnd, dest, jumpIfNull);
- }else{
- /* Mark the expression is being from the ON or USING clause of a join
- ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
- ** it into the Parse.pConstExpr list. We should use a new bit for this,
- ** for clarity, but we are out of bits in the Expr.flags field so we
- ** have to reuse the EP_FromJoin bit. Bummer. */
- exprX.flags |= EP_FromJoin;
- sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
- }
- sqlite3ReleaseTempReg(pParse, regFree1);
-
- /* Ensure adequate test coverage */
- testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 );
- testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1!=0 );
- testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1==0 );
- testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1!=0 );
- testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1==0 );
- testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1!=0 );
- testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1==0 );
- testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1!=0 );
- testcase( xJump==0 );
-}
-
-/*
-** Generate code for a boolean expression such that a jump is made
-** to the label "dest" if the expression is true but execution
-** continues straight thru if the expression is false.
-**
-** If the expression evaluates to NULL (neither true nor false), then
-** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL.
-**
-** This code depends on the fact that certain token values (ex: TK_EQ)
-** are the same as opcode values (ex: OP_Eq) that implement the corresponding
-** operation. Special comments in vdbe.c and the mkopcodeh.awk script in
-** the make process cause these values to align. Assert()s in the code
-** below verify that the numbers are aligned correctly.
-*/
-void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
- Vdbe *v = pParse->pVdbe;
- int op = 0;
- int regFree1 = 0;
- int regFree2 = 0;
- int r1, r2;
-
- assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
- if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
- if( NEVER(pExpr==0) ) return; /* No way this can happen */
- op = pExpr->op;
- switch( op ){
- case TK_AND: {
- int d2 = sqlite3VdbeMakeLabel(v);
- testcase( jumpIfNull==0 );
- sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
- sqlite3ExprCachePush(pParse);
- sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3VdbeResolveLabel(v, d2);
- sqlite3ExprCachePop(pParse);
- break;
- }
- case TK_OR: {
- testcase( jumpIfNull==0 );
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqlite3ExprCachePush(pParse);
- sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3ExprCachePop(pParse);
- break;
- }
- case TK_NOT: {
- testcase( jumpIfNull==0 );
- sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
- break;
- }
- case TK_TRUTH: {
- int isNot; /* IS NOT TRUE or IS NOT FALSE */
- int isTrue; /* IS TRUE or IS NOT TRUE */
- testcase( jumpIfNull==0 );
- isNot = pExpr->op2==TK_ISNOT;
- isTrue = sqlite3ExprTruthValue(pExpr->pRight);
- testcase( isTrue && isNot );
- testcase( !isTrue && isNot );
- if( isTrue ^ isNot ){
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest,
- isNot ? SQLITE_JUMPIFNULL : 0);
- }else{
- sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest,
- isNot ? SQLITE_JUMPIFNULL : 0);
- }
- break;
- }
- case TK_IS:
- case TK_ISNOT:
- testcase( op==TK_IS );
- testcase( op==TK_ISNOT );
- op = (op==TK_IS) ? TK_EQ : TK_NE;
- jumpIfNull = SQLITE_NULLEQ;
- /* Fall thru */
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_NE:
- case TK_EQ: {
- if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
- testcase( jumpIfNull==0 );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
- codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
- r1, r2, dest, jumpIfNull);
- assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
- assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
- assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
- assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
- assert(TK_EQ==OP_Eq); testcase(op==OP_Eq);
- VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ);
- VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ);
- assert(TK_NE==OP_Ne); testcase(op==OP_Ne);
- VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ);
- VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ);
- testcase( regFree1==0 );
- testcase( regFree2==0 );
- break;
- }
- case TK_ISNULL:
- case TK_NOTNULL: {
- assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
- assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- sqlite3VdbeAddOp2(v, op, r1, dest);
- VdbeCoverageIf(v, op==TK_ISNULL);
- VdbeCoverageIf(v, op==TK_NOTNULL);
- testcase( regFree1==0 );
- break;
- }
- case TK_BETWEEN: {
- testcase( jumpIfNull==0 );
- exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull);
- break;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_IN: {
- int destIfFalse = sqlite3VdbeMakeLabel(v);
- int destIfNull = jumpIfNull ? dest : destIfFalse;
- sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
- sqlite3VdbeGoto(v, dest);
- sqlite3VdbeResolveLabel(v, destIfFalse);
- break;
- }
-#endif
- default: {
- default_expr:
- if( exprAlwaysTrue(pExpr) ){
- sqlite3VdbeGoto(v, dest);
- }else if( exprAlwaysFalse(pExpr) ){
- /* No-op */
- }else{
- r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
- sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
- VdbeCoverage(v);
- testcase( regFree1==0 );
- testcase( jumpIfNull==0 );
- }
- break;
- }
- }
- sqlite3ReleaseTempReg(pParse, regFree1);
- sqlite3ReleaseTempReg(pParse, regFree2);
-}
-
-/*
-** Generate code for a boolean expression such that a jump is made
-** to the label "dest" if the expression is false but execution
-** continues straight thru if the expression is true.
-**
-** If the expression evaluates to NULL (neither true nor false) then
-** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull
-** is 0.
-*/
-void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
- Vdbe *v = pParse->pVdbe;
- int op = 0;
- int regFree1 = 0;
- int regFree2 = 0;
- int r1, r2;
-
- assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
- if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
- if( pExpr==0 ) return;
-
- /* The value of pExpr->op and op are related as follows:
- **
- ** pExpr->op op
- ** --------- ----------
- ** TK_ISNULL OP_NotNull
- ** TK_NOTNULL OP_IsNull
- ** TK_NE OP_Eq
- ** TK_EQ OP_Ne
- ** TK_GT OP_Le
- ** TK_LE OP_Gt
- ** TK_GE OP_Lt
- ** TK_LT OP_Ge
- **
- ** For other values of pExpr->op, op is undefined and unused.
- ** The value of TK_ and OP_ constants are arranged such that we
- ** can compute the mapping above using the following expression.
- ** Assert()s verify that the computation is correct.
- */
- op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1);
-
- /* Verify correct alignment of TK_ and OP_ constants
- */
- assert( pExpr->op!=TK_ISNULL || op==OP_NotNull );
- assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull );
- assert( pExpr->op!=TK_NE || op==OP_Eq );
- assert( pExpr->op!=TK_EQ || op==OP_Ne );
- assert( pExpr->op!=TK_LT || op==OP_Ge );
- assert( pExpr->op!=TK_LE || op==OP_Gt );
- assert( pExpr->op!=TK_GT || op==OP_Le );
- assert( pExpr->op!=TK_GE || op==OP_Lt );
-
- switch( pExpr->op ){
- case TK_AND: {
- testcase( jumpIfNull==0 );
- sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqlite3ExprCachePush(pParse);
- sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3ExprCachePop(pParse);
- break;
- }
- case TK_OR: {
- int d2 = sqlite3VdbeMakeLabel(v);
- testcase( jumpIfNull==0 );
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
- sqlite3ExprCachePush(pParse);
- sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3VdbeResolveLabel(v, d2);
- sqlite3ExprCachePop(pParse);
- break;
- }
- case TK_NOT: {
- testcase( jumpIfNull==0 );
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
- break;
- }
- case TK_TRUTH: {
- int isNot; /* IS NOT TRUE or IS NOT FALSE */
- int isTrue; /* IS TRUE or IS NOT TRUE */
- testcase( jumpIfNull==0 );
- isNot = pExpr->op2==TK_ISNOT;
- isTrue = sqlite3ExprTruthValue(pExpr->pRight);
- testcase( isTrue && isNot );
- testcase( !isTrue && isNot );
- if( isTrue ^ isNot ){
- /* IS TRUE and IS NOT FALSE */
- sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest,
- isNot ? 0 : SQLITE_JUMPIFNULL);
-
- }else{
- /* IS FALSE and IS NOT TRUE */
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest,
- isNot ? 0 : SQLITE_JUMPIFNULL);
- }
- break;
- }
- case TK_IS:
- case TK_ISNOT:
- testcase( pExpr->op==TK_IS );
- testcase( pExpr->op==TK_ISNOT );
- op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
- jumpIfNull = SQLITE_NULLEQ;
- /* Fall thru */
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_NE:
- case TK_EQ: {
- if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
- testcase( jumpIfNull==0 );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
- codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
- r1, r2, dest, jumpIfNull);
- assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
- assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
- assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
- assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
- assert(TK_EQ==OP_Eq); testcase(op==OP_Eq);
- VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ);
- VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ);
- assert(TK_NE==OP_Ne); testcase(op==OP_Ne);
- VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ);
- VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ);
- testcase( regFree1==0 );
- testcase( regFree2==0 );
- break;
- }
- case TK_ISNULL:
- case TK_NOTNULL: {
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- sqlite3VdbeAddOp2(v, op, r1, dest);
- testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
- testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
- testcase( regFree1==0 );
- break;
- }
- case TK_BETWEEN: {
- testcase( jumpIfNull==0 );
- exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfFalse, jumpIfNull);
- break;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_IN: {
- if( jumpIfNull ){
- sqlite3ExprCodeIN(pParse, pExpr, dest, dest);
- }else{
- int destIfNull = sqlite3VdbeMakeLabel(v);
- sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull);
- sqlite3VdbeResolveLabel(v, destIfNull);
- }
- break;
- }
-#endif
- default: {
- default_expr:
- if( exprAlwaysFalse(pExpr) ){
- sqlite3VdbeGoto(v, dest);
- }else if( exprAlwaysTrue(pExpr) ){
- /* no-op */
- }else{
- r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
- sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
- VdbeCoverage(v);
- testcase( regFree1==0 );
- testcase( jumpIfNull==0 );
- }
- break;
- }
- }
- sqlite3ReleaseTempReg(pParse, regFree1);
- sqlite3ReleaseTempReg(pParse, regFree2);
-}
-
-/*
-** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before
-** code generation, and that copy is deleted after code generation. This
-** ensures that the original pExpr is unchanged.
-*/
-void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){
- sqlite3 *db = pParse->db;
- Expr *pCopy = sqlite3ExprDup(db, pExpr, 0);
- if( db->mallocFailed==0 ){
- sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull);
- }
- sqlite3ExprDelete(db, pCopy);
-}
-
-/*
-** Expression pVar is guaranteed to be an SQL variable. pExpr may be any
-** type of expression.
-**
-** If pExpr is a simple SQL value - an integer, real, string, blob
-** or NULL value - then the VDBE currently being prepared is configured
-** to re-prepare each time a new value is bound to variable pVar.
-**
-** Additionally, if pExpr is a simple SQL value and the value is the
-** same as that currently bound to variable pVar, non-zero is returned.
-** Otherwise, if the values are not the same or if pExpr is not a simple
-** SQL value, zero is returned.
-*/
-static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
- int res = 0;
- int iVar;
- sqlite3_value *pL, *pR = 0;
-
- sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
- if( pR ){
- iVar = pVar->iColumn;
- sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
- pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
- if( pL ){
- if( sqlite3_value_type(pL)==SQLITE_TEXT ){
- sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
- }
- res = 0==sqlite3MemCompare(pL, pR, 0);
- }
- sqlite3ValueFree(pR);
- sqlite3ValueFree(pL);
- }
-
- return res;
-}
-
-/*
-** Do a deep comparison of two expression trees. Return 0 if the two
-** expressions are completely identical. Return 1 if they differ only
-** by a COLLATE operator at the top level. Return 2 if there are differences
-** other than the top-level COLLATE operator.
-**
-** If any subelement of pB has Expr.iTable==(-1) then it is allowed
-** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
-**
-** The pA side might be using TK_REGISTER. If that is the case and pB is
-** not using TK_REGISTER but is otherwise equivalent, then still return 0.
-**
-** Sometimes this routine will return 2 even if the two expressions
-** really are equivalent. If we cannot prove that the expressions are
-** identical, we return 2 just to be safe. So if this routine
-** returns 2, then you do not really know for certain if the two
-** expressions are the same. But if you get a 0 or 1 return, then you
-** can be sure the expressions are the same. In the places where
-** this routine is used, it does not hurt to get an extra 2 - that
-** just might result in some slightly slower code. But returning
-** an incorrect 0 or 1 could lead to a malfunction.
-**
-** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
-** pParse->pReprepare can be matched against literals in pB. The
-** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
-** If pParse is NULL (the normal case) then any TK_VARIABLE term in
-** Argument pParse should normally be NULL. If it is not NULL and pA or
-** pB causes a return value of 2.
-*/
-int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
- u32 combinedFlags;
- if( pA==0 || pB==0 ){
- return pB==pA ? 0 : 2;
- }
- if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
- return 0;
- }
- combinedFlags = pA->flags | pB->flags;
- if( combinedFlags & EP_IntValue ){
- if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
- return 0;
- }
- return 2;
- }
- if( pA->op!=pB->op ){
- if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
- return 1;
- }
- if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){
- return 1;
- }
- return 2;
- }
- if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
- if( pA->op==TK_FUNCTION ){
- if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
- }else if( pA->op==TK_COLLATE ){
- if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
- }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
- return 2;
- }
- }
- if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
- if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
- if( combinedFlags & EP_xIsSelect ) return 2;
- if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
- if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
- if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
- assert( (combinedFlags & EP_Reduced)==0 );
- if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
- if( pA->iColumn!=pB->iColumn ) return 2;
- if( pA->iTable!=pB->iTable
- && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
- }
- }
- return 0;
-}
-
-/*
-** Compare two ExprList objects. Return 0 if they are identical and
-** non-zero if they differ in any way.
-**
-** If any subelement of pB has Expr.iTable==(-1) then it is allowed
-** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
-**
-** This routine might return non-zero for equivalent ExprLists. The
-** only consequence will be disabled optimizations. But this routine
-** must never return 0 if the two ExprList objects are different, or
-** a malfunction will result.
-**
-** Two NULL pointers are considered to be the same. But a NULL pointer
-** always differs from a non-NULL pointer.
-*/
-int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
- int i;
- if( pA==0 && pB==0 ) return 0;
- if( pA==0 || pB==0 ) return 1;
- if( pA->nExpr!=pB->nExpr ) return 1;
- for(i=0; i<pA->nExpr; i++){
- Expr *pExprA = pA->a[i].pExpr;
- Expr *pExprB = pB->a[i].pExpr;
- if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
- if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1;
- }
- return 0;
-}
-
-/*
-** Like sqlite3ExprCompare() except COLLATE operators at the top-level
-** are ignored.
-*/
-int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
- return sqlite3ExprCompare(0,
- sqlite3ExprSkipCollate(pA),
- sqlite3ExprSkipCollate(pB),
- iTab);
-}
-
-/*
-** Return true if we can prove the pE2 will always be true if pE1 is
-** true. Return false if we cannot complete the proof or if pE2 might
-** be false. Examples:
-**
-** pE1: x==5 pE2: x==5 Result: true
-** pE1: x>0 pE2: x==5 Result: false
-** pE1: x=21 pE2: x=21 OR y=43 Result: true
-** pE1: x!=123 pE2: x IS NOT NULL Result: true
-** pE1: x!=?1 pE2: x IS NOT NULL Result: true
-** pE1: x IS NULL pE2: x IS NOT NULL Result: false
-** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false
-**
-** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
-** Expr.iTable<0 then assume a table number given by iTab.
-**
-** If pParse is not NULL, then the values of bound variables in pE1 are
-** compared against literal values in pE2 and pParse->pVdbe->expmask is
-** modified to record which bound variables are referenced. If pParse
-** is NULL, then false will be returned if pE1 contains any bound variables.
-**
-** When in doubt, return false. Returning true might give a performance
-** improvement. Returning false might cause a performance reduction, but
-** it will always give the correct answer and is hence always safe.
-*/
-int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
- if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
- return 1;
- }
- if( pE2->op==TK_OR
- && (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab)
- || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) )
- ){
- return 1;
- }
- if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){
- Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft);
- testcase( pX!=pE1->pLeft );
- if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1;
- }
- return 0;
-}
-
-/*
-** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
-** If the expression node requires that the table at pWalker->iCur
-** have a non-NULL column, then set pWalker->eCode to 1 and abort.
-*/
-static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
- /* This routine is only called for WHERE clause expressions and so it
- ** cannot have any TK_AGG_COLUMN entries because those are only found
- ** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause,
- ** but that is an illegal construct and the query will be rejected at
- ** a later stage of processing, so the TK_AGG_FUNCTION case does not
- ** need to be considered here. */
- assert( pExpr->op!=TK_AGG_COLUMN );
- testcase( pExpr->op==TK_AGG_FUNCTION );
-
- if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
- switch( pExpr->op ){
- case TK_ISNOT:
- case TK_NOT:
- case TK_ISNULL:
- case TK_IS:
- case TK_OR:
- case TK_CASE:
- case TK_IN:
- case TK_FUNCTION:
- testcase( pExpr->op==TK_ISNOT );
- testcase( pExpr->op==TK_NOT );
- testcase( pExpr->op==TK_ISNULL );
- testcase( pExpr->op==TK_IS );
- testcase( pExpr->op==TK_OR );
- testcase( pExpr->op==TK_CASE );
- testcase( pExpr->op==TK_IN );
- testcase( pExpr->op==TK_FUNCTION );
- return WRC_Prune;
- case TK_COLUMN:
- if( pWalker->u.iCur==pExpr->iTable ){
- pWalker->eCode = 1;
- return WRC_Abort;
- }
- return WRC_Prune;
-
- /* Virtual tables are allowed to use constraints like x=NULL. So
- ** a term of the form x=y does not prove that y is not null if x
- ** is the column of a virtual table */
- case TK_EQ:
- case TK_NE:
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- testcase( pExpr->op==TK_EQ );
- testcase( pExpr->op==TK_NE );
- testcase( pExpr->op==TK_LT );
- testcase( pExpr->op==TK_LE );
- testcase( pExpr->op==TK_GT );
- testcase( pExpr->op==TK_GE );
- if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
- || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
- ){
- return WRC_Prune;
- }
- default:
- return WRC_Continue;
- }
-}
-
-/*
-** Return true (non-zero) if expression p can only be true if at least
-** one column of table iTab is non-null. In other words, return true
-** if expression p will always be NULL or false if every column of iTab
-** is NULL.
-**
-** False negatives are acceptable. In other words, it is ok to return
-** zero even if expression p will never be true of every column of iTab
-** is NULL. A false negative is merely a missed optimization opportunity.
-**
-** False positives are not allowed, however. A false positive may result
-** in an incorrect answer.
-**
-** Terms of p that are marked with EP_FromJoin (and hence that come from
-** the ON or USING clauses of LEFT JOINS) are excluded from the analysis.
-**
-** This routine is used to check if a LEFT JOIN can be converted into
-** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE
-** clause requires that some column of the right table of the LEFT JOIN
-** be non-NULL, then the LEFT JOIN can be safely converted into an
-** ordinary join.
-*/
-int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
- Walker w;
- w.xExprCallback = impliesNotNullRow;
- w.xSelectCallback = 0;
- w.xSelectCallback2 = 0;
- w.eCode = 0;
- w.u.iCur = iTab;
- sqlite3WalkExpr(&w, p);
- return w.eCode;
-}
-
-/*
-** An instance of the following structure is used by the tree walker
-** to determine if an expression can be evaluated by reference to the
-** index only, without having to do a search for the corresponding
-** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur
-** is the cursor for the table.
-*/
-struct IdxCover {
- Index *pIdx; /* The index to be tested for coverage */
- int iCur; /* Cursor number for the table corresponding to the index */
-};
-
-/*
-** Check to see if there are references to columns in table
-** pWalker->u.pIdxCover->iCur can be satisfied using the index
-** pWalker->u.pIdxCover->pIdx.
-*/
-static int exprIdxCover(Walker *pWalker, Expr *pExpr){
- if( pExpr->op==TK_COLUMN
- && pExpr->iTable==pWalker->u.pIdxCover->iCur
- && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
- ){
- pWalker->eCode = 1;
- return WRC_Abort;
- }
- return WRC_Continue;
-}
-
-/*
-** Determine if an index pIdx on table with cursor iCur contains will
-** the expression pExpr. Return true if the index does cover the
-** expression and false if the pExpr expression references table columns
-** that are not found in the index pIdx.
-**
-** An index covering an expression means that the expression can be
-** evaluated using only the index and without having to lookup the
-** corresponding table entry.
-*/
-int sqlite3ExprCoveredByIndex(
- Expr *pExpr, /* The index to be tested */
- int iCur, /* The cursor number for the corresponding table */
- Index *pIdx /* The index that might be used for coverage */
-){
- Walker w;
- struct IdxCover xcov;
- memset(&w, 0, sizeof(w));
- xcov.iCur = iCur;
- xcov.pIdx = pIdx;
- w.xExprCallback = exprIdxCover;
- w.u.pIdxCover = &xcov;
- sqlite3WalkExpr(&w, pExpr);
- return !w.eCode;
-}
-
-
-/*
-** An instance of the following structure is used by the tree walker
-** to count references to table columns in the arguments of an
-** aggregate function, in order to implement the
-** sqlite3FunctionThisSrc() routine.
-*/
-struct SrcCount {
- SrcList *pSrc; /* One particular FROM clause in a nested query */
- int nThis; /* Number of references to columns in pSrcList */
- int nOther; /* Number of references to columns in other FROM clauses */
-};
-
-/*
-** Count the number of references to columns.
-*/
-static int exprSrcCount(Walker *pWalker, Expr *pExpr){
- /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
- ** is always called before sqlite3ExprAnalyzeAggregates() and so the
- ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If
- ** sqlite3FunctionUsesThisSrc() is used differently in the future, the
- ** NEVER() will need to be removed. */
- if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
- int i;
- struct SrcCount *p = pWalker->u.pSrcCount;
- SrcList *pSrc = p->pSrc;
- int nSrc = pSrc ? pSrc->nSrc : 0;
- for(i=0; i<nSrc; i++){
- if( pExpr->iTable==pSrc->a[i].iCursor ) break;
- }
- if( i<nSrc ){
- p->nThis++;
- }else{
- p->nOther++;
- }
- }
- return WRC_Continue;
-}
-
-/*
-** Determine if any of the arguments to the pExpr Function reference
-** pSrcList. Return true if they do. Also return true if the function
-** has no arguments or has only constant arguments. Return false if pExpr
-** references columns but not columns of tables found in pSrcList.
-*/
-int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
- Walker w;
- struct SrcCount cnt;
- assert( pExpr->op==TK_AGG_FUNCTION );
- w.xExprCallback = exprSrcCount;
- w.xSelectCallback = 0;
- w.u.pSrcCount = &cnt;
- cnt.pSrc = pSrcList;
- cnt.nThis = 0;
- cnt.nOther = 0;
- sqlite3WalkExprList(&w, pExpr->x.pList);
- return cnt.nThis>0 || cnt.nOther==0;
-}
-
-/*
-** Add a new element to the pAggInfo->aCol[] array. Return the index of
-** the new element. Return a negative number if malloc fails.
-*/
-static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
- int i;
- pInfo->aCol = sqlite3ArrayAllocate(
- db,
- pInfo->aCol,
- sizeof(pInfo->aCol[0]),
- &pInfo->nColumn,
- &i
- );
- return i;
-}
-
-/*
-** Add a new element to the pAggInfo->aFunc[] array. Return the index of
-** the new element. Return a negative number if malloc fails.
-*/
-static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
- int i;
- pInfo->aFunc = sqlite3ArrayAllocate(
- db,
- pInfo->aFunc,
- sizeof(pInfo->aFunc[0]),
- &pInfo->nFunc,
- &i
- );
- return i;
-}
-
-/*
-** This is the xExprCallback for a tree walker. It is used to
-** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
-** for additional information.
-*/
-static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
- int i;
- NameContext *pNC = pWalker->u.pNC;
- Parse *pParse = pNC->pParse;
- SrcList *pSrcList = pNC->pSrcList;
- AggInfo *pAggInfo = pNC->uNC.pAggInfo;
-
- assert( pNC->ncFlags & NC_UAggInfo );
- switch( pExpr->op ){
- case TK_AGG_COLUMN:
- case TK_COLUMN: {
- testcase( pExpr->op==TK_AGG_COLUMN );
- testcase( pExpr->op==TK_COLUMN );
- /* Check to see if the column is in one of the tables in the FROM
- ** clause of the aggregate query */
- if( ALWAYS(pSrcList!=0) ){
- struct SrcList_item *pItem = pSrcList->a;
- for(i=0; i<pSrcList->nSrc; i++, pItem++){
- struct AggInfo_col *pCol;
- assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
- if( pExpr->iTable==pItem->iCursor ){
- /* If we reach this point, it means that pExpr refers to a table
- ** that is in the FROM clause of the aggregate query.
- **
- ** Make an entry for the column in pAggInfo->aCol[] if there
- ** is not an entry there already.
- */
- int k;
- pCol = pAggInfo->aCol;
- for(k=0; k<pAggInfo->nColumn; k++, pCol++){
- if( pCol->iTable==pExpr->iTable &&
- pCol->iColumn==pExpr->iColumn ){
- break;
- }
- }
- if( (k>=pAggInfo->nColumn)
- && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
- ){
- pCol = &pAggInfo->aCol[k];
- pCol->pTab = pExpr->pTab;
- pCol->iTable = pExpr->iTable;
- pCol->iColumn = pExpr->iColumn;
- pCol->iMem = ++pParse->nMem;
- pCol->iSorterColumn = -1;
- pCol->pExpr = pExpr;
- if( pAggInfo->pGroupBy ){
- int j, n;
- ExprList *pGB = pAggInfo->pGroupBy;
- struct ExprList_item *pTerm = pGB->a;
- n = pGB->nExpr;
- for(j=0; j<n; j++, pTerm++){
- Expr *pE = pTerm->pExpr;
- if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable &&
- pE->iColumn==pExpr->iColumn ){
- pCol->iSorterColumn = j;
- break;
- }
- }
- }
- if( pCol->iSorterColumn<0 ){
- pCol->iSorterColumn = pAggInfo->nSortingColumn++;
- }
- }
- /* There is now an entry for pExpr in pAggInfo->aCol[] (either
- ** because it was there before or because we just created it).
- ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
- ** pAggInfo->aCol[] entry.
- */
- ExprSetVVAProperty(pExpr, EP_NoReduce);
- pExpr->pAggInfo = pAggInfo;
- pExpr->op = TK_AGG_COLUMN;
- pExpr->iAgg = (i16)k;
- break;
- } /* endif pExpr->iTable==pItem->iCursor */
- } /* end loop over pSrcList */
- }
- return WRC_Prune;
- }
- case TK_AGG_FUNCTION: {
- if( (pNC->ncFlags & NC_InAggFunc)==0
- && pWalker->walkerDepth==pExpr->op2
- ){
- /* Check to see if pExpr is a duplicate of another aggregate
- ** function that is already in the pAggInfo structure
- */
- struct AggInfo_func *pItem = pAggInfo->aFunc;
- for(i=0; i<pAggInfo->nFunc; i++, pItem++){
- if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){
- break;
- }
- }
- if( i>=pAggInfo->nFunc ){
- /* pExpr is original. Make a new entry in pAggInfo->aFunc[]
- */
- u8 enc = ENC(pParse->db);
- i = addAggInfoFunc(pParse->db, pAggInfo);
- if( i>=0 ){
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- pItem = &pAggInfo->aFunc[i];
- pItem->pExpr = pExpr;
- pItem->iMem = ++pParse->nMem;
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- pItem->pFunc = sqlite3FindFunction(pParse->db,
- pExpr->u.zToken,
- pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
- if( pExpr->flags & EP_Distinct ){
- pItem->iDistinct = pParse->nTab++;
- }else{
- pItem->iDistinct = -1;
- }
- }
- }
- /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
- */
- assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
- ExprSetVVAProperty(pExpr, EP_NoReduce);
- pExpr->iAgg = (i16)i;
- pExpr->pAggInfo = pAggInfo;
- return WRC_Prune;
- }else{
- return WRC_Continue;
- }
- }
- }
- return WRC_Continue;
-}
-static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
- UNUSED_PARAMETER(pSelect);
- pWalker->walkerDepth++;
- return WRC_Continue;
-}
-static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
- UNUSED_PARAMETER(pSelect);
- pWalker->walkerDepth--;
-}
-
-/*
-** Analyze the pExpr expression looking for aggregate functions and
-** for variables that need to be added to AggInfo object that pNC->pAggInfo
-** points to. Additional entries are made on the AggInfo object as
-** necessary.
-**
-** This routine should only be called after the expression has been
-** analyzed by sqlite3ResolveExprNames().
-*/
-void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
- Walker w;
- w.xExprCallback = analyzeAggregate;
- w.xSelectCallback = analyzeAggregatesInSelect;
- w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
- w.walkerDepth = 0;
- w.u.pNC = pNC;
- assert( pNC->pSrcList!=0 );
- sqlite3WalkExpr(&w, pExpr);
-}
-
-/*
-** Call sqlite3ExprAnalyzeAggregates() for every expression in an
-** expression list. Return the number of errors.
-**
-** If an error is found, the analysis is cut short.
-*/
-void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
- struct ExprList_item *pItem;
- int i;
- if( pList ){
- for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
- sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr);
- }
- }
-}
-
-/*
-** Allocate a single new register for use to hold some intermediate result.
-*/
-int sqlite3GetTempReg(Parse *pParse){
- if( pParse->nTempReg==0 ){
- return ++pParse->nMem;
- }
- return pParse->aTempReg[--pParse->nTempReg];
-}
-
-/*
-** Deallocate a register, making available for reuse for some other
-** purpose.
-**
-** If a register is currently being used by the column cache, then
-** the deallocation is deferred until the column cache line that uses
-** the register becomes stale.
-*/
-void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
- if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
- int i;
- struct yColCache *p;
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- if( p->iReg==iReg ){
- p->tempReg = 1;
- return;
- }
- }
- pParse->aTempReg[pParse->nTempReg++] = iReg;
- }
-}
-
-/*
-** Allocate or deallocate a block of nReg consecutive registers.
-*/
-int sqlite3GetTempRange(Parse *pParse, int nReg){
- int i, n;
- if( nReg==1 ) return sqlite3GetTempReg(pParse);
- i = pParse->iRangeReg;
- n = pParse->nRangeReg;
- if( nReg<=n ){
- assert( !usedAsColumnCache(pParse, i, i+n-1) );
- pParse->iRangeReg += nReg;
- pParse->nRangeReg -= nReg;
- }else{
- i = pParse->nMem+1;
- pParse->nMem += nReg;
- }
- return i;
-}
-void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
- if( nReg==1 ){
- sqlite3ReleaseTempReg(pParse, iReg);
- return;
- }
- sqlite3ExprCacheRemove(pParse, iReg, nReg);
- if( nReg>pParse->nRangeReg ){
- pParse->nRangeReg = nReg;
- pParse->iRangeReg = iReg;
- }
-}
-
-/*
-** Mark all temporary registers as being unavailable for reuse.
-*/
-void sqlite3ClearTempRegCache(Parse *pParse){
- pParse->nTempReg = 0;
- pParse->nRangeReg = 0;
-}
-
-/*
-** Validate that no temporary register falls within the range of
-** iFirst..iLast, inclusive. This routine is only call from within assert()
-** statements.
-*/
-#ifdef SQLITE_DEBUG
-int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){
- int i;
- if( pParse->nRangeReg>0
- && pParse->iRangeReg+pParse->nRangeReg > iFirst
- && pParse->iRangeReg <= iLast
- ){
- return 0;
- }
- for(i=0; i<pParse->nTempReg; i++){
- if( pParse->aTempReg[i]>=iFirst && pParse->aTempReg[i]<=iLast ){
- return 0;
- }
- }
- return 1;
-}
-#endif /* SQLITE_DEBUG */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/fault.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/fault.c
deleted file mode 100644
index 5b41b603639..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/fault.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-** 2008 Jan 22
-**
-** 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 contains code to support the concept of "benign"
-** malloc failures (when the xMalloc() or xRealloc() method of the
-** sqlite3_mem_methods structure fails to allocate a block of memory
-** and returns 0).
-**
-** Most malloc failures are non-benign. After they occur, SQLite
-** abandons the current operation and returns an error code (usually
-** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
-** fatal. For example, if a malloc fails while resizing a hash table, this
-** is completely recoverable simply by not carrying out the resize. The
-** hash table will continue to function normally. So a malloc failure
-** during a hash table resize is a benign fault.
-*/
-
-#include "sqliteInt.h"
-
-#ifndef SQLITE_UNTESTABLE
-
-/*
-** Global variables.
-*/
-typedef struct BenignMallocHooks BenignMallocHooks;
-static SQLITE_WSD struct BenignMallocHooks {
- void (*xBenignBegin)(void);
- void (*xBenignEnd)(void);
-} sqlite3Hooks = { 0, 0 };
-
-/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
-** structure. If writable static data is unsupported on the target,
-** we have to locate the state vector at run-time. In the more common
-** case where writable static data is supported, wsdHooks can refer directly
-** to the "sqlite3Hooks" state vector declared above.
-*/
-#ifdef SQLITE_OMIT_WSD
-# define wsdHooksInit \
- BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
-# define wsdHooks x[0]
-#else
-# define wsdHooksInit
-# define wsdHooks sqlite3Hooks
-#endif
-
-
-/*
-** Register hooks to call when sqlite3BeginBenignMalloc() and
-** sqlite3EndBenignMalloc() are called, respectively.
-*/
-void sqlite3BenignMallocHooks(
- void (*xBenignBegin)(void),
- void (*xBenignEnd)(void)
-){
- wsdHooksInit;
- wsdHooks.xBenignBegin = xBenignBegin;
- wsdHooks.xBenignEnd = xBenignEnd;
-}
-
-/*
-** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
-** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
-** indicates that subsequent malloc failures are non-benign.
-*/
-void sqlite3BeginBenignMalloc(void){
- wsdHooksInit;
- if( wsdHooks.xBenignBegin ){
- wsdHooks.xBenignBegin();
- }
-}
-void sqlite3EndBenignMalloc(void){
- wsdHooksInit;
- if( wsdHooks.xBenignEnd ){
- wsdHooks.xBenignEnd();
- }
-}
-
-#endif /* #ifndef SQLITE_UNTESTABLE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/fkey.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/fkey.c
deleted file mode 100644
index 256b19db8a4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/fkey.c
+++ /dev/null
@@ -1,1428 +0,0 @@
-/*
-**
-** 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 contains code used by the compiler to add foreign key
-** support to compiled SQL statements.
-*/
-#include "sqliteInt.h"
-
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-#ifndef SQLITE_OMIT_TRIGGER
-
-/*
-** Deferred and Immediate FKs
-** --------------------------
-**
-** Foreign keys in SQLite come in two flavours: deferred and immediate.
-** If an immediate foreign key constraint is violated,
-** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
-** statement transaction rolled back. If a
-** deferred foreign key constraint is violated, no action is taken
-** immediately. However if the application attempts to commit the
-** transaction before fixing the constraint violation, the attempt fails.
-**
-** Deferred constraints are implemented using a simple counter associated
-** with the database handle. The counter is set to zero each time a
-** database transaction is opened. Each time a statement is executed
-** that causes a foreign key violation, the counter is incremented. Each
-** time a statement is executed that removes an existing violation from
-** the database, the counter is decremented. When the transaction is
-** committed, the commit fails if the current value of the counter is
-** greater than zero. This scheme has two big drawbacks:
-**
-** * When a commit fails due to a deferred foreign key constraint,
-** there is no way to tell which foreign constraint is not satisfied,
-** or which row it is not satisfied for.
-**
-** * If the database contains foreign key violations when the
-** transaction is opened, this may cause the mechanism to malfunction.
-**
-** Despite these problems, this approach is adopted as it seems simpler
-** than the alternatives.
-**
-** INSERT operations:
-**
-** I.1) For each FK for which the table is the child table, search
-** the parent table for a match. If none is found increment the
-** constraint counter.
-**
-** I.2) For each FK for which the table is the parent table,
-** search the child table for rows that correspond to the new
-** row in the parent table. Decrement the counter for each row
-** found (as the constraint is now satisfied).
-**
-** DELETE operations:
-**
-** D.1) For each FK for which the table is the child table,
-** search the parent table for a row that corresponds to the
-** deleted row in the child table. If such a row is not found,
-** decrement the counter.
-**
-** D.2) For each FK for which the table is the parent table, search
-** the child table for rows that correspond to the deleted row
-** in the parent table. For each found increment the counter.
-**
-** UPDATE operations:
-**
-** An UPDATE command requires that all 4 steps above are taken, but only
-** for FK constraints for which the affected columns are actually
-** modified (values must be compared at runtime).
-**
-** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2.
-** This simplifies the implementation a bit.
-**
-** For the purposes of immediate FK constraints, the OR REPLACE conflict
-** resolution is considered to delete rows before the new row is inserted.
-** If a delete caused by OR REPLACE violates an FK constraint, an exception
-** is thrown, even if the FK constraint would be satisfied after the new
-** row is inserted.
-**
-** Immediate constraints are usually handled similarly. The only difference
-** is that the counter used is stored as part of each individual statement
-** object (struct Vdbe). If, after the statement has run, its immediate
-** constraint counter is greater than zero,
-** it returns SQLITE_CONSTRAINT_FOREIGNKEY
-** and the statement transaction is rolled back. An exception is an INSERT
-** statement that inserts a single row only (no triggers). In this case,
-** instead of using a counter, an exception is thrown immediately if the
-** INSERT violates a foreign key constraint. This is necessary as such
-** an INSERT does not open a statement transaction.
-**
-** TODO: How should dropping a table be handled? How should renaming a
-** table be handled?
-**
-**
-** Query API Notes
-** ---------------
-**
-** Before coding an UPDATE or DELETE row operation, the code-generator
-** for those two operations needs to know whether or not the operation
-** requires any FK processing and, if so, which columns of the original
-** row are required by the FK processing VDBE code (i.e. if FKs were
-** implemented using triggers, which of the old.* columns would be
-** accessed). No information is required by the code-generator before
-** coding an INSERT operation. The functions used by the UPDATE/DELETE
-** generation code to query for this information are:
-**
-** sqlite3FkRequired() - Test to see if FK processing is required.
-** sqlite3FkOldmask() - Query for the set of required old.* columns.
-**
-**
-** Externally accessible module functions
-** --------------------------------------
-**
-** sqlite3FkCheck() - Check for foreign key violations.
-** sqlite3FkActions() - Code triggers for ON UPDATE/ON DELETE actions.
-** sqlite3FkDelete() - Delete an FKey structure.
-*/
-
-/*
-** VDBE Calling Convention
-** -----------------------
-**
-** Example:
-**
-** For the following INSERT statement:
-**
-** CREATE TABLE t1(a, b INTEGER PRIMARY KEY, c);
-** INSERT INTO t1 VALUES(1, 2, 3.1);
-**
-** Register (x): 2 (type integer)
-** Register (x+1): 1 (type integer)
-** Register (x+2): NULL (type NULL)
-** Register (x+3): 3.1 (type real)
-*/
-
-/*
-** A foreign key constraint requires that the key columns in the parent
-** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
-** Given that pParent is the parent table for foreign key constraint pFKey,
-** search the schema for a unique index on the parent key columns.
-**
-** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
-** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
-** is set to point to the unique index.
-**
-** If the parent key consists of a single column (the foreign key constraint
-** is not a composite foreign key), output variable *paiCol is set to NULL.
-** Otherwise, it is set to point to an allocated array of size N, where
-** N is the number of columns in the parent key. The first element of the
-** array is the index of the child table column that is mapped by the FK
-** constraint to the parent table column stored in the left-most column
-** of index *ppIdx. The second element of the array is the index of the
-** child table column that corresponds to the second left-most column of
-** *ppIdx, and so on.
-**
-** If the required index cannot be found, either because:
-**
-** 1) The named parent key columns do not exist, or
-**
-** 2) The named parent key columns do exist, but are not subject to a
-** UNIQUE or PRIMARY KEY constraint, or
-**
-** 3) No parent key columns were provided explicitly as part of the
-** foreign key definition, and the parent table does not have a
-** PRIMARY KEY, or
-**
-** 4) No parent key columns were provided explicitly as part of the
-** foreign key definition, and the PRIMARY KEY of the parent table
-** consists of a different number of columns to the child key in
-** the child table.
-**
-** then non-zero is returned, and a "foreign key mismatch" error loaded
-** into pParse. If an OOM error occurs, non-zero is returned and the
-** pParse->db->mallocFailed flag is set.
-*/
-int sqlite3FkLocateIndex(
- Parse *pParse, /* Parse context to store any error in */
- Table *pParent, /* Parent table of FK constraint pFKey */
- FKey *pFKey, /* Foreign key to find index for */
- Index **ppIdx, /* OUT: Unique index on parent table */
- int **paiCol /* OUT: Map of index columns in pFKey */
-){
- Index *pIdx = 0; /* Value to return via *ppIdx */
- int *aiCol = 0; /* Value to return via *paiCol */
- int nCol = pFKey->nCol; /* Number of columns in parent key */
- char *zKey = pFKey->aCol[0].zCol; /* Name of left-most parent key column */
-
- /* The caller is responsible for zeroing output parameters. */
- assert( ppIdx && *ppIdx==0 );
- assert( !paiCol || *paiCol==0 );
- assert( pParse );
-
- /* If this is a non-composite (single column) foreign key, check if it
- ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx
- ** and *paiCol set to zero and return early.
- **
- ** Otherwise, for a composite foreign key (more than one column), allocate
- ** space for the aiCol array (returned via output parameter *paiCol).
- ** Non-composite foreign keys do not require the aiCol array.
- */
- if( nCol==1 ){
- /* The FK maps to the IPK if any of the following are true:
- **
- ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly
- ** mapped to the primary key of table pParent, or
- ** 2) The FK is explicitly mapped to a column declared as INTEGER
- ** PRIMARY KEY.
- */
- if( pParent->iPKey>=0 ){
- if( !zKey ) return 0;
- if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0;
- }
- }else if( paiCol ){
- assert( nCol>1 );
- aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int));
- if( !aiCol ) return 1;
- *paiCol = aiCol;
- }
-
- for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){
- /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
- ** of columns. If each indexed column corresponds to a foreign key
- ** column of pFKey, then this index is a winner. */
-
- if( zKey==0 ){
- /* If zKey is NULL, then this foreign key is implicitly mapped to
- ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
- ** identified by the test. */
- if( IsPrimaryKeyIndex(pIdx) ){
- if( aiCol ){
- int i;
- for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom;
- }
- break;
- }
- }else{
- /* If zKey is non-NULL, then this foreign key was declared to
- ** map to an explicit list of columns in table pParent. Check if this
- ** index matches those columns. Also, check that the index uses
- ** the default collation sequences for each column. */
- int i, j;
- for(i=0; i<nCol; i++){
- i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
- const char *zDfltColl; /* Def. collation for column */
- char *zIdxCol; /* Name of indexed column */
-
- if( iCol<0 ) break; /* No foreign keys against expression indexes */
-
- /* If the index uses a collation sequence that is different from
- ** the default collation sequence for the column, this index is
- ** unusable. Bail out early in this case. */
- zDfltColl = pParent->aCol[iCol].zColl;
- if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
- if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
-
- zIdxCol = pParent->aCol[iCol].zName;
- for(j=0; j<nCol; j++){
- if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
- if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
- break;
- }
- }
- if( j==nCol ) break;
- }
- if( i==nCol ) break; /* pIdx is usable */
- }
- }
- }
-
- if( !pIdx ){
- if( !pParse->disableTriggers ){
- sqlite3ErrorMsg(pParse,
- "foreign key mismatch - \"%w\" referencing \"%w\"",
- pFKey->pFrom->zName, pFKey->zTo);
- }
- sqlite3DbFree(pParse->db, aiCol);
- return 1;
- }
-
- *ppIdx = pIdx;
- return 0;
-}
-
-/*
-** This function is called when a row is inserted into or deleted from the
-** child table of foreign key constraint pFKey. If an SQL UPDATE is executed
-** on the child table of pFKey, this function is invoked twice for each row
-** affected - once to "delete" the old row, and then again to "insert" the
-** new row.
-**
-** Each time it is called, this function generates VDBE code to locate the
-** row in the parent table that corresponds to the row being inserted into
-** or deleted from the child table. If the parent row can be found, no
-** special action is taken. Otherwise, if the parent row can *not* be
-** found in the parent table:
-**
-** Operation | FK type | Action taken
-** --------------------------------------------------------------------------
-** INSERT immediate Increment the "immediate constraint counter".
-**
-** DELETE immediate Decrement the "immediate constraint counter".
-**
-** INSERT deferred Increment the "deferred constraint counter".
-**
-** DELETE deferred Decrement the "deferred constraint counter".
-**
-** These operations are identified in the comment at the top of this file
-** (fkey.c) as "I.1" and "D.1".
-*/
-static void fkLookupParent(
- Parse *pParse, /* Parse context */
- int iDb, /* Index of database housing pTab */
- Table *pTab, /* Parent table of FK pFKey */
- Index *pIdx, /* Unique index on parent key columns in pTab */
- FKey *pFKey, /* Foreign key constraint */
- int *aiCol, /* Map from parent key columns to child table columns */
- int regData, /* Address of array containing child table row */
- int nIncr, /* Increment constraint counter by this */
- int isIgnore /* If true, pretend pTab contains all NULL values */
-){
- int i; /* Iterator variable */
- Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */
- int iCur = pParse->nTab - 1; /* Cursor number to use */
- int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */
-
- sqlite3VdbeVerifyAbortable(v,
- (!pFKey->isDeferred
- && !(pParse->db->flags & SQLITE_DeferFKs)
- && !pParse->pToplevel
- && !pParse->isMultiWrite) ? OE_Abort : OE_Ignore);
-
- /* If nIncr is less than zero, then check at runtime if there are any
- ** outstanding constraints to resolve. If there are not, there is no need
- ** to check if deleting this row resolves any outstanding violations.
- **
- ** Check if any of the key columns in the child table row are NULL. If
- ** any are, then the constraint is considered satisfied. No need to
- ** search for a matching row in the parent table. */
- if( nIncr<0 ){
- sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
- VdbeCoverage(v);
- }
- for(i=0; i<pFKey->nCol; i++){
- int iReg = aiCol[i] + regData + 1;
- sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v);
- }
-
- if( isIgnore==0 ){
- if( pIdx==0 ){
- /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY
- ** column of the parent table (table pTab). */
- int iMustBeInt; /* Address of MustBeInt instruction */
- int regTemp = sqlite3GetTempReg(pParse);
-
- /* Invoke MustBeInt to coerce the child key value to an integer (i.e.
- ** apply the affinity of the parent key). If this fails, then there
- ** is no matching parent key. Before using MustBeInt, make a copy of
- ** the value. Otherwise, the value inserted into the child key column
- ** will have INTEGER affinity applied to it, which may not be correct. */
- sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
- iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
- VdbeCoverage(v);
-
- /* If the parent table is the same as the child table, and we are about
- ** to increment the constraint-counter (i.e. this is an INSERT operation),
- ** then check if the row being inserted matches itself. If so, do not
- ** increment the constraint-counter. */
- if( pTab==pFKey->pFrom && nIncr==1 ){
- sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v);
- sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- }
-
- sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v);
- sqlite3VdbeGoto(v, iOk);
- sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
- sqlite3VdbeJumpHere(v, iMustBeInt);
- sqlite3ReleaseTempReg(pParse, regTemp);
- }else{
- int nCol = pFKey->nCol;
- int regTemp = sqlite3GetTempRange(pParse, nCol);
- int regRec = sqlite3GetTempReg(pParse);
-
- sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
- sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
- for(i=0; i<nCol; i++){
- sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
- }
-
- /* If the parent table is the same as the child table, and we are about
- ** to increment the constraint-counter (i.e. this is an INSERT operation),
- ** then check if the row being inserted matches itself. If so, do not
- ** increment the constraint-counter.
- **
- ** If any of the parent-key values are NULL, then the row cannot match
- ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
- ** of the parent-key values are NULL (at this point it is known that
- ** none of the child key values are).
- */
- if( pTab==pFKey->pFrom && nIncr==1 ){
- int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
- for(i=0; i<nCol; i++){
- int iChild = aiCol[i]+1+regData;
- int iParent = pIdx->aiColumn[i]+1+regData;
- assert( pIdx->aiColumn[i]>=0 );
- assert( aiCol[i]!=pTab->iPKey );
- if( pIdx->aiColumn[i]==pTab->iPKey ){
- /* The parent key is a composite key that includes the IPK column */
- iParent = regData;
- }
- sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v);
- sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
- }
- sqlite3VdbeGoto(v, iOk);
- }
-
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec,
- sqlite3IndexAffinityStr(pParse->db,pIdx), nCol);
- sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v);
-
- sqlite3ReleaseTempReg(pParse, regRec);
- sqlite3ReleaseTempRange(pParse, regTemp, nCol);
- }
- }
-
- if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs)
- && !pParse->pToplevel
- && !pParse->isMultiWrite
- ){
- /* Special case: If this is an INSERT statement that will insert exactly
- ** one row into the table, raise a constraint immediately instead of
- ** incrementing a counter. This is necessary as the VM code is being
- ** generated for will not open a statement transaction. */
- assert( nIncr==1 );
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
- OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
- }else{
- if( nIncr>0 && pFKey->isDeferred==0 ){
- sqlite3MayAbort(pParse);
- }
- sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
- }
-
- sqlite3VdbeResolveLabel(v, iOk);
- sqlite3VdbeAddOp1(v, OP_Close, iCur);
-}
-
-
-/*
-** Return an Expr object that refers to a memory register corresponding
-** to column iCol of table pTab.
-**
-** regBase is the first of an array of register that contains the data
-** for pTab. regBase itself holds the rowid. regBase+1 holds the first
-** column. regBase+2 holds the second column, and so forth.
-*/
-static Expr *exprTableRegister(
- Parse *pParse, /* Parsing and code generating context */
- Table *pTab, /* The table whose content is at r[regBase]... */
- int regBase, /* Contents of table pTab */
- i16 iCol /* Which column of pTab is desired */
-){
- Expr *pExpr;
- Column *pCol;
- const char *zColl;
- sqlite3 *db = pParse->db;
-
- pExpr = sqlite3Expr(db, TK_REGISTER, 0);
- if( pExpr ){
- if( iCol>=0 && iCol!=pTab->iPKey ){
- pCol = &pTab->aCol[iCol];
- pExpr->iTable = regBase + iCol + 1;
- pExpr->affinity = pCol->affinity;
- zColl = pCol->zColl;
- if( zColl==0 ) zColl = db->pDfltColl->zName;
- pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
- }else{
- pExpr->iTable = regBase;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- }
- }
- return pExpr;
-}
-
-/*
-** Return an Expr object that refers to column iCol of table pTab which
-** has cursor iCur.
-*/
-static Expr *exprTableColumn(
- sqlite3 *db, /* The database connection */
- Table *pTab, /* The table whose column is desired */
- int iCursor, /* The open cursor on the table */
- i16 iCol /* The column that is wanted */
-){
- Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
- if( pExpr ){
- pExpr->pTab = pTab;
- pExpr->iTable = iCursor;
- pExpr->iColumn = iCol;
- }
- return pExpr;
-}
-
-/*
-** This function is called to generate code executed when a row is deleted
-** from the parent table of foreign key constraint pFKey and, if pFKey is
-** deferred, when a row is inserted into the same table. When generating
-** code for an SQL UPDATE operation, this function may be called twice -
-** once to "delete" the old row and once to "insert" the new row.
-**
-** Parameter nIncr is passed -1 when inserting a row (as this may decrease
-** the number of FK violations in the db) or +1 when deleting one (as this
-** may increase the number of FK constraint problems).
-**
-** The code generated by this function scans through the rows in the child
-** table that correspond to the parent table row being deleted or inserted.
-** For each child row found, one of the following actions is taken:
-**
-** Operation | FK type | Action taken
-** --------------------------------------------------------------------------
-** DELETE immediate Increment the "immediate constraint counter".
-** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
-** throw a "FOREIGN KEY constraint failed" exception.
-**
-** INSERT immediate Decrement the "immediate constraint counter".
-**
-** DELETE deferred Increment the "deferred constraint counter".
-** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
-** throw a "FOREIGN KEY constraint failed" exception.
-**
-** INSERT deferred Decrement the "deferred constraint counter".
-**
-** These operations are identified in the comment at the top of this file
-** (fkey.c) as "I.2" and "D.2".
-*/
-static void fkScanChildren(
- Parse *pParse, /* Parse context */
- SrcList *pSrc, /* The child table to be scanned */
- Table *pTab, /* The parent table */
- Index *pIdx, /* Index on parent covering the foreign key */
- FKey *pFKey, /* The foreign key linking pSrc to pTab */
- int *aiCol, /* Map from pIdx cols to child table cols */
- int regData, /* Parent row data starts here */
- int nIncr /* Amount to increment deferred counter by */
-){
- sqlite3 *db = pParse->db; /* Database handle */
- int i; /* Iterator variable */
- Expr *pWhere = 0; /* WHERE clause to scan with */
- NameContext sNameContext; /* Context used to resolve WHERE clause */
- WhereInfo *pWInfo; /* Context used by sqlite3WhereXXX() */
- int iFkIfZero = 0; /* Address of OP_FkIfZero */
- Vdbe *v = sqlite3GetVdbe(pParse);
-
- assert( pIdx==0 || pIdx->pTable==pTab );
- assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol );
- assert( pIdx!=0 || pFKey->nCol==1 );
- assert( pIdx!=0 || HasRowid(pTab) );
-
- if( nIncr<0 ){
- iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
- VdbeCoverage(v);
- }
-
- /* Create an Expr object representing an SQL expression like:
- **
- ** <parent-key1> = <child-key1> AND <parent-key2> = <child-key2> ...
- **
- ** The collation sequence used for the comparison should be that of
- ** the parent key columns. The affinity of the parent key column should
- ** be applied to each child key value before the comparison takes place.
- */
- for(i=0; i<pFKey->nCol; i++){
- Expr *pLeft; /* Value from parent table row */
- Expr *pRight; /* Column ref to child table */
- Expr *pEq; /* Expression (pLeft = pRight) */
- i16 iCol; /* Index of column in child table */
- const char *zCol; /* Name of column in child table */
-
- iCol = pIdx ? pIdx->aiColumn[i] : -1;
- pLeft = exprTableRegister(pParse, pTab, regData, iCol);
- iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
- assert( iCol>=0 );
- zCol = pFKey->pFrom->aCol[iCol].zName;
- pRight = sqlite3Expr(db, TK_ID, zCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
- pWhere = sqlite3ExprAnd(db, pWhere, pEq);
- }
-
- /* If the child table is the same as the parent table, then add terms
- ** to the WHERE clause that prevent this entry from being scanned.
- ** The added WHERE clause terms are like this:
- **
- ** $current_rowid!=rowid
- ** NOT( $current_a==a AND $current_b==b AND ... )
- **
- ** The first form is used for rowid tables. The second form is used
- ** for WITHOUT ROWID tables. In the second form, the primary key is
- ** (a,b,...)
- */
- if( pTab==pFKey->pFrom && nIncr>0 ){
- Expr *pNe; /* Expression (pLeft != pRight) */
- Expr *pLeft; /* Value from parent table row */
- Expr *pRight; /* Column ref to child table */
- if( HasRowid(pTab) ){
- pLeft = exprTableRegister(pParse, pTab, regData, -1);
- pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1);
- pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight);
- }else{
- Expr *pEq, *pAll = 0;
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- assert( pIdx!=0 );
- for(i=0; i<pPk->nKeyCol; i++){
- i16 iCol = pIdx->aiColumn[i];
- assert( iCol>=0 );
- pLeft = exprTableRegister(pParse, pTab, regData, iCol);
- pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
- pAll = sqlite3ExprAnd(db, pAll, pEq);
- }
- pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
- }
- pWhere = sqlite3ExprAnd(db, pWhere, pNe);
- }
-
- /* Resolve the references in the WHERE clause. */
- memset(&sNameContext, 0, sizeof(NameContext));
- sNameContext.pSrcList = pSrc;
- sNameContext.pParse = pParse;
- sqlite3ResolveExprNames(&sNameContext, pWhere);
-
- /* Create VDBE to loop through the entries in pSrc that match the WHERE
- ** clause. For each row found, increment either the deferred or immediate
- ** foreign key constraint counter. */
- if( pParse->nErr==0 ){
- pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
- sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
- if( pWInfo ){
- sqlite3WhereEnd(pWInfo);
- }
- }
-
- /* Clean up the WHERE clause constructed above. */
- sqlite3ExprDelete(db, pWhere);
- if( iFkIfZero ){
- sqlite3VdbeJumpHere(v, iFkIfZero);
- }
-}
-
-/*
-** This function returns a linked list of FKey objects (connected by
-** FKey.pNextTo) holding all children of table pTab. For example,
-** given the following schema:
-**
-** CREATE TABLE t1(a PRIMARY KEY);
-** CREATE TABLE t2(b REFERENCES t1(a);
-**
-** Calling this function with table "t1" as an argument returns a pointer
-** to the FKey structure representing the foreign key constraint on table
-** "t2". Calling this function with "t2" as the argument would return a
-** NULL pointer (as there are no FK constraints for which t2 is the parent
-** table).
-*/
-FKey *sqlite3FkReferences(Table *pTab){
- return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName);
-}
-
-/*
-** The second argument is a Trigger structure allocated by the
-** fkActionTrigger() routine. This function deletes the Trigger structure
-** and all of its sub-components.
-**
-** The Trigger structure or any of its sub-components may be allocated from
-** the lookaside buffer belonging to database handle dbMem.
-*/
-static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
- if( p ){
- TriggerStep *pStep = p->step_list;
- sqlite3ExprDelete(dbMem, pStep->pWhere);
- sqlite3ExprListDelete(dbMem, pStep->pExprList);
- sqlite3SelectDelete(dbMem, pStep->pSelect);
- sqlite3ExprDelete(dbMem, p->pWhen);
- sqlite3DbFree(dbMem, p);
- }
-}
-
-/*
-** This function is called to generate code that runs when table pTab is
-** being dropped from the database. The SrcList passed as the second argument
-** to this function contains a single entry guaranteed to resolve to
-** table pTab.
-**
-** Normally, no code is required. However, if either
-**
-** (a) The table is the parent table of a FK constraint, or
-** (b) The table is the child table of a deferred FK constraint and it is
-** determined at runtime that there are outstanding deferred FK
-** constraint violations in the database,
-**
-** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
-** the table from the database. Triggers are disabled while running this
-** DELETE, but foreign key actions are not.
-*/
-void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
- sqlite3 *db = pParse->db;
- if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){
- int iSkip = 0;
- Vdbe *v = sqlite3GetVdbe(pParse);
-
- assert( v ); /* VDBE has already been allocated */
- if( sqlite3FkReferences(pTab)==0 ){
- /* Search for a deferred foreign key constraint for which this table
- ** is the child table. If one cannot be found, return without
- ** generating any VDBE code. If one can be found, then jump over
- ** the entire DELETE if there are no outstanding deferred constraints
- ** when this statement is run. */
- FKey *p;
- for(p=pTab->pFKey; p; p=p->pNextFrom){
- if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
- }
- if( !p ) return;
- iSkip = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
- }
-
- pParse->disableTriggers = 1;
- sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0);
- pParse->disableTriggers = 0;
-
- /* If the DELETE has generated immediate foreign key constraint
- ** violations, halt the VDBE and return an error at this point, before
- ** any modifications to the schema are made. This is because statement
- ** transactions are not able to rollback schema changes.
- **
- ** If the SQLITE_DeferFKs flag is set, then this is not required, as
- ** the statement transaction will not be rolled back even if FK
- ** constraints are violated.
- */
- if( (db->flags & SQLITE_DeferFKs)==0 ){
- sqlite3VdbeVerifyAbortable(v, OE_Abort);
- sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
- VdbeCoverage(v);
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
- OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
- }
-
- if( iSkip ){
- sqlite3VdbeResolveLabel(v, iSkip);
- }
- }
-}
-
-
-/*
-** The second argument points to an FKey object representing a foreign key
-** for which pTab is the child table. An UPDATE statement against pTab
-** is currently being processed. For each column of the table that is
-** actually updated, the corresponding element in the aChange[] array
-** is zero or greater (if a column is unmodified the corresponding element
-** is set to -1). If the rowid column is modified by the UPDATE statement
-** the bChngRowid argument is non-zero.
-**
-** This function returns true if any of the columns that are part of the
-** child key for FK constraint *p are modified.
-*/
-static int fkChildIsModified(
- Table *pTab, /* Table being updated */
- FKey *p, /* Foreign key for which pTab is the child */
- int *aChange, /* Array indicating modified columns */
- int bChngRowid /* True if rowid is modified by this update */
-){
- int i;
- for(i=0; i<p->nCol; i++){
- int iChildKey = p->aCol[i].iFrom;
- if( aChange[iChildKey]>=0 ) return 1;
- if( iChildKey==pTab->iPKey && bChngRowid ) return 1;
- }
- return 0;
-}
-
-/*
-** The second argument points to an FKey object representing a foreign key
-** for which pTab is the parent table. An UPDATE statement against pTab
-** is currently being processed. For each column of the table that is
-** actually updated, the corresponding element in the aChange[] array
-** is zero or greater (if a column is unmodified the corresponding element
-** is set to -1). If the rowid column is modified by the UPDATE statement
-** the bChngRowid argument is non-zero.
-**
-** This function returns true if any of the columns that are part of the
-** parent key for FK constraint *p are modified.
-*/
-static int fkParentIsModified(
- Table *pTab,
- FKey *p,
- int *aChange,
- int bChngRowid
-){
- int i;
- for(i=0; i<p->nCol; i++){
- char *zKey = p->aCol[i].zCol;
- int iKey;
- for(iKey=0; iKey<pTab->nCol; iKey++){
- if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
- Column *pCol = &pTab->aCol[iKey];
- if( zKey ){
- if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1;
- }else if( pCol->colFlags & COLFLAG_PRIMKEY ){
- return 1;
- }
- }
- }
- }
- return 0;
-}
-
-/*
-** Return true if the parser passed as the first argument is being
-** used to code a trigger that is really a "SET NULL" action belonging
-** to trigger pFKey.
-*/
-static int isSetNullAction(Parse *pParse, FKey *pFKey){
- Parse *pTop = sqlite3ParseToplevel(pParse);
- if( pTop->pTriggerPrg ){
- Trigger *p = pTop->pTriggerPrg->pTrigger;
- if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull)
- || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull)
- ){
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** This function is called when inserting, deleting or updating a row of
-** table pTab to generate VDBE code to perform foreign key constraint
-** processing for the operation.
-**
-** For a DELETE operation, parameter regOld is passed the index of the
-** first register in an array of (pTab->nCol+1) registers containing the
-** rowid of the row being deleted, followed by each of the column values
-** of the row being deleted, from left to right. Parameter regNew is passed
-** zero in this case.
-**
-** For an INSERT operation, regOld is passed zero and regNew is passed the
-** first register of an array of (pTab->nCol+1) registers containing the new
-** row data.
-**
-** For an UPDATE operation, this function is called twice. Once before
-** the original record is deleted from the table using the calling convention
-** described for DELETE. Then again after the original record is deleted
-** but before the new record is inserted using the INSERT convention.
-*/
-void sqlite3FkCheck(
- Parse *pParse, /* Parse context */
- Table *pTab, /* Row is being deleted from this table */
- int regOld, /* Previous row data is stored here */
- int regNew, /* New row data is stored here */
- int *aChange, /* Array indicating UPDATEd columns (or 0) */
- int bChngRowid /* True if rowid is UPDATEd */
-){
- sqlite3 *db = pParse->db; /* Database handle */
- FKey *pFKey; /* Used to iterate through FKs */
- int iDb; /* Index of database containing pTab */
- const char *zDb; /* Name of database containing pTab */
- int isIgnoreErrors = pParse->disableTriggers;
-
- /* Exactly one of regOld and regNew should be non-zero. */
- assert( (regOld==0)!=(regNew==0) );
-
- /* If foreign-keys are disabled, this function is a no-op. */
- if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
-
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- zDb = db->aDb[iDb].zDbSName;
-
- /* Loop through all the foreign key constraints for which pTab is the
- ** child table (the table that the foreign key definition is part of). */
- for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
- Table *pTo; /* Parent table of foreign key pFKey */
- Index *pIdx = 0; /* Index on key columns in pTo */
- int *aiFree = 0;
- int *aiCol;
- int iCol;
- int i;
- int bIgnore = 0;
-
- if( aChange
- && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
- && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0
- ){
- continue;
- }
-
- /* Find the parent table of this foreign key. Also find a unique index
- ** on the parent key columns in the parent table. If either of these
- ** schema items cannot be located, set an error in pParse and return
- ** early. */
- if( pParse->disableTriggers ){
- pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
- }else{
- pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
- }
- if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
- assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
- if( !isIgnoreErrors || db->mallocFailed ) return;
- if( pTo==0 ){
- /* If isIgnoreErrors is true, then a table is being dropped. In this
- ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
- ** before actually dropping it in order to check FK constraints.
- ** If the parent table of an FK constraint on the current table is
- ** missing, behave as if it is empty. i.e. decrement the relevant
- ** FK counter for each row of the current table with non-NULL keys.
- */
- Vdbe *v = sqlite3GetVdbe(pParse);
- int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
- for(i=0; i<pFKey->nCol; i++){
- int iReg = pFKey->aCol[i].iFrom + regOld + 1;
- sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v);
- }
- sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
- }
- continue;
- }
- assert( pFKey->nCol==1 || (aiFree && pIdx) );
-
- if( aiFree ){
- aiCol = aiFree;
- }else{
- iCol = pFKey->aCol[0].iFrom;
- aiCol = &iCol;
- }
- for(i=0; i<pFKey->nCol; i++){
- if( aiCol[i]==pTab->iPKey ){
- aiCol[i] = -1;
- }
- assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
-#ifndef SQLITE_OMIT_AUTHORIZATION
- /* Request permission to read the parent key columns. If the
- ** authorization callback returns SQLITE_IGNORE, behave as if any
- ** values read from the parent table are NULL. */
- if( db->xAuth ){
- int rcauth;
- char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
- rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
- bIgnore = (rcauth==SQLITE_IGNORE);
- }
-#endif
- }
-
- /* Take a shared-cache advisory read-lock on the parent table. Allocate
- ** a cursor to use to search the unique index on the parent key columns
- ** in the parent table. */
- sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName);
- pParse->nTab++;
-
- if( regOld!=0 ){
- /* A row is being removed from the child table. Search for the parent.
- ** If the parent does not exist, removing the child row resolves an
- ** outstanding foreign key constraint violation. */
- fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore);
- }
- if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){
- /* A row is being added to the child table. If a parent row cannot
- ** be found, adding the child row has violated the FK constraint.
- **
- ** If this operation is being performed as part of a trigger program
- ** that is actually a "SET NULL" action belonging to this very
- ** foreign key, then omit this scan altogether. As all child key
- ** values are guaranteed to be NULL, it is not possible for adding
- ** this row to cause an FK violation. */
- fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore);
- }
-
- sqlite3DbFree(db, aiFree);
- }
-
- /* Loop through all the foreign key constraints that refer to this table.
- ** (the "child" constraints) */
- for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
- Index *pIdx = 0; /* Foreign key index for pFKey */
- SrcList *pSrc;
- int *aiCol = 0;
-
- if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){
- continue;
- }
-
- if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs)
- && !pParse->pToplevel && !pParse->isMultiWrite
- ){
- assert( regOld==0 && regNew!=0 );
- /* Inserting a single row into a parent table cannot cause (or fix)
- ** an immediate foreign key violation. So do nothing in this case. */
- continue;
- }
-
- if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
- if( !isIgnoreErrors || db->mallocFailed ) return;
- continue;
- }
- assert( aiCol || pFKey->nCol==1 );
-
- /* Create a SrcList structure containing the child table. We need the
- ** child table as a SrcList for sqlite3WhereBegin() */
- pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pSrc ){
- struct SrcList_item *pItem = pSrc->a;
- pItem->pTab = pFKey->pFrom;
- pItem->zName = pFKey->pFrom->zName;
- pItem->pTab->nTabRef++;
- pItem->iCursor = pParse->nTab++;
-
- if( regNew!=0 ){
- fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
- }
- if( regOld!=0 ){
- int eAction = pFKey->aAction[aChange!=0];
- fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);
- /* If this is a deferred FK constraint, or a CASCADE or SET NULL
- ** action applies, then any foreign key violations caused by
- ** removing the parent key will be rectified by the action trigger.
- ** So do not set the "may-abort" flag in this case.
- **
- ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the
- ** may-abort flag will eventually be set on this statement anyway
- ** (when this function is called as part of processing the UPDATE
- ** within the action trigger).
- **
- ** Note 2: At first glance it may seem like SQLite could simply omit
- ** all OP_FkCounter related scans when either CASCADE or SET NULL
- ** applies. The trouble starts if the CASCADE or SET NULL action
- ** trigger causes other triggers or action rules attached to the
- ** child table to fire. In these cases the fk constraint counters
- ** might be set incorrectly if any OP_FkCounter related scans are
- ** omitted. */
- if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){
- sqlite3MayAbort(pParse);
- }
- }
- pItem->zName = 0;
- sqlite3SrcListDelete(db, pSrc);
- }
- sqlite3DbFree(db, aiCol);
- }
-}
-
-#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x)))
-
-/*
-** This function is called before generating code to update or delete a
-** row contained in table pTab.
-*/
-u32 sqlite3FkOldmask(
- Parse *pParse, /* Parse context */
- Table *pTab /* Table being modified */
-){
- u32 mask = 0;
- if( pParse->db->flags&SQLITE_ForeignKeys ){
- FKey *p;
- int i;
- for(p=pTab->pFKey; p; p=p->pNextFrom){
- for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
- }
- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- Index *pIdx = 0;
- sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
- if( pIdx ){
- for(i=0; i<pIdx->nKeyCol; i++){
- assert( pIdx->aiColumn[i]>=0 );
- mask |= COLUMN_MASK(pIdx->aiColumn[i]);
- }
- }
- }
- }
- return mask;
-}
-
-
-/*
-** This function is called before generating code to update or delete a
-** row contained in table pTab. If the operation is a DELETE, then
-** parameter aChange is passed a NULL value. For an UPDATE, aChange points
-** to an array of size N, where N is the number of columns in table pTab.
-** If the i'th column is not modified by the UPDATE, then the corresponding
-** entry in the aChange[] array is set to -1. If the column is modified,
-** the value is 0 or greater. Parameter chngRowid is set to true if the
-** UPDATE statement modifies the rowid fields of the table.
-**
-** If any foreign key processing will be required, this function returns
-** non-zero. If there is no foreign key related processing, this function
-** returns zero.
-**
-** For an UPDATE, this function returns 2 if:
-**
-** * There are any FKs for which pTab is the child and the parent table, or
-** * the UPDATE modifies one or more parent keys for which the action is
-** not "NO ACTION" (i.e. is CASCADE, SET DEFAULT or SET NULL).
-**
-** Or, assuming some other foreign key processing is required, 1.
-*/
-int sqlite3FkRequired(
- Parse *pParse, /* Parse context */
- Table *pTab, /* Table being modified */
- int *aChange, /* Non-NULL for UPDATE operations */
- int chngRowid /* True for UPDATE that affects rowid */
-){
- int eRet = 0;
- if( pParse->db->flags&SQLITE_ForeignKeys ){
- if( !aChange ){
- /* A DELETE operation. Foreign key processing is required if the
- ** table in question is either the child or parent table for any
- ** foreign key constraint. */
- eRet = (sqlite3FkReferences(pTab) || pTab->pFKey);
- }else{
- /* This is an UPDATE. Foreign key processing is only required if the
- ** operation modifies one or more child or parent key columns. */
- FKey *p;
-
- /* Check if any child key columns are being modified. */
- for(p=pTab->pFKey; p; p=p->pNextFrom){
- if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) return 2;
- if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
- eRet = 1;
- }
- }
-
- /* Check if any parent key columns are being modified. */
- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- if( fkParentIsModified(pTab, p, aChange, chngRowid) ){
- if( p->aAction[1]!=OE_None ) return 2;
- eRet = 1;
- }
- }
- }
- }
- return eRet;
-}
-
-/*
-** This function is called when an UPDATE or DELETE operation is being
-** compiled on table pTab, which is the parent table of foreign-key pFKey.
-** If the current operation is an UPDATE, then the pChanges parameter is
-** passed a pointer to the list of columns being modified. If it is a
-** DELETE, pChanges is passed a NULL pointer.
-**
-** It returns a pointer to a Trigger structure containing a trigger
-** equivalent to the ON UPDATE or ON DELETE action specified by pFKey.
-** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is
-** returned (these actions require no special handling by the triggers
-** sub-system, code for them is created by fkScanChildren()).
-**
-** For example, if pFKey is the foreign key and pTab is table "p" in
-** the following schema:
-**
-** CREATE TABLE p(pk PRIMARY KEY);
-** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE);
-**
-** then the returned trigger structure is equivalent to:
-**
-** CREATE TRIGGER ... DELETE ON p BEGIN
-** DELETE FROM c WHERE ck = old.pk;
-** END;
-**
-** The returned pointer is cached as part of the foreign key object. It
-** is eventually freed along with the rest of the foreign key object by
-** sqlite3FkDelete().
-*/
-static Trigger *fkActionTrigger(
- Parse *pParse, /* Parse context */
- Table *pTab, /* Table being updated or deleted from */
- FKey *pFKey, /* Foreign key to get action for */
- ExprList *pChanges /* Change-list for UPDATE, NULL for DELETE */
-){
- sqlite3 *db = pParse->db; /* Database handle */
- int action; /* One of OE_None, OE_Cascade etc. */
- Trigger *pTrigger; /* Trigger definition to return */
- int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */
-
- action = pFKey->aAction[iAction];
- if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){
- return 0;
- }
- pTrigger = pFKey->apTrigger[iAction];
-
- if( action!=OE_None && !pTrigger ){
- char const *zFrom; /* Name of child table */
- int nFrom; /* Length in bytes of zFrom */
- Index *pIdx = 0; /* Parent key index for this FK */
- int *aiCol = 0; /* child table cols -> parent key cols */
- TriggerStep *pStep = 0; /* First (only) step of trigger program */
- Expr *pWhere = 0; /* WHERE clause of trigger step */
- ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */
- Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */
- int i; /* Iterator variable */
- Expr *pWhen = 0; /* WHEN clause for the trigger */
-
- if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
- assert( aiCol || pFKey->nCol==1 );
-
- for(i=0; i<pFKey->nCol; i++){
- Token tOld = { "old", 3 }; /* Literal "old" token */
- Token tNew = { "new", 3 }; /* Literal "new" token */
- Token tFromCol; /* Name of column in child table */
- Token tToCol; /* Name of column in parent table */
- int iFromCol; /* Idx of column in child table */
- Expr *pEq; /* tFromCol = OLD.tToCol */
-
- iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
- assert( iFromCol>=0 );
- assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
- assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
- sqlite3TokenInit(&tToCol,
- pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName);
- sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName);
-
- /* Create the expression "OLD.zToCol = zFromCol". It is important
- ** that the "OLD.zToCol" term is on the LHS of the = operator, so
- ** that the affinity and collation sequence associated with the
- ** parent table are used for the comparison. */
- pEq = sqlite3PExpr(pParse, TK_EQ,
- sqlite3PExpr(pParse, TK_DOT,
- sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
- sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0)
- );
- pWhere = sqlite3ExprAnd(db, pWhere, pEq);
-
- /* For ON UPDATE, construct the next term of the WHEN clause.
- ** The final WHEN clause will be like this:
- **
- ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN)
- */
- if( pChanges ){
- pEq = sqlite3PExpr(pParse, TK_IS,
- sqlite3PExpr(pParse, TK_DOT,
- sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
- sqlite3PExpr(pParse, TK_DOT,
- sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0))
- );
- pWhen = sqlite3ExprAnd(db, pWhen, pEq);
- }
-
- if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){
- Expr *pNew;
- if( action==OE_Cascade ){
- pNew = sqlite3PExpr(pParse, TK_DOT,
- sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0));
- }else if( action==OE_SetDflt ){
- Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
- if( pDflt ){
- pNew = sqlite3ExprDup(db, pDflt, 0);
- }else{
- pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
- }
- }else{
- pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
- }
- pList = sqlite3ExprListAppend(pParse, pList, pNew);
- sqlite3ExprListSetName(pParse, pList, &tFromCol, 0);
- }
- }
- sqlite3DbFree(db, aiCol);
-
- zFrom = pFKey->pFrom->zName;
- nFrom = sqlite3Strlen30(zFrom);
-
- if( action==OE_Restrict ){
- Token tFrom;
- Expr *pRaise;
-
- tFrom.z = zFrom;
- tFrom.n = nFrom;
- pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
- if( pRaise ){
- pRaise->affinity = OE_Abort;
- }
- pSelect = sqlite3SelectNew(pParse,
- sqlite3ExprListAppend(pParse, 0, pRaise),
- sqlite3SrcListAppend(db, 0, &tFrom, 0),
- pWhere,
- 0, 0, 0, 0, 0
- );
- pWhere = 0;
- }
-
- /* Disable lookaside memory allocation */
- db->lookaside.bDisable++;
-
- pTrigger = (Trigger *)sqlite3DbMallocZero(db,
- sizeof(Trigger) + /* struct Trigger */
- sizeof(TriggerStep) + /* Single step in trigger program */
- nFrom + 1 /* Space for pStep->zTarget */
- );
- if( pTrigger ){
- pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
- pStep->zTarget = (char *)&pStep[1];
- memcpy((char *)pStep->zTarget, zFrom, nFrom);
-
- pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
- pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
- pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
- if( pWhen ){
- pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0);
- pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
- }
- }
-
- /* Re-enable the lookaside buffer, if it was disabled earlier. */
- db->lookaside.bDisable--;
-
- sqlite3ExprDelete(db, pWhere);
- sqlite3ExprDelete(db, pWhen);
- sqlite3ExprListDelete(db, pList);
- sqlite3SelectDelete(db, pSelect);
- if( db->mallocFailed==1 ){
- fkTriggerDelete(db, pTrigger);
- return 0;
- }
- assert( pStep!=0 );
-
- switch( action ){
- case OE_Restrict:
- pStep->op = TK_SELECT;
- break;
- case OE_Cascade:
- if( !pChanges ){
- pStep->op = TK_DELETE;
- break;
- }
- default:
- pStep->op = TK_UPDATE;
- }
- pStep->pTrig = pTrigger;
- pTrigger->pSchema = pTab->pSchema;
- pTrigger->pTabSchema = pTab->pSchema;
- pFKey->apTrigger[iAction] = pTrigger;
- pTrigger->op = (pChanges ? TK_UPDATE : TK_DELETE);
- }
-
- return pTrigger;
-}
-
-/*
-** This function is called when deleting or updating a row to implement
-** any required CASCADE, SET NULL or SET DEFAULT actions.
-*/
-void sqlite3FkActions(
- Parse *pParse, /* Parse context */
- Table *pTab, /* Table being updated or deleted from */
- ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */
- int regOld, /* Address of array containing old row */
- int *aChange, /* Array indicating UPDATEd columns (or 0) */
- int bChngRowid /* True if rowid is UPDATEd */
-){
- /* If foreign-key support is enabled, iterate through all FKs that
- ** refer to table pTab. If there is an action associated with the FK
- ** for this operation (either update or delete), invoke the associated
- ** trigger sub-program. */
- if( pParse->db->flags&SQLITE_ForeignKeys ){
- FKey *pFKey; /* Iterator variable */
- for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
- if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){
- Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges);
- if( pAct ){
- sqlite3CodeRowTriggerDirect(pParse, pAct, pTab, regOld, OE_Abort, 0);
- }
- }
- }
- }
-}
-
-#endif /* ifndef SQLITE_OMIT_TRIGGER */
-
-/*
-** Free all memory associated with foreign key definitions attached to
-** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash
-** hash table.
-*/
-void sqlite3FkDelete(sqlite3 *db, Table *pTab){
- FKey *pFKey; /* Iterator variable */
- FKey *pNext; /* Copy of pFKey->pNextFrom */
-
- assert( db==0 || IsVirtual(pTab)
- || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
- for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
-
- /* Remove the FK from the fkeyHash hash table. */
- if( !db || db->pnBytesFreed==0 ){
- if( pFKey->pPrevTo ){
- pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
- }else{
- void *p = (void *)pFKey->pNextTo;
- const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo);
- sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p);
- }
- if( pFKey->pNextTo ){
- pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
- }
- }
-
- /* EV: R-30323-21917 Each foreign key constraint in SQLite is
- ** classified as either immediate or deferred.
- */
- assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 );
-
- /* Delete any triggers created to implement actions for this FK. */
-#ifndef SQLITE_OMIT_TRIGGER
- fkTriggerDelete(db, pFKey->apTrigger[0]);
- fkTriggerDelete(db, pFKey->apTrigger[1]);
-#endif
-
- pNext = pFKey->pNextFrom;
- sqlite3DbFree(db, pFKey);
- }
-}
-#endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/func.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/func.c
deleted file mode 100644
index 17a267e2239..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/func.c
+++ /dev/null
@@ -1,1910 +0,0 @@
-/*
-** 2002 February 23
-**
-** 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 contains the C-language implementations for many of the SQL
-** functions of SQLite. (Some function, and in particular the date and
-** time functions, are implemented separately.)
-*/
-#include "sqliteInt.h"
-#include <stdlib.h>
-#include <assert.h>
-#include "vdbeInt.h"
-
-/*
-** Return the collating function associated with a function.
-*/
-static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
- VdbeOp *pOp;
- assert( context->pVdbe!=0 );
- pOp = &context->pVdbe->aOp[context->iOp-1];
- assert( pOp->opcode==OP_CollSeq );
- assert( pOp->p4type==P4_COLLSEQ );
- return pOp->p4.pColl;
-}
-
-/*
-** Indicate that the accumulator load should be skipped on this
-** iteration of the aggregate loop.
-*/
-static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){
- assert( context->isError<=0 );
- context->isError = -1;
- context->skipFlag = 1;
-}
-
-/*
-** Implementation of the non-aggregate min() and max() functions
-*/
-static void minmaxFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int i;
- int mask; /* 0 for min() or 0xffffffff for max() */
- int iBest;
- CollSeq *pColl;
-
- assert( argc>1 );
- mask = sqlite3_user_data(context)==0 ? 0 : -1;
- pColl = sqlite3GetFuncCollSeq(context);
- assert( pColl );
- assert( mask==-1 || mask==0 );
- iBest = 0;
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- for(i=1; i<argc; i++){
- if( sqlite3_value_type(argv[i])==SQLITE_NULL ) return;
- if( (sqlite3MemCompare(argv[iBest], argv[i], pColl)^mask)>=0 ){
- testcase( mask==0 );
- iBest = i;
- }
- }
- sqlite3_result_value(context, argv[iBest]);
-}
-
-/*
-** Return the type of the argument.
-*/
-static void typeofFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- static const char *azType[] = { "integer", "real", "text", "blob", "null" };
- int i = sqlite3_value_type(argv[0]) - 1;
- UNUSED_PARAMETER(NotUsed);
- assert( i>=0 && i<ArraySize(azType) );
- assert( SQLITE_INTEGER==1 );
- assert( SQLITE_FLOAT==2 );
- assert( SQLITE_TEXT==3 );
- assert( SQLITE_BLOB==4 );
- assert( SQLITE_NULL==5 );
- /* EVIDENCE-OF: R-01470-60482 The sqlite3_value_type(V) interface returns
- ** the datatype code for the initial datatype of the sqlite3_value object
- ** V. The returned value is one of SQLITE_INTEGER, SQLITE_FLOAT,
- ** SQLITE_TEXT, SQLITE_BLOB, or SQLITE_NULL. */
- sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC);
-}
-
-
-/*
-** Implementation of the length() function
-*/
-static void lengthFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- switch( sqlite3_value_type(argv[0]) ){
- case SQLITE_BLOB:
- case SQLITE_INTEGER:
- case SQLITE_FLOAT: {
- sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
- break;
- }
- case SQLITE_TEXT: {
- const unsigned char *z = sqlite3_value_text(argv[0]);
- const unsigned char *z0;
- unsigned char c;
- if( z==0 ) return;
- z0 = z;
- while( (c = *z)!=0 ){
- z++;
- if( c>=0xc0 ){
- while( (*z & 0xc0)==0x80 ){ z++; z0++; }
- }
- }
- sqlite3_result_int(context, (int)(z-z0));
- break;
- }
- default: {
- sqlite3_result_null(context);
- break;
- }
- }
-}
-
-/*
-** Implementation of the abs() function.
-**
-** IMP: R-23979-26855 The abs(X) function returns the absolute value of
-** the numeric argument X.
-*/
-static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- switch( sqlite3_value_type(argv[0]) ){
- case SQLITE_INTEGER: {
- i64 iVal = sqlite3_value_int64(argv[0]);
- if( iVal<0 ){
- if( iVal==SMALLEST_INT64 ){
- /* IMP: R-31676-45509 If X is the integer -9223372036854775808
- ** then abs(X) throws an integer overflow error since there is no
- ** equivalent positive 64-bit two complement value. */
- sqlite3_result_error(context, "integer overflow", -1);
- return;
- }
- iVal = -iVal;
- }
- sqlite3_result_int64(context, iVal);
- break;
- }
- case SQLITE_NULL: {
- /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */
- sqlite3_result_null(context);
- break;
- }
- default: {
- /* Because sqlite3_value_double() returns 0.0 if the argument is not
- ** something that can be converted into a number, we have:
- ** IMP: R-01992-00519 Abs(X) returns 0.0 if X is a string or blob
- ** that cannot be converted to a numeric value.
- */
- double rVal = sqlite3_value_double(argv[0]);
- if( rVal<0 ) rVal = -rVal;
- sqlite3_result_double(context, rVal);
- break;
- }
- }
-}
-
-/*
-** Implementation of the instr() function.
-**
-** instr(haystack,needle) finds the first occurrence of needle
-** in haystack and returns the number of previous characters plus 1,
-** or 0 if needle does not occur within haystack.
-**
-** If both haystack and needle are BLOBs, then the result is one more than
-** the number of bytes in haystack prior to the first occurrence of needle,
-** or 0 if needle never occurs in haystack.
-*/
-static void instrFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zHaystack;
- const unsigned char *zNeedle;
- int nHaystack;
- int nNeedle;
- int typeHaystack, typeNeedle;
- int N = 1;
- int isText;
-
- UNUSED_PARAMETER(argc);
- typeHaystack = sqlite3_value_type(argv[0]);
- typeNeedle = sqlite3_value_type(argv[1]);
- if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
- nHaystack = sqlite3_value_bytes(argv[0]);
- nNeedle = sqlite3_value_bytes(argv[1]);
- if( nNeedle>0 ){
- if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
- zHaystack = sqlite3_value_blob(argv[0]);
- zNeedle = sqlite3_value_blob(argv[1]);
- isText = 0;
- }else{
- zHaystack = sqlite3_value_text(argv[0]);
- zNeedle = sqlite3_value_text(argv[1]);
- isText = 1;
- }
- if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
- while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
- N++;
- do{
- nHaystack--;
- zHaystack++;
- }while( isText && (zHaystack[0]&0xc0)==0x80 );
- }
- if( nNeedle>nHaystack ) N = 0;
- }
- sqlite3_result_int(context, N);
-}
-
-/*
-** Implementation of the printf() function.
-*/
-static void printfFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- PrintfArguments x;
- StrAccum str;
- const char *zFormat;
- int n;
- sqlite3 *db = sqlite3_context_db_handle(context);
-
- if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
- x.nArg = argc-1;
- x.nUsed = 0;
- x.apArg = argv+1;
- sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
- str.printfFlags = SQLITE_PRINTF_SQLFUNC;
- sqlite3_str_appendf(&str, zFormat, &x);
- n = str.nChar;
- sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
- SQLITE_DYNAMIC);
- }
-}
-
-/*
-** Implementation of the substr() function.
-**
-** substr(x,p1,p2) returns p2 characters of x[] beginning with p1.
-** p1 is 1-indexed. So substr(x,1,1) returns the first character
-** of x. If x is text, then we actually count UTF-8 characters.
-** If x is a blob, then we count bytes.
-**
-** If p1 is negative, then we begin abs(p1) from the end of x[].
-**
-** If p2 is negative, return the p2 characters preceding p1.
-*/
-static void substrFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *z;
- const unsigned char *z2;
- int len;
- int p0type;
- i64 p1, p2;
- int negP2 = 0;
-
- assert( argc==3 || argc==2 );
- if( sqlite3_value_type(argv[1])==SQLITE_NULL
- || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL)
- ){
- return;
- }
- p0type = sqlite3_value_type(argv[0]);
- p1 = sqlite3_value_int(argv[1]);
- if( p0type==SQLITE_BLOB ){
- len = sqlite3_value_bytes(argv[0]);
- z = sqlite3_value_blob(argv[0]);
- if( z==0 ) return;
- assert( len==sqlite3_value_bytes(argv[0]) );
- }else{
- z = sqlite3_value_text(argv[0]);
- if( z==0 ) return;
- len = 0;
- if( p1<0 ){
- for(z2=z; *z2; len++){
- SQLITE_SKIP_UTF8(z2);
- }
- }
- }
-#ifdef SQLITE_SUBSTR_COMPATIBILITY
- /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as
- ** as substr(X,1,N) - it returns the first N characters of X. This
- ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8]
- ** from 2009-02-02 for compatibility of applications that exploited the
- ** old buggy behavior. */
- if( p1==0 ) p1 = 1; /* <rdar://problem/6778339> */
-#endif
- if( argc==3 ){
- p2 = sqlite3_value_int(argv[2]);
- if( p2<0 ){
- p2 = -p2;
- negP2 = 1;
- }
- }else{
- p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
- }
- if( p1<0 ){
- p1 += len;
- if( p1<0 ){
- p2 += p1;
- if( p2<0 ) p2 = 0;
- p1 = 0;
- }
- }else if( p1>0 ){
- p1--;
- }else if( p2>0 ){
- p2--;
- }
- if( negP2 ){
- p1 -= p2;
- if( p1<0 ){
- p2 += p1;
- p1 = 0;
- }
- }
- assert( p1>=0 && p2>=0 );
- if( p0type!=SQLITE_BLOB ){
- while( *z && p1 ){
- SQLITE_SKIP_UTF8(z);
- p1--;
- }
- for(z2=z; *z2 && p2; p2--){
- SQLITE_SKIP_UTF8(z2);
- }
- sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
- SQLITE_UTF8);
- }else{
- if( p1+p2>len ){
- p2 = len-p1;
- if( p2<0 ) p2 = 0;
- }
- sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
- }
-}
-
-/*
-** Implementation of the round() function
-*/
-#ifndef SQLITE_OMIT_FLOATING_POINT
-static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- int n = 0;
- double r;
- char *zBuf;
- assert( argc==1 || argc==2 );
- if( argc==2 ){
- if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
- n = sqlite3_value_int(argv[1]);
- if( n>30 ) n = 30;
- if( n<0 ) n = 0;
- }
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- r = sqlite3_value_double(argv[0]);
- /* If Y==0 and X will fit in a 64-bit int,
- ** handle the rounding directly,
- ** otherwise use printf.
- */
- if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
- r = (double)((sqlite_int64)(r+0.5));
- }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
- r = -(double)((sqlite_int64)((-r)+0.5));
- }else{
- zBuf = sqlite3_mprintf("%.*f",n,r);
- if( zBuf==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
- sqlite3_free(zBuf);
- }
- sqlite3_result_double(context, r);
-}
-#endif
-
-/*
-** Allocate nByte bytes of space using sqlite3Malloc(). If the
-** allocation fails, call sqlite3_result_error_nomem() to notify
-** the database handle that malloc() has failed and return NULL.
-** If nByte is larger than the maximum string or blob length, then
-** raise an SQLITE_TOOBIG exception and return NULL.
-*/
-static void *contextMalloc(sqlite3_context *context, i64 nByte){
- char *z;
- sqlite3 *db = sqlite3_context_db_handle(context);
- assert( nByte>0 );
- testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] );
- testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
- if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- sqlite3_result_error_toobig(context);
- z = 0;
- }else{
- z = sqlite3Malloc(nByte);
- if( !z ){
- sqlite3_result_error_nomem(context);
- }
- }
- return z;
-}
-
-/*
-** Implementation of the upper() and lower() SQL functions.
-*/
-static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- char *z1;
- const char *z2;
- int i, n;
- UNUSED_PARAMETER(argc);
- z2 = (char*)sqlite3_value_text(argv[0]);
- n = sqlite3_value_bytes(argv[0]);
- /* Verify that the call to _bytes() does not invalidate the _text() pointer */
- assert( z2==(char*)sqlite3_value_text(argv[0]) );
- if( z2 ){
- z1 = contextMalloc(context, ((i64)n)+1);
- if( z1 ){
- for(i=0; i<n; i++){
- z1[i] = (char)sqlite3Toupper(z2[i]);
- }
- sqlite3_result_text(context, z1, n, sqlite3_free);
- }
- }
-}
-static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- char *z1;
- const char *z2;
- int i, n;
- UNUSED_PARAMETER(argc);
- z2 = (char*)sqlite3_value_text(argv[0]);
- n = sqlite3_value_bytes(argv[0]);
- /* Verify that the call to _bytes() does not invalidate the _text() pointer */
- assert( z2==(char*)sqlite3_value_text(argv[0]) );
- if( z2 ){
- z1 = contextMalloc(context, ((i64)n)+1);
- if( z1 ){
- for(i=0; i<n; i++){
- z1[i] = sqlite3Tolower(z2[i]);
- }
- sqlite3_result_text(context, z1, n, sqlite3_free);
- }
- }
-}
-
-/*
-** Some functions like COALESCE() and IFNULL() and UNLIKELY() are implemented
-** as VDBE code so that unused argument values do not have to be computed.
-** However, we still need some kind of function implementation for this
-** routines in the function table. The noopFunc macro provides this.
-** noopFunc will never be called so it doesn't matter what the implementation
-** is. We might as well use the "version()" function as a substitute.
-*/
-#define noopFunc versionFunc /* Substitute function - never called */
-
-/*
-** Implementation of random(). Return a random integer.
-*/
-static void randomFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- sqlite_int64 r;
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- sqlite3_randomness(sizeof(r), &r);
- if( r<0 ){
- /* We need to prevent a random number of 0x8000000000000000
- ** (or -9223372036854775808) since when you do abs() of that
- ** number of you get the same value back again. To do this
- ** in a way that is testable, mask the sign bit off of negative
- ** values, resulting in a positive value. Then take the
- ** 2s complement of that positive value. The end result can
- ** therefore be no less than -9223372036854775807.
- */
- r = -(r & LARGEST_INT64);
- }
- sqlite3_result_int64(context, r);
-}
-
-/*
-** Implementation of randomblob(N). Return a random blob
-** that is N bytes long.
-*/
-static void randomBlob(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int n;
- unsigned char *p;
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- n = sqlite3_value_int(argv[0]);
- if( n<1 ){
- n = 1;
- }
- p = contextMalloc(context, n);
- if( p ){
- sqlite3_randomness(n, p);
- sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
- }
-}
-
-/*
-** Implementation of the last_insert_rowid() SQL function. The return
-** value is the same as the sqlite3_last_insert_rowid() API function.
-*/
-static void last_insert_rowid(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a
- ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface
- ** function. */
- sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
-}
-
-/*
-** Implementation of the changes() SQL function.
-**
-** IMP: R-62073-11209 The changes() SQL function is a wrapper
-** around the sqlite3_changes() C/C++ function and hence follows the same
-** rules for counting changes.
-*/
-static void changes(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- sqlite3_result_int(context, sqlite3_changes(db));
-}
-
-/*
-** Implementation of the total_changes() SQL function. The return value is
-** the same as the sqlite3_total_changes() API function.
-*/
-static void total_changes(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-52756-41993 This function is a wrapper around the
- ** sqlite3_total_changes() C/C++ interface. */
- sqlite3_result_int(context, sqlite3_total_changes(db));
-}
-
-/*
-** A structure defining how to do GLOB-style comparisons.
-*/
-struct compareInfo {
- u8 matchAll; /* "*" or "%" */
- u8 matchOne; /* "?" or "_" */
- u8 matchSet; /* "[" or 0 */
- u8 noCase; /* true to ignore case differences */
-};
-
-/*
-** For LIKE and GLOB matching on EBCDIC machines, assume that every
-** character is exactly one byte in size. Also, provde the Utf8Read()
-** macro for fast reading of the next character in the common case where
-** the next character is ASCII.
-*/
-#if defined(SQLITE_EBCDIC)
-# define sqlite3Utf8Read(A) (*((*A)++))
-# define Utf8Read(A) (*(A++))
-#else
-# define Utf8Read(A) (A[0]<0x80?*(A++):sqlite3Utf8Read(&A))
-#endif
-
-static const struct compareInfo globInfo = { '*', '?', '[', 0 };
-/* The correct SQL-92 behavior is for the LIKE operator to ignore
-** case. Thus 'a' LIKE 'A' would be true. */
-static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
-/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
-** is case sensitive causing 'a' LIKE 'A' to be false */
-static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
-
-/*
-** Possible error returns from patternMatch()
-*/
-#define SQLITE_MATCH 0
-#define SQLITE_NOMATCH 1
-#define SQLITE_NOWILDCARDMATCH 2
-
-/*
-** Compare two UTF-8 strings for equality where the first string is
-** a GLOB or LIKE expression. Return values:
-**
-** SQLITE_MATCH: Match
-** SQLITE_NOMATCH: No match
-** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards.
-**
-** Globbing rules:
-**
-** '*' Matches any sequence of zero or more characters.
-**
-** '?' Matches exactly one character.
-**
-** [...] Matches one character from the enclosed list of
-** characters.
-**
-** [^...] Matches one character not in the enclosed list.
-**
-** With the [...] and [^...] matching, a ']' character can be included
-** in the list by making it the first character after '[' or '^'. A
-** range of characters can be specified using '-'. Example:
-** "[a-z]" matches any single lower-case letter. To match a '-', make
-** it the last character in the list.
-**
-** Like matching rules:
-**
-** '%' Matches any sequence of zero or more characters
-**
-*** '_' Matches any one character
-**
-** Ec Where E is the "esc" character and c is any other
-** character, including '%', '_', and esc, match exactly c.
-**
-** The comments within this routine usually assume glob matching.
-**
-** This routine is usually quick, but can be N**2 in the worst case.
-*/
-static int patternCompare(
- const u8 *zPattern, /* The glob pattern */
- const u8 *zString, /* The string to compare against the glob */
- const struct compareInfo *pInfo, /* Information about how to do the compare */
- u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */
-){
- u32 c, c2; /* Next pattern and input string chars */
- u32 matchOne = pInfo->matchOne; /* "?" or "_" */
- u32 matchAll = pInfo->matchAll; /* "*" or "%" */
- u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
- const u8 *zEscaped = 0; /* One past the last escaped input char */
-
- while( (c = Utf8Read(zPattern))!=0 ){
- if( c==matchAll ){ /* Match "*" */
- /* Skip over multiple "*" characters in the pattern. If there
- ** are also "?" characters, skip those as well, but consume a
- ** single character of the input string for each "?" skipped */
- while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
- if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
- return SQLITE_NOWILDCARDMATCH;
- }
- }
- if( c==0 ){
- return SQLITE_MATCH; /* "*" at the end of the pattern matches */
- }else if( c==matchOther ){
- if( pInfo->matchSet==0 ){
- c = sqlite3Utf8Read(&zPattern);
- if( c==0 ) return SQLITE_NOWILDCARDMATCH;
- }else{
- /* "[...]" immediately follows the "*". We have to do a slow
- ** recursive search in this case, but it is an unusual case. */
- assert( matchOther<0x80 ); /* '[' is a single-byte character */
- while( *zString ){
- int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther);
- if( bMatch!=SQLITE_NOMATCH ) return bMatch;
- SQLITE_SKIP_UTF8(zString);
- }
- return SQLITE_NOWILDCARDMATCH;
- }
- }
-
- /* At this point variable c contains the first character of the
- ** pattern string past the "*". Search in the input string for the
- ** first matching character and recursively continue the match from
- ** that point.
- **
- ** For a case-insensitive search, set variable cx to be the same as
- ** c but in the other case and search the input string for either
- ** c or cx.
- */
- if( c<=0x80 ){
- char zStop[3];
- int bMatch;
- if( noCase ){
- zStop[0] = sqlite3Toupper(c);
- zStop[1] = sqlite3Tolower(c);
- zStop[2] = 0;
- }else{
- zStop[0] = c;
- zStop[1] = 0;
- }
- while(1){
- zString += strcspn((const char*)zString, zStop);
- if( zString[0]==0 ) break;
- zString++;
- bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
- if( bMatch!=SQLITE_NOMATCH ) return bMatch;
- }
- }else{
- int bMatch;
- while( (c2 = Utf8Read(zString))!=0 ){
- if( c2!=c ) continue;
- bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
- if( bMatch!=SQLITE_NOMATCH ) return bMatch;
- }
- }
- return SQLITE_NOWILDCARDMATCH;
- }
- if( c==matchOther ){
- if( pInfo->matchSet==0 ){
- c = sqlite3Utf8Read(&zPattern);
- if( c==0 ) return SQLITE_NOMATCH;
- zEscaped = zPattern;
- }else{
- u32 prior_c = 0;
- int seen = 0;
- int invert = 0;
- c = sqlite3Utf8Read(&zString);
- if( c==0 ) return SQLITE_NOMATCH;
- c2 = sqlite3Utf8Read(&zPattern);
- if( c2=='^' ){
- invert = 1;
- c2 = sqlite3Utf8Read(&zPattern);
- }
- if( c2==']' ){
- if( c==']' ) seen = 1;
- c2 = sqlite3Utf8Read(&zPattern);
- }
- while( c2 && c2!=']' ){
- if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
- c2 = sqlite3Utf8Read(&zPattern);
- if( c>=prior_c && c<=c2 ) seen = 1;
- prior_c = 0;
- }else{
- if( c==c2 ){
- seen = 1;
- }
- prior_c = c2;
- }
- c2 = sqlite3Utf8Read(&zPattern);
- }
- if( c2==0 || (seen ^ invert)==0 ){
- return SQLITE_NOMATCH;
- }
- continue;
- }
- }
- c2 = Utf8Read(zString);
- if( c==c2 ) continue;
- if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) && c<0x80 && c2<0x80 ){
- continue;
- }
- if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
- return SQLITE_NOMATCH;
- }
- return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH;
-}
-
-/*
-** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and
-** non-zero if there is no match.
-*/
-int sqlite3_strglob(const char *zGlobPattern, const char *zString){
- return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
-}
-
-/*
-** The sqlite3_strlike() interface. Return 0 on a match and non-zero for
-** a miss - like strcmp().
-*/
-int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
- return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
-}
-
-/*
-** Count the number of times that the LIKE operator (or GLOB which is
-** just a variation of LIKE) gets called. This is used for testing
-** only.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_like_count = 0;
-#endif
-
-
-/*
-** Implementation of the like() SQL function. This function implements
-** the build-in LIKE operator. The first argument to the function is the
-** pattern and the second argument is the string. So, the SQL statements:
-**
-** A LIKE B
-**
-** is implemented as like(B,A).
-**
-** This same function (with a different compareInfo structure) computes
-** the GLOB operator.
-*/
-static void likeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zA, *zB;
- u32 escape;
- int nPat;
- sqlite3 *db = sqlite3_context_db_handle(context);
- struct compareInfo *pInfo = sqlite3_user_data(context);
-
-#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- if( sqlite3_value_type(argv[0])==SQLITE_BLOB
- || sqlite3_value_type(argv[1])==SQLITE_BLOB
- ){
-#ifdef SQLITE_TEST
- sqlite3_like_count++;
-#endif
- sqlite3_result_int(context, 0);
- return;
- }
-#endif
- zB = sqlite3_value_text(argv[0]);
- zA = sqlite3_value_text(argv[1]);
-
- /* Limit the length of the LIKE or GLOB pattern to avoid problems
- ** of deep recursion and N*N behavior in patternCompare().
- */
- nPat = sqlite3_value_bytes(argv[0]);
- testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] );
- testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 );
- if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
- sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
- return;
- }
- assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */
-
- if( argc==3 ){
- /* The escape character string must consist of a single UTF-8 character.
- ** Otherwise, return an error.
- */
- const unsigned char *zEsc = sqlite3_value_text(argv[2]);
- if( zEsc==0 ) return;
- if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){
- sqlite3_result_error(context,
- "ESCAPE expression must be a single character", -1);
- return;
- }
- escape = sqlite3Utf8Read(&zEsc);
- }else{
- escape = pInfo->matchSet;
- }
- if( zA && zB ){
-#ifdef SQLITE_TEST
- sqlite3_like_count++;
-#endif
- sqlite3_result_int(context,
- patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
- }
-}
-
-/*
-** Implementation of the NULLIF(x,y) function. The result is the first
-** argument if the arguments are different. The result is NULL if the
-** arguments are equal to each other.
-*/
-static void nullifFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- CollSeq *pColl = sqlite3GetFuncCollSeq(context);
- UNUSED_PARAMETER(NotUsed);
- if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){
- sqlite3_result_value(context, argv[0]);
- }
-}
-
-/*
-** Implementation of the sqlite_version() function. The result is the version
-** of the SQLite library that is running.
-*/
-static void versionFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-48699-48617 This function is an SQL wrapper around the
- ** sqlite3_libversion() C-interface. */
- sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC);
-}
-
-/*
-** Implementation of the sqlite_source_id() function. The result is a string
-** that identifies the particular version of the source code used to build
-** SQLite.
-*/
-static void sourceidFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
-){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-24470-31136 This function is an SQL wrapper around the
- ** sqlite3_sourceid() C interface. */
- sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
-}
-
-/*
-** Implementation of the sqlite_log() function. This is a wrapper around
-** sqlite3_log(). The return value is NULL. The function exists purely for
-** its side-effects.
-*/
-static void errlogFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- UNUSED_PARAMETER(argc);
- UNUSED_PARAMETER(context);
- sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1]));
-}
-
-/*
-** Implementation of the sqlite_compileoption_used() function.
-** The result is an integer that identifies if the compiler option
-** was used to build SQLite.
-*/
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-static void compileoptionusedFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zOptName;
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL
- ** function is a wrapper around the sqlite3_compileoption_used() C/C++
- ** function.
- */
- if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
- sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
- }
-}
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-
-/*
-** Implementation of the sqlite_compileoption_get() function.
-** The result is a string that identifies the compiler options
-** used to build SQLite.
-*/
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-static void compileoptiongetFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int n;
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function
- ** is a wrapper around the sqlite3_compileoption_get() C/C++ function.
- */
- n = sqlite3_value_int(argv[0]);
- sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
-}
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-
-/* Array for converting from half-bytes (nybbles) into ASCII hex
-** digits. */
-static const char hexdigits[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-/*
-** Implementation of the QUOTE() function. This function takes a single
-** argument. If the argument is numeric, the return value is the same as
-** the argument. If the argument is NULL, the return value is the string
-** "NULL". Otherwise, the argument is enclosed in single quotes with
-** single-quote escapes.
-*/
-static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- switch( sqlite3_value_type(argv[0]) ){
- case SQLITE_FLOAT: {
- double r1, r2;
- char zBuf[50];
- r1 = sqlite3_value_double(argv[0]);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
- sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
- if( r1!=r2 ){
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
- }
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_result_value(context, argv[0]);
- break;
- }
- case SQLITE_BLOB: {
- char *zText = 0;
- char const *zBlob = sqlite3_value_blob(argv[0]);
- int nBlob = sqlite3_value_bytes(argv[0]);
- assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
- zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
- if( zText ){
- int i;
- for(i=0; i<nBlob; i++){
- zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
- zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F];
- }
- zText[(nBlob*2)+2] = '\'';
- zText[(nBlob*2)+3] = '\0';
- zText[0] = 'X';
- zText[1] = '\'';
- sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
- sqlite3_free(zText);
- }
- break;
- }
- case SQLITE_TEXT: {
- int i,j;
- u64 n;
- const unsigned char *zArg = sqlite3_value_text(argv[0]);
- char *z;
-
- if( zArg==0 ) return;
- for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
- z = contextMalloc(context, ((i64)i)+((i64)n)+3);
- if( z ){
- z[0] = '\'';
- for(i=0, j=1; zArg[i]; i++){
- z[j++] = zArg[i];
- if( zArg[i]=='\'' ){
- z[j++] = '\'';
- }
- }
- z[j++] = '\'';
- z[j] = 0;
- sqlite3_result_text(context, z, j, sqlite3_free);
- }
- break;
- }
- default: {
- assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
- sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
- break;
- }
- }
-}
-
-/*
-** The unicode() function. Return the integer unicode code-point value
-** for the first character of the input string.
-*/
-static void unicodeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *z = sqlite3_value_text(argv[0]);
- (void)argc;
- if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z));
-}
-
-/*
-** The char() function takes zero or more arguments, each of which is
-** an integer. It constructs a string where each character of the string
-** is the unicode character for the corresponding integer argument.
-*/
-static void charFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- unsigned char *z, *zOut;
- int i;
- zOut = z = sqlite3_malloc64( argc*4+1 );
- if( z==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- for(i=0; i<argc; i++){
- sqlite3_int64 x;
- unsigned c;
- x = sqlite3_value_int64(argv[i]);
- if( x<0 || x>0x10ffff ) x = 0xfffd;
- c = (unsigned)(x & 0x1fffff);
- if( c<0x00080 ){
- *zOut++ = (u8)(c&0xFF);
- }else if( c<0x00800 ){
- *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);
- *zOut++ = 0x80 + (u8)(c & 0x3F);
- }else if( c<0x10000 ){
- *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);
- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
- *zOut++ = 0x80 + (u8)(c & 0x3F);
- }else{
- *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);
- *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);
- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
- *zOut++ = 0x80 + (u8)(c & 0x3F);
- } \
- }
- sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8);
-}
-
-/*
-** The hex() function. Interpret the argument as a blob. Return
-** a hexadecimal rendering as text.
-*/
-static void hexFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int i, n;
- const unsigned char *pBlob;
- char *zHex, *z;
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- pBlob = sqlite3_value_blob(argv[0]);
- n = sqlite3_value_bytes(argv[0]);
- assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
- z = zHex = contextMalloc(context, ((i64)n)*2 + 1);
- if( zHex ){
- for(i=0; i<n; i++, pBlob++){
- unsigned char c = *pBlob;
- *(z++) = hexdigits[(c>>4)&0xf];
- *(z++) = hexdigits[c&0xf];
- }
- *z = 0;
- sqlite3_result_text(context, zHex, n*2, sqlite3_free);
- }
-}
-
-/*
-** The zeroblob(N) function returns a zero-filled blob of size N bytes.
-*/
-static void zeroblobFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- i64 n;
- int rc;
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- n = sqlite3_value_int64(argv[0]);
- if( n<0 ) n = 0;
- rc = sqlite3_result_zeroblob64(context, n); /* IMP: R-00293-64994 */
- if( rc ){
- sqlite3_result_error_code(context, rc);
- }
-}
-
-/*
-** The replace() function. Three arguments are all strings: call
-** them A, B, and C. The result is also a string which is derived
-** from A by replacing every occurrence of B with C. The match
-** must be exact. Collating sequences are not used.
-*/
-static void replaceFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zStr; /* The input string A */
- const unsigned char *zPattern; /* The pattern string B */
- const unsigned char *zRep; /* The replacement string C */
- unsigned char *zOut; /* The output */
- int nStr; /* Size of zStr */
- int nPattern; /* Size of zPattern */
- int nRep; /* Size of zRep */
- i64 nOut; /* Maximum size of zOut */
- int loopLimit; /* Last zStr[] that might match zPattern[] */
- int i, j; /* Loop counters */
- unsigned cntExpand; /* Number zOut expansions */
- sqlite3 *db = sqlite3_context_db_handle(context);
-
- assert( argc==3 );
- UNUSED_PARAMETER(argc);
- zStr = sqlite3_value_text(argv[0]);
- if( zStr==0 ) return;
- nStr = sqlite3_value_bytes(argv[0]);
- assert( zStr==sqlite3_value_text(argv[0]) ); /* No encoding change */
- zPattern = sqlite3_value_text(argv[1]);
- if( zPattern==0 ){
- assert( sqlite3_value_type(argv[1])==SQLITE_NULL
- || sqlite3_context_db_handle(context)->mallocFailed );
- return;
- }
- if( zPattern[0]==0 ){
- assert( sqlite3_value_type(argv[1])!=SQLITE_NULL );
- sqlite3_result_value(context, argv[0]);
- return;
- }
- nPattern = sqlite3_value_bytes(argv[1]);
- assert( zPattern==sqlite3_value_text(argv[1]) ); /* No encoding change */
- zRep = sqlite3_value_text(argv[2]);
- if( zRep==0 ) return;
- nRep = sqlite3_value_bytes(argv[2]);
- assert( zRep==sqlite3_value_text(argv[2]) );
- nOut = nStr + 1;
- assert( nOut<SQLITE_MAX_LENGTH );
- zOut = contextMalloc(context, (i64)nOut);
- if( zOut==0 ){
- return;
- }
- loopLimit = nStr - nPattern;
- cntExpand = 0;
- for(i=j=0; i<=loopLimit; i++){
- if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
- zOut[j++] = zStr[i];
- }else{
- if( nRep>nPattern ){
- nOut += nRep - nPattern;
- testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
- testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
- if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- sqlite3_result_error_toobig(context);
- sqlite3_free(zOut);
- return;
- }
- cntExpand++;
- if( (cntExpand&(cntExpand-1))==0 ){
- /* Grow the size of the output buffer only on substitutions
- ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
- u8 *zOld;
- zOld = zOut;
- zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
- if( zOut==0 ){
- sqlite3_result_error_nomem(context);
- sqlite3_free(zOld);
- return;
- }
- }
- }
- memcpy(&zOut[j], zRep, nRep);
- j += nRep;
- i += nPattern-1;
- }
- }
- assert( j+nStr-i+1<=nOut );
- memcpy(&zOut[j], &zStr[i], nStr-i);
- j += nStr - i;
- assert( j<=nOut );
- zOut[j] = 0;
- sqlite3_result_text(context, (char*)zOut, j, sqlite3_free);
-}
-
-/*
-** Implementation of the TRIM(), LTRIM(), and RTRIM() functions.
-** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both.
-*/
-static void trimFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const unsigned char *zIn; /* Input string */
- const unsigned char *zCharSet; /* Set of characters to trim */
- int nIn; /* Number of bytes in input */
- int flags; /* 1: trimleft 2: trimright 3: trim */
- int i; /* Loop counter */
- unsigned char *aLen = 0; /* Length of each character in zCharSet */
- unsigned char **azChar = 0; /* Individual characters in zCharSet */
- int nChar; /* Number of characters in zCharSet */
-
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
- return;
- }
- zIn = sqlite3_value_text(argv[0]);
- if( zIn==0 ) return;
- nIn = sqlite3_value_bytes(argv[0]);
- assert( zIn==sqlite3_value_text(argv[0]) );
- if( argc==1 ){
- static const unsigned char lenOne[] = { 1 };
- static unsigned char * const azOne[] = { (u8*)" " };
- nChar = 1;
- aLen = (u8*)lenOne;
- azChar = (unsigned char **)azOne;
- zCharSet = 0;
- }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
- return;
- }else{
- const unsigned char *z;
- for(z=zCharSet, nChar=0; *z; nChar++){
- SQLITE_SKIP_UTF8(z);
- }
- if( nChar>0 ){
- azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
- if( azChar==0 ){
- return;
- }
- aLen = (unsigned char*)&azChar[nChar];
- for(z=zCharSet, nChar=0; *z; nChar++){
- azChar[nChar] = (unsigned char *)z;
- SQLITE_SKIP_UTF8(z);
- aLen[nChar] = (u8)(z - azChar[nChar]);
- }
- }
- }
- if( nChar>0 ){
- flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
- if( flags & 1 ){
- while( nIn>0 ){
- int len = 0;
- for(i=0; i<nChar; i++){
- len = aLen[i];
- if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
- }
- if( i>=nChar ) break;
- zIn += len;
- nIn -= len;
- }
- }
- if( flags & 2 ){
- while( nIn>0 ){
- int len = 0;
- for(i=0; i<nChar; i++){
- len = aLen[i];
- if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
- }
- if( i>=nChar ) break;
- nIn -= len;
- }
- }
- if( zCharSet ){
- sqlite3_free(azChar);
- }
- }
- sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
-}
-
-
-#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
-/*
-** The "unknown" function is automatically substituted in place of
-** any unrecognized function name when doing an EXPLAIN or EXPLAIN QUERY PLAN
-** when the SQLITE_ENABLE_UNKNOWN_FUNCTION compile-time option is used.
-** When the "sqlite3" command-line shell is built using this functionality,
-** that allows an EXPLAIN or EXPLAIN QUERY PLAN for complex queries
-** involving application-defined functions to be examined in a generic
-** sqlite3 shell.
-*/
-static void unknownFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- /* no-op */
-}
-#endif /*SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION*/
-
-
-/* IMP: R-25361-16150 This function is omitted from SQLite by default. It
-** is only available if the SQLITE_SOUNDEX compile-time option is used
-** when SQLite is built.
-*/
-#ifdef SQLITE_SOUNDEX
-/*
-** Compute the soundex encoding of a word.
-**
-** IMP: R-59782-00072 The soundex(X) function returns a string that is the
-** soundex encoding of the string X.
-*/
-static void soundexFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- char zResult[8];
- const u8 *zIn;
- int i, j;
- static const unsigned char iCode[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
- 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
- 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
- };
- assert( argc==1 );
- zIn = (u8*)sqlite3_value_text(argv[0]);
- if( zIn==0 ) zIn = (u8*)"";
- for(i=0; zIn[i] && !sqlite3Isalpha(zIn[i]); i++){}
- if( zIn[i] ){
- u8 prevcode = iCode[zIn[i]&0x7f];
- zResult[0] = sqlite3Toupper(zIn[i]);
- for(j=1; j<4 && zIn[i]; i++){
- int code = iCode[zIn[i]&0x7f];
- if( code>0 ){
- if( code!=prevcode ){
- prevcode = code;
- zResult[j++] = code + '0';
- }
- }else{
- prevcode = 0;
- }
- }
- while( j<4 ){
- zResult[j++] = '0';
- }
- zResult[j] = 0;
- sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT);
- }else{
- /* IMP: R-64894-50321 The string "?000" is returned if the argument
- ** is NULL or contains no ASCII alphabetic characters. */
- sqlite3_result_text(context, "?000", 4, SQLITE_STATIC);
- }
-}
-#endif /* SQLITE_SOUNDEX */
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-/*
-** A function that loads a shared-library extension then returns NULL.
-*/
-static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
- const char *zFile = (const char *)sqlite3_value_text(argv[0]);
- const char *zProc;
- sqlite3 *db = sqlite3_context_db_handle(context);
- char *zErrMsg = 0;
-
- /* Disallow the load_extension() SQL function unless the SQLITE_LoadExtFunc
- ** flag is set. See the sqlite3_enable_load_extension() API.
- */
- if( (db->flags & SQLITE_LoadExtFunc)==0 ){
- sqlite3_result_error(context, "not authorized", -1);
- return;
- }
-
- if( argc==2 ){
- zProc = (const char *)sqlite3_value_text(argv[1]);
- }else{
- zProc = 0;
- }
- if( zFile && sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){
- sqlite3_result_error(context, zErrMsg, -1);
- sqlite3_free(zErrMsg);
- }
-}
-#endif
-
-
-/*
-** An instance of the following structure holds the context of a
-** sum() or avg() aggregate computation.
-*/
-typedef struct SumCtx SumCtx;
-struct SumCtx {
- double rSum; /* Floating point sum */
- i64 iSum; /* Integer sum */
- i64 cnt; /* Number of elements summed */
- u8 overflow; /* True if integer overflow seen */
- u8 approx; /* True if non-integer value was input to the sum */
-};
-
-/*
-** Routines used to compute the sum, average, and total.
-**
-** The SUM() function follows the (broken) SQL standard which means
-** that it returns NULL if it sums over no inputs. TOTAL returns
-** 0.0 in that case. In addition, TOTAL always returns a float where
-** SUM might return an integer if it never encounters a floating point
-** value. TOTAL never fails, but SUM might through an exception if
-** it overflows an integer.
-*/
-static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
- SumCtx *p;
- int type;
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- p = sqlite3_aggregate_context(context, sizeof(*p));
- type = sqlite3_value_numeric_type(argv[0]);
- if( p && type!=SQLITE_NULL ){
- p->cnt++;
- if( type==SQLITE_INTEGER ){
- i64 v = sqlite3_value_int64(argv[0]);
- p->rSum += v;
- if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){
- p->overflow = 1;
- }
- }else{
- p->rSum += sqlite3_value_double(argv[0]);
- p->approx = 1;
- }
- }
-}
-static void sumFinalize(sqlite3_context *context){
- SumCtx *p;
- p = sqlite3_aggregate_context(context, 0);
- if( p && p->cnt>0 ){
- if( p->overflow ){
- sqlite3_result_error(context,"integer overflow",-1);
- }else if( p->approx ){
- sqlite3_result_double(context, p->rSum);
- }else{
- sqlite3_result_int64(context, p->iSum);
- }
- }
-}
-static void avgFinalize(sqlite3_context *context){
- SumCtx *p;
- p = sqlite3_aggregate_context(context, 0);
- if( p && p->cnt>0 ){
- sqlite3_result_double(context, p->rSum/(double)p->cnt);
- }
-}
-static void totalFinalize(sqlite3_context *context){
- SumCtx *p;
- p = sqlite3_aggregate_context(context, 0);
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- sqlite3_result_double(context, p ? p->rSum : (double)0);
-}
-
-/*
-** The following structure keeps track of state information for the
-** count() aggregate function.
-*/
-typedef struct CountCtx CountCtx;
-struct CountCtx {
- i64 n;
-};
-
-/*
-** Routines to implement the count() aggregate function.
-*/
-static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
- CountCtx *p;
- p = sqlite3_aggregate_context(context, sizeof(*p));
- if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){
- p->n++;
- }
-
-#ifndef SQLITE_OMIT_DEPRECATED
- /* The sqlite3_aggregate_count() function is deprecated. But just to make
- ** sure it still operates correctly, verify that its count agrees with our
- ** internal count when using count(*) and when the total count can be
- ** expressed as a 32-bit integer. */
- assert( argc==1 || p==0 || p->n>0x7fffffff
- || p->n==sqlite3_aggregate_count(context) );
-#endif
-}
-static void countFinalize(sqlite3_context *context){
- CountCtx *p;
- p = sqlite3_aggregate_context(context, 0);
- sqlite3_result_int64(context, p ? p->n : 0);
-}
-
-/*
-** Routines to implement min() and max() aggregate functions.
-*/
-static void minmaxStep(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- Mem *pArg = (Mem *)argv[0];
- Mem *pBest;
- UNUSED_PARAMETER(NotUsed);
-
- pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));
- if( !pBest ) return;
-
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
- if( pBest->flags ) sqlite3SkipAccumulatorLoad(context);
- }else if( pBest->flags ){
- int max;
- int cmp;
- CollSeq *pColl = sqlite3GetFuncCollSeq(context);
- /* This step function is used for both the min() and max() aggregates,
- ** the only difference between the two being that the sense of the
- ** comparison is inverted. For the max() aggregate, the
- ** sqlite3_user_data() function returns (void *)-1. For min() it
- ** returns (void *)db, where db is the sqlite3* database pointer.
- ** Therefore the next statement sets variable 'max' to 1 for the max()
- ** aggregate, or 0 for min().
- */
- max = sqlite3_user_data(context)!=0;
- cmp = sqlite3MemCompare(pBest, pArg, pColl);
- if( (max && cmp<0) || (!max && cmp>0) ){
- sqlite3VdbeMemCopy(pBest, pArg);
- }else{
- sqlite3SkipAccumulatorLoad(context);
- }
- }else{
- pBest->db = sqlite3_context_db_handle(context);
- sqlite3VdbeMemCopy(pBest, pArg);
- }
-}
-static void minMaxFinalize(sqlite3_context *context){
- sqlite3_value *pRes;
- pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
- if( pRes ){
- if( pRes->flags ){
- sqlite3_result_value(context, pRes);
- }
- sqlite3VdbeMemRelease(pRes);
- }
-}
-
-/*
-** group_concat(EXPR, ?SEPARATOR?)
-*/
-static void groupConcatStep(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zVal;
- StrAccum *pAccum;
- const char *zSep;
- int nVal, nSep;
- assert( argc==1 || argc==2 );
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
-
- if( pAccum ){
- sqlite3 *db = sqlite3_context_db_handle(context);
- int firstTerm = pAccum->mxAlloc==0;
- pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
- if( !firstTerm ){
- if( argc==2 ){
- zSep = (char*)sqlite3_value_text(argv[1]);
- nSep = sqlite3_value_bytes(argv[1]);
- }else{
- zSep = ",";
- nSep = 1;
- }
- if( zSep ) sqlite3_str_append(pAccum, zSep, nSep);
- }
- zVal = (char*)sqlite3_value_text(argv[0]);
- nVal = sqlite3_value_bytes(argv[0]);
- if( zVal ) sqlite3_str_append(pAccum, zVal, nVal);
- }
-}
-static void groupConcatFinalize(sqlite3_context *context){
- StrAccum *pAccum;
- pAccum = sqlite3_aggregate_context(context, 0);
- if( pAccum ){
- if( pAccum->accError==SQLITE_TOOBIG ){
- sqlite3_result_error_toobig(context);
- }else if( pAccum->accError==SQLITE_NOMEM ){
- sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
- sqlite3_free);
- }
- }
-}
-
-/*
-** This routine does per-connection function registration. Most
-** of the built-in functions above are part of the global function set.
-** This routine only deals with those that are not global.
-*/
-void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){
- int rc = sqlite3_overload_function(db, "MATCH", 2);
- assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
- if( rc==SQLITE_NOMEM ){
- sqlite3OomFault(db);
- }
-}
-
-/*
-** Set the LIKEOPT flag on the 2-argument function with the given name.
-*/
-static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
- FuncDef *pDef;
- pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0);
- if( ALWAYS(pDef) ){
- pDef->funcFlags |= flagVal;
- }
-}
-
-/*
-** Register the built-in LIKE and GLOB functions. The caseSensitive
-** parameter determines whether or not the LIKE operator is case
-** sensitive. GLOB is always case sensitive.
-*/
-void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
- struct compareInfo *pInfo;
- if( caseSensitive ){
- pInfo = (struct compareInfo*)&likeInfoAlt;
- }else{
- pInfo = (struct compareInfo*)&likeInfoNorm;
- }
- sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
- sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
- sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
- (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0);
- setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
- setLikeOptFlag(db, "like",
- caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
-}
-
-/*
-** pExpr points to an expression which implements a function. If
-** it is appropriate to apply the LIKE optimization to that function
-** then set aWc[0] through aWc[2] to the wildcard characters and the
-** escape character and then return TRUE. If the function is not a
-** LIKE-style function then return FALSE.
-**
-** The expression "a LIKE b ESCAPE c" is only considered a valid LIKE
-** operator if c is a string literal that is exactly one byte in length.
-** That one byte is stored in aWc[3]. aWc[3] is set to zero if there is
-** no ESCAPE clause.
-**
-** *pIsNocase is set to true if uppercase and lowercase are equivalent for
-** the function (default for LIKE). If the function makes the distinction
-** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to
-** false.
-*/
-int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
- FuncDef *pDef;
- int nExpr;
- if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){
- return 0;
- }
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- nExpr = pExpr->x.pList->nExpr;
- pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
- if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
- return 0;
- }
- if( nExpr<3 ){
- aWc[3] = 0;
- }else{
- Expr *pEscape = pExpr->x.pList->a[2].pExpr;
- char *zEscape;
- if( pEscape->op!=TK_STRING ) return 0;
- zEscape = pEscape->u.zToken;
- if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
- aWc[3] = zEscape[0];
- }
-
- /* The memcpy() statement assumes that the wildcard characters are
- ** the first three statements in the compareInfo structure. The
- ** asserts() that follow verify that assumption
- */
- memcpy(aWc, pDef->pUserData, 3);
- assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
- assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
- assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
- *pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0;
- return 1;
-}
-
-/*
-** All of the FuncDef structures in the aBuiltinFunc[] array above
-** to the global function hash table. This occurs at start-time (as
-** a consequence of calling sqlite3_initialize()).
-**
-** After this routine runs
-*/
-void sqlite3RegisterBuiltinFunctions(void){
- /*
- ** The following array holds FuncDef structures for all of the functions
- ** defined in this file.
- **
- ** The array cannot be constant since changes are made to the
- ** FuncDef.pHash elements at start-time. The elements of this array
- ** are read-only after initialization is complete.
- **
- ** For peak efficiency, put the most frequently used function last.
- */
- static FuncDef aBuiltinFunc[] = {
-#ifdef SQLITE_SOUNDEX
- FUNCTION(soundex, 1, 0, 0, soundexFunc ),
-#endif
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- VFUNCTION(load_extension, 1, 0, 0, loadExt ),
- VFUNCTION(load_extension, 2, 0, 0, loadExt ),
-#endif
-#if SQLITE_USER_AUTHENTICATION
- FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
-#endif
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
- DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
- DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
- FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
- FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
- FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
-#ifdef SQLITE_DEBUG
- FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
-#endif
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
- FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
- SQLITE_FUNC_TYPEOF),
-#endif
- FUNCTION(ltrim, 1, 1, 0, trimFunc ),
- FUNCTION(ltrim, 2, 1, 0, trimFunc ),
- FUNCTION(rtrim, 1, 2, 0, trimFunc ),
- FUNCTION(rtrim, 2, 2, 0, trimFunc ),
- FUNCTION(trim, 1, 3, 0, trimFunc ),
- FUNCTION(trim, 2, 3, 0, trimFunc ),
- FUNCTION(min, -1, 0, 1, minmaxFunc ),
- FUNCTION(min, 0, 0, 1, 0 ),
- AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize,
- SQLITE_FUNC_MINMAX ),
- FUNCTION(max, -1, 1, 1, minmaxFunc ),
- FUNCTION(max, 0, 1, 1, 0 ),
- AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize,
- SQLITE_FUNC_MINMAX ),
- FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
- FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
- FUNCTION(instr, 2, 0, 0, instrFunc ),
- FUNCTION(printf, -1, 0, 0, printfFunc ),
- FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
- FUNCTION(char, -1, 0, 0, charFunc ),
- FUNCTION(abs, 1, 0, 0, absFunc ),
-#ifndef SQLITE_OMIT_FLOATING_POINT
- FUNCTION(round, 1, 0, 0, roundFunc ),
- FUNCTION(round, 2, 0, 0, roundFunc ),
-#endif
- FUNCTION(upper, 1, 0, 0, upperFunc ),
- FUNCTION(lower, 1, 0, 0, lowerFunc ),
- FUNCTION(hex, 1, 0, 0, hexFunc ),
- FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
- VFUNCTION(random, 0, 0, 0, randomFunc ),
- VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
- FUNCTION(nullif, 2, 0, 1, nullifFunc ),
- DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
- DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
- FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
- FUNCTION(quote, 1, 0, 0, quoteFunc ),
- VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
- VFUNCTION(changes, 0, 0, 0, changes ),
- VFUNCTION(total_changes, 0, 0, 0, total_changes ),
- FUNCTION(replace, 3, 0, 0, replaceFunc ),
- FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
- FUNCTION(substr, 2, 0, 0, substrFunc ),
- FUNCTION(substr, 3, 0, 0, substrFunc ),
- AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
- AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
- AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
- AGGREGATE2(count, 0, 0, 0, countStep, countFinalize,
- SQLITE_FUNC_COUNT ),
- AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
- AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
- AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
-
- LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
-#ifdef SQLITE_CASE_SENSITIVE_LIKE
- LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
- LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
-#else
- LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
- LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
-#endif
-#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- FUNCTION(unknown, -1, 0, 0, unknownFunc ),
-#endif
- FUNCTION(coalesce, 1, 0, 0, 0 ),
- FUNCTION(coalesce, 0, 0, 0, 0 ),
- FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
- };
-#ifndef SQLITE_OMIT_ALTERTABLE
- sqlite3AlterFunctions();
-#endif
-#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
- sqlite3AnalyzeFunctions();
-#endif
- sqlite3RegisterDateTimeFunctions();
- sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));
-
-#if 0 /* Enable to print out how the built-in functions are hashed */
- {
- int i;
- FuncDef *p;
- for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
- printf("FUNC-HASH %02d:", i);
- for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
- int n = sqlite3Strlen30(p->zName);
- int h = p->zName[0] + n;
- printf(" %s(%d)", p->zName, h);
- }
- printf("\n");
- }
- }
-#endif
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/global.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/global.c
deleted file mode 100644
index f0362d1e044..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/global.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
-** 2008 June 13
-**
-** 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 contains definitions of global variables and constants.
-*/
-#include "sqliteInt.h"
-
-/* An array to map all upper-case characters into their corresponding
-** lower-case character.
-**
-** SQLite only considers US-ASCII (or EBCDIC) characters. We do not
-** handle case conversions for the UTF character set since the tables
-** involved are nearly as big or bigger than SQLite itself.
-*/
-const unsigned char sqlite3UpperToLower[] = {
-#ifdef SQLITE_ASCII
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
- 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
- 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
- 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
- 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
- 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
- 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
- 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
- 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
- 252,253,254,255
-#endif
-#ifdef SQLITE_EBCDIC
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
- 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */
- 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */
- 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */
- 160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
- 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
- 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
- 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
- 224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
- 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
-#endif
-};
-
-/*
-** The following 256 byte lookup table is used to support SQLites built-in
-** equivalents to the following standard library functions:
-**
-** isspace() 0x01
-** isalpha() 0x02
-** isdigit() 0x04
-** isalnum() 0x06
-** isxdigit() 0x08
-** toupper() 0x20
-** SQLite identifier character 0x40
-** Quote character 0x80
-**
-** Bit 0x20 is set if the mapped character requires translation to upper
-** case. i.e. if the character is a lower-case ASCII character.
-** If x is a lower-case ASCII character, then its upper-case equivalent
-** is (x - 0x20). Therefore toupper() can be implemented as:
-**
-** (x & ~(map[x]&0x20))
-**
-** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
-** array. tolower() is used more often than toupper() by SQLite.
-**
-** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
-** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
-** non-ASCII UTF character. Hence the test for whether or not a character is
-** part of an identifier is 0x46.
-*/
-#ifdef SQLITE_ASCII
-const unsigned char sqlite3CtypeMap[256] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */
- 0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27 !"#$%&' */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
- 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
-
- 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
- 0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
- 0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
- 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
-
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */
-
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
-};
-#endif
-
-/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards
-** compatibility for legacy applications, the URI filename capability is
-** disabled by default.
-**
-** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled
-** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options.
-**
-** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
-** disabled. The default value may be changed by compiling with the
-** SQLITE_USE_URI symbol defined.
-**
-** URI filenames are enabled by default if SQLITE_HAS_CODEC is
-** enabled.
-*/
-#ifndef SQLITE_USE_URI
-# ifdef SQLITE_HAS_CODEC
-# define SQLITE_USE_URI 1
-# else
-# define SQLITE_USE_URI 0
-# endif
-#endif
-
-/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
-** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
-** that compile-time option is omitted.
-*/
-#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
-# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
-#endif
-
-/* The minimum PMA size is set to this value multiplied by the database
-** page size in bytes.
-*/
-#ifndef SQLITE_SORTER_PMASZ
-# define SQLITE_SORTER_PMASZ 250
-#endif
-
-/* Statement journals spill to disk when their size exceeds the following
-** threshold (in bytes). 0 means that statement journals are created and
-** written to disk immediately (the default behavior for SQLite versions
-** before 3.12.0). -1 means always keep the entire statement journal in
-** memory. (The statement journal is also always held entirely in memory
-** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this
-** setting.)
-*/
-#ifndef SQLITE_STMTJRNL_SPILL
-# define SQLITE_STMTJRNL_SPILL (64*1024)
-#endif
-
-/*
-** The default lookaside-configuration, the format "SZ,N". SZ is the
-** number of bytes in each lookaside slot (should be a multiple of 8)
-** and N is the number of slots. The lookaside-configuration can be
-** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
-** or at run-time for an individual database connection using
-** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
-*/
-#ifndef SQLITE_DEFAULT_LOOKASIDE
-# define SQLITE_DEFAULT_LOOKASIDE 1200,100
-#endif
-
-
-/*
-** The following singleton contains the global configuration for
-** the SQLite library.
-*/
-SQLITE_WSD struct Sqlite3Config sqlite3Config = {
- SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
- 1, /* bCoreMutex */
- SQLITE_THREADSAFE==1, /* bFullMutex */
- SQLITE_USE_URI, /* bOpenUri */
- SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
- 0, /* bSmallMalloc */
- 0x7ffffffe, /* mxStrlen */
- 0, /* neverCorrupt */
- SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
- SQLITE_STMTJRNL_SPILL, /* nStmtSpill */
- {0,0,0,0,0,0,0,0}, /* m */
- {0,0,0,0,0,0,0,0,0}, /* mutex */
- {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
- (void*)0, /* pHeap */
- 0, /* nHeap */
- 0, 0, /* mnHeap, mxHeap */
- SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */
- SQLITE_MAX_MMAP_SIZE, /* mxMmap */
- (void*)0, /* pPage */
- 0, /* szPage */
- SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */
- 0, /* mxParserStack */
- 0, /* sharedCacheEnabled */
- SQLITE_SORTER_PMASZ, /* szPma */
- /* All the rest should always be initialized to zero */
- 0, /* isInit */
- 0, /* inProgress */
- 0, /* isMutexInit */
- 0, /* isMallocInit */
- 0, /* isPCacheInit */
- 0, /* nRefInitMutex */
- 0, /* pInitMutex */
- 0, /* xLog */
- 0, /* pLogArg */
-#ifdef SQLITE_ENABLE_SQLLOG
- 0, /* xSqllog */
- 0, /* pSqllogArg */
-#endif
-#ifdef SQLITE_VDBE_COVERAGE
- 0, /* xVdbeBranch */
- 0, /* pVbeBranchArg */
-#endif
-#ifndef SQLITE_UNTESTABLE
- 0, /* xTestCallback */
-#endif
- 0, /* bLocaltimeFault */
- 0x7ffffffe, /* iOnceResetThreshold */
- SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */
-};
-
-/*
-** Hash table for global functions - functions common to all
-** database connections. After initialization, this table is
-** read-only.
-*/
-FuncDefHash sqlite3BuiltinFunctions;
-
-/*
-** Constant tokens for values 0 and 1.
-*/
-const Token sqlite3IntTokens[] = {
- { "0", 1 },
- { "1", 1 }
-};
-
-#ifdef VDBE_PROFILE
-/*
-** The following performance counter can be used in place of
-** sqlite3Hwtime() for profiling. This is a no-op on standard builds.
-*/
-sqlite3_uint64 sqlite3NProfileCnt = 0;
-#endif
-
-/*
-** The value of the "pending" byte must be 0x40000000 (1 byte past the
-** 1-gibabyte boundary) in a compatible database. SQLite never uses
-** the database page that contains the pending byte. It never attempts
-** to read or write that page. The pending byte page is set aside
-** for use by the VFS layers as space for managing file locks.
-**
-** During testing, it is often desirable to move the pending byte to
-** a different position in the file. This allows code that has to
-** deal with the pending byte to run on files that are much smaller
-** than 1 GiB. The sqlite3_test_control() interface can be used to
-** move the pending byte.
-**
-** IMPORTANT: Changing the pending byte to any value other than
-** 0x40000000 results in an incompatible database file format!
-** Changing the pending byte during operation will result in undefined
-** and incorrect behavior.
-*/
-#ifndef SQLITE_OMIT_WSD
-int sqlite3PendingByte = 0x40000000;
-#endif
-
-#include "opcodes.h"
-/*
-** Properties of opcodes. The OPFLG_INITIALIZER macro is
-** created by mkopcodeh.awk during compilation. Data is obtained
-** from the comments following the "case OP_xxxx:" statements in
-** the vdbe.c file.
-*/
-const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
-
-/*
-** Name of the default collating sequence
-*/
-const char sqlite3StrBINARY[] = "BINARY";
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/hash.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/hash.c
deleted file mode 100644
index 79bb85ac01d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/hash.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the implementation of generic hash-tables
-** used in SQLite.
-*/
-#include "sqliteInt.h"
-#include <assert.h>
-
-/* Turn bulk memory into a hash table object by initializing the
-** fields of the Hash structure.
-**
-** "pNew" is a pointer to the hash table that is to be initialized.
-*/
-void sqlite3HashInit(Hash *pNew){
- assert( pNew!=0 );
- pNew->first = 0;
- pNew->count = 0;
- pNew->htsize = 0;
- pNew->ht = 0;
-}
-
-/* Remove all entries from a hash table. Reclaim all memory.
-** Call this routine to delete a hash table or to reset a hash table
-** to the empty state.
-*/
-void sqlite3HashClear(Hash *pH){
- HashElem *elem; /* For looping over all elements of the table */
-
- assert( pH!=0 );
- elem = pH->first;
- pH->first = 0;
- sqlite3_free(pH->ht);
- pH->ht = 0;
- pH->htsize = 0;
- while( elem ){
- HashElem *next_elem = elem->next;
- sqlite3_free(elem);
- elem = next_elem;
- }
- pH->count = 0;
-}
-
-/*
-** The hashing function.
-*/
-static unsigned int strHash(const char *z){
- unsigned int h = 0;
- unsigned char c;
- while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
- /* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
- ** 0x9e3779b1 is 2654435761 which is the closest prime number to
- ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
- h += sqlite3UpperToLower[c];
- h *= 0x9e3779b1;
- }
- return h;
-}
-
-
-/* Link pNew element into the hash table pH. If pEntry!=0 then also
-** insert pNew into the pEntry hash bucket.
-*/
-static void insertElement(
- Hash *pH, /* The complete hash table */
- struct _ht *pEntry, /* The entry into which pNew is inserted */
- HashElem *pNew /* The element to be inserted */
-){
- HashElem *pHead; /* First element already in pEntry */
- if( pEntry ){
- pHead = pEntry->count ? pEntry->chain : 0;
- pEntry->count++;
- pEntry->chain = pNew;
- }else{
- pHead = 0;
- }
- if( pHead ){
- pNew->next = pHead;
- pNew->prev = pHead->prev;
- if( pHead->prev ){ pHead->prev->next = pNew; }
- else { pH->first = pNew; }
- pHead->prev = pNew;
- }else{
- pNew->next = pH->first;
- if( pH->first ){ pH->first->prev = pNew; }
- pNew->prev = 0;
- pH->first = pNew;
- }
-}
-
-
-/* Resize the hash table so that it cantains "new_size" buckets.
-**
-** The hash table might fail to resize if sqlite3_malloc() fails or
-** if the new size is the same as the prior size.
-** Return TRUE if the resize occurs and false if not.
-*/
-static int rehash(Hash *pH, unsigned int new_size){
- struct _ht *new_ht; /* The new hash table */
- HashElem *elem, *next_elem; /* For looping over existing elements */
-
-#if SQLITE_MALLOC_SOFT_LIMIT>0
- if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
- new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
- }
- if( new_size==pH->htsize ) return 0;
-#endif
-
- /* The inability to allocates space for a larger hash table is
- ** a performance hit but it is not a fatal error. So mark the
- ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
- ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
- ** only zeroes the requested number of bytes whereas this module will
- ** use the actual amount of space allocated for the hash table (which
- ** may be larger than the requested amount).
- */
- sqlite3BeginBenignMalloc();
- new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
- sqlite3EndBenignMalloc();
-
- if( new_ht==0 ) return 0;
- sqlite3_free(pH->ht);
- pH->ht = new_ht;
- pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
- memset(new_ht, 0, new_size*sizeof(struct _ht));
- for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- unsigned int h = strHash(elem->pKey) % new_size;
- next_elem = elem->next;
- insertElement(pH, &new_ht[h], elem);
- }
- return 1;
-}
-
-/* This function (for internal use only) locates an element in an
-** hash table that matches the given key. If no element is found,
-** a pointer to a static null element with HashElem.data==0 is returned.
-** If pH is not NULL, then the hash for this key is written to *pH.
-*/
-static HashElem *findElementWithHash(
- const Hash *pH, /* The pH to be searched */
- const char *pKey, /* The key we are searching for */
- unsigned int *pHash /* Write the hash value here */
-){
- HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- unsigned int h; /* The computed hash */
- static HashElem nullElement = { 0, 0, 0, 0 };
-
- if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
- struct _ht *pEntry;
- h = strHash(pKey) % pH->htsize;
- pEntry = &pH->ht[h];
- elem = pEntry->chain;
- count = pEntry->count;
- }else{
- h = 0;
- elem = pH->first;
- count = pH->count;
- }
- if( pHash ) *pHash = h;
- while( count-- ){
- assert( elem!=0 );
- if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- return &nullElement;
-}
-
-/* Remove a single entry from the hash table given a pointer to that
-** element and a hash on the element's key.
-*/
-static void removeElementGivenHash(
- Hash *pH, /* The pH containing "elem" */
- HashElem* elem, /* The element to be removed from the pH */
- unsigned int h /* Hash value for the element */
-){
- struct _ht *pEntry;
- if( elem->prev ){
- elem->prev->next = elem->next;
- }else{
- pH->first = elem->next;
- }
- if( elem->next ){
- elem->next->prev = elem->prev;
- }
- if( pH->ht ){
- pEntry = &pH->ht[h];
- if( pEntry->chain==elem ){
- pEntry->chain = elem->next;
- }
- pEntry->count--;
- assert( pEntry->count>=0 );
- }
- sqlite3_free( elem );
- pH->count--;
- if( pH->count==0 ){
- assert( pH->first==0 );
- assert( pH->count==0 );
- sqlite3HashClear(pH);
- }
-}
-
-/* Attempt to locate an element of the hash table pH with a key
-** that matches pKey. Return the data for this element if it is
-** found, or NULL if there is no match.
-*/
-void *sqlite3HashFind(const Hash *pH, const char *pKey){
- assert( pH!=0 );
- assert( pKey!=0 );
- return findElementWithHash(pH, pKey, 0)->data;
-}
-
-/* Insert an element into the hash table pH. The key is pKey
-** and the data is "data".
-**
-** If no element exists with a matching key, then a new
-** element is created and NULL is returned.
-**
-** If another element already exists with the same key, then the
-** new data replaces the old data and the old data is returned.
-** The key is not copied in this instance. If a malloc fails, then
-** the new data is returned and the hash table is unchanged.
-**
-** If the "data" parameter to this function is NULL, then the
-** element corresponding to "key" is removed from the hash table.
-*/
-void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
- unsigned int h; /* the hash of the key modulo hash table size */
- HashElem *elem; /* Used to loop thru the element list */
- HashElem *new_elem; /* New element added to the pH */
-
- assert( pH!=0 );
- assert( pKey!=0 );
- elem = findElementWithHash(pH,pKey,&h);
- if( elem->data ){
- void *old_data = elem->data;
- if( data==0 ){
- removeElementGivenHash(pH,elem,h);
- }else{
- elem->data = data;
- elem->pKey = pKey;
- }
- return old_data;
- }
- if( data==0 ) return 0;
- new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
- if( new_elem==0 ) return data;
- new_elem->pKey = pKey;
- new_elem->data = data;
- pH->count++;
- if( pH->count>=10 && pH->count > 2*pH->htsize ){
- if( rehash(pH, pH->count*2) ){
- assert( pH->htsize>0 );
- h = strHash(pKey) % pH->htsize;
- }
- }
- insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/hash.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/hash.h
deleted file mode 100644
index 90540eda50e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/hash.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-** 2001 September 22
-**
-** 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 is the header file for the generic hash-table implementation
-** used in SQLite.
-*/
-#ifndef SQLITE_HASH_H
-#define SQLITE_HASH_H
-
-/* Forward declarations of structures. */
-typedef struct Hash Hash;
-typedef struct HashElem HashElem;
-
-/* A complete hash table is an instance of the following structure.
-** The internals of this structure are intended to be opaque -- client
-** code should not attempt to access or modify the fields of this structure
-** directly. Change this structure only by using the routines below.
-** However, some of the "procedures" and "functions" for modifying and
-** accessing this structure are really macros, so we can't really make
-** this structure opaque.
-**
-** All elements of the hash table are on a single doubly-linked list.
-** Hash.first points to the head of this list.
-**
-** There are Hash.htsize buckets. Each bucket points to a spot in
-** the global doubly-linked list. The contents of the bucket are the
-** element pointed to plus the next _ht.count-1 elements in the list.
-**
-** Hash.htsize and Hash.ht may be zero. In that case lookup is done
-** by a linear search of the global list. For small tables, the
-** Hash.ht table is never allocated because if there are few elements
-** in the table, it is faster to do a linear search than to manage
-** the hash table.
-*/
-struct Hash {
- unsigned int htsize; /* Number of buckets in the hash table */
- unsigned int count; /* Number of entries in this table */
- HashElem *first; /* The first element of the array */
- struct _ht { /* the hash table */
- int count; /* Number of entries with this hash */
- HashElem *chain; /* Pointer to first entry with this hash */
- } *ht;
-};
-
-/* Each element in the hash table is an instance of the following
-** structure. All elements are stored on a single doubly-linked list.
-**
-** Again, this structure is intended to be opaque, but it can't really
-** be opaque because it is used by macros.
-*/
-struct HashElem {
- HashElem *next, *prev; /* Next and previous elements in the table */
- void *data; /* Data associated with this element */
- const char *pKey; /* Key associated with this element */
-};
-
-/*
-** Access routines. To delete, insert a NULL pointer.
-*/
-void sqlite3HashInit(Hash*);
-void *sqlite3HashInsert(Hash*, const char *pKey, void *pData);
-void *sqlite3HashFind(const Hash*, const char *pKey);
-void sqlite3HashClear(Hash*);
-
-/*
-** Macros for looping over all elements of a hash table. The idiom is
-** like this:
-**
-** Hash h;
-** HashElem *p;
-** ...
-** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
-** SomeStructure *pData = sqliteHashData(p);
-** // do something with pData
-** }
-*/
-#define sqliteHashFirst(H) ((H)->first)
-#define sqliteHashNext(E) ((E)->next)
-#define sqliteHashData(E) ((E)->data)
-/* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */
-/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */
-
-/*
-** Number of entries in a hash table
-*/
-/* #define sqliteHashCount(H) ((H)->count) // NOT USED */
-
-#endif /* SQLITE_HASH_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/hwtime.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/hwtime.h
deleted file mode 100644
index 5b209db8afc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/hwtime.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
-** 2008 May 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 contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_HWTIME_H
-
-/*
-** The following routine only works on pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long val;
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
- return val;
- }
-
-#elif (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long long retval;
- unsigned long junk;
- __asm__ __volatile__ ("\n\
- 1: mftbu %1\n\
- mftb %L0\n\
- mftbu %0\n\
- cmpw %0,%1\n\
- bne 1b"
- : "=r" (retval), "=r" (junk));
- return retval;
- }
-
-#else
-
- #error Need implementation of sqlite3Hwtime() for your platform.
-
- /*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
- */
- sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/in-operator.md b/chromium/third_party/sqlite/sqlite-src-3240000/src/in-operator.md
deleted file mode 100644
index e9ad2101aa9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/in-operator.md
+++ /dev/null
@@ -1,107 +0,0 @@
-IN-Operator Implementation Notes
-================================
-
-## Definitions:
-
-An IN operator has one of the following formats:
-
->
- x IN (y1,y2,y3,...,yN)
- x IN (subquery)
-
-The "x" is referred to as the LHS (left-hand side). The list or subquery
-on the right is called the RHS (right-hand side). If the RHS is a list
-it must be a non-empty list. But if the RHS is a subquery, it can be an
-empty set.
-
-The LHS can be a scalar (a single quantity) or a vector (a list of
-two or or more values) or a subquery that returns one or more columns.
-We use the term "vector" to mean an actually list of values or a
-subquery that returns two or more columns. An isolated value or
-a subquery that returns a single columns is called a scalar.
-
-The RHS can be a subquery that returns a single column, a subquery
-that returns two or more columns, or a list of scalars. It is not
-currently support for the RHS to be a list of vectors.
-
-The number of columns for LHS must match the number of columns for
-the RHS. If the RHS is a list of values, then the LHS must be a
-scalar. If the RHS is a subquery returning N columns, then the LHS
-must be a vector of size N.
-
-NULL values can occur in either or both of the LHS and RHS.
-If the LHS contains only
-NULL values then we say that it is a "total-NULL". If the LHS contains
-some NULL values and some non-NULL values, then it is a "partial-NULL".
-For a scalar, there is no difference between a partial-NULL and a total-NULL.
-The RHS is a partial-NULL if any row contains a NULL value. The RHS is
-a total-NULL if it contains one or more rows that contain only NULL values.
-The LHS is called "non-NULL" if it contains no NULL values. The RHS is
-called "non-NULL" if it contains no NULL values in any row.
-
-The result of an IN operator is one of TRUE, FALSE, or NULL. A NULL result
-means that it cannot be determined if the LHS is contained in the RHS due
-to the presence of NULL values. In some contexts (for example, when the IN
-operator occurs in a WHERE clause)
-the system only needs a binary result: TRUE or NOT-TRUE. One can also
-to define a binary result of FALSE and NOT-FALSE, but
-it turns out that no extra optimizations are possible in that case, so if
-the FALSE/NOT-FALSE binary is needed, we have to compute the three-state
-TRUE/FALSE/NULL result and then combine the TRUE and NULL values into
-NOT-FALSE.
-
-A "NOT IN" operator is computed by first computing the equivalent IN
-operator, then interchanging the TRUE and FALSE results.
-
-## Simple Full-Scan Algorithm
-
-The following algorithm always compute the correct answer. However, this
-algorithm is suboptimal, especially if there are many rows on the RHS.
-
- 1. Set the null-flag to false
- 2. For each row in the RHS:
- <ol type='a'>
- <li> Compare the LHS against the RHS
- <li> If the LHS exactly matches the RHS, immediately return TRUE
- <li> If the comparison result is NULL, set the null-flag to true
- </ol>
- 3. If the null-flag is true, return NULL.
- 4. Return FALSE
-
-## Optimized Algorithm
-
-The following procedure computes the same answer as the simple full-scan
-algorithm, though it does so with less work in the common case. This
-is the algorithm that is implemented in SQLite.
-
- 1. If the RHS is a constant list of length 1 or 2, then rewrite the
- IN operator as a simple expression. Implement
-
- x IN (y1,y2)
-
- as if it were
-
- x=y1 OR x=y2
-
- This is the INDEX_NOOP optimization and is only undertaken if the
- IN operator is used for membership testing. If the IN operator is
- driving a loop, then skip this step entirely.
-
- 2. Check the LHS to see if it is a partial-NULL and if it is, jump
- ahead to step 5.
-
- 3. Do a binary search of the RHS using the LHS as a probe. If
- an exact match is found, return TRUE.
-
- 4. If the RHS is non-NULL then return FALSE.
-
- 5. If we do not need to distinguish between FALSE and NULL,
- then return FALSE.
-
- 6. For each row in the RHS, compare that row against the LHS and
- if the result is NULL, immediately return NULL. In the case
- of a scalar IN operator, we only need to look at the very first
- row the RHS because for a scalar RHS, all NULLs will always come
- first. If the RHS is empty, this step is a no-op.
-
- 7. Return FALSE.
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/insert.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/insert.c
deleted file mode 100644
index 3d516428345..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/insert.c
+++ /dev/null
@@ -1,2450 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains C code routines that are called by the parser
-** to handle INSERT statements in SQLite.
-*/
-#include "sqliteInt.h"
-
-/*
-** Generate code that will
-**
-** (1) acquire a lock for table pTab then
-** (2) open pTab as cursor iCur.
-**
-** If pTab is a WITHOUT ROWID table, then it is the PRIMARY KEY index
-** for that table that is actually opened.
-*/
-void sqlite3OpenTable(
- Parse *pParse, /* Generate code into this VDBE */
- int iCur, /* The cursor number of the table */
- int iDb, /* The database index in sqlite3.aDb[] */
- Table *pTab, /* The table to be opened */
- int opcode /* OP_OpenRead or OP_OpenWrite */
-){
- Vdbe *v;
- assert( !IsVirtual(pTab) );
- v = sqlite3GetVdbe(pParse);
- assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
- sqlite3TableLock(pParse, iDb, pTab->tnum,
- (opcode==OP_OpenWrite)?1:0, pTab->zName);
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
- VdbeComment((v, "%s", pTab->zName));
- }else{
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- assert( pPk!=0 );
- assert( pPk->tnum==pTab->tnum );
- sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
- sqlite3VdbeSetP4KeyInfo(pParse, pPk);
- VdbeComment((v, "%s", pTab->zName));
- }
-}
-
-/*
-** Return a pointer to the column affinity string associated with index
-** pIdx. A column affinity string has one character for each column in
-** the table, according to the affinity of the column:
-**
-** Character Column affinity
-** ------------------------------
-** 'A' BLOB
-** 'B' TEXT
-** 'C' NUMERIC
-** 'D' INTEGER
-** 'F' REAL
-**
-** An extra 'D' is appended to the end of the string to cover the
-** rowid that appears as the last column in every index.
-**
-** Memory for the buffer containing the column index affinity string
-** is managed along with the rest of the Index structure. It will be
-** released when sqlite3DeleteIndex() is called.
-*/
-const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
- if( !pIdx->zColAff ){
- /* The first time a column affinity string for a particular index is
- ** required, it is allocated and populated here. It is then stored as
- ** a member of the Index structure for subsequent use.
- **
- ** The column affinity string will eventually be deleted by
- ** sqliteDeleteIndex() when the Index structure itself is cleaned
- ** up.
- */
- int n;
- Table *pTab = pIdx->pTable;
- pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
- if( !pIdx->zColAff ){
- sqlite3OomFault(db);
- return 0;
- }
- for(n=0; n<pIdx->nColumn; n++){
- i16 x = pIdx->aiColumn[n];
- if( x>=0 ){
- pIdx->zColAff[n] = pTab->aCol[x].affinity;
- }else if( x==XN_ROWID ){
- pIdx->zColAff[n] = SQLITE_AFF_INTEGER;
- }else{
- char aff;
- assert( x==XN_EXPR );
- assert( pIdx->aColExpr!=0 );
- aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
- if( aff==0 ) aff = SQLITE_AFF_BLOB;
- pIdx->zColAff[n] = aff;
- }
- }
- pIdx->zColAff[n] = 0;
- }
-
- return pIdx->zColAff;
-}
-
-/*
-** Compute the affinity string for table pTab, if it has not already been
-** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
-**
-** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and
-** if iReg>0 then code an OP_Affinity opcode that will set the affinities
-** for register iReg and following. Or if affinities exists and iReg==0,
-** then just set the P4 operand of the previous opcode (which should be
-** an OP_MakeRecord) to the affinity string.
-**
-** A column affinity string has one character per column:
-**
-** Character Column affinity
-** ------------------------------
-** 'A' BLOB
-** 'B' TEXT
-** 'C' NUMERIC
-** 'D' INTEGER
-** 'E' REAL
-*/
-void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
- int i;
- char *zColAff = pTab->zColAff;
- if( zColAff==0 ){
- sqlite3 *db = sqlite3VdbeDb(v);
- zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
- if( !zColAff ){
- sqlite3OomFault(db);
- return;
- }
-
- for(i=0; i<pTab->nCol; i++){
- zColAff[i] = pTab->aCol[i].affinity;
- }
- do{
- zColAff[i--] = 0;
- }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
- pTab->zColAff = zColAff;
- }
- i = sqlite3Strlen30(zColAff);
- if( i ){
- if( iReg ){
- sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i);
- }else{
- sqlite3VdbeChangeP4(v, -1, zColAff, i);
- }
- }
-}
-
-/*
-** Return non-zero if the table pTab in database iDb or any of its indices
-** have been opened at any point in the VDBE program. This is used to see if
-** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can
-** run without using a temporary table for the results of the SELECT.
-*/
-static int readsTable(Parse *p, int iDb, Table *pTab){
- Vdbe *v = sqlite3GetVdbe(p);
- int i;
- int iEnd = sqlite3VdbeCurrentAddr(v);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0;
-#endif
-
- for(i=1; i<iEnd; i++){
- VdbeOp *pOp = sqlite3VdbeGetOp(v, i);
- assert( pOp!=0 );
- if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){
- Index *pIndex;
- int tnum = pOp->p2;
- if( tnum==pTab->tnum ){
- return 1;
- }
- for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
- if( tnum==pIndex->tnum ){
- return 1;
- }
- }
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pVTab ){
- assert( pOp->p4.pVtab!=0 );
- assert( pOp->p4type==P4_VTAB );
- return 1;
- }
-#endif
- }
- return 0;
-}
-
-#ifndef SQLITE_OMIT_AUTOINCREMENT
-/*
-** Locate or create an AutoincInfo structure associated with table pTab
-** which is in database iDb. Return the register number for the register
-** that holds the maximum rowid. Return zero if pTab is not an AUTOINCREMENT
-** table. (Also return zero when doing a VACUUM since we do not want to
-** update the AUTOINCREMENT counters during a VACUUM.)
-**
-** There is at most one AutoincInfo structure per table even if the
-** same table is autoincremented multiple times due to inserts within
-** triggers. A new AutoincInfo structure is created if this is the
-** first use of table pTab. On 2nd and subsequent uses, the original
-** AutoincInfo structure is used.
-**
-** Four consecutive registers are allocated:
-**
-** (1) The name of the pTab table.
-** (2) The maximum ROWID of pTab.
-** (3) The rowid in sqlite_sequence of pTab
-** (4) The original value of the max ROWID in pTab, or NULL if none
-**
-** The 2nd register is the one that is returned. That is all the
-** insert routine needs to know about.
-*/
-static int autoIncBegin(
- Parse *pParse, /* Parsing context */
- int iDb, /* Index of the database holding pTab */
- Table *pTab /* The table we are writing to */
-){
- int memId = 0; /* Register holding maximum rowid */
- assert( pParse->db->aDb[iDb].pSchema!=0 );
- if( (pTab->tabFlags & TF_Autoincrement)!=0
- && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0
- ){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
- AutoincInfo *pInfo;
- Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab;
-
- /* Verify that the sqlite_sequence table exists and is an ordinary
- ** rowid table with exactly two columns.
- ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
- if( pSeqTab==0
- || !HasRowid(pSeqTab)
- || IsVirtual(pSeqTab)
- || pSeqTab->nCol!=2
- ){
- pParse->nErr++;
- pParse->rc = SQLITE_CORRUPT_SEQUENCE;
- return 0;
- }
-
- pInfo = pToplevel->pAinc;
- while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
- if( pInfo==0 ){
- pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo));
- if( pInfo==0 ) return 0;
- pInfo->pNext = pToplevel->pAinc;
- pToplevel->pAinc = pInfo;
- pInfo->pTab = pTab;
- pInfo->iDb = iDb;
- pToplevel->nMem++; /* Register to hold name of table */
- pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */
- pToplevel->nMem +=2; /* Rowid in sqlite_sequence + orig max val */
- }
- memId = pInfo->regCtr;
- }
- return memId;
-}
-
-/*
-** This routine generates code that will initialize all of the
-** register used by the autoincrement tracker.
-*/
-void sqlite3AutoincrementBegin(Parse *pParse){
- AutoincInfo *p; /* Information about an AUTOINCREMENT */
- sqlite3 *db = pParse->db; /* The database connection */
- Db *pDb; /* Database only autoinc table */
- int memId; /* Register holding max rowid */
- Vdbe *v = pParse->pVdbe; /* VDBE under construction */
-
- /* This routine is never called during trigger-generation. It is
- ** only called from the top-level */
- assert( pParse->pTriggerTab==0 );
- assert( sqlite3IsToplevel(pParse) );
-
- assert( v ); /* We failed long ago if this is not so */
- for(p = pParse->pAinc; p; p = p->pNext){
- static const int iLn = VDBE_OFFSET_LINENO(2);
- static const VdbeOpList autoInc[] = {
- /* 0 */ {OP_Null, 0, 0, 0},
- /* 1 */ {OP_Rewind, 0, 10, 0},
- /* 2 */ {OP_Column, 0, 0, 0},
- /* 3 */ {OP_Ne, 0, 9, 0},
- /* 4 */ {OP_Rowid, 0, 0, 0},
- /* 5 */ {OP_Column, 0, 1, 0},
- /* 6 */ {OP_AddImm, 0, 0, 0},
- /* 7 */ {OP_Copy, 0, 0, 0},
- /* 8 */ {OP_Goto, 0, 11, 0},
- /* 9 */ {OP_Next, 0, 2, 0},
- /* 10 */ {OP_Integer, 0, 0, 0},
- /* 11 */ {OP_Close, 0, 0, 0}
- };
- VdbeOp *aOp;
- pDb = &db->aDb[p->iDb];
- memId = p->regCtr;
- assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
- sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
- sqlite3VdbeLoadString(v, memId-1, p->pTab->zName);
- aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn);
- if( aOp==0 ) break;
- aOp[0].p2 = memId;
- aOp[0].p3 = memId+2;
- aOp[2].p3 = memId;
- aOp[3].p1 = memId-1;
- aOp[3].p3 = memId;
- aOp[3].p5 = SQLITE_JUMPIFNULL;
- aOp[4].p2 = memId+1;
- aOp[5].p3 = memId;
- aOp[6].p1 = memId;
- aOp[7].p2 = memId+2;
- aOp[7].p1 = memId;
- aOp[10].p2 = memId;
- }
-}
-
-/*
-** Update the maximum rowid for an autoincrement calculation.
-**
-** This routine should be called when the regRowid register holds a
-** new rowid that is about to be inserted. If that new rowid is
-** larger than the maximum rowid in the memId memory cell, then the
-** memory cell is updated.
-*/
-static void autoIncStep(Parse *pParse, int memId, int regRowid){
- if( memId>0 ){
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid);
- }
-}
-
-/*
-** This routine generates the code needed to write autoincrement
-** maximum rowid values back into the sqlite_sequence register.
-** Every statement that might do an INSERT into an autoincrement
-** table (either directly or through triggers) needs to call this
-** routine just before the "exit" code.
-*/
-static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
- AutoincInfo *p;
- Vdbe *v = pParse->pVdbe;
- sqlite3 *db = pParse->db;
-
- assert( v );
- for(p = pParse->pAinc; p; p = p->pNext){
- static const int iLn = VDBE_OFFSET_LINENO(2);
- static const VdbeOpList autoIncEnd[] = {
- /* 0 */ {OP_NotNull, 0, 2, 0},
- /* 1 */ {OP_NewRowid, 0, 0, 0},
- /* 2 */ {OP_MakeRecord, 0, 2, 0},
- /* 3 */ {OP_Insert, 0, 0, 0},
- /* 4 */ {OP_Close, 0, 0, 0}
- };
- VdbeOp *aOp;
- Db *pDb = &db->aDb[p->iDb];
- int iRec;
- int memId = p->regCtr;
-
- iRec = sqlite3GetTempReg(pParse);
- assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
- sqlite3VdbeAddOp3(v, OP_Le, memId+2, sqlite3VdbeCurrentAddr(v)+7, memId);
- VdbeCoverage(v);
- sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
- aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn);
- if( aOp==0 ) break;
- aOp[0].p1 = memId+1;
- aOp[1].p2 = memId+1;
- aOp[2].p1 = memId-1;
- aOp[2].p3 = iRec;
- aOp[3].p2 = iRec;
- aOp[3].p3 = memId+1;
- aOp[3].p5 = OPFLAG_APPEND;
- sqlite3ReleaseTempReg(pParse, iRec);
- }
-}
-void sqlite3AutoincrementEnd(Parse *pParse){
- if( pParse->pAinc ) autoIncrementEnd(pParse);
-}
-#else
-/*
-** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines
-** above are all no-ops
-*/
-# define autoIncBegin(A,B,C) (0)
-# define autoIncStep(A,B,C)
-#endif /* SQLITE_OMIT_AUTOINCREMENT */
-
-
-/* Forward declaration */
-static int xferOptimization(
- Parse *pParse, /* Parser context */
- Table *pDest, /* The table we are inserting into */
- Select *pSelect, /* A SELECT statement to use as the data source */
- int onError, /* How to handle constraint errors */
- int iDbDest /* The database of pDest */
-);
-
-/*
-** This routine is called to handle SQL of the following forms:
-**
-** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),...
-** insert into TABLE (IDLIST) select
-** insert into TABLE (IDLIST) default values
-**
-** The IDLIST following the table name is always optional. If omitted,
-** then a list of all (non-hidden) columns for the table is substituted.
-** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST
-** is omitted.
-**
-** For the pSelect parameter holds the values to be inserted for the
-** first two forms shown above. A VALUES clause is really just short-hand
-** for a SELECT statement that omits the FROM clause and everything else
-** that follows. If the pSelect parameter is NULL, that means that the
-** DEFAULT VALUES form of the INSERT statement is intended.
-**
-** The code generated follows one of four templates. For a simple
-** insert with data coming from a single-row VALUES clause, the code executes
-** once straight down through. Pseudo-code follows (we call this
-** the "1st template"):
-**
-** open write cursor to <table> and its indices
-** put VALUES clause expressions into registers
-** write the resulting record into <table>
-** cleanup
-**
-** The three remaining templates assume the statement is of the form
-**
-** INSERT INTO <table> SELECT ...
-**
-** If the SELECT clause is of the restricted form "SELECT * FROM <table2>" -
-** in other words if the SELECT pulls all columns from a single table
-** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and
-** if <table2> and <table1> are distinct tables but have identical
-** schemas, including all the same indices, then a special optimization
-** is invoked that copies raw records from <table2> over to <table1>.
-** See the xferOptimization() function for the implementation of this
-** template. This is the 2nd template.
-**
-** open a write cursor to <table>
-** open read cursor on <table2>
-** transfer all records in <table2> over to <table>
-** close cursors
-** foreach index on <table>
-** open a write cursor on the <table> index
-** open a read cursor on the corresponding <table2> index
-** transfer all records from the read to the write cursors
-** close cursors
-** end foreach
-**
-** The 3rd template is for when the second template does not apply
-** and the SELECT clause does not read from <table> at any time.
-** The generated code follows this template:
-**
-** X <- A
-** goto B
-** A: setup for the SELECT
-** loop over the rows in the SELECT
-** load values into registers R..R+n
-** yield X
-** end loop
-** cleanup after the SELECT
-** end-coroutine X
-** B: open write cursor to <table> and its indices
-** C: yield X, at EOF goto D
-** insert the select result into <table> from R..R+n
-** goto C
-** D: cleanup
-**
-** The 4th template is used if the insert statement takes its
-** values from a SELECT but the data is being inserted into a table
-** that is also read as part of the SELECT. In the third form,
-** we have to use an intermediate table to store the results of
-** the select. The template is like this:
-**
-** X <- A
-** goto B
-** A: setup for the SELECT
-** loop over the tables in the SELECT
-** load value into register R..R+n
-** yield X
-** end loop
-** cleanup after the SELECT
-** end co-routine R
-** B: open temp table
-** L: yield X, at EOF goto M
-** insert row from R..R+n into temp table
-** goto L
-** M: open write cursor to <table> and its indices
-** rewind temp table
-** C: loop over rows of intermediate table
-** transfer values form intermediate table into <table>
-** end loop
-** D: cleanup
-*/
-void sqlite3Insert(
- Parse *pParse, /* Parser context */
- SrcList *pTabList, /* Name of table into which we are inserting */
- Select *pSelect, /* A SELECT statement to use as the data source */
- IdList *pColumn, /* Column names corresponding to IDLIST. */
- int onError, /* How to handle constraint errors */
- Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */
-){
- sqlite3 *db; /* The main database structure */
- Table *pTab; /* The table to insert into. aka TABLE */
- int i, j; /* Loop counters */
- Vdbe *v; /* Generate code into this virtual machine */
- Index *pIdx; /* For looping over indices of the table */
- int nColumn; /* Number of columns in the data */
- int nHidden = 0; /* Number of hidden columns if TABLE is virtual */
- int iDataCur = 0; /* VDBE cursor that is the main data repository */
- int iIdxCur = 0; /* First index cursor */
- int ipkColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
- int endOfLoop; /* Label for the end of the insertion loop */
- int srcTab = 0; /* Data comes from this temporary cursor if >=0 */
- int addrInsTop = 0; /* Jump to label "D" */
- int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */
- SelectDest dest; /* Destination for SELECT on rhs of INSERT */
- int iDb; /* Index of database holding TABLE */
- u8 useTempTable = 0; /* Store SELECT results in intermediate table */
- u8 appendFlag = 0; /* True if the insert is likely to be an append */
- u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
- u8 bIdListInOrder; /* True if IDLIST is in table order */
- ExprList *pList = 0; /* List of VALUES() to be inserted */
-
- /* Register allocations */
- int regFromSelect = 0;/* Base register for data coming from SELECT */
- int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */
- int regRowCount = 0; /* Memory cell used for the row counter */
- int regIns; /* Block of regs holding rowid+data being inserted */
- int regRowid; /* registers holding insert rowid */
- int regData; /* register holding first column to insert */
- int *aRegIdx = 0; /* One register allocated to each index */
-
-#ifndef SQLITE_OMIT_TRIGGER
- int isView; /* True if attempting to insert into a view */
- Trigger *pTrigger; /* List of triggers on pTab, if required */
- int tmask; /* Mask of trigger times */
-#endif
-
- db = pParse->db;
- if( pParse->nErr || db->mallocFailed ){
- goto insert_cleanup;
- }
- dest.iSDParm = 0; /* Suppress a harmless compiler warning */
-
- /* If the Select object is really just a simple VALUES() list with a
- ** single row (the common case) then keep that one row of values
- ** and discard the other (unused) parts of the pSelect object
- */
- if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
- pList = pSelect->pEList;
- pSelect->pEList = 0;
- sqlite3SelectDelete(db, pSelect);
- pSelect = 0;
- }
-
- /* Locate the table into which we will be inserting new information.
- */
- assert( pTabList->nSrc==1 );
- pTab = sqlite3SrcListLookup(pParse, pTabList);
- if( pTab==0 ){
- goto insert_cleanup;
- }
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDb<db->nDb );
- if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0,
- db->aDb[iDb].zDbSName) ){
- goto insert_cleanup;
- }
- withoutRowid = !HasRowid(pTab);
-
- /* Figure out if we have any triggers and if the table being
- ** inserted into is a view
- */
-#ifndef SQLITE_OMIT_TRIGGER
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
- isView = pTab->pSelect!=0;
-#else
-# define pTrigger 0
-# define tmask 0
-# define isView 0
-#endif
-#ifdef SQLITE_OMIT_VIEW
-# undef isView
-# define isView 0
-#endif
- assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
-
- /* If pTab is really a view, make sure it has been initialized.
- ** ViewGetColumnNames() is a no-op if pTab is not a view.
- */
- if( sqlite3ViewGetColumnNames(pParse, pTab) ){
- goto insert_cleanup;
- }
-
- /* Cannot insert into a read-only table.
- */
- if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
- goto insert_cleanup;
- }
-
- /* Allocate a VDBE
- */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto insert_cleanup;
- if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
- sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb);
-
-#ifndef SQLITE_OMIT_XFER_OPT
- /* If the statement is of the form
- **
- ** INSERT INTO <table1> SELECT * FROM <table2>;
- **
- ** Then special optimizations can be applied that make the transfer
- ** very fast and which reduce fragmentation of indices.
- **
- ** This is the 2nd template.
- */
- if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
- assert( !pTrigger );
- assert( pList==0 );
- goto insert_end;
- }
-#endif /* SQLITE_OMIT_XFER_OPT */
-
- /* If this is an AUTOINCREMENT table, look up the sequence number in the
- ** sqlite_sequence table and store it in memory cell regAutoinc.
- */
- regAutoinc = autoIncBegin(pParse, iDb, pTab);
-
- /* Allocate registers for holding the rowid of the new row,
- ** the content of the new row, and the assembled row record.
- */
- regRowid = regIns = pParse->nMem+1;
- pParse->nMem += pTab->nCol + 1;
- if( IsVirtual(pTab) ){
- regRowid++;
- pParse->nMem++;
- }
- regData = regRowid+1;
-
- /* If the INSERT statement included an IDLIST term, then make sure
- ** all elements of the IDLIST really are columns of the table and
- ** remember the column indices.
- **
- ** If the table has an INTEGER PRIMARY KEY column and that column
- ** is named in the IDLIST, then record in the ipkColumn variable
- ** the index into IDLIST of the primary key column. ipkColumn is
- ** the index of the primary key as it appears in IDLIST, not as
- ** is appears in the original table. (The index of the INTEGER
- ** PRIMARY KEY in the original table is pTab->iPKey.)
- */
- bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0;
- if( pColumn ){
- for(i=0; i<pColumn->nId; i++){
- pColumn->a[i].idx = -1;
- }
- for(i=0; i<pColumn->nId; i++){
- for(j=0; j<pTab->nCol; j++){
- if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
- pColumn->a[i].idx = j;
- if( i!=j ) bIdListInOrder = 0;
- if( j==pTab->iPKey ){
- ipkColumn = i; assert( !withoutRowid );
- }
- break;
- }
- }
- if( j>=pTab->nCol ){
- if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
- ipkColumn = i;
- bIdListInOrder = 0;
- }else{
- sqlite3ErrorMsg(pParse, "table %S has no column named %s",
- pTabList, 0, pColumn->a[i].zName);
- pParse->checkSchema = 1;
- goto insert_cleanup;
- }
- }
- }
- }
-
- /* Figure out how many columns of data are supplied. If the data
- ** is coming from a SELECT statement, then generate a co-routine that
- ** produces a single row of the SELECT on each invocation. The
- ** co-routine is the common header to the 3rd and 4th templates.
- */
- if( pSelect ){
- /* Data is coming from a SELECT or from a multi-row VALUES clause.
- ** Generate a co-routine to run the SELECT. */
- int regYield; /* Register holding co-routine entry-point */
- int addrTop; /* Top of the co-routine */
- int rc; /* Result code */
-
- regYield = ++pParse->nMem;
- addrTop = sqlite3VdbeCurrentAddr(v) + 1;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
- sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
- dest.iSdst = bIdListInOrder ? regData : 0;
- dest.nSdst = pTab->nCol;
- rc = sqlite3Select(pParse, pSelect, &dest);
- regFromSelect = dest.iSdst;
- if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
- sqlite3VdbeEndCoroutine(v, regYield);
- sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
- assert( pSelect->pEList );
- nColumn = pSelect->pEList->nExpr;
-
- /* Set useTempTable to TRUE if the result of the SELECT statement
- ** should be written into a temporary table (template 4). Set to
- ** FALSE if each output row of the SELECT can be written directly into
- ** the destination table (template 3).
- **
- ** A temp table must be used if the table being updated is also one
- ** of the tables being read by the SELECT statement. Also use a
- ** temp table in the case of row triggers.
- */
- if( pTrigger || readsTable(pParse, iDb, pTab) ){
- useTempTable = 1;
- }
-
- if( useTempTable ){
- /* Invoke the coroutine to extract information from the SELECT
- ** and add it to a transient table srcTab. The code generated
- ** here is from the 4th template:
- **
- ** B: open temp table
- ** L: yield X, goto M at EOF
- ** insert row from R..R+n into temp table
- ** goto L
- ** M: ...
- */
- int regRec; /* Register to hold packed record */
- int regTempRowid; /* Register to hold temp table ROWID */
- int addrL; /* Label "L" */
-
- srcTab = pParse->nTab++;
- regRec = sqlite3GetTempReg(pParse);
- regTempRowid = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
- addrL = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
- sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
- sqlite3VdbeGoto(v, addrL);
- sqlite3VdbeJumpHere(v, addrL);
- sqlite3ReleaseTempReg(pParse, regRec);
- sqlite3ReleaseTempReg(pParse, regTempRowid);
- }
- }else{
- /* This is the case if the data for the INSERT is coming from a
- ** single-row VALUES clause
- */
- NameContext sNC;
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- srcTab = -1;
- assert( useTempTable==0 );
- if( pList ){
- nColumn = pList->nExpr;
- if( sqlite3ResolveExprListNames(&sNC, pList) ){
- goto insert_cleanup;
- }
- }else{
- nColumn = 0;
- }
- }
-
- /* If there is no IDLIST term but the table has an integer primary
- ** key, the set the ipkColumn variable to the integer primary key
- ** column index in the original table definition.
- */
- if( pColumn==0 && nColumn>0 ){
- ipkColumn = pTab->iPKey;
- }
-
- /* Make sure the number of columns in the source data matches the number
- ** of columns to be inserted into the table.
- */
- for(i=0; i<pTab->nCol; i++){
- nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
- }
- if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
- sqlite3ErrorMsg(pParse,
- "table %S has %d columns but %d values were supplied",
- pTabList, 0, pTab->nCol-nHidden, nColumn);
- goto insert_cleanup;
- }
- if( pColumn!=0 && nColumn!=pColumn->nId ){
- sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
- goto insert_cleanup;
- }
-
- /* Initialize the count of rows to be inserted
- */
- if( (db->flags & SQLITE_CountRows)!=0
- && !pParse->nested
- && !pParse->pTriggerTab
- ){
- regRowCount = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
- }
-
- /* If this is not a view, open the table and and all indices */
- if( !isView ){
- int nIdx;
- nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
- &iDataCur, &iIdxCur);
- aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1));
- if( aRegIdx==0 ){
- goto insert_cleanup;
- }
- for(i=0, pIdx=pTab->pIndex; i<nIdx; pIdx=pIdx->pNext, i++){
- assert( pIdx );
- aRegIdx[i] = ++pParse->nMem;
- pParse->nMem += pIdx->nColumn;
- }
- }
-#ifndef SQLITE_OMIT_UPSERT
- if( pUpsert ){
- pTabList->a[0].iCursor = iDataCur;
- pUpsert->pUpsertSrc = pTabList;
- pUpsert->regData = regData;
- pUpsert->iDataCur = iDataCur;
- pUpsert->iIdxCur = iIdxCur;
- if( pUpsert->pUpsertTarget ){
- sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert);
- }
- }
-#endif
-
-
- /* This is the top of the main insertion loop */
- if( useTempTable ){
- /* This block codes the top of loop only. The complete loop is the
- ** following pseudocode (template 4):
- **
- ** rewind temp table, if empty goto D
- ** C: loop over rows of intermediate table
- ** transfer values form intermediate table into <table>
- ** end loop
- ** D: ...
- */
- addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); VdbeCoverage(v);
- addrCont = sqlite3VdbeCurrentAddr(v);
- }else if( pSelect ){
- /* This block codes the top of loop only. The complete loop is the
- ** following pseudocode (template 3):
- **
- ** C: yield X, at EOF goto D
- ** insert the select result into <table> from R..R+n
- ** goto C
- ** D: ...
- */
- addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
- VdbeCoverage(v);
- }
-
- /* Run the BEFORE and INSTEAD OF triggers, if there are any
- */
- endOfLoop = sqlite3VdbeMakeLabel(v);
- if( tmask & TRIGGER_BEFORE ){
- int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1);
-
- /* build the NEW.* reference row. Note that if there is an INTEGER
- ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
- ** translated into a unique ID for the row. But on a BEFORE trigger,
- ** we do not know what the unique ID will be (because the insert has
- ** not happened yet) so we substitute a rowid of -1
- */
- if( ipkColumn<0 ){
- sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
- }else{
- int addr1;
- assert( !withoutRowid );
- if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regCols);
- }else{
- assert( pSelect==0 ); /* Otherwise useTempTable is true */
- sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols);
- }
- addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
- sqlite3VdbeJumpHere(v, addr1);
- sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
- }
-
- /* Cannot have triggers on a virtual table. If it were possible,
- ** this block would have to account for hidden column.
- */
- assert( !IsVirtual(pTab) );
-
- /* Create the new column data
- */
- for(i=j=0; i<pTab->nCol; i++){
- if( pColumn ){
- for(j=0; j<pColumn->nId; j++){
- if( pColumn->a[j].idx==i ) break;
- }
- }
- if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId)
- || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
- }else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
- }else{
- assert( pSelect==0 ); /* Otherwise useTempTable is true */
- sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
- }
- if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++;
- }
-
- /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
- ** do not attempt any conversions before assembling the record.
- ** If this is a real table, attempt conversions as required by the
- ** table column affinities.
- */
- if( !isView ){
- sqlite3TableAffinity(v, pTab, regCols+1);
- }
-
- /* Fire BEFORE or INSTEAD OF triggers */
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
- pTab, regCols-pTab->nCol-1, onError, endOfLoop);
-
- sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
- }
-
- /* Compute the content of the next row to insert into a range of
- ** registers beginning at regIns.
- */
- if( !isView ){
- if( IsVirtual(pTab) ){
- /* The row that the VUpdate opcode will delete: none */
- sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
- }
- if( ipkColumn>=0 ){
- if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid);
- }else if( pSelect ){
- sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
- }else{
- VdbeOp *pOp;
- sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
- pOp = sqlite3VdbeGetOp(v, -1);
- assert( pOp!=0 );
- if( pOp->opcode==OP_Null && !IsVirtual(pTab) ){
- appendFlag = 1;
- pOp->opcode = OP_NewRowid;
- pOp->p1 = iDataCur;
- pOp->p2 = regRowid;
- pOp->p3 = regAutoinc;
- }
- }
- /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
- ** to generate a unique primary key value.
- */
- if( !appendFlag ){
- int addr1;
- if( !IsVirtual(pTab) ){
- addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
- sqlite3VdbeJumpHere(v, addr1);
- }else{
- addr1 = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, addr1+2); VdbeCoverage(v);
- }
- sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v);
- }
- }else if( IsVirtual(pTab) || withoutRowid ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
- }else{
- sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
- appendFlag = 1;
- }
- autoIncStep(pParse, regAutoinc, regRowid);
-
- /* Compute data for all columns of the new entry, beginning
- ** with the first column.
- */
- nHidden = 0;
- for(i=0; i<pTab->nCol; i++){
- int iRegStore = regRowid+1+i;
- if( i==pTab->iPKey ){
- /* The value of the INTEGER PRIMARY KEY column is always a NULL.
- ** Whenever this column is read, the rowid will be substituted
- ** in its place. Hence, fill this column with a NULL to avoid
- ** taking up data space with information that will never be used.
- ** As there may be shallow copies of this value, make it a soft-NULL */
- sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
- continue;
- }
- if( pColumn==0 ){
- if( IsHiddenColumn(&pTab->aCol[i]) ){
- j = -1;
- nHidden++;
- }else{
- j = i - nHidden;
- }
- }else{
- for(j=0; j<pColumn->nId; j++){
- if( pColumn->a[j].idx==i ) break;
- }
- }
- if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
- sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
- }else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
- }else if( pSelect ){
- if( regFromSelect!=regData ){
- sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
- }
- }else{
- sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
- }
- }
-
- /* Generate code to check constraints and generate index keys and
- ** do the insertion.
- */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab) ){
- const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
- sqlite3VtabMakeWritable(pParse, pTab);
- sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
- sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
- sqlite3MayAbort(pParse);
- }else
-#endif
- {
- int isReplace; /* Set to true if constraints may cause a replace */
- int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
- sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
- regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
- );
- sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
-
- /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
- ** constraints or (b) there are no triggers and this table is not a
- ** parent table in a foreign key constraint. It is safe to set the
- ** flag in the second case as if any REPLACE constraint is hit, an
- ** OP_Delete or OP_IdxDelete instruction will be executed on each
- ** cursor that is disturbed. And these instructions both clear the
- ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
- ** functionality. */
- bUseSeek = (isReplace==0 || (pTrigger==0 &&
- ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
- ));
- sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
- regIns, aRegIdx, 0, appendFlag, bUseSeek
- );
- }
- }
-
- /* Update the count of rows that are inserted
- */
- if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
- }
-
- if( pTrigger ){
- /* Code AFTER triggers */
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
- pTab, regData-2-pTab->nCol, onError, endOfLoop);
- }
-
- /* The bottom of the main insertion loop, if the data source
- ** is a SELECT statement.
- */
- sqlite3VdbeResolveLabel(v, endOfLoop);
- if( useTempTable ){
- sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addrInsTop);
- sqlite3VdbeAddOp1(v, OP_Close, srcTab);
- }else if( pSelect ){
- sqlite3VdbeGoto(v, addrCont);
- sqlite3VdbeJumpHere(v, addrInsTop);
- }
-
-insert_end:
- /* Update the sqlite_sequence table by storing the content of the
- ** maximum rowid counter values recorded while inserting into
- ** autoincrement tables.
- */
- if( pParse->nested==0 && pParse->pTriggerTab==0 ){
- sqlite3AutoincrementEnd(pParse);
- }
-
- /*
- ** Return the number of rows inserted. If this routine is
- ** generating code because of a call to sqlite3NestedParse(), do not
- ** invoke the callback function.
- */
- if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
- }
-
-insert_cleanup:
- sqlite3SrcListDelete(db, pTabList);
- sqlite3ExprListDelete(db, pList);
- sqlite3UpsertDelete(db, pUpsert);
- sqlite3SelectDelete(db, pSelect);
- sqlite3IdListDelete(db, pColumn);
- sqlite3DbFree(db, aRegIdx);
-}
-
-/* Make sure "isView" and other macros defined above are undefined. Otherwise
-** they may interfere with compilation of other functions in this file
-** (or in another file, if this file becomes part of the amalgamation). */
-#ifdef isView
- #undef isView
-#endif
-#ifdef pTrigger
- #undef pTrigger
-#endif
-#ifdef tmask
- #undef tmask
-#endif
-
-/*
-** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged()
-*/
-#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */
-#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */
-
-/* This is the Walker callback from checkConstraintUnchanged(). Set
-** bit 0x01 of pWalker->eCode if
-** pWalker->eCode to 0 if this expression node references any of the
-** columns that are being modifed by an UPDATE statement.
-*/
-static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
- if( pExpr->op==TK_COLUMN ){
- assert( pExpr->iColumn>=0 || pExpr->iColumn==-1 );
- if( pExpr->iColumn>=0 ){
- if( pWalker->u.aiCol[pExpr->iColumn]>=0 ){
- pWalker->eCode |= CKCNSTRNT_COLUMN;
- }
- }else{
- pWalker->eCode |= CKCNSTRNT_ROWID;
- }
- }
- return WRC_Continue;
-}
-
-/*
-** pExpr is a CHECK constraint on a row that is being UPDATE-ed. The
-** only columns that are modified by the UPDATE are those for which
-** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true.
-**
-** Return true if CHECK constraint pExpr does not use any of the
-** changing columns (or the rowid if it is changing). In other words,
-** return true if this CHECK constraint can be skipped when validating
-** the new row in the UPDATE statement.
-*/
-static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
- Walker w;
- memset(&w, 0, sizeof(w));
- w.eCode = 0;
- w.xExprCallback = checkConstraintExprNode;
- w.u.aiCol = aiChng;
- sqlite3WalkExpr(&w, pExpr);
- if( !chngRowid ){
- testcase( (w.eCode & CKCNSTRNT_ROWID)!=0 );
- w.eCode &= ~CKCNSTRNT_ROWID;
- }
- testcase( w.eCode==0 );
- testcase( w.eCode==CKCNSTRNT_COLUMN );
- testcase( w.eCode==CKCNSTRNT_ROWID );
- testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) );
- return !w.eCode;
-}
-
-/*
-** An instance of the ConstraintAddr object remembers the byte-code addresses
-** for sections of the constraint checks that deal with uniqueness constraints
-** on the rowid and on the upsert constraint.
-**
-** This information is passed into checkReorderConstraintChecks() to insert
-** some OP_Goto operations so that the rowid and upsert constraints occur
-** in the correct order relative to other constraints.
-*/
-typedef struct ConstraintAddr ConstraintAddr;
-struct ConstraintAddr {
- int ipkTop; /* Subroutine for rowid constraint check */
- int upsertTop; /* Label for upsert constraint check subroutine */
- int upsertTop2; /* Copy of upsertTop not cleared by the call */
- int upsertBtm; /* upsert constraint returns to this label */
- int ipkBtm; /* Return opcode rowid constraint check */
-};
-
-/*
-** Generate any OP_Goto operations needed to cause constraints to be
-** run that haven't already been run.
-*/
-static void reorderConstraintChecks(Vdbe *v, ConstraintAddr *p){
- if( p->upsertTop ){
- testcase( sqlite3VdbeLabelHasBeenResolved(v, p->upsertTop) );
- sqlite3VdbeGoto(v, p->upsertTop);
- VdbeComment((v, "call upsert subroutine"));
- sqlite3VdbeResolveLabel(v, p->upsertBtm);
- p->upsertTop = 0;
- }
- if( p->ipkTop ){
- sqlite3VdbeGoto(v, p->ipkTop);
- VdbeComment((v, "call rowid unique-check subroutine"));
- sqlite3VdbeJumpHere(v, p->ipkBtm);
- p->ipkTop = 0;
- }
-}
-
-/*
-** Generate code to do constraint checks prior to an INSERT or an UPDATE
-** on table pTab.
-**
-** The regNewData parameter is the first register in a range that contains
-** the data to be inserted or the data after the update. There will be
-** pTab->nCol+1 registers in this range. The first register (the one
-** that regNewData points to) will contain the new rowid, or NULL in the
-** case of a WITHOUT ROWID table. The second register in the range will
-** contain the content of the first table column. The third register will
-** contain the content of the second table column. And so forth.
-**
-** The regOldData parameter is similar to regNewData except that it contains
-** the data prior to an UPDATE rather than afterwards. regOldData is zero
-** for an INSERT. This routine can distinguish between UPDATE and INSERT by
-** checking regOldData for zero.
-**
-** For an UPDATE, the pkChng boolean is true if the true primary key (the
-** rowid for a normal table or the PRIMARY KEY for a WITHOUT ROWID table)
-** might be modified by the UPDATE. If pkChng is false, then the key of
-** the iDataCur content table is guaranteed to be unchanged by the UPDATE.
-**
-** For an INSERT, the pkChng boolean indicates whether or not the rowid
-** was explicitly specified as part of the INSERT statement. If pkChng
-** is zero, it means that the either rowid is computed automatically or
-** that the table is a WITHOUT ROWID table and has no rowid. On an INSERT,
-** pkChng will only be true if the INSERT statement provides an integer
-** value for either the rowid column or its INTEGER PRIMARY KEY alias.
-**
-** The code generated by this routine will store new index entries into
-** registers identified by aRegIdx[]. No index entry is created for
-** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is
-** the same as the order of indices on the linked list of indices
-** at pTab->pIndex.
-**
-** The caller must have already opened writeable cursors on the main
-** table and all applicable indices (that is to say, all indices for which
-** aRegIdx[] is not zero). iDataCur is the cursor for the main table when
-** inserting or updating a rowid table, or the cursor for the PRIMARY KEY
-** index when operating on a WITHOUT ROWID table. iIdxCur is the cursor
-** for the first index in the pTab->pIndex list. Cursors for other indices
-** are at iIdxCur+N for the N-th element of the pTab->pIndex list.
-**
-** This routine also generates code to check constraints. NOT NULL,
-** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
-** then the appropriate action is performed. There are five possible
-** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
-**
-** Constraint type Action What Happens
-** --------------- ---------- ----------------------------------------
-** any ROLLBACK The current transaction is rolled back and
-** sqlite3_step() returns immediately with a
-** return code of SQLITE_CONSTRAINT.
-**
-** any ABORT Back out changes from the current command
-** only (do not do a complete rollback) then
-** cause sqlite3_step() to return immediately
-** with SQLITE_CONSTRAINT.
-**
-** any FAIL Sqlite3_step() returns immediately with a
-** return code of SQLITE_CONSTRAINT. The
-** transaction is not rolled back and any
-** changes to prior rows are retained.
-**
-** any IGNORE The attempt in insert or update the current
-** row is skipped, without throwing an error.
-** Processing continues with the next row.
-** (There is an immediate jump to ignoreDest.)
-**
-** NOT NULL REPLACE The NULL value is replace by the default
-** value for that column. If the default value
-** is NULL, the action is the same as ABORT.
-**
-** UNIQUE REPLACE The other row that conflicts with the row
-** being inserted is removed.
-**
-** CHECK REPLACE Illegal. The results in an exception.
-**
-** Which action to take is determined by the overrideError parameter.
-** Or if overrideError==OE_Default, then the pParse->onError parameter
-** is used. Or if pParse->onError==OE_Default then the onError value
-** for the constraint is used.
-*/
-void sqlite3GenerateConstraintChecks(
- Parse *pParse, /* The parser context */
- Table *pTab, /* The table being inserted or updated */
- int *aRegIdx, /* Use register aRegIdx[i] for index i. 0 for unused */
- int iDataCur, /* Canonical data cursor (main table or PK index) */
- int iIdxCur, /* First index cursor */
- int regNewData, /* First register in a range holding values to insert */
- int regOldData, /* Previous content. 0 for INSERTs */
- u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */
- u8 overrideError, /* Override onError to this if not OE_Default */
- int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
- int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */
- int *aiChng, /* column i is unchanged if aiChng[i]<0 */
- Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */
-){
- Vdbe *v; /* VDBE under constrution */
- Index *pIdx; /* Pointer to one of the indices */
- Index *pPk = 0; /* The PRIMARY KEY index */
- sqlite3 *db; /* Database connection */
- int i; /* loop counter */
- int ix; /* Index loop counter */
- int nCol; /* Number of columns */
- int onError; /* Conflict resolution strategy */
- int addr1; /* Address of jump instruction */
- int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
- int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
- ConstraintAddr sAddr;/* Address information for constraint reordering */
- Index *pUpIdx = 0; /* Index to which to apply the upsert */
- u8 isUpdate; /* True if this is an UPDATE operation */
- u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
- int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */
-
- isUpdate = regOldData!=0;
- db = pParse->db;
- v = sqlite3GetVdbe(pParse);
- assert( v!=0 );
- assert( pTab->pSelect==0 ); /* This table is not a VIEW */
- nCol = pTab->nCol;
- memset(&sAddr, 0, sizeof(sAddr));
-
- /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
- ** normal rowid tables. nPkField is the number of key fields in the
- ** pPk index or 1 for a rowid table. In other words, nPkField is the
- ** number of fields in the true primary key of the table. */
- if( HasRowid(pTab) ){
- pPk = 0;
- nPkField = 1;
- }else{
- pPk = sqlite3PrimaryKeyIndex(pTab);
- nPkField = pPk->nKeyCol;
- }
-
- /* Record that this module has started */
- VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)",
- iDataCur, iIdxCur, regNewData, regOldData, pkChng));
-
- /* Test all NOT NULL constraints.
- */
- for(i=0; i<nCol; i++){
- if( i==pTab->iPKey ){
- continue; /* ROWID is never NULL */
- }
- if( aiChng && aiChng[i]<0 ){
- /* Don't bother checking for NOT NULL on columns that do not change */
- continue;
- }
- onError = pTab->aCol[i].notNull;
- if( onError==OE_None ) continue; /* This column is allowed to be NULL */
- if( overrideError!=OE_Default ){
- onError = overrideError;
- }else if( onError==OE_Default ){
- onError = OE_Abort;
- }
- if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
- onError = OE_Abort;
- }
- assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
- || onError==OE_Ignore || onError==OE_Replace );
- switch( onError ){
- case OE_Abort:
- sqlite3MayAbort(pParse);
- /* Fall through */
- case OE_Rollback:
- case OE_Fail: {
- char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
- pTab->aCol[i].zName);
- sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
- regNewData+1+i);
- sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
- sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
- VdbeCoverage(v);
- break;
- }
- case OE_Ignore: {
- sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
- VdbeCoverage(v);
- break;
- }
- default: {
- assert( onError==OE_Replace );
- addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i);
- VdbeCoverage(v);
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
- sqlite3VdbeJumpHere(v, addr1);
- break;
- }
- }
- }
-
- /* Test all CHECK constraints
- */
-#ifndef SQLITE_OMIT_CHECK
- if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
- ExprList *pCheck = pTab->pCheck;
- pParse->iSelfTab = -(regNewData+1);
- onError = overrideError!=OE_Default ? overrideError : OE_Abort;
- for(i=0; i<pCheck->nExpr; i++){
- int allOk;
- Expr *pExpr = pCheck->a[i].pExpr;
- if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue;
- allOk = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeVerifyAbortable(v, onError);
- sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
- if( onError==OE_Ignore ){
- sqlite3VdbeGoto(v, ignoreDest);
- }else{
- char *zName = pCheck->a[i].zName;
- if( zName==0 ) zName = pTab->zName;
- if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
- onError, zName, P4_TRANSIENT,
- P5_ConstraintCheck);
- }
- sqlite3VdbeResolveLabel(v, allOk);
- }
- pParse->iSelfTab = 0;
- }
-#endif /* !defined(SQLITE_OMIT_CHECK) */
-
- /* UNIQUE and PRIMARY KEY constraints should be handled in the following
- ** order:
- **
- ** (1) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore
- ** (2) OE_Update
- ** (3) OE_Replace
- **
- ** OE_Fail and OE_Ignore must happen before any changes are made.
- ** OE_Update guarantees that only a single row will change, so it
- ** must happen before OE_Replace. Technically, OE_Abort and OE_Rollback
- ** could happen in any order, but they are grouped up front for
- ** convenience.
- **
- ** Constraint checking code is generated in this order:
- ** (A) The rowid constraint
- ** (B) Unique index constraints that do not have OE_Replace as their
- ** default conflict resolution strategy
- ** (C) Unique index that do use OE_Replace by default.
- **
- ** The ordering of (2) and (3) is accomplished by making sure the linked
- ** list of indexes attached to a table puts all OE_Replace indexes last
- ** in the list. See sqlite3CreateIndex() for where that happens.
- */
-
- if( pUpsert ){
- if( pUpsert->pUpsertTarget==0 ){
- /* An ON CONFLICT DO NOTHING clause, without a constraint-target.
- ** Make all unique constraint resolution be OE_Ignore */
- assert( pUpsert->pUpsertSet==0 );
- overrideError = OE_Ignore;
- pUpsert = 0;
- }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
- /* If the constraint-target is on some column other than
- ** then ROWID, then we might need to move the UPSERT around
- ** so that it occurs in the correct order. */
- sAddr.upsertTop = sAddr.upsertTop2 = sqlite3VdbeMakeLabel(v);
- sAddr.upsertBtm = sqlite3VdbeMakeLabel(v);
- }
- }
-
- /* If rowid is changing, make sure the new rowid does not previously
- ** exist in the table.
- */
- if( pkChng && pPk==0 ){
- int addrRowidOk = sqlite3VdbeMakeLabel(v);
-
- /* Figure out what action to take in case of a rowid collision */
- onError = pTab->keyConf;
- if( overrideError!=OE_Default ){
- onError = overrideError;
- }else if( onError==OE_Default ){
- onError = OE_Abort;
- }
-
- /* figure out whether or not upsert applies in this case */
- if( pUpsert && pUpsert->pUpsertIdx==0 ){
- if( pUpsert->pUpsertSet==0 ){
- onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
- }else{
- onError = OE_Update; /* DO UPDATE */
- }
- }
-
- /* If the response to a rowid conflict is REPLACE but the response
- ** to some other UNIQUE constraint is FAIL or IGNORE, then we need
- ** to defer the running of the rowid conflict checking until after
- ** the UNIQUE constraints have run.
- */
- assert( OE_Update>OE_Replace );
- assert( OE_Ignore<OE_Replace );
- assert( OE_Fail<OE_Replace );
- assert( OE_Abort<OE_Replace );
- assert( OE_Rollback<OE_Replace );
- if( onError>=OE_Replace
- && (pUpsert || onError!=overrideError)
- && pTab->pIndex
- ){
- sAddr.ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
- }
-
- if( isUpdate ){
- /* pkChng!=0 does not mean that the rowid has changed, only that
- ** it might have changed. Skip the conflict logic below if the rowid
- ** is unchanged. */
- sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
- sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- VdbeCoverage(v);
- }
-
- /* Check to see if the new rowid already exists in the table. Skip
- ** the following conflict logic if it does not. */
- VdbeNoopComment((v, "uniqueness check for ROWID"));
- sqlite3VdbeVerifyAbortable(v, onError);
- sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
- VdbeCoverage(v);
-
- switch( onError ){
- default: {
- onError = OE_Abort;
- /* Fall thru into the next case */
- }
- case OE_Rollback:
- case OE_Abort:
- case OE_Fail: {
- testcase( onError==OE_Rollback );
- testcase( onError==OE_Abort );
- testcase( onError==OE_Fail );
- sqlite3RowidConstraint(pParse, onError, pTab);
- break;
- }
- case OE_Replace: {
- /* If there are DELETE triggers on this table and the
- ** recursive-triggers flag is set, call GenerateRowDelete() to
- ** remove the conflicting row from the table. This will fire
- ** the triggers and remove both the table and index b-tree entries.
- **
- ** Otherwise, if there are no triggers or the recursive-triggers
- ** flag is not set, but the table has one or more indexes, call
- ** GenerateRowIndexDelete(). This removes the index b-tree entries
- ** only. The table b-tree entry will be replaced by the new entry
- ** when it is inserted.
- **
- ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
- ** also invoke MultiWrite() to indicate that this VDBE may require
- ** statement rollback (if the statement is aborted after the delete
- ** takes place). Earlier versions called sqlite3MultiWrite() regardless,
- ** but being more selective here allows statements like:
- **
- ** REPLACE INTO t(rowid) VALUES($newrowid)
- **
- ** to run without a statement journal if there are no indexes on the
- ** table.
- */
- Trigger *pTrigger = 0;
- if( db->flags&SQLITE_RecTriggers ){
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
- }
- if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
- sqlite3MultiWrite(pParse);
- sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- regNewData, 1, 0, OE_Replace, 1, -1);
- }else{
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- assert( HasRowid(pTab) );
- /* This OP_Delete opcode fires the pre-update-hook only. It does
- ** not modify the b-tree. It is more efficient to let the coming
- ** OP_Insert replace the existing entry than it is to delete the
- ** existing entry and then insert a new one. */
- sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP);
- sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
- if( pTab->pIndex ){
- sqlite3MultiWrite(pParse);
- sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1);
- }
- }
- seenReplace = 1;
- break;
- }
-#ifndef SQLITE_OMIT_UPSERT
- case OE_Update: {
- sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur);
- /* Fall through */
- }
-#endif
- case OE_Ignore: {
- testcase( onError==OE_Ignore );
- sqlite3VdbeGoto(v, ignoreDest);
- break;
- }
- }
- sqlite3VdbeResolveLabel(v, addrRowidOk);
- if( sAddr.ipkTop ){
- sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto);
- sqlite3VdbeJumpHere(v, sAddr.ipkTop-1);
- }
- }
-
- /* Test all UNIQUE constraints by creating entries for each UNIQUE
- ** index and making sure that duplicate entries do not already exist.
- ** Compute the revised record entries for indices as we go.
- **
- ** This loop also handles the case of the PRIMARY KEY index for a
- ** WITHOUT ROWID table.
- */
- for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
- int regIdx; /* Range of registers hold conent for pIdx */
- int regR; /* Range of registers holding conflicting PK */
- int iThisCur; /* Cursor for this UNIQUE index */
- int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */
-
- if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
- if( pUpIdx==pIdx ){
- addrUniqueOk = sAddr.upsertBtm;
- upsertBypass = sqlite3VdbeGoto(v, 0);
- VdbeComment((v, "Skip upsert subroutine"));
- sqlite3VdbeResolveLabel(v, sAddr.upsertTop2);
- }else{
- addrUniqueOk = sqlite3VdbeMakeLabel(v);
- }
- VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
- if( bAffinityDone==0 ){
- sqlite3TableAffinity(v, pTab, regNewData+1);
- bAffinityDone = 1;
- }
- iThisCur = iIdxCur+ix;
-
-
- /* Skip partial indices for which the WHERE clause is not true */
- if( pIdx->pPartIdxWhere ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
- pParse->iSelfTab = -(regNewData+1);
- sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
- SQLITE_JUMPIFNULL);
- pParse->iSelfTab = 0;
- }
-
- /* Create a record for this index entry as it should appear after
- ** the insert or update. Store that record in the aRegIdx[ix] register
- */
- regIdx = aRegIdx[ix]+1;
- for(i=0; i<pIdx->nColumn; i++){
- int iField = pIdx->aiColumn[i];
- int x;
- if( iField==XN_EXPR ){
- pParse->iSelfTab = -(regNewData+1);
- sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
- pParse->iSelfTab = 0;
- VdbeComment((v, "%s column %d", pIdx->zName, i));
- }else{
- if( iField==XN_ROWID || iField==pTab->iPKey ){
- x = regNewData;
- }else{
- x = iField + regNewData + 1;
- }
- sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i);
- VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
- }
- }
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
- VdbeComment((v, "for %s", pIdx->zName));
-#ifdef SQLITE_ENABLE_NULL_TRIM
- if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable);
-#endif
-
- /* In an UPDATE operation, if this index is the PRIMARY KEY index
- ** of a WITHOUT ROWID table and there has been no change the
- ** primary key, then no collision is possible. The collision detection
- ** logic below can all be skipped. */
- if( isUpdate && pPk==pIdx && pkChng==0 ){
- sqlite3VdbeResolveLabel(v, addrUniqueOk);
- continue;
- }
-
- /* Find out what action to take in case there is a uniqueness conflict */
- onError = pIdx->onError;
- if( onError==OE_None ){
- sqlite3VdbeResolveLabel(v, addrUniqueOk);
- continue; /* pIdx is not a UNIQUE index */
- }
- if( overrideError!=OE_Default ){
- onError = overrideError;
- }else if( onError==OE_Default ){
- onError = OE_Abort;
- }
-
- /* Figure out if the upsert clause applies to this index */
- if( pUpIdx==pIdx ){
- if( pUpsert->pUpsertSet==0 ){
- onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
- }else{
- onError = OE_Update; /* DO UPDATE */
- }
- }
-
- /* Invoke subroutines to handle IPK replace and upsert prior to running
- ** the first REPLACE constraint check. */
- if( onError==OE_Replace ){
- testcase( sAddr.ipkTop );
- testcase( sAddr.upsertTop
- && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) );
- reorderConstraintChecks(v, &sAddr);
- }
-
- /* Collision detection may be omitted if all of the following are true:
- ** (1) The conflict resolution algorithm is REPLACE
- ** (2) The table is a WITHOUT ROWID table
- ** (3) There are no secondary indexes on the table
- ** (4) No delete triggers need to be fired if there is a conflict
- ** (5) No FK constraint counters need to be updated if a conflict occurs.
- */
- if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
- && pPk==pIdx /* Condition 2 */
- && onError==OE_Replace /* Condition 1 */
- && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
- 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
- && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
- (0==pTab->pFKey && 0==sqlite3FkReferences(pTab)))
- ){
- sqlite3VdbeResolveLabel(v, addrUniqueOk);
- continue;
- }
-
- /* Check to see if the new index entry will be unique */
- sqlite3ExprCachePush(pParse);
- sqlite3VdbeVerifyAbortable(v, onError);
- sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
- regIdx, pIdx->nKeyCol); VdbeCoverage(v);
-
- /* Generate code to handle collisions */
- regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
- if( isUpdate || onError==OE_Replace ){
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
- /* Conflict only if the rowid of the existing index entry
- ** is different from old-rowid */
- if( isUpdate ){
- sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
- sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- VdbeCoverage(v);
- }
- }else{
- int x;
- /* Extract the PRIMARY KEY from the end of the index entry and
- ** store it in registers regR..regR+nPk-1 */
- if( pIdx!=pPk ){
- for(i=0; i<pPk->nKeyCol; i++){
- assert( pPk->aiColumn[i]>=0 );
- x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
- sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
- VdbeComment((v, "%s.%s", pTab->zName,
- pTab->aCol[pPk->aiColumn[i]].zName));
- }
- }
- if( isUpdate ){
- /* If currently processing the PRIMARY KEY of a WITHOUT ROWID
- ** table, only conflict if the new PRIMARY KEY values are actually
- ** different from the old.
- **
- ** For a UNIQUE index, only conflict if the PRIMARY KEY values
- ** of the matched index row are different from the original PRIMARY
- ** KEY values of this row before the update. */
- int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
- int op = OP_Ne;
- int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR);
-
- for(i=0; i<pPk->nKeyCol; i++){
- char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
- x = pPk->aiColumn[i];
- assert( x>=0 );
- if( i==(pPk->nKeyCol-1) ){
- addrJump = addrUniqueOk;
- op = OP_Eq;
- }
- sqlite3VdbeAddOp4(v, op,
- regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
- );
- sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- VdbeCoverageIf(v, op==OP_Eq);
- VdbeCoverageIf(v, op==OP_Ne);
- }
- }
- }
- }
-
- /* Generate code that executes if the new index entry is not unique */
- assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
- || onError==OE_Ignore || onError==OE_Replace || onError==OE_Update );
- switch( onError ){
- case OE_Rollback:
- case OE_Abort:
- case OE_Fail: {
- testcase( onError==OE_Rollback );
- testcase( onError==OE_Abort );
- testcase( onError==OE_Fail );
- sqlite3UniqueConstraint(pParse, onError, pIdx);
- break;
- }
-#ifndef SQLITE_OMIT_UPSERT
- case OE_Update: {
- sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, pIdx, iIdxCur+ix);
- /* Fall through */
- }
-#endif
- case OE_Ignore: {
- testcase( onError==OE_Ignore );
- sqlite3VdbeGoto(v, ignoreDest);
- break;
- }
- default: {
- Trigger *pTrigger = 0;
- assert( onError==OE_Replace );
- if( db->flags&SQLITE_RecTriggers ){
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
- }
- if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
- sqlite3MultiWrite(pParse);
- }
- sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- regR, nPkField, 0, OE_Replace,
- (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
- seenReplace = 1;
- break;
- }
- }
- if( pUpIdx==pIdx ){
- sqlite3VdbeJumpHere(v, upsertBypass);
- }else{
- sqlite3VdbeResolveLabel(v, addrUniqueOk);
- }
- sqlite3ExprCachePop(pParse);
- if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
-
- }
- testcase( sAddr.ipkTop!=0 );
- testcase( sAddr.upsertTop
- && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) );
- reorderConstraintChecks(v, &sAddr);
-
- *pbMayReplace = seenReplace;
- VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
-}
-
-#ifdef SQLITE_ENABLE_NULL_TRIM
-/*
-** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)
-** to be the number of columns in table pTab that must not be NULL-trimmed.
-**
-** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero.
-*/
-void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
- u16 i;
-
- /* Records with omitted columns are only allowed for schema format
- ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
- if( pTab->pSchema->file_format<2 ) return;
-
- for(i=pTab->nCol-1; i>0; i--){
- if( pTab->aCol[i].pDflt!=0 ) break;
- if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
- }
- sqlite3VdbeChangeP5(v, i+1);
-}
-#endif
-
-/*
-** This routine generates code to finish the INSERT or UPDATE operation
-** that was started by a prior call to sqlite3GenerateConstraintChecks.
-** A consecutive range of registers starting at regNewData contains the
-** rowid and the content to be inserted.
-**
-** The arguments to this routine should be the same as the first six
-** arguments to sqlite3GenerateConstraintChecks.
-*/
-void sqlite3CompleteInsertion(
- Parse *pParse, /* The parser context */
- Table *pTab, /* the table into which we are inserting */
- int iDataCur, /* Cursor of the canonical data source */
- int iIdxCur, /* First index cursor */
- int regNewData, /* Range of content */
- int *aRegIdx, /* Register used by each index. 0 for unused indices */
- int update_flags, /* True for UPDATE, False for INSERT */
- int appendBias, /* True if this is likely to be an append */
- int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
-){
- Vdbe *v; /* Prepared statements under construction */
- Index *pIdx; /* An index being inserted or updated */
- u8 pik_flags; /* flag values passed to the btree insert */
- int regData; /* Content registers (after the rowid) */
- int regRec; /* Register holding assembled record for the table */
- int i; /* Loop counter */
- u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */
-
- assert( update_flags==0
- || update_flags==OPFLAG_ISUPDATE
- || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
- );
-
- v = sqlite3GetVdbe(pParse);
- assert( v!=0 );
- assert( pTab->pSelect==0 ); /* This table is not a VIEW */
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( aRegIdx[i]==0 ) continue;
- bAffinityDone = 1;
- if( pIdx->pPartIdxWhere ){
- sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
- VdbeCoverage(v);
- }
- pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
- if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
- assert( pParse->nested==0 );
- pik_flags |= OPFLAG_NCHANGE;
- pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- if( update_flags==0 ){
- sqlite3VdbeAddOp4(v, OP_InsertInt,
- iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE
- );
- sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
- }
-#endif
- }
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
- aRegIdx[i]+1,
- pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
- sqlite3VdbeChangeP5(v, pik_flags);
- }
- if( !HasRowid(pTab) ) return;
- regData = regNewData + 1;
- regRec = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
- sqlite3SetMakeRecordP5(v, pTab);
- if( !bAffinityDone ){
- sqlite3TableAffinity(v, pTab, 0);
- sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
- }
- if( pParse->nested ){
- pik_flags = 0;
- }else{
- pik_flags = OPFLAG_NCHANGE;
- pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID);
- }
- if( appendBias ){
- pik_flags |= OPFLAG_APPEND;
- }
- if( useSeekResult ){
- pik_flags |= OPFLAG_USESEEKRESULT;
- }
- sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData);
- if( !pParse->nested ){
- sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
- }
- sqlite3VdbeChangeP5(v, pik_flags);
-}
-
-/*
-** Allocate cursors for the pTab table and all its indices and generate
-** code to open and initialized those cursors.
-**
-** The cursor for the object that contains the complete data (normally
-** the table itself, but the PRIMARY KEY index in the case of a WITHOUT
-** ROWID table) is returned in *piDataCur. The first index cursor is
-** returned in *piIdxCur. The number of indices is returned.
-**
-** Use iBase as the first cursor (either the *piDataCur for rowid tables
-** or the first index for WITHOUT ROWID tables) if it is non-negative.
-** If iBase is negative, then allocate the next available cursor.
-**
-** For a rowid table, *piDataCur will be exactly one less than *piIdxCur.
-** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range
-** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the
-** pTab->pIndex list.
-**
-** If pTab is a virtual table, then this routine is a no-op and the
-** *piDataCur and *piIdxCur values are left uninitialized.
-*/
-int sqlite3OpenTableAndIndices(
- Parse *pParse, /* Parsing context */
- Table *pTab, /* Table to be opened */
- int op, /* OP_OpenRead or OP_OpenWrite */
- u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */
- int iBase, /* Use this for the table cursor, if there is one */
- u8 *aToOpen, /* If not NULL: boolean for each table and index */
- int *piDataCur, /* Write the database source cursor number here */
- int *piIdxCur /* Write the first index cursor number here */
-){
- int i;
- int iDb;
- int iDataCur;
- Index *pIdx;
- Vdbe *v;
-
- assert( op==OP_OpenRead || op==OP_OpenWrite );
- assert( op==OP_OpenWrite || p5==0 );
- if( IsVirtual(pTab) ){
- /* This routine is a no-op for virtual tables. Leave the output
- ** variables *piDataCur and *piIdxCur uninitialized so that valgrind
- ** can detect if they are used by mistake in the caller. */
- return 0;
- }
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- v = sqlite3GetVdbe(pParse);
- assert( v!=0 );
- if( iBase<0 ) iBase = pParse->nTab;
- iDataCur = iBase++;
- if( piDataCur ) *piDataCur = iDataCur;
- if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){
- sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op);
- }else{
- sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName);
- }
- if( piIdxCur ) *piIdxCur = iBase;
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- int iIdxCur = iBase++;
- assert( pIdx->pSchema==pTab->pSchema );
- if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
- if( piDataCur ) *piDataCur = iIdxCur;
- p5 = 0;
- }
- if( aToOpen==0 || aToOpen[i+1] ){
- sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
- sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
- sqlite3VdbeChangeP5(v, p5);
- VdbeComment((v, "%s", pIdx->zName));
- }
- }
- if( iBase>pParse->nTab ) pParse->nTab = iBase;
- return i;
-}
-
-
-#ifdef SQLITE_TEST
-/*
-** The following global variable is incremented whenever the
-** transfer optimization is used. This is used for testing
-** purposes only - to make sure the transfer optimization really
-** is happening when it is supposed to.
-*/
-int sqlite3_xferopt_count;
-#endif /* SQLITE_TEST */
-
-
-#ifndef SQLITE_OMIT_XFER_OPT
-/*
-** Check to see if index pSrc is compatible as a source of data
-** for index pDest in an insert transfer optimization. The rules
-** for a compatible index:
-**
-** * The index is over the same set of columns
-** * The same DESC and ASC markings occurs on all columns
-** * The same onError processing (OE_Abort, OE_Ignore, etc)
-** * The same collating sequence on each column
-** * The index has the exact same WHERE clause
-*/
-static int xferCompatibleIndex(Index *pDest, Index *pSrc){
- int i;
- assert( pDest && pSrc );
- assert( pDest->pTable!=pSrc->pTable );
- if( pDest->nKeyCol!=pSrc->nKeyCol ){
- return 0; /* Different number of columns */
- }
- if( pDest->onError!=pSrc->onError ){
- return 0; /* Different conflict resolution strategies */
- }
- for(i=0; i<pSrc->nKeyCol; i++){
- if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
- return 0; /* Different columns indexed */
- }
- if( pSrc->aiColumn[i]==XN_EXPR ){
- assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 );
- if( sqlite3ExprCompare(0, pSrc->aColExpr->a[i].pExpr,
- pDest->aColExpr->a[i].pExpr, -1)!=0 ){
- return 0; /* Different expressions in the index */
- }
- }
- if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
- return 0; /* Different sort orders */
- }
- if( sqlite3_stricmp(pSrc->azColl[i],pDest->azColl[i])!=0 ){
- return 0; /* Different collating sequences */
- }
- }
- if( sqlite3ExprCompare(0, pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
- return 0; /* Different WHERE clauses */
- }
-
- /* If no test above fails then the indices must be compatible */
- return 1;
-}
-
-/*
-** Attempt the transfer optimization on INSERTs of the form
-**
-** INSERT INTO tab1 SELECT * FROM tab2;
-**
-** The xfer optimization transfers raw records from tab2 over to tab1.
-** Columns are not decoded and reassembled, which greatly improves
-** performance. Raw index records are transferred in the same way.
-**
-** The xfer optimization is only attempted if tab1 and tab2 are compatible.
-** There are lots of rules for determining compatibility - see comments
-** embedded in the code for details.
-**
-** This routine returns TRUE if the optimization is guaranteed to be used.
-** Sometimes the xfer optimization will only work if the destination table
-** is empty - a factor that can only be determined at run-time. In that
-** case, this routine generates code for the xfer optimization but also
-** does a test to see if the destination table is empty and jumps over the
-** xfer optimization code if the test fails. In that case, this routine
-** returns FALSE so that the caller will know to go ahead and generate
-** an unoptimized transfer. This routine also returns FALSE if there
-** is no chance that the xfer optimization can be applied.
-**
-** This optimization is particularly useful at making VACUUM run faster.
-*/
-static int xferOptimization(
- Parse *pParse, /* Parser context */
- Table *pDest, /* The table we are inserting into */
- Select *pSelect, /* A SELECT statement to use as the data source */
- int onError, /* How to handle constraint errors */
- int iDbDest /* The database of pDest */
-){
- sqlite3 *db = pParse->db;
- ExprList *pEList; /* The result set of the SELECT */
- Table *pSrc; /* The table in the FROM clause of SELECT */
- Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
- struct SrcList_item *pItem; /* An element of pSelect->pSrc */
- int i; /* Loop counter */
- int iDbSrc; /* The database of pSrc */
- int iSrc, iDest; /* Cursors from source and destination */
- int addr1, addr2; /* Loop addresses */
- int emptyDestTest = 0; /* Address of test for empty pDest */
- int emptySrcTest = 0; /* Address of test for empty pSrc */
- Vdbe *v; /* The VDBE we are building */
- int regAutoinc; /* Memory register used by AUTOINC */
- int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
- int regData, regRowid; /* Registers holding data and rowid */
-
- if( pSelect==0 ){
- return 0; /* Must be of the form INSERT INTO ... SELECT ... */
- }
- if( pParse->pWith || pSelect->pWith ){
- /* Do not attempt to process this query if there are an WITH clauses
- ** attached to it. Proceeding may generate a false "no such table: xxx"
- ** error if pSelect reads from a CTE named "xxx". */
- return 0;
- }
- if( sqlite3TriggerList(pParse, pDest) ){
- return 0; /* tab1 must not have triggers */
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pDest) ){
- return 0; /* tab1 must not be a virtual table */
- }
-#endif
- if( onError==OE_Default ){
- if( pDest->iPKey>=0 ) onError = pDest->keyConf;
- if( onError==OE_Default ) onError = OE_Abort;
- }
- assert(pSelect->pSrc); /* allocated even if there is no FROM clause */
- if( pSelect->pSrc->nSrc!=1 ){
- return 0; /* FROM clause must have exactly one term */
- }
- if( pSelect->pSrc->a[0].pSelect ){
- return 0; /* FROM clause cannot contain a subquery */
- }
- if( pSelect->pWhere ){
- return 0; /* SELECT may not have a WHERE clause */
- }
- if( pSelect->pOrderBy ){
- return 0; /* SELECT may not have an ORDER BY clause */
- }
- /* Do not need to test for a HAVING clause. If HAVING is present but
- ** there is no ORDER BY, we will get an error. */
- if( pSelect->pGroupBy ){
- return 0; /* SELECT may not have a GROUP BY clause */
- }
- if( pSelect->pLimit ){
- return 0; /* SELECT may not have a LIMIT clause */
- }
- if( pSelect->pPrior ){
- return 0; /* SELECT may not be a compound query */
- }
- if( pSelect->selFlags & SF_Distinct ){
- return 0; /* SELECT may not be DISTINCT */
- }
- pEList = pSelect->pEList;
- assert( pEList!=0 );
- if( pEList->nExpr!=1 ){
- return 0; /* The result set must have exactly one column */
- }
- assert( pEList->a[0].pExpr );
- if( pEList->a[0].pExpr->op!=TK_ASTERISK ){
- return 0; /* The result set must be the special operator "*" */
- }
-
- /* At this point we have established that the statement is of the
- ** correct syntactic form to participate in this optimization. Now
- ** we have to check the semantics.
- */
- pItem = pSelect->pSrc->a;
- pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
- if( pSrc==0 ){
- return 0; /* FROM clause does not contain a real table */
- }
- if( pSrc==pDest ){
- return 0; /* tab1 and tab2 may not be the same table */
- }
- if( HasRowid(pDest)!=HasRowid(pSrc) ){
- return 0; /* source and destination must both be WITHOUT ROWID or not */
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pSrc) ){
- return 0; /* tab2 must not be a virtual table */
- }
-#endif
- if( pSrc->pSelect ){
- return 0; /* tab2 may not be a view */
- }
- if( pDest->nCol!=pSrc->nCol ){
- return 0; /* Number of columns must be the same in tab1 and tab2 */
- }
- if( pDest->iPKey!=pSrc->iPKey ){
- return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
- }
- for(i=0; i<pDest->nCol; i++){
- Column *pDestCol = &pDest->aCol[i];
- Column *pSrcCol = &pSrc->aCol[i];
-#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
- if( (db->mDbFlags & DBFLAG_Vacuum)==0
- && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN
- ){
- return 0; /* Neither table may have __hidden__ columns */
- }
-#endif
- if( pDestCol->affinity!=pSrcCol->affinity ){
- return 0; /* Affinity must be the same on all columns */
- }
- if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
- return 0; /* Collating sequence must be the same on all columns */
- }
- if( pDestCol->notNull && !pSrcCol->notNull ){
- return 0; /* tab2 must be NOT NULL if tab1 is */
- }
- /* Default values for second and subsequent columns need to match. */
- if( i>0 ){
- assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
- assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
- if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0)
- || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken,
- pSrcCol->pDflt->u.zToken)!=0)
- ){
- return 0; /* Default values must be the same for all columns */
- }
- }
- }
- for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
- if( IsUniqueIndex(pDestIdx) ){
- destHasUniqueIdx = 1;
- }
- for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
- if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
- }
- if( pSrcIdx==0 ){
- return 0; /* pDestIdx has no corresponding index in pSrc */
- }
- }
-#ifndef SQLITE_OMIT_CHECK
- if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
- return 0; /* Tables have different CHECK constraints. Ticket #2252 */
- }
-#endif
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- /* Disallow the transfer optimization if the destination table constains
- ** any foreign key constraints. This is more restrictive than necessary.
- ** But the main beneficiary of the transfer optimization is the VACUUM
- ** command, and the VACUUM command disables foreign key constraints. So
- ** the extra complication to make this rule less restrictive is probably
- ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
- */
- if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
- return 0;
- }
-#endif
- if( (db->flags & SQLITE_CountRows)!=0 ){
- return 0; /* xfer opt does not play well with PRAGMA count_changes */
- }
-
- /* If we get this far, it means that the xfer optimization is at
- ** least a possibility, though it might only work if the destination
- ** table (tab1) is initially empty.
- */
-#ifdef SQLITE_TEST
- sqlite3_xferopt_count++;
-#endif
- iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema);
- v = sqlite3GetVdbe(pParse);
- sqlite3CodeVerifySchema(pParse, iDbSrc);
- iSrc = pParse->nTab++;
- iDest = pParse->nTab++;
- regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
- regData = sqlite3GetTempReg(pParse);
- regRowid = sqlite3GetTempReg(pParse);
- sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
- assert( HasRowid(pDest) || destHasUniqueIdx );
- if( (db->mDbFlags & DBFLAG_Vacuum)==0 && (
- (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
- || destHasUniqueIdx /* (2) */
- || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */
- )){
- /* In some circumstances, we are able to run the xfer optimization
- ** only if the destination table is initially empty. Unless the
- ** DBFLAG_Vacuum flag is set, this block generates code to make
- ** that determination. If DBFLAG_Vacuum is set, then the destination
- ** table is always empty.
- **
- ** Conditions under which the destination must be empty:
- **
- ** (1) There is no INTEGER PRIMARY KEY but there are indices.
- ** (If the destination is not initially empty, the rowid fields
- ** of index entries might need to change.)
- **
- ** (2) The destination has a unique index. (The xfer optimization
- ** is unable to test uniqueness.)
- **
- ** (3) onError is something other than OE_Abort and OE_Rollback.
- */
- addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v);
- emptyDestTest = sqlite3VdbeAddOp0(v, OP_Goto);
- sqlite3VdbeJumpHere(v, addr1);
- }
- if( HasRowid(pSrc) ){
- u8 insFlags;
- sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
- emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
- if( pDest->iPKey>=0 ){
- addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- sqlite3VdbeVerifyAbortable(v, onError);
- addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
- VdbeCoverage(v);
- sqlite3RowidConstraint(pParse, onError, pDest);
- sqlite3VdbeJumpHere(v, addr2);
- autoIncStep(pParse, regAutoinc, regRowid);
- }else if( pDest->pIndex==0 ){
- addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
- }else{
- addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- assert( (pDest->tabFlags & TF_Autoincrement)==0 );
- }
- sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
- if( db->mDbFlags & DBFLAG_Vacuum ){
- sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
- insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
- OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
- }else{
- insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
- }
- sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
- (char*)pDest, P4_TABLE);
- sqlite3VdbeChangeP5(v, insFlags);
- sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
- sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
- }else{
- sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName);
- sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName);
- }
- for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
- u8 idxInsFlags = 0;
- for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
- if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
- }
- assert( pSrcIdx );
- sqlite3VdbeAddOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc);
- sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx);
- VdbeComment((v, "%s", pSrcIdx->zName));
- sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest);
- sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx);
- sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
- VdbeComment((v, "%s", pDestIdx->zName));
- addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
- if( db->mDbFlags & DBFLAG_Vacuum ){
- /* This INSERT command is part of a VACUUM operation, which guarantees
- ** that the destination table is empty. If all indexed columns use
- ** collation sequence BINARY, then it can also be assumed that the
- ** index will be populated by inserting keys in strictly sorted
- ** order. In this case, instead of seeking within the b-tree as part
- ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the
- ** OP_IdxInsert to seek to the point within the b-tree where each key
- ** should be inserted. This is faster.
- **
- ** If any of the indexed columns use a collation sequence other than
- ** BINARY, this optimization is disabled. This is because the user
- ** might change the definition of a collation sequence and then run
- ** a VACUUM command. In that case keys may not be written in strictly
- ** sorted order. */
- for(i=0; i<pSrcIdx->nColumn; i++){
- const char *zColl = pSrcIdx->azColl[i];
- if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
- }
- if( i==pSrcIdx->nColumn ){
- idxInsFlags = OPFLAG_USESEEKRESULT;
- sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
- }
- }
- if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){
- idxInsFlags |= OPFLAG_NCHANGE;
- }
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
- sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
- sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addr1);
- sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
- sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
- }
- if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest);
- sqlite3ReleaseTempReg(pParse, regRowid);
- sqlite3ReleaseTempReg(pParse, regData);
- if( emptyDestTest ){
- sqlite3AutoincrementEnd(pParse);
- sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);
- sqlite3VdbeJumpHere(v, emptyDestTest);
- sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
- return 0;
- }else{
- return 1;
- }
-}
-#endif /* SQLITE_OMIT_XFER_OPT */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/legacy.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/legacy.c
deleted file mode 100644
index 40959a85440..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/legacy.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Main file for the SQLite library. The routines in this file
-** implement the programmer interface to the library. Routines in
-** other files are for internal use by SQLite and should not be
-** accessed by users of the library.
-*/
-
-#include "sqliteInt.h"
-
-/*
-** Execute SQL code. Return one of the SQLITE_ success/failure
-** codes. Also write an error message into memory obtained from
-** malloc() and make *pzErrMsg point to that message.
-**
-** If the SQL is a query, then for each row in the query result
-** the xCallback() function is called. pArg becomes the first
-** argument to xCallback(). If xCallback=NULL then no callback
-** is invoked, even for queries.
-*/
-int sqlite3_exec(
- sqlite3 *db, /* The database on which the SQL executes */
- const char *zSql, /* The SQL to be executed */
- sqlite3_callback xCallback, /* Invoke this callback routine */
- void *pArg, /* First argument to xCallback() */
- char **pzErrMsg /* Write error messages here */
-){
- int rc = SQLITE_OK; /* Return code */
- const char *zLeftover; /* Tail of unprocessed SQL */
- sqlite3_stmt *pStmt = 0; /* The current SQL statement */
- char **azCols = 0; /* Names of result columns */
- int callbackIsInit; /* True if callback data is initialized */
-
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
- if( zSql==0 ) zSql = "";
-
- sqlite3_mutex_enter(db->mutex);
- sqlite3Error(db, SQLITE_OK);
- while( rc==SQLITE_OK && zSql[0] ){
- int nCol;
- char **azVals = 0;
-
- pStmt = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
- assert( rc==SQLITE_OK || pStmt==0 );
- if( rc!=SQLITE_OK ){
- continue;
- }
- if( !pStmt ){
- /* this happens for a comment or white-space */
- zSql = zLeftover;
- continue;
- }
-
- callbackIsInit = 0;
- nCol = sqlite3_column_count(pStmt);
-
- while( 1 ){
- int i;
- rc = sqlite3_step(pStmt);
-
- /* Invoke the callback function if required */
- if( xCallback && (SQLITE_ROW==rc ||
- (SQLITE_DONE==rc && !callbackIsInit
- && db->flags&SQLITE_NullCallback)) ){
- if( !callbackIsInit ){
- azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*));
- if( azCols==0 ){
- goto exec_out;
- }
- for(i=0; i<nCol; i++){
- azCols[i] = (char *)sqlite3_column_name(pStmt, i);
- /* sqlite3VdbeSetColName() installs column names as UTF8
- ** strings so there is no way for sqlite3_column_name() to fail. */
- assert( azCols[i]!=0 );
- }
- callbackIsInit = 1;
- }
- if( rc==SQLITE_ROW ){
- azVals = &azCols[nCol];
- for(i=0; i<nCol; i++){
- azVals[i] = (char *)sqlite3_column_text(pStmt, i);
- if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){
- sqlite3OomFault(db);
- goto exec_out;
- }
- }
- azVals[i] = 0;
- }
- if( xCallback(pArg, nCol, azVals, azCols) ){
- /* EVIDENCE-OF: R-38229-40159 If the callback function to
- ** sqlite3_exec() returns non-zero, then sqlite3_exec() will
- ** return SQLITE_ABORT. */
- rc = SQLITE_ABORT;
- sqlite3VdbeFinalize((Vdbe *)pStmt);
- pStmt = 0;
- sqlite3Error(db, SQLITE_ABORT);
- goto exec_out;
- }
- }
-
- if( rc!=SQLITE_ROW ){
- rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
- pStmt = 0;
- zSql = zLeftover;
- while( sqlite3Isspace(zSql[0]) ) zSql++;
- break;
- }
- }
-
- sqlite3DbFree(db, azCols);
- azCols = 0;
- }
-
-exec_out:
- if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
- sqlite3DbFree(db, azCols);
-
- rc = sqlite3ApiExit(db, rc);
- if( rc!=SQLITE_OK && pzErrMsg ){
- *pzErrMsg = sqlite3DbStrDup(0, sqlite3_errmsg(db));
- if( *pzErrMsg==0 ){
- rc = SQLITE_NOMEM_BKPT;
- sqlite3Error(db, SQLITE_NOMEM);
- }
- }else if( pzErrMsg ){
- *pzErrMsg = 0;
- }
-
- assert( (rc&db->errMask)==rc );
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/loadext.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/loadext.c
deleted file mode 100644
index 3a48176beb1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/loadext.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
-** 2006 June 7
-**
-** 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 contains code used to dynamically load extensions into
-** the SQLite library.
-*/
-
-#ifndef SQLITE_CORE
- #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
-#endif
-#include "sqlite3ext.h"
-#include "sqliteInt.h"
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-/*
-** Some API routines are omitted when various features are
-** excluded from a build of SQLite. Substitute a NULL pointer
-** for any missing APIs.
-*/
-#ifndef SQLITE_ENABLE_COLUMN_METADATA
-# define sqlite3_column_database_name 0
-# define sqlite3_column_database_name16 0
-# define sqlite3_column_table_name 0
-# define sqlite3_column_table_name16 0
-# define sqlite3_column_origin_name 0
-# define sqlite3_column_origin_name16 0
-#endif
-
-#ifdef SQLITE_OMIT_AUTHORIZATION
-# define sqlite3_set_authorizer 0
-#endif
-
-#ifdef SQLITE_OMIT_UTF16
-# define sqlite3_bind_text16 0
-# define sqlite3_collation_needed16 0
-# define sqlite3_column_decltype16 0
-# define sqlite3_column_name16 0
-# define sqlite3_column_text16 0
-# define sqlite3_complete16 0
-# define sqlite3_create_collation16 0
-# define sqlite3_create_function16 0
-# define sqlite3_errmsg16 0
-# define sqlite3_open16 0
-# define sqlite3_prepare16 0
-# define sqlite3_prepare16_v2 0
-# define sqlite3_prepare16_v3 0
-# define sqlite3_result_error16 0
-# define sqlite3_result_text16 0
-# define sqlite3_result_text16be 0
-# define sqlite3_result_text16le 0
-# define sqlite3_value_text16 0
-# define sqlite3_value_text16be 0
-# define sqlite3_value_text16le 0
-# define sqlite3_column_database_name16 0
-# define sqlite3_column_table_name16 0
-# define sqlite3_column_origin_name16 0
-#endif
-
-#ifdef SQLITE_OMIT_COMPLETE
-# define sqlite3_complete 0
-# define sqlite3_complete16 0
-#endif
-
-#ifdef SQLITE_OMIT_DECLTYPE
-# define sqlite3_column_decltype16 0
-# define sqlite3_column_decltype 0
-#endif
-
-#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
-# define sqlite3_progress_handler 0
-#endif
-
-#ifdef SQLITE_OMIT_VIRTUALTABLE
-# define sqlite3_create_module 0
-# define sqlite3_create_module_v2 0
-# define sqlite3_declare_vtab 0
-# define sqlite3_vtab_config 0
-# define sqlite3_vtab_on_conflict 0
-#endif
-
-#ifdef SQLITE_OMIT_SHARED_CACHE
-# define sqlite3_enable_shared_cache 0
-#endif
-
-#if defined(SQLITE_OMIT_TRACE) || defined(SQLITE_OMIT_DEPRECATED)
-# define sqlite3_profile 0
-# define sqlite3_trace 0
-#endif
-
-#ifdef SQLITE_OMIT_GET_TABLE
-# define sqlite3_free_table 0
-# define sqlite3_get_table 0
-#endif
-
-#ifdef SQLITE_OMIT_INCRBLOB
-#define sqlite3_bind_zeroblob 0
-#define sqlite3_blob_bytes 0
-#define sqlite3_blob_close 0
-#define sqlite3_blob_open 0
-#define sqlite3_blob_read 0
-#define sqlite3_blob_write 0
-#define sqlite3_blob_reopen 0
-#endif
-
-#if defined(SQLITE_OMIT_TRACE)
-# define sqlite3_trace_v2 0
-#endif
-
-/*
-** The following structure contains pointers to all SQLite API routines.
-** A pointer to this structure is passed into extensions when they are
-** loaded so that the extension can make calls back into the SQLite
-** library.
-**
-** When adding new APIs, add them to the bottom of this structure
-** in order to preserve backwards compatibility.
-**
-** Extensions that use newer APIs should first call the
-** sqlite3_libversion_number() to make sure that the API they
-** intend to use is supported by the library. Extensions should
-** also check to make sure that the pointer to the function is
-** not NULL before calling it.
-*/
-static const sqlite3_api_routines sqlite3Apis = {
- sqlite3_aggregate_context,
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_aggregate_count,
-#else
- 0,
-#endif
- sqlite3_bind_blob,
- sqlite3_bind_double,
- sqlite3_bind_int,
- sqlite3_bind_int64,
- sqlite3_bind_null,
- sqlite3_bind_parameter_count,
- sqlite3_bind_parameter_index,
- sqlite3_bind_parameter_name,
- sqlite3_bind_text,
- sqlite3_bind_text16,
- sqlite3_bind_value,
- sqlite3_busy_handler,
- sqlite3_busy_timeout,
- sqlite3_changes,
- sqlite3_close,
- sqlite3_collation_needed,
- sqlite3_collation_needed16,
- sqlite3_column_blob,
- sqlite3_column_bytes,
- sqlite3_column_bytes16,
- sqlite3_column_count,
- sqlite3_column_database_name,
- sqlite3_column_database_name16,
- sqlite3_column_decltype,
- sqlite3_column_decltype16,
- sqlite3_column_double,
- sqlite3_column_int,
- sqlite3_column_int64,
- sqlite3_column_name,
- sqlite3_column_name16,
- sqlite3_column_origin_name,
- sqlite3_column_origin_name16,
- sqlite3_column_table_name,
- sqlite3_column_table_name16,
- sqlite3_column_text,
- sqlite3_column_text16,
- sqlite3_column_type,
- sqlite3_column_value,
- sqlite3_commit_hook,
- sqlite3_complete,
- sqlite3_complete16,
- sqlite3_create_collation,
- sqlite3_create_collation16,
- sqlite3_create_function,
- sqlite3_create_function16,
- sqlite3_create_module,
- sqlite3_data_count,
- sqlite3_db_handle,
- sqlite3_declare_vtab,
- sqlite3_enable_shared_cache,
- sqlite3_errcode,
- sqlite3_errmsg,
- sqlite3_errmsg16,
- sqlite3_exec,
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_expired,
-#else
- 0,
-#endif
- sqlite3_finalize,
- sqlite3_free,
- sqlite3_free_table,
- sqlite3_get_autocommit,
- sqlite3_get_auxdata,
- sqlite3_get_table,
- 0, /* Was sqlite3_global_recover(), but that function is deprecated */
- sqlite3_interrupt,
- sqlite3_last_insert_rowid,
- sqlite3_libversion,
- sqlite3_libversion_number,
- sqlite3_malloc,
- sqlite3_mprintf,
- sqlite3_open,
- sqlite3_open16,
- sqlite3_prepare,
- sqlite3_prepare16,
- sqlite3_profile,
- sqlite3_progress_handler,
- sqlite3_realloc,
- sqlite3_reset,
- sqlite3_result_blob,
- sqlite3_result_double,
- sqlite3_result_error,
- sqlite3_result_error16,
- sqlite3_result_int,
- sqlite3_result_int64,
- sqlite3_result_null,
- sqlite3_result_text,
- sqlite3_result_text16,
- sqlite3_result_text16be,
- sqlite3_result_text16le,
- sqlite3_result_value,
- sqlite3_rollback_hook,
- sqlite3_set_authorizer,
- sqlite3_set_auxdata,
- sqlite3_snprintf,
- sqlite3_step,
- sqlite3_table_column_metadata,
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_thread_cleanup,
-#else
- 0,
-#endif
- sqlite3_total_changes,
- sqlite3_trace,
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_transfer_bindings,
-#else
- 0,
-#endif
- sqlite3_update_hook,
- sqlite3_user_data,
- sqlite3_value_blob,
- sqlite3_value_bytes,
- sqlite3_value_bytes16,
- sqlite3_value_double,
- sqlite3_value_int,
- sqlite3_value_int64,
- sqlite3_value_numeric_type,
- sqlite3_value_text,
- sqlite3_value_text16,
- sqlite3_value_text16be,
- sqlite3_value_text16le,
- sqlite3_value_type,
- sqlite3_vmprintf,
- /*
- ** The original API set ends here. All extensions can call any
- ** of the APIs above provided that the pointer is not NULL. But
- ** before calling APIs that follow, extension should check the
- ** sqlite3_libversion_number() to make sure they are dealing with
- ** a library that is new enough to support that API.
- *************************************************************************
- */
- sqlite3_overload_function,
-
- /*
- ** Added after 3.3.13
- */
- sqlite3_prepare_v2,
- sqlite3_prepare16_v2,
- sqlite3_clear_bindings,
-
- /*
- ** Added for 3.4.1
- */
- sqlite3_create_module_v2,
-
- /*
- ** Added for 3.5.0
- */
- sqlite3_bind_zeroblob,
- sqlite3_blob_bytes,
- sqlite3_blob_close,
- sqlite3_blob_open,
- sqlite3_blob_read,
- sqlite3_blob_write,
- sqlite3_create_collation_v2,
- sqlite3_file_control,
- sqlite3_memory_highwater,
- sqlite3_memory_used,
-#ifdef SQLITE_MUTEX_OMIT
- 0,
- 0,
- 0,
- 0,
- 0,
-#else
- sqlite3_mutex_alloc,
- sqlite3_mutex_enter,
- sqlite3_mutex_free,
- sqlite3_mutex_leave,
- sqlite3_mutex_try,
-#endif
- sqlite3_open_v2,
- sqlite3_release_memory,
- sqlite3_result_error_nomem,
- sqlite3_result_error_toobig,
- sqlite3_sleep,
- sqlite3_soft_heap_limit,
- sqlite3_vfs_find,
- sqlite3_vfs_register,
- sqlite3_vfs_unregister,
-
- /*
- ** Added for 3.5.8
- */
- sqlite3_threadsafe,
- sqlite3_result_zeroblob,
- sqlite3_result_error_code,
- sqlite3_test_control,
- sqlite3_randomness,
- sqlite3_context_db_handle,
-
- /*
- ** Added for 3.6.0
- */
- sqlite3_extended_result_codes,
- sqlite3_limit,
- sqlite3_next_stmt,
- sqlite3_sql,
- sqlite3_status,
-
- /*
- ** Added for 3.7.4
- */
- sqlite3_backup_finish,
- sqlite3_backup_init,
- sqlite3_backup_pagecount,
- sqlite3_backup_remaining,
- sqlite3_backup_step,
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
- sqlite3_compileoption_get,
- sqlite3_compileoption_used,
-#else
- 0,
- 0,
-#endif
- sqlite3_create_function_v2,
- sqlite3_db_config,
- sqlite3_db_mutex,
- sqlite3_db_status,
- sqlite3_extended_errcode,
- sqlite3_log,
- sqlite3_soft_heap_limit64,
- sqlite3_sourceid,
- sqlite3_stmt_status,
- sqlite3_strnicmp,
-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
- sqlite3_unlock_notify,
-#else
- 0,
-#endif
-#ifndef SQLITE_OMIT_WAL
- sqlite3_wal_autocheckpoint,
- sqlite3_wal_checkpoint,
- sqlite3_wal_hook,
-#else
- 0,
- 0,
- 0,
-#endif
- sqlite3_blob_reopen,
- sqlite3_vtab_config,
- sqlite3_vtab_on_conflict,
- sqlite3_close_v2,
- sqlite3_db_filename,
- sqlite3_db_readonly,
- sqlite3_db_release_memory,
- sqlite3_errstr,
- sqlite3_stmt_busy,
- sqlite3_stmt_readonly,
- sqlite3_stricmp,
- sqlite3_uri_boolean,
- sqlite3_uri_int64,
- sqlite3_uri_parameter,
- sqlite3_vsnprintf,
- sqlite3_wal_checkpoint_v2,
- /* Version 3.8.7 and later */
- sqlite3_auto_extension,
- sqlite3_bind_blob64,
- sqlite3_bind_text64,
- sqlite3_cancel_auto_extension,
- sqlite3_load_extension,
- sqlite3_malloc64,
- sqlite3_msize,
- sqlite3_realloc64,
- sqlite3_reset_auto_extension,
- sqlite3_result_blob64,
- sqlite3_result_text64,
- sqlite3_strglob,
- /* Version 3.8.11 and later */
- (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup,
- sqlite3_value_free,
- sqlite3_result_zeroblob64,
- sqlite3_bind_zeroblob64,
- /* Version 3.9.0 and later */
- sqlite3_value_subtype,
- sqlite3_result_subtype,
- /* Version 3.10.0 and later */
- sqlite3_status64,
- sqlite3_strlike,
- sqlite3_db_cacheflush,
- /* Version 3.12.0 and later */
- sqlite3_system_errno,
- /* Version 3.14.0 and later */
- sqlite3_trace_v2,
- sqlite3_expanded_sql,
- /* Version 3.18.0 and later */
- sqlite3_set_last_insert_rowid,
- /* Version 3.20.0 and later */
- sqlite3_prepare_v3,
- sqlite3_prepare16_v3,
- sqlite3_bind_pointer,
- sqlite3_result_pointer,
- sqlite3_value_pointer,
- /* Version 3.22.0 and later */
- sqlite3_vtab_nochange,
- sqlite3_value_nochange,
- sqlite3_vtab_collation,
- /* Version 3.24.0 and later */
- sqlite3_keyword_count,
- sqlite3_keyword_name,
- sqlite3_keyword_check,
- sqlite3_str_new,
- sqlite3_str_finish,
- sqlite3_str_appendf,
- sqlite3_str_vappendf,
- sqlite3_str_append,
- sqlite3_str_appendall,
- sqlite3_str_appendchar,
- sqlite3_str_reset,
- sqlite3_str_errcode,
- sqlite3_str_length,
- sqlite3_str_value
-};
-
-/*
-** Attempt to load an SQLite extension library contained in the file
-** zFile. The entry point is zProc. zProc may be 0 in which case a
-** default entry point name (sqlite3_extension_init) is used. Use
-** of the default name is recommended.
-**
-** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
-**
-** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
-** error message text. The calling function should free this memory
-** by calling sqlite3DbFree(db, ).
-*/
-static int sqlite3LoadExtension(
- sqlite3 *db, /* Load the extension into this database connection */
- const char *zFile, /* Name of the shared library containing extension */
- const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */
- char **pzErrMsg /* Put error message here if not 0 */
-){
- sqlite3_vfs *pVfs = db->pVfs;
- void *handle;
- sqlite3_loadext_entry xInit;
- char *zErrmsg = 0;
- const char *zEntry;
- char *zAltEntry = 0;
- void **aHandle;
- u64 nMsg = 300 + sqlite3Strlen30(zFile);
- int ii;
- int rc;
-
- /* Shared library endings to try if zFile cannot be loaded as written */
- static const char *azEndings[] = {
-#if SQLITE_OS_WIN
- "dll"
-#elif defined(__APPLE__)
- "dylib"
-#else
- "so"
-#endif
- };
-
-
- if( pzErrMsg ) *pzErrMsg = 0;
-
- /* Ticket #1863. To avoid a creating security problems for older
- ** applications that relink against newer versions of SQLite, the
- ** ability to run load_extension is turned off by default. One
- ** must call either sqlite3_enable_load_extension(db) or
- ** sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0)
- ** to turn on extension loading.
- */
- if( (db->flags & SQLITE_LoadExtension)==0 ){
- if( pzErrMsg ){
- *pzErrMsg = sqlite3_mprintf("not authorized");
- }
- return SQLITE_ERROR;
- }
-
- zEntry = zProc ? zProc : "sqlite3_extension_init";
-
- handle = sqlite3OsDlOpen(pVfs, zFile);
-#if SQLITE_OS_UNIX || SQLITE_OS_WIN
- for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){
- char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]);
- if( zAltFile==0 ) return SQLITE_NOMEM_BKPT;
- handle = sqlite3OsDlOpen(pVfs, zAltFile);
- sqlite3_free(zAltFile);
- }
-#endif
- if( handle==0 ){
- if( pzErrMsg ){
- *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
- if( zErrmsg ){
- sqlite3_snprintf(nMsg, zErrmsg,
- "unable to open shared library [%s]", zFile);
- sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
- }
- }
- return SQLITE_ERROR;
- }
- xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
-
- /* If no entry point was specified and the default legacy
- ** entry point name "sqlite3_extension_init" was not found, then
- ** construct an entry point name "sqlite3_X_init" where the X is
- ** replaced by the lowercase value of every ASCII alphabetic
- ** character in the filename after the last "/" upto the first ".",
- ** and eliding the first three characters if they are "lib".
- ** Examples:
- **
- ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init
- ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init
- */
- if( xInit==0 && zProc==0 ){
- int iFile, iEntry, c;
- int ncFile = sqlite3Strlen30(zFile);
- zAltEntry = sqlite3_malloc64(ncFile+30);
- if( zAltEntry==0 ){
- sqlite3OsDlClose(pVfs, handle);
- return SQLITE_NOMEM_BKPT;
- }
- memcpy(zAltEntry, "sqlite3_", 8);
- for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
- iFile++;
- if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
- for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
- if( sqlite3Isalpha(c) ){
- zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
- }
- }
- memcpy(zAltEntry+iEntry, "_init", 6);
- zEntry = zAltEntry;
- xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
- }
- if( xInit==0 ){
- if( pzErrMsg ){
- nMsg += sqlite3Strlen30(zEntry);
- *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
- if( zErrmsg ){
- sqlite3_snprintf(nMsg, zErrmsg,
- "no entry point [%s] in shared library [%s]", zEntry, zFile);
- sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
- }
- }
- sqlite3OsDlClose(pVfs, handle);
- sqlite3_free(zAltEntry);
- return SQLITE_ERROR;
- }
- sqlite3_free(zAltEntry);
- rc = xInit(db, &zErrmsg, &sqlite3Apis);
- if( rc ){
- if( rc==SQLITE_OK_LOAD_PERMANENTLY ) return SQLITE_OK;
- if( pzErrMsg ){
- *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
- }
- sqlite3_free(zErrmsg);
- sqlite3OsDlClose(pVfs, handle);
- return SQLITE_ERROR;
- }
-
- /* Append the new shared library handle to the db->aExtension array. */
- aHandle = sqlite3DbMallocZero(db, sizeof(handle)*(db->nExtension+1));
- if( aHandle==0 ){
- return SQLITE_NOMEM_BKPT;
- }
- if( db->nExtension>0 ){
- memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension);
- }
- sqlite3DbFree(db, db->aExtension);
- db->aExtension = aHandle;
-
- db->aExtension[db->nExtension++] = handle;
- return SQLITE_OK;
-}
-int sqlite3_load_extension(
- sqlite3 *db, /* Load the extension into this database connection */
- const char *zFile, /* Name of the shared library containing extension */
- const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */
- char **pzErrMsg /* Put error message here if not 0 */
-){
- int rc;
- sqlite3_mutex_enter(db->mutex);
- rc = sqlite3LoadExtension(db, zFile, zProc, pzErrMsg);
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** Call this routine when the database connection is closing in order
-** to clean up loaded extensions
-*/
-void sqlite3CloseExtensions(sqlite3 *db){
- int i;
- assert( sqlite3_mutex_held(db->mutex) );
- for(i=0; i<db->nExtension; i++){
- sqlite3OsDlClose(db->pVfs, db->aExtension[i]);
- }
- sqlite3DbFree(db, db->aExtension);
-}
-
-/*
-** Enable or disable extension loading. Extension loading is disabled by
-** default so as not to open security holes in older applications.
-*/
-int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
- sqlite3_mutex_enter(db->mutex);
- if( onoff ){
- db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc;
- }else{
- db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
- }
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
-}
-
-#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */
-
-/*
-** The following object holds the list of automatically loaded
-** extensions.
-**
-** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER
-** mutex must be held while accessing this list.
-*/
-typedef struct sqlite3AutoExtList sqlite3AutoExtList;
-static SQLITE_WSD struct sqlite3AutoExtList {
- u32 nExt; /* Number of entries in aExt[] */
- void (**aExt)(void); /* Pointers to the extension init functions */
-} sqlite3Autoext = { 0, 0 };
-
-/* The "wsdAutoext" macro will resolve to the autoextension
-** state vector. If writable static data is unsupported on the target,
-** we have to locate the state vector at run-time. In the more common
-** case where writable static data is supported, wsdStat can refer directly
-** to the "sqlite3Autoext" state vector declared above.
-*/
-#ifdef SQLITE_OMIT_WSD
-# define wsdAutoextInit \
- sqlite3AutoExtList *x = &GLOBAL(sqlite3AutoExtList,sqlite3Autoext)
-# define wsdAutoext x[0]
-#else
-# define wsdAutoextInit
-# define wsdAutoext sqlite3Autoext
-#endif
-
-
-/*
-** Register a statically linked extension that is automatically
-** loaded by every new database connection.
-*/
-int sqlite3_auto_extension(
- void (*xInit)(void)
-){
- int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_AUTOINIT
- rc = sqlite3_initialize();
- if( rc ){
- return rc;
- }else
-#endif
- {
- u32 i;
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
- wsdAutoextInit;
- sqlite3_mutex_enter(mutex);
- for(i=0; i<wsdAutoext.nExt; i++){
- if( wsdAutoext.aExt[i]==xInit ) break;
- }
- if( i==wsdAutoext.nExt ){
- u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
- void (**aNew)(void);
- aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte);
- if( aNew==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- wsdAutoext.aExt = aNew;
- wsdAutoext.aExt[wsdAutoext.nExt] = xInit;
- wsdAutoext.nExt++;
- }
- }
- sqlite3_mutex_leave(mutex);
- assert( (rc&0xff)==rc );
- return rc;
- }
-}
-
-/*
-** Cancel a prior call to sqlite3_auto_extension. Remove xInit from the
-** set of routines that is invoked for each new database connection, if it
-** is currently on the list. If xInit is not on the list, then this
-** routine is a no-op.
-**
-** Return 1 if xInit was found on the list and removed. Return 0 if xInit
-** was not on the list.
-*/
-int sqlite3_cancel_auto_extension(
- void (*xInit)(void)
-){
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
- int i;
- int n = 0;
- wsdAutoextInit;
- sqlite3_mutex_enter(mutex);
- for(i=(int)wsdAutoext.nExt-1; i>=0; i--){
- if( wsdAutoext.aExt[i]==xInit ){
- wsdAutoext.nExt--;
- wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
- n++;
- break;
- }
- }
- sqlite3_mutex_leave(mutex);
- return n;
-}
-
-/*
-** Reset the automatic extension loading mechanism.
-*/
-void sqlite3_reset_auto_extension(void){
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize()==SQLITE_OK )
-#endif
- {
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
- wsdAutoextInit;
- sqlite3_mutex_enter(mutex);
- sqlite3_free(wsdAutoext.aExt);
- wsdAutoext.aExt = 0;
- wsdAutoext.nExt = 0;
- sqlite3_mutex_leave(mutex);
- }
-}
-
-/*
-** Load all automatic extensions.
-**
-** If anything goes wrong, set an error in the database connection.
-*/
-void sqlite3AutoLoadExtensions(sqlite3 *db){
- u32 i;
- int go = 1;
- int rc;
- sqlite3_loadext_entry xInit;
-
- wsdAutoextInit;
- if( wsdAutoext.nExt==0 ){
- /* Common case: early out without every having to acquire a mutex */
- return;
- }
- for(i=0; go; i++){
- char *zErrmsg;
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
-#ifdef SQLITE_OMIT_LOAD_EXTENSION
- const sqlite3_api_routines *pThunk = 0;
-#else
- const sqlite3_api_routines *pThunk = &sqlite3Apis;
-#endif
- sqlite3_mutex_enter(mutex);
- if( i>=wsdAutoext.nExt ){
- xInit = 0;
- go = 0;
- }else{
- xInit = (sqlite3_loadext_entry)wsdAutoext.aExt[i];
- }
- sqlite3_mutex_leave(mutex);
- zErrmsg = 0;
- if( xInit && (rc = xInit(db, &zErrmsg, pThunk))!=0 ){
- sqlite3ErrorWithMsg(db, rc,
- "automatic extension loading failed: %s", zErrmsg);
- go = 0;
- }
- sqlite3_free(zErrmsg);
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/main.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/main.c
deleted file mode 100644
index 8e89cc553a8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/main.c
+++ /dev/null
@@ -1,4258 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Main file for the SQLite library. The routines in this file
-** implement the programmer interface to the library. Routines in
-** other files are for internal use by SQLite and should not be
-** accessed by users of the library.
-*/
-#include "sqliteInt.h"
-
-#ifdef SQLITE_ENABLE_FTS3
-# include "fts3.h"
-#endif
-#ifdef SQLITE_ENABLE_RTREE
-# include "rtree.h"
-#endif
-#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
-# include "sqliteicu.h"
-#endif
-#ifdef SQLITE_ENABLE_JSON1
-int sqlite3Json1Init(sqlite3*);
-#endif
-#ifdef SQLITE_ENABLE_STMTVTAB
-int sqlite3StmtVtabInit(sqlite3*);
-#endif
-#ifdef SQLITE_ENABLE_FTS5
-int sqlite3Fts5Init(sqlite3*);
-#endif
-
-#ifndef SQLITE_AMALGAMATION
-/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
-** contains the text of SQLITE_VERSION macro.
-*/
-const char sqlite3_version[] = SQLITE_VERSION;
-#endif
-
-/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns
-** a pointer to the to the sqlite3_version[] string constant.
-*/
-const char *sqlite3_libversion(void){ return sqlite3_version; }
-
-/* IMPLEMENTATION-OF: R-25063-23286 The sqlite3_sourceid() function returns a
-** pointer to a string constant whose value is the same as the
-** SQLITE_SOURCE_ID C preprocessor macro. Except if SQLite is built using
-** an edited copy of the amalgamation, then the last four characters of
-** the hash might be different from SQLITE_SOURCE_ID.
-*/
-const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
-
-/* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function
-** returns an integer equal to SQLITE_VERSION_NUMBER.
-*/
-int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
-
-/* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns
-** zero if and only if SQLite was compiled with mutexing code omitted due to
-** the SQLITE_THREADSAFE compile-time option being set to 0.
-*/
-int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
-
-/*
-** When compiling the test fixture or with debugging enabled (on Win32),
-** this variable being set to non-zero will cause OSTRACE macros to emit
-** extra diagnostic information.
-*/
-#ifdef SQLITE_HAVE_OS_TRACE
-# ifndef SQLITE_DEBUG_OS_TRACE
-# define SQLITE_DEBUG_OS_TRACE 0
-# endif
- int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
-#endif
-
-#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
-/*
-** If the following function pointer is not NULL and if
-** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
-** I/O active are written using this function. These messages
-** are intended for debugging activity only.
-*/
-SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0;
-#endif
-
-/*
-** If the following global variable points to a string which is the
-** name of a directory, then that directory will be used to store
-** temporary files.
-**
-** See also the "PRAGMA temp_store_directory" SQL command.
-*/
-char *sqlite3_temp_directory = 0;
-
-/*
-** If the following global variable points to a string which is the
-** name of a directory, then that directory will be used to store
-** all database files specified with a relative pathname.
-**
-** See also the "PRAGMA data_store_directory" SQL command.
-*/
-char *sqlite3_data_directory = 0;
-
-/*
-** Initialize SQLite.
-**
-** This routine must be called to initialize the memory allocation,
-** VFS, and mutex subsystems prior to doing any serious work with
-** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
-** this routine will be called automatically by key routines such as
-** sqlite3_open().
-**
-** This routine is a no-op except on its very first call for the process,
-** or for the first call after a call to sqlite3_shutdown.
-**
-** The first thread to call this routine runs the initialization to
-** completion. If subsequent threads call this routine before the first
-** thread has finished the initialization process, then the subsequent
-** threads must block until the first thread finishes with the initialization.
-**
-** The first thread might call this routine recursively. Recursive
-** calls to this routine should not block, of course. Otherwise the
-** initialization process would never complete.
-**
-** Let X be the first thread to enter this routine. Let Y be some other
-** thread. Then while the initial invocation of this routine by X is
-** incomplete, it is required that:
-**
-** * Calls to this routine from Y must block until the outer-most
-** call by X completes.
-**
-** * Recursive calls to this routine from thread X return immediately
-** without blocking.
-*/
-int sqlite3_initialize(void){
- MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
- int rc; /* Result code */
-#ifdef SQLITE_EXTRA_INIT
- int bRunExtraInit = 0; /* Extra initialization needed */
-#endif
-
-#ifdef SQLITE_OMIT_WSD
- rc = sqlite3_wsd_init(4096, 24);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-#endif
-
- /* If the following assert() fails on some obscure processor/compiler
- ** combination, the work-around is to set the correct pointer
- ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */
- assert( SQLITE_PTRSIZE==sizeof(char*) );
-
- /* If SQLite is already completely initialized, then this call
- ** to sqlite3_initialize() should be a no-op. But the initialization
- ** must be complete. So isInit must not be set until the very end
- ** of this routine.
- */
- if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
-
- /* Make sure the mutex subsystem is initialized. If unable to
- ** initialize the mutex subsystem, return early with the error.
- ** If the system is so sick that we are unable to allocate a mutex,
- ** there is not much SQLite is going to be able to do.
- **
- ** The mutex subsystem must take care of serializing its own
- ** initialization.
- */
- rc = sqlite3MutexInit();
- if( rc ) return rc;
-
- /* Initialize the malloc() system and the recursive pInitMutex mutex.
- ** This operation is protected by the STATIC_MASTER mutex. Note that
- ** MutexAlloc() is called for a static mutex prior to initializing the
- ** malloc subsystem - this implies that the allocation of a static
- ** mutex must not require support from the malloc subsystem.
- */
- MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
- sqlite3_mutex_enter(pMaster);
- sqlite3GlobalConfig.isMutexInit = 1;
- if( !sqlite3GlobalConfig.isMallocInit ){
- rc = sqlite3MallocInit();
- }
- if( rc==SQLITE_OK ){
- sqlite3GlobalConfig.isMallocInit = 1;
- if( !sqlite3GlobalConfig.pInitMutex ){
- sqlite3GlobalConfig.pInitMutex =
- sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
- if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){
- rc = SQLITE_NOMEM_BKPT;
- }
- }
- }
- if( rc==SQLITE_OK ){
- sqlite3GlobalConfig.nRefInitMutex++;
- }
- sqlite3_mutex_leave(pMaster);
-
- /* If rc is not SQLITE_OK at this point, then either the malloc
- ** subsystem could not be initialized or the system failed to allocate
- ** the pInitMutex mutex. Return an error in either case. */
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Do the rest of the initialization under the recursive mutex so
- ** that we will be able to handle recursive calls into
- ** sqlite3_initialize(). The recursive calls normally come through
- ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
- ** recursive calls might also be possible.
- **
- ** IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls
- ** to the xInit method, so the xInit method need not be threadsafe.
- **
- ** The following mutex is what serializes access to the appdef pcache xInit
- ** methods. The sqlite3_pcache_methods.xInit() all is embedded in the
- ** call to sqlite3PcacheInitialize().
- */
- sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex);
- if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){
- sqlite3GlobalConfig.inProgress = 1;
-#ifdef SQLITE_ENABLE_SQLLOG
- {
- extern void sqlite3_init_sqllog(void);
- sqlite3_init_sqllog();
- }
-#endif
- memset(&sqlite3BuiltinFunctions, 0, sizeof(sqlite3BuiltinFunctions));
- sqlite3RegisterBuiltinFunctions();
- if( sqlite3GlobalConfig.isPCacheInit==0 ){
- rc = sqlite3PcacheInitialize();
- }
- if( rc==SQLITE_OK ){
- sqlite3GlobalConfig.isPCacheInit = 1;
- rc = sqlite3OsInit();
- }
-#ifdef SQLITE_ENABLE_DESERIALIZE
- if( rc==SQLITE_OK ){
- rc = sqlite3MemdbInit();
- }
-#endif
- if( rc==SQLITE_OK ){
- sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
- sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
- sqlite3GlobalConfig.isInit = 1;
-#ifdef SQLITE_EXTRA_INIT
- bRunExtraInit = 1;
-#endif
- }
- sqlite3GlobalConfig.inProgress = 0;
- }
- sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);
-
- /* Go back under the static mutex and clean up the recursive
- ** mutex to prevent a resource leak.
- */
- sqlite3_mutex_enter(pMaster);
- sqlite3GlobalConfig.nRefInitMutex--;
- if( sqlite3GlobalConfig.nRefInitMutex<=0 ){
- assert( sqlite3GlobalConfig.nRefInitMutex==0 );
- sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
- sqlite3GlobalConfig.pInitMutex = 0;
- }
- sqlite3_mutex_leave(pMaster);
-
- /* The following is just a sanity check to make sure SQLite has
- ** been compiled correctly. It is important to run this code, but
- ** we don't want to run it too often and soak up CPU cycles for no
- ** reason. So we run it once during initialization.
- */
-#ifndef NDEBUG
-#ifndef SQLITE_OMIT_FLOATING_POINT
- /* This section of code's only "output" is via assert() statements. */
- if( rc==SQLITE_OK ){
- u64 x = (((u64)1)<<63)-1;
- double y;
- assert(sizeof(x)==8);
- assert(sizeof(x)==sizeof(y));
- memcpy(&y, &x, 8);
- assert( sqlite3IsNaN(y) );
- }
-#endif
-#endif
-
- /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
- ** compile-time option.
- */
-#ifdef SQLITE_EXTRA_INIT
- if( bRunExtraInit ){
- int SQLITE_EXTRA_INIT(const char*);
- rc = SQLITE_EXTRA_INIT(0);
- }
-#endif
-
- return rc;
-}
-
-/*
-** Undo the effects of sqlite3_initialize(). Must not be called while
-** there are outstanding database connections or memory allocations or
-** while any part of SQLite is otherwise in use in any thread. This
-** routine is not threadsafe. But it is safe to invoke this routine
-** on when SQLite is already shut down. If SQLite is already shut down
-** when this routine is invoked, then this routine is a harmless no-op.
-*/
-int sqlite3_shutdown(void){
-#ifdef SQLITE_OMIT_WSD
- int rc = sqlite3_wsd_init(4096, 24);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-#endif
-
- if( sqlite3GlobalConfig.isInit ){
-#ifdef SQLITE_EXTRA_SHUTDOWN
- void SQLITE_EXTRA_SHUTDOWN(void);
- SQLITE_EXTRA_SHUTDOWN();
-#endif
- sqlite3_os_end();
- sqlite3_reset_auto_extension();
- sqlite3GlobalConfig.isInit = 0;
- }
- if( sqlite3GlobalConfig.isPCacheInit ){
- sqlite3PcacheShutdown();
- sqlite3GlobalConfig.isPCacheInit = 0;
- }
- if( sqlite3GlobalConfig.isMallocInit ){
- sqlite3MallocEnd();
- sqlite3GlobalConfig.isMallocInit = 0;
-
-#ifndef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
- /* The heap subsystem has now been shutdown and these values are supposed
- ** to be NULL or point to memory that was obtained from sqlite3_malloc(),
- ** which would rely on that heap subsystem; therefore, make sure these
- ** values cannot refer to heap memory that was just invalidated when the
- ** heap subsystem was shutdown. This is only done if the current call to
- ** this function resulted in the heap subsystem actually being shutdown.
- */
- sqlite3_data_directory = 0;
- sqlite3_temp_directory = 0;
-#endif
- }
- if( sqlite3GlobalConfig.isMutexInit ){
- sqlite3MutexEnd();
- sqlite3GlobalConfig.isMutexInit = 0;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** This API allows applications to modify the global configuration of
-** the SQLite library at run-time.
-**
-** This routine should only be called when there are no outstanding
-** database connections or memory allocations. This routine is not
-** threadsafe. Failure to heed these warnings can lead to unpredictable
-** behavior.
-*/
-int sqlite3_config(int op, ...){
- va_list ap;
- int rc = SQLITE_OK;
-
- /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
- ** the SQLite library is in use. */
- if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT;
-
- va_start(ap, op);
- switch( op ){
-
- /* Mutex configuration options are only available in a threadsafe
- ** compile.
- */
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */
- case SQLITE_CONFIG_SINGLETHREAD: {
- /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to
- ** Single-thread. */
- sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */
- sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
- break;
- }
-#endif
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */
- case SQLITE_CONFIG_MULTITHREAD: {
- /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to
- ** Multi-thread. */
- sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
- sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
- break;
- }
-#endif
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */
- case SQLITE_CONFIG_SERIALIZED: {
- /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to
- ** Serialized. */
- sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
- sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */
- break;
- }
-#endif
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */
- case SQLITE_CONFIG_MUTEX: {
- /* Specify an alternative mutex implementation */
- sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
- break;
- }
-#endif
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-14450-37597 */
- case SQLITE_CONFIG_GETMUTEX: {
- /* Retrieve the current mutex implementation */
- *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex;
- break;
- }
-#endif
-
- case SQLITE_CONFIG_MALLOC: {
- /* EVIDENCE-OF: R-55594-21030 The SQLITE_CONFIG_MALLOC option takes a
- ** single argument which is a pointer to an instance of the
- ** sqlite3_mem_methods structure. The argument specifies alternative
- ** low-level memory allocation routines to be used in place of the memory
- ** allocation routines built into SQLite. */
- sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*);
- break;
- }
- case SQLITE_CONFIG_GETMALLOC: {
- /* EVIDENCE-OF: R-51213-46414 The SQLITE_CONFIG_GETMALLOC option takes a
- ** single argument which is a pointer to an instance of the
- ** sqlite3_mem_methods structure. The sqlite3_mem_methods structure is
- ** filled with the currently defined memory allocation routines. */
- if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
- *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m;
- break;
- }
- case SQLITE_CONFIG_MEMSTATUS: {
- /* EVIDENCE-OF: R-61275-35157 The SQLITE_CONFIG_MEMSTATUS option takes
- ** single argument of type int, interpreted as a boolean, which enables
- ** or disables the collection of memory allocation statistics. */
- sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
- break;
- }
- case SQLITE_CONFIG_SMALL_MALLOC: {
- sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int);
- break;
- }
- case SQLITE_CONFIG_PAGECACHE: {
- /* EVIDENCE-OF: R-18761-36601 There are three arguments to
- ** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory (pMem),
- ** the size of each page cache line (sz), and the number of cache lines
- ** (N). */
- sqlite3GlobalConfig.pPage = va_arg(ap, void*);
- sqlite3GlobalConfig.szPage = va_arg(ap, int);
- sqlite3GlobalConfig.nPage = va_arg(ap, int);
- break;
- }
- case SQLITE_CONFIG_PCACHE_HDRSZ: {
- /* EVIDENCE-OF: R-39100-27317 The SQLITE_CONFIG_PCACHE_HDRSZ option takes
- ** a single parameter which is a pointer to an integer and writes into
- ** that integer the number of extra bytes per page required for each page
- ** in SQLITE_CONFIG_PAGECACHE. */
- *va_arg(ap, int*) =
- sqlite3HeaderSizeBtree() +
- sqlite3HeaderSizePcache() +
- sqlite3HeaderSizePcache1();
- break;
- }
-
- case SQLITE_CONFIG_PCACHE: {
- /* no-op */
- break;
- }
- case SQLITE_CONFIG_GETPCACHE: {
- /* now an error */
- rc = SQLITE_ERROR;
- break;
- }
-
- case SQLITE_CONFIG_PCACHE2: {
- /* EVIDENCE-OF: R-63325-48378 The SQLITE_CONFIG_PCACHE2 option takes a
- ** single argument which is a pointer to an sqlite3_pcache_methods2
- ** object. This object specifies the interface to a custom page cache
- ** implementation. */
- sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*);
- break;
- }
- case SQLITE_CONFIG_GETPCACHE2: {
- /* EVIDENCE-OF: R-22035-46182 The SQLITE_CONFIG_GETPCACHE2 option takes a
- ** single argument which is a pointer to an sqlite3_pcache_methods2
- ** object. SQLite copies of the current page cache implementation into
- ** that object. */
- if( sqlite3GlobalConfig.pcache2.xInit==0 ){
- sqlite3PCacheSetDefault();
- }
- *va_arg(ap, sqlite3_pcache_methods2*) = sqlite3GlobalConfig.pcache2;
- break;
- }
-
-/* EVIDENCE-OF: R-06626-12911 The SQLITE_CONFIG_HEAP option is only
-** available if SQLite is compiled with either SQLITE_ENABLE_MEMSYS3 or
-** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */
-#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
- case SQLITE_CONFIG_HEAP: {
- /* EVIDENCE-OF: R-19854-42126 There are three arguments to
- ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the
- ** number of bytes in the memory buffer, and the minimum allocation size.
- */
- sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
- sqlite3GlobalConfig.nHeap = va_arg(ap, int);
- sqlite3GlobalConfig.mnReq = va_arg(ap, int);
-
- if( sqlite3GlobalConfig.mnReq<1 ){
- sqlite3GlobalConfig.mnReq = 1;
- }else if( sqlite3GlobalConfig.mnReq>(1<<12) ){
- /* cap min request size at 2^12 */
- sqlite3GlobalConfig.mnReq = (1<<12);
- }
-
- if( sqlite3GlobalConfig.pHeap==0 ){
- /* EVIDENCE-OF: R-49920-60189 If the first pointer (the memory pointer)
- ** is NULL, then SQLite reverts to using its default memory allocator
- ** (the system malloc() implementation), undoing any prior invocation of
- ** SQLITE_CONFIG_MALLOC.
- **
- ** Setting sqlite3GlobalConfig.m to all zeros will cause malloc to
- ** revert to its default implementation when sqlite3_initialize() is run
- */
- memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
- }else{
- /* EVIDENCE-OF: R-61006-08918 If the memory pointer is not NULL then the
- ** alternative memory allocator is engaged to handle all of SQLites
- ** memory allocation needs. */
-#ifdef SQLITE_ENABLE_MEMSYS3
- sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
-#endif
-#ifdef SQLITE_ENABLE_MEMSYS5
- sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5();
-#endif
- }
- break;
- }
-#endif
-
- case SQLITE_CONFIG_LOOKASIDE: {
- sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
- sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
- break;
- }
-
- /* Record a pointer to the logger function and its first argument.
- ** The default is NULL. Logging is disabled if the function pointer is
- ** NULL.
- */
- case SQLITE_CONFIG_LOG: {
- /* MSVC is picky about pulling func ptrs from va lists.
- ** http://support.microsoft.com/kb/47961
- ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
- */
- typedef void(*LOGFUNC_t)(void*,int,const char*);
- sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
- sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
- break;
- }
-
- /* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames
- ** can be changed at start-time using the
- ** sqlite3_config(SQLITE_CONFIG_URI,1) or
- ** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls.
- */
- case SQLITE_CONFIG_URI: {
- /* EVIDENCE-OF: R-25451-61125 The SQLITE_CONFIG_URI option takes a single
- ** argument of type int. If non-zero, then URI handling is globally
- ** enabled. If the parameter is zero, then URI handling is globally
- ** disabled. */
- sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
- break;
- }
-
- case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
- /* EVIDENCE-OF: R-36592-02772 The SQLITE_CONFIG_COVERING_INDEX_SCAN
- ** option takes a single integer argument which is interpreted as a
- ** boolean in order to enable or disable the use of covering indices for
- ** full table scans in the query optimizer. */
- sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
- break;
- }
-
-#ifdef SQLITE_ENABLE_SQLLOG
- case SQLITE_CONFIG_SQLLOG: {
- typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
- sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
- sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
- break;
- }
-#endif
-
- case SQLITE_CONFIG_MMAP_SIZE: {
- /* EVIDENCE-OF: R-58063-38258 SQLITE_CONFIG_MMAP_SIZE takes two 64-bit
- ** integer (sqlite3_int64) values that are the default mmap size limit
- ** (the default setting for PRAGMA mmap_size) and the maximum allowed
- ** mmap size limit. */
- sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64);
- sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64);
- /* EVIDENCE-OF: R-53367-43190 If either argument to this option is
- ** negative, then that argument is changed to its compile-time default.
- **
- ** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be
- ** silently truncated if necessary so that it does not exceed the
- ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE
- ** compile-time option.
- */
- if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
- mxMmap = SQLITE_MAX_MMAP_SIZE;
- }
- if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
- if( szMmap>mxMmap) szMmap = mxMmap;
- sqlite3GlobalConfig.mxMmap = mxMmap;
- sqlite3GlobalConfig.szMmap = szMmap;
- break;
- }
-
-#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC) /* IMP: R-04780-55815 */
- case SQLITE_CONFIG_WIN32_HEAPSIZE: {
- /* EVIDENCE-OF: R-34926-03360 SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit
- ** unsigned integer value that specifies the maximum size of the created
- ** heap. */
- sqlite3GlobalConfig.nHeap = va_arg(ap, int);
- break;
- }
-#endif
-
- case SQLITE_CONFIG_PMASZ: {
- sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int);
- break;
- }
-
- case SQLITE_CONFIG_STMTJRNL_SPILL: {
- sqlite3GlobalConfig.nStmtSpill = va_arg(ap, int);
- break;
- }
-
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- case SQLITE_CONFIG_SORTERREF_SIZE: {
- int iVal = va_arg(ap, int);
- if( iVal<0 ){
- iVal = SQLITE_DEFAULT_SORTERREF_SIZE;
- }
- sqlite3GlobalConfig.szSorterRef = (u32)iVal;
- break;
- }
-#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
-
- default: {
- rc = SQLITE_ERROR;
- break;
- }
- }
- va_end(ap);
- return rc;
-}
-
-/*
-** Set up the lookaside buffers for a database connection.
-** Return SQLITE_OK on success.
-** If lookaside is already active, return SQLITE_BUSY.
-**
-** The sz parameter is the number of bytes in each lookaside slot.
-** The cnt parameter is the number of slots. If pStart is NULL the
-** space for the lookaside memory is obtained from sqlite3_malloc().
-** If pStart is not NULL then it is sz*cnt bytes of memory to use for
-** the lookaside memory.
-*/
-static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
-#ifndef SQLITE_OMIT_LOOKASIDE
- void *pStart;
-
- if( sqlite3LookasideUsed(db,0)>0 ){
- return SQLITE_BUSY;
- }
- /* Free any existing lookaside buffer for this handle before
- ** allocating a new one so we don't have to have space for
- ** both at the same time.
- */
- if( db->lookaside.bMalloced ){
- sqlite3_free(db->lookaside.pStart);
- }
- /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger
- ** than a pointer to be useful.
- */
- sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */
- if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
- if( cnt<0 ) cnt = 0;
- if( sz==0 || cnt==0 ){
- sz = 0;
- pStart = 0;
- }else if( pBuf==0 ){
- sqlite3BeginBenignMalloc();
- pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */
- sqlite3EndBenignMalloc();
- if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
- }else{
- pStart = pBuf;
- }
- db->lookaside.pStart = pStart;
- db->lookaside.pInit = 0;
- db->lookaside.pFree = 0;
- db->lookaside.sz = (u16)sz;
- if( pStart ){
- int i;
- LookasideSlot *p;
- assert( sz > (int)sizeof(LookasideSlot*) );
- db->lookaside.nSlot = cnt;
- p = (LookasideSlot*)pStart;
- for(i=cnt-1; i>=0; i--){
- p->pNext = db->lookaside.pInit;
- db->lookaside.pInit = p;
- p = (LookasideSlot*)&((u8*)p)[sz];
- }
- db->lookaside.pEnd = p;
- db->lookaside.bDisable = 0;
- db->lookaside.bMalloced = pBuf==0 ?1:0;
- }else{
- db->lookaside.pStart = db;
- db->lookaside.pEnd = db;
- db->lookaside.bDisable = 1;
- db->lookaside.bMalloced = 0;
- db->lookaside.nSlot = 0;
- }
-#endif /* SQLITE_OMIT_LOOKASIDE */
- return SQLITE_OK;
-}
-
-/*
-** Return the mutex associated with a database connection.
-*/
-sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- return db->mutex;
-}
-
-/*
-** Free up as much memory as we can from the given database
-** connection.
-*/
-int sqlite3_db_release_memory(sqlite3 *db){
- int i;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- sqlite3BtreeEnterAll(db);
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- Pager *pPager = sqlite3BtreePager(pBt);
- sqlite3PagerShrink(pPager);
- }
- }
- sqlite3BtreeLeaveAll(db);
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
-}
-
-/*
-** Flush any dirty pages in the pager-cache for any attached database
-** to disk.
-*/
-int sqlite3_db_cacheflush(sqlite3 *db){
- int i;
- int rc = SQLITE_OK;
- int bSeenBusy = 0;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- sqlite3BtreeEnterAll(db);
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt && sqlite3BtreeIsInTrans(pBt) ){
- Pager *pPager = sqlite3BtreePager(pBt);
- rc = sqlite3PagerFlush(pPager);
- if( rc==SQLITE_BUSY ){
- bSeenBusy = 1;
- rc = SQLITE_OK;
- }
- }
- }
- sqlite3BtreeLeaveAll(db);
- sqlite3_mutex_leave(db->mutex);
- return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc);
-}
-
-/*
-** Configuration settings for an individual database connection
-*/
-int sqlite3_db_config(sqlite3 *db, int op, ...){
- va_list ap;
- int rc;
- va_start(ap, op);
- switch( op ){
- case SQLITE_DBCONFIG_MAINDBNAME: {
- /* IMP: R-06824-28531 */
- /* IMP: R-36257-52125 */
- db->aDb[0].zDbSName = va_arg(ap,char*);
- rc = SQLITE_OK;
- break;
- }
- case SQLITE_DBCONFIG_LOOKASIDE: {
- void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */
- int sz = va_arg(ap, int); /* IMP: R-47871-25994 */
- int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */
- rc = setupLookaside(db, pBuf, sz, cnt);
- break;
- }
- default: {
- static const struct {
- int op; /* The opcode */
- u32 mask; /* Mask of the bit in sqlite3.flags to set/clear */
- } aFlagOp[] = {
- { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
- { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
- { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
- { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
- { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
- { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG },
- { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP },
- { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase },
- };
- unsigned int i;
- rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
- for(i=0; i<ArraySize(aFlagOp); i++){
- if( aFlagOp[i].op==op ){
- int onoff = va_arg(ap, int);
- int *pRes = va_arg(ap, int*);
- u32 oldFlags = db->flags;
- if( onoff>0 ){
- db->flags |= aFlagOp[i].mask;
- }else if( onoff==0 ){
- db->flags &= ~aFlagOp[i].mask;
- }
- if( oldFlags!=db->flags ){
- sqlite3ExpirePreparedStatements(db);
- }
- if( pRes ){
- *pRes = (db->flags & aFlagOp[i].mask)!=0;
- }
- rc = SQLITE_OK;
- break;
- }
- }
- break;
- }
- }
- va_end(ap);
- return rc;
-}
-
-
-/*
-** Return true if the buffer z[0..n-1] contains all spaces.
-*/
-static int allSpaces(const char *z, int n){
- while( n>0 && z[n-1]==' ' ){ n--; }
- return n==0;
-}
-
-/*
-** This is the default collating function named "BINARY" which is always
-** available.
-**
-** If the padFlag argument is not NULL then space padding at the end
-** of strings is ignored. This implements the RTRIM collation.
-*/
-static int binCollFunc(
- void *padFlag,
- int nKey1, const void *pKey1,
- int nKey2, const void *pKey2
-){
- int rc, n;
- n = nKey1<nKey2 ? nKey1 : nKey2;
- /* EVIDENCE-OF: R-65033-28449 The built-in BINARY collation compares
- ** strings byte by byte using the memcmp() function from the standard C
- ** library. */
- assert( pKey1 && pKey2 );
- rc = memcmp(pKey1, pKey2, n);
- if( rc==0 ){
- if( padFlag
- && allSpaces(((char*)pKey1)+n, nKey1-n)
- && allSpaces(((char*)pKey2)+n, nKey2-n)
- ){
- /* EVIDENCE-OF: R-31624-24737 RTRIM is like BINARY except that extra
- ** spaces at the end of either string do not change the result. In other
- ** words, strings will compare equal to one another as long as they
- ** differ only in the number of spaces at the end.
- */
- }else{
- rc = nKey1 - nKey2;
- }
- }
- return rc;
-}
-
-/*
-** Another built-in collating sequence: NOCASE.
-**
-** This collating sequence is intended to be used for "case independent
-** comparison". SQLite's knowledge of upper and lower case equivalents
-** extends only to the 26 characters used in the English language.
-**
-** At the moment there is only a UTF-8 implementation.
-*/
-static int nocaseCollatingFunc(
- void *NotUsed,
- int nKey1, const void *pKey1,
- int nKey2, const void *pKey2
-){
- int r = sqlite3StrNICmp(
- (const char *)pKey1, (const char *)pKey2, (nKey1<nKey2)?nKey1:nKey2);
- UNUSED_PARAMETER(NotUsed);
- if( 0==r ){
- r = nKey1-nKey2;
- }
- return r;
-}
-
-/*
-** Return the ROWID of the most recent insert
-*/
-sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- return db->lastRowid;
-}
-
-/*
-** Set the value returned by the sqlite3_last_insert_rowid() API function.
-*/
-void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- db->lastRowid = iRowid;
- sqlite3_mutex_leave(db->mutex);
-}
-
-/*
-** Return the number of changes in the most recent call to sqlite3_exec().
-*/
-int sqlite3_changes(sqlite3 *db){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- return db->nChange;
-}
-
-/*
-** Return the number of changes since the database handle was opened.
-*/
-int sqlite3_total_changes(sqlite3 *db){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- return db->nTotalChange;
-}
-
-/*
-** Close all open savepoints. This function only manipulates fields of the
-** database handle object, it does not close any savepoints that may be open
-** at the b-tree/pager level.
-*/
-void sqlite3CloseSavepoints(sqlite3 *db){
- while( db->pSavepoint ){
- Savepoint *pTmp = db->pSavepoint;
- db->pSavepoint = pTmp->pNext;
- sqlite3DbFree(db, pTmp);
- }
- db->nSavepoint = 0;
- db->nStatement = 0;
- db->isTransactionSavepoint = 0;
-}
-
-/*
-** Invoke the destructor function associated with FuncDef p, if any. Except,
-** if this is not the last copy of the function, do not invoke it. Multiple
-** copies of a single function are created when create_function() is called
-** with SQLITE_ANY as the encoding.
-*/
-static void functionDestroy(sqlite3 *db, FuncDef *p){
- FuncDestructor *pDestructor = p->u.pDestructor;
- if( pDestructor ){
- pDestructor->nRef--;
- if( pDestructor->nRef==0 ){
- pDestructor->xDestroy(pDestructor->pUserData);
- sqlite3DbFree(db, pDestructor);
- }
- }
-}
-
-/*
-** Disconnect all sqlite3_vtab objects that belong to database connection
-** db. This is called when db is being closed.
-*/
-static void disconnectAllVtab(sqlite3 *db){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- int i;
- HashElem *p;
- sqlite3BtreeEnterAll(db);
- for(i=0; i<db->nDb; i++){
- Schema *pSchema = db->aDb[i].pSchema;
- if( db->aDb[i].pSchema ){
- for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
- Table *pTab = (Table *)sqliteHashData(p);
- if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
- }
- }
- }
- for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){
- Module *pMod = (Module *)sqliteHashData(p);
- if( pMod->pEpoTab ){
- sqlite3VtabDisconnect(db, pMod->pEpoTab);
- }
- }
- sqlite3VtabUnlockList(db);
- sqlite3BtreeLeaveAll(db);
-#else
- UNUSED_PARAMETER(db);
-#endif
-}
-
-/*
-** Return TRUE if database connection db has unfinalized prepared
-** statements or unfinished sqlite3_backup objects.
-*/
-static int connectionIsBusy(sqlite3 *db){
- int j;
- assert( sqlite3_mutex_held(db->mutex) );
- if( db->pVdbe ) return 1;
- for(j=0; j<db->nDb; j++){
- Btree *pBt = db->aDb[j].pBt;
- if( pBt && sqlite3BtreeIsInBackup(pBt) ) return 1;
- }
- return 0;
-}
-
-/*
-** Close an existing SQLite database
-*/
-static int sqlite3Close(sqlite3 *db, int forceZombie){
- if( !db ){
- /* EVIDENCE-OF: R-63257-11740 Calling sqlite3_close() or
- ** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */
- return SQLITE_OK;
- }
- if( !sqlite3SafetyCheckSickOrOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
- sqlite3_mutex_enter(db->mutex);
- if( db->mTrace & SQLITE_TRACE_CLOSE ){
- db->xTrace(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0);
- }
-
- /* Force xDisconnect calls on all virtual tables */
- disconnectAllVtab(db);
-
- /* If a transaction is open, the disconnectAllVtab() call above
- ** will not have called the xDisconnect() method on any virtual
- ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
- ** call will do so. We need to do this before the check for active
- ** SQL statements below, as the v-table implementation may be storing
- ** some prepared statements internally.
- */
- sqlite3VtabRollback(db);
-
- /* Legacy behavior (sqlite3_close() behavior) is to return
- ** SQLITE_BUSY if the connection can not be closed immediately.
- */
- if( !forceZombie && connectionIsBusy(db) ){
- sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to close due to unfinalized "
- "statements or unfinished backups");
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_BUSY;
- }
-
-#ifdef SQLITE_ENABLE_SQLLOG
- if( sqlite3GlobalConfig.xSqllog ){
- /* Closing the handle. Fourth parameter is passed the value 2. */
- sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2);
- }
-#endif
-
- /* Convert the connection into a zombie and then close it.
- */
- db->magic = SQLITE_MAGIC_ZOMBIE;
- sqlite3LeaveMutexAndCloseZombie(db);
- return SQLITE_OK;
-}
-
-/*
-** Two variations on the public interface for closing a database
-** connection. The sqlite3_close() version returns SQLITE_BUSY and
-** leaves the connection option if there are unfinalized prepared
-** statements or unfinished sqlite3_backups. The sqlite3_close_v2()
-** version forces the connection to become a zombie if there are
-** unclosed resources, and arranges for deallocation when the last
-** prepare statement or sqlite3_backup closes.
-*/
-int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); }
-int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); }
-
-
-/*
-** Close the mutex on database connection db.
-**
-** Furthermore, if database connection db is a zombie (meaning that there
-** has been a prior call to sqlite3_close(db) or sqlite3_close_v2(db)) and
-** every sqlite3_stmt has now been finalized and every sqlite3_backup has
-** finished, then free all resources.
-*/
-void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
- HashElem *i; /* Hash table iterator */
- int j;
-
- /* If there are outstanding sqlite3_stmt or sqlite3_backup objects
- ** or if the connection has not yet been closed by sqlite3_close_v2(),
- ** then just leave the mutex and return.
- */
- if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
- sqlite3_mutex_leave(db->mutex);
- return;
- }
-
- /* If we reach this point, it means that the database connection has
- ** closed all sqlite3_stmt and sqlite3_backup objects and has been
- ** passed to sqlite3_close (meaning that it is a zombie). Therefore,
- ** go ahead and free all resources.
- */
-
- /* If a transaction is open, roll it back. This also ensures that if
- ** any database schemas have been modified by an uncommitted transaction
- ** they are reset. And that the required b-tree mutex is held to make
- ** the pager rollback and schema reset an atomic operation. */
- sqlite3RollbackAll(db, SQLITE_OK);
-
- /* Free any outstanding Savepoint structures. */
- sqlite3CloseSavepoints(db);
-
- /* Close all database connections */
- for(j=0; j<db->nDb; j++){
- struct Db *pDb = &db->aDb[j];
- if( pDb->pBt ){
- sqlite3BtreeClose(pDb->pBt);
- pDb->pBt = 0;
- if( j!=1 ){
- pDb->pSchema = 0;
- }
- }
- }
- /* Clear the TEMP schema separately and last */
- if( db->aDb[1].pSchema ){
- sqlite3SchemaClear(db->aDb[1].pSchema);
- }
- sqlite3VtabUnlockList(db);
-
- /* Free up the array of auxiliary databases */
- sqlite3CollapseDatabaseArray(db);
- assert( db->nDb<=2 );
- assert( db->aDb==db->aDbStatic );
-
- /* Tell the code in notify.c that the connection no longer holds any
- ** locks and does not require any further unlock-notify callbacks.
- */
- sqlite3ConnectionClosed(db);
-
- for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
- FuncDef *pNext, *p;
- p = sqliteHashData(i);
- do{
- functionDestroy(db, p);
- pNext = p->pNext;
- sqlite3DbFree(db, p);
- p = pNext;
- }while( p );
- }
- sqlite3HashClear(&db->aFunc);
- for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
- CollSeq *pColl = (CollSeq *)sqliteHashData(i);
- /* Invoke any destructors registered for collation sequence user data. */
- for(j=0; j<3; j++){
- if( pColl[j].xDel ){
- pColl[j].xDel(pColl[j].pUser);
- }
- }
- sqlite3DbFree(db, pColl);
- }
- sqlite3HashClear(&db->aCollSeq);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
- Module *pMod = (Module *)sqliteHashData(i);
- if( pMod->xDestroy ){
- pMod->xDestroy(pMod->pAux);
- }
- sqlite3VtabEponymousTableClear(db, pMod);
- sqlite3DbFree(db, pMod);
- }
- sqlite3HashClear(&db->aModule);
-#endif
-
- sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
- sqlite3ValueFree(db->pErr);
- sqlite3CloseExtensions(db);
-#if SQLITE_USER_AUTHENTICATION
- sqlite3_free(db->auth.zAuthUser);
- sqlite3_free(db->auth.zAuthPW);
-#endif
-
- db->magic = SQLITE_MAGIC_ERROR;
-
- /* The temp-database schema is allocated differently from the other schema
- ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
- ** So it needs to be freed here. Todo: Why not roll the temp schema into
- ** the same sqliteMalloc() as the one that allocates the database
- ** structure?
- */
- sqlite3DbFree(db, db->aDb[1].pSchema);
- sqlite3_mutex_leave(db->mutex);
- db->magic = SQLITE_MAGIC_CLOSED;
- sqlite3_mutex_free(db->mutex);
- assert( sqlite3LookasideUsed(db,0)==0 );
- if( db->lookaside.bMalloced ){
- sqlite3_free(db->lookaside.pStart);
- }
- sqlite3_free(db);
-}
-
-/*
-** Rollback all database files. If tripCode is not SQLITE_OK, then
-** any write cursors are invalidated ("tripped" - as in "tripping a circuit
-** breaker") and made to return tripCode if there are any further
-** attempts to use that cursor. Read cursors remain open and valid
-** but are "saved" in case the table pages are moved around.
-*/
-void sqlite3RollbackAll(sqlite3 *db, int tripCode){
- int i;
- int inTrans = 0;
- int schemaChange;
- assert( sqlite3_mutex_held(db->mutex) );
- sqlite3BeginBenignMalloc();
-
- /* Obtain all b-tree mutexes before making any calls to BtreeRollback().
- ** This is important in case the transaction being rolled back has
- ** modified the database schema. If the b-tree mutexes are not taken
- ** here, then another shared-cache connection might sneak in between
- ** the database rollback and schema reset, which can cause false
- ** corruption reports in some cases. */
- sqlite3BtreeEnterAll(db);
- schemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0 && db->init.busy==0;
-
- for(i=0; i<db->nDb; i++){
- Btree *p = db->aDb[i].pBt;
- if( p ){
- if( sqlite3BtreeIsInTrans(p) ){
- inTrans = 1;
- }
- sqlite3BtreeRollback(p, tripCode, !schemaChange);
- }
- }
- sqlite3VtabRollback(db);
- sqlite3EndBenignMalloc();
-
- if( (db->mDbFlags&DBFLAG_SchemaChange)!=0 && db->init.busy==0 ){
- sqlite3ExpirePreparedStatements(db);
- sqlite3ResetAllSchemasOfConnection(db);
- }
- sqlite3BtreeLeaveAll(db);
-
- /* Any deferred constraint violations have now been resolved. */
- db->nDeferredCons = 0;
- db->nDeferredImmCons = 0;
- db->flags &= ~SQLITE_DeferFKs;
-
- /* If one has been configured, invoke the rollback-hook callback */
- if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
- db->xRollbackCallback(db->pRollbackArg);
- }
-}
-
-/*
-** Return a static string containing the name corresponding to the error code
-** specified in the argument.
-*/
-#if defined(SQLITE_NEED_ERR_NAME)
-const char *sqlite3ErrName(int rc){
- const char *zName = 0;
- int i, origRc = rc;
- for(i=0; i<2 && zName==0; i++, rc &= 0xff){
- switch( rc ){
- case SQLITE_OK: zName = "SQLITE_OK"; break;
- case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
- case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
- case SQLITE_PERM: zName = "SQLITE_PERM"; break;
- case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
- case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break;
- case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
- case SQLITE_BUSY_RECOVERY: zName = "SQLITE_BUSY_RECOVERY"; break;
- case SQLITE_BUSY_SNAPSHOT: zName = "SQLITE_BUSY_SNAPSHOT"; break;
- case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
- case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
- case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
- case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
- case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break;
- case SQLITE_READONLY_CANTINIT: zName = "SQLITE_READONLY_CANTINIT"; break;
- case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break;
- case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break;
- case SQLITE_READONLY_DIRECTORY: zName = "SQLITE_READONLY_DIRECTORY";break;
- case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
- case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
- case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break;
- case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break;
- case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break;
- case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break;
- case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break;
- case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break;
- case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break;
- case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
- case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
- case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
- case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
- case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
- case SQLITE_IOERR_CHECKRESERVEDLOCK:
- zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
- case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
- case SQLITE_IOERR_CLOSE: zName = "SQLITE_IOERR_CLOSE"; break;
- case SQLITE_IOERR_DIR_CLOSE: zName = "SQLITE_IOERR_DIR_CLOSE"; break;
- case SQLITE_IOERR_SHMOPEN: zName = "SQLITE_IOERR_SHMOPEN"; break;
- case SQLITE_IOERR_SHMSIZE: zName = "SQLITE_IOERR_SHMSIZE"; break;
- case SQLITE_IOERR_SHMLOCK: zName = "SQLITE_IOERR_SHMLOCK"; break;
- case SQLITE_IOERR_SHMMAP: zName = "SQLITE_IOERR_SHMMAP"; break;
- case SQLITE_IOERR_SEEK: zName = "SQLITE_IOERR_SEEK"; break;
- case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break;
- case SQLITE_IOERR_MMAP: zName = "SQLITE_IOERR_MMAP"; break;
- case SQLITE_IOERR_GETTEMPPATH: zName = "SQLITE_IOERR_GETTEMPPATH"; break;
- case SQLITE_IOERR_CONVPATH: zName = "SQLITE_IOERR_CONVPATH"; break;
- case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
- case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break;
- case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
- case SQLITE_FULL: zName = "SQLITE_FULL"; break;
- case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
- case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break;
- case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break;
- case SQLITE_CANTOPEN_FULLPATH: zName = "SQLITE_CANTOPEN_FULLPATH"; break;
- case SQLITE_CANTOPEN_CONVPATH: zName = "SQLITE_CANTOPEN_CONVPATH"; break;
- case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
- case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
- case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
- case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
- case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
- case SQLITE_CONSTRAINT_UNIQUE: zName = "SQLITE_CONSTRAINT_UNIQUE"; break;
- case SQLITE_CONSTRAINT_TRIGGER: zName = "SQLITE_CONSTRAINT_TRIGGER";break;
- case SQLITE_CONSTRAINT_FOREIGNKEY:
- zName = "SQLITE_CONSTRAINT_FOREIGNKEY"; break;
- case SQLITE_CONSTRAINT_CHECK: zName = "SQLITE_CONSTRAINT_CHECK"; break;
- case SQLITE_CONSTRAINT_PRIMARYKEY:
- zName = "SQLITE_CONSTRAINT_PRIMARYKEY"; break;
- case SQLITE_CONSTRAINT_NOTNULL: zName = "SQLITE_CONSTRAINT_NOTNULL";break;
- case SQLITE_CONSTRAINT_COMMITHOOK:
- zName = "SQLITE_CONSTRAINT_COMMITHOOK"; break;
- case SQLITE_CONSTRAINT_VTAB: zName = "SQLITE_CONSTRAINT_VTAB"; break;
- case SQLITE_CONSTRAINT_FUNCTION:
- zName = "SQLITE_CONSTRAINT_FUNCTION"; break;
- case SQLITE_CONSTRAINT_ROWID: zName = "SQLITE_CONSTRAINT_ROWID"; break;
- case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
- case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
- case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
- case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
- case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
- case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
- case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
- case SQLITE_ROW: zName = "SQLITE_ROW"; break;
- case SQLITE_NOTICE: zName = "SQLITE_NOTICE"; break;
- case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break;
- case SQLITE_NOTICE_RECOVER_ROLLBACK:
- zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break;
- case SQLITE_WARNING: zName = "SQLITE_WARNING"; break;
- case SQLITE_WARNING_AUTOINDEX: zName = "SQLITE_WARNING_AUTOINDEX"; break;
- case SQLITE_DONE: zName = "SQLITE_DONE"; break;
- }
- }
- if( zName==0 ){
- static char zBuf[50];
- sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_UNKNOWN(%d)", origRc);
- zName = zBuf;
- }
- return zName;
-}
-#endif
-
-/*
-** Return a static string that describes the kind of error specified in the
-** argument.
-*/
-const char *sqlite3ErrStr(int rc){
- static const char* const aMsg[] = {
- /* SQLITE_OK */ "not an error",
- /* SQLITE_ERROR */ "SQL logic error",
- /* SQLITE_INTERNAL */ 0,
- /* SQLITE_PERM */ "access permission denied",
- /* SQLITE_ABORT */ "query aborted",
- /* SQLITE_BUSY */ "database is locked",
- /* SQLITE_LOCKED */ "database table is locked",
- /* SQLITE_NOMEM */ "out of memory",
- /* SQLITE_READONLY */ "attempt to write a readonly database",
- /* SQLITE_INTERRUPT */ "interrupted",
- /* SQLITE_IOERR */ "disk I/O error",
- /* SQLITE_CORRUPT */ "database disk image is malformed",
- /* SQLITE_NOTFOUND */ "unknown operation",
- /* SQLITE_FULL */ "database or disk is full",
- /* SQLITE_CANTOPEN */ "unable to open database file",
- /* SQLITE_PROTOCOL */ "locking protocol",
- /* SQLITE_EMPTY */ 0,
- /* SQLITE_SCHEMA */ "database schema has changed",
- /* SQLITE_TOOBIG */ "string or blob too big",
- /* SQLITE_CONSTRAINT */ "constraint failed",
- /* SQLITE_MISMATCH */ "datatype mismatch",
- /* SQLITE_MISUSE */ "bad parameter or other API misuse",
-#ifdef SQLITE_DISABLE_LFS
- /* SQLITE_NOLFS */ "large file support is disabled",
-#else
- /* SQLITE_NOLFS */ 0,
-#endif
- /* SQLITE_AUTH */ "authorization denied",
- /* SQLITE_FORMAT */ 0,
- /* SQLITE_RANGE */ "column index out of range",
- /* SQLITE_NOTADB */ "file is not a database",
- /* SQLITE_NOTICE */ "notification message",
- /* SQLITE_WARNING */ "warning message",
- };
- const char *zErr = "unknown error";
- switch( rc ){
- case SQLITE_ABORT_ROLLBACK: {
- zErr = "abort due to ROLLBACK";
- break;
- }
- case SQLITE_ROW: {
- zErr = "another row available";
- break;
- }
- case SQLITE_DONE: {
- zErr = "no more rows available";
- break;
- }
- default: {
- rc &= 0xff;
- if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){
- zErr = aMsg[rc];
- }
- break;
- }
- }
- return zErr;
-}
-
-/*
-** This routine implements a busy callback that sleeps and tries
-** again until a timeout value is reached. The timeout value is
-** an integer number of milliseconds passed in as the first
-** argument.
-**
-** Return non-zero to retry the lock. Return zero to stop trying
-** and cause SQLite to return SQLITE_BUSY.
-*/
-static int sqliteDefaultBusyCallback(
- void *ptr, /* Database connection */
- int count, /* Number of times table has been busy */
- sqlite3_file *pFile /* The file on which the lock occurred */
-){
-#if SQLITE_OS_WIN || HAVE_USLEEP
- /* This case is for systems that have support for sleeping for fractions of
- ** a second. Examples: All windows systems, unix systems with usleep() */
- static const u8 delays[] =
- { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
- static const u8 totals[] =
- { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
-# define NDELAY ArraySize(delays)
- sqlite3 *db = (sqlite3 *)ptr;
- int tmout = db->busyTimeout;
- int delay, prior;
-
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
- if( count ){
- tmout = 0;
- sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
- return 0;
- }else{
- return 1;
- }
- }
-#else
- UNUSED_PARAMETER(pFile);
-#endif
- assert( count>=0 );
- if( count < NDELAY ){
- delay = delays[count];
- prior = totals[count];
- }else{
- delay = delays[NDELAY-1];
- prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
- }
- if( prior + delay > tmout ){
- delay = tmout - prior;
- if( delay<=0 ) return 0;
- }
- sqlite3OsSleep(db->pVfs, delay*1000);
- return 1;
-#else
- /* This case for unix systems that lack usleep() support. Sleeping
- ** must be done in increments of whole seconds */
- sqlite3 *db = (sqlite3 *)ptr;
- int tmout = ((sqlite3 *)ptr)->busyTimeout;
- UNUSED_PARAMETER(pFile);
- if( (count+1)*1000 > tmout ){
- return 0;
- }
- sqlite3OsSleep(db->pVfs, 1000000);
- return 1;
-#endif
-}
-
-/*
-** Invoke the given busy handler.
-**
-** This routine is called when an operation failed to acquire a
-** lock on VFS file pFile.
-**
-** If this routine returns non-zero, the lock is retried. If it
-** returns 0, the operation aborts with an SQLITE_BUSY error.
-*/
-int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
- int rc;
- if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
- if( p->bExtraFileArg ){
- /* Add an extra parameter with the pFile pointer to the end of the
- ** callback argument list */
- int (*xTra)(void*,int,sqlite3_file*);
- xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
- rc = xTra(p->pBusyArg, p->nBusy, pFile);
- }else{
- /* Legacy style busy handler callback */
- rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
- }
- if( rc==0 ){
- p->nBusy = -1;
- }else{
- p->nBusy++;
- }
- return rc;
-}
-
-/*
-** This routine sets the busy callback for an Sqlite database to the
-** given callback function with the given argument.
-*/
-int sqlite3_busy_handler(
- sqlite3 *db,
- int (*xBusy)(void*,int),
- void *pArg
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- db->busyHandler.xBusyHandler = xBusy;
- db->busyHandler.pBusyArg = pArg;
- db->busyHandler.nBusy = 0;
- db->busyHandler.bExtraFileArg = 0;
- db->busyTimeout = 0;
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
-}
-
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
-/*
-** This routine sets the progress callback for an Sqlite database to the
-** given callback function with the given argument. The progress callback will
-** be invoked every nOps opcodes.
-*/
-void sqlite3_progress_handler(
- sqlite3 *db,
- int nOps,
- int (*xProgress)(void*),
- void *pArg
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- if( nOps>0 ){
- db->xProgress = xProgress;
- db->nProgressOps = (unsigned)nOps;
- db->pProgressArg = pArg;
- }else{
- db->xProgress = 0;
- db->nProgressOps = 0;
- db->pProgressArg = 0;
- }
- sqlite3_mutex_leave(db->mutex);
-}
-#endif
-
-
-/*
-** This routine installs a default busy handler that waits for the
-** specified number of milliseconds before returning 0.
-*/
-int sqlite3_busy_timeout(sqlite3 *db, int ms){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- if( ms>0 ){
- sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
- (void*)db);
- db->busyTimeout = ms;
- db->busyHandler.bExtraFileArg = 1;
- }else{
- sqlite3_busy_handler(db, 0, 0);
- }
- return SQLITE_OK;
-}
-
-/*
-** Cause any pending operation to stop at its earliest opportunity.
-*/
-void sqlite3_interrupt(sqlite3 *db){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){
- (void)SQLITE_MISUSE_BKPT;
- return;
- }
-#endif
- db->u1.isInterrupted = 1;
-}
-
-
-/*
-** This function is exactly the same as sqlite3_create_function(), except
-** that it is designed to be called by internal code. The difference is
-** that if a malloc() fails in sqlite3_create_function(), an error code
-** is returned and the mallocFailed flag cleared.
-*/
-int sqlite3CreateFunc(
- sqlite3 *db,
- const char *zFunctionName,
- int nArg,
- int enc,
- void *pUserData,
- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **),
- void (*xStep)(sqlite3_context*,int,sqlite3_value **),
- void (*xFinal)(sqlite3_context*),
- FuncDestructor *pDestructor
-){
- FuncDef *p;
- int nName;
- int extraFlags;
-
- assert( sqlite3_mutex_held(db->mutex) );
- if( zFunctionName==0 ||
- (xSFunc && (xFinal || xStep)) ||
- (!xSFunc && (xFinal && !xStep)) ||
- (!xSFunc && (!xFinal && xStep)) ||
- (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
- (255<(nName = sqlite3Strlen30( zFunctionName))) ){
- return SQLITE_MISUSE_BKPT;
- }
-
- assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
- extraFlags = enc & SQLITE_DETERMINISTIC;
- enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
-
-#ifndef SQLITE_OMIT_UTF16
- /* If SQLITE_UTF16 is specified as the encoding type, transform this
- ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
- ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
- **
- ** If SQLITE_ANY is specified, add three versions of the function
- ** to the hash table.
- */
- if( enc==SQLITE_UTF16 ){
- enc = SQLITE_UTF16NATIVE;
- }else if( enc==SQLITE_ANY ){
- int rc;
- rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags,
- pUserData, xSFunc, xStep, xFinal, pDestructor);
- if( rc==SQLITE_OK ){
- rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags,
- pUserData, xSFunc, xStep, xFinal, pDestructor);
- }
- if( rc!=SQLITE_OK ){
- return rc;
- }
- enc = SQLITE_UTF16BE;
- }
-#else
- enc = SQLITE_UTF8;
-#endif
-
- /* Check if an existing function is being overridden or deleted. If so,
- ** and there are active VMs, then return SQLITE_BUSY. If a function
- ** is being overridden/deleted but there are no active VMs, allow the
- ** operation to continue but invalidate all precompiled statements.
- */
- p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0);
- if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){
- if( db->nVdbeActive ){
- sqlite3ErrorWithMsg(db, SQLITE_BUSY,
- "unable to delete/modify user-function due to active statements");
- assert( !db->mallocFailed );
- return SQLITE_BUSY;
- }else{
- sqlite3ExpirePreparedStatements(db);
- }
- }
-
- p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
- assert(p || db->mallocFailed);
- if( !p ){
- return SQLITE_NOMEM_BKPT;
- }
-
- /* If an older version of the function with a configured destructor is
- ** being replaced invoke the destructor function here. */
- functionDestroy(db, p);
-
- if( pDestructor ){
- pDestructor->nRef++;
- }
- p->u.pDestructor = pDestructor;
- p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
- testcase( p->funcFlags & SQLITE_DETERMINISTIC );
- p->xSFunc = xSFunc ? xSFunc : xStep;
- p->xFinalize = xFinal;
- p->pUserData = pUserData;
- p->nArg = (u16)nArg;
- return SQLITE_OK;
-}
-
-/*
-** Create new user functions.
-*/
-int sqlite3_create_function(
- sqlite3 *db,
- const char *zFunc,
- int nArg,
- int enc,
- void *p,
- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **),
- void (*xStep)(sqlite3_context*,int,sqlite3_value **),
- void (*xFinal)(sqlite3_context*)
-){
- return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xSFunc, xStep,
- xFinal, 0);
-}
-
-int sqlite3_create_function_v2(
- sqlite3 *db,
- const char *zFunc,
- int nArg,
- int enc,
- void *p,
- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **),
- void (*xStep)(sqlite3_context*,int,sqlite3_value **),
- void (*xFinal)(sqlite3_context*),
- void (*xDestroy)(void *)
-){
- int rc = SQLITE_ERROR;
- FuncDestructor *pArg = 0;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- if( xDestroy ){
- pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor));
- if( !pArg ){
- sqlite3OomFault(db);
- xDestroy(p);
- goto out;
- }
- pArg->nRef = 0;
- pArg->xDestroy = xDestroy;
- pArg->pUserData = p;
- }
- rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, pArg);
- if( pArg && pArg->nRef==0 ){
- assert( rc!=SQLITE_OK );
- xDestroy(p);
- sqlite3_free(pArg);
- }
-
- out:
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-#ifndef SQLITE_OMIT_UTF16
-int sqlite3_create_function16(
- sqlite3 *db,
- const void *zFunctionName,
- int nArg,
- int eTextRep,
- void *p,
- void (*xSFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*)
-){
- int rc;
- char *zFunc8;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zFunctionName==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- assert( !db->mallocFailed );
- zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE);
- rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0);
- sqlite3DbFree(db, zFunc8);
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-#endif
-
-
-/*
-** The following is the implementation of an SQL function that always
-** fails with an error message stating that the function is used in the
-** wrong context. The sqlite3_overload_function() API might construct
-** SQL function that use this routine so that the functions will exist
-** for name resolution but are actually overloaded by the xFindFunction
-** method of virtual tables.
-*/
-static void sqlite3InvalidFunction(
- sqlite3_context *context, /* The function calling context */
- int NotUsed, /* Number of arguments to the function */
- sqlite3_value **NotUsed2 /* Value of each argument */
-){
- const char *zName = (const char*)sqlite3_user_data(context);
- char *zErr;
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- zErr = sqlite3_mprintf(
- "unable to use function %s in the requested context", zName);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
-}
-
-/*
-** Declare that a function has been overloaded by a virtual table.
-**
-** If the function already exists as a regular global function, then
-** this routine is a no-op. If the function does not exist, then create
-** a new one that always throws a run-time error.
-**
-** When virtual tables intend to provide an overloaded function, they
-** should call this routine to make sure the global function exists.
-** A global function must exist in order for name resolution to work
-** properly.
-*/
-int sqlite3_overload_function(
- sqlite3 *db,
- const char *zName,
- int nArg
-){
- int rc;
- char *zCopy;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0;
- sqlite3_mutex_leave(db->mutex);
- if( rc ) return SQLITE_OK;
- zCopy = sqlite3_mprintf(zName);
- if( zCopy==0 ) return SQLITE_NOMEM;
- return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8,
- zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free);
-}
-
-#ifndef SQLITE_OMIT_TRACE
-/*
-** Register a trace function. The pArg from the previously registered trace
-** is returned.
-**
-** A NULL trace function means that no tracing is executes. A non-NULL
-** trace is a pointer to a function that is invoked at the start of each
-** SQL statement.
-*/
-#ifndef SQLITE_OMIT_DEPRECATED
-void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){
- void *pOld;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- pOld = db->pTraceArg;
- db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0;
- db->xTrace = (int(*)(u32,void*,void*,void*))xTrace;
- db->pTraceArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return pOld;
-}
-#endif /* SQLITE_OMIT_DEPRECATED */
-
-/* Register a trace callback using the version-2 interface.
-*/
-int sqlite3_trace_v2(
- sqlite3 *db, /* Trace this connection */
- unsigned mTrace, /* Mask of events to be traced */
- int(*xTrace)(unsigned,void*,void*,void*), /* Callback to invoke */
- void *pArg /* Context */
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- if( mTrace==0 ) xTrace = 0;
- if( xTrace==0 ) mTrace = 0;
- db->mTrace = mTrace;
- db->xTrace = xTrace;
- db->pTraceArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
-}
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** Register a profile function. The pArg from the previously registered
-** profile function is returned.
-**
-** A NULL profile function means that no profiling is executes. A non-NULL
-** profile is a pointer to a function that is invoked at the conclusion of
-** each SQL statement that is run.
-*/
-void *sqlite3_profile(
- sqlite3 *db,
- void (*xProfile)(void*,const char*,sqlite_uint64),
- void *pArg
-){
- void *pOld;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- pOld = db->pProfileArg;
- db->xProfile = xProfile;
- db->pProfileArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return pOld;
-}
-#endif /* SQLITE_OMIT_DEPRECATED */
-#endif /* SQLITE_OMIT_TRACE */
-
-/*
-** Register a function to be invoked when a transaction commits.
-** If the invoked function returns non-zero, then the commit becomes a
-** rollback.
-*/
-void *sqlite3_commit_hook(
- sqlite3 *db, /* Attach the hook to this database */
- int (*xCallback)(void*), /* Function to invoke on each commit */
- void *pArg /* Argument to the function */
-){
- void *pOld;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- pOld = db->pCommitArg;
- db->xCommitCallback = xCallback;
- db->pCommitArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return pOld;
-}
-
-/*
-** Register a callback to be invoked each time a row is updated,
-** inserted or deleted using this database connection.
-*/
-void *sqlite3_update_hook(
- sqlite3 *db, /* Attach the hook to this database */
- void (*xCallback)(void*,int,char const *,char const *,sqlite_int64),
- void *pArg /* Argument to the function */
-){
- void *pRet;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- pRet = db->pUpdateArg;
- db->xUpdateCallback = xCallback;
- db->pUpdateArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return pRet;
-}
-
-/*
-** Register a callback to be invoked each time a transaction is rolled
-** back by this database connection.
-*/
-void *sqlite3_rollback_hook(
- sqlite3 *db, /* Attach the hook to this database */
- void (*xCallback)(void*), /* Callback function */
- void *pArg /* Argument to the function */
-){
- void *pRet;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- pRet = db->pRollbackArg;
- db->xRollbackCallback = xCallback;
- db->pRollbackArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return pRet;
-}
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-/*
-** Register a callback to be invoked each time a row is updated,
-** inserted or deleted using this database connection.
-*/
-void *sqlite3_preupdate_hook(
- sqlite3 *db, /* Attach the hook to this database */
- void(*xCallback)( /* Callback function */
- void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64),
- void *pArg /* First callback argument */
-){
- void *pRet;
- sqlite3_mutex_enter(db->mutex);
- pRet = db->pPreUpdateArg;
- db->xPreUpdateCallback = xCallback;
- db->pPreUpdateArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return pRet;
-}
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
-
-#ifndef SQLITE_OMIT_WAL
-/*
-** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
-** Invoke sqlite3_wal_checkpoint if the number of frames in the log file
-** is greater than sqlite3.pWalArg cast to an integer (the value configured by
-** wal_autocheckpoint()).
-*/
-int sqlite3WalDefaultHook(
- void *pClientData, /* Argument */
- sqlite3 *db, /* Connection */
- const char *zDb, /* Database */
- int nFrame /* Size of WAL */
-){
- if( nFrame>=SQLITE_PTR_TO_INT(pClientData) ){
- sqlite3BeginBenignMalloc();
- sqlite3_wal_checkpoint(db, zDb);
- sqlite3EndBenignMalloc();
- }
- return SQLITE_OK;
-}
-#endif /* SQLITE_OMIT_WAL */
-
-/*
-** Configure an sqlite3_wal_hook() callback to automatically checkpoint
-** a database after committing a transaction if there are nFrame or
-** more frames in the log file. Passing zero or a negative value as the
-** nFrame parameter disables automatic checkpoints entirely.
-**
-** The callback registered by this function replaces any existing callback
-** registered using sqlite3_wal_hook(). Likewise, registering a callback
-** using sqlite3_wal_hook() disables the automatic checkpoint mechanism
-** configured by this function.
-*/
-int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){
-#ifdef SQLITE_OMIT_WAL
- UNUSED_PARAMETER(db);
- UNUSED_PARAMETER(nFrame);
-#else
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- if( nFrame>0 ){
- sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame));
- }else{
- sqlite3_wal_hook(db, 0, 0);
- }
-#endif
- return SQLITE_OK;
-}
-
-/*
-** Register a callback to be invoked each time a transaction is written
-** into the write-ahead-log by this database connection.
-*/
-void *sqlite3_wal_hook(
- sqlite3 *db, /* Attach the hook to this db handle */
- int(*xCallback)(void *, sqlite3*, const char*, int),
- void *pArg /* First argument passed to xCallback() */
-){
-#ifndef SQLITE_OMIT_WAL
- void *pRet;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- pRet = db->pWalArg;
- db->xWalCallback = xCallback;
- db->pWalArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return pRet;
-#else
- return 0;
-#endif
-}
-
-/*
-** Checkpoint database zDb.
-*/
-int sqlite3_wal_checkpoint_v2(
- sqlite3 *db, /* Database handle */
- const char *zDb, /* Name of attached database (or NULL) */
- int eMode, /* SQLITE_CHECKPOINT_* value */
- int *pnLog, /* OUT: Size of WAL log in frames */
- int *pnCkpt /* OUT: Total number of frames checkpointed */
-){
-#ifdef SQLITE_OMIT_WAL
- return SQLITE_OK;
-#else
- int rc; /* Return code */
- int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
-
- /* Initialize the output variables to -1 in case an error occurs. */
- if( pnLog ) *pnLog = -1;
- if( pnCkpt ) *pnCkpt = -1;
-
- assert( SQLITE_CHECKPOINT_PASSIVE==0 );
- assert( SQLITE_CHECKPOINT_FULL==1 );
- assert( SQLITE_CHECKPOINT_RESTART==2 );
- assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
- if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_TRUNCATE ){
- /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint
- ** mode: */
- return SQLITE_MISUSE;
- }
-
- sqlite3_mutex_enter(db->mutex);
- if( zDb && zDb[0] ){
- iDb = sqlite3FindDbName(db, zDb);
- }
- if( iDb<0 ){
- rc = SQLITE_ERROR;
- sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb);
- }else{
- db->busyHandler.nBusy = 0;
- rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
- sqlite3Error(db, rc);
- }
- rc = sqlite3ApiExit(db, rc);
-
- /* If there are no active statements, clear the interrupt flag at this
- ** point. */
- if( db->nVdbeActive==0 ){
- db->u1.isInterrupted = 0;
- }
-
- sqlite3_mutex_leave(db->mutex);
- return rc;
-#endif
-}
-
-
-/*
-** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points
-** to contains a zero-length string, all attached databases are
-** checkpointed.
-*/
-int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
- /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to
- ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */
- return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0);
-}
-
-#ifndef SQLITE_OMIT_WAL
-/*
-** Run a checkpoint on database iDb. This is a no-op if database iDb is
-** not currently open in WAL mode.
-**
-** If a transaction is open on the database being checkpointed, this
-** function returns SQLITE_LOCKED and a checkpoint is not attempted. If
-** an error occurs while running the checkpoint, an SQLite error code is
-** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK.
-**
-** The mutex on database handle db should be held by the caller. The mutex
-** associated with the specific b-tree being checkpointed is taken by
-** this function while the checkpoint is running.
-**
-** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are
-** checkpointed. If an error is encountered it is returned immediately -
-** no attempt is made to checkpoint any remaining databases.
-**
-** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART
-** or TRUNCATE.
-*/
-int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){
- int rc = SQLITE_OK; /* Return code */
- int i; /* Used to iterate through attached dbs */
- int bBusy = 0; /* True if SQLITE_BUSY has been encountered */
-
- assert( sqlite3_mutex_held(db->mutex) );
- assert( !pnLog || *pnLog==-1 );
- assert( !pnCkpt || *pnCkpt==-1 );
-
- for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
- if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
- rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt);
- pnLog = 0;
- pnCkpt = 0;
- if( rc==SQLITE_BUSY ){
- bBusy = 1;
- rc = SQLITE_OK;
- }
- }
- }
-
- return (rc==SQLITE_OK && bBusy) ? SQLITE_BUSY : rc;
-}
-#endif /* SQLITE_OMIT_WAL */
-
-/*
-** This function returns true if main-memory should be used instead of
-** a temporary file for transient pager files and statement journals.
-** The value returned depends on the value of db->temp_store (runtime
-** parameter) and the compile time value of SQLITE_TEMP_STORE. The
-** following table describes the relationship between these two values
-** and this functions return value.
-**
-** SQLITE_TEMP_STORE db->temp_store Location of temporary database
-** ----------------- -------------- ------------------------------
-** 0 any file (return 0)
-** 1 1 file (return 0)
-** 1 2 memory (return 1)
-** 1 0 file (return 0)
-** 2 1 file (return 0)
-** 2 2 memory (return 1)
-** 2 0 memory (return 1)
-** 3 any memory (return 1)
-*/
-int sqlite3TempInMemory(const sqlite3 *db){
-#if SQLITE_TEMP_STORE==1
- return ( db->temp_store==2 );
-#endif
-#if SQLITE_TEMP_STORE==2
- return ( db->temp_store!=1 );
-#endif
-#if SQLITE_TEMP_STORE==3
- UNUSED_PARAMETER(db);
- return 1;
-#endif
-#if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3
- UNUSED_PARAMETER(db);
- return 0;
-#endif
-}
-
-/*
-** Return UTF-8 encoded English language explanation of the most recent
-** error.
-*/
-const char *sqlite3_errmsg(sqlite3 *db){
- const char *z;
- if( !db ){
- return sqlite3ErrStr(SQLITE_NOMEM_BKPT);
- }
- if( !sqlite3SafetyCheckSickOrOk(db) ){
- return sqlite3ErrStr(SQLITE_MISUSE_BKPT);
- }
- sqlite3_mutex_enter(db->mutex);
- if( db->mallocFailed ){
- z = sqlite3ErrStr(SQLITE_NOMEM_BKPT);
- }else{
- testcase( db->pErr==0 );
- z = (char*)sqlite3_value_text(db->pErr);
- assert( !db->mallocFailed );
- if( z==0 ){
- z = sqlite3ErrStr(db->errCode);
- }
- }
- sqlite3_mutex_leave(db->mutex);
- return z;
-}
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** Return UTF-16 encoded English language explanation of the most recent
-** error.
-*/
-const void *sqlite3_errmsg16(sqlite3 *db){
- static const u16 outOfMem[] = {
- 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0
- };
- static const u16 misuse[] = {
- 'b', 'a', 'd', ' ', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', ' ',
- 'o', 'r', ' ', 'o', 't', 'h', 'e', 'r', ' ', 'A', 'P', 'I', ' ',
- 'm', 'i', 's', 'u', 's', 'e', 0
- };
-
- const void *z;
- if( !db ){
- return (void *)outOfMem;
- }
- if( !sqlite3SafetyCheckSickOrOk(db) ){
- return (void *)misuse;
- }
- sqlite3_mutex_enter(db->mutex);
- if( db->mallocFailed ){
- z = (void *)outOfMem;
- }else{
- z = sqlite3_value_text16(db->pErr);
- if( z==0 ){
- sqlite3ErrorWithMsg(db, db->errCode, sqlite3ErrStr(db->errCode));
- z = sqlite3_value_text16(db->pErr);
- }
- /* A malloc() may have failed within the call to sqlite3_value_text16()
- ** above. If this is the case, then the db->mallocFailed flag needs to
- ** be cleared before returning. Do this directly, instead of via
- ** sqlite3ApiExit(), to avoid setting the database handle error message.
- */
- sqlite3OomClear(db);
- }
- sqlite3_mutex_leave(db->mutex);
- return z;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-
-/*
-** Return the most recent error code generated by an SQLite routine. If NULL is
-** passed to this function, we assume a malloc() failed during sqlite3_open().
-*/
-int sqlite3_errcode(sqlite3 *db){
- if( db && !sqlite3SafetyCheckSickOrOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
- if( !db || db->mallocFailed ){
- return SQLITE_NOMEM_BKPT;
- }
- return db->errCode & db->errMask;
-}
-int sqlite3_extended_errcode(sqlite3 *db){
- if( db && !sqlite3SafetyCheckSickOrOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
- if( !db || db->mallocFailed ){
- return SQLITE_NOMEM_BKPT;
- }
- return db->errCode;
-}
-int sqlite3_system_errno(sqlite3 *db){
- return db ? db->iSysErrno : 0;
-}
-
-/*
-** Return a string that describes the kind of error specified in the
-** argument. For now, this simply calls the internal sqlite3ErrStr()
-** function.
-*/
-const char *sqlite3_errstr(int rc){
- return sqlite3ErrStr(rc);
-}
-
-/*
-** Create a new collating function for database "db". The name is zName
-** and the encoding is enc.
-*/
-static int createCollation(
- sqlite3* db,
- const char *zName,
- u8 enc,
- void* pCtx,
- int(*xCompare)(void*,int,const void*,int,const void*),
- void(*xDel)(void*)
-){
- CollSeq *pColl;
- int enc2;
-
- assert( sqlite3_mutex_held(db->mutex) );
-
- /* If SQLITE_UTF16 is specified as the encoding type, transform this
- ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
- ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
- */
- enc2 = enc;
- testcase( enc2==SQLITE_UTF16 );
- testcase( enc2==SQLITE_UTF16_ALIGNED );
- if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){
- enc2 = SQLITE_UTF16NATIVE;
- }
- if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){
- return SQLITE_MISUSE_BKPT;
- }
-
- /* Check if this call is removing or replacing an existing collation
- ** sequence. If so, and there are active VMs, return busy. If there
- ** are no active VMs, invalidate any pre-compiled statements.
- */
- pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
- if( pColl && pColl->xCmp ){
- if( db->nVdbeActive ){
- sqlite3ErrorWithMsg(db, SQLITE_BUSY,
- "unable to delete/modify collation sequence due to active statements");
- return SQLITE_BUSY;
- }
- sqlite3ExpirePreparedStatements(db);
-
- /* If collation sequence pColl was created directly by a call to
- ** sqlite3_create_collation, and not generated by synthCollSeq(),
- ** then any copies made by synthCollSeq() need to be invalidated.
- ** Also, collation destructor - CollSeq.xDel() - function may need
- ** to be called.
- */
- if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){
- CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName);
- int j;
- for(j=0; j<3; j++){
- CollSeq *p = &aColl[j];
- if( p->enc==pColl->enc ){
- if( p->xDel ){
- p->xDel(p->pUser);
- }
- p->xCmp = 0;
- }
- }
- }
- }
-
- pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1);
- if( pColl==0 ) return SQLITE_NOMEM_BKPT;
- pColl->xCmp = xCompare;
- pColl->pUser = pCtx;
- pColl->xDel = xDel;
- pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED));
- sqlite3Error(db, SQLITE_OK);
- return SQLITE_OK;
-}
-
-
-/*
-** This array defines hard upper bounds on limit values. The
-** initializer must be kept in sync with the SQLITE_LIMIT_*
-** #defines in sqlite3.h.
-*/
-static const int aHardLimit[] = {
- SQLITE_MAX_LENGTH,
- SQLITE_MAX_SQL_LENGTH,
- SQLITE_MAX_COLUMN,
- SQLITE_MAX_EXPR_DEPTH,
- SQLITE_MAX_COMPOUND_SELECT,
- SQLITE_MAX_VDBE_OP,
- SQLITE_MAX_FUNCTION_ARG,
- SQLITE_MAX_ATTACHED,
- SQLITE_MAX_LIKE_PATTERN_LENGTH,
- SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */
- SQLITE_MAX_TRIGGER_DEPTH,
- SQLITE_MAX_WORKER_THREADS,
-};
-
-/*
-** Make sure the hard limits are set to reasonable values
-*/
-#if SQLITE_MAX_LENGTH<100
-# error SQLITE_MAX_LENGTH must be at least 100
-#endif
-#if SQLITE_MAX_SQL_LENGTH<100
-# error SQLITE_MAX_SQL_LENGTH must be at least 100
-#endif
-#if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH
-# error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH
-#endif
-#if SQLITE_MAX_COMPOUND_SELECT<2
-# error SQLITE_MAX_COMPOUND_SELECT must be at least 2
-#endif
-#if SQLITE_MAX_VDBE_OP<40
-# error SQLITE_MAX_VDBE_OP must be at least 40
-#endif
-#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127
-# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127
-#endif
-#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125
-# error SQLITE_MAX_ATTACHED must be between 0 and 125
-#endif
-#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
-# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
-#endif
-#if SQLITE_MAX_COLUMN>32767
-# error SQLITE_MAX_COLUMN must not exceed 32767
-#endif
-#if SQLITE_MAX_TRIGGER_DEPTH<1
-# error SQLITE_MAX_TRIGGER_DEPTH must be at least 1
-#endif
-#if SQLITE_MAX_WORKER_THREADS<0 || SQLITE_MAX_WORKER_THREADS>50
-# error SQLITE_MAX_WORKER_THREADS must be between 0 and 50
-#endif
-
-
-/*
-** Change the value of a limit. Report the old value.
-** If an invalid limit index is supplied, report -1.
-** Make no changes but still report the old value if the
-** new limit is negative.
-**
-** A new lower limit does not shrink existing constructs.
-** It merely prevents new constructs that exceed the limit
-** from forming.
-*/
-int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
- int oldLimit;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return -1;
- }
-#endif
-
- /* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME
- ** there is a hard upper bound set at compile-time by a C preprocessor
- ** macro called SQLITE_MAX_NAME. (The "_LIMIT_" in the name is changed to
- ** "_MAX_".)
- */
- assert( aHardLimit[SQLITE_LIMIT_LENGTH]==SQLITE_MAX_LENGTH );
- assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH );
- assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN );
- assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH );
- assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT);
- assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP );
- assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG );
- assert( aHardLimit[SQLITE_LIMIT_ATTACHED]==SQLITE_MAX_ATTACHED );
- assert( aHardLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]==
- SQLITE_MAX_LIKE_PATTERN_LENGTH );
- assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER);
- assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH );
- assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS );
- assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) );
-
-
- if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
- return -1;
- }
- oldLimit = db->aLimit[limitId];
- if( newLimit>=0 ){ /* IMP: R-52476-28732 */
- if( newLimit>aHardLimit[limitId] ){
- newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
- }
- db->aLimit[limitId] = newLimit;
- }
- return oldLimit; /* IMP: R-53341-35419 */
-}
-
-/*
-** This function is used to parse both URIs and non-URI filenames passed by the
-** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
-** URIs specified as part of ATTACH statements.
-**
-** The first argument to this function is the name of the VFS to use (or
-** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
-** query parameter. The second argument contains the URI (or non-URI filename)
-** itself. When this function is called the *pFlags variable should contain
-** the default flags to open the database handle with. The value stored in
-** *pFlags may be updated before returning if the URI filename contains
-** "cache=xxx" or "mode=xxx" query parameters.
-**
-** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
-** the VFS that should be used to open the database file. *pzFile is set to
-** point to a buffer containing the name of the file to open. It is the
-** responsibility of the caller to eventually call sqlite3_free() to release
-** this buffer.
-**
-** If an error occurs, then an SQLite error code is returned and *pzErrMsg
-** may be set to point to a buffer containing an English language error
-** message. It is the responsibility of the caller to eventually release
-** this buffer by calling sqlite3_free().
-*/
-int sqlite3ParseUri(
- const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
- const char *zUri, /* Nul-terminated URI to parse */
- unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */
- sqlite3_vfs **ppVfs, /* OUT: VFS to use */
- char **pzFile, /* OUT: Filename component of URI */
- char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
-){
- int rc = SQLITE_OK;
- unsigned int flags = *pFlags;
- const char *zVfs = zDefaultVfs;
- char *zFile;
- char c;
- int nUri = sqlite3Strlen30(zUri);
-
- assert( *pzErrMsg==0 );
-
- if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */
- || sqlite3GlobalConfig.bOpenUri) /* IMP: R-51689-46548 */
- && nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */
- ){
- char *zOpt;
- int eState; /* Parser state when parsing URI */
- int iIn; /* Input character index */
- int iOut = 0; /* Output character index */
- u64 nByte = nUri+2; /* Bytes of space to allocate */
-
- /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
- ** method that there may be extra parameters following the file-name. */
- flags |= SQLITE_OPEN_URI;
-
- for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
- zFile = sqlite3_malloc64(nByte);
- if( !zFile ) return SQLITE_NOMEM_BKPT;
-
- iIn = 5;
-#ifdef SQLITE_ALLOW_URI_AUTHORITY
- if( strncmp(zUri+5, "///", 3)==0 ){
- iIn = 7;
- /* The following condition causes URIs with five leading / characters
- ** like file://///host/path to be converted into UNCs like //host/path.
- ** The correct URI for that UNC has only two or four leading / characters
- ** file://host/path or file:////host/path. But 5 leading slashes is a
- ** common error, we are told, so we handle it as a special case. */
- if( strncmp(zUri+7, "///", 3)==0 ){ iIn++; }
- }else if( strncmp(zUri+5, "//localhost/", 12)==0 ){
- iIn = 16;
- }
-#else
- /* Discard the scheme and authority segments of the URI. */
- if( zUri[5]=='/' && zUri[6]=='/' ){
- iIn = 7;
- while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
- if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
- *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
- iIn-7, &zUri[7]);
- rc = SQLITE_ERROR;
- goto parse_uri_out;
- }
- }
-#endif
-
- /* Copy the filename and any query parameters into the zFile buffer.
- ** Decode %HH escape codes along the way.
- **
- ** Within this loop, variable eState may be set to 0, 1 or 2, depending
- ** on the parsing context. As follows:
- **
- ** 0: Parsing file-name.
- ** 1: Parsing name section of a name=value query parameter.
- ** 2: Parsing value section of a name=value query parameter.
- */
- eState = 0;
- while( (c = zUri[iIn])!=0 && c!='#' ){
- iIn++;
- if( c=='%'
- && sqlite3Isxdigit(zUri[iIn])
- && sqlite3Isxdigit(zUri[iIn+1])
- ){
- int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
- octet += sqlite3HexToInt(zUri[iIn++]);
-
- assert( octet>=0 && octet<256 );
- if( octet==0 ){
-#ifndef SQLITE_ENABLE_URI_00_ERROR
- /* This branch is taken when "%00" appears within the URI. In this
- ** case we ignore all text in the remainder of the path, name or
- ** value currently being parsed. So ignore the current character
- ** and skip to the next "?", "=" or "&", as appropriate. */
- while( (c = zUri[iIn])!=0 && c!='#'
- && (eState!=0 || c!='?')
- && (eState!=1 || (c!='=' && c!='&'))
- && (eState!=2 || c!='&')
- ){
- iIn++;
- }
- continue;
-#else
- /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */
- *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri");
- rc = SQLITE_ERROR;
- goto parse_uri_out;
-#endif
- }
- c = octet;
- }else if( eState==1 && (c=='&' || c=='=') ){
- if( zFile[iOut-1]==0 ){
- /* An empty option name. Ignore this option altogether. */
- while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
- continue;
- }
- if( c=='&' ){
- zFile[iOut++] = '\0';
- }else{
- eState = 2;
- }
- c = 0;
- }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
- c = 0;
- eState = 1;
- }
- zFile[iOut++] = c;
- }
- if( eState==1 ) zFile[iOut++] = '\0';
- zFile[iOut++] = '\0';
- zFile[iOut++] = '\0';
-
- /* Check if there were any options specified that should be interpreted
- ** here. Options that are interpreted here include "vfs" and those that
- ** correspond to flags that may be passed to the sqlite3_open_v2()
- ** method. */
- zOpt = &zFile[sqlite3Strlen30(zFile)+1];
- while( zOpt[0] ){
- int nOpt = sqlite3Strlen30(zOpt);
- char *zVal = &zOpt[nOpt+1];
- int nVal = sqlite3Strlen30(zVal);
-
- if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
- zVfs = zVal;
- }else{
- struct OpenMode {
- const char *z;
- int mode;
- } *aMode = 0;
- char *zModeType = 0;
- int mask = 0;
- int limit = 0;
-
- if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
- static struct OpenMode aCacheMode[] = {
- { "shared", SQLITE_OPEN_SHAREDCACHE },
- { "private", SQLITE_OPEN_PRIVATECACHE },
- { 0, 0 }
- };
-
- mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
- aMode = aCacheMode;
- limit = mask;
- zModeType = "cache";
- }
- if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
- static struct OpenMode aOpenMode[] = {
- { "ro", SQLITE_OPEN_READONLY },
- { "rw", SQLITE_OPEN_READWRITE },
- { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
- { "memory", SQLITE_OPEN_MEMORY },
- { 0, 0 }
- };
-
- mask = SQLITE_OPEN_READONLY | SQLITE_OPEN_READWRITE
- | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY;
- aMode = aOpenMode;
- limit = mask & flags;
- zModeType = "access";
- }
-
- if( aMode ){
- int i;
- int mode = 0;
- for(i=0; aMode[i].z; i++){
- const char *z = aMode[i].z;
- if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
- mode = aMode[i].mode;
- break;
- }
- }
- if( mode==0 ){
- *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
- rc = SQLITE_ERROR;
- goto parse_uri_out;
- }
- if( (mode & ~SQLITE_OPEN_MEMORY)>limit ){
- *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
- zModeType, zVal);
- rc = SQLITE_PERM;
- goto parse_uri_out;
- }
- flags = (flags & ~mask) | mode;
- }
- }
-
- zOpt = &zVal[nVal+1];
- }
-
- }else{
- zFile = sqlite3_malloc64(nUri+2);
- if( !zFile ) return SQLITE_NOMEM_BKPT;
- if( nUri ){
- memcpy(zFile, zUri, nUri);
- }
- zFile[nUri] = '\0';
- zFile[nUri+1] = '\0';
- flags &= ~SQLITE_OPEN_URI;
- }
-
- *ppVfs = sqlite3_vfs_find(zVfs);
- if( *ppVfs==0 ){
- *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
- rc = SQLITE_ERROR;
- }
- parse_uri_out:
- if( rc!=SQLITE_OK ){
- sqlite3_free(zFile);
- zFile = 0;
- }
- *pFlags = flags;
- *pzFile = zFile;
- return rc;
-}
-
-
-/*
-** This routine does the work of opening a database on behalf of
-** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
-** is UTF-8 encoded.
-*/
-static int openDatabase(
- const char *zFilename, /* Database filename UTF-8 encoded */
- sqlite3 **ppDb, /* OUT: Returned database handle */
- unsigned int flags, /* Operational flags */
- const char *zVfs /* Name of the VFS to use */
-){
- sqlite3 *db; /* Store allocated handle here */
- int rc; /* Return code */
- int isThreadsafe; /* True for threadsafe connections */
- char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
- char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- *ppDb = 0;
-#ifndef SQLITE_OMIT_AUTOINIT
- rc = sqlite3_initialize();
- if( rc ) return rc;
-#endif
-
- if( sqlite3GlobalConfig.bCoreMutex==0 ){
- isThreadsafe = 0;
- }else if( flags & SQLITE_OPEN_NOMUTEX ){
- isThreadsafe = 0;
- }else if( flags & SQLITE_OPEN_FULLMUTEX ){
- isThreadsafe = 1;
- }else{
- isThreadsafe = sqlite3GlobalConfig.bFullMutex;
- }
-
- if( flags & SQLITE_OPEN_PRIVATECACHE ){
- flags &= ~SQLITE_OPEN_SHAREDCACHE;
- }else if( sqlite3GlobalConfig.sharedCacheEnabled ){
- flags |= SQLITE_OPEN_SHAREDCACHE;
- }
-
- /* Remove harmful bits from the flags parameter
- **
- ** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were
- ** dealt with in the previous code block. Besides these, the only
- ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY,
- ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
- ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask
- ** off all other flags.
- */
- flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
- SQLITE_OPEN_EXCLUSIVE |
- SQLITE_OPEN_MAIN_DB |
- SQLITE_OPEN_TEMP_DB |
- SQLITE_OPEN_TRANSIENT_DB |
- SQLITE_OPEN_MAIN_JOURNAL |
- SQLITE_OPEN_TEMP_JOURNAL |
- SQLITE_OPEN_SUBJOURNAL |
- SQLITE_OPEN_MASTER_JOURNAL |
- SQLITE_OPEN_NOMUTEX |
- SQLITE_OPEN_FULLMUTEX |
- SQLITE_OPEN_WAL
- );
-
- /* Allocate the sqlite data structure */
- db = sqlite3MallocZero( sizeof(sqlite3) );
- if( db==0 ) goto opendb_out;
- if( isThreadsafe
-#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
- || sqlite3GlobalConfig.bCoreMutex
-#endif
- ){
- db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
- if( db->mutex==0 ){
- sqlite3_free(db);
- db = 0;
- goto opendb_out;
- }
- if( isThreadsafe==0 ){
- sqlite3MutexWarnOnContention(db->mutex);
- }
- }
- sqlite3_mutex_enter(db->mutex);
- db->errMask = 0xff;
- db->nDb = 2;
- db->magic = SQLITE_MAGIC_BUSY;
- db->aDb = db->aDbStatic;
-
- assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
- memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
- db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS;
- db->autoCommit = 1;
- db->nextAutovac = -1;
- db->szMmap = sqlite3GlobalConfig.szMmap;
- db->nextPagesize = 0;
- db->nMaxSorterMmap = 0x7FFFFFFF;
- db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
-#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
- | SQLITE_AutoIndex
-#endif
-#if SQLITE_DEFAULT_CKPTFULLFSYNC
- | SQLITE_CkptFullFSync
-#endif
-#if SQLITE_DEFAULT_FILE_FORMAT<4
- | SQLITE_LegacyFileFmt
-#endif
-#ifdef SQLITE_ENABLE_LOAD_EXTENSION
- | SQLITE_LoadExtension
-#endif
-#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
- | SQLITE_RecTriggers
-#endif
-#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS
- | SQLITE_ForeignKeys
-#endif
-#if defined(SQLITE_REVERSE_UNORDERED_SELECTS)
- | SQLITE_ReverseOrder
-#endif
-#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
- | SQLITE_CellSizeCk
-#endif
-#if defined(SQLITE_ENABLE_FTS3_TOKENIZER)
- | SQLITE_Fts3Tokenizer
-#endif
-#if defined(SQLITE_ENABLE_QPSG)
- | SQLITE_EnableQPSG
-#endif
- ;
- sqlite3HashInit(&db->aCollSeq);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3HashInit(&db->aModule);
-#endif
-
- /* Add the default collation sequence BINARY. BINARY works for both UTF-8
- ** and UTF-16, so add a version for each to avoid any unnecessary
- ** conversions. The only error that can occur here is a malloc() failure.
- **
- ** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating
- ** functions:
- */
- createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0);
- createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0);
- createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0);
- createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
- createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
- if( db->mallocFailed ){
- goto opendb_out;
- }
- /* EVIDENCE-OF: R-08308-17224 The default collating function for all
- ** strings is BINARY.
- */
- db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
- assert( db->pDfltColl!=0 );
-
- /* Parse the filename/URI argument
- **
- ** Only allow sensible combinations of bits in the flags argument.
- ** Throw an error if any non-sense combination is used. If we
- ** do not block illegal combinations here, it could trigger
- ** assert() statements in deeper layers. Sensible combinations
- ** are:
- **
- ** 1: SQLITE_OPEN_READONLY
- ** 2: SQLITE_OPEN_READWRITE
- ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
- */
- db->openFlags = flags;
- assert( SQLITE_OPEN_READONLY == 0x01 );
- assert( SQLITE_OPEN_READWRITE == 0x02 );
- assert( SQLITE_OPEN_CREATE == 0x04 );
- testcase( (1<<(flags&7))==0x02 ); /* READONLY */
- testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
- testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
- if( ((1<<(flags&7)) & 0x46)==0 ){
- rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
- }else{
- rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
- }
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
- sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
- sqlite3_free(zErrMsg);
- goto opendb_out;
- }
-
- /* Open the backend database driver */
- rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
- flags | SQLITE_OPEN_MAIN_DB);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_IOERR_NOMEM ){
- rc = SQLITE_NOMEM_BKPT;
- }
- sqlite3Error(db, rc);
- goto opendb_out;
- }
- sqlite3BtreeEnter(db->aDb[0].pBt);
- db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
- if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db);
- sqlite3BtreeLeave(db->aDb[0].pBt);
- db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
-
- /* The default safety_level for the main database is FULL; for the temp
- ** database it is OFF. This matches the pager layer defaults.
- */
- db->aDb[0].zDbSName = "main";
- db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- db->aDb[1].zDbSName = "temp";
- db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF;
-
- db->magic = SQLITE_MAGIC_OPEN;
- if( db->mallocFailed ){
- goto opendb_out;
- }
-
- /* Register all built-in functions, but do not attempt to read the
- ** database schema yet. This is delayed until the first time the database
- ** is accessed.
- */
- sqlite3Error(db, SQLITE_OK);
- sqlite3RegisterPerConnectionBuiltinFunctions(db);
- rc = sqlite3_errcode(db);
-
-#ifdef SQLITE_ENABLE_FTS5
- /* Register any built-in FTS5 module before loading the automatic
- ** extensions. This allows automatic extensions to register FTS5
- ** tokenizers and auxiliary functions. */
- if( !db->mallocFailed && rc==SQLITE_OK ){
- rc = sqlite3Fts5Init(db);
- }
-#endif
-
- /* Load automatic extensions - extensions that have been registered
- ** using the sqlite3_automatic_extension() API.
- */
- if( rc==SQLITE_OK ){
- sqlite3AutoLoadExtensions(db);
- rc = sqlite3_errcode(db);
- if( rc!=SQLITE_OK ){
- goto opendb_out;
- }
- }
-
-#ifdef SQLITE_ENABLE_FTS1
- if( !db->mallocFailed ){
- extern int sqlite3Fts1Init(sqlite3*);
- rc = sqlite3Fts1Init(db);
- }
-#endif
-
-#ifdef SQLITE_ENABLE_FTS2
- if( !db->mallocFailed && rc==SQLITE_OK ){
- extern int sqlite3Fts2Init(sqlite3*);
- rc = sqlite3Fts2Init(db);
- }
-#endif
-
-#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */
- if( !db->mallocFailed && rc==SQLITE_OK ){
- rc = sqlite3Fts3Init(db);
- }
-#endif
-
-#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
- if( !db->mallocFailed && rc==SQLITE_OK ){
- rc = sqlite3IcuInit(db);
- }
-#endif
-
-#ifdef SQLITE_ENABLE_RTREE
- if( !db->mallocFailed && rc==SQLITE_OK){
- rc = sqlite3RtreeInit(db);
- }
-#endif
-
-#ifdef SQLITE_ENABLE_DBPAGE_VTAB
- if( !db->mallocFailed && rc==SQLITE_OK){
- rc = sqlite3DbpageRegister(db);
- }
-#endif
-
-#ifdef SQLITE_ENABLE_DBSTAT_VTAB
- if( !db->mallocFailed && rc==SQLITE_OK){
- rc = sqlite3DbstatRegister(db);
- }
-#endif
-
-#ifdef SQLITE_ENABLE_JSON1
- if( !db->mallocFailed && rc==SQLITE_OK){
- rc = sqlite3Json1Init(db);
- }
-#endif
-
-#ifdef SQLITE_ENABLE_STMTVTAB
- if( !db->mallocFailed && rc==SQLITE_OK){
- rc = sqlite3StmtVtabInit(db);
- }
-#endif
-
- /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
- ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
- ** mode. Doing nothing at all also makes NORMAL the default.
- */
-#ifdef SQLITE_DEFAULT_LOCKING_MODE
- db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE;
- sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt),
- SQLITE_DEFAULT_LOCKING_MODE);
-#endif
-
- if( rc ) sqlite3Error(db, rc);
-
- /* Enable the lookaside-malloc subsystem */
- setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
- sqlite3GlobalConfig.nLookaside);
-
- sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
-
-opendb_out:
- if( db ){
- assert( db->mutex!=0 || isThreadsafe==0
- || sqlite3GlobalConfig.bFullMutex==0 );
- sqlite3_mutex_leave(db->mutex);
- }
- rc = sqlite3_errcode(db);
- assert( db!=0 || rc==SQLITE_NOMEM );
- if( rc==SQLITE_NOMEM ){
- sqlite3_close(db);
- db = 0;
- }else if( rc!=SQLITE_OK ){
- db->magic = SQLITE_MAGIC_SICK;
- }
- *ppDb = db;
-#ifdef SQLITE_ENABLE_SQLLOG
- if( sqlite3GlobalConfig.xSqllog ){
- /* Opening a db handle. Fourth parameter is passed 0. */
- void *pArg = sqlite3GlobalConfig.pSqllogArg;
- sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
- }
-#endif
-#if defined(SQLITE_HAS_CODEC)
- if( rc==SQLITE_OK ){
- const char *zKey;
- if( (zKey = sqlite3_uri_parameter(zOpen, "hexkey"))!=0 && zKey[0] ){
- u8 iByte;
- int i;
- char zDecoded[40];
- for(i=0, iByte=0; i<sizeof(zDecoded)*2 && sqlite3Isxdigit(zKey[i]); i++){
- iByte = (iByte<<4) + sqlite3HexToInt(zKey[i]);
- if( (i&1)!=0 ) zDecoded[i/2] = iByte;
- }
- sqlite3_key_v2(db, 0, zDecoded, i/2);
- }else if( (zKey = sqlite3_uri_parameter(zOpen, "key"))!=0 ){
- sqlite3_key_v2(db, 0, zKey, sqlite3Strlen30(zKey));
- }
- }
-#endif
- sqlite3_free(zOpen);
- return rc & 0xff;
-}
-
-/*
-** Open a new database handle.
-*/
-int sqlite3_open(
- const char *zFilename,
- sqlite3 **ppDb
-){
- return openDatabase(zFilename, ppDb,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
-}
-int sqlite3_open_v2(
- const char *filename, /* Database filename (UTF-8) */
- sqlite3 **ppDb, /* OUT: SQLite db handle */
- int flags, /* Flags */
- const char *zVfs /* Name of VFS module to use */
-){
- return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
-}
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** Open a new database handle.
-*/
-int sqlite3_open16(
- const void *zFilename,
- sqlite3 **ppDb
-){
- char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */
- sqlite3_value *pVal;
- int rc;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- *ppDb = 0;
-#ifndef SQLITE_OMIT_AUTOINIT
- rc = sqlite3_initialize();
- if( rc ) return rc;
-#endif
- if( zFilename==0 ) zFilename = "\000\000";
- pVal = sqlite3ValueNew(0);
- sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC);
- zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8);
- if( zFilename8 ){
- rc = openDatabase(zFilename8, ppDb,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
- assert( *ppDb || rc==SQLITE_NOMEM );
- if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
- SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE;
- }
- }else{
- rc = SQLITE_NOMEM_BKPT;
- }
- sqlite3ValueFree(pVal);
-
- return rc & 0xff;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-
-/*
-** Register a new collation sequence with the database handle db.
-*/
-int sqlite3_create_collation(
- sqlite3* db,
- const char *zName,
- int enc,
- void* pCtx,
- int(*xCompare)(void*,int,const void*,int,const void*)
-){
- return sqlite3_create_collation_v2(db, zName, enc, pCtx, xCompare, 0);
-}
-
-/*
-** Register a new collation sequence with the database handle db.
-*/
-int sqlite3_create_collation_v2(
- sqlite3* db,
- const char *zName,
- int enc,
- void* pCtx,
- int(*xCompare)(void*,int,const void*,int,const void*),
- void(*xDel)(void*)
-){
- int rc;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- assert( !db->mallocFailed );
- rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, xDel);
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** Register a new collation sequence with the database handle db.
-*/
-int sqlite3_create_collation16(
- sqlite3* db,
- const void *zName,
- int enc,
- void* pCtx,
- int(*xCompare)(void*,int,const void*,int,const void*)
-){
- int rc = SQLITE_OK;
- char *zName8;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- assert( !db->mallocFailed );
- zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE);
- if( zName8 ){
- rc = createCollation(db, zName8, (u8)enc, pCtx, xCompare, 0);
- sqlite3DbFree(db, zName8);
- }
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-
-/*
-** Register a collation sequence factory callback with the database handle
-** db. Replace any previously installed collation sequence factory.
-*/
-int sqlite3_collation_needed(
- sqlite3 *db,
- void *pCollNeededArg,
- void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*)
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- db->xCollNeeded = xCollNeeded;
- db->xCollNeeded16 = 0;
- db->pCollNeededArg = pCollNeededArg;
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
-}
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** Register a collation sequence factory callback with the database handle
-** db. Replace any previously installed collation sequence factory.
-*/
-int sqlite3_collation_needed16(
- sqlite3 *db,
- void *pCollNeededArg,
- void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*)
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- db->xCollNeeded = 0;
- db->xCollNeeded16 = xCollNeeded16;
- db->pCollNeededArg = pCollNeededArg;
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** This function is now an anachronism. It used to be used to recover from a
-** malloc() failure, but SQLite now does this automatically.
-*/
-int sqlite3_global_recover(void){
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Test to see whether or not the database connection is in autocommit
-** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on
-** by default. Autocommit is disabled by a BEGIN statement and reenabled
-** by the next COMMIT or ROLLBACK.
-*/
-int sqlite3_get_autocommit(sqlite3 *db){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- return db->autoCommit;
-}
-
-/*
-** The following routines are substitutes for constants SQLITE_CORRUPT,
-** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_NOMEM and possibly other error
-** constants. They serve two purposes:
-**
-** 1. Serve as a convenient place to set a breakpoint in a debugger
-** to detect when version error conditions occurs.
-**
-** 2. Invoke sqlite3_log() to provide the source code location where
-** a low-level error is first detected.
-*/
-int sqlite3ReportError(int iErr, int lineno, const char *zType){
- sqlite3_log(iErr, "%s at line %d of [%.10s]",
- zType, lineno, 20+sqlite3_sourceid());
- return iErr;
-}
-int sqlite3CorruptError(int lineno){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- return sqlite3ReportError(SQLITE_CORRUPT, lineno, "database corruption");
-}
-int sqlite3MisuseError(int lineno){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- return sqlite3ReportError(SQLITE_MISUSE, lineno, "misuse");
-}
-int sqlite3CantopenError(int lineno){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file");
-}
-#ifdef SQLITE_DEBUG
-int sqlite3CorruptPgnoError(int lineno, Pgno pgno){
- char zMsg[100];
- sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno);
- testcase( sqlite3GlobalConfig.xLog!=0 );
- return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
-}
-int sqlite3NomemError(int lineno){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM");
-}
-int sqlite3IoerrnomemError(int lineno){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- return sqlite3ReportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error");
-}
-#endif
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** This is a convenience routine that makes sure that all thread-specific
-** data for this thread has been deallocated.
-**
-** SQLite no longer uses thread-specific data so this routine is now a
-** no-op. It is retained for historical compatibility.
-*/
-void sqlite3_thread_cleanup(void){
-}
-#endif
-
-/*
-** Return meta information about a specific column of a database table.
-** See comment in sqlite3.h (sqlite.h.in) for details.
-*/
-int sqlite3_table_column_metadata(
- sqlite3 *db, /* Connection handle */
- const char *zDbName, /* Database name or NULL */
- const char *zTableName, /* Table name */
- const char *zColumnName, /* Column name */
- char const **pzDataType, /* OUTPUT: Declared data type */
- char const **pzCollSeq, /* OUTPUT: Collation sequence name */
- int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */
- int *pPrimaryKey, /* OUTPUT: True if column part of PK */
- int *pAutoinc /* OUTPUT: True if column is auto-increment */
-){
- int rc;
- char *zErrMsg = 0;
- Table *pTab = 0;
- Column *pCol = 0;
- int iCol = 0;
- char const *zDataType = 0;
- char const *zCollSeq = 0;
- int notnull = 0;
- int primarykey = 0;
- int autoinc = 0;
-
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
-
- /* Ensure the database schema has been loaded */
- sqlite3_mutex_enter(db->mutex);
- sqlite3BtreeEnterAll(db);
- rc = sqlite3Init(db, &zErrMsg);
- if( SQLITE_OK!=rc ){
- goto error_out;
- }
-
- /* Locate the table in question */
- pTab = sqlite3FindTable(db, zTableName, zDbName);
- if( !pTab || pTab->pSelect ){
- pTab = 0;
- goto error_out;
- }
-
- /* Find the column for which info is requested */
- if( zColumnName==0 ){
- /* Query for existance of table only */
- }else{
- for(iCol=0; iCol<pTab->nCol; iCol++){
- pCol = &pTab->aCol[iCol];
- if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
- break;
- }
- }
- if( iCol==pTab->nCol ){
- if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
- iCol = pTab->iPKey;
- pCol = iCol>=0 ? &pTab->aCol[iCol] : 0;
- }else{
- pTab = 0;
- goto error_out;
- }
- }
- }
-
- /* The following block stores the meta information that will be returned
- ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey
- ** and autoinc. At this point there are two possibilities:
- **
- ** 1. The specified column name was rowid", "oid" or "_rowid_"
- ** and there is no explicitly declared IPK column.
- **
- ** 2. The table is not a view and the column name identified an
- ** explicitly declared column. Copy meta information from *pCol.
- */
- if( pCol ){
- zDataType = sqlite3ColumnType(pCol,0);
- zCollSeq = pCol->zColl;
- notnull = pCol->notNull!=0;
- primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
- autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
- }else{
- zDataType = "INTEGER";
- primarykey = 1;
- }
- if( !zCollSeq ){
- zCollSeq = sqlite3StrBINARY;
- }
-
-error_out:
- sqlite3BtreeLeaveAll(db);
-
- /* Whether the function call succeeded or failed, set the output parameters
- ** to whatever their local counterparts contain. If an error did occur,
- ** this has the effect of zeroing all output parameters.
- */
- if( pzDataType ) *pzDataType = zDataType;
- if( pzCollSeq ) *pzCollSeq = zCollSeq;
- if( pNotNull ) *pNotNull = notnull;
- if( pPrimaryKey ) *pPrimaryKey = primarykey;
- if( pAutoinc ) *pAutoinc = autoinc;
-
- if( SQLITE_OK==rc && !pTab ){
- sqlite3DbFree(db, zErrMsg);
- zErrMsg = sqlite3MPrintf(db, "no such table column: %s.%s", zTableName,
- zColumnName);
- rc = SQLITE_ERROR;
- }
- sqlite3ErrorWithMsg(db, rc, (zErrMsg?"%s":0), zErrMsg);
- sqlite3DbFree(db, zErrMsg);
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** Sleep for a little while. Return the amount of time slept.
-*/
-int sqlite3_sleep(int ms){
- sqlite3_vfs *pVfs;
- int rc;
- pVfs = sqlite3_vfs_find(0);
- if( pVfs==0 ) return 0;
-
- /* This function works in milliseconds, but the underlying OsSleep()
- ** API uses microseconds. Hence the 1000's.
- */
- rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000);
- return rc;
-}
-
-/*
-** Enable or disable the extended result codes.
-*/
-int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- db->errMask = onoff ? 0xffffffff : 0xff;
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
-}
-
-/*
-** Invoke the xFileControl method on a particular database.
-*/
-int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
- int rc = SQLITE_ERROR;
- Btree *pBtree;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- pBtree = sqlite3DbNameToBtree(db, zDbName);
- if( pBtree ){
- Pager *pPager;
- sqlite3_file *fd;
- sqlite3BtreeEnter(pBtree);
- pPager = sqlite3BtreePager(pBtree);
- assert( pPager!=0 );
- fd = sqlite3PagerFile(pPager);
- assert( fd!=0 );
- if( op==SQLITE_FCNTL_FILE_POINTER ){
- *(sqlite3_file**)pArg = fd;
- rc = SQLITE_OK;
- }else if( op==SQLITE_FCNTL_VFS_POINTER ){
- *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager);
- rc = SQLITE_OK;
- }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){
- *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
- rc = SQLITE_OK;
- }else{
- rc = sqlite3OsFileControl(fd, op, pArg);
- }
- sqlite3BtreeLeave(pBtree);
- }
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** Interface to the testing logic.
-*/
-int sqlite3_test_control(int op, ...){
- int rc = 0;
-#ifdef SQLITE_UNTESTABLE
- UNUSED_PARAMETER(op);
-#else
- va_list ap;
- va_start(ap, op);
- switch( op ){
-
- /*
- ** Save the current state of the PRNG.
- */
- case SQLITE_TESTCTRL_PRNG_SAVE: {
- sqlite3PrngSaveState();
- break;
- }
-
- /*
- ** Restore the state of the PRNG to the last state saved using
- ** PRNG_SAVE. If PRNG_SAVE has never before been called, then
- ** this verb acts like PRNG_RESET.
- */
- case SQLITE_TESTCTRL_PRNG_RESTORE: {
- sqlite3PrngRestoreState();
- break;
- }
-
- /*
- ** Reset the PRNG back to its uninitialized state. The next call
- ** to sqlite3_randomness() will reseed the PRNG using a single call
- ** to the xRandomness method of the default VFS.
- */
- case SQLITE_TESTCTRL_PRNG_RESET: {
- sqlite3_randomness(0,0);
- break;
- }
-
- /*
- ** sqlite3_test_control(BITVEC_TEST, size, program)
- **
- ** Run a test against a Bitvec object of size. The program argument
- ** is an array of integers that defines the test. Return -1 on a
- ** memory allocation error, 0 on success, or non-zero for an error.
- ** See the sqlite3BitvecBuiltinTest() for additional information.
- */
- case SQLITE_TESTCTRL_BITVEC_TEST: {
- int sz = va_arg(ap, int);
- int *aProg = va_arg(ap, int*);
- rc = sqlite3BitvecBuiltinTest(sz, aProg);
- break;
- }
-
- /*
- ** sqlite3_test_control(FAULT_INSTALL, xCallback)
- **
- ** Arrange to invoke xCallback() whenever sqlite3FaultSim() is called,
- ** if xCallback is not NULL.
- **
- ** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0)
- ** is called immediately after installing the new callback and the return
- ** value from sqlite3FaultSim(0) becomes the return from
- ** sqlite3_test_control().
- */
- case SQLITE_TESTCTRL_FAULT_INSTALL: {
- /* MSVC is picky about pulling func ptrs from va lists.
- ** http://support.microsoft.com/kb/47961
- ** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int));
- */
- typedef int(*TESTCALLBACKFUNC_t)(int);
- sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
- rc = sqlite3FaultSim(0);
- break;
- }
-
- /*
- ** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
- **
- ** Register hooks to call to indicate which malloc() failures
- ** are benign.
- */
- case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: {
- typedef void (*void_function)(void);
- void_function xBenignBegin;
- void_function xBenignEnd;
- xBenignBegin = va_arg(ap, void_function);
- xBenignEnd = va_arg(ap, void_function);
- sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd);
- break;
- }
-
- /*
- ** sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, unsigned int X)
- **
- ** Set the PENDING byte to the value in the argument, if X>0.
- ** Make no changes if X==0. Return the value of the pending byte
- ** as it existing before this routine was called.
- **
- ** IMPORTANT: Changing the PENDING byte from 0x40000000 results in
- ** an incompatible database file format. Changing the PENDING byte
- ** while any database connection is open results in undefined and
- ** deleterious behavior.
- */
- case SQLITE_TESTCTRL_PENDING_BYTE: {
- rc = PENDING_BYTE;
-#ifndef SQLITE_OMIT_WSD
- {
- unsigned int newVal = va_arg(ap, unsigned int);
- if( newVal ) sqlite3PendingByte = newVal;
- }
-#endif
- break;
- }
-
- /*
- ** sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, int X)
- **
- ** This action provides a run-time test to see whether or not
- ** assert() was enabled at compile-time. If X is true and assert()
- ** is enabled, then the return value is true. If X is true and
- ** assert() is disabled, then the return value is zero. If X is
- ** false and assert() is enabled, then the assertion fires and the
- ** process aborts. If X is false and assert() is disabled, then the
- ** return value is zero.
- */
- case SQLITE_TESTCTRL_ASSERT: {
- volatile int x = 0;
- assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 );
- rc = x;
- break;
- }
-
-
- /*
- ** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X)
- **
- ** This action provides a run-time test to see how the ALWAYS and
- ** NEVER macros were defined at compile-time.
- **
- ** The return value is ALWAYS(X) if X is true, or 0 if X is false.
- **
- ** The recommended test is X==2. If the return value is 2, that means
- ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the
- ** default setting. If the return value is 1, then ALWAYS() is either
- ** hard-coded to true or else it asserts if its argument is false.
- ** The first behavior (hard-coded to true) is the case if
- ** SQLITE_TESTCTRL_ASSERT shows that assert() is disabled and the second
- ** behavior (assert if the argument to ALWAYS() is false) is the case if
- ** SQLITE_TESTCTRL_ASSERT shows that assert() is enabled.
- **
- ** The run-time test procedure might look something like this:
- **
- ** if( sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, 2)==2 ){
- ** // ALWAYS() and NEVER() are no-op pass-through macros
- ** }else if( sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, 1) ){
- ** // ALWAYS(x) asserts that x is true. NEVER(x) asserts x is false.
- ** }else{
- ** // ALWAYS(x) is a constant 1. NEVER(x) is a constant 0.
- ** }
- */
- case SQLITE_TESTCTRL_ALWAYS: {
- int x = va_arg(ap,int);
- rc = x ? ALWAYS(x) : 0;
- break;
- }
-
- /*
- ** sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER);
- **
- ** The integer returned reveals the byte-order of the computer on which
- ** SQLite is running:
- **
- ** 1 big-endian, determined at run-time
- ** 10 little-endian, determined at run-time
- ** 432101 big-endian, determined at compile-time
- ** 123410 little-endian, determined at compile-time
- */
- case SQLITE_TESTCTRL_BYTEORDER: {
- rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN;
- break;
- }
-
- /* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
- **
- ** Set the nReserve size to N for the main database on the database
- ** connection db.
- */
- case SQLITE_TESTCTRL_RESERVE: {
- sqlite3 *db = va_arg(ap, sqlite3*);
- int x = va_arg(ap,int);
- sqlite3_mutex_enter(db->mutex);
- sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0);
- sqlite3_mutex_leave(db->mutex);
- break;
- }
-
- /* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
- **
- ** Enable or disable various optimizations for testing purposes. The
- ** argument N is a bitmask of optimizations to be disabled. For normal
- ** operation N should be 0. The idea is that a test program (like the
- ** SQL Logic Test or SLT test module) can run the same SQL multiple times
- ** with various optimizations disabled to verify that the same answer
- ** is obtained in every case.
- */
- case SQLITE_TESTCTRL_OPTIMIZATIONS: {
- sqlite3 *db = va_arg(ap, sqlite3*);
- db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
- break;
- }
-
- /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
- **
- ** If parameter onoff is non-zero, configure the wrappers so that all
- ** subsequent calls to localtime() and variants fail. If onoff is zero,
- ** undo this setting.
- */
- case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
- sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
- break;
- }
-
- /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
- **
- ** Set or clear a flag that indicates that the database file is always well-
- ** formed and never corrupt. This flag is clear by default, indicating that
- ** database files might have arbitrary corruption. Setting the flag during
- ** testing causes certain assert() statements in the code to be activated
- ** that demonstrat invariants on well-formed database files.
- */
- case SQLITE_TESTCTRL_NEVER_CORRUPT: {
- sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
- break;
- }
-
- /* Set the threshold at which OP_Once counters reset back to zero.
- ** By default this is 0x7ffffffe (over 2 billion), but that value is
- ** too big to test in a reasonable amount of time, so this control is
- ** provided to set a small and easily reachable reset value.
- */
- case SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: {
- sqlite3GlobalConfig.iOnceResetThreshold = va_arg(ap, int);
- break;
- }
-
- /* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr);
- **
- ** Set the VDBE coverage callback function to xCallback with context
- ** pointer ptr.
- */
- case SQLITE_TESTCTRL_VDBE_COVERAGE: {
-#ifdef SQLITE_VDBE_COVERAGE
- typedef void (*branch_callback)(void*,int,u8,u8);
- sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback);
- sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
-#endif
- break;
- }
-
- /* sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, nMax); */
- case SQLITE_TESTCTRL_SORTER_MMAP: {
- sqlite3 *db = va_arg(ap, sqlite3*);
- db->nMaxSorterMmap = va_arg(ap, int);
- break;
- }
-
- /* sqlite3_test_control(SQLITE_TESTCTRL_ISINIT);
- **
- ** Return SQLITE_OK if SQLite has been initialized and SQLITE_ERROR if
- ** not.
- */
- case SQLITE_TESTCTRL_ISINIT: {
- if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
- break;
- }
-
- /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
- **
- ** This test control is used to create imposter tables. "db" is a pointer
- ** to the database connection. dbName is the database name (ex: "main" or
- ** "temp") which will receive the imposter. "onOff" turns imposter mode on
- ** or off. "tnum" is the root page of the b-tree to which the imposter
- ** table should connect.
- **
- ** Enable imposter mode only when the schema has already been parsed. Then
- ** run a single CREATE TABLE statement to construct the imposter table in
- ** the parsed schema. Then turn imposter mode back off again.
- **
- ** If onOff==0 and tnum>0 then reset the schema for all databases, causing
- ** the schema to be reparsed the next time it is needed. This has the
- ** effect of erasing all imposter tables.
- */
- case SQLITE_TESTCTRL_IMPOSTER: {
- sqlite3 *db = va_arg(ap, sqlite3*);
- sqlite3_mutex_enter(db->mutex);
- db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
- db->init.busy = db->init.imposterTable = va_arg(ap,int);
- db->init.newTnum = va_arg(ap,int);
- if( db->init.busy==0 && db->init.newTnum>0 ){
- sqlite3ResetAllSchemasOfConnection(db);
- }
- sqlite3_mutex_leave(db->mutex);
- break;
- }
-
-#if defined(YYCOVERAGE)
- /* sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out)
- **
- ** This test control (only available when SQLite is compiled with
- ** -DYYCOVERAGE) writes a report onto "out" that shows all
- ** state/lookahead combinations in the parser state machine
- ** which are never exercised. If any state is missed, make the
- ** return code SQLITE_ERROR.
- */
- case SQLITE_TESTCTRL_PARSER_COVERAGE: {
- FILE *out = va_arg(ap, FILE*);
- if( sqlite3ParserCoverage(out) ) rc = SQLITE_ERROR;
- break;
- }
-#endif /* defined(YYCOVERAGE) */
- }
- va_end(ap);
-#endif /* SQLITE_UNTESTABLE */
- return rc;
-}
-
-/*
-** This is a utility routine, useful to VFS implementations, that checks
-** to see if a database file was a URI that contained a specific query
-** parameter, and if so obtains the value of the query parameter.
-**
-** The zFilename argument is the filename pointer passed into the xOpen()
-** method of a VFS implementation. The zParam argument is the name of the
-** query parameter we seek. This routine returns the value of the zParam
-** parameter if it exists. If the parameter does not exist, this routine
-** returns a NULL pointer.
-*/
-const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
- if( zFilename==0 || zParam==0 ) return 0;
- zFilename += sqlite3Strlen30(zFilename) + 1;
- while( zFilename[0] ){
- int x = strcmp(zFilename, zParam);
- zFilename += sqlite3Strlen30(zFilename) + 1;
- if( x==0 ) return zFilename;
- zFilename += sqlite3Strlen30(zFilename) + 1;
- }
- return 0;
-}
-
-/*
-** Return a boolean value for a query parameter.
-*/
-int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
- const char *z = sqlite3_uri_parameter(zFilename, zParam);
- bDflt = bDflt!=0;
- return z ? sqlite3GetBoolean(z, bDflt) : bDflt;
-}
-
-/*
-** Return a 64-bit integer value for a query parameter.
-*/
-sqlite3_int64 sqlite3_uri_int64(
- const char *zFilename, /* Filename as passed to xOpen */
- const char *zParam, /* URI parameter sought */
- sqlite3_int64 bDflt /* return if parameter is missing */
-){
- const char *z = sqlite3_uri_parameter(zFilename, zParam);
- sqlite3_int64 v;
- if( z && sqlite3DecOrHexToI64(z, &v)==0 ){
- bDflt = v;
- }
- return bDflt;
-}
-
-/*
-** Return the Btree pointer identified by zDbName. Return NULL if not found.
-*/
-Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
- int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0;
- return iDb<0 ? 0 : db->aDb[iDb].pBt;
-}
-
-/*
-** Return the filename of the database associated with a database
-** connection.
-*/
-const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
- Btree *pBt;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- pBt = sqlite3DbNameToBtree(db, zDbName);
- return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
-}
-
-/*
-** Return 1 if database is read-only or 0 if read/write. Return -1 if
-** no such database exists.
-*/
-int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
- Btree *pBt;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return -1;
- }
-#endif
- pBt = sqlite3DbNameToBtree(db, zDbName);
- return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
-}
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Obtain a snapshot handle for the snapshot of database zDb currently
-** being read by handle db.
-*/
-int sqlite3_snapshot_get(
- sqlite3 *db,
- const char *zDb,
- sqlite3_snapshot **ppSnapshot
-){
- int rc = SQLITE_ERROR;
-#ifndef SQLITE_OMIT_WAL
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
-
- if( db->autoCommit==0 ){
- int iDb = sqlite3FindDbName(db, zDb);
- if( iDb==0 || iDb>1 ){
- Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInTrans(pBt) ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
- }
- }
- }
- }
-
- sqlite3_mutex_leave(db->mutex);
-#endif /* SQLITE_OMIT_WAL */
- return rc;
-}
-
-/*
-** Open a read-transaction on the snapshot idendified by pSnapshot.
-*/
-int sqlite3_snapshot_open(
- sqlite3 *db,
- const char *zDb,
- sqlite3_snapshot *pSnapshot
-){
- int rc = SQLITE_ERROR;
-#ifndef SQLITE_OMIT_WAL
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- if( db->autoCommit==0 ){
- int iDb;
- iDb = sqlite3FindDbName(db, zDb);
- if( iDb==0 || iDb>1 ){
- Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
- rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
- sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0);
- }
- }
- }
- }
-
- sqlite3_mutex_leave(db->mutex);
-#endif /* SQLITE_OMIT_WAL */
- return rc;
-}
-
-/*
-** Recover as many snapshots as possible from the wal file associated with
-** schema zDb of database db.
-*/
-int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
- int rc = SQLITE_ERROR;
- int iDb;
-#ifndef SQLITE_OMIT_WAL
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
-
- sqlite3_mutex_enter(db->mutex);
- iDb = sqlite3FindDbName(db, zDb);
- if( iDb==0 || iDb>1 ){
- Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
- sqlite3BtreeCommit(pBt);
- }
- }
- }
- sqlite3_mutex_leave(db->mutex);
-#endif /* SQLITE_OMIT_WAL */
- return rc;
-}
-
-/*
-** Free a snapshot handle obtained from sqlite3_snapshot_get().
-*/
-void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){
- sqlite3_free(pSnapshot);
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-/*
-** Given the name of a compile-time option, return true if that option
-** was used and false if not.
-**
-** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
-** is not required for a match.
-*/
-int sqlite3_compileoption_used(const char *zOptName){
- int i, n;
- int nOpt;
- const char **azCompileOpt;
-
-#if SQLITE_ENABLE_API_ARMOR
- if( zOptName==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-
- azCompileOpt = sqlite3CompileOptions(&nOpt);
-
- if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
- n = sqlite3Strlen30(zOptName);
-
- /* Since nOpt is normally in single digits, a linear search is
- ** adequate. No need for a binary search. */
- for(i=0; i<nOpt; i++){
- if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
- && sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0
- ){
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** Return the N-th compile-time option string. If N is out of range,
-** return a NULL pointer.
-*/
-const char *sqlite3_compileoption_get(int N){
- int nOpt;
- const char **azCompileOpt;
- azCompileOpt = sqlite3CompileOptions(&nOpt);
- if( N>=0 && N<nOpt ){
- return azCompileOpt[N];
- }
- return 0;
-}
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/malloc.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/malloc.c
deleted file mode 100644
index d7f9df5efc8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/malloc.c
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-**
-** Memory allocation functions used throughout sqlite.
-*/
-#include "sqliteInt.h"
-#include <stdarg.h>
-
-/*
-** Attempt to release up to n bytes of non-essential memory currently
-** held by SQLite. An example of non-essential memory is memory used to
-** cache database pages that are not currently in use.
-*/
-int sqlite3_release_memory(int n){
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- return sqlite3PcacheReleaseMemory(n);
-#else
- /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine
- ** is a no-op returning zero if SQLite is not compiled with
- ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
- UNUSED_PARAMETER(n);
- return 0;
-#endif
-}
-
-/*
-** State information local to the memory allocation subsystem.
-*/
-static SQLITE_WSD struct Mem0Global {
- sqlite3_mutex *mutex; /* Mutex to serialize access */
- sqlite3_int64 alarmThreshold; /* The soft heap limit */
-
- /*
- ** True if heap is nearly "full" where "full" is defined by the
- ** sqlite3_soft_heap_limit() setting.
- */
- int nearlyFull;
-} mem0 = { 0, 0, 0 };
-
-#define mem0 GLOBAL(struct Mem0Global, mem0)
-
-/*
-** Return the memory allocator mutex. sqlite3_status() needs it.
-*/
-sqlite3_mutex *sqlite3MallocMutex(void){
- return mem0.mutex;
-}
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** Deprecated external interface. It used to set an alarm callback
-** that was invoked when memory usage grew too large. Now it is a
-** no-op.
-*/
-int sqlite3_memory_alarm(
- void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
- void *pArg,
- sqlite3_int64 iThreshold
-){
- (void)xCallback;
- (void)pArg;
- (void)iThreshold;
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Set the soft heap-size limit for the library. Passing a zero or
-** negative value indicates no limit.
-*/
-sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
- sqlite3_int64 priorLimit;
- sqlite3_int64 excess;
- sqlite3_int64 nUsed;
-#ifndef SQLITE_OMIT_AUTOINIT
- int rc = sqlite3_initialize();
- if( rc ) return -1;
-#endif
- sqlite3_mutex_enter(mem0.mutex);
- priorLimit = mem0.alarmThreshold;
- if( n<0 ){
- sqlite3_mutex_leave(mem0.mutex);
- return priorLimit;
- }
- mem0.alarmThreshold = n;
- nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
- mem0.nearlyFull = (n>0 && n<=nUsed);
- sqlite3_mutex_leave(mem0.mutex);
- excess = sqlite3_memory_used() - n;
- if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
- return priorLimit;
-}
-void sqlite3_soft_heap_limit(int n){
- if( n<0 ) n = 0;
- sqlite3_soft_heap_limit64(n);
-}
-
-/*
-** Initialize the memory allocation subsystem.
-*/
-int sqlite3MallocInit(void){
- int rc;
- if( sqlite3GlobalConfig.m.xMalloc==0 ){
- sqlite3MemSetDefault();
- }
- memset(&mem0, 0, sizeof(mem0));
- mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
- || sqlite3GlobalConfig.nPage<=0 ){
- sqlite3GlobalConfig.pPage = 0;
- sqlite3GlobalConfig.szPage = 0;
- }
- rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
- if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));
- return rc;
-}
-
-/*
-** Return true if the heap is currently under memory pressure - in other
-** words if the amount of heap used is close to the limit set by
-** sqlite3_soft_heap_limit().
-*/
-int sqlite3HeapNearlyFull(void){
- return mem0.nearlyFull;
-}
-
-/*
-** Deinitialize the memory allocation subsystem.
-*/
-void sqlite3MallocEnd(void){
- if( sqlite3GlobalConfig.m.xShutdown ){
- sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
- }
- memset(&mem0, 0, sizeof(mem0));
-}
-
-/*
-** Return the amount of memory currently checked out.
-*/
-sqlite3_int64 sqlite3_memory_used(void){
- sqlite3_int64 res, mx;
- sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, 0);
- return res;
-}
-
-/*
-** Return the maximum amount of memory that has ever been
-** checked out since either the beginning of this process
-** or since the most recent reset.
-*/
-sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
- sqlite3_int64 res, mx;
- sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag);
- return mx;
-}
-
-/*
-** Trigger the alarm
-*/
-static void sqlite3MallocAlarm(int nByte){
- if( mem0.alarmThreshold<=0 ) return;
- sqlite3_mutex_leave(mem0.mutex);
- sqlite3_release_memory(nByte);
- sqlite3_mutex_enter(mem0.mutex);
-}
-
-/*
-** Do a memory allocation with statistics and alarms. Assume the
-** lock is already held.
-*/
-static void mallocWithAlarm(int n, void **pp){
- void *p;
- int nFull;
- assert( sqlite3_mutex_held(mem0.mutex) );
- assert( n>0 );
-
- /* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal
- ** implementation of malloc_good_size(), which must be called in debug
- ** mode and specifically when the DMD "Dark Matter Detector" is enabled
- ** or else a crash results. Hence, do not attempt to optimize out the
- ** following xRoundup() call. */
- nFull = sqlite3GlobalConfig.m.xRoundup(n);
-
-#ifdef SQLITE_MAX_MEMORY
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){
- *pp = 0;
- return;
- }
-#endif
-
- sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
- if( mem0.alarmThreshold>0 ){
- sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
- if( nUsed >= mem0.alarmThreshold - nFull ){
- mem0.nearlyFull = 1;
- sqlite3MallocAlarm(nFull);
- }else{
- mem0.nearlyFull = 0;
- }
- }
- p = sqlite3GlobalConfig.m.xMalloc(nFull);
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( p==0 && mem0.alarmThreshold>0 ){
- sqlite3MallocAlarm(nFull);
- p = sqlite3GlobalConfig.m.xMalloc(nFull);
- }
-#endif
- if( p ){
- nFull = sqlite3MallocSize(p);
- sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull);
- sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
- }
- *pp = p;
-}
-
-/*
-** Allocate memory. This routine is like sqlite3_malloc() except that it
-** assumes the memory subsystem has already been initialized.
-*/
-void *sqlite3Malloc(u64 n){
- void *p;
- if( n==0 || n>=0x7fffff00 ){
- /* A memory allocation of a number of bytes which is near the maximum
- ** signed integer value might cause an integer overflow inside of the
- ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving
- ** 255 bytes of overhead. SQLite itself will never use anything near
- ** this amount. The only way to reach the limit is with sqlite3_malloc() */
- p = 0;
- }else if( sqlite3GlobalConfig.bMemstat ){
- sqlite3_mutex_enter(mem0.mutex);
- mallocWithAlarm((int)n, &p);
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- p = sqlite3GlobalConfig.m.xMalloc((int)n);
- }
- assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-11148-40995 */
- return p;
-}
-
-/*
-** This version of the memory allocation is for use by the application.
-** First make sure the memory subsystem is initialized, then do the
-** allocation.
-*/
-void *sqlite3_malloc(int n){
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return n<=0 ? 0 : sqlite3Malloc(n);
-}
-void *sqlite3_malloc64(sqlite3_uint64 n){
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return sqlite3Malloc(n);
-}
-
-/*
-** TRUE if p is a lookaside memory allocation from db
-*/
-#ifndef SQLITE_OMIT_LOOKASIDE
-static int isLookaside(sqlite3 *db, void *p){
- return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
-}
-#else
-#define isLookaside(A,B) 0
-#endif
-
-/*
-** Return the size of a memory allocation previously obtained from
-** sqlite3Malloc() or sqlite3_malloc().
-*/
-int sqlite3MallocSize(void *p){
- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
- return sqlite3GlobalConfig.m.xSize(p);
-}
-int sqlite3DbMallocSize(sqlite3 *db, void *p){
- assert( p!=0 );
- if( db==0 || !isLookaside(db,p) ){
-#ifdef SQLITE_DEBUG
- if( db==0 ){
- assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
- }else{
- assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- }
-#endif
- return sqlite3GlobalConfig.m.xSize(p);
- }else{
- assert( sqlite3_mutex_held(db->mutex) );
- return db->lookaside.sz;
- }
-}
-sqlite3_uint64 sqlite3_msize(void *p){
- assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
- return p ? sqlite3GlobalConfig.m.xSize(p) : 0;
-}
-
-/*
-** Free memory previously obtained from sqlite3Malloc().
-*/
-void sqlite3_free(void *p){
- if( p==0 ) return; /* IMP: R-49053-54554 */
- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
- assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
- if( sqlite3GlobalConfig.bMemstat ){
- sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p));
- sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
- sqlite3GlobalConfig.m.xFree(p);
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- sqlite3GlobalConfig.m.xFree(p);
- }
-}
-
-/*
-** Add the size of memory allocation "p" to the count in
-** *db->pnBytesFreed.
-*/
-static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
- *db->pnBytesFreed += sqlite3DbMallocSize(db,p);
-}
-
-/*
-** Free memory that might be associated with a particular database
-** connection. Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op.
-** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL.
-*/
-void sqlite3DbFreeNN(sqlite3 *db, void *p){
- assert( db==0 || sqlite3_mutex_held(db->mutex) );
- assert( p!=0 );
- if( db ){
- if( db->pnBytesFreed ){
- measureAllocationSize(db, p);
- return;
- }
- if( isLookaside(db, p) ){
- LookasideSlot *pBuf = (LookasideSlot*)p;
-#ifdef SQLITE_DEBUG
- /* Trash all content in the buffer being freed */
- memset(p, 0xaa, db->lookaside.sz);
-#endif
- pBuf->pNext = db->lookaside.pFree;
- db->lookaside.pFree = pBuf;
- return;
- }
- }
- assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
- sqlite3_free(p);
-}
-void sqlite3DbFree(sqlite3 *db, void *p){
- assert( db==0 || sqlite3_mutex_held(db->mutex) );
- if( p ) sqlite3DbFreeNN(db, p);
-}
-
-/*
-** Change the size of an existing memory allocation
-*/
-void *sqlite3Realloc(void *pOld, u64 nBytes){
- int nOld, nNew, nDiff;
- void *pNew;
- assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
- assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) );
- if( pOld==0 ){
- return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */
- }
- if( nBytes==0 ){
- sqlite3_free(pOld); /* IMP: R-26507-47431 */
- return 0;
- }
- if( nBytes>=0x7fffff00 ){
- /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
- return 0;
- }
- nOld = sqlite3MallocSize(pOld);
- /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
- ** argument to xRealloc is always a value returned by a prior call to
- ** xRoundup. */
- nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes);
- if( nOld==nNew ){
- pNew = pOld;
- }else if( sqlite3GlobalConfig.bMemstat ){
- sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
- nDiff = nNew - nOld;
- if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
- mem0.alarmThreshold-nDiff ){
- sqlite3MallocAlarm(nDiff);
- }
- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
- if( pNew==0 && mem0.alarmThreshold>0 ){
- sqlite3MallocAlarm((int)nBytes);
- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
- }
- if( pNew ){
- nNew = sqlite3MallocSize(pNew);
- sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
- }
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
- }
- assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */
- return pNew;
-}
-
-/*
-** The public interface to sqlite3Realloc. Make sure that the memory
-** subsystem is initialized prior to invoking sqliteRealloc.
-*/
-void *sqlite3_realloc(void *pOld, int n){
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- if( n<0 ) n = 0; /* IMP: R-26507-47431 */
- return sqlite3Realloc(pOld, n);
-}
-void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return sqlite3Realloc(pOld, n);
-}
-
-
-/*
-** Allocate and zero memory.
-*/
-void *sqlite3MallocZero(u64 n){
- void *p = sqlite3Malloc(n);
- if( p ){
- memset(p, 0, (size_t)n);
- }
- return p;
-}
-
-/*
-** Allocate and zero memory. If the allocation fails, make
-** the mallocFailed flag in the connection pointer.
-*/
-void *sqlite3DbMallocZero(sqlite3 *db, u64 n){
- void *p;
- testcase( db==0 );
- p = sqlite3DbMallocRaw(db, n);
- if( p ) memset(p, 0, (size_t)n);
- return p;
-}
-
-
-/* Finish the work of sqlite3DbMallocRawNN for the unusual and
-** slower case when the allocation cannot be fulfilled using lookaside.
-*/
-static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){
- void *p;
- assert( db!=0 );
- p = sqlite3Malloc(n);
- if( !p ) sqlite3OomFault(db);
- sqlite3MemdebugSetType(p,
- (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
- return p;
-}
-
-/*
-** Allocate memory, either lookaside (if possible) or heap.
-** If the allocation fails, set the mallocFailed flag in
-** the connection pointer.
-**
-** If db!=0 and db->mallocFailed is true (indicating a prior malloc
-** failure on the same database connection) then always return 0.
-** Hence for a particular database connection, once malloc starts
-** failing, it fails consistently until mallocFailed is reset.
-** This is an important assumption. There are many places in the
-** code that do things like this:
-**
-** int *a = (int*)sqlite3DbMallocRaw(db, 100);
-** int *b = (int*)sqlite3DbMallocRaw(db, 200);
-** if( b ) a[10] = 9;
-**
-** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
-** that all prior mallocs (ex: "a") worked too.
-**
-** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is
-** not a NULL pointer.
-*/
-void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
- void *p;
- if( db ) return sqlite3DbMallocRawNN(db, n);
- p = sqlite3Malloc(n);
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
- return p;
-}
-void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
-#ifndef SQLITE_OMIT_LOOKASIDE
- LookasideSlot *pBuf;
- assert( db!=0 );
- assert( sqlite3_mutex_held(db->mutex) );
- assert( db->pnBytesFreed==0 );
- if( db->lookaside.bDisable==0 ){
- assert( db->mallocFailed==0 );
- if( n>db->lookaside.sz ){
- db->lookaside.anStat[1]++;
- }else if( (pBuf = db->lookaside.pFree)!=0 ){
- db->lookaside.pFree = pBuf->pNext;
- db->lookaside.anStat[0]++;
- return (void*)pBuf;
- }else if( (pBuf = db->lookaside.pInit)!=0 ){
- db->lookaside.pInit = pBuf->pNext;
- db->lookaside.anStat[0]++;
- return (void*)pBuf;
- }else{
- db->lookaside.anStat[2]++;
- }
- }else if( db->mallocFailed ){
- return 0;
- }
-#else
- assert( db!=0 );
- assert( sqlite3_mutex_held(db->mutex) );
- assert( db->pnBytesFreed==0 );
- if( db->mallocFailed ){
- return 0;
- }
-#endif
- return dbMallocRawFinish(db, n);
-}
-
-/* Forward declaration */
-static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n);
-
-/*
-** Resize the block of memory pointed to by p to n bytes. If the
-** resize fails, set the mallocFailed flag in the connection object.
-*/
-void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
- assert( db!=0 );
- if( p==0 ) return sqlite3DbMallocRawNN(db, n);
- assert( sqlite3_mutex_held(db->mutex) );
- if( isLookaside(db,p) && n<=db->lookaside.sz ) return p;
- return dbReallocFinish(db, p, n);
-}
-static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
- void *pNew = 0;
- assert( db!=0 );
- assert( p!=0 );
- if( db->mallocFailed==0 ){
- if( isLookaside(db, p) ){
- pNew = sqlite3DbMallocRawNN(db, n);
- if( pNew ){
- memcpy(pNew, p, db->lookaside.sz);
- sqlite3DbFree(db, p);
- }
- }else{
- assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
- pNew = sqlite3_realloc64(p, n);
- if( !pNew ){
- sqlite3OomFault(db);
- }
- sqlite3MemdebugSetType(pNew,
- (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
- }
- }
- return pNew;
-}
-
-/*
-** Attempt to reallocate p. If the reallocation fails, then free p
-** and set the mallocFailed flag in the database connection.
-*/
-void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){
- void *pNew;
- pNew = sqlite3DbRealloc(db, p, n);
- if( !pNew ){
- sqlite3DbFree(db, p);
- }
- return pNew;
-}
-
-/*
-** Make a copy of a string in memory obtained from sqliteMalloc(). These
-** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This
-** is because when memory debugging is turned on, these two functions are
-** called via macros that record the current file and line number in the
-** ThreadData structure.
-*/
-char *sqlite3DbStrDup(sqlite3 *db, const char *z){
- char *zNew;
- size_t n;
- if( z==0 ){
- return 0;
- }
- n = strlen(z) + 1;
- zNew = sqlite3DbMallocRaw(db, n);
- if( zNew ){
- memcpy(zNew, z, n);
- }
- return zNew;
-}
-char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
- char *zNew;
- assert( db!=0 );
- if( z==0 ){
- return 0;
- }
- assert( (n&0x7fffffff)==n );
- zNew = sqlite3DbMallocRawNN(db, n+1);
- if( zNew ){
- memcpy(zNew, z, (size_t)n);
- zNew[n] = 0;
- }
- return zNew;
-}
-
-/*
-** The text between zStart and zEnd represents a phrase within a larger
-** SQL statement. Make a copy of this phrase in space obtained form
-** sqlite3DbMalloc(). Omit leading and trailing whitespace.
-*/
-char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
- int n;
- while( sqlite3Isspace(zStart[0]) ) zStart++;
- n = (int)(zEnd - zStart);
- while( ALWAYS(n>0) && sqlite3Isspace(zStart[n-1]) ) n--;
- return sqlite3DbStrNDup(db, zStart, n);
-}
-
-/*
-** Free any prior content in *pz and replace it with a copy of zNew.
-*/
-void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
- sqlite3DbFree(db, *pz);
- *pz = sqlite3DbStrDup(db, zNew);
-}
-
-/*
-** Call this routine to record the fact that an OOM (out-of-memory) error
-** has happened. This routine will set db->mallocFailed, and also
-** temporarily disable the lookaside memory allocator and interrupt
-** any running VDBEs.
-*/
-void sqlite3OomFault(sqlite3 *db){
- if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
- db->mallocFailed = 1;
- if( db->nVdbeExec>0 ){
- db->u1.isInterrupted = 1;
- }
- db->lookaside.bDisable++;
- }
-}
-
-/*
-** This routine reactivates the memory allocator and clears the
-** db->mallocFailed flag as necessary.
-**
-** The memory allocator is not restarted if there are running
-** VDBEs.
-*/
-void sqlite3OomClear(sqlite3 *db){
- if( db->mallocFailed && db->nVdbeExec==0 ){
- db->mallocFailed = 0;
- db->u1.isInterrupted = 0;
- assert( db->lookaside.bDisable>0 );
- db->lookaside.bDisable--;
- }
-}
-
-/*
-** Take actions at the end of an API call to indicate an OOM error
-*/
-static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
- sqlite3OomClear(db);
- sqlite3Error(db, SQLITE_NOMEM);
- return SQLITE_NOMEM_BKPT;
-}
-
-/*
-** This function must be called before exiting any API function (i.e.
-** returning control to the user) that has called sqlite3_malloc or
-** sqlite3_realloc.
-**
-** The returned value is normally a copy of the second argument to this
-** function. However, if a malloc() failure has occurred since the previous
-** invocation SQLITE_NOMEM is returned instead.
-**
-** If an OOM as occurred, then the connection error-code (the value
-** returned by sqlite3_errcode()) is set to SQLITE_NOMEM.
-*/
-int sqlite3ApiExit(sqlite3* db, int rc){
- /* If the db handle must hold the connection handle mutex here.
- ** Otherwise the read (and possible write) of db->mallocFailed
- ** is unsafe, as is the call to sqlite3Error().
- */
- assert( db!=0 );
- assert( sqlite3_mutex_held(db->mutex) );
- if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
- return apiOomError(db);
- }
- return rc & db->errMask;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem0.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mem0.c
deleted file mode 100644
index 0d0b6667d60..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem0.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-** 2008 October 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 contains a no-op memory allocation drivers for use when
-** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented
-** here always fail. SQLite will not operate with these drivers. These
-** are merely placeholders. Real drivers must be substituted using
-** sqlite3_config() before SQLite will operate.
-*/
-#include "sqliteInt.h"
-
-/*
-** This version of the memory allocator is the default. It is
-** used when no other memory allocator is specified using compile-time
-** macros.
-*/
-#ifdef SQLITE_ZERO_MALLOC
-
-/*
-** No-op versions of all memory allocation routines
-*/
-static void *sqlite3MemMalloc(int nByte){ return 0; }
-static void sqlite3MemFree(void *pPrior){ return; }
-static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
-static int sqlite3MemSize(void *pPrior){ return 0; }
-static int sqlite3MemRoundup(int n){ return n; }
-static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
-static void sqlite3MemShutdown(void *NotUsed){ return; }
-
-/*
-** This routine is the only routine in this file with external linkage.
-**
-** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file.
-*/
-void sqlite3MemSetDefault(void){
- static const sqlite3_mem_methods defaultMethods = {
- sqlite3MemMalloc,
- sqlite3MemFree,
- sqlite3MemRealloc,
- sqlite3MemSize,
- sqlite3MemRoundup,
- sqlite3MemInit,
- sqlite3MemShutdown,
- 0
- };
- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
-}
-
-#endif /* SQLITE_ZERO_MALLOC */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem1.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mem1.c
deleted file mode 100644
index 512ab3747f3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem1.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
-** 2007 August 14
-**
-** 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 contains low-level memory allocation drivers for when
-** SQLite will use the standard C-library malloc/realloc/free interface
-** to obtain the memory it needs.
-**
-** This file contains implementations of the low-level memory allocation
-** routines specified in the sqlite3_mem_methods object. The content of
-** this file is only used if SQLITE_SYSTEM_MALLOC is defined. The
-** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the
-** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined. The
-** default configuration is to use memory allocation routines in this
-** file.
-**
-** C-preprocessor macro summary:
-**
-** HAVE_MALLOC_USABLE_SIZE The configure script sets this symbol if
-** the malloc_usable_size() interface exists
-** on the target platform. Or, this symbol
-** can be set manually, if desired.
-** If an equivalent interface exists by
-** a different name, using a separate -D
-** option to rename it.
-**
-** SQLITE_WITHOUT_ZONEMALLOC Some older macs lack support for the zone
-** memory allocator. Set this symbol to enable
-** building on older macs.
-**
-** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of
-** _msize() on windows systems. This might
-** be necessary when compiling for Delphi,
-** for example.
-*/
-#include "sqliteInt.h"
-
-/*
-** This version of the memory allocator is the default. It is
-** used when no other memory allocator is specified using compile-time
-** macros.
-*/
-#ifdef SQLITE_SYSTEM_MALLOC
-#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
-
-/*
-** Use the zone allocator available on apple products unless the
-** SQLITE_WITHOUT_ZONEMALLOC symbol is defined.
-*/
-#include <sys/sysctl.h>
-#include <malloc/malloc.h>
-#ifdef SQLITE_MIGHT_BE_SINGLE_CORE
-#include <libkern/OSAtomic.h>
-#endif /* SQLITE_MIGHT_BE_SINGLE_CORE */
-static malloc_zone_t* _sqliteZone_;
-#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
-#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
-#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
-#define SQLITE_MALLOCSIZE(x) \
- (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
-
-#else /* if not __APPLE__ */
-
-/*
-** Use standard C library malloc and free on non-Apple systems.
-** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
-*/
-#define SQLITE_MALLOC(x) malloc(x)
-#define SQLITE_FREE(x) free(x)
-#define SQLITE_REALLOC(x,y) realloc((x),(y))
-
-/*
-** The malloc.h header file is needed for malloc_usable_size() function
-** on some systems (e.g. Linux).
-*/
-#if HAVE_MALLOC_H && HAVE_MALLOC_USABLE_SIZE
-# define SQLITE_USE_MALLOC_H 1
-# define SQLITE_USE_MALLOC_USABLE_SIZE 1
-/*
-** The MSVCRT has malloc_usable_size(), but it is called _msize(). The
-** use of _msize() is automatic, but can be disabled by compiling with
-** -DSQLITE_WITHOUT_MSIZE. Using the _msize() function also requires
-** the malloc.h header file.
-*/
-#elif defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
-# define SQLITE_USE_MALLOC_H
-# define SQLITE_USE_MSIZE
-#endif
-
-/*
-** Include the malloc.h header file, if necessary. Also set define macro
-** SQLITE_MALLOCSIZE to the appropriate function name, which is _msize()
-** for MSVC and malloc_usable_size() for most other systems (e.g. Linux).
-** The memory size function can always be overridden manually by defining
-** the macro SQLITE_MALLOCSIZE to the desired function name.
-*/
-#if defined(SQLITE_USE_MALLOC_H)
-# include <malloc.h>
-# if defined(SQLITE_USE_MALLOC_USABLE_SIZE)
-# if !defined(SQLITE_MALLOCSIZE)
-# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
-# endif
-# elif defined(SQLITE_USE_MSIZE)
-# if !defined(SQLITE_MALLOCSIZE)
-# define SQLITE_MALLOCSIZE _msize
-# endif
-# endif
-#endif /* defined(SQLITE_USE_MALLOC_H) */
-
-#endif /* __APPLE__ or not __APPLE__ */
-
-/*
-** Like malloc(), but remember the size of the allocation
-** so that we can find it later using sqlite3MemSize().
-**
-** For this low-level routine, we are guaranteed that nByte>0 because
-** cases of nByte<=0 will be intercepted and dealt with by higher level
-** routines.
-*/
-static void *sqlite3MemMalloc(int nByte){
-#ifdef SQLITE_MALLOCSIZE
- void *p;
- testcase( ROUND8(nByte)==nByte );
- p = SQLITE_MALLOC( nByte );
- if( p==0 ){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
- }
- return p;
-#else
- sqlite3_int64 *p;
- assert( nByte>0 );
- testcase( ROUND8(nByte)!=nByte );
- p = SQLITE_MALLOC( nByte+8 );
- if( p ){
- p[0] = nByte;
- p++;
- }else{
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
- }
- return (void *)p;
-#endif
-}
-
-/*
-** Like free() but works for allocations obtained from sqlite3MemMalloc()
-** or sqlite3MemRealloc().
-**
-** For this low-level routine, we already know that pPrior!=0 since
-** cases where pPrior==0 will have been intecepted and dealt with
-** by higher-level routines.
-*/
-static void sqlite3MemFree(void *pPrior){
-#ifdef SQLITE_MALLOCSIZE
- SQLITE_FREE(pPrior);
-#else
- sqlite3_int64 *p = (sqlite3_int64*)pPrior;
- assert( pPrior!=0 );
- p--;
- SQLITE_FREE(p);
-#endif
-}
-
-/*
-** Report the allocated size of a prior return from xMalloc()
-** or xRealloc().
-*/
-static int sqlite3MemSize(void *pPrior){
-#ifdef SQLITE_MALLOCSIZE
- assert( pPrior!=0 );
- return (int)SQLITE_MALLOCSIZE(pPrior);
-#else
- sqlite3_int64 *p;
- assert( pPrior!=0 );
- p = (sqlite3_int64*)pPrior;
- p--;
- return (int)p[0];
-#endif
-}
-
-/*
-** Like realloc(). Resize an allocation previously obtained from
-** sqlite3MemMalloc().
-**
-** For this low-level interface, we know that pPrior!=0. Cases where
-** pPrior==0 while have been intercepted by higher-level routine and
-** redirected to xMalloc. Similarly, we know that nByte>0 because
-** cases where nByte<=0 will have been intercepted by higher-level
-** routines and redirected to xFree.
-*/
-static void *sqlite3MemRealloc(void *pPrior, int nByte){
-#ifdef SQLITE_MALLOCSIZE
- void *p = SQLITE_REALLOC(pPrior, nByte);
- if( p==0 ){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(SQLITE_NOMEM,
- "failed memory resize %u to %u bytes",
- SQLITE_MALLOCSIZE(pPrior), nByte);
- }
- return p;
-#else
- sqlite3_int64 *p = (sqlite3_int64*)pPrior;
- assert( pPrior!=0 && nByte>0 );
- assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
- p--;
- p = SQLITE_REALLOC(p, nByte+8 );
- if( p ){
- p[0] = nByte;
- p++;
- }else{
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(SQLITE_NOMEM,
- "failed memory resize %u to %u bytes",
- sqlite3MemSize(pPrior), nByte);
- }
- return (void*)p;
-#endif
-}
-
-/*
-** Round up a request size to the next valid allocation size.
-*/
-static int sqlite3MemRoundup(int n){
- return ROUND8(n);
-}
-
-/*
-** Initialize this module.
-*/
-static int sqlite3MemInit(void *NotUsed){
-#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
- int cpuCount;
- size_t len;
- if( _sqliteZone_ ){
- return SQLITE_OK;
- }
- len = sizeof(cpuCount);
- /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
- sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
- if( cpuCount>1 ){
- /* defer MT decisions to system malloc */
- _sqliteZone_ = malloc_default_zone();
- }else{
- /* only 1 core, use our own zone to contention over global locks,
- ** e.g. we have our own dedicated locks */
- _sqliteZone_ = malloc_create_zone(4096, 0);
- malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap");
- }
-#endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */
- UNUSED_PARAMETER(NotUsed);
- return SQLITE_OK;
-}
-
-/*
-** Deinitialize this module.
-*/
-static void sqlite3MemShutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- return;
-}
-
-/*
-** This routine is the only routine in this file with external linkage.
-**
-** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file.
-*/
-void sqlite3MemSetDefault(void){
- static const sqlite3_mem_methods defaultMethods = {
- sqlite3MemMalloc,
- sqlite3MemFree,
- sqlite3MemRealloc,
- sqlite3MemSize,
- sqlite3MemRoundup,
- sqlite3MemInit,
- sqlite3MemShutdown,
- 0
- };
- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
-}
-
-#endif /* SQLITE_SYSTEM_MALLOC */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem2.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mem2.c
deleted file mode 100644
index 51ea297c6a1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem2.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
-** 2007 August 15
-**
-** 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 contains low-level memory allocation drivers for when
-** SQLite will use the standard C-library malloc/realloc/free interface
-** to obtain the memory it needs while adding lots of additional debugging
-** information to each allocation in order to help detect and fix memory
-** leaks and memory usage errors.
-**
-** This file contains implementations of the low-level memory allocation
-** routines specified in the sqlite3_mem_methods object.
-*/
-#include "sqliteInt.h"
-
-/*
-** This version of the memory allocator is used only if the
-** SQLITE_MEMDEBUG macro is defined
-*/
-#ifdef SQLITE_MEMDEBUG
-
-/*
-** The backtrace functionality is only available with GLIBC
-*/
-#ifdef __GLIBC__
- extern int backtrace(void**,int);
- extern void backtrace_symbols_fd(void*const*,int,int);
-#else
-# define backtrace(A,B) 1
-# define backtrace_symbols_fd(A,B,C)
-#endif
-#include <stdio.h>
-
-/*
-** Each memory allocation looks like this:
-**
-** ------------------------------------------------------------------------
-** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard |
-** ------------------------------------------------------------------------
-**
-** The application code sees only a pointer to the allocation. We have
-** to back up from the allocation pointer to find the MemBlockHdr. The
-** MemBlockHdr tells us the size of the allocation and the number of
-** backtrace pointers. There is also a guard word at the end of the
-** MemBlockHdr.
-*/
-struct MemBlockHdr {
- i64 iSize; /* Size of this allocation */
- struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */
- char nBacktrace; /* Number of backtraces on this alloc */
- char nBacktraceSlots; /* Available backtrace slots */
- u8 nTitle; /* Bytes of title; includes '\0' */
- u8 eType; /* Allocation type code */
- int iForeGuard; /* Guard word for sanity */
-};
-
-/*
-** Guard words
-*/
-#define FOREGUARD 0x80F5E153
-#define REARGUARD 0xE4676B53
-
-/*
-** Number of malloc size increments to track.
-*/
-#define NCSIZE 1000
-
-/*
-** All of the static variables used by this module are collected
-** into a single structure named "mem". This is to keep the
-** static variables organized and to reduce namespace pollution
-** when this module is combined with other in the amalgamation.
-*/
-static struct {
-
- /*
- ** Mutex to control access to the memory allocation subsystem.
- */
- sqlite3_mutex *mutex;
-
- /*
- ** Head and tail of a linked list of all outstanding allocations
- */
- struct MemBlockHdr *pFirst;
- struct MemBlockHdr *pLast;
-
- /*
- ** The number of levels of backtrace to save in new allocations.
- */
- int nBacktrace;
- void (*xBacktrace)(int, int, void **);
-
- /*
- ** Title text to insert in front of each block
- */
- int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */
- char zTitle[100]; /* The title text */
-
- /*
- ** sqlite3MallocDisallow() increments the following counter.
- ** sqlite3MallocAllow() decrements it.
- */
- int disallow; /* Do not allow memory allocation */
-
- /*
- ** Gather statistics on the sizes of memory allocations.
- ** nAlloc[i] is the number of allocation attempts of i*8
- ** bytes. i==NCSIZE is the number of allocation attempts for
- ** sizes more than NCSIZE*8 bytes.
- */
- int nAlloc[NCSIZE]; /* Total number of allocations */
- int nCurrent[NCSIZE]; /* Current number of allocations */
- int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */
-
-} mem;
-
-
-/*
-** Adjust memory usage statistics
-*/
-static void adjustStats(int iSize, int increment){
- int i = ROUND8(iSize)/8;
- if( i>NCSIZE-1 ){
- i = NCSIZE - 1;
- }
- if( increment>0 ){
- mem.nAlloc[i]++;
- mem.nCurrent[i]++;
- if( mem.nCurrent[i]>mem.mxCurrent[i] ){
- mem.mxCurrent[i] = mem.nCurrent[i];
- }
- }else{
- mem.nCurrent[i]--;
- assert( mem.nCurrent[i]>=0 );
- }
-}
-
-/*
-** Given an allocation, find the MemBlockHdr for that allocation.
-**
-** This routine checks the guards at either end of the allocation and
-** if they are incorrect it asserts.
-*/
-static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
- struct MemBlockHdr *p;
- int *pInt;
- u8 *pU8;
- int nReserve;
-
- p = (struct MemBlockHdr*)pAllocation;
- p--;
- assert( p->iForeGuard==(int)FOREGUARD );
- nReserve = ROUND8(p->iSize);
- pInt = (int*)pAllocation;
- pU8 = (u8*)pAllocation;
- assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
- /* This checks any of the "extra" bytes allocated due
- ** to rounding up to an 8 byte boundary to ensure
- ** they haven't been overwritten.
- */
- while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
- return p;
-}
-
-/*
-** Return the number of bytes currently allocated at address p.
-*/
-static int sqlite3MemSize(void *p){
- struct MemBlockHdr *pHdr;
- if( !p ){
- return 0;
- }
- pHdr = sqlite3MemsysGetHeader(p);
- return (int)pHdr->iSize;
-}
-
-/*
-** Initialize the memory allocation subsystem.
-*/
-static int sqlite3MemInit(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- assert( (sizeof(struct MemBlockHdr)&7) == 0 );
- if( !sqlite3GlobalConfig.bMemstat ){
- /* If memory status is enabled, then the malloc.c wrapper will already
- ** hold the STATIC_MEM mutex when the routines here are invoked. */
- mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- }
- return SQLITE_OK;
-}
-
-/*
-** Deinitialize the memory allocation subsystem.
-*/
-static void sqlite3MemShutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- mem.mutex = 0;
-}
-
-/*
-** Round up a request size to the next valid allocation size.
-*/
-static int sqlite3MemRoundup(int n){
- return ROUND8(n);
-}
-
-/*
-** Fill a buffer with pseudo-random bytes. This is used to preset
-** the content of a new memory allocation to unpredictable values and
-** to clear the content of a freed allocation to unpredictable values.
-*/
-static void randomFill(char *pBuf, int nByte){
- unsigned int x, y, r;
- x = SQLITE_PTR_TO_INT(pBuf);
- y = nByte | 1;
- while( nByte >= 4 ){
- x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
- y = y*1103515245 + 12345;
- r = x ^ y;
- *(int*)pBuf = r;
- pBuf += 4;
- nByte -= 4;
- }
- while( nByte-- > 0 ){
- x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
- y = y*1103515245 + 12345;
- r = x ^ y;
- *(pBuf++) = r & 0xff;
- }
-}
-
-/*
-** Allocate nByte bytes of memory.
-*/
-static void *sqlite3MemMalloc(int nByte){
- struct MemBlockHdr *pHdr;
- void **pBt;
- char *z;
- int *pInt;
- void *p = 0;
- int totalSize;
- int nReserve;
- sqlite3_mutex_enter(mem.mutex);
- assert( mem.disallow==0 );
- nReserve = ROUND8(nByte);
- totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
- mem.nBacktrace*sizeof(void*) + mem.nTitle;
- p = malloc(totalSize);
- if( p ){
- z = p;
- pBt = (void**)&z[mem.nTitle];
- pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
- pHdr->pNext = 0;
- pHdr->pPrev = mem.pLast;
- if( mem.pLast ){
- mem.pLast->pNext = pHdr;
- }else{
- mem.pFirst = pHdr;
- }
- mem.pLast = pHdr;
- pHdr->iForeGuard = FOREGUARD;
- pHdr->eType = MEMTYPE_HEAP;
- pHdr->nBacktraceSlots = mem.nBacktrace;
- pHdr->nTitle = mem.nTitle;
- if( mem.nBacktrace ){
- void *aAddr[40];
- pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
- memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
- assert(pBt[0]);
- if( mem.xBacktrace ){
- mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
- }
- }else{
- pHdr->nBacktrace = 0;
- }
- if( mem.nTitle ){
- memcpy(z, mem.zTitle, mem.nTitle);
- }
- pHdr->iSize = nByte;
- adjustStats(nByte, +1);
- pInt = (int*)&pHdr[1];
- pInt[nReserve/sizeof(int)] = REARGUARD;
- randomFill((char*)pInt, nByte);
- memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
- p = (void*)pInt;
- }
- sqlite3_mutex_leave(mem.mutex);
- return p;
-}
-
-/*
-** Free memory.
-*/
-static void sqlite3MemFree(void *pPrior){
- struct MemBlockHdr *pHdr;
- void **pBt;
- char *z;
- assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
- || mem.mutex!=0 );
- pHdr = sqlite3MemsysGetHeader(pPrior);
- pBt = (void**)pHdr;
- pBt -= pHdr->nBacktraceSlots;
- sqlite3_mutex_enter(mem.mutex);
- if( pHdr->pPrev ){
- assert( pHdr->pPrev->pNext==pHdr );
- pHdr->pPrev->pNext = pHdr->pNext;
- }else{
- assert( mem.pFirst==pHdr );
- mem.pFirst = pHdr->pNext;
- }
- if( pHdr->pNext ){
- assert( pHdr->pNext->pPrev==pHdr );
- pHdr->pNext->pPrev = pHdr->pPrev;
- }else{
- assert( mem.pLast==pHdr );
- mem.pLast = pHdr->pPrev;
- }
- z = (char*)pBt;
- z -= pHdr->nTitle;
- adjustStats((int)pHdr->iSize, -1);
- randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
- (int)pHdr->iSize + sizeof(int) + pHdr->nTitle);
- free(z);
- sqlite3_mutex_leave(mem.mutex);
-}
-
-/*
-** Change the size of an existing memory allocation.
-**
-** For this debugging implementation, we *always* make a copy of the
-** allocation into a new place in memory. In this way, if the
-** higher level code is using pointer to the old allocation, it is
-** much more likely to break and we are much more liking to find
-** the error.
-*/
-static void *sqlite3MemRealloc(void *pPrior, int nByte){
- struct MemBlockHdr *pOldHdr;
- void *pNew;
- assert( mem.disallow==0 );
- assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */
- pOldHdr = sqlite3MemsysGetHeader(pPrior);
- pNew = sqlite3MemMalloc(nByte);
- if( pNew ){
- memcpy(pNew, pPrior, (int)(nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize));
- if( nByte>pOldHdr->iSize ){
- randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize);
- }
- sqlite3MemFree(pPrior);
- }
- return pNew;
-}
-
-/*
-** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file.
-*/
-void sqlite3MemSetDefault(void){
- static const sqlite3_mem_methods defaultMethods = {
- sqlite3MemMalloc,
- sqlite3MemFree,
- sqlite3MemRealloc,
- sqlite3MemSize,
- sqlite3MemRoundup,
- sqlite3MemInit,
- sqlite3MemShutdown,
- 0
- };
- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
-}
-
-/*
-** Set the "type" of an allocation.
-*/
-void sqlite3MemdebugSetType(void *p, u8 eType){
- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
- struct MemBlockHdr *pHdr;
- pHdr = sqlite3MemsysGetHeader(p);
- assert( pHdr->iForeGuard==FOREGUARD );
- pHdr->eType = eType;
- }
-}
-
-/*
-** Return TRUE if the mask of type in eType matches the type of the
-** allocation p. Also return true if p==NULL.
-**
-** This routine is designed for use within an assert() statement, to
-** verify the type of an allocation. For example:
-**
-** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
-*/
-int sqlite3MemdebugHasType(void *p, u8 eType){
- int rc = 1;
- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
- struct MemBlockHdr *pHdr;
- pHdr = sqlite3MemsysGetHeader(p);
- assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
- if( (pHdr->eType&eType)==0 ){
- rc = 0;
- }
- }
- return rc;
-}
-
-/*
-** Return TRUE if the mask of type in eType matches no bits of the type of the
-** allocation p. Also return true if p==NULL.
-**
-** This routine is designed for use within an assert() statement, to
-** verify the type of an allocation. For example:
-**
-** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
-*/
-int sqlite3MemdebugNoType(void *p, u8 eType){
- int rc = 1;
- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
- struct MemBlockHdr *pHdr;
- pHdr = sqlite3MemsysGetHeader(p);
- assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
- if( (pHdr->eType&eType)!=0 ){
- rc = 0;
- }
- }
- return rc;
-}
-
-/*
-** Set the number of backtrace levels kept for each allocation.
-** A value of zero turns off backtracing. The number is always rounded
-** up to a multiple of 2.
-*/
-void sqlite3MemdebugBacktrace(int depth){
- if( depth<0 ){ depth = 0; }
- if( depth>20 ){ depth = 20; }
- depth = (depth+1)&0xfe;
- mem.nBacktrace = depth;
-}
-
-void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
- mem.xBacktrace = xBacktrace;
-}
-
-/*
-** Set the title string for subsequent allocations.
-*/
-void sqlite3MemdebugSettitle(const char *zTitle){
- unsigned int n = sqlite3Strlen30(zTitle) + 1;
- sqlite3_mutex_enter(mem.mutex);
- if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
- memcpy(mem.zTitle, zTitle, n);
- mem.zTitle[n] = 0;
- mem.nTitle = ROUND8(n);
- sqlite3_mutex_leave(mem.mutex);
-}
-
-void sqlite3MemdebugSync(){
- struct MemBlockHdr *pHdr;
- for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
- void **pBt = (void**)pHdr;
- pBt -= pHdr->nBacktraceSlots;
- mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
- }
-}
-
-/*
-** Open the file indicated and write a log of all unfreed memory
-** allocations into that log.
-*/
-void sqlite3MemdebugDump(const char *zFilename){
- FILE *out;
- struct MemBlockHdr *pHdr;
- void **pBt;
- int i;
- out = fopen(zFilename, "w");
- if( out==0 ){
- fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
- zFilename);
- return;
- }
- for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
- char *z = (char*)pHdr;
- z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
- fprintf(out, "**** %lld bytes at %p from %s ****\n",
- pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
- if( pHdr->nBacktrace ){
- fflush(out);
- pBt = (void**)pHdr;
- pBt -= pHdr->nBacktraceSlots;
- backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
- fprintf(out, "\n");
- }
- }
- fprintf(out, "COUNTS:\n");
- for(i=0; i<NCSIZE-1; i++){
- if( mem.nAlloc[i] ){
- fprintf(out, " %5d: %10d %10d %10d\n",
- i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
- }
- }
- if( mem.nAlloc[NCSIZE-1] ){
- fprintf(out, " %5d: %10d %10d %10d\n",
- NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
- mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
- }
- fclose(out);
-}
-
-/*
-** Return the number of times sqlite3MemMalloc() has been called.
-*/
-int sqlite3MemdebugMallocCount(){
- int i;
- int nTotal = 0;
- for(i=0; i<NCSIZE; i++){
- nTotal += mem.nAlloc[i];
- }
- return nTotal;
-}
-
-
-#endif /* SQLITE_MEMDEBUG */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem3.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mem3.c
deleted file mode 100644
index 2de028daa93..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem3.c
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
-** 2007 October 14
-**
-** 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 contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.
-**
-** This version of the memory allocation subsystem omits all
-** use of malloc(). The SQLite user supplies a block of memory
-** before calling sqlite3_initialize() from which allocations
-** are made and returned by the xMalloc() and xRealloc()
-** implementations. Once sqlite3_initialize() has been called,
-** the amount of memory available to SQLite is fixed and cannot
-** be changed.
-**
-** This version of the memory allocation subsystem is included
-** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
-*/
-#include "sqliteInt.h"
-
-/*
-** This version of the memory allocator is only built into the library
-** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
-** mean that the library will use a memory-pool by default, just that
-** it is available. The mempool allocator is activated by calling
-** sqlite3_config().
-*/
-#ifdef SQLITE_ENABLE_MEMSYS3
-
-/*
-** Maximum size (in Mem3Blocks) of a "small" chunk.
-*/
-#define MX_SMALL 10
-
-
-/*
-** Number of freelist hash slots
-*/
-#define N_HASH 61
-
-/*
-** A memory allocation (also called a "chunk") consists of two or
-** more blocks where each block is 8 bytes. The first 8 bytes are
-** a header that is not returned to the user.
-**
-** A chunk is two or more blocks that is either checked out or
-** free. The first block has format u.hdr. u.hdr.size4x is 4 times the
-** size of the allocation in blocks if the allocation is free.
-** The u.hdr.size4x&1 bit is true if the chunk is checked out and
-** false if the chunk is on the freelist. The u.hdr.size4x&2 bit
-** is true if the previous chunk is checked out and false if the
-** previous chunk is free. The u.hdr.prevSize field is the size of
-** the previous chunk in blocks if the previous chunk is on the
-** freelist. If the previous chunk is checked out, then
-** u.hdr.prevSize can be part of the data for that chunk and should
-** not be read or written.
-**
-** We often identify a chunk by its index in mem3.aPool[]. When
-** this is done, the chunk index refers to the second block of
-** the chunk. In this way, the first chunk has an index of 1.
-** A chunk index of 0 means "no such chunk" and is the equivalent
-** of a NULL pointer.
-**
-** The second block of free chunks is of the form u.list. The
-** two fields form a double-linked list of chunks of related sizes.
-** Pointers to the head of the list are stored in mem3.aiSmall[]
-** for smaller chunks and mem3.aiHash[] for larger chunks.
-**
-** The second block of a chunk is user data if the chunk is checked
-** out. If a chunk is checked out, the user data may extend into
-** the u.hdr.prevSize value of the following chunk.
-*/
-typedef struct Mem3Block Mem3Block;
-struct Mem3Block {
- union {
- struct {
- u32 prevSize; /* Size of previous chunk in Mem3Block elements */
- u32 size4x; /* 4x the size of current chunk in Mem3Block elements */
- } hdr;
- struct {
- u32 next; /* Index in mem3.aPool[] of next free chunk */
- u32 prev; /* Index in mem3.aPool[] of previous free chunk */
- } list;
- } u;
-};
-
-/*
-** All of the static variables used by this module are collected
-** into a single structure named "mem3". This is to keep the
-** static variables organized and to reduce namespace pollution
-** when this module is combined with other in the amalgamation.
-*/
-static SQLITE_WSD struct Mem3Global {
- /*
- ** Memory available for allocation. nPool is the size of the array
- ** (in Mem3Blocks) pointed to by aPool less 2.
- */
- u32 nPool;
- Mem3Block *aPool;
-
- /*
- ** True if we are evaluating an out-of-memory callback.
- */
- int alarmBusy;
-
- /*
- ** Mutex to control access to the memory allocation subsystem.
- */
- sqlite3_mutex *mutex;
-
- /*
- ** The minimum amount of free space that we have seen.
- */
- u32 mnMaster;
-
- /*
- ** iMaster is the index of the master chunk. Most new allocations
- ** occur off of this chunk. szMaster is the size (in Mem3Blocks)
- ** of the current master. iMaster is 0 if there is not master chunk.
- ** The master chunk is not in either the aiHash[] or aiSmall[].
- */
- u32 iMaster;
- u32 szMaster;
-
- /*
- ** Array of lists of free blocks according to the block size
- ** for smaller chunks, or a hash on the block size for larger
- ** chunks.
- */
- u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
- u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
-} mem3 = { 97535575 };
-
-#define mem3 GLOBAL(struct Mem3Global, mem3)
-
-/*
-** Unlink the chunk at mem3.aPool[i] from list it is currently
-** on. *pRoot is the list that i is a member of.
-*/
-static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
- u32 next = mem3.aPool[i].u.list.next;
- u32 prev = mem3.aPool[i].u.list.prev;
- assert( sqlite3_mutex_held(mem3.mutex) );
- if( prev==0 ){
- *pRoot = next;
- }else{
- mem3.aPool[prev].u.list.next = next;
- }
- if( next ){
- mem3.aPool[next].u.list.prev = prev;
- }
- mem3.aPool[i].u.list.next = 0;
- mem3.aPool[i].u.list.prev = 0;
-}
-
-/*
-** Unlink the chunk at index i from
-** whatever list is currently a member of.
-*/
-static void memsys3Unlink(u32 i){
- u32 size, hash;
- assert( sqlite3_mutex_held(mem3.mutex) );
- assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
- assert( i>=1 );
- size = mem3.aPool[i-1].u.hdr.size4x/4;
- assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
- assert( size>=2 );
- if( size <= MX_SMALL ){
- memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
- }else{
- hash = size % N_HASH;
- memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
- }
-}
-
-/*
-** Link the chunk at mem3.aPool[i] so that is on the list rooted
-** at *pRoot.
-*/
-static void memsys3LinkIntoList(u32 i, u32 *pRoot){
- assert( sqlite3_mutex_held(mem3.mutex) );
- mem3.aPool[i].u.list.next = *pRoot;
- mem3.aPool[i].u.list.prev = 0;
- if( *pRoot ){
- mem3.aPool[*pRoot].u.list.prev = i;
- }
- *pRoot = i;
-}
-
-/*
-** Link the chunk at index i into either the appropriate
-** small chunk list, or into the large chunk hash table.
-*/
-static void memsys3Link(u32 i){
- u32 size, hash;
- assert( sqlite3_mutex_held(mem3.mutex) );
- assert( i>=1 );
- assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
- size = mem3.aPool[i-1].u.hdr.size4x/4;
- assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
- assert( size>=2 );
- if( size <= MX_SMALL ){
- memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
- }else{
- hash = size % N_HASH;
- memsys3LinkIntoList(i, &mem3.aiHash[hash]);
- }
-}
-
-/*
-** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
-** will already be held (obtained by code in malloc.c) if
-** sqlite3GlobalConfig.bMemStat is true.
-*/
-static void memsys3Enter(void){
- if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
- mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- }
- sqlite3_mutex_enter(mem3.mutex);
-}
-static void memsys3Leave(void){
- sqlite3_mutex_leave(mem3.mutex);
-}
-
-/*
-** Called when we are unable to satisfy an allocation of nBytes.
-*/
-static void memsys3OutOfMemory(int nByte){
- if( !mem3.alarmBusy ){
- mem3.alarmBusy = 1;
- assert( sqlite3_mutex_held(mem3.mutex) );
- sqlite3_mutex_leave(mem3.mutex);
- sqlite3_release_memory(nByte);
- sqlite3_mutex_enter(mem3.mutex);
- mem3.alarmBusy = 0;
- }
-}
-
-
-/*
-** Chunk i is a free chunk that has been unlinked. Adjust its
-** size parameters for check-out and return a pointer to the
-** user portion of the chunk.
-*/
-static void *memsys3Checkout(u32 i, u32 nBlock){
- u32 x;
- assert( sqlite3_mutex_held(mem3.mutex) );
- assert( i>=1 );
- assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
- assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
- x = mem3.aPool[i-1].u.hdr.size4x;
- mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
- mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
- mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
- return &mem3.aPool[i];
-}
-
-/*
-** Carve a piece off of the end of the mem3.iMaster free chunk.
-** Return a pointer to the new allocation. Or, if the master chunk
-** is not large enough, return 0.
-*/
-static void *memsys3FromMaster(u32 nBlock){
- assert( sqlite3_mutex_held(mem3.mutex) );
- assert( mem3.szMaster>=nBlock );
- if( nBlock>=mem3.szMaster-1 ){
- /* Use the entire master */
- void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
- mem3.iMaster = 0;
- mem3.szMaster = 0;
- mem3.mnMaster = 0;
- return p;
- }else{
- /* Split the master block. Return the tail. */
- u32 newi, x;
- newi = mem3.iMaster + mem3.szMaster - nBlock;
- assert( newi > mem3.iMaster+1 );
- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
- mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
- mem3.szMaster -= nBlock;
- mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
- if( mem3.szMaster < mem3.mnMaster ){
- mem3.mnMaster = mem3.szMaster;
- }
- return (void*)&mem3.aPool[newi];
- }
-}
-
-/*
-** *pRoot is the head of a list of free chunks of the same size
-** or same size hash. In other words, *pRoot is an entry in either
-** mem3.aiSmall[] or mem3.aiHash[].
-**
-** This routine examines all entries on the given list and tries
-** to coalesce each entries with adjacent free chunks.
-**
-** If it sees a chunk that is larger than mem3.iMaster, it replaces
-** the current mem3.iMaster with the new larger chunk. In order for
-** this mem3.iMaster replacement to work, the master chunk must be
-** linked into the hash tables. That is not the normal state of
-** affairs, of course. The calling routine must link the master
-** chunk before invoking this routine, then must unlink the (possibly
-** changed) master chunk once this routine has finished.
-*/
-static void memsys3Merge(u32 *pRoot){
- u32 iNext, prev, size, i, x;
-
- assert( sqlite3_mutex_held(mem3.mutex) );
- for(i=*pRoot; i>0; i=iNext){
- iNext = mem3.aPool[i].u.list.next;
- size = mem3.aPool[i-1].u.hdr.size4x;
- assert( (size&1)==0 );
- if( (size&2)==0 ){
- memsys3UnlinkFromList(i, pRoot);
- assert( i > mem3.aPool[i-1].u.hdr.prevSize );
- prev = i - mem3.aPool[i-1].u.hdr.prevSize;
- if( prev==iNext ){
- iNext = mem3.aPool[prev].u.list.next;
- }
- memsys3Unlink(prev);
- size = i + size/4 - prev;
- x = mem3.aPool[prev-1].u.hdr.size4x & 2;
- mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
- mem3.aPool[prev+size-1].u.hdr.prevSize = size;
- memsys3Link(prev);
- i = prev;
- }else{
- size /= 4;
- }
- if( size>mem3.szMaster ){
- mem3.iMaster = i;
- mem3.szMaster = size;
- }
- }
-}
-
-/*
-** Return a block of memory of at least nBytes in size.
-** Return NULL if unable.
-**
-** This function assumes that the necessary mutexes, if any, are
-** already held by the caller. Hence "Unsafe".
-*/
-static void *memsys3MallocUnsafe(int nByte){
- u32 i;
- u32 nBlock;
- u32 toFree;
-
- assert( sqlite3_mutex_held(mem3.mutex) );
- assert( sizeof(Mem3Block)==8 );
- if( nByte<=12 ){
- nBlock = 2;
- }else{
- nBlock = (nByte + 11)/8;
- }
- assert( nBlock>=2 );
-
- /* STEP 1:
- ** Look for an entry of the correct size in either the small
- ** chunk table or in the large chunk hash table. This is
- ** successful most of the time (about 9 times out of 10).
- */
- if( nBlock <= MX_SMALL ){
- i = mem3.aiSmall[nBlock-2];
- if( i>0 ){
- memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
- return memsys3Checkout(i, nBlock);
- }
- }else{
- int hash = nBlock % N_HASH;
- for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
- if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
- memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
- return memsys3Checkout(i, nBlock);
- }
- }
- }
-
- /* STEP 2:
- ** Try to satisfy the allocation by carving a piece off of the end
- ** of the master chunk. This step usually works if step 1 fails.
- */
- if( mem3.szMaster>=nBlock ){
- return memsys3FromMaster(nBlock);
- }
-
-
- /* STEP 3:
- ** Loop through the entire memory pool. Coalesce adjacent free
- ** chunks. Recompute the master chunk as the largest free chunk.
- ** Then try again to satisfy the allocation by carving a piece off
- ** of the end of the master chunk. This step happens very
- ** rarely (we hope!)
- */
- for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
- memsys3OutOfMemory(toFree);
- if( mem3.iMaster ){
- memsys3Link(mem3.iMaster);
- mem3.iMaster = 0;
- mem3.szMaster = 0;
- }
- for(i=0; i<N_HASH; i++){
- memsys3Merge(&mem3.aiHash[i]);
- }
- for(i=0; i<MX_SMALL-1; i++){
- memsys3Merge(&mem3.aiSmall[i]);
- }
- if( mem3.szMaster ){
- memsys3Unlink(mem3.iMaster);
- if( mem3.szMaster>=nBlock ){
- return memsys3FromMaster(nBlock);
- }
- }
- }
-
- /* If none of the above worked, then we fail. */
- return 0;
-}
-
-/*
-** Free an outstanding memory allocation.
-**
-** This function assumes that the necessary mutexes, if any, are
-** already held by the caller. Hence "Unsafe".
-*/
-static void memsys3FreeUnsafe(void *pOld){
- Mem3Block *p = (Mem3Block*)pOld;
- int i;
- u32 size, x;
- assert( sqlite3_mutex_held(mem3.mutex) );
- assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
- i = p - mem3.aPool;
- assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
- size = mem3.aPool[i-1].u.hdr.size4x/4;
- assert( i+size<=mem3.nPool+1 );
- mem3.aPool[i-1].u.hdr.size4x &= ~1;
- mem3.aPool[i+size-1].u.hdr.prevSize = size;
- mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
- memsys3Link(i);
-
- /* Try to expand the master using the newly freed chunk */
- if( mem3.iMaster ){
- while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
- size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
- mem3.iMaster -= size;
- mem3.szMaster += size;
- memsys3Unlink(mem3.iMaster);
- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
- }
- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
- while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
- memsys3Unlink(mem3.iMaster+mem3.szMaster);
- mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
- }
- }
-}
-
-/*
-** Return the size of an outstanding allocation, in bytes. The
-** size returned omits the 8-byte header overhead. This only
-** works for chunks that are currently checked out.
-*/
-static int memsys3Size(void *p){
- Mem3Block *pBlock;
- assert( p!=0 );
- pBlock = (Mem3Block*)p;
- assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
- return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
-}
-
-/*
-** Round up a request size to the next valid allocation size.
-*/
-static int memsys3Roundup(int n){
- if( n<=12 ){
- return 12;
- }else{
- return ((n+11)&~7) - 4;
- }
-}
-
-/*
-** Allocate nBytes of memory.
-*/
-static void *memsys3Malloc(int nBytes){
- sqlite3_int64 *p;
- assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */
- memsys3Enter();
- p = memsys3MallocUnsafe(nBytes);
- memsys3Leave();
- return (void*)p;
-}
-
-/*
-** Free memory.
-*/
-static void memsys3Free(void *pPrior){
- assert( pPrior );
- memsys3Enter();
- memsys3FreeUnsafe(pPrior);
- memsys3Leave();
-}
-
-/*
-** Change the size of an existing memory allocation
-*/
-static void *memsys3Realloc(void *pPrior, int nBytes){
- int nOld;
- void *p;
- if( pPrior==0 ){
- return sqlite3_malloc(nBytes);
- }
- if( nBytes<=0 ){
- sqlite3_free(pPrior);
- return 0;
- }
- nOld = memsys3Size(pPrior);
- if( nBytes<=nOld && nBytes>=nOld-128 ){
- return pPrior;
- }
- memsys3Enter();
- p = memsys3MallocUnsafe(nBytes);
- if( p ){
- if( nOld<nBytes ){
- memcpy(p, pPrior, nOld);
- }else{
- memcpy(p, pPrior, nBytes);
- }
- memsys3FreeUnsafe(pPrior);
- }
- memsys3Leave();
- return p;
-}
-
-/*
-** Initialize this module.
-*/
-static int memsys3Init(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- if( !sqlite3GlobalConfig.pHeap ){
- return SQLITE_ERROR;
- }
-
- /* Store a pointer to the memory block in global structure mem3. */
- assert( sizeof(Mem3Block)==8 );
- mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
- mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
-
- /* Initialize the master block. */
- mem3.szMaster = mem3.nPool;
- mem3.mnMaster = mem3.szMaster;
- mem3.iMaster = 1;
- mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
- mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
- mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
-
- return SQLITE_OK;
-}
-
-/*
-** Deinitialize this module.
-*/
-static void memsys3Shutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- mem3.mutex = 0;
- return;
-}
-
-
-
-/*
-** Open the file indicated and write a log of all unfreed memory
-** allocations into that log.
-*/
-void sqlite3Memsys3Dump(const char *zFilename){
-#ifdef SQLITE_DEBUG
- FILE *out;
- u32 i, j;
- u32 size;
- if( zFilename==0 || zFilename[0]==0 ){
- out = stdout;
- }else{
- out = fopen(zFilename, "w");
- if( out==0 ){
- fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
- zFilename);
- return;
- }
- }
- memsys3Enter();
- fprintf(out, "CHUNKS:\n");
- for(i=1; i<=mem3.nPool; i+=size/4){
- size = mem3.aPool[i-1].u.hdr.size4x;
- if( size/4<=1 ){
- fprintf(out, "%p size error\n", &mem3.aPool[i]);
- assert( 0 );
- break;
- }
- if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
- fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
- assert( 0 );
- break;
- }
- if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
- fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
- assert( 0 );
- break;
- }
- if( size&1 ){
- fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
- }else{
- fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
- i==mem3.iMaster ? " **master**" : "");
- }
- }
- for(i=0; i<MX_SMALL-1; i++){
- if( mem3.aiSmall[i]==0 ) continue;
- fprintf(out, "small(%2d):", i);
- for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
- fprintf(out, " %p(%d)", &mem3.aPool[j],
- (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
- }
- fprintf(out, "\n");
- }
- for(i=0; i<N_HASH; i++){
- if( mem3.aiHash[i]==0 ) continue;
- fprintf(out, "hash(%2d):", i);
- for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
- fprintf(out, " %p(%d)", &mem3.aPool[j],
- (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
- }
- fprintf(out, "\n");
- }
- fprintf(out, "master=%d\n", mem3.iMaster);
- fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
- fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
- sqlite3_mutex_leave(mem3.mutex);
- if( out==stdout ){
- fflush(stdout);
- }else{
- fclose(out);
- }
-#else
- UNUSED_PARAMETER(zFilename);
-#endif
-}
-
-/*
-** This routine is the only routine in this file with external
-** linkage.
-**
-** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file. The
-** arguments specify the block of memory to manage.
-**
-** This routine is only called by sqlite3_config(), and therefore
-** is not required to be threadsafe (it is not).
-*/
-const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
- static const sqlite3_mem_methods mempoolMethods = {
- memsys3Malloc,
- memsys3Free,
- memsys3Realloc,
- memsys3Size,
- memsys3Roundup,
- memsys3Init,
- memsys3Shutdown,
- 0
- };
- return &mempoolMethods;
-}
-
-#endif /* SQLITE_ENABLE_MEMSYS3 */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem5.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mem5.c
deleted file mode 100644
index c194a6b7781..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mem5.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
-** 2007 October 14
-**
-** 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 contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.
-**
-** This version of the memory allocation subsystem omits all
-** use of malloc(). The application gives SQLite a block of memory
-** before calling sqlite3_initialize() from which allocations
-** are made and returned by the xMalloc() and xRealloc()
-** implementations. Once sqlite3_initialize() has been called,
-** the amount of memory available to SQLite is fixed and cannot
-** be changed.
-**
-** This version of the memory allocation subsystem is included
-** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
-**
-** This memory allocator uses the following algorithm:
-**
-** 1. All memory allocation sizes are rounded up to a power of 2.
-**
-** 2. If two adjacent free blocks are the halves of a larger block,
-** then the two blocks are coalesced into the single larger block.
-**
-** 3. New memory is allocated from the first available free block.
-**
-** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
-** Concerning Dynamic Storage Allocation". Journal of the Association for
-** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
-**
-** Let n be the size of the largest allocation divided by the minimum
-** allocation size (after rounding all sizes up to a power of 2.) Let M
-** be the maximum amount of memory ever outstanding at one time. Let
-** N be the total amount of memory available for allocation. Robson
-** proved that this memory allocator will never breakdown due to
-** fragmentation as long as the following constraint holds:
-**
-** N >= M*(1 + log2(n)/2) - n + 1
-**
-** The sqlite3_status() logic tracks the maximum values of n and M so
-** that an application can, at any time, verify this constraint.
-*/
-#include "sqliteInt.h"
-
-/*
-** This version of the memory allocator is used only when
-** SQLITE_ENABLE_MEMSYS5 is defined.
-*/
-#ifdef SQLITE_ENABLE_MEMSYS5
-
-/*
-** A minimum allocation is an instance of the following structure.
-** Larger allocations are an array of these structures where the
-** size of the array is a power of 2.
-**
-** The size of this object must be a power of two. That fact is
-** verified in memsys5Init().
-*/
-typedef struct Mem5Link Mem5Link;
-struct Mem5Link {
- int next; /* Index of next free chunk */
- int prev; /* Index of previous free chunk */
-};
-
-/*
-** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since
-** mem5.szAtom is always at least 8 and 32-bit integers are used,
-** it is not actually possible to reach this limit.
-*/
-#define LOGMAX 30
-
-/*
-** Masks used for mem5.aCtrl[] elements.
-*/
-#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block */
-#define CTRL_FREE 0x20 /* True if not checked out */
-
-/*
-** All of the static variables used by this module are collected
-** into a single structure named "mem5". This is to keep the
-** static variables organized and to reduce namespace pollution
-** when this module is combined with other in the amalgamation.
-*/
-static SQLITE_WSD struct Mem5Global {
- /*
- ** Memory available for allocation
- */
- int szAtom; /* Smallest possible allocation in bytes */
- int nBlock; /* Number of szAtom sized blocks in zPool */
- u8 *zPool; /* Memory available to be allocated */
-
- /*
- ** Mutex to control access to the memory allocation subsystem.
- */
- sqlite3_mutex *mutex;
-
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- /*
- ** Performance statistics
- */
- u64 nAlloc; /* Total number of calls to malloc */
- u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
- u64 totalExcess; /* Total internal fragmentation */
- u32 currentOut; /* Current checkout, including internal fragmentation */
- u32 currentCount; /* Current number of distinct checkouts */
- u32 maxOut; /* Maximum instantaneous currentOut */
- u32 maxCount; /* Maximum instantaneous currentCount */
- u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
-#endif
-
- /*
- ** Lists of free blocks. aiFreelist[0] is a list of free blocks of
- ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
- ** aiFreelist[2] holds free blocks of size szAtom*4. And so forth.
- */
- int aiFreelist[LOGMAX+1];
-
- /*
- ** Space for tracking which blocks are checked out and the size
- ** of each block. One byte per block.
- */
- u8 *aCtrl;
-
-} mem5;
-
-/*
-** Access the static variable through a macro for SQLITE_OMIT_WSD.
-*/
-#define mem5 GLOBAL(struct Mem5Global, mem5)
-
-/*
-** Assuming mem5.zPool is divided up into an array of Mem5Link
-** structures, return a pointer to the idx-th such link.
-*/
-#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
-
-/*
-** Unlink the chunk at mem5.aPool[i] from list it is currently
-** on. It should be found on mem5.aiFreelist[iLogsize].
-*/
-static void memsys5Unlink(int i, int iLogsize){
- int next, prev;
- assert( i>=0 && i<mem5.nBlock );
- assert( iLogsize>=0 && iLogsize<=LOGMAX );
- assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
-
- next = MEM5LINK(i)->next;
- prev = MEM5LINK(i)->prev;
- if( prev<0 ){
- mem5.aiFreelist[iLogsize] = next;
- }else{
- MEM5LINK(prev)->next = next;
- }
- if( next>=0 ){
- MEM5LINK(next)->prev = prev;
- }
-}
-
-/*
-** Link the chunk at mem5.aPool[i] so that is on the iLogsize
-** free list.
-*/
-static void memsys5Link(int i, int iLogsize){
- int x;
- assert( sqlite3_mutex_held(mem5.mutex) );
- assert( i>=0 && i<mem5.nBlock );
- assert( iLogsize>=0 && iLogsize<=LOGMAX );
- assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
-
- x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
- MEM5LINK(i)->prev = -1;
- if( x>=0 ){
- assert( x<mem5.nBlock );
- MEM5LINK(x)->prev = i;
- }
- mem5.aiFreelist[iLogsize] = i;
-}
-
-/*
-** Obtain or release the mutex needed to access global data structures.
-*/
-static void memsys5Enter(void){
- sqlite3_mutex_enter(mem5.mutex);
-}
-static void memsys5Leave(void){
- sqlite3_mutex_leave(mem5.mutex);
-}
-
-/*
-** Return the size of an outstanding allocation, in bytes.
-** This only works for chunks that are currently checked out.
-*/
-static int memsys5Size(void *p){
- int iSize, i;
- assert( p!=0 );
- i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom);
- assert( i>=0 && i<mem5.nBlock );
- iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
- return iSize;
-}
-
-/*
-** Return a block of memory of at least nBytes in size.
-** Return NULL if unable. Return NULL if nBytes==0.
-**
-** The caller guarantees that nByte is positive.
-**
-** The caller has obtained a mutex prior to invoking this
-** routine so there is never any chance that two or more
-** threads can be in this routine at the same time.
-*/
-static void *memsys5MallocUnsafe(int nByte){
- int i; /* Index of a mem5.aPool[] slot */
- int iBin; /* Index into mem5.aiFreelist[] */
- int iFullSz; /* Size of allocation rounded up to power of 2 */
- int iLogsize; /* Log2 of iFullSz/POW2_MIN */
-
- /* nByte must be a positive */
- assert( nByte>0 );
-
- /* No more than 1GiB per allocation */
- if( nByte > 0x40000000 ) return 0;
-
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- /* Keep track of the maximum allocation request. Even unfulfilled
- ** requests are counted */
- if( (u32)nByte>mem5.maxRequest ){
- mem5.maxRequest = nByte;
- }
-#endif
-
-
- /* Round nByte up to the next valid power of two */
- for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){}
-
- /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
- ** block. If not, then split a block of the next larger power of
- ** two in order to create a new free block of size iLogsize.
- */
- for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){}
- if( iBin>LOGMAX ){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
- return 0;
- }
- i = mem5.aiFreelist[iBin];
- memsys5Unlink(i, iBin);
- while( iBin>iLogsize ){
- int newSize;
-
- iBin--;
- newSize = 1 << iBin;
- mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
- memsys5Link(i+newSize, iBin);
- }
- mem5.aCtrl[i] = iLogsize;
-
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- /* Update allocator performance statistics. */
- mem5.nAlloc++;
- mem5.totalAlloc += iFullSz;
- mem5.totalExcess += iFullSz - nByte;
- mem5.currentCount++;
- mem5.currentOut += iFullSz;
- if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
- if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
-#endif
-
-#ifdef SQLITE_DEBUG
- /* Make sure the allocated memory does not assume that it is set to zero
- ** or retains a value from a previous allocation */
- memset(&mem5.zPool[i*mem5.szAtom], 0xAA, iFullSz);
-#endif
-
- /* Return a pointer to the allocated memory. */
- return (void*)&mem5.zPool[i*mem5.szAtom];
-}
-
-/*
-** Free an outstanding memory allocation.
-*/
-static void memsys5FreeUnsafe(void *pOld){
- u32 size, iLogsize;
- int iBlock;
-
- /* Set iBlock to the index of the block pointed to by pOld in
- ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
- */
- iBlock = (int)(((u8 *)pOld-mem5.zPool)/mem5.szAtom);
-
- /* Check that the pointer pOld points to a valid, non-free block. */
- assert( iBlock>=0 && iBlock<mem5.nBlock );
- assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 );
- assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );
-
- iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
- size = 1<<iLogsize;
- assert( iBlock+size-1<(u32)mem5.nBlock );
-
- mem5.aCtrl[iBlock] |= CTRL_FREE;
- mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
-
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- assert( mem5.currentCount>0 );
- assert( mem5.currentOut>=(size*mem5.szAtom) );
- mem5.currentCount--;
- mem5.currentOut -= size*mem5.szAtom;
- assert( mem5.currentOut>0 || mem5.currentCount==0 );
- assert( mem5.currentCount>0 || mem5.currentOut==0 );
-#endif
-
- mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
- while( ALWAYS(iLogsize<LOGMAX) ){
- int iBuddy;
- if( (iBlock>>iLogsize) & 1 ){
- iBuddy = iBlock - size;
- assert( iBuddy>=0 );
- }else{
- iBuddy = iBlock + size;
- if( iBuddy>=mem5.nBlock ) break;
- }
- if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
- memsys5Unlink(iBuddy, iLogsize);
- iLogsize++;
- if( iBuddy<iBlock ){
- mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
- mem5.aCtrl[iBlock] = 0;
- iBlock = iBuddy;
- }else{
- mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
- mem5.aCtrl[iBuddy] = 0;
- }
- size *= 2;
- }
-
-#ifdef SQLITE_DEBUG
- /* Overwrite freed memory with the 0x55 bit pattern to verify that it is
- ** not used after being freed */
- memset(&mem5.zPool[iBlock*mem5.szAtom], 0x55, size);
-#endif
-
- memsys5Link(iBlock, iLogsize);
-}
-
-/*
-** Allocate nBytes of memory.
-*/
-static void *memsys5Malloc(int nBytes){
- sqlite3_int64 *p = 0;
- if( nBytes>0 ){
- memsys5Enter();
- p = memsys5MallocUnsafe(nBytes);
- memsys5Leave();
- }
- return (void*)p;
-}
-
-/*
-** Free memory.
-**
-** The outer layer memory allocator prevents this routine from
-** being called with pPrior==0.
-*/
-static void memsys5Free(void *pPrior){
- assert( pPrior!=0 );
- memsys5Enter();
- memsys5FreeUnsafe(pPrior);
- memsys5Leave();
-}
-
-/*
-** Change the size of an existing memory allocation.
-**
-** The outer layer memory allocator prevents this routine from
-** being called with pPrior==0.
-**
-** nBytes is always a value obtained from a prior call to
-** memsys5Round(). Hence nBytes is always a non-negative power
-** of two. If nBytes==0 that means that an oversize allocation
-** (an allocation larger than 0x40000000) was requested and this
-** routine should return 0 without freeing pPrior.
-*/
-static void *memsys5Realloc(void *pPrior, int nBytes){
- int nOld;
- void *p;
- assert( pPrior!=0 );
- assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */
- assert( nBytes>=0 );
- if( nBytes==0 ){
- return 0;
- }
- nOld = memsys5Size(pPrior);
- if( nBytes<=nOld ){
- return pPrior;
- }
- p = memsys5Malloc(nBytes);
- if( p ){
- memcpy(p, pPrior, nOld);
- memsys5Free(pPrior);
- }
- return p;
-}
-
-/*
-** Round up a request size to the next valid allocation size. If
-** the allocation is too large to be handled by this allocation system,
-** return 0.
-**
-** All allocations must be a power of two and must be expressed by a
-** 32-bit signed integer. Hence the largest allocation is 0x40000000
-** or 1073741824 bytes.
-*/
-static int memsys5Roundup(int n){
- int iFullSz;
- if( n > 0x40000000 ) return 0;
- for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
- return iFullSz;
-}
-
-/*
-** Return the ceiling of the logarithm base 2 of iValue.
-**
-** Examples: memsys5Log(1) -> 0
-** memsys5Log(2) -> 1
-** memsys5Log(4) -> 2
-** memsys5Log(5) -> 3
-** memsys5Log(8) -> 3
-** memsys5Log(9) -> 4
-*/
-static int memsys5Log(int iValue){
- int iLog;
- for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
- return iLog;
-}
-
-/*
-** Initialize the memory allocator.
-**
-** This routine is not threadsafe. The caller must be holding a mutex
-** to prevent multiple threads from entering at the same time.
-*/
-static int memsys5Init(void *NotUsed){
- int ii; /* Loop counter */
- int nByte; /* Number of bytes of memory available to this allocator */
- u8 *zByte; /* Memory usable by this allocator */
- int nMinLog; /* Log base 2 of minimum allocation size in bytes */
- int iOffset; /* An offset into mem5.aCtrl[] */
-
- UNUSED_PARAMETER(NotUsed);
-
- /* For the purposes of this routine, disable the mutex */
- mem5.mutex = 0;
-
- /* The size of a Mem5Link object must be a power of two. Verify that
- ** this is case.
- */
- assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 );
-
- nByte = sqlite3GlobalConfig.nHeap;
- zByte = (u8*)sqlite3GlobalConfig.pHeap;
- assert( zByte!=0 ); /* sqlite3_config() does not allow otherwise */
-
- /* boundaries on sqlite3GlobalConfig.mnReq are enforced in sqlite3_config() */
- nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
- mem5.szAtom = (1<<nMinLog);
- while( (int)sizeof(Mem5Link)>mem5.szAtom ){
- mem5.szAtom = mem5.szAtom << 1;
- }
-
- mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8)));
- mem5.zPool = zByte;
- mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom];
-
- for(ii=0; ii<=LOGMAX; ii++){
- mem5.aiFreelist[ii] = -1;
- }
-
- iOffset = 0;
- for(ii=LOGMAX; ii>=0; ii--){
- int nAlloc = (1<<ii);
- if( (iOffset+nAlloc)<=mem5.nBlock ){
- mem5.aCtrl[iOffset] = ii | CTRL_FREE;
- memsys5Link(iOffset, ii);
- iOffset += nAlloc;
- }
- assert((iOffset+nAlloc)>mem5.nBlock);
- }
-
- /* If a mutex is required for normal operation, allocate one */
- if( sqlite3GlobalConfig.bMemstat==0 ){
- mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Deinitialize this module.
-*/
-static void memsys5Shutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- mem5.mutex = 0;
- return;
-}
-
-#ifdef SQLITE_TEST
-/*
-** Open the file indicated and write a log of all unfreed memory
-** allocations into that log.
-*/
-void sqlite3Memsys5Dump(const char *zFilename){
- FILE *out;
- int i, j, n;
- int nMinLog;
-
- if( zFilename==0 || zFilename[0]==0 ){
- out = stdout;
- }else{
- out = fopen(zFilename, "w");
- if( out==0 ){
- fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
- zFilename);
- return;
- }
- }
- memsys5Enter();
- nMinLog = memsys5Log(mem5.szAtom);
- for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
- for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
- fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n);
- }
- fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc);
- fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc);
- fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess);
- fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut);
- fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
- fprintf(out, "mem5.maxOut = %u\n", mem5.maxOut);
- fprintf(out, "mem5.maxCount = %u\n", mem5.maxCount);
- fprintf(out, "mem5.maxRequest = %u\n", mem5.maxRequest);
- memsys5Leave();
- if( out==stdout ){
- fflush(stdout);
- }else{
- fclose(out);
- }
-}
-#endif
-
-/*
-** This routine is the only routine in this file with external
-** linkage. It returns a pointer to a static sqlite3_mem_methods
-** struct populated with the memsys5 methods.
-*/
-const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
- static const sqlite3_mem_methods memsys5Methods = {
- memsys5Malloc,
- memsys5Free,
- memsys5Realloc,
- memsys5Size,
- memsys5Roundup,
- memsys5Init,
- memsys5Shutdown,
- 0
- };
- return &memsys5Methods;
-}
-
-#endif /* SQLITE_ENABLE_MEMSYS5 */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/memdb.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/memdb.c
deleted file mode 100644
index 44189852ea9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/memdb.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
-** 2016-09-07
-**
-** 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 an in-memory VFS. A database is held as a contiguous
-** block of memory.
-**
-** This file also implements interface sqlite3_serialize() and
-** sqlite3_deserialize().
-*/
-#ifdef SQLITE_ENABLE_DESERIALIZE
-#include "sqliteInt.h"
-
-/*
-** Forward declaration of objects used by this utility
-*/
-typedef struct sqlite3_vfs MemVfs;
-typedef struct MemFile MemFile;
-
-/* Access to a lower-level VFS that (might) implement dynamic loading,
-** access to randomness, etc.
-*/
-#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
-
-/* An open file */
-struct MemFile {
- sqlite3_file base; /* IO methods */
- sqlite3_int64 sz; /* Size of the file */
- sqlite3_int64 szMax; /* Space allocated to aData */
- unsigned char *aData; /* content of the file */
- int nMmap; /* Number of memory mapped pages */
- unsigned mFlags; /* Flags */
- int eLock; /* Most recent lock against this file */
-};
-
-/*
-** Methods for MemFile
-*/
-static int memdbClose(sqlite3_file*);
-static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
-static int memdbSync(sqlite3_file*, int flags);
-static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int memdbLock(sqlite3_file*, int);
-/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
-static int memdbFileControl(sqlite3_file*, int op, void *pArg);
-/* static int memdbSectorSize(sqlite3_file*); // not used */
-static int memdbDeviceCharacteristics(sqlite3_file*);
-static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
-static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
-
-/*
-** Methods for MemVfs
-*/
-static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
-static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
-static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
-static void memdbDlClose(sqlite3_vfs*, void*);
-static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int memdbSleep(sqlite3_vfs*, int microseconds);
-/* static int memdbCurrentTime(sqlite3_vfs*, double*); */
-static int memdbGetLastError(sqlite3_vfs*, int, char *);
-static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-
-static sqlite3_vfs memdb_vfs = {
- 2, /* iVersion */
- 0, /* szOsFile (set when registered) */
- 1024, /* mxPathname */
- 0, /* pNext */
- "memdb", /* zName */
- 0, /* pAppData (set when registered) */
- memdbOpen, /* xOpen */
- 0, /* memdbDelete, */ /* xDelete */
- memdbAccess, /* xAccess */
- memdbFullPathname, /* xFullPathname */
- memdbDlOpen, /* xDlOpen */
- memdbDlError, /* xDlError */
- memdbDlSym, /* xDlSym */
- memdbDlClose, /* xDlClose */
- memdbRandomness, /* xRandomness */
- memdbSleep, /* xSleep */
- 0, /* memdbCurrentTime, */ /* xCurrentTime */
- memdbGetLastError, /* xGetLastError */
- memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
-};
-
-static const sqlite3_io_methods memdb_io_methods = {
- 3, /* iVersion */
- memdbClose, /* xClose */
- memdbRead, /* xRead */
- memdbWrite, /* xWrite */
- memdbTruncate, /* xTruncate */
- memdbSync, /* xSync */
- memdbFileSize, /* xFileSize */
- memdbLock, /* xLock */
- memdbLock, /* xUnlock - same as xLock in this case */
- 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
- memdbFileControl, /* xFileControl */
- 0, /* memdbSectorSize,*/ /* xSectorSize */
- memdbDeviceCharacteristics, /* xDeviceCharacteristics */
- 0, /* xShmMap */
- 0, /* xShmLock */
- 0, /* xShmBarrier */
- 0, /* xShmUnmap */
- memdbFetch, /* xFetch */
- memdbUnfetch /* xUnfetch */
-};
-
-
-
-/*
-** Close an memdb-file.
-**
-** The pData pointer is owned by the application, so there is nothing
-** to free.
-*/
-static int memdbClose(sqlite3_file *pFile){
- MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
- return SQLITE_OK;
-}
-
-/*
-** Read data from an memdb-file.
-*/
-static int memdbRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- MemFile *p = (MemFile *)pFile;
- if( iOfst+iAmt>p->sz ){
- memset(zBuf, 0, iAmt);
- if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
- return SQLITE_IOERR_SHORT_READ;
- }
- memcpy(zBuf, p->aData+iOfst, iAmt);
- return SQLITE_OK;
-}
-
-/*
-** Try to enlarge the memory allocation to hold at least sz bytes
-*/
-static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
- unsigned char *pNew;
- if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
- return SQLITE_FULL;
- }
- pNew = sqlite3_realloc64(p->aData, newSz);
- if( pNew==0 ) return SQLITE_NOMEM;
- p->aData = pNew;
- p->szMax = newSz;
- return SQLITE_OK;
-}
-
-/*
-** Write data to an memdb-file.
-*/
-static int memdbWrite(
- sqlite3_file *pFile,
- const void *z,
- int iAmt,
- sqlite_int64 iOfst
-){
- MemFile *p = (MemFile *)pFile;
- if( iOfst+iAmt>p->sz ){
- int rc;
- if( iOfst+iAmt>p->szMax
- && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK
- ){
- return rc;
- }
- if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
- p->sz = iOfst+iAmt;
- }
- memcpy(p->aData+iOfst, z, iAmt);
- return SQLITE_OK;
-}
-
-/*
-** Truncate an memdb-file.
-**
-** In rollback mode (which is always the case for memdb, as it does not
-** support WAL mode) the truncate() method is only used to reduce
-** the size of a file, never to increase the size.
-*/
-static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(size>p->sz) ) return SQLITE_FULL;
- p->sz = size;
- return SQLITE_OK;
-}
-
-/*
-** Sync an memdb-file.
-*/
-static int memdbSync(sqlite3_file *pFile, int flags){
- return SQLITE_OK;
-}
-
-/*
-** Return the current file-size of an memdb-file.
-*/
-static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- MemFile *p = (MemFile *)pFile;
- *pSize = p->sz;
- return SQLITE_OK;
-}
-
-/*
-** Lock an memdb-file.
-*/
-static int memdbLock(sqlite3_file *pFile, int eLock){
- MemFile *p = (MemFile *)pFile;
- p->eLock = eLock;
- return SQLITE_OK;
-}
-
-#if 0 /* Never used because memdbAccess() always returns false */
-/*
-** Check if another file-handle holds a RESERVED lock on an memdb-file.
-*/
-static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- *pResOut = 0;
- return SQLITE_OK;
-}
-#endif
-
-/*
-** File control method. For custom operations on an memdb-file.
-*/
-static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
- MemFile *p = (MemFile *)pFile;
- int rc = SQLITE_NOTFOUND;
- if( op==SQLITE_FCNTL_VFSNAME ){
- *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
-/*
-** Return the sector-size in bytes for an memdb-file.
-*/
-static int memdbSectorSize(sqlite3_file *pFile){
- return 1024;
-}
-#endif
-
-/*
-** Return the device characteristic flags supported by an memdb-file.
-*/
-static int memdbDeviceCharacteristics(sqlite3_file *pFile){
- return SQLITE_IOCAP_ATOMIC |
- SQLITE_IOCAP_POWERSAFE_OVERWRITE |
- SQLITE_IOCAP_SAFE_APPEND |
- SQLITE_IOCAP_SEQUENTIAL;
-}
-
-/* Fetch a page of a memory-mapped file */
-static int memdbFetch(
- sqlite3_file *pFile,
- sqlite3_int64 iOfst,
- int iAmt,
- void **pp
-){
- MemFile *p = (MemFile *)pFile;
- p->nMmap++;
- *pp = (void*)(p->aData + iOfst);
- return SQLITE_OK;
-}
-
-/* Release a memory-mapped page */
-static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
- MemFile *p = (MemFile *)pFile;
- p->nMmap--;
- return SQLITE_OK;
-}
-
-/*
-** Open an mem file handle.
-*/
-static int memdbOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- MemFile *p = (MemFile*)pFile;
- if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
- }
- memset(p, 0, sizeof(*p));
- p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
- assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
- *pOutFlags = flags | SQLITE_OPEN_MEMORY;
- p->base.pMethods = &memdb_io_methods;
- return SQLITE_OK;
-}
-
-#if 0 /* Only used to delete rollback journals, master journals, and WAL
- ** files, none of which exist in memdb. So this routine is never used */
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- return SQLITE_IOERR_DELETE;
-}
-#endif
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-**
-** With memdb, no files ever exist on disk. So always return false.
-*/
-static int memdbAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- *pResOut = 0;
- return SQLITE_OK;
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (INST_MAX_PATHNAME+1) bytes.
-*/
-static int memdbFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- sqlite3_snprintf(nOut, zOut, "%s", zPath);
- return SQLITE_OK;
-}
-
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
- ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
-}
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
- return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
-}
-
-#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
-}
-#endif
-
-static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
- return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
-}
-static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
- return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
-}
-
-/*
-** Translate a database connection pointer and schema name into a
-** MemFile pointer.
-*/
-static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
- MemFile *p = 0;
- int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
- if( rc ) return 0;
- if( p->base.pMethods!=&memdb_io_methods ) return 0;
- return p;
-}
-
-/*
-** Return the serialization of a database
-*/
-unsigned char *sqlite3_serialize(
- sqlite3 *db, /* The database connection */
- const char *zSchema, /* Which database within the connection */
- sqlite3_int64 *piSize, /* Write size here, if not NULL */
- unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */
-){
- MemFile *p;
- int iDb;
- Btree *pBt;
- sqlite3_int64 sz;
- int szPage = 0;
- sqlite3_stmt *pStmt = 0;
- unsigned char *pOut;
- char *zSql;
- int rc;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-
- if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
- p = memdbFromDbSchema(db, zSchema);
- iDb = sqlite3FindDbName(db, zSchema);
- if( piSize ) *piSize = -1;
- if( iDb<0 ) return 0;
- if( p ){
- if( piSize ) *piSize = p->sz;
- if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
- pOut = p->aData;
- }else{
- pOut = sqlite3_malloc64( p->sz );
- if( pOut ) memcpy(pOut, p->aData, p->sz);
- }
- return pOut;
- }
- pBt = db->aDb[iDb].pBt;
- if( pBt==0 ) return 0;
- szPage = sqlite3BtreeGetPageSize(pBt);
- zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
- rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
- sqlite3_free(zSql);
- if( rc ) return 0;
- rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW ){
- pOut = 0;
- }else{
- sz = sqlite3_column_int64(pStmt, 0)*szPage;
- if( piSize ) *piSize = sz;
- if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
- pOut = 0;
- }else{
- pOut = sqlite3_malloc64( sz );
- if( pOut ){
- int nPage = sqlite3_column_int(pStmt, 0);
- Pager *pPager = sqlite3BtreePager(pBt);
- int pgno;
- for(pgno=1; pgno<=nPage; pgno++){
- DbPage *pPage = 0;
- unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
- rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
- if( rc==SQLITE_OK ){
- memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
- }else{
- memset(pTo, 0, szPage);
- }
- sqlite3PagerUnref(pPage);
- }
- }
- }
- }
- sqlite3_finalize(pStmt);
- return pOut;
-}
-
-/* Convert zSchema to a MemDB and initialize its content.
-*/
-int sqlite3_deserialize(
- sqlite3 *db, /* The database connection */
- const char *zSchema, /* Which DB to reopen with the deserialization */
- unsigned char *pData, /* The serialized database content */
- sqlite3_int64 szDb, /* Number bytes in the deserialization */
- sqlite3_int64 szBuf, /* Total size of buffer pData[] */
- unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
-){
- MemFile *p;
- char *zSql;
- sqlite3_stmt *pStmt = 0;
- int rc;
- int iDb;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
- return SQLITE_MISUSE_BKPT;
- }
- if( szDb<0 ) return SQLITE_MISUSE_BKPT;
- if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
-#endif
-
- sqlite3_mutex_enter(db->mutex);
- if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
- iDb = sqlite3FindDbName(db, zSchema);
- if( iDb<0 ){
- rc = SQLITE_ERROR;
- goto end_deserialize;
- }
- zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ) goto end_deserialize;
- db->init.iDb = (u8)iDb;
- db->init.reopenMemdb = 1;
- rc = sqlite3_step(pStmt);
- db->init.reopenMemdb = 0;
- if( rc!=SQLITE_DONE ){
- rc = SQLITE_ERROR;
- goto end_deserialize;
- }
- p = memdbFromDbSchema(db, zSchema);
- if( p==0 ){
- rc = SQLITE_ERROR;
- }else{
- p->aData = pData;
- p->sz = szDb;
- p->szMax = szBuf;
- p->mFlags = mFlags;
- rc = SQLITE_OK;
- }
-
-end_deserialize:
- sqlite3_finalize(pStmt);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** This routine is called when the extension is loaded.
-** Register the new VFS.
-*/
-int sqlite3MemdbInit(void){
- sqlite3_vfs *pLower = sqlite3_vfs_find(0);
- int sz = pLower->szOsFile;
- memdb_vfs.pAppData = pLower;
- /* In all known configurations of SQLite, the size of a default
- ** sqlite3_file is greater than the size of a memdb sqlite3_file.
- ** Should that ever change, remove the following NEVER() */
- if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
- memdb_vfs.szOsFile = sz;
- return sqlite3_vfs_register(&memdb_vfs, 0);
-}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/memjournal.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/memjournal.c
deleted file mode 100644
index 3b0e7a67286..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/memjournal.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
-** 2008 October 7
-**
-** 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 contains code use to implement an in-memory rollback journal.
-** The in-memory rollback journal is used to journal transactions for
-** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
-**
-** Update: The in-memory journal is also used to temporarily cache
-** smaller journals that are not critical for power-loss recovery.
-** For example, statement journals that are not too big will be held
-** entirely in memory, thus reducing the number of file I/O calls, and
-** more importantly, reducing temporary file creation events. If these
-** journals become too large for memory, they are spilled to disk. But
-** in the common case, they are usually small and no file I/O needs to
-** occur.
-*/
-#include "sqliteInt.h"
-
-/* Forward references to internal structures */
-typedef struct MemJournal MemJournal;
-typedef struct FilePoint FilePoint;
-typedef struct FileChunk FileChunk;
-
-/*
-** The rollback journal is composed of a linked list of these structures.
-**
-** The zChunk array is always at least 8 bytes in size - usually much more.
-** Its actual size is stored in the MemJournal.nChunkSize variable.
-*/
-struct FileChunk {
- FileChunk *pNext; /* Next chunk in the journal */
- u8 zChunk[8]; /* Content of this chunk */
-};
-
-/*
-** By default, allocate this many bytes of memory for each FileChunk object.
-*/
-#define MEMJOURNAL_DFLT_FILECHUNKSIZE 1024
-
-/*
-** For chunk size nChunkSize, return the number of bytes that should
-** be allocated for each FileChunk structure.
-*/
-#define fileChunkSize(nChunkSize) (sizeof(FileChunk) + ((nChunkSize)-8))
-
-/*
-** An instance of this object serves as a cursor into the rollback journal.
-** The cursor can be either for reading or writing.
-*/
-struct FilePoint {
- sqlite3_int64 iOffset; /* Offset from the beginning of the file */
- FileChunk *pChunk; /* Specific chunk into which cursor points */
-};
-
-/*
-** This structure is a subclass of sqlite3_file. Each open memory-journal
-** is an instance of this class.
-*/
-struct MemJournal {
- const sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */
- int nChunkSize; /* In-memory chunk-size */
-
- int nSpill; /* Bytes of data before flushing */
- int nSize; /* Bytes of data currently in memory */
- FileChunk *pFirst; /* Head of in-memory chunk-list */
- FilePoint endpoint; /* Pointer to the end of the file */
- FilePoint readpoint; /* Pointer to the end of the last xRead() */
-
- int flags; /* xOpen flags */
- sqlite3_vfs *pVfs; /* The "real" underlying VFS */
- const char *zJournal; /* Name of the journal file */
-};
-
-/*
-** Read data from the in-memory journal file. This is the implementation
-** of the sqlite3_vfs.xRead method.
-*/
-static int memjrnlRead(
- sqlite3_file *pJfd, /* The journal file from which to read */
- void *zBuf, /* Put the results here */
- int iAmt, /* Number of bytes to read */
- sqlite_int64 iOfst /* Begin reading at this offset */
-){
- MemJournal *p = (MemJournal *)pJfd;
- u8 *zOut = zBuf;
- int nRead = iAmt;
- int iChunkOffset;
- FileChunk *pChunk;
-
-#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
- || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
- if( (iAmt+iOfst)>p->endpoint.iOffset ){
- return SQLITE_IOERR_SHORT_READ;
- }
-#endif
-
- assert( (iAmt+iOfst)<=p->endpoint.iOffset );
- assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 );
- if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
- sqlite3_int64 iOff = 0;
- for(pChunk=p->pFirst;
- ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst;
- pChunk=pChunk->pNext
- ){
- iOff += p->nChunkSize;
- }
- }else{
- pChunk = p->readpoint.pChunk;
- assert( pChunk!=0 );
- }
-
- iChunkOffset = (int)(iOfst%p->nChunkSize);
- do {
- int iSpace = p->nChunkSize - iChunkOffset;
- int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset));
- memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy);
- zOut += nCopy;
- nRead -= iSpace;
- iChunkOffset = 0;
- } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
- p->readpoint.iOffset = pChunk ? iOfst+iAmt : 0;
- p->readpoint.pChunk = pChunk;
-
- return SQLITE_OK;
-}
-
-/*
-** Free the list of FileChunk structures headed at MemJournal.pFirst.
-*/
-static void memjrnlFreeChunks(MemJournal *p){
- FileChunk *pIter;
- FileChunk *pNext;
- for(pIter=p->pFirst; pIter; pIter=pNext){
- pNext = pIter->pNext;
- sqlite3_free(pIter);
- }
- p->pFirst = 0;
-}
-
-/*
-** Flush the contents of memory to a real file on disk.
-*/
-static int memjrnlCreateFile(MemJournal *p){
- int rc;
- sqlite3_file *pReal = (sqlite3_file*)p;
- MemJournal copy = *p;
-
- memset(p, 0, sizeof(MemJournal));
- rc = sqlite3OsOpen(copy.pVfs, copy.zJournal, pReal, copy.flags, 0);
- if( rc==SQLITE_OK ){
- int nChunk = copy.nChunkSize;
- i64 iOff = 0;
- FileChunk *pIter;
- for(pIter=copy.pFirst; pIter; pIter=pIter->pNext){
- if( iOff + nChunk > copy.endpoint.iOffset ){
- nChunk = copy.endpoint.iOffset - iOff;
- }
- rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nChunk, iOff);
- if( rc ) break;
- iOff += nChunk;
- }
- if( rc==SQLITE_OK ){
- /* No error has occurred. Free the in-memory buffers. */
- memjrnlFreeChunks(&copy);
- }
- }
- if( rc!=SQLITE_OK ){
- /* If an error occurred while creating or writing to the file, restore
- ** the original before returning. This way, SQLite uses the in-memory
- ** journal data to roll back changes made to the internal page-cache
- ** before this function was called. */
- sqlite3OsClose(pReal);
- *p = copy;
- }
- return rc;
-}
-
-
-/*
-** Write data to the file.
-*/
-static int memjrnlWrite(
- sqlite3_file *pJfd, /* The journal file into which to write */
- const void *zBuf, /* Take data to be written from here */
- int iAmt, /* Number of bytes to write */
- sqlite_int64 iOfst /* Begin writing at this offset into the file */
-){
- MemJournal *p = (MemJournal *)pJfd;
- int nWrite = iAmt;
- u8 *zWrite = (u8 *)zBuf;
-
- /* If the file should be created now, create it and write the new data
- ** into the file on disk. */
- if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){
- int rc = memjrnlCreateFile(p);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pJfd, zBuf, iAmt, iOfst);
- }
- return rc;
- }
-
- /* If the contents of this write should be stored in memory */
- else{
- /* An in-memory journal file should only ever be appended to. Random
- ** access writes are not required. The only exception to this is when
- ** the in-memory journal is being used by a connection using the
- ** atomic-write optimization. In this case the first 28 bytes of the
- ** journal file may be written as part of committing the transaction. */
- assert( iOfst==p->endpoint.iOffset || iOfst==0 );
-#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
- || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
- if( iOfst==0 && p->pFirst ){
- assert( p->nChunkSize>iAmt );
- memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
- }else
-#else
- assert( iOfst>0 || p->pFirst==0 );
-#endif
- {
- while( nWrite>0 ){
- FileChunk *pChunk = p->endpoint.pChunk;
- int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize);
- int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset);
-
- if( iChunkOffset==0 ){
- /* New chunk is required to extend the file. */
- FileChunk *pNew = sqlite3_malloc(fileChunkSize(p->nChunkSize));
- if( !pNew ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- pNew->pNext = 0;
- if( pChunk ){
- assert( p->pFirst );
- pChunk->pNext = pNew;
- }else{
- assert( !p->pFirst );
- p->pFirst = pNew;
- }
- p->endpoint.pChunk = pNew;
- }
-
- memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace);
- zWrite += iSpace;
- nWrite -= iSpace;
- p->endpoint.iOffset += iSpace;
- }
- p->nSize = iAmt + iOfst;
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Truncate the file.
-**
-** If the journal file is already on disk, truncate it there. Or, if it
-** is still in main memory but is being truncated to zero bytes in size,
-** ignore
-*/
-static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
- MemJournal *p = (MemJournal *)pJfd;
- if( ALWAYS(size==0) ){
- memjrnlFreeChunks(p);
- p->nSize = 0;
- p->endpoint.pChunk = 0;
- p->endpoint.iOffset = 0;
- p->readpoint.pChunk = 0;
- p->readpoint.iOffset = 0;
- }
- return SQLITE_OK;
-}
-
-/*
-** Close the file.
-*/
-static int memjrnlClose(sqlite3_file *pJfd){
- MemJournal *p = (MemJournal *)pJfd;
- memjrnlFreeChunks(p);
- return SQLITE_OK;
-}
-
-/*
-** Sync the file.
-**
-** If the real file has been created, call its xSync method. Otherwise,
-** syncing an in-memory journal is a no-op.
-*/
-static int memjrnlSync(sqlite3_file *pJfd, int flags){
- UNUSED_PARAMETER2(pJfd, flags);
- return SQLITE_OK;
-}
-
-/*
-** Query the size of the file in bytes.
-*/
-static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
- MemJournal *p = (MemJournal *)pJfd;
- *pSize = (sqlite_int64) p->endpoint.iOffset;
- return SQLITE_OK;
-}
-
-/*
-** Table of methods for MemJournal sqlite3_file object.
-*/
-static const struct sqlite3_io_methods MemJournalMethods = {
- 1, /* iVersion */
- memjrnlClose, /* xClose */
- memjrnlRead, /* xRead */
- memjrnlWrite, /* xWrite */
- memjrnlTruncate, /* xTruncate */
- memjrnlSync, /* xSync */
- memjrnlFileSize, /* xFileSize */
- 0, /* xLock */
- 0, /* xUnlock */
- 0, /* xCheckReservedLock */
- 0, /* xFileControl */
- 0, /* xSectorSize */
- 0, /* xDeviceCharacteristics */
- 0, /* xShmMap */
- 0, /* xShmLock */
- 0, /* xShmBarrier */
- 0, /* xShmUnmap */
- 0, /* xFetch */
- 0 /* xUnfetch */
-};
-
-/*
-** Open a journal file.
-**
-** The behaviour of the journal file depends on the value of parameter
-** nSpill. If nSpill is 0, then the journal file is always create and
-** accessed using the underlying VFS. If nSpill is less than zero, then
-** all content is always stored in main-memory. Finally, if nSpill is a
-** positive value, then the journal file is initially created in-memory
-** but may be flushed to disk later on. In this case the journal file is
-** flushed to disk either when it grows larger than nSpill bytes in size,
-** or when sqlite3JournalCreate() is called.
-*/
-int sqlite3JournalOpen(
- sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */
- const char *zName, /* Name of the journal file */
- sqlite3_file *pJfd, /* Preallocated, blank file handle */
- int flags, /* Opening flags */
- int nSpill /* Bytes buffered before opening the file */
-){
- MemJournal *p = (MemJournal*)pJfd;
-
- /* Zero the file-handle object. If nSpill was passed zero, initialize
- ** it using the sqlite3OsOpen() function of the underlying VFS. In this
- ** case none of the code in this module is executed as a result of calls
- ** made on the journal file-handle. */
- memset(p, 0, sizeof(MemJournal));
- if( nSpill==0 ){
- return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
- }
-
- if( nSpill>0 ){
- p->nChunkSize = nSpill;
- }else{
- p->nChunkSize = 8 + MEMJOURNAL_DFLT_FILECHUNKSIZE - sizeof(FileChunk);
- assert( MEMJOURNAL_DFLT_FILECHUNKSIZE==fileChunkSize(p->nChunkSize) );
- }
-
- p->pMethod = (const sqlite3_io_methods*)&MemJournalMethods;
- p->nSpill = nSpill;
- p->flags = flags;
- p->zJournal = zName;
- p->pVfs = pVfs;
- return SQLITE_OK;
-}
-
-/*
-** Open an in-memory journal file.
-*/
-void sqlite3MemJournalOpen(sqlite3_file *pJfd){
- sqlite3JournalOpen(0, 0, pJfd, 0, -1);
-}
-
-#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
- || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
-/*
-** If the argument p points to a MemJournal structure that is not an
-** in-memory-only journal file (i.e. is one that was opened with a +ve
-** nSpill parameter or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying
-** file has not yet been created, create it now.
-*/
-int sqlite3JournalCreate(sqlite3_file *pJfd){
- int rc = SQLITE_OK;
- MemJournal *p = (MemJournal*)pJfd;
- if( p->pMethod==&MemJournalMethods && (
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
- p->nSpill>0
-#else
- /* While this appears to not be possible without ATOMIC_WRITE, the
- ** paths are complex, so it seems prudent to leave the test in as
- ** a NEVER(), in case our analysis is subtly flawed. */
- NEVER(p->nSpill>0)
-#endif
-#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- || (p->flags & SQLITE_OPEN_MAIN_JOURNAL)
-#endif
- )){
- rc = memjrnlCreateFile(p);
- }
- return rc;
-}
-#endif
-
-/*
-** The file-handle passed as the only argument is open on a journal file.
-** Return true if this "journal file" is currently stored in heap memory,
-** or false otherwise.
-*/
-int sqlite3JournalIsInMemory(sqlite3_file *p){
- return p->pMethods==&MemJournalMethods;
-}
-
-/*
-** Return the number of bytes required to store a JournalFile that uses vfs
-** pVfs to create the underlying on-disk files.
-*/
-int sqlite3JournalSize(sqlite3_vfs *pVfs){
- return MAX(pVfs->szOsFile, (int)sizeof(MemJournal));
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/msvc.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/msvc.h
deleted file mode 100644
index 3914b05bcfa..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/msvc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-** 2015 January 12
-**
-** 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 contains code that is specific to MSVC.
-*/
-#ifndef SQLITE_MSVC_H
-#define SQLITE_MSVC_H
-
-#if defined(_MSC_VER)
-#pragma warning(disable : 4054)
-#pragma warning(disable : 4055)
-#pragma warning(disable : 4100)
-#pragma warning(disable : 4127)
-#pragma warning(disable : 4130)
-#pragma warning(disable : 4152)
-#pragma warning(disable : 4189)
-#pragma warning(disable : 4206)
-#pragma warning(disable : 4210)
-#pragma warning(disable : 4232)
-#pragma warning(disable : 4244)
-#pragma warning(disable : 4305)
-#pragma warning(disable : 4306)
-#pragma warning(disable : 4702)
-#pragma warning(disable : 4706)
-#endif /* defined(_MSC_VER) */
-
-#endif /* SQLITE_MSVC_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex.c
deleted file mode 100644
index 3ad7b89edc2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
-** 2007 August 14
-**
-** 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 contains the C functions that implement mutexes.
-**
-** This file contains code that is common across all mutex implementations.
-*/
-#include "sqliteInt.h"
-
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
-/*
-** For debugging purposes, record when the mutex subsystem is initialized
-** and uninitialized so that we can assert() if there is an attempt to
-** allocate a mutex while the system is uninitialized.
-*/
-static SQLITE_WSD int mutexIsInit = 0;
-#endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */
-
-
-#ifndef SQLITE_MUTEX_OMIT
-
-#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
-/*
-** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
-** the implementation of a wrapper around the system default mutex
-** implementation (sqlite3DefaultMutex()).
-**
-** Most calls are passed directly through to the underlying default
-** mutex implementation. Except, if a mutex is configured by calling
-** sqlite3MutexWarnOnContention() on it, then if contention is ever
-** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
-**
-** This type of mutex is used as the database handle mutex when testing
-** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
-*/
-
-/*
-** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
-** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
-** allocated by the system mutex implementation. Variable iType is usually set
-** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
-** or one of the static mutex identifiers. Or, if this is a recursive mutex
-** that has been configured using sqlite3MutexWarnOnContention(), it is
-** set to SQLITE_MUTEX_WARNONCONTENTION.
-*/
-typedef struct CheckMutex CheckMutex;
-struct CheckMutex {
- int iType;
- sqlite3_mutex *mutex;
-};
-
-#define SQLITE_MUTEX_WARNONCONTENTION (-1)
-
-/*
-** Pointer to real mutex methods object used by the CheckMutex
-** implementation. Set by checkMutexInit().
-*/
-static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods;
-
-#ifdef SQLITE_DEBUG
-static int checkMutexHeld(sqlite3_mutex *p){
- return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex);
-}
-static int checkMutexNotheld(sqlite3_mutex *p){
- return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex);
-}
-#endif
-
-/*
-** Initialize and deinitialize the mutex subsystem.
-*/
-static int checkMutexInit(void){
- pGlobalMutexMethods = sqlite3DefaultMutex();
- return SQLITE_OK;
-}
-static int checkMutexEnd(void){
- pGlobalMutexMethods = 0;
- return SQLITE_OK;
-}
-
-/*
-** Allocate a mutex.
-*/
-static sqlite3_mutex *checkMutexAlloc(int iType){
- static CheckMutex staticMutexes[] = {
- {2, 0}, {3, 0}, {4, 0}, {5, 0},
- {6, 0}, {7, 0}, {8, 0}, {9, 0},
- {10, 0}, {11, 0}, {12, 0}, {13, 0}
- };
- CheckMutex *p = 0;
-
- assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 );
- if( iType<2 ){
- p = sqlite3MallocZero(sizeof(CheckMutex));
- if( p==0 ) return 0;
- p->iType = iType;
- }else{
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( iType-2>=ArraySize(staticMutexes) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- p = &staticMutexes[iType-2];
- }
-
- if( p->mutex==0 ){
- p->mutex = pGlobalMutexMethods->xMutexAlloc(iType);
- if( p->mutex==0 ){
- if( iType<2 ){
- sqlite3_free(p);
- }
- p = 0;
- }
- }
-
- return (sqlite3_mutex*)p;
-}
-
-/*
-** Free a mutex.
-*/
-static void checkMutexFree(sqlite3_mutex *p){
- assert( SQLITE_MUTEX_RECURSIVE<2 );
- assert( SQLITE_MUTEX_FAST<2 );
- assert( SQLITE_MUTEX_WARNONCONTENTION<2 );
-
-#if SQLITE_ENABLE_API_ARMOR
- if( ((CheckMutex*)p)->iType<2 )
-#endif
- {
- CheckMutex *pCheck = (CheckMutex*)p;
- pGlobalMutexMethods->xMutexFree(pCheck->mutex);
- sqlite3_free(pCheck);
- }
-#ifdef SQLITE_ENABLE_API_ARMOR
- else{
- (void)SQLITE_MISUSE_BKPT;
- }
-#endif
-}
-
-/*
-** Enter the mutex.
-*/
-static void checkMutexEnter(sqlite3_mutex *p){
- CheckMutex *pCheck = (CheckMutex*)p;
- if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){
- if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){
- return;
- }
- sqlite3_log(SQLITE_MISUSE,
- "illegal multi-threaded access to database connection"
- );
- }
- pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
-}
-
-/*
-** Enter the mutex (do not block).
-*/
-static int checkMutexTry(sqlite3_mutex *p){
- CheckMutex *pCheck = (CheckMutex*)p;
- return pGlobalMutexMethods->xMutexTry(pCheck->mutex);
-}
-
-/*
-** Leave the mutex.
-*/
-static void checkMutexLeave(sqlite3_mutex *p){
- CheckMutex *pCheck = (CheckMutex*)p;
- pGlobalMutexMethods->xMutexLeave(pCheck->mutex);
-}
-
-sqlite3_mutex_methods const *multiThreadedCheckMutex(void){
- static const sqlite3_mutex_methods sMutex = {
- checkMutexInit,
- checkMutexEnd,
- checkMutexAlloc,
- checkMutexFree,
- checkMutexEnter,
- checkMutexTry,
- checkMutexLeave,
-#ifdef SQLITE_DEBUG
- checkMutexHeld,
- checkMutexNotheld
-#else
- 0,
- 0
-#endif
- };
- return &sMutex;
-}
-
-/*
-** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as
-** one on which there should be no contention.
-*/
-void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
- if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){
- CheckMutex *pCheck = (CheckMutex*)p;
- assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE );
- pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
- }
-}
-#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
-
-/*
-** Initialize the mutex system.
-*/
-int sqlite3MutexInit(void){
- int rc = SQLITE_OK;
- if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
- /* If the xMutexAlloc method has not been set, then the user did not
- ** install a mutex implementation via sqlite3_config() prior to
- ** sqlite3_initialize() being called. This block copies pointers to
- ** the default implementation into the sqlite3GlobalConfig structure.
- */
- sqlite3_mutex_methods const *pFrom;
- sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
-
- if( sqlite3GlobalConfig.bCoreMutex ){
-#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
- pFrom = multiThreadedCheckMutex();
-#else
- pFrom = sqlite3DefaultMutex();
-#endif
- }else{
- pFrom = sqlite3NoopMutex();
- }
- pTo->xMutexInit = pFrom->xMutexInit;
- pTo->xMutexEnd = pFrom->xMutexEnd;
- pTo->xMutexFree = pFrom->xMutexFree;
- pTo->xMutexEnter = pFrom->xMutexEnter;
- pTo->xMutexTry = pFrom->xMutexTry;
- pTo->xMutexLeave = pFrom->xMutexLeave;
- pTo->xMutexHeld = pFrom->xMutexHeld;
- pTo->xMutexNotheld = pFrom->xMutexNotheld;
- sqlite3MemoryBarrier();
- pTo->xMutexAlloc = pFrom->xMutexAlloc;
- }
- assert( sqlite3GlobalConfig.mutex.xMutexInit );
- rc = sqlite3GlobalConfig.mutex.xMutexInit();
-
-#ifdef SQLITE_DEBUG
- GLOBAL(int, mutexIsInit) = 1;
-#endif
-
- return rc;
-}
-
-/*
-** Shutdown the mutex system. This call frees resources allocated by
-** sqlite3MutexInit().
-*/
-int sqlite3MutexEnd(void){
- int rc = SQLITE_OK;
- if( sqlite3GlobalConfig.mutex.xMutexEnd ){
- rc = sqlite3GlobalConfig.mutex.xMutexEnd();
- }
-
-#ifdef SQLITE_DEBUG
- GLOBAL(int, mutexIsInit) = 0;
-#endif
-
- return rc;
-}
-
-/*
-** Retrieve a pointer to a static mutex or allocate a new dynamic one.
-*/
-sqlite3_mutex *sqlite3_mutex_alloc(int id){
-#ifndef SQLITE_OMIT_AUTOINIT
- if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
- if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
-#endif
- assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
- return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
-}
-
-sqlite3_mutex *sqlite3MutexAlloc(int id){
- if( !sqlite3GlobalConfig.bCoreMutex ){
- return 0;
- }
- assert( GLOBAL(int, mutexIsInit) );
- assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
- return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
-}
-
-/*
-** Free a dynamic mutex.
-*/
-void sqlite3_mutex_free(sqlite3_mutex *p){
- if( p ){
- assert( sqlite3GlobalConfig.mutex.xMutexFree );
- sqlite3GlobalConfig.mutex.xMutexFree(p);
- }
-}
-
-/*
-** Obtain the mutex p. If some other thread already has the mutex, block
-** until it can be obtained.
-*/
-void sqlite3_mutex_enter(sqlite3_mutex *p){
- if( p ){
- assert( sqlite3GlobalConfig.mutex.xMutexEnter );
- sqlite3GlobalConfig.mutex.xMutexEnter(p);
- }
-}
-
-/*
-** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
-** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
-*/
-int sqlite3_mutex_try(sqlite3_mutex *p){
- int rc = SQLITE_OK;
- if( p ){
- assert( sqlite3GlobalConfig.mutex.xMutexTry );
- return sqlite3GlobalConfig.mutex.xMutexTry(p);
- }
- return rc;
-}
-
-/*
-** The sqlite3_mutex_leave() routine exits a mutex that was previously
-** entered by the same thread. The behavior is undefined if the mutex
-** is not currently entered. If a NULL pointer is passed as an argument
-** this function is a no-op.
-*/
-void sqlite3_mutex_leave(sqlite3_mutex *p){
- if( p ){
- assert( sqlite3GlobalConfig.mutex.xMutexLeave );
- sqlite3GlobalConfig.mutex.xMutexLeave(p);
- }
-}
-
-#ifndef NDEBUG
-/*
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-** intended for use inside assert() statements.
-*/
-int sqlite3_mutex_held(sqlite3_mutex *p){
- assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
- return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
-}
-int sqlite3_mutex_notheld(sqlite3_mutex *p){
- assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
- return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
-}
-#endif
-
-#endif /* !defined(SQLITE_MUTEX_OMIT) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex.h
deleted file mode 100644
index 03eb1faadb6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-** 2007 August 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 contains the common header for all mutex implementations.
-** The sqliteInt.h header #includes this file so that it is available
-** to all source files. We break it out in an effort to keep the code
-** better organized.
-**
-** NOTE: source files should *not* #include this header file directly.
-** Source files should #include the sqliteInt.h file and let that file
-** include this one indirectly.
-*/
-
-
-/*
-** Figure out what version of the code to use. The choices are
-**
-** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The
-** mutexes implementation cannot be overridden
-** at start-time.
-**
-** SQLITE_MUTEX_NOOP For single-threaded applications. No
-** mutual exclusion is provided. But this
-** implementation can be overridden at
-** start-time.
-**
-** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix.
-**
-** SQLITE_MUTEX_W32 For multi-threaded applications on Win32.
-*/
-#if !SQLITE_THREADSAFE
-# define SQLITE_MUTEX_OMIT
-#endif
-#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP)
-# if SQLITE_OS_UNIX
-# define SQLITE_MUTEX_PTHREADS
-# elif SQLITE_OS_WIN
-# define SQLITE_MUTEX_W32
-# else
-# define SQLITE_MUTEX_NOOP
-# endif
-#endif
-
-#ifdef SQLITE_MUTEX_OMIT
-/*
-** If this is a no-op implementation, implement everything as macros.
-*/
-#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
-#define sqlite3_mutex_free(X)
-#define sqlite3_mutex_enter(X)
-#define sqlite3_mutex_try(X) SQLITE_OK
-#define sqlite3_mutex_leave(X)
-#define sqlite3_mutex_held(X) ((void)(X),1)
-#define sqlite3_mutex_notheld(X) ((void)(X),1)
-#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8)
-#define sqlite3MutexInit() SQLITE_OK
-#define sqlite3MutexEnd()
-#define MUTEX_LOGIC(X)
-#else
-#define MUTEX_LOGIC(X) X
-#endif /* defined(SQLITE_MUTEX_OMIT) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_noop.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_noop.c
deleted file mode 100644
index ecc84b4a94a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_noop.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-** 2008 October 07
-**
-** 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 contains the C functions that implement mutexes.
-**
-** This implementation in this file does not provide any mutual
-** exclusion and is thus suitable for use only in applications
-** that use SQLite in a single thread. The routines defined
-** here are place-holders. Applications can substitute working
-** mutex routines at start-time using the
-**
-** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
-**
-** interface.
-**
-** If compiled with SQLITE_DEBUG, then additional logic is inserted
-** that does error checking on mutexes to make sure they are being
-** called correctly.
-*/
-#include "sqliteInt.h"
-
-#ifndef SQLITE_MUTEX_OMIT
-
-#ifndef SQLITE_DEBUG
-/*
-** Stub routines for all mutex methods.
-**
-** This routines provide no mutual exclusion or error checking.
-*/
-static int noopMutexInit(void){ return SQLITE_OK; }
-static int noopMutexEnd(void){ return SQLITE_OK; }
-static sqlite3_mutex *noopMutexAlloc(int id){
- UNUSED_PARAMETER(id);
- return (sqlite3_mutex*)8;
-}
-static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
-static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
-static int noopMutexTry(sqlite3_mutex *p){
- UNUSED_PARAMETER(p);
- return SQLITE_OK;
-}
-static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
-
-sqlite3_mutex_methods const *sqlite3NoopMutex(void){
- static const sqlite3_mutex_methods sMutex = {
- noopMutexInit,
- noopMutexEnd,
- noopMutexAlloc,
- noopMutexFree,
- noopMutexEnter,
- noopMutexTry,
- noopMutexLeave,
-
- 0,
- 0,
- };
-
- return &sMutex;
-}
-#endif /* !SQLITE_DEBUG */
-
-#ifdef SQLITE_DEBUG
-/*
-** In this implementation, error checking is provided for testing
-** and debugging purposes. The mutexes still do not provide any
-** mutual exclusion.
-*/
-
-/*
-** The mutex object
-*/
-typedef struct sqlite3_debug_mutex {
- int id; /* The mutex type */
- int cnt; /* Number of entries without a matching leave */
-} sqlite3_debug_mutex;
-
-/*
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-** intended for use inside assert() statements.
-*/
-static int debugMutexHeld(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- return p==0 || p->cnt>0;
-}
-static int debugMutexNotheld(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- return p==0 || p->cnt==0;
-}
-
-/*
-** Initialize and deinitialize the mutex subsystem.
-*/
-static int debugMutexInit(void){ return SQLITE_OK; }
-static int debugMutexEnd(void){ return SQLITE_OK; }
-
-/*
-** The sqlite3_mutex_alloc() routine allocates a new
-** mutex and returns a pointer to it. If it returns NULL
-** that means that a mutex could not be allocated.
-*/
-static sqlite3_mutex *debugMutexAlloc(int id){
- static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1];
- sqlite3_debug_mutex *pNew = 0;
- switch( id ){
- case SQLITE_MUTEX_FAST:
- case SQLITE_MUTEX_RECURSIVE: {
- pNew = sqlite3Malloc(sizeof(*pNew));
- if( pNew ){
- pNew->id = id;
- pNew->cnt = 0;
- }
- break;
- }
- default: {
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( id-2<0 || id-2>=ArraySize(aStatic) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- pNew = &aStatic[id-2];
- pNew->id = id;
- break;
- }
- }
- return (sqlite3_mutex*)pNew;
-}
-
-/*
-** This routine deallocates a previously allocated mutex.
-*/
-static void debugMutexFree(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- assert( p->cnt==0 );
- if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){
- sqlite3_free(p);
- }else{
-#ifdef SQLITE_ENABLE_API_ARMOR
- (void)SQLITE_MISUSE_BKPT;
-#endif
- }
-}
-
-/*
-** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
-** to enter a mutex. If another thread is already within the mutex,
-** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
-** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
-** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
-** be entered multiple times by the same thread. In such cases the,
-** mutex must be exited an equal number of times before another thread
-** can enter. If the same thread tries to enter any other kind of mutex
-** more than once, the behavior is undefined.
-*/
-static void debugMutexEnter(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
- p->cnt++;
-}
-static int debugMutexTry(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
- p->cnt++;
- return SQLITE_OK;
-}
-
-/*
-** The sqlite3_mutex_leave() routine exits a mutex that was
-** previously entered by the same thread. The behavior
-** is undefined if the mutex is not currently entered or
-** is not currently allocated. SQLite will never do either.
-*/
-static void debugMutexLeave(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- assert( debugMutexHeld(pX) );
- p->cnt--;
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
-}
-
-sqlite3_mutex_methods const *sqlite3NoopMutex(void){
- static const sqlite3_mutex_methods sMutex = {
- debugMutexInit,
- debugMutexEnd,
- debugMutexAlloc,
- debugMutexFree,
- debugMutexEnter,
- debugMutexTry,
- debugMutexLeave,
-
- debugMutexHeld,
- debugMutexNotheld
- };
-
- return &sMutex;
-}
-#endif /* SQLITE_DEBUG */
-
-/*
-** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
-** is used regardless of the run-time threadsafety setting.
-*/
-#ifdef SQLITE_MUTEX_NOOP
-sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
- return sqlite3NoopMutex();
-}
-#endif /* defined(SQLITE_MUTEX_NOOP) */
-#endif /* !defined(SQLITE_MUTEX_OMIT) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_unix.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_unix.c
deleted file mode 100644
index 9282d28016e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_unix.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
-** 2007 August 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 contains the C functions that implement mutexes for pthreads
-*/
-#include "sqliteInt.h"
-
-/*
-** The code in this file is only used if we are compiling threadsafe
-** under unix with pthreads.
-**
-** Note that this implementation requires a version of pthreads that
-** supports recursive mutexes.
-*/
-#ifdef SQLITE_MUTEX_PTHREADS
-
-#include <pthread.h>
-
-/*
-** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
-** are necessary under two condidtions: (1) Debug builds and (2) using
-** home-grown mutexes. Encapsulate these conditions into a single #define.
-*/
-#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
-# define SQLITE_MUTEX_NREF 1
-#else
-# define SQLITE_MUTEX_NREF 0
-#endif
-
-/*
-** Each recursive mutex is an instance of the following structure.
-*/
-struct sqlite3_mutex {
- pthread_mutex_t mutex; /* Mutex controlling the lock */
-#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
- int id; /* Mutex type */
-#endif
-#if SQLITE_MUTEX_NREF
- volatile int nRef; /* Number of entrances */
- volatile pthread_t owner; /* Thread that is within this mutex */
- int trace; /* True to trace changes */
-#endif
-};
-#if SQLITE_MUTEX_NREF
-# define SQLITE3_MUTEX_INITIALIZER(id) \
- {PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0}
-#elif defined(SQLITE_ENABLE_API_ARMOR)
-# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id }
-#else
-#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER }
-#endif
-
-/*
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-** intended for use only inside assert() statements. On some platforms,
-** there might be race conditions that can cause these routines to
-** deliver incorrect results. In particular, if pthread_equal() is
-** not an atomic operation, then these routines might delivery
-** incorrect results. On most platforms, pthread_equal() is a
-** comparison of two integers and is therefore atomic. But we are
-** told that HPUX is not such a platform. If so, then these routines
-** will not always work correctly on HPUX.
-**
-** On those platforms where pthread_equal() is not atomic, SQLite
-** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
-** make sure no assert() statements are evaluated and hence these
-** routines are never called.
-*/
-#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
-static int pthreadMutexHeld(sqlite3_mutex *p){
- return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
-}
-static int pthreadMutexNotheld(sqlite3_mutex *p){
- return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
-}
-#endif
-
-/*
-** Try to provide a memory barrier operation, needed for initialization
-** and also for the implementation of xShmBarrier in the VFS in cases
-** where SQLite is compiled without mutexes.
-*/
-void sqlite3MemoryBarrier(void){
-#if defined(SQLITE_MEMORY_BARRIER)
- SQLITE_MEMORY_BARRIER;
-#elif defined(__GNUC__) && GCC_VERSION>=4001000
- __sync_synchronize();
-#endif
-}
-
-/*
-** Initialize and deinitialize the mutex subsystem.
-*/
-static int pthreadMutexInit(void){ return SQLITE_OK; }
-static int pthreadMutexEnd(void){ return SQLITE_OK; }
-
-/*
-** The sqlite3_mutex_alloc() routine allocates a new
-** mutex and returns a pointer to it. If it returns NULL
-** that means that a mutex could not be allocated. SQLite
-** will unwind its stack and return an error. The argument
-** to sqlite3_mutex_alloc() is one of these integer constants:
-**
-** <ul>
-** <li> SQLITE_MUTEX_FAST
-** <li> SQLITE_MUTEX_RECURSIVE
-** <li> SQLITE_MUTEX_STATIC_MASTER
-** <li> SQLITE_MUTEX_STATIC_MEM
-** <li> SQLITE_MUTEX_STATIC_OPEN
-** <li> SQLITE_MUTEX_STATIC_PRNG
-** <li> SQLITE_MUTEX_STATIC_LRU
-** <li> SQLITE_MUTEX_STATIC_PMEM
-** <li> SQLITE_MUTEX_STATIC_APP1
-** <li> SQLITE_MUTEX_STATIC_APP2
-** <li> SQLITE_MUTEX_STATIC_APP3
-** <li> SQLITE_MUTEX_STATIC_VFS1
-** <li> SQLITE_MUTEX_STATIC_VFS2
-** <li> SQLITE_MUTEX_STATIC_VFS3
-** </ul>
-**
-** The first two constants cause sqlite3_mutex_alloc() to create
-** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
-** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
-** The mutex implementation does not need to make a distinction
-** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
-** not want to. But SQLite will only request a recursive mutex in
-** cases where it really needs one. If a faster non-recursive mutex
-** implementation is available on the host platform, the mutex subsystem
-** might return such a mutex in response to SQLITE_MUTEX_FAST.
-**
-** The other allowed parameters to sqlite3_mutex_alloc() each return
-** a pointer to a static preexisting mutex. Six static mutexes are
-** used by the current version of SQLite. Future versions of SQLite
-** may add additional static mutexes. Static mutexes are for internal
-** use by SQLite only. Applications that use SQLite mutexes should
-** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
-** SQLITE_MUTEX_RECURSIVE.
-**
-** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
-** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call. But for the static
-** mutex types, the same mutex is returned on every call that has
-** the same type number.
-*/
-static sqlite3_mutex *pthreadMutexAlloc(int iType){
- static sqlite3_mutex staticMutexes[] = {
- SQLITE3_MUTEX_INITIALIZER(2),
- SQLITE3_MUTEX_INITIALIZER(3),
- SQLITE3_MUTEX_INITIALIZER(4),
- SQLITE3_MUTEX_INITIALIZER(5),
- SQLITE3_MUTEX_INITIALIZER(6),
- SQLITE3_MUTEX_INITIALIZER(7),
- SQLITE3_MUTEX_INITIALIZER(8),
- SQLITE3_MUTEX_INITIALIZER(9),
- SQLITE3_MUTEX_INITIALIZER(10),
- SQLITE3_MUTEX_INITIALIZER(11),
- SQLITE3_MUTEX_INITIALIZER(12),
- SQLITE3_MUTEX_INITIALIZER(13)
- };
- sqlite3_mutex *p;
- switch( iType ){
- case SQLITE_MUTEX_RECURSIVE: {
- p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- /* If recursive mutexes are not available, we will have to
- ** build our own. See below. */
- pthread_mutex_init(&p->mutex, 0);
-#else
- /* Use a recursive mutex if it is available */
- pthread_mutexattr_t recursiveAttr;
- pthread_mutexattr_init(&recursiveAttr);
- pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&p->mutex, &recursiveAttr);
- pthread_mutexattr_destroy(&recursiveAttr);
-#endif
-#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
- p->id = SQLITE_MUTEX_RECURSIVE;
-#endif
- }
- break;
- }
- case SQLITE_MUTEX_FAST: {
- p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
- pthread_mutex_init(&p->mutex, 0);
-#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
- p->id = SQLITE_MUTEX_FAST;
-#endif
- }
- break;
- }
- default: {
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- p = &staticMutexes[iType-2];
- break;
- }
- }
-#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
- assert( p==0 || p->id==iType );
-#endif
- return p;
-}
-
-
-/*
-** This routine deallocates a previously
-** allocated mutex. SQLite is careful to deallocate every
-** mutex that it allocates.
-*/
-static void pthreadMutexFree(sqlite3_mutex *p){
- assert( p->nRef==0 );
-#if SQLITE_ENABLE_API_ARMOR
- if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE )
-#endif
- {
- pthread_mutex_destroy(&p->mutex);
- sqlite3_free(p);
- }
-#ifdef SQLITE_ENABLE_API_ARMOR
- else{
- (void)SQLITE_MISUSE_BKPT;
- }
-#endif
-}
-
-/*
-** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
-** to enter a mutex. If another thread is already within the mutex,
-** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
-** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
-** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
-** be entered multiple times by the same thread. In such cases the,
-** mutex must be exited an equal number of times before another thread
-** can enter. If the same thread tries to enter any other kind of mutex
-** more than once, the behavior is undefined.
-*/
-static void pthreadMutexEnter(sqlite3_mutex *p){
- assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
-
-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- /* If recursive mutexes are not available, then we have to grow
- ** our own. This implementation assumes that pthread_equal()
- ** is atomic - that it cannot be deceived into thinking self
- ** and p->owner are equal if p->owner changes between two values
- ** that are not equal to self while the comparison is taking place.
- ** This implementation also assumes a coherent cache - that
- ** separate processes cannot read different values from the same
- ** address at the same time. If either of these two conditions
- ** are not met, then the mutexes will fail and problems will result.
- */
- {
- pthread_t self = pthread_self();
- if( p->nRef>0 && pthread_equal(p->owner, self) ){
- p->nRef++;
- }else{
- pthread_mutex_lock(&p->mutex);
- assert( p->nRef==0 );
- p->owner = self;
- p->nRef = 1;
- }
- }
-#else
- /* Use the built-in recursive mutexes if they are available.
- */
- pthread_mutex_lock(&p->mutex);
-#if SQLITE_MUTEX_NREF
- assert( p->nRef>0 || p->owner==0 );
- p->owner = pthread_self();
- p->nRef++;
-#endif
-#endif
-
-#ifdef SQLITE_DEBUG
- if( p->trace ){
- printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
- }
-#endif
-}
-static int pthreadMutexTry(sqlite3_mutex *p){
- int rc;
- assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
-
-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- /* If recursive mutexes are not available, then we have to grow
- ** our own. This implementation assumes that pthread_equal()
- ** is atomic - that it cannot be deceived into thinking self
- ** and p->owner are equal if p->owner changes between two values
- ** that are not equal to self while the comparison is taking place.
- ** This implementation also assumes a coherent cache - that
- ** separate processes cannot read different values from the same
- ** address at the same time. If either of these two conditions
- ** are not met, then the mutexes will fail and problems will result.
- */
- {
- pthread_t self = pthread_self();
- if( p->nRef>0 && pthread_equal(p->owner, self) ){
- p->nRef++;
- rc = SQLITE_OK;
- }else if( pthread_mutex_trylock(&p->mutex)==0 ){
- assert( p->nRef==0 );
- p->owner = self;
- p->nRef = 1;
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_BUSY;
- }
- }
-#else
- /* Use the built-in recursive mutexes if they are available.
- */
- if( pthread_mutex_trylock(&p->mutex)==0 ){
-#if SQLITE_MUTEX_NREF
- p->owner = pthread_self();
- p->nRef++;
-#endif
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_BUSY;
- }
-#endif
-
-#ifdef SQLITE_DEBUG
- if( rc==SQLITE_OK && p->trace ){
- printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
- }
-#endif
- return rc;
-}
-
-/*
-** The sqlite3_mutex_leave() routine exits a mutex that was
-** previously entered by the same thread. The behavior
-** is undefined if the mutex is not currently entered or
-** is not currently allocated. SQLite will never do either.
-*/
-static void pthreadMutexLeave(sqlite3_mutex *p){
- assert( pthreadMutexHeld(p) );
-#if SQLITE_MUTEX_NREF
- p->nRef--;
- if( p->nRef==0 ) p->owner = 0;
-#endif
- assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
-
-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- if( p->nRef==0 ){
- pthread_mutex_unlock(&p->mutex);
- }
-#else
- pthread_mutex_unlock(&p->mutex);
-#endif
-
-#ifdef SQLITE_DEBUG
- if( p->trace ){
- printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
- }
-#endif
-}
-
-sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
- static const sqlite3_mutex_methods sMutex = {
- pthreadMutexInit,
- pthreadMutexEnd,
- pthreadMutexAlloc,
- pthreadMutexFree,
- pthreadMutexEnter,
- pthreadMutexTry,
- pthreadMutexLeave,
-#ifdef SQLITE_DEBUG
- pthreadMutexHeld,
- pthreadMutexNotheld
-#else
- 0,
- 0
-#endif
- };
-
- return &sMutex;
-}
-
-#endif /* SQLITE_MUTEX_PTHREADS */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_w32.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_w32.c
deleted file mode 100644
index 8a8ae289bac..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/mutex_w32.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
-** 2007 August 14
-**
-** 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 contains the C functions that implement mutexes for Win32.
-*/
-#include "sqliteInt.h"
-
-#if SQLITE_OS_WIN
-/*
-** Include code that is common to all os_*.c files
-*/
-#include "os_common.h"
-
-/*
-** Include the header file for the Windows VFS.
-*/
-#include "os_win.h"
-#endif
-
-/*
-** The code in this file is only used if we are compiling multithreaded
-** on a Win32 system.
-*/
-#ifdef SQLITE_MUTEX_W32
-
-/*
-** Each recursive mutex is an instance of the following structure.
-*/
-struct sqlite3_mutex {
- CRITICAL_SECTION mutex; /* Mutex controlling the lock */
- int id; /* Mutex type */
-#ifdef SQLITE_DEBUG
- volatile int nRef; /* Number of enterances */
- volatile DWORD owner; /* Thread holding this mutex */
- volatile LONG trace; /* True to trace changes */
-#endif
-};
-
-/*
-** These are the initializer values used when declaring a "static" mutex
-** on Win32. It should be noted that all mutexes require initialization
-** on the Win32 platform.
-*/
-#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
-
-#ifdef SQLITE_DEBUG
-#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \
- 0L, (DWORD)0, 0 }
-#else
-#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }
-#endif
-
-#ifdef SQLITE_DEBUG
-/*
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-** intended for use only inside assert() statements.
-*/
-static int winMutexHeld(sqlite3_mutex *p){
- return p->nRef!=0 && p->owner==GetCurrentThreadId();
-}
-
-static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
- return p->nRef==0 || p->owner!=tid;
-}
-
-static int winMutexNotheld(sqlite3_mutex *p){
- DWORD tid = GetCurrentThreadId();
- return winMutexNotheld2(p, tid);
-}
-#endif
-
-/*
-** Try to provide a memory barrier operation, needed for initialization
-** and also for the xShmBarrier method of the VFS in cases when SQLite is
-** compiled without mutexes (SQLITE_THREADSAFE=0).
-*/
-void sqlite3MemoryBarrier(void){
-#if defined(SQLITE_MEMORY_BARRIER)
- SQLITE_MEMORY_BARRIER;
-#elif defined(__GNUC__)
- __sync_synchronize();
-#elif MSVC_VERSION>=1300
- _ReadWriteBarrier();
-#elif defined(MemoryBarrier)
- MemoryBarrier();
-#endif
-}
-
-/*
-** Initialize and deinitialize the mutex subsystem.
-*/
-static sqlite3_mutex winMutex_staticMutexes[] = {
- SQLITE3_MUTEX_INITIALIZER(2),
- SQLITE3_MUTEX_INITIALIZER(3),
- SQLITE3_MUTEX_INITIALIZER(4),
- SQLITE3_MUTEX_INITIALIZER(5),
- SQLITE3_MUTEX_INITIALIZER(6),
- SQLITE3_MUTEX_INITIALIZER(7),
- SQLITE3_MUTEX_INITIALIZER(8),
- SQLITE3_MUTEX_INITIALIZER(9),
- SQLITE3_MUTEX_INITIALIZER(10),
- SQLITE3_MUTEX_INITIALIZER(11),
- SQLITE3_MUTEX_INITIALIZER(12),
- SQLITE3_MUTEX_INITIALIZER(13)
-};
-
-static int winMutex_isInit = 0;
-static int winMutex_isNt = -1; /* <0 means "need to query" */
-
-/* As the winMutexInit() and winMutexEnd() functions are called as part
-** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
-** "interlocked" magic used here is probably not strictly necessary.
-*/
-static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
-
-int sqlite3_win32_is_nt(void); /* os_win.c */
-void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
-
-static int winMutexInit(void){
- /* The first to increment to 1 does actual initialization */
- if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
- int i;
- for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
-#if SQLITE_OS_WINRT
- InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
-#else
- InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
-#endif
- }
- winMutex_isInit = 1;
- }else{
- /* Another thread is (in the process of) initializing the static
- ** mutexes */
- while( !winMutex_isInit ){
- sqlite3_win32_sleep(1);
- }
- }
- return SQLITE_OK;
-}
-
-static int winMutexEnd(void){
- /* The first to decrement to 0 does actual shutdown
- ** (which should be the last to shutdown.) */
- if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
- if( winMutex_isInit==1 ){
- int i;
- for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
- DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
- }
- winMutex_isInit = 0;
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** The sqlite3_mutex_alloc() routine allocates a new
-** mutex and returns a pointer to it. If it returns NULL
-** that means that a mutex could not be allocated. SQLite
-** will unwind its stack and return an error. The argument
-** to sqlite3_mutex_alloc() is one of these integer constants:
-**
-** <ul>
-** <li> SQLITE_MUTEX_FAST
-** <li> SQLITE_MUTEX_RECURSIVE
-** <li> SQLITE_MUTEX_STATIC_MASTER
-** <li> SQLITE_MUTEX_STATIC_MEM
-** <li> SQLITE_MUTEX_STATIC_OPEN
-** <li> SQLITE_MUTEX_STATIC_PRNG
-** <li> SQLITE_MUTEX_STATIC_LRU
-** <li> SQLITE_MUTEX_STATIC_PMEM
-** <li> SQLITE_MUTEX_STATIC_APP1
-** <li> SQLITE_MUTEX_STATIC_APP2
-** <li> SQLITE_MUTEX_STATIC_APP3
-** <li> SQLITE_MUTEX_STATIC_VFS1
-** <li> SQLITE_MUTEX_STATIC_VFS2
-** <li> SQLITE_MUTEX_STATIC_VFS3
-** </ul>
-**
-** The first two constants cause sqlite3_mutex_alloc() to create
-** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
-** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
-** The mutex implementation does not need to make a distinction
-** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
-** not want to. But SQLite will only request a recursive mutex in
-** cases where it really needs one. If a faster non-recursive mutex
-** implementation is available on the host platform, the mutex subsystem
-** might return such a mutex in response to SQLITE_MUTEX_FAST.
-**
-** The other allowed parameters to sqlite3_mutex_alloc() each return
-** a pointer to a static preexisting mutex. Six static mutexes are
-** used by the current version of SQLite. Future versions of SQLite
-** may add additional static mutexes. Static mutexes are for internal
-** use by SQLite only. Applications that use SQLite mutexes should
-** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
-** SQLITE_MUTEX_RECURSIVE.
-**
-** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
-** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call. But for the static
-** mutex types, the same mutex is returned on every call that has
-** the same type number.
-*/
-static sqlite3_mutex *winMutexAlloc(int iType){
- sqlite3_mutex *p;
-
- switch( iType ){
- case SQLITE_MUTEX_FAST:
- case SQLITE_MUTEX_RECURSIVE: {
- p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
- p->id = iType;
-#ifdef SQLITE_DEBUG
-#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
- p->trace = 1;
-#endif
-#endif
-#if SQLITE_OS_WINRT
- InitializeCriticalSectionEx(&p->mutex, 0, 0);
-#else
- InitializeCriticalSection(&p->mutex);
-#endif
- }
- break;
- }
- default: {
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- p = &winMutex_staticMutexes[iType-2];
-#ifdef SQLITE_DEBUG
-#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
- InterlockedCompareExchange(&p->trace, 1, 0);
-#endif
-#endif
- break;
- }
- }
- assert( p==0 || p->id==iType );
- return p;
-}
-
-
-/*
-** This routine deallocates a previously
-** allocated mutex. SQLite is careful to deallocate every
-** mutex that it allocates.
-*/
-static void winMutexFree(sqlite3_mutex *p){
- assert( p );
- assert( p->nRef==0 && p->owner==0 );
- if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
- DeleteCriticalSection(&p->mutex);
- sqlite3_free(p);
- }else{
-#ifdef SQLITE_ENABLE_API_ARMOR
- (void)SQLITE_MISUSE_BKPT;
-#endif
- }
-}
-
-/*
-** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
-** to enter a mutex. If another thread is already within the mutex,
-** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
-** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
-** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
-** be entered multiple times by the same thread. In such cases the,
-** mutex must be exited an equal number of times before another thread
-** can enter. If the same thread tries to enter any other kind of mutex
-** more than once, the behavior is undefined.
-*/
-static void winMutexEnter(sqlite3_mutex *p){
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- DWORD tid = GetCurrentThreadId();
-#endif
-#ifdef SQLITE_DEBUG
- assert( p );
- assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
-#else
- assert( p );
-#endif
- assert( winMutex_isInit==1 );
- EnterCriticalSection(&p->mutex);
-#ifdef SQLITE_DEBUG
- assert( p->nRef>0 || p->owner==0 );
- p->owner = tid;
- p->nRef++;
- if( p->trace ){
- OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
- tid, p->id, p, p->trace, p->nRef));
- }
-#endif
-}
-
-static int winMutexTry(sqlite3_mutex *p){
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- DWORD tid = GetCurrentThreadId();
-#endif
- int rc = SQLITE_BUSY;
- assert( p );
- assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
- /*
- ** The sqlite3_mutex_try() routine is very rarely used, and when it
- ** is used it is merely an optimization. So it is OK for it to always
- ** fail.
- **
- ** The TryEnterCriticalSection() interface is only available on WinNT.
- ** And some windows compilers complain if you try to use it without
- ** first doing some #defines that prevent SQLite from building on Win98.
- ** For that reason, we will omit this optimization for now. See
- ** ticket #2685.
- */
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
- assert( winMutex_isInit==1 );
- assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
- if( winMutex_isNt<0 ){
- winMutex_isNt = sqlite3_win32_is_nt();
- }
- assert( winMutex_isNt==0 || winMutex_isNt==1 );
- if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
-#ifdef SQLITE_DEBUG
- p->owner = tid;
- p->nRef++;
-#endif
- rc = SQLITE_OK;
- }
-#else
- UNUSED_PARAMETER(p);
-#endif
-#ifdef SQLITE_DEBUG
- if( p->trace ){
- OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
- tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
- }
-#endif
- return rc;
-}
-
-/*
-** The sqlite3_mutex_leave() routine exits a mutex that was
-** previously entered by the same thread. The behavior
-** is undefined if the mutex is not currently entered or
-** is not currently allocated. SQLite will never do either.
-*/
-static void winMutexLeave(sqlite3_mutex *p){
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- DWORD tid = GetCurrentThreadId();
-#endif
- assert( p );
-#ifdef SQLITE_DEBUG
- assert( p->nRef>0 );
- assert( p->owner==tid );
- p->nRef--;
- if( p->nRef==0 ) p->owner = 0;
- assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
-#endif
- assert( winMutex_isInit==1 );
- LeaveCriticalSection(&p->mutex);
-#ifdef SQLITE_DEBUG
- if( p->trace ){
- OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
- tid, p->id, p, p->trace, p->nRef));
- }
-#endif
-}
-
-sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
- static const sqlite3_mutex_methods sMutex = {
- winMutexInit,
- winMutexEnd,
- winMutexAlloc,
- winMutexFree,
- winMutexEnter,
- winMutexTry,
- winMutexLeave,
-#ifdef SQLITE_DEBUG
- winMutexHeld,
- winMutexNotheld
-#else
- 0,
- 0
-#endif
- };
- return &sMutex;
-}
-
-#endif /* SQLITE_MUTEX_W32 */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/notify.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/notify.c
deleted file mode 100644
index 8137226f35d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/notify.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
-** 2009 March 3
-**
-** 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 contains the implementation of the sqlite3_unlock_notify()
-** API method and its associated functionality.
-*/
-#include "sqliteInt.h"
-#include "btreeInt.h"
-
-/* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */
-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
-
-/*
-** Public interfaces:
-**
-** sqlite3ConnectionBlocked()
-** sqlite3ConnectionUnlocked()
-** sqlite3ConnectionClosed()
-** sqlite3_unlock_notify()
-*/
-
-#define assertMutexHeld() \
- assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) )
-
-/*
-** Head of a linked list of all sqlite3 objects created by this process
-** for which either sqlite3.pBlockingConnection or sqlite3.pUnlockConnection
-** is not NULL. This variable may only accessed while the STATIC_MASTER
-** mutex is held.
-*/
-static sqlite3 *SQLITE_WSD sqlite3BlockedList = 0;
-
-#ifndef NDEBUG
-/*
-** This function is a complex assert() that verifies the following
-** properties of the blocked connections list:
-**
-** 1) Each entry in the list has a non-NULL value for either
-** pUnlockConnection or pBlockingConnection, or both.
-**
-** 2) All entries in the list that share a common value for
-** xUnlockNotify are grouped together.
-**
-** 3) If the argument db is not NULL, then none of the entries in the
-** blocked connections list have pUnlockConnection or pBlockingConnection
-** set to db. This is used when closing connection db.
-*/
-static void checkListProperties(sqlite3 *db){
- sqlite3 *p;
- for(p=sqlite3BlockedList; p; p=p->pNextBlocked){
- int seen = 0;
- sqlite3 *p2;
-
- /* Verify property (1) */
- assert( p->pUnlockConnection || p->pBlockingConnection );
-
- /* Verify property (2) */
- for(p2=sqlite3BlockedList; p2!=p; p2=p2->pNextBlocked){
- if( p2->xUnlockNotify==p->xUnlockNotify ) seen = 1;
- assert( p2->xUnlockNotify==p->xUnlockNotify || !seen );
- assert( db==0 || p->pUnlockConnection!=db );
- assert( db==0 || p->pBlockingConnection!=db );
- }
- }
-}
-#else
-# define checkListProperties(x)
-#endif
-
-/*
-** Remove connection db from the blocked connections list. If connection
-** db is not currently a part of the list, this function is a no-op.
-*/
-static void removeFromBlockedList(sqlite3 *db){
- sqlite3 **pp;
- assertMutexHeld();
- for(pp=&sqlite3BlockedList; *pp; pp = &(*pp)->pNextBlocked){
- if( *pp==db ){
- *pp = (*pp)->pNextBlocked;
- break;
- }
- }
-}
-
-/*
-** Add connection db to the blocked connections list. It is assumed
-** that it is not already a part of the list.
-*/
-static void addToBlockedList(sqlite3 *db){
- sqlite3 **pp;
- assertMutexHeld();
- for(
- pp=&sqlite3BlockedList;
- *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify;
- pp=&(*pp)->pNextBlocked
- );
- db->pNextBlocked = *pp;
- *pp = db;
-}
-
-/*
-** Obtain the STATIC_MASTER mutex.
-*/
-static void enterMutex(void){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- checkListProperties(0);
-}
-
-/*
-** Release the STATIC_MASTER mutex.
-*/
-static void leaveMutex(void){
- assertMutexHeld();
- checkListProperties(0);
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-}
-
-/*
-** Register an unlock-notify callback.
-**
-** This is called after connection "db" has attempted some operation
-** but has received an SQLITE_LOCKED error because another connection
-** (call it pOther) in the same process was busy using the same shared
-** cache. pOther is found by looking at db->pBlockingConnection.
-**
-** If there is no blocking connection, the callback is invoked immediately,
-** before this routine returns.
-**
-** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate
-** a deadlock.
-**
-** Otherwise, make arrangements to invoke xNotify when pOther drops
-** its locks.
-**
-** Each call to this routine overrides any prior callbacks registered
-** on the same "db". If xNotify==0 then any prior callbacks are immediately
-** cancelled.
-*/
-int sqlite3_unlock_notify(
- sqlite3 *db,
- void (*xNotify)(void **, int),
- void *pArg
-){
- int rc = SQLITE_OK;
-
- sqlite3_mutex_enter(db->mutex);
- enterMutex();
-
- if( xNotify==0 ){
- removeFromBlockedList(db);
- db->pBlockingConnection = 0;
- db->pUnlockConnection = 0;
- db->xUnlockNotify = 0;
- db->pUnlockArg = 0;
- }else if( 0==db->pBlockingConnection ){
- /* The blocking transaction has been concluded. Or there never was a
- ** blocking transaction. In either case, invoke the notify callback
- ** immediately.
- */
- xNotify(&pArg, 1);
- }else{
- sqlite3 *p;
-
- for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection){}
- if( p ){
- rc = SQLITE_LOCKED; /* Deadlock detected. */
- }else{
- db->pUnlockConnection = db->pBlockingConnection;
- db->xUnlockNotify = xNotify;
- db->pUnlockArg = pArg;
- removeFromBlockedList(db);
- addToBlockedList(db);
- }
- }
-
- leaveMutex();
- assert( !db->mallocFailed );
- sqlite3ErrorWithMsg(db, rc, (rc?"database is deadlocked":0));
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** This function is called while stepping or preparing a statement
-** associated with connection db. The operation will return SQLITE_LOCKED
-** to the user because it requires a lock that will not be available
-** until connection pBlocker concludes its current transaction.
-*/
-void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){
- enterMutex();
- if( db->pBlockingConnection==0 && db->pUnlockConnection==0 ){
- addToBlockedList(db);
- }
- db->pBlockingConnection = pBlocker;
- leaveMutex();
-}
-
-/*
-** This function is called when
-** the transaction opened by database db has just finished. Locks held
-** by database connection db have been released.
-**
-** This function loops through each entry in the blocked connections
-** list and does the following:
-**
-** 1) If the sqlite3.pBlockingConnection member of a list entry is
-** set to db, then set pBlockingConnection=0.
-**
-** 2) If the sqlite3.pUnlockConnection member of a list entry is
-** set to db, then invoke the configured unlock-notify callback and
-** set pUnlockConnection=0.
-**
-** 3) If the two steps above mean that pBlockingConnection==0 and
-** pUnlockConnection==0, remove the entry from the blocked connections
-** list.
-*/
-void sqlite3ConnectionUnlocked(sqlite3 *db){
- void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */
- int nArg = 0; /* Number of entries in aArg[] */
- sqlite3 **pp; /* Iterator variable */
- void **aArg; /* Arguments to the unlock callback */
- void **aDyn = 0; /* Dynamically allocated space for aArg[] */
- void *aStatic[16]; /* Starter space for aArg[]. No malloc required */
-
- aArg = aStatic;
- enterMutex(); /* Enter STATIC_MASTER mutex */
-
- /* This loop runs once for each entry in the blocked-connections list. */
- for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){
- sqlite3 *p = *pp;
-
- /* Step 1. */
- if( p->pBlockingConnection==db ){
- p->pBlockingConnection = 0;
- }
-
- /* Step 2. */
- if( p->pUnlockConnection==db ){
- assert( p->xUnlockNotify );
- if( p->xUnlockNotify!=xUnlockNotify && nArg!=0 ){
- xUnlockNotify(aArg, nArg);
- nArg = 0;
- }
-
- sqlite3BeginBenignMalloc();
- assert( aArg==aDyn || (aDyn==0 && aArg==aStatic) );
- assert( nArg<=(int)ArraySize(aStatic) || aArg==aDyn );
- if( (!aDyn && nArg==(int)ArraySize(aStatic))
- || (aDyn && nArg==(int)(sqlite3MallocSize(aDyn)/sizeof(void*)))
- ){
- /* The aArg[] array needs to grow. */
- void **pNew = (void **)sqlite3Malloc(nArg*sizeof(void *)*2);
- if( pNew ){
- memcpy(pNew, aArg, nArg*sizeof(void *));
- sqlite3_free(aDyn);
- aDyn = aArg = pNew;
- }else{
- /* This occurs when the array of context pointers that need to
- ** be passed to the unlock-notify callback is larger than the
- ** aStatic[] array allocated on the stack and the attempt to
- ** allocate a larger array from the heap has failed.
- **
- ** This is a difficult situation to handle. Returning an error
- ** code to the caller is insufficient, as even if an error code
- ** is returned the transaction on connection db will still be
- ** closed and the unlock-notify callbacks on blocked connections
- ** will go unissued. This might cause the application to wait
- ** indefinitely for an unlock-notify callback that will never
- ** arrive.
- **
- ** Instead, invoke the unlock-notify callback with the context
- ** array already accumulated. We can then clear the array and
- ** begin accumulating any further context pointers without
- ** requiring any dynamic allocation. This is sub-optimal because
- ** it means that instead of one callback with a large array of
- ** context pointers the application will receive two or more
- ** callbacks with smaller arrays of context pointers, which will
- ** reduce the applications ability to prioritize multiple
- ** connections. But it is the best that can be done under the
- ** circumstances.
- */
- xUnlockNotify(aArg, nArg);
- nArg = 0;
- }
- }
- sqlite3EndBenignMalloc();
-
- aArg[nArg++] = p->pUnlockArg;
- xUnlockNotify = p->xUnlockNotify;
- p->pUnlockConnection = 0;
- p->xUnlockNotify = 0;
- p->pUnlockArg = 0;
- }
-
- /* Step 3. */
- if( p->pBlockingConnection==0 && p->pUnlockConnection==0 ){
- /* Remove connection p from the blocked connections list. */
- *pp = p->pNextBlocked;
- p->pNextBlocked = 0;
- }else{
- pp = &p->pNextBlocked;
- }
- }
-
- if( nArg!=0 ){
- xUnlockNotify(aArg, nArg);
- }
- sqlite3_free(aDyn);
- leaveMutex(); /* Leave STATIC_MASTER mutex */
-}
-
-/*
-** This is called when the database connection passed as an argument is
-** being closed. The connection is removed from the blocked list.
-*/
-void sqlite3ConnectionClosed(sqlite3 *db){
- sqlite3ConnectionUnlocked(db);
- enterMutex();
- removeFromBlockedList(db);
- checkListProperties(db);
- leaveMutex();
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/os.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/os.c
deleted file mode 100644
index 997f97121fd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/os.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
-** 2005 November 29
-**
-** 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 contains OS interface code that is common to all
-** architectures.
-*/
-#include "sqliteInt.h"
-
-/*
-** If we compile with the SQLITE_TEST macro set, then the following block
-** of code will give us the ability to simulate a disk I/O error. This
-** is used for testing the I/O recovery logic.
-*/
-#if defined(SQLITE_TEST)
-int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
-int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
-int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
-int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
-int sqlite3_io_error_benign = 0; /* True if errors are benign */
-int sqlite3_diskfull_pending = 0;
-int sqlite3_diskfull = 0;
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** When testing, also keep a count of the number of open files.
-*/
-#if defined(SQLITE_TEST)
-int sqlite3_open_file_count = 0;
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** The default SQLite sqlite3_vfs implementations do not allocate
-** memory (actually, os_unix.c allocates a small amount of memory
-** from within OsOpen()), but some third-party implementations may.
-** So we test the effects of a malloc() failing and the sqlite3OsXXX()
-** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
-**
-** The following functions are instrumented for malloc() failure
-** testing:
-**
-** sqlite3OsRead()
-** sqlite3OsWrite()
-** sqlite3OsSync()
-** sqlite3OsFileSize()
-** sqlite3OsLock()
-** sqlite3OsCheckReservedLock()
-** sqlite3OsFileControl()
-** sqlite3OsShmMap()
-** sqlite3OsOpen()
-** sqlite3OsDelete()
-** sqlite3OsAccess()
-** sqlite3OsFullPathname()
-**
-*/
-#if defined(SQLITE_TEST)
-int sqlite3_memdebug_vfs_oom_test = 1;
- #define DO_OS_MALLOC_TEST(x) \
- if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3JournalIsInMemory(x))) { \
- void *pTstAlloc = sqlite3Malloc(10); \
- if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \
- sqlite3_free(pTstAlloc); \
- }
-#else
- #define DO_OS_MALLOC_TEST(x)
-#endif
-
-/*
-** The following routines are convenience wrappers around methods
-** of the sqlite3_file object. This is mostly just syntactic sugar. All
-** of this would be completely automatic if SQLite were coded using
-** C++ instead of plain old C.
-*/
-void sqlite3OsClose(sqlite3_file *pId){
- if( pId->pMethods ){
- pId->pMethods->xClose(pId);
- pId->pMethods = 0;
- }
-}
-int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
- DO_OS_MALLOC_TEST(id);
- return id->pMethods->xRead(id, pBuf, amt, offset);
-}
-int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
- DO_OS_MALLOC_TEST(id);
- return id->pMethods->xWrite(id, pBuf, amt, offset);
-}
-int sqlite3OsTruncate(sqlite3_file *id, i64 size){
- return id->pMethods->xTruncate(id, size);
-}
-int sqlite3OsSync(sqlite3_file *id, int flags){
- DO_OS_MALLOC_TEST(id);
- return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;
-}
-int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
- DO_OS_MALLOC_TEST(id);
- return id->pMethods->xFileSize(id, pSize);
-}
-int sqlite3OsLock(sqlite3_file *id, int lockType){
- DO_OS_MALLOC_TEST(id);
- return id->pMethods->xLock(id, lockType);
-}
-int sqlite3OsUnlock(sqlite3_file *id, int lockType){
- return id->pMethods->xUnlock(id, lockType);
-}
-int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
- DO_OS_MALLOC_TEST(id);
- return id->pMethods->xCheckReservedLock(id, pResOut);
-}
-
-/*
-** Use sqlite3OsFileControl() when we are doing something that might fail
-** and we need to know about the failures. Use sqlite3OsFileControlHint()
-** when simply tossing information over the wall to the VFS and we do not
-** really care if the VFS receives and understands the information since it
-** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
-** routine has no return value since the return value would be meaningless.
-*/
-int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
- if( id->pMethods==0 ) return SQLITE_NOTFOUND;
-#ifdef SQLITE_TEST
- if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
- && op!=SQLITE_FCNTL_LOCK_TIMEOUT
- ){
- /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
- ** is using a regular VFS, it is called after the corresponding
- ** transaction has been committed. Injecting a fault at this point
- ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
- ** but the transaction is committed anyway.
- **
- ** The core must call OsFileControl() though, not OsFileControlHint(),
- ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
- ** means the commit really has failed and an error should be returned
- ** to the user. */
- DO_OS_MALLOC_TEST(id);
- }
-#endif
- return id->pMethods->xFileControl(id, op, pArg);
-}
-void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
- if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg);
-}
-
-int sqlite3OsSectorSize(sqlite3_file *id){
- int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
- return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
-}
-int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
- return id->pMethods->xDeviceCharacteristics(id);
-}
-#ifndef SQLITE_OMIT_WAL
-int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
- return id->pMethods->xShmLock(id, offset, n, flags);
-}
-void sqlite3OsShmBarrier(sqlite3_file *id){
- id->pMethods->xShmBarrier(id);
-}
-int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
- return id->pMethods->xShmUnmap(id, deleteFlag);
-}
-int sqlite3OsShmMap(
- sqlite3_file *id, /* Database file handle */
- int iPage,
- int pgsz,
- int bExtend, /* True to extend file if necessary */
- void volatile **pp /* OUT: Pointer to mapping */
-){
- DO_OS_MALLOC_TEST(id);
- return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
-}
-#endif /* SQLITE_OMIT_WAL */
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/* The real implementation of xFetch and xUnfetch */
-int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
- DO_OS_MALLOC_TEST(id);
- return id->pMethods->xFetch(id, iOff, iAmt, pp);
-}
-int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
- return id->pMethods->xUnfetch(id, iOff, p);
-}
-#else
-/* No-op stubs to use when memory-mapped I/O is disabled */
-int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
- *pp = 0;
- return SQLITE_OK;
-}
-int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
- return SQLITE_OK;
-}
-#endif
-
-/*
-** The next group of routines are convenience wrappers around the
-** VFS methods.
-*/
-int sqlite3OsOpen(
- sqlite3_vfs *pVfs,
- const char *zPath,
- sqlite3_file *pFile,
- int flags,
- int *pFlagsOut
-){
- int rc;
- DO_OS_MALLOC_TEST(0);
- /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
- ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
- ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
- ** reaching the VFS. */
- rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
- assert( rc==SQLITE_OK || pFile->pMethods==0 );
- return rc;
-}
-int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- DO_OS_MALLOC_TEST(0);
- assert( dirSync==0 || dirSync==1 );
- return pVfs->xDelete(pVfs, zPath, dirSync);
-}
-int sqlite3OsAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- DO_OS_MALLOC_TEST(0);
- return pVfs->xAccess(pVfs, zPath, flags, pResOut);
-}
-int sqlite3OsFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nPathOut,
- char *zPathOut
-){
- DO_OS_MALLOC_TEST(0);
- zPathOut[0] = 0;
- return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
-}
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return pVfs->xDlOpen(pVfs, zPath);
-}
-void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- pVfs->xDlError(pVfs, nByte, zBufOut);
-}
-void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
- return pVfs->xDlSym(pVfs, pHdle, zSym);
-}
-void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
- pVfs->xDlClose(pVfs, pHandle);
-}
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return pVfs->xRandomness(pVfs, nByte, zBufOut);
-}
-int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
- return pVfs->xSleep(pVfs, nMicro);
-}
-int sqlite3OsGetLastError(sqlite3_vfs *pVfs){
- return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0;
-}
-int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
- int rc;
- /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
- ** method to get the current date and time if that method is available
- ** (if iVersion is 2 or greater and the function pointer is not NULL) and
- ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
- ** unavailable.
- */
- if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
- rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
- }else{
- double r;
- rc = pVfs->xCurrentTime(pVfs, &r);
- *pTimeOut = (sqlite3_int64)(r*86400000.0);
- }
- return rc;
-}
-
-int sqlite3OsOpenMalloc(
- sqlite3_vfs *pVfs,
- const char *zFile,
- sqlite3_file **ppFile,
- int flags,
- int *pOutFlags
-){
- int rc;
- sqlite3_file *pFile;
- pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
- if( pFile ){
- rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
- if( rc!=SQLITE_OK ){
- sqlite3_free(pFile);
- }else{
- *ppFile = pFile;
- }
- }else{
- rc = SQLITE_NOMEM_BKPT;
- }
- return rc;
-}
-void sqlite3OsCloseFree(sqlite3_file *pFile){
- assert( pFile );
- sqlite3OsClose(pFile);
- sqlite3_free(pFile);
-}
-
-/*
-** This function is a wrapper around the OS specific implementation of
-** sqlite3_os_init(). The purpose of the wrapper is to provide the
-** ability to simulate a malloc failure, so that the handling of an
-** error in sqlite3_os_init() by the upper layers can be tested.
-*/
-int sqlite3OsInit(void){
- void *p = sqlite3_malloc(10);
- if( p==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3_free(p);
- return sqlite3_os_init();
-}
-
-/*
-** The list of all registered VFS implementations.
-*/
-static sqlite3_vfs * SQLITE_WSD vfsList = 0;
-#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
-
-/*
-** Locate a VFS by name. If no name is given, simply return the
-** first VFS on the list.
-*/
-sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
- sqlite3_vfs *pVfs = 0;
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex;
-#endif
-#ifndef SQLITE_OMIT_AUTOINIT
- int rc = sqlite3_initialize();
- if( rc ) return 0;
-#endif
-#if SQLITE_THREADSAFE
- mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
- sqlite3_mutex_enter(mutex);
- for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
- if( zVfs==0 ) break;
- if( strcmp(zVfs, pVfs->zName)==0 ) break;
- }
- sqlite3_mutex_leave(mutex);
- return pVfs;
-}
-
-/*
-** Unlink a VFS from the linked list
-*/
-static void vfsUnlink(sqlite3_vfs *pVfs){
- assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
- if( pVfs==0 ){
- /* No-op */
- }else if( vfsList==pVfs ){
- vfsList = pVfs->pNext;
- }else if( vfsList ){
- sqlite3_vfs *p = vfsList;
- while( p->pNext && p->pNext!=pVfs ){
- p = p->pNext;
- }
- if( p->pNext==pVfs ){
- p->pNext = pVfs->pNext;
- }
- }
-}
-
-/*
-** Register a VFS with the system. It is harmless to register the same
-** VFS multiple times. The new VFS becomes the default if makeDflt is
-** true.
-*/
-int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
- MUTEX_LOGIC(sqlite3_mutex *mutex;)
-#ifndef SQLITE_OMIT_AUTOINIT
- int rc = sqlite3_initialize();
- if( rc ) return rc;
-#endif
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
-#endif
-
- MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
- sqlite3_mutex_enter(mutex);
- vfsUnlink(pVfs);
- if( makeDflt || vfsList==0 ){
- pVfs->pNext = vfsList;
- vfsList = pVfs;
- }else{
- pVfs->pNext = vfsList->pNext;
- vfsList->pNext = pVfs;
- }
- assert(vfsList);
- sqlite3_mutex_leave(mutex);
- return SQLITE_OK;
-}
-
-/*
-** Unregister a VFS so that it is no longer accessible.
-*/
-int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
- sqlite3_mutex_enter(mutex);
- vfsUnlink(pVfs);
- sqlite3_mutex_leave(mutex);
- return SQLITE_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/os.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/os.h
deleted file mode 100644
index f841d6bab10..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/os.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
-** 2001 September 16
-**
-** 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 header file (together with is companion C source-code file
-** "os.c") attempt to abstract the underlying operating system so that
-** the SQLite library will work on both POSIX and windows systems.
-**
-** This header file is #include-ed by sqliteInt.h and thus ends up
-** being included by every source file.
-*/
-#ifndef _SQLITE_OS_H_
-#define _SQLITE_OS_H_
-
-/*
-** Attempt to automatically detect the operating system and setup the
-** necessary pre-processor macros for it.
-*/
-#include "os_setup.h"
-
-/* If the SET_FULLSYNC macro is not defined above, then make it
-** a no-op
-*/
-#ifndef SET_FULLSYNC
-# define SET_FULLSYNC(x,y)
-#endif
-
-/*
-** The default size of a disk sector
-*/
-#ifndef SQLITE_DEFAULT_SECTOR_SIZE
-# define SQLITE_DEFAULT_SECTOR_SIZE 4096
-#endif
-
-/*
-** Temporary files are named starting with this prefix followed by 16 random
-** alphanumeric characters, and no file extension. They are stored in the
-** OS's standard temporary file directory, and are deleted prior to exit.
-** If sqlite is being embedded in another program, you may wish to change the
-** prefix to reflect your program's name, so that if your program exits
-** prematurely, old temporary files can be easily identified. This can be done
-** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line.
-**
-** 2006-10-31: The default prefix used to be "sqlite_". But then
-** Mcafee started using SQLite in their anti-virus product and it
-** started putting files with the "sqlite" name in the c:/temp folder.
-** This annoyed many windows users. Those users would then do a
-** Google search for "sqlite", find the telephone numbers of the
-** developers and call to wake them up at night and complain.
-** For this reason, the default name prefix is changed to be "sqlite"
-** spelled backwards. So the temp files are still identified, but
-** anybody smart enough to figure out the code is also likely smart
-** enough to know that calling the developer will not help get rid
-** of the file.
-*/
-#ifndef SQLITE_TEMP_FILE_PREFIX
-# define SQLITE_TEMP_FILE_PREFIX "etilqs_"
-#endif
-
-/*
-** The following values may be passed as the second argument to
-** sqlite3OsLock(). The various locks exhibit the following semantics:
-**
-** SHARED: Any number of processes may hold a SHARED lock simultaneously.
-** RESERVED: A single process may hold a RESERVED lock on a file at
-** any time. Other processes may hold and obtain new SHARED locks.
-** PENDING: A single process may hold a PENDING lock on a file at
-** any one time. Existing SHARED locks may persist, but no new
-** SHARED locks may be obtained by other processes.
-** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
-**
-** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
-** process that requests an EXCLUSIVE lock may actually obtain a PENDING
-** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
-** sqlite3OsLock().
-*/
-#define NO_LOCK 0
-#define SHARED_LOCK 1
-#define RESERVED_LOCK 2
-#define PENDING_LOCK 3
-#define EXCLUSIVE_LOCK 4
-
-/*
-** File Locking Notes: (Mostly about windows but also some info for Unix)
-**
-** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
-** those functions are not available. So we use only LockFile() and
-** UnlockFile().
-**
-** LockFile() prevents not just writing but also reading by other processes.
-** A SHARED_LOCK is obtained by locking a single randomly-chosen
-** byte out of a specific range of bytes. The lock byte is obtained at
-** random so two separate readers can probably access the file at the
-** same time, unless they are unlucky and choose the same lock byte.
-** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
-** There can only be one writer. A RESERVED_LOCK is obtained by locking
-** a single byte of the file that is designated as the reserved lock byte.
-** A PENDING_LOCK is obtained by locking a designated byte different from
-** the RESERVED_LOCK byte.
-**
-** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
-** which means we can use reader/writer locks. When reader/writer locks
-** are used, the lock is placed on the same range of bytes that is used
-** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
-** will support two or more Win95 readers or two or more WinNT readers.
-** But a single Win95 reader will lock out all WinNT readers and a single
-** WinNT reader will lock out all other Win95 readers.
-**
-** The following #defines specify the range of bytes used for locking.
-** SHARED_SIZE is the number of bytes available in the pool from which
-** a random byte is selected for a shared lock. The pool of bytes for
-** shared locks begins at SHARED_FIRST.
-**
-** The same locking strategy and
-** byte ranges are used for Unix. This leaves open the possibility of having
-** clients on win95, winNT, and unix all talking to the same shared file
-** and all locking correctly. To do so would require that samba (or whatever
-** tool is being used for file sharing) implements locks correctly between
-** windows and unix. I'm guessing that isn't likely to happen, but by
-** using the same locking range we are at least open to the possibility.
-**
-** Locking in windows is manditory. For this reason, we cannot store
-** actual data in the bytes used for locking. The pager never allocates
-** the pages involved in locking therefore. SHARED_SIZE is selected so
-** that all locks will fit on a single page even at the minimum page size.
-** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE
-** is set high so that we don't have to allocate an unused page except
-** for very large databases. But one should test the page skipping logic
-** by setting PENDING_BYTE low and running the entire regression suite.
-**
-** Changing the value of PENDING_BYTE results in a subtly incompatible
-** file format. Depending on how it is changed, you might not notice
-** the incompatibility right away, even running a full regression test.
-** The default location of PENDING_BYTE is the first byte past the
-** 1GB boundary.
-**
-*/
-#ifdef SQLITE_OMIT_WSD
-# define PENDING_BYTE (0x40000000)
-#else
-# define PENDING_BYTE sqlite3PendingByte
-#endif
-#define RESERVED_BYTE (PENDING_BYTE+1)
-#define SHARED_FIRST (PENDING_BYTE+2)
-#define SHARED_SIZE 510
-
-/*
-** Wrapper around OS specific sqlite3_os_init() function.
-*/
-int sqlite3OsInit(void);
-
-/*
-** Functions for accessing sqlite3_file methods
-*/
-void sqlite3OsClose(sqlite3_file*);
-int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
-int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
-int sqlite3OsTruncate(sqlite3_file*, i64 size);
-int sqlite3OsSync(sqlite3_file*, int);
-int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
-int sqlite3OsLock(sqlite3_file*, int);
-int sqlite3OsUnlock(sqlite3_file*, int);
-int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
-int sqlite3OsFileControl(sqlite3_file*,int,void*);
-void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
-#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
-int sqlite3OsSectorSize(sqlite3_file *id);
-int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
-#ifndef SQLITE_OMIT_WAL
-int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
-int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
-void sqlite3OsShmBarrier(sqlite3_file *id);
-int sqlite3OsShmUnmap(sqlite3_file *id, int);
-#endif /* SQLITE_OMIT_WAL */
-int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
-int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
-
-
-/*
-** Functions for accessing sqlite3_vfs methods
-*/
-int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
-int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
-int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
-int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
-void sqlite3OsDlError(sqlite3_vfs *, int, char *);
-void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
-void sqlite3OsDlClose(sqlite3_vfs *, void *);
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
-int sqlite3OsSleep(sqlite3_vfs *, int);
-int sqlite3OsGetLastError(sqlite3_vfs*);
-int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
-
-/*
-** Convenience functions for opening and closing files using
-** sqlite3_malloc() to obtain space for the file-handle structure.
-*/
-int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
-void sqlite3OsCloseFree(sqlite3_file *);
-
-#endif /* _SQLITE_OS_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_common.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/os_common.h
deleted file mode 100644
index 1ed4d7a8e1a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_common.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-** 2004 May 22
-**
-** 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 contains macros and a little bit of code that is common to
-** all of the platform-specific files (os_*.c) and is #included into those
-** files.
-**
-** This file should be #included by the os_*.c files only. It is not a
-** general purpose header file.
-*/
-#ifndef _OS_COMMON_H_
-#define _OS_COMMON_H_
-
-/*
-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
-** switch. The following code should catch this problem at compile-time.
-*/
-#ifdef MEMORY_DEBUG
-# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
-#endif
-
-/*
-** Macros for performance tracing. Normally turned off. Only works
-** on i486 hardware.
-*/
-#ifdef SQLITE_PERFORMANCE_TRACE
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-#include "hwtime.h"
-
-static sqlite_uint64 g_start;
-static sqlite_uint64 g_elapsed;
-#define TIMER_START g_start=sqlite3Hwtime()
-#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
-#define TIMER_ELAPSED g_elapsed
-#else
-#define TIMER_START
-#define TIMER_END
-#define TIMER_ELAPSED ((sqlite_uint64)0)
-#endif
-
-/*
-** If we compile with the SQLITE_TEST macro set, then the following block
-** of code will give us the ability to simulate a disk I/O error. This
-** is used for testing the I/O recovery logic.
-*/
-#if defined(SQLITE_TEST)
-extern int sqlite3_io_error_hit;
-extern int sqlite3_io_error_hardhit;
-extern int sqlite3_io_error_pending;
-extern int sqlite3_io_error_persist;
-extern int sqlite3_io_error_benign;
-extern int sqlite3_diskfull_pending;
-extern int sqlite3_diskfull;
-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
-#define SimulateIOError(CODE) \
- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
- || sqlite3_io_error_pending-- == 1 ) \
- { local_ioerr(); CODE; }
-static void local_ioerr(){
- IOTRACE(("IOERR\n"));
- sqlite3_io_error_hit++;
- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
-}
-#define SimulateDiskfullError(CODE) \
- if( sqlite3_diskfull_pending ){ \
- if( sqlite3_diskfull_pending == 1 ){ \
- local_ioerr(); \
- sqlite3_diskfull = 1; \
- sqlite3_io_error_hit = 1; \
- CODE; \
- }else{ \
- sqlite3_diskfull_pending--; \
- } \
- }
-#else
-#define SimulateIOErrorBenign(X)
-#define SimulateIOError(A)
-#define SimulateDiskfullError(A)
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** When testing, keep a count of the number of open files.
-*/
-#if defined(SQLITE_TEST)
-extern int sqlite3_open_file_count;
-#define OpenCounter(X) sqlite3_open_file_count+=(X)
-#else
-#define OpenCounter(X)
-#endif /* defined(SQLITE_TEST) */
-
-#endif /* !defined(_OS_COMMON_H_) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_setup.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/os_setup.h
deleted file mode 100644
index 08aaa1195ac..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_setup.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-** 2013 November 25
-**
-** 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 contains pre-processor directives related to operating system
-** detection and/or setup.
-*/
-#ifndef SQLITE_OS_SETUP_H
-#define SQLITE_OS_SETUP_H
-
-/*
-** Figure out if we are dealing with Unix, Windows, or some other operating
-** system.
-**
-** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
-** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of
-** the three will be 1. The other two will be 0.
-*/
-#if defined(SQLITE_OS_OTHER)
-# if SQLITE_OS_OTHER==1
-# undef SQLITE_OS_UNIX
-# define SQLITE_OS_UNIX 0
-# undef SQLITE_OS_WIN
-# define SQLITE_OS_WIN 0
-# else
-# undef SQLITE_OS_OTHER
-# endif
-#endif
-#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
-# define SQLITE_OS_OTHER 0
-# ifndef SQLITE_OS_WIN
-# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
- defined(__MINGW32__) || defined(__BORLANDC__)
-# define SQLITE_OS_WIN 1
-# define SQLITE_OS_UNIX 0
-# else
-# define SQLITE_OS_WIN 0
-# define SQLITE_OS_UNIX 1
-# endif
-# else
-# define SQLITE_OS_UNIX 0
-# endif
-#else
-# ifndef SQLITE_OS_WIN
-# define SQLITE_OS_WIN 0
-# endif
-#endif
-
-#endif /* SQLITE_OS_SETUP_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_unix.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/os_unix.c
deleted file mode 100644
index 0dd461da0a2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_unix.c
+++ /dev/null
@@ -1,7788 +0,0 @@
-/*
-** 2004 May 22
-**
-** 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 contains the VFS implementation for unix-like operating systems
-** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
-**
-** There are actually several different VFS implementations in this file.
-** The differences are in the way that file locking is done. The default
-** implementation uses Posix Advisory Locks. Alternative implementations
-** use flock(), dot-files, various proprietary locking schemas, or simply
-** skip locking all together.
-**
-** This source file is organized into divisions where the logic for various
-** subfunctions is contained within the appropriate division. PLEASE
-** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed
-** in the correct division and should be clearly labeled.
-**
-** The layout of divisions is as follows:
-**
-** * General-purpose declarations and utility functions.
-** * Unique file ID logic used by VxWorks.
-** * Various locking primitive implementations (all except proxy locking):
-** + for Posix Advisory Locks
-** + for no-op locks
-** + for dot-file locks
-** + for flock() locking
-** + for named semaphore locks (VxWorks only)
-** + for AFP filesystem locks (MacOSX only)
-** * sqlite3_file methods not associated with locking.
-** * Definitions of sqlite3_io_methods objects for all locking
-** methods plus "finder" functions for each locking method.
-** * sqlite3_vfs method implementations.
-** * Locking primitives for the proxy uber-locking-method. (MacOSX only)
-** * Definitions of sqlite3_vfs objects for all locking methods
-** plus implementations of sqlite3_os_init() and sqlite3_os_end().
-*/
-#include "sqliteInt.h"
-#if SQLITE_OS_UNIX /* This file is used on unix only */
-
-/*
-** There are various methods for file locking used for concurrency
-** control:
-**
-** 1. POSIX locking (the default),
-** 2. No locking,
-** 3. Dot-file locking,
-** 4. flock() locking,
-** 5. AFP locking (OSX only),
-** 6. Named POSIX semaphores (VXWorks only),
-** 7. proxy locking. (OSX only)
-**
-** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
-** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
-** selection of the appropriate locking style based on the filesystem
-** where the database is located.
-*/
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-# if defined(__APPLE__)
-# define SQLITE_ENABLE_LOCKING_STYLE 1
-# else
-# define SQLITE_ENABLE_LOCKING_STYLE 0
-# endif
-#endif
-
-/* Use pread() and pwrite() if they are available */
-#if defined(__APPLE__)
-# define HAVE_PREAD 1
-# define HAVE_PWRITE 1
-#endif
-#if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64)
-# undef USE_PREAD
-# define USE_PREAD64 1
-#elif defined(HAVE_PREAD) && defined(HAVE_PWRITE)
-# undef USE_PREAD64
-# define USE_PREAD 1
-#endif
-
-/*
-** standard include files.
-*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/time.h>
-#include <errno.h>
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
-# include <sys/mman.h>
-#endif
-
-#if SQLITE_ENABLE_LOCKING_STYLE
-# include <sys/ioctl.h>
-# include <sys/file.h>
-# include <sys/param.h>
-#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-
-#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
- (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
-# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
- && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
-# define HAVE_GETHOSTUUID 1
-# else
-# warning "gethostuuid() is disabled."
-# endif
-#endif
-
-
-#if OS_VXWORKS
-# include <sys/ioctl.h>
-# include <semaphore.h>
-# include <limits.h>
-#endif /* OS_VXWORKS */
-
-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-# include <sys/mount.h>
-#endif
-
-#ifdef HAVE_UTIME
-# include <utime.h>
-#endif
-
-/*
-** Allowed values of unixFile.fsFlags
-*/
-#define SQLITE_FSFLAGS_IS_MSDOS 0x1
-
-/*
-** If we are to be thread-safe, include the pthreads header and define
-** the SQLITE_UNIX_THREADS macro.
-*/
-#if SQLITE_THREADSAFE
-# include <pthread.h>
-# define SQLITE_UNIX_THREADS 1
-#endif
-
-/*
-** Default permissions when creating a new file
-*/
-#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
-# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
-#endif
-
-/*
-** Default permissions when creating auto proxy dir
-*/
-#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
-# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
-#endif
-
-/*
-** Maximum supported path-length.
-*/
-#define MAX_PATHNAME 512
-
-/*
-** Maximum supported symbolic links
-*/
-#define SQLITE_MAX_SYMLINKS 100
-
-/* Always cast the getpid() return type for compatibility with
-** kernel modules in VxWorks. */
-#define osGetpid(X) (pid_t)getpid()
-
-/*
-** Only set the lastErrno if the error code is a real error and not
-** a normal expected return code of SQLITE_BUSY or SQLITE_OK
-*/
-#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
-
-/* Forward references */
-typedef struct unixShm unixShm; /* Connection shared memory */
-typedef struct unixShmNode unixShmNode; /* Shared memory instance */
-typedef struct unixInodeInfo unixInodeInfo; /* An i-node */
-typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */
-
-/*
-** Sometimes, after a file handle is closed by SQLite, the file descriptor
-** cannot be closed immediately. In these cases, instances of the following
-** structure are used to store the file descriptor while waiting for an
-** opportunity to either close or reuse it.
-*/
-struct UnixUnusedFd {
- int fd; /* File descriptor to close */
- int flags; /* Flags this file descriptor was opened with */
- UnixUnusedFd *pNext; /* Next unused file descriptor on same file */
-};
-
-/*
-** The unixFile structure is subclass of sqlite3_file specific to the unix
-** VFS implementations.
-*/
-typedef struct unixFile unixFile;
-struct unixFile {
- sqlite3_io_methods const *pMethod; /* Always the first entry */
- sqlite3_vfs *pVfs; /* The VFS that created this unixFile */
- unixInodeInfo *pInode; /* Info about locks on this inode */
- int h; /* The file descriptor */
- unsigned char eFileLock; /* The type of lock held on this fd */
- unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
- int lastErrno; /* The unix errno from last I/O error */
- void *lockingContext; /* Locking style specific state */
- UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */
- const char *zPath; /* Name of the file */
- unixShm *pShm; /* Shared memory segment information */
- int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
-#if SQLITE_MAX_MMAP_SIZE>0
- int nFetchOut; /* Number of outstanding xFetch refs */
- sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */
- sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */
- sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
- void *pMapRegion; /* Memory mapped region */
-#endif
- int sectorSize; /* Device sector size */
- int deviceCharacteristics; /* Precomputed device characteristics */
-#if SQLITE_ENABLE_LOCKING_STYLE
- int openFlags; /* The flags specified at open() */
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
- unsigned fsFlags; /* cached details from statfs() */
-#endif
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- unsigned iBusyTimeout; /* Wait this many millisec on locks */
-#endif
-#if OS_VXWORKS
- struct vxworksFileId *pId; /* Unique file ID */
-#endif
-#ifdef SQLITE_DEBUG
- /* The next group of variables are used to track whether or not the
- ** transaction counter in bytes 24-27 of database files are updated
- ** whenever any part of the database changes. An assertion fault will
- ** occur if a file is updated without also updating the transaction
- ** counter. This test is made to avoid new problems similar to the
- ** one described by ticket #3584.
- */
- unsigned char transCntrChng; /* True if the transaction counter changed */
- unsigned char dbUpdate; /* True if any part of database file changed */
- unsigned char inNormalWrite; /* True if in a normal write operation */
-
-#endif
-
-#ifdef SQLITE_TEST
- /* In test mode, increase the size of this structure a bit so that
- ** it is larger than the struct CrashFile defined in test6.c.
- */
- char aPadding[32];
-#endif
-};
-
-/* This variable holds the process id (pid) from when the xRandomness()
-** method was called. If xOpen() is called from a different process id,
-** indicating that a fork() has occurred, the PRNG will be reset.
-*/
-static pid_t randomnessPid = 0;
-
-/*
-** Allowed values for the unixFile.ctrlFlags bitmask:
-*/
-#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
-#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
-#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
-#ifndef SQLITE_DISABLE_DIRSYNC
-# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
-#else
-# define UNIXFILE_DIRSYNC 0x00
-#endif
-#define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
-#define UNIXFILE_DELETE 0x20 /* Delete on close */
-#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
-#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
-
-/*
-** Include code that is common to all os_*.c files
-*/
-#include "os_common.h"
-
-/*
-** Define various macros that are missing from some systems.
-*/
-#ifndef O_LARGEFILE
-# define O_LARGEFILE 0
-#endif
-#ifdef SQLITE_DISABLE_LFS
-# undef O_LARGEFILE
-# define O_LARGEFILE 0
-#endif
-#ifndef O_NOFOLLOW
-# define O_NOFOLLOW 0
-#endif
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-/*
-** The threadid macro resolves to the thread-id or to 0. Used for
-** testing and debugging only.
-*/
-#if SQLITE_THREADSAFE
-#define threadid pthread_self()
-#else
-#define threadid 0
-#endif
-
-/*
-** HAVE_MREMAP defaults to true on Linux and false everywhere else.
-*/
-#if !defined(HAVE_MREMAP)
-# if defined(__linux__) && defined(_GNU_SOURCE)
-# define HAVE_MREMAP 1
-# else
-# define HAVE_MREMAP 0
-# endif
-#endif
-
-/*
-** Explicitly call the 64-bit version of lseek() on Android. Otherwise, lseek()
-** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined.
-*/
-#ifdef __ANDROID__
-# define lseek lseek64
-#endif
-
-#ifdef __linux__
-/*
-** Linux-specific IOCTL magic numbers used for controlling F2FS
-*/
-#define F2FS_IOCTL_MAGIC 0xf5
-#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
-#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
-#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
-#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
-#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32)
-#define F2FS_FEATURE_ATOMIC_WRITE 0x0004
-#endif /* __linux__ */
-
-
-/*
-** Different Unix systems declare open() in different ways. Same use
-** open(const char*,int,mode_t). Others use open(const char*,int,...).
-** The difference is important when using a pointer to the function.
-**
-** The safest way to deal with the problem is to always use this wrapper
-** which always has the same well-defined interface.
-*/
-static int posixOpen(const char *zFile, int flags, int mode){
- return open(zFile, flags, mode);
-}
-
-/* Forward reference */
-static int openDirectory(const char*, int*);
-static int unixGetpagesize(void);
-
-/*
-** Many system calls are accessed through pointer-to-functions so that
-** they may be overridden at runtime to facilitate fault injection during
-** testing and sandboxing. The following array holds the names and pointers
-** to all overrideable system calls.
-*/
-static struct unix_syscall {
- const char *zName; /* Name of the system call */
- sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
- sqlite3_syscall_ptr pDefault; /* Default value */
-} aSyscall[] = {
- { "open", (sqlite3_syscall_ptr)posixOpen, 0 },
-#define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
-
- { "close", (sqlite3_syscall_ptr)close, 0 },
-#define osClose ((int(*)(int))aSyscall[1].pCurrent)
-
- { "access", (sqlite3_syscall_ptr)access, 0 },
-#define osAccess ((int(*)(const char*,int))aSyscall[2].pCurrent)
-
- { "getcwd", (sqlite3_syscall_ptr)getcwd, 0 },
-#define osGetcwd ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
-
- { "stat", (sqlite3_syscall_ptr)stat, 0 },
-#define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
-
-/*
-** The DJGPP compiler environment looks mostly like Unix, but it
-** lacks the fcntl() system call. So redefine fcntl() to be something
-** that always succeeds. This means that locking does not occur under
-** DJGPP. But it is DOS - what did you expect?
-*/
-#ifdef __DJGPP__
- { "fstat", 0, 0 },
-#define osFstat(a,b,c) 0
-#else
- { "fstat", (sqlite3_syscall_ptr)fstat, 0 },
-#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
-#endif
-
- { "ftruncate", (sqlite3_syscall_ptr)ftruncate, 0 },
-#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
-
- { "fcntl", (sqlite3_syscall_ptr)fcntl, 0 },
-#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
-
- { "read", (sqlite3_syscall_ptr)read, 0 },
-#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
-
-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
- { "pread", (sqlite3_syscall_ptr)pread, 0 },
-#else
- { "pread", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
-
-#if defined(USE_PREAD64)
- { "pread64", (sqlite3_syscall_ptr)pread64, 0 },
-#else
- { "pread64", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osPread64 ((ssize_t(*)(int,void*,size_t,off64_t))aSyscall[10].pCurrent)
-
- { "write", (sqlite3_syscall_ptr)write, 0 },
-#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
-
-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
- { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
-#else
- { "pwrite", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
- aSyscall[12].pCurrent)
-
-#if defined(USE_PREAD64)
- { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 },
-#else
- { "pwrite64", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\
- aSyscall[13].pCurrent)
-
- { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
-#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
-
-#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
- { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
-#else
- { "fallocate", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
-
- { "unlink", (sqlite3_syscall_ptr)unlink, 0 },
-#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent)
-
- { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
-#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
-
- { "mkdir", (sqlite3_syscall_ptr)mkdir, 0 },
-#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
-
- { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
-#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
-
-#if defined(HAVE_FCHOWN)
- { "fchown", (sqlite3_syscall_ptr)fchown, 0 },
-#else
- { "fchown", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
-
-#if defined(HAVE_FCHOWN)
- { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 },
-#else
- { "geteuid", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
-
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
- { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
-#else
- { "mmap", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
-
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
- { "munmap", (sqlite3_syscall_ptr)munmap, 0 },
-#else
- { "munmap", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent)
-
-#if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
- { "mremap", (sqlite3_syscall_ptr)mremap, 0 },
-#else
- { "mremap", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent)
-
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
- { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
-#else
- { "getpagesize", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent)
-
-#if defined(HAVE_READLINK)
- { "readlink", (sqlite3_syscall_ptr)readlink, 0 },
-#else
- { "readlink", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
-
-#if defined(HAVE_LSTAT)
- { "lstat", (sqlite3_syscall_ptr)lstat, 0 },
-#else
- { "lstat", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
-
-#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
- { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
-#else
- { "ioctl", (sqlite3_syscall_ptr)0, 0 },
-#endif
-#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
-
-}; /* End of the overrideable system calls */
-
-
-/*
-** On some systems, calls to fchown() will trigger a message in a security
-** log if they come from non-root processes. So avoid calling fchown() if
-** we are not running as root.
-*/
-static int robustFchown(int fd, uid_t uid, gid_t gid){
-#if defined(HAVE_FCHOWN)
- return osGeteuid() ? 0 : osFchown(fd,uid,gid);
-#else
- return 0;
-#endif
-}
-
-/*
-** This is the xSetSystemCall() method of sqlite3_vfs for all of the
-** "unix" VFSes. Return SQLITE_OK opon successfully updating the
-** system call pointer, or SQLITE_NOTFOUND if there is no configurable
-** system call named zName.
-*/
-static int unixSetSystemCall(
- sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
- const char *zName, /* Name of system call to override */
- sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
-){
- unsigned int i;
- int rc = SQLITE_NOTFOUND;
-
- UNUSED_PARAMETER(pNotUsed);
- if( zName==0 ){
- /* If no zName is given, restore all system calls to their default
- ** settings and return NULL
- */
- rc = SQLITE_OK;
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( aSyscall[i].pDefault ){
- aSyscall[i].pCurrent = aSyscall[i].pDefault;
- }
- }
- }else{
- /* If zName is specified, operate on only the one system call
- ** specified.
- */
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ){
- if( aSyscall[i].pDefault==0 ){
- aSyscall[i].pDefault = aSyscall[i].pCurrent;
- }
- rc = SQLITE_OK;
- if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
- aSyscall[i].pCurrent = pNewFunc;
- break;
- }
- }
- }
- return rc;
-}
-
-/*
-** Return the value of a system call. Return NULL if zName is not a
-** recognized system call name. NULL is also returned if the system call
-** is currently undefined.
-*/
-static sqlite3_syscall_ptr unixGetSystemCall(
- sqlite3_vfs *pNotUsed,
- const char *zName
-){
- unsigned int i;
-
- UNUSED_PARAMETER(pNotUsed);
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
- }
- return 0;
-}
-
-/*
-** Return the name of the first system call after zName. If zName==NULL
-** then return the name of the first system call. Return NULL if zName
-** is the last system call or if zName is not the name of a valid
-** system call.
-*/
-static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
- int i = -1;
-
- UNUSED_PARAMETER(p);
- if( zName ){
- for(i=0; i<ArraySize(aSyscall)-1; i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ) break;
- }
- }
- for(i++; i<ArraySize(aSyscall); i++){
- if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
- }
- return 0;
-}
-
-/*
-** Do not accept any file descriptor less than this value, in order to avoid
-** opening database file using file descriptors that are commonly used for
-** standard input, output, and error.
-*/
-#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
-# define SQLITE_MINIMUM_FILE_DESCRIPTOR 3
-#endif
-
-/*
-** Invoke open(). Do so multiple times, until it either succeeds or
-** fails for some reason other than EINTR.
-**
-** If the file creation mode "m" is 0 then set it to the default for
-** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
-** 0644) as modified by the system umask. If m is not 0, then
-** make the file creation mode be exactly m ignoring the umask.
-**
-** The m parameter will be non-zero only when creating -wal, -journal,
-** and -shm files. We want those files to have *exactly* the same
-** permissions as their original database, unadulterated by the umask.
-** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
-** transaction crashes and leaves behind hot journals, then any
-** process that is able to write to the database will also be able to
-** recover the hot journals.
-*/
-static int robust_open(const char *z, int f, mode_t m){
- int fd;
- mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
- while(1){
-#if defined(O_CLOEXEC)
- fd = osOpen(z,f|O_CLOEXEC,m2);
-#else
- fd = osOpen(z,f,m2);
-#endif
- if( fd<0 ){
- if( errno==EINTR ) continue;
- break;
- }
- if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
- osClose(fd);
- sqlite3_log(SQLITE_WARNING,
- "attempt to open \"%s\" as file descriptor %d", z, fd);
- fd = -1;
- if( osOpen("/dev/null", f, m)<0 ) break;
- }
- if( fd>=0 ){
- if( m!=0 ){
- struct stat statbuf;
- if( osFstat(fd, &statbuf)==0
- && statbuf.st_size==0
- && (statbuf.st_mode&0777)!=m
- ){
- osFchmod(fd, m);
- }
- }
-#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
- osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
-#endif
- }
- return fd;
-}
-
-/*
-** Helper functions to obtain and relinquish the global mutex. The
-** global mutex is used to protect the unixInodeInfo and
-** vxworksFileId objects used by this file, all of which may be
-** shared by multiple threads.
-**
-** Function unixMutexHeld() is used to assert() that the global mutex
-** is held when required. This function is only used as part of assert()
-** statements. e.g.
-**
-** unixEnterMutex()
-** assert( unixMutexHeld() );
-** unixEnterLeave()
-*/
-static sqlite3_mutex *unixBigLock = 0;
-static void unixEnterMutex(void){
- sqlite3_mutex_enter(unixBigLock);
-}
-static void unixLeaveMutex(void){
- sqlite3_mutex_leave(unixBigLock);
-}
-#ifdef SQLITE_DEBUG
-static int unixMutexHeld(void) {
- return sqlite3_mutex_held(unixBigLock);
-}
-#endif
-
-
-#ifdef SQLITE_HAVE_OS_TRACE
-/*
-** Helper function for printing out trace information from debugging
-** binaries. This returns the string representation of the supplied
-** integer lock-type.
-*/
-static const char *azFileLock(int eFileLock){
- switch( eFileLock ){
- case NO_LOCK: return "NONE";
- case SHARED_LOCK: return "SHARED";
- case RESERVED_LOCK: return "RESERVED";
- case PENDING_LOCK: return "PENDING";
- case EXCLUSIVE_LOCK: return "EXCLUSIVE";
- }
- return "ERROR";
-}
-#endif
-
-#ifdef SQLITE_LOCK_TRACE
-/*
-** Print out information about all locking operations.
-**
-** This routine is used for troubleshooting locks on multithreaded
-** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE
-** command-line option on the compiler. This code is normally
-** turned off.
-*/
-static int lockTrace(int fd, int op, struct flock *p){
- char *zOpName, *zType;
- int s;
- int savedErrno;
- if( op==F_GETLK ){
- zOpName = "GETLK";
- }else if( op==F_SETLK ){
- zOpName = "SETLK";
- }else{
- s = osFcntl(fd, op, p);
- sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
- return s;
- }
- if( p->l_type==F_RDLCK ){
- zType = "RDLCK";
- }else if( p->l_type==F_WRLCK ){
- zType = "WRLCK";
- }else if( p->l_type==F_UNLCK ){
- zType = "UNLCK";
- }else{
- assert( 0 );
- }
- assert( p->l_whence==SEEK_SET );
- s = osFcntl(fd, op, p);
- savedErrno = errno;
- sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
- threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
- (int)p->l_pid, s);
- if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
- struct flock l2;
- l2 = *p;
- osFcntl(fd, F_GETLK, &l2);
- if( l2.l_type==F_RDLCK ){
- zType = "RDLCK";
- }else if( l2.l_type==F_WRLCK ){
- zType = "WRLCK";
- }else if( l2.l_type==F_UNLCK ){
- zType = "UNLCK";
- }else{
- assert( 0 );
- }
- sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
- zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
- }
- errno = savedErrno;
- return s;
-}
-#undef osFcntl
-#define osFcntl lockTrace
-#endif /* SQLITE_LOCK_TRACE */
-
-/*
-** Retry ftruncate() calls that fail due to EINTR
-**
-** All calls to ftruncate() within this file should be made through
-** this wrapper. On the Android platform, bypassing the logic below
-** could lead to a corrupt database.
-*/
-static int robust_ftruncate(int h, sqlite3_int64 sz){
- int rc;
-#ifdef __ANDROID__
- /* On Android, ftruncate() always uses 32-bit offsets, even if
- ** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to
- ** truncate a file to any size larger than 2GiB. Silently ignore any
- ** such attempts. */
- if( sz>(sqlite3_int64)0x7FFFFFFF ){
- rc = SQLITE_OK;
- }else
-#endif
- do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
- return rc;
-}
-
-/*
-** This routine translates a standard POSIX errno code into something
-** useful to the clients of the sqlite3 functions. Specifically, it is
-** intended to translate a variety of "try again" errors into SQLITE_BUSY
-** and a variety of "please close the file descriptor NOW" errors into
-** SQLITE_IOERR
-**
-** Errors during initialization of locks, or file system support for locks,
-** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
-*/
-static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
- assert( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) );
- switch (posixError) {
- case EACCES:
- case EAGAIN:
- case ETIMEDOUT:
- case EBUSY:
- case EINTR:
- case ENOLCK:
- /* random NFS retry error, unless during file system support
- * introspection, in which it actually means what it says */
- return SQLITE_BUSY;
-
- case EPERM:
- return SQLITE_PERM;
-
- default:
- return sqliteIOErr;
- }
-}
-
-
-/******************************************************************************
-****************** Begin Unique File ID Utility Used By VxWorks ***************
-**
-** On most versions of unix, we can get a unique ID for a file by concatenating
-** the device number and the inode number. But this does not work on VxWorks.
-** On VxWorks, a unique file id must be based on the canonical filename.
-**
-** A pointer to an instance of the following structure can be used as a
-** unique file ID in VxWorks. Each instance of this structure contains
-** a copy of the canonical filename. There is also a reference count.
-** The structure is reclaimed when the number of pointers to it drops to
-** zero.
-**
-** There are never very many files open at one time and lookups are not
-** a performance-critical path, so it is sufficient to put these
-** structures on a linked list.
-*/
-struct vxworksFileId {
- struct vxworksFileId *pNext; /* Next in a list of them all */
- int nRef; /* Number of references to this one */
- int nName; /* Length of the zCanonicalName[] string */
- char *zCanonicalName; /* Canonical filename */
-};
-
-#if OS_VXWORKS
-/*
-** All unique filenames are held on a linked list headed by this
-** variable:
-*/
-static struct vxworksFileId *vxworksFileList = 0;
-
-/*
-** Simplify a filename into its canonical form
-** by making the following changes:
-**
-** * removing any trailing and duplicate /
-** * convert /./ into just /
-** * convert /A/../ where A is any simple name into just /
-**
-** Changes are made in-place. Return the new name length.
-**
-** The original filename is in z[0..n-1]. Return the number of
-** characters in the simplified name.
-*/
-static int vxworksSimplifyName(char *z, int n){
- int i, j;
- while( n>1 && z[n-1]=='/' ){ n--; }
- for(i=j=0; i<n; i++){
- if( z[i]=='/' ){
- if( z[i+1]=='/' ) continue;
- if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
- i += 1;
- continue;
- }
- if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
- while( j>0 && z[j-1]!='/' ){ j--; }
- if( j>0 ){ j--; }
- i += 2;
- continue;
- }
- }
- z[j++] = z[i];
- }
- z[j] = 0;
- return j;
-}
-
-/*
-** Find a unique file ID for the given absolute pathname. Return
-** a pointer to the vxworksFileId object. This pointer is the unique
-** file ID.
-**
-** The nRef field of the vxworksFileId object is incremented before
-** the object is returned. A new vxworksFileId object is created
-** and added to the global list if necessary.
-**
-** If a memory allocation error occurs, return NULL.
-*/
-static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
- struct vxworksFileId *pNew; /* search key and new file ID */
- struct vxworksFileId *pCandidate; /* For looping over existing file IDs */
- int n; /* Length of zAbsoluteName string */
-
- assert( zAbsoluteName[0]=='/' );
- n = (int)strlen(zAbsoluteName);
- pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) );
- if( pNew==0 ) return 0;
- pNew->zCanonicalName = (char*)&pNew[1];
- memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
- n = vxworksSimplifyName(pNew->zCanonicalName, n);
-
- /* Search for an existing entry that matching the canonical name.
- ** If found, increment the reference count and return a pointer to
- ** the existing file ID.
- */
- unixEnterMutex();
- for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
- if( pCandidate->nName==n
- && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
- ){
- sqlite3_free(pNew);
- pCandidate->nRef++;
- unixLeaveMutex();
- return pCandidate;
- }
- }
-
- /* No match was found. We will make a new file ID */
- pNew->nRef = 1;
- pNew->nName = n;
- pNew->pNext = vxworksFileList;
- vxworksFileList = pNew;
- unixLeaveMutex();
- return pNew;
-}
-
-/*
-** Decrement the reference count on a vxworksFileId object. Free
-** the object when the reference count reaches zero.
-*/
-static void vxworksReleaseFileId(struct vxworksFileId *pId){
- unixEnterMutex();
- assert( pId->nRef>0 );
- pId->nRef--;
- if( pId->nRef==0 ){
- struct vxworksFileId **pp;
- for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
- assert( *pp==pId );
- *pp = pId->pNext;
- sqlite3_free(pId);
- }
- unixLeaveMutex();
-}
-#endif /* OS_VXWORKS */
-/*************** End of Unique File ID Utility Used By VxWorks ****************
-******************************************************************************/
-
-
-/******************************************************************************
-*************************** Posix Advisory Locking ****************************
-**
-** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996)
-** section 6.5.2.2 lines 483 through 490 specify that when a process
-** sets or clears a lock, that operation overrides any prior locks set
-** by the same process. It does not explicitly say so, but this implies
-** that it overrides locks set by the same process using a different
-** file descriptor. Consider this test case:
-**
-** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
-** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
-**
-** Suppose ./file1 and ./file2 are really the same file (because
-** one is a hard or symbolic link to the other) then if you set
-** an exclusive lock on fd1, then try to get an exclusive lock
-** on fd2, it works. I would have expected the second lock to
-** fail since there was already a lock on the file due to fd1.
-** But not so. Since both locks came from the same process, the
-** second overrides the first, even though they were on different
-** file descriptors opened on different file names.
-**
-** This means that we cannot use POSIX locks to synchronize file access
-** among competing threads of the same process. POSIX locks will work fine
-** to synchronize access for threads in separate processes, but not
-** threads within the same process.
-**
-** To work around the problem, SQLite has to manage file locks internally
-** on its own. Whenever a new database is opened, we have to find the
-** specific inode of the database file (the inode is determined by the
-** st_dev and st_ino fields of the stat structure that fstat() fills in)
-** and check for locks already existing on that inode. When locks are
-** created or removed, we have to look at our own internal record of the
-** locks to see if another thread has previously set a lock on that same
-** inode.
-**
-** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
-** For VxWorks, we have to use the alternative unique ID system based on
-** canonical filename and implemented in the previous division.)
-**
-** The sqlite3_file structure for POSIX is no longer just an integer file
-** descriptor. It is now a structure that holds the integer file
-** descriptor and a pointer to a structure that describes the internal
-** locks on the corresponding inode. There is one locking structure
-** per inode, so if the same inode is opened twice, both unixFile structures
-** point to the same locking structure. The locking structure keeps
-** a reference count (so we will know when to delete it) and a "cnt"
-** field that tells us its internal lock status. cnt==0 means the
-** file is unlocked. cnt==-1 means the file has an exclusive lock.
-** cnt>0 means there are cnt shared locks on the file.
-**
-** Any attempt to lock or unlock a file first checks the locking
-** structure. The fcntl() system call is only invoked to set a
-** POSIX lock if the internal lock structure transitions between
-** a locked and an unlocked state.
-**
-** But wait: there are yet more problems with POSIX advisory locks.
-**
-** If you close a file descriptor that points to a file that has locks,
-** all locks on that file that are owned by the current process are
-** released. To work around this problem, each unixInodeInfo object
-** maintains a count of the number of pending locks on tha inode.
-** When an attempt is made to close an unixFile, if there are
-** other unixFile open on the same inode that are holding locks, the call
-** to close() the file descriptor is deferred until all of the locks clear.
-** The unixInodeInfo structure keeps a list of file descriptors that need to
-** be closed and that list is walked (and cleared) when the last lock
-** clears.
-**
-** Yet another problem: LinuxThreads do not play well with posix locks.
-**
-** Many older versions of linux use the LinuxThreads library which is
-** not posix compliant. Under LinuxThreads, a lock created by thread
-** A cannot be modified or overridden by a different thread B.
-** Only thread A can modify the lock. Locking behavior is correct
-** if the appliation uses the newer Native Posix Thread Library (NPTL)
-** on linux - with NPTL a lock created by thread A can override locks
-** in thread B. But there is no way to know at compile-time which
-** threading library is being used. So there is no way to know at
-** compile-time whether or not thread A can override locks on thread B.
-** One has to do a run-time check to discover the behavior of the
-** current process.
-**
-** SQLite used to support LinuxThreads. But support for LinuxThreads
-** was dropped beginning with version 3.7.0. SQLite will still work with
-** LinuxThreads provided that (1) there is no more than one connection
-** per database file in the same process and (2) database connections
-** do not move across threads.
-*/
-
-/*
-** An instance of the following structure serves as the key used
-** to locate a particular unixInodeInfo object.
-*/
-struct unixFileId {
- dev_t dev; /* Device number */
-#if OS_VXWORKS
- struct vxworksFileId *pId; /* Unique file ID for vxworks. */
-#else
- /* We are told that some versions of Android contain a bug that
- ** sizes ino_t at only 32-bits instead of 64-bits. (See
- ** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c)
- ** To work around this, always allocate 64-bits for the inode number.
- ** On small machines that only have 32-bit inodes, this wastes 4 bytes,
- ** but that should not be a big deal. */
- /* WAS: ino_t ino; */
- u64 ino; /* Inode number */
-#endif
-};
-
-/*
-** An instance of the following structure is allocated for each open
-** inode. Or, on LinuxThreads, there is one of these structures for
-** each inode opened by each thread.
-**
-** A single inode can have multiple file descriptors, so each unixFile
-** structure contains a pointer to an instance of this object and this
-** object keeps a count of the number of unixFile pointing to it.
-*/
-struct unixInodeInfo {
- struct unixFileId fileId; /* The lookup key */
- int nShared; /* Number of SHARED locks held */
- unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
- unsigned char bProcessLock; /* An exclusive process lock is held */
- int nRef; /* Number of pointers to this structure */
- unixShmNode *pShmNode; /* Shared memory associated with this inode */
- int nLock; /* Number of outstanding file locks */
- UnixUnusedFd *pUnused; /* Unused file descriptors to close */
- unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
- unixInodeInfo *pPrev; /* .... doubly linked */
-#if SQLITE_ENABLE_LOCKING_STYLE
- unsigned long long sharedByte; /* for AFP simulated shared lock */
-#endif
-#if OS_VXWORKS
- sem_t *pSem; /* Named POSIX semaphore */
- char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
-#endif
-};
-
-/*
-** A lists of all unixInodeInfo objects.
-*/
-static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
-static unsigned int nUnusedFd = 0; /* Total unused file descriptors */
-
-/*
-**
-** This function - unixLogErrorAtLine(), is only ever called via the macro
-** unixLogError().
-**
-** It is invoked after an error occurs in an OS function and errno has been
-** set. It logs a message using sqlite3_log() containing the current value of
-** errno and, if possible, the human-readable equivalent from strerror() or
-** strerror_r().
-**
-** The first argument passed to the macro should be the error code that
-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
-** The two subsequent arguments should be the name of the OS function that
-** failed (e.g. "unlink", "open") and the associated file-system path,
-** if any.
-*/
-#define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__)
-static int unixLogErrorAtLine(
- int errcode, /* SQLite error code */
- const char *zFunc, /* Name of OS function that failed */
- const char *zPath, /* File path associated with error */
- int iLine /* Source line number where error occurred */
-){
- char *zErr; /* Message from strerror() or equivalent */
- int iErrno = errno; /* Saved syscall error number */
-
- /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
- ** the strerror() function to obtain the human-readable error message
- ** equivalent to errno. Otherwise, use strerror_r().
- */
-#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
- char aErr[80];
- memset(aErr, 0, sizeof(aErr));
- zErr = aErr;
-
- /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
- ** assume that the system provides the GNU version of strerror_r() that
- ** returns a pointer to a buffer containing the error message. That pointer
- ** may point to aErr[], or it may point to some static storage somewhere.
- ** Otherwise, assume that the system provides the POSIX version of
- ** strerror_r(), which always writes an error message into aErr[].
- **
- ** If the code incorrectly assumes that it is the POSIX version that is
- ** available, the error message will often be an empty string. Not a
- ** huge problem. Incorrectly concluding that the GNU version is available
- ** could lead to a segfault though.
- */
-#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
- zErr =
-# endif
- strerror_r(iErrno, aErr, sizeof(aErr)-1);
-
-#elif SQLITE_THREADSAFE
- /* This is a threadsafe build, but strerror_r() is not available. */
- zErr = "";
-#else
- /* Non-threadsafe build, use strerror(). */
- zErr = strerror(iErrno);
-#endif
-
- if( zPath==0 ) zPath = "";
- sqlite3_log(errcode,
- "os_unix.c:%d: (%d) %s(%s) - %s",
- iLine, iErrno, zFunc, zPath, zErr
- );
-
- return errcode;
-}
-
-/*
-** Close a file descriptor.
-**
-** We assume that close() almost always works, since it is only in a
-** very sick application or on a very sick platform that it might fail.
-** If it does fail, simply leak the file descriptor, but do log the
-** error.
-**
-** Note that it is not safe to retry close() after EINTR since the
-** file descriptor might have already been reused by another thread.
-** So we don't even try to recover from an EINTR. Just log the error
-** and move on.
-*/
-static void robust_close(unixFile *pFile, int h, int lineno){
- if( osClose(h) ){
- unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
- pFile ? pFile->zPath : 0, lineno);
- }
-}
-
-/*
-** Set the pFile->lastErrno. Do this in a subroutine as that provides
-** a convenient place to set a breakpoint.
-*/
-static void storeLastErrno(unixFile *pFile, int error){
- pFile->lastErrno = error;
-}
-
-/*
-** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
-*/
-static void closePendingFds(unixFile *pFile){
- unixInodeInfo *pInode = pFile->pInode;
- UnixUnusedFd *p;
- UnixUnusedFd *pNext;
- for(p=pInode->pUnused; p; p=pNext){
- pNext = p->pNext;
- robust_close(pFile, p->fd, __LINE__);
- sqlite3_free(p);
- nUnusedFd--;
- }
- pInode->pUnused = 0;
-}
-
-/*
-** Release a unixInodeInfo structure previously allocated by findInodeInfo().
-**
-** The mutex entered using the unixEnterMutex() function must be held
-** when this function is called.
-*/
-static void releaseInodeInfo(unixFile *pFile){
- unixInodeInfo *pInode = pFile->pInode;
- assert( unixMutexHeld() );
- if( ALWAYS(pInode) ){
- pInode->nRef--;
- if( pInode->nRef==0 ){
- assert( pInode->pShmNode==0 );
- closePendingFds(pFile);
- if( pInode->pPrev ){
- assert( pInode->pPrev->pNext==pInode );
- pInode->pPrev->pNext = pInode->pNext;
- }else{
- assert( inodeList==pInode );
- inodeList = pInode->pNext;
- }
- if( pInode->pNext ){
- assert( pInode->pNext->pPrev==pInode );
- pInode->pNext->pPrev = pInode->pPrev;
- }
- sqlite3_free(pInode);
- }
- }
- assert( inodeList!=0 || nUnusedFd==0 );
-}
-
-/*
-** Given a file descriptor, locate the unixInodeInfo object that
-** describes that file descriptor. Create a new one if necessary. The
-** return value might be uninitialized if an error occurs.
-**
-** The mutex entered using the unixEnterMutex() function must be held
-** when this function is called.
-**
-** Return an appropriate error code.
-*/
-static int findInodeInfo(
- unixFile *pFile, /* Unix file with file desc used in the key */
- unixInodeInfo **ppInode /* Return the unixInodeInfo object here */
-){
- int rc; /* System call return code */
- int fd; /* The file descriptor for pFile */
- struct unixFileId fileId; /* Lookup key for the unixInodeInfo */
- struct stat statbuf; /* Low-level file information */
- unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */
-
- assert( unixMutexHeld() );
-
- /* Get low-level information about the file that we can used to
- ** create a unique name for the file.
- */
- fd = pFile->h;
- rc = osFstat(fd, &statbuf);
- if( rc!=0 ){
- storeLastErrno(pFile, errno);
-#if defined(EOVERFLOW) && defined(SQLITE_DISABLE_LFS)
- if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
-#endif
- return SQLITE_IOERR;
- }
-
-#ifdef __APPLE__
- /* On OS X on an msdos filesystem, the inode number is reported
- ** incorrectly for zero-size files. See ticket #3260. To work
- ** around this problem (we consider it a bug in OS X, not SQLite)
- ** we always increase the file size to 1 by writing a single byte
- ** prior to accessing the inode number. The one byte written is
- ** an ASCII 'S' character which also happens to be the first byte
- ** in the header of every SQLite database. In this way, if there
- ** is a race condition such that another thread has already populated
- ** the first page of the database, no damage is done.
- */
- if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
- do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
- if( rc!=1 ){
- storeLastErrno(pFile, errno);
- return SQLITE_IOERR;
- }
- rc = osFstat(fd, &statbuf);
- if( rc!=0 ){
- storeLastErrno(pFile, errno);
- return SQLITE_IOERR;
- }
- }
-#endif
-
- memset(&fileId, 0, sizeof(fileId));
- fileId.dev = statbuf.st_dev;
-#if OS_VXWORKS
- fileId.pId = pFile->pId;
-#else
- fileId.ino = (u64)statbuf.st_ino;
-#endif
- assert( inodeList!=0 || nUnusedFd==0 );
- pInode = inodeList;
- while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
- pInode = pInode->pNext;
- }
- if( pInode==0 ){
- pInode = sqlite3_malloc64( sizeof(*pInode) );
- if( pInode==0 ){
- return SQLITE_NOMEM_BKPT;
- }
- memset(pInode, 0, sizeof(*pInode));
- memcpy(&pInode->fileId, &fileId, sizeof(fileId));
- pInode->nRef = 1;
- pInode->pNext = inodeList;
- pInode->pPrev = 0;
- if( inodeList ) inodeList->pPrev = pInode;
- inodeList = pInode;
- }else{
- pInode->nRef++;
- }
- *ppInode = pInode;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if pFile has been renamed or unlinked since it was first opened.
-*/
-static int fileHasMoved(unixFile *pFile){
-#if OS_VXWORKS
- return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
-#else
- struct stat buf;
- return pFile->pInode!=0 &&
- (osStat(pFile->zPath, &buf)!=0
- || (u64)buf.st_ino!=pFile->pInode->fileId.ino);
-#endif
-}
-
-
-/*
-** Check a unixFile that is a database. Verify the following:
-**
-** (1) There is exactly one hard link on the file
-** (2) The file is not a symbolic link
-** (3) The file has not been renamed or unlinked
-**
-** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
-*/
-static void verifyDbFile(unixFile *pFile){
- struct stat buf;
- int rc;
-
- /* These verifications occurs for the main database only */
- if( pFile->ctrlFlags & UNIXFILE_NOLOCK ) return;
-
- rc = osFstat(pFile->h, &buf);
- if( rc!=0 ){
- sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
- return;
- }
- if( buf.st_nlink==0 ){
- sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
- return;
- }
- if( buf.st_nlink>1 ){
- sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
- return;
- }
- if( fileHasMoved(pFile) ){
- sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
- return;
- }
-}
-
-
-/*
-** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-*/
-static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
- unixFile *pFile = (unixFile*)id;
-
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
- assert( pFile->eFileLock<=SHARED_LOCK );
- unixEnterMutex(); /* Because pFile->pInode is shared across threads */
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->pInode->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it.
- */
-#ifndef __DJGPP__
- if( !reserved && !pFile->pInode->bProcessLock ){
- struct flock lock;
- lock.l_whence = SEEK_SET;
- lock.l_start = RESERVED_BYTE;
- lock.l_len = 1;
- lock.l_type = F_WRLCK;
- if( osFcntl(pFile->h, F_GETLK, &lock) ){
- rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
- storeLastErrno(pFile, errno);
- } else if( lock.l_type!=F_UNLCK ){
- reserved = 1;
- }
- }
-#endif
-
- unixLeaveMutex();
- OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
-
- *pResOut = reserved;
- return rc;
-}
-
-/*
-** Set a posix-advisory-lock.
-**
-** There are two versions of this routine. If compiled with
-** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter
-** which is a pointer to a unixFile. If the unixFile->iBusyTimeout
-** value is set, then it is the number of milliseconds to wait before
-** failing the lock. The iBusyTimeout value is always reset back to
-** zero on each call.
-**
-** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking
-** attempt to set the lock.
-*/
-#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
-# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
-#else
-static int osSetPosixAdvisoryLock(
- int h, /* The file descriptor on which to take the lock */
- struct flock *pLock, /* The description of the lock */
- unixFile *pFile /* Structure holding timeout value */
-){
- int rc = osFcntl(h,F_SETLK,pLock);
- while( rc<0 && pFile->iBusyTimeout>0 ){
- /* On systems that support some kind of blocking file lock with a timeout,
- ** make appropriate changes here to invoke that blocking file lock. On
- ** generic posix, however, there is no such API. So we simply try the
- ** lock once every millisecond until either the timeout expires, or until
- ** the lock is obtained. */
- usleep(1000);
- rc = osFcntl(h,F_SETLK,pLock);
- pFile->iBusyTimeout--;
- }
- return rc;
-}
-#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
-
-
-/*
-** Attempt to set a system-lock on the file pFile. The lock is
-** described by pLock.
-**
-** If the pFile was opened read/write from unix-excl, then the only lock
-** ever obtained is an exclusive lock, and it is obtained exactly once
-** the first time any lock is attempted. All subsequent system locking
-** operations become no-ops. Locking operations still happen internally,
-** in order to coordinate access between separate database connections
-** within this process, but all of that is handled in memory and the
-** operating system does not participate.
-**
-** This function is a pass-through to fcntl(F_SETLK) if pFile is using
-** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
-** and is read-only.
-**
-** Zero is returned if the call completes successfully, or -1 if a call
-** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
-*/
-static int unixFileLock(unixFile *pFile, struct flock *pLock){
- int rc;
- unixInodeInfo *pInode = pFile->pInode;
- assert( unixMutexHeld() );
- assert( pInode!=0 );
- if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
- if( pInode->bProcessLock==0 ){
- struct flock lock;
- assert( pInode->nLock==0 );
- lock.l_whence = SEEK_SET;
- lock.l_start = SHARED_FIRST;
- lock.l_len = SHARED_SIZE;
- lock.l_type = F_WRLCK;
- rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile);
- if( rc<0 ) return rc;
- pInode->bProcessLock = 1;
- pInode->nLock++;
- }else{
- rc = 0;
- }
- }else{
- rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
- }
- return rc;
-}
-
-/*
-** Lock the file with the lock specified by parameter eFileLock - one
-** of the following:
-**
-** (1) SHARED_LOCK
-** (2) RESERVED_LOCK
-** (3) PENDING_LOCK
-** (4) EXCLUSIVE_LOCK
-**
-** Sometimes when requesting one lock state, additional lock states
-** are inserted in between. The locking might fail on one of the later
-** transitions leaving the lock state different from what it started but
-** still short of its goal. The following chart shows the allowed
-** transitions and the inserted intermediate states:
-**
-** UNLOCKED -> SHARED
-** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
-** RESERVED -> (PENDING) -> EXCLUSIVE
-** PENDING -> EXCLUSIVE
-**
-** This routine will only increase a lock. Use the sqlite3OsUnlock()
-** routine to lower a locking level.
-*/
-static int unixLock(sqlite3_file *id, int eFileLock){
- /* The following describes the implementation of the various locks and
- ** lock transitions in terms of the POSIX advisory shared and exclusive
- ** lock primitives (called read-locks and write-locks below, to avoid
- ** confusion with SQLite lock names). The algorithms are complicated
- ** slightly in order to be compatible with Windows95 systems simultaneously
- ** accessing the same database file, in case that is ever required.
- **
- ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
- ** byte', each single bytes at well known offsets, and the 'shared byte
- ** range', a range of 510 bytes at a well known offset.
- **
- ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
- ** byte'. If this is successful, 'shared byte range' is read-locked
- ** and the lock on the 'pending byte' released. (Legacy note: When
- ** SQLite was first developed, Windows95 systems were still very common,
- ** and Widnows95 lacks a shared-lock capability. So on Windows95, a
- ** single randomly selected by from the 'shared byte range' is locked.
- ** Windows95 is now pretty much extinct, but this work-around for the
- ** lack of shared-locks on Windows95 lives on, for backwards
- ** compatibility.)
- **
- ** A process may only obtain a RESERVED lock after it has a SHARED lock.
- ** A RESERVED lock is implemented by grabbing a write-lock on the
- ** 'reserved byte'.
- **
- ** A process may only obtain a PENDING lock after it has obtained a
- ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
- ** on the 'pending byte'. This ensures that no new SHARED locks can be
- ** obtained, but existing SHARED locks are allowed to persist. A process
- ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
- ** This property is used by the algorithm for rolling back a journal file
- ** after a crash.
- **
- ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
- ** implemented by obtaining a write-lock on the entire 'shared byte
- ** range'. Since all other locks require a read-lock on one of the bytes
- ** within this range, this ensures that no other locks are held on the
- ** database.
- */
- int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
- unixInodeInfo *pInode;
- struct flock lock;
- int tErrno = 0;
-
- assert( pFile );
- OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
- azFileLock(eFileLock), azFileLock(pFile->eFileLock),
- azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared,
- osGetpid(0)));
-
- /* If there is already a lock of this type or more restrictive on the
- ** unixFile, do nothing. Don't use the end_lock: exit path, as
- ** unixEnterMutex() hasn't been called yet.
- */
- if( pFile->eFileLock>=eFileLock ){
- OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h,
- azFileLock(eFileLock)));
- return SQLITE_OK;
- }
-
- /* Make sure the locking sequence is correct.
- ** (1) We never move from unlocked to anything higher than shared lock.
- ** (2) SQLite never explicitly requests a pendig lock.
- ** (3) A shared lock is always held when a reserve lock is requested.
- */
- assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
- assert( eFileLock!=PENDING_LOCK );
- assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
-
- /* This mutex is needed because pFile->pInode is shared across threads
- */
- unixEnterMutex();
- pInode = pFile->pInode;
-
- /* If some thread using this PID has a lock via a different unixFile*
- ** handle that precludes the requested lock, return BUSY.
- */
- if( (pFile->eFileLock!=pInode->eFileLock &&
- (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
- ){
- rc = SQLITE_BUSY;
- goto end_lock;
- }
-
- /* If a SHARED lock is requested, and some thread using this PID already
- ** has a SHARED or RESERVED lock, then increment reference counts and
- ** return SQLITE_OK.
- */
- if( eFileLock==SHARED_LOCK &&
- (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
- assert( eFileLock==SHARED_LOCK );
- assert( pFile->eFileLock==0 );
- assert( pInode->nShared>0 );
- pFile->eFileLock = SHARED_LOCK;
- pInode->nShared++;
- pInode->nLock++;
- goto end_lock;
- }
-
-
- /* A PENDING lock is needed before acquiring a SHARED lock and before
- ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
- ** be released.
- */
- lock.l_len = 1L;
- lock.l_whence = SEEK_SET;
- if( eFileLock==SHARED_LOCK
- || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
- ){
- lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
- lock.l_start = PENDING_BYTE;
- if( unixFileLock(pFile, &lock) ){
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( rc!=SQLITE_BUSY ){
- storeLastErrno(pFile, tErrno);
- }
- goto end_lock;
- }
- }
-
-
- /* If control gets to this point, then actually go ahead and make
- ** operating system calls for the specified lock.
- */
- if( eFileLock==SHARED_LOCK ){
- assert( pInode->nShared==0 );
- assert( pInode->eFileLock==0 );
- assert( rc==SQLITE_OK );
-
- /* Now get the read-lock */
- lock.l_start = SHARED_FIRST;
- lock.l_len = SHARED_SIZE;
- if( unixFileLock(pFile, &lock) ){
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- }
-
- /* Drop the temporary PENDING lock */
- lock.l_start = PENDING_BYTE;
- lock.l_len = 1L;
- lock.l_type = F_UNLCK;
- if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
- /* This could happen with a network mount */
- tErrno = errno;
- rc = SQLITE_IOERR_UNLOCK;
- }
-
- if( rc ){
- if( rc!=SQLITE_BUSY ){
- storeLastErrno(pFile, tErrno);
- }
- goto end_lock;
- }else{
- pFile->eFileLock = SHARED_LOCK;
- pInode->nLock++;
- pInode->nShared = 1;
- }
- }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
- /* We are trying for an exclusive lock but another thread in this
- ** same process is still holding a shared lock. */
- rc = SQLITE_BUSY;
- }else{
- /* The request was for a RESERVED or EXCLUSIVE lock. It is
- ** assumed that there is a SHARED or greater lock on the file
- ** already.
- */
- assert( 0!=pFile->eFileLock );
- lock.l_type = F_WRLCK;
-
- assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
- if( eFileLock==RESERVED_LOCK ){
- lock.l_start = RESERVED_BYTE;
- lock.l_len = 1L;
- }else{
- lock.l_start = SHARED_FIRST;
- lock.l_len = SHARED_SIZE;
- }
-
- if( unixFileLock(pFile, &lock) ){
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( rc!=SQLITE_BUSY ){
- storeLastErrno(pFile, tErrno);
- }
- }
- }
-
-
-#ifdef SQLITE_DEBUG
- /* Set up the transaction-counter change checking flags when
- ** transitioning from a SHARED to a RESERVED lock. The change
- ** from SHARED to RESERVED marks the beginning of a normal
- ** write operation (not a hot journal rollback).
- */
- if( rc==SQLITE_OK
- && pFile->eFileLock<=SHARED_LOCK
- && eFileLock==RESERVED_LOCK
- ){
- pFile->transCntrChng = 0;
- pFile->dbUpdate = 0;
- pFile->inNormalWrite = 1;
- }
-#endif
-
-
- if( rc==SQLITE_OK ){
- pFile->eFileLock = eFileLock;
- pInode->eFileLock = eFileLock;
- }else if( eFileLock==EXCLUSIVE_LOCK ){
- pFile->eFileLock = PENDING_LOCK;
- pInode->eFileLock = PENDING_LOCK;
- }
-
-end_lock:
- unixLeaveMutex();
- OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
- rc==SQLITE_OK ? "ok" : "failed"));
- return rc;
-}
-
-/*
-** Add the file descriptor used by file handle pFile to the corresponding
-** pUnused list.
-*/
-static void setPendingFd(unixFile *pFile){
- unixInodeInfo *pInode = pFile->pInode;
- UnixUnusedFd *p = pFile->pPreallocatedUnused;
- p->pNext = pInode->pUnused;
- pInode->pUnused = p;
- pFile->h = -1;
- pFile->pPreallocatedUnused = 0;
- nUnusedFd++;
-}
-
-/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-** must be either NO_LOCK or SHARED_LOCK.
-**
-** If the locking level of the file descriptor is already at or below
-** the requested locking level, this routine is a no-op.
-**
-** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
-** the byte range is divided into 2 parts and the first part is unlocked then
-** set to a read lock, then the other part is simply unlocked. This works
-** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
-** remove the write lock on a region when a read lock is set.
-*/
-static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
- unixFile *pFile = (unixFile*)id;
- unixInodeInfo *pInode;
- struct flock lock;
- int rc = SQLITE_OK;
-
- assert( pFile );
- OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
- pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
- osGetpid(0)));
-
- assert( eFileLock<=SHARED_LOCK );
- if( pFile->eFileLock<=eFileLock ){
- return SQLITE_OK;
- }
- unixEnterMutex();
- pInode = pFile->pInode;
- assert( pInode->nShared!=0 );
- if( pFile->eFileLock>SHARED_LOCK ){
- assert( pInode->eFileLock==pFile->eFileLock );
-
-#ifdef SQLITE_DEBUG
- /* When reducing a lock such that other processes can start
- ** reading the database file again, make sure that the
- ** transaction counter was updated if any part of the database
- ** file changed. If the transaction counter is not updated,
- ** other connections to the same file might not realize that
- ** the file has changed and hence might not know to flush their
- ** cache. The use of a stale cache can lead to database corruption.
- */
- pFile->inNormalWrite = 0;
-#endif
-
- /* downgrading to a shared lock on NFS involves clearing the write lock
- ** before establishing the readlock - to avoid a race condition we downgrade
- ** the lock in 2 blocks, so that part of the range will be covered by a
- ** write lock until the rest is covered by a read lock:
- ** 1: [WWWWW]
- ** 2: [....W]
- ** 3: [RRRRW]
- ** 4: [RRRR.]
- */
- if( eFileLock==SHARED_LOCK ){
-#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
- (void)handleNFSUnlock;
- assert( handleNFSUnlock==0 );
-#endif
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- if( handleNFSUnlock ){
- int tErrno; /* Error code from system call errors */
- off_t divSize = SHARED_SIZE - 1;
-
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = SHARED_FIRST;
- lock.l_len = divSize;
- if( unixFileLock(pFile, &lock)==(-1) ){
- tErrno = errno;
- rc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- goto end_unlock;
- }
- lock.l_type = F_RDLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = SHARED_FIRST;
- lock.l_len = divSize;
- if( unixFileLock(pFile, &lock)==(-1) ){
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
- if( IS_LOCK_ERROR(rc) ){
- storeLastErrno(pFile, tErrno);
- }
- goto end_unlock;
- }
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = SHARED_FIRST+divSize;
- lock.l_len = SHARED_SIZE-divSize;
- if( unixFileLock(pFile, &lock)==(-1) ){
- tErrno = errno;
- rc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- goto end_unlock;
- }
- }else
-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
- {
- lock.l_type = F_RDLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = SHARED_FIRST;
- lock.l_len = SHARED_SIZE;
- if( unixFileLock(pFile, &lock) ){
- /* In theory, the call to unixFileLock() cannot fail because another
- ** process is holding an incompatible lock. If it does, this
- ** indicates that the other process is not following the locking
- ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
- ** SQLITE_BUSY would confuse the upper layer (in practice it causes
- ** an assert to fail). */
- rc = SQLITE_IOERR_RDLOCK;
- storeLastErrno(pFile, errno);
- goto end_unlock;
- }
- }
- }
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = PENDING_BYTE;
- lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
- if( unixFileLock(pFile, &lock)==0 ){
- pInode->eFileLock = SHARED_LOCK;
- }else{
- rc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, errno);
- goto end_unlock;
- }
- }
- if( eFileLock==NO_LOCK ){
- /* Decrement the shared lock counter. Release the lock using an
- ** OS call only when all threads in this same process have released
- ** the lock.
- */
- pInode->nShared--;
- if( pInode->nShared==0 ){
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = lock.l_len = 0L;
- if( unixFileLock(pFile, &lock)==0 ){
- pInode->eFileLock = NO_LOCK;
- }else{
- rc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, errno);
- pInode->eFileLock = NO_LOCK;
- pFile->eFileLock = NO_LOCK;
- }
- }
-
- /* Decrement the count of locks against this same file. When the
- ** count reaches zero, close any other file descriptors whose close
- ** was deferred because of outstanding locks.
- */
- pInode->nLock--;
- assert( pInode->nLock>=0 );
- if( pInode->nLock==0 ){
- closePendingFds(pFile);
- }
- }
-
-end_unlock:
- unixLeaveMutex();
- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
- return rc;
-}
-
-/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-** must be either NO_LOCK or SHARED_LOCK.
-**
-** If the locking level of the file descriptor is already at or below
-** the requested locking level, this routine is a no-op.
-*/
-static int unixUnlock(sqlite3_file *id, int eFileLock){
-#if SQLITE_MAX_MMAP_SIZE>0
- assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
-#endif
- return posixUnlock(id, eFileLock, 0);
-}
-
-#if SQLITE_MAX_MMAP_SIZE>0
-static int unixMapfile(unixFile *pFd, i64 nByte);
-static void unixUnmapfile(unixFile *pFd);
-#endif
-
-/*
-** This function performs the parts of the "close file" operation
-** common to all locking schemes. It closes the directory and file
-** handles, if they are valid, and sets all fields of the unixFile
-** structure to 0.
-**
-** It is *not* necessary to hold the mutex when this routine is called,
-** even on VxWorks. A mutex will be acquired on VxWorks by the
-** vxworksReleaseFileId() routine.
-*/
-static int closeUnixFile(sqlite3_file *id){
- unixFile *pFile = (unixFile*)id;
-#if SQLITE_MAX_MMAP_SIZE>0
- unixUnmapfile(pFile);
-#endif
- if( pFile->h>=0 ){
- robust_close(pFile, pFile->h, __LINE__);
- pFile->h = -1;
- }
-#if OS_VXWORKS
- if( pFile->pId ){
- if( pFile->ctrlFlags & UNIXFILE_DELETE ){
- osUnlink(pFile->pId->zCanonicalName);
- }
- vxworksReleaseFileId(pFile->pId);
- pFile->pId = 0;
- }
-#endif
-#ifdef SQLITE_UNLINK_AFTER_CLOSE
- if( pFile->ctrlFlags & UNIXFILE_DELETE ){
- osUnlink(pFile->zPath);
- sqlite3_free(*(char**)&pFile->zPath);
- pFile->zPath = 0;
- }
-#endif
- OSTRACE(("CLOSE %-3d\n", pFile->h));
- OpenCounter(-1);
- sqlite3_free(pFile->pPreallocatedUnused);
- memset(pFile, 0, sizeof(unixFile));
- return SQLITE_OK;
-}
-
-/*
-** Close a file.
-*/
-static int unixClose(sqlite3_file *id){
- int rc = SQLITE_OK;
- unixFile *pFile = (unixFile *)id;
- verifyDbFile(pFile);
- unixUnlock(id, NO_LOCK);
- unixEnterMutex();
-
- /* unixFile.pInode is always valid here. Otherwise, a different close
- ** routine (e.g. nolockClose()) would be called instead.
- */
- assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
- if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
- /* If there are outstanding locks, do not actually close the file just
- ** yet because that would clear those locks. Instead, add the file
- ** descriptor to pInode->pUnused list. It will be automatically closed
- ** when the last lock is cleared.
- */
- setPendingFd(pFile);
- }
- releaseInodeInfo(pFile);
- rc = closeUnixFile(id);
- unixLeaveMutex();
- return rc;
-}
-
-/************** End of the posix advisory lock implementation *****************
-******************************************************************************/
-
-/******************************************************************************
-****************************** No-op Locking **********************************
-**
-** Of the various locking implementations available, this is by far the
-** simplest: locking is ignored. No attempt is made to lock the database
-** file for reading or writing.
-**
-** This locking mode is appropriate for use on read-only databases
-** (ex: databases that are burned into CD-ROM, for example.) It can
-** also be used if the application employs some external mechanism to
-** prevent simultaneous access of the same database by two or more
-** database connections. But there is a serious risk of database
-** corruption if this locking mode is used in situations where multiple
-** database connections are accessing the same database file at the same
-** time and one or more of those connections are writing.
-*/
-
-static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
- UNUSED_PARAMETER(NotUsed);
- *pResOut = 0;
- return SQLITE_OK;
-}
-static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return SQLITE_OK;
-}
-static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return SQLITE_OK;
-}
-
-/*
-** Close the file.
-*/
-static int nolockClose(sqlite3_file *id) {
- return closeUnixFile(id);
-}
-
-/******************* End of the no-op lock implementation *********************
-******************************************************************************/
-
-/******************************************************************************
-************************* Begin dot-file Locking ******************************
-**
-** The dotfile locking implementation uses the existence of separate lock
-** files (really a directory) to control access to the database. This works
-** on just about every filesystem imaginable. But there are serious downsides:
-**
-** (1) There is zero concurrency. A single reader blocks all other
-** connections from reading or writing the database.
-**
-** (2) An application crash or power loss can leave stale lock files
-** sitting around that need to be cleared manually.
-**
-** Nevertheless, a dotlock is an appropriate locking mode for use if no
-** other locking strategy is available.
-**
-** Dotfile locking works by creating a subdirectory in the same directory as
-** the database and with the same name but with a ".lock" extension added.
-** The existence of a lock directory implies an EXCLUSIVE lock. All other
-** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
-*/
-
-/*
-** The file suffix added to the data base filename in order to create the
-** lock directory.
-*/
-#define DOTLOCK_SUFFIX ".lock"
-
-/*
-** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-**
-** In dotfile locking, either a lock exists or it does not. So in this
-** variation of CheckReservedLock(), *pResOut is set to true if any lock
-** is held on the file and false if the file is unlocked.
-*/
-static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
- unixFile *pFile = (unixFile*)id;
-
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
- reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
- *pResOut = reserved;
- return rc;
-}
-
-/*
-** Lock the file with the lock specified by parameter eFileLock - one
-** of the following:
-**
-** (1) SHARED_LOCK
-** (2) RESERVED_LOCK
-** (3) PENDING_LOCK
-** (4) EXCLUSIVE_LOCK
-**
-** Sometimes when requesting one lock state, additional lock states
-** are inserted in between. The locking might fail on one of the later
-** transitions leaving the lock state different from what it started but
-** still short of its goal. The following chart shows the allowed
-** transitions and the inserted intermediate states:
-**
-** UNLOCKED -> SHARED
-** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
-** RESERVED -> (PENDING) -> EXCLUSIVE
-** PENDING -> EXCLUSIVE
-**
-** This routine will only increase a lock. Use the sqlite3OsUnlock()
-** routine to lower a locking level.
-**
-** With dotfile locking, we really only support state (4): EXCLUSIVE.
-** But we track the other locking levels internally.
-*/
-static int dotlockLock(sqlite3_file *id, int eFileLock) {
- unixFile *pFile = (unixFile*)id;
- char *zLockFile = (char *)pFile->lockingContext;
- int rc = SQLITE_OK;
-
-
- /* If we have any lock, then the lock file already exists. All we have
- ** to do is adjust our internal record of the lock level.
- */
- if( pFile->eFileLock > NO_LOCK ){
- pFile->eFileLock = eFileLock;
- /* Always update the timestamp on the old file */
-#ifdef HAVE_UTIME
- utime(zLockFile, NULL);
-#else
- utimes(zLockFile, NULL);
-#endif
- return SQLITE_OK;
- }
-
- /* grab an exclusive lock */
- rc = osMkdir(zLockFile, 0777);
- if( rc<0 ){
- /* failed to open/create the lock directory */
- int tErrno = errno;
- if( EEXIST == tErrno ){
- rc = SQLITE_BUSY;
- } else {
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( rc!=SQLITE_BUSY ){
- storeLastErrno(pFile, tErrno);
- }
- }
- return rc;
- }
-
- /* got it, set the type and return ok */
- pFile->eFileLock = eFileLock;
- return rc;
-}
-
-/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-** must be either NO_LOCK or SHARED_LOCK.
-**
-** If the locking level of the file descriptor is already at or below
-** the requested locking level, this routine is a no-op.
-**
-** When the locking level reaches NO_LOCK, delete the lock file.
-*/
-static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
- unixFile *pFile = (unixFile*)id;
- char *zLockFile = (char *)pFile->lockingContext;
- int rc;
-
- assert( pFile );
- OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
- pFile->eFileLock, osGetpid(0)));
- assert( eFileLock<=SHARED_LOCK );
-
- /* no-op if possible */
- if( pFile->eFileLock==eFileLock ){
- return SQLITE_OK;
- }
-
- /* To downgrade to shared, simply update our internal notion of the
- ** lock state. No need to mess with the file on disk.
- */
- if( eFileLock==SHARED_LOCK ){
- pFile->eFileLock = SHARED_LOCK;
- return SQLITE_OK;
- }
-
- /* To fully unlock the database, delete the lock file */
- assert( eFileLock==NO_LOCK );
- rc = osRmdir(zLockFile);
- if( rc<0 ){
- int tErrno = errno;
- if( tErrno==ENOENT ){
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- }
- return rc;
- }
- pFile->eFileLock = NO_LOCK;
- return SQLITE_OK;
-}
-
-/*
-** Close a file. Make sure the lock has been released before closing.
-*/
-static int dotlockClose(sqlite3_file *id) {
- unixFile *pFile = (unixFile*)id;
- assert( id!=0 );
- dotlockUnlock(id, NO_LOCK);
- sqlite3_free(pFile->lockingContext);
- return closeUnixFile(id);
-}
-/****************** End of the dot-file lock implementation *******************
-******************************************************************************/
-
-/******************************************************************************
-************************** Begin flock Locking ********************************
-**
-** Use the flock() system call to do file locking.
-**
-** flock() locking is like dot-file locking in that the various
-** fine-grain locking levels supported by SQLite are collapsed into
-** a single exclusive lock. In other words, SHARED, RESERVED, and
-** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
-** still works when you do this, but concurrency is reduced since
-** only a single process can be reading the database at a time.
-**
-** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off
-*/
-#if SQLITE_ENABLE_LOCKING_STYLE
-
-/*
-** Retry flock() calls that fail with EINTR
-*/
-#ifdef EINTR
-static int robust_flock(int fd, int op){
- int rc;
- do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
- return rc;
-}
-#else
-# define robust_flock(a,b) flock(a,b)
-#endif
-
-
-/*
-** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-*/
-static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
- unixFile *pFile = (unixFile*)id;
-
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- /* attempt to get the lock */
- int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
- if( !lrc ){
- /* got the lock, unlock it */
- lrc = robust_flock(pFile->h, LOCK_UN);
- if ( lrc ) {
- int tErrno = errno;
- /* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- } else {
- int tErrno = errno;
- reserved = 1;
- /* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(lrc) ){
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- }
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
-
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & 0xff) == SQLITE_IOERR ){
- rc = SQLITE_OK;
- reserved=1;
- }
-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- *pResOut = reserved;
- return rc;
-}
-
-/*
-** Lock the file with the lock specified by parameter eFileLock - one
-** of the following:
-**
-** (1) SHARED_LOCK
-** (2) RESERVED_LOCK
-** (3) PENDING_LOCK
-** (4) EXCLUSIVE_LOCK
-**
-** Sometimes when requesting one lock state, additional lock states
-** are inserted in between. The locking might fail on one of the later
-** transitions leaving the lock state different from what it started but
-** still short of its goal. The following chart shows the allowed
-** transitions and the inserted intermediate states:
-**
-** UNLOCKED -> SHARED
-** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
-** RESERVED -> (PENDING) -> EXCLUSIVE
-** PENDING -> EXCLUSIVE
-**
-** flock() only really support EXCLUSIVE locks. We track intermediate
-** lock states in the sqlite3_file structure, but all locks SHARED or
-** above are really EXCLUSIVE locks and exclude all other processes from
-** access the file.
-**
-** This routine will only increase a lock. Use the sqlite3OsUnlock()
-** routine to lower a locking level.
-*/
-static int flockLock(sqlite3_file *id, int eFileLock) {
- int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
-
- assert( pFile );
-
- /* if we already have a lock, it is exclusive.
- ** Just adjust level and punt on outta here. */
- if (pFile->eFileLock > NO_LOCK) {
- pFile->eFileLock = eFileLock;
- return SQLITE_OK;
- }
-
- /* grab an exclusive lock */
-
- if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
- int tErrno = errno;
- /* didn't get, must be busy */
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- storeLastErrno(pFile, tErrno);
- }
- } else {
- /* got it, set the type and return ok */
- pFile->eFileLock = eFileLock;
- }
- OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
- rc==SQLITE_OK ? "ok" : "failed"));
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & 0xff) == SQLITE_IOERR ){
- rc = SQLITE_BUSY;
- }
-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- return rc;
-}
-
-
-/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-** must be either NO_LOCK or SHARED_LOCK.
-**
-** If the locking level of the file descriptor is already at or below
-** the requested locking level, this routine is a no-op.
-*/
-static int flockUnlock(sqlite3_file *id, int eFileLock) {
- unixFile *pFile = (unixFile*)id;
-
- assert( pFile );
- OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
- pFile->eFileLock, osGetpid(0)));
- assert( eFileLock<=SHARED_LOCK );
-
- /* no-op if possible */
- if( pFile->eFileLock==eFileLock ){
- return SQLITE_OK;
- }
-
- /* shared can just be set because we always have an exclusive */
- if (eFileLock==SHARED_LOCK) {
- pFile->eFileLock = eFileLock;
- return SQLITE_OK;
- }
-
- /* no, really, unlock. */
- if( robust_flock(pFile->h, LOCK_UN) ){
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- return SQLITE_OK;
-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- return SQLITE_IOERR_UNLOCK;
- }else{
- pFile->eFileLock = NO_LOCK;
- return SQLITE_OK;
- }
-}
-
-/*
-** Close a file.
-*/
-static int flockClose(sqlite3_file *id) {
- assert( id!=0 );
- flockUnlock(id, NO_LOCK);
- return closeUnixFile(id);
-}
-
-#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
-
-/******************* End of the flock lock implementation *********************
-******************************************************************************/
-
-/******************************************************************************
-************************ Begin Named Semaphore Locking ************************
-**
-** Named semaphore locking is only supported on VxWorks.
-**
-** Semaphore locking is like dot-lock and flock in that it really only
-** supports EXCLUSIVE locking. Only a single process can read or write
-** the database file at a time. This reduces potential concurrency, but
-** makes the lock implementation much easier.
-*/
-#if OS_VXWORKS
-
-/*
-** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-*/
-static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
- unixFile *pFile = (unixFile*)id;
-
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- sem_t *pSem = pFile->pInode->pSem;
-
- if( sem_trywait(pSem)==-1 ){
- int tErrno = errno;
- if( EAGAIN != tErrno ){
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
- storeLastErrno(pFile, tErrno);
- } else {
- /* someone else has the lock when we are in NO_LOCK */
- reserved = (pFile->eFileLock < SHARED_LOCK);
- }
- }else{
- /* we could have it if we want it */
- sem_post(pSem);
- }
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
-
- *pResOut = reserved;
- return rc;
-}
-
-/*
-** Lock the file with the lock specified by parameter eFileLock - one
-** of the following:
-**
-** (1) SHARED_LOCK
-** (2) RESERVED_LOCK
-** (3) PENDING_LOCK
-** (4) EXCLUSIVE_LOCK
-**
-** Sometimes when requesting one lock state, additional lock states
-** are inserted in between. The locking might fail on one of the later
-** transitions leaving the lock state different from what it started but
-** still short of its goal. The following chart shows the allowed
-** transitions and the inserted intermediate states:
-**
-** UNLOCKED -> SHARED
-** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
-** RESERVED -> (PENDING) -> EXCLUSIVE
-** PENDING -> EXCLUSIVE
-**
-** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
-** lock states in the sqlite3_file structure, but all locks SHARED or
-** above are really EXCLUSIVE locks and exclude all other processes from
-** access the file.
-**
-** This routine will only increase a lock. Use the sqlite3OsUnlock()
-** routine to lower a locking level.
-*/
-static int semXLock(sqlite3_file *id, int eFileLock) {
- unixFile *pFile = (unixFile*)id;
- sem_t *pSem = pFile->pInode->pSem;
- int rc = SQLITE_OK;
-
- /* if we already have a lock, it is exclusive.
- ** Just adjust level and punt on outta here. */
- if (pFile->eFileLock > NO_LOCK) {
- pFile->eFileLock = eFileLock;
- rc = SQLITE_OK;
- goto sem_end_lock;
- }
-
- /* lock semaphore now but bail out when already locked. */
- if( sem_trywait(pSem)==-1 ){
- rc = SQLITE_BUSY;
- goto sem_end_lock;
- }
-
- /* got it, set the type and return ok */
- pFile->eFileLock = eFileLock;
-
- sem_end_lock:
- return rc;
-}
-
-/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-** must be either NO_LOCK or SHARED_LOCK.
-**
-** If the locking level of the file descriptor is already at or below
-** the requested locking level, this routine is a no-op.
-*/
-static int semXUnlock(sqlite3_file *id, int eFileLock) {
- unixFile *pFile = (unixFile*)id;
- sem_t *pSem = pFile->pInode->pSem;
-
- assert( pFile );
- assert( pSem );
- OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
- pFile->eFileLock, osGetpid(0)));
- assert( eFileLock<=SHARED_LOCK );
-
- /* no-op if possible */
- if( pFile->eFileLock==eFileLock ){
- return SQLITE_OK;
- }
-
- /* shared can just be set because we always have an exclusive */
- if (eFileLock==SHARED_LOCK) {
- pFile->eFileLock = eFileLock;
- return SQLITE_OK;
- }
-
- /* no, really unlock. */
- if ( sem_post(pSem)==-1 ) {
- int rc, tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if( IS_LOCK_ERROR(rc) ){
- storeLastErrno(pFile, tErrno);
- }
- return rc;
- }
- pFile->eFileLock = NO_LOCK;
- return SQLITE_OK;
-}
-
-/*
- ** Close a file.
- */
-static int semXClose(sqlite3_file *id) {
- if( id ){
- unixFile *pFile = (unixFile*)id;
- semXUnlock(id, NO_LOCK);
- assert( pFile );
- unixEnterMutex();
- releaseInodeInfo(pFile);
- unixLeaveMutex();
- closeUnixFile(id);
- }
- return SQLITE_OK;
-}
-
-#endif /* OS_VXWORKS */
-/*
-** Named semaphore locking is only available on VxWorks.
-**
-*************** End of the named semaphore lock implementation ****************
-******************************************************************************/
-
-
-/******************************************************************************
-*************************** Begin AFP Locking *********************************
-**
-** AFP is the Apple Filing Protocol. AFP is a network filesystem found
-** on Apple Macintosh computers - both OS9 and OSX.
-**
-** Third-party implementations of AFP are available. But this code here
-** only works on OSX.
-*/
-
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-/*
-** The afpLockingContext structure contains all afp lock specific state
-*/
-typedef struct afpLockingContext afpLockingContext;
-struct afpLockingContext {
- int reserved;
- const char *dbPath; /* Name of the open file */
-};
-
-struct ByteRangeLockPB2
-{
- unsigned long long offset; /* offset to first byte to lock */
- unsigned long long length; /* nbr of bytes to lock */
- unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
- unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
- unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
- int fd; /* file desc to assoc this lock with */
-};
-
-#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
-
-/*
-** This is a utility for setting or clearing a bit-range lock on an
-** AFP filesystem.
-**
-** Return SQLITE_OK on success, SQLITE_BUSY on failure.
-*/
-static int afpSetLock(
- const char *path, /* Name of the file to be locked or unlocked */
- unixFile *pFile, /* Open file descriptor on path */
- unsigned long long offset, /* First byte to be locked */
- unsigned long long length, /* Number of bytes to lock */
- int setLockFlag /* True to set lock. False to clear lock */
-){
- struct ByteRangeLockPB2 pb;
- int err;
-
- pb.unLockFlag = setLockFlag ? 0 : 1;
- pb.startEndFlag = 0;
- pb.offset = offset;
- pb.length = length;
- pb.fd = pFile->h;
-
- OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
- (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
- offset, length));
- err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
- if ( err==-1 ) {
- int rc;
- int tErrno = errno;
- OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
- path, tErrno, strerror(tErrno)));
-#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
- rc = SQLITE_BUSY;
-#else
- rc = sqliteErrorFromPosixError(tErrno,
- setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
-#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
- if( IS_LOCK_ERROR(rc) ){
- storeLastErrno(pFile, tErrno);
- }
- return rc;
- } else {
- return SQLITE_OK;
- }
-}
-
-/*
-** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-*/
-static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
- unixFile *pFile = (unixFile*)id;
- afpLockingContext *context;
-
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
- context = (afpLockingContext *) pFile->lockingContext;
- if( context->reserved ){
- *pResOut = 1;
- return SQLITE_OK;
- }
- unixEnterMutex(); /* Because pFile->pInode is shared across threads */
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->pInode->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it.
- */
- if( !reserved ){
- /* lock the RESERVED byte */
- int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
- if( SQLITE_OK==lrc ){
- /* if we succeeded in taking the reserved lock, unlock it to restore
- ** the original state */
- lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
- } else {
- /* if we failed to get the lock then someone else must have it */
- reserved = 1;
- }
- if( IS_LOCK_ERROR(lrc) ){
- rc=lrc;
- }
- }
-
- unixLeaveMutex();
- OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
-
- *pResOut = reserved;
- return rc;
-}
-
-/*
-** Lock the file with the lock specified by parameter eFileLock - one
-** of the following:
-**
-** (1) SHARED_LOCK
-** (2) RESERVED_LOCK
-** (3) PENDING_LOCK
-** (4) EXCLUSIVE_LOCK
-**
-** Sometimes when requesting one lock state, additional lock states
-** are inserted in between. The locking might fail on one of the later
-** transitions leaving the lock state different from what it started but
-** still short of its goal. The following chart shows the allowed
-** transitions and the inserted intermediate states:
-**
-** UNLOCKED -> SHARED
-** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
-** RESERVED -> (PENDING) -> EXCLUSIVE
-** PENDING -> EXCLUSIVE
-**
-** This routine will only increase a lock. Use the sqlite3OsUnlock()
-** routine to lower a locking level.
-*/
-static int afpLock(sqlite3_file *id, int eFileLock){
- int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
- unixInodeInfo *pInode = pFile->pInode;
- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
-
- assert( pFile );
- OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
- azFileLock(eFileLock), azFileLock(pFile->eFileLock),
- azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0)));
-
- /* If there is already a lock of this type or more restrictive on the
- ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
- ** unixEnterMutex() hasn't been called yet.
- */
- if( pFile->eFileLock>=eFileLock ){
- OSTRACE(("LOCK %d %s ok (already held) (afp)\n", pFile->h,
- azFileLock(eFileLock)));
- return SQLITE_OK;
- }
-
- /* Make sure the locking sequence is correct
- ** (1) We never move from unlocked to anything higher than shared lock.
- ** (2) SQLite never explicitly requests a pendig lock.
- ** (3) A shared lock is always held when a reserve lock is requested.
- */
- assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
- assert( eFileLock!=PENDING_LOCK );
- assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
-
- /* This mutex is needed because pFile->pInode is shared across threads
- */
- unixEnterMutex();
- pInode = pFile->pInode;
-
- /* If some thread using this PID has a lock via a different unixFile*
- ** handle that precludes the requested lock, return BUSY.
- */
- if( (pFile->eFileLock!=pInode->eFileLock &&
- (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
- ){
- rc = SQLITE_BUSY;
- goto afp_end_lock;
- }
-
- /* If a SHARED lock is requested, and some thread using this PID already
- ** has a SHARED or RESERVED lock, then increment reference counts and
- ** return SQLITE_OK.
- */
- if( eFileLock==SHARED_LOCK &&
- (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
- assert( eFileLock==SHARED_LOCK );
- assert( pFile->eFileLock==0 );
- assert( pInode->nShared>0 );
- pFile->eFileLock = SHARED_LOCK;
- pInode->nShared++;
- pInode->nLock++;
- goto afp_end_lock;
- }
-
- /* A PENDING lock is needed before acquiring a SHARED lock and before
- ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
- ** be released.
- */
- if( eFileLock==SHARED_LOCK
- || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
- ){
- int failed;
- failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
- if (failed) {
- rc = failed;
- goto afp_end_lock;
- }
- }
-
- /* If control gets to this point, then actually go ahead and make
- ** operating system calls for the specified lock.
- */
- if( eFileLock==SHARED_LOCK ){
- int lrc1, lrc2, lrc1Errno = 0;
- long lk, mask;
-
- assert( pInode->nShared==0 );
- assert( pInode->eFileLock==0 );
-
- mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
- /* Now get the read-lock SHARED_LOCK */
- /* note that the quality of the randomness doesn't matter that much */
- lk = random();
- pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
- lrc1 = afpSetLock(context->dbPath, pFile,
- SHARED_FIRST+pInode->sharedByte, 1, 1);
- if( IS_LOCK_ERROR(lrc1) ){
- lrc1Errno = pFile->lastErrno;
- }
- /* Drop the temporary PENDING lock */
- lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
-
- if( IS_LOCK_ERROR(lrc1) ) {
- storeLastErrno(pFile, lrc1Errno);
- rc = lrc1;
- goto afp_end_lock;
- } else if( IS_LOCK_ERROR(lrc2) ){
- rc = lrc2;
- goto afp_end_lock;
- } else if( lrc1 != SQLITE_OK ) {
- rc = lrc1;
- } else {
- pFile->eFileLock = SHARED_LOCK;
- pInode->nLock++;
- pInode->nShared = 1;
- }
- }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
- /* We are trying for an exclusive lock but another thread in this
- ** same process is still holding a shared lock. */
- rc = SQLITE_BUSY;
- }else{
- /* The request was for a RESERVED or EXCLUSIVE lock. It is
- ** assumed that there is a SHARED or greater lock on the file
- ** already.
- */
- int failed = 0;
- assert( 0!=pFile->eFileLock );
- if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
- /* Acquire a RESERVED lock */
- failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
- if( !failed ){
- context->reserved = 1;
- }
- }
- if (!failed && eFileLock == EXCLUSIVE_LOCK) {
- /* Acquire an EXCLUSIVE lock */
-
- /* Remove the shared lock before trying the range. we'll need to
- ** reestablish the shared lock if we can't get the afpUnlock
- */
- if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
- pInode->sharedByte, 1, 0)) ){
- int failed2 = SQLITE_OK;
- /* now attemmpt to get the exclusive lock range */
- failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
- SHARED_SIZE, 1);
- if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
- SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
- /* Can't reestablish the shared lock. Sqlite can't deal, this is
- ** a critical I/O error
- */
- rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 :
- SQLITE_IOERR_LOCK;
- goto afp_end_lock;
- }
- }else{
- rc = failed;
- }
- }
- if( failed ){
- rc = failed;
- }
- }
-
- if( rc==SQLITE_OK ){
- pFile->eFileLock = eFileLock;
- pInode->eFileLock = eFileLock;
- }else if( eFileLock==EXCLUSIVE_LOCK ){
- pFile->eFileLock = PENDING_LOCK;
- pInode->eFileLock = PENDING_LOCK;
- }
-
-afp_end_lock:
- unixLeaveMutex();
- OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
- rc==SQLITE_OK ? "ok" : "failed"));
- return rc;
-}
-
-/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-** must be either NO_LOCK or SHARED_LOCK.
-**
-** If the locking level of the file descriptor is already at or below
-** the requested locking level, this routine is a no-op.
-*/
-static int afpUnlock(sqlite3_file *id, int eFileLock) {
- int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
- unixInodeInfo *pInode;
- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
- int skipShared = 0;
-#ifdef SQLITE_TEST
- int h = pFile->h;
-#endif
-
- assert( pFile );
- OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
- pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
- osGetpid(0)));
-
- assert( eFileLock<=SHARED_LOCK );
- if( pFile->eFileLock<=eFileLock ){
- return SQLITE_OK;
- }
- unixEnterMutex();
- pInode = pFile->pInode;
- assert( pInode->nShared!=0 );
- if( pFile->eFileLock>SHARED_LOCK ){
- assert( pInode->eFileLock==pFile->eFileLock );
- SimulateIOErrorBenign(1);
- SimulateIOError( h=(-1) )
- SimulateIOErrorBenign(0);
-
-#ifdef SQLITE_DEBUG
- /* When reducing a lock such that other processes can start
- ** reading the database file again, make sure that the
- ** transaction counter was updated if any part of the database
- ** file changed. If the transaction counter is not updated,
- ** other connections to the same file might not realize that
- ** the file has changed and hence might not know to flush their
- ** cache. The use of a stale cache can lead to database corruption.
- */
- assert( pFile->inNormalWrite==0
- || pFile->dbUpdate==0
- || pFile->transCntrChng==1 );
- pFile->inNormalWrite = 0;
-#endif
-
- if( pFile->eFileLock==EXCLUSIVE_LOCK ){
- rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
- if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
- /* only re-establish the shared lock if necessary */
- int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
- rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
- } else {
- skipShared = 1;
- }
- }
- if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
- rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
- }
- if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
- rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
- if( !rc ){
- context->reserved = 0;
- }
- }
- if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
- pInode->eFileLock = SHARED_LOCK;
- }
- }
- if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
-
- /* Decrement the shared lock counter. Release the lock using an
- ** OS call only when all threads in this same process have released
- ** the lock.
- */
- unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
- pInode->nShared--;
- if( pInode->nShared==0 ){
- SimulateIOErrorBenign(1);
- SimulateIOError( h=(-1) )
- SimulateIOErrorBenign(0);
- if( !skipShared ){
- rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
- }
- if( !rc ){
- pInode->eFileLock = NO_LOCK;
- pFile->eFileLock = NO_LOCK;
- }
- }
- if( rc==SQLITE_OK ){
- pInode->nLock--;
- assert( pInode->nLock>=0 );
- if( pInode->nLock==0 ){
- closePendingFds(pFile);
- }
- }
- }
-
- unixLeaveMutex();
- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
- return rc;
-}
-
-/*
-** Close a file & cleanup AFP specific locking context
-*/
-static int afpClose(sqlite3_file *id) {
- int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
- assert( id!=0 );
- afpUnlock(id, NO_LOCK);
- unixEnterMutex();
- if( pFile->pInode && pFile->pInode->nLock ){
- /* If there are outstanding locks, do not actually close the file just
- ** yet because that would clear those locks. Instead, add the file
- ** descriptor to pInode->aPending. It will be automatically closed when
- ** the last lock is cleared.
- */
- setPendingFd(pFile);
- }
- releaseInodeInfo(pFile);
- sqlite3_free(pFile->lockingContext);
- rc = closeUnixFile(id);
- unixLeaveMutex();
- return rc;
-}
-
-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-/*
-** The code above is the AFP lock implementation. The code is specific
-** to MacOSX and does not work on other unix platforms. No alternative
-** is available. If you don't compile for a mac, then the "unix-afp"
-** VFS is not available.
-**
-********************* End of the AFP lock implementation **********************
-******************************************************************************/
-
-/******************************************************************************
-*************************** Begin NFS Locking ********************************/
-
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-/*
- ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
- ** must be either NO_LOCK or SHARED_LOCK.
- **
- ** If the locking level of the file descriptor is already at or below
- ** the requested locking level, this routine is a no-op.
- */
-static int nfsUnlock(sqlite3_file *id, int eFileLock){
- return posixUnlock(id, eFileLock, 1);
-}
-
-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-/*
-** The code above is the NFS lock implementation. The code is specific
-** to MacOSX and does not work on other unix platforms. No alternative
-** is available.
-**
-********************* End of the NFS lock implementation **********************
-******************************************************************************/
-
-/******************************************************************************
-**************** Non-locking sqlite3_file methods *****************************
-**
-** The next division contains implementations for all methods of the
-** sqlite3_file object other than the locking methods. The locking
-** methods were defined in divisions above (one locking method per
-** division). Those methods that are common to all locking modes
-** are gather together into this division.
-*/
-
-/*
-** Seek to the offset passed as the second argument, then read cnt
-** bytes into pBuf. Return the number of bytes actually read.
-**
-** NB: If you define USE_PREAD or USE_PREAD64, then it might also
-** be necessary to define _XOPEN_SOURCE to be 500. This varies from
-** one system to another. Since SQLite does not define USE_PREAD
-** in any form by default, we will not attempt to define _XOPEN_SOURCE.
-** See tickets #2741 and #2681.
-**
-** To avoid stomping the errno value on a failed read the lastErrno value
-** is set before returning.
-*/
-static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
- int got;
- int prior = 0;
-#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
- i64 newOffset;
-#endif
- TIMER_START;
- assert( cnt==(cnt&0x1ffff) );
- assert( id->h>2 );
- do{
-#if defined(USE_PREAD)
- got = osPread(id->h, pBuf, cnt, offset);
- SimulateIOError( got = -1 );
-#elif defined(USE_PREAD64)
- got = osPread64(id->h, pBuf, cnt, offset);
- SimulateIOError( got = -1 );
-#else
- newOffset = lseek(id->h, offset, SEEK_SET);
- SimulateIOError( newOffset = -1 );
- if( newOffset<0 ){
- storeLastErrno((unixFile*)id, errno);
- return -1;
- }
- got = osRead(id->h, pBuf, cnt);
-#endif
- if( got==cnt ) break;
- if( got<0 ){
- if( errno==EINTR ){ got = 1; continue; }
- prior = 0;
- storeLastErrno((unixFile*)id, errno);
- break;
- }else if( got>0 ){
- cnt -= got;
- offset += got;
- prior += got;
- pBuf = (void*)(got + (char*)pBuf);
- }
- }while( got>0 );
- TIMER_END;
- OSTRACE(("READ %-3d %5d %7lld %llu\n",
- id->h, got+prior, offset-prior, TIMER_ELAPSED));
- return got+prior;
-}
-
-/*
-** Read data from a file into a buffer. Return SQLITE_OK if all
-** bytes were read successfully and SQLITE_IOERR if anything goes
-** wrong.
-*/
-static int unixRead(
- sqlite3_file *id,
- void *pBuf,
- int amt,
- sqlite3_int64 offset
-){
- unixFile *pFile = (unixFile *)id;
- int got;
- assert( id );
- assert( offset>=0 );
- assert( amt>0 );
-
- /* If this is a database file (not a journal, master-journal or temp
- ** file), the bytes in the locking range should never be read or written. */
-#if 0
- assert( pFile->pPreallocatedUnused==0
- || offset>=PENDING_BYTE+512
- || offset+amt<=PENDING_BYTE
- );
-#endif
-
-#if SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this read request as possible by transfering
- ** data from the memory mapping using memcpy(). */
- if( offset<pFile->mmapSize ){
- if( offset+amt <= pFile->mmapSize ){
- memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
- return SQLITE_OK;
- }else{
- int nCopy = pFile->mmapSize - offset;
- memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
- pBuf = &((u8 *)pBuf)[nCopy];
- amt -= nCopy;
- offset += nCopy;
- }
- }
-#endif
-
- got = seekAndRead(pFile, offset, pBuf, amt);
- if( got==amt ){
- return SQLITE_OK;
- }else if( got<0 ){
- /* lastErrno set by seekAndRead */
- return SQLITE_IOERR_READ;
- }else{
- storeLastErrno(pFile, 0); /* not a system error */
- /* Unread parts of the buffer must be zero-filled */
- memset(&((char*)pBuf)[got], 0, amt-got);
- return SQLITE_IOERR_SHORT_READ;
- }
-}
-
-/*
-** Attempt to seek the file-descriptor passed as the first argument to
-** absolute offset iOff, then attempt to write nBuf bytes of data from
-** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
-** return the actual number of bytes written (which may be less than
-** nBuf).
-*/
-static int seekAndWriteFd(
- int fd, /* File descriptor to write to */
- i64 iOff, /* File offset to begin writing at */
- const void *pBuf, /* Copy data from this buffer to the file */
- int nBuf, /* Size of buffer pBuf in bytes */
- int *piErrno /* OUT: Error number if error occurs */
-){
- int rc = 0; /* Value returned by system call */
-
- assert( nBuf==(nBuf&0x1ffff) );
- assert( fd>2 );
- assert( piErrno!=0 );
- nBuf &= 0x1ffff;
- TIMER_START;
-
-#if defined(USE_PREAD)
- do{ rc = (int)osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
-#elif defined(USE_PREAD64)
- do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
-#else
- do{
- i64 iSeek = lseek(fd, iOff, SEEK_SET);
- SimulateIOError( iSeek = -1 );
- if( iSeek<0 ){
- rc = -1;
- break;
- }
- rc = osWrite(fd, pBuf, nBuf);
- }while( rc<0 && errno==EINTR );
-#endif
-
- TIMER_END;
- OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
-
- if( rc<0 ) *piErrno = errno;
- return rc;
-}
-
-
-/*
-** Seek to the offset in id->offset then read cnt bytes into pBuf.
-** Return the number of bytes actually read. Update the offset.
-**
-** To avoid stomping the errno value on a failed write the lastErrno value
-** is set before returning.
-*/
-static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
- return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
-}
-
-
-/*
-** Write data from a buffer into a file. Return SQLITE_OK on success
-** or some other error code on failure.
-*/
-static int unixWrite(
- sqlite3_file *id,
- const void *pBuf,
- int amt,
- sqlite3_int64 offset
-){
- unixFile *pFile = (unixFile*)id;
- int wrote = 0;
- assert( id );
- assert( amt>0 );
-
- /* If this is a database file (not a journal, master-journal or temp
- ** file), the bytes in the locking range should never be read or written. */
-#if 0
- assert( pFile->pPreallocatedUnused==0
- || offset>=PENDING_BYTE+512
- || offset+amt<=PENDING_BYTE
- );
-#endif
-
-#ifdef SQLITE_DEBUG
- /* If we are doing a normal write to a database file (as opposed to
- ** doing a hot-journal rollback or a write to some file other than a
- ** normal database file) then record the fact that the database
- ** has changed. If the transaction counter is modified, record that
- ** fact too.
- */
- if( pFile->inNormalWrite ){
- pFile->dbUpdate = 1; /* The database has been modified */
- if( offset<=24 && offset+amt>=27 ){
- int rc;
- char oldCntr[4];
- SimulateIOErrorBenign(1);
- rc = seekAndRead(pFile, 24, oldCntr, 4);
- SimulateIOErrorBenign(0);
- if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
- pFile->transCntrChng = 1; /* The transaction counter has changed */
- }
- }
- }
-#endif
-
-#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this write request as possible by transfering
- ** data from the memory mapping using memcpy(). */
- if( offset<pFile->mmapSize ){
- if( offset+amt <= pFile->mmapSize ){
- memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
- return SQLITE_OK;
- }else{
- int nCopy = pFile->mmapSize - offset;
- memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
- pBuf = &((u8 *)pBuf)[nCopy];
- amt -= nCopy;
- offset += nCopy;
- }
- }
-#endif
-
- while( (wrote = seekAndWrite(pFile, offset, pBuf, amt))<amt && wrote>0 ){
- amt -= wrote;
- offset += wrote;
- pBuf = &((char*)pBuf)[wrote];
- }
- SimulateIOError(( wrote=(-1), amt=1 ));
- SimulateDiskfullError(( wrote=0, amt=1 ));
-
- if( amt>wrote ){
- if( wrote<0 && pFile->lastErrno!=ENOSPC ){
- /* lastErrno set by seekAndWrite */
- return SQLITE_IOERR_WRITE;
- }else{
- storeLastErrno(pFile, 0); /* not a system error */
- return SQLITE_FULL;
- }
- }
-
- return SQLITE_OK;
-}
-
-#ifdef SQLITE_TEST
-/*
-** Count the number of fullsyncs and normal syncs. This is used to test
-** that syncs and fullsyncs are occurring at the right times.
-*/
-int sqlite3_sync_count = 0;
-int sqlite3_fullsync_count = 0;
-#endif
-
-/*
-** We do not trust systems to provide a working fdatasync(). Some do.
-** Others do no. To be safe, we will stick with the (slightly slower)
-** fsync(). If you know that your system does support fdatasync() correctly,
-** then simply compile with -Dfdatasync=fdatasync or -DHAVE_FDATASYNC
-*/
-#if !defined(fdatasync) && !HAVE_FDATASYNC
-# define fdatasync fsync
-#endif
-
-/*
-** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
-** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently
-** only available on Mac OS X. But that could change.
-*/
-#ifdef F_FULLFSYNC
-# define HAVE_FULLFSYNC 1
-#else
-# define HAVE_FULLFSYNC 0
-#endif
-
-
-/*
-** The fsync() system call does not work as advertised on many
-** unix systems. The following procedure is an attempt to make
-** it work better.
-**
-** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
-** for testing when we want to run through the test suite quickly.
-** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
-** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
-** or power failure will likely corrupt the database file.
-**
-** SQLite sets the dataOnly flag if the size of the file is unchanged.
-** The idea behind dataOnly is that it should only write the file content
-** to disk, not the inode. We only set dataOnly if the file size is
-** unchanged since the file size is part of the inode. However,
-** Ted Ts'o tells us that fdatasync() will also write the inode if the
-** file size has changed. The only real difference between fdatasync()
-** and fsync(), Ted tells us, is that fdatasync() will not flush the
-** inode if the mtime or owner or other inode attributes have changed.
-** We only care about the file size, not the other file attributes, so
-** as far as SQLite is concerned, an fdatasync() is always adequate.
-** So, we always use fdatasync() if it is available, regardless of
-** the value of the dataOnly flag.
-*/
-static int full_fsync(int fd, int fullSync, int dataOnly){
- int rc;
-
- /* The following "ifdef/elif/else/" block has the same structure as
- ** the one below. It is replicated here solely to avoid cluttering
- ** up the real code with the UNUSED_PARAMETER() macros.
- */
-#ifdef SQLITE_NO_SYNC
- UNUSED_PARAMETER(fd);
- UNUSED_PARAMETER(fullSync);
- UNUSED_PARAMETER(dataOnly);
-#elif HAVE_FULLFSYNC
- UNUSED_PARAMETER(dataOnly);
-#else
- UNUSED_PARAMETER(fullSync);
- UNUSED_PARAMETER(dataOnly);
-#endif
-
- /* Record the number of times that we do a normal fsync() and
- ** FULLSYNC. This is used during testing to verify that this procedure
- ** gets called with the correct arguments.
- */
-#ifdef SQLITE_TEST
- if( fullSync ) sqlite3_fullsync_count++;
- sqlite3_sync_count++;
-#endif
-
- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
- ** no-op. But go ahead and call fstat() to validate the file
- ** descriptor as we need a method to provoke a failure during
- ** coverate testing.
- */
-#ifdef SQLITE_NO_SYNC
- {
- struct stat buf;
- rc = osFstat(fd, &buf);
- }
-#elif HAVE_FULLFSYNC
- if( fullSync ){
- rc = osFcntl(fd, F_FULLFSYNC, 0);
- }else{
- rc = 1;
- }
- /* If the FULLFSYNC failed, fall back to attempting an fsync().
- ** It shouldn't be possible for fullfsync to fail on the local
- ** file system (on OSX), so failure indicates that FULLFSYNC
- ** isn't supported for this file system. So, attempt an fsync
- ** and (for now) ignore the overhead of a superfluous fcntl call.
- ** It'd be better to detect fullfsync support once and avoid
- ** the fcntl call every time sync is called.
- */
- if( rc ) rc = fsync(fd);
-
-#elif defined(__APPLE__)
- /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
- ** so currently we default to the macro that redefines fdatasync to fsync
- */
- rc = fsync(fd);
-#else
- rc = fdatasync(fd);
-#if OS_VXWORKS
- if( rc==-1 && errno==ENOTSUP ){
- rc = fsync(fd);
- }
-#endif /* OS_VXWORKS */
-#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
-
- if( OS_VXWORKS && rc!= -1 ){
- rc = 0;
- }
- return rc;
-}
-
-/*
-** Open a file descriptor to the directory containing file zFilename.
-** If successful, *pFd is set to the opened file descriptor and
-** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
-** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
-** value.
-**
-** The directory file descriptor is used for only one thing - to
-** fsync() a directory to make sure file creation and deletion events
-** are flushed to disk. Such fsyncs are not needed on newer
-** journaling filesystems, but are required on older filesystems.
-**
-** This routine can be overridden using the xSetSysCall interface.
-** The ability to override this routine was added in support of the
-** chromium sandbox. Opening a directory is a security risk (we are
-** told) so making it overrideable allows the chromium sandbox to
-** replace this routine with a harmless no-op. To make this routine
-** a no-op, replace it with a stub that returns SQLITE_OK but leaves
-** *pFd set to a negative number.
-**
-** If SQLITE_OK is returned, the caller is responsible for closing
-** the file descriptor *pFd using close().
-*/
-static int openDirectory(const char *zFilename, int *pFd){
- int ii;
- int fd = -1;
- char zDirname[MAX_PATHNAME+1];
-
- sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
- for(ii=(int)strlen(zDirname); ii>0 && zDirname[ii]!='/'; ii--);
- if( ii>0 ){
- zDirname[ii] = '\0';
- }else{
- if( zDirname[0]!='/' ) zDirname[0] = '.';
- zDirname[1] = 0;
- }
- fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
- if( fd>=0 ){
- OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
- }
- *pFd = fd;
- if( fd>=0 ) return SQLITE_OK;
- return unixLogError(SQLITE_CANTOPEN_BKPT, "openDirectory", zDirname);
-}
-
-/*
-** Make sure all writes to a particular file are committed to disk.
-**
-** If dataOnly==0 then both the file itself and its metadata (file
-** size, access time, etc) are synced. If dataOnly!=0 then only the
-** file data is synced.
-**
-** Under Unix, also make sure that the directory entry for the file
-** has been created by fsync-ing the directory that contains the file.
-** If we do not do this and we encounter a power failure, the directory
-** entry for the journal might not exist after we reboot. The next
-** SQLite to access the file will not know that the journal exists (because
-** the directory entry for the journal was never created) and the transaction
-** will not roll back - possibly leading to database corruption.
-*/
-static int unixSync(sqlite3_file *id, int flags){
- int rc;
- unixFile *pFile = (unixFile*)id;
-
- int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
- int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
-
- /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
- assert((flags&0x0F)==SQLITE_SYNC_NORMAL
- || (flags&0x0F)==SQLITE_SYNC_FULL
- );
-
- /* Unix cannot, but some systems may return SQLITE_FULL from here. This
- ** line is to test that doing so does not cause any problems.
- */
- SimulateDiskfullError( return SQLITE_FULL );
-
- assert( pFile );
- OSTRACE(("SYNC %-3d\n", pFile->h));
- rc = full_fsync(pFile->h, isFullsync, isDataOnly);
- SimulateIOError( rc=1 );
- if( rc ){
- storeLastErrno(pFile, errno);
- return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
- }
-
- /* Also fsync the directory containing the file if the DIRSYNC flag
- ** is set. This is a one-time occurrence. Many systems (examples: AIX)
- ** are unable to fsync a directory, so ignore errors on the fsync.
- */
- if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
- int dirfd;
- OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
- HAVE_FULLFSYNC, isFullsync));
- rc = osOpenDirectory(pFile->zPath, &dirfd);
- if( rc==SQLITE_OK ){
- full_fsync(dirfd, 0, 0);
- robust_close(pFile, dirfd, __LINE__);
- }else{
- assert( rc==SQLITE_CANTOPEN );
- rc = SQLITE_OK;
- }
- pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
- }
- return rc;
-}
-
-/*
-** Truncate an open file to a specified size
-*/
-static int unixTruncate(sqlite3_file *id, i64 nByte){
- unixFile *pFile = (unixFile *)id;
- int rc;
- assert( pFile );
- SimulateIOError( return SQLITE_IOERR_TRUNCATE );
-
- /* If the user has configured a chunk-size for this file, truncate the
- ** file so that it consists of an integer number of chunks (i.e. the
- ** actual file size after the operation may be larger than the requested
- ** size).
- */
- if( pFile->szChunk>0 ){
- nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
- }
-
- rc = robust_ftruncate(pFile->h, nByte);
- if( rc ){
- storeLastErrno(pFile, errno);
- return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
- }else{
-#ifdef SQLITE_DEBUG
- /* If we are doing a normal write to a database file (as opposed to
- ** doing a hot-journal rollback or a write to some file other than a
- ** normal database file) and we truncate the file to zero length,
- ** that effectively updates the change counter. This might happen
- ** when restoring a database using the backup API from a zero-length
- ** source.
- */
- if( pFile->inNormalWrite && nByte==0 ){
- pFile->transCntrChng = 1;
- }
-#endif
-
-#if SQLITE_MAX_MMAP_SIZE>0
- /* If the file was just truncated to a size smaller than the currently
- ** mapped region, reduce the effective mapping size as well. SQLite will
- ** use read() and write() to access data beyond this point from now on.
- */
- if( nByte<pFile->mmapSize ){
- pFile->mmapSize = nByte;
- }
-#endif
-
- return SQLITE_OK;
- }
-}
-
-/*
-** Determine the current size of a file in bytes
-*/
-static int unixFileSize(sqlite3_file *id, i64 *pSize){
- int rc;
- struct stat buf;
- assert( id );
- rc = osFstat(((unixFile*)id)->h, &buf);
- SimulateIOError( rc=1 );
- if( rc!=0 ){
- storeLastErrno((unixFile*)id, errno);
- return SQLITE_IOERR_FSTAT;
- }
- *pSize = buf.st_size;
-
- /* When opening a zero-size database, the findInodeInfo() procedure
- ** writes a single byte into that file in order to work around a bug
- ** in the OS-X msdos filesystem. In order to avoid problems with upper
- ** layers, we need to report this file size as zero even though it is
- ** really 1. Ticket #3260.
- */
- if( *pSize==1 ) *pSize = 0;
-
-
- return SQLITE_OK;
-}
-
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-/*
-** Handler for proxy-locking file-control verbs. Defined below in the
-** proxying locking division.
-*/
-static int proxyFileControl(sqlite3_file*,int,void*);
-#endif
-
-/*
-** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
-** file-control operation. Enlarge the database to nBytes in size
-** (rounded up to the next chunk-size). If the database is already
-** nBytes or larger, this routine is a no-op.
-*/
-static int fcntlSizeHint(unixFile *pFile, i64 nByte){
- if( pFile->szChunk>0 ){
- i64 nSize; /* Required file size */
- struct stat buf; /* Used to hold return values of fstat() */
-
- if( osFstat(pFile->h, &buf) ){
- return SQLITE_IOERR_FSTAT;
- }
-
- nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
- if( nSize>(i64)buf.st_size ){
-
-#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
- /* The code below is handling the return value of osFallocate()
- ** correctly. posix_fallocate() is defined to "returns zero on success,
- ** or an error number on failure". See the manpage for details. */
- int err;
- do{
- err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
- }while( err==EINTR );
- if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE;
-#else
- /* If the OS does not have posix_fallocate(), fake it. Write a
- ** single byte to the last byte in each block that falls entirely
- ** within the extended region. Then, if required, a single byte
- ** at offset (nSize-1), to set the size of the file correctly.
- ** This is a similar technique to that used by glibc on systems
- ** that do not have a real fallocate() call.
- */
- int nBlk = buf.st_blksize; /* File-system block size */
- int nWrite = 0; /* Number of bytes written by seekAndWrite */
- i64 iWrite; /* Next offset to write to */
-
- iWrite = (buf.st_size/nBlk)*nBlk + nBlk - 1;
- assert( iWrite>=buf.st_size );
- assert( ((iWrite+1)%nBlk)==0 );
- for(/*no-op*/; iWrite<nSize+nBlk-1; iWrite+=nBlk ){
- if( iWrite>=nSize ) iWrite = nSize - 1;
- nWrite = seekAndWrite(pFile, iWrite, "", 1);
- if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
- }
-#endif
- }
- }
-
-#if SQLITE_MAX_MMAP_SIZE>0
- if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
- int rc;
- if( pFile->szChunk<=0 ){
- if( robust_ftruncate(pFile->h, nByte) ){
- storeLastErrno(pFile, errno);
- return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
- }
- }
-
- rc = unixMapfile(pFile, nByte);
- return rc;
- }
-#endif
-
- return SQLITE_OK;
-}
-
-/*
-** If *pArg is initially negative then this is a query. Set *pArg to
-** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
-**
-** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
-*/
-static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
- if( *pArg<0 ){
- *pArg = (pFile->ctrlFlags & mask)!=0;
- }else if( (*pArg)==0 ){
- pFile->ctrlFlags &= ~mask;
- }else{
- pFile->ctrlFlags |= mask;
- }
-}
-
-/* Forward declaration */
-static int unixGetTempname(int nBuf, char *zBuf);
-
-/*
-** Information and control of an open file handle.
-*/
-static int unixFileControl(sqlite3_file *id, int op, void *pArg){
- unixFile *pFile = (unixFile*)id;
- switch( op ){
-#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
- case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: {
- int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE);
- return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK;
- }
- case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: {
- int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE);
- return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK;
- }
- case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
- int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE);
- return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK;
- }
-#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
-
- case SQLITE_FCNTL_LOCKSTATE: {
- *(int*)pArg = pFile->eFileLock;
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_LAST_ERRNO: {
- *(int*)pArg = pFile->lastErrno;
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_CHUNK_SIZE: {
- pFile->szChunk = *(int *)pArg;
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_SIZE_HINT: {
- int rc;
- SimulateIOErrorBenign(1);
- rc = fcntlSizeHint(pFile, *(i64 *)pArg);
- SimulateIOErrorBenign(0);
- return rc;
- }
- case SQLITE_FCNTL_PERSIST_WAL: {
- unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
- unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_VFSNAME: {
- *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_TEMPFILENAME: {
- char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname );
- if( zTFile ){
- unixGetTempname(pFile->pVfs->mxPathname, zTFile);
- *(char**)pArg = zTFile;
- }
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_HAS_MOVED: {
- *(int*)pArg = fileHasMoved(pFile);
- return SQLITE_OK;
- }
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- case SQLITE_FCNTL_LOCK_TIMEOUT: {
- pFile->iBusyTimeout = *(int*)pArg;
- return SQLITE_OK;
- }
-#endif
-#if SQLITE_MAX_MMAP_SIZE>0
- case SQLITE_FCNTL_MMAP_SIZE: {
- i64 newLimit = *(i64*)pArg;
- int rc = SQLITE_OK;
- if( newLimit>sqlite3GlobalConfig.mxMmap ){
- newLimit = sqlite3GlobalConfig.mxMmap;
- }
-
- /* The value of newLimit may be eventually cast to (size_t) and passed
- ** to mmap(). Restrict its value to 2GB if (size_t) is not at least a
- ** 64-bit type. */
- if( newLimit>0 && sizeof(size_t)<8 ){
- newLimit = (newLimit & 0x7FFFFFFF);
- }
-
- *(i64*)pArg = pFile->mmapSizeMax;
- if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
- pFile->mmapSizeMax = newLimit;
- if( pFile->mmapSize>0 ){
- unixUnmapfile(pFile);
- rc = unixMapfile(pFile, -1);
- }
- }
- return rc;
- }
-#endif
-#ifdef SQLITE_DEBUG
- /* The pager calls this method to signal that it has done
- ** a rollback and that the database is therefore unchanged and
- ** it hence it is OK for the transaction change counter to be
- ** unchanged.
- */
- case SQLITE_FCNTL_DB_UNCHANGED: {
- ((unixFile*)id)->dbUpdate = 0;
- return SQLITE_OK;
- }
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- case SQLITE_FCNTL_SET_LOCKPROXYFILE:
- case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
- return proxyFileControl(id,op,pArg);
- }
-#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
- }
- return SQLITE_NOTFOUND;
-}
-
-/*
-** If pFd->sectorSize is non-zero when this function is called, it is a
-** no-op. Otherwise, the values of pFd->sectorSize and
-** pFd->deviceCharacteristics are set according to the file-system
-** characteristics.
-**
-** There are two versions of this function. One for QNX and one for all
-** other systems.
-*/
-#ifndef __QNXNTO__
-static void setDeviceCharacteristics(unixFile *pFd){
- assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 );
- if( pFd->sectorSize==0 ){
-#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
- int res;
- u32 f = 0;
-
- /* Check for support for F2FS atomic batch writes. */
- res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f);
- if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){
- pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC;
- }
-#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
-
- /* Set the POWERSAFE_OVERWRITE flag if requested. */
- if( pFd->ctrlFlags & UNIXFILE_PSOW ){
- pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
- }
-
- pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
- }
-}
-#else
-#include <sys/dcmd_blk.h>
-#include <sys/statvfs.h>
-static void setDeviceCharacteristics(unixFile *pFile){
- if( pFile->sectorSize == 0 ){
- struct statvfs fsInfo;
-
- /* Set defaults for non-supported filesystems */
- pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
- pFile->deviceCharacteristics = 0;
- if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
- return;
- }
-
- if( !strcmp(fsInfo.f_basetype, "tmp") ) {
- pFile->sectorSize = fsInfo.f_bsize;
- pFile->deviceCharacteristics =
- SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */
- SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
- ** the write succeeds */
- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
- ** so it is ordered */
- 0;
- }else if( strstr(fsInfo.f_basetype, "etfs") ){
- pFile->sectorSize = fsInfo.f_bsize;
- pFile->deviceCharacteristics =
- /* etfs cluster size writes are atomic */
- (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
- SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
- ** the write succeeds */
- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
- ** so it is ordered */
- 0;
- }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
- pFile->sectorSize = fsInfo.f_bsize;
- pFile->deviceCharacteristics =
- SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */
- SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
- ** the write succeeds */
- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
- ** so it is ordered */
- 0;
- }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
- pFile->sectorSize = fsInfo.f_bsize;
- pFile->deviceCharacteristics =
- /* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
- ** so it is ordered */
- 0;
- }else if( strstr(fsInfo.f_basetype, "dos") ){
- pFile->sectorSize = fsInfo.f_bsize;
- pFile->deviceCharacteristics =
- /* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
- ** so it is ordered */
- 0;
- }else{
- pFile->deviceCharacteristics =
- SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */
- SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
- ** the write succeeds */
- 0;
- }
- }
- /* Last chance verification. If the sector size isn't a multiple of 512
- ** then it isn't valid.*/
- if( pFile->sectorSize % 512 != 0 ){
- pFile->deviceCharacteristics = 0;
- pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
- }
-}
-#endif
-
-/*
-** Return the sector size in bytes of the underlying block device for
-** the specified file. This is almost always 512 bytes, but may be
-** larger for some devices.
-**
-** SQLite code assumes this function cannot fail. It also assumes that
-** if two files are created in the same file-system directory (i.e.
-** a database and its journal file) that the sector size will be the
-** same for both.
-*/
-static int unixSectorSize(sqlite3_file *id){
- unixFile *pFd = (unixFile*)id;
- setDeviceCharacteristics(pFd);
- return pFd->sectorSize;
-}
-
-/*
-** Return the device characteristics for the file.
-**
-** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
-** However, that choice is controversial since technically the underlying
-** file system does not always provide powersafe overwrites. (In other
-** words, after a power-loss event, parts of the file that were never
-** written might end up being altered.) However, non-PSOW behavior is very,
-** very rare. And asserting PSOW makes a large reduction in the amount
-** of required I/O for journaling, since a lot of padding is eliminated.
-** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
-** available to turn it off and URI query parameter available to turn it off.
-*/
-static int unixDeviceCharacteristics(sqlite3_file *id){
- unixFile *pFd = (unixFile*)id;
- setDeviceCharacteristics(pFd);
- return pFd->deviceCharacteristics;
-}
-
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
-
-/*
-** Return the system page size.
-**
-** This function should not be called directly by other code in this file.
-** Instead, it should be called via macro osGetpagesize().
-*/
-static int unixGetpagesize(void){
-#if OS_VXWORKS
- return 1024;
-#elif defined(_BSD_SOURCE)
- return getpagesize();
-#else
- return (int)sysconf(_SC_PAGESIZE);
-#endif
-}
-
-#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
-
-#ifndef SQLITE_OMIT_WAL
-
-/*
-** Object used to represent an shared memory buffer.
-**
-** When multiple threads all reference the same wal-index, each thread
-** has its own unixShm object, but they all point to a single instance
-** of this unixShmNode object. In other words, each wal-index is opened
-** only once per process.
-**
-** Each unixShmNode object is connected to a single unixInodeInfo object.
-** We could coalesce this object into unixInodeInfo, but that would mean
-** every open file that does not use shared memory (in other words, most
-** open files) would have to carry around this extra information. So
-** the unixInodeInfo object contains a pointer to this unixShmNode object
-** and the unixShmNode object is created only when needed.
-**
-** unixMutexHeld() must be true when creating or destroying
-** this object or while reading or writing the following fields:
-**
-** nRef
-**
-** The following fields are read-only after the object is created:
-**
-** fid
-** zFilename
-**
-** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
-** unixMutexHeld() is true when reading or writing any other field
-** in this structure.
-*/
-struct unixShmNode {
- unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
- sqlite3_mutex *mutex; /* Mutex to access this object */
- char *zFilename; /* Name of the mmapped file */
- int h; /* Open file descriptor */
- int szRegion; /* Size of shared-memory regions */
- u16 nRegion; /* Size of array apRegion */
- u8 isReadonly; /* True if read-only */
- u8 isUnlocked; /* True if no DMS lock held */
- char **apRegion; /* Array of mapped shared-memory regions */
- int nRef; /* Number of unixShm objects pointing to this */
- unixShm *pFirst; /* All unixShm objects pointing to this */
-#ifdef SQLITE_DEBUG
- u8 exclMask; /* Mask of exclusive locks held */
- u8 sharedMask; /* Mask of shared locks held */
- u8 nextShmId; /* Next available unixShm.id value */
-#endif
-};
-
-/*
-** Structure used internally by this VFS to record the state of an
-** open shared memory connection.
-**
-** The following fields are initialized when this object is created and
-** are read-only thereafter:
-**
-** unixShm.pFile
-** unixShm.id
-**
-** All other fields are read/write. The unixShm.pFile->mutex must be held
-** while accessing any read/write fields.
-*/
-struct unixShm {
- unixShmNode *pShmNode; /* The underlying unixShmNode object */
- unixShm *pNext; /* Next unixShm with the same unixShmNode */
- u8 hasMutex; /* True if holding the unixShmNode mutex */
- u8 id; /* Id of this connection within its unixShmNode */
- u16 sharedMask; /* Mask of shared locks held */
- u16 exclMask; /* Mask of exclusive locks held */
-};
-
-/*
-** Constants used for locking
-*/
-#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
-#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-
-/*
-** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
-**
-** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
-** otherwise.
-*/
-static int unixShmSystemLock(
- unixFile *pFile, /* Open connection to the WAL file */
- int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
- int ofst, /* First byte of the locking range */
- int n /* Number of bytes to lock */
-){
- unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */
- struct flock f; /* The posix advisory locking structure */
- int rc = SQLITE_OK; /* Result code form fcntl() */
-
- /* Access to the unixShmNode object is serialized by the caller */
- pShmNode = pFile->pInode->pShmNode;
- assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) );
-
- /* Shared locks never span more than one byte */
- assert( n==1 || lockType!=F_RDLCK );
-
- /* Locks are within range */
- assert( n>=1 && n<=SQLITE_SHM_NLOCK );
-
- if( pShmNode->h>=0 ){
- /* Initialize the locking parameters */
- f.l_type = lockType;
- f.l_whence = SEEK_SET;
- f.l_start = ofst;
- f.l_len = n;
- rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
- rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
- }
-
- /* Update the global lock state and do debug tracing */
-#ifdef SQLITE_DEBUG
- { u16 mask;
- OSTRACE(("SHM-LOCK "));
- mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
- if( rc==SQLITE_OK ){
- if( lockType==F_UNLCK ){
- OSTRACE(("unlock %d ok", ofst));
- pShmNode->exclMask &= ~mask;
- pShmNode->sharedMask &= ~mask;
- }else if( lockType==F_RDLCK ){
- OSTRACE(("read-lock %d ok", ofst));
- pShmNode->exclMask &= ~mask;
- pShmNode->sharedMask |= mask;
- }else{
- assert( lockType==F_WRLCK );
- OSTRACE(("write-lock %d ok", ofst));
- pShmNode->exclMask |= mask;
- pShmNode->sharedMask &= ~mask;
- }
- }else{
- if( lockType==F_UNLCK ){
- OSTRACE(("unlock %d failed", ofst));
- }else if( lockType==F_RDLCK ){
- OSTRACE(("read-lock failed"));
- }else{
- assert( lockType==F_WRLCK );
- OSTRACE(("write-lock %d failed", ofst));
- }
- }
- OSTRACE((" - afterwards %03x,%03x\n",
- pShmNode->sharedMask, pShmNode->exclMask));
- }
-#endif
-
- return rc;
-}
-
-/*
-** Return the minimum number of 32KB shm regions that should be mapped at
-** a time, assuming that each mapping must be an integer multiple of the
-** current system page-size.
-**
-** Usually, this is 1. The exception seems to be systems that are configured
-** to use 64KB pages - in this case each mapping must cover at least two
-** shm regions.
-*/
-static int unixShmRegionPerMap(void){
- int shmsz = 32*1024; /* SHM region size */
- int pgsz = osGetpagesize(); /* System page size */
- assert( ((pgsz-1)&pgsz)==0 ); /* Page size must be a power of 2 */
- if( pgsz<shmsz ) return 1;
- return pgsz/shmsz;
-}
-
-/*
-** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
-**
-** This is not a VFS shared-memory method; it is a utility function called
-** by VFS shared-memory methods.
-*/
-static void unixShmPurge(unixFile *pFd){
- unixShmNode *p = pFd->pInode->pShmNode;
- assert( unixMutexHeld() );
- if( p && ALWAYS(p->nRef==0) ){
- int nShmPerMap = unixShmRegionPerMap();
- int i;
- assert( p->pInode==pFd->pInode );
- sqlite3_mutex_free(p->mutex);
- for(i=0; i<p->nRegion; i+=nShmPerMap){
- if( p->h>=0 ){
- osMunmap(p->apRegion[i], p->szRegion);
- }else{
- sqlite3_free(p->apRegion[i]);
- }
- }
- sqlite3_free(p->apRegion);
- if( p->h>=0 ){
- robust_close(pFd, p->h, __LINE__);
- p->h = -1;
- }
- p->pInode->pShmNode = 0;
- sqlite3_free(p);
- }
-}
-
-/*
-** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
-** take it now. Return SQLITE_OK if successful, or an SQLite error
-** code otherwise.
-**
-** If the DMS cannot be locked because this is a readonly_shm=1
-** connection and no other process already holds a lock, return
-** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
-*/
-static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
- struct flock lock;
- int rc = SQLITE_OK;
-
- /* Use F_GETLK to determine the locks other processes are holding
- ** on the DMS byte. If it indicates that another process is holding
- ** a SHARED lock, then this process may also take a SHARED lock
- ** and proceed with opening the *-shm file.
- **
- ** Or, if no other process is holding any lock, then this process
- ** is the first to open it. In this case take an EXCLUSIVE lock on the
- ** DMS byte and truncate the *-shm file to zero bytes in size. Then
- ** downgrade to a SHARED lock on the DMS byte.
- **
- ** If another process is holding an EXCLUSIVE lock on the DMS byte,
- ** return SQLITE_BUSY to the caller (it will try again). An earlier
- ** version of this code attempted the SHARED lock at this point. But
- ** this introduced a subtle race condition: if the process holding
- ** EXCLUSIVE failed just before truncating the *-shm file, then this
- ** process might open and use the *-shm file without truncating it.
- ** And if the *-shm file has been corrupted by a power failure or
- ** system crash, the database itself may also become corrupt. */
- lock.l_whence = SEEK_SET;
- lock.l_start = UNIX_SHM_DMS;
- lock.l_len = 1;
- lock.l_type = F_WRLCK;
- if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) {
- rc = SQLITE_IOERR_LOCK;
- }else if( lock.l_type==F_UNLCK ){
- if( pShmNode->isReadonly ){
- pShmNode->isUnlocked = 1;
- rc = SQLITE_READONLY_CANTINIT;
- }else{
- rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
- if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){
- rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
- }
- }
- }else if( lock.l_type==F_WRLCK ){
- rc = SQLITE_BUSY;
- }
-
- if( rc==SQLITE_OK ){
- assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK );
- rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1);
- }
- return rc;
-}
-
-/*
-** Open a shared-memory area associated with open database file pDbFd.
-** This particular implementation uses mmapped files.
-**
-** The file used to implement shared-memory is in the same directory
-** as the open database file and has the same name as the open database
-** file with the "-shm" suffix added. For example, if the database file
-** is "/home/user1/config.db" then the file that is created and mmapped
-** for shared memory will be called "/home/user1/config.db-shm".
-**
-** Another approach to is to use files in /dev/shm or /dev/tmp or an
-** some other tmpfs mount. But if a file in a different directory
-** from the database file is used, then differing access permissions
-** or a chroot() might cause two different processes on the same
-** database to end up using different files for shared memory -
-** meaning that their memory would not really be shared - resulting
-** in database corruption. Nevertheless, this tmpfs file usage
-** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
-** or the equivalent. The use of the SQLITE_SHM_DIRECTORY compile-time
-** option results in an incompatible build of SQLite; builds of SQLite
-** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the
-** same database file at the same time, database corruption will likely
-** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
-** "unsupported" and may go away in a future SQLite release.
-**
-** When opening a new shared-memory file, if no other instances of that
-** file are currently open, in this process or in other processes, then
-** the file must be truncated to zero length or have its header cleared.
-**
-** If the original database file (pDbFd) is using the "unix-excl" VFS
-** that means that an exclusive lock is held on the database file and
-** that no other processes are able to read or write the database. In
-** that case, we do not really need shared memory. No shared memory
-** file is created. The shared memory will be simulated with heap memory.
-*/
-static int unixOpenSharedMemory(unixFile *pDbFd){
- struct unixShm *p = 0; /* The connection to be opened */
- struct unixShmNode *pShmNode; /* The underlying mmapped file */
- int rc = SQLITE_OK; /* Result code */
- unixInodeInfo *pInode; /* The inode of fd */
- char *zShm; /* Name of the file used for SHM */
- int nShmFilename; /* Size of the SHM filename in bytes */
-
- /* Allocate space for the new unixShm object. */
- p = sqlite3_malloc64( sizeof(*p) );
- if( p==0 ) return SQLITE_NOMEM_BKPT;
- memset(p, 0, sizeof(*p));
- assert( pDbFd->pShm==0 );
-
- /* Check to see if a unixShmNode object already exists. Reuse an existing
- ** one if present. Create a new one if necessary.
- */
- unixEnterMutex();
- pInode = pDbFd->pInode;
- pShmNode = pInode->pShmNode;
- if( pShmNode==0 ){
- struct stat sStat; /* fstat() info for database file */
-#ifndef SQLITE_SHM_DIRECTORY
- const char *zBasePath = pDbFd->zPath;
-#endif
-
- /* Call fstat() to figure out the permissions on the database file. If
- ** a new *-shm file is created, an attempt will be made to create it
- ** with the same permissions.
- */
- if( osFstat(pDbFd->h, &sStat) ){
- rc = SQLITE_IOERR_FSTAT;
- goto shm_open_err;
- }
-
-#ifdef SQLITE_SHM_DIRECTORY
- nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
-#else
- nShmFilename = 6 + (int)strlen(zBasePath);
-#endif
- pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename );
- if( pShmNode==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto shm_open_err;
- }
- memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
- zShm = pShmNode->zFilename = (char*)&pShmNode[1];
-#ifdef SQLITE_SHM_DIRECTORY
- sqlite3_snprintf(nShmFilename, zShm,
- SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
- (u32)sStat.st_ino, (u32)sStat.st_dev);
-#else
- sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath);
- sqlite3FileSuffix3(pDbFd->zPath, zShm);
-#endif
- pShmNode->h = -1;
- pDbFd->pInode->pShmNode = pShmNode;
- pShmNode->pInode = pDbFd->pInode;
- if( sqlite3GlobalConfig.bCoreMutex ){
- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto shm_open_err;
- }
- }
-
- if( pInode->bProcessLock==0 ){
- if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777));
- }
- if( pShmNode->h<0 ){
- pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
- if( pShmNode->h<0 ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
- goto shm_open_err;
- }
- pShmNode->isReadonly = 1;
- }
-
- /* If this process is running as root, make sure that the SHM file
- ** is owned by the same user that owns the original database. Otherwise,
- ** the original owner will not be able to connect.
- */
- robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
-
- rc = unixLockSharedMemory(pDbFd, pShmNode);
- if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
- }
- }
-
- /* Make the new connection a child of the unixShmNode */
- p->pShmNode = pShmNode;
-#ifdef SQLITE_DEBUG
- p->id = pShmNode->nextShmId++;
-#endif
- pShmNode->nRef++;
- pDbFd->pShm = p;
- unixLeaveMutex();
-
- /* The reference count on pShmNode has already been incremented under
- ** the cover of the unixEnterMutex() mutex and the pointer from the
- ** new (struct unixShm) object to the pShmNode has been set. All that is
- ** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
- */
- sqlite3_mutex_enter(pShmNode->mutex);
- p->pNext = pShmNode->pFirst;
- pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
-
- /* Jump here on any error */
-shm_open_err:
- unixShmPurge(pDbFd); /* This call frees pShmNode if required */
- sqlite3_free(p);
- unixLeaveMutex();
- return rc;
-}
-
-/*
-** This function is called to obtain a pointer to region iRegion of the
-** shared-memory associated with the database file fd. Shared-memory regions
-** are numbered starting from zero. Each shared-memory region is szRegion
-** bytes in size.
-**
-** If an error occurs, an error code is returned and *pp is set to NULL.
-**
-** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
-** region has not been allocated (by any client, including one running in a
-** separate process), then *pp is set to NULL and SQLITE_OK returned. If
-** bExtend is non-zero and the requested shared-memory region has not yet
-** been allocated, it is allocated by this function.
-**
-** If the shared-memory region has already been allocated or is allocated by
-** this call as described above, then it is mapped into this processes
-** address space (if it is not already), *pp is set to point to the mapped
-** memory and SQLITE_OK returned.
-*/
-static int unixShmMap(
- sqlite3_file *fd, /* Handle open on database file */
- int iRegion, /* Region to retrieve */
- int szRegion, /* Size of regions */
- int bExtend, /* True to extend file if necessary */
- void volatile **pp /* OUT: Mapped memory */
-){
- unixFile *pDbFd = (unixFile*)fd;
- unixShm *p;
- unixShmNode *pShmNode;
- int rc = SQLITE_OK;
- int nShmPerMap = unixShmRegionPerMap();
- int nReqRegion;
-
- /* If the shared-memory file has not yet been opened, open it now. */
- if( pDbFd->pShm==0 ){
- rc = unixOpenSharedMemory(pDbFd);
- if( rc!=SQLITE_OK ) return rc;
- }
-
- p = pDbFd->pShm;
- pShmNode = p->pShmNode;
- sqlite3_mutex_enter(pShmNode->mutex);
- if( pShmNode->isUnlocked ){
- rc = unixLockSharedMemory(pDbFd, pShmNode);
- if( rc!=SQLITE_OK ) goto shmpage_out;
- pShmNode->isUnlocked = 0;
- }
- assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
- assert( pShmNode->pInode==pDbFd->pInode );
- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
-
- /* Minimum number of regions required to be mapped. */
- nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
-
- if( pShmNode->nRegion<nReqRegion ){
- char **apNew; /* New apRegion[] array */
- int nByte = nReqRegion*szRegion; /* Minimum required file size */
- struct stat sStat; /* Used by fstat() */
-
- pShmNode->szRegion = szRegion;
-
- if( pShmNode->h>=0 ){
- /* The requested region is not mapped into this processes address space.
- ** Check to see if it has been allocated (i.e. if the wal-index file is
- ** large enough to contain the requested region).
- */
- if( osFstat(pShmNode->h, &sStat) ){
- rc = SQLITE_IOERR_SHMSIZE;
- goto shmpage_out;
- }
-
- if( sStat.st_size<nByte ){
- /* The requested memory region does not exist. If bExtend is set to
- ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
- */
- if( !bExtend ){
- goto shmpage_out;
- }
-
- /* Alternatively, if bExtend is true, extend the file. Do this by
- ** writing a single byte to the end of each (OS) page being
- ** allocated or extended. Technically, we need only write to the
- ** last page in order to extend the file. But writing to all new
- ** pages forces the OS to allocate them immediately, which reduces
- ** the chances of SIGBUS while accessing the mapped region later on.
- */
- else{
- static const int pgsz = 4096;
- int iPg;
-
- /* Write to the last byte of each newly allocated or extended page */
- assert( (nByte % pgsz)==0 );
- for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
- int x = 0;
- if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){
- const char *zFile = pShmNode->zFilename;
- rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
- goto shmpage_out;
- }
- }
- }
- }
- }
-
- /* Map the requested memory region into this processes address space. */
- apNew = (char **)sqlite3_realloc(
- pShmNode->apRegion, nReqRegion*sizeof(char *)
- );
- if( !apNew ){
- rc = SQLITE_IOERR_NOMEM_BKPT;
- goto shmpage_out;
- }
- pShmNode->apRegion = apNew;
- while( pShmNode->nRegion<nReqRegion ){
- int nMap = szRegion*nShmPerMap;
- int i;
- void *pMem;
- if( pShmNode->h>=0 ){
- pMem = osMmap(0, nMap,
- pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
- MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
- );
- if( pMem==MAP_FAILED ){
- rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
- goto shmpage_out;
- }
- }else{
- pMem = sqlite3_malloc64(szRegion);
- if( pMem==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto shmpage_out;
- }
- memset(pMem, 0, szRegion);
- }
-
- for(i=0; i<nShmPerMap; i++){
- pShmNode->apRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i];
- }
- pShmNode->nRegion += nShmPerMap;
- }
- }
-
-shmpage_out:
- if( pShmNode->nRegion>iRegion ){
- *pp = pShmNode->apRegion[iRegion];
- }else{
- *pp = 0;
- }
- if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
-}
-
-/*
-** Change the lock state for a shared-memory segment.
-**
-** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
-** different here than in posix. In xShmLock(), one can go from unlocked
-** to shared and back or from unlocked to exclusive and back. But one may
-** not go from shared to exclusive or from exclusive to shared.
-*/
-static int unixShmLock(
- sqlite3_file *fd, /* Database file holding the shared memory */
- int ofst, /* First lock to acquire or release */
- int n, /* Number of locks to acquire or release */
- int flags /* What to do with the lock */
-){
- unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
- unixShm *p = pDbFd->pShm; /* The shared memory being locked */
- unixShm *pX; /* For looping over all siblings */
- unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
- int rc = SQLITE_OK; /* Result code */
- u16 mask; /* Mask of locks to take or release */
-
- assert( pShmNode==pDbFd->pInode->pShmNode );
- assert( pShmNode->pInode==pDbFd->pInode );
- assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
- assert( n>=1 );
- assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
- || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
- || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
- || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
- assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
-
- mask = (1<<(ofst+n)) - (1<<ofst);
- assert( n>1 || mask==(1<<ofst) );
- sqlite3_mutex_enter(pShmNode->mutex);
- if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
-
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
-
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
-
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
- }else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
-
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- allShared |= pX->sharedMask;
- }
-
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
- rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
- }
-
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
- }
- }else{
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- }
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
- if( rc==SQLITE_OK ){
- assert( (p->sharedMask & mask)==0 );
- p->exclMask |= mask;
- }
- }
- }
- sqlite3_mutex_leave(pShmNode->mutex);
- OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
- p->id, osGetpid(0), p->sharedMask, p->exclMask));
- return rc;
-}
-
-/*
-** Implement a memory barrier or memory fence on shared memory.
-**
-** All loads and stores begun before the barrier must complete before
-** any load or store begun after the barrier.
-*/
-static void unixShmBarrier(
- sqlite3_file *fd /* Database file holding the shared memory */
-){
- UNUSED_PARAMETER(fd);
- sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
- unixEnterMutex(); /* Also mutex, for redundancy */
- unixLeaveMutex();
-}
-
-/*
-** Close a connection to shared-memory. Delete the underlying
-** storage if deleteFlag is true.
-**
-** If there is no shared memory associated with the connection then this
-** routine is a harmless no-op.
-*/
-static int unixShmUnmap(
- sqlite3_file *fd, /* The underlying database file */
- int deleteFlag /* Delete shared-memory if true */
-){
- unixShm *p; /* The connection to be closed */
- unixShmNode *pShmNode; /* The underlying shared-memory file */
- unixShm **pp; /* For looping over sibling connections */
- unixFile *pDbFd; /* The underlying database file */
-
- pDbFd = (unixFile*)fd;
- p = pDbFd->pShm;
- if( p==0 ) return SQLITE_OK;
- pShmNode = p->pShmNode;
-
- assert( pShmNode==pDbFd->pInode->pShmNode );
- assert( pShmNode->pInode==pDbFd->pInode );
-
- /* Remove connection p from the set of connections associated
- ** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
- for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
- *pp = p->pNext;
-
- /* Free the connection p */
- sqlite3_free(p);
- pDbFd->pShm = 0;
- sqlite3_mutex_leave(pShmNode->mutex);
-
- /* If pShmNode->nRef has reached 0, then close the underlying
- ** shared-memory file, too */
- unixEnterMutex();
- assert( pShmNode->nRef>0 );
- pShmNode->nRef--;
- if( pShmNode->nRef==0 ){
- if( deleteFlag && pShmNode->h>=0 ){
- osUnlink(pShmNode->zFilename);
- }
- unixShmPurge(pDbFd);
- }
- unixLeaveMutex();
-
- return SQLITE_OK;
-}
-
-
-#else
-# define unixShmMap 0
-# define unixShmLock 0
-# define unixShmBarrier 0
-# define unixShmUnmap 0
-#endif /* #ifndef SQLITE_OMIT_WAL */
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/*
-** If it is currently memory mapped, unmap file pFd.
-*/
-static void unixUnmapfile(unixFile *pFd){
- assert( pFd->nFetchOut==0 );
- if( pFd->pMapRegion ){
- osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
- pFd->pMapRegion = 0;
- pFd->mmapSize = 0;
- pFd->mmapSizeActual = 0;
- }
-}
-
-/*
-** Attempt to set the size of the memory mapping maintained by file
-** descriptor pFd to nNew bytes. Any existing mapping is discarded.
-**
-** If successful, this function sets the following variables:
-**
-** unixFile.pMapRegion
-** unixFile.mmapSize
-** unixFile.mmapSizeActual
-**
-** If unsuccessful, an error message is logged via sqlite3_log() and
-** the three variables above are zeroed. In this case SQLite should
-** continue accessing the database using the xRead() and xWrite()
-** methods.
-*/
-static void unixRemapfile(
- unixFile *pFd, /* File descriptor object */
- i64 nNew /* Required mapping size */
-){
- const char *zErr = "mmap";
- int h = pFd->h; /* File descriptor open on db file */
- u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */
- i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */
- u8 *pNew = 0; /* Location of new mapping */
- int flags = PROT_READ; /* Flags to pass to mmap() */
-
- assert( pFd->nFetchOut==0 );
- assert( nNew>pFd->mmapSize );
- assert( nNew<=pFd->mmapSizeMax );
- assert( nNew>0 );
- assert( pFd->mmapSizeActual>=pFd->mmapSize );
- assert( MAP_FAILED!=0 );
-
-#ifdef SQLITE_MMAP_READWRITE
- if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
-#endif
-
- if( pOrig ){
-#if HAVE_MREMAP
- i64 nReuse = pFd->mmapSize;
-#else
- const int szSyspage = osGetpagesize();
- i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
-#endif
- u8 *pReq = &pOrig[nReuse];
-
- /* Unmap any pages of the existing mapping that cannot be reused. */
- if( nReuse!=nOrig ){
- osMunmap(pReq, nOrig-nReuse);
- }
-
-#if HAVE_MREMAP
- pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
- zErr = "mremap";
-#else
- pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
- if( pNew!=MAP_FAILED ){
- if( pNew!=pReq ){
- osMunmap(pNew, nNew - nReuse);
- pNew = 0;
- }else{
- pNew = pOrig;
- }
- }
-#endif
-
- /* The attempt to extend the existing mapping failed. Free it. */
- if( pNew==MAP_FAILED || pNew==0 ){
- osMunmap(pOrig, nReuse);
- }
- }
-
- /* If pNew is still NULL, try to create an entirely new mapping. */
- if( pNew==0 ){
- pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
- }
-
- if( pNew==MAP_FAILED ){
- pNew = 0;
- nNew = 0;
- unixLogError(SQLITE_OK, zErr, pFd->zPath);
-
- /* If the mmap() above failed, assume that all subsequent mmap() calls
- ** will probably fail too. Fall back to using xRead/xWrite exclusively
- ** in this case. */
- pFd->mmapSizeMax = 0;
- }
- pFd->pMapRegion = (void *)pNew;
- pFd->mmapSize = pFd->mmapSizeActual = nNew;
-}
-
-/*
-** Memory map or remap the file opened by file-descriptor pFd (if the file
-** is already mapped, the existing mapping is replaced by the new). Or, if
-** there already exists a mapping for this file, and there are still
-** outstanding xFetch() references to it, this function is a no-op.
-**
-** If parameter nByte is non-negative, then it is the requested size of
-** the mapping to create. Otherwise, if nByte is less than zero, then the
-** requested size is the size of the file on disk. The actual size of the
-** created mapping is either the requested size or the value configured
-** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
-**
-** SQLITE_OK is returned if no error occurs (even if the mapping is not
-** recreated as a result of outstanding references) or an SQLite error
-** code otherwise.
-*/
-static int unixMapfile(unixFile *pFd, i64 nMap){
- assert( nMap>=0 || pFd->nFetchOut==0 );
- assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
- if( pFd->nFetchOut>0 ) return SQLITE_OK;
-
- if( nMap<0 ){
- struct stat statbuf; /* Low-level file information */
- if( osFstat(pFd->h, &statbuf) ){
- return SQLITE_IOERR_FSTAT;
- }
- nMap = statbuf.st_size;
- }
- if( nMap>pFd->mmapSizeMax ){
- nMap = pFd->mmapSizeMax;
- }
-
- assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
- if( nMap!=pFd->mmapSize ){
- unixRemapfile(pFd, nMap);
- }
-
- return SQLITE_OK;
-}
-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-
-/*
-** If possible, return a pointer to a mapping of file fd starting at offset
-** iOff. The mapping must be valid for at least nAmt bytes.
-**
-** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
-** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
-** Finally, if an error does occur, return an SQLite error code. The final
-** value of *pp is undefined in this case.
-**
-** If this function does return a pointer, the caller must eventually
-** release the reference by calling unixUnfetch().
-*/
-static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
-#if SQLITE_MAX_MMAP_SIZE>0
- unixFile *pFd = (unixFile *)fd; /* The underlying database file */
-#endif
- *pp = 0;
-
-#if SQLITE_MAX_MMAP_SIZE>0
- if( pFd->mmapSizeMax>0 ){
- if( pFd->pMapRegion==0 ){
- int rc = unixMapfile(pFd, -1);
- if( rc!=SQLITE_OK ) return rc;
- }
- if( pFd->mmapSize >= iOff+nAmt ){
- *pp = &((u8 *)pFd->pMapRegion)[iOff];
- pFd->nFetchOut++;
- }
- }
-#endif
- return SQLITE_OK;
-}
-
-/*
-** If the third argument is non-NULL, then this function releases a
-** reference obtained by an earlier call to unixFetch(). The second
-** argument passed to this function must be the same as the corresponding
-** argument that was passed to the unixFetch() invocation.
-**
-** Or, if the third argument is NULL, then this function is being called
-** to inform the VFS layer that, according to POSIX, any existing mapping
-** may now be invalid and should be unmapped.
-*/
-static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
-#if SQLITE_MAX_MMAP_SIZE>0
- unixFile *pFd = (unixFile *)fd; /* The underlying database file */
- UNUSED_PARAMETER(iOff);
-
- /* If p==0 (unmap the entire file) then there must be no outstanding
- ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
- ** then there must be at least one outstanding. */
- assert( (p==0)==(pFd->nFetchOut==0) );
-
- /* If p!=0, it must match the iOff value. */
- assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
-
- if( p ){
- pFd->nFetchOut--;
- }else{
- unixUnmapfile(pFd);
- }
-
- assert( pFd->nFetchOut>=0 );
-#else
- UNUSED_PARAMETER(fd);
- UNUSED_PARAMETER(p);
- UNUSED_PARAMETER(iOff);
-#endif
- return SQLITE_OK;
-}
-
-/*
-** Here ends the implementation of all sqlite3_file methods.
-**
-********************** End sqlite3_file Methods *******************************
-******************************************************************************/
-
-/*
-** This division contains definitions of sqlite3_io_methods objects that
-** implement various file locking strategies. It also contains definitions
-** of "finder" functions. A finder-function is used to locate the appropriate
-** sqlite3_io_methods object for a particular database file. The pAppData
-** field of the sqlite3_vfs VFS objects are initialized to be pointers to
-** the correct finder-function for that VFS.
-**
-** Most finder functions return a pointer to a fixed sqlite3_io_methods
-** object. The only interesting finder-function is autolockIoFinder, which
-** looks at the filesystem type and tries to guess the best locking
-** strategy from that.
-**
-** For finder-function F, two objects are created:
-**
-** (1) The real finder-function named "FImpt()".
-**
-** (2) A constant pointer to this function named just "F".
-**
-**
-** A pointer to the F pointer is used as the pAppData value for VFS
-** objects. We have to do this instead of letting pAppData point
-** directly at the finder-function since C90 rules prevent a void*
-** from be cast into a function pointer.
-**
-**
-** Each instance of this macro generates two objects:
-**
-** * A constant sqlite3_io_methods object call METHOD that has locking
-** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
-**
-** * An I/O method finder function called FINDER that returns a pointer
-** to the METHOD object in the previous bullet.
-*/
-#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP) \
-static const sqlite3_io_methods METHOD = { \
- VERSION, /* iVersion */ \
- CLOSE, /* xClose */ \
- unixRead, /* xRead */ \
- unixWrite, /* xWrite */ \
- unixTruncate, /* xTruncate */ \
- unixSync, /* xSync */ \
- unixFileSize, /* xFileSize */ \
- LOCK, /* xLock */ \
- UNLOCK, /* xUnlock */ \
- CKLOCK, /* xCheckReservedLock */ \
- unixFileControl, /* xFileControl */ \
- unixSectorSize, /* xSectorSize */ \
- unixDeviceCharacteristics, /* xDeviceCapabilities */ \
- SHMMAP, /* xShmMap */ \
- unixShmLock, /* xShmLock */ \
- unixShmBarrier, /* xShmBarrier */ \
- unixShmUnmap, /* xShmUnmap */ \
- unixFetch, /* xFetch */ \
- unixUnfetch, /* xUnfetch */ \
-}; \
-static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
- UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
- return &METHOD; \
-} \
-static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \
- = FINDER##Impl;
-
-/*
-** Here are all of the sqlite3_io_methods objects for each of the
-** locking strategies. Functions that return pointers to these methods
-** are also created.
-*/
-IOMETHODS(
- posixIoFinder, /* Finder function name */
- posixIoMethods, /* sqlite3_io_methods object name */
- 3, /* shared memory and mmap are enabled */
- unixClose, /* xClose method */
- unixLock, /* xLock method */
- unixUnlock, /* xUnlock method */
- unixCheckReservedLock, /* xCheckReservedLock method */
- unixShmMap /* xShmMap method */
-)
-IOMETHODS(
- nolockIoFinder, /* Finder function name */
- nolockIoMethods, /* sqlite3_io_methods object name */
- 3, /* shared memory is disabled */
- nolockClose, /* xClose method */
- nolockLock, /* xLock method */
- nolockUnlock, /* xUnlock method */
- nolockCheckReservedLock, /* xCheckReservedLock method */
- 0 /* xShmMap method */
-)
-IOMETHODS(
- dotlockIoFinder, /* Finder function name */
- dotlockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- dotlockClose, /* xClose method */
- dotlockLock, /* xLock method */
- dotlockUnlock, /* xUnlock method */
- dotlockCheckReservedLock, /* xCheckReservedLock method */
- 0 /* xShmMap method */
-)
-
-#if SQLITE_ENABLE_LOCKING_STYLE
-IOMETHODS(
- flockIoFinder, /* Finder function name */
- flockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- flockClose, /* xClose method */
- flockLock, /* xLock method */
- flockUnlock, /* xUnlock method */
- flockCheckReservedLock, /* xCheckReservedLock method */
- 0 /* xShmMap method */
-)
-#endif
-
-#if OS_VXWORKS
-IOMETHODS(
- semIoFinder, /* Finder function name */
- semIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- semXClose, /* xClose method */
- semXLock, /* xLock method */
- semXUnlock, /* xUnlock method */
- semXCheckReservedLock, /* xCheckReservedLock method */
- 0 /* xShmMap method */
-)
-#endif
-
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-IOMETHODS(
- afpIoFinder, /* Finder function name */
- afpIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- afpClose, /* xClose method */
- afpLock, /* xLock method */
- afpUnlock, /* xUnlock method */
- afpCheckReservedLock, /* xCheckReservedLock method */
- 0 /* xShmMap method */
-)
-#endif
-
-/*
-** The proxy locking method is a "super-method" in the sense that it
-** opens secondary file descriptors for the conch and lock files and
-** it uses proxy, dot-file, AFP, and flock() locking methods on those
-** secondary files. For this reason, the division that implements
-** proxy locking is located much further down in the file. But we need
-** to go ahead and define the sqlite3_io_methods and finder function
-** for proxy locking here. So we forward declare the I/O methods.
-*/
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-static int proxyClose(sqlite3_file*);
-static int proxyLock(sqlite3_file*, int);
-static int proxyUnlock(sqlite3_file*, int);
-static int proxyCheckReservedLock(sqlite3_file*, int*);
-IOMETHODS(
- proxyIoFinder, /* Finder function name */
- proxyIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- proxyClose, /* xClose method */
- proxyLock, /* xLock method */
- proxyUnlock, /* xUnlock method */
- proxyCheckReservedLock, /* xCheckReservedLock method */
- 0 /* xShmMap method */
-)
-#endif
-
-/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-IOMETHODS(
- nfsIoFinder, /* Finder function name */
- nfsIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- unixClose, /* xClose method */
- unixLock, /* xLock method */
- nfsUnlock, /* xUnlock method */
- unixCheckReservedLock, /* xCheckReservedLock method */
- 0 /* xShmMap method */
-)
-#endif
-
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-/*
-** This "finder" function attempts to determine the best locking strategy
-** for the database file "filePath". It then returns the sqlite3_io_methods
-** object that implements that strategy.
-**
-** This is for MacOSX only.
-*/
-static const sqlite3_io_methods *autolockIoFinderImpl(
- const char *filePath, /* name of the database file */
- unixFile *pNew /* open file object for the database file */
-){
- static const struct Mapping {
- const char *zFilesystem; /* Filesystem type name */
- const sqlite3_io_methods *pMethods; /* Appropriate locking method */
- } aMap[] = {
- { "hfs", &posixIoMethods },
- { "ufs", &posixIoMethods },
- { "afpfs", &afpIoMethods },
- { "smbfs", &afpIoMethods },
- { "webdav", &nolockIoMethods },
- { 0, 0 }
- };
- int i;
- struct statfs fsInfo;
- struct flock lockInfo;
-
- if( !filePath ){
- /* If filePath==NULL that means we are dealing with a transient file
- ** that does not need to be locked. */
- return &nolockIoMethods;
- }
- if( statfs(filePath, &fsInfo) != -1 ){
- if( fsInfo.f_flags & MNT_RDONLY ){
- return &nolockIoMethods;
- }
- for(i=0; aMap[i].zFilesystem; i++){
- if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
- return aMap[i].pMethods;
- }
- }
- }
-
- /* Default case. Handles, amongst others, "nfs".
- ** Test byte-range lock using fcntl(). If the call succeeds,
- ** assume that the file-system supports POSIX style locks.
- */
- lockInfo.l_len = 1;
- lockInfo.l_start = 0;
- lockInfo.l_whence = SEEK_SET;
- lockInfo.l_type = F_RDLCK;
- if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
- if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
- return &nfsIoMethods;
- } else {
- return &posixIoMethods;
- }
- }else{
- return &dotlockIoMethods;
- }
-}
-static const sqlite3_io_methods
- *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
-
-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-
-#if OS_VXWORKS
-/*
-** This "finder" function for VxWorks checks to see if posix advisory
-** locking works. If it does, then that is what is used. If it does not
-** work, then fallback to named semaphore locking.
-*/
-static const sqlite3_io_methods *vxworksIoFinderImpl(
- const char *filePath, /* name of the database file */
- unixFile *pNew /* the open file object */
-){
- struct flock lockInfo;
-
- if( !filePath ){
- /* If filePath==NULL that means we are dealing with a transient file
- ** that does not need to be locked. */
- return &nolockIoMethods;
- }
-
- /* Test if fcntl() is supported and use POSIX style locks.
- ** Otherwise fall back to the named semaphore method.
- */
- lockInfo.l_len = 1;
- lockInfo.l_start = 0;
- lockInfo.l_whence = SEEK_SET;
- lockInfo.l_type = F_RDLCK;
- if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
- return &posixIoMethods;
- }else{
- return &semIoMethods;
- }
-}
-static const sqlite3_io_methods
- *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl;
-
-#endif /* OS_VXWORKS */
-
-/*
-** An abstract type for a pointer to an IO method finder function:
-*/
-typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
-
-
-/****************************************************************************
-**************************** sqlite3_vfs methods ****************************
-**
-** This division contains the implementation of methods on the
-** sqlite3_vfs object.
-*/
-
-/*
-** Initialize the contents of the unixFile structure pointed to by pId.
-*/
-static int fillInUnixFile(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- int h, /* Open file descriptor of file being opened */
- sqlite3_file *pId, /* Write to the unixFile structure here */
- const char *zFilename, /* Name of the file being opened */
- int ctrlFlags /* Zero or more UNIXFILE_* values */
-){
- const sqlite3_io_methods *pLockingStyle;
- unixFile *pNew = (unixFile *)pId;
- int rc = SQLITE_OK;
-
- assert( pNew->pInode==NULL );
-
- /* No locking occurs in temporary files */
- assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
-
- OSTRACE(("OPEN %-3d %s\n", h, zFilename));
- pNew->h = h;
- pNew->pVfs = pVfs;
- pNew->zPath = zFilename;
- pNew->ctrlFlags = (u8)ctrlFlags;
-#if SQLITE_MAX_MMAP_SIZE>0
- pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
-#endif
- if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
- "psow", SQLITE_POWERSAFE_OVERWRITE) ){
- pNew->ctrlFlags |= UNIXFILE_PSOW;
- }
- if( strcmp(pVfs->zName,"unix-excl")==0 ){
- pNew->ctrlFlags |= UNIXFILE_EXCL;
- }
-
-#if OS_VXWORKS
- pNew->pId = vxworksFindFileId(zFilename);
- if( pNew->pId==0 ){
- ctrlFlags |= UNIXFILE_NOLOCK;
- rc = SQLITE_NOMEM_BKPT;
- }
-#endif
-
- if( ctrlFlags & UNIXFILE_NOLOCK ){
- pLockingStyle = &nolockIoMethods;
- }else{
- pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
-#if SQLITE_ENABLE_LOCKING_STYLE
- /* Cache zFilename in the locking context (AFP and dotlock override) for
- ** proxyLock activation is possible (remote proxy is based on db name)
- ** zFilename remains valid until file is closed, to support */
- pNew->lockingContext = (void*)zFilename;
-#endif
- }
-
- if( pLockingStyle == &posixIoMethods
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- || pLockingStyle == &nfsIoMethods
-#endif
- ){
- unixEnterMutex();
- rc = findInodeInfo(pNew, &pNew->pInode);
- if( rc!=SQLITE_OK ){
- /* If an error occurred in findInodeInfo(), close the file descriptor
- ** immediately, before releasing the mutex. findInodeInfo() may fail
- ** in two scenarios:
- **
- ** (a) A call to fstat() failed.
- ** (b) A malloc failed.
- **
- ** Scenario (b) may only occur if the process is holding no other
- ** file descriptors open on the same file. If there were other file
- ** descriptors on this file, then no malloc would be required by
- ** findInodeInfo(). If this is the case, it is quite safe to close
- ** handle h - as it is guaranteed that no posix locks will be released
- ** by doing so.
- **
- ** If scenario (a) caused the error then things are not so safe. The
- ** implicit assumption here is that if fstat() fails, things are in
- ** such bad shape that dropping a lock or two doesn't matter much.
- */
- robust_close(pNew, h, __LINE__);
- h = -1;
- }
- unixLeaveMutex();
- }
-
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- else if( pLockingStyle == &afpIoMethods ){
- /* AFP locking uses the file path so it needs to be included in
- ** the afpLockingContext.
- */
- afpLockingContext *pCtx;
- pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) );
- if( pCtx==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- /* NB: zFilename exists and remains valid until the file is closed
- ** according to requirement F11141. So we do not need to make a
- ** copy of the filename. */
- pCtx->dbPath = zFilename;
- pCtx->reserved = 0;
- srandomdev();
- unixEnterMutex();
- rc = findInodeInfo(pNew, &pNew->pInode);
- if( rc!=SQLITE_OK ){
- sqlite3_free(pNew->lockingContext);
- robust_close(pNew, h, __LINE__);
- h = -1;
- }
- unixLeaveMutex();
- }
- }
-#endif
-
- else if( pLockingStyle == &dotlockIoMethods ){
- /* Dotfile locking uses the file path so it needs to be included in
- ** the dotlockLockingContext
- */
- char *zLockFile;
- int nFilename;
- assert( zFilename!=0 );
- nFilename = (int)strlen(zFilename) + 6;
- zLockFile = (char *)sqlite3_malloc64(nFilename);
- if( zLockFile==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
- }
- pNew->lockingContext = zLockFile;
- }
-
-#if OS_VXWORKS
- else if( pLockingStyle == &semIoMethods ){
- /* Named semaphore locking uses the file path so it needs to be
- ** included in the semLockingContext
- */
- unixEnterMutex();
- rc = findInodeInfo(pNew, &pNew->pInode);
- if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
- char *zSemName = pNew->pInode->aSemName;
- int n;
- sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
- pNew->pId->zCanonicalName);
- for( n=1; zSemName[n]; n++ )
- if( zSemName[n]=='/' ) zSemName[n] = '_';
- pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
- if( pNew->pInode->pSem == SEM_FAILED ){
- rc = SQLITE_NOMEM_BKPT;
- pNew->pInode->aSemName[0] = '\0';
- }
- }
- unixLeaveMutex();
- }
-#endif
-
- storeLastErrno(pNew, 0);
-#if OS_VXWORKS
- if( rc!=SQLITE_OK ){
- if( h>=0 ) robust_close(pNew, h, __LINE__);
- h = -1;
- osUnlink(zFilename);
- pNew->ctrlFlags |= UNIXFILE_DELETE;
- }
-#endif
- if( rc!=SQLITE_OK ){
- if( h>=0 ) robust_close(pNew, h, __LINE__);
- }else{
- pNew->pMethod = pLockingStyle;
- OpenCounter(+1);
- verifyDbFile(pNew);
- }
- return rc;
-}
-
-/*
-** Return the name of a directory in which to put temporary files.
-** If no suitable temporary file directory can be found, return NULL.
-*/
-static const char *unixTempFileDir(void){
- static const char *azDirs[] = {
- 0,
- 0,
- "/var/tmp",
- "/usr/tmp",
- "/tmp",
- "."
- };
- unsigned int i = 0;
- struct stat buf;
- const char *zDir = sqlite3_temp_directory;
-
- if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
- while(1){
- if( zDir!=0
- && osStat(zDir, &buf)==0
- && S_ISDIR(buf.st_mode)
- && osAccess(zDir, 03)==0
- ){
- return zDir;
- }
- if( i>=sizeof(azDirs)/sizeof(azDirs[0]) ) break;
- zDir = azDirs[i++];
- }
- return 0;
-}
-
-/*
-** Create a temporary file name in zBuf. zBuf must be allocated
-** by the calling process and must be big enough to hold at least
-** pVfs->mxPathname bytes.
-*/
-static int unixGetTempname(int nBuf, char *zBuf){
- const char *zDir;
- int iLimit = 0;
-
- /* It's odd to simulate an io-error here, but really this is just
- ** using the io-error infrastructure to test that SQLite handles this
- ** function failing.
- */
- zBuf[0] = 0;
- SimulateIOError( return SQLITE_IOERR );
-
- zDir = unixTempFileDir();
- if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH;
- do{
- u64 r;
- sqlite3_randomness(sizeof(r), &r);
- assert( nBuf>2 );
- zBuf[nBuf-2] = 0;
- sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
- zDir, r, 0);
- if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR;
- }while( osAccess(zBuf,0)==0 );
- return SQLITE_OK;
-}
-
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-/*
-** Routine to transform a unixFile into a proxy-locking unixFile.
-** Implementation in the proxy-lock division, but used by unixOpen()
-** if SQLITE_PREFER_PROXY_LOCKING is defined.
-*/
-static int proxyTransformUnixFile(unixFile*, const char*);
-#endif
-
-/*
-** Search for an unused file descriptor that was opened on the database
-** file (not a journal or master-journal file) identified by pathname
-** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
-** argument to this function.
-**
-** Such a file descriptor may exist if a database connection was closed
-** but the associated file descriptor could not be closed because some
-** other file descriptor open on the same file is holding a file-lock.
-** Refer to comments in the unixClose() function and the lengthy comment
-** describing "Posix Advisory Locking" at the start of this file for
-** further details. Also, ticket #4018.
-**
-** If a suitable file descriptor is found, then it is returned. If no
-** such file descriptor is located, -1 is returned.
-*/
-static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
- UnixUnusedFd *pUnused = 0;
-
- /* Do not search for an unused file descriptor on vxworks. Not because
- ** vxworks would not benefit from the change (it might, we're not sure),
- ** but because no way to test it is currently available. It is better
- ** not to risk breaking vxworks support for the sake of such an obscure
- ** feature. */
-#if !OS_VXWORKS
- struct stat sStat; /* Results of stat() call */
-
- unixEnterMutex();
-
- /* A stat() call may fail for various reasons. If this happens, it is
- ** almost certain that an open() call on the same path will also fail.
- ** For this reason, if an error occurs in the stat() call here, it is
- ** ignored and -1 is returned. The caller will try to open a new file
- ** descriptor on the same path, fail, and return an error to SQLite.
- **
- ** Even if a subsequent open() call does succeed, the consequences of
- ** not searching for a reusable file descriptor are not dire. */
- if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){
- unixInodeInfo *pInode;
-
- pInode = inodeList;
- while( pInode && (pInode->fileId.dev!=sStat.st_dev
- || pInode->fileId.ino!=(u64)sStat.st_ino) ){
- pInode = pInode->pNext;
- }
- if( pInode ){
- UnixUnusedFd **pp;
- for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
- pUnused = *pp;
- if( pUnused ){
- nUnusedFd--;
- *pp = pUnused->pNext;
- }
- }
- }
- unixLeaveMutex();
-#endif /* if !OS_VXWORKS */
- return pUnused;
-}
-
-/*
-** Find the mode, uid and gid of file zFile.
-*/
-static int getFileMode(
- const char *zFile, /* File name */
- mode_t *pMode, /* OUT: Permissions of zFile */
- uid_t *pUid, /* OUT: uid of zFile. */
- gid_t *pGid /* OUT: gid of zFile. */
-){
- struct stat sStat; /* Output of stat() on database file */
- int rc = SQLITE_OK;
- if( 0==osStat(zFile, &sStat) ){
- *pMode = sStat.st_mode & 0777;
- *pUid = sStat.st_uid;
- *pGid = sStat.st_gid;
- }else{
- rc = SQLITE_IOERR_FSTAT;
- }
- return rc;
-}
-
-/*
-** This function is called by unixOpen() to determine the unix permissions
-** to create new files with. If no error occurs, then SQLITE_OK is returned
-** and a value suitable for passing as the third argument to open(2) is
-** written to *pMode. If an IO error occurs, an SQLite error code is
-** returned and the value of *pMode is not modified.
-**
-** In most cases, this routine sets *pMode to 0, which will become
-** an indication to robust_open() to create the file using
-** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
-** But if the file being opened is a WAL or regular journal file, then
-** this function queries the file-system for the permissions on the
-** corresponding database file and sets *pMode to this value. Whenever
-** possible, WAL and journal files are created using the same permissions
-** as the associated database file.
-**
-** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
-** original filename is unavailable. But 8_3_NAMES is only used for
-** FAT filesystems and permissions do not matter there, so just use
-** the default permissions.
-*/
-static int findCreateFileMode(
- const char *zPath, /* Path of file (possibly) being created */
- int flags, /* Flags passed as 4th argument to xOpen() */
- mode_t *pMode, /* OUT: Permissions to open file with */
- uid_t *pUid, /* OUT: uid to set on the file */
- gid_t *pGid /* OUT: gid to set on the file */
-){
- int rc = SQLITE_OK; /* Return Code */
- *pMode = 0;
- *pUid = 0;
- *pGid = 0;
- if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
- char zDb[MAX_PATHNAME+1]; /* Database file path */
- int nDb; /* Number of valid bytes in zDb */
-
- /* zPath is a path to a WAL or journal file. The following block derives
- ** the path to the associated database file from zPath. This block handles
- ** the following naming conventions:
- **
- ** "<path to db>-journal"
- ** "<path to db>-wal"
- ** "<path to db>-journalNN"
- ** "<path to db>-walNN"
- **
- ** where NN is a decimal number. The NN naming schemes are
- ** used by the test_multiplex.c module.
- */
- nDb = sqlite3Strlen30(zPath) - 1;
- while( zPath[nDb]!='-' ){
- /* In normal operation, the journal file name will always contain
- ** a '-' character. However in 8+3 filename mode, or if a corrupt
- ** rollback journal specifies a master journal with a goofy name, then
- ** the '-' might be missing. */
- if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
- nDb--;
- }
- memcpy(zDb, zPath, nDb);
- zDb[nDb] = '\0';
-
- rc = getFileMode(zDb, pMode, pUid, pGid);
- }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
- *pMode = 0600;
- }else if( flags & SQLITE_OPEN_URI ){
- /* If this is a main database file and the file was opened using a URI
- ** filename, check for the "modeof" parameter. If present, interpret
- ** its value as a filename and try to copy the mode, uid and gid from
- ** that file. */
- const char *z = sqlite3_uri_parameter(zPath, "modeof");
- if( z ){
- rc = getFileMode(z, pMode, pUid, pGid);
- }
- }
- return rc;
-}
-
-/*
-** Open the file zPath.
-**
-** Previously, the SQLite OS layer used three functions in place of this
-** one:
-**
-** sqlite3OsOpenReadWrite();
-** sqlite3OsOpenReadOnly();
-** sqlite3OsOpenExclusive();
-**
-** These calls correspond to the following combinations of flags:
-**
-** ReadWrite() -> (READWRITE | CREATE)
-** ReadOnly() -> (READONLY)
-** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
-**
-** The old OpenExclusive() accepted a boolean argument - "delFlag". If
-** true, the file was configured to be automatically deleted when the
-** file handle closed. To achieve the same effect using this new
-** interface, add the DELETEONCLOSE flag to those specified above for
-** OpenExclusive().
-*/
-static int unixOpen(
- sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */
- const char *zPath, /* Pathname of file to be opened */
- sqlite3_file *pFile, /* The file descriptor to be filled in */
- int flags, /* Input flags to control the opening */
- int *pOutFlags /* Output flags returned to SQLite core */
-){
- unixFile *p = (unixFile *)pFile;
- int fd = -1; /* File descriptor returned by open() */
- int openFlags = 0; /* Flags to pass to open() */
- int eType = flags&0xFFFFFF00; /* Type of file to open */
- int noLock; /* True to omit locking primitives */
- int rc = SQLITE_OK; /* Function Return Code */
- int ctrlFlags = 0; /* UNIXFILE_* flags */
-
- int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
- int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
- int isCreate = (flags & SQLITE_OPEN_CREATE);
- int isReadonly = (flags & SQLITE_OPEN_READONLY);
- int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
-#if SQLITE_ENABLE_LOCKING_STYLE
- int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
-#endif
-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
- struct statfs fsInfo;
-#endif
-
- /* If creating a master or main-file journal, this function will open
- ** a file-descriptor on the directory too. The first time unixSync()
- ** is called the directory file descriptor will be fsync()ed and close()d.
- */
- int isNewJrnl = (isCreate && (
- eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_MAIN_JOURNAL
- || eType==SQLITE_OPEN_WAL
- ));
-
- /* If argument zPath is a NULL pointer, this function is required to open
- ** a temporary file. Use this buffer to store the file name in.
- */
- char zTmpname[MAX_PATHNAME+2];
- const char *zName = zPath;
-
- /* Check the following statements are true:
- **
- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
- ** (b) if CREATE is set, then READWRITE must also be set, and
- ** (c) if EXCLUSIVE is set, then CREATE must also be set.
- ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
- */
- assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
- assert(isCreate==0 || isReadWrite);
- assert(isExclusive==0 || isCreate);
- assert(isDelete==0 || isCreate);
-
- /* The main DB, main journal, WAL file and master journal are never
- ** automatically deleted. Nor are they ever temporary files. */
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
-
- /* Assert that the upper layer has set one of the "file-type" flags. */
- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
- );
-
- /* Detect a pid change and reset the PRNG. There is a race condition
- ** here such that two or more threads all trying to open databases at
- ** the same instant might all reset the PRNG. But multiple resets
- ** are harmless.
- */
- if( randomnessPid!=osGetpid(0) ){
- randomnessPid = osGetpid(0);
- sqlite3_randomness(0,0);
- }
- memset(p, 0, sizeof(unixFile));
-
- if( eType==SQLITE_OPEN_MAIN_DB ){
- UnixUnusedFd *pUnused;
- pUnused = findReusableFd(zName, flags);
- if( pUnused ){
- fd = pUnused->fd;
- }else{
- pUnused = sqlite3_malloc64(sizeof(*pUnused));
- if( !pUnused ){
- return SQLITE_NOMEM_BKPT;
- }
- }
- p->pPreallocatedUnused = pUnused;
-
- /* Database filenames are double-zero terminated if they are not
- ** URIs with parameters. Hence, they can always be passed into
- ** sqlite3_uri_parameter(). */
- assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
-
- }else if( !zName ){
- /* If zName is NULL, the upper layer is requesting a temp file. */
- assert(isDelete && !isNewJrnl);
- rc = unixGetTempname(pVfs->mxPathname, zTmpname);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- zName = zTmpname;
-
- /* Generated temporary filenames are always double-zero terminated
- ** for use by sqlite3_uri_parameter(). */
- assert( zName[strlen(zName)+1]==0 );
- }
-
- /* Determine the value of the flags parameter passed to POSIX function
- ** open(). These must be calculated even if open() is not called, as
- ** they may be stored as part of the file handle and used by the
- ** 'conch file' locking functions later on. */
- if( isReadonly ) openFlags |= O_RDONLY;
- if( isReadWrite ) openFlags |= O_RDWR;
- if( isCreate ) openFlags |= O_CREAT;
- if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
- openFlags |= (O_LARGEFILE|O_BINARY);
-
- if( fd<0 ){
- mode_t openMode; /* Permissions to create file with */
- uid_t uid; /* Userid for the file */
- gid_t gid; /* Groupid for the file */
- rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
- if( rc!=SQLITE_OK ){
- assert( !p->pPreallocatedUnused );
- assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
- return rc;
- }
- fd = robust_open(zName, openFlags, openMode);
- OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
- assert( !isExclusive || (openFlags & O_CREAT)!=0 );
- if( fd<0 ){
- if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
- /* If unable to create a journal because the directory is not
- ** writable, change the error code to indicate that. */
- rc = SQLITE_READONLY_DIRECTORY;
- }else if( errno!=EISDIR && isReadWrite ){
- /* Failed to open the file for read/write access. Try read-only. */
- flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
- openFlags &= ~(O_RDWR|O_CREAT);
- flags |= SQLITE_OPEN_READONLY;
- openFlags |= O_RDONLY;
- isReadonly = 1;
- fd = robust_open(zName, openFlags, openMode);
- }
- }
- if( fd<0 ){
- int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
- if( rc==SQLITE_OK ) rc = rc2;
- goto open_finished;
- }
-
- /* If this process is running as root and if creating a new rollback
- ** journal or WAL file, set the ownership of the journal or WAL to be
- ** the same as the original database.
- */
- if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
- robustFchown(fd, uid, gid);
- }
- }
- assert( fd>=0 );
- if( pOutFlags ){
- *pOutFlags = flags;
- }
-
- if( p->pPreallocatedUnused ){
- p->pPreallocatedUnused->fd = fd;
- p->pPreallocatedUnused->flags = flags;
- }
-
- if( isDelete ){
-#if OS_VXWORKS
- zPath = zName;
-#elif defined(SQLITE_UNLINK_AFTER_CLOSE)
- zPath = sqlite3_mprintf("%s", zName);
- if( zPath==0 ){
- robust_close(p, fd, __LINE__);
- return SQLITE_NOMEM_BKPT;
- }
-#else
- osUnlink(zName);
-#endif
- }
-#if SQLITE_ENABLE_LOCKING_STYLE
- else{
- p->openFlags = openFlags;
- }
-#endif
-
-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
- if( fstatfs(fd, &fsInfo) == -1 ){
- storeLastErrno(p, errno);
- robust_close(p, fd, __LINE__);
- return SQLITE_IOERR_ACCESS;
- }
- if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
- ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
- }
- if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) {
- ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
- }
-#endif
-
- /* Set up appropriate ctrlFlags */
- if( isDelete ) ctrlFlags |= UNIXFILE_DELETE;
- if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
- noLock = eType!=SQLITE_OPEN_MAIN_DB;
- if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
- if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC;
- if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
-
-#if SQLITE_ENABLE_LOCKING_STYLE
-#if SQLITE_PREFER_PROXY_LOCKING
- isAutoProxy = 1;
-#endif
- if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
- char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
- int useProxy = 0;
-
- /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
- ** never use proxy, NULL means use proxy for non-local files only. */
- if( envforce!=NULL ){
- useProxy = atoi(envforce)>0;
- }else{
- useProxy = !(fsInfo.f_flags&MNT_LOCAL);
- }
- if( useProxy ){
- rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
- if( rc==SQLITE_OK ){
- rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
- if( rc!=SQLITE_OK ){
- /* Use unixClose to clean up the resources added in fillInUnixFile
- ** and clear all the structure's references. Specifically,
- ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
- */
- unixClose(pFile);
- return rc;
- }
- }
- goto open_finished;
- }
- }
-#endif
-
- assert( zPath==0 || zPath[0]=='/'
- || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
- );
- rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
-
-open_finished:
- if( rc!=SQLITE_OK ){
- sqlite3_free(p->pPreallocatedUnused);
- }
- return rc;
-}
-
-
-/*
-** Delete the file at zPath. If the dirSync argument is true, fsync()
-** the directory after deleting the file.
-*/
-static int unixDelete(
- sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */
- const char *zPath, /* Name of file to be deleted */
- int dirSync /* If true, fsync() directory after deleting file */
-){
- int rc = SQLITE_OK;
- UNUSED_PARAMETER(NotUsed);
- SimulateIOError(return SQLITE_IOERR_DELETE);
- if( osUnlink(zPath)==(-1) ){
- if( errno==ENOENT
-#if OS_VXWORKS
- || osAccess(zPath,0)!=0
-#endif
- ){
- rc = SQLITE_IOERR_DELETE_NOENT;
- }else{
- rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
- }
- return rc;
- }
-#ifndef SQLITE_DISABLE_DIRSYNC
- if( (dirSync & 1)!=0 ){
- int fd;
- rc = osOpenDirectory(zPath, &fd);
- if( rc==SQLITE_OK ){
- if( full_fsync(fd,0,0) ){
- rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
- }
- robust_close(0, fd, __LINE__);
- }else{
- assert( rc==SQLITE_CANTOPEN );
- rc = SQLITE_OK;
- }
- }
-#endif
- return rc;
-}
-
-/*
-** Test the existence of or access permissions of file zPath. The
-** test performed depends on the value of flags:
-**
-** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
-** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
-** SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
-**
-** Otherwise return 0.
-*/
-static int unixAccess(
- sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */
- const char *zPath, /* Path of the file to examine */
- int flags, /* What do we want to learn about the zPath file? */
- int *pResOut /* Write result boolean here */
-){
- UNUSED_PARAMETER(NotUsed);
- SimulateIOError( return SQLITE_IOERR_ACCESS; );
- assert( pResOut!=0 );
-
- /* The spec says there are three possible values for flags. But only
- ** two of them are actually used */
- assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE );
-
- if( flags==SQLITE_ACCESS_EXISTS ){
- struct stat buf;
- *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0);
- }else{
- *pResOut = osAccess(zPath, W_OK|R_OK)==0;
- }
- return SQLITE_OK;
-}
-
-/*
-**
-*/
-static int mkFullPathname(
- const char *zPath, /* Input path */
- char *zOut, /* Output buffer */
- int nOut /* Allocated size of buffer zOut */
-){
- int nPath = sqlite3Strlen30(zPath);
- int iOff = 0;
- if( zPath[0]!='/' ){
- if( osGetcwd(zOut, nOut-2)==0 ){
- return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
- }
- iOff = sqlite3Strlen30(zOut);
- zOut[iOff++] = '/';
- }
- if( (iOff+nPath+1)>nOut ){
- /* SQLite assumes that xFullPathname() nul-terminates the output buffer
- ** even if it returns an error. */
- zOut[iOff] = '\0';
- return SQLITE_CANTOPEN_BKPT;
- }
- sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
- return SQLITE_OK;
-}
-
-/*
-** Turn a relative pathname into a full pathname. The relative path
-** is stored as a nul-terminated string in the buffer pointed to by
-** zPath.
-**
-** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
-** (in this case, MAX_PATHNAME bytes). The full-path is written to
-** this buffer before returning.
-*/
-static int unixFullPathname(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- const char *zPath, /* Possibly relative input path */
- int nOut, /* Size of output buffer in bytes */
- char *zOut /* Output buffer */
-){
-#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT)
- return mkFullPathname(zPath, zOut, nOut);
-#else
- int rc = SQLITE_OK;
- int nByte;
- int nLink = 1; /* Number of symbolic links followed so far */
- const char *zIn = zPath; /* Input path for each iteration of loop */
- char *zDel = 0;
-
- assert( pVfs->mxPathname==MAX_PATHNAME );
- UNUSED_PARAMETER(pVfs);
-
- /* It's odd to simulate an io-error here, but really this is just
- ** using the io-error infrastructure to test that SQLite handles this
- ** function failing. This function could fail if, for example, the
- ** current working directory has been unlinked.
- */
- SimulateIOError( return SQLITE_ERROR );
-
- do {
-
- /* Call stat() on path zIn. Set bLink to true if the path is a symbolic
- ** link, or false otherwise. */
- int bLink = 0;
- struct stat buf;
- if( osLstat(zIn, &buf)!=0 ){
- if( errno!=ENOENT ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
- }
- }else{
- bLink = S_ISLNK(buf.st_mode);
- }
-
- if( bLink ){
- if( zDel==0 ){
- zDel = sqlite3_malloc(nOut);
- if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
- }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
- rc = SQLITE_CANTOPEN_BKPT;
- }
-
- if( rc==SQLITE_OK ){
- nByte = osReadlink(zIn, zDel, nOut-1);
- if( nByte<0 ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
- }else{
- if( zDel[0]!='/' ){
- int n;
- for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
- if( nByte+n+1>nOut ){
- rc = SQLITE_CANTOPEN_BKPT;
- }else{
- memmove(&zDel[n], zDel, nByte+1);
- memcpy(zDel, zIn, n);
- nByte += n;
- }
- }
- zDel[nByte] = '\0';
- }
- }
-
- zIn = zDel;
- }
-
- assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' );
- if( rc==SQLITE_OK && zIn!=zOut ){
- rc = mkFullPathname(zIn, zOut, nOut);
- }
- if( bLink==0 ) break;
- zIn = zOut;
- }while( rc==SQLITE_OK );
-
- sqlite3_free(zDel);
- return rc;
-#endif /* HAVE_READLINK && HAVE_LSTAT */
-}
-
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-/*
-** Interfaces for opening a shared library, finding entry points
-** within the shared library, and closing the shared library.
-*/
-#include <dlfcn.h>
-static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
- UNUSED_PARAMETER(NotUsed);
- return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
-}
-
-/*
-** SQLite calls this function immediately after a call to unixDlSym() or
-** unixDlOpen() fails (returns a null pointer). If a more detailed error
-** message is available, it is written to zBufOut. If no error message
-** is available, zBufOut is left unmodified and SQLite uses a default
-** error message.
-*/
-static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
- const char *zErr;
- UNUSED_PARAMETER(NotUsed);
- unixEnterMutex();
- zErr = dlerror();
- if( zErr ){
- sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
- }
- unixLeaveMutex();
-}
-static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
- /*
- ** GCC with -pedantic-errors says that C90 does not allow a void* to be
- ** cast into a pointer to a function. And yet the library dlsym() routine
- ** returns a void* which is really a pointer to a function. So how do we
- ** use dlsym() with -pedantic-errors?
- **
- ** Variable x below is defined to be a pointer to a function taking
- ** parameters void* and const char* and returning a pointer to a function.
- ** We initialize x by assigning it a pointer to the dlsym() function.
- ** (That assignment requires a cast.) Then we call the function that
- ** x points to.
- **
- ** This work-around is unlikely to work correctly on any system where
- ** you really cannot cast a function pointer into void*. But then, on the
- ** other hand, dlsym() will not work on such a system either, so we have
- ** not really lost anything.
- */
- void (*(*x)(void*,const char*))(void);
- UNUSED_PARAMETER(NotUsed);
- x = (void(*(*)(void*,const char*))(void))dlsym;
- return (*x)(p, zSym);
-}
-static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
- UNUSED_PARAMETER(NotUsed);
- dlclose(pHandle);
-}
-#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
- #define unixDlOpen 0
- #define unixDlError 0
- #define unixDlSym 0
- #define unixDlClose 0
-#endif
-
-/*
-** Write nBuf bytes of random data to the supplied buffer zBuf.
-*/
-static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
- UNUSED_PARAMETER(NotUsed);
- assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
-
- /* We have to initialize zBuf to prevent valgrind from reporting
- ** errors. The reports issued by valgrind are incorrect - we would
- ** prefer that the randomness be increased by making use of the
- ** uninitialized space in zBuf - but valgrind errors tend to worry
- ** some users. Rather than argue, it seems easier just to initialize
- ** the whole array and silence valgrind, even if that means less randomness
- ** in the random seed.
- **
- ** When testing, initializing zBuf[] to zero is all we do. That means
- ** that we always use the same random number sequence. This makes the
- ** tests repeatable.
- */
- memset(zBuf, 0, nBuf);
- randomnessPid = osGetpid(0);
-#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
- {
- int fd, got;
- fd = robust_open("/dev/urandom", O_RDONLY, 0);
- if( fd<0 ){
- time_t t;
- time(&t);
- memcpy(zBuf, &t, sizeof(t));
- memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid));
- assert( sizeof(t)+sizeof(randomnessPid)<=(size_t)nBuf );
- nBuf = sizeof(t) + sizeof(randomnessPid);
- }else{
- do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
- robust_close(0, fd, __LINE__);
- }
- }
-#endif
- return nBuf;
-}
-
-
-/*
-** Sleep for a little while. Return the amount of time slept.
-** The argument is the number of microseconds we want to sleep.
-** The return value is the number of microseconds of sleep actually
-** requested from the underlying operating system, a number which
-** might be greater than or equal to the argument, but not less
-** than the argument.
-*/
-static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
-#if OS_VXWORKS
- struct timespec sp;
-
- sp.tv_sec = microseconds / 1000000;
- sp.tv_nsec = (microseconds % 1000000) * 1000;
- nanosleep(&sp, NULL);
- UNUSED_PARAMETER(NotUsed);
- return microseconds;
-#elif defined(HAVE_USLEEP) && HAVE_USLEEP
- usleep(microseconds);
- UNUSED_PARAMETER(NotUsed);
- return microseconds;
-#else
- int seconds = (microseconds+999999)/1000000;
- sleep(seconds);
- UNUSED_PARAMETER(NotUsed);
- return seconds*1000000;
-#endif
-}
-
-/*
-** The following variable, if set to a non-zero value, is interpreted as
-** the number of seconds since 1970 and is used to set the result of
-** sqlite3OsCurrentTime() during testing.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
-#endif
-
-/*
-** Find the current time (in Universal Coordinated Time). Write into *piNow
-** the current time and date as a Julian Day number times 86_400_000. In
-** other words, write into *piNow the number of milliseconds since the Julian
-** epoch of noon in Greenwich on November 24, 4714 B.C according to the
-** proleptic Gregorian calendar.
-**
-** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
-** cannot be found.
-*/
-static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
- static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
- int rc = SQLITE_OK;
-#if defined(NO_GETTOD)
- time_t t;
- time(&t);
- *piNow = ((sqlite3_int64)t)*1000 + unixEpoch;
-#elif OS_VXWORKS
- struct timespec sNow;
- clock_gettime(CLOCK_REALTIME, &sNow);
- *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
-#else
- struct timeval sNow;
- (void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */
- *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
-#endif
-
-#ifdef SQLITE_TEST
- if( sqlite3_current_time ){
- *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
- }
-#endif
- UNUSED_PARAMETER(NotUsed);
- return rc;
-}
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** Find the current time (in Universal Coordinated Time). Write the
-** current time and date as a Julian Day number into *prNow and
-** return 0. Return 1 if the time and date cannot be found.
-*/
-static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
- sqlite3_int64 i = 0;
- int rc;
- UNUSED_PARAMETER(NotUsed);
- rc = unixCurrentTimeInt64(0, &i);
- *prNow = i/86400000.0;
- return rc;
-}
-#else
-# define unixCurrentTime 0
-#endif
-
-/*
-** The xGetLastError() method is designed to return a better
-** low-level error message when operating-system problems come up
-** during SQLite operation. Only the integer return code is currently
-** used.
-*/
-static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
- UNUSED_PARAMETER(NotUsed);
- UNUSED_PARAMETER(NotUsed2);
- UNUSED_PARAMETER(NotUsed3);
- return errno;
-}
-
-
-/*
-************************ End of sqlite3_vfs methods ***************************
-******************************************************************************/
-
-/******************************************************************************
-************************** Begin Proxy Locking ********************************
-**
-** Proxy locking is a "uber-locking-method" in this sense: It uses the
-** other locking methods on secondary lock files. Proxy locking is a
-** meta-layer over top of the primitive locking implemented above. For
-** this reason, the division that implements of proxy locking is deferred
-** until late in the file (here) after all of the other I/O methods have
-** been defined - so that the primitive locking methods are available
-** as services to help with the implementation of proxy locking.
-**
-****
-**
-** The default locking schemes in SQLite use byte-range locks on the
-** database file to coordinate safe, concurrent access by multiple readers
-** and writers [http://sqlite.org/lockingv3.html]. The five file locking
-** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
-** as POSIX read & write locks over fixed set of locations (via fsctl),
-** on AFP and SMB only exclusive byte-range locks are available via fsctl
-** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
-** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
-** address in the shared range is taken for a SHARED lock, the entire
-** shared range is taken for an EXCLUSIVE lock):
-**
-** PENDING_BYTE 0x40000000
-** RESERVED_BYTE 0x40000001
-** SHARED_RANGE 0x40000002 -> 0x40000200
-**
-** This works well on the local file system, but shows a nearly 100x
-** slowdown in read performance on AFP because the AFP client disables
-** the read cache when byte-range locks are present. Enabling the read
-** cache exposes a cache coherency problem that is present on all OS X
-** supported network file systems. NFS and AFP both observe the
-** close-to-open semantics for ensuring cache coherency
-** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
-** address the requirements for concurrent database access by multiple
-** readers and writers
-** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
-**
-** To address the performance and cache coherency issues, proxy file locking
-** changes the way database access is controlled by limiting access to a
-** single host at a time and moving file locks off of the database file
-** and onto a proxy file on the local file system.
-**
-**
-** Using proxy locks
-** -----------------
-**
-** C APIs
-**
-** sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE,
-** <proxy_path> | ":auto:");
-** sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE,
-** &<proxy_path>);
-**
-**
-** SQL pragmas
-**
-** PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
-** PRAGMA [database.]lock_proxy_file
-**
-** Specifying ":auto:" means that if there is a conch file with a matching
-** host ID in it, the proxy path in the conch file will be used, otherwise
-** a proxy path based on the user's temp dir
-** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
-** actual proxy file name is generated from the name and path of the
-** database file. For example:
-**
-** For database path "/Users/me/foo.db"
-** The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
-**
-** Once a lock proxy is configured for a database connection, it can not
-** be removed, however it may be switched to a different proxy path via
-** the above APIs (assuming the conch file is not being held by another
-** connection or process).
-**
-**
-** How proxy locking works
-** -----------------------
-**
-** Proxy file locking relies primarily on two new supporting files:
-**
-** * conch file to limit access to the database file to a single host
-** at a time
-**
-** * proxy file to act as a proxy for the advisory locks normally
-** taken on the database
-**
-** The conch file - to use a proxy file, sqlite must first "hold the conch"
-** by taking an sqlite-style shared lock on the conch file, reading the
-** contents and comparing the host's unique host ID (see below) and lock
-** proxy path against the values stored in the conch. The conch file is
-** stored in the same directory as the database file and the file name
-** is patterned after the database file name as ".<databasename>-conch".
-** If the conch file does not exist, or its contents do not match the
-** host ID and/or proxy path, then the lock is escalated to an exclusive
-** lock and the conch file contents is updated with the host ID and proxy
-** path and the lock is downgraded to a shared lock again. If the conch
-** is held by another process (with a shared lock), the exclusive lock
-** will fail and SQLITE_BUSY is returned.
-**
-** The proxy file - a single-byte file used for all advisory file locks
-** normally taken on the database file. This allows for safe sharing
-** of the database file for multiple readers and writers on the same
-** host (the conch ensures that they all use the same local lock file).
-**
-** Requesting the lock proxy does not immediately take the conch, it is
-** only taken when the first request to lock database file is made.
-** This matches the semantics of the traditional locking behavior, where
-** opening a connection to a database file does not take a lock on it.
-** The shared lock and an open file descriptor are maintained until
-** the connection to the database is closed.
-**
-** The proxy file and the lock file are never deleted so they only need
-** to be created the first time they are used.
-**
-** Configuration options
-** ---------------------
-**
-** SQLITE_PREFER_PROXY_LOCKING
-**
-** Database files accessed on non-local file systems are
-** automatically configured for proxy locking, lock files are
-** named automatically using the same logic as
-** PRAGMA lock_proxy_file=":auto:"
-**
-** SQLITE_PROXY_DEBUG
-**
-** Enables the logging of error messages during host id file
-** retrieval and creation
-**
-** LOCKPROXYDIR
-**
-** Overrides the default directory used for lock proxy files that
-** are named automatically via the ":auto:" setting
-**
-** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
-**
-** Permissions to use when creating a directory for storing the
-** lock proxy files, only used when LOCKPROXYDIR is not set.
-**
-**
-** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
-** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
-** force proxy locking to be used for every database file opened, and 0
-** will force automatic proxy locking to be disabled for all database
-** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or
-** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
-*/
-
-/*
-** Proxy locking is only available on MacOSX
-*/
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-
-/*
-** The proxyLockingContext has the path and file structures for the remote
-** and local proxy files in it
-*/
-typedef struct proxyLockingContext proxyLockingContext;
-struct proxyLockingContext {
- unixFile *conchFile; /* Open conch file */
- char *conchFilePath; /* Name of the conch file */
- unixFile *lockProxy; /* Open proxy lock file */
- char *lockProxyPath; /* Name of the proxy lock file */
- char *dbPath; /* Name of the open file */
- int conchHeld; /* 1 if the conch is held, -1 if lockless */
- int nFails; /* Number of conch taking failures */
- void *oldLockingContext; /* Original lockingcontext to restore on close */
- sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
-};
-
-/*
-** The proxy lock file path for the database at dbPath is written into lPath,
-** which must point to valid, writable memory large enough for a maxLen length
-** file path.
-*/
-static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
- int len;
- int dbLen;
- int i;
-
-#ifdef LOCKPROXYDIR
- len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
-#else
-# ifdef _CS_DARWIN_USER_TEMP_DIR
- {
- if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
- OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
- lPath, errno, osGetpid(0)));
- return SQLITE_IOERR_LOCK;
- }
- len = strlcat(lPath, "sqliteplocks", maxLen);
- }
-# else
- len = strlcpy(lPath, "/tmp/", maxLen);
-# endif
-#endif
-
- if( lPath[len-1]!='/' ){
- len = strlcat(lPath, "/", maxLen);
- }
-
- /* transform the db path to a unique cache name */
- dbLen = (int)strlen(dbPath);
- for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
- char c = dbPath[i];
- lPath[i+len] = (c=='/')?'_':c;
- }
- lPath[i+len]='\0';
- strlcat(lPath, ":auto:", maxLen);
- OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid(0)));
- return SQLITE_OK;
-}
-
-/*
- ** Creates the lock file and any missing directories in lockPath
- */
-static int proxyCreateLockPath(const char *lockPath){
- int i, len;
- char buf[MAXPATHLEN];
- int start = 0;
-
- assert(lockPath!=NULL);
- /* try to create all the intermediate directories */
- len = (int)strlen(lockPath);
- buf[0] = lockPath[0];
- for( i=1; i<len; i++ ){
- if( lockPath[i] == '/' && (i - start > 0) ){
- /* only mkdir if leaf dir != "." or "/" or ".." */
- if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
- || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
- buf[i]='\0';
- if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
- int err=errno;
- if( err!=EEXIST ) {
- OSTRACE(("CREATELOCKPATH FAILED creating %s, "
- "'%s' proxy lock path=%s pid=%d\n",
- buf, strerror(err), lockPath, osGetpid(0)));
- return err;
- }
- }
- }
- start=i+1;
- }
- buf[i] = lockPath[i];
- }
- OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n",lockPath,osGetpid(0)));
- return 0;
-}
-
-/*
-** Create a new VFS file descriptor (stored in memory obtained from
-** sqlite3_malloc) and open the file named "path" in the file descriptor.
-**
-** The caller is responsible not only for closing the file descriptor
-** but also for freeing the memory associated with the file descriptor.
-*/
-static int proxyCreateUnixFile(
- const char *path, /* path for the new unixFile */
- unixFile **ppFile, /* unixFile created and returned by ref */
- int islockfile /* if non zero missing dirs will be created */
-) {
- int fd = -1;
- unixFile *pNew;
- int rc = SQLITE_OK;
- int openFlags = O_RDWR | O_CREAT;
- sqlite3_vfs dummyVfs;
- int terrno = 0;
- UnixUnusedFd *pUnused = NULL;
-
- /* 1. first try to open/create the file
- ** 2. if that fails, and this is a lock file (not-conch), try creating
- ** the parent directories and then try again.
- ** 3. if that fails, try to open the file read-only
- ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
- */
- pUnused = findReusableFd(path, openFlags);
- if( pUnused ){
- fd = pUnused->fd;
- }else{
- pUnused = sqlite3_malloc64(sizeof(*pUnused));
- if( !pUnused ){
- return SQLITE_NOMEM_BKPT;
- }
- }
- if( fd<0 ){
- fd = robust_open(path, openFlags, 0);
- terrno = errno;
- if( fd<0 && errno==ENOENT && islockfile ){
- if( proxyCreateLockPath(path) == SQLITE_OK ){
- fd = robust_open(path, openFlags, 0);
- }
- }
- }
- if( fd<0 ){
- openFlags = O_RDONLY;
- fd = robust_open(path, openFlags, 0);
- terrno = errno;
- }
- if( fd<0 ){
- if( islockfile ){
- return SQLITE_BUSY;
- }
- switch (terrno) {
- case EACCES:
- return SQLITE_PERM;
- case EIO:
- return SQLITE_IOERR_LOCK; /* even though it is the conch */
- default:
- return SQLITE_CANTOPEN_BKPT;
- }
- }
-
- pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew));
- if( pNew==NULL ){
- rc = SQLITE_NOMEM_BKPT;
- goto end_create_proxy;
- }
- memset(pNew, 0, sizeof(unixFile));
- pNew->openFlags = openFlags;
- memset(&dummyVfs, 0, sizeof(dummyVfs));
- dummyVfs.pAppData = (void*)&autolockIoFinder;
- dummyVfs.zName = "dummy";
- pUnused->fd = fd;
- pUnused->flags = openFlags;
- pNew->pPreallocatedUnused = pUnused;
-
- rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
- if( rc==SQLITE_OK ){
- *ppFile = pNew;
- return SQLITE_OK;
- }
-end_create_proxy:
- robust_close(pNew, fd, __LINE__);
- sqlite3_free(pNew);
- sqlite3_free(pUnused);
- return rc;
-}
-
-#ifdef SQLITE_TEST
-/* simulate multiple hosts by creating unique hostid file paths */
-int sqlite3_hostid_num = 0;
-#endif
-
-#define PROXY_HOSTIDLEN 16 /* conch file host id length */
-
-#ifdef HAVE_GETHOSTUUID
-/* Not always defined in the headers as it ought to be */
-extern int gethostuuid(uuid_t id, const struct timespec *wait);
-#endif
-
-/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
-** bytes of writable memory.
-*/
-static int proxyGetHostID(unsigned char *pHostID, int *pError){
- assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
- memset(pHostID, 0, PROXY_HOSTIDLEN);
-#ifdef HAVE_GETHOSTUUID
- {
- struct timespec timeout = {1, 0}; /* 1 sec timeout */
- if( gethostuuid(pHostID, &timeout) ){
- int err = errno;
- if( pError ){
- *pError = err;
- }
- return SQLITE_IOERR;
- }
- }
-#else
- UNUSED_PARAMETER(pError);
-#endif
-#ifdef SQLITE_TEST
- /* simulate multiple hosts by creating unique hostid file paths */
- if( sqlite3_hostid_num != 0){
- pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
- }
-#endif
-
- return SQLITE_OK;
-}
-
-/* The conch file contains the header, host id and lock file path
- */
-#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */
-#define PROXY_HEADERLEN 1 /* conch file header length */
-#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
-#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
-
-/*
-** Takes an open conch file, copies the contents to a new path and then moves
-** it back. The newly created file's file descriptor is assigned to the
-** conch file structure and finally the original conch file descriptor is
-** closed. Returns zero if successful.
-*/
-static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
- unixFile *conchFile = pCtx->conchFile;
- char tPath[MAXPATHLEN];
- char buf[PROXY_MAXCONCHLEN];
- char *cPath = pCtx->conchFilePath;
- size_t readLen = 0;
- size_t pathLen = 0;
- char errmsg[64] = "";
- int fd = -1;
- int rc = -1;
- UNUSED_PARAMETER(myHostID);
-
- /* create a new path by replace the trailing '-conch' with '-break' */
- pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
- if( pathLen>MAXPATHLEN || pathLen<6 ||
- (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
- sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
- goto end_breaklock;
- }
- /* read the conch content */
- readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
- if( readLen<PROXY_PATHINDEX ){
- sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
- goto end_breaklock;
- }
- /* write it out to the temporary break file */
- fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
- if( fd<0 ){
- sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
- goto end_breaklock;
- }
- if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
- sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
- goto end_breaklock;
- }
- if( rename(tPath, cPath) ){
- sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)", errno);
- goto end_breaklock;
- }
- rc = 0;
- fprintf(stderr, "broke stale lock on %s\n", cPath);
- robust_close(pFile, conchFile->h, __LINE__);
- conchFile->h = fd;
- conchFile->openFlags = O_RDWR | O_CREAT;
-
-end_breaklock:
- if( rc ){
- if( fd>=0 ){
- osUnlink(tPath);
- robust_close(pFile, fd, __LINE__);
- }
- fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
- }
- return rc;
-}
-
-/* Take the requested lock on the conch file and break a stale lock if the
-** host id matches.
-*/
-static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
- unixFile *conchFile = pCtx->conchFile;
- int rc = SQLITE_OK;
- int nTries = 0;
- struct timespec conchModTime;
-
- memset(&conchModTime, 0, sizeof(conchModTime));
- do {
- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
- nTries ++;
- if( rc==SQLITE_BUSY ){
- /* If the lock failed (busy):
- * 1st try: get the mod time of the conch, wait 0.5s and try again.
- * 2nd try: fail if the mod time changed or host id is different, wait
- * 10 sec and try again
- * 3rd try: break the lock unless the mod time has changed.
- */
- struct stat buf;
- if( osFstat(conchFile->h, &buf) ){
- storeLastErrno(pFile, errno);
- return SQLITE_IOERR_LOCK;
- }
-
- if( nTries==1 ){
- conchModTime = buf.st_mtimespec;
- usleep(500000); /* wait 0.5 sec and try the lock again*/
- continue;
- }
-
- assert( nTries>1 );
- if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
- conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
- return SQLITE_BUSY;
- }
-
- if( nTries==2 ){
- char tBuf[PROXY_MAXCONCHLEN];
- int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
- if( len<0 ){
- storeLastErrno(pFile, errno);
- return SQLITE_IOERR_LOCK;
- }
- if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
- /* don't break the lock if the host id doesn't match */
- if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
- return SQLITE_BUSY;
- }
- }else{
- /* don't break the lock on short read or a version mismatch */
- return SQLITE_BUSY;
- }
- usleep(10000000); /* wait 10 sec and try the lock again */
- continue;
- }
-
- assert( nTries==3 );
- if( 0==proxyBreakConchLock(pFile, myHostID) ){
- rc = SQLITE_OK;
- if( lockType==EXCLUSIVE_LOCK ){
- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
- }
- if( !rc ){
- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
- }
- }
- }
- } while( rc==SQLITE_BUSY && nTries<3 );
-
- return rc;
-}
-
-/* Takes the conch by taking a shared lock and read the contents conch, if
-** lockPath is non-NULL, the host ID and lock file path must match. A NULL
-** lockPath means that the lockPath in the conch file will be used if the
-** host IDs match, or a new lock path will be generated automatically
-** and written to the conch file.
-*/
-static int proxyTakeConch(unixFile *pFile){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-
- if( pCtx->conchHeld!=0 ){
- return SQLITE_OK;
- }else{
- unixFile *conchFile = pCtx->conchFile;
- uuid_t myHostID;
- int pError = 0;
- char readBuf[PROXY_MAXCONCHLEN];
- char lockPath[MAXPATHLEN];
- char *tempLockPath = NULL;
- int rc = SQLITE_OK;
- int createConch = 0;
- int hostIdMatch = 0;
- int readLen = 0;
- int tryOldLockPath = 0;
- int forceNewLockPath = 0;
-
- OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
- (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
- osGetpid(0)));
-
- rc = proxyGetHostID(myHostID, &pError);
- if( (rc&0xff)==SQLITE_IOERR ){
- storeLastErrno(pFile, pError);
- goto end_takeconch;
- }
- rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
- if( rc!=SQLITE_OK ){
- goto end_takeconch;
- }
- /* read the existing conch file */
- readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
- if( readLen<0 ){
- /* I/O error: lastErrno set by seekAndRead */
- storeLastErrno(pFile, conchFile->lastErrno);
- rc = SQLITE_IOERR_READ;
- goto end_takeconch;
- }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
- readBuf[0]!=(char)PROXY_CONCHVERSION ){
- /* a short read or version format mismatch means we need to create a new
- ** conch file.
- */
- createConch = 1;
- }
- /* if the host id matches and the lock path already exists in the conch
- ** we'll try to use the path there, if we can't open that path, we'll
- ** retry with a new auto-generated path
- */
- do { /* in case we need to try again for an :auto: named lock file */
-
- if( !createConch && !forceNewLockPath ){
- hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
- PROXY_HOSTIDLEN);
- /* if the conch has data compare the contents */
- if( !pCtx->lockProxyPath ){
- /* for auto-named local lock file, just check the host ID and we'll
- ** use the local lock file path that's already in there
- */
- if( hostIdMatch ){
- size_t pathLen = (readLen - PROXY_PATHINDEX);
-
- if( pathLen>=MAXPATHLEN ){
- pathLen=MAXPATHLEN-1;
- }
- memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
- lockPath[pathLen] = 0;
- tempLockPath = lockPath;
- tryOldLockPath = 1;
- /* create a copy of the lock path if the conch is taken */
- goto end_takeconch;
- }
- }else if( hostIdMatch
- && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
- readLen-PROXY_PATHINDEX)
- ){
- /* conch host and lock path match */
- goto end_takeconch;
- }
- }
-
- /* if the conch isn't writable and doesn't match, we can't take it */
- if( (conchFile->openFlags&O_RDWR) == 0 ){
- rc = SQLITE_BUSY;
- goto end_takeconch;
- }
-
- /* either the conch didn't match or we need to create a new one */
- if( !pCtx->lockProxyPath ){
- proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
- tempLockPath = lockPath;
- /* create a copy of the lock path _only_ if the conch is taken */
- }
-
- /* update conch with host and path (this will fail if other process
- ** has a shared lock already), if the host id matches, use the big
- ** stick.
- */
- futimes(conchFile->h, NULL);
- if( hostIdMatch && !createConch ){
- if( conchFile->pInode && conchFile->pInode->nShared>1 ){
- /* We are trying for an exclusive lock but another thread in this
- ** same process is still holding a shared lock. */
- rc = SQLITE_BUSY;
- } else {
- rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
- }
- }else{
- rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
- }
- if( rc==SQLITE_OK ){
- char writeBuffer[PROXY_MAXCONCHLEN];
- int writeSize = 0;
-
- writeBuffer[0] = (char)PROXY_CONCHVERSION;
- memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
- if( pCtx->lockProxyPath!=NULL ){
- strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath,
- MAXPATHLEN);
- }else{
- strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
- }
- writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
- robust_ftruncate(conchFile->h, writeSize);
- rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
- full_fsync(conchFile->h,0,0);
- /* If we created a new conch file (not just updated the contents of a
- ** valid conch file), try to match the permissions of the database
- */
- if( rc==SQLITE_OK && createConch ){
- struct stat buf;
- int err = osFstat(pFile->h, &buf);
- if( err==0 ){
- mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
- S_IROTH|S_IWOTH);
- /* try to match the database file R/W permissions, ignore failure */
-#ifndef SQLITE_PROXY_DEBUG
- osFchmod(conchFile->h, cmode);
-#else
- do{
- rc = osFchmod(conchFile->h, cmode);
- }while( rc==(-1) && errno==EINTR );
- if( rc!=0 ){
- int code = errno;
- fprintf(stderr, "fchmod %o FAILED with %d %s\n",
- cmode, code, strerror(code));
- } else {
- fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
- }
- }else{
- int code = errno;
- fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
- err, code, strerror(code));
-#endif
- }
- }
- }
- conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
-
- end_takeconch:
- OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
- if( rc==SQLITE_OK && pFile->openFlags ){
- int fd;
- if( pFile->h>=0 ){
- robust_close(pFile, pFile->h, __LINE__);
- }
- pFile->h = -1;
- fd = robust_open(pCtx->dbPath, pFile->openFlags, 0);
- OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
- if( fd>=0 ){
- pFile->h = fd;
- }else{
- rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
- during locking */
- }
- }
- if( rc==SQLITE_OK && !pCtx->lockProxy ){
- char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
- rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
- if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
- /* we couldn't create the proxy lock file with the old lock file path
- ** so try again via auto-naming
- */
- forceNewLockPath = 1;
- tryOldLockPath = 0;
- continue; /* go back to the do {} while start point, try again */
- }
- }
- if( rc==SQLITE_OK ){
- /* Need to make a copy of path if we extracted the value
- ** from the conch file or the path was allocated on the stack
- */
- if( tempLockPath ){
- pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
- if( !pCtx->lockProxyPath ){
- rc = SQLITE_NOMEM_BKPT;
- }
- }
- }
- if( rc==SQLITE_OK ){
- pCtx->conchHeld = 1;
-
- if( pCtx->lockProxy->pMethod == &afpIoMethods ){
- afpLockingContext *afpCtx;
- afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
- afpCtx->dbPath = pCtx->lockProxyPath;
- }
- } else {
- conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
- }
- OSTRACE(("TAKECONCH %d %s\n", conchFile->h,
- rc==SQLITE_OK?"ok":"failed"));
- return rc;
- } while (1); /* in case we need to retry the :auto: lock file -
- ** we should never get here except via the 'continue' call. */
- }
-}
-
-/*
-** If pFile holds a lock on a conch file, then release that lock.
-*/
-static int proxyReleaseConch(unixFile *pFile){
- int rc = SQLITE_OK; /* Subroutine return code */
- proxyLockingContext *pCtx; /* The locking context for the proxy lock */
- unixFile *conchFile; /* Name of the conch file */
-
- pCtx = (proxyLockingContext *)pFile->lockingContext;
- conchFile = pCtx->conchFile;
- OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
- (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
- osGetpid(0)));
- if( pCtx->conchHeld>0 ){
- rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
- }
- pCtx->conchHeld = 0;
- OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
- (rc==SQLITE_OK ? "ok" : "failed")));
- return rc;
-}
-
-/*
-** Given the name of a database file, compute the name of its conch file.
-** Store the conch filename in memory obtained from sqlite3_malloc64().
-** Make *pConchPath point to the new name. Return SQLITE_OK on success
-** or SQLITE_NOMEM if unable to obtain memory.
-**
-** The caller is responsible for ensuring that the allocated memory
-** space is eventually freed.
-**
-** *pConchPath is set to NULL if a memory allocation error occurs.
-*/
-static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
- int i; /* Loop counter */
- int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
- char *conchPath; /* buffer in which to construct conch name */
-
- /* Allocate space for the conch filename and initialize the name to
- ** the name of the original database file. */
- *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8);
- if( conchPath==0 ){
- return SQLITE_NOMEM_BKPT;
- }
- memcpy(conchPath, dbPath, len+1);
-
- /* now insert a "." before the last / character */
- for( i=(len-1); i>=0; i-- ){
- if( conchPath[i]=='/' ){
- i++;
- break;
- }
- }
- conchPath[i]='.';
- while ( i<len ){
- conchPath[i+1]=dbPath[i];
- i++;
- }
-
- /* append the "-conch" suffix to the file */
- memcpy(&conchPath[i+1], "-conch", 7);
- assert( (int)strlen(conchPath) == len+7 );
-
- return SQLITE_OK;
-}
-
-
-/* Takes a fully configured proxy locking-style unix file and switches
-** the local lock file path
-*/
-static int switchLockProxyPath(unixFile *pFile, const char *path) {
- proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
- char *oldPath = pCtx->lockProxyPath;
- int rc = SQLITE_OK;
-
- if( pFile->eFileLock!=NO_LOCK ){
- return SQLITE_BUSY;
- }
-
- /* nothing to do if the path is NULL, :auto: or matches the existing path */
- if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
- (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
- return SQLITE_OK;
- }else{
- unixFile *lockProxy = pCtx->lockProxy;
- pCtx->lockProxy=NULL;
- pCtx->conchHeld = 0;
- if( lockProxy!=NULL ){
- rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
- if( rc ) return rc;
- sqlite3_free(lockProxy);
- }
- sqlite3_free(oldPath);
- pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
- }
-
- return rc;
-}
-
-/*
-** pFile is a file that has been opened by a prior xOpen call. dbPath
-** is a string buffer at least MAXPATHLEN+1 characters in size.
-**
-** This routine find the filename associated with pFile and writes it
-** int dbPath.
-*/
-static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
-#if defined(__APPLE__)
- if( pFile->pMethod == &afpIoMethods ){
- /* afp style keeps a reference to the db path in the filePath field
- ** of the struct */
- assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
- strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath,
- MAXPATHLEN);
- } else
-#endif
- if( pFile->pMethod == &dotlockIoMethods ){
- /* dot lock style uses the locking context to store the dot lock
- ** file path */
- int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
- memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
- }else{
- /* all other styles use the locking context to store the db file path */
- assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
- strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
- }
- return SQLITE_OK;
-}
-
-/*
-** Takes an already filled in unix file and alters it so all file locking
-** will be performed on the local proxy lock file. The following fields
-** are preserved in the locking context so that they can be restored and
-** the unix structure properly cleaned up at close time:
-** ->lockingContext
-** ->pMethod
-*/
-static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
- proxyLockingContext *pCtx;
- char dbPath[MAXPATHLEN+1]; /* Name of the database file */
- char *lockPath=NULL;
- int rc = SQLITE_OK;
-
- if( pFile->eFileLock!=NO_LOCK ){
- return SQLITE_BUSY;
- }
- proxyGetDbPathForUnixFile(pFile, dbPath);
- if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
- lockPath=NULL;
- }else{
- lockPath=(char *)path;
- }
-
- OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
- (lockPath ? lockPath : ":auto:"), osGetpid(0)));
-
- pCtx = sqlite3_malloc64( sizeof(*pCtx) );
- if( pCtx==0 ){
- return SQLITE_NOMEM_BKPT;
- }
- memset(pCtx, 0, sizeof(*pCtx));
-
- rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
- if( rc==SQLITE_OK ){
- rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
- if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
- /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
- ** (c) the file system is read-only, then enable no-locking access.
- ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
- ** that openFlags will have only one of O_RDONLY or O_RDWR.
- */
- struct statfs fsInfo;
- struct stat conchInfo;
- int goLockless = 0;
-
- if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
- int err = errno;
- if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
- goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
- }
- }
- if( goLockless ){
- pCtx->conchHeld = -1; /* read only FS/ lockless */
- rc = SQLITE_OK;
- }
- }
- }
- if( rc==SQLITE_OK && lockPath ){
- pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
- }
-
- if( rc==SQLITE_OK ){
- pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
- if( pCtx->dbPath==NULL ){
- rc = SQLITE_NOMEM_BKPT;
- }
- }
- if( rc==SQLITE_OK ){
- /* all memory is allocated, proxys are created and assigned,
- ** switch the locking context and pMethod then return.
- */
- pCtx->oldLockingContext = pFile->lockingContext;
- pFile->lockingContext = pCtx;
- pCtx->pOldMethod = pFile->pMethod;
- pFile->pMethod = &proxyIoMethods;
- }else{
- if( pCtx->conchFile ){
- pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
- sqlite3_free(pCtx->conchFile);
- }
- sqlite3DbFree(0, pCtx->lockProxyPath);
- sqlite3_free(pCtx->conchFilePath);
- sqlite3_free(pCtx);
- }
- OSTRACE(("TRANSPROXY %d %s\n", pFile->h,
- (rc==SQLITE_OK ? "ok" : "failed")));
- return rc;
-}
-
-
-/*
-** This routine handles sqlite3_file_control() calls that are specific
-** to proxy locking.
-*/
-static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
- switch( op ){
- case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
- unixFile *pFile = (unixFile*)id;
- if( pFile->pMethod == &proxyIoMethods ){
- proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
- proxyTakeConch(pFile);
- if( pCtx->lockProxyPath ){
- *(const char **)pArg = pCtx->lockProxyPath;
- }else{
- *(const char **)pArg = ":auto: (not held)";
- }
- } else {
- *(const char **)pArg = NULL;
- }
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_SET_LOCKPROXYFILE: {
- unixFile *pFile = (unixFile*)id;
- int rc = SQLITE_OK;
- int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
- if( pArg==NULL || (const char *)pArg==0 ){
- if( isProxyStyle ){
- /* turn off proxy locking - not supported. If support is added for
- ** switching proxy locking mode off then it will need to fail if
- ** the journal mode is WAL mode.
- */
- rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
- }else{
- /* turn off proxy locking - already off - NOOP */
- rc = SQLITE_OK;
- }
- }else{
- const char *proxyPath = (const char *)pArg;
- if( isProxyStyle ){
- proxyLockingContext *pCtx =
- (proxyLockingContext*)pFile->lockingContext;
- if( !strcmp(pArg, ":auto:")
- || (pCtx->lockProxyPath &&
- !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
- ){
- rc = SQLITE_OK;
- }else{
- rc = switchLockProxyPath(pFile, proxyPath);
- }
- }else{
- /* turn on proxy file locking */
- rc = proxyTransformUnixFile(pFile, proxyPath);
- }
- }
- return rc;
- }
- default: {
- assert( 0 ); /* The call assures that only valid opcodes are sent */
- }
- }
- /*NOTREACHED*/
- return SQLITE_ERROR;
-}
-
-/*
-** Within this division (the proxying locking implementation) the procedures
-** above this point are all utilities. The lock-related methods of the
-** proxy-locking sqlite3_io_method object follow.
-*/
-
-
-/*
-** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-*/
-static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
- unixFile *pFile = (unixFile*)id;
- int rc = proxyTakeConch(pFile);
- if( rc==SQLITE_OK ){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
- if( pCtx->conchHeld>0 ){
- unixFile *proxy = pCtx->lockProxy;
- return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
- }else{ /* conchHeld < 0 is lockless */
- pResOut=0;
- }
- }
- return rc;
-}
-
-/*
-** Lock the file with the lock specified by parameter eFileLock - one
-** of the following:
-**
-** (1) SHARED_LOCK
-** (2) RESERVED_LOCK
-** (3) PENDING_LOCK
-** (4) EXCLUSIVE_LOCK
-**
-** Sometimes when requesting one lock state, additional lock states
-** are inserted in between. The locking might fail on one of the later
-** transitions leaving the lock state different from what it started but
-** still short of its goal. The following chart shows the allowed
-** transitions and the inserted intermediate states:
-**
-** UNLOCKED -> SHARED
-** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
-** RESERVED -> (PENDING) -> EXCLUSIVE
-** PENDING -> EXCLUSIVE
-**
-** This routine will only increase a lock. Use the sqlite3OsUnlock()
-** routine to lower a locking level.
-*/
-static int proxyLock(sqlite3_file *id, int eFileLock) {
- unixFile *pFile = (unixFile*)id;
- int rc = proxyTakeConch(pFile);
- if( rc==SQLITE_OK ){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
- if( pCtx->conchHeld>0 ){
- unixFile *proxy = pCtx->lockProxy;
- rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
- pFile->eFileLock = proxy->eFileLock;
- }else{
- /* conchHeld < 0 is lockless */
- }
- }
- return rc;
-}
-
-
-/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-** must be either NO_LOCK or SHARED_LOCK.
-**
-** If the locking level of the file descriptor is already at or below
-** the requested locking level, this routine is a no-op.
-*/
-static int proxyUnlock(sqlite3_file *id, int eFileLock) {
- unixFile *pFile = (unixFile*)id;
- int rc = proxyTakeConch(pFile);
- if( rc==SQLITE_OK ){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
- if( pCtx->conchHeld>0 ){
- unixFile *proxy = pCtx->lockProxy;
- rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
- pFile->eFileLock = proxy->eFileLock;
- }else{
- /* conchHeld < 0 is lockless */
- }
- }
- return rc;
-}
-
-/*
-** Close a file that uses proxy locks.
-*/
-static int proxyClose(sqlite3_file *id) {
- if( ALWAYS(id) ){
- unixFile *pFile = (unixFile*)id;
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
- unixFile *lockProxy = pCtx->lockProxy;
- unixFile *conchFile = pCtx->conchFile;
- int rc = SQLITE_OK;
-
- if( lockProxy ){
- rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
- if( rc ) return rc;
- rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
- if( rc ) return rc;
- sqlite3_free(lockProxy);
- pCtx->lockProxy = 0;
- }
- if( conchFile ){
- if( pCtx->conchHeld ){
- rc = proxyReleaseConch(pFile);
- if( rc ) return rc;
- }
- rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
- if( rc ) return rc;
- sqlite3_free(conchFile);
- }
- sqlite3DbFree(0, pCtx->lockProxyPath);
- sqlite3_free(pCtx->conchFilePath);
- sqlite3DbFree(0, pCtx->dbPath);
- /* restore the original locking context and pMethod then close it */
- pFile->lockingContext = pCtx->oldLockingContext;
- pFile->pMethod = pCtx->pOldMethod;
- sqlite3_free(pCtx);
- return pFile->pMethod->xClose(id);
- }
- return SQLITE_OK;
-}
-
-
-
-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-/*
-** The proxy locking style is intended for use with AFP filesystems.
-** And since AFP is only supported on MacOSX, the proxy locking is also
-** restricted to MacOSX.
-**
-**
-******************* End of the proxy lock implementation **********************
-******************************************************************************/
-
-/*
-** Initialize the operating system interface.
-**
-** This routine registers all VFS implementations for unix-like operating
-** systems. This routine, and the sqlite3_os_end() routine that follows,
-** should be the only routines in this file that are visible from other
-** files.
-**
-** This routine is called once during SQLite initialization and by a
-** single thread. The memory allocation and mutex subsystems have not
-** necessarily been initialized when this routine is called, and so they
-** should not be used.
-*/
-int sqlite3_os_init(void){
- /*
- ** The following macro defines an initializer for an sqlite3_vfs object.
- ** The name of the VFS is NAME. The pAppData is a pointer to a pointer
- ** to the "finder" function. (pAppData is a pointer to a pointer because
- ** silly C90 rules prohibit a void* from being cast to a function pointer
- ** and so we have to go through the intermediate pointer to avoid problems
- ** when compiling with -pedantic-errors on GCC.)
- **
- ** The FINDER parameter to this macro is the name of the pointer to the
- ** finder-function. The finder-function returns a pointer to the
- ** sqlite_io_methods object that implements the desired locking
- ** behaviors. See the division above that contains the IOMETHODS
- ** macro for addition information on finder-functions.
- **
- ** Most finders simply return a pointer to a fixed sqlite3_io_methods
- ** object. But the "autolockIoFinder" available on MacOSX does a little
- ** more than that; it looks at the filesystem type that hosts the
- ** database file and tries to choose an locking method appropriate for
- ** that filesystem time.
- */
- #define UNIXVFS(VFSNAME, FINDER) { \
- 3, /* iVersion */ \
- sizeof(unixFile), /* szOsFile */ \
- MAX_PATHNAME, /* mxPathname */ \
- 0, /* pNext */ \
- VFSNAME, /* zName */ \
- (void*)&FINDER, /* pAppData */ \
- unixOpen, /* xOpen */ \
- unixDelete, /* xDelete */ \
- unixAccess, /* xAccess */ \
- unixFullPathname, /* xFullPathname */ \
- unixDlOpen, /* xDlOpen */ \
- unixDlError, /* xDlError */ \
- unixDlSym, /* xDlSym */ \
- unixDlClose, /* xDlClose */ \
- unixRandomness, /* xRandomness */ \
- unixSleep, /* xSleep */ \
- unixCurrentTime, /* xCurrentTime */ \
- unixGetLastError, /* xGetLastError */ \
- unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \
- unixSetSystemCall, /* xSetSystemCall */ \
- unixGetSystemCall, /* xGetSystemCall */ \
- unixNextSystemCall, /* xNextSystemCall */ \
- }
-
- /*
- ** All default VFSes for unix are contained in the following array.
- **
- ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
- ** by the SQLite core when the VFS is registered. So the following
- ** array cannot be const.
- */
- static sqlite3_vfs aVfs[] = {
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- UNIXVFS("unix", autolockIoFinder ),
-#elif OS_VXWORKS
- UNIXVFS("unix", vxworksIoFinder ),
-#else
- UNIXVFS("unix", posixIoFinder ),
-#endif
- UNIXVFS("unix-none", nolockIoFinder ),
- UNIXVFS("unix-dotfile", dotlockIoFinder ),
- UNIXVFS("unix-excl", posixIoFinder ),
-#if OS_VXWORKS
- UNIXVFS("unix-namedsem", semIoFinder ),
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
- UNIXVFS("unix-posix", posixIoFinder ),
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE
- UNIXVFS("unix-flock", flockIoFinder ),
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- UNIXVFS("unix-afp", afpIoFinder ),
- UNIXVFS("unix-nfs", nfsIoFinder ),
- UNIXVFS("unix-proxy", proxyIoFinder ),
-#endif
- };
- unsigned int i; /* Loop counter */
-
- /* Double-check that the aSyscall[] array has been constructed
- ** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==29 );
-
- /* Register all VFSes defined in the aVfs[] array */
- for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
- sqlite3_vfs_register(&aVfs[i], i==0);
- }
- unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
- return SQLITE_OK;
-}
-
-/*
-** Shutdown the operating system interface.
-**
-** Some operating systems might need to do some cleanup in this routine,
-** to release dynamically allocated objects. But not on unix.
-** This routine is a no-op for unix.
-*/
-int sqlite3_os_end(void){
- unixBigLock = 0;
- return SQLITE_OK;
-}
-
-#endif /* SQLITE_OS_UNIX */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_win.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/os_win.c
deleted file mode 100644
index 3eb2f3c6123..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_win.c
+++ /dev/null
@@ -1,6105 +0,0 @@
-/*
-** 2004 May 22
-**
-** 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 contains code that is specific to Windows.
-*/
-#include "sqliteInt.h"
-#if SQLITE_OS_WIN /* This file is used for Windows only */
-
-/*
-** Include code that is common to all os_*.c files
-*/
-#include "os_common.h"
-
-/*
-** Include the header file for the Windows VFS.
-*/
-#include "os_win.h"
-
-/*
-** Compiling and using WAL mode requires several APIs that are only
-** available in Windows platforms based on the NT kernel.
-*/
-#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
-# error "WAL mode requires support from the Windows NT kernel, compile\
- with SQLITE_OMIT_WAL."
-#endif
-
-#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0
-# error "Memory mapped files require support from the Windows NT kernel,\
- compile with SQLITE_MAX_MMAP_SIZE=0."
-#endif
-
-/*
-** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
-** based on the sub-platform)?
-*/
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI)
-# define SQLITE_WIN32_HAS_ANSI
-#endif
-
-/*
-** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
-** based on the sub-platform)?
-*/
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \
- !defined(SQLITE_WIN32_NO_WIDE)
-# define SQLITE_WIN32_HAS_WIDE
-#endif
-
-/*
-** Make sure at least one set of Win32 APIs is available.
-*/
-#if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE)
-# error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\
- must be defined."
-#endif
-
-/*
-** Define the required Windows SDK version constants if they are not
-** already available.
-*/
-#ifndef NTDDI_WIN8
-# define NTDDI_WIN8 0x06020000
-#endif
-
-#ifndef NTDDI_WINBLUE
-# define NTDDI_WINBLUE 0x06030000
-#endif
-
-#ifndef NTDDI_WINTHRESHOLD
-# define NTDDI_WINTHRESHOLD 0x06040000
-#endif
-
-/*
-** Check to see if the GetVersionEx[AW] functions are deprecated on the
-** target system. GetVersionEx was first deprecated in Win8.1.
-*/
-#ifndef SQLITE_WIN32_GETVERSIONEX
-# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
-# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */
-# else
-# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */
-# endif
-#endif
-
-/*
-** Check to see if the CreateFileMappingA function is supported on the
-** target system. It is unavailable when using "mincore.lib" on Win10.
-** When compiling for Windows 10, always assume "mincore.lib" is in use.
-*/
-#ifndef SQLITE_WIN32_CREATEFILEMAPPINGA
-# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINTHRESHOLD
-# define SQLITE_WIN32_CREATEFILEMAPPINGA 0
-# else
-# define SQLITE_WIN32_CREATEFILEMAPPINGA 1
-# endif
-#endif
-
-/*
-** This constant should already be defined (in the "WinDef.h" SDK file).
-*/
-#ifndef MAX_PATH
-# define MAX_PATH (260)
-#endif
-
-/*
-** Maximum pathname length (in chars) for Win32. This should normally be
-** MAX_PATH.
-*/
-#ifndef SQLITE_WIN32_MAX_PATH_CHARS
-# define SQLITE_WIN32_MAX_PATH_CHARS (MAX_PATH)
-#endif
-
-/*
-** This constant should already be defined (in the "WinNT.h" SDK file).
-*/
-#ifndef UNICODE_STRING_MAX_CHARS
-# define UNICODE_STRING_MAX_CHARS (32767)
-#endif
-
-/*
-** Maximum pathname length (in chars) for WinNT. This should normally be
-** UNICODE_STRING_MAX_CHARS.
-*/
-#ifndef SQLITE_WINNT_MAX_PATH_CHARS
-# define SQLITE_WINNT_MAX_PATH_CHARS (UNICODE_STRING_MAX_CHARS)
-#endif
-
-/*
-** Maximum pathname length (in bytes) for Win32. The MAX_PATH macro is in
-** characters, so we allocate 4 bytes per character assuming worst-case of
-** 4-bytes-per-character for UTF8.
-*/
-#ifndef SQLITE_WIN32_MAX_PATH_BYTES
-# define SQLITE_WIN32_MAX_PATH_BYTES (SQLITE_WIN32_MAX_PATH_CHARS*4)
-#endif
-
-/*
-** Maximum pathname length (in bytes) for WinNT. This should normally be
-** UNICODE_STRING_MAX_CHARS * sizeof(WCHAR).
-*/
-#ifndef SQLITE_WINNT_MAX_PATH_BYTES
-# define SQLITE_WINNT_MAX_PATH_BYTES \
- (sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS)
-#endif
-
-/*
-** Maximum error message length (in chars) for WinRT.
-*/
-#ifndef SQLITE_WIN32_MAX_ERRMSG_CHARS
-# define SQLITE_WIN32_MAX_ERRMSG_CHARS (1024)
-#endif
-
-/*
-** Returns non-zero if the character should be treated as a directory
-** separator.
-*/
-#ifndef winIsDirSep
-# define winIsDirSep(a) (((a) == '/') || ((a) == '\\'))
-#endif
-
-/*
-** This macro is used when a local variable is set to a value that is
-** [sometimes] not used by the code (e.g. via conditional compilation).
-*/
-#ifndef UNUSED_VARIABLE_VALUE
-# define UNUSED_VARIABLE_VALUE(x) (void)(x)
-#endif
-
-/*
-** Returns the character that should be used as the directory separator.
-*/
-#ifndef winGetDirSep
-# define winGetDirSep() '\\'
-#endif
-
-/*
-** Do we need to manually define the Win32 file mapping APIs for use with WAL
-** mode or memory mapped files (e.g. these APIs are available in the Windows
-** CE SDK; however, they are not present in the header file)?
-*/
-#if SQLITE_WIN32_FILEMAPPING_API && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
-/*
-** Two of the file mapping APIs are different under WinRT. Figure out which
-** set we need.
-*/
-#if SQLITE_OS_WINRT
-WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
- LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
-
-WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
-#else
-#if defined(SQLITE_WIN32_HAS_ANSI)
-WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
- DWORD, DWORD, DWORD, LPCSTR);
-#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
-WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
- DWORD, DWORD, DWORD, LPCWSTR);
-#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
-
-WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
-#endif /* SQLITE_OS_WINRT */
-
-/*
-** These file mapping APIs are common to both Win32 and WinRT.
-*/
-
-WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T);
-WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
-#endif /* SQLITE_WIN32_FILEMAPPING_API */
-
-/*
-** Some Microsoft compilers lack this definition.
-*/
-#ifndef INVALID_FILE_ATTRIBUTES
-# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
-#endif
-
-#ifndef FILE_FLAG_MASK
-# define FILE_FLAG_MASK (0xFF3C0000)
-#endif
-
-#ifndef FILE_ATTRIBUTE_MASK
-# define FILE_ATTRIBUTE_MASK (0x0003FFF7)
-#endif
-
-#ifndef SQLITE_OMIT_WAL
-/* Forward references to structures used for WAL */
-typedef struct winShm winShm; /* A connection to shared-memory */
-typedef struct winShmNode winShmNode; /* A region of shared-memory */
-#endif
-
-/*
-** WinCE lacks native support for file locking so we have to fake it
-** with some code of our own.
-*/
-#if SQLITE_OS_WINCE
-typedef struct winceLock {
- int nReaders; /* Number of reader locks obtained */
- BOOL bPending; /* Indicates a pending lock has been obtained */
- BOOL bReserved; /* Indicates a reserved lock has been obtained */
- BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
-} winceLock;
-#endif
-
-/*
-** The winFile structure is a subclass of sqlite3_file* specific to the win32
-** portability layer.
-*/
-typedef struct winFile winFile;
-struct winFile {
- const sqlite3_io_methods *pMethod; /*** Must be first ***/
- sqlite3_vfs *pVfs; /* The VFS used to open this file */
- HANDLE h; /* Handle for accessing the file */
- u8 locktype; /* Type of lock currently held on this file */
- short sharedLockByte; /* Randomly chosen byte used as a shared lock */
- u8 ctrlFlags; /* Flags. See WINFILE_* below */
- DWORD lastErrno; /* The Windows errno from the last I/O error */
-#ifndef SQLITE_OMIT_WAL
- winShm *pShm; /* Instance of shared memory on this file */
-#endif
- const char *zPath; /* Full pathname of this file */
- int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
-#if SQLITE_OS_WINCE
- LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
- HANDLE hMutex; /* Mutex used to control access to shared lock */
- HANDLE hShared; /* Shared memory segment used for locking */
- winceLock local; /* Locks obtained by this instance of winFile */
- winceLock *shared; /* Global shared lock memory for the file */
-#endif
-#if SQLITE_MAX_MMAP_SIZE>0
- int nFetchOut; /* Number of outstanding xFetch references */
- HANDLE hMap; /* Handle for accessing memory mapping */
- void *pMapRegion; /* Area memory mapped */
- sqlite3_int64 mmapSize; /* Usable size of mapped region */
- sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
- sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
-#endif
-};
-
-/*
-** The winVfsAppData structure is used for the pAppData member for all of the
-** Win32 VFS variants.
-*/
-typedef struct winVfsAppData winVfsAppData;
-struct winVfsAppData {
- const sqlite3_io_methods *pMethod; /* The file I/O methods to use. */
- void *pAppData; /* The extra pAppData, if any. */
- BOOL bNoLock; /* Non-zero if locking is disabled. */
-};
-
-/*
-** Allowed values for winFile.ctrlFlags
-*/
-#define WINFILE_RDONLY 0x02 /* Connection is read only */
-#define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
-#define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
-
-/*
- * The size of the buffer used by sqlite3_win32_write_debug().
- */
-#ifndef SQLITE_WIN32_DBG_BUF_SIZE
-# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD)))
-#endif
-
-/*
- * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
- * various Win32 API heap functions instead of our own.
- */
-#ifdef SQLITE_WIN32_MALLOC
-
-/*
- * If this is non-zero, an isolated heap will be created by the native Win32
- * allocator subsystem; otherwise, the default process heap will be used. This
- * setting has no effect when compiling for WinRT. By default, this is enabled
- * and an isolated heap will be created to store all allocated data.
- *
- ******************************************************************************
- * WARNING: It is important to note that when this setting is non-zero and the
- * winMemShutdown function is called (e.g. by the sqlite3_shutdown
- * function), all data that was allocated using the isolated heap will
- * be freed immediately and any attempt to access any of that freed
- * data will almost certainly result in an immediate access violation.
- ******************************************************************************
- */
-#ifndef SQLITE_WIN32_HEAP_CREATE
-# define SQLITE_WIN32_HEAP_CREATE (TRUE)
-#endif
-
-/*
- * This is the maximum possible initial size of the Win32-specific heap, in
- * bytes.
- */
-#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE
-# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U)
-#endif
-
-/*
- * This is the extra space for the initial size of the Win32-specific heap,
- * in bytes. This value may be zero.
- */
-#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA
-# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304)
-#endif
-
-/*
- * Calculate the maximum legal cache size, in pages, based on the maximum
- * possible initial heap size and the default page size, setting aside the
- * needed extra space.
- */
-#ifndef SQLITE_WIN32_MAX_CACHE_SIZE
-# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \
- (SQLITE_WIN32_HEAP_INIT_EXTRA)) / \
- (SQLITE_DEFAULT_PAGE_SIZE))
-#endif
-
-/*
- * This is cache size used in the calculation of the initial size of the
- * Win32-specific heap. It cannot be negative.
- */
-#ifndef SQLITE_WIN32_CACHE_SIZE
-# if SQLITE_DEFAULT_CACHE_SIZE>=0
-# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
-# else
-# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
-# endif
-#endif
-
-/*
- * Make sure that the calculated cache size, in pages, cannot cause the
- * initial size of the Win32-specific heap to exceed the maximum amount
- * of memory that can be specified in the call to HeapCreate.
- */
-#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE
-# undef SQLITE_WIN32_CACHE_SIZE
-# define SQLITE_WIN32_CACHE_SIZE (2000)
-#endif
-
-/*
- * The initial size of the Win32-specific heap. This value may be zero.
- */
-#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
-# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
- (SQLITE_DEFAULT_PAGE_SIZE) + \
- (SQLITE_WIN32_HEAP_INIT_EXTRA))
-#endif
-
-/*
- * The maximum size of the Win32-specific heap. This value may be zero.
- */
-#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
-# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
-#endif
-
-/*
- * The extra flags to use in calls to the Win32 heap APIs. This value may be
- * zero for the default behavior.
- */
-#ifndef SQLITE_WIN32_HEAP_FLAGS
-# define SQLITE_WIN32_HEAP_FLAGS (0)
-#endif
-
-
-/*
-** The winMemData structure stores information required by the Win32-specific
-** sqlite3_mem_methods implementation.
-*/
-typedef struct winMemData winMemData;
-struct winMemData {
-#ifndef NDEBUG
- u32 magic1; /* Magic number to detect structure corruption. */
-#endif
- HANDLE hHeap; /* The handle to our heap. */
- BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
-#ifndef NDEBUG
- u32 magic2; /* Magic number to detect structure corruption. */
-#endif
-};
-
-#ifndef NDEBUG
-#define WINMEM_MAGIC1 0x42b2830b
-#define WINMEM_MAGIC2 0xbd4d7cf4
-#endif
-
-static struct winMemData win_mem_data = {
-#ifndef NDEBUG
- WINMEM_MAGIC1,
-#endif
- NULL, FALSE
-#ifndef NDEBUG
- ,WINMEM_MAGIC2
-#endif
-};
-
-#ifndef NDEBUG
-#define winMemAssertMagic1() assert( win_mem_data.magic1==WINMEM_MAGIC1 )
-#define winMemAssertMagic2() assert( win_mem_data.magic2==WINMEM_MAGIC2 )
-#define winMemAssertMagic() winMemAssertMagic1(); winMemAssertMagic2();
-#else
-#define winMemAssertMagic()
-#endif
-
-#define winMemGetDataPtr() &win_mem_data
-#define winMemGetHeap() win_mem_data.hHeap
-#define winMemGetOwned() win_mem_data.bOwned
-
-static void *winMemMalloc(int nBytes);
-static void winMemFree(void *pPrior);
-static void *winMemRealloc(void *pPrior, int nBytes);
-static int winMemSize(void *p);
-static int winMemRoundup(int n);
-static int winMemInit(void *pAppData);
-static void winMemShutdown(void *pAppData);
-
-const sqlite3_mem_methods *sqlite3MemGetWin32(void);
-#endif /* SQLITE_WIN32_MALLOC */
-
-/*
-** The following variable is (normally) set once and never changes
-** thereafter. It records whether the operating system is Win9x
-** or WinNT.
-**
-** 0: Operating system unknown.
-** 1: Operating system is Win9x.
-** 2: Operating system is WinNT.
-**
-** In order to facilitate testing on a WinNT system, the test fixture
-** can manually set this value to 1 to emulate Win98 behavior.
-*/
-#ifdef SQLITE_TEST
-LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
-#else
-static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
-#endif
-
-#ifndef SYSCALL
-# define SYSCALL sqlite3_syscall_ptr
-#endif
-
-/*
-** This function is not available on Windows CE or WinRT.
- */
-
-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
-# define osAreFileApisANSI() 1
-#endif
-
-/*
-** Many system calls are accessed through pointer-to-functions so that
-** they may be overridden at runtime to facilitate fault injection during
-** testing and sandboxing. The following array holds the names and pointers
-** to all overrideable system calls.
-*/
-static struct win_syscall {
- const char *zName; /* Name of the system call */
- sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
- sqlite3_syscall_ptr pDefault; /* Default value */
-} aSyscall[] = {
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
-#else
- { "AreFileApisANSI", (SYSCALL)0, 0 },
-#endif
-
-#ifndef osAreFileApisANSI
-#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
-#endif
-
-#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
- { "CharLowerW", (SYSCALL)CharLowerW, 0 },
-#else
- { "CharLowerW", (SYSCALL)0, 0 },
-#endif
-
-#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
-
-#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
- { "CharUpperW", (SYSCALL)CharUpperW, 0 },
-#else
- { "CharUpperW", (SYSCALL)0, 0 },
-#endif
-
-#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
-
- { "CloseHandle", (SYSCALL)CloseHandle, 0 },
-
-#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "CreateFileA", (SYSCALL)CreateFileA, 0 },
-#else
- { "CreateFileA", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
- LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "CreateFileW", (SYSCALL)CreateFileW, 0 },
-#else
- { "CreateFileW", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
- LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \
- SQLITE_WIN32_CREATEFILEMAPPINGA
- { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
-#else
- { "CreateFileMappingA", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
- DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
-
-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
- { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
-#else
- { "CreateFileMappingW", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
- DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
-#else
- { "CreateMutexW", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
- LPCWSTR))aSyscall[8].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "DeleteFileA", (SYSCALL)DeleteFileA, 0 },
-#else
- { "DeleteFileA", (SYSCALL)0, 0 },
-#endif
-
-#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
- { "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
-#else
- { "DeleteFileW", (SYSCALL)0, 0 },
-#endif
-
-#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
-
-#if SQLITE_OS_WINCE
- { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
-#else
- { "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
-#endif
-
-#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
- LPFILETIME))aSyscall[11].pCurrent)
-
-#if SQLITE_OS_WINCE
- { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 },
-#else
- { "FileTimeToSystemTime", (SYSCALL)0, 0 },
-#endif
-
-#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
- LPSYSTEMTIME))aSyscall[12].pCurrent)
-
- { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
-
-#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "FormatMessageA", (SYSCALL)FormatMessageA, 0 },
-#else
- { "FormatMessageA", (SYSCALL)0, 0 },
-#endif
-
-#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
- DWORD,va_list*))aSyscall[14].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
- { "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
-#else
- { "FormatMessageW", (SYSCALL)0, 0 },
-#endif
-
-#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
- DWORD,va_list*))aSyscall[15].pCurrent)
-
-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
- { "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
-#else
- { "FreeLibrary", (SYSCALL)0, 0 },
-#endif
-
-#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
-
- { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
-
-#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
-
-#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
- { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 },
-#else
- { "GetDiskFreeSpaceA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
- LPDWORD))aSyscall[18].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
-#else
- { "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
- LPDWORD))aSyscall[19].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 },
-#else
- { "GetFileAttributesA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
-#else
- { "GetFileAttributesW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
- { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
-#else
- { "GetFileAttributesExW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
- LPVOID))aSyscall[22].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "GetFileSize", (SYSCALL)GetFileSize, 0 },
-#else
- { "GetFileSize", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
-
-#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
- { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
-#else
- { "GetFullPathNameA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
- LPSTR*))aSyscall[24].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
-#else
- { "GetFullPathNameW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
- LPWSTR*))aSyscall[25].pCurrent)
-
- { "GetLastError", (SYSCALL)GetLastError, 0 },
-
-#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
-
-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
-#if SQLITE_OS_WINCE
- /* The GetProcAddressA() routine is only available on Windows CE. */
- { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
-#else
- /* All other Windows platforms expect GetProcAddress() to take
- ** an ANSI string regardless of the _UNICODE setting */
- { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
-#endif
-#else
- { "GetProcAddressA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
- LPCSTR))aSyscall[27].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
-#else
- { "GetSystemInfo", (SYSCALL)0, 0 },
-#endif
-
-#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
-
- { "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
-
-#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
-
-#if !SQLITE_OS_WINCE
- { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
-#else
- { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 },
-#endif
-
-#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
- LPFILETIME))aSyscall[30].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "GetTempPathA", (SYSCALL)GetTempPathA, 0 },
-#else
- { "GetTempPathA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
-#else
- { "GetTempPathW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "GetTickCount", (SYSCALL)GetTickCount, 0 },
-#else
- { "GetTickCount", (SYSCALL)0, 0 },
-#endif
-
-#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_GETVERSIONEX
- { "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
-#else
- { "GetVersionExA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetVersionExA ((BOOL(WINAPI*)( \
- LPOSVERSIONINFOA))aSyscall[34].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
- SQLITE_WIN32_GETVERSIONEX
- { "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
-#else
- { "GetVersionExW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetVersionExW ((BOOL(WINAPI*)( \
- LPOSVERSIONINFOW))aSyscall[35].pCurrent)
-
- { "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
-
-#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
- SIZE_T))aSyscall[36].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "HeapCreate", (SYSCALL)HeapCreate, 0 },
-#else
- { "HeapCreate", (SYSCALL)0, 0 },
-#endif
-
-#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
- SIZE_T))aSyscall[37].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
-#else
- { "HeapDestroy", (SYSCALL)0, 0 },
-#endif
-
-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent)
-
- { "HeapFree", (SYSCALL)HeapFree, 0 },
-
-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent)
-
- { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
-
-#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
- SIZE_T))aSyscall[40].pCurrent)
-
- { "HeapSize", (SYSCALL)HeapSize, 0 },
-
-#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
- LPCVOID))aSyscall[41].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "HeapValidate", (SYSCALL)HeapValidate, 0 },
-#else
- { "HeapValidate", (SYSCALL)0, 0 },
-#endif
-
-#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
- LPCVOID))aSyscall[42].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- { "HeapCompact", (SYSCALL)HeapCompact, 0 },
-#else
- { "HeapCompact", (SYSCALL)0, 0 },
-#endif
-
-#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[43].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
- { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
-#else
- { "LoadLibraryA", (SYSCALL)0, 0 },
-#endif
-
-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
- !defined(SQLITE_OMIT_LOAD_EXTENSION)
- { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
-#else
- { "LoadLibraryW", (SYSCALL)0, 0 },
-#endif
-
-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "LocalFree", (SYSCALL)LocalFree, 0 },
-#else
- { "LocalFree", (SYSCALL)0, 0 },
-#endif
-
-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- { "LockFile", (SYSCALL)LockFile, 0 },
-#else
- { "LockFile", (SYSCALL)0, 0 },
-#endif
-
-#ifndef osLockFile
-#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- DWORD))aSyscall[47].pCurrent)
-#endif
-
-#if !SQLITE_OS_WINCE
- { "LockFileEx", (SYSCALL)LockFileEx, 0 },
-#else
- { "LockFileEx", (SYSCALL)0, 0 },
-#endif
-
-#ifndef osLockFileEx
-#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
- LPOVERLAPPED))aSyscall[48].pCurrent)
-#endif
-
-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
- { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
-#else
- { "MapViewOfFile", (SYSCALL)0, 0 },
-#endif
-
-#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- SIZE_T))aSyscall[49].pCurrent)
-
- { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
-
-#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
- int))aSyscall[50].pCurrent)
-
- { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
-
-#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
- LARGE_INTEGER*))aSyscall[51].pCurrent)
-
- { "ReadFile", (SYSCALL)ReadFile, 0 },
-
-#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
- LPOVERLAPPED))aSyscall[52].pCurrent)
-
- { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
-
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
-#else
- { "SetFilePointer", (SYSCALL)0, 0 },
-#endif
-
-#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
- DWORD))aSyscall[54].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "Sleep", (SYSCALL)Sleep, 0 },
-#else
- { "Sleep", (SYSCALL)0, 0 },
-#endif
-
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent)
-
- { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
-
-#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
- LPFILETIME))aSyscall[56].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- { "UnlockFile", (SYSCALL)UnlockFile, 0 },
-#else
- { "UnlockFile", (SYSCALL)0, 0 },
-#endif
-
-#ifndef osUnlockFile
-#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- DWORD))aSyscall[57].pCurrent)
-#endif
-
-#if !SQLITE_OS_WINCE
- { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 },
-#else
- { "UnlockFileEx", (SYSCALL)0, 0 },
-#endif
-
-#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- LPOVERLAPPED))aSyscall[58].pCurrent)
-
-#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
- { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
-#else
- { "UnmapViewOfFile", (SYSCALL)0, 0 },
-#endif
-
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent)
-
- { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
-
-#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
- LPCSTR,LPBOOL))aSyscall[60].pCurrent)
-
- { "WriteFile", (SYSCALL)WriteFile, 0 },
-
-#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
- LPOVERLAPPED))aSyscall[61].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
-#else
- { "CreateEventExW", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
- DWORD,DWORD))aSyscall[62].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
-#else
- { "WaitForSingleObject", (SYSCALL)0, 0 },
-#endif
-
-#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
- DWORD))aSyscall[63].pCurrent)
-
-#if !SQLITE_OS_WINCE
- { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
-#else
- { "WaitForSingleObjectEx", (SYSCALL)0, 0 },
-#endif
-
-#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
- BOOL))aSyscall[64].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
-#else
- { "SetFilePointerEx", (SYSCALL)0, 0 },
-#endif
-
-#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
- PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
-#else
- { "GetFileInformationByHandleEx", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
- FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
-
-#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
- { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
-#else
- { "MapViewOfFileFromApp", (SYSCALL)0, 0 },
-#endif
-
-#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
- SIZE_T))aSyscall[67].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "CreateFile2", (SYSCALL)CreateFile2, 0 },
-#else
- { "CreateFile2", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
- LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent)
-
-#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
- { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
-#else
- { "LoadPackagedLibrary", (SYSCALL)0, 0 },
-#endif
-
-#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
- DWORD))aSyscall[69].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
-#else
- { "GetTickCount64", (SYSCALL)0, 0 },
-#endif
-
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
-#else
- { "GetNativeSystemInfo", (SYSCALL)0, 0 },
-#endif
-
-#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
- LPSYSTEM_INFO))aSyscall[71].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
-#else
- { "OutputDebugStringA", (SYSCALL)0, 0 },
-#endif
-
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
- { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
-#else
- { "OutputDebugStringW", (SYSCALL)0, 0 },
-#endif
-
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent)
-
- { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
-
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
-
-#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
- { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
-#else
- { "CreateFileMappingFromApp", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
- LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
-
-/*
-** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
-** is really just a macro that uses a compiler intrinsic (e.g. x64).
-** So do not try to make this is into a redefinable interface.
-*/
-#if defined(InterlockedCompareExchange)
- { "InterlockedCompareExchange", (SYSCALL)0, 0 },
-
-#define osInterlockedCompareExchange InterlockedCompareExchange
-#else
- { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
-
-#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
- SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
-#endif /* defined(InterlockedCompareExchange) */
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
- { "UuidCreate", (SYSCALL)UuidCreate, 0 },
-#else
- { "UuidCreate", (SYSCALL)0, 0 },
-#endif
-
-#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
- { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
-#else
- { "UuidCreateSequential", (SYSCALL)0, 0 },
-#endif
-
-#define osUuidCreateSequential \
- ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
-
-#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
- { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
-#else
- { "FlushViewOfFile", (SYSCALL)0, 0 },
-#endif
-
-#define osFlushViewOfFile \
- ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
-
-}; /* End of the overrideable system calls */
-
-/*
-** This is the xSetSystemCall() method of sqlite3_vfs for all of the
-** "win32" VFSes. Return SQLITE_OK opon successfully updating the
-** system call pointer, or SQLITE_NOTFOUND if there is no configurable
-** system call named zName.
-*/
-static int winSetSystemCall(
- sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
- const char *zName, /* Name of system call to override */
- sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
-){
- unsigned int i;
- int rc = SQLITE_NOTFOUND;
-
- UNUSED_PARAMETER(pNotUsed);
- if( zName==0 ){
- /* If no zName is given, restore all system calls to their default
- ** settings and return NULL
- */
- rc = SQLITE_OK;
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( aSyscall[i].pDefault ){
- aSyscall[i].pCurrent = aSyscall[i].pDefault;
- }
- }
- }else{
- /* If zName is specified, operate on only the one system call
- ** specified.
- */
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ){
- if( aSyscall[i].pDefault==0 ){
- aSyscall[i].pDefault = aSyscall[i].pCurrent;
- }
- rc = SQLITE_OK;
- if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
- aSyscall[i].pCurrent = pNewFunc;
- break;
- }
- }
- }
- return rc;
-}
-
-/*
-** Return the value of a system call. Return NULL if zName is not a
-** recognized system call name. NULL is also returned if the system call
-** is currently undefined.
-*/
-static sqlite3_syscall_ptr winGetSystemCall(
- sqlite3_vfs *pNotUsed,
- const char *zName
-){
- unsigned int i;
-
- UNUSED_PARAMETER(pNotUsed);
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
- }
- return 0;
-}
-
-/*
-** Return the name of the first system call after zName. If zName==NULL
-** then return the name of the first system call. Return NULL if zName
-** is the last system call or if zName is not the name of a valid
-** system call.
-*/
-static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
- int i = -1;
-
- UNUSED_PARAMETER(p);
- if( zName ){
- for(i=0; i<ArraySize(aSyscall)-1; i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ) break;
- }
- }
- for(i++; i<ArraySize(aSyscall); i++){
- if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
- }
- return 0;
-}
-
-#ifdef SQLITE_WIN32_MALLOC
-/*
-** If a Win32 native heap has been configured, this function will attempt to
-** compact it. Upon success, SQLITE_OK will be returned. Upon failure, one
-** of SQLITE_NOMEM, SQLITE_ERROR, or SQLITE_NOTFOUND will be returned. The
-** "pnLargest" argument, if non-zero, will be used to return the size of the
-** largest committed free block in the heap, in bytes.
-*/
-int sqlite3_win32_compact_heap(LPUINT pnLargest){
- int rc = SQLITE_OK;
- UINT nLargest = 0;
- HANDLE hHeap;
-
- winMemAssertMagic();
- hHeap = winMemGetHeap();
- assert( hHeap!=0 );
- assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-#endif
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){
- DWORD lastErrno = osGetLastError();
- if( lastErrno==NO_ERROR ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapCompact (no space), heap=%p",
- (void*)hHeap);
- rc = SQLITE_NOMEM_BKPT;
- }else{
- sqlite3_log(SQLITE_ERROR, "failed to HeapCompact (%lu), heap=%p",
- osGetLastError(), (void*)hHeap);
- rc = SQLITE_ERROR;
- }
- }
-#else
- sqlite3_log(SQLITE_NOTFOUND, "failed to HeapCompact, heap=%p",
- (void*)hHeap);
- rc = SQLITE_NOTFOUND;
-#endif
- if( pnLargest ) *pnLargest = nLargest;
- return rc;
-}
-
-/*
-** If a Win32 native heap has been configured, this function will attempt to
-** destroy and recreate it. If the Win32 native heap is not isolated and/or
-** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will
-** be returned and no changes will be made to the Win32 native heap.
-*/
-int sqlite3_win32_reset_heap(){
- int rc;
- MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
- MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
- MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
- MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
- sqlite3_mutex_enter(pMaster);
- sqlite3_mutex_enter(pMem);
- winMemAssertMagic();
- if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
- /*
- ** At this point, there should be no outstanding memory allocations on
- ** the heap. Also, since both the master and memsys locks are currently
- ** being held by us, no other function (i.e. from another thread) should
- ** be able to even access the heap. Attempt to destroy and recreate our
- ** isolated Win32 native heap now.
- */
- assert( winMemGetHeap()!=NULL );
- assert( winMemGetOwned() );
- assert( sqlite3_memory_used()==0 );
- winMemShutdown(winMemGetDataPtr());
- assert( winMemGetHeap()==NULL );
- assert( !winMemGetOwned() );
- assert( sqlite3_memory_used()==0 );
- rc = winMemInit(winMemGetDataPtr());
- assert( rc!=SQLITE_OK || winMemGetHeap()!=NULL );
- assert( rc!=SQLITE_OK || winMemGetOwned() );
- assert( rc!=SQLITE_OK || sqlite3_memory_used()==0 );
- }else{
- /*
- ** The Win32 native heap cannot be modified because it may be in use.
- */
- rc = SQLITE_BUSY;
- }
- sqlite3_mutex_leave(pMem);
- sqlite3_mutex_leave(pMaster);
- return rc;
-}
-#endif /* SQLITE_WIN32_MALLOC */
-
-/*
-** This function outputs the specified (ANSI) string to the Win32 debugger
-** (if available).
-*/
-
-void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
- char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
- int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
- if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
- assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !zBuf ){
- (void)SQLITE_MISUSE_BKPT;
- return;
- }
-#endif
-#if defined(SQLITE_WIN32_HAS_ANSI)
- if( nMin>0 ){
- memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
- memcpy(zDbgBuf, zBuf, nMin);
- osOutputDebugStringA(zDbgBuf);
- }else{
- osOutputDebugStringA(zBuf);
- }
-#elif defined(SQLITE_WIN32_HAS_WIDE)
- memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
- if ( osMultiByteToWideChar(
- osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,
- nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){
- return;
- }
- osOutputDebugStringW((LPCWSTR)zDbgBuf);
-#else
- if( nMin>0 ){
- memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
- memcpy(zDbgBuf, zBuf, nMin);
- fprintf(stderr, "%s", zDbgBuf);
- }else{
- fprintf(stderr, "%s", zBuf);
- }
-#endif
-}
-
-/*
-** The following routine suspends the current thread for at least ms
-** milliseconds. This is equivalent to the Win32 Sleep() interface.
-*/
-#if SQLITE_OS_WINRT
-static HANDLE sleepObj = NULL;
-#endif
-
-void sqlite3_win32_sleep(DWORD milliseconds){
-#if SQLITE_OS_WINRT
- if ( sleepObj==NULL ){
- sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
- SYNCHRONIZE);
- }
- assert( sleepObj!=NULL );
- osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
-#else
- osSleep(milliseconds);
-#endif
-}
-
-#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
- SQLITE_THREADSAFE>0
-DWORD sqlite3Win32Wait(HANDLE hObject){
- DWORD rc;
- while( (rc = osWaitForSingleObjectEx(hObject, INFINITE,
- TRUE))==WAIT_IO_COMPLETION ){}
- return rc;
-}
-#endif
-
-/*
-** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
-** or WinCE. Return false (zero) for Win95, Win98, or WinME.
-**
-** Here is an interesting observation: Win95, Win98, and WinME lack
-** the LockFileEx() API. But we can still statically link against that
-** API as long as we don't call it when running Win95/98/ME. A call to
-** this routine is used to determine if the host is Win95/98/ME or
-** WinNT/2K/XP so that we will know whether or not we can safely call
-** the LockFileEx() API.
-*/
-
-#if !SQLITE_WIN32_GETVERSIONEX
-# define osIsNT() (1)
-#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
-# define osIsNT() (1)
-#elif !defined(SQLITE_WIN32_HAS_WIDE)
-# define osIsNT() (0)
-#else
-# define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
-#endif
-
-/*
-** This function determines if the machine is running a version of Windows
-** based on the NT kernel.
-*/
-int sqlite3_win32_is_nt(void){
-#if SQLITE_OS_WINRT
- /*
- ** NOTE: The WinRT sub-platform is always assumed to be based on the NT
- ** kernel.
- */
- return 1;
-#elif SQLITE_WIN32_GETVERSIONEX
- if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
-#if defined(SQLITE_WIN32_HAS_ANSI)
- OSVERSIONINFOA sInfo;
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
- osGetVersionExA(&sInfo);
- osInterlockedCompareExchange(&sqlite3_os_type,
- (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
-#elif defined(SQLITE_WIN32_HAS_WIDE)
- OSVERSIONINFOW sInfo;
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
- osGetVersionExW(&sInfo);
- osInterlockedCompareExchange(&sqlite3_os_type,
- (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
-#endif
- }
- return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
-#elif SQLITE_TEST
- return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
-#else
- /*
- ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
- ** deprecated are always assumed to be based on the NT kernel.
- */
- return 1;
-#endif
-}
-
-#ifdef SQLITE_WIN32_MALLOC
-/*
-** Allocate nBytes of memory.
-*/
-static void *winMemMalloc(int nBytes){
- HANDLE hHeap;
- void *p;
-
- winMemAssertMagic();
- hHeap = winMemGetHeap();
- assert( hHeap!=0 );
- assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-#endif
- assert( nBytes>=0 );
- p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
- if( !p ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p",
- nBytes, osGetLastError(), (void*)hHeap);
- }
- return p;
-}
-
-/*
-** Free memory.
-*/
-static void winMemFree(void *pPrior){
- HANDLE hHeap;
-
- winMemAssertMagic();
- hHeap = winMemGetHeap();
- assert( hHeap!=0 );
- assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
-#endif
- if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
- if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p",
- pPrior, osGetLastError(), (void*)hHeap);
- }
-}
-
-/*
-** Change the size of an existing memory allocation
-*/
-static void *winMemRealloc(void *pPrior, int nBytes){
- HANDLE hHeap;
- void *p;
-
- winMemAssertMagic();
- hHeap = winMemGetHeap();
- assert( hHeap!=0 );
- assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
-#endif
- assert( nBytes>=0 );
- if( !pPrior ){
- p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
- }else{
- p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
- }
- if( !p ){
- sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p",
- pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
- (void*)hHeap);
- }
- return p;
-}
-
-/*
-** Return the size of an outstanding allocation, in bytes.
-*/
-static int winMemSize(void *p){
- HANDLE hHeap;
- SIZE_T n;
-
- winMemAssertMagic();
- hHeap = winMemGetHeap();
- assert( hHeap!=0 );
- assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) );
-#endif
- if( !p ) return 0;
- n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
- if( n==(SIZE_T)-1 ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p",
- p, osGetLastError(), (void*)hHeap);
- return 0;
- }
- return (int)n;
-}
-
-/*
-** Round up a request size to the next valid allocation size.
-*/
-static int winMemRoundup(int n){
- return n;
-}
-
-/*
-** Initialize this module.
-*/
-static int winMemInit(void *pAppData){
- winMemData *pWinMemData = (winMemData *)pAppData;
-
- if( !pWinMemData ) return SQLITE_ERROR;
- assert( pWinMemData->magic1==WINMEM_MAGIC1 );
- assert( pWinMemData->magic2==WINMEM_MAGIC2 );
-
-#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
- if( !pWinMemData->hHeap ){
- DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE;
- DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap;
- if( dwMaximumSize==0 ){
- dwMaximumSize = SQLITE_WIN32_HEAP_MAX_SIZE;
- }else if( dwInitialSize>dwMaximumSize ){
- dwInitialSize = dwMaximumSize;
- }
- pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
- dwInitialSize, dwMaximumSize);
- if( !pWinMemData->hHeap ){
- sqlite3_log(SQLITE_NOMEM,
- "failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu",
- osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize,
- dwMaximumSize);
- return SQLITE_NOMEM_BKPT;
- }
- pWinMemData->bOwned = TRUE;
- assert( pWinMemData->bOwned );
- }
-#else
- pWinMemData->hHeap = osGetProcessHeap();
- if( !pWinMemData->hHeap ){
- sqlite3_log(SQLITE_NOMEM,
- "failed to GetProcessHeap (%lu)", osGetLastError());
- return SQLITE_NOMEM_BKPT;
- }
- pWinMemData->bOwned = FALSE;
- assert( !pWinMemData->bOwned );
-#endif
- assert( pWinMemData->hHeap!=0 );
- assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-#endif
- return SQLITE_OK;
-}
-
-/*
-** Deinitialize this module.
-*/
-static void winMemShutdown(void *pAppData){
- winMemData *pWinMemData = (winMemData *)pAppData;
-
- if( !pWinMemData ) return;
- assert( pWinMemData->magic1==WINMEM_MAGIC1 );
- assert( pWinMemData->magic2==WINMEM_MAGIC2 );
-
- if( pWinMemData->hHeap ){
- assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-#endif
- if( pWinMemData->bOwned ){
- if( !osHeapDestroy(pWinMemData->hHeap) ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p",
- osGetLastError(), (void*)pWinMemData->hHeap);
- }
- pWinMemData->bOwned = FALSE;
- }
- pWinMemData->hHeap = NULL;
- }
-}
-
-/*
-** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file. The
-** arguments specify the block of memory to manage.
-**
-** This routine is only called by sqlite3_config(), and therefore
-** is not required to be threadsafe (it is not).
-*/
-const sqlite3_mem_methods *sqlite3MemGetWin32(void){
- static const sqlite3_mem_methods winMemMethods = {
- winMemMalloc,
- winMemFree,
- winMemRealloc,
- winMemSize,
- winMemRoundup,
- winMemInit,
- winMemShutdown,
- &win_mem_data
- };
- return &winMemMethods;
-}
-
-void sqlite3MemSetDefault(void){
- sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
-}
-#endif /* SQLITE_WIN32_MALLOC */
-
-/*
-** Convert a UTF-8 string to Microsoft Unicode.
-**
-** Space to hold the returned string is obtained from sqlite3_malloc().
-*/
-static LPWSTR winUtf8ToUnicode(const char *zText){
- int nChar;
- LPWSTR zWideText;
-
- nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
- if( nChar==0 ){
- return 0;
- }
- zWideText = sqlite3MallocZero( nChar*sizeof(WCHAR) );
- if( zWideText==0 ){
- return 0;
- }
- nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText,
- nChar);
- if( nChar==0 ){
- sqlite3_free(zWideText);
- zWideText = 0;
- }
- return zWideText;
-}
-
-/*
-** Convert a Microsoft Unicode string to UTF-8.
-**
-** Space to hold the returned string is obtained from sqlite3_malloc().
-*/
-static char *winUnicodeToUtf8(LPCWSTR zWideText){
- int nByte;
- char *zText;
-
- nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
- if( nByte == 0 ){
- return 0;
- }
- zText = sqlite3MallocZero( nByte );
- if( zText==0 ){
- return 0;
- }
- nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte,
- 0, 0);
- if( nByte == 0 ){
- sqlite3_free(zText);
- zText = 0;
- }
- return zText;
-}
-
-/*
-** Convert an ANSI string to Microsoft Unicode, using the ANSI or OEM
-** code page.
-**
-** Space to hold the returned string is obtained from sqlite3_malloc().
-*/
-static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){
- int nByte;
- LPWSTR zMbcsText;
- int codepage = useAnsi ? CP_ACP : CP_OEMCP;
-
- nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
- 0)*sizeof(WCHAR);
- if( nByte==0 ){
- return 0;
- }
- zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) );
- if( zMbcsText==0 ){
- return 0;
- }
- nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
- nByte);
- if( nByte==0 ){
- sqlite3_free(zMbcsText);
- zMbcsText = 0;
- }
- return zMbcsText;
-}
-
-/*
-** Convert a Microsoft Unicode string to a multi-byte character string,
-** using the ANSI or OEM code page.
-**
-** Space to hold the returned string is obtained from sqlite3_malloc().
-*/
-static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){
- int nByte;
- char *zText;
- int codepage = useAnsi ? CP_ACP : CP_OEMCP;
-
- nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, 0, 0, 0, 0);
- if( nByte == 0 ){
- return 0;
- }
- zText = sqlite3MallocZero( nByte );
- if( zText==0 ){
- return 0;
- }
- nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, zText,
- nByte, 0, 0);
- if( nByte == 0 ){
- sqlite3_free(zText);
- zText = 0;
- }
- return zText;
-}
-
-/*
-** Convert a multi-byte character string to UTF-8.
-**
-** Space to hold the returned string is obtained from sqlite3_malloc().
-*/
-static char *winMbcsToUtf8(const char *zText, int useAnsi){
- char *zTextUtf8;
- LPWSTR zTmpWide;
-
- zTmpWide = winMbcsToUnicode(zText, useAnsi);
- if( zTmpWide==0 ){
- return 0;
- }
- zTextUtf8 = winUnicodeToUtf8(zTmpWide);
- sqlite3_free(zTmpWide);
- return zTextUtf8;
-}
-
-/*
-** Convert a UTF-8 string to a multi-byte character string.
-**
-** Space to hold the returned string is obtained from sqlite3_malloc().
-*/
-static char *winUtf8ToMbcs(const char *zText, int useAnsi){
- char *zTextMbcs;
- LPWSTR zTmpWide;
-
- zTmpWide = winUtf8ToUnicode(zText);
- if( zTmpWide==0 ){
- return 0;
- }
- zTextMbcs = winUnicodeToMbcs(zTmpWide, useAnsi);
- sqlite3_free(zTmpWide);
- return zTextMbcs;
-}
-
-/*
-** This is a public wrapper for the winUtf8ToUnicode() function.
-*/
-LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !zText ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return winUtf8ToUnicode(zText);
-}
-
-/*
-** This is a public wrapper for the winUnicodeToUtf8() function.
-*/
-char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !zWideText ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return winUnicodeToUtf8(zWideText);
-}
-
-/*
-** This is a public wrapper for the winMbcsToUtf8() function.
-*/
-char *sqlite3_win32_mbcs_to_utf8(const char *zText){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !zText ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return winMbcsToUtf8(zText, osAreFileApisANSI());
-}
-
-/*
-** This is a public wrapper for the winMbcsToUtf8() function.
-*/
-char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !zText ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return winMbcsToUtf8(zText, useAnsi);
-}
-
-/*
-** This is a public wrapper for the winUtf8ToMbcs() function.
-*/
-char *sqlite3_win32_utf8_to_mbcs(const char *zText){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !zText ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return winUtf8ToMbcs(zText, osAreFileApisANSI());
-}
-
-/*
-** This is a public wrapper for the winUtf8ToMbcs() function.
-*/
-char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !zText ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- return winUtf8ToMbcs(zText, useAnsi);
-}
-
-/*
-** This function is the same as sqlite3_win32_set_directory (below); however,
-** it accepts a UTF-8 string.
-*/
-int sqlite3_win32_set_directory8(
- unsigned long type, /* Identifier for directory being set or reset */
- const char *zValue /* New value for directory being set or reset */
-){
- char **ppDirectory = 0;
-#ifndef SQLITE_OMIT_AUTOINIT
- int rc = sqlite3_initialize();
- if( rc ) return rc;
-#endif
- if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
- ppDirectory = &sqlite3_data_directory;
- }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
- ppDirectory = &sqlite3_temp_directory;
- }
- assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
- || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
- );
- assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
- if( ppDirectory ){
- char *zCopy = 0;
- if( zValue && zValue[0] ){
- zCopy = sqlite3_mprintf("%s", zValue);
- if ( zCopy==0 ){
- return SQLITE_NOMEM_BKPT;
- }
- }
- sqlite3_free(*ppDirectory);
- *ppDirectory = zCopy;
- return SQLITE_OK;
- }
- return SQLITE_ERROR;
-}
-
-/*
-** This function is the same as sqlite3_win32_set_directory (below); however,
-** it accepts a UTF-16 string.
-*/
-int sqlite3_win32_set_directory16(
- unsigned long type, /* Identifier for directory being set or reset */
- const void *zValue /* New value for directory being set or reset */
-){
- int rc;
- char *zUtf8 = 0;
- if( zValue ){
- zUtf8 = sqlite3_win32_unicode_to_utf8(zValue);
- if( zUtf8==0 ) return SQLITE_NOMEM_BKPT;
- }
- rc = sqlite3_win32_set_directory8(type, zUtf8);
- if( zUtf8 ) sqlite3_free(zUtf8);
- return rc;
-}
-
-/*
-** This function sets the data directory or the temporary directory based on
-** the provided arguments. The type argument must be 1 in order to set the
-** data directory or 2 in order to set the temporary directory. The zValue
-** argument is the name of the directory to use. The return value will be
-** SQLITE_OK if successful.
-*/
-int sqlite3_win32_set_directory(
- unsigned long type, /* Identifier for directory being set or reset */
- void *zValue /* New value for directory being set or reset */
-){
- return sqlite3_win32_set_directory16(type, zValue);
-}
-
-/*
-** The return value of winGetLastErrorMsg
-** is zero if the error message fits in the buffer, or non-zero
-** otherwise (if the message was truncated).
-*/
-static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
- /* FormatMessage returns 0 on failure. Otherwise it
- ** returns the number of TCHARs written to the output
- ** buffer, excluding the terminating null char.
- */
- DWORD dwLen = 0;
- char *zOut = 0;
-
- if( osIsNT() ){
-#if SQLITE_OS_WINRT
- WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1];
- dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- lastErrno,
- 0,
- zTempWide,
- SQLITE_WIN32_MAX_ERRMSG_CHARS,
- 0);
-#else
- LPWSTR zTempWide = NULL;
- dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- lastErrno,
- 0,
- (LPWSTR) &zTempWide,
- 0,
- 0);
-#endif
- if( dwLen > 0 ){
- /* allocate a buffer and convert to UTF8 */
- sqlite3BeginBenignMalloc();
- zOut = winUnicodeToUtf8(zTempWide);
- sqlite3EndBenignMalloc();
-#if !SQLITE_OS_WINRT
- /* free the system buffer allocated by FormatMessage */
- osLocalFree(zTempWide);
-#endif
- }
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- char *zTemp = NULL;
- dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- lastErrno,
- 0,
- (LPSTR) &zTemp,
- 0,
- 0);
- if( dwLen > 0 ){
- /* allocate a buffer and convert to UTF8 */
- sqlite3BeginBenignMalloc();
- zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI());
- sqlite3EndBenignMalloc();
- /* free the system buffer allocated by FormatMessage */
- osLocalFree(zTemp);
- }
- }
-#endif
- if( 0 == dwLen ){
- sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
- }else{
- /* copy a maximum of nBuf chars to output buffer */
- sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
- /* free the UTF8 buffer */
- sqlite3_free(zOut);
- }
- return 0;
-}
-
-/*
-**
-** This function - winLogErrorAtLine() - is only ever called via the macro
-** winLogError().
-**
-** This routine is invoked after an error occurs in an OS function.
-** It logs a message using sqlite3_log() containing the current value of
-** error code and, if possible, the human-readable equivalent from
-** FormatMessage.
-**
-** The first argument passed to the macro should be the error code that
-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
-** The two subsequent arguments should be the name of the OS function that
-** failed and the associated file-system path, if any.
-*/
-#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
-static int winLogErrorAtLine(
- int errcode, /* SQLite error code */
- DWORD lastErrno, /* Win32 last error */
- const char *zFunc, /* Name of OS function that failed */
- const char *zPath, /* File path associated with error */
- int iLine /* Source line number where error occurred */
-){
- char zMsg[500]; /* Human readable error text */
- int i; /* Loop counter */
-
- zMsg[0] = 0;
- winGetLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
- assert( errcode!=SQLITE_OK );
- if( zPath==0 ) zPath = "";
- for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
- zMsg[i] = 0;
- sqlite3_log(errcode,
- "os_win.c:%d: (%lu) %s(%s) - %s",
- iLine, lastErrno, zFunc, zPath, zMsg
- );
-
- return errcode;
-}
-
-/*
-** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
-** will be retried following a locking error - probably caused by
-** antivirus software. Also the initial delay before the first retry.
-** The delay increases linearly with each retry.
-*/
-#ifndef SQLITE_WIN32_IOERR_RETRY
-# define SQLITE_WIN32_IOERR_RETRY 10
-#endif
-#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
-# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
-#endif
-static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
-static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
-
-/*
-** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
-** error code obtained via GetLastError() is eligible to be retried. It
-** must accept the error code DWORD as its only argument and should return
-** non-zero if the error code is transient in nature and the operation
-** responsible for generating the original error might succeed upon being
-** retried. The argument to this macro should be a variable.
-**
-** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it
-** is defined, it will be consulted only when the macro "winIoerrCanRetry1"
-** returns zero. The "winIoerrCanRetry2" macro is completely optional and
-** may be used to include additional error codes in the set that should
-** result in the failing I/O operation being retried by the caller. If
-** defined, the "winIoerrCanRetry2" macro must exhibit external semantics
-** identical to those of the "winIoerrCanRetry1" macro.
-*/
-#if !defined(winIoerrCanRetry1)
-#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \
- ((a)==ERROR_SHARING_VIOLATION) || \
- ((a)==ERROR_LOCK_VIOLATION) || \
- ((a)==ERROR_DEV_NOT_EXIST) || \
- ((a)==ERROR_NETNAME_DELETED) || \
- ((a)==ERROR_SEM_TIMEOUT) || \
- ((a)==ERROR_NETWORK_UNREACHABLE))
-#endif
-
-/*
-** If a ReadFile() or WriteFile() error occurs, invoke this routine
-** to see if it should be retried. Return TRUE to retry. Return FALSE
-** to give up with an error.
-*/
-static int winRetryIoerr(int *pnRetry, DWORD *pError){
- DWORD e = osGetLastError();
- if( *pnRetry>=winIoerrRetry ){
- if( pError ){
- *pError = e;
- }
- return 0;
- }
- if( winIoerrCanRetry1(e) ){
- sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
- ++*pnRetry;
- return 1;
- }
-#if defined(winIoerrCanRetry2)
- else if( winIoerrCanRetry2(e) ){
- sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
- ++*pnRetry;
- return 1;
- }
-#endif
- if( pError ){
- *pError = e;
- }
- return 0;
-}
-
-/*
-** Log a I/O error retry episode.
-*/
-static void winLogIoerr(int nRetry, int lineno){
- if( nRetry ){
- sqlite3_log(SQLITE_NOTICE,
- "delayed %dms for lock/sharing conflict at line %d",
- winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
- );
- }
-}
-
-/*
-** This #if does not rely on the SQLITE_OS_WINCE define because the
-** corresponding section in "date.c" cannot use it.
-*/
-#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \
- (!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API)
-/*
-** The MSVC CRT on Windows CE may not have a localtime() function.
-** So define a substitute.
-*/
-# include <time.h>
-struct tm *__cdecl localtime(const time_t *t)
-{
- static struct tm y;
- FILETIME uTm, lTm;
- SYSTEMTIME pTm;
- sqlite3_int64 t64;
- t64 = *t;
- t64 = (t64 + 11644473600)*10000000;
- uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
- uTm.dwHighDateTime= (DWORD)(t64 >> 32);
- osFileTimeToLocalFileTime(&uTm,&lTm);
- osFileTimeToSystemTime(&lTm,&pTm);
- y.tm_year = pTm.wYear - 1900;
- y.tm_mon = pTm.wMonth - 1;
- y.tm_wday = pTm.wDayOfWeek;
- y.tm_mday = pTm.wDay;
- y.tm_hour = pTm.wHour;
- y.tm_min = pTm.wMinute;
- y.tm_sec = pTm.wSecond;
- return &y;
-}
-#endif
-
-#if SQLITE_OS_WINCE
-/*************************************************************************
-** This section contains code for WinCE only.
-*/
-#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
-
-/*
-** Acquire a lock on the handle h
-*/
-static void winceMutexAcquire(HANDLE h){
- DWORD dwErr;
- do {
- dwErr = osWaitForSingleObject(h, INFINITE);
- } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
-}
-/*
-** Release a lock acquired by winceMutexAcquire()
-*/
-#define winceMutexRelease(h) ReleaseMutex(h)
-
-/*
-** Create the mutex and shared memory used for locking in the file
-** descriptor pFile
-*/
-static int winceCreateLock(const char *zFilename, winFile *pFile){
- LPWSTR zTok;
- LPWSTR zName;
- DWORD lastErrno;
- BOOL bLogged = FALSE;
- BOOL bInit = TRUE;
-
- zName = winUtf8ToUnicode(zFilename);
- if( zName==0 ){
- /* out of memory */
- return SQLITE_IOERR_NOMEM_BKPT;
- }
-
- /* Initialize the local lockdata */
- memset(&pFile->local, 0, sizeof(pFile->local));
-
- /* Replace the backslashes from the filename and lowercase it
- ** to derive a mutex name. */
- zTok = osCharLowerW(zName);
- for (;*zTok;zTok++){
- if (*zTok == '\\') *zTok = '_';
- }
-
- /* Create/open the named mutex */
- pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
- if (!pFile->hMutex){
- pFile->lastErrno = osGetLastError();
- sqlite3_free(zName);
- return winLogError(SQLITE_IOERR, pFile->lastErrno,
- "winceCreateLock1", zFilename);
- }
-
- /* Acquire the mutex before continuing */
- winceMutexAcquire(pFile->hMutex);
-
- /* Since the names of named mutexes, semaphores, file mappings etc are
- ** case-sensitive, take advantage of that by uppercasing the mutex name
- ** and using that as the shared filemapping name.
- */
- osCharUpperW(zName);
- pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
- PAGE_READWRITE, 0, sizeof(winceLock),
- zName);
-
- /* Set a flag that indicates we're the first to create the memory so it
- ** must be zero-initialized */
- lastErrno = osGetLastError();
- if (lastErrno == ERROR_ALREADY_EXISTS){
- bInit = FALSE;
- }
-
- sqlite3_free(zName);
-
- /* If we succeeded in making the shared memory handle, map it. */
- if( pFile->hShared ){
- pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
- FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
- /* If mapping failed, close the shared memory handle and erase it */
- if( !pFile->shared ){
- pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR, pFile->lastErrno,
- "winceCreateLock2", zFilename);
- bLogged = TRUE;
- osCloseHandle(pFile->hShared);
- pFile->hShared = NULL;
- }
- }
-
- /* If shared memory could not be created, then close the mutex and fail */
- if( pFile->hShared==NULL ){
- if( !bLogged ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_IOERR, pFile->lastErrno,
- "winceCreateLock3", zFilename);
- bLogged = TRUE;
- }
- winceMutexRelease(pFile->hMutex);
- osCloseHandle(pFile->hMutex);
- pFile->hMutex = NULL;
- return SQLITE_IOERR;
- }
-
- /* Initialize the shared memory if we're supposed to */
- if( bInit ){
- memset(pFile->shared, 0, sizeof(winceLock));
- }
-
- winceMutexRelease(pFile->hMutex);
- return SQLITE_OK;
-}
-
-/*
-** Destroy the part of winFile that deals with wince locks
-*/
-static void winceDestroyLock(winFile *pFile){
- if (pFile->hMutex){
- /* Acquire the mutex */
- winceMutexAcquire(pFile->hMutex);
-
- /* The following blocks should probably assert in debug mode, but they
- are to cleanup in case any locks remained open */
- if (pFile->local.nReaders){
- pFile->shared->nReaders --;
- }
- if (pFile->local.bReserved){
- pFile->shared->bReserved = FALSE;
- }
- if (pFile->local.bPending){
- pFile->shared->bPending = FALSE;
- }
- if (pFile->local.bExclusive){
- pFile->shared->bExclusive = FALSE;
- }
-
- /* De-reference and close our copy of the shared memory handle */
- osUnmapViewOfFile(pFile->shared);
- osCloseHandle(pFile->hShared);
-
- /* Done with the mutex */
- winceMutexRelease(pFile->hMutex);
- osCloseHandle(pFile->hMutex);
- pFile->hMutex = NULL;
- }
-}
-
-/*
-** An implementation of the LockFile() API of Windows for CE
-*/
-static BOOL winceLockFile(
- LPHANDLE phFile,
- DWORD dwFileOffsetLow,
- DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToLockLow,
- DWORD nNumberOfBytesToLockHigh
-){
- winFile *pFile = HANDLE_TO_WINFILE(phFile);
- BOOL bReturn = FALSE;
-
- UNUSED_PARAMETER(dwFileOffsetHigh);
- UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
-
- if (!pFile->hMutex) return TRUE;
- winceMutexAcquire(pFile->hMutex);
-
- /* Wanting an exclusive lock? */
- if (dwFileOffsetLow == (DWORD)SHARED_FIRST
- && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
- if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
- pFile->shared->bExclusive = TRUE;
- pFile->local.bExclusive = TRUE;
- bReturn = TRUE;
- }
- }
-
- /* Want a read-only lock? */
- else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
- nNumberOfBytesToLockLow == 1){
- if (pFile->shared->bExclusive == 0){
- pFile->local.nReaders ++;
- if (pFile->local.nReaders == 1){
- pFile->shared->nReaders ++;
- }
- bReturn = TRUE;
- }
- }
-
- /* Want a pending lock? */
- else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
- && nNumberOfBytesToLockLow == 1){
- /* If no pending lock has been acquired, then acquire it */
- if (pFile->shared->bPending == 0) {
- pFile->shared->bPending = TRUE;
- pFile->local.bPending = TRUE;
- bReturn = TRUE;
- }
- }
-
- /* Want a reserved lock? */
- else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
- && nNumberOfBytesToLockLow == 1){
- if (pFile->shared->bReserved == 0) {
- pFile->shared->bReserved = TRUE;
- pFile->local.bReserved = TRUE;
- bReturn = TRUE;
- }
- }
-
- winceMutexRelease(pFile->hMutex);
- return bReturn;
-}
-
-/*
-** An implementation of the UnlockFile API of Windows for CE
-*/
-static BOOL winceUnlockFile(
- LPHANDLE phFile,
- DWORD dwFileOffsetLow,
- DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToUnlockLow,
- DWORD nNumberOfBytesToUnlockHigh
-){
- winFile *pFile = HANDLE_TO_WINFILE(phFile);
- BOOL bReturn = FALSE;
-
- UNUSED_PARAMETER(dwFileOffsetHigh);
- UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
-
- if (!pFile->hMutex) return TRUE;
- winceMutexAcquire(pFile->hMutex);
-
- /* Releasing a reader lock or an exclusive lock */
- if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
- /* Did we have an exclusive lock? */
- if (pFile->local.bExclusive){
- assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
- pFile->local.bExclusive = FALSE;
- pFile->shared->bExclusive = FALSE;
- bReturn = TRUE;
- }
-
- /* Did we just have a reader lock? */
- else if (pFile->local.nReaders){
- assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
- || nNumberOfBytesToUnlockLow == 1);
- pFile->local.nReaders --;
- if (pFile->local.nReaders == 0)
- {
- pFile->shared->nReaders --;
- }
- bReturn = TRUE;
- }
- }
-
- /* Releasing a pending lock */
- else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
- && nNumberOfBytesToUnlockLow == 1){
- if (pFile->local.bPending){
- pFile->local.bPending = FALSE;
- pFile->shared->bPending = FALSE;
- bReturn = TRUE;
- }
- }
- /* Releasing a reserved lock */
- else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
- && nNumberOfBytesToUnlockLow == 1){
- if (pFile->local.bReserved) {
- pFile->local.bReserved = FALSE;
- pFile->shared->bReserved = FALSE;
- bReturn = TRUE;
- }
- }
-
- winceMutexRelease(pFile->hMutex);
- return bReturn;
-}
-/*
-** End of the special code for wince
-*****************************************************************************/
-#endif /* SQLITE_OS_WINCE */
-
-/*
-** Lock a file region.
-*/
-static BOOL winLockFile(
- LPHANDLE phFile,
- DWORD flags,
- DWORD offsetLow,
- DWORD offsetHigh,
- DWORD numBytesLow,
- DWORD numBytesHigh
-){
-#if SQLITE_OS_WINCE
- /*
- ** NOTE: Windows CE is handled differently here due its lack of the Win32
- ** API LockFile.
- */
- return winceLockFile(phFile, offsetLow, offsetHigh,
- numBytesLow, numBytesHigh);
-#else
- if( osIsNT() ){
- OVERLAPPED ovlp;
- memset(&ovlp, 0, sizeof(OVERLAPPED));
- ovlp.Offset = offsetLow;
- ovlp.OffsetHigh = offsetHigh;
- return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
- }else{
- return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
- numBytesHigh);
- }
-#endif
-}
-
-/*
-** Unlock a file region.
- */
-static BOOL winUnlockFile(
- LPHANDLE phFile,
- DWORD offsetLow,
- DWORD offsetHigh,
- DWORD numBytesLow,
- DWORD numBytesHigh
-){
-#if SQLITE_OS_WINCE
- /*
- ** NOTE: Windows CE is handled differently here due its lack of the Win32
- ** API UnlockFile.
- */
- return winceUnlockFile(phFile, offsetLow, offsetHigh,
- numBytesLow, numBytesHigh);
-#else
- if( osIsNT() ){
- OVERLAPPED ovlp;
- memset(&ovlp, 0, sizeof(OVERLAPPED));
- ovlp.Offset = offsetLow;
- ovlp.OffsetHigh = offsetHigh;
- return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
- }else{
- return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
- numBytesHigh);
- }
-#endif
-}
-
-/*****************************************************************************
-** The next group of routines implement the I/O methods specified
-** by the sqlite3_io_methods object.
-******************************************************************************/
-
-/*
-** Some Microsoft compilers lack this definition.
-*/
-#ifndef INVALID_SET_FILE_POINTER
-# define INVALID_SET_FILE_POINTER ((DWORD)-1)
-#endif
-
-/*
-** Move the current position of the file handle passed as the first
-** argument to offset iOffset within the file. If successful, return 0.
-** Otherwise, set pFile->lastErrno and return non-zero.
-*/
-static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
-#if !SQLITE_OS_WINRT
- LONG upperBits; /* Most sig. 32 bits of new offset */
- LONG lowerBits; /* Least sig. 32 bits of new offset */
- DWORD dwRet; /* Value returned by SetFilePointer() */
- DWORD lastErrno; /* Value returned by GetLastError() */
-
- OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
-
- upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
- lowerBits = (LONG)(iOffset & 0xffffffff);
-
- /* API oddity: If successful, SetFilePointer() returns a dword
- ** containing the lower 32-bits of the new file-offset. Or, if it fails,
- ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
- ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
- ** whether an error has actually occurred, it is also necessary to call
- ** GetLastError().
- */
- dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
-
- if( (dwRet==INVALID_SET_FILE_POINTER
- && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
- }
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
-#else
- /*
- ** Same as above, except that this implementation works for WinRT.
- */
-
- LARGE_INTEGER x; /* The new offset */
- BOOL bRet; /* Value returned by SetFilePointerEx() */
-
- x.QuadPart = iOffset;
- bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
-
- if(!bRet){
- pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
- }
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
-#endif
-}
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/* Forward references to VFS helper methods used for memory mapped files */
-static int winMapfile(winFile*, sqlite3_int64);
-static int winUnmapfile(winFile*);
-#endif
-
-/*
-** Close a file.
-**
-** It is reported that an attempt to close a handle might sometimes
-** fail. This is a very unreasonable result, but Windows is notorious
-** for being unreasonable so I do not doubt that it might happen. If
-** the close fails, we pause for 100 milliseconds and try again. As
-** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
-** giving up and returning an error.
-*/
-#define MX_CLOSE_ATTEMPT 3
-static int winClose(sqlite3_file *id){
- int rc, cnt = 0;
- winFile *pFile = (winFile*)id;
-
- assert( id!=0 );
-#ifndef SQLITE_OMIT_WAL
- assert( pFile->pShm==0 );
-#endif
- assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
- OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n",
- osGetCurrentProcessId(), pFile, pFile->h));
-
-#if SQLITE_MAX_MMAP_SIZE>0
- winUnmapfile(pFile);
-#endif
-
- do{
- rc = osCloseHandle(pFile->h);
- /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
- }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
-#if SQLITE_OS_WINCE
-#define WINCE_DELETION_ATTEMPTS 3
- {
- winVfsAppData *pAppData = (winVfsAppData*)pFile->pVfs->pAppData;
- if( pAppData==NULL || !pAppData->bNoLock ){
- winceDestroyLock(pFile);
- }
- }
- if( pFile->zDeleteOnClose ){
- int cnt = 0;
- while(
- osDeleteFileW(pFile->zDeleteOnClose)==0
- && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
- && cnt++ < WINCE_DELETION_ATTEMPTS
- ){
- sqlite3_win32_sleep(100); /* Wait a little before trying again */
- }
- sqlite3_free(pFile->zDeleteOnClose);
- }
-#endif
- if( rc ){
- pFile->h = NULL;
- }
- OpenCounter(-1);
- OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n",
- osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed"));
- return rc ? SQLITE_OK
- : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
- "winClose", pFile->zPath);
-}
-
-/*
-** Read data from a file into a buffer. Return SQLITE_OK if all
-** bytes were read successfully and SQLITE_IOERR if anything goes
-** wrong.
-*/
-static int winRead(
- sqlite3_file *id, /* File to read from */
- void *pBuf, /* Write content into this buffer */
- int amt, /* Number of bytes to read */
- sqlite3_int64 offset /* Begin reading at this offset */
-){
-#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
- OVERLAPPED overlapped; /* The offset for ReadFile. */
-#endif
- winFile *pFile = (winFile*)id; /* file handle */
- DWORD nRead; /* Number of bytes actually read from file */
- int nRetry = 0; /* Number of retrys */
-
- assert( id!=0 );
- assert( amt>0 );
- assert( offset>=0 );
- SimulateIOError(return SQLITE_IOERR_READ);
- OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
- "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
- pFile->h, pBuf, amt, offset, pFile->locktype));
-
-#if SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this read request as possible by transfering
- ** data from the memory mapping using memcpy(). */
- if( offset<pFile->mmapSize ){
- if( offset+amt <= pFile->mmapSize ){
- memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
- OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return SQLITE_OK;
- }else{
- int nCopy = (int)(pFile->mmapSize - offset);
- memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
- pBuf = &((u8 *)pBuf)[nCopy];
- amt -= nCopy;
- offset += nCopy;
- }
- }
-#endif
-
-#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
- if( winSeekFile(pFile, offset) ){
- OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return SQLITE_FULL;
- }
- while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
-#else
- memset(&overlapped, 0, sizeof(OVERLAPPED));
- overlapped.Offset = (LONG)(offset & 0xffffffff);
- overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
- while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
- osGetLastError()!=ERROR_HANDLE_EOF ){
-#endif
- DWORD lastErrno;
- if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
- pFile->lastErrno = lastErrno;
- OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
- "winRead", pFile->zPath);
- }
- winLogIoerr(nRetry, __LINE__);
- if( nRead<(DWORD)amt ){
- /* Unread parts of the buffer must be zero-filled */
- memset(&((char*)pBuf)[nRead], 0, amt-nRead);
- OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return SQLITE_IOERR_SHORT_READ;
- }
-
- OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return SQLITE_OK;
-}
-
-/*
-** Write data from a buffer into a file. Return SQLITE_OK on success
-** or some other error code on failure.
-*/
-static int winWrite(
- sqlite3_file *id, /* File to write into */
- const void *pBuf, /* The bytes to be written */
- int amt, /* Number of bytes to write */
- sqlite3_int64 offset /* Offset into the file to begin writing at */
-){
- int rc = 0; /* True if error has occurred, else false */
- winFile *pFile = (winFile*)id; /* File handle */
- int nRetry = 0; /* Number of retries */
-
- assert( amt>0 );
- assert( pFile );
- SimulateIOError(return SQLITE_IOERR_WRITE);
- SimulateDiskfullError(return SQLITE_FULL);
-
- OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
- "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
- pFile->h, pBuf, amt, offset, pFile->locktype));
-
-#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this write request as possible by transfering
- ** data from the memory mapping using memcpy(). */
- if( offset<pFile->mmapSize ){
- if( offset+amt <= pFile->mmapSize ){
- memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
- OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return SQLITE_OK;
- }else{
- int nCopy = (int)(pFile->mmapSize - offset);
- memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
- pBuf = &((u8 *)pBuf)[nCopy];
- amt -= nCopy;
- offset += nCopy;
- }
- }
-#endif
-
-#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
- rc = winSeekFile(pFile, offset);
- if( rc==0 ){
-#else
- {
-#endif
-#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
- OVERLAPPED overlapped; /* The offset for WriteFile. */
-#endif
- u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
- int nRem = amt; /* Number of bytes yet to be written */
- DWORD nWrite; /* Bytes written by each WriteFile() call */
- DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
-
-#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
- memset(&overlapped, 0, sizeof(OVERLAPPED));
- overlapped.Offset = (LONG)(offset & 0xffffffff);
- overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
-#endif
-
- while( nRem>0 ){
-#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
- if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
-#else
- if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
-#endif
- if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
- break;
- }
- assert( nWrite==0 || nWrite<=(DWORD)nRem );
- if( nWrite==0 || nWrite>(DWORD)nRem ){
- lastErrno = osGetLastError();
- break;
- }
-#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
- offset += nWrite;
- overlapped.Offset = (LONG)(offset & 0xffffffff);
- overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
-#endif
- aRem += nWrite;
- nRem -= nWrite;
- }
- if( nRem>0 ){
- pFile->lastErrno = lastErrno;
- rc = 1;
- }
- }
-
- if( rc ){
- if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
- || ( pFile->lastErrno==ERROR_DISK_FULL )){
- OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return winLogError(SQLITE_FULL, pFile->lastErrno,
- "winWrite1", pFile->zPath);
- }
- OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
- "winWrite2", pFile->zPath);
- }else{
- winLogIoerr(nRetry, __LINE__);
- }
- OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return SQLITE_OK;
-}
-
-/*
-** Truncate an open file to a specified size
-*/
-static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
- winFile *pFile = (winFile*)id; /* File handle object */
- int rc = SQLITE_OK; /* Return code for this function */
- DWORD lastErrno;
-
- assert( pFile );
- SimulateIOError(return SQLITE_IOERR_TRUNCATE);
- OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
- osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));
-
- /* If the user has configured a chunk-size for this file, truncate the
- ** file so that it consists of an integer number of chunks (i.e. the
- ** actual file size after the operation may be larger than the requested
- ** size).
- */
- if( pFile->szChunk>0 ){
- nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
- }
-
- /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
- if( winSeekFile(pFile, nByte) ){
- rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
- "winTruncate1", pFile->zPath);
- }else if( 0==osSetEndOfFile(pFile->h) &&
- ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
- pFile->lastErrno = lastErrno;
- rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
- "winTruncate2", pFile->zPath);
- }
-
-#if SQLITE_MAX_MMAP_SIZE>0
- /* If the file was truncated to a size smaller than the currently
- ** mapped region, reduce the effective mapping size as well. SQLite will
- ** use read() and write() to access data beyond this point from now on.
- */
- if( pFile->pMapRegion && nByte<pFile->mmapSize ){
- pFile->mmapSize = nByte;
- }
-#endif
-
- OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
- osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc)));
- return rc;
-}
-
-#ifdef SQLITE_TEST
-/*
-** Count the number of fullsyncs and normal syncs. This is used to test
-** that syncs and fullsyncs are occuring at the right times.
-*/
-int sqlite3_sync_count = 0;
-int sqlite3_fullsync_count = 0;
-#endif
-
-/*
-** Make sure all writes to a particular file are committed to disk.
-*/
-static int winSync(sqlite3_file *id, int flags){
-#ifndef SQLITE_NO_SYNC
- /*
- ** Used only when SQLITE_NO_SYNC is not defined.
- */
- BOOL rc;
-#endif
-#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
- defined(SQLITE_HAVE_OS_TRACE)
- /*
- ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
- ** OSTRACE() macros.
- */
- winFile *pFile = (winFile*)id;
-#else
- UNUSED_PARAMETER(id);
-#endif
-
- assert( pFile );
- /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
- assert((flags&0x0F)==SQLITE_SYNC_NORMAL
- || (flags&0x0F)==SQLITE_SYNC_FULL
- );
-
- /* Unix cannot, but some systems may return SQLITE_FULL from here. This
- ** line is to test that doing so does not cause any problems.
- */
- SimulateDiskfullError( return SQLITE_FULL );
-
- OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n",
- osGetCurrentProcessId(), pFile, pFile->h, flags,
- pFile->locktype));
-
-#ifndef SQLITE_TEST
- UNUSED_PARAMETER(flags);
-#else
- if( (flags&0x0F)==SQLITE_SYNC_FULL ){
- sqlite3_fullsync_count++;
- }
- sqlite3_sync_count++;
-#endif
-
- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
- ** no-op
- */
-#ifdef SQLITE_NO_SYNC
- OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return SQLITE_OK;
-#else
-#if SQLITE_MAX_MMAP_SIZE>0
- if( pFile->pMapRegion ){
- if( osFlushViewOfFile(pFile->pMapRegion, 0) ){
- OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
- "rc=SQLITE_OK\n", osGetCurrentProcessId(),
- pFile, pFile->pMapRegion));
- }else{
- pFile->lastErrno = osGetLastError();
- OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
- "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(),
- pFile, pFile->pMapRegion));
- return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
- "winSync1", pFile->zPath);
- }
- }
-#endif
- rc = osFlushFileBuffers(pFile->h);
- SimulateIOError( rc=FALSE );
- if( rc ){
- OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return SQLITE_OK;
- }else{
- pFile->lastErrno = osGetLastError();
- OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
- osGetCurrentProcessId(), pFile, pFile->h));
- return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
- "winSync2", pFile->zPath);
- }
-#endif
-}
-
-/*
-** Determine the current size of a file in bytes
-*/
-static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
- winFile *pFile = (winFile*)id;
- int rc = SQLITE_OK;
-
- assert( id!=0 );
- assert( pSize!=0 );
- SimulateIOError(return SQLITE_IOERR_FSTAT);
- OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
-
-#if SQLITE_OS_WINRT
- {
- FILE_STANDARD_INFO info;
- if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
- &info, sizeof(info)) ){
- *pSize = info.EndOfFile.QuadPart;
- }else{
- pFile->lastErrno = osGetLastError();
- rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
- "winFileSize", pFile->zPath);
- }
- }
-#else
- {
- DWORD upperBits;
- DWORD lowerBits;
- DWORD lastErrno;
-
- lowerBits = osGetFileSize(pFile->h, &upperBits);
- *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
- if( (lowerBits == INVALID_FILE_SIZE)
- && ((lastErrno = osGetLastError())!=NO_ERROR) ){
- pFile->lastErrno = lastErrno;
- rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
- "winFileSize", pFile->zPath);
- }
- }
-#endif
- OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
- pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
- return rc;
-}
-
-/*
-** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
-*/
-#ifndef LOCKFILE_FAIL_IMMEDIATELY
-# define LOCKFILE_FAIL_IMMEDIATELY 1
-#endif
-
-#ifndef LOCKFILE_EXCLUSIVE_LOCK
-# define LOCKFILE_EXCLUSIVE_LOCK 2
-#endif
-
-/*
-** Historically, SQLite has used both the LockFile and LockFileEx functions.
-** When the LockFile function was used, it was always expected to fail
-** immediately if the lock could not be obtained. Also, it always expected to
-** obtain an exclusive lock. These flags are used with the LockFileEx function
-** and reflect those expectations; therefore, they should not be changed.
-*/
-#ifndef SQLITE_LOCKFILE_FLAGS
-# define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \
- LOCKFILE_EXCLUSIVE_LOCK)
-#endif
-
-/*
-** Currently, SQLite never calls the LockFileEx function without wanting the
-** call to fail immediately if the lock cannot be obtained.
-*/
-#ifndef SQLITE_LOCKFILEEX_FLAGS
-# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY)
-#endif
-
-/*
-** Acquire a reader lock.
-** Different API routines are called depending on whether or not this
-** is Win9x or WinNT.
-*/
-static int winGetReadLock(winFile *pFile){
- int res;
- OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
- if( osIsNT() ){
-#if SQLITE_OS_WINCE
- /*
- ** NOTE: Windows CE is handled differently here due its lack of the Win32
- ** API LockFileEx.
- */
- res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
-#else
- res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
- SHARED_SIZE, 0);
-#endif
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- int lk;
- sqlite3_randomness(sizeof(lk), &lk);
- pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
- SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
- }
-#endif
- if( res == 0 ){
- pFile->lastErrno = osGetLastError();
- /* No need to log a failure to lock */
- }
- OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res));
- return res;
-}
-
-/*
-** Undo a readlock
-*/
-static int winUnlockReadLock(winFile *pFile){
- int res;
- DWORD lastErrno;
- OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
- if( osIsNT() ){
- res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
- }
-#endif
- if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
- "winUnlockReadLock", pFile->zPath);
- }
- OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res));
- return res;
-}
-
-/*
-** Lock the file with the lock specified by parameter locktype - one
-** of the following:
-**
-** (1) SHARED_LOCK
-** (2) RESERVED_LOCK
-** (3) PENDING_LOCK
-** (4) EXCLUSIVE_LOCK
-**
-** Sometimes when requesting one lock state, additional lock states
-** are inserted in between. The locking might fail on one of the later
-** transitions leaving the lock state different from what it started but
-** still short of its goal. The following chart shows the allowed
-** transitions and the inserted intermediate states:
-**
-** UNLOCKED -> SHARED
-** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
-** RESERVED -> (PENDING) -> EXCLUSIVE
-** PENDING -> EXCLUSIVE
-**
-** This routine will only increase a lock. The winUnlock() routine
-** erases all locks at once and returns us immediately to locking level 0.
-** It is not possible to lower the locking level one step at a time. You
-** must go straight to locking level 0.
-*/
-static int winLock(sqlite3_file *id, int locktype){
- int rc = SQLITE_OK; /* Return code from subroutines */
- int res = 1; /* Result of a Windows lock call */
- int newLocktype; /* Set pFile->locktype to this value before exiting */
- int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
- winFile *pFile = (winFile*)id;
- DWORD lastErrno = NO_ERROR;
-
- assert( id!=0 );
- OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n",
- pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
-
- /* If there is already a lock of this type or more restrictive on the
- ** OsFile, do nothing. Don't use the end_lock: exit path, as
- ** sqlite3OsEnterMutex() hasn't been called yet.
- */
- if( pFile->locktype>=locktype ){
- OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
-
- /* Do not allow any kind of write-lock on a read-only database
- */
- if( (pFile->ctrlFlags & WINFILE_RDONLY)!=0 && locktype>=RESERVED_LOCK ){
- return SQLITE_IOERR_LOCK;
- }
-
- /* Make sure the locking sequence is correct
- */
- assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
- assert( locktype!=PENDING_LOCK );
- assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
-
- /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
- ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
- ** the PENDING_LOCK byte is temporary.
- */
- newLocktype = pFile->locktype;
- if( pFile->locktype==NO_LOCK
- || (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK)
- ){
- int cnt = 3;
- while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
- PENDING_BYTE, 0, 1, 0))==0 ){
- /* Try 3 times to get the pending lock. This is needed to work
- ** around problems caused by indexing and/or anti-virus software on
- ** Windows systems.
- ** If you are using this code as a model for alternative VFSes, do not
- ** copy this retry logic. It is a hack intended for Windows only.
- */
- lastErrno = osGetLastError();
- OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
- pFile->h, cnt, res));
- if( lastErrno==ERROR_INVALID_HANDLE ){
- pFile->lastErrno = lastErrno;
- rc = SQLITE_IOERR_LOCK;
- OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
- pFile->h, cnt, sqlite3ErrName(rc)));
- return rc;
- }
- if( cnt ) sqlite3_win32_sleep(1);
- }
- gotPendingLock = res;
- if( !res ){
- lastErrno = osGetLastError();
- }
- }
-
- /* Acquire a shared lock
- */
- if( locktype==SHARED_LOCK && res ){
- assert( pFile->locktype==NO_LOCK );
- res = winGetReadLock(pFile);
- if( res ){
- newLocktype = SHARED_LOCK;
- }else{
- lastErrno = osGetLastError();
- }
- }
-
- /* Acquire a RESERVED lock
- */
- if( locktype==RESERVED_LOCK && res ){
- assert( pFile->locktype==SHARED_LOCK );
- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
- if( res ){
- newLocktype = RESERVED_LOCK;
- }else{
- lastErrno = osGetLastError();
- }
- }
-
- /* Acquire a PENDING lock
- */
- if( locktype==EXCLUSIVE_LOCK && res ){
- newLocktype = PENDING_LOCK;
- gotPendingLock = 0;
- }
-
- /* Acquire an EXCLUSIVE lock
- */
- if( locktype==EXCLUSIVE_LOCK && res ){
- assert( pFile->locktype>=SHARED_LOCK );
- res = winUnlockReadLock(pFile);
- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
- SHARED_SIZE, 0);
- if( res ){
- newLocktype = EXCLUSIVE_LOCK;
- }else{
- lastErrno = osGetLastError();
- winGetReadLock(pFile);
- }
- }
-
- /* If we are holding a PENDING lock that ought to be released, then
- ** release it now.
- */
- if( gotPendingLock && locktype==SHARED_LOCK ){
- winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
- }
-
- /* Update the state of the lock has held in the file descriptor then
- ** return the appropriate result code.
- */
- if( res ){
- rc = SQLITE_OK;
- }else{
- pFile->lastErrno = lastErrno;
- rc = SQLITE_BUSY;
- OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
- pFile->h, locktype, newLocktype));
- }
- pFile->locktype = (u8)newLocktype;
- OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
- pFile->h, pFile->locktype, sqlite3ErrName(rc)));
- return rc;
-}
-
-/*
-** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, return
-** non-zero, otherwise zero.
-*/
-static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
- int res;
- winFile *pFile = (winFile*)id;
-
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
- OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut));
-
- assert( id!=0 );
- if( pFile->locktype>=RESERVED_LOCK ){
- res = 1;
- OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res));
- }else{
- res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE,0,1,0);
- if( res ){
- winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
- }
- res = !res;
- OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res));
- }
- *pResOut = res;
- OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
- pFile->h, pResOut, *pResOut));
- return SQLITE_OK;
-}
-
-/*
-** Lower the locking level on file descriptor id to locktype. locktype
-** must be either NO_LOCK or SHARED_LOCK.
-**
-** If the locking level of the file descriptor is already at or below
-** the requested locking level, this routine is a no-op.
-**
-** It is not possible for this routine to fail if the second argument
-** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
-** might return SQLITE_IOERR;
-*/
-static int winUnlock(sqlite3_file *id, int locktype){
- int type;
- winFile *pFile = (winFile*)id;
- int rc = SQLITE_OK;
- assert( pFile!=0 );
- assert( locktype<=SHARED_LOCK );
- OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n",
- pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
- type = pFile->locktype;
- if( type>=EXCLUSIVE_LOCK ){
- winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
- /* This should never happen. We should always be able to
- ** reacquire the read lock */
- rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
- "winUnlock", pFile->zPath);
- }
- }
- if( type>=RESERVED_LOCK ){
- winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
- }
- if( locktype==NO_LOCK && type>=SHARED_LOCK ){
- winUnlockReadLock(pFile);
- }
- if( type>=PENDING_LOCK ){
- winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
- }
- pFile->locktype = (u8)locktype;
- OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
- pFile->h, pFile->locktype, sqlite3ErrName(rc)));
- return rc;
-}
-
-/******************************************************************************
-****************************** No-op Locking **********************************
-**
-** Of the various locking implementations available, this is by far the
-** simplest: locking is ignored. No attempt is made to lock the database
-** file for reading or writing.
-**
-** This locking mode is appropriate for use on read-only databases
-** (ex: databases that are burned into CD-ROM, for example.) It can
-** also be used if the application employs some external mechanism to
-** prevent simultaneous access of the same database by two or more
-** database connections. But there is a serious risk of database
-** corruption if this locking mode is used in situations where multiple
-** database connections are accessing the same database file at the same
-** time and one or more of those connections are writing.
-*/
-
-static int winNolockLock(sqlite3_file *id, int locktype){
- UNUSED_PARAMETER(id);
- UNUSED_PARAMETER(locktype);
- return SQLITE_OK;
-}
-
-static int winNolockCheckReservedLock(sqlite3_file *id, int *pResOut){
- UNUSED_PARAMETER(id);
- UNUSED_PARAMETER(pResOut);
- return SQLITE_OK;
-}
-
-static int winNolockUnlock(sqlite3_file *id, int locktype){
- UNUSED_PARAMETER(id);
- UNUSED_PARAMETER(locktype);
- return SQLITE_OK;
-}
-
-/******************* End of the no-op lock implementation *********************
-******************************************************************************/
-
-/*
-** If *pArg is initially negative then this is a query. Set *pArg to
-** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
-**
-** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
-*/
-static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
- if( *pArg<0 ){
- *pArg = (pFile->ctrlFlags & mask)!=0;
- }else if( (*pArg)==0 ){
- pFile->ctrlFlags &= ~mask;
- }else{
- pFile->ctrlFlags |= mask;
- }
-}
-
-/* Forward references to VFS helper methods used for temporary files */
-static int winGetTempname(sqlite3_vfs *, char **);
-static int winIsDir(const void *);
-static BOOL winIsDriveLetterAndColon(const char *);
-
-/*
-** Control and query of the open file handle.
-*/
-static int winFileControl(sqlite3_file *id, int op, void *pArg){
- winFile *pFile = (winFile*)id;
- OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg));
- switch( op ){
- case SQLITE_FCNTL_LOCKSTATE: {
- *(int*)pArg = pFile->locktype;
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_LAST_ERRNO: {
- *(int*)pArg = (int)pFile->lastErrno;
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_CHUNK_SIZE: {
- pFile->szChunk = *(int *)pArg;
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_SIZE_HINT: {
- if( pFile->szChunk>0 ){
- sqlite3_int64 oldSz;
- int rc = winFileSize(id, &oldSz);
- if( rc==SQLITE_OK ){
- sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
- if( newSz>oldSz ){
- SimulateIOErrorBenign(1);
- rc = winTruncate(id, newSz);
- SimulateIOErrorBenign(0);
- }
- }
- OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
- return rc;
- }
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_PERSIST_WAL: {
- winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
- winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_VFSNAME: {
- *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_WIN32_AV_RETRY: {
- int *a = (int*)pArg;
- if( a[0]>0 ){
- winIoerrRetry = a[0];
- }else{
- a[0] = winIoerrRetry;
- }
- if( a[1]>0 ){
- winIoerrRetryDelay = a[1];
- }else{
- a[1] = winIoerrRetryDelay;
- }
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_WIN32_GET_HANDLE: {
- LPHANDLE phFile = (LPHANDLE)pArg;
- *phFile = pFile->h;
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
-#ifdef SQLITE_TEST
- case SQLITE_FCNTL_WIN32_SET_HANDLE: {
- LPHANDLE phFile = (LPHANDLE)pArg;
- HANDLE hOldFile = pFile->h;
- pFile->h = *phFile;
- *phFile = hOldFile;
- OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
- hOldFile, pFile->h));
- return SQLITE_OK;
- }
-#endif
- case SQLITE_FCNTL_TEMPFILENAME: {
- char *zTFile = 0;
- int rc = winGetTempname(pFile->pVfs, &zTFile);
- if( rc==SQLITE_OK ){
- *(char**)pArg = zTFile;
- }
- OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
- return rc;
- }
-#if SQLITE_MAX_MMAP_SIZE>0
- case SQLITE_FCNTL_MMAP_SIZE: {
- i64 newLimit = *(i64*)pArg;
- int rc = SQLITE_OK;
- if( newLimit>sqlite3GlobalConfig.mxMmap ){
- newLimit = sqlite3GlobalConfig.mxMmap;
- }
-
- /* The value of newLimit may be eventually cast to (SIZE_T) and passed
- ** to MapViewOfFile(). Restrict its value to 2GB if (SIZE_T) is not at
- ** least a 64-bit type. */
- if( newLimit>0 && sizeof(SIZE_T)<8 ){
- newLimit = (newLimit & 0x7FFFFFFF);
- }
-
- *(i64*)pArg = pFile->mmapSizeMax;
- if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
- pFile->mmapSizeMax = newLimit;
- if( pFile->mmapSize>0 ){
- winUnmapfile(pFile);
- rc = winMapfile(pFile, -1);
- }
- }
- OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
- return rc;
- }
-#endif
- }
- OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
- return SQLITE_NOTFOUND;
-}
-
-/*
-** Return the sector size in bytes of the underlying block device for
-** the specified file. This is almost always 512 bytes, but may be
-** larger for some devices.
-**
-** SQLite code assumes this function cannot fail. It also assumes that
-** if two files are created in the same file-system directory (i.e.
-** a database and its journal file) that the sector size will be the
-** same for both.
-*/
-static int winSectorSize(sqlite3_file *id){
- (void)id;
- return SQLITE_DEFAULT_SECTOR_SIZE;
-}
-
-/*
-** Return a vector of device characteristics.
-*/
-static int winDeviceCharacteristics(sqlite3_file *id){
- winFile *p = (winFile*)id;
- return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
- ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
-}
-
-/*
-** Windows will only let you create file view mappings
-** on allocation size granularity boundaries.
-** During sqlite3_os_init() we do a GetSystemInfo()
-** to get the granularity size.
-*/
-static SYSTEM_INFO winSysInfo;
-
-#ifndef SQLITE_OMIT_WAL
-
-/*
-** Helper functions to obtain and relinquish the global mutex. The
-** global mutex is used to protect the winLockInfo objects used by
-** this file, all of which may be shared by multiple threads.
-**
-** Function winShmMutexHeld() is used to assert() that the global mutex
-** is held when required. This function is only used as part of assert()
-** statements. e.g.
-**
-** winShmEnterMutex()
-** assert( winShmMutexHeld() );
-** winShmLeaveMutex()
-*/
-static sqlite3_mutex *winBigLock = 0;
-static void winShmEnterMutex(void){
- sqlite3_mutex_enter(winBigLock);
-}
-static void winShmLeaveMutex(void){
- sqlite3_mutex_leave(winBigLock);
-}
-#ifndef NDEBUG
-static int winShmMutexHeld(void) {
- return sqlite3_mutex_held(winBigLock);
-}
-#endif
-
-/*
-** Object used to represent a single file opened and mmapped to provide
-** shared memory. When multiple threads all reference the same
-** log-summary, each thread has its own winFile object, but they all
-** point to a single instance of this object. In other words, each
-** log-summary is opened only once per process.
-**
-** winShmMutexHeld() must be true when creating or destroying
-** this object or while reading or writing the following fields:
-**
-** nRef
-** pNext
-**
-** The following fields are read-only after the object is created:
-**
-** fid
-** zFilename
-**
-** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
-** winShmMutexHeld() is true when reading or writing any other field
-** in this structure.
-**
-*/
-struct winShmNode {
- sqlite3_mutex *mutex; /* Mutex to access this object */
- char *zFilename; /* Name of the file */
- winFile hFile; /* File handle from winOpen */
-
- int szRegion; /* Size of shared-memory regions */
- int nRegion; /* Size of array apRegion */
- u8 isReadonly; /* True if read-only */
- u8 isUnlocked; /* True if no DMS lock held */
-
- struct ShmRegion {
- HANDLE hMap; /* File handle from CreateFileMapping */
- void *pMap;
- } *aRegion;
- DWORD lastErrno; /* The Windows errno from the last I/O error */
-
- int nRef; /* Number of winShm objects pointing to this */
- winShm *pFirst; /* All winShm objects pointing to this */
- winShmNode *pNext; /* Next in list of all winShmNode objects */
-#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
- u8 nextShmId; /* Next available winShm.id value */
-#endif
-};
-
-/*
-** A global array of all winShmNode objects.
-**
-** The winShmMutexHeld() must be true while reading or writing this list.
-*/
-static winShmNode *winShmNodeList = 0;
-
-/*
-** Structure used internally by this VFS to record the state of an
-** open shared memory connection.
-**
-** The following fields are initialized when this object is created and
-** are read-only thereafter:
-**
-** winShm.pShmNode
-** winShm.id
-**
-** All other fields are read/write. The winShm.pShmNode->mutex must be held
-** while accessing any read/write fields.
-*/
-struct winShm {
- winShmNode *pShmNode; /* The underlying winShmNode object */
- winShm *pNext; /* Next winShm with the same winShmNode */
- u8 hasMutex; /* True if holding the winShmNode mutex */
- u16 sharedMask; /* Mask of shared locks held */
- u16 exclMask; /* Mask of exclusive locks held */
-#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
- u8 id; /* Id of this connection with its winShmNode */
-#endif
-};
-
-/*
-** Constants used for locking
-*/
-#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
-#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-
-/*
-** Apply advisory locks for all n bytes beginning at ofst.
-*/
-#define WINSHM_UNLCK 1
-#define WINSHM_RDLCK 2
-#define WINSHM_WRLCK 3
-static int winShmSystemLock(
- winShmNode *pFile, /* Apply locks to this open shared-memory segment */
- int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */
- int ofst, /* Offset to first byte to be locked/unlocked */
- int nByte /* Number of bytes to lock or unlock */
-){
- int rc = 0; /* Result code form Lock/UnlockFileEx() */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );
-
- OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
- pFile->hFile.h, lockType, ofst, nByte));
-
- /* Release/Acquire the system-level lock */
- if( lockType==WINSHM_UNLCK ){
- rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
- }else{
- /* Initialize the locking parameters */
- DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
- if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
- rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
- }
-
- if( rc!= 0 ){
- rc = SQLITE_OK;
- }else{
- pFile->lastErrno = osGetLastError();
- rc = SQLITE_BUSY;
- }
-
- OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
- pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" :
- "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
-
- return rc;
-}
-
-/* Forward references to VFS methods */
-static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
-static int winDelete(sqlite3_vfs *,const char*,int);
-
-/*
-** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
-**
-** This is not a VFS shared-memory method; it is a utility function called
-** by VFS shared-memory methods.
-*/
-static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
- winShmNode **pp;
- winShmNode *p;
- assert( winShmMutexHeld() );
- OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
- osGetCurrentProcessId(), deleteFlag));
- pp = &winShmNodeList;
- while( (p = *pp)!=0 ){
- if( p->nRef==0 ){
- int i;
- if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
- for(i=0; i<p->nRegion; i++){
- BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
- OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
- osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
- UNUSED_VARIABLE_VALUE(bRc);
- bRc = osCloseHandle(p->aRegion[i].hMap);
- OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
- osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
- UNUSED_VARIABLE_VALUE(bRc);
- }
- if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
- SimulateIOErrorBenign(1);
- winClose((sqlite3_file *)&p->hFile);
- SimulateIOErrorBenign(0);
- }
- if( deleteFlag ){
- SimulateIOErrorBenign(1);
- sqlite3BeginBenignMalloc();
- winDelete(pVfs, p->zFilename, 0);
- sqlite3EndBenignMalloc();
- SimulateIOErrorBenign(0);
- }
- *pp = p->pNext;
- sqlite3_free(p->aRegion);
- sqlite3_free(p);
- }else{
- pp = &p->pNext;
- }
- }
-}
-
-/*
-** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
-** take it now. Return SQLITE_OK if successful, or an SQLite error
-** code otherwise.
-**
-** If the DMS cannot be locked because this is a readonly_shm=1
-** connection and no other process already holds a lock, return
-** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
-*/
-static int winLockSharedMemory(winShmNode *pShmNode){
- int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
-
- if( rc==SQLITE_OK ){
- if( pShmNode->isReadonly ){
- pShmNode->isUnlocked = 1;
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return SQLITE_READONLY_CANTINIT;
- }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
- "winLockSharedMemory", pShmNode->zFilename);
- }
- }
-
- if( rc==SQLITE_OK ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- }
-
- return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
-}
-
-/*
-** Open the shared-memory area associated with database file pDbFd.
-**
-** When opening a new shared-memory file, if no other instances of that
-** file are currently open, in this process or in other processes, then
-** the file must be truncated to zero length or have its header cleared.
-*/
-static int winOpenSharedMemory(winFile *pDbFd){
- struct winShm *p; /* The connection to be opened */
- winShmNode *pShmNode = 0; /* The underlying mmapped file */
- int rc = SQLITE_OK; /* Result code */
- winShmNode *pNew; /* Newly allocated winShmNode */
- int nName; /* Size of zName in bytes */
-
- assert( pDbFd->pShm==0 ); /* Not previously opened */
-
- /* Allocate space for the new sqlite3_shm object. Also speculatively
- ** allocate space for a new winShmNode and filename.
- */
- p = sqlite3MallocZero( sizeof(*p) );
- if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT;
- nName = sqlite3Strlen30(pDbFd->zPath);
- pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
- if( pNew==0 ){
- sqlite3_free(p);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- pNew->zFilename = (char*)&pNew[1];
- sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
- sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
-
- /* Look to see if there is an existing winShmNode that can be used.
- ** If no matching winShmNode currently exists, create a new one.
- */
- winShmEnterMutex();
- for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
- /* TBD need to come up with better match here. Perhaps
- ** use FILE_ID_BOTH_DIR_INFO Structure.
- */
- if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
- }
- if( pShmNode ){
- sqlite3_free(pNew);
- }else{
- int inFlags = SQLITE_OPEN_WAL;
- int outFlags = 0;
-
- pShmNode = pNew;
- pNew = 0;
- ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
- pShmNode->pNext = winShmNodeList;
- winShmNodeList = pShmNode;
-
- if( sqlite3GlobalConfig.bCoreMutex ){
- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
- rc = SQLITE_IOERR_NOMEM_BKPT;
- goto shm_open_err;
- }
- }
-
- if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
- }else{
- inFlags |= SQLITE_OPEN_READONLY;
- }
- rc = winOpen(pDbFd->pVfs, pShmNode->zFilename,
- (sqlite3_file*)&pShmNode->hFile,
- inFlags, &outFlags);
- if( rc!=SQLITE_OK ){
- rc = winLogError(rc, osGetLastError(), "winOpenShm",
- pShmNode->zFilename);
- goto shm_open_err;
- }
- if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1;
-
- rc = winLockSharedMemory(pShmNode);
- if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
- }
-
- /* Make the new connection a child of the winShmNode */
- p->pShmNode = pShmNode;
-#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
- p->id = pShmNode->nextShmId++;
-#endif
- pShmNode->nRef++;
- pDbFd->pShm = p;
- winShmLeaveMutex();
-
- /* The reference count on pShmNode has already been incremented under
- ** the cover of the winShmEnterMutex() mutex and the pointer from the
- ** new (struct winShm) object to the pShmNode has been set. All that is
- ** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
- */
- sqlite3_mutex_enter(pShmNode->mutex);
- p->pNext = pShmNode->pFirst;
- pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
-
- /* Jump here on any error */
-shm_open_err:
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
- sqlite3_free(p);
- sqlite3_free(pNew);
- winShmLeaveMutex();
- return rc;
-}
-
-/*
-** Close a connection to shared-memory. Delete the underlying
-** storage if deleteFlag is true.
-*/
-static int winShmUnmap(
- sqlite3_file *fd, /* Database holding shared memory */
- int deleteFlag /* Delete after closing if true */
-){
- winFile *pDbFd; /* Database holding shared-memory */
- winShm *p; /* The connection to be closed */
- winShmNode *pShmNode; /* The underlying shared-memory file */
- winShm **pp; /* For looping over sibling connections */
-
- pDbFd = (winFile*)fd;
- p = pDbFd->pShm;
- if( p==0 ) return SQLITE_OK;
- pShmNode = p->pShmNode;
-
- /* Remove connection p from the set of connections associated
- ** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
- for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
- *pp = p->pNext;
-
- /* Free the connection p */
- sqlite3_free(p);
- pDbFd->pShm = 0;
- sqlite3_mutex_leave(pShmNode->mutex);
-
- /* If pShmNode->nRef has reached 0, then close the underlying
- ** shared-memory file, too */
- winShmEnterMutex();
- assert( pShmNode->nRef>0 );
- pShmNode->nRef--;
- if( pShmNode->nRef==0 ){
- winShmPurge(pDbFd->pVfs, deleteFlag);
- }
- winShmLeaveMutex();
-
- return SQLITE_OK;
-}
-
-/*
-** Change the lock state for a shared-memory segment.
-*/
-static int winShmLock(
- sqlite3_file *fd, /* Database file holding the shared memory */
- int ofst, /* First lock to acquire or release */
- int n, /* Number of locks to acquire or release */
- int flags /* What to do with the lock */
-){
- winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
- winShm *p = pDbFd->pShm; /* The shared memory being locked */
- winShm *pX; /* For looping over all siblings */
- winShmNode *pShmNode = p->pShmNode;
- int rc = SQLITE_OK; /* Result code */
- u16 mask; /* Mask of locks to take or release */
-
- assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
- assert( n>=1 );
- assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
- || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
- || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
- || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
- assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
-
- mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
- assert( n>1 || mask==(1<<ofst) );
- sqlite3_mutex_enter(pShmNode->mutex);
- if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
-
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
-
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
-
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
- }else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
-
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- allShared |= pX->sharedMask;
- }
-
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
- }
-
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
- }
- }else{
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- }
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- if( rc==SQLITE_OK ){
- rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n);
- if( rc==SQLITE_OK ){
- assert( (p->sharedMask & mask)==0 );
- p->exclMask |= mask;
- }
- }
- }
- sqlite3_mutex_leave(pShmNode->mutex);
- OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
- osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
- sqlite3ErrName(rc)));
- return rc;
-}
-
-/*
-** Implement a memory barrier or memory fence on shared memory.
-**
-** All loads and stores begun before the barrier must complete before
-** any load or store begun after the barrier.
-*/
-static void winShmBarrier(
- sqlite3_file *fd /* Database holding the shared memory */
-){
- UNUSED_PARAMETER(fd);
- sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
- winShmEnterMutex(); /* Also mutex, for redundancy */
- winShmLeaveMutex();
-}
-
-/*
-** This function is called to obtain a pointer to region iRegion of the
-** shared-memory associated with the database file fd. Shared-memory regions
-** are numbered starting from zero. Each shared-memory region is szRegion
-** bytes in size.
-**
-** If an error occurs, an error code is returned and *pp is set to NULL.
-**
-** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
-** region has not been allocated (by any client, including one running in a
-** separate process), then *pp is set to NULL and SQLITE_OK returned. If
-** isWrite is non-zero and the requested shared-memory region has not yet
-** been allocated, it is allocated by this function.
-**
-** If the shared-memory region has already been allocated or is allocated by
-** this call as described above, then it is mapped into this processes
-** address space (if it is not already), *pp is set to point to the mapped
-** memory and SQLITE_OK returned.
-*/
-static int winShmMap(
- sqlite3_file *fd, /* Handle open on database file */
- int iRegion, /* Region to retrieve */
- int szRegion, /* Size of regions */
- int isWrite, /* True to extend file if necessary */
- void volatile **pp /* OUT: Mapped memory */
-){
- winFile *pDbFd = (winFile*)fd;
- winShm *pShm = pDbFd->pShm;
- winShmNode *pShmNode;
- DWORD protect = PAGE_READWRITE;
- DWORD flags = FILE_MAP_WRITE | FILE_MAP_READ;
- int rc = SQLITE_OK;
-
- if( !pShm ){
- rc = winOpenSharedMemory(pDbFd);
- if( rc!=SQLITE_OK ) return rc;
- pShm = pDbFd->pShm;
- }
- pShmNode = pShm->pShmNode;
-
- sqlite3_mutex_enter(pShmNode->mutex);
- if( pShmNode->isUnlocked ){
- rc = winLockSharedMemory(pShmNode);
- if( rc!=SQLITE_OK ) goto shmpage_out;
- pShmNode->isUnlocked = 0;
- }
- assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
-
- if( pShmNode->nRegion<=iRegion ){
- struct ShmRegion *apNew; /* New aRegion[] array */
- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
- sqlite3_int64 sz; /* Current size of wal-index file */
-
- pShmNode->szRegion = szRegion;
-
- /* The requested region is not mapped into this processes address space.
- ** Check to see if it has been allocated (i.e. if the wal-index file is
- ** large enough to contain the requested region).
- */
- rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
- if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap1", pDbFd->zPath);
- goto shmpage_out;
- }
-
- if( sz<nByte ){
- /* The requested memory region does not exist. If isWrite is set to
- ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
- **
- ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
- ** the requested memory region.
- */
- if( !isWrite ) goto shmpage_out;
- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
- if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap2", pDbFd->zPath);
- goto shmpage_out;
- }
- }
-
- /* Map the requested memory region into this processes address space. */
- apNew = (struct ShmRegion *)sqlite3_realloc64(
- pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
- );
- if( !apNew ){
- rc = SQLITE_IOERR_NOMEM_BKPT;
- goto shmpage_out;
- }
- pShmNode->aRegion = apNew;
-
- if( pShmNode->isReadonly ){
- protect = PAGE_READONLY;
- flags = FILE_MAP_READ;
- }
-
- while( pShmNode->nRegion<=iRegion ){
- HANDLE hMap = NULL; /* file-mapping handle */
- void *pMap = 0; /* Mapped memory region */
-
-#if SQLITE_OS_WINRT
- hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
- NULL, protect, nByte, NULL
- );
-#elif defined(SQLITE_WIN32_HAS_WIDE)
- hMap = osCreateFileMappingW(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
-#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
- hMap = osCreateFileMappingA(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
-#endif
- OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
- osGetCurrentProcessId(), pShmNode->nRegion, nByte,
- hMap ? "ok" : "failed"));
- if( hMap ){
- int iOffset = pShmNode->nRegion*szRegion;
- int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
-#if SQLITE_OS_WINRT
- pMap = osMapViewOfFileFromApp(hMap, flags,
- iOffset - iOffsetShift, szRegion + iOffsetShift
- );
-#else
- pMap = osMapViewOfFile(hMap, flags,
- 0, iOffset - iOffsetShift, szRegion + iOffsetShift
- );
-#endif
- OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
- osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
- szRegion, pMap ? "ok" : "failed"));
- }
- if( !pMap ){
- pShmNode->lastErrno = osGetLastError();
- rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
- "winShmMap3", pDbFd->zPath);
- if( hMap ) osCloseHandle(hMap);
- goto shmpage_out;
- }
-
- pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
- pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
- pShmNode->nRegion++;
- }
- }
-
-shmpage_out:
- if( pShmNode->nRegion>iRegion ){
- int iOffset = iRegion*szRegion;
- int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
- char *p = (char *)pShmNode->aRegion[iRegion].pMap;
- *pp = (void *)&p[iOffsetShift];
- }else{
- *pp = 0;
- }
- if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
-}
-
-#else
-# define winShmMap 0
-# define winShmLock 0
-# define winShmBarrier 0
-# define winShmUnmap 0
-#endif /* #ifndef SQLITE_OMIT_WAL */
-
-/*
-** Cleans up the mapped region of the specified file, if any.
-*/
-#if SQLITE_MAX_MMAP_SIZE>0
-static int winUnmapfile(winFile *pFile){
- assert( pFile!=0 );
- OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
- "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
- osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
- pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
- if( pFile->pMapRegion ){
- if( !osUnmapViewOfFile(pFile->pMapRegion) ){
- pFile->lastErrno = osGetLastError();
- OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, "
- "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
- pFile->pMapRegion));
- return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
- "winUnmapfile1", pFile->zPath);
- }
- pFile->pMapRegion = 0;
- pFile->mmapSize = 0;
- pFile->mmapSizeActual = 0;
- }
- if( pFile->hMap!=NULL ){
- if( !osCloseHandle(pFile->hMap) ){
- pFile->lastErrno = osGetLastError();
- OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
- osGetCurrentProcessId(), pFile, pFile->hMap));
- return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
- "winUnmapfile2", pFile->zPath);
- }
- pFile->hMap = NULL;
- }
- OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), pFile));
- return SQLITE_OK;
-}
-
-/*
-** Memory map or remap the file opened by file-descriptor pFd (if the file
-** is already mapped, the existing mapping is replaced by the new). Or, if
-** there already exists a mapping for this file, and there are still
-** outstanding xFetch() references to it, this function is a no-op.
-**
-** If parameter nByte is non-negative, then it is the requested size of
-** the mapping to create. Otherwise, if nByte is less than zero, then the
-** requested size is the size of the file on disk. The actual size of the
-** created mapping is either the requested size or the value configured
-** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
-**
-** SQLITE_OK is returned if no error occurs (even if the mapping is not
-** recreated as a result of outstanding references) or an SQLite error
-** code otherwise.
-*/
-static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
- sqlite3_int64 nMap = nByte;
- int rc;
-
- assert( nMap>=0 || pFd->nFetchOut==0 );
- OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n",
- osGetCurrentProcessId(), pFd, nByte));
-
- if( pFd->nFetchOut>0 ) return SQLITE_OK;
-
- if( nMap<0 ){
- rc = winFileSize((sqlite3_file*)pFd, &nMap);
- if( rc ){
- OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n",
- osGetCurrentProcessId(), pFd));
- return SQLITE_IOERR_FSTAT;
- }
- }
- if( nMap>pFd->mmapSizeMax ){
- nMap = pFd->mmapSizeMax;
- }
- nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
-
- if( nMap==0 && pFd->mmapSize>0 ){
- winUnmapfile(pFd);
- }
- if( nMap!=pFd->mmapSize ){
- void *pNew = 0;
- DWORD protect = PAGE_READONLY;
- DWORD flags = FILE_MAP_READ;
-
- winUnmapfile(pFd);
-#ifdef SQLITE_MMAP_READWRITE
- if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
- protect = PAGE_READWRITE;
- flags |= FILE_MAP_WRITE;
- }
-#endif
-#if SQLITE_OS_WINRT
- pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
-#elif defined(SQLITE_WIN32_HAS_WIDE)
- pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
- (DWORD)((nMap>>32) & 0xffffffff),
- (DWORD)(nMap & 0xffffffff), NULL);
-#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
- pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
- (DWORD)((nMap>>32) & 0xffffffff),
- (DWORD)(nMap & 0xffffffff), NULL);
-#endif
- if( pFd->hMap==NULL ){
- pFd->lastErrno = osGetLastError();
- rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
- "winMapfile1", pFd->zPath);
- /* Log the error, but continue normal operation using xRead/xWrite */
- OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=%s\n",
- osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
- return SQLITE_OK;
- }
- assert( (nMap % winSysInfo.dwPageSize)==0 );
- assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
-#if SQLITE_OS_WINRT
- pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap);
-#else
- pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
-#endif
- if( pNew==NULL ){
- osCloseHandle(pFd->hMap);
- pFd->hMap = NULL;
- pFd->lastErrno = osGetLastError();
- rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
- "winMapfile2", pFd->zPath);
- /* Log the error, but continue normal operation using xRead/xWrite */
- OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=%s\n",
- osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
- return SQLITE_OK;
- }
- pFd->pMapRegion = pNew;
- pFd->mmapSize = nMap;
- pFd->mmapSizeActual = nMap;
- }
-
- OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), pFd));
- return SQLITE_OK;
-}
-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-
-/*
-** If possible, return a pointer to a mapping of file fd starting at offset
-** iOff. The mapping must be valid for at least nAmt bytes.
-**
-** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
-** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
-** Finally, if an error does occur, return an SQLite error code. The final
-** value of *pp is undefined in this case.
-**
-** If this function does return a pointer, the caller must eventually
-** release the reference by calling winUnfetch().
-*/
-static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
-#if SQLITE_MAX_MMAP_SIZE>0
- winFile *pFd = (winFile*)fd; /* The underlying database file */
-#endif
- *pp = 0;
-
- OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n",
- osGetCurrentProcessId(), fd, iOff, nAmt, pp));
-
-#if SQLITE_MAX_MMAP_SIZE>0
- if( pFd->mmapSizeMax>0 ){
- if( pFd->pMapRegion==0 ){
- int rc = winMapfile(pFd, -1);
- if( rc!=SQLITE_OK ){
- OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n",
- osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
- return rc;
- }
- }
- if( pFd->mmapSize >= iOff+nAmt ){
- *pp = &((u8 *)pFd->pMapRegion)[iOff];
- pFd->nFetchOut++;
- }
- }
-#endif
-
- OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), fd, pp, *pp));
- return SQLITE_OK;
-}
-
-/*
-** If the third argument is non-NULL, then this function releases a
-** reference obtained by an earlier call to winFetch(). The second
-** argument passed to this function must be the same as the corresponding
-** argument that was passed to the winFetch() invocation.
-**
-** Or, if the third argument is NULL, then this function is being called
-** to inform the VFS layer that, according to POSIX, any existing mapping
-** may now be invalid and should be unmapped.
-*/
-static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
-#if SQLITE_MAX_MMAP_SIZE>0
- winFile *pFd = (winFile*)fd; /* The underlying database file */
-
- /* If p==0 (unmap the entire file) then there must be no outstanding
- ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
- ** then there must be at least one outstanding. */
- assert( (p==0)==(pFd->nFetchOut==0) );
-
- /* If p!=0, it must match the iOff value. */
- assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
-
- OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n",
- osGetCurrentProcessId(), pFd, iOff, p));
-
- if( p ){
- pFd->nFetchOut--;
- }else{
- /* FIXME: If Windows truly always prevents truncating or deleting a
- ** file while a mapping is held, then the following winUnmapfile() call
- ** is unnecessary can be omitted - potentially improving
- ** performance. */
- winUnmapfile(pFd);
- }
-
- assert( pFd->nFetchOut>=0 );
-#endif
-
- OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n",
- osGetCurrentProcessId(), fd));
- return SQLITE_OK;
-}
-
-/*
-** Here ends the implementation of all sqlite3_file methods.
-**
-********************** End sqlite3_file Methods *******************************
-******************************************************************************/
-
-/*
-** This vector defines all the methods that can operate on an
-** sqlite3_file for win32.
-*/
-static const sqlite3_io_methods winIoMethod = {
- 3, /* iVersion */
- winClose, /* xClose */
- winRead, /* xRead */
- winWrite, /* xWrite */
- winTruncate, /* xTruncate */
- winSync, /* xSync */
- winFileSize, /* xFileSize */
- winLock, /* xLock */
- winUnlock, /* xUnlock */
- winCheckReservedLock, /* xCheckReservedLock */
- winFileControl, /* xFileControl */
- winSectorSize, /* xSectorSize */
- winDeviceCharacteristics, /* xDeviceCharacteristics */
- winShmMap, /* xShmMap */
- winShmLock, /* xShmLock */
- winShmBarrier, /* xShmBarrier */
- winShmUnmap, /* xShmUnmap */
- winFetch, /* xFetch */
- winUnfetch /* xUnfetch */
-};
-
-/*
-** This vector defines all the methods that can operate on an
-** sqlite3_file for win32 without performing any locking.
-*/
-static const sqlite3_io_methods winIoNolockMethod = {
- 3, /* iVersion */
- winClose, /* xClose */
- winRead, /* xRead */
- winWrite, /* xWrite */
- winTruncate, /* xTruncate */
- winSync, /* xSync */
- winFileSize, /* xFileSize */
- winNolockLock, /* xLock */
- winNolockUnlock, /* xUnlock */
- winNolockCheckReservedLock, /* xCheckReservedLock */
- winFileControl, /* xFileControl */
- winSectorSize, /* xSectorSize */
- winDeviceCharacteristics, /* xDeviceCharacteristics */
- winShmMap, /* xShmMap */
- winShmLock, /* xShmLock */
- winShmBarrier, /* xShmBarrier */
- winShmUnmap, /* xShmUnmap */
- winFetch, /* xFetch */
- winUnfetch /* xUnfetch */
-};
-
-static winVfsAppData winAppData = {
- &winIoMethod, /* pMethod */
- 0, /* pAppData */
- 0 /* bNoLock */
-};
-
-static winVfsAppData winNolockAppData = {
- &winIoNolockMethod, /* pMethod */
- 0, /* pAppData */
- 1 /* bNoLock */
-};
-
-/****************************************************************************
-**************************** sqlite3_vfs methods ****************************
-**
-** This division contains the implementation of methods on the
-** sqlite3_vfs object.
-*/
-
-#if defined(__CYGWIN__)
-/*
-** Convert a filename from whatever the underlying operating system
-** supports for filenames into UTF-8. Space to hold the result is
-** obtained from malloc and must be freed by the calling function.
-*/
-static char *winConvertToUtf8Filename(const void *zFilename){
- char *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUnicodeToUtf8(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-#endif
-
-/*
-** Convert a UTF-8 filename into whatever form the underlying
-** operating system wants filenames in. Space to hold the result
-** is obtained from malloc and must be freed by the calling
-** function.
-*/
-static void *winConvertFromUtf8Filename(const char *zFilename){
- void *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUtf8ToUnicode(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-
-/*
-** This function returns non-zero if the specified UTF-8 string buffer
-** ends with a directory separator character or one was successfully
-** added to it.
-*/
-static int winMakeEndInDirSep(int nBuf, char *zBuf){
- if( zBuf ){
- int nLen = sqlite3Strlen30(zBuf);
- if( nLen>0 ){
- if( winIsDirSep(zBuf[nLen-1]) ){
- return 1;
- }else if( nLen+1<nBuf ){
- zBuf[nLen] = winGetDirSep();
- zBuf[nLen+1] = '\0';
- return 1;
- }
- }
- }
- return 0;
-}
-
-/*
-** Create a temporary file name and store the resulting pointer into pzBuf.
-** The pointer returned in pzBuf must be freed via sqlite3_free().
-*/
-static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
- static char zChars[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789";
- size_t i, j;
- int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX);
- int nMax, nBuf, nDir, nLen;
- char *zBuf;
-
- /* It's odd to simulate an io-error here, but really this is just
- ** using the io-error infrastructure to test that SQLite handles this
- ** function failing.
- */
- SimulateIOError( return SQLITE_IOERR );
-
- /* Allocate a temporary buffer to store the fully qualified file
- ** name for the temporary file. If this fails, we cannot continue.
- */
- nMax = pVfs->mxPathname; nBuf = nMax + 2;
- zBuf = sqlite3MallocZero( nBuf );
- if( !zBuf ){
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
-
- /* Figure out the effective temporary directory. First, check if one
- ** has been explicitly set by the application; otherwise, use the one
- ** configured by the operating system.
- */
- nDir = nMax - (nPre + 15);
- assert( nDir>0 );
- if( sqlite3_temp_directory ){
- int nDirLen = sqlite3Strlen30(sqlite3_temp_directory);
- if( nDirLen>0 ){
- if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){
- nDirLen++;
- }
- if( nDirLen>nDir ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
- return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0);
- }
- sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory);
- }
- }
-#if defined(__CYGWIN__)
- else{
- static const char *azDirs[] = {
- 0, /* getenv("SQLITE_TMPDIR") */
- 0, /* getenv("TMPDIR") */
- 0, /* getenv("TMP") */
- 0, /* getenv("TEMP") */
- 0, /* getenv("USERPROFILE") */
- "/var/tmp",
- "/usr/tmp",
- "/tmp",
- ".",
- 0 /* List terminator */
- };
- unsigned int i;
- const char *zDir = 0;
-
- if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
- if( !azDirs[2] ) azDirs[2] = getenv("TMP");
- if( !azDirs[3] ) azDirs[3] = getenv("TEMP");
- if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE");
- for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
- void *zConverted;
- if( zDir==0 ) continue;
- /* If the path starts with a drive letter followed by the colon
- ** character, assume it is already a native Win32 path; otherwise,
- ** it must be converted to a native Win32 path via the Cygwin API
- ** prior to using it.
- */
- if( winIsDriveLetterAndColon(zDir) ){
- zConverted = winConvertFromUtf8Filename(zDir);
- if( !zConverted ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( winIsDir(zConverted) ){
- sqlite3_snprintf(nMax, zBuf, "%s", zDir);
- sqlite3_free(zConverted);
- break;
- }
- sqlite3_free(zConverted);
- }else{
- zConverted = sqlite3MallocZero( nMax+1 );
- if( !zConverted ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
- zConverted, nMax+1)<0 ){
- sqlite3_free(zConverted);
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
- return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
- "winGetTempname2", zDir);
- }
- if( winIsDir(zConverted) ){
- /* At this point, we know the candidate directory exists and should
- ** be used. However, we may need to convert the string containing
- ** its name into UTF-8 (i.e. if it is UTF-16 right now).
- */
- char *zUtf8 = winConvertToUtf8Filename(zConverted);
- if( !zUtf8 ){
- sqlite3_free(zConverted);
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zConverted);
- break;
- }
- sqlite3_free(zConverted);
- }
- }
- }
-#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
- else if( osIsNT() ){
- char *zMulti;
- LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) );
- if( !zWidePath ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( osGetTempPathW(nMax, zWidePath)==0 ){
- sqlite3_free(zWidePath);
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
- return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
- "winGetTempname2", 0);
- }
- zMulti = winUnicodeToUtf8(zWidePath);
- if( zMulti ){
- sqlite3_snprintf(nMax, zBuf, "%s", zMulti);
- sqlite3_free(zMulti);
- sqlite3_free(zWidePath);
- }else{
- sqlite3_free(zWidePath);
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- char *zUtf8;
- char *zMbcsPath = sqlite3MallocZero( nMax );
- if( !zMbcsPath ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( osGetTempPathA(nMax, zMbcsPath)==0 ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
- return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
- "winGetTempname3", 0);
- }
- zUtf8 = winMbcsToUtf8(zMbcsPath, osAreFileApisANSI());
- if( zUtf8 ){
- sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
- sqlite3_free(zUtf8);
- }else{
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- }
-#endif /* SQLITE_WIN32_HAS_ANSI */
-#endif /* !SQLITE_OS_WINRT */
-
- /*
- ** Check to make sure the temporary directory ends with an appropriate
- ** separator. If it does not and there is not enough space left to add
- ** one, fail.
- */
- if( !winMakeEndInDirSep(nDir+1, zBuf) ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
- return winLogError(SQLITE_ERROR, 0, "winGetTempname4", 0);
- }
-
- /*
- ** Check that the output buffer is large enough for the temporary file
- ** name in the following format:
- **
- ** "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0"
- **
- ** If not, return SQLITE_ERROR. The number 17 is used here in order to
- ** account for the space used by the 15 character random suffix and the
- ** two trailing NUL characters. The final directory separator character
- ** has already added if it was not already present.
- */
- nLen = sqlite3Strlen30(zBuf);
- if( (nLen + nPre + 17) > nBuf ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
- return winLogError(SQLITE_ERROR, 0, "winGetTempname5", 0);
- }
-
- sqlite3_snprintf(nBuf-16-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX);
-
- j = sqlite3Strlen30(zBuf);
- sqlite3_randomness(15, &zBuf[j]);
- for(i=0; i<15; i++, j++){
- zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
- }
- zBuf[j] = 0;
- zBuf[j+1] = 0;
- *pzBuf = zBuf;
-
- OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the named file is really a directory. Return false if
-** it is something other than a directory, or if there is any kind of memory
-** allocation failure.
-*/
-static int winIsDir(const void *zConverted){
- DWORD attr;
- int rc = 0;
- DWORD lastErrno;
-
- if( osIsNT() ){
- int cnt = 0;
- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
- memset(&sAttrData, 0, sizeof(sAttrData));
- while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
- GetFileExInfoStandard,
- &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
- if( !rc ){
- return 0; /* Invalid name? */
- }
- attr = sAttrData.dwFileAttributes;
-#if SQLITE_OS_WINCE==0
- }else{
- attr = osGetFileAttributesA((char*)zConverted);
-#endif
- }
- return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
-}
-
-/* forward reference */
-static int winAccess(
- sqlite3_vfs *pVfs, /* Not used on win32 */
- const char *zFilename, /* Name of file to check */
- int flags, /* Type of test to make on this file */
- int *pResOut /* OUT: Result */
-);
-
-/*
-** Open a file.
-*/
-static int winOpen(
- sqlite3_vfs *pVfs, /* Used to get maximum path length and AppData */
- const char *zName, /* Name of the file (UTF-8) */
- sqlite3_file *id, /* Write the SQLite file handle here */
- int flags, /* Open mode flags */
- int *pOutFlags /* Status return flags */
-){
- HANDLE h;
- DWORD lastErrno = 0;
- DWORD dwDesiredAccess;
- DWORD dwShareMode;
- DWORD dwCreationDisposition;
- DWORD dwFlagsAndAttributes = 0;
-#if SQLITE_OS_WINCE
- int isTemp = 0;
-#endif
- winVfsAppData *pAppData;
- winFile *pFile = (winFile*)id;
- void *zConverted; /* Filename in OS encoding */
- const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
- int cnt = 0;
-
- /* If argument zPath is a NULL pointer, this function is required to open
- ** a temporary file. Use this buffer to store the file name in.
- */
- char *zTmpname = 0; /* For temporary filename, if necessary. */
-
- int rc = SQLITE_OK; /* Function Return Code */
-#if !defined(NDEBUG) || SQLITE_OS_WINCE
- int eType = flags&0xFFFFFF00; /* Type of file to open */
-#endif
-
- int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
- int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
- int isCreate = (flags & SQLITE_OPEN_CREATE);
- int isReadonly = (flags & SQLITE_OPEN_READONLY);
- int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
-
-#ifndef NDEBUG
- int isOpenJournal = (isCreate && (
- eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_MAIN_JOURNAL
- || eType==SQLITE_OPEN_WAL
- ));
-#endif
-
- OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
- zUtf8Name, id, flags, pOutFlags));
-
- /* Check the following statements are true:
- **
- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
- ** (b) if CREATE is set, then READWRITE must also be set, and
- ** (c) if EXCLUSIVE is set, then CREATE must also be set.
- ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
- */
- assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
- assert(isCreate==0 || isReadWrite);
- assert(isExclusive==0 || isCreate);
- assert(isDelete==0 || isCreate);
-
- /* The main DB, main journal, WAL file and master journal are never
- ** automatically deleted. Nor are they ever temporary files. */
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
-
- /* Assert that the upper layer has set one of the "file-type" flags. */
- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
- );
-
- assert( pFile!=0 );
- memset(pFile, 0, sizeof(winFile));
- pFile->h = INVALID_HANDLE_VALUE;
-
-#if SQLITE_OS_WINRT
- if( !zUtf8Name && !sqlite3_temp_directory ){
- sqlite3_log(SQLITE_ERROR,
- "sqlite3_temp_directory variable should be set for WinRT");
- }
-#endif
-
- /* If the second argument to this function is NULL, generate a
- ** temporary file name to use
- */
- if( !zUtf8Name ){
- assert( isDelete && !isOpenJournal );
- rc = winGetTempname(pVfs, &zTmpname);
- if( rc!=SQLITE_OK ){
- OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
- return rc;
- }
- zUtf8Name = zTmpname;
- }
-
- /* Database filenames are double-zero terminated if they are not
- ** URIs with parameters. Hence, they can always be passed into
- ** sqlite3_uri_parameter().
- */
- assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
- zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 );
-
- /* Convert the filename to the system encoding. */
- zConverted = winConvertFromUtf8Filename(zUtf8Name);
- if( zConverted==0 ){
- sqlite3_free(zTmpname);
- OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
-
- if( winIsDir(zConverted) ){
- sqlite3_free(zConverted);
- sqlite3_free(zTmpname);
- OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
- return SQLITE_CANTOPEN_ISDIR;
- }
-
- if( isReadWrite ){
- dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
- }else{
- dwDesiredAccess = GENERIC_READ;
- }
-
- /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
- ** created. SQLite doesn't use it to indicate "exclusive access"
- ** as it is usually understood.
- */
- if( isExclusive ){
- /* Creates a new file, only if it does not already exist. */
- /* If the file exists, it fails. */
- dwCreationDisposition = CREATE_NEW;
- }else if( isCreate ){
- /* Open existing file, or create if it doesn't exist */
- dwCreationDisposition = OPEN_ALWAYS;
- }else{
- /* Opens a file, only if it exists. */
- dwCreationDisposition = OPEN_EXISTING;
- }
-
- dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
-
- if( isDelete ){
-#if SQLITE_OS_WINCE
- dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
- isTemp = 1;
-#else
- dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
- | FILE_ATTRIBUTE_HIDDEN
- | FILE_FLAG_DELETE_ON_CLOSE;
-#endif
- }else{
- dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
- }
- /* Reports from the internet are that performance is always
- ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
-#if SQLITE_OS_WINCE
- dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
-#endif
-
- if( osIsNT() ){
-#if SQLITE_OS_WINRT
- CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
- extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
- extendedParameters.dwFileAttributes =
- dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
- extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
- extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
- extendedParameters.lpSecurityAttributes = NULL;
- extendedParameters.hTemplateFile = NULL;
- do{
- h = osCreateFile2((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode,
- dwCreationDisposition,
- &extendedParameters);
- if( h!=INVALID_HANDLE_VALUE ) break;
- if( isReadWrite ){
- int rc2, isRO = 0;
- sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
- sqlite3EndBenignMalloc();
- if( rc2==SQLITE_OK && isRO ) break;
- }
- }while( winRetryIoerr(&cnt, &lastErrno) );
-#else
- do{
- h = osCreateFileW((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL);
- if( h!=INVALID_HANDLE_VALUE ) break;
- if( isReadWrite ){
- int rc2, isRO = 0;
- sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
- sqlite3EndBenignMalloc();
- if( rc2==SQLITE_OK && isRO ) break;
- }
- }while( winRetryIoerr(&cnt, &lastErrno) );
-#endif
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- do{
- h = osCreateFileA((LPCSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL);
- if( h!=INVALID_HANDLE_VALUE ) break;
- if( isReadWrite ){
- int rc2, isRO = 0;
- sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
- sqlite3EndBenignMalloc();
- if( rc2==SQLITE_OK && isRO ) break;
- }
- }while( winRetryIoerr(&cnt, &lastErrno) );
- }
-#endif
- winLogIoerr(cnt, __LINE__);
-
- OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
- dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
-
- if( h==INVALID_HANDLE_VALUE ){
- sqlite3_free(zConverted);
- sqlite3_free(zTmpname);
- if( isReadWrite && !isExclusive ){
- return winOpen(pVfs, zName, id,
- ((flags|SQLITE_OPEN_READONLY) &
- ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
- pOutFlags);
- }else{
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
- return SQLITE_CANTOPEN_BKPT;
- }
- }
-
- if( pOutFlags ){
- if( isReadWrite ){
- *pOutFlags = SQLITE_OPEN_READWRITE;
- }else{
- *pOutFlags = SQLITE_OPEN_READONLY;
- }
- }
-
- OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, "
- "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ?
- *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
-
- pAppData = (winVfsAppData*)pVfs->pAppData;
-
-#if SQLITE_OS_WINCE
- {
- if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
- && ((pAppData==NULL) || !pAppData->bNoLock)
- && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
- ){
- osCloseHandle(h);
- sqlite3_free(zConverted);
- sqlite3_free(zTmpname);
- OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
- return rc;
- }
- }
- if( isTemp ){
- pFile->zDeleteOnClose = zConverted;
- }else
-#endif
- {
- sqlite3_free(zConverted);
- }
-
- sqlite3_free(zTmpname);
- pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod;
- pFile->pVfs = pVfs;
- pFile->h = h;
- if( isReadonly ){
- pFile->ctrlFlags |= WINFILE_RDONLY;
- }
- if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
- pFile->ctrlFlags |= WINFILE_PSOW;
- }
- pFile->lastErrno = NO_ERROR;
- pFile->zPath = zName;
-#if SQLITE_MAX_MMAP_SIZE>0
- pFile->hMap = NULL;
- pFile->pMapRegion = 0;
- pFile->mmapSize = 0;
- pFile->mmapSizeActual = 0;
- pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
-#endif
-
- OpenCounter(+1);
- return rc;
-}
-
-/*
-** Delete the named file.
-**
-** Note that Windows does not allow a file to be deleted if some other
-** process has it open. Sometimes a virus scanner or indexing program
-** will open a journal file shortly after it is created in order to do
-** whatever it does. While this other process is holding the
-** file open, we will be unable to delete it. To work around this
-** problem, we delay 100 milliseconds and try to delete again. Up
-** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
-** up and returning an error.
-*/
-static int winDelete(
- sqlite3_vfs *pVfs, /* Not used on win32 */
- const char *zFilename, /* Name of file to delete */
- int syncDir /* Not used on win32 */
-){
- int cnt = 0;
- int rc;
- DWORD attr;
- DWORD lastErrno = 0;
- void *zConverted;
- UNUSED_PARAMETER(pVfs);
- UNUSED_PARAMETER(syncDir);
-
- SimulateIOError(return SQLITE_IOERR_DELETE);
- OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
-
- zConverted = winConvertFromUtf8Filename(zFilename);
- if( zConverted==0 ){
- OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( osIsNT() ){
- do {
-#if SQLITE_OS_WINRT
- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
- memset(&sAttrData, 0, sizeof(sAttrData));
- if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
- &sAttrData) ){
- attr = sAttrData.dwFileAttributes;
- }else{
- lastErrno = osGetLastError();
- if( lastErrno==ERROR_FILE_NOT_FOUND
- || lastErrno==ERROR_PATH_NOT_FOUND ){
- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
- }else{
- rc = SQLITE_ERROR;
- }
- break;
- }
-#else
- attr = osGetFileAttributesW(zConverted);
-#endif
- if ( attr==INVALID_FILE_ATTRIBUTES ){
- lastErrno = osGetLastError();
- if( lastErrno==ERROR_FILE_NOT_FOUND
- || lastErrno==ERROR_PATH_NOT_FOUND ){
- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
- }else{
- rc = SQLITE_ERROR;
- }
- break;
- }
- if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
- rc = SQLITE_ERROR; /* Files only. */
- break;
- }
- if ( osDeleteFileW(zConverted) ){
- rc = SQLITE_OK; /* Deleted OK. */
- break;
- }
- if ( !winRetryIoerr(&cnt, &lastErrno) ){
- rc = SQLITE_ERROR; /* No more retries. */
- break;
- }
- } while(1);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- do {
- attr = osGetFileAttributesA(zConverted);
- if ( attr==INVALID_FILE_ATTRIBUTES ){
- lastErrno = osGetLastError();
- if( lastErrno==ERROR_FILE_NOT_FOUND
- || lastErrno==ERROR_PATH_NOT_FOUND ){
- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
- }else{
- rc = SQLITE_ERROR;
- }
- break;
- }
- if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
- rc = SQLITE_ERROR; /* Files only. */
- break;
- }
- if ( osDeleteFileA(zConverted) ){
- rc = SQLITE_OK; /* Deleted OK. */
- break;
- }
- if ( !winRetryIoerr(&cnt, &lastErrno) ){
- rc = SQLITE_ERROR; /* No more retries. */
- break;
- }
- } while(1);
- }
-#endif
- if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
- rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
- }else{
- winLogIoerr(cnt, __LINE__);
- }
- sqlite3_free(zConverted);
- OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
- return rc;
-}
-
-/*
-** Check the existence and status of a file.
-*/
-static int winAccess(
- sqlite3_vfs *pVfs, /* Not used on win32 */
- const char *zFilename, /* Name of file to check */
- int flags, /* Type of test to make on this file */
- int *pResOut /* OUT: Result */
-){
- DWORD attr;
- int rc = 0;
- DWORD lastErrno = 0;
- void *zConverted;
- UNUSED_PARAMETER(pVfs);
-
- SimulateIOError( return SQLITE_IOERR_ACCESS; );
- OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
- zFilename, flags, pResOut));
-
- zConverted = winConvertFromUtf8Filename(zFilename);
- if( zConverted==0 ){
- OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( osIsNT() ){
- int cnt = 0;
- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
- memset(&sAttrData, 0, sizeof(sAttrData));
- while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
- GetFileExInfoStandard,
- &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
- if( rc ){
- /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
- ** as if it does not exist.
- */
- if( flags==SQLITE_ACCESS_EXISTS
- && sAttrData.nFileSizeHigh==0
- && sAttrData.nFileSizeLow==0 ){
- attr = INVALID_FILE_ATTRIBUTES;
- }else{
- attr = sAttrData.dwFileAttributes;
- }
- }else{
- winLogIoerr(cnt, __LINE__);
- if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
- sqlite3_free(zConverted);
- return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
- zFilename);
- }else{
- attr = INVALID_FILE_ATTRIBUTES;
- }
- }
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- attr = osGetFileAttributesA((char*)zConverted);
- }
-#endif
- sqlite3_free(zConverted);
- switch( flags ){
- case SQLITE_ACCESS_READ:
- case SQLITE_ACCESS_EXISTS:
- rc = attr!=INVALID_FILE_ATTRIBUTES;
- break;
- case SQLITE_ACCESS_READWRITE:
- rc = attr!=INVALID_FILE_ATTRIBUTES &&
- (attr & FILE_ATTRIBUTE_READONLY)==0;
- break;
- default:
- assert(!"Invalid flags argument");
- }
- *pResOut = rc;
- OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
- zFilename, pResOut, *pResOut));
- return SQLITE_OK;
-}
-
-/*
-** Returns non-zero if the specified path name starts with a drive letter
-** followed by a colon character.
-*/
-static BOOL winIsDriveLetterAndColon(
- const char *zPathname
-){
- return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' );
-}
-
-/*
-** Returns non-zero if the specified path name should be used verbatim. If
-** non-zero is returned from this function, the calling function must simply
-** use the provided path name verbatim -OR- resolve it into a full path name
-** using the GetFullPathName Win32 API function (if available).
-*/
-static BOOL winIsVerbatimPathname(
- const char *zPathname
-){
- /*
- ** If the path name starts with a forward slash or a backslash, it is either
- ** a legal UNC name, a volume relative path, or an absolute path name in the
- ** "Unix" format on Windows. There is no easy way to differentiate between
- ** the final two cases; therefore, we return the safer return value of TRUE
- ** so that callers of this function will simply use it verbatim.
- */
- if ( winIsDirSep(zPathname[0]) ){
- return TRUE;
- }
-
- /*
- ** If the path name starts with a letter and a colon it is either a volume
- ** relative path or an absolute path. Callers of this function must not
- ** attempt to treat it as a relative path name (i.e. they should simply use
- ** it verbatim).
- */
- if ( winIsDriveLetterAndColon(zPathname) ){
- return TRUE;
- }
-
- /*
- ** If we get to this point, the path name should almost certainly be a purely
- ** relative one (i.e. not a UNC name, not absolute, and not volume relative).
- */
- return FALSE;
-}
-
-/*
-** Turn a relative pathname into a full pathname. Write the full
-** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
-** bytes in size.
-*/
-static int winFullPathname(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- const char *zRelative, /* Possibly relative input path */
- int nFull, /* Size of output buffer in bytes */
- char *zFull /* Output buffer */
-){
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
- DWORD nByte;
- void *zConverted;
- char *zOut;
-#endif
-
- /* If this path name begins with "/X:", where "X" is any alphabetic
- ** character, discard the initial "/" from the pathname.
- */
- if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
- zRelative++;
- }
-
-#if defined(__CYGWIN__)
- SimulateIOError( return SQLITE_ERROR );
- UNUSED_PARAMETER(nFull);
- assert( nFull>=pVfs->mxPathname );
- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
- /*
- ** NOTE: We are dealing with a relative path name and the data
- ** directory has been set. Therefore, use it as the basis
- ** for converting the relative path name to an absolute
- ** one by prepending the data directory and a slash.
- */
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) |
- CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname1", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
- sqlite3_data_directory, winGetDirSep(), zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
- }
- }else{
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A),
- zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname2", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
- }
- }
- return SQLITE_OK;
-#endif
-
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
- SimulateIOError( return SQLITE_ERROR );
- /* WinCE has no concept of a relative pathname, or so I am told. */
- /* WinRT has no way to convert a relative path to an absolute one. */
- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
- /*
- ** NOTE: We are dealing with a relative path name and the data
- ** directory has been set. Therefore, use it as the basis
- ** for converting the relative path name to an absolute
- ** one by prepending the data directory and a backslash.
- */
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
- sqlite3_data_directory, winGetDirSep(), zRelative);
- }else{
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
- }
- return SQLITE_OK;
-#endif
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
- /* It's odd to simulate an io-error here, but really this is just
- ** using the io-error infrastructure to test that SQLite handles this
- ** function failing. This function could fail if, for example, the
- ** current working directory has been unlinked.
- */
- SimulateIOError( return SQLITE_ERROR );
- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
- /*
- ** NOTE: We are dealing with a relative path name and the data
- ** directory has been set. Therefore, use it as the basis
- ** for converting the relative path name to an absolute
- ** one by prepending the data directory and a backslash.
- */
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
- sqlite3_data_directory, winGetDirSep(), zRelative);
- return SQLITE_OK;
- }
- zConverted = winConvertFromUtf8Filename(zRelative);
- if( zConverted==0 ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( osIsNT() ){
- LPWSTR zTemp;
- nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
- if( nByte==0 ){
- sqlite3_free(zConverted);
- return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
- "winFullPathname1", zRelative);
- }
- nByte += 3;
- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
- if( zTemp==0 ){
- sqlite3_free(zConverted);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
- if( nByte==0 ){
- sqlite3_free(zConverted);
- sqlite3_free(zTemp);
- return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
- "winFullPathname2", zRelative);
- }
- sqlite3_free(zConverted);
- zOut = winUnicodeToUtf8(zTemp);
- sqlite3_free(zTemp);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- char *zTemp;
- nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
- if( nByte==0 ){
- sqlite3_free(zConverted);
- return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
- "winFullPathname3", zRelative);
- }
- nByte += 3;
- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
- if( zTemp==0 ){
- sqlite3_free(zConverted);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
- if( nByte==0 ){
- sqlite3_free(zConverted);
- sqlite3_free(zTemp);
- return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
- "winFullPathname4", zRelative);
- }
- sqlite3_free(zConverted);
- zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI());
- sqlite3_free(zTemp);
- }
-#endif
- if( zOut ){
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
- sqlite3_free(zOut);
- return SQLITE_OK;
- }else{
- return SQLITE_IOERR_NOMEM_BKPT;
- }
-#endif
-}
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-/*
-** Interfaces for opening a shared library, finding entry points
-** within the shared library, and closing the shared library.
-*/
-static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
- HANDLE h;
-#if defined(__CYGWIN__)
- int nFull = pVfs->mxPathname+1;
- char *zFull = sqlite3MallocZero( nFull );
- void *zConverted = 0;
- if( zFull==0 ){
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
- sqlite3_free(zFull);
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- zConverted = winConvertFromUtf8Filename(zFull);
- sqlite3_free(zFull);
-#else
- void *zConverted = winConvertFromUtf8Filename(zFilename);
- UNUSED_PARAMETER(pVfs);
-#endif
- if( zConverted==0 ){
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- if( osIsNT() ){
-#if SQLITE_OS_WINRT
- h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
-#else
- h = osLoadLibraryW((LPCWSTR)zConverted);
-#endif
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- h = osLoadLibraryA((char*)zConverted);
- }
-#endif
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h));
- sqlite3_free(zConverted);
- return (void*)h;
-}
-static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
- UNUSED_PARAMETER(pVfs);
- winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
-}
-static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
- FARPROC proc;
- UNUSED_PARAMETER(pVfs);
- proc = osGetProcAddressA((HANDLE)pH, zSym);
- OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n",
- (void*)pH, zSym, (void*)proc));
- return (void(*)(void))proc;
-}
-static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
- UNUSED_PARAMETER(pVfs);
- osFreeLibrary((HANDLE)pHandle);
- OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle));
-}
-#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
- #define winDlOpen 0
- #define winDlError 0
- #define winDlSym 0
- #define winDlClose 0
-#endif
-
-/* State information for the randomness gatherer. */
-typedef struct EntropyGatherer EntropyGatherer;
-struct EntropyGatherer {
- unsigned char *a; /* Gather entropy into this buffer */
- int na; /* Size of a[] in bytes */
- int i; /* XOR next input into a[i] */
- int nXor; /* Number of XOR operations done */
-};
-
-#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
-/* Mix sz bytes of entropy into p. */
-static void xorMemory(EntropyGatherer *p, unsigned char *x, int sz){
- int j, k;
- for(j=0, k=p->i; j<sz; j++){
- p->a[k++] ^= x[j];
- if( k>=p->na ) k = 0;
- }
- p->i = k;
- p->nXor += sz;
-}
-#endif /* !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) */
-
-/*
-** Write up to nBuf bytes of randomness into zBuf.
-*/
-static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
-#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS)
- UNUSED_PARAMETER(pVfs);
- memset(zBuf, 0, nBuf);
- return nBuf;
-#else
- EntropyGatherer e;
- UNUSED_PARAMETER(pVfs);
- memset(zBuf, 0, nBuf);
- e.a = (unsigned char*)zBuf;
- e.na = nBuf;
- e.nXor = 0;
- e.i = 0;
- {
- SYSTEMTIME x;
- osGetSystemTime(&x);
- xorMemory(&e, (unsigned char*)&x, sizeof(SYSTEMTIME));
- }
- {
- DWORD pid = osGetCurrentProcessId();
- xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD));
- }
-#if SQLITE_OS_WINRT
- {
- ULONGLONG cnt = osGetTickCount64();
- xorMemory(&e, (unsigned char*)&cnt, sizeof(ULONGLONG));
- }
-#else
- {
- DWORD cnt = osGetTickCount();
- xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD));
- }
-#endif /* SQLITE_OS_WINRT */
- {
- LARGE_INTEGER i;
- osQueryPerformanceCounter(&i);
- xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER));
- }
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
- {
- UUID id;
- memset(&id, 0, sizeof(UUID));
- osUuidCreate(&id);
- xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
- memset(&id, 0, sizeof(UUID));
- osUuidCreateSequential(&id);
- xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
- }
-#endif /* !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID */
- return e.nXor>nBuf ? nBuf : e.nXor;
-#endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */
-}
-
-
-/*
-** Sleep for a little while. Return the amount of time slept.
-*/
-static int winSleep(sqlite3_vfs *pVfs, int microsec){
- sqlite3_win32_sleep((microsec+999)/1000);
- UNUSED_PARAMETER(pVfs);
- return ((microsec+999)/1000)*1000;
-}
-
-/*
-** The following variable, if set to a non-zero value, is interpreted as
-** the number of seconds since 1970 and is used to set the result of
-** sqlite3OsCurrentTime() during testing.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
-#endif
-
-/*
-** Find the current time (in Universal Coordinated Time). Write into *piNow
-** the current time and date as a Julian Day number times 86_400_000. In
-** other words, write into *piNow the number of milliseconds since the Julian
-** epoch of noon in Greenwich on November 24, 4714 B.C according to the
-** proleptic Gregorian calendar.
-**
-** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
-** cannot be found.
-*/
-static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
- /* FILETIME structure is a 64-bit value representing the number of
- 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
- */
- FILETIME ft;
- static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
-#ifdef SQLITE_TEST
- static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
-#endif
- /* 2^32 - to avoid use of LL and warnings in gcc */
- static const sqlite3_int64 max32BitValue =
- (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
- (sqlite3_int64)294967296;
-
-#if SQLITE_OS_WINCE
- SYSTEMTIME time;
- osGetSystemTime(&time);
- /* if SystemTimeToFileTime() fails, it returns zero. */
- if (!osSystemTimeToFileTime(&time,&ft)){
- return SQLITE_ERROR;
- }
-#else
- osGetSystemTimeAsFileTime( &ft );
-#endif
-
- *piNow = winFiletimeEpoch +
- ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
- (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
-
-#ifdef SQLITE_TEST
- if( sqlite3_current_time ){
- *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
- }
-#endif
- UNUSED_PARAMETER(pVfs);
- return SQLITE_OK;
-}
-
-/*
-** Find the current time (in Universal Coordinated Time). Write the
-** current time and date as a Julian Day number into *prNow and
-** return 0. Return 1 if the time and date cannot be found.
-*/
-static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
- int rc;
- sqlite3_int64 i;
- rc = winCurrentTimeInt64(pVfs, &i);
- if( !rc ){
- *prNow = i/86400000.0;
- }
- return rc;
-}
-
-/*
-** The idea is that this function works like a combination of
-** GetLastError() and FormatMessage() on Windows (or errno and
-** strerror_r() on Unix). After an error is returned by an OS
-** function, SQLite calls this function with zBuf pointing to
-** a buffer of nBuf bytes. The OS layer should populate the
-** buffer with a nul-terminated UTF-8 encoded error message
-** describing the last IO error to have occurred within the calling
-** thread.
-**
-** If the error message is too large for the supplied buffer,
-** it should be truncated. The return value of xGetLastError
-** is zero if the error message fits in the buffer, or non-zero
-** otherwise (if the message was truncated). If non-zero is returned,
-** then it is not necessary to include the nul-terminator character
-** in the output buffer.
-**
-** Not supplying an error message will have no adverse effect
-** on SQLite. It is fine to have an implementation that never
-** returns an error message:
-**
-** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
-** assert(zBuf[0]=='\0');
-** return 0;
-** }
-**
-** However if an error message is supplied, it will be incorporated
-** by sqlite into the error message available to the user using
-** sqlite3_errmsg(), possibly making IO errors easier to debug.
-*/
-static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
- DWORD e = osGetLastError();
- UNUSED_PARAMETER(pVfs);
- if( nBuf>0 ) winGetLastErrorMsg(e, nBuf, zBuf);
- return e;
-}
-
-/*
-** Initialize and deinitialize the operating system interface.
-*/
-int sqlite3_os_init(void){
- static sqlite3_vfs winVfs = {
- 3, /* iVersion */
- sizeof(winFile), /* szOsFile */
- SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
- 0, /* pNext */
- "win32", /* zName */
- &winAppData, /* pAppData */
- winOpen, /* xOpen */
- winDelete, /* xDelete */
- winAccess, /* xAccess */
- winFullPathname, /* xFullPathname */
- winDlOpen, /* xDlOpen */
- winDlError, /* xDlError */
- winDlSym, /* xDlSym */
- winDlClose, /* xDlClose */
- winRandomness, /* xRandomness */
- winSleep, /* xSleep */
- winCurrentTime, /* xCurrentTime */
- winGetLastError, /* xGetLastError */
- winCurrentTimeInt64, /* xCurrentTimeInt64 */
- winSetSystemCall, /* xSetSystemCall */
- winGetSystemCall, /* xGetSystemCall */
- winNextSystemCall, /* xNextSystemCall */
- };
-#if defined(SQLITE_WIN32_HAS_WIDE)
- static sqlite3_vfs winLongPathVfs = {
- 3, /* iVersion */
- sizeof(winFile), /* szOsFile */
- SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
- 0, /* pNext */
- "win32-longpath", /* zName */
- &winAppData, /* pAppData */
- winOpen, /* xOpen */
- winDelete, /* xDelete */
- winAccess, /* xAccess */
- winFullPathname, /* xFullPathname */
- winDlOpen, /* xDlOpen */
- winDlError, /* xDlError */
- winDlSym, /* xDlSym */
- winDlClose, /* xDlClose */
- winRandomness, /* xRandomness */
- winSleep, /* xSleep */
- winCurrentTime, /* xCurrentTime */
- winGetLastError, /* xGetLastError */
- winCurrentTimeInt64, /* xCurrentTimeInt64 */
- winSetSystemCall, /* xSetSystemCall */
- winGetSystemCall, /* xGetSystemCall */
- winNextSystemCall, /* xNextSystemCall */
- };
-#endif
- static sqlite3_vfs winNolockVfs = {
- 3, /* iVersion */
- sizeof(winFile), /* szOsFile */
- SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
- 0, /* pNext */
- "win32-none", /* zName */
- &winNolockAppData, /* pAppData */
- winOpen, /* xOpen */
- winDelete, /* xDelete */
- winAccess, /* xAccess */
- winFullPathname, /* xFullPathname */
- winDlOpen, /* xDlOpen */
- winDlError, /* xDlError */
- winDlSym, /* xDlSym */
- winDlClose, /* xDlClose */
- winRandomness, /* xRandomness */
- winSleep, /* xSleep */
- winCurrentTime, /* xCurrentTime */
- winGetLastError, /* xGetLastError */
- winCurrentTimeInt64, /* xCurrentTimeInt64 */
- winSetSystemCall, /* xSetSystemCall */
- winGetSystemCall, /* xGetSystemCall */
- winNextSystemCall, /* xNextSystemCall */
- };
-#if defined(SQLITE_WIN32_HAS_WIDE)
- static sqlite3_vfs winLongPathNolockVfs = {
- 3, /* iVersion */
- sizeof(winFile), /* szOsFile */
- SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
- 0, /* pNext */
- "win32-longpath-none", /* zName */
- &winNolockAppData, /* pAppData */
- winOpen, /* xOpen */
- winDelete, /* xDelete */
- winAccess, /* xAccess */
- winFullPathname, /* xFullPathname */
- winDlOpen, /* xDlOpen */
- winDlError, /* xDlError */
- winDlSym, /* xDlSym */
- winDlClose, /* xDlClose */
- winRandomness, /* xRandomness */
- winSleep, /* xSleep */
- winCurrentTime, /* xCurrentTime */
- winGetLastError, /* xGetLastError */
- winCurrentTimeInt64, /* xCurrentTimeInt64 */
- winSetSystemCall, /* xSetSystemCall */
- winGetSystemCall, /* xGetSystemCall */
- winNextSystemCall, /* xNextSystemCall */
- };
-#endif
-
- /* Double-check that the aSyscall[] array has been constructed
- ** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==80 );
-
- /* get memory map allocation granularity */
- memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
-#if SQLITE_OS_WINRT
- osGetNativeSystemInfo(&winSysInfo);
-#else
- osGetSystemInfo(&winSysInfo);
-#endif
- assert( winSysInfo.dwAllocationGranularity>0 );
- assert( winSysInfo.dwPageSize>0 );
-
- sqlite3_vfs_register(&winVfs, 1);
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
- sqlite3_vfs_register(&winLongPathVfs, 0);
-#endif
-
- sqlite3_vfs_register(&winNolockVfs, 0);
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
- sqlite3_vfs_register(&winLongPathNolockVfs, 0);
-#endif
-
-#ifndef SQLITE_OMIT_WAL
- winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
-#endif
-
- return SQLITE_OK;
-}
-
-int sqlite3_os_end(void){
-#if SQLITE_OS_WINRT
- if( sleepObj!=NULL ){
- osCloseHandle(sleepObj);
- sleepObj = NULL;
- }
-#endif
-
-#ifndef SQLITE_OMIT_WAL
- winBigLock = 0;
-#endif
-
- return SQLITE_OK;
-}
-
-#endif /* SQLITE_OS_WIN */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_win.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/os_win.h
deleted file mode 100644
index 27714ed0793..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/os_win.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-** 2013 November 25
-**
-** 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 contains code that is specific to Windows.
-*/
-#ifndef SQLITE_OS_WIN_H
-#define SQLITE_OS_WIN_H
-
-/*
-** Include the primary Windows SDK header file.
-*/
-#include "windows.h"
-
-#ifdef __CYGWIN__
-# include <sys/cygwin.h>
-# include <errno.h> /* amalgamator: dontcache */
-#endif
-
-/*
-** Determine if we are dealing with Windows NT.
-**
-** We ought to be able to determine if we are compiling for Windows 9x or
-** Windows NT using the _WIN32_WINNT macro as follows:
-**
-** #if defined(_WIN32_WINNT)
-** # define SQLITE_OS_WINNT 1
-** #else
-** # define SQLITE_OS_WINNT 0
-** #endif
-**
-** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
-** it ought to, so the above test does not work. We'll just assume that
-** everything is Windows NT unless the programmer explicitly says otherwise
-** by setting SQLITE_OS_WINNT to 0.
-*/
-#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
-# define SQLITE_OS_WINNT 1
-#endif
-
-/*
-** Determine if we are dealing with Windows CE - which has a much reduced
-** API.
-*/
-#if defined(_WIN32_WCE)
-# define SQLITE_OS_WINCE 1
-#else
-# define SQLITE_OS_WINCE 0
-#endif
-
-/*
-** Determine if we are dealing with WinRT, which provides only a subset of
-** the full Win32 API.
-*/
-#if !defined(SQLITE_OS_WINRT)
-# define SQLITE_OS_WINRT 0
-#endif
-
-/*
-** For WinCE, some API function parameters do not appear to be declared as
-** volatile.
-*/
-#if SQLITE_OS_WINCE
-# define SQLITE_WIN32_VOLATILE
-#else
-# define SQLITE_WIN32_VOLATILE volatile
-#endif
-
-/*
-** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
-** functions are not available (e.g. those not using MSVC, Cygwin, etc).
-*/
-#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
- SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
-# define SQLITE_OS_WIN_THREADS 1
-#else
-# define SQLITE_OS_WIN_THREADS 0
-#endif
-
-#endif /* SQLITE_OS_WIN_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/pager.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/pager.c
deleted file mode 100644
index a5e1edf7829..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/pager.c
+++ /dev/null
@@ -1,7660 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 is the implementation of the page cache subsystem or "pager".
-**
-** The pager is used to access a database disk file. It implements
-** atomic commit and rollback through the use of a journal file that
-** is separate from the database file. The pager also implements file
-** locking to prevent two processes from writing the same database
-** file simultaneously, or one process from reading the database while
-** another is writing.
-*/
-#ifndef SQLITE_OMIT_DISKIO
-#include "sqliteInt.h"
-#include "wal.h"
-
-
-/******************* NOTES ON THE DESIGN OF THE PAGER ************************
-**
-** This comment block describes invariants that hold when using a rollback
-** journal. These invariants do not apply for journal_mode=WAL,
-** journal_mode=MEMORY, or journal_mode=OFF.
-**
-** Within this comment block, a page is deemed to have been synced
-** automatically as soon as it is written when PRAGMA synchronous=OFF.
-** Otherwise, the page is not synced until the xSync method of the VFS
-** is called successfully on the file containing the page.
-**
-** Definition: A page of the database file is said to be "overwriteable" if
-** one or more of the following are true about the page:
-**
-** (a) The original content of the page as it was at the beginning of
-** the transaction has been written into the rollback journal and
-** synced.
-**
-** (b) The page was a freelist leaf page at the start of the transaction.
-**
-** (c) The page number is greater than the largest page that existed in
-** the database file at the start of the transaction.
-**
-** (1) A page of the database file is never overwritten unless one of the
-** following are true:
-**
-** (a) The page and all other pages on the same sector are overwriteable.
-**
-** (b) The atomic page write optimization is enabled, and the entire
-** transaction other than the update of the transaction sequence
-** number consists of a single page change.
-**
-** (2) The content of a page written into the rollback journal exactly matches
-** both the content in the database when the rollback journal was written
-** and the content in the database at the beginning of the current
-** transaction.
-**
-** (3) Writes to the database file are an integer multiple of the page size
-** in length and are aligned on a page boundary.
-**
-** (4) Reads from the database file are either aligned on a page boundary and
-** an integer multiple of the page size in length or are taken from the
-** first 100 bytes of the database file.
-**
-** (5) All writes to the database file are synced prior to the rollback journal
-** being deleted, truncated, or zeroed.
-**
-** (6) If a master journal file is used, then all writes to the database file
-** are synced prior to the master journal being deleted.
-**
-** Definition: Two databases (or the same database at two points it time)
-** are said to be "logically equivalent" if they give the same answer to
-** all queries. Note in particular the content of freelist leaf
-** pages can be changed arbitrarily without affecting the logical equivalence
-** of the database.
-**
-** (7) At any time, if any subset, including the empty set and the total set,
-** of the unsynced changes to a rollback journal are removed and the
-** journal is rolled back, the resulting database file will be logically
-** equivalent to the database file at the beginning of the transaction.
-**
-** (8) When a transaction is rolled back, the xTruncate method of the VFS
-** is called to restore the database file to the same size it was at
-** the beginning of the transaction. (In some VFSes, the xTruncate
-** method is a no-op, but that does not change the fact the SQLite will
-** invoke it.)
-**
-** (9) Whenever the database file is modified, at least one bit in the range
-** of bytes from 24 through 39 inclusive will be changed prior to releasing
-** the EXCLUSIVE lock, thus signaling other connections on the same
-** database to flush their caches.
-**
-** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less
-** than one billion transactions.
-**
-** (11) A database file is well-formed at the beginning and at the conclusion
-** of every transaction.
-**
-** (12) An EXCLUSIVE lock is held on the database file when writing to
-** the database file.
-**
-** (13) A SHARED lock is held on the database file while reading any
-** content out of the database file.
-**
-******************************************************************************/
-
-/*
-** Macros for troubleshooting. Normally turned off
-*/
-#if 0
-int sqlite3PagerTrace=1; /* True to enable tracing */
-#define sqlite3DebugPrintf printf
-#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }
-#else
-#define PAGERTRACE(X)
-#endif
-
-/*
-** The following two macros are used within the PAGERTRACE() macros above
-** to print out file-descriptors.
-**
-** PAGERID() takes a pointer to a Pager struct as its argument. The
-** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
-** struct as its argument.
-*/
-#define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd))
-#define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd))
-
-/*
-** The Pager.eState variable stores the current 'state' of a pager. A
-** pager may be in any one of the seven states shown in the following
-** state diagram.
-**
-** OPEN <------+------+
-** | | |
-** V | |
-** +---------> READER-------+ |
-** | | |
-** | V |
-** |<-------WRITER_LOCKED------> ERROR
-** | | ^
-** | V |
-** |<------WRITER_CACHEMOD-------->|
-** | | |
-** | V |
-** |<-------WRITER_DBMOD---------->|
-** | | |
-** | V |
-** +<------WRITER_FINISHED-------->+
-**
-**
-** List of state transitions and the C [function] that performs each:
-**
-** OPEN -> READER [sqlite3PagerSharedLock]
-** READER -> OPEN [pager_unlock]
-**
-** READER -> WRITER_LOCKED [sqlite3PagerBegin]
-** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal]
-** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal]
-** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne]
-** WRITER_*** -> READER [pager_end_transaction]
-**
-** WRITER_*** -> ERROR [pager_error]
-** ERROR -> OPEN [pager_unlock]
-**
-**
-** OPEN:
-**
-** The pager starts up in this state. Nothing is guaranteed in this
-** state - the file may or may not be locked and the database size is
-** unknown. The database may not be read or written.
-**
-** * No read or write transaction is active.
-** * Any lock, or no lock at all, may be held on the database file.
-** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
-**
-** READER:
-**
-** In this state all the requirements for reading the database in
-** rollback (non-WAL) mode are met. Unless the pager is (or recently
-** was) in exclusive-locking mode, a user-level read transaction is
-** open. The database size is known in this state.
-**
-** A connection running with locking_mode=normal enters this state when
-** it opens a read-transaction on the database and returns to state
-** OPEN after the read-transaction is completed. However a connection
-** running in locking_mode=exclusive (including temp databases) remains in
-** this state even after the read-transaction is closed. The only way
-** a locking_mode=exclusive connection can transition from READER to OPEN
-** is via the ERROR state (see below).
-**
-** * A read transaction may be active (but a write-transaction cannot).
-** * A SHARED or greater lock is held on the database file.
-** * The dbSize variable may be trusted (even if a user-level read
-** transaction is not active). The dbOrigSize and dbFileSize variables
-** may not be trusted at this point.
-** * If the database is a WAL database, then the WAL connection is open.
-** * Even if a read-transaction is not open, it is guaranteed that
-** there is no hot-journal in the file-system.
-**
-** WRITER_LOCKED:
-**
-** The pager moves to this state from READER when a write-transaction
-** is first opened on the database. In WRITER_LOCKED state, all locks
-** required to start a write-transaction are held, but no actual
-** modifications to the cache or database have taken place.
-**
-** In rollback mode, a RESERVED or (if the transaction was opened with
-** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
-** moving to this state, but the journal file is not written to or opened
-** to in this state. If the transaction is committed or rolled back while
-** in WRITER_LOCKED state, all that is required is to unlock the database
-** file.
-**
-** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
-** If the connection is running with locking_mode=exclusive, an attempt
-** is made to obtain an EXCLUSIVE lock on the database file.
-**
-** * A write transaction is active.
-** * If the connection is open in rollback-mode, a RESERVED or greater
-** lock is held on the database file.
-** * If the connection is open in WAL-mode, a WAL write transaction
-** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
-** called).
-** * The dbSize, dbOrigSize and dbFileSize variables are all valid.
-** * The contents of the pager cache have not been modified.
-** * The journal file may or may not be open.
-** * Nothing (not even the first header) has been written to the journal.
-**
-** WRITER_CACHEMOD:
-**
-** A pager moves from WRITER_LOCKED state to this state when a page is
-** first modified by the upper layer. In rollback mode the journal file
-** is opened (if it is not already open) and a header written to the
-** start of it. The database file on disk has not been modified.
-**
-** * A write transaction is active.
-** * A RESERVED or greater lock is held on the database file.
-** * The journal file is open and the first header has been written
-** to it, but the header has not been synced to disk.
-** * The contents of the page cache have been modified.
-**
-** WRITER_DBMOD:
-**
-** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state
-** when it modifies the contents of the database file. WAL connections
-** never enter this state (since they do not modify the database file,
-** just the log file).
-**
-** * A write transaction is active.
-** * An EXCLUSIVE or greater lock is held on the database file.
-** * The journal file is open and the first header has been written
-** and synced to disk.
-** * The contents of the page cache have been modified (and possibly
-** written to disk).
-**
-** WRITER_FINISHED:
-**
-** It is not possible for a WAL connection to enter this state.
-**
-** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
-** state after the entire transaction has been successfully written into the
-** database file. In this state the transaction may be committed simply
-** by finalizing the journal file. Once in WRITER_FINISHED state, it is
-** not possible to modify the database further. At this point, the upper
-** layer must either commit or rollback the transaction.
-**
-** * A write transaction is active.
-** * An EXCLUSIVE or greater lock is held on the database file.
-** * All writing and syncing of journal and database data has finished.
-** If no error occurred, all that remains is to finalize the journal to
-** commit the transaction. If an error did occur, the caller will need
-** to rollback the transaction.
-**
-** ERROR:
-**
-** The ERROR state is entered when an IO or disk-full error (including
-** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
-** difficult to be sure that the in-memory pager state (cache contents,
-** db size etc.) are consistent with the contents of the file-system.
-**
-** Temporary pager files may enter the ERROR state, but in-memory pagers
-** cannot.
-**
-** For example, if an IO error occurs while performing a rollback,
-** the contents of the page-cache may be left in an inconsistent state.
-** At this point it would be dangerous to change back to READER state
-** (as usually happens after a rollback). Any subsequent readers might
-** report database corruption (due to the inconsistent cache), and if
-** they upgrade to writers, they may inadvertently corrupt the database
-** file. To avoid this hazard, the pager switches into the ERROR state
-** instead of READER following such an error.
-**
-** Once it has entered the ERROR state, any attempt to use the pager
-** to read or write data returns an error. Eventually, once all
-** outstanding transactions have been abandoned, the pager is able to
-** transition back to OPEN state, discarding the contents of the
-** page-cache and any other in-memory state at the same time. Everything
-** is reloaded from disk (and, if necessary, hot-journal rollback peformed)
-** when a read-transaction is next opened on the pager (transitioning
-** the pager into READER state). At that point the system has recovered
-** from the error.
-**
-** Specifically, the pager jumps into the ERROR state if:
-**
-** 1. An error occurs while attempting a rollback. This happens in
-** function sqlite3PagerRollback().
-**
-** 2. An error occurs while attempting to finalize a journal file
-** following a commit in function sqlite3PagerCommitPhaseTwo().
-**
-** 3. An error occurs while attempting to write to the journal or
-** database file in function pagerStress() in order to free up
-** memory.
-**
-** In other cases, the error is returned to the b-tree layer. The b-tree
-** layer then attempts a rollback operation. If the error condition
-** persists, the pager enters the ERROR state via condition (1) above.
-**
-** Condition (3) is necessary because it can be triggered by a read-only
-** statement executed within a transaction. In this case, if the error
-** code were simply returned to the user, the b-tree layer would not
-** automatically attempt a rollback, as it assumes that an error in a
-** read-only statement cannot leave the pager in an internally inconsistent
-** state.
-**
-** * The Pager.errCode variable is set to something other than SQLITE_OK.
-** * There are one or more outstanding references to pages (after the
-** last reference is dropped the pager should move back to OPEN state).
-** * The pager is not an in-memory pager.
-**
-**
-** Notes:
-**
-** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
-** connection is open in WAL mode. A WAL connection is always in one
-** of the first four states.
-**
-** * Normally, a connection open in exclusive mode is never in PAGER_OPEN
-** state. There are two exceptions: immediately after exclusive-mode has
-** been turned on (and before any read or write transactions are
-** executed), and when the pager is leaving the "error state".
-**
-** * See also: assert_pager_state().
-*/
-#define PAGER_OPEN 0
-#define PAGER_READER 1
-#define PAGER_WRITER_LOCKED 2
-#define PAGER_WRITER_CACHEMOD 3
-#define PAGER_WRITER_DBMOD 4
-#define PAGER_WRITER_FINISHED 5
-#define PAGER_ERROR 6
-
-/*
-** The Pager.eLock variable is almost always set to one of the
-** following locking-states, according to the lock currently held on
-** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
-** This variable is kept up to date as locks are taken and released by
-** the pagerLockDb() and pagerUnlockDb() wrappers.
-**
-** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY
-** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not
-** the operation was successful. In these circumstances pagerLockDb() and
-** pagerUnlockDb() take a conservative approach - eLock is always updated
-** when unlocking the file, and only updated when locking the file if the
-** VFS call is successful. This way, the Pager.eLock variable may be set
-** to a less exclusive (lower) value than the lock that is actually held
-** at the system level, but it is never set to a more exclusive value.
-**
-** This is usually safe. If an xUnlock fails or appears to fail, there may
-** be a few redundant xLock() calls or a lock may be held for longer than
-** required, but nothing really goes wrong.
-**
-** The exception is when the database file is unlocked as the pager moves
-** from ERROR to OPEN state. At this point there may be a hot-journal file
-** in the file-system that needs to be rolled back (as part of an OPEN->SHARED
-** transition, by the same pager or any other). If the call to xUnlock()
-** fails at this point and the pager is left holding an EXCLUSIVE lock, this
-** can confuse the call to xCheckReservedLock() call made later as part
-** of hot-journal detection.
-**
-** xCheckReservedLock() is defined as returning true "if there is a RESERVED
-** lock held by this process or any others". So xCheckReservedLock may
-** return true because the caller itself is holding an EXCLUSIVE lock (but
-** doesn't know it because of a previous error in xUnlock). If this happens
-** a hot-journal may be mistaken for a journal being created by an active
-** transaction in another process, causing SQLite to read from the database
-** without rolling it back.
-**
-** To work around this, if a call to xUnlock() fails when unlocking the
-** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
-** is only changed back to a real locking state after a successful call
-** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
-** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
-** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
-** lock on the database file before attempting to roll it back. See function
-** PagerSharedLock() for more detail.
-**
-** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
-** PAGER_OPEN state.
-*/
-#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
-
-/*
-** A macro used for invoking the codec if there is one
-*/
-#ifdef SQLITE_HAS_CODEC
-# define CODEC1(P,D,N,X,E) \
- if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
-# define CODEC2(P,D,N,X,E,O) \
- if( P->xCodec==0 ){ O=(char*)D; }else \
- if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
-#else
-# define CODEC1(P,D,N,X,E) /* NO-OP */
-# define CODEC2(P,D,N,X,E,O) O=(char*)D
-#endif
-
-/*
-** The maximum allowed sector size. 64KiB. If the xSectorsize() method
-** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
-** This could conceivably cause corruption following a power failure on
-** such a system. This is currently an undocumented limit.
-*/
-#define MAX_SECTOR_SIZE 0x10000
-
-
-/*
-** An instance of the following structure is allocated for each active
-** savepoint and statement transaction in the system. All such structures
-** are stored in the Pager.aSavepoint[] array, which is allocated and
-** resized using sqlite3Realloc().
-**
-** When a savepoint is created, the PagerSavepoint.iHdrOffset field is
-** set to 0. If a journal-header is written into the main journal while
-** the savepoint is active, then iHdrOffset is set to the byte offset
-** immediately following the last journal record written into the main
-** journal before the journal-header. This is required during savepoint
-** rollback (see pagerPlaybackSavepoint()).
-*/
-typedef struct PagerSavepoint PagerSavepoint;
-struct PagerSavepoint {
- i64 iOffset; /* Starting offset in main journal */
- i64 iHdrOffset; /* See above */
- Bitvec *pInSavepoint; /* Set of pages in this savepoint */
- Pgno nOrig; /* Original number of pages in file */
- Pgno iSubRec; /* Index of first record in sub-journal */
-#ifndef SQLITE_OMIT_WAL
- u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
-#endif
-};
-
-/*
-** Bits of the Pager.doNotSpill flag. See further description below.
-*/
-#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */
-#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */
-#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */
-
-/*
-** An open page cache is an instance of struct Pager. A description of
-** some of the more important member variables follows:
-**
-** eState
-**
-** The current 'state' of the pager object. See the comment and state
-** diagram above for a description of the pager state.
-**
-** eLock
-**
-** For a real on-disk database, the current lock held on the database file -
-** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
-**
-** For a temporary or in-memory database (neither of which require any
-** locks), this variable is always set to EXCLUSIVE_LOCK. Since such
-** databases always have Pager.exclusiveMode==1, this tricks the pager
-** logic into thinking that it already has all the locks it will ever
-** need (and no reason to release them).
-**
-** In some (obscure) circumstances, this variable may also be set to
-** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for
-** details.
-**
-** changeCountDone
-**
-** This boolean variable is used to make sure that the change-counter
-** (the 4-byte header field at byte offset 24 of the database file) is
-** not updated more often than necessary.
-**
-** It is set to true when the change-counter field is updated, which
-** can only happen if an exclusive lock is held on the database file.
-** It is cleared (set to false) whenever an exclusive lock is
-** relinquished on the database file. Each time a transaction is committed,
-** The changeCountDone flag is inspected. If it is true, the work of
-** updating the change-counter is omitted for the current transaction.
-**
-** This mechanism means that when running in exclusive mode, a connection
-** need only update the change-counter once, for the first transaction
-** committed.
-**
-** setMaster
-**
-** When PagerCommitPhaseOne() is called to commit a transaction, it may
-** (or may not) specify a master-journal name to be written into the
-** journal file before it is synced to disk.
-**
-** Whether or not a journal file contains a master-journal pointer affects
-** the way in which the journal file is finalized after the transaction is
-** committed or rolled back when running in "journal_mode=PERSIST" mode.
-** If a journal file does not contain a master-journal pointer, it is
-** finalized by overwriting the first journal header with zeroes. If
-** it does contain a master-journal pointer the journal file is finalized
-** by truncating it to zero bytes, just as if the connection were
-** running in "journal_mode=truncate" mode.
-**
-** Journal files that contain master journal pointers cannot be finalized
-** simply by overwriting the first journal-header with zeroes, as the
-** master journal pointer could interfere with hot-journal rollback of any
-** subsequently interrupted transaction that reuses the journal file.
-**
-** The flag is cleared as soon as the journal file is finalized (either
-** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
-** journal file from being successfully finalized, the setMaster flag
-** is cleared anyway (and the pager will move to ERROR state).
-**
-** doNotSpill
-**
-** This variables control the behavior of cache-spills (calls made by
-** the pcache module to the pagerStress() routine to write cached data
-** to the file-system in order to free up memory).
-**
-** When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set,
-** writing to the database from pagerStress() is disabled altogether.
-** The SPILLFLAG_ROLLBACK case is done in a very obscure case that
-** comes up during savepoint rollback that requires the pcache module
-** to allocate a new page to prevent the journal file from being written
-** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF
-** case is a user preference.
-**
-** If the SPILLFLAG_NOSYNC bit is set, writing to the database from
-** pagerStress() is permitted, but syncing the journal file is not.
-** This flag is set by sqlite3PagerWrite() when the file-system sector-size
-** is larger than the database page-size in order to prevent a journal sync
-** from happening in between the journalling of two pages on the same sector.
-**
-** subjInMemory
-**
-** This is a boolean variable. If true, then any required sub-journal
-** is opened as an in-memory journal file. If false, then in-memory
-** sub-journals are only used for in-memory pager files.
-**
-** This variable is updated by the upper layer each time a new
-** write-transaction is opened.
-**
-** dbSize, dbOrigSize, dbFileSize
-**
-** Variable dbSize is set to the number of pages in the database file.
-** It is valid in PAGER_READER and higher states (all states except for
-** OPEN and ERROR).
-**
-** dbSize is set based on the size of the database file, which may be
-** larger than the size of the database (the value stored at offset
-** 28 of the database header by the btree). If the size of the file
-** is not an integer multiple of the page-size, the value stored in
-** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2).
-** Except, any file that is greater than 0 bytes in size is considered
-** to have at least one page. (i.e. a 1KB file with 2K page-size leads
-** to dbSize==1).
-**
-** During a write-transaction, if pages with page-numbers greater than
-** dbSize are modified in the cache, dbSize is updated accordingly.
-** Similarly, if the database is truncated using PagerTruncateImage(),
-** dbSize is updated.
-**
-** Variables dbOrigSize and dbFileSize are valid in states
-** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
-** variable at the start of the transaction. It is used during rollback,
-** and to determine whether or not pages need to be journalled before
-** being modified.
-**
-** Throughout a write-transaction, dbFileSize contains the size of
-** the file on disk in pages. It is set to a copy of dbSize when the
-** write-transaction is first opened, and updated when VFS calls are made
-** to write or truncate the database file on disk.
-**
-** The only reason the dbFileSize variable is required is to suppress
-** unnecessary calls to xTruncate() after committing a transaction. If,
-** when a transaction is committed, the dbFileSize variable indicates
-** that the database file is larger than the database image (Pager.dbSize),
-** pager_truncate() is called. The pager_truncate() call uses xFilesize()
-** to measure the database file on disk, and then truncates it if required.
-** dbFileSize is not used when rolling back a transaction. In this case
-** pager_truncate() is called unconditionally (which means there may be
-** a call to xFilesize() that is not strictly required). In either case,
-** pager_truncate() may cause the file to become smaller or larger.
-**
-** dbHintSize
-**
-** The dbHintSize variable is used to limit the number of calls made to
-** the VFS xFileControl(FCNTL_SIZE_HINT) method.
-**
-** dbHintSize is set to a copy of the dbSize variable when a
-** write-transaction is opened (at the same time as dbFileSize and
-** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
-** dbHintSize is increased to the number of pages that correspond to the
-** size-hint passed to the method call. See pager_write_pagelist() for
-** details.
-**
-** errCode
-**
-** The Pager.errCode variable is only ever used in PAGER_ERROR state. It
-** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
-** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
-** sub-codes.
-**
-** syncFlags, walSyncFlags
-**
-** syncFlags is either SQLITE_SYNC_NORMAL (0x02) or SQLITE_SYNC_FULL (0x03).
-** syncFlags is used for rollback mode. walSyncFlags is used for WAL mode
-** and contains the flags used to sync the checkpoint operations in the
-** lower two bits, and sync flags used for transaction commits in the WAL
-** file in bits 0x04 and 0x08. In other words, to get the correct sync flags
-** for checkpoint operations, use (walSyncFlags&0x03) and to get the correct
-** sync flags for transaction commit, use ((walSyncFlags>>2)&0x03). Note
-** that with synchronous=NORMAL in WAL mode, transaction commit is not synced
-** meaning that the 0x04 and 0x08 bits are both zero.
-*/
-struct Pager {
- sqlite3_vfs *pVfs; /* OS functions to use for IO */
- u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */
- u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */
- u8 useJournal; /* Use a rollback journal on this file */
- u8 noSync; /* Do not sync the journal if true */
- u8 fullSync; /* Do extra syncs of the journal for robustness */
- u8 extraSync; /* sync directory after journal delete */
- u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
- u8 walSyncFlags; /* See description above */
- u8 tempFile; /* zFilename is a temporary or immutable file */
- u8 noLock; /* Do not lock (except in WAL mode) */
- u8 readOnly; /* True for a read-only database */
- u8 memDb; /* True to inhibit all file I/O */
-
- /**************************************************************************
- ** The following block contains those class members that change during
- ** routine operation. Class members not in this block are either fixed
- ** when the pager is first created or else only change when there is a
- ** significant mode change (such as changing the page_size, locking_mode,
- ** or the journal_mode). From another view, these class members describe
- ** the "state" of the pager, while other class members describe the
- ** "configuration" of the pager.
- */
- u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */
- u8 eLock; /* Current lock held on database file */
- u8 changeCountDone; /* Set after incrementing the change-counter */
- u8 setMaster; /* True if a m-j name has been written to jrnl */
- u8 doNotSpill; /* Do not spill the cache when non-zero */
- u8 subjInMemory; /* True to use in-memory sub-journals */
- u8 bUseFetch; /* True to use xFetch() */
- u8 hasHeldSharedLock; /* True if a shared lock has ever been held */
- Pgno dbSize; /* Number of pages in the database */
- Pgno dbOrigSize; /* dbSize before the current transaction */
- Pgno dbFileSize; /* Number of pages in the database file */
- Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */
- int errCode; /* One of several kinds of errors */
- int nRec; /* Pages journalled since last j-header written */
- u32 cksumInit; /* Quasi-random value added to every checksum */
- u32 nSubRec; /* Number of records written to sub-journal */
- Bitvec *pInJournal; /* One bit for each page in the database file */
- sqlite3_file *fd; /* File descriptor for database */
- sqlite3_file *jfd; /* File descriptor for main journal */
- sqlite3_file *sjfd; /* File descriptor for sub-journal */
- i64 journalOff; /* Current write offset in the journal file */
- i64 journalHdr; /* Byte offset to previous journal header */
- sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
- PagerSavepoint *aSavepoint; /* Array of active savepoints */
- int nSavepoint; /* Number of elements in aSavepoint[] */
- u32 iDataVersion; /* Changes whenever database content changes */
- char dbFileVers[16]; /* Changes whenever database file changes */
-
- int nMmapOut; /* Number of mmap pages currently outstanding */
- sqlite3_int64 szMmap; /* Desired maximum mmap size */
- PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */
- /*
- ** End of the routinely-changing class members
- ***************************************************************************/
-
- u16 nExtra; /* Add this many bytes to each in-memory page */
- i16 nReserve; /* Number of unused bytes at end of each page */
- u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
- u32 sectorSize; /* Assumed sector size during rollback */
- int pageSize; /* Number of bytes in a page */
- Pgno mxPgno; /* Maximum allowed size of the database */
- i64 journalSizeLimit; /* Size limit for persistent journal files */
- char *zFilename; /* Name of the database file */
- char *zJournal; /* Name of the journal file */
- int (*xBusyHandler)(void*); /* Function to call when busy */
- void *pBusyHandlerArg; /* Context argument for xBusyHandler */
- int aStat[4]; /* Total cache hits, misses, writes, spills */
-#ifdef SQLITE_TEST
- int nRead; /* Database pages read */
-#endif
- void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
- int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
-#ifdef SQLITE_HAS_CODEC
- void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
- void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
- void (*xCodecFree)(void*); /* Destructor for the codec */
- void *pCodec; /* First argument to xCodec... methods */
-#endif
- char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
- PCache *pPCache; /* Pointer to page cache object */
-#ifndef SQLITE_OMIT_WAL
- Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
- char *zWal; /* File name for write-ahead log */
-#endif
-};
-
-/*
-** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
-** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
-** or CACHE_WRITE to sqlite3_db_status().
-*/
-#define PAGER_STAT_HIT 0
-#define PAGER_STAT_MISS 1
-#define PAGER_STAT_WRITE 2
-#define PAGER_STAT_SPILL 3
-
-/*
-** The following global variables hold counters used for
-** testing purposes only. These variables do not exist in
-** a non-testing build. These variables are not thread-safe.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */
-int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */
-int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */
-# define PAGER_INCR(v) v++
-#else
-# define PAGER_INCR(v)
-#endif
-
-
-
-/*
-** Journal files begin with the following magic string. The data
-** was obtained from /dev/random. It is used only as a sanity check.
-**
-** Since version 2.8.0, the journal format contains additional sanity
-** checking information. If the power fails while the journal is being
-** written, semi-random garbage data might appear in the journal
-** file after power is restored. If an attempt is then made
-** to roll the journal back, the database could be corrupted. The additional
-** sanity checking data is an attempt to discover the garbage in the
-** journal and ignore it.
-**
-** The sanity checking information for the new journal format consists
-** of a 32-bit checksum on each page of data. The checksum covers both
-** the page number and the pPager->pageSize bytes of data for the page.
-** This cksum is initialized to a 32-bit random value that appears in the
-** journal file right after the header. The random initializer is important,
-** because garbage data that appears at the end of a journal is likely
-** data that was once in other files that have now been deleted. If the
-** garbage data came from an obsolete journal file, the checksums might
-** be correct. But by initializing the checksum to random value which
-** is different for every journal, we minimize that risk.
-*/
-static const unsigned char aJournalMagic[] = {
- 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
-};
-
-/*
-** The size of the of each page record in the journal is given by
-** the following macro.
-*/
-#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8)
-
-/*
-** The journal header size for this pager. This is usually the same
-** size as a single disk sector. See also setSectorSize().
-*/
-#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
-
-/*
-** The macro MEMDB is true if we are dealing with an in-memory database.
-** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
-** the value of MEMDB will be a constant and the compiler will optimize
-** out code that would never execute.
-*/
-#ifdef SQLITE_OMIT_MEMORYDB
-# define MEMDB 0
-#else
-# define MEMDB pPager->memDb
-#endif
-
-/*
-** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
-** interfaces to access the database using memory-mapped I/O.
-*/
-#if SQLITE_MAX_MMAP_SIZE>0
-# define USEFETCH(x) ((x)->bUseFetch)
-#else
-# define USEFETCH(x) 0
-#endif
-
-/*
-** The maximum legal page number is (2^31 - 1).
-*/
-#define PAGER_MAX_PGNO 2147483647
-
-/*
-** The argument to this macro is a file descriptor (type sqlite3_file*).
-** Return 0 if it is not open, or non-zero (but not 1) if it is.
-**
-** This is so that expressions can be written as:
-**
-** if( isOpen(pPager->jfd) ){ ...
-**
-** instead of
-**
-** if( pPager->jfd->pMethods ){ ...
-*/
-#define isOpen(pFd) ((pFd)->pMethods!=0)
-
-/*
-** Return true if this pager uses a write-ahead log to read page pgno.
-** Return false if the pager reads pgno directly from the database.
-*/
-#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
-int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
- u32 iRead = 0;
- int rc;
- if( pPager->pWal==0 ) return 0;
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return rc || iRead;
-}
-#endif
-#ifndef SQLITE_OMIT_WAL
-# define pagerUseWal(x) ((x)->pWal!=0)
-#else
-# define pagerUseWal(x) 0
-# define pagerRollbackWal(x) 0
-# define pagerWalFrames(v,w,x,y) 0
-# define pagerOpenWalIfPresent(z) SQLITE_OK
-# define pagerBeginReadTransaction(z) SQLITE_OK
-#endif
-
-#ifndef NDEBUG
-/*
-** Usage:
-**
-** assert( assert_pager_state(pPager) );
-**
-** This function runs many asserts to try to find inconsistencies in
-** the internal state of the Pager object.
-*/
-static int assert_pager_state(Pager *p){
- Pager *pPager = p;
-
- /* State must be valid. */
- assert( p->eState==PAGER_OPEN
- || p->eState==PAGER_READER
- || p->eState==PAGER_WRITER_LOCKED
- || p->eState==PAGER_WRITER_CACHEMOD
- || p->eState==PAGER_WRITER_DBMOD
- || p->eState==PAGER_WRITER_FINISHED
- || p->eState==PAGER_ERROR
- );
-
- /* Regardless of the current state, a temp-file connection always behaves
- ** as if it has an exclusive lock on the database file. It never updates
- ** the change-counter field, so the changeCountDone flag is always set.
- */
- assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
- assert( p->tempFile==0 || pPager->changeCountDone );
-
- /* If the useJournal flag is clear, the journal-mode must be "OFF".
- ** And if the journal-mode is "OFF", the journal file must not be open.
- */
- assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
- assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
-
- /* Check that MEMDB implies noSync. And an in-memory journal. Since
- ** this means an in-memory pager performs no IO at all, it cannot encounter
- ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
- ** a journal file. (although the in-memory journal implementation may
- ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
- ** is therefore not possible for an in-memory pager to enter the ERROR
- ** state.
- */
- if( MEMDB ){
- assert( !isOpen(p->fd) );
- assert( p->noSync );
- assert( p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_MEMORY
- );
- assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
- assert( pagerUseWal(p)==0 );
- }
-
- /* If changeCountDone is set, a RESERVED lock or greater must be held
- ** on the file.
- */
- assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
- assert( p->eLock!=PENDING_LOCK );
-
- switch( p->eState ){
- case PAGER_OPEN:
- assert( !MEMDB );
- assert( pPager->errCode==SQLITE_OK );
- assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
- break;
-
- case PAGER_READER:
- assert( pPager->errCode==SQLITE_OK );
- assert( p->eLock!=UNKNOWN_LOCK );
- assert( p->eLock>=SHARED_LOCK );
- break;
-
- case PAGER_WRITER_LOCKED:
- assert( p->eLock!=UNKNOWN_LOCK );
- assert( pPager->errCode==SQLITE_OK );
- if( !pagerUseWal(pPager) ){
- assert( p->eLock>=RESERVED_LOCK );
- }
- assert( pPager->dbSize==pPager->dbOrigSize );
- assert( pPager->dbOrigSize==pPager->dbFileSize );
- assert( pPager->dbOrigSize==pPager->dbHintSize );
- assert( pPager->setMaster==0 );
- break;
-
- case PAGER_WRITER_CACHEMOD:
- assert( p->eLock!=UNKNOWN_LOCK );
- assert( pPager->errCode==SQLITE_OK );
- if( !pagerUseWal(pPager) ){
- /* It is possible that if journal_mode=wal here that neither the
- ** journal file nor the WAL file are open. This happens during
- ** a rollback transaction that switches from journal_mode=off
- ** to journal_mode=wal.
- */
- assert( p->eLock>=RESERVED_LOCK );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
- );
- }
- assert( pPager->dbOrigSize==pPager->dbFileSize );
- assert( pPager->dbOrigSize==pPager->dbHintSize );
- break;
-
- case PAGER_WRITER_DBMOD:
- assert( p->eLock==EXCLUSIVE_LOCK );
- assert( pPager->errCode==SQLITE_OK );
- assert( !pagerUseWal(pPager) );
- assert( p->eLock>=EXCLUSIVE_LOCK );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
- || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
- );
- assert( pPager->dbOrigSize<=pPager->dbHintSize );
- break;
-
- case PAGER_WRITER_FINISHED:
- assert( p->eLock==EXCLUSIVE_LOCK );
- assert( pPager->errCode==SQLITE_OK );
- assert( !pagerUseWal(pPager) );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
- || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
- );
- break;
-
- case PAGER_ERROR:
- /* There must be at least one outstanding reference to the pager if
- ** in ERROR state. Otherwise the pager should have already dropped
- ** back to OPEN state.
- */
- assert( pPager->errCode!=SQLITE_OK );
- assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile );
- break;
- }
-
- return 1;
-}
-#endif /* ifndef NDEBUG */
-
-#ifdef SQLITE_DEBUG
-/*
-** Return a pointer to a human readable string in a static buffer
-** containing the state of the Pager object passed as an argument. This
-** is intended to be used within debuggers. For example, as an alternative
-** to "print *pPager" in gdb:
-**
-** (gdb) printf "%s", print_pager_state(pPager)
-*/
-static char *print_pager_state(Pager *p){
- static char zRet[1024];
-
- sqlite3_snprintf(1024, zRet,
- "Filename: %s\n"
- "State: %s errCode=%d\n"
- "Lock: %s\n"
- "Locking mode: locking_mode=%s\n"
- "Journal mode: journal_mode=%s\n"
- "Backing store: tempFile=%d memDb=%d useJournal=%d\n"
- "Journal: journalOff=%lld journalHdr=%lld\n"
- "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n"
- , p->zFilename
- , p->eState==PAGER_OPEN ? "OPEN" :
- p->eState==PAGER_READER ? "READER" :
- p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" :
- p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" :
- p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" :
- p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
- p->eState==PAGER_ERROR ? "ERROR" : "?error?"
- , (int)p->errCode
- , p->eLock==NO_LOCK ? "NO_LOCK" :
- p->eLock==RESERVED_LOCK ? "RESERVED" :
- p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" :
- p->eLock==SHARED_LOCK ? "SHARED" :
- p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?"
- , p->exclusiveMode ? "exclusive" : "normal"
- , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" :
- p->journalMode==PAGER_JOURNALMODE_OFF ? "off" :
- p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" :
- p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" :
- p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
- p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?"
- , (int)p->tempFile, (int)p->memDb, (int)p->useJournal
- , p->journalOff, p->journalHdr
- , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
- );
-
- return zRet;
-}
-#endif
-
-/* Forward references to the various page getters */
-static int getPageNormal(Pager*,Pgno,DbPage**,int);
-static int getPageError(Pager*,Pgno,DbPage**,int);
-#if SQLITE_MAX_MMAP_SIZE>0
-static int getPageMMap(Pager*,Pgno,DbPage**,int);
-#endif
-
-/*
-** Set the Pager.xGet method for the appropriate routine used to fetch
-** content from the pager.
-*/
-static void setGetterMethod(Pager *pPager){
- if( pPager->errCode ){
- pPager->xGet = getPageError;
-#if SQLITE_MAX_MMAP_SIZE>0
- }else if( USEFETCH(pPager)
-#ifdef SQLITE_HAS_CODEC
- && pPager->xCodec==0
-#endif
- ){
- pPager->xGet = getPageMMap;
-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
- }else{
- pPager->xGet = getPageNormal;
- }
-}
-
-/*
-** Return true if it is necessary to write page *pPg into the sub-journal.
-** A page needs to be written into the sub-journal if there exists one
-** or more open savepoints for which:
-**
-** * The page-number is less than or equal to PagerSavepoint.nOrig, and
-** * The bit corresponding to the page-number is not set in
-** PagerSavepoint.pInSavepoint.
-*/
-static int subjRequiresPage(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- PagerSavepoint *p;
- Pgno pgno = pPg->pgno;
- int i;
- for(i=0; i<pPager->nSavepoint; i++){
- p = &pPager->aSavepoint[i];
- if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
- return 1;
- }
- }
- return 0;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** Return true if the page is already in the journal file.
-*/
-static int pageInJournal(Pager *pPager, PgHdr *pPg){
- return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno);
-}
-#endif
-
-/*
-** Read a 32-bit integer from the given file descriptor. Store the integer
-** that is read in *pRes. Return SQLITE_OK if everything worked, or an
-** error code is something goes wrong.
-**
-** All values are stored on disk as big-endian.
-*/
-static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
- unsigned char ac[4];
- int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
- if( rc==SQLITE_OK ){
- *pRes = sqlite3Get4byte(ac);
- }
- return rc;
-}
-
-/*
-** Write a 32-bit integer into a string buffer in big-endian byte order.
-*/
-#define put32bits(A,B) sqlite3Put4byte((u8*)A,B)
-
-
-/*
-** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK
-** on success or an error code is something goes wrong.
-*/
-static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
- char ac[4];
- put32bits(ac, val);
- return sqlite3OsWrite(fd, ac, 4, offset);
-}
-
-/*
-** Unlock the database file to level eLock, which must be either NO_LOCK
-** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
-** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
-**
-** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
-** called, do not modify it. See the comment above the #define of
-** UNKNOWN_LOCK for an explanation of this.
-*/
-static int pagerUnlockDb(Pager *pPager, int eLock){
- int rc = SQLITE_OK;
-
- assert( !pPager->exclusiveMode || pPager->eLock==eLock );
- assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
- assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
- if( isOpen(pPager->fd) ){
- assert( pPager->eLock>=eLock );
- rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
- if( pPager->eLock!=UNKNOWN_LOCK ){
- pPager->eLock = (u8)eLock;
- }
- IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
- }
- return rc;
-}
-
-/*
-** Lock the database file to level eLock, which must be either SHARED_LOCK,
-** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
-** Pager.eLock variable to the new locking state.
-**
-** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
-** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
-** See the comment above the #define of UNKNOWN_LOCK for an explanation
-** of this.
-*/
-static int pagerLockDb(Pager *pPager, int eLock){
- int rc = SQLITE_OK;
-
- assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
- if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
- rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock);
- if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
- pPager->eLock = (u8)eLock;
- IOTRACE(("LOCK %p %d\n", pPager, eLock))
- }
- }
- return rc;
-}
-
-/*
-** This function determines whether or not the atomic-write or
-** atomic-batch-write optimizations can be used with this pager. The
-** atomic-write optimization can be used if:
-**
-** (a) the value returned by OsDeviceCharacteristics() indicates that
-** a database page may be written atomically, and
-** (b) the value returned by OsSectorSize() is less than or equal
-** to the page size.
-**
-** If it can be used, then the value returned is the size of the journal
-** file when it contains rollback data for exactly one page.
-**
-** The atomic-batch-write optimization can be used if OsDeviceCharacteristics()
-** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is
-** returned in this case.
-**
-** If neither optimization can be used, 0 is returned.
-*/
-static int jrnlBufferSize(Pager *pPager){
- assert( !MEMDB );
-
-#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
- || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
- int dc; /* Device characteristics */
-
- assert( isOpen(pPager->fd) );
- dc = sqlite3OsDeviceCharacteristics(pPager->fd);
-#else
- UNUSED_PARAMETER(pPager);
-#endif
-
-#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){
- return -1;
- }
-#endif
-
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
- {
- int nSector = pPager->sectorSize;
- int szPage = pPager->pageSize;
-
- assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
- assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
- if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
- return 0;
- }
- }
-
- return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
-#endif
-
- return 0;
-}
-
-/*
-** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
-** on the cache using a hash function. This is used for testing
-** and debugging only.
-*/
-#ifdef SQLITE_CHECK_PAGES
-/*
-** Return a 32-bit hash of the page data for pPage.
-*/
-static u32 pager_datahash(int nByte, unsigned char *pData){
- u32 hash = 0;
- int i;
- for(i=0; i<nByte; i++){
- hash = (hash*1039) + pData[i];
- }
- return hash;
-}
-static u32 pager_pagehash(PgHdr *pPage){
- return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
-}
-static void pager_set_pagehash(PgHdr *pPage){
- pPage->pageHash = pager_pagehash(pPage);
-}
-
-/*
-** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
-** is defined, and NDEBUG is not defined, an assert() statement checks
-** that the page is either dirty or still matches the calculated page-hash.
-*/
-#define CHECK_PAGE(x) checkPage(x)
-static void checkPage(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- assert( pPager->eState!=PAGER_ERROR );
- assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
-}
-
-#else
-#define pager_datahash(X,Y) 0
-#define pager_pagehash(X) 0
-#define pager_set_pagehash(X)
-#define CHECK_PAGE(x)
-#endif /* SQLITE_CHECK_PAGES */
-
-/*
-** When this is called the journal file for pager pPager must be open.
-** This function attempts to read a master journal file name from the
-** end of the file and, if successful, copies it into memory supplied
-** by the caller. See comments above writeMasterJournal() for the format
-** used to store a master journal file name at the end of a journal file.
-**
-** zMaster must point to a buffer of at least nMaster bytes allocated by
-** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
-** enough space to write the master journal name). If the master journal
-** name in the journal is longer than nMaster bytes (including a
-** nul-terminator), then this is handled as if no master journal name
-** were present in the journal.
-**
-** If a master journal file name is present at the end of the journal
-** file, then it is copied into the buffer pointed to by zMaster. A
-** nul-terminator byte is appended to the buffer following the master
-** journal file name.
-**
-** If it is determined that no master journal file name is present
-** zMaster[0] is set to 0 and SQLITE_OK returned.
-**
-** If an error occurs while reading from the journal file, an SQLite
-** error code is returned.
-*/
-static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
- int rc; /* Return code */
- u32 len; /* Length in bytes of master journal name */
- i64 szJ; /* Total size in bytes of journal file pJrnl */
- u32 cksum; /* MJ checksum value read from journal */
- u32 u; /* Unsigned loop counter */
- unsigned char aMagic[8]; /* A buffer to hold the magic header */
- zMaster[0] = '\0';
-
- if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
- || szJ<16
- || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
- || len>=nMaster
- || len>szJ-16
- || len==0
- || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
- || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
- || memcmp(aMagic, aJournalMagic, 8)
- || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
- ){
- return rc;
- }
-
- /* See if the checksum matches the master journal name */
- for(u=0; u<len; u++){
- cksum -= zMaster[u];
- }
- if( cksum ){
- /* If the checksum doesn't add up, then one or more of the disk sectors
- ** containing the master journal filename is corrupted. This means
- ** definitely roll back, so just return SQLITE_OK and report a (nul)
- ** master-journal filename.
- */
- len = 0;
- }
- zMaster[len] = '\0';
-
- return SQLITE_OK;
-}
-
-/*
-** Return the offset of the sector boundary at or immediately
-** following the value in pPager->journalOff, assuming a sector
-** size of pPager->sectorSize bytes.
-**
-** i.e for a sector size of 512:
-**
-** Pager.journalOff Return value
-** ---------------------------------------
-** 0 0
-** 512 512
-** 100 512
-** 2000 2048
-**
-*/
-static i64 journalHdrOffset(Pager *pPager){
- i64 offset = 0;
- i64 c = pPager->journalOff;
- if( c ){
- offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
- }
- assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
- assert( offset>=c );
- assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
- return offset;
-}
-
-/*
-** The journal file must be open when this function is called.
-**
-** This function is a no-op if the journal file has not been written to
-** within the current transaction (i.e. if Pager.journalOff==0).
-**
-** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
-** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
-** zero the 28-byte header at the start of the journal file. In either case,
-** if the pager is not in no-sync mode, sync the journal file immediately
-** after writing or truncating it.
-**
-** If Pager.journalSizeLimit is set to a positive, non-zero value, and
-** following the truncation or zeroing described above the size of the
-** journal file in bytes is larger than this value, then truncate the
-** journal file to Pager.journalSizeLimit bytes. The journal file does
-** not need to be synced following this operation.
-**
-** If an IO error occurs, abandon processing and return the IO error code.
-** Otherwise, return SQLITE_OK.
-*/
-static int zeroJournalHdr(Pager *pPager, int doTruncate){
- int rc = SQLITE_OK; /* Return code */
- assert( isOpen(pPager->jfd) );
- assert( !sqlite3JournalIsInMemory(pPager->jfd) );
- if( pPager->journalOff ){
- const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */
-
- IOTRACE(("JZEROHDR %p\n", pPager))
- if( doTruncate || iLimit==0 ){
- rc = sqlite3OsTruncate(pPager->jfd, 0);
- }else{
- static const char zeroHdr[28] = {0};
- rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
- }
- if( rc==SQLITE_OK && !pPager->noSync ){
- rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
- }
-
- /* At this point the transaction is committed but the write lock
- ** is still held on the file. If there is a size limit configured for
- ** the persistent journal and the journal file currently consumes more
- ** space than that limit allows for, truncate it now. There is no need
- ** to sync the file following this operation.
- */
- if( rc==SQLITE_OK && iLimit>0 ){
- i64 sz;
- rc = sqlite3OsFileSize(pPager->jfd, &sz);
- if( rc==SQLITE_OK && sz>iLimit ){
- rc = sqlite3OsTruncate(pPager->jfd, iLimit);
- }
- }
- }
- return rc;
-}
-
-/*
-** The journal file must be open when this routine is called. A journal
-** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
-** current location.
-**
-** The format for the journal header is as follows:
-** - 8 bytes: Magic identifying journal format.
-** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
-** - 4 bytes: Random number used for page hash.
-** - 4 bytes: Initial database page count.
-** - 4 bytes: Sector size used by the process that wrote this journal.
-** - 4 bytes: Database page size.
-**
-** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
-*/
-static int writeJournalHdr(Pager *pPager){
- int rc = SQLITE_OK; /* Return code */
- char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */
- u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */
- u32 nWrite; /* Bytes of header sector written */
- int ii; /* Loop counter */
-
- assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
-
- if( nHeader>JOURNAL_HDR_SZ(pPager) ){
- nHeader = JOURNAL_HDR_SZ(pPager);
- }
-
- /* If there are active savepoints and any of them were created
- ** since the most recent journal header was written, update the
- ** PagerSavepoint.iHdrOffset fields now.
- */
- for(ii=0; ii<pPager->nSavepoint; ii++){
- if( pPager->aSavepoint[ii].iHdrOffset==0 ){
- pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff;
- }
- }
-
- pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);
-
- /*
- ** Write the nRec Field - the number of page records that follow this
- ** journal header. Normally, zero is written to this value at this time.
- ** After the records are added to the journal (and the journal synced,
- ** if in full-sync mode), the zero is overwritten with the true number
- ** of records (see syncJournal()).
- **
- ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
- ** reading the journal this value tells SQLite to assume that the
- ** rest of the journal file contains valid page records. This assumption
- ** is dangerous, as if a failure occurred whilst writing to the journal
- ** file it may contain some garbage data. There are two scenarios
- ** where this risk can be ignored:
- **
- ** * When the pager is in no-sync mode. Corruption can follow a
- ** power failure in this case anyway.
- **
- ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
- ** that garbage data is never appended to the journal file.
- */
- assert( isOpen(pPager->fd) || pPager->noSync );
- if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
- || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
- ){
- memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
- put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
- }else{
- memset(zHeader, 0, sizeof(aJournalMagic)+4);
- }
-
- /* The random check-hash initializer */
- sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
- put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
- /* The initial database size */
- put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize);
- /* The assumed sector size for this process */
- put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
-
- /* The page size */
- put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
-
- /* Initializing the tail of the buffer is not necessary. Everything
- ** works find if the following memset() is omitted. But initializing
- ** the memory prevents valgrind from complaining, so we are willing to
- ** take the performance hit.
- */
- memset(&zHeader[sizeof(aJournalMagic)+20], 0,
- nHeader-(sizeof(aJournalMagic)+20));
-
- /* In theory, it is only necessary to write the 28 bytes that the
- ** journal header consumes to the journal file here. Then increment the
- ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
- ** record is written to the following sector (leaving a gap in the file
- ** that will be implicitly filled in by the OS).
- **
- ** However it has been discovered that on some systems this pattern can
- ** be significantly slower than contiguously writing data to the file,
- ** even if that means explicitly writing data to the block of
- ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
- ** is done.
- **
- ** The loop is required here in case the sector-size is larger than the
- ** database page size. Since the zHeader buffer is only Pager.pageSize
- ** bytes in size, more than one call to sqlite3OsWrite() may be required
- ** to populate the entire journal header sector.
- */
- for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
- IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
- rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
- assert( pPager->journalHdr <= pPager->journalOff );
- pPager->journalOff += nHeader;
- }
-
- return rc;
-}
-
-/*
-** The journal file must be open when this is called. A journal header file
-** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
-** file. The current location in the journal file is given by
-** pPager->journalOff. See comments above function writeJournalHdr() for
-** a description of the journal header format.
-**
-** If the header is read successfully, *pNRec is set to the number of
-** page records following this header and *pDbSize is set to the size of the
-** database before the transaction began, in pages. Also, pPager->cksumInit
-** is set to the value read from the journal header. SQLITE_OK is returned
-** in this case.
-**
-** If the journal header file appears to be corrupted, SQLITE_DONE is
-** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes
-** cannot be read from the journal file an error code is returned.
-*/
-static int readJournalHdr(
- Pager *pPager, /* Pager object */
- int isHot,
- i64 journalSize, /* Size of the open journal file in bytes */
- u32 *pNRec, /* OUT: Value read from the nRec field */
- u32 *pDbSize /* OUT: Value of original database size field */
-){
- int rc; /* Return code */
- unsigned char aMagic[8]; /* A buffer to hold the magic header */
- i64 iHdrOff; /* Offset of journal header being read */
-
- assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
-
- /* Advance Pager.journalOff to the start of the next sector. If the
- ** journal file is too small for there to be a header stored at this
- ** point, return SQLITE_DONE.
- */
- pPager->journalOff = journalHdrOffset(pPager);
- if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
- return SQLITE_DONE;
- }
- iHdrOff = pPager->journalOff;
-
- /* Read in the first 8 bytes of the journal header. If they do not match
- ** the magic string found at the start of each journal header, return
- ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise,
- ** proceed.
- */
- if( isHot || iHdrOff!=pPager->journalHdr ){
- rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff);
- if( rc ){
- return rc;
- }
- if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
- return SQLITE_DONE;
- }
- }
-
- /* Read the first three 32-bit fields of the journal header: The nRec
- ** field, the checksum-initializer and the database size at the start
- ** of the transaction. Return an error code if anything goes wrong.
- */
- if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec))
- || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit))
- || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize))
- ){
- return rc;
- }
-
- if( pPager->journalOff==0 ){
- u32 iPageSize; /* Page-size field of journal header */
- u32 iSectorSize; /* Sector-size field of journal header */
-
- /* Read the page-size and sector-size journal header fields. */
- if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize))
- || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize))
- ){
- return rc;
- }
-
- /* Versions of SQLite prior to 3.5.8 set the page-size field of the
- ** journal header to zero. In this case, assume that the Pager.pageSize
- ** variable is already set to the correct page size.
- */
- if( iPageSize==0 ){
- iPageSize = pPager->pageSize;
- }
-
- /* Check that the values read from the page-size and sector-size fields
- ** are within range. To be 'in range', both values need to be a power
- ** of two greater than or equal to 512 or 32, and not greater than their
- ** respective compile time maximum limits.
- */
- if( iPageSize<512 || iSectorSize<32
- || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
- || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0
- ){
- /* If the either the page-size or sector-size in the journal-header is
- ** invalid, then the process that wrote the journal-header must have
- ** crashed before the header was synced. In this case stop reading
- ** the journal file here.
- */
- return SQLITE_DONE;
- }
-
- /* Update the page-size to match the value read from the journal.
- ** Use a testcase() macro to make sure that malloc failure within
- ** PagerSetPagesize() is tested.
- */
- rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
- testcase( rc!=SQLITE_OK );
-
- /* Update the assumed sector-size to match the value used by
- ** the process that created this journal. If this journal was
- ** created by a process other than this one, then this routine
- ** is being called from within pager_playback(). The local value
- ** of Pager.sectorSize is restored at the end of that routine.
- */
- pPager->sectorSize = iSectorSize;
- }
-
- pPager->journalOff += JOURNAL_HDR_SZ(pPager);
- return rc;
-}
-
-
-/*
-** Write the supplied master journal name into the journal file for pager
-** pPager at the current location. The master journal name must be the last
-** thing written to a journal file. If the pager is in full-sync mode, the
-** journal file descriptor is advanced to the next sector boundary before
-** anything is written. The format is:
-**
-** + 4 bytes: PAGER_MJ_PGNO.
-** + N bytes: Master journal filename in utf-8.
-** + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
-** + 4 bytes: Master journal name checksum.
-** + 8 bytes: aJournalMagic[].
-**
-** The master journal page checksum is the sum of the bytes in the master
-** journal name, where each byte is interpreted as a signed 8-bit integer.
-**
-** If zMaster is a NULL pointer (occurs for a single database transaction),
-** this call is a no-op.
-*/
-static int writeMasterJournal(Pager *pPager, const char *zMaster){
- int rc; /* Return code */
- int nMaster; /* Length of string zMaster */
- i64 iHdrOff; /* Offset of header in journal file */
- i64 jrnlSize; /* Size of journal file on disk */
- u32 cksum = 0; /* Checksum of string zMaster */
-
- assert( pPager->setMaster==0 );
- assert( !pagerUseWal(pPager) );
-
- if( !zMaster
- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
- || !isOpen(pPager->jfd)
- ){
- return SQLITE_OK;
- }
- pPager->setMaster = 1;
- assert( pPager->journalHdr <= pPager->journalOff );
-
- /* Calculate the length in bytes and the checksum of zMaster */
- for(nMaster=0; zMaster[nMaster]; nMaster++){
- cksum += zMaster[nMaster];
- }
-
- /* If in full-sync mode, advance to the next disk sector before writing
- ** the master journal name. This is in case the previous page written to
- ** the journal has already been synced.
- */
- if( pPager->fullSync ){
- pPager->journalOff = journalHdrOffset(pPager);
- }
- iHdrOff = pPager->journalOff;
-
- /* Write the master journal data to the end of the journal file. If
- ** an error occurs, return the error code to the caller.
- */
- if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
- || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
- || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
- || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
- || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8,
- iHdrOff+4+nMaster+8)))
- ){
- return rc;
- }
- pPager->journalOff += (nMaster+20);
-
- /* If the pager is in peristent-journal mode, then the physical
- ** journal-file may extend past the end of the master-journal name
- ** and 8 bytes of magic data just written to the file. This is
- ** dangerous because the code to rollback a hot-journal file
- ** will not be able to find the master-journal name to determine
- ** whether or not the journal is hot.
- **
- ** Easiest thing to do in this scenario is to truncate the journal
- ** file to the required size.
- */
- if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
- && jrnlSize>pPager->journalOff
- ){
- rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff);
- }
- return rc;
-}
-
-/*
-** Discard the entire contents of the in-memory page-cache.
-*/
-static void pager_reset(Pager *pPager){
- pPager->iDataVersion++;
- sqlite3BackupRestart(pPager->pBackup);
- sqlite3PcacheClear(pPager->pPCache);
-}
-
-/*
-** Return the pPager->iDataVersion value
-*/
-u32 sqlite3PagerDataVersion(Pager *pPager){
- assert( pPager->eState>PAGER_OPEN );
- return pPager->iDataVersion;
-}
-
-/*
-** Free all structures in the Pager.aSavepoint[] array and set both
-** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
-** if it is open and the pager is not in exclusive mode.
-*/
-static void releaseAllSavepoints(Pager *pPager){
- int ii; /* Iterator for looping through Pager.aSavepoint */
- for(ii=0; ii<pPager->nSavepoint; ii++){
- sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
- }
- if( !pPager->exclusiveMode || sqlite3JournalIsInMemory(pPager->sjfd) ){
- sqlite3OsClose(pPager->sjfd);
- }
- sqlite3_free(pPager->aSavepoint);
- pPager->aSavepoint = 0;
- pPager->nSavepoint = 0;
- pPager->nSubRec = 0;
-}
-
-/*
-** Set the bit number pgno in the PagerSavepoint.pInSavepoint
-** bitvecs of all open savepoints. Return SQLITE_OK if successful
-** or SQLITE_NOMEM if a malloc failure occurs.
-*/
-static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
- int ii; /* Loop counter */
- int rc = SQLITE_OK; /* Result code */
-
- for(ii=0; ii<pPager->nSavepoint; ii++){
- PagerSavepoint *p = &pPager->aSavepoint[ii];
- if( pgno<=p->nOrig ){
- rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
- testcase( rc==SQLITE_NOMEM );
- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
- }
- }
- return rc;
-}
-
-/*
-** This function is a no-op if the pager is in exclusive mode and not
-** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
-** state.
-**
-** If the pager is not in exclusive-access mode, the database file is
-** completely unlocked. If the file is unlocked and the file-system does
-** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
-** closed (if it is open).
-**
-** If the pager is in ERROR state when this function is called, the
-** contents of the pager cache are discarded before switching back to
-** the OPEN state. Regardless of whether the pager is in exclusive-mode
-** or not, any journal file left in the file-system will be treated
-** as a hot-journal and rolled back the next time a read-transaction
-** is opened (by this or by any other connection).
-*/
-static void pager_unlock(Pager *pPager){
-
- assert( pPager->eState==PAGER_READER
- || pPager->eState==PAGER_OPEN
- || pPager->eState==PAGER_ERROR
- );
-
- sqlite3BitvecDestroy(pPager->pInJournal);
- pPager->pInJournal = 0;
- releaseAllSavepoints(pPager);
-
- if( pagerUseWal(pPager) ){
- assert( !isOpen(pPager->jfd) );
- sqlite3WalEndReadTransaction(pPager->pWal);
- pPager->eState = PAGER_OPEN;
- }else if( !pPager->exclusiveMode ){
- int rc; /* Error code returned by pagerUnlockDb() */
- int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
-
- /* If the operating system support deletion of open files, then
- ** close the journal file when dropping the database lock. Otherwise
- ** another connection with journal_mode=delete might delete the file
- ** out from under us.
- */
- assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 );
- assert( (PAGER_JOURNALMODE_OFF & 5)!=1 );
- assert( (PAGER_JOURNALMODE_WAL & 5)!=1 );
- assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 );
- assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
- assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
- if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
- || 1!=(pPager->journalMode & 5)
- ){
- sqlite3OsClose(pPager->jfd);
- }
-
- /* If the pager is in the ERROR state and the call to unlock the database
- ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
- ** above the #define for UNKNOWN_LOCK for an explanation of why this
- ** is necessary.
- */
- rc = pagerUnlockDb(pPager, NO_LOCK);
- if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
- pPager->eLock = UNKNOWN_LOCK;
- }
-
- /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
- ** without clearing the error code. This is intentional - the error
- ** code is cleared and the cache reset in the block below.
- */
- assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
- pPager->changeCountDone = 0;
- pPager->eState = PAGER_OPEN;
- }
-
- /* If Pager.errCode is set, the contents of the pager cache cannot be
- ** trusted. Now that there are no outstanding references to the pager,
- ** it can safely move back to PAGER_OPEN state. This happens in both
- ** normal and exclusive-locking mode.
- */
- assert( pPager->errCode==SQLITE_OK || !MEMDB );
- if( pPager->errCode ){
- if( pPager->tempFile==0 ){
- pager_reset(pPager);
- pPager->changeCountDone = 0;
- pPager->eState = PAGER_OPEN;
- }else{
- pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
- }
- if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
- pPager->errCode = SQLITE_OK;
- setGetterMethod(pPager);
- }
-
- pPager->journalOff = 0;
- pPager->journalHdr = 0;
- pPager->setMaster = 0;
-}
-
-/*
-** This function is called whenever an IOERR or FULL error that requires
-** the pager to transition into the ERROR state may ahve occurred.
-** The first argument is a pointer to the pager structure, the second
-** the error-code about to be returned by a pager API function. The
-** value returned is a copy of the second argument to this function.
-**
-** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
-** IOERR sub-codes, the pager enters the ERROR state and the error code
-** is stored in Pager.errCode. While the pager remains in the ERROR state,
-** all major API calls on the Pager will immediately return Pager.errCode.
-**
-** The ERROR state indicates that the contents of the pager-cache
-** cannot be trusted. This state can be cleared by completely discarding
-** the contents of the pager-cache. If a transaction was active when
-** the persistent error occurred, then the rollback journal may need
-** to be replayed to restore the contents of the database file (as if
-** it were a hot-journal).
-*/
-static int pager_error(Pager *pPager, int rc){
- int rc2 = rc & 0xff;
- assert( rc==SQLITE_OK || !MEMDB );
- assert(
- pPager->errCode==SQLITE_FULL ||
- pPager->errCode==SQLITE_OK ||
- (pPager->errCode & 0xff)==SQLITE_IOERR
- );
- if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
- pPager->errCode = rc;
- pPager->eState = PAGER_ERROR;
- setGetterMethod(pPager);
- }
- return rc;
-}
-
-static int pager_truncate(Pager *pPager, Pgno nPage);
-
-/*
-** The write transaction open on pPager is being committed (bCommit==1)
-** or rolled back (bCommit==0).
-**
-** Return TRUE if and only if all dirty pages should be flushed to disk.
-**
-** Rules:
-**
-** * For non-TEMP databases, always sync to disk. This is necessary
-** for transactions to be durable.
-**
-** * Sync TEMP database only on a COMMIT (not a ROLLBACK) when the backing
-** file has been created already (via a spill on pagerStress()) and
-** when the number of dirty pages in memory exceeds 25% of the total
-** cache size.
-*/
-static int pagerFlushOnCommit(Pager *pPager, int bCommit){
- if( pPager->tempFile==0 ) return 1;
- if( !bCommit ) return 0;
- if( !isOpen(pPager->fd) ) return 0;
- return (sqlite3PCachePercentDirty(pPager->pPCache)>=25);
-}
-
-/*
-** This routine ends a transaction. A transaction is usually ended by
-** either a COMMIT or a ROLLBACK operation. This routine may be called
-** after rollback of a hot-journal, or if an error occurs while opening
-** the journal file or writing the very first journal-header of a
-** database transaction.
-**
-** This routine is never called in PAGER_ERROR state. If it is called
-** in PAGER_NONE or PAGER_SHARED state and the lock held is less
-** exclusive than a RESERVED lock, it is a no-op.
-**
-** Otherwise, any active savepoints are released.
-**
-** If the journal file is open, then it is "finalized". Once a journal
-** file has been finalized it is not possible to use it to roll back a
-** transaction. Nor will it be considered to be a hot-journal by this
-** or any other database connection. Exactly how a journal is finalized
-** depends on whether or not the pager is running in exclusive mode and
-** the current journal-mode (Pager.journalMode value), as follows:
-**
-** journalMode==MEMORY
-** Journal file descriptor is simply closed. This destroys an
-** in-memory journal.
-**
-** journalMode==TRUNCATE
-** Journal file is truncated to zero bytes in size.
-**
-** journalMode==PERSIST
-** The first 28 bytes of the journal file are zeroed. This invalidates
-** the first journal header in the file, and hence the entire journal
-** file. An invalid journal file cannot be rolled back.
-**
-** journalMode==DELETE
-** The journal file is closed and deleted using sqlite3OsDelete().
-**
-** If the pager is running in exclusive mode, this method of finalizing
-** the journal file is never used. Instead, if the journalMode is
-** DELETE and the pager is in exclusive mode, the method described under
-** journalMode==PERSIST is used instead.
-**
-** After the journal is finalized, the pager moves to PAGER_READER state.
-** If running in non-exclusive rollback mode, the lock on the file is
-** downgraded to a SHARED_LOCK.
-**
-** SQLITE_OK is returned if no error occurs. If an error occurs during
-** any of the IO operations to finalize the journal file or unlock the
-** database then the IO error code is returned to the user. If the
-** operation to finalize the journal file fails, then the code still
-** tries to unlock the database file if not in exclusive mode. If the
-** unlock operation fails as well, then the first error code related
-** to the first error encountered (the journal finalization one) is
-** returned.
-*/
-static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
- int rc = SQLITE_OK; /* Error code from journal finalization operation */
- int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
-
- /* Do nothing if the pager does not have an open write transaction
- ** or at least a RESERVED lock. This function may be called when there
- ** is no write-transaction active but a RESERVED or greater lock is
- ** held under two circumstances:
- **
- ** 1. After a successful hot-journal rollback, it is called with
- ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
- **
- ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
- ** lock switches back to locking_mode=normal and then executes a
- ** read-transaction, this function is called with eState==PAGER_READER
- ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
- */
- assert( assert_pager_state(pPager) );
- assert( pPager->eState!=PAGER_ERROR );
- if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){
- return SQLITE_OK;
- }
-
- releaseAllSavepoints(pPager);
- assert( isOpen(pPager->jfd) || pPager->pInJournal==0
- || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
- );
- if( isOpen(pPager->jfd) ){
- assert( !pagerUseWal(pPager) );
-
- /* Finalize the journal file. */
- if( sqlite3JournalIsInMemory(pPager->jfd) ){
- /* assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); */
- sqlite3OsClose(pPager->jfd);
- }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
- if( pPager->journalOff==0 ){
- rc = SQLITE_OK;
- }else{
- rc = sqlite3OsTruncate(pPager->jfd, 0);
- if( rc==SQLITE_OK && pPager->fullSync ){
- /* Make sure the new file size is written into the inode right away.
- ** Otherwise the journal might resurrect following a power loss and
- ** cause the last transaction to roll back. See
- ** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773
- */
- rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
- }
- }
- pPager->journalOff = 0;
- }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
- || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
- ){
- rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile);
- pPager->journalOff = 0;
- }else{
- /* This branch may be executed with Pager.journalMode==MEMORY if
- ** a hot-journal was just rolled back. In this case the journal
- ** file should be closed and deleted. If this connection writes to
- ** the database file, it will do so using an in-memory journal.
- */
- int bDelete = !pPager->tempFile;
- assert( sqlite3JournalIsInMemory(pPager->jfd)==0 );
- assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
- );
- sqlite3OsClose(pPager->jfd);
- if( bDelete ){
- rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync);
- }
- }
- }
-
-#ifdef SQLITE_CHECK_PAGES
- sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
- if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
- PgHdr *p = sqlite3PagerLookup(pPager, 1);
- if( p ){
- p->pageHash = 0;
- sqlite3PagerUnrefNotNull(p);
- }
- }
-#endif
-
- sqlite3BitvecDestroy(pPager->pInJournal);
- pPager->pInJournal = 0;
- pPager->nRec = 0;
- if( rc==SQLITE_OK ){
- if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){
- sqlite3PcacheCleanAll(pPager->pPCache);
- }else{
- sqlite3PcacheClearWritable(pPager->pPCache);
- }
- sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
- }
-
- if( pagerUseWal(pPager) ){
- /* Drop the WAL write-lock, if any. Also, if the connection was in
- ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
- ** lock held on the database file.
- */
- rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
- assert( rc2==SQLITE_OK );
- }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
- /* This branch is taken when committing a transaction in rollback-journal
- ** mode if the database file on disk is larger than the database image.
- ** At this point the journal has been finalized and the transaction
- ** successfully committed, but the EXCLUSIVE lock is still held on the
- ** file. So it is safe to truncate the database file to its minimum
- ** required size. */
- assert( pPager->eLock==EXCLUSIVE_LOCK );
- rc = pager_truncate(pPager, pPager->dbSize);
- }
-
- if( rc==SQLITE_OK && bCommit ){
- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
- if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
- }
-
- if( !pPager->exclusiveMode
- && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
- ){
- rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
- pPager->changeCountDone = 0;
- }
- pPager->eState = PAGER_READER;
- pPager->setMaster = 0;
-
- return (rc==SQLITE_OK?rc2:rc);
-}
-
-/*
-** Execute a rollback if a transaction is active and unlock the
-** database file.
-**
-** If the pager has already entered the ERROR state, do not attempt
-** the rollback at this time. Instead, pager_unlock() is called. The
-** call to pager_unlock() will discard all in-memory pages, unlock
-** the database file and move the pager back to OPEN state. If this
-** means that there is a hot-journal left in the file-system, the next
-** connection to obtain a shared lock on the pager (which may be this one)
-** will roll it back.
-**
-** If the pager has not already entered the ERROR state, but an IO or
-** malloc error occurs during a rollback, then this will itself cause
-** the pager to enter the ERROR state. Which will be cleared by the
-** call to pager_unlock(), as described above.
-*/
-static void pagerUnlockAndRollback(Pager *pPager){
- if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){
- assert( assert_pager_state(pPager) );
- if( pPager->eState>=PAGER_WRITER_LOCKED ){
- sqlite3BeginBenignMalloc();
- sqlite3PagerRollback(pPager);
- sqlite3EndBenignMalloc();
- }else if( !pPager->exclusiveMode ){
- assert( pPager->eState==PAGER_READER );
- pager_end_transaction(pPager, 0, 0);
- }
- }
- pager_unlock(pPager);
-}
-
-/*
-** Parameter aData must point to a buffer of pPager->pageSize bytes
-** of data. Compute and return a checksum based ont the contents of the
-** page of data and the current value of pPager->cksumInit.
-**
-** This is not a real checksum. It is really just the sum of the
-** random initial value (pPager->cksumInit) and every 200th byte
-** of the page data, starting with byte offset (pPager->pageSize%200).
-** Each byte is interpreted as an 8-bit unsigned integer.
-**
-** Changing the formula used to compute this checksum results in an
-** incompatible journal file format.
-**
-** If journal corruption occurs due to a power failure, the most likely
-** scenario is that one end or the other of the record will be changed.
-** It is much less likely that the two ends of the journal record will be
-** correct and the middle be corrupt. Thus, this "checksum" scheme,
-** though fast and simple, catches the mostly likely kind of corruption.
-*/
-static u32 pager_cksum(Pager *pPager, const u8 *aData){
- u32 cksum = pPager->cksumInit; /* Checksum value to return */
- int i = pPager->pageSize-200; /* Loop counter */
- while( i>0 ){
- cksum += aData[i];
- i -= 200;
- }
- return cksum;
-}
-
-/*
-** Report the current page size and number of reserved bytes back
-** to the codec.
-*/
-#ifdef SQLITE_HAS_CODEC
-static void pagerReportSize(Pager *pPager){
- if( pPager->xCodecSizeChng ){
- pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
- (int)pPager->nReserve);
- }
-}
-#else
-# define pagerReportSize(X) /* No-op if we do not support a codec */
-#endif
-
-#ifdef SQLITE_HAS_CODEC
-/*
-** Make sure the number of reserved bits is the same in the destination
-** pager as it is in the source. This comes up when a VACUUM changes the
-** number of reserved bits to the "optimal" amount.
-*/
-void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){
- if( pDest->nReserve!=pSrc->nReserve ){
- pDest->nReserve = pSrc->nReserve;
- pagerReportSize(pDest);
- }
-}
-#endif
-
-/*
-** Read a single page from either the journal file (if isMainJrnl==1) or
-** from the sub-journal (if isMainJrnl==0) and playback that page.
-** The page begins at offset *pOffset into the file. The *pOffset
-** value is increased to the start of the next page in the journal.
-**
-** The main rollback journal uses checksums - the statement journal does
-** not.
-**
-** If the page number of the page record read from the (sub-)journal file
-** is greater than the current value of Pager.dbSize, then playback is
-** skipped and SQLITE_OK is returned.
-**
-** If pDone is not NULL, then it is a record of pages that have already
-** been played back. If the page at *pOffset has already been played back
-** (if the corresponding pDone bit is set) then skip the playback.
-** Make sure the pDone bit corresponding to the *pOffset page is set
-** prior to returning.
-**
-** If the page record is successfully read from the (sub-)journal file
-** and played back, then SQLITE_OK is returned. If an IO error occurs
-** while reading the record from the (sub-)journal file or while writing
-** to the database file, then the IO error code is returned. If data
-** is successfully read from the (sub-)journal file but appears to be
-** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
-** two circumstances:
-**
-** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
-** * If the record is being rolled back from the main journal file
-** and the checksum field does not match the record content.
-**
-** Neither of these two scenarios are possible during a savepoint rollback.
-**
-** If this is a savepoint rollback, then memory may have to be dynamically
-** allocated by this function. If this is the case and an allocation fails,
-** SQLITE_NOMEM is returned.
-*/
-static int pager_playback_one_page(
- Pager *pPager, /* The pager being played back */
- i64 *pOffset, /* Offset of record to playback */
- Bitvec *pDone, /* Bitvec of pages already played back */
- int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */
- int isSavepnt /* True for a savepoint rollback */
-){
- int rc;
- PgHdr *pPg; /* An existing page in the cache */
- Pgno pgno; /* The page number of a page in journal */
- u32 cksum; /* Checksum used for sanity checking */
- char *aData; /* Temporary storage for the page */
- sqlite3_file *jfd; /* The file descriptor for the journal file */
- int isSynced; /* True if journal page is synced */
-#ifdef SQLITE_HAS_CODEC
- /* The jrnlEnc flag is true if Journal pages should be passed through
- ** the codec. It is false for pure in-memory journals. */
- const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0);
-#endif
-
- assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
- assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
- assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */
- assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */
-
- aData = pPager->pTmpSpace;
- assert( aData ); /* Temp storage must have already been allocated */
- assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
-
- /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
- ** or savepoint rollback done at the request of the caller) or this is
- ** a hot-journal rollback. If it is a hot-journal rollback, the pager
- ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
- ** only reads from the main journal, not the sub-journal.
- */
- assert( pPager->eState>=PAGER_WRITER_CACHEMOD
- || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
- );
- assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );
-
- /* Read the page number and page data from the journal or sub-journal
- ** file. Return an error code to the caller if an IO error occurs.
- */
- jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
- rc = read32bits(jfd, *pOffset, &pgno);
- if( rc!=SQLITE_OK ) return rc;
- rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
- if( rc!=SQLITE_OK ) return rc;
- *pOffset += pPager->pageSize + 4 + isMainJrnl*4;
-
- /* Sanity checking on the page. This is more important that I originally
- ** thought. If a power failure occurs while the journal is being written,
- ** it could cause invalid data to be written into the journal. We need to
- ** detect this invalid data (with high probability) and ignore it.
- */
- if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
- assert( !isSavepnt );
- return SQLITE_DONE;
- }
- if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
- return SQLITE_OK;
- }
- if( isMainJrnl ){
- rc = read32bits(jfd, (*pOffset)-4, &cksum);
- if( rc ) return rc;
- if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
- return SQLITE_DONE;
- }
- }
-
- /* If this page has already been played back before during the current
- ** rollback, then don't bother to play it back again.
- */
- if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
- return rc;
- }
-
- /* When playing back page 1, restore the nReserve setting
- */
- if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
- pPager->nReserve = ((u8*)aData)[20];
- pagerReportSize(pPager);
- }
-
- /* If the pager is in CACHEMOD state, then there must be a copy of this
- ** page in the pager cache. In this case just update the pager cache,
- ** not the database file. The page is left marked dirty in this case.
- **
- ** An exception to the above rule: If the database is in no-sync mode
- ** and a page is moved during an incremental vacuum then the page may
- ** not be in the pager cache. Later: if a malloc() or IO error occurs
- ** during a Movepage() call, then the page may not be in the cache
- ** either. So the condition described in the above paragraph is not
- ** assert()able.
- **
- ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
- ** pager cache if it exists and the main file. The page is then marked
- ** not dirty. Since this code is only executed in PAGER_OPEN state for
- ** a hot-journal rollback, it is guaranteed that the page-cache is empty
- ** if the pager is in OPEN state.
- **
- ** Ticket #1171: The statement journal might contain page content that is
- ** different from the page content at the start of the transaction.
- ** This occurs when a page is changed prior to the start of a statement
- ** then changed again within the statement. When rolling back such a
- ** statement we must not write to the original database unless we know
- ** for certain that original page contents are synced into the main rollback
- ** journal. Otherwise, a power loss might leave modified data in the
- ** database file without an entry in the rollback journal that can
- ** restore the database to its original form. Two conditions must be
- ** met before writing to the database files. (1) the database must be
- ** locked. (2) we know that the original page content is fully synced
- ** in the main journal either because the page is not in cache or else
- ** the page is marked as needSync==0.
- **
- ** 2008-04-14: When attempting to vacuum a corrupt database file, it
- ** is possible to fail a statement on a database that does not yet exist.
- ** Do not attempt to write if database file has never been opened.
- */
- if( pagerUseWal(pPager) ){
- pPg = 0;
- }else{
- pPg = sqlite3PagerLookup(pPager, pgno);
- }
- assert( pPg || !MEMDB );
- assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile );
- PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
- PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
- (isMainJrnl?"main-journal":"sub-journal")
- ));
- if( isMainJrnl ){
- isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
- }else{
- isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
- }
- if( isOpen(pPager->fd)
- && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
- && isSynced
- ){
- i64 ofst = (pgno-1)*(i64)pPager->pageSize;
- testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
- assert( !pagerUseWal(pPager) );
-
- /* Write the data read from the journal back into the database file.
- ** This is usually safe even for an encrypted database - as the data
- ** was encrypted before it was written to the journal file. The exception
- ** is if the data was just read from an in-memory sub-journal. In that
- ** case it must be encrypted here before it is copied into the database
- ** file. */
-#ifdef SQLITE_HAS_CODEC
- if( !jrnlEnc ){
- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
- rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
- }else
-#endif
- rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
-
- if( pgno>pPager->dbFileSize ){
- pPager->dbFileSize = pgno;
- }
- if( pPager->pBackup ){
-#ifdef SQLITE_HAS_CODEC
- if( jrnlEnc ){
- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
- sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);
- }else
-#endif
- sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
- }
- }else if( !isMainJrnl && pPg==0 ){
- /* If this is a rollback of a savepoint and data was not written to
- ** the database and the page is not in-memory, there is a potential
- ** problem. When the page is next fetched by the b-tree layer, it
- ** will be read from the database file, which may or may not be
- ** current.
- **
- ** There are a couple of different ways this can happen. All are quite
- ** obscure. When running in synchronous mode, this can only happen
- ** if the page is on the free-list at the start of the transaction, then
- ** populated, then moved using sqlite3PagerMovepage().
- **
- ** The solution is to add an in-memory page to the cache containing
- ** the data just read from the sub-journal. Mark the page as dirty
- ** and if the pager requires a journal-sync, then mark the page as
- ** requiring a journal-sync before it is written.
- */
- assert( isSavepnt );
- assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
- pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
- rc = sqlite3PagerGet(pPager, pgno, &pPg, 1);
- assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
- pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
- if( rc!=SQLITE_OK ) return rc;
- sqlite3PcacheMakeDirty(pPg);
- }
- if( pPg ){
- /* No page should ever be explicitly rolled back that is in use, except
- ** for page 1 which is held in use in order to keep the lock on the
- ** database active. However such a page may be rolled back as a result
- ** of an internal error resulting in an automatic call to
- ** sqlite3PagerRollback().
- */
- void *pData;
- pData = pPg->pData;
- memcpy(pData, (u8*)aData, pPager->pageSize);
- pPager->xReiniter(pPg);
- /* It used to be that sqlite3PcacheMakeClean(pPg) was called here. But
- ** that call was dangerous and had no detectable benefit since the cache
- ** is normally cleaned by sqlite3PcacheCleanAll() after rollback and so
- ** has been removed. */
- pager_set_pagehash(pPg);
-
- /* If this was page 1, then restore the value of Pager.dbFileVers.
- ** Do this before any decoding. */
- if( pgno==1 ){
- memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
- }
-
- /* Decode the page just read from disk */
-#if SQLITE_HAS_CODEC
- if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); }
-#endif
- sqlite3PcacheRelease(pPg);
- }
- return rc;
-}
-
-/*
-** Parameter zMaster is the name of a master journal file. A single journal
-** file that referred to the master journal file has just been rolled back.
-** This routine checks if it is possible to delete the master journal file,
-** and does so if it is.
-**
-** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
-** available for use within this function.
-**
-** When a master journal file is created, it is populated with the names
-** of all of its child journals, one after another, formatted as utf-8
-** encoded text. The end of each child journal file is marked with a
-** nul-terminator byte (0x00). i.e. the entire contents of a master journal
-** file for a transaction involving two databases might be:
-**
-** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
-**
-** A master journal file may only be deleted once all of its child
-** journals have been rolled back.
-**
-** This function reads the contents of the master-journal file into
-** memory and loops through each of the child journal names. For
-** each child journal, it checks if:
-**
-** * if the child journal exists, and if so
-** * if the child journal contains a reference to master journal
-** file zMaster
-**
-** If a child journal can be found that matches both of the criteria
-** above, this function returns without doing anything. Otherwise, if
-** no such child journal can be found, file zMaster is deleted from
-** the file-system using sqlite3OsDelete().
-**
-** If an IO error within this function, an error code is returned. This
-** function allocates memory by calling sqlite3Malloc(). If an allocation
-** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
-** occur, SQLITE_OK is returned.
-**
-** TODO: This function allocates a single block of memory to load
-** the entire contents of the master journal file. This could be
-** a couple of kilobytes or so - potentially larger than the page
-** size.
-*/
-static int pager_delmaster(Pager *pPager, const char *zMaster){
- sqlite3_vfs *pVfs = pPager->pVfs;
- int rc; /* Return code */
- sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */
- sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
- char *zMasterJournal = 0; /* Contents of master journal file */
- i64 nMasterJournal; /* Size of master journal file */
- char *zJournal; /* Pointer to one journal within MJ file */
- char *zMasterPtr; /* Space to hold MJ filename from a journal file */
- int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */
-
- /* Allocate space for both the pJournal and pMaster file descriptors.
- ** If successful, open the master journal file for reading.
- */
- pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
- pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
- if( !pMaster ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
- rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
- }
- if( rc!=SQLITE_OK ) goto delmaster_out;
-
- /* Load the entire master journal file into space obtained from
- ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain
- ** sufficient space (in zMasterPtr) to hold the names of master
- ** journal files extracted from regular rollback-journals.
- */
- rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
- if( rc!=SQLITE_OK ) goto delmaster_out;
- nMasterPtr = pVfs->mxPathname+1;
- zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1);
- if( !zMasterJournal ){
- rc = SQLITE_NOMEM_BKPT;
- goto delmaster_out;
- }
- zMasterPtr = &zMasterJournal[nMasterJournal+1];
- rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
- if( rc!=SQLITE_OK ) goto delmaster_out;
- zMasterJournal[nMasterJournal] = 0;
-
- zJournal = zMasterJournal;
- while( (zJournal-zMasterJournal)<nMasterJournal ){
- int exists;
- rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
- if( rc!=SQLITE_OK ){
- goto delmaster_out;
- }
- if( exists ){
- /* One of the journals pointed to by the master journal exists.
- ** Open it and check if it points at the master journal. If
- ** so, return without deleting the master journal file.
- */
- int c;
- int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
- rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
- if( rc!=SQLITE_OK ){
- goto delmaster_out;
- }
-
- rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
- sqlite3OsClose(pJournal);
- if( rc!=SQLITE_OK ){
- goto delmaster_out;
- }
-
- c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
- if( c ){
- /* We have a match. Do not delete the master journal file. */
- goto delmaster_out;
- }
- }
- zJournal += (sqlite3Strlen30(zJournal)+1);
- }
-
- sqlite3OsClose(pMaster);
- rc = sqlite3OsDelete(pVfs, zMaster, 0);
-
-delmaster_out:
- sqlite3_free(zMasterJournal);
- if( pMaster ){
- sqlite3OsClose(pMaster);
- assert( !isOpen(pJournal) );
- sqlite3_free(pMaster);
- }
- return rc;
-}
-
-
-/*
-** This function is used to change the actual size of the database
-** file in the file-system. This only happens when committing a transaction,
-** or rolling back a transaction (including rolling back a hot-journal).
-**
-** If the main database file is not open, or the pager is not in either
-** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
-** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
-** If the file on disk is currently larger than nPage pages, then use the VFS
-** xTruncate() method to truncate it.
-**
-** Or, it might be the case that the file on disk is smaller than
-** nPage pages. Some operating system implementations can get confused if
-** you try to truncate a file to some size that is larger than it
-** currently is, so detect this case and write a single zero byte to
-** the end of the new file instead.
-**
-** If successful, return SQLITE_OK. If an IO error occurs while modifying
-** the database file, return the error code to the caller.
-*/
-static int pager_truncate(Pager *pPager, Pgno nPage){
- int rc = SQLITE_OK;
- assert( pPager->eState!=PAGER_ERROR );
- assert( pPager->eState!=PAGER_READER );
-
- if( isOpen(pPager->fd)
- && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
- ){
- i64 currentSize, newSize;
- int szPage = pPager->pageSize;
- assert( pPager->eLock==EXCLUSIVE_LOCK );
- /* TODO: Is it safe to use Pager.dbFileSize here? */
- rc = sqlite3OsFileSize(pPager->fd, &currentSize);
- newSize = szPage*(i64)nPage;
- if( rc==SQLITE_OK && currentSize!=newSize ){
- if( currentSize>newSize ){
- rc = sqlite3OsTruncate(pPager->fd, newSize);
- }else if( (currentSize+szPage)<=newSize ){
- char *pTmp = pPager->pTmpSpace;
- memset(pTmp, 0, szPage);
- testcase( (newSize-szPage) == currentSize );
- testcase( (newSize-szPage) > currentSize );
- rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
- }
- if( rc==SQLITE_OK ){
- pPager->dbFileSize = nPage;
- }
- }
- }
- return rc;
-}
-
-/*
-** Return a sanitized version of the sector-size of OS file pFile. The
-** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
-*/
-int sqlite3SectorSize(sqlite3_file *pFile){
- int iRet = sqlite3OsSectorSize(pFile);
- if( iRet<32 ){
- iRet = 512;
- }else if( iRet>MAX_SECTOR_SIZE ){
- assert( MAX_SECTOR_SIZE>=512 );
- iRet = MAX_SECTOR_SIZE;
- }
- return iRet;
-}
-
-/*
-** Set the value of the Pager.sectorSize variable for the given
-** pager based on the value returned by the xSectorSize method
-** of the open database file. The sector size will be used
-** to determine the size and alignment of journal header and
-** master journal pointers within created journal files.
-**
-** For temporary files the effective sector size is always 512 bytes.
-**
-** Otherwise, for non-temporary files, the effective sector size is
-** the value returned by the xSectorSize() method rounded up to 32 if
-** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
-** is greater than MAX_SECTOR_SIZE.
-**
-** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set
-** the effective sector size to its minimum value (512). The purpose of
-** pPager->sectorSize is to define the "blast radius" of bytes that
-** might change if a crash occurs while writing to a single byte in
-** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero
-** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector
-** size. For backwards compatibility of the rollback journal file format,
-** we cannot reduce the effective sector size below 512.
-*/
-static void setSectorSize(Pager *pPager){
- assert( isOpen(pPager->fd) || pPager->tempFile );
-
- if( pPager->tempFile
- || (sqlite3OsDeviceCharacteristics(pPager->fd) &
- SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
- ){
- /* Sector size doesn't matter for temporary files. Also, the file
- ** may not have been opened yet, in which case the OsSectorSize()
- ** call will segfault. */
- pPager->sectorSize = 512;
- }else{
- pPager->sectorSize = sqlite3SectorSize(pPager->fd);
- }
-}
-
-/*
-** Playback the journal and thus restore the database file to
-** the state it was in before we started making changes.
-**
-** The journal file format is as follows:
-**
-** (1) 8 byte prefix. A copy of aJournalMagic[].
-** (2) 4 byte big-endian integer which is the number of valid page records
-** in the journal. If this value is 0xffffffff, then compute the
-** number of page records from the journal size.
-** (3) 4 byte big-endian integer which is the initial value for the
-** sanity checksum.
-** (4) 4 byte integer which is the number of pages to truncate the
-** database to during a rollback.
-** (5) 4 byte big-endian integer which is the sector size. The header
-** is this many bytes in size.
-** (6) 4 byte big-endian integer which is the page size.
-** (7) zero padding out to the next sector size.
-** (8) Zero or more pages instances, each as follows:
-** + 4 byte page number.
-** + pPager->pageSize bytes of data.
-** + 4 byte checksum
-**
-** When we speak of the journal header, we mean the first 7 items above.
-** Each entry in the journal is an instance of the 8th item.
-**
-** Call the value from the second bullet "nRec". nRec is the number of
-** valid page entries in the journal. In most cases, you can compute the
-** value of nRec from the size of the journal file. But if a power
-** failure occurred while the journal was being written, it could be the
-** case that the size of the journal file had already been increased but
-** the extra entries had not yet made it safely to disk. In such a case,
-** the value of nRec computed from the file size would be too large. For
-** that reason, we always use the nRec value in the header.
-**
-** If the nRec value is 0xffffffff it means that nRec should be computed
-** from the file size. This value is used when the user selects the
-** no-sync option for the journal. A power failure could lead to corruption
-** in this case. But for things like temporary table (which will be
-** deleted when the power is restored) we don't care.
-**
-** If the file opened as the journal file is not a well-formed
-** journal file then all pages up to the first corrupted page are rolled
-** back (or no pages if the journal header is corrupted). The journal file
-** is then deleted and SQLITE_OK returned, just as if no corruption had
-** been encountered.
-**
-** If an I/O or malloc() error occurs, the journal-file is not deleted
-** and an error code is returned.
-**
-** The isHot parameter indicates that we are trying to rollback a journal
-** that might be a hot journal. Or, it could be that the journal is
-** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
-** If the journal really is hot, reset the pager cache prior rolling
-** back any content. If the journal is merely persistent, no reset is
-** needed.
-*/
-static int pager_playback(Pager *pPager, int isHot){
- sqlite3_vfs *pVfs = pPager->pVfs;
- i64 szJ; /* Size of the journal file in bytes */
- u32 nRec; /* Number of Records in the journal */
- u32 u; /* Unsigned loop counter */
- Pgno mxPg = 0; /* Size of the original file in pages */
- int rc; /* Result code of a subroutine */
- int res = 1; /* Value returned by sqlite3OsAccess() */
- char *zMaster = 0; /* Name of master journal file if any */
- int needPagerReset; /* True to reset page prior to first page rollback */
- int nPlayback = 0; /* Total number of pages restored from journal */
- u32 savedPageSize = pPager->pageSize;
-
- /* Figure out how many records are in the journal. Abort early if
- ** the journal is empty.
- */
- assert( isOpen(pPager->jfd) );
- rc = sqlite3OsFileSize(pPager->jfd, &szJ);
- if( rc!=SQLITE_OK ){
- goto end_playback;
- }
-
- /* Read the master journal name from the journal, if it is present.
- ** If a master journal file name is specified, but the file is not
- ** present on disk, then the journal is not hot and does not need to be
- ** played back.
- **
- ** TODO: Technically the following is an error because it assumes that
- ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
- ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
- ** mxPathname is 512, which is the same as the minimum allowable value
- ** for pageSize.
- */
- zMaster = pPager->pTmpSpace;
- rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
- if( rc==SQLITE_OK && zMaster[0] ){
- rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
- }
- zMaster = 0;
- if( rc!=SQLITE_OK || !res ){
- goto end_playback;
- }
- pPager->journalOff = 0;
- needPagerReset = isHot;
-
- /* This loop terminates either when a readJournalHdr() or
- ** pager_playback_one_page() call returns SQLITE_DONE or an IO error
- ** occurs.
- */
- while( 1 ){
- /* Read the next journal header from the journal file. If there are
- ** not enough bytes left in the journal file for a complete header, or
- ** it is corrupted, then a process must have failed while writing it.
- ** This indicates nothing more needs to be rolled back.
- */
- rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- }
- goto end_playback;
- }
-
- /* If nRec is 0xffffffff, then this journal was created by a process
- ** working in no-sync mode. This means that the rest of the journal
- ** file consists of pages, there are no more journal headers. Compute
- ** the value of nRec based on this assumption.
- */
- if( nRec==0xffffffff ){
- assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
- nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
- }
-
- /* If nRec is 0 and this rollback is of a transaction created by this
- ** process and if this is the final header in the journal, then it means
- ** that this part of the journal was being filled but has not yet been
- ** synced to disk. Compute the number of pages based on the remaining
- ** size of the file.
- **
- ** The third term of the test was added to fix ticket #2565.
- ** When rolling back a hot journal, nRec==0 always means that the next
- ** chunk of the journal contains zero pages to be rolled back. But
- ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
- ** the journal, it means that the journal might contain additional
- ** pages that need to be rolled back and that the number of pages
- ** should be computed based on the journal file size.
- */
- if( nRec==0 && !isHot &&
- pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
- nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
- }
-
- /* If this is the first header read from the journal, truncate the
- ** database file back to its original size.
- */
- if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
- rc = pager_truncate(pPager, mxPg);
- if( rc!=SQLITE_OK ){
- goto end_playback;
- }
- pPager->dbSize = mxPg;
- }
-
- /* Copy original pages out of the journal and back into the
- ** database file and/or page cache.
- */
- for(u=0; u<nRec; u++){
- if( needPagerReset ){
- pager_reset(pPager);
- needPagerReset = 0;
- }
- rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
- if( rc==SQLITE_OK ){
- nPlayback++;
- }else{
- if( rc==SQLITE_DONE ){
- pPager->journalOff = szJ;
- break;
- }else if( rc==SQLITE_IOERR_SHORT_READ ){
- /* If the journal has been truncated, simply stop reading and
- ** processing the journal. This might happen if the journal was
- ** not completely written and synced prior to a crash. In that
- ** case, the database should have never been written in the
- ** first place so it is OK to simply abandon the rollback. */
- rc = SQLITE_OK;
- goto end_playback;
- }else{
- /* If we are unable to rollback, quit and return the error
- ** code. This will cause the pager to enter the error state
- ** so that no further harm will be done. Perhaps the next
- ** process to come along will be able to rollback the database.
- */
- goto end_playback;
- }
- }
- }
- }
- /*NOTREACHED*/
- assert( 0 );
-
-end_playback:
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerSetPagesize(pPager, &savedPageSize, -1);
- }
- /* Following a rollback, the database file should be back in its original
- ** state prior to the start of the transaction, so invoke the
- ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
- ** assertion that the transaction counter was modified.
- */
-#ifdef SQLITE_DEBUG
- sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
-#endif
-
- /* If this playback is happening automatically as a result of an IO or
- ** malloc error that occurred after the change-counter was updated but
- ** before the transaction was committed, then the change-counter
- ** modification may just have been reverted. If this happens in exclusive
- ** mode, then subsequent transactions performed by the connection will not
- ** update the change-counter at all. This may lead to cache inconsistency
- ** problems for other processes at some point in the future. So, just
- ** in case this has happened, clear the changeCountDone flag now.
- */
- pPager->changeCountDone = pPager->tempFile;
-
- if( rc==SQLITE_OK ){
- zMaster = pPager->pTmpSpace;
- rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
- testcase( rc!=SQLITE_OK );
- }
- if( rc==SQLITE_OK
- && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
- ){
- rc = sqlite3PagerSync(pPager, 0);
- }
- if( rc==SQLITE_OK ){
- rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
- testcase( rc!=SQLITE_OK );
- }
- if( rc==SQLITE_OK && zMaster[0] && res ){
- /* If there was a master journal and this routine will return success,
- ** see if it is possible to delete the master journal.
- */
- rc = pager_delmaster(pPager, zMaster);
- testcase( rc!=SQLITE_OK );
- }
- if( isHot && nPlayback ){
- sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
- nPlayback, pPager->zJournal);
- }
-
- /* The Pager.sectorSize variable may have been updated while rolling
- ** back a journal created by a process with a different sector size
- ** value. Reset it to the correct value for this process.
- */
- setSectorSize(pPager);
- return rc;
-}
-
-
-/*
-** Read the content for page pPg out of the database file (or out of
-** the WAL if that is where the most recent copy if found) into
-** pPg->pData. A shared lock or greater must be held on the database
-** file before this function is called.
-**
-** If page 1 is read, then the value of Pager.dbFileVers[] is set to
-** the value read from the database file.
-**
-** If an IO error occurs, then the IO error is returned to the caller.
-** Otherwise, SQLITE_OK is returned.
-*/
-static int readDbPage(PgHdr *pPg){
- Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
- int rc = SQLITE_OK; /* Return code */
-
-#ifndef SQLITE_OMIT_WAL
- u32 iFrame = 0; /* Frame of WAL containing pgno */
-
- assert( pPager->eState>=PAGER_READER && !MEMDB );
- assert( isOpen(pPager->fd) );
-
- if( pagerUseWal(pPager) ){
- rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
- if( rc ) return rc;
- }
- if( iFrame ){
- rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData);
- }else
-#endif
- {
- i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset);
- if( rc==SQLITE_IOERR_SHORT_READ ){
- rc = SQLITE_OK;
- }
- }
-
- if( pPg->pgno==1 ){
- if( rc ){
- /* If the read is unsuccessful, set the dbFileVers[] to something
- ** that will never be a valid file version. dbFileVers[] is a copy
- ** of bytes 24..39 of the database. Bytes 28..31 should always be
- ** zero or the size of the database in page. Bytes 32..35 and 35..39
- ** should be page numbers which are never 0xffffffff. So filling
- ** pPager->dbFileVers[] with all 0xff bytes should suffice.
- **
- ** For an encrypted database, the situation is more complex: bytes
- ** 24..39 of the database are white noise. But the probability of
- ** white noise equaling 16 bytes of 0xff is vanishingly small so
- ** we should still be ok.
- */
- memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
- }else{
- u8 *dbFileVers = &((u8*)pPg->pData)[24];
- memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
- }
- }
- CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT);
-
- PAGER_INCR(sqlite3_pager_readdb_count);
- PAGER_INCR(pPager->nRead);
- IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
- PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
- PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)));
-
- return rc;
-}
-
-/*
-** Update the value of the change-counter at offsets 24 and 92 in
-** the header and the sqlite version number at offset 96.
-**
-** This is an unconditional update. See also the pager_incr_changecounter()
-** routine which only updates the change-counter if the update is actually
-** needed, as determined by the pPager->changeCountDone state variable.
-*/
-static void pager_write_changecounter(PgHdr *pPg){
- u32 change_counter;
-
- /* Increment the value just read and write it back to byte 24. */
- change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
- put32bits(((char*)pPg->pData)+24, change_counter);
-
- /* Also store the SQLite version number in bytes 96..99 and in
- ** bytes 92..95 store the change counter for which the version number
- ** is valid. */
- put32bits(((char*)pPg->pData)+92, change_counter);
- put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
-}
-
-#ifndef SQLITE_OMIT_WAL
-/*
-** This function is invoked once for each page that has already been
-** written into the log file when a WAL transaction is rolled back.
-** Parameter iPg is the page number of said page. The pCtx argument
-** is actually a pointer to the Pager structure.
-**
-** If page iPg is present in the cache, and has no outstanding references,
-** it is discarded. Otherwise, if there are one or more outstanding
-** references, the page content is reloaded from the database. If the
-** attempt to reload content from the database is required and fails,
-** return an SQLite error code. Otherwise, SQLITE_OK.
-*/
-static int pagerUndoCallback(void *pCtx, Pgno iPg){
- int rc = SQLITE_OK;
- Pager *pPager = (Pager *)pCtx;
- PgHdr *pPg;
-
- assert( pagerUseWal(pPager) );
- pPg = sqlite3PagerLookup(pPager, iPg);
- if( pPg ){
- if( sqlite3PcachePageRefcount(pPg)==1 ){
- sqlite3PcacheDrop(pPg);
- }else{
- rc = readDbPage(pPg);
- if( rc==SQLITE_OK ){
- pPager->xReiniter(pPg);
- }
- sqlite3PagerUnrefNotNull(pPg);
- }
- }
-
- /* Normally, if a transaction is rolled back, any backup processes are
- ** updated as data is copied out of the rollback journal and into the
- ** database. This is not generally possible with a WAL database, as
- ** rollback involves simply truncating the log file. Therefore, if one
- ** or more frames have already been written to the log (and therefore
- ** also copied into the backup databases) as part of this transaction,
- ** the backups must be restarted.
- */
- sqlite3BackupRestart(pPager->pBackup);
-
- return rc;
-}
-
-/*
-** This function is called to rollback a transaction on a WAL database.
-*/
-static int pagerRollbackWal(Pager *pPager){
- int rc; /* Return Code */
- PgHdr *pList; /* List of dirty pages to revert */
-
- /* For all pages in the cache that are currently dirty or have already
- ** been written (but not committed) to the log file, do one of the
- ** following:
- **
- ** + Discard the cached page (if refcount==0), or
- ** + Reload page content from the database (if refcount>0).
- */
- pPager->dbSize = pPager->dbOrigSize;
- rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
- pList = sqlite3PcacheDirtyList(pPager->pPCache);
- while( pList && rc==SQLITE_OK ){
- PgHdr *pNext = pList->pDirty;
- rc = pagerUndoCallback((void *)pPager, pList->pgno);
- pList = pNext;
- }
-
- return rc;
-}
-
-/*
-** This function is a wrapper around sqlite3WalFrames(). As well as logging
-** the contents of the list of pages headed by pList (connected by pDirty),
-** this function notifies any active backup processes that the pages have
-** changed.
-**
-** The list of pages passed into this routine is always sorted by page number.
-** Hence, if page 1 appears anywhere on the list, it will be the first page.
-*/
-static int pagerWalFrames(
- Pager *pPager, /* Pager object */
- PgHdr *pList, /* List of frames to log */
- Pgno nTruncate, /* Database size after this commit */
- int isCommit /* True if this is a commit */
-){
- int rc; /* Return code */
- int nList; /* Number of pages in pList */
- PgHdr *p; /* For looping over pages */
-
- assert( pPager->pWal );
- assert( pList );
-#ifdef SQLITE_DEBUG
- /* Verify that the page list is in accending order */
- for(p=pList; p && p->pDirty; p=p->pDirty){
- assert( p->pgno < p->pDirty->pgno );
- }
-#endif
-
- assert( pList->pDirty==0 || isCommit );
- if( isCommit ){
- /* If a WAL transaction is being committed, there is no point in writing
- ** any pages with page numbers greater than nTruncate into the WAL file.
- ** They will never be read by any client. So remove them from the pDirty
- ** list here. */
- PgHdr **ppNext = &pList;
- nList = 0;
- for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
- if( p->pgno<=nTruncate ){
- ppNext = &p->pDirty;
- nList++;
- }
- }
- assert( pList );
- }else{
- nList = 1;
- }
- pPager->aStat[PAGER_STAT_WRITE] += nList;
-
- if( pList->pgno==1 ) pager_write_changecounter(pList);
- rc = sqlite3WalFrames(pPager->pWal,
- pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
- );
- if( rc==SQLITE_OK && pPager->pBackup ){
- for(p=pList; p; p=p->pDirty){
- sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
- }
- }
-
-#ifdef SQLITE_CHECK_PAGES
- pList = sqlite3PcacheDirtyList(pPager->pPCache);
- for(p=pList; p; p=p->pDirty){
- pager_set_pagehash(p);
- }
-#endif
-
- return rc;
-}
-
-/*
-** Begin a read transaction on the WAL.
-**
-** This routine used to be called "pagerOpenSnapshot()" because it essentially
-** makes a snapshot of the database at the current point in time and preserves
-** that snapshot for use by the reader in spite of concurrently changes by
-** other writers or checkpointers.
-*/
-static int pagerBeginReadTransaction(Pager *pPager){
- int rc; /* Return code */
- int changed = 0; /* True if cache must be reset */
-
- assert( pagerUseWal(pPager) );
- assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
-
- /* sqlite3WalEndReadTransaction() was not called for the previous
- ** transaction in locking_mode=EXCLUSIVE. So call it now. If we
- ** are in locking_mode=NORMAL and EndRead() was previously called,
- ** the duplicate call is harmless.
- */
- sqlite3WalEndReadTransaction(pPager->pWal);
-
- rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
- if( rc!=SQLITE_OK || changed ){
- pager_reset(pPager);
- if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
- }
-
- return rc;
-}
-#endif
-
-/*
-** This function is called as part of the transition from PAGER_OPEN
-** to PAGER_READER state to determine the size of the database file
-** in pages (assuming the page size currently stored in Pager.pageSize).
-**
-** If no error occurs, SQLITE_OK is returned and the size of the database
-** in pages is stored in *pnPage. Otherwise, an error code (perhaps
-** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified.
-*/
-static int pagerPagecount(Pager *pPager, Pgno *pnPage){
- Pgno nPage; /* Value to return via *pnPage */
-
- /* Query the WAL sub-system for the database size. The WalDbsize()
- ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
- ** if the database size is not available. The database size is not
- ** available from the WAL sub-system if the log file is empty or
- ** contains no valid committed transactions.
- */
- assert( pPager->eState==PAGER_OPEN );
- assert( pPager->eLock>=SHARED_LOCK );
- assert( isOpen(pPager->fd) );
- assert( pPager->tempFile==0 );
- nPage = sqlite3WalDbsize(pPager->pWal);
-
- /* If the number of pages in the database is not available from the
- ** WAL sub-system, determine the page count based on the size of
- ** the database file. If the size of the database file is not an
- ** integer multiple of the page-size, round up the result.
- */
- if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){
- i64 n = 0; /* Size of db file in bytes */
- int rc = sqlite3OsFileSize(pPager->fd, &n);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
- }
-
- /* If the current number of pages in the file is greater than the
- ** configured maximum pager number, increase the allowed limit so
- ** that the file can be read.
- */
- if( nPage>pPager->mxPgno ){
- pPager->mxPgno = (Pgno)nPage;
- }
-
- *pnPage = nPage;
- return SQLITE_OK;
-}
-
-#ifndef SQLITE_OMIT_WAL
-/*
-** Check if the *-wal file that corresponds to the database opened by pPager
-** exists if the database is not empy, or verify that the *-wal file does
-** not exist (by deleting it) if the database file is empty.
-**
-** If the database is not empty and the *-wal file exists, open the pager
-** in WAL mode. If the database is empty or if no *-wal file exists and
-** if no error occurs, make sure Pager.journalMode is not set to
-** PAGER_JOURNALMODE_WAL.
-**
-** Return SQLITE_OK or an error code.
-**
-** The caller must hold a SHARED lock on the database file to call this
-** function. Because an EXCLUSIVE lock on the db file is required to delete
-** a WAL on a none-empty database, this ensures there is no race condition
-** between the xAccess() below and an xDelete() being executed by some
-** other connection.
-*/
-static int pagerOpenWalIfPresent(Pager *pPager){
- int rc = SQLITE_OK;
- assert( pPager->eState==PAGER_OPEN );
- assert( pPager->eLock>=SHARED_LOCK );
-
- if( !pPager->tempFile ){
- int isWal; /* True if WAL file exists */
- rc = sqlite3OsAccess(
- pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
- );
- if( rc==SQLITE_OK ){
- if( isWal ){
- Pgno nPage; /* Size of the database file */
-
- rc = pagerPagecount(pPager, &nPage);
- if( rc ) return rc;
- if( nPage==0 ){
- rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
- }else{
- testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
- rc = sqlite3PagerOpenWal(pPager, 0);
- }
- }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
- pPager->journalMode = PAGER_JOURNALMODE_DELETE;
- }
- }
- }
- return rc;
-}
-#endif
-
-/*
-** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
-** the entire master journal file. The case pSavepoint==NULL occurs when
-** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
-** savepoint.
-**
-** When pSavepoint is not NULL (meaning a non-transaction savepoint is
-** being rolled back), then the rollback consists of up to three stages,
-** performed in the order specified:
-**
-** * Pages are played back from the main journal starting at byte
-** offset PagerSavepoint.iOffset and continuing to
-** PagerSavepoint.iHdrOffset, or to the end of the main journal
-** file if PagerSavepoint.iHdrOffset is zero.
-**
-** * If PagerSavepoint.iHdrOffset is not zero, then pages are played
-** back starting from the journal header immediately following
-** PagerSavepoint.iHdrOffset to the end of the main journal file.
-**
-** * Pages are then played back from the sub-journal file, starting
-** with the PagerSavepoint.iSubRec and continuing to the end of
-** the journal file.
-**
-** Throughout the rollback process, each time a page is rolled back, the
-** corresponding bit is set in a bitvec structure (variable pDone in the
-** implementation below). This is used to ensure that a page is only
-** rolled back the first time it is encountered in either journal.
-**
-** If pSavepoint is NULL, then pages are only played back from the main
-** journal file. There is no need for a bitvec in this case.
-**
-** In either case, before playback commences the Pager.dbSize variable
-** is reset to the value that it held at the start of the savepoint
-** (or transaction). No page with a page-number greater than this value
-** is played back. If one is encountered it is simply skipped.
-*/
-static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
- i64 szJ; /* Effective size of the main journal */
- i64 iHdrOff; /* End of first segment of main-journal records */
- int rc = SQLITE_OK; /* Return code */
- Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */
-
- assert( pPager->eState!=PAGER_ERROR );
- assert( pPager->eState>=PAGER_WRITER_LOCKED );
-
- /* Allocate a bitvec to use to store the set of pages rolled back */
- if( pSavepoint ){
- pDone = sqlite3BitvecCreate(pSavepoint->nOrig);
- if( !pDone ){
- return SQLITE_NOMEM_BKPT;
- }
- }
-
- /* Set the database size back to the value it was before the savepoint
- ** being reverted was opened.
- */
- pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
- pPager->changeCountDone = pPager->tempFile;
-
- if( !pSavepoint && pagerUseWal(pPager) ){
- return pagerRollbackWal(pPager);
- }
-
- /* Use pPager->journalOff as the effective size of the main rollback
- ** journal. The actual file might be larger than this in
- ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything
- ** past pPager->journalOff is off-limits to us.
- */
- szJ = pPager->journalOff;
- assert( pagerUseWal(pPager)==0 || szJ==0 );
-
- /* Begin by rolling back records from the main journal starting at
- ** PagerSavepoint.iOffset and continuing to the next journal header.
- ** There might be records in the main journal that have a page number
- ** greater than the current database size (pPager->dbSize) but those
- ** will be skipped automatically. Pages are added to pDone as they
- ** are played back.
- */
- if( pSavepoint && !pagerUseWal(pPager) ){
- iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
- pPager->journalOff = pSavepoint->iOffset;
- while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
- rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
- }
- assert( rc!=SQLITE_DONE );
- }else{
- pPager->journalOff = 0;
- }
-
- /* Continue rolling back records out of the main journal starting at
- ** the first journal header seen and continuing until the effective end
- ** of the main journal file. Continue to skip out-of-range pages and
- ** continue adding pages rolled back to pDone.
- */
- while( rc==SQLITE_OK && pPager->journalOff<szJ ){
- u32 ii; /* Loop counter */
- u32 nJRec = 0; /* Number of Journal Records */
- u32 dummy;
- rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy);
- assert( rc!=SQLITE_DONE );
-
- /*
- ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff"
- ** test is related to ticket #2565. See the discussion in the
- ** pager_playback() function for additional information.
- */
- if( nJRec==0
- && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
- ){
- nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
- }
- for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
- rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
- }
- assert( rc!=SQLITE_DONE );
- }
- assert( rc!=SQLITE_OK || pPager->journalOff>=szJ );
-
- /* Finally, rollback pages from the sub-journal. Page that were
- ** previously rolled back out of the main journal (and are hence in pDone)
- ** will be skipped. Out-of-range pages are also skipped.
- */
- if( pSavepoint ){
- u32 ii; /* Loop counter */
- i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
-
- if( pagerUseWal(pPager) ){
- rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
- }
- for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
- assert( offset==(i64)ii*(4+pPager->pageSize) );
- rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
- }
- assert( rc!=SQLITE_DONE );
- }
-
- sqlite3BitvecDestroy(pDone);
- if( rc==SQLITE_OK ){
- pPager->journalOff = szJ;
- }
-
- return rc;
-}
-
-/*
-** Change the maximum number of in-memory pages that are allowed
-** before attempting to recycle clean and unused pages.
-*/
-void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
- sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
-}
-
-/*
-** Change the maximum number of in-memory pages that are allowed
-** before attempting to spill pages to journal.
-*/
-int sqlite3PagerSetSpillsize(Pager *pPager, int mxPage){
- return sqlite3PcacheSetSpillsize(pPager->pPCache, mxPage);
-}
-
-/*
-** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
-*/
-static void pagerFixMaplimit(Pager *pPager){
-#if SQLITE_MAX_MMAP_SIZE>0
- sqlite3_file *fd = pPager->fd;
- if( isOpen(fd) && fd->pMethods->iVersion>=3 ){
- sqlite3_int64 sz;
- sz = pPager->szMmap;
- pPager->bUseFetch = (sz>0);
- setGetterMethod(pPager);
- sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
- }
-#endif
-}
-
-/*
-** Change the maximum size of any memory mapping made of the database file.
-*/
-void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
- pPager->szMmap = szMmap;
- pagerFixMaplimit(pPager);
-}
-
-/*
-** Free as much memory as possible from the pager.
-*/
-void sqlite3PagerShrink(Pager *pPager){
- sqlite3PcacheShrink(pPager->pPCache);
-}
-
-/*
-** Adjust settings of the pager to those specified in the pgFlags parameter.
-**
-** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
-** of the database to damage due to OS crashes or power failures by
-** changing the number of syncs()s when writing the journals.
-** There are four levels:
-**
-** OFF sqlite3OsSync() is never called. This is the default
-** for temporary and transient files.
-**
-** NORMAL The journal is synced once before writes begin on the
-** database. This is normally adequate protection, but
-** it is theoretically possible, though very unlikely,
-** that an inopertune power failure could leave the journal
-** in a state which would cause damage to the database
-** when it is rolled back.
-**
-** FULL The journal is synced twice before writes begin on the
-** database (with some additional information - the nRec field
-** of the journal header - being written in between the two
-** syncs). If we assume that writing a
-** single disk sector is atomic, then this mode provides
-** assurance that the journal will not be corrupted to the
-** point of causing damage to the database during rollback.
-**
-** EXTRA This is like FULL except that is also syncs the directory
-** that contains the rollback journal after the rollback
-** journal is unlinked.
-**
-** The above is for a rollback-journal mode. For WAL mode, OFF continues
-** to mean that no syncs ever occur. NORMAL means that the WAL is synced
-** prior to the start of checkpoint and that the database file is synced
-** at the conclusion of the checkpoint if the entire content of the WAL
-** was written back into the database. But no sync operations occur for
-** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL
-** file is synced following each commit operation, in addition to the
-** syncs associated with NORMAL. There is no difference between FULL
-** and EXTRA for WAL mode.
-**
-** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The
-** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
-** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an
-** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL
-** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the
-** synchronous=FULL versus synchronous=NORMAL setting determines when
-** the xSync primitive is called and is relevant to all platforms.
-**
-** Numeric values associated with these states are OFF==1, NORMAL=2,
-** and FULL=3.
-*/
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-void sqlite3PagerSetFlags(
- Pager *pPager, /* The pager to set safety level for */
- unsigned pgFlags /* Various flags */
-){
- unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
- if( pPager->tempFile ){
- pPager->noSync = 1;
- pPager->fullSync = 0;
- pPager->extraSync = 0;
- }else{
- pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0;
- pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0;
- pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0;
- }
- if( pPager->noSync ){
- pPager->syncFlags = 0;
- }else if( pgFlags & PAGER_FULLFSYNC ){
- pPager->syncFlags = SQLITE_SYNC_FULL;
- }else{
- pPager->syncFlags = SQLITE_SYNC_NORMAL;
- }
- pPager->walSyncFlags = (pPager->syncFlags<<2);
- if( pPager->fullSync ){
- pPager->walSyncFlags |= pPager->syncFlags;
- }
- if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){
- pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2);
- }
- if( pgFlags & PAGER_CACHESPILL ){
- pPager->doNotSpill &= ~SPILLFLAG_OFF;
- }else{
- pPager->doNotSpill |= SPILLFLAG_OFF;
- }
-}
-#endif
-
-/*
-** The following global variable is incremented whenever the library
-** attempts to open a temporary file. This information is used for
-** testing and analysis only.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_opentemp_count = 0;
-#endif
-
-/*
-** Open a temporary file.
-**
-** Write the file descriptor into *pFile. Return SQLITE_OK on success
-** or some other error code if we fail. The OS will automatically
-** delete the temporary file when it is closed.
-**
-** The flags passed to the VFS layer xOpen() call are those specified
-** by parameter vfsFlags ORed with the following:
-**
-** SQLITE_OPEN_READWRITE
-** SQLITE_OPEN_CREATE
-** SQLITE_OPEN_EXCLUSIVE
-** SQLITE_OPEN_DELETEONCLOSE
-*/
-static int pagerOpentemp(
- Pager *pPager, /* The pager object */
- sqlite3_file *pFile, /* Write the file descriptor here */
- int vfsFlags /* Flags passed through to the VFS */
-){
- int rc; /* Return code */
-
-#ifdef SQLITE_TEST
- sqlite3_opentemp_count++; /* Used for testing and analysis only */
-#endif
-
- vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
- SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
- rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
- assert( rc!=SQLITE_OK || isOpen(pFile) );
- return rc;
-}
-
-/*
-** Set the busy handler function.
-**
-** The pager invokes the busy-handler if sqlite3OsLock() returns
-** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
-** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
-** lock. It does *not* invoke the busy handler when upgrading from
-** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
-** (which occurs during hot-journal rollback). Summary:
-**
-** Transition | Invokes xBusyHandler
-** --------------------------------------------------------
-** NO_LOCK -> SHARED_LOCK | Yes
-** SHARED_LOCK -> RESERVED_LOCK | No
-** SHARED_LOCK -> EXCLUSIVE_LOCK | No
-** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes
-**
-** If the busy-handler callback returns non-zero, the lock is
-** retried. If it returns zero, then the SQLITE_BUSY error is
-** returned to the caller of the pager API function.
-*/
-void sqlite3PagerSetBusyHandler(
- Pager *pPager, /* Pager object */
- int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
- void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
-){
- void **ap;
- pPager->xBusyHandler = xBusyHandler;
- pPager->pBusyHandlerArg = pBusyHandlerArg;
- ap = (void **)&pPager->xBusyHandler;
- assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
- assert( ap[1]==pBusyHandlerArg );
- sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
-}
-
-/*
-** Change the page size used by the Pager object. The new page size
-** is passed in *pPageSize.
-**
-** If the pager is in the error state when this function is called, it
-** is a no-op. The value returned is the error state error code (i.e.
-** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL).
-**
-** Otherwise, if all of the following are true:
-**
-** * the new page size (value of *pPageSize) is valid (a power
-** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
-**
-** * there are no outstanding page references, and
-**
-** * the database is either not an in-memory database or it is
-** an in-memory database that currently consists of zero pages.
-**
-** then the pager object page size is set to *pPageSize.
-**
-** If the page size is changed, then this function uses sqlite3PagerMalloc()
-** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
-** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
-** In all other cases, SQLITE_OK is returned.
-**
-** If the page size is not changed, either because one of the enumerated
-** conditions above is not true, the pager was in error state when this
-** function was called, or because the memory allocation attempt failed,
-** then *pPageSize is set to the old, retained page size before returning.
-*/
-int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
- int rc = SQLITE_OK;
-
- /* It is not possible to do a full assert_pager_state() here, as this
- ** function may be called from within PagerOpen(), before the state
- ** of the Pager object is internally consistent.
- **
- ** At one point this function returned an error if the pager was in
- ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
- ** there is at least one outstanding page reference, this function
- ** is a no-op for that case anyhow.
- */
-
- u32 pageSize = *pPageSize;
- assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
- if( (pPager->memDb==0 || pPager->dbSize==0)
- && sqlite3PcacheRefCount(pPager->pPCache)==0
- && pageSize && pageSize!=(u32)pPager->pageSize
- ){
- char *pNew = NULL; /* New temp space */
- i64 nByte = 0;
-
- if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
- rc = sqlite3OsFileSize(pPager->fd, &nByte);
- }
- if( rc==SQLITE_OK ){
- pNew = (char *)sqlite3PageMalloc(pageSize);
- if( !pNew ) rc = SQLITE_NOMEM_BKPT;
- }
-
- if( rc==SQLITE_OK ){
- pager_reset(pPager);
- rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
- }
- if( rc==SQLITE_OK ){
- sqlite3PageFree(pPager->pTmpSpace);
- pPager->pTmpSpace = pNew;
- pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
- pPager->pageSize = pageSize;
- }else{
- sqlite3PageFree(pNew);
- }
- }
-
- *pPageSize = pPager->pageSize;
- if( rc==SQLITE_OK ){
- if( nReserve<0 ) nReserve = pPager->nReserve;
- assert( nReserve>=0 && nReserve<1000 );
- pPager->nReserve = (i16)nReserve;
- pagerReportSize(pPager);
- pagerFixMaplimit(pPager);
- }
- return rc;
-}
-
-/*
-** Return a pointer to the "temporary page" buffer held internally
-** by the pager. This is a buffer that is big enough to hold the
-** entire content of a database page. This buffer is used internally
-** during rollback and will be overwritten whenever a rollback
-** occurs. But other modules are free to use it too, as long as
-** no rollbacks are happening.
-*/
-void *sqlite3PagerTempSpace(Pager *pPager){
- return pPager->pTmpSpace;
-}
-
-/*
-** Attempt to set the maximum database page count if mxPage is positive.
-** Make no changes if mxPage is zero or negative. And never reduce the
-** maximum page count below the current size of the database.
-**
-** Regardless of mxPage, return the current maximum page count.
-*/
-int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
- if( mxPage>0 ){
- pPager->mxPgno = mxPage;
- }
- assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */
- assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */
- return pPager->mxPgno;
-}
-
-/*
-** The following set of routines are used to disable the simulated
-** I/O error mechanism. These routines are used to avoid simulated
-** errors in places where we do not care about errors.
-**
-** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
-** and generate no code.
-*/
-#ifdef SQLITE_TEST
-extern int sqlite3_io_error_pending;
-extern int sqlite3_io_error_hit;
-static int saved_cnt;
-void disable_simulated_io_errors(void){
- saved_cnt = sqlite3_io_error_pending;
- sqlite3_io_error_pending = -1;
-}
-void enable_simulated_io_errors(void){
- sqlite3_io_error_pending = saved_cnt;
-}
-#else
-# define disable_simulated_io_errors()
-# define enable_simulated_io_errors()
-#endif
-
-/*
-** Read the first N bytes from the beginning of the file into memory
-** that pDest points to.
-**
-** If the pager was opened on a transient file (zFilename==""), or
-** opened on a file less than N bytes in size, the output buffer is
-** zeroed and SQLITE_OK returned. The rationale for this is that this
-** function is used to read database headers, and a new transient or
-** zero sized database has a header than consists entirely of zeroes.
-**
-** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered,
-** the error code is returned to the caller and the contents of the
-** output buffer undefined.
-*/
-int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
- int rc = SQLITE_OK;
- memset(pDest, 0, N);
- assert( isOpen(pPager->fd) || pPager->tempFile );
-
- /* This routine is only called by btree immediately after creating
- ** the Pager object. There has not been an opportunity to transition
- ** to WAL mode yet.
- */
- assert( !pagerUseWal(pPager) );
-
- if( isOpen(pPager->fd) ){
- IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
- rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
- if( rc==SQLITE_IOERR_SHORT_READ ){
- rc = SQLITE_OK;
- }
- }
- return rc;
-}
-
-/*
-** This function may only be called when a read-transaction is open on
-** the pager. It returns the total number of pages in the database.
-**
-** However, if the file is between 1 and <page-size> bytes in size, then
-** this is considered a 1 page file.
-*/
-void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
- assert( pPager->eState>=PAGER_READER );
- assert( pPager->eState!=PAGER_WRITER_FINISHED );
- *pnPage = (int)pPager->dbSize;
-}
-
-
-/*
-** Try to obtain a lock of type locktype on the database file. If
-** a similar or greater lock is already held, this function is a no-op
-** (returning SQLITE_OK immediately).
-**
-** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke
-** the busy callback if the lock is currently not available. Repeat
-** until the busy callback returns false or until the attempt to
-** obtain the lock succeeds.
-**
-** Return SQLITE_OK on success and an error code if we cannot obtain
-** the lock. If the lock is obtained successfully, set the Pager.state
-** variable to locktype before returning.
-*/
-static int pager_wait_on_lock(Pager *pPager, int locktype){
- int rc; /* Return code */
-
- /* Check that this is either a no-op (because the requested lock is
- ** already held), or one of the transitions that the busy-handler
- ** may be invoked during, according to the comment above
- ** sqlite3PagerSetBusyhandler().
- */
- assert( (pPager->eLock>=locktype)
- || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
- || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
- );
-
- do {
- rc = pagerLockDb(pPager, locktype);
- }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
- return rc;
-}
-
-/*
-** Function assertTruncateConstraint(pPager) checks that one of the
-** following is true for all dirty pages currently in the page-cache:
-**
-** a) The page number is less than or equal to the size of the
-** current database image, in pages, OR
-**
-** b) if the page content were written at this time, it would not
-** be necessary to write the current content out to the sub-journal
-** (as determined by function subjRequiresPage()).
-**
-** If the condition asserted by this function were not true, and the
-** dirty page were to be discarded from the cache via the pagerStress()
-** routine, pagerStress() would not write the current page content to
-** the database file. If a savepoint transaction were rolled back after
-** this happened, the correct behavior would be to restore the current
-** content of the page. However, since this content is not present in either
-** the database file or the portion of the rollback journal and
-** sub-journal rolled back the content could not be restored and the
-** database image would become corrupt. It is therefore fortunate that
-** this circumstance cannot arise.
-*/
-#if defined(SQLITE_DEBUG)
-static void assertTruncateConstraintCb(PgHdr *pPg){
- assert( pPg->flags&PGHDR_DIRTY );
- assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
-}
-static void assertTruncateConstraint(Pager *pPager){
- sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
-}
-#else
-# define assertTruncateConstraint(pPager)
-#endif
-
-/*
-** Truncate the in-memory database file image to nPage pages. This
-** function does not actually modify the database file on disk. It
-** just sets the internal state of the pager object so that the
-** truncation will be done when the current transaction is committed.
-**
-** This function is only called right before committing a transaction.
-** Once this function has been called, the transaction must either be
-** rolled back or committed. It is not safe to call this function and
-** then continue writing to the database.
-*/
-void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
- assert( pPager->dbSize>=nPage );
- assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
- pPager->dbSize = nPage;
-
- /* At one point the code here called assertTruncateConstraint() to
- ** ensure that all pages being truncated away by this operation are,
- ** if one or more savepoints are open, present in the savepoint
- ** journal so that they can be restored if the savepoint is rolled
- ** back. This is no longer necessary as this function is now only
- ** called right before committing a transaction. So although the
- ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
- ** they cannot be rolled back. So the assertTruncateConstraint() call
- ** is no longer correct. */
-}
-
-
-/*
-** This function is called before attempting a hot-journal rollback. It
-** syncs the journal file to disk, then sets pPager->journalHdr to the
-** size of the journal file so that the pager_playback() routine knows
-** that the entire journal file has been synced.
-**
-** Syncing a hot-journal to disk before attempting to roll it back ensures
-** that if a power-failure occurs during the rollback, the process that
-** attempts rollback following system recovery sees the same journal
-** content as this process.
-**
-** If everything goes as planned, SQLITE_OK is returned. Otherwise,
-** an SQLite error code.
-*/
-static int pagerSyncHotJournal(Pager *pPager){
- int rc = SQLITE_OK;
- if( !pPager->noSync ){
- rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
- }
- return rc;
-}
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/*
-** Obtain a reference to a memory mapped page object for page number pgno.
-** The new object will use the pointer pData, obtained from xFetch().
-** If successful, set *ppPage to point to the new page reference
-** and return SQLITE_OK. Otherwise, return an SQLite error code and set
-** *ppPage to zero.
-**
-** Page references obtained by calling this function should be released
-** by calling pagerReleaseMapPage().
-*/
-static int pagerAcquireMapPage(
- Pager *pPager, /* Pager object */
- Pgno pgno, /* Page number */
- void *pData, /* xFetch()'d data for this page */
- PgHdr **ppPage /* OUT: Acquired page object */
-){
- PgHdr *p; /* Memory mapped page to return */
-
- if( pPager->pMmapFreelist ){
- *ppPage = p = pPager->pMmapFreelist;
- pPager->pMmapFreelist = p->pDirty;
- p->pDirty = 0;
- assert( pPager->nExtra>=8 );
- memset(p->pExtra, 0, 8);
- }else{
- *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
- if( p==0 ){
- sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
- return SQLITE_NOMEM_BKPT;
- }
- p->pExtra = (void *)&p[1];
- p->flags = PGHDR_MMAP;
- p->nRef = 1;
- p->pPager = pPager;
- }
-
- assert( p->pExtra==(void *)&p[1] );
- assert( p->pPage==0 );
- assert( p->flags==PGHDR_MMAP );
- assert( p->pPager==pPager );
- assert( p->nRef==1 );
-
- p->pgno = pgno;
- p->pData = pData;
- pPager->nMmapOut++;
-
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Release a reference to page pPg. pPg must have been returned by an
-** earlier call to pagerAcquireMapPage().
-*/
-static void pagerReleaseMapPage(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- pPager->nMmapOut--;
- pPg->pDirty = pPager->pMmapFreelist;
- pPager->pMmapFreelist = pPg;
-
- assert( pPager->fd->pMethods->iVersion>=3 );
- sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
-}
-
-/*
-** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
-*/
-static void pagerFreeMapHdrs(Pager *pPager){
- PgHdr *p;
- PgHdr *pNext;
- for(p=pPager->pMmapFreelist; p; p=pNext){
- pNext = p->pDirty;
- sqlite3_free(p);
- }
-}
-
-/* Verify that the database file has not be deleted or renamed out from
-** under the pager. Return SQLITE_OK if the database is still where it ought
-** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
-** code from sqlite3OsAccess()) if the database has gone missing.
-*/
-static int databaseIsUnmoved(Pager *pPager){
- int bHasMoved = 0;
- int rc;
-
- if( pPager->tempFile ) return SQLITE_OK;
- if( pPager->dbSize==0 ) return SQLITE_OK;
- assert( pPager->zFilename && pPager->zFilename[0] );
- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
- if( rc==SQLITE_NOTFOUND ){
- /* If the HAS_MOVED file-control is unimplemented, assume that the file
- ** has not been moved. That is the historical behavior of SQLite: prior to
- ** version 3.8.3, it never checked */
- rc = SQLITE_OK;
- }else if( rc==SQLITE_OK && bHasMoved ){
- rc = SQLITE_READONLY_DBMOVED;
- }
- return rc;
-}
-
-
-/*
-** Shutdown the page cache. Free all memory and close all files.
-**
-** If a transaction was in progress when this routine is called, that
-** transaction is rolled back. All outstanding pages are invalidated
-** and their memory is freed. Any attempt to use a page associated
-** with this page cache after this function returns will likely
-** result in a coredump.
-**
-** This function always succeeds. If a transaction is active an attempt
-** is made to roll it back. If an error occurs during the rollback
-** a hot journal may be left in the filesystem but no error is returned
-** to the caller.
-*/
-int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
- u8 *pTmp = (u8*)pPager->pTmpSpace;
- assert( db || pagerUseWal(pPager)==0 );
- assert( assert_pager_state(pPager) );
- disable_simulated_io_errors();
- sqlite3BeginBenignMalloc();
- pagerFreeMapHdrs(pPager);
- /* pPager->errCode = 0; */
- pPager->exclusiveMode = 0;
-#ifndef SQLITE_OMIT_WAL
- {
- u8 *a = 0;
- assert( db || pPager->pWal==0 );
- if( db && 0==(db->flags & SQLITE_NoCkptOnClose)
- && SQLITE_OK==databaseIsUnmoved(pPager)
- ){
- a = pTmp;
- }
- sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a);
- pPager->pWal = 0;
- }
-#endif
- pager_reset(pPager);
- if( MEMDB ){
- pager_unlock(pPager);
- }else{
- /* If it is open, sync the journal file before calling UnlockAndRollback.
- ** If this is not done, then an unsynced portion of the open journal
- ** file may be played back into the database. If a power failure occurs
- ** while this is happening, the database could become corrupt.
- **
- ** If an error occurs while trying to sync the journal, shift the pager
- ** into the ERROR state. This causes UnlockAndRollback to unlock the
- ** database and close the journal file without attempting to roll it
- ** back or finalize it. The next database user will have to do hot-journal
- ** rollback before accessing the database file.
- */
- if( isOpen(pPager->jfd) ){
- pager_error(pPager, pagerSyncHotJournal(pPager));
- }
- pagerUnlockAndRollback(pPager);
- }
- sqlite3EndBenignMalloc();
- enable_simulated_io_errors();
- PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
- IOTRACE(("CLOSE %p\n", pPager))
- sqlite3OsClose(pPager->jfd);
- sqlite3OsClose(pPager->fd);
- sqlite3PageFree(pTmp);
- sqlite3PcacheClose(pPager->pPCache);
-
-#ifdef SQLITE_HAS_CODEC
- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
-#endif
-
- assert( !pPager->aSavepoint && !pPager->pInJournal );
- assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
-
- sqlite3_free(pPager);
- return SQLITE_OK;
-}
-
-#if !defined(NDEBUG) || defined(SQLITE_TEST)
-/*
-** Return the page number for page pPg.
-*/
-Pgno sqlite3PagerPagenumber(DbPage *pPg){
- return pPg->pgno;
-}
-#endif
-
-/*
-** Increment the reference count for page pPg.
-*/
-void sqlite3PagerRef(DbPage *pPg){
- sqlite3PcacheRef(pPg);
-}
-
-/*
-** Sync the journal. In other words, make sure all the pages that have
-** been written to the journal have actually reached the surface of the
-** disk and can be restored in the event of a hot-journal rollback.
-**
-** If the Pager.noSync flag is set, then this function is a no-op.
-** Otherwise, the actions required depend on the journal-mode and the
-** device characteristics of the file-system, as follows:
-**
-** * If the journal file is an in-memory journal file, no action need
-** be taken.
-**
-** * Otherwise, if the device does not support the SAFE_APPEND property,
-** then the nRec field of the most recently written journal header
-** is updated to contain the number of journal records that have
-** been written following it. If the pager is operating in full-sync
-** mode, then the journal file is synced before this field is updated.
-**
-** * If the device does not support the SEQUENTIAL property, then
-** journal file is synced.
-**
-** Or, in pseudo-code:
-**
-** if( NOT <in-memory journal> ){
-** if( NOT SAFE_APPEND ){
-** if( <full-sync mode> ) xSync(<journal file>);
-** <update nRec field>
-** }
-** if( NOT SEQUENTIAL ) xSync(<journal file>);
-** }
-**
-** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
-** page currently held in memory before returning SQLITE_OK. If an IO
-** error is encountered, then the IO error code is returned to the caller.
-*/
-static int syncJournal(Pager *pPager, int newHdr){
- int rc; /* Return code */
-
- assert( pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
- );
- assert( assert_pager_state(pPager) );
- assert( !pagerUseWal(pPager) );
-
- rc = sqlite3PagerExclusiveLock(pPager);
- if( rc!=SQLITE_OK ) return rc;
-
- if( !pPager->noSync ){
- assert( !pPager->tempFile );
- if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
- const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
- assert( isOpen(pPager->jfd) );
-
- if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
- /* This block deals with an obscure problem. If the last connection
- ** that wrote to this database was operating in persistent-journal
- ** mode, then the journal file may at this point actually be larger
- ** than Pager.journalOff bytes. If the next thing in the journal
- ** file happens to be a journal-header (written as part of the
- ** previous connection's transaction), and a crash or power-failure
- ** occurs after nRec is updated but before this connection writes
- ** anything else to the journal file (or commits/rolls back its
- ** transaction), then SQLite may become confused when doing the
- ** hot-journal rollback following recovery. It may roll back all
- ** of this connections data, then proceed to rolling back the old,
- ** out-of-date data that follows it. Database corruption.
- **
- ** To work around this, if the journal file does appear to contain
- ** a valid header following Pager.journalOff, then write a 0x00
- ** byte to the start of it to prevent it from being recognized.
- **
- ** Variable iNextHdrOffset is set to the offset at which this
- ** problematic header will occur, if it exists. aMagic is used
- ** as a temporary buffer to inspect the first couple of bytes of
- ** the potential journal header.
- */
- i64 iNextHdrOffset;
- u8 aMagic[8];
- u8 zHeader[sizeof(aJournalMagic)+4];
-
- memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
- put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);
-
- iNextHdrOffset = journalHdrOffset(pPager);
- rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset);
- if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){
- static const u8 zerobyte = 0;
- rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset);
- }
- if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
- return rc;
- }
-
- /* Write the nRec value into the journal file header. If in
- ** full-synchronous mode, sync the journal first. This ensures that
- ** all data has really hit the disk before nRec is updated to mark
- ** it as a candidate for rollback.
- **
- ** This is not required if the persistent media supports the
- ** SAFE_APPEND property. Because in this case it is not possible
- ** for garbage data to be appended to the file, the nRec field
- ** is populated with 0xFFFFFFFF when the journal header is written
- ** and never needs to be updated.
- */
- if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
- PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
- IOTRACE(("JSYNC %p\n", pPager))
- rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
- if( rc!=SQLITE_OK ) return rc;
- }
- IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr));
- rc = sqlite3OsWrite(
- pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr
- );
- if( rc!=SQLITE_OK ) return rc;
- }
- if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
- PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
- IOTRACE(("JSYNC %p\n", pPager))
- rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
- (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
- );
- if( rc!=SQLITE_OK ) return rc;
- }
-
- pPager->journalHdr = pPager->journalOff;
- if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
- pPager->nRec = 0;
- rc = writeJournalHdr(pPager);
- if( rc!=SQLITE_OK ) return rc;
- }
- }else{
- pPager->journalHdr = pPager->journalOff;
- }
- }
-
- /* Unless the pager is in noSync mode, the journal file was just
- ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
- ** all pages.
- */
- sqlite3PcacheClearSyncFlags(pPager->pPCache);
- pPager->eState = PAGER_WRITER_DBMOD;
- assert( assert_pager_state(pPager) );
- return SQLITE_OK;
-}
-
-/*
-** The argument is the first in a linked list of dirty pages connected
-** by the PgHdr.pDirty pointer. This function writes each one of the
-** in-memory pages in the list to the database file. The argument may
-** be NULL, representing an empty list. In this case this function is
-** a no-op.
-**
-** The pager must hold at least a RESERVED lock when this function
-** is called. Before writing anything to the database file, this lock
-** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained,
-** SQLITE_BUSY is returned and no data is written to the database file.
-**
-** If the pager is a temp-file pager and the actual file-system file
-** is not yet open, it is created and opened before any data is
-** written out.
-**
-** Once the lock has been upgraded and, if necessary, the file opened,
-** the pages are written out to the database file in list order. Writing
-** a page is skipped if it meets either of the following criteria:
-**
-** * The page number is greater than Pager.dbSize, or
-** * The PGHDR_DONT_WRITE flag is set on the page.
-**
-** If writing out a page causes the database file to grow, Pager.dbFileSize
-** is updated accordingly. If page 1 is written out, then the value cached
-** in Pager.dbFileVers[] is updated to match the new value stored in
-** the database file.
-**
-** If everything is successful, SQLITE_OK is returned. If an IO error
-** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
-** be obtained, SQLITE_BUSY is returned.
-*/
-static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
- int rc = SQLITE_OK; /* Return code */
-
- /* This function is only called for rollback pagers in WRITER_DBMOD state. */
- assert( !pagerUseWal(pPager) );
- assert( pPager->tempFile || pPager->eState==PAGER_WRITER_DBMOD );
- assert( pPager->eLock==EXCLUSIVE_LOCK );
- assert( isOpen(pPager->fd) || pList->pDirty==0 );
-
- /* If the file is a temp-file has not yet been opened, open it now. It
- ** is not possible for rc to be other than SQLITE_OK if this branch
- ** is taken, as pager_wait_on_lock() is a no-op for temp-files.
- */
- if( !isOpen(pPager->fd) ){
- assert( pPager->tempFile && rc==SQLITE_OK );
- rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
- }
-
- /* Before the first write, give the VFS a hint of what the final
- ** file size will be.
- */
- assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
- if( rc==SQLITE_OK
- && pPager->dbHintSize<pPager->dbSize
- && (pList->pDirty || pList->pgno>pPager->dbHintSize)
- ){
- sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
- sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
- pPager->dbHintSize = pPager->dbSize;
- }
-
- while( rc==SQLITE_OK && pList ){
- Pgno pgno = pList->pgno;
-
- /* If there are dirty pages in the page cache with page numbers greater
- ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
- ** make the file smaller (presumably by auto-vacuum code). Do not write
- ** any such pages to the file.
- **
- ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
- ** set (set by sqlite3PagerDontWrite()).
- */
- if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
- i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
- char *pData; /* Data to write */
-
- assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
- if( pList->pgno==1 ) pager_write_changecounter(pList);
-
- /* Encode the database */
- CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM_BKPT, pData);
-
- /* Write out the page data. */
- rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
-
- /* If page 1 was just written, update Pager.dbFileVers to match
- ** the value now stored in the database file. If writing this
- ** page caused the database file to grow, update dbFileSize.
- */
- if( pgno==1 ){
- memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
- }
- if( pgno>pPager->dbFileSize ){
- pPager->dbFileSize = pgno;
- }
- pPager->aStat[PAGER_STAT_WRITE]++;
-
- /* Update any backup objects copying the contents of this pager. */
- sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
-
- PAGERTRACE(("STORE %d page %d hash(%08x)\n",
- PAGERID(pPager), pgno, pager_pagehash(pList)));
- IOTRACE(("PGOUT %p %d\n", pPager, pgno));
- PAGER_INCR(sqlite3_pager_writedb_count);
- }else{
- PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
- }
- pager_set_pagehash(pList);
- pList = pList->pDirty;
- }
-
- return rc;
-}
-
-/*
-** Ensure that the sub-journal file is open. If it is already open, this
-** function is a no-op.
-**
-** SQLITE_OK is returned if everything goes according to plan. An
-** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen()
-** fails.
-*/
-static int openSubJournal(Pager *pPager){
- int rc = SQLITE_OK;
- if( !isOpen(pPager->sjfd) ){
- const int flags = SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE
- | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE
- | SQLITE_OPEN_DELETEONCLOSE;
- int nStmtSpill = sqlite3Config.nStmtSpill;
- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
- nStmtSpill = -1;
- }
- rc = sqlite3JournalOpen(pPager->pVfs, 0, pPager->sjfd, flags, nStmtSpill);
- }
- return rc;
-}
-
-/*
-** Append a record of the current state of page pPg to the sub-journal.
-**
-** If successful, set the bit corresponding to pPg->pgno in the bitvecs
-** for all open savepoints before returning.
-**
-** This function returns SQLITE_OK if everything is successful, an IO
-** error code if the attempt to write to the sub-journal fails, or
-** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint
-** bitvec.
-*/
-static int subjournalPage(PgHdr *pPg){
- int rc = SQLITE_OK;
- Pager *pPager = pPg->pPager;
- if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
-
- /* Open the sub-journal, if it has not already been opened */
- assert( pPager->useJournal );
- assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
- assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
- assert( pagerUseWal(pPager)
- || pageInJournal(pPager, pPg)
- || pPg->pgno>pPager->dbOrigSize
- );
- rc = openSubJournal(pPager);
-
- /* If the sub-journal was opened successfully (or was already open),
- ** write the journal record into the file. */
- if( rc==SQLITE_OK ){
- void *pData = pPg->pData;
- i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
- char *pData2;
-
-#if SQLITE_HAS_CODEC
- if( !pPager->subjInMemory ){
- CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
- }else
-#endif
- pData2 = pData;
- PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
- rc = write32bits(pPager->sjfd, offset, pPg->pgno);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
- }
- }
- }
- if( rc==SQLITE_OK ){
- pPager->nSubRec++;
- assert( pPager->nSavepoint>0 );
- rc = addToSavepointBitvecs(pPager, pPg->pgno);
- }
- return rc;
-}
-static int subjournalPageIfRequired(PgHdr *pPg){
- if( subjRequiresPage(pPg) ){
- return subjournalPage(pPg);
- }else{
- return SQLITE_OK;
- }
-}
-
-/*
-** This function is called by the pcache layer when it has reached some
-** soft memory limit. The first argument is a pointer to a Pager object
-** (cast as a void*). The pager is always 'purgeable' (not an in-memory
-** database). The second argument is a reference to a page that is
-** currently dirty but has no outstanding references. The page
-** is always associated with the Pager object passed as the first
-** argument.
-**
-** The job of this function is to make pPg clean by writing its contents
-** out to the database file, if possible. This may involve syncing the
-** journal file.
-**
-** If successful, sqlite3PcacheMakeClean() is called on the page and
-** SQLITE_OK returned. If an IO error occurs while trying to make the
-** page clean, the IO error code is returned. If the page cannot be
-** made clean for some other reason, but no error occurs, then SQLITE_OK
-** is returned by sqlite3PcacheMakeClean() is not called.
-*/
-static int pagerStress(void *p, PgHdr *pPg){
- Pager *pPager = (Pager *)p;
- int rc = SQLITE_OK;
-
- assert( pPg->pPager==pPager );
- assert( pPg->flags&PGHDR_DIRTY );
-
- /* The doNotSpill NOSYNC bit is set during times when doing a sync of
- ** journal (and adding a new header) is not allowed. This occurs
- ** during calls to sqlite3PagerWrite() while trying to journal multiple
- ** pages belonging to the same sector.
- **
- ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling
- ** regardless of whether or not a sync is required. This is set during
- ** a rollback or by user request, respectively.
- **
- ** Spilling is also prohibited when in an error state since that could
- ** lead to database corruption. In the current implementation it
- ** is impossible for sqlite3PcacheFetch() to be called with createFlag==3
- ** while in the error state, hence it is impossible for this routine to
- ** be called in the error state. Nevertheless, we include a NEVER()
- ** test for the error state as a safeguard against future changes.
- */
- if( NEVER(pPager->errCode) ) return SQLITE_OK;
- testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK );
- testcase( pPager->doNotSpill & SPILLFLAG_OFF );
- testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC );
- if( pPager->doNotSpill
- && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
- || (pPg->flags & PGHDR_NEED_SYNC)!=0)
- ){
- return SQLITE_OK;
- }
-
- pPager->aStat[PAGER_STAT_SPILL]++;
- pPg->pDirty = 0;
- if( pagerUseWal(pPager) ){
- /* Write a single frame for this page to the log. */
- rc = subjournalPageIfRequired(pPg);
- if( rc==SQLITE_OK ){
- rc = pagerWalFrames(pPager, pPg, 0, 0);
- }
- }else{
-
-#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- if( pPager->tempFile==0 ){
- rc = sqlite3JournalCreate(pPager->jfd);
- if( rc!=SQLITE_OK ) return pager_error(pPager, rc);
- }
-#endif
-
- /* Sync the journal file if required. */
- if( pPg->flags&PGHDR_NEED_SYNC
- || pPager->eState==PAGER_WRITER_CACHEMOD
- ){
- rc = syncJournal(pPager, 1);
- }
-
- /* Write the contents of the page out to the database file. */
- if( rc==SQLITE_OK ){
- assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
- rc = pager_write_pagelist(pPager, pPg);
- }
- }
-
- /* Mark the page as clean. */
- if( rc==SQLITE_OK ){
- PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
- sqlite3PcacheMakeClean(pPg);
- }
-
- return pager_error(pPager, rc);
-}
-
-/*
-** Flush all unreferenced dirty pages to disk.
-*/
-int sqlite3PagerFlush(Pager *pPager){
- int rc = pPager->errCode;
- if( !MEMDB ){
- PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
- assert( assert_pager_state(pPager) );
- while( rc==SQLITE_OK && pList ){
- PgHdr *pNext = pList->pDirty;
- if( pList->nRef==0 ){
- rc = pagerStress((void*)pPager, pList);
- }
- pList = pNext;
- }
- }
-
- return rc;
-}
-
-/*
-** Allocate and initialize a new Pager object and put a pointer to it
-** in *ppPager. The pager should eventually be freed by passing it
-** to sqlite3PagerClose().
-**
-** The zFilename argument is the path to the database file to open.
-** If zFilename is NULL then a randomly-named temporary file is created
-** and used as the file to be cached. Temporary files are be deleted
-** automatically when they are closed. If zFilename is ":memory:" then
-** all information is held in cache. It is never written to disk.
-** This can be used to implement an in-memory database.
-**
-** The nExtra parameter specifies the number of bytes of space allocated
-** along with each page reference. This space is available to the user
-** via the sqlite3PagerGetExtra() API. When a new page is allocated, the
-** first 8 bytes of this space are zeroed but the remainder is uninitialized.
-** (The extra space is used by btree as the MemPage object.)
-**
-** The flags argument is used to specify properties that affect the
-** operation of the pager. It should be passed some bitwise combination
-** of the PAGER_* flags.
-**
-** The vfsFlags parameter is a bitmask to pass to the flags parameter
-** of the xOpen() method of the supplied VFS when opening files.
-**
-** If the pager object is allocated and the specified file opened
-** successfully, SQLITE_OK is returned and *ppPager set to point to
-** the new pager object. If an error occurs, *ppPager is set to NULL
-** and error code returned. This function may return SQLITE_NOMEM
-** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or
-** various SQLITE_IO_XXX errors.
-*/
-int sqlite3PagerOpen(
- sqlite3_vfs *pVfs, /* The virtual file system to use */
- Pager **ppPager, /* OUT: Return the Pager structure here */
- const char *zFilename, /* Name of the database file to open */
- int nExtra, /* Extra bytes append to each in-memory page */
- int flags, /* flags controlling this file */
- int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */
- void (*xReinit)(DbPage*) /* Function to reinitialize pages */
-){
- u8 *pPtr;
- Pager *pPager = 0; /* Pager object to allocate and return */
- int rc = SQLITE_OK; /* Return code */
- int tempFile = 0; /* True for temp files (incl. in-memory files) */
- int memDb = 0; /* True if this is an in-memory file */
-#ifdef SQLITE_ENABLE_DESERIALIZE
- int memJM = 0; /* Memory journal mode */
-#else
-# define memJM 0
-#endif
- int readOnly = 0; /* True if this is a read-only file */
- int journalFileSize; /* Bytes to allocate for each journal fd */
- char *zPathname = 0; /* Full path to database file */
- int nPathname = 0; /* Number of bytes in zPathname */
- int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
- int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
- u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
- const char *zUri = 0; /* URI args to copy */
- int nUri = 0; /* Number of bytes of URI args at *zUri */
-
- /* Figure out how much space is required for each journal file-handle
- ** (there are two of them, the main journal and the sub-journal). */
- journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
-
- /* Set the output variable to NULL in case an error occurs. */
- *ppPager = 0;
-
-#ifndef SQLITE_OMIT_MEMORYDB
- if( flags & PAGER_MEMORY ){
- memDb = 1;
- if( zFilename && zFilename[0] ){
- zPathname = sqlite3DbStrDup(0, zFilename);
- if( zPathname==0 ) return SQLITE_NOMEM_BKPT;
- nPathname = sqlite3Strlen30(zPathname);
- zFilename = 0;
- }
- }
-#endif
-
- /* Compute and store the full pathname in an allocated buffer pointed
- ** to by zPathname, length nPathname. Or, if this is a temporary file,
- ** leave both nPathname and zPathname set to 0.
- */
- if( zFilename && zFilename[0] ){
- const char *z;
- nPathname = pVfs->mxPathname+1;
- zPathname = sqlite3DbMallocRaw(0, nPathname*2);
- if( zPathname==0 ){
- return SQLITE_NOMEM_BKPT;
- }
- zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
- rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
- nPathname = sqlite3Strlen30(zPathname);
- z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
- while( *z ){
- z += sqlite3Strlen30(z)+1;
- z += sqlite3Strlen30(z)+1;
- }
- nUri = (int)(&z[1] - zUri);
- assert( nUri>=0 );
- if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
- /* This branch is taken when the journal path required by
- ** the database being opened will be more than pVfs->mxPathname
- ** bytes in length. This means the database cannot be opened,
- ** as it will not be possible to open the journal file or even
- ** check for a hot-journal before reading.
- */
- rc = SQLITE_CANTOPEN_BKPT;
- }
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(0, zPathname);
- return rc;
- }
- }
-
- /* Allocate memory for the Pager structure, PCache object, the
- ** three file descriptors, the database file name and the journal
- ** file name. The layout in memory is as follows:
- **
- ** Pager object (sizeof(Pager) bytes)
- ** PCache object (sqlite3PcacheSize() bytes)
- ** Database file handle (pVfs->szOsFile bytes)
- ** Sub-journal file handle (journalFileSize bytes)
- ** Main journal file handle (journalFileSize bytes)
- ** Database file name (nPathname+1 bytes)
- ** Journal file name (nPathname+8+1 bytes)
- */
- pPtr = (u8 *)sqlite3MallocZero(
- ROUND8(sizeof(*pPager)) + /* Pager structure */
- ROUND8(pcacheSize) + /* PCache object */
- ROUND8(pVfs->szOsFile) + /* The main db file */
- journalFileSize * 2 + /* The two journal files */
- nPathname + 1 + nUri + /* zFilename */
- nPathname + 8 + 2 /* zJournal */
-#ifndef SQLITE_OMIT_WAL
- + nPathname + 4 + 2 /* zWal */
-#endif
- );
- assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
- if( !pPtr ){
- sqlite3DbFree(0, zPathname);
- return SQLITE_NOMEM_BKPT;
- }
- pPager = (Pager*)(pPtr);
- pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
- pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
- pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
- pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
- pPager->zFilename = (char*)(pPtr += journalFileSize);
- assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
-
- /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
- if( zPathname ){
- assert( nPathname>0 );
- pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
- memcpy(pPager->zFilename, zPathname, nPathname);
- if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
- memcpy(pPager->zJournal, zPathname, nPathname);
- memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
- sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
-#ifndef SQLITE_OMIT_WAL
- pPager->zWal = &pPager->zJournal[nPathname+8+1];
- memcpy(pPager->zWal, zPathname, nPathname);
- memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
- sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
-#endif
- sqlite3DbFree(0, zPathname);
- }
- pPager->pVfs = pVfs;
- pPager->vfsFlags = vfsFlags;
-
- /* Open the pager file.
- */
- if( zFilename && zFilename[0] ){
- int fout = 0; /* VFS flags returned by xOpen() */
- rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
- assert( !memDb );
-#ifdef SQLITE_ENABLE_DESERIALIZE
- memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
-#endif
- readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
-
- /* If the file was successfully opened for read/write access,
- ** choose a default page size in case we have to create the
- ** database file. The default page size is the maximum of:
- **
- ** + SQLITE_DEFAULT_PAGE_SIZE,
- ** + The value returned by sqlite3OsSectorSize()
- ** + The largest page size that can be written atomically.
- */
- if( rc==SQLITE_OK ){
- int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
- if( !readOnly ){
- setSectorSize(pPager);
- assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
- if( szPageDflt<pPager->sectorSize ){
- if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
- szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
- }else{
- szPageDflt = (u32)pPager->sectorSize;
- }
- }
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
- {
- int ii;
- assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
- assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
- assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
- for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
- if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
- szPageDflt = ii;
- }
- }
- }
-#endif
- }
- pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
- if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
- || sqlite3_uri_boolean(zFilename, "immutable", 0) ){
- vfsFlags |= SQLITE_OPEN_READONLY;
- goto act_like_temp_file;
- }
- }
- }else{
- /* If a temporary file is requested, it is not opened immediately.
- ** In this case we accept the default page size and delay actually
- ** opening the file until the first call to OsWrite().
- **
- ** This branch is also run for an in-memory database. An in-memory
- ** database is the same as a temp-file that is never written out to
- ** disk and uses an in-memory rollback journal.
- **
- ** This branch also runs for files marked as immutable.
- */
-act_like_temp_file:
- tempFile = 1;
- pPager->eState = PAGER_READER; /* Pretend we already have a lock */
- pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE mode */
- pPager->noLock = 1; /* Do no locking */
- readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
- }
-
- /* The following call to PagerSetPagesize() serves to set the value of
- ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
- */
- if( rc==SQLITE_OK ){
- assert( pPager->memDb==0 );
- rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1);
- testcase( rc!=SQLITE_OK );
- }
-
- /* Initialize the PCache object. */
- if( rc==SQLITE_OK ){
- nExtra = ROUND8(nExtra);
- assert( nExtra>=8 && nExtra<1000 );
- rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
- !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
- }
-
- /* If an error occurred above, free the Pager structure and close the file.
- */
- if( rc!=SQLITE_OK ){
- sqlite3OsClose(pPager->fd);
- sqlite3PageFree(pPager->pTmpSpace);
- sqlite3_free(pPager);
- return rc;
- }
-
- PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
- IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
-
- pPager->useJournal = (u8)useJournal;
- /* pPager->stmtOpen = 0; */
- /* pPager->stmtInUse = 0; */
- /* pPager->nRef = 0; */
- /* pPager->stmtSize = 0; */
- /* pPager->stmtJSize = 0; */
- /* pPager->nPage = 0; */
- pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
- /* pPager->state = PAGER_UNLOCK; */
- /* pPager->errMask = 0; */
- pPager->tempFile = (u8)tempFile;
- assert( tempFile==PAGER_LOCKINGMODE_NORMAL
- || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
- assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
- pPager->exclusiveMode = (u8)tempFile;
- pPager->changeCountDone = pPager->tempFile;
- pPager->memDb = (u8)memDb;
- pPager->readOnly = (u8)readOnly;
- assert( useJournal || pPager->tempFile );
- pPager->noSync = pPager->tempFile;
- if( pPager->noSync ){
- assert( pPager->fullSync==0 );
- assert( pPager->extraSync==0 );
- assert( pPager->syncFlags==0 );
- assert( pPager->walSyncFlags==0 );
- }else{
- pPager->fullSync = 1;
- pPager->extraSync = 0;
- pPager->syncFlags = SQLITE_SYNC_NORMAL;
- pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL<<2);
- }
- /* pPager->pFirst = 0; */
- /* pPager->pFirstSynced = 0; */
- /* pPager->pLast = 0; */
- pPager->nExtra = (u16)nExtra;
- pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
- assert( isOpen(pPager->fd) || tempFile );
- setSectorSize(pPager);
- if( !useJournal ){
- pPager->journalMode = PAGER_JOURNALMODE_OFF;
- }else if( memDb || memJM ){
- pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
- }
- /* pPager->xBusyHandler = 0; */
- /* pPager->pBusyHandlerArg = 0; */
- pPager->xReiniter = xReinit;
- setGetterMethod(pPager);
- /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
- /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
-
- *ppPager = pPager;
- return SQLITE_OK;
-}
-
-
-
-/*
-** This function is called after transitioning from PAGER_UNLOCK to
-** PAGER_SHARED state. It tests if there is a hot journal present in
-** the file-system for the given pager. A hot journal is one that
-** needs to be played back. According to this function, a hot-journal
-** file exists if the following criteria are met:
-**
-** * The journal file exists in the file system, and
-** * No process holds a RESERVED or greater lock on the database file, and
-** * The database file itself is greater than 0 bytes in size, and
-** * The first byte of the journal file exists and is not 0x00.
-**
-** If the current size of the database file is 0 but a journal file
-** exists, that is probably an old journal left over from a prior
-** database with the same name. In this case the journal file is
-** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
-** is returned.
-**
-** This routine does not check if there is a master journal filename
-** at the end of the file. If there is, and that master journal file
-** does not exist, then the journal file is not really hot. In this
-** case this routine will return a false-positive. The pager_playback()
-** routine will discover that the journal file is not really hot and
-** will not roll it back.
-**
-** If a hot-journal file is found to exist, *pExists is set to 1 and
-** SQLITE_OK returned. If no hot-journal file is present, *pExists is
-** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
-** to determine whether or not a hot-journal file exists, the IO error
-** code is returned and the value of *pExists is undefined.
-*/
-static int hasHotJournal(Pager *pPager, int *pExists){
- sqlite3_vfs * const pVfs = pPager->pVfs;
- int rc = SQLITE_OK; /* Return code */
- int exists = 1; /* True if a journal file is present */
- int jrnlOpen = !!isOpen(pPager->jfd);
-
- assert( pPager->useJournal );
- assert( isOpen(pPager->fd) );
- assert( pPager->eState==PAGER_OPEN );
-
- assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
- SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
- ));
-
- *pExists = 0;
- if( !jrnlOpen ){
- rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
- }
- if( rc==SQLITE_OK && exists ){
- int locked = 0; /* True if some process holds a RESERVED lock */
-
- /* Race condition here: Another process might have been holding the
- ** the RESERVED lock and have a journal open at the sqlite3OsAccess()
- ** call above, but then delete the journal and drop the lock before
- ** we get to the following sqlite3OsCheckReservedLock() call. If that
- ** is the case, this routine might think there is a hot journal when
- ** in fact there is none. This results in a false-positive which will
- ** be dealt with by the playback routine. Ticket #3883.
- */
- rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
- if( rc==SQLITE_OK && !locked ){
- Pgno nPage; /* Number of pages in database file */
-
- assert( pPager->tempFile==0 );
- rc = pagerPagecount(pPager, &nPage);
- if( rc==SQLITE_OK ){
- /* If the database is zero pages in size, that means that either (1) the
- ** journal is a remnant from a prior database with the same name where
- ** the database file but not the journal was deleted, or (2) the initial
- ** transaction that populates a new database is being rolled back.
- ** In either case, the journal file can be deleted. However, take care
- ** not to delete the journal file if it is already open due to
- ** journal_mode=PERSIST.
- */
- if( nPage==0 && !jrnlOpen ){
- sqlite3BeginBenignMalloc();
- if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
- sqlite3OsDelete(pVfs, pPager->zJournal, 0);
- if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
- }
- sqlite3EndBenignMalloc();
- }else{
- /* The journal file exists and no other connection has a reserved
- ** or greater lock on the database file. Now check that there is
- ** at least one non-zero bytes at the start of the journal file.
- ** If there is, then we consider this journal to be hot. If not,
- ** it can be ignored.
- */
- if( !jrnlOpen ){
- int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
- }
- if( rc==SQLITE_OK ){
- u8 first = 0;
- rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0);
- if( rc==SQLITE_IOERR_SHORT_READ ){
- rc = SQLITE_OK;
- }
- if( !jrnlOpen ){
- sqlite3OsClose(pPager->jfd);
- }
- *pExists = (first!=0);
- }else if( rc==SQLITE_CANTOPEN ){
- /* If we cannot open the rollback journal file in order to see if
- ** it has a zero header, that might be due to an I/O error, or
- ** it might be due to the race condition described above and in
- ** ticket #3883. Either way, assume that the journal is hot.
- ** This might be a false positive. But if it is, then the
- ** automatic journal playback and recovery mechanism will deal
- ** with it under an EXCLUSIVE lock where we do not need to
- ** worry so much with race conditions.
- */
- *pExists = 1;
- rc = SQLITE_OK;
- }
- }
- }
- }
- }
-
- return rc;
-}
-
-/*
-** This function is called to obtain a shared lock on the database file.
-** It is illegal to call sqlite3PagerGet() until after this function
-** has been successfully called. If a shared-lock is already held when
-** this function is called, it is a no-op.
-**
-** The following operations are also performed by this function.
-**
-** 1) If the pager is currently in PAGER_OPEN state (no lock held
-** on the database file), then an attempt is made to obtain a
-** SHARED lock on the database file. Immediately after obtaining
-** the SHARED lock, the file-system is checked for a hot-journal,
-** which is played back if present. Following any hot-journal
-** rollback, the contents of the cache are validated by checking
-** the 'change-counter' field of the database file header and
-** discarded if they are found to be invalid.
-**
-** 2) If the pager is running in exclusive-mode, and there are currently
-** no outstanding references to any pages, and is in the error state,
-** then an attempt is made to clear the error state by discarding
-** the contents of the page cache and rolling back any open journal
-** file.
-**
-** If everything is successful, SQLITE_OK is returned. If an IO error
-** occurs while locking the database, checking for a hot-journal file or
-** rolling back a journal file, the IO error code is returned.
-*/
-int sqlite3PagerSharedLock(Pager *pPager){
- int rc = SQLITE_OK; /* Return code */
-
- /* This routine is only called from b-tree and only when there are no
- ** outstanding pages. This implies that the pager state should either
- ** be OPEN or READER. READER is only possible if the pager is or was in
- ** exclusive access mode. */
- assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
- assert( assert_pager_state(pPager) );
- assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
- assert( pPager->errCode==SQLITE_OK );
-
- if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
- int bHotJournal = 1; /* True if there exists a hot journal-file */
-
- assert( !MEMDB );
- assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK );
-
- rc = pager_wait_on_lock(pPager, SHARED_LOCK);
- if( rc!=SQLITE_OK ){
- assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
- goto failed;
- }
-
- /* If a journal file exists, and there is no RESERVED lock on the
- ** database file, then it either needs to be played back or deleted.
- */
- if( pPager->eLock<=SHARED_LOCK ){
- rc = hasHotJournal(pPager, &bHotJournal);
- }
- if( rc!=SQLITE_OK ){
- goto failed;
- }
- if( bHotJournal ){
- if( pPager->readOnly ){
- rc = SQLITE_READONLY_ROLLBACK;
- goto failed;
- }
-
- /* Get an EXCLUSIVE lock on the database file. At this point it is
- ** important that a RESERVED lock is not obtained on the way to the
- ** EXCLUSIVE lock. If it were, another process might open the
- ** database file, detect the RESERVED lock, and conclude that the
- ** database is safe to read while this process is still rolling the
- ** hot-journal back.
- **
- ** Because the intermediate RESERVED lock is not requested, any
- ** other process attempting to access the database file will get to
- ** this point in the code and fail to obtain its own EXCLUSIVE lock
- ** on the database file.
- **
- ** Unless the pager is in locking_mode=exclusive mode, the lock is
- ** downgraded to SHARED_LOCK before this function returns.
- */
- rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
- if( rc!=SQLITE_OK ){
- goto failed;
- }
-
- /* If it is not already open and the file exists on disk, open the
- ** journal for read/write access. Write access is required because
- ** in exclusive-access mode the file descriptor will be kept open
- ** and possibly used for a transaction later on. Also, write-access
- ** is usually required to finalize the journal in journal_mode=persist
- ** mode (and also for journal_mode=truncate on some systems).
- **
- ** If the journal does not exist, it usually means that some
- ** other connection managed to get in and roll it back before
- ** this connection obtained the exclusive lock above. Or, it
- ** may mean that the pager was in the error-state when this
- ** function was called and the journal file does not exist.
- */
- if( !isOpen(pPager->jfd) ){
- sqlite3_vfs * const pVfs = pPager->pVfs;
- int bExists; /* True if journal file exists */
- rc = sqlite3OsAccess(
- pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
- if( rc==SQLITE_OK && bExists ){
- int fout = 0;
- int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
- assert( !pPager->tempFile );
- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
- assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
- if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
- rc = SQLITE_CANTOPEN_BKPT;
- sqlite3OsClose(pPager->jfd);
- }
- }
- }
-
- /* Playback and delete the journal. Drop the database write
- ** lock and reacquire the read lock. Purge the cache before
- ** playing back the hot-journal so that we don't end up with
- ** an inconsistent cache. Sync the hot journal before playing
- ** it back since the process that crashed and left the hot journal
- ** probably did not sync it and we are required to always sync
- ** the journal before playing it back.
- */
- if( isOpen(pPager->jfd) ){
- assert( rc==SQLITE_OK );
- rc = pagerSyncHotJournal(pPager);
- if( rc==SQLITE_OK ){
- rc = pager_playback(pPager, !pPager->tempFile);
- pPager->eState = PAGER_OPEN;
- }
- }else if( !pPager->exclusiveMode ){
- pagerUnlockDb(pPager, SHARED_LOCK);
- }
-
- if( rc!=SQLITE_OK ){
- /* This branch is taken if an error occurs while trying to open
- ** or roll back a hot-journal while holding an EXCLUSIVE lock. The
- ** pager_unlock() routine will be called before returning to unlock
- ** the file. If the unlock attempt fails, then Pager.eLock must be
- ** set to UNKNOWN_LOCK (see the comment above the #define for
- ** UNKNOWN_LOCK above for an explanation).
- **
- ** In order to get pager_unlock() to do this, set Pager.eState to
- ** PAGER_ERROR now. This is not actually counted as a transition
- ** to ERROR state in the state diagram at the top of this file,
- ** since we know that the same call to pager_unlock() will very
- ** shortly transition the pager object to the OPEN state. Calling
- ** assert_pager_state() would fail now, as it should not be possible
- ** to be in ERROR state when there are zero outstanding page
- ** references.
- */
- pager_error(pPager, rc);
- goto failed;
- }
-
- assert( pPager->eState==PAGER_OPEN );
- assert( (pPager->eLock==SHARED_LOCK)
- || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
- );
- }
-
- if( !pPager->tempFile && pPager->hasHeldSharedLock ){
- /* The shared-lock has just been acquired then check to
- ** see if the database has been modified. If the database has changed,
- ** flush the cache. The hasHeldSharedLock flag prevents this from
- ** occurring on the very first access to a file, in order to save a
- ** single unnecessary sqlite3OsRead() call at the start-up.
- **
- ** Database changes are detected by looking at 15 bytes beginning
- ** at offset 24 into the file. The first 4 of these 16 bytes are
- ** a 32-bit counter that is incremented with each change. The
- ** other bytes change randomly with each file change when
- ** a codec is in use.
- **
- ** There is a vanishingly small chance that a change will not be
- ** detected. The chance of an undetected change is so small that
- ** it can be neglected.
- */
- char dbFileVers[sizeof(pPager->dbFileVers)];
-
- IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
- rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
- if( rc!=SQLITE_OK ){
- if( rc!=SQLITE_IOERR_SHORT_READ ){
- goto failed;
- }
- memset(dbFileVers, 0, sizeof(dbFileVers));
- }
-
- if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
- pager_reset(pPager);
-
- /* Unmap the database file. It is possible that external processes
- ** may have truncated the database file and then extended it back
- ** to its original size while this process was not holding a lock.
- ** In this case there may exist a Pager.pMap mapping that appears
- ** to be the right size but is not actually valid. Avoid this
- ** possibility by unmapping the db here. */
- if( USEFETCH(pPager) ){
- sqlite3OsUnfetch(pPager->fd, 0, 0);
- }
- }
- }
-
- /* If there is a WAL file in the file-system, open this database in WAL
- ** mode. Otherwise, the following function call is a no-op.
- */
- rc = pagerOpenWalIfPresent(pPager);
-#ifndef SQLITE_OMIT_WAL
- assert( pPager->pWal==0 || rc==SQLITE_OK );
-#endif
- }
-
- if( pagerUseWal(pPager) ){
- assert( rc==SQLITE_OK );
- rc = pagerBeginReadTransaction(pPager);
- }
-
- if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
- rc = pagerPagecount(pPager, &pPager->dbSize);
- }
-
- failed:
- if( rc!=SQLITE_OK ){
- assert( !MEMDB );
- pager_unlock(pPager);
- assert( pPager->eState==PAGER_OPEN );
- }else{
- pPager->eState = PAGER_READER;
- pPager->hasHeldSharedLock = 1;
- }
- return rc;
-}
-
-/*
-** If the reference count has reached zero, rollback any active
-** transaction and unlock the pager.
-**
-** Except, in locking_mode=EXCLUSIVE when there is nothing to in
-** the rollback journal, the unlock is not performed and there is
-** nothing to rollback, so this routine is a no-op.
-*/
-static void pagerUnlockIfUnused(Pager *pPager){
- if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){
- assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */
- pagerUnlockAndRollback(pPager);
- }
-}
-
-/*
-** The page getter methods each try to acquire a reference to a
-** page with page number pgno. If the requested reference is
-** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
-**
-** There are different implementations of the getter method depending
-** on the current state of the pager.
-**
-** getPageNormal() -- The normal getter
-** getPageError() -- Used if the pager is in an error state
-** getPageMmap() -- Used if memory-mapped I/O is enabled
-**
-** If the requested page is already in the cache, it is returned.
-** Otherwise, a new page object is allocated and populated with data
-** read from the database file. In some cases, the pcache module may
-** choose not to allocate a new page object and may reuse an existing
-** object with no outstanding references.
-**
-** The extra data appended to a page is always initialized to zeros the
-** first time a page is loaded into memory. If the page requested is
-** already in the cache when this function is called, then the extra
-** data is left as it was when the page object was last used.
-**
-** If the database image is smaller than the requested page or if
-** the flags parameter contains the PAGER_GET_NOCONTENT bit and the
-** requested page is not already stored in the cache, then no
-** actual disk read occurs. In this case the memory image of the
-** page is initialized to all zeros.
-**
-** If PAGER_GET_NOCONTENT is true, it means that we do not care about
-** the contents of the page. This occurs in two scenarios:
-**
-** a) When reading a free-list leaf page from the database, and
-**
-** b) When a savepoint is being rolled back and we need to load
-** a new page into the cache to be filled with the data read
-** from the savepoint journal.
-**
-** If PAGER_GET_NOCONTENT is true, then the data returned is zeroed instead
-** of being read from the database. Additionally, the bits corresponding
-** to pgno in Pager.pInJournal (bitvec of pages already written to the
-** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
-** savepoints are set. This means if the page is made writable at any
-** point in the future, using a call to sqlite3PagerWrite(), its contents
-** will not be journaled. This saves IO.
-**
-** The acquisition might fail for several reasons. In all cases,
-** an appropriate error code is returned and *ppPage is set to NULL.
-**
-** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt
-** to find a page in the in-memory cache first. If the page is not already
-** in memory, this routine goes to disk to read it in whereas Lookup()
-** just returns 0. This routine acquires a read-lock the first time it
-** has to go to disk, and could also playback an old journal if necessary.
-** Since Lookup() never goes to disk, it never has to deal with locks
-** or journal files.
-*/
-static int getPageNormal(
- Pager *pPager, /* The pager open on the database file */
- Pgno pgno, /* Page number to fetch */
- DbPage **ppPage, /* Write a pointer to the page here */
- int flags /* PAGER_GET_XXX flags */
-){
- int rc = SQLITE_OK;
- PgHdr *pPg;
- u8 noContent; /* True if PAGER_GET_NOCONTENT is set */
- sqlite3_pcache_page *pBase;
-
- assert( pPager->errCode==SQLITE_OK );
- assert( pPager->eState>=PAGER_READER );
- assert( assert_pager_state(pPager) );
- assert( pPager->hasHeldSharedLock==1 );
-
- if( pgno==0 ) return SQLITE_CORRUPT_BKPT;
- pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
- if( pBase==0 ){
- pPg = 0;
- rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
- if( rc!=SQLITE_OK ) goto pager_acquire_err;
- if( pBase==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto pager_acquire_err;
- }
- }
- pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);
- assert( pPg==(*ppPage) );
- assert( pPg->pgno==pgno );
- assert( pPg->pPager==pPager || pPg->pPager==0 );
-
- noContent = (flags & PAGER_GET_NOCONTENT)!=0;
- if( pPg->pPager && !noContent ){
- /* In this case the pcache already contains an initialized copy of
- ** the page. Return without further ado. */
- assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
- pPager->aStat[PAGER_STAT_HIT]++;
- return SQLITE_OK;
-
- }else{
- /* The pager cache has created a new page. Its content needs to
- ** be initialized. But first some error checks:
- **
- ** (1) The maximum page number is 2^31
- ** (2) Never try to fetch the locking page
- */
- if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
- rc = SQLITE_CORRUPT_BKPT;
- goto pager_acquire_err;
- }
-
- pPg->pPager = pPager;
-
- assert( !isOpen(pPager->fd) || !MEMDB );
- if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){
- if( pgno>pPager->mxPgno ){
- rc = SQLITE_FULL;
- goto pager_acquire_err;
- }
- if( noContent ){
- /* Failure to set the bits in the InJournal bit-vectors is benign.
- ** It merely means that we might do some extra work to journal a
- ** page that does not need to be journaled. Nevertheless, be sure
- ** to test the case where a malloc error occurs while trying to set
- ** a bit in a bit vector.
- */
- sqlite3BeginBenignMalloc();
- if( pgno<=pPager->dbOrigSize ){
- TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
- testcase( rc==SQLITE_NOMEM );
- }
- TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
- testcase( rc==SQLITE_NOMEM );
- sqlite3EndBenignMalloc();
- }
- memset(pPg->pData, 0, pPager->pageSize);
- IOTRACE(("ZERO %p %d\n", pPager, pgno));
- }else{
- assert( pPg->pPager==pPager );
- pPager->aStat[PAGER_STAT_MISS]++;
- rc = readDbPage(pPg);
- if( rc!=SQLITE_OK ){
- goto pager_acquire_err;
- }
- }
- pager_set_pagehash(pPg);
- }
- return SQLITE_OK;
-
-pager_acquire_err:
- assert( rc!=SQLITE_OK );
- if( pPg ){
- sqlite3PcacheDrop(pPg);
- }
- pagerUnlockIfUnused(pPager);
- *ppPage = 0;
- return rc;
-}
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/* The page getter for when memory-mapped I/O is enabled */
-static int getPageMMap(
- Pager *pPager, /* The pager open on the database file */
- Pgno pgno, /* Page number to fetch */
- DbPage **ppPage, /* Write a pointer to the page here */
- int flags /* PAGER_GET_XXX flags */
-){
- int rc = SQLITE_OK;
- PgHdr *pPg = 0;
- u32 iFrame = 0; /* Frame to read from WAL file */
-
- /* It is acceptable to use a read-only (mmap) page for any page except
- ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
- ** flag was specified by the caller. And so long as the db is not a
- ** temporary or in-memory database. */
- const int bMmapOk = (pgno>1
- && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
- );
-
- assert( USEFETCH(pPager) );
-#ifdef SQLITE_HAS_CODEC
- assert( pPager->xCodec==0 );
-#endif
-
- /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here
- ** allows the compiler optimizer to reuse the results of the "pgno>1"
- ** test in the previous statement, and avoid testing pgno==0 in the
- ** common case where pgno is large. */
- if( pgno<=1 && pgno==0 ){
- return SQLITE_CORRUPT_BKPT;
- }
- assert( pPager->eState>=PAGER_READER );
- assert( assert_pager_state(pPager) );
- assert( pPager->hasHeldSharedLock==1 );
- assert( pPager->errCode==SQLITE_OK );
-
- if( bMmapOk && pagerUseWal(pPager) ){
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
- if( rc!=SQLITE_OK ){
- *ppPage = 0;
- return rc;
- }
- }
- if( bMmapOk && iFrame==0 ){
- void *pData = 0;
- rc = sqlite3OsFetch(pPager->fd,
- (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
- );
- if( rc==SQLITE_OK && pData ){
- if( pPager->eState>PAGER_READER || pPager->tempFile ){
- pPg = sqlite3PagerLookup(pPager, pgno);
- }
- if( pPg==0 ){
- rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
- }else{
- sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
- }
- if( pPg ){
- assert( rc==SQLITE_OK );
- *ppPage = pPg;
- return SQLITE_OK;
- }
- }
- if( rc!=SQLITE_OK ){
- *ppPage = 0;
- return rc;
- }
- }
- return getPageNormal(pPager, pgno, ppPage, flags);
-}
-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-
-/* The page getter method for when the pager is an error state */
-static int getPageError(
- Pager *pPager, /* The pager open on the database file */
- Pgno pgno, /* Page number to fetch */
- DbPage **ppPage, /* Write a pointer to the page here */
- int flags /* PAGER_GET_XXX flags */
-){
- UNUSED_PARAMETER(pgno);
- UNUSED_PARAMETER(flags);
- assert( pPager->errCode!=SQLITE_OK );
- *ppPage = 0;
- return pPager->errCode;
-}
-
-
-/* Dispatch all page fetch requests to the appropriate getter method.
-*/
-int sqlite3PagerGet(
- Pager *pPager, /* The pager open on the database file */
- Pgno pgno, /* Page number to fetch */
- DbPage **ppPage, /* Write a pointer to the page here */
- int flags /* PAGER_GET_XXX flags */
-){
- return pPager->xGet(pPager, pgno, ppPage, flags);
-}
-
-/*
-** Acquire a page if it is already in the in-memory cache. Do
-** not read the page from disk. Return a pointer to the page,
-** or 0 if the page is not in cache.
-**
-** See also sqlite3PagerGet(). The difference between this routine
-** and sqlite3PagerGet() is that _get() will go to the disk and read
-** in the page if the page is not already in cache. This routine
-** returns NULL if the page is not in cache or if a disk I/O error
-** has ever happened.
-*/
-DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
- sqlite3_pcache_page *pPage;
- assert( pPager!=0 );
- assert( pgno!=0 );
- assert( pPager->pPCache!=0 );
- pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);
- assert( pPage==0 || pPager->hasHeldSharedLock );
- if( pPage==0 ) return 0;
- return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
-}
-
-/*
-** Release a page reference.
-**
-** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be
-** used if we know that the page being released is not the last page.
-** The btree layer always holds page1 open until the end, so these first
-** to routines can be used to release any page other than BtShared.pPage1.
-**
-** Use sqlite3PagerUnrefPageOne() to release page1. This latter routine
-** checks the total number of outstanding pages and if the number of
-** pages reaches zero it drops the database lock.
-*/
-void sqlite3PagerUnrefNotNull(DbPage *pPg){
- TESTONLY( Pager *pPager = pPg->pPager; )
- assert( pPg!=0 );
- if( pPg->flags & PGHDR_MMAP ){
- assert( pPg->pgno!=1 ); /* Page1 is never memory mapped */
- pagerReleaseMapPage(pPg);
- }else{
- sqlite3PcacheRelease(pPg);
- }
- /* Do not use this routine to release the last reference to page1 */
- assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
-}
-void sqlite3PagerUnref(DbPage *pPg){
- if( pPg ) sqlite3PagerUnrefNotNull(pPg);
-}
-void sqlite3PagerUnrefPageOne(DbPage *pPg){
- Pager *pPager;
- assert( pPg!=0 );
- assert( pPg->pgno==1 );
- assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
- pPager = pPg->pPager;
- sqlite3PagerResetLockTimeout(pPager);
- sqlite3PcacheRelease(pPg);
- pagerUnlockIfUnused(pPager);
-}
-
-/*
-** This function is called at the start of every write transaction.
-** There must already be a RESERVED or EXCLUSIVE lock on the database
-** file when this routine is called.
-**
-** Open the journal file for pager pPager and write a journal header
-** to the start of it. If there are active savepoints, open the sub-journal
-** as well. This function is only used when the journal file is being
-** opened to write a rollback log for a transaction. It is not used
-** when opening a hot journal file to roll it back.
-**
-** If the journal file is already open (as it may be in exclusive mode),
-** then this function just writes a journal header to the start of the
-** already open file.
-**
-** Whether or not the journal file is opened by this function, the
-** Pager.pInJournal bitvec structure is allocated.
-**
-** Return SQLITE_OK if everything is successful. Otherwise, return
-** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or
-** an IO error code if opening or writing the journal file fails.
-*/
-static int pager_open_journal(Pager *pPager){
- int rc = SQLITE_OK; /* Return code */
- sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */
-
- assert( pPager->eState==PAGER_WRITER_LOCKED );
- assert( assert_pager_state(pPager) );
- assert( pPager->pInJournal==0 );
-
- /* If already in the error state, this function is a no-op. But on
- ** the other hand, this routine is never called if we are already in
- ** an error state. */
- if( NEVER(pPager->errCode) ) return pPager->errCode;
-
- if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
- pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
- if( pPager->pInJournal==0 ){
- return SQLITE_NOMEM_BKPT;
- }
-
- /* Open the journal file if it is not already open. */
- if( !isOpen(pPager->jfd) ){
- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
- sqlite3MemJournalOpen(pPager->jfd);
- }else{
- int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
- int nSpill;
-
- if( pPager->tempFile ){
- flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
- nSpill = sqlite3Config.nStmtSpill;
- }else{
- flags |= SQLITE_OPEN_MAIN_JOURNAL;
- nSpill = jrnlBufferSize(pPager);
- }
-
- /* Verify that the database still has the same name as it did when
- ** it was originally opened. */
- rc = databaseIsUnmoved(pPager);
- if( rc==SQLITE_OK ){
- rc = sqlite3JournalOpen (
- pVfs, pPager->zJournal, pPager->jfd, flags, nSpill
- );
- }
- }
- assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
- }
-
-
- /* Write the first journal header to the journal file and open
- ** the sub-journal if necessary.
- */
- if( rc==SQLITE_OK ){
- /* TODO: Check if all of these are really required. */
- pPager->nRec = 0;
- pPager->journalOff = 0;
- pPager->setMaster = 0;
- pPager->journalHdr = 0;
- rc = writeJournalHdr(pPager);
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3BitvecDestroy(pPager->pInJournal);
- pPager->pInJournal = 0;
- }else{
- assert( pPager->eState==PAGER_WRITER_LOCKED );
- pPager->eState = PAGER_WRITER_CACHEMOD;
- }
-
- return rc;
-}
-
-/*
-** Begin a write-transaction on the specified pager object. If a
-** write-transaction has already been opened, this function is a no-op.
-**
-** If the exFlag argument is false, then acquire at least a RESERVED
-** lock on the database file. If exFlag is true, then acquire at least
-** an EXCLUSIVE lock. If such a lock is already held, no locking
-** functions need be called.
-**
-** If the subjInMemory argument is non-zero, then any sub-journal opened
-** within this transaction will be opened as an in-memory file. This
-** has no effect if the sub-journal is already opened (as it may be when
-** running in exclusive mode) or if the transaction does not require a
-** sub-journal. If the subjInMemory argument is zero, then any required
-** sub-journal is implemented in-memory if pPager is an in-memory database,
-** or using a temporary file otherwise.
-*/
-int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
- int rc = SQLITE_OK;
-
- if( pPager->errCode ) return pPager->errCode;
- assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
- pPager->subjInMemory = (u8)subjInMemory;
-
- if( ALWAYS(pPager->eState==PAGER_READER) ){
- assert( pPager->pInJournal==0 );
-
- if( pagerUseWal(pPager) ){
- /* If the pager is configured to use locking_mode=exclusive, and an
- ** exclusive lock on the database is not already held, obtain it now.
- */
- if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
- rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- (void)sqlite3WalExclusiveMode(pPager->pWal, 1);
- }
-
- /* Grab the write lock on the log file. If successful, upgrade to
- ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
- ** The busy-handler is not invoked if another connection already
- ** holds the write-lock. If possible, the upper layer will call it.
- */
- rc = sqlite3WalBeginWriteTransaction(pPager->pWal);
- }else{
- /* Obtain a RESERVED lock on the database file. If the exFlag parameter
- ** is true, then immediately upgrade this to an EXCLUSIVE lock. The
- ** busy-handler callback can be used when upgrading to the EXCLUSIVE
- ** lock, but not when obtaining the RESERVED lock.
- */
- rc = pagerLockDb(pPager, RESERVED_LOCK);
- if( rc==SQLITE_OK && exFlag ){
- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
- }
- }
-
- if( rc==SQLITE_OK ){
- /* Change to WRITER_LOCKED state.
- **
- ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
- ** when it has an open transaction, but never to DBMOD or FINISHED.
- ** This is because in those states the code to roll back savepoint
- ** transactions may copy data from the sub-journal into the database
- ** file as well as into the page cache. Which would be incorrect in
- ** WAL mode.
- */
- pPager->eState = PAGER_WRITER_LOCKED;
- pPager->dbHintSize = pPager->dbSize;
- pPager->dbFileSize = pPager->dbSize;
- pPager->dbOrigSize = pPager->dbSize;
- pPager->journalOff = 0;
- }
-
- assert( rc==SQLITE_OK || pPager->eState==PAGER_READER );
- assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED );
- assert( assert_pager_state(pPager) );
- }
-
- PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
- return rc;
-}
-
-/*
-** Write page pPg onto the end of the rollback journal.
-*/
-static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- int rc;
- u32 cksum;
- char *pData2;
- i64 iOff = pPager->journalOff;
-
- /* We should never write to the journal file the page that
- ** contains the database locks. The following assert verifies
- ** that we do not. */
- assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
-
- assert( pPager->journalHdr<=pPager->journalOff );
- CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
- cksum = pager_cksum(pPager, (u8*)pData2);
-
- /* Even if an IO or diskfull error occurs while journalling the
- ** page in the block above, set the need-sync flag for the page.
- ** Otherwise, when the transaction is rolled back, the logic in
- ** playback_one_page() will think that the page needs to be restored
- ** in the database file. And if an IO error occurs while doing so,
- ** then corruption may follow.
- */
- pPg->flags |= PGHDR_NEED_SYNC;
-
- rc = write32bits(pPager->jfd, iOff, pPg->pgno);
- if( rc!=SQLITE_OK ) return rc;
- rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
- if( rc!=SQLITE_OK ) return rc;
- rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
- if( rc!=SQLITE_OK ) return rc;
-
- IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
- pPager->journalOff, pPager->pageSize));
- PAGER_INCR(sqlite3_pager_writej_count);
- PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
- PAGERID(pPager), pPg->pgno,
- ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
-
- pPager->journalOff += 8 + pPager->pageSize;
- pPager->nRec++;
- assert( pPager->pInJournal!=0 );
- rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
- testcase( rc==SQLITE_NOMEM );
- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
- rc |= addToSavepointBitvecs(pPager, pPg->pgno);
- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
- return rc;
-}
-
-/*
-** Mark a single data page as writeable. The page is written into the
-** main journal or sub-journal as required. If the page is written into
-** one of the journals, the corresponding bit is set in the
-** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs
-** of any open savepoints as appropriate.
-*/
-static int pager_write(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- int rc = SQLITE_OK;
-
- /* This routine is not called unless a write-transaction has already
- ** been started. The journal file may or may not be open at this point.
- ** It is never called in the ERROR state.
- */
- assert( pPager->eState==PAGER_WRITER_LOCKED
- || pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
- );
- assert( assert_pager_state(pPager) );
- assert( pPager->errCode==0 );
- assert( pPager->readOnly==0 );
- CHECK_PAGE(pPg);
-
- /* The journal file needs to be opened. Higher level routines have already
- ** obtained the necessary locks to begin the write-transaction, but the
- ** rollback journal might not yet be open. Open it now if this is the case.
- **
- ** This is done before calling sqlite3PcacheMakeDirty() on the page.
- ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
- ** an error might occur and the pager would end up in WRITER_LOCKED state
- ** with pages marked as dirty in the cache.
- */
- if( pPager->eState==PAGER_WRITER_LOCKED ){
- rc = pager_open_journal(pPager);
- if( rc!=SQLITE_OK ) return rc;
- }
- assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
- assert( assert_pager_state(pPager) );
-
- /* Mark the page that is about to be modified as dirty. */
- sqlite3PcacheMakeDirty(pPg);
-
- /* If a rollback journal is in use, them make sure the page that is about
- ** to change is in the rollback journal, or if the page is a new page off
- ** then end of the file, make sure it is marked as PGHDR_NEED_SYNC.
- */
- assert( (pPager->pInJournal!=0) == isOpen(pPager->jfd) );
- if( pPager->pInJournal!=0
- && sqlite3BitvecTestNotNull(pPager->pInJournal, pPg->pgno)==0
- ){
- assert( pagerUseWal(pPager)==0 );
- if( pPg->pgno<=pPager->dbOrigSize ){
- rc = pagerAddPageToRollbackJournal(pPg);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }else{
- if( pPager->eState!=PAGER_WRITER_DBMOD ){
- pPg->flags |= PGHDR_NEED_SYNC;
- }
- PAGERTRACE(("APPEND %d page %d needSync=%d\n",
- PAGERID(pPager), pPg->pgno,
- ((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
- }
- }
-
- /* The PGHDR_DIRTY bit is set above when the page was added to the dirty-list
- ** and before writing the page into the rollback journal. Wait until now,
- ** after the page has been successfully journalled, before setting the
- ** PGHDR_WRITEABLE bit that indicates that the page can be safely modified.
- */
- pPg->flags |= PGHDR_WRITEABLE;
-
- /* If the statement journal is open and the page is not in it,
- ** then write the page into the statement journal.
- */
- if( pPager->nSavepoint>0 ){
- rc = subjournalPageIfRequired(pPg);
- }
-
- /* Update the database size and return. */
- if( pPager->dbSize<pPg->pgno ){
- pPager->dbSize = pPg->pgno;
- }
- return rc;
-}
-
-/*
-** This is a variant of sqlite3PagerWrite() that runs when the sector size
-** is larger than the page size. SQLite makes the (reasonable) assumption that
-** all bytes of a sector are written together by hardware. Hence, all bytes of
-** a sector need to be journalled in case of a power loss in the middle of
-** a write.
-**
-** Usually, the sector size is less than or equal to the page size, in which
-** case pages can be individually written. This routine only runs in the
-** exceptional case where the page size is smaller than the sector size.
-*/
-static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
- int rc = SQLITE_OK; /* Return code */
- Pgno nPageCount; /* Total number of pages in database file */
- Pgno pg1; /* First page of the sector pPg is located on. */
- int nPage = 0; /* Number of pages starting at pg1 to journal */
- int ii; /* Loop counter */
- int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
- Pager *pPager = pPg->pPager; /* The pager that owns pPg */
- Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
-
- /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
- ** a journal header to be written between the pages journaled by
- ** this function.
- */
- assert( !MEMDB );
- assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
- pPager->doNotSpill |= SPILLFLAG_NOSYNC;
-
- /* This trick assumes that both the page-size and sector-size are
- ** an integer power of 2. It sets variable pg1 to the identifier
- ** of the first page of the sector pPg is located on.
- */
- pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
-
- nPageCount = pPager->dbSize;
- if( pPg->pgno>nPageCount ){
- nPage = (pPg->pgno - pg1)+1;
- }else if( (pg1+nPagePerSector-1)>nPageCount ){
- nPage = nPageCount+1-pg1;
- }else{
- nPage = nPagePerSector;
- }
- assert(nPage>0);
- assert(pg1<=pPg->pgno);
- assert((pg1+nPage)>pPg->pgno);
-
- for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
- Pgno pg = pg1+ii;
- PgHdr *pPage;
- if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
- if( pg!=PAGER_MJ_PGNO(pPager) ){
- rc = sqlite3PagerGet(pPager, pg, &pPage, 0);
- if( rc==SQLITE_OK ){
- rc = pager_write(pPage);
- if( pPage->flags&PGHDR_NEED_SYNC ){
- needSync = 1;
- }
- sqlite3PagerUnrefNotNull(pPage);
- }
- }
- }else if( (pPage = sqlite3PagerLookup(pPager, pg))!=0 ){
- if( pPage->flags&PGHDR_NEED_SYNC ){
- needSync = 1;
- }
- sqlite3PagerUnrefNotNull(pPage);
- }
- }
-
- /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
- ** starting at pg1, then it needs to be set for all of them. Because
- ** writing to any of these nPage pages may damage the others, the
- ** journal file must contain sync()ed copies of all of them
- ** before any of them can be written out to the database file.
- */
- if( rc==SQLITE_OK && needSync ){
- assert( !MEMDB );
- for(ii=0; ii<nPage; ii++){
- PgHdr *pPage = sqlite3PagerLookup(pPager, pg1+ii);
- if( pPage ){
- pPage->flags |= PGHDR_NEED_SYNC;
- sqlite3PagerUnrefNotNull(pPage);
- }
- }
- }
-
- assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
- pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
- return rc;
-}
-
-/*
-** Mark a data page as writeable. This routine must be called before
-** making changes to a page. The caller must check the return value
-** of this function and be careful not to change any page data unless
-** this routine returns SQLITE_OK.
-**
-** The difference between this function and pager_write() is that this
-** function also deals with the special case where 2 or more pages
-** fit on a single disk sector. In this case all co-resident pages
-** must have been written to the journal file before returning.
-**
-** If an error occurs, SQLITE_NOMEM or an IO error code is returned
-** as appropriate. Otherwise, SQLITE_OK.
-*/
-int sqlite3PagerWrite(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- assert( (pPg->flags & PGHDR_MMAP)==0 );
- assert( pPager->eState>=PAGER_WRITER_LOCKED );
- assert( assert_pager_state(pPager) );
- if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
- if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
- return SQLITE_OK;
- }else if( pPager->errCode ){
- return pPager->errCode;
- }else if( pPager->sectorSize > (u32)pPager->pageSize ){
- assert( pPager->tempFile==0 );
- return pagerWriteLargeSector(pPg);
- }else{
- return pager_write(pPg);
- }
-}
-
-/*
-** Return TRUE if the page given in the argument was previously passed
-** to sqlite3PagerWrite(). In other words, return TRUE if it is ok
-** to change the content of the page.
-*/
-#ifndef NDEBUG
-int sqlite3PagerIswriteable(DbPage *pPg){
- return pPg->flags & PGHDR_WRITEABLE;
-}
-#endif
-
-/*
-** A call to this routine tells the pager that it is not necessary to
-** write the information on page pPg back to the disk, even though
-** that page might be marked as dirty. This happens, for example, when
-** the page has been added as a leaf of the freelist and so its
-** content no longer matters.
-**
-** The overlying software layer calls this routine when all of the data
-** on the given page is unused. The pager marks the page as clean so
-** that it does not get written to disk.
-**
-** Tests show that this optimization can quadruple the speed of large
-** DELETE operations.
-**
-** This optimization cannot be used with a temp-file, as the page may
-** have been dirty at the start of the transaction. In that case, if
-** memory pressure forces page pPg out of the cache, the data does need
-** to be written out to disk so that it may be read back in if the
-** current transaction is rolled back.
-*/
-void sqlite3PagerDontWrite(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
- PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
- IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
- pPg->flags |= PGHDR_DONT_WRITE;
- pPg->flags &= ~PGHDR_WRITEABLE;
- testcase( pPg->flags & PGHDR_NEED_SYNC );
- pager_set_pagehash(pPg);
- }
-}
-
-/*
-** This routine is called to increment the value of the database file
-** change-counter, stored as a 4-byte big-endian integer starting at
-** byte offset 24 of the pager file. The secondary change counter at
-** 92 is also updated, as is the SQLite version number at offset 96.
-**
-** But this only happens if the pPager->changeCountDone flag is false.
-** To avoid excess churning of page 1, the update only happens once.
-** See also the pager_write_changecounter() routine that does an
-** unconditional update of the change counters.
-**
-** If the isDirectMode flag is zero, then this is done by calling
-** sqlite3PagerWrite() on page 1, then modifying the contents of the
-** page data. In this case the file will be updated when the current
-** transaction is committed.
-**
-** The isDirectMode flag may only be non-zero if the library was compiled
-** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case,
-** if isDirect is non-zero, then the database file is updated directly
-** by writing an updated version of page 1 using a call to the
-** sqlite3OsWrite() function.
-*/
-static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
- int rc = SQLITE_OK;
-
- assert( pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
- );
- assert( assert_pager_state(pPager) );
-
- /* Declare and initialize constant integer 'isDirect'. If the
- ** atomic-write optimization is enabled in this build, then isDirect
- ** is initialized to the value passed as the isDirectMode parameter
- ** to this function. Otherwise, it is always set to zero.
- **
- ** The idea is that if the atomic-write optimization is not
- ** enabled at compile time, the compiler can omit the tests of
- ** 'isDirect' below, as well as the block enclosed in the
- ** "if( isDirect )" condition.
- */
-#ifndef SQLITE_ENABLE_ATOMIC_WRITE
-# define DIRECT_MODE 0
- assert( isDirectMode==0 );
- UNUSED_PARAMETER(isDirectMode);
-#else
-# define DIRECT_MODE isDirectMode
-#endif
-
- if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
- PgHdr *pPgHdr; /* Reference to page 1 */
-
- assert( !pPager->tempFile && isOpen(pPager->fd) );
-
- /* Open page 1 of the file for writing. */
- rc = sqlite3PagerGet(pPager, 1, &pPgHdr, 0);
- assert( pPgHdr==0 || rc==SQLITE_OK );
-
- /* If page one was fetched successfully, and this function is not
- ** operating in direct-mode, make page 1 writable. When not in
- ** direct mode, page 1 is always held in cache and hence the PagerGet()
- ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
- */
- if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
- rc = sqlite3PagerWrite(pPgHdr);
- }
-
- if( rc==SQLITE_OK ){
- /* Actually do the update of the change counter */
- pager_write_changecounter(pPgHdr);
-
- /* If running in direct mode, write the contents of page 1 to the file. */
- if( DIRECT_MODE ){
- const void *zBuf;
- assert( pPager->dbFileSize>0 );
- CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM_BKPT, zBuf);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
- pPager->aStat[PAGER_STAT_WRITE]++;
- }
- if( rc==SQLITE_OK ){
- /* Update the pager's copy of the change-counter. Otherwise, the
- ** next time a read transaction is opened the cache will be
- ** flushed (as the change-counter values will not match). */
- const void *pCopy = (const void *)&((const char *)zBuf)[24];
- memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers));
- pPager->changeCountDone = 1;
- }
- }else{
- pPager->changeCountDone = 1;
- }
- }
-
- /* Release the page reference. */
- sqlite3PagerUnref(pPgHdr);
- }
- return rc;
-}
-
-/*
-** Sync the database file to disk. This is a no-op for in-memory databases
-** or pages with the Pager.noSync flag set.
-**
-** If successful, or if called on a pager for which it is a no-op, this
-** function returns SQLITE_OK. Otherwise, an IO error code is returned.
-*/
-int sqlite3PagerSync(Pager *pPager, const char *zMaster){
- int rc = SQLITE_OK;
- void *pArg = (void*)zMaster;
- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
- if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
- if( rc==SQLITE_OK && !pPager->noSync ){
- assert( !MEMDB );
- rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
- }
- return rc;
-}
-
-/*
-** This function may only be called while a write-transaction is active in
-** rollback. If the connection is in WAL mode, this call is a no-op.
-** Otherwise, if the connection does not already have an EXCLUSIVE lock on
-** the database file, an attempt is made to obtain one.
-**
-** If the EXCLUSIVE lock is already held or the attempt to obtain it is
-** successful, or the connection is in WAL mode, SQLITE_OK is returned.
-** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
-** returned.
-*/
-int sqlite3PagerExclusiveLock(Pager *pPager){
- int rc = pPager->errCode;
- assert( assert_pager_state(pPager) );
- if( rc==SQLITE_OK ){
- assert( pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
- || pPager->eState==PAGER_WRITER_LOCKED
- );
- assert( assert_pager_state(pPager) );
- if( 0==pagerUseWal(pPager) ){
- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
- }
- }
- return rc;
-}
-
-/*
-** Sync the database file for the pager pPager. zMaster points to the name
-** of a master journal file that should be written into the individual
-** journal file. zMaster may be NULL, which is interpreted as no master
-** journal (a single database transaction).
-**
-** This routine ensures that:
-**
-** * The database file change-counter is updated,
-** * the journal is synced (unless the atomic-write optimization is used),
-** * all dirty pages are written to the database file,
-** * the database file is truncated (if required), and
-** * the database file synced.
-**
-** The only thing that remains to commit the transaction is to finalize
-** (delete, truncate or zero the first part of) the journal file (or
-** delete the master journal file if specified).
-**
-** Note that if zMaster==NULL, this does not overwrite a previous value
-** passed to an sqlite3PagerCommitPhaseOne() call.
-**
-** If the final parameter - noSync - is true, then the database file itself
-** is not synced. The caller must call sqlite3PagerSync() directly to
-** sync the database file before calling CommitPhaseTwo() to delete the
-** journal file in this case.
-*/
-int sqlite3PagerCommitPhaseOne(
- Pager *pPager, /* Pager object */
- const char *zMaster, /* If not NULL, the master journal name */
- int noSync /* True to omit the xSync on the db file */
-){
- int rc = SQLITE_OK; /* Return code */
-
- assert( pPager->eState==PAGER_WRITER_LOCKED
- || pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
- || pPager->eState==PAGER_ERROR
- );
- assert( assert_pager_state(pPager) );
-
- /* If a prior error occurred, report that error again. */
- if( NEVER(pPager->errCode) ) return pPager->errCode;
-
- /* Provide the ability to easily simulate an I/O error during testing */
- if( sqlite3FaultSim(400) ) return SQLITE_IOERR;
-
- PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
- pPager->zFilename, zMaster, pPager->dbSize));
-
- /* If no database changes have been made, return early. */
- if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
-
- assert( MEMDB==0 || pPager->tempFile );
- assert( isOpen(pPager->fd) || pPager->tempFile );
- if( 0==pagerFlushOnCommit(pPager, 1) ){
- /* If this is an in-memory db, or no pages have been written to, or this
- ** function has already been called, it is mostly a no-op. However, any
- ** backup in progress needs to be restarted. */
- sqlite3BackupRestart(pPager->pBackup);
- }else{
- if( pagerUseWal(pPager) ){
- PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
- PgHdr *pPageOne = 0;
- if( pList==0 ){
- /* Must have at least one page for the WAL commit flag.
- ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
- rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0);
- pList = pPageOne;
- pList->pDirty = 0;
- }
- assert( rc==SQLITE_OK );
- if( ALWAYS(pList) ){
- rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
- }
- sqlite3PagerUnref(pPageOne);
- if( rc==SQLITE_OK ){
- sqlite3PcacheCleanAll(pPager->pPCache);
- }
- }else{
- /* The bBatch boolean is true if the batch-atomic-write commit method
- ** should be used. No rollback journal is created if batch-atomic-write
- ** is enabled.
- */
- sqlite3_file *fd = pPager->fd;
-#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- const int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
- && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
- && !pPager->noSync
- && sqlite3JournalIsInMemory(pPager->jfd);
-#else
-# define bBatch 0
-#endif
-
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
- /* The following block updates the change-counter. Exactly how it
- ** does this depends on whether or not the atomic-update optimization
- ** was enabled at compile time, and if this transaction meets the
- ** runtime criteria to use the operation:
- **
- ** * The file-system supports the atomic-write property for
- ** blocks of size page-size, and
- ** * This commit is not part of a multi-file transaction, and
- ** * Exactly one page has been modified and store in the journal file.
- **
- ** If the optimization was not enabled at compile time, then the
- ** pager_incr_changecounter() function is called to update the change
- ** counter in 'indirect-mode'. If the optimization is compiled in but
- ** is not applicable to this transaction, call sqlite3JournalCreate()
- ** to make sure the journal file has actually been created, then call
- ** pager_incr_changecounter() to update the change-counter in indirect
- ** mode.
- **
- ** Otherwise, if the optimization is both enabled and applicable,
- ** then call pager_incr_changecounter() to update the change-counter
- ** in 'direct' mode. In this case the journal file will never be
- ** created for this transaction.
- */
- if( bBatch==0 ){
- PgHdr *pPg;
- assert( isOpen(pPager->jfd)
- || pPager->journalMode==PAGER_JOURNALMODE_OFF
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
- );
- if( !zMaster && isOpen(pPager->jfd)
- && pPager->journalOff==jrnlBufferSize(pPager)
- && pPager->dbSize>=pPager->dbOrigSize
- && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
- ){
- /* Update the db file change counter via the direct-write method. The
- ** following call will modify the in-memory representation of page 1
- ** to include the updated change counter and then write page 1
- ** directly to the database file. Because of the atomic-write
- ** property of the host file-system, this is safe.
- */
- rc = pager_incr_changecounter(pPager, 1);
- }else{
- rc = sqlite3JournalCreate(pPager->jfd);
- if( rc==SQLITE_OK ){
- rc = pager_incr_changecounter(pPager, 0);
- }
- }
- }
-#else
-#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- if( zMaster ){
- rc = sqlite3JournalCreate(pPager->jfd);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- }
-#endif
- rc = pager_incr_changecounter(pPager, 0);
-#endif
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-
- /* Write the master journal name into the journal file. If a master
- ** journal file name has already been written to the journal file,
- ** or if zMaster is NULL (no master journal), then this call is a no-op.
- */
- rc = writeMasterJournal(pPager, zMaster);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-
- /* Sync the journal file and write all dirty pages to the database.
- ** If the atomic-update optimization is being used, this sync will not
- ** create the journal file or perform any real IO.
- **
- ** Because the change-counter page was just modified, unless the
- ** atomic-update optimization is used it is almost certain that the
- ** journal requires a sync here. However, in locking_mode=exclusive
- ** on a system under memory pressure it is just possible that this is
- ** not the case. In this case it is likely enough that the redundant
- ** xSync() call will be changed to a no-op by the OS anyhow.
- */
- rc = syncJournal(pPager, 0);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-
- if( bBatch ){
- /* The pager is now in DBMOD state. But regardless of what happens
- ** next, attempting to play the journal back into the database would
- ** be unsafe. Close it now to make sure that does not happen. */
- sqlite3OsClose(pPager->jfd);
- rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- }
- rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
- if( bBatch ){
- if( rc==SQLITE_OK ){
- rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
- }
- if( rc!=SQLITE_OK ){
- sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
- }
- }
-
- if( rc!=SQLITE_OK ){
- assert( rc!=SQLITE_IOERR_BLOCKED );
- goto commit_phase_one_exit;
- }
- sqlite3PcacheCleanAll(pPager->pPCache);
-
- /* If the file on disk is smaller than the database image, use
- ** pager_truncate to grow the file here. This can happen if the database
- ** image was extended as part of the current transaction and then the
- ** last page in the db image moved to the free-list. In this case the
- ** last page is never written out to disk, leaving the database file
- ** undersized. Fix this now if it is the case. */
- if( pPager->dbSize>pPager->dbFileSize ){
- Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
- assert( pPager->eState==PAGER_WRITER_DBMOD );
- rc = pager_truncate(pPager, nNew);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- }
-
- /* Finally, sync the database file. */
- if( !noSync ){
- rc = sqlite3PagerSync(pPager, zMaster);
- }
- IOTRACE(("DBSYNC %p\n", pPager))
- }
- }
-
-commit_phase_one_exit:
- if( rc==SQLITE_OK && !pagerUseWal(pPager) ){
- pPager->eState = PAGER_WRITER_FINISHED;
- }
- return rc;
-}
-
-
-/*
-** When this function is called, the database file has been completely
-** updated to reflect the changes made by the current transaction and
-** synced to disk. The journal file still exists in the file-system
-** though, and if a failure occurs at this point it will eventually
-** be used as a hot-journal and the current transaction rolled back.
-**
-** This function finalizes the journal file, either by deleting,
-** truncating or partially zeroing it, so that it cannot be used
-** for hot-journal rollback. Once this is done the transaction is
-** irrevocably committed.
-**
-** If an error occurs, an IO error code is returned and the pager
-** moves into the error state. Otherwise, SQLITE_OK is returned.
-*/
-int sqlite3PagerCommitPhaseTwo(Pager *pPager){
- int rc = SQLITE_OK; /* Return code */
-
- /* This routine should not be called if a prior error has occurred.
- ** But if (due to a coding error elsewhere in the system) it does get
- ** called, just return the same error code without doing anything. */
- if( NEVER(pPager->errCode) ) return pPager->errCode;
-
- assert( pPager->eState==PAGER_WRITER_LOCKED
- || pPager->eState==PAGER_WRITER_FINISHED
- || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
- );
- assert( assert_pager_state(pPager) );
-
- /* An optimization. If the database was not actually modified during
- ** this transaction, the pager is running in exclusive-mode and is
- ** using persistent journals, then this function is a no-op.
- **
- ** The start of the journal file currently contains a single journal
- ** header with the nRec field set to 0. If such a journal is used as
- ** a hot-journal during hot-journal rollback, 0 changes will be made
- ** to the database file. So there is no need to zero the journal
- ** header. Since the pager is in exclusive mode, there is no need
- ** to drop any locks either.
- */
- if( pPager->eState==PAGER_WRITER_LOCKED
- && pPager->exclusiveMode
- && pPager->journalMode==PAGER_JOURNALMODE_PERSIST
- ){
- assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
- pPager->eState = PAGER_READER;
- return SQLITE_OK;
- }
-
- PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
- pPager->iDataVersion++;
- rc = pager_end_transaction(pPager, pPager->setMaster, 1);
- return pager_error(pPager, rc);
-}
-
-/*
-** If a write transaction is open, then all changes made within the
-** transaction are reverted and the current write-transaction is closed.
-** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
-** state if an error occurs.
-**
-** If the pager is already in PAGER_ERROR state when this function is called,
-** it returns Pager.errCode immediately. No work is performed in this case.
-**
-** Otherwise, in rollback mode, this function performs two functions:
-**
-** 1) It rolls back the journal file, restoring all database file and
-** in-memory cache pages to the state they were in when the transaction
-** was opened, and
-**
-** 2) It finalizes the journal file, so that it is not used for hot
-** rollback at any point in the future.
-**
-** Finalization of the journal file (task 2) is only performed if the
-** rollback is successful.
-**
-** In WAL mode, all cache-entries containing data modified within the
-** current transaction are either expelled from the cache or reverted to
-** their pre-transaction state by re-reading data from the database or
-** WAL files. The WAL transaction is then closed.
-*/
-int sqlite3PagerRollback(Pager *pPager){
- int rc = SQLITE_OK; /* Return code */
- PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
-
- /* PagerRollback() is a no-op if called in READER or OPEN state. If
- ** the pager is already in the ERROR state, the rollback is not
- ** attempted here. Instead, the error code is returned to the caller.
- */
- assert( assert_pager_state(pPager) );
- if( pPager->eState==PAGER_ERROR ) return pPager->errCode;
- if( pPager->eState<=PAGER_READER ) return SQLITE_OK;
-
- if( pagerUseWal(pPager) ){
- int rc2;
- rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
- rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
- if( rc==SQLITE_OK ) rc = rc2;
- }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
- int eState = pPager->eState;
- rc = pager_end_transaction(pPager, 0, 0);
- if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
- /* This can happen using journal_mode=off. Move the pager to the error
- ** state to indicate that the contents of the cache may not be trusted.
- ** Any active readers will get SQLITE_ABORT.
- */
- pPager->errCode = SQLITE_ABORT;
- pPager->eState = PAGER_ERROR;
- setGetterMethod(pPager);
- return rc;
- }
- }else{
- rc = pager_playback(pPager, 0);
- }
-
- assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
- assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
- || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR
- || rc==SQLITE_CANTOPEN
- );
-
- /* If an error occurs during a ROLLBACK, we can no longer trust the pager
- ** cache. So call pager_error() on the way out to make any error persistent.
- */
- return pager_error(pPager, rc);
-}
-
-/*
-** Return TRUE if the database file is opened read-only. Return FALSE
-** if the database is (in theory) writable.
-*/
-u8 sqlite3PagerIsreadonly(Pager *pPager){
- return pPager->readOnly;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** Return the sum of the reference counts for all pages held by pPager.
-*/
-int sqlite3PagerRefcount(Pager *pPager){
- return sqlite3PcacheRefCount(pPager->pPCache);
-}
-#endif
-
-/*
-** Return the approximate number of bytes of memory currently
-** used by the pager and its associated cache.
-*/
-int sqlite3PagerMemUsed(Pager *pPager){
- int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
- + 5*sizeof(void*);
- return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
- + sqlite3MallocSize(pPager)
- + pPager->pageSize;
-}
-
-/*
-** Return the number of references to the specified page.
-*/
-int sqlite3PagerPageRefcount(DbPage *pPage){
- return sqlite3PcachePageRefcount(pPage);
-}
-
-#ifdef SQLITE_TEST
-/*
-** This routine is used for testing and analysis only.
-*/
-int *sqlite3PagerStats(Pager *pPager){
- static int a[11];
- a[0] = sqlite3PcacheRefCount(pPager->pPCache);
- a[1] = sqlite3PcachePagecount(pPager->pPCache);
- a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
- a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
- a[4] = pPager->eState;
- a[5] = pPager->errCode;
- a[6] = pPager->aStat[PAGER_STAT_HIT];
- a[7] = pPager->aStat[PAGER_STAT_MISS];
- a[8] = 0; /* Used to be pPager->nOvfl */
- a[9] = pPager->nRead;
- a[10] = pPager->aStat[PAGER_STAT_WRITE];
- return a;
-}
-#endif
-
-/*
-** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE,
-** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation
-** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because
-** it was added later.
-**
-** Before returning, *pnVal is incremented by the
-** current cache hit or miss count, according to the value of eStat. If the
-** reset parameter is non-zero, the cache hit or miss count is zeroed before
-** returning.
-*/
-void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
-
- assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
- || eStat==SQLITE_DBSTATUS_CACHE_MISS
- || eStat==SQLITE_DBSTATUS_CACHE_WRITE
- || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1
- );
-
- assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
- assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
- assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1
- && PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 );
-
- eStat -= SQLITE_DBSTATUS_CACHE_HIT;
- *pnVal += pPager->aStat[eStat];
- if( reset ){
- pPager->aStat[eStat] = 0;
- }
-}
-
-/*
-** Return true if this is an in-memory or temp-file backed pager.
-*/
-int sqlite3PagerIsMemdb(Pager *pPager){
- return pPager->tempFile;
-}
-
-/*
-** Check that there are at least nSavepoint savepoints open. If there are
-** currently less than nSavepoints open, then open one or more savepoints
-** to make up the difference. If the number of savepoints is already
-** equal to nSavepoint, then this function is a no-op.
-**
-** If a memory allocation fails, SQLITE_NOMEM is returned. If an error
-** occurs while opening the sub-journal file, then an IO error code is
-** returned. Otherwise, SQLITE_OK.
-*/
-static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){
- int rc = SQLITE_OK; /* Return code */
- int nCurrent = pPager->nSavepoint; /* Current number of savepoints */
- int ii; /* Iterator variable */
- PagerSavepoint *aNew; /* New Pager.aSavepoint array */
-
- assert( pPager->eState>=PAGER_WRITER_LOCKED );
- assert( assert_pager_state(pPager) );
- assert( nSavepoint>nCurrent && pPager->useJournal );
-
- /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
- ** if the allocation fails. Otherwise, zero the new portion in case a
- ** malloc failure occurs while populating it in the for(...) loop below.
- */
- aNew = (PagerSavepoint *)sqlite3Realloc(
- pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint
- );
- if( !aNew ){
- return SQLITE_NOMEM_BKPT;
- }
- memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint));
- pPager->aSavepoint = aNew;
-
- /* Populate the PagerSavepoint structures just allocated. */
- for(ii=nCurrent; ii<nSavepoint; ii++){
- aNew[ii].nOrig = pPager->dbSize;
- if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
- aNew[ii].iOffset = pPager->journalOff;
- }else{
- aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager);
- }
- aNew[ii].iSubRec = pPager->nSubRec;
- aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
- if( !aNew[ii].pInSavepoint ){
- return SQLITE_NOMEM_BKPT;
- }
- if( pagerUseWal(pPager) ){
- sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData);
- }
- pPager->nSavepoint = ii+1;
- }
- assert( pPager->nSavepoint==nSavepoint );
- assertTruncateConstraint(pPager);
- return rc;
-}
-int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
- assert( pPager->eState>=PAGER_WRITER_LOCKED );
- assert( assert_pager_state(pPager) );
-
- if( nSavepoint>pPager->nSavepoint && pPager->useJournal ){
- return pagerOpenSavepoint(pPager, nSavepoint);
- }else{
- return SQLITE_OK;
- }
-}
-
-
-/*
-** This function is called to rollback or release (commit) a savepoint.
-** The savepoint to release or rollback need not be the most recently
-** created savepoint.
-**
-** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
-** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with
-** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
-** that have occurred since the specified savepoint was created.
-**
-** The savepoint to rollback or release is identified by parameter
-** iSavepoint. A value of 0 means to operate on the outermost savepoint
-** (the first created). A value of (Pager.nSavepoint-1) means operate
-** on the most recently created savepoint. If iSavepoint is greater than
-** (Pager.nSavepoint-1), then this function is a no-op.
-**
-** If a negative value is passed to this function, then the current
-** transaction is rolled back. This is different to calling
-** sqlite3PagerRollback() because this function does not terminate
-** the transaction or unlock the database, it just restores the
-** contents of the database to its original state.
-**
-** In any case, all savepoints with an index greater than iSavepoint
-** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
-** then savepoint iSavepoint is also destroyed.
-**
-** This function may return SQLITE_NOMEM if a memory allocation fails,
-** or an IO error code if an IO error occurs while rolling back a
-** savepoint. If no errors occur, SQLITE_OK is returned.
-*/
-int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
- int rc = pPager->errCode;
-
-#ifdef SQLITE_ENABLE_ZIPVFS
- if( op==SAVEPOINT_RELEASE ) rc = SQLITE_OK;
-#endif
-
- assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
- assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );
-
- if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){
- int ii; /* Iterator variable */
- int nNew; /* Number of remaining savepoints after this op. */
-
- /* Figure out how many savepoints will still be active after this
- ** operation. Store this value in nNew. Then free resources associated
- ** with any savepoints that are destroyed by this operation.
- */
- nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
- for(ii=nNew; ii<pPager->nSavepoint; ii++){
- sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
- }
- pPager->nSavepoint = nNew;
-
- /* If this is a release of the outermost savepoint, truncate
- ** the sub-journal to zero bytes in size. */
- if( op==SAVEPOINT_RELEASE ){
- if( nNew==0 && isOpen(pPager->sjfd) ){
- /* Only truncate if it is an in-memory sub-journal. */
- if( sqlite3JournalIsInMemory(pPager->sjfd) ){
- rc = sqlite3OsTruncate(pPager->sjfd, 0);
- assert( rc==SQLITE_OK );
- }
- pPager->nSubRec = 0;
- }
- }
- /* Else this is a rollback operation, playback the specified savepoint.
- ** If this is a temp-file, it is possible that the journal file has
- ** not yet been opened. In this case there have been no changes to
- ** the database file, so the playback operation can be skipped.
- */
- else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){
- PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
- rc = pagerPlaybackSavepoint(pPager, pSavepoint);
- assert(rc!=SQLITE_DONE);
- }
-
-#ifdef SQLITE_ENABLE_ZIPVFS
- /* If the cache has been modified but the savepoint cannot be rolled
- ** back journal_mode=off, put the pager in the error state. This way,
- ** if the VFS used by this pager includes ZipVFS, the entire transaction
- ** can be rolled back at the ZipVFS level. */
- else if(
- pPager->journalMode==PAGER_JOURNALMODE_OFF
- && pPager->eState>=PAGER_WRITER_CACHEMOD
- ){
- pPager->errCode = SQLITE_ABORT;
- pPager->eState = PAGER_ERROR;
- setGetterMethod(pPager);
- }
-#endif
- }
-
- return rc;
-}
-
-/*
-** Return the full pathname of the database file.
-**
-** Except, if the pager is in-memory only, then return an empty string if
-** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when
-** used to report the filename to the user, for compatibility with legacy
-** behavior. But when the Btree needs to know the filename for matching to
-** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
-** participate in shared-cache.
-*/
-const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
- return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
-}
-
-/*
-** Return the VFS structure for the pager.
-*/
-sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
- return pPager->pVfs;
-}
-
-/*
-** Return the file handle for the database file associated
-** with the pager. This might return NULL if the file has
-** not yet been opened.
-*/
-sqlite3_file *sqlite3PagerFile(Pager *pPager){
- return pPager->fd;
-}
-
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
-/*
-** Reset the lock timeout for pager.
-*/
-void sqlite3PagerResetLockTimeout(Pager *pPager){
- int x = 0;
- sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
-}
-#endif
-
-/*
-** Return the file handle for the journal file (if it exists).
-** This will be either the rollback journal or the WAL file.
-*/
-sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
-#if SQLITE_OMIT_WAL
- return pPager->jfd;
-#else
- return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
-#endif
-}
-
-/*
-** Return the full pathname of the journal file.
-*/
-const char *sqlite3PagerJournalname(Pager *pPager){
- return pPager->zJournal;
-}
-
-#ifdef SQLITE_HAS_CODEC
-/*
-** Set or retrieve the codec for this pager
-*/
-void sqlite3PagerSetCodec(
- Pager *pPager,
- void *(*xCodec)(void*,void*,Pgno,int),
- void (*xCodecSizeChng)(void*,int,int),
- void (*xCodecFree)(void*),
- void *pCodec
-){
- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
- pPager->xCodec = pPager->memDb ? 0 : xCodec;
- pPager->xCodecSizeChng = xCodecSizeChng;
- pPager->xCodecFree = xCodecFree;
- pPager->pCodec = pCodec;
- setGetterMethod(pPager);
- pagerReportSize(pPager);
-}
-void *sqlite3PagerGetCodec(Pager *pPager){
- return pPager->pCodec;
-}
-
-/*
-** This function is called by the wal module when writing page content
-** into the log file.
-**
-** This function returns a pointer to a buffer containing the encrypted
-** page content. If a malloc fails, this function may return NULL.
-*/
-void *sqlite3PagerCodec(PgHdr *pPg){
- void *aData = 0;
- CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
- return aData;
-}
-
-/*
-** Return the current pager state
-*/
-int sqlite3PagerState(Pager *pPager){
- return pPager->eState;
-}
-#endif /* SQLITE_HAS_CODEC */
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
-/*
-** Move the page pPg to location pgno in the file.
-**
-** There must be no references to the page previously located at
-** pgno (which we call pPgOld) though that page is allowed to be
-** in cache. If the page previously located at pgno is not already
-** in the rollback journal, it is not put there by by this routine.
-**
-** References to the page pPg remain valid. Updating any
-** meta-data associated with pPg (i.e. data stored in the nExtra bytes
-** allocated along with the page) is the responsibility of the caller.
-**
-** A transaction must be active when this routine is called. It used to be
-** required that a statement transaction was not active, but this restriction
-** has been removed (CREATE INDEX needs to move a page when a statement
-** transaction is active).
-**
-** If the fourth argument, isCommit, is non-zero, then this page is being
-** moved as part of a database reorganization just before the transaction
-** is being committed. In this case, it is guaranteed that the database page
-** pPg refers to will not be written to again within this transaction.
-**
-** This function may return SQLITE_NOMEM or an IO error code if an error
-** occurs. Otherwise, it returns SQLITE_OK.
-*/
-int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
- PgHdr *pPgOld; /* The page being overwritten. */
- Pgno needSyncPgno = 0; /* Old value of pPg->pgno, if sync is required */
- int rc; /* Return code */
- Pgno origPgno; /* The original page number */
-
- assert( pPg->nRef>0 );
- assert( pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
- );
- assert( assert_pager_state(pPager) );
-
- /* In order to be able to rollback, an in-memory database must journal
- ** the page we are moving from.
- */
- assert( pPager->tempFile || !MEMDB );
- if( pPager->tempFile ){
- rc = sqlite3PagerWrite(pPg);
- if( rc ) return rc;
- }
-
- /* If the page being moved is dirty and has not been saved by the latest
- ** savepoint, then save the current contents of the page into the
- ** sub-journal now. This is required to handle the following scenario:
- **
- ** BEGIN;
- ** <journal page X, then modify it in memory>
- ** SAVEPOINT one;
- ** <Move page X to location Y>
- ** ROLLBACK TO one;
- **
- ** If page X were not written to the sub-journal here, it would not
- ** be possible to restore its contents when the "ROLLBACK TO one"
- ** statement were is processed.
- **
- ** subjournalPage() may need to allocate space to store pPg->pgno into
- ** one or more savepoint bitvecs. This is the reason this function
- ** may return SQLITE_NOMEM.
- */
- if( (pPg->flags & PGHDR_DIRTY)!=0
- && SQLITE_OK!=(rc = subjournalPageIfRequired(pPg))
- ){
- return rc;
- }
-
- PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n",
- PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
- IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
-
- /* If the journal needs to be sync()ed before page pPg->pgno can
- ** be written to, store pPg->pgno in local variable needSyncPgno.
- **
- ** If the isCommit flag is set, there is no need to remember that
- ** the journal needs to be sync()ed before database page pPg->pgno
- ** can be written to. The caller has already promised not to write to it.
- */
- if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
- needSyncPgno = pPg->pgno;
- assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
- pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize );
- assert( pPg->flags&PGHDR_DIRTY );
- }
-
- /* If the cache contains a page with page-number pgno, remove it
- ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for
- ** page pgno before the 'move' operation, it needs to be retained
- ** for the page moved there.
- */
- pPg->flags &= ~PGHDR_NEED_SYNC;
- pPgOld = sqlite3PagerLookup(pPager, pgno);
- assert( !pPgOld || pPgOld->nRef==1 );
- if( pPgOld ){
- pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
- if( pPager->tempFile ){
- /* Do not discard pages from an in-memory database since we might
- ** need to rollback later. Just move the page out of the way. */
- sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
- }else{
- sqlite3PcacheDrop(pPgOld);
- }
- }
-
- origPgno = pPg->pgno;
- sqlite3PcacheMove(pPg, pgno);
- sqlite3PcacheMakeDirty(pPg);
-
- /* For an in-memory database, make sure the original page continues
- ** to exist, in case the transaction needs to roll back. Use pPgOld
- ** as the original page since it has already been allocated.
- */
- if( pPager->tempFile && pPgOld ){
- sqlite3PcacheMove(pPgOld, origPgno);
- sqlite3PagerUnrefNotNull(pPgOld);
- }
-
- if( needSyncPgno ){
- /* If needSyncPgno is non-zero, then the journal file needs to be
- ** sync()ed before any data is written to database file page needSyncPgno.
- ** Currently, no such page exists in the page-cache and the
- ** "is journaled" bitvec flag has been set. This needs to be remedied by
- ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC
- ** flag.
- **
- ** If the attempt to load the page into the page-cache fails, (due
- ** to a malloc() or IO failure), clear the bit in the pInJournal[]
- ** array. Otherwise, if the page is loaded and written again in
- ** this transaction, it may be written to the database file before
- ** it is synced into the journal file. This way, it may end up in
- ** the journal file twice, but that is not a problem.
- */
- PgHdr *pPgHdr;
- rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr, 0);
- if( rc!=SQLITE_OK ){
- if( needSyncPgno<=pPager->dbOrigSize ){
- assert( pPager->pTmpSpace!=0 );
- sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace);
- }
- return rc;
- }
- pPgHdr->flags |= PGHDR_NEED_SYNC;
- sqlite3PcacheMakeDirty(pPgHdr);
- sqlite3PagerUnrefNotNull(pPgHdr);
- }
-
- return SQLITE_OK;
-}
-#endif
-
-/*
-** The page handle passed as the first argument refers to a dirty page
-** with a page number other than iNew. This function changes the page's
-** page number to iNew and sets the value of the PgHdr.flags field to
-** the value passed as the third parameter.
-*/
-void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){
- assert( pPg->pgno!=iNew );
- pPg->flags = flags;
- sqlite3PcacheMove(pPg, iNew);
-}
-
-/*
-** Return a pointer to the data for the specified page.
-*/
-void *sqlite3PagerGetData(DbPage *pPg){
- assert( pPg->nRef>0 || pPg->pPager->memDb );
- return pPg->pData;
-}
-
-/*
-** Return a pointer to the Pager.nExtra bytes of "extra" space
-** allocated along with the specified page.
-*/
-void *sqlite3PagerGetExtra(DbPage *pPg){
- return pPg->pExtra;
-}
-
-/*
-** Get/set the locking-mode for this pager. Parameter eMode must be one
-** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
-** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
-** the locking-mode is set to the value specified.
-**
-** The returned value is either PAGER_LOCKINGMODE_NORMAL or
-** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
-** locking-mode.
-*/
-int sqlite3PagerLockingMode(Pager *pPager, int eMode){
- assert( eMode==PAGER_LOCKINGMODE_QUERY
- || eMode==PAGER_LOCKINGMODE_NORMAL
- || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
- assert( PAGER_LOCKINGMODE_QUERY<0 );
- assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
- assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
- if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
- pPager->exclusiveMode = (u8)eMode;
- }
- return (int)pPager->exclusiveMode;
-}
-
-/*
-** Set the journal-mode for this pager. Parameter eMode must be one of:
-**
-** PAGER_JOURNALMODE_DELETE
-** PAGER_JOURNALMODE_TRUNCATE
-** PAGER_JOURNALMODE_PERSIST
-** PAGER_JOURNALMODE_OFF
-** PAGER_JOURNALMODE_MEMORY
-** PAGER_JOURNALMODE_WAL
-**
-** The journalmode is set to the value specified if the change is allowed.
-** The change may be disallowed for the following reasons:
-**
-** * An in-memory database can only have its journal_mode set to _OFF
-** or _MEMORY.
-**
-** * Temporary databases cannot have _WAL journalmode.
-**
-** The returned indicate the current (possibly updated) journal-mode.
-*/
-int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
- u8 eOld = pPager->journalMode; /* Prior journalmode */
-
-#ifdef SQLITE_DEBUG
- /* The print_pager_state() routine is intended to be used by the debugger
- ** only. We invoke it once here to suppress a compiler warning. */
- print_pager_state(pPager);
-#endif
-
-
- /* The eMode parameter is always valid */
- assert( eMode==PAGER_JOURNALMODE_DELETE
- || eMode==PAGER_JOURNALMODE_TRUNCATE
- || eMode==PAGER_JOURNALMODE_PERSIST
- || eMode==PAGER_JOURNALMODE_OFF
- || eMode==PAGER_JOURNALMODE_WAL
- || eMode==PAGER_JOURNALMODE_MEMORY );
-
- /* This routine is only called from the OP_JournalMode opcode, and
- ** the logic there will never allow a temporary file to be changed
- ** to WAL mode.
- */
- assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL );
-
- /* Do allow the journalmode of an in-memory database to be set to
- ** anything other than MEMORY or OFF
- */
- if( MEMDB ){
- assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF );
- if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){
- eMode = eOld;
- }
- }
-
- if( eMode!=eOld ){
-
- /* Change the journal mode. */
- assert( pPager->eState!=PAGER_ERROR );
- pPager->journalMode = (u8)eMode;
-
- /* When transistioning from TRUNCATE or PERSIST to any other journal
- ** mode except WAL, unless the pager is in locking_mode=exclusive mode,
- ** delete the journal file.
- */
- assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
- assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
- assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
- assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
- assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
- assert( (PAGER_JOURNALMODE_WAL & 5)==5 );
-
- assert( isOpen(pPager->fd) || pPager->exclusiveMode );
- if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
-
- /* In this case we would like to delete the journal file. If it is
- ** not possible, then that is not a problem. Deleting the journal file
- ** here is an optimization only.
- **
- ** Before deleting the journal file, obtain a RESERVED lock on the
- ** database file. This ensures that the journal file is not deleted
- ** while it is in use by some other client.
- */
- sqlite3OsClose(pPager->jfd);
- if( pPager->eLock>=RESERVED_LOCK ){
- sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
- }else{
- int rc = SQLITE_OK;
- int state = pPager->eState;
- assert( state==PAGER_OPEN || state==PAGER_READER );
- if( state==PAGER_OPEN ){
- rc = sqlite3PagerSharedLock(pPager);
- }
- if( pPager->eState==PAGER_READER ){
- assert( rc==SQLITE_OK );
- rc = pagerLockDb(pPager, RESERVED_LOCK);
- }
- if( rc==SQLITE_OK ){
- sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
- }
- if( rc==SQLITE_OK && state==PAGER_READER ){
- pagerUnlockDb(pPager, SHARED_LOCK);
- }else if( state==PAGER_OPEN ){
- pager_unlock(pPager);
- }
- assert( state==pPager->eState );
- }
- }else if( eMode==PAGER_JOURNALMODE_OFF ){
- sqlite3OsClose(pPager->jfd);
- }
- }
-
- /* Return the new journal mode */
- return (int)pPager->journalMode;
-}
-
-/*
-** Return the current journal mode.
-*/
-int sqlite3PagerGetJournalMode(Pager *pPager){
- return (int)pPager->journalMode;
-}
-
-/*
-** Return TRUE if the pager is in a state where it is OK to change the
-** journalmode. Journalmode changes can only happen when the database
-** is unmodified.
-*/
-int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
- assert( assert_pager_state(pPager) );
- if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
- if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
- return 1;
-}
-
-/*
-** Get/set the size-limit used for persistent journal files.
-**
-** Setting the size limit to -1 means no limit is enforced.
-** An attempt to set a limit smaller than -1 is a no-op.
-*/
-i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
- if( iLimit>=-1 ){
- pPager->journalSizeLimit = iLimit;
- sqlite3WalLimit(pPager->pWal, iLimit);
- }
- return pPager->journalSizeLimit;
-}
-
-/*
-** Return a pointer to the pPager->pBackup variable. The backup module
-** in backup.c maintains the content of this variable. This module
-** uses it opaquely as an argument to sqlite3BackupRestart() and
-** sqlite3BackupUpdate() only.
-*/
-sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
- return &pPager->pBackup;
-}
-
-#ifndef SQLITE_OMIT_VACUUM
-/*
-** Unless this is an in-memory or temporary database, clear the pager cache.
-*/
-void sqlite3PagerClearCache(Pager *pPager){
- assert( MEMDB==0 || pPager->tempFile );
- if( pPager->tempFile==0 ) pager_reset(pPager);
-}
-#endif
-
-
-#ifndef SQLITE_OMIT_WAL
-/*
-** This function is called when the user invokes "PRAGMA wal_checkpoint",
-** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
-** or wal_blocking_checkpoint() API functions.
-**
-** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
-*/
-int sqlite3PagerCheckpoint(
- Pager *pPager, /* Checkpoint on this pager */
- sqlite3 *db, /* Db handle used to check for interrupts */
- int eMode, /* Type of checkpoint */
- int *pnLog, /* OUT: Final number of frames in log */
- int *pnCkpt /* OUT: Final number of checkpointed frames */
-){
- int rc = SQLITE_OK;
- if( pPager->pWal ){
- rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
- (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
- pPager->pBusyHandlerArg,
- pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
- pnLog, pnCkpt
- );
- sqlite3PagerResetLockTimeout(pPager);
- }
- return rc;
-}
-
-int sqlite3PagerWalCallback(Pager *pPager){
- return sqlite3WalCallback(pPager->pWal);
-}
-
-/*
-** Return true if the underlying VFS for the given pager supports the
-** primitives necessary for write-ahead logging.
-*/
-int sqlite3PagerWalSupported(Pager *pPager){
- const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
- if( pPager->noLock ) return 0;
- return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
-}
-
-/*
-** Attempt to take an exclusive lock on the database file. If a PENDING lock
-** is obtained instead, immediately release it.
-*/
-static int pagerExclusiveLock(Pager *pPager){
- int rc; /* Return code */
-
- assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
- rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
- if( rc!=SQLITE_OK ){
- /* If the attempt to grab the exclusive lock failed, release the
- ** pending lock that may have been obtained instead. */
- pagerUnlockDb(pPager, SHARED_LOCK);
- }
-
- return rc;
-}
-
-/*
-** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
-** exclusive-locking mode when this function is called, take an EXCLUSIVE
-** lock on the database file and use heap-memory to store the wal-index
-** in. Otherwise, use the normal shared-memory.
-*/
-static int pagerOpenWal(Pager *pPager){
- int rc = SQLITE_OK;
-
- assert( pPager->pWal==0 && pPager->tempFile==0 );
- assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
-
- /* If the pager is already in exclusive-mode, the WAL module will use
- ** heap-memory for the wal-index instead of the VFS shared-memory
- ** implementation. Take the exclusive lock now, before opening the WAL
- ** file, to make sure this is safe.
- */
- if( pPager->exclusiveMode ){
- rc = pagerExclusiveLock(pPager);
- }
-
- /* Open the connection to the log file. If this operation fails,
- ** (e.g. due to malloc() failure), return an error code.
- */
- if( rc==SQLITE_OK ){
- rc = sqlite3WalOpen(pPager->pVfs,
- pPager->fd, pPager->zWal, pPager->exclusiveMode,
- pPager->journalSizeLimit, &pPager->pWal
- );
- }
- pagerFixMaplimit(pPager);
-
- return rc;
-}
-
-
-/*
-** The caller must be holding a SHARED lock on the database file to call
-** this function.
-**
-** If the pager passed as the first argument is open on a real database
-** file (not a temp file or an in-memory database), and the WAL file
-** is not already open, make an attempt to open it now. If successful,
-** return SQLITE_OK. If an error occurs or the VFS used by the pager does
-** not support the xShmXXX() methods, return an error code. *pbOpen is
-** not modified in either case.
-**
-** If the pager is open on a temp-file (or in-memory database), or if
-** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
-** without doing anything.
-*/
-int sqlite3PagerOpenWal(
- Pager *pPager, /* Pager object */
- int *pbOpen /* OUT: Set to true if call is a no-op */
-){
- int rc = SQLITE_OK; /* Return code */
-
- assert( assert_pager_state(pPager) );
- assert( pPager->eState==PAGER_OPEN || pbOpen );
- assert( pPager->eState==PAGER_READER || !pbOpen );
- assert( pbOpen==0 || *pbOpen==0 );
- assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );
-
- if( !pPager->tempFile && !pPager->pWal ){
- if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
-
- /* Close any rollback journal previously open */
- sqlite3OsClose(pPager->jfd);
-
- rc = pagerOpenWal(pPager);
- if( rc==SQLITE_OK ){
- pPager->journalMode = PAGER_JOURNALMODE_WAL;
- pPager->eState = PAGER_OPEN;
- }
- }else{
- *pbOpen = 1;
- }
-
- return rc;
-}
-
-/*
-** This function is called to close the connection to the log file prior
-** to switching from WAL to rollback mode.
-**
-** Before closing the log file, this function attempts to take an
-** EXCLUSIVE lock on the database file. If this cannot be obtained, an
-** error (SQLITE_BUSY) is returned and the log connection is not closed.
-** If successful, the EXCLUSIVE lock is not released before returning.
-*/
-int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
- int rc = SQLITE_OK;
-
- assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
-
- /* If the log file is not already open, but does exist in the file-system,
- ** it may need to be checkpointed before the connection can switch to
- ** rollback mode. Open it now so this can happen.
- */
- if( !pPager->pWal ){
- int logexists = 0;
- rc = pagerLockDb(pPager, SHARED_LOCK);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsAccess(
- pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
- );
- }
- if( rc==SQLITE_OK && logexists ){
- rc = pagerOpenWal(pPager);
- }
- }
-
- /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
- ** the database file, the log and log-summary files will be deleted.
- */
- if( rc==SQLITE_OK && pPager->pWal ){
- rc = pagerExclusiveLock(pPager);
- if( rc==SQLITE_OK ){
- rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags,
- pPager->pageSize, (u8*)pPager->pTmpSpace);
- pPager->pWal = 0;
- pagerFixMaplimit(pPager);
- if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
- }
- }
- return rc;
-}
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** If this is a WAL database, obtain a snapshot handle for the snapshot
-** currently open. Otherwise, return an error.
-*/
-int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){
- int rc = SQLITE_ERROR;
- if( pPager->pWal ){
- rc = sqlite3WalSnapshotGet(pPager->pWal, ppSnapshot);
- }
- return rc;
-}
-
-/*
-** If this is a WAL database, store a pointer to pSnapshot. Next time a
-** read transaction is opened, attempt to read from the snapshot it
-** identifies. If this is not a WAL database, return an error.
-*/
-int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){
- int rc = SQLITE_OK;
- if( pPager->pWal ){
- sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
- }else{
- rc = SQLITE_ERROR;
- }
- return rc;
-}
-
-/*
-** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this
-** is not a WAL database, return an error.
-*/
-int sqlite3PagerSnapshotRecover(Pager *pPager){
- int rc;
- if( pPager->pWal ){
- rc = sqlite3WalSnapshotRecover(pPager->pWal);
- }else{
- rc = SQLITE_ERROR;
- }
- return rc;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-#endif /* !SQLITE_OMIT_WAL */
-
-#ifdef SQLITE_ENABLE_ZIPVFS
-/*
-** A read-lock must be held on the pager when this function is called. If
-** the pager is in WAL mode and the WAL file currently contains one or more
-** frames, return the size in bytes of the page images stored within the
-** WAL frames. Otherwise, if this is not a WAL database or the WAL file
-** is empty, return 0.
-*/
-int sqlite3PagerWalFramesize(Pager *pPager){
- assert( pPager->eState>=PAGER_READER );
- return sqlite3WalFramesize(pPager->pWal);
-}
-#endif
-
-#endif /* SQLITE_OMIT_DISKIO */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/pager.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/pager.h
deleted file mode 100644
index 730e366fbb0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/pager.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 header file defines the interface that the sqlite page cache
-** subsystem. The page cache subsystem reads and writes a file a page
-** at a time and provides a journal for rollback.
-*/
-
-#ifndef SQLITE_PAGER_H
-#define SQLITE_PAGER_H
-
-/*
-** Default maximum size for persistent journal files. A negative
-** value means no limit. This value may be overridden using the
-** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit".
-*/
-#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
- #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1
-#endif
-
-/*
-** The type used to represent a page number. The first page in a file
-** is called page 1. 0 is used to represent "not a page".
-*/
-typedef u32 Pgno;
-
-/*
-** Each open file is managed by a separate instance of the "Pager" structure.
-*/
-typedef struct Pager Pager;
-
-/*
-** Handle type for pages.
-*/
-typedef struct PgHdr DbPage;
-
-/*
-** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
-** reserved for working around a windows/posix incompatibility). It is
-** used in the journal to signify that the remainder of the journal file
-** is devoted to storing a master journal name - there are no more pages to
-** roll back. See comments for function writeMasterJournal() in pager.c
-** for details.
-*/
-#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
-
-/*
-** Allowed values for the flags parameter to sqlite3PagerOpen().
-**
-** NOTE: These values must match the corresponding BTREE_ values in btree.h.
-*/
-#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
-#define PAGER_MEMORY 0x0002 /* In-memory database */
-
-/*
-** Valid values for the second argument to sqlite3PagerLockingMode().
-*/
-#define PAGER_LOCKINGMODE_QUERY -1
-#define PAGER_LOCKINGMODE_NORMAL 0
-#define PAGER_LOCKINGMODE_EXCLUSIVE 1
-
-/*
-** Numeric constants that encode the journalmode.
-**
-** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY)
-** are exposed in the API via the "PRAGMA journal_mode" command and
-** therefore cannot be changed without a compatibility break.
-*/
-#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
-#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
-#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
-#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
-#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
-#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
-#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
-
-/*
-** Flags that make up the mask passed to sqlite3PagerGet().
-*/
-#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */
-#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */
-
-/*
-** Flags for sqlite3PagerSetFlags()
-**
-** Value constraints (enforced via assert()):
-** PAGER_FULLFSYNC == SQLITE_FullFSync
-** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync
-** PAGER_CACHE_SPILL == SQLITE_CacheSpill
-*/
-#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
-#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
-#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */
-#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */
-#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */
-#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */
-#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */
-#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */
-#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */
-
-/*
-** The remainder of this file contains the declarations of the functions
-** that make up the Pager sub-system API. See source code comments for
-** a detailed description of each routine.
-*/
-
-/* Open and close a Pager connection. */
-int sqlite3PagerOpen(
- sqlite3_vfs*,
- Pager **ppPager,
- const char*,
- int,
- int,
- int,
- void(*)(DbPage*)
-);
-int sqlite3PagerClose(Pager *pPager, sqlite3*);
-int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
-
-/* Functions used to configure a Pager object. */
-void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
-int sqlite3PagerSetPagesize(Pager*, u32*, int);
-#ifdef SQLITE_HAS_CODEC
-void sqlite3PagerAlignReserve(Pager*,Pager*);
-#endif
-int sqlite3PagerMaxPageCount(Pager*, int);
-void sqlite3PagerSetCachesize(Pager*, int);
-int sqlite3PagerSetSpillsize(Pager*, int);
-void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
-void sqlite3PagerShrink(Pager*);
-void sqlite3PagerSetFlags(Pager*,unsigned);
-int sqlite3PagerLockingMode(Pager *, int);
-int sqlite3PagerSetJournalMode(Pager *, int);
-int sqlite3PagerGetJournalMode(Pager*);
-int sqlite3PagerOkToChangeJournalMode(Pager*);
-i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
-sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
-int sqlite3PagerFlush(Pager*);
-
-/* Functions used to obtain and release page references. */
-int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
-DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
-void sqlite3PagerRef(DbPage*);
-void sqlite3PagerUnref(DbPage*);
-void sqlite3PagerUnrefNotNull(DbPage*);
-void sqlite3PagerUnrefPageOne(DbPage*);
-
-/* Operations on page references. */
-int sqlite3PagerWrite(DbPage*);
-void sqlite3PagerDontWrite(DbPage*);
-int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
-int sqlite3PagerPageRefcount(DbPage*);
-void *sqlite3PagerGetData(DbPage *);
-void *sqlite3PagerGetExtra(DbPage *);
-
-/* Functions used to manage pager transactions and savepoints. */
-void sqlite3PagerPagecount(Pager*, int*);
-int sqlite3PagerBegin(Pager*, int exFlag, int);
-int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
-int sqlite3PagerExclusiveLock(Pager*);
-int sqlite3PagerSync(Pager *pPager, const char *zMaster);
-int sqlite3PagerCommitPhaseTwo(Pager*);
-int sqlite3PagerRollback(Pager*);
-int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
-int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
-int sqlite3PagerSharedLock(Pager *pPager);
-
-#ifndef SQLITE_OMIT_WAL
- int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
- int sqlite3PagerWalSupported(Pager *pPager);
- int sqlite3PagerWalCallback(Pager *pPager);
- int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
- int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
-# ifdef SQLITE_DIRECT_OVERFLOW_READ
- int sqlite3PagerUseWal(Pager *pPager, Pgno);
-# endif
-# ifdef SQLITE_ENABLE_SNAPSHOT
- int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
- int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
- int sqlite3PagerSnapshotRecover(Pager *pPager);
-# endif
-#else
-# define sqlite3PagerUseWal(x,y) 0
-#endif
-
-#ifdef SQLITE_ENABLE_ZIPVFS
- int sqlite3PagerWalFramesize(Pager *pPager);
-#endif
-
-/* Functions used to query pager state and configuration. */
-u8 sqlite3PagerIsreadonly(Pager*);
-u32 sqlite3PagerDataVersion(Pager*);
-#ifdef SQLITE_DEBUG
- int sqlite3PagerRefcount(Pager*);
-#endif
-int sqlite3PagerMemUsed(Pager*);
-const char *sqlite3PagerFilename(Pager*, int);
-sqlite3_vfs *sqlite3PagerVfs(Pager*);
-sqlite3_file *sqlite3PagerFile(Pager*);
-sqlite3_file *sqlite3PagerJrnlFile(Pager*);
-const char *sqlite3PagerJournalname(Pager*);
-void *sqlite3PagerTempSpace(Pager*);
-int sqlite3PagerIsMemdb(Pager*);
-void sqlite3PagerCacheStat(Pager *, int, int, int *);
-void sqlite3PagerClearCache(Pager*);
-int sqlite3SectorSize(sqlite3_file *);
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
-void sqlite3PagerResetLockTimeout(Pager *pPager);
-#else
-# define sqlite3PagerResetLockTimeout(X)
-#endif
-
-/* Functions used to truncate the database file. */
-void sqlite3PagerTruncateImage(Pager*,Pgno);
-
-void sqlite3PagerRekey(DbPage*, Pgno, u16);
-
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
-void *sqlite3PagerCodec(DbPage *);
-#endif
-
-/* Functions to support testing and debugging. */
-#if !defined(NDEBUG) || defined(SQLITE_TEST)
- Pgno sqlite3PagerPagenumber(DbPage*);
- int sqlite3PagerIswriteable(DbPage*);
-#endif
-#ifdef SQLITE_TEST
- int *sqlite3PagerStats(Pager*);
- void sqlite3PagerRefdump(Pager*);
- void disable_simulated_io_errors(void);
- void enable_simulated_io_errors(void);
-#else
-# define disable_simulated_io_errors()
-# define enable_simulated_io_errors()
-#endif
-
-#endif /* SQLITE_PAGER_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/parse.y b/chromium/third_party/sqlite/sqlite-src-3240000/src/parse.y
deleted file mode 100644
index a29a98d0e2f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/parse.y
+++ /dev/null
@@ -1,1572 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains SQLite's grammar for SQL. Process this file
-** using the lemon parser generator to generate C code that runs
-** the parser. Lemon will also generate a header file containing
-** numeric codes for all of the tokens.
-*/
-
-// All token codes are small integers with #defines that begin with "TK_"
-%token_prefix TK_
-
-// The type of the data attached to each token is Token. This is also the
-// default type for non-terminals.
-//
-%token_type {Token}
-%default_type {Token}
-
-// An extra argument to the constructor for the parser, which is available
-// to all actions.
-%extra_context {Parse *pParse}
-
-// This code runs whenever there is a syntax error
-//
-%syntax_error {
- UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */
- if( TOKEN.z[0] ){
- sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
- }else{
- sqlite3ErrorMsg(pParse, "incomplete input");
- }
-}
-%stack_overflow {
- sqlite3ErrorMsg(pParse, "parser stack overflow");
-}
-
-// The name of the generated procedure that implements the parser
-// is as follows:
-%name sqlite3Parser
-
-// The following text is included near the beginning of the C source
-// code file that implements the parser.
-//
-%include {
-#include "sqliteInt.h"
-
-/*
-** Disable all error recovery processing in the parser push-down
-** automaton.
-*/
-#define YYNOERRORRECOVERY 1
-
-/*
-** Make yytestcase() the same as testcase()
-*/
-#define yytestcase(X) testcase(X)
-
-/*
-** Indicate that sqlite3ParserFree() will never be called with a null
-** pointer.
-*/
-#define YYPARSEFREENEVERNULL 1
-
-/*
-** In the amalgamation, the parse.c file generated by lemon and the
-** tokenize.c file are concatenated. In that case, sqlite3RunParser()
-** has access to the the size of the yyParser object and so the parser
-** engine can be allocated from stack. In that case, only the
-** sqlite3ParserInit() and sqlite3ParserFinalize() routines are invoked
-** and the sqlite3ParserAlloc() and sqlite3ParserFree() routines can be
-** omitted.
-*/
-#ifdef SQLITE_AMALGAMATION
-# define sqlite3Parser_ENGINEALWAYSONSTACK 1
-#endif
-
-/*
-** Alternative datatype for the argument to the malloc() routine passed
-** into sqlite3ParserAlloc(). The default is size_t.
-*/
-#define YYMALLOCARGTYPE u64
-
-/*
-** An instance of the following structure describes the event of a
-** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
-** TK_DELETE, or TK_INSTEAD. If the event is of the form
-**
-** UPDATE ON (a,b,c)
-**
-** Then the "b" IdList records the list "a,b,c".
-*/
-struct TrigEvent { int a; IdList * b; };
-
-/*
-** Disable lookaside memory allocation for objects that might be
-** shared across database connections.
-*/
-static void disableLookaside(Parse *pParse){
- pParse->disableLookaside++;
- pParse->db->lookaside.bDisable++;
-}
-
-} // end %include
-
-// Input is a single SQL command
-input ::= cmdlist.
-cmdlist ::= cmdlist ecmd.
-cmdlist ::= ecmd.
-ecmd ::= SEMI.
-ecmd ::= cmdx SEMI.
-%ifndef SQLITE_OMIT_EXPLAIN
-ecmd ::= explain cmdx.
-explain ::= EXPLAIN. { pParse->explain = 1; }
-explain ::= EXPLAIN QUERY PLAN. { pParse->explain = 2; }
-%endif SQLITE_OMIT_EXPLAIN
-cmdx ::= cmd. { sqlite3FinishCoding(pParse); }
-
-///////////////////// Begin and end transactions. ////////////////////////////
-//
-
-cmd ::= BEGIN transtype(Y) trans_opt. {sqlite3BeginTransaction(pParse, Y);}
-trans_opt ::= .
-trans_opt ::= TRANSACTION.
-trans_opt ::= TRANSACTION nm.
-%type transtype {int}
-transtype(A) ::= . {A = TK_DEFERRED;}
-transtype(A) ::= DEFERRED(X). {A = @X; /*A-overwrites-X*/}
-transtype(A) ::= IMMEDIATE(X). {A = @X; /*A-overwrites-X*/}
-transtype(A) ::= EXCLUSIVE(X). {A = @X; /*A-overwrites-X*/}
-cmd ::= COMMIT|END(X) trans_opt. {sqlite3EndTransaction(pParse,@X);}
-cmd ::= ROLLBACK(X) trans_opt. {sqlite3EndTransaction(pParse,@X);}
-
-savepoint_opt ::= SAVEPOINT.
-savepoint_opt ::= .
-cmd ::= SAVEPOINT nm(X). {
- sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &X);
-}
-cmd ::= RELEASE savepoint_opt nm(X). {
- sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &X);
-}
-cmd ::= ROLLBACK trans_opt TO savepoint_opt nm(X). {
- sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X);
-}
-
-///////////////////// The CREATE TABLE statement ////////////////////////////
-//
-cmd ::= create_table create_table_args.
-create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). {
- sqlite3StartTable(pParse,&Y,&Z,T,0,0,E);
-}
-createkw(A) ::= CREATE(A). {disableLookaside(pParse);}
-
-%type ifnotexists {int}
-ifnotexists(A) ::= . {A = 0;}
-ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
-%type temp {int}
-%ifndef SQLITE_OMIT_TEMPDB
-temp(A) ::= TEMP. {A = 1;}
-%endif SQLITE_OMIT_TEMPDB
-temp(A) ::= . {A = 0;}
-create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_options(F). {
- sqlite3EndTable(pParse,&X,&E,F,0);
-}
-create_table_args ::= AS select(S). {
- sqlite3EndTable(pParse,0,0,0,S);
- sqlite3SelectDelete(pParse->db, S);
-}
-%type table_options {int}
-table_options(A) ::= . {A = 0;}
-table_options(A) ::= WITHOUT nm(X). {
- if( X.n==5 && sqlite3_strnicmp(X.z,"rowid",5)==0 ){
- A = TF_WithoutRowid | TF_NoVisibleRowid;
- }else{
- A = 0;
- sqlite3ErrorMsg(pParse, "unknown table option: %.*s", X.n, X.z);
- }
-}
-columnlist ::= columnlist COMMA columnname carglist.
-columnlist ::= columnname carglist.
-columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
-
-// Declare some tokens early in order to influence their values, to
-// improve performance and reduce the executable size. The goal here is
-// to get the "jump" operations in ISNULL through ESCAPE to have numeric
-// values that are early enough so that all jump operations are clustered
-// at the beginning, but also so that the comparison tokens NE through GE
-// are as large as possible so that they are near to FUNCTION, which is a
-// token synthesized by addopcodes.tcl.
-//
-%token ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST.
-%token CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL.
-%token OR AND NOT IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
-%token GT LE LT GE ESCAPE.
-
-// The following directive causes tokens ABORT, AFTER, ASC, etc. to
-// fallback to ID if they will not parse as their original value.
-// This obviates the need for the "id" nonterminal.
-//
-%fallback ID
- ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
- CONFLICT DATABASE DEFERRED DESC DETACH DO
- EACH END EXCLUSIVE EXPLAIN FAIL FOR
- IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
- QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
- ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
-%ifdef SQLITE_OMIT_COMPOUND_SELECT
- EXCEPT INTERSECT UNION
-%endif SQLITE_OMIT_COMPOUND_SELECT
- REINDEX RENAME CTIME_KW IF
- .
-%wildcard ANY.
-
-// Define operator precedence early so that this is the first occurrence
-// of the operator tokens in the grammer. Keeping the operators together
-// causes them to be assigned integer values that are close together,
-// which keeps parser tables smaller.
-//
-// The token values assigned to these symbols is determined by the order
-// in which lemon first sees them. It must be the case that ISNULL/NOTNULL,
-// NE/EQ, GT/LE, and GE/LT are separated by only a single value. See
-// the sqlite3ExprIfFalse() routine for additional information on this
-// constraint.
-//
-%left OR.
-%left AND.
-%right NOT.
-%left IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
-%left GT LE LT GE.
-%right ESCAPE.
-%left BITAND BITOR LSHIFT RSHIFT.
-%left PLUS MINUS.
-%left STAR SLASH REM.
-%left CONCAT.
-%left COLLATE.
-%right BITNOT.
-%nonassoc ON.
-
-// An IDENTIFIER can be a generic identifier, or one of several
-// keywords. Any non-standard keyword can also be an identifier.
-//
-%token_class id ID|INDEXED.
-
-
-// And "ids" is an identifer-or-string.
-//
-%token_class ids ID|STRING.
-
-// The name of a column or table can be any of the following:
-//
-%type nm {Token}
-nm(A) ::= id(A).
-nm(A) ::= STRING(A).
-nm(A) ::= JOIN_KW(A).
-
-// A typetoken is really zero or more tokens that form a type name such
-// as can be found after the column name in a CREATE TABLE statement.
-// Multiple tokens are concatenated to form the value of the typetoken.
-//
-%type typetoken {Token}
-typetoken(A) ::= . {A.n = 0; A.z = 0;}
-typetoken(A) ::= typename(A).
-typetoken(A) ::= typename(A) LP signed RP(Y). {
- A.n = (int)(&Y.z[Y.n] - A.z);
-}
-typetoken(A) ::= typename(A) LP signed COMMA signed RP(Y). {
- A.n = (int)(&Y.z[Y.n] - A.z);
-}
-%type typename {Token}
-typename(A) ::= ids(A).
-typename(A) ::= typename(A) ids(Y). {A.n=Y.n+(int)(Y.z-A.z);}
-signed ::= plus_num.
-signed ::= minus_num.
-
-// The scanpt non-terminal takes a value which is a pointer to the
-// input text just past the last token that has been shifted into
-// the parser. By surrounding some phrase in the grammar with two
-// scanpt non-terminals, we can capture the input text for that phrase.
-// For example:
-//
-// something ::= .... scanpt(A) phrase scanpt(Z).
-//
-// The text that is parsed as "phrase" is a string starting at A
-// and containing (int)(Z-A) characters. There might be some extra
-// whitespace on either end of the text, but that can be removed in
-// post-processing, if needed.
-//
-%type scanpt {const char*}
-scanpt(A) ::= . {
- assert( yyLookahead!=YYNOCODE );
- A = yyLookaheadToken.z;
-}
-
-// "carglist" is a list of additional constraints that come after the
-// column name and column type in a CREATE TABLE statement.
-//
-carglist ::= carglist ccons.
-carglist ::= .
-ccons ::= CONSTRAINT nm(X). {pParse->constraintName = X;}
-ccons ::= DEFAULT scanpt(A) term(X) scanpt(Z).
- {sqlite3AddDefaultValue(pParse,X,A,Z);}
-ccons ::= DEFAULT LP(A) expr(X) RP(Z).
- {sqlite3AddDefaultValue(pParse,X,A.z+1,Z.z);}
-ccons ::= DEFAULT PLUS(A) term(X) scanpt(Z).
- {sqlite3AddDefaultValue(pParse,X,A.z,Z);}
-ccons ::= DEFAULT MINUS(A) term(X) scanpt(Z). {
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, X, 0);
- sqlite3AddDefaultValue(pParse,p,A.z,Z);
-}
-ccons ::= DEFAULT scanpt id(X). {
- Expr *p = tokenExpr(pParse, TK_STRING, X);
- if( p ){
- sqlite3ExprIdToTrueFalse(p);
- testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) );
- }
- sqlite3AddDefaultValue(pParse,p,X.z,X.z+X.n);
-}
-
-// In addition to the type name, we also care about the primary key and
-// UNIQUE constraints.
-//
-ccons ::= NULL onconf.
-ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);}
-ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I).
- {sqlite3AddPrimaryKey(pParse,0,R,I,Z);}
-ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0,
- SQLITE_IDXTYPE_UNIQUE);}
-ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);}
-ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R).
- {sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
-ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);}
-ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);}
-
-// The optional AUTOINCREMENT keyword
-%type autoinc {int}
-autoinc(X) ::= . {X = 0;}
-autoinc(X) ::= AUTOINCR. {X = 1;}
-
-// The next group of rules parses the arguments to a REFERENCES clause
-// that determine if the referential integrity checking is deferred or
-// or immediate and which determine what action to take if a ref-integ
-// check fails.
-//
-%type refargs {int}
-refargs(A) ::= . { A = OE_None*0x0101; /* EV: R-19803-45884 */}
-refargs(A) ::= refargs(A) refarg(Y). { A = (A & ~Y.mask) | Y.value; }
-%type refarg {struct {int value; int mask;}}
-refarg(A) ::= MATCH nm. { A.value = 0; A.mask = 0x000000; }
-refarg(A) ::= ON INSERT refact. { A.value = 0; A.mask = 0x000000; }
-refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; }
-refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; }
-%type refact {int}
-refact(A) ::= SET NULL. { A = OE_SetNull; /* EV: R-33326-45252 */}
-refact(A) ::= SET DEFAULT. { A = OE_SetDflt; /* EV: R-33326-45252 */}
-refact(A) ::= CASCADE. { A = OE_Cascade; /* EV: R-33326-45252 */}
-refact(A) ::= RESTRICT. { A = OE_Restrict; /* EV: R-33326-45252 */}
-refact(A) ::= NO ACTION. { A = OE_None; /* EV: R-33326-45252 */}
-%type defer_subclause {int}
-defer_subclause(A) ::= NOT DEFERRABLE init_deferred_pred_opt. {A = 0;}
-defer_subclause(A) ::= DEFERRABLE init_deferred_pred_opt(X). {A = X;}
-%type init_deferred_pred_opt {int}
-init_deferred_pred_opt(A) ::= . {A = 0;}
-init_deferred_pred_opt(A) ::= INITIALLY DEFERRED. {A = 1;}
-init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE. {A = 0;}
-
-conslist_opt(A) ::= . {A.n = 0; A.z = 0;}
-conslist_opt(A) ::= COMMA(A) conslist.
-conslist ::= conslist tconscomma tcons.
-conslist ::= tcons.
-tconscomma ::= COMMA. {pParse->constraintName.n = 0;}
-tconscomma ::= .
-tcons ::= CONSTRAINT nm(X). {pParse->constraintName = X;}
-tcons ::= PRIMARY KEY LP sortlist(X) autoinc(I) RP onconf(R).
- {sqlite3AddPrimaryKey(pParse,X,R,I,0);}
-tcons ::= UNIQUE LP sortlist(X) RP onconf(R).
- {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0,
- SQLITE_IDXTYPE_UNIQUE);}
-tcons ::= CHECK LP expr(E) RP onconf.
- {sqlite3AddCheckConstraint(pParse,E);}
-tcons ::= FOREIGN KEY LP eidlist(FA) RP
- REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
- sqlite3CreateForeignKey(pParse, FA, &T, TA, R);
- sqlite3DeferForeignKey(pParse, D);
-}
-%type defer_subclause_opt {int}
-defer_subclause_opt(A) ::= . {A = 0;}
-defer_subclause_opt(A) ::= defer_subclause(A).
-
-// The following is a non-standard extension that allows us to declare the
-// default behavior when there is a constraint conflict.
-//
-%type onconf {int}
-%type orconf {int}
-%type resolvetype {int}
-onconf(A) ::= . {A = OE_Default;}
-onconf(A) ::= ON CONFLICT resolvetype(X). {A = X;}
-orconf(A) ::= . {A = OE_Default;}
-orconf(A) ::= OR resolvetype(X). {A = X;}
-resolvetype(A) ::= raisetype(A).
-resolvetype(A) ::= IGNORE. {A = OE_Ignore;}
-resolvetype(A) ::= REPLACE. {A = OE_Replace;}
-
-////////////////////////// The DROP TABLE /////////////////////////////////////
-//
-cmd ::= DROP TABLE ifexists(E) fullname(X). {
- sqlite3DropTable(pParse, X, 0, E);
-}
-%type ifexists {int}
-ifexists(A) ::= IF EXISTS. {A = 1;}
-ifexists(A) ::= . {A = 0;}
-
-///////////////////// The CREATE VIEW statement /////////////////////////////
-//
-%ifndef SQLITE_OMIT_VIEW
-cmd ::= createkw(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) eidlist_opt(C)
- AS select(S). {
- sqlite3CreateView(pParse, &X, &Y, &Z, C, S, T, E);
-}
-cmd ::= DROP VIEW ifexists(E) fullname(X). {
- sqlite3DropTable(pParse, X, 1, E);
-}
-%endif SQLITE_OMIT_VIEW
-
-//////////////////////// The SELECT statement /////////////////////////////////
-//
-cmd ::= select(X). {
- SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
- sqlite3Select(pParse, X, &dest);
- sqlite3SelectDelete(pParse->db, X);
-}
-
-%type select {Select*}
-%destructor select {sqlite3SelectDelete(pParse->db, $$);}
-%type selectnowith {Select*}
-%destructor selectnowith {sqlite3SelectDelete(pParse->db, $$);}
-%type oneselect {Select*}
-%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
-
-%include {
- /*
- ** For a compound SELECT statement, make sure p->pPrior->pNext==p for
- ** all elements in the list. And make sure list length does not exceed
- ** SQLITE_LIMIT_COMPOUND_SELECT.
- */
- static void parserDoubleLinkSelect(Parse *pParse, Select *p){
- if( p->pPrior ){
- Select *pNext = 0, *pLoop;
- int mxSelect, cnt = 0;
- for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
- pLoop->pNext = pNext;
- pLoop->selFlags |= SF_Compound;
- }
- if( (p->selFlags & SF_MultiValue)==0 &&
- (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
- cnt>mxSelect
- ){
- sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
- }
- }
- }
-}
-
-%ifndef SQLITE_OMIT_CTE
-select(A) ::= WITH wqlist(W) selectnowith(X). {
- Select *p = X;
- if( p ){
- p->pWith = W;
- parserDoubleLinkSelect(pParse, p);
- }else{
- sqlite3WithDelete(pParse->db, W);
- }
- A = p;
-}
-select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {
- Select *p = X;
- if( p ){
- p->pWith = W;
- parserDoubleLinkSelect(pParse, p);
- }else{
- sqlite3WithDelete(pParse->db, W);
- }
- A = p;
-}
-%endif /* SQLITE_OMIT_CTE */
-select(A) ::= selectnowith(X). {
- Select *p = X;
- if( p ){
- parserDoubleLinkSelect(pParse, p);
- }
- A = p; /*A-overwrites-X*/
-}
-
-selectnowith(A) ::= oneselect(A).
-%ifndef SQLITE_OMIT_COMPOUND_SELECT
-selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). {
- Select *pRhs = Z;
- Select *pLhs = A;
- if( pRhs && pRhs->pPrior ){
- SrcList *pFrom;
- Token x;
- x.n = 0;
- parserDoubleLinkSelect(pParse, pRhs);
- pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
- pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
- }
- if( pRhs ){
- pRhs->op = (u8)Y;
- pRhs->pPrior = pLhs;
- if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
- pRhs->selFlags &= ~SF_MultiValue;
- if( Y!=TK_ALL ) pParse->hasCompound = 1;
- }else{
- sqlite3SelectDelete(pParse->db, pLhs);
- }
- A = pRhs;
-}
-%type multiselect_op {int}
-multiselect_op(A) ::= UNION(OP). {A = @OP; /*A-overwrites-OP*/}
-multiselect_op(A) ::= UNION ALL. {A = TK_ALL;}
-multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP; /*A-overwrites-OP*/}
-%endif SQLITE_OMIT_COMPOUND_SELECT
-oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
- groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
-#if SELECTTRACE_ENABLED
- Token s = S; /*A-overwrites-S*/
-#endif
- A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L);
-#if SELECTTRACE_ENABLED
- /* Populate the Select.zSelName[] string that is used to help with
- ** query planner debugging, to differentiate between multiple Select
- ** objects in a complex query.
- **
- ** If the SELECT keyword is immediately followed by a C-style comment
- ** then extract the first few alphanumeric characters from within that
- ** comment to be the zSelName value. Otherwise, the label is #N where
- ** is an integer that is incremented with each SELECT statement seen.
- */
- if( A!=0 ){
- const char *z = s.z+6;
- int i;
- sqlite3_snprintf(sizeof(A->zSelName), A->zSelName,"#%d",++pParse->nSelect);
- while( z[0]==' ' ) z++;
- if( z[0]=='/' && z[1]=='*' ){
- z += 2;
- while( z[0]==' ' ) z++;
- for(i=0; sqlite3Isalnum(z[i]); i++){}
- sqlite3_snprintf(sizeof(A->zSelName), A->zSelName, "%.*s", i, z);
- }
- }
-#endif /* SELECTRACE_ENABLED */
-}
-oneselect(A) ::= values(A).
-
-%type values {Select*}
-%destructor values {sqlite3SelectDelete(pParse->db, $$);}
-values(A) ::= VALUES LP nexprlist(X) RP. {
- A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0);
-}
-values(A) ::= values(A) COMMA LP exprlist(Y) RP. {
- Select *pRight, *pLeft = A;
- pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0);
- if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
- if( pRight ){
- pRight->op = TK_ALL;
- pRight->pPrior = pLeft;
- A = pRight;
- }else{
- A = pLeft;
- }
-}
-
-// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
-// present and false (0) if it is not.
-//
-%type distinct {int}
-distinct(A) ::= DISTINCT. {A = SF_Distinct;}
-distinct(A) ::= ALL. {A = SF_All;}
-distinct(A) ::= . {A = 0;}
-
-// selcollist is a list of expressions that are to become the return
-// values of the SELECT statement. The "*" in statements like
-// "SELECT * FROM ..." is encoded as a special expression with an
-// opcode of TK_ASTERISK.
-//
-%type selcollist {ExprList*}
-%destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);}
-%type sclp {ExprList*}
-%destructor sclp {sqlite3ExprListDelete(pParse->db, $$);}
-sclp(A) ::= selcollist(A) COMMA.
-sclp(A) ::= . {A = 0;}
-selcollist(A) ::= sclp(A) scanpt(B) expr(X) scanpt(Z) as(Y). {
- A = sqlite3ExprListAppend(pParse, A, X);
- if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1);
- sqlite3ExprListSetSpan(pParse,A,B,Z);
-}
-selcollist(A) ::= sclp(A) scanpt STAR. {
- Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
- A = sqlite3ExprListAppend(pParse, A, p);
-}
-selcollist(A) ::= sclp(A) scanpt nm(X) DOT STAR. {
- Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
- Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
- Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- A = sqlite3ExprListAppend(pParse,A, pDot);
-}
-
-// An option "AS <id>" phrase that can follow one of the expressions that
-// define the result set, or one of the tables in the FROM clause.
-//
-%type as {Token}
-as(X) ::= AS nm(Y). {X = Y;}
-as(X) ::= ids(X).
-as(X) ::= . {X.n = 0; X.z = 0;}
-
-
-%type seltablist {SrcList*}
-%destructor seltablist {sqlite3SrcListDelete(pParse->db, $$);}
-%type stl_prefix {SrcList*}
-%destructor stl_prefix {sqlite3SrcListDelete(pParse->db, $$);}
-%type from {SrcList*}
-%destructor from {sqlite3SrcListDelete(pParse->db, $$);}
-
-// A complete FROM clause.
-//
-from(A) ::= . {A = sqlite3DbMallocZero(pParse->db, sizeof(*A));}
-from(A) ::= FROM seltablist(X). {
- A = X;
- sqlite3SrcListShiftJoinType(A);
-}
-
-// "seltablist" is a "Select Table List" - the content of the FROM clause
-// in a SELECT statement. "stl_prefix" is a prefix of this list.
-//
-stl_prefix(A) ::= seltablist(A) joinop(Y). {
- if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].fg.jointype = (u8)Y;
-}
-stl_prefix(A) ::= . {A = 0;}
-seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) as(Z) indexed_opt(I)
- on_opt(N) using_opt(U). {
- A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U);
- sqlite3SrcListIndexedBy(pParse, A, &I);
-}
-seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
- on_opt(N) using_opt(U). {
- A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U);
- sqlite3SrcListFuncArgs(pParse, A, E);
-}
-%ifndef SQLITE_OMIT_SUBQUERY
- seltablist(A) ::= stl_prefix(A) LP select(S) RP
- as(Z) on_opt(N) using_opt(U). {
- A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,N,U);
- }
- seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP
- as(Z) on_opt(N) using_opt(U). {
- if( A==0 && Z.n==0 && N==0 && U==0 ){
- A = F;
- }else if( F->nSrc==1 ){
- A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,N,U);
- if( A ){
- struct SrcList_item *pNew = &A->a[A->nSrc-1];
- struct SrcList_item *pOld = F->a;
- pNew->zName = pOld->zName;
- pNew->zDatabase = pOld->zDatabase;
- pNew->pSelect = pOld->pSelect;
- pOld->zName = pOld->zDatabase = 0;
- pOld->pSelect = 0;
- }
- sqlite3SrcListDelete(pParse->db, F);
- }else{
- Select *pSubquery;
- sqlite3SrcListShiftJoinType(F);
- pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0);
- A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,N,U);
- }
- }
-%endif SQLITE_OMIT_SUBQUERY
-
-%type dbnm {Token}
-dbnm(A) ::= . {A.z=0; A.n=0;}
-dbnm(A) ::= DOT nm(X). {A = X;}
-
-%type fullname {SrcList*}
-%destructor fullname {sqlite3SrcListDelete(pParse->db, $$);}
-fullname(A) ::= nm(X).
- {A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/}
-fullname(A) ::= nm(X) DOT nm(Y).
- {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/}
-
-%type xfullname {SrcList*}
-%destructor xfullname {sqlite3SrcListDelete(pParse->db, $$);}
-xfullname(A) ::= nm(X).
- {A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/}
-xfullname(A) ::= nm(X) DOT nm(Y).
- {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/}
-xfullname(A) ::= nm(X) DOT nm(Y) AS nm(Z). {
- A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/
- if( A ) A->a[0].zAlias = sqlite3NameFromToken(pParse->db, &Z);
-}
-xfullname(A) ::= nm(X) AS nm(Z). {
- A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/
- if( A ) A->a[0].zAlias = sqlite3NameFromToken(pParse->db, &Z);
-}
-
-%type joinop {int}
-joinop(X) ::= COMMA|JOIN. { X = JT_INNER; }
-joinop(X) ::= JOIN_KW(A) JOIN.
- {X = sqlite3JoinType(pParse,&A,0,0); /*X-overwrites-A*/}
-joinop(X) ::= JOIN_KW(A) nm(B) JOIN.
- {X = sqlite3JoinType(pParse,&A,&B,0); /*X-overwrites-A*/}
-joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
- {X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
-
-// There is a parsing abiguity in an upsert statement that uses a
-// SELECT on the RHS of a the INSERT:
-//
-// INSERT INTO tab SELECT * FROM aaa JOIN bbb ON CONFLICT ...
-// here ----^^
-//
-// When the ON token is encountered, the parser does not know if it is
-// the beginning of an ON CONFLICT clause, or the beginning of an ON
-// clause associated with the JOIN. The conflict is resolved in favor
-// of the JOIN. If an ON CONFLICT clause is intended, insert a dummy
-// WHERE clause in between, like this:
-//
-// INSERT INTO tab SELECT * FROM aaa JOIN bbb WHERE true ON CONFLICT ...
-//
-// The [AND] and [OR] precedence marks in the rules for on_opt cause the
-// ON in this context to always be interpreted as belonging to the JOIN.
-//
-%type on_opt {Expr*}
-%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
-on_opt(N) ::= ON expr(E). {N = E;}
-on_opt(N) ::= . [OR] {N = 0;}
-
-// Note that this block abuses the Token type just a little. If there is
-// no "INDEXED BY" clause, the returned token is empty (z==0 && n==0). If
-// there is an INDEXED BY clause, then the token is populated as per normal,
-// with z pointing to the token data and n containing the number of bytes
-// in the token.
-//
-// If there is a "NOT INDEXED" clause, then (z==0 && n==1), which is
-// normally illegal. The sqlite3SrcListIndexedBy() function
-// recognizes and interprets this as a special case.
-//
-%type indexed_opt {Token}
-indexed_opt(A) ::= . {A.z=0; A.n=0;}
-indexed_opt(A) ::= INDEXED BY nm(X). {A = X;}
-indexed_opt(A) ::= NOT INDEXED. {A.z=0; A.n=1;}
-
-%type using_opt {IdList*}
-%destructor using_opt {sqlite3IdListDelete(pParse->db, $$);}
-using_opt(U) ::= USING LP idlist(L) RP. {U = L;}
-using_opt(U) ::= . {U = 0;}
-
-
-%type orderby_opt {ExprList*}
-%destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);}
-
-// the sortlist non-terminal stores a list of expression where each
-// expression is optionally followed by ASC or DESC to indicate the
-// sort order.
-//
-%type sortlist {ExprList*}
-%destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);}
-
-orderby_opt(A) ::= . {A = 0;}
-orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
-sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). {
- A = sqlite3ExprListAppend(pParse,A,Y);
- sqlite3ExprListSetSortOrder(A,Z);
-}
-sortlist(A) ::= expr(Y) sortorder(Z). {
- A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/
- sqlite3ExprListSetSortOrder(A,Z);
-}
-
-%type sortorder {int}
-
-sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;}
-sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;}
-sortorder(A) ::= . {A = SQLITE_SO_UNDEFINED;}
-
-%type groupby_opt {ExprList*}
-%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);}
-groupby_opt(A) ::= . {A = 0;}
-groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
-
-%type having_opt {Expr*}
-%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
-having_opt(A) ::= . {A = 0;}
-having_opt(A) ::= HAVING expr(X). {A = X;}
-
-%type limit_opt {Expr*}
-
-// The destructor for limit_opt will never fire in the current grammar.
-// The limit_opt non-terminal only occurs at the end of a single production
-// rule for SELECT statements. As soon as the rule that create the
-// limit_opt non-terminal reduces, the SELECT statement rule will also
-// reduce. So there is never a limit_opt non-terminal on the stack
-// except as a transient. So there is never anything to destroy.
-//
-//%destructor limit_opt {sqlite3ExprDelete(pParse->db, $$);}
-limit_opt(A) ::= . {A = 0;}
-limit_opt(A) ::= LIMIT expr(X).
- {A = sqlite3PExpr(pParse,TK_LIMIT,X,0);}
-limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y).
- {A = sqlite3PExpr(pParse,TK_LIMIT,X,Y);}
-limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
- {A = sqlite3PExpr(pParse,TK_LIMIT,Y,X);}
-
-/////////////////////////// The DELETE statement /////////////////////////////
-//
-%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
-cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W)
- orderby_opt(O) limit_opt(L). {
- sqlite3SrcListIndexedBy(pParse, X, &I);
- sqlite3DeleteFrom(pParse,X,W,O,L);
-}
-%endif
-%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
-cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W). {
- sqlite3SrcListIndexedBy(pParse, X, &I);
- sqlite3DeleteFrom(pParse,X,W,0,0);
-}
-%endif
-
-%type where_opt {Expr*}
-%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
-
-where_opt(A) ::= . {A = 0;}
-where_opt(A) ::= WHERE expr(X). {A = X;}
-
-////////////////////////// The UPDATE command ////////////////////////////////
-//
-%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
-cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y)
- where_opt(W) orderby_opt(O) limit_opt(L). {
- sqlite3SrcListIndexedBy(pParse, X, &I);
- sqlite3ExprListCheckLength(pParse,Y,"set list");
- sqlite3Update(pParse,X,Y,W,R,O,L,0);
-}
-%endif
-%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
-cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y)
- where_opt(W). {
- sqlite3SrcListIndexedBy(pParse, X, &I);
- sqlite3ExprListCheckLength(pParse,Y,"set list");
- sqlite3Update(pParse,X,Y,W,R,0,0,0);
-}
-%endif
-
-%type setlist {ExprList*}
-%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}
-
-setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). {
- A = sqlite3ExprListAppend(pParse, A, Y);
- sqlite3ExprListSetName(pParse, A, &X, 1);
-}
-setlist(A) ::= setlist(A) COMMA LP idlist(X) RP EQ expr(Y). {
- A = sqlite3ExprListAppendVector(pParse, A, X, Y);
-}
-setlist(A) ::= nm(X) EQ expr(Y). {
- A = sqlite3ExprListAppend(pParse, 0, Y);
- sqlite3ExprListSetName(pParse, A, &X, 1);
-}
-setlist(A) ::= LP idlist(X) RP EQ expr(Y). {
- A = sqlite3ExprListAppendVector(pParse, 0, X, Y);
-}
-
-////////////////////////// The INSERT command /////////////////////////////////
-//
-cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) select(S)
- upsert(U). {
- sqlite3Insert(pParse, X, S, F, R, U);
-}
-cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES.
-{
- sqlite3Insert(pParse, X, 0, F, R, 0);
-}
-
-%type upsert {Upsert*}
-
-// Because upsert only occurs at the tip end of the INSERT rule for cmd,
-// there is never a case where the value of the upsert pointer will not
-// be destroyed by the cmd action. So comment-out the destructor to
-// avoid unreachable code.
-//%destructor upsert {sqlite3UpsertDelete(pParse->db,$$);}
-upsert(A) ::= . { A = 0; }
-upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW)
- DO UPDATE SET setlist(Z) where_opt(W).
- { A = sqlite3UpsertNew(pParse->db,T,TW,Z,W);}
-upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING.
- { A = sqlite3UpsertNew(pParse->db,T,TW,0,0); }
-upsert(A) ::= ON CONFLICT DO NOTHING.
- { A = sqlite3UpsertNew(pParse->db,0,0,0,0); }
-
-%type insert_cmd {int}
-insert_cmd(A) ::= INSERT orconf(R). {A = R;}
-insert_cmd(A) ::= REPLACE. {A = OE_Replace;}
-
-%type idlist_opt {IdList*}
-%destructor idlist_opt {sqlite3IdListDelete(pParse->db, $$);}
-%type idlist {IdList*}
-%destructor idlist {sqlite3IdListDelete(pParse->db, $$);}
-
-idlist_opt(A) ::= . {A = 0;}
-idlist_opt(A) ::= LP idlist(X) RP. {A = X;}
-idlist(A) ::= idlist(A) COMMA nm(Y).
- {A = sqlite3IdListAppend(pParse->db,A,&Y);}
-idlist(A) ::= nm(Y).
- {A = sqlite3IdListAppend(pParse->db,0,&Y); /*A-overwrites-Y*/}
-
-/////////////////////////// Expression Processing /////////////////////////////
-//
-
-%type expr {Expr*}
-%destructor expr {sqlite3ExprDelete(pParse->db, $$);}
-%type term {Expr*}
-%destructor term {sqlite3ExprDelete(pParse->db, $$);}
-
-%include {
-
- /* Construct a new Expr object from a single identifier. Use the
- ** new Expr to populate pOut. Set the span of pOut to be the identifier
- ** that created the expression.
- */
- static Expr *tokenExpr(Parse *pParse, int op, Token t){
- Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1);
- if( p ){
- memset(p, 0, sizeof(Expr));
- p->op = (u8)op;
- p->flags = EP_Leaf;
- p->iAgg = -1;
- p->u.zToken = (char*)&p[1];
- memcpy(p->u.zToken, t.z, t.n);
- p->u.zToken[t.n] = 0;
- if( sqlite3Isquote(p->u.zToken[0]) ){
- if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted;
- sqlite3Dequote(p->u.zToken);
- }
-#if SQLITE_MAX_EXPR_DEPTH>0
- p->nHeight = 1;
-#endif
- }
- return p;
- }
-}
-
-expr(A) ::= term(A).
-expr(A) ::= LP expr(X) RP. {A = X;}
-expr(A) ::= id(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/}
-expr(A) ::= JOIN_KW(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/}
-expr(A) ::= nm(X) DOT nm(Y). {
- Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
- Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
- A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
-}
-expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
- Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
- Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
- Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &Z, 1);
- Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3);
- A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
-}
-term(A) ::= NULL|FLOAT|BLOB(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/}
-term(A) ::= STRING(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/}
-term(A) ::= INTEGER(X). {
- A = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1);
-}
-expr(A) ::= VARIABLE(X). {
- if( !(X.z[0]=='#' && sqlite3Isdigit(X.z[1])) ){
- u32 n = X.n;
- A = tokenExpr(pParse, TK_VARIABLE, X);
- sqlite3ExprAssignVarNumber(pParse, A, n);
- }else{
- /* When doing a nested parse, one can include terms in an expression
- ** that look like this: #1 #2 ... These terms refer to registers
- ** in the virtual machine. #N is the N-th register. */
- Token t = X; /*A-overwrites-X*/
- assert( t.n>=2 );
- if( pParse->nested==0 ){
- sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
- A = 0;
- }else{
- A = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
- if( A ) sqlite3GetInt32(&t.z[1], &A->iTable);
- }
- }
-}
-expr(A) ::= expr(A) COLLATE ids(C). {
- A = sqlite3ExprAddCollateToken(pParse, A, &C, 1);
-}
-%ifndef SQLITE_OMIT_CAST
-expr(A) ::= CAST LP expr(E) AS typetoken(T) RP. {
- A = sqlite3ExprAlloc(pParse->db, TK_CAST, &T, 1);
- sqlite3ExprAttachSubtrees(pParse->db, A, E, 0);
-}
-%endif SQLITE_OMIT_CAST
-expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP. {
- if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
- sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
- }
- A = sqlite3ExprFunction(pParse, Y, &X);
- if( D==SF_Distinct && A ){
- A->flags |= EP_Distinct;
- }
-}
-expr(A) ::= id(X) LP STAR RP. {
- A = sqlite3ExprFunction(pParse, 0, &X);
-}
-term(A) ::= CTIME_KW(OP). {
- A = sqlite3ExprFunction(pParse, 0, &OP);
-}
-
-expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
- ExprList *pList = sqlite3ExprListAppend(pParse, X, Y);
- A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( A ){
- A->x.pList = pList;
- }else{
- sqlite3ExprListDelete(pParse->db, pList);
- }
-}
-
-expr(A) ::= expr(A) AND(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);}
-expr(A) ::= expr(A) OR(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);}
-expr(A) ::= expr(A) LT|GT|GE|LE(OP) expr(Y).
- {A=sqlite3PExpr(pParse,@OP,A,Y);}
-expr(A) ::= expr(A) EQ|NE(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);}
-expr(A) ::= expr(A) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
- {A=sqlite3PExpr(pParse,@OP,A,Y);}
-expr(A) ::= expr(A) PLUS|MINUS(OP) expr(Y).
- {A=sqlite3PExpr(pParse,@OP,A,Y);}
-expr(A) ::= expr(A) STAR|SLASH|REM(OP) expr(Y).
- {A=sqlite3PExpr(pParse,@OP,A,Y);}
-expr(A) ::= expr(A) CONCAT(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);}
-%type likeop {Token}
-likeop(A) ::= LIKE_KW|MATCH(A).
-likeop(A) ::= NOT LIKE_KW|MATCH(X). {A=X; A.n|=0x80000000; /*A-overwrite-X*/}
-expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] {
- ExprList *pList;
- int bNot = OP.n & 0x80000000;
- OP.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, Y);
- pList = sqlite3ExprListAppend(pParse,pList, A);
- A = sqlite3ExprFunction(pParse, pList, &OP);
- if( bNot ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
- if( A ) A->flags |= EP_InfixFunc;
-}
-expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] {
- ExprList *pList;
- int bNot = OP.n & 0x80000000;
- OP.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, Y);
- pList = sqlite3ExprListAppend(pParse,pList, A);
- pList = sqlite3ExprListAppend(pParse,pList, E);
- A = sqlite3ExprFunction(pParse, pList, &OP);
- if( bNot ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
- if( A ) A->flags |= EP_InfixFunc;
-}
-
-expr(A) ::= expr(A) ISNULL|NOTNULL(E). {A = sqlite3PExpr(pParse,@E,A,0);}
-expr(A) ::= expr(A) NOT NULL. {A = sqlite3PExpr(pParse,TK_NOTNULL,A,0);}
-
-%include {
- /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
- ** unary TK_ISNULL or TK_NOTNULL expression. */
- static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
- sqlite3 *db = pParse->db;
- if( pA && pY && pY->op==TK_NULL ){
- pA->op = (u8)op;
- sqlite3ExprDelete(db, pA->pRight);
- pA->pRight = 0;
- }
- }
-}
-
-// expr1 IS expr2
-// expr1 IS NOT expr2
-//
-// If expr2 is NULL then code as TK_ISNULL or TK_NOTNULL. If expr2
-// is any other expression, code as TK_IS or TK_ISNOT.
-//
-expr(A) ::= expr(A) IS expr(Y). {
- A = sqlite3PExpr(pParse,TK_IS,A,Y);
- binaryToUnaryIfNull(pParse, Y, A, TK_ISNULL);
-}
-expr(A) ::= expr(A) IS NOT expr(Y). {
- A = sqlite3PExpr(pParse,TK_ISNOT,A,Y);
- binaryToUnaryIfNull(pParse, Y, A, TK_NOTNULL);
-}
-
-expr(A) ::= NOT(B) expr(X).
- {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/}
-expr(A) ::= BITNOT(B) expr(X).
- {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/}
-expr(A) ::= MINUS expr(X). [BITNOT]
- {A = sqlite3PExpr(pParse, TK_UMINUS, X, 0);}
-expr(A) ::= PLUS expr(X). [BITNOT]
- {A = sqlite3PExpr(pParse, TK_UPLUS, X, 0);}
-
-%type between_op {int}
-between_op(A) ::= BETWEEN. {A = 0;}
-between_op(A) ::= NOT BETWEEN. {A = 1;}
-expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
- ExprList *pList = sqlite3ExprListAppend(pParse,0, X);
- pList = sqlite3ExprListAppend(pParse,pList, Y);
- A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0);
- if( A ){
- A->x.pList = pList;
- }else{
- sqlite3ExprListDelete(pParse->db, pList);
- }
- if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
-}
-%ifndef SQLITE_OMIT_SUBQUERY
- %type in_op {int}
- in_op(A) ::= IN. {A = 0;}
- in_op(A) ::= NOT IN. {A = 1;}
- expr(A) ::= expr(A) in_op(N) LP exprlist(Y) RP. [IN] {
- if( Y==0 ){
- /* Expressions of the form
- **
- ** expr1 IN ()
- ** expr1 NOT IN ()
- **
- ** simplify to constants 0 (false) and 1 (true), respectively,
- ** regardless of the value of expr1.
- */
- sqlite3ExprDelete(pParse->db, A);
- A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1);
- }else if( Y->nExpr==1 ){
- /* Expressions of the form:
- **
- ** expr1 IN (?1)
- ** expr1 NOT IN (?2)
- **
- ** with exactly one value on the RHS can be simplified to something
- ** like this:
- **
- ** expr1 == ?1
- ** expr1 <> ?2
- **
- ** But, the RHS of the == or <> is marked with the EP_Generic flag
- ** so that it may not contribute to the computation of comparison
- ** affinity or the collating sequence to use for comparison. Otherwise,
- ** the semantics would be subtly different from IN or NOT IN.
- */
- Expr *pRHS = Y->a[0].pExpr;
- Y->a[0].pExpr = 0;
- sqlite3ExprListDelete(pParse->db, Y);
- /* pRHS cannot be NULL because a malloc error would have been detected
- ** before now and control would have never reached this point */
- if( ALWAYS(pRHS) ){
- pRHS->flags &= ~EP_Collate;
- pRHS->flags |= EP_Generic;
- }
- A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS);
- }else{
- A = sqlite3PExpr(pParse, TK_IN, A, 0);
- if( A ){
- A->x.pList = Y;
- sqlite3ExprSetHeightAndFlags(pParse, A);
- }else{
- sqlite3ExprListDelete(pParse->db, Y);
- }
- if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
- }
- }
- expr(A) ::= LP select(X) RP. {
- A = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlite3PExprAddSelect(pParse, A, X);
- }
- expr(A) ::= expr(A) in_op(N) LP select(Y) RP. [IN] {
- A = sqlite3PExpr(pParse, TK_IN, A, 0);
- sqlite3PExprAddSelect(pParse, A, Y);
- if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
- }
- expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z) paren_exprlist(E). [IN] {
- SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
- Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
- if( E ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, E);
- A = sqlite3PExpr(pParse, TK_IN, A, 0);
- sqlite3PExprAddSelect(pParse, A, pSelect);
- if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
- }
- expr(A) ::= EXISTS LP select(Y) RP. {
- Expr *p;
- p = A = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
- sqlite3PExprAddSelect(pParse, p, Y);
- }
-%endif SQLITE_OMIT_SUBQUERY
-
-/* CASE expressions */
-expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. {
- A = sqlite3PExpr(pParse, TK_CASE, X, 0);
- if( A ){
- A->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y;
- sqlite3ExprSetHeightAndFlags(pParse, A);
- }else{
- sqlite3ExprListDelete(pParse->db, Y);
- sqlite3ExprDelete(pParse->db, Z);
- }
-}
-%type case_exprlist {ExprList*}
-%destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
-case_exprlist(A) ::= case_exprlist(A) WHEN expr(Y) THEN expr(Z). {
- A = sqlite3ExprListAppend(pParse,A, Y);
- A = sqlite3ExprListAppend(pParse,A, Z);
-}
-case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
- A = sqlite3ExprListAppend(pParse,0, Y);
- A = sqlite3ExprListAppend(pParse,A, Z);
-}
-%type case_else {Expr*}
-%destructor case_else {sqlite3ExprDelete(pParse->db, $$);}
-case_else(A) ::= ELSE expr(X). {A = X;}
-case_else(A) ::= . {A = 0;}
-%type case_operand {Expr*}
-%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
-case_operand(A) ::= expr(X). {A = X; /*A-overwrites-X*/}
-case_operand(A) ::= . {A = 0;}
-
-%type exprlist {ExprList*}
-%destructor exprlist {sqlite3ExprListDelete(pParse->db, $$);}
-%type nexprlist {ExprList*}
-%destructor nexprlist {sqlite3ExprListDelete(pParse->db, $$);}
-
-exprlist(A) ::= nexprlist(A).
-exprlist(A) ::= . {A = 0;}
-nexprlist(A) ::= nexprlist(A) COMMA expr(Y).
- {A = sqlite3ExprListAppend(pParse,A,Y);}
-nexprlist(A) ::= expr(Y).
- {A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/}
-
-%ifndef SQLITE_OMIT_SUBQUERY
-/* A paren_exprlist is an optional expression list contained inside
-** of parenthesis */
-%type paren_exprlist {ExprList*}
-%destructor paren_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
-paren_exprlist(A) ::= . {A = 0;}
-paren_exprlist(A) ::= LP exprlist(X) RP. {A = X;}
-%endif SQLITE_OMIT_SUBQUERY
-
-
-///////////////////////////// The CREATE INDEX command ///////////////////////
-//
-cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D)
- ON nm(Y) LP sortlist(Z) RP where_opt(W). {
- sqlite3CreateIndex(pParse, &X, &D,
- sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U,
- &S, W, SQLITE_SO_ASC, NE, SQLITE_IDXTYPE_APPDEF);
-}
-
-%type uniqueflag {int}
-uniqueflag(A) ::= UNIQUE. {A = OE_Abort;}
-uniqueflag(A) ::= . {A = OE_None;}
-
-
-// The eidlist non-terminal (Expression Id List) generates an ExprList
-// from a list of identifiers. The identifier names are in ExprList.a[].zName.
-// This list is stored in an ExprList rather than an IdList so that it
-// can be easily sent to sqlite3ColumnsExprList().
-//
-// eidlist is grouped with CREATE INDEX because it used to be the non-terminal
-// used for the arguments to an index. That is just an historical accident.
-//
-// IMPORTANT COMPATIBILITY NOTE: Some prior versions of SQLite accepted
-// COLLATE clauses and ASC or DESC keywords on ID lists in inappropriate
-// places - places that might have been stored in the sqlite_master schema.
-// Those extra features were ignored. But because they might be in some
-// (busted) old databases, we need to continue parsing them when loading
-// historical schemas.
-//
-%type eidlist {ExprList*}
-%destructor eidlist {sqlite3ExprListDelete(pParse->db, $$);}
-%type eidlist_opt {ExprList*}
-%destructor eidlist_opt {sqlite3ExprListDelete(pParse->db, $$);}
-
-%include {
- /* Add a single new term to an ExprList that is used to store a
- ** list of identifiers. Report an error if the ID list contains
- ** a COLLATE clause or an ASC or DESC keyword, except ignore the
- ** error while parsing a legacy schema.
- */
- static ExprList *parserAddExprIdListTerm(
- Parse *pParse,
- ExprList *pPrior,
- Token *pIdToken,
- int hasCollate,
- int sortOrder
- ){
- ExprList *p = sqlite3ExprListAppend(pParse, pPrior, 0);
- if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED)
- && pParse->db->init.busy==0
- ){
- sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"",
- pIdToken->n, pIdToken->z);
- }
- sqlite3ExprListSetName(pParse, p, pIdToken, 1);
- return p;
- }
-} // end %include
-
-eidlist_opt(A) ::= . {A = 0;}
-eidlist_opt(A) ::= LP eidlist(X) RP. {A = X;}
-eidlist(A) ::= eidlist(A) COMMA nm(Y) collate(C) sortorder(Z). {
- A = parserAddExprIdListTerm(pParse, A, &Y, C, Z);
-}
-eidlist(A) ::= nm(Y) collate(C) sortorder(Z). {
- A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z); /*A-overwrites-Y*/
-}
-
-%type collate {int}
-collate(C) ::= . {C = 0;}
-collate(C) ::= COLLATE ids. {C = 1;}
-
-
-///////////////////////////// The DROP INDEX command /////////////////////////
-//
-cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);}
-
-///////////////////////////// The VACUUM command /////////////////////////////
-//
-%ifndef SQLITE_OMIT_VACUUM
-%ifndef SQLITE_OMIT_ATTACH
-cmd ::= VACUUM. {sqlite3Vacuum(pParse,0);}
-cmd ::= VACUUM nm(X). {sqlite3Vacuum(pParse,&X);}
-%endif SQLITE_OMIT_ATTACH
-%endif SQLITE_OMIT_VACUUM
-
-///////////////////////////// The PRAGMA command /////////////////////////////
-//
-%ifndef SQLITE_OMIT_PRAGMA
-cmd ::= PRAGMA nm(X) dbnm(Z). {sqlite3Pragma(pParse,&X,&Z,0,0);}
-cmd ::= PRAGMA nm(X) dbnm(Z) EQ nmnum(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
-cmd ::= PRAGMA nm(X) dbnm(Z) LP nmnum(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
-cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y).
- {sqlite3Pragma(pParse,&X,&Z,&Y,1);}
-cmd ::= PRAGMA nm(X) dbnm(Z) LP minus_num(Y) RP.
- {sqlite3Pragma(pParse,&X,&Z,&Y,1);}
-
-nmnum(A) ::= plus_num(A).
-nmnum(A) ::= nm(A).
-nmnum(A) ::= ON(A).
-nmnum(A) ::= DELETE(A).
-nmnum(A) ::= DEFAULT(A).
-%endif SQLITE_OMIT_PRAGMA
-%token_class number INTEGER|FLOAT.
-plus_num(A) ::= PLUS number(X). {A = X;}
-plus_num(A) ::= number(A).
-minus_num(A) ::= MINUS number(X). {A = X;}
-//////////////////////////// The CREATE TRIGGER command /////////////////////
-
-%ifndef SQLITE_OMIT_TRIGGER
-
-cmd ::= createkw trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
- Token all;
- all.z = A.z;
- all.n = (int)(Z.z - A.z) + Z.n;
- sqlite3FinishTrigger(pParse, S, &all);
-}
-
-trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z)
- trigger_time(C) trigger_event(D)
- ON fullname(E) foreach_clause when_clause(G). {
- sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR);
- A = (Z.n==0?B:Z); /*A-overwrites-T*/
-}
-
-%type trigger_time {int}
-trigger_time(A) ::= BEFORE|AFTER(X). { A = @X; /*A-overwrites-X*/ }
-trigger_time(A) ::= INSTEAD OF. { A = TK_INSTEAD;}
-trigger_time(A) ::= . { A = TK_BEFORE; }
-
-%type trigger_event {struct TrigEvent}
-%destructor trigger_event {sqlite3IdListDelete(pParse->db, $$.b);}
-trigger_event(A) ::= DELETE|INSERT(X). {A.a = @X; /*A-overwrites-X*/ A.b = 0;}
-trigger_event(A) ::= UPDATE(X). {A.a = @X; /*A-overwrites-X*/ A.b = 0;}
-trigger_event(A) ::= UPDATE OF idlist(X).{A.a = TK_UPDATE; A.b = X;}
-
-foreach_clause ::= .
-foreach_clause ::= FOR EACH ROW.
-
-%type when_clause {Expr*}
-%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);}
-when_clause(A) ::= . { A = 0; }
-when_clause(A) ::= WHEN expr(X). { A = X; }
-
-%type trigger_cmd_list {TriggerStep*}
-%destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);}
-trigger_cmd_list(A) ::= trigger_cmd_list(A) trigger_cmd(X) SEMI. {
- assert( A!=0 );
- A->pLast->pNext = X;
- A->pLast = X;
-}
-trigger_cmd_list(A) ::= trigger_cmd(A) SEMI. {
- assert( A!=0 );
- A->pLast = A;
-}
-
-// Disallow qualified table names on INSERT, UPDATE, and DELETE statements
-// within a trigger. The table to INSERT, UPDATE, or DELETE is always in
-// the same database as the table that the trigger fires on.
-//
-%type trnm {Token}
-trnm(A) ::= nm(A).
-trnm(A) ::= nm DOT nm(X). {
- A = X;
- sqlite3ErrorMsg(pParse,
- "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
- "statements within triggers");
-}
-
-// Disallow the INDEX BY and NOT INDEXED clauses on UPDATE and DELETE
-// statements within triggers. We make a specific error message for this
-// since it is an exception to the default grammar rules.
-//
-tridxby ::= .
-tridxby ::= INDEXED BY nm. {
- sqlite3ErrorMsg(pParse,
- "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
- "within triggers");
-}
-tridxby ::= NOT INDEXED. {
- sqlite3ErrorMsg(pParse,
- "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
- "within triggers");
-}
-
-
-
-%type trigger_cmd {TriggerStep*}
-%destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);}
-// UPDATE
-trigger_cmd(A) ::=
- UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z) scanpt(E).
- {A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R, B.z, E);}
-
-// INSERT
-trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO
- trnm(X) idlist_opt(F) select(S) upsert(U) scanpt(Z). {
- A = sqlite3TriggerInsertStep(pParse->db,&X,F,S,R,U,B,Z);/*A-overwrites-R*/
-}
-// DELETE
-trigger_cmd(A) ::= DELETE(B) FROM trnm(X) tridxby where_opt(Y) scanpt(E).
- {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y, B.z, E);}
-
-// SELECT
-trigger_cmd(A) ::= scanpt(B) select(X) scanpt(E).
- {A = sqlite3TriggerSelectStep(pParse->db, X, B, E); /*A-overwrites-X*/}
-
-// The special RAISE expression that may occur in trigger programs
-expr(A) ::= RAISE LP IGNORE RP. {
- A = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
- if( A ){
- A->affinity = OE_Ignore;
- }
-}
-expr(A) ::= RAISE LP raisetype(T) COMMA nm(Z) RP. {
- A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1);
- if( A ) {
- A->affinity = (char)T;
- }
-}
-%endif !SQLITE_OMIT_TRIGGER
-
-%type raisetype {int}
-raisetype(A) ::= ROLLBACK. {A = OE_Rollback;}
-raisetype(A) ::= ABORT. {A = OE_Abort;}
-raisetype(A) ::= FAIL. {A = OE_Fail;}
-
-
-//////////////////////// DROP TRIGGER statement //////////////////////////////
-%ifndef SQLITE_OMIT_TRIGGER
-cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). {
- sqlite3DropTrigger(pParse,X,NOERR);
-}
-%endif !SQLITE_OMIT_TRIGGER
-
-//////////////////////// ATTACH DATABASE file AS name /////////////////////////
-%ifndef SQLITE_OMIT_ATTACH
-cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). {
- sqlite3Attach(pParse, F, D, K);
-}
-cmd ::= DETACH database_kw_opt expr(D). {
- sqlite3Detach(pParse, D);
-}
-
-%type key_opt {Expr*}
-%destructor key_opt {sqlite3ExprDelete(pParse->db, $$);}
-key_opt(A) ::= . { A = 0; }
-key_opt(A) ::= KEY expr(X). { A = X; }
-
-database_kw_opt ::= DATABASE.
-database_kw_opt ::= .
-%endif SQLITE_OMIT_ATTACH
-
-////////////////////////// REINDEX collation //////////////////////////////////
-%ifndef SQLITE_OMIT_REINDEX
-cmd ::= REINDEX. {sqlite3Reindex(pParse, 0, 0);}
-cmd ::= REINDEX nm(X) dbnm(Y). {sqlite3Reindex(pParse, &X, &Y);}
-%endif SQLITE_OMIT_REINDEX
-
-/////////////////////////////////// ANALYZE ///////////////////////////////////
-%ifndef SQLITE_OMIT_ANALYZE
-cmd ::= ANALYZE. {sqlite3Analyze(pParse, 0, 0);}
-cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y);}
-%endif
-
-//////////////////////// ALTER TABLE table ... ////////////////////////////////
-%ifndef SQLITE_OMIT_ALTERTABLE
-cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
- sqlite3AlterRenameTable(pParse,X,&Z);
-}
-cmd ::= ALTER TABLE add_column_fullname
- ADD kwcolumn_opt columnname(Y) carglist. {
- Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n;
- sqlite3AlterFinishAddColumn(pParse, &Y);
-}
-add_column_fullname ::= fullname(X). {
- disableLookaside(pParse);
- sqlite3AlterBeginAddColumn(pParse, X);
-}
-kwcolumn_opt ::= .
-kwcolumn_opt ::= COLUMNKW.
-%endif SQLITE_OMIT_ALTERTABLE
-
-//////////////////////// CREATE VIRTUAL TABLE ... /////////////////////////////
-%ifndef SQLITE_OMIT_VIRTUALTABLE
-cmd ::= create_vtab. {sqlite3VtabFinishParse(pParse,0);}
-cmd ::= create_vtab LP vtabarglist RP(X). {sqlite3VtabFinishParse(pParse,&X);}
-create_vtab ::= createkw VIRTUAL TABLE ifnotexists(E)
- nm(X) dbnm(Y) USING nm(Z). {
- sqlite3VtabBeginParse(pParse, &X, &Y, &Z, E);
-}
-vtabarglist ::= vtabarg.
-vtabarglist ::= vtabarglist COMMA vtabarg.
-vtabarg ::= . {sqlite3VtabArgInit(pParse);}
-vtabarg ::= vtabarg vtabargtoken.
-vtabargtoken ::= ANY(X). {sqlite3VtabArgExtend(pParse,&X);}
-vtabargtoken ::= lp anylist RP(X). {sqlite3VtabArgExtend(pParse,&X);}
-lp ::= LP(X). {sqlite3VtabArgExtend(pParse,&X);}
-anylist ::= .
-anylist ::= anylist LP anylist RP.
-anylist ::= anylist ANY.
-%endif SQLITE_OMIT_VIRTUALTABLE
-
-
-//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
-%type wqlist {With*}
-%destructor wqlist {sqlite3WithDelete(pParse->db, $$);}
-
-with ::= .
-%ifndef SQLITE_OMIT_CTE
-with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); }
-with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); }
-
-wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
- A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/
-}
-wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
- A = sqlite3WithAdd(pParse, A, &X, Y, Z);
-}
-%endif SQLITE_OMIT_CTE
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache.c
deleted file mode 100644
index 41fb03100c6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache.c
+++ /dev/null
@@ -1,871 +0,0 @@
-/*
-** 2008 August 05
-**
-** 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 that page cache.
-*/
-#include "sqliteInt.h"
-
-/*
-** A complete page cache is an instance of this structure. Every
-** entry in the cache holds a single page of the database file. The
-** btree layer only operates on the cached copy of the database pages.
-**
-** A page cache entry is "clean" if it exactly matches what is currently
-** on disk. A page is "dirty" if it has been modified and needs to be
-** persisted to disk.
-**
-** pDirty, pDirtyTail, pSynced:
-** All dirty pages are linked into the doubly linked list using
-** PgHdr.pDirtyNext and pDirtyPrev. The list is maintained in LRU order
-** such that p was added to the list more recently than p->pDirtyNext.
-** PCache.pDirty points to the first (newest) element in the list and
-** pDirtyTail to the last (oldest).
-**
-** The PCache.pSynced variable is used to optimize searching for a dirty
-** page to eject from the cache mid-transaction. It is better to eject
-** a page that does not require a journal sync than one that does.
-** Therefore, pSynced is maintained to that it *almost* always points
-** to either the oldest page in the pDirty/pDirtyTail list that has a
-** clear PGHDR_NEED_SYNC flag or to a page that is older than this one
-** (so that the right page to eject can be found by following pDirtyPrev
-** pointers).
-*/
-struct PCache {
- PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
- PgHdr *pSynced; /* Last synced page in dirty page list */
- int nRefSum; /* Sum of ref counts over all pages */
- int szCache; /* Configured cache size */
- int szSpill; /* Size before spilling occurs */
- int szPage; /* Size of every page in this cache */
- int szExtra; /* Size of extra space for each page */
- u8 bPurgeable; /* True if pages are on backing store */
- u8 eCreate; /* eCreate value for for xFetch() */
- int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
- void *pStress; /* Argument to xStress */
- sqlite3_pcache *pCache; /* Pluggable cache module */
-};
-
-/********************************** Test and Debug Logic **********************/
-/*
-** Debug tracing macros. Enable by by changing the "0" to "1" and
-** recompiling.
-**
-** When sqlite3PcacheTrace is 1, single line trace messages are issued.
-** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries
-** is displayed for many operations, resulting in a lot of output.
-*/
-#if defined(SQLITE_DEBUG) && 0
- int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */
- int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */
-# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
- void pcacheDump(PCache *pCache){
- int N;
- int i, j;
- sqlite3_pcache_page *pLower;
- PgHdr *pPg;
- unsigned char *a;
-
- if( sqlite3PcacheTrace<2 ) return;
- if( pCache->pCache==0 ) return;
- N = sqlite3PcachePagecount(pCache);
- if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump;
- for(i=1; i<=N; i++){
- pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0);
- if( pLower==0 ) continue;
- pPg = (PgHdr*)pLower->pExtra;
- printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
- a = (unsigned char *)pLower->pBuf;
- for(j=0; j<12; j++) printf("%02x", a[j]);
- printf("\n");
- if( pPg->pPage==0 ){
- sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0);
- }
- }
- }
- #else
-# define pcacheTrace(X)
-# define pcacheDump(X)
-#endif
-
-/*
-** Check invariants on a PgHdr entry. Return true if everything is OK.
-** Return false if any invariant is violated.
-**
-** This routine is for use inside of assert() statements only. For
-** example:
-**
-** assert( sqlite3PcachePageSanity(pPg) );
-*/
-#ifdef SQLITE_DEBUG
-int sqlite3PcachePageSanity(PgHdr *pPg){
- PCache *pCache;
- assert( pPg!=0 );
- assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */
- pCache = pPg->pCache;
- assert( pCache!=0 ); /* Every page has an associated PCache */
- if( pPg->flags & PGHDR_CLEAN ){
- assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
- assert( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */
- assert( pCache->pDirtyTail!=pPg );
- }
- /* WRITEABLE pages must also be DIRTY */
- if( pPg->flags & PGHDR_WRITEABLE ){
- assert( pPg->flags & PGHDR_DIRTY ); /* WRITEABLE implies DIRTY */
- }
- /* NEED_SYNC can be set independently of WRITEABLE. This can happen,
- ** for example, when using the sqlite3PagerDontWrite() optimization:
- ** (1) Page X is journalled, and gets WRITEABLE and NEED_SEEK.
- ** (2) Page X moved to freelist, WRITEABLE is cleared
- ** (3) Page X reused, WRITEABLE is set again
- ** If NEED_SYNC had been cleared in step 2, then it would not be reset
- ** in step 3, and page might be written into the database without first
- ** syncing the rollback journal, which might cause corruption on a power
- ** loss.
- **
- ** Another example is when the database page size is smaller than the
- ** disk sector size. When any page of a sector is journalled, all pages
- ** in that sector are marked NEED_SYNC even if they are still CLEAN, just
- ** in case they are later modified, since all pages in the same sector
- ** must be journalled and synced before any of those pages can be safely
- ** written.
- */
- return 1;
-}
-#endif /* SQLITE_DEBUG */
-
-
-/********************************** Linked List Management ********************/
-
-/* Allowed values for second argument to pcacheManageDirtyList() */
-#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */
-#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */
-#define PCACHE_DIRTYLIST_FRONT 3 /* Move pPage to the front of the list */
-
-/*
-** Manage pPage's participation on the dirty list. Bits of the addRemove
-** argument determines what operation to do. The 0x01 bit means first
-** remove pPage from the dirty list. The 0x02 means add pPage back to
-** the dirty list. Doing both moves pPage to the front of the dirty list.
-*/
-static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
- PCache *p = pPage->pCache;
-
- pcacheTrace(("%p.DIRTYLIST.%s %d\n", p,
- addRemove==1 ? "REMOVE" : addRemove==2 ? "ADD" : "FRONT",
- pPage->pgno));
- if( addRemove & PCACHE_DIRTYLIST_REMOVE ){
- assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
- assert( pPage->pDirtyPrev || pPage==p->pDirty );
-
- /* Update the PCache1.pSynced variable if necessary. */
- if( p->pSynced==pPage ){
- p->pSynced = pPage->pDirtyPrev;
- }
-
- if( pPage->pDirtyNext ){
- pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
- }else{
- assert( pPage==p->pDirtyTail );
- p->pDirtyTail = pPage->pDirtyPrev;
- }
- if( pPage->pDirtyPrev ){
- pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
- }else{
- /* If there are now no dirty pages in the cache, set eCreate to 2.
- ** This is an optimization that allows sqlite3PcacheFetch() to skip
- ** searching for a dirty page to eject from the cache when it might
- ** otherwise have to. */
- assert( pPage==p->pDirty );
- p->pDirty = pPage->pDirtyNext;
- assert( p->bPurgeable || p->eCreate==2 );
- if( p->pDirty==0 ){ /*OPTIMIZATION-IF-TRUE*/
- assert( p->bPurgeable==0 || p->eCreate==1 );
- p->eCreate = 2;
- }
- }
- }
- if( addRemove & PCACHE_DIRTYLIST_ADD ){
- pPage->pDirtyPrev = 0;
- pPage->pDirtyNext = p->pDirty;
- if( pPage->pDirtyNext ){
- assert( pPage->pDirtyNext->pDirtyPrev==0 );
- pPage->pDirtyNext->pDirtyPrev = pPage;
- }else{
- p->pDirtyTail = pPage;
- if( p->bPurgeable ){
- assert( p->eCreate==2 );
- p->eCreate = 1;
- }
- }
- p->pDirty = pPage;
-
- /* If pSynced is NULL and this page has a clear NEED_SYNC flag, set
- ** pSynced to point to it. Checking the NEED_SYNC flag is an
- ** optimization, as if pSynced points to a page with the NEED_SYNC
- ** flag set sqlite3PcacheFetchStress() searches through all newer
- ** entries of the dirty-list for a page with NEED_SYNC clear anyway. */
- if( !p->pSynced
- && 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/
- ){
- p->pSynced = pPage;
- }
- }
- pcacheDump(p);
-}
-
-/*
-** Wrapper around the pluggable caches xUnpin method. If the cache is
-** being used for an in-memory database, this function is a no-op.
-*/
-static void pcacheUnpin(PgHdr *p){
- if( p->pCache->bPurgeable ){
- pcacheTrace(("%p.UNPIN %d\n", p->pCache, p->pgno));
- sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
- pcacheDump(p->pCache);
- }
-}
-
-/*
-** Compute the number of pages of cache requested. p->szCache is the
-** cache size requested by the "PRAGMA cache_size" statement.
-*/
-static int numberOfCachePages(PCache *p){
- if( p->szCache>=0 ){
- /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the
- ** suggested cache size is set to N. */
- return p->szCache;
- }else{
- /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then
- ** the number of cache pages is adjusted to use approximately abs(N*1024)
- ** bytes of memory. */
- return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
- }
-}
-
-/*************************************************** General Interfaces ******
-**
-** Initialize and shutdown the page cache subsystem. Neither of these
-** functions are threadsafe.
-*/
-int sqlite3PcacheInitialize(void){
- if( sqlite3GlobalConfig.pcache2.xInit==0 ){
- /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
- ** built-in default page cache is used instead of the application defined
- ** page cache. */
- sqlite3PCacheSetDefault();
- }
- return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
-}
-void sqlite3PcacheShutdown(void){
- if( sqlite3GlobalConfig.pcache2.xShutdown ){
- /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
- sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
- }
-}
-
-/*
-** Return the size in bytes of a PCache object.
-*/
-int sqlite3PcacheSize(void){ return sizeof(PCache); }
-
-/*
-** Create a new PCache object. Storage space to hold the object
-** has already been allocated and is passed in as the p pointer.
-** The caller discovers how much space needs to be allocated by
-** calling sqlite3PcacheSize().
-**
-** szExtra is some extra space allocated for each page. The first
-** 8 bytes of the extra space will be zeroed as the page is allocated,
-** but remaining content will be uninitialized. Though it is opaque
-** to this module, the extra space really ends up being the MemPage
-** structure in the pager.
-*/
-int sqlite3PcacheOpen(
- int szPage, /* Size of every page */
- int szExtra, /* Extra space associated with each page */
- int bPurgeable, /* True if pages are on backing store */
- int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
- void *pStress, /* Argument to xStress */
- PCache *p /* Preallocated space for the PCache */
-){
- memset(p, 0, sizeof(PCache));
- p->szPage = 1;
- p->szExtra = szExtra;
- assert( szExtra>=8 ); /* First 8 bytes will be zeroed */
- p->bPurgeable = bPurgeable;
- p->eCreate = 2;
- p->xStress = xStress;
- p->pStress = pStress;
- p->szCache = 100;
- p->szSpill = 1;
- pcacheTrace(("%p.OPEN szPage %d bPurgeable %d\n",p,szPage,bPurgeable));
- return sqlite3PcacheSetPageSize(p, szPage);
-}
-
-/*
-** Change the page size for PCache object. The caller must ensure that there
-** are no outstanding page references when this function is called.
-*/
-int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
- assert( pCache->nRefSum==0 && pCache->pDirty==0 );
- if( pCache->szPage ){
- sqlite3_pcache *pNew;
- pNew = sqlite3GlobalConfig.pcache2.xCreate(
- szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)),
- pCache->bPurgeable
- );
- if( pNew==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
- if( pCache->pCache ){
- sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
- }
- pCache->pCache = pNew;
- pCache->szPage = szPage;
- pcacheTrace(("%p.PAGESIZE %d\n",pCache,szPage));
- }
- return SQLITE_OK;
-}
-
-/*
-** Try to obtain a page from the cache.
-**
-** This routine returns a pointer to an sqlite3_pcache_page object if
-** such an object is already in cache, or if a new one is created.
-** This routine returns a NULL pointer if the object was not in cache
-** and could not be created.
-**
-** The createFlags should be 0 to check for existing pages and should
-** be 3 (not 1, but 3) to try to create a new page.
-**
-** If the createFlag is 0, then NULL is always returned if the page
-** is not already in the cache. If createFlag is 1, then a new page
-** is created only if that can be done without spilling dirty pages
-** and without exceeding the cache size limit.
-**
-** The caller needs to invoke sqlite3PcacheFetchFinish() to properly
-** initialize the sqlite3_pcache_page object and convert it into a
-** PgHdr object. The sqlite3PcacheFetch() and sqlite3PcacheFetchFinish()
-** routines are split this way for performance reasons. When separated
-** they can both (usually) operate without having to push values to
-** the stack on entry and pop them back off on exit, which saves a
-** lot of pushing and popping.
-*/
-sqlite3_pcache_page *sqlite3PcacheFetch(
- PCache *pCache, /* Obtain the page from this cache */
- Pgno pgno, /* Page number to obtain */
- int createFlag /* If true, create page if it does not exist already */
-){
- int eCreate;
- sqlite3_pcache_page *pRes;
-
- assert( pCache!=0 );
- assert( pCache->pCache!=0 );
- assert( createFlag==3 || createFlag==0 );
- assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) );
-
- /* eCreate defines what to do if the page does not exist.
- ** 0 Do not allocate a new page. (createFlag==0)
- ** 1 Allocate a new page if doing so is inexpensive.
- ** (createFlag==1 AND bPurgeable AND pDirty)
- ** 2 Allocate a new page even it doing so is difficult.
- ** (createFlag==1 AND !(bPurgeable AND pDirty)
- */
- eCreate = createFlag & pCache->eCreate;
- assert( eCreate==0 || eCreate==1 || eCreate==2 );
- assert( createFlag==0 || pCache->eCreate==eCreate );
- assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
- pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
- pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno,
- createFlag?" create":"",pRes));
- return pRes;
-}
-
-/*
-** If the sqlite3PcacheFetch() routine is unable to allocate a new
-** page because no clean pages are available for reuse and the cache
-** size limit has been reached, then this routine can be invoked to
-** try harder to allocate a page. This routine might invoke the stress
-** callback to spill dirty pages to the journal. It will then try to
-** allocate the new page and will only fail to allocate a new page on
-** an OOM error.
-**
-** This routine should be invoked only after sqlite3PcacheFetch() fails.
-*/
-int sqlite3PcacheFetchStress(
- PCache *pCache, /* Obtain the page from this cache */
- Pgno pgno, /* Page number to obtain */
- sqlite3_pcache_page **ppPage /* Write result here */
-){
- PgHdr *pPg;
- if( pCache->eCreate==2 ) return 0;
-
- if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){
- /* Find a dirty page to write-out and recycle. First try to find a
- ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
- ** cleared), but if that is not possible settle for any other
- ** unreferenced dirty page.
- **
- ** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC
- ** flag is currently referenced, then the following may leave pSynced
- ** set incorrectly (pointing to other than the LRU page with NEED_SYNC
- ** cleared). This is Ok, as pSynced is just an optimization. */
- for(pPg=pCache->pSynced;
- pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
- pPg=pPg->pDirtyPrev
- );
- pCache->pSynced = pPg;
- if( !pPg ){
- for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
- }
- if( pPg ){
- int rc;
-#ifdef SQLITE_LOG_CACHE_SPILL
- sqlite3_log(SQLITE_FULL,
- "spill page %d making room for %d - cache used: %d/%d",
- pPg->pgno, pgno,
- sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache),
- numberOfCachePages(pCache));
-#endif
- pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno));
- rc = pCache->xStress(pCache->pStress, pPg);
- pcacheDump(pCache);
- if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
- return rc;
- }
- }
- }
- *ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
- return *ppPage==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
-}
-
-/*
-** This is a helper routine for sqlite3PcacheFetchFinish()
-**
-** In the uncommon case where the page being fetched has not been
-** initialized, this routine is invoked to do the initialization.
-** This routine is broken out into a separate function since it
-** requires extra stack manipulation that can be avoided in the common
-** case.
-*/
-static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
- PCache *pCache, /* Obtain the page from this cache */
- Pgno pgno, /* Page number obtained */
- sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */
-){
- PgHdr *pPgHdr;
- assert( pPage!=0 );
- pPgHdr = (PgHdr*)pPage->pExtra;
- assert( pPgHdr->pPage==0 );
- memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty));
- pPgHdr->pPage = pPage;
- pPgHdr->pData = pPage->pBuf;
- pPgHdr->pExtra = (void *)&pPgHdr[1];
- memset(pPgHdr->pExtra, 0, 8);
- pPgHdr->pCache = pCache;
- pPgHdr->pgno = pgno;
- pPgHdr->flags = PGHDR_CLEAN;
- return sqlite3PcacheFetchFinish(pCache,pgno,pPage);
-}
-
-/*
-** This routine converts the sqlite3_pcache_page object returned by
-** sqlite3PcacheFetch() into an initialized PgHdr object. This routine
-** must be called after sqlite3PcacheFetch() in order to get a usable
-** result.
-*/
-PgHdr *sqlite3PcacheFetchFinish(
- PCache *pCache, /* Obtain the page from this cache */
- Pgno pgno, /* Page number obtained */
- sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */
-){
- PgHdr *pPgHdr;
-
- assert( pPage!=0 );
- pPgHdr = (PgHdr *)pPage->pExtra;
-
- if( !pPgHdr->pPage ){
- return pcacheFetchFinishWithInit(pCache, pgno, pPage);
- }
- pCache->nRefSum++;
- pPgHdr->nRef++;
- assert( sqlite3PcachePageSanity(pPgHdr) );
- return pPgHdr;
-}
-
-/*
-** Decrement the reference count on a page. If the page is clean and the
-** reference count drops to 0, then it is made eligible for recycling.
-*/
-void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
- assert( p->nRef>0 );
- p->pCache->nRefSum--;
- if( (--p->nRef)==0 ){
- if( p->flags&PGHDR_CLEAN ){
- pcacheUnpin(p);
- }else{
- pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
- }
- }
-}
-
-/*
-** Increase the reference count of a supplied page by 1.
-*/
-void sqlite3PcacheRef(PgHdr *p){
- assert(p->nRef>0);
- assert( sqlite3PcachePageSanity(p) );
- p->nRef++;
- p->pCache->nRefSum++;
-}
-
-/*
-** Drop a page from the cache. There must be exactly one reference to the
-** page. This function deletes that reference, so after it returns the
-** page pointed to by p is invalid.
-*/
-void sqlite3PcacheDrop(PgHdr *p){
- assert( p->nRef==1 );
- assert( sqlite3PcachePageSanity(p) );
- if( p->flags&PGHDR_DIRTY ){
- pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
- }
- p->pCache->nRefSum--;
- sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1);
-}
-
-/*
-** Make sure the page is marked as dirty. If it isn't dirty already,
-** make it so.
-*/
-void sqlite3PcacheMakeDirty(PgHdr *p){
- assert( p->nRef>0 );
- assert( sqlite3PcachePageSanity(p) );
- if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ /*OPTIMIZATION-IF-FALSE*/
- p->flags &= ~PGHDR_DONT_WRITE;
- if( p->flags & PGHDR_CLEAN ){
- p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN);
- pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno));
- assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY );
- pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
- }
- assert( sqlite3PcachePageSanity(p) );
- }
-}
-
-/*
-** Make sure the page is marked as clean. If it isn't clean already,
-** make it so.
-*/
-void sqlite3PcacheMakeClean(PgHdr *p){
- assert( sqlite3PcachePageSanity(p) );
- assert( (p->flags & PGHDR_DIRTY)!=0 );
- assert( (p->flags & PGHDR_CLEAN)==0 );
- pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
- p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
- p->flags |= PGHDR_CLEAN;
- pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno));
- assert( sqlite3PcachePageSanity(p) );
- if( p->nRef==0 ){
- pcacheUnpin(p);
- }
-}
-
-/*
-** Make every page in the cache clean.
-*/
-void sqlite3PcacheCleanAll(PCache *pCache){
- PgHdr *p;
- pcacheTrace(("%p.CLEAN-ALL\n",pCache));
- while( (p = pCache->pDirty)!=0 ){
- sqlite3PcacheMakeClean(p);
- }
-}
-
-/*
-** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages.
-*/
-void sqlite3PcacheClearWritable(PCache *pCache){
- PgHdr *p;
- pcacheTrace(("%p.CLEAR-WRITEABLE\n",pCache));
- for(p=pCache->pDirty; p; p=p->pDirtyNext){
- p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
- }
- pCache->pSynced = pCache->pDirtyTail;
-}
-
-/*
-** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
-*/
-void sqlite3PcacheClearSyncFlags(PCache *pCache){
- PgHdr *p;
- for(p=pCache->pDirty; p; p=p->pDirtyNext){
- p->flags &= ~PGHDR_NEED_SYNC;
- }
- pCache->pSynced = pCache->pDirtyTail;
-}
-
-/*
-** Change the page number of page p to newPgno.
-*/
-void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
- PCache *pCache = p->pCache;
- assert( p->nRef>0 );
- assert( newPgno>0 );
- assert( sqlite3PcachePageSanity(p) );
- pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
- sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
- p->pgno = newPgno;
- if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
- pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
- }
-}
-
-/*
-** Drop every cache entry whose page number is greater than "pgno". The
-** caller must ensure that there are no outstanding references to any pages
-** other than page 1 with a page number greater than pgno.
-**
-** If there is a reference to page 1 and the pgno parameter passed to this
-** function is 0, then the data area associated with page 1 is zeroed, but
-** the page object is not dropped.
-*/
-void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
- if( pCache->pCache ){
- PgHdr *p;
- PgHdr *pNext;
- pcacheTrace(("%p.TRUNCATE %d\n",pCache,pgno));
- for(p=pCache->pDirty; p; p=pNext){
- pNext = p->pDirtyNext;
- /* This routine never gets call with a positive pgno except right
- ** after sqlite3PcacheCleanAll(). So if there are dirty pages,
- ** it must be that pgno==0.
- */
- assert( p->pgno>0 );
- if( p->pgno>pgno ){
- assert( p->flags&PGHDR_DIRTY );
- sqlite3PcacheMakeClean(p);
- }
- }
- if( pgno==0 && pCache->nRefSum ){
- sqlite3_pcache_page *pPage1;
- pPage1 = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache,1,0);
- if( ALWAYS(pPage1) ){ /* Page 1 is always available in cache, because
- ** pCache->nRefSum>0 */
- memset(pPage1->pBuf, 0, pCache->szPage);
- pgno = 1;
- }
- }
- sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
- }
-}
-
-/*
-** Close a cache.
-*/
-void sqlite3PcacheClose(PCache *pCache){
- assert( pCache->pCache!=0 );
- pcacheTrace(("%p.CLOSE\n",pCache));
- sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
-}
-
-/*
-** Discard the contents of the cache.
-*/
-void sqlite3PcacheClear(PCache *pCache){
- sqlite3PcacheTruncate(pCache, 0);
-}
-
-/*
-** Merge two lists of pages connected by pDirty and in pgno order.
-** Do not bother fixing the pDirtyPrev pointers.
-*/
-static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
- PgHdr result, *pTail;
- pTail = &result;
- assert( pA!=0 && pB!=0 );
- for(;;){
- if( pA->pgno<pB->pgno ){
- pTail->pDirty = pA;
- pTail = pA;
- pA = pA->pDirty;
- if( pA==0 ){
- pTail->pDirty = pB;
- break;
- }
- }else{
- pTail->pDirty = pB;
- pTail = pB;
- pB = pB->pDirty;
- if( pB==0 ){
- pTail->pDirty = pA;
- break;
- }
- }
- }
- return result.pDirty;
-}
-
-/*
-** Sort the list of pages in accending order by pgno. Pages are
-** connected by pDirty pointers. The pDirtyPrev pointers are
-** corrupted by this sort.
-**
-** Since there cannot be more than 2^31 distinct pages in a database,
-** there cannot be more than 31 buckets required by the merge sorter.
-** One extra bucket is added to catch overflow in case something
-** ever changes to make the previous sentence incorrect.
-*/
-#define N_SORT_BUCKET 32
-static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
- PgHdr *a[N_SORT_BUCKET], *p;
- int i;
- memset(a, 0, sizeof(a));
- while( pIn ){
- p = pIn;
- pIn = p->pDirty;
- p->pDirty = 0;
- for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){
- if( a[i]==0 ){
- a[i] = p;
- break;
- }else{
- p = pcacheMergeDirtyList(a[i], p);
- a[i] = 0;
- }
- }
- if( NEVER(i==N_SORT_BUCKET-1) ){
- /* To get here, there need to be 2^(N_SORT_BUCKET) elements in
- ** the input list. But that is impossible.
- */
- a[i] = pcacheMergeDirtyList(a[i], p);
- }
- }
- p = a[0];
- for(i=1; i<N_SORT_BUCKET; i++){
- if( a[i]==0 ) continue;
- p = p ? pcacheMergeDirtyList(p, a[i]) : a[i];
- }
- return p;
-}
-
-/*
-** Return a list of all dirty pages in the cache, sorted by page number.
-*/
-PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
- PgHdr *p;
- for(p=pCache->pDirty; p; p=p->pDirtyNext){
- p->pDirty = p->pDirtyNext;
- }
- return pcacheSortDirtyList(pCache->pDirty);
-}
-
-/*
-** Return the total number of references to all pages held by the cache.
-**
-** This is not the total number of pages referenced, but the sum of the
-** reference count for all pages.
-*/
-int sqlite3PcacheRefCount(PCache *pCache){
- return pCache->nRefSum;
-}
-
-/*
-** Return the number of references to the page supplied as an argument.
-*/
-int sqlite3PcachePageRefcount(PgHdr *p){
- return p->nRef;
-}
-
-/*
-** Return the total number of pages in the cache.
-*/
-int sqlite3PcachePagecount(PCache *pCache){
- assert( pCache->pCache!=0 );
- return sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
-}
-
-#ifdef SQLITE_TEST
-/*
-** Get the suggested cache-size value.
-*/
-int sqlite3PcacheGetCachesize(PCache *pCache){
- return numberOfCachePages(pCache);
-}
-#endif
-
-/*
-** Set the suggested cache-size value.
-*/
-void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
- assert( pCache->pCache!=0 );
- pCache->szCache = mxPage;
- sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
- numberOfCachePages(pCache));
-}
-
-/*
-** Set the suggested cache-spill value. Make no changes if if the
-** argument is zero. Return the effective cache-spill size, which will
-** be the larger of the szSpill and szCache.
-*/
-int sqlite3PcacheSetSpillsize(PCache *p, int mxPage){
- int res;
- assert( p->pCache!=0 );
- if( mxPage ){
- if( mxPage<0 ){
- mxPage = (int)((-1024*(i64)mxPage)/(p->szPage+p->szExtra));
- }
- p->szSpill = mxPage;
- }
- res = numberOfCachePages(p);
- if( res<p->szSpill ) res = p->szSpill;
- return res;
-}
-
-/*
-** Free up as much memory as possible from the page cache.
-*/
-void sqlite3PcacheShrink(PCache *pCache){
- assert( pCache->pCache!=0 );
- sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
-}
-
-/*
-** Return the size of the header added by this middleware layer
-** in the page-cache hierarchy.
-*/
-int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
-
-/*
-** Return the number of dirty pages currently in the cache, as a percentage
-** of the configured cache size.
-*/
-int sqlite3PCachePercentDirty(PCache *pCache){
- PgHdr *pDirty;
- int nDirty = 0;
- int nCache = numberOfCachePages(pCache);
- for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++;
- return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
-}
-
-#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
-/*
-** For all dirty pages currently in the cache, invoke the specified
-** callback. This is only used if the SQLITE_CHECK_PAGES macro is
-** defined.
-*/
-void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
- PgHdr *pDirty;
- for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
- xIter(pDirty);
- }
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache.h
deleted file mode 100644
index bbc2cb45398..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
-** 2008 August 05
-**
-** 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 header file defines the interface that the sqlite page cache
-** subsystem.
-*/
-
-#ifndef _PCACHE_H_
-
-typedef struct PgHdr PgHdr;
-typedef struct PCache PCache;
-
-/*
-** Every page in the cache is controlled by an instance of the following
-** structure.
-*/
-struct PgHdr {
- sqlite3_pcache_page *pPage; /* Pcache object page handle */
- void *pData; /* Page data */
- void *pExtra; /* Extra content */
- PCache *pCache; /* PRIVATE: Cache that owns this page */
- PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
- Pager *pPager; /* The pager this page is part of */
- Pgno pgno; /* Page number for this page */
-#ifdef SQLITE_CHECK_PAGES
- u32 pageHash; /* Hash of page content */
-#endif
- u16 flags; /* PGHDR flags defined below */
-
- /**********************************************************************
- ** Elements above, except pCache, are public. All that follow are
- ** private to pcache.c and should not be accessed by other modules.
- ** pCache is grouped with the public elements for efficiency.
- */
- i16 nRef; /* Number of users of this page */
- PgHdr *pDirtyNext; /* Next element in list of dirty pages */
- PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
- /* NB: pDirtyNext and pDirtyPrev are undefined if the
- ** PgHdr object is not dirty */
-};
-
-/* Bit values for PgHdr.flags */
-#define PGHDR_CLEAN 0x001 /* Page not on the PCache.pDirty list */
-#define PGHDR_DIRTY 0x002 /* Page is on the PCache.pDirty list */
-#define PGHDR_WRITEABLE 0x004 /* Journaled and ready to modify */
-#define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before
- ** writing this page to the database */
-#define PGHDR_DONT_WRITE 0x010 /* Do not write content to disk */
-#define PGHDR_MMAP 0x020 /* This is an mmap page object */
-
-#define PGHDR_WAL_APPEND 0x040 /* Appended to wal file */
-
-/* Initialize and shutdown the page cache subsystem */
-int sqlite3PcacheInitialize(void);
-void sqlite3PcacheShutdown(void);
-
-/* Page cache buffer management:
-** These routines implement SQLITE_CONFIG_PAGECACHE.
-*/
-void sqlite3PCacheBufferSetup(void *, int sz, int n);
-
-/* Create a new pager cache.
-** Under memory stress, invoke xStress to try to make pages clean.
-** Only clean and unpinned pages can be reclaimed.
-*/
-int sqlite3PcacheOpen(
- int szPage, /* Size of every page */
- int szExtra, /* Extra space associated with each page */
- int bPurgeable, /* True if pages are on backing store */
- int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */
- void *pStress, /* Argument to xStress */
- PCache *pToInit /* Preallocated space for the PCache */
-);
-
-/* Modify the page-size after the cache has been created. */
-int sqlite3PcacheSetPageSize(PCache *, int);
-
-/* Return the size in bytes of a PCache object. Used to preallocate
-** storage space.
-*/
-int sqlite3PcacheSize(void);
-
-/* One release per successful fetch. Page is pinned until released.
-** Reference counted.
-*/
-sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag);
-int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**);
-PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage);
-void sqlite3PcacheRelease(PgHdr*);
-
-void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
-void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
-void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
-void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
-void sqlite3PcacheClearWritable(PCache*);
-
-/* Change a page number. Used by incr-vacuum. */
-void sqlite3PcacheMove(PgHdr*, Pgno);
-
-/* Remove all pages with pgno>x. Reset the cache if x==0 */
-void sqlite3PcacheTruncate(PCache*, Pgno x);
-
-/* Get a list of all dirty pages in the cache, sorted by page number */
-PgHdr *sqlite3PcacheDirtyList(PCache*);
-
-/* Reset and close the cache object */
-void sqlite3PcacheClose(PCache*);
-
-/* Clear flags from pages of the page cache */
-void sqlite3PcacheClearSyncFlags(PCache *);
-
-/* Discard the contents of the cache */
-void sqlite3PcacheClear(PCache*);
-
-/* Return the total number of outstanding page references */
-int sqlite3PcacheRefCount(PCache*);
-
-/* Increment the reference count of an existing page */
-void sqlite3PcacheRef(PgHdr*);
-
-int sqlite3PcachePageRefcount(PgHdr*);
-
-/* Return the total number of pages stored in the cache */
-int sqlite3PcachePagecount(PCache*);
-
-#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
-/* Iterate through all dirty pages currently stored in the cache. This
-** interface is only available if SQLITE_CHECK_PAGES is defined when the
-** library is built.
-*/
-void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
-#endif
-
-#if defined(SQLITE_DEBUG)
-/* Check invariants on a PgHdr object */
-int sqlite3PcachePageSanity(PgHdr*);
-#endif
-
-/* Set and get the suggested cache-size for the specified pager-cache.
-**
-** If no global maximum is configured, then the system attempts to limit
-** the total number of pages cached by purgeable pager-caches to the sum
-** of the suggested cache-sizes.
-*/
-void sqlite3PcacheSetCachesize(PCache *, int);
-#ifdef SQLITE_TEST
-int sqlite3PcacheGetCachesize(PCache *);
-#endif
-
-/* Set or get the suggested spill-size for the specified pager-cache.
-**
-** The spill-size is the minimum number of pages in cache before the cache
-** will attempt to spill dirty pages by calling xStress.
-*/
-int sqlite3PcacheSetSpillsize(PCache *, int);
-
-/* Free up as much memory as possible from the page cache */
-void sqlite3PcacheShrink(PCache*);
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-/* Try to return memory used by the pcache module to the main memory heap */
-int sqlite3PcacheReleaseMemory(int);
-#endif
-
-#ifdef SQLITE_TEST
-void sqlite3PcacheStats(int*,int*,int*,int*);
-#endif
-
-void sqlite3PCacheSetDefault(void);
-
-/* Return the header size */
-int sqlite3HeaderSizePcache(void);
-int sqlite3HeaderSizePcache1(void);
-
-/* Number of dirty pages as a percentage of the configured cache size */
-int sqlite3PCachePercentDirty(PCache*);
-
-#endif /* _PCACHE_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache1.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache1.c
deleted file mode 100644
index fc3cbc5abe0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/pcache1.c
+++ /dev/null
@@ -1,1258 +0,0 @@
-/*
-** 2008 November 05
-**
-** 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 the default page cache implementation (the
-** sqlite3_pcache interface). It also contains part of the implementation
-** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
-** If the default page cache implementation is overridden, then neither of
-** these two features are available.
-**
-** A Page cache line looks like this:
-**
-** -------------------------------------------------------------
-** | database page content | PgHdr1 | MemPage | PgHdr |
-** -------------------------------------------------------------
-**
-** The database page content is up front (so that buffer overreads tend to
-** flow harmlessly into the PgHdr1, MemPage, and PgHdr extensions). MemPage
-** is the extension added by the btree.c module containing information such
-** as the database page number and how that database page is used. PgHdr
-** is added by the pcache.c layer and contains information used to keep track
-** of which pages are "dirty". PgHdr1 is an extension added by this
-** module (pcache1.c). The PgHdr1 header is a subclass of sqlite3_pcache_page.
-** PgHdr1 contains information needed to look up a page by its page number.
-** The superclass sqlite3_pcache_page.pBuf points to the start of the
-** database page content and sqlite3_pcache_page.pExtra points to PgHdr.
-**
-** The size of the extension (MemPage+PgHdr+PgHdr1) can be determined at
-** runtime using sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &size). The
-** sizes of the extensions sum to 272 bytes on x64 for 3.8.10, but this
-** size can vary according to architecture, compile-time options, and
-** SQLite library version number.
-**
-** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained
-** using a separate memory allocation from the database page content. This
-** seeks to overcome the "clownshoe" problem (also called "internal
-** fragmentation" in academic literature) of allocating a few bytes more
-** than a power of two with the memory allocator rounding up to the next
-** power of two, and leaving the rounded-up space unused.
-**
-** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates
-** with this module. Information is passed back and forth as PgHdr1 pointers.
-**
-** The pcache.c and pager.c modules deal pointers to PgHdr objects.
-** The btree.c module deals with pointers to MemPage objects.
-**
-** SOURCE OF PAGE CACHE MEMORY:
-**
-** Memory for a page might come from any of three sources:
-**
-** (1) The general-purpose memory allocator - sqlite3Malloc()
-** (2) Global page-cache memory provided using sqlite3_config() with
-** SQLITE_CONFIG_PAGECACHE.
-** (3) PCache-local bulk allocation.
-**
-** The third case is a chunk of heap memory (defaulting to 100 pages worth)
-** that is allocated when the page cache is created. The size of the local
-** bulk allocation can be adjusted using
-**
-** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N).
-**
-** If N is positive, then N pages worth of memory are allocated using a single
-** sqlite3Malloc() call and that memory is used for the first N pages allocated.
-** Or if N is negative, then -1024*N bytes of memory are allocated and used
-** for as many pages as can be accomodated.
-**
-** Only one of (2) or (3) can be used. Once the memory available to (2) or
-** (3) is exhausted, subsequent allocations fail over to the general-purpose
-** memory allocator (1).
-**
-** Earlier versions of SQLite used only methods (1) and (2). But experiments
-** show that method (3) with N==100 provides about a 5% performance boost for
-** common workloads.
-*/
-#include "sqliteInt.h"
-
-typedef struct PCache1 PCache1;
-typedef struct PgHdr1 PgHdr1;
-typedef struct PgFreeslot PgFreeslot;
-typedef struct PGroup PGroup;
-
-/*
-** Each cache entry is represented by an instance of the following
-** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
-** PgHdr1.pCache->szPage bytes is allocated directly before this structure
-** in memory.
-*/
-struct PgHdr1 {
- sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
- unsigned int iKey; /* Key value (page number) */
- u8 isBulkLocal; /* This page from bulk local storage */
- u8 isAnchor; /* This is the PGroup.lru element */
- PgHdr1 *pNext; /* Next in hash table chain */
- PCache1 *pCache; /* Cache that currently owns this page */
- PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
- PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
-};
-
-/*
-** A page is pinned if it is no on the LRU list
-*/
-#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
-#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
-
-/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
-** of one or more PCaches that are able to recycle each other's unpinned
-** pages when they are under memory pressure. A PGroup is an instance of
-** the following object.
-**
-** This page cache implementation works in one of two modes:
-**
-** (1) Every PCache is the sole member of its own PGroup. There is
-** one PGroup per PCache.
-**
-** (2) There is a single global PGroup that all PCaches are a member
-** of.
-**
-** Mode 1 uses more memory (since PCache instances are not able to rob
-** unused pages from other PCaches) but it also operates without a mutex,
-** and is therefore often faster. Mode 2 requires a mutex in order to be
-** threadsafe, but recycles pages more efficiently.
-**
-** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single
-** PGroup which is the pcache1.grp global variable and its mutex is
-** SQLITE_MUTEX_STATIC_LRU.
-*/
-struct PGroup {
- sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */
- unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
- unsigned int nMinPage; /* Sum of nMin for purgeable caches */
- unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
- unsigned int nPurgeable; /* Number of purgeable pages allocated */
- PgHdr1 lru; /* The beginning and end of the LRU list */
-};
-
-/* Each page cache is an instance of the following object. Every
-** open database file (including each in-memory database and each
-** temporary or transient database) has a single page cache which
-** is an instance of this object.
-**
-** Pointers to structures of this type are cast and returned as
-** opaque sqlite3_pcache* handles.
-*/
-struct PCache1 {
- /* Cache configuration parameters. Page size (szPage) and the purgeable
- ** flag (bPurgeable) and the pnPurgeable pointer are all set when the
- ** cache is created and are never changed thereafter. nMax may be
- ** modified at any time by a call to the pcache1Cachesize() method.
- ** The PGroup mutex must be held when accessing nMax.
- */
- PGroup *pGroup; /* PGroup this cache belongs to */
- unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */
- int szPage; /* Size of database content section */
- int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */
- int szAlloc; /* Total size of one pcache line */
- int bPurgeable; /* True if cache is purgeable */
- unsigned int nMin; /* Minimum number of pages reserved */
- unsigned int nMax; /* Configured "cache_size" value */
- unsigned int n90pct; /* nMax*9/10 */
- unsigned int iMaxKey; /* Largest key seen since xTruncate() */
-
- /* Hash table of all pages. The following variables may only be accessed
- ** when the accessor is holding the PGroup mutex.
- */
- unsigned int nRecyclable; /* Number of pages in the LRU list */
- unsigned int nPage; /* Total number of pages in apHash */
- unsigned int nHash; /* Number of slots in apHash[] */
- PgHdr1 **apHash; /* Hash table for fast lookup by key */
- PgHdr1 *pFree; /* List of unused pcache-local pages */
- void *pBulk; /* Bulk memory used by pcache-local */
-};
-
-/*
-** Free slots in the allocator used to divide up the global page cache
-** buffer provided using the SQLITE_CONFIG_PAGECACHE mechanism.
-*/
-struct PgFreeslot {
- PgFreeslot *pNext; /* Next free slot */
-};
-
-/*
-** Global data used by this cache.
-*/
-static SQLITE_WSD struct PCacheGlobal {
- PGroup grp; /* The global PGroup for mode (2) */
-
- /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The
- ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all
- ** fixed at sqlite3_initialize() time and do not require mutex protection.
- ** The nFreeSlot and pFree values do require mutex protection.
- */
- int isInit; /* True if initialized */
- int separateCache; /* Use a new PGroup for each PCache */
- int nInitPage; /* Initial bulk allocation size */
- int szSlot; /* Size of each free slot */
- int nSlot; /* The number of pcache slots */
- int nReserve; /* Try to keep nFreeSlot above this */
- void *pStart, *pEnd; /* Bounds of global page cache memory */
- /* Above requires no mutex. Use mutex below for variable that follow. */
- sqlite3_mutex *mutex; /* Mutex for accessing the following: */
- PgFreeslot *pFree; /* Free page blocks */
- int nFreeSlot; /* Number of unused pcache slots */
- /* The following value requires a mutex to change. We skip the mutex on
- ** reading because (1) most platforms read a 32-bit integer atomically and
- ** (2) even if an incorrect value is read, no great harm is done since this
- ** is really just an optimization. */
- int bUnderPressure; /* True if low on PAGECACHE memory */
-} pcache1_g;
-
-/*
-** All code in this file should access the global structure above via the
-** alias "pcache1". This ensures that the WSD emulation is used when
-** compiling for systems that do not support real WSD.
-*/
-#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
-
-/*
-** Macros to enter and leave the PCache LRU mutex.
-*/
-#if !defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
-# define pcache1EnterMutex(X) assert((X)->mutex==0)
-# define pcache1LeaveMutex(X) assert((X)->mutex==0)
-# define PCACHE1_MIGHT_USE_GROUP_MUTEX 0
-#else
-# define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
-# define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
-# define PCACHE1_MIGHT_USE_GROUP_MUTEX 1
-#endif
-
-/******************************************************************************/
-/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
-
-
-/*
-** This function is called during initialization if a static buffer is
-** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
-** verb to sqlite3_config(). Parameter pBuf points to an allocation large
-** enough to contain 'n' buffers of 'sz' bytes each.
-**
-** This routine is called from sqlite3_initialize() and so it is guaranteed
-** to be serialized already. There is no need for further mutexing.
-*/
-void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
- if( pcache1.isInit ){
- PgFreeslot *p;
- if( pBuf==0 ) sz = n = 0;
- if( n==0 ) sz = 0;
- sz = ROUNDDOWN8(sz);
- pcache1.szSlot = sz;
- pcache1.nSlot = pcache1.nFreeSlot = n;
- pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
- pcache1.pStart = pBuf;
- pcache1.pFree = 0;
- pcache1.bUnderPressure = 0;
- while( n-- ){
- p = (PgFreeslot*)pBuf;
- p->pNext = pcache1.pFree;
- pcache1.pFree = p;
- pBuf = (void*)&((char*)pBuf)[sz];
- }
- pcache1.pEnd = pBuf;
- }
-}
-
-/*
-** Try to initialize the pCache->pFree and pCache->pBulk fields. Return
-** true if pCache->pFree ends up containing one or more free pages.
-*/
-static int pcache1InitBulk(PCache1 *pCache){
- i64 szBulk;
- char *zBulk;
- if( pcache1.nInitPage==0 ) return 0;
- /* Do not bother with a bulk allocation if the cache size very small */
- if( pCache->nMax<3 ) return 0;
- sqlite3BeginBenignMalloc();
- if( pcache1.nInitPage>0 ){
- szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
- }else{
- szBulk = -1024 * (i64)pcache1.nInitPage;
- }
- if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
- szBulk = pCache->szAlloc*(i64)pCache->nMax;
- }
- zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
- sqlite3EndBenignMalloc();
- if( zBulk ){
- int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
- do{
- PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
- pX->page.pBuf = zBulk;
- pX->page.pExtra = &pX[1];
- pX->isBulkLocal = 1;
- pX->isAnchor = 0;
- pX->pNext = pCache->pFree;
- pCache->pFree = pX;
- zBulk += pCache->szAlloc;
- }while( --nBulk );
- }
- return pCache->pFree!=0;
-}
-
-/*
-** Malloc function used within this file to allocate space from the buffer
-** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
-** such buffer exists or there is no space left in it, this function falls
-** back to sqlite3Malloc().
-**
-** Multiple threads can run this routine at the same time. Global variables
-** in pcache1 need to be protected via mutex.
-*/
-static void *pcache1Alloc(int nByte){
- void *p = 0;
- assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
- if( nByte<=pcache1.szSlot ){
- sqlite3_mutex_enter(pcache1.mutex);
- p = (PgHdr1 *)pcache1.pFree;
- if( p ){
- pcache1.pFree = pcache1.pFree->pNext;
- pcache1.nFreeSlot--;
- pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
- assert( pcache1.nFreeSlot>=0 );
- sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
- sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
- }
- sqlite3_mutex_leave(pcache1.mutex);
- }
- if( p==0 ){
- /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get
- ** it from sqlite3Malloc instead.
- */
- p = sqlite3Malloc(nByte);
-#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
- if( p ){
- int sz = sqlite3MallocSize(p);
- sqlite3_mutex_enter(pcache1.mutex);
- sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
- sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
- sqlite3_mutex_leave(pcache1.mutex);
- }
-#endif
- sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
- }
- return p;
-}
-
-/*
-** Free an allocated buffer obtained from pcache1Alloc().
-*/
-static void pcache1Free(void *p){
- if( p==0 ) return;
- if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){
- PgFreeslot *pSlot;
- sqlite3_mutex_enter(pcache1.mutex);
- sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
- pSlot = (PgFreeslot*)p;
- pSlot->pNext = pcache1.pFree;
- pcache1.pFree = pSlot;
- pcache1.nFreeSlot++;
- pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
- assert( pcache1.nFreeSlot<=pcache1.nSlot );
- sqlite3_mutex_leave(pcache1.mutex);
- }else{
- assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
- {
- int nFreed = 0;
- nFreed = sqlite3MallocSize(p);
- sqlite3_mutex_enter(pcache1.mutex);
- sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed);
- sqlite3_mutex_leave(pcache1.mutex);
- }
-#endif
- sqlite3_free(p);
- }
-}
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-/*
-** Return the size of a pcache allocation
-*/
-static int pcache1MemSize(void *p){
- if( p>=pcache1.pStart && p<pcache1.pEnd ){
- return pcache1.szSlot;
- }else{
- int iSize;
- assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
- iSize = sqlite3MallocSize(p);
- sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
- return iSize;
- }
-}
-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
-
-/*
-** Allocate a new page object initially associated with cache pCache.
-*/
-static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
- PgHdr1 *p = 0;
- void *pPg;
-
- assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
- if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){
- p = pCache->pFree;
- pCache->pFree = p->pNext;
- p->pNext = 0;
- }else{
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- /* The group mutex must be released before pcache1Alloc() is called. This
- ** is because it might call sqlite3_release_memory(), which assumes that
- ** this mutex is not held. */
- assert( pcache1.separateCache==0 );
- assert( pCache->pGroup==&pcache1.grp );
- pcache1LeaveMutex(pCache->pGroup);
-#endif
- if( benignMalloc ){ sqlite3BeginBenignMalloc(); }
-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
- pPg = pcache1Alloc(pCache->szPage);
- p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
- if( !pPg || !p ){
- pcache1Free(pPg);
- sqlite3_free(p);
- pPg = 0;
- }
-#else
- pPg = pcache1Alloc(pCache->szAlloc);
- p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
-#endif
- if( benignMalloc ){ sqlite3EndBenignMalloc(); }
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- pcache1EnterMutex(pCache->pGroup);
-#endif
- if( pPg==0 ) return 0;
- p->page.pBuf = pPg;
- p->page.pExtra = &p[1];
- p->isBulkLocal = 0;
- p->isAnchor = 0;
- }
- (*pCache->pnPurgeable)++;
- return p;
-}
-
-/*
-** Free a page object allocated by pcache1AllocPage().
-*/
-static void pcache1FreePage(PgHdr1 *p){
- PCache1 *pCache;
- assert( p!=0 );
- pCache = p->pCache;
- assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
- if( p->isBulkLocal ){
- p->pNext = pCache->pFree;
- pCache->pFree = p;
- }else{
- pcache1Free(p->page.pBuf);
-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
- sqlite3_free(p);
-#endif
- }
- (*pCache->pnPurgeable)--;
-}
-
-/*
-** Malloc function used by SQLite to obtain space from the buffer configured
-** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
-** exists, this function falls back to sqlite3Malloc().
-*/
-void *sqlite3PageMalloc(int sz){
- return pcache1Alloc(sz);
-}
-
-/*
-** Free an allocated buffer obtained from sqlite3PageMalloc().
-*/
-void sqlite3PageFree(void *p){
- pcache1Free(p);
-}
-
-
-/*
-** Return true if it desirable to avoid allocating a new page cache
-** entry.
-**
-** If memory was allocated specifically to the page cache using
-** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then
-** it is desirable to avoid allocating a new page cache entry because
-** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient
-** for all page cache needs and we should not need to spill the
-** allocation onto the heap.
-**
-** Or, the heap is used for all page cache memory but the heap is
-** under memory pressure, then again it is desirable to avoid
-** allocating a new page cache entry in order to avoid stressing
-** the heap even further.
-*/
-static int pcache1UnderMemoryPressure(PCache1 *pCache){
- if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
- return pcache1.bUnderPressure;
- }else{
- return sqlite3HeapNearlyFull();
- }
-}
-
-/******************************************************************************/
-/******** General Implementation Functions ************************************/
-
-/*
-** This function is used to resize the hash table used by the cache passed
-** as the first argument.
-**
-** The PCache mutex must be held when this function is called.
-*/
-static void pcache1ResizeHash(PCache1 *p){
- PgHdr1 **apNew;
- unsigned int nNew;
- unsigned int i;
-
- assert( sqlite3_mutex_held(p->pGroup->mutex) );
-
- nNew = p->nHash*2;
- if( nNew<256 ){
- nNew = 256;
- }
-
- pcache1LeaveMutex(p->pGroup);
- if( p->nHash ){ sqlite3BeginBenignMalloc(); }
- apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
- if( p->nHash ){ sqlite3EndBenignMalloc(); }
- pcache1EnterMutex(p->pGroup);
- if( apNew ){
- for(i=0; i<p->nHash; i++){
- PgHdr1 *pPage;
- PgHdr1 *pNext = p->apHash[i];
- while( (pPage = pNext)!=0 ){
- unsigned int h = pPage->iKey % nNew;
- pNext = pPage->pNext;
- pPage->pNext = apNew[h];
- apNew[h] = pPage;
- }
- }
- sqlite3_free(p->apHash);
- p->apHash = apNew;
- p->nHash = nNew;
- }
-}
-
-/*
-** This function is used internally to remove the page pPage from the
-** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
-** LRU list, then this function is a no-op.
-**
-** The PGroup mutex must be held when this function is called.
-*/
-static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
- assert( pPage!=0 );
- assert( PAGE_IS_UNPINNED(pPage) );
- assert( pPage->pLruNext );
- assert( pPage->pLruPrev );
- assert( sqlite3_mutex_held(pPage->pCache->pGroup->mutex) );
- pPage->pLruPrev->pLruNext = pPage->pLruNext;
- pPage->pLruNext->pLruPrev = pPage->pLruPrev;
- pPage->pLruNext = 0;
- pPage->pLruPrev = 0;
- assert( pPage->isAnchor==0 );
- assert( pPage->pCache->pGroup->lru.isAnchor==1 );
- pPage->pCache->nRecyclable--;
- return pPage;
-}
-
-
-/*
-** Remove the page supplied as an argument from the hash table
-** (PCache1.apHash structure) that it is currently stored in.
-** Also free the page if freePage is true.
-**
-** The PGroup mutex must be held when this function is called.
-*/
-static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){
- unsigned int h;
- PCache1 *pCache = pPage->pCache;
- PgHdr1 **pp;
-
- assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
- h = pPage->iKey % pCache->nHash;
- for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
- *pp = (*pp)->pNext;
-
- pCache->nPage--;
- if( freeFlag ) pcache1FreePage(pPage);
-}
-
-/*
-** If there are currently more than nMaxPage pages allocated, try
-** to recycle pages to reduce the number allocated to nMaxPage.
-*/
-static void pcache1EnforceMaxPage(PCache1 *pCache){
- PGroup *pGroup = pCache->pGroup;
- PgHdr1 *p;
- assert( sqlite3_mutex_held(pGroup->mutex) );
- while( pGroup->nPurgeable>pGroup->nMaxPage
- && (p=pGroup->lru.pLruPrev)->isAnchor==0
- ){
- assert( p->pCache->pGroup==pGroup );
- assert( PAGE_IS_UNPINNED(p) );
- pcache1PinPage(p);
- pcache1RemoveFromHash(p, 1);
- }
- if( pCache->nPage==0 && pCache->pBulk ){
- sqlite3_free(pCache->pBulk);
- pCache->pBulk = pCache->pFree = 0;
- }
-}
-
-/*
-** Discard all pages from cache pCache with a page number (key value)
-** greater than or equal to iLimit. Any pinned pages that meet this
-** criteria are unpinned before they are discarded.
-**
-** The PCache mutex must be held when this function is called.
-*/
-static void pcache1TruncateUnsafe(
- PCache1 *pCache, /* The cache to truncate */
- unsigned int iLimit /* Drop pages with this pgno or larger */
-){
- TESTONLY( int nPage = 0; ) /* To assert pCache->nPage is correct */
- unsigned int h, iStop;
- assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
- assert( pCache->iMaxKey >= iLimit );
- assert( pCache->nHash > 0 );
- if( pCache->iMaxKey - iLimit < pCache->nHash ){
- /* If we are just shaving the last few pages off the end of the
- ** cache, then there is no point in scanning the entire hash table.
- ** Only scan those hash slots that might contain pages that need to
- ** be removed. */
- h = iLimit % pCache->nHash;
- iStop = pCache->iMaxKey % pCache->nHash;
- TESTONLY( nPage = -10; ) /* Disable the pCache->nPage validity check */
- }else{
- /* This is the general case where many pages are being removed.
- ** It is necessary to scan the entire hash table */
- h = pCache->nHash/2;
- iStop = h - 1;
- }
- for(;;){
- PgHdr1 **pp;
- PgHdr1 *pPage;
- assert( h<pCache->nHash );
- pp = &pCache->apHash[h];
- while( (pPage = *pp)!=0 ){
- if( pPage->iKey>=iLimit ){
- pCache->nPage--;
- *pp = pPage->pNext;
- if( PAGE_IS_UNPINNED(pPage) ) pcache1PinPage(pPage);
- pcache1FreePage(pPage);
- }else{
- pp = &pPage->pNext;
- TESTONLY( if( nPage>=0 ) nPage++; )
- }
- }
- if( h==iStop ) break;
- h = (h+1) % pCache->nHash;
- }
- assert( nPage<0 || pCache->nPage==(unsigned)nPage );
-}
-
-/******************************************************************************/
-/******** sqlite3_pcache Methods **********************************************/
-
-/*
-** Implementation of the sqlite3_pcache.xInit method.
-*/
-static int pcache1Init(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- assert( pcache1.isInit==0 );
- memset(&pcache1, 0, sizeof(pcache1));
-
-
- /*
- ** The pcache1.separateCache variable is true if each PCache has its own
- ** private PGroup (mode-1). pcache1.separateCache is false if the single
- ** PGroup in pcache1.grp is used for all page caches (mode-2).
- **
- ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
- **
- ** * Use a unified cache in single-threaded applications that have
- ** configured a start-time buffer for use as page-cache memory using
- ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL
- ** pBuf argument.
- **
- ** * Otherwise use separate caches (mode-1)
- */
-#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
- pcache1.separateCache = 0;
-#elif SQLITE_THREADSAFE
- pcache1.separateCache = sqlite3GlobalConfig.pPage==0
- || sqlite3GlobalConfig.bCoreMutex>0;
-#else
- pcache1.separateCache = sqlite3GlobalConfig.pPage==0;
-#endif
-
-#if SQLITE_THREADSAFE
- if( sqlite3GlobalConfig.bCoreMutex ){
- pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU);
- pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM);
- }
-#endif
- if( pcache1.separateCache
- && sqlite3GlobalConfig.nPage!=0
- && sqlite3GlobalConfig.pPage==0
- ){
- pcache1.nInitPage = sqlite3GlobalConfig.nPage;
- }else{
- pcache1.nInitPage = 0;
- }
- pcache1.grp.mxPinned = 10;
- pcache1.isInit = 1;
- return SQLITE_OK;
-}
-
-/*
-** Implementation of the sqlite3_pcache.xShutdown method.
-** Note that the static mutex allocated in xInit does
-** not need to be freed.
-*/
-static void pcache1Shutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- assert( pcache1.isInit!=0 );
- memset(&pcache1, 0, sizeof(pcache1));
-}
-
-/* forward declaration */
-static void pcache1Destroy(sqlite3_pcache *p);
-
-/*
-** Implementation of the sqlite3_pcache.xCreate method.
-**
-** Allocate a new cache.
-*/
-static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
- PCache1 *pCache; /* The newly created page cache */
- PGroup *pGroup; /* The group the new page cache will belong to */
- int sz; /* Bytes of memory required to allocate the new cache */
-
- assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
- assert( szExtra < 300 );
-
- sz = sizeof(PCache1) + sizeof(PGroup)*pcache1.separateCache;
- pCache = (PCache1 *)sqlite3MallocZero(sz);
- if( pCache ){
- if( pcache1.separateCache ){
- pGroup = (PGroup*)&pCache[1];
- pGroup->mxPinned = 10;
- }else{
- pGroup = &pcache1.grp;
- }
- if( pGroup->lru.isAnchor==0 ){
- pGroup->lru.isAnchor = 1;
- pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru;
- }
- pCache->pGroup = pGroup;
- pCache->szPage = szPage;
- pCache->szExtra = szExtra;
- pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1));
- pCache->bPurgeable = (bPurgeable ? 1 : 0);
- pcache1EnterMutex(pGroup);
- pcache1ResizeHash(pCache);
- if( bPurgeable ){
- pCache->nMin = 10;
- pGroup->nMinPage += pCache->nMin;
- pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
- pCache->pnPurgeable = &pGroup->nPurgeable;
- }else{
- static unsigned int dummyCurrentPage;
- pCache->pnPurgeable = &dummyCurrentPage;
- }
- pcache1LeaveMutex(pGroup);
- if( pCache->nHash==0 ){
- pcache1Destroy((sqlite3_pcache*)pCache);
- pCache = 0;
- }
- }
- return (sqlite3_pcache *)pCache;
-}
-
-/*
-** Implementation of the sqlite3_pcache.xCachesize method.
-**
-** Configure the cache_size limit for a cache.
-*/
-static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
- PCache1 *pCache = (PCache1 *)p;
- if( pCache->bPurgeable ){
- PGroup *pGroup = pCache->pGroup;
- pcache1EnterMutex(pGroup);
- pGroup->nMaxPage += (nMax - pCache->nMax);
- pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
- pCache->nMax = nMax;
- pCache->n90pct = pCache->nMax*9/10;
- pcache1EnforceMaxPage(pCache);
- pcache1LeaveMutex(pGroup);
- }
-}
-
-/*
-** Implementation of the sqlite3_pcache.xShrink method.
-**
-** Free up as much memory as possible.
-*/
-static void pcache1Shrink(sqlite3_pcache *p){
- PCache1 *pCache = (PCache1*)p;
- if( pCache->bPurgeable ){
- PGroup *pGroup = pCache->pGroup;
- int savedMaxPage;
- pcache1EnterMutex(pGroup);
- savedMaxPage = pGroup->nMaxPage;
- pGroup->nMaxPage = 0;
- pcache1EnforceMaxPage(pCache);
- pGroup->nMaxPage = savedMaxPage;
- pcache1LeaveMutex(pGroup);
- }
-}
-
-/*
-** Implementation of the sqlite3_pcache.xPagecount method.
-*/
-static int pcache1Pagecount(sqlite3_pcache *p){
- int n;
- PCache1 *pCache = (PCache1*)p;
- pcache1EnterMutex(pCache->pGroup);
- n = pCache->nPage;
- pcache1LeaveMutex(pCache->pGroup);
- return n;
-}
-
-
-/*
-** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described
-** in the header of the pcache1Fetch() procedure.
-**
-** This steps are broken out into a separate procedure because they are
-** usually not needed, and by avoiding the stack initialization required
-** for these steps, the main pcache1Fetch() procedure can run faster.
-*/
-static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
- PCache1 *pCache,
- unsigned int iKey,
- int createFlag
-){
- unsigned int nPinned;
- PGroup *pGroup = pCache->pGroup;
- PgHdr1 *pPage = 0;
-
- /* Step 3: Abort if createFlag is 1 but the cache is nearly full */
- assert( pCache->nPage >= pCache->nRecyclable );
- nPinned = pCache->nPage - pCache->nRecyclable;
- assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
- assert( pCache->n90pct == pCache->nMax*9/10 );
- if( createFlag==1 && (
- nPinned>=pGroup->mxPinned
- || nPinned>=pCache->n90pct
- || (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable<nPinned)
- )){
- return 0;
- }
-
- if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache);
- assert( pCache->nHash>0 && pCache->apHash );
-
- /* Step 4. Try to recycle a page. */
- if( pCache->bPurgeable
- && !pGroup->lru.pLruPrev->isAnchor
- && ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache))
- ){
- PCache1 *pOther;
- pPage = pGroup->lru.pLruPrev;
- assert( PAGE_IS_UNPINNED(pPage) );
- pcache1RemoveFromHash(pPage, 0);
- pcache1PinPage(pPage);
- pOther = pPage->pCache;
- if( pOther->szAlloc != pCache->szAlloc ){
- pcache1FreePage(pPage);
- pPage = 0;
- }else{
- pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable);
- }
- }
-
- /* Step 5. If a usable page buffer has still not been found,
- ** attempt to allocate a new one.
- */
- if( !pPage ){
- pPage = pcache1AllocPage(pCache, createFlag==1);
- }
-
- if( pPage ){
- unsigned int h = iKey % pCache->nHash;
- pCache->nPage++;
- pPage->iKey = iKey;
- pPage->pNext = pCache->apHash[h];
- pPage->pCache = pCache;
- pPage->pLruPrev = 0;
- pPage->pLruNext = 0;
- *(void **)pPage->page.pExtra = 0;
- pCache->apHash[h] = pPage;
- if( iKey>pCache->iMaxKey ){
- pCache->iMaxKey = iKey;
- }
- }
- return pPage;
-}
-
-/*
-** Implementation of the sqlite3_pcache.xFetch method.
-**
-** Fetch a page by key value.
-**
-** Whether or not a new page may be allocated by this function depends on
-** the value of the createFlag argument. 0 means do not allocate a new
-** page. 1 means allocate a new page if space is easily available. 2
-** means to try really hard to allocate a new page.
-**
-** For a non-purgeable cache (a cache used as the storage for an in-memory
-** database) there is really no difference between createFlag 1 and 2. So
-** the calling function (pcache.c) will never have a createFlag of 1 on
-** a non-purgeable cache.
-**
-** There are three different approaches to obtaining space for a page,
-** depending on the value of parameter createFlag (which may be 0, 1 or 2).
-**
-** 1. Regardless of the value of createFlag, the cache is searched for a
-** copy of the requested page. If one is found, it is returned.
-**
-** 2. If createFlag==0 and the page is not already in the cache, NULL is
-** returned.
-**
-** 3. If createFlag is 1, and the page is not already in the cache, then
-** return NULL (do not allocate a new page) if any of the following
-** conditions are true:
-**
-** (a) the number of pages pinned by the cache is greater than
-** PCache1.nMax, or
-**
-** (b) the number of pages pinned by the cache is greater than
-** the sum of nMax for all purgeable caches, less the sum of
-** nMin for all other purgeable caches, or
-**
-** 4. If none of the first three conditions apply and the cache is marked
-** as purgeable, and if one of the following is true:
-**
-** (a) The number of pages allocated for the cache is already
-** PCache1.nMax, or
-**
-** (b) The number of pages allocated for all purgeable caches is
-** already equal to or greater than the sum of nMax for all
-** purgeable caches,
-**
-** (c) The system is under memory pressure and wants to avoid
-** unnecessary pages cache entry allocations
-**
-** then attempt to recycle a page from the LRU list. If it is the right
-** size, return the recycled buffer. Otherwise, free the buffer and
-** proceed to step 5.
-**
-** 5. Otherwise, allocate and return a new page buffer.
-**
-** There are two versions of this routine. pcache1FetchWithMutex() is
-** the general case. pcache1FetchNoMutex() is a faster implementation for
-** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper
-** invokes the appropriate routine.
-*/
-static PgHdr1 *pcache1FetchNoMutex(
- sqlite3_pcache *p,
- unsigned int iKey,
- int createFlag
-){
- PCache1 *pCache = (PCache1 *)p;
- PgHdr1 *pPage = 0;
-
- /* Step 1: Search the hash table for an existing entry. */
- pPage = pCache->apHash[iKey % pCache->nHash];
- while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; }
-
- /* Step 2: If the page was found in the hash table, then return it.
- ** If the page was not in the hash table and createFlag is 0, abort.
- ** Otherwise (page not in hash and createFlag!=0) continue with
- ** subsequent steps to try to create the page. */
- if( pPage ){
- if( PAGE_IS_UNPINNED(pPage) ){
- return pcache1PinPage(pPage);
- }else{
- return pPage;
- }
- }else if( createFlag ){
- /* Steps 3, 4, and 5 implemented by this subroutine */
- return pcache1FetchStage2(pCache, iKey, createFlag);
- }else{
- return 0;
- }
-}
-#if PCACHE1_MIGHT_USE_GROUP_MUTEX
-static PgHdr1 *pcache1FetchWithMutex(
- sqlite3_pcache *p,
- unsigned int iKey,
- int createFlag
-){
- PCache1 *pCache = (PCache1 *)p;
- PgHdr1 *pPage;
-
- pcache1EnterMutex(pCache->pGroup);
- pPage = pcache1FetchNoMutex(p, iKey, createFlag);
- assert( pPage==0 || pCache->iMaxKey>=iKey );
- pcache1LeaveMutex(pCache->pGroup);
- return pPage;
-}
-#endif
-static sqlite3_pcache_page *pcache1Fetch(
- sqlite3_pcache *p,
- unsigned int iKey,
- int createFlag
-){
-#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG)
- PCache1 *pCache = (PCache1 *)p;
-#endif
-
- assert( offsetof(PgHdr1,page)==0 );
- assert( pCache->bPurgeable || createFlag!=1 );
- assert( pCache->bPurgeable || pCache->nMin==0 );
- assert( pCache->bPurgeable==0 || pCache->nMin==10 );
- assert( pCache->nMin==0 || pCache->bPurgeable );
- assert( pCache->nHash>0 );
-#if PCACHE1_MIGHT_USE_GROUP_MUTEX
- if( pCache->pGroup->mutex ){
- return (sqlite3_pcache_page*)pcache1FetchWithMutex(p, iKey, createFlag);
- }else
-#endif
- {
- return (sqlite3_pcache_page*)pcache1FetchNoMutex(p, iKey, createFlag);
- }
-}
-
-
-/*
-** Implementation of the sqlite3_pcache.xUnpin method.
-**
-** Mark a page as unpinned (eligible for asynchronous recycling).
-*/
-static void pcache1Unpin(
- sqlite3_pcache *p,
- sqlite3_pcache_page *pPg,
- int reuseUnlikely
-){
- PCache1 *pCache = (PCache1 *)p;
- PgHdr1 *pPage = (PgHdr1 *)pPg;
- PGroup *pGroup = pCache->pGroup;
-
- assert( pPage->pCache==pCache );
- pcache1EnterMutex(pGroup);
-
- /* It is an error to call this function if the page is already
- ** part of the PGroup LRU list.
- */
- assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
- assert( PAGE_IS_PINNED(pPage) );
-
- if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
- pcache1RemoveFromHash(pPage, 1);
- }else{
- /* Add the page to the PGroup LRU list. */
- PgHdr1 **ppFirst = &pGroup->lru.pLruNext;
- pPage->pLruPrev = &pGroup->lru;
- (pPage->pLruNext = *ppFirst)->pLruPrev = pPage;
- *ppFirst = pPage;
- pCache->nRecyclable++;
- }
-
- pcache1LeaveMutex(pCache->pGroup);
-}
-
-/*
-** Implementation of the sqlite3_pcache.xRekey method.
-*/
-static void pcache1Rekey(
- sqlite3_pcache *p,
- sqlite3_pcache_page *pPg,
- unsigned int iOld,
- unsigned int iNew
-){
- PCache1 *pCache = (PCache1 *)p;
- PgHdr1 *pPage = (PgHdr1 *)pPg;
- PgHdr1 **pp;
- unsigned int h;
- assert( pPage->iKey==iOld );
- assert( pPage->pCache==pCache );
-
- pcache1EnterMutex(pCache->pGroup);
-
- h = iOld%pCache->nHash;
- pp = &pCache->apHash[h];
- while( (*pp)!=pPage ){
- pp = &(*pp)->pNext;
- }
- *pp = pPage->pNext;
-
- h = iNew%pCache->nHash;
- pPage->iKey = iNew;
- pPage->pNext = pCache->apHash[h];
- pCache->apHash[h] = pPage;
- if( iNew>pCache->iMaxKey ){
- pCache->iMaxKey = iNew;
- }
-
- pcache1LeaveMutex(pCache->pGroup);
-}
-
-/*
-** Implementation of the sqlite3_pcache.xTruncate method.
-**
-** Discard all unpinned pages in the cache with a page number equal to
-** or greater than parameter iLimit. Any pinned pages with a page number
-** equal to or greater than iLimit are implicitly unpinned.
-*/
-static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
- PCache1 *pCache = (PCache1 *)p;
- pcache1EnterMutex(pCache->pGroup);
- if( iLimit<=pCache->iMaxKey ){
- pcache1TruncateUnsafe(pCache, iLimit);
- pCache->iMaxKey = iLimit-1;
- }
- pcache1LeaveMutex(pCache->pGroup);
-}
-
-/*
-** Implementation of the sqlite3_pcache.xDestroy method.
-**
-** Destroy a cache allocated using pcache1Create().
-*/
-static void pcache1Destroy(sqlite3_pcache *p){
- PCache1 *pCache = (PCache1 *)p;
- PGroup *pGroup = pCache->pGroup;
- assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
- pcache1EnterMutex(pGroup);
- if( pCache->nPage ) pcache1TruncateUnsafe(pCache, 0);
- assert( pGroup->nMaxPage >= pCache->nMax );
- pGroup->nMaxPage -= pCache->nMax;
- assert( pGroup->nMinPage >= pCache->nMin );
- pGroup->nMinPage -= pCache->nMin;
- pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
- pcache1EnforceMaxPage(pCache);
- pcache1LeaveMutex(pGroup);
- sqlite3_free(pCache->pBulk);
- sqlite3_free(pCache->apHash);
- sqlite3_free(pCache);
-}
-
-/*
-** This function is called during initialization (sqlite3_initialize()) to
-** install the default pluggable cache module, assuming the user has not
-** already provided an alternative.
-*/
-void sqlite3PCacheSetDefault(void){
- static const sqlite3_pcache_methods2 defaultMethods = {
- 1, /* iVersion */
- 0, /* pArg */
- pcache1Init, /* xInit */
- pcache1Shutdown, /* xShutdown */
- pcache1Create, /* xCreate */
- pcache1Cachesize, /* xCachesize */
- pcache1Pagecount, /* xPagecount */
- pcache1Fetch, /* xFetch */
- pcache1Unpin, /* xUnpin */
- pcache1Rekey, /* xRekey */
- pcache1Truncate, /* xTruncate */
- pcache1Destroy, /* xDestroy */
- pcache1Shrink /* xShrink */
- };
- sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
-}
-
-/*
-** Return the size of the header on each page of this PCACHE implementation.
-*/
-int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
-
-/*
-** Return the global mutex used by this PCACHE implementation. The
-** sqlite3_status() routine needs access to this mutex.
-*/
-sqlite3_mutex *sqlite3Pcache1Mutex(void){
- return pcache1.mutex;
-}
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-/*
-** This function is called to free superfluous dynamically allocated memory
-** held by the pager system. Memory in use by any SQLite pager allocated
-** by the current thread may be sqlite3_free()ed.
-**
-** nReq is the number of bytes of memory required. Once this much has
-** been released, the function returns. The return value is the total number
-** of bytes of memory released.
-*/
-int sqlite3PcacheReleaseMemory(int nReq){
- int nFree = 0;
- assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
- assert( sqlite3_mutex_notheld(pcache1.mutex) );
- if( sqlite3GlobalConfig.pPage==0 ){
- PgHdr1 *p;
- pcache1EnterMutex(&pcache1.grp);
- while( (nReq<0 || nFree<nReq)
- && (p=pcache1.grp.lru.pLruPrev)!=0
- && p->isAnchor==0
- ){
- nFree += pcache1MemSize(p->page.pBuf);
-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
- nFree += sqlite3MemSize(p);
-#endif
- assert( PAGE_IS_UNPINNED(p) );
- pcache1PinPage(p);
- pcache1RemoveFromHash(p, 1);
- }
- pcache1LeaveMutex(&pcache1.grp);
- }
- return nFree;
-}
-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
-
-#ifdef SQLITE_TEST
-/*
-** This function is used by test procedures to inspect the internal state
-** of the global cache.
-*/
-void sqlite3PcacheStats(
- int *pnCurrent, /* OUT: Total number of pages cached */
- int *pnMax, /* OUT: Global maximum cache size */
- int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
- int *pnRecyclable /* OUT: Total number of pages available for recycling */
-){
- PgHdr1 *p;
- int nRecyclable = 0;
- for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){
- assert( PAGE_IS_UNPINNED(p) );
- nRecyclable++;
- }
- *pnCurrent = pcache1.grp.nPurgeable;
- *pnMax = (int)pcache1.grp.nMaxPage;
- *pnMin = (int)pcache1.grp.nMinPage;
- *pnRecyclable = nRecyclable;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/pragma.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/pragma.c
deleted file mode 100644
index 4699c96a1eb..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/pragma.c
+++ /dev/null
@@ -1,2488 +0,0 @@
-/*
-** 2003 April 6
-**
-** 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 contains code used to implement the PRAGMA command.
-*/
-#include "sqliteInt.h"
-
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-# if defined(__APPLE__)
-# define SQLITE_ENABLE_LOCKING_STYLE 1
-# else
-# define SQLITE_ENABLE_LOCKING_STYLE 0
-# endif
-#endif
-
-/***************************************************************************
-** The "pragma.h" include file is an automatically generated file that
-** that includes the PragType_XXXX macro definitions and the aPragmaName[]
-** object. This ensures that the aPragmaName[] table is arranged in
-** lexicographical order to facility a binary search of the pragma name.
-** Do not edit pragma.h directly. Edit and rerun the script in at
-** ../tool/mkpragmatab.tcl. */
-#include "pragma.h"
-
-/*
-** Interpret the given string as a safety level. Return 0 for OFF,
-** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or
-** unrecognized string argument. The FULL and EXTRA option is disallowed
-** if the omitFull parameter it 1.
-**
-** Note that the values returned are one less that the values that
-** should be passed into sqlite3BtreeSetSafetyLevel(). The is done
-** to support legacy SQL code. The safety level used to be boolean
-** and older scripts may have used numbers 0 for OFF and 1 for ON.
-*/
-static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){
- /* 123456789 123456789 123 */
- static const char zText[] = "onoffalseyestruextrafull";
- static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 15, 20};
- static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 5, 4};
- static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 3, 2};
- /* on no off false yes true extra full */
- int i, n;
- if( sqlite3Isdigit(*z) ){
- return (u8)sqlite3Atoi(z);
- }
- n = sqlite3Strlen30(z);
- for(i=0; i<ArraySize(iLength); i++){
- if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0
- && (!omitFull || iValue[i]<=1)
- ){
- return iValue[i];
- }
- }
- return dflt;
-}
-
-/*
-** Interpret the given string as a boolean value.
-*/
-u8 sqlite3GetBoolean(const char *z, u8 dflt){
- return getSafetyLevel(z,1,dflt)!=0;
-}
-
-/* The sqlite3GetBoolean() function is used by other modules but the
-** remainder of this file is specific to PRAGMA processing. So omit
-** the rest of the file if PRAGMAs are omitted from the build.
-*/
-#if !defined(SQLITE_OMIT_PRAGMA)
-
-/*
-** Interpret the given string as a locking mode value.
-*/
-static int getLockingMode(const char *z){
- if( z ){
- if( 0==sqlite3StrICmp(z, "exclusive") ) return PAGER_LOCKINGMODE_EXCLUSIVE;
- if( 0==sqlite3StrICmp(z, "normal") ) return PAGER_LOCKINGMODE_NORMAL;
- }
- return PAGER_LOCKINGMODE_QUERY;
-}
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
-/*
-** Interpret the given string as an auto-vacuum mode value.
-**
-** The following strings, "none", "full" and "incremental" are
-** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively.
-*/
-static int getAutoVacuum(const char *z){
- int i;
- if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE;
- if( 0==sqlite3StrICmp(z, "full") ) return BTREE_AUTOVACUUM_FULL;
- if( 0==sqlite3StrICmp(z, "incremental") ) return BTREE_AUTOVACUUM_INCR;
- i = sqlite3Atoi(z);
- return (u8)((i>=0&&i<=2)?i:0);
-}
-#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */
-
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-/*
-** Interpret the given string as a temp db location. Return 1 for file
-** backed temporary databases, 2 for the Red-Black tree in memory database
-** and 0 to use the compile-time default.
-*/
-static int getTempStore(const char *z){
- if( z[0]>='0' && z[0]<='2' ){
- return z[0] - '0';
- }else if( sqlite3StrICmp(z, "file")==0 ){
- return 1;
- }else if( sqlite3StrICmp(z, "memory")==0 ){
- return 2;
- }else{
- return 0;
- }
-}
-#endif /* SQLITE_PAGER_PRAGMAS */
-
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-/*
-** Invalidate temp storage, either when the temp storage is changed
-** from default, or when 'file' and the temp_store_directory has changed
-*/
-static int invalidateTempStorage(Parse *pParse){
- sqlite3 *db = pParse->db;
- if( db->aDb[1].pBt!=0 ){
- if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){
- sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
- "from within a transaction");
- return SQLITE_ERROR;
- }
- sqlite3BtreeClose(db->aDb[1].pBt);
- db->aDb[1].pBt = 0;
- sqlite3ResetAllSchemasOfConnection(db);
- }
- return SQLITE_OK;
-}
-#endif /* SQLITE_PAGER_PRAGMAS */
-
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-/*
-** If the TEMP database is open, close it and mark the database schema
-** as needing reloading. This must be done when using the SQLITE_TEMP_STORE
-** or DEFAULT_TEMP_STORE pragmas.
-*/
-static int changeTempStorage(Parse *pParse, const char *zStorageType){
- int ts = getTempStore(zStorageType);
- sqlite3 *db = pParse->db;
- if( db->temp_store==ts ) return SQLITE_OK;
- if( invalidateTempStorage( pParse ) != SQLITE_OK ){
- return SQLITE_ERROR;
- }
- db->temp_store = (u8)ts;
- return SQLITE_OK;
-}
-#endif /* SQLITE_PAGER_PRAGMAS */
-
-/*
-** Set result column names for a pragma.
-*/
-static void setPragmaResultColumnNames(
- Vdbe *v, /* The query under construction */
- const PragmaName *pPragma /* The pragma */
-){
- u8 n = pPragma->nPragCName;
- sqlite3VdbeSetNumCols(v, n==0 ? 1 : n);
- if( n==0 ){
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, pPragma->zName, SQLITE_STATIC);
- }else{
- int i, j;
- for(i=0, j=pPragma->iPragCName; i<n; i++, j++){
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, pragCName[j], SQLITE_STATIC);
- }
- }
-}
-
-/*
-** Generate code to return a single integer value.
-*/
-static void returnSingleInt(Vdbe *v, i64 value){
- sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, 1, 0, (const u8*)&value, P4_INT64);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
-}
-
-/*
-** Generate code to return a single text value.
-*/
-static void returnSingleText(
- Vdbe *v, /* Prepared statement under construction */
- const char *zValue /* Value to be returned */
-){
- if( zValue ){
- sqlite3VdbeLoadString(v, 1, (const char*)zValue);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- }
-}
-
-
-/*
-** Set the safety_level and pager flags for pager iDb. Or if iDb<0
-** set these values for all pagers.
-*/
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-static void setAllPagerFlags(sqlite3 *db){
- if( db->autoCommit ){
- Db *pDb = db->aDb;
- int n = db->nDb;
- assert( SQLITE_FullFSync==PAGER_FULLFSYNC );
- assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC );
- assert( SQLITE_CacheSpill==PAGER_CACHESPILL );
- assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL)
- == PAGER_FLAGS_MASK );
- assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level );
- while( (n--) > 0 ){
- if( pDb->pBt ){
- sqlite3BtreeSetPagerFlags(pDb->pBt,
- pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) );
- }
- pDb++;
- }
- }
-}
-#else
-# define setAllPagerFlags(X) /* no-op */
-#endif
-
-
-/*
-** Return a human-readable name for a constraint resolution action.
-*/
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-static const char *actionName(u8 action){
- const char *zName;
- switch( action ){
- case OE_SetNull: zName = "SET NULL"; break;
- case OE_SetDflt: zName = "SET DEFAULT"; break;
- case OE_Cascade: zName = "CASCADE"; break;
- case OE_Restrict: zName = "RESTRICT"; break;
- default: zName = "NO ACTION";
- assert( action==OE_None ); break;
- }
- return zName;
-}
-#endif
-
-
-/*
-** Parameter eMode must be one of the PAGER_JOURNALMODE_XXX constants
-** defined in pager.h. This function returns the associated lowercase
-** journal-mode name.
-*/
-const char *sqlite3JournalModename(int eMode){
- static char * const azModeName[] = {
- "delete", "persist", "off", "truncate", "memory"
-#ifndef SQLITE_OMIT_WAL
- , "wal"
-#endif
- };
- assert( PAGER_JOURNALMODE_DELETE==0 );
- assert( PAGER_JOURNALMODE_PERSIST==1 );
- assert( PAGER_JOURNALMODE_OFF==2 );
- assert( PAGER_JOURNALMODE_TRUNCATE==3 );
- assert( PAGER_JOURNALMODE_MEMORY==4 );
- assert( PAGER_JOURNALMODE_WAL==5 );
- assert( eMode>=0 && eMode<=ArraySize(azModeName) );
-
- if( eMode==ArraySize(azModeName) ) return 0;
- return azModeName[eMode];
-}
-
-/*
-** Locate a pragma in the aPragmaName[] array.
-*/
-static const PragmaName *pragmaLocate(const char *zName){
- int upr, lwr, mid = 0, rc;
- lwr = 0;
- upr = ArraySize(aPragmaName)-1;
- while( lwr<=upr ){
- mid = (lwr+upr)/2;
- rc = sqlite3_stricmp(zName, aPragmaName[mid].zName);
- if( rc==0 ) break;
- if( rc<0 ){
- upr = mid - 1;
- }else{
- lwr = mid + 1;
- }
- }
- return lwr>upr ? 0 : &aPragmaName[mid];
-}
-
-/*
-** Helper subroutine for PRAGMA integrity_check:
-**
-** Generate code to output a single-column result row with a value of the
-** string held in register 3. Decrement the result count in register 1
-** and halt if the maximum number of result rows have been issued.
-*/
-static int integrityCheckResultRow(Vdbe *v){
- int addr;
- sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
- addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
- VdbeCoverage(v);
- sqlite3VdbeAddOp0(v, OP_Halt);
- return addr;
-}
-
-/*
-** Process a pragma statement.
-**
-** Pragmas are of this form:
-**
-** PRAGMA [schema.]id [= value]
-**
-** The identifier might also be a string. The value is a string, and
-** identifier, or a number. If minusFlag is true, then the value is
-** a number that was preceded by a minus sign.
-**
-** If the left side is "database.id" then pId1 is the database name
-** and pId2 is the id. If the left side is just "id" then pId1 is the
-** id and pId2 is any empty string.
-*/
-void sqlite3Pragma(
- Parse *pParse,
- Token *pId1, /* First part of [schema.]id field */
- Token *pId2, /* Second part of [schema.]id field, or NULL */
- Token *pValue, /* Token for <value>, or NULL */
- int minusFlag /* True if a '-' sign preceded <value> */
-){
- char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */
- char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */
- const char *zDb = 0; /* The database name */
- Token *pId; /* Pointer to <id> token */
- char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
- int iDb; /* Database index for <database> */
- int rc; /* return value form SQLITE_FCNTL_PRAGMA */
- sqlite3 *db = pParse->db; /* The database connection */
- Db *pDb; /* The specific database being pragmaed */
- Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */
- const PragmaName *pPragma; /* The pragma */
-
- if( v==0 ) return;
- sqlite3VdbeRunOnlyOnce(v);
- pParse->nMem = 2;
-
- /* Interpret the [schema.] part of the pragma statement. iDb is the
- ** index of the database this pragma is being applied to in db.aDb[]. */
- iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId);
- if( iDb<0 ) return;
- pDb = &db->aDb[iDb];
-
- /* If the temp database has been explicitly named as part of the
- ** pragma, make sure it is open.
- */
- if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){
- return;
- }
-
- zLeft = sqlite3NameFromToken(db, pId);
- if( !zLeft ) return;
- if( minusFlag ){
- zRight = sqlite3MPrintf(db, "-%T", pValue);
- }else{
- zRight = sqlite3NameFromToken(db, pValue);
- }
-
- assert( pId2 );
- zDb = pId2->n>0 ? pDb->zDbSName : 0;
- if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
- goto pragma_out;
- }
-
- /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
- ** connection. If it returns SQLITE_OK, then assume that the VFS
- ** handled the pragma and generate a no-op prepared statement.
- **
- ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed,
- ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file
- ** object corresponding to the database file to which the pragma
- ** statement refers.
- **
- ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
- ** file control is an array of pointers to strings (char**) in which the
- ** second element of the array is the name of the pragma and the third
- ** element is the argument to the pragma or NULL if the pragma has no
- ** argument.
- */
- aFcntl[0] = 0;
- aFcntl[1] = zLeft;
- aFcntl[2] = zRight;
- aFcntl[3] = 0;
- db->busyHandler.nBusy = 0;
- rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
- if( rc==SQLITE_OK ){
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT);
- returnSingleText(v, aFcntl[0]);
- sqlite3_free(aFcntl[0]);
- goto pragma_out;
- }
- if( rc!=SQLITE_NOTFOUND ){
- if( aFcntl[0] ){
- sqlite3ErrorMsg(pParse, "%s", aFcntl[0]);
- sqlite3_free(aFcntl[0]);
- }
- pParse->nErr++;
- pParse->rc = rc;
- goto pragma_out;
- }
-
- /* Locate the pragma in the lookup table */
- pPragma = pragmaLocate(zLeft);
- if( pPragma==0 ) goto pragma_out;
-
- /* Make sure the database schema is loaded if the pragma requires that */
- if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
- }
-
- /* Register the result column names for pragmas that return results */
- if( (pPragma->mPragFlg & PragFlg_NoColumns)==0
- && ((pPragma->mPragFlg & PragFlg_NoColumns1)==0 || zRight==0)
- ){
- setPragmaResultColumnNames(v, pPragma);
- }
-
- /* Jump to the appropriate pragma handler */
- switch( pPragma->ePragTyp ){
-
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
- /*
- ** PRAGMA [schema.]default_cache_size
- ** PRAGMA [schema.]default_cache_size=N
- **
- ** The first form reports the current persistent setting for the
- ** page cache size. The value returned is the maximum number of
- ** pages in the page cache. The second form sets both the current
- ** page cache size value and the persistent page cache size value
- ** stored in the database file.
- **
- ** Older versions of SQLite would set the default cache size to a
- ** negative number to indicate synchronous=OFF. These days, synchronous
- ** is always on by default regardless of the sign of the default cache
- ** size. But continue to take the absolute value of the default cache
- ** size of historical compatibility.
- */
- case PragTyp_DEFAULT_CACHE_SIZE: {
- static const int iLn = VDBE_OFFSET_LINENO(2);
- static const VdbeOpList getCacheSize[] = {
- { OP_Transaction, 0, 0, 0}, /* 0 */
- { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */
- { OP_IfPos, 1, 8, 0},
- { OP_Integer, 0, 2, 0},
- { OP_Subtract, 1, 2, 1},
- { OP_IfPos, 1, 8, 0},
- { OP_Integer, 0, 1, 0}, /* 6 */
- { OP_Noop, 0, 0, 0},
- { OP_ResultRow, 1, 1, 0},
- };
- VdbeOp *aOp;
- sqlite3VdbeUsesBtree(v, iDb);
- if( !zRight ){
- pParse->nMem += 2;
- sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(getCacheSize));
- aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn);
- if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break;
- aOp[0].p1 = iDb;
- aOp[1].p1 = iDb;
- aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE;
- }else{
- int size = sqlite3AbsInt32(sqlite3Atoi(zRight));
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, size);
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pDb->pSchema->cache_size = size;
- sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
- }
- break;
- }
-#endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */
-
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- /*
- ** PRAGMA [schema.]page_size
- ** PRAGMA [schema.]page_size=N
- **
- ** The first form reports the current setting for the
- ** database page size in bytes. The second form sets the
- ** database page size value. The value can only be set if
- ** the database has not yet been created.
- */
- case PragTyp_PAGE_SIZE: {
- Btree *pBt = pDb->pBt;
- assert( pBt!=0 );
- if( !zRight ){
- int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
- returnSingleInt(v, size);
- }else{
- /* Malloc may fail when setting the page-size, as there is an internal
- ** buffer that the pager module resizes using sqlite3_realloc().
- */
- db->nextPagesize = sqlite3Atoi(zRight);
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){
- sqlite3OomFault(db);
- }
- }
- break;
- }
-
- /*
- ** PRAGMA [schema.]secure_delete
- ** PRAGMA [schema.]secure_delete=ON/OFF/FAST
- **
- ** The first form reports the current setting for the
- ** secure_delete flag. The second form changes the secure_delete
- ** flag setting and reports the new value.
- */
- case PragTyp_SECURE_DELETE: {
- Btree *pBt = pDb->pBt;
- int b = -1;
- assert( pBt!=0 );
- if( zRight ){
- if( sqlite3_stricmp(zRight, "fast")==0 ){
- b = 2;
- }else{
- b = sqlite3GetBoolean(zRight, 0);
- }
- }
- if( pId2->n==0 && b>=0 ){
- int ii;
- for(ii=0; ii<db->nDb; ii++){
- sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
- }
- }
- b = sqlite3BtreeSecureDelete(pBt, b);
- returnSingleInt(v, b);
- break;
- }
-
- /*
- ** PRAGMA [schema.]max_page_count
- ** PRAGMA [schema.]max_page_count=N
- **
- ** The first form reports the current setting for the
- ** maximum number of pages in the database file. The
- ** second form attempts to change this setting. Both
- ** forms return the current setting.
- **
- ** The absolute value of N is used. This is undocumented and might
- ** change. The only purpose is to provide an easy way to test
- ** the sqlite3AbsInt32() function.
- **
- ** PRAGMA [schema.]page_count
- **
- ** Return the number of pages in the specified database.
- */
- case PragTyp_PAGE_COUNT: {
- int iReg;
- sqlite3CodeVerifySchema(pParse, iDb);
- iReg = ++pParse->nMem;
- if( sqlite3Tolower(zLeft[0])=='p' ){
- sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
- }else{
- sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg,
- sqlite3AbsInt32(sqlite3Atoi(zRight)));
- }
- sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
- break;
- }
-
- /*
- ** PRAGMA [schema.]locking_mode
- ** PRAGMA [schema.]locking_mode = (normal|exclusive)
- */
- case PragTyp_LOCKING_MODE: {
- const char *zRet = "normal";
- int eMode = getLockingMode(zRight);
-
- if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){
- /* Simple "PRAGMA locking_mode;" statement. This is a query for
- ** the current default locking mode (which may be different to
- ** the locking-mode of the main database).
- */
- eMode = db->dfltLockMode;
- }else{
- Pager *pPager;
- if( pId2->n==0 ){
- /* This indicates that no database name was specified as part
- ** of the PRAGMA command. In this case the locking-mode must be
- ** set on all attached databases, as well as the main db file.
- **
- ** Also, the sqlite3.dfltLockMode variable is set so that
- ** any subsequently attached databases also use the specified
- ** locking mode.
- */
- int ii;
- assert(pDb==&db->aDb[0]);
- for(ii=2; ii<db->nDb; ii++){
- pPager = sqlite3BtreePager(db->aDb[ii].pBt);
- sqlite3PagerLockingMode(pPager, eMode);
- }
- db->dfltLockMode = (u8)eMode;
- }
- pPager = sqlite3BtreePager(pDb->pBt);
- eMode = sqlite3PagerLockingMode(pPager, eMode);
- }
-
- assert( eMode==PAGER_LOCKINGMODE_NORMAL
- || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
- if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
- zRet = "exclusive";
- }
- returnSingleText(v, zRet);
- break;
- }
-
- /*
- ** PRAGMA [schema.]journal_mode
- ** PRAGMA [schema.]journal_mode =
- ** (delete|persist|off|truncate|memory|wal|off)
- */
- case PragTyp_JOURNAL_MODE: {
- int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
- int ii; /* Loop counter */
-
- if( zRight==0 ){
- /* If there is no "=MODE" part of the pragma, do a query for the
- ** current mode */
- eMode = PAGER_JOURNALMODE_QUERY;
- }else{
- const char *zMode;
- int n = sqlite3Strlen30(zRight);
- for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){
- if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break;
- }
- if( !zMode ){
- /* If the "=MODE" part does not match any known journal mode,
- ** then do a query */
- eMode = PAGER_JOURNALMODE_QUERY;
- }
- }
- if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){
- /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */
- iDb = 0;
- pId2->n = 1;
- }
- for(ii=db->nDb-1; ii>=0; ii--){
- if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
- sqlite3VdbeUsesBtree(v, ii);
- sqlite3VdbeAddOp3(v, OP_JournalMode, ii, 1, eMode);
- }
- }
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- break;
- }
-
- /*
- ** PRAGMA [schema.]journal_size_limit
- ** PRAGMA [schema.]journal_size_limit=N
- **
- ** Get or set the size limit on rollback journal files.
- */
- case PragTyp_JOURNAL_SIZE_LIMIT: {
- Pager *pPager = sqlite3BtreePager(pDb->pBt);
- i64 iLimit = -2;
- if( zRight ){
- sqlite3DecOrHexToI64(zRight, &iLimit);
- if( iLimit<-1 ) iLimit = -1;
- }
- iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
- returnSingleInt(v, iLimit);
- break;
- }
-
-#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
-
- /*
- ** PRAGMA [schema.]auto_vacuum
- ** PRAGMA [schema.]auto_vacuum=N
- **
- ** Get or set the value of the database 'auto-vacuum' parameter.
- ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL
- */
-#ifndef SQLITE_OMIT_AUTOVACUUM
- case PragTyp_AUTO_VACUUM: {
- Btree *pBt = pDb->pBt;
- assert( pBt!=0 );
- if( !zRight ){
- returnSingleInt(v, sqlite3BtreeGetAutoVacuum(pBt));
- }else{
- int eAuto = getAutoVacuum(zRight);
- assert( eAuto>=0 && eAuto<=2 );
- db->nextAutovac = (u8)eAuto;
- /* Call SetAutoVacuum() to set initialize the internal auto and
- ** incr-vacuum flags. This is required in case this connection
- ** creates the database file. It is important that it is created
- ** as an auto-vacuum capable db.
- */
- rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
- if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
- /* When setting the auto_vacuum mode to either "full" or
- ** "incremental", write the value of meta[6] in the database
- ** file. Before writing to meta[6], check that meta[3] indicates
- ** that this really is an auto-vacuum capable database.
- */
- static const int iLn = VDBE_OFFSET_LINENO(2);
- static const VdbeOpList setMeta6[] = {
- { OP_Transaction, 0, 1, 0}, /* 0 */
- { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
- { OP_If, 1, 0, 0}, /* 2 */
- { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
- { OP_SetCookie, 0, BTREE_INCR_VACUUM, 0}, /* 4 */
- };
- VdbeOp *aOp;
- int iAddr = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setMeta6));
- aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn);
- if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break;
- aOp[0].p1 = iDb;
- aOp[1].p1 = iDb;
- aOp[2].p2 = iAddr+4;
- aOp[4].p1 = iDb;
- aOp[4].p3 = eAuto - 1;
- sqlite3VdbeUsesBtree(v, iDb);
- }
- }
- break;
- }
-#endif
-
- /*
- ** PRAGMA [schema.]incremental_vacuum(N)
- **
- ** Do N steps of incremental vacuuming on a database.
- */
-#ifndef SQLITE_OMIT_AUTOVACUUM
- case PragTyp_INCREMENTAL_VACUUM: {
- int iLimit, addr;
- if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
- iLimit = 0x7fffffff;
- }
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
- addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v);
- sqlite3VdbeAddOp1(v, OP_ResultRow, 1);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
- sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addr);
- break;
- }
-#endif
-
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
- /*
- ** PRAGMA [schema.]cache_size
- ** PRAGMA [schema.]cache_size=N
- **
- ** The first form reports the current local setting for the
- ** page cache size. The second form sets the local
- ** page cache size value. If N is positive then that is the
- ** number of pages in the cache. If N is negative, then the
- ** number of pages is adjusted so that the cache uses -N kibibytes
- ** of memory.
- */
- case PragTyp_CACHE_SIZE: {
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- if( !zRight ){
- returnSingleInt(v, pDb->pSchema->cache_size);
- }else{
- int size = sqlite3Atoi(zRight);
- pDb->pSchema->cache_size = size;
- sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
- }
- break;
- }
-
- /*
- ** PRAGMA [schema.]cache_spill
- ** PRAGMA cache_spill=BOOLEAN
- ** PRAGMA [schema.]cache_spill=N
- **
- ** The first form reports the current local setting for the
- ** page cache spill size. The second form turns cache spill on
- ** or off. When turnning cache spill on, the size is set to the
- ** current cache_size. The third form sets a spill size that
- ** may be different form the cache size.
- ** If N is positive then that is the
- ** number of pages in the cache. If N is negative, then the
- ** number of pages is adjusted so that the cache uses -N kibibytes
- ** of memory.
- **
- ** If the number of cache_spill pages is less then the number of
- ** cache_size pages, no spilling occurs until the page count exceeds
- ** the number of cache_size pages.
- **
- ** The cache_spill=BOOLEAN setting applies to all attached schemas,
- ** not just the schema specified.
- */
- case PragTyp_CACHE_SPILL: {
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- if( !zRight ){
- returnSingleInt(v,
- (db->flags & SQLITE_CacheSpill)==0 ? 0 :
- sqlite3BtreeSetSpillSize(pDb->pBt,0));
- }else{
- int size = 1;
- if( sqlite3GetInt32(zRight, &size) ){
- sqlite3BtreeSetSpillSize(pDb->pBt, size);
- }
- if( sqlite3GetBoolean(zRight, size!=0) ){
- db->flags |= SQLITE_CacheSpill;
- }else{
- db->flags &= ~SQLITE_CacheSpill;
- }
- setAllPagerFlags(db);
- }
- break;
- }
-
- /*
- ** PRAGMA [schema.]mmap_size(N)
- **
- ** Used to set mapping size limit. The mapping size limit is
- ** used to limit the aggregate size of all memory mapped regions of the
- ** database file. If this parameter is set to zero, then memory mapping
- ** is not used at all. If N is negative, then the default memory map
- ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set.
- ** The parameter N is measured in bytes.
- **
- ** This value is advisory. The underlying VFS is free to memory map
- ** as little or as much as it wants. Except, if N is set to 0 then the
- ** upper layers will never invoke the xFetch interfaces to the VFS.
- */
- case PragTyp_MMAP_SIZE: {
- sqlite3_int64 sz;
-#if SQLITE_MAX_MMAP_SIZE>0
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- if( zRight ){
- int ii;
- sqlite3DecOrHexToI64(zRight, &sz);
- if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
- if( pId2->n==0 ) db->szMmap = sz;
- for(ii=db->nDb-1; ii>=0; ii--){
- if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
- sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz);
- }
- }
- }
- sz = -1;
- rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_MMAP_SIZE, &sz);
-#else
- sz = 0;
- rc = SQLITE_OK;
-#endif
- if( rc==SQLITE_OK ){
- returnSingleInt(v, sz);
- }else if( rc!=SQLITE_NOTFOUND ){
- pParse->nErr++;
- pParse->rc = rc;
- }
- break;
- }
-
- /*
- ** PRAGMA temp_store
- ** PRAGMA temp_store = "default"|"memory"|"file"
- **
- ** Return or set the local value of the temp_store flag. Changing
- ** the local value does not make changes to the disk file and the default
- ** value will be restored the next time the database is opened.
- **
- ** Note that it is possible for the library compile-time options to
- ** override this setting
- */
- case PragTyp_TEMP_STORE: {
- if( !zRight ){
- returnSingleInt(v, db->temp_store);
- }else{
- changeTempStorage(pParse, zRight);
- }
- break;
- }
-
- /*
- ** PRAGMA temp_store_directory
- ** PRAGMA temp_store_directory = ""|"directory_name"
- **
- ** Return or set the local value of the temp_store_directory flag. Changing
- ** the value sets a specific directory to be used for temporary files.
- ** Setting to a null string reverts to the default temporary directory search.
- ** If temporary directory is changed, then invalidateTempStorage.
- **
- */
- case PragTyp_TEMP_STORE_DIRECTORY: {
- if( !zRight ){
- returnSingleText(v, sqlite3_temp_directory);
- }else{
-#ifndef SQLITE_OMIT_WSD
- if( zRight[0] ){
- int res;
- rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
- if( rc!=SQLITE_OK || res==0 ){
- sqlite3ErrorMsg(pParse, "not a writable directory");
- goto pragma_out;
- }
- }
- if( SQLITE_TEMP_STORE==0
- || (SQLITE_TEMP_STORE==1 && db->temp_store<=1)
- || (SQLITE_TEMP_STORE==2 && db->temp_store==1)
- ){
- invalidateTempStorage(pParse);
- }
- sqlite3_free(sqlite3_temp_directory);
- if( zRight[0] ){
- sqlite3_temp_directory = sqlite3_mprintf("%s", zRight);
- }else{
- sqlite3_temp_directory = 0;
- }
-#endif /* SQLITE_OMIT_WSD */
- }
- break;
- }
-
-#if SQLITE_OS_WIN
- /*
- ** PRAGMA data_store_directory
- ** PRAGMA data_store_directory = ""|"directory_name"
- **
- ** Return or set the local value of the data_store_directory flag. Changing
- ** the value sets a specific directory to be used for database files that
- ** were specified with a relative pathname. Setting to a null string reverts
- ** to the default database directory, which for database files specified with
- ** a relative path will probably be based on the current directory for the
- ** process. Database file specified with an absolute path are not impacted
- ** by this setting, regardless of its value.
- **
- */
- case PragTyp_DATA_STORE_DIRECTORY: {
- if( !zRight ){
- returnSingleText(v, sqlite3_data_directory);
- }else{
-#ifndef SQLITE_OMIT_WSD
- if( zRight[0] ){
- int res;
- rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
- if( rc!=SQLITE_OK || res==0 ){
- sqlite3ErrorMsg(pParse, "not a writable directory");
- goto pragma_out;
- }
- }
- sqlite3_free(sqlite3_data_directory);
- if( zRight[0] ){
- sqlite3_data_directory = sqlite3_mprintf("%s", zRight);
- }else{
- sqlite3_data_directory = 0;
- }
-#endif /* SQLITE_OMIT_WSD */
- }
- break;
- }
-#endif
-
-#if SQLITE_ENABLE_LOCKING_STYLE
- /*
- ** PRAGMA [schema.]lock_proxy_file
- ** PRAGMA [schema.]lock_proxy_file = ":auto:"|"lock_file_path"
- **
- ** Return or set the value of the lock_proxy_file flag. Changing
- ** the value sets a specific file to be used for database access locks.
- **
- */
- case PragTyp_LOCK_PROXY_FILE: {
- if( !zRight ){
- Pager *pPager = sqlite3BtreePager(pDb->pBt);
- char *proxy_file_path = NULL;
- sqlite3_file *pFile = sqlite3PagerFile(pPager);
- sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE,
- &proxy_file_path);
- returnSingleText(v, proxy_file_path);
- }else{
- Pager *pPager = sqlite3BtreePager(pDb->pBt);
- sqlite3_file *pFile = sqlite3PagerFile(pPager);
- int res;
- if( zRight[0] ){
- res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
- zRight);
- } else {
- res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
- NULL);
- }
- if( res!=SQLITE_OK ){
- sqlite3ErrorMsg(pParse, "failed to set lock proxy file");
- goto pragma_out;
- }
- }
- break;
- }
-#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-
- /*
- ** PRAGMA [schema.]synchronous
- ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA
- **
- ** Return or set the local value of the synchronous flag. Changing
- ** the local value does not make changes to the disk file and the
- ** default value will be restored the next time the database is
- ** opened.
- */
- case PragTyp_SYNCHRONOUS: {
- if( !zRight ){
- returnSingleInt(v, pDb->safety_level-1);
- }else{
- if( !db->autoCommit ){
- sqlite3ErrorMsg(pParse,
- "Safety level may not be changed inside a transaction");
- }else if( iDb!=1 ){
- int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
- if( iLevel==0 ) iLevel = 1;
- pDb->safety_level = iLevel;
- pDb->bSyncSet = 1;
- setAllPagerFlags(db);
- }
- }
- break;
- }
-#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
-
-#ifndef SQLITE_OMIT_FLAG_PRAGMAS
- case PragTyp_FLAG: {
- if( zRight==0 ){
- setPragmaResultColumnNames(v, pPragma);
- returnSingleInt(v, (db->flags & pPragma->iArg)!=0 );
- }else{
- int mask = pPragma->iArg; /* Mask of bits to set or clear. */
- if( db->autoCommit==0 ){
- /* Foreign key support may not be enabled or disabled while not
- ** in auto-commit mode. */
- mask &= ~(SQLITE_ForeignKeys);
- }
-#if SQLITE_USER_AUTHENTICATION
- if( db->auth.authLevel==UAUTH_User ){
- /* Do not allow non-admin users to modify the schema arbitrarily */
- mask &= ~(SQLITE_WriteSchema);
- }
-#endif
-
- if( sqlite3GetBoolean(zRight, 0) ){
- db->flags |= mask;
- }else{
- db->flags &= ~mask;
- if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
- }
-
- /* Many of the flag-pragmas modify the code generated by the SQL
- ** compiler (eg. count_changes). So add an opcode to expire all
- ** compiled SQL statements after modifying a pragma value.
- */
- sqlite3VdbeAddOp0(v, OP_Expire);
- setAllPagerFlags(db);
- }
- break;
- }
-#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
-
-#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
- /*
- ** PRAGMA table_info(<table>)
- **
- ** Return a single row for each column of the named table. The columns of
- ** the returned data set are:
- **
- ** cid: Column id (numbered from left to right, starting at 0)
- ** name: Column name
- ** type: Column declaration type.
- ** notnull: True if 'NOT NULL' is part of column declaration
- ** dflt_value: The default value for the column, if any.
- ** pk: Non-zero for PK fields.
- */
- case PragTyp_TABLE_INFO: if( zRight ){
- Table *pTab;
- pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
- if( pTab ){
- int i, k;
- int nHidden = 0;
- Column *pCol;
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- pParse->nMem = 6;
- sqlite3CodeVerifySchema(pParse, iDb);
- sqlite3ViewGetColumnNames(pParse, pTab);
- for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
- if( IsHiddenColumn(pCol) ){
- nHidden++;
- continue;
- }
- if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
- k = 0;
- }else if( pPk==0 ){
- k = 1;
- }else{
- for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
- }
- assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
- sqlite3VdbeMultiLoad(v, 1, "issisi",
- i-nHidden,
- pCol->zName,
- sqlite3ColumnType(pCol,""),
- pCol->notNull ? 1 : 0,
- pCol->pDflt ? pCol->pDflt->u.zToken : 0,
- k);
- }
- }
- }
- break;
-
-#ifdef SQLITE_DEBUG
- case PragTyp_STATS: {
- Index *pIdx;
- HashElem *i;
- pParse->nMem = 5;
- sqlite3CodeVerifySchema(pParse, iDb);
- for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
- Table *pTab = sqliteHashData(i);
- sqlite3VdbeMultiLoad(v, 1, "ssiii",
- pTab->zName,
- 0,
- pTab->szTabRow,
- pTab->nRowLogEst,
- pTab->tabFlags);
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- sqlite3VdbeMultiLoad(v, 2, "siiiX",
- pIdx->zName,
- pIdx->szIdxRow,
- pIdx->aiRowLogEst[0],
- pIdx->hasStat1);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
- }
- }
- }
- break;
-#endif
-
- case PragTyp_INDEX_INFO: if( zRight ){
- Index *pIdx;
- Table *pTab;
- pIdx = sqlite3FindIndex(db, zRight, zDb);
- if( pIdx ){
- int i;
- int mx;
- if( pPragma->iArg ){
- /* PRAGMA index_xinfo (newer version with more rows and columns) */
- mx = pIdx->nColumn;
- pParse->nMem = 6;
- }else{
- /* PRAGMA index_info (legacy version) */
- mx = pIdx->nKeyCol;
- pParse->nMem = 3;
- }
- pTab = pIdx->pTable;
- sqlite3CodeVerifySchema(pParse, iDb);
- assert( pParse->nMem<=pPragma->nPragCName );
- for(i=0; i<mx; i++){
- i16 cnum = pIdx->aiColumn[i];
- sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
- cnum<0 ? 0 : pTab->aCol[cnum].zName);
- if( pPragma->iArg ){
- sqlite3VdbeMultiLoad(v, 4, "isiX",
- pIdx->aSortOrder[i],
- pIdx->azColl[i],
- i<pIdx->nKeyCol);
- }
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem);
- }
- }
- }
- break;
-
- case PragTyp_INDEX_LIST: if( zRight ){
- Index *pIdx;
- Table *pTab;
- int i;
- pTab = sqlite3FindTable(db, zRight, zDb);
- if( pTab ){
- pParse->nMem = 5;
- sqlite3CodeVerifySchema(pParse, iDb);
- for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
- const char *azOrigin[] = { "c", "u", "pk" };
- sqlite3VdbeMultiLoad(v, 1, "isisi",
- i,
- pIdx->zName,
- IsUniqueIndex(pIdx),
- azOrigin[pIdx->idxType],
- pIdx->pPartIdxWhere!=0);
- }
- }
- }
- break;
-
- case PragTyp_DATABASE_LIST: {
- int i;
- pParse->nMem = 3;
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt==0 ) continue;
- assert( db->aDb[i].zDbSName!=0 );
- sqlite3VdbeMultiLoad(v, 1, "iss",
- i,
- db->aDb[i].zDbSName,
- sqlite3BtreeGetFilename(db->aDb[i].pBt));
- }
- }
- break;
-
- case PragTyp_COLLATION_LIST: {
- int i = 0;
- HashElem *p;
- pParse->nMem = 2;
- for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
- CollSeq *pColl = (CollSeq *)sqliteHashData(p);
- sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName);
- }
- }
- break;
-
-#ifdef SQLITE_INTROSPECTION_PRAGMAS
- case PragTyp_FUNCTION_LIST: {
- int i;
- HashElem *j;
- FuncDef *p;
- pParse->nMem = 2;
- for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
- for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
- sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
- }
- }
- for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
- p = (FuncDef*)sqliteHashData(j);
- sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0);
- }
- }
- break;
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- case PragTyp_MODULE_LIST: {
- HashElem *j;
- pParse->nMem = 1;
- for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){
- Module *pMod = (Module*)sqliteHashData(j);
- sqlite3VdbeMultiLoad(v, 1, "s", pMod->zName);
- }
- }
- break;
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
- case PragTyp_PRAGMA_LIST: {
- int i;
- for(i=0; i<ArraySize(aPragmaName); i++){
- sqlite3VdbeMultiLoad(v, 1, "s", aPragmaName[i].zName);
- }
- }
- break;
-#endif /* SQLITE_INTROSPECTION_PRAGMAS */
-
-#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
-
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
- FKey *pFK;
- Table *pTab;
- pTab = sqlite3FindTable(db, zRight, zDb);
- if( pTab ){
- pFK = pTab->pFKey;
- if( pFK ){
- int i = 0;
- pParse->nMem = 8;
- sqlite3CodeVerifySchema(pParse, iDb);
- while(pFK){
- int j;
- for(j=0; j<pFK->nCol; j++){
- sqlite3VdbeMultiLoad(v, 1, "iissssss",
- i,
- j,
- pFK->zTo,
- pTab->aCol[pFK->aCol[j].iFrom].zName,
- pFK->aCol[j].zCol,
- actionName(pFK->aAction[1]), /* ON UPDATE */
- actionName(pFK->aAction[0]), /* ON DELETE */
- "NONE");
- }
- ++i;
- pFK = pFK->pNextFrom;
- }
- }
- }
- }
- break;
-#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
-
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-#ifndef SQLITE_OMIT_TRIGGER
- case PragTyp_FOREIGN_KEY_CHECK: {
- FKey *pFK; /* A foreign key constraint */
- Table *pTab; /* Child table contain "REFERENCES" keyword */
- Table *pParent; /* Parent table that child points to */
- Index *pIdx; /* Index in the parent table */
- int i; /* Loop counter: Foreign key number for pTab */
- int j; /* Loop counter: Field of the foreign key */
- HashElem *k; /* Loop counter: Next table in schema */
- int x; /* result variable */
- int regResult; /* 3 registers to hold a result row */
- int regKey; /* Register to hold key for checking the FK */
- int regRow; /* Registers to hold a row from pTab */
- int addrTop; /* Top of a loop checking foreign keys */
- int addrOk; /* Jump here if the key is OK */
- int *aiCols; /* child to parent column mapping */
-
- regResult = pParse->nMem+1;
- pParse->nMem += 4;
- regKey = ++pParse->nMem;
- regRow = ++pParse->nMem;
- sqlite3CodeVerifySchema(pParse, iDb);
- k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
- while( k ){
- if( zRight ){
- pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
- k = 0;
- }else{
- pTab = (Table*)sqliteHashData(k);
- k = sqliteHashNext(k);
- }
- if( pTab==0 || pTab->pFKey==0 ) continue;
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
- if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
- sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
- sqlite3VdbeLoadString(v, regResult, pTab->zName);
- for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
- pParent = sqlite3FindTable(db, pFK->zTo, zDb);
- if( pParent==0 ) continue;
- pIdx = 0;
- sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
- x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
- if( x==0 ){
- if( pIdx==0 ){
- sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
- }else{
- sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
- sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
- }
- }else{
- k = 0;
- break;
- }
- }
- assert( pParse->nErr>0 || pFK==0 );
- if( pFK ) break;
- if( pParse->nTab<i ) pParse->nTab = i;
- addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
- for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
- pParent = sqlite3FindTable(db, pFK->zTo, zDb);
- pIdx = 0;
- aiCols = 0;
- if( pParent ){
- x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
- assert( x==0 );
- }
- addrOk = sqlite3VdbeMakeLabel(v);
-
- /* Generate code to read the child key values into registers
- ** regRow..regRow+n. If any of the child key values are NULL, this
- ** row cannot cause an FK violation. Jump directly to addrOk in
- ** this case. */
- for(j=0; j<pFK->nCol; j++){
- int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
- sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
- sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
- }
-
- /* Generate code to query the parent index for a matching parent
- ** key. If a match is found, jump to addrOk. */
- if( pIdx ){
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
- sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
- sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
- VdbeCoverage(v);
- }else if( pParent ){
- int jmp = sqlite3VdbeCurrentAddr(v)+2;
- sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
- sqlite3VdbeGoto(v, addrOk);
- assert( pFK->nCol==1 );
- }
-
- /* Generate code to report an FK violation to the caller. */
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
- }else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, regResult+1);
- }
- sqlite3VdbeMultiLoad(v, regResult+2, "siX", pFK->zTo, i-1);
- sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
- sqlite3VdbeResolveLabel(v, addrOk);
- sqlite3DbFree(db, aiCols);
- }
- sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addrTop);
- }
- }
- break;
-#endif /* !defined(SQLITE_OMIT_TRIGGER) */
-#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
-
-#ifndef NDEBUG
- case PragTyp_PARSER_TRACE: {
- if( zRight ){
- if( sqlite3GetBoolean(zRight, 0) ){
- sqlite3ParserTrace(stdout, "parser: ");
- }else{
- sqlite3ParserTrace(0, 0);
- }
- }
- }
- break;
-#endif
-
- /* Reinstall the LIKE and GLOB functions. The variant of LIKE
- ** used will be case sensitive or not depending on the RHS.
- */
- case PragTyp_CASE_SENSITIVE_LIKE: {
- if( zRight ){
- sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0));
- }
- }
- break;
-
-#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
-# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
-#endif
-
-#ifndef SQLITE_OMIT_INTEGRITY_CHECK
- /* PRAGMA integrity_check
- ** PRAGMA integrity_check(N)
- ** PRAGMA quick_check
- ** PRAGMA quick_check(N)
- **
- ** Verify the integrity of the database.
- **
- ** The "quick_check" is reduced version of
- ** integrity_check designed to detect most database corruption
- ** without the overhead of cross-checking indexes. Quick_check
- ** is linear time wherease integrity_check is O(NlogN).
- */
- case PragTyp_INTEGRITY_CHECK: {
- int i, j, addr, mxErr;
-
- int isQuick = (sqlite3Tolower(zLeft[0])=='q');
-
- /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
- ** then iDb is set to the index of the database identified by <db>.
- ** In this case, the integrity of database iDb only is verified by
- ** the VDBE created below.
- **
- ** Otherwise, if the command was simply "PRAGMA integrity_check" (or
- ** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb
- ** to -1 here, to indicate that the VDBE should verify the integrity
- ** of all attached databases. */
- assert( iDb>=0 );
- assert( iDb==0 || pId2->z );
- if( pId2->z==0 ) iDb = -1;
-
- /* Initialize the VDBE program */
- pParse->nMem = 6;
-
- /* Set the maximum error count */
- mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
- if( zRight ){
- sqlite3GetInt32(zRight, &mxErr);
- if( mxErr<=0 ){
- mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
- }
- }
- sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */
-
- /* Do an integrity check on each database file */
- for(i=0; i<db->nDb; i++){
- HashElem *x; /* For looping over tables in the schema */
- Hash *pTbls; /* Set of all tables in the schema */
- int *aRoot; /* Array of root page numbers of all btrees */
- int cnt = 0; /* Number of entries in aRoot[] */
- int mxIdx = 0; /* Maximum number of indexes for any table */
-
- if( OMIT_TEMPDB && i==1 ) continue;
- if( iDb>=0 && i!=iDb ) continue;
-
- sqlite3CodeVerifySchema(pParse, i);
-
- /* Do an integrity check of the B-Tree
- **
- ** Begin by finding the root pages numbers
- ** for all tables and indices in the database.
- */
- assert( sqlite3SchemaMutexHeld(db, i, 0) );
- pTbls = &db->aDb[i].pSchema->tblHash;
- for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
- Table *pTab = sqliteHashData(x); /* Current table */
- Index *pIdx; /* An index on pTab */
- int nIdx; /* Number of indexes on pTab */
- if( HasRowid(pTab) ) cnt++;
- for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
- if( nIdx>mxIdx ) mxIdx = nIdx;
- }
- aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1));
- if( aRoot==0 ) break;
- for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
- Table *pTab = sqliteHashData(x);
- Index *pIdx;
- if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- aRoot[++cnt] = pIdx->tnum;
- }
- }
- aRoot[0] = cnt;
-
- /* Make sure sufficient number of registers have been allocated */
- pParse->nMem = MAX( pParse->nMem, 8+mxIdx );
- sqlite3ClearTempRegCache(pParse);
-
- /* Do the b-tree integrity checks */
- sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
- sqlite3VdbeChangeP5(v, (u8)i);
- addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
- sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
- P4_DYNAMIC);
- sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3);
- integrityCheckResultRow(v);
- sqlite3VdbeJumpHere(v, addr);
-
- /* Make sure all the indices are constructed correctly.
- */
- for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
- Table *pTab = sqliteHashData(x);
- Index *pIdx, *pPk;
- Index *pPrior = 0;
- int loopTop;
- int iDataCur, iIdxCur;
- int r1 = -1;
-
- if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
- pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
- sqlite3ExprCacheClear(pParse);
- sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
- 1, 0, &iDataCur, &iIdxCur);
- /* reg[7] counts the number of entries in the table.
- ** reg[8+i] counts the number of entries in the i-th index
- */
- sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
- }
- assert( pParse->nMem>=8+j );
- assert( sqlite3NoTempsInRange(pParse,1,7+j) );
- sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
- loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
- /* Verify that all NOT NULL columns really are NOT NULL */
- for(j=0; j<pTab->nCol; j++){
- char *zErr;
- int jmp2;
- if( j==pTab->iPKey ) continue;
- if( pTab->aCol[j].notNull==0 ) continue;
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
- jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
- zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
- pTab->aCol[j].zName);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
- integrityCheckResultRow(v);
- sqlite3VdbeJumpHere(v, jmp2);
- }
- /* Verify CHECK constraints */
- if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
- ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
- if( db->mallocFailed==0 ){
- int addrCkFault = sqlite3VdbeMakeLabel(v);
- int addrCkOk = sqlite3VdbeMakeLabel(v);
- char *zErr;
- int k;
- pParse->iSelfTab = iDataCur + 1;
- sqlite3ExprCachePush(pParse);
- for(k=pCheck->nExpr-1; k>0; k--){
- sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
- }
- sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk,
- SQLITE_JUMPIFNULL);
- sqlite3VdbeResolveLabel(v, addrCkFault);
- pParse->iSelfTab = 0;
- zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
- pTab->zName);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
- integrityCheckResultRow(v);
- sqlite3VdbeResolveLabel(v, addrCkOk);
- sqlite3ExprCachePop(pParse);
- }
- sqlite3ExprListDelete(db, pCheck);
- }
- if( !isQuick ){ /* Omit the remaining tests for quick_check */
- /* Sanity check on record header decoding */
- sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
- /* Validate index entries for the current row */
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- int jmp2, jmp3, jmp4, jmp5;
- int ckUniq = sqlite3VdbeMakeLabel(v);
- if( pPk==pIdx ) continue;
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
- pPrior, r1);
- pPrior = pIdx;
- sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
- /* Verify that an index entry exists for the current table row */
- jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
- pIdx->nColumn); VdbeCoverage(v);
- sqlite3VdbeLoadString(v, 3, "row ");
- sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
- sqlite3VdbeLoadString(v, 4, " missing from index ");
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
- jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
- jmp4 = integrityCheckResultRow(v);
- sqlite3VdbeJumpHere(v, jmp2);
- /* For UNIQUE indexes, verify that only one entry exists with the
- ** current key. The entry is unique if (1) any column is NULL
- ** or (2) the next entry has a different key */
- if( IsUniqueIndex(pIdx) ){
- int uniqOk = sqlite3VdbeMakeLabel(v);
- int jmp6;
- int kk;
- for(kk=0; kk<pIdx->nKeyCol; kk++){
- int iCol = pIdx->aiColumn[kk];
- assert( iCol!=XN_ROWID && iCol<pTab->nCol );
- if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
- sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
- VdbeCoverage(v);
- }
- jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
- sqlite3VdbeGoto(v, uniqOk);
- sqlite3VdbeJumpHere(v, jmp6);
- sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
- pIdx->nKeyCol); VdbeCoverage(v);
- sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
- sqlite3VdbeGoto(v, jmp5);
- sqlite3VdbeResolveLabel(v, uniqOk);
- }
- sqlite3VdbeJumpHere(v, jmp4);
- sqlite3ResolvePartIdxLabel(pParse, jmp3);
- }
- }
- sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, loopTop-1);
-#ifndef SQLITE_OMIT_BTREECOUNT
- if( !isQuick ){
- sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- if( pPk==pIdx ) continue;
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
- addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
- sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- sqlite3VdbeLoadString(v, 4, pIdx->zName);
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
- integrityCheckResultRow(v);
- sqlite3VdbeJumpHere(v, addr);
- }
- }
-#endif /* SQLITE_OMIT_BTREECOUNT */
- }
- }
- {
- static const int iLn = VDBE_OFFSET_LINENO(2);
- static const VdbeOpList endCode[] = {
- { OP_AddImm, 1, 0, 0}, /* 0 */
- { OP_IfNotZero, 1, 4, 0}, /* 1 */
- { OP_String8, 0, 3, 0}, /* 2 */
- { OP_ResultRow, 3, 1, 0}, /* 3 */
- { OP_Halt, 0, 0, 0}, /* 4 */
- { OP_String8, 0, 3, 0}, /* 5 */
- { OP_Goto, 0, 3, 0}, /* 6 */
- };
- VdbeOp *aOp;
-
- aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
- if( aOp ){
- aOp[0].p2 = 1-mxErr;
- aOp[2].p4type = P4_STATIC;
- aOp[2].p4.z = "ok";
- aOp[5].p4type = P4_STATIC;
- aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT);
- }
- sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2);
- }
- }
- break;
-#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
-
-#ifndef SQLITE_OMIT_UTF16
- /*
- ** PRAGMA encoding
- ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
- **
- ** In its first form, this pragma returns the encoding of the main
- ** database. If the database is not initialized, it is initialized now.
- **
- ** The second form of this pragma is a no-op if the main database file
- ** has not already been initialized. In this case it sets the default
- ** encoding that will be used for the main database file if a new file
- ** is created. If an existing main database file is opened, then the
- ** default text encoding for the existing database is used.
- **
- ** In all cases new databases created using the ATTACH command are
- ** created to use the same default text encoding as the main database. If
- ** the main database has not been initialized and/or created when ATTACH
- ** is executed, this is done before the ATTACH operation.
- **
- ** In the second form this pragma sets the text encoding to be used in
- ** new database files created using this database handle. It is only
- ** useful if invoked immediately after the main database i
- */
- case PragTyp_ENCODING: {
- static const struct EncName {
- char *zName;
- u8 enc;
- } encnames[] = {
- { "UTF8", SQLITE_UTF8 },
- { "UTF-8", SQLITE_UTF8 }, /* Must be element [1] */
- { "UTF-16le", SQLITE_UTF16LE }, /* Must be element [2] */
- { "UTF-16be", SQLITE_UTF16BE }, /* Must be element [3] */
- { "UTF16le", SQLITE_UTF16LE },
- { "UTF16be", SQLITE_UTF16BE },
- { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */
- { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */
- { 0, 0 }
- };
- const struct EncName *pEnc;
- if( !zRight ){ /* "PRAGMA encoding" */
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
- assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 );
- assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE );
- assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE );
- returnSingleText(v, encnames[ENC(pParse->db)].zName);
- }else{ /* "PRAGMA encoding = XXX" */
- /* Only change the value of sqlite.enc if the database handle is not
- ** initialized. If the main database exists, the new sqlite.enc value
- ** will be overwritten when the schema is next loaded. If it does not
- ** already exists, it will be created to use the new encoding value.
- */
- if(
- !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
- DbHasProperty(db, 0, DB_Empty)
- ){
- for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
- if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
- SCHEMA_ENC(db) = ENC(db) =
- pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
- break;
- }
- }
- if( !pEnc->zName ){
- sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight);
- }
- }
- }
- }
- break;
-#endif /* SQLITE_OMIT_UTF16 */
-
-#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
- /*
- ** PRAGMA [schema.]schema_version
- ** PRAGMA [schema.]schema_version = <integer>
- **
- ** PRAGMA [schema.]user_version
- ** PRAGMA [schema.]user_version = <integer>
- **
- ** PRAGMA [schema.]freelist_count
- **
- ** PRAGMA [schema.]data_version
- **
- ** PRAGMA [schema.]application_id
- ** PRAGMA [schema.]application_id = <integer>
- **
- ** The pragma's schema_version and user_version are used to set or get
- ** the value of the schema-version and user-version, respectively. Both
- ** the schema-version and the user-version are 32-bit signed integers
- ** stored in the database header.
- **
- ** The schema-cookie is usually only manipulated internally by SQLite. It
- ** is incremented by SQLite whenever the database schema is modified (by
- ** creating or dropping a table or index). The schema version is used by
- ** SQLite each time a query is executed to ensure that the internal cache
- ** of the schema used when compiling the SQL query matches the schema of
- ** the database against which the compiled query is actually executed.
- ** Subverting this mechanism by using "PRAGMA schema_version" to modify
- ** the schema-version is potentially dangerous and may lead to program
- ** crashes or database corruption. Use with caution!
- **
- ** The user-version is not used internally by SQLite. It may be used by
- ** applications for any purpose.
- */
- case PragTyp_HEADER_VALUE: {
- int iCookie = pPragma->iArg; /* Which cookie to read or write */
- sqlite3VdbeUsesBtree(v, iDb);
- if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){
- /* Write the specified cookie value */
- static const VdbeOpList setCookie[] = {
- { OP_Transaction, 0, 1, 0}, /* 0 */
- { OP_SetCookie, 0, 0, 0}, /* 1 */
- };
- VdbeOp *aOp;
- sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie));
- aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);
- if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break;
- aOp[0].p1 = iDb;
- aOp[1].p1 = iDb;
- aOp[1].p2 = iCookie;
- aOp[1].p3 = sqlite3Atoi(zRight);
- }else{
- /* Read the specified cookie value */
- static const VdbeOpList readCookie[] = {
- { OP_Transaction, 0, 0, 0}, /* 0 */
- { OP_ReadCookie, 0, 1, 0}, /* 1 */
- { OP_ResultRow, 1, 1, 0}
- };
- VdbeOp *aOp;
- sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(readCookie));
- aOp = sqlite3VdbeAddOpList(v, ArraySize(readCookie),readCookie,0);
- if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break;
- aOp[0].p1 = iDb;
- aOp[1].p1 = iDb;
- aOp[1].p3 = iCookie;
- sqlite3VdbeReusable(v);
- }
- }
- break;
-#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
-
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
- /*
- ** PRAGMA compile_options
- **
- ** Return the names of all compile-time options used in this build,
- ** one option per row.
- */
- case PragTyp_COMPILE_OPTIONS: {
- int i = 0;
- const char *zOpt;
- pParse->nMem = 1;
- while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
- sqlite3VdbeLoadString(v, 1, zOpt);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- }
- sqlite3VdbeReusable(v);
- }
- break;
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-
-#ifndef SQLITE_OMIT_WAL
- /*
- ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate
- **
- ** Checkpoint the database.
- */
- case PragTyp_WAL_CHECKPOINT: {
- int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
- int eMode = SQLITE_CHECKPOINT_PASSIVE;
- if( zRight ){
- if( sqlite3StrICmp(zRight, "full")==0 ){
- eMode = SQLITE_CHECKPOINT_FULL;
- }else if( sqlite3StrICmp(zRight, "restart")==0 ){
- eMode = SQLITE_CHECKPOINT_RESTART;
- }else if( sqlite3StrICmp(zRight, "truncate")==0 ){
- eMode = SQLITE_CHECKPOINT_TRUNCATE;
- }
- }
- pParse->nMem = 3;
- sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
- }
- break;
-
- /*
- ** PRAGMA wal_autocheckpoint
- ** PRAGMA wal_autocheckpoint = N
- **
- ** Configure a database connection to automatically checkpoint a database
- ** after accumulating N frames in the log. Or query for the current value
- ** of N.
- */
- case PragTyp_WAL_AUTOCHECKPOINT: {
- if( zRight ){
- sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
- }
- returnSingleInt(v,
- db->xWalCallback==sqlite3WalDefaultHook ?
- SQLITE_PTR_TO_INT(db->pWalArg) : 0);
- }
- break;
-#endif
-
- /*
- ** PRAGMA shrink_memory
- **
- ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database
- ** connection on which it is invoked to free up as much memory as it
- ** can, by calling sqlite3_db_release_memory().
- */
- case PragTyp_SHRINK_MEMORY: {
- sqlite3_db_release_memory(db);
- break;
- }
-
- /*
- ** PRAGMA optimize
- ** PRAGMA optimize(MASK)
- ** PRAGMA schema.optimize
- ** PRAGMA schema.optimize(MASK)
- **
- ** Attempt to optimize the database. All schemas are optimized in the first
- ** two forms, and only the specified schema is optimized in the latter two.
- **
- ** The details of optimizations performed by this pragma are expected
- ** to change and improve over time. Applications should anticipate that
- ** this pragma will perform new optimizations in future releases.
- **
- ** The optional argument is a bitmask of optimizations to perform:
- **
- ** 0x0001 Debugging mode. Do not actually perform any optimizations
- ** but instead return one line of text for each optimization
- ** that would have been done. Off by default.
- **
- ** 0x0002 Run ANALYZE on tables that might benefit. On by default.
- ** See below for additional information.
- **
- ** 0x0004 (Not yet implemented) Record usage and performance
- ** information from the current session in the
- ** database file so that it will be available to "optimize"
- ** pragmas run by future database connections.
- **
- ** 0x0008 (Not yet implemented) Create indexes that might have
- ** been helpful to recent queries
- **
- ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all
- ** of the optimizations listed above except Debug Mode, including new
- ** optimizations that have not yet been invented. If new optimizations are
- ** ever added that should be off by default, those off-by-default
- ** optimizations will have bitmasks of 0x10000 or larger.
- **
- ** DETERMINATION OF WHEN TO RUN ANALYZE
- **
- ** In the current implementation, a table is analyzed if only if all of
- ** the following are true:
- **
- ** (1) MASK bit 0x02 is set.
- **
- ** (2) The query planner used sqlite_stat1-style statistics for one or
- ** more indexes of the table at some point during the lifetime of
- ** the current connection.
- **
- ** (3) One or more indexes of the table are currently unanalyzed OR
- ** the number of rows in the table has increased by 25 times or more
- ** since the last time ANALYZE was run.
- **
- ** The rules for when tables are analyzed are likely to change in
- ** future releases.
- */
- case PragTyp_OPTIMIZE: {
- int iDbLast; /* Loop termination point for the schema loop */
- int iTabCur; /* Cursor for a table whose size needs checking */
- HashElem *k; /* Loop over tables of a schema */
- Schema *pSchema; /* The current schema */
- Table *pTab; /* A table in the schema */
- Index *pIdx; /* An index of the table */
- LogEst szThreshold; /* Size threshold above which reanalysis is needd */
- char *zSubSql; /* SQL statement for the OP_SqlExec opcode */
- u32 opMask; /* Mask of operations to perform */
-
- if( zRight ){
- opMask = (u32)sqlite3Atoi(zRight);
- if( (opMask & 0x02)==0 ) break;
- }else{
- opMask = 0xfffe;
- }
- iTabCur = pParse->nTab++;
- for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){
- if( iDb==1 ) continue;
- sqlite3CodeVerifySchema(pParse, iDb);
- pSchema = db->aDb[iDb].pSchema;
- for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
- pTab = (Table*)sqliteHashData(k);
-
- /* If table pTab has not been used in a way that would benefit from
- ** having analysis statistics during the current session, then skip it.
- ** This also has the effect of skipping virtual tables and views */
- if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue;
-
- /* Reanalyze if the table is 25 times larger than the last analysis */
- szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 );
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( !pIdx->hasStat1 ){
- szThreshold = 0; /* Always analyze if any index lacks statistics */
- break;
- }
- }
- if( szThreshold ){
- sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
- sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur,
- sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold);
- VdbeCoverage(v);
- }
- zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"",
- db->aDb[iDb].zDbSName, pTab->zName);
- if( opMask & 0x01 ){
- int r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC);
- sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1);
- }else{
- sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC);
- }
- }
- }
- sqlite3VdbeAddOp0(v, OP_Expire);
- break;
- }
-
- /*
- ** PRAGMA busy_timeout
- ** PRAGMA busy_timeout = N
- **
- ** Call sqlite3_busy_timeout(db, N). Return the current timeout value
- ** if one is set. If no busy handler or a different busy handler is set
- ** then 0 is returned. Setting the busy_timeout to 0 or negative
- ** disables the timeout.
- */
- /*case PragTyp_BUSY_TIMEOUT*/ default: {
- assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT );
- if( zRight ){
- sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
- }
- returnSingleInt(v, db->busyTimeout);
- break;
- }
-
- /*
- ** PRAGMA soft_heap_limit
- ** PRAGMA soft_heap_limit = N
- **
- ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the
- ** sqlite3_soft_heap_limit64() interface with the argument N, if N is
- ** specified and is a non-negative integer.
- ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always
- ** returns the same integer that would be returned by the
- ** sqlite3_soft_heap_limit64(-1) C-language function.
- */
- case PragTyp_SOFT_HEAP_LIMIT: {
- sqlite3_int64 N;
- if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
- sqlite3_soft_heap_limit64(N);
- }
- returnSingleInt(v, sqlite3_soft_heap_limit64(-1));
- break;
- }
-
- /*
- ** PRAGMA threads
- ** PRAGMA threads = N
- **
- ** Configure the maximum number of worker threads. Return the new
- ** maximum, which might be less than requested.
- */
- case PragTyp_THREADS: {
- sqlite3_int64 N;
- if( zRight
- && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
- && N>=0
- ){
- sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff));
- }
- returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
- break;
- }
-
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- /*
- ** Report the current state of file logs for all databases
- */
- case PragTyp_LOCK_STATUS: {
- static const char *const azLockName[] = {
- "unlocked", "shared", "reserved", "pending", "exclusive"
- };
- int i;
- pParse->nMem = 2;
- for(i=0; i<db->nDb; i++){
- Btree *pBt;
- const char *zState = "unknown";
- int j;
- if( db->aDb[i].zDbSName==0 ) continue;
- pBt = db->aDb[i].pBt;
- if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
- zState = "closed";
- }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0,
- SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
- zState = azLockName[j];
- }
- sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState);
- }
- break;
- }
-#endif
-
-#ifdef SQLITE_HAS_CODEC
- case PragTyp_KEY: {
- if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
- break;
- }
- case PragTyp_REKEY: {
- if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
- break;
- }
- case PragTyp_HEXKEY: {
- if( zRight ){
- u8 iByte;
- int i;
- char zKey[40];
- for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){
- iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
- if( (i&1)!=0 ) zKey[i/2] = iByte;
- }
- if( (zLeft[3] & 0xf)==0xb ){
- sqlite3_key_v2(db, zDb, zKey, i/2);
- }else{
- sqlite3_rekey_v2(db, zDb, zKey, i/2);
- }
- }
- break;
- }
-#endif
-#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
- case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){
-#ifdef SQLITE_HAS_CODEC
- if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
- sqlite3_activate_see(&zRight[4]);
- }
-#endif
-#ifdef SQLITE_ENABLE_CEROD
- if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
- sqlite3_activate_cerod(&zRight[6]);
- }
-#endif
- }
- break;
-#endif
-
- } /* End of the PRAGMA switch */
-
- /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only
- ** purpose is to execute assert() statements to verify that if the
- ** PragFlg_NoColumns1 flag is set and the caller specified an argument
- ** to the PRAGMA, the implementation has not added any OP_ResultRow
- ** instructions to the VM. */
- if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){
- sqlite3VdbeVerifyNoResultRow(v);
- }
-
-pragma_out:
- sqlite3DbFree(db, zLeft);
- sqlite3DbFree(db, zRight);
-}
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*****************************************************************************
-** Implementation of an eponymous virtual table that runs a pragma.
-**
-*/
-typedef struct PragmaVtab PragmaVtab;
-typedef struct PragmaVtabCursor PragmaVtabCursor;
-struct PragmaVtab {
- sqlite3_vtab base; /* Base class. Must be first */
- sqlite3 *db; /* The database connection to which it belongs */
- const PragmaName *pName; /* Name of the pragma */
- u8 nHidden; /* Number of hidden columns */
- u8 iHidden; /* Index of the first hidden column */
-};
-struct PragmaVtabCursor {
- sqlite3_vtab_cursor base; /* Base class. Must be first */
- sqlite3_stmt *pPragma; /* The pragma statement to run */
- sqlite_int64 iRowid; /* Current rowid */
- char *azArg[2]; /* Value of the argument and schema */
-};
-
-/*
-** Pragma virtual table module xConnect method.
-*/
-static int pragmaVtabConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- const PragmaName *pPragma = (const PragmaName*)pAux;
- PragmaVtab *pTab = 0;
- int rc;
- int i, j;
- char cSep = '(';
- StrAccum acc;
- char zBuf[200];
-
- UNUSED_PARAMETER(argc);
- UNUSED_PARAMETER(argv);
- sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
- sqlite3_str_appendall(&acc, "CREATE TABLE x");
- for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){
- sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]);
- cSep = ',';
- }
- if( i==0 ){
- sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName);
- cSep = ',';
- i++;
- }
- j = 0;
- if( pPragma->mPragFlg & PragFlg_Result1 ){
- sqlite3_str_appendall(&acc, ",arg HIDDEN");
- j++;
- }
- if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){
- sqlite3_str_appendall(&acc, ",schema HIDDEN");
- j++;
- }
- sqlite3_str_append(&acc, ")", 1);
- sqlite3StrAccumFinish(&acc);
- assert( strlen(zBuf) < sizeof(zBuf)-1 );
- rc = sqlite3_declare_vtab(db, zBuf);
- if( rc==SQLITE_OK ){
- pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab));
- if( pTab==0 ){
- rc = SQLITE_NOMEM;
- }else{
- memset(pTab, 0, sizeof(PragmaVtab));
- pTab->pName = pPragma;
- pTab->db = db;
- pTab->iHidden = i;
- pTab->nHidden = j;
- }
- }else{
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }
-
- *ppVtab = (sqlite3_vtab*)pTab;
- return rc;
-}
-
-/*
-** Pragma virtual table module xDisconnect method.
-*/
-static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){
- PragmaVtab *pTab = (PragmaVtab*)pVtab;
- sqlite3_free(pTab);
- return SQLITE_OK;
-}
-
-/* Figure out the best index to use to search a pragma virtual table.
-**
-** There are not really any index choices. But we want to encourage the
-** query planner to give == constraints on as many hidden parameters as
-** possible, and especially on the first hidden parameter. So return a
-** high cost if hidden parameters are unconstrained.
-*/
-static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- PragmaVtab *pTab = (PragmaVtab*)tab;
- const struct sqlite3_index_constraint *pConstraint;
- int i, j;
- int seen[2];
-
- pIdxInfo->estimatedCost = (double)1;
- if( pTab->nHidden==0 ){ return SQLITE_OK; }
- pConstraint = pIdxInfo->aConstraint;
- seen[0] = 0;
- seen[1] = 0;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- if( pConstraint->iColumn < pTab->iHidden ) continue;
- j = pConstraint->iColumn - pTab->iHidden;
- assert( j < 2 );
- seen[j] = i+1;
- }
- if( seen[0]==0 ){
- pIdxInfo->estimatedCost = (double)2147483647;
- pIdxInfo->estimatedRows = 2147483647;
- return SQLITE_OK;
- }
- j = seen[0]-1;
- pIdxInfo->aConstraintUsage[j].argvIndex = 1;
- pIdxInfo->aConstraintUsage[j].omit = 1;
- if( seen[1]==0 ) return SQLITE_OK;
- pIdxInfo->estimatedCost = (double)20;
- pIdxInfo->estimatedRows = 20;
- j = seen[1]-1;
- pIdxInfo->aConstraintUsage[j].argvIndex = 2;
- pIdxInfo->aConstraintUsage[j].omit = 1;
- return SQLITE_OK;
-}
-
-/* Create a new cursor for the pragma virtual table */
-static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
- PragmaVtabCursor *pCsr;
- pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr));
- if( pCsr==0 ) return SQLITE_NOMEM;
- memset(pCsr, 0, sizeof(PragmaVtabCursor));
- pCsr->base.pVtab = pVtab;
- *ppCursor = &pCsr->base;
- return SQLITE_OK;
-}
-
-/* Clear all content from pragma virtual table cursor. */
-static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
- int i;
- sqlite3_finalize(pCsr->pPragma);
- pCsr->pPragma = 0;
- for(i=0; i<ArraySize(pCsr->azArg); i++){
- sqlite3_free(pCsr->azArg[i]);
- pCsr->azArg[i] = 0;
- }
-}
-
-/* Close a pragma virtual table cursor */
-static int pragmaVtabClose(sqlite3_vtab_cursor *cur){
- PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur;
- pragmaVtabCursorClear(pCsr);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/* Advance the pragma virtual table cursor to the next row */
-static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){
- PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
- int rc = SQLITE_OK;
-
- /* Increment the xRowid value */
- pCsr->iRowid++;
- assert( pCsr->pPragma );
- if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){
- rc = sqlite3_finalize(pCsr->pPragma);
- pCsr->pPragma = 0;
- pragmaVtabCursorClear(pCsr);
- }
- return rc;
-}
-
-/*
-** Pragma virtual table module xFilter method.
-*/
-static int pragmaVtabFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
- PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
- int rc;
- int i, j;
- StrAccum acc;
- char *zSql;
-
- UNUSED_PARAMETER(idxNum);
- UNUSED_PARAMETER(idxStr);
- pragmaVtabCursorClear(pCsr);
- j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1;
- for(i=0; i<argc; i++, j++){
- const char *zText = (const char*)sqlite3_value_text(argv[i]);
- assert( j<ArraySize(pCsr->azArg) );
- assert( pCsr->azArg[j]==0 );
- if( zText ){
- pCsr->azArg[j] = sqlite3_mprintf("%s", zText);
- if( pCsr->azArg[j]==0 ){
- return SQLITE_NOMEM;
- }
- }
- }
- sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]);
- sqlite3_str_appendall(&acc, "PRAGMA ");
- if( pCsr->azArg[1] ){
- sqlite3_str_appendf(&acc, "%Q.", pCsr->azArg[1]);
- }
- sqlite3_str_appendall(&acc, pTab->pName->zName);
- if( pCsr->azArg[0] ){
- sqlite3_str_appendf(&acc, "=%Q", pCsr->azArg[0]);
- }
- zSql = sqlite3StrAccumFinish(&acc);
- if( zSql==0 ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK ){
- pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
- return rc;
- }
- return pragmaVtabNext(pVtabCursor);
-}
-
-/*
-** Pragma virtual table module xEof method.
-*/
-static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){
- PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
- return (pCsr->pPragma==0);
-}
-
-/* The xColumn method simply returns the corresponding column from
-** the PRAGMA.
-*/
-static int pragmaVtabColumn(
- sqlite3_vtab_cursor *pVtabCursor,
- sqlite3_context *ctx,
- int i
-){
- PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
- PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
- if( i<pTab->iHidden ){
- sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i));
- }else{
- sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT);
- }
- return SQLITE_OK;
-}
-
-/*
-** Pragma virtual table module xRowid method.
-*/
-static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){
- PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
- *p = pCsr->iRowid;
- return SQLITE_OK;
-}
-
-/* The pragma virtual table object */
-static const sqlite3_module pragmaVtabModule = {
- 0, /* iVersion */
- 0, /* xCreate - create a table */
- pragmaVtabConnect, /* xConnect - connect to an existing table */
- pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */
- pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */
- 0, /* xDestroy - Drop a table */
- pragmaVtabOpen, /* xOpen - open a cursor */
- pragmaVtabClose, /* xClose - close a cursor */
- pragmaVtabFilter, /* xFilter - configure scan constraints */
- pragmaVtabNext, /* xNext - advance a cursor */
- pragmaVtabEof, /* xEof */
- pragmaVtabColumn, /* xColumn - read data */
- pragmaVtabRowid, /* xRowid - read data */
- 0, /* xUpdate - write data */
- 0, /* xBegin - begin transaction */
- 0, /* xSync - sync transaction */
- 0, /* xCommit - commit transaction */
- 0, /* xRollback - rollback transaction */
- 0, /* xFindFunction - function overloading */
- 0, /* xRename - rename the table */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-
-/*
-** Check to see if zTabName is really the name of a pragma. If it is,
-** then register an eponymous virtual table for that pragma and return
-** a pointer to the Module object for the new virtual table.
-*/
-Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){
- const PragmaName *pName;
- assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 );
- pName = pragmaLocate(zName+7);
- if( pName==0 ) return 0;
- if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0;
- assert( sqlite3HashFind(&db->aModule, zName)==0 );
- return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0);
-}
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#endif /* SQLITE_OMIT_PRAGMA */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/pragma.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/pragma.h
deleted file mode 100644
index c9ece2dc875..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/pragma.h
+++ /dev/null
@@ -1,649 +0,0 @@
-/* DO NOT EDIT!
-** This file is automatically generated by the script at
-** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit
-** that script and rerun it.
-*/
-
-/* The various pragma types */
-#define PragTyp_HEADER_VALUE 0
-#define PragTyp_AUTO_VACUUM 1
-#define PragTyp_FLAG 2
-#define PragTyp_BUSY_TIMEOUT 3
-#define PragTyp_CACHE_SIZE 4
-#define PragTyp_CACHE_SPILL 5
-#define PragTyp_CASE_SENSITIVE_LIKE 6
-#define PragTyp_COLLATION_LIST 7
-#define PragTyp_COMPILE_OPTIONS 8
-#define PragTyp_DATA_STORE_DIRECTORY 9
-#define PragTyp_DATABASE_LIST 10
-#define PragTyp_DEFAULT_CACHE_SIZE 11
-#define PragTyp_ENCODING 12
-#define PragTyp_FOREIGN_KEY_CHECK 13
-#define PragTyp_FOREIGN_KEY_LIST 14
-#define PragTyp_FUNCTION_LIST 15
-#define PragTyp_INCREMENTAL_VACUUM 16
-#define PragTyp_INDEX_INFO 17
-#define PragTyp_INDEX_LIST 18
-#define PragTyp_INTEGRITY_CHECK 19
-#define PragTyp_JOURNAL_MODE 20
-#define PragTyp_JOURNAL_SIZE_LIMIT 21
-#define PragTyp_LOCK_PROXY_FILE 22
-#define PragTyp_LOCKING_MODE 23
-#define PragTyp_PAGE_COUNT 24
-#define PragTyp_MMAP_SIZE 25
-#define PragTyp_MODULE_LIST 26
-#define PragTyp_OPTIMIZE 27
-#define PragTyp_PAGE_SIZE 28
-#define PragTyp_PRAGMA_LIST 29
-#define PragTyp_SECURE_DELETE 30
-#define PragTyp_SHRINK_MEMORY 31
-#define PragTyp_SOFT_HEAP_LIMIT 32
-#define PragTyp_SYNCHRONOUS 33
-#define PragTyp_TABLE_INFO 34
-#define PragTyp_TEMP_STORE 35
-#define PragTyp_TEMP_STORE_DIRECTORY 36
-#define PragTyp_THREADS 37
-#define PragTyp_WAL_AUTOCHECKPOINT 38
-#define PragTyp_WAL_CHECKPOINT 39
-#define PragTyp_ACTIVATE_EXTENSIONS 40
-#define PragTyp_HEXKEY 41
-#define PragTyp_KEY 42
-#define PragTyp_REKEY 43
-#define PragTyp_LOCK_STATUS 44
-#define PragTyp_PARSER_TRACE 45
-#define PragTyp_STATS 46
-
-/* Property flags associated with various pragma. */
-#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
-#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */
-#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
-#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */
-#define PragFlg_Result0 0x10 /* Acts as query when no argument */
-#define PragFlg_Result1 0x20 /* Acts as query when has one argument */
-#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */
-#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */
-
-/* Names of columns for pragmas that return multi-column result
-** or that return single-column results where the name of the
-** result column is different from the name of the pragma
-*/
-static const char *const pragCName[] = {
- /* 0 */ "cache_size", /* Used by: default_cache_size */
- /* 1 */ "cid", /* Used by: table_info */
- /* 2 */ "name",
- /* 3 */ "type",
- /* 4 */ "notnull",
- /* 5 */ "dflt_value",
- /* 6 */ "pk",
- /* 7 */ "tbl", /* Used by: stats */
- /* 8 */ "idx",
- /* 9 */ "wdth",
- /* 10 */ "hght",
- /* 11 */ "flgs",
- /* 12 */ "seqno", /* Used by: index_info */
- /* 13 */ "cid",
- /* 14 */ "name",
- /* 15 */ "seqno", /* Used by: index_xinfo */
- /* 16 */ "cid",
- /* 17 */ "name",
- /* 18 */ "desc",
- /* 19 */ "coll",
- /* 20 */ "key",
- /* 21 */ "seq", /* Used by: index_list */
- /* 22 */ "name",
- /* 23 */ "unique",
- /* 24 */ "origin",
- /* 25 */ "partial",
- /* 26 */ "seq", /* Used by: database_list */
- /* 27 */ "name",
- /* 28 */ "file",
- /* 29 */ "name", /* Used by: function_list */
- /* 30 */ "builtin",
- /* 31 */ "name", /* Used by: module_list pragma_list */
- /* 32 */ "seq", /* Used by: collation_list */
- /* 33 */ "name",
- /* 34 */ "id", /* Used by: foreign_key_list */
- /* 35 */ "seq",
- /* 36 */ "table",
- /* 37 */ "from",
- /* 38 */ "to",
- /* 39 */ "on_update",
- /* 40 */ "on_delete",
- /* 41 */ "match",
- /* 42 */ "table", /* Used by: foreign_key_check */
- /* 43 */ "rowid",
- /* 44 */ "parent",
- /* 45 */ "fkid",
- /* 46 */ "busy", /* Used by: wal_checkpoint */
- /* 47 */ "log",
- /* 48 */ "checkpointed",
- /* 49 */ "timeout", /* Used by: busy_timeout */
- /* 50 */ "database", /* Used by: lock_status */
- /* 51 */ "status",
-};
-
-/* Definitions of all built-in pragmas */
-typedef struct PragmaName {
- const char *const zName; /* Name of pragma */
- u8 ePragTyp; /* PragTyp_XXX value */
- u8 mPragFlg; /* Zero or more PragFlg_XXX values */
- u8 iPragCName; /* Start of column names in pragCName[] */
- u8 nPragCName; /* Num of col names. 0 means use pragma name */
- u32 iArg; /* Extra argument */
-} PragmaName;
-static const PragmaName aPragmaName[] = {
-#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
- {/* zName: */ "activate_extensions",
- /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
- /* ePragFlg: */ 0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- {/* zName: */ "application_id",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ BTREE_APPLICATION_ID },
-#endif
-#if !defined(SQLITE_OMIT_AUTOVACUUM)
- {/* zName: */ "auto_vacuum",
- /* ePragTyp: */ PragTyp_AUTO_VACUUM,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
- {/* zName: */ "automatic_index",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_AutoIndex },
-#endif
-#endif
- {/* zName: */ "busy_timeout",
- /* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 49, 1,
- /* iArg: */ 0 },
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- {/* zName: */ "cache_size",
- /* ePragTyp: */ PragTyp_CACHE_SIZE,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "cache_spill",
- /* ePragTyp: */ PragTyp_CACHE_SPILL,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
- {/* zName: */ "case_sensitive_like",
- /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
- /* ePragFlg: */ PragFlg_NoColumns,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "cell_size_check",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_CellSizeCk },
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "checkpoint_fullfsync",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_CkptFullFSync },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- {/* zName: */ "collation_list",
- /* ePragTyp: */ PragTyp_COLLATION_LIST,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 32, 2,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
- {/* zName: */ "compile_options",
- /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "count_changes",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_CountRows },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
- {/* zName: */ "data_store_directory",
- /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
- /* ePragFlg: */ PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- {/* zName: */ "data_version",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ BTREE_DATA_VERSION },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- {/* zName: */ "database_list",
- /* ePragTyp: */ PragTyp_DATABASE_LIST,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 26, 3,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
- {/* zName: */ "default_cache_size",
- /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 0, 1,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- {/* zName: */ "defer_foreign_keys",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_DeferFKs },
-#endif
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "empty_result_callbacks",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_NullCallback },
-#endif
-#if !defined(SQLITE_OMIT_UTF16)
- {/* zName: */ "encoding",
- /* ePragTyp: */ PragTyp_ENCODING,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- {/* zName: */ "foreign_key_check",
- /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 42, 4,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FOREIGN_KEY)
- {/* zName: */ "foreign_key_list",
- /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 34, 8,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- {/* zName: */ "foreign_keys",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_ForeignKeys },
-#endif
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- {/* zName: */ "freelist_count",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ BTREE_FREE_PAGE_COUNT },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "full_column_names",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_FullColNames },
- {/* zName: */ "fullfsync",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_FullFSync },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-#if defined(SQLITE_INTROSPECTION_PRAGMAS)
- {/* zName: */ "function_list",
- /* ePragTyp: */ PragTyp_FUNCTION_LIST,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 29, 2,
- /* iArg: */ 0 },
-#endif
-#endif
-#if defined(SQLITE_HAS_CODEC)
- {/* zName: */ "hexkey",
- /* ePragTyp: */ PragTyp_HEXKEY,
- /* ePragFlg: */ 0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "hexrekey",
- /* ePragTyp: */ PragTyp_HEXKEY,
- /* ePragFlg: */ 0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-#if !defined(SQLITE_OMIT_CHECK)
- {/* zName: */ "ignore_check_constraints",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_IgnoreChecks },
-#endif
-#endif
-#if !defined(SQLITE_OMIT_AUTOVACUUM)
- {/* zName: */ "incremental_vacuum",
- /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- {/* zName: */ "index_info",
- /* ePragTyp: */ PragTyp_INDEX_INFO,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 12, 3,
- /* iArg: */ 0 },
- {/* zName: */ "index_list",
- /* ePragTyp: */ PragTyp_INDEX_LIST,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 21, 5,
- /* iArg: */ 0 },
- {/* zName: */ "index_xinfo",
- /* ePragTyp: */ PragTyp_INDEX_INFO,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 15, 6,
- /* iArg: */ 1 },
-#endif
-#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
- {/* zName: */ "integrity_check",
- /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- {/* zName: */ "journal_mode",
- /* ePragTyp: */ PragTyp_JOURNAL_MODE,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "journal_size_limit",
- /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if defined(SQLITE_HAS_CODEC)
- {/* zName: */ "key",
- /* ePragTyp: */ PragTyp_KEY,
- /* ePragFlg: */ 0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "legacy_file_format",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_LegacyFileFmt },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
- {/* zName: */ "lock_proxy_file",
- /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
- /* ePragFlg: */ PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- {/* zName: */ "lock_status",
- /* ePragTyp: */ PragTyp_LOCK_STATUS,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 50, 2,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- {/* zName: */ "locking_mode",
- /* ePragTyp: */ PragTyp_LOCKING_MODE,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "max_page_count",
- /* ePragTyp: */ PragTyp_PAGE_COUNT,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "mmap_size",
- /* ePragTyp: */ PragTyp_MMAP_SIZE,
- /* ePragFlg: */ 0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-#if !defined(SQLITE_OMIT_VIRTUALTABLE)
-#if defined(SQLITE_INTROSPECTION_PRAGMAS)
- {/* zName: */ "module_list",
- /* ePragTyp: */ PragTyp_MODULE_LIST,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 31, 1,
- /* iArg: */ 0 },
-#endif
-#endif
-#endif
- {/* zName: */ "optimize",
- /* ePragTyp: */ PragTyp_OPTIMIZE,
- /* ePragFlg: */ PragFlg_Result1|PragFlg_NeedSchema,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- {/* zName: */ "page_count",
- /* ePragTyp: */ PragTyp_PAGE_COUNT,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "page_size",
- /* ePragTyp: */ PragTyp_PAGE_SIZE,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
- {/* zName: */ "parser_trace",
- /* ePragTyp: */ PragTyp_PARSER_TRACE,
- /* ePragFlg: */ 0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if defined(SQLITE_INTROSPECTION_PRAGMAS)
- {/* zName: */ "pragma_list",
- /* ePragTyp: */ PragTyp_PRAGMA_LIST,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 31, 1,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "query_only",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_QueryOnly },
-#endif
-#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
- {/* zName: */ "quick_check",
- /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "read_uncommitted",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_ReadUncommit },
- {/* zName: */ "recursive_triggers",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_RecTriggers },
-#endif
-#if defined(SQLITE_HAS_CODEC)
- {/* zName: */ "rekey",
- /* ePragTyp: */ PragTyp_REKEY,
- /* ePragFlg: */ 0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "reverse_unordered_selects",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_ReverseOrder },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- {/* zName: */ "schema_version",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ BTREE_SCHEMA_VERSION },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- {/* zName: */ "secure_delete",
- /* ePragTyp: */ PragTyp_SECURE_DELETE,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "short_column_names",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_ShortColNames },
-#endif
- {/* zName: */ "shrink_memory",
- /* ePragTyp: */ PragTyp_SHRINK_MEMORY,
- /* ePragFlg: */ PragFlg_NoColumns,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "soft_heap_limit",
- /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-#if defined(SQLITE_DEBUG)
- {/* zName: */ "sql_trace",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_SqlTrace },
-#endif
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
- {/* zName: */ "stats",
- /* ePragTyp: */ PragTyp_STATS,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 7, 5,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- {/* zName: */ "synchronous",
- /* ePragTyp: */ PragTyp_SYNCHRONOUS,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- {/* zName: */ "table_info",
- /* ePragTyp: */ PragTyp_TABLE_INFO,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 1, 6,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- {/* zName: */ "temp_store",
- /* ePragTyp: */ PragTyp_TEMP_STORE,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "temp_store_directory",
- /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
- /* ePragFlg: */ PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#endif
- {/* zName: */ "threads",
- /* ePragTyp: */ PragTyp_THREADS,
- /* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
-#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- {/* zName: */ "user_version",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
- /* ColNames: */ 0, 0,
- /* iArg: */ BTREE_USER_VERSION },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-#if defined(SQLITE_DEBUG)
- {/* zName: */ "vdbe_addoptrace",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_VdbeAddopTrace },
- {/* zName: */ "vdbe_debug",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
- {/* zName: */ "vdbe_eqp",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_VdbeEQP },
- {/* zName: */ "vdbe_listing",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_VdbeListing },
- {/* zName: */ "vdbe_trace",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_VdbeTrace },
-#endif
-#endif
-#if !defined(SQLITE_OMIT_WAL)
- {/* zName: */ "wal_autocheckpoint",
- /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT,
- /* ePragFlg: */ 0,
- /* ColNames: */ 0, 0,
- /* iArg: */ 0 },
- {/* zName: */ "wal_checkpoint",
- /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
- /* ePragFlg: */ PragFlg_NeedSchema,
- /* ColNames: */ 46, 3,
- /* iArg: */ 0 },
-#endif
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- {/* zName: */ "writable_schema",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_WriteSchema },
-#endif
-};
-/* Number of pragmas: 60 on by default, 77 total. */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/prepare.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/prepare.c
deleted file mode 100644
index c745f45a5ab..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/prepare.c
+++ /dev/null
@@ -1,906 +0,0 @@
-/*
-** 2005 May 25
-**
-** 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 contains the implementation of the sqlite3_prepare()
-** interface, and routines that contribute to loading the database schema
-** from disk.
-*/
-#include "sqliteInt.h"
-
-/*
-** Fill the InitData structure with an error message that indicates
-** that the database is corrupt.
-*/
-static void corruptSchema(
- InitData *pData, /* Initialization context */
- const char *zObj, /* Object being parsed at the point of error */
- const char *zExtra /* Error information */
-){
- sqlite3 *db = pData->db;
- if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){
- char *z;
- if( zObj==0 ) zObj = "?";
- z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
- if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
- sqlite3DbFree(db, *pData->pzErrMsg);
- *pData->pzErrMsg = z;
- }
- pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT;
-}
-
-/*
-** This is the callback routine for the code that initializes the
-** database. See sqlite3Init() below for additional information.
-** This routine is also called from the OP_ParseSchema opcode of the VDBE.
-**
-** Each callback contains the following information:
-**
-** argv[0] = name of thing being created
-** argv[1] = root page number for table or index. 0 for trigger or view.
-** argv[2] = SQL text for the CREATE statement.
-**
-*/
-int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
- InitData *pData = (InitData*)pInit;
- sqlite3 *db = pData->db;
- int iDb = pData->iDb;
-
- assert( argc==3 );
- UNUSED_PARAMETER2(NotUsed, argc);
- assert( sqlite3_mutex_held(db->mutex) );
- DbClearProperty(db, iDb, DB_Empty);
- if( db->mallocFailed ){
- corruptSchema(pData, argv[0], 0);
- return 1;
- }
-
- assert( iDb>=0 && iDb<db->nDb );
- if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
- if( argv[1]==0 ){
- corruptSchema(pData, argv[0], 0);
- }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
- /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
- ** But because db->init.busy is set to 1, no VDBE code is generated
- ** or executed. All the parser does is build the internal data
- ** structures that describe the table, index, or view.
- */
- int rc;
- u8 saved_iDb = db->init.iDb;
- sqlite3_stmt *pStmt;
- TESTONLY(int rcp); /* Return code from sqlite3_prepare() */
-
- assert( db->init.busy );
- db->init.iDb = iDb;
- db->init.newTnum = sqlite3Atoi(argv[1]);
- db->init.orphanTrigger = 0;
- TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
- rc = db->errCode;
- assert( (rc&0xFF)==(rcp&0xFF) );
- db->init.iDb = saved_iDb;
- assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 );
- if( SQLITE_OK!=rc ){
- if( db->init.orphanTrigger ){
- assert( iDb==1 );
- }else{
- pData->rc = rc;
- if( rc==SQLITE_NOMEM ){
- sqlite3OomFault(db);
- }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
- corruptSchema(pData, argv[0], sqlite3_errmsg(db));
- }
- }
- }
- sqlite3_finalize(pStmt);
- }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
- corruptSchema(pData, argv[0], 0);
- }else{
- /* If the SQL column is blank it means this is an index that
- ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
- ** constraint for a CREATE TABLE. The index should have already
- ** been created when we processed the CREATE TABLE. All we have
- ** to do here is record the root page number for that index.
- */
- Index *pIndex;
- pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
- if( pIndex==0 ){
- /* This can occur if there exists an index on a TEMP table which
- ** has the same name as another index on a permanent index. Since
- ** the permanent table is hidden by the TEMP table, we can also
- ** safely ignore the index on the permanent table.
- */
- /* Do Nothing */;
- }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){
- corruptSchema(pData, argv[0], "invalid rootpage");
- }
- }
- return 0;
-}
-
-/*
-** Attempt to read the database schema and initialize internal
-** data structures for a single database file. The index of the
-** database file is given by iDb. iDb==0 is used for the main
-** database. iDb==1 should never be used. iDb>=2 is used for
-** auxiliary databases. Return one of the SQLITE_ error codes to
-** indicate success or failure.
-*/
-static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
- int rc;
- int i;
-#ifndef SQLITE_OMIT_DEPRECATED
- int size;
-#endif
- Db *pDb;
- char const *azArg[4];
- int meta[5];
- InitData initData;
- const char *zMasterName;
- int openedTransaction = 0;
-
- assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
- assert( iDb>=0 && iDb<db->nDb );
- assert( db->aDb[iDb].pSchema );
- assert( sqlite3_mutex_held(db->mutex) );
- assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
-
- db->init.busy = 1;
-
- /* Construct the in-memory representation schema tables (sqlite_master or
- ** sqlite_temp_master) by invoking the parser directly. The appropriate
- ** table name will be inserted automatically by the parser so we can just
- ** use the abbreviation "x" here. The parser will also automatically tag
- ** the schema table as read-only. */
- azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
- azArg[1] = "1";
- azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
- "rootpage int,sql text)";
- azArg[3] = 0;
- initData.db = db;
- initData.iDb = iDb;
- initData.rc = SQLITE_OK;
- initData.pzErrMsg = pzErrMsg;
- sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
- if( initData.rc ){
- rc = initData.rc;
- goto error_out;
- }
-
- /* Create a cursor to hold the database open
- */
- pDb = &db->aDb[iDb];
- if( pDb->pBt==0 ){
- assert( iDb==1 );
- DbSetProperty(db, 1, DB_SchemaLoaded);
- rc = SQLITE_OK;
- goto error_out;
- }
-
- /* If there is not already a read-only (or read-write) transaction opened
- ** on the b-tree database, open one now. If a transaction is opened, it
- ** will be closed before this function returns. */
- sqlite3BtreeEnter(pDb->pBt);
- if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
- rc = sqlite3BtreeBeginTrans(pDb->pBt, 0);
- if( rc!=SQLITE_OK ){
- sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
- goto initone_error_out;
- }
- openedTransaction = 1;
- }
-
- /* Get the database meta information.
- **
- ** Meta values are as follows:
- ** meta[0] Schema cookie. Changes with each schema change.
- ** meta[1] File format of schema layer.
- ** meta[2] Size of the page cache.
- ** meta[3] Largest rootpage (auto/incr_vacuum mode)
- ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE
- ** meta[5] User version
- ** meta[6] Incremental vacuum mode
- ** meta[7] unused
- ** meta[8] unused
- ** meta[9] unused
- **
- ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
- ** the possible values of meta[4].
- */
- for(i=0; i<ArraySize(meta); i++){
- sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
- }
- if( (db->flags & SQLITE_ResetDatabase)!=0 ){
- memset(meta, 0, sizeof(meta));
- }
- pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1];
-
- /* If opening a non-empty database, check the text encoding. For the
- ** main database, set sqlite3.enc to the encoding of the main database.
- ** For an attached db, it is an error if the encoding is not the same
- ** as sqlite3.enc.
- */
- if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */
- if( iDb==0 ){
-#ifndef SQLITE_OMIT_UTF16
- u8 encoding;
- /* If opening the main database, set ENC(db). */
- encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
- if( encoding==0 ) encoding = SQLITE_UTF8;
- ENC(db) = encoding;
-#else
- ENC(db) = SQLITE_UTF8;
-#endif
- }else{
- /* If opening an attached database, the encoding much match ENC(db) */
- if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
- sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
- " text encoding as main database");
- rc = SQLITE_ERROR;
- goto initone_error_out;
- }
- }
- }else{
- DbSetProperty(db, iDb, DB_Empty);
- }
- pDb->pSchema->enc = ENC(db);
-
- if( pDb->pSchema->cache_size==0 ){
-#ifndef SQLITE_OMIT_DEPRECATED
- size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]);
- if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; }
- pDb->pSchema->cache_size = size;
-#else
- pDb->pSchema->cache_size = SQLITE_DEFAULT_CACHE_SIZE;
-#endif
- sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
- }
-
- /*
- ** file_format==1 Version 3.0.0.
- ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN
- ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults
- ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants
- */
- pDb->pSchema->file_format = (u8)meta[BTREE_FILE_FORMAT-1];
- if( pDb->pSchema->file_format==0 ){
- pDb->pSchema->file_format = 1;
- }
- if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
- sqlite3SetString(pzErrMsg, db, "unsupported file format");
- rc = SQLITE_ERROR;
- goto initone_error_out;
- }
-
- /* Ticket #2804: When we open a database in the newer file format,
- ** clear the legacy_file_format pragma flag so that a VACUUM will
- ** not downgrade the database and thus invalidate any descending
- ** indices that the user might have created.
- */
- if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){
- db->flags &= ~SQLITE_LegacyFileFmt;
- }
-
- /* Read the schema information out of the schema tables
- */
- assert( db->init.busy );
- {
- char *zSql;
- zSql = sqlite3MPrintf(db,
- "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
- db->aDb[iDb].zDbSName, zMasterName);
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- sqlite3_xauth xAuth;
- xAuth = db->xAuth;
- db->xAuth = 0;
-#endif
- rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
-#ifndef SQLITE_OMIT_AUTHORIZATION
- db->xAuth = xAuth;
- }
-#endif
- if( rc==SQLITE_OK ) rc = initData.rc;
- sqlite3DbFree(db, zSql);
-#ifndef SQLITE_OMIT_ANALYZE
- if( rc==SQLITE_OK ){
- sqlite3AnalysisLoad(db, iDb);
- }
-#endif
- }
- if( db->mallocFailed ){
- rc = SQLITE_NOMEM_BKPT;
- sqlite3ResetAllSchemasOfConnection(db);
- }
- if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){
- /* Black magic: If the SQLITE_WriteSchema flag is set, then consider
- ** the schema loaded, even if errors occurred. In this situation the
- ** current sqlite3_prepare() operation will fail, but the following one
- ** will attempt to compile the supplied statement against whatever subset
- ** of the schema was loaded before the error occurred. The primary
- ** purpose of this is to allow access to the sqlite_master table
- ** even when its contents have been corrupted.
- */
- DbSetProperty(db, iDb, DB_SchemaLoaded);
- rc = SQLITE_OK;
- }
-
- /* Jump here for an error that occurs after successfully allocating
- ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
- ** before that point, jump to error_out.
- */
-initone_error_out:
- if( openedTransaction ){
- sqlite3BtreeCommit(pDb->pBt);
- }
- sqlite3BtreeLeave(pDb->pBt);
-
-error_out:
- if( rc ){
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
- sqlite3OomFault(db);
- }
- sqlite3ResetOneSchema(db, iDb);
- }
- db->init.busy = 0;
- return rc;
-}
-
-/*
-** Initialize all database files - the main database file, the file
-** used to store temporary tables, and any additional database files
-** created using ATTACH statements. Return a success code. If an
-** error occurs, write an error message into *pzErrMsg.
-**
-** After a database is initialized, the DB_SchemaLoaded bit is set
-** bit is set in the flags field of the Db structure. If the database
-** file was of zero-length, then the DB_Empty flag is also set.
-*/
-int sqlite3Init(sqlite3 *db, char **pzErrMsg){
- int i, rc;
- int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange);
-
- assert( sqlite3_mutex_held(db->mutex) );
- assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
- assert( db->init.busy==0 );
- ENC(db) = SCHEMA_ENC(db);
- assert( db->nDb>0 );
- /* Do the main schema first */
- if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
- rc = sqlite3InitOne(db, 0, pzErrMsg);
- if( rc ) return rc;
- }
- /* All other schemas after the main schema. The "temp" schema must be last */
- for(i=db->nDb-1; i>0; i--){
- assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) );
- if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
- rc = sqlite3InitOne(db, i, pzErrMsg);
- if( rc ) return rc;
- }
- }
- if( commit_internal ){
- sqlite3CommitInternalChanges(db);
- }
- return SQLITE_OK;
-}
-
-/*
-** This routine is a no-op if the database schema is already initialized.
-** Otherwise, the schema is loaded. An error code is returned.
-*/
-int sqlite3ReadSchema(Parse *pParse){
- int rc = SQLITE_OK;
- sqlite3 *db = pParse->db;
- assert( sqlite3_mutex_held(db->mutex) );
- if( !db->init.busy ){
- rc = sqlite3Init(db, &pParse->zErrMsg);
- if( rc!=SQLITE_OK ){
- pParse->rc = rc;
- pParse->nErr++;
- }else if( db->noSharedCache ){
- db->mDbFlags |= DBFLAG_SchemaKnownOk;
- }
- }
- return rc;
-}
-
-
-/*
-** Check schema cookies in all databases. If any cookie is out
-** of date set pParse->rc to SQLITE_SCHEMA. If all schema cookies
-** make no changes to pParse->rc.
-*/
-static void schemaIsValid(Parse *pParse){
- sqlite3 *db = pParse->db;
- int iDb;
- int rc;
- int cookie;
-
- assert( pParse->checkSchema );
- assert( sqlite3_mutex_held(db->mutex) );
- for(iDb=0; iDb<db->nDb; iDb++){
- int openedTransaction = 0; /* True if a transaction is opened */
- Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */
- if( pBt==0 ) continue;
-
- /* If there is not already a read-only (or read-write) transaction opened
- ** on the b-tree database, open one now. If a transaction is opened, it
- ** will be closed immediately after reading the meta-value. */
- if( !sqlite3BtreeIsInReadTrans(pBt) ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
- sqlite3OomFault(db);
- }
- if( rc!=SQLITE_OK ) return;
- openedTransaction = 1;
- }
-
- /* Read the schema cookie from the database. If it does not match the
- ** value stored as part of the in-memory schema representation,
- ** set Parse.rc to SQLITE_SCHEMA. */
- sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
- sqlite3ResetOneSchema(db, iDb);
- pParse->rc = SQLITE_SCHEMA;
- }
-
- /* Close the transaction, if one was opened. */
- if( openedTransaction ){
- sqlite3BtreeCommit(pBt);
- }
- }
-}
-
-/*
-** Convert a schema pointer into the iDb index that indicates
-** which database file in db->aDb[] the schema refers to.
-**
-** If the same database is attached more than once, the first
-** attached database is returned.
-*/
-int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
- int i = -1000000;
-
- /* If pSchema is NULL, then return -1000000. This happens when code in
- ** expr.c is trying to resolve a reference to a transient table (i.e. one
- ** created by a sub-select). In this case the return value of this
- ** function should never be used.
- **
- ** We return -1000000 instead of the more usual -1 simply because using
- ** -1000000 as the incorrect index into db->aDb[] is much
- ** more likely to cause a segfault than -1 (of course there are assert()
- ** statements too, but it never hurts to play the odds).
- */
- assert( sqlite3_mutex_held(db->mutex) );
- if( pSchema ){
- for(i=0; 1; i++){
- assert( i<db->nDb );
- if( db->aDb[i].pSchema==pSchema ){
- break;
- }
- }
- assert( i>=0 && i<db->nDb );
- }
- return i;
-}
-
-/*
-** Free all memory allocations in the pParse object
-*/
-void sqlite3ParserReset(Parse *pParse){
- sqlite3 *db = pParse->db;
- sqlite3DbFree(db, pParse->aLabel);
- sqlite3ExprListDelete(db, pParse->pConstExpr);
- if( db ){
- assert( db->lookaside.bDisable >= pParse->disableLookaside );
- db->lookaside.bDisable -= pParse->disableLookaside;
- }
- pParse->disableLookaside = 0;
-}
-
-/*
-** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
-*/
-static int sqlite3Prepare(
- sqlite3 *db, /* Database handle. */
- const char *zSql, /* UTF-8 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
- Vdbe *pReprepare, /* VM being reprepared */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const char **pzTail /* OUT: End of parsed string */
-){
- char *zErrMsg = 0; /* Error message */
- int rc = SQLITE_OK; /* Result code */
- int i; /* Loop counter */
- Parse sParse; /* Parsing context */
-
- memset(&sParse, 0, PARSE_HDR_SZ);
- memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
- sParse.pReprepare = pReprepare;
- assert( ppStmt && *ppStmt==0 );
- /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
- assert( sqlite3_mutex_held(db->mutex) );
-
- /* For a long-term use prepared statement avoid the use of
- ** lookaside memory.
- */
- if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
- sParse.disableLookaside++;
- db->lookaside.bDisable++;
- }
-
- /* Check to verify that it is possible to get a read lock on all
- ** database schemas. The inability to get a read lock indicates that
- ** some other database connection is holding a write-lock, which in
- ** turn means that the other connection has made uncommitted changes
- ** to the schema.
- **
- ** Were we to proceed and prepare the statement against the uncommitted
- ** schema changes and if those schema changes are subsequently rolled
- ** back and different changes are made in their place, then when this
- ** prepared statement goes to run the schema cookie would fail to detect
- ** the schema change. Disaster would follow.
- **
- ** This thread is currently holding mutexes on all Btrees (because
- ** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it
- ** is not possible for another thread to start a new schema change
- ** while this routine is running. Hence, we do not need to hold
- ** locks on the schema, we just need to make sure nobody else is
- ** holding them.
- **
- ** Note that setting READ_UNCOMMITTED overrides most lock detection,
- ** but it does *not* override schema lock detection, so this all still
- ** works even if READ_UNCOMMITTED is set.
- */
- for(i=0; i<db->nDb; i++) {
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- assert( sqlite3BtreeHoldsMutex(pBt) );
- rc = sqlite3BtreeSchemaLocked(pBt);
- if( rc ){
- const char *zDb = db->aDb[i].zDbSName;
- sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
- testcase( db->flags & SQLITE_ReadUncommit );
- goto end_prepare;
- }
- }
- }
-
- sqlite3VtabUnlockList(db);
-
- sParse.db = db;
- if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
- char *zSqlCopy;
- int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
- testcase( nBytes==mxLen );
- testcase( nBytes==mxLen+1 );
- if( nBytes>mxLen ){
- sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long");
- rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
- goto end_prepare;
- }
- zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
- if( zSqlCopy ){
- sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
- sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
- sqlite3DbFree(db, zSqlCopy);
- }else{
- sParse.zTail = &zSql[nBytes];
- }
- }else{
- sqlite3RunParser(&sParse, zSql, &zErrMsg);
- }
- assert( 0==sParse.nQueryLoop );
-
- if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
- if( sParse.checkSchema ){
- schemaIsValid(&sParse);
- }
- if( db->mallocFailed ){
- sParse.rc = SQLITE_NOMEM_BKPT;
- }
- if( pzTail ){
- *pzTail = sParse.zTail;
- }
- rc = sParse.rc;
-
-#ifndef SQLITE_OMIT_EXPLAIN
- if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
- static const char * const azColName[] = {
- "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
- "id", "parent", "notused", "detail"
- };
- int iFirst, mx;
- if( sParse.explain==2 ){
- sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
- iFirst = 8;
- mx = 12;
- }else{
- sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
- iFirst = 0;
- mx = 8;
- }
- for(i=iFirst; i<mx; i++){
- sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
- azColName[i], SQLITE_STATIC);
- }
- }
-#endif
-
- if( db->init.busy==0 ){
- sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
- }
- if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
- sqlite3VdbeFinalize(sParse.pVdbe);
- assert(!(*ppStmt));
- }else{
- *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
- }
-
- if( zErrMsg ){
- sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
- sqlite3DbFree(db, zErrMsg);
- }else{
- sqlite3Error(db, rc);
- }
-
- /* Delete any TriggerPrg structures allocated while parsing this statement. */
- while( sParse.pTriggerPrg ){
- TriggerPrg *pT = sParse.pTriggerPrg;
- sParse.pTriggerPrg = pT->pNext;
- sqlite3DbFree(db, pT);
- }
-
-end_prepare:
-
- sqlite3ParserReset(&sParse);
- return rc;
-}
-static int sqlite3LockAndPrepare(
- sqlite3 *db, /* Database handle. */
- const char *zSql, /* UTF-8 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
- Vdbe *pOld, /* VM being reprepared */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const char **pzTail /* OUT: End of parsed string */
-){
- int rc;
- int cnt = 0;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- *ppStmt = 0;
- if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
- return SQLITE_MISUSE_BKPT;
- }
- sqlite3_mutex_enter(db->mutex);
- sqlite3BtreeEnterAll(db);
- do{
- /* Make multiple attempts to compile the SQL, until it either succeeds
- ** or encounters a permanent error. A schema problem after one schema
- ** reset is considered a permanent error. */
- rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
- assert( rc==SQLITE_OK || *ppStmt==0 );
- }while( rc==SQLITE_ERROR_RETRY
- || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
- sqlite3BtreeLeaveAll(db);
- rc = sqlite3ApiExit(db, rc);
- assert( (rc&db->errMask)==rc );
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** Rerun the compilation of a statement after a schema change.
-**
-** If the statement is successfully recompiled, return SQLITE_OK. Otherwise,
-** if the statement cannot be recompiled because another connection has
-** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error
-** occurs, return SQLITE_SCHEMA.
-*/
-int sqlite3Reprepare(Vdbe *p){
- int rc;
- sqlite3_stmt *pNew;
- const char *zSql;
- sqlite3 *db;
- u8 prepFlags;
-
- assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) );
- zSql = sqlite3_sql((sqlite3_stmt *)p);
- assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */
- db = sqlite3VdbeDb(p);
- assert( sqlite3_mutex_held(db->mutex) );
- prepFlags = sqlite3VdbePrepareFlags(p);
- rc = sqlite3LockAndPrepare(db, zSql, -1, prepFlags, p, &pNew, 0);
- if( rc ){
- if( rc==SQLITE_NOMEM ){
- sqlite3OomFault(db);
- }
- assert( pNew==0 );
- return rc;
- }else{
- assert( pNew!=0 );
- }
- sqlite3VdbeSwap((Vdbe*)pNew, p);
- sqlite3TransferBindings(pNew, (sqlite3_stmt*)p);
- sqlite3VdbeResetStepResult((Vdbe*)pNew);
- sqlite3VdbeFinalize((Vdbe*)pNew);
- return SQLITE_OK;
-}
-
-
-/*
-** Two versions of the official API. Legacy and new use. In the legacy
-** version, the original SQL text is not saved in the prepared statement
-** and so if a schema change occurs, SQLITE_SCHEMA is returned by
-** sqlite3_step(). In the new version, the original SQL text is retained
-** and the statement is automatically recompiled if an schema change
-** occurs.
-*/
-int sqlite3_prepare(
- sqlite3 *db, /* Database handle. */
- const char *zSql, /* UTF-8 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const char **pzTail /* OUT: End of parsed string */
-){
- int rc;
- rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,0,ppStmt,pzTail);
- assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
- return rc;
-}
-int sqlite3_prepare_v2(
- sqlite3 *db, /* Database handle. */
- const char *zSql, /* UTF-8 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const char **pzTail /* OUT: End of parsed string */
-){
- int rc;
- /* EVIDENCE-OF: R-37923-12173 The sqlite3_prepare_v2() interface works
- ** exactly the same as sqlite3_prepare_v3() with a zero prepFlags
- ** parameter.
- **
- ** Proof in that the 5th parameter to sqlite3LockAndPrepare is 0 */
- rc = sqlite3LockAndPrepare(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,0,
- ppStmt,pzTail);
- assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );
- return rc;
-}
-int sqlite3_prepare_v3(
- sqlite3 *db, /* Database handle. */
- const char *zSql, /* UTF-8 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const char **pzTail /* OUT: End of parsed string */
-){
- int rc;
- /* EVIDENCE-OF: R-56861-42673 sqlite3_prepare_v3() differs from
- ** sqlite3_prepare_v2() only in having the extra prepFlags parameter,
- ** which is a bit array consisting of zero or more of the
- ** SQLITE_PREPARE_* flags.
- **
- ** Proof by comparison to the implementation of sqlite3_prepare_v2()
- ** directly above. */
- rc = sqlite3LockAndPrepare(db,zSql,nBytes,
- SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK),
- 0,ppStmt,pzTail);
- assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );
- return rc;
-}
-
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
-*/
-static int sqlite3Prepare16(
- sqlite3 *db, /* Database handle. */
- const void *zSql, /* UTF-16 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const void **pzTail /* OUT: End of parsed string */
-){
- /* This function currently works by first transforming the UTF-16
- ** encoded string to UTF-8, then invoking sqlite3_prepare(). The
- ** tricky bit is figuring out the pointer to return in *pzTail.
- */
- char *zSql8;
- const char *zTail8 = 0;
- int rc = SQLITE_OK;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- *ppStmt = 0;
- if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
- return SQLITE_MISUSE_BKPT;
- }
- if( nBytes>=0 ){
- int sz;
- const char *z = (const char*)zSql;
- for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
- nBytes = sz;
- }
- sqlite3_mutex_enter(db->mutex);
- zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
- if( zSql8 ){
- rc = sqlite3LockAndPrepare(db, zSql8, -1, prepFlags, 0, ppStmt, &zTail8);
- }
-
- if( zTail8 && pzTail ){
- /* If sqlite3_prepare returns a tail pointer, we calculate the
- ** equivalent pointer into the UTF-16 string by counting the unicode
- ** characters between zSql8 and zTail8, and then returning a pointer
- ** the same number of characters into the UTF-16 string.
- */
- int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
- *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
- }
- sqlite3DbFree(db, zSql8);
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** Two versions of the official API. Legacy and new use. In the legacy
-** version, the original SQL text is not saved in the prepared statement
-** and so if a schema change occurs, SQLITE_SCHEMA is returned by
-** sqlite3_step(). In the new version, the original SQL text is retained
-** and the statement is automatically recompiled if an schema change
-** occurs.
-*/
-int sqlite3_prepare16(
- sqlite3 *db, /* Database handle. */
- const void *zSql, /* UTF-16 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const void **pzTail /* OUT: End of parsed string */
-){
- int rc;
- rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail);
- assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
- return rc;
-}
-int sqlite3_prepare16_v2(
- sqlite3 *db, /* Database handle. */
- const void *zSql, /* UTF-16 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const void **pzTail /* OUT: End of parsed string */
-){
- int rc;
- rc = sqlite3Prepare16(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail);
- assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
- return rc;
-}
-int sqlite3_prepare16_v3(
- sqlite3 *db, /* Database handle. */
- const void *zSql, /* UTF-16 encoded SQL statement. */
- int nBytes, /* Length of zSql in bytes. */
- unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const void **pzTail /* OUT: End of parsed string */
-){
- int rc;
- rc = sqlite3Prepare16(db,zSql,nBytes,
- SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK),
- ppStmt,pzTail);
- assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
- return rc;
-}
-
-#endif /* SQLITE_OMIT_UTF16 */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/printf.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/printf.c
deleted file mode 100644
index 71296ac907f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/printf.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
-** The "printf" code that follows dates from the 1980's. It is in
-** the public domain.
-**
-**************************************************************************
-**
-** This file contains code for a set of "printf"-like routines. These
-** routines format strings much like the printf() from the standard C
-** library, though the implementation here has enhancements to support
-** SQLite.
-*/
-#include "sqliteInt.h"
-
-/*
-** Conversion types fall into various categories as defined by the
-** following enumeration.
-*/
-#define etRADIX 0 /* non-decimal integer types. %x %o */
-#define etFLOAT 1 /* Floating point. %f */
-#define etEXP 2 /* Exponentional notation. %e and %E */
-#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */
-#define etSIZE 4 /* Return number of characters processed so far. %n */
-#define etSTRING 5 /* Strings. %s */
-#define etDYNSTRING 6 /* Dynamically allocated strings. %z */
-#define etPERCENT 7 /* Percent symbol. %% */
-#define etCHARX 8 /* Characters. %c */
-/* The rest are extensions, not normally found in printf() */
-#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
-#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
- NULL pointers replaced by SQL NULL. %Q */
-#define etTOKEN 11 /* a pointer to a Token structure */
-#define etSRCLIST 12 /* a pointer to a SrcList */
-#define etPOINTER 13 /* The %p conversion */
-#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
-#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
-#define etDECIMAL 16 /* %d or %u, but not %x, %o */
-
-#define etINVALID 17 /* Any unrecognized conversion type */
-
-
-/*
-** An "etByte" is an 8-bit unsigned value.
-*/
-typedef unsigned char etByte;
-
-/*
-** Each builtin conversion character (ex: the 'd' in "%d") is described
-** by an instance of the following structure
-*/
-typedef struct et_info { /* Information about each format field */
- char fmttype; /* The format field code letter */
- etByte base; /* The base for radix conversion */
- etByte flags; /* One or more of FLAG_ constants below */
- etByte type; /* Conversion paradigm */
- etByte charset; /* Offset into aDigits[] of the digits string */
- etByte prefix; /* Offset into aPrefix[] of the prefix string */
-} et_info;
-
-/*
-** Allowed values for et_info.flags
-*/
-#define FLAG_SIGNED 1 /* True if the value to convert is signed */
-#define FLAG_STRING 4 /* Allow infinite precision */
-
-
-/*
-** The following table is searched linearly, so it is good to put the
-** most frequently used conversion types first.
-*/
-static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
-static const char aPrefix[] = "-x0\000X0";
-static const et_info fmtinfo[] = {
- { 'd', 10, 1, etDECIMAL, 0, 0 },
- { 's', 0, 4, etSTRING, 0, 0 },
- { 'g', 0, 1, etGENERIC, 30, 0 },
- { 'z', 0, 4, etDYNSTRING, 0, 0 },
- { 'q', 0, 4, etSQLESCAPE, 0, 0 },
- { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
- { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
- { 'c', 0, 0, etCHARX, 0, 0 },
- { 'o', 8, 0, etRADIX, 0, 2 },
- { 'u', 10, 0, etDECIMAL, 0, 0 },
- { 'x', 16, 0, etRADIX, 16, 1 },
- { 'X', 16, 0, etRADIX, 0, 4 },
-#ifndef SQLITE_OMIT_FLOATING_POINT
- { 'f', 0, 1, etFLOAT, 0, 0 },
- { 'e', 0, 1, etEXP, 30, 0 },
- { 'E', 0, 1, etEXP, 14, 0 },
- { 'G', 0, 1, etGENERIC, 14, 0 },
-#endif
- { 'i', 10, 1, etDECIMAL, 0, 0 },
- { 'n', 0, 0, etSIZE, 0, 0 },
- { '%', 0, 0, etPERCENT, 0, 0 },
- { 'p', 16, 0, etPOINTER, 0, 1 },
-
- /* All the rest are undocumented and are for internal use only */
- { 'T', 0, 0, etTOKEN, 0, 0 },
- { 'S', 0, 0, etSRCLIST, 0, 0 },
- { 'r', 10, 1, etORDINAL, 0, 0 },
-};
-
-/*
-** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
-** conversions will work.
-*/
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/*
-** "*val" is a double such that 0.1 <= *val < 10.0
-** Return the ascii code for the leading digit of *val, then
-** multiply "*val" by 10.0 to renormalize.
-**
-** Example:
-** input: *val = 3.14159
-** output: *val = 1.4159 function return = '3'
-**
-** The counter *cnt is incremented each time. After counter exceeds
-** 16 (the number of significant digits in a 64-bit float) '0' is
-** always returned.
-*/
-static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
- int digit;
- LONGDOUBLE_TYPE d;
- if( (*cnt)<=0 ) return '0';
- (*cnt)--;
- digit = (int)*val;
- d = digit;
- digit += '0';
- *val = (*val - d)*10.0;
- return (char)digit;
-}
-#endif /* SQLITE_OMIT_FLOATING_POINT */
-
-/*
-** Set the StrAccum object to an error mode.
-*/
-static void setStrAccumError(StrAccum *p, u8 eError){
- assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
- p->accError = eError;
- p->nAlloc = 0;
-}
-
-/*
-** Extra argument values from a PrintfArguments object
-*/
-static sqlite3_int64 getIntArg(PrintfArguments *p){
- if( p->nArg<=p->nUsed ) return 0;
- return sqlite3_value_int64(p->apArg[p->nUsed++]);
-}
-static double getDoubleArg(PrintfArguments *p){
- if( p->nArg<=p->nUsed ) return 0.0;
- return sqlite3_value_double(p->apArg[p->nUsed++]);
-}
-static char *getTextArg(PrintfArguments *p){
- if( p->nArg<=p->nUsed ) return 0;
- return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
-}
-
-
-/*
-** On machines with a small stack size, you can redefine the
-** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
-*/
-#ifndef SQLITE_PRINT_BUF_SIZE
-# define SQLITE_PRINT_BUF_SIZE 70
-#endif
-#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
-
-/*
-** Render a string given by "fmt" into the StrAccum object.
-*/
-void sqlite3_str_vappendf(
- sqlite3_str *pAccum, /* Accumulate results here */
- const char *fmt, /* Format string */
- va_list ap /* arguments */
-){
- int c; /* Next character in the format string */
- char *bufpt; /* Pointer to the conversion buffer */
- int precision; /* Precision of the current field */
- int length; /* Length of the field */
- int idx; /* A general purpose loop counter */
- int width; /* Width of the current field */
- etByte flag_leftjustify; /* True if "-" flag is present */
- etByte flag_prefix; /* '+' or ' ' or 0 for prefix */
- etByte flag_alternateform; /* True if "#" flag is present */
- etByte flag_altform2; /* True if "!" flag is present */
- etByte flag_zeropad; /* True if field width constant starts with zero */
- etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */
- etByte done; /* Loop termination flag */
- etByte cThousand; /* Thousands separator for %d and %u */
- etByte xtype = etINVALID; /* Conversion paradigm */
- u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
- char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
- sqlite_uint64 longvalue; /* Value for integer types */
- LONGDOUBLE_TYPE realvalue; /* Value for real types */
- const et_info *infop; /* Pointer to the appropriate info structure */
- char *zOut; /* Rendering buffer */
- int nOut; /* Size of the rendering buffer */
- char *zExtra = 0; /* Malloced memory used by some conversion */
-#ifndef SQLITE_OMIT_FLOATING_POINT
- int exp, e2; /* exponent of real numbers */
- int nsd; /* Number of significant digits returned */
- double rounder; /* Used for rounding floating point values */
- etByte flag_dp; /* True if decimal point should be shown */
- etByte flag_rtz; /* True if trailing zeros should be removed */
-#endif
- PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
- char buf[etBUFSIZE]; /* Conversion buffer */
-
- /* pAccum never starts out with an empty buffer that was obtained from
- ** malloc(). This precondition is required by the mprintf("%z...")
- ** optimization. */
- assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
-
- bufpt = 0;
- if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){
- pArgList = va_arg(ap, PrintfArguments*);
- bArgList = 1;
- }else{
- bArgList = 0;
- }
- for(; (c=(*fmt))!=0; ++fmt){
- if( c!='%' ){
- bufpt = (char *)fmt;
-#if HAVE_STRCHRNUL
- fmt = strchrnul(fmt, '%');
-#else
- do{ fmt++; }while( *fmt && *fmt != '%' );
-#endif
- sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt));
- if( *fmt==0 ) break;
- }
- if( (c=(*++fmt))==0 ){
- sqlite3_str_append(pAccum, "%", 1);
- break;
- }
- /* Find out what flags are present */
- flag_leftjustify = flag_prefix = cThousand =
- flag_alternateform = flag_altform2 = flag_zeropad = 0;
- done = 0;
- do{
- switch( c ){
- case '-': flag_leftjustify = 1; break;
- case '+': flag_prefix = '+'; break;
- case ' ': flag_prefix = ' '; break;
- case '#': flag_alternateform = 1; break;
- case '!': flag_altform2 = 1; break;
- case '0': flag_zeropad = 1; break;
- case ',': cThousand = ','; break;
- default: done = 1; break;
- }
- }while( !done && (c=(*++fmt))!=0 );
- /* Get the field width */
- if( c=='*' ){
- if( bArgList ){
- width = (int)getIntArg(pArgList);
- }else{
- width = va_arg(ap,int);
- }
- if( width<0 ){
- flag_leftjustify = 1;
- width = width >= -2147483647 ? -width : 0;
- }
- c = *++fmt;
- }else{
- unsigned wx = 0;
- while( c>='0' && c<='9' ){
- wx = wx*10 + c - '0';
- c = *++fmt;
- }
- testcase( wx>0x7fffffff );
- width = wx & 0x7fffffff;
- }
- assert( width>=0 );
-#ifdef SQLITE_PRINTF_PRECISION_LIMIT
- if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
- width = SQLITE_PRINTF_PRECISION_LIMIT;
- }
-#endif
-
- /* Get the precision */
- if( c=='.' ){
- c = *++fmt;
- if( c=='*' ){
- if( bArgList ){
- precision = (int)getIntArg(pArgList);
- }else{
- precision = va_arg(ap,int);
- }
- c = *++fmt;
- if( precision<0 ){
- precision = precision >= -2147483647 ? -precision : -1;
- }
- }else{
- unsigned px = 0;
- while( c>='0' && c<='9' ){
- px = px*10 + c - '0';
- c = *++fmt;
- }
- testcase( px>0x7fffffff );
- precision = px & 0x7fffffff;
- }
- }else{
- precision = -1;
- }
- assert( precision>=(-1) );
-#ifdef SQLITE_PRINTF_PRECISION_LIMIT
- if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
- precision = SQLITE_PRINTF_PRECISION_LIMIT;
- }
-#endif
-
-
- /* Get the conversion type modifier */
- if( c=='l' ){
- flag_long = 1;
- c = *++fmt;
- if( c=='l' ){
- flag_long = 2;
- c = *++fmt;
- }
- }else{
- flag_long = 0;
- }
- /* Fetch the info entry for the field */
- infop = &fmtinfo[0];
- xtype = etINVALID;
- for(idx=0; idx<ArraySize(fmtinfo); idx++){
- if( c==fmtinfo[idx].fmttype ){
- infop = &fmtinfo[idx];
- xtype = infop->type;
- break;
- }
- }
-
- /*
- ** At this point, variables are initialized as follows:
- **
- ** flag_alternateform TRUE if a '#' is present.
- ** flag_altform2 TRUE if a '!' is present.
- ** flag_prefix '+' or ' ' or zero
- ** flag_leftjustify TRUE if a '-' is present or if the
- ** field width was negative.
- ** flag_zeropad TRUE if the width began with 0.
- ** flag_long 1 for "l", 2 for "ll"
- ** width The specified field width. This is
- ** always non-negative. Zero is the default.
- ** precision The specified precision. The default
- ** is -1.
- ** xtype The class of the conversion.
- ** infop Pointer to the appropriate info struct.
- */
- switch( xtype ){
- case etPOINTER:
- flag_long = sizeof(char*)==sizeof(i64) ? 2 :
- sizeof(char*)==sizeof(long int) ? 1 : 0;
- /* Fall through into the next case */
- case etORDINAL:
- case etRADIX:
- cThousand = 0;
- /* Fall through into the next case */
- case etDECIMAL:
- if( infop->flags & FLAG_SIGNED ){
- i64 v;
- if( bArgList ){
- v = getIntArg(pArgList);
- }else if( flag_long ){
- if( flag_long==2 ){
- v = va_arg(ap,i64) ;
- }else{
- v = va_arg(ap,long int);
- }
- }else{
- v = va_arg(ap,int);
- }
- if( v<0 ){
- if( v==SMALLEST_INT64 ){
- longvalue = ((u64)1)<<63;
- }else{
- longvalue = -v;
- }
- prefix = '-';
- }else{
- longvalue = v;
- prefix = flag_prefix;
- }
- }else{
- if( bArgList ){
- longvalue = (u64)getIntArg(pArgList);
- }else if( flag_long ){
- if( flag_long==2 ){
- longvalue = va_arg(ap,u64);
- }else{
- longvalue = va_arg(ap,unsigned long int);
- }
- }else{
- longvalue = va_arg(ap,unsigned int);
- }
- prefix = 0;
- }
- if( longvalue==0 ) flag_alternateform = 0;
- if( flag_zeropad && precision<width-(prefix!=0) ){
- precision = width-(prefix!=0);
- }
- if( precision<etBUFSIZE-10-etBUFSIZE/3 ){
- nOut = etBUFSIZE;
- zOut = buf;
- }else{
- u64 n = (u64)precision + 10 + precision/3;
- zOut = zExtra = sqlite3Malloc( n );
- if( zOut==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
- nOut = (int)n;
- }
- bufpt = &zOut[nOut-1];
- if( xtype==etORDINAL ){
- static const char zOrd[] = "thstndrd";
- int x = (int)(longvalue % 10);
- if( x>=4 || (longvalue/10)%10==1 ){
- x = 0;
- }
- *(--bufpt) = zOrd[x*2+1];
- *(--bufpt) = zOrd[x*2];
- }
- {
- const char *cset = &aDigits[infop->charset];
- u8 base = infop->base;
- do{ /* Convert to ascii */
- *(--bufpt) = cset[longvalue%base];
- longvalue = longvalue/base;
- }while( longvalue>0 );
- }
- length = (int)(&zOut[nOut-1]-bufpt);
- while( precision>length ){
- *(--bufpt) = '0'; /* Zero pad */
- length++;
- }
- if( cThousand ){
- int nn = (length - 1)/3; /* Number of "," to insert */
- int ix = (length - 1)%3 + 1;
- bufpt -= nn;
- for(idx=0; nn>0; idx++){
- bufpt[idx] = bufpt[idx+nn];
- ix--;
- if( ix==0 ){
- bufpt[++idx] = cThousand;
- nn--;
- ix = 3;
- }
- }
- }
- if( prefix ) *(--bufpt) = prefix; /* Add sign */
- if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
- const char *pre;
- char x;
- pre = &aPrefix[infop->prefix];
- for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
- }
- length = (int)(&zOut[nOut-1]-bufpt);
- break;
- case etFLOAT:
- case etEXP:
- case etGENERIC:
- if( bArgList ){
- realvalue = getDoubleArg(pArgList);
- }else{
- realvalue = va_arg(ap,double);
- }
-#ifdef SQLITE_OMIT_FLOATING_POINT
- length = 0;
-#else
- if( precision<0 ) precision = 6; /* Set default precision */
- if( realvalue<0.0 ){
- realvalue = -realvalue;
- prefix = '-';
- }else{
- prefix = flag_prefix;
- }
- if( xtype==etGENERIC && precision>0 ) precision--;
- testcase( precision>0xfff );
- for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
- if( xtype==etFLOAT ) realvalue += rounder;
- /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
- exp = 0;
- if( sqlite3IsNaN((double)realvalue) ){
- bufpt = "NaN";
- length = 3;
- break;
- }
- if( realvalue>0.0 ){
- LONGDOUBLE_TYPE scale = 1.0;
- while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
- while( realvalue>=1e10*scale && exp<=350 ){ scale *= 1e10; exp+=10; }
- while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
- realvalue /= scale;
- while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
- while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
- if( exp>350 ){
- bufpt = buf;
- buf[0] = prefix;
- memcpy(buf+(prefix!=0),"Inf",4);
- length = 3+(prefix!=0);
- break;
- }
- }
- bufpt = buf;
- /*
- ** If the field type is etGENERIC, then convert to either etEXP
- ** or etFLOAT, as appropriate.
- */
- if( xtype!=etFLOAT ){
- realvalue += rounder;
- if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
- }
- if( xtype==etGENERIC ){
- flag_rtz = !flag_alternateform;
- if( exp<-4 || exp>precision ){
- xtype = etEXP;
- }else{
- precision = precision - exp;
- xtype = etFLOAT;
- }
- }else{
- flag_rtz = flag_altform2;
- }
- if( xtype==etEXP ){
- e2 = 0;
- }else{
- e2 = exp;
- }
- if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){
- bufpt = zExtra
- = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
- if( bufpt==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
- }
- zOut = bufpt;
- nsd = 16 + flag_altform2*10;
- flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
- /* The sign in front of the number */
- if( prefix ){
- *(bufpt++) = prefix;
- }
- /* Digits prior to the decimal point */
- if( e2<0 ){
- *(bufpt++) = '0';
- }else{
- for(; e2>=0; e2--){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
- }
- }
- /* The decimal point */
- if( flag_dp ){
- *(bufpt++) = '.';
- }
- /* "0" digits after the decimal point but before the first
- ** significant digit of the number */
- for(e2++; e2<0; precision--, e2++){
- assert( precision>0 );
- *(bufpt++) = '0';
- }
- /* Significant digits after the decimal point */
- while( (precision--)>0 ){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
- }
- /* Remove trailing zeros and the "." if no digits follow the "." */
- if( flag_rtz && flag_dp ){
- while( bufpt[-1]=='0' ) *(--bufpt) = 0;
- assert( bufpt>zOut );
- if( bufpt[-1]=='.' ){
- if( flag_altform2 ){
- *(bufpt++) = '0';
- }else{
- *(--bufpt) = 0;
- }
- }
- }
- /* Add the "eNNN" suffix */
- if( xtype==etEXP ){
- *(bufpt++) = aDigits[infop->charset];
- if( exp<0 ){
- *(bufpt++) = '-'; exp = -exp;
- }else{
- *(bufpt++) = '+';
- }
- if( exp>=100 ){
- *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */
- exp %= 100;
- }
- *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
- *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */
- }
- *bufpt = 0;
-
- /* The converted number is in buf[] and zero terminated. Output it.
- ** Note that the number is in the usual order, not reversed as with
- ** integer conversions. */
- length = (int)(bufpt-zOut);
- bufpt = zOut;
-
- /* Special case: Add leading zeros if the flag_zeropad flag is
- ** set and we are not left justified */
- if( flag_zeropad && !flag_leftjustify && length < width){
- int i;
- int nPad = width - length;
- for(i=width; i>=nPad; i--){
- bufpt[i] = bufpt[i-nPad];
- }
- i = prefix!=0;
- while( nPad-- ) bufpt[i++] = '0';
- length = width;
- }
-#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
- break;
- case etSIZE:
- if( !bArgList ){
- *(va_arg(ap,int*)) = pAccum->nChar;
- }
- length = width = 0;
- break;
- case etPERCENT:
- buf[0] = '%';
- bufpt = buf;
- length = 1;
- break;
- case etCHARX:
- if( bArgList ){
- bufpt = getTextArg(pArgList);
- length = 1;
- if( bufpt ){
- buf[0] = c = *(bufpt++);
- if( (c&0xc0)==0xc0 ){
- while( length<4 && (bufpt[0]&0xc0)==0x80 ){
- buf[length++] = *(bufpt++);
- }
- }
- }else{
- buf[0] = 0;
- }
- }else{
- unsigned int ch = va_arg(ap,unsigned int);
- if( ch<0x00080 ){
- buf[0] = ch & 0xff;
- length = 1;
- }else if( ch<0x00800 ){
- buf[0] = 0xc0 + (u8)((ch>>6)&0x1f);
- buf[1] = 0x80 + (u8)(ch & 0x3f);
- length = 2;
- }else if( ch<0x10000 ){
- buf[0] = 0xe0 + (u8)((ch>>12)&0x0f);
- buf[1] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[2] = 0x80 + (u8)(ch & 0x3f);
- length = 3;
- }else{
- buf[0] = 0xf0 + (u8)((ch>>18) & 0x07);
- buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
- buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[3] = 0x80 + (u8)(ch & 0x3f);
- length = 4;
- }
- }
- if( precision>1 ){
- width -= precision-1;
- if( width>1 && !flag_leftjustify ){
- sqlite3_str_appendchar(pAccum, width-1, ' ');
- width = 0;
- }
- while( precision-- > 1 ){
- sqlite3_str_append(pAccum, buf, length);
- }
- }
- bufpt = buf;
- flag_altform2 = 1;
- goto adjust_width_for_utf8;
- case etSTRING:
- case etDYNSTRING:
- if( bArgList ){
- bufpt = getTextArg(pArgList);
- xtype = etSTRING;
- }else{
- bufpt = va_arg(ap,char*);
- }
- if( bufpt==0 ){
- bufpt = "";
- }else if( xtype==etDYNSTRING ){
- if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 ){
- /* Special optimization for sqlite3_mprintf("%z..."):
- ** Extend an existing memory allocation rather than creating
- ** a new one. */
- assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
- pAccum->zText = bufpt;
- pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt);
- pAccum->nChar = 0x7fffffff & (int)strlen(bufpt);
- pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED;
- length = 0;
- break;
- }
- zExtra = bufpt;
- }
- if( precision>=0 ){
- if( flag_altform2 ){
- /* Set length to the number of bytes needed in order to display
- ** precision characters */
- unsigned char *z = (unsigned char*)bufpt;
- while( precision-- > 0 && z[0] ){
- SQLITE_SKIP_UTF8(z);
- }
- length = (int)(z - (unsigned char*)bufpt);
- }else{
- for(length=0; length<precision && bufpt[length]; length++){}
- }
- }else{
- length = 0x7fffffff & (int)strlen(bufpt);
- }
- adjust_width_for_utf8:
- if( flag_altform2 && width>0 ){
- /* Adjust width to account for extra bytes in UTF-8 characters */
- int ii = length - 1;
- while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
- }
- break;
- case etSQLESCAPE: /* %q: Escape ' characters */
- case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
- case etSQLESCAPE3: { /* %w: Escape " characters */
- int i, j, k, n, isnull;
- int needQuote;
- char ch;
- char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
- char *escarg;
-
- if( bArgList ){
- escarg = getTextArg(pArgList);
- }else{
- escarg = va_arg(ap,char*);
- }
- isnull = escarg==0;
- if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
- /* For %q, %Q, and %w, the precision is the number of byte (or
- ** characters if the ! flags is present) to use from the input.
- ** Because of the extra quoting characters inserted, the number
- ** of output characters may be larger than the precision.
- */
- k = precision;
- for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
- if( ch==q ) n++;
- if( flag_altform2 && (ch&0xc0)==0xc0 ){
- while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
- }
- }
- needQuote = !isnull && xtype==etSQLESCAPE2;
- n += i + 3;
- if( n>etBUFSIZE ){
- bufpt = zExtra = sqlite3Malloc( n );
- if( bufpt==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
- }else{
- bufpt = buf;
- }
- j = 0;
- if( needQuote ) bufpt[j++] = q;
- k = i;
- for(i=0; i<k; i++){
- bufpt[j++] = ch = escarg[i];
- if( ch==q ) bufpt[j++] = ch;
- }
- if( needQuote ) bufpt[j++] = q;
- bufpt[j] = 0;
- length = j;
- goto adjust_width_for_utf8;
- }
- case etTOKEN: {
- Token *pToken;
- if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
- pToken = va_arg(ap, Token*);
- assert( bArgList==0 );
- if( pToken && pToken->n ){
- sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
- }
- length = width = 0;
- break;
- }
- case etSRCLIST: {
- SrcList *pSrc;
- int k;
- struct SrcList_item *pItem;
- if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
- pSrc = va_arg(ap, SrcList*);
- k = va_arg(ap, int);
- pItem = &pSrc->a[k];
- assert( bArgList==0 );
- assert( k>=0 && k<pSrc->nSrc );
- if( pItem->zDatabase ){
- sqlite3_str_appendall(pAccum, pItem->zDatabase);
- sqlite3_str_append(pAccum, ".", 1);
- }
- sqlite3_str_appendall(pAccum, pItem->zName);
- length = width = 0;
- break;
- }
- default: {
- assert( xtype==etINVALID );
- return;
- }
- }/* End switch over the format type */
- /*
- ** The text of the conversion is pointed to by "bufpt" and is
- ** "length" characters long. The field width is "width". Do
- ** the output. Both length and width are in bytes, not characters,
- ** at this point. If the "!" flag was present on string conversions
- ** indicating that width and precision should be expressed in characters,
- ** then the values have been translated prior to reaching this point.
- */
- width -= length;
- if( width>0 ){
- if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');
- sqlite3_str_append(pAccum, bufpt, length);
- if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');
- }else{
- sqlite3_str_append(pAccum, bufpt, length);
- }
-
- if( zExtra ){
- sqlite3DbFree(pAccum->db, zExtra);
- zExtra = 0;
- }
- }/* End for loop over the format string */
-} /* End of function */
-
-/*
-** Enlarge the memory allocation on a StrAccum object so that it is
-** able to accept at least N more bytes of text.
-**
-** Return the number of bytes of text that StrAccum is able to accept
-** after the attempted enlargement. The value returned might be zero.
-*/
-static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
- char *zNew;
- assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
- if( p->accError ){
- testcase(p->accError==SQLITE_TOOBIG);
- testcase(p->accError==SQLITE_NOMEM);
- return 0;
- }
- if( p->mxAlloc==0 ){
- N = p->nAlloc - p->nChar - 1;
- setStrAccumError(p, SQLITE_TOOBIG);
- return N;
- }else{
- char *zOld = isMalloced(p) ? p->zText : 0;
- i64 szNew = p->nChar;
- szNew += N + 1;
- if( szNew+p->nChar<=p->mxAlloc ){
- /* Force exponential buffer size growth as long as it does not overflow,
- ** to avoid having to call this routine too often */
- szNew += p->nChar;
- }
- if( szNew > p->mxAlloc ){
- sqlite3_str_reset(p);
- setStrAccumError(p, SQLITE_TOOBIG);
- return 0;
- }else{
- p->nAlloc = (int)szNew;
- }
- if( p->db ){
- zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
- }else{
- zNew = sqlite3_realloc64(zOld, p->nAlloc);
- }
- if( zNew ){
- assert( p->zText!=0 || p->nChar==0 );
- if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
- p->zText = zNew;
- p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
- p->printfFlags |= SQLITE_PRINTF_MALLOCED;
- }else{
- sqlite3_str_reset(p);
- setStrAccumError(p, SQLITE_NOMEM);
- return 0;
- }
- }
- return N;
-}
-
-/*
-** Append N copies of character c to the given string buffer.
-*/
-void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){
- testcase( p->nChar + (i64)N > 0x7fffffff );
- if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
- return;
- }
- while( (N--)>0 ) p->zText[p->nChar++] = c;
-}
-
-/*
-** The StrAccum "p" is not large enough to accept N new bytes of z[].
-** So enlarge if first, then do the append.
-**
-** This is a helper routine to sqlite3_str_append() that does special-case
-** work (enlarging the buffer) using tail recursion, so that the
-** sqlite3_str_append() routine can use fast calling semantics.
-*/
-static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
- N = sqlite3StrAccumEnlarge(p, N);
- if( N>0 ){
- memcpy(&p->zText[p->nChar], z, N);
- p->nChar += N;
- }
-}
-
-/*
-** Append N bytes of text from z to the StrAccum object. Increase the
-** size of the memory allocation for StrAccum if necessary.
-*/
-void sqlite3_str_append(sqlite3_str *p, const char *z, int N){
- assert( z!=0 || N==0 );
- assert( p->zText!=0 || p->nChar==0 || p->accError );
- assert( N>=0 );
- assert( p->accError==0 || p->nAlloc==0 );
- if( p->nChar+N >= p->nAlloc ){
- enlargeAndAppend(p,z,N);
- }else if( N ){
- assert( p->zText );
- p->nChar += N;
- memcpy(&p->zText[p->nChar-N], z, N);
- }
-}
-
-/*
-** Append the complete text of zero-terminated string z[] to the p string.
-*/
-void sqlite3_str_appendall(sqlite3_str *p, const char *z){
- sqlite3_str_append(p, z, sqlite3Strlen30(z));
-}
-
-
-/*
-** Finish off a string by making sure it is zero-terminated.
-** Return a pointer to the resulting string. Return a NULL
-** pointer if any kind of error was encountered.
-*/
-static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
- char *zText;
- assert( p->mxAlloc>0 && !isMalloced(p) );
- zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
- if( zText ){
- memcpy(zText, p->zText, p->nChar+1);
- p->printfFlags |= SQLITE_PRINTF_MALLOCED;
- }else{
- setStrAccumError(p, SQLITE_NOMEM);
- }
- p->zText = zText;
- return zText;
-}
-char *sqlite3StrAccumFinish(StrAccum *p){
- if( p->zText ){
- p->zText[p->nChar] = 0;
- if( p->mxAlloc>0 && !isMalloced(p) ){
- return strAccumFinishRealloc(p);
- }
- }
- return p->zText;
-}
-
-/*
-** This singleton is an sqlite3_str object that is returned if
-** sqlite3_malloc() fails to provide space for a real one. This
-** sqlite3_str object accepts no new text and always returns
-** an SQLITE_NOMEM error.
-*/
-static sqlite3_str sqlite3OomStr = {
- 0, 0, 0, 0, 0, SQLITE_NOMEM, 0
-};
-
-/* Finalize a string created using sqlite3_str_new().
-*/
-char *sqlite3_str_finish(sqlite3_str *p){
- char *z;
- if( p!=0 && p!=&sqlite3OomStr ){
- z = sqlite3StrAccumFinish(p);
- sqlite3_free(p);
- }else{
- z = 0;
- }
- return z;
-}
-
-/* Return any error code associated with p */
-int sqlite3_str_errcode(sqlite3_str *p){
- return p ? p->accError : SQLITE_NOMEM;
-}
-
-/* Return the current length of p in bytes */
-int sqlite3_str_length(sqlite3_str *p){
- return p ? p->nChar : 0;
-}
-
-/* Return the current value for p */
-char *sqlite3_str_value(sqlite3_str *p){
- if( p==0 || p->nChar==0 ) return 0;
- p->zText[p->nChar] = 0;
- return p->zText;
-}
-
-/*
-** Reset an StrAccum string. Reclaim all malloced memory.
-*/
-void sqlite3_str_reset(StrAccum *p){
- if( isMalloced(p) ){
- sqlite3DbFree(p->db, p->zText);
- p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
- }
- p->nAlloc = 0;
- p->nChar = 0;
- p->zText = 0;
-}
-
-/*
-** Initialize a string accumulator.
-**
-** p: The accumulator to be initialized.
-** db: Pointer to a database connection. May be NULL. Lookaside
-** memory is used if not NULL. db->mallocFailed is set appropriately
-** when not NULL.
-** zBase: An initial buffer. May be NULL in which case the initial buffer
-** is malloced.
-** n: Size of zBase in bytes. If total space requirements never exceed
-** n then no memory allocations ever occur.
-** mx: Maximum number of bytes to accumulate. If mx==0 then no memory
-** allocations will ever occur.
-*/
-void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
- p->zText = zBase;
- p->db = db;
- p->nAlloc = n;
- p->mxAlloc = mx;
- p->nChar = 0;
- p->accError = 0;
- p->printfFlags = 0;
-}
-
-/* Allocate and initialize a new dynamic string object */
-sqlite3_str *sqlite3_str_new(sqlite3 *db){
- sqlite3_str *p = sqlite3_malloc64(sizeof(*p));
- if( p ){
- sqlite3StrAccumInit(p, 0, 0, 0,
- db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
- }else{
- p = &sqlite3OomStr;
- }
- return p;
-}
-
-/*
-** Print into memory obtained from sqliteMalloc(). Use the internal
-** %-conversion extensions.
-*/
-char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
- char *z;
- char zBase[SQLITE_PRINT_BUF_SIZE];
- StrAccum acc;
- assert( db!=0 );
- sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase),
- db->aLimit[SQLITE_LIMIT_LENGTH]);
- acc.printfFlags = SQLITE_PRINTF_INTERNAL;
- sqlite3_str_vappendf(&acc, zFormat, ap);
- z = sqlite3StrAccumFinish(&acc);
- if( acc.accError==SQLITE_NOMEM ){
- sqlite3OomFault(db);
- }
- return z;
-}
-
-/*
-** Print into memory obtained from sqliteMalloc(). Use the internal
-** %-conversion extensions.
-*/
-char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
- va_list ap;
- char *z;
- va_start(ap, zFormat);
- z = sqlite3VMPrintf(db, zFormat, ap);
- va_end(ap);
- return z;
-}
-
-/*
-** Print into memory obtained from sqlite3_malloc(). Omit the internal
-** %-conversion extensions.
-*/
-char *sqlite3_vmprintf(const char *zFormat, va_list ap){
- char *z;
- char zBase[SQLITE_PRINT_BUF_SIZE];
- StrAccum acc;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( zFormat==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
- sqlite3_str_vappendf(&acc, zFormat, ap);
- z = sqlite3StrAccumFinish(&acc);
- return z;
-}
-
-/*
-** Print into memory obtained from sqlite3_malloc()(). Omit the internal
-** %-conversion extensions.
-*/
-char *sqlite3_mprintf(const char *zFormat, ...){
- va_list ap;
- char *z;
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return 0;
-#endif
- va_start(ap, zFormat);
- z = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- return z;
-}
-
-/*
-** sqlite3_snprintf() works like snprintf() except that it ignores the
-** current locale settings. This is important for SQLite because we
-** are not able to use a "," as the decimal point in place of "." as
-** specified by some locales.
-**
-** Oops: The first two arguments of sqlite3_snprintf() are backwards
-** from the snprintf() standard. Unfortunately, it is too late to change
-** this without breaking compatibility, so we just have to live with the
-** mistake.
-**
-** sqlite3_vsnprintf() is the varargs version.
-*/
-char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
- StrAccum acc;
- if( n<=0 ) return zBuf;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( zBuf==0 || zFormat==0 ) {
- (void)SQLITE_MISUSE_BKPT;
- if( zBuf ) zBuf[0] = 0;
- return zBuf;
- }
-#endif
- sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
- sqlite3_str_vappendf(&acc, zFormat, ap);
- zBuf[acc.nChar] = 0;
- return zBuf;
-}
-char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
- char *z;
- va_list ap;
- va_start(ap,zFormat);
- z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
- va_end(ap);
- return z;
-}
-
-/*
-** This is the routine that actually formats the sqlite3_log() message.
-** We house it in a separate routine from sqlite3_log() to avoid using
-** stack space on small-stack systems when logging is disabled.
-**
-** sqlite3_log() must render into a static buffer. It cannot dynamically
-** allocate memory because it might be called while the memory allocator
-** mutex is held.
-**
-** sqlite3_str_vappendf() might ask for *temporary* memory allocations for
-** certain format characters (%q) or for very large precisions or widths.
-** Care must be taken that any sqlite3_log() calls that occur while the
-** memory mutex is held do not use these mechanisms.
-*/
-static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
- StrAccum acc; /* String accumulator */
- char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
-
- sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
- sqlite3_str_vappendf(&acc, zFormat, ap);
- sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
- sqlite3StrAccumFinish(&acc));
-}
-
-/*
-** Format and write a message to the log if logging is enabled.
-*/
-void sqlite3_log(int iErrCode, const char *zFormat, ...){
- va_list ap; /* Vararg list */
- if( sqlite3GlobalConfig.xLog ){
- va_start(ap, zFormat);
- renderLogMsg(iErrCode, zFormat, ap);
- va_end(ap);
- }
-}
-
-#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
-/*
-** A version of printf() that understands %lld. Used for debugging.
-** The printf() built into some versions of windows does not understand %lld
-** and segfaults if you give it a long long int.
-*/
-void sqlite3DebugPrintf(const char *zFormat, ...){
- va_list ap;
- StrAccum acc;
- char zBuf[500];
- sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
- va_start(ap,zFormat);
- sqlite3_str_vappendf(&acc, zFormat, ap);
- va_end(ap);
- sqlite3StrAccumFinish(&acc);
-#ifdef SQLITE_OS_TRACE_PROC
- {
- extern void SQLITE_OS_TRACE_PROC(const char *zBuf, int nBuf);
- SQLITE_OS_TRACE_PROC(zBuf, sizeof(zBuf));
- }
-#else
- fprintf(stdout,"%s", zBuf);
- fflush(stdout);
-#endif
-}
-#endif
-
-
-/*
-** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument
-** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats.
-*/
-void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
- va_list ap;
- va_start(ap,zFormat);
- sqlite3_str_vappendf(p, zFormat, ap);
- va_end(ap);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/random.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/random.c
deleted file mode 100644
index d4ae77c4355..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/random.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains code to implement a pseudo-random number
-** generator (PRNG) for SQLite.
-**
-** Random numbers are used by some of the database backends in order
-** to generate random integer keys for tables or random filenames.
-*/
-#include "sqliteInt.h"
-
-
-/* All threads share a single random number generator.
-** This structure is the current state of the generator.
-*/
-static SQLITE_WSD struct sqlite3PrngType {
- unsigned char isInit; /* True if initialized */
- unsigned char i, j; /* State variables */
- unsigned char s[256]; /* State variables */
-} sqlite3Prng;
-
-/*
-** Return N random bytes.
-*/
-void sqlite3_randomness(int N, void *pBuf){
- unsigned char t;
- unsigned char *zBuf = pBuf;
-
- /* The "wsdPrng" macro will resolve to the pseudo-random number generator
- ** state vector. If writable static data is unsupported on the target,
- ** we have to locate the state vector at run-time. In the more common
- ** case where writable static data is supported, wsdPrng can refer directly
- ** to the "sqlite3Prng" state vector declared above.
- */
-#ifdef SQLITE_OMIT_WSD
- struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
-# define wsdPrng p[0]
-#else
-# define wsdPrng sqlite3Prng
-#endif
-
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex;
-#endif
-
-#ifndef SQLITE_OMIT_AUTOINIT
- if( sqlite3_initialize() ) return;
-#endif
-
-#if SQLITE_THREADSAFE
- mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
-#endif
-
- sqlite3_mutex_enter(mutex);
- if( N<=0 || pBuf==0 ){
- wsdPrng.isInit = 0;
- sqlite3_mutex_leave(mutex);
- return;
- }
-
- /* Initialize the state of the random number generator once,
- ** the first time this routine is called. The seed value does
- ** not need to contain a lot of randomness since we are not
- ** trying to do secure encryption or anything like that...
- **
- ** Nothing in this file or anywhere else in SQLite does any kind of
- ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
- ** number generator) not as an encryption device.
- */
- if( !wsdPrng.isInit ){
- int i;
- char k[256];
- wsdPrng.j = 0;
- wsdPrng.i = 0;
- sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
- for(i=0; i<256; i++){
- wsdPrng.s[i] = (u8)i;
- }
- for(i=0; i<256; i++){
- wsdPrng.j += wsdPrng.s[i] + k[i];
- t = wsdPrng.s[wsdPrng.j];
- wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
- wsdPrng.s[i] = t;
- }
- wsdPrng.isInit = 1;
- }
-
- assert( N>0 );
- do{
- wsdPrng.i++;
- t = wsdPrng.s[wsdPrng.i];
- wsdPrng.j += t;
- wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
- wsdPrng.s[wsdPrng.j] = t;
- t += wsdPrng.s[wsdPrng.i];
- *(zBuf++) = wsdPrng.s[t];
- }while( --N );
- sqlite3_mutex_leave(mutex);
-}
-
-#ifndef SQLITE_UNTESTABLE
-/*
-** For testing purposes, we sometimes want to preserve the state of
-** PRNG and restore the PRNG to its saved state at a later time, or
-** to reset the PRNG to its initial state. These routines accomplish
-** those tasks.
-**
-** The sqlite3_test_control() interface calls these routines to
-** control the PRNG.
-*/
-static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
-void sqlite3PrngSaveState(void){
- memcpy(
- &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
- &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
- sizeof(sqlite3Prng)
- );
-}
-void sqlite3PrngRestoreState(void){
- memcpy(
- &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
- &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
- sizeof(sqlite3Prng)
- );
-}
-#endif /* SQLITE_UNTESTABLE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/resolve.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/resolve.c
deleted file mode 100644
index d9ce28682c8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/resolve.c
+++ /dev/null
@@ -1,1583 +0,0 @@
-/*
-** 2008 August 18
-**
-** 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 contains routines used for walking the parser tree and
-** resolve all identifiers by associating them with a particular
-** table and column.
-*/
-#include "sqliteInt.h"
-
-/*
-** Walk the expression tree pExpr and increase the aggregate function
-** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
-** This needs to occur when copying a TK_AGG_FUNCTION node from an
-** outer query into an inner subquery.
-**
-** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
-** is a helper function - a callback for the tree walker.
-*/
-static int incrAggDepth(Walker *pWalker, Expr *pExpr){
- if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
- return WRC_Continue;
-}
-static void incrAggFunctionDepth(Expr *pExpr, int N){
- if( N>0 ){
- Walker w;
- memset(&w, 0, sizeof(w));
- w.xExprCallback = incrAggDepth;
- w.u.n = N;
- sqlite3WalkExpr(&w, pExpr);
- }
-}
-
-/*
-** Turn the pExpr expression into an alias for the iCol-th column of the
-** result set in pEList.
-**
-** If the reference is followed by a COLLATE operator, then make sure
-** the COLLATE operator is preserved. For example:
-**
-** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
-**
-** Should be transformed into:
-**
-** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
-**
-** The nSubquery parameter specifies how many levels of subquery the
-** alias is removed from the original expression. The usual value is
-** zero but it might be more if the alias is contained within a subquery
-** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
-** structures must be increased by the nSubquery amount.
-*/
-static void resolveAlias(
- Parse *pParse, /* Parsing context */
- ExprList *pEList, /* A result set */
- int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
- Expr *pExpr, /* Transform this into an alias to the result set */
- const char *zType, /* "GROUP" or "ORDER" or "" */
- int nSubquery /* Number of subqueries that the label is moving */
-){
- Expr *pOrig; /* The iCol-th column of the result set */
- Expr *pDup; /* Copy of pOrig */
- sqlite3 *db; /* The database connection */
-
- assert( iCol>=0 && iCol<pEList->nExpr );
- pOrig = pEList->a[iCol].pExpr;
- assert( pOrig!=0 );
- db = pParse->db;
- pDup = sqlite3ExprDup(db, pOrig, 0);
- if( pDup!=0 ){
- if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
- if( pExpr->op==TK_COLLATE ){
- pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
- }
- ExprSetProperty(pDup, EP_Alias);
-
- /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
- ** prevents ExprDelete() from deleting the Expr structure itself,
- ** allowing it to be repopulated by the memcpy() on the following line.
- ** The pExpr->u.zToken might point into memory that will be freed by the
- ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
- ** make a copy of the token before doing the sqlite3DbFree().
- */
- ExprSetProperty(pExpr, EP_Static);
- sqlite3ExprDelete(db, pExpr);
- memcpy(pExpr, pDup, sizeof(*pExpr));
- if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
- assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
- pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
- pExpr->flags |= EP_MemToken;
- }
- sqlite3DbFree(db, pDup);
- }
- ExprSetProperty(pExpr, EP_Alias);
-}
-
-
-/*
-** Return TRUE if the name zCol occurs anywhere in the USING clause.
-**
-** Return FALSE if the USING clause is NULL or if it does not contain
-** zCol.
-*/
-static int nameInUsingClause(IdList *pUsing, const char *zCol){
- if( pUsing ){
- int k;
- for(k=0; k<pUsing->nId; k++){
- if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1;
- }
- }
- return 0;
-}
-
-/*
-** Subqueries stores the original database, table and column names for their
-** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
-** Check to see if the zSpan given to this routine matches the zDb, zTab,
-** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
-** match anything.
-*/
-int sqlite3MatchSpanName(
- const char *zSpan,
- const char *zCol,
- const char *zTab,
- const char *zDb
-){
- int n;
- for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
- if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
- return 0;
- }
- zSpan += n+1;
- for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
- if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){
- return 0;
- }
- zSpan += n+1;
- if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
- return 0;
- }
- return 1;
-}
-
-/*
-** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-** that name in the set of source tables in pSrcList and make the pExpr
-** expression node refer back to that source column. The following changes
-** are made to pExpr:
-**
-** pExpr->iDb Set the index in db->aDb[] of the database X
-** (even if X is implied).
-** pExpr->iTable Set to the cursor number for the table obtained
-** from pSrcList.
-** pExpr->pTab Points to the Table structure of X.Y (even if
-** X and/or Y are implied.)
-** pExpr->iColumn Set to the column number within the table.
-** pExpr->op Set to TK_COLUMN.
-** pExpr->pLeft Any expression this points to is deleted
-** pExpr->pRight Any expression this points to is deleted.
-**
-** The zDb variable is the name of the database (the "X"). This value may be
-** NULL meaning that name is of the form Y.Z or Z. Any available database
-** can be used. The zTable variable is the name of the table (the "Y"). This
-** value can be NULL if zDb is also NULL. If zTable is NULL it
-** means that the form of the name is Z and that columns from any table
-** can be used.
-**
-** If the name cannot be resolved unambiguously, leave an error message
-** in pParse and return WRC_Abort. Return WRC_Prune on success.
-*/
-static int lookupName(
- Parse *pParse, /* The parsing context */
- const char *zDb, /* Name of the database containing table, or NULL */
- const char *zTab, /* Name of table containing column, or NULL */
- const char *zCol, /* Name of the column. */
- NameContext *pNC, /* The name context used to resolve the name */
- Expr *pExpr /* Make this EXPR node point to the selected column */
-){
- int i, j; /* Loop counters */
- int cnt = 0; /* Number of matching column names */
- int cntTab = 0; /* Number of matching table names */
- int nSubquery = 0; /* How many levels of subquery */
- sqlite3 *db = pParse->db; /* The database connection */
- struct SrcList_item *pItem; /* Use for looping over pSrcList items */
- struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
- NameContext *pTopNC = pNC; /* First namecontext in the list */
- Schema *pSchema = 0; /* Schema of the expression */
- int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
- Table *pTab = 0; /* Table hold the row */
- Column *pCol; /* A column of pTab */
-
- assert( pNC ); /* the name context cannot be NULL. */
- assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
- assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
-
- /* Initialize the node to no-match */
- pExpr->iTable = -1;
- pExpr->pTab = 0;
- ExprSetVVAProperty(pExpr, EP_NoReduce);
-
- /* Translate the schema name in zDb into a pointer to the corresponding
- ** schema. If not found, pSchema will remain NULL and nothing will match
- ** resulting in an appropriate error message toward the end of this routine
- */
- if( zDb ){
- testcase( pNC->ncFlags & NC_PartIdx );
- testcase( pNC->ncFlags & NC_IsCheck );
- if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){
- /* Silently ignore database qualifiers inside CHECK constraints and
- ** partial indices. Do not raise errors because that might break
- ** legacy and because it does not hurt anything to just ignore the
- ** database name. */
- zDb = 0;
- }else{
- for(i=0; i<db->nDb; i++){
- assert( db->aDb[i].zDbSName );
- if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){
- pSchema = db->aDb[i].pSchema;
- break;
- }
- }
- }
- }
-
- /* Start at the inner-most context and move outward until a match is found */
- assert( pNC && cnt==0 );
- do{
- ExprList *pEList;
- SrcList *pSrcList = pNC->pSrcList;
-
- if( pSrcList ){
- for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
- pTab = pItem->pTab;
- assert( pTab!=0 && pTab->zName!=0 );
- assert( pTab->nCol>0 );
- if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
- int hit = 0;
- pEList = pItem->pSelect->pEList;
- for(j=0; j<pEList->nExpr; j++){
- if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
- cnt++;
- cntTab = 2;
- pMatch = pItem;
- pExpr->iColumn = j;
- hit = 1;
- }
- }
- if( hit || zTab==0 ) continue;
- }
- if( zDb && pTab->pSchema!=pSchema ){
- continue;
- }
- if( zTab ){
- const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
- assert( zTabName!=0 );
- if( sqlite3StrICmp(zTabName, zTab)!=0 ){
- continue;
- }
- }
- if( 0==(cntTab++) ){
- pMatch = pItem;
- }
- for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- /* If there has been exactly one prior match and this match
- ** is for the right-hand table of a NATURAL JOIN or is in a
- ** USING clause, then skip this match.
- */
- if( cnt==1 ){
- if( pItem->fg.jointype & JT_NATURAL ) continue;
- if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
- }
- cnt++;
- pMatch = pItem;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
- break;
- }
- }
- }
- if( pMatch ){
- pExpr->iTable = pMatch->iCursor;
- pExpr->pTab = pMatch->pTab;
- /* RIGHT JOIN not (yet) supported */
- assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
- if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
- ExprSetProperty(pExpr, EP_CanBeNull);
- }
- pSchema = pExpr->pTab->pSchema;
- }
- } /* if( pSrcList ) */
-
-#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT)
- /* If we have not already resolved the name, then maybe
- ** it is a new.* or old.* trigger argument reference. Or
- ** maybe it is an excluded.* from an upsert.
- */
- if( zDb==0 && zTab!=0 && cntTab==0 ){
- pTab = 0;
-#ifndef SQLITE_OMIT_TRIGGER
- if( pParse->pTriggerTab!=0 ){
- int op = pParse->eTriggerOp;
- assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
- if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
- pExpr->iTable = 1;
- pTab = pParse->pTriggerTab;
- }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
- pExpr->iTable = 0;
- pTab = pParse->pTriggerTab;
- }
- }
-#endif /* SQLITE_OMIT_TRIGGER */
-#ifndef SQLITE_OMIT_UPSERT
- if( (pNC->ncFlags & NC_UUpsert)!=0 ){
- Upsert *pUpsert = pNC->uNC.pUpsert;
- if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
- pTab = pUpsert->pUpsertSrc->a[0].pTab;
- pExpr->iTable = 2;
- }
- }
-#endif /* SQLITE_OMIT_UPSERT */
-
- if( pTab ){
- int iCol;
- pSchema = pTab->pSchema;
- cntTab++;
- for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- if( iCol==pTab->iPKey ){
- iCol = -1;
- }
- break;
- }
- }
- if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
- /* IMP: R-51414-32910 */
- iCol = -1;
- }
- if( iCol<pTab->nCol ){
- cnt++;
-#ifndef SQLITE_OMIT_UPSERT
- if( pExpr->iTable==2 ){
- testcase( iCol==(-1) );
- pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
- eNewExprOp = TK_REGISTER;
- ExprSetProperty(pExpr, EP_Alias);
- }else
-#endif /* SQLITE_OMIT_UPSERT */
- {
-#ifndef SQLITE_OMIT_TRIGGER
- if( iCol<0 ){
- pExpr->affinity = SQLITE_AFF_INTEGER;
- }else if( pExpr->iTable==0 ){
- testcase( iCol==31 );
- testcase( iCol==32 );
- pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
- }else{
- testcase( iCol==31 );
- testcase( iCol==32 );
- pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
- }
- pExpr->pTab = pTab;
- pExpr->iColumn = (i16)iCol;
- eNewExprOp = TK_TRIGGER;
-#endif /* SQLITE_OMIT_TRIGGER */
- }
- }
- }
- }
-#endif /* !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) */
-
- /*
- ** Perhaps the name is a reference to the ROWID
- */
- if( cnt==0
- && cntTab==1
- && pMatch
- && (pNC->ncFlags & NC_IdxExpr)==0
- && sqlite3IsRowid(zCol)
- && VisibleRowid(pMatch->pTab)
- ){
- cnt = 1;
- pExpr->iColumn = -1;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- }
-
- /*
- ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
- ** might refer to an result-set alias. This happens, for example, when
- ** we are resolving names in the WHERE clause of the following command:
- **
- ** SELECT a+b AS x FROM table WHERE x<10;
- **
- ** In cases like this, replace pExpr with a copy of the expression that
- ** forms the result set entry ("a+b" in the example) and return immediately.
- ** Note that the expression in the result set should have already been
- ** resolved by the time the WHERE clause is resolved.
- **
- ** The ability to use an output result-set column in the WHERE, GROUP BY,
- ** or HAVING clauses, or as part of a larger expression in the ORDER BY
- ** clause is not standard SQL. This is a (goofy) SQLite extension, that
- ** is supported for backwards compatibility only. Hence, we issue a warning
- ** on sqlite3_log() whenever the capability is used.
- */
- if( (pNC->ncFlags & NC_UEList)!=0
- && cnt==0
- && zTab==0
- ){
- pEList = pNC->uNC.pEList;
- assert( pEList!=0 );
- for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- Expr *pOrig;
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- assert( pExpr->x.pList==0 );
- assert( pExpr->x.pSelect==0 );
- pOrig = pEList->a[j].pExpr;
- if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
- sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
- return WRC_Abort;
- }
- if( sqlite3ExprVectorSize(pOrig)!=1 ){
- sqlite3ErrorMsg(pParse, "row value misused");
- return WRC_Abort;
- }
- resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
- cnt = 1;
- pMatch = 0;
- assert( zTab==0 && zDb==0 );
- goto lookupname_end;
- }
- }
- }
-
- /* Advance to the next name context. The loop will exit when either
- ** we have a match (cnt>0) or when we run out of name contexts.
- */
- if( cnt ) break;
- pNC = pNC->pNext;
- nSubquery++;
- }while( pNC );
-
-
- /*
- ** If X and Y are NULL (in other words if only the column name Z is
- ** supplied) and the value of Z is enclosed in double-quotes, then
- ** Z is a string literal if it doesn't match any column names. In that
- ** case, we need to return right away and not make any changes to
- ** pExpr.
- **
- ** Because no reference was made to outer contexts, the pNC->nRef
- ** fields are not changed in any context.
- */
- if( cnt==0 && zTab==0 ){
- assert( pExpr->op==TK_ID );
- if( ExprHasProperty(pExpr,EP_DblQuoted) ){
- pExpr->op = TK_STRING;
- pExpr->pTab = 0;
- return WRC_Prune;
- }
- if( sqlite3ExprIdToTrueFalse(pExpr) ){
- return WRC_Prune;
- }
- }
-
- /*
- ** cnt==0 means there was not match. cnt>1 means there were two or
- ** more matches. Either way, we have an error.
- */
- if( cnt!=1 ){
- const char *zErr;
- zErr = cnt==0 ? "no such column" : "ambiguous column name";
- if( zDb ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
- }else if( zTab ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
- }else{
- sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
- }
- pParse->checkSchema = 1;
- pTopNC->nErr++;
- }
-
- /* If a column from a table in pSrcList is referenced, then record
- ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
- ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
- ** column number is greater than the number of bits in the bitmask
- ** then set the high-order bit of the bitmask.
- */
- if( pExpr->iColumn>=0 && pMatch!=0 ){
- int n = pExpr->iColumn;
- testcase( n==BMS-1 );
- if( n>=BMS ){
- n = BMS-1;
- }
- assert( pMatch->iCursor==pExpr->iTable );
- pMatch->colUsed |= ((Bitmask)1)<<n;
- }
-
- /* Clean up and return
- */
- sqlite3ExprDelete(db, pExpr->pLeft);
- pExpr->pLeft = 0;
- sqlite3ExprDelete(db, pExpr->pRight);
- pExpr->pRight = 0;
- pExpr->op = eNewExprOp;
- ExprSetProperty(pExpr, EP_Leaf);
-lookupname_end:
- if( cnt==1 ){
- assert( pNC!=0 );
- if( !ExprHasProperty(pExpr, EP_Alias) ){
- sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
- }
- /* Increment the nRef value on all name contexts from TopNC up to
- ** the point where the name matched. */
- for(;;){
- assert( pTopNC!=0 );
- pTopNC->nRef++;
- if( pTopNC==pNC ) break;
- pTopNC = pTopNC->pNext;
- }
- return WRC_Prune;
- } else {
- return WRC_Abort;
- }
-}
-
-/*
-** Allocate and return a pointer to an expression to load the column iCol
-** from datasource iSrc in SrcList pSrc.
-*/
-Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
- Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
- if( p ){
- struct SrcList_item *pItem = &pSrc->a[iSrc];
- p->pTab = pItem->pTab;
- p->iTable = pItem->iCursor;
- if( p->pTab->iPKey==iCol ){
- p->iColumn = -1;
- }else{
- p->iColumn = (ynVar)iCol;
- testcase( iCol==BMS );
- testcase( iCol==BMS-1 );
- pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
- }
- }
- return p;
-}
-
-/*
-** Report an error that an expression is not valid for some set of
-** pNC->ncFlags values determined by validMask.
-*/
-static void notValid(
- Parse *pParse, /* Leave error message here */
- NameContext *pNC, /* The name context */
- const char *zMsg, /* Type of error */
- int validMask /* Set of contexts for which prohibited */
-){
- assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr))==0 );
- if( (pNC->ncFlags & validMask)!=0 ){
- const char *zIn = "partial index WHERE clauses";
- if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
-#ifndef SQLITE_OMIT_CHECK
- else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
-#endif
- sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
- }
-}
-
-/*
-** Expression p should encode a floating point value between 1.0 and 0.0.
-** Return 1024 times this value. Or return -1 if p is not a floating point
-** value between 1.0 and 0.0.
-*/
-static int exprProbability(Expr *p){
- double r = -1.0;
- if( p->op!=TK_FLOAT ) return -1;
- sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
- assert( r>=0.0 );
- if( r>1.0 ) return -1;
- return (int)(r*134217728.0);
-}
-
-/*
-** This routine is callback for sqlite3WalkExpr().
-**
-** Resolve symbolic names into TK_COLUMN operators for the current
-** node in the expression tree. Return 0 to continue the search down
-** the tree or 2 to abort the tree walk.
-**
-** This routine also does error checking and name resolution for
-** function names. The operator for aggregate functions is changed
-** to TK_AGG_FUNCTION.
-*/
-static int resolveExprStep(Walker *pWalker, Expr *pExpr){
- NameContext *pNC;
- Parse *pParse;
-
- pNC = pWalker->u.pNC;
- assert( pNC!=0 );
- pParse = pNC->pParse;
- assert( pParse==pWalker->pParse );
-
-#ifndef NDEBUG
- if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
- SrcList *pSrcList = pNC->pSrcList;
- int i;
- for(i=0; i<pNC->pSrcList->nSrc; i++){
- assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
- }
- }
-#endif
- switch( pExpr->op ){
-
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
- /* The special operator TK_ROW means use the rowid for the first
- ** column in the FROM clause. This is used by the LIMIT and ORDER BY
- ** clause processing on UPDATE and DELETE statements.
- */
- case TK_ROW: {
- SrcList *pSrcList = pNC->pSrcList;
- struct SrcList_item *pItem;
- assert( pSrcList && pSrcList->nSrc==1 );
- pItem = pSrcList->a;
- assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
- pExpr->op = TK_COLUMN;
- pExpr->pTab = pItem->pTab;
- pExpr->iTable = pItem->iCursor;
- pExpr->iColumn = -1;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- break;
- }
-#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
- && !defined(SQLITE_OMIT_SUBQUERY) */
-
- /* A column name: ID
- ** Or table name and column name: ID.ID
- ** Or a database, table and column: ID.ID.ID
- **
- ** The TK_ID and TK_OUT cases are combined so that there will only
- ** be one call to lookupName(). Then the compiler will in-line
- ** lookupName() for a size reduction and performance increase.
- */
- case TK_ID:
- case TK_DOT: {
- const char *zColumn;
- const char *zTable;
- const char *zDb;
- Expr *pRight;
-
- if( pExpr->op==TK_ID ){
- zDb = 0;
- zTable = 0;
- zColumn = pExpr->u.zToken;
- }else{
- notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
- pRight = pExpr->pRight;
- if( pRight->op==TK_ID ){
- zDb = 0;
- zTable = pExpr->pLeft->u.zToken;
- zColumn = pRight->u.zToken;
- }else{
- assert( pRight->op==TK_DOT );
- zDb = pExpr->pLeft->u.zToken;
- zTable = pRight->pLeft->u.zToken;
- zColumn = pRight->pRight->u.zToken;
- }
- }
- return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
- }
-
- /* Resolve function names
- */
- case TK_FUNCTION: {
- ExprList *pList = pExpr->x.pList; /* The argument list */
- int n = pList ? pList->nExpr : 0; /* Number of arguments */
- int no_such_func = 0; /* True if no such function exists */
- int wrong_num_args = 0; /* True if wrong number of arguments */
- int is_agg = 0; /* True if is an aggregate function */
- int nId; /* Number of characters in function name */
- const char *zId; /* The function name. */
- FuncDef *pDef; /* Information about the function */
- u8 enc = ENC(pParse->db); /* The database encoding */
-
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- zId = pExpr->u.zToken;
- nId = sqlite3Strlen30(zId);
- pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
- if( pDef==0 ){
- pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
- if( pDef==0 ){
- no_such_func = 1;
- }else{
- wrong_num_args = 1;
- }
- }else{
- is_agg = pDef->xFinalize!=0;
- if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
- ExprSetProperty(pExpr, EP_Unlikely|EP_Skip);
- if( n==2 ){
- pExpr->iTable = exprProbability(pList->a[1].pExpr);
- if( pExpr->iTable<0 ){
- sqlite3ErrorMsg(pParse,
- "second argument to likelihood() must be a "
- "constant between 0.0 and 1.0");
- pNC->nErr++;
- }
- }else{
- /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
- ** equivalent to likelihood(X, 0.0625).
- ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is
- ** short-hand for likelihood(X,0.0625).
- ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand
- ** for likelihood(X,0.9375).
- ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent
- ** to likelihood(X,0.9375). */
- /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
- pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120;
- }
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0);
- if( auth!=SQLITE_OK ){
- if( auth==SQLITE_DENY ){
- sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
- pDef->zName);
- pNC->nErr++;
- }
- pExpr->op = TK_NULL;
- return WRC_Prune;
- }
- }
-#endif
- if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
- /* For the purposes of the EP_ConstFunc flag, date and time
- ** functions and other functions that change slowly are considered
- ** constant because they are constant for the duration of one query */
- ExprSetProperty(pExpr,EP_ConstFunc);
- }
- if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
- /* Date/time functions that use 'now', and other functions like
- ** sqlite_version() that might change over time cannot be used
- ** in an index. */
- notValid(pParse, pNC, "non-deterministic functions",
- NC_IdxExpr|NC_PartIdx);
- }
- }
- if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
- pNC->nErr++;
- is_agg = 0;
- }else if( no_such_func && pParse->db->init.busy==0
-#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- && pParse->explain==0
-#endif
- ){
- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- pNC->nErr++;
- }else if( wrong_num_args ){
- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- pNC->nErr++;
- }
- if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
- sqlite3WalkExprList(pWalker, pList);
- if( is_agg ){
- NameContext *pNC2 = pNC;
- pExpr->op = TK_AGG_FUNCTION;
- pExpr->op2 = 0;
- while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
- pExpr->op2++;
- pNC2 = pNC2->pNext;
- }
- assert( pDef!=0 );
- if( pNC2 ){
- assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
- testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
- pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
-
- }
- pNC->ncFlags |= NC_AllowAgg;
- }
- /* FIX ME: Compute pExpr->affinity based on the expected return
- ** type of the function
- */
- return WRC_Prune;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_SELECT:
- case TK_EXISTS: testcase( pExpr->op==TK_EXISTS );
-#endif
- case TK_IN: {
- testcase( pExpr->op==TK_IN );
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- int nRef = pNC->nRef;
- notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
- sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
- assert( pNC->nRef>=nRef );
- if( nRef!=pNC->nRef ){
- ExprSetProperty(pExpr, EP_VarSelect);
- pNC->ncFlags |= NC_VarSelect;
- }
- }
- break;
- }
- case TK_VARIABLE: {
- notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
- break;
- }
- case TK_IS:
- case TK_ISNOT: {
- Expr *pRight;
- assert( !ExprHasProperty(pExpr, EP_Reduced) );
- /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
- ** and "x IS NOT FALSE". */
- if( (pRight = pExpr->pRight)->op==TK_ID ){
- int rc = resolveExprStep(pWalker, pRight);
- if( rc==WRC_Abort ) return WRC_Abort;
- if( pRight->op==TK_TRUEFALSE ){
- pExpr->op2 = pExpr->op;
- pExpr->op = TK_TRUTH;
- return WRC_Continue;
- }
- }
- /* Fall thru */
- }
- case TK_BETWEEN:
- case TK_EQ:
- case TK_NE:
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE: {
- int nLeft, nRight;
- if( pParse->db->mallocFailed ) break;
- assert( pExpr->pLeft!=0 );
- nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
- if( pExpr->op==TK_BETWEEN ){
- nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr);
- if( nRight==nLeft ){
- nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
- }
- }else{
- assert( pExpr->pRight!=0 );
- nRight = sqlite3ExprVectorSize(pExpr->pRight);
- }
- if( nLeft!=nRight ){
- testcase( pExpr->op==TK_EQ );
- testcase( pExpr->op==TK_NE );
- testcase( pExpr->op==TK_LT );
- testcase( pExpr->op==TK_LE );
- testcase( pExpr->op==TK_GT );
- testcase( pExpr->op==TK_GE );
- testcase( pExpr->op==TK_IS );
- testcase( pExpr->op==TK_ISNOT );
- testcase( pExpr->op==TK_BETWEEN );
- sqlite3ErrorMsg(pParse, "row value misused");
- }
- break;
- }
- }
- return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
-}
-
-/*
-** pEList is a list of expressions which are really the result set of the
-** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause.
-** This routine checks to see if pE is a simple identifier which corresponds
-** to the AS-name of one of the terms of the expression list. If it is,
-** this routine return an integer between 1 and N where N is the number of
-** elements in pEList, corresponding to the matching entry. If there is
-** no match, or if pE is not a simple identifier, then this routine
-** return 0.
-**
-** pEList has been resolved. pE has not.
-*/
-static int resolveAsName(
- Parse *pParse, /* Parsing context for error messages */
- ExprList *pEList, /* List of expressions to scan */
- Expr *pE /* Expression we are trying to match */
-){
- int i; /* Loop counter */
-
- UNUSED_PARAMETER(pParse);
-
- if( pE->op==TK_ID ){
- char *zCol = pE->u.zToken;
- for(i=0; i<pEList->nExpr; i++){
- char *zAs = pEList->a[i].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- return i+1;
- }
- }
- }
- return 0;
-}
-
-/*
-** pE is a pointer to an expression which is a single term in the
-** ORDER BY of a compound SELECT. The expression has not been
-** name resolved.
-**
-** At the point this routine is called, we already know that the
-** ORDER BY term is not an integer index into the result set. That
-** case is handled by the calling routine.
-**
-** Attempt to match pE against result set columns in the left-most
-** SELECT statement. Return the index i of the matching column,
-** as an indication to the caller that it should sort by the i-th column.
-** The left-most column is 1. In other words, the value returned is the
-** same integer value that would be used in the SQL statement to indicate
-** the column.
-**
-** If there is no match, return 0. Return -1 if an error occurs.
-*/
-static int resolveOrderByTermToExprList(
- Parse *pParse, /* Parsing context for error messages */
- Select *pSelect, /* The SELECT statement with the ORDER BY clause */
- Expr *pE /* The specific ORDER BY term */
-){
- int i; /* Loop counter */
- ExprList *pEList; /* The columns of the result set */
- NameContext nc; /* Name context for resolving pE */
- sqlite3 *db; /* Database connection */
- int rc; /* Return code from subprocedures */
- u8 savedSuppErr; /* Saved value of db->suppressErr */
-
- assert( sqlite3ExprIsInteger(pE, &i)==0 );
- pEList = pSelect->pEList;
-
- /* Resolve all names in the ORDER BY term expression
- */
- memset(&nc, 0, sizeof(nc));
- nc.pParse = pParse;
- nc.pSrcList = pSelect->pSrc;
- nc.uNC.pEList = pEList;
- nc.ncFlags = NC_AllowAgg|NC_UEList;
- nc.nErr = 0;
- db = pParse->db;
- savedSuppErr = db->suppressErr;
- db->suppressErr = 1;
- rc = sqlite3ResolveExprNames(&nc, pE);
- db->suppressErr = savedSuppErr;
- if( rc ) return 0;
-
- /* Try to match the ORDER BY expression against an expression
- ** in the result set. Return an 1-based index of the matching
- ** result-set entry.
- */
- for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprCompare(0, pEList->a[i].pExpr, pE, -1)<2 ){
- return i+1;
- }
- }
-
- /* If no match, return 0. */
- return 0;
-}
-
-/*
-** Generate an ORDER BY or GROUP BY term out-of-range error.
-*/
-static void resolveOutOfRangeError(
- Parse *pParse, /* The error context into which to write the error */
- const char *zType, /* "ORDER" or "GROUP" */
- int i, /* The index (1-based) of the term out of range */
- int mx /* Largest permissible value of i */
-){
- sqlite3ErrorMsg(pParse,
- "%r %s BY term out of range - should be "
- "between 1 and %d", i, zType, mx);
-}
-
-/*
-** Analyze the ORDER BY clause in a compound SELECT statement. Modify
-** each term of the ORDER BY clause is a constant integer between 1
-** and N where N is the number of columns in the compound SELECT.
-**
-** ORDER BY terms that are already an integer between 1 and N are
-** unmodified. ORDER BY terms that are integers outside the range of
-** 1 through N generate an error. ORDER BY terms that are expressions
-** are matched against result set expressions of compound SELECT
-** beginning with the left-most SELECT and working toward the right.
-** At the first match, the ORDER BY expression is transformed into
-** the integer column number.
-**
-** Return the number of errors seen.
-*/
-static int resolveCompoundOrderBy(
- Parse *pParse, /* Parsing context. Leave error messages here */
- Select *pSelect /* The SELECT statement containing the ORDER BY */
-){
- int i;
- ExprList *pOrderBy;
- ExprList *pEList;
- sqlite3 *db;
- int moreToDo = 1;
-
- pOrderBy = pSelect->pOrderBy;
- if( pOrderBy==0 ) return 0;
- db = pParse->db;
- if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
- return 1;
- }
- for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].done = 0;
- }
- pSelect->pNext = 0;
- while( pSelect->pPrior ){
- pSelect->pPrior->pNext = pSelect;
- pSelect = pSelect->pPrior;
- }
- while( pSelect && moreToDo ){
- struct ExprList_item *pItem;
- moreToDo = 0;
- pEList = pSelect->pEList;
- assert( pEList!=0 );
- for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
- int iCol = -1;
- Expr *pE, *pDup;
- if( pItem->done ) continue;
- pE = sqlite3ExprSkipCollate(pItem->pExpr);
- if( sqlite3ExprIsInteger(pE, &iCol) ){
- if( iCol<=0 || iCol>pEList->nExpr ){
- resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
- return 1;
- }
- }else{
- iCol = resolveAsName(pParse, pEList, pE);
- if( iCol==0 ){
- pDup = sqlite3ExprDup(db, pE, 0);
- if( !db->mallocFailed ){
- assert(pDup);
- iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
- }
- sqlite3ExprDelete(db, pDup);
- }
- }
- if( iCol>0 ){
- /* Convert the ORDER BY term into an integer column number iCol,
- ** taking care to preserve the COLLATE clause if it exists */
- Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
- if( pNew==0 ) return 1;
- pNew->flags |= EP_IntValue;
- pNew->u.iValue = iCol;
- if( pItem->pExpr==pE ){
- pItem->pExpr = pNew;
- }else{
- Expr *pParent = pItem->pExpr;
- assert( pParent->op==TK_COLLATE );
- while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
- assert( pParent->pLeft==pE );
- pParent->pLeft = pNew;
- }
- sqlite3ExprDelete(db, pE);
- pItem->u.x.iOrderByCol = (u16)iCol;
- pItem->done = 1;
- }else{
- moreToDo = 1;
- }
- }
- pSelect = pSelect->pNext;
- }
- for(i=0; i<pOrderBy->nExpr; i++){
- if( pOrderBy->a[i].done==0 ){
- sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
- "column in the result set", i+1);
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
-** the SELECT statement pSelect. If any term is reference to a
-** result set expression (as determined by the ExprList.a.u.x.iOrderByCol
-** field) then convert that term into a copy of the corresponding result set
-** column.
-**
-** If any errors are detected, add an error message to pParse and
-** return non-zero. Return zero if no errors are seen.
-*/
-int sqlite3ResolveOrderGroupBy(
- Parse *pParse, /* Parsing context. Leave error messages here */
- Select *pSelect, /* The SELECT statement containing the clause */
- ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */
- const char *zType /* "ORDER" or "GROUP" */
-){
- int i;
- sqlite3 *db = pParse->db;
- ExprList *pEList;
- struct ExprList_item *pItem;
-
- if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
- if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
- return 1;
- }
- pEList = pSelect->pEList;
- assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
- for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
- if( pItem->u.x.iOrderByCol ){
- if( pItem->u.x.iOrderByCol>pEList->nExpr ){
- resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
- return 1;
- }
- resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
- zType,0);
- }
- }
- return 0;
-}
-
-/*
-** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
-** The Name context of the SELECT statement is pNC. zType is either
-** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
-**
-** This routine resolves each term of the clause into an expression.
-** If the order-by term is an integer I between 1 and N (where N is the
-** number of columns in the result set of the SELECT) then the expression
-** in the resolution is a copy of the I-th result-set expression. If
-** the order-by term is an identifier that corresponds to the AS-name of
-** a result-set expression, then the term resolves to a copy of the
-** result-set expression. Otherwise, the expression is resolved in
-** the usual way - using sqlite3ResolveExprNames().
-**
-** This routine returns the number of errors. If errors occur, then
-** an appropriate error message might be left in pParse. (OOM errors
-** excepted.)
-*/
-static int resolveOrderGroupBy(
- NameContext *pNC, /* The name context of the SELECT statement */
- Select *pSelect, /* The SELECT statement holding pOrderBy */
- ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */
- const char *zType /* Either "ORDER" or "GROUP", as appropriate */
-){
- int i, j; /* Loop counters */
- int iCol; /* Column number */
- struct ExprList_item *pItem; /* A term of the ORDER BY clause */
- Parse *pParse; /* Parsing context */
- int nResult; /* Number of terms in the result set */
-
- if( pOrderBy==0 ) return 0;
- nResult = pSelect->pEList->nExpr;
- pParse = pNC->pParse;
- for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
- Expr *pE = pItem->pExpr;
- Expr *pE2 = sqlite3ExprSkipCollate(pE);
- if( zType[0]!='G' ){
- iCol = resolveAsName(pParse, pSelect->pEList, pE2);
- if( iCol>0 ){
- /* If an AS-name match is found, mark this ORDER BY column as being
- ** a copy of the iCol-th result-set column. The subsequent call to
- ** sqlite3ResolveOrderGroupBy() will convert the expression to a
- ** copy of the iCol-th result-set expression. */
- pItem->u.x.iOrderByCol = (u16)iCol;
- continue;
- }
- }
- if( sqlite3ExprIsInteger(pE2, &iCol) ){
- /* The ORDER BY term is an integer constant. Again, set the column
- ** number so that sqlite3ResolveOrderGroupBy() will convert the
- ** order-by term to a copy of the result-set expression */
- if( iCol<1 || iCol>0xffff ){
- resolveOutOfRangeError(pParse, zType, i+1, nResult);
- return 1;
- }
- pItem->u.x.iOrderByCol = (u16)iCol;
- continue;
- }
-
- /* Otherwise, treat the ORDER BY term as an ordinary expression */
- pItem->u.x.iOrderByCol = 0;
- if( sqlite3ResolveExprNames(pNC, pE) ){
- return 1;
- }
- for(j=0; j<pSelect->pEList->nExpr; j++){
- if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
- pItem->u.x.iOrderByCol = j+1;
- }
- }
- }
- return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
-}
-
-/*
-** Resolve names in the SELECT statement p and all of its descendants.
-*/
-static int resolveSelectStep(Walker *pWalker, Select *p){
- NameContext *pOuterNC; /* Context that contains this SELECT */
- NameContext sNC; /* Name context of this SELECT */
- int isCompound; /* True if p is a compound select */
- int nCompound; /* Number of compound terms processed so far */
- Parse *pParse; /* Parsing context */
- int i; /* Loop counter */
- ExprList *pGroupBy; /* The GROUP BY clause */
- Select *pLeftmost; /* Left-most of SELECT of a compound */
- sqlite3 *db; /* Database connection */
-
-
- assert( p!=0 );
- if( p->selFlags & SF_Resolved ){
- return WRC_Prune;
- }
- pOuterNC = pWalker->u.pNC;
- pParse = pWalker->pParse;
- db = pParse->db;
-
- /* Normally sqlite3SelectExpand() will be called first and will have
- ** already expanded this SELECT. However, if this is a subquery within
- ** an expression, sqlite3ResolveExprNames() will be called without a
- ** prior call to sqlite3SelectExpand(). When that happens, let
- ** sqlite3SelectPrep() do all of the processing for this SELECT.
- ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
- ** this routine in the correct order.
- */
- if( (p->selFlags & SF_Expanded)==0 ){
- sqlite3SelectPrep(pParse, p, pOuterNC);
- return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
- }
-
- isCompound = p->pPrior!=0;
- nCompound = 0;
- pLeftmost = p;
- while( p ){
- assert( (p->selFlags & SF_Expanded)!=0 );
- assert( (p->selFlags & SF_Resolved)==0 );
- p->selFlags |= SF_Resolved;
-
- /* Resolve the expressions in the LIMIT and OFFSET clauses. These
- ** are not allowed to refer to any names, so pass an empty NameContext.
- */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){
- return WRC_Abort;
- }
-
- /* If the SF_Converted flags is set, then this Select object was
- ** was created by the convertCompoundSelectToSubquery() function.
- ** In this case the ORDER BY clause (p->pOrderBy) should be resolved
- ** as if it were part of the sub-query, not the parent. This block
- ** moves the pOrderBy down to the sub-query. It will be moved back
- ** after the names have been resolved. */
- if( p->selFlags & SF_Converted ){
- Select *pSub = p->pSrc->a[0].pSelect;
- assert( p->pSrc->nSrc==1 && p->pOrderBy );
- assert( pSub->pPrior && pSub->pOrderBy==0 );
- pSub->pOrderBy = p->pOrderBy;
- p->pOrderBy = 0;
- }
-
- /* Recursively resolve names in all subqueries
- */
- for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
- if( pItem->pSelect ){
- NameContext *pNC; /* Used to iterate name contexts */
- int nRef = 0; /* Refcount for pOuterNC and outer contexts */
- const char *zSavedContext = pParse->zAuthContext;
-
- /* Count the total number of references to pOuterNC and all of its
- ** parent contexts. After resolving references to expressions in
- ** pItem->pSelect, check if this value has changed. If so, then
- ** SELECT statement pItem->pSelect must be correlated. Set the
- ** pItem->fg.isCorrelated flag if this is the case. */
- for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
-
- if( pItem->zName ) pParse->zAuthContext = pItem->zName;
- sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
- pParse->zAuthContext = zSavedContext;
- if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
-
- for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
- assert( pItem->fg.isCorrelated==0 && nRef<=0 );
- pItem->fg.isCorrelated = (nRef!=0);
- }
- }
-
- /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
- ** resolve the result-set expression list.
- */
- sNC.ncFlags = NC_AllowAgg;
- sNC.pSrcList = p->pSrc;
- sNC.pNext = pOuterNC;
-
- /* Resolve names in the result set. */
- if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort;
-
- /* If there are no aggregate functions in the result-set, and no GROUP BY
- ** expression, do not allow aggregates in any of the other expressions.
- */
- assert( (p->selFlags & SF_Aggregate)==0 );
- pGroupBy = p->pGroupBy;
- if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
- assert( NC_MinMaxAgg==SF_MinMaxAgg );
- p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
- }else{
- sNC.ncFlags &= ~NC_AllowAgg;
- }
-
- /* If a HAVING clause is present, then there must be a GROUP BY clause.
- */
- if( p->pHaving && !pGroupBy ){
- sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- return WRC_Abort;
- }
-
- /* Add the output column list to the name-context before parsing the
- ** other expressions in the SELECT statement. This is so that
- ** expressions in the WHERE clause (etc.) can refer to expressions by
- ** aliases in the result set.
- **
- ** Minor point: If this is the case, then the expression will be
- ** re-evaluated for each reference to it.
- */
- assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert))==0 );
- sNC.uNC.pEList = p->pEList;
- sNC.ncFlags |= NC_UEList;
- if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
- if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
-
- /* Resolve names in table-valued-function arguments */
- for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
- if( pItem->fg.isTabFunc
- && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg)
- ){
- return WRC_Abort;
- }
- }
-
- /* The ORDER BY and GROUP BY clauses may not refer to terms in
- ** outer queries
- */
- sNC.pNext = 0;
- sNC.ncFlags |= NC_AllowAgg;
-
- /* If this is a converted compound query, move the ORDER BY clause from
- ** the sub-query back to the parent query. At this point each term
- ** within the ORDER BY clause has been transformed to an integer value.
- ** These integers will be replaced by copies of the corresponding result
- ** set expressions by the call to resolveOrderGroupBy() below. */
- if( p->selFlags & SF_Converted ){
- Select *pSub = p->pSrc->a[0].pSelect;
- p->pOrderBy = pSub->pOrderBy;
- pSub->pOrderBy = 0;
- }
-
- /* Process the ORDER BY clause for singleton SELECT statements.
- ** The ORDER BY clause for compounds SELECT statements is handled
- ** below, after all of the result-sets for all of the elements of
- ** the compound have been resolved.
- **
- ** If there is an ORDER BY clause on a term of a compound-select other
- ** than the right-most term, then that is a syntax error. But the error
- ** is not detected until much later, and so we need to go ahead and
- ** resolve those symbols on the incorrect ORDER BY for consistency.
- */
- if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
- && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
- ){
- return WRC_Abort;
- }
- if( db->mallocFailed ){
- return WRC_Abort;
- }
-
- /* Resolve the GROUP BY clause. At the same time, make sure
- ** the GROUP BY clause does not contain aggregate functions.
- */
- if( pGroupBy ){
- struct ExprList_item *pItem;
-
- if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
- return WRC_Abort;
- }
- for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
- if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
- sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
- "the GROUP BY clause");
- return WRC_Abort;
- }
- }
- }
-
- /* If this is part of a compound SELECT, check that it has the right
- ** number of expressions in the select list. */
- if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
- sqlite3SelectWrongNumTermsError(pParse, p->pNext);
- return WRC_Abort;
- }
-
- /* Advance to the next term of the compound
- */
- p = p->pPrior;
- nCompound++;
- }
-
- /* Resolve the ORDER BY on a compound SELECT after all terms of
- ** the compound have been resolved.
- */
- if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
- return WRC_Abort;
- }
-
- return WRC_Prune;
-}
-
-/*
-** This routine walks an expression tree and resolves references to
-** table columns and result-set columns. At the same time, do error
-** checking on function usage and set a flag if any aggregate functions
-** are seen.
-**
-** To resolve table columns references we look for nodes (or subtrees) of the
-** form X.Y.Z or Y.Z or just Z where
-**
-** X: The name of a database. Ex: "main" or "temp" or
-** the symbolic name assigned to an ATTACH-ed database.
-**
-** Y: The name of a table in a FROM clause. Or in a trigger
-** one of the special names "old" or "new".
-**
-** Z: The name of a column in table Y.
-**
-** The node at the root of the subtree is modified as follows:
-**
-** Expr.op Changed to TK_COLUMN
-** Expr.pTab Points to the Table object for X.Y
-** Expr.iColumn The column index in X.Y. -1 for the rowid.
-** Expr.iTable The VDBE cursor number for X.Y
-**
-**
-** To resolve result-set references, look for expression nodes of the
-** form Z (with no X and Y prefix) where the Z matches the right-hand
-** size of an AS clause in the result-set of a SELECT. The Z expression
-** is replaced by a copy of the left-hand side of the result-set expression.
-** Table-name and function resolution occurs on the substituted expression
-** tree. For example, in:
-**
-** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
-**
-** The "x" term of the order by is replaced by "a+b" to render:
-**
-** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
-**
-** Function calls are checked to make sure that the function is
-** defined and that the correct number of arguments are specified.
-** If the function is an aggregate function, then the NC_HasAgg flag is
-** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
-** If an expression contains aggregate functions then the EP_Agg
-** property on the expression is set.
-**
-** An error message is left in pParse if anything is amiss. The number
-** if errors is returned.
-*/
-int sqlite3ResolveExprNames(
- NameContext *pNC, /* Namespace to resolve expressions in. */
- Expr *pExpr /* The expression to be analyzed. */
-){
- u16 savedHasAgg;
- Walker w;
-
- if( pExpr==0 ) return SQLITE_OK;
- savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
- w.pParse = pNC->pParse;
- w.xExprCallback = resolveExprStep;
- w.xSelectCallback = resolveSelectStep;
- w.xSelectCallback2 = 0;
- w.u.pNC = pNC;
-#if SQLITE_MAX_EXPR_DEPTH>0
- w.pParse->nHeight += pExpr->nHeight;
- if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
- return SQLITE_ERROR;
- }
-#endif
- sqlite3WalkExpr(&w, pExpr);
-#if SQLITE_MAX_EXPR_DEPTH>0
- w.pParse->nHeight -= pExpr->nHeight;
-#endif
- if( pNC->ncFlags & NC_HasAgg ){
- ExprSetProperty(pExpr, EP_Agg);
- }
- pNC->ncFlags |= savedHasAgg;
- return pNC->nErr>0 || w.pParse->nErr>0;
-}
-
-/*
-** Resolve all names for all expression in an expression list. This is
-** just like sqlite3ResolveExprNames() except that it works for an expression
-** list rather than a single expression.
-*/
-int sqlite3ResolveExprListNames(
- NameContext *pNC, /* Namespace to resolve expressions in. */
- ExprList *pList /* The expression list to be analyzed. */
-){
- int i;
- if( pList ){
- for(i=0; i<pList->nExpr; i++){
- if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort;
- }
- }
- return WRC_Continue;
-}
-
-/*
-** Resolve all names in all expressions of a SELECT and in all
-** decendents of the SELECT, including compounds off of p->pPrior,
-** subqueries in expressions, and subqueries used as FROM clause
-** terms.
-**
-** See sqlite3ResolveExprNames() for a description of the kinds of
-** transformations that occur.
-**
-** All SELECT statements should have been expanded using
-** sqlite3SelectExpand() prior to invoking this routine.
-*/
-void sqlite3ResolveSelectNames(
- Parse *pParse, /* The parser context */
- Select *p, /* The SELECT statement being coded. */
- NameContext *pOuterNC /* Name context for parent SELECT statement */
-){
- Walker w;
-
- assert( p!=0 );
- w.xExprCallback = resolveExprStep;
- w.xSelectCallback = resolveSelectStep;
- w.xSelectCallback2 = 0;
- w.pParse = pParse;
- w.u.pNC = pOuterNC;
- sqlite3WalkSelect(&w, p);
-}
-
-/*
-** Resolve names in expressions that can only reference a single table:
-**
-** * CHECK constraints
-** * WHERE clauses on partial indices
-**
-** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression
-** is set to -1 and the Expr.iColumn value is set to the column number.
-**
-** Any errors cause an error message to be set in pParse.
-*/
-void sqlite3ResolveSelfReference(
- Parse *pParse, /* Parsing context */
- Table *pTab, /* The table being referenced */
- int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */
- Expr *pExpr, /* Expression to resolve. May be NULL. */
- ExprList *pList /* Expression list to resolve. May be NULL. */
-){
- SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
- NameContext sNC; /* Name context for pParse->pNewTable */
-
- assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr );
- memset(&sNC, 0, sizeof(sNC));
- memset(&sSrc, 0, sizeof(sSrc));
- sSrc.nSrc = 1;
- sSrc.a[0].zName = pTab->zName;
- sSrc.a[0].pTab = pTab;
- sSrc.a[0].iCursor = -1;
- sNC.pParse = pParse;
- sNC.pSrcList = &sSrc;
- sNC.ncFlags = type;
- if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
- if( pList ) sqlite3ResolveExprListNames(&sNC, pList);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/rowset.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/rowset.c
deleted file mode 100644
index aa81607b9fd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/rowset.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
-** 2008 December 3
-**
-** 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 module implements an object we call a "RowSet".
-**
-** The RowSet object is a collection of rowids. Rowids
-** are inserted into the RowSet in an arbitrary order. Inserts
-** can be intermixed with tests to see if a given rowid has been
-** previously inserted into the RowSet.
-**
-** After all inserts are finished, it is possible to extract the
-** elements of the RowSet in sorted order. Once this extraction
-** process has started, no new elements may be inserted.
-**
-** Hence, the primitive operations for a RowSet are:
-**
-** CREATE
-** INSERT
-** TEST
-** SMALLEST
-** DESTROY
-**
-** The CREATE and DESTROY primitives are the constructor and destructor,
-** obviously. The INSERT primitive adds a new element to the RowSet.
-** TEST checks to see if an element is already in the RowSet. SMALLEST
-** extracts the least value from the RowSet.
-**
-** The INSERT primitive might allocate additional memory. Memory is
-** allocated in chunks so most INSERTs do no allocation. There is an
-** upper bound on the size of allocated memory. No memory is freed
-** until DESTROY.
-**
-** The TEST primitive includes a "batch" number. The TEST primitive
-** will only see elements that were inserted before the last change
-** in the batch number. In other words, if an INSERT occurs between
-** two TESTs where the TESTs have the same batch nubmer, then the
-** value added by the INSERT will not be visible to the second TEST.
-** The initial batch number is zero, so if the very first TEST contains
-** a non-zero batch number, it will see all prior INSERTs.
-**
-** No INSERTs may occurs after a SMALLEST. An assertion will fail if
-** that is attempted.
-**
-** The cost of an INSERT is roughly constant. (Sometimes new memory
-** has to be allocated on an INSERT.) The cost of a TEST with a new
-** batch number is O(NlogN) where N is the number of elements in the RowSet.
-** The cost of a TEST using the same batch number is O(logN). The cost
-** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
-** primitives are constant time. The cost of DESTROY is O(N).
-**
-** TEST and SMALLEST may not be used by the same RowSet. This used to
-** be possible, but the feature was not used, so it was removed in order
-** to simplify the code.
-*/
-#include "sqliteInt.h"
-
-
-/*
-** Target size for allocation chunks.
-*/
-#define ROWSET_ALLOCATION_SIZE 1024
-
-/*
-** The number of rowset entries per allocation chunk.
-*/
-#define ROWSET_ENTRY_PER_CHUNK \
- ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry))
-
-/*
-** Each entry in a RowSet is an instance of the following object.
-**
-** This same object is reused to store a linked list of trees of RowSetEntry
-** objects. In that alternative use, pRight points to the next entry
-** in the list, pLeft points to the tree, and v is unused. The
-** RowSet.pForest value points to the head of this forest list.
-*/
-struct RowSetEntry {
- i64 v; /* ROWID value for this entry */
- struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */
- struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */
-};
-
-/*
-** RowSetEntry objects are allocated in large chunks (instances of the
-** following structure) to reduce memory allocation overhead. The
-** chunks are kept on a linked list so that they can be deallocated
-** when the RowSet is destroyed.
-*/
-struct RowSetChunk {
- struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */
- struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
-};
-
-/*
-** A RowSet in an instance of the following structure.
-**
-** A typedef of this structure if found in sqliteInt.h.
-*/
-struct RowSet {
- struct RowSetChunk *pChunk; /* List of all chunk allocations */
- sqlite3 *db; /* The database connection */
- struct RowSetEntry *pEntry; /* List of entries using pRight */
- struct RowSetEntry *pLast; /* Last entry on the pEntry list */
- struct RowSetEntry *pFresh; /* Source of new entry objects */
- struct RowSetEntry *pForest; /* List of binary trees of entries */
- u16 nFresh; /* Number of objects on pFresh */
- u16 rsFlags; /* Various flags */
- int iBatch; /* Current insert batch */
-};
-
-/*
-** Allowed values for RowSet.rsFlags
-*/
-#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */
-#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */
-
-/*
-** Turn bulk memory into a RowSet object. N bytes of memory
-** are available at pSpace. The db pointer is used as a memory context
-** for any subsequent allocations that need to occur.
-** Return a pointer to the new RowSet object.
-**
-** It must be the case that N is sufficient to make a Rowset. If not
-** an assertion fault occurs.
-**
-** If N is larger than the minimum, use the surplus as an initial
-** allocation of entries available to be filled.
-*/
-RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
- RowSet *p;
- assert( N >= ROUND8(sizeof(*p)) );
- p = pSpace;
- p->pChunk = 0;
- p->db = db;
- p->pEntry = 0;
- p->pLast = 0;
- p->pForest = 0;
- p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
- p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
- p->rsFlags = ROWSET_SORTED;
- p->iBatch = 0;
- return p;
-}
-
-/*
-** Deallocate all chunks from a RowSet. This frees all memory that
-** the RowSet has allocated over its lifetime. This routine is
-** the destructor for the RowSet.
-*/
-void sqlite3RowSetClear(RowSet *p){
- struct RowSetChunk *pChunk, *pNextChunk;
- for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
- pNextChunk = pChunk->pNextChunk;
- sqlite3DbFree(p->db, pChunk);
- }
- p->pChunk = 0;
- p->nFresh = 0;
- p->pEntry = 0;
- p->pLast = 0;
- p->pForest = 0;
- p->rsFlags = ROWSET_SORTED;
-}
-
-/*
-** Allocate a new RowSetEntry object that is associated with the
-** given RowSet. Return a pointer to the new and completely uninitialized
-** objected.
-**
-** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
-** routine returns NULL.
-*/
-static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
- assert( p!=0 );
- if( p->nFresh==0 ){ /*OPTIMIZATION-IF-FALSE*/
- /* We could allocate a fresh RowSetEntry each time one is needed, but it
- ** is more efficient to pull a preallocated entry from the pool */
- struct RowSetChunk *pNew;
- pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew));
- if( pNew==0 ){
- return 0;
- }
- pNew->pNextChunk = p->pChunk;
- p->pChunk = pNew;
- p->pFresh = pNew->aEntry;
- p->nFresh = ROWSET_ENTRY_PER_CHUNK;
- }
- p->nFresh--;
- return p->pFresh++;
-}
-
-/*
-** Insert a new value into a RowSet.
-**
-** The mallocFailed flag of the database connection is set if a
-** memory allocation fails.
-*/
-void sqlite3RowSetInsert(RowSet *p, i64 rowid){
- struct RowSetEntry *pEntry; /* The new entry */
- struct RowSetEntry *pLast; /* The last prior entry */
-
- /* This routine is never called after sqlite3RowSetNext() */
- assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
-
- pEntry = rowSetEntryAlloc(p);
- if( pEntry==0 ) return;
- pEntry->v = rowid;
- pEntry->pRight = 0;
- pLast = p->pLast;
- if( pLast ){
- if( rowid<=pLast->v ){ /*OPTIMIZATION-IF-FALSE*/
- /* Avoid unnecessary sorts by preserving the ROWSET_SORTED flags
- ** where possible */
- p->rsFlags &= ~ROWSET_SORTED;
- }
- pLast->pRight = pEntry;
- }else{
- p->pEntry = pEntry;
- }
- p->pLast = pEntry;
-}
-
-/*
-** Merge two lists of RowSetEntry objects. Remove duplicates.
-**
-** The input lists are connected via pRight pointers and are
-** assumed to each already be in sorted order.
-*/
-static struct RowSetEntry *rowSetEntryMerge(
- struct RowSetEntry *pA, /* First sorted list to be merged */
- struct RowSetEntry *pB /* Second sorted list to be merged */
-){
- struct RowSetEntry head;
- struct RowSetEntry *pTail;
-
- pTail = &head;
- assert( pA!=0 && pB!=0 );
- for(;;){
- assert( pA->pRight==0 || pA->v<=pA->pRight->v );
- assert( pB->pRight==0 || pB->v<=pB->pRight->v );
- if( pA->v<=pB->v ){
- if( pA->v<pB->v ) pTail = pTail->pRight = pA;
- pA = pA->pRight;
- if( pA==0 ){
- pTail->pRight = pB;
- break;
- }
- }else{
- pTail = pTail->pRight = pB;
- pB = pB->pRight;
- if( pB==0 ){
- pTail->pRight = pA;
- break;
- }
- }
- }
- return head.pRight;
-}
-
-/*
-** Sort all elements on the list of RowSetEntry objects into order of
-** increasing v.
-*/
-static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
- unsigned int i;
- struct RowSetEntry *pNext, *aBucket[40];
-
- memset(aBucket, 0, sizeof(aBucket));
- while( pIn ){
- pNext = pIn->pRight;
- pIn->pRight = 0;
- for(i=0; aBucket[i]; i++){
- pIn = rowSetEntryMerge(aBucket[i], pIn);
- aBucket[i] = 0;
- }
- aBucket[i] = pIn;
- pIn = pNext;
- }
- pIn = aBucket[0];
- for(i=1; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
- if( aBucket[i]==0 ) continue;
- pIn = pIn ? rowSetEntryMerge(pIn, aBucket[i]) : aBucket[i];
- }
- return pIn;
-}
-
-
-/*
-** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
-** Convert this tree into a linked list connected by the pRight pointers
-** and return pointers to the first and last elements of the new list.
-*/
-static void rowSetTreeToList(
- struct RowSetEntry *pIn, /* Root of the input tree */
- struct RowSetEntry **ppFirst, /* Write head of the output list here */
- struct RowSetEntry **ppLast /* Write tail of the output list here */
-){
- assert( pIn!=0 );
- if( pIn->pLeft ){
- struct RowSetEntry *p;
- rowSetTreeToList(pIn->pLeft, ppFirst, &p);
- p->pRight = pIn;
- }else{
- *ppFirst = pIn;
- }
- if( pIn->pRight ){
- rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
- }else{
- *ppLast = pIn;
- }
- assert( (*ppLast)->pRight==0 );
-}
-
-
-/*
-** Convert a sorted list of elements (connected by pRight) into a binary
-** tree with depth of iDepth. A depth of 1 means the tree contains a single
-** node taken from the head of *ppList. A depth of 2 means a tree with
-** three nodes. And so forth.
-**
-** Use as many entries from the input list as required and update the
-** *ppList to point to the unused elements of the list. If the input
-** list contains too few elements, then construct an incomplete tree
-** and leave *ppList set to NULL.
-**
-** Return a pointer to the root of the constructed binary tree.
-*/
-static struct RowSetEntry *rowSetNDeepTree(
- struct RowSetEntry **ppList,
- int iDepth
-){
- struct RowSetEntry *p; /* Root of the new tree */
- struct RowSetEntry *pLeft; /* Left subtree */
- if( *ppList==0 ){ /*OPTIMIZATION-IF-TRUE*/
- /* Prevent unnecessary deep recursion when we run out of entries */
- return 0;
- }
- if( iDepth>1 ){ /*OPTIMIZATION-IF-TRUE*/
- /* This branch causes a *balanced* tree to be generated. A valid tree
- ** is still generated without this branch, but the tree is wildly
- ** unbalanced and inefficient. */
- pLeft = rowSetNDeepTree(ppList, iDepth-1);
- p = *ppList;
- if( p==0 ){ /*OPTIMIZATION-IF-FALSE*/
- /* It is safe to always return here, but the resulting tree
- ** would be unbalanced */
- return pLeft;
- }
- p->pLeft = pLeft;
- *ppList = p->pRight;
- p->pRight = rowSetNDeepTree(ppList, iDepth-1);
- }else{
- p = *ppList;
- *ppList = p->pRight;
- p->pLeft = p->pRight = 0;
- }
- return p;
-}
-
-/*
-** Convert a sorted list of elements into a binary tree. Make the tree
-** as deep as it needs to be in order to contain the entire list.
-*/
-static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
- int iDepth; /* Depth of the tree so far */
- struct RowSetEntry *p; /* Current tree root */
- struct RowSetEntry *pLeft; /* Left subtree */
-
- assert( pList!=0 );
- p = pList;
- pList = p->pRight;
- p->pLeft = p->pRight = 0;
- for(iDepth=1; pList; iDepth++){
- pLeft = p;
- p = pList;
- pList = p->pRight;
- p->pLeft = pLeft;
- p->pRight = rowSetNDeepTree(&pList, iDepth);
- }
- return p;
-}
-
-/*
-** Extract the smallest element from the RowSet.
-** Write the element into *pRowid. Return 1 on success. Return
-** 0 if the RowSet is already empty.
-**
-** After this routine has been called, the sqlite3RowSetInsert()
-** routine may not be called again.
-**
-** This routine may not be called after sqlite3RowSetTest() has
-** been used. Older versions of RowSet allowed that, but as the
-** capability was not used by the code generator, it was removed
-** for code economy.
-*/
-int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
- assert( p!=0 );
- assert( p->pForest==0 ); /* Cannot be used with sqlite3RowSetText() */
-
- /* Merge the forest into a single sorted list on first call */
- if( (p->rsFlags & ROWSET_NEXT)==0 ){ /*OPTIMIZATION-IF-FALSE*/
- if( (p->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
- p->pEntry = rowSetEntrySort(p->pEntry);
- }
- p->rsFlags |= ROWSET_SORTED|ROWSET_NEXT;
- }
-
- /* Return the next entry on the list */
- if( p->pEntry ){
- *pRowid = p->pEntry->v;
- p->pEntry = p->pEntry->pRight;
- if( p->pEntry==0 ){ /*OPTIMIZATION-IF-TRUE*/
- /* Free memory immediately, rather than waiting on sqlite3_finalize() */
- sqlite3RowSetClear(p);
- }
- return 1;
- }else{
- return 0;
- }
-}
-
-/*
-** Check to see if element iRowid was inserted into the rowset as
-** part of any insert batch prior to iBatch. Return 1 or 0.
-**
-** If this is the first test of a new batch and if there exist entries
-** on pRowSet->pEntry, then sort those entries into the forest at
-** pRowSet->pForest so that they can be tested.
-*/
-int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
- struct RowSetEntry *p, *pTree;
-
- /* This routine is never called after sqlite3RowSetNext() */
- assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
-
- /* Sort entries into the forest on the first test of a new batch.
- ** To save unnecessary work, only do this when the batch number changes.
- */
- if( iBatch!=pRowSet->iBatch ){ /*OPTIMIZATION-IF-FALSE*/
- p = pRowSet->pEntry;
- if( p ){
- struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
- if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
- /* Only sort the current set of entiries if they need it */
- p = rowSetEntrySort(p);
- }
- for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
- ppPrevTree = &pTree->pRight;
- if( pTree->pLeft==0 ){
- pTree->pLeft = rowSetListToTree(p);
- break;
- }else{
- struct RowSetEntry *pAux, *pTail;
- rowSetTreeToList(pTree->pLeft, &pAux, &pTail);
- pTree->pLeft = 0;
- p = rowSetEntryMerge(pAux, p);
- }
- }
- if( pTree==0 ){
- *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet);
- if( pTree ){
- pTree->v = 0;
- pTree->pRight = 0;
- pTree->pLeft = rowSetListToTree(p);
- }
- }
- pRowSet->pEntry = 0;
- pRowSet->pLast = 0;
- pRowSet->rsFlags |= ROWSET_SORTED;
- }
- pRowSet->iBatch = iBatch;
- }
-
- /* Test to see if the iRowid value appears anywhere in the forest.
- ** Return 1 if it does and 0 if not.
- */
- for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
- p = pTree->pLeft;
- while( p ){
- if( p->v<iRowid ){
- p = p->pRight;
- }else if( p->v>iRowid ){
- p = p->pLeft;
- }else{
- return 1;
- }
- }
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/select.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/select.c
deleted file mode 100644
index 529df0f9499..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/select.c
+++ /dev/null
@@ -1,6352 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains C code routines that are called by the parser
-** to handle SELECT statements in SQLite.
-*/
-#include "sqliteInt.h"
-
-/*
-** Trace output macros
-*/
-#if SELECTTRACE_ENABLED
-/***/ int sqlite3SelectTrace = 0;
-# define SELECTTRACE(K,P,S,X) \
- if(sqlite3SelectTrace&(K)) \
- sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->addrExplain,(S)),\
- sqlite3DebugPrintf X
-#else
-# define SELECTTRACE(K,P,S,X)
-#endif
-
-
-/*
-** An instance of the following object is used to record information about
-** how to process the DISTINCT keyword, to simplify passing that information
-** into the selectInnerLoop() routine.
-*/
-typedef struct DistinctCtx DistinctCtx;
-struct DistinctCtx {
- u8 isTnct; /* True if the DISTINCT keyword is present */
- u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
- int tabTnct; /* Ephemeral table used for DISTINCT processing */
- int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
-};
-
-/*
-** An instance of the following object is used to record information about
-** the ORDER BY (or GROUP BY) clause of query is being coded.
-**
-** The aDefer[] array is used by the sorter-references optimization. For
-** example, assuming there is no index that can be used for the ORDER BY,
-** for the query:
-**
-** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10;
-**
-** it may be more efficient to add just the "a" values to the sorter, and
-** retrieve the associated "bigblob" values directly from table t1 as the
-** 10 smallest "a" values are extracted from the sorter.
-**
-** When the sorter-reference optimization is used, there is one entry in the
-** aDefer[] array for each database table that may be read as values are
-** extracted from the sorter.
-*/
-typedef struct SortCtx SortCtx;
-struct SortCtx {
- ExprList *pOrderBy; /* The ORDER BY (or GROUP BY clause) */
- int nOBSat; /* Number of ORDER BY terms satisfied by indices */
- int iECursor; /* Cursor number for the sorter */
- int regReturn; /* Register holding block-output return address */
- int labelBkOut; /* Start label for the block-output subroutine */
- int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */
- int labelDone; /* Jump here when done, ex: LIMIT reached */
- u8 sortFlags; /* Zero or more SORTFLAG_* bits */
- u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- u8 nDefer; /* Number of valid entries in aDefer[] */
- struct DeferredCsr {
- Table *pTab; /* Table definition */
- int iCsr; /* Cursor number for table */
- int nKey; /* Number of PK columns for table pTab (>=1) */
- } aDefer[4];
-#endif
- struct RowLoadInfo *pDeferredRowLoad; /* Deferred row loading info or NULL */
-};
-#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
-
-/*
-** Delete all the content of a Select structure. Deallocate the structure
-** itself only if bFree is true.
-*/
-static void clearSelect(sqlite3 *db, Select *p, int bFree){
- while( p ){
- Select *pPrior = p->pPrior;
- sqlite3ExprListDelete(db, p->pEList);
- sqlite3SrcListDelete(db, p->pSrc);
- sqlite3ExprDelete(db, p->pWhere);
- sqlite3ExprListDelete(db, p->pGroupBy);
- sqlite3ExprDelete(db, p->pHaving);
- sqlite3ExprListDelete(db, p->pOrderBy);
- sqlite3ExprDelete(db, p->pLimit);
- if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
- if( bFree ) sqlite3DbFreeNN(db, p);
- p = pPrior;
- bFree = 1;
- }
-}
-
-/*
-** Initialize a SelectDest structure.
-*/
-void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
- pDest->eDest = (u8)eDest;
- pDest->iSDParm = iParm;
- pDest->zAffSdst = 0;
- pDest->iSdst = 0;
- pDest->nSdst = 0;
-}
-
-
-/*
-** Allocate a new Select structure and return a pointer to that
-** structure.
-*/
-Select *sqlite3SelectNew(
- Parse *pParse, /* Parsing context */
- ExprList *pEList, /* which columns to include in the result */
- SrcList *pSrc, /* the FROM clause -- which tables to scan */
- Expr *pWhere, /* the WHERE clause */
- ExprList *pGroupBy, /* the GROUP BY clause */
- Expr *pHaving, /* the HAVING clause */
- ExprList *pOrderBy, /* the ORDER BY clause */
- u32 selFlags, /* Flag parameters, such as SF_Distinct */
- Expr *pLimit /* LIMIT value. NULL means not used */
-){
- Select *pNew;
- Select standin;
- pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
- if( pNew==0 ){
- assert( pParse->db->mallocFailed );
- pNew = &standin;
- }
- if( pEList==0 ){
- pEList = sqlite3ExprListAppend(pParse, 0,
- sqlite3Expr(pParse->db,TK_ASTERISK,0));
- }
- pNew->pEList = pEList;
- pNew->op = TK_SELECT;
- pNew->selFlags = selFlags;
- pNew->iLimit = 0;
- pNew->iOffset = 0;
-#if SELECTTRACE_ENABLED
- pNew->zSelName[0] = 0;
-#endif
- pNew->addrOpenEphm[0] = -1;
- pNew->addrOpenEphm[1] = -1;
- pNew->nSelectRow = 0;
- if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
- pNew->pSrc = pSrc;
- pNew->pWhere = pWhere;
- pNew->pGroupBy = pGroupBy;
- pNew->pHaving = pHaving;
- pNew->pOrderBy = pOrderBy;
- pNew->pPrior = 0;
- pNew->pNext = 0;
- pNew->pLimit = pLimit;
- pNew->pWith = 0;
- if( pParse->db->mallocFailed ) {
- clearSelect(pParse->db, pNew, pNew!=&standin);
- pNew = 0;
- }else{
- assert( pNew->pSrc!=0 || pParse->nErr>0 );
- }
- assert( pNew!=&standin );
- return pNew;
-}
-
-#if SELECTTRACE_ENABLED
-/*
-** Set the name of a Select object
-*/
-void sqlite3SelectSetName(Select *p, const char *zName){
- if( p && zName ){
- sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName);
- }
-}
-#endif
-
-
-/*
-** Delete the given Select structure and all of its substructures.
-*/
-void sqlite3SelectDelete(sqlite3 *db, Select *p){
- if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
-}
-
-/*
-** Return a pointer to the right-most SELECT statement in a compound.
-*/
-static Select *findRightmost(Select *p){
- while( p->pNext ) p = p->pNext;
- return p;
-}
-
-/*
-** Given 1 to 3 identifiers preceding the JOIN keyword, determine the
-** type of join. Return an integer constant that expresses that type
-** in terms of the following bit values:
-**
-** JT_INNER
-** JT_CROSS
-** JT_OUTER
-** JT_NATURAL
-** JT_LEFT
-** JT_RIGHT
-**
-** A full outer join is the combination of JT_LEFT and JT_RIGHT.
-**
-** If an illegal or unsupported join type is seen, then still return
-** a join type, but put an error in the pParse structure.
-*/
-int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
- int jointype = 0;
- Token *apAll[3];
- Token *p;
- /* 0123456789 123456789 123456789 123 */
- static const char zKeyText[] = "naturaleftouterightfullinnercross";
- static const struct {
- u8 i; /* Beginning of keyword text in zKeyText[] */
- u8 nChar; /* Length of the keyword in characters */
- u8 code; /* Join type mask */
- } aKeyword[] = {
- /* natural */ { 0, 7, JT_NATURAL },
- /* left */ { 6, 4, JT_LEFT|JT_OUTER },
- /* outer */ { 10, 5, JT_OUTER },
- /* right */ { 14, 5, JT_RIGHT|JT_OUTER },
- /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },
- /* inner */ { 23, 5, JT_INNER },
- /* cross */ { 28, 5, JT_INNER|JT_CROSS },
- };
- int i, j;
- apAll[0] = pA;
- apAll[1] = pB;
- apAll[2] = pC;
- for(i=0; i<3 && apAll[i]; i++){
- p = apAll[i];
- for(j=0; j<ArraySize(aKeyword); j++){
- if( p->n==aKeyword[j].nChar
- && sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){
- jointype |= aKeyword[j].code;
- break;
- }
- }
- testcase( j==0 || j==1 || j==2 || j==3 || j==4 || j==5 || j==6 );
- if( j>=ArraySize(aKeyword) ){
- jointype |= JT_ERROR;
- break;
- }
- }
- if(
- (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
- (jointype & JT_ERROR)!=0
- ){
- const char *zSp = " ";
- assert( pB!=0 );
- if( pC==0 ){ zSp++; }
- sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
- "%T %T%s%T", pA, pB, zSp, pC);
- jointype = JT_INNER;
- }else if( (jointype & JT_OUTER)!=0
- && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){
- sqlite3ErrorMsg(pParse,
- "RIGHT and FULL OUTER JOINs are not currently supported");
- jointype = JT_INNER;
- }
- return jointype;
-}
-
-/*
-** Return the index of a column in a table. Return -1 if the column
-** is not contained in the table.
-*/
-static int columnIndex(Table *pTab, const char *zCol){
- int i;
- for(i=0; i<pTab->nCol; i++){
- if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i;
- }
- return -1;
-}
-
-/*
-** Search the first N tables in pSrc, from left to right, looking for a
-** table that has a column named zCol.
-**
-** When found, set *piTab and *piCol to the table index and column index
-** of the matching column and return TRUE.
-**
-** If not found, return FALSE.
-*/
-static int tableAndColumnIndex(
- SrcList *pSrc, /* Array of tables to search */
- int N, /* Number of tables in pSrc->a[] to search */
- const char *zCol, /* Name of the column we are looking for */
- int *piTab, /* Write index of pSrc->a[] here */
- int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
-){
- int i; /* For looping over tables in pSrc */
- int iCol; /* Index of column matching zCol */
-
- assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
- for(i=0; i<N; i++){
- iCol = columnIndex(pSrc->a[i].pTab, zCol);
- if( iCol>=0 ){
- if( piTab ){
- *piTab = i;
- *piCol = iCol;
- }
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** This function is used to add terms implied by JOIN syntax to the
-** WHERE clause expression of a SELECT statement. The new term, which
-** is ANDed with the existing WHERE clause, is of the form:
-**
-** (tab1.col1 = tab2.col2)
-**
-** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
-** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
-** column iColRight of tab2.
-*/
-static void addWhereTerm(
- Parse *pParse, /* Parsing context */
- SrcList *pSrc, /* List of tables in FROM clause */
- int iLeft, /* Index of first table to join in pSrc */
- int iColLeft, /* Index of column in first table */
- int iRight, /* Index of second table in pSrc */
- int iColRight, /* Index of column in second table */
- int isOuterJoin, /* True if this is an OUTER join */
- Expr **ppWhere /* IN/OUT: The WHERE clause to add to */
-){
- sqlite3 *db = pParse->db;
- Expr *pE1;
- Expr *pE2;
- Expr *pEq;
-
- assert( iLeft<iRight );
- assert( pSrc->nSrc>iRight );
- assert( pSrc->a[iLeft].pTab );
- assert( pSrc->a[iRight].pTab );
-
- pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
- pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
-
- pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
- if( pEq && isOuterJoin ){
- ExprSetProperty(pEq, EP_FromJoin);
- assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
- ExprSetVVAProperty(pEq, EP_NoReduce);
- pEq->iRightJoinTable = (i16)pE2->iTable;
- }
- *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
-}
-
-/*
-** Set the EP_FromJoin property on all terms of the given expression.
-** And set the Expr.iRightJoinTable to iTable for every term in the
-** expression.
-**
-** The EP_FromJoin property is used on terms of an expression to tell
-** the LEFT OUTER JOIN processing logic that this term is part of the
-** join restriction specified in the ON or USING clause and not a part
-** of the more general WHERE clause. These terms are moved over to the
-** WHERE clause during join processing but we need to remember that they
-** originated in the ON or USING clause.
-**
-** The Expr.iRightJoinTable tells the WHERE clause processing that the
-** expression depends on table iRightJoinTable even if that table is not
-** explicitly mentioned in the expression. That information is needed
-** for cases like this:
-**
-** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
-**
-** The where clause needs to defer the handling of the t1.x=5
-** term until after the t2 loop of the join. In that way, a
-** NULL t2 row will be inserted whenever t1.x!=5. If we do not
-** defer the handling of t1.x=5, it will be processed immediately
-** after the t1 loop and rows with t1.x!=5 will never appear in
-** the output, which is incorrect.
-*/
-static void setJoinExpr(Expr *p, int iTable){
- while( p ){
- ExprSetProperty(p, EP_FromJoin);
- assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
- ExprSetVVAProperty(p, EP_NoReduce);
- p->iRightJoinTable = (i16)iTable;
- if( p->op==TK_FUNCTION && p->x.pList ){
- int i;
- for(i=0; i<p->x.pList->nExpr; i++){
- setJoinExpr(p->x.pList->a[i].pExpr, iTable);
- }
- }
- setJoinExpr(p->pLeft, iTable);
- p = p->pRight;
- }
-}
-
-/* Undo the work of setJoinExpr(). In the expression tree p, convert every
-** term that is marked with EP_FromJoin and iRightJoinTable==iTable into
-** an ordinary term that omits the EP_FromJoin mark.
-**
-** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
-*/
-static void unsetJoinExpr(Expr *p, int iTable){
- while( p ){
- if( ExprHasProperty(p, EP_FromJoin)
- && (iTable<0 || p->iRightJoinTable==iTable) ){
- ExprClearProperty(p, EP_FromJoin);
- }
- if( p->op==TK_FUNCTION && p->x.pList ){
- int i;
- for(i=0; i<p->x.pList->nExpr; i++){
- unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
- }
- }
- unsetJoinExpr(p->pLeft, iTable);
- p = p->pRight;
- }
-}
-
-/*
-** This routine processes the join information for a SELECT statement.
-** ON and USING clauses are converted into extra terms of the WHERE clause.
-** NATURAL joins also create extra WHERE clause terms.
-**
-** The terms of a FROM clause are contained in the Select.pSrc structure.
-** The left most table is the first entry in Select.pSrc. The right-most
-** table is the last entry. The join operator is held in the entry to
-** the left. Thus entry 0 contains the join operator for the join between
-** entries 0 and 1. Any ON or USING clauses associated with the join are
-** also attached to the left entry.
-**
-** This routine returns the number of errors encountered.
-*/
-static int sqliteProcessJoin(Parse *pParse, Select *p){
- SrcList *pSrc; /* All tables in the FROM clause */
- int i, j; /* Loop counters */
- struct SrcList_item *pLeft; /* Left table being joined */
- struct SrcList_item *pRight; /* Right table being joined */
-
- pSrc = p->pSrc;
- pLeft = &pSrc->a[0];
- pRight = &pLeft[1];
- for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
- Table *pRightTab = pRight->pTab;
- int isOuter;
-
- if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
- isOuter = (pRight->fg.jointype & JT_OUTER)!=0;
-
- /* When the NATURAL keyword is present, add WHERE clause terms for
- ** every column that the two tables have in common.
- */
- if( pRight->fg.jointype & JT_NATURAL ){
- if( pRight->pOn || pRight->pUsing ){
- sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
- "an ON or USING clause", 0);
- return 1;
- }
- for(j=0; j<pRightTab->nCol; j++){
- char *zName; /* Name of column in the right table */
- int iLeft; /* Matching left table */
- int iLeftCol; /* Matching column in the left table */
-
- zName = pRightTab->aCol[j].zName;
- if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
- addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
- isOuter, &p->pWhere);
- }
- }
- }
-
- /* Disallow both ON and USING clauses in the same join
- */
- if( pRight->pOn && pRight->pUsing ){
- sqlite3ErrorMsg(pParse, "cannot have both ON and USING "
- "clauses in the same join");
- return 1;
- }
-
- /* Add the ON clause to the end of the WHERE clause, connected by
- ** an AND operator.
- */
- if( pRight->pOn ){
- if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
- p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn);
- pRight->pOn = 0;
- }
-
- /* Create extra terms on the WHERE clause for each column named
- ** in the USING clause. Example: If the two tables to be joined are
- ** A and B and the USING clause names X, Y, and Z, then add this
- ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
- ** Report an error if any column mentioned in the USING clause is
- ** not contained in both tables to be joined.
- */
- if( pRight->pUsing ){
- IdList *pList = pRight->pUsing;
- for(j=0; j<pList->nId; j++){
- char *zName; /* Name of the term in the USING clause */
- int iLeft; /* Table on the left with matching column name */
- int iLeftCol; /* Column number of matching column on the left */
- int iRightCol; /* Column number of matching column on the right */
-
- zName = pList->a[j].zName;
- iRightCol = columnIndex(pRightTab, zName);
- if( iRightCol<0
- || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
- ){
- sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
- "not present in both tables", zName);
- return 1;
- }
- addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
- isOuter, &p->pWhere);
- }
- }
- }
- return 0;
-}
-
-/* Forward reference */
-static KeyInfo *keyInfoFromExprList(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* Form the KeyInfo object from this ExprList */
- int iStart, /* Begin with this column of pList */
- int nExtra /* Add this many extra columns to the end */
-);
-
-/*
-** An instance of this object holds information (beyond pParse and pSelect)
-** needed to load the next result row that is to be added to the sorter.
-*/
-typedef struct RowLoadInfo RowLoadInfo;
-struct RowLoadInfo {
- int regResult; /* Store results in array of registers here */
- u8 ecelFlags; /* Flag argument to ExprCodeExprList() */
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- ExprList *pExtra; /* Extra columns needed by sorter refs */
- int regExtraResult; /* Where to load the extra columns */
-#endif
-};
-
-/*
-** This routine does the work of loading query data into an array of
-** registers so that it can be added to the sorter.
-*/
-static void innerLoopLoadRow(
- Parse *pParse, /* Statement under construction */
- Select *pSelect, /* The query being coded */
- RowLoadInfo *pInfo /* Info needed to complete the row load */
-){
- sqlite3ExprCodeExprList(pParse, pSelect->pEList, pInfo->regResult,
- 0, pInfo->ecelFlags);
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( pInfo->pExtra ){
- sqlite3ExprCodeExprList(pParse, pInfo->pExtra, pInfo->regExtraResult, 0, 0);
- sqlite3ExprListDelete(pParse->db, pInfo->pExtra);
- }
-#endif
-}
-
-/*
-** Code the OP_MakeRecord instruction that generates the entry to be
-** added into the sorter.
-**
-** Return the register in which the result is stored.
-*/
-static int makeSorterRecord(
- Parse *pParse,
- SortCtx *pSort,
- Select *pSelect,
- int regBase,
- int nBase
-){
- int nOBSat = pSort->nOBSat;
- Vdbe *v = pParse->pVdbe;
- int regOut = ++pParse->nMem;
- if( pSort->pDeferredRowLoad ){
- innerLoopLoadRow(pParse, pSelect, pSort->pDeferredRowLoad);
- }
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regOut);
- return regOut;
-}
-
-/*
-** Generate code that will push the record in registers regData
-** through regData+nData-1 onto the sorter.
-*/
-static void pushOntoSorter(
- Parse *pParse, /* Parser context */
- SortCtx *pSort, /* Information about the ORDER BY clause */
- Select *pSelect, /* The whole SELECT statement */
- int regData, /* First register holding data to be sorted */
- int regOrigData, /* First register holding data before packing */
- int nData, /* Number of elements in the regData data array */
- int nPrefixReg /* No. of reg prior to regData available for use */
-){
- Vdbe *v = pParse->pVdbe; /* Stmt under construction */
- int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0);
- int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */
- int nBase = nExpr + bSeq + nData; /* Fields in sorter record */
- int regBase; /* Regs for sorter record */
- int regRecord = 0; /* Assembled sorter record */
- int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */
- int op; /* Opcode to add sorter record to sorter */
- int iLimit; /* LIMIT counter */
- int iSkip = 0; /* End of the sorter insert loop */
-
- assert( bSeq==0 || bSeq==1 );
-
- /* Three cases:
- ** (1) The data to be sorted has already been packed into a Record
- ** by a prior OP_MakeRecord. In this case nData==1 and regData
- ** will be completely unrelated to regOrigData.
- ** (2) All output columns are included in the sort record. In that
- ** case regData==regOrigData.
- ** (3) Some output columns are omitted from the sort record due to
- ** the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the
- ** SQLITE_ECEL_OMITREF optimization, or due to the
- ** SortCtx.pDeferredRowLoad optimiation. In any of these cases
- ** regOrigData is 0 to prevent this routine from trying to copy
- ** values that might not yet exist.
- */
- assert( nData==1 || regData==regOrigData || regOrigData==0 );
-
- if( nPrefixReg ){
- assert( nPrefixReg==nExpr+bSeq );
- regBase = regData - nPrefixReg;
- }else{
- regBase = pParse->nMem + 1;
- pParse->nMem += nBase;
- }
- assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
- iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
- pSort->labelDone = sqlite3VdbeMakeLabel(v);
- sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
- SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
- if( bSeq ){
- sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
- }
- if( nPrefixReg==0 && nData>0 ){
- sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
- }
- if( nOBSat>0 ){
- int regPrevKey; /* The first nOBSat columns of the previous row */
- int addrFirst; /* Address of the OP_IfNot opcode */
- int addrJmp; /* Address of the OP_Jump opcode */
- VdbeOp *pOp; /* Opcode that opens the sorter */
- int nKey; /* Number of sorting key columns, including OP_Sequence */
- KeyInfo *pKI; /* Original KeyInfo on the sorter table */
-
- regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase);
- regPrevKey = pParse->nMem+1;
- pParse->nMem += pSort->nOBSat;
- nKey = nExpr - pSort->nOBSat + bSeq;
- if( bSeq ){
- addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr);
- }else{
- addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor);
- }
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
- pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
- if( pParse->db->mallocFailed ) return;
- pOp->p2 = nKey + nData;
- pKI = pOp->p4.pKeyInfo;
- memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */
- sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
- testcase( pKI->nAllField > pKI->nKeyField+2 );
- pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat,
- pKI->nAllField-pKI->nKeyField-1);
- addrJmp = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
- pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
- pSort->regReturn = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
- sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
- if( iLimit ){
- sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone);
- VdbeCoverage(v);
- }
- sqlite3VdbeJumpHere(v, addrFirst);
- sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat);
- sqlite3VdbeJumpHere(v, addrJmp);
- }
- if( iLimit ){
- /* At this point the values for the new sorter entry are stored
- ** in an array of registers. They need to be composed into a record
- ** and inserted into the sorter if either (a) there are currently
- ** less than LIMIT+OFFSET items or (b) the new record is smaller than
- ** the largest record currently in the sorter. If (b) is true and there
- ** are already LIMIT+OFFSET items in the sorter, delete the largest
- ** entry before inserting the new one. This way there are never more
- ** than LIMIT+OFFSET items in the sorter.
- **
- ** If the new record does not need to be inserted into the sorter,
- ** jump to the next iteration of the loop. Or, if the
- ** pSort->bOrderedInnerLoop flag is set to indicate that the inner
- ** loop delivers items in sorted order, jump to the next iteration
- ** of the outer loop.
- */
- int iCsr = pSort->iECursor;
- sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4);
- VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0);
- iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE,
- iCsr, 0, regBase+nOBSat, nExpr-nOBSat);
- VdbeCoverage(v);
- sqlite3VdbeAddOp1(v, OP_Delete, iCsr);
- }
- if( regRecord==0 ){
- regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase);
- }
- if( pSort->sortFlags & SORTFLAG_UseSorter ){
- op = OP_SorterInsert;
- }else{
- op = OP_IdxInsert;
- }
- sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
- regBase+nOBSat, nBase-nOBSat);
- if( iSkip ){
- assert( pSort->bOrderedInnerLoop==0 || pSort->bOrderedInnerLoop==1 );
- sqlite3VdbeChangeP2(v, iSkip,
- sqlite3VdbeCurrentAddr(v) + pSort->bOrderedInnerLoop);
- }
-}
-
-/*
-** Add code to implement the OFFSET
-*/
-static void codeOffset(
- Vdbe *v, /* Generate code into this VM */
- int iOffset, /* Register holding the offset counter */
- int iContinue /* Jump here to skip the current record */
-){
- if( iOffset>0 ){
- sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
- VdbeComment((v, "OFFSET"));
- }
-}
-
-/*
-** Add code that will check to make sure the N registers starting at iMem
-** form a distinct entry. iTab is a sorting index that holds previously
-** seen combinations of the N values. A new entry is made in iTab
-** if the current N values are new.
-**
-** A jump to addrRepeat is made and the N+1 values are popped from the
-** stack if the top N elements are not distinct.
-*/
-static void codeDistinct(
- Parse *pParse, /* Parsing and code generating context */
- int iTab, /* A sorting index used to test for distinctness */
- int addrRepeat, /* Jump to here if not distinct */
- int N, /* Number of elements */
- int iMem /* First element */
-){
- Vdbe *v;
- int r1;
-
- v = pParse->pVdbe;
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- sqlite3ReleaseTempReg(pParse, r1);
-}
-
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
-/*
-** This function is called as part of inner-loop generation for a SELECT
-** statement with an ORDER BY that is not optimized by an index. It
-** determines the expressions, if any, that the sorter-reference
-** optimization should be used for. The sorter-reference optimization
-** is used for SELECT queries like:
-**
-** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10
-**
-** If the optimization is used for expression "bigblob", then instead of
-** storing values read from that column in the sorter records, the PK of
-** the row from table t1 is stored instead. Then, as records are extracted from
-** the sorter to return to the user, the required value of bigblob is
-** retrieved directly from table t1. If the values are very large, this
-** can be more efficient than storing them directly in the sorter records.
-**
-** The ExprList_item.bSorterRef flag is set for each expression in pEList
-** for which the sorter-reference optimization should be enabled.
-** Additionally, the pSort->aDefer[] array is populated with entries
-** for all cursors required to evaluate all selected expressions. Finally.
-** output variable (*ppExtra) is set to an expression list containing
-** expressions for all extra PK values that should be stored in the
-** sorter records.
-*/
-static void selectExprDefer(
- Parse *pParse, /* Leave any error here */
- SortCtx *pSort, /* Sorter context */
- ExprList *pEList, /* Expressions destined for sorter */
- ExprList **ppExtra /* Expressions to append to sorter record */
-){
- int i;
- int nDefer = 0;
- ExprList *pExtra = 0;
- for(i=0; i<pEList->nExpr; i++){
- struct ExprList_item *pItem = &pEList->a[i];
- if( pItem->u.x.iOrderByCol==0 ){
- Expr *pExpr = pItem->pExpr;
- Table *pTab = pExpr->pTab;
- if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
- && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
- ){
- int j;
- for(j=0; j<nDefer; j++){
- if( pSort->aDefer[j].iCsr==pExpr->iTable ) break;
- }
- if( j==nDefer ){
- if( nDefer==ArraySize(pSort->aDefer) ){
- continue;
- }else{
- int nKey = 1;
- int k;
- Index *pPk = 0;
- if( !HasRowid(pTab) ){
- pPk = sqlite3PrimaryKeyIndex(pTab);
- nKey = pPk->nKeyCol;
- }
- for(k=0; k<nKey; k++){
- Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
- if( pNew ){
- pNew->iTable = pExpr->iTable;
- pNew->pTab = pExpr->pTab;
- pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
- pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
- }
- }
- pSort->aDefer[nDefer].pTab = pExpr->pTab;
- pSort->aDefer[nDefer].iCsr = pExpr->iTable;
- pSort->aDefer[nDefer].nKey = nKey;
- nDefer++;
- }
- }
- pItem->bSorterRef = 1;
- }
- }
- }
- pSort->nDefer = (u8)nDefer;
- *ppExtra = pExtra;
-}
-#endif
-
-/*
-** This routine generates the code for the inside of the inner loop
-** of a SELECT.
-**
-** If srcTab is negative, then the p->pEList expressions
-** are evaluated in order to get the data for this row. If srcTab is
-** zero or more, then data is pulled from srcTab and p->pEList is used only
-** to get the number of columns and the collation sequence for each column.
-*/
-static void selectInnerLoop(
- Parse *pParse, /* The parser context */
- Select *p, /* The complete select statement being coded */
- int srcTab, /* Pull data from this table if non-negative */
- SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */
- DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
- SelectDest *pDest, /* How to dispose of the results */
- int iContinue, /* Jump here to continue with next row */
- int iBreak /* Jump here to break out of the inner loop */
-){
- Vdbe *v = pParse->pVdbe;
- int i;
- int hasDistinct; /* True if the DISTINCT keyword is present */
- int eDest = pDest->eDest; /* How to dispose of results */
- int iParm = pDest->iSDParm; /* First argument to disposal method */
- int nResultCol; /* Number of result columns */
- int nPrefixReg = 0; /* Number of extra registers before regResult */
- RowLoadInfo sRowLoadInfo; /* Info for deferred row loading */
-
- /* Usually, regResult is the first cell in an array of memory cells
- ** containing the current result row. In this case regOrig is set to the
- ** same value. However, if the results are being sent to the sorter, the
- ** values for any expressions that are also part of the sort-key are omitted
- ** from this array. In this case regOrig is set to zero. */
- int regResult; /* Start of memory holding current results */
- int regOrig; /* Start of memory holding full result (or 0) */
-
- assert( v );
- assert( p->pEList!=0 );
- hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
- if( pSort && pSort->pOrderBy==0 ) pSort = 0;
- if( pSort==0 && !hasDistinct ){
- assert( iContinue!=0 );
- codeOffset(v, p->iOffset, iContinue);
- }
-
- /* Pull the requested columns.
- */
- nResultCol = p->pEList->nExpr;
-
- if( pDest->iSdst==0 ){
- if( pSort ){
- nPrefixReg = pSort->pOrderBy->nExpr;
- if( !(pSort->sortFlags & SORTFLAG_UseSorter) ) nPrefixReg++;
- pParse->nMem += nPrefixReg;
- }
- pDest->iSdst = pParse->nMem+1;
- pParse->nMem += nResultCol;
- }else if( pDest->iSdst+nResultCol > pParse->nMem ){
- /* This is an error condition that can result, for example, when a SELECT
- ** on the right-hand side of an INSERT contains more result columns than
- ** there are columns in the table on the left. The error will be caught
- ** and reported later. But we need to make sure enough memory is allocated
- ** to avoid other spurious errors in the meantime. */
- pParse->nMem += nResultCol;
- }
- pDest->nSdst = nResultCol;
- regOrig = regResult = pDest->iSdst;
- if( srcTab>=0 ){
- for(i=0; i<nResultCol; i++){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
- VdbeComment((v, "%s", p->pEList->a[i].zName));
- }
- }else if( eDest!=SRT_Exists ){
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- ExprList *pExtra = 0;
-#endif
- /* If the destination is an EXISTS(...) expression, the actual
- ** values returned by the SELECT are not required.
- */
- u8 ecelFlags; /* "ecel" is an abbreviation of "ExprCodeExprList" */
- ExprList *pEList;
- if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){
- ecelFlags = SQLITE_ECEL_DUP;
- }else{
- ecelFlags = 0;
- }
- if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
- /* For each expression in p->pEList that is a copy of an expression in
- ** the ORDER BY clause (pSort->pOrderBy), set the associated
- ** iOrderByCol value to one more than the index of the ORDER BY
- ** expression within the sort-key that pushOntoSorter() will generate.
- ** This allows the p->pEList field to be omitted from the sorted record,
- ** saving space and CPU cycles. */
- ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF);
-
- for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){
- int j;
- if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){
- p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
- }
- }
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- selectExprDefer(pParse, pSort, p->pEList, &pExtra);
- if( pExtra && pParse->db->mallocFailed==0 ){
- /* If there are any extra PK columns to add to the sorter records,
- ** allocate extra memory cells and adjust the OpenEphemeral
- ** instruction to account for the larger records. This is only
- ** required if there are one or more WITHOUT ROWID tables with
- ** composite primary keys in the SortCtx.aDefer[] array. */
- VdbeOp *pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
- pOp->p2 += (pExtra->nExpr - pSort->nDefer);
- pOp->p4.pKeyInfo->nAllField += (pExtra->nExpr - pSort->nDefer);
- pParse->nMem += pExtra->nExpr;
- }
-#endif
-
- /* Adjust nResultCol to account for columns that are omitted
- ** from the sorter by the optimizations in this branch */
- pEList = p->pEList;
- for(i=0; i<pEList->nExpr; i++){
- if( pEList->a[i].u.x.iOrderByCol>0
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- || pEList->a[i].bSorterRef
-#endif
- ){
- nResultCol--;
- regOrig = 0;
- }
- }
-
- testcase( regOrig );
- testcase( eDest==SRT_Set );
- testcase( eDest==SRT_Mem );
- testcase( eDest==SRT_Coroutine );
- testcase( eDest==SRT_Output );
- assert( eDest==SRT_Set || eDest==SRT_Mem
- || eDest==SRT_Coroutine || eDest==SRT_Output );
- }
- sRowLoadInfo.regResult = regResult;
- sRowLoadInfo.ecelFlags = ecelFlags;
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- sRowLoadInfo.pExtra = pExtra;
- sRowLoadInfo.regExtraResult = regResult + nResultCol;
- if( pExtra ) nResultCol += pExtra->nExpr;
-#endif
- if( p->iLimit
- && (ecelFlags & SQLITE_ECEL_OMITREF)!=0
- && nPrefixReg>0
- ){
- assert( pSort!=0 );
- assert( hasDistinct==0 );
- pSort->pDeferredRowLoad = &sRowLoadInfo;
- regOrig = 0;
- }else{
- innerLoopLoadRow(pParse, p, &sRowLoadInfo);
- }
- }
-
- /* If the DISTINCT keyword was present on the SELECT statement
- ** and this row has been seen before, then do not make this row
- ** part of the result.
- */
- if( hasDistinct ){
- switch( pDistinct->eTnctType ){
- case WHERE_DISTINCT_ORDERED: {
- VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
- int iJump; /* Jump destination */
- int regPrev; /* Previous row content */
-
- /* Allocate space for the previous row */
- regPrev = pParse->nMem+1;
- pParse->nMem += nResultCol;
-
- /* Change the OP_OpenEphemeral coded earlier to an OP_Null
- ** sets the MEM_Cleared bit on the first register of the
- ** previous value. This will cause the OP_Ne below to always
- ** fail on the first iteration of the loop even if the first
- ** row is all NULLs.
- */
- sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
- pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
- pOp->opcode = OP_Null;
- pOp->p1 = 1;
- pOp->p2 = regPrev;
-
- iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
- for(i=0; i<nResultCol; i++){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr);
- if( i<nResultCol-1 ){
- sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
- VdbeCoverage(v);
- }else{
- sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i);
- VdbeCoverage(v);
- }
- sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
- sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
- }
- assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
- sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
- break;
- }
-
- case WHERE_DISTINCT_UNIQUE: {
- sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
- break;
- }
-
- default: {
- assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
- codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol,
- regResult);
- break;
- }
- }
- if( pSort==0 ){
- codeOffset(v, p->iOffset, iContinue);
- }
- }
-
- switch( eDest ){
- /* In this mode, write each query result to the key of the temporary
- ** table iParm.
- */
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
- case SRT_Union: {
- int r1;
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
- sqlite3ReleaseTempReg(pParse, r1);
- break;
- }
-
- /* Construct a record from the query result, but instead of
- ** saving that record, use it as a key to delete elements from
- ** the temporary table iParm.
- */
- case SRT_Except: {
- sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol);
- break;
- }
-#endif /* SQLITE_OMIT_COMPOUND_SELECT */
-
- /* Store the result as data using a unique key.
- */
- case SRT_Fifo:
- case SRT_DistFifo:
- case SRT_Table:
- case SRT_EphemTab: {
- int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1);
- testcase( eDest==SRT_Table );
- testcase( eDest==SRT_EphemTab );
- testcase( eDest==SRT_Fifo );
- testcase( eDest==SRT_DistFifo );
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
-#ifndef SQLITE_OMIT_CTE
- if( eDest==SRT_DistFifo ){
- /* If the destination is DistFifo, then cursor (iParm+1) is open
- ** on an ephemeral index. If the current row is already present
- ** in the index, do not write it to the output. If not, add the
- ** current row to the index and proceed with writing it to the
- ** output table as well. */
- int addr = sqlite3VdbeCurrentAddr(v) + 4;
- sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
- VdbeCoverage(v);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol);
- assert( pSort==0 );
- }
-#endif
- if( pSort ){
- assert( regResult==regOrig );
- pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg);
- }else{
- int r2 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
- sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
- sqlite3ReleaseTempReg(pParse, r2);
- }
- sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1);
- break;
- }
-
-#ifndef SQLITE_OMIT_SUBQUERY
- /* If we are creating a set for an "expr IN (SELECT ...)" construct,
- ** then there should be a single item on the stack. Write this
- ** item into the set table with bogus data.
- */
- case SRT_Set: {
- if( pSort ){
- /* At first glance you would think we could optimize out the
- ** ORDER BY in this case since the order of entries in the set
- ** does not matter. But there might be a LIMIT clause, in which
- ** case the order does matter */
- pushOntoSorter(
- pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
- }else{
- int r1 = sqlite3GetTempReg(pParse);
- assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
- r1, pDest->zAffSdst, nResultCol);
- sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
- sqlite3ReleaseTempReg(pParse, r1);
- }
- break;
- }
-
- /* If any row exist in the result set, record that fact and abort.
- */
- case SRT_Exists: {
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);
- /* The LIMIT clause will terminate the loop for us */
- break;
- }
-
- /* If this is a scalar select that is part of an expression, then
- ** store the results in the appropriate memory cell or array of
- ** memory cells and break out of the scan loop.
- */
- case SRT_Mem: {
- if( pSort ){
- assert( nResultCol<=pDest->nSdst );
- pushOntoSorter(
- pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
- }else{
- assert( nResultCol==pDest->nSdst );
- assert( regResult==iParm );
- /* The LIMIT clause will jump out of the loop for us */
- }
- break;
- }
-#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
-
- case SRT_Coroutine: /* Send data to a co-routine */
- case SRT_Output: { /* Return the results */
- testcase( eDest==SRT_Coroutine );
- testcase( eDest==SRT_Output );
- if( pSort ){
- pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol,
- nPrefixReg);
- }else if( eDest==SRT_Coroutine ){
- sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
- }else{
- sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
- sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
- }
- break;
- }
-
-#ifndef SQLITE_OMIT_CTE
- /* Write the results into a priority queue that is order according to
- ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an
- ** index with pSO->nExpr+2 columns. Build a key using pSO for the first
- ** pSO->nExpr columns, then make sure all keys are unique by adding a
- ** final OP_Sequence column. The last column is the record as a blob.
- */
- case SRT_DistQueue:
- case SRT_Queue: {
- int nKey;
- int r1, r2, r3;
- int addrTest = 0;
- ExprList *pSO;
- pSO = pDest->pOrderBy;
- assert( pSO );
- nKey = pSO->nExpr;
- r1 = sqlite3GetTempReg(pParse);
- r2 = sqlite3GetTempRange(pParse, nKey+2);
- r3 = r2+nKey+1;
- if( eDest==SRT_DistQueue ){
- /* If the destination is DistQueue, then cursor (iParm+1) is open
- ** on a second ephemeral index that holds all values every previously
- ** added to the queue. */
- addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0,
- regResult, nResultCol);
- VdbeCoverage(v);
- }
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3);
- if( eDest==SRT_DistQueue ){
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- }
- for(i=0; i<nKey; i++){
- sqlite3VdbeAddOp2(v, OP_SCopy,
- regResult + pSO->a[i].u.x.iOrderByCol - 1,
- r2+i);
- }
- sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
- if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
- sqlite3ReleaseTempReg(pParse, r1);
- sqlite3ReleaseTempRange(pParse, r2, nKey+2);
- break;
- }
-#endif /* SQLITE_OMIT_CTE */
-
-
-
-#if !defined(SQLITE_OMIT_TRIGGER)
- /* Discard the results. This is used for SELECT statements inside
- ** the body of a TRIGGER. The purpose of such selects is to call
- ** user-defined functions that have side effects. We do not care
- ** about the actual results of the select.
- */
- default: {
- assert( eDest==SRT_Discard );
- break;
- }
-#endif
- }
-
- /* Jump to the end of the loop if the LIMIT is reached. Except, if
- ** there is a sorter, in which case the sorter has already limited
- ** the output for us.
- */
- if( pSort==0 && p->iLimit ){
- sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
- }
-}
-
-/*
-** Allocate a KeyInfo object sufficient for an index of N key columns and
-** X extra columns.
-*/
-KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
- int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
- KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
- if( p ){
- p->aSortOrder = (u8*)&p->aColl[N+X];
- p->nKeyField = (u16)N;
- p->nAllField = (u16)(N+X);
- p->enc = ENC(db);
- p->db = db;
- p->nRef = 1;
- memset(&p[1], 0, nExtra);
- }else{
- sqlite3OomFault(db);
- }
- return p;
-}
-
-/*
-** Deallocate a KeyInfo object
-*/
-void sqlite3KeyInfoUnref(KeyInfo *p){
- if( p ){
- assert( p->nRef>0 );
- p->nRef--;
- if( p->nRef==0 ) sqlite3DbFreeNN(p->db, p);
- }
-}
-
-/*
-** Make a new pointer to a KeyInfo object
-*/
-KeyInfo *sqlite3KeyInfoRef(KeyInfo *p){
- if( p ){
- assert( p->nRef>0 );
- p->nRef++;
- }
- return p;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** Return TRUE if a KeyInfo object can be change. The KeyInfo object
-** can only be changed if this is just a single reference to the object.
-**
-** This routine is used only inside of assert() statements.
-*/
-int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; }
-#endif /* SQLITE_DEBUG */
-
-/*
-** Given an expression list, generate a KeyInfo structure that records
-** the collating sequence for each expression in that expression list.
-**
-** If the ExprList is an ORDER BY or GROUP BY clause then the resulting
-** KeyInfo structure is appropriate for initializing a virtual index to
-** implement that clause. If the ExprList is the result set of a SELECT
-** then the KeyInfo structure is appropriate for initializing a virtual
-** index to implement a DISTINCT test.
-**
-** Space to hold the KeyInfo structure is obtained from malloc. The calling
-** function is responsible for seeing that this structure is eventually
-** freed.
-*/
-static KeyInfo *keyInfoFromExprList(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* Form the KeyInfo object from this ExprList */
- int iStart, /* Begin with this column of pList */
- int nExtra /* Add this many extra columns to the end */
-){
- int nExpr;
- KeyInfo *pInfo;
- struct ExprList_item *pItem;
- sqlite3 *db = pParse->db;
- int i;
-
- nExpr = pList->nExpr;
- pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
- if( pInfo ){
- assert( sqlite3KeyInfoIsWriteable(pInfo) );
- for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
- pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
- pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
- }
- }
- return pInfo;
-}
-
-/*
-** Name of the connection operator, used for error messages.
-*/
-static const char *selectOpName(int id){
- char *z;
- switch( id ){
- case TK_ALL: z = "UNION ALL"; break;
- case TK_INTERSECT: z = "INTERSECT"; break;
- case TK_EXCEPT: z = "EXCEPT"; break;
- default: z = "UNION"; break;
- }
- return z;
-}
-
-#ifndef SQLITE_OMIT_EXPLAIN
-/*
-** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
-** is a no-op. Otherwise, it adds a single row of output to the EQP result,
-** where the caption is of the form:
-**
-** "USE TEMP B-TREE FOR xxx"
-**
-** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which
-** is determined by the zUsage argument.
-*/
-static void explainTempTable(Parse *pParse, const char *zUsage){
- ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage));
-}
-
-/*
-** Assign expression b to lvalue a. A second, no-op, version of this macro
-** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
-** in sqlite3Select() to assign values to structure member variables that
-** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
-** code with #ifndef directives.
-*/
-# define explainSetInteger(a, b) a = b
-
-#else
-/* No-op versions of the explainXXX() functions and macros. */
-# define explainTempTable(y,z)
-# define explainSetInteger(y,z)
-#endif
-
-
-/*
-** If the inner loop was generated using a non-null pOrderBy argument,
-** then the results were placed in a sorter. After the loop is terminated
-** we need to run the sorter and output the results. The following
-** routine generates the code needed to do that.
-*/
-static void generateSortTail(
- Parse *pParse, /* Parsing context */
- Select *p, /* The SELECT statement */
- SortCtx *pSort, /* Information on the ORDER BY clause */
- int nColumn, /* Number of columns of data */
- SelectDest *pDest /* Write the sorted results here */
-){
- Vdbe *v = pParse->pVdbe; /* The prepared statement */
- int addrBreak = pSort->labelDone; /* Jump here to exit loop */
- int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
- int addr; /* Top of output loop. Jump for Next. */
- int addrOnce = 0;
- int iTab;
- ExprList *pOrderBy = pSort->pOrderBy;
- int eDest = pDest->eDest;
- int iParm = pDest->iSDParm;
- int regRow;
- int regRowid;
- int iCol;
- int nKey; /* Number of key columns in sorter record */
- int iSortTab; /* Sorter cursor to read from */
- int i;
- int bSeq; /* True if sorter record includes seq. no. */
- int nRefKey = 0;
- struct ExprList_item *aOutEx = p->pEList->a;
-
- assert( addrBreak<0 );
- if( pSort->labelBkOut ){
- sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
- sqlite3VdbeGoto(v, addrBreak);
- sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
- }
-
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- /* Open any cursors needed for sorter-reference expressions */
- for(i=0; i<pSort->nDefer; i++){
- Table *pTab = pSort->aDefer[i].pTab;
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead);
- nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey);
- }
-#endif
-
- iTab = pSort->iECursor;
- if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){
- regRowid = 0;
- regRow = pDest->iSdst;
- }else{
- regRowid = sqlite3GetTempReg(pParse);
- regRow = sqlite3GetTempRange(pParse, nColumn);
- }
- nKey = pOrderBy->nExpr - pSort->nOBSat;
- if( pSort->sortFlags & SORTFLAG_UseSorter ){
- int regSortOut = ++pParse->nMem;
- iSortTab = pParse->nTab++;
- if( pSort->labelBkOut ){
- addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- }
- sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut,
- nKey+1+nColumn+nRefKey);
- if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
- addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
- VdbeCoverage(v);
- codeOffset(v, p->iOffset, addrContinue);
- sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab);
- bSeq = 0;
- }else{
- addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
- codeOffset(v, p->iOffset, addrContinue);
- iSortTab = iTab;
- bSeq = 1;
- }
- for(i=0, iCol=nKey+bSeq-1; i<nColumn; i++){
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( aOutEx[i].bSorterRef ) continue;
-#endif
- if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
- }
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( pSort->nDefer ){
- int iKey = iCol+1;
- int regKey = sqlite3GetTempRange(pParse, nRefKey);
-
- for(i=0; i<pSort->nDefer; i++){
- int iCsr = pSort->aDefer[i].iCsr;
- Table *pTab = pSort->aDefer[i].pTab;
- int nKey = pSort->aDefer[i].nKey;
-
- sqlite3VdbeAddOp1(v, OP_NullRow, iCsr);
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey);
- sqlite3VdbeAddOp3(v, OP_SeekRowid, iCsr,
- sqlite3VdbeCurrentAddr(v)+1, regKey);
- }else{
- int k;
- int iJmp;
- assert( sqlite3PrimaryKeyIndex(pTab)->nKeyCol==nKey );
- for(k=0; k<nKey; k++){
- sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey+k);
- }
- iJmp = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp4Int(v, OP_SeekGE, iCsr, iJmp+2, regKey, nKey);
- sqlite3VdbeAddOp4Int(v, OP_IdxLE, iCsr, iJmp+3, regKey, nKey);
- sqlite3VdbeAddOp1(v, OP_NullRow, iCsr);
- }
- }
- sqlite3ReleaseTempRange(pParse, regKey, nRefKey);
- }
-#endif
- for(i=nColumn-1; i>=0; i--){
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( aOutEx[i].bSorterRef ){
- sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i);
- }else
-#endif
- {
- int iRead;
- if( aOutEx[i].u.x.iOrderByCol ){
- iRead = aOutEx[i].u.x.iOrderByCol-1;
- }else{
- iRead = iCol--;
- }
- sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
- VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan));
- }
- }
- switch( eDest ){
- case SRT_Table:
- case SRT_EphemTab: {
- sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
- break;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case SRT_Set: {
- assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) );
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid,
- pDest->zAffSdst, nColumn);
- sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
- break;
- }
- case SRT_Mem: {
- /* The LIMIT clause will terminate the loop for us */
- break;
- }
-#endif
- default: {
- assert( eDest==SRT_Output || eDest==SRT_Coroutine );
- testcase( eDest==SRT_Output );
- testcase( eDest==SRT_Coroutine );
- if( eDest==SRT_Output ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
- sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
- }else{
- sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
- }
- break;
- }
- }
- if( regRowid ){
- if( eDest==SRT_Set ){
- sqlite3ReleaseTempRange(pParse, regRow, nColumn);
- }else{
- sqlite3ReleaseTempReg(pParse, regRow);
- }
- sqlite3ReleaseTempReg(pParse, regRowid);
- }
- /* The bottom of the loop
- */
- sqlite3VdbeResolveLabel(v, addrContinue);
- if( pSort->sortFlags & SORTFLAG_UseSorter ){
- sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
- }else{
- sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
- }
- if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
- sqlite3VdbeResolveLabel(v, addrBreak);
-}
-
-/*
-** Return a pointer to a string containing the 'declaration type' of the
-** expression pExpr. The string may be treated as static by the caller.
-**
-** Also try to estimate the size of the returned value and return that
-** result in *pEstWidth.
-**
-** The declaration type is the exact datatype definition extracted from the
-** original CREATE TABLE statement if the expression is a column. The
-** declaration type for a ROWID field is INTEGER. Exactly when an expression
-** is considered a column can be complex in the presence of subqueries. The
-** result-set expression in all of the following SELECT statements is
-** considered a column by this function.
-**
-** SELECT col FROM tbl;
-** SELECT (SELECT col FROM tbl;
-** SELECT (SELECT col FROM tbl);
-** SELECT abc FROM (SELECT col AS abc FROM tbl);
-**
-** The declaration type for any expression other than a column is NULL.
-**
-** This routine has either 3 or 6 parameters depending on whether or not
-** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
-*/
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
-# define columnType(A,B,C,D,E) columnTypeImpl(A,B,C,D,E)
-#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
-# define columnType(A,B,C,D,E) columnTypeImpl(A,B)
-#endif
-static const char *columnTypeImpl(
- NameContext *pNC,
-#ifndef SQLITE_ENABLE_COLUMN_METADATA
- Expr *pExpr
-#else
- Expr *pExpr,
- const char **pzOrigDb,
- const char **pzOrigTab,
- const char **pzOrigCol
-#endif
-){
- char const *zType = 0;
- int j;
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
- char const *zOrigDb = 0;
- char const *zOrigTab = 0;
- char const *zOrigCol = 0;
-#endif
-
- assert( pExpr!=0 );
- assert( pNC->pSrcList!=0 );
- assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates
- ** are processed */
- switch( pExpr->op ){
- case TK_COLUMN: {
- /* The expression is a column. Locate the table the column is being
- ** extracted from in NameContext.pSrcList. This table may be real
- ** database table or a subquery.
- */
- Table *pTab = 0; /* Table structure column is extracted from */
- Select *pS = 0; /* Select the column is extracted from */
- int iCol = pExpr->iColumn; /* Index of column in pTab */
- while( pNC && !pTab ){
- SrcList *pTabList = pNC->pSrcList;
- for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
- if( j<pTabList->nSrc ){
- pTab = pTabList->a[j].pTab;
- pS = pTabList->a[j].pSelect;
- }else{
- pNC = pNC->pNext;
- }
- }
-
- if( pTab==0 ){
- /* At one time, code such as "SELECT new.x" within a trigger would
- ** cause this condition to run. Since then, we have restructured how
- ** trigger code is generated and so this condition is no longer
- ** possible. However, it can still be true for statements like
- ** the following:
- **
- ** CREATE TABLE t1(col INTEGER);
- ** SELECT (SELECT t1.col) FROM FROM t1;
- **
- ** when columnType() is called on the expression "t1.col" in the
- ** sub-select. In this case, set the column type to NULL, even
- ** though it should really be "INTEGER".
- **
- ** This is not a problem, as the column type of "t1.col" is never
- ** used. When columnType() is called on the expression
- ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
- ** branch below. */
- break;
- }
-
- assert( pTab && pExpr->pTab==pTab );
- if( pS ){
- /* The "table" is actually a sub-select or a view in the FROM clause
- ** of the SELECT statement. Return the declaration type and origin
- ** data for the result-set column of the sub-select.
- */
- if( iCol>=0 && iCol<pS->pEList->nExpr ){
- /* If iCol is less than zero, then the expression requests the
- ** rowid of the sub-select or view. This expression is legal (see
- ** test case misc2.2.2) - it always evaluates to NULL.
- */
- NameContext sNC;
- Expr *p = pS->pEList->a[iCol].pExpr;
- sNC.pSrcList = pS->pSrc;
- sNC.pNext = pNC;
- sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol);
- }
- }else{
- /* A real table or a CTE table */
- assert( !pS );
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
- if( iCol<0 ) iCol = pTab->iPKey;
- assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) );
- if( iCol<0 ){
- zType = "INTEGER";
- zOrigCol = "rowid";
- }else{
- zOrigCol = pTab->aCol[iCol].zName;
- zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
- }
- zOrigTab = pTab->zName;
- if( pNC->pParse && pTab->pSchema ){
- int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
- zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName;
- }
-#else
- assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) );
- if( iCol<0 ){
- zType = "INTEGER";
- }else{
- zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
- }
-#endif
- }
- break;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_SELECT: {
- /* The expression is a sub-select. Return the declaration type and
- ** origin info for the single column in the result set of the SELECT
- ** statement.
- */
- NameContext sNC;
- Select *pS = pExpr->x.pSelect;
- Expr *p = pS->pEList->a[0].pExpr;
- assert( ExprHasProperty(pExpr, EP_xIsSelect) );
- sNC.pSrcList = pS->pSrc;
- sNC.pNext = pNC;
- sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
- break;
- }
-#endif
- }
-
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
- if( pzOrigDb ){
- assert( pzOrigTab && pzOrigCol );
- *pzOrigDb = zOrigDb;
- *pzOrigTab = zOrigTab;
- *pzOrigCol = zOrigCol;
- }
-#endif
- return zType;
-}
-
-/*
-** Generate code that will tell the VDBE the declaration types of columns
-** in the result set.
-*/
-static void generateColumnTypes(
- Parse *pParse, /* Parser context */
- SrcList *pTabList, /* List of tables */
- ExprList *pEList /* Expressions defining the result set */
-){
-#ifndef SQLITE_OMIT_DECLTYPE
- Vdbe *v = pParse->pVdbe;
- int i;
- NameContext sNC;
- sNC.pSrcList = pTabList;
- sNC.pParse = pParse;
- sNC.pNext = 0;
- for(i=0; i<pEList->nExpr; i++){
- Expr *p = pEList->a[i].pExpr;
- const char *zType;
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
- const char *zOrigDb = 0;
- const char *zOrigTab = 0;
- const char *zOrigCol = 0;
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
-
- /* The vdbe must make its own copy of the column-type and other
- ** column specific strings, in case the schema is reset before this
- ** virtual machine is deleted.
- */
- sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
- sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
- sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
-#else
- zType = columnType(&sNC, p, 0, 0, 0);
-#endif
- sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
- }
-#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
-}
-
-
-/*
-** Compute the column names for a SELECT statement.
-**
-** The only guarantee that SQLite makes about column names is that if the
-** column has an AS clause assigning it a name, that will be the name used.
-** That is the only documented guarantee. However, countless applications
-** developed over the years have made baseless assumptions about column names
-** and will break if those assumptions changes. Hence, use extreme caution
-** when modifying this routine to avoid breaking legacy.
-**
-** See Also: sqlite3ColumnsFromExprList()
-**
-** The PRAGMA short_column_names and PRAGMA full_column_names settings are
-** deprecated. The default setting is short=ON, full=OFF. 99.9% of all
-** applications should operate this way. Nevertheless, we need to support the
-** other modes for legacy:
-**
-** short=OFF, full=OFF: Column name is the text of the expression has it
-** originally appears in the SELECT statement. In
-** other words, the zSpan of the result expression.
-**
-** short=ON, full=OFF: (This is the default setting). If the result
-** refers directly to a table column, then the
-** result column name is just the table column
-** name: COLUMN. Otherwise use zSpan.
-**
-** full=ON, short=ANY: If the result refers directly to a table column,
-** then the result column name with the table name
-** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
-*/
-static void generateColumnNames(
- Parse *pParse, /* Parser context */
- Select *pSelect /* Generate column names for this SELECT statement */
-){
- Vdbe *v = pParse->pVdbe;
- int i;
- Table *pTab;
- SrcList *pTabList;
- ExprList *pEList;
- sqlite3 *db = pParse->db;
- int fullName; /* TABLE.COLUMN if no AS clause and is a direct table ref */
- int srcName; /* COLUMN or TABLE.COLUMN if no AS clause and is direct */
-
-#ifndef SQLITE_OMIT_EXPLAIN
- /* If this is an EXPLAIN, skip this step */
- if( pParse->explain ){
- return;
- }
-#endif
-
- if( pParse->colNamesSet ) return;
- /* Column names are determined by the left-most term of a compound select */
- while( pSelect->pPrior ) pSelect = pSelect->pPrior;
- SELECTTRACE(1,pParse,pSelect,("generating column names\n"));
- pTabList = pSelect->pSrc;
- pEList = pSelect->pEList;
- assert( v!=0 );
- assert( pTabList!=0 );
- pParse->colNamesSet = 1;
- fullName = (db->flags & SQLITE_FullColNames)!=0;
- srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName;
- sqlite3VdbeSetNumCols(v, pEList->nExpr);
- for(i=0; i<pEList->nExpr; i++){
- Expr *p = pEList->a[i].pExpr;
-
- assert( p!=0 );
- assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
- assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
- if( pEList->a[i].zName ){
- /* An AS clause always takes first priority */
- char *zName = pEList->a[i].zName;
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
- }else if( srcName && p->op==TK_COLUMN ){
- char *zCol;
- int iCol = p->iColumn;
- pTab = p->pTab;
- assert( pTab!=0 );
- if( iCol<0 ) iCol = pTab->iPKey;
- assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
- if( iCol<0 ){
- zCol = "rowid";
- }else{
- zCol = pTab->aCol[iCol].zName;
- }
- if( fullName ){
- char *zName = 0;
- zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
- }else{
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
- }
- }else{
- const char *z = pEList->a[i].zSpan;
- z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z);
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC);
- }
- }
- generateColumnTypes(pParse, pTabList, pEList);
-}
-
-/*
-** Given an expression list (which is really the list of expressions
-** that form the result set of a SELECT statement) compute appropriate
-** column names for a table that would hold the expression list.
-**
-** All column names will be unique.
-**
-** Only the column names are computed. Column.zType, Column.zColl,
-** and other fields of Column are zeroed.
-**
-** Return SQLITE_OK on success. If a memory allocation error occurs,
-** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
-**
-** The only guarantee that SQLite makes about column names is that if the
-** column has an AS clause assigning it a name, that will be the name used.
-** That is the only documented guarantee. However, countless applications
-** developed over the years have made baseless assumptions about column names
-** and will break if those assumptions changes. Hence, use extreme caution
-** when modifying this routine to avoid breaking legacy.
-**
-** See Also: generateColumnNames()
-*/
-int sqlite3ColumnsFromExprList(
- Parse *pParse, /* Parsing context */
- ExprList *pEList, /* Expr list from which to derive column names */
- i16 *pnCol, /* Write the number of columns here */
- Column **paCol /* Write the new column list here */
-){
- sqlite3 *db = pParse->db; /* Database connection */
- int i, j; /* Loop counters */
- u32 cnt; /* Index added to make the name unique */
- Column *aCol, *pCol; /* For looping over result columns */
- int nCol; /* Number of columns in the result set */
- char *zName; /* Column name */
- int nName; /* Size of name in zName[] */
- Hash ht; /* Hash table of column names */
-
- sqlite3HashInit(&ht);
- if( pEList ){
- nCol = pEList->nExpr;
- aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
- testcase( aCol==0 );
- if( nCol>32767 ) nCol = 32767;
- }else{
- nCol = 0;
- aCol = 0;
- }
- assert( nCol==(i16)nCol );
- *pnCol = nCol;
- *paCol = aCol;
-
- for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
- /* Get an appropriate name for the column
- */
- if( (zName = pEList->a[i].zName)!=0 ){
- /* If the column contains an "AS <name>" phrase, use <name> as the name */
- }else{
- Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
- while( pColExpr->op==TK_DOT ){
- pColExpr = pColExpr->pRight;
- assert( pColExpr!=0 );
- }
- assert( pColExpr->op!=TK_AGG_COLUMN );
- if( pColExpr->op==TK_COLUMN ){
- /* For columns use the column name name */
- int iCol = pColExpr->iColumn;
- Table *pTab = pColExpr->pTab;
- assert( pTab!=0 );
- if( iCol<0 ) iCol = pTab->iPKey;
- zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
- }else if( pColExpr->op==TK_ID ){
- assert( !ExprHasProperty(pColExpr, EP_IntValue) );
- zName = pColExpr->u.zToken;
- }else{
- /* Use the original text of the column expression as its name */
- zName = pEList->a[i].zSpan;
- }
- }
- if( zName ){
- zName = sqlite3DbStrDup(db, zName);
- }else{
- zName = sqlite3MPrintf(db,"column%d",i+1);
- }
-
- /* Make sure the column name is unique. If the name is not unique,
- ** append an integer to the name so that it becomes unique.
- */
- cnt = 0;
- while( zName && sqlite3HashFind(&ht, zName)!=0 ){
- nName = sqlite3Strlen30(zName);
- if( nName>0 ){
- for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){}
- if( zName[j]==':' ) nName = j;
- }
- zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
- if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
- }
- pCol->zName = zName;
- sqlite3ColumnPropertiesFromName(0, pCol);
- if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
- sqlite3OomFault(db);
- }
- }
- sqlite3HashClear(&ht);
- if( db->mallocFailed ){
- for(j=0; j<i; j++){
- sqlite3DbFree(db, aCol[j].zName);
- }
- sqlite3DbFree(db, aCol);
- *paCol = 0;
- *pnCol = 0;
- return SQLITE_NOMEM_BKPT;
- }
- return SQLITE_OK;
-}
-
-/*
-** Add type and collation information to a column list based on
-** a SELECT statement.
-**
-** The column list presumably came from selectColumnNamesFromExprList().
-** The column list has only names, not types or collations. This
-** routine goes through and adds the types and collations.
-**
-** This routine requires that all identifiers in the SELECT
-** statement be resolved.
-*/
-void sqlite3SelectAddColumnTypeAndCollation(
- Parse *pParse, /* Parsing contexts */
- Table *pTab, /* Add column type information to this table */
- Select *pSelect /* SELECT used to determine types and collations */
-){
- sqlite3 *db = pParse->db;
- NameContext sNC;
- Column *pCol;
- CollSeq *pColl;
- int i;
- Expr *p;
- struct ExprList_item *a;
-
- assert( pSelect!=0 );
- assert( (pSelect->selFlags & SF_Resolved)!=0 );
- assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
- if( db->mallocFailed ) return;
- memset(&sNC, 0, sizeof(sNC));
- sNC.pSrcList = pSelect->pSrc;
- a = pSelect->pEList->a;
- for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
- const char *zType;
- int n, m;
- p = a[i].pExpr;
- zType = columnType(&sNC, p, 0, 0, 0);
- /* pCol->szEst = ... // Column size est for SELECT tables never used */
- pCol->affinity = sqlite3ExprAffinity(p);
- if( zType ){
- m = sqlite3Strlen30(zType);
- n = sqlite3Strlen30(pCol->zName);
- pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2);
- if( pCol->zName ){
- memcpy(&pCol->zName[n+1], zType, m+1);
- pCol->colFlags |= COLFLAG_HASTYPE;
- }
- }
- if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
- pColl = sqlite3ExprCollSeq(pParse, p);
- if( pColl && pCol->zColl==0 ){
- pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
- }
- }
- pTab->szTabRow = 1; /* Any non-zero value works */
-}
-
-/*
-** Given a SELECT statement, generate a Table structure that describes
-** the result set of that SELECT.
-*/
-Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
- Table *pTab;
- sqlite3 *db = pParse->db;
- int savedFlags;
-
- savedFlags = db->flags;
- db->flags &= ~SQLITE_FullColNames;
- db->flags |= SQLITE_ShortColNames;
- sqlite3SelectPrep(pParse, pSelect, 0);
- if( pParse->nErr ) return 0;
- while( pSelect->pPrior ) pSelect = pSelect->pPrior;
- db->flags = savedFlags;
- pTab = sqlite3DbMallocZero(db, sizeof(Table) );
- if( pTab==0 ){
- return 0;
- }
- /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
- ** is disabled */
- assert( db->lookaside.bDisable );
- pTab->nTabRef = 1;
- pTab->zName = 0;
- pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
- sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
- pTab->iPKey = -1;
- if( db->mallocFailed ){
- sqlite3DeleteTable(db, pTab);
- return 0;
- }
- return pTab;
-}
-
-/*
-** Get a VDBE for the given parser context. Create a new one if necessary.
-** If an error occurs, return NULL and leave a message in pParse.
-*/
-Vdbe *sqlite3GetVdbe(Parse *pParse){
- if( pParse->pVdbe ){
- return pParse->pVdbe;
- }
- if( pParse->pToplevel==0
- && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
- ){
- pParse->okConstFactor = 1;
- }
- return sqlite3VdbeCreate(pParse);
-}
-
-
-/*
-** Compute the iLimit and iOffset fields of the SELECT based on the
-** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions
-** that appear in the original SQL statement after the LIMIT and OFFSET
-** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
-** are the integer memory register numbers for counters used to compute
-** the limit and offset. If there is no limit and/or offset, then
-** iLimit and iOffset are negative.
-**
-** This routine changes the values of iLimit and iOffset only if
-** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit
-** and iOffset should have been preset to appropriate default values (zero)
-** prior to calling this routine.
-**
-** The iOffset register (if it exists) is initialized to the value
-** of the OFFSET. The iLimit register is initialized to LIMIT. Register
-** iOffset+1 is initialized to LIMIT+OFFSET.
-**
-** Only if pLimit->pLeft!=0 do the limit registers get
-** redefined. The UNION ALL operator uses this property to force
-** the reuse of the same limit and offset registers across multiple
-** SELECT statements.
-*/
-static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
- Vdbe *v = 0;
- int iLimit = 0;
- int iOffset;
- int n;
- Expr *pLimit = p->pLimit;
-
- if( p->iLimit ) return;
-
- /*
- ** "LIMIT -1" always shows all rows. There is some
- ** controversy about what the correct behavior should be.
- ** The current implementation interprets "LIMIT 0" to mean
- ** no rows.
- */
- sqlite3ExprCacheClear(pParse);
- if( pLimit ){
- assert( pLimit->op==TK_LIMIT );
- assert( pLimit->pLeft!=0 );
- p->iLimit = iLimit = ++pParse->nMem;
- v = sqlite3GetVdbe(pParse);
- assert( v!=0 );
- if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
- sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
- VdbeComment((v, "LIMIT counter"));
- if( n==0 ){
- sqlite3VdbeGoto(v, iBreak);
- }else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){
- p->nSelectRow = sqlite3LogEst((u64)n);
- p->selFlags |= SF_FixedLimit;
- }
- }else{
- sqlite3ExprCode(pParse, pLimit->pLeft, iLimit);
- sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
- VdbeComment((v, "LIMIT counter"));
- sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
- }
- if( pLimit->pRight ){
- p->iOffset = iOffset = ++pParse->nMem;
- pParse->nMem++; /* Allocate an extra register for limit+offset */
- sqlite3ExprCode(pParse, pLimit->pRight, iOffset);
- sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
- VdbeComment((v, "OFFSET counter"));
- sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
- VdbeComment((v, "LIMIT+OFFSET"));
- }
- }
-}
-
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
-/*
-** Return the appropriate collating sequence for the iCol-th column of
-** the result set for the compound-select statement "p". Return NULL if
-** the column has no default collating sequence.
-**
-** The collating sequence for the compound select is taken from the
-** left-most term of the select that has a collating sequence.
-*/
-static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
- CollSeq *pRet;
- if( p->pPrior ){
- pRet = multiSelectCollSeq(pParse, p->pPrior, iCol);
- }else{
- pRet = 0;
- }
- assert( iCol>=0 );
- /* iCol must be less than p->pEList->nExpr. Otherwise an error would
- ** have been thrown during name resolution and we would not have gotten
- ** this far */
- if( pRet==0 && ALWAYS(iCol<p->pEList->nExpr) ){
- pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
- }
- return pRet;
-}
-
-/*
-** The select statement passed as the second parameter is a compound SELECT
-** with an ORDER BY clause. This function allocates and returns a KeyInfo
-** structure suitable for implementing the ORDER BY.
-**
-** Space to hold the KeyInfo structure is obtained from malloc. The calling
-** function is responsible for ensuring that this structure is eventually
-** freed.
-*/
-static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
- ExprList *pOrderBy = p->pOrderBy;
- int nOrderBy = p->pOrderBy->nExpr;
- sqlite3 *db = pParse->db;
- KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
- if( pRet ){
- int i;
- for(i=0; i<nOrderBy; i++){
- struct ExprList_item *pItem = &pOrderBy->a[i];
- Expr *pTerm = pItem->pExpr;
- CollSeq *pColl;
-
- if( pTerm->flags & EP_Collate ){
- pColl = sqlite3ExprCollSeq(pParse, pTerm);
- }else{
- pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
- if( pColl==0 ) pColl = db->pDfltColl;
- pOrderBy->a[i].pExpr =
- sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
- }
- assert( sqlite3KeyInfoIsWriteable(pRet) );
- pRet->aColl[i] = pColl;
- pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
- }
- }
-
- return pRet;
-}
-
-#ifndef SQLITE_OMIT_CTE
-/*
-** This routine generates VDBE code to compute the content of a WITH RECURSIVE
-** query of the form:
-**
-** <recursive-table> AS (<setup-query> UNION [ALL] <recursive-query>)
-** \___________/ \_______________/
-** p->pPrior p
-**
-**
-** There is exactly one reference to the recursive-table in the FROM clause
-** of recursive-query, marked with the SrcList->a[].fg.isRecursive flag.
-**
-** The setup-query runs once to generate an initial set of rows that go
-** into a Queue table. Rows are extracted from the Queue table one by
-** one. Each row extracted from Queue is output to pDest. Then the single
-** extracted row (now in the iCurrent table) becomes the content of the
-** recursive-table for a recursive-query run. The output of the recursive-query
-** is added back into the Queue table. Then another row is extracted from Queue
-** and the iteration continues until the Queue table is empty.
-**
-** If the compound query operator is UNION then no duplicate rows are ever
-** inserted into the Queue table. The iDistinct table keeps a copy of all rows
-** that have ever been inserted into Queue and causes duplicates to be
-** discarded. If the operator is UNION ALL, then duplicates are allowed.
-**
-** If the query has an ORDER BY, then entries in the Queue table are kept in
-** ORDER BY order and the first entry is extracted for each cycle. Without
-** an ORDER BY, the Queue table is just a FIFO.
-**
-** If a LIMIT clause is provided, then the iteration stops after LIMIT rows
-** have been output to pDest. A LIMIT of zero means to output no rows and a
-** negative LIMIT means to output all rows. If there is also an OFFSET clause
-** with a positive value, then the first OFFSET outputs are discarded rather
-** than being sent to pDest. The LIMIT count does not begin until after OFFSET
-** rows have been skipped.
-*/
-static void generateWithRecursiveQuery(
- Parse *pParse, /* Parsing context */
- Select *p, /* The recursive SELECT to be coded */
- SelectDest *pDest /* What to do with query results */
-){
- SrcList *pSrc = p->pSrc; /* The FROM clause of the recursive query */
- int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */
- Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
- Select *pSetup = p->pPrior; /* The setup query */
- int addrTop; /* Top of the loop */
- int addrCont, addrBreak; /* CONTINUE and BREAK addresses */
- int iCurrent = 0; /* The Current table */
- int regCurrent; /* Register holding Current table */
- int iQueue; /* The Queue table */
- int iDistinct = 0; /* To ensure unique results if UNION */
- int eDest = SRT_Fifo; /* How to write to Queue */
- SelectDest destQueue; /* SelectDest targetting the Queue table */
- int i; /* Loop counter */
- int rc; /* Result code */
- ExprList *pOrderBy; /* The ORDER BY clause */
- Expr *pLimit; /* Saved LIMIT and OFFSET */
- int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */
-
- /* Obtain authorization to do a recursive query */
- if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
-
- /* Process the LIMIT and OFFSET clauses, if they exist */
- addrBreak = sqlite3VdbeMakeLabel(v);
- p->nSelectRow = 320; /* 4 billion rows */
- computeLimitRegisters(pParse, p, addrBreak);
- pLimit = p->pLimit;
- regLimit = p->iLimit;
- regOffset = p->iOffset;
- p->pLimit = 0;
- p->iLimit = p->iOffset = 0;
- pOrderBy = p->pOrderBy;
-
- /* Locate the cursor number of the Current table */
- for(i=0; ALWAYS(i<pSrc->nSrc); i++){
- if( pSrc->a[i].fg.isRecursive ){
- iCurrent = pSrc->a[i].iCursor;
- break;
- }
- }
-
- /* Allocate cursors numbers for Queue and Distinct. The cursor number for
- ** the Distinct table must be exactly one greater than Queue in order
- ** for the SRT_DistFifo and SRT_DistQueue destinations to work. */
- iQueue = pParse->nTab++;
- if( p->op==TK_UNION ){
- eDest = pOrderBy ? SRT_DistQueue : SRT_DistFifo;
- iDistinct = pParse->nTab++;
- }else{
- eDest = pOrderBy ? SRT_Queue : SRT_Fifo;
- }
- sqlite3SelectDestInit(&destQueue, eDest, iQueue);
-
- /* Allocate cursors for Current, Queue, and Distinct. */
- regCurrent = ++pParse->nMem;
- sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
- if( pOrderBy ){
- KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
- (char*)pKeyInfo, P4_KEYINFO);
- destQueue.pOrderBy = pOrderBy;
- }else{
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
- }
- VdbeComment((v, "Queue table"));
- if( iDistinct ){
- p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
- p->selFlags |= SF_UsesEphemeral;
- }
-
- /* Detach the ORDER BY clause from the compound SELECT */
- p->pOrderBy = 0;
-
- /* Store the results of the setup-query in Queue. */
- pSetup->pNext = 0;
- ExplainQueryPlan((pParse, 1, "SETUP"));
- rc = sqlite3Select(pParse, pSetup, &destQueue);
- pSetup->pNext = p;
- if( rc ) goto end_of_recursive_query;
-
- /* Find the next row in the Queue and output that row */
- addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v);
-
- /* Transfer the next row in Queue over to Current */
- sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */
- if( pOrderBy ){
- sqlite3VdbeAddOp3(v, OP_Column, iQueue, pOrderBy->nExpr+1, regCurrent);
- }else{
- sqlite3VdbeAddOp2(v, OP_RowData, iQueue, regCurrent);
- }
- sqlite3VdbeAddOp1(v, OP_Delete, iQueue);
-
- /* Output the single row in Current */
- addrCont = sqlite3VdbeMakeLabel(v);
- codeOffset(v, regOffset, addrCont);
- selectInnerLoop(pParse, p, iCurrent,
- 0, 0, pDest, addrCont, addrBreak);
- if( regLimit ){
- sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak);
- VdbeCoverage(v);
- }
- sqlite3VdbeResolveLabel(v, addrCont);
-
- /* Execute the recursive SELECT taking the single row in Current as
- ** the value for the recursive-table. Store the results in the Queue.
- */
- if( p->selFlags & SF_Aggregate ){
- sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
- }else{
- p->pPrior = 0;
- ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
- sqlite3Select(pParse, p, &destQueue);
- assert( p->pPrior==0 );
- p->pPrior = pSetup;
- }
-
- /* Keep running the loop until the Queue is empty */
- sqlite3VdbeGoto(v, addrTop);
- sqlite3VdbeResolveLabel(v, addrBreak);
-
-end_of_recursive_query:
- sqlite3ExprListDelete(pParse->db, p->pOrderBy);
- p->pOrderBy = pOrderBy;
- p->pLimit = pLimit;
- return;
-}
-#endif /* SQLITE_OMIT_CTE */
-
-/* Forward references */
-static int multiSelectOrderBy(
- Parse *pParse, /* Parsing context */
- Select *p, /* The right-most of SELECTs to be coded */
- SelectDest *pDest /* What to do with query results */
-);
-
-/*
-** Handle the special case of a compound-select that originates from a
-** VALUES clause. By handling this as a special case, we avoid deep
-** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT
-** on a VALUES clause.
-**
-** Because the Select object originates from a VALUES clause:
-** (1) There is no LIMIT or OFFSET or else there is a LIMIT of exactly 1
-** (2) All terms are UNION ALL
-** (3) There is no ORDER BY clause
-**
-** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES
-** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))").
-** The sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case.
-** Since the limit is exactly 1, we only need to evalutes the left-most VALUES.
-*/
-static int multiSelectValues(
- Parse *pParse, /* Parsing context */
- Select *p, /* The right-most of SELECTs to be coded */
- SelectDest *pDest /* What to do with query results */
-){
- int nRow = 1;
- int rc = 0;
- int bShowAll = p->pLimit==0;
- assert( p->selFlags & SF_MultiValue );
- do{
- assert( p->selFlags & SF_Values );
- assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
- assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
- if( p->pPrior==0 ) break;
- assert( p->pPrior->pNext==p );
- p = p->pPrior;
- nRow += bShowAll;
- }while(1);
- ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow,
- nRow==1 ? "" : "S"));
- while( p ){
- selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1);
- if( !bShowAll ) break;
- p->nSelectRow = nRow;
- p = p->pNext;
- }
- return rc;
-}
-
-/*
-** This routine is called to process a compound query form from
-** two or more separate queries using UNION, UNION ALL, EXCEPT, or
-** INTERSECT
-**
-** "p" points to the right-most of the two queries. the query on the
-** left is p->pPrior. The left query could also be a compound query
-** in which case this routine will be called recursively.
-**
-** The results of the total query are to be written into a destination
-** of type eDest with parameter iParm.
-**
-** Example 1: Consider a three-way compound SQL statement.
-**
-** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3
-**
-** This statement is parsed up as follows:
-**
-** SELECT c FROM t3
-** |
-** `-----> SELECT b FROM t2
-** |
-** `------> SELECT a FROM t1
-**
-** The arrows in the diagram above represent the Select.pPrior pointer.
-** So if this routine is called with p equal to the t3 query, then
-** pPrior will be the t2 query. p->op will be TK_UNION in this case.
-**
-** Notice that because of the way SQLite parses compound SELECTs, the
-** individual selects always group from left to right.
-*/
-static int multiSelect(
- Parse *pParse, /* Parsing context */
- Select *p, /* The right-most of SELECTs to be coded */
- SelectDest *pDest /* What to do with query results */
-){
- int rc = SQLITE_OK; /* Success code from a subroutine */
- Select *pPrior; /* Another SELECT immediately to our left */
- Vdbe *v; /* Generate code to this VDBE */
- SelectDest dest; /* Alternative data destination */
- Select *pDelete = 0; /* Chain of simple selects to delete */
- sqlite3 *db; /* Database connection */
-
- /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
- ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
- */
- assert( p && p->pPrior ); /* Calling function guarantees this much */
- assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
- db = pParse->db;
- pPrior = p->pPrior;
- dest = *pDest;
- if( pPrior->pOrderBy || pPrior->pLimit ){
- sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
- pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op));
- rc = 1;
- goto multi_select_end;
- }
-
- v = sqlite3GetVdbe(pParse);
- assert( v!=0 ); /* The VDBE already created by calling function */
-
- /* Create the destination temporary table if necessary
- */
- if( dest.eDest==SRT_EphemTab ){
- assert( p->pEList );
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr);
- dest.eDest = SRT_Table;
- }
-
- /* Special handling for a compound-select that originates as a VALUES clause.
- */
- if( p->selFlags & SF_MultiValue ){
- rc = multiSelectValues(pParse, p, &dest);
- goto multi_select_end;
- }
-
- /* Make sure all SELECTs in the statement have the same number of elements
- ** in their result sets.
- */
- assert( p->pEList && pPrior->pEList );
- assert( p->pEList->nExpr==pPrior->pEList->nExpr );
-
-#ifndef SQLITE_OMIT_CTE
- if( p->selFlags & SF_Recursive ){
- generateWithRecursiveQuery(pParse, p, &dest);
- }else
-#endif
-
- /* Compound SELECTs that have an ORDER BY clause are handled separately.
- */
- if( p->pOrderBy ){
- return multiSelectOrderBy(pParse, p, pDest);
- }else{
-
-#ifndef SQLITE_OMIT_EXPLAIN
- if( pPrior->pPrior==0 ){
- ExplainQueryPlan((pParse, 1, "COMPOUND QUERY"));
- ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY"));
- }
-#endif
-
- /* Generate code for the left and right SELECT statements.
- */
- switch( p->op ){
- case TK_ALL: {
- int addr = 0;
- int nLimit;
- assert( !pPrior->pLimit );
- pPrior->iLimit = p->iLimit;
- pPrior->iOffset = p->iOffset;
- pPrior->pLimit = p->pLimit;
- rc = sqlite3Select(pParse, pPrior, &dest);
- p->pLimit = 0;
- if( rc ){
- goto multi_select_end;
- }
- p->pPrior = 0;
- p->iLimit = pPrior->iLimit;
- p->iOffset = pPrior->iOffset;
- if( p->iLimit ){
- addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
- VdbeComment((v, "Jump ahead if LIMIT reached"));
- if( p->iOffset ){
- sqlite3VdbeAddOp3(v, OP_OffsetLimit,
- p->iLimit, p->iOffset+1, p->iOffset);
- }
- }
- ExplainQueryPlan((pParse, 1, "UNION ALL"));
- rc = sqlite3Select(pParse, p, &dest);
- testcase( rc!=SQLITE_OK );
- pDelete = p->pPrior;
- p->pPrior = pPrior;
- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- if( pPrior->pLimit
- && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
- && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
- ){
- p->nSelectRow = sqlite3LogEst((u64)nLimit);
- }
- if( addr ){
- sqlite3VdbeJumpHere(v, addr);
- }
- break;
- }
- case TK_EXCEPT:
- case TK_UNION: {
- int unionTab; /* Cursor number of the temp table holding result */
- u8 op = 0; /* One of the SRT_ operations to apply to self */
- int priorOp; /* The SRT_ operation to apply to prior selects */
- Expr *pLimit; /* Saved values of p->nLimit */
- int addr;
- SelectDest uniondest;
-
- testcase( p->op==TK_EXCEPT );
- testcase( p->op==TK_UNION );
- priorOp = SRT_Union;
- if( dest.eDest==priorOp ){
- /* We can reuse a temporary table generated by a SELECT to our
- ** right.
- */
- assert( p->pLimit==0 ); /* Not allowed on leftward elements */
- unionTab = dest.iSDParm;
- }else{
- /* We will need to create our own temporary table to hold the
- ** intermediate results.
- */
- unionTab = pParse->nTab++;
- assert( p->pOrderBy==0 );
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
- assert( p->addrOpenEphm[0] == -1 );
- p->addrOpenEphm[0] = addr;
- findRightmost(p)->selFlags |= SF_UsesEphemeral;
- assert( p->pEList );
- }
-
- /* Code the SELECT statements to our left
- */
- assert( !pPrior->pOrderBy );
- sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
- rc = sqlite3Select(pParse, pPrior, &uniondest);
- if( rc ){
- goto multi_select_end;
- }
-
- /* Code the current SELECT statement
- */
- if( p->op==TK_EXCEPT ){
- op = SRT_Except;
- }else{
- assert( p->op==TK_UNION );
- op = SRT_Union;
- }
- p->pPrior = 0;
- pLimit = p->pLimit;
- p->pLimit = 0;
- uniondest.eDest = op;
- ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
- rc = sqlite3Select(pParse, p, &uniondest);
- testcase( rc!=SQLITE_OK );
- /* Query flattening in sqlite3Select() might refill p->pOrderBy.
- ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
- sqlite3ExprListDelete(db, p->pOrderBy);
- pDelete = p->pPrior;
- p->pPrior = pPrior;
- p->pOrderBy = 0;
- if( p->op==TK_UNION ){
- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- }
- sqlite3ExprDelete(db, p->pLimit);
- p->pLimit = pLimit;
- p->iLimit = 0;
- p->iOffset = 0;
-
- /* Convert the data in the temporary table into whatever form
- ** it is that we currently need.
- */
- assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
- if( dest.eDest!=priorOp ){
- int iCont, iBreak, iStart;
- assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(v);
- iCont = sqlite3VdbeMakeLabel(v);
- computeLimitRegisters(pParse, p, iBreak);
- sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
- iStart = sqlite3VdbeCurrentAddr(v);
- selectInnerLoop(pParse, p, unionTab,
- 0, 0, &dest, iCont, iBreak);
- sqlite3VdbeResolveLabel(v, iCont);
- sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
- sqlite3VdbeResolveLabel(v, iBreak);
- sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
- }
- break;
- }
- default: assert( p->op==TK_INTERSECT ); {
- int tab1, tab2;
- int iCont, iBreak, iStart;
- Expr *pLimit;
- int addr;
- SelectDest intersectdest;
- int r1;
-
- /* INTERSECT is different from the others since it requires
- ** two temporary tables. Hence it has its own case. Begin
- ** by allocating the tables we will need.
- */
- tab1 = pParse->nTab++;
- tab2 = pParse->nTab++;
- assert( p->pOrderBy==0 );
-
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
- assert( p->addrOpenEphm[0] == -1 );
- p->addrOpenEphm[0] = addr;
- findRightmost(p)->selFlags |= SF_UsesEphemeral;
- assert( p->pEList );
-
- /* Code the SELECTs to our left into temporary table "tab1".
- */
- sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
- rc = sqlite3Select(pParse, pPrior, &intersectdest);
- if( rc ){
- goto multi_select_end;
- }
-
- /* Code the current SELECT into temporary table "tab2"
- */
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
- assert( p->addrOpenEphm[1] == -1 );
- p->addrOpenEphm[1] = addr;
- p->pPrior = 0;
- pLimit = p->pLimit;
- p->pLimit = 0;
- intersectdest.iSDParm = tab2;
- ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
- rc = sqlite3Select(pParse, p, &intersectdest);
- testcase( rc!=SQLITE_OK );
- pDelete = p->pPrior;
- p->pPrior = pPrior;
- if( p->nSelectRow>pPrior->nSelectRow ){
- p->nSelectRow = pPrior->nSelectRow;
- }
- sqlite3ExprDelete(db, p->pLimit);
- p->pLimit = pLimit;
-
- /* Generate code to take the intersection of the two temporary
- ** tables.
- */
- assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(v);
- iCont = sqlite3VdbeMakeLabel(v);
- computeLimitRegisters(pParse, p, iBreak);
- sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
- r1 = sqlite3GetTempReg(pParse);
- iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
- sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
- VdbeCoverage(v);
- sqlite3ReleaseTempReg(pParse, r1);
- selectInnerLoop(pParse, p, tab1,
- 0, 0, &dest, iCont, iBreak);
- sqlite3VdbeResolveLabel(v, iCont);
- sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
- sqlite3VdbeResolveLabel(v, iBreak);
- sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
- sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
- break;
- }
- }
-
- #ifndef SQLITE_OMIT_EXPLAIN
- if( p->pNext==0 ){
- ExplainQueryPlanPop(pParse);
- }
- #endif
- }
-
- /* Compute collating sequences used by
- ** temporary tables needed to implement the compound select.
- ** Attach the KeyInfo structure to all temporary tables.
- **
- ** This section is run by the right-most SELECT statement only.
- ** SELECT statements to the left always skip this part. The right-most
- ** SELECT might also skip this part if it has no ORDER BY clause and
- ** no temp tables are required.
- */
- if( p->selFlags & SF_UsesEphemeral ){
- int i; /* Loop counter */
- KeyInfo *pKeyInfo; /* Collating sequence for the result set */
- Select *pLoop; /* For looping through SELECT statements */
- CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
- int nCol; /* Number of columns in result set */
-
- assert( p->pNext==0 );
- nCol = p->pEList->nExpr;
- pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
- if( !pKeyInfo ){
- rc = SQLITE_NOMEM_BKPT;
- goto multi_select_end;
- }
- for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
- *apColl = multiSelectCollSeq(pParse, p, i);
- if( 0==*apColl ){
- *apColl = db->pDfltColl;
- }
- }
-
- for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
- for(i=0; i<2; i++){
- int addr = pLoop->addrOpenEphm[i];
- if( addr<0 ){
- /* If [0] is unused then [1] is also unused. So we can
- ** always safely abort as soon as the first unused slot is found */
- assert( pLoop->addrOpenEphm[1]<0 );
- break;
- }
- sqlite3VdbeChangeP2(v, addr, nCol);
- sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo),
- P4_KEYINFO);
- pLoop->addrOpenEphm[i] = -1;
- }
- }
- sqlite3KeyInfoUnref(pKeyInfo);
- }
-
-multi_select_end:
- pDest->iSdst = dest.iSdst;
- pDest->nSdst = dest.nSdst;
- sqlite3SelectDelete(db, pDelete);
- return rc;
-}
-#endif /* SQLITE_OMIT_COMPOUND_SELECT */
-
-/*
-** Error message for when two or more terms of a compound select have different
-** size result sets.
-*/
-void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
- if( p->selFlags & SF_Values ){
- sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
- }else{
- sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
- " do not have the same number of result columns", selectOpName(p->op));
- }
-}
-
-/*
-** Code an output subroutine for a coroutine implementation of a
-** SELECT statment.
-**
-** The data to be output is contained in pIn->iSdst. There are
-** pIn->nSdst columns to be output. pDest is where the output should
-** be sent.
-**
-** regReturn is the number of the register holding the subroutine
-** return address.
-**
-** If regPrev>0 then it is the first register in a vector that
-** records the previous output. mem[regPrev] is a flag that is false
-** if there has been no previous output. If regPrev>0 then code is
-** generated to suppress duplicates. pKeyInfo is used for comparing
-** keys.
-**
-** If the LIMIT found in p->iLimit is reached, jump immediately to
-** iBreak.
-*/
-static int generateOutputSubroutine(
- Parse *pParse, /* Parsing context */
- Select *p, /* The SELECT statement */
- SelectDest *pIn, /* Coroutine supplying data */
- SelectDest *pDest, /* Where to send the data */
- int regReturn, /* The return address register */
- int regPrev, /* Previous result register. No uniqueness if 0 */
- KeyInfo *pKeyInfo, /* For comparing with previous entry */
- int iBreak /* Jump here if we hit the LIMIT */
-){
- Vdbe *v = pParse->pVdbe;
- int iContinue;
- int addr;
-
- addr = sqlite3VdbeCurrentAddr(v);
- iContinue = sqlite3VdbeMakeLabel(v);
-
- /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
- */
- if( regPrev ){
- int addr1, addr2;
- addr1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v);
- addr2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
- (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
- sqlite3VdbeAddOp3(v, OP_Jump, addr2+2, iContinue, addr2+2); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addr1);
- sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
- }
- if( pParse->db->mallocFailed ) return 0;
-
- /* Suppress the first OFFSET entries if there is an OFFSET clause
- */
- codeOffset(v, p->iOffset, iContinue);
-
- assert( pDest->eDest!=SRT_Exists );
- assert( pDest->eDest!=SRT_Table );
- switch( pDest->eDest ){
- /* Store the result as data using a unique key.
- */
- case SRT_EphemTab: {
- int r1 = sqlite3GetTempReg(pParse);
- int r2 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
- sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
- sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
- sqlite3ReleaseTempReg(pParse, r2);
- sqlite3ReleaseTempReg(pParse, r1);
- break;
- }
-
-#ifndef SQLITE_OMIT_SUBQUERY
- /* If we are creating a set for an "expr IN (SELECT ...)".
- */
- case SRT_Set: {
- int r1;
- testcase( pIn->nSdst>1 );
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
- r1, pDest->zAffSdst, pIn->nSdst);
- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
- pIn->iSdst, pIn->nSdst);
- sqlite3ReleaseTempReg(pParse, r1);
- break;
- }
-
- /* If this is a scalar select that is part of an expression, then
- ** store the results in the appropriate memory cell and break out
- ** of the scan loop.
- */
- case SRT_Mem: {
- assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 );
- sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
- /* The LIMIT clause will jump out of the loop for us */
- break;
- }
-#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
-
- /* The results are stored in a sequence of registers
- ** starting at pDest->iSdst. Then the co-routine yields.
- */
- case SRT_Coroutine: {
- if( pDest->iSdst==0 ){
- pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst);
- pDest->nSdst = pIn->nSdst;
- }
- sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst);
- sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
- break;
- }
-
- /* If none of the above, then the result destination must be
- ** SRT_Output. This routine is never called with any other
- ** destination other than the ones handled above or SRT_Output.
- **
- ** For SRT_Output, results are stored in a sequence of registers.
- ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
- ** return the next row of result.
- */
- default: {
- assert( pDest->eDest==SRT_Output );
- sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst);
- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
- break;
- }
- }
-
- /* Jump to the end of the loop if the LIMIT is reached.
- */
- if( p->iLimit ){
- sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
- }
-
- /* Generate the subroutine return
- */
- sqlite3VdbeResolveLabel(v, iContinue);
- sqlite3VdbeAddOp1(v, OP_Return, regReturn);
-
- return addr;
-}
-
-/*
-** Alternative compound select code generator for cases when there
-** is an ORDER BY clause.
-**
-** We assume a query of the following form:
-**
-** <selectA> <operator> <selectB> ORDER BY <orderbylist>
-**
-** <operator> is one of UNION ALL, UNION, EXCEPT, or INTERSECT. The idea
-** is to code both <selectA> and <selectB> with the ORDER BY clause as
-** co-routines. Then run the co-routines in parallel and merge the results
-** into the output. In addition to the two coroutines (called selectA and
-** selectB) there are 7 subroutines:
-**
-** outA: Move the output of the selectA coroutine into the output
-** of the compound query.
-**
-** outB: Move the output of the selectB coroutine into the output
-** of the compound query. (Only generated for UNION and
-** UNION ALL. EXCEPT and INSERTSECT never output a row that
-** appears only in B.)
-**
-** AltB: Called when there is data from both coroutines and A<B.
-**
-** AeqB: Called when there is data from both coroutines and A==B.
-**
-** AgtB: Called when there is data from both coroutines and A>B.
-**
-** EofA: Called when data is exhausted from selectA.
-**
-** EofB: Called when data is exhausted from selectB.
-**
-** The implementation of the latter five subroutines depend on which
-** <operator> is used:
-**
-**
-** UNION ALL UNION EXCEPT INTERSECT
-** ------------- ----------------- -------------- -----------------
-** AltB: outA, nextA outA, nextA outA, nextA nextA
-**
-** AeqB: outA, nextA nextA nextA outA, nextA
-**
-** AgtB: outB, nextB outB, nextB nextB nextB
-**
-** EofA: outB, nextB outB, nextB halt halt
-**
-** EofB: outA, nextA outA, nextA outA, nextA halt
-**
-** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA
-** causes an immediate jump to EofA and an EOF on B following nextB causes
-** an immediate jump to EofB. Within EofA and EofB, and EOF on entry or
-** following nextX causes a jump to the end of the select processing.
-**
-** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled
-** within the output subroutine. The regPrev register set holds the previously
-** output value. A comparison is made against this value and the output
-** is skipped if the next results would be the same as the previous.
-**
-** The implementation plan is to implement the two coroutines and seven
-** subroutines first, then put the control logic at the bottom. Like this:
-**
-** goto Init
-** coA: coroutine for left query (A)
-** coB: coroutine for right query (B)
-** outA: output one row of A
-** outB: output one row of B (UNION and UNION ALL only)
-** EofA: ...
-** EofB: ...
-** AltB: ...
-** AeqB: ...
-** AgtB: ...
-** Init: initialize coroutine registers
-** yield coA
-** if eof(A) goto EofA
-** yield coB
-** if eof(B) goto EofB
-** Cmpr: Compare A, B
-** Jump AltB, AeqB, AgtB
-** End: ...
-**
-** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not
-** actually called using Gosub and they do not Return. EofA and EofB loop
-** until all data is exhausted then jump to the "end" labe. AltB, AeqB,
-** and AgtB jump to either L2 or to one of EofA or EofB.
-*/
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
-static int multiSelectOrderBy(
- Parse *pParse, /* Parsing context */
- Select *p, /* The right-most of SELECTs to be coded */
- SelectDest *pDest /* What to do with query results */
-){
- int i, j; /* Loop counters */
- Select *pPrior; /* Another SELECT immediately to our left */
- Vdbe *v; /* Generate code to this VDBE */
- SelectDest destA; /* Destination for coroutine A */
- SelectDest destB; /* Destination for coroutine B */
- int regAddrA; /* Address register for select-A coroutine */
- int regAddrB; /* Address register for select-B coroutine */
- int addrSelectA; /* Address of the select-A coroutine */
- int addrSelectB; /* Address of the select-B coroutine */
- int regOutA; /* Address register for the output-A subroutine */
- int regOutB; /* Address register for the output-B subroutine */
- int addrOutA; /* Address of the output-A subroutine */
- int addrOutB = 0; /* Address of the output-B subroutine */
- int addrEofA; /* Address of the select-A-exhausted subroutine */
- int addrEofA_noB; /* Alternate addrEofA if B is uninitialized */
- int addrEofB; /* Address of the select-B-exhausted subroutine */
- int addrAltB; /* Address of the A<B subroutine */
- int addrAeqB; /* Address of the A==B subroutine */
- int addrAgtB; /* Address of the A>B subroutine */
- int regLimitA; /* Limit register for select-A */
- int regLimitB; /* Limit register for select-A */
- int regPrev; /* A range of registers to hold previous output */
- int savedLimit; /* Saved value of p->iLimit */
- int savedOffset; /* Saved value of p->iOffset */
- int labelCmpr; /* Label for the start of the merge algorithm */
- int labelEnd; /* Label for the end of the overall SELECT stmt */
- int addr1; /* Jump instructions that get retargetted */
- int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
- KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
- KeyInfo *pKeyMerge; /* Comparison information for merging rows */
- sqlite3 *db; /* Database connection */
- ExprList *pOrderBy; /* The ORDER BY clause */
- int nOrderBy; /* Number of terms in the ORDER BY clause */
- int *aPermute; /* Mapping from ORDER BY terms to result set columns */
-
- assert( p->pOrderBy!=0 );
- assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */
- db = pParse->db;
- v = pParse->pVdbe;
- assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */
- labelEnd = sqlite3VdbeMakeLabel(v);
- labelCmpr = sqlite3VdbeMakeLabel(v);
-
-
- /* Patch up the ORDER BY clause
- */
- op = p->op;
- pPrior = p->pPrior;
- assert( pPrior->pOrderBy==0 );
- pOrderBy = p->pOrderBy;
- assert( pOrderBy );
- nOrderBy = pOrderBy->nExpr;
-
- /* For operators other than UNION ALL we have to make sure that
- ** the ORDER BY clause covers every term of the result set. Add
- ** terms to the ORDER BY clause as necessary.
- */
- if( op!=TK_ALL ){
- for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
- struct ExprList_item *pItem;
- for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
- assert( pItem->u.x.iOrderByCol>0 );
- if( pItem->u.x.iOrderByCol==i ) break;
- }
- if( j==nOrderBy ){
- Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
- if( pNew==0 ) return SQLITE_NOMEM_BKPT;
- pNew->flags |= EP_IntValue;
- pNew->u.iValue = i;
- p->pOrderBy = pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
- if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i;
- }
- }
- }
-
- /* Compute the comparison permutation and keyinfo that is used with
- ** the permutation used to determine if the next
- ** row of results comes from selectA or selectB. Also add explicit
- ** collations to the ORDER BY clause terms so that when the subqueries
- ** to the right and the left are evaluated, they use the correct
- ** collation.
- */
- aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1));
- if( aPermute ){
- struct ExprList_item *pItem;
- aPermute[0] = nOrderBy;
- for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
- assert( pItem->u.x.iOrderByCol>0 );
- assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
- aPermute[i] = pItem->u.x.iOrderByCol - 1;
- }
- pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
- }else{
- pKeyMerge = 0;
- }
-
- /* Reattach the ORDER BY clause to the query.
- */
- p->pOrderBy = pOrderBy;
- pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);
-
- /* Allocate a range of temporary registers and the KeyInfo needed
- ** for the logic that removes duplicate result rows when the
- ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
- */
- if( op==TK_ALL ){
- regPrev = 0;
- }else{
- int nExpr = p->pEList->nExpr;
- assert( nOrderBy>=nExpr || db->mallocFailed );
- regPrev = pParse->nMem+1;
- pParse->nMem += nExpr+1;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
- pKeyDup = sqlite3KeyInfoAlloc(db, nExpr, 1);
- if( pKeyDup ){
- assert( sqlite3KeyInfoIsWriteable(pKeyDup) );
- for(i=0; i<nExpr; i++){
- pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
- pKeyDup->aSortOrder[i] = 0;
- }
- }
- }
-
- /* Separate the left and the right query from one another
- */
- p->pPrior = 0;
- pPrior->pNext = 0;
- sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
- if( pPrior->pPrior==0 ){
- sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
- }
-
- /* Compute the limit registers */
- computeLimitRegisters(pParse, p, labelEnd);
- if( p->iLimit && op==TK_ALL ){
- regLimitA = ++pParse->nMem;
- regLimitB = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit,
- regLimitA);
- sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB);
- }else{
- regLimitA = regLimitB = 0;
- }
- sqlite3ExprDelete(db, p->pLimit);
- p->pLimit = 0;
-
- regAddrA = ++pParse->nMem;
- regAddrB = ++pParse->nMem;
- regOutA = ++pParse->nMem;
- regOutB = ++pParse->nMem;
- sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
- sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
-
- ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op)));
-
- /* Generate a coroutine to evaluate the SELECT statement to the
- ** left of the compound operator - the "A" select.
- */
- addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
- addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
- VdbeComment((v, "left SELECT"));
- pPrior->iLimit = regLimitA;
- ExplainQueryPlan((pParse, 1, "LEFT"));
- sqlite3Select(pParse, pPrior, &destA);
- sqlite3VdbeEndCoroutine(v, regAddrA);
- sqlite3VdbeJumpHere(v, addr1);
-
- /* Generate a coroutine to evaluate the SELECT statement on
- ** the right - the "B" select
- */
- addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
- addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
- VdbeComment((v, "right SELECT"));
- savedLimit = p->iLimit;
- savedOffset = p->iOffset;
- p->iLimit = regLimitB;
- p->iOffset = 0;
- ExplainQueryPlan((pParse, 1, "RIGHT"));
- sqlite3Select(pParse, p, &destB);
- p->iLimit = savedLimit;
- p->iOffset = savedOffset;
- sqlite3VdbeEndCoroutine(v, regAddrB);
-
- /* Generate a subroutine that outputs the current row of the A
- ** select as the next output row of the compound select.
- */
- VdbeNoopComment((v, "Output routine for A"));
- addrOutA = generateOutputSubroutine(pParse,
- p, &destA, pDest, regOutA,
- regPrev, pKeyDup, labelEnd);
-
- /* Generate a subroutine that outputs the current row of the B
- ** select as the next output row of the compound select.
- */
- if( op==TK_ALL || op==TK_UNION ){
- VdbeNoopComment((v, "Output routine for B"));
- addrOutB = generateOutputSubroutine(pParse,
- p, &destB, pDest, regOutB,
- regPrev, pKeyDup, labelEnd);
- }
- sqlite3KeyInfoUnref(pKeyDup);
-
- /* Generate a subroutine to run when the results from select A
- ** are exhausted and only data in select B remains.
- */
- if( op==TK_EXCEPT || op==TK_INTERSECT ){
- addrEofA_noB = addrEofA = labelEnd;
- }else{
- VdbeNoopComment((v, "eof-A subroutine"));
- addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
- addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
- VdbeCoverage(v);
- sqlite3VdbeGoto(v, addrEofA);
- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- }
-
- /* Generate a subroutine to run when the results from select B
- ** are exhausted and only data in select A remains.
- */
- if( op==TK_INTERSECT ){
- addrEofB = addrEofA;
- if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
- }else{
- VdbeNoopComment((v, "eof-B subroutine"));
- addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v);
- sqlite3VdbeGoto(v, addrEofB);
- }
-
- /* Generate code to handle the case of A<B
- */
- VdbeNoopComment((v, "A-lt-B subroutine"));
- addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
- sqlite3VdbeGoto(v, labelCmpr);
-
- /* Generate code to handle the case of A==B
- */
- if( op==TK_ALL ){
- addrAeqB = addrAltB;
- }else if( op==TK_INTERSECT ){
- addrAeqB = addrAltB;
- addrAltB++;
- }else{
- VdbeNoopComment((v, "A-eq-B subroutine"));
- addrAeqB =
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
- sqlite3VdbeGoto(v, labelCmpr);
- }
-
- /* Generate code to handle the case of A>B
- */
- VdbeNoopComment((v, "A-gt-B subroutine"));
- addrAgtB = sqlite3VdbeCurrentAddr(v);
- if( op==TK_ALL || op==TK_UNION ){
- sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
- }
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
- sqlite3VdbeGoto(v, labelCmpr);
-
- /* This code runs once to initialize everything.
- */
- sqlite3VdbeJumpHere(v, addr1);
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
-
- /* Implement the main merge loop
- */
- sqlite3VdbeResolveLabel(v, labelCmpr);
- sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
- sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
- (char*)pKeyMerge, P4_KEYINFO);
- sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
- sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v);
-
- /* Jump to the this point in order to terminate the query.
- */
- sqlite3VdbeResolveLabel(v, labelEnd);
-
- /* Reassembly the compound query so that it will be freed correctly
- ** by the calling function */
- if( p->pPrior ){
- sqlite3SelectDelete(db, p->pPrior);
- }
- p->pPrior = pPrior;
- pPrior->pNext = p;
-
- /*** TBD: Insert subroutine calls to close cursors on incomplete
- **** subqueries ****/
- ExplainQueryPlanPop(pParse);
- return pParse->nErr!=0;
-}
-#endif
-
-#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
-
-/* An instance of the SubstContext object describes an substitution edit
-** to be performed on a parse tree.
-**
-** All references to columns in table iTable are to be replaced by corresponding
-** expressions in pEList.
-*/
-typedef struct SubstContext {
- Parse *pParse; /* The parsing context */
- int iTable; /* Replace references to this table */
- int iNewTable; /* New table number */
- int isLeftJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */
- ExprList *pEList; /* Replacement expressions */
-} SubstContext;
-
-/* Forward Declarations */
-static void substExprList(SubstContext*, ExprList*);
-static void substSelect(SubstContext*, Select*, int);
-
-/*
-** Scan through the expression pExpr. Replace every reference to
-** a column in table number iTable with a copy of the iColumn-th
-** entry in pEList. (But leave references to the ROWID column
-** unchanged.)
-**
-** This routine is part of the flattening procedure. A subquery
-** whose result set is defined by pEList appears as entry in the
-** FROM clause of a SELECT such that the VDBE cursor assigned to that
-** FORM clause entry is iTable. This routine makes the necessary
-** changes to pExpr so that it refers directly to the source table
-** of the subquery rather the result set of the subquery.
-*/
-static Expr *substExpr(
- SubstContext *pSubst, /* Description of the substitution */
- Expr *pExpr /* Expr in which substitution occurs */
-){
- if( pExpr==0 ) return 0;
- if( ExprHasProperty(pExpr, EP_FromJoin)
- && pExpr->iRightJoinTable==pSubst->iTable
- ){
- pExpr->iRightJoinTable = pSubst->iNewTable;
- }
- if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
- if( pExpr->iColumn<0 ){
- pExpr->op = TK_NULL;
- }else{
- Expr *pNew;
- Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
- Expr ifNullRow;
- assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- if( sqlite3ExprIsVector(pCopy) ){
- sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
- }else{
- sqlite3 *db = pSubst->pParse->db;
- if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
- memset(&ifNullRow, 0, sizeof(ifNullRow));
- ifNullRow.op = TK_IF_NULL_ROW;
- ifNullRow.pLeft = pCopy;
- ifNullRow.iTable = pSubst->iNewTable;
- pCopy = &ifNullRow;
- }
- pNew = sqlite3ExprDup(db, pCopy, 0);
- if( pNew && pSubst->isLeftJoin ){
- ExprSetProperty(pNew, EP_CanBeNull);
- }
- if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
- pNew->iRightJoinTable = pExpr->iRightJoinTable;
- ExprSetProperty(pNew, EP_FromJoin);
- }
- sqlite3ExprDelete(db, pExpr);
- pExpr = pNew;
- }
- }
- }else{
- if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
- pExpr->iTable = pSubst->iNewTable;
- }
- pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
- pExpr->pRight = substExpr(pSubst, pExpr->pRight);
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- substSelect(pSubst, pExpr->x.pSelect, 1);
- }else{
- substExprList(pSubst, pExpr->x.pList);
- }
- }
- return pExpr;
-}
-static void substExprList(
- SubstContext *pSubst, /* Description of the substitution */
- ExprList *pList /* List to scan and in which to make substitutes */
-){
- int i;
- if( pList==0 ) return;
- for(i=0; i<pList->nExpr; i++){
- pList->a[i].pExpr = substExpr(pSubst, pList->a[i].pExpr);
- }
-}
-static void substSelect(
- SubstContext *pSubst, /* Description of the substitution */
- Select *p, /* SELECT statement in which to make substitutions */
- int doPrior /* Do substitutes on p->pPrior too */
-){
- SrcList *pSrc;
- struct SrcList_item *pItem;
- int i;
- if( !p ) return;
- do{
- substExprList(pSubst, p->pEList);
- substExprList(pSubst, p->pGroupBy);
- substExprList(pSubst, p->pOrderBy);
- p->pHaving = substExpr(pSubst, p->pHaving);
- p->pWhere = substExpr(pSubst, p->pWhere);
- pSrc = p->pSrc;
- assert( pSrc!=0 );
- for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- substSelect(pSubst, pItem->pSelect, 1);
- if( pItem->fg.isTabFunc ){
- substExprList(pSubst, pItem->u1.pFuncArg);
- }
- }
- }while( doPrior && (p = p->pPrior)!=0 );
-}
-#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
-
-#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
-/*
-** This routine attempts to flatten subqueries as a performance optimization.
-** This routine returns 1 if it makes changes and 0 if no flattening occurs.
-**
-** To understand the concept of flattening, consider the following
-** query:
-**
-** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5
-**
-** The default way of implementing this query is to execute the
-** subquery first and store the results in a temporary table, then
-** run the outer query on that temporary table. This requires two
-** passes over the data. Furthermore, because the temporary table
-** has no indices, the WHERE clause on the outer query cannot be
-** optimized.
-**
-** This routine attempts to rewrite queries such as the above into
-** a single flat select, like this:
-**
-** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
-**
-** The code generated for this simplification gives the same result
-** but only has to scan the data once. And because indices might
-** exist on the table t1, a complete scan of the data might be
-** avoided.
-**
-** Flattening is subject to the following constraints:
-**
-** (**) We no longer attempt to flatten aggregate subqueries. Was:
-** The subquery and the outer query cannot both be aggregates.
-**
-** (**) We no longer attempt to flatten aggregate subqueries. Was:
-** (2) If the subquery is an aggregate then
-** (2a) the outer query must not be a join and
-** (2b) the outer query must not use subqueries
-** other than the one FROM-clause subquery that is a candidate
-** for flattening. (This is due to ticket [2f7170d73bf9abf80]
-** from 2015-02-09.)
-**
-** (3) If the subquery is the right operand of a LEFT JOIN then
-** (3a) the subquery may not be a join and
-** (3b) the FROM clause of the subquery may not contain a virtual
-** table and
-** (3c) the outer query may not be an aggregate.
-**
-** (4) The subquery can not be DISTINCT.
-**
-** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
-** sub-queries that were excluded from this optimization. Restriction
-** (4) has since been expanded to exclude all DISTINCT subqueries.
-**
-** (**) We no longer attempt to flatten aggregate subqueries. Was:
-** If the subquery is aggregate, the outer query may not be DISTINCT.
-**
-** (7) The subquery must have a FROM clause. TODO: For subqueries without
-** A FROM clause, consider adding a FROM clause with the special
-** table sqlite_once that consists of a single row containing a
-** single NULL.
-**
-** (8) If the subquery uses LIMIT then the outer query may not be a join.
-**
-** (9) If the subquery uses LIMIT then the outer query may not be aggregate.
-**
-** (**) Restriction (10) was removed from the code on 2005-02-05 but we
-** accidently carried the comment forward until 2014-09-15. Original
-** constraint: "If the subquery is aggregate then the outer query
-** may not use LIMIT."
-**
-** (11) The subquery and the outer query may not both have ORDER BY clauses.
-**
-** (**) Not implemented. Subsumed into restriction (3). Was previously
-** a separate restriction deriving from ticket #350.
-**
-** (13) The subquery and outer query may not both use LIMIT.
-**
-** (14) The subquery may not use OFFSET.
-**
-** (15) If the outer query is part of a compound select, then the
-** subquery may not use LIMIT.
-** (See ticket #2339 and ticket [02a8e81d44]).
-**
-** (16) If the outer query is aggregate, then the subquery may not
-** use ORDER BY. (Ticket #2942) This used to not matter
-** until we introduced the group_concat() function.
-**
-** (17) If the subquery is a compound select, then
-** (17a) all compound operators must be a UNION ALL, and
-** (17b) no terms within the subquery compound may be aggregate
-** or DISTINCT, and
-** (17c) every term within the subquery compound must have a FROM clause
-** (17d) the outer query may not be
-** (17d1) aggregate, or
-** (17d2) DISTINCT, or
-** (17d3) a join.
-**
-** The parent and sub-query may contain WHERE clauses. Subject to
-** rules (11), (13) and (14), they may also contain ORDER BY,
-** LIMIT and OFFSET clauses. The subquery cannot use any compound
-** operator other than UNION ALL because all the other compound
-** operators have an implied DISTINCT which is disallowed by
-** restriction (4).
-**
-** Also, each component of the sub-query must return the same number
-** of result columns. This is actually a requirement for any compound
-** SELECT statement, but all the code here does is make sure that no
-** such (illegal) sub-query is flattened. The caller will detect the
-** syntax error and return a detailed message.
-**
-** (18) If the sub-query is a compound select, then all terms of the
-** ORDER BY clause of the parent must be simple references to
-** columns of the sub-query.
-**
-** (19) If the subquery uses LIMIT then the outer query may not
-** have a WHERE clause.
-**
-** (20) If the sub-query is a compound select, then it must not use
-** an ORDER BY clause. Ticket #3773. We could relax this constraint
-** somewhat by saying that the terms of the ORDER BY clause must
-** appear as unmodified result columns in the outer query. But we
-** have other optimizations in mind to deal with that case.
-**
-** (21) If the subquery uses LIMIT then the outer query may not be
-** DISTINCT. (See ticket [752e1646fc]).
-**
-** (22) The subquery may not be a recursive CTE.
-**
-** (**) Subsumed into restriction (17d3). Was: If the outer query is
-** a recursive CTE, then the sub-query may not be a compound query.
-** This restriction is because transforming the
-** parent to a compound query confuses the code that handles
-** recursive queries in multiSelect().
-**
-** (**) We no longer attempt to flatten aggregate subqueries. Was:
-** The subquery may not be an aggregate that uses the built-in min() or
-** or max() functions. (Without this restriction, a query like:
-** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
-** return the value X for which Y was maximal.)
-**
-**
-** In this routine, the "p" parameter is a pointer to the outer query.
-** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
-** uses aggregates.
-**
-** If flattening is not attempted, this routine is a no-op and returns 0.
-** If flattening is attempted this routine returns 1.
-**
-** All of the expression analysis must occur on both the outer query and
-** the subquery before this routine runs.
-*/
-static int flattenSubquery(
- Parse *pParse, /* Parsing context */
- Select *p, /* The parent or outer SELECT statement */
- int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
- int isAgg /* True if outer SELECT uses aggregate functions */
-){
- const char *zSavedAuthContext = pParse->zAuthContext;
- Select *pParent; /* Current UNION ALL term of the other query */
- Select *pSub; /* The inner query or "subquery" */
- Select *pSub1; /* Pointer to the rightmost select in sub-query */
- SrcList *pSrc; /* The FROM clause of the outer query */
- SrcList *pSubSrc; /* The FROM clause of the subquery */
- int iParent; /* VDBE cursor number of the pSub result set temp table */
- int iNewParent = -1;/* Replacement table for iParent */
- int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
- int i; /* Loop counter */
- Expr *pWhere; /* The WHERE clause */
- struct SrcList_item *pSubitem; /* The subquery */
- sqlite3 *db = pParse->db;
-
- /* Check to see if flattening is permitted. Return 0 if not.
- */
- assert( p!=0 );
- assert( p->pPrior==0 );
- if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
- pSrc = p->pSrc;
- assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
- pSubitem = &pSrc->a[iFrom];
- iParent = pSubitem->iCursor;
- pSub = pSubitem->pSelect;
- assert( pSub!=0 );
-
- pSubSrc = pSub->pSrc;
- assert( pSubSrc );
- /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
- ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
- ** because they could be computed at compile-time. But when LIMIT and OFFSET
- ** became arbitrary expressions, we were forced to add restrictions (13)
- ** and (14). */
- if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
- if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */
- if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
- return 0; /* Restriction (15) */
- }
- if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
- if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */
- if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
- return 0; /* Restrictions (8)(9) */
- }
- if( p->pOrderBy && pSub->pOrderBy ){
- return 0; /* Restriction (11) */
- }
- if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
- if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
- if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
- return 0; /* Restriction (21) */
- }
- if( pSub->selFlags & (SF_Recursive) ){
- return 0; /* Restrictions (22) */
- }
-
- /*
- ** If the subquery is the right operand of a LEFT JOIN, then the
- ** subquery may not be a join itself (3a). Example of why this is not
- ** allowed:
- **
- ** t1 LEFT OUTER JOIN (t2 JOIN t3)
- **
- ** If we flatten the above, we would get
- **
- ** (t1 LEFT OUTER JOIN t2) JOIN t3
- **
- ** which is not at all the same thing.
- **
- ** If the subquery is the right operand of a LEFT JOIN, then the outer
- ** query cannot be an aggregate. (3c) This is an artifact of the way
- ** aggregates are processed - there is no mechanism to determine if
- ** the LEFT JOIN table should be all-NULL.
- **
- ** See also tickets #306, #350, and #3300.
- */
- if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
- isLeftJoin = 1;
- if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
- /* (3a) (3c) (3b) */
- return 0;
- }
- }
-#ifdef SQLITE_EXTRA_IFNULLROW
- else if( iFrom>0 && !isAgg ){
- /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
- ** every reference to any result column from subquery in a join, even
- ** though they are not necessary. This will stress-test the OP_IfNullRow
- ** opcode. */
- isLeftJoin = -1;
- }
-#endif
-
- /* Restriction (17): If the sub-query is a compound SELECT, then it must
- ** use only the UNION ALL operator. And none of the simple select queries
- ** that make up the compound SELECT are allowed to be aggregate or distinct
- ** queries.
- */
- if( pSub->pPrior ){
- if( pSub->pOrderBy ){
- return 0; /* Restriction (20) */
- }
- if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
- return 0; /* (17d1), (17d2), or (17d3) */
- }
- for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
- testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
- testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
- assert( pSub->pSrc!=0 );
- assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
- if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
- || (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
- || pSub1->pSrc->nSrc<1 /* (17c) */
- ){
- return 0;
- }
- testcase( pSub1->pSrc->nSrc>1 );
- }
-
- /* Restriction (18). */
- if( p->pOrderBy ){
- int ii;
- for(ii=0; ii<p->pOrderBy->nExpr; ii++){
- if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
- }
- }
- }
-
- /* Ex-restriction (23):
- ** The only way that the recursive part of a CTE can contain a compound
- ** subquery is for the subquery to be one term of a join. But if the
- ** subquery is a join, then the flattening has already been stopped by
- ** restriction (17d3)
- */
- assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
-
- /***** If we reach this point, flattening is permitted. *****/
- SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n",
- pSub->zSelName, pSub, iFrom));
-
- /* Authorize the subquery */
- pParse->zAuthContext = pSubitem->zName;
- TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
- testcase( i==SQLITE_DENY );
- pParse->zAuthContext = zSavedAuthContext;
-
- /* If the sub-query is a compound SELECT statement, then (by restrictions
- ** 17 and 18 above) it must be a UNION ALL and the parent query must
- ** be of the form:
- **
- ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
- **
- ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
- ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
- ** OFFSET clauses and joins them to the left-hand-side of the original
- ** using UNION ALL operators. In this case N is the number of simple
- ** select statements in the compound sub-query.
- **
- ** Example:
- **
- ** SELECT a+1 FROM (
- ** SELECT x FROM tab
- ** UNION ALL
- ** SELECT y FROM tab
- ** UNION ALL
- ** SELECT abs(z*2) FROM tab2
- ** ) WHERE a!=5 ORDER BY 1
- **
- ** Transformed into:
- **
- ** SELECT x+1 FROM tab WHERE x+1!=5
- ** UNION ALL
- ** SELECT y+1 FROM tab WHERE y+1!=5
- ** UNION ALL
- ** SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5
- ** ORDER BY 1
- **
- ** We call this the "compound-subquery flattening".
- */
- for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){
- Select *pNew;
- ExprList *pOrderBy = p->pOrderBy;
- Expr *pLimit = p->pLimit;
- Select *pPrior = p->pPrior;
- p->pOrderBy = 0;
- p->pSrc = 0;
- p->pPrior = 0;
- p->pLimit = 0;
- pNew = sqlite3SelectDup(db, p, 0);
- sqlite3SelectSetName(pNew, pSub->zSelName);
- p->pLimit = pLimit;
- p->pOrderBy = pOrderBy;
- p->pSrc = pSrc;
- p->op = TK_ALL;
- if( pNew==0 ){
- p->pPrior = pPrior;
- }else{
- pNew->pPrior = pPrior;
- if( pPrior ) pPrior->pNext = pNew;
- pNew->pNext = p;
- p->pPrior = pNew;
- SELECTTRACE(2,pParse,p,("compound-subquery flattener"
- " creates %s.%p as peer\n",pNew->zSelName, pNew));
- }
- if( db->mallocFailed ) return 1;
- }
-
- /* Begin flattening the iFrom-th entry of the FROM clause
- ** in the outer query.
- */
- pSub = pSub1 = pSubitem->pSelect;
-
- /* Delete the transient table structure associated with the
- ** subquery
- */
- sqlite3DbFree(db, pSubitem->zDatabase);
- sqlite3DbFree(db, pSubitem->zName);
- sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
- pSubitem->zName = 0;
- pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
-
- /* Defer deleting the Table object associated with the
- ** subquery until code generation is
- ** complete, since there may still exist Expr.pTab entries that
- ** refer to the subquery even after flattening. Ticket #3346.
- **
- ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
- */
- if( ALWAYS(pSubitem->pTab!=0) ){
- Table *pTabToDel = pSubitem->pTab;
- if( pTabToDel->nTabRef==1 ){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
- pTabToDel->pNextZombie = pToplevel->pZombieTab;
- pToplevel->pZombieTab = pTabToDel;
- }else{
- pTabToDel->nTabRef--;
- }
- pSubitem->pTab = 0;
- }
-
- /* The following loop runs once for each term in a compound-subquery
- ** flattening (as described above). If we are doing a different kind
- ** of flattening - a flattening other than a compound-subquery flattening -
- ** then this loop only runs once.
- **
- ** This loop moves all of the FROM elements of the subquery into the
- ** the FROM clause of the outer query. Before doing this, remember
- ** the cursor number for the original outer query FROM element in
- ** iParent. The iParent cursor will never be used. Subsequent code
- ** will scan expressions looking for iParent references and replace
- ** those references with expressions that resolve to the subquery FROM
- ** elements we are now copying in.
- */
- for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
- int nSubSrc;
- u8 jointype = 0;
- pSubSrc = pSub->pSrc; /* FROM clause of subquery */
- nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
- pSrc = pParent->pSrc; /* FROM clause of the outer query */
-
- if( pSrc ){
- assert( pParent==p ); /* First time through the loop */
- jointype = pSubitem->fg.jointype;
- }else{
- assert( pParent!=p ); /* 2nd and subsequent times through the loop */
- pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pSrc==0 ){
- assert( db->mallocFailed );
- break;
- }
- }
-
- /* The subquery uses a single slot of the FROM clause of the outer
- ** query. If the subquery has more than one element in its FROM clause,
- ** then expand the outer query to make space for it to hold all elements
- ** of the subquery.
- **
- ** Example:
- **
- ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
- **
- ** The outer query has 3 slots in its FROM clause. One slot of the
- ** outer query (the middle slot) is used by the subquery. The next
- ** block of code will expand the outer query FROM clause to 4 slots.
- ** The middle slot is expanded to two slots in order to make space
- ** for the two elements in the FROM clause of the subquery.
- */
- if( nSubSrc>1 ){
- pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
- if( db->mallocFailed ){
- break;
- }
- }
-
- /* Transfer the FROM clause terms from the subquery into the
- ** outer query.
- */
- for(i=0; i<nSubSrc; i++){
- sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
- assert( pSrc->a[i+iFrom].fg.isTabFunc==0 );
- pSrc->a[i+iFrom] = pSubSrc->a[i];
- iNewParent = pSubSrc->a[i].iCursor;
- memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
- }
- pSrc->a[iFrom].fg.jointype = jointype;
-
- /* Now begin substituting subquery result set expressions for
- ** references to the iParent in the outer query.
- **
- ** Example:
- **
- ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
- ** \ \_____________ subquery __________/ /
- ** \_____________________ outer query ______________________________/
- **
- ** We look at every expression in the outer query and every place we see
- ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
- */
- if( pSub->pOrderBy ){
- /* At this point, any non-zero iOrderByCol values indicate that the
- ** ORDER BY column expression is identical to the iOrderByCol'th
- ** expression returned by SELECT statement pSub. Since these values
- ** do not necessarily correspond to columns in SELECT statement pParent,
- ** zero them before transfering the ORDER BY clause.
- **
- ** Not doing this may cause an error if a subsequent call to this
- ** function attempts to flatten a compound sub-query into pParent
- ** (the only way this can happen is if the compound sub-query is
- ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */
- ExprList *pOrderBy = pSub->pOrderBy;
- for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].u.x.iOrderByCol = 0;
- }
- assert( pParent->pOrderBy==0 );
- pParent->pOrderBy = pOrderBy;
- pSub->pOrderBy = 0;
- }
- pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
- if( isLeftJoin>0 ){
- setJoinExpr(pWhere, iNewParent);
- }
- pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
- if( db->mallocFailed==0 ){
- SubstContext x;
- x.pParse = pParse;
- x.iTable = iParent;
- x.iNewTable = iNewParent;
- x.isLeftJoin = isLeftJoin;
- x.pEList = pSub->pEList;
- substSelect(&x, pParent, 0);
- }
-
- /* The flattened query is distinct if either the inner or the
- ** outer query is distinct.
- */
- pParent->selFlags |= pSub->selFlags & SF_Distinct;
-
- /*
- ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
- **
- ** One is tempted to try to add a and b to combine the limits. But this
- ** does not work if either limit is negative.
- */
- if( pSub->pLimit ){
- pParent->pLimit = pSub->pLimit;
- pSub->pLimit = 0;
- }
- }
-
- /* Finially, delete what is left of the subquery and return
- ** success.
- */
- sqlite3SelectDelete(db, pSub1);
-
-#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x100 ){
- SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
-
- return 1;
-}
-#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
-
-
-
-#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
-/*
-** Make copies of relevant WHERE clause terms of the outer query into
-** the WHERE clause of subquery. Example:
-**
-** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10;
-**
-** Transformed into:
-**
-** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
-** WHERE x=5 AND y=10;
-**
-** The hope is that the terms added to the inner query will make it more
-** efficient.
-**
-** Do not attempt this optimization if:
-**
-** (1) (** This restriction was removed on 2017-09-29. We used to
-** disallow this optimization for aggregate subqueries, but now
-** it is allowed by putting the extra terms on the HAVING clause.
-** The added HAVING clause is pointless if the subquery lacks
-** a GROUP BY clause. But such a HAVING clause is also harmless
-** so there does not appear to be any reason to add extra logic
-** to suppress it. **)
-**
-** (2) The inner query is the recursive part of a common table expression.
-**
-** (3) The inner query has a LIMIT clause (since the changes to the WHERE
-** close would change the meaning of the LIMIT).
-**
-** (4) The inner query is the right operand of a LEFT JOIN and the
-** expression to be pushed down does not come from the ON clause
-** on that LEFT JOIN.
-**
-** (5) The WHERE clause expression originates in the ON or USING clause
-** of a LEFT JOIN where iCursor is not the right-hand table of that
-** left join. An example:
-**
-** SELECT *
-** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa
-** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2)
-** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2);
-**
-** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9).
-** But if the (b2=2) term were to be pushed down into the bb subquery,
-** then the (1,1,NULL) row would be suppressed.
-**
-** Return 0 if no changes are made and non-zero if one or more WHERE clause
-** terms are duplicated into the subquery.
-*/
-static int pushDownWhereTerms(
- Parse *pParse, /* Parse context (for malloc() and error reporting) */
- Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
- Expr *pWhere, /* The WHERE clause of the outer query */
- int iCursor, /* Cursor number of the subquery */
- int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */
-){
- Expr *pNew;
- int nChng = 0;
- if( pWhere==0 ) return 0;
- if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
-
-#ifdef SQLITE_DEBUG
- /* Only the first term of a compound can have a WITH clause. But make
- ** sure no other terms are marked SF_Recursive in case something changes
- ** in the future.
- */
- {
- Select *pX;
- for(pX=pSubq; pX; pX=pX->pPrior){
- assert( (pX->selFlags & (SF_Recursive))==0 );
- }
- }
-#endif
-
- if( pSubq->pLimit!=0 ){
- return 0; /* restriction (3) */
- }
- while( pWhere->op==TK_AND ){
- nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
- iCursor, isLeftJoin);
- pWhere = pWhere->pLeft;
- }
- if( isLeftJoin
- && (ExprHasProperty(pWhere,EP_FromJoin)==0
- || pWhere->iRightJoinTable!=iCursor)
- ){
- return 0; /* restriction (4) */
- }
- if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){
- return 0; /* restriction (5) */
- }
- if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
- nChng++;
- while( pSubq ){
- SubstContext x;
- pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
- unsetJoinExpr(pNew, -1);
- x.pParse = pParse;
- x.iTable = iCursor;
- x.iNewTable = iCursor;
- x.isLeftJoin = 0;
- x.pEList = pSubq->pEList;
- pNew = substExpr(&x, pNew);
- if( pSubq->selFlags & SF_Aggregate ){
- pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew);
- }else{
- pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
- }
- pSubq = pSubq->pPrior;
- }
- }
- return nChng;
-}
-#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
-
-/*
-** The pFunc is the only aggregate function in the query. Check to see
-** if the query is a candidate for the min/max optimization.
-**
-** If the query is a candidate for the min/max optimization, then set
-** *ppMinMax to be an ORDER BY clause to be used for the optimization
-** and return either WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX depending on
-** whether pFunc is a min() or max() function.
-**
-** If the query is not a candidate for the min/max optimization, return
-** WHERE_ORDERBY_NORMAL (which must be zero).
-**
-** This routine must be called after aggregate functions have been
-** located but before their arguments have been subjected to aggregate
-** analysis.
-*/
-static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
- int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
- ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */
- const char *zFunc; /* Name of aggregate function pFunc */
- ExprList *pOrderBy;
- u8 sortOrder;
-
- assert( *ppMinMax==0 );
- assert( pFunc->op==TK_AGG_FUNCTION );
- if( pEList==0 || pEList->nExpr!=1 ) return eRet;
- zFunc = pFunc->u.zToken;
- if( sqlite3StrICmp(zFunc, "min")==0 ){
- eRet = WHERE_ORDERBY_MIN;
- sortOrder = SQLITE_SO_ASC;
- }else if( sqlite3StrICmp(zFunc, "max")==0 ){
- eRet = WHERE_ORDERBY_MAX;
- sortOrder = SQLITE_SO_DESC;
- }else{
- return eRet;
- }
- *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0);
- assert( pOrderBy!=0 || db->mallocFailed );
- if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder;
- return eRet;
-}
-
-/*
-** The select statement passed as the first argument is an aggregate query.
-** The second argument is the associated aggregate-info object. This
-** function tests if the SELECT is of the form:
-**
-** SELECT count(*) FROM <tbl>
-**
-** where table is a database table, not a sub-select or view. If the query
-** does match this pattern, then a pointer to the Table object representing
-** <tbl> is returned. Otherwise, 0 is returned.
-*/
-static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
- Table *pTab;
- Expr *pExpr;
-
- assert( !p->pGroupBy );
-
- if( p->pWhere || p->pEList->nExpr!=1
- || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect
- ){
- return 0;
- }
- pTab = p->pSrc->a[0].pTab;
- pExpr = p->pEList->a[0].pExpr;
- assert( pTab && !pTab->pSelect && pExpr );
-
- if( IsVirtual(pTab) ) return 0;
- if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
- if( NEVER(pAggInfo->nFunc==0) ) return 0;
- if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
- if( pExpr->flags&EP_Distinct ) return 0;
-
- return pTab;
-}
-
-/*
-** If the source-list item passed as an argument was augmented with an
-** INDEXED BY clause, then try to locate the specified index. If there
-** was such a clause and the named index cannot be found, return
-** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
-** pFrom->pIndex and return SQLITE_OK.
-*/
-int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
- if( pFrom->pTab && pFrom->fg.isIndexedBy ){
- Table *pTab = pFrom->pTab;
- char *zIndexedBy = pFrom->u1.zIndexedBy;
- Index *pIdx;
- for(pIdx=pTab->pIndex;
- pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
- pIdx=pIdx->pNext
- );
- if( !pIdx ){
- sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
- pParse->checkSchema = 1;
- return SQLITE_ERROR;
- }
- pFrom->pIBIndex = pIdx;
- }
- return SQLITE_OK;
-}
-/*
-** Detect compound SELECT statements that use an ORDER BY clause with
-** an alternative collating sequence.
-**
-** SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ...
-**
-** These are rewritten as a subquery:
-**
-** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2)
-** ORDER BY ... COLLATE ...
-**
-** This transformation is necessary because the multiSelectOrderBy() routine
-** above that generates the code for a compound SELECT with an ORDER BY clause
-** uses a merge algorithm that requires the same collating sequence on the
-** result columns as on the ORDER BY clause. See ticket
-** http://www.sqlite.org/src/info/6709574d2a
-**
-** This transformation is only needed for EXCEPT, INTERSECT, and UNION.
-** The UNION ALL operator works fine with multiSelectOrderBy() even when
-** there are COLLATE terms in the ORDER BY.
-*/
-static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
- int i;
- Select *pNew;
- Select *pX;
- sqlite3 *db;
- struct ExprList_item *a;
- SrcList *pNewSrc;
- Parse *pParse;
- Token dummy;
-
- if( p->pPrior==0 ) return WRC_Continue;
- if( p->pOrderBy==0 ) return WRC_Continue;
- for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){}
- if( pX==0 ) return WRC_Continue;
- a = p->pOrderBy->a;
- for(i=p->pOrderBy->nExpr-1; i>=0; i--){
- if( a[i].pExpr->flags & EP_Collate ) break;
- }
- if( i<0 ) return WRC_Continue;
-
- /* If we reach this point, that means the transformation is required. */
-
- pParse = pWalker->pParse;
- db = pParse->db;
- pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
- if( pNew==0 ) return WRC_Abort;
- memset(&dummy, 0, sizeof(dummy));
- pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0);
- if( pNewSrc==0 ) return WRC_Abort;
- *pNew = *p;
- p->pSrc = pNewSrc;
- p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0));
- p->op = TK_SELECT;
- p->pWhere = 0;
- pNew->pGroupBy = 0;
- pNew->pHaving = 0;
- pNew->pOrderBy = 0;
- p->pPrior = 0;
- p->pNext = 0;
- p->pWith = 0;
- p->selFlags &= ~SF_Compound;
- assert( (p->selFlags & SF_Converted)==0 );
- p->selFlags |= SF_Converted;
- assert( pNew->pPrior!=0 );
- pNew->pPrior->pNext = pNew;
- pNew->pLimit = 0;
- return WRC_Continue;
-}
-
-/*
-** Check to see if the FROM clause term pFrom has table-valued function
-** arguments. If it does, leave an error message in pParse and return
-** non-zero, since pFrom is not allowed to be a table-valued function.
-*/
-static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
- if( pFrom->fg.isTabFunc ){
- sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName);
- return 1;
- }
- return 0;
-}
-
-#ifndef SQLITE_OMIT_CTE
-/*
-** Argument pWith (which may be NULL) points to a linked list of nested
-** WITH contexts, from inner to outermost. If the table identified by
-** FROM clause element pItem is really a common-table-expression (CTE)
-** then return a pointer to the CTE definition for that table. Otherwise
-** return NULL.
-**
-** If a non-NULL value is returned, set *ppContext to point to the With
-** object that the returned CTE belongs to.
-*/
-static struct Cte *searchWith(
- With *pWith, /* Current innermost WITH clause */
- struct SrcList_item *pItem, /* FROM clause element to resolve */
- With **ppContext /* OUT: WITH clause return value belongs to */
-){
- const char *zName;
- if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){
- With *p;
- for(p=pWith; p; p=p->pOuter){
- int i;
- for(i=0; i<p->nCte; i++){
- if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
- *ppContext = p;
- return &p->a[i];
- }
- }
- }
- }
- return 0;
-}
-
-/* The code generator maintains a stack of active WITH clauses
-** with the inner-most WITH clause being at the top of the stack.
-**
-** This routine pushes the WITH clause passed as the second argument
-** onto the top of the stack. If argument bFree is true, then this
-** WITH clause will never be popped from the stack. In this case it
-** should be freed along with the Parse object. In other cases, when
-** bFree==0, the With object will be freed along with the SELECT
-** statement with which it is associated.
-*/
-void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
- assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
- if( pWith ){
- assert( pParse->pWith!=pWith );
- pWith->pOuter = pParse->pWith;
- pParse->pWith = pWith;
- if( bFree ) pParse->pWithToFree = pWith;
- }
-}
-
-/*
-** This function checks if argument pFrom refers to a CTE declared by
-** a WITH clause on the stack currently maintained by the parser. And,
-** if currently processing a CTE expression, if it is a recursive
-** reference to the current CTE.
-**
-** If pFrom falls into either of the two categories above, pFrom->pTab
-** and other fields are populated accordingly. The caller should check
-** (pFrom->pTab!=0) to determine whether or not a successful match
-** was found.
-**
-** Whether or not a match is found, SQLITE_OK is returned if no error
-** occurs. If an error does occur, an error message is stored in the
-** parser and some error code other than SQLITE_OK returned.
-*/
-static int withExpand(
- Walker *pWalker,
- struct SrcList_item *pFrom
-){
- Parse *pParse = pWalker->pParse;
- sqlite3 *db = pParse->db;
- struct Cte *pCte; /* Matched CTE (or NULL if no match) */
- With *pWith; /* WITH clause that pCte belongs to */
-
- assert( pFrom->pTab==0 );
-
- pCte = searchWith(pParse->pWith, pFrom, &pWith);
- if( pCte ){
- Table *pTab;
- ExprList *pEList;
- Select *pSel;
- Select *pLeft; /* Left-most SELECT statement */
- int bMayRecursive; /* True if compound joined by UNION [ALL] */
- With *pSavedWith; /* Initial value of pParse->pWith */
-
- /* If pCte->zCteErr is non-NULL at this point, then this is an illegal
- ** recursive reference to CTE pCte. Leave an error in pParse and return
- ** early. If pCte->zCteErr is NULL, then this is not a recursive reference.
- ** In this case, proceed. */
- if( pCte->zCteErr ){
- sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName);
- return SQLITE_ERROR;
- }
- if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR;
-
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return WRC_Abort;
- pTab->nTabRef = 1;
- pTab->zName = sqlite3DbStrDup(db, pCte->zName);
- pTab->iPKey = -1;
- pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
- pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
- pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
- if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
- assert( pFrom->pSelect );
-
- /* Check if this is a recursive CTE. */
- pSel = pFrom->pSelect;
- bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
- if( bMayRecursive ){
- int i;
- SrcList *pSrc = pFrom->pSelect->pSrc;
- for(i=0; i<pSrc->nSrc; i++){
- struct SrcList_item *pItem = &pSrc->a[i];
- if( pItem->zDatabase==0
- && pItem->zName!=0
- && 0==sqlite3StrICmp(pItem->zName, pCte->zName)
- ){
- pItem->pTab = pTab;
- pItem->fg.isRecursive = 1;
- pTab->nTabRef++;
- pSel->selFlags |= SF_Recursive;
- }
- }
- }
-
- /* Only one recursive reference is permitted. */
- if( pTab->nTabRef>2 ){
- sqlite3ErrorMsg(
- pParse, "multiple references to recursive table: %s", pCte->zName
- );
- return SQLITE_ERROR;
- }
- assert( pTab->nTabRef==1 ||
- ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
-
- pCte->zCteErr = "circular reference: %s";
- pSavedWith = pParse->pWith;
- pParse->pWith = pWith;
- if( bMayRecursive ){
- Select *pPrior = pSel->pPrior;
- assert( pPrior->pWith==0 );
- pPrior->pWith = pSel->pWith;
- sqlite3WalkSelect(pWalker, pPrior);
- pPrior->pWith = 0;
- }else{
- sqlite3WalkSelect(pWalker, pSel);
- }
- pParse->pWith = pWith;
-
- for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
- pEList = pLeft->pEList;
- if( pCte->pCols ){
- if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){
- sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns",
- pCte->zName, pEList->nExpr, pCte->pCols->nExpr
- );
- pParse->pWith = pSavedWith;
- return SQLITE_ERROR;
- }
- pEList = pCte->pCols;
- }
-
- sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol);
- if( bMayRecursive ){
- if( pSel->selFlags & SF_Recursive ){
- pCte->zCteErr = "multiple recursive references: %s";
- }else{
- pCte->zCteErr = "recursive reference in a subquery: %s";
- }
- sqlite3WalkSelect(pWalker, pSel);
- }
- pCte->zCteErr = 0;
- pParse->pWith = pSavedWith;
- }
-
- return SQLITE_OK;
-}
-#endif
-
-#ifndef SQLITE_OMIT_CTE
-/*
-** If the SELECT passed as the second argument has an associated WITH
-** clause, pop it from the stack stored as part of the Parse object.
-**
-** This function is used as the xSelectCallback2() callback by
-** sqlite3SelectExpand() when walking a SELECT tree to resolve table
-** names and other FROM clause elements.
-*/
-static void selectPopWith(Walker *pWalker, Select *p){
- Parse *pParse = pWalker->pParse;
- if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
- With *pWith = findRightmost(p)->pWith;
- if( pWith!=0 ){
- assert( pParse->pWith==pWith );
- pParse->pWith = pWith->pOuter;
- }
- }
-}
-#else
-#define selectPopWith 0
-#endif
-
-/*
-** This routine is a Walker callback for "expanding" a SELECT statement.
-** "Expanding" means to do the following:
-**
-** (1) Make sure VDBE cursor numbers have been assigned to every
-** element of the FROM clause.
-**
-** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
-** defines FROM clause. When views appear in the FROM clause,
-** fill pTabList->a[].pSelect with a copy of the SELECT statement
-** that implements the view. A copy is made of the view's SELECT
-** statement so that we can freely modify or delete that statement
-** without worrying about messing up the persistent representation
-** of the view.
-**
-** (3) Add terms to the WHERE clause to accommodate the NATURAL keyword
-** on joins and the ON and USING clause of joins.
-**
-** (4) Scan the list of columns in the result set (pEList) looking
-** for instances of the "*" operator or the TABLE.* operator.
-** If found, expand each "*" to be every column in every table
-** and TABLE.* to be every column in TABLE.
-**
-*/
-static int selectExpander(Walker *pWalker, Select *p){
- Parse *pParse = pWalker->pParse;
- int i, j, k;
- SrcList *pTabList;
- ExprList *pEList;
- struct SrcList_item *pFrom;
- sqlite3 *db = pParse->db;
- Expr *pE, *pRight, *pExpr;
- u16 selFlags = p->selFlags;
- u32 elistFlags = 0;
-
- p->selFlags |= SF_Expanded;
- if( db->mallocFailed ){
- return WRC_Abort;
- }
- assert( p->pSrc!=0 );
- if( (selFlags & SF_Expanded)!=0 ){
- return WRC_Prune;
- }
- pTabList = p->pSrc;
- pEList = p->pEList;
- sqlite3WithPush(pParse, p->pWith, 0);
-
- /* Make sure cursor numbers have been assigned to all entries in
- ** the FROM clause of the SELECT statement.
- */
- sqlite3SrcListAssignCursors(pParse, pTabList);
-
- /* Look up every table named in the FROM clause of the select. If
- ** an entry of the FROM clause is a subquery instead of a table or view,
- ** then create a transient table structure to describe the subquery.
- */
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab;
- assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
- if( pFrom->fg.isRecursive ) continue;
- assert( pFrom->pTab==0 );
-#ifndef SQLITE_OMIT_CTE
- if( withExpand(pWalker, pFrom) ) return WRC_Abort;
- if( pFrom->pTab ) {} else
-#endif
- if( pFrom->zName==0 ){
-#ifndef SQLITE_OMIT_SUBQUERY
- Select *pSel = pFrom->pSelect;
- /* A sub-query in the FROM clause of a SELECT */
- assert( pSel!=0 );
- assert( pFrom->pTab==0 );
- if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return WRC_Abort;
- pTab->nTabRef = 1;
- if( pFrom->zAlias ){
- pTab->zName = sqlite3DbStrDup(db, pFrom->zAlias);
- }else{
- pTab->zName = sqlite3MPrintf(db, "subquery_%p", (void*)pTab);
- }
- while( pSel->pPrior ){ pSel = pSel->pPrior; }
- sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
- pTab->iPKey = -1;
- pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
- pTab->tabFlags |= TF_Ephemeral;
-#endif
- }else{
- /* An ordinary table or view name in the FROM clause */
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
- if( pTab==0 ) return WRC_Abort;
- if( pTab->nTabRef>=0xffff ){
- sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
- pTab->zName);
- pFrom->pTab = 0;
- return WRC_Abort;
- }
- pTab->nTabRef++;
- if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
- return WRC_Abort;
- }
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
- if( IsVirtual(pTab) || pTab->pSelect ){
- i16 nCol;
- if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
- assert( pFrom->pSelect==0 );
- pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
- sqlite3SelectSetName(pFrom->pSelect, pTab->zName);
- nCol = pTab->nCol;
- pTab->nCol = -1;
- sqlite3WalkSelect(pWalker, pFrom->pSelect);
- pTab->nCol = nCol;
- }
-#endif
- }
-
- /* Locate the index named by the INDEXED BY clause, if any. */
- if( sqlite3IndexedByLookup(pParse, pFrom) ){
- return WRC_Abort;
- }
- }
-
- /* Process NATURAL keywords, and ON and USING clauses of joins.
- */
- if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
- return WRC_Abort;
- }
-
- /* For every "*" that occurs in the column list, insert the names of
- ** all columns in all tables. And for every TABLE.* insert the names
- ** of all columns in TABLE. The parser inserted a special expression
- ** with the TK_ASTERISK operator for each "*" that it found in the column
- ** list. The following code just has to locate the TK_ASTERISK
- ** expressions and expand each one to the list of all columns in
- ** all tables.
- **
- ** The first loop just checks to see if there are any "*" operators
- ** that need expanding.
- */
- for(k=0; k<pEList->nExpr; k++){
- pE = pEList->a[k].pExpr;
- if( pE->op==TK_ASTERISK ) break;
- assert( pE->op!=TK_DOT || pE->pRight!=0 );
- assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
- if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break;
- elistFlags |= pE->flags;
- }
- if( k<pEList->nExpr ){
- /*
- ** If we get here it means the result set contains one or more "*"
- ** operators that need to be expanded. Loop through each expression
- ** in the result set and expand them one by one.
- */
- struct ExprList_item *a = pEList->a;
- ExprList *pNew = 0;
- int flags = pParse->db->flags;
- int longNames = (flags & SQLITE_FullColNames)!=0
- && (flags & SQLITE_ShortColNames)==0;
-
- for(k=0; k<pEList->nExpr; k++){
- pE = a[k].pExpr;
- elistFlags |= pE->flags;
- pRight = pE->pRight;
- assert( pE->op!=TK_DOT || pRight!=0 );
- if( pE->op!=TK_ASTERISK
- && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
- ){
- /* This particular expression does not need to be expanded.
- */
- pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
- if( pNew ){
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
- pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
- a[k].zName = 0;
- a[k].zSpan = 0;
- }
- a[k].pExpr = 0;
- }else{
- /* This expression is a "*" or a "TABLE.*" and needs to be
- ** expanded. */
- int tableSeen = 0; /* Set to 1 when TABLE matches */
- char *zTName = 0; /* text of name of TABLE */
- if( pE->op==TK_DOT ){
- assert( pE->pLeft!=0 );
- assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
- zTName = pE->pLeft->u.zToken;
- }
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
- Select *pSub = pFrom->pSelect;
- char *zTabName = pFrom->zAlias;
- const char *zSchemaName = 0;
- int iDb;
- if( zTabName==0 ){
- zTabName = pTab->zName;
- }
- if( db->mallocFailed ) break;
- if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
- pSub = 0;
- if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
- continue;
- }
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
- }
- for(j=0; j<pTab->nCol; j++){
- char *zName = pTab->aCol[j].zName;
- char *zColname; /* The computed column name */
- char *zToFree; /* Malloced string that needs to be freed */
- Token sColname; /* Computed column name as a token */
-
- assert( zName );
- if( zTName && pSub
- && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
- ){
- continue;
- }
-
- /* If a column is marked as 'hidden', omit it from the expanded
- ** result-set list unless the SELECT has the SF_IncludeHidden
- ** bit set.
- */
- if( (p->selFlags & SF_IncludeHidden)==0
- && IsHiddenColumn(&pTab->aCol[j])
- ){
- continue;
- }
- tableSeen = 1;
-
- if( i>0 && zTName==0 ){
- if( (pFrom->fg.jointype & JT_NATURAL)!=0
- && tableAndColumnIndex(pTabList, i, zName, 0, 0)
- ){
- /* In a NATURAL join, omit the join columns from the
- ** table to the right of the join */
- continue;
- }
- if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){
- /* In a join with a USING clause, omit columns in the
- ** using clause from the table on the right. */
- continue;
- }
- }
- pRight = sqlite3Expr(db, TK_ID, zName);
- zColname = zName;
- zToFree = 0;
- if( longNames || pTabList->nSrc>1 ){
- Expr *pLeft;
- pLeft = sqlite3Expr(db, TK_ID, zTabName);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- if( zSchemaName ){
- pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr);
- }
- if( longNames ){
- zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
- zToFree = zColname;
- }
- }else{
- pExpr = pRight;
- }
- pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
- sqlite3TokenInit(&sColname, zColname);
- sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
- if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
- struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
- if( pSub ){
- pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
- testcase( pX->zSpan==0 );
- }else{
- pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
- zSchemaName, zTabName, zColname);
- testcase( pX->zSpan==0 );
- }
- pX->bSpanIsTab = 1;
- }
- sqlite3DbFree(db, zToFree);
- }
- }
- if( !tableSeen ){
- if( zTName ){
- sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
- }else{
- sqlite3ErrorMsg(pParse, "no tables specified");
- }
- }
- }
- }
- sqlite3ExprListDelete(db, pEList);
- p->pEList = pNew;
- }
- if( p->pEList ){
- if( p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many columns in result set");
- return WRC_Abort;
- }
- if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){
- p->selFlags |= SF_ComplexResult;
- }
- }
- return WRC_Continue;
-}
-
-/*
-** No-op routine for the parse-tree walker.
-**
-** When this routine is the Walker.xExprCallback then expression trees
-** are walked without any actions being taken at each node. Presumably,
-** when this routine is used for Walker.xExprCallback then
-** Walker.xSelectCallback is set to do something useful for every
-** subquery in the parser tree.
-*/
-int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return WRC_Continue;
-}
-
-/*
-** No-op routine for the parse-tree walker for SELECT statements.
-** subquery in the parser tree.
-*/
-int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return WRC_Continue;
-}
-
-#if SQLITE_DEBUG
-/*
-** Always assert. This xSelectCallback2 implementation proves that the
-** xSelectCallback2 is never invoked.
-*/
-void sqlite3SelectWalkAssert2(Walker *NotUsed, Select *NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- assert( 0 );
-}
-#endif
-/*
-** This routine "expands" a SELECT statement and all of its subqueries.
-** For additional information on what it means to "expand" a SELECT
-** statement, see the comment on the selectExpand worker callback above.
-**
-** Expanding a SELECT statement is the first step in processing a
-** SELECT statement. The SELECT statement must be expanded before
-** name resolution is performed.
-**
-** If anything goes wrong, an error message is written into pParse.
-** The calling function can detect the problem by looking at pParse->nErr
-** and/or pParse->db->mallocFailed.
-*/
-static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
- Walker w;
- w.xExprCallback = sqlite3ExprWalkNoop;
- w.pParse = pParse;
- if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){
- w.xSelectCallback = convertCompoundSelectToSubquery;
- w.xSelectCallback2 = 0;
- sqlite3WalkSelect(&w, pSelect);
- }
- w.xSelectCallback = selectExpander;
- w.xSelectCallback2 = selectPopWith;
- sqlite3WalkSelect(&w, pSelect);
-}
-
-
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()
-** interface.
-**
-** For each FROM-clause subquery, add Column.zType and Column.zColl
-** information to the Table structure that represents the result set
-** of that subquery.
-**
-** The Table structure that represents the result set was constructed
-** by selectExpander() but the type and collation information was omitted
-** at that point because identifiers had not yet been resolved. This
-** routine is called after identifier resolution.
-*/
-static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
- Parse *pParse;
- int i;
- SrcList *pTabList;
- struct SrcList_item *pFrom;
-
- assert( p->selFlags & SF_Resolved );
- assert( (p->selFlags & SF_HasTypeInfo)==0 );
- p->selFlags |= SF_HasTypeInfo;
- pParse = pWalker->pParse;
- pTabList = p->pSrc;
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
- assert( pTab!=0 );
- if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
- /* A sub-query in the FROM clause of a SELECT */
- Select *pSel = pFrom->pSelect;
- if( pSel ){
- while( pSel->pPrior ) pSel = pSel->pPrior;
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel);
- }
- }
- }
-}
-#endif
-
-
-/*
-** This routine adds datatype and collating sequence information to
-** the Table structures of all FROM-clause subqueries in a
-** SELECT statement.
-**
-** Use this routine after name resolution.
-*/
-static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
-#ifndef SQLITE_OMIT_SUBQUERY
- Walker w;
- w.xSelectCallback = sqlite3SelectWalkNoop;
- w.xSelectCallback2 = selectAddSubqueryTypeInfo;
- w.xExprCallback = sqlite3ExprWalkNoop;
- w.pParse = pParse;
- sqlite3WalkSelect(&w, pSelect);
-#endif
-}
-
-
-/*
-** This routine sets up a SELECT statement for processing. The
-** following is accomplished:
-**
-** * VDBE Cursor numbers are assigned to all FROM-clause terms.
-** * Ephemeral Table objects are created for all FROM-clause subqueries.
-** * ON and USING clauses are shifted into WHERE statements
-** * Wildcards "*" and "TABLE.*" in result sets are expanded.
-** * Identifiers in expression are matched to tables.
-**
-** This routine acts recursively on all subqueries within the SELECT.
-*/
-void sqlite3SelectPrep(
- Parse *pParse, /* The parser context */
- Select *p, /* The SELECT statement being coded. */
- NameContext *pOuterNC /* Name context for container */
-){
- assert( p!=0 || pParse->db->mallocFailed );
- if( pParse->db->mallocFailed ) return;
- if( p->selFlags & SF_HasTypeInfo ) return;
- sqlite3SelectExpand(pParse, p);
- if( pParse->nErr || pParse->db->mallocFailed ) return;
- sqlite3ResolveSelectNames(pParse, p, pOuterNC);
- if( pParse->nErr || pParse->db->mallocFailed ) return;
- sqlite3SelectAddTypeInfo(pParse, p);
-}
-
-/*
-** Reset the aggregate accumulator.
-**
-** The aggregate accumulator is a set of memory cells that hold
-** intermediate results while calculating an aggregate. This
-** routine generates code that stores NULLs in all of those memory
-** cells.
-*/
-static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
- Vdbe *v = pParse->pVdbe;
- int i;
- struct AggInfo_func *pFunc;
- int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
- if( nReg==0 ) return;
-#ifdef SQLITE_DEBUG
- /* Verify that all AggInfo registers are within the range specified by
- ** AggInfo.mnReg..AggInfo.mxReg */
- assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 );
- for(i=0; i<pAggInfo->nColumn; i++){
- assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg
- && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg );
- }
- for(i=0; i<pAggInfo->nFunc; i++){
- assert( pAggInfo->aFunc[i].iMem>=pAggInfo->mnReg
- && pAggInfo->aFunc[i].iMem<=pAggInfo->mxReg );
- }
-#endif
- sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg);
- for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
- if( pFunc->iDistinct>=0 ){
- Expr *pE = pFunc->pExpr;
- assert( !ExprHasProperty(pE, EP_xIsSelect) );
- if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
- sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
- "argument");
- pFunc->iDistinct = -1;
- }else{
- KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0);
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
- (char*)pKeyInfo, P4_KEYINFO);
- }
- }
- }
-}
-
-/*
-** Invoke the OP_AggFinalize opcode for every aggregate function
-** in the AggInfo structure.
-*/
-static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
- Vdbe *v = pParse->pVdbe;
- int i;
- struct AggInfo_func *pF;
- for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
- ExprList *pList = pF->pExpr->x.pList;
- assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
- sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
- sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
- }
-}
-
-/*
-** Update the accumulator memory cells for an aggregate based on
-** the current cursor position.
-*/
-static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
- Vdbe *v = pParse->pVdbe;
- int i;
- int regHit = 0;
- int addrHitTest = 0;
- struct AggInfo_func *pF;
- struct AggInfo_col *pC;
-
- pAggInfo->directMode = 1;
- for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
- int nArg;
- int addrNext = 0;
- int regAgg;
- ExprList *pList = pF->pExpr->x.pList;
- assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
- if( pList ){
- nArg = pList->nExpr;
- regAgg = sqlite3GetTempRange(pParse, nArg);
- sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
- }else{
- nArg = 0;
- regAgg = 0;
- }
- if( pF->iDistinct>=0 ){
- addrNext = sqlite3VdbeMakeLabel(v);
- testcase( nArg==0 ); /* Error condition */
- testcase( nArg>1 ); /* Also an error */
- codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
- }
- if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
- CollSeq *pColl = 0;
- struct ExprList_item *pItem;
- int j;
- assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */
- for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
- pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
- }
- if( !pColl ){
- pColl = pParse->db->pDfltColl;
- }
- if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
- sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
- }
- sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem);
- sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nArg);
- sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
- sqlite3ReleaseTempRange(pParse, regAgg, nArg);
- if( addrNext ){
- sqlite3VdbeResolveLabel(v, addrNext);
- sqlite3ExprCacheClear(pParse);
- }
- }
-
- /* Before populating the accumulator registers, clear the column cache.
- ** Otherwise, if any of the required column values are already present
- ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value
- ** to pC->iMem. But by the time the value is used, the original register
- ** may have been used, invalidating the underlying buffer holding the
- ** text or blob value. See ticket [883034dcb5].
- **
- ** Another solution would be to change the OP_SCopy used to copy cached
- ** values to an OP_Copy.
- */
- if( regHit ){
- addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
- }
- sqlite3ExprCacheClear(pParse);
- for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
- sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
- }
- pAggInfo->directMode = 0;
- sqlite3ExprCacheClear(pParse);
- if( addrHitTest ){
- sqlite3VdbeJumpHere(v, addrHitTest);
- }
-}
-
-/*
-** Add a single OP_Explain instruction to the VDBE to explain a simple
-** count(*) query ("SELECT count(*) FROM pTab").
-*/
-#ifndef SQLITE_OMIT_EXPLAIN
-static void explainSimpleCount(
- Parse *pParse, /* Parse context */
- Table *pTab, /* Table being queried */
- Index *pIdx /* Index used to optimize scan, or NULL */
-){
- if( pParse->explain==2 ){
- int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
- sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s",
- pTab->zName,
- bCover ? " USING COVERING INDEX " : "",
- bCover ? pIdx->zName : ""
- );
- }
-}
-#else
-# define explainSimpleCount(a,b,c)
-#endif
-
-/*
-** sqlite3WalkExpr() callback used by havingToWhere().
-**
-** If the node passed to the callback is a TK_AND node, return
-** WRC_Continue to tell sqlite3WalkExpr() to iterate through child nodes.
-**
-** Otherwise, return WRC_Prune. In this case, also check if the
-** sub-expression matches the criteria for being moved to the WHERE
-** clause. If so, add it to the WHERE clause and replace the sub-expression
-** within the HAVING expression with a constant "1".
-*/
-static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
- if( pExpr->op!=TK_AND ){
- Select *pS = pWalker->u.pSelect;
- if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){
- sqlite3 *db = pWalker->pParse->db;
- Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
- if( pNew ){
- Expr *pWhere = pS->pWhere;
- SWAP(Expr, *pNew, *pExpr);
- pNew = sqlite3ExprAnd(db, pWhere, pNew);
- pS->pWhere = pNew;
- pWalker->eCode = 1;
- }
- }
- return WRC_Prune;
- }
- return WRC_Continue;
-}
-
-/*
-** Transfer eligible terms from the HAVING clause of a query, which is
-** processed after grouping, to the WHERE clause, which is processed before
-** grouping. For example, the query:
-**
-** SELECT * FROM <tables> WHERE a=? GROUP BY b HAVING b=? AND c=?
-**
-** can be rewritten as:
-**
-** SELECT * FROM <tables> WHERE a=? AND b=? GROUP BY b HAVING c=?
-**
-** A term of the HAVING expression is eligible for transfer if it consists
-** entirely of constants and expressions that are also GROUP BY terms that
-** use the "BINARY" collation sequence.
-*/
-static void havingToWhere(Parse *pParse, Select *p){
- Walker sWalker;
- memset(&sWalker, 0, sizeof(sWalker));
- sWalker.pParse = pParse;
- sWalker.xExprCallback = havingToWhereExprCb;
- sWalker.u.pSelect = p;
- sqlite3WalkExpr(&sWalker, p->pHaving);
-#if SELECTTRACE_ENABLED
- if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){
- SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
-}
-
-/*
-** Check to see if the pThis entry of pTabList is a self-join of a prior view.
-** If it is, then return the SrcList_item for the prior view. If it is not,
-** then return 0.
-*/
-static struct SrcList_item *isSelfJoinView(
- SrcList *pTabList, /* Search for self-joins in this FROM clause */
- struct SrcList_item *pThis /* Search for prior reference to this subquery */
-){
- struct SrcList_item *pItem;
- for(pItem = pTabList->a; pItem<pThis; pItem++){
- if( pItem->pSelect==0 ) continue;
- if( pItem->fg.viaCoroutine ) continue;
- if( pItem->zName==0 ) continue;
- if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
- if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
- if( sqlite3ExprCompare(0,
- pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1)
- ){
- /* The view was modified by some other optimization such as
- ** pushDownWhereTerms() */
- continue;
- }
- return pItem;
- }
- return 0;
-}
-
-#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
-/*
-** Attempt to transform a query of the form
-**
-** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2)
-**
-** Into this:
-**
-** SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2)
-**
-** The transformation only works if all of the following are true:
-**
-** * The subquery is a UNION ALL of two or more terms
-** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
-** * The outer query is a simple count(*)
-**
-** Return TRUE if the optimization is undertaken.
-*/
-static int countOfViewOptimization(Parse *pParse, Select *p){
- Select *pSub, *pPrior;
- Expr *pExpr;
- Expr *pCount;
- sqlite3 *db;
- if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
- if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
- pExpr = p->pEList->a[0].pExpr;
- if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
- if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
- if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
- if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
- pSub = p->pSrc->a[0].pSelect;
- if( pSub==0 ) return 0; /* The FROM is a subquery */
- if( pSub->pPrior==0 ) return 0; /* Must be a compound ry */
- do{
- if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
- if( pSub->pWhere ) return 0; /* No WHERE clause */
- if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
- pSub = pSub->pPrior; /* Repeat over compound */
- }while( pSub );
-
- /* If we reach this point then it is OK to perform the transformation */
-
- db = pParse->db;
- pCount = pExpr;
- pExpr = 0;
- pSub = p->pSrc->a[0].pSelect;
- p->pSrc->a[0].pSelect = 0;
- sqlite3SrcListDelete(db, p->pSrc);
- p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
- while( pSub ){
- Expr *pTerm;
- pPrior = pSub->pPrior;
- pSub->pPrior = 0;
- pSub->pNext = 0;
- pSub->selFlags |= SF_Aggregate;
- pSub->selFlags &= ~SF_Compound;
- pSub->nSelectRow = 0;
- sqlite3ExprListDelete(db, pSub->pEList);
- pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount;
- pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm);
- pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlite3PExprAddSelect(pParse, pTerm, pSub);
- if( pExpr==0 ){
- pExpr = pTerm;
- }else{
- pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr);
- }
- pSub = pPrior;
- }
- p->pEList->a[0].pExpr = pExpr;
- p->selFlags &= ~SF_Aggregate;
-
-#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x400 ){
- SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
- return 1;
-}
-#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */
-
-/*
-** Generate code for the SELECT statement given in the p argument.
-**
-** The results are returned according to the SelectDest structure.
-** See comments in sqliteInt.h for further information.
-**
-** This routine returns the number of errors. If any errors are
-** encountered, then an appropriate error message is left in
-** pParse->zErrMsg.
-**
-** This routine does NOT free the Select structure passed in. The
-** calling function needs to do that.
-*/
-int sqlite3Select(
- Parse *pParse, /* The parser context */
- Select *p, /* The SELECT statement being coded. */
- SelectDest *pDest /* What to do with the query results */
-){
- int i, j; /* Loop counters */
- WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */
- Vdbe *v; /* The virtual machine under construction */
- int isAgg; /* True for select lists like "count(*)" */
- ExprList *pEList = 0; /* List of columns to extract. */
- SrcList *pTabList; /* List of tables to select from */
- Expr *pWhere; /* The WHERE clause. May be NULL */
- ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
- Expr *pHaving; /* The HAVING clause. May be NULL */
- int rc = 1; /* Value to return from this function */
- DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
- SortCtx sSort; /* Info on how to code the ORDER BY clause */
- AggInfo sAggInfo; /* Information used by aggregate queries */
- int iEnd; /* Address of the end of the query */
- sqlite3 *db; /* The database connection */
- ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */
- u8 minMaxFlag; /* Flag for min/max queries */
-
- db = pParse->db;
- v = sqlite3GetVdbe(pParse);
- if( p==0 || db->mallocFailed || pParse->nErr ){
- return 1;
- }
- if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
- memset(&sAggInfo, 0, sizeof(sAggInfo));
-#if SELECTTRACE_ENABLED
- SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
- if( sqlite3SelectTrace & 0x100 ){
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
-
- assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
- assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
- assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
- assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
- if( IgnorableOrderby(pDest) ){
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
- pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
- pDest->eDest==SRT_Queue || pDest->eDest==SRT_DistFifo ||
- pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
- /* If ORDER BY makes no difference in the output then neither does
- ** DISTINCT so it can be removed too. */
- sqlite3ExprListDelete(db, p->pOrderBy);
- p->pOrderBy = 0;
- p->selFlags &= ~SF_Distinct;
- }
- sqlite3SelectPrep(pParse, p, 0);
- memset(&sSort, 0, sizeof(sSort));
- sSort.pOrderBy = p->pOrderBy;
- pTabList = p->pSrc;
- if( pParse->nErr || db->mallocFailed ){
- goto select_end;
- }
- assert( p->pEList!=0 );
- isAgg = (p->selFlags & SF_Aggregate)!=0;
-#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x104 ){
- SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
-
- if( pDest->eDest==SRT_Output ){
- generateColumnNames(pParse, p);
- }
-
- /* Try to various optimizations (flattening subqueries, and strength
- ** reduction of join operators) in the FROM clause up into the main query
- */
-#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
- for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
- Select *pSub = pItem->pSelect;
- Table *pTab = pItem->pTab;
-
- /* Convert LEFT JOIN into JOIN if there are terms of the right table
- ** of the LEFT JOIN used in the WHERE clause.
- */
- if( (pItem->fg.jointype & JT_LEFT)!=0
- && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor)
- && OptimizationEnabled(db, SQLITE_SimplifyJoin)
- ){
- SELECTTRACE(0x100,pParse,p,
- ("LEFT-JOIN simplifies to JOIN on term %d\n",i));
- pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
- unsetJoinExpr(p->pWhere, pItem->iCursor);
- }
-
- /* No futher action if this term of the FROM clause is no a subquery */
- if( pSub==0 ) continue;
-
- /* Catch mismatch in the declared columns of a view and the number of
- ** columns in the SELECT on the RHS */
- if( pTab->nCol!=pSub->pEList->nExpr ){
- sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d",
- pTab->nCol, pTab->zName, pSub->pEList->nExpr);
- goto select_end;
- }
-
- /* Do not try to flatten an aggregate subquery.
- **
- ** Flattening an aggregate subquery is only possible if the outer query
- ** is not a join. But if the outer query is not a join, then the subquery
- ** will be implemented as a co-routine and there is no advantage to
- ** flattening in that case.
- */
- if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
- assert( pSub->pGroupBy==0 );
-
- /* If the outer query contains a "complex" result set (that is,
- ** if the result set of the outer query uses functions or subqueries)
- ** and if the subquery contains an ORDER BY clause and if
- ** it will be implemented as a co-routine, then do not flatten. This
- ** restriction allows SQL constructs like this:
- **
- ** SELECT expensive_function(x)
- ** FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
- **
- ** The expensive_function() is only computed on the 10 rows that
- ** are output, rather than every row of the table.
- **
- ** The requirement that the outer query have a complex result set
- ** means that flattening does occur on simpler SQL constraints without
- ** the expensive_function() like:
- **
- ** SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
- */
- if( pSub->pOrderBy!=0
- && i==0
- && (p->selFlags & SF_ComplexResult)!=0
- && (pTabList->nSrc==1
- || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
- ){
- continue;
- }
-
- if( flattenSubquery(pParse, p, i, isAgg) ){
- /* This subquery can be absorbed into its parent. */
- i = -1;
- }
- pTabList = p->pSrc;
- if( db->mallocFailed ) goto select_end;
- if( !IgnorableOrderby(pDest) ){
- sSort.pOrderBy = p->pOrderBy;
- }
- }
-#endif
-
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
- /* Handle compound SELECT statements using the separate multiSelect()
- ** procedure.
- */
- if( p->pPrior ){
- rc = multiSelect(pParse, p, pDest);
-#if SELECTTRACE_ENABLED
- SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
- if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
- if( p->pNext==0 ) ExplainQueryPlanPop(pParse);
- return rc;
- }
-#endif
-
- /* For each term in the FROM clause, do two things:
- ** (1) Authorized unreferenced tables
- ** (2) Generate code for all sub-queries
- */
- for(i=0; i<pTabList->nSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
- SelectDest dest;
- Select *pSub;
-#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
- const char *zSavedAuthContext;
-#endif
-
- /* Issue SQLITE_READ authorizations with a fake column name for any
- ** tables that are referenced but from which no values are extracted.
- ** Examples of where these kinds of null SQLITE_READ authorizations
- ** would occur:
- **
- ** SELECT count(*) FROM t1; -- SQLITE_READ t1.""
- ** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2.""
- **
- ** The fake column name is an empty string. It is possible for a table to
- ** have a column named by the empty string, in which case there is no way to
- ** distinguish between an unreferenced table and an actual reference to the
- ** "" column. The original design was for the fake column name to be a NULL,
- ** which would be unambiguous. But legacy authorization callbacks might
- ** assume the column name is non-NULL and segfault. The use of an empty
- ** string for the fake column name seems safer.
- */
- if( pItem->colUsed==0 ){
- sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
- }
-
-#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
- /* Generate code for all sub-queries in the FROM clause
- */
- pSub = pItem->pSelect;
- if( pSub==0 ) continue;
-
- /* Sometimes the code for a subquery will be generated more than
- ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
- ** for example. In that case, do not regenerate the code to manifest
- ** a view or the co-routine to implement a view. The first instance
- ** is sufficient, though the subroutine to manifest the view does need
- ** to be invoked again. */
- if( pItem->addrFillSub ){
- if( pItem->fg.viaCoroutine==0 ){
- /* The subroutine that manifests the view might be a one-time routine,
- ** or it might need to be rerun on each iteration because it
- ** encodes a correlated subquery. */
- testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once );
- sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
- }
- continue;
- }
-
- /* Increment Parse.nHeight by the height of the largest expression
- ** tree referred to by this, the parent select. The child select
- ** may contain expression trees of at most
- ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
- ** more conservative than necessary, but much easier than enforcing
- ** an exact limit.
- */
- pParse->nHeight += sqlite3SelectExprHeight(p);
-
- /* Make copies of constant WHERE-clause terms in the outer query down
- ** inside the subquery. This can help the subquery to run more efficiently.
- */
- if( OptimizationEnabled(db, SQLITE_PushDown)
- && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
- (pItem->fg.jointype & JT_OUTER)!=0)
- ){
-#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x100 ){
- SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
- }else{
- SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
- }
-
- zSavedAuthContext = pParse->zAuthContext;
- pParse->zAuthContext = pItem->zName;
-
- /* Generate code to implement the subquery
- **
- ** The subquery is implemented as a co-routine if the subquery is
- ** guaranteed to be the outer loop (so that it does not need to be
- ** computed more than once)
- **
- ** TODO: Are there other reasons beside (1) to use a co-routine
- ** implementation?
- */
- if( i==0
- && (pTabList->nSrc==1
- || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
- ){
- /* Implement a co-routine that will return a single row of the result
- ** set on each invocation.
- */
- int addrTop = sqlite3VdbeCurrentAddr(v)+1;
-
- pItem->regReturn = ++pParse->nMem;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
- VdbeComment((v, "%s", pItem->pTab->zName));
- pItem->addrFillSub = addrTop;
- sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
- ExplainQueryPlan((pParse, 1, "CO-ROUTINE 0x%p", pSub));
- sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->nRowLogEst = pSub->nSelectRow;
- pItem->fg.viaCoroutine = 1;
- pItem->regResult = dest.iSdst;
- sqlite3VdbeEndCoroutine(v, pItem->regReturn);
- sqlite3VdbeJumpHere(v, addrTop-1);
- sqlite3ClearTempRegCache(pParse);
- }else{
- /* Generate a subroutine that will fill an ephemeral table with
- ** the content of this subquery. pItem->addrFillSub will point
- ** to the address of the generated subroutine. pItem->regReturn
- ** is a register allocated to hold the subroutine return address
- */
- int topAddr;
- int onceAddr = 0;
- int retAddr;
- struct SrcList_item *pPrior;
-
- assert( pItem->addrFillSub==0 );
- pItem->regReturn = ++pParse->nMem;
- topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
- pItem->addrFillSub = topAddr+1;
- if( pItem->fg.isCorrelated==0 ){
- /* If the subquery is not correlated and if we are not inside of
- ** a trigger, then we only need to compute the value of the subquery
- ** once. */
- onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
- }else{
- VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
- }
- pPrior = isSelfJoinView(pTabList, pItem);
- if( pPrior ){
- sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
- assert( pPrior->pSelect!=0 );
- pSub->nSelectRow = pPrior->pSelect->nSelectRow;
- }else{
- sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- ExplainQueryPlan((pParse, 1, "MATERIALIZE 0x%p", pSub));
- sqlite3Select(pParse, pSub, &dest);
- }
- pItem->pTab->nRowLogEst = pSub->nSelectRow;
- if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
- retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
- VdbeComment((v, "end %s", pItem->pTab->zName));
- sqlite3VdbeChangeP1(v, topAddr, retAddr);
- sqlite3ClearTempRegCache(pParse);
- }
- if( db->mallocFailed ) goto select_end;
- pParse->nHeight -= sqlite3SelectExprHeight(p);
- pParse->zAuthContext = zSavedAuthContext;
-#endif
- }
-
- /* Various elements of the SELECT copied into local variables for
- ** convenience */
- pEList = p->pEList;
- pWhere = p->pWhere;
- pGroupBy = p->pGroupBy;
- pHaving = p->pHaving;
- sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
-
-#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x400 ){
- SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
-
-#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
- if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
- && countOfViewOptimization(pParse, p)
- ){
- if( db->mallocFailed ) goto select_end;
- pEList = p->pEList;
- pTabList = p->pSrc;
- }
-#endif
-
- /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
- ** if the select-list is the same as the ORDER BY list, then this query
- ** can be rewritten as a GROUP BY. In other words, this:
- **
- ** SELECT DISTINCT xyz FROM ... ORDER BY xyz
- **
- ** is transformed to:
- **
- ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz
- **
- ** The second form is preferred as a single index (or temp-table) may be
- ** used for both the ORDER BY and DISTINCT processing. As originally
- ** written the query must use a temp-table for at least one of the ORDER
- ** BY and DISTINCT, and an index or separate temp-table for the other.
- */
- if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
- && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
- ){
- p->selFlags &= ~SF_Distinct;
- pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
- /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
- ** the sDistinct.isTnct is still set. Hence, isTnct represents the
- ** original setting of the SF_Distinct flag, not the current setting */
- assert( sDistinct.isTnct );
-
-#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x400 ){
- SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
- }
-
- /* If there is an ORDER BY clause, then create an ephemeral index to
- ** do the sorting. But this sorting ephemeral index might end up
- ** being unused if the data can be extracted in pre-sorted order.
- ** If that is the case, then the OP_OpenEphemeral instruction will be
- ** changed to an OP_Noop once we figure out that the sorting index is
- ** not needed. The sSort.addrSortIndex variable is used to facilitate
- ** that change.
- */
- if( sSort.pOrderBy ){
- KeyInfo *pKeyInfo;
- pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr);
- sSort.iECursor = pParse->nTab++;
- sSort.addrSortIndex =
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
- sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0,
- (char*)pKeyInfo, P4_KEYINFO
- );
- }else{
- sSort.addrSortIndex = -1;
- }
-
- /* If the output is destined for a temporary table, open that table.
- */
- if( pDest->eDest==SRT_EphemTab ){
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
- }
-
- /* Set the limiter.
- */
- iEnd = sqlite3VdbeMakeLabel(v);
- if( (p->selFlags & SF_FixedLimit)==0 ){
- p->nSelectRow = 320; /* 4 billion rows */
- }
- computeLimitRegisters(pParse, p, iEnd);
- if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
- sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
- sSort.sortFlags |= SORTFLAG_UseSorter;
- }
-
- /* Open an ephemeral index to use for the distinct set.
- */
- if( p->selFlags & SF_Distinct ){
- sDistinct.tabTnct = pParse->nTab++;
- sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
- sDistinct.tabTnct, 0, 0,
- (char*)keyInfoFromExprList(pParse, p->pEList,0,0),
- P4_KEYINFO);
- sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
- sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
- }else{
- sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
- }
-
- if( !isAgg && pGroupBy==0 ){
- /* No aggregate functions and no GROUP BY clause */
- u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
- assert( WHERE_USE_LIMIT==SF_FixedLimit );
- wctrlFlags |= p->selFlags & SF_FixedLimit;
-
- /* Begin the database scan. */
- SELECTTRACE(1,pParse,p,("WhereBegin\n"));
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
- p->pEList, wctrlFlags, p->nSelectRow);
- if( pWInfo==0 ) goto select_end;
- if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
- p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
- }
- if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
- sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
- }
- if( sSort.pOrderBy ){
- sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
- sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo);
- if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
- sSort.pOrderBy = 0;
- }
- }
-
- /* If sorting index that was created by a prior OP_OpenEphemeral
- ** instruction ended up not being needed, then change the OP_OpenEphemeral
- ** into an OP_Noop.
- */
- if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){
- sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
- }
-
- /* Use the standard inner loop. */
- assert( p->pEList==pEList );
- selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest,
- sqlite3WhereContinueLabel(pWInfo),
- sqlite3WhereBreakLabel(pWInfo));
-
- /* End the database scan loop.
- */
- sqlite3WhereEnd(pWInfo);
- }else{
- /* This case when there exist aggregate functions or a GROUP BY clause
- ** or both */
- NameContext sNC; /* Name context for processing aggregate information */
- int iAMem; /* First Mem address for storing current GROUP BY */
- int iBMem; /* First Mem address for previous GROUP BY */
- int iUseFlag; /* Mem address holding flag indicating that at least
- ** one row of the input to the aggregator has been
- ** processed */
- int iAbortFlag; /* Mem address which causes query abort if positive */
- int groupBySort; /* Rows come from source in GROUP BY order */
- int addrEnd; /* End of processing for this SELECT */
- int sortPTab = 0; /* Pseudotable used to decode sorting results */
- int sortOut = 0; /* Output register from the sorter */
- int orderByGrp = 0; /* True if the GROUP BY and ORDER BY are the same */
-
- /* Remove any and all aliases between the result set and the
- ** GROUP BY clause.
- */
- if( pGroupBy ){
- int k; /* Loop counter */
- struct ExprList_item *pItem; /* For looping over expression in a list */
-
- for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
- pItem->u.x.iAlias = 0;
- }
- for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
- pItem->u.x.iAlias = 0;
- }
- assert( 66==sqlite3LogEst(100) );
- if( p->nSelectRow>66 ) p->nSelectRow = 66;
- }else{
- assert( 0==sqlite3LogEst(1) );
- p->nSelectRow = 0;
- }
-
- /* If there is both a GROUP BY and an ORDER BY clause and they are
- ** identical, then it may be possible to disable the ORDER BY clause
- ** on the grounds that the GROUP BY will cause elements to come out
- ** in the correct order. It also may not - the GROUP BY might use a
- ** database index that causes rows to be grouped together as required
- ** but not actually sorted. Either way, record the fact that the
- ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
- ** variable. */
- if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
- orderByGrp = 1;
- }
-
- /* Create a label to jump to when we want to abort the query */
- addrEnd = sqlite3VdbeMakeLabel(v);
-
- /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
- ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
- ** SELECT statement.
- */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- sNC.pSrcList = pTabList;
- sNC.uNC.pAggInfo = &sAggInfo;
- VVA_ONLY( sNC.ncFlags = NC_UAggInfo; )
- sAggInfo.mnReg = pParse->nMem+1;
- sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
- sAggInfo.pGroupBy = pGroupBy;
- sqlite3ExprAnalyzeAggList(&sNC, pEList);
- sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
- if( pHaving ){
- if( pGroupBy ){
- assert( pWhere==p->pWhere );
- assert( pHaving==p->pHaving );
- assert( pGroupBy==p->pGroupBy );
- havingToWhere(pParse, p);
- pWhere = p->pWhere;
- }
- sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
- }
- sAggInfo.nAccumulator = sAggInfo.nColumn;
- if( p->pGroupBy==0 && p->pHaving==0 && sAggInfo.nFunc==1 ){
- minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy);
- }else{
- minMaxFlag = WHERE_ORDERBY_NORMAL;
- }
- for(i=0; i<sAggInfo.nFunc; i++){
- assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
- sNC.ncFlags |= NC_InAggFunc;
- sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
- sNC.ncFlags &= ~NC_InAggFunc;
- }
- sAggInfo.mxReg = pParse->nMem;
- if( db->mallocFailed ) goto select_end;
-#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x400 ){
- int ii;
- SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n"));
- sqlite3TreeViewSelect(0, p, 0);
- for(ii=0; ii<sAggInfo.nColumn; ii++){
- sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
- ii, sAggInfo.aCol[ii].iMem);
- sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
- }
- for(ii=0; ii<sAggInfo.nFunc; ii++){
- sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n",
- ii, sAggInfo.aFunc[ii].iMem);
- sqlite3TreeViewExpr(0, sAggInfo.aFunc[ii].pExpr, 0);
- }
- }
-#endif
-
-
- /* Processing for aggregates with GROUP BY is very different and
- ** much more complex than aggregates without a GROUP BY.
- */
- if( pGroupBy ){
- KeyInfo *pKeyInfo; /* Keying information for the group by clause */
- int addr1; /* A-vs-B comparision jump */
- int addrOutputRow; /* Start of subroutine that outputs a result row */
- int regOutputRow; /* Return address register for output subroutine */
- int addrSetAbort; /* Set the abort flag and return */
- int addrTopOfLoop; /* Top of the input loop */
- int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
- int addrReset; /* Subroutine for resetting the accumulator */
- int regReset; /* Return address register for reset subroutine */
-
- /* If there is a GROUP BY clause we might need a sorting index to
- ** implement it. Allocate that sorting index now. If it turns out
- ** that we do not need it after all, the OP_SorterOpen instruction
- ** will be converted into a Noop.
- */
- sAggInfo.sortingIdx = pParse->nTab++;
- pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn);
- addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
- sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
- 0, (char*)pKeyInfo, P4_KEYINFO);
-
- /* Initialize memory locations used by GROUP BY aggregate processing
- */
- iUseFlag = ++pParse->nMem;
- iAbortFlag = ++pParse->nMem;
- regOutputRow = ++pParse->nMem;
- addrOutputRow = sqlite3VdbeMakeLabel(v);
- regReset = ++pParse->nMem;
- addrReset = sqlite3VdbeMakeLabel(v);
- iAMem = pParse->nMem + 1;
- pParse->nMem += pGroupBy->nExpr;
- iBMem = pParse->nMem + 1;
- pParse->nMem += pGroupBy->nExpr;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
- VdbeComment((v, "clear abort flag"));
- sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
- VdbeComment((v, "indicate accumulator empty"));
- sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
-
- /* Begin a loop that will extract all source rows in GROUP BY order.
- ** This might involve two separate loops with an OP_Sort in between, or
- ** it might be a single loop that uses an index to extract information
- ** in the right order to begin with.
- */
- sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
- SELECTTRACE(1,pParse,p,("WhereBegin\n"));
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
- WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
- );
- if( pWInfo==0 ) goto select_end;
- if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
- /* The optimizer is able to deliver rows in group by order so
- ** we do not have to sort. The OP_OpenEphemeral table will be
- ** cancelled later because we still need to use the pKeyInfo
- */
- groupBySort = 0;
- }else{
- /* Rows are coming out in undetermined order. We have to push
- ** each row into a sorting index, terminate the first loop,
- ** then loop over the sorting index in order to get the output
- ** in sorted order
- */
- int regBase;
- int regRecord;
- int nCol;
- int nGroupBy;
-
- explainTempTable(pParse,
- (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
- "DISTINCT" : "GROUP BY");
-
- groupBySort = 1;
- nGroupBy = pGroupBy->nExpr;
- nCol = nGroupBy;
- j = nGroupBy;
- for(i=0; i<sAggInfo.nColumn; i++){
- if( sAggInfo.aCol[i].iSorterColumn>=j ){
- nCol++;
- j++;
- }
- }
- regBase = sqlite3GetTempRange(pParse, nCol);
- sqlite3ExprCacheClear(pParse);
- sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
- j = nGroupBy;
- for(i=0; i<sAggInfo.nColumn; i++){
- struct AggInfo_col *pCol = &sAggInfo.aCol[i];
- if( pCol->iSorterColumn>=j ){
- int r1 = j + regBase;
- sqlite3ExprCodeGetColumnToReg(pParse,
- pCol->pTab, pCol->iColumn, pCol->iTable, r1);
- j++;
- }
- }
- regRecord = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
- sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
- sqlite3ReleaseTempReg(pParse, regRecord);
- sqlite3ReleaseTempRange(pParse, regBase, nCol);
- sqlite3WhereEnd(pWInfo);
- sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
- sortOut = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
- sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
- VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
- sAggInfo.useSortingIdx = 1;
- sqlite3ExprCacheClear(pParse);
-
- }
-
- /* If the index or temporary table used by the GROUP BY sort
- ** will naturally deliver rows in the order required by the ORDER BY
- ** clause, cancel the ephemeral table open coded earlier.
- **
- ** This is an optimization - the correct answer should result regardless.
- ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to
- ** disable this optimization for testing purposes. */
- if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder)
- && (groupBySort || sqlite3WhereIsSorted(pWInfo))
- ){
- sSort.pOrderBy = 0;
- sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
- }
-
- /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
- ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
- ** Then compare the current GROUP BY terms against the GROUP BY terms
- ** from the previous row currently stored in a0, a1, a2...
- */
- addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
- sqlite3ExprCacheClear(pParse);
- if( groupBySort ){
- sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
- sortOut, sortPTab);
- }
- for(j=0; j<pGroupBy->nExpr; j++){
- if( groupBySort ){
- sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
- }else{
- sAggInfo.directMode = 1;
- sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
- }
- }
- sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
- (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
- addr1 = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v);
-
- /* Generate code that runs whenever the GROUP BY changes.
- ** Changes in the GROUP BY are detected by the previous code
- ** block. If there were no changes, this block is skipped.
- **
- ** This code copies current group by terms in b0,b1,b2,...
- ** over to a0,a1,a2. It then calls the output subroutine
- ** and resets the aggregate accumulator registers in preparation
- ** for the next GROUP BY batch.
- */
- sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
- sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
- VdbeComment((v, "output one row"));
- sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
- VdbeComment((v, "check abort flag"));
- sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
- VdbeComment((v, "reset accumulator"));
-
- /* Update the aggregate accumulators based on the content of
- ** the current row
- */
- sqlite3VdbeJumpHere(v, addr1);
- updateAccumulator(pParse, &sAggInfo);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
- VdbeComment((v, "indicate data in accumulator"));
-
- /* End of the loop
- */
- if( groupBySort ){
- sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
- VdbeCoverage(v);
- }else{
- sqlite3WhereEnd(pWInfo);
- sqlite3VdbeChangeToNoop(v, addrSortingIdx);
- }
-
- /* Output the final row of result
- */
- sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
- VdbeComment((v, "output final row"));
-
- /* Jump over the subroutines
- */
- sqlite3VdbeGoto(v, addrEnd);
-
- /* Generate a subroutine that outputs a single row of the result
- ** set. This subroutine first looks at the iUseFlag. If iUseFlag
- ** is less than or equal to zero, the subroutine is a no-op. If
- ** the processing calls for the query to abort, this subroutine
- ** increments the iAbortFlag memory location before returning in
- ** order to signal the caller to abort.
- */
- addrSetAbort = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
- VdbeComment((v, "set abort flag"));
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- sqlite3VdbeResolveLabel(v, addrOutputRow);
- addrOutputRow = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
- VdbeCoverage(v);
- VdbeComment((v, "Groupby result generator entry point"));
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- finalizeAggFunctions(pParse, &sAggInfo);
- sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
- selectInnerLoop(pParse, p, -1, &sSort,
- &sDistinct, pDest,
- addrOutputRow+1, addrSetAbort);
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- VdbeComment((v, "end groupby result generator"));
-
- /* Generate a subroutine that will reset the group-by accumulator
- */
- sqlite3VdbeResolveLabel(v, addrReset);
- resetAccumulator(pParse, &sAggInfo);
- sqlite3VdbeAddOp1(v, OP_Return, regReset);
-
- } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
- else {
-#ifndef SQLITE_OMIT_BTREECOUNT
- Table *pTab;
- if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
- /* If isSimpleCount() returns a pointer to a Table structure, then
- ** the SQL statement is of the form:
- **
- ** SELECT count(*) FROM <tbl>
- **
- ** where the Table structure returned represents table <tbl>.
- **
- ** This statement is so common that it is optimized specially. The
- ** OP_Count instruction is executed either on the intkey table that
- ** contains the data for table <tbl> or on one of its indexes. It
- ** is better to execute the op on an index, as indexes are almost
- ** always spread across less pages than their corresponding tables.
- */
- const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */
- Index *pIdx; /* Iterator variable */
- KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */
- Index *pBest = 0; /* Best index found so far */
- int iRoot = pTab->tnum; /* Root page of scanned b-tree */
-
- sqlite3CodeVerifySchema(pParse, iDb);
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
-
- /* Search for the index that has the lowest scan cost.
- **
- ** (2011-04-15) Do not do a full scan of an unordered index.
- **
- ** (2013-10-03) Do not count the entries in a partial index.
- **
- ** In practice the KeyInfo structure will not be used. It is only
- ** passed to keep OP_OpenRead happy.
- */
- if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->bUnordered==0
- && pIdx->szIdxRow<pTab->szTabRow
- && pIdx->pPartIdxWhere==0
- && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
- ){
- pBest = pIdx;
- }
- }
- if( pBest ){
- iRoot = pBest->tnum;
- pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest);
- }
-
- /* Open a read-only cursor, execute the OP_Count, close the cursor. */
- sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
- if( pKeyInfo ){
- sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
- }
- sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
- sqlite3VdbeAddOp1(v, OP_Close, iCsr);
- explainSimpleCount(pParse, pTab, pBest);
- }else
-#endif /* SQLITE_OMIT_BTREECOUNT */
- {
- /* This case runs if the aggregate has no GROUP BY clause. The
- ** processing is much simpler since there is only a single row
- ** of output.
- */
- assert( p->pGroupBy==0 );
- resetAccumulator(pParse, &sAggInfo);
-
- /* If this query is a candidate for the min/max optimization, then
- ** minMaxFlag will have been previously set to either
- ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will
- ** be an appropriate ORDER BY expression for the optimization.
- */
- assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
- assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );
-
- SELECTTRACE(1,pParse,p,("WhereBegin\n"));
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
- 0, minMaxFlag, 0);
- if( pWInfo==0 ){
- goto select_end;
- }
- updateAccumulator(pParse, &sAggInfo);
- if( sqlite3WhereIsOrdered(pWInfo)>0 ){
- sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
- VdbeComment((v, "%s() by index",
- (minMaxFlag==WHERE_ORDERBY_MIN?"min":"max")));
- }
- sqlite3WhereEnd(pWInfo);
- finalizeAggFunctions(pParse, &sAggInfo);
- }
-
- sSort.pOrderBy = 0;
- sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
- selectInnerLoop(pParse, p, -1, 0, 0,
- pDest, addrEnd, addrEnd);
- }
- sqlite3VdbeResolveLabel(v, addrEnd);
-
- } /* endif aggregate query */
-
- if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
- explainTempTable(pParse, "DISTINCT");
- }
-
- /* If there is an ORDER BY clause, then we need to sort the results
- ** and send them to the callback one by one.
- */
- if( sSort.pOrderBy ){
- explainTempTable(pParse,
- sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
- assert( p->pEList==pEList );
- generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
- }
-
- /* Jump here to skip this query
- */
- sqlite3VdbeResolveLabel(v, iEnd);
-
- /* The SELECT has been coded. If there is an error in the Parse structure,
- ** set the return code to 1. Otherwise 0. */
- rc = (pParse->nErr>0);
-
- /* Control jumps to here if an error is encountered above, or upon
- ** successful coding of the SELECT.
- */
-select_end:
- sqlite3ExprListDelete(db, pMinMaxOrderBy);
- sqlite3DbFree(db, sAggInfo.aCol);
- sqlite3DbFree(db, sAggInfo.aFunc);
-#if SELECTTRACE_ENABLED
- SELECTTRACE(0x1,pParse,p,("end processing\n"));
- if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
- sqlite3TreeViewSelect(0, p, 0);
- }
-#endif
- ExplainQueryPlanPop(pParse);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/shell.c.in b/chromium/third_party/sqlite/sqlite-src-3240000/src/shell.c.in
deleted file mode 100644
index b9d7cecbc70..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/shell.c.in
+++ /dev/null
@@ -1,8787 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains code to implement the "sqlite" command line
-** utility for accessing SQLite databases.
-*/
-#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
-/* This needs to come before any includes for MSVC compiler */
-#define _CRT_SECURE_NO_WARNINGS
-#endif
-
-/*
-** Warning pragmas copied from msvc.h in the core.
-*/
-#if defined(_MSC_VER)
-#pragma warning(disable : 4054)
-#pragma warning(disable : 4055)
-#pragma warning(disable : 4100)
-#pragma warning(disable : 4127)
-#pragma warning(disable : 4130)
-#pragma warning(disable : 4152)
-#pragma warning(disable : 4189)
-#pragma warning(disable : 4206)
-#pragma warning(disable : 4210)
-#pragma warning(disable : 4232)
-#pragma warning(disable : 4244)
-#pragma warning(disable : 4305)
-#pragma warning(disable : 4306)
-#pragma warning(disable : 4702)
-#pragma warning(disable : 4706)
-#endif /* defined(_MSC_VER) */
-
-/*
-** No support for loadable extensions in VxWorks.
-*/
-#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
-# define SQLITE_OMIT_LOAD_EXTENSION 1
-#endif
-
-/*
-** Enable large-file support for fopen() and friends on unix.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE 1
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <assert.h>
-#include "sqlite3.h"
-typedef sqlite3_int64 i64;
-typedef sqlite3_uint64 u64;
-typedef unsigned char u8;
-#if SQLITE_USER_AUTHENTICATION
-# include "sqlite3userauth.h"
-#endif
-#include <ctype.h>
-#include <stdarg.h>
-
-#if !defined(_WIN32) && !defined(WIN32)
-# include <signal.h>
-# if !defined(__RTP__) && !defined(_WRS_KERNEL)
-# include <pwd.h>
-# endif
-#endif
-#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
-# include <unistd.h>
-# include <dirent.h>
-# if defined(__MINGW32__)
-# define DIRENT dirent
-# ifndef S_ISLNK
-# define S_ISLNK(mode) (0)
-# endif
-# endif
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#if HAVE_READLINE
-# include <readline/readline.h>
-# include <readline/history.h>
-#endif
-
-#if HAVE_EDITLINE
-# include <editline/readline.h>
-#endif
-
-#if HAVE_EDITLINE || HAVE_READLINE
-
-# define shell_add_history(X) add_history(X)
-# define shell_read_history(X) read_history(X)
-# define shell_write_history(X) write_history(X)
-# define shell_stifle_history(X) stifle_history(X)
-# define shell_readline(X) readline(X)
-
-#elif HAVE_LINENOISE
-
-# include "linenoise.h"
-# define shell_add_history(X) linenoiseHistoryAdd(X)
-# define shell_read_history(X) linenoiseHistoryLoad(X)
-# define shell_write_history(X) linenoiseHistorySave(X)
-# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
-# define shell_readline(X) linenoise(X)
-
-#else
-
-# define shell_read_history(X)
-# define shell_write_history(X)
-# define shell_stifle_history(X)
-
-# define SHELL_USE_LOCAL_GETLINE 1
-#endif
-
-
-#if defined(_WIN32) || defined(WIN32)
-# include <io.h>
-# include <fcntl.h>
-# define isatty(h) _isatty(h)
-# ifndef access
-# define access(f,m) _access((f),(m))
-# endif
-# ifndef unlink
-# define unlink _unlink
-# endif
-# undef popen
-# define popen _popen
-# undef pclose
-# define pclose _pclose
-#else
- /* Make sure isatty() has a prototype. */
- extern int isatty(int);
-
-# if !defined(__RTP__) && !defined(_WRS_KERNEL)
- /* popen and pclose are not C89 functions and so are
- ** sometimes omitted from the <stdio.h> header */
- extern FILE *popen(const char*,const char*);
- extern int pclose(FILE*);
-# else
-# define SQLITE_OMIT_POPEN 1
-# endif
-#endif
-
-#if defined(_WIN32_WCE)
-/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
- * thus we always assume that we have a console. That can be
- * overridden with the -batch command line option.
- */
-#define isatty(x) 1
-#endif
-
-/* ctype macros that work with signed characters */
-#define IsSpace(X) isspace((unsigned char)X)
-#define IsDigit(X) isdigit((unsigned char)X)
-#define ToLower(X) (char)tolower((unsigned char)X)
-
-#if defined(_WIN32) || defined(WIN32)
-#include <windows.h>
-
-/* string conversion routines only needed on Win32 */
-extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
-extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
-extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
-extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
-#endif
-
-/* On Windows, we normally run with output mode of TEXT so that \n characters
-** are automatically translated into \r\n. However, this behavior needs
-** to be disabled in some cases (ex: when generating CSV output and when
-** rendering quoted strings that contain \n characters). The following
-** routines take care of that.
-*/
-#if defined(_WIN32) || defined(WIN32)
-static void setBinaryMode(FILE *file, int isOutput){
- if( isOutput ) fflush(file);
- _setmode(_fileno(file), _O_BINARY);
-}
-static void setTextMode(FILE *file, int isOutput){
- if( isOutput ) fflush(file);
- _setmode(_fileno(file), _O_TEXT);
-}
-#else
-# define setBinaryMode(X,Y)
-# define setTextMode(X,Y)
-#endif
-
-
-/* True if the timer is enabled */
-static int enableTimer = 0;
-
-/* Return the current wall-clock time */
-static sqlite3_int64 timeOfDay(void){
- static sqlite3_vfs *clockVfs = 0;
- sqlite3_int64 t;
- if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
- if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
- clockVfs->xCurrentTimeInt64(clockVfs, &t);
- }else{
- double r;
- clockVfs->xCurrentTime(clockVfs, &r);
- t = (sqlite3_int64)(r*86400000.0);
- }
- return t;
-}
-
-#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
-#include <sys/time.h>
-#include <sys/resource.h>
-
-/* VxWorks does not support getrusage() as far as we can determine */
-#if defined(_WRS_KERNEL) || defined(__RTP__)
-struct rusage {
- struct timeval ru_utime; /* user CPU time used */
- struct timeval ru_stime; /* system CPU time used */
-};
-#define getrusage(A,B) memset(B,0,sizeof(*B))
-#endif
-
-/* Saved resource information for the beginning of an operation */
-static struct rusage sBegin; /* CPU time at start */
-static sqlite3_int64 iBegin; /* Wall-clock time at start */
-
-/*
-** Begin timing an operation
-*/
-static void beginTimer(void){
- if( enableTimer ){
- getrusage(RUSAGE_SELF, &sBegin);
- iBegin = timeOfDay();
- }
-}
-
-/* Return the difference of two time_structs in seconds */
-static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
- return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
- (double)(pEnd->tv_sec - pStart->tv_sec);
-}
-
-/*
-** Print the timing results.
-*/
-static void endTimer(void){
- if( enableTimer ){
- sqlite3_int64 iEnd = timeOfDay();
- struct rusage sEnd;
- getrusage(RUSAGE_SELF, &sEnd);
- printf("Run Time: real %.3f user %f sys %f\n",
- (iEnd - iBegin)*0.001,
- timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
- timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
- }
-}
-
-#define BEGIN_TIMER beginTimer()
-#define END_TIMER endTimer()
-#define HAS_TIMER 1
-
-#elif (defined(_WIN32) || defined(WIN32))
-
-/* Saved resource information for the beginning of an operation */
-static HANDLE hProcess;
-static FILETIME ftKernelBegin;
-static FILETIME ftUserBegin;
-static sqlite3_int64 ftWallBegin;
-typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
- LPFILETIME, LPFILETIME);
-static GETPROCTIMES getProcessTimesAddr = NULL;
-
-/*
-** Check to see if we have timer support. Return 1 if necessary
-** support found (or found previously).
-*/
-static int hasTimer(void){
- if( getProcessTimesAddr ){
- return 1;
- } else {
- /* GetProcessTimes() isn't supported in WIN95 and some other Windows
- ** versions. See if the version we are running on has it, and if it
- ** does, save off a pointer to it and the current process handle.
- */
- hProcess = GetCurrentProcess();
- if( hProcess ){
- HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
- if( NULL != hinstLib ){
- getProcessTimesAddr =
- (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
- if( NULL != getProcessTimesAddr ){
- return 1;
- }
- FreeLibrary(hinstLib);
- }
- }
- }
- return 0;
-}
-
-/*
-** Begin timing an operation
-*/
-static void beginTimer(void){
- if( enableTimer && getProcessTimesAddr ){
- FILETIME ftCreation, ftExit;
- getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
- &ftKernelBegin,&ftUserBegin);
- ftWallBegin = timeOfDay();
- }
-}
-
-/* Return the difference of two FILETIME structs in seconds */
-static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
- sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
- sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
- return (double) ((i64End - i64Start) / 10000000.0);
-}
-
-/*
-** Print the timing results.
-*/
-static void endTimer(void){
- if( enableTimer && getProcessTimesAddr){
- FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
- sqlite3_int64 ftWallEnd = timeOfDay();
- getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
- printf("Run Time: real %.3f user %f sys %f\n",
- (ftWallEnd - ftWallBegin)*0.001,
- timeDiff(&ftUserBegin, &ftUserEnd),
- timeDiff(&ftKernelBegin, &ftKernelEnd));
- }
-}
-
-#define BEGIN_TIMER beginTimer()
-#define END_TIMER endTimer()
-#define HAS_TIMER hasTimer()
-
-#else
-#define BEGIN_TIMER
-#define END_TIMER
-#define HAS_TIMER 0
-#endif
-
-/*
-** Used to prevent warnings about unused parameters
-*/
-#define UNUSED_PARAMETER(x) (void)(x)
-
-/*
-** Number of elements in an array
-*/
-#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
-
-/*
-** If the following flag is set, then command execution stops
-** at an error if we are not interactive.
-*/
-static int bail_on_error = 0;
-
-/*
-** Threat stdin as an interactive input if the following variable
-** is true. Otherwise, assume stdin is connected to a file or pipe.
-*/
-static int stdin_is_interactive = 1;
-
-/*
-** On Windows systems we have to know if standard output is a console
-** in order to translate UTF-8 into MBCS. The following variable is
-** true if translation is required.
-*/
-static int stdout_is_console = 1;
-
-/*
-** The following is the open SQLite database. We make a pointer
-** to this database a static variable so that it can be accessed
-** by the SIGINT handler to interrupt database processing.
-*/
-static sqlite3 *globalDb = 0;
-
-/*
-** True if an interrupt (Control-C) has been received.
-*/
-static volatile int seenInterrupt = 0;
-
-/*
-** This is the name of our program. It is set in main(), used
-** in a number of other places, mostly for error messages.
-*/
-static char *Argv0;
-
-/*
-** Prompt strings. Initialized in main. Settable with
-** .prompt main continue
-*/
-static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
-static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
-
-/*
-** Render output like fprintf(). Except, if the output is going to the
-** console and if this is running on a Windows machine, translate the
-** output from UTF-8 into MBCS.
-*/
-#if defined(_WIN32) || defined(WIN32)
-void utf8_printf(FILE *out, const char *zFormat, ...){
- va_list ap;
- va_start(ap, zFormat);
- if( stdout_is_console && (out==stdout || out==stderr) ){
- char *z1 = sqlite3_vmprintf(zFormat, ap);
- char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
- sqlite3_free(z1);
- fputs(z2, out);
- sqlite3_free(z2);
- }else{
- vfprintf(out, zFormat, ap);
- }
- va_end(ap);
-}
-#elif !defined(utf8_printf)
-# define utf8_printf fprintf
-#endif
-
-/*
-** Render output like fprintf(). This should not be used on anything that
-** includes string formatting (e.g. "%s").
-*/
-#if !defined(raw_printf)
-# define raw_printf fprintf
-#endif
-
-/* Indicate out-of-memory and exit. */
-static void shell_out_of_memory(void){
- raw_printf(stderr,"Error: out of memory\n");
- exit(1);
-}
-
-/*
-** Write I/O traces to the following stream.
-*/
-#ifdef SQLITE_ENABLE_IOTRACE
-static FILE *iotrace = 0;
-#endif
-
-/*
-** This routine works like printf in that its first argument is a
-** format string and subsequent arguments are values to be substituted
-** in place of % fields. The result of formatting this string
-** is written to iotrace.
-*/
-#ifdef SQLITE_ENABLE_IOTRACE
-static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
- va_list ap;
- char *z;
- if( iotrace==0 ) return;
- va_start(ap, zFormat);
- z = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- utf8_printf(iotrace, "%s", z);
- sqlite3_free(z);
-}
-#endif
-
-/*
-** Output string zUtf to stream pOut as w characters. If w is negative,
-** then right-justify the text. W is the width in UTF-8 characters, not
-** in bytes. This is different from the %*.*s specification in printf
-** since with %*.*s the width is measured in bytes, not characters.
-*/
-static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
- int i;
- int n;
- int aw = w<0 ? -w : w;
- char zBuf[1000];
- if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
- for(i=n=0; zUtf[i]; i++){
- if( (zUtf[i]&0xc0)!=0x80 ){
- n++;
- if( n==aw ){
- do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
- break;
- }
- }
- }
- if( n>=aw ){
- utf8_printf(pOut, "%.*s", i, zUtf);
- }else if( w<0 ){
- utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
- }else{
- utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
- }
-}
-
-
-/*
-** Determines if a string is a number of not.
-*/
-static int isNumber(const char *z, int *realnum){
- if( *z=='-' || *z=='+' ) z++;
- if( !IsDigit(*z) ){
- return 0;
- }
- z++;
- if( realnum ) *realnum = 0;
- while( IsDigit(*z) ){ z++; }
- if( *z=='.' ){
- z++;
- if( !IsDigit(*z) ) return 0;
- while( IsDigit(*z) ){ z++; }
- if( realnum ) *realnum = 1;
- }
- if( *z=='e' || *z=='E' ){
- z++;
- if( *z=='+' || *z=='-' ) z++;
- if( !IsDigit(*z) ) return 0;
- while( IsDigit(*z) ){ z++; }
- if( realnum ) *realnum = 1;
- }
- return *z==0;
-}
-
-/*
-** Compute a string length that is limited to what can be stored in
-** lower 30 bits of a 32-bit signed integer.
-*/
-static int strlen30(const char *z){
- const char *z2 = z;
- while( *z2 ){ z2++; }
- return 0x3fffffff & (int)(z2 - z);
-}
-
-/*
-** Return the length of a string in characters. Multibyte UTF8 characters
-** count as a single character.
-*/
-static int strlenChar(const char *z){
- int n = 0;
- while( *z ){
- if( (0xc0&*(z++))!=0x80 ) n++;
- }
- return n;
-}
-
-/*
-** This routine reads a line of text from FILE in, stores
-** the text in memory obtained from malloc() and returns a pointer
-** to the text. NULL is returned at end of file, or if malloc()
-** fails.
-**
-** If zLine is not NULL then it is a malloced buffer returned from
-** a previous call to this routine that may be reused.
-*/
-static char *local_getline(char *zLine, FILE *in){
- int nLine = zLine==0 ? 0 : 100;
- int n = 0;
-
- while( 1 ){
- if( n+100>nLine ){
- nLine = nLine*2 + 100;
- zLine = realloc(zLine, nLine);
- if( zLine==0 ) return 0;
- }
- if( fgets(&zLine[n], nLine - n, in)==0 ){
- if( n==0 ){
- free(zLine);
- return 0;
- }
- zLine[n] = 0;
- break;
- }
- while( zLine[n] ) n++;
- if( n>0 && zLine[n-1]=='\n' ){
- n--;
- if( n>0 && zLine[n-1]=='\r' ) n--;
- zLine[n] = 0;
- break;
- }
- }
-#if defined(_WIN32) || defined(WIN32)
- /* For interactive input on Windows systems, translate the
- ** multi-byte characterset characters into UTF-8. */
- if( stdin_is_interactive && in==stdin ){
- char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
- if( zTrans ){
- int nTrans = strlen30(zTrans)+1;
- if( nTrans>nLine ){
- zLine = realloc(zLine, nTrans);
- if( zLine==0 ){
- sqlite3_free(zTrans);
- return 0;
- }
- }
- memcpy(zLine, zTrans, nTrans);
- sqlite3_free(zTrans);
- }
- }
-#endif /* defined(_WIN32) || defined(WIN32) */
- return zLine;
-}
-
-/*
-** Retrieve a single line of input text.
-**
-** If in==0 then read from standard input and prompt before each line.
-** If isContinuation is true, then a continuation prompt is appropriate.
-** If isContinuation is zero, then the main prompt should be used.
-**
-** If zPrior is not NULL then it is a buffer from a prior call to this
-** routine that can be reused.
-**
-** The result is stored in space obtained from malloc() and must either
-** be freed by the caller or else passed back into this routine via the
-** zPrior argument for reuse.
-*/
-static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
- char *zPrompt;
- char *zResult;
- if( in!=0 ){
- zResult = local_getline(zPrior, in);
- }else{
- zPrompt = isContinuation ? continuePrompt : mainPrompt;
-#if SHELL_USE_LOCAL_GETLINE
- printf("%s", zPrompt);
- fflush(stdout);
- zResult = local_getline(zPrior, stdin);
-#else
- free(zPrior);
- zResult = shell_readline(zPrompt);
- if( zResult && *zResult ) shell_add_history(zResult);
-#endif
- }
- return zResult;
-}
-
-
-/*
-** Return the value of a hexadecimal digit. Return -1 if the input
-** is not a hex digit.
-*/
-static int hexDigitValue(char c){
- if( c>='0' && c<='9' ) return c - '0';
- if( c>='a' && c<='f' ) return c - 'a' + 10;
- if( c>='A' && c<='F' ) return c - 'A' + 10;
- return -1;
-}
-
-/*
-** Interpret zArg as an integer value, possibly with suffixes.
-*/
-static sqlite3_int64 integerValue(const char *zArg){
- sqlite3_int64 v = 0;
- static const struct { char *zSuffix; int iMult; } aMult[] = {
- { "KiB", 1024 },
- { "MiB", 1024*1024 },
- { "GiB", 1024*1024*1024 },
- { "KB", 1000 },
- { "MB", 1000000 },
- { "GB", 1000000000 },
- { "K", 1000 },
- { "M", 1000000 },
- { "G", 1000000000 },
- };
- int i;
- int isNeg = 0;
- if( zArg[0]=='-' ){
- isNeg = 1;
- zArg++;
- }else if( zArg[0]=='+' ){
- zArg++;
- }
- if( zArg[0]=='0' && zArg[1]=='x' ){
- int x;
- zArg += 2;
- while( (x = hexDigitValue(zArg[0]))>=0 ){
- v = (v<<4) + x;
- zArg++;
- }
- }else{
- while( IsDigit(zArg[0]) ){
- v = v*10 + zArg[0] - '0';
- zArg++;
- }
- }
- for(i=0; i<ArraySize(aMult); i++){
- if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
- v *= aMult[i].iMult;
- break;
- }
- }
- return isNeg? -v : v;
-}
-
-/*
-** A variable length string to which one can append text.
-*/
-typedef struct ShellText ShellText;
-struct ShellText {
- char *z;
- int n;
- int nAlloc;
-};
-
-/*
-** Initialize and destroy a ShellText object
-*/
-static void initText(ShellText *p){
- memset(p, 0, sizeof(*p));
-}
-static void freeText(ShellText *p){
- free(p->z);
- initText(p);
-}
-
-/* zIn is either a pointer to a NULL-terminated string in memory obtained
-** from malloc(), or a NULL pointer. The string pointed to by zAppend is
-** added to zIn, and the result returned in memory obtained from malloc().
-** zIn, if it was not NULL, is freed.
-**
-** If the third argument, quote, is not '\0', then it is used as a
-** quote character for zAppend.
-*/
-static void appendText(ShellText *p, char const *zAppend, char quote){
- int len;
- int i;
- int nAppend = strlen30(zAppend);
-
- len = nAppend+p->n+1;
- if( quote ){
- len += 2;
- for(i=0; i<nAppend; i++){
- if( zAppend[i]==quote ) len++;
- }
- }
-
- if( p->n+len>=p->nAlloc ){
- p->nAlloc = p->nAlloc*2 + len + 20;
- p->z = realloc(p->z, p->nAlloc);
- if( p->z==0 ){
- memset(p, 0, sizeof(*p));
- return;
- }
- }
-
- if( quote ){
- char *zCsr = p->z+p->n;
- *zCsr++ = quote;
- for(i=0; i<nAppend; i++){
- *zCsr++ = zAppend[i];
- if( zAppend[i]==quote ) *zCsr++ = quote;
- }
- *zCsr++ = quote;
- p->n = (int)(zCsr - p->z);
- *zCsr = '\0';
- }else{
- memcpy(p->z+p->n, zAppend, nAppend);
- p->n += nAppend;
- p->z[p->n] = '\0';
- }
-}
-
-/*
-** Attempt to determine if identifier zName needs to be quoted, either
-** because it contains non-alphanumeric characters, or because it is an
-** SQLite keyword. Be conservative in this estimate: When in doubt assume
-** that quoting is required.
-**
-** Return '"' if quoting is required. Return 0 if no quoting is required.
-*/
-static char quoteChar(const char *zName){
- int i;
- if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
- for(i=0; zName[i]; i++){
- if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
- }
- return sqlite3_keyword_check(zName, i) ? '"' : 0;
-}
-
-/*
-** Construct a fake object name and column list to describe the structure
-** of the view, virtual table, or table valued function zSchema.zName.
-*/
-static char *shellFakeSchema(
- sqlite3 *db, /* The database connection containing the vtab */
- const char *zSchema, /* Schema of the database holding the vtab */
- const char *zName /* The name of the virtual table */
-){
- sqlite3_stmt *pStmt = 0;
- char *zSql;
- ShellText s;
- char cQuote;
- char *zDiv = "(";
- int nRow = 0;
-
- zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
- zSchema ? zSchema : "main", zName);
- sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- initText(&s);
- if( zSchema ){
- cQuote = quoteChar(zSchema);
- if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
- appendText(&s, zSchema, cQuote);
- appendText(&s, ".", 0);
- }
- cQuote = quoteChar(zName);
- appendText(&s, zName, cQuote);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
- nRow++;
- appendText(&s, zDiv, 0);
- zDiv = ",";
- cQuote = quoteChar(zCol);
- appendText(&s, zCol, cQuote);
- }
- appendText(&s, ")", 0);
- sqlite3_finalize(pStmt);
- if( nRow==0 ){
- freeText(&s);
- s.z = 0;
- }
- return s.z;
-}
-
-/*
-** SQL function: shell_module_schema(X)
-**
-** Return a fake schema for the table-valued function or eponymous virtual
-** table X.
-*/
-static void shellModuleSchema(
- sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal
-){
- const char *zName = (const char*)sqlite3_value_text(apVal[0]);
- char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
- UNUSED_PARAMETER(nVal);
- if( zFake ){
- sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
- -1, sqlite3_free);
- free(zFake);
- }
-}
-
-/*
-** SQL function: shell_add_schema(S,X)
-**
-** Add the schema name X to the CREATE statement in S and return the result.
-** Examples:
-**
-** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
-**
-** Also works on
-**
-** CREATE INDEX
-** CREATE UNIQUE INDEX
-** CREATE VIEW
-** CREATE TRIGGER
-** CREATE VIRTUAL TABLE
-**
-** This UDF is used by the .schema command to insert the schema name of
-** attached databases into the middle of the sqlite_master.sql field.
-*/
-static void shellAddSchemaName(
- sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal
-){
- static const char *aPrefix[] = {
- "TABLE",
- "INDEX",
- "UNIQUE INDEX",
- "VIEW",
- "TRIGGER",
- "VIRTUAL TABLE"
- };
- int i = 0;
- const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
- const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
- const char *zName = (const char*)sqlite3_value_text(apVal[2]);
- sqlite3 *db = sqlite3_context_db_handle(pCtx);
- UNUSED_PARAMETER(nVal);
- if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
- for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
- int n = strlen30(aPrefix[i]);
- if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
- char *z = 0;
- char *zFake = 0;
- if( zSchema ){
- char cQuote = quoteChar(zSchema);
- if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
- z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
- }else{
- z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
- }
- }
- if( zName
- && aPrefix[i][0]=='V'
- && (zFake = shellFakeSchema(db, zSchema, zName))!=0
- ){
- if( z==0 ){
- z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
- }else{
- z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
- }
- free(zFake);
- }
- if( z ){
- sqlite3_result_text(pCtx, z, -1, sqlite3_free);
- return;
- }
- }
- }
- }
- sqlite3_result_value(pCtx, apVal[0]);
-}
-
-/*
-** The source code for several run-time loadable extensions is inserted
-** below by the ../tool/mkshellc.tcl script. Before processing that included
-** code, we need to override some macros to make the included program code
-** work here in the middle of this regular program.
-*/
-#define SQLITE_EXTENSION_INIT1
-#define SQLITE_EXTENSION_INIT2(X) (void)(X)
-
-#if defined(_WIN32) && defined(_MSC_VER)
-INCLUDE test_windirent.h
-INCLUDE test_windirent.c
-#define dirent DIRENT
-#endif
-INCLUDE ../ext/misc/shathree.c
-INCLUDE ../ext/misc/fileio.c
-INCLUDE ../ext/misc/completion.c
-INCLUDE ../ext/misc/appendvfs.c
-#ifdef SQLITE_HAVE_ZLIB
-INCLUDE ../ext/misc/zipfile.c
-INCLUDE ../ext/misc/sqlar.c
-#endif
-INCLUDE ../ext/expert/sqlite3expert.h
-INCLUDE ../ext/expert/sqlite3expert.c
-
-#if defined(SQLITE_ENABLE_SESSION)
-/*
-** State information for a single open session
-*/
-typedef struct OpenSession OpenSession;
-struct OpenSession {
- char *zName; /* Symbolic name for this session */
- int nFilter; /* Number of xFilter rejection GLOB patterns */
- char **azFilter; /* Array of xFilter rejection GLOB patterns */
- sqlite3_session *p; /* The open session */
-};
-#endif
-
-/*
-** Shell output mode information from before ".explain on",
-** saved so that it can be restored by ".explain off"
-*/
-typedef struct SavedModeInfo SavedModeInfo;
-struct SavedModeInfo {
- int valid; /* Is there legit data in here? */
- int mode; /* Mode prior to ".explain on" */
- int showHeader; /* The ".header" setting prior to ".explain on" */
- int colWidth[100]; /* Column widths prior to ".explain on" */
-};
-
-typedef struct ExpertInfo ExpertInfo;
-struct ExpertInfo {
- sqlite3expert *pExpert;
- int bVerbose;
-};
-
-/* A single line in the EQP output */
-typedef struct EQPGraphRow EQPGraphRow;
-struct EQPGraphRow {
- int iEqpId; /* ID for this row */
- int iParentId; /* ID of the parent row */
- EQPGraphRow *pNext; /* Next row in sequence */
- char zText[1]; /* Text to display for this row */
-};
-
-/* All EQP output is collected into an instance of the following */
-typedef struct EQPGraph EQPGraph;
-struct EQPGraph {
- EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
- EQPGraphRow *pLast; /* Last element of the pRow list */
- char zPrefix[100]; /* Graph prefix */
-};
-
-/*
-** State information about the database connection is contained in an
-** instance of the following structure.
-*/
-typedef struct ShellState ShellState;
-struct ShellState {
- sqlite3 *db; /* The database */
- u8 autoExplain; /* Automatically turn on .explain mode */
- u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
- u8 autoEQPtest; /* autoEQP is in test mode */
- u8 statsOn; /* True to display memory stats before each finalize */
- u8 scanstatsOn; /* True to display scan stats before each finalize */
- u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
- u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
- u8 nEqpLevel; /* Depth of the EQP output graph */
- unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
- int outCount; /* Revert to stdout when reaching zero */
- int cnt; /* Number of records displayed so far */
- FILE *out; /* Write results here */
- FILE *traceOut; /* Output for sqlite3_trace() */
- int nErr; /* Number of errors seen */
- int mode; /* An output mode setting */
- int modePrior; /* Saved mode */
- int cMode; /* temporary output mode for the current query */
- int normalMode; /* Output mode before ".explain on" */
- int writableSchema; /* True if PRAGMA writable_schema=ON */
- int showHeader; /* True to show column names in List or Column mode */
- int nCheck; /* Number of ".check" commands run */
- unsigned shellFlgs; /* Various flags */
- char *zDestTable; /* Name of destination table when MODE_Insert */
- char *zTempFile; /* Temporary file that might need deleting */
- char zTestcase[30]; /* Name of current test case */
- char colSeparator[20]; /* Column separator character for several modes */
- char rowSeparator[20]; /* Row separator character for MODE_Ascii */
- char colSepPrior[20]; /* Saved column separator */
- char rowSepPrior[20]; /* Saved row separator */
- int colWidth[100]; /* Requested width of each column when in column mode*/
- int actualWidth[100]; /* Actual width of each column */
- char nullValue[20]; /* The text to print when a NULL comes back from
- ** the database */
- char outfile[FILENAME_MAX]; /* Filename for *out */
- const char *zDbFilename; /* name of the database file */
- char *zFreeOnClose; /* Filename to free when closing */
- const char *zVfs; /* Name of VFS to use */
- sqlite3_stmt *pStmt; /* Current statement if any. */
- FILE *pLog; /* Write log output here */
- int *aiIndent; /* Array of indents used in MODE_Explain */
- int nIndent; /* Size of array aiIndent[] */
- int iIndent; /* Index of current op in aiIndent[] */
- EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
-#if defined(SQLITE_ENABLE_SESSION)
- int nSession; /* Number of active sessions */
- OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
-#endif
- ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
-};
-
-
-/* Allowed values for ShellState.autoEQP
-*/
-#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
-#define AUTOEQP_on 1 /* Automatic EQP is on */
-#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
-#define AUTOEQP_full 3 /* Show full EXPLAIN */
-
-/* Allowed values for ShellState.openMode
-*/
-#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
-#define SHELL_OPEN_NORMAL 1 /* Normal database file */
-#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
-#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
-#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
-
-/*
-** These are the allowed shellFlgs values
-*/
-#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
-#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
-#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
-#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
-#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
-#define SHFLG_CountChanges 0x00000020 /* .changes setting */
-#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
-
-/*
-** Macros for testing and setting shellFlgs
-*/
-#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
-#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
-#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
-
-/*
-** These are the allowed modes.
-*/
-#define MODE_Line 0 /* One column per line. Blank line between records */
-#define MODE_Column 1 /* One record per line in neat columns */
-#define MODE_List 2 /* One record per line with a separator */
-#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
-#define MODE_Html 4 /* Generate an XHTML table */
-#define MODE_Insert 5 /* Generate SQL "insert" statements */
-#define MODE_Quote 6 /* Quote values as for SQL */
-#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
-#define MODE_Csv 8 /* Quote strings, numbers are plain */
-#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
-#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
-#define MODE_Pretty 11 /* Pretty-print schemas */
-#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
-
-static const char *modeDescr[] = {
- "line",
- "column",
- "list",
- "semi",
- "html",
- "insert",
- "quote",
- "tcl",
- "csv",
- "explain",
- "ascii",
- "prettyprint",
- "eqp"
-};
-
-/*
-** These are the column/row/line separators used by the various
-** import/export modes.
-*/
-#define SEP_Column "|"
-#define SEP_Row "\n"
-#define SEP_Tab "\t"
-#define SEP_Space " "
-#define SEP_Comma ","
-#define SEP_CrLf "\r\n"
-#define SEP_Unit "\x1F"
-#define SEP_Record "\x1E"
-
-/*
-** A callback for the sqlite3_log() interface.
-*/
-static void shellLog(void *pArg, int iErrCode, const char *zMsg){
- ShellState *p = (ShellState*)pArg;
- if( p->pLog==0 ) return;
- utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
- fflush(p->pLog);
-}
-
-/*
-** SQL function: shell_putsnl(X)
-**
-** Write the text X to the screen (or whatever output is being directed)
-** adding a newline at the end, and then return X.
-*/
-static void shellPutsFunc(
- sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal
-){
- ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
- (void)nVal;
- utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
- sqlite3_result_value(pCtx, apVal[0]);
-}
-
-/*
-** SQL function: edit(VALUE)
-** edit(VALUE,EDITOR)
-**
-** These steps:
-**
-** (1) Write VALUE into a temporary file.
-** (2) Run program EDITOR on that temporary file.
-** (3) Read the temporary file back and return its content as the result.
-** (4) Delete the temporary file
-**
-** If the EDITOR argument is omitted, use the value in the VISUAL
-** environment variable. If still there is no EDITOR, through an error.
-**
-** Also throw an error if the EDITOR program returns a non-zero exit code.
-*/
-#ifndef SQLITE_NOHAVE_SYSTEM
-static void editFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zEditor;
- char *zTempFile = 0;
- sqlite3 *db;
- char *zCmd = 0;
- int bBin;
- int rc;
- FILE *f = 0;
- sqlite3_int64 sz;
- sqlite3_int64 x;
- unsigned char *p = 0;
-
- if( argc==2 ){
- zEditor = (const char*)sqlite3_value_text(argv[1]);
- }else{
- zEditor = getenv("VISUAL");
- }
- if( zEditor==0 ){
- sqlite3_result_error(context, "no editor for edit()", -1);
- return;
- }
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
- sqlite3_result_error(context, "NULL input to edit()", -1);
- return;
- }
- db = sqlite3_context_db_handle(context);
- zTempFile = 0;
- sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
- if( zTempFile==0 ){
- sqlite3_uint64 r = 0;
- sqlite3_randomness(sizeof(r), &r);
- zTempFile = sqlite3_mprintf("temp%llx", r);
- if( zTempFile==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- }
- bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
- f = fopen(zTempFile, bBin ? "wb" : "w");
- if( f==0 ){
- sqlite3_result_error(context, "edit() cannot open temp file", -1);
- goto edit_func_end;
- }
- sz = sqlite3_value_bytes(argv[0]);
- if( bBin ){
- x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f);
- }else{
- x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f);
- }
- fclose(f);
- f = 0;
- if( x!=sz ){
- sqlite3_result_error(context, "edit() could not write the whole file", -1);
- goto edit_func_end;
- }
- zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
- if( zCmd==0 ){
- sqlite3_result_error_nomem(context);
- goto edit_func_end;
- }
- rc = system(zCmd);
- sqlite3_free(zCmd);
- if( rc ){
- sqlite3_result_error(context, "EDITOR returned non-zero", -1);
- goto edit_func_end;
- }
- f = fopen(zTempFile, bBin ? "rb" : "r");
- if( f==0 ){
- sqlite3_result_error(context,
- "edit() cannot reopen temp file after edit", -1);
- goto edit_func_end;
- }
- fseek(f, 0, SEEK_END);
- sz = ftell(f);
- rewind(f);
- p = sqlite3_malloc64( sz+(bBin==0) );
- if( p==0 ){
- sqlite3_result_error_nomem(context);
- goto edit_func_end;
- }
- if( bBin ){
- x = fread(p, 1, sz, f);
- }else{
- x = fread(p, 1, sz, f);
- p[sz] = 0;
- }
- fclose(f);
- f = 0;
- if( x!=sz ){
- sqlite3_result_error(context, "could not read back the whole file", -1);
- goto edit_func_end;
- }
- if( bBin ){
- sqlite3_result_blob64(context, p, sz, sqlite3_free);
- }else{
- sqlite3_result_text64(context, (const char*)p, sz,
- sqlite3_free, SQLITE_UTF8);
- }
- p = 0;
-
-edit_func_end:
- if( f ) fclose(f);
- unlink(zTempFile);
- sqlite3_free(zTempFile);
- sqlite3_free(p);
-}
-#endif /* SQLITE_NOHAVE_SYSTEM */
-
-/*
-** Save or restore the current output mode
-*/
-static void outputModePush(ShellState *p){
- p->modePrior = p->mode;
- memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
- memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
-}
-static void outputModePop(ShellState *p){
- p->mode = p->modePrior;
- memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
- memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
-}
-
-/*
-** Output the given string as a hex-encoded blob (eg. X'1234' )
-*/
-static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
- int i;
- char *zBlob = (char *)pBlob;
- raw_printf(out,"X'");
- for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
- raw_printf(out,"'");
-}
-
-/*
-** Find a string that is not found anywhere in z[]. Return a pointer
-** to that string.
-**
-** Try to use zA and zB first. If both of those are already found in z[]
-** then make up some string and store it in the buffer zBuf.
-*/
-static const char *unused_string(
- const char *z, /* Result must not appear anywhere in z */
- const char *zA, const char *zB, /* Try these first */
- char *zBuf /* Space to store a generated string */
-){
- unsigned i = 0;
- if( strstr(z, zA)==0 ) return zA;
- if( strstr(z, zB)==0 ) return zB;
- do{
- sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
- }while( strstr(z,zBuf)!=0 );
- return zBuf;
-}
-
-/*
-** Output the given string as a quoted string using SQL quoting conventions.
-**
-** See also: output_quoted_escaped_string()
-*/
-static void output_quoted_string(FILE *out, const char *z){
- int i;
- char c;
- setBinaryMode(out, 1);
- for(i=0; (c = z[i])!=0 && c!='\''; i++){}
- if( c==0 ){
- utf8_printf(out,"'%s'",z);
- }else{
- raw_printf(out, "'");
- while( *z ){
- for(i=0; (c = z[i])!=0 && c!='\''; i++){}
- if( c=='\'' ) i++;
- if( i ){
- utf8_printf(out, "%.*s", i, z);
- z += i;
- }
- if( c=='\'' ){
- raw_printf(out, "'");
- continue;
- }
- if( c==0 ){
- break;
- }
- z++;
- }
- raw_printf(out, "'");
- }
- setTextMode(out, 1);
-}
-
-/*
-** Output the given string as a quoted string using SQL quoting conventions.
-** Additionallly , escape the "\n" and "\r" characters so that they do not
-** get corrupted by end-of-line translation facilities in some operating
-** systems.
-**
-** This is like output_quoted_string() but with the addition of the \r\n
-** escape mechanism.
-*/
-static void output_quoted_escaped_string(FILE *out, const char *z){
- int i;
- char c;
- setBinaryMode(out, 1);
- for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
- if( c==0 ){
- utf8_printf(out,"'%s'",z);
- }else{
- const char *zNL = 0;
- const char *zCR = 0;
- int nNL = 0;
- int nCR = 0;
- char zBuf1[20], zBuf2[20];
- for(i=0; z[i]; i++){
- if( z[i]=='\n' ) nNL++;
- if( z[i]=='\r' ) nCR++;
- }
- if( nNL ){
- raw_printf(out, "replace(");
- zNL = unused_string(z, "\\n", "\\012", zBuf1);
- }
- if( nCR ){
- raw_printf(out, "replace(");
- zCR = unused_string(z, "\\r", "\\015", zBuf2);
- }
- raw_printf(out, "'");
- while( *z ){
- for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
- if( c=='\'' ) i++;
- if( i ){
- utf8_printf(out, "%.*s", i, z);
- z += i;
- }
- if( c=='\'' ){
- raw_printf(out, "'");
- continue;
- }
- if( c==0 ){
- break;
- }
- z++;
- if( c=='\n' ){
- raw_printf(out, "%s", zNL);
- continue;
- }
- raw_printf(out, "%s", zCR);
- }
- raw_printf(out, "'");
- if( nCR ){
- raw_printf(out, ",'%s',char(13))", zCR);
- }
- if( nNL ){
- raw_printf(out, ",'%s',char(10))", zNL);
- }
- }
- setTextMode(out, 1);
-}
-
-/*
-** Output the given string as a quoted according to C or TCL quoting rules.
-*/
-static void output_c_string(FILE *out, const char *z){
- unsigned int c;
- fputc('"', out);
- while( (c = *(z++))!=0 ){
- if( c=='\\' ){
- fputc(c, out);
- fputc(c, out);
- }else if( c=='"' ){
- fputc('\\', out);
- fputc('"', out);
- }else if( c=='\t' ){
- fputc('\\', out);
- fputc('t', out);
- }else if( c=='\n' ){
- fputc('\\', out);
- fputc('n', out);
- }else if( c=='\r' ){
- fputc('\\', out);
- fputc('r', out);
- }else if( !isprint(c&0xff) ){
- raw_printf(out, "\\%03o", c&0xff);
- }else{
- fputc(c, out);
- }
- }
- fputc('"', out);
-}
-
-/*
-** Output the given string with characters that are special to
-** HTML escaped.
-*/
-static void output_html_string(FILE *out, const char *z){
- int i;
- if( z==0 ) z = "";
- while( *z ){
- for(i=0; z[i]
- && z[i]!='<'
- && z[i]!='&'
- && z[i]!='>'
- && z[i]!='\"'
- && z[i]!='\'';
- i++){}
- if( i>0 ){
- utf8_printf(out,"%.*s",i,z);
- }
- if( z[i]=='<' ){
- raw_printf(out,"&lt;");
- }else if( z[i]=='&' ){
- raw_printf(out,"&amp;");
- }else if( z[i]=='>' ){
- raw_printf(out,"&gt;");
- }else if( z[i]=='\"' ){
- raw_printf(out,"&quot;");
- }else if( z[i]=='\'' ){
- raw_printf(out,"&#39;");
- }else{
- break;
- }
- z += i + 1;
- }
-}
-
-/*
-** If a field contains any character identified by a 1 in the following
-** array, then the string must be quoted for CSV.
-*/
-static const char needCsvQuote[] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-};
-
-/*
-** Output a single term of CSV. Actually, p->colSeparator is used for
-** the separator, which may or may not be a comma. p->nullValue is
-** the null value. Strings are quoted if necessary. The separator
-** is only issued if bSep is true.
-*/
-static void output_csv(ShellState *p, const char *z, int bSep){
- FILE *out = p->out;
- if( z==0 ){
- utf8_printf(out,"%s",p->nullValue);
- }else{
- int i;
- int nSep = strlen30(p->colSeparator);
- for(i=0; z[i]; i++){
- if( needCsvQuote[((unsigned char*)z)[i]]
- || (z[i]==p->colSeparator[0] &&
- (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
- i = 0;
- break;
- }
- }
- if( i==0 ){
- char *zQuoted = sqlite3_mprintf("\"%w\"", z);
- utf8_printf(out, "%s", zQuoted);
- sqlite3_free(zQuoted);
- }else{
- utf8_printf(out, "%s", z);
- }
- }
- if( bSep ){
- utf8_printf(p->out, "%s", p->colSeparator);
- }
-}
-
-/*
-** This routine runs when the user presses Ctrl-C
-*/
-static void interrupt_handler(int NotUsed){
- UNUSED_PARAMETER(NotUsed);
- seenInterrupt++;
- if( seenInterrupt>2 ) exit(1);
- if( globalDb ) sqlite3_interrupt(globalDb);
-}
-
-#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
-/*
-** This routine runs for console events (e.g. Ctrl-C) on Win32
-*/
-static BOOL WINAPI ConsoleCtrlHandler(
- DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
-){
- if( dwCtrlType==CTRL_C_EVENT ){
- interrupt_handler(0);
- return TRUE;
- }
- return FALSE;
-}
-#endif
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
-/*
-** When the ".auth ON" is set, the following authorizer callback is
-** invoked. It always returns SQLITE_OK.
-*/
-static int shellAuth(
- void *pClientData,
- int op,
- const char *zA1,
- const char *zA2,
- const char *zA3,
- const char *zA4
-){
- ShellState *p = (ShellState*)pClientData;
- static const char *azAction[] = { 0,
- "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
- "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
- "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
- "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
- "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
- "DROP_TRIGGER", "DROP_VIEW", "INSERT",
- "PRAGMA", "READ", "SELECT",
- "TRANSACTION", "UPDATE", "ATTACH",
- "DETACH", "ALTER_TABLE", "REINDEX",
- "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
- "FUNCTION", "SAVEPOINT", "RECURSIVE"
- };
- int i;
- const char *az[4];
- az[0] = zA1;
- az[1] = zA2;
- az[2] = zA3;
- az[3] = zA4;
- utf8_printf(p->out, "authorizer: %s", azAction[op]);
- for(i=0; i<4; i++){
- raw_printf(p->out, " ");
- if( az[i] ){
- output_c_string(p->out, az[i]);
- }else{
- raw_printf(p->out, "NULL");
- }
- }
- raw_printf(p->out, "\n");
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
-**
-** This routine converts some CREATE TABLE statements for shadow tables
-** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
-*/
-static void printSchemaLine(FILE *out, const char *z, const char *zTail){
- if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
- utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
- }else{
- utf8_printf(out, "%s%s", z, zTail);
- }
-}
-static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
- char c = z[n];
- z[n] = 0;
- printSchemaLine(out, z, zTail);
- z[n] = c;
-}
-
-/*
-** Return true if string z[] has nothing but whitespace and comments to the
-** end of the first line.
-*/
-static int wsToEol(const char *z){
- int i;
- for(i=0; z[i]; i++){
- if( z[i]=='\n' ) return 1;
- if( IsSpace(z[i]) ) continue;
- if( z[i]=='-' && z[i+1]=='-' ) return 1;
- return 0;
- }
- return 1;
-}
-
-/*
-** Add a new entry to the EXPLAIN QUERY PLAN data
-*/
-static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
- EQPGraphRow *pNew;
- int nText = strlen30(zText);
- if( p->autoEQPtest ){
- utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
- }
- pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
- if( pNew==0 ) shell_out_of_memory();
- pNew->iEqpId = iEqpId;
- pNew->iParentId = p2;
- memcpy(pNew->zText, zText, nText+1);
- pNew->pNext = 0;
- if( p->sGraph.pLast ){
- p->sGraph.pLast->pNext = pNew;
- }else{
- p->sGraph.pRow = pNew;
- }
- p->sGraph.pLast = pNew;
-}
-
-/*
-** Free and reset the EXPLAIN QUERY PLAN data that has been collected
-** in p->sGraph.
-*/
-static void eqp_reset(ShellState *p){
- EQPGraphRow *pRow, *pNext;
- for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
- pNext = pRow->pNext;
- sqlite3_free(pRow);
- }
- memset(&p->sGraph, 0, sizeof(p->sGraph));
-}
-
-/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
-** pOld, or return the first such line if pOld is NULL
-*/
-static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
- EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
- while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
- return pRow;
-}
-
-/* Render a single level of the graph that has iEqpId as its parent. Called
-** recursively to render sublevels.
-*/
-static void eqp_render_level(ShellState *p, int iEqpId){
- EQPGraphRow *pRow, *pNext;
- int n = strlen30(p->sGraph.zPrefix);
- char *z;
- for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
- pNext = eqp_next_row(p, iEqpId, pRow);
- z = pRow->zText;
- utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
- if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
- memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
- eqp_render_level(p, pRow->iEqpId);
- p->sGraph.zPrefix[n] = 0;
- }
- }
-}
-
-/*
-** Display and reset the EXPLAIN QUERY PLAN data
-*/
-static void eqp_render(ShellState *p){
- EQPGraphRow *pRow = p->sGraph.pRow;
- if( pRow ){
- if( pRow->zText[0]=='-' ){
- if( pRow->pNext==0 ){
- eqp_reset(p);
- return;
- }
- utf8_printf(p->out, "%s\n", pRow->zText+3);
- p->sGraph.pRow = pRow->pNext;
- sqlite3_free(pRow);
- }else{
- utf8_printf(p->out, "QUERY PLAN\n");
- }
- p->sGraph.zPrefix[0] = 0;
- eqp_render_level(p, 0);
- eqp_reset(p);
- }
-}
-
-/*
-** This is the callback routine that the shell
-** invokes for each row of a query result.
-*/
-static int shell_callback(
- void *pArg,
- int nArg, /* Number of result columns */
- char **azArg, /* Text of each result column */
- char **azCol, /* Column names */
- int *aiType /* Column types */
-){
- int i;
- ShellState *p = (ShellState*)pArg;
-
- if( azArg==0 ) return 0;
- switch( p->cMode ){
- case MODE_Line: {
- int w = 5;
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- int len = strlen30(azCol[i] ? azCol[i] : "");
- if( len>w ) w = len;
- }
- if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
- for(i=0; i<nArg; i++){
- utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
- azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
- }
- break;
- }
- case MODE_Explain:
- case MODE_Column: {
- static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
- const int *colWidth;
- int showHdr;
- char *rowSep;
- if( p->cMode==MODE_Column ){
- colWidth = p->colWidth;
- showHdr = p->showHeader;
- rowSep = p->rowSeparator;
- }else{
- colWidth = aExplainWidths;
- showHdr = 1;
- rowSep = SEP_Row;
- }
- if( p->cnt++==0 ){
- for(i=0; i<nArg; i++){
- int w, n;
- if( i<ArraySize(p->colWidth) ){
- w = colWidth[i];
- }else{
- w = 0;
- }
- if( w==0 ){
- w = strlenChar(azCol[i] ? azCol[i] : "");
- if( w<10 ) w = 10;
- n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
- if( w<n ) w = n;
- }
- if( i<ArraySize(p->actualWidth) ){
- p->actualWidth[i] = w;
- }
- if( showHdr ){
- utf8_width_print(p->out, w, azCol[i]);
- utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
- }
- }
- if( showHdr ){
- for(i=0; i<nArg; i++){
- int w;
- if( i<ArraySize(p->actualWidth) ){
- w = p->actualWidth[i];
- if( w<0 ) w = -w;
- }else{
- w = 10;
- }
- utf8_printf(p->out,"%-*.*s%s",w,w,
- "----------------------------------------------------------"
- "----------------------------------------------------------",
- i==nArg-1 ? rowSep : " ");
- }
- }
- }
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- int w;
- if( i<ArraySize(p->actualWidth) ){
- w = p->actualWidth[i];
- }else{
- w = 10;
- }
- if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
- w = strlenChar(azArg[i]);
- }
- if( i==1 && p->aiIndent && p->pStmt ){
- if( p->iIndent<p->nIndent ){
- utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
- }
- p->iIndent++;
- }
- utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
- utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
- }
- break;
- }
- case MODE_Semi: { /* .schema and .fullschema output */
- printSchemaLine(p->out, azArg[0], ";\n");
- break;
- }
- case MODE_Pretty: { /* .schema and .fullschema with --indent */
- char *z;
- int j;
- int nParen = 0;
- char cEnd = 0;
- char c;
- int nLine = 0;
- assert( nArg==1 );
- if( azArg[0]==0 ) break;
- if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
- || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
- ){
- utf8_printf(p->out, "%s;\n", azArg[0]);
- break;
- }
- z = sqlite3_mprintf("%s", azArg[0]);
- j = 0;
- for(i=0; IsSpace(z[i]); i++){}
- for(; (c = z[i])!=0; i++){
- if( IsSpace(c) ){
- if( z[j-1]=='\r' ) z[j-1] = '\n';
- if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
- }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
- j--;
- }
- z[j++] = c;
- }
- while( j>0 && IsSpace(z[j-1]) ){ j--; }
- z[j] = 0;
- if( strlen30(z)>=79 ){
- for(i=j=0; (c = z[i])!=0; i++){ /* Copy changes from z[i] back to z[j] */
- if( c==cEnd ){
- cEnd = 0;
- }else if( c=='"' || c=='\'' || c=='`' ){
- cEnd = c;
- }else if( c=='[' ){
- cEnd = ']';
- }else if( c=='-' && z[i+1]=='-' ){
- cEnd = '\n';
- }else if( c=='(' ){
- nParen++;
- }else if( c==')' ){
- nParen--;
- if( nLine>0 && nParen==0 && j>0 ){
- printSchemaLineN(p->out, z, j, "\n");
- j = 0;
- }
- }
- z[j++] = c;
- if( nParen==1 && cEnd==0
- && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
- ){
- if( c=='\n' ) j--;
- printSchemaLineN(p->out, z, j, "\n ");
- j = 0;
- nLine++;
- while( IsSpace(z[i+1]) ){ i++; }
- }
- }
- z[j] = 0;
- }
- printSchemaLine(p->out, z, ";\n");
- sqlite3_free(z);
- break;
- }
- case MODE_List: {
- if( p->cnt++==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- utf8_printf(p->out,"%s%s",azCol[i],
- i==nArg-1 ? p->rowSeparator : p->colSeparator);
- }
- }
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- char *z = azArg[i];
- if( z==0 ) z = p->nullValue;
- utf8_printf(p->out, "%s", z);
- if( i<nArg-1 ){
- utf8_printf(p->out, "%s", p->colSeparator);
- }else{
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- }
- break;
- }
- case MODE_Html: {
- if( p->cnt++==0 && p->showHeader ){
- raw_printf(p->out,"<TR>");
- for(i=0; i<nArg; i++){
- raw_printf(p->out,"<TH>");
- output_html_string(p->out, azCol[i]);
- raw_printf(p->out,"</TH>\n");
- }
- raw_printf(p->out,"</TR>\n");
- }
- if( azArg==0 ) break;
- raw_printf(p->out,"<TR>");
- for(i=0; i<nArg; i++){
- raw_printf(p->out,"<TD>");
- output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
- raw_printf(p->out,"</TD>\n");
- }
- raw_printf(p->out,"</TR>\n");
- break;
- }
- case MODE_Tcl: {
- if( p->cnt++==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- output_c_string(p->out,azCol[i] ? azCol[i] : "");
- if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
- if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- break;
- }
- case MODE_Csv: {
- setBinaryMode(p->out, 1);
- if( p->cnt++==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- if( nArg>0 ){
- for(i=0; i<nArg; i++){
- output_csv(p, azArg[i], i<nArg-1);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- setTextMode(p->out, 1);
- break;
- }
- case MODE_Insert: {
- if( azArg==0 ) break;
- utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
- if( p->showHeader ){
- raw_printf(p->out,"(");
- for(i=0; i<nArg; i++){
- if( i>0 ) raw_printf(p->out, ",");
- if( quoteChar(azCol[i]) ){
- char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
- utf8_printf(p->out, "%s", z);
- sqlite3_free(z);
- }else{
- raw_printf(p->out, "%s", azCol[i]);
- }
- }
- raw_printf(p->out,")");
- }
- p->cnt++;
- for(i=0; i<nArg; i++){
- raw_printf(p->out, i>0 ? "," : " VALUES(");
- if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
- utf8_printf(p->out,"NULL");
- }else if( aiType && aiType[i]==SQLITE_TEXT ){
- if( ShellHasFlag(p, SHFLG_Newlines) ){
- output_quoted_string(p->out, azArg[i]);
- }else{
- output_quoted_escaped_string(p->out, azArg[i]);
- }
- }else if( aiType && aiType[i]==SQLITE_INTEGER ){
- utf8_printf(p->out,"%s", azArg[i]);
- }else if( aiType && aiType[i]==SQLITE_FLOAT ){
- char z[50];
- double r = sqlite3_column_double(p->pStmt, i);
- sqlite3_snprintf(50,z,"%!.20g", r);
- raw_printf(p->out, "%s", z);
- }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
- const void *pBlob = sqlite3_column_blob(p->pStmt, i);
- int nBlob = sqlite3_column_bytes(p->pStmt, i);
- output_hex_blob(p->out, pBlob, nBlob);
- }else if( isNumber(azArg[i], 0) ){
- utf8_printf(p->out,"%s", azArg[i]);
- }else if( ShellHasFlag(p, SHFLG_Newlines) ){
- output_quoted_string(p->out, azArg[i]);
- }else{
- output_quoted_escaped_string(p->out, azArg[i]);
- }
- }
- raw_printf(p->out,");\n");
- break;
- }
- case MODE_Quote: {
- if( azArg==0 ) break;
- if( p->cnt==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- if( i>0 ) raw_printf(p->out, ",");
- output_quoted_string(p->out, azCol[i]);
- }
- raw_printf(p->out,"\n");
- }
- p->cnt++;
- for(i=0; i<nArg; i++){
- if( i>0 ) raw_printf(p->out, ",");
- if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
- utf8_printf(p->out,"NULL");
- }else if( aiType && aiType[i]==SQLITE_TEXT ){
- output_quoted_string(p->out, azArg[i]);
- }else if( aiType && aiType[i]==SQLITE_INTEGER ){
- utf8_printf(p->out,"%s", azArg[i]);
- }else if( aiType && aiType[i]==SQLITE_FLOAT ){
- char z[50];
- double r = sqlite3_column_double(p->pStmt, i);
- sqlite3_snprintf(50,z,"%!.20g", r);
- raw_printf(p->out, "%s", z);
- }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
- const void *pBlob = sqlite3_column_blob(p->pStmt, i);
- int nBlob = sqlite3_column_bytes(p->pStmt, i);
- output_hex_blob(p->out, pBlob, nBlob);
- }else if( isNumber(azArg[i], 0) ){
- utf8_printf(p->out,"%s", azArg[i]);
- }else{
- output_quoted_string(p->out, azArg[i]);
- }
- }
- raw_printf(p->out,"\n");
- break;
- }
- case MODE_Ascii: {
- if( p->cnt++==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
- utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
- utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- break;
- }
- case MODE_EQP: {
- eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
- break;
- }
- }
- return 0;
-}
-
-/*
-** This is the callback routine that the SQLite library
-** invokes for each row of a query result.
-*/
-static int callback(void *pArg, int nArg, char **azArg, char **azCol){
- /* since we don't have type info, call the shell_callback with a NULL value */
- return shell_callback(pArg, nArg, azArg, azCol, NULL);
-}
-
-/*
-** This is the callback routine from sqlite3_exec() that appends all
-** output onto the end of a ShellText object.
-*/
-static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
- ShellText *p = (ShellText*)pArg;
- int i;
- UNUSED_PARAMETER(az);
- if( azArg==0 ) return 0;
- if( p->n ) appendText(p, "|", 0);
- for(i=0; i<nArg; i++){
- if( i ) appendText(p, ",", 0);
- if( azArg[i] ) appendText(p, azArg[i], 0);
- }
- return 0;
-}
-
-/*
-** Generate an appropriate SELFTEST table in the main database.
-*/
-static void createSelftestTable(ShellState *p){
- char *zErrMsg = 0;
- sqlite3_exec(p->db,
- "SAVEPOINT selftest_init;\n"
- "CREATE TABLE IF NOT EXISTS selftest(\n"
- " tno INTEGER PRIMARY KEY,\n" /* Test number */
- " op TEXT,\n" /* Operator: memo run */
- " cmd TEXT,\n" /* Command text */
- " ans TEXT\n" /* Desired answer */
- ");"
- "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
- "INSERT INTO [_shell$self](rowid,op,cmd)\n"
- " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
- " 'memo','Tests generated by --init');\n"
- "INSERT INTO [_shell$self]\n"
- " SELECT 'run',\n"
- " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
- "FROM sqlite_master ORDER BY 2'',224))',\n"
- " hex(sha3_query('SELECT type,name,tbl_name,sql "
- "FROM sqlite_master ORDER BY 2',224));\n"
- "INSERT INTO [_shell$self]\n"
- " SELECT 'run',"
- " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
- " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
- " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
- " FROM (\n"
- " SELECT name FROM sqlite_master\n"
- " WHERE type='table'\n"
- " AND name<>'selftest'\n"
- " AND coalesce(rootpage,0)>0\n"
- " )\n"
- " ORDER BY name;\n"
- "INSERT INTO [_shell$self]\n"
- " VALUES('run','PRAGMA integrity_check','ok');\n"
- "INSERT INTO selftest(tno,op,cmd,ans)"
- " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
- "DROP TABLE [_shell$self];"
- ,0,0,&zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- }
- sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
-}
-
-
-/*
-** Set the destination table field of the ShellState structure to
-** the name of the table given. Escape any quote characters in the
-** table name.
-*/
-static void set_table_name(ShellState *p, const char *zName){
- int i, n;
- char cQuote;
- char *z;
-
- if( p->zDestTable ){
- free(p->zDestTable);
- p->zDestTable = 0;
- }
- if( zName==0 ) return;
- cQuote = quoteChar(zName);
- n = strlen30(zName);
- if( cQuote ) n += n+2;
- z = p->zDestTable = malloc( n+1 );
- if( z==0 ) shell_out_of_memory();
- n = 0;
- if( cQuote ) z[n++] = cQuote;
- for(i=0; zName[i]; i++){
- z[n++] = zName[i];
- if( zName[i]==cQuote ) z[n++] = cQuote;
- }
- if( cQuote ) z[n++] = cQuote;
- z[n] = 0;
-}
-
-
-/*
-** Execute a query statement that will generate SQL output. Print
-** the result columns, comma-separated, on a line and then add a
-** semicolon terminator to the end of that line.
-**
-** If the number of columns is 1 and that column contains text "--"
-** then write the semicolon on a separate line. That way, if a
-** "--" comment occurs at the end of the statement, the comment
-** won't consume the semicolon terminator.
-*/
-static int run_table_dump_query(
- ShellState *p, /* Query context */
- const char *zSelect, /* SELECT statement to extract content */
- const char *zFirstRow /* Print before first row, if not NULL */
-){
- sqlite3_stmt *pSelect;
- int rc;
- int nResult;
- int i;
- const char *z;
- rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
- if( rc!=SQLITE_OK || !pSelect ){
- utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
- sqlite3_errmsg(p->db));
- if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
- return rc;
- }
- rc = sqlite3_step(pSelect);
- nResult = sqlite3_column_count(pSelect);
- while( rc==SQLITE_ROW ){
- if( zFirstRow ){
- utf8_printf(p->out, "%s", zFirstRow);
- zFirstRow = 0;
- }
- z = (const char*)sqlite3_column_text(pSelect, 0);
- utf8_printf(p->out, "%s", z);
- for(i=1; i<nResult; i++){
- utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
- }
- if( z==0 ) z = "";
- while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
- if( z[0] ){
- raw_printf(p->out, "\n;\n");
- }else{
- raw_printf(p->out, ";\n");
- }
- rc = sqlite3_step(pSelect);
- }
- rc = sqlite3_finalize(pSelect);
- if( rc!=SQLITE_OK ){
- utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
- sqlite3_errmsg(p->db));
- if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
- }
- return rc;
-}
-
-/*
-** Allocate space and save off current error string.
-*/
-static char *save_err_msg(
- sqlite3 *db /* Database to query */
-){
- int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
- char *zErrMsg = sqlite3_malloc64(nErrMsg);
- if( zErrMsg ){
- memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
- }
- return zErrMsg;
-}
-
-#ifdef __linux__
-/*
-** Attempt to display I/O stats on Linux using /proc/PID/io
-*/
-static void displayLinuxIoStats(FILE *out){
- FILE *in;
- char z[200];
- sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
- in = fopen(z, "rb");
- if( in==0 ) return;
- while( fgets(z, sizeof(z), in)!=0 ){
- static const struct {
- const char *zPattern;
- const char *zDesc;
- } aTrans[] = {
- { "rchar: ", "Bytes received by read():" },
- { "wchar: ", "Bytes sent to write():" },
- { "syscr: ", "Read() system calls:" },
- { "syscw: ", "Write() system calls:" },
- { "read_bytes: ", "Bytes read from storage:" },
- { "write_bytes: ", "Bytes written to storage:" },
- { "cancelled_write_bytes: ", "Cancelled write bytes:" },
- };
- int i;
- for(i=0; i<ArraySize(aTrans); i++){
- int n = strlen30(aTrans[i].zPattern);
- if( strncmp(aTrans[i].zPattern, z, n)==0 ){
- utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
- break;
- }
- }
- }
- fclose(in);
-}
-#endif
-
-/*
-** Display a single line of status using 64-bit values.
-*/
-static void displayStatLine(
- ShellState *p, /* The shell context */
- char *zLabel, /* Label for this one line */
- char *zFormat, /* Format for the result */
- int iStatusCtrl, /* Which status to display */
- int bReset /* True to reset the stats */
-){
- sqlite3_int64 iCur = -1;
- sqlite3_int64 iHiwtr = -1;
- int i, nPercent;
- char zLine[200];
- sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
- for(i=0, nPercent=0; zFormat[i]; i++){
- if( zFormat[i]=='%' ) nPercent++;
- }
- if( nPercent>1 ){
- sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
- }else{
- sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
- }
- raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
-}
-
-/*
-** Display memory stats.
-*/
-static int display_stats(
- sqlite3 *db, /* Database to query */
- ShellState *pArg, /* Pointer to ShellState */
- int bReset /* True to reset the stats */
-){
- int iCur;
- int iHiwtr;
- FILE *out;
- if( pArg==0 || pArg->out==0 ) return 0;
- out = pArg->out;
-
- if( pArg->pStmt && (pArg->statsOn & 2) ){
- int nCol, i, x;
- sqlite3_stmt *pStmt = pArg->pStmt;
- char z[100];
- nCol = sqlite3_column_count(pStmt);
- raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
- for(i=0; i<nCol; i++){
- sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
- utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
-#ifndef SQLITE_OMIT_DECLTYPE
- sqlite3_snprintf(30, z+x, "declared type:");
- utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
-#endif
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
- sqlite3_snprintf(30, z+x, "database name:");
- utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
- sqlite3_snprintf(30, z+x, "table name:");
- utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
- sqlite3_snprintf(30, z+x, "origin name:");
- utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
-#endif
- }
- }
-
- displayStatLine(pArg, "Memory Used:",
- "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
- displayStatLine(pArg, "Number of Outstanding Allocations:",
- "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
- if( pArg->shellFlgs & SHFLG_Pagecache ){
- displayStatLine(pArg, "Number of Pcache Pages Used:",
- "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
- }
- displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
- "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
- displayStatLine(pArg, "Largest Allocation:",
- "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
- displayStatLine(pArg, "Largest Pcache Allocation:",
- "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
-#ifdef YYTRACKMAXSTACKDEPTH
- displayStatLine(pArg, "Deepest Parser Stack:",
- "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
-#endif
-
- if( db ){
- if( pArg->shellFlgs & SHFLG_Lookaside ){
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
- &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out,
- "Lookaside Slots Used: %d (max %d)\n",
- iCur, iHiwtr);
- sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
- &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
- iHiwtr);
- sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
- &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
- iHiwtr);
- sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
- &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
- iHiwtr);
- }
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
- iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
- raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
- raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
- raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
- raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
- iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
- iCur);
- }
-
- if( pArg->pStmt ){
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
- bReset);
- raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
- raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
- raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
- raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset);
- raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
- raw_printf(pArg->out, "Number of times run: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
- raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
- }
-
-#ifdef __linux__
- displayLinuxIoStats(pArg->out);
-#endif
-
- /* Do not remove this machine readable comment: extra-stats-output-here */
-
- return 0;
-}
-
-/*
-** Display scan stats.
-*/
-static void display_scanstats(
- sqlite3 *db, /* Database to query */
- ShellState *pArg /* Pointer to ShellState */
-){
-#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
- UNUSED_PARAMETER(db);
- UNUSED_PARAMETER(pArg);
-#else
- int i, k, n, mx;
- raw_printf(pArg->out, "-------- scanstats --------\n");
- mx = 0;
- for(k=0; k<=mx; k++){
- double rEstLoop = 1.0;
- for(i=n=0; 1; i++){
- sqlite3_stmt *p = pArg->pStmt;
- sqlite3_int64 nLoop, nVisit;
- double rEst;
- int iSid;
- const char *zExplain;
- if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
- break;
- }
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
- if( iSid>mx ) mx = iSid;
- if( iSid!=k ) continue;
- if( n==0 ){
- rEstLoop = (double)nLoop;
- if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
- }
- n++;
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
- utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
- rEstLoop *= rEst;
- raw_printf(pArg->out,
- " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
- nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
- );
- }
- }
- raw_printf(pArg->out, "---------------------------\n");
-#endif
-}
-
-/*
-** Parameter azArray points to a zero-terminated array of strings. zStr
-** points to a single nul-terminated string. Return non-zero if zStr
-** is equal, according to strcmp(), to any of the strings in the array.
-** Otherwise, return zero.
-*/
-static int str_in_array(const char *zStr, const char **azArray){
- int i;
- for(i=0; azArray[i]; i++){
- if( 0==strcmp(zStr, azArray[i]) ) return 1;
- }
- return 0;
-}
-
-/*
-** If compiled statement pSql appears to be an EXPLAIN statement, allocate
-** and populate the ShellState.aiIndent[] array with the number of
-** spaces each opcode should be indented before it is output.
-**
-** The indenting rules are:
-**
-** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
-** all opcodes that occur between the p2 jump destination and the opcode
-** itself by 2 spaces.
-**
-** * For each "Goto", if the jump destination is earlier in the program
-** and ends on one of:
-** Yield SeekGt SeekLt RowSetRead Rewind
-** or if the P1 parameter is one instead of zero,
-** then indent all opcodes between the earlier instruction
-** and "Goto" by 2 spaces.
-*/
-static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
- const char *zSql; /* The text of the SQL statement */
- const char *z; /* Used to check if this is an EXPLAIN */
- int *abYield = 0; /* True if op is an OP_Yield */
- int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
- int iOp; /* Index of operation in p->aiIndent[] */
-
- const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
- "NextIfOpen", "PrevIfOpen", 0 };
- const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
- "Rewind", 0 };
- const char *azGoto[] = { "Goto", 0 };
-
- /* Try to figure out if this is really an EXPLAIN statement. If this
- ** cannot be verified, return early. */
- if( sqlite3_column_count(pSql)!=8 ){
- p->cMode = p->mode;
- return;
- }
- zSql = sqlite3_sql(pSql);
- if( zSql==0 ) return;
- for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
- if( sqlite3_strnicmp(z, "explain", 7) ){
- p->cMode = p->mode;
- return;
- }
-
- for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
- int i;
- int iAddr = sqlite3_column_int(pSql, 0);
- const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
-
- /* Set p2 to the P2 field of the current opcode. Then, assuming that
- ** p2 is an instruction address, set variable p2op to the index of that
- ** instruction in the aiIndent[] array. p2 and p2op may be different if
- ** the current instruction is part of a sub-program generated by an
- ** SQL trigger or foreign key. */
- int p2 = sqlite3_column_int(pSql, 3);
- int p2op = (p2 + (iOp-iAddr));
-
- /* Grow the p->aiIndent array as required */
- if( iOp>=nAlloc ){
- if( iOp==0 ){
- /* Do further verfication that this is explain output. Abort if
- ** it is not */
- static const char *explainCols[] = {
- "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
- int jj;
- for(jj=0; jj<ArraySize(explainCols); jj++){
- if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
- p->cMode = p->mode;
- sqlite3_reset(pSql);
- return;
- }
- }
- }
- nAlloc += 100;
- p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
- abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
- }
- abYield[iOp] = str_in_array(zOp, azYield);
- p->aiIndent[iOp] = 0;
- p->nIndent = iOp+1;
-
- if( str_in_array(zOp, azNext) ){
- for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
- }
- if( str_in_array(zOp, azGoto) && p2op<p->nIndent
- && (abYield[p2op] || sqlite3_column_int(pSql, 2))
- ){
- for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
- }
- }
-
- p->iIndent = 0;
- sqlite3_free(abYield);
- sqlite3_reset(pSql);
-}
-
-/*
-** Free the array allocated by explain_data_prepare().
-*/
-static void explain_data_delete(ShellState *p){
- sqlite3_free(p->aiIndent);
- p->aiIndent = 0;
- p->nIndent = 0;
- p->iIndent = 0;
-}
-
-/*
-** Disable and restore .wheretrace and .selecttrace settings.
-*/
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
-extern int sqlite3SelectTrace;
-static int savedSelectTrace;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
-extern int sqlite3WhereTrace;
-static int savedWhereTrace;
-#endif
-static void disable_debug_trace_modes(void){
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
- savedSelectTrace = sqlite3SelectTrace;
- sqlite3SelectTrace = 0;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
- savedWhereTrace = sqlite3WhereTrace;
- sqlite3WhereTrace = 0;
-#endif
-}
-static void restore_debug_trace_modes(void){
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
- sqlite3SelectTrace = savedSelectTrace;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
- sqlite3WhereTrace = savedWhereTrace;
-#endif
-}
-
-/*
-** Run a prepared statement
-*/
-static void exec_prepared_stmt(
- ShellState *pArg, /* Pointer to ShellState */
- sqlite3_stmt *pStmt /* Statment to run */
-){
- int rc;
-
- /* perform the first step. this will tell us if we
- ** have a result set or not and how wide it is.
- */
- rc = sqlite3_step(pStmt);
- /* if we have a result set... */
- if( SQLITE_ROW == rc ){
- /* allocate space for col name ptr, value ptr, and type */
- int nCol = sqlite3_column_count(pStmt);
- void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
- if( !pData ){
- rc = SQLITE_NOMEM;
- }else{
- char **azCols = (char **)pData; /* Names of result columns */
- char **azVals = &azCols[nCol]; /* Results */
- int *aiTypes = (int *)&azVals[nCol]; /* Result types */
- int i, x;
- assert(sizeof(int) <= sizeof(char *));
- /* save off ptrs to column names */
- for(i=0; i<nCol; i++){
- azCols[i] = (char *)sqlite3_column_name(pStmt, i);
- }
- do{
- /* extract the data and data types */
- for(i=0; i<nCol; i++){
- aiTypes[i] = x = sqlite3_column_type(pStmt, i);
- if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
- azVals[i] = "";
- }else{
- azVals[i] = (char*)sqlite3_column_text(pStmt, i);
- }
- if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
- rc = SQLITE_NOMEM;
- break; /* from for */
- }
- } /* end for */
-
- /* if data and types extracted successfully... */
- if( SQLITE_ROW == rc ){
- /* call the supplied callback with the result row data */
- if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
- rc = SQLITE_ABORT;
- }else{
- rc = sqlite3_step(pStmt);
- }
- }
- } while( SQLITE_ROW == rc );
- sqlite3_free(pData);
- }
- }
-}
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*
-** This function is called to process SQL if the previous shell command
-** was ".expert". It passes the SQL in the second argument directly to
-** the sqlite3expert object.
-**
-** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
-** code. In this case, (*pzErr) may be set to point to a buffer containing
-** an English language error message. It is the responsibility of the
-** caller to eventually free this buffer using sqlite3_free().
-*/
-static int expertHandleSQL(
- ShellState *pState,
- const char *zSql,
- char **pzErr
-){
- assert( pState->expert.pExpert );
- assert( pzErr==0 || *pzErr==0 );
- return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
-}
-
-/*
-** This function is called either to silently clean up the object
-** created by the ".expert" command (if bCancel==1), or to generate a
-** report from it and then clean it up (if bCancel==0).
-**
-** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
-** code. In this case, (*pzErr) may be set to point to a buffer containing
-** an English language error message. It is the responsibility of the
-** caller to eventually free this buffer using sqlite3_free().
-*/
-static int expertFinish(
- ShellState *pState,
- int bCancel,
- char **pzErr
-){
- int rc = SQLITE_OK;
- sqlite3expert *p = pState->expert.pExpert;
- assert( p );
- assert( bCancel || pzErr==0 || *pzErr==0 );
- if( bCancel==0 ){
- FILE *out = pState->out;
- int bVerbose = pState->expert.bVerbose;
-
- rc = sqlite3_expert_analyze(p, pzErr);
- if( rc==SQLITE_OK ){
- int nQuery = sqlite3_expert_count(p);
- int i;
-
- if( bVerbose ){
- const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
- raw_printf(out, "-- Candidates -----------------------------\n");
- raw_printf(out, "%s\n", zCand);
- }
- for(i=0; i<nQuery; i++){
- const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
- const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
- const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
- if( zIdx==0 ) zIdx = "(no new indexes)\n";
- if( bVerbose ){
- raw_printf(out, "-- Query %d --------------------------------\n",i+1);
- raw_printf(out, "%s\n\n", zSql);
- }
- raw_printf(out, "%s\n", zIdx);
- raw_printf(out, "%s\n", zEQP);
- }
- }
- }
- sqlite3_expert_destroy(p);
- pState->expert.pExpert = 0;
- return rc;
-}
-
-/*
-** Implementation of ".expert" dot command.
-*/
-static int expertDotCommand(
- ShellState *pState, /* Current shell tool state */
- char **azArg, /* Array of arguments passed to dot command */
- int nArg /* Number of entries in azArg[] */
-){
- int rc = SQLITE_OK;
- char *zErr = 0;
- int i;
- int iSample = 0;
-
- assert( pState->expert.pExpert==0 );
- memset(&pState->expert, 0, sizeof(ExpertInfo));
-
- for(i=1; rc==SQLITE_OK && i<nArg; i++){
- char *z = azArg[i];
- int n;
- if( z[0]=='-' && z[1]=='-' ) z++;
- n = strlen30(z);
- if( n>=2 && 0==strncmp(z, "-verbose", n) ){
- pState->expert.bVerbose = 1;
- }
- else if( n>=2 && 0==strncmp(z, "-sample", n) ){
- if( i==(nArg-1) ){
- raw_printf(stderr, "option requires an argument: %s\n", z);
- rc = SQLITE_ERROR;
- }else{
- iSample = (int)integerValue(azArg[++i]);
- if( iSample<0 || iSample>100 ){
- raw_printf(stderr, "value out of range: %s\n", azArg[i]);
- rc = SQLITE_ERROR;
- }
- }
- }
- else{
- raw_printf(stderr, "unknown option: %s\n", z);
- rc = SQLITE_ERROR;
- }
- }
-
- if( rc==SQLITE_OK ){
- pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
- if( pState->expert.pExpert==0 ){
- raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
- rc = SQLITE_ERROR;
- }else{
- sqlite3_expert_config(
- pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
- );
- }
- }
-
- return rc;
-}
-#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
-
-/*
-** Execute a statement or set of statements. Print
-** any result rows/columns depending on the current mode
-** set via the supplied callback.
-**
-** This is very similar to SQLite's built-in sqlite3_exec()
-** function except it takes a slightly different callback
-** and callback data argument.
-*/
-static int shell_exec(
- ShellState *pArg, /* Pointer to ShellState */
- const char *zSql, /* SQL to be evaluated */
- char **pzErrMsg /* Error msg written here */
-){
- sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
- int rc = SQLITE_OK; /* Return Code */
- int rc2;
- const char *zLeftover; /* Tail of unprocessed SQL */
- sqlite3 *db = pArg->db;
-
- if( pzErrMsg ){
- *pzErrMsg = NULL;
- }
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pArg->expert.pExpert ){
- rc = expertHandleSQL(pArg, zSql, pzErrMsg);
- return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
- }
-#endif
-
- while( zSql[0] && (SQLITE_OK == rc) ){
- static const char *zStmtSql;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
- if( SQLITE_OK != rc ){
- if( pzErrMsg ){
- *pzErrMsg = save_err_msg(db);
- }
- }else{
- if( !pStmt ){
- /* this happens for a comment or white-space */
- zSql = zLeftover;
- while( IsSpace(zSql[0]) ) zSql++;
- continue;
- }
- zStmtSql = sqlite3_sql(pStmt);
- if( zStmtSql==0 ) zStmtSql = "";
- while( IsSpace(zStmtSql[0]) ) zStmtSql++;
-
- /* save off the prepared statment handle and reset row count */
- if( pArg ){
- pArg->pStmt = pStmt;
- pArg->cnt = 0;
- }
-
- /* echo the sql statement if echo on */
- if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
- utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
- }
-
- /* Show the EXPLAIN QUERY PLAN if .eqp is on */
- if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
- sqlite3_stmt *pExplain;
- char *zEQP;
- int triggerEQP = 0;
- disable_debug_trace_modes();
- sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
- if( pArg->autoEQP>=AUTOEQP_trigger ){
- sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
- }
- zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
- rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
- if( rc==SQLITE_OK ){
- while( sqlite3_step(pExplain)==SQLITE_ROW ){
- const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
- int iEqpId = sqlite3_column_int(pExplain, 0);
- int iParentId = sqlite3_column_int(pExplain, 1);
- if( zEQPLine[0]=='-' ) eqp_render(pArg);
- eqp_append(pArg, iEqpId, iParentId, zEQPLine);
- }
- eqp_render(pArg);
- }
- sqlite3_finalize(pExplain);
- sqlite3_free(zEQP);
- if( pArg->autoEQP>=AUTOEQP_full ){
- /* Also do an EXPLAIN for ".eqp full" mode */
- zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
- rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
- if( rc==SQLITE_OK ){
- pArg->cMode = MODE_Explain;
- explain_data_prepare(pArg, pExplain);
- exec_prepared_stmt(pArg, pExplain);
- explain_data_delete(pArg);
- }
- sqlite3_finalize(pExplain);
- sqlite3_free(zEQP);
- }
- if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
- sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
- /* Reprepare pStmt before reactiving trace modes */
- sqlite3_finalize(pStmt);
- sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- }
- restore_debug_trace_modes();
- }
-
- if( pArg ){
- pArg->cMode = pArg->mode;
- if( pArg->autoExplain ){
- if( sqlite3_column_count(pStmt)==8
- && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
- ){
- pArg->cMode = MODE_Explain;
- }
- if( sqlite3_column_count(pStmt)==4
- && sqlite3_strlike("EXPLAIN QUERY PLAN%", zStmtSql,0)==0 ){
- pArg->cMode = MODE_EQP;
- }
- }
-
- /* If the shell is currently in ".explain" mode, gather the extra
- ** data required to add indents to the output.*/
- if( pArg->cMode==MODE_Explain ){
- explain_data_prepare(pArg, pStmt);
- }
- }
-
- exec_prepared_stmt(pArg, pStmt);
- explain_data_delete(pArg);
- eqp_render(pArg);
-
- /* print usage stats if stats on */
- if( pArg && pArg->statsOn ){
- display_stats(db, pArg, 0);
- }
-
- /* print loop-counters if required */
- if( pArg && pArg->scanstatsOn ){
- display_scanstats(db, pArg);
- }
-
- /* Finalize the statement just executed. If this fails, save a
- ** copy of the error message. Otherwise, set zSql to point to the
- ** next statement to execute. */
- rc2 = sqlite3_finalize(pStmt);
- if( rc!=SQLITE_NOMEM ) rc = rc2;
- if( rc==SQLITE_OK ){
- zSql = zLeftover;
- while( IsSpace(zSql[0]) ) zSql++;
- }else if( pzErrMsg ){
- *pzErrMsg = save_err_msg(db);
- }
-
- /* clear saved stmt handle */
- if( pArg ){
- pArg->pStmt = NULL;
- }
- }
- } /* end while */
-
- return rc;
-}
-
-/*
-** Release memory previously allocated by tableColumnList().
-*/
-static void freeColumnList(char **azCol){
- int i;
- for(i=1; azCol[i]; i++){
- sqlite3_free(azCol[i]);
- }
- /* azCol[0] is a static string */
- sqlite3_free(azCol);
-}
-
-/*
-** Return a list of pointers to strings which are the names of all
-** columns in table zTab. The memory to hold the names is dynamically
-** allocated and must be released by the caller using a subsequent call
-** to freeColumnList().
-**
-** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
-** value that needs to be preserved, then azCol[0] is filled in with the
-** name of the rowid column.
-**
-** The first regular column in the table is azCol[1]. The list is terminated
-** by an entry with azCol[i]==0.
-*/
-static char **tableColumnList(ShellState *p, const char *zTab){
- char **azCol = 0;
- sqlite3_stmt *pStmt;
- char *zSql;
- int nCol = 0;
- int nAlloc = 0;
- int nPK = 0; /* Number of PRIMARY KEY columns seen */
- int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
- int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
- int rc;
-
- zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ) return 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- if( nCol>=nAlloc-2 ){
- nAlloc = nAlloc*2 + nCol + 10;
- azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
- if( azCol==0 ) shell_out_of_memory();
- }
- azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
- if( sqlite3_column_int(pStmt, 5) ){
- nPK++;
- if( nPK==1
- && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
- "INTEGER")==0
- ){
- isIPK = 1;
- }else{
- isIPK = 0;
- }
- }
- }
- sqlite3_finalize(pStmt);
- if( azCol==0 ) return 0;
- azCol[0] = 0;
- azCol[nCol+1] = 0;
-
- /* The decision of whether or not a rowid really needs to be preserved
- ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
- ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
- ** rowids on tables where the rowid is inaccessible because there are other
- ** columns in the table named "rowid", "_rowid_", and "oid".
- */
- if( preserveRowid && isIPK ){
- /* If a single PRIMARY KEY column with type INTEGER was seen, then it
- ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
- ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
- ** ROWID aliases. To distinguish these cases, check to see if
- ** there is a "pk" entry in "PRAGMA index_list". There will be
- ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
- */
- zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
- " WHERE origin='pk'", zTab);
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ){
- freeColumnList(azCol);
- return 0;
- }
- rc = sqlite3_step(pStmt);
- sqlite3_finalize(pStmt);
- preserveRowid = rc==SQLITE_ROW;
- }
- if( preserveRowid ){
- /* Only preserve the rowid if we can find a name to use for the
- ** rowid */
- static char *azRowid[] = { "rowid", "_rowid_", "oid" };
- int i, j;
- for(j=0; j<3; j++){
- for(i=1; i<=nCol; i++){
- if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
- }
- if( i>nCol ){
- /* At this point, we know that azRowid[j] is not the name of any
- ** ordinary column in the table. Verify that azRowid[j] is a valid
- ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
- ** tables will fail this last check */
- rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
- if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
- break;
- }
- }
- }
- return azCol;
-}
-
-/*
-** Toggle the reverse_unordered_selects setting.
-*/
-static void toggleSelectOrder(sqlite3 *db){
- sqlite3_stmt *pStmt = 0;
- int iSetting = 0;
- char zStmt[100];
- sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- iSetting = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- sqlite3_snprintf(sizeof(zStmt), zStmt,
- "PRAGMA reverse_unordered_selects(%d)", !iSetting);
- sqlite3_exec(db, zStmt, 0, 0, 0);
-}
-
-/*
-** This is a different callback routine used for dumping the database.
-** Each row received by this callback consists of a table name,
-** the table type ("index" or "table") and SQL to create the table.
-** This routine should print text sufficient to recreate the table.
-*/
-static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
- int rc;
- const char *zTable;
- const char *zType;
- const char *zSql;
- ShellState *p = (ShellState *)pArg;
-
- UNUSED_PARAMETER(azNotUsed);
- if( nArg!=3 || azArg==0 ) return 0;
- zTable = azArg[0];
- zType = azArg[1];
- zSql = azArg[2];
-
- if( strcmp(zTable, "sqlite_sequence")==0 ){
- raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
- }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
- raw_printf(p->out, "ANALYZE sqlite_master;\n");
- }else if( strncmp(zTable, "sqlite_", 7)==0 ){
- return 0;
- }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
- char *zIns;
- if( !p->writableSchema ){
- raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
- p->writableSchema = 1;
- }
- zIns = sqlite3_mprintf(
- "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
- "VALUES('table','%q','%q',0,'%q');",
- zTable, zTable, zSql);
- utf8_printf(p->out, "%s\n", zIns);
- sqlite3_free(zIns);
- return 0;
- }else{
- printSchemaLine(p->out, zSql, ";\n");
- }
-
- if( strcmp(zType, "table")==0 ){
- ShellText sSelect;
- ShellText sTable;
- char **azCol;
- int i;
- char *savedDestTable;
- int savedMode;
-
- azCol = tableColumnList(p, zTable);
- if( azCol==0 ){
- p->nErr++;
- return 0;
- }
-
- /* Always quote the table name, even if it appears to be pure ascii,
- ** in case it is a keyword. Ex: INSERT INTO "table" ... */
- initText(&sTable);
- appendText(&sTable, zTable, quoteChar(zTable));
- /* If preserving the rowid, add a column list after the table name.
- ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
- ** instead of the usual "INSERT INTO tab VALUES(...)".
- */
- if( azCol[0] ){
- appendText(&sTable, "(", 0);
- appendText(&sTable, azCol[0], 0);
- for(i=1; azCol[i]; i++){
- appendText(&sTable, ",", 0);
- appendText(&sTable, azCol[i], quoteChar(azCol[i]));
- }
- appendText(&sTable, ")", 0);
- }
-
- /* Build an appropriate SELECT statement */
- initText(&sSelect);
- appendText(&sSelect, "SELECT ", 0);
- if( azCol[0] ){
- appendText(&sSelect, azCol[0], 0);
- appendText(&sSelect, ",", 0);
- }
- for(i=1; azCol[i]; i++){
- appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
- if( azCol[i+1] ){
- appendText(&sSelect, ",", 0);
- }
- }
- freeColumnList(azCol);
- appendText(&sSelect, " FROM ", 0);
- appendText(&sSelect, zTable, quoteChar(zTable));
-
- savedDestTable = p->zDestTable;
- savedMode = p->mode;
- p->zDestTable = sTable.z;
- p->mode = p->cMode = MODE_Insert;
- rc = shell_exec(p, sSelect.z, 0);
- if( (rc&0xff)==SQLITE_CORRUPT ){
- raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
- toggleSelectOrder(p->db);
- shell_exec(p, sSelect.z, 0);
- toggleSelectOrder(p->db);
- }
- p->zDestTable = savedDestTable;
- p->mode = savedMode;
- freeText(&sTable);
- freeText(&sSelect);
- if( rc ) p->nErr++;
- }
- return 0;
-}
-
-/*
-** Run zQuery. Use dump_callback() as the callback routine so that
-** the contents of the query are output as SQL statements.
-**
-** If we get a SQLITE_CORRUPT error, rerun the query after appending
-** "ORDER BY rowid DESC" to the end.
-*/
-static int run_schema_dump_query(
- ShellState *p,
- const char *zQuery
-){
- int rc;
- char *zErr = 0;
- rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
- if( rc==SQLITE_CORRUPT ){
- char *zQ2;
- int len = strlen30(zQuery);
- raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
- if( zErr ){
- utf8_printf(p->out, "/****** %s ******/\n", zErr);
- sqlite3_free(zErr);
- zErr = 0;
- }
- zQ2 = malloc( len+100 );
- if( zQ2==0 ) return rc;
- sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
- rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
- if( rc ){
- utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
- }else{
- rc = SQLITE_CORRUPT;
- }
- sqlite3_free(zErr);
- free(zQ2);
- }
- return rc;
-}
-
-/*
-** Text of a help message
-*/
-static char zHelp[] =
-#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
- ".archive ... Manage SQL archives: \".archive --help\" for details\n"
-#endif
-#ifndef SQLITE_OMIT_AUTHORIZATION
- ".auth ON|OFF Show authorizer callbacks\n"
-#endif
- ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
- " Add \"--append\" to open using appendvfs.\n"
- ".bail on|off Stop after hitting an error. Default OFF\n"
- ".binary on|off Turn binary output on or off. Default OFF\n"
- ".cd DIRECTORY Change the working directory to DIRECTORY\n"
- ".changes on|off Show number of rows changed by SQL\n"
- ".check GLOB Fail if output since .testcase does not match\n"
- ".clone NEWDB Clone data into NEWDB from the existing database\n"
- ".databases List names and files of attached databases\n"
- ".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n"
- ".dbinfo ?DB? Show status information about the database\n"
- ".dump ?TABLE? ... Dump the database in an SQL text format\n"
- " If TABLE specified, only dump tables matching\n"
- " LIKE pattern TABLE.\n"
- ".echo on|off Turn command echo on or off\n"
- ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n"
- ".excel Display the output of next command in a spreadsheet\n"
- ".exit Exit this program\n"
- ".expert EXPERIMENTAL. Suggest indexes for specified queries\n"
-/* Because explain mode comes on automatically now, the ".explain" mode
-** is removed from the help screen. It is still supported for legacy, however */
-/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/
- ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
- ".headers on|off Turn display of headers on or off\n"
- ".help Show this message\n"
- ".import FILE TABLE Import data from FILE into TABLE\n"
-#ifndef SQLITE_OMIT_TEST_CONTROL
- ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n"
-#endif
- ".indexes ?TABLE? Show names of all indexes\n"
- " If TABLE specified, only show indexes for tables\n"
- " matching LIKE pattern TABLE.\n"
-#ifdef SQLITE_ENABLE_IOTRACE
- ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
-#endif
- ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
- ".lint OPTIONS Report potential schema issues. Options:\n"
- " fkey-indexes Find missing foreign key indexes\n"
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- ".load FILE ?ENTRY? Load an extension library\n"
-#endif
- ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
- ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
- " ascii Columns/rows delimited by 0x1F and 0x1E\n"
- " csv Comma-separated values\n"
- " column Left-aligned columns. (See .width)\n"
- " html HTML <table> code\n"
- " insert SQL insert statements for TABLE\n"
- " line One value per line\n"
- " list Values delimited by \"|\"\n"
- " quote Escape answers as for SQL\n"
- " tabs Tab-separated values\n"
- " tcl TCL list elements\n"
- ".nullvalue STRING Use STRING in place of NULL values\n"
- ".once (-e|-x|FILE) Output for the next SQL command only to FILE\n"
- " or invoke system text editor (-e) or spreadsheet (-x)\n"
- " on the output.\n"
- ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
- " The --new option starts with an empty file\n"
- " Other options: --readonly --append --zip\n"
- ".output ?FILE? Send output to FILE or stdout\n"
- ".print STRING... Print literal STRING\n"
- ".prompt MAIN CONTINUE Replace the standard prompts\n"
- ".quit Exit this program\n"
- ".read FILENAME Execute SQL in FILENAME\n"
- ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
- ".save FILE Write in-memory database into FILE\n"
- ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
- ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n"
- " Add --indent for pretty-printing\n"
- ".selftest ?--init? Run tests defined in the SELFTEST table\n"
- ".separator COL ?ROW? Change the column separator and optionally the row\n"
- " separator for both the output mode and .import\n"
-#if defined(SQLITE_ENABLE_SESSION)
- ".session CMD ... Create or control sessions\n"
-#endif
- ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n"
-#ifndef SQLITE_NOHAVE_SYSTEM
- ".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
-#endif
- ".show Show the current values for various settings\n"
- ".stats ?on|off? Show stats or turn stats on or off\n"
-#ifndef SQLITE_NOHAVE_SYSTEM
- ".system CMD ARGS... Run CMD ARGS... in a system shell\n"
-#endif
- ".tables ?TABLE? List names of tables\n"
- " If TABLE specified, only list tables matching\n"
- " LIKE pattern TABLE.\n"
- ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n"
- ".timeout MS Try opening locked tables for MS milliseconds\n"
- ".timer on|off Turn SQL timer on or off\n"
- ".trace FILE|off Output each SQL statement as it is run\n"
- ".vfsinfo ?AUX? Information about the top-level VFS\n"
- ".vfslist List all available VFSes\n"
- ".vfsname ?AUX? Print the name of the VFS stack\n"
- ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
- " Negative values right-justify\n"
-;
-
-#if defined(SQLITE_ENABLE_SESSION)
-/*
-** Print help information for the ".sessions" command
-*/
-void session_help(ShellState *p){
- raw_printf(p->out,
- ".session ?NAME? SUBCOMMAND ?ARGS...?\n"
- "If ?NAME? is omitted, the first defined session is used.\n"
- "Subcommands:\n"
- " attach TABLE Attach TABLE\n"
- " changeset FILE Write a changeset into FILE\n"
- " close Close one session\n"
- " enable ?BOOLEAN? Set or query the enable bit\n"
- " filter GLOB... Reject tables matching GLOBs\n"
- " indirect ?BOOLEAN? Mark or query the indirect status\n"
- " isempty Query whether the session is empty\n"
- " list List currently open session names\n"
- " open DB NAME Open a new session on DB\n"
- " patchset FILE Write a patchset into FILE\n"
- );
-}
-#endif
-
-
-/* Forward reference */
-static int process_input(ShellState *p, FILE *in);
-
-/*
-** Read the content of file zName into memory obtained from sqlite3_malloc64()
-** and return a pointer to the buffer. The caller is responsible for freeing
-** the memory.
-**
-** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
-** read.
-**
-** For convenience, a nul-terminator byte is always appended to the data read
-** from the file before the buffer is returned. This byte is not included in
-** the final value of (*pnByte), if applicable.
-**
-** NULL is returned if any error is encountered. The final value of *pnByte
-** is undefined in this case.
-*/
-static char *readFile(const char *zName, int *pnByte){
- FILE *in = fopen(zName, "rb");
- long nIn;
- size_t nRead;
- char *pBuf;
- if( in==0 ) return 0;
- fseek(in, 0, SEEK_END);
- nIn = ftell(in);
- rewind(in);
- pBuf = sqlite3_malloc64( nIn+1 );
- if( pBuf==0 ) return 0;
- nRead = fread(pBuf, nIn, 1, in);
- fclose(in);
- if( nRead!=1 ){
- sqlite3_free(pBuf);
- return 0;
- }
- pBuf[nIn] = 0;
- if( pnByte ) *pnByte = nIn;
- return pBuf;
-}
-
-#if defined(SQLITE_ENABLE_SESSION)
-/*
-** Close a single OpenSession object and release all of its associated
-** resources.
-*/
-static void session_close(OpenSession *pSession){
- int i;
- sqlite3session_delete(pSession->p);
- sqlite3_free(pSession->zName);
- for(i=0; i<pSession->nFilter; i++){
- sqlite3_free(pSession->azFilter[i]);
- }
- sqlite3_free(pSession->azFilter);
- memset(pSession, 0, sizeof(OpenSession));
-}
-#endif
-
-/*
-** Close all OpenSession objects and release all associated resources.
-*/
-#if defined(SQLITE_ENABLE_SESSION)
-static void session_close_all(ShellState *p){
- int i;
- for(i=0; i<p->nSession; i++){
- session_close(&p->aSession[i]);
- }
- p->nSession = 0;
-}
-#else
-# define session_close_all(X)
-#endif
-
-/*
-** Implementation of the xFilter function for an open session. Omit
-** any tables named by ".session filter" but let all other table through.
-*/
-#if defined(SQLITE_ENABLE_SESSION)
-static int session_filter(void *pCtx, const char *zTab){
- OpenSession *pSession = (OpenSession*)pCtx;
- int i;
- for(i=0; i<pSession->nFilter; i++){
- if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
- }
- return 1;
-}
-#endif
-
-/*
-** Try to deduce the type of file for zName based on its content. Return
-** one of the SHELL_OPEN_* constants.
-**
-** If the file does not exist or is empty but its name looks like a ZIP
-** archive and the dfltZip flag is true, then assume it is a ZIP archive.
-** Otherwise, assume an ordinary database regardless of the filename if
-** the type cannot be determined from content.
-*/
-int deduceDatabaseType(const char *zName, int dfltZip){
- FILE *f = fopen(zName, "rb");
- size_t n;
- int rc = SHELL_OPEN_UNSPEC;
- char zBuf[100];
- if( f==0 ){
- if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
- return SHELL_OPEN_ZIPFILE;
- }else{
- return SHELL_OPEN_NORMAL;
- }
- }
- fseek(f, -25, SEEK_END);
- n = fread(zBuf, 25, 1, f);
- if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
- rc = SHELL_OPEN_APPENDVFS;
- }else{
- fseek(f, -22, SEEK_END);
- n = fread(zBuf, 22, 1, f);
- if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
- && zBuf[3]==0x06 ){
- rc = SHELL_OPEN_ZIPFILE;
- }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
- rc = SHELL_OPEN_ZIPFILE;
- }
- }
- fclose(f);
- return rc;
-}
-
-/* Flags for open_db().
-**
-** The default behavior of open_db() is to exit(1) if the database fails to
-** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
-** but still returns without calling exit.
-**
-** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
-** ZIP archive if the file does not exist or is empty and its name matches
-** the *.zip pattern.
-*/
-#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
-#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
-
-/*
-** Make sure the database is open. If it is not, then open it. If
-** the database fails to open, print an error message and exit.
-*/
-static void open_db(ShellState *p, int openFlags){
- if( p->db==0 ){
- if( p->openMode==SHELL_OPEN_UNSPEC ){
- if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
- p->openMode = SHELL_OPEN_NORMAL;
- }else{
- p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
- (openFlags & OPEN_DB_ZIPFILE)!=0);
- }
- }
- switch( p->openMode ){
- case SHELL_OPEN_APPENDVFS: {
- sqlite3_open_v2(p->zDbFilename, &p->db,
- SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
- break;
- }
- case SHELL_OPEN_ZIPFILE: {
- sqlite3_open(":memory:", &p->db);
- break;
- }
- case SHELL_OPEN_READONLY: {
- sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
- break;
- }
- case SHELL_OPEN_UNSPEC:
- case SHELL_OPEN_NORMAL: {
- sqlite3_open(p->zDbFilename, &p->db);
- break;
- }
- }
- globalDb = p->db;
- if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
- utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
- p->zDbFilename, sqlite3_errmsg(p->db));
- if( openFlags & OPEN_DB_KEEPALIVE ) return;
- exit(1);
- }
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- sqlite3_enable_load_extension(p->db, 1);
-#endif
- sqlite3_fileio_init(p->db, 0, 0);
- sqlite3_shathree_init(p->db, 0, 0);
- sqlite3_completion_init(p->db, 0, 0);
-#ifdef SQLITE_HAVE_ZLIB
- sqlite3_zipfile_init(p->db, 0, 0);
- sqlite3_sqlar_init(p->db, 0, 0);
-#endif
- sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
- shellAddSchemaName, 0, 0);
- sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
- shellModuleSchema, 0, 0);
- sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
- shellPutsFunc, 0, 0);
-#ifndef SQLITE_NOHAVE_SYSTEM
- sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
- editFunc, 0, 0);
- sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
- editFunc, 0, 0);
-#endif
- if( p->openMode==SHELL_OPEN_ZIPFILE ){
- char *zSql = sqlite3_mprintf(
- "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
- sqlite3_exec(p->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
- }
-}
-
-/*
-** Attempt to close the databaes connection. Report errors.
-*/
-void close_db(sqlite3 *db){
- int rc = sqlite3_close(db);
- if( rc ){
- utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
- rc, sqlite3_errmsg(db));
- }
-}
-
-#if HAVE_READLINE || HAVE_EDITLINE
-/*
-** Readline completion callbacks
-*/
-static char *readline_completion_generator(const char *text, int state){
- static sqlite3_stmt *pStmt = 0;
- char *zRet;
- if( state==0 ){
- char *zSql;
- sqlite3_finalize(pStmt);
- zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
- " FROM completion(%Q) ORDER BY 1", text);
- sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- }
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
- }else{
- sqlite3_finalize(pStmt);
- pStmt = 0;
- zRet = 0;
- }
- return zRet;
-}
-static char **readline_completion(const char *zText, int iStart, int iEnd){
- rl_attempted_completion_over = 1;
- return rl_completion_matches(zText, readline_completion_generator);
-}
-
-#elif HAVE_LINENOISE
-/*
-** Linenoise completion callback
-*/
-static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
- int nLine = strlen30(zLine);
- int i, iStart;
- sqlite3_stmt *pStmt = 0;
- char *zSql;
- char zBuf[1000];
-
- if( nLine>sizeof(zBuf)-30 ) return;
- if( zLine[0]=='.' || zLine[0]=='#') return;
- for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
- if( i==nLine-1 ) return;
- iStart = i+1;
- memcpy(zBuf, zLine, iStart);
- zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
- " FROM completion(%Q,%Q) ORDER BY 1",
- &zLine[iStart], zLine);
- sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
- int nCompletion = sqlite3_column_bytes(pStmt, 0);
- if( iStart+nCompletion < sizeof(zBuf)-1 ){
- memcpy(zBuf+iStart, zCompletion, nCompletion+1);
- linenoiseAddCompletion(lc, zBuf);
- }
- }
- sqlite3_finalize(pStmt);
-}
-#endif
-
-/*
-** Do C-language style dequoting.
-**
-** \a -> alarm
-** \b -> backspace
-** \t -> tab
-** \n -> newline
-** \v -> vertical tab
-** \f -> form feed
-** \r -> carriage return
-** \s -> space
-** \" -> "
-** \' -> '
-** \\ -> backslash
-** \NNN -> ascii character NNN in octal
-*/
-static void resolve_backslashes(char *z){
- int i, j;
- char c;
- while( *z && *z!='\\' ) z++;
- for(i=j=0; (c = z[i])!=0; i++, j++){
- if( c=='\\' && z[i+1]!=0 ){
- c = z[++i];
- if( c=='a' ){
- c = '\a';
- }else if( c=='b' ){
- c = '\b';
- }else if( c=='t' ){
- c = '\t';
- }else if( c=='n' ){
- c = '\n';
- }else if( c=='v' ){
- c = '\v';
- }else if( c=='f' ){
- c = '\f';
- }else if( c=='r' ){
- c = '\r';
- }else if( c=='"' ){
- c = '"';
- }else if( c=='\'' ){
- c = '\'';
- }else if( c=='\\' ){
- c = '\\';
- }else if( c>='0' && c<='7' ){
- c -= '0';
- if( z[i+1]>='0' && z[i+1]<='7' ){
- i++;
- c = (c<<3) + z[i] - '0';
- if( z[i+1]>='0' && z[i+1]<='7' ){
- i++;
- c = (c<<3) + z[i] - '0';
- }
- }
- }
- }
- z[j] = c;
- }
- if( j<i ) z[j] = 0;
-}
-
-/*
-** Interpret zArg as either an integer or a boolean value. Return 1 or 0
-** for TRUE and FALSE. Return the integer value if appropriate.
-*/
-static int booleanValue(const char *zArg){
- int i;
- if( zArg[0]=='0' && zArg[1]=='x' ){
- for(i=2; hexDigitValue(zArg[i])>=0; i++){}
- }else{
- for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
- }
- if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
- if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
- return 1;
- }
- if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
- return 0;
- }
- utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
- zArg);
- return 0;
-}
-
-/*
-** Set or clear a shell flag according to a boolean value.
-*/
-static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
- if( booleanValue(zArg) ){
- ShellSetFlag(p, mFlag);
- }else{
- ShellClearFlag(p, mFlag);
- }
-}
-
-/*
-** Close an output file, assuming it is not stderr or stdout
-*/
-static void output_file_close(FILE *f){
- if( f && f!=stdout && f!=stderr ) fclose(f);
-}
-
-/*
-** Try to open an output file. The names "stdout" and "stderr" are
-** recognized and do the right thing. NULL is returned if the output
-** filename is "off".
-*/
-static FILE *output_file_open(const char *zFile, int bTextMode){
- FILE *f;
- if( strcmp(zFile,"stdout")==0 ){
- f = stdout;
- }else if( strcmp(zFile, "stderr")==0 ){
- f = stderr;
- }else if( strcmp(zFile, "off")==0 ){
- f = 0;
- }else{
- f = fopen(zFile, bTextMode ? "w" : "wb");
- if( f==0 ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
- }
- }
- return f;
-}
-
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
-/*
-** A routine for handling output from sqlite3_trace().
-*/
-static int sql_trace_callback(
- unsigned mType,
- void *pArg,
- void *pP,
- void *pX
-){
- FILE *f = (FILE*)pArg;
- UNUSED_PARAMETER(mType);
- UNUSED_PARAMETER(pP);
- if( f ){
- const char *z = (const char*)pX;
- int i = strlen30(z);
- while( i>0 && z[i-1]==';' ){ i--; }
- utf8_printf(f, "%.*s;\n", i, z);
- }
- return 0;
-}
-#endif
-
-/*
-** A no-op routine that runs with the ".breakpoint" doc-command. This is
-** a useful spot to set a debugger breakpoint.
-*/
-static void test_breakpoint(void){
- static int nCall = 0;
- nCall++;
-}
-
-/*
-** An object used to read a CSV and other files for import.
-*/
-typedef struct ImportCtx ImportCtx;
-struct ImportCtx {
- const char *zFile; /* Name of the input file */
- FILE *in; /* Read the CSV text from this input stream */
- char *z; /* Accumulated text for a field */
- int n; /* Number of bytes in z */
- int nAlloc; /* Space allocated for z[] */
- int nLine; /* Current line number */
- int bNotFirst; /* True if one or more bytes already read */
- int cTerm; /* Character that terminated the most recent field */
- int cColSep; /* The column separator character. (Usually ",") */
- int cRowSep; /* The row separator character. (Usually "\n") */
-};
-
-/* Append a single byte to z[] */
-static void import_append_char(ImportCtx *p, int c){
- if( p->n+1>=p->nAlloc ){
- p->nAlloc += p->nAlloc + 100;
- p->z = sqlite3_realloc64(p->z, p->nAlloc);
- if( p->z==0 ) shell_out_of_memory();
- }
- p->z[p->n++] = (char)c;
-}
-
-/* Read a single field of CSV text. Compatible with rfc4180 and extended
-** with the option of having a separator other than ",".
-**
-** + Input comes from p->in.
-** + Store results in p->z of length p->n. Space to hold p->z comes
-** from sqlite3_malloc64().
-** + Use p->cSep as the column separator. The default is ",".
-** + Use p->rSep as the row separator. The default is "\n".
-** + Keep track of the line number in p->nLine.
-** + Store the character that terminates the field in p->cTerm. Store
-** EOF on end-of-file.
-** + Report syntax errors on stderr
-*/
-static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
- int c;
- int cSep = p->cColSep;
- int rSep = p->cRowSep;
- p->n = 0;
- c = fgetc(p->in);
- if( c==EOF || seenInterrupt ){
- p->cTerm = EOF;
- return 0;
- }
- if( c=='"' ){
- int pc, ppc;
- int startLine = p->nLine;
- int cQuote = c;
- pc = ppc = 0;
- while( 1 ){
- c = fgetc(p->in);
- if( c==rSep ) p->nLine++;
- if( c==cQuote ){
- if( pc==cQuote ){
- pc = 0;
- continue;
- }
- }
- if( (c==cSep && pc==cQuote)
- || (c==rSep && pc==cQuote)
- || (c==rSep && pc=='\r' && ppc==cQuote)
- || (c==EOF && pc==cQuote)
- ){
- do{ p->n--; }while( p->z[p->n]!=cQuote );
- p->cTerm = c;
- break;
- }
- if( pc==cQuote && c!='\r' ){
- utf8_printf(stderr, "%s:%d: unescaped %c character\n",
- p->zFile, p->nLine, cQuote);
- }
- if( c==EOF ){
- utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
- p->zFile, startLine, cQuote);
- p->cTerm = c;
- break;
- }
- import_append_char(p, c);
- ppc = pc;
- pc = c;
- }
- }else{
- /* If this is the first field being parsed and it begins with the
- ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
- if( (c&0xff)==0xef && p->bNotFirst==0 ){
- import_append_char(p, c);
- c = fgetc(p->in);
- if( (c&0xff)==0xbb ){
- import_append_char(p, c);
- c = fgetc(p->in);
- if( (c&0xff)==0xbf ){
- p->bNotFirst = 1;
- p->n = 0;
- return csv_read_one_field(p);
- }
- }
- }
- while( c!=EOF && c!=cSep && c!=rSep ){
- import_append_char(p, c);
- c = fgetc(p->in);
- }
- if( c==rSep ){
- p->nLine++;
- if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
- }
- p->cTerm = c;
- }
- if( p->z ) p->z[p->n] = 0;
- p->bNotFirst = 1;
- return p->z;
-}
-
-/* Read a single field of ASCII delimited text.
-**
-** + Input comes from p->in.
-** + Store results in p->z of length p->n. Space to hold p->z comes
-** from sqlite3_malloc64().
-** + Use p->cSep as the column separator. The default is "\x1F".
-** + Use p->rSep as the row separator. The default is "\x1E".
-** + Keep track of the row number in p->nLine.
-** + Store the character that terminates the field in p->cTerm. Store
-** EOF on end-of-file.
-** + Report syntax errors on stderr
-*/
-static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
- int c;
- int cSep = p->cColSep;
- int rSep = p->cRowSep;
- p->n = 0;
- c = fgetc(p->in);
- if( c==EOF || seenInterrupt ){
- p->cTerm = EOF;
- return 0;
- }
- while( c!=EOF && c!=cSep && c!=rSep ){
- import_append_char(p, c);
- c = fgetc(p->in);
- }
- if( c==rSep ){
- p->nLine++;
- }
- p->cTerm = c;
- if( p->z ) p->z[p->n] = 0;
- return p->z;
-}
-
-/*
-** Try to transfer data for table zTable. If an error is seen while
-** moving forward, try to go backwards. The backwards movement won't
-** work for WITHOUT ROWID tables.
-*/
-static void tryToCloneData(
- ShellState *p,
- sqlite3 *newDb,
- const char *zTable
-){
- sqlite3_stmt *pQuery = 0;
- sqlite3_stmt *pInsert = 0;
- char *zQuery = 0;
- char *zInsert = 0;
- int rc;
- int i, j, n;
- int nTable = strlen30(zTable);
- int k = 0;
- int cnt = 0;
- const int spinRate = 10000;
-
- zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
- rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
- if( rc ){
- utf8_printf(stderr, "Error %d: %s on [%s]\n",
- sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
- zQuery);
- goto end_data_xfer;
- }
- n = sqlite3_column_count(pQuery);
- zInsert = sqlite3_malloc64(200 + nTable + n*3);
- if( zInsert==0 ) shell_out_of_memory();
- sqlite3_snprintf(200+nTable,zInsert,
- "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
- i = strlen30(zInsert);
- for(j=1; j<n; j++){
- memcpy(zInsert+i, ",?", 2);
- i += 2;
- }
- memcpy(zInsert+i, ");", 3);
- rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
- if( rc ){
- utf8_printf(stderr, "Error %d: %s on [%s]\n",
- sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
- zQuery);
- goto end_data_xfer;
- }
- for(k=0; k<2; k++){
- while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
- for(i=0; i<n; i++){
- switch( sqlite3_column_type(pQuery, i) ){
- case SQLITE_NULL: {
- sqlite3_bind_null(pInsert, i+1);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
- break;
- }
- case SQLITE_FLOAT: {
- sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
- break;
- }
- case SQLITE_TEXT: {
- sqlite3_bind_text(pInsert, i+1,
- (const char*)sqlite3_column_text(pQuery,i),
- -1, SQLITE_STATIC);
- break;
- }
- case SQLITE_BLOB: {
- sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
- sqlite3_column_bytes(pQuery,i),
- SQLITE_STATIC);
- break;
- }
- }
- } /* End for */
- rc = sqlite3_step(pInsert);
- if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
- utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
- sqlite3_errmsg(newDb));
- }
- sqlite3_reset(pInsert);
- cnt++;
- if( (cnt%spinRate)==0 ){
- printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
- fflush(stdout);
- }
- } /* End while */
- if( rc==SQLITE_DONE ) break;
- sqlite3_finalize(pQuery);
- sqlite3_free(zQuery);
- zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
- zTable);
- rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
- if( rc ){
- utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
- break;
- }
- } /* End for(k=0...) */
-
-end_data_xfer:
- sqlite3_finalize(pQuery);
- sqlite3_finalize(pInsert);
- sqlite3_free(zQuery);
- sqlite3_free(zInsert);
-}
-
-
-/*
-** Try to transfer all rows of the schema that match zWhere. For
-** each row, invoke xForEach() on the object defined by that row.
-** If an error is encountered while moving forward through the
-** sqlite_master table, try again moving backwards.
-*/
-static void tryToCloneSchema(
- ShellState *p,
- sqlite3 *newDb,
- const char *zWhere,
- void (*xForEach)(ShellState*,sqlite3*,const char*)
-){
- sqlite3_stmt *pQuery = 0;
- char *zQuery = 0;
- int rc;
- const unsigned char *zName;
- const unsigned char *zSql;
- char *zErrMsg = 0;
-
- zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
- " WHERE %s", zWhere);
- rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
- if( rc ){
- utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
- sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
- zQuery);
- goto end_schema_xfer;
- }
- while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
- zName = sqlite3_column_text(pQuery, 0);
- zSql = sqlite3_column_text(pQuery, 1);
- printf("%s... ", zName); fflush(stdout);
- sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
- sqlite3_free(zErrMsg);
- zErrMsg = 0;
- }
- if( xForEach ){
- xForEach(p, newDb, (const char*)zName);
- }
- printf("done\n");
- }
- if( rc!=SQLITE_DONE ){
- sqlite3_finalize(pQuery);
- sqlite3_free(zQuery);
- zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
- " WHERE %s ORDER BY rowid DESC", zWhere);
- rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
- if( rc ){
- utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
- sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
- zQuery);
- goto end_schema_xfer;
- }
- while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
- zName = sqlite3_column_text(pQuery, 0);
- zSql = sqlite3_column_text(pQuery, 1);
- printf("%s... ", zName); fflush(stdout);
- sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
- sqlite3_free(zErrMsg);
- zErrMsg = 0;
- }
- if( xForEach ){
- xForEach(p, newDb, (const char*)zName);
- }
- printf("done\n");
- }
- }
-end_schema_xfer:
- sqlite3_finalize(pQuery);
- sqlite3_free(zQuery);
-}
-
-/*
-** Open a new database file named "zNewDb". Try to recover as much information
-** as possible out of the main database (which might be corrupt) and write it
-** into zNewDb.
-*/
-static void tryToClone(ShellState *p, const char *zNewDb){
- int rc;
- sqlite3 *newDb = 0;
- if( access(zNewDb,0)==0 ){
- utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
- return;
- }
- rc = sqlite3_open(zNewDb, &newDb);
- if( rc ){
- utf8_printf(stderr, "Cannot create output database: %s\n",
- sqlite3_errmsg(newDb));
- }else{
- sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
- sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
- tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
- tryToCloneSchema(p, newDb, "type!='table'", 0);
- sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
- sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
- }
- close_db(newDb);
-}
-
-/*
-** Change the output file back to stdout.
-**
-** If the p->doXdgOpen flag is set, that means the output was being
-** redirected to a temporary file named by p->zTempFile. In that case,
-** launch start/open/xdg-open on that temporary file.
-*/
-static void output_reset(ShellState *p){
- if( p->outfile[0]=='|' ){
-#ifndef SQLITE_OMIT_POPEN
- pclose(p->out);
-#endif
- }else{
- output_file_close(p->out);
-#ifndef SQLITE_NOHAVE_SYSTEM
- if( p->doXdgOpen ){
- const char *zXdgOpenCmd =
-#if defined(_WIN32)
- "start";
-#elif defined(__APPLE__)
- "open";
-#else
- "xdg-open";
-#endif
- char *zCmd;
- zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
- if( system(zCmd) ){
- utf8_printf(stderr, "Failed: [%s]\n", zCmd);
- }
- sqlite3_free(zCmd);
- outputModePop(p);
- p->doXdgOpen = 0;
- }
-#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
- }
- p->outfile[0] = 0;
- p->out = stdout;
-}
-
-/*
-** Run an SQL command and return the single integer result.
-*/
-static int db_int(ShellState *p, const char *zSql){
- sqlite3_stmt *pStmt;
- int res = 0;
- sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
- res = sqlite3_column_int(pStmt,0);
- }
- sqlite3_finalize(pStmt);
- return res;
-}
-
-/*
-** Convert a 2-byte or 4-byte big-endian integer into a native integer
-*/
-static unsigned int get2byteInt(unsigned char *a){
- return (a[0]<<8) + a[1];
-}
-static unsigned int get4byteInt(unsigned char *a){
- return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
-}
-
-/*
-** Implementation of the ".info" command.
-**
-** Return 1 on error, 2 to exit, and 0 otherwise.
-*/
-static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
- static const struct { const char *zName; int ofst; } aField[] = {
- { "file change counter:", 24 },
- { "database page count:", 28 },
- { "freelist page count:", 36 },
- { "schema cookie:", 40 },
- { "schema format:", 44 },
- { "default cache size:", 48 },
- { "autovacuum top root:", 52 },
- { "incremental vacuum:", 64 },
- { "text encoding:", 56 },
- { "user version:", 60 },
- { "application id:", 68 },
- { "software version:", 96 },
- };
- static const struct { const char *zName; const char *zSql; } aQuery[] = {
- { "number of tables:",
- "SELECT count(*) FROM %s WHERE type='table'" },
- { "number of indexes:",
- "SELECT count(*) FROM %s WHERE type='index'" },
- { "number of triggers:",
- "SELECT count(*) FROM %s WHERE type='trigger'" },
- { "number of views:",
- "SELECT count(*) FROM %s WHERE type='view'" },
- { "schema size:",
- "SELECT total(length(sql)) FROM %s" },
- };
- int i;
- char *zSchemaTab;
- char *zDb = nArg>=2 ? azArg[1] : "main";
- sqlite3_stmt *pStmt = 0;
- unsigned char aHdr[100];
- open_db(p, 0);
- if( p->db==0 ) return 1;
- sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
- -1, &pStmt, 0);
- sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
- if( sqlite3_step(pStmt)==SQLITE_ROW
- && sqlite3_column_bytes(pStmt,0)>100
- ){
- memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
- sqlite3_finalize(pStmt);
- }else{
- raw_printf(stderr, "unable to read database header\n");
- sqlite3_finalize(pStmt);
- return 1;
- }
- i = get2byteInt(aHdr+16);
- if( i==1 ) i = 65536;
- utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
- utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
- utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
- utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
- for(i=0; i<ArraySize(aField); i++){
- int ofst = aField[i].ofst;
- unsigned int val = get4byteInt(aHdr + ofst);
- utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
- switch( ofst ){
- case 56: {
- if( val==1 ) raw_printf(p->out, " (utf8)");
- if( val==2 ) raw_printf(p->out, " (utf16le)");
- if( val==3 ) raw_printf(p->out, " (utf16be)");
- }
- }
- raw_printf(p->out, "\n");
- }
- if( zDb==0 ){
- zSchemaTab = sqlite3_mprintf("main.sqlite_master");
- }else if( strcmp(zDb,"temp")==0 ){
- zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
- }else{
- zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
- }
- for(i=0; i<ArraySize(aQuery); i++){
- char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
- int val = db_int(p, zSql);
- sqlite3_free(zSql);
- utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
- }
- sqlite3_free(zSchemaTab);
- return 0;
-}
-
-/*
-** Print the current sqlite3_errmsg() value to stderr and return 1.
-*/
-static int shellDatabaseError(sqlite3 *db){
- const char *zErr = sqlite3_errmsg(db);
- utf8_printf(stderr, "Error: %s\n", zErr);
- return 1;
-}
-
-/*
-** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
-** if they match and FALSE (0) if they do not match.
-**
-** Globbing rules:
-**
-** '*' Matches any sequence of zero or more characters.
-**
-** '?' Matches exactly one character.
-**
-** [...] Matches one character from the enclosed list of
-** characters.
-**
-** [^...] Matches one character not in the enclosed list.
-**
-** '#' Matches any sequence of one or more digits with an
-** optional + or - sign in front
-**
-** ' ' Any span of whitespace matches any other span of
-** whitespace.
-**
-** Extra whitespace at the end of z[] is ignored.
-*/
-static int testcase_glob(const char *zGlob, const char *z){
- int c, c2;
- int invert;
- int seen;
-
- while( (c = (*(zGlob++)))!=0 ){
- if( IsSpace(c) ){
- if( !IsSpace(*z) ) return 0;
- while( IsSpace(*zGlob) ) zGlob++;
- while( IsSpace(*z) ) z++;
- }else if( c=='*' ){
- while( (c=(*(zGlob++))) == '*' || c=='?' ){
- if( c=='?' && (*(z++))==0 ) return 0;
- }
- if( c==0 ){
- return 1;
- }else if( c=='[' ){
- while( *z && testcase_glob(zGlob-1,z)==0 ){
- z++;
- }
- return (*z)!=0;
- }
- while( (c2 = (*(z++)))!=0 ){
- while( c2!=c ){
- c2 = *(z++);
- if( c2==0 ) return 0;
- }
- if( testcase_glob(zGlob,z) ) return 1;
- }
- return 0;
- }else if( c=='?' ){
- if( (*(z++))==0 ) return 0;
- }else if( c=='[' ){
- int prior_c = 0;
- seen = 0;
- invert = 0;
- c = *(z++);
- if( c==0 ) return 0;
- c2 = *(zGlob++);
- if( c2=='^' ){
- invert = 1;
- c2 = *(zGlob++);
- }
- if( c2==']' ){
- if( c==']' ) seen = 1;
- c2 = *(zGlob++);
- }
- while( c2 && c2!=']' ){
- if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
- c2 = *(zGlob++);
- if( c>=prior_c && c<=c2 ) seen = 1;
- prior_c = 0;
- }else{
- if( c==c2 ){
- seen = 1;
- }
- prior_c = c2;
- }
- c2 = *(zGlob++);
- }
- if( c2==0 || (seen ^ invert)==0 ) return 0;
- }else if( c=='#' ){
- if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
- if( !IsDigit(z[0]) ) return 0;
- z++;
- while( IsDigit(z[0]) ){ z++; }
- }else{
- if( c!=(*(z++)) ) return 0;
- }
- }
- while( IsSpace(*z) ){ z++; }
- return *z==0;
-}
-
-
-/*
-** Compare the string as a command-line option with either one or two
-** initial "-" characters.
-*/
-static int optionMatch(const char *zStr, const char *zOpt){
- if( zStr[0]!='-' ) return 0;
- zStr++;
- if( zStr[0]=='-' ) zStr++;
- return strcmp(zStr, zOpt)==0;
-}
-
-/*
-** Delete a file.
-*/
-int shellDeleteFile(const char *zFilename){
- int rc;
-#ifdef _WIN32
- wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
- rc = _wunlink(z);
- sqlite3_free(z);
-#else
- rc = unlink(zFilename);
-#endif
- return rc;
-}
-
-/*
-** Try to delete the temporary file (if there is one) and free the
-** memory used to hold the name of the temp file.
-*/
-static void clearTempFile(ShellState *p){
- if( p->zTempFile==0 ) return;
- if( p->doXdgOpen ) return;
- if( shellDeleteFile(p->zTempFile) ) return;
- sqlite3_free(p->zTempFile);
- p->zTempFile = 0;
-}
-
-/*
-** Create a new temp file name with the given suffix.
-*/
-static void newTempFile(ShellState *p, const char *zSuffix){
- clearTempFile(p);
- sqlite3_free(p->zTempFile);
- p->zTempFile = 0;
- if( p->db ){
- sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
- }
- if( p->zTempFile==0 ){
- sqlite3_uint64 r;
- sqlite3_randomness(sizeof(r), &r);
- p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix);
- }else{
- p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
- }
- if( p->zTempFile==0 ){
- raw_printf(stderr, "out of memory\n");
- exit(1);
- }
-}
-
-
-/*
-** The implementation of SQL scalar function fkey_collate_clause(), used
-** by the ".lint fkey-indexes" command. This scalar function is always
-** called with four arguments - the parent table name, the parent column name,
-** the child table name and the child column name.
-**
-** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
-**
-** If either of the named tables or columns do not exist, this function
-** returns an empty string. An empty string is also returned if both tables
-** and columns exist but have the same default collation sequence. Or,
-** if both exist but the default collation sequences are different, this
-** function returns the string " COLLATE <parent-collation>", where
-** <parent-collation> is the default collation sequence of the parent column.
-*/
-static void shellFkeyCollateClause(
- sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal
-){
- sqlite3 *db = sqlite3_context_db_handle(pCtx);
- const char *zParent;
- const char *zParentCol;
- const char *zParentSeq;
- const char *zChild;
- const char *zChildCol;
- const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
- int rc;
-
- assert( nVal==4 );
- zParent = (const char*)sqlite3_value_text(apVal[0]);
- zParentCol = (const char*)sqlite3_value_text(apVal[1]);
- zChild = (const char*)sqlite3_value_text(apVal[2]);
- zChildCol = (const char*)sqlite3_value_text(apVal[3]);
-
- sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
- rc = sqlite3_table_column_metadata(
- db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3_table_column_metadata(
- db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
- );
- }
-
- if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
- char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
- sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
- sqlite3_free(z);
- }
-}
-
-
-/*
-** The implementation of dot-command ".lint fkey-indexes".
-*/
-static int lintFkeyIndexes(
- ShellState *pState, /* Current shell tool state */
- char **azArg, /* Array of arguments passed to dot command */
- int nArg /* Number of entries in azArg[] */
-){
- sqlite3 *db = pState->db; /* Database handle to query "main" db of */
- FILE *out = pState->out; /* Stream to write non-error output to */
- int bVerbose = 0; /* If -verbose is present */
- int bGroupByParent = 0; /* If -groupbyparent is present */
- int i; /* To iterate through azArg[] */
- const char *zIndent = ""; /* How much to indent CREATE INDEX by */
- int rc; /* Return code */
- sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
-
- /*
- ** This SELECT statement returns one row for each foreign key constraint
- ** in the schema of the main database. The column values are:
- **
- ** 0. The text of an SQL statement similar to:
- **
- ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
- **
- ** This SELECT is similar to the one that the foreign keys implementation
- ** needs to run internally on child tables. If there is an index that can
- ** be used to optimize this query, then it can also be used by the FK
- ** implementation to optimize DELETE or UPDATE statements on the parent
- ** table.
- **
- ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
- ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
- ** contains an index that can be used to optimize the query.
- **
- ** 2. Human readable text that describes the child table and columns. e.g.
- **
- ** "child_table(child_key1, child_key2)"
- **
- ** 3. Human readable text that describes the parent table and columns. e.g.
- **
- ** "parent_table(parent_key1, parent_key2)"
- **
- ** 4. A full CREATE INDEX statement for an index that could be used to
- ** optimize DELETE or UPDATE statements on the parent table. e.g.
- **
- ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
- **
- ** 5. The name of the parent table.
- **
- ** These six values are used by the C logic below to generate the report.
- */
- const char *zSql =
- "SELECT "
- " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
- " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
- " || fkey_collate_clause("
- " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
- ", "
- " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
- " || group_concat('*=?', ' AND ') || ')'"
- ", "
- " s.name || '(' || group_concat(f.[from], ', ') || ')'"
- ", "
- " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
- ", "
- " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
- " || ' ON ' || quote(s.name) || '('"
- " || group_concat(quote(f.[from]) ||"
- " fkey_collate_clause("
- " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
- " || ');'"
- ", "
- " f.[table] "
- "FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f "
- "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
- "GROUP BY s.name, f.id "
- "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
- ;
- const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
-
- for(i=2; i<nArg; i++){
- int n = strlen30(azArg[i]);
- if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
- bVerbose = 1;
- }
- else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
- bGroupByParent = 1;
- zIndent = " ";
- }
- else{
- raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
- azArg[0], azArg[1]
- );
- return SQLITE_ERROR;
- }
- }
-
- /* Register the fkey_collate_clause() SQL function */
- rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
- 0, shellFkeyCollateClause, 0, 0
- );
-
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
- }
- if( rc==SQLITE_OK ){
- sqlite3_bind_int(pSql, 1, bGroupByParent);
- }
-
- if( rc==SQLITE_OK ){
- int rc2;
- char *zPrev = 0;
- while( SQLITE_ROW==sqlite3_step(pSql) ){
- int res = -1;
- sqlite3_stmt *pExplain = 0;
- const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
- const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
- const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
- const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
- const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
- const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
-
- rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
- if( rc!=SQLITE_OK ) break;
- if( SQLITE_ROW==sqlite3_step(pExplain) ){
- const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
- res = (
- 0==sqlite3_strglob(zGlob, zPlan)
- || 0==sqlite3_strglob(zGlobIPK, zPlan)
- );
- }
- rc = sqlite3_finalize(pExplain);
- if( rc!=SQLITE_OK ) break;
-
- if( res<0 ){
- raw_printf(stderr, "Error: internal error");
- break;
- }else{
- if( bGroupByParent
- && (bVerbose || res==0)
- && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
- ){
- raw_printf(out, "-- Parent table %s\n", zParent);
- sqlite3_free(zPrev);
- zPrev = sqlite3_mprintf("%s", zParent);
- }
-
- if( res==0 ){
- raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
- }else if( bVerbose ){
- raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
- zIndent, zFrom, zTarget
- );
- }
- }
- }
- sqlite3_free(zPrev);
-
- if( rc!=SQLITE_OK ){
- raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
- }
-
- rc2 = sqlite3_finalize(pSql);
- if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
- rc = rc2;
- raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
- }
- }else{
- raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
- }
-
- return rc;
-}
-
-/*
-** Implementation of ".lint" dot command.
-*/
-static int lintDotCommand(
- ShellState *pState, /* Current shell tool state */
- char **azArg, /* Array of arguments passed to dot command */
- int nArg /* Number of entries in azArg[] */
-){
- int n;
- n = (nArg>=2 ? strlen30(azArg[1]) : 0);
- if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
- return lintFkeyIndexes(pState, azArg, nArg);
-
- usage:
- raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
- raw_printf(stderr, "Where sub-commands are:\n");
- raw_printf(stderr, " fkey-indexes\n");
- return SQLITE_ERROR;
-}
-
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
-/*********************************************************************************
-** The ".archive" or ".ar" command.
-*/
-static void shellPrepare(
- sqlite3 *db,
- int *pRc,
- const char *zSql,
- sqlite3_stmt **ppStmt
-){
- *ppStmt = 0;
- if( *pRc==SQLITE_OK ){
- int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
- if( rc!=SQLITE_OK ){
- raw_printf(stderr, "sql error: %s (%d)\n",
- sqlite3_errmsg(db), sqlite3_errcode(db)
- );
- *pRc = rc;
- }
- }
-}
-
-static void shellPreparePrintf(
- sqlite3 *db,
- int *pRc,
- sqlite3_stmt **ppStmt,
- const char *zFmt,
- ...
-){
- *ppStmt = 0;
- if( *pRc==SQLITE_OK ){
- va_list ap;
- char *z;
- va_start(ap, zFmt);
- z = sqlite3_vmprintf(zFmt, ap);
- if( z==0 ){
- *pRc = SQLITE_NOMEM;
- }else{
- shellPrepare(db, pRc, z, ppStmt);
- sqlite3_free(z);
- }
- }
-}
-
-static void shellFinalize(
- int *pRc,
- sqlite3_stmt *pStmt
-){
- if( pStmt ){
- sqlite3 *db = sqlite3_db_handle(pStmt);
- int rc = sqlite3_finalize(pStmt);
- if( *pRc==SQLITE_OK ){
- if( rc!=SQLITE_OK ){
- raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
- }
- *pRc = rc;
- }
- }
-}
-
-static void shellReset(
- int *pRc,
- sqlite3_stmt *pStmt
-){
- int rc = sqlite3_reset(pStmt);
- if( *pRc==SQLITE_OK ){
- if( rc!=SQLITE_OK ){
- sqlite3 *db = sqlite3_db_handle(pStmt);
- raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
- }
- *pRc = rc;
- }
-}
-/*
-** Structure representing a single ".ar" command.
-*/
-typedef struct ArCommand ArCommand;
-struct ArCommand {
- u8 eCmd; /* An AR_CMD_* value */
- u8 bVerbose; /* True if --verbose */
- u8 bZip; /* True if the archive is a ZIP */
- u8 bDryRun; /* True if --dry-run */
- u8 bAppend; /* True if --append */
- u8 fromCmdLine; /* Run from -A instead of .archive */
- int nArg; /* Number of command arguments */
- char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
- const char *zFile; /* --file argument, or NULL */
- const char *zDir; /* --directory argument, or NULL */
- char **azArg; /* Array of command arguments */
- ShellState *p; /* Shell state */
- sqlite3 *db; /* Database containing the archive */
-};
-
-/*
-** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
-*/
-static int arUsage(FILE *f){
- raw_printf(f,
-"\n"
-"Usage: .ar [OPTION...] [FILE...]\n"
-"The .ar command manages sqlar archives.\n"
-"\n"
-"Examples:\n"
-" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n"
-" .ar -tf archive.sar # List members of archive.sar\n"
-" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n"
-"\n"
-"Each command line must feature exactly one command option:\n"
-" -c, --create Create a new archive\n"
-" -u, --update Update or add files to an existing archive\n"
-" -t, --list List contents of archive\n"
-" -x, --extract Extract files from archive\n"
-"\n"
-"And zero or more optional options:\n"
-" -v, --verbose Print each filename as it is processed\n"
-" -f FILE, --file FILE Operate on archive FILE (default is current db)\n"
-" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n"
-" -C DIR, --directory DIR Change to directory DIR to read/extract files\n"
-" -n, --dryrun Show the SQL that would have occurred\n"
-"\n"
-"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
-"\n"
-);
- return SQLITE_ERROR;
-}
-
-/*
-** Print an error message for the .ar command to stderr and return
-** SQLITE_ERROR.
-*/
-static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
- va_list ap;
- char *z;
- va_start(ap, zFmt);
- z = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
- utf8_printf(stderr, "Error: %s\n", z);
- if( pAr->fromCmdLine ){
- utf8_printf(stderr, "Use \"-A\" for more help\n");
- }else{
- utf8_printf(stderr, "Use \".archive --help\" for more help\n");
- }
- sqlite3_free(z);
- return SQLITE_ERROR;
-}
-
-/*
-** Values for ArCommand.eCmd.
-*/
-#define AR_CMD_CREATE 1
-#define AR_CMD_EXTRACT 2
-#define AR_CMD_LIST 3
-#define AR_CMD_UPDATE 4
-#define AR_CMD_HELP 5
-
-/*
-** Other (non-command) switches.
-*/
-#define AR_SWITCH_VERBOSE 6
-#define AR_SWITCH_FILE 7
-#define AR_SWITCH_DIRECTORY 8
-#define AR_SWITCH_APPEND 9
-#define AR_SWITCH_DRYRUN 10
-
-static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
- switch( eSwitch ){
- case AR_CMD_CREATE:
- case AR_CMD_EXTRACT:
- case AR_CMD_LIST:
- case AR_CMD_UPDATE:
- case AR_CMD_HELP:
- if( pAr->eCmd ){
- return arErrorMsg(pAr, "multiple command options");
- }
- pAr->eCmd = eSwitch;
- break;
-
- case AR_SWITCH_DRYRUN:
- pAr->bDryRun = 1;
- break;
- case AR_SWITCH_VERBOSE:
- pAr->bVerbose = 1;
- break;
- case AR_SWITCH_APPEND:
- pAr->bAppend = 1;
- /* Fall thru into --file */
- case AR_SWITCH_FILE:
- pAr->zFile = zArg;
- break;
- case AR_SWITCH_DIRECTORY:
- pAr->zDir = zArg;
- break;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Parse the command line for an ".ar" command. The results are written into
-** structure (*pAr). SQLITE_OK is returned if the command line is parsed
-** successfully, otherwise an error message is written to stderr and
-** SQLITE_ERROR returned.
-*/
-static int arParseCommand(
- char **azArg, /* Array of arguments passed to dot command */
- int nArg, /* Number of entries in azArg[] */
- ArCommand *pAr /* Populate this object */
-){
- struct ArSwitch {
- const char *zLong;
- char cShort;
- u8 eSwitch;
- u8 bArg;
- } aSwitch[] = {
- { "create", 'c', AR_CMD_CREATE, 0 },
- { "extract", 'x', AR_CMD_EXTRACT, 0 },
- { "list", 't', AR_CMD_LIST, 0 },
- { "update", 'u', AR_CMD_UPDATE, 0 },
- { "help", 'h', AR_CMD_HELP, 0 },
- { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
- { "file", 'f', AR_SWITCH_FILE, 1 },
- { "append", 'a', AR_SWITCH_APPEND, 1 },
- { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
- { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
- };
- int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
- struct ArSwitch *pEnd = &aSwitch[nSwitch];
-
- if( nArg<=1 ){
- return arUsage(stderr);
- }else{
- char *z = azArg[1];
- if( z[0]!='-' ){
- /* Traditional style [tar] invocation */
- int i;
- int iArg = 2;
- for(i=0; z[i]; i++){
- const char *zArg = 0;
- struct ArSwitch *pOpt;
- for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
- if( z[i]==pOpt->cShort ) break;
- }
- if( pOpt==pEnd ){
- return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
- }
- if( pOpt->bArg ){
- if( iArg>=nArg ){
- return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
- }
- zArg = azArg[iArg++];
- }
- if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
- }
- pAr->nArg = nArg-iArg;
- if( pAr->nArg>0 ){
- pAr->azArg = &azArg[iArg];
- }
- }else{
- /* Non-traditional invocation */
- int iArg;
- for(iArg=1; iArg<nArg; iArg++){
- int n;
- z = azArg[iArg];
- if( z[0]!='-' ){
- /* All remaining command line words are command arguments. */
- pAr->azArg = &azArg[iArg];
- pAr->nArg = nArg-iArg;
- break;
- }
- n = strlen30(z);
-
- if( z[1]!='-' ){
- int i;
- /* One or more short options */
- for(i=1; i<n; i++){
- const char *zArg = 0;
- struct ArSwitch *pOpt;
- for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
- if( z[i]==pOpt->cShort ) break;
- }
- if( pOpt==pEnd ){
- return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
- }
- if( pOpt->bArg ){
- if( i<(n-1) ){
- zArg = &z[i+1];
- i = n;
- }else{
- if( iArg>=(nArg-1) ){
- return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
- }
- zArg = azArg[++iArg];
- }
- }
- if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
- }
- }else if( z[2]=='\0' ){
- /* A -- option, indicating that all remaining command line words
- ** are command arguments. */
- pAr->azArg = &azArg[iArg+1];
- pAr->nArg = nArg-iArg-1;
- break;
- }else{
- /* A long option */
- const char *zArg = 0; /* Argument for option, if any */
- struct ArSwitch *pMatch = 0; /* Matching option */
- struct ArSwitch *pOpt; /* Iterator */
- for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
- const char *zLong = pOpt->zLong;
- if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
- if( pMatch ){
- return arErrorMsg(pAr, "ambiguous option: %s",z);
- }else{
- pMatch = pOpt;
- }
- }
- }
-
- if( pMatch==0 ){
- return arErrorMsg(pAr, "unrecognized option: %s", z);
- }
- if( pMatch->bArg ){
- if( iArg>=(nArg-1) ){
- return arErrorMsg(pAr, "option requires an argument: %s", z);
- }
- zArg = azArg[++iArg];
- }
- if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
- }
- }
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** This function assumes that all arguments within the ArCommand.azArg[]
-** array refer to archive members, as for the --extract or --list commands.
-** It checks that each of them are present. If any specified file is not
-** present in the archive, an error is printed to stderr and an error
-** code returned. Otherwise, if all specified arguments are present in
-** the archive, SQLITE_OK is returned.
-**
-** This function strips any trailing '/' characters from each argument.
-** This is consistent with the way the [tar] command seems to work on
-** Linux.
-*/
-static int arCheckEntries(ArCommand *pAr){
- int rc = SQLITE_OK;
- if( pAr->nArg ){
- int i, j;
- sqlite3_stmt *pTest = 0;
-
- shellPreparePrintf(pAr->db, &rc, &pTest,
- "SELECT name FROM %s WHERE name=$name",
- pAr->zSrcTable
- );
- j = sqlite3_bind_parameter_index(pTest, "$name");
- for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
- char *z = pAr->azArg[i];
- int n = strlen30(z);
- int bOk = 0;
- while( n>0 && z[n-1]=='/' ) n--;
- z[n] = '\0';
- sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
- if( SQLITE_ROW==sqlite3_step(pTest) ){
- bOk = 1;
- }
- shellReset(&rc, pTest);
- if( rc==SQLITE_OK && bOk==0 ){
- utf8_printf(stderr, "not found in archive: %s\n", z);
- rc = SQLITE_ERROR;
- }
- }
- shellFinalize(&rc, pTest);
- }
- return rc;
-}
-
-/*
-** Format a WHERE clause that can be used against the "sqlar" table to
-** identify all archive members that match the command arguments held
-** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
-** The caller is responsible for eventually calling sqlite3_free() on
-** any non-NULL (*pzWhere) value.
-*/
-static void arWhereClause(
- int *pRc,
- ArCommand *pAr,
- char **pzWhere /* OUT: New WHERE clause */
-){
- char *zWhere = 0;
- if( *pRc==SQLITE_OK ){
- if( pAr->nArg==0 ){
- zWhere = sqlite3_mprintf("1");
- }else{
- int i;
- const char *zSep = "";
- for(i=0; i<pAr->nArg; i++){
- const char *z = pAr->azArg[i];
- zWhere = sqlite3_mprintf(
- "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
- zWhere, zSep, z, strlen30(z)+1, z
- );
- if( zWhere==0 ){
- *pRc = SQLITE_NOMEM;
- break;
- }
- zSep = " OR ";
- }
- }
- }
- *pzWhere = zWhere;
-}
-
-/*
-** Implementation of .ar "lisT" command.
-*/
-static int arListCommand(ArCommand *pAr){
- const char *zSql = "SELECT %s FROM %s WHERE %s";
- const char *azCols[] = {
- "name",
- "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
- };
-
- char *zWhere = 0;
- sqlite3_stmt *pSql = 0;
- int rc;
-
- rc = arCheckEntries(pAr);
- arWhereClause(&rc, pAr, &zWhere);
-
- shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
- pAr->zSrcTable, zWhere);
- if( pAr->bDryRun ){
- utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
- }else{
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
- if( pAr->bVerbose ){
- utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
- sqlite3_column_text(pSql, 0),
- sqlite3_column_int(pSql, 1),
- sqlite3_column_text(pSql, 2),
- sqlite3_column_text(pSql, 3)
- );
- }else{
- utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
- }
- }
- }
- shellFinalize(&rc, pSql);
- sqlite3_free(zWhere);
- return rc;
-}
-
-
-/*
-** Implementation of .ar "eXtract" command.
-*/
-static int arExtractCommand(ArCommand *pAr){
- const char *zSql1 =
- "SELECT "
- " ($dir || name),"
- " writefile(($dir || name), %s, mode, mtime) "
- "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)";
-
- const char *azExtraArg[] = {
- "sqlar_uncompress(data, sz)",
- "data"
- };
-
- sqlite3_stmt *pSql = 0;
- int rc = SQLITE_OK;
- char *zDir = 0;
- char *zWhere = 0;
- int i, j;
-
- /* If arguments are specified, check that they actually exist within
- ** the archive before proceeding. And formulate a WHERE clause to
- ** match them. */
- rc = arCheckEntries(pAr);
- arWhereClause(&rc, pAr, &zWhere);
-
- if( rc==SQLITE_OK ){
- if( pAr->zDir ){
- zDir = sqlite3_mprintf("%s/", pAr->zDir);
- }else{
- zDir = sqlite3_mprintf("");
- }
- if( zDir==0 ) rc = SQLITE_NOMEM;
- }
-
- shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
- azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
- );
-
- if( rc==SQLITE_OK ){
- j = sqlite3_bind_parameter_index(pSql, "$dir");
- sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
-
- /* Run the SELECT statement twice. The first time, writefile() is called
- ** for all archive members that should be extracted. The second time,
- ** only for the directories. This is because the timestamps for
- ** extracted directories must be reset after they are populated (as
- ** populating them changes the timestamp). */
- for(i=0; i<2; i++){
- j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
- sqlite3_bind_int(pSql, j, i);
- if( pAr->bDryRun ){
- utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
- }else{
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
- if( i==0 && pAr->bVerbose ){
- utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
- }
- }
- }
- shellReset(&rc, pSql);
- }
- shellFinalize(&rc, pSql);
- }
-
- sqlite3_free(zDir);
- sqlite3_free(zWhere);
- return rc;
-}
-
-/*
-** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
-*/
-static int arExecSql(ArCommand *pAr, const char *zSql){
- int rc;
- if( pAr->bDryRun ){
- utf8_printf(pAr->p->out, "%s\n", zSql);
- rc = SQLITE_OK;
- }else{
- char *zErr = 0;
- rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
- if( zErr ){
- utf8_printf(stdout, "ERROR: %s\n", zErr);
- sqlite3_free(zErr);
- }
- }
- return rc;
-}
-
-
-/*
-** Implementation of .ar "create" and "update" commands.
-**
-** Create the "sqlar" table in the database if it does not already exist.
-** Then add each file in the azFile[] array to the archive. Directories
-** are added recursively. If argument bVerbose is non-zero, a message is
-** printed on stdout for each file archived.
-**
-** The create command is the same as update, except that it drops
-** any existing "sqlar" table before beginning.
-*/
-static int arCreateOrUpdateCommand(
- ArCommand *pAr, /* Command arguments and options */
- int bUpdate /* true for a --create. false for --update */
-){
- const char *zCreate =
- "CREATE TABLE IF NOT EXISTS sqlar(\n"
- " name TEXT PRIMARY KEY, -- name of the file\n"
- " mode INT, -- access permissions\n"
- " mtime INT, -- last modification time\n"
- " sz INT, -- original file size\n"
- " data BLOB -- compressed content\n"
- ")";
- const char *zDrop = "DROP TABLE IF EXISTS sqlar";
- const char *zInsertFmt[2] = {
- "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
- " SELECT\n"
- " %s,\n"
- " mode,\n"
- " mtime,\n"
- " CASE substr(lsmode(mode),1,1)\n"
- " WHEN '-' THEN length(data)\n"
- " WHEN 'd' THEN 0\n"
- " ELSE -1 END,\n"
- " sqlar_compress(data)\n"
- " FROM fsdir(%Q,%Q)\n"
- " WHERE lsmode(mode) NOT LIKE '?%%';",
- "REPLACE INTO %s(name,mode,mtime,data)\n"
- " SELECT\n"
- " %s,\n"
- " mode,\n"
- " mtime,\n"
- " data\n"
- " FROM fsdir(%Q,%Q)\n"
- " WHERE lsmode(mode) NOT LIKE '?%%';"
- };
- int i; /* For iterating through azFile[] */
- int rc; /* Return code */
- const char *zTab = 0; /* SQL table into which to insert */
- char *zSql;
- char zTemp[50];
-
- arExecSql(pAr, "PRAGMA page_size=512");
- rc = arExecSql(pAr, "SAVEPOINT ar;");
- if( rc!=SQLITE_OK ) return rc;
- zTemp[0] = 0;
- if( pAr->bZip ){
- /* Initialize the zipfile virtual table, if necessary */
- if( pAr->zFile ){
- sqlite3_uint64 r;
- sqlite3_randomness(sizeof(r),&r);
- sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
- zTab = zTemp;
- zSql = sqlite3_mprintf(
- "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
- zTab, pAr->zFile
- );
- rc = arExecSql(pAr, zSql);
- sqlite3_free(zSql);
- }else{
- zTab = "zip";
- }
- }else{
- /* Initialize the table for an SQLAR */
- zTab = "sqlar";
- if( bUpdate==0 ){
- rc = arExecSql(pAr, zDrop);
- if( rc!=SQLITE_OK ) goto end_ar_transaction;
- }
- rc = arExecSql(pAr, zCreate);
- }
- for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
- char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
- pAr->bVerbose ? "shell_putsnl(name)" : "name",
- pAr->azArg[i], pAr->zDir);
- rc = arExecSql(pAr, zSql2);
- sqlite3_free(zSql2);
- }
-end_ar_transaction:
- if( rc!=SQLITE_OK ){
- arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;");
- }else{
- rc = arExecSql(pAr, "RELEASE ar;");
- if( pAr->bZip && pAr->zFile ){
- zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
- arExecSql(pAr, zSql);
- sqlite3_free(zSql);
- }
- }
- return rc;
-}
-
-/*
-** Implementation of ".ar" dot command.
-*/
-static int arDotCommand(
- ShellState *pState, /* Current shell tool state */
- int fromCmdLine, /* True if -A command-line option, not .ar cmd */
- char **azArg, /* Array of arguments passed to dot command */
- int nArg /* Number of entries in azArg[] */
-){
- ArCommand cmd;
- int rc;
- memset(&cmd, 0, sizeof(cmd));
- cmd.fromCmdLine = fromCmdLine;
- rc = arParseCommand(azArg, nArg, &cmd);
- if( rc==SQLITE_OK ){
- int eDbType = SHELL_OPEN_UNSPEC;
- cmd.p = pState;
- cmd.db = pState->db;
- if( cmd.zFile ){
- eDbType = deduceDatabaseType(cmd.zFile, 1);
- }else{
- eDbType = pState->openMode;
- }
- if( eDbType==SHELL_OPEN_ZIPFILE ){
- if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
- if( cmd.zFile==0 ){
- cmd.zSrcTable = sqlite3_mprintf("zip");
- }else{
- cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
- }
- }
- cmd.bZip = 1;
- }else if( cmd.zFile ){
- int flags;
- if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
- if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
- flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
- }else{
- flags = SQLITE_OPEN_READONLY;
- }
- cmd.db = 0;
- if( cmd.bDryRun ){
- utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
- eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
- }
- rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
- eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "cannot open file: %s (%s)\n",
- cmd.zFile, sqlite3_errmsg(cmd.db)
- );
- goto end_ar_command;
- }
- sqlite3_fileio_init(cmd.db, 0, 0);
- sqlite3_sqlar_init(cmd.db, 0, 0);
- sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
- shellPutsFunc, 0, 0);
-
- }
- if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
- if( cmd.eCmd!=AR_CMD_CREATE
- && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
- ){
- utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
- rc = SQLITE_ERROR;
- goto end_ar_command;
- }
- cmd.zSrcTable = sqlite3_mprintf("sqlar");
- }
-
- switch( cmd.eCmd ){
- case AR_CMD_CREATE:
- rc = arCreateOrUpdateCommand(&cmd, 0);
- break;
-
- case AR_CMD_EXTRACT:
- rc = arExtractCommand(&cmd);
- break;
-
- case AR_CMD_LIST:
- rc = arListCommand(&cmd);
- break;
-
- case AR_CMD_HELP:
- arUsage(pState->out);
- break;
-
- default:
- assert( cmd.eCmd==AR_CMD_UPDATE );
- rc = arCreateOrUpdateCommand(&cmd, 1);
- break;
- }
- }
-end_ar_command:
- if( cmd.db!=pState->db ){
- close_db(cmd.db);
- }
- sqlite3_free(cmd.zSrcTable);
-
- return rc;
-}
-/* End of the ".archive" or ".ar" command logic
-**********************************************************************************/
-#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
-
-
-/*
-** If an input line begins with "." then invoke this routine to
-** process that line.
-**
-** Return 1 on error, 2 to exit, and 0 otherwise.
-*/
-static int do_meta_command(char *zLine, ShellState *p){
- int h = 1;
- int nArg = 0;
- int n, c;
- int rc = 0;
- char *azArg[50];
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( p->expert.pExpert ){
- expertFinish(p, 1, 0);
- }
-#endif
-
- /* Parse the input line into tokens.
- */
- while( zLine[h] && nArg<ArraySize(azArg) ){
- while( IsSpace(zLine[h]) ){ h++; }
- if( zLine[h]==0 ) break;
- if( zLine[h]=='\'' || zLine[h]=='"' ){
- int delim = zLine[h++];
- azArg[nArg++] = &zLine[h];
- while( zLine[h] && zLine[h]!=delim ){
- if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
- h++;
- }
- if( zLine[h]==delim ){
- zLine[h++] = 0;
- }
- if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
- }else{
- azArg[nArg++] = &zLine[h];
- while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
- if( zLine[h] ) zLine[h++] = 0;
- resolve_backslashes(azArg[nArg-1]);
- }
- }
-
- /* Process the input line.
- */
- if( nArg==0 ) return 0; /* no tokens, no error */
- n = strlen30(azArg[0]);
- c = azArg[0][0];
- clearTempFile(p);
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .auth ON|OFF\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- if( booleanValue(azArg[1]) ){
- sqlite3_set_authorizer(p->db, shellAuth, p);
- }else{
- sqlite3_set_authorizer(p->db, 0, 0);
- }
- }else
-#endif
-
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
- if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
- open_db(p, 0);
- rc = arDotCommand(p, 0, azArg, nArg);
- }else
-#endif
-
- if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
- || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
- ){
- const char *zDestFile = 0;
- const char *zDb = 0;
- sqlite3 *pDest;
- sqlite3_backup *pBackup;
- int j;
- const char *zVfs = 0;
- for(j=1; j<nArg; j++){
- const char *z = azArg[j];
- if( z[0]=='-' ){
- if( z[1]=='-' ) z++;
- if( strcmp(z, "-append")==0 ){
- zVfs = "apndvfs";
- }else
- {
- utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
- return 1;
- }
- }else if( zDestFile==0 ){
- zDestFile = azArg[j];
- }else if( zDb==0 ){
- zDb = zDestFile;
- zDestFile = azArg[j];
- }else{
- raw_printf(stderr, "Usage: .backup ?DB? ?--append? FILENAME\n");
- return 1;
- }
- }
- if( zDestFile==0 ){
- raw_printf(stderr, "missing FILENAME argument on .backup\n");
- return 1;
- }
- if( zDb==0 ) zDb = "main";
- rc = sqlite3_open_v2(zDestFile, &pDest,
- SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
- close_db(pDest);
- return 1;
- }
- open_db(p, 0);
- pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
- if( pBackup==0 ){
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
- close_db(pDest);
- return 1;
- }
- while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
- sqlite3_backup_finish(pBackup);
- if( rc==SQLITE_DONE ){
- rc = 0;
- }else{
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
- rc = 1;
- }
- close_db(pDest);
- }else
-
- if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
- if( nArg==2 ){
- bail_on_error = booleanValue(azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .bail on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
- if( nArg==2 ){
- if( booleanValue(azArg[1]) ){
- setBinaryMode(p->out, 1);
- }else{
- setTextMode(p->out, 1);
- }
- }else{
- raw_printf(stderr, "Usage: .binary on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='c' && strcmp(azArg[0],"cd")==0 ){
- if( nArg==2 ){
-#if defined(_WIN32) || defined(WIN32)
- wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
- rc = !SetCurrentDirectoryW(z);
- sqlite3_free(z);
-#else
- rc = chdir(azArg[1]);
-#endif
- if( rc ){
- utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
- rc = 1;
- }
- }else{
- raw_printf(stderr, "Usage: .cd DIRECTORY\n");
- rc = 1;
- }
- }else
-
- /* The undocumented ".breakpoint" command causes a call to the no-op
- ** routine named test_breakpoint().
- */
- if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
- test_breakpoint();
- }else
-
- if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
- if( nArg==2 ){
- setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .changes on|off\n");
- rc = 1;
- }
- }else
-
- /* Cancel output redirection, if it is currently set (by .testcase)
- ** Then read the content of the testcase-out.txt file and compare against
- ** azArg[1]. If there are differences, report an error and exit.
- */
- if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
- char *zRes = 0;
- output_reset(p);
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
- rc = 2;
- }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
- raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
- rc = 2;
- }else if( testcase_glob(azArg[1],zRes)==0 ){
- utf8_printf(stderr,
- "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
- p->zTestcase, azArg[1], zRes);
- rc = 1;
- }else{
- utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
- p->nCheck++;
- }
- sqlite3_free(zRes);
- }else
-
- if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
- if( nArg==2 ){
- tryToClone(p, azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .clone FILENAME\n");
- rc = 1;
- }
- }else
-
- if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
- ShellState data;
- char *zErrMsg = 0;
- open_db(p, 0);
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_List;
- sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
- data.cnt = 0;
- sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
- callback, &data, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- rc = 1;
- }
- }else
-
- if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
- static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = {
- { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
- { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
- { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
- { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
- { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
- { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
- { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
- { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
- };
- int ii, v;
- open_db(p, 0);
- for(ii=0; ii<ArraySize(aDbConfig); ii++){
- if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
- if( nArg>=3 ){
- sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
- }
- sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
- utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
- if( nArg>1 ) break;
- }
- if( nArg>1 && ii==ArraySize(aDbConfig) ){
- utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
- utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
- }
- }else
-
- if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
- rc = shell_dbinfo_command(p, nArg, azArg);
- }else
-
- if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
- const char *zLike = 0;
- int i;
- int savedShowHeader = p->showHeader;
- ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines);
- for(i=1; i<nArg; i++){
- if( azArg[i][0]=='-' ){
- const char *z = azArg[i]+1;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"preserve-rowids")==0 ){
-#ifdef SQLITE_OMIT_VIRTUALTABLE
- raw_printf(stderr, "The --preserve-rowids option is not compatible"
- " with SQLITE_OMIT_VIRTUALTABLE\n");
- rc = 1;
- goto meta_command_exit;
-#else
- ShellSetFlag(p, SHFLG_PreserveRowid);
-#endif
- }else
- if( strcmp(z,"newlines")==0 ){
- ShellSetFlag(p, SHFLG_Newlines);
- }else
- {
- raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
- rc = 1;
- goto meta_command_exit;
- }
- }else if( zLike ){
- raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "
- "?--newlines? ?LIKE-PATTERN?\n");
- rc = 1;
- goto meta_command_exit;
- }else{
- zLike = azArg[i];
- }
- }
- open_db(p, 0);
- /* When playing back a "dump", the content might appear in an order
- ** which causes immediate foreign key constraints to be violated.
- ** So disable foreign-key constraint enforcement to prevent problems. */
- raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
- raw_printf(p->out, "BEGIN TRANSACTION;\n");
- p->writableSchema = 0;
- p->showHeader = 0;
- /* Set writable_schema=ON since doing so forces SQLite to initialize
- ** as much of the schema as it can even if the sqlite_master table is
- ** corrupt. */
- sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
- p->nErr = 0;
- if( zLike==0 ){
- run_schema_dump_query(p,
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
- );
- run_schema_dump_query(p,
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE name=='sqlite_sequence'"
- );
- run_table_dump_query(p,
- "SELECT sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
- );
- }else{
- char *zSql;
- zSql = sqlite3_mprintf(
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE tbl_name LIKE %Q AND type=='table'"
- " AND sql NOT NULL", zLike);
- run_schema_dump_query(p,zSql);
- sqlite3_free(zSql);
- zSql = sqlite3_mprintf(
- "SELECT sql FROM sqlite_master "
- "WHERE sql NOT NULL"
- " AND type IN ('index','trigger','view')"
- " AND tbl_name LIKE %Q", zLike);
- run_table_dump_query(p, zSql, 0);
- sqlite3_free(zSql);
- }
- if( p->writableSchema ){
- raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
- p->writableSchema = 0;
- }
- sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
- sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
- raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
- p->showHeader = savedShowHeader;
- }else
-
- if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
- if( nArg==2 ){
- setOrClearFlag(p, SHFLG_Echo, azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .echo on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
- if( nArg==2 ){
- p->autoEQPtest = 0;
- if( strcmp(azArg[1],"full")==0 ){
- p->autoEQP = AUTOEQP_full;
- }else if( strcmp(azArg[1],"trigger")==0 ){
- p->autoEQP = AUTOEQP_trigger;
- }else if( strcmp(azArg[1],"test")==0 ){
- p->autoEQP = AUTOEQP_on;
- p->autoEQPtest = 1;
- }else{
- p->autoEQP = (u8)booleanValue(azArg[1]);
- }
- }else{
- raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n");
- rc = 1;
- }
- }else
-
- if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
- if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
- rc = 2;
- }else
-
- /* The ".explain" command is automatic now. It is largely pointless. It
- ** retained purely for backwards compatibility */
- if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
- int val = 1;
- if( nArg>=2 ){
- if( strcmp(azArg[1],"auto")==0 ){
- val = 99;
- }else{
- val = booleanValue(azArg[1]);
- }
- }
- if( val==1 && p->mode!=MODE_Explain ){
- p->normalMode = p->mode;
- p->mode = MODE_Explain;
- p->autoExplain = 0;
- }else if( val==0 ){
- if( p->mode==MODE_Explain ) p->mode = p->normalMode;
- p->autoExplain = 0;
- }else if( val==99 ){
- if( p->mode==MODE_Explain ) p->mode = p->normalMode;
- p->autoExplain = 1;
- }
- }else
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
- open_db(p, 0);
- expertDotCommand(p, azArg, nArg);
- }else
-#endif
-
- if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
- ShellState data;
- char *zErrMsg = 0;
- int doStats = 0;
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_Semi;
- if( nArg==2 && optionMatch(azArg[1], "indent") ){
- data.cMode = data.mode = MODE_Pretty;
- nArg = 1;
- }
- if( nArg!=1 ){
- raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- rc = sqlite3_exec(p->db,
- "SELECT sql FROM"
- " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
- " FROM sqlite_master UNION ALL"
- " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
- "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
- "ORDER BY rowid",
- callback, &data, &zErrMsg
- );
- if( rc==SQLITE_OK ){
- sqlite3_stmt *pStmt;
- rc = sqlite3_prepare_v2(p->db,
- "SELECT rowid FROM sqlite_master"
- " WHERE name GLOB 'sqlite_stat[134]'",
- -1, &pStmt, 0);
- doStats = sqlite3_step(pStmt)==SQLITE_ROW;
- sqlite3_finalize(pStmt);
- }
- if( doStats==0 ){
- raw_printf(p->out, "/* No STAT tables available */\n");
- }else{
- raw_printf(p->out, "ANALYZE sqlite_master;\n");
- sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
- callback, &data, &zErrMsg);
- data.cMode = data.mode = MODE_Insert;
- data.zDestTable = "sqlite_stat1";
- shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
- data.zDestTable = "sqlite_stat3";
- shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg);
- data.zDestTable = "sqlite_stat4";
- shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
- raw_printf(p->out, "ANALYZE sqlite_master;\n");
- }
- }else
-
- if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
- if( nArg==2 ){
- p->showHeader = booleanValue(azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .headers on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
- utf8_printf(p->out, "%s", zHelp);
- }else
-
- if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
- char *zTable; /* Insert data into this table */
- char *zFile; /* Name of file to extra content from */
- sqlite3_stmt *pStmt = NULL; /* A statement */
- int nCol; /* Number of columns in the table */
- int nByte; /* Number of bytes in an SQL string */
- int i, j; /* Loop counters */
- int needCommit; /* True to COMMIT or ROLLBACK at end */
- int nSep; /* Number of bytes in p->colSeparator[] */
- char *zSql; /* An SQL statement */
- ImportCtx sCtx; /* Reader context */
- char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
- int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
-
- if( nArg!=3 ){
- raw_printf(stderr, "Usage: .import FILE TABLE\n");
- goto meta_command_exit;
- }
- zFile = azArg[1];
- zTable = azArg[2];
- seenInterrupt = 0;
- memset(&sCtx, 0, sizeof(sCtx));
- open_db(p, 0);
- nSep = strlen30(p->colSeparator);
- if( nSep==0 ){
- raw_printf(stderr,
- "Error: non-null column separator required for import\n");
- return 1;
- }
- if( nSep>1 ){
- raw_printf(stderr, "Error: multi-character column separators not allowed"
- " for import\n");
- return 1;
- }
- nSep = strlen30(p->rowSeparator);
- if( nSep==0 ){
- raw_printf(stderr, "Error: non-null row separator required for import\n");
- return 1;
- }
- if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
- /* When importing CSV (only), if the row separator is set to the
- ** default output row separator, change it to the default input
- ** row separator. This avoids having to maintain different input
- ** and output row separators. */
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- nSep = strlen30(p->rowSeparator);
- }
- if( nSep>1 ){
- raw_printf(stderr, "Error: multi-character row separators not allowed"
- " for import\n");
- return 1;
- }
- sCtx.zFile = zFile;
- sCtx.nLine = 1;
- if( sCtx.zFile[0]=='|' ){
-#ifdef SQLITE_OMIT_POPEN
- raw_printf(stderr, "Error: pipes are not supported in this OS\n");
- return 1;
-#else
- sCtx.in = popen(sCtx.zFile+1, "r");
- sCtx.zFile = "<pipe>";
- xCloser = pclose;
-#endif
- }else{
- sCtx.in = fopen(sCtx.zFile, "rb");
- xCloser = fclose;
- }
- if( p->mode==MODE_Ascii ){
- xRead = ascii_read_one_field;
- }else{
- xRead = csv_read_one_field;
- }
- if( sCtx.in==0 ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
- return 1;
- }
- sCtx.cColSep = p->colSeparator[0];
- sCtx.cRowSep = p->rowSeparator[0];
- zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
- if( zSql==0 ){
- xCloser(sCtx.in);
- shell_out_of_memory();
- }
- nByte = strlen30(zSql);
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
- if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
- char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
- char cSep = '(';
- while( xRead(&sCtx) ){
- zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
- cSep = ',';
- if( sCtx.cTerm!=sCtx.cColSep ) break;
- }
- if( cSep=='(' ){
- sqlite3_free(zCreate);
- sqlite3_free(sCtx.z);
- xCloser(sCtx.in);
- utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
- return 1;
- }
- zCreate = sqlite3_mprintf("%z\n)", zCreate);
- rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
- sqlite3_free(zCreate);
- if( rc ){
- utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
- sqlite3_errmsg(p->db));
- sqlite3_free(sCtx.z);
- xCloser(sCtx.in);
- return 1;
- }
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- }
- sqlite3_free(zSql);
- if( rc ){
- if (pStmt) sqlite3_finalize(pStmt);
- utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
- xCloser(sCtx.in);
- return 1;
- }
- nCol = sqlite3_column_count(pStmt);
- sqlite3_finalize(pStmt);
- pStmt = 0;
- if( nCol==0 ) return 0; /* no columns, no error */
- zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
- if( zSql==0 ){
- xCloser(sCtx.in);
- shell_out_of_memory();
- }
- sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
- j = strlen30(zSql);
- for(i=1; i<nCol; i++){
- zSql[j++] = ',';
- zSql[j++] = '?';
- }
- zSql[j++] = ')';
- zSql[j] = 0;
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ){
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- if (pStmt) sqlite3_finalize(pStmt);
- xCloser(sCtx.in);
- return 1;
- }
- needCommit = sqlite3_get_autocommit(p->db);
- if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
- do{
- int startLine = sCtx.nLine;
- for(i=0; i<nCol; i++){
- char *z = xRead(&sCtx);
- /*
- ** Did we reach end-of-file before finding any columns?
- ** If so, stop instead of NULL filling the remaining columns.
- */
- if( z==0 && i==0 ) break;
- /*
- ** Did we reach end-of-file OR end-of-line before finding any
- ** columns in ASCII mode? If so, stop instead of NULL filling
- ** the remaining columns.
- */
- if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
- sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
- if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
- utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
- "filling the rest with NULL\n",
- sCtx.zFile, startLine, nCol, i+1);
- i += 2;
- while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
- }
- }
- if( sCtx.cTerm==sCtx.cColSep ){
- do{
- xRead(&sCtx);
- i++;
- }while( sCtx.cTerm==sCtx.cColSep );
- utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
- "extras ignored\n",
- sCtx.zFile, startLine, nCol, i);
- }
- if( i>=nCol ){
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
- startLine, sqlite3_errmsg(p->db));
- }
- }
- }while( sCtx.cTerm!=EOF );
-
- xCloser(sCtx.in);
- sqlite3_free(sCtx.z);
- sqlite3_finalize(pStmt);
- if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
- }else
-
-#ifndef SQLITE_UNTESTABLE
- if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
- char *zSql;
- char *zCollist = 0;
- sqlite3_stmt *pStmt;
- int tnum = 0;
- int i;
- if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
- utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
- " .imposter off\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- if( nArg==2 ){
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
- goto meta_command_exit;
- }
- zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
- " WHERE name='%q' AND type='index'", azArg[1]);
- sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- tnum = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- if( tnum==0 ){
- utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
- rc = 1;
- goto meta_command_exit;
- }
- zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- i = 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- char zLabel[20];
- const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
- i++;
- if( zCol==0 ){
- if( sqlite3_column_int(pStmt,1)==-1 ){
- zCol = "_ROWID_";
- }else{
- sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
- zCol = zLabel;
- }
- }
- if( zCollist==0 ){
- zCollist = sqlite3_mprintf("\"%w\"", zCol);
- }else{
- zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
- }
- }
- sqlite3_finalize(pStmt);
- zSql = sqlite3_mprintf(
- "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
- azArg[2], zCollist, zCollist);
- sqlite3_free(zCollist);
- rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
- if( rc ){
- utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
- }else{
- utf8_printf(stdout, "%s;\n", zSql);
- raw_printf(stdout,
- "WARNING: writing to an imposter table will corrupt the index!\n"
- );
- }
- }else{
- raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
- rc = 1;
- }
- sqlite3_free(zSql);
- }else
-#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
-
-#ifdef SQLITE_ENABLE_IOTRACE
- if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
- SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
- if( iotrace && iotrace!=stdout ) fclose(iotrace);
- iotrace = 0;
- if( nArg<2 ){
- sqlite3IoTrace = 0;
- }else if( strcmp(azArg[1], "-")==0 ){
- sqlite3IoTrace = iotracePrintf;
- iotrace = stdout;
- }else{
- iotrace = fopen(azArg[1], "w");
- if( iotrace==0 ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
- sqlite3IoTrace = 0;
- rc = 1;
- }else{
- sqlite3IoTrace = iotracePrintf;
- }
- }
- }else
-#endif
-
- if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
- static const struct {
- const char *zLimitName; /* Name of a limit */
- int limitCode; /* Integer code for that limit */
- } aLimit[] = {
- { "length", SQLITE_LIMIT_LENGTH },
- { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
- { "column", SQLITE_LIMIT_COLUMN },
- { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
- { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
- { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
- { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
- { "attached", SQLITE_LIMIT_ATTACHED },
- { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
- { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
- { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
- { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
- };
- int i, n2;
- open_db(p, 0);
- if( nArg==1 ){
- for(i=0; i<ArraySize(aLimit); i++){
- printf("%20s %d\n", aLimit[i].zLimitName,
- sqlite3_limit(p->db, aLimit[i].limitCode, -1));
- }
- }else if( nArg>3 ){
- raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
- rc = 1;
- goto meta_command_exit;
- }else{
- int iLimit = -1;
- n2 = strlen30(azArg[1]);
- for(i=0; i<ArraySize(aLimit); i++){
- if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
- if( iLimit<0 ){
- iLimit = i;
- }else{
- utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
- rc = 1;
- goto meta_command_exit;
- }
- }
- }
- if( iLimit<0 ){
- utf8_printf(stderr, "unknown limit: \"%s\"\n"
- "enter \".limits\" with no arguments for a list.\n",
- azArg[1]);
- rc = 1;
- goto meta_command_exit;
- }
- if( nArg==3 ){
- sqlite3_limit(p->db, aLimit[iLimit].limitCode,
- (int)integerValue(azArg[2]));
- }
- printf("%20s %d\n", aLimit[iLimit].zLimitName,
- sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
- }
- }else
-
- if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
- open_db(p, 0);
- lintDotCommand(p, azArg, nArg);
- }else
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
- const char *zFile, *zProc;
- char *zErrMsg = 0;
- if( nArg<2 ){
- raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
- rc = 1;
- goto meta_command_exit;
- }
- zFile = azArg[1];
- zProc = nArg>=3 ? azArg[2] : 0;
- open_db(p, 0);
- rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- rc = 1;
- }
- }else
-#endif
-
- if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .log FILENAME\n");
- rc = 1;
- }else{
- const char *zFile = azArg[1];
- output_file_close(p->pLog);
- p->pLog = output_file_open(zFile, 0);
- }
- }else
-
- if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
- const char *zMode = nArg>=2 ? azArg[1] : "";
- int n2 = strlen30(zMode);
- int c2 = zMode[0];
- if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
- p->mode = MODE_Line;
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
- p->mode = MODE_Column;
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
- p->mode = MODE_List;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
- p->mode = MODE_Html;
- }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
- p->mode = MODE_Tcl;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
- p->mode = MODE_Csv;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
- }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
- p->mode = MODE_List;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
- }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
- p->mode = MODE_Insert;
- set_table_name(p, nArg>=3 ? azArg[2] : "table");
- }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
- p->mode = MODE_Quote;
- }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
- p->mode = MODE_Ascii;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
- }else if( nArg==1 ){
- raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
- }else{
- raw_printf(stderr, "Error: mode should be one of: "
- "ascii column csv html insert line list quote tabs tcl\n");
- rc = 1;
- }
- p->cMode = p->mode;
- }else
-
- if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
- if( nArg==2 ){
- sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
- "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .nullvalue STRING\n");
- rc = 1;
- }
- }else
-
- if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
- char *zNewFilename; /* Name of the database file to open */
- int iName = 1; /* Index in azArg[] of the filename */
- int newFlag = 0; /* True to delete file before opening */
- /* Close the existing database */
- session_close_all(p);
- close_db(p->db);
- p->db = 0;
- p->zDbFilename = 0;
- sqlite3_free(p->zFreeOnClose);
- p->zFreeOnClose = 0;
- p->openMode = SHELL_OPEN_UNSPEC;
- /* Check for command-line arguments */
- for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
- const char *z = azArg[iName];
- if( optionMatch(z,"new") ){
- newFlag = 1;
-#ifdef SQLITE_HAVE_ZLIB
- }else if( optionMatch(z, "zip") ){
- p->openMode = SHELL_OPEN_ZIPFILE;
-#endif
- }else if( optionMatch(z, "append") ){
- p->openMode = SHELL_OPEN_APPENDVFS;
- }else if( optionMatch(z, "readonly") ){
- p->openMode = SHELL_OPEN_READONLY;
- }else if( z[0]=='-' ){
- utf8_printf(stderr, "unknown option: %s\n", z);
- rc = 1;
- goto meta_command_exit;
- }
- }
- /* If a filename is specified, try to open it first */
- zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
- if( zNewFilename ){
- if( newFlag ) shellDeleteFile(zNewFilename);
- p->zDbFilename = zNewFilename;
- open_db(p, OPEN_DB_KEEPALIVE);
- if( p->db==0 ){
- utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
- sqlite3_free(zNewFilename);
- }else{
- p->zFreeOnClose = zNewFilename;
- }
- }
- if( p->db==0 ){
- /* As a fall-back open a TEMP database */
- p->zDbFilename = 0;
- open_db(p, 0);
- }
- }else
-
- if( (c=='o'
- && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
- || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
- ){
- const char *zFile = nArg>=2 ? azArg[1] : "stdout";
- int bTxtMode = 0;
- if( azArg[0][0]=='e' ){
- /* Transform the ".excel" command into ".once -x" */
- nArg = 2;
- azArg[0] = "once";
- zFile = azArg[1] = "-x";
- n = 4;
- }
- if( nArg>2 ){
- utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]);
- rc = 1;
- goto meta_command_exit;
- }
- if( n>1 && strncmp(azArg[0], "once", n)==0 ){
- if( nArg<2 ){
- raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n");
- rc = 1;
- goto meta_command_exit;
- }
- p->outCount = 2;
- }else{
- p->outCount = 0;
- }
- output_reset(p);
- if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;
-#ifndef SQLITE_NOHAVE_SYSTEM
- if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){
- p->doXdgOpen = 1;
- outputModePush(p);
- if( zFile[1]=='x' ){
- newTempFile(p, "csv");
- p->mode = MODE_Csv;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
- }else{
- newTempFile(p, "txt");
- bTxtMode = 1;
- }
- zFile = p->zTempFile;
- }
-#endif /* SQLITE_NOHAVE_SYSTEM */
- if( zFile[0]=='|' ){
-#ifdef SQLITE_OMIT_POPEN
- raw_printf(stderr, "Error: pipes are not supported in this OS\n");
- rc = 1;
- p->out = stdout;
-#else
- p->out = popen(zFile + 1, "w");
- if( p->out==0 ){
- utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
- p->out = stdout;
- rc = 1;
- }else{
- sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
- }
-#endif
- }else{
- p->out = output_file_open(zFile, bTxtMode);
- if( p->out==0 ){
- if( strcmp(zFile,"off")!=0 ){
- utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
- }
- p->out = stdout;
- rc = 1;
- } else {
- sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
- }
- }
- }else
-
- if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
- int i;
- for(i=1; i<nArg; i++){
- if( i>1 ) raw_printf(p->out, " ");
- utf8_printf(p->out, "%s", azArg[i]);
- }
- raw_printf(p->out, "\n");
- }else
-
- if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
- if( nArg >= 2) {
- strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
- }
- if( nArg >= 3) {
- strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
- }
- }else
-
- if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
- rc = 2;
- }else
-
- if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
- FILE *alt;
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .read FILE\n");
- rc = 1;
- goto meta_command_exit;
- }
- alt = fopen(azArg[1], "rb");
- if( alt==0 ){
- utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
- rc = 1;
- }else{
- rc = process_input(p, alt);
- fclose(alt);
- }
- }else
-
- if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
- const char *zSrcFile;
- const char *zDb;
- sqlite3 *pSrc;
- sqlite3_backup *pBackup;
- int nTimeout = 0;
-
- if( nArg==2 ){
- zSrcFile = azArg[1];
- zDb = "main";
- }else if( nArg==3 ){
- zSrcFile = azArg[2];
- zDb = azArg[1];
- }else{
- raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_open(zSrcFile, &pSrc);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
- close_db(pSrc);
- return 1;
- }
- open_db(p, 0);
- pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
- if( pBackup==0 ){
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- close_db(pSrc);
- return 1;
- }
- while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
- || rc==SQLITE_BUSY ){
- if( rc==SQLITE_BUSY ){
- if( nTimeout++ >= 3 ) break;
- sqlite3_sleep(100);
- }
- }
- sqlite3_backup_finish(pBackup);
- if( rc==SQLITE_DONE ){
- rc = 0;
- }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
- raw_printf(stderr, "Error: source database is busy\n");
- rc = 1;
- }else{
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- rc = 1;
- }
- close_db(pSrc);
- }else
-
- if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
- if( nArg==2 ){
- p->scanstatsOn = (u8)booleanValue(azArg[1]);
-#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
- raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
-#endif
- }else{
- raw_printf(stderr, "Usage: .scanstats on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
- ShellText sSelect;
- ShellState data;
- char *zErrMsg = 0;
- const char *zDiv = "(";
- const char *zName = 0;
- int iSchema = 0;
- int bDebug = 0;
- int ii;
-
- open_db(p, 0);
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_Semi;
- initText(&sSelect);
- for(ii=1; ii<nArg; ii++){
- if( optionMatch(azArg[ii],"indent") ){
- data.cMode = data.mode = MODE_Pretty;
- }else if( optionMatch(azArg[ii],"debug") ){
- bDebug = 1;
- }else if( zName==0 ){
- zName = azArg[ii];
- }else{
- raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
- rc = 1;
- goto meta_command_exit;
- }
- }
- if( zName!=0 ){
- int isMaster = sqlite3_strlike(zName, "sqlite_master", '\\')==0;
- if( isMaster || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 ){
- char *new_argv[2], *new_colv[2];
- new_argv[0] = sqlite3_mprintf(
- "CREATE TABLE %s (\n"
- " type text,\n"
- " name text,\n"
- " tbl_name text,\n"
- " rootpage integer,\n"
- " sql text\n"
- ")", isMaster ? "sqlite_master" : "sqlite_temp_master");
- new_argv[1] = 0;
- new_colv[0] = "sql";
- new_colv[1] = 0;
- callback(&data, 1, new_argv, new_colv);
- sqlite3_free(new_argv[0]);
- }
- }
- if( zDiv ){
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
- -1, &pStmt, 0);
- if( rc ){
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- sqlite3_finalize(pStmt);
- rc = 1;
- goto meta_command_exit;
- }
- appendText(&sSelect, "SELECT sql FROM", 0);
- iSchema = 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
- char zScNum[30];
- sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
- appendText(&sSelect, zDiv, 0);
- zDiv = " UNION ALL ";
- appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
- if( sqlite3_stricmp(zDb, "main")!=0 ){
- appendText(&sSelect, zDb, '"');
- }else{
- appendText(&sSelect, "NULL", 0);
- }
- appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
- appendText(&sSelect, zScNum, 0);
- appendText(&sSelect, " AS snum, ", 0);
- appendText(&sSelect, zDb, '\'');
- appendText(&sSelect, " AS sname FROM ", 0);
- appendText(&sSelect, zDb, '"');
- appendText(&sSelect, ".sqlite_master", 0);
- }
- sqlite3_finalize(pStmt);
-#ifdef SQLITE_INTROSPECTION_PRAGMAS
- if( zName ){
- appendText(&sSelect,
- " UNION ALL SELECT shell_module_schema(name),"
- " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0);
- }
-#endif
- appendText(&sSelect, ") WHERE ", 0);
- if( zName ){
- char *zQarg = sqlite3_mprintf("%Q", zName);
- int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
- strchr(zName, '[') != 0;
- if( strchr(zName, '.') ){
- appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
- }else{
- appendText(&sSelect, "lower(tbl_name)", 0);
- }
- appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
- appendText(&sSelect, zQarg, 0);
- if( !bGlob ){
- appendText(&sSelect, " ESCAPE '\\' ", 0);
- }
- appendText(&sSelect, " AND ", 0);
- sqlite3_free(zQarg);
- }
- appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
- " ORDER BY snum, rowid", 0);
- if( bDebug ){
- utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
- }else{
- rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
- }
- freeText(&sSelect);
- }
- if( zErrMsg ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- rc = 1;
- }else if( rc != SQLITE_OK ){
- raw_printf(stderr,"Error: querying schema information\n");
- rc = 1;
- }else{
- rc = 0;
- }
- }else
-
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
- if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
- sqlite3SelectTrace = (int)integerValue(azArg[1]);
- }else
-#endif
-
-#if defined(SQLITE_ENABLE_SESSION)
- if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
- OpenSession *pSession = &p->aSession[0];
- char **azCmd = &azArg[1];
- int iSes = 0;
- int nCmd = nArg - 1;
- int i;
- if( nArg<=1 ) goto session_syntax_error;
- open_db(p, 0);
- if( nArg>=3 ){
- for(iSes=0; iSes<p->nSession; iSes++){
- if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
- }
- if( iSes<p->nSession ){
- pSession = &p->aSession[iSes];
- azCmd++;
- nCmd--;
- }else{
- pSession = &p->aSession[0];
- iSes = 0;
- }
- }
-
- /* .session attach TABLE
- ** Invoke the sqlite3session_attach() interface to attach a particular
- ** table so that it is never filtered.
- */
- if( strcmp(azCmd[0],"attach")==0 ){
- if( nCmd!=2 ) goto session_syntax_error;
- if( pSession->p==0 ){
- session_not_open:
- raw_printf(stderr, "ERROR: No sessions are open\n");
- }else{
- rc = sqlite3session_attach(pSession->p, azCmd[1]);
- if( rc ){
- raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
- rc = 0;
- }
- }
- }else
-
- /* .session changeset FILE
- ** .session patchset FILE
- ** Write a changeset or patchset into a file. The file is overwritten.
- */
- if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
- FILE *out = 0;
- if( nCmd!=2 ) goto session_syntax_error;
- if( pSession->p==0 ) goto session_not_open;
- out = fopen(azCmd[1], "wb");
- if( out==0 ){
- utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);
- }else{
- int szChng;
- void *pChng;
- if( azCmd[0][0]=='c' ){
- rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
- }else{
- rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
- }
- if( rc ){
- printf("Error: error code %d\n", rc);
- rc = 0;
- }
- if( pChng
- && fwrite(pChng, szChng, 1, out)!=1 ){
- raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
- szChng);
- }
- sqlite3_free(pChng);
- fclose(out);
- }
- }else
-
- /* .session close
- ** Close the identified session
- */
- if( strcmp(azCmd[0], "close")==0 ){
- if( nCmd!=1 ) goto session_syntax_error;
- if( p->nSession ){
- session_close(pSession);
- p->aSession[iSes] = p->aSession[--p->nSession];
- }
- }else
-
- /* .session enable ?BOOLEAN?
- ** Query or set the enable flag
- */
- if( strcmp(azCmd[0], "enable")==0 ){
- int ii;
- if( nCmd>2 ) goto session_syntax_error;
- ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
- if( p->nSession ){
- ii = sqlite3session_enable(pSession->p, ii);
- utf8_printf(p->out, "session %s enable flag = %d\n",
- pSession->zName, ii);
- }
- }else
-
- /* .session filter GLOB ....
- ** Set a list of GLOB patterns of table names to be excluded.
- */
- if( strcmp(azCmd[0], "filter")==0 ){
- int ii, nByte;
- if( nCmd<2 ) goto session_syntax_error;
- if( p->nSession ){
- for(ii=0; ii<pSession->nFilter; ii++){
- sqlite3_free(pSession->azFilter[ii]);
- }
- sqlite3_free(pSession->azFilter);
- nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
- pSession->azFilter = sqlite3_malloc( nByte );
- if( pSession->azFilter==0 ){
- raw_printf(stderr, "Error: out or memory\n");
- exit(1);
- }
- for(ii=1; ii<nCmd; ii++){
- pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
- }
- pSession->nFilter = ii-1;
- }
- }else
-
- /* .session indirect ?BOOLEAN?
- ** Query or set the indirect flag
- */
- if( strcmp(azCmd[0], "indirect")==0 ){
- int ii;
- if( nCmd>2 ) goto session_syntax_error;
- ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
- if( p->nSession ){
- ii = sqlite3session_indirect(pSession->p, ii);
- utf8_printf(p->out, "session %s indirect flag = %d\n",
- pSession->zName, ii);
- }
- }else
-
- /* .session isempty
- ** Determine if the session is empty
- */
- if( strcmp(azCmd[0], "isempty")==0 ){
- int ii;
- if( nCmd!=1 ) goto session_syntax_error;
- if( p->nSession ){
- ii = sqlite3session_isempty(pSession->p);
- utf8_printf(p->out, "session %s isempty flag = %d\n",
- pSession->zName, ii);
- }
- }else
-
- /* .session list
- ** List all currently open sessions
- */
- if( strcmp(azCmd[0],"list")==0 ){
- for(i=0; i<p->nSession; i++){
- utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
- }
- }else
-
- /* .session open DB NAME
- ** Open a new session called NAME on the attached database DB.
- ** DB is normally "main".
- */
- if( strcmp(azCmd[0],"open")==0 ){
- char *zName;
- if( nCmd!=3 ) goto session_syntax_error;
- zName = azCmd[2];
- if( zName[0]==0 ) goto session_syntax_error;
- for(i=0; i<p->nSession; i++){
- if( strcmp(p->aSession[i].zName,zName)==0 ){
- utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
- goto meta_command_exit;
- }
- }
- if( p->nSession>=ArraySize(p->aSession) ){
- raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
- goto meta_command_exit;
- }
- pSession = &p->aSession[p->nSession];
- rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
- if( rc ){
- raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
- rc = 0;
- goto meta_command_exit;
- }
- pSession->nFilter = 0;
- sqlite3session_table_filter(pSession->p, session_filter, pSession);
- p->nSession++;
- pSession->zName = sqlite3_mprintf("%s", zName);
- }else
- /* If no command name matches, show a syntax error */
- session_syntax_error:
- session_help(p);
- }else
-#endif
-
-#ifdef SQLITE_DEBUG
- /* Undocumented commands for internal testing. Subject to change
- ** without notice. */
- if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
- if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
- int i, v;
- for(i=1; i<nArg; i++){
- v = booleanValue(azArg[i]);
- utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
- }
- }
- if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
- int i; sqlite3_int64 v;
- for(i=1; i<nArg; i++){
- char zBuf[200];
- v = integerValue(azArg[i]);
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
- utf8_printf(p->out, "%s", zBuf);
- }
- }
- }else
-#endif
-
- if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
- int bIsInit = 0; /* True to initialize the SELFTEST table */
- int bVerbose = 0; /* Verbose output */
- int bSelftestExists; /* True if SELFTEST already exists */
- int i, k; /* Loop counters */
- int nTest = 0; /* Number of tests runs */
- int nErr = 0; /* Number of errors seen */
- ShellText str; /* Answer for a query */
- sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
-
- open_db(p,0);
- for(i=1; i<nArg; i++){
- const char *z = azArg[i];
- if( z[0]=='-' && z[1]=='-' ) z++;
- if( strcmp(z,"-init")==0 ){
- bIsInit = 1;
- }else
- if( strcmp(z,"-v")==0 ){
- bVerbose++;
- }else
- {
- utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
- azArg[i], azArg[0]);
- raw_printf(stderr, "Should be one of: --init -v\n");
- rc = 1;
- goto meta_command_exit;
- }
- }
- if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
- != SQLITE_OK ){
- bSelftestExists = 0;
- }else{
- bSelftestExists = 1;
- }
- if( bIsInit ){
- createSelftestTable(p);
- bSelftestExists = 1;
- }
- initText(&str);
- appendText(&str, "x", 0);
- for(k=bSelftestExists; k>=0; k--){
- if( k==1 ){
- rc = sqlite3_prepare_v2(p->db,
- "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
- -1, &pStmt, 0);
- }else{
- rc = sqlite3_prepare_v2(p->db,
- "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
- " (1,'run','PRAGMA integrity_check','ok')",
- -1, &pStmt, 0);
- }
- if( rc ){
- raw_printf(stderr, "Error querying the selftest table\n");
- rc = 1;
- sqlite3_finalize(pStmt);
- goto meta_command_exit;
- }
- for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
- int tno = sqlite3_column_int(pStmt, 0);
- const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
- const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
- const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
-
- k = 0;
- if( bVerbose>0 ){
- char *zQuote = sqlite3_mprintf("%q", zSql);
- printf("%d: %s %s\n", tno, zOp, zSql);
- sqlite3_free(zQuote);
- }
- if( strcmp(zOp,"memo")==0 ){
- utf8_printf(p->out, "%s\n", zSql);
- }else
- if( strcmp(zOp,"run")==0 ){
- char *zErrMsg = 0;
- str.n = 0;
- str.z[0] = 0;
- rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
- nTest++;
- if( bVerbose ){
- utf8_printf(p->out, "Result: %s\n", str.z);
- }
- if( rc || zErrMsg ){
- nErr++;
- rc = 1;
- utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
- sqlite3_free(zErrMsg);
- }else if( strcmp(zAns,str.z)!=0 ){
- nErr++;
- rc = 1;
- utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
- utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
- }
- }else
- {
- utf8_printf(stderr,
- "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
- rc = 1;
- break;
- }
- } /* End loop over rows of content from SELFTEST */
- sqlite3_finalize(pStmt);
- } /* End loop over k */
- freeText(&str);
- utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
- }else
-
- if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
- if( nArg<2 || nArg>3 ){
- raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
- rc = 1;
- }
- if( nArg>=2 ){
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
- "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
- }
- if( nArg>=3 ){
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
- "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
- }
- }else
-
- if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
- const char *zLike = 0; /* Which table to checksum. 0 means everything */
- int i; /* Loop counter */
- int bSchema = 0; /* Also hash the schema */
- int bSeparate = 0; /* Hash each table separately */
- int iSize = 224; /* Hash algorithm to use */
- int bDebug = 0; /* Only show the query that would have run */
- sqlite3_stmt *pStmt; /* For querying tables names */
- char *zSql; /* SQL to be run */
- char *zSep; /* Separator */
- ShellText sSql; /* Complete SQL for the query to run the hash */
- ShellText sQuery; /* Set of queries used to read all content */
- open_db(p, 0);
- for(i=1; i<nArg; i++){
- const char *z = azArg[i];
- if( z[0]=='-' ){
- z++;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"schema")==0 ){
- bSchema = 1;
- }else
- if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
- || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
- ){
- iSize = atoi(&z[5]);
- }else
- if( strcmp(z,"debug")==0 ){
- bDebug = 1;
- }else
- {
- utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
- azArg[i], azArg[0]);
- raw_printf(stderr, "Should be one of: --schema"
- " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n");
- rc = 1;
- goto meta_command_exit;
- }
- }else if( zLike ){
- raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
- rc = 1;
- goto meta_command_exit;
- }else{
- zLike = z;
- bSeparate = 1;
- if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
- }
- }
- if( bSchema ){
- zSql = "SELECT lower(name) FROM sqlite_master"
- " WHERE type='table' AND coalesce(rootpage,0)>1"
- " UNION ALL SELECT 'sqlite_master'"
- " ORDER BY 1 collate nocase";
- }else{
- zSql = "SELECT lower(name) FROM sqlite_master"
- " WHERE type='table' AND coalesce(rootpage,0)>1"
- " AND name NOT LIKE 'sqlite_%'"
- " ORDER BY 1 collate nocase";
- }
- sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- initText(&sQuery);
- initText(&sSql);
- appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
- zSep = "VALUES(";
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
- if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
- if( strncmp(zTab, "sqlite_",7)!=0 ){
- appendText(&sQuery,"SELECT * FROM ", 0);
- appendText(&sQuery,zTab,'"');
- appendText(&sQuery," NOT INDEXED;", 0);
- }else if( strcmp(zTab, "sqlite_master")==0 ){
- appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master"
- " ORDER BY name;", 0);
- }else if( strcmp(zTab, "sqlite_sequence")==0 ){
- appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
- " ORDER BY name;", 0);
- }else if( strcmp(zTab, "sqlite_stat1")==0 ){
- appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
- " ORDER BY tbl,idx;", 0);
- }else if( strcmp(zTab, "sqlite_stat3")==0
- || strcmp(zTab, "sqlite_stat4")==0 ){
- appendText(&sQuery, "SELECT * FROM ", 0);
- appendText(&sQuery, zTab, 0);
- appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
- }
- appendText(&sSql, zSep, 0);
- appendText(&sSql, sQuery.z, '\'');
- sQuery.n = 0;
- appendText(&sSql, ",", 0);
- appendText(&sSql, zTab, '\'');
- zSep = "),(";
- }
- sqlite3_finalize(pStmt);
- if( bSeparate ){
- zSql = sqlite3_mprintf(
- "%s))"
- " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
- " FROM [sha3sum$query]",
- sSql.z, iSize);
- }else{
- zSql = sqlite3_mprintf(
- "%s))"
- " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
- " FROM [sha3sum$query]",
- sSql.z, iSize);
- }
- freeText(&sQuery);
- freeText(&sSql);
- if( bDebug ){
- utf8_printf(p->out, "%s\n", zSql);
- }else{
- shell_exec(p, zSql, 0);
- }
- sqlite3_free(zSql);
- }else
-
-#ifndef SQLITE_NOHAVE_SYSTEM
- if( c=='s'
- && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
- ){
- char *zCmd;
- int i, x;
- if( nArg<2 ){
- raw_printf(stderr, "Usage: .system COMMAND\n");
- rc = 1;
- goto meta_command_exit;
- }
- zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
- for(i=2; i<nArg; i++){
- zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
- zCmd, azArg[i]);
- }
- x = system(zCmd);
- sqlite3_free(zCmd);
- if( x ) raw_printf(stderr, "System command returns %d\n", x);
- }else
-#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
-
- if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
- static const char *azBool[] = { "off", "on", "trigger", "full"};
- int i;
- if( nArg!=1 ){
- raw_printf(stderr, "Usage: .show\n");
- rc = 1;
- goto meta_command_exit;
- }
- utf8_printf(p->out, "%12.12s: %s\n","echo",
- azBool[ShellHasFlag(p, SHFLG_Echo)]);
- utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
- utf8_printf(p->out, "%12.12s: %s\n","explain",
- p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
- utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
- utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
- utf8_printf(p->out, "%12.12s: ", "nullvalue");
- output_c_string(p->out, p->nullValue);
- raw_printf(p->out, "\n");
- utf8_printf(p->out,"%12.12s: %s\n","output",
- strlen30(p->outfile) ? p->outfile : "stdout");
- utf8_printf(p->out,"%12.12s: ", "colseparator");
- output_c_string(p->out, p->colSeparator);
- raw_printf(p->out, "\n");
- utf8_printf(p->out,"%12.12s: ", "rowseparator");
- output_c_string(p->out, p->rowSeparator);
- raw_printf(p->out, "\n");
- utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
- utf8_printf(p->out, "%12.12s: ", "width");
- for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
- raw_printf(p->out, "%d ", p->colWidth[i]);
- }
- raw_printf(p->out, "\n");
- utf8_printf(p->out, "%12.12s: %s\n", "filename",
- p->zDbFilename ? p->zDbFilename : "");
- }else
-
- if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
- if( nArg==2 ){
- p->statsOn = (u8)booleanValue(azArg[1]);
- }else if( nArg==1 ){
- display_stats(p->db, p, 0);
- }else{
- raw_printf(stderr, "Usage: .stats ?on|off?\n");
- rc = 1;
- }
- }else
-
- if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
- || (c=='i' && (strncmp(azArg[0], "indices", n)==0
- || strncmp(azArg[0], "indexes", n)==0) )
- ){
- sqlite3_stmt *pStmt;
- char **azResult;
- int nRow, nAlloc;
- int ii;
- ShellText s;
- initText(&s);
- open_db(p, 0);
- rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
- if( rc ){
- sqlite3_finalize(pStmt);
- return shellDatabaseError(p->db);
- }
-
- if( nArg>2 && c=='i' ){
- /* It is an historical accident that the .indexes command shows an error
- ** when called with the wrong number of arguments whereas the .tables
- ** command does not. */
- raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
- rc = 1;
- sqlite3_finalize(pStmt);
- goto meta_command_exit;
- }
- for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
- const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
- if( zDbName==0 ) continue;
- if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
- if( sqlite3_stricmp(zDbName, "main")==0 ){
- appendText(&s, "SELECT name FROM ", 0);
- }else{
- appendText(&s, "SELECT ", 0);
- appendText(&s, zDbName, '\'');
- appendText(&s, "||'.'||name FROM ", 0);
- }
- appendText(&s, zDbName, '"');
- appendText(&s, ".sqlite_master ", 0);
- if( c=='t' ){
- appendText(&s," WHERE type IN ('table','view')"
- " AND name NOT LIKE 'sqlite_%'"
- " AND name LIKE ?1", 0);
- }else{
- appendText(&s," WHERE type='index'"
- " AND tbl_name LIKE ?1", 0);
- }
- }
- rc = sqlite3_finalize(pStmt);
- appendText(&s, " ORDER BY 1", 0);
- rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
- freeText(&s);
- if( rc ) return shellDatabaseError(p->db);
-
- /* Run the SQL statement prepared by the above block. Store the results
- ** as an array of nul-terminated strings in azResult[]. */
- nRow = nAlloc = 0;
- azResult = 0;
- if( nArg>1 ){
- sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
- }
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- if( nRow>=nAlloc ){
- char **azNew;
- int n2 = nAlloc*2 + 10;
- azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
- if( azNew==0 ) shell_out_of_memory();
- nAlloc = n2;
- azResult = azNew;
- }
- azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
- if( 0==azResult[nRow] ) shell_out_of_memory();
- nRow++;
- }
- if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
- rc = shellDatabaseError(p->db);
- }
-
- /* Pretty-print the contents of array azResult[] to the output */
- if( rc==0 && nRow>0 ){
- int len, maxlen = 0;
- int i, j;
- int nPrintCol, nPrintRow;
- for(i=0; i<nRow; i++){
- len = strlen30(azResult[i]);
- if( len>maxlen ) maxlen = len;
- }
- nPrintCol = 80/(maxlen+2);
- if( nPrintCol<1 ) nPrintCol = 1;
- nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
- for(i=0; i<nPrintRow; i++){
- for(j=i; j<nRow; j+=nPrintRow){
- char *zSp = j<nPrintRow ? "" : " ";
- utf8_printf(p->out, "%s%-*s", zSp, maxlen,
- azResult[j] ? azResult[j]:"");
- }
- raw_printf(p->out, "\n");
- }
- }
-
- for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
- sqlite3_free(azResult);
- }else
-
- /* Begin redirecting output to the file "testcase-out.txt" */
- if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
- output_reset(p);
- p->out = output_file_open("testcase-out.txt", 0);
- if( p->out==0 ){
- raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
- }
- if( nArg>=2 ){
- sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
- }else{
- sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
- }
- }else
-
-#ifndef SQLITE_UNTESTABLE
- if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
- static const struct {
- const char *zCtrlName; /* Name of a test-control option */
- int ctrlCode; /* Integer code for that option */
- const char *zUsage; /* Usage notes */
- } aCtrl[] = {
- { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
- { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
- /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
- /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
- { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
- /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */
- { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
- { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
- { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
- { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
-#ifdef YYCOVERAGE
- { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
-#endif
- { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
- { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" },
- { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
- { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
- { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE" },
- };
- int testctrl = -1;
- int iCtrl = -1;
- int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
- int isOk = 0;
- int i, n2;
- const char *zCmd = 0;
-
- open_db(p, 0);
- zCmd = nArg>=2 ? azArg[1] : "help";
-
- /* The argument can optionally begin with "-" or "--" */
- if( zCmd[0]=='-' && zCmd[1] ){
- zCmd++;
- if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
- }
-
- /* --help lists all test-controls */
- if( strcmp(zCmd,"help")==0 ){
- utf8_printf(p->out, "Available test-controls:\n");
- for(i=0; i<ArraySize(aCtrl); i++){
- utf8_printf(p->out, " .testctrl %s %s\n",
- aCtrl[i].zCtrlName, aCtrl[i].zUsage);
- }
- rc = 1;
- goto meta_command_exit;
- }
-
- /* convert testctrl text option to value. allow any unique prefix
- ** of the option name, or a numerical value. */
- n2 = strlen30(zCmd);
- for(i=0; i<ArraySize(aCtrl); i++){
- if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
- if( testctrl<0 ){
- testctrl = aCtrl[i].ctrlCode;
- iCtrl = i;
- }else{
- utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
- "Use \".testctrl --help\" for help\n", zCmd);
- rc = 1;
- goto meta_command_exit;
- }
- }
- }
- if( testctrl<0 ){
- utf8_printf(stderr,"Error: unknown test-control: %s\n"
- "Use \".testctrl --help\" for help\n", zCmd);
- }else{
- switch(testctrl){
-
- /* sqlite3_test_control(int, db, int) */
- case SQLITE_TESTCTRL_OPTIMIZATIONS:
- case SQLITE_TESTCTRL_RESERVE:
- if( nArg==3 ){
- int opt = (int)strtol(azArg[2], 0, 0);
- rc2 = sqlite3_test_control(testctrl, p->db, opt);
- isOk = 3;
- }
- break;
-
- /* sqlite3_test_control(int) */
- case SQLITE_TESTCTRL_PRNG_SAVE:
- case SQLITE_TESTCTRL_PRNG_RESTORE:
- case SQLITE_TESTCTRL_PRNG_RESET:
- case SQLITE_TESTCTRL_BYTEORDER:
- if( nArg==2 ){
- rc2 = sqlite3_test_control(testctrl);
- isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
- }
- break;
-
- /* sqlite3_test_control(int, uint) */
- case SQLITE_TESTCTRL_PENDING_BYTE:
- if( nArg==3 ){
- unsigned int opt = (unsigned int)integerValue(azArg[2]);
- rc2 = sqlite3_test_control(testctrl, opt);
- isOk = 3;
- }
- break;
-
- /* sqlite3_test_control(int, int) */
- case SQLITE_TESTCTRL_ASSERT:
- case SQLITE_TESTCTRL_ALWAYS:
- if( nArg==3 ){
- int opt = booleanValue(azArg[2]);
- rc2 = sqlite3_test_control(testctrl, opt);
- isOk = 1;
- }
- break;
-
- /* sqlite3_test_control(int, int) */
- case SQLITE_TESTCTRL_LOCALTIME_FAULT:
- case SQLITE_TESTCTRL_NEVER_CORRUPT:
- if( nArg==3 ){
- int opt = booleanValue(azArg[2]);
- rc2 = sqlite3_test_control(testctrl, opt);
- isOk = 3;
- }
- break;
-
- case SQLITE_TESTCTRL_IMPOSTER:
- if( nArg==5 ){
- rc2 = sqlite3_test_control(testctrl, p->db,
- azArg[2],
- integerValue(azArg[3]),
- integerValue(azArg[4]));
- isOk = 3;
- }
- break;
-
-#ifdef YYCOVERAGE
- case SQLITE_TESTCTRL_PARSER_COVERAGE:
- if( nArg==2 ){
- sqlite3_test_control(testctrl, p->out);
- isOk = 3;
- }
-#endif
- }
- }
- if( isOk==0 && iCtrl>=0 ){
- utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage);
- rc = 1;
- }else if( isOk==1 ){
- raw_printf(p->out, "%d\n", rc2);
- }else if( isOk==2 ){
- raw_printf(p->out, "0x%08x\n", rc2);
- }
- }else
-#endif /* !defined(SQLITE_UNTESTABLE) */
-
- if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
- open_db(p, 0);
- sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
- }else
-
- if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
- if( nArg==2 ){
- enableTimer = booleanValue(azArg[1]);
- if( enableTimer && !HAS_TIMER ){
- raw_printf(stderr, "Error: timer not available on this system.\n");
- enableTimer = 0;
- }
- }else{
- raw_printf(stderr, "Usage: .timer on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
- open_db(p, 0);
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .trace FILE|off\n");
- rc = 1;
- goto meta_command_exit;
- }
- output_file_close(p->traceOut);
- p->traceOut = output_file_open(azArg[1], 0);
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
- if( p->traceOut==0 ){
- sqlite3_trace_v2(p->db, 0, 0, 0);
- }else{
- sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
- }
-#endif
- }else
-
-#if SQLITE_USER_AUTHENTICATION
- if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
- if( nArg<2 ){
- raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- if( strcmp(azArg[1],"login")==0 ){
- if( nArg!=4 ){
- raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3]));
- if( rc ){
- utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
- rc = 1;
- }
- }else if( strcmp(azArg[1],"add")==0 ){
- if( nArg!=5 ){
- raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
- booleanValue(azArg[4]));
- if( rc ){
- raw_printf(stderr, "User-Add failed: %d\n", rc);
- rc = 1;
- }
- }else if( strcmp(azArg[1],"edit")==0 ){
- if( nArg!=5 ){
- raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
- booleanValue(azArg[4]));
- if( rc ){
- raw_printf(stderr, "User-Edit failed: %d\n", rc);
- rc = 1;
- }
- }else if( strcmp(azArg[1],"delete")==0 ){
- if( nArg!=3 ){
- raw_printf(stderr, "Usage: .user delete USER\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_user_delete(p->db, azArg[2]);
- if( rc ){
- raw_printf(stderr, "User-Delete failed: %d\n", rc);
- rc = 1;
- }
- }else{
- raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
- rc = 1;
- goto meta_command_exit;
- }
- }else
-#endif /* SQLITE_USER_AUTHENTICATION */
-
- if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
- utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
- sqlite3_libversion(), sqlite3_sourceid());
-#if SQLITE_HAVE_ZLIB
- utf8_printf(p->out, "zlib version %s\n", zlibVersion());
-#endif
-#define CTIMEOPT_VAL_(opt) #opt
-#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
-#if defined(__clang__) && defined(__clang_major__)
- utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
- CTIMEOPT_VAL(__clang_minor__) "."
- CTIMEOPT_VAL(__clang_patchlevel__) "\n");
-#elif defined(_MSC_VER)
- utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
-#elif defined(__GNUC__) && defined(__VERSION__)
- utf8_printf(p->out, "gcc-" __VERSION__ "\n");
-#endif
- }else
-
- if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
- const char *zDbName = nArg==2 ? azArg[1] : "main";
- sqlite3_vfs *pVfs = 0;
- if( p->db ){
- sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
- if( pVfs ){
- utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
- raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
- raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
- raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
- }
- }
- }else
-
- if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
- sqlite3_vfs *pVfs;
- sqlite3_vfs *pCurrent = 0;
- if( p->db ){
- sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
- }
- for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
- utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
- pVfs==pCurrent ? " <--- CURRENT" : "");
- raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
- raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
- raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
- if( pVfs->pNext ){
- raw_printf(p->out, "-----------------------------------\n");
- }
- }
- }else
-
- if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
- const char *zDbName = nArg==2 ? azArg[1] : "main";
- char *zVfsName = 0;
- if( p->db ){
- sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
- if( zVfsName ){
- utf8_printf(p->out, "%s\n", zVfsName);
- sqlite3_free(zVfsName);
- }
- }
- }else
-
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
- if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
- sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
- }else
-#endif
-
- if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
- int j;
- assert( nArg<=ArraySize(azArg) );
- for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
- p->colWidth[j-1] = (int)integerValue(azArg[j]);
- }
- }else
-
- {
- utf8_printf(stderr, "Error: unknown command or invalid arguments: "
- " \"%s\". Enter \".help\" for help\n", azArg[0]);
- rc = 1;
- }
-
-meta_command_exit:
- if( p->outCount ){
- p->outCount--;
- if( p->outCount==0 ) output_reset(p);
- }
- return rc;
-}
-
-/*
-** Return TRUE if a semicolon occurs anywhere in the first N characters
-** of string z[].
-*/
-static int line_contains_semicolon(const char *z, int N){
- int i;
- for(i=0; i<N; i++){ if( z[i]==';' ) return 1; }
- return 0;
-}
-
-/*
-** Test to see if a line consists entirely of whitespace.
-*/
-static int _all_whitespace(const char *z){
- for(; *z; z++){
- if( IsSpace(z[0]) ) continue;
- if( *z=='/' && z[1]=='*' ){
- z += 2;
- while( *z && (*z!='*' || z[1]!='/') ){ z++; }
- if( *z==0 ) return 0;
- z++;
- continue;
- }
- if( *z=='-' && z[1]=='-' ){
- z += 2;
- while( *z && *z!='\n' ){ z++; }
- if( *z==0 ) return 1;
- continue;
- }
- return 0;
- }
- return 1;
-}
-
-/*
-** Return TRUE if the line typed in is an SQL command terminator other
-** than a semi-colon. The SQL Server style "go" command is understood
-** as is the Oracle "/".
-*/
-static int line_is_command_terminator(const char *zLine){
- while( IsSpace(zLine[0]) ){ zLine++; };
- if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
- return 1; /* Oracle */
- }
- if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
- && _all_whitespace(&zLine[2]) ){
- return 1; /* SQL Server */
- }
- return 0;
-}
-
-/*
-** We need a default sqlite3_complete() implementation to use in case
-** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
-** any arbitrary text is a complete SQL statement. This is not very
-** user-friendly, but it does seem to work.
-*/
-#ifdef SQLITE_OMIT_COMPLETE
-int sqlite3_complete(const char *zSql){ return 1; }
-#endif
-
-/*
-** Return true if zSql is a complete SQL statement. Return false if it
-** ends in the middle of a string literal or C-style comment.
-*/
-static int line_is_complete(char *zSql, int nSql){
- int rc;
- if( zSql==0 ) return 1;
- zSql[nSql] = ';';
- zSql[nSql+1] = 0;
- rc = sqlite3_complete(zSql);
- zSql[nSql] = 0;
- return rc;
-}
-
-/*
-** Run a single line of SQL. Return the number of errors.
-*/
-static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
- int rc;
- char *zErrMsg = 0;
-
- open_db(p, 0);
- if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
- BEGIN_TIMER;
- rc = shell_exec(p, zSql, &zErrMsg);
- END_TIMER;
- if( rc || zErrMsg ){
- char zPrefix[100];
- if( in!=0 || !stdin_is_interactive ){
- sqlite3_snprintf(sizeof(zPrefix), zPrefix,
- "Error: near line %d:", startline);
- }else{
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
- }
- if( zErrMsg!=0 ){
- utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
- sqlite3_free(zErrMsg);
- zErrMsg = 0;
- }else{
- utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
- }
- return 1;
- }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
- raw_printf(p->out, "changes: %3d total_changes: %d\n",
- sqlite3_changes(p->db), sqlite3_total_changes(p->db));
- }
- return 0;
-}
-
-
-/*
-** Read input from *in and process it. If *in==0 then input
-** is interactive - the user is typing it it. Otherwise, input
-** is coming from a file or device. A prompt is issued and history
-** is saved only if input is interactive. An interrupt signal will
-** cause this routine to exit immediately, unless input is interactive.
-**
-** Return the number of errors.
-*/
-static int process_input(ShellState *p, FILE *in){
- char *zLine = 0; /* A single input line */
- char *zSql = 0; /* Accumulated SQL text */
- int nLine; /* Length of current line */
- int nSql = 0; /* Bytes of zSql[] used */
- int nAlloc = 0; /* Allocated zSql[] space */
- int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
- int rc; /* Error code */
- int errCnt = 0; /* Number of errors seen */
- int lineno = 0; /* Current line number */
- int startline = 0; /* Line number for start of current input */
-
- while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
- fflush(p->out);
- zLine = one_input_line(in, zLine, nSql>0);
- if( zLine==0 ){
- /* End of input */
- if( in==0 && stdin_is_interactive ) printf("\n");
- break;
- }
- if( seenInterrupt ){
- if( in!=0 ) break;
- seenInterrupt = 0;
- }
- lineno++;
- if( nSql==0 && _all_whitespace(zLine) ){
- if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
- continue;
- }
- if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
- if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
- if( zLine[0]=='.' ){
- rc = do_meta_command(zLine, p);
- if( rc==2 ){ /* exit requested */
- break;
- }else if( rc ){
- errCnt++;
- }
- }
- continue;
- }
- if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
- memcpy(zLine,";",2);
- }
- nLine = strlen30(zLine);
- if( nSql+nLine+2>=nAlloc ){
- nAlloc = nSql+nLine+100;
- zSql = realloc(zSql, nAlloc);
- if( zSql==0 ) shell_out_of_memory();
- }
- nSqlPrior = nSql;
- if( nSql==0 ){
- int i;
- for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
- assert( nAlloc>0 && zSql!=0 );
- memcpy(zSql, zLine+i, nLine+1-i);
- startline = lineno;
- nSql = nLine-i;
- }else{
- zSql[nSql++] = '\n';
- memcpy(zSql+nSql, zLine, nLine+1);
- nSql += nLine;
- }
- if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
- && sqlite3_complete(zSql) ){
- errCnt += runOneSqlLine(p, zSql, in, startline);
- nSql = 0;
- if( p->outCount ){
- output_reset(p);
- p->outCount = 0;
- }else{
- clearTempFile(p);
- }
- }else if( nSql && _all_whitespace(zSql) ){
- if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
- nSql = 0;
- }
- }
- if( nSql && !_all_whitespace(zSql) ){
- errCnt += runOneSqlLine(p, zSql, in, startline);
- }
- free(zSql);
- free(zLine);
- return errCnt>0;
-}
-
-/*
-** Return a pathname which is the user's home directory. A
-** 0 return indicates an error of some kind.
-*/
-static char *find_home_dir(int clearFlag){
- static char *home_dir = NULL;
- if( clearFlag ){
- free(home_dir);
- home_dir = 0;
- return 0;
- }
- if( home_dir ) return home_dir;
-
-#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
- && !defined(__RTP__) && !defined(_WRS_KERNEL)
- {
- struct passwd *pwent;
- uid_t uid = getuid();
- if( (pwent=getpwuid(uid)) != NULL) {
- home_dir = pwent->pw_dir;
- }
- }
-#endif
-
-#if defined(_WIN32_WCE)
- /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
- */
- home_dir = "/";
-#else
-
-#if defined(_WIN32) || defined(WIN32)
- if (!home_dir) {
- home_dir = getenv("USERPROFILE");
- }
-#endif
-
- if (!home_dir) {
- home_dir = getenv("HOME");
- }
-
-#if defined(_WIN32) || defined(WIN32)
- if (!home_dir) {
- char *zDrive, *zPath;
- int n;
- zDrive = getenv("HOMEDRIVE");
- zPath = getenv("HOMEPATH");
- if( zDrive && zPath ){
- n = strlen30(zDrive) + strlen30(zPath) + 1;
- home_dir = malloc( n );
- if( home_dir==0 ) return 0;
- sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
- return home_dir;
- }
- home_dir = "c:\\";
- }
-#endif
-
-#endif /* !_WIN32_WCE */
-
- if( home_dir ){
- int n = strlen30(home_dir) + 1;
- char *z = malloc( n );
- if( z ) memcpy(z, home_dir, n);
- home_dir = z;
- }
-
- return home_dir;
-}
-
-/*
-** Read input from the file given by sqliterc_override. Or if that
-** parameter is NULL, take input from ~/.sqliterc
-**
-** Returns the number of errors.
-*/
-static void process_sqliterc(
- ShellState *p, /* Configuration data */
- const char *sqliterc_override /* Name of config file. NULL to use default */
-){
- char *home_dir = NULL;
- const char *sqliterc = sqliterc_override;
- char *zBuf = 0;
- FILE *in = NULL;
-
- if (sqliterc == NULL) {
- home_dir = find_home_dir(0);
- if( home_dir==0 ){
- raw_printf(stderr, "-- warning: cannot find home directory;"
- " cannot read ~/.sqliterc\n");
- return;
- }
- zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
- sqliterc = zBuf;
- }
- in = fopen(sqliterc,"rb");
- if( in ){
- if( stdin_is_interactive ){
- utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
- }
- process_input(p,in);
- fclose(in);
- }
- sqlite3_free(zBuf);
-}
-
-/*
-** Show available command line options
-*/
-static const char zOptions[] =
-#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
- " -A ARGS... run \".archive ARGS\" and exit\n"
-#endif
- " -append append the database to the end of the file\n"
- " -ascii set output mode to 'ascii'\n"
- " -bail stop after hitting an error\n"
- " -batch force batch I/O\n"
- " -column set output mode to 'column'\n"
- " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
- " -csv set output mode to 'csv'\n"
- " -echo print commands before execution\n"
- " -init FILENAME read/process named file\n"
- " -[no]header turn headers on or off\n"
-#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
- " -heap SIZE Size of heap for memsys3 or memsys5\n"
-#endif
- " -help show this message\n"
- " -html set output mode to HTML\n"
- " -interactive force interactive I/O\n"
- " -line set output mode to 'line'\n"
- " -list set output mode to 'list'\n"
- " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
- " -mmap N default mmap size set to N\n"
-#ifdef SQLITE_ENABLE_MULTIPLEX
- " -multiplex enable the multiplexor VFS\n"
-#endif
- " -newline SEP set output row separator. Default: '\\n'\n"
- " -nullvalue TEXT set text string for NULL values. Default ''\n"
- " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
- " -quote set output mode to 'quote'\n"
- " -readonly open the database read-only\n"
- " -separator SEP set output column separator. Default: '|'\n"
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- " -sorterref SIZE sorter references threshold size\n"
-#endif
- " -stats print memory stats before each finalize\n"
- " -version show SQLite version\n"
- " -vfs NAME use NAME as the default VFS\n"
-#ifdef SQLITE_ENABLE_VFSTRACE
- " -vfstrace enable tracing of all VFS calls\n"
-#endif
-#ifdef SQLITE_HAVE_ZLIB
- " -zip open the file as a ZIP Archive\n"
-#endif
-;
-static void usage(int showDetail){
- utf8_printf(stderr,
- "Usage: %s [OPTIONS] FILENAME [SQL]\n"
- "FILENAME is the name of an SQLite database. A new database is created\n"
- "if the file does not previously exist.\n", Argv0);
- if( showDetail ){
- utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
- }else{
- raw_printf(stderr, "Use the -help option for additional information\n");
- }
- exit(1);
-}
-
-/*
-** Internal check: Verify that the SQLite is uninitialized. Print a
-** error message if it is initialized.
-*/
-static void verify_uninitialized(void){
- if( sqlite3_config(-1)==SQLITE_MISUSE ){
- utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
- " initialization.\n");
- }
-}
-
-/*
-** Initialize the state information in data
-*/
-static void main_init(ShellState *data) {
- memset(data, 0, sizeof(*data));
- data->normalMode = data->cMode = data->mode = MODE_List;
- data->autoExplain = 1;
- memcpy(data->colSeparator,SEP_Column, 2);
- memcpy(data->rowSeparator,SEP_Row, 2);
- data->showHeader = 0;
- data->shellFlgs = SHFLG_Lookaside;
- verify_uninitialized();
- sqlite3_config(SQLITE_CONFIG_URI, 1);
- sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
- sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
- sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
- sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
-}
-
-/*
-** Output text to the console in a font that attracts extra attention.
-*/
-#ifdef _WIN32
-static void printBold(const char *zText){
- HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
- GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
- SetConsoleTextAttribute(out,
- FOREGROUND_RED|FOREGROUND_INTENSITY
- );
- printf("%s", zText);
- SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
-}
-#else
-static void printBold(const char *zText){
- printf("\033[1m%s\033[0m", zText);
-}
-#endif
-
-/*
-** Get the argument to an --option. Throw an error and die if no argument
-** is available.
-*/
-static char *cmdline_option_value(int argc, char **argv, int i){
- if( i==argc ){
- utf8_printf(stderr, "%s: Error: missing argument to %s\n",
- argv[0], argv[argc-1]);
- exit(1);
- }
- return argv[i];
-}
-
-#ifndef SQLITE_SHELL_IS_UTF8
-# if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
-# define SQLITE_SHELL_IS_UTF8 (0)
-# else
-# define SQLITE_SHELL_IS_UTF8 (1)
-# endif
-#endif
-
-#if SQLITE_SHELL_IS_UTF8
-int SQLITE_CDECL main(int argc, char **argv){
-#else
-int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
- char **argv;
-#endif
- char *zErrMsg = 0;
- ShellState data;
- const char *zInitFile = 0;
- int i;
- int rc = 0;
- int warnInmemoryDb = 0;
- int readStdin = 1;
- int nCmd = 0;
- char **azCmd = 0;
- const char *zVfs = 0; /* Value of -vfs command-line option */
-#if !SQLITE_SHELL_IS_UTF8
- char **argvToFree = 0;
- int argcToFree = 0;
-#endif
-
- setBinaryMode(stdin, 0);
- setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
- stdin_is_interactive = isatty(0);
- stdout_is_console = isatty(1);
-
-#if USE_SYSTEM_SQLITE+0!=1
- if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
- utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
- sqlite3_sourceid(), SQLITE_SOURCE_ID);
- exit(1);
- }
-#endif
- main_init(&data);
-
- /* On Windows, we must translate command-line arguments into UTF-8.
- ** The SQLite memory allocator subsystem has to be enabled in order to
- ** do this. But we want to run an sqlite3_shutdown() afterwards so that
- ** subsequent sqlite3_config() calls will work. So copy all results into
- ** memory that does not come from the SQLite memory allocator.
- */
-#if !SQLITE_SHELL_IS_UTF8
- sqlite3_initialize();
- argvToFree = malloc(sizeof(argv[0])*argc*2);
- argcToFree = argc;
- argv = argvToFree + argc;
- if( argv==0 ) shell_out_of_memory();
- for(i=0; i<argc; i++){
- char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
- int n;
- if( z==0 ) shell_out_of_memory();
- n = (int)strlen(z);
- argv[i] = malloc( n+1 );
- if( argv[i]==0 ) shell_out_of_memory();
- memcpy(argv[i], z, n+1);
- argvToFree[i] = argv[i];
- sqlite3_free(z);
- }
- sqlite3_shutdown();
-#endif
-
- assert( argc>=1 && argv && argv[0] );
- Argv0 = argv[0];
-
- /* Make sure we have a valid signal handler early, before anything
- ** else is done.
- */
-#ifdef SIGINT
- signal(SIGINT, interrupt_handler);
-#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
- SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
-#endif
-
-#ifdef SQLITE_SHELL_DBNAME_PROC
- {
- /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
- ** of a C-function that will provide the name of the database file. Use
- ** this compile-time option to embed this shell program in larger
- ** applications. */
- extern void SQLITE_SHELL_DBNAME_PROC(const char**);
- SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
- warnInmemoryDb = 0;
- }
-#endif
-
- /* Do an initial pass through the command-line argument to locate
- ** the name of the database file, the name of the initialization file,
- ** the size of the alternative malloc heap,
- ** and the first command to execute.
- */
- verify_uninitialized();
- for(i=1; i<argc; i++){
- char *z;
- z = argv[i];
- if( z[0]!='-' ){
- if( data.zDbFilename==0 ){
- data.zDbFilename = z;
- }else{
- /* Excesss arguments are interpreted as SQL (or dot-commands) and
- ** mean that nothing is read from stdin */
- readStdin = 0;
- nCmd++;
- azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
- if( azCmd==0 ) shell_out_of_memory();
- azCmd[nCmd-1] = z;
- }
- }
- if( z[1]=='-' ) z++;
- if( strcmp(z,"-separator")==0
- || strcmp(z,"-nullvalue")==0
- || strcmp(z,"-newline")==0
- || strcmp(z,"-cmd")==0
- ){
- (void)cmdline_option_value(argc, argv, ++i);
- }else if( strcmp(z,"-init")==0 ){
- zInitFile = cmdline_option_value(argc, argv, ++i);
- }else if( strcmp(z,"-batch")==0 ){
- /* Need to check for batch mode here to so we can avoid printing
- ** informational messages (like from process_sqliterc) before
- ** we do the actual processing of arguments later in a second pass.
- */
- stdin_is_interactive = 0;
- }else if( strcmp(z,"-heap")==0 ){
-#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
- const char *zSize;
- sqlite3_int64 szHeap;
-
- zSize = cmdline_option_value(argc, argv, ++i);
- szHeap = integerValue(zSize);
- if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
- sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
-#else
- (void)cmdline_option_value(argc, argv, ++i);
-#endif
- }else if( strcmp(z,"-pagecache")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( sz>70000 ) sz = 70000;
- if( sz<0 ) sz = 0;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
- sqlite3_config(SQLITE_CONFIG_PAGECACHE,
- (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
- data.shellFlgs |= SHFLG_Pagecache;
- }else if( strcmp(z,"-lookaside")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( sz<0 ) sz = 0;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( n<0 ) n = 0;
- sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
- if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
-#ifdef SQLITE_ENABLE_VFSTRACE
- }else if( strcmp(z,"-vfstrace")==0 ){
- extern int vfstrace_register(
- const char *zTraceName,
- const char *zOldVfsName,
- int (*xOut)(const char*,void*),
- void *pOutArg,
- int makeDefault
- );
- vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
-#endif
-#ifdef SQLITE_ENABLE_MULTIPLEX
- }else if( strcmp(z,"-multiplex")==0 ){
- extern int sqlite3_multiple_initialize(const char*,int);
- sqlite3_multiplex_initialize(0, 1);
-#endif
- }else if( strcmp(z,"-mmap")==0 ){
- sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
- sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- }else if( strcmp(z,"-sorterref")==0 ){
- sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
- sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
-#endif
- }else if( strcmp(z,"-vfs")==0 ){
- zVfs = cmdline_option_value(argc, argv, ++i);
-#ifdef SQLITE_HAVE_ZLIB
- }else if( strcmp(z,"-zip")==0 ){
- data.openMode = SHELL_OPEN_ZIPFILE;
-#endif
- }else if( strcmp(z,"-append")==0 ){
- data.openMode = SHELL_OPEN_APPENDVFS;
- }else if( strcmp(z,"-readonly")==0 ){
- data.openMode = SHELL_OPEN_READONLY;
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
- }else if( strncmp(z, "-A",2)==0 ){
- /* All remaining command-line arguments are passed to the ".archive"
- ** command, so ignore them */
- break;
-#endif
- }
- }
- verify_uninitialized();
-
-
-#ifdef SQLITE_SHELL_INIT_PROC
- {
- /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
- ** of a C-function that will perform initialization actions on SQLite that
- ** occur just before or after sqlite3_initialize(). Use this compile-time
- ** option to embed this shell program in larger applications. */
- extern void SQLITE_SHELL_INIT_PROC(void);
- SQLITE_SHELL_INIT_PROC();
- }
-#else
- /* All the sqlite3_config() calls have now been made. So it is safe
- ** to call sqlite3_initialize() and process any command line -vfs option. */
- sqlite3_initialize();
-#endif
-
- if( zVfs ){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
- if( pVfs ){
- sqlite3_vfs_register(pVfs, 1);
- }else{
- utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
- exit(1);
- }
- }
-
- if( data.zDbFilename==0 ){
-#ifndef SQLITE_OMIT_MEMORYDB
- data.zDbFilename = ":memory:";
- warnInmemoryDb = argc==1;
-#else
- utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
- return 1;
-#endif
- }
- data.out = stdout;
- sqlite3_appendvfs_init(0,0,0);
-
- /* Go ahead and open the database file if it already exists. If the
- ** file does not exist, delay opening it. This prevents empty database
- ** files from being created if a user mistypes the database name argument
- ** to the sqlite command-line tool.
- */
- if( access(data.zDbFilename, 0)==0 ){
- open_db(&data, 0);
- }
-
- /* Process the initialization file if there is one. If no -init option
- ** is given on the command line, look for a file named ~/.sqliterc and
- ** try to process it.
- */
- process_sqliterc(&data,zInitFile);
-
- /* Make a second pass through the command-line argument and set
- ** options. This second pass is delayed until after the initialization
- ** file is processed so that the command-line arguments will override
- ** settings in the initialization file.
- */
- for(i=1; i<argc; i++){
- char *z = argv[i];
- if( z[0]!='-' ) continue;
- if( z[1]=='-' ){ z++; }
- if( strcmp(z,"-init")==0 ){
- i++;
- }else if( strcmp(z,"-html")==0 ){
- data.mode = MODE_Html;
- }else if( strcmp(z,"-list")==0 ){
- data.mode = MODE_List;
- }else if( strcmp(z,"-quote")==0 ){
- data.mode = MODE_Quote;
- }else if( strcmp(z,"-line")==0 ){
- data.mode = MODE_Line;
- }else if( strcmp(z,"-column")==0 ){
- data.mode = MODE_Column;
- }else if( strcmp(z,"-csv")==0 ){
- data.mode = MODE_Csv;
- memcpy(data.colSeparator,",",2);
-#ifdef SQLITE_HAVE_ZLIB
- }else if( strcmp(z,"-zip")==0 ){
- data.openMode = SHELL_OPEN_ZIPFILE;
-#endif
- }else if( strcmp(z,"-append")==0 ){
- data.openMode = SHELL_OPEN_APPENDVFS;
- }else if( strcmp(z,"-readonly")==0 ){
- data.openMode = SHELL_OPEN_READONLY;
- }else if( strcmp(z,"-ascii")==0 ){
- data.mode = MODE_Ascii;
- sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
- SEP_Unit);
- sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
- SEP_Record);
- }else if( strcmp(z,"-separator")==0 ){
- sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
- "%s",cmdline_option_value(argc,argv,++i));
- }else if( strcmp(z,"-newline")==0 ){
- sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
- "%s",cmdline_option_value(argc,argv,++i));
- }else if( strcmp(z,"-nullvalue")==0 ){
- sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
- "%s",cmdline_option_value(argc,argv,++i));
- }else if( strcmp(z,"-header")==0 ){
- data.showHeader = 1;
- }else if( strcmp(z,"-noheader")==0 ){
- data.showHeader = 0;
- }else if( strcmp(z,"-echo")==0 ){
- ShellSetFlag(&data, SHFLG_Echo);
- }else if( strcmp(z,"-eqp")==0 ){
- data.autoEQP = AUTOEQP_on;
- }else if( strcmp(z,"-eqpfull")==0 ){
- data.autoEQP = AUTOEQP_full;
- }else if( strcmp(z,"-stats")==0 ){
- data.statsOn = 1;
- }else if( strcmp(z,"-scanstats")==0 ){
- data.scanstatsOn = 1;
- }else if( strcmp(z,"-backslash")==0 ){
- /* Undocumented command-line option: -backslash
- ** Causes C-style backslash escapes to be evaluated in SQL statements
- ** prior to sending the SQL into SQLite. Useful for injecting
- ** crazy bytes in the middle of SQL statements for testing and debugging.
- */
- ShellSetFlag(&data, SHFLG_Backslash);
- }else if( strcmp(z,"-bail")==0 ){
- bail_on_error = 1;
- }else if( strcmp(z,"-version")==0 ){
- printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
- return 0;
- }else if( strcmp(z,"-interactive")==0 ){
- stdin_is_interactive = 1;
- }else if( strcmp(z,"-batch")==0 ){
- stdin_is_interactive = 0;
- }else if( strcmp(z,"-heap")==0 ){
- i++;
- }else if( strcmp(z,"-pagecache")==0 ){
- i+=2;
- }else if( strcmp(z,"-lookaside")==0 ){
- i+=2;
- }else if( strcmp(z,"-mmap")==0 ){
- i++;
-#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- }else if( strcmp(z,"-sorterref")==0 ){
- i++;
-#endif
- }else if( strcmp(z,"-vfs")==0 ){
- i++;
-#ifdef SQLITE_ENABLE_VFSTRACE
- }else if( strcmp(z,"-vfstrace")==0 ){
- i++;
-#endif
-#ifdef SQLITE_ENABLE_MULTIPLEX
- }else if( strcmp(z,"-multiplex")==0 ){
- i++;
-#endif
- }else if( strcmp(z,"-help")==0 ){
- usage(1);
- }else if( strcmp(z,"-cmd")==0 ){
- /* Run commands that follow -cmd first and separately from commands
- ** that simply appear on the command-line. This seems goofy. It would
- ** be better if all commands ran in the order that they appear. But
- ** we retain the goofy behavior for historical compatibility. */
- if( i==argc-1 ) break;
- z = cmdline_option_value(argc,argv,++i);
- if( z[0]=='.' ){
- rc = do_meta_command(z, &data);
- if( rc && bail_on_error ) return rc==2 ? 0 : rc;
- }else{
- open_db(&data, 0);
- rc = shell_exec(&data, z, &zErrMsg);
- if( zErrMsg!=0 ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- if( bail_on_error ) return rc!=0 ? rc : 1;
- }else if( rc!=0 ){
- utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
- if( bail_on_error ) return rc;
- }
- }
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
- }else if( strncmp(z, "-A", 2)==0 ){
- if( nCmd>0 ){
- utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
- " with \"%s\"\n", z);
- return 1;
- }
- open_db(&data, OPEN_DB_ZIPFILE);
- if( z[2] ){
- argv[i] = &z[2];
- arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
- }else{
- arDotCommand(&data, 1, argv+i, argc-i);
- }
- readStdin = 0;
- break;
-#endif
- }else{
- utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
- raw_printf(stderr,"Use -help for a list of options.\n");
- return 1;
- }
- data.cMode = data.mode;
- }
-
- if( !readStdin ){
- /* Run all arguments that do not begin with '-' as if they were separate
- ** command-line inputs, except for the argToSkip argument which contains
- ** the database filename.
- */
- for(i=0; i<nCmd; i++){
- if( azCmd[i][0]=='.' ){
- rc = do_meta_command(azCmd[i], &data);
- if( rc ) return rc==2 ? 0 : rc;
- }else{
- open_db(&data, 0);
- rc = shell_exec(&data, azCmd[i], &zErrMsg);
- if( zErrMsg!=0 ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- return rc!=0 ? rc : 1;
- }else if( rc!=0 ){
- utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
- return rc;
- }
- }
- }
- free(azCmd);
- }else{
- /* Run commands received from standard input
- */
- if( stdin_is_interactive ){
- char *zHome;
- char *zHistory = 0;
- int nHistory;
- printf(
- "SQLite version %s %.19s\n" /*extra-version-info*/
- "Enter \".help\" for usage hints.\n",
- sqlite3_libversion(), sqlite3_sourceid()
- );
- if( warnInmemoryDb ){
- printf("Connected to a ");
- printBold("transient in-memory database");
- printf(".\nUse \".open FILENAME\" to reopen on a "
- "persistent database.\n");
- }
- zHome = find_home_dir(0);
- if( zHome ){
- nHistory = strlen30(zHome) + 20;
- if( (zHistory = malloc(nHistory))!=0 ){
- sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
- }
- }
- if( zHistory ){ shell_read_history(zHistory); }
-#if HAVE_READLINE || HAVE_EDITLINE
- rl_attempted_completion_function = readline_completion;
-#elif HAVE_LINENOISE
- linenoiseSetCompletionCallback(linenoise_completion);
-#endif
- rc = process_input(&data, 0);
- if( zHistory ){
- shell_stifle_history(2000);
- shell_write_history(zHistory);
- free(zHistory);
- }
- }else{
- rc = process_input(&data, stdin);
- }
- }
- set_table_name(&data, 0);
- if( data.db ){
- session_close_all(&data);
- close_db(data.db);
- }
- sqlite3_free(data.zFreeOnClose);
- find_home_dir(1);
- output_reset(&data);
- data.doXdgOpen = 0;
- clearTempFile(&data);
-#if !SQLITE_SHELL_IS_UTF8
- for(i=0; i<argcToFree; i++) free(argvToFree[i]);
- free(argvToFree);
-#endif
- /* Clear the global data structure so that valgrind will detect memory
- ** leaks */
- memset(&data, 0, sizeof(data));
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite.h.in b/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite.h.in
deleted file mode 100644
index 3d2effa5b78..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite.h.in
+++ /dev/null
@@ -1,9148 +0,0 @@
-/*
-** 2001-09-15
-**
-** 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 header file defines the interface that the SQLite library
-** presents to client programs. If a C-function, structure, datatype,
-** or constant definition does not appear in this file, then it is
-** not a published API of SQLite, is subject to change without
-** notice, and should not be referenced by programs that use SQLite.
-**
-** Some of the definitions that are in this file are marked as
-** "experimental". Experimental interfaces are normally new
-** features recently added to SQLite. We do not anticipate changes
-** to experimental interfaces but reserve the right to make minor changes
-** if experience from use "in the wild" suggest such changes are prudent.
-**
-** The official C-language API documentation for SQLite is derived
-** from comments in this file. This file is the authoritative source
-** on how SQLite interfaces are supposed to operate.
-**
-** The name of this file under configuration management is "sqlite.h.in".
-** The makefile makes some minor changes to this file (such as inserting
-** the version number) and changes its name to "sqlite3.h" as
-** part of the build process.
-*/
-#ifndef SQLITE3_H
-#define SQLITE3_H
-#include <stdarg.h> /* Needed for the definition of va_list */
-
-/*
-** Make sure we can call this stuff from C++.
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*
-** Provide the ability to override linkage features of the interface.
-*/
-#ifndef SQLITE_EXTERN
-# define SQLITE_EXTERN extern
-#endif
-#ifndef SQLITE_API
-# define SQLITE_API
-#endif
-#ifndef SQLITE_CDECL
-# define SQLITE_CDECL
-#endif
-#ifndef SQLITE_APICALL
-# define SQLITE_APICALL
-#endif
-#ifndef SQLITE_STDCALL
-# define SQLITE_STDCALL SQLITE_APICALL
-#endif
-#ifndef SQLITE_CALLBACK
-# define SQLITE_CALLBACK
-#endif
-#ifndef SQLITE_SYSAPI
-# define SQLITE_SYSAPI
-#endif
-
-/*
-** These no-op macros are used in front of interfaces to mark those
-** interfaces as either deprecated or experimental. New applications
-** should not use deprecated interfaces - they are supported for backwards
-** compatibility only. Application writers should be aware that
-** experimental interfaces are subject to change in point releases.
-**
-** These macros used to resolve to various kinds of compiler magic that
-** would generate warning messages when they were used. But that
-** compiler magic ended up generating such a flurry of bug reports
-** that we have taken it all out and gone back to using simple
-** noop macros.
-*/
-#define SQLITE_DEPRECATED
-#define SQLITE_EXPERIMENTAL
-
-/*
-** Ensure these symbols were not defined by some previous header file.
-*/
-#ifdef SQLITE_VERSION
-# undef SQLITE_VERSION
-#endif
-#ifdef SQLITE_VERSION_NUMBER
-# undef SQLITE_VERSION_NUMBER
-#endif
-
-/*
-** CAPI3REF: Compile-Time Library Version Numbers
-**
-** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header
-** evaluates to a string literal that is the SQLite version in the
-** format "X.Y.Z" where X is the major version number (always 3 for
-** SQLite3) and Y is the minor version number and Z is the release number.)^
-** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer
-** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
-** numbers used in [SQLITE_VERSION].)^
-** The SQLITE_VERSION_NUMBER for any given release of SQLite will also
-** be larger than the release from which it is derived. Either Y will
-** be held constant and Z will be incremented or else Y will be incremented
-** and Z will be reset to zero.
-**
-** Since [version 3.6.18] ([dateof:3.6.18]),
-** SQLite source code has been stored in the
-** <a href="http://www.fossil-scm.org/">Fossil configuration management
-** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
-** a string which identifies a particular check-in of SQLite
-** within its configuration management system. ^The SQLITE_SOURCE_ID
-** string contains the date and time of the check-in (UTC) and a SHA1
-** or SHA3-256 hash of the entire source tree. If the source code has
-** been edited in any way since it was last checked in, then the last
-** four hexadecimal digits of the hash may be modified.
-**
-** See also: [sqlite3_libversion()],
-** [sqlite3_libversion_number()], [sqlite3_sourceid()],
-** [sqlite_version()] and [sqlite_source_id()].
-*/
-#define SQLITE_VERSION "--VERS--"
-#define SQLITE_VERSION_NUMBER --VERSION-NUMBER--
-#define SQLITE_SOURCE_ID "--SOURCE-ID--"
-
-/*
-** CAPI3REF: Run-Time Library Version Numbers
-** KEYWORDS: sqlite3_version sqlite3_sourceid
-**
-** These interfaces provide the same information as the [SQLITE_VERSION],
-** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
-** but are associated with the library instead of the header file. ^(Cautious
-** programmers might include assert() statements in their application to
-** verify that values returned by these interfaces match the macros in
-** the header, and thus ensure that the application is
-** compiled with matching library and header files.
-**
-** <blockquote><pre>
-** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
-** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
-** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
-** </pre></blockquote>)^
-**
-** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION]
-** macro. ^The sqlite3_libversion() function returns a pointer to the
-** to the sqlite3_version[] string constant. The sqlite3_libversion()
-** function is provided for use in DLLs since DLL users usually do not have
-** direct access to string constants within the DLL. ^The
-** sqlite3_libversion_number() function returns an integer equal to
-** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns
-** a pointer to a string constant whose value is the same as the
-** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built
-** using an edited copy of [the amalgamation], then the last four characters
-** of the hash might be different from [SQLITE_SOURCE_ID].)^
-**
-** See also: [sqlite_version()] and [sqlite_source_id()].
-*/
-SQLITE_EXTERN const char sqlite3_version[];
-const char *sqlite3_libversion(void);
-const char *sqlite3_sourceid(void);
-int sqlite3_libversion_number(void);
-
-/*
-** CAPI3REF: Run-Time Library Compilation Options Diagnostics
-**
-** ^The sqlite3_compileoption_used() function returns 0 or 1
-** indicating whether the specified option was defined at
-** compile time. ^The SQLITE_ prefix may be omitted from the
-** option name passed to sqlite3_compileoption_used().
-**
-** ^The sqlite3_compileoption_get() function allows iterating
-** over the list of options that were defined at compile time by
-** returning the N-th compile time option string. ^If N is out of range,
-** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_
-** prefix is omitted from any strings returned by
-** sqlite3_compileoption_get().
-**
-** ^Support for the diagnostic functions sqlite3_compileoption_used()
-** and sqlite3_compileoption_get() may be omitted by specifying the
-** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
-**
-** See also: SQL functions [sqlite_compileoption_used()] and
-** [sqlite_compileoption_get()] and the [compile_options pragma].
-*/
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-int sqlite3_compileoption_used(const char *zOptName);
-const char *sqlite3_compileoption_get(int N);
-#endif
-
-/*
-** CAPI3REF: Test To See If The Library Is Threadsafe
-**
-** ^The sqlite3_threadsafe() function returns zero if and only if
-** SQLite was compiled with mutexing code omitted due to the
-** [SQLITE_THREADSAFE] compile-time option being set to 0.
-**
-** SQLite can be compiled with or without mutexes. When
-** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes
-** are enabled and SQLite is threadsafe. When the
-** [SQLITE_THREADSAFE] macro is 0,
-** the mutexes are omitted. Without the mutexes, it is not safe
-** to use SQLite concurrently from more than one thread.
-**
-** Enabling mutexes incurs a measurable performance penalty.
-** So if speed is of utmost importance, it makes sense to disable
-** the mutexes. But for maximum safety, mutexes should be enabled.
-** ^The default behavior is for mutexes to be enabled.
-**
-** This interface can be used by an application to make sure that the
-** version of SQLite that it is linking against was compiled with
-** the desired setting of the [SQLITE_THREADSAFE] macro.
-**
-** This interface only reports on the compile-time mutex setting
-** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
-** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
-** can be fully or partially disabled using a call to [sqlite3_config()]
-** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
-** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the
-** sqlite3_threadsafe() function shows only the compile-time setting of
-** thread safety, not any run-time changes to that setting made by
-** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
-** is unchanged by calls to sqlite3_config().)^
-**
-** See the [threading mode] documentation for additional information.
-*/
-int sqlite3_threadsafe(void);
-
-/*
-** CAPI3REF: Database Connection Handle
-** KEYWORDS: {database connection} {database connections}
-**
-** Each open SQLite database is represented by a pointer to an instance of
-** the opaque structure named "sqlite3". It is useful to think of an sqlite3
-** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and
-** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
-** and [sqlite3_close_v2()] are its destructors. There are many other
-** interfaces (such as
-** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
-** [sqlite3_busy_timeout()] to name but three) that are methods on an
-** sqlite3 object.
-*/
-typedef struct sqlite3 sqlite3;
-
-/*
-** CAPI3REF: 64-Bit Integer Types
-** KEYWORDS: sqlite_int64 sqlite_uint64
-**
-** Because there is no cross-platform way to specify 64-bit integer types
-** SQLite includes typedefs for 64-bit signed and unsigned integers.
-**
-** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions.
-** The sqlite_int64 and sqlite_uint64 types are supported for backwards
-** compatibility only.
-**
-** ^The sqlite3_int64 and sqlite_int64 types can store integer values
-** between -9223372036854775808 and +9223372036854775807 inclusive. ^The
-** sqlite3_uint64 and sqlite_uint64 types can store integer values
-** between 0 and +18446744073709551615 inclusive.
-*/
-#ifdef SQLITE_INT64_TYPE
- typedef SQLITE_INT64_TYPE sqlite_int64;
-# ifdef SQLITE_UINT64_TYPE
- typedef SQLITE_UINT64_TYPE sqlite_uint64;
-# else
- typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
-# endif
-#elif defined(_MSC_VER) || defined(__BORLANDC__)
- typedef __int64 sqlite_int64;
- typedef unsigned __int64 sqlite_uint64;
-#else
- typedef long long int sqlite_int64;
- typedef unsigned long long int sqlite_uint64;
-#endif
-typedef sqlite_int64 sqlite3_int64;
-typedef sqlite_uint64 sqlite3_uint64;
-
-/*
-** If compiling for a processor that lacks floating point support,
-** substitute integer for floating-point.
-*/
-#ifdef SQLITE_OMIT_FLOATING_POINT
-# define double sqlite3_int64
-#endif
-
-/*
-** CAPI3REF: Closing A Database Connection
-** DESTRUCTOR: sqlite3
-**
-** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
-** for the [sqlite3] object.
-** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
-** the [sqlite3] object is successfully destroyed and all associated
-** resources are deallocated.
-**
-** ^If the database connection is associated with unfinalized prepared
-** statements or unfinished sqlite3_backup objects then sqlite3_close()
-** will leave the database connection open and return [SQLITE_BUSY].
-** ^If sqlite3_close_v2() is called with unfinalized prepared statements
-** and/or unfinished sqlite3_backups, then the database connection becomes
-** an unusable "zombie" which will automatically be deallocated when the
-** last prepared statement is finalized or the last sqlite3_backup is
-** finished. The sqlite3_close_v2() interface is intended for use with
-** host languages that are garbage collected, and where the order in which
-** destructors are called is arbitrary.
-**
-** Applications should [sqlite3_finalize | finalize] all [prepared statements],
-** [sqlite3_blob_close | close] all [BLOB handles], and
-** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
-** with the [sqlite3] object prior to attempting to close the object. ^If
-** sqlite3_close_v2() is called on a [database connection] that still has
-** outstanding [prepared statements], [BLOB handles], and/or
-** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
-** of resources is deferred until all [prepared statements], [BLOB handles],
-** and [sqlite3_backup] objects are also destroyed.
-**
-** ^If an [sqlite3] object is destroyed while a transaction is open,
-** the transaction is automatically rolled back.
-**
-** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
-** must be either a NULL
-** pointer or an [sqlite3] object pointer obtained
-** from [sqlite3_open()], [sqlite3_open16()], or
-** [sqlite3_open_v2()], and not previously closed.
-** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
-** argument is a harmless no-op.
-*/
-int sqlite3_close(sqlite3*);
-int sqlite3_close_v2(sqlite3*);
-
-/*
-** The type for a callback function.
-** This is legacy and deprecated. It is included for historical
-** compatibility and is not documented.
-*/
-typedef int (*sqlite3_callback)(void*,int,char**, char**);
-
-/*
-** CAPI3REF: One-Step Query Execution Interface
-** METHOD: sqlite3
-**
-** The sqlite3_exec() interface is a convenience wrapper around
-** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
-** that allows an application to run multiple statements of SQL
-** without having to use a lot of C code.
-**
-** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
-** semicolon-separate SQL statements passed into its 2nd argument,
-** in the context of the [database connection] passed in as its 1st
-** argument. ^If the callback function of the 3rd argument to
-** sqlite3_exec() is not NULL, then it is invoked for each result row
-** coming out of the evaluated SQL statements. ^The 4th argument to
-** sqlite3_exec() is relayed through to the 1st argument of each
-** callback invocation. ^If the callback pointer to sqlite3_exec()
-** is NULL, then no callback is ever invoked and result rows are
-** ignored.
-**
-** ^If an error occurs while evaluating the SQL statements passed into
-** sqlite3_exec(), then execution of the current statement stops and
-** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec()
-** is not NULL then any error message is written into memory obtained
-** from [sqlite3_malloc()] and passed back through the 5th parameter.
-** To avoid memory leaks, the application should invoke [sqlite3_free()]
-** on error message strings returned through the 5th parameter of
-** sqlite3_exec() after the error message string is no longer needed.
-** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors
-** occur, then sqlite3_exec() sets the pointer in its 5th parameter to
-** NULL before returning.
-**
-** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec()
-** routine returns SQLITE_ABORT without invoking the callback again and
-** without running any subsequent SQL statements.
-**
-** ^The 2nd argument to the sqlite3_exec() callback function is the
-** number of columns in the result. ^The 3rd argument to the sqlite3_exec()
-** callback is an array of pointers to strings obtained as if from
-** [sqlite3_column_text()], one for each column. ^If an element of a
-** result row is NULL then the corresponding string pointer for the
-** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the
-** sqlite3_exec() callback is an array of pointers to strings where each
-** entry represents the name of corresponding result column as obtained
-** from [sqlite3_column_name()].
-**
-** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
-** to an empty string, or a pointer that contains only whitespace and/or
-** SQL comments, then no SQL statements are evaluated and the database
-** is not changed.
-**
-** Restrictions:
-**
-** <ul>
-** <li> The application must ensure that the 1st parameter to sqlite3_exec()
-** is a valid and open [database connection].
-** <li> The application must not close the [database connection] specified by
-** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
-** <li> The application must not modify the SQL statement text passed into
-** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
-** </ul>
-*/
-int sqlite3_exec(
- sqlite3*, /* An open database */
- const char *sql, /* SQL to be evaluated */
- int (*callback)(void*,int,char**,char**), /* Callback function */
- void *, /* 1st argument to callback */
- char **errmsg /* Error msg written here */
-);
-
-/*
-** CAPI3REF: Result Codes
-** KEYWORDS: {result code definitions}
-**
-** Many SQLite functions return an integer result code from the set shown
-** here in order to indicate success or failure.
-**
-** New error codes may be added in future versions of SQLite.
-**
-** See also: [extended result code definitions]
-*/
-#define SQLITE_OK 0 /* Successful result */
-/* beginning-of-error-codes */
-#define SQLITE_ERROR 1 /* Generic error */
-#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
-#define SQLITE_PERM 3 /* Access permission denied */
-#define SQLITE_ABORT 4 /* Callback routine requested an abort */
-#define SQLITE_BUSY 5 /* The database file is locked */
-#define SQLITE_LOCKED 6 /* A table in the database is locked */
-#define SQLITE_NOMEM 7 /* A malloc() failed */
-#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
-#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
-#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
-#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
-#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */
-#define SQLITE_FULL 13 /* Insertion failed because database is full */
-#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
-#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
-#define SQLITE_EMPTY 16 /* Internal use only */
-#define SQLITE_SCHEMA 17 /* The database schema changed */
-#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
-#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
-#define SQLITE_MISMATCH 20 /* Data type mismatch */
-#define SQLITE_MISUSE 21 /* Library used incorrectly */
-#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
-#define SQLITE_AUTH 23 /* Authorization denied */
-#define SQLITE_FORMAT 24 /* Not used */
-#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
-#define SQLITE_NOTADB 26 /* File opened that is not a database file */
-#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */
-#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */
-#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
-#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
-/* end-of-error-codes */
-
-/*
-** CAPI3REF: Extended Result Codes
-** KEYWORDS: {extended result code definitions}
-**
-** In its default configuration, SQLite API routines return one of 30 integer
-** [result codes]. However, experience has shown that many of
-** these result codes are too coarse-grained. They do not provide as
-** much information about problems as programmers might like. In an effort to
-** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8]
-** and later) include
-** support for additional result codes that provide more detailed information
-** about errors. These [extended result codes] are enabled or disabled
-** on a per database connection basis using the
-** [sqlite3_extended_result_codes()] API. Or, the extended code for
-** the most recent error can be obtained using
-** [sqlite3_extended_errcode()].
-*/
-#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
-#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
-#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
-#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
-#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
-#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
-#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8))
-#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8))
-#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8))
-#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8))
-#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8))
-#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8))
-#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8))
-#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8))
-#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8))
-#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
-#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
-#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
-#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
-#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
-#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
-#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
-#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
-#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
-#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
-#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8))
-#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
-#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
-#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
-#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
-#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
-#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
-#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
-#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
-#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
-#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
-#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
-#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
-#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
-#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
-#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
-#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
-#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
-#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
-#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
-#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
-#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
-#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
-#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8))
-#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
-#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
-#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
-#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8))
-#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8))
-#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8))
-#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8))
-#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8))
-#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
-#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
-#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
-#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
-#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
-#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
-#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
-#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
-
-/*
-** CAPI3REF: Flags For File Open Operations
-**
-** These bit values are intended for use in the
-** 3rd parameter to the [sqlite3_open_v2()] interface and
-** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
-*/
-#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
-#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
-#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
-#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
-#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
-#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
-#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
-#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
-#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */
-#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
-#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
-#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
-
-/* Reserved: 0x00F00000 */
-
-/*
-** CAPI3REF: Device Characteristics
-**
-** The xDeviceCharacteristics method of the [sqlite3_io_methods]
-** object returns an integer which is a vector of these
-** bit values expressing I/O characteristics of the mass storage
-** device that holds the file that the [sqlite3_io_methods]
-** refers to.
-**
-** The SQLITE_IOCAP_ATOMIC property means that all writes of
-** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
-** mean that writes of blocks that are nnn bytes in size and
-** are aligned to an address which is an integer multiple of
-** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
-** that when data is appended to a file, the data is appended
-** first then the size of the file is extended, never the other
-** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
-** information is written to disk in the same order as calls
-** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that
-** after reboot following a crash or power loss, the only bytes in a
-** file that were written at the application level might have changed
-** and that adjacent bytes, even bytes within the same sector are
-** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
-** flag indicates that a file cannot be deleted when open. The
-** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
-** read-only media and cannot be changed even by processes with
-** elevated privileges.
-**
-** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying
-** filesystem supports doing multiple write operations atomically when those
-** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
-** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
-*/
-#define SQLITE_IOCAP_ATOMIC 0x00000001
-#define SQLITE_IOCAP_ATOMIC512 0x00000002
-#define SQLITE_IOCAP_ATOMIC1K 0x00000004
-#define SQLITE_IOCAP_ATOMIC2K 0x00000008
-#define SQLITE_IOCAP_ATOMIC4K 0x00000010
-#define SQLITE_IOCAP_ATOMIC8K 0x00000020
-#define SQLITE_IOCAP_ATOMIC16K 0x00000040
-#define SQLITE_IOCAP_ATOMIC32K 0x00000080
-#define SQLITE_IOCAP_ATOMIC64K 0x00000100
-#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
-#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
-#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
-#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
-#define SQLITE_IOCAP_IMMUTABLE 0x00002000
-#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
-
-/*
-** CAPI3REF: File Locking Levels
-**
-** SQLite uses one of these integer values as the second
-** argument to calls it makes to the xLock() and xUnlock() methods
-** of an [sqlite3_io_methods] object.
-*/
-#define SQLITE_LOCK_NONE 0
-#define SQLITE_LOCK_SHARED 1
-#define SQLITE_LOCK_RESERVED 2
-#define SQLITE_LOCK_PENDING 3
-#define SQLITE_LOCK_EXCLUSIVE 4
-
-/*
-** CAPI3REF: Synchronization Type Flags
-**
-** When SQLite invokes the xSync() method of an
-** [sqlite3_io_methods] object it uses a combination of
-** these integer values as the second argument.
-**
-** When the SQLITE_SYNC_DATAONLY flag is used, it means that the
-** sync operation only needs to flush data to mass storage. Inode
-** information need not be flushed. If the lower four bits of the flag
-** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics.
-** If the lower four bits equal SQLITE_SYNC_FULL, that means
-** to use Mac OS X style fullsync instead of fsync().
-**
-** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags
-** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL
-** settings. The [synchronous pragma] determines when calls to the
-** xSync VFS method occur and applies uniformly across all platforms.
-** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how
-** energetic or rigorous or forceful the sync operations are and
-** only make a difference on Mac OSX for the default SQLite code.
-** (Third-party VFS implementations might also make the distinction
-** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the
-** operating systems natively supported by SQLite, only Mac OSX
-** cares about the difference.)
-*/
-#define SQLITE_SYNC_NORMAL 0x00002
-#define SQLITE_SYNC_FULL 0x00003
-#define SQLITE_SYNC_DATAONLY 0x00010
-
-/*
-** CAPI3REF: OS Interface Open File Handle
-**
-** An [sqlite3_file] object represents an open file in the
-** [sqlite3_vfs | OS interface layer]. Individual OS interface
-** implementations will
-** want to subclass this object by appending additional fields
-** for their own use. The pMethods entry is a pointer to an
-** [sqlite3_io_methods] object that defines methods for performing
-** I/O operations on the open file.
-*/
-typedef struct sqlite3_file sqlite3_file;
-struct sqlite3_file {
- const struct sqlite3_io_methods *pMethods; /* Methods for an open file */
-};
-
-/*
-** CAPI3REF: OS Interface File Virtual Methods Object
-**
-** Every file opened by the [sqlite3_vfs.xOpen] method populates an
-** [sqlite3_file] object (or, more commonly, a subclass of the
-** [sqlite3_file] object) with a pointer to an instance of this object.
-** This object defines the methods used to perform various operations
-** against the open file represented by the [sqlite3_file] object.
-**
-** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
-** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
-** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
-** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
-** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
-** to NULL.
-**
-** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
-** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
-** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
-** flag may be ORed in to indicate that only the data of the file
-** and not its inode needs to be synced.
-**
-** The integer values to xLock() and xUnlock() are one of
-** <ul>
-** <li> [SQLITE_LOCK_NONE],
-** <li> [SQLITE_LOCK_SHARED],
-** <li> [SQLITE_LOCK_RESERVED],
-** <li> [SQLITE_LOCK_PENDING], or
-** <li> [SQLITE_LOCK_EXCLUSIVE].
-** </ul>
-** xLock() increases the lock. xUnlock() decreases the lock.
-** The xCheckReservedLock() method checks whether any database connection,
-** either in this process or in some other process, is holding a RESERVED,
-** PENDING, or EXCLUSIVE lock on the file. It returns true
-** if such a lock exists and false otherwise.
-**
-** The xFileControl() method is a generic interface that allows custom
-** VFS implementations to directly control an open file using the
-** [sqlite3_file_control()] interface. The second "op" argument is an
-** integer opcode. The third argument is a generic pointer intended to
-** point to a structure that may contain arguments or space in which to
-** write return values. Potential uses for xFileControl() might be
-** functions to enable blocking locks with timeouts, to change the
-** locking strategy (for example to use dot-file locks), to inquire
-** about the status of a lock, or to break stale locks. The SQLite
-** core reserves all opcodes less than 100 for its own use.
-** A [file control opcodes | list of opcodes] less than 100 is available.
-** Applications that define a custom xFileControl method should use opcodes
-** greater than 100 to avoid conflicts. VFS implementations should
-** return [SQLITE_NOTFOUND] for file control opcodes that they do not
-** recognize.
-**
-** The xSectorSize() method returns the sector size of the
-** device that underlies the file. The sector size is the
-** minimum write that can be performed without disturbing
-** other bytes in the file. The xDeviceCharacteristics()
-** method returns a bit vector describing behaviors of the
-** underlying device:
-**
-** <ul>
-** <li> [SQLITE_IOCAP_ATOMIC]
-** <li> [SQLITE_IOCAP_ATOMIC512]
-** <li> [SQLITE_IOCAP_ATOMIC1K]
-** <li> [SQLITE_IOCAP_ATOMIC2K]
-** <li> [SQLITE_IOCAP_ATOMIC4K]
-** <li> [SQLITE_IOCAP_ATOMIC8K]
-** <li> [SQLITE_IOCAP_ATOMIC16K]
-** <li> [SQLITE_IOCAP_ATOMIC32K]
-** <li> [SQLITE_IOCAP_ATOMIC64K]
-** <li> [SQLITE_IOCAP_SAFE_APPEND]
-** <li> [SQLITE_IOCAP_SEQUENTIAL]
-** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
-** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
-** <li> [SQLITE_IOCAP_IMMUTABLE]
-** <li> [SQLITE_IOCAP_BATCH_ATOMIC]
-** </ul>
-**
-** The SQLITE_IOCAP_ATOMIC property means that all writes of
-** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
-** mean that writes of blocks that are nnn bytes in size and
-** are aligned to an address which is an integer multiple of
-** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
-** that when data is appended to a file, the data is appended
-** first then the size of the file is extended, never the other
-** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
-** information is written to disk in the same order as calls
-** to xWrite().
-**
-** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill
-** in the unread portions of the buffer with zeros. A VFS that
-** fails to zero-fill short reads might seem to work. However,
-** failure to zero-fill short reads will eventually lead to
-** database corruption.
-*/
-typedef struct sqlite3_io_methods sqlite3_io_methods;
-struct sqlite3_io_methods {
- int iVersion;
- int (*xClose)(sqlite3_file*);
- int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
- int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
- int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
- int (*xSync)(sqlite3_file*, int flags);
- int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
- int (*xLock)(sqlite3_file*, int);
- int (*xUnlock)(sqlite3_file*, int);
- int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
- int (*xFileControl)(sqlite3_file*, int op, void *pArg);
- int (*xSectorSize)(sqlite3_file*);
- int (*xDeviceCharacteristics)(sqlite3_file*);
- /* Methods above are valid for version 1 */
- int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
- int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
- void (*xShmBarrier)(sqlite3_file*);
- int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
- /* Methods above are valid for version 2 */
- int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
- int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
- /* Methods above are valid for version 3 */
- /* Additional methods may be added in future releases */
-};
-
-/*
-** CAPI3REF: Standard File Control Opcodes
-** KEYWORDS: {file control opcodes} {file control opcode}
-**
-** These integer constants are opcodes for the xFileControl method
-** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
-** interface.
-**
-** <ul>
-** <li>[[SQLITE_FCNTL_LOCKSTATE]]
-** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
-** opcode causes the xFileControl method to write the current state of
-** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
-** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
-** into an integer that the pArg argument points to. This capability
-** is used during testing and is only available when the SQLITE_TEST
-** compile-time option is used.
-**
-** <li>[[SQLITE_FCNTL_SIZE_HINT]]
-** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
-** layer a hint of how large the database file will grow to be during the
-** current transaction. This hint is not guaranteed to be accurate but it
-** is often close. The underlying VFS might choose to preallocate database
-** file space based on this hint in order to help writes to the database
-** file run faster.
-**
-** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
-** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
-** extends and truncates the database file in chunks of a size specified
-** by the user. The fourth argument to [sqlite3_file_control()] should
-** point to an integer (type int) containing the new chunk-size to use
-** for the nominated database. Allocating database file space in large
-** chunks (say 1MB at a time), may reduce file-system fragmentation and
-** improve performance on some systems.
-**
-** <li>[[SQLITE_FCNTL_FILE_POINTER]]
-** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
-** to the [sqlite3_file] object associated with a particular database
-** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER].
-**
-** <li>[[SQLITE_FCNTL_JOURNAL_POINTER]]
-** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer
-** to the [sqlite3_file] object associated with the journal file (either
-** the [rollback journal] or the [write-ahead log]) for a particular database
-** connection. See also [SQLITE_FCNTL_FILE_POINTER].
-**
-** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
-** No longer in use.
-**
-** <li>[[SQLITE_FCNTL_SYNC]]
-** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
-** sent to the VFS immediately before the xSync method is invoked on a
-** database file descriptor. Or, if the xSync method is not invoked
-** because the user has configured SQLite with
-** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place
-** of the xSync method. In most cases, the pointer argument passed with
-** this file-control is NULL. However, if the database file is being synced
-** as part of a multi-database commit, the argument points to a nul-terminated
-** string containing the transactions master-journal file name. VFSes that
-** do not need this signal should silently ignore this opcode. Applications
-** should not call [sqlite3_file_control()] with this opcode as doing so may
-** disrupt the operation of the specialized VFSes that do require it.
-**
-** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
-** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
-** and sent to the VFS after a transaction has been committed immediately
-** but before the database is unlocked. VFSes that do not need this signal
-** should silently ignore this opcode. Applications should not call
-** [sqlite3_file_control()] with this opcode as doing so may disrupt the
-** operation of the specialized VFSes that do require it.
-**
-** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
-** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
-** retry counts and intervals for certain disk I/O operations for the
-** windows [VFS] in order to provide robustness in the presence of
-** anti-virus programs. By default, the windows VFS will retry file read,
-** file write, and file delete operations up to 10 times, with a delay
-** of 25 milliseconds before the first retry and with the delay increasing
-** by an additional 25 milliseconds with each subsequent retry. This
-** opcode allows these two values (10 retries and 25 milliseconds of delay)
-** to be adjusted. The values are changed for all database connections
-** within the same process. The argument is a pointer to an array of two
-** integers where the first integer is the new retry count and the second
-** integer is the delay. If either integer is negative, then the setting
-** is not changed but instead the prior value of that setting is written
-** into the array entry, allowing the current retry settings to be
-** interrogated. The zDbName parameter is ignored.
-**
-** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
-** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
-** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary
-** write ahead log and shared memory files used for transaction control
-** are automatically deleted when the latest connection to the database
-** closes. Setting persistent WAL mode causes those files to persist after
-** close. Persisting the files is useful when other processes that do not
-** have write permission on the directory containing the database file want
-** to read the database file, as the WAL and shared memory files must exist
-** in order for the database to be readable. The fourth parameter to
-** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
-** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
-** WAL mode. If the integer is -1, then it is overwritten with the current
-** WAL persistence setting.
-**
-** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
-** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
-** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
-** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
-** xDeviceCharacteristics methods. The fourth parameter to
-** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
-** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
-** mode. If the integer is -1, then it is overwritten with the current
-** zero-damage mode setting.
-**
-** <li>[[SQLITE_FCNTL_OVERWRITE]]
-** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
-** a write transaction to indicate that, unless it is rolled back for some
-** reason, the entire database file will be overwritten by the current
-** transaction. This is used by VACUUM operations.
-**
-** <li>[[SQLITE_FCNTL_VFSNAME]]
-** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
-** all [VFSes] in the VFS stack. The names are of all VFS shims and the
-** final bottom-level VFS are written into memory obtained from
-** [sqlite3_malloc()] and the result is stored in the char* variable
-** that the fourth parameter of [sqlite3_file_control()] points to.
-** The caller is responsible for freeing the memory when done. As with
-** all file-control actions, there is no guarantee that this will actually
-** do anything. Callers should initialize the char* variable to a NULL
-** pointer in case this file-control is not implemented. This file-control
-** is intended for diagnostic use only.
-**
-** <li>[[SQLITE_FCNTL_VFS_POINTER]]
-** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level
-** [VFSes] currently in use. ^(The argument X in
-** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be
-** of type "[sqlite3_vfs] **". This opcodes will set *X
-** to a pointer to the top-level VFS.)^
-** ^When there are multiple VFS shims in the stack, this opcode finds the
-** upper-most shim only.
-**
-** <li>[[SQLITE_FCNTL_PRAGMA]]
-** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
-** file control is sent to the open [sqlite3_file] object corresponding
-** to the database file to which the pragma statement refers. ^The argument
-** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
-** pointers to strings (char**) in which the second element of the array
-** is the name of the pragma and the third element is the argument to the
-** pragma or NULL if the pragma has no argument. ^The handler for an
-** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
-** of the char** argument point to a string obtained from [sqlite3_mprintf()]
-** or the equivalent and that string will become the result of the pragma or
-** the error message if the pragma fails. ^If the
-** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
-** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
-** file control returns [SQLITE_OK], then the parser assumes that the
-** VFS has handled the PRAGMA itself and the parser generates a no-op
-** prepared statement if result string is NULL, or that returns a copy
-** of the result string if the string is non-NULL.
-** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
-** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
-** that the VFS encountered an error while handling the [PRAGMA] and the
-** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
-** file control occurs at the beginning of pragma statement analysis and so
-** it is able to override built-in [PRAGMA] statements.
-**
-** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
-** ^The [SQLITE_FCNTL_BUSYHANDLER]
-** file-control may be invoked by SQLite on the database file handle
-** shortly after it is opened in order to provide a custom VFS with access
-** to the connections busy-handler callback. The argument is of type (void **)
-** - an array of two (void *) values. The first (void *) actually points
-** to a function of type (int (*)(void *)). In order to invoke the connections
-** busy-handler, this function should be invoked with the second (void *) in
-** the array as the only argument. If it returns non-zero, then the operation
-** should be retried. If it returns zero, the custom VFS should abandon the
-** current operation.
-**
-** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
-** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
-** to have SQLite generate a
-** temporary filename using the same algorithm that is followed to generate
-** temporary filenames for TEMP tables and other internal uses. The
-** argument should be a char** which will be filled with the filename
-** written into memory obtained from [sqlite3_malloc()]. The caller should
-** invoke [sqlite3_free()] on the result to avoid a memory leak.
-**
-** <li>[[SQLITE_FCNTL_MMAP_SIZE]]
-** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the
-** maximum number of bytes that will be used for memory-mapped I/O.
-** The argument is a pointer to a value of type sqlite3_int64 that
-** is an advisory maximum number of bytes in the file to memory map. The
-** pointer is overwritten with the old value. The limit is not changed if
-** the value originally pointed to is negative, and so the current limit
-** can be queried by passing in a pointer to a negative number. This
-** file-control is used internally to implement [PRAGMA mmap_size].
-**
-** <li>[[SQLITE_FCNTL_TRACE]]
-** The [SQLITE_FCNTL_TRACE] file control provides advisory information
-** to the VFS about what the higher layers of the SQLite stack are doing.
-** This file control is used by some VFS activity tracing [shims].
-** The argument is a zero-terminated string. Higher layers in the
-** SQLite stack may generate instances of this file control if
-** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
-**
-** <li>[[SQLITE_FCNTL_HAS_MOVED]]
-** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
-** pointer to an integer and it writes a boolean into that integer depending
-** on whether or not the file has been renamed, moved, or deleted since it
-** was first opened.
-**
-** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]]
-** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
-** underlying native file handle associated with a file handle. This file
-** control interprets its argument as a pointer to a native file handle and
-** writes the resulting value there.
-**
-** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
-** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
-** opcode causes the xFileControl method to swap the file handle with the one
-** pointed to by the pArg argument. This capability is used during testing
-** and only needs to be supported when SQLITE_TEST is defined.
-**
-** <li>[[SQLITE_FCNTL_WAL_BLOCK]]
-** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
-** be advantageous to block on the next WAL lock if the lock is not immediately
-** available. The WAL subsystem issues this signal during rare
-** circumstances in order to fix a problem with priority inversion.
-** Applications should <em>not</em> use this file-control.
-**
-** <li>[[SQLITE_FCNTL_ZIPVFS]]
-** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
-** VFS should return SQLITE_NOTFOUND for this opcode.
-**
-** <li>[[SQLITE_FCNTL_RBU]]
-** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
-** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for
-** this opcode.
-**
-** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]]
-** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then
-** the file descriptor is placed in "batch write mode", which
-** means all subsequent write operations will be deferred and done
-** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems
-** that do not support batch atomic writes will return SQLITE_NOTFOUND.
-** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to
-** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or
-** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make
-** no VFS interface calls on the same [sqlite3_file] file descriptor
-** except for calls to the xWrite method and the xFileControl method
-** with [SQLITE_FCNTL_SIZE_HINT].
-**
-** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]]
-** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write
-** operations since the previous successful call to
-** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically.
-** This file control returns [SQLITE_OK] if and only if the writes were
-** all performed successfully and have been committed to persistent storage.
-** ^Regardless of whether or not it is successful, this file control takes
-** the file descriptor out of batch write mode so that all subsequent
-** write operations are independent.
-** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without
-** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
-**
-** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]]
-** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write
-** operations since the previous successful call to
-** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back.
-** ^This file control takes the file descriptor out of batch write mode
-** so that all subsequent write operations are independent.
-** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
-** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
-**
-** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
-** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
-** a file lock using the xLock or xShmLock methods of the VFS to wait
-** for up to M milliseconds before failing, where M is the single
-** unsigned integer parameter.
-** </ul>
-*/
-#define SQLITE_FCNTL_LOCKSTATE 1
-#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
-#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3
-#define SQLITE_FCNTL_LAST_ERRNO 4
-#define SQLITE_FCNTL_SIZE_HINT 5
-#define SQLITE_FCNTL_CHUNK_SIZE 6
-#define SQLITE_FCNTL_FILE_POINTER 7
-#define SQLITE_FCNTL_SYNC_OMITTED 8
-#define SQLITE_FCNTL_WIN32_AV_RETRY 9
-#define SQLITE_FCNTL_PERSIST_WAL 10
-#define SQLITE_FCNTL_OVERWRITE 11
-#define SQLITE_FCNTL_VFSNAME 12
-#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
-#define SQLITE_FCNTL_PRAGMA 14
-#define SQLITE_FCNTL_BUSYHANDLER 15
-#define SQLITE_FCNTL_TEMPFILENAME 16
-#define SQLITE_FCNTL_MMAP_SIZE 18
-#define SQLITE_FCNTL_TRACE 19
-#define SQLITE_FCNTL_HAS_MOVED 20
-#define SQLITE_FCNTL_SYNC 21
-#define SQLITE_FCNTL_COMMIT_PHASETWO 22
-#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
-#define SQLITE_FCNTL_WAL_BLOCK 24
-#define SQLITE_FCNTL_ZIPVFS 25
-#define SQLITE_FCNTL_RBU 26
-#define SQLITE_FCNTL_VFS_POINTER 27
-#define SQLITE_FCNTL_JOURNAL_POINTER 28
-#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
-#define SQLITE_FCNTL_PDB 30
-#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31
-#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
-#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
-#define SQLITE_FCNTL_LOCK_TIMEOUT 34
-
-/* deprecated names */
-#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
-#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
-#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
-
-
-/*
-** CAPI3REF: Mutex Handle
-**
-** The mutex module within SQLite defines [sqlite3_mutex] to be an
-** abstract type for a mutex object. The SQLite core never looks
-** at the internal representation of an [sqlite3_mutex]. It only
-** deals with pointers to the [sqlite3_mutex] object.
-**
-** Mutexes are created using [sqlite3_mutex_alloc()].
-*/
-typedef struct sqlite3_mutex sqlite3_mutex;
-
-/*
-** CAPI3REF: Loadable Extension Thunk
-**
-** A pointer to the opaque sqlite3_api_routines structure is passed as
-** the third parameter to entry points of [loadable extensions]. This
-** structure must be typedefed in order to work around compiler warnings
-** on some platforms.
-*/
-typedef struct sqlite3_api_routines sqlite3_api_routines;
-
-/*
-** CAPI3REF: OS Interface Object
-**
-** An instance of the sqlite3_vfs object defines the interface between
-** the SQLite core and the underlying operating system. The "vfs"
-** in the name of the object stands for "virtual file system". See
-** the [VFS | VFS documentation] for further information.
-**
-** The VFS interface is sometimes extended by adding new methods onto
-** the end. Each time such an extension occurs, the iVersion field
-** is incremented. The iVersion value started out as 1 in
-** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2
-** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased
-** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
-** may be appended to the sqlite3_vfs object and the iVersion value
-** may increase again in future versions of SQLite.
-** Note that the structure
-** of the sqlite3_vfs object changes in the transition from
-** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
-** and yet the iVersion field was not modified.
-**
-** The szOsFile field is the size of the subclassed [sqlite3_file]
-** structure used by this VFS. mxPathname is the maximum length of
-** a pathname in this VFS.
-**
-** Registered sqlite3_vfs objects are kept on a linked list formed by
-** the pNext pointer. The [sqlite3_vfs_register()]
-** and [sqlite3_vfs_unregister()] interfaces manage this list
-** in a thread-safe way. The [sqlite3_vfs_find()] interface
-** searches the list. Neither the application code nor the VFS
-** implementation should use the pNext pointer.
-**
-** The pNext field is the only field in the sqlite3_vfs
-** structure that SQLite will ever modify. SQLite will only access
-** or modify this field while holding a particular static mutex.
-** The application should never modify anything within the sqlite3_vfs
-** object once the object has been registered.
-**
-** The zName field holds the name of the VFS module. The name must
-** be unique across all VFS modules.
-**
-** [[sqlite3_vfs.xOpen]]
-** ^SQLite guarantees that the zFilename parameter to xOpen
-** is either a NULL pointer or string obtained
-** from xFullPathname() with an optional suffix added.
-** ^If a suffix is added to the zFilename parameter, it will
-** consist of a single "-" character followed by no more than
-** 11 alphanumeric and/or "-" characters.
-** ^SQLite further guarantees that
-** the string will be valid and unchanged until xClose() is
-** called. Because of the previous sentence,
-** the [sqlite3_file] can safely store a pointer to the
-** filename if it needs to remember the filename for some reason.
-** If the zFilename parameter to xOpen is a NULL pointer then xOpen
-** must invent its own temporary name for the file. ^Whenever the
-** xFilename parameter is NULL it will also be the case that the
-** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
-**
-** The flags argument to xOpen() includes all bits set in
-** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
-** or [sqlite3_open16()] is used, then flags includes at least
-** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
-** If xOpen() opens a file read-only then it sets *pOutFlags to
-** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
-**
-** ^(SQLite will also add one of the following flags to the xOpen()
-** call, depending on the object being opened:
-**
-** <ul>
-** <li> [SQLITE_OPEN_MAIN_DB]
-** <li> [SQLITE_OPEN_MAIN_JOURNAL]
-** <li> [SQLITE_OPEN_TEMP_DB]
-** <li> [SQLITE_OPEN_TEMP_JOURNAL]
-** <li> [SQLITE_OPEN_TRANSIENT_DB]
-** <li> [SQLITE_OPEN_SUBJOURNAL]
-** <li> [SQLITE_OPEN_MASTER_JOURNAL]
-** <li> [SQLITE_OPEN_WAL]
-** </ul>)^
-**
-** The file I/O implementation can use the object type flags to
-** change the way it deals with files. For example, an application
-** that does not care about crash recovery or rollback might make
-** the open of a journal file a no-op. Writes to this journal would
-** also be no-ops, and any attempt to read the journal would return
-** SQLITE_IOERR. Or the implementation might recognize that a database
-** file will be doing page-aligned sector reads and writes in a random
-** order and set up its I/O subsystem accordingly.
-**
-** SQLite might also add one of the following flags to the xOpen method:
-**
-** <ul>
-** <li> [SQLITE_OPEN_DELETEONCLOSE]
-** <li> [SQLITE_OPEN_EXCLUSIVE]
-** </ul>
-**
-** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
-** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE]
-** will be set for TEMP databases and their journals, transient
-** databases, and subjournals.
-**
-** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
-** with the [SQLITE_OPEN_CREATE] flag, which are both directly
-** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
-** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
-** SQLITE_OPEN_CREATE, is used to indicate that file should always
-** be created, and that it is an error if it already exists.
-** It is <i>not</i> used to indicate the file should be opened
-** for exclusive access.
-**
-** ^At least szOsFile bytes of memory are allocated by SQLite
-** to hold the [sqlite3_file] structure passed as the third
-** argument to xOpen. The xOpen method does not have to
-** allocate the structure; it should just fill it in. Note that
-** the xOpen method must set the sqlite3_file.pMethods to either
-** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
-** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
-** element will be valid after xOpen returns regardless of the success
-** or failure of the xOpen call.
-**
-** [[sqlite3_vfs.xAccess]]
-** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
-** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
-** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
-** to test whether a file is at least readable. The file can be a
-** directory.
-**
-** ^SQLite will always allocate at least mxPathname+1 bytes for the
-** output buffer xFullPathname. The exact size of the output buffer
-** is also passed as a parameter to both methods. If the output buffer
-** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is
-** handled as a fatal error by SQLite, vfs implementations should endeavor
-** to prevent this by setting mxPathname to a sufficiently large value.
-**
-** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
-** interfaces are not strictly a part of the filesystem, but they are
-** included in the VFS structure for completeness.
-** The xRandomness() function attempts to return nBytes bytes
-** of good-quality randomness into zOut. The return value is
-** the actual number of bytes of randomness obtained.
-** The xSleep() method causes the calling thread to sleep for at
-** least the number of microseconds given. ^The xCurrentTime()
-** method returns a Julian Day Number for the current date and time as
-** a floating point value.
-** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
-** Day Number multiplied by 86400000 (the number of milliseconds in
-** a 24-hour day).
-** ^SQLite will use the xCurrentTimeInt64() method to get the current
-** date and time if that method is available (if iVersion is 2 or
-** greater and the function pointer is not NULL) and will fall back
-** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
-**
-** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
-** are not used by the SQLite core. These optional interfaces are provided
-** by some VFSes to facilitate testing of the VFS code. By overriding
-** system calls with functions under its control, a test program can
-** simulate faults and error conditions that would otherwise be difficult
-** or impossible to induce. The set of system calls that can be overridden
-** varies from one VFS to another, and from one version of the same VFS to the
-** next. Applications that use these interfaces must be prepared for any
-** or all of these interfaces to be NULL or for their behavior to change
-** from one release to the next. Applications must not attempt to access
-** any of these methods if the iVersion of the VFS is less than 3.
-*/
-typedef struct sqlite3_vfs sqlite3_vfs;
-typedef void (*sqlite3_syscall_ptr)(void);
-struct sqlite3_vfs {
- int iVersion; /* Structure version number (currently 3) */
- int szOsFile; /* Size of subclassed sqlite3_file */
- int mxPathname; /* Maximum file pathname length */
- sqlite3_vfs *pNext; /* Next registered VFS */
- const char *zName; /* Name of this virtual file system */
- void *pAppData; /* Pointer to application-specific data */
- int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
- int flags, int *pOutFlags);
- int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
- int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
- int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
- void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
- void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
- void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
- void (*xDlClose)(sqlite3_vfs*, void*);
- int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
- int (*xSleep)(sqlite3_vfs*, int microseconds);
- int (*xCurrentTime)(sqlite3_vfs*, double*);
- int (*xGetLastError)(sqlite3_vfs*, int, char *);
- /*
- ** The methods above are in version 1 of the sqlite_vfs object
- ** definition. Those that follow are added in version 2 or later
- */
- int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
- /*
- ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
- ** Those below are for version 3 and greater.
- */
- int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
- sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
- const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
- /*
- ** The methods above are in versions 1 through 3 of the sqlite_vfs object.
- ** New fields may be appended in future versions. The iVersion
- ** value will increment whenever this happens.
- */
-};
-
-/*
-** CAPI3REF: Flags for the xAccess VFS method
-**
-** These integer constants can be used as the third parameter to
-** the xAccess method of an [sqlite3_vfs] object. They determine
-** what kind of permissions the xAccess method is looking for.
-** With SQLITE_ACCESS_EXISTS, the xAccess method
-** simply checks whether the file exists.
-** With SQLITE_ACCESS_READWRITE, the xAccess method
-** checks whether the named directory is both readable and writable
-** (in other words, if files can be added, removed, and renamed within
-** the directory).
-** The SQLITE_ACCESS_READWRITE constant is currently used only by the
-** [temp_store_directory pragma], though this could change in a future
-** release of SQLite.
-** With SQLITE_ACCESS_READ, the xAccess method
-** checks whether the file is readable. The SQLITE_ACCESS_READ constant is
-** currently unused, though it might be used in a future release of
-** SQLite.
-*/
-#define SQLITE_ACCESS_EXISTS 0
-#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */
-#define SQLITE_ACCESS_READ 2 /* Unused */
-
-/*
-** CAPI3REF: Flags for the xShmLock VFS method
-**
-** These integer constants define the various locking operations
-** allowed by the xShmLock method of [sqlite3_io_methods]. The
-** following are the only legal combinations of flags to the
-** xShmLock method:
-**
-** <ul>
-** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED
-** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE
-** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED
-** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE
-** </ul>
-**
-** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
-** was given on the corresponding lock.
-**
-** The xShmLock method can transition between unlocked and SHARED or
-** between unlocked and EXCLUSIVE. It cannot transition between SHARED
-** and EXCLUSIVE.
-*/
-#define SQLITE_SHM_UNLOCK 1
-#define SQLITE_SHM_LOCK 2
-#define SQLITE_SHM_SHARED 4
-#define SQLITE_SHM_EXCLUSIVE 8
-
-/*
-** CAPI3REF: Maximum xShmLock index
-**
-** The xShmLock method on [sqlite3_io_methods] may use values
-** between 0 and this upper bound as its "offset" argument.
-** The SQLite core will never attempt to acquire or release a
-** lock outside of this range
-*/
-#define SQLITE_SHM_NLOCK 8
-
-
-/*
-** CAPI3REF: Initialize The SQLite Library
-**
-** ^The sqlite3_initialize() routine initializes the
-** SQLite library. ^The sqlite3_shutdown() routine
-** deallocates any resources that were allocated by sqlite3_initialize().
-** These routines are designed to aid in process initialization and
-** shutdown on embedded systems. Workstation applications using
-** SQLite normally do not need to invoke either of these routines.
-**
-** A call to sqlite3_initialize() is an "effective" call if it is
-** the first time sqlite3_initialize() is invoked during the lifetime of
-** the process, or if it is the first time sqlite3_initialize() is invoked
-** following a call to sqlite3_shutdown(). ^(Only an effective call
-** of sqlite3_initialize() does any initialization. All other calls
-** are harmless no-ops.)^
-**
-** A call to sqlite3_shutdown() is an "effective" call if it is the first
-** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only
-** an effective call to sqlite3_shutdown() does any deinitialization.
-** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^
-**
-** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown()
-** is not. The sqlite3_shutdown() interface must only be called from a
-** single thread. All open [database connections] must be closed and all
-** other SQLite resources must be deallocated prior to invoking
-** sqlite3_shutdown().
-**
-** Among other things, ^sqlite3_initialize() will invoke
-** sqlite3_os_init(). Similarly, ^sqlite3_shutdown()
-** will invoke sqlite3_os_end().
-**
-** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success.
-** ^If for some reason, sqlite3_initialize() is unable to initialize
-** the library (perhaps it is unable to allocate a needed resource such
-** as a mutex) it returns an [error code] other than [SQLITE_OK].
-**
-** ^The sqlite3_initialize() routine is called internally by many other
-** SQLite interfaces so that an application usually does not need to
-** invoke sqlite3_initialize() directly. For example, [sqlite3_open()]
-** calls sqlite3_initialize() so the SQLite library will be automatically
-** initialized when [sqlite3_open()] is called if it has not be initialized
-** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT]
-** compile-time option, then the automatic calls to sqlite3_initialize()
-** are omitted and the application must call sqlite3_initialize() directly
-** prior to using any other SQLite interface. For maximum portability,
-** it is recommended that applications always invoke sqlite3_initialize()
-** directly prior to using any other SQLite interface. Future releases
-** of SQLite may require this. In other words, the behavior exhibited
-** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the
-** default behavior in some future release of SQLite.
-**
-** The sqlite3_os_init() routine does operating-system specific
-** initialization of the SQLite library. The sqlite3_os_end()
-** routine undoes the effect of sqlite3_os_init(). Typical tasks
-** performed by these routines include allocation or deallocation
-** of static resources, initialization of global variables,
-** setting up a default [sqlite3_vfs] module, or setting up
-** a default configuration using [sqlite3_config()].
-**
-** The application should never invoke either sqlite3_os_init()
-** or sqlite3_os_end() directly. The application should only invoke
-** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init()
-** interface is called automatically by sqlite3_initialize() and
-** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate
-** implementations for sqlite3_os_init() and sqlite3_os_end()
-** are built into SQLite when it is compiled for Unix, Windows, or OS/2.
-** When [custom builds | built for other platforms]
-** (using the [SQLITE_OS_OTHER=1] compile-time
-** option) the application must supply a suitable implementation for
-** sqlite3_os_init() and sqlite3_os_end(). An application-supplied
-** implementation of sqlite3_os_init() or sqlite3_os_end()
-** must return [SQLITE_OK] on success and some other [error code] upon
-** failure.
-*/
-int sqlite3_initialize(void);
-int sqlite3_shutdown(void);
-int sqlite3_os_init(void);
-int sqlite3_os_end(void);
-
-/*
-** CAPI3REF: Configuring The SQLite Library
-**
-** The sqlite3_config() interface is used to make global configuration
-** changes to SQLite in order to tune SQLite to the specific needs of
-** the application. The default configuration is recommended for most
-** applications and so this routine is usually not necessary. It is
-** provided to support rare applications with unusual needs.
-**
-** <b>The sqlite3_config() interface is not threadsafe. The application
-** must ensure that no other SQLite interfaces are invoked by other
-** threads while sqlite3_config() is running.</b>
-**
-** The sqlite3_config() interface
-** may only be invoked prior to library initialization using
-** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
-** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
-** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
-** Note, however, that ^sqlite3_config() can be called as part of the
-** implementation of an application-defined [sqlite3_os_init()].
-**
-** The first argument to sqlite3_config() is an integer
-** [configuration option] that determines
-** what property of SQLite is to be configured. Subsequent arguments
-** vary depending on the [configuration option]
-** in the first argument.
-**
-** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
-** ^If the option is unknown or SQLite is unable to set the option
-** then this routine returns a non-zero [error code].
-*/
-int sqlite3_config(int, ...);
-
-/*
-** CAPI3REF: Configure database connections
-** METHOD: sqlite3
-**
-** The sqlite3_db_config() interface is used to make configuration
-** changes to a [database connection]. The interface is similar to
-** [sqlite3_config()] except that the changes apply to a single
-** [database connection] (specified in the first argument).
-**
-** The second argument to sqlite3_db_config(D,V,...) is the
-** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code
-** that indicates what aspect of the [database connection] is being configured.
-** Subsequent arguments vary depending on the configuration verb.
-**
-** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
-** the call is considered successful.
-*/
-int sqlite3_db_config(sqlite3*, int op, ...);
-
-/*
-** CAPI3REF: Memory Allocation Routines
-**
-** An instance of this object defines the interface between SQLite
-** and low-level memory allocation routines.
-**
-** This object is used in only one place in the SQLite interface.
-** A pointer to an instance of this object is the argument to
-** [sqlite3_config()] when the configuration option is
-** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
-** By creating an instance of this object
-** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC])
-** during configuration, an application can specify an alternative
-** memory allocation subsystem for SQLite to use for all of its
-** dynamic memory needs.
-**
-** Note that SQLite comes with several [built-in memory allocators]
-** that are perfectly adequate for the overwhelming majority of applications
-** and that this object is only useful to a tiny minority of applications
-** with specialized memory allocation requirements. This object is
-** also used during testing of SQLite in order to specify an alternative
-** memory allocator that simulates memory out-of-memory conditions in
-** order to verify that SQLite recovers gracefully from such
-** conditions.
-**
-** The xMalloc, xRealloc, and xFree methods must work like the
-** malloc(), realloc() and free() functions from the standard C library.
-** ^SQLite guarantees that the second argument to
-** xRealloc is always a value returned by a prior call to xRoundup.
-**
-** xSize should return the allocated size of a memory allocation
-** previously obtained from xMalloc or xRealloc. The allocated size
-** is always at least as big as the requested size but may be larger.
-**
-** The xRoundup method returns what would be the allocated size of
-** a memory allocation given a particular requested size. Most memory
-** allocators round up memory allocations at least to the next multiple
-** of 8. Some allocators round up to a larger multiple or to a power of 2.
-** Every memory allocation request coming in through [sqlite3_malloc()]
-** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
-** that causes the corresponding memory allocation to fail.
-**
-** The xInit method initializes the memory allocator. For example,
-** it might allocate any require mutexes or initialize internal data
-** structures. The xShutdown method is invoked (indirectly) by
-** [sqlite3_shutdown()] and should deallocate any resources acquired
-** by xInit. The pAppData pointer is used as the only parameter to
-** xInit and xShutdown.
-**
-** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes
-** the xInit method, so the xInit method need not be threadsafe. The
-** xShutdown method is only called from [sqlite3_shutdown()] so it does
-** not need to be threadsafe either. For all other methods, SQLite
-** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the
-** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which
-** it is by default) and so the methods are automatically serialized.
-** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other
-** methods must be threadsafe or else make their own arrangements for
-** serialization.
-**
-** SQLite will never invoke xInit() more than once without an intervening
-** call to xShutdown().
-*/
-typedef struct sqlite3_mem_methods sqlite3_mem_methods;
-struct sqlite3_mem_methods {
- void *(*xMalloc)(int); /* Memory allocation function */
- void (*xFree)(void*); /* Free a prior allocation */
- void *(*xRealloc)(void*,int); /* Resize an allocation */
- int (*xSize)(void*); /* Return the size of an allocation */
- int (*xRoundup)(int); /* Round up request size to allocation size */
- int (*xInit)(void*); /* Initialize the memory allocator */
- void (*xShutdown)(void*); /* Deinitialize the memory allocator */
- void *pAppData; /* Argument to xInit() and xShutdown() */
-};
-
-/*
-** CAPI3REF: Configuration Options
-** KEYWORDS: {configuration option}
-**
-** These constants are the available integer configuration options that
-** can be passed as the first argument to the [sqlite3_config()] interface.
-**
-** New configuration options may be added in future releases of SQLite.
-** Existing configuration options might be discontinued. Applications
-** should check the return code from [sqlite3_config()] to make sure that
-** the call worked. The [sqlite3_config()] interface will return a
-** non-zero [error code] if a discontinued or unsupported configuration option
-** is invoked.
-**
-** <dl>
-** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
-** <dd>There are no arguments to this option. ^This option sets the
-** [threading mode] to Single-thread. In other words, it disables
-** all mutexing and puts SQLite into a mode where it can only be used
-** by a single thread. ^If SQLite is compiled with
-** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
-** it is not possible to change the [threading mode] from its default
-** value of Single-thread and so [sqlite3_config()] will return
-** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
-** configuration option.</dd>
-**
-** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
-** <dd>There are no arguments to this option. ^This option sets the
-** [threading mode] to Multi-thread. In other words, it disables
-** mutexing on [database connection] and [prepared statement] objects.
-** The application is responsible for serializing access to
-** [database connections] and [prepared statements]. But other mutexes
-** are enabled so that SQLite will be safe to use in a multi-threaded
-** environment as long as no two threads attempt to use the same
-** [database connection] at the same time. ^If SQLite is compiled with
-** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
-** it is not possible to set the Multi-thread [threading mode] and
-** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
-** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
-**
-** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
-** <dd>There are no arguments to this option. ^This option sets the
-** [threading mode] to Serialized. In other words, this option enables
-** all mutexes including the recursive
-** mutexes on [database connection] and [prepared statement] objects.
-** In this mode (which is the default when SQLite is compiled with
-** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access
-** to [database connections] and [prepared statements] so that the
-** application is free to use the same [database connection] or the
-** same [prepared statement] in different threads at the same time.
-** ^If SQLite is compiled with
-** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
-** it is not possible to set the Serialized [threading mode] and
-** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
-** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
-**
-** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
-** <dd> ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is
-** a pointer to an instance of the [sqlite3_mem_methods] structure.
-** The argument specifies
-** alternative low-level memory allocation routines to be used in place of
-** the memory allocation routines built into SQLite.)^ ^SQLite makes
-** its own private copy of the content of the [sqlite3_mem_methods] structure
-** before the [sqlite3_config()] call returns.</dd>
-**
-** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
-** <dd> ^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which
-** is a pointer to an instance of the [sqlite3_mem_methods] structure.
-** The [sqlite3_mem_methods]
-** structure is filled with the currently defined memory allocation routines.)^
-** This option can be used to overload the default memory allocation
-** routines with a wrapper that simulations memory allocation failure or
-** tracks memory usage, for example. </dd>
-**
-** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt>
-** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of
-** type int, interpreted as a boolean, which if true provides a hint to
-** SQLite that it should avoid large memory allocations if possible.
-** SQLite will run faster if it is free to make large memory allocations,
-** but some application might prefer to run slower in exchange for
-** guarantees about memory fragmentation that are possible if large
-** allocations are avoided. This hint is normally off.
-** </dd>
-**
-** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
-** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
-** interpreted as a boolean, which enables or disables the collection of
-** memory allocation statistics. ^(When memory allocation statistics are
-** disabled, the following SQLite interfaces become non-operational:
-** <ul>
-** <li> [sqlite3_memory_used()]
-** <li> [sqlite3_memory_highwater()]
-** <li> [sqlite3_soft_heap_limit64()]
-** <li> [sqlite3_status64()]
-** </ul>)^
-** ^Memory allocation statistics are enabled by default unless SQLite is
-** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
-** allocation statistics are disabled by default.
-** </dd>
-**
-** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
-** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used.
-** </dd>
-**
-** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
-** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
-** that SQLite can use for the database page cache with the default page
-** cache implementation.
-** This configuration option is a no-op if an application-define page
-** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
-** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
-** 8-byte aligned memory (pMem), the size of each page cache line (sz),
-** and the number of cache lines (N).
-** The sz argument should be the size of the largest database page
-** (a power of two between 512 and 65536) plus some extra bytes for each
-** page header. ^The number of extra bytes needed by the page header
-** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ].
-** ^It is harmless, apart from the wasted memory,
-** for the sz parameter to be larger than necessary. The pMem
-** argument must be either a NULL pointer or a pointer to an 8-byte
-** aligned block of memory of at least sz*N bytes, otherwise
-** subsequent behavior is undefined.
-** ^When pMem is not NULL, SQLite will strive to use the memory provided
-** to satisfy page cache needs, falling back to [sqlite3_malloc()] if
-** a page cache line is larger than sz bytes or if all of the pMem buffer
-** is exhausted.
-** ^If pMem is NULL and N is non-zero, then each database connection
-** does an initial bulk allocation for page cache memory
-** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or
-** of -1024*N bytes if N is negative, . ^If additional
-** page cache memory is needed beyond what is provided by the initial
-** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
-** additional cache line. </dd>
-**
-** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
-** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
-** that SQLite will use for all of its dynamic memory allocation needs
-** beyond those provided for by [SQLITE_CONFIG_PAGECACHE].
-** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled
-** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns
-** [SQLITE_ERROR] if invoked otherwise.
-** ^There are three arguments to SQLITE_CONFIG_HEAP:
-** An 8-byte aligned pointer to the memory,
-** the number of bytes in the memory buffer, and the minimum allocation size.
-** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts
-** to using its default memory allocator (the system malloc() implementation),
-** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the
-** memory pointer is not NULL then the alternative memory
-** allocator is engaged to handle all of SQLites memory allocation needs.
-** The first pointer (the memory pointer) must be aligned to an 8-byte
-** boundary or subsequent behavior of SQLite will be undefined.
-** The minimum allocation size is capped at 2**12. Reasonable values
-** for the minimum allocation size are 2**5 through 2**8.</dd>
-**
-** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
-** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a
-** pointer to an instance of the [sqlite3_mutex_methods] structure.
-** The argument specifies alternative low-level mutex routines to be used
-** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of
-** the content of the [sqlite3_mutex_methods] structure before the call to
-** [sqlite3_config()] returns. ^If SQLite is compiled with
-** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
-** the entire mutexing subsystem is omitted from the build and hence calls to
-** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
-** return [SQLITE_ERROR].</dd>
-**
-** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
-** <dd> ^(The SQLITE_CONFIG_GETMUTEX option takes a single argument which
-** is a pointer to an instance of the [sqlite3_mutex_methods] structure. The
-** [sqlite3_mutex_methods]
-** structure is filled with the currently defined mutex routines.)^
-** This option can be used to overload the default mutex allocation
-** routines with a wrapper used to track mutex usage for performance
-** profiling or testing, for example. ^If SQLite is compiled with
-** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
-** the entire mutexing subsystem is omitted from the build and hence calls to
-** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
-** return [SQLITE_ERROR].</dd>
-**
-** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
-** <dd> ^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine
-** the default size of lookaside memory on each [database connection].
-** The first argument is the
-** size of each lookaside buffer slot and the second is the number of
-** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE
-** sets the <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
-** option to [sqlite3_db_config()] can be used to change the lookaside
-** configuration on individual connections.)^ </dd>
-**
-** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
-** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is
-** a pointer to an [sqlite3_pcache_methods2] object. This object specifies
-** the interface to a custom page cache implementation.)^
-** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd>
-**
-** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
-** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which
-** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of
-** the current page cache implementation into that object.)^ </dd>
-**
-** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
-** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite
-** global [error log].
-** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
-** function with a call signature of void(*)(void*,int,const char*),
-** and a pointer to void. ^If the function pointer is not NULL, it is
-** invoked by [sqlite3_log()] to process each logging event. ^If the
-** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
-** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is
-** passed through as the first parameter to the application-defined logger
-** function whenever that function is invoked. ^The second parameter to
-** the logger function is a copy of the first parameter to the corresponding
-** [sqlite3_log()] call and is intended to be a [result code] or an
-** [extended result code]. ^The third parameter passed to the logger is
-** log message after formatting via [sqlite3_snprintf()].
-** The SQLite logging interface is not reentrant; the logger function
-** supplied by the application must not invoke any SQLite interface.
-** In a multi-threaded application, the application-defined logger
-** function must be threadsafe. </dd>
-**
-** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
-** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int.
-** If non-zero, then URI handling is globally enabled. If the parameter is zero,
-** then URI handling is globally disabled.)^ ^If URI handling is globally
-** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()],
-** [sqlite3_open16()] or
-** specified as part of [ATTACH] commands are interpreted as URIs, regardless
-** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
-** connection is opened. ^If it is globally disabled, filenames are
-** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
-** database connection is opened. ^(By default, URI handling is globally
-** disabled. The default value may be changed by compiling with the
-** [SQLITE_USE_URI] symbol defined.)^
-**
-** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
-** <dd>^The SQLITE_CONFIG_COVERING_INDEX_SCAN option takes a single integer
-** argument which is interpreted as a boolean in order to enable or disable
-** the use of covering indices for full table scans in the query optimizer.
-** ^The default setting is determined
-** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
-** if that compile-time option is omitted.
-** The ability to disable the use of covering indices for full table scans
-** is because some incorrectly coded legacy applications might malfunction
-** when the optimization is enabled. Providing the ability to
-** disable the optimization allows the older, buggy application code to work
-** without change even with newer versions of SQLite.
-**
-** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
-** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
-** <dd> These options are obsolete and should not be used by new code.
-** They are retained for backwards compatibility but are now no-ops.
-** </dd>
-**
-** [[SQLITE_CONFIG_SQLLOG]]
-** <dt>SQLITE_CONFIG_SQLLOG
-** <dd>This option is only available if sqlite is compiled with the
-** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should
-** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
-** The second should be of type (void*). The callback is invoked by the library
-** in three separate circumstances, identified by the value passed as the
-** fourth parameter. If the fourth parameter is 0, then the database connection
-** passed as the second argument has just been opened. The third argument
-** points to a buffer containing the name of the main database file. If the
-** fourth parameter is 1, then the SQL statement that the third parameter
-** points to has just been executed. Or, if the fourth parameter is 2, then
-** the connection being passed as the second parameter is being closed. The
-** third parameter is passed NULL In this case. An example of using this
-** configuration option can be seen in the "test_sqllog.c" source file in
-** the canonical SQLite source tree.</dd>
-**
-** [[SQLITE_CONFIG_MMAP_SIZE]]
-** <dt>SQLITE_CONFIG_MMAP_SIZE
-** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
-** that are the default mmap size limit (the default setting for
-** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
-** ^The default setting can be overridden by each database connection using
-** either the [PRAGMA mmap_size] command, or by using the
-** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
-** will be silently truncated if necessary so that it does not exceed the
-** compile-time maximum mmap size set by the
-** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
-** ^If either argument to this option is negative, then that argument is
-** changed to its compile-time default.
-**
-** [[SQLITE_CONFIG_WIN32_HEAPSIZE]]
-** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
-** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
-** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
-** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
-** that specifies the maximum size of the created heap.
-**
-** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
-** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
-** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
-** is a pointer to an integer and writes into that integer the number of extra
-** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
-** The amount of extra space required can change depending on the compiler,
-** target platform, and SQLite version.
-**
-** [[SQLITE_CONFIG_PMASZ]]
-** <dt>SQLITE_CONFIG_PMASZ
-** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which
-** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded
-** sorter to that integer. The default minimum PMA Size is set by the
-** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched
-** to help with sort operations when multithreaded sorting
-** is enabled (using the [PRAGMA threads] command) and the amount of content
-** to be sorted exceeds the page size times the minimum of the
-** [PRAGMA cache_size] setting and this value.
-**
-** [[SQLITE_CONFIG_STMTJRNL_SPILL]]
-** <dt>SQLITE_CONFIG_STMTJRNL_SPILL
-** <dd>^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which
-** becomes the [statement journal] spill-to-disk threshold.
-** [Statement journals] are held in memory until their size (in bytes)
-** exceeds this threshold, at which point they are written to disk.
-** Or if the threshold is -1, statement journals are always held
-** exclusively in memory.
-** Since many statement journals never become large, setting the spill
-** threshold to a value such as 64KiB can greatly reduce the amount of
-** I/O required to support statement rollback.
-** The default value for this setting is controlled by the
-** [SQLITE_STMTJRNL_SPILL] compile-time option.
-**
-** [[SQLITE_CONFIG_SORTERREF_SIZE]]
-** <dt>SQLITE_CONFIG_SORTERREF_SIZE
-** <dd>The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter
-** of type (int) - the new value of the sorter-reference size threshold.
-** Usually, when SQLite uses an external sort to order records according
-** to an ORDER BY clause, all fields required by the caller are present in the
-** sorted records. However, if SQLite determines based on the declared type
-** of a table column that its values are likely to be very large - larger
-** than the configured sorter-reference size threshold - then a reference
-** is stored in each sorted record and the required column values loaded
-** from the database as records are returned in sorted order. The default
-** value for this option is to never use this optimization. Specifying a
-** negative value for this option restores the default behaviour.
-** This option is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
-** </dl>
-*/
-#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
-#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
-#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
-#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
-#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
-#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */
-#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
-#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
-#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
-#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
-#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
-/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
-#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
-#define SQLITE_CONFIG_PCACHE 14 /* no-op */
-#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */
-#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
-#define SQLITE_CONFIG_URI 17 /* int */
-#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
-#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
-#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
-#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
-#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
-#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
-#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
-#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
-#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
-#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
-#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
-
-/*
-** CAPI3REF: Database Connection Configuration Options
-**
-** These constants are the available integer configuration options that
-** can be passed as the second argument to the [sqlite3_db_config()] interface.
-**
-** New configuration options may be added in future releases of SQLite.
-** Existing configuration options might be discontinued. Applications
-** should check the return code from [sqlite3_db_config()] to make sure that
-** the call worked. ^The [sqlite3_db_config()] interface will return a
-** non-zero [error code] if a discontinued or unsupported configuration option
-** is invoked.
-**
-** <dl>
-** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
-** <dd> ^This option takes three additional arguments that determine the
-** [lookaside memory allocator] configuration for the [database connection].
-** ^The first argument (the third parameter to [sqlite3_db_config()] is a
-** pointer to a memory buffer to use for lookaside memory.
-** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
-** may be NULL in which case SQLite will allocate the
-** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
-** size of each lookaside buffer slot. ^The third argument is the number of
-** slots. The size of the buffer in the first argument must be greater than
-** or equal to the product of the second and third arguments. The buffer
-** must be aligned to an 8-byte boundary. ^If the second argument to
-** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
-** rounded down to the next smaller multiple of 8. ^(The lookaside memory
-** configuration for a database connection can only be changed when that
-** connection is not currently using lookaside memory, or in other words
-** when the "current value" returned by
-** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero.
-** Any attempt to change the lookaside memory configuration when lookaside
-** memory is in use leaves the configuration unchanged and returns
-** [SQLITE_BUSY].)^</dd>
-**
-** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
-** <dd> ^This option is used to enable or disable the enforcement of
-** [foreign key constraints]. There should be two additional arguments.
-** The first argument is an integer which is 0 to disable FK enforcement,
-** positive to enable FK enforcement or negative to leave FK enforcement
-** unchanged. The second parameter is a pointer to an integer into which
-** is written 0 or 1 to indicate whether FK enforcement is off or on
-** following this call. The second parameter may be a NULL pointer, in
-** which case the FK enforcement setting is not reported back. </dd>
-**
-** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
-** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
-** There should be two additional arguments.
-** The first argument is an integer which is 0 to disable triggers,
-** positive to enable triggers or negative to leave the setting unchanged.
-** The second parameter is a pointer to an integer into which
-** is written 0 or 1 to indicate whether triggers are disabled or enabled
-** following this call. The second parameter may be a NULL pointer, in
-** which case the trigger setting is not reported back. </dd>
-**
-** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
-** <dd> ^This option is used to enable or disable the two-argument
-** version of the [fts3_tokenizer()] function which is part of the
-** [FTS3] full-text search engine extension.
-** There should be two additional arguments.
-** The first argument is an integer which is 0 to disable fts3_tokenizer() or
-** positive to enable fts3_tokenizer() or negative to leave the setting
-** unchanged.
-** The second parameter is a pointer to an integer into which
-** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
-** following this call. The second parameter may be a NULL pointer, in
-** which case the new setting is not reported back. </dd>
-**
-** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
-** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
-** interface independently of the [load_extension()] SQL function.
-** The [sqlite3_enable_load_extension()] API enables or disables both the
-** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
-** There should be two additional arguments.
-** When the first argument to this interface is 1, then only the C-API is
-** enabled and the SQL function remains disabled. If the first argument to
-** this interface is 0, then both the C-API and the SQL function are disabled.
-** If the first argument is -1, then no changes are made to state of either the
-** C-API or the SQL function.
-** The second parameter is a pointer to an integer into which
-** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface
-** is disabled or enabled following this call. The second parameter may
-** be a NULL pointer, in which case the new setting is not reported back.
-** </dd>
-**
-** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
-** <dd> ^This option is used to change the name of the "main" database
-** schema. ^The sole argument is a pointer to a constant UTF8 string
-** which will become the new schema name in place of "main". ^SQLite
-** does not make a copy of the new main schema name string, so the application
-** must ensure that the argument passed into this DBCONFIG option is unchanged
-** until after the database connection closes.
-** </dd>
-**
-** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
-** <dd> Usually, when a database in wal mode is closed or detached from a
-** database handle, SQLite checks if this will mean that there are now no
-** connections at all to the database. If so, it performs a checkpoint
-** operation before closing the connection. This option may be used to
-** override this behaviour. The first parameter passed to this operation
-** is an integer - positive to disable checkpoints-on-close, or zero (the
-** default) to enable them, and negative to leave the setting unchanged.
-** The second parameter is a pointer to an integer
-** into which is written 0 or 1 to indicate whether checkpoints-on-close
-** have been disabled - 0 if they are not disabled, 1 if they are.
-** </dd>
-**
-** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
-** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
-** the [query planner stability guarantee] (QPSG). When the QPSG is active,
-** a single SQL query statement will always use the same algorithm regardless
-** of values of [bound parameters].)^ The QPSG disables some query optimizations
-** that look at the values of bound parameters, which can make some queries
-** slower. But the QPSG has the advantage of more predictable behavior. With
-** the QPSG active, SQLite will always use the same query plan in the field as
-** was used during testing in the lab.
-** The first argument to this setting is an integer which is 0 to disable
-** the QPSG, positive to enable QPSG, or negative to leave the setting
-** unchanged. The second parameter is a pointer to an integer into which
-** is written 0 or 1 to indicate whether the QPSG is disabled or enabled
-** following this call.
-** </dd>
-**
-** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
-** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
-** include output for any operations performed by trigger programs. This
-** option is used to set or clear (the default) a flag that governs this
-** behavior. The first parameter passed to this operation is an integer -
-** positive to enable output for trigger programs, or zero to disable it,
-** or negative to leave the setting unchanged.
-** The second parameter is a pointer to an integer into which is written
-** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
-** it is not disabled, 1 if it is.
-** </dd>
-**
-** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
-** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
-** [VACUUM] in order to reset a database back to an empty database
-** with no schema and no content. The following process works even for
-** a badly corrupted database file:
-** <ol>
-** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
-** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
-** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
-** </ol>
-** Because resetting a database is destructive and irreversible, the
-** process requires the use of this obscure API and multiple steps to help
-** ensure that it does not happen by accident.
-** </dd>
-** </dl>
-*/
-#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
-#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
-#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
-#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
-#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
-#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
-#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
-#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
-#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
-#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */
-
-/*
-** CAPI3REF: Enable Or Disable Extended Result Codes
-** METHOD: sqlite3
-**
-** ^The sqlite3_extended_result_codes() routine enables or disables the
-** [extended result codes] feature of SQLite. ^The extended result
-** codes are disabled by default for historical compatibility.
-*/
-int sqlite3_extended_result_codes(sqlite3*, int onoff);
-
-/*
-** CAPI3REF: Last Insert Rowid
-** METHOD: sqlite3
-**
-** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
-** has a unique 64-bit signed
-** integer key called the [ROWID | "rowid"]. ^The rowid is always available
-** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
-** names are not also used by explicitly declared columns. ^If
-** the table has a column of type [INTEGER PRIMARY KEY] then that column
-** is another alias for the rowid.
-**
-** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of
-** the most recent successful [INSERT] into a rowid table or [virtual table]
-** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not
-** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred
-** on the database connection D, then sqlite3_last_insert_rowid(D) returns
-** zero.
-**
-** As well as being set automatically as rows are inserted into database
-** tables, the value returned by this function may be set explicitly by
-** [sqlite3_set_last_insert_rowid()]
-**
-** Some virtual table implementations may INSERT rows into rowid tables as
-** part of committing a transaction (e.g. to flush data accumulated in memory
-** to disk). In this case subsequent calls to this function return the rowid
-** associated with these internal INSERT operations, which leads to
-** unintuitive results. Virtual table implementations that do write to rowid
-** tables in this way can avoid this problem by restoring the original
-** rowid value using [sqlite3_set_last_insert_rowid()] before returning
-** control to the user.
-**
-** ^(If an [INSERT] occurs within a trigger then this routine will
-** return the [rowid] of the inserted row as long as the trigger is
-** running. Once the trigger program ends, the value returned
-** by this routine reverts to what it was before the trigger was fired.)^
-**
-** ^An [INSERT] that fails due to a constraint violation is not a
-** successful [INSERT] and does not change the value returned by this
-** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
-** and INSERT OR ABORT make no changes to the return value of this
-** routine when their insertion fails. ^(When INSERT OR REPLACE
-** encounters a constraint violation, it does not fail. The
-** INSERT continues to completion after deleting rows that caused
-** the constraint problem so INSERT OR REPLACE will always change
-** the return value of this interface.)^
-**
-** ^For the purposes of this routine, an [INSERT] is considered to
-** be successful even if it is subsequently rolled back.
-**
-** This function is accessible to SQL statements via the
-** [last_insert_rowid() SQL function].
-**
-** If a separate thread performs a new [INSERT] on the same
-** database connection while the [sqlite3_last_insert_rowid()]
-** function is running and thus changes the last insert [rowid],
-** then the value returned by [sqlite3_last_insert_rowid()] is
-** unpredictable and might not equal either the old or the new
-** last insert [rowid].
-*/
-sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
-
-/*
-** CAPI3REF: Set the Last Insert Rowid value.
-** METHOD: sqlite3
-**
-** The sqlite3_set_last_insert_rowid(D, R) method allows the application to
-** set the value returned by calling sqlite3_last_insert_rowid(D) to R
-** without inserting a row into the database.
-*/
-void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
-
-/*
-** CAPI3REF: Count The Number Of Rows Modified
-** METHOD: sqlite3
-**
-** ^This function returns the number of rows modified, inserted or
-** deleted by the most recently completed INSERT, UPDATE or DELETE
-** statement on the database connection specified by the only parameter.
-** ^Executing any other type of SQL statement does not modify the value
-** returned by this function.
-**
-** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
-** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
-** [foreign key actions] or [REPLACE] constraint resolution are not counted.
-**
-** Changes to a view that are intercepted by
-** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value
-** returned by sqlite3_changes() immediately after an INSERT, UPDATE or
-** DELETE statement run on a view is always zero. Only changes made to real
-** tables are counted.
-**
-** Things are more complicated if the sqlite3_changes() function is
-** executed while a trigger program is running. This may happen if the
-** program uses the [changes() SQL function], or if some other callback
-** function invokes sqlite3_changes() directly. Essentially:
-**
-** <ul>
-** <li> ^(Before entering a trigger program the value returned by
-** sqlite3_changes() function is saved. After the trigger program
-** has finished, the original value is restored.)^
-**
-** <li> ^(Within a trigger program each INSERT, UPDATE and DELETE
-** statement sets the value returned by sqlite3_changes()
-** upon completion as normal. Of course, this value will not include
-** any changes performed by sub-triggers, as the sqlite3_changes()
-** value will be saved and restored after each sub-trigger has run.)^
-** </ul>
-**
-** ^This means that if the changes() SQL function (or similar) is used
-** by the first INSERT, UPDATE or DELETE statement within a trigger, it
-** returns the value as set when the calling statement began executing.
-** ^If it is used by the second or subsequent such statement within a trigger
-** program, the value returned reflects the number of rows modified by the
-** previous INSERT, UPDATE or DELETE statement within the same trigger.
-**
-** See also the [sqlite3_total_changes()] interface, the
-** [count_changes pragma], and the [changes() SQL function].
-**
-** If a separate thread makes changes on the same database connection
-** while [sqlite3_changes()] is running then the value returned
-** is unpredictable and not meaningful.
-*/
-int sqlite3_changes(sqlite3*);
-
-/*
-** CAPI3REF: Total Number Of Rows Modified
-** METHOD: sqlite3
-**
-** ^This function returns the total number of rows inserted, modified or
-** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
-** since the database connection was opened, including those executed as
-** part of trigger programs. ^Executing any other type of SQL statement
-** does not affect the value returned by sqlite3_total_changes().
-**
-** ^Changes made as part of [foreign key actions] are included in the
-** count, but those made as part of REPLACE constraint resolution are
-** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
-** are not counted.
-**
-** See also the [sqlite3_changes()] interface, the
-** [count_changes pragma], and the [total_changes() SQL function].
-**
-** If a separate thread makes changes on the same database connection
-** while [sqlite3_total_changes()] is running then the value
-** returned is unpredictable and not meaningful.
-*/
-int sqlite3_total_changes(sqlite3*);
-
-/*
-** CAPI3REF: Interrupt A Long-Running Query
-** METHOD: sqlite3
-**
-** ^This function causes any pending database operation to abort and
-** return at its earliest opportunity. This routine is typically
-** called in response to a user action such as pressing "Cancel"
-** or Ctrl-C where the user wants a long query operation to halt
-** immediately.
-**
-** ^It is safe to call this routine from a thread different from the
-** thread that is currently running the database operation. But it
-** is not safe to call this routine with a [database connection] that
-** is closed or might close before sqlite3_interrupt() returns.
-**
-** ^If an SQL operation is very nearly finished at the time when
-** sqlite3_interrupt() is called, then it might not have an opportunity
-** to be interrupted and might continue to completion.
-**
-** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT].
-** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE
-** that is inside an explicit transaction, then the entire transaction
-** will be rolled back automatically.
-**
-** ^The sqlite3_interrupt(D) call is in effect until all currently running
-** SQL statements on [database connection] D complete. ^Any new SQL statements
-** that are started after the sqlite3_interrupt() call and before the
-** running statements reaches zero are interrupted as if they had been
-** running prior to the sqlite3_interrupt() call. ^New SQL statements
-** that are started after the running statement count reaches zero are
-** not effected by the sqlite3_interrupt().
-** ^A call to sqlite3_interrupt(D) that occurs when there are no running
-** SQL statements is a no-op and has no effect on SQL statements
-** that are started after the sqlite3_interrupt() call returns.
-*/
-void sqlite3_interrupt(sqlite3*);
-
-/*
-** CAPI3REF: Determine If An SQL Statement Is Complete
-**
-** These routines are useful during command-line input to determine if the
-** currently entered text seems to form a complete SQL statement or
-** if additional input is needed before sending the text into
-** SQLite for parsing. ^These routines return 1 if the input string
-** appears to be a complete SQL statement. ^A statement is judged to be
-** complete if it ends with a semicolon token and is not a prefix of a
-** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within
-** string literals or quoted identifier names or comments are not
-** independent tokens (they are part of the token in which they are
-** embedded) and thus do not count as a statement terminator. ^Whitespace
-** and comments that follow the final semicolon are ignored.
-**
-** ^These routines return 0 if the statement is incomplete. ^If a
-** memory allocation fails, then SQLITE_NOMEM is returned.
-**
-** ^These routines do not parse the SQL statements thus
-** will not detect syntactically incorrect SQL.
-**
-** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
-** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
-** automatically by sqlite3_complete16(). If that initialization fails,
-** then the return value from sqlite3_complete16() will be non-zero
-** regardless of whether or not the input SQL is complete.)^
-**
-** The input to [sqlite3_complete()] must be a zero-terminated
-** UTF-8 string.
-**
-** The input to [sqlite3_complete16()] must be a zero-terminated
-** UTF-16 string in native byte order.
-*/
-int sqlite3_complete(const char *sql);
-int sqlite3_complete16(const void *sql);
-
-/*
-** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
-** KEYWORDS: {busy-handler callback} {busy handler}
-** METHOD: sqlite3
-**
-** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
-** that might be invoked with argument P whenever
-** an attempt is made to access a database table associated with
-** [database connection] D when another thread
-** or process has the table locked.
-** The sqlite3_busy_handler() interface is used to implement
-** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
-**
-** ^If the busy callback is NULL, then [SQLITE_BUSY]
-** is returned immediately upon encountering the lock. ^If the busy callback
-** is not NULL, then the callback might be invoked with two arguments.
-**
-** ^The first argument to the busy handler is a copy of the void* pointer which
-** is the third argument to sqlite3_busy_handler(). ^The second argument to
-** the busy handler callback is the number of times that the busy handler has
-** been invoked previously for the same locking event. ^If the
-** busy callback returns 0, then no additional attempts are made to
-** access the database and [SQLITE_BUSY] is returned
-** to the application.
-** ^If the callback returns non-zero, then another attempt
-** is made to access the database and the cycle repeats.
-**
-** The presence of a busy handler does not guarantee that it will be invoked
-** when there is lock contention. ^If SQLite determines that invoking the busy
-** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
-** to the application instead of invoking the
-** busy handler.
-** Consider a scenario where one process is holding a read lock that
-** it is trying to promote to a reserved lock and
-** a second process is holding a reserved lock that it is trying
-** to promote to an exclusive lock. The first process cannot proceed
-** because it is blocked by the second and the second process cannot
-** proceed because it is blocked by the first. If both processes
-** invoke the busy handlers, neither will make any progress. Therefore,
-** SQLite returns [SQLITE_BUSY] for the first process, hoping that this
-** will induce the first process to release its read lock and allow
-** the second process to proceed.
-**
-** ^The default busy callback is NULL.
-**
-** ^(There can only be a single busy handler defined for each
-** [database connection]. Setting a new busy handler clears any
-** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
-** or evaluating [PRAGMA busy_timeout=N] will change the
-** busy handler and thus clear any previously set busy handler.
-**
-** The busy callback should not take any actions which modify the
-** database connection that invoked the busy handler. In other words,
-** the busy handler is not reentrant. Any such actions
-** result in undefined behavior.
-**
-** A busy handler must not close the database connection
-** or [prepared statement] that invoked the busy handler.
-*/
-int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
-
-/*
-** CAPI3REF: Set A Busy Timeout
-** METHOD: sqlite3
-**
-** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
-** for a specified amount of time when a table is locked. ^The handler
-** will sleep multiple times until at least "ms" milliseconds of sleeping
-** have accumulated. ^After at least "ms" milliseconds of sleeping,
-** the handler returns 0 which causes [sqlite3_step()] to return
-** [SQLITE_BUSY].
-**
-** ^Calling this routine with an argument less than or equal to zero
-** turns off all busy handlers.
-**
-** ^(There can only be a single busy handler for a particular
-** [database connection] at any given moment. If another busy handler
-** was defined (using [sqlite3_busy_handler()]) prior to calling
-** this routine, that other busy handler is cleared.)^
-**
-** See also: [PRAGMA busy_timeout]
-*/
-int sqlite3_busy_timeout(sqlite3*, int ms);
-
-/*
-** CAPI3REF: Convenience Routines For Running Queries
-** METHOD: sqlite3
-**
-** This is a legacy interface that is preserved for backwards compatibility.
-** Use of this interface is not recommended.
-**
-** Definition: A <b>result table</b> is memory data structure created by the
-** [sqlite3_get_table()] interface. A result table records the
-** complete query results from one or more queries.
-**
-** The table conceptually has a number of rows and columns. But
-** these numbers are not part of the result table itself. These
-** numbers are obtained separately. Let N be the number of rows
-** and M be the number of columns.
-**
-** A result table is an array of pointers to zero-terminated UTF-8 strings.
-** There are (N+1)*M elements in the array. The first M pointers point
-** to zero-terminated strings that contain the names of the columns.
-** The remaining entries all point to query results. NULL values result
-** in NULL pointers. All other values are in their UTF-8 zero-terminated
-** string representation as returned by [sqlite3_column_text()].
-**
-** A result table might consist of one or more memory allocations.
-** It is not safe to pass a result table directly to [sqlite3_free()].
-** A result table should be deallocated using [sqlite3_free_table()].
-**
-** ^(As an example of the result table format, suppose a query result
-** is as follows:
-**
-** <blockquote><pre>
-** Name | Age
-** -----------------------
-** Alice | 43
-** Bob | 28
-** Cindy | 21
-** </pre></blockquote>
-**
-** There are two column (M==2) and three rows (N==3). Thus the
-** result table has 8 entries. Suppose the result table is stored
-** in an array names azResult. Then azResult holds this content:
-**
-** <blockquote><pre>
-** azResult&#91;0] = "Name";
-** azResult&#91;1] = "Age";
-** azResult&#91;2] = "Alice";
-** azResult&#91;3] = "43";
-** azResult&#91;4] = "Bob";
-** azResult&#91;5] = "28";
-** azResult&#91;6] = "Cindy";
-** azResult&#91;7] = "21";
-** </pre></blockquote>)^
-**
-** ^The sqlite3_get_table() function evaluates one or more
-** semicolon-separated SQL statements in the zero-terminated UTF-8
-** string of its 2nd parameter and returns a result table to the
-** pointer given in its 3rd parameter.
-**
-** After the application has finished with the result from sqlite3_get_table(),
-** it must pass the result table pointer to sqlite3_free_table() in order to
-** release the memory that was malloced. Because of the way the
-** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling
-** function must not try to call [sqlite3_free()] directly. Only
-** [sqlite3_free_table()] is able to release the memory properly and safely.
-**
-** The sqlite3_get_table() interface is implemented as a wrapper around
-** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access
-** to any internal data structures of SQLite. It uses only the public
-** interface defined here. As a consequence, errors that occur in the
-** wrapper layer outside of the internal [sqlite3_exec()] call are not
-** reflected in subsequent calls to [sqlite3_errcode()] or
-** [sqlite3_errmsg()].
-*/
-int sqlite3_get_table(
- sqlite3 *db, /* An open database */
- const char *zSql, /* SQL to be evaluated */
- char ***pazResult, /* Results of the query */
- int *pnRow, /* Number of result rows written here */
- int *pnColumn, /* Number of result columns written here */
- char **pzErrmsg /* Error msg written here */
-);
-void sqlite3_free_table(char **result);
-
-/*
-** CAPI3REF: Formatted String Printing Functions
-**
-** These routines are work-alikes of the "printf()" family of functions
-** from the standard C library.
-** These routines understand most of the common formatting options from
-** the standard library printf()
-** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]).
-** See the [built-in printf()] documentation for details.
-**
-** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
-** results into memory obtained from [sqlite3_malloc64()].
-** The strings returned by these two routines should be
-** released by [sqlite3_free()]. ^Both routines return a
-** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough
-** memory to hold the resulting string.
-**
-** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
-** the standard C library. The result is written into the
-** buffer supplied as the second parameter whose size is given by
-** the first parameter. Note that the order of the
-** first two parameters is reversed from snprintf().)^ This is an
-** historical accident that cannot be fixed without breaking
-** backwards compatibility. ^(Note also that sqlite3_snprintf()
-** returns a pointer to its buffer instead of the number of
-** characters actually written into the buffer.)^ We admit that
-** the number of characters written would be a more useful return
-** value but we cannot change the implementation of sqlite3_snprintf()
-** now without breaking compatibility.
-**
-** ^As long as the buffer size is greater than zero, sqlite3_snprintf()
-** guarantees that the buffer is always zero-terminated. ^The first
-** parameter "n" is the total size of the buffer, including space for
-** the zero terminator. So the longest string that can be completely
-** written will be n-1 characters.
-**
-** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
-**
-** See also: [built-in printf()], [printf() SQL function]
-*/
-char *sqlite3_mprintf(const char*,...);
-char *sqlite3_vmprintf(const char*, va_list);
-char *sqlite3_snprintf(int,char*,const char*, ...);
-char *sqlite3_vsnprintf(int,char*,const char*, va_list);
-
-/*
-** CAPI3REF: Memory Allocation Subsystem
-**
-** The SQLite core uses these three routines for all of its own
-** internal memory allocation needs. "Core" in the previous sentence
-** does not include operating-system specific VFS implementation. The
-** Windows VFS uses native malloc() and free() for some operations.
-**
-** ^The sqlite3_malloc() routine returns a pointer to a block
-** of memory at least N bytes in length, where N is the parameter.
-** ^If sqlite3_malloc() is unable to obtain sufficient free
-** memory, it returns a NULL pointer. ^If the parameter N to
-** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
-** a NULL pointer.
-**
-** ^The sqlite3_malloc64(N) routine works just like
-** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead
-** of a signed 32-bit integer.
-**
-** ^Calling sqlite3_free() with a pointer previously returned
-** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
-** that it might be reused. ^The sqlite3_free() routine is
-** a no-op if is called with a NULL pointer. Passing a NULL pointer
-** to sqlite3_free() is harmless. After being freed, memory
-** should neither be read nor written. Even reading previously freed
-** memory might result in a segmentation fault or other severe error.
-** Memory corruption, a segmentation fault, or other severe error
-** might result if sqlite3_free() is called with a non-NULL pointer that
-** was not obtained from sqlite3_malloc() or sqlite3_realloc().
-**
-** ^The sqlite3_realloc(X,N) interface attempts to resize a
-** prior memory allocation X to be at least N bytes.
-** ^If the X parameter to sqlite3_realloc(X,N)
-** is a NULL pointer then its behavior is identical to calling
-** sqlite3_malloc(N).
-** ^If the N parameter to sqlite3_realloc(X,N) is zero or
-** negative then the behavior is exactly the same as calling
-** sqlite3_free(X).
-** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation
-** of at least N bytes in size or NULL if insufficient memory is available.
-** ^If M is the size of the prior allocation, then min(N,M) bytes
-** of the prior allocation are copied into the beginning of buffer returned
-** by sqlite3_realloc(X,N) and the prior allocation is freed.
-** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the
-** prior allocation is not freed.
-**
-** ^The sqlite3_realloc64(X,N) interfaces works the same as
-** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead
-** of a 32-bit signed integer.
-**
-** ^If X is a memory allocation previously obtained from sqlite3_malloc(),
-** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then
-** sqlite3_msize(X) returns the size of that memory allocation in bytes.
-** ^The value returned by sqlite3_msize(X) might be larger than the number
-** of bytes requested when X was allocated. ^If X is a NULL pointer then
-** sqlite3_msize(X) returns zero. If X points to something that is not
-** the beginning of memory allocation, or if it points to a formerly
-** valid memory allocation that has now been freed, then the behavior
-** of sqlite3_msize(X) is undefined and possibly harmful.
-**
-** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(),
-** sqlite3_malloc64(), and sqlite3_realloc64()
-** is always aligned to at least an 8 byte boundary, or to a
-** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
-** option is used.
-**
-** In SQLite version 3.5.0 and 3.5.1, it was possible to define
-** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
-** implementation of these routines to be omitted. That capability
-** is no longer provided. Only built-in memory allocators can be used.
-**
-** Prior to SQLite version 3.7.10, the Windows OS interface layer called
-** the system malloc() and free() directly when converting
-** filenames between the UTF-8 encoding used by SQLite
-** and whatever filename encoding is used by the particular Windows
-** installation. Memory allocation errors were detected, but
-** they were reported back as [SQLITE_CANTOPEN] or
-** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
-**
-** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
-** must be either NULL or else pointers obtained from a prior
-** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
-** not yet been released.
-**
-** The application must not read or write any part of
-** a block of memory after it has been released using
-** [sqlite3_free()] or [sqlite3_realloc()].
-*/
-void *sqlite3_malloc(int);
-void *sqlite3_malloc64(sqlite3_uint64);
-void *sqlite3_realloc(void*, int);
-void *sqlite3_realloc64(void*, sqlite3_uint64);
-void sqlite3_free(void*);
-sqlite3_uint64 sqlite3_msize(void*);
-
-/*
-** CAPI3REF: Memory Allocator Statistics
-**
-** SQLite provides these two interfaces for reporting on the status
-** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()]
-** routines, which form the built-in memory allocation subsystem.
-**
-** ^The [sqlite3_memory_used()] routine returns the number of bytes
-** of memory currently outstanding (malloced but not freed).
-** ^The [sqlite3_memory_highwater()] routine returns the maximum
-** value of [sqlite3_memory_used()] since the high-water mark
-** was last reset. ^The values returned by [sqlite3_memory_used()] and
-** [sqlite3_memory_highwater()] include any overhead
-** added by SQLite in its implementation of [sqlite3_malloc()],
-** but not overhead added by the any underlying system library
-** routines that [sqlite3_malloc()] may call.
-**
-** ^The memory high-water mark is reset to the current value of
-** [sqlite3_memory_used()] if and only if the parameter to
-** [sqlite3_memory_highwater()] is true. ^The value returned
-** by [sqlite3_memory_highwater(1)] is the high-water mark
-** prior to the reset.
-*/
-sqlite3_int64 sqlite3_memory_used(void);
-sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
-
-/*
-** CAPI3REF: Pseudo-Random Number Generator
-**
-** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
-** select random [ROWID | ROWIDs] when inserting new records into a table that
-** already uses the largest possible [ROWID]. The PRNG is also used for
-** the build-in random() and randomblob() SQL functions. This interface allows
-** applications to access the same PRNG for other purposes.
-**
-** ^A call to this routine stores N bytes of randomness into buffer P.
-** ^The P parameter can be a NULL pointer.
-**
-** ^If this routine has not been previously called or if the previous
-** call had N less than one or a NULL pointer for P, then the PRNG is
-** seeded using randomness obtained from the xRandomness method of
-** the default [sqlite3_vfs] object.
-** ^If the previous call to this routine had an N of 1 or more and a
-** non-NULL P then the pseudo-randomness is generated
-** internally and without recourse to the [sqlite3_vfs] xRandomness
-** method.
-*/
-void sqlite3_randomness(int N, void *P);
-
-/*
-** CAPI3REF: Compile-Time Authorization Callbacks
-** METHOD: sqlite3
-** KEYWORDS: {authorizer callback}
-**
-** ^This routine registers an authorizer callback with a particular
-** [database connection], supplied in the first argument.
-** ^The authorizer callback is invoked as SQL statements are being compiled
-** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
-** [sqlite3_prepare_v3()], [sqlite3_prepare16()], [sqlite3_prepare16_v2()],
-** and [sqlite3_prepare16_v3()]. ^At various
-** points during the compilation process, as logic is being created
-** to perform various actions, the authorizer callback is invoked to
-** see if those actions are allowed. ^The authorizer callback should
-** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the
-** specific action but allow the SQL statement to continue to be
-** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be
-** rejected with an error. ^If the authorizer callback returns
-** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY]
-** then the [sqlite3_prepare_v2()] or equivalent call that triggered
-** the authorizer will fail with an error message.
-**
-** When the callback returns [SQLITE_OK], that means the operation
-** requested is ok. ^When the callback returns [SQLITE_DENY], the
-** [sqlite3_prepare_v2()] or equivalent call that triggered the
-** authorizer will fail with an error message explaining that
-** access is denied.
-**
-** ^The first parameter to the authorizer callback is a copy of the third
-** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
-** to the callback is an integer [SQLITE_COPY | action code] that specifies
-** the particular action to be authorized. ^The third through sixth parameters
-** to the callback are either NULL pointers or zero-terminated strings
-** that contain additional details about the action to be authorized.
-** Applications must always be prepared to encounter a NULL pointer in any
-** of the third through the sixth parameters of the authorization callback.
-**
-** ^If the action code is [SQLITE_READ]
-** and the callback returns [SQLITE_IGNORE] then the
-** [prepared statement] statement is constructed to substitute
-** a NULL value in place of the table column that would have
-** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
-** return can be used to deny an untrusted user access to individual
-** columns of a table.
-** ^When a table is referenced by a [SELECT] but no column values are
-** extracted from that table (for example in a query like
-** "SELECT count(*) FROM tab") then the [SQLITE_READ] authorizer callback
-** is invoked once for that table with a column name that is an empty string.
-** ^If the action code is [SQLITE_DELETE] and the callback returns
-** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
-** [truncate optimization] is disabled and all rows are deleted individually.
-**
-** An authorizer is used when [sqlite3_prepare | preparing]
-** SQL statements from an untrusted source, to ensure that the SQL statements
-** do not try to access data they are not allowed to see, or that they do not
-** try to execute malicious statements that damage the database. For
-** example, an application may allow a user to enter arbitrary
-** SQL queries for evaluation by a database. But the application does
-** not want the user to be able to make arbitrary changes to the
-** database. An authorizer could then be put in place while the
-** user-entered SQL is being [sqlite3_prepare | prepared] that
-** disallows everything except [SELECT] statements.
-**
-** Applications that need to process SQL from untrusted sources
-** might also consider lowering resource limits using [sqlite3_limit()]
-** and limiting database size using the [max_page_count] [PRAGMA]
-** in addition to using an authorizer.
-**
-** ^(Only a single authorizer can be in place on a database connection
-** at a time. Each call to sqlite3_set_authorizer overrides the
-** previous call.)^ ^Disable the authorizer by installing a NULL callback.
-** The authorizer is disabled by default.
-**
-** The authorizer callback must not do anything that will modify
-** the database connection that invoked the authorizer callback.
-** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
-** database connections for the meaning of "modify" in this paragraph.
-**
-** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the
-** statement might be re-prepared during [sqlite3_step()] due to a
-** schema change. Hence, the application should ensure that the
-** correct authorizer callback remains in place during the [sqlite3_step()].
-**
-** ^Note that the authorizer callback is invoked only during
-** [sqlite3_prepare()] or its variants. Authorization is not
-** performed during statement evaluation in [sqlite3_step()], unless
-** as stated in the previous paragraph, sqlite3_step() invokes
-** sqlite3_prepare_v2() to reprepare a statement after a schema change.
-*/
-int sqlite3_set_authorizer(
- sqlite3*,
- int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
- void *pUserData
-);
-
-/*
-** CAPI3REF: Authorizer Return Codes
-**
-** The [sqlite3_set_authorizer | authorizer callback function] must
-** return either [SQLITE_OK] or one of these two constants in order
-** to signal SQLite whether or not the action is permitted. See the
-** [sqlite3_set_authorizer | authorizer documentation] for additional
-** information.
-**
-** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
-** returned from the [sqlite3_vtab_on_conflict()] interface.
-*/
-#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
-#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
-
-/*
-** CAPI3REF: Authorizer Action Codes
-**
-** The [sqlite3_set_authorizer()] interface registers a callback function
-** that is invoked to authorize certain SQL statement actions. The
-** second parameter to the callback is an integer code that specifies
-** what action is being authorized. These are the integer action codes that
-** the authorizer callback may be passed.
-**
-** These action code values signify what kind of operation is to be
-** authorized. The 3rd and 4th parameters to the authorization
-** callback function will be parameters or NULL depending on which of these
-** codes is used as the second parameter. ^(The 5th parameter to the
-** authorizer callback is the name of the database ("main", "temp",
-** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback
-** is the name of the inner-most trigger or view that is responsible for
-** the access attempt or NULL if this access attempt is directly from
-** top-level SQL code.
-*/
-/******************************************* 3rd ************ 4th ***********/
-#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */
-#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */
-#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
-#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */
-#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
-#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */
-#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */
-#define SQLITE_CREATE_VIEW 8 /* View Name NULL */
-#define SQLITE_DELETE 9 /* Table Name NULL */
-#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */
-#define SQLITE_DROP_TABLE 11 /* Table Name NULL */
-#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */
-#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */
-#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
-#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */
-#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */
-#define SQLITE_DROP_VIEW 17 /* View Name NULL */
-#define SQLITE_INSERT 18 /* Table Name NULL */
-#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */
-#define SQLITE_READ 20 /* Table Name Column Name */
-#define SQLITE_SELECT 21 /* NULL NULL */
-#define SQLITE_TRANSACTION 22 /* Operation NULL */
-#define SQLITE_UPDATE 23 /* Table Name Column Name */
-#define SQLITE_ATTACH 24 /* Filename NULL */
-#define SQLITE_DETACH 25 /* Database Name NULL */
-#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */
-#define SQLITE_REINDEX 27 /* Index Name NULL */
-#define SQLITE_ANALYZE 28 /* Table Name NULL */
-#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */
-#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
-#define SQLITE_FUNCTION 31 /* NULL Function Name */
-#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */
-#define SQLITE_COPY 0 /* No longer used */
-#define SQLITE_RECURSIVE 33 /* NULL NULL */
-
-/*
-** CAPI3REF: Tracing And Profiling Functions
-** METHOD: sqlite3
-**
-** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
-** instead of the routines described here.
-**
-** These routines register callback functions that can be used for
-** tracing and profiling the execution of SQL statements.
-**
-** ^The callback function registered by sqlite3_trace() is invoked at
-** various times when an SQL statement is being run by [sqlite3_step()].
-** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the
-** SQL statement text as the statement first begins executing.
-** ^(Additional sqlite3_trace() callbacks might occur
-** as each triggered subprogram is entered. The callbacks for triggers
-** contain a UTF-8 SQL comment that identifies the trigger.)^
-**
-** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit
-** the length of [bound parameter] expansion in the output of sqlite3_trace().
-**
-** ^The callback function registered by sqlite3_profile() is invoked
-** as each SQL statement finishes. ^The profile callback contains
-** the original statement text and an estimate of wall-clock time
-** of how long that statement took to run. ^The profile callback
-** time is in units of nanoseconds, however the current implementation
-** is only capable of millisecond resolution so the six least significant
-** digits in the time are meaningless. Future versions of SQLite
-** might provide greater resolution on the profiler callback. The
-** sqlite3_profile() function is considered experimental and is
-** subject to change in future versions of SQLite.
-*/
-SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*,
- void(*xTrace)(void*,const char*), void*);
-SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
- void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
-
-/*
-** CAPI3REF: SQL Trace Event Codes
-** KEYWORDS: SQLITE_TRACE
-**
-** These constants identify classes of events that can be monitored
-** using the [sqlite3_trace_v2()] tracing logic. The M argument
-** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of
-** the following constants. ^The first argument to the trace callback
-** is one of the following constants.
-**
-** New tracing constants may be added in future releases.
-**
-** ^A trace callback has four arguments: xCallback(T,C,P,X).
-** ^The T argument is one of the integer type codes above.
-** ^The C argument is a copy of the context pointer passed in as the
-** fourth argument to [sqlite3_trace_v2()].
-** The P and X arguments are pointers whose meanings depend on T.
-**
-** <dl>
-** [[SQLITE_TRACE_STMT]] <dt>SQLITE_TRACE_STMT</dt>
-** <dd>^An SQLITE_TRACE_STMT callback is invoked when a prepared statement
-** first begins running and possibly at other times during the
-** execution of the prepared statement, such as at the start of each
-** trigger subprogram. ^The P argument is a pointer to the
-** [prepared statement]. ^The X argument is a pointer to a string which
-** is the unexpanded SQL text of the prepared statement or an SQL comment
-** that indicates the invocation of a trigger. ^The callback can compute
-** the same text that would have been returned by the legacy [sqlite3_trace()]
-** interface by using the X argument when X begins with "--" and invoking
-** [sqlite3_expanded_sql(P)] otherwise.
-**
-** [[SQLITE_TRACE_PROFILE]] <dt>SQLITE_TRACE_PROFILE</dt>
-** <dd>^An SQLITE_TRACE_PROFILE callback provides approximately the same
-** information as is provided by the [sqlite3_profile()] callback.
-** ^The P argument is a pointer to the [prepared statement] and the
-** X argument points to a 64-bit integer which is the estimated of
-** the number of nanosecond that the prepared statement took to run.
-** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes.
-**
-** [[SQLITE_TRACE_ROW]] <dt>SQLITE_TRACE_ROW</dt>
-** <dd>^An SQLITE_TRACE_ROW callback is invoked whenever a prepared
-** statement generates a single row of result.
-** ^The P argument is a pointer to the [prepared statement] and the
-** X argument is unused.
-**
-** [[SQLITE_TRACE_CLOSE]] <dt>SQLITE_TRACE_CLOSE</dt>
-** <dd>^An SQLITE_TRACE_CLOSE callback is invoked when a database
-** connection closes.
-** ^The P argument is a pointer to the [database connection] object
-** and the X argument is unused.
-** </dl>
-*/
-#define SQLITE_TRACE_STMT 0x01
-#define SQLITE_TRACE_PROFILE 0x02
-#define SQLITE_TRACE_ROW 0x04
-#define SQLITE_TRACE_CLOSE 0x08
-
-/*
-** CAPI3REF: SQL Trace Hook
-** METHOD: sqlite3
-**
-** ^The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback
-** function X against [database connection] D, using property mask M
-** and context pointer P. ^If the X callback is
-** NULL or if the M mask is zero, then tracing is disabled. The
-** M argument should be the bitwise OR-ed combination of
-** zero or more [SQLITE_TRACE] constants.
-**
-** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides
-** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2().
-**
-** ^The X callback is invoked whenever any of the events identified by
-** mask M occur. ^The integer return value from the callback is currently
-** ignored, though this may change in future releases. Callback
-** implementations should return zero to ensure future compatibility.
-**
-** ^A trace callback is invoked with four arguments: callback(T,C,P,X).
-** ^The T argument is one of the [SQLITE_TRACE]
-** constants to indicate why the callback was invoked.
-** ^The C argument is a copy of the context pointer.
-** The P and X arguments are pointers whose meanings depend on T.
-**
-** The sqlite3_trace_v2() interface is intended to replace the legacy
-** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which
-** are deprecated.
-*/
-int sqlite3_trace_v2(
- sqlite3*,
- unsigned uMask,
- int(*xCallback)(unsigned,void*,void*,void*),
- void *pCtx
-);
-
-/*
-** CAPI3REF: Query Progress Callbacks
-** METHOD: sqlite3
-**
-** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
-** function X to be invoked periodically during long running calls to
-** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for
-** database connection D. An example use for this
-** interface is to keep a GUI updated during a large query.
-**
-** ^The parameter P is passed through as the only parameter to the
-** callback function X. ^The parameter N is the approximate number of
-** [virtual machine instructions] that are evaluated between successive
-** invocations of the callback X. ^If N is less than one then the progress
-** handler is disabled.
-**
-** ^Only a single progress handler may be defined at one time per
-** [database connection]; setting a new progress handler cancels the
-** old one. ^Setting parameter X to NULL disables the progress handler.
-** ^The progress handler is also disabled by setting N to a value less
-** than 1.
-**
-** ^If the progress callback returns non-zero, the operation is
-** interrupted. This feature can be used to implement a
-** "Cancel" button on a GUI progress dialog box.
-**
-** The progress handler callback must not do anything that will modify
-** the database connection that invoked the progress handler.
-** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
-** database connections for the meaning of "modify" in this paragraph.
-**
-*/
-void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
-
-/*
-** CAPI3REF: Opening A New Database Connection
-** CONSTRUCTOR: sqlite3
-**
-** ^These routines open an SQLite database file as specified by the
-** filename argument. ^The filename argument is interpreted as UTF-8 for
-** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
-** order for sqlite3_open16(). ^(A [database connection] handle is usually
-** returned in *ppDb, even if an error occurs. The only exception is that
-** if SQLite is unable to allocate memory to hold the [sqlite3] object,
-** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
-** object.)^ ^(If the database is opened (and/or created) successfully, then
-** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The
-** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain
-** an English language description of the error following a failure of any
-** of the sqlite3_open() routines.
-**
-** ^The default encoding will be UTF-8 for databases created using
-** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases
-** created using sqlite3_open16() will be UTF-16 in the native byte order.
-**
-** Whether or not an error occurs when it is opened, resources
-** associated with the [database connection] handle should be released by
-** passing it to [sqlite3_close()] when it is no longer required.
-**
-** The sqlite3_open_v2() interface works like sqlite3_open()
-** except that it accepts two additional parameters for additional control
-** over the new database connection. ^(The flags parameter to
-** sqlite3_open_v2() can take one of
-** the following three values, optionally combined with the
-** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
-** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
-**
-** <dl>
-** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
-** <dd>The database is opened in read-only mode. If the database does not
-** already exist, an error is returned.</dd>)^
-**
-** ^(<dt>[SQLITE_OPEN_READWRITE]</dt>
-** <dd>The database is opened for reading and writing if possible, or reading
-** only if the file is write protected by the operating system. In either
-** case the database must already exist, otherwise an error is returned.</dd>)^
-**
-** ^(<dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt>
-** <dd>The database is opened for reading and writing, and is created if
-** it does not already exist. This is the behavior that is always used for
-** sqlite3_open() and sqlite3_open16().</dd>)^
-** </dl>
-**
-** If the 3rd parameter to sqlite3_open_v2() is not one of the
-** combinations shown above optionally combined with other
-** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
-** then the behavior is undefined.
-**
-** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
-** opens in the multi-thread [threading mode] as long as the single-thread
-** mode has not been set at compile-time or start-time. ^If the
-** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
-** in the serialized [threading mode] unless single-thread was
-** previously selected at compile-time or start-time.
-** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
-** eligible to use [shared cache mode], regardless of whether or not shared
-** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
-** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
-** participate in [shared cache mode] even if it is enabled.
-**
-** ^The fourth parameter to sqlite3_open_v2() is the name of the
-** [sqlite3_vfs] object that defines the operating system interface that
-** the new database connection should use. ^If the fourth parameter is
-** a NULL pointer then the default [sqlite3_vfs] object is used.
-**
-** ^If the filename is ":memory:", then a private, temporary in-memory database
-** is created for the connection. ^This in-memory database will vanish when
-** the database connection is closed. Future versions of SQLite might
-** make use of additional special filenames that begin with the ":" character.
-** It is recommended that when a database filename actually does begin with
-** a ":" character you should prefix the filename with a pathname such as
-** "./" to avoid ambiguity.
-**
-** ^If the filename is an empty string, then a private, temporary
-** on-disk database will be created. ^This private database will be
-** automatically deleted as soon as the database connection is closed.
-**
-** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
-**
-** ^If [URI filename] interpretation is enabled, and the filename argument
-** begins with "file:", then the filename is interpreted as a URI. ^URI
-** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
-** set in the third argument to sqlite3_open_v2(), or if it has
-** been enabled globally using the [SQLITE_CONFIG_URI] option with the
-** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
-** URI filename interpretation is turned off
-** by default, but future releases of SQLite might enable URI filename
-** interpretation by default. See "[URI filenames]" for additional
-** information.
-**
-** URI filenames are parsed according to RFC 3986. ^If the URI contains an
-** authority, then it must be either an empty string or the string
-** "localhost". ^If the authority is not an empty string or "localhost", an
-** error is returned to the caller. ^The fragment component of a URI, if
-** present, is ignored.
-**
-** ^SQLite uses the path component of the URI as the name of the disk file
-** which contains the database. ^If the path begins with a '/' character,
-** then it is interpreted as an absolute path. ^If the path does not begin
-** with a '/' (meaning that the authority section is omitted from the URI)
-** then the path is interpreted as a relative path.
-** ^(On windows, the first component of an absolute path
-** is a drive specification (e.g. "C:").)^
-**
-** [[core URI query parameters]]
-** The query component of a URI may contain parameters that are interpreted
-** either by SQLite itself, or by a [VFS | custom VFS implementation].
-** SQLite and its built-in [VFSes] interpret the
-** following query parameters:
-**
-** <ul>
-** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
-** a VFS object that provides the operating system interface that should
-** be used to access the database file on disk. ^If this option is set to
-** an empty string the default VFS object is used. ^Specifying an unknown
-** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
-** present, then the VFS specified by the option takes precedence over
-** the value passed as the fourth parameter to sqlite3_open_v2().
-**
-** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
-** "rwc", or "memory". Attempting to set it to any other value is
-** an error)^.
-** ^If "ro" is specified, then the database is opened for read-only
-** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
-** third argument to sqlite3_open_v2(). ^If the mode option is set to
-** "rw", then the database is opened for read-write (but not create)
-** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
-** been set. ^Value "rwc" is equivalent to setting both
-** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is
-** set to "memory" then a pure [in-memory database] that never reads
-** or writes from disk is used. ^It is an error to specify a value for
-** the mode parameter that is less restrictive than that specified by
-** the flags passed in the third parameter to sqlite3_open_v2().
-**
-** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
-** "private". ^Setting it to "shared" is equivalent to setting the
-** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
-** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
-** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
-** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
-** a URI filename, its value overrides any behavior requested by setting
-** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
-**
-** <li> <b>psow</b>: ^The psow parameter indicates whether or not the
-** [powersafe overwrite] property does or does not apply to the
-** storage media on which the database file resides.
-**
-** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
-** which if set disables file locking in rollback journal modes. This
-** is useful for accessing a database on a filesystem that does not
-** support locking. Caution: Database corruption might result if two
-** or more processes write to the same database and any one of those
-** processes uses nolock=1.
-**
-** <li> <b>immutable</b>: ^The immutable parameter is a boolean query
-** parameter that indicates that the database file is stored on
-** read-only media. ^When immutable is set, SQLite assumes that the
-** database file cannot be changed, even by a process with higher
-** privilege, and so the database is opened read-only and all locking
-** and change detection is disabled. Caution: Setting the immutable
-** property on a database file that does in fact change can result
-** in incorrect query results and/or [SQLITE_CORRUPT] errors.
-** See also: [SQLITE_IOCAP_IMMUTABLE].
-**
-** </ul>
-**
-** ^Specifying an unknown parameter in the query component of a URI is not an
-** error. Future versions of SQLite might understand additional query
-** parameters. See "[query parameters with special meaning to SQLite]" for
-** additional information.
-**
-** [[URI filename examples]] <h3>URI filename examples</h3>
-**
-** <table border="1" align=center cellpadding=5>
-** <tr><th> URI filenames <th> Results
-** <tr><td> file:data.db <td>
-** Open the file "data.db" in the current directory.
-** <tr><td> file:/home/fred/data.db<br>
-** file:///home/fred/data.db <br>
-** file://localhost/home/fred/data.db <br> <td>
-** Open the database file "/home/fred/data.db".
-** <tr><td> file://darkstar/home/fred/data.db <td>
-** An error. "darkstar" is not a recognized authority.
-** <tr><td style="white-space:nowrap">
-** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
-** <td> Windows only: Open the file "data.db" on fred's desktop on drive
-** C:. Note that the %20 escaping in this example is not strictly
-** necessary - space characters can be used literally
-** in URI filenames.
-** <tr><td> file:data.db?mode=ro&cache=private <td>
-** Open file "data.db" in the current directory for read-only access.
-** Regardless of whether or not shared-cache mode is enabled by
-** default, use a private cache.
-** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
-** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
-** that uses dot-files in place of posix advisory locking.
-** <tr><td> file:data.db?mode=readonly <td>
-** An error. "readonly" is not a valid option for the "mode" parameter.
-** </table>
-**
-** ^URI hexadecimal escape sequences (%HH) are supported within the path and
-** query components of a URI. A hexadecimal escape sequence consists of a
-** percent sign - "%" - followed by exactly two hexadecimal digits
-** specifying an octet value. ^Before the path or query components of a
-** URI filename are interpreted, they are encoded using UTF-8 and all
-** hexadecimal escape sequences replaced by a single byte containing the
-** corresponding octet. If this process generates an invalid UTF-8 encoding,
-** the results are undefined.
-**
-** <b>Note to Windows users:</b> The encoding used for the filename argument
-** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
-** codepage is currently defined. Filenames containing international
-** characters must be converted to UTF-8 prior to passing them into
-** sqlite3_open() or sqlite3_open_v2().
-**
-** <b>Note to Windows Runtime users:</b> The temporary directory must be set
-** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various
-** features that require the use of temporary files may fail.
-**
-** See also: [sqlite3_temp_directory]
-*/
-int sqlite3_open(
- const char *filename, /* Database filename (UTF-8) */
- sqlite3 **ppDb /* OUT: SQLite db handle */
-);
-int sqlite3_open16(
- const void *filename, /* Database filename (UTF-16) */
- sqlite3 **ppDb /* OUT: SQLite db handle */
-);
-int sqlite3_open_v2(
- const char *filename, /* Database filename (UTF-8) */
- sqlite3 **ppDb, /* OUT: SQLite db handle */
- int flags, /* Flags */
- const char *zVfs /* Name of VFS module to use */
-);
-
-/*
-** CAPI3REF: Obtain Values For URI Parameters
-**
-** These are utility routines, useful to VFS implementations, that check
-** to see if a database file was a URI that contained a specific query
-** parameter, and if so obtains the value of that query parameter.
-**
-** If F is the database filename pointer passed into the xOpen() method of
-** a VFS implementation when the flags parameter to xOpen() has one or
-** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
-** P is the name of the query parameter, then
-** sqlite3_uri_parameter(F,P) returns the value of the P
-** parameter if it exists or a NULL pointer if P does not appear as a
-** query parameter on F. If P is a query parameter of F
-** has no explicit value, then sqlite3_uri_parameter(F,P) returns
-** a pointer to an empty string.
-**
-** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
-** parameter and returns true (1) or false (0) according to the value
-** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
-** value of query parameter P is one of "yes", "true", or "on" in any
-** case or if the value begins with a non-zero number. The
-** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
-** query parameter P is one of "no", "false", or "off" in any case or
-** if the value begins with a numeric zero. If P is not a query
-** parameter on F or if the value of P is does not match any of the
-** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
-**
-** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
-** 64-bit signed integer and returns that integer, or D if P does not
-** exist. If the value of P is something other than an integer, then
-** zero is returned.
-**
-** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
-** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
-** is not a database file pathname pointer that SQLite passed into the xOpen
-** VFS method, then the behavior of this routine is undefined and probably
-** undesirable.
-*/
-const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
-int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
-sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
-
-
-/*
-** CAPI3REF: Error Codes And Messages
-** METHOD: sqlite3
-**
-** ^If the most recent sqlite3_* API call associated with
-** [database connection] D failed, then the sqlite3_errcode(D) interface
-** returns the numeric [result code] or [extended result code] for that
-** API call.
-** If the most recent API call was successful,
-** then the return value from sqlite3_errcode() is undefined.
-** ^The sqlite3_extended_errcode()
-** interface is the same except that it always returns the
-** [extended result code] even when extended result codes are
-** disabled.
-**
-** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
-** text that describes the error, as either UTF-8 or UTF-16 respectively.
-** ^(Memory to hold the error message string is managed internally.
-** The application does not need to worry about freeing the result.
-** However, the error string might be overwritten or deallocated by
-** subsequent calls to other SQLite interface functions.)^
-**
-** ^The sqlite3_errstr() interface returns the English-language text
-** that describes the [result code], as UTF-8.
-** ^(Memory to hold the error message string is managed internally
-** and must not be freed by the application)^.
-**
-** When the serialized [threading mode] is in use, it might be the
-** case that a second error occurs on a separate thread in between
-** the time of the first error and the call to these interfaces.
-** When that happens, the second error will be reported since these
-** interfaces always report the most recent result. To avoid
-** this, each thread can obtain exclusive use of the [database connection] D
-** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning
-** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after
-** all calls to the interfaces listed here are completed.
-**
-** If an interface fails with SQLITE_MISUSE, that means the interface
-** was invoked incorrectly by the application. In that case, the
-** error code and message may or may not be set.
-*/
-int sqlite3_errcode(sqlite3 *db);
-int sqlite3_extended_errcode(sqlite3 *db);
-const char *sqlite3_errmsg(sqlite3*);
-const void *sqlite3_errmsg16(sqlite3*);
-const char *sqlite3_errstr(int);
-
-/*
-** CAPI3REF: Prepared Statement Object
-** KEYWORDS: {prepared statement} {prepared statements}
-**
-** An instance of this object represents a single SQL statement that
-** has been compiled into binary form and is ready to be evaluated.
-**
-** Think of each SQL statement as a separate computer program. The
-** original SQL text is source code. A prepared statement object
-** is the compiled object code. All SQL must be converted into a
-** prepared statement before it can be run.
-**
-** The life-cycle of a prepared statement object usually goes like this:
-**
-** <ol>
-** <li> Create the prepared statement object using [sqlite3_prepare_v2()].
-** <li> Bind values to [parameters] using the sqlite3_bind_*()
-** interfaces.
-** <li> Run the SQL by calling [sqlite3_step()] one or more times.
-** <li> Reset the prepared statement using [sqlite3_reset()] then go back
-** to step 2. Do this zero or more times.
-** <li> Destroy the object using [sqlite3_finalize()].
-** </ol>
-*/
-typedef struct sqlite3_stmt sqlite3_stmt;
-
-/*
-** CAPI3REF: Run-time Limits
-** METHOD: sqlite3
-**
-** ^(This interface allows the size of various constructs to be limited
-** on a connection by connection basis. The first parameter is the
-** [database connection] whose limit is to be set or queried. The
-** second parameter is one of the [limit categories] that define a
-** class of constructs to be size limited. The third parameter is the
-** new limit for that construct.)^
-**
-** ^If the new limit is a negative number, the limit is unchanged.
-** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a
-** [limits | hard upper bound]
-** set at compile-time by a C preprocessor macro called
-** [limits | SQLITE_MAX_<i>NAME</i>].
-** (The "_LIMIT_" in the name is changed to "_MAX_".))^
-** ^Attempts to increase a limit above its hard upper bound are
-** silently truncated to the hard upper bound.
-**
-** ^Regardless of whether or not the limit was changed, the
-** [sqlite3_limit()] interface returns the prior value of the limit.
-** ^Hence, to find the current value of a limit without changing it,
-** simply invoke this interface with the third parameter set to -1.
-**
-** Run-time limits are intended for use in applications that manage
-** both their own internal database and also databases that are controlled
-** by untrusted external sources. An example application might be a
-** web browser that has its own databases for storing history and
-** separate databases controlled by JavaScript applications downloaded
-** off the Internet. The internal databases can be given the
-** large, default limits. Databases managed by external sources can
-** be given much smaller limits designed to prevent a denial of service
-** attack. Developers might also want to use the [sqlite3_set_authorizer()]
-** interface to further control untrusted SQL. The size of the database
-** created by an untrusted script can be contained using the
-** [max_page_count] [PRAGMA].
-**
-** New run-time limit categories may be added in future releases.
-*/
-int sqlite3_limit(sqlite3*, int id, int newVal);
-
-/*
-** CAPI3REF: Run-Time Limit Categories
-** KEYWORDS: {limit category} {*limit categories}
-**
-** These constants define various performance limits
-** that can be lowered at run-time using [sqlite3_limit()].
-** The synopsis of the meanings of the various limits is shown below.
-** Additional information is available at [limits | Limits in SQLite].
-**
-** <dl>
-** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
-** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
-**
-** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
-** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
-**
-** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
-** <dd>The maximum number of columns in a table definition or in the
-** result set of a [SELECT] or the maximum number of columns in an index
-** or in an ORDER BY or GROUP BY clause.</dd>)^
-**
-** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
-** <dd>The maximum depth of the parse tree on any expression.</dd>)^
-**
-** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
-** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
-**
-** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
-** <dd>The maximum number of instructions in a virtual machine program
-** used to implement an SQL statement. If [sqlite3_prepare_v2()] or
-** the equivalent tries to allocate space for more than this many opcodes
-** in a single prepared statement, an SQLITE_NOMEM error is returned.</dd>)^
-**
-** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
-** <dd>The maximum number of arguments on a function.</dd>)^
-**
-** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
-** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
-**
-** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
-** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
-** <dd>The maximum length of the pattern argument to the [LIKE] or
-** [GLOB] operators.</dd>)^
-**
-** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
-** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
-** <dd>The maximum index number of any [parameter] in an SQL statement.)^
-**
-** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
-** <dd>The maximum depth of recursion for triggers.</dd>)^
-**
-** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
-** <dd>The maximum number of auxiliary worker threads that a single
-** [prepared statement] may start.</dd>)^
-** </dl>
-*/
-#define SQLITE_LIMIT_LENGTH 0
-#define SQLITE_LIMIT_SQL_LENGTH 1
-#define SQLITE_LIMIT_COLUMN 2
-#define SQLITE_LIMIT_EXPR_DEPTH 3
-#define SQLITE_LIMIT_COMPOUND_SELECT 4
-#define SQLITE_LIMIT_VDBE_OP 5
-#define SQLITE_LIMIT_FUNCTION_ARG 6
-#define SQLITE_LIMIT_ATTACHED 7
-#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
-#define SQLITE_LIMIT_VARIABLE_NUMBER 9
-#define SQLITE_LIMIT_TRIGGER_DEPTH 10
-#define SQLITE_LIMIT_WORKER_THREADS 11
-
-/*
-** CAPI3REF: Prepare Flags
-**
-** These constants define various flags that can be passed into
-** "prepFlags" parameter of the [sqlite3_prepare_v3()] and
-** [sqlite3_prepare16_v3()] interfaces.
-**
-** New flags may be added in future releases of SQLite.
-**
-** <dl>
-** [[SQLITE_PREPARE_PERSISTENT]] ^(<dt>SQLITE_PREPARE_PERSISTENT</dt>
-** <dd>The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner
-** that the prepared statement will be retained for a long time and
-** probably reused many times.)^ ^Without this flag, [sqlite3_prepare_v3()]
-** and [sqlite3_prepare16_v3()] assume that the prepared statement will
-** be used just once or at most a few times and then destroyed using
-** [sqlite3_finalize()] relatively soon. The current implementation acts
-** on this hint by avoiding the use of [lookaside memory] so as not to
-** deplete the limited store of lookaside memory. Future versions of
-** SQLite may act on this hint differently.
-** </dl>
-*/
-#define SQLITE_PREPARE_PERSISTENT 0x01
-
-/*
-** CAPI3REF: Compiling An SQL Statement
-** KEYWORDS: {SQL statement compiler}
-** METHOD: sqlite3
-** CONSTRUCTOR: sqlite3_stmt
-**
-** To execute an SQL statement, it must first be compiled into a byte-code
-** program using one of these routines. Or, in other words, these routines
-** are constructors for the [prepared statement] object.
-**
-** The preferred routine to use is [sqlite3_prepare_v2()]. The
-** [sqlite3_prepare()] interface is legacy and should be avoided.
-** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
-** for special purposes.
-**
-** The use of the UTF-8 interfaces is preferred, as SQLite currently
-** does all parsing using UTF-8. The UTF-16 interfaces are provided
-** as a convenience. The UTF-16 interfaces work by converting the
-** input text into UTF-8, then invoking the corresponding UTF-8 interface.
-**
-** The first argument, "db", is a [database connection] obtained from a
-** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or
-** [sqlite3_open16()]. The database connection must not have been closed.
-**
-** The second argument, "zSql", is the statement to be compiled, encoded
-** as either UTF-8 or UTF-16. The sqlite3_prepare(), sqlite3_prepare_v2(),
-** and sqlite3_prepare_v3()
-** interfaces use UTF-8, and sqlite3_prepare16(), sqlite3_prepare16_v2(),
-** and sqlite3_prepare16_v3() use UTF-16.
-**
-** ^If the nByte argument is negative, then zSql is read up to the
-** first zero terminator. ^If nByte is positive, then it is the
-** number of bytes read from zSql. ^If nByte is zero, then no prepared
-** statement is generated.
-** If the caller knows that the supplied string is nul-terminated, then
-** there is a small performance advantage to passing an nByte parameter that
-** is the number of bytes in the input string <i>including</i>
-** the nul-terminator.
-**
-** ^If pzTail is not NULL then *pzTail is made to point to the first byte
-** past the end of the first SQL statement in zSql. These routines only
-** compile the first statement in zSql, so *pzTail is left pointing to
-** what remains uncompiled.
-**
-** ^*ppStmt is left pointing to a compiled [prepared statement] that can be
-** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set
-** to NULL. ^If the input text contains no SQL (if the input is an empty
-** string or a comment) then *ppStmt is set to NULL.
-** The calling procedure is responsible for deleting the compiled
-** SQL statement using [sqlite3_finalize()] after it has finished with it.
-** ppStmt may not be NULL.
-**
-** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK];
-** otherwise an [error code] is returned.
-**
-** The sqlite3_prepare_v2(), sqlite3_prepare_v3(), sqlite3_prepare16_v2(),
-** and sqlite3_prepare16_v3() interfaces are recommended for all new programs.
-** The older interfaces (sqlite3_prepare() and sqlite3_prepare16())
-** are retained for backwards compatibility, but their use is discouraged.
-** ^In the "vX" interfaces, the prepared statement
-** that is returned (the [sqlite3_stmt] object) contains a copy of the
-** original SQL text. This causes the [sqlite3_step()] interface to
-** behave differently in three ways:
-**
-** <ol>
-** <li>
-** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it
-** always used to do, [sqlite3_step()] will automatically recompile the SQL
-** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY]
-** retries will occur before sqlite3_step() gives up and returns an error.
-** </li>
-**
-** <li>
-** ^When an error occurs, [sqlite3_step()] will return one of the detailed
-** [error codes] or [extended error codes]. ^The legacy behavior was that
-** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code
-** and the application would have to make a second call to [sqlite3_reset()]
-** in order to find the underlying cause of the problem. With the "v2" prepare
-** interfaces, the underlying reason for the error is returned immediately.
-** </li>
-**
-** <li>
-** ^If the specific value bound to [parameter | host parameter] in the
-** WHERE clause might influence the choice of query plan for a statement,
-** then the statement will be automatically recompiled, as if there had been
-** a schema change, on the first [sqlite3_step()] call following any change
-** to the [sqlite3_bind_text | bindings] of that [parameter].
-** ^The specific value of WHERE-clause [parameter] might influence the
-** choice of query plan if the parameter is the left-hand side of a [LIKE]
-** or [GLOB] operator or if the parameter is compared to an indexed column
-** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
-** </li>
-** </ol>
-**
-** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having
-** the extra prepFlags parameter, which is a bit array consisting of zero or
-** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The
-** sqlite3_prepare_v2() interface works exactly the same as
-** sqlite3_prepare_v3() with a zero prepFlags parameter.
-*/
-int sqlite3_prepare(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL statement, UTF-8 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const char **pzTail /* OUT: Pointer to unused portion of zSql */
-);
-int sqlite3_prepare_v2(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL statement, UTF-8 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const char **pzTail /* OUT: Pointer to unused portion of zSql */
-);
-int sqlite3_prepare_v3(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL statement, UTF-8 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const char **pzTail /* OUT: Pointer to unused portion of zSql */
-);
-int sqlite3_prepare16(
- sqlite3 *db, /* Database handle */
- const void *zSql, /* SQL statement, UTF-16 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const void **pzTail /* OUT: Pointer to unused portion of zSql */
-);
-int sqlite3_prepare16_v2(
- sqlite3 *db, /* Database handle */
- const void *zSql, /* SQL statement, UTF-16 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const void **pzTail /* OUT: Pointer to unused portion of zSql */
-);
-int sqlite3_prepare16_v3(
- sqlite3 *db, /* Database handle */
- const void *zSql, /* SQL statement, UTF-16 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const void **pzTail /* OUT: Pointer to unused portion of zSql */
-);
-
-/*
-** CAPI3REF: Retrieving Statement SQL
-** METHOD: sqlite3_stmt
-**
-** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8
-** SQL text used to create [prepared statement] P if P was
-** created by [sqlite3_prepare_v2()], [sqlite3_prepare_v3()],
-** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()].
-** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
-** string containing the SQL text of prepared statement P with
-** [bound parameters] expanded.
-**
-** ^(For example, if a prepared statement is created using the SQL
-** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345
-** and parameter :xyz is unbound, then sqlite3_sql() will return
-** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql()
-** will return "SELECT 2345,NULL".)^
-**
-** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory
-** is available to hold the result, or if the result would exceed the
-** the maximum string length determined by the [SQLITE_LIMIT_LENGTH].
-**
-** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of
-** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
-** option causes sqlite3_expanded_sql() to always return NULL.
-**
-** ^The string returned by sqlite3_sql(P) is managed by SQLite and is
-** automatically freed when the prepared statement is finalized.
-** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
-** is obtained from [sqlite3_malloc()] and must be free by the application
-** by passing it to [sqlite3_free()].
-*/
-const char *sqlite3_sql(sqlite3_stmt *pStmt);
-char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
-
-/*
-** CAPI3REF: Determine If An SQL Statement Writes The Database
-** METHOD: sqlite3_stmt
-**
-** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
-** and only if the [prepared statement] X makes no direct changes to
-** the content of the database file.
-**
-** Note that [application-defined SQL functions] or
-** [virtual tables] might change the database indirectly as a side effect.
-** ^(For example, if an application defines a function "eval()" that
-** calls [sqlite3_exec()], then the following SQL statement would
-** change the database file through side-effects:
-**
-** <blockquote><pre>
-** SELECT eval('DELETE FROM t1') FROM t2;
-** </pre></blockquote>
-**
-** But because the [SELECT] statement does not change the database file
-** directly, sqlite3_stmt_readonly() would still return true.)^
-**
-** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
-** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
-** since the statements themselves do not actually modify the database but
-** rather they control the timing of when other statements modify the
-** database. ^The [ATTACH] and [DETACH] statements also cause
-** sqlite3_stmt_readonly() to return true since, while those statements
-** change the configuration of a database connection, they do not make
-** changes to the content of the database files on disk.
-** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
-** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
-** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
-** sqlite3_stmt_readonly() returns false for those commands.
-*/
-int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
-
-/*
-** CAPI3REF: Determine If A Prepared Statement Has Been Reset
-** METHOD: sqlite3_stmt
-**
-** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
-** [prepared statement] S has been stepped at least once using
-** [sqlite3_step(S)] but has neither run to completion (returned
-** [SQLITE_DONE] from [sqlite3_step(S)]) nor
-** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S)
-** interface returns false if S is a NULL pointer. If S is not a
-** NULL pointer and is not a pointer to a valid [prepared statement]
-** object, then the behavior is undefined and probably undesirable.
-**
-** This interface can be used in combination [sqlite3_next_stmt()]
-** to locate all prepared statements associated with a database
-** connection that are in need of being reset. This can be used,
-** for example, in diagnostic routines to search for prepared
-** statements that are holding a transaction open.
-*/
-int sqlite3_stmt_busy(sqlite3_stmt*);
-
-/*
-** CAPI3REF: Dynamically Typed Value Object
-** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
-**
-** SQLite uses the sqlite3_value object to represent all values
-** that can be stored in a database table. SQLite uses dynamic typing
-** for the values it stores. ^Values stored in sqlite3_value objects
-** can be integers, floating point values, strings, BLOBs, or NULL.
-**
-** An sqlite3_value object may be either "protected" or "unprotected".
-** Some interfaces require a protected sqlite3_value. Other interfaces
-** will accept either a protected or an unprotected sqlite3_value.
-** Every interface that accepts sqlite3_value arguments specifies
-** whether or not it requires a protected sqlite3_value. The
-** [sqlite3_value_dup()] interface can be used to construct a new
-** protected sqlite3_value from an unprotected sqlite3_value.
-**
-** The terms "protected" and "unprotected" refer to whether or not
-** a mutex is held. An internal mutex is held for a protected
-** sqlite3_value object but no mutex is held for an unprotected
-** sqlite3_value object. If SQLite is compiled to be single-threaded
-** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
-** or if SQLite is run in one of reduced mutex modes
-** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
-** then there is no distinction between protected and unprotected
-** sqlite3_value objects and they can be used interchangeably. However,
-** for maximum code portability it is recommended that applications
-** still make the distinction between protected and unprotected
-** sqlite3_value objects even when not strictly required.
-**
-** ^The sqlite3_value objects that are passed as parameters into the
-** implementation of [application-defined SQL functions] are protected.
-** ^The sqlite3_value object returned by
-** [sqlite3_column_value()] is unprotected.
-** Unprotected sqlite3_value objects may only be used as arguments
-** to [sqlite3_result_value()], [sqlite3_bind_value()], and
-** [sqlite3_value_dup()].
-** The [sqlite3_value_blob | sqlite3_value_type()] family of
-** interfaces require protected sqlite3_value objects.
-*/
-typedef struct sqlite3_value sqlite3_value;
-
-/*
-** CAPI3REF: SQL Function Context Object
-**
-** The context in which an SQL function executes is stored in an
-** sqlite3_context object. ^A pointer to an sqlite3_context object
-** is always first parameter to [application-defined SQL functions].
-** The application-defined SQL function implementation will pass this
-** pointer through into calls to [sqlite3_result_int | sqlite3_result()],
-** [sqlite3_aggregate_context()], [sqlite3_user_data()],
-** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()],
-** and/or [sqlite3_set_auxdata()].
-*/
-typedef struct sqlite3_context sqlite3_context;
-
-/*
-** CAPI3REF: Binding Values To Prepared Statements
-** KEYWORDS: {host parameter} {host parameters} {host parameter name}
-** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
-** METHOD: sqlite3_stmt
-**
-** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
-** literals may be replaced by a [parameter] that matches one of following
-** templates:
-**
-** <ul>
-** <li> ?
-** <li> ?NNN
-** <li> :VVV
-** <li> @VVV
-** <li> $VVV
-** </ul>
-**
-** In the templates above, NNN represents an integer literal,
-** and VVV represents an alphanumeric identifier.)^ ^The values of these
-** parameters (also called "host parameter names" or "SQL parameters")
-** can be set using the sqlite3_bind_*() routines defined here.
-**
-** ^The first argument to the sqlite3_bind_*() routines is always
-** a pointer to the [sqlite3_stmt] object returned from
-** [sqlite3_prepare_v2()] or its variants.
-**
-** ^The second argument is the index of the SQL parameter to be set.
-** ^The leftmost SQL parameter has an index of 1. ^When the same named
-** SQL parameter is used more than once, second and subsequent
-** occurrences have the same index as the first occurrence.
-** ^The index for named parameters can be looked up using the
-** [sqlite3_bind_parameter_index()] API if desired. ^The index
-** for "?NNN" parameters is the value of NNN.
-** ^The NNN value must be between 1 and the [sqlite3_limit()]
-** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
-**
-** ^The third argument is the value to bind to the parameter.
-** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
-** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
-** is ignored and the end result is the same as sqlite3_bind_null().
-**
-** ^(In those routines that have a fourth argument, its value is the
-** number of bytes in the parameter. To be clear: the value is the
-** number of <u>bytes</u> in the value, not the number of characters.)^
-** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
-** is negative, then the length of the string is
-** the number of bytes up to the first zero terminator.
-** If the fourth parameter to sqlite3_bind_blob() is negative, then
-** the behavior is undefined.
-** If a non-negative fourth parameter is provided to sqlite3_bind_text()
-** or sqlite3_bind_text16() or sqlite3_bind_text64() then
-** that parameter must be the byte offset
-** where the NUL terminator would occur assuming the string were NUL
-** terminated. If any NUL characters occur at byte offsets less than
-** the value of the fourth parameter then the resulting string value will
-** contain embedded NULs. The result of expressions involving strings
-** with embedded NULs is undefined.
-**
-** ^The fifth argument to the BLOB and string binding interfaces
-** is a destructor used to dispose of the BLOB or
-** string after SQLite has finished with it. ^The destructor is called
-** to dispose of the BLOB or string even if the call to bind API fails.
-** ^If the fifth argument is
-** the special value [SQLITE_STATIC], then SQLite assumes that the
-** information is in static, unmanaged space and does not need to be freed.
-** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
-** SQLite makes its own private copy of the data immediately, before
-** the sqlite3_bind_*() routine returns.
-**
-** ^The sixth argument to sqlite3_bind_text64() must be one of
-** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
-** to specify the encoding of the text in the third parameter. If
-** the sixth argument to sqlite3_bind_text64() is not one of the
-** allowed values shown above, or if the text encoding is different
-** from the encoding specified by the sixth parameter, then the behavior
-** is undefined.
-**
-** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
-** is filled with zeroes. ^A zeroblob uses a fixed amount of memory
-** (just an integer to hold its size) while it is being processed.
-** Zeroblobs are intended to serve as placeholders for BLOBs whose
-** content is later written using
-** [sqlite3_blob_open | incremental BLOB I/O] routines.
-** ^A negative value for the zeroblob results in a zero-length BLOB.
-**
-** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in
-** [prepared statement] S to have an SQL value of NULL, but to also be
-** associated with the pointer P of type T. ^D is either a NULL pointer or
-** a pointer to a destructor function for P. ^SQLite will invoke the
-** destructor D with a single argument of P when it is finished using
-** P. The T parameter should be a static string, preferably a string
-** literal. The sqlite3_bind_pointer() routine is part of the
-** [pointer passing interface] added for SQLite 3.20.0.
-**
-** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
-** for the [prepared statement] or with a prepared statement for which
-** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
-** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_()
-** routine is passed a [prepared statement] that has been finalized, the
-** result is undefined and probably harmful.
-**
-** ^Bindings are not cleared by the [sqlite3_reset()] routine.
-** ^Unbound parameters are interpreted as NULL.
-**
-** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an
-** [error code] if anything goes wrong.
-** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB
-** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or
-** [SQLITE_MAX_LENGTH].
-** ^[SQLITE_RANGE] is returned if the parameter
-** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails.
-**
-** See also: [sqlite3_bind_parameter_count()],
-** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
-*/
-int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
-int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
- void(*)(void*));
-int sqlite3_bind_double(sqlite3_stmt*, int, double);
-int sqlite3_bind_int(sqlite3_stmt*, int, int);
-int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
-int sqlite3_bind_null(sqlite3_stmt*, int);
-int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
-int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
-int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
- void(*)(void*), unsigned char encoding);
-int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
-int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
-int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
-int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
-
-/*
-** CAPI3REF: Number Of SQL Parameters
-** METHOD: sqlite3_stmt
-**
-** ^This routine can be used to find the number of [SQL parameters]
-** in a [prepared statement]. SQL parameters are tokens of the
-** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as
-** placeholders for values that are [sqlite3_bind_blob | bound]
-** to the parameters at a later time.
-**
-** ^(This routine actually returns the index of the largest (rightmost)
-** parameter. For all forms except ?NNN, this will correspond to the
-** number of unique parameters. If parameters of the ?NNN form are used,
-** there may be gaps in the list.)^
-**
-** See also: [sqlite3_bind_blob|sqlite3_bind()],
-** [sqlite3_bind_parameter_name()], and
-** [sqlite3_bind_parameter_index()].
-*/
-int sqlite3_bind_parameter_count(sqlite3_stmt*);
-
-/*
-** CAPI3REF: Name Of A Host Parameter
-** METHOD: sqlite3_stmt
-**
-** ^The sqlite3_bind_parameter_name(P,N) interface returns
-** the name of the N-th [SQL parameter] in the [prepared statement] P.
-** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA"
-** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA"
-** respectively.
-** In other words, the initial ":" or "$" or "@" or "?"
-** is included as part of the name.)^
-** ^Parameters of the form "?" without a following integer have no name
-** and are referred to as "nameless" or "anonymous parameters".
-**
-** ^The first host parameter has an index of 1, not 0.
-**
-** ^If the value N is out of range or if the N-th parameter is
-** nameless, then NULL is returned. ^The returned string is
-** always in UTF-8 encoding even if the named parameter was
-** originally specified as UTF-16 in [sqlite3_prepare16()],
-** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()].
-**
-** See also: [sqlite3_bind_blob|sqlite3_bind()],
-** [sqlite3_bind_parameter_count()], and
-** [sqlite3_bind_parameter_index()].
-*/
-const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
-
-/*
-** CAPI3REF: Index Of A Parameter With A Given Name
-** METHOD: sqlite3_stmt
-**
-** ^Return the index of an SQL parameter given its name. ^The
-** index value returned is suitable for use as the second
-** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero
-** is returned if no matching parameter is found. ^The parameter
-** name must be given in UTF-8 even if the original statement
-** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or
-** [sqlite3_prepare16_v3()].
-**
-** See also: [sqlite3_bind_blob|sqlite3_bind()],
-** [sqlite3_bind_parameter_count()], and
-** [sqlite3_bind_parameter_name()].
-*/
-int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
-
-/*
-** CAPI3REF: Reset All Bindings On A Prepared Statement
-** METHOD: sqlite3_stmt
-**
-** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset
-** the [sqlite3_bind_blob | bindings] on a [prepared statement].
-** ^Use this routine to reset all host parameters to NULL.
-*/
-int sqlite3_clear_bindings(sqlite3_stmt*);
-
-/*
-** CAPI3REF: Number Of Columns In A Result Set
-** METHOD: sqlite3_stmt
-**
-** ^Return the number of columns in the result set returned by the
-** [prepared statement]. ^If this routine returns 0, that means the
-** [prepared statement] returns no data (for example an [UPDATE]).
-** ^However, just because this routine returns a positive number does not
-** mean that one or more rows of data will be returned. ^A SELECT statement
-** will always have a positive sqlite3_column_count() but depending on the
-** WHERE clause constraints and the table content, it might return no rows.
-**
-** See also: [sqlite3_data_count()]
-*/
-int sqlite3_column_count(sqlite3_stmt *pStmt);
-
-/*
-** CAPI3REF: Column Names In A Result Set
-** METHOD: sqlite3_stmt
-**
-** ^These routines return the name assigned to a particular column
-** in the result set of a [SELECT] statement. ^The sqlite3_column_name()
-** interface returns a pointer to a zero-terminated UTF-8 string
-** and sqlite3_column_name16() returns a pointer to a zero-terminated
-** UTF-16 string. ^The first parameter is the [prepared statement]
-** that implements the [SELECT] statement. ^The second parameter is the
-** column number. ^The leftmost column is number 0.
-**
-** ^The returned string pointer is valid until either the [prepared statement]
-** is destroyed by [sqlite3_finalize()] or until the statement is automatically
-** reprepared by the first call to [sqlite3_step()] for a particular run
-** or until the next call to
-** sqlite3_column_name() or sqlite3_column_name16() on the same column.
-**
-** ^If sqlite3_malloc() fails during the processing of either routine
-** (for example during a conversion from UTF-8 to UTF-16) then a
-** NULL pointer is returned.
-**
-** ^The name of a result column is the value of the "AS" clause for
-** that column, if there is an AS clause. If there is no AS clause
-** then the name of the column is unspecified and may change from
-** one release of SQLite to the next.
-*/
-const char *sqlite3_column_name(sqlite3_stmt*, int N);
-const void *sqlite3_column_name16(sqlite3_stmt*, int N);
-
-/*
-** CAPI3REF: Source Of Data In A Query Result
-** METHOD: sqlite3_stmt
-**
-** ^These routines provide a means to determine the database, table, and
-** table column that is the origin of a particular result column in
-** [SELECT] statement.
-** ^The name of the database or table or column can be returned as
-** either a UTF-8 or UTF-16 string. ^The _database_ routines return
-** the database name, the _table_ routines return the table name, and
-** the origin_ routines return the column name.
-** ^The returned string is valid until the [prepared statement] is destroyed
-** using [sqlite3_finalize()] or until the statement is automatically
-** reprepared by the first call to [sqlite3_step()] for a particular run
-** or until the same information is requested
-** again in a different encoding.
-**
-** ^The names returned are the original un-aliased names of the
-** database, table, and column.
-**
-** ^The first argument to these interfaces is a [prepared statement].
-** ^These functions return information about the Nth result column returned by
-** the statement, where N is the second function argument.
-** ^The left-most column is column 0 for these routines.
-**
-** ^If the Nth column returned by the statement is an expression or
-** subquery and is not a column value, then all of these functions return
-** NULL. ^These routine might also return NULL if a memory allocation error
-** occurs. ^Otherwise, they return the name of the attached database, table,
-** or column that query result column was extracted from.
-**
-** ^As with all other SQLite APIs, those whose names end with "16" return
-** UTF-16 encoded strings and the other functions return UTF-8.
-**
-** ^These APIs are only available if the library was compiled with the
-** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
-**
-** If two or more threads call one or more of these routines against the same
-** prepared statement and column at the same time then the results are
-** undefined.
-**
-** If two or more threads call one or more
-** [sqlite3_column_database_name | column metadata interfaces]
-** for the same [prepared statement] and result column
-** at the same time then the results are undefined.
-*/
-const char *sqlite3_column_database_name(sqlite3_stmt*,int);
-const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
-const char *sqlite3_column_table_name(sqlite3_stmt*,int);
-const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
-const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
-const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
-
-/*
-** CAPI3REF: Declared Datatype Of A Query Result
-** METHOD: sqlite3_stmt
-**
-** ^(The first parameter is a [prepared statement].
-** If this statement is a [SELECT] statement and the Nth column of the
-** returned result set of that [SELECT] is a table column (not an
-** expression or subquery) then the declared type of the table
-** column is returned.)^ ^If the Nth column of the result set is an
-** expression or subquery, then a NULL pointer is returned.
-** ^The returned string is always UTF-8 encoded.
-**
-** ^(For example, given the database schema:
-**
-** CREATE TABLE t1(c1 VARIANT);
-**
-** and the following statement to be compiled:
-**
-** SELECT c1 + 1, c1 FROM t1;
-**
-** this routine would return the string "VARIANT" for the second result
-** column (i==1), and a NULL pointer for the first result column (i==0).)^
-**
-** ^SQLite uses dynamic run-time typing. ^So just because a column
-** is declared to contain a particular type does not mean that the
-** data stored in that column is of the declared type. SQLite is
-** strongly typed, but the typing is dynamic not static. ^Type
-** is associated with individual values, not with the containers
-** used to hold those values.
-*/
-const char *sqlite3_column_decltype(sqlite3_stmt*,int);
-const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
-
-/*
-** CAPI3REF: Evaluate An SQL Statement
-** METHOD: sqlite3_stmt
-**
-** After a [prepared statement] has been prepared using any of
-** [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()],
-** or [sqlite3_prepare16_v3()] or one of the legacy
-** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function
-** must be called one or more times to evaluate the statement.
-**
-** The details of the behavior of the sqlite3_step() interface depend
-** on whether the statement was prepared using the newer "vX" interfaces
-** [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()],
-** [sqlite3_prepare16_v2()] or the older legacy
-** interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
-** new "vX" interface is recommended for new applications but the legacy
-** interface will continue to be supported.
-**
-** ^In the legacy interface, the return value will be either [SQLITE_BUSY],
-** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE].
-** ^With the "v2" interface, any of the other [result codes] or
-** [extended result codes] might be returned as well.
-**
-** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
-** database locks it needs to do its job. ^If the statement is a [COMMIT]
-** or occurs outside of an explicit transaction, then you can retry the
-** statement. If the statement is not a [COMMIT] and occurs within an
-** explicit transaction then you should rollback the transaction before
-** continuing.
-**
-** ^[SQLITE_DONE] means that the statement has finished executing
-** successfully. sqlite3_step() should not be called again on this virtual
-** machine without first calling [sqlite3_reset()] to reset the virtual
-** machine back to its initial state.
-**
-** ^If the SQL statement being executed returns any data, then [SQLITE_ROW]
-** is returned each time a new row of data is ready for processing by the
-** caller. The values may be accessed using the [column access functions].
-** sqlite3_step() is called again to retrieve the next row of data.
-**
-** ^[SQLITE_ERROR] means that a run-time error (such as a constraint
-** violation) has occurred. sqlite3_step() should not be called again on
-** the VM. More information may be found by calling [sqlite3_errmsg()].
-** ^With the legacy interface, a more specific error code (for example,
-** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth)
-** can be obtained by calling [sqlite3_reset()] on the
-** [prepared statement]. ^In the "v2" interface,
-** the more specific error code is returned directly by sqlite3_step().
-**
-** [SQLITE_MISUSE] means that the this routine was called inappropriately.
-** Perhaps it was called on a [prepared statement] that has
-** already been [sqlite3_finalize | finalized] or on one that had
-** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could
-** be the case that the same database connection is being used by two or
-** more threads at the same moment in time.
-**
-** For all versions of SQLite up to and including 3.6.23.1, a call to
-** [sqlite3_reset()] was required after sqlite3_step() returned anything
-** other than [SQLITE_ROW] before any subsequent invocation of
-** sqlite3_step(). Failure to reset the prepared statement using
-** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
-** sqlite3_step() began
-** calling [sqlite3_reset()] automatically in this circumstance rather
-** than returning [SQLITE_MISUSE]. This is not considered a compatibility
-** break because any application that ever receives an SQLITE_MISUSE error
-** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
-** can be used to restore the legacy behavior.
-**
-** <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
-** API always returns a generic error code, [SQLITE_ERROR], following any
-** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call
-** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the
-** specific [error codes] that better describes the error.
-** We admit that this is a goofy design. The problem has been fixed
-** with the "v2" interface. If you prepare all of your SQL statements
-** using [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()]
-** or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead
-** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
-** then the more specific [error codes] are returned directly
-** by sqlite3_step(). The use of the "vX" interfaces is recommended.
-*/
-int sqlite3_step(sqlite3_stmt*);
-
-/*
-** CAPI3REF: Number of columns in a result set
-** METHOD: sqlite3_stmt
-**
-** ^The sqlite3_data_count(P) interface returns the number of columns in the
-** current row of the result set of [prepared statement] P.
-** ^If prepared statement P does not have results ready to return
-** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
-** interfaces) then sqlite3_data_count(P) returns 0.
-** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
-** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
-** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P)
-** will return non-zero if previous call to [sqlite3_step](P) returned
-** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
-** where it always returns zero since each step of that multi-step
-** pragma returns 0 columns of data.
-**
-** See also: [sqlite3_column_count()]
-*/
-int sqlite3_data_count(sqlite3_stmt *pStmt);
-
-/*
-** CAPI3REF: Fundamental Datatypes
-** KEYWORDS: SQLITE_TEXT
-**
-** ^(Every value in SQLite has one of five fundamental datatypes:
-**
-** <ul>
-** <li> 64-bit signed integer
-** <li> 64-bit IEEE floating point number
-** <li> string
-** <li> BLOB
-** <li> NULL
-** </ul>)^
-**
-** These constants are codes for each of those types.
-**
-** Note that the SQLITE_TEXT constant was also used in SQLite version 2
-** for a completely different meaning. Software that links against both
-** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not
-** SQLITE_TEXT.
-*/
-#define SQLITE_INTEGER 1
-#define SQLITE_FLOAT 2
-#define SQLITE_BLOB 4
-#define SQLITE_NULL 5
-#ifdef SQLITE_TEXT
-# undef SQLITE_TEXT
-#else
-# define SQLITE_TEXT 3
-#endif
-#define SQLITE3_TEXT 3
-
-/*
-** CAPI3REF: Result Values From A Query
-** KEYWORDS: {column access functions}
-** METHOD: sqlite3_stmt
-**
-** <b>Summary:</b>
-** <blockquote><table border=0 cellpadding=0 cellspacing=0>
-** <tr><td><b>sqlite3_column_blob</b><td>&rarr;<td>BLOB result
-** <tr><td><b>sqlite3_column_double</b><td>&rarr;<td>REAL result
-** <tr><td><b>sqlite3_column_int</b><td>&rarr;<td>32-bit INTEGER result
-** <tr><td><b>sqlite3_column_int64</b><td>&rarr;<td>64-bit INTEGER result
-** <tr><td><b>sqlite3_column_text</b><td>&rarr;<td>UTF-8 TEXT result
-** <tr><td><b>sqlite3_column_text16</b><td>&rarr;<td>UTF-16 TEXT result
-** <tr><td><b>sqlite3_column_value</b><td>&rarr;<td>The result as an
-** [sqlite3_value|unprotected sqlite3_value] object.
-** <tr><td>&nbsp;<td>&nbsp;<td>&nbsp;
-** <tr><td><b>sqlite3_column_bytes</b><td>&rarr;<td>Size of a BLOB
-** or a UTF-8 TEXT result in bytes
-** <tr><td><b>sqlite3_column_bytes16&nbsp;&nbsp;</b>
-** <td>&rarr;&nbsp;&nbsp;<td>Size of UTF-16
-** TEXT in bytes
-** <tr><td><b>sqlite3_column_type</b><td>&rarr;<td>Default
-** datatype of the result
-** </table></blockquote>
-**
-** <b>Details:</b>
-**
-** ^These routines return information about a single column of the current
-** result row of a query. ^In every case the first argument is a pointer
-** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
-** that was returned from [sqlite3_prepare_v2()] or one of its variants)
-** and the second argument is the index of the column for which information
-** should be returned. ^The leftmost column of the result set has the index 0.
-** ^The number of columns in the result can be determined using
-** [sqlite3_column_count()].
-**
-** If the SQL statement does not currently point to a valid row, or if the
-** column index is out of range, the result is undefined.
-** These routines may only be called when the most recent call to
-** [sqlite3_step()] has returned [SQLITE_ROW] and neither
-** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently.
-** If any of these routines are called after [sqlite3_reset()] or
-** [sqlite3_finalize()] or after [sqlite3_step()] has returned
-** something other than [SQLITE_ROW], the results are undefined.
-** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()]
-** are called from a different thread while any of these routines
-** are pending, then the results are undefined.
-**
-** The first six interfaces (_blob, _double, _int, _int64, _text, and _text16)
-** each return the value of a result column in a specific data format. If
-** the result column is not initially in the requested format (for example,
-** if the query returns an integer but the sqlite3_column_text() interface
-** is used to extract the value) then an automatic type conversion is performed.
-**
-** ^The sqlite3_column_type() routine returns the
-** [SQLITE_INTEGER | datatype code] for the initial data type
-** of the result column. ^The returned value is one of [SQLITE_INTEGER],
-** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].
-** The return value of sqlite3_column_type() can be used to decide which
-** of the first six interface should be used to extract the column value.
-** The value returned by sqlite3_column_type() is only meaningful if no
-** automatic type conversions have occurred for the value in question.
-** After a type conversion, the result of calling sqlite3_column_type()
-** is undefined, though harmless. Future
-** versions of SQLite may change the behavior of sqlite3_column_type()
-** following a type conversion.
-**
-** If the result is a BLOB or a TEXT string, then the sqlite3_column_bytes()
-** or sqlite3_column_bytes16() interfaces can be used to determine the size
-** of that BLOB or string.
-**
-** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes()
-** routine returns the number of bytes in that BLOB or string.
-** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts
-** the string to UTF-8 and then returns the number of bytes.
-** ^If the result is a numeric value then sqlite3_column_bytes() uses
-** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns
-** the number of bytes in that string.
-** ^If the result is NULL, then sqlite3_column_bytes() returns zero.
-**
-** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16()
-** routine returns the number of bytes in that BLOB or string.
-** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts
-** the string to UTF-16 and then returns the number of bytes.
-** ^If the result is a numeric value then sqlite3_column_bytes16() uses
-** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns
-** the number of bytes in that string.
-** ^If the result is NULL, then sqlite3_column_bytes16() returns zero.
-**
-** ^The values returned by [sqlite3_column_bytes()] and
-** [sqlite3_column_bytes16()] do not include the zero terminators at the end
-** of the string. ^For clarity: the values returned by
-** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
-** bytes in the string, not the number of characters.
-**
-** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
-** even empty strings, are always zero-terminated. ^The return
-** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
-**
-** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
-** [unprotected sqlite3_value] object. In a multithreaded environment,
-** an unprotected sqlite3_value object may only be used safely with
-** [sqlite3_bind_value()] and [sqlite3_result_value()].
-** If the [unprotected sqlite3_value] object returned by
-** [sqlite3_column_value()] is used in any other way, including calls
-** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
-** or [sqlite3_value_bytes()], the behavior is not threadsafe.
-** Hence, the sqlite3_column_value() interface
-** is normally only useful within the implementation of
-** [application-defined SQL functions] or [virtual tables], not within
-** top-level application code.
-**
-** The these routines may attempt to convert the datatype of the result.
-** ^For example, if the internal representation is FLOAT and a text result
-** is requested, [sqlite3_snprintf()] is used internally to perform the
-** conversion automatically. ^(The following table details the conversions
-** that are applied:
-**
-** <blockquote>
-** <table border="1">
-** <tr><th> Internal<br>Type <th> Requested<br>Type <th> Conversion
-**
-** <tr><td> NULL <td> INTEGER <td> Result is 0
-** <tr><td> NULL <td> FLOAT <td> Result is 0.0
-** <tr><td> NULL <td> TEXT <td> Result is a NULL pointer
-** <tr><td> NULL <td> BLOB <td> Result is a NULL pointer
-** <tr><td> INTEGER <td> FLOAT <td> Convert from integer to float
-** <tr><td> INTEGER <td> TEXT <td> ASCII rendering of the integer
-** <tr><td> INTEGER <td> BLOB <td> Same as INTEGER->TEXT
-** <tr><td> FLOAT <td> INTEGER <td> [CAST] to INTEGER
-** <tr><td> FLOAT <td> TEXT <td> ASCII rendering of the float
-** <tr><td> FLOAT <td> BLOB <td> [CAST] to BLOB
-** <tr><td> TEXT <td> INTEGER <td> [CAST] to INTEGER
-** <tr><td> TEXT <td> FLOAT <td> [CAST] to REAL
-** <tr><td> TEXT <td> BLOB <td> No change
-** <tr><td> BLOB <td> INTEGER <td> [CAST] to INTEGER
-** <tr><td> BLOB <td> FLOAT <td> [CAST] to REAL
-** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
-** </table>
-** </blockquote>)^
-**
-** Note that when type conversions occur, pointers returned by prior
-** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
-** sqlite3_column_text16() may be invalidated.
-** Type conversions and pointer invalidations might occur
-** in the following cases:
-**
-** <ul>
-** <li> The initial content is a BLOB and sqlite3_column_text() or
-** sqlite3_column_text16() is called. A zero-terminator might
-** need to be added to the string.</li>
-** <li> The initial content is UTF-8 text and sqlite3_column_bytes16() or
-** sqlite3_column_text16() is called. The content must be converted
-** to UTF-16.</li>
-** <li> The initial content is UTF-16 text and sqlite3_column_bytes() or
-** sqlite3_column_text() is called. The content must be converted
-** to UTF-8.</li>
-** </ul>
-**
-** ^Conversions between UTF-16be and UTF-16le are always done in place and do
-** not invalidate a prior pointer, though of course the content of the buffer
-** that the prior pointer references will have been modified. Other kinds
-** of conversion are done in place when it is possible, but sometimes they
-** are not possible and in those cases prior pointers are invalidated.
-**
-** The safest policy is to invoke these routines
-** in one of the following ways:
-**
-** <ul>
-** <li>sqlite3_column_text() followed by sqlite3_column_bytes()</li>
-** <li>sqlite3_column_blob() followed by sqlite3_column_bytes()</li>
-** <li>sqlite3_column_text16() followed by sqlite3_column_bytes16()</li>
-** </ul>
-**
-** In other words, you should call sqlite3_column_text(),
-** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result
-** into the desired format, then invoke sqlite3_column_bytes() or
-** sqlite3_column_bytes16() to find the size of the result. Do not mix calls
-** to sqlite3_column_text() or sqlite3_column_blob() with calls to
-** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16()
-** with calls to sqlite3_column_bytes().
-**
-** ^The pointers returned are valid until a type conversion occurs as
-** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
-** [sqlite3_finalize()] is called. ^The memory space used to hold strings
-** and BLOBs is freed automatically. Do not pass the pointers returned
-** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
-** [sqlite3_free()].
-**
-** ^(If a memory allocation error occurs during the evaluation of any
-** of these routines, a default value is returned. The default value
-** is either the integer 0, the floating point number 0.0, or a NULL
-** pointer. Subsequent calls to [sqlite3_errcode()] will return
-** [SQLITE_NOMEM].)^
-*/
-const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-double sqlite3_column_double(sqlite3_stmt*, int iCol);
-int sqlite3_column_int(sqlite3_stmt*, int iCol);
-sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
-const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
-const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
-sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
-int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
-int sqlite3_column_type(sqlite3_stmt*, int iCol);
-
-/*
-** CAPI3REF: Destroy A Prepared Statement Object
-** DESTRUCTOR: sqlite3_stmt
-**
-** ^The sqlite3_finalize() function is called to delete a [prepared statement].
-** ^If the most recent evaluation of the statement encountered no errors
-** or if the statement is never been evaluated, then sqlite3_finalize() returns
-** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
-** sqlite3_finalize(S) returns the appropriate [error code] or
-** [extended error code].
-**
-** ^The sqlite3_finalize(S) routine can be called at any point during
-** the life cycle of [prepared statement] S:
-** before statement S is ever evaluated, after
-** one or more calls to [sqlite3_reset()], or after any call
-** to [sqlite3_step()] regardless of whether or not the statement has
-** completed execution.
-**
-** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.
-**
-** The application must finalize every [prepared statement] in order to avoid
-** resource leaks. It is a grievous error for the application to try to use
-** a prepared statement after it has been finalized. Any use of a prepared
-** statement after it has been finalized can result in undefined and
-** undesirable behavior such as segfaults and heap corruption.
-*/
-int sqlite3_finalize(sqlite3_stmt *pStmt);
-
-/*
-** CAPI3REF: Reset A Prepared Statement Object
-** METHOD: sqlite3_stmt
-**
-** The sqlite3_reset() function is called to reset a [prepared statement]
-** object back to its initial state, ready to be re-executed.
-** ^Any SQL statement variables that had values bound to them using
-** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values.
-** Use [sqlite3_clear_bindings()] to reset the bindings.
-**
-** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S
-** back to the beginning of its program.
-**
-** ^If the most recent call to [sqlite3_step(S)] for the
-** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
-** or if [sqlite3_step(S)] has never before been called on S,
-** then [sqlite3_reset(S)] returns [SQLITE_OK].
-**
-** ^If the most recent call to [sqlite3_step(S)] for the
-** [prepared statement] S indicated an error, then
-** [sqlite3_reset(S)] returns an appropriate [error code].
-**
-** ^The [sqlite3_reset(S)] interface does not change the values
-** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
-*/
-int sqlite3_reset(sqlite3_stmt *pStmt);
-
-/*
-** CAPI3REF: Create Or Redefine SQL Functions
-** KEYWORDS: {function creation routines}
-** KEYWORDS: {application-defined SQL function}
-** KEYWORDS: {application-defined SQL functions}
-** METHOD: sqlite3
-**
-** ^These functions (collectively known as "function creation routines")
-** are used to add SQL functions or aggregates or to redefine the behavior
-** of existing SQL functions or aggregates. The only differences between
-** these routines are the text encoding expected for
-** the second parameter (the name of the function being created)
-** and the presence or absence of a destructor callback for
-** the application data pointer.
-**
-** ^The first parameter is the [database connection] to which the SQL
-** function is to be added. ^If an application uses more than one database
-** connection then application-defined SQL functions must be added
-** to each database connection separately.
-**
-** ^The second parameter is the name of the SQL function to be created or
-** redefined. ^The length of the name is limited to 255 bytes in a UTF-8
-** representation, exclusive of the zero-terminator. ^Note that the name
-** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
-** ^Any attempt to create a function with a longer name
-** will result in [SQLITE_MISUSE] being returned.
-**
-** ^The third parameter (nArg)
-** is the number of arguments that the SQL function or
-** aggregate takes. ^If this parameter is -1, then the SQL function or
-** aggregate may take any number of arguments between 0 and the limit
-** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third
-** parameter is less than -1 or greater than 127 then the behavior is
-** undefined.
-**
-** ^The fourth parameter, eTextRep, specifies what
-** [SQLITE_UTF8 | text encoding] this SQL function prefers for
-** its parameters. The application should set this parameter to
-** [SQLITE_UTF16LE] if the function implementation invokes
-** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
-** implementation invokes [sqlite3_value_text16be()] on an input, or
-** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
-** otherwise. ^The same SQL function may be registered multiple times using
-** different preferred text encodings, with different implementations for
-** each encoding.
-** ^When multiple implementations of the same function are available, SQLite
-** will pick the one that involves the least amount of data conversion.
-**
-** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
-** to signal that the function will always return the same result given
-** the same inputs within a single SQL statement. Most SQL functions are
-** deterministic. The built-in [random()] SQL function is an example of a
-** function that is not deterministic. The SQLite query planner is able to
-** perform additional optimizations on deterministic functions, so use
-** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
-**
-** ^(The fifth parameter is an arbitrary pointer. The implementation of the
-** function can gain access to this pointer using [sqlite3_user_data()].)^
-**
-** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are
-** pointers to C-language functions that implement the SQL function or
-** aggregate. ^A scalar SQL function requires an implementation of the xFunc
-** callback only; NULL pointers must be passed as the xStep and xFinal
-** parameters. ^An aggregate SQL function requires an implementation of xStep
-** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing
-** SQL function or aggregate, pass NULL pointers for all three function
-** callbacks.
-**
-** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
-** then it is destructor for the application data pointer.
-** The destructor is invoked when the function is deleted, either by being
-** overloaded or when the database connection closes.)^
-** ^The destructor is also invoked if the call to
-** sqlite3_create_function_v2() fails.
-** ^When the destructor callback of the tenth parameter is invoked, it
-** is passed a single argument which is a copy of the application data
-** pointer which was the fifth parameter to sqlite3_create_function_v2().
-**
-** ^It is permitted to register multiple implementations of the same
-** functions with the same name but with either differing numbers of
-** arguments or differing preferred text encodings. ^SQLite will use
-** the implementation that most closely matches the way in which the
-** SQL function is used. ^A function implementation with a non-negative
-** nArg parameter is a better match than a function implementation with
-** a negative nArg. ^A function where the preferred text encoding
-** matches the database encoding is a better
-** match than a function where the encoding is different.
-** ^A function where the encoding difference is between UTF16le and UTF16be
-** is a closer match than a function where the encoding difference is
-** between UTF8 and UTF16.
-**
-** ^Built-in functions may be overloaded by new application-defined functions.
-**
-** ^An application-defined function is permitted to call other
-** SQLite interfaces. However, such calls must not
-** close the database connection nor finalize or reset the prepared
-** statement in which the function is running.
-*/
-int sqlite3_create_function(
- sqlite3 *db,
- const char *zFunctionName,
- int nArg,
- int eTextRep,
- void *pApp,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*)
-);
-int sqlite3_create_function16(
- sqlite3 *db,
- const void *zFunctionName,
- int nArg,
- int eTextRep,
- void *pApp,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*)
-);
-int sqlite3_create_function_v2(
- sqlite3 *db,
- const char *zFunctionName,
- int nArg,
- int eTextRep,
- void *pApp,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*),
- void(*xDestroy)(void*)
-);
-
-/*
-** CAPI3REF: Text Encodings
-**
-** These constant define integer codes that represent the various
-** text encodings supported by SQLite.
-*/
-#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
-#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
-#define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */
-#define SQLITE_UTF16 4 /* Use native byte order */
-#define SQLITE_ANY 5 /* Deprecated */
-#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
-
-/*
-** CAPI3REF: Function Flags
-**
-** These constants may be ORed together with the
-** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
-** to [sqlite3_create_function()], [sqlite3_create_function16()], or
-** [sqlite3_create_function_v2()].
-*/
-#define SQLITE_DETERMINISTIC 0x800
-
-/*
-** CAPI3REF: Deprecated Functions
-** DEPRECATED
-**
-** These functions are [deprecated]. In order to maintain
-** backwards compatibility with older code, these functions continue
-** to be supported. However, new applications should avoid
-** the use of these functions. To encourage programmers to avoid
-** these functions, we will not explain what they do.
-*/
-#ifndef SQLITE_OMIT_DEPRECATED
-SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
-SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
-SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
-SQLITE_DEPRECATED int sqlite3_global_recover(void);
-SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
- void*,sqlite3_int64);
-#endif
-
-/*
-** CAPI3REF: Obtaining SQL Values
-** METHOD: sqlite3_value
-**
-** <b>Summary:</b>
-** <blockquote><table border=0 cellpadding=0 cellspacing=0>
-** <tr><td><b>sqlite3_value_blob</b><td>&rarr;<td>BLOB value
-** <tr><td><b>sqlite3_value_double</b><td>&rarr;<td>REAL value
-** <tr><td><b>sqlite3_value_int</b><td>&rarr;<td>32-bit INTEGER value
-** <tr><td><b>sqlite3_value_int64</b><td>&rarr;<td>64-bit INTEGER value
-** <tr><td><b>sqlite3_value_pointer</b><td>&rarr;<td>Pointer value
-** <tr><td><b>sqlite3_value_text</b><td>&rarr;<td>UTF-8 TEXT value
-** <tr><td><b>sqlite3_value_text16</b><td>&rarr;<td>UTF-16 TEXT value in
-** the native byteorder
-** <tr><td><b>sqlite3_value_text16be</b><td>&rarr;<td>UTF-16be TEXT value
-** <tr><td><b>sqlite3_value_text16le</b><td>&rarr;<td>UTF-16le TEXT value
-** <tr><td>&nbsp;<td>&nbsp;<td>&nbsp;
-** <tr><td><b>sqlite3_value_bytes</b><td>&rarr;<td>Size of a BLOB
-** or a UTF-8 TEXT in bytes
-** <tr><td><b>sqlite3_value_bytes16&nbsp;&nbsp;</b>
-** <td>&rarr;&nbsp;&nbsp;<td>Size of UTF-16
-** TEXT in bytes
-** <tr><td><b>sqlite3_value_type</b><td>&rarr;<td>Default
-** datatype of the value
-** <tr><td><b>sqlite3_value_numeric_type&nbsp;&nbsp;</b>
-** <td>&rarr;&nbsp;&nbsp;<td>Best numeric datatype of the value
-** <tr><td><b>sqlite3_value_nochange&nbsp;&nbsp;</b>
-** <td>&rarr;&nbsp;&nbsp;<td>True if the column is unchanged in an UPDATE
-** against a virtual table.
-** </table></blockquote>
-**
-** <b>Details:</b>
-**
-** These routines extract type, size, and content information from
-** [protected sqlite3_value] objects. Protected sqlite3_value objects
-** are used to pass parameter information into implementation of
-** [application-defined SQL functions] and [virtual tables].
-**
-** These routines work only with [protected sqlite3_value] objects.
-** Any attempt to use these routines on an [unprotected sqlite3_value]
-** is not threadsafe.
-**
-** ^These routines work just like the corresponding [column access functions]
-** except that these routines take a single [protected sqlite3_value] object
-** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
-**
-** ^The sqlite3_value_text16() interface extracts a UTF-16 string
-** in the native byte-order of the host machine. ^The
-** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
-** extract UTF-16 strings as big-endian and little-endian respectively.
-**
-** ^If [sqlite3_value] object V was initialized
-** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)]
-** and if X and Y are strings that compare equal according to strcmp(X,Y),
-** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise,
-** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer()
-** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
-**
-** ^(The sqlite3_value_type(V) interface returns the
-** [SQLITE_INTEGER | datatype code] for the initial datatype of the
-** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER],
-** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^
-** Other interfaces might change the datatype for an sqlite3_value object.
-** For example, if the datatype is initially SQLITE_INTEGER and
-** sqlite3_value_text(V) is called to extract a text value for that
-** integer, then subsequent calls to sqlite3_value_type(V) might return
-** SQLITE_TEXT. Whether or not a persistent internal datatype conversion
-** occurs is undefined and may change from one release of SQLite to the next.
-**
-** ^(The sqlite3_value_numeric_type() interface attempts to apply
-** numeric affinity to the value. This means that an attempt is
-** made to convert the value to an integer or floating point. If
-** such a conversion is possible without loss of information (in other
-** words, if the value is a string that looks like a number)
-** then the conversion is performed. Otherwise no conversion occurs.
-** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
-**
-** ^Within the [xUpdate] method of a [virtual table], the
-** sqlite3_value_nochange(X) interface returns true if and only if
-** the column corresponding to X is unchanged by the UPDATE operation
-** that the xUpdate method call was invoked to implement and if
-** and the prior [xColumn] method call that was invoked to extracted
-** the value for that column returned without setting a result (probably
-** because it queried [sqlite3_vtab_nochange()] and found that the column
-** was unchanging). ^Within an [xUpdate] method, any value for which
-** sqlite3_value_nochange(X) is true will in all other respects appear
-** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other
-** than within an [xUpdate] method call for an UPDATE statement, then
-** the return value is arbitrary and meaningless.
-**
-** Please pay particular attention to the fact that the pointer returned
-** from [sqlite3_value_blob()], [sqlite3_value_text()], or
-** [sqlite3_value_text16()] can be invalidated by a subsequent call to
-** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
-** or [sqlite3_value_text16()].
-**
-** These routines must be called from the same thread as
-** the SQL function that supplied the [sqlite3_value*] parameters.
-*/
-const void *sqlite3_value_blob(sqlite3_value*);
-double sqlite3_value_double(sqlite3_value*);
-int sqlite3_value_int(sqlite3_value*);
-sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
-void *sqlite3_value_pointer(sqlite3_value*, const char*);
-const unsigned char *sqlite3_value_text(sqlite3_value*);
-const void *sqlite3_value_text16(sqlite3_value*);
-const void *sqlite3_value_text16le(sqlite3_value*);
-const void *sqlite3_value_text16be(sqlite3_value*);
-int sqlite3_value_bytes(sqlite3_value*);
-int sqlite3_value_bytes16(sqlite3_value*);
-int sqlite3_value_type(sqlite3_value*);
-int sqlite3_value_numeric_type(sqlite3_value*);
-int sqlite3_value_nochange(sqlite3_value*);
-
-/*
-** CAPI3REF: Finding The Subtype Of SQL Values
-** METHOD: sqlite3_value
-**
-** The sqlite3_value_subtype(V) function returns the subtype for
-** an [application-defined SQL function] argument V. The subtype
-** information can be used to pass a limited amount of context from
-** one SQL function to another. Use the [sqlite3_result_subtype()]
-** routine to set the subtype for the return value of an SQL function.
-*/
-unsigned int sqlite3_value_subtype(sqlite3_value*);
-
-/*
-** CAPI3REF: Copy And Free SQL Values
-** METHOD: sqlite3_value
-**
-** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
-** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
-** is a [protected sqlite3_value] object even if the input is not.
-** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
-** memory allocation fails.
-**
-** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object
-** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
-** then sqlite3_value_free(V) is a harmless no-op.
-*/
-sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
-void sqlite3_value_free(sqlite3_value*);
-
-/*
-** CAPI3REF: Obtain Aggregate Function Context
-** METHOD: sqlite3_context
-**
-** Implementations of aggregate SQL functions use this
-** routine to allocate memory for storing their state.
-**
-** ^The first time the sqlite3_aggregate_context(C,N) routine is called
-** for a particular aggregate function, SQLite
-** allocates N of memory, zeroes out that memory, and returns a pointer
-** to the new memory. ^On second and subsequent calls to
-** sqlite3_aggregate_context() for the same aggregate function instance,
-** the same buffer is returned. Sqlite3_aggregate_context() is normally
-** called once for each invocation of the xStep callback and then one
-** last time when the xFinal callback is invoked. ^(When no rows match
-** an aggregate query, the xStep() callback of the aggregate function
-** implementation is never called and xFinal() is called exactly once.
-** In those cases, sqlite3_aggregate_context() might be called for the
-** first time from within xFinal().)^
-**
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
-** when first called if N is less than or equal to zero or if a memory
-** allocate error occurs.
-**
-** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
-** determined by the N parameter on first successful call. Changing the
-** value of N in subsequent call to sqlite3_aggregate_context() within
-** the same aggregate function instance will not resize the memory
-** allocation.)^ Within the xFinal callback, it is customary to set
-** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
-** pointless memory allocations occur.
-**
-** ^SQLite automatically frees the memory allocated by
-** sqlite3_aggregate_context() when the aggregate query concludes.
-**
-** The first parameter must be a copy of the
-** [sqlite3_context | SQL function context] that is the first parameter
-** to the xStep or xFinal callback routine that implements the aggregate
-** function.
-**
-** This routine must be called from the same thread in which
-** the aggregate SQL function is running.
-*/
-void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
-
-/*
-** CAPI3REF: User Data For Functions
-** METHOD: sqlite3_context
-**
-** ^The sqlite3_user_data() interface returns a copy of
-** the pointer that was the pUserData parameter (the 5th parameter)
-** of the [sqlite3_create_function()]
-** and [sqlite3_create_function16()] routines that originally
-** registered the application defined function.
-**
-** This routine must be called from the same thread in which
-** the application-defined function is running.
-*/
-void *sqlite3_user_data(sqlite3_context*);
-
-/*
-** CAPI3REF: Database Connection For Functions
-** METHOD: sqlite3_context
-**
-** ^The sqlite3_context_db_handle() interface returns a copy of
-** the pointer to the [database connection] (the 1st parameter)
-** of the [sqlite3_create_function()]
-** and [sqlite3_create_function16()] routines that originally
-** registered the application defined function.
-*/
-sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
-
-/*
-** CAPI3REF: Function Auxiliary Data
-** METHOD: sqlite3_context
-**
-** These functions may be used by (non-aggregate) SQL functions to
-** associate metadata with argument values. If the same value is passed to
-** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. An example
-** of where this might be useful is in a regular-expression matching
-** function. The compiled version of the regular expression can be stored as
-** metadata associated with the pattern string.
-** Then as long as the pattern string remains the same,
-** the compiled regular expression can be reused on multiple
-** invocations of the same function.
-**
-** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata
-** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
-** value to the application-defined function. ^N is zero for the left-most
-** function argument. ^If there is no metadata
-** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
-** returns a NULL pointer.
-**
-** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
-** argument of the application-defined function. ^Subsequent
-** calls to sqlite3_get_auxdata(C,N) return P from the most recent
-** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
-** NULL if the metadata has been discarded.
-** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
-** SQLite will invoke the destructor function X with parameter P exactly
-** once, when the metadata is discarded.
-** SQLite is free to discard the metadata at any time, including: <ul>
-** <li> ^(when the corresponding function parameter changes)^, or
-** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
-** SQL statement)^, or
-** <li> ^(when sqlite3_set_auxdata() is invoked again on the same
-** parameter)^, or
-** <li> ^(during the original sqlite3_set_auxdata() call when a memory
-** allocation error occurs.)^ </ul>
-**
-** Note the last bullet in particular. The destructor X in
-** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
-** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
-** should be called near the end of the function implementation and the
-** function implementation should not make any use of P after
-** sqlite3_set_auxdata() has been called.
-**
-** ^(In practice, metadata is preserved between function calls for
-** function parameters that are compile-time constants, including literal
-** values and [parameters] and expressions composed from the same.)^
-**
-** The value of the N parameter to these interfaces should be non-negative.
-** Future enhancements may make use of negative N values to define new
-** kinds of function caching behavior.
-**
-** These routines must be called from the same thread in which
-** the SQL function is running.
-*/
-void *sqlite3_get_auxdata(sqlite3_context*, int N);
-void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
-
-
-/*
-** CAPI3REF: Constants Defining Special Destructor Behavior
-**
-** These are special values for the destructor that is passed in as the
-** final argument to routines like [sqlite3_result_blob()]. ^If the destructor
-** argument is SQLITE_STATIC, it means that the content pointer is constant
-** and will never change. It does not need to be destroyed. ^The
-** SQLITE_TRANSIENT value means that the content will likely change in
-** the near future and that SQLite should make its own private copy of
-** the content before returning.
-**
-** The typedef is necessary to work around problems in certain
-** C++ compilers.
-*/
-typedef void (*sqlite3_destructor_type)(void*);
-#define SQLITE_STATIC ((sqlite3_destructor_type)0)
-#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
-
-/*
-** CAPI3REF: Setting The Result Of An SQL Function
-** METHOD: sqlite3_context
-**
-** These routines are used by the xFunc or xFinal callbacks that
-** implement SQL functions and aggregates. See
-** [sqlite3_create_function()] and [sqlite3_create_function16()]
-** for additional information.
-**
-** These functions work very much like the [parameter binding] family of
-** functions used to bind values to host parameters in prepared statements.
-** Refer to the [SQL parameter] documentation for additional information.
-**
-** ^The sqlite3_result_blob() interface sets the result from
-** an application-defined function to be the BLOB whose content is pointed
-** to by the second parameter and which is N bytes long where N is the
-** third parameter.
-**
-** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N)
-** interfaces set the result of the application-defined function to be
-** a BLOB containing all zero bytes and N bytes in size.
-**
-** ^The sqlite3_result_double() interface sets the result from
-** an application-defined function to be a floating point value specified
-** by its 2nd argument.
-**
-** ^The sqlite3_result_error() and sqlite3_result_error16() functions
-** cause the implemented SQL function to throw an exception.
-** ^SQLite uses the string pointed to by the
-** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
-** as the text of an error message. ^SQLite interprets the error
-** message string from sqlite3_result_error() as UTF-8. ^SQLite
-** interprets the string from sqlite3_result_error16() as UTF-16 in native
-** byte order. ^If the third parameter to sqlite3_result_error()
-** or sqlite3_result_error16() is negative then SQLite takes as the error
-** message all text up through the first zero character.
-** ^If the third parameter to sqlite3_result_error() or
-** sqlite3_result_error16() is non-negative then SQLite takes that many
-** bytes (not characters) from the 2nd parameter as the error message.
-** ^The sqlite3_result_error() and sqlite3_result_error16()
-** routines make a private copy of the error message text before
-** they return. Hence, the calling function can deallocate or
-** modify the text after they return without harm.
-** ^The sqlite3_result_error_code() function changes the error code
-** returned by SQLite as a result of an error in a function. ^By default,
-** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error()
-** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
-**
-** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an
-** error indicating that a string or BLOB is too long to represent.
-**
-** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an
-** error indicating that a memory allocation failed.
-**
-** ^The sqlite3_result_int() interface sets the return value
-** of the application-defined function to be the 32-bit signed integer
-** value given in the 2nd argument.
-** ^The sqlite3_result_int64() interface sets the return value
-** of the application-defined function to be the 64-bit signed integer
-** value given in the 2nd argument.
-**
-** ^The sqlite3_result_null() interface sets the return value
-** of the application-defined function to be NULL.
-**
-** ^The sqlite3_result_text(), sqlite3_result_text16(),
-** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
-** set the return value of the application-defined function to be
-** a text string which is represented as UTF-8, UTF-16 native byte order,
-** UTF-16 little endian, or UTF-16 big endian, respectively.
-** ^The sqlite3_result_text64() interface sets the return value of an
-** application-defined function to be a text string in an encoding
-** specified by the fifth (and last) parameter, which must be one
-** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
-** ^SQLite takes the text result from the application from
-** the 2nd parameter of the sqlite3_result_text* interfaces.
-** ^If the 3rd parameter to the sqlite3_result_text* interfaces
-** is negative, then SQLite takes result text from the 2nd parameter
-** through the first zero character.
-** ^If the 3rd parameter to the sqlite3_result_text* interfaces
-** is non-negative, then as many bytes (not characters) of the text
-** pointed to by the 2nd parameter are taken as the application-defined
-** function result. If the 3rd parameter is non-negative, then it
-** must be the byte offset into the string where the NUL terminator would
-** appear if the string where NUL terminated. If any NUL characters occur
-** in the string at a byte offset that is less than the value of the 3rd
-** parameter, then the resulting string will contain embedded NULs and the
-** result of expressions operating on strings with embedded NULs is undefined.
-** ^If the 4th parameter to the sqlite3_result_text* interfaces
-** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
-** function as the destructor on the text or BLOB result when it has
-** finished using that result.
-** ^If the 4th parameter to the sqlite3_result_text* interfaces or to
-** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite
-** assumes that the text or BLOB result is in constant space and does not
-** copy the content of the parameter nor call a destructor on the content
-** when it has finished using that result.
-** ^If the 4th parameter to the sqlite3_result_text* interfaces
-** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT
-** then SQLite makes a copy of the result into space obtained
-** from [sqlite3_malloc()] before it returns.
-**
-** ^The sqlite3_result_value() interface sets the result of
-** the application-defined function to be a copy of the
-** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
-** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
-** so that the [sqlite3_value] specified in the parameter may change or
-** be deallocated after sqlite3_result_value() returns without harm.
-** ^A [protected sqlite3_value] object may always be used where an
-** [unprotected sqlite3_value] object is required, so either
-** kind of [sqlite3_value] object can be used with this interface.
-**
-** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an
-** SQL NULL value, just like [sqlite3_result_null(C)], except that it
-** also associates the host-language pointer P or type T with that
-** NULL value such that the pointer can be retrieved within an
-** [application-defined SQL function] using [sqlite3_value_pointer()].
-** ^If the D parameter is not NULL, then it is a pointer to a destructor
-** for the P parameter. ^SQLite invokes D with P as its only argument
-** when SQLite is finished with P. The T parameter should be a static
-** string and preferably a string literal. The sqlite3_result_pointer()
-** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
-**
-** If these routines are called from within the different thread
-** than the one containing the application-defined function that received
-** the [sqlite3_context] pointer, the results are undefined.
-*/
-void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
-void sqlite3_result_blob64(sqlite3_context*,const void*,
- sqlite3_uint64,void(*)(void*));
-void sqlite3_result_double(sqlite3_context*, double);
-void sqlite3_result_error(sqlite3_context*, const char*, int);
-void sqlite3_result_error16(sqlite3_context*, const void*, int);
-void sqlite3_result_error_toobig(sqlite3_context*);
-void sqlite3_result_error_nomem(sqlite3_context*);
-void sqlite3_result_error_code(sqlite3_context*, int);
-void sqlite3_result_int(sqlite3_context*, int);
-void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
-void sqlite3_result_null(sqlite3_context*);
-void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
-void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
- void(*)(void*), unsigned char encoding);
-void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
-void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
-void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
-void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
-void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
-void sqlite3_result_zeroblob(sqlite3_context*, int n);
-int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
-
-
-/*
-** CAPI3REF: Setting The Subtype Of An SQL Function
-** METHOD: sqlite3_context
-**
-** The sqlite3_result_subtype(C,T) function causes the subtype of
-** the result from the [application-defined SQL function] with
-** [sqlite3_context] C to be the value T. Only the lower 8 bits
-** of the subtype T are preserved in current versions of SQLite;
-** higher order bits are discarded.
-** The number of subtype bytes preserved by SQLite might increase
-** in future releases of SQLite.
-*/
-void sqlite3_result_subtype(sqlite3_context*,unsigned int);
-
-/*
-** CAPI3REF: Define New Collating Sequences
-** METHOD: sqlite3
-**
-** ^These functions add, remove, or modify a [collation] associated
-** with the [database connection] specified as the first argument.
-**
-** ^The name of the collation is a UTF-8 string
-** for sqlite3_create_collation() and sqlite3_create_collation_v2()
-** and a UTF-16 string in native byte order for sqlite3_create_collation16().
-** ^Collation names that compare equal according to [sqlite3_strnicmp()] are
-** considered to be the same name.
-**
-** ^(The third argument (eTextRep) must be one of the constants:
-** <ul>
-** <li> [SQLITE_UTF8],
-** <li> [SQLITE_UTF16LE],
-** <li> [SQLITE_UTF16BE],
-** <li> [SQLITE_UTF16], or
-** <li> [SQLITE_UTF16_ALIGNED].
-** </ul>)^
-** ^The eTextRep argument determines the encoding of strings passed
-** to the collating function callback, xCallback.
-** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
-** force strings to be UTF16 with native byte order.
-** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
-** on an even byte address.
-**
-** ^The fourth argument, pArg, is an application data pointer that is passed
-** through as the first argument to the collating function callback.
-**
-** ^The fifth argument, xCallback, is a pointer to the collating function.
-** ^Multiple collating functions can be registered using the same name but
-** with different eTextRep parameters and SQLite will use whichever
-** function requires the least amount of data transformation.
-** ^If the xCallback argument is NULL then the collating function is
-** deleted. ^When all collating functions having the same name are deleted,
-** that collation is no longer usable.
-**
-** ^The collating function callback is invoked with a copy of the pArg
-** application data pointer and with two strings in the encoding specified
-** by the eTextRep argument. The collating function must return an
-** integer that is negative, zero, or positive
-** if the first string is less than, equal to, or greater than the second,
-** respectively. A collating function must always return the same answer
-** given the same inputs. If two or more collating functions are registered
-** to the same collation name (using different eTextRep values) then all
-** must give an equivalent answer when invoked with equivalent strings.
-** The collating function must obey the following properties for all
-** strings A, B, and C:
-**
-** <ol>
-** <li> If A==B then B==A.
-** <li> If A==B and B==C then A==C.
-** <li> If A&lt;B THEN B&gt;A.
-** <li> If A&lt;B and B&lt;C then A&lt;C.
-** </ol>
-**
-** If a collating function fails any of the above constraints and that
-** collating function is registered and used, then the behavior of SQLite
-** is undefined.
-**
-** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
-** with the addition that the xDestroy callback is invoked on pArg when
-** the collating function is deleted.
-** ^Collating functions are deleted when they are overridden by later
-** calls to the collation creation functions or when the
-** [database connection] is closed using [sqlite3_close()].
-**
-** ^The xDestroy callback is <u>not</u> called if the
-** sqlite3_create_collation_v2() function fails. Applications that invoke
-** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
-** check the return code and dispose of the application data pointer
-** themselves rather than expecting SQLite to deal with it for them.
-** This is different from every other SQLite interface. The inconsistency
-** is unfortunate but cannot be changed without breaking backwards
-** compatibility.
-**
-** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
-*/
-int sqlite3_create_collation(
- sqlite3*,
- const char *zName,
- int eTextRep,
- void *pArg,
- int(*xCompare)(void*,int,const void*,int,const void*)
-);
-int sqlite3_create_collation_v2(
- sqlite3*,
- const char *zName,
- int eTextRep,
- void *pArg,
- int(*xCompare)(void*,int,const void*,int,const void*),
- void(*xDestroy)(void*)
-);
-int sqlite3_create_collation16(
- sqlite3*,
- const void *zName,
- int eTextRep,
- void *pArg,
- int(*xCompare)(void*,int,const void*,int,const void*)
-);
-
-/*
-** CAPI3REF: Collation Needed Callbacks
-** METHOD: sqlite3
-**
-** ^To avoid having to register all collation sequences before a database
-** can be used, a single callback function may be registered with the
-** [database connection] to be invoked whenever an undefined collation
-** sequence is required.
-**
-** ^If the function is registered using the sqlite3_collation_needed() API,
-** then it is passed the names of undefined collation sequences as strings
-** encoded in UTF-8. ^If sqlite3_collation_needed16() is used,
-** the names are passed as UTF-16 in machine native byte order.
-** ^A call to either function replaces the existing collation-needed callback.
-**
-** ^(When the callback is invoked, the first argument passed is a copy
-** of the second argument to sqlite3_collation_needed() or
-** sqlite3_collation_needed16(). The second argument is the database
-** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE],
-** or [SQLITE_UTF16LE], indicating the most desirable form of the collation
-** sequence function required. The fourth parameter is the name of the
-** required collation sequence.)^
-**
-** The callback function should register the desired collation using
-** [sqlite3_create_collation()], [sqlite3_create_collation16()], or
-** [sqlite3_create_collation_v2()].
-*/
-int sqlite3_collation_needed(
- sqlite3*,
- void*,
- void(*)(void*,sqlite3*,int eTextRep,const char*)
-);
-int sqlite3_collation_needed16(
- sqlite3*,
- void*,
- void(*)(void*,sqlite3*,int eTextRep,const void*)
-);
-
-#ifdef SQLITE_HAS_CODEC
-/*
-** Specify the key for an encrypted database. This routine should be
-** called right after sqlite3_open().
-**
-** The code to implement this API is not available in the public release
-** of SQLite.
-*/
-int sqlite3_key(
- sqlite3 *db, /* Database to be rekeyed */
- const void *pKey, int nKey /* The key */
-);
-int sqlite3_key_v2(
- sqlite3 *db, /* Database to be rekeyed */
- const char *zDbName, /* Name of the database */
- const void *pKey, int nKey /* The key */
-);
-
-/*
-** Change the key on an open database. If the current database is not
-** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
-** database is decrypted.
-**
-** The code to implement this API is not available in the public release
-** of SQLite.
-*/
-int sqlite3_rekey(
- sqlite3 *db, /* Database to be rekeyed */
- const void *pKey, int nKey /* The new key */
-);
-int sqlite3_rekey_v2(
- sqlite3 *db, /* Database to be rekeyed */
- const char *zDbName, /* Name of the database */
- const void *pKey, int nKey /* The new key */
-);
-
-/*
-** Specify the activation key for a SEE database. Unless
-** activated, none of the SEE routines will work.
-*/
-void sqlite3_activate_see(
- const char *zPassPhrase /* Activation phrase */
-);
-#endif
-
-#ifdef SQLITE_ENABLE_CEROD
-/*
-** Specify the activation key for a CEROD database. Unless
-** activated, none of the CEROD routines will work.
-*/
-void sqlite3_activate_cerod(
- const char *zPassPhrase /* Activation phrase */
-);
-#endif
-
-/*
-** CAPI3REF: Suspend Execution For A Short Time
-**
-** The sqlite3_sleep() function causes the current thread to suspend execution
-** for at least a number of milliseconds specified in its parameter.
-**
-** If the operating system does not support sleep requests with
-** millisecond time resolution, then the time will be rounded up to
-** the nearest second. The number of milliseconds of sleep actually
-** requested from the operating system is returned.
-**
-** ^SQLite implements this interface by calling the xSleep()
-** method of the default [sqlite3_vfs] object. If the xSleep() method
-** of the default VFS is not implemented correctly, or not implemented at
-** all, then the behavior of sqlite3_sleep() may deviate from the description
-** in the previous paragraphs.
-*/
-int sqlite3_sleep(int);
-
-/*
-** CAPI3REF: Name Of The Folder Holding Temporary Files
-**
-** ^(If this global variable is made to point to a string which is
-** the name of a folder (a.k.a. directory), then all temporary files
-** created by SQLite when using a built-in [sqlite3_vfs | VFS]
-** will be placed in that directory.)^ ^If this variable
-** is a NULL pointer, then SQLite performs a search for an appropriate
-** temporary file directory.
-**
-** Applications are strongly discouraged from using this global variable.
-** It is required to set a temporary folder on Windows Runtime (WinRT).
-** But for all other platforms, it is highly recommended that applications
-** neither read nor write this variable. This global variable is a relic
-** that exists for backwards compatibility of legacy applications and should
-** be avoided in new projects.
-**
-** It is not safe to read or modify this variable in more than one
-** thread at a time. It is not safe to read or modify this variable
-** if a [database connection] is being used at the same time in a separate
-** thread.
-** It is intended that this variable be set once
-** as part of process initialization and before any SQLite interface
-** routines have been called and that this variable remain unchanged
-** thereafter.
-**
-** ^The [temp_store_directory pragma] may modify this variable and cause
-** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
-** the [temp_store_directory pragma] always assumes that any string
-** that this variable points to is held in memory obtained from
-** [sqlite3_malloc] and the pragma may attempt to free that memory
-** using [sqlite3_free].
-** Hence, if this variable is modified directly, either it should be
-** made NULL or made to point to memory obtained from [sqlite3_malloc]
-** or else the use of the [temp_store_directory pragma] should be avoided.
-** Except when requested by the [temp_store_directory pragma], SQLite
-** does not free the memory that sqlite3_temp_directory points to. If
-** the application wants that memory to be freed, it must do
-** so itself, taking care to only do so after all [database connection]
-** objects have been destroyed.
-**
-** <b>Note to Windows Runtime users:</b> The temporary directory must be set
-** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
-** features that require the use of temporary files may fail. Here is an
-** example of how to do this using C++ with the Windows Runtime:
-**
-** <blockquote><pre>
-** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
-** &nbsp; TemporaryFolder->Path->Data();
-** char zPathBuf&#91;MAX_PATH + 1&#93;;
-** memset(zPathBuf, 0, sizeof(zPathBuf));
-** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
-** &nbsp; NULL, NULL);
-** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
-** </pre></blockquote>
-*/
-SQLITE_EXTERN char *sqlite3_temp_directory;
-
-/*
-** CAPI3REF: Name Of The Folder Holding Database Files
-**
-** ^(If this global variable is made to point to a string which is
-** the name of a folder (a.k.a. directory), then all database files
-** specified with a relative pathname and created or accessed by
-** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed
-** to be relative to that directory.)^ ^If this variable is a NULL
-** pointer, then SQLite assumes that all database files specified
-** with a relative pathname are relative to the current directory
-** for the process. Only the windows VFS makes use of this global
-** variable; it is ignored by the unix VFS.
-**
-** Changing the value of this variable while a database connection is
-** open can result in a corrupt database.
-**
-** It is not safe to read or modify this variable in more than one
-** thread at a time. It is not safe to read or modify this variable
-** if a [database connection] is being used at the same time in a separate
-** thread.
-** It is intended that this variable be set once
-** as part of process initialization and before any SQLite interface
-** routines have been called and that this variable remain unchanged
-** thereafter.
-**
-** ^The [data_store_directory pragma] may modify this variable and cause
-** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
-** the [data_store_directory pragma] always assumes that any string
-** that this variable points to is held in memory obtained from
-** [sqlite3_malloc] and the pragma may attempt to free that memory
-** using [sqlite3_free].
-** Hence, if this variable is modified directly, either it should be
-** made NULL or made to point to memory obtained from [sqlite3_malloc]
-** or else the use of the [data_store_directory pragma] should be avoided.
-*/
-SQLITE_EXTERN char *sqlite3_data_directory;
-
-/*
-** CAPI3REF: Win32 Specific Interface
-**
-** These interfaces are available only on Windows. The
-** [sqlite3_win32_set_directory] interface is used to set the value associated
-** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to
-** zValue, depending on the value of the type parameter. The zValue parameter
-** should be NULL to cause the previous value to be freed via [sqlite3_free];
-** a non-NULL value will be copied into memory obtained from [sqlite3_malloc]
-** prior to being used. The [sqlite3_win32_set_directory] interface returns
-** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported,
-** or [SQLITE_NOMEM] if memory could not be allocated. The value of the
-** [sqlite3_data_directory] variable is intended to act as a replacement for
-** the current directory on the sub-platforms of Win32 where that concept is
-** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and
-** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the
-** sqlite3_win32_set_directory interface except the string parameter must be
-** UTF-8 or UTF-16, respectively.
-*/
-int sqlite3_win32_set_directory(
- unsigned long type, /* Identifier for directory being set or reset */
- void *zValue /* New value for directory being set or reset */
-);
-int sqlite3_win32_set_directory8(unsigned long type, const char *zValue);
-int sqlite3_win32_set_directory16(unsigned long type, const void *zValue);
-
-/*
-** CAPI3REF: Win32 Directory Types
-**
-** These macros are only available on Windows. They define the allowed values
-** for the type argument to the [sqlite3_win32_set_directory] interface.
-*/
-#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1
-#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2
-
-/*
-** CAPI3REF: Test For Auto-Commit Mode
-** KEYWORDS: {autocommit mode}
-** METHOD: sqlite3
-**
-** ^The sqlite3_get_autocommit() interface returns non-zero or
-** zero if the given database connection is or is not in autocommit mode,
-** respectively. ^Autocommit mode is on by default.
-** ^Autocommit mode is disabled by a [BEGIN] statement.
-** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK].
-**
-** If certain kinds of errors occur on a statement within a multi-statement
-** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR],
-** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the
-** transaction might be rolled back automatically. The only way to
-** find out whether SQLite automatically rolled back the transaction after
-** an error is to use this function.
-**
-** If another thread changes the autocommit status of the database
-** connection while this routine is running, then the return value
-** is undefined.
-*/
-int sqlite3_get_autocommit(sqlite3*);
-
-/*
-** CAPI3REF: Find The Database Handle Of A Prepared Statement
-** METHOD: sqlite3_stmt
-**
-** ^The sqlite3_db_handle interface returns the [database connection] handle
-** to which a [prepared statement] belongs. ^The [database connection]
-** returned by sqlite3_db_handle is the same [database connection]
-** that was the first argument
-** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
-** create the statement in the first place.
-*/
-sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
-
-/*
-** CAPI3REF: Return The Filename For A Database Connection
-** METHOD: sqlite3
-**
-** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
-** associated with database N of connection D. ^The main database file
-** has the name "main". If there is no attached database N on the database
-** connection D, or if database N is a temporary or in-memory database, then
-** a NULL pointer is returned.
-**
-** ^The filename returned by this function is the output of the
-** xFullPathname method of the [VFS]. ^In other words, the filename
-** will be an absolute pathname, even if the filename used
-** to open the database originally was a URI or relative pathname.
-*/
-const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
-
-/*
-** CAPI3REF: Determine if a database is read-only
-** METHOD: sqlite3
-**
-** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
-** of connection D is read-only, 0 if it is read/write, or -1 if N is not
-** the name of a database on connection D.
-*/
-int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
-
-/*
-** CAPI3REF: Find the next prepared statement
-** METHOD: sqlite3
-**
-** ^This interface returns a pointer to the next [prepared statement] after
-** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
-** then this interface returns a pointer to the first prepared statement
-** associated with the database connection pDb. ^If no prepared statement
-** satisfies the conditions of this routine, it returns NULL.
-**
-** The [database connection] pointer D in a call to
-** [sqlite3_next_stmt(D,S)] must refer to an open database
-** connection and in particular must not be a NULL pointer.
-*/
-sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
-
-/*
-** CAPI3REF: Commit And Rollback Notification Callbacks
-** METHOD: sqlite3
-**
-** ^The sqlite3_commit_hook() interface registers a callback
-** function to be invoked whenever a transaction is [COMMIT | committed].
-** ^Any callback set by a previous call to sqlite3_commit_hook()
-** for the same database connection is overridden.
-** ^The sqlite3_rollback_hook() interface registers a callback
-** function to be invoked whenever a transaction is [ROLLBACK | rolled back].
-** ^Any callback set by a previous call to sqlite3_rollback_hook()
-** for the same database connection is overridden.
-** ^The pArg argument is passed through to the callback.
-** ^If the callback on a commit hook function returns non-zero,
-** then the commit is converted into a rollback.
-**
-** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions
-** return the P argument from the previous call of the same function
-** on the same [database connection] D, or NULL for
-** the first call for each function on D.
-**
-** The commit and rollback hook callbacks are not reentrant.
-** The callback implementation must not do anything that will modify
-** the database connection that invoked the callback. Any actions
-** to modify the database connection must be deferred until after the
-** completion of the [sqlite3_step()] call that triggered the commit
-** or rollback hook in the first place.
-** Note that running any other SQL statements, including SELECT statements,
-** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify
-** the database connections for the meaning of "modify" in this paragraph.
-**
-** ^Registering a NULL function disables the callback.
-**
-** ^When the commit hook callback routine returns zero, the [COMMIT]
-** operation is allowed to continue normally. ^If the commit hook
-** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK].
-** ^The rollback hook is invoked on a rollback that results from a commit
-** hook returning non-zero, just as it would be with any other rollback.
-**
-** ^For the purposes of this API, a transaction is said to have been
-** rolled back if an explicit "ROLLBACK" statement is executed, or
-** an error or constraint causes an implicit rollback to occur.
-** ^The rollback callback is not invoked if a transaction is
-** automatically rolled back because the database connection is closed.
-**
-** See also the [sqlite3_update_hook()] interface.
-*/
-void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
-void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
-
-/*
-** CAPI3REF: Data Change Notification Callbacks
-** METHOD: sqlite3
-**
-** ^The sqlite3_update_hook() interface registers a callback function
-** with the [database connection] identified by the first argument
-** to be invoked whenever a row is updated, inserted or deleted in
-** a [rowid table].
-** ^Any callback set by a previous call to this function
-** for the same database connection is overridden.
-**
-** ^The second argument is a pointer to the function to invoke when a
-** row is updated, inserted or deleted in a rowid table.
-** ^The first argument to the callback is a copy of the third argument
-** to sqlite3_update_hook().
-** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
-** or [SQLITE_UPDATE], depending on the operation that caused the callback
-** to be invoked.
-** ^The third and fourth arguments to the callback contain pointers to the
-** database and table name containing the affected row.
-** ^The final callback parameter is the [rowid] of the row.
-** ^In the case of an update, this is the [rowid] after the update takes place.
-**
-** ^(The update hook is not invoked when internal system tables are
-** modified (i.e. sqlite_master and sqlite_sequence).)^
-** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
-**
-** ^In the current implementation, the update hook
-** is not invoked when conflicting rows are deleted because of an
-** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
-** invoked when rows are deleted using the [truncate optimization].
-** The exceptions defined in this paragraph might change in a future
-** release of SQLite.
-**
-** The update hook implementation must not do anything that will modify
-** the database connection that invoked the update hook. Any actions
-** to modify the database connection must be deferred until after the
-** completion of the [sqlite3_step()] call that triggered the update hook.
-** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
-** database connections for the meaning of "modify" in this paragraph.
-**
-** ^The sqlite3_update_hook(D,C,P) function
-** returns the P argument from the previous call
-** on the same [database connection] D, or NULL for
-** the first call on D.
-**
-** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()],
-** and [sqlite3_preupdate_hook()] interfaces.
-*/
-void *sqlite3_update_hook(
- sqlite3*,
- void(*)(void *,int ,char const *,char const *,sqlite3_int64),
- void*
-);
-
-/*
-** CAPI3REF: Enable Or Disable Shared Pager Cache
-**
-** ^(This routine enables or disables the sharing of the database cache
-** and schema data structures between [database connection | connections]
-** to the same database. Sharing is enabled if the argument is true
-** and disabled if the argument is false.)^
-**
-** ^Cache sharing is enabled and disabled for an entire process.
-** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]).
-** In prior versions of SQLite,
-** sharing was enabled or disabled for each thread separately.
-**
-** ^(The cache sharing mode set by this interface effects all subsequent
-** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
-** Existing database connections continue use the sharing mode
-** that was in effect at the time they were opened.)^
-**
-** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
-** successfully. An [error code] is returned otherwise.)^
-**
-** ^Shared cache is disabled by default. But this might change in
-** future releases of SQLite. Applications that care about shared
-** cache setting should set it explicitly.
-**
-** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
-** and will always return SQLITE_MISUSE. On those systems,
-** shared cache mode should be enabled per-database connection via
-** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE].
-**
-** This interface is threadsafe on processors where writing a
-** 32-bit integer is atomic.
-**
-** See Also: [SQLite Shared-Cache Mode]
-*/
-int sqlite3_enable_shared_cache(int);
-
-/*
-** CAPI3REF: Attempt To Free Heap Memory
-**
-** ^The sqlite3_release_memory() interface attempts to free N bytes
-** of heap memory by deallocating non-essential memory allocations
-** held by the database library. Memory used to cache database
-** pages to improve performance is an example of non-essential memory.
-** ^sqlite3_release_memory() returns the number of bytes actually freed,
-** which might be more or less than the amount requested.
-** ^The sqlite3_release_memory() routine is a no-op returning zero
-** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT].
-**
-** See also: [sqlite3_db_release_memory()]
-*/
-int sqlite3_release_memory(int);
-
-/*
-** CAPI3REF: Free Memory Used By A Database Connection
-** METHOD: sqlite3
-**
-** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
-** memory as possible from database connection D. Unlike the
-** [sqlite3_release_memory()] interface, this interface is in effect even
-** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
-** omitted.
-**
-** See also: [sqlite3_release_memory()]
-*/
-int sqlite3_db_release_memory(sqlite3*);
-
-/*
-** CAPI3REF: Impose A Limit On Heap Size
-**
-** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
-** soft limit on the amount of heap memory that may be allocated by SQLite.
-** ^SQLite strives to keep heap memory utilization below the soft heap
-** limit by reducing the number of pages held in the page cache
-** as heap memory usages approaches the limit.
-** ^The soft heap limit is "soft" because even though SQLite strives to stay
-** below the limit, it will exceed the limit rather than generate
-** an [SQLITE_NOMEM] error. In other words, the soft heap limit
-** is advisory only.
-**
-** ^The return value from sqlite3_soft_heap_limit64() is the size of
-** the soft heap limit prior to the call, or negative in the case of an
-** error. ^If the argument N is negative
-** then no change is made to the soft heap limit. Hence, the current
-** size of the soft heap limit can be determined by invoking
-** sqlite3_soft_heap_limit64() with a negative argument.
-**
-** ^If the argument N is zero then the soft heap limit is disabled.
-**
-** ^(The soft heap limit is not enforced in the current implementation
-** if one or more of following conditions are true:
-**
-** <ul>
-** <li> The soft heap limit is set to zero.
-** <li> Memory accounting is disabled using a combination of the
-** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
-** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
-** <li> An alternative page cache implementation is specified using
-** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...).
-** <li> The page cache allocates from its own memory pool supplied
-** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than
-** from the heap.
-** </ul>)^
-**
-** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
-** the soft heap limit is enforced
-** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
-** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
-** the soft heap limit is enforced on every memory allocation. Without
-** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
-** when memory is allocated by the page cache. Testing suggests that because
-** the page cache is the predominate memory user in SQLite, most
-** applications will achieve adequate soft heap limit enforcement without
-** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
-**
-** The circumstances under which SQLite will enforce the soft heap limit may
-** changes in future releases of SQLite.
-*/
-sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
-
-/*
-** CAPI3REF: Deprecated Soft Heap Limit Interface
-** DEPRECATED
-**
-** This is a deprecated version of the [sqlite3_soft_heap_limit64()]
-** interface. This routine is provided for historical compatibility
-** only. All new applications should use the
-** [sqlite3_soft_heap_limit64()] interface rather than this one.
-*/
-SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
-
-
-/*
-** CAPI3REF: Extract Metadata About A Column Of A Table
-** METHOD: sqlite3
-**
-** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
-** information about column C of table T in database D
-** on [database connection] X.)^ ^The sqlite3_table_column_metadata()
-** interface returns SQLITE_OK and fills in the non-NULL pointers in
-** the final five arguments with appropriate values if the specified
-** column exists. ^The sqlite3_table_column_metadata() interface returns
-** SQLITE_ERROR and if the specified column does not exist.
-** ^If the column-name parameter to sqlite3_table_column_metadata() is a
-** NULL pointer, then this routine simply checks for the existence of the
-** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
-** does not. If the table name parameter T in a call to
-** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is
-** undefined behavior.
-**
-** ^The column is identified by the second, third and fourth parameters to
-** this function. ^(The second parameter is either the name of the database
-** (i.e. "main", "temp", or an attached database) containing the specified
-** table or NULL.)^ ^If it is NULL, then all attached databases are searched
-** for the table using the same algorithm used by the database engine to
-** resolve unqualified table references.
-**
-** ^The third and fourth parameters to this function are the table and column
-** name of the desired column, respectively.
-**
-** ^Metadata is returned by writing to the memory locations passed as the 5th
-** and subsequent parameters to this function. ^Any of these arguments may be
-** NULL, in which case the corresponding element of metadata is omitted.
-**
-** ^(<blockquote>
-** <table border="1">
-** <tr><th> Parameter <th> Output<br>Type <th> Description
-**
-** <tr><td> 5th <td> const char* <td> Data type
-** <tr><td> 6th <td> const char* <td> Name of default collation sequence
-** <tr><td> 7th <td> int <td> True if column has a NOT NULL constraint
-** <tr><td> 8th <td> int <td> True if column is part of the PRIMARY KEY
-** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
-** </table>
-** </blockquote>)^
-**
-** ^The memory pointed to by the character pointers returned for the
-** declaration type and collation sequence is valid until the next
-** call to any SQLite API function.
-**
-** ^If the specified table is actually a view, an [error code] is returned.
-**
-** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
-** is not a [WITHOUT ROWID] table and an
-** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
-** parameters are set for the explicitly declared column. ^(If there is no
-** [INTEGER PRIMARY KEY] column, then the outputs
-** for the [rowid] are set as follows:
-**
-** <pre>
-** data type: "INTEGER"
-** collation sequence: "BINARY"
-** not null: 0
-** primary key: 1
-** auto increment: 0
-** </pre>)^
-**
-** ^This function causes all database schemas to be read from disk and
-** parsed, if that has not already been done, and returns an error if
-** any errors are encountered while loading the schema.
-*/
-int sqlite3_table_column_metadata(
- sqlite3 *db, /* Connection handle */
- const char *zDbName, /* Database name or NULL */
- const char *zTableName, /* Table name */
- const char *zColumnName, /* Column name */
- char const **pzDataType, /* OUTPUT: Declared data type */
- char const **pzCollSeq, /* OUTPUT: Collation sequence name */
- int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */
- int *pPrimaryKey, /* OUTPUT: True if column part of PK */
- int *pAutoinc /* OUTPUT: True if column is auto-increment */
-);
-
-/*
-** CAPI3REF: Load An Extension
-** METHOD: sqlite3
-**
-** ^This interface loads an SQLite extension library from the named file.
-**
-** ^The sqlite3_load_extension() interface attempts to load an
-** [SQLite extension] library contained in the file zFile. If
-** the file cannot be loaded directly, attempts are made to load
-** with various operating-system specific extensions added.
-** So for example, if "samplelib" cannot be loaded, then names like
-** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
-** be tried also.
-**
-** ^The entry point is zProc.
-** ^(zProc may be 0, in which case SQLite will try to come up with an
-** entry point name on its own. It first tries "sqlite3_extension_init".
-** If that does not work, it constructs a name "sqlite3_X_init" where the
-** X is consists of the lower-case equivalent of all ASCII alphabetic
-** characters in the filename from the last "/" to the first following
-** "." and omitting any initial "lib".)^
-** ^The sqlite3_load_extension() interface returns
-** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
-** ^If an error occurs and pzErrMsg is not 0, then the
-** [sqlite3_load_extension()] interface shall attempt to
-** fill *pzErrMsg with error message text stored in memory
-** obtained from [sqlite3_malloc()]. The calling function
-** should free this memory by calling [sqlite3_free()].
-**
-** ^Extension loading must be enabled using
-** [sqlite3_enable_load_extension()] or
-** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL)
-** prior to calling this API,
-** otherwise an error will be returned.
-**
-** <b>Security warning:</b> It is recommended that the
-** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this
-** interface. The use of the [sqlite3_enable_load_extension()] interface
-** should be avoided. This will keep the SQL function [load_extension()]
-** disabled and prevent SQL injections from giving attackers
-** access to extension loading capabilities.
-**
-** See also the [load_extension() SQL function].
-*/
-int sqlite3_load_extension(
- sqlite3 *db, /* Load the extension into this database connection */
- const char *zFile, /* Name of the shared library containing extension */
- const char *zProc, /* Entry point. Derived from zFile if 0 */
- char **pzErrMsg /* Put error message here if not 0 */
-);
-
-/*
-** CAPI3REF: Enable Or Disable Extension Loading
-** METHOD: sqlite3
-**
-** ^So as not to open security holes in older applications that are
-** unprepared to deal with [extension loading], and as a means of disabling
-** [extension loading] while evaluating user-entered SQL, the following API
-** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
-**
-** ^Extension loading is off by default.
-** ^Call the sqlite3_enable_load_extension() routine with onoff==1
-** to turn extension loading on and call it with onoff==0 to turn
-** it back off again.
-**
-** ^This interface enables or disables both the C-API
-** [sqlite3_load_extension()] and the SQL function [load_extension()].
-** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..)
-** to enable or disable only the C-API.)^
-**
-** <b>Security warning:</b> It is recommended that extension loading
-** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
-** rather than this interface, so the [load_extension()] SQL function
-** remains disabled. This will prevent SQL injections from giving attackers
-** access to extension loading capabilities.
-*/
-int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
-
-/*
-** CAPI3REF: Automatically Load Statically Linked Extensions
-**
-** ^This interface causes the xEntryPoint() function to be invoked for
-** each new [database connection] that is created. The idea here is that
-** xEntryPoint() is the entry point for a statically linked [SQLite extension]
-** that is to be automatically loaded into all new database connections.
-**
-** ^(Even though the function prototype shows that xEntryPoint() takes
-** no arguments and returns void, SQLite invokes xEntryPoint() with three
-** arguments and expects an integer result as if the signature of the
-** entry point where as follows:
-**
-** <blockquote><pre>
-** &nbsp; int xEntryPoint(
-** &nbsp; sqlite3 *db,
-** &nbsp; const char **pzErrMsg,
-** &nbsp; const struct sqlite3_api_routines *pThunk
-** &nbsp; );
-** </pre></blockquote>)^
-**
-** If the xEntryPoint routine encounters an error, it should make *pzErrMsg
-** point to an appropriate error message (obtained from [sqlite3_mprintf()])
-** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg
-** is NULL before calling the xEntryPoint(). ^SQLite will invoke
-** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any
-** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()],
-** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail.
-**
-** ^Calling sqlite3_auto_extension(X) with an entry point X that is already
-** on the list of automatic extensions is a harmless no-op. ^No entry point
-** will be called more than once for each database connection that is opened.
-**
-** See also: [sqlite3_reset_auto_extension()]
-** and [sqlite3_cancel_auto_extension()]
-*/
-int sqlite3_auto_extension(void(*xEntryPoint)(void));
-
-/*
-** CAPI3REF: Cancel Automatic Extension Loading
-**
-** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
-** initialization routine X that was registered using a prior call to
-** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
-** routine returns 1 if initialization routine X was successfully
-** unregistered and it returns 0 if X was not on the list of initialization
-** routines.
-*/
-int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));
-
-/*
-** CAPI3REF: Reset Automatic Extension Loading
-**
-** ^This interface disables all automatic extensions previously
-** registered using [sqlite3_auto_extension()].
-*/
-void sqlite3_reset_auto_extension(void);
-
-/*
-** The interface to the virtual-table mechanism is currently considered
-** to be experimental. The interface might change in incompatible ways.
-** If this is a problem for you, do not use the interface at this time.
-**
-** When the virtual-table mechanism stabilizes, we will declare the
-** interface fixed, support it indefinitely, and remove this comment.
-*/
-
-/*
-** Structures used by the virtual table interface
-*/
-typedef struct sqlite3_vtab sqlite3_vtab;
-typedef struct sqlite3_index_info sqlite3_index_info;
-typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
-typedef struct sqlite3_module sqlite3_module;
-
-/*
-** CAPI3REF: Virtual Table Object
-** KEYWORDS: sqlite3_module {virtual table module}
-**
-** This structure, sometimes called a "virtual table module",
-** defines the implementation of a [virtual tables].
-** This structure consists mostly of methods for the module.
-**
-** ^A virtual table module is created by filling in a persistent
-** instance of this structure and passing a pointer to that instance
-** to [sqlite3_create_module()] or [sqlite3_create_module_v2()].
-** ^The registration remains valid until it is replaced by a different
-** module or until the [database connection] closes. The content
-** of this structure must not change while it is registered with
-** any database connection.
-*/
-struct sqlite3_module {
- int iVersion;
- int (*xCreate)(sqlite3*, void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab, char**);
- int (*xConnect)(sqlite3*, void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab, char**);
- int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
- int (*xDisconnect)(sqlite3_vtab *pVTab);
- int (*xDestroy)(sqlite3_vtab *pVTab);
- int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
- int (*xClose)(sqlite3_vtab_cursor*);
- int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv);
- int (*xNext)(sqlite3_vtab_cursor*);
- int (*xEof)(sqlite3_vtab_cursor*);
- int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
- int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
- int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
- int (*xBegin)(sqlite3_vtab *pVTab);
- int (*xSync)(sqlite3_vtab *pVTab);
- int (*xCommit)(sqlite3_vtab *pVTab);
- int (*xRollback)(sqlite3_vtab *pVTab);
- int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
- void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
- void **ppArg);
- int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
- /* The methods above are in version 1 of the sqlite_module object. Those
- ** below are for version 2 and greater. */
- int (*xSavepoint)(sqlite3_vtab *pVTab, int);
- int (*xRelease)(sqlite3_vtab *pVTab, int);
- int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
-};
-
-/*
-** CAPI3REF: Virtual Table Indexing Information
-** KEYWORDS: sqlite3_index_info
-**
-** The sqlite3_index_info structure and its substructures is used as part
-** of the [virtual table] interface to
-** pass information into and receive the reply from the [xBestIndex]
-** method of a [virtual table module]. The fields under **Inputs** are the
-** inputs to xBestIndex and are read-only. xBestIndex inserts its
-** results into the **Outputs** fields.
-**
-** ^(The aConstraint[] array records WHERE clause constraints of the form:
-**
-** <blockquote>column OP expr</blockquote>
-**
-** where OP is =, &lt;, &lt;=, &gt;, or &gt;=.)^ ^(The particular operator is
-** stored in aConstraint[].op using one of the
-** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^
-** ^(The index of the column is stored in
-** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the
-** expr on the right-hand side can be evaluated (and thus the constraint
-** is usable) and false if it cannot.)^
-**
-** ^The optimizer automatically inverts terms of the form "expr OP column"
-** and makes other simplifications to the WHERE clause in an attempt to
-** get as many WHERE clause terms into the form shown above as possible.
-** ^The aConstraint[] array only reports WHERE clause terms that are
-** relevant to the particular virtual table being queried.
-**
-** ^Information about the ORDER BY clause is stored in aOrderBy[].
-** ^Each term of aOrderBy records a column of the ORDER BY clause.
-**
-** The colUsed field indicates which columns of the virtual table may be
-** required by the current scan. Virtual table columns are numbered from
-** zero in the order in which they appear within the CREATE TABLE statement
-** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62),
-** the corresponding bit is set within the colUsed mask if the column may be
-** required by SQLite. If the table has at least 64 columns and any column
-** to the right of the first 63 is required, then bit 63 of colUsed is also
-** set. In other words, column iCol may be required if the expression
-** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to
-** non-zero.
-**
-** The [xBestIndex] method must fill aConstraintUsage[] with information
-** about what parameters to pass to xFilter. ^If argvIndex>0 then
-** the right-hand side of the corresponding aConstraint[] is evaluated
-** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit
-** is true, then the constraint is assumed to be fully handled by the
-** virtual table and is not checked again by SQLite.)^
-**
-** ^The idxNum and idxPtr values are recorded and passed into the
-** [xFilter] method.
-** ^[sqlite3_free()] is used to free idxPtr if and only if
-** needToFreeIdxPtr is true.
-**
-** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in
-** the correct order to satisfy the ORDER BY clause so that no separate
-** sorting step is required.
-**
-** ^The estimatedCost value is an estimate of the cost of a particular
-** strategy. A cost of N indicates that the cost of the strategy is similar
-** to a linear scan of an SQLite table with N rows. A cost of log(N)
-** indicates that the expense of the operation is similar to that of a
-** binary search on a unique indexed field of an SQLite table with N rows.
-**
-** ^The estimatedRows value is an estimate of the number of rows that
-** will be returned by the strategy.
-**
-** The xBestIndex method may optionally populate the idxFlags field with a
-** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
-** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
-** assumes that the strategy may visit at most one row.
-**
-** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
-** SQLite also assumes that if a call to the xUpdate() method is made as
-** part of the same statement to delete or update a virtual table row and the
-** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback
-** any database changes. In other words, if the xUpdate() returns
-** SQLITE_CONSTRAINT, the database contents must be exactly as they were
-** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not
-** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by
-** the xUpdate method are automatically rolled back by SQLite.
-**
-** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
-** structure for SQLite [version 3.8.2] ([dateof:3.8.2]).
-** If a virtual table extension is
-** used with an SQLite version earlier than 3.8.2, the results of attempting
-** to read or write the estimatedRows field are undefined (but are likely
-** to included crashing the application). The estimatedRows field should
-** therefore only be used if [sqlite3_libversion_number()] returns a
-** value greater than or equal to 3008002. Similarly, the idxFlags field
-** was added for [version 3.9.0] ([dateof:3.9.0]).
-** It may therefore only be used if
-** sqlite3_libversion_number() returns a value greater than or equal to
-** 3009000.
-*/
-struct sqlite3_index_info {
- /* Inputs */
- int nConstraint; /* Number of entries in aConstraint */
- struct sqlite3_index_constraint {
- int iColumn; /* Column constrained. -1 for ROWID */
- unsigned char op; /* Constraint operator */
- unsigned char usable; /* True if this constraint is usable */
- int iTermOffset; /* Used internally - xBestIndex should ignore */
- } *aConstraint; /* Table of WHERE clause constraints */
- int nOrderBy; /* Number of terms in the ORDER BY clause */
- struct sqlite3_index_orderby {
- int iColumn; /* Column number */
- unsigned char desc; /* True for DESC. False for ASC. */
- } *aOrderBy; /* The ORDER BY clause */
- /* Outputs */
- struct sqlite3_index_constraint_usage {
- int argvIndex; /* if >0, constraint is part of argv to xFilter */
- unsigned char omit; /* Do not code a test for this constraint */
- } *aConstraintUsage;
- int idxNum; /* Number used to identify the index */
- char *idxStr; /* String, possibly obtained from sqlite3_malloc */
- int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
- int orderByConsumed; /* True if output is already ordered */
- double estimatedCost; /* Estimated cost of using this index */
- /* Fields below are only available in SQLite 3.8.2 and later */
- sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
- /* Fields below are only available in SQLite 3.9.0 and later */
- int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
- /* Fields below are only available in SQLite 3.10.0 and later */
- sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */
-};
-
-/*
-** CAPI3REF: Virtual Table Scan Flags
-**
-** Virtual table implementations are allowed to set the
-** [sqlite3_index_info].idxFlags field to some combination of
-** these bits.
-*/
-#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
-
-/*
-** CAPI3REF: Virtual Table Constraint Operator Codes
-**
-** These macros defined the allowed values for the
-** [sqlite3_index_info].aConstraint[].op field. Each value represents
-** an operator that is part of a constraint term in the wHERE clause of
-** a query that uses a [virtual table].
-*/
-#define SQLITE_INDEX_CONSTRAINT_EQ 2
-#define SQLITE_INDEX_CONSTRAINT_GT 4
-#define SQLITE_INDEX_CONSTRAINT_LE 8
-#define SQLITE_INDEX_CONSTRAINT_LT 16
-#define SQLITE_INDEX_CONSTRAINT_GE 32
-#define SQLITE_INDEX_CONSTRAINT_MATCH 64
-#define SQLITE_INDEX_CONSTRAINT_LIKE 65
-#define SQLITE_INDEX_CONSTRAINT_GLOB 66
-#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
-#define SQLITE_INDEX_CONSTRAINT_NE 68
-#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
-#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
-#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
-#define SQLITE_INDEX_CONSTRAINT_IS 72
-
-/*
-** CAPI3REF: Register A Virtual Table Implementation
-** METHOD: sqlite3
-**
-** ^These routines are used to register a new [virtual table module] name.
-** ^Module names must be registered before
-** creating a new [virtual table] using the module and before using a
-** preexisting [virtual table] for the module.
-**
-** ^The module name is registered on the [database connection] specified
-** by the first parameter. ^The name of the module is given by the
-** second parameter. ^The third parameter is a pointer to
-** the implementation of the [virtual table module]. ^The fourth
-** parameter is an arbitrary client data pointer that is passed through
-** into the [xCreate] and [xConnect] methods of the virtual table module
-** when a new virtual table is be being created or reinitialized.
-**
-** ^The sqlite3_create_module_v2() interface has a fifth parameter which
-** is a pointer to a destructor for the pClientData. ^SQLite will
-** invoke the destructor function (if it is not NULL) when SQLite
-** no longer needs the pClientData pointer. ^The destructor will also
-** be invoked if the call to sqlite3_create_module_v2() fails.
-** ^The sqlite3_create_module()
-** interface is equivalent to sqlite3_create_module_v2() with a NULL
-** destructor.
-*/
-int sqlite3_create_module(
- sqlite3 *db, /* SQLite connection to register module with */
- const char *zName, /* Name of the module */
- const sqlite3_module *p, /* Methods for the module */
- void *pClientData /* Client data for xCreate/xConnect */
-);
-int sqlite3_create_module_v2(
- sqlite3 *db, /* SQLite connection to register module with */
- const char *zName, /* Name of the module */
- const sqlite3_module *p, /* Methods for the module */
- void *pClientData, /* Client data for xCreate/xConnect */
- void(*xDestroy)(void*) /* Module destructor function */
-);
-
-/*
-** CAPI3REF: Virtual Table Instance Object
-** KEYWORDS: sqlite3_vtab
-**
-** Every [virtual table module] implementation uses a subclass
-** of this object to describe a particular instance
-** of the [virtual table]. Each subclass will
-** be tailored to the specific needs of the module implementation.
-** The purpose of this superclass is to define certain fields that are
-** common to all module implementations.
-**
-** ^Virtual tables methods can set an error message by assigning a
-** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should
-** take care that any prior string is freed by a call to [sqlite3_free()]
-** prior to assigning a new string to zErrMsg. ^After the error message
-** is delivered up to the client application, the string will be automatically
-** freed by sqlite3_free() and the zErrMsg field will be zeroed.
-*/
-struct sqlite3_vtab {
- const sqlite3_module *pModule; /* The module for this virtual table */
- int nRef; /* Number of open cursors */
- char *zErrMsg; /* Error message from sqlite3_mprintf() */
- /* Virtual table implementations will typically add additional fields */
-};
-
-/*
-** CAPI3REF: Virtual Table Cursor Object
-** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
-**
-** Every [virtual table module] implementation uses a subclass of the
-** following structure to describe cursors that point into the
-** [virtual table] and are used
-** to loop through the virtual table. Cursors are created using the
-** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed
-** by the [sqlite3_module.xClose | xClose] method. Cursors are used
-** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods
-** of the module. Each module implementation will define
-** the content of a cursor structure to suit its own needs.
-**
-** This superclass exists in order to define fields of the cursor that
-** are common to all implementations.
-*/
-struct sqlite3_vtab_cursor {
- sqlite3_vtab *pVtab; /* Virtual table of this cursor */
- /* Virtual table implementations will typically add additional fields */
-};
-
-/*
-** CAPI3REF: Declare The Schema Of A Virtual Table
-**
-** ^The [xCreate] and [xConnect] methods of a
-** [virtual table module] call this interface
-** to declare the format (the names and datatypes of the columns) of
-** the virtual tables they implement.
-*/
-int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
-
-/*
-** CAPI3REF: Overload A Function For A Virtual Table
-** METHOD: sqlite3
-**
-** ^(Virtual tables can provide alternative implementations of functions
-** using the [xFindFunction] method of the [virtual table module].
-** But global versions of those functions
-** must exist in order to be overloaded.)^
-**
-** ^(This API makes sure a global version of a function with a particular
-** name and number of parameters exists. If no such function exists
-** before this API is called, a new function is created.)^ ^The implementation
-** of the new function always causes an exception to be thrown. So
-** the new function is not good for anything by itself. Its only
-** purpose is to be a placeholder function that can be overloaded
-** by a [virtual table].
-*/
-int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
-
-/*
-** The interface to the virtual-table mechanism defined above (back up
-** to a comment remarkably similar to this one) is currently considered
-** to be experimental. The interface might change in incompatible ways.
-** If this is a problem for you, do not use the interface at this time.
-**
-** When the virtual-table mechanism stabilizes, we will declare the
-** interface fixed, support it indefinitely, and remove this comment.
-*/
-
-/*
-** CAPI3REF: A Handle To An Open BLOB
-** KEYWORDS: {BLOB handle} {BLOB handles}
-**
-** An instance of this object represents an open BLOB on which
-** [sqlite3_blob_open | incremental BLOB I/O] can be performed.
-** ^Objects of this type are created by [sqlite3_blob_open()]
-** and destroyed by [sqlite3_blob_close()].
-** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces
-** can be used to read or write small subsections of the BLOB.
-** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes.
-*/
-typedef struct sqlite3_blob sqlite3_blob;
-
-/*
-** CAPI3REF: Open A BLOB For Incremental I/O
-** METHOD: sqlite3
-** CONSTRUCTOR: sqlite3_blob
-**
-** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
-** in row iRow, column zColumn, table zTable in database zDb;
-** in other words, the same BLOB that would be selected by:
-**
-** <pre>
-** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
-** </pre>)^
-**
-** ^(Parameter zDb is not the filename that contains the database, but
-** rather the symbolic name of the database. For attached databases, this is
-** the name that appears after the AS keyword in the [ATTACH] statement.
-** For the main database file, the database name is "main". For TEMP
-** tables, the database name is "temp".)^
-**
-** ^If the flags parameter is non-zero, then the BLOB is opened for read
-** and write access. ^If the flags parameter is zero, the BLOB is opened for
-** read-only access.
-**
-** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored
-** in *ppBlob. Otherwise an [error code] is returned and, unless the error
-** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided
-** the API is not misused, it is always safe to call [sqlite3_blob_close()]
-** on *ppBlob after this function it returns.
-**
-** This function fails with SQLITE_ERROR if any of the following are true:
-** <ul>
-** <li> ^(Database zDb does not exist)^,
-** <li> ^(Table zTable does not exist within database zDb)^,
-** <li> ^(Table zTable is a WITHOUT ROWID table)^,
-** <li> ^(Column zColumn does not exist)^,
-** <li> ^(Row iRow is not present in the table)^,
-** <li> ^(The specified column of row iRow contains a value that is not
-** a TEXT or BLOB value)^,
-** <li> ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE
-** constraint and the blob is being opened for read/write access)^,
-** <li> ^([foreign key constraints | Foreign key constraints] are enabled,
-** column zColumn is part of a [child key] definition and the blob is
-** being opened for read/write access)^.
-** </ul>
-**
-** ^Unless it returns SQLITE_MISUSE, this function sets the
-** [database connection] error code and message accessible via
-** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
-**
-** A BLOB referenced by sqlite3_blob_open() may be read using the
-** [sqlite3_blob_read()] interface and modified by using
-** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a
-** different row of the same table using the [sqlite3_blob_reopen()]
-** interface. However, the column, table, or database of a [BLOB handle]
-** cannot be changed after the [BLOB handle] is opened.
-**
-** ^(If the row that a BLOB handle points to is modified by an
-** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
-** then the BLOB handle is marked as "expired".
-** This is true if any column of the row is changed, even a column
-** other than the one the BLOB handle is open on.)^
-** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for
-** an expired BLOB handle fail with a return code of [SQLITE_ABORT].
-** ^(Changes written into a BLOB prior to the BLOB expiring are not
-** rolled back by the expiration of the BLOB. Such changes will eventually
-** commit if the transaction continues to completion.)^
-**
-** ^Use the [sqlite3_blob_bytes()] interface to determine the size of
-** the opened blob. ^The size of a blob may not be changed by this
-** interface. Use the [UPDATE] SQL command to change the size of a
-** blob.
-**
-** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
-** and the built-in [zeroblob] SQL function may be used to create a
-** zero-filled blob to read or write using the incremental-blob interface.
-**
-** To avoid a resource leak, every open [BLOB handle] should eventually
-** be released by a call to [sqlite3_blob_close()].
-**
-** See also: [sqlite3_blob_close()],
-** [sqlite3_blob_reopen()], [sqlite3_blob_read()],
-** [sqlite3_blob_bytes()], [sqlite3_blob_write()].
-*/
-int sqlite3_blob_open(
- sqlite3*,
- const char *zDb,
- const char *zTable,
- const char *zColumn,
- sqlite3_int64 iRow,
- int flags,
- sqlite3_blob **ppBlob
-);
-
-/*
-** CAPI3REF: Move a BLOB Handle to a New Row
-** METHOD: sqlite3_blob
-**
-** ^This function is used to move an existing [BLOB handle] so that it points
-** to a different row of the same database table. ^The new row is identified
-** by the rowid value passed as the second argument. Only the row can be
-** changed. ^The database, table and column on which the blob handle is open
-** remain the same. Moving an existing [BLOB handle] to a new row is
-** faster than closing the existing handle and opening a new one.
-**
-** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
-** it must exist and there must be either a blob or text value stored in
-** the nominated column.)^ ^If the new row is not present in the table, or if
-** it does not contain a blob or text value, or if another error occurs, an
-** SQLite error code is returned and the blob handle is considered aborted.
-** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or
-** [sqlite3_blob_reopen()] on an aborted blob handle immediately return
-** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle
-** always returns zero.
-**
-** ^This function sets the database handle error code and message.
-*/
-int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
-
-/*
-** CAPI3REF: Close A BLOB Handle
-** DESTRUCTOR: sqlite3_blob
-**
-** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed
-** unconditionally. Even if this routine returns an error code, the
-** handle is still closed.)^
-**
-** ^If the blob handle being closed was opened for read-write access, and if
-** the database is in auto-commit mode and there are no other open read-write
-** blob handles or active write statements, the current transaction is
-** committed. ^If an error occurs while committing the transaction, an error
-** code is returned and the transaction rolled back.
-**
-** Calling this function with an argument that is not a NULL pointer or an
-** open blob handle results in undefined behaviour. ^Calling this routine
-** with a null pointer (such as would be returned by a failed call to
-** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function
-** is passed a valid open blob handle, the values returned by the
-** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
-*/
-int sqlite3_blob_close(sqlite3_blob *);
-
-/*
-** CAPI3REF: Return The Size Of An Open BLOB
-** METHOD: sqlite3_blob
-**
-** ^Returns the size in bytes of the BLOB accessible via the
-** successfully opened [BLOB handle] in its only argument. ^The
-** incremental blob I/O routines can only read or overwriting existing
-** blob content; they cannot change the size of a blob.
-**
-** This routine only works on a [BLOB handle] which has been created
-** by a prior successful call to [sqlite3_blob_open()] and which has not
-** been closed by [sqlite3_blob_close()]. Passing any other pointer in
-** to this routine results in undefined and probably undesirable behavior.
-*/
-int sqlite3_blob_bytes(sqlite3_blob *);
-
-/*
-** CAPI3REF: Read Data From A BLOB Incrementally
-** METHOD: sqlite3_blob
-**
-** ^(This function is used to read data from an open [BLOB handle] into a
-** caller-supplied buffer. N bytes of data are copied into buffer Z
-** from the open BLOB, starting at offset iOffset.)^
-**
-** ^If offset iOffset is less than N bytes from the end of the BLOB,
-** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is
-** less than zero, [SQLITE_ERROR] is returned and no data is read.
-** ^The size of the blob (and hence the maximum value of N+iOffset)
-** can be determined using the [sqlite3_blob_bytes()] interface.
-**
-** ^An attempt to read from an expired [BLOB handle] fails with an
-** error code of [SQLITE_ABORT].
-**
-** ^(On success, sqlite3_blob_read() returns SQLITE_OK.
-** Otherwise, an [error code] or an [extended error code] is returned.)^
-**
-** This routine only works on a [BLOB handle] which has been created
-** by a prior successful call to [sqlite3_blob_open()] and which has not
-** been closed by [sqlite3_blob_close()]. Passing any other pointer in
-** to this routine results in undefined and probably undesirable behavior.
-**
-** See also: [sqlite3_blob_write()].
-*/
-int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
-
-/*
-** CAPI3REF: Write Data Into A BLOB Incrementally
-** METHOD: sqlite3_blob
-**
-** ^(This function is used to write data into an open [BLOB handle] from a
-** caller-supplied buffer. N bytes of data are copied from the buffer Z
-** into the open BLOB, starting at offset iOffset.)^
-**
-** ^(On success, sqlite3_blob_write() returns SQLITE_OK.
-** Otherwise, an [error code] or an [extended error code] is returned.)^
-** ^Unless SQLITE_MISUSE is returned, this function sets the
-** [database connection] error code and message accessible via
-** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
-**
-** ^If the [BLOB handle] passed as the first argument was not opened for
-** writing (the flags parameter to [sqlite3_blob_open()] was zero),
-** this function returns [SQLITE_READONLY].
-**
-** This function may only modify the contents of the BLOB; it is
-** not possible to increase the size of a BLOB using this API.
-** ^If offset iOffset is less than N bytes from the end of the BLOB,
-** [SQLITE_ERROR] is returned and no data is written. The size of the
-** BLOB (and hence the maximum value of N+iOffset) can be determined
-** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less
-** than zero [SQLITE_ERROR] is returned and no data is written.
-**
-** ^An attempt to write to an expired [BLOB handle] fails with an
-** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred
-** before the [BLOB handle] expired are not rolled back by the
-** expiration of the handle, though of course those changes might
-** have been overwritten by the statement that expired the BLOB handle
-** or by other independent statements.
-**
-** This routine only works on a [BLOB handle] which has been created
-** by a prior successful call to [sqlite3_blob_open()] and which has not
-** been closed by [sqlite3_blob_close()]. Passing any other pointer in
-** to this routine results in undefined and probably undesirable behavior.
-**
-** See also: [sqlite3_blob_read()].
-*/
-int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
-
-/*
-** CAPI3REF: Virtual File System Objects
-**
-** A virtual filesystem (VFS) is an [sqlite3_vfs] object
-** that SQLite uses to interact
-** with the underlying operating system. Most SQLite builds come with a
-** single default VFS that is appropriate for the host computer.
-** New VFSes can be registered and existing VFSes can be unregistered.
-** The following interfaces are provided.
-**
-** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name.
-** ^Names are case sensitive.
-** ^Names are zero-terminated UTF-8 strings.
-** ^If there is no match, a NULL pointer is returned.
-** ^If zVfsName is NULL then the default VFS is returned.
-**
-** ^New VFSes are registered with sqlite3_vfs_register().
-** ^Each new VFS becomes the default VFS if the makeDflt flag is set.
-** ^The same VFS can be registered multiple times without injury.
-** ^To make an existing VFS into the default VFS, register it again
-** with the makeDflt flag set. If two different VFSes with the
-** same name are registered, the behavior is undefined. If a
-** VFS is registered with a name that is NULL or an empty string,
-** then the behavior is undefined.
-**
-** ^Unregister a VFS with the sqlite3_vfs_unregister() interface.
-** ^(If the default VFS is unregistered, another VFS is chosen as
-** the default. The choice for the new VFS is arbitrary.)^
-*/
-sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
-int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
-int sqlite3_vfs_unregister(sqlite3_vfs*);
-
-/*
-** CAPI3REF: Mutexes
-**
-** The SQLite core uses these routines for thread
-** synchronization. Though they are intended for internal
-** use by SQLite, code that links against SQLite is
-** permitted to use any of these routines.
-**
-** The SQLite source code contains multiple implementations
-** of these mutex routines. An appropriate implementation
-** is selected automatically at compile-time. The following
-** implementations are available in the SQLite core:
-**
-** <ul>
-** <li> SQLITE_MUTEX_PTHREADS
-** <li> SQLITE_MUTEX_W32
-** <li> SQLITE_MUTEX_NOOP
-** </ul>
-**
-** The SQLITE_MUTEX_NOOP implementation is a set of routines
-** that does no real locking and is appropriate for use in
-** a single-threaded application. The SQLITE_MUTEX_PTHREADS and
-** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
-** and Windows.
-**
-** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
-** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
-** implementation is included with the library. In this case the
-** application must supply a custom mutex implementation using the
-** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
-** before calling sqlite3_initialize() or any other public sqlite3_
-** function that calls sqlite3_initialize().
-**
-** ^The sqlite3_mutex_alloc() routine allocates a new
-** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc()
-** routine returns NULL if it is unable to allocate the requested
-** mutex. The argument to sqlite3_mutex_alloc() must one of these
-** integer constants:
-**
-** <ul>
-** <li> SQLITE_MUTEX_FAST
-** <li> SQLITE_MUTEX_RECURSIVE
-** <li> SQLITE_MUTEX_STATIC_MASTER
-** <li> SQLITE_MUTEX_STATIC_MEM
-** <li> SQLITE_MUTEX_STATIC_OPEN
-** <li> SQLITE_MUTEX_STATIC_PRNG
-** <li> SQLITE_MUTEX_STATIC_LRU
-** <li> SQLITE_MUTEX_STATIC_PMEM
-** <li> SQLITE_MUTEX_STATIC_APP1
-** <li> SQLITE_MUTEX_STATIC_APP2
-** <li> SQLITE_MUTEX_STATIC_APP3
-** <li> SQLITE_MUTEX_STATIC_VFS1
-** <li> SQLITE_MUTEX_STATIC_VFS2
-** <li> SQLITE_MUTEX_STATIC_VFS3
-** </ul>
-**
-** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
-** cause sqlite3_mutex_alloc() to create
-** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
-** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
-** The mutex implementation does not need to make a distinction
-** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
-** not want to. SQLite will only request a recursive mutex in
-** cases where it really needs one. If a faster non-recursive mutex
-** implementation is available on the host platform, the mutex subsystem
-** might return such a mutex in response to SQLITE_MUTEX_FAST.
-**
-** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other
-** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return
-** a pointer to a static preexisting mutex. ^Nine static mutexes are
-** used by the current version of SQLite. Future versions of SQLite
-** may add additional static mutexes. Static mutexes are for internal
-** use by SQLite only. Applications that use SQLite mutexes should
-** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
-** SQLITE_MUTEX_RECURSIVE.
-**
-** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
-** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call. ^For the static
-** mutex types, the same mutex is returned on every call that has
-** the same type number.
-**
-** ^The sqlite3_mutex_free() routine deallocates a previously
-** allocated dynamic mutex. Attempting to deallocate a static
-** mutex results in undefined behavior.
-**
-** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
-** to enter a mutex. ^If another thread is already within the mutex,
-** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
-** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK]
-** upon successful entry. ^(Mutexes created using
-** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread.
-** In such cases, the
-** mutex must be exited an equal number of times before another thread
-** can enter.)^ If the same thread tries to enter any mutex other
-** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined.
-**
-** ^(Some systems (for example, Windows 95) do not support the operation
-** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
-** will always return SQLITE_BUSY. The SQLite core only ever uses
-** sqlite3_mutex_try() as an optimization so this is acceptable
-** behavior.)^
-**
-** ^The sqlite3_mutex_leave() routine exits a mutex that was
-** previously entered by the same thread. The behavior
-** is undefined if the mutex is not currently entered by the
-** calling thread or is not currently allocated.
-**
-** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
-** sqlite3_mutex_leave() is a NULL pointer, then all three routines
-** behave as no-ops.
-**
-** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
-*/
-sqlite3_mutex *sqlite3_mutex_alloc(int);
-void sqlite3_mutex_free(sqlite3_mutex*);
-void sqlite3_mutex_enter(sqlite3_mutex*);
-int sqlite3_mutex_try(sqlite3_mutex*);
-void sqlite3_mutex_leave(sqlite3_mutex*);
-
-/*
-** CAPI3REF: Mutex Methods Object
-**
-** An instance of this structure defines the low-level routines
-** used to allocate and use mutexes.
-**
-** Usually, the default mutex implementations provided by SQLite are
-** sufficient, however the application has the option of substituting a custom
-** implementation for specialized deployments or systems for which SQLite
-** does not provide a suitable implementation. In this case, the application
-** creates and populates an instance of this structure to pass
-** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option.
-** Additionally, an instance of this structure can be used as an
-** output variable when querying the system for the current mutex
-** implementation, using the [SQLITE_CONFIG_GETMUTEX] option.
-**
-** ^The xMutexInit method defined by this structure is invoked as
-** part of system initialization by the sqlite3_initialize() function.
-** ^The xMutexInit routine is called by SQLite exactly once for each
-** effective call to [sqlite3_initialize()].
-**
-** ^The xMutexEnd method defined by this structure is invoked as
-** part of system shutdown by the sqlite3_shutdown() function. The
-** implementation of this method is expected to release all outstanding
-** resources obtained by the mutex methods implementation, especially
-** those obtained by the xMutexInit method. ^The xMutexEnd()
-** interface is invoked exactly once for each call to [sqlite3_shutdown()].
-**
-** ^(The remaining seven methods defined by this structure (xMutexAlloc,
-** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and
-** xMutexNotheld) implement the following interfaces (respectively):
-**
-** <ul>
-** <li> [sqlite3_mutex_alloc()] </li>
-** <li> [sqlite3_mutex_free()] </li>
-** <li> [sqlite3_mutex_enter()] </li>
-** <li> [sqlite3_mutex_try()] </li>
-** <li> [sqlite3_mutex_leave()] </li>
-** <li> [sqlite3_mutex_held()] </li>
-** <li> [sqlite3_mutex_notheld()] </li>
-** </ul>)^
-**
-** The only difference is that the public sqlite3_XXX functions enumerated
-** above silently ignore any invocations that pass a NULL pointer instead
-** of a valid mutex handle. The implementations of the methods defined
-** by this structure are not required to handle this case, the results
-** of passing a NULL pointer instead of a valid mutex handle are undefined
-** (i.e. it is acceptable to provide an implementation that segfaults if
-** it is passed a NULL pointer).
-**
-** The xMutexInit() method must be threadsafe. It must be harmless to
-** invoke xMutexInit() multiple times within the same process and without
-** intervening calls to xMutexEnd(). Second and subsequent calls to
-** xMutexInit() must be no-ops.
-**
-** xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()]
-** and its associates). Similarly, xMutexAlloc() must not use SQLite memory
-** allocation for a static mutex. ^However xMutexAlloc() may use SQLite
-** memory allocation for a fast or recursive mutex.
-**
-** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is
-** called, but only if the prior call to xMutexInit returned SQLITE_OK.
-** If xMutexInit fails in any way, it is expected to clean up after itself
-** prior to returning.
-*/
-typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
-struct sqlite3_mutex_methods {
- int (*xMutexInit)(void);
- int (*xMutexEnd)(void);
- sqlite3_mutex *(*xMutexAlloc)(int);
- void (*xMutexFree)(sqlite3_mutex *);
- void (*xMutexEnter)(sqlite3_mutex *);
- int (*xMutexTry)(sqlite3_mutex *);
- void (*xMutexLeave)(sqlite3_mutex *);
- int (*xMutexHeld)(sqlite3_mutex *);
- int (*xMutexNotheld)(sqlite3_mutex *);
-};
-
-/*
-** CAPI3REF: Mutex Verification Routines
-**
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines
-** are intended for use inside assert() statements. The SQLite core
-** never uses these routines except inside an assert() and applications
-** are advised to follow the lead of the core. The SQLite core only
-** provides implementations for these routines when it is compiled
-** with the SQLITE_DEBUG flag. External mutex implementations
-** are only required to provide these routines if SQLITE_DEBUG is
-** defined and if NDEBUG is not defined.
-**
-** These routines should return true if the mutex in their argument
-** is held or not held, respectively, by the calling thread.
-**
-** The implementation is not required to provide versions of these
-** routines that actually work. If the implementation does not provide working
-** versions of these routines, it should at least provide stubs that always
-** return true so that one does not get spurious assertion failures.
-**
-** If the argument to sqlite3_mutex_held() is a NULL pointer then
-** the routine should return 1. This seems counter-intuitive since
-** clearly the mutex cannot be held if it does not exist. But
-** the reason the mutex does not exist is because the build is not
-** using mutexes. And we do not want the assert() containing the
-** call to sqlite3_mutex_held() to fail, so a non-zero return is
-** the appropriate thing to do. The sqlite3_mutex_notheld()
-** interface should also return 1 when given a NULL pointer.
-*/
-#ifndef NDEBUG
-int sqlite3_mutex_held(sqlite3_mutex*);
-int sqlite3_mutex_notheld(sqlite3_mutex*);
-#endif
-
-/*
-** CAPI3REF: Mutex Types
-**
-** The [sqlite3_mutex_alloc()] interface takes a single argument
-** which is one of these integer constants.
-**
-** The set of static mutexes may change from one SQLite release to the
-** next. Applications that override the built-in mutex logic must be
-** prepared to accommodate additional static mutexes.
-*/
-#define SQLITE_MUTEX_FAST 0
-#define SQLITE_MUTEX_RECURSIVE 1
-#define SQLITE_MUTEX_STATIC_MASTER 2
-#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
-#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */
-#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
-#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */
-#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
-#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
-#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
-#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
-#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
-#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
-#define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */
-#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */
-#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */
-
-/*
-** CAPI3REF: Retrieve the mutex for a database connection
-** METHOD: sqlite3
-**
-** ^This interface returns a pointer the [sqlite3_mutex] object that
-** serializes access to the [database connection] given in the argument
-** when the [threading mode] is Serialized.
-** ^If the [threading mode] is Single-thread or Multi-thread then this
-** routine returns a NULL pointer.
-*/
-sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
-
-/*
-** CAPI3REF: Low-Level Control Of Database Files
-** METHOD: sqlite3
-**
-** ^The [sqlite3_file_control()] interface makes a direct call to the
-** xFileControl method for the [sqlite3_io_methods] object associated
-** with a particular database identified by the second argument. ^The
-** name of the database is "main" for the main database or "temp" for the
-** TEMP database, or the name that appears after the AS keyword for
-** databases that are added using the [ATTACH] SQL command.
-** ^A NULL pointer can be used in place of "main" to refer to the
-** main database file.
-** ^The third and fourth parameters to this routine
-** are passed directly through to the second and third parameters of
-** the xFileControl method. ^The return value of the xFileControl
-** method becomes the return value of this routine.
-**
-** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
-** a pointer to the underlying [sqlite3_file] object to be written into
-** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER]
-** case is a short-circuit path which does not actually invoke the
-** underlying sqlite3_io_methods.xFileControl method.
-**
-** ^If the second parameter (zDbName) does not match the name of any
-** open database file, then SQLITE_ERROR is returned. ^This error
-** code is not remembered and will not be recalled by [sqlite3_errcode()]
-** or [sqlite3_errmsg()]. The underlying xFileControl method might
-** also return SQLITE_ERROR. There is no way to distinguish between
-** an incorrect zDbName and an SQLITE_ERROR return from the underlying
-** xFileControl method.
-**
-** See also: [file control opcodes]
-*/
-int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
-
-/*
-** CAPI3REF: Testing Interface
-**
-** ^The sqlite3_test_control() interface is used to read out internal
-** state of SQLite and to inject faults into SQLite for testing
-** purposes. ^The first parameter is an operation code that determines
-** the number, meaning, and operation of all subsequent parameters.
-**
-** This interface is not for use by applications. It exists solely
-** for verifying the correct operation of the SQLite library. Depending
-** on how the SQLite library is compiled, this interface might not exist.
-**
-** The details of the operation codes, their meanings, the parameters
-** they take, and what they do are all subject to change without notice.
-** Unlike most of the SQLite API, this function is not guaranteed to
-** operate consistently from one release to the next.
-*/
-int sqlite3_test_control(int op, ...);
-
-/*
-** CAPI3REF: Testing Interface Operation Codes
-**
-** These constants are the valid operation code parameters used
-** as the first argument to [sqlite3_test_control()].
-**
-** These parameters and their meanings are subject to change
-** without notice. These values are for testing purposes only.
-** Applications should not use any of these parameters or the
-** [sqlite3_test_control()] interface.
-*/
-#define SQLITE_TESTCTRL_FIRST 5
-#define SQLITE_TESTCTRL_PRNG_SAVE 5
-#define SQLITE_TESTCTRL_PRNG_RESTORE 6
-#define SQLITE_TESTCTRL_PRNG_RESET 7
-#define SQLITE_TESTCTRL_BITVEC_TEST 8
-#define SQLITE_TESTCTRL_FAULT_INSTALL 9
-#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
-#define SQLITE_TESTCTRL_PENDING_BYTE 11
-#define SQLITE_TESTCTRL_ASSERT 12
-#define SQLITE_TESTCTRL_ALWAYS 13
-#define SQLITE_TESTCTRL_RESERVE 14
-#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
-#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
-#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
-#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
-#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
-#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
-#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
-#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
-#define SQLITE_TESTCTRL_BYTEORDER 22
-#define SQLITE_TESTCTRL_ISINIT 23
-#define SQLITE_TESTCTRL_SORTER_MMAP 24
-#define SQLITE_TESTCTRL_IMPOSTER 25
-#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
-#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */
-
-/*
-** CAPI3REF: SQL Keyword Checking
-**
-** These routines provide access to the set of SQL language keywords
-** recognized by SQLite. Applications can uses these routines to determine
-** whether or not a specific identifier needs to be escaped (for example,
-** by enclosing in double-quotes) so as not to confuse the parser.
-**
-** The sqlite3_keyword_count() interface returns the number of distinct
-** keywords understood by SQLite.
-**
-** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
-** makes *Z point to that keyword expressed as UTF8 and writes the number
-** of bytes in the keyword into *L. The string that *Z points to is not
-** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
-** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
-** or L are NULL or invalid pointers then calls to
-** sqlite3_keyword_name(N,Z,L) result in undefined behavior.
-**
-** The sqlite3_keyword_check(Z,L) interface checks to see whether or not
-** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero
-** if it is and zero if not.
-**
-** The parser used by SQLite is forgiving. It is often possible to use
-** a keyword as an identifier as long as such use does not result in a
-** parsing ambiguity. For example, the statement
-** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and
-** creates a new table named "BEGIN" with three columns named
-** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid
-** using keywords as identifiers. Common techniques used to avoid keyword
-** name collisions include:
-** <ul>
-** <li> Put all identifier names inside double-quotes. This is the official
-** SQL way to escape identifier names.
-** <li> Put identifier names inside &#91;...&#93;. This is not standard SQL,
-** but it is what SQL Server does and so lots of programmers use this
-** technique.
-** <li> Begin every identifier with the letter "Z" as no SQL keywords start
-** with "Z".
-** <li> Include a digit somewhere in every identifier name.
-** </ul>
-**
-** Note that the number of keywords understood by SQLite can depend on
-** compile-time options. For example, "VACUUM" is not a keyword if
-** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also,
-** new keywords may be added to future releases of SQLite.
-*/
-int sqlite3_keyword_count(void);
-int sqlite3_keyword_name(int,const char**,int*);
-int sqlite3_keyword_check(const char*,int);
-
-/*
-** CAPI3REF: Dynamic String Object
-** KEYWORDS: {dynamic string}
-**
-** An instance of the sqlite3_str object contains a dynamically-sized
-** string under construction.
-**
-** The lifecycle of an sqlite3_str object is as follows:
-** <ol>
-** <li> ^The sqlite3_str object is created using [sqlite3_str_new()].
-** <li> ^Text is appended to the sqlite3_str object using various
-** methods, such as [sqlite3_str_appendf()].
-** <li> ^The sqlite3_str object is destroyed and the string it created
-** is returned using the [sqlite3_str_finish()] interface.
-** </ol>
-*/
-typedef struct sqlite3_str sqlite3_str;
-
-/*
-** CAPI3REF: Create A New Dynamic String Object
-** CONSTRUCTOR: sqlite3_str
-**
-** ^The [sqlite3_str_new(D)] interface allocates and initializes
-** a new [sqlite3_str] object. To avoid memory leaks, the object returned by
-** [sqlite3_str_new()] must be freed by a subsequent call to
-** [sqlite3_str_finish(X)].
-**
-** ^The [sqlite3_str_new(D)] interface always returns a pointer to a
-** valid [sqlite3_str] object, though in the event of an out-of-memory
-** error the returned object might be a special singleton that will
-** silently reject new text, always return SQLITE_NOMEM from
-** [sqlite3_str_errcode()], always return 0 for
-** [sqlite3_str_length()], and always return NULL from
-** [sqlite3_str_finish(X)]. It is always safe to use the value
-** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter
-** to any of the other [sqlite3_str] methods.
-**
-** The D parameter to [sqlite3_str_new(D)] may be NULL. If the
-** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum
-** length of the string contained in the [sqlite3_str] object will be
-** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead
-** of [SQLITE_MAX_LENGTH].
-*/
-sqlite3_str *sqlite3_str_new(sqlite3*);
-
-/*
-** CAPI3REF: Finalize A Dynamic String
-** DESTRUCTOR: sqlite3_str
-**
-** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X
-** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()]
-** that contains the constructed string. The calling application should
-** pass the returned value to [sqlite3_free()] to avoid a memory leak.
-** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any
-** errors were encountered during construction of the string. ^The
-** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the
-** string in [sqlite3_str] object X is zero bytes long.
-*/
-char *sqlite3_str_finish(sqlite3_str*);
-
-/*
-** CAPI3REF: Add Content To A Dynamic String
-** METHOD: sqlite3_str
-**
-** These interfaces add content to an sqlite3_str object previously obtained
-** from [sqlite3_str_new()].
-**
-** ^The [sqlite3_str_appendf(X,F,...)] and
-** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf]
-** functionality of SQLite to append formatted text onto the end of
-** [sqlite3_str] object X.
-**
-** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S
-** onto the end of the [sqlite3_str] object X. N must be non-negative.
-** S must contain at least N non-zero bytes of content. To append a
-** zero-terminated string in its entirety, use the [sqlite3_str_appendall()]
-** method instead.
-**
-** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of
-** zero-terminated string S onto the end of [sqlite3_str] object X.
-**
-** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the
-** single-byte character C onto the end of [sqlite3_str] object X.
-** ^This method can be used, for example, to add whitespace indentation.
-**
-** ^The [sqlite3_str_reset(X)] method resets the string under construction
-** inside [sqlite3_str] object X back to zero bytes in length.
-**
-** These methods do not return a result code. ^If an error occurs, that fact
-** is recorded in the [sqlite3_str] object and can be recovered by a
-** subsequent call to [sqlite3_str_errcode(X)].
-*/
-void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...);
-void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list);
-void sqlite3_str_append(sqlite3_str*, const char *zIn, int N);
-void sqlite3_str_appendall(sqlite3_str*, const char *zIn);
-void sqlite3_str_appendchar(sqlite3_str*, int N, char C);
-void sqlite3_str_reset(sqlite3_str*);
-
-/*
-** CAPI3REF: Status Of A Dynamic String
-** METHOD: sqlite3_str
-**
-** These interfaces return the current status of an [sqlite3_str] object.
-**
-** ^If any prior errors have occurred while constructing the dynamic string
-** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return
-** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns
-** [SQLITE_NOMEM] following any out-of-memory error, or
-** [SQLITE_TOOBIG] if the size of the dynamic string exceeds
-** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors.
-**
-** ^The [sqlite3_str_length(X)] method returns the current length, in bytes,
-** of the dynamic string under construction in [sqlite3_str] object X.
-** ^The length returned by [sqlite3_str_length(X)] does not include the
-** zero-termination byte.
-**
-** ^The [sqlite3_str_value(X)] method returns a pointer to the current
-** content of the dynamic string under construction in X. The value
-** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
-** and might be freed or altered by any subsequent method on the same
-** [sqlite3_str] object. Applications must not used the pointer returned
-** [sqlite3_str_value(X)] after any subsequent method call on the same
-** object. ^Applications may change the content of the string returned
-** by [sqlite3_str_value(X)] as long as they do not write into any bytes
-** outside the range of 0 to [sqlite3_str_length(X)] and do not read or
-** write any byte after any subsequent sqlite3_str method call.
-*/
-int sqlite3_str_errcode(sqlite3_str*);
-int sqlite3_str_length(sqlite3_str*);
-char *sqlite3_str_value(sqlite3_str*);
-
-/*
-** CAPI3REF: SQLite Runtime Status
-**
-** ^These interfaces are used to retrieve runtime status information
-** about the performance of SQLite, and optionally to reset various
-** highwater marks. ^The first argument is an integer code for
-** the specific parameter to measure. ^(Recognized integer codes
-** are of the form [status parameters | SQLITE_STATUS_...].)^
-** ^The current value of the parameter is returned into *pCurrent.
-** ^The highest recorded value is returned in *pHighwater. ^If the
-** resetFlag is true, then the highest record value is reset after
-** *pHighwater is written. ^(Some parameters do not record the highest
-** value. For those parameters
-** nothing is written into *pHighwater and the resetFlag is ignored.)^
-** ^(Other parameters record only the highwater mark and not the current
-** value. For these latter parameters nothing is written into *pCurrent.)^
-**
-** ^The sqlite3_status() and sqlite3_status64() routines return
-** SQLITE_OK on success and a non-zero [error code] on failure.
-**
-** If either the current value or the highwater mark is too large to
-** be represented by a 32-bit integer, then the values returned by
-** sqlite3_status() are undefined.
-**
-** See also: [sqlite3_db_status()]
-*/
-int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
-int sqlite3_status64(
- int op,
- sqlite3_int64 *pCurrent,
- sqlite3_int64 *pHighwater,
- int resetFlag
-);
-
-
-/*
-** CAPI3REF: Status Parameters
-** KEYWORDS: {status parameters}
-**
-** These integer constants designate various run-time status parameters
-** that can be returned by [sqlite3_status()].
-**
-** <dl>
-** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
-** <dd>This parameter is the current amount of memory checked out
-** using [sqlite3_malloc()], either directly or indirectly. The
-** figure includes calls made to [sqlite3_malloc()] by the application
-** and internal memory usage by the SQLite library. Auxiliary page-cache
-** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
-** this parameter. The amount returned is the sum of the allocation
-** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
-**
-** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
-** <dd>This parameter records the largest memory allocation request
-** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
-** internal equivalents). Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
-** The value written into the *pCurrent parameter is undefined.</dd>)^
-**
-** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
-** <dd>This parameter records the number of separate memory allocations
-** currently checked out.</dd>)^
-**
-** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
-** <dd>This parameter returns the number of pages used out of the
-** [pagecache memory allocator] that was configured using
-** [SQLITE_CONFIG_PAGECACHE]. The
-** value returned is in pages, not in bytes.</dd>)^
-**
-** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
-** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
-** <dd>This parameter returns the number of bytes of page cache
-** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
-** buffer and where forced to overflow to [sqlite3_malloc()]. The
-** returned value includes allocations that overflowed because they
-** where too large (they were larger than the "sz" parameter to
-** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
-** no space was left in the page cache.</dd>)^
-**
-** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
-** <dd>This parameter records the largest memory allocation request
-** handed to [pagecache memory allocator]. Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
-** The value written into the *pCurrent parameter is undefined.</dd>)^
-**
-** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt>
-** <dd>No longer used.</dd>
-**
-** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
-** <dd>No longer used.</dd>
-**
-** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
-** <dd>No longer used.</dd>
-**
-** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
-** <dd>The *pHighwater parameter records the deepest parser stack.
-** The *pCurrent value is undefined. The *pHighwater value is only
-** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
-** </dl>
-**
-** New status parameters may be added from time to time.
-*/
-#define SQLITE_STATUS_MEMORY_USED 0
-#define SQLITE_STATUS_PAGECACHE_USED 1
-#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
-#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */
-#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */
-#define SQLITE_STATUS_MALLOC_SIZE 5
-#define SQLITE_STATUS_PARSER_STACK 6
-#define SQLITE_STATUS_PAGECACHE_SIZE 7
-#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */
-#define SQLITE_STATUS_MALLOC_COUNT 9
-
-/*
-** CAPI3REF: Database Connection Status
-** METHOD: sqlite3
-**
-** ^This interface is used to retrieve runtime status information
-** about a single [database connection]. ^The first argument is the
-** database connection object to be interrogated. ^The second argument
-** is an integer constant, taken from the set of
-** [SQLITE_DBSTATUS options], that
-** determines the parameter to interrogate. The set of
-** [SQLITE_DBSTATUS options] is likely
-** to grow in future releases of SQLite.
-**
-** ^The current value of the requested parameter is written into *pCur
-** and the highest instantaneous value is written into *pHiwtr. ^If
-** the resetFlg is true, then the highest instantaneous value is
-** reset back down to the current value.
-**
-** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a
-** non-zero [error code] on failure.
-**
-** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
-*/
-int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
-
-/*
-** CAPI3REF: Status Parameters for database connections
-** KEYWORDS: {SQLITE_DBSTATUS options}
-**
-** These constants are the available integer "verbs" that can be passed as
-** the second argument to the [sqlite3_db_status()] interface.
-**
-** New verbs may be added in future releases of SQLite. Existing verbs
-** might be discontinued. Applications should check the return code from
-** [sqlite3_db_status()] to make sure that the call worked.
-** The [sqlite3_db_status()] interface will return a non-zero error code
-** if a discontinued or unsupported verb is invoked.
-**
-** <dl>
-** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
-** <dd>This parameter returns the number of lookaside memory slots currently
-** checked out.</dd>)^
-**
-** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
-** <dd>This parameter returns the number malloc attempts that were
-** satisfied using lookaside memory. Only the high-water value is meaningful;
-** the current value is always zero.)^
-**
-** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
-** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
-** <dd>This parameter returns the number malloc attempts that might have
-** been satisfied using lookaside memory but failed due to the amount of
-** memory requested being larger than the lookaside slot size.
-** Only the high-water value is meaningful;
-** the current value is always zero.)^
-**
-** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
-** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
-** <dd>This parameter returns the number malloc attempts that might have
-** been satisfied using lookaside memory but failed due to all lookaside
-** memory already being in use.
-** Only the high-water value is meaningful;
-** the current value is always zero.)^
-**
-** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
-** <dd>This parameter returns the approximate number of bytes of heap
-** memory used by all pager caches associated with the database connection.)^
-** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
-**
-** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]]
-** ^(<dt>SQLITE_DBSTATUS_CACHE_USED_SHARED</dt>
-** <dd>This parameter is similar to DBSTATUS_CACHE_USED, except that if a
-** pager cache is shared between two or more connections the bytes of heap
-** memory used by that pager cache is divided evenly between the attached
-** connections.)^ In other words, if none of the pager caches associated
-** with the database connection are shared, this request returns the same
-** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are
-** shared, the value returned by this call will be smaller than that returned
-** by DBSTATUS_CACHE_USED. ^The highwater mark associated with
-** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
-**
-** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
-** <dd>This parameter returns the approximate number of bytes of heap
-** memory used to store the schema for all databases associated
-** with the connection - main, temp, and any [ATTACH]-ed databases.)^
-** ^The full amount of memory used by the schemas is reported, even if the
-** schema memory is shared with other database connections due to
-** [shared cache mode] being enabled.
-** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
-**
-** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
-** <dd>This parameter returns the approximate number of bytes of heap
-** and lookaside memory used by all prepared statements associated with
-** the database connection.)^
-** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
-** </dd>
-**
-** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
-** <dd>This parameter returns the number of pager cache hits that have
-** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
-** is always 0.
-** </dd>
-**
-** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
-** <dd>This parameter returns the number of pager cache misses that have
-** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
-** is always 0.
-** </dd>
-**
-** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
-** <dd>This parameter returns the number of dirty cache entries that have
-** been written to disk. Specifically, the number of pages written to the
-** wal file in wal mode databases, or the number of pages written to the
-** database file in rollback mode databases. Any pages written as part of
-** transaction rollback or database recovery operations are not included.
-** If an IO or other error occurs while writing a page to disk, the effect
-** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
-** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
-** </dd>
-**
-** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt>
-** <dd>This parameter returns the number of dirty cache entries that have
-** been written to disk in the middle of a transaction due to the page
-** cache overflowing. Transactions are more efficient if they are written
-** to disk all at once. When pages spill mid-transaction, that introduces
-** additional overhead. This parameter can be used help identify
-** inefficiencies that can be resolve by increasing the cache size.
-** </dd>
-**
-** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
-** <dd>This parameter returns zero for the current value if and only if
-** all foreign key constraints (deferred or immediate) have been
-** resolved.)^ ^The highwater mark is always 0.
-** </dd>
-** </dl>
-*/
-#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
-#define SQLITE_DBSTATUS_CACHE_USED 1
-#define SQLITE_DBSTATUS_SCHEMA_USED 2
-#define SQLITE_DBSTATUS_STMT_USED 3
-#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
-#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
-#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
-#define SQLITE_DBSTATUS_CACHE_HIT 7
-#define SQLITE_DBSTATUS_CACHE_MISS 8
-#define SQLITE_DBSTATUS_CACHE_WRITE 9
-#define SQLITE_DBSTATUS_DEFERRED_FKS 10
-#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11
-#define SQLITE_DBSTATUS_CACHE_SPILL 12
-#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */
-
-
-/*
-** CAPI3REF: Prepared Statement Status
-** METHOD: sqlite3_stmt
-**
-** ^(Each prepared statement maintains various
-** [SQLITE_STMTSTATUS counters] that measure the number
-** of times it has performed specific operations.)^ These counters can
-** be used to monitor the performance characteristics of the prepared
-** statements. For example, if the number of table steps greatly exceeds
-** the number of table searches or result rows, that would tend to indicate
-** that the prepared statement is using a full table scan rather than
-** an index.
-**
-** ^(This interface is used to retrieve and reset counter values from
-** a [prepared statement]. The first argument is the prepared statement
-** object to be interrogated. The second argument
-** is an integer code for a specific [SQLITE_STMTSTATUS counter]
-** to be interrogated.)^
-** ^The current value of the requested counter is returned.
-** ^If the resetFlg is true, then the counter is reset to zero after this
-** interface call returns.
-**
-** See also: [sqlite3_status()] and [sqlite3_db_status()].
-*/
-int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
-
-/*
-** CAPI3REF: Status Parameters for prepared statements
-** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
-**
-** These preprocessor macros define integer codes that name counter
-** values associated with the [sqlite3_stmt_status()] interface.
-** The meanings of the various counters are as follows:
-**
-** <dl>
-** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
-** <dd>^This is the number of times that SQLite has stepped forward in
-** a table as part of a full table scan. Large numbers for this counter
-** may indicate opportunities for performance improvement through
-** careful use of indices.</dd>
-**
-** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
-** <dd>^This is the number of sort operations that have occurred.
-** A non-zero value in this counter may indicate an opportunity to
-** improvement performance through careful use of indices.</dd>
-**
-** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
-** <dd>^This is the number of rows inserted into transient indices that
-** were created automatically in order to help joins run faster.
-** A non-zero value in this counter may indicate an opportunity to
-** improvement performance by adding permanent indices that do not
-** need to be reinitialized each time the statement is run.</dd>
-**
-** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
-** <dd>^This is the number of virtual machine operations executed
-** by the prepared statement if that number is less than or equal
-** to 2147483647. The number of virtual machine operations can be
-** used as a proxy for the total work done by the prepared statement.
-** If the number of virtual machine operations exceeds 2147483647
-** then the value returned by this statement status code is undefined.
-**
-** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
-** <dd>^This is the number of times that the prepare statement has been
-** automatically regenerated due to schema changes or change to
-** [bound parameters] that might affect the query plan.
-**
-** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
-** <dd>^This is the number of times that the prepared statement has
-** been run. A single "run" for the purposes of this counter is one
-** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
-** The counter is incremented on the first [sqlite3_step()] call of each
-** cycle.
-**
-** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
-** <dd>^This is the approximate number of bytes of heap memory
-** used to store the prepared statement. ^This value is not actually
-** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
-** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
-** </dd>
-** </dl>
-*/
-#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
-#define SQLITE_STMTSTATUS_SORT 2
-#define SQLITE_STMTSTATUS_AUTOINDEX 3
-#define SQLITE_STMTSTATUS_VM_STEP 4
-#define SQLITE_STMTSTATUS_REPREPARE 5
-#define SQLITE_STMTSTATUS_RUN 6
-#define SQLITE_STMTSTATUS_MEMUSED 99
-
-/*
-** CAPI3REF: Custom Page Cache Object
-**
-** The sqlite3_pcache type is opaque. It is implemented by
-** the pluggable module. The SQLite core has no knowledge of
-** its size or internal structure and never deals with the
-** sqlite3_pcache object except by holding and passing pointers
-** to the object.
-**
-** See [sqlite3_pcache_methods2] for additional information.
-*/
-typedef struct sqlite3_pcache sqlite3_pcache;
-
-/*
-** CAPI3REF: Custom Page Cache Object
-**
-** The sqlite3_pcache_page object represents a single page in the
-** page cache. The page cache will allocate instances of this
-** object. Various methods of the page cache use pointers to instances
-** of this object as parameters or as their return value.
-**
-** See [sqlite3_pcache_methods2] for additional information.
-*/
-typedef struct sqlite3_pcache_page sqlite3_pcache_page;
-struct sqlite3_pcache_page {
- void *pBuf; /* The content of the page */
- void *pExtra; /* Extra information associated with the page */
-};
-
-/*
-** CAPI3REF: Application Defined Page Cache.
-** KEYWORDS: {page cache}
-**
-** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
-** register an alternative page cache implementation by passing in an
-** instance of the sqlite3_pcache_methods2 structure.)^
-** In many applications, most of the heap memory allocated by
-** SQLite is used for the page cache.
-** By implementing a
-** custom page cache using this API, an application can better control
-** the amount of memory consumed by SQLite, the way in which
-** that memory is allocated and released, and the policies used to
-** determine exactly which parts of a database file are cached and for
-** how long.
-**
-** The alternative page cache mechanism is an
-** extreme measure that is only needed by the most demanding applications.
-** The built-in page cache is recommended for most uses.
-**
-** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an
-** internal buffer by SQLite within the call to [sqlite3_config]. Hence
-** the application may discard the parameter after the call to
-** [sqlite3_config()] returns.)^
-**
-** [[the xInit() page cache method]]
-** ^(The xInit() method is called once for each effective
-** call to [sqlite3_initialize()])^
-** (usually only once during the lifetime of the process). ^(The xInit()
-** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^
-** The intent of the xInit() method is to set up global data structures
-** required by the custom page cache implementation.
-** ^(If the xInit() method is NULL, then the
-** built-in default page cache is used instead of the application defined
-** page cache.)^
-**
-** [[the xShutdown() page cache method]]
-** ^The xShutdown() method is called by [sqlite3_shutdown()].
-** It can be used to clean up
-** any outstanding resources before process shutdown, if required.
-** ^The xShutdown() method may be NULL.
-**
-** ^SQLite automatically serializes calls to the xInit method,
-** so the xInit method need not be threadsafe. ^The
-** xShutdown method is only called from [sqlite3_shutdown()] so it does
-** not need to be threadsafe either. All other methods must be threadsafe
-** in multithreaded applications.
-**
-** ^SQLite will never invoke xInit() more than once without an intervening
-** call to xShutdown().
-**
-** [[the xCreate() page cache methods]]
-** ^SQLite invokes the xCreate() method to construct a new cache instance.
-** SQLite will typically create one cache instance for each open database file,
-** though this is not guaranteed. ^The
-** first parameter, szPage, is the size in bytes of the pages that must
-** be allocated by the cache. ^szPage will always a power of two. ^The
-** second parameter szExtra is a number of bytes of extra storage
-** associated with each page cache entry. ^The szExtra parameter will
-** a number less than 250. SQLite will use the
-** extra szExtra bytes on each page to store metadata about the underlying
-** database page on disk. The value passed into szExtra depends
-** on the SQLite version, the target platform, and how SQLite was compiled.
-** ^The third argument to xCreate(), bPurgeable, is true if the cache being
-** created will be used to cache database pages of a file stored on disk, or
-** false if it is used for an in-memory database. The cache implementation
-** does not have to do anything special based with the value of bPurgeable;
-** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
-** never invoke xUnpin() except to deliberately delete a page.
-** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
-** false will always have the "discard" flag set to true.
-** ^Hence, a cache created with bPurgeable false will
-** never contain any unpinned pages.
-**
-** [[the xCachesize() page cache method]]
-** ^(The xCachesize() method may be called at any time by SQLite to set the
-** suggested maximum cache-size (number of pages stored by) the cache
-** instance passed as the first argument. This is the value configured using
-** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
-** parameter, the implementation is not required to do anything with this
-** value; it is advisory only.
-**
-** [[the xPagecount() page cache methods]]
-** The xPagecount() method must return the number of pages currently
-** stored in the cache, both pinned and unpinned.
-**
-** [[the xFetch() page cache methods]]
-** The xFetch() method locates a page in the cache and returns a pointer to
-** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
-** The pBuf element of the returned sqlite3_pcache_page object will be a
-** pointer to a buffer of szPage bytes used to store the content of a
-** single database page. The pExtra element of sqlite3_pcache_page will be
-** a pointer to the szExtra bytes of extra storage that SQLite has requested
-** for each entry in the page cache.
-**
-** The page to be fetched is determined by the key. ^The minimum key value
-** is 1. After it has been retrieved using xFetch, the page is considered
-** to be "pinned".
-**
-** If the requested page is already in the page cache, then the page cache
-** implementation must return a pointer to the page buffer with its content
-** intact. If the requested page is not already in the cache, then the
-** cache implementation should use the value of the createFlag
-** parameter to help it determined what action to take:
-**
-** <table border=1 width=85% align=center>
-** <tr><th> createFlag <th> Behavior when page is not already in cache
-** <tr><td> 0 <td> Do not allocate a new page. Return NULL.
-** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
-** Otherwise return NULL.
-** <tr><td> 2 <td> Make every effort to allocate a new page. Only return
-** NULL if allocating a new page is effectively impossible.
-** </table>
-**
-** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
-** will only use a createFlag of 2 after a prior call with a createFlag of 1
-** failed.)^ In between the to xFetch() calls, SQLite may
-** attempt to unpin one or more cache pages by spilling the content of
-** pinned pages to disk and synching the operating system disk cache.
-**
-** [[the xUnpin() page cache method]]
-** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
-** as its second argument. If the third parameter, discard, is non-zero,
-** then the page must be evicted from the cache.
-** ^If the discard parameter is
-** zero, then the page may be discarded or retained at the discretion of
-** page cache implementation. ^The page cache implementation
-** may choose to evict unpinned pages at any time.
-**
-** The cache must not perform any reference counting. A single
-** call to xUnpin() unpins the page regardless of the number of prior calls
-** to xFetch().
-**
-** [[the xRekey() page cache methods]]
-** The xRekey() method is used to change the key value associated with the
-** page passed as the second argument. If the cache
-** previously contains an entry associated with newKey, it must be
-** discarded. ^Any prior cache entry associated with newKey is guaranteed not
-** to be pinned.
-**
-** When SQLite calls the xTruncate() method, the cache must discard all
-** existing cache entries with page numbers (keys) greater than or equal
-** to the value of the iLimit parameter passed to xTruncate(). If any
-** of these pages are pinned, they are implicitly unpinned, meaning that
-** they can be safely discarded.
-**
-** [[the xDestroy() page cache method]]
-** ^The xDestroy() method is used to delete a cache allocated by xCreate().
-** All resources associated with the specified cache should be freed. ^After
-** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
-** handle invalid, and will not use it with any other sqlite3_pcache_methods2
-** functions.
-**
-** [[the xShrink() page cache method]]
-** ^SQLite invokes the xShrink() method when it wants the page cache to
-** free up as much of heap memory as possible. The page cache implementation
-** is not obligated to free any memory, but well-behaved implementations should
-** do their best.
-*/
-typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
-struct sqlite3_pcache_methods2 {
- int iVersion;
- void *pArg;
- int (*xInit)(void*);
- void (*xShutdown)(void*);
- sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
- void (*xCachesize)(sqlite3_pcache*, int nCachesize);
- int (*xPagecount)(sqlite3_pcache*);
- sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
- void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
- void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
- unsigned oldKey, unsigned newKey);
- void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
- void (*xDestroy)(sqlite3_pcache*);
- void (*xShrink)(sqlite3_pcache*);
-};
-
-/*
-** This is the obsolete pcache_methods object that has now been replaced
-** by sqlite3_pcache_methods2. This object is not used by SQLite. It is
-** retained in the header file for backwards compatibility only.
-*/
-typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
-struct sqlite3_pcache_methods {
- void *pArg;
- int (*xInit)(void*);
- void (*xShutdown)(void*);
- sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
- void (*xCachesize)(sqlite3_pcache*, int nCachesize);
- int (*xPagecount)(sqlite3_pcache*);
- void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
- void (*xUnpin)(sqlite3_pcache*, void*, int discard);
- void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
- void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
- void (*xDestroy)(sqlite3_pcache*);
-};
-
-
-/*
-** CAPI3REF: Online Backup Object
-**
-** The sqlite3_backup object records state information about an ongoing
-** online backup operation. ^The sqlite3_backup object is created by
-** a call to [sqlite3_backup_init()] and is destroyed by a call to
-** [sqlite3_backup_finish()].
-**
-** See Also: [Using the SQLite Online Backup API]
-*/
-typedef struct sqlite3_backup sqlite3_backup;
-
-/*
-** CAPI3REF: Online Backup API.
-**
-** The backup API copies the content of one database into another.
-** It is useful either for creating backups of databases or
-** for copying in-memory databases to or from persistent files.
-**
-** See Also: [Using the SQLite Online Backup API]
-**
-** ^SQLite holds a write transaction open on the destination database file
-** for the duration of the backup operation.
-** ^The source database is read-locked only while it is being read;
-** it is not locked continuously for the entire backup operation.
-** ^Thus, the backup may be performed on a live source database without
-** preventing other database connections from
-** reading or writing to the source database while the backup is underway.
-**
-** ^(To perform a backup operation:
-** <ol>
-** <li><b>sqlite3_backup_init()</b> is called once to initialize the
-** backup,
-** <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
-** the data between the two databases, and finally
-** <li><b>sqlite3_backup_finish()</b> is called to release all resources
-** associated with the backup operation.
-** </ol>)^
-** There should be exactly one call to sqlite3_backup_finish() for each
-** successful call to sqlite3_backup_init().
-**
-** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
-**
-** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
-** [database connection] associated with the destination database
-** and the database name, respectively.
-** ^The database name is "main" for the main database, "temp" for the
-** temporary database, or the name specified after the AS keyword in
-** an [ATTACH] statement for an attached database.
-** ^The S and M arguments passed to
-** sqlite3_backup_init(D,N,S,M) identify the [database connection]
-** and database name of the source database, respectively.
-** ^The source and destination [database connections] (parameters S and D)
-** must be different or else sqlite3_backup_init(D,N,S,M) will fail with
-** an error.
-**
-** ^A call to sqlite3_backup_init() will fail, returning NULL, if
-** there is already a read or read-write transaction open on the
-** destination database.
-**
-** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is
-** returned and an error code and error message are stored in the
-** destination [database connection] D.
-** ^The error code and message for the failed call to sqlite3_backup_init()
-** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or
-** [sqlite3_errmsg16()] functions.
-** ^A successful call to sqlite3_backup_init() returns a pointer to an
-** [sqlite3_backup] object.
-** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
-** sqlite3_backup_finish() functions to perform the specified backup
-** operation.
-**
-** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
-**
-** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
-** the source and destination databases specified by [sqlite3_backup] object B.
-** ^If N is negative, all remaining source pages are copied.
-** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
-** are still more pages to be copied, then the function returns [SQLITE_OK].
-** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
-** from source to destination, then it returns [SQLITE_DONE].
-** ^If an error occurs while running sqlite3_backup_step(B,N),
-** then an [error code] is returned. ^As well as [SQLITE_OK] and
-** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY],
-** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an
-** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code.
-**
-** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if
-** <ol>
-** <li> the destination database was opened read-only, or
-** <li> the destination database is using write-ahead-log journaling
-** and the destination and source page sizes differ, or
-** <li> the destination database is an in-memory database and the
-** destination and source page sizes differ.
-** </ol>)^
-**
-** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
-** the [sqlite3_busy_handler | busy-handler function]
-** is invoked (if one is specified). ^If the
-** busy-handler returns non-zero before the lock is available, then
-** [SQLITE_BUSY] is returned to the caller. ^In this case the call to
-** sqlite3_backup_step() can be retried later. ^If the source
-** [database connection]
-** is being used to write to the source database when sqlite3_backup_step()
-** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this
-** case the call to sqlite3_backup_step() can be retried later on. ^(If
-** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or
-** [SQLITE_READONLY] is returned, then
-** there is no point in retrying the call to sqlite3_backup_step(). These
-** errors are considered fatal.)^ The application must accept
-** that the backup operation has failed and pass the backup operation handle
-** to the sqlite3_backup_finish() to release associated resources.
-**
-** ^The first call to sqlite3_backup_step() obtains an exclusive lock
-** on the destination file. ^The exclusive lock is not released until either
-** sqlite3_backup_finish() is called or the backup operation is complete
-** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to
-** sqlite3_backup_step() obtains a [shared lock] on the source database that
-** lasts for the duration of the sqlite3_backup_step() call.
-** ^Because the source database is not locked between calls to
-** sqlite3_backup_step(), the source database may be modified mid-way
-** through the backup process. ^If the source database is modified by an
-** external process or via a database connection other than the one being
-** used by the backup operation, then the backup will be automatically
-** restarted by the next call to sqlite3_backup_step(). ^If the source
-** database is modified by the using the same database connection as is used
-** by the backup operation, then the backup database is automatically
-** updated at the same time.
-**
-** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
-**
-** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
-** application wishes to abandon the backup operation, the application
-** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
-** ^The sqlite3_backup_finish() interfaces releases all
-** resources associated with the [sqlite3_backup] object.
-** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any
-** active write-transaction on the destination database is rolled back.
-** The [sqlite3_backup] object is invalid
-** and may not be used following a call to sqlite3_backup_finish().
-**
-** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
-** sqlite3_backup_step() errors occurred, regardless or whether or not
-** sqlite3_backup_step() completed.
-** ^If an out-of-memory condition or IO error occurred during any prior
-** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
-** sqlite3_backup_finish() returns the corresponding [error code].
-**
-** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
-** is not a permanent error and does not affect the return value of
-** sqlite3_backup_finish().
-**
-** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
-** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
-**
-** ^The sqlite3_backup_remaining() routine returns the number of pages still
-** to be backed up at the conclusion of the most recent sqlite3_backup_step().
-** ^The sqlite3_backup_pagecount() routine returns the total number of pages
-** in the source database at the conclusion of the most recent
-** sqlite3_backup_step().
-** ^(The values returned by these functions are only updated by
-** sqlite3_backup_step(). If the source database is modified in a way that
-** changes the size of the source database or the number of pages remaining,
-** those changes are not reflected in the output of sqlite3_backup_pagecount()
-** and sqlite3_backup_remaining() until after the next
-** sqlite3_backup_step().)^
-**
-** <b>Concurrent Usage of Database Handles</b>
-**
-** ^The source [database connection] may be used by the application for other
-** purposes while a backup operation is underway or being initialized.
-** ^If SQLite is compiled and configured to support threadsafe database
-** connections, then the source database connection may be used concurrently
-** from within other threads.
-**
-** However, the application must guarantee that the destination
-** [database connection] is not passed to any other API (by any thread) after
-** sqlite3_backup_init() is called and before the corresponding call to
-** sqlite3_backup_finish(). SQLite does not currently check to see
-** if the application incorrectly accesses the destination [database connection]
-** and so no error code is reported, but the operations may malfunction
-** nevertheless. Use of the destination database connection while a
-** backup is in progress might also also cause a mutex deadlock.
-**
-** If running in [shared cache mode], the application must
-** guarantee that the shared cache used by the destination database
-** is not accessed while the backup is running. In practice this means
-** that the application must guarantee that the disk file being
-** backed up to is not accessed by any connection within the process,
-** not just the specific connection that was passed to sqlite3_backup_init().
-**
-** The [sqlite3_backup] object itself is partially threadsafe. Multiple
-** threads may safely make multiple concurrent calls to sqlite3_backup_step().
-** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount()
-** APIs are not strictly speaking threadsafe. If they are invoked at the
-** same time as another thread is invoking sqlite3_backup_step() it is
-** possible that they return invalid values.
-*/
-sqlite3_backup *sqlite3_backup_init(
- sqlite3 *pDest, /* Destination database handle */
- const char *zDestName, /* Destination database name */
- sqlite3 *pSource, /* Source database handle */
- const char *zSourceName /* Source database name */
-);
-int sqlite3_backup_step(sqlite3_backup *p, int nPage);
-int sqlite3_backup_finish(sqlite3_backup *p);
-int sqlite3_backup_remaining(sqlite3_backup *p);
-int sqlite3_backup_pagecount(sqlite3_backup *p);
-
-/*
-** CAPI3REF: Unlock Notification
-** METHOD: sqlite3
-**
-** ^When running in shared-cache mode, a database operation may fail with
-** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
-** individual tables within the shared-cache cannot be obtained. See
-** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
-** ^This API may be used to register a callback that SQLite will invoke
-** when the connection currently holding the required lock relinquishes it.
-** ^This API is only available if the library was compiled with the
-** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined.
-**
-** See Also: [Using the SQLite Unlock Notification Feature].
-**
-** ^Shared-cache locks are released when a database connection concludes
-** its current transaction, either by committing it or rolling it back.
-**
-** ^When a connection (known as the blocked connection) fails to obtain a
-** shared-cache lock and SQLITE_LOCKED is returned to the caller, the
-** identity of the database connection (the blocking connection) that
-** has locked the required resource is stored internally. ^After an
-** application receives an SQLITE_LOCKED error, it may call the
-** sqlite3_unlock_notify() method with the blocked connection handle as
-** the first argument to register for a callback that will be invoked
-** when the blocking connections current transaction is concluded. ^The
-** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
-** call that concludes the blocking connections transaction.
-**
-** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
-** there is a chance that the blocking connection will have already
-** concluded its transaction by the time sqlite3_unlock_notify() is invoked.
-** If this happens, then the specified callback is invoked immediately,
-** from within the call to sqlite3_unlock_notify().)^
-**
-** ^If the blocked connection is attempting to obtain a write-lock on a
-** shared-cache table, and more than one other connection currently holds
-** a read-lock on the same table, then SQLite arbitrarily selects one of
-** the other connections to use as the blocking connection.
-**
-** ^(There may be at most one unlock-notify callback registered by a
-** blocked connection. If sqlite3_unlock_notify() is called when the
-** blocked connection already has a registered unlock-notify callback,
-** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
-** called with a NULL pointer as its second argument, then any existing
-** unlock-notify callback is canceled. ^The blocked connections
-** unlock-notify callback may also be canceled by closing the blocked
-** connection using [sqlite3_close()].
-**
-** The unlock-notify callback is not reentrant. If an application invokes
-** any sqlite3_xxx API functions from within an unlock-notify callback, a
-** crash or deadlock may be the result.
-**
-** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always
-** returns SQLITE_OK.
-**
-** <b>Callback Invocation Details</b>
-**
-** When an unlock-notify callback is registered, the application provides a
-** single void* pointer that is passed to the callback when it is invoked.
-** However, the signature of the callback function allows SQLite to pass
-** it an array of void* context pointers. The first argument passed to
-** an unlock-notify callback is a pointer to an array of void* pointers,
-** and the second is the number of entries in the array.
-**
-** When a blocking connections transaction is concluded, there may be
-** more than one blocked connection that has registered for an unlock-notify
-** callback. ^If two or more such blocked connections have specified the
-** same callback function, then instead of invoking the callback function
-** multiple times, it is invoked once with the set of void* context pointers
-** specified by the blocked connections bundled together into an array.
-** This gives the application an opportunity to prioritize any actions
-** related to the set of unblocked database connections.
-**
-** <b>Deadlock Detection</b>
-**
-** Assuming that after registering for an unlock-notify callback a
-** database waits for the callback to be issued before taking any further
-** action (a reasonable assumption), then using this API may cause the
-** application to deadlock. For example, if connection X is waiting for
-** connection Y's transaction to be concluded, and similarly connection
-** Y is waiting on connection X's transaction, then neither connection
-** will proceed and the system may remain deadlocked indefinitely.
-**
-** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock
-** detection. ^If a given call to sqlite3_unlock_notify() would put the
-** system in a deadlocked state, then SQLITE_LOCKED is returned and no
-** unlock-notify callback is registered. The system is said to be in
-** a deadlocked state if connection A has registered for an unlock-notify
-** callback on the conclusion of connection B's transaction, and connection
-** B has itself registered for an unlock-notify callback when connection
-** A's transaction is concluded. ^Indirect deadlock is also detected, so
-** the system is also considered to be deadlocked if connection B has
-** registered for an unlock-notify callback on the conclusion of connection
-** C's transaction, where connection C is waiting on connection A. ^Any
-** number of levels of indirection are allowed.
-**
-** <b>The "DROP TABLE" Exception</b>
-**
-** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
-** always appropriate to call sqlite3_unlock_notify(). There is however,
-** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement,
-** SQLite checks if there are any currently executing SELECT statements
-** that belong to the same connection. If there are, SQLITE_LOCKED is
-** returned. In this case there is no "blocking connection", so invoking
-** sqlite3_unlock_notify() results in the unlock-notify callback being
-** invoked immediately. If the application then re-attempts the "DROP TABLE"
-** or "DROP INDEX" query, an infinite loop might be the result.
-**
-** One way around this problem is to check the extended error code returned
-** by an sqlite3_step() call. ^(If there is a blocking connection, then the
-** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in
-** the special "DROP TABLE/INDEX" case, the extended error code is just
-** SQLITE_LOCKED.)^
-*/
-int sqlite3_unlock_notify(
- sqlite3 *pBlocked, /* Waiting connection */
- void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
- void *pNotifyArg /* Argument to pass to xNotify */
-);
-
-
-/*
-** CAPI3REF: String Comparison
-**
-** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
-** and extensions to compare the contents of two buffers containing UTF-8
-** strings in a case-independent fashion, using the same definition of "case
-** independence" that SQLite uses internally when comparing identifiers.
-*/
-int sqlite3_stricmp(const char *, const char *);
-int sqlite3_strnicmp(const char *, const char *, int);
-
-/*
-** CAPI3REF: String Globbing
-*
-** ^The [sqlite3_strglob(P,X)] interface returns zero if and only if
-** string X matches the [GLOB] pattern P.
-** ^The definition of [GLOB] pattern matching used in
-** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the
-** SQL dialect understood by SQLite. ^The [sqlite3_strglob(P,X)] function
-** is case sensitive.
-**
-** Note that this routine returns zero on a match and non-zero if the strings
-** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
-**
-** See also: [sqlite3_strlike()].
-*/
-int sqlite3_strglob(const char *zGlob, const char *zStr);
-
-/*
-** CAPI3REF: String LIKE Matching
-*
-** ^The [sqlite3_strlike(P,X,E)] interface returns zero if and only if
-** string X matches the [LIKE] pattern P with escape character E.
-** ^The definition of [LIKE] pattern matching used in
-** [sqlite3_strlike(P,X,E)] is the same as for the "X LIKE P ESCAPE E"
-** operator in the SQL dialect understood by SQLite. ^For "X LIKE P" without
-** the ESCAPE clause, set the E parameter of [sqlite3_strlike(P,X,E)] to 0.
-** ^As with the LIKE operator, the [sqlite3_strlike(P,X,E)] function is case
-** insensitive - equivalent upper and lower case ASCII characters match
-** one another.
-**
-** ^The [sqlite3_strlike(P,X,E)] function matches Unicode characters, though
-** only ASCII characters are case folded.
-**
-** Note that this routine returns zero on a match and non-zero if the strings
-** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
-**
-** See also: [sqlite3_strglob()].
-*/
-int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc);
-
-/*
-** CAPI3REF: Error Logging Interface
-**
-** ^The [sqlite3_log()] interface writes a message into the [error log]
-** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
-** ^If logging is enabled, the zFormat string and subsequent arguments are
-** used with [sqlite3_snprintf()] to generate the final output string.
-**
-** The sqlite3_log() interface is intended for use by extensions such as
-** virtual tables, collating functions, and SQL functions. While there is
-** nothing to prevent an application from calling sqlite3_log(), doing so
-** is considered bad form.
-**
-** The zFormat string must not be NULL.
-**
-** To avoid deadlocks and other threading problems, the sqlite3_log() routine
-** will not use dynamically allocated memory. The log message is stored in
-** a fixed-length buffer on the stack. If the log message is longer than
-** a few hundred characters, it will be truncated to the length of the
-** buffer.
-*/
-void sqlite3_log(int iErrCode, const char *zFormat, ...);
-
-/*
-** CAPI3REF: Write-Ahead Log Commit Hook
-** METHOD: sqlite3
-**
-** ^The [sqlite3_wal_hook()] function is used to register a callback that
-** is invoked each time data is committed to a database in wal mode.
-**
-** ^(The callback is invoked by SQLite after the commit has taken place and
-** the associated write-lock on the database released)^, so the implementation
-** may read, write or [checkpoint] the database as required.
-**
-** ^The first parameter passed to the callback function when it is invoked
-** is a copy of the third parameter passed to sqlite3_wal_hook() when
-** registering the callback. ^The second is a copy of the database handle.
-** ^The third parameter is the name of the database that was written to -
-** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
-** is the number of pages currently in the write-ahead log file,
-** including those that were just committed.
-**
-** The callback function should normally return [SQLITE_OK]. ^If an error
-** code is returned, that error will propagate back up through the
-** SQLite code base to cause the statement that provoked the callback
-** to report an error, though the commit will have still occurred. If the
-** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
-** that does not correspond to any valid SQLite error code, the results
-** are undefined.
-**
-** A single database handle may have at most a single write-ahead log callback
-** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
-** previously registered write-ahead log callback. ^Note that the
-** [sqlite3_wal_autocheckpoint()] interface and the
-** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
-** overwrite any prior [sqlite3_wal_hook()] settings.
-*/
-void *sqlite3_wal_hook(
- sqlite3*,
- int(*)(void *,sqlite3*,const char*,int),
- void*
-);
-
-/*
-** CAPI3REF: Configure an auto-checkpoint
-** METHOD: sqlite3
-**
-** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
-** [sqlite3_wal_hook()] that causes any database on [database connection] D
-** to automatically [checkpoint]
-** after committing a transaction if there are N or
-** more frames in the [write-ahead log] file. ^Passing zero or
-** a negative value as the nFrame parameter disables automatic
-** checkpoints entirely.
-**
-** ^The callback registered by this function replaces any existing callback
-** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback
-** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
-** configured by this function.
-**
-** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
-** from SQL.
-**
-** ^Checkpoints initiated by this mechanism are
-** [sqlite3_wal_checkpoint_v2|PASSIVE].
-**
-** ^Every new [database connection] defaults to having the auto-checkpoint
-** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
-** pages. The use of this interface
-** is only necessary if the default setting is found to be suboptimal
-** for a particular application.
-*/
-int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
-
-/*
-** CAPI3REF: Checkpoint a database
-** METHOD: sqlite3
-**
-** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
-** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
-**
-** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the
-** [write-ahead log] for database X on [database connection] D to be
-** transferred into the database file and for the write-ahead log to
-** be reset. See the [checkpointing] documentation for addition
-** information.
-**
-** This interface used to be the only way to cause a checkpoint to
-** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()]
-** interface was added. This interface is retained for backwards
-** compatibility and as a convenience for applications that need to manually
-** start a callback but which do not need the full power (and corresponding
-** complication) of [sqlite3_wal_checkpoint_v2()].
-*/
-int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
-
-/*
-** CAPI3REF: Checkpoint a database
-** METHOD: sqlite3
-**
-** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint
-** operation on database X of [database connection] D in mode M. Status
-** information is written back into integers pointed to by L and C.)^
-** ^(The M parameter must be a valid [checkpoint mode]:)^
-**
-** <dl>
-** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
-** ^Checkpoint as many frames as possible without waiting for any database
-** readers or writers to finish, then sync the database file if all frames
-** in the log were checkpointed. ^The [busy-handler callback]
-** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode.
-** ^On the other hand, passive mode might leave the checkpoint unfinished
-** if there are concurrent readers or writers.
-**
-** <dt>SQLITE_CHECKPOINT_FULL<dd>
-** ^This mode blocks (it invokes the
-** [sqlite3_busy_handler|busy-handler callback]) until there is no
-** database writer and all readers are reading from the most recent database
-** snapshot. ^It then checkpoints all frames in the log file and syncs the
-** database file. ^This mode blocks new database writers while it is pending,
-** but new database readers are allowed to continue unimpeded.
-**
-** <dt>SQLITE_CHECKPOINT_RESTART<dd>
-** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition
-** that after checkpointing the log file it blocks (calls the
-** [busy-handler callback])
-** until all readers are reading from the database file only. ^This ensures
-** that the next writer will restart the log file from the beginning.
-** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
-** database writer attempts while it is pending, but does not impede readers.
-**
-** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd>
-** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
-** addition that it also truncates the log file to zero bytes just prior
-** to a successful return.
-** </dl>
-**
-** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
-** the log file or to -1 if the checkpoint could not run because
-** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not
-** NULL,then *pnCkpt is set to the total number of checkpointed frames in the
-** log file (including any that were already checkpointed before the function
-** was called) or to -1 if the checkpoint could not run due to an error or
-** because the database is not in WAL mode. ^Note that upon successful
-** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been
-** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero.
-**
-** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If
-** any other process is running a checkpoint operation at the same time, the
-** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a
-** busy-handler configured, it will not be invoked in this case.
-**
-** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the
-** exclusive "writer" lock on the database file. ^If the writer lock cannot be
-** obtained immediately, and a busy-handler is configured, it is invoked and
-** the writer lock retried until either the busy-handler returns 0 or the lock
-** is successfully obtained. ^The busy-handler is also invoked while waiting for
-** database readers as described above. ^If the busy-handler returns 0 before
-** the writer lock is obtained or while waiting for database readers, the
-** checkpoint operation proceeds from that point in the same way as
-** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
-** without blocking any further. ^SQLITE_BUSY is returned in this case.
-**
-** ^If parameter zDb is NULL or points to a zero length string, then the
-** specified operation is attempted on all WAL databases [attached] to
-** [database connection] db. In this case the
-** values written to output parameters *pnLog and *pnCkpt are undefined. ^If
-** an SQLITE_BUSY error is encountered when processing one or more of the
-** attached WAL databases, the operation is still attempted on any remaining
-** attached databases and SQLITE_BUSY is returned at the end. ^If any other
-** error occurs while processing an attached database, processing is abandoned
-** and the error code is returned to the caller immediately. ^If no error
-** (SQLITE_BUSY or otherwise) is encountered while processing the attached
-** databases, SQLITE_OK is returned.
-**
-** ^If database zDb is the name of an attached database that is not in WAL
-** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If
-** zDb is not NULL (or a zero length string) and is not the name of any
-** attached database, SQLITE_ERROR is returned to the caller.
-**
-** ^Unless it returns SQLITE_MISUSE,
-** the sqlite3_wal_checkpoint_v2() interface
-** sets the error information that is queried by
-** [sqlite3_errcode()] and [sqlite3_errmsg()].
-**
-** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface
-** from SQL.
-*/
-int sqlite3_wal_checkpoint_v2(
- sqlite3 *db, /* Database handle */
- const char *zDb, /* Name of attached database (or NULL) */
- int eMode, /* SQLITE_CHECKPOINT_* value */
- int *pnLog, /* OUT: Size of WAL log in frames */
- int *pnCkpt /* OUT: Total number of frames checkpointed */
-);
-
-/*
-** CAPI3REF: Checkpoint Mode Values
-** KEYWORDS: {checkpoint mode}
-**
-** These constants define all valid values for the "checkpoint mode" passed
-** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
-** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
-** meaning of each of these checkpoint modes.
-*/
-#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */
-#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */
-#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */
-#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */
-
-/*
-** CAPI3REF: Virtual Table Interface Configuration
-**
-** This function may be called by either the [xConnect] or [xCreate] method
-** of a [virtual table] implementation to configure
-** various facets of the virtual table interface.
-**
-** If this interface is invoked outside the context of an xConnect or
-** xCreate virtual table method then the behavior is undefined.
-**
-** At present, there is only one option that may be configured using
-** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
-** may be added in the future.
-*/
-int sqlite3_vtab_config(sqlite3*, int op, ...);
-
-/*
-** CAPI3REF: Virtual Table Configuration Options
-**
-** These macros define the various options to the
-** [sqlite3_vtab_config()] interface that [virtual table] implementations
-** can use to customize and optimize their behavior.
-**
-** <dl>
-** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
-** <dd>Calls of the form
-** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
-** where X is an integer. If X is zero, then the [virtual table] whose
-** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
-** support constraints. In this configuration (which is the default) if
-** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
-** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
-** specified as part of the users SQL statement, regardless of the actual
-** ON CONFLICT mode specified.
-**
-** If X is non-zero, then the virtual table implementation guarantees
-** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
-** any modifications to internal or persistent data structures have been made.
-** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
-** is able to roll back a statement or database transaction, and abandon
-** or continue processing the current SQL statement as appropriate.
-** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
-** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
-** had been ABORT.
-**
-** Virtual table implementations that are required to handle OR REPLACE
-** must do so within the [xUpdate] method. If a call to the
-** [sqlite3_vtab_on_conflict()] function indicates that the current ON
-** CONFLICT policy is REPLACE, the virtual table implementation should
-** silently replace the appropriate rows within the xUpdate callback and
-** return SQLITE_OK. Or, if this is not possible, it may return
-** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
-** constraint handling.
-** </dl>
-*/
-#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
-
-/*
-** CAPI3REF: Determine The Virtual Table Conflict Policy
-**
-** This function may only be called from within a call to the [xUpdate] method
-** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
-** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
-** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
-** of the SQL statement that triggered the call to the [xUpdate] method of the
-** [virtual table].
-*/
-int sqlite3_vtab_on_conflict(sqlite3 *);
-
-/*
-** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
-**
-** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
-** method of a [virtual table], then it returns true if and only if the
-** column is being fetched as part of an UPDATE operation during which the
-** column value will not change. Applications might use this to substitute
-** a return value that is less expensive to compute and that the corresponding
-** [xUpdate] method understands as a "no-change" value.
-**
-** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
-** the column is not changed by the UPDATE statement, then the xColumn
-** method can optionally return without setting a result, without calling
-** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
-** In that case, [sqlite3_value_nochange(X)] will return true for the
-** same column in the [xUpdate] method.
-*/
-int sqlite3_vtab_nochange(sqlite3_context*);
-
-/*
-** CAPI3REF: Determine The Collation For a Virtual Table Constraint
-**
-** This function may only be called from within a call to the [xBestIndex]
-** method of a [virtual table].
-**
-** The first argument must be the sqlite3_index_info object that is the
-** first parameter to the xBestIndex() method. The second argument must be
-** an index into the aConstraint[] array belonging to the sqlite3_index_info
-** structure passed to xBestIndex. This function returns a pointer to a buffer
-** containing the name of the collation sequence for the corresponding
-** constraint.
-*/
-SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
-
-/*
-** CAPI3REF: Conflict resolution modes
-** KEYWORDS: {conflict resolution mode}
-**
-** These constants are returned by [sqlite3_vtab_on_conflict()] to
-** inform a [virtual table] implementation what the [ON CONFLICT] mode
-** is for the SQL statement being evaluated.
-**
-** Note that the [SQLITE_IGNORE] constant is also used as a potential
-** return value from the [sqlite3_set_authorizer()] callback and that
-** [SQLITE_ABORT] is also a [result code].
-*/
-#define SQLITE_ROLLBACK 1
-/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
-#define SQLITE_FAIL 3
-/* #define SQLITE_ABORT 4 // Also an error code */
-#define SQLITE_REPLACE 5
-
-/*
-** CAPI3REF: Prepared Statement Scan Status Opcodes
-** KEYWORDS: {scanstatus options}
-**
-** The following constants can be used for the T parameter to the
-** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a
-** different metric for sqlite3_stmt_scanstatus() to return.
-**
-** When the value returned to V is a string, space to hold that string is
-** managed by the prepared statement S and will be automatically freed when
-** S is finalized.
-**
-** <dl>
-** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be
-** set to the total number of times that the X-th loop has run.</dd>
-**
-** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt>
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set
-** to the total number of rows examined by all iterations of the X-th loop.</dd>
-**
-** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
-** <dd>^The "double" variable pointed to by the T parameter will be set to the
-** query planner's estimate for the average number of rows output from each
-** iteration of the X-th loop. If the query planner's estimates was accurate,
-** then this value will approximate the quotient NVISIT/NLOOP and the
-** product of this value for all prior loops with the same SELECTID will
-** be the NLOOP value for the current loop.
-**
-** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
-** to a zero-terminated UTF-8 string containing the name of the index or table
-** used for the X-th loop.
-**
-** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
-** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
-** description for the X-th loop.
-**
-** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt>
-** <dd>^The "int" variable pointed to by the T parameter will be set to the
-** "select-id" for the X-th loop. The select-id identifies which query or
-** subquery the loop is part of. The main query has a select-id of zero.
-** The select-id is the same value as is output in the first column
-** of an [EXPLAIN QUERY PLAN] query.
-** </dl>
-*/
-#define SQLITE_SCANSTAT_NLOOP 0
-#define SQLITE_SCANSTAT_NVISIT 1
-#define SQLITE_SCANSTAT_EST 2
-#define SQLITE_SCANSTAT_NAME 3
-#define SQLITE_SCANSTAT_EXPLAIN 4
-#define SQLITE_SCANSTAT_SELECTID 5
-
-/*
-** CAPI3REF: Prepared Statement Scan Status
-** METHOD: sqlite3_stmt
-**
-** This interface returns information about the predicted and measured
-** performance for pStmt. Advanced applications can use this
-** interface to compare the predicted and the measured performance and
-** issue warnings and/or rerun [ANALYZE] if discrepancies are found.
-**
-** Since this interface is expected to be rarely used, it is only
-** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS]
-** compile-time option.
-**
-** The "iScanStatusOp" parameter determines which status information to return.
-** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior
-** of this interface is undefined.
-** ^The requested measurement is written into a variable pointed to by
-** the "pOut" parameter.
-** Parameter "idx" identifies the specific loop to retrieve statistics for.
-** Loops are numbered starting from zero. ^If idx is out of range - less than
-** zero or greater than or equal to the total number of loops used to implement
-** the statement - a non-zero value is returned and the variable that pOut
-** points to is unchanged.
-**
-** ^Statistics might not be available for all loops in all statements. ^In cases
-** where there exist loops with no available statistics, this function behaves
-** as if the loop did not exist - it returns non-zero and leave the variable
-** that pOut points to unchanged.
-**
-** See also: [sqlite3_stmt_scanstatus_reset()]
-*/
-int sqlite3_stmt_scanstatus(
- sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
- int idx, /* Index of loop to report on */
- int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
- void *pOut /* Result written here */
-);
-
-/*
-** CAPI3REF: Zero Scan-Status Counters
-** METHOD: sqlite3_stmt
-**
-** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
-**
-** This API is only available if the library is built with pre-processor
-** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
-*/
-void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
-
-/*
-** CAPI3REF: Flush caches to disk mid-transaction
-**
-** ^If a write-transaction is open on [database connection] D when the
-** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
-** pages in the pager-cache that are not currently in use are written out
-** to disk. A dirty page may be in use if a database cursor created by an
-** active SQL statement is reading from it, or if it is page 1 of a database
-** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)]
-** interface flushes caches for all schemas - "main", "temp", and
-** any [attached] databases.
-**
-** ^If this function needs to obtain extra database locks before dirty pages
-** can be flushed to disk, it does so. ^If those locks cannot be obtained
-** immediately and there is a busy-handler callback configured, it is invoked
-** in the usual manner. ^If the required lock still cannot be obtained, then
-** the database is skipped and an attempt made to flush any dirty pages
-** belonging to the next (if any) database. ^If any databases are skipped
-** because locks cannot be obtained, but no other error occurs, this
-** function returns SQLITE_BUSY.
-**
-** ^If any other error occurs while flushing dirty pages to disk (for
-** example an IO error or out-of-memory condition), then processing is
-** abandoned and an SQLite [error code] is returned to the caller immediately.
-**
-** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK.
-**
-** ^This function does not set the database handle error code or message
-** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions.
-*/
-int sqlite3_db_cacheflush(sqlite3*);
-
-/*
-** CAPI3REF: The pre-update hook.
-**
-** ^These interfaces are only available if SQLite is compiled using the
-** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
-**
-** ^The [sqlite3_preupdate_hook()] interface registers a callback function
-** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
-** on a database table.
-** ^At most one preupdate hook may be registered at a time on a single
-** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
-** the previous setting.
-** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()]
-** with a NULL pointer as the second parameter.
-** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
-** the first parameter to callbacks.
-**
-** ^The preupdate hook only fires for changes to real database tables; the
-** preupdate hook is not invoked for changes to [virtual tables] or to
-** system tables like sqlite_master or sqlite_stat1.
-**
-** ^The second parameter to the preupdate callback is a pointer to
-** the [database connection] that registered the preupdate hook.
-** ^The third parameter to the preupdate callback is one of the constants
-** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the
-** kind of update operation that is about to occur.
-** ^(The fourth parameter to the preupdate callback is the name of the
-** database within the database connection that is being modified. This
-** will be "main" for the main database or "temp" for TEMP tables or
-** the name given after the AS keyword in the [ATTACH] statement for attached
-** databases.)^
-** ^The fifth parameter to the preupdate callback is the name of the
-** table that is being modified.
-**
-** For an UPDATE or DELETE operation on a [rowid table], the sixth
-** parameter passed to the preupdate callback is the initial [rowid] of the
-** row being modified or deleted. For an INSERT operation on a rowid table,
-** or any operation on a WITHOUT ROWID table, the value of the sixth
-** parameter is undefined. For an INSERT or UPDATE on a rowid table the
-** seventh parameter is the final rowid value of the row being inserted
-** or updated. The value of the seventh parameter passed to the callback
-** function is not defined for operations on WITHOUT ROWID tables, or for
-** INSERT operations on rowid tables.
-**
-** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
-** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
-** provide additional information about a preupdate event. These routines
-** may only be called from within a preupdate callback. Invoking any of
-** these routines from outside of a preupdate callback or with a
-** [database connection] pointer that is different from the one supplied
-** to the preupdate callback results in undefined and probably undesirable
-** behavior.
-**
-** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns
-** in the row that is being inserted, updated, or deleted.
-**
-** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to
-** a [protected sqlite3_value] that contains the value of the Nth column of
-** the table row before it is updated. The N parameter must be between 0
-** and one less than the number of columns or the behavior will be
-** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE
-** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the
-** behavior is undefined. The [sqlite3_value] that P points to
-** will be destroyed when the preupdate callback returns.
-**
-** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to
-** a [protected sqlite3_value] that contains the value of the Nth column of
-** the table row after it is updated. The N parameter must be between 0
-** and one less than the number of columns or the behavior will be
-** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE
-** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the
-** behavior is undefined. The [sqlite3_value] that P points to
-** will be destroyed when the preupdate callback returns.
-**
-** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
-** callback was invoked as a result of a direct insert, update, or delete
-** operation; or 1 for inserts, updates, or deletes invoked by top-level
-** triggers; or 2 for changes resulting from triggers called by top-level
-** triggers; and so forth.
-**
-** See also: [sqlite3_update_hook()]
-*/
-#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
-void *sqlite3_preupdate_hook(
- sqlite3 *db,
- void(*xPreUpdate)(
- void *pCtx, /* Copy of third arg to preupdate_hook() */
- sqlite3 *db, /* Database handle */
- int op, /* SQLITE_UPDATE, DELETE or INSERT */
- char const *zDb, /* Database name */
- char const *zName, /* Table name */
- sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
- sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
- ),
- void*
-);
-int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
-int sqlite3_preupdate_count(sqlite3 *);
-int sqlite3_preupdate_depth(sqlite3 *);
-int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
-#endif
-
-/*
-** CAPI3REF: Low-level system error code
-**
-** ^Attempt to return the underlying operating system error code or error
-** number that caused the most recent I/O error or failure to open a file.
-** The return value is OS-dependent. For example, on unix systems, after
-** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be
-** called to get back the underlying "errno" that caused the problem, such
-** as ENOSPC, EAUTH, EISDIR, and so forth.
-*/
-int sqlite3_system_errno(sqlite3*);
-
-/*
-** CAPI3REF: Database Snapshot
-** KEYWORDS: {snapshot} {sqlite3_snapshot}
-** EXPERIMENTAL
-**
-** An instance of the snapshot object records the state of a [WAL mode]
-** database for some specific point in history.
-**
-** In [WAL mode], multiple [database connections] that are open on the
-** same database file can each be reading a different historical version
-** of the database file. When a [database connection] begins a read
-** transaction, that connection sees an unchanging copy of the database
-** as it existed for the point in time when the transaction first started.
-** Subsequent changes to the database from other connections are not seen
-** by the reader until a new read transaction is started.
-**
-** The sqlite3_snapshot object records state information about an historical
-** version of the database file so that it is possible to later open a new read
-** transaction that sees that historical version of the database rather than
-** the most recent version.
-**
-** The constructor for this object is [sqlite3_snapshot_get()]. The
-** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer
-** to an historical snapshot (if possible). The destructor for
-** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
-*/
-typedef struct sqlite3_snapshot {
- unsigned char hidden[48];
-} sqlite3_snapshot;
-
-/*
-** CAPI3REF: Record A Database Snapshot
-** EXPERIMENTAL
-**
-** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a
-** new [sqlite3_snapshot] object that records the current state of
-** schema S in database connection D. ^On success, the
-** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
-** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
-** If there is not already a read-transaction open on schema S when
-** this function is called, one is opened automatically.
-**
-** The following must be true for this function to succeed. If any of
-** the following statements are false when sqlite3_snapshot_get() is
-** called, SQLITE_ERROR is returned. The final value of *P is undefined
-** in this case.
-**
-** <ul>
-** <li> The database handle must be in [autocommit mode].
-**
-** <li> Schema S of [database connection] D must be a [WAL mode] database.
-**
-** <li> There must not be a write transaction open on schema S of database
-** connection D.
-**
-** <li> One or more transactions must have been written to the current wal
-** file since it was created on disk (by any connection). This means
-** that a snapshot cannot be taken on a wal mode database with no wal
-** file immediately after it is first opened. At least one transaction
-** must be written to it first.
-** </ul>
-**
-** This function may also return SQLITE_NOMEM. If it is called with the
-** database handle in autocommit mode but fails for some other reason,
-** whether or not a read transaction is opened on schema S is undefined.
-**
-** The [sqlite3_snapshot] object returned from a successful call to
-** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
-** to avoid a memory leak.
-**
-** The [sqlite3_snapshot_get()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
-*/
-SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
- sqlite3 *db,
- const char *zSchema,
- sqlite3_snapshot **ppSnapshot
-);
-
-/*
-** CAPI3REF: Start a read transaction on an historical snapshot
-** EXPERIMENTAL
-**
-** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a
-** read transaction for schema S of
-** [database connection] D such that the read transaction
-** refers to historical [snapshot] P, rather than the most
-** recent change to the database.
-** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success
-** or an appropriate [error code] if it fails.
-**
-** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be
-** the first operation following the [BEGIN] that takes the schema S
-** out of [autocommit mode].
-** ^In other words, schema S must not currently be in
-** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the
-** database connection D must be out of [autocommit mode].
-** ^A [snapshot] will fail to open if it has been overwritten by a
-** [checkpoint].
-** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the
-** database connection D does not know that the database file for
-** schema S is in [WAL mode]. A database connection might not know
-** that the database file is in [WAL mode] if there has been no prior
-** I/O on that database connection, or if the database entered [WAL mode]
-** after the most recent I/O on the database connection.)^
-** (Hint: Run "[PRAGMA application_id]" against a newly opened
-** database connection in order to make it ready to use snapshots.)
-**
-** The [sqlite3_snapshot_open()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
-*/
-SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
- sqlite3 *db,
- const char *zSchema,
- sqlite3_snapshot *pSnapshot
-);
-
-/*
-** CAPI3REF: Destroy a snapshot
-** EXPERIMENTAL
-**
-** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
-** The application must eventually free every [sqlite3_snapshot] object
-** using this routine to avoid a memory leak.
-**
-** The [sqlite3_snapshot_free()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
-*/
-SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
-
-/*
-** CAPI3REF: Compare the ages of two snapshot handles.
-** EXPERIMENTAL
-**
-** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
-** of two valid snapshot handles.
-**
-** If the two snapshot handles are not associated with the same database
-** file, the result of the comparison is undefined.
-**
-** Additionally, the result of the comparison is only valid if both of the
-** snapshot handles were obtained by calling sqlite3_snapshot_get() since the
-** last time the wal file was deleted. The wal file is deleted when the
-** database is changed back to rollback mode or when the number of database
-** clients drops to zero. If either snapshot handle was obtained before the
-** wal file was last deleted, the value returned by this function
-** is undefined.
-**
-** Otherwise, this API returns a negative value if P1 refers to an older
-** snapshot than P2, zero if the two handles refer to the same database
-** snapshot, and a positive value if P1 is a newer snapshot than P2.
-*/
-SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
- sqlite3_snapshot *p1,
- sqlite3_snapshot *p2
-);
-
-/*
-** CAPI3REF: Recover snapshots from a wal file
-** EXPERIMENTAL
-**
-** If all connections disconnect from a database file but do not perform
-** a checkpoint, the existing wal file is opened along with the database
-** file the next time the database is opened. At this point it is only
-** possible to successfully call sqlite3_snapshot_open() to open the most
-** recent snapshot of the database (the one at the head of the wal file),
-** even though the wal file may contain other valid snapshots for which
-** clients have sqlite3_snapshot handles.
-**
-** This function attempts to scan the wal file associated with database zDb
-** of database handle db and make all valid snapshots available to
-** sqlite3_snapshot_open(). It is an error if there is already a read
-** transaction open on the database, or if the database is not a wal mode
-** database.
-**
-** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
-*/
-SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
-
-/*
-** CAPI3REF: Serialize a database
-**
-** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
-** that is a serialization of the S database on [database connection] D.
-** If P is not a NULL pointer, then the size of the database in bytes
-** is written into *P.
-**
-** For an ordinary on-disk database file, the serialization is just a
-** copy of the disk file. For an in-memory database or a "TEMP" database,
-** the serialization is the same sequence of bytes which would be written
-** to disk if that database where backed up to disk.
-**
-** The usual case is that sqlite3_serialize() copies the serialization of
-** the database into memory obtained from [sqlite3_malloc64()] and returns
-** a pointer to that memory. The caller is responsible for freeing the
-** returned value to avoid a memory leak. However, if the F argument
-** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations
-** are made, and the sqlite3_serialize() function will return a pointer
-** to the contiguous memory representation of the database that SQLite
-** is currently using for that database, or NULL if the no such contiguous
-** memory representation of the database exists. A contiguous memory
-** representation of the database will usually only exist if there has
-** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
-** values of D and S.
-** The size of the database is written into *P even if the
-** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
-** of the database exists.
-**
-** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
-** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
-** allocation error occurs.
-**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
-*/
-unsigned char *sqlite3_serialize(
- sqlite3 *db, /* The database connection */
- const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */
- sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */
- unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */
-);
-
-/*
-** CAPI3REF: Flags for sqlite3_serialize
-**
-** Zero or more of the following constants can be OR-ed together for
-** the F argument to [sqlite3_serialize(D,S,P,F)].
-**
-** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return
-** a pointer to contiguous in-memory database that it is currently using,
-** without making a copy of the database. If SQLite is not currently using
-** a contiguous in-memory database, then this option causes
-** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be
-** using a contiguous in-memory database if it has been initialized by a
-** prior call to [sqlite3_deserialize()].
-*/
-#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */
-
-/*
-** CAPI3REF: Deserialize a database
-**
-** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
-** [database connection] D to disconnect from database S and then
-** reopen S as an in-memory database based on the serialization contained
-** in P. The serialized database P is N bytes in size. M is the size of
-** the buffer P, which might be larger than N. If M is larger than N, and
-** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
-** permitted to add content to the in-memory database as long as the total
-** size does not exceed M bytes.
-**
-** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
-** invoke sqlite3_free() on the serialization buffer when the database
-** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
-** SQLite will try to increase the buffer size using sqlite3_realloc64()
-** if writes on the database cause it to grow larger than M bytes.
-**
-** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
-** database is currently in a read transaction or is involved in a backup
-** operation.
-**
-** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
-** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
-** [sqlite3_free()] is invoked on argument P prior to returning.
-**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
-*/
-int sqlite3_deserialize(
- sqlite3 *db, /* The database connection */
- const char *zSchema, /* Which DB to reopen with the deserialization */
- unsigned char *pData, /* The serialized database content */
- sqlite3_int64 szDb, /* Number bytes in the deserialization */
- sqlite3_int64 szBuf, /* Total size of buffer pData[] */
- unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
-);
-
-/*
-** CAPI3REF: Flags for sqlite3_deserialize()
-**
-** The following are allowed values for 6th argument (the F argument) to
-** the [sqlite3_deserialize(D,S,P,N,M,F)] interface.
-**
-** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization
-** in the P argument is held in memory obtained from [sqlite3_malloc64()]
-** and that SQLite should take ownership of this memory and automatically
-** free it when it has finished using it. Without this flag, the caller
-** is resposible for freeing any dynamically allocated memory.
-**
-** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
-** grow the size of the database using calls to [sqlite3_realloc64()]. This
-** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used.
-** Without this flag, the deserialized database cannot increase in size beyond
-** the number of bytes specified by the M parameter.
-**
-** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database
-** should be treated as read-only.
-*/
-#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */
-#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */
-#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
-
-/*
-** Undo the hack that converts floating point types to integer for
-** builds on processors without floating point support.
-*/
-#ifdef SQLITE_OMIT_FLOATING_POINT
-# undef double
-#endif
-
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-#endif /* SQLITE3_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite3.rc b/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite3.rc
deleted file mode 100644
index 5a856490d64..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite3.rc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-** 2012 September 2
-**
-** 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 contains code and resources that are specific to Windows.
-*/
-
-#if !defined(_WIN32_WCE)
-#include "winresrc.h"
-#else
-#include "windows.h"
-#endif /* !defined(_WIN32_WCE) */
-
-#if !defined(VS_FF_NONE)
-# define VS_FF_NONE 0x00000000L
-#endif /* !defined(VS_FF_NONE) */
-
-#include "sqlite3.h"
-#include "sqlite3rc.h"
-
-/*
- * English (U.S.) resources
- */
-
-#if defined(_WIN32)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif /* defined(_WIN32) */
-
-/*
- * Icon
- */
-
-#if !defined(RC_VERONLY)
-#define IDI_SQLITE 101
-
-IDI_SQLITE ICON "..\\art\\sqlite370.ico"
-#endif /* !defined(RC_VERONLY) */
-
-/*
- * Version
- */
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION SQLITE_RESOURCE_VERSION
- PRODUCTVERSION SQLITE_RESOURCE_VERSION
- FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
-#if defined(_DEBUG)
- FILEFLAGS VS_FF_DEBUG
-#else
- FILEFLAGS VS_FF_NONE
-#endif /* defined(_DEBUG) */
- FILEOS VOS__WINDOWS32
- FILETYPE VFT_DLL
- FILESUBTYPE VFT2_UNKNOWN
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "CompanyName", "SQLite Development Team"
- VALUE "FileDescription", "SQLite is a software library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine."
- VALUE "FileVersion", SQLITE_VERSION
- VALUE "InternalName", "sqlite3"
- VALUE "LegalCopyright", "http://www.sqlite.org/copyright.html"
- VALUE "ProductName", "SQLite"
- VALUE "ProductVersion", SQLITE_VERSION
- VALUE "SourceId", SQLITE_SOURCE_ID
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 0x4b0
- END
-END
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite3ext.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite3ext.h
deleted file mode 100644
index e0cd2f4d8dc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqlite3ext.h
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
-** 2006 June 7
-**
-** 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 header file defines the SQLite interface for use by
-** shared libraries that want to be imported as extensions into
-** an SQLite instance. Shared libraries that intend to be loaded
-** as extensions by SQLite should #include this file instead of
-** sqlite3.h.
-*/
-#ifndef SQLITE3EXT_H
-#define SQLITE3EXT_H
-#include "sqlite3.h"
-
-/*
-** The following structure holds pointers to all of the SQLite API
-** routines.
-**
-** WARNING: In order to maintain backwards compatibility, add new
-** interfaces to the end of this structure only. If you insert new
-** interfaces in the middle of this structure, then older different
-** versions of SQLite will not be able to load each other's shared
-** libraries!
-*/
-struct sqlite3_api_routines {
- void * (*aggregate_context)(sqlite3_context*,int nBytes);
- int (*aggregate_count)(sqlite3_context*);
- int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
- int (*bind_double)(sqlite3_stmt*,int,double);
- int (*bind_int)(sqlite3_stmt*,int,int);
- int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
- int (*bind_null)(sqlite3_stmt*,int);
- int (*bind_parameter_count)(sqlite3_stmt*);
- int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
- const char * (*bind_parameter_name)(sqlite3_stmt*,int);
- int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
- int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
- int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
- int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
- int (*busy_timeout)(sqlite3*,int ms);
- int (*changes)(sqlite3*);
- int (*close)(sqlite3*);
- int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
- int eTextRep,const char*));
- int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
- int eTextRep,const void*));
- const void * (*column_blob)(sqlite3_stmt*,int iCol);
- int (*column_bytes)(sqlite3_stmt*,int iCol);
- int (*column_bytes16)(sqlite3_stmt*,int iCol);
- int (*column_count)(sqlite3_stmt*pStmt);
- const char * (*column_database_name)(sqlite3_stmt*,int);
- const void * (*column_database_name16)(sqlite3_stmt*,int);
- const char * (*column_decltype)(sqlite3_stmt*,int i);
- const void * (*column_decltype16)(sqlite3_stmt*,int);
- double (*column_double)(sqlite3_stmt*,int iCol);
- int (*column_int)(sqlite3_stmt*,int iCol);
- sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
- const char * (*column_name)(sqlite3_stmt*,int);
- const void * (*column_name16)(sqlite3_stmt*,int);
- const char * (*column_origin_name)(sqlite3_stmt*,int);
- const void * (*column_origin_name16)(sqlite3_stmt*,int);
- const char * (*column_table_name)(sqlite3_stmt*,int);
- const void * (*column_table_name16)(sqlite3_stmt*,int);
- const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
- const void * (*column_text16)(sqlite3_stmt*,int iCol);
- int (*column_type)(sqlite3_stmt*,int iCol);
- sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
- void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
- int (*complete)(const char*sql);
- int (*complete16)(const void*sql);
- int (*create_collation)(sqlite3*,const char*,int,void*,
- int(*)(void*,int,const void*,int,const void*));
- int (*create_collation16)(sqlite3*,const void*,int,void*,
- int(*)(void*,int,const void*,int,const void*));
- int (*create_function)(sqlite3*,const char*,int,int,void*,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*));
- int (*create_function16)(sqlite3*,const void*,int,int,void*,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*));
- int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
- int (*data_count)(sqlite3_stmt*pStmt);
- sqlite3 * (*db_handle)(sqlite3_stmt*);
- int (*declare_vtab)(sqlite3*,const char*);
- int (*enable_shared_cache)(int);
- int (*errcode)(sqlite3*db);
- const char * (*errmsg)(sqlite3*);
- const void * (*errmsg16)(sqlite3*);
- int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
- int (*expired)(sqlite3_stmt*);
- int (*finalize)(sqlite3_stmt*pStmt);
- void (*free)(void*);
- void (*free_table)(char**result);
- int (*get_autocommit)(sqlite3*);
- void * (*get_auxdata)(sqlite3_context*,int);
- int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
- int (*global_recover)(void);
- void (*interruptx)(sqlite3*);
- sqlite_int64 (*last_insert_rowid)(sqlite3*);
- const char * (*libversion)(void);
- int (*libversion_number)(void);
- void *(*malloc)(int);
- char * (*mprintf)(const char*,...);
- int (*open)(const char*,sqlite3**);
- int (*open16)(const void*,sqlite3**);
- int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
- int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
- void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
- void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
- void *(*realloc)(void*,int);
- int (*reset)(sqlite3_stmt*pStmt);
- void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
- void (*result_double)(sqlite3_context*,double);
- void (*result_error)(sqlite3_context*,const char*,int);
- void (*result_error16)(sqlite3_context*,const void*,int);
- void (*result_int)(sqlite3_context*,int);
- void (*result_int64)(sqlite3_context*,sqlite_int64);
- void (*result_null)(sqlite3_context*);
- void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
- void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
- void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
- void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
- void (*result_value)(sqlite3_context*,sqlite3_value*);
- void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
- int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
- const char*,const char*),void*);
- void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
- char * (*xsnprintf)(int,char*,const char*,...);
- int (*step)(sqlite3_stmt*);
- int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
- char const**,char const**,int*,int*,int*);
- void (*thread_cleanup)(void);
- int (*total_changes)(sqlite3*);
- void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
- int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
- void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
- sqlite_int64),void*);
- void * (*user_data)(sqlite3_context*);
- const void * (*value_blob)(sqlite3_value*);
- int (*value_bytes)(sqlite3_value*);
- int (*value_bytes16)(sqlite3_value*);
- double (*value_double)(sqlite3_value*);
- int (*value_int)(sqlite3_value*);
- sqlite_int64 (*value_int64)(sqlite3_value*);
- int (*value_numeric_type)(sqlite3_value*);
- const unsigned char * (*value_text)(sqlite3_value*);
- const void * (*value_text16)(sqlite3_value*);
- const void * (*value_text16be)(sqlite3_value*);
- const void * (*value_text16le)(sqlite3_value*);
- int (*value_type)(sqlite3_value*);
- char *(*vmprintf)(const char*,va_list);
- /* Added ??? */
- int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
- /* Added by 3.3.13 */
- int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
- int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
- int (*clear_bindings)(sqlite3_stmt*);
- /* Added by 3.4.1 */
- int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
- void (*xDestroy)(void *));
- /* Added by 3.5.0 */
- int (*bind_zeroblob)(sqlite3_stmt*,int,int);
- int (*blob_bytes)(sqlite3_blob*);
- int (*blob_close)(sqlite3_blob*);
- int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
- int,sqlite3_blob**);
- int (*blob_read)(sqlite3_blob*,void*,int,int);
- int (*blob_write)(sqlite3_blob*,const void*,int,int);
- int (*create_collation_v2)(sqlite3*,const char*,int,void*,
- int(*)(void*,int,const void*,int,const void*),
- void(*)(void*));
- int (*file_control)(sqlite3*,const char*,int,void*);
- sqlite3_int64 (*memory_highwater)(int);
- sqlite3_int64 (*memory_used)(void);
- sqlite3_mutex *(*mutex_alloc)(int);
- void (*mutex_enter)(sqlite3_mutex*);
- void (*mutex_free)(sqlite3_mutex*);
- void (*mutex_leave)(sqlite3_mutex*);
- int (*mutex_try)(sqlite3_mutex*);
- int (*open_v2)(const char*,sqlite3**,int,const char*);
- int (*release_memory)(int);
- void (*result_error_nomem)(sqlite3_context*);
- void (*result_error_toobig)(sqlite3_context*);
- int (*sleep)(int);
- void (*soft_heap_limit)(int);
- sqlite3_vfs *(*vfs_find)(const char*);
- int (*vfs_register)(sqlite3_vfs*,int);
- int (*vfs_unregister)(sqlite3_vfs*);
- int (*xthreadsafe)(void);
- void (*result_zeroblob)(sqlite3_context*,int);
- void (*result_error_code)(sqlite3_context*,int);
- int (*test_control)(int, ...);
- void (*randomness)(int,void*);
- sqlite3 *(*context_db_handle)(sqlite3_context*);
- int (*extended_result_codes)(sqlite3*,int);
- int (*limit)(sqlite3*,int,int);
- sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
- const char *(*sql)(sqlite3_stmt*);
- int (*status)(int,int*,int*,int);
- int (*backup_finish)(sqlite3_backup*);
- sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
- int (*backup_pagecount)(sqlite3_backup*);
- int (*backup_remaining)(sqlite3_backup*);
- int (*backup_step)(sqlite3_backup*,int);
- const char *(*compileoption_get)(int);
- int (*compileoption_used)(const char*);
- int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*),
- void(*xDestroy)(void*));
- int (*db_config)(sqlite3*,int,...);
- sqlite3_mutex *(*db_mutex)(sqlite3*);
- int (*db_status)(sqlite3*,int,int*,int*,int);
- int (*extended_errcode)(sqlite3*);
- void (*log)(int,const char*,...);
- sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
- const char *(*sourceid)(void);
- int (*stmt_status)(sqlite3_stmt*,int,int);
- int (*strnicmp)(const char*,const char*,int);
- int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
- int (*wal_autocheckpoint)(sqlite3*,int);
- int (*wal_checkpoint)(sqlite3*,const char*);
- void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
- int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
- int (*vtab_config)(sqlite3*,int op,...);
- int (*vtab_on_conflict)(sqlite3*);
- /* Version 3.7.16 and later */
- int (*close_v2)(sqlite3*);
- const char *(*db_filename)(sqlite3*,const char*);
- int (*db_readonly)(sqlite3*,const char*);
- int (*db_release_memory)(sqlite3*);
- const char *(*errstr)(int);
- int (*stmt_busy)(sqlite3_stmt*);
- int (*stmt_readonly)(sqlite3_stmt*);
- int (*stricmp)(const char*,const char*);
- int (*uri_boolean)(const char*,const char*,int);
- sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
- const char *(*uri_parameter)(const char*,const char*);
- char *(*xvsnprintf)(int,char*,const char*,va_list);
- int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
- /* Version 3.8.7 and later */
- int (*auto_extension)(void(*)(void));
- int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
- void(*)(void*));
- int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
- void(*)(void*),unsigned char);
- int (*cancel_auto_extension)(void(*)(void));
- int (*load_extension)(sqlite3*,const char*,const char*,char**);
- void *(*malloc64)(sqlite3_uint64);
- sqlite3_uint64 (*msize)(void*);
- void *(*realloc64)(void*,sqlite3_uint64);
- void (*reset_auto_extension)(void);
- void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
- void(*)(void*));
- void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
- void(*)(void*), unsigned char);
- int (*strglob)(const char*,const char*);
- /* Version 3.8.11 and later */
- sqlite3_value *(*value_dup)(const sqlite3_value*);
- void (*value_free)(sqlite3_value*);
- int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
- int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
- /* Version 3.9.0 and later */
- unsigned int (*value_subtype)(sqlite3_value*);
- void (*result_subtype)(sqlite3_context*,unsigned int);
- /* Version 3.10.0 and later */
- int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
- int (*strlike)(const char*,const char*,unsigned int);
- int (*db_cacheflush)(sqlite3*);
- /* Version 3.12.0 and later */
- int (*system_errno)(sqlite3*);
- /* Version 3.14.0 and later */
- int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
- char *(*expanded_sql)(sqlite3_stmt*);
- /* Version 3.18.0 and later */
- void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
- /* Version 3.20.0 and later */
- int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
- sqlite3_stmt**,const char**);
- int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
- sqlite3_stmt**,const void**);
- int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
- void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
- void *(*value_pointer)(sqlite3_value*,const char*);
- int (*vtab_nochange)(sqlite3_context*);
- int (*value_nochange)(sqlite3_value*);
- const char *(*vtab_collation)(sqlite3_index_info*,int);
- /* Version 3.24.0 and later */
- int (*keyword_count)(void);
- int (*keyword_name)(int,const char**,int*);
- int (*keyword_check)(const char*,int);
- sqlite3_str *(*str_new)(sqlite3*);
- char *(*str_finish)(sqlite3_str*);
- void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
- void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
- void (*str_append)(sqlite3_str*, const char *zIn, int N);
- void (*str_appendall)(sqlite3_str*, const char *zIn);
- void (*str_appendchar)(sqlite3_str*, int N, char C);
- void (*str_reset)(sqlite3_str*);
- int (*str_errcode)(sqlite3_str*);
- int (*str_length)(sqlite3_str*);
- char *(*str_value)(sqlite3_str*);
-};
-
-/*
-** This is the function signature used for all extension entry points. It
-** is also defined in the file "loadext.c".
-*/
-typedef int (*sqlite3_loadext_entry)(
- sqlite3 *db, /* Handle to the database. */
- char **pzErrMsg, /* Used to set error string on failure. */
- const sqlite3_api_routines *pThunk /* Extension API function pointers. */
-);
-
-/*
-** The following macros redefine the API routines so that they are
-** redirected through the global sqlite3_api structure.
-**
-** This header file is also used by the loadext.c source file
-** (part of the main SQLite library - not an extension) so that
-** it can get access to the sqlite3_api_routines structure
-** definition. But the main library does not want to redefine
-** the API. So the redefinition macros are only valid if the
-** SQLITE_CORE macros is undefined.
-*/
-#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
-#define sqlite3_aggregate_context sqlite3_api->aggregate_context
-#ifndef SQLITE_OMIT_DEPRECATED
-#define sqlite3_aggregate_count sqlite3_api->aggregate_count
-#endif
-#define sqlite3_bind_blob sqlite3_api->bind_blob
-#define sqlite3_bind_double sqlite3_api->bind_double
-#define sqlite3_bind_int sqlite3_api->bind_int
-#define sqlite3_bind_int64 sqlite3_api->bind_int64
-#define sqlite3_bind_null sqlite3_api->bind_null
-#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
-#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
-#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
-#define sqlite3_bind_text sqlite3_api->bind_text
-#define sqlite3_bind_text16 sqlite3_api->bind_text16
-#define sqlite3_bind_value sqlite3_api->bind_value
-#define sqlite3_busy_handler sqlite3_api->busy_handler
-#define sqlite3_busy_timeout sqlite3_api->busy_timeout
-#define sqlite3_changes sqlite3_api->changes
-#define sqlite3_close sqlite3_api->close
-#define sqlite3_collation_needed sqlite3_api->collation_needed
-#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
-#define sqlite3_column_blob sqlite3_api->column_blob
-#define sqlite3_column_bytes sqlite3_api->column_bytes
-#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
-#define sqlite3_column_count sqlite3_api->column_count
-#define sqlite3_column_database_name sqlite3_api->column_database_name
-#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
-#define sqlite3_column_decltype sqlite3_api->column_decltype
-#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
-#define sqlite3_column_double sqlite3_api->column_double
-#define sqlite3_column_int sqlite3_api->column_int
-#define sqlite3_column_int64 sqlite3_api->column_int64
-#define sqlite3_column_name sqlite3_api->column_name
-#define sqlite3_column_name16 sqlite3_api->column_name16
-#define sqlite3_column_origin_name sqlite3_api->column_origin_name
-#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
-#define sqlite3_column_table_name sqlite3_api->column_table_name
-#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
-#define sqlite3_column_text sqlite3_api->column_text
-#define sqlite3_column_text16 sqlite3_api->column_text16
-#define sqlite3_column_type sqlite3_api->column_type
-#define sqlite3_column_value sqlite3_api->column_value
-#define sqlite3_commit_hook sqlite3_api->commit_hook
-#define sqlite3_complete sqlite3_api->complete
-#define sqlite3_complete16 sqlite3_api->complete16
-#define sqlite3_create_collation sqlite3_api->create_collation
-#define sqlite3_create_collation16 sqlite3_api->create_collation16
-#define sqlite3_create_function sqlite3_api->create_function
-#define sqlite3_create_function16 sqlite3_api->create_function16
-#define sqlite3_create_module sqlite3_api->create_module
-#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
-#define sqlite3_data_count sqlite3_api->data_count
-#define sqlite3_db_handle sqlite3_api->db_handle
-#define sqlite3_declare_vtab sqlite3_api->declare_vtab
-#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
-#define sqlite3_errcode sqlite3_api->errcode
-#define sqlite3_errmsg sqlite3_api->errmsg
-#define sqlite3_errmsg16 sqlite3_api->errmsg16
-#define sqlite3_exec sqlite3_api->exec
-#ifndef SQLITE_OMIT_DEPRECATED
-#define sqlite3_expired sqlite3_api->expired
-#endif
-#define sqlite3_finalize sqlite3_api->finalize
-#define sqlite3_free sqlite3_api->free
-#define sqlite3_free_table sqlite3_api->free_table
-#define sqlite3_get_autocommit sqlite3_api->get_autocommit
-#define sqlite3_get_auxdata sqlite3_api->get_auxdata
-#define sqlite3_get_table sqlite3_api->get_table
-#ifndef SQLITE_OMIT_DEPRECATED
-#define sqlite3_global_recover sqlite3_api->global_recover
-#endif
-#define sqlite3_interrupt sqlite3_api->interruptx
-#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
-#define sqlite3_libversion sqlite3_api->libversion
-#define sqlite3_libversion_number sqlite3_api->libversion_number
-#define sqlite3_malloc sqlite3_api->malloc
-#define sqlite3_mprintf sqlite3_api->mprintf
-#define sqlite3_open sqlite3_api->open
-#define sqlite3_open16 sqlite3_api->open16
-#define sqlite3_prepare sqlite3_api->prepare
-#define sqlite3_prepare16 sqlite3_api->prepare16
-#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
-#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
-#define sqlite3_profile sqlite3_api->profile
-#define sqlite3_progress_handler sqlite3_api->progress_handler
-#define sqlite3_realloc sqlite3_api->realloc
-#define sqlite3_reset sqlite3_api->reset
-#define sqlite3_result_blob sqlite3_api->result_blob
-#define sqlite3_result_double sqlite3_api->result_double
-#define sqlite3_result_error sqlite3_api->result_error
-#define sqlite3_result_error16 sqlite3_api->result_error16
-#define sqlite3_result_int sqlite3_api->result_int
-#define sqlite3_result_int64 sqlite3_api->result_int64
-#define sqlite3_result_null sqlite3_api->result_null
-#define sqlite3_result_text sqlite3_api->result_text
-#define sqlite3_result_text16 sqlite3_api->result_text16
-#define sqlite3_result_text16be sqlite3_api->result_text16be
-#define sqlite3_result_text16le sqlite3_api->result_text16le
-#define sqlite3_result_value sqlite3_api->result_value
-#define sqlite3_rollback_hook sqlite3_api->rollback_hook
-#define sqlite3_set_authorizer sqlite3_api->set_authorizer
-#define sqlite3_set_auxdata sqlite3_api->set_auxdata
-#define sqlite3_snprintf sqlite3_api->xsnprintf
-#define sqlite3_step sqlite3_api->step
-#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
-#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
-#define sqlite3_total_changes sqlite3_api->total_changes
-#define sqlite3_trace sqlite3_api->trace
-#ifndef SQLITE_OMIT_DEPRECATED
-#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
-#endif
-#define sqlite3_update_hook sqlite3_api->update_hook
-#define sqlite3_user_data sqlite3_api->user_data
-#define sqlite3_value_blob sqlite3_api->value_blob
-#define sqlite3_value_bytes sqlite3_api->value_bytes
-#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
-#define sqlite3_value_double sqlite3_api->value_double
-#define sqlite3_value_int sqlite3_api->value_int
-#define sqlite3_value_int64 sqlite3_api->value_int64
-#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
-#define sqlite3_value_text sqlite3_api->value_text
-#define sqlite3_value_text16 sqlite3_api->value_text16
-#define sqlite3_value_text16be sqlite3_api->value_text16be
-#define sqlite3_value_text16le sqlite3_api->value_text16le
-#define sqlite3_value_type sqlite3_api->value_type
-#define sqlite3_vmprintf sqlite3_api->vmprintf
-#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
-#define sqlite3_overload_function sqlite3_api->overload_function
-#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
-#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
-#define sqlite3_clear_bindings sqlite3_api->clear_bindings
-#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
-#define sqlite3_blob_bytes sqlite3_api->blob_bytes
-#define sqlite3_blob_close sqlite3_api->blob_close
-#define sqlite3_blob_open sqlite3_api->blob_open
-#define sqlite3_blob_read sqlite3_api->blob_read
-#define sqlite3_blob_write sqlite3_api->blob_write
-#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
-#define sqlite3_file_control sqlite3_api->file_control
-#define sqlite3_memory_highwater sqlite3_api->memory_highwater
-#define sqlite3_memory_used sqlite3_api->memory_used
-#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
-#define sqlite3_mutex_enter sqlite3_api->mutex_enter
-#define sqlite3_mutex_free sqlite3_api->mutex_free
-#define sqlite3_mutex_leave sqlite3_api->mutex_leave
-#define sqlite3_mutex_try sqlite3_api->mutex_try
-#define sqlite3_open_v2 sqlite3_api->open_v2
-#define sqlite3_release_memory sqlite3_api->release_memory
-#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
-#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
-#define sqlite3_sleep sqlite3_api->sleep
-#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
-#define sqlite3_vfs_find sqlite3_api->vfs_find
-#define sqlite3_vfs_register sqlite3_api->vfs_register
-#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
-#define sqlite3_threadsafe sqlite3_api->xthreadsafe
-#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
-#define sqlite3_result_error_code sqlite3_api->result_error_code
-#define sqlite3_test_control sqlite3_api->test_control
-#define sqlite3_randomness sqlite3_api->randomness
-#define sqlite3_context_db_handle sqlite3_api->context_db_handle
-#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
-#define sqlite3_limit sqlite3_api->limit
-#define sqlite3_next_stmt sqlite3_api->next_stmt
-#define sqlite3_sql sqlite3_api->sql
-#define sqlite3_status sqlite3_api->status
-#define sqlite3_backup_finish sqlite3_api->backup_finish
-#define sqlite3_backup_init sqlite3_api->backup_init
-#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
-#define sqlite3_backup_remaining sqlite3_api->backup_remaining
-#define sqlite3_backup_step sqlite3_api->backup_step
-#define sqlite3_compileoption_get sqlite3_api->compileoption_get
-#define sqlite3_compileoption_used sqlite3_api->compileoption_used
-#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
-#define sqlite3_db_config sqlite3_api->db_config
-#define sqlite3_db_mutex sqlite3_api->db_mutex
-#define sqlite3_db_status sqlite3_api->db_status
-#define sqlite3_extended_errcode sqlite3_api->extended_errcode
-#define sqlite3_log sqlite3_api->log
-#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
-#define sqlite3_sourceid sqlite3_api->sourceid
-#define sqlite3_stmt_status sqlite3_api->stmt_status
-#define sqlite3_strnicmp sqlite3_api->strnicmp
-#define sqlite3_unlock_notify sqlite3_api->unlock_notify
-#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
-#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
-#define sqlite3_wal_hook sqlite3_api->wal_hook
-#define sqlite3_blob_reopen sqlite3_api->blob_reopen
-#define sqlite3_vtab_config sqlite3_api->vtab_config
-#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
-/* Version 3.7.16 and later */
-#define sqlite3_close_v2 sqlite3_api->close_v2
-#define sqlite3_db_filename sqlite3_api->db_filename
-#define sqlite3_db_readonly sqlite3_api->db_readonly
-#define sqlite3_db_release_memory sqlite3_api->db_release_memory
-#define sqlite3_errstr sqlite3_api->errstr
-#define sqlite3_stmt_busy sqlite3_api->stmt_busy
-#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
-#define sqlite3_stricmp sqlite3_api->stricmp
-#define sqlite3_uri_boolean sqlite3_api->uri_boolean
-#define sqlite3_uri_int64 sqlite3_api->uri_int64
-#define sqlite3_uri_parameter sqlite3_api->uri_parameter
-#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
-#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
-/* Version 3.8.7 and later */
-#define sqlite3_auto_extension sqlite3_api->auto_extension
-#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
-#define sqlite3_bind_text64 sqlite3_api->bind_text64
-#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
-#define sqlite3_load_extension sqlite3_api->load_extension
-#define sqlite3_malloc64 sqlite3_api->malloc64
-#define sqlite3_msize sqlite3_api->msize
-#define sqlite3_realloc64 sqlite3_api->realloc64
-#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
-#define sqlite3_result_blob64 sqlite3_api->result_blob64
-#define sqlite3_result_text64 sqlite3_api->result_text64
-#define sqlite3_strglob sqlite3_api->strglob
-/* Version 3.8.11 and later */
-#define sqlite3_value_dup sqlite3_api->value_dup
-#define sqlite3_value_free sqlite3_api->value_free
-#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
-#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
-/* Version 3.9.0 and later */
-#define sqlite3_value_subtype sqlite3_api->value_subtype
-#define sqlite3_result_subtype sqlite3_api->result_subtype
-/* Version 3.10.0 and later */
-#define sqlite3_status64 sqlite3_api->status64
-#define sqlite3_strlike sqlite3_api->strlike
-#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
-/* Version 3.12.0 and later */
-#define sqlite3_system_errno sqlite3_api->system_errno
-/* Version 3.14.0 and later */
-#define sqlite3_trace_v2 sqlite3_api->trace_v2
-#define sqlite3_expanded_sql sqlite3_api->expanded_sql
-/* Version 3.18.0 and later */
-#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
-/* Version 3.20.0 and later */
-#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
-#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
-#define sqlite3_bind_pointer sqlite3_api->bind_pointer
-#define sqlite3_result_pointer sqlite3_api->result_pointer
-#define sqlite3_value_pointer sqlite3_api->value_pointer
-/* Version 3.22.0 and later */
-#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
-#define sqlite3_value_nochange sqlite3_api->value_nochange
-#define sqlite3_vtab_collation sqlite3_api->vtab_collation
-/* Version 3.24.0 and later */
-#define sqlite3_keyword_count sqlite3_api->keyword_count
-#define sqlite3_keyword_name sqlite3_api->keyword_name
-#define sqlite3_keyword_check sqlite3_api->keyword_check
-#define sqlite3_str_new sqlite3_api->str_new
-#define sqlite3_str_finish sqlite3_api->str_finish
-#define sqlite3_str_appendf sqlite3_api->str_appendf
-#define sqlite3_str_vappendf sqlite3_api->str_vappendf
-#define sqlite3_str_append sqlite3_api->str_append
-#define sqlite3_str_appendall sqlite3_api->str_appendall
-#define sqlite3_str_appendchar sqlite3_api->str_appendchar
-#define sqlite3_str_reset sqlite3_api->str_reset
-#define sqlite3_str_errcode sqlite3_api->str_errcode
-#define sqlite3_str_length sqlite3_api->str_length
-#define sqlite3_str_value sqlite3_api->str_value
-#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
-
-#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
- /* This case when the file really is being compiled as a loadable
- ** extension */
-# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
-# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
-# define SQLITE_EXTENSION_INIT3 \
- extern const sqlite3_api_routines *sqlite3_api;
-#else
- /* This case when the file is being statically linked into the
- ** application */
-# define SQLITE_EXTENSION_INIT1 /*no-op*/
-# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
-# define SQLITE_EXTENSION_INIT3 /*no-op*/
-#endif
-
-#endif /* SQLITE3EXT_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqliteInt.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/sqliteInt.h
deleted file mode 100644
index 91fde727a2b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqliteInt.h
+++ /dev/null
@@ -1,4491 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Internal interface definitions for SQLite.
-**
-*/
-#ifndef SQLITEINT_H
-#define SQLITEINT_H
-
-/* Special Comments:
-**
-** Some comments have special meaning to the tools that measure test
-** coverage:
-**
-** NO_TEST - The branches on this line are not
-** measured by branch coverage. This is
-** used on lines of code that actually
-** implement parts of coverage testing.
-**
-** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false
-** and the correct answer is still obtained,
-** though perhaps more slowly.
-**
-** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true
-** and the correct answer is still obtained,
-** though perhaps more slowly.
-**
-** PREVENTS-HARMLESS-OVERREAD - This branch prevents a buffer overread
-** that would be harmless and undetectable
-** if it did occur.
-**
-** In all cases, the special comment must be enclosed in the usual
-** slash-asterisk...asterisk-slash comment marks, with no spaces between the
-** asterisks and the comment text.
-*/
-
-/*
-** Make sure the Tcl calling convention macro is defined. This macro is
-** only used by test code and Tcl integration code.
-*/
-#ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-#endif
-
-/*
-** Include the header file used to customize the compiler options for MSVC.
-** This should be done first so that it can successfully prevent spurious
-** compiler warnings due to subsequent content in this file and other files
-** that are included by this file.
-*/
-#include "msvc.h"
-
-/*
-** Special setup for VxWorks
-*/
-#include "vxworks.h"
-
-/*
-** These #defines should enable >2GB file support on POSIX if the
-** underlying operating system supports it. If the OS lacks
-** large file support, or if the OS is windows, these should be no-ops.
-**
-** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
-** system #includes. Hence, this block of code must be the very first
-** code in all source files.
-**
-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
-** on the compiler command line. This is necessary if you are compiling
-** on a recent machine (ex: Red Hat 7.2) but you want your code to work
-** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
-** without this option, LFS is enable. But LFS does not exist in the kernel
-** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
-** portability you should omit LFS.
-**
-** The previous paragraph was written in 2005. (This paragraph is written
-** on 2008-11-28.) These days, all Linux kernels support large files, so
-** you should probably leave LFS enabled. But some embedded platforms might
-** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
-**
-** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE 1
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
-
-/* The GCC_VERSION and MSVC_VERSION macros are used to
-** conditionally include optimizations for each of these compilers. A
-** value of 0 means that compiler is not being used. The
-** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific
-** optimizations, and hence set all compiler macros to 0
-**
-** There was once also a CLANG_VERSION macro. However, we learn that the
-** version numbers in clang are for "marketing" only and are inconsistent
-** and unreliable. Fortunately, all versions of clang also recognize the
-** gcc version numbers and have reasonable settings for gcc version numbers,
-** so the GCC_VERSION macro will be set to a correct non-zero value even
-** when compiling with clang.
-*/
-#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
-# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
-#else
-# define GCC_VERSION 0
-#endif
-#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
-# define MSVC_VERSION _MSC_VER
-#else
-# define MSVC_VERSION 0
-#endif
-
-/* Needed for various definitions... */
-#if defined(__GNUC__) && !defined(_GNU_SOURCE)
-# define _GNU_SOURCE
-#endif
-
-#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
-# define _BSD_SOURCE
-#endif
-
-/*
-** For MinGW, check to see if we can include the header file containing its
-** version information, among other things. Normally, this internal MinGW
-** header file would [only] be included automatically by other MinGW header
-** files; however, the contained version information is now required by this
-** header file to work around binary compatibility issues (see below) and
-** this is the only known way to reliably obtain it. This entire #if block
-** would be completely unnecessary if there was any other way of detecting
-** MinGW via their preprocessor (e.g. if they customized their GCC to define
-** some MinGW-specific macros). When compiling for MinGW, either the
-** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be
-** defined; otherwise, detection of conditions specific to MinGW will be
-** disabled.
-*/
-#if defined(_HAVE_MINGW_H)
-# include "mingw.h"
-#elif defined(_HAVE__MINGW_H)
-# include "_mingw.h"
-#endif
-
-/*
-** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T
-** define is required to maintain binary compatibility with the MSVC runtime
-** library in use (e.g. for Windows XP).
-*/
-#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
- defined(_WIN32) && !defined(_WIN64) && \
- defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
- defined(__MSVCRT__)
-# define _USE_32BIT_TIME_T
-#endif
-
-/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
-** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
-** MinGW.
-*/
-#include "sqlite3.h"
-
-/*
-** Include the configuration header output by 'configure' if we're using the
-** autoconf-based build
-*/
-#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
-#include "config.h"
-#define SQLITECONFIG_H 1
-#endif
-
-#include "sqliteLimit.h"
-
-/* Disable nuisance warnings on Borland compilers */
-#if defined(__BORLANDC__)
-#pragma warn -rch /* unreachable code */
-#pragma warn -ccc /* Condition is always true or false */
-#pragma warn -aus /* Assigned value is never used */
-#pragma warn -csu /* Comparing signed and unsigned */
-#pragma warn -spa /* Suspicious pointer arithmetic */
-#endif
-
-/*
-** Include standard header files as necessary
-*/
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-/*
-** The following macros are used to cast pointers to integers and
-** integers to pointers. The way you do this varies from one compiler
-** to the next, so we have developed the following set of #if statements
-** to generate appropriate macros for a wide range of compilers.
-**
-** The correct "ANSI" way to do this is to use the intptr_t type.
-** Unfortunately, that typedef is not available on all compilers, or
-** if it is available, it requires an #include of specific headers
-** that vary from one machine to the next.
-**
-** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
-** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
-** So we have to define the macros in different ways depending on the
-** compiler.
-*/
-#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
-# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
-#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
-# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
-# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
-#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
-# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
-#else /* Generates a warning - but it always works */
-# define SQLITE_INT_TO_PTR(X) ((void*)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(X))
-#endif
-
-/*
-** A macro to hint to the compiler that a function should not be
-** inlined.
-*/
-#if defined(__GNUC__)
-# define SQLITE_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER) && _MSC_VER>=1310
-# define SQLITE_NOINLINE __declspec(noinline)
-#else
-# define SQLITE_NOINLINE
-#endif
-
-/*
-** Make sure that the compiler intrinsics we desire are enabled when
-** compiling with an appropriate version of MSVC unless prevented by
-** the SQLITE_DISABLE_INTRINSIC define.
-*/
-#if !defined(SQLITE_DISABLE_INTRINSIC)
-# if defined(_MSC_VER) && _MSC_VER>=1400
-# if !defined(_WIN32_WCE)
-# include <intrin.h>
-# pragma intrinsic(_byteswap_ushort)
-# pragma intrinsic(_byteswap_ulong)
-# pragma intrinsic(_byteswap_uint64)
-# pragma intrinsic(_ReadWriteBarrier)
-# else
-# include <cmnintrin.h>
-# endif
-# endif
-#endif
-
-/*
-** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
-** 0 means mutexes are permanently disable and the library is never
-** threadsafe. 1 means the library is serialized which is the highest
-** level of threadsafety. 2 means the library is multithreaded - multiple
-** threads can use SQLite as long as no two threads try to use the same
-** database connection at the same time.
-**
-** Older versions of SQLite used an optional THREADSAFE macro.
-** We support that for legacy.
-**
-** To ensure that the correct value of "THREADSAFE" is reported when querying
-** for compile-time options at runtime (e.g. "PRAGMA compile_options"), this
-** logic is partially replicated in ctime.c. If it is updated here, it should
-** also be updated there.
-*/
-#if !defined(SQLITE_THREADSAFE)
-# if defined(THREADSAFE)
-# define SQLITE_THREADSAFE THREADSAFE
-# else
-# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
-# endif
-#endif
-
-/*
-** Powersafe overwrite is on by default. But can be turned off using
-** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
-*/
-#ifndef SQLITE_POWERSAFE_OVERWRITE
-# define SQLITE_POWERSAFE_OVERWRITE 1
-#endif
-
-/*
-** EVIDENCE-OF: R-25715-37072 Memory allocation statistics are enabled by
-** default unless SQLite is compiled with SQLITE_DEFAULT_MEMSTATUS=0 in
-** which case memory allocation statistics are disabled by default.
-*/
-#if !defined(SQLITE_DEFAULT_MEMSTATUS)
-# define SQLITE_DEFAULT_MEMSTATUS 1
-#endif
-
-/*
-** Exactly one of the following macros must be defined in order to
-** specify which memory allocation subsystem to use.
-**
-** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
-** SQLITE_WIN32_MALLOC // Use Win32 native heap API
-** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
-** SQLITE_MEMDEBUG // Debugging version of system malloc()
-**
-** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
-** assert() macro is enabled, each call into the Win32 native heap subsystem
-** will cause HeapValidate to be called. If heap validation should fail, an
-** assertion will be triggered.
-**
-** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
-** the default.
-*/
-#if defined(SQLITE_SYSTEM_MALLOC) \
- + defined(SQLITE_WIN32_MALLOC) \
- + defined(SQLITE_ZERO_MALLOC) \
- + defined(SQLITE_MEMDEBUG)>1
-# error "Two or more of the following compile-time configuration options\
- are defined but at most one is allowed:\
- SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
- SQLITE_ZERO_MALLOC"
-#endif
-#if defined(SQLITE_SYSTEM_MALLOC) \
- + defined(SQLITE_WIN32_MALLOC) \
- + defined(SQLITE_ZERO_MALLOC) \
- + defined(SQLITE_MEMDEBUG)==0
-# define SQLITE_SYSTEM_MALLOC 1
-#endif
-
-/*
-** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
-** sizes of memory allocations below this value where possible.
-*/
-#if !defined(SQLITE_MALLOC_SOFT_LIMIT)
-# define SQLITE_MALLOC_SOFT_LIMIT 1024
-#endif
-
-/*
-** We need to define _XOPEN_SOURCE as follows in order to enable
-** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
-** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
-** it.
-*/
-#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
-# define _XOPEN_SOURCE 600
-#endif
-
-/*
-** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
-** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
-** make it true by defining or undefining NDEBUG.
-**
-** Setting NDEBUG makes the code smaller and faster by disabling the
-** assert() statements in the code. So we want the default action
-** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
-** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
-** feature.
-*/
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
-# define NDEBUG 1
-#endif
-#if defined(NDEBUG) && defined(SQLITE_DEBUG)
-# undef NDEBUG
-#endif
-
-/*
-** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on.
-*/
-#if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG)
-# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1
-#endif
-
-/*
-** The testcase() macro is used to aid in coverage testing. When
-** doing coverage testing, the condition inside the argument to
-** testcase() must be evaluated both true and false in order to
-** get full branch coverage. The testcase() macro is inserted
-** to help ensure adequate test coverage in places where simple
-** condition/decision coverage is inadequate. For example, testcase()
-** can be used to make sure boundary values are tested. For
-** bitmask tests, testcase() can be used to make sure each bit
-** is significant and used at least once. On switch statements
-** where multiple cases go to the same block of code, testcase()
-** can insure that all cases are evaluated.
-**
-*/
-#ifdef SQLITE_COVERAGE_TEST
- void sqlite3Coverage(int);
-# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
-#else
-# define testcase(X)
-#endif
-
-/*
-** The TESTONLY macro is used to enclose variable declarations or
-** other bits of code that are needed to support the arguments
-** within testcase() and assert() macros.
-*/
-#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
-# define TESTONLY(X) X
-#else
-# define TESTONLY(X)
-#endif
-
-/*
-** Sometimes we need a small amount of code such as a variable initialization
-** to setup for a later assert() statement. We do not want this code to
-** appear when assert() is disabled. The following macro is therefore
-** used to contain that setup code. The "VVA" acronym stands for
-** "Verification, Validation, and Accreditation". In other words, the
-** code within VVA_ONLY() will only run during verification processes.
-*/
-#ifndef NDEBUG
-# define VVA_ONLY(X) X
-#else
-# define VVA_ONLY(X)
-#endif
-
-/*
-** The ALWAYS and NEVER macros surround boolean expressions which
-** are intended to always be true or false, respectively. Such
-** expressions could be omitted from the code completely. But they
-** are included in a few cases in order to enhance the resilience
-** of SQLite to unexpected behavior - to make the code "self-healing"
-** or "ductile" rather than being "brittle" and crashing at the first
-** hint of unplanned behavior.
-**
-** In other words, ALWAYS and NEVER are added for defensive code.
-**
-** When doing coverage testing ALWAYS and NEVER are hard-coded to
-** be true and false so that the unreachable code they specify will
-** not be counted as untested code.
-*/
-#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
-# define ALWAYS(X) (1)
-# define NEVER(X) (0)
-#elif !defined(NDEBUG)
-# define ALWAYS(X) ((X)?1:(assert(0),0))
-# define NEVER(X) ((X)?(assert(0),1):0)
-#else
-# define ALWAYS(X) (X)
-# define NEVER(X) (X)
-#endif
-
-/*
-** Some conditionals are optimizations only. In other words, if the
-** conditionals are replaced with a constant 1 (true) or 0 (false) then
-** the correct answer is still obtained, though perhaps not as quickly.
-**
-** The following macros mark these optimizations conditionals.
-*/
-#if defined(SQLITE_MUTATION_TEST)
-# define OK_IF_ALWAYS_TRUE(X) (1)
-# define OK_IF_ALWAYS_FALSE(X) (0)
-#else
-# define OK_IF_ALWAYS_TRUE(X) (X)
-# define OK_IF_ALWAYS_FALSE(X) (X)
-#endif
-
-/*
-** Some malloc failures are only possible if SQLITE_TEST_REALLOC_STRESS is
-** defined. We need to defend against those failures when testing with
-** SQLITE_TEST_REALLOC_STRESS, but we don't want the unreachable branches
-** during a normal build. The following macro can be used to disable tests
-** that are always false except when SQLITE_TEST_REALLOC_STRESS is set.
-*/
-#if defined(SQLITE_TEST_REALLOC_STRESS)
-# define ONLY_IF_REALLOC_STRESS(X) (X)
-#elif !defined(NDEBUG)
-# define ONLY_IF_REALLOC_STRESS(X) ((X)?(assert(0),1):0)
-#else
-# define ONLY_IF_REALLOC_STRESS(X) (0)
-#endif
-
-/*
-** Declarations used for tracing the operating system interfaces.
-*/
-#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \
- (defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
- extern int sqlite3OSTrace;
-# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
-# define SQLITE_HAVE_OS_TRACE
-#else
-# define OSTRACE(X)
-# undef SQLITE_HAVE_OS_TRACE
-#endif
-
-/*
-** Is the sqlite3ErrName() function needed in the build? Currently,
-** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when
-** OSTRACE is enabled), and by several "test*.c" files (which are
-** compiled using SQLITE_TEST).
-*/
-#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \
- (defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
-# define SQLITE_NEED_ERR_NAME
-#else
-# undef SQLITE_NEED_ERR_NAME
-#endif
-
-/*
-** SQLITE_ENABLE_EXPLAIN_COMMENTS is incompatible with SQLITE_OMIT_EXPLAIN
-*/
-#ifdef SQLITE_OMIT_EXPLAIN
-# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
-#endif
-
-/*
-** Return true (non-zero) if the input is an integer that is too large
-** to fit in 32-bits. This macro is used inside of various testcase()
-** macros to verify that we have tested SQLite for large-file support.
-*/
-#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
-
-/*
-** The macro unlikely() is a hint that surrounds a boolean
-** expression that is usually false. Macro likely() surrounds
-** a boolean expression that is usually true. These hints could,
-** in theory, be used by the compiler to generate better code, but
-** currently they are just comments for human readers.
-*/
-#define likely(X) (X)
-#define unlikely(X) (X)
-
-#include "hash.h"
-#include "parse.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stddef.h>
-
-/*
-** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
-** This allows better measurements of where memcpy() is used when running
-** cachegrind. But this macro version of memcpy() is very slow so it
-** should not be used in production. This is a performance measurement
-** hack only.
-*/
-#ifdef SQLITE_INLINE_MEMCPY
-# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\
- int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);}
-#endif
-
-/*
-** If compiling for a processor that lacks floating point support,
-** substitute integer for floating-point
-*/
-#ifdef SQLITE_OMIT_FLOATING_POINT
-# define double sqlite_int64
-# define float sqlite_int64
-# define LONGDOUBLE_TYPE sqlite_int64
-# ifndef SQLITE_BIG_DBL
-# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
-# endif
-# define SQLITE_OMIT_DATETIME_FUNCS 1
-# define SQLITE_OMIT_TRACE 1
-# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
-# undef SQLITE_HAVE_ISNAN
-#endif
-#ifndef SQLITE_BIG_DBL
-# define SQLITE_BIG_DBL (1e99)
-#endif
-
-/*
-** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
-** afterward. Having this macro allows us to cause the C compiler
-** to omit code used by TEMP tables without messy #ifndef statements.
-*/
-#ifdef SQLITE_OMIT_TEMPDB
-#define OMIT_TEMPDB 1
-#else
-#define OMIT_TEMPDB 0
-#endif
-
-/*
-** The "file format" number is an integer that is incremented whenever
-** the VDBE-level file format changes. The following macros define the
-** the default file format for new databases and the maximum file format
-** that the library can read.
-*/
-#define SQLITE_MAX_FILE_FORMAT 4
-#ifndef SQLITE_DEFAULT_FILE_FORMAT
-# define SQLITE_DEFAULT_FILE_FORMAT 4
-#endif
-
-/*
-** Determine whether triggers are recursive by default. This can be
-** changed at run-time using a pragma.
-*/
-#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
-# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0
-#endif
-
-/*
-** Provide a default value for SQLITE_TEMP_STORE in case it is not specified
-** on the command-line
-*/
-#ifndef SQLITE_TEMP_STORE
-# define SQLITE_TEMP_STORE 1
-#endif
-
-/*
-** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if
-** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it
-** to zero.
-*/
-#if SQLITE_TEMP_STORE==3 || SQLITE_THREADSAFE==0
-# undef SQLITE_MAX_WORKER_THREADS
-# define SQLITE_MAX_WORKER_THREADS 0
-#endif
-#ifndef SQLITE_MAX_WORKER_THREADS
-# define SQLITE_MAX_WORKER_THREADS 8
-#endif
-#ifndef SQLITE_DEFAULT_WORKER_THREADS
-# define SQLITE_DEFAULT_WORKER_THREADS 0
-#endif
-#if SQLITE_DEFAULT_WORKER_THREADS>SQLITE_MAX_WORKER_THREADS
-# undef SQLITE_MAX_WORKER_THREADS
-# define SQLITE_MAX_WORKER_THREADS SQLITE_DEFAULT_WORKER_THREADS
-#endif
-
-/*
-** The default initial allocation for the pagecache when using separate
-** pagecaches for each database connection. A positive number is the
-** number of pages. A negative number N translations means that a buffer
-** of -1024*N bytes is allocated and used for as many pages as it will hold.
-**
-** The default value of "20" was choosen to minimize the run-time of the
-** speedtest1 test program with options: --shrink-memory --reprepare
-*/
-#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
-# define SQLITE_DEFAULT_PCACHE_INITSZ 20
-#endif
-
-/*
-** Default value for the SQLITE_CONFIG_SORTERREF_SIZE option.
-*/
-#ifndef SQLITE_DEFAULT_SORTERREF_SIZE
-# define SQLITE_DEFAULT_SORTERREF_SIZE 0x7fffffff
-#endif
-
-/*
-** The compile-time options SQLITE_MMAP_READWRITE and
-** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another.
-** You must choose one or the other (or neither) but not both.
-*/
-#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
-#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE
-#endif
-
-/*
-** GCC does not define the offsetof() macro so we'll have to do it
-** ourselves.
-*/
-#ifndef offsetof
-#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
-#endif
-
-/*
-** Macros to compute minimum and maximum of two numbers.
-*/
-#ifndef MIN
-# define MIN(A,B) ((A)<(B)?(A):(B))
-#endif
-#ifndef MAX
-# define MAX(A,B) ((A)>(B)?(A):(B))
-#endif
-
-/*
-** Swap two objects of type TYPE.
-*/
-#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
-
-/*
-** Check to see if this machine uses EBCDIC. (Yes, believe it or
-** not, there are still machines out there that use EBCDIC.)
-*/
-#if 'A' == '\301'
-# define SQLITE_EBCDIC 1
-#else
-# define SQLITE_ASCII 1
-#endif
-
-/*
-** Integers of known sizes. These typedefs might change for architectures
-** where the sizes very. Preprocessor macros are available so that the
-** types can be conveniently redefined at compile-type. Like this:
-**
-** cc '-DUINTPTR_TYPE=long long int' ...
-*/
-#ifndef UINT32_TYPE
-# ifdef HAVE_UINT32_T
-# define UINT32_TYPE uint32_t
-# else
-# define UINT32_TYPE unsigned int
-# endif
-#endif
-#ifndef UINT16_TYPE
-# ifdef HAVE_UINT16_T
-# define UINT16_TYPE uint16_t
-# else
-# define UINT16_TYPE unsigned short int
-# endif
-#endif
-#ifndef INT16_TYPE
-# ifdef HAVE_INT16_T
-# define INT16_TYPE int16_t
-# else
-# define INT16_TYPE short int
-# endif
-#endif
-#ifndef UINT8_TYPE
-# ifdef HAVE_UINT8_T
-# define UINT8_TYPE uint8_t
-# else
-# define UINT8_TYPE unsigned char
-# endif
-#endif
-#ifndef INT8_TYPE
-# ifdef HAVE_INT8_T
-# define INT8_TYPE int8_t
-# else
-# define INT8_TYPE signed char
-# endif
-#endif
-#ifndef LONGDOUBLE_TYPE
-# define LONGDOUBLE_TYPE long double
-#endif
-typedef sqlite_int64 i64; /* 8-byte signed integer */
-typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
-typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
-typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
-typedef INT16_TYPE i16; /* 2-byte signed integer */
-typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
-typedef INT8_TYPE i8; /* 1-byte signed integer */
-
-/*
-** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
-** that can be stored in a u32 without loss of data. The value
-** is 0x00000000ffffffff. But because of quirks of some compilers, we
-** have to specify the value in the less intuitive manner shown:
-*/
-#define SQLITE_MAX_U32 ((((u64)1)<<32)-1)
-
-/*
-** The datatype used to store estimates of the number of rows in a
-** table or index. This is an unsigned integer type. For 99.9% of
-** the world, a 32-bit integer is sufficient. But a 64-bit integer
-** can be used at compile-time if desired.
-*/
-#ifdef SQLITE_64BIT_STATS
- typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
-#else
- typedef u32 tRowcnt; /* 32-bit is the default */
-#endif
-
-/*
-** Estimated quantities used for query planning are stored as 16-bit
-** logarithms. For quantity X, the value stored is 10*log2(X). This
-** gives a possible range of values of approximately 1.0e986 to 1e-986.
-** But the allowed values are "grainy". Not every value is representable.
-** For example, quantities 16 and 17 are both represented by a LogEst
-** of 40. However, since LogEst quantities are suppose to be estimates,
-** not exact values, this imprecision is not a problem.
-**
-** "LogEst" is short for "Logarithmic Estimate".
-**
-** Examples:
-** 1 -> 0 20 -> 43 10000 -> 132
-** 2 -> 10 25 -> 46 25000 -> 146
-** 3 -> 16 100 -> 66 1000000 -> 199
-** 4 -> 20 1000 -> 99 1048576 -> 200
-** 10 -> 33 1024 -> 100 4294967296 -> 320
-**
-** The LogEst can be negative to indicate fractional values.
-** Examples:
-**
-** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
-*/
-typedef INT16_TYPE LogEst;
-
-/*
-** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
-*/
-#ifndef SQLITE_PTRSIZE
-# if defined(__SIZEOF_POINTER__)
-# define SQLITE_PTRSIZE __SIZEOF_POINTER__
-# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(_M_ARM) || defined(__arm__) || defined(__x86)
-# define SQLITE_PTRSIZE 4
-# else
-# define SQLITE_PTRSIZE 8
-# endif
-#endif
-
-/* The uptr type is an unsigned integer large enough to hold a pointer
-*/
-#if defined(HAVE_STDINT_H)
- typedef uintptr_t uptr;
-#elif SQLITE_PTRSIZE==4
- typedef u32 uptr;
-#else
- typedef u64 uptr;
-#endif
-
-/*
-** The SQLITE_WITHIN(P,S,E) macro checks to see if pointer P points to
-** something between S (inclusive) and E (exclusive).
-**
-** In other words, S is a buffer and E is a pointer to the first byte after
-** the end of buffer S. This macro returns true if P points to something
-** contained within the buffer S.
-*/
-#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
-
-
-/*
-** Macros to determine whether the machine is big or little endian,
-** and whether or not that determination is run-time or compile-time.
-**
-** For best performance, an attempt is made to guess at the byte-order
-** using C-preprocessor macros. If that is unsuccessful, or if
-** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined
-** at run-time.
-*/
-#ifndef SQLITE_BYTEORDER
-# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
- defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)
-# define SQLITE_BYTEORDER 1234
-# elif defined(sparc) || defined(__ppc__)
-# define SQLITE_BYTEORDER 4321
-# else
-# define SQLITE_BYTEORDER 0
-# endif
-#endif
-#if SQLITE_BYTEORDER==4321
-# define SQLITE_BIGENDIAN 1
-# define SQLITE_LITTLEENDIAN 0
-# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
-#elif SQLITE_BYTEORDER==1234
-# define SQLITE_BIGENDIAN 0
-# define SQLITE_LITTLEENDIAN 1
-# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
-#else
-# ifdef SQLITE_AMALGAMATION
- const int sqlite3one = 1;
-# else
- extern const int sqlite3one;
-# endif
-# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
-# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
-# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
-#endif
-
-/*
-** Constants for the largest and smallest possible 64-bit signed integers.
-** These macros are designed to work correctly on both 32-bit and 64-bit
-** compilers.
-*/
-#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
-#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
-
-/*
-** Round up a number to the next larger multiple of 8. This is used
-** to force 8-byte alignment on 64-bit architectures.
-*/
-#define ROUND8(x) (((x)+7)&~7)
-
-/*
-** Round down to the nearest multiple of 8
-*/
-#define ROUNDDOWN8(x) ((x)&~7)
-
-/*
-** Assert that the pointer X is aligned to an 8-byte boundary. This
-** macro is used only within assert() to verify that the code gets
-** all alignment restrictions correct.
-**
-** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
-** underlying malloc() implementation might return us 4-byte aligned
-** pointers. In that case, only verify 4-byte alignment.
-*/
-#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
-# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0)
-#else
-# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0)
-#endif
-
-/*
-** Disable MMAP on platforms where it is known to not work
-*/
-#if defined(__OpenBSD__) || defined(__QNXNTO__)
-# undef SQLITE_MAX_MMAP_SIZE
-# define SQLITE_MAX_MMAP_SIZE 0
-#endif
-
-/*
-** Default maximum size of memory used by memory-mapped I/O in the VFS
-*/
-#ifdef __APPLE__
-# include <TargetConditionals.h>
-#endif
-#ifndef SQLITE_MAX_MMAP_SIZE
-# if defined(__linux__) \
- || defined(_WIN32) \
- || (defined(__APPLE__) && defined(__MACH__)) \
- || defined(__sun) \
- || defined(__FreeBSD__) \
- || defined(__DragonFly__)
-# define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */
-# else
-# define SQLITE_MAX_MMAP_SIZE 0
-# endif
-#endif
-
-/*
-** The default MMAP_SIZE is zero on all platforms. Or, even if a larger
-** default MMAP_SIZE is specified at compile-time, make sure that it does
-** not exceed the maximum mmap size.
-*/
-#ifndef SQLITE_DEFAULT_MMAP_SIZE
-# define SQLITE_DEFAULT_MMAP_SIZE 0
-#endif
-#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
-# undef SQLITE_DEFAULT_MMAP_SIZE
-# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
-#endif
-
-/*
-** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined.
-** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also
-** define SQLITE_ENABLE_STAT3_OR_STAT4
-*/
-#ifdef SQLITE_ENABLE_STAT4
-# undef SQLITE_ENABLE_STAT3
-# define SQLITE_ENABLE_STAT3_OR_STAT4 1
-#elif SQLITE_ENABLE_STAT3
-# define SQLITE_ENABLE_STAT3_OR_STAT4 1
-#elif SQLITE_ENABLE_STAT3_OR_STAT4
-# undef SQLITE_ENABLE_STAT3_OR_STAT4
-#endif
-
-/*
-** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
-** the Select query generator tracing logic is turned on.
-*/
-#if defined(SQLITE_ENABLE_SELECTTRACE)
-# define SELECTTRACE_ENABLED 1
-#else
-# define SELECTTRACE_ENABLED 0
-#endif
-
-/*
-** An instance of the following structure is used to store the busy-handler
-** callback for a given sqlite handle.
-**
-** The sqlite.busyHandler member of the sqlite struct contains the busy
-** callback for the database handle. Each pager opened via the sqlite
-** handle is passed a pointer to sqlite.busyHandler. The busy-handler
-** callback is currently invoked only from within pager.c.
-*/
-typedef struct BusyHandler BusyHandler;
-struct BusyHandler {
- int (*xBusyHandler)(void *,int); /* The busy callback */
- void *pBusyArg; /* First arg to busy callback */
- int nBusy; /* Incremented with each busy call */
- u8 bExtraFileArg; /* Include sqlite3_file as callback arg */
-};
-
-/*
-** Name of the master database table. The master database table
-** is a special table that holds the names and attributes of all
-** user tables and indices.
-*/
-#define MASTER_NAME "sqlite_master"
-#define TEMP_MASTER_NAME "sqlite_temp_master"
-
-/*
-** The root-page of the master database table.
-*/
-#define MASTER_ROOT 1
-
-/*
-** The name of the schema table.
-*/
-#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)
-
-/*
-** A convenience macro that returns the number of elements in
-** an array.
-*/
-#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
-
-/*
-** Determine if the argument is a power of two
-*/
-#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
-
-/*
-** The following value as a destructor means to use sqlite3DbFree().
-** The sqlite3DbFree() routine requires two parameters instead of the
-** one parameter that destructors normally want. So we have to introduce
-** this magic value that the code knows to handle differently. Any
-** pointer will work here as long as it is distinct from SQLITE_STATIC
-** and SQLITE_TRANSIENT.
-*/
-#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3MallocSize)
-
-/*
-** When SQLITE_OMIT_WSD is defined, it means that the target platform does
-** not support Writable Static Data (WSD) such as global and static variables.
-** All variables must either be on the stack or dynamically allocated from
-** the heap. When WSD is unsupported, the variable declarations scattered
-** throughout the SQLite code must become constants instead. The SQLITE_WSD
-** macro is used for this purpose. And instead of referencing the variable
-** directly, we use its constant as a key to lookup the run-time allocated
-** buffer that holds real variable. The constant is also the initializer
-** for the run-time allocated buffer.
-**
-** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL
-** macros become no-ops and have zero performance impact.
-*/
-#ifdef SQLITE_OMIT_WSD
- #define SQLITE_WSD const
- #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
- #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
- int sqlite3_wsd_init(int N, int J);
- void *sqlite3_wsd_find(void *K, int L);
-#else
- #define SQLITE_WSD
- #define GLOBAL(t,v) v
- #define sqlite3GlobalConfig sqlite3Config
-#endif
-
-/*
-** The following macros are used to suppress compiler warnings and to
-** make it clear to human readers when a function parameter is deliberately
-** left unused within the body of a function. This usually happens when
-** a function is called via a function pointer. For example the
-** implementation of an SQL aggregate step callback may not use the
-** parameter indicating the number of arguments passed to the aggregate,
-** if it knows that this is enforced elsewhere.
-**
-** When a function parameter is not used at all within the body of a function,
-** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
-** However, these macros may also be used to suppress warnings related to
-** parameters that may or may not be used depending on compilation options.
-** For example those parameters only used in assert() statements. In these
-** cases the parameters are named as per the usual conventions.
-*/
-#define UNUSED_PARAMETER(x) (void)(x)
-#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
-
-/*
-** Forward references to structures
-*/
-typedef struct AggInfo AggInfo;
-typedef struct AuthContext AuthContext;
-typedef struct AutoincInfo AutoincInfo;
-typedef struct Bitvec Bitvec;
-typedef struct CollSeq CollSeq;
-typedef struct Column Column;
-typedef struct Db Db;
-typedef struct Schema Schema;
-typedef struct Expr Expr;
-typedef struct ExprList ExprList;
-typedef struct FKey FKey;
-typedef struct FuncDestructor FuncDestructor;
-typedef struct FuncDef FuncDef;
-typedef struct FuncDefHash FuncDefHash;
-typedef struct IdList IdList;
-typedef struct Index Index;
-typedef struct IndexSample IndexSample;
-typedef struct KeyClass KeyClass;
-typedef struct KeyInfo KeyInfo;
-typedef struct Lookaside Lookaside;
-typedef struct LookasideSlot LookasideSlot;
-typedef struct Module Module;
-typedef struct NameContext NameContext;
-typedef struct Parse Parse;
-typedef struct PreUpdate PreUpdate;
-typedef struct PrintfArguments PrintfArguments;
-typedef struct RowSet RowSet;
-typedef struct Savepoint Savepoint;
-typedef struct Select Select;
-typedef struct SQLiteThread SQLiteThread;
-typedef struct SelectDest SelectDest;
-typedef struct SrcList SrcList;
-typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
-typedef struct Table Table;
-typedef struct TableLock TableLock;
-typedef struct Token Token;
-typedef struct TreeView TreeView;
-typedef struct Trigger Trigger;
-typedef struct TriggerPrg TriggerPrg;
-typedef struct TriggerStep TriggerStep;
-typedef struct UnpackedRecord UnpackedRecord;
-typedef struct Upsert Upsert;
-typedef struct VTable VTable;
-typedef struct VtabCtx VtabCtx;
-typedef struct Walker Walker;
-typedef struct WhereInfo WhereInfo;
-typedef struct With With;
-
-/* A VList object records a mapping between parameters/variables/wildcards
-** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
-** variable number associated with that parameter. See the format description
-** on the sqlite3VListAdd() routine for more information. A VList is really
-** just an array of integers.
-*/
-typedef int VList;
-
-/*
-** Defer sourcing vdbe.h and btree.h until after the "u8" and
-** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
-** pointer types (i.e. FuncDef) defined above.
-*/
-#include "btree.h"
-#include "vdbe.h"
-#include "pager.h"
-#include "pcache.h"
-#include "os.h"
-#include "mutex.h"
-
-/* The SQLITE_EXTRA_DURABLE compile-time option used to set the default
-** synchronous setting to EXTRA. It is no longer supported.
-*/
-#ifdef SQLITE_EXTRA_DURABLE
-# warning Use SQLITE_DEFAULT_SYNCHRONOUS=3 instead of SQLITE_EXTRA_DURABLE
-# define SQLITE_DEFAULT_SYNCHRONOUS 3
-#endif
-
-/*
-** Default synchronous levels.
-**
-** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ
-** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1.
-**
-** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS
-** OFF 1 0
-** NORMAL 2 1
-** FULL 3 2
-** EXTRA 4 3
-**
-** The "PRAGMA synchronous" statement also uses the zero-based numbers.
-** In other words, the zero-based numbers are used for all external interfaces
-** and the one-based values are used internally.
-*/
-#ifndef SQLITE_DEFAULT_SYNCHRONOUS
-# define SQLITE_DEFAULT_SYNCHRONOUS 2
-#endif
-#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS
-# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS
-#endif
-
-/*
-** Each database file to be accessed by the system is an instance
-** of the following structure. There are normally two of these structures
-** in the sqlite.aDb[] array. aDb[0] is the main database file and
-** aDb[1] is the database file used to hold temporary tables. Additional
-** databases may be attached.
-*/
-struct Db {
- char *zDbSName; /* Name of this database. (schema name, not filename) */
- Btree *pBt; /* The B*Tree structure for this database file */
- u8 safety_level; /* How aggressive at syncing data to disk */
- u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */
- Schema *pSchema; /* Pointer to database schema (possibly shared) */
-};
-
-/*
-** An instance of the following structure stores a database schema.
-**
-** Most Schema objects are associated with a Btree. The exception is
-** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing.
-** In shared cache mode, a single Schema object can be shared by multiple
-** Btrees that refer to the same underlying BtShared object.
-**
-** Schema objects are automatically deallocated when the last Btree that
-** references them is destroyed. The TEMP Schema is manually freed by
-** sqlite3_close().
-*
-** A thread must be holding a mutex on the corresponding Btree in order
-** to access Schema content. This implies that the thread must also be
-** holding a mutex on the sqlite3 connection pointer that owns the Btree.
-** For a TEMP Schema, only the connection mutex is required.
-*/
-struct Schema {
- int schema_cookie; /* Database schema version number for this file */
- int iGeneration; /* Generation counter. Incremented with each change */
- Hash tblHash; /* All tables indexed by name */
- Hash idxHash; /* All (named) indices indexed by name */
- Hash trigHash; /* All triggers indexed by name */
- Hash fkeyHash; /* All foreign keys by referenced table name */
- Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */
- u8 file_format; /* Schema format version for this file */
- u8 enc; /* Text encoding used by this database */
- u16 schemaFlags; /* Flags associated with this schema */
- int cache_size; /* Number of pages to use in the cache */
-};
-
-/*
-** These macros can be used to test, set, or clear bits in the
-** Db.pSchema->flags field.
-*/
-#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))==(P))
-#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))!=0)
-#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags|=(P)
-#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags&=~(P)
-
-/*
-** Allowed values for the DB.pSchema->flags field.
-**
-** The DB_SchemaLoaded flag is set after the database schema has been
-** read into internal hash tables.
-**
-** DB_UnresetViews means that one or more views have column names that
-** have been filled out. If the schema changes, these column names might
-** changes and so the view will need to be reset.
-*/
-#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */
-#define DB_UnresetViews 0x0002 /* Some views have defined column names */
-#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */
-#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */
-
-/*
-** The number of different kinds of things that can be limited
-** using the sqlite3_limit() interface.
-*/
-#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1)
-
-/*
-** Lookaside malloc is a set of fixed-size buffers that can be used
-** to satisfy small transient memory allocation requests for objects
-** associated with a particular database connection. The use of
-** lookaside malloc provides a significant performance enhancement
-** (approx 10%) by avoiding numerous malloc/free requests while parsing
-** SQL statements.
-**
-** The Lookaside structure holds configuration information about the
-** lookaside malloc subsystem. Each available memory allocation in
-** the lookaside subsystem is stored on a linked list of LookasideSlot
-** objects.
-**
-** Lookaside allocations are only allowed for objects that are associated
-** with a particular database connection. Hence, schema information cannot
-** be stored in lookaside because in shared cache mode the schema information
-** is shared by multiple database connections. Therefore, while parsing
-** schema information, the Lookaside.bEnabled flag is cleared so that
-** lookaside allocations are not used to construct the schema objects.
-*/
-struct Lookaside {
- u32 bDisable; /* Only operate the lookaside when zero */
- u16 sz; /* Size of each buffer in bytes */
- u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
- u32 nSlot; /* Number of lookaside slots allocated */
- u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
- LookasideSlot *pInit; /* List of buffers not previously used */
- LookasideSlot *pFree; /* List of available buffers */
- void *pStart; /* First byte of available memory space */
- void *pEnd; /* First byte past end of available space */
-};
-struct LookasideSlot {
- LookasideSlot *pNext; /* Next buffer in the list of free buffers */
-};
-
-/*
-** A hash table for built-in function definitions. (Application-defined
-** functions use a regular table table from hash.h.)
-**
-** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
-** Collisions are on the FuncDef.u.pHash chain.
-*/
-#define SQLITE_FUNC_HASH_SZ 23
-struct FuncDefHash {
- FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */
-};
-
-#ifdef SQLITE_USER_AUTHENTICATION
-/*
-** Information held in the "sqlite3" database connection object and used
-** to manage user authentication.
-*/
-typedef struct sqlite3_userauth sqlite3_userauth;
-struct sqlite3_userauth {
- u8 authLevel; /* Current authentication level */
- int nAuthPW; /* Size of the zAuthPW in bytes */
- char *zAuthPW; /* Password used to authenticate */
- char *zAuthUser; /* User name used to authenticate */
-};
-
-/* Allowed values for sqlite3_userauth.authLevel */
-#define UAUTH_Unknown 0 /* Authentication not yet checked */
-#define UAUTH_Fail 1 /* User authentication failed */
-#define UAUTH_User 2 /* Authenticated as a normal user */
-#define UAUTH_Admin 3 /* Authenticated as an administrator */
-
-/* Functions used only by user authorization logic */
-int sqlite3UserAuthTable(const char*);
-int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
-void sqlite3UserAuthInit(sqlite3*);
-void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
-
-#endif /* SQLITE_USER_AUTHENTICATION */
-
-/*
-** typedef for the authorization callback function.
-*/
-#ifdef SQLITE_USER_AUTHENTICATION
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*, const char*);
-#else
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*);
-#endif
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
-** in the style of sqlite3_trace()
-*/
-#define SQLITE_TRACE_LEGACY 0x80
-#else
-#define SQLITE_TRACE_LEGACY 0
-#endif /* SQLITE_OMIT_DEPRECATED */
-
-
-/*
-** Each database connection is an instance of the following structure.
-*/
-struct sqlite3 {
- sqlite3_vfs *pVfs; /* OS Interface */
- struct Vdbe *pVdbe; /* List of active virtual machines */
- CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
- sqlite3_mutex *mutex; /* Connection mutex */
- Db *aDb; /* All backends */
- int nDb; /* Number of backends currently in use */
- u32 mDbFlags; /* flags recording internal state */
- u32 flags; /* flags settable by pragmas. See below */
- i64 lastRowid; /* ROWID of most recent insert (see above) */
- i64 szMmap; /* Default mmap_size setting */
- u32 nSchemaLock; /* Do not reset the schema when non-zero */
- unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
- int errCode; /* Most recent error code (SQLITE_*) */
- int errMask; /* & result codes with this before returning */
- int iSysErrno; /* Errno value from last system error */
- u16 dbOptFlags; /* Flags to enable/disable optimizations */
- u8 enc; /* Text encoding */
- u8 autoCommit; /* The auto-commit flag. */
- u8 temp_store; /* 1: file 2: memory 0: default */
- u8 mallocFailed; /* True if we have seen a malloc failure */
- u8 bBenignMalloc; /* Do not require OOMs if true */
- u8 dfltLockMode; /* Default locking-mode for attached dbs */
- signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
- u8 suppressErr; /* Do not issue error messages if true */
- u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
- u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
- u8 mTrace; /* zero or more SQLITE_TRACE flags */
- u8 noSharedCache; /* True if no shared-cache backends */
- u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
- int nextPagesize; /* Pagesize after VACUUM if >0 */
- u32 magic; /* Magic number for detect library misuse */
- int nChange; /* Value returned by sqlite3_changes() */
- int nTotalChange; /* Value returned by sqlite3_total_changes() */
- int aLimit[SQLITE_N_LIMIT]; /* Limits */
- int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
- struct sqlite3InitInfo { /* Information used during initialization */
- int newTnum; /* Rootpage of table being initialized */
- u8 iDb; /* Which db file is being initialized */
- u8 busy; /* TRUE if currently initializing */
- unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
- unsigned imposterTable : 1; /* Building an imposter table */
- unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
- } init;
- int nVdbeActive; /* Number of VDBEs currently running */
- int nVdbeRead; /* Number of active VDBEs that read or write */
- int nVdbeWrite; /* Number of active VDBEs that read and write */
- int nVdbeExec; /* Number of nested calls to VdbeExec() */
- int nVDestroy; /* Number of active OP_VDestroy operations */
- int nExtension; /* Number of loaded extensions */
- void **aExtension; /* Array of shared library handles */
- int (*xTrace)(u32,void*,void*,void*); /* Trace function */
- void *pTraceArg; /* Argument to the trace function */
- void (*xProfile)(void*,const char*,u64); /* Profiling function */
- void *pProfileArg; /* Argument to profile function */
- void *pCommitArg; /* Argument to xCommitCallback() */
- int (*xCommitCallback)(void*); /* Invoked at every commit. */
- void *pRollbackArg; /* Argument to xRollbackCallback() */
- void (*xRollbackCallback)(void*); /* Invoked at every commit. */
- void *pUpdateArg;
- void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- void *pPreUpdateArg; /* First argument to xPreUpdateCallback */
- void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */
- void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64
- );
- PreUpdate *pPreUpdate; /* Context for active pre-update callback */
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
-#ifndef SQLITE_OMIT_WAL
- int (*xWalCallback)(void *, sqlite3 *, const char *, int);
- void *pWalArg;
-#endif
- void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
- void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
- void *pCollNeededArg;
- sqlite3_value *pErr; /* Most recent error message */
- union {
- volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
- double notUsed1; /* Spacer */
- } u1;
- Lookaside lookaside; /* Lookaside malloc configuration */
-#ifndef SQLITE_OMIT_AUTHORIZATION
- sqlite3_xauth xAuth; /* Access authorization function */
- void *pAuthArg; /* 1st argument to the access auth function */
-#endif
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- int (*xProgress)(void *); /* The progress callback */
- void *pProgressArg; /* Argument to the progress callback */
- unsigned nProgressOps; /* Number of opcodes for progress callback */
-#endif
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- int nVTrans; /* Allocated size of aVTrans */
- Hash aModule; /* populated by sqlite3_create_module() */
- VtabCtx *pVtabCtx; /* Context for active vtab connect/create */
- VTable **aVTrans; /* Virtual tables with open transactions */
- VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
-#endif
- Hash aFunc; /* Hash table of connection functions */
- Hash aCollSeq; /* All collating sequences */
- BusyHandler busyHandler; /* Busy callback */
- Db aDbStatic[2]; /* Static space for the 2 default backends */
- Savepoint *pSavepoint; /* List of active savepoints */
- int busyTimeout; /* Busy handler timeout, in msec */
- int nSavepoint; /* Number of non-transaction savepoints */
- int nStatement; /* Number of nested statement-transactions */
- i64 nDeferredCons; /* Net deferred constraints this transaction. */
- i64 nDeferredImmCons; /* Net deferred immediate constraints */
- int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
- /* The following variables are all protected by the STATIC_MASTER
- ** mutex, not by sqlite3.mutex. They are used by code in notify.c.
- **
- ** When X.pUnlockConnection==Y, that means that X is waiting for Y to
- ** unlock so that it can proceed.
- **
- ** When X.pBlockingConnection==Y, that means that something that X tried
- ** tried to do recently failed with an SQLITE_LOCKED error due to locks
- ** held by Y.
- */
- sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
- sqlite3 *pUnlockConnection; /* Connection to watch for unlock */
- void *pUnlockArg; /* Argument to xUnlockNotify */
- void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
- sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
-#endif
-#ifdef SQLITE_USER_AUTHENTICATION
- sqlite3_userauth auth; /* User authentication information */
-#endif
-};
-
-/*
-** A macro to discover the encoding of a database.
-*/
-#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
-#define ENC(db) ((db)->enc)
-
-/*
-** Possible values for the sqlite3.flags.
-**
-** Value constraints (enforced via assert()):
-** SQLITE_FullFSync == PAGER_FULLFSYNC
-** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
-** SQLITE_CacheSpill == PAGER_CACHE_SPILL
-*/
-#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_MASTER */
-#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */
-#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
-#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */
-#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */
-#define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */
-#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
-#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
- /* DELETE, or UPDATE and return */
- /* the count using a callback. */
-#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
- /* result set is empty */
-#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
-#define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */
-#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */
-#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */
-#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */
-#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */
-#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */
-#define SQLITE_LoadExtFunc 0x00020000 /* Enable load_extension() SQL func */
-#define SQLITE_EnableTrigger 0x00040000 /* True to enable triggers */
-#define SQLITE_DeferFKs 0x00080000 /* Defer all FK constraints */
-#define SQLITE_QueryOnly 0x00100000 /* Disable database changes */
-#define SQLITE_CellSizeCk 0x00200000 /* Check btree cell sizes on load */
-#define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */
-#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/
-#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
-#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
-
-/* Flags used only if debugging */
-#ifdef SQLITE_DEBUG
-#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */
-#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */
-#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */
-#endif
-
-/*
-** Allowed values for sqlite3.mDbFlags
-*/
-#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */
-#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */
-#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
-#define DBFLAG_SchemaKnownOk 0x0008 /* Schema is known to be valid */
-
-/*
-** Bits of the sqlite3.dbOptFlags field that are used by the
-** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
-** selectively disable various optimizations.
-*/
-#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
-#define SQLITE_ColumnCache 0x0002 /* Column cache */
-#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
-#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
-#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
-#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
-#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
-#define SQLITE_Transitive 0x0080 /* Transitive constraints */
-#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
-#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
-#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
-#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
- /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
-#define SQLITE_PushDown 0x1000 /* The push-down optimization */
-#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
-#define SQLITE_AllOpts 0xffff /* All optimizations */
-
-/*
-** Macros for testing whether or not optimizations are enabled or disabled.
-*/
-#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0)
-#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0)
-
-/*
-** Return true if it OK to factor constant expressions into the initialization
-** code. The argument is a Parse object for the code generator.
-*/
-#define ConstFactorOk(P) ((P)->okConstFactor)
-
-/*
-** Possible values for the sqlite.magic field.
-** The numbers are obtained at random and have no special meaning, other
-** than being distinct from one another.
-*/
-#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */
-#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */
-#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */
-#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */
-#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */
-#define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */
-
-/*
-** Each SQL function is defined by an instance of the following
-** structure. For global built-in functions (ex: substr(), max(), count())
-** a pointer to this structure is held in the sqlite3BuiltinFunctions object.
-** For per-connection application-defined functions, a pointer to this
-** structure is held in the db->aHash hash table.
-**
-** The u.pHash field is used by the global built-ins. The u.pDestructor
-** field is used by per-connection app-def functions.
-*/
-struct FuncDef {
- i8 nArg; /* Number of arguments. -1 means unlimited */
- u16 funcFlags; /* Some combination of SQLITE_FUNC_* */
- void *pUserData; /* User data parameter */
- FuncDef *pNext; /* Next function with same name */
- void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */
- void (*xFinalize)(sqlite3_context*); /* Agg finalizer */
- const char *zName; /* SQL name of the function. */
- union {
- FuncDef *pHash; /* Next with a different name but the same hash */
- FuncDestructor *pDestructor; /* Reference counted destructor function */
- } u;
-};
-
-/*
-** This structure encapsulates a user-function destructor callback (as
-** configured using create_function_v2()) and a reference counter. When
-** create_function_v2() is called to create a function with a destructor,
-** a single object of this type is allocated. FuncDestructor.nRef is set to
-** the number of FuncDef objects created (either 1 or 3, depending on whether
-** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor
-** member of each of the new FuncDef objects is set to point to the allocated
-** FuncDestructor.
-**
-** Thereafter, when one of the FuncDef objects is deleted, the reference
-** count on this object is decremented. When it reaches 0, the destructor
-** is invoked and the FuncDestructor structure freed.
-*/
-struct FuncDestructor {
- int nRef;
- void (*xDestroy)(void *);
- void *pUserData;
-};
-
-/*
-** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF
-** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And
-** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There
-** are assert() statements in the code to verify this.
-**
-** Value constraints (enforced via assert()):
-** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
-** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
-** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
-** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
-** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
-*/
-#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
-#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
-#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
-#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
-#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
-#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
-#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
-#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
-#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
-#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
-#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
-#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
-#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
- ** single query - might change over time */
-#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
-#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
-
-/*
-** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
-** used to create the initializers for the FuncDef structures.
-**
-** FUNCTION(zName, nArg, iArg, bNC, xFunc)
-** Used to create a scalar function definition of a function zName
-** implemented by C function xFunc that accepts nArg arguments. The
-** value passed as iArg is cast to a (void*) and made available
-** as the user-data (sqlite3_user_data()) for the function. If
-** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
-**
-** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
-** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
-**
-** DFUNCTION(zName, nArg, iArg, bNC, xFunc)
-** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
-** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions
-** and functions like sqlite_version() that can change, but not during
-** a single query. The iArg is ignored. The user-data is always set
-** to a NULL pointer. The bNC parameter is not used.
-**
-** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
-** Used for "pure" date/time functions, this macro is like DFUNCTION
-** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
-** ignored and the user-data for these functions is set to an
-** arbitrary non-NULL pointer. The bNC parameter is not used.
-**
-** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
-** Used to create an aggregate function definition implemented by
-** the C functions xStep and xFinal. The first four parameters
-** are interpreted in the same way as the first 4 parameters to
-** FUNCTION().
-**
-** LIKEFUNC(zName, nArg, pArg, flags)
-** Used to create a scalar function definition of a function zName
-** that accepts nArg arguments and is implemented by a call to C
-** function likeFunc. Argument pArg is cast to a (void *) and made
-** available as the function user-data (sqlite3_user_data()). The
-** FuncDef.flags variable is set to the value passed as the flags
-** parameter.
-*/
-#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
-#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
-#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
- 0, 0, xFunc, 0, #zName, {0} }
-#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
- (void*)&sqlite3Config, 0, xFunc, 0, #zName, {0} }
-#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
- {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
-#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- pArg, 0, xFunc, 0, #zName, }
-#define LIKEFUNC(zName, nArg, arg, flags) \
- {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
- (void *)arg, 0, likeFunc, 0, #zName, {0} }
-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}}
-#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}}
-
-/*
-** All current savepoints are stored in a linked list starting at
-** sqlite3.pSavepoint. The first element in the list is the most recently
-** opened savepoint. Savepoints are added to the list by the vdbe
-** OP_Savepoint instruction.
-*/
-struct Savepoint {
- char *zName; /* Savepoint name (nul-terminated) */
- i64 nDeferredCons; /* Number of deferred fk violations */
- i64 nDeferredImmCons; /* Number of deferred imm fk. */
- Savepoint *pNext; /* Parent savepoint (if any) */
-};
-
-/*
-** The following are used as the second parameter to sqlite3Savepoint(),
-** and as the P1 argument to the OP_Savepoint instruction.
-*/
-#define SAVEPOINT_BEGIN 0
-#define SAVEPOINT_RELEASE 1
-#define SAVEPOINT_ROLLBACK 2
-
-
-/*
-** Each SQLite module (virtual table definition) is defined by an
-** instance of the following structure, stored in the sqlite3.aModule
-** hash table.
-*/
-struct Module {
- const sqlite3_module *pModule; /* Callback pointers */
- const char *zName; /* Name passed to create_module() */
- void *pAux; /* pAux passed to create_module() */
- void (*xDestroy)(void *); /* Module destructor function */
- Table *pEpoTab; /* Eponymous table for this module */
-};
-
-/*
-** information about each column of an SQL table is held in an instance
-** of this structure.
-*/
-struct Column {
- char *zName; /* Name of this column, \000, then the type */
- Expr *pDflt; /* Default value of this column */
- char *zColl; /* Collating sequence. If NULL, use the default */
- u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
- char affinity; /* One of the SQLITE_AFF_... values */
- u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
- u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
-};
-
-/* Allowed values for Column.colFlags:
-*/
-#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
-#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
-#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
-#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
-#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
-
-/*
-** A "Collating Sequence" is defined by an instance of the following
-** structure. Conceptually, a collating sequence consists of a name and
-** a comparison routine that defines the order of that sequence.
-**
-** If CollSeq.xCmp is NULL, it means that the
-** collating sequence is undefined. Indices built on an undefined
-** collating sequence may not be read or written.
-*/
-struct CollSeq {
- char *zName; /* Name of the collating sequence, UTF-8 encoded */
- u8 enc; /* Text encoding handled by xCmp() */
- void *pUser; /* First argument to xCmp() */
- int (*xCmp)(void*,int, const void*, int, const void*);
- void (*xDel)(void*); /* Destructor for pUser */
-};
-
-/*
-** A sort order can be either ASC or DESC.
-*/
-#define SQLITE_SO_ASC 0 /* Sort in ascending order */
-#define SQLITE_SO_DESC 1 /* Sort in ascending order */
-#define SQLITE_SO_UNDEFINED -1 /* No sort order specified */
-
-/*
-** Column affinity types.
-**
-** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
-** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
-** the speed a little by numbering the values consecutively.
-**
-** But rather than start with 0 or 1, we begin with 'A'. That way,
-** when multiple affinity types are concatenated into a string and
-** used as the P4 operand, they will be more readable.
-**
-** Note also that the numeric types are grouped together so that testing
-** for a numeric type is a single comparison. And the BLOB type is first.
-*/
-#define SQLITE_AFF_BLOB 'A'
-#define SQLITE_AFF_TEXT 'B'
-#define SQLITE_AFF_NUMERIC 'C'
-#define SQLITE_AFF_INTEGER 'D'
-#define SQLITE_AFF_REAL 'E'
-
-#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
-
-/*
-** The SQLITE_AFF_MASK values masks off the significant bits of an
-** affinity value.
-*/
-#define SQLITE_AFF_MASK 0x47
-
-/*
-** Additional bit values that can be ORed with an affinity without
-** changing the affinity.
-**
-** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
-** It causes an assert() to fire if either operand to a comparison
-** operator is NULL. It is added to certain comparison operators to
-** prove that the operands are always NOT NULL.
-*/
-#define SQLITE_KEEPNULL 0x08 /* Used by vector == or <> */
-#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */
-#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */
-#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
-#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
-
-/*
-** An object of this type is created for each virtual table present in
-** the database schema.
-**
-** If the database schema is shared, then there is one instance of this
-** structure for each database connection (sqlite3*) that uses the shared
-** schema. This is because each database connection requires its own unique
-** instance of the sqlite3_vtab* handle used to access the virtual table
-** implementation. sqlite3_vtab* handles can not be shared between
-** database connections, even when the rest of the in-memory database
-** schema is shared, as the implementation often stores the database
-** connection handle passed to it via the xConnect() or xCreate() method
-** during initialization internally. This database connection handle may
-** then be used by the virtual table implementation to access real tables
-** within the database. So that they appear as part of the callers
-** transaction, these accesses need to be made via the same database
-** connection as that used to execute SQL operations on the virtual table.
-**
-** All VTable objects that correspond to a single table in a shared
-** database schema are initially stored in a linked-list pointed to by
-** the Table.pVTable member variable of the corresponding Table object.
-** When an sqlite3_prepare() operation is required to access the virtual
-** table, it searches the list for the VTable that corresponds to the
-** database connection doing the preparing so as to use the correct
-** sqlite3_vtab* handle in the compiled query.
-**
-** When an in-memory Table object is deleted (for example when the
-** schema is being reloaded for some reason), the VTable objects are not
-** deleted and the sqlite3_vtab* handles are not xDisconnect()ed
-** immediately. Instead, they are moved from the Table.pVTable list to
-** another linked list headed by the sqlite3.pDisconnect member of the
-** corresponding sqlite3 structure. They are then deleted/xDisconnected
-** next time a statement is prepared using said sqlite3*. This is done
-** to avoid deadlock issues involving multiple sqlite3.mutex mutexes.
-** Refer to comments above function sqlite3VtabUnlockList() for an
-** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect
-** list without holding the corresponding sqlite3.mutex mutex.
-**
-** The memory for objects of this type is always allocated by
-** sqlite3DbMalloc(), using the connection handle stored in VTable.db as
-** the first argument.
-*/
-struct VTable {
- sqlite3 *db; /* Database connection associated with this table */
- Module *pMod; /* Pointer to module implementation */
- sqlite3_vtab *pVtab; /* Pointer to vtab instance */
- int nRef; /* Number of pointers to this structure */
- u8 bConstraint; /* True if constraints are supported */
- int iSavepoint; /* Depth of the SAVEPOINT stack */
- VTable *pNext; /* Next in linked list (see above) */
-};
-
-/*
-** The schema for each SQL table and view is represented in memory
-** by an instance of the following structure.
-*/
-struct Table {
- char *zName; /* Name of the table or view */
- Column *aCol; /* Information about each column */
- Index *pIndex; /* List of SQL indexes on this table. */
- Select *pSelect; /* NULL for tables. Points to definition if a view. */
- FKey *pFKey; /* Linked list of all foreign keys in this table */
- char *zColAff; /* String defining the affinity of each column */
- ExprList *pCheck; /* All CHECK constraints */
- /* ... also used as column name list in a VIEW */
- int tnum; /* Root BTree page for this table */
- u32 nTabRef; /* Number of pointers to this Table */
- u32 tabFlags; /* Mask of TF_* values */
- i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
- i16 nCol; /* Number of columns in this table */
- LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
- LogEst szTabRow; /* Estimated size of each table row in bytes */
-#ifdef SQLITE_ENABLE_COSTMULT
- LogEst costMult; /* Cost multiplier for using this table */
-#endif
- u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
-#ifndef SQLITE_OMIT_ALTERTABLE
- int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
-#endif
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- int nModuleArg; /* Number of arguments to the module */
- char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */
- VTable *pVTable; /* List of VTable objects. */
-#endif
- Trigger *pTrigger; /* List of triggers stored in pSchema */
- Schema *pSchema; /* Schema that contains this table */
- Table *pNextZombie; /* Next on the Parse.pZombieTab list */
-};
-
-/*
-** Allowed values for Table.tabFlags.
-**
-** TF_OOOHidden applies to tables or view that have hidden columns that are
-** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
-** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
-** the TF_OOOHidden attribute would apply in this case. Such tables require
-** special handling during INSERT processing.
-*/
-#define TF_Readonly 0x0001 /* Read-only system table */
-#define TF_Ephemeral 0x0002 /* An ephemeral table */
-#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
-#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
-#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
-#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */
-#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */
-#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
-#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
- ** Index.aiRowLogEst[] values */
-#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
-
-/*
-** Test to see whether or not a table is a virtual table. This is
-** done as a macro so that it will be optimized out when virtual
-** table support is omitted from the build.
-*/
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-# define IsVirtual(X) ((X)->nModuleArg)
-#else
-# define IsVirtual(X) 0
-#endif
-
-/*
-** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn()
-** only works for non-virtual tables (ordinary tables and views) and is
-** always false unless SQLITE_ENABLE_HIDDEN_COLUMNS is defined. The
-** IsHiddenColumn() macro is general purpose.
-*/
-#if defined(SQLITE_ENABLE_HIDDEN_COLUMNS)
-# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
-# define IsOrdinaryHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
-#elif !defined(SQLITE_OMIT_VIRTUALTABLE)
-# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
-# define IsOrdinaryHiddenColumn(X) 0
-#else
-# define IsHiddenColumn(X) 0
-# define IsOrdinaryHiddenColumn(X) 0
-#endif
-
-
-/* Does the table have a rowid */
-#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
-#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
-
-/*
-** Each foreign key constraint is an instance of the following structure.
-**
-** A foreign key is associated with two tables. The "from" table is
-** the table that contains the REFERENCES clause that creates the foreign
-** key. The "to" table is the table that is named in the REFERENCES clause.
-** Consider this example:
-**
-** CREATE TABLE ex1(
-** a INTEGER PRIMARY KEY,
-** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x)
-** );
-**
-** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2".
-** Equivalent names:
-**
-** from-table == child-table
-** to-table == parent-table
-**
-** Each REFERENCES clause generates an instance of the following structure
-** which is attached to the from-table. The to-table need not exist when
-** the from-table is created. The existence of the to-table is not checked.
-**
-** The list of all parents for child Table X is held at X.pFKey.
-**
-** A list of all children for a table named Z (which might not even exist)
-** is held in Schema.fkeyHash with a hash key of Z.
-*/
-struct FKey {
- Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */
- FKey *pNextFrom; /* Next FKey with the same in pFrom. Next parent of pFrom */
- char *zTo; /* Name of table that the key points to (aka: Parent) */
- FKey *pNextTo; /* Next with the same zTo. Next child of zTo. */
- FKey *pPrevTo; /* Previous with the same zTo */
- int nCol; /* Number of columns in this key */
- /* EV: R-30323-21917 */
- u8 isDeferred; /* True if constraint checking is deferred till COMMIT */
- u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */
- Trigger *apTrigger[2];/* Triggers for aAction[] actions */
- struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
- int iFrom; /* Index of column in pFrom */
- char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
- } aCol[1]; /* One entry for each of nCol columns */
-};
-
-/*
-** SQLite supports many different ways to resolve a constraint
-** error. ROLLBACK processing means that a constraint violation
-** causes the operation in process to fail and for the current transaction
-** to be rolled back. ABORT processing means the operation in process
-** fails and any prior changes from that one operation are backed out,
-** but the transaction is not rolled back. FAIL processing means that
-** the operation in progress stops and returns an error code. But prior
-** changes due to the same operation are not backed out and no rollback
-** occurs. IGNORE means that the particular row that caused the constraint
-** error is not inserted or updated. Processing continues and no error
-** is returned. REPLACE means that preexisting database rows that caused
-** a UNIQUE constraint violation are removed so that the new insert or
-** update can proceed. Processing continues and no error is reported.
-**
-** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
-** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
-** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
-** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
-** referenced table row is propagated into the row that holds the
-** foreign key.
-**
-** The following symbolic values are used to record which type
-** of action to take.
-*/
-#define OE_None 0 /* There is no constraint to check */
-#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
-#define OE_Abort 2 /* Back out changes but do no rollback transaction */
-#define OE_Fail 3 /* Stop the operation but leave all prior changes */
-#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */
-#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */
-#define OE_Update 6 /* Process as a DO UPDATE in an upsert */
-#define OE_Restrict 7 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
-#define OE_SetNull 8 /* Set the foreign key value to NULL */
-#define OE_SetDflt 9 /* Set the foreign key value to its default */
-#define OE_Cascade 10 /* Cascade the changes */
-#define OE_Default 11 /* Do whatever the default action is */
-
-
-/*
-** An instance of the following structure is passed as the first
-** argument to sqlite3VdbeKeyCompare and is used to control the
-** comparison of the two index keys.
-**
-** Note that aSortOrder[] and aColl[] have nField+1 slots. There
-** are nField slots for the columns of an index then one extra slot
-** for the rowid at the end.
-*/
-struct KeyInfo {
- u32 nRef; /* Number of references to this KeyInfo object */
- u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
- u16 nKeyField; /* Number of key columns in the index */
- u16 nAllField; /* Total columns, including key plus others */
- sqlite3 *db; /* The database connection */
- u8 *aSortOrder; /* Sort order for each column. */
- CollSeq *aColl[1]; /* Collating sequence for each term of the key */
-};
-
-/*
-** This object holds a record which has been parsed out into individual
-** fields, for the purposes of doing a comparison.
-**
-** A record is an object that contains one or more fields of data.
-** Records are used to store the content of a table row and to store
-** the key of an index. A blob encoding of a record is created by
-** the OP_MakeRecord opcode of the VDBE and is disassembled by the
-** OP_Column opcode.
-**
-** An instance of this object serves as a "key" for doing a search on
-** an index b+tree. The goal of the search is to find the entry that
-** is closed to the key described by this object. This object might hold
-** just a prefix of the key. The number of fields is given by
-** pKeyInfo->nField.
-**
-** The r1 and r2 fields are the values to return if this key is less than
-** or greater than a key in the btree, respectively. These are normally
-** -1 and +1 respectively, but might be inverted to +1 and -1 if the b-tree
-** is in DESC order.
-**
-** The key comparison functions actually return default_rc when they find
-** an equals comparison. default_rc can be -1, 0, or +1. If there are
-** multiple entries in the b-tree with the same key (when only looking
-** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to
-** cause the search to find the last match, or +1 to cause the search to
-** find the first match.
-**
-** The key comparison functions will set eqSeen to true if they ever
-** get and equal results when comparing this structure to a b-tree record.
-** When default_rc!=0, the search might end up on the record immediately
-** before the first match or immediately after the last match. The
-** eqSeen field will indicate whether or not an exact match exists in the
-** b-tree.
-*/
-struct UnpackedRecord {
- KeyInfo *pKeyInfo; /* Collation and sort-order information */
- Mem *aMem; /* Values */
- u16 nField; /* Number of entries in apMem[] */
- i8 default_rc; /* Comparison result if keys are equal */
- u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
- i8 r1; /* Value to return if (lhs < rhs) */
- i8 r2; /* Value to return if (lhs > rhs) */
- u8 eqSeen; /* True if an equality comparison has been seen */
-};
-
-
-/*
-** Each SQL index is represented in memory by an
-** instance of the following structure.
-**
-** The columns of the table that are to be indexed are described
-** by the aiColumn[] field of this structure. For example, suppose
-** we have the following table and index:
-**
-** CREATE TABLE Ex1(c1 int, c2 int, c3 text);
-** CREATE INDEX Ex2 ON Ex1(c3,c1);
-**
-** In the Table structure describing Ex1, nCol==3 because there are
-** three columns in the table. In the Index structure describing
-** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed.
-** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
-** first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
-** The second column to be indexed (c1) has an index of 0 in
-** Ex1.aCol[], hence Ex2.aiColumn[1]==0.
-**
-** The Index.onError field determines whether or not the indexed columns
-** must be unique and what to do if they are not. When Index.onError=OE_None,
-** it means this is not a unique index. Otherwise it is a unique index
-** and the value of Index.onError indicate the which conflict resolution
-** algorithm to employ whenever an attempt is made to insert a non-unique
-** element.
-**
-** While parsing a CREATE TABLE or CREATE INDEX statement in order to
-** generate VDBE code (as opposed to parsing one read from an sqlite_master
-** table as part of parsing an existing database schema), transient instances
-** of this structure may be created. In this case the Index.tnum variable is
-** used to store the address of a VDBE instruction, not a database page
-** number (it cannot - the database page is not allocated until the VDBE
-** program is executed). See convertToWithoutRowidTable() for details.
-*/
-struct Index {
- char *zName; /* Name of this index */
- i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */
- LogEst *aiRowLogEst; /* From ANALYZE: Est. rows selected by each column */
- Table *pTable; /* The SQL table being indexed */
- char *zColAff; /* String defining the affinity of each column */
- Index *pNext; /* The next index associated with the same table */
- Schema *pSchema; /* Schema containing this index */
- u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
- const char **azColl; /* Array of collation sequence names for index */
- Expr *pPartIdxWhere; /* WHERE clause for partial indices */
- ExprList *aColExpr; /* Column expressions */
- int tnum; /* DB Page containing root of this index */
- LogEst szIdxRow; /* Estimated average row size in bytes */
- u16 nKeyCol; /* Number of columns forming the key */
- u16 nColumn; /* Number of columns stored in the index */
- u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
- unsigned bUnordered:1; /* Use this index for == or IN queries only */
- unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
- unsigned isResized:1; /* True if resizeIndexObject() has been called */
- unsigned isCovering:1; /* True if this is a covering index */
- unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
- unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
- unsigned bNoQuery:1; /* Do not use this index to optimize queries */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- int nSample; /* Number of elements in aSample[] */
- int nSampleCol; /* Size of IndexSample.anEq[] and so on */
- tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
- IndexSample *aSample; /* Samples of the left-most key */
- tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */
- tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */
-#endif
-};
-
-/*
-** Allowed values for Index.idxType
-*/
-#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
-#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
-#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
-
-/* Return true if index X is a PRIMARY KEY index */
-#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
-
-/* Return true if index X is a UNIQUE index */
-#define IsUniqueIndex(X) ((X)->onError!=OE_None)
-
-/* The Index.aiColumn[] values are normally positive integer. But
-** there are some negative values that have special meaning:
-*/
-#define XN_ROWID (-1) /* Indexed column is the rowid */
-#define XN_EXPR (-2) /* Indexed column is an expression */
-
-/*
-** Each sample stored in the sqlite_stat3 table is represented in memory
-** using a structure of this type. See documentation at the top of the
-** analyze.c source file for additional information.
-*/
-struct IndexSample {
- void *p; /* Pointer to sampled record */
- int n; /* Size of record in bytes */
- tRowcnt *anEq; /* Est. number of rows where the key equals this sample */
- tRowcnt *anLt; /* Est. number of rows where key is less than this sample */
- tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */
-};
-
-/*
-** Each token coming out of the lexer is an instance of
-** this structure. Tokens are also used as part of an expression.
-**
-** Note if Token.z==0 then Token.dyn and Token.n are undefined and
-** may contain random values. Do not make any assumptions about Token.dyn
-** and Token.n when Token.z==0.
-*/
-struct Token {
- const char *z; /* Text of the token. Not NULL-terminated! */
- unsigned int n; /* Number of characters in this token */
-};
-
-/*
-** An instance of this structure contains information needed to generate
-** code for a SELECT that contains aggregate functions.
-**
-** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
-** pointer to this structure. The Expr.iColumn field is the index in
-** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
-** code for that node.
-**
-** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the
-** original Select structure that describes the SELECT statement. These
-** fields do not need to be freed when deallocating the AggInfo structure.
-*/
-struct AggInfo {
- u8 directMode; /* Direct rendering mode means take data directly
- ** from source tables rather than from accumulators */
- u8 useSortingIdx; /* In direct mode, reference the sorting index rather
- ** than the source table */
- int sortingIdx; /* Cursor number of the sorting index */
- int sortingIdxPTab; /* Cursor number of pseudo-table */
- int nSortingColumn; /* Number of columns in the sorting index */
- int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */
- ExprList *pGroupBy; /* The group by clause */
- struct AggInfo_col { /* For each column used in source tables */
- Table *pTab; /* Source table */
- int iTable; /* Cursor number of the source table */
- int iColumn; /* Column number within the source table */
- int iSorterColumn; /* Column number in the sorting index */
- int iMem; /* Memory location that acts as accumulator */
- Expr *pExpr; /* The original expression */
- } *aCol;
- int nColumn; /* Number of used entries in aCol[] */
- int nAccumulator; /* Number of columns that show through to the output.
- ** Additional columns are used only as parameters to
- ** aggregate functions */
- struct AggInfo_func { /* For each aggregate function */
- Expr *pExpr; /* Expression encoding the function */
- FuncDef *pFunc; /* The aggregate function implementation */
- int iMem; /* Memory location that acts as accumulator */
- int iDistinct; /* Ephemeral table used to enforce DISTINCT */
- } *aFunc;
- int nFunc; /* Number of entries in aFunc[] */
-};
-
-/*
-** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
-** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater
-** than 32767 we have to make it 32-bit. 16-bit is preferred because
-** it uses less memory in the Expr object, which is a big memory user
-** in systems with lots of prepared statements. And few applications
-** need more than about 10 or 20 variables. But some extreme users want
-** to have prepared statements with over 32767 variables, and for them
-** the option is available (at compile-time).
-*/
-#if SQLITE_MAX_VARIABLE_NUMBER<=32767
-typedef i16 ynVar;
-#else
-typedef int ynVar;
-#endif
-
-/*
-** Each node of an expression in the parse tree is an instance
-** of this structure.
-**
-** Expr.op is the opcode. The integer parser token codes are reused
-** as opcodes here. For example, the parser defines TK_GE to be an integer
-** code representing the ">=" operator. This same integer code is reused
-** to represent the greater-than-or-equal-to operator in the expression
-** tree.
-**
-** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
-** or TK_STRING), then Expr.token contains the text of the SQL literal. If
-** the expression is a variable (TK_VARIABLE), then Expr.token contains the
-** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
-** then Expr.token contains the name of the function.
-**
-** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
-** binary operator. Either or both may be NULL.
-**
-** Expr.x.pList is a list of arguments if the expression is an SQL function,
-** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
-** Expr.x.pSelect is used if the expression is a sub-select or an expression of
-** the form "<lhs> IN (SELECT ...)". If the EP_xIsSelect bit is set in the
-** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
-** valid.
-**
-** An expression of the form ID or ID.ID refers to a column in a table.
-** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is
-** the integer cursor number of a VDBE cursor pointing to that table and
-** Expr.iColumn is the column number for the specific column. If the
-** expression is used as a result in an aggregate SELECT, then the
-** value is also stored in the Expr.iAgg column in the aggregate so that
-** it can be accessed after all aggregates are computed.
-**
-** If the expression is an unbound variable marker (a question mark
-** character '?' in the original SQL) then the Expr.iTable holds the index
-** number for that variable.
-**
-** If the expression is a subquery then Expr.iColumn holds an integer
-** register number containing the result of the subquery. If the
-** subquery gives a constant result, then iTable is -1. If the subquery
-** gives a different answer at different times during statement processing
-** then iTable is the address of a subroutine that computes the subquery.
-**
-** If the Expr is of type OP_Column, and the table it is selecting from
-** is a disk table or the "old.*" pseudo-table, then pTab points to the
-** corresponding table definition.
-**
-** ALLOCATION NOTES:
-**
-** Expr objects can use a lot of memory space in database schema. To
-** help reduce memory requirements, sometimes an Expr object will be
-** truncated. And to reduce the number of memory allocations, sometimes
-** two or more Expr objects will be stored in a single memory allocation,
-** together with Expr.zToken strings.
-**
-** If the EP_Reduced and EP_TokenOnly flags are set when
-** an Expr object is truncated. When EP_Reduced is set, then all
-** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
-** are contained within the same memory allocation. Note, however, that
-** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately
-** allocated, regardless of whether or not EP_Reduced is set.
-*/
-struct Expr {
- u8 op; /* Operation performed by this node */
- char affinity; /* The affinity of the column or 0 if not a column */
- u32 flags; /* Various flags. EP_* See below */
- union {
- char *zToken; /* Token value. Zero terminated and dequoted */
- int iValue; /* Non-negative integer value if EP_IntValue */
- } u;
-
- /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
- ** space is allocated for the fields below this point. An attempt to
- ** access them will result in a segfault or malfunction.
- *********************************************************************/
-
- Expr *pLeft; /* Left subnode */
- Expr *pRight; /* Right subnode */
- union {
- ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
- Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
- } x;
-
- /* If the EP_Reduced flag is set in the Expr.flags mask, then no
- ** space is allocated for the fields below this point. An attempt to
- ** access them will result in a segfault or malfunction.
- *********************************************************************/
-
-#if SQLITE_MAX_EXPR_DEPTH>0
- int nHeight; /* Height of the tree headed by this node */
-#endif
- int iTable; /* TK_COLUMN: cursor number of table holding column
- ** TK_REGISTER: register number
- ** TK_TRIGGER: 1 -> new, 0 -> old
- ** EP_Unlikely: 134217728 times likelihood
- ** TK_SELECT: 1st register of result vector */
- ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
- ** TK_VARIABLE: variable number (always >= 1).
- ** TK_SELECT_COLUMN: column of the result vector */
- i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
- i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
- u8 op2; /* TK_REGISTER: original value of Expr.op
- ** TK_COLUMN: the value of p5 for OP_Column
- ** TK_AGG_FUNCTION: nesting depth */
- AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
- Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
- ** for a column of an index on an expression */
-};
-
-/*
-** The following are the meanings of bits in the Expr.flags field.
-*/
-#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
-#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
-#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
- /* 0x000008 // available for use */
-#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
-#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
-#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
-#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
-#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
-#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */
-#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
-#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
-#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
-#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
-#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
-#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */
-#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
-#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
-#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
-#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
-#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
-#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
-#define EP_Alias 0x400000 /* Is an alias for a result set column */
-#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
-
-/*
-** The EP_Propagate mask is a set of properties that automatically propagate
-** upwards into parent nodes.
-*/
-#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc)
-
-/*
-** These macros can be used to test, set, or clear bits in the
-** Expr.flags field.
-*/
-#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
-#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
-#define ExprSetProperty(E,P) (E)->flags|=(P)
-#define ExprClearProperty(E,P) (E)->flags&=~(P)
-
-/* The ExprSetVVAProperty() macro is used for Verification, Validation,
-** and Accreditation only. It works like ExprSetProperty() during VVA
-** processes but is a no-op for delivery.
-*/
-#ifdef SQLITE_DEBUG
-# define ExprSetVVAProperty(E,P) (E)->flags|=(P)
-#else
-# define ExprSetVVAProperty(E,P)
-#endif
-
-/*
-** Macros to determine the number of bytes required by a normal Expr
-** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
-** and an Expr struct with the EP_TokenOnly flag set.
-*/
-#define EXPR_FULLSIZE sizeof(Expr) /* Full size */
-#define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */
-#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */
-
-/*
-** Flags passed to the sqlite3ExprDup() function. See the header comment
-** above sqlite3ExprDup() for details.
-*/
-#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
-
-/*
-** A list of expressions. Each expression may optionally have a
-** name. An expr/name combination can be used in several ways, such
-** as the list of "expr AS ID" fields following a "SELECT" or in the
-** list of "ID = expr" items in an UPDATE. A list of expressions can
-** also be used as the argument to a function, in which case the a.zName
-** field is not used.
-**
-** By default the Expr.zSpan field holds a human-readable description of
-** the expression that is used in the generation of error messages and
-** column labels. In this case, Expr.zSpan is typically the text of a
-** column expression as it exists in a SELECT statement. However, if
-** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
-** of the result column in the form: DATABASE.TABLE.COLUMN. This later
-** form is used for name resolution with nested FROM clauses.
-*/
-struct ExprList {
- int nExpr; /* Number of expressions on the list */
- struct ExprList_item { /* For each expression in the list */
- Expr *pExpr; /* The parse tree for this expression */
- char *zName; /* Token associated with this expression */
- char *zSpan; /* Original text of the expression */
- u8 sortOrder; /* 1 for DESC or 0 for ASC */
- unsigned done :1; /* A flag to indicate when processing is finished */
- unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
- unsigned reusable :1; /* Constant expression is reusable */
- unsigned bSorterRef :1; /* Defer evaluation until after sorting */
- union {
- struct {
- u16 iOrderByCol; /* For ORDER BY, column number in result set */
- u16 iAlias; /* Index into Parse.aAlias[] for zName */
- } x;
- int iConstExprReg; /* Register in which Expr value is cached */
- } u;
- } a[1]; /* One slot for each expression in the list */
-};
-
-/*
-** An instance of this structure can hold a simple list of identifiers,
-** such as the list "a,b,c" in the following statements:
-**
-** INSERT INTO t(a,b,c) VALUES ...;
-** CREATE INDEX idx ON t(a,b,c);
-** CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...;
-**
-** The IdList.a.idx field is used when the IdList represents the list of
-** column names after a table name in an INSERT statement. In the statement
-**
-** INSERT INTO t(a,b,c) ...
-**
-** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
-*/
-struct IdList {
- struct IdList_item {
- char *zName; /* Name of the identifier */
- int idx; /* Index in some Table.aCol[] of a column named zName */
- } *a;
- int nId; /* Number of identifiers on the list */
-};
-
-/*
-** The bitmask datatype defined below is used for various optimizations.
-**
-** Changing this from a 64-bit to a 32-bit type limits the number of
-** tables in a join to 32 instead of 64. But it also reduces the size
-** of the library by 738 bytes on ix86.
-*/
-#ifdef SQLITE_BITMASK_TYPE
- typedef SQLITE_BITMASK_TYPE Bitmask;
-#else
- typedef u64 Bitmask;
-#endif
-
-/*
-** The number of bits in a Bitmask. "BMS" means "BitMask Size".
-*/
-#define BMS ((int)(sizeof(Bitmask)*8))
-
-/*
-** A bit in a Bitmask
-*/
-#define MASKBIT(n) (((Bitmask)1)<<(n))
-#define MASKBIT32(n) (((unsigned int)1)<<(n))
-#define ALLBITS ((Bitmask)-1)
-
-/*
-** The following structure describes the FROM clause of a SELECT statement.
-** Each table or subquery in the FROM clause is a separate element of
-** the SrcList.a[] array.
-**
-** With the addition of multiple database support, the following structure
-** can also be used to describe a particular table such as the table that
-** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL,
-** such a table must be a simple name: ID. But in SQLite, the table can
-** now be identified by a database name, a dot, then the table name: ID.ID.
-**
-** The jointype starts out showing the join type between the current table
-** and the next table on the list. The parser builds the list this way.
-** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
-** jointype expresses the join between the table and the previous table.
-**
-** In the colUsed field, the high-order bit (bit 63) is set if the table
-** contains more than 63 columns and the 64-th or later column is used.
-*/
-struct SrcList {
- int nSrc; /* Number of tables or subqueries in the FROM clause */
- u32 nAlloc; /* Number of entries allocated in a[] below */
- struct SrcList_item {
- Schema *pSchema; /* Schema to which this item is fixed */
- char *zDatabase; /* Name of database holding this table */
- char *zName; /* Name of the table */
- char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int addrFillSub; /* Address of subroutine to manifest a subquery */
- int regReturn; /* Register holding return address of addrFillSub */
- int regResult; /* Registers holding results of a co-routine */
- struct {
- u8 jointype; /* Type of join between this table and the previous */
- unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
- unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
- unsigned isTabFunc :1; /* True if table-valued-function syntax */
- unsigned isCorrelated :1; /* True if sub-query is correlated */
- unsigned viaCoroutine :1; /* Implemented as a co-routine */
- unsigned isRecursive :1; /* True for recursive reference in WITH */
- } fg;
- int iCursor; /* The VDBE cursor number used to access this table */
- Expr *pOn; /* The ON clause of a join */
- IdList *pUsing; /* The USING clause of a join */
- Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
- union {
- char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
- ExprList *pFuncArg; /* Arguments to table-valued-function */
- } u1;
- Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
- } a[1]; /* One entry for each identifier on the list */
-};
-
-/*
-** Permitted values of the SrcList.a.jointype field
-*/
-#define JT_INNER 0x0001 /* Any kind of inner or cross join */
-#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */
-#define JT_NATURAL 0x0004 /* True for a "natural" join */
-#define JT_LEFT 0x0008 /* Left outer join */
-#define JT_RIGHT 0x0010 /* Right outer join */
-#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */
-#define JT_ERROR 0x0040 /* unknown or unsupported join type */
-
-
-/*
-** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
-** and the WhereInfo.wctrlFlags member.
-**
-** Value constraints (enforced via assert()):
-** WHERE_USE_LIMIT == SF_FixedLimit
-*/
-#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */
-#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
-#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */
-#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
-#define WHERE_ONEPASS_MULTIROW 0x0008 /* ONEPASS is ok with multiple rows */
-#define WHERE_DUPLICATES_OK 0x0010 /* Ok to return a row more than once */
-#define WHERE_OR_SUBCLAUSE 0x0020 /* Processing a sub-WHERE as part of
- ** the OR optimization */
-#define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */
-#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
-#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
-#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
-#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
-#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
-#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
- /* 0x2000 not currently used */
-#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
- /* 0x8000 not currently used */
-
-/* Allowed return values from sqlite3WhereIsDistinct()
-*/
-#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
-#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
-#define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */
-#define WHERE_DISTINCT_UNORDERED 3 /* Duplicates are scattered */
-
-/*
-** A NameContext defines a context in which to resolve table and column
-** names. The context consists of a list of tables (the pSrcList) field and
-** a list of named expression (pEList). The named expression list may
-** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
-** to the table being operated on by INSERT, UPDATE, or DELETE. The
-** pEList corresponds to the result set of a SELECT and is NULL for
-** other statements.
-**
-** NameContexts can be nested. When resolving names, the inner-most
-** context is searched first. If no match is found, the next outer
-** context is checked. If there is still no match, the next context
-** is checked. This process continues until either a match is found
-** or all contexts are check. When a match is found, the nRef member of
-** the context containing the match is incremented.
-**
-** Each subquery gets a new NameContext. The pNext field points to the
-** NameContext in the parent query. Thus the process of scanning the
-** NameContext list corresponds to searching through successively outer
-** subqueries looking for a match.
-*/
-struct NameContext {
- Parse *pParse; /* The parser */
- SrcList *pSrcList; /* One or more tables used to resolve names */
- union {
- ExprList *pEList; /* Optional list of result-set columns */
- AggInfo *pAggInfo; /* Information about aggregates at this level */
- Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
- } uNC;
- NameContext *pNext; /* Next outer name context. NULL for outermost */
- int nRef; /* Number of names resolved by this context */
- int nErr; /* Number of errors encountered while resolving names */
- u16 ncFlags; /* Zero or more NC_* flags defined below */
-};
-
-/*
-** Allowed values for the NameContext, ncFlags field.
-**
-** Value constraints (all checked via assert()):
-** NC_HasAgg == SF_HasAgg
-** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
-**
-*/
-#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
-#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */
-#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
-#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
-#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */
-#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
-#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */
-#define NC_UEList 0x0080 /* True if uNC.pEList is used */
-#define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */
-#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */
-#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
-#define NC_Complex 0x2000 /* True if a function or subquery seen */
-
-/*
-** An instance of the following object describes a single ON CONFLICT
-** clause in an upsert.
-**
-** The pUpsertTarget field is only set if the ON CONFLICT clause includes
-** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the
-** conflict-target clause.) The pUpsertTargetWhere is the optional
-** WHERE clause used to identify partial unique indexes.
-**
-** pUpsertSet is the list of column=expr terms of the UPDATE statement.
-** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The
-** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the
-** WHERE clause is omitted.
-*/
-struct Upsert {
- ExprList *pUpsertTarget; /* Optional description of conflicting index */
- Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
- ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
- Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
- /* The fields above comprise the parse tree for the upsert clause.
- ** The fields below are used to transfer information from the INSERT
- ** processing down into the UPDATE processing while generating code.
- ** Upsert owns the memory allocated above, but not the memory below. */
- Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
- SrcList *pUpsertSrc; /* Table to be updated */
- int regData; /* First register holding array of VALUES */
- int iDataCur; /* Index of the data cursor */
- int iIdxCur; /* Index of the first index cursor */
-};
-
-/*
-** An instance of the following structure contains all information
-** needed to generate code for a single SELECT statement.
-**
-** See the header comment on the computeLimitRegisters() routine for a
-** detailed description of the meaning of the iLimit and iOffset fields.
-**
-** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
-** These addresses must be stored so that we can go back and fill in
-** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor
-** the number of columns in P2 can be computed at the same time
-** as the OP_OpenEphm instruction is coded because not
-** enough information about the compound query is known at that point.
-** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
-** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
-** sequences for the ORDER BY clause.
-*/
-struct Select {
- ExprList *pEList; /* The fields of the result */
- u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
- LogEst nSelectRow; /* Estimated number of result rows */
- u32 selFlags; /* Various SF_* values */
- int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
-#if SELECTTRACE_ENABLED
- char zSelName[12]; /* Symbolic name of this SELECT use for debugging */
-#endif
- int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
- SrcList *pSrc; /* The FROM clause */
- Expr *pWhere; /* The WHERE clause */
- ExprList *pGroupBy; /* The GROUP BY clause */
- Expr *pHaving; /* The HAVING clause */
- ExprList *pOrderBy; /* The ORDER BY clause */
- Select *pPrior; /* Prior select in a compound select statement */
- Select *pNext; /* Next select to the left in a compound */
- Expr *pLimit; /* LIMIT expression. NULL means not used. */
- With *pWith; /* WITH clause attached to this select. Or NULL. */
-};
-
-/*
-** Allowed values for Select.selFlags. The "SF" prefix stands for
-** "Select Flag".
-**
-** Value constraints (all checked via assert())
-** SF_HasAgg == NC_HasAgg
-** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
-** SF_FixedLimit == WHERE_USE_LIMIT
-*/
-#define SF_Distinct 0x00001 /* Output should be DISTINCT */
-#define SF_All 0x00002 /* Includes the ALL keyword */
-#define SF_Resolved 0x00004 /* Identifiers have been resolved */
-#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */
-#define SF_HasAgg 0x00010 /* Contains aggregate functions */
-#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */
-#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */
-#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */
-#define SF_Compound 0x00100 /* Part of a compound query */
-#define SF_Values 0x00200 /* Synthesized from VALUES clause */
-#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */
-#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */
-#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */
-#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */
-#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */
-#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
-#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
-#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
-#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
-
-/*
-** The results of a SELECT can be distributed in several ways, as defined
-** by one of the following macros. The "SRT" prefix means "SELECT Result
-** Type".
-**
-** SRT_Union Store results as a key in a temporary index
-** identified by pDest->iSDParm.
-**
-** SRT_Except Remove results from the temporary index pDest->iSDParm.
-**
-** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
-** set is not empty.
-**
-** SRT_Discard Throw the results away. This is used by SELECT
-** statements within triggers whose only purpose is
-** the side-effects of functions.
-**
-** All of the above are free to ignore their ORDER BY clause. Those that
-** follow must honor the ORDER BY clause.
-**
-** SRT_Output Generate a row of output (using the OP_ResultRow
-** opcode) for each row in the result set.
-**
-** SRT_Mem Only valid if the result is a single column.
-** Store the first column of the first result row
-** in register pDest->iSDParm then abandon the rest
-** of the query. This destination implies "LIMIT 1".
-**
-** SRT_Set The result must be a single column. Store each
-** row of result as the key in table pDest->iSDParm.
-** Apply the affinity pDest->affSdst before storing
-** results. Used to implement "IN (SELECT ...)".
-**
-** SRT_EphemTab Create an temporary table pDest->iSDParm and store
-** the result there. The cursor is left open after
-** returning. This is like SRT_Table except that
-** this destination uses OP_OpenEphemeral to create
-** the table first.
-**
-** SRT_Coroutine Generate a co-routine that returns a new row of
-** results each time it is invoked. The entry point
-** of the co-routine is stored in register pDest->iSDParm
-** and the result row is stored in pDest->nDest registers
-** starting with pDest->iSdst.
-**
-** SRT_Table Store results in temporary table pDest->iSDParm.
-** SRT_Fifo This is like SRT_EphemTab except that the table
-** is assumed to already be open. SRT_Fifo has
-** the additional property of being able to ignore
-** the ORDER BY clause.
-**
-** SRT_DistFifo Store results in a temporary table pDest->iSDParm.
-** But also use temporary table pDest->iSDParm+1 as
-** a record of all prior results and ignore any duplicate
-** rows. Name means: "Distinct Fifo".
-**
-** SRT_Queue Store results in priority queue pDest->iSDParm (really
-** an index). Append a sequence number so that all entries
-** are distinct.
-**
-** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
-** the same record has never been stored before. The
-** index at pDest->iSDParm+1 hold all prior stores.
-*/
-#define SRT_Union 1 /* Store result as keys in an index */
-#define SRT_Except 2 /* Remove result from a UNION index */
-#define SRT_Exists 3 /* Store 1 if the result is not empty */
-#define SRT_Discard 4 /* Do not save the results anywhere */
-#define SRT_Fifo 5 /* Store result as data with an automatic rowid */
-#define SRT_DistFifo 6 /* Like SRT_Fifo, but unique results only */
-#define SRT_Queue 7 /* Store result in an queue */
-#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */
-
-/* The ORDER BY clause is ignored for all of the above */
-#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)
-
-#define SRT_Output 9 /* Output each row of result */
-#define SRT_Mem 10 /* Store result in a memory cell */
-#define SRT_Set 11 /* Store results as keys in an index */
-#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
-#define SRT_Coroutine 13 /* Generate a single row of result */
-#define SRT_Table 14 /* Store result as data with an automatic rowid */
-
-/*
-** An instance of this object describes where to put of the results of
-** a SELECT statement.
-*/
-struct SelectDest {
- u8 eDest; /* How to dispose of the results. On of SRT_* above. */
- int iSDParm; /* A parameter used by the eDest disposal method */
- int iSdst; /* Base register where results are written */
- int nSdst; /* Number of registers allocated */
- char *zAffSdst; /* Affinity used when eDest==SRT_Set */
- ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */
-};
-
-/*
-** During code generation of statements that do inserts into AUTOINCREMENT
-** tables, the following information is attached to the Table.u.autoInc.p
-** pointer of each autoincrement table to record some side information that
-** the code generator needs. We have to keep per-table autoincrement
-** information in case inserts are done within triggers. Triggers do not
-** normally coordinate their activities, but we do need to coordinate the
-** loading and saving of autoincrement information.
-*/
-struct AutoincInfo {
- AutoincInfo *pNext; /* Next info block in a list of them all */
- Table *pTab; /* Table this info block refers to */
- int iDb; /* Index in sqlite3.aDb[] of database holding pTab */
- int regCtr; /* Memory register holding the rowid counter */
-};
-
-/*
-** Size of the column cache
-*/
-#ifndef SQLITE_N_COLCACHE
-# define SQLITE_N_COLCACHE 10
-#endif
-
-/*
-** At least one instance of the following structure is created for each
-** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
-** statement. All such objects are stored in the linked list headed at
-** Parse.pTriggerPrg and deleted once statement compilation has been
-** completed.
-**
-** A Vdbe sub-program that implements the body and WHEN clause of trigger
-** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of
-** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable.
-** The Parse.pTriggerPrg list never contains two entries with the same
-** values for both pTrigger and orconf.
-**
-** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
-** accessed (or set to 0 for triggers fired as a result of INSERT
-** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
-** a mask of new.* columns used by the program.
-*/
-struct TriggerPrg {
- Trigger *pTrigger; /* Trigger this program was coded from */
- TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */
- SubProgram *pProgram; /* Program implementing pTrigger/orconf */
- int orconf; /* Default ON CONFLICT policy */
- u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */
-};
-
-/*
-** The yDbMask datatype for the bitmask of all attached databases.
-*/
-#if SQLITE_MAX_ATTACHED>30
- typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8];
-# define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0)
-# define DbMaskZero(M) memset((M),0,sizeof(M))
-# define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7))
-# define DbMaskAllZero(M) sqlite3DbMaskAllZero(M)
-# define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0)
-#else
- typedef unsigned int yDbMask;
-# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0)
-# define DbMaskZero(M) (M)=0
-# define DbMaskSet(M,I) (M)|=(((yDbMask)1)<<(I))
-# define DbMaskAllZero(M) (M)==0
-# define DbMaskNonZero(M) (M)!=0
-#endif
-
-/*
-** An SQL parser context. A copy of this structure is passed through
-** the parser and down into all the parser action routine in order to
-** carry around information that is global to the entire parse.
-**
-** The structure is divided into two parts. When the parser and code
-** generate call themselves recursively, the first part of the structure
-** is constant but the second part is reset at the beginning and end of
-** each recursion.
-**
-** The nTableLock and aTableLock variables are only used if the shared-cache
-** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are
-** used to store the set of table-locks required by the statement being
-** compiled. Function sqlite3TableLock() is used to add entries to the
-** list.
-*/
-struct Parse {
- sqlite3 *db; /* The main database structure */
- char *zErrMsg; /* An error message */
- Vdbe *pVdbe; /* An engine for executing database bytecode */
- int rc; /* Return code from execution */
- u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
- u8 checkSchema; /* Causes schema cookie check after an error */
- u8 nested; /* Number of nested calls to the parser/code generator */
- u8 nTempReg; /* Number of temporary registers in aTempReg[] */
- u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
- u8 mayAbort; /* True if statement may throw an ABORT exception */
- u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
- u8 okConstFactor; /* OK to factor out constants */
- u8 disableLookaside; /* Number of times lookaside has been disabled */
- u8 nColCache; /* Number of entries in aColCache[] */
- int nRangeReg; /* Size of the temporary register block */
- int iRangeReg; /* First register in temporary register block */
- int nErr; /* Number of errors seen */
- int nTab; /* Number of previously allocated VDBE cursors */
- int nMem; /* Number of memory cells used so far */
- int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
- int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
- int iSelfTab; /* Table associated with an index on expr, or negative
- ** of the base register during check-constraint eval */
- int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
- int iCacheCnt; /* Counter used to generate aColCache[].lru values */
- int nLabel; /* Number of labels used */
- int *aLabel; /* Space to hold the labels */
- ExprList *pConstExpr;/* Constant expressions */
- Token constraintName;/* Name of the constraint currently being parsed */
- yDbMask writeMask; /* Start a write transaction on these databases */
- yDbMask cookieMask; /* Bitmask of schema verified databases */
- int regRowid; /* Register holding rowid of CREATE TABLE entry */
- int regRoot; /* Register holding root page number for new objects */
- int nMaxArg; /* Max args passed to user function by sub-program */
-#if SELECTTRACE_ENABLED
- int nSelect; /* Number of SELECT statements seen */
-#endif
-#ifndef SQLITE_OMIT_SHARED_CACHE
- int nTableLock; /* Number of locks in aTableLock */
- TableLock *aTableLock; /* Required table locks for shared-cache mode */
-#endif
- AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
- Parse *pToplevel; /* Parse structure for main program (or NULL) */
- Table *pTriggerTab; /* Table triggers are being coded for */
- int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
- u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
- u32 oldmask; /* Mask of old.* columns referenced */
- u32 newmask; /* Mask of new.* columns referenced */
- u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
- u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
- u8 disableTriggers; /* True to disable triggers */
-
- /**************************************************************************
- ** Fields above must be initialized to zero. The fields that follow,
- ** down to the beginning of the recursive section, do not need to be
- ** initialized as they will be set before being used. The boundary is
- ** determined by offsetof(Parse,aColCache).
- **************************************************************************/
-
- struct yColCache {
- int iTable; /* Table cursor number */
- i16 iColumn; /* Table column number */
- u8 tempReg; /* iReg is a temp register that needs to be freed */
- int iLevel; /* Nesting level */
- int iReg; /* Reg with value of this column. 0 means none. */
- int lru; /* Least recently used entry has the smallest value */
- } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
- int aTempReg[8]; /* Holding area for temporary registers */
- Token sNameToken; /* Token with unqualified schema object name */
-
- /************************************************************************
- ** Above is constant between recursions. Below is reset before and after
- ** each recursion. The boundary between these two regions is determined
- ** using offsetof(Parse,sLastToken) so the sLastToken field must be the
- ** first field in the recursive region.
- ************************************************************************/
-
- Token sLastToken; /* The last token parsed */
- ynVar nVar; /* Number of '?' variables seen in the SQL so far */
- u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
- u8 explain; /* True if the EXPLAIN flag is found on the query */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
- int nVtabLock; /* Number of virtual tables to lock */
-#endif
- int nHeight; /* Expression tree height of current sub-select */
-#ifndef SQLITE_OMIT_EXPLAIN
- int addrExplain; /* Address of current OP_Explain opcode */
-#endif
- VList *pVList; /* Mapping between variable names and numbers */
- Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
- const char *zTail; /* All SQL text past the last semicolon parsed */
- Table *pNewTable; /* A table being constructed by CREATE TABLE */
- Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
- const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- Token sArg; /* Complete text of a module argument */
- Table **apVtabLock; /* Pointer to virtual tables needing locking */
-#endif
- Table *pZombieTab; /* List of Table objects to delete after code gen */
- TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
- With *pWith; /* Current WITH clause, or NULL */
- With *pWithToFree; /* Free this WITH object at the end of the parse */
-};
-
-/*
-** Sizes and pointers of various parts of the Parse object.
-*/
-#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/
-#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
-#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
-#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
-
-/*
-** Return true if currently inside an sqlite3_declare_vtab() call.
-*/
-#ifdef SQLITE_OMIT_VIRTUALTABLE
- #define IN_DECLARE_VTAB 0
-#else
- #define IN_DECLARE_VTAB (pParse->declareVtab)
-#endif
-
-/*
-** An instance of the following structure can be declared on a stack and used
-** to save the Parse.zAuthContext value so that it can be restored later.
-*/
-struct AuthContext {
- const char *zAuthContext; /* Put saved Parse.zAuthContext here */
- Parse *pParse; /* The Parse structure */
-};
-
-/*
-** Bitfield flags for P5 value in various opcodes.
-**
-** Value constraints (enforced via assert()):
-** OPFLAG_LENGTHARG == SQLITE_FUNC_LENGTH
-** OPFLAG_TYPEOFARG == SQLITE_FUNC_TYPEOF
-** OPFLAG_BULKCSR == BTREE_BULKLOAD
-** OPFLAG_SEEKEQ == BTREE_SEEK_EQ
-** OPFLAG_FORDELETE == BTREE_FORDELETE
-** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION
-** OPFLAG_AUXDELETE == BTREE_AUXDELETE
-*/
-#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
- /* Also used in P2 (not P5) of OP_Delete */
-#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
-#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
-#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
-#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
-#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
-#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
-#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
-#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
-#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
-#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
-#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
-#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
-#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
-#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
-#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
-#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
-
-/*
- * Each trigger present in the database schema is stored as an instance of
- * struct Trigger.
- *
- * Pointers to instances of struct Trigger are stored in two ways.
- * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
- * database). This allows Trigger structures to be retrieved by name.
- * 2. All triggers associated with a single table form a linked list, using the
- * pNext member of struct Trigger. A pointer to the first element of the
- * linked list is stored as the "pTrigger" member of the associated
- * struct Table.
- *
- * The "step_list" member points to the first element of a linked list
- * containing the SQL statements specified as the trigger program.
- */
-struct Trigger {
- char *zName; /* The name of the trigger */
- char *table; /* The table or view to which the trigger applies */
- u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
- u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
- Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
- IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
- the <column-list> is stored here */
- Schema *pSchema; /* Schema containing the trigger */
- Schema *pTabSchema; /* Schema containing the table */
- TriggerStep *step_list; /* Link list of trigger program steps */
- Trigger *pNext; /* Next trigger associated with the table */
-};
-
-/*
-** A trigger is either a BEFORE or an AFTER trigger. The following constants
-** determine which.
-**
-** If there are multiple triggers, you might of some BEFORE and some AFTER.
-** In that cases, the constants below can be ORed together.
-*/
-#define TRIGGER_BEFORE 1
-#define TRIGGER_AFTER 2
-
-/*
- * An instance of struct TriggerStep is used to store a single SQL statement
- * that is a part of a trigger-program.
- *
- * Instances of struct TriggerStep are stored in a singly linked list (linked
- * using the "pNext" member) referenced by the "step_list" member of the
- * associated struct Trigger instance. The first element of the linked list is
- * the first step of the trigger-program.
- *
- * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
- * "SELECT" statement. The meanings of the other members is determined by the
- * value of "op" as follows:
- *
- * (op == TK_INSERT)
- * orconf -> stores the ON CONFLICT algorithm
- * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
- * this stores a pointer to the SELECT statement. Otherwise NULL.
- * zTarget -> Dequoted name of the table to insert into.
- * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
- * this stores values to be inserted. Otherwise NULL.
- * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
- * statement, then this stores the column-names to be
- * inserted into.
- *
- * (op == TK_DELETE)
- * zTarget -> Dequoted name of the table to delete from.
- * pWhere -> The WHERE clause of the DELETE statement if one is specified.
- * Otherwise NULL.
- *
- * (op == TK_UPDATE)
- * zTarget -> Dequoted name of the table to update.
- * pWhere -> The WHERE clause of the UPDATE statement if one is specified.
- * Otherwise NULL.
- * pExprList -> A list of the columns to update and the expressions to update
- * them to. See sqlite3Update() documentation of "pChanges"
- * argument.
- *
- */
-struct TriggerStep {
- u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
- u8 orconf; /* OE_Rollback etc. */
- Trigger *pTrig; /* The trigger that this step is a part of */
- Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
- char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
- Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
- ExprList *pExprList; /* SET clause for UPDATE */
- IdList *pIdList; /* Column names for INSERT */
- Upsert *pUpsert; /* Upsert clauses on an INSERT */
- char *zSpan; /* Original SQL text of this command */
- TriggerStep *pNext; /* Next in the link-list */
- TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
-};
-
-/*
-** The following structure contains information used by the sqliteFix...
-** routines as they walk the parse tree to make database references
-** explicit.
-*/
-typedef struct DbFixer DbFixer;
-struct DbFixer {
- Parse *pParse; /* The parsing context. Error messages written here */
- Schema *pSchema; /* Fix items to this schema */
- int bVarOnly; /* Check for variable references only */
- const char *zDb; /* Make sure all objects are contained in this database */
- const char *zType; /* Type of the container - used for error messages */
- const Token *pName; /* Name of the container - used for error messages */
-};
-
-/*
-** An objected used to accumulate the text of a string where we
-** do not necessarily know how big the string will be in the end.
-*/
-struct sqlite3_str {
- sqlite3 *db; /* Optional database for lookaside. Can be NULL */
- char *zText; /* The string collected so far */
- u32 nAlloc; /* Amount of space allocated in zText */
- u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
- u32 nChar; /* Length of the string so far */
- u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */
- u8 printfFlags; /* SQLITE_PRINTF flags below */
-};
-#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
-#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
-#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
-
-#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
-
-
-/*
-** A pointer to this structure is used to communicate information
-** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
-*/
-typedef struct {
- sqlite3 *db; /* The database being initialized */
- char **pzErrMsg; /* Error message stored here */
- int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */
- int rc; /* Result code stored here */
-} InitData;
-
-/*
-** Structure containing global configuration data for the SQLite library.
-**
-** This structure also contains some state information.
-*/
-struct Sqlite3Config {
- int bMemstat; /* True to enable memory status */
- int bCoreMutex; /* True to enable core mutexing */
- int bFullMutex; /* True to enable full mutexing */
- int bOpenUri; /* True to interpret filenames as URIs */
- int bUseCis; /* Use covering indices for full-scans */
- int bSmallMalloc; /* Avoid large memory allocations if true */
- int mxStrlen; /* Maximum string length */
- int neverCorrupt; /* Database is always well-formed */
- int szLookaside; /* Default lookaside buffer size */
- int nLookaside; /* Default lookaside buffer count */
- int nStmtSpill; /* Stmt-journal spill-to-disk threshold */
- sqlite3_mem_methods m; /* Low-level memory allocation interface */
- sqlite3_mutex_methods mutex; /* Low-level mutex interface */
- sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */
- void *pHeap; /* Heap storage space */
- int nHeap; /* Size of pHeap[] */
- int mnReq, mxReq; /* Min and max heap requests sizes */
- sqlite3_int64 szMmap; /* mmap() space per open file */
- sqlite3_int64 mxMmap; /* Maximum value for szMmap */
- void *pPage; /* Page cache memory */
- int szPage; /* Size of each page in pPage[] */
- int nPage; /* Number of pages in pPage[] */
- int mxParserStack; /* maximum depth of the parser stack */
- int sharedCacheEnabled; /* true if shared-cache mode enabled */
- u32 szPma; /* Maximum Sorter PMA size */
- /* The above might be initialized to non-zero. The following need to always
- ** initially be zero, however. */
- int isInit; /* True after initialization has finished */
- int inProgress; /* True while initialization in progress */
- int isMutexInit; /* True after mutexes are initialized */
- int isMallocInit; /* True after malloc is initialized */
- int isPCacheInit; /* True after malloc is initialized */
- int nRefInitMutex; /* Number of users of pInitMutex */
- sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
- void (*xLog)(void*,int,const char*); /* Function for logging */
- void *pLogArg; /* First argument to xLog() */
-#ifdef SQLITE_ENABLE_SQLLOG
- void(*xSqllog)(void*,sqlite3*,const char*, int);
- void *pSqllogArg;
-#endif
-#ifdef SQLITE_VDBE_COVERAGE
- /* The following callback (if not NULL) is invoked on every VDBE branch
- ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
- */
- void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
- void *pVdbeBranchArg; /* 1st argument */
-#endif
-#ifndef SQLITE_UNTESTABLE
- int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
-#endif
- int bLocaltimeFault; /* True to fail localtime() calls */
- int iOnceResetThreshold; /* When to reset OP_Once counters */
- u32 szSorterRef; /* Min size in bytes to use sorter-refs */
-};
-
-/*
-** This macro is used inside of assert() statements to indicate that
-** the assert is only valid on a well-formed database. Instead of:
-**
-** assert( X );
-**
-** One writes:
-**
-** assert( X || CORRUPT_DB );
-**
-** CORRUPT_DB is true during normal operation. CORRUPT_DB does not indicate
-** that the database is definitely corrupt, only that it might be corrupt.
-** For most test cases, CORRUPT_DB is set to false using a special
-** sqlite3_test_control(). This enables assert() statements to prove
-** things that are always true for well-formed databases.
-*/
-#define CORRUPT_DB (sqlite3Config.neverCorrupt==0)
-
-/*
-** Context pointer passed down through the tree-walk.
-*/
-struct Walker {
- Parse *pParse; /* Parser context. */
- int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
- int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
- void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
- int walkerDepth; /* Number of subqueries */
- u8 eCode; /* A small processing code */
- union { /* Extra data for callback */
- NameContext *pNC; /* Naming context */
- int n; /* A counter */
- int iCur; /* A cursor number */
- SrcList *pSrcList; /* FROM clause */
- struct SrcCount *pSrcCount; /* Counting column references */
- struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
- int *aiCol; /* array of column indexes */
- struct IdxCover *pIdxCover; /* Check for index coverage */
- struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */
- ExprList *pGroupBy; /* GROUP BY clause */
- Select *pSelect; /* HAVING to WHERE clause ctx */
- } u;
-};
-
-/* Forward declarations */
-int sqlite3WalkExpr(Walker*, Expr*);
-int sqlite3WalkExprList(Walker*, ExprList*);
-int sqlite3WalkSelect(Walker*, Select*);
-int sqlite3WalkSelectExpr(Walker*, Select*);
-int sqlite3WalkSelectFrom(Walker*, Select*);
-int sqlite3ExprWalkNoop(Walker*, Expr*);
-int sqlite3SelectWalkNoop(Walker*, Select*);
-int sqlite3SelectWalkFail(Walker*, Select*);
-#ifdef SQLITE_DEBUG
-void sqlite3SelectWalkAssert2(Walker*, Select*);
-#endif
-
-/*
-** Return code from the parse-tree walking primitives and their
-** callbacks.
-*/
-#define WRC_Continue 0 /* Continue down into children */
-#define WRC_Prune 1 /* Omit children but continue walking siblings */
-#define WRC_Abort 2 /* Abandon the tree walk */
-
-/*
-** An instance of this structure represents a set of one or more CTEs
-** (common table expressions) created by a single WITH clause.
-*/
-struct With {
- int nCte; /* Number of CTEs in the WITH clause */
- With *pOuter; /* Containing WITH clause, or NULL */
- struct Cte { /* For each CTE in the WITH clause.... */
- char *zName; /* Name of this CTE */
- ExprList *pCols; /* List of explicit column names, or NULL */
- Select *pSelect; /* The definition of this CTE */
- const char *zCteErr; /* Error message for circular references */
- } a[1];
-};
-
-#ifdef SQLITE_DEBUG
-/*
-** An instance of the TreeView object is used for printing the content of
-** data structures on sqlite3DebugPrintf() using a tree-like view.
-*/
-struct TreeView {
- int iLevel; /* Which level of the tree we are on */
- u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */
-};
-#endif /* SQLITE_DEBUG */
-
-/*
-** Assuming zIn points to the first byte of a UTF-8 character,
-** advance zIn to point to the first byte of the next UTF-8 character.
-*/
-#define SQLITE_SKIP_UTF8(zIn) { \
- if( (*(zIn++))>=0xc0 ){ \
- while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
- } \
-}
-
-/*
-** The SQLITE_*_BKPT macros are substitutes for the error codes with
-** the same name but without the _BKPT suffix. These macros invoke
-** routines that report the line-number on which the error originated
-** using sqlite3_log(). The routines also provide a convenient place
-** to set a debugger breakpoint.
-*/
-int sqlite3ReportError(int iErr, int lineno, const char *zType);
-int sqlite3CorruptError(int);
-int sqlite3MisuseError(int);
-int sqlite3CantopenError(int);
-#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
-#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)
-#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
-#ifdef SQLITE_DEBUG
- int sqlite3NomemError(int);
- int sqlite3IoerrnomemError(int);
- int sqlite3CorruptPgnoError(int,Pgno);
-# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__)
-# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__)
-# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
-#else
-# define SQLITE_NOMEM_BKPT SQLITE_NOMEM
-# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM
-# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
-#endif
-
-/*
-** FTS3 and FTS4 both require virtual table support
-*/
-#if defined(SQLITE_OMIT_VIRTUALTABLE)
-# undef SQLITE_ENABLE_FTS3
-# undef SQLITE_ENABLE_FTS4
-#endif
-
-/*
-** FTS4 is really an extension for FTS3. It is enabled using the
-** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also call
-** the SQLITE_ENABLE_FTS4 macro to serve as an alias for SQLITE_ENABLE_FTS3.
-*/
-#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
-# define SQLITE_ENABLE_FTS3 1
-#endif
-
-/*
-** The ctype.h header is needed for non-ASCII systems. It is also
-** needed by FTS3 when FTS3 is included in the amalgamation.
-*/
-#if !defined(SQLITE_ASCII) || \
- (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
-# include <ctype.h>
-#endif
-
-/*
-** The following macros mimic the standard library functions toupper(),
-** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
-** sqlite versions only work for ASCII characters, regardless of locale.
-*/
-#ifdef SQLITE_ASCII
-# define sqlite3Toupper(x) ((x)&~(sqlite3CtypeMap[(unsigned char)(x)]&0x20))
-# define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01)
-# define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06)
-# define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02)
-# define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04)
-# define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
-# define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
-# define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80)
-#else
-# define sqlite3Toupper(x) toupper((unsigned char)(x))
-# define sqlite3Isspace(x) isspace((unsigned char)(x))
-# define sqlite3Isalnum(x) isalnum((unsigned char)(x))
-# define sqlite3Isalpha(x) isalpha((unsigned char)(x))
-# define sqlite3Isdigit(x) isdigit((unsigned char)(x))
-# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
-# define sqlite3Tolower(x) tolower((unsigned char)(x))
-# define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`')
-#endif
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-int sqlite3IsIdChar(u8);
-#endif
-
-/*
-** Internal function prototypes
-*/
-int sqlite3StrICmp(const char*,const char*);
-int sqlite3Strlen30(const char*);
-char *sqlite3ColumnType(Column*,char*);
-#define sqlite3StrNICmp sqlite3_strnicmp
-
-int sqlite3MallocInit(void);
-void sqlite3MallocEnd(void);
-void *sqlite3Malloc(u64);
-void *sqlite3MallocZero(u64);
-void *sqlite3DbMallocZero(sqlite3*, u64);
-void *sqlite3DbMallocRaw(sqlite3*, u64);
-void *sqlite3DbMallocRawNN(sqlite3*, u64);
-char *sqlite3DbStrDup(sqlite3*,const char*);
-char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
-char *sqlite3DbSpanDup(sqlite3*,const char*,const char*);
-void *sqlite3Realloc(void*, u64);
-void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
-void *sqlite3DbRealloc(sqlite3 *, void *, u64);
-void sqlite3DbFree(sqlite3*, void*);
-void sqlite3DbFreeNN(sqlite3*, void*);
-int sqlite3MallocSize(void*);
-int sqlite3DbMallocSize(sqlite3*, void*);
-void *sqlite3PageMalloc(int);
-void sqlite3PageFree(void*);
-void sqlite3MemSetDefault(void);
-#ifndef SQLITE_UNTESTABLE
-void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
-#endif
-int sqlite3HeapNearlyFull(void);
-
-/*
-** On systems with ample stack space and that support alloca(), make
-** use of alloca() to obtain space for large automatic objects. By default,
-** obtain space from malloc().
-**
-** The alloca() routine never returns NULL. This will cause code paths
-** that deal with sqlite3StackAlloc() failures to be unreachable.
-*/
-#ifdef SQLITE_USE_ALLOCA
-# define sqlite3StackAllocRaw(D,N) alloca(N)
-# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N)
-# define sqlite3StackFree(D,P)
-#else
-# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N)
-# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N)
-# define sqlite3StackFree(D,P) sqlite3DbFree(D,P)
-#endif
-
-/* Do not allow both MEMSYS5 and MEMSYS3 to be defined together. If they
-** are, disable MEMSYS3
-*/
-#ifdef SQLITE_ENABLE_MEMSYS5
-const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
-#undef SQLITE_ENABLE_MEMSYS3
-#endif
-#ifdef SQLITE_ENABLE_MEMSYS3
-const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
-#endif
-
-
-#ifndef SQLITE_MUTEX_OMIT
- sqlite3_mutex_methods const *sqlite3DefaultMutex(void);
- sqlite3_mutex_methods const *sqlite3NoopMutex(void);
- sqlite3_mutex *sqlite3MutexAlloc(int);
- int sqlite3MutexInit(void);
- int sqlite3MutexEnd(void);
-#endif
-#if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP)
- void sqlite3MemoryBarrier(void);
-#else
-# define sqlite3MemoryBarrier()
-#endif
-
-sqlite3_int64 sqlite3StatusValue(int);
-void sqlite3StatusUp(int, int);
-void sqlite3StatusDown(int, int);
-void sqlite3StatusHighwater(int, int);
-int sqlite3LookasideUsed(sqlite3*,int*);
-
-/* Access to mutexes used by sqlite3_status() */
-sqlite3_mutex *sqlite3Pcache1Mutex(void);
-sqlite3_mutex *sqlite3MallocMutex(void);
-
-#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
-void sqlite3MutexWarnOnContention(sqlite3_mutex*);
-#else
-# define sqlite3MutexWarnOnContention(x)
-#endif
-
-#ifndef SQLITE_OMIT_FLOATING_POINT
- int sqlite3IsNaN(double);
-#else
-# define sqlite3IsNaN(X) 0
-#endif
-
-/*
-** An instance of the following structure holds information about SQL
-** functions arguments that are the parameters to the printf() function.
-*/
-struct PrintfArguments {
- int nArg; /* Total number of arguments */
- int nUsed; /* Number of arguments used so far */
- sqlite3_value **apArg; /* The argument values */
-};
-
-char *sqlite3MPrintf(sqlite3*,const char*, ...);
-char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
-#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
- void sqlite3DebugPrintf(const char*, ...);
-#endif
-#if defined(SQLITE_TEST)
- void *sqlite3TestTextToPtr(const char*);
-#endif
-
-#if defined(SQLITE_DEBUG)
- void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
- void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
- void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
- void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
- void sqlite3TreeViewWith(TreeView*, const With*, u8);
-#endif
-
-
-void sqlite3SetString(char **, sqlite3*, const char*);
-void sqlite3ErrorMsg(Parse*, const char*, ...);
-void sqlite3Dequote(char*);
-void sqlite3TokenInit(Token*,char*);
-int sqlite3KeywordCode(const unsigned char*, int);
-int sqlite3RunParser(Parse*, const char*, char **);
-void sqlite3FinishCoding(Parse*);
-int sqlite3GetTempReg(Parse*);
-void sqlite3ReleaseTempReg(Parse*,int);
-int sqlite3GetTempRange(Parse*,int);
-void sqlite3ReleaseTempRange(Parse*,int,int);
-void sqlite3ClearTempRegCache(Parse*);
-#ifdef SQLITE_DEBUG
-int sqlite3NoTempsInRange(Parse*,int,int);
-#endif
-Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
-Expr *sqlite3Expr(sqlite3*,int,const char*);
-void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
-Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
-void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
-Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
-Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
-void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
-void sqlite3ExprDelete(sqlite3*, Expr*);
-ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
-ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
-void sqlite3ExprListSetSortOrder(ExprList*,int);
-void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
-void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
-void sqlite3ExprListDelete(sqlite3*, ExprList*);
-u32 sqlite3ExprListFlags(const ExprList*);
-int sqlite3Init(sqlite3*, char**);
-int sqlite3InitCallback(void*, int, char**, char**);
-void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
-#endif
-void sqlite3ResetAllSchemasOfConnection(sqlite3*);
-void sqlite3ResetOneSchema(sqlite3*,int);
-void sqlite3CollapseDatabaseArray(sqlite3*);
-void sqlite3CommitInternalChanges(sqlite3*);
-void sqlite3DeleteColumnNames(sqlite3*,Table*);
-int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
-void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
-Table *sqlite3ResultSetOfSelect(Parse*,Select*);
-void sqlite3OpenMasterTable(Parse *, int);
-Index *sqlite3PrimaryKeyIndex(Table*);
-i16 sqlite3ColumnOfIndex(Index*, i16);
-void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
-#if SQLITE_ENABLE_HIDDEN_COLUMNS
- void sqlite3ColumnPropertiesFromName(Table*, Column*);
-#else
-# define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
-#endif
-void sqlite3AddColumn(Parse*,Token*,Token*);
-void sqlite3AddNotNull(Parse*, int);
-void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
-void sqlite3AddCheckConstraint(Parse*, Expr*);
-void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
-void sqlite3AddCollateType(Parse*, Token*);
-void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
-int sqlite3ParseUri(const char*,const char*,unsigned int*,
- sqlite3_vfs**,char**,char **);
-Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
-
-#ifdef SQLITE_UNTESTABLE
-# define sqlite3FaultSim(X) SQLITE_OK
-#else
- int sqlite3FaultSim(int);
-#endif
-
-Bitvec *sqlite3BitvecCreate(u32);
-int sqlite3BitvecTest(Bitvec*, u32);
-int sqlite3BitvecTestNotNull(Bitvec*, u32);
-int sqlite3BitvecSet(Bitvec*, u32);
-void sqlite3BitvecClear(Bitvec*, u32, void*);
-void sqlite3BitvecDestroy(Bitvec*);
-u32 sqlite3BitvecSize(Bitvec*);
-#ifndef SQLITE_UNTESTABLE
-int sqlite3BitvecBuiltinTest(int,int*);
-#endif
-
-RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
-void sqlite3RowSetClear(RowSet*);
-void sqlite3RowSetInsert(RowSet*, i64);
-int sqlite3RowSetTest(RowSet*, int iBatch, i64);
-int sqlite3RowSetNext(RowSet*, i64*);
-
-void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
-
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
- int sqlite3ViewGetColumnNames(Parse*,Table*);
-#else
-# define sqlite3ViewGetColumnNames(A,B) 0
-#endif
-
-#if SQLITE_MAX_ATTACHED>30
- int sqlite3DbMaskAllZero(yDbMask);
-#endif
-void sqlite3DropTable(Parse*, SrcList*, int, int);
-void sqlite3CodeDropTable(Parse*, Table*, int, int);
-void sqlite3DeleteTable(sqlite3*, Table*);
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- void sqlite3AutoincrementBegin(Parse *pParse);
- void sqlite3AutoincrementEnd(Parse *pParse);
-#else
-# define sqlite3AutoincrementBegin(X)
-# define sqlite3AutoincrementEnd(X)
-#endif
-void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
-void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
-IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
-int sqlite3IdListIndex(IdList*,const char*);
-SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
-SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
-SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
- Token*, Select*, Expr*, IdList*);
-void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
-void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
-int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
-void sqlite3SrcListShiftJoinType(SrcList*);
-void sqlite3SrcListAssignCursors(Parse*, SrcList*);
-void sqlite3IdListDelete(sqlite3*, IdList*);
-void sqlite3SrcListDelete(sqlite3*, SrcList*);
-Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
-void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
- Expr*, int, int, u8);
-void sqlite3DropIndex(Parse*, SrcList*, int);
-int sqlite3Select(Parse*, Select*, SelectDest*);
-Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
- Expr*,ExprList*,u32,Expr*);
-void sqlite3SelectDelete(sqlite3*, Select*);
-Table *sqlite3SrcListLookup(Parse*, SrcList*);
-int sqlite3IsReadOnly(Parse*, Table*, int);
-void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
-#endif
-void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
-void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
- Upsert*);
-WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
-void sqlite3WhereEnd(WhereInfo*);
-LogEst sqlite3WhereOutputRowCount(WhereInfo*);
-int sqlite3WhereIsDistinct(WhereInfo*);
-int sqlite3WhereIsOrdered(WhereInfo*);
-int sqlite3WhereOrderedInnerLoop(WhereInfo*);
-int sqlite3WhereIsSorted(WhereInfo*);
-int sqlite3WhereContinueLabel(WhereInfo*);
-int sqlite3WhereBreakLabel(WhereInfo*);
-int sqlite3WhereOkOnePass(WhereInfo*, int*);
-#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */
-#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
-#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
-void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
-int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
-void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int);
-void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
-void sqlite3ExprCodeMove(Parse*, int, int, int);
-void sqlite3ExprCacheStore(Parse*, int, int, int);
-void sqlite3ExprCachePush(Parse*);
-void sqlite3ExprCachePop(Parse*);
-void sqlite3ExprCacheRemove(Parse*, int, int);
-void sqlite3ExprCacheClear(Parse*);
-void sqlite3ExprCacheAffinityChange(Parse*, int, int);
-void sqlite3ExprCode(Parse*, Expr*, int);
-void sqlite3ExprCodeCopy(Parse*, Expr*, int);
-void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
-int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
-int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
-int sqlite3ExprCodeTarget(Parse*, Expr*, int);
-void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
-int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
-#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
-#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
-#define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */
-#define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */
-void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
-void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
-void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
-Table *sqlite3FindTable(sqlite3*,const char*, const char*);
-#define LOCATE_VIEW 0x01
-#define LOCATE_NOERR 0x02
-Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
-Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
-Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
-void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
-void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
-void sqlite3Vacuum(Parse*,Token*);
-int sqlite3RunVacuum(char**, sqlite3*, int);
-char *sqlite3NameFromToken(sqlite3*, Token*);
-int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
-int sqlite3ExprCompareSkip(Expr*, Expr*, int);
-int sqlite3ExprListCompare(ExprList*, ExprList*, int);
-int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
-int sqlite3ExprImpliesNonNullRow(Expr*,int);
-void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
-void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
-int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
-int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
-Vdbe *sqlite3GetVdbe(Parse*);
-#ifndef SQLITE_UNTESTABLE
-void sqlite3PrngSaveState(void);
-void sqlite3PrngRestoreState(void);
-#endif
-void sqlite3RollbackAll(sqlite3*,int);
-void sqlite3CodeVerifySchema(Parse*, int);
-void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
-void sqlite3BeginTransaction(Parse*, int);
-void sqlite3EndTransaction(Parse*,int);
-void sqlite3Savepoint(Parse*, int, Token*);
-void sqlite3CloseSavepoints(sqlite3 *);
-void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
-int sqlite3ExprIdToTrueFalse(Expr*);
-int sqlite3ExprTruthValue(const Expr*);
-int sqlite3ExprIsConstant(Expr*);
-int sqlite3ExprIsConstantNotJoin(Expr*);
-int sqlite3ExprIsConstantOrFunction(Expr*, u8);
-int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
-int sqlite3ExprIsTableConstant(Expr*,int);
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
-int sqlite3ExprContainsSubquery(Expr*);
-#endif
-int sqlite3ExprIsInteger(Expr*, int*);
-int sqlite3ExprCanBeNull(const Expr*);
-int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
-int sqlite3IsRowid(const char*);
-void sqlite3GenerateRowDelete(
- Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
-void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
-int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
-void sqlite3ResolvePartIdxLabel(Parse*,int);
-void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
- u8,u8,int,int*,int*,Upsert*);
-#ifdef SQLITE_ENABLE_NULL_TRIM
- void sqlite3SetMakeRecordP5(Vdbe*,Table*);
-#else
-# define sqlite3SetMakeRecordP5(A,B)
-#endif
-void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
-int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
-void sqlite3BeginWriteOperation(Parse*, int, int);
-void sqlite3MultiWrite(Parse*);
-void sqlite3MayAbort(Parse*);
-void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
-void sqlite3UniqueConstraint(Parse*, int, Index*);
-void sqlite3RowidConstraint(Parse*, int, Table*);
-Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
-ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
-SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
-IdList *sqlite3IdListDup(sqlite3*,IdList*);
-Select *sqlite3SelectDup(sqlite3*,Select*,int);
-#if SELECTTRACE_ENABLED
-void sqlite3SelectSetName(Select*,const char*);
-#else
-# define sqlite3SelectSetName(A,B)
-#endif
-void sqlite3InsertBuiltinFuncs(FuncDef*,int);
-FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
-void sqlite3RegisterBuiltinFunctions(void);
-void sqlite3RegisterDateTimeFunctions(void);
-void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
-int sqlite3SafetyCheckOk(sqlite3*);
-int sqlite3SafetyCheckSickOrOk(sqlite3*);
-void sqlite3ChangeCookie(Parse*, int);
-
-#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
-void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
-#endif
-
-#ifndef SQLITE_OMIT_TRIGGER
- void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
- Expr*,int, int);
- void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
- void sqlite3DropTrigger(Parse*, SrcList*, int);
- void sqlite3DropTriggerPtr(Parse*, Trigger*);
- Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask);
- Trigger *sqlite3TriggerList(Parse *, Table *);
- void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
- int, int, int);
- void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
- void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
- void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
- TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
- const char*,const char*);
- TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
- Select*,u8,Upsert*,
- const char*,const char*);
- TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8,
- const char*,const char*);
- TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*,
- const char*,const char*);
- void sqlite3DeleteTrigger(sqlite3*, Trigger*);
- void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
- u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
-# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
-# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
-#else
-# define sqlite3TriggersExist(B,C,D,E,F) 0
-# define sqlite3DeleteTrigger(A,B)
-# define sqlite3DropTriggerPtr(A,B)
-# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
-# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I)
-# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
-# define sqlite3TriggerList(X, Y) 0
-# define sqlite3ParseToplevel(p) p
-# define sqlite3IsToplevel(p) 1
-# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
-#endif
-
-int sqlite3JoinType(Parse*, Token*, Token*, Token*);
-void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
-void sqlite3DeferForeignKey(Parse*, int);
-#ifndef SQLITE_OMIT_AUTHORIZATION
- void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*);
- int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
- void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);
- void sqlite3AuthContextPop(AuthContext*);
- int sqlite3AuthReadCol(Parse*, const char *, const char *, int);
-#else
-# define sqlite3AuthRead(a,b,c,d)
-# define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK
-# define sqlite3AuthContextPush(a,b,c)
-# define sqlite3AuthContextPop(a) ((void)(a))
-#endif
-void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
-void sqlite3Detach(Parse*, Expr*);
-void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
-int sqlite3FixSrcList(DbFixer*, SrcList*);
-int sqlite3FixSelect(DbFixer*, Select*);
-int sqlite3FixExpr(DbFixer*, Expr*);
-int sqlite3FixExprList(DbFixer*, ExprList*);
-int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
-int sqlite3AtoF(const char *z, double*, int, u8);
-int sqlite3GetInt32(const char *, int*);
-int sqlite3Atoi(const char*);
-#ifndef SQLITE_OMIT_UTF16
-int sqlite3Utf16ByteLen(const void *pData, int nChar);
-#endif
-int sqlite3Utf8CharLen(const char *pData, int nByte);
-u32 sqlite3Utf8Read(const u8**);
-LogEst sqlite3LogEst(u64);
-LogEst sqlite3LogEstAdd(LogEst,LogEst);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-LogEst sqlite3LogEstFromDouble(double);
-#endif
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
- defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
-u64 sqlite3LogEstToInt(LogEst);
-#endif
-VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
-const char *sqlite3VListNumToName(VList*,int);
-int sqlite3VListNameToNum(VList*,const char*,int);
-
-/*
-** Routines to read and write variable-length integers. These used to
-** be defined locally, but now we use the varint routines in the util.c
-** file.
-*/
-int sqlite3PutVarint(unsigned char*, u64);
-u8 sqlite3GetVarint(const unsigned char *, u64 *);
-u8 sqlite3GetVarint32(const unsigned char *, u32 *);
-int sqlite3VarintLen(u64 v);
-
-/*
-** The common case is for a varint to be a single byte. They following
-** macros handle the common case without a procedure call, but then call
-** the procedure for larger varints.
-*/
-#define getVarint32(A,B) \
- (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
-#define putVarint32(A,B) \
- (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
- sqlite3PutVarint((A),(B)))
-#define getVarint sqlite3GetVarint
-#define putVarint sqlite3PutVarint
-
-
-const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
-void sqlite3TableAffinity(Vdbe*, Table*, int);
-char sqlite3CompareAffinity(Expr *pExpr, char aff2);
-int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
-char sqlite3TableColumnAffinity(Table*,int);
-char sqlite3ExprAffinity(Expr *pExpr);
-int sqlite3Atoi64(const char*, i64*, int, u8);
-int sqlite3DecOrHexToI64(const char*, i64*);
-void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
-void sqlite3Error(sqlite3*,int);
-void sqlite3SystemError(sqlite3*,int);
-void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
-u8 sqlite3HexToInt(int h);
-int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
-
-#if defined(SQLITE_NEED_ERR_NAME)
-const char *sqlite3ErrName(int);
-#endif
-
-#ifdef SQLITE_ENABLE_DESERIALIZE
-int sqlite3MemdbInit(void);
-#endif
-
-const char *sqlite3ErrStr(int);
-int sqlite3ReadSchema(Parse *pParse);
-CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
-CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
-CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
-int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
-Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
-Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
-Expr *sqlite3ExprSkipCollate(Expr*);
-int sqlite3CheckCollSeq(Parse *, CollSeq *);
-int sqlite3CheckObjectName(Parse *, const char *);
-void sqlite3VdbeSetChanges(sqlite3 *, int);
-int sqlite3AddInt64(i64*,i64);
-int sqlite3SubInt64(i64*,i64);
-int sqlite3MulInt64(i64*,i64);
-int sqlite3AbsInt32(int);
-#ifdef SQLITE_ENABLE_8_3_NAMES
-void sqlite3FileSuffix3(const char*, char*);
-#else
-# define sqlite3FileSuffix3(X,Y)
-#endif
-u8 sqlite3GetBoolean(const char *z,u8);
-
-const void *sqlite3ValueText(sqlite3_value*, u8);
-int sqlite3ValueBytes(sqlite3_value*, u8);
-void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
- void(*)(void*));
-void sqlite3ValueSetNull(sqlite3_value*);
-void sqlite3ValueFree(sqlite3_value*);
-sqlite3_value *sqlite3ValueNew(sqlite3 *);
-#ifndef SQLITE_OMIT_UTF16
-char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
-#endif
-int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
-void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
-#ifndef SQLITE_AMALGAMATION
-extern const unsigned char sqlite3OpcodeProperty[];
-extern const char sqlite3StrBINARY[];
-extern const unsigned char sqlite3UpperToLower[];
-extern const unsigned char sqlite3CtypeMap[];
-extern const Token sqlite3IntTokens[];
-extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
-extern FuncDefHash sqlite3BuiltinFunctions;
-#ifndef SQLITE_OMIT_WSD
-extern int sqlite3PendingByte;
-#endif
-#endif
-#ifdef VDBE_PROFILE
-extern sqlite3_uint64 sqlite3NProfileCnt;
-#endif
-void sqlite3RootPageMoved(sqlite3*, int, int, int);
-void sqlite3Reindex(Parse*, Token*, Token*);
-void sqlite3AlterFunctions(void);
-void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
-int sqlite3GetToken(const unsigned char *, int *);
-void sqlite3NestedParse(Parse*, const char*, ...);
-void sqlite3ExpirePreparedStatements(sqlite3*);
-int sqlite3CodeSubselect(Parse*, Expr *, int, int);
-void sqlite3SelectPrep(Parse*, Select*, NameContext*);
-void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
-int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
-int sqlite3ResolveExprNames(NameContext*, Expr*);
-int sqlite3ResolveExprListNames(NameContext*, ExprList*);
-void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
-void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
-int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
-void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
-void sqlite3AlterFinishAddColumn(Parse *, Token *);
-void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
-CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
-char sqlite3AffinityType(const char*, Column*);
-void sqlite3Analyze(Parse*, Token*, Token*);
-int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
-int sqlite3FindDb(sqlite3*, Token*);
-int sqlite3FindDbName(sqlite3 *, const char *);
-int sqlite3AnalysisLoad(sqlite3*,int iDB);
-void sqlite3DeleteIndexSamples(sqlite3*,Index*);
-void sqlite3DefaultRowEst(Index*);
-void sqlite3RegisterLikeFunctions(sqlite3*, int);
-int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
-void sqlite3SchemaClear(void *);
-Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
-int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
-KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
-void sqlite3KeyInfoUnref(KeyInfo*);
-KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
-KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
-#ifdef SQLITE_DEBUG
-int sqlite3KeyInfoIsWriteable(KeyInfo*);
-#endif
-int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
- void (*)(sqlite3_context*,int,sqlite3_value **),
- void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
- FuncDestructor *pDestructor
-);
-void sqlite3NoopDestructor(void*);
-void sqlite3OomFault(sqlite3*);
-void sqlite3OomClear(sqlite3*);
-int sqlite3ApiExit(sqlite3 *db, int);
-int sqlite3OpenTempDatabase(Parse *);
-
-void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
-char *sqlite3StrAccumFinish(StrAccum*);
-void sqlite3SelectDestInit(SelectDest*,int,int);
-Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
-
-void sqlite3BackupRestart(sqlite3_backup *);
-void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
-
-#ifndef SQLITE_OMIT_SUBQUERY
-int sqlite3ExprCheckIN(Parse*, Expr*);
-#else
-# define sqlite3ExprCheckIN(x,y) SQLITE_OK
-#endif
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-void sqlite3AnalyzeFunctions(void);
-int sqlite3Stat4ProbeSetValue(
- Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*);
-int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
-void sqlite3Stat4ProbeFree(UnpackedRecord*);
-int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**);
-char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
-#endif
-
-/*
-** The interface to the LEMON-generated parser
-*/
-#ifndef SQLITE_AMALGAMATION
- void *sqlite3ParserAlloc(void*(*)(u64), Parse*);
- void sqlite3ParserFree(void*, void(*)(void*));
-#endif
-void sqlite3Parser(void*, int, Token);
-#ifdef YYTRACKMAXSTACKDEPTH
- int sqlite3ParserStackPeak(void*);
-#endif
-
-void sqlite3AutoLoadExtensions(sqlite3*);
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- void sqlite3CloseExtensions(sqlite3*);
-#else
-# define sqlite3CloseExtensions(X)
-#endif
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
- void sqlite3TableLock(Parse *, int, int, u8, const char *);
-#else
- #define sqlite3TableLock(v,w,x,y,z)
-#endif
-
-#ifdef SQLITE_TEST
- int sqlite3Utf8To8(unsigned char*);
-#endif
-
-#ifdef SQLITE_OMIT_VIRTUALTABLE
-# define sqlite3VtabClear(Y)
-# define sqlite3VtabSync(X,Y) SQLITE_OK
-# define sqlite3VtabRollback(X)
-# define sqlite3VtabCommit(X)
-# define sqlite3VtabInSync(db) 0
-# define sqlite3VtabLock(X)
-# define sqlite3VtabUnlock(X)
-# define sqlite3VtabUnlockList(X)
-# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
-# define sqlite3GetVTable(X,Y) ((VTable*)0)
-#else
- void sqlite3VtabClear(sqlite3 *db, Table*);
- void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
- int sqlite3VtabSync(sqlite3 *db, Vdbe*);
- int sqlite3VtabRollback(sqlite3 *db);
- int sqlite3VtabCommit(sqlite3 *db);
- void sqlite3VtabLock(VTable *);
- void sqlite3VtabUnlock(VTable *);
- void sqlite3VtabUnlockList(sqlite3*);
- int sqlite3VtabSavepoint(sqlite3 *, int, int);
- void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
- VTable *sqlite3GetVTable(sqlite3*, Table*);
- Module *sqlite3VtabCreateModule(
- sqlite3*,
- const char*,
- const sqlite3_module*,
- void*,
- void(*)(void*)
- );
-# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
-#endif
-int sqlite3VtabEponymousTableInit(Parse*,Module*);
-void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
-void sqlite3VtabMakeWritable(Parse*,Table*);
-void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
-void sqlite3VtabFinishParse(Parse*, Token*);
-void sqlite3VtabArgInit(Parse*);
-void sqlite3VtabArgExtend(Parse*, Token*);
-int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
-int sqlite3VtabCallConnect(Parse*, Table*);
-int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
-int sqlite3VtabBegin(sqlite3 *, VTable *);
-FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
-sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
-int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
-int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
-void sqlite3ParserReset(Parse*);
-int sqlite3Reprepare(Vdbe*);
-void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
-CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
-int sqlite3TempInMemory(const sqlite3*);
-const char *sqlite3JournalModename(int);
-#ifndef SQLITE_OMIT_WAL
- int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
- int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
-#endif
-#ifndef SQLITE_OMIT_CTE
- With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
- void sqlite3WithDelete(sqlite3*,With*);
- void sqlite3WithPush(Parse*, With*, u8);
-#else
-#define sqlite3WithPush(x,y,z)
-#define sqlite3WithDelete(x,y)
-#endif
-#ifndef SQLITE_OMIT_UPSERT
- Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
- void sqlite3UpsertDelete(sqlite3*,Upsert*);
- Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
- int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
- void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
-#else
-#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0)
-#define sqlite3UpsertDelete(x,y)
-#define sqlite3UpsertDup(x,y) ((Upsert*)0)
-#endif
-
-
-/* Declarations for functions in fkey.c. All of these are replaced by
-** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
-** key functionality is available. If OMIT_TRIGGER is defined but
-** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
-** this case foreign keys are parsed, but no other functionality is
-** provided (enforcement of FK constraints requires the triggers sub-system).
-*/
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
- void sqlite3FkDropTable(Parse*, SrcList *, Table*);
- void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
- int sqlite3FkRequired(Parse*, Table*, int*, int);
- u32 sqlite3FkOldmask(Parse*, Table*);
- FKey *sqlite3FkReferences(Table *);
-#else
- #define sqlite3FkActions(a,b,c,d,e,f)
- #define sqlite3FkCheck(a,b,c,d,e,f)
- #define sqlite3FkDropTable(a,b,c)
- #define sqlite3FkOldmask(a,b) 0
- #define sqlite3FkRequired(a,b,c,d) 0
- #define sqlite3FkReferences(a) 0
-#endif
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- void sqlite3FkDelete(sqlite3 *, Table*);
- int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
-#else
- #define sqlite3FkDelete(a,b)
- #define sqlite3FkLocateIndex(a,b,c,d,e)
-#endif
-
-
-/*
-** Available fault injectors. Should be numbered beginning with 0.
-*/
-#define SQLITE_FAULTINJECTOR_MALLOC 0
-#define SQLITE_FAULTINJECTOR_COUNT 1
-
-/*
-** The interface to the code in fault.c used for identifying "benign"
-** malloc failures. This is only present if SQLITE_UNTESTABLE
-** is not defined.
-*/
-#ifndef SQLITE_UNTESTABLE
- void sqlite3BeginBenignMalloc(void);
- void sqlite3EndBenignMalloc(void);
-#else
- #define sqlite3BeginBenignMalloc()
- #define sqlite3EndBenignMalloc()
-#endif
-
-/*
-** Allowed return values from sqlite3FindInIndex()
-*/
-#define IN_INDEX_ROWID 1 /* Search the rowid of the table */
-#define IN_INDEX_EPH 2 /* Search an ephemeral b-tree */
-#define IN_INDEX_INDEX_ASC 3 /* Existing index ASCENDING */
-#define IN_INDEX_INDEX_DESC 4 /* Existing index DESCENDING */
-#define IN_INDEX_NOOP 5 /* No table available. Use comparisons */
-/*
-** Allowed flags for the 3rd parameter to sqlite3FindInIndex().
-*/
-#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */
-#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */
-#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */
-int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
-
-int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
-int sqlite3JournalSize(sqlite3_vfs *);
-#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
- || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
- int sqlite3JournalCreate(sqlite3_file *);
-#endif
-
-int sqlite3JournalIsInMemory(sqlite3_file *p);
-void sqlite3MemJournalOpen(sqlite3_file *);
-
-void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
-#if SQLITE_MAX_EXPR_DEPTH>0
- int sqlite3SelectExprHeight(Select *);
- int sqlite3ExprCheckHeight(Parse*, int);
-#else
- #define sqlite3SelectExprHeight(x) 0
- #define sqlite3ExprCheckHeight(x,y)
-#endif
-
-u32 sqlite3Get4byte(const u8*);
-void sqlite3Put4byte(u8*, u32);
-
-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
- void sqlite3ConnectionBlocked(sqlite3 *, sqlite3 *);
- void sqlite3ConnectionUnlocked(sqlite3 *db);
- void sqlite3ConnectionClosed(sqlite3 *db);
-#else
- #define sqlite3ConnectionBlocked(x,y)
- #define sqlite3ConnectionUnlocked(x)
- #define sqlite3ConnectionClosed(x)
-#endif
-
-#ifdef SQLITE_DEBUG
- void sqlite3ParserTrace(FILE*, char *);
-#endif
-#if defined(YYCOVERAGE)
- int sqlite3ParserCoverage(FILE*);
-#endif
-
-/*
-** If the SQLITE_ENABLE IOTRACE exists then the global variable
-** sqlite3IoTrace is a pointer to a printf-like routine used to
-** print I/O tracing messages.
-*/
-#ifdef SQLITE_ENABLE_IOTRACE
-# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
- void sqlite3VdbeIOTraceSql(Vdbe*);
-SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
-#else
-# define IOTRACE(A)
-# define sqlite3VdbeIOTraceSql(X)
-#endif
-
-/*
-** These routines are available for the mem2.c debugging memory allocator
-** only. They are used to verify that different "types" of memory
-** allocations are properly tracked by the system.
-**
-** sqlite3MemdebugSetType() sets the "type" of an allocation to one of
-** the MEMTYPE_* macros defined below. The type must be a bitmask with
-** a single bit set.
-**
-** sqlite3MemdebugHasType() returns true if any of the bits in its second
-** argument match the type set by the previous sqlite3MemdebugSetType().
-** sqlite3MemdebugHasType() is intended for use inside assert() statements.
-**
-** sqlite3MemdebugNoType() returns true if none of the bits in its second
-** argument match the type set by the previous sqlite3MemdebugSetType().
-**
-** Perhaps the most important point is the difference between MEMTYPE_HEAP
-** and MEMTYPE_LOOKASIDE. If an allocation is MEMTYPE_LOOKASIDE, that means
-** it might have been allocated by lookaside, except the allocation was
-** too large or lookaside was already full. It is important to verify
-** that allocations that might have been satisfied by lookaside are not
-** passed back to non-lookaside free() routines. Asserts such as the
-** example above are placed on the non-lookaside free() routines to verify
-** this constraint.
-**
-** All of this is no-op for a production build. It only comes into
-** play when the SQLITE_MEMDEBUG compile-time option is used.
-*/
-#ifdef SQLITE_MEMDEBUG
- void sqlite3MemdebugSetType(void*,u8);
- int sqlite3MemdebugHasType(void*,u8);
- int sqlite3MemdebugNoType(void*,u8);
-#else
-# define sqlite3MemdebugSetType(X,Y) /* no-op */
-# define sqlite3MemdebugHasType(X,Y) 1
-# define sqlite3MemdebugNoType(X,Y) 1
-#endif
-#define MEMTYPE_HEAP 0x01 /* General heap allocations */
-#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */
-#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */
-
-/*
-** Threading interface
-*/
-#if SQLITE_MAX_WORKER_THREADS>0
-int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
-int sqlite3ThreadJoin(SQLiteThread*, void**);
-#endif
-
-#if defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)
-int sqlite3DbpageRegister(sqlite3*);
-#endif
-#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)
-int sqlite3DbstatRegister(sqlite3*);
-#endif
-
-int sqlite3ExprVectorSize(Expr *pExpr);
-int sqlite3ExprIsVector(Expr *pExpr);
-Expr *sqlite3VectorFieldSubexpr(Expr*, int);
-Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
-void sqlite3VectorErrorMsg(Parse*, Expr*);
-
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-const char **sqlite3CompileOptions(int *pnOpt);
-#endif
-
-#endif /* SQLITEINT_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqliteLimit.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/sqliteLimit.h
deleted file mode 100644
index 28e7a41cc3e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/sqliteLimit.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
-** 2007 May 7
-**
-** 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 defines various limits of what SQLite can process.
-*/
-
-/*
-** The maximum length of a TEXT or BLOB in bytes. This also
-** limits the size of a row in a table or index.
-**
-** The hard limit is the ability of a 32-bit signed integer
-** to count the size: 2^31-1 or 2147483647.
-*/
-#ifndef SQLITE_MAX_LENGTH
-# define SQLITE_MAX_LENGTH 1000000000
-#endif
-
-/*
-** This is the maximum number of
-**
-** * Columns in a table
-** * Columns in an index
-** * Columns in a view
-** * Terms in the SET clause of an UPDATE statement
-** * Terms in the result set of a SELECT statement
-** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
-** * Terms in the VALUES clause of an INSERT statement
-**
-** The hard upper limit here is 32676. Most database people will
-** tell you that in a well-normalized database, you usually should
-** not have more than a dozen or so columns in any table. And if
-** that is the case, there is no point in having more than a few
-** dozen values in any of the other situations described above.
-*/
-#ifndef SQLITE_MAX_COLUMN
-# define SQLITE_MAX_COLUMN 2000
-#endif
-
-/*
-** The maximum length of a single SQL statement in bytes.
-**
-** It used to be the case that setting this value to zero would
-** turn the limit off. That is no longer true. It is not possible
-** to turn this limit off.
-*/
-#ifndef SQLITE_MAX_SQL_LENGTH
-# define SQLITE_MAX_SQL_LENGTH 1000000000
-#endif
-
-/*
-** The maximum depth of an expression tree. This is limited to
-** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
-** want to place more severe limits on the complexity of an
-** expression.
-**
-** A value of 0 used to mean that the limit was not enforced.
-** But that is no longer true. The limit is now strictly enforced
-** at all times.
-*/
-#ifndef SQLITE_MAX_EXPR_DEPTH
-# define SQLITE_MAX_EXPR_DEPTH 1000
-#endif
-
-/*
-** The maximum number of terms in a compound SELECT statement.
-** The code generator for compound SELECT statements does one
-** level of recursion for each term. A stack overflow can result
-** if the number of terms is too large. In practice, most SQL
-** never has more than 3 or 4 terms. Use a value of 0 to disable
-** any limit on the number of terms in a compount SELECT.
-*/
-#ifndef SQLITE_MAX_COMPOUND_SELECT
-# define SQLITE_MAX_COMPOUND_SELECT 500
-#endif
-
-/*
-** The maximum number of opcodes in a VDBE program.
-** Not currently enforced.
-*/
-#ifndef SQLITE_MAX_VDBE_OP
-# define SQLITE_MAX_VDBE_OP 250000000
-#endif
-
-/*
-** The maximum number of arguments to an SQL function.
-*/
-#ifndef SQLITE_MAX_FUNCTION_ARG
-# define SQLITE_MAX_FUNCTION_ARG 127
-#endif
-
-/*
-** The suggested maximum number of in-memory pages to use for
-** the main database table and for temporary tables.
-**
-** IMPLEMENTATION-OF: R-30185-15359 The default suggested cache size is -2000,
-** which means the cache size is limited to 2048000 bytes of memory.
-** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be
-** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options.
-*/
-#ifndef SQLITE_DEFAULT_CACHE_SIZE
-# define SQLITE_DEFAULT_CACHE_SIZE -2000
-#endif
-
-/*
-** The default number of frames to accumulate in the log file before
-** checkpointing the database in WAL mode.
-*/
-#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
-# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
-#endif
-
-/*
-** The maximum number of attached databases. This must be between 0
-** and 125. The upper bound of 125 is because the attached databases are
-** counted using a signed 8-bit integer which has a maximum value of 127
-** and we have to allow 2 extra counts for the "main" and "temp" databases.
-*/
-#ifndef SQLITE_MAX_ATTACHED
-# define SQLITE_MAX_ATTACHED 10
-#endif
-
-
-/*
-** The maximum value of a ?nnn wildcard that the parser will accept.
-*/
-#ifndef SQLITE_MAX_VARIABLE_NUMBER
-# define SQLITE_MAX_VARIABLE_NUMBER 999
-#endif
-
-/* Maximum page size. The upper bound on this value is 65536. This a limit
-** imposed by the use of 16-bit offsets within each page.
-**
-** Earlier versions of SQLite allowed the user to change this value at
-** compile time. This is no longer permitted, on the grounds that it creates
-** a library that is technically incompatible with an SQLite library
-** compiled with a different limit. If a process operating on a database
-** with a page-size of 65536 bytes crashes, then an instance of SQLite
-** compiled with the default page-size limit will not be able to rollback
-** the aborted transaction. This could lead to database corruption.
-*/
-#ifdef SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_MAX_PAGE_SIZE
-#endif
-#define SQLITE_MAX_PAGE_SIZE 65536
-
-
-/*
-** The default size of a database page.
-*/
-#ifndef SQLITE_DEFAULT_PAGE_SIZE
-# define SQLITE_DEFAULT_PAGE_SIZE 4096
-#endif
-#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_DEFAULT_PAGE_SIZE
-# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
-#endif
-
-/*
-** Ordinarily, if no value is explicitly provided, SQLite creates databases
-** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
-** device characteristics (sector-size and atomic write() support),
-** SQLite may choose a larger value. This constant is the maximum value
-** SQLite will choose on its own.
-*/
-#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
-# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
-#endif
-#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
-# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
-#endif
-
-
-/*
-** Maximum number of pages in one database file.
-**
-** This is really just the default value for the max_page_count pragma.
-** This value can be lowered (or raised) at run-time using that the
-** max_page_count macro.
-*/
-#ifndef SQLITE_MAX_PAGE_COUNT
-# define SQLITE_MAX_PAGE_COUNT 1073741823
-#endif
-
-/*
-** Maximum length (in bytes) of the pattern in a LIKE or GLOB
-** operator.
-*/
-#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
-# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
-#endif
-
-/*
-** Maximum depth of recursion for triggers.
-**
-** A value of 1 means that a trigger program will not be able to itself
-** fire any triggers. A value of 0 means that no trigger programs at all
-** may be executed.
-*/
-#ifndef SQLITE_MAX_TRIGGER_DEPTH
-# define SQLITE_MAX_TRIGGER_DEPTH 1000
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/status.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/status.c
deleted file mode 100644
index a5a39f4c182..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/status.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
-** 2008 June 18
-**
-** 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 module implements the sqlite3_status() interface and related
-** functionality.
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-/*
-** Variables in which to record status information.
-*/
-#if SQLITE_PTRSIZE>4
-typedef sqlite3_int64 sqlite3StatValueType;
-#else
-typedef u32 sqlite3StatValueType;
-#endif
-typedef struct sqlite3StatType sqlite3StatType;
-static SQLITE_WSD struct sqlite3StatType {
- sqlite3StatValueType nowValue[10]; /* Current value */
- sqlite3StatValueType mxValue[10]; /* Maximum value */
-} sqlite3Stat = { {0,}, {0,} };
-
-/*
-** Elements of sqlite3Stat[] are protected by either the memory allocator
-** mutex, or by the pcache1 mutex. The following array determines which.
-*/
-static const char statMutex[] = {
- 0, /* SQLITE_STATUS_MEMORY_USED */
- 1, /* SQLITE_STATUS_PAGECACHE_USED */
- 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */
- 0, /* SQLITE_STATUS_SCRATCH_USED */
- 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */
- 0, /* SQLITE_STATUS_MALLOC_SIZE */
- 0, /* SQLITE_STATUS_PARSER_STACK */
- 1, /* SQLITE_STATUS_PAGECACHE_SIZE */
- 0, /* SQLITE_STATUS_SCRATCH_SIZE */
- 0, /* SQLITE_STATUS_MALLOC_COUNT */
-};
-
-
-/* The "wsdStat" macro will resolve to the status information
-** state vector. If writable static data is unsupported on the target,
-** we have to locate the state vector at run-time. In the more common
-** case where writable static data is supported, wsdStat can refer directly
-** to the "sqlite3Stat" state vector declared above.
-*/
-#ifdef SQLITE_OMIT_WSD
-# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
-# define wsdStat x[0]
-#else
-# define wsdStatInit
-# define wsdStat sqlite3Stat
-#endif
-
-/*
-** Return the current value of a status parameter. The caller must
-** be holding the appropriate mutex.
-*/
-sqlite3_int64 sqlite3StatusValue(int op){
- wsdStatInit;
- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
- assert( op>=0 && op<ArraySize(statMutex) );
- assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
- : sqlite3MallocMutex()) );
- return wsdStat.nowValue[op];
-}
-
-/*
-** Add N to the value of a status record. The caller must hold the
-** appropriate mutex. (Locking is checked by assert()).
-**
-** The StatusUp() routine can accept positive or negative values for N.
-** The value of N is added to the current status value and the high-water
-** mark is adjusted if necessary.
-**
-** The StatusDown() routine lowers the current value by N. The highwater
-** mark is unchanged. N must be non-negative for StatusDown().
-*/
-void sqlite3StatusUp(int op, int N){
- wsdStatInit;
- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
- assert( op>=0 && op<ArraySize(statMutex) );
- assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
- : sqlite3MallocMutex()) );
- wsdStat.nowValue[op] += N;
- if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
- wsdStat.mxValue[op] = wsdStat.nowValue[op];
- }
-}
-void sqlite3StatusDown(int op, int N){
- wsdStatInit;
- assert( N>=0 );
- assert( op>=0 && op<ArraySize(statMutex) );
- assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
- : sqlite3MallocMutex()) );
- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
- wsdStat.nowValue[op] -= N;
-}
-
-/*
-** Adjust the highwater mark if necessary.
-** The caller must hold the appropriate mutex.
-*/
-void sqlite3StatusHighwater(int op, int X){
- sqlite3StatValueType newValue;
- wsdStatInit;
- assert( X>=0 );
- newValue = (sqlite3StatValueType)X;
- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
- assert( op>=0 && op<ArraySize(statMutex) );
- assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
- : sqlite3MallocMutex()) );
- assert( op==SQLITE_STATUS_MALLOC_SIZE
- || op==SQLITE_STATUS_PAGECACHE_SIZE
- || op==SQLITE_STATUS_PARSER_STACK );
- if( newValue>wsdStat.mxValue[op] ){
- wsdStat.mxValue[op] = newValue;
- }
-}
-
-/*
-** Query status information.
-*/
-int sqlite3_status64(
- int op,
- sqlite3_int64 *pCurrent,
- sqlite3_int64 *pHighwater,
- int resetFlag
-){
- sqlite3_mutex *pMutex;
- wsdStatInit;
- if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
- return SQLITE_MISUSE_BKPT;
- }
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex();
- sqlite3_mutex_enter(pMutex);
- *pCurrent = wsdStat.nowValue[op];
- *pHighwater = wsdStat.mxValue[op];
- if( resetFlag ){
- wsdStat.mxValue[op] = wsdStat.nowValue[op];
- }
- sqlite3_mutex_leave(pMutex);
- (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */
- return SQLITE_OK;
-}
-int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
- sqlite3_int64 iCur = 0, iHwtr = 0;
- int rc;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
- if( rc==0 ){
- *pCurrent = (int)iCur;
- *pHighwater = (int)iHwtr;
- }
- return rc;
-}
-
-/*
-** Return the number of LookasideSlot elements on the linked list
-*/
-static u32 countLookasideSlots(LookasideSlot *p){
- u32 cnt = 0;
- while( p ){
- p = p->pNext;
- cnt++;
- }
- return cnt;
-}
-
-/*
-** Count the number of slots of lookaside memory that are outstanding
-*/
-int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
- u32 nInit = countLookasideSlots(db->lookaside.pInit);
- u32 nFree = countLookasideSlots(db->lookaside.pFree);
- if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
- return db->lookaside.nSlot - (nInit+nFree);
-}
-
-/*
-** Query status information for a single database connection
-*/
-int sqlite3_db_status(
- sqlite3 *db, /* The database connection whose status is desired */
- int op, /* Status verb */
- int *pCurrent, /* Write current value here */
- int *pHighwater, /* Write high-water mark here */
- int resetFlag /* Reset high-water mark if true */
-){
- int rc = SQLITE_OK; /* Return code */
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- switch( op ){
- case SQLITE_DBSTATUS_LOOKASIDE_USED: {
- *pCurrent = sqlite3LookasideUsed(db, pHighwater);
- if( resetFlag ){
- LookasideSlot *p = db->lookaside.pFree;
- if( p ){
- while( p->pNext ) p = p->pNext;
- p->pNext = db->lookaside.pInit;
- db->lookaside.pInit = db->lookaside.pFree;
- db->lookaside.pFree = 0;
- }
- }
- break;
- }
-
- case SQLITE_DBSTATUS_LOOKASIDE_HIT:
- case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
- case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
- testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT );
- testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE );
- testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL );
- assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
- assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
- *pCurrent = 0;
- *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
- if( resetFlag ){
- db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
- }
- break;
- }
-
- /*
- ** Return an approximation for the amount of memory currently used
- ** by all pagers associated with the given database connection. The
- ** highwater mark is meaningless and is returned as zero.
- */
- case SQLITE_DBSTATUS_CACHE_USED_SHARED:
- case SQLITE_DBSTATUS_CACHE_USED: {
- int totalUsed = 0;
- int i;
- sqlite3BtreeEnterAll(db);
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- Pager *pPager = sqlite3BtreePager(pBt);
- int nByte = sqlite3PagerMemUsed(pPager);
- if( op==SQLITE_DBSTATUS_CACHE_USED_SHARED ){
- nByte = nByte / sqlite3BtreeConnectionCount(pBt);
- }
- totalUsed += nByte;
- }
- }
- sqlite3BtreeLeaveAll(db);
- *pCurrent = totalUsed;
- *pHighwater = 0;
- break;
- }
-
- /*
- ** *pCurrent gets an accurate estimate of the amount of memory used
- ** to store the schema for all databases (main, temp, and any ATTACHed
- ** databases. *pHighwater is set to zero.
- */
- case SQLITE_DBSTATUS_SCHEMA_USED: {
- int i; /* Used to iterate through schemas */
- int nByte = 0; /* Used to accumulate return value */
-
- sqlite3BtreeEnterAll(db);
- db->pnBytesFreed = &nByte;
- for(i=0; i<db->nDb; i++){
- Schema *pSchema = db->aDb[i].pSchema;
- if( ALWAYS(pSchema!=0) ){
- HashElem *p;
-
- nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
- pSchema->tblHash.count
- + pSchema->trigHash.count
- + pSchema->idxHash.count
- + pSchema->fkeyHash.count
- );
- nByte += sqlite3_msize(pSchema->tblHash.ht);
- nByte += sqlite3_msize(pSchema->trigHash.ht);
- nByte += sqlite3_msize(pSchema->idxHash.ht);
- nByte += sqlite3_msize(pSchema->fkeyHash.ht);
-
- for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
- sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
- }
- for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
- sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
- }
- }
- }
- db->pnBytesFreed = 0;
- sqlite3BtreeLeaveAll(db);
-
- *pHighwater = 0;
- *pCurrent = nByte;
- break;
- }
-
- /*
- ** *pCurrent gets an accurate estimate of the amount of memory used
- ** to store all prepared statements.
- ** *pHighwater is set to zero.
- */
- case SQLITE_DBSTATUS_STMT_USED: {
- struct Vdbe *pVdbe; /* Used to iterate through VMs */
- int nByte = 0; /* Used to accumulate return value */
-
- db->pnBytesFreed = &nByte;
- for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
- sqlite3VdbeClearObject(db, pVdbe);
- sqlite3DbFree(db, pVdbe);
- }
- db->pnBytesFreed = 0;
-
- *pHighwater = 0; /* IMP: R-64479-57858 */
- *pCurrent = nByte;
-
- break;
- }
-
- /*
- ** Set *pCurrent to the total cache hits or misses encountered by all
- ** pagers the database handle is connected to. *pHighwater is always set
- ** to zero.
- */
- case SQLITE_DBSTATUS_CACHE_SPILL:
- op = SQLITE_DBSTATUS_CACHE_WRITE+1;
- /* Fall through into the next case */
- case SQLITE_DBSTATUS_CACHE_HIT:
- case SQLITE_DBSTATUS_CACHE_MISS:
- case SQLITE_DBSTATUS_CACHE_WRITE:{
- int i;
- int nRet = 0;
- assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
- assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
-
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt ){
- Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
- sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
- }
- }
- *pHighwater = 0; /* IMP: R-42420-56072 */
- /* IMP: R-54100-20147 */
- /* IMP: R-29431-39229 */
- *pCurrent = nRet;
- break;
- }
-
- /* Set *pCurrent to non-zero if there are unresolved deferred foreign
- ** key constraints. Set *pCurrent to zero if all foreign key constraints
- ** have been satisfied. The *pHighwater is always set to zero.
- */
- case SQLITE_DBSTATUS_DEFERRED_FKS: {
- *pHighwater = 0; /* IMP: R-11967-56545 */
- *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
- break;
- }
-
- default: {
- rc = SQLITE_ERROR;
- }
- }
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/table.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/table.c
deleted file mode 100644
index c79255f990c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/table.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains the sqlite3_get_table() and sqlite3_free_table()
-** interface routines. These are just wrappers around the main
-** interface routine of sqlite3_exec().
-**
-** These routines are in a separate files so that they will not be linked
-** if they are not used.
-*/
-#include "sqliteInt.h"
-
-#ifndef SQLITE_OMIT_GET_TABLE
-
-/*
-** This structure is used to pass data from sqlite3_get_table() through
-** to the callback function is uses to build the result.
-*/
-typedef struct TabResult {
- char **azResult; /* Accumulated output */
- char *zErrMsg; /* Error message text, if an error occurs */
- u32 nAlloc; /* Slots allocated for azResult[] */
- u32 nRow; /* Number of rows in the result */
- u32 nColumn; /* Number of columns in the result */
- u32 nData; /* Slots used in azResult[]. (nRow+1)*nColumn */
- int rc; /* Return code from sqlite3_exec() */
-} TabResult;
-
-/*
-** This routine is called once for each row in the result table. Its job
-** is to fill in the TabResult structure appropriately, allocating new
-** memory as necessary.
-*/
-static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
- TabResult *p = (TabResult*)pArg; /* Result accumulator */
- int need; /* Slots needed in p->azResult[] */
- int i; /* Loop counter */
- char *z; /* A single column of result */
-
- /* Make sure there is enough space in p->azResult to hold everything
- ** we need to remember from this invocation of the callback.
- */
- if( p->nRow==0 && argv!=0 ){
- need = nCol*2;
- }else{
- need = nCol;
- }
- if( p->nData + need > p->nAlloc ){
- char **azNew;
- p->nAlloc = p->nAlloc*2 + need;
- azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
- if( azNew==0 ) goto malloc_failed;
- p->azResult = azNew;
- }
-
- /* If this is the first row, then generate an extra row containing
- ** the names of all columns.
- */
- if( p->nRow==0 ){
- p->nColumn = nCol;
- for(i=0; i<nCol; i++){
- z = sqlite3_mprintf("%s", colv[i]);
- if( z==0 ) goto malloc_failed;
- p->azResult[p->nData++] = z;
- }
- }else if( (int)p->nColumn!=nCol ){
- sqlite3_free(p->zErrMsg);
- p->zErrMsg = sqlite3_mprintf(
- "sqlite3_get_table() called with two or more incompatible queries"
- );
- p->rc = SQLITE_ERROR;
- return 1;
- }
-
- /* Copy over the row data
- */
- if( argv!=0 ){
- for(i=0; i<nCol; i++){
- if( argv[i]==0 ){
- z = 0;
- }else{
- int n = sqlite3Strlen30(argv[i])+1;
- z = sqlite3_malloc64( n );
- if( z==0 ) goto malloc_failed;
- memcpy(z, argv[i], n);
- }
- p->azResult[p->nData++] = z;
- }
- p->nRow++;
- }
- return 0;
-
-malloc_failed:
- p->rc = SQLITE_NOMEM_BKPT;
- return 1;
-}
-
-/*
-** Query the database. But instead of invoking a callback for each row,
-** malloc() for space to hold the result and return the entire results
-** at the conclusion of the call.
-**
-** The result that is written to ***pazResult is held in memory obtained
-** from malloc(). But the caller cannot free this memory directly.
-** Instead, the entire table should be passed to sqlite3_free_table() when
-** the calling procedure is finished using it.
-*/
-int sqlite3_get_table(
- sqlite3 *db, /* The database on which the SQL executes */
- const char *zSql, /* The SQL to be executed */
- char ***pazResult, /* Write the result table here */
- int *pnRow, /* Write the number of rows in the result here */
- int *pnColumn, /* Write the number of columns of result here */
- char **pzErrMsg /* Write error messages here */
-){
- int rc;
- TabResult res;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- *pazResult = 0;
- if( pnColumn ) *pnColumn = 0;
- if( pnRow ) *pnRow = 0;
- if( pzErrMsg ) *pzErrMsg = 0;
- res.zErrMsg = 0;
- res.nRow = 0;
- res.nColumn = 0;
- res.nData = 1;
- res.nAlloc = 20;
- res.rc = SQLITE_OK;
- res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc );
- if( res.azResult==0 ){
- db->errCode = SQLITE_NOMEM;
- return SQLITE_NOMEM_BKPT;
- }
- res.azResult[0] = 0;
- rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
- assert( sizeof(res.azResult[0])>= sizeof(res.nData) );
- res.azResult[0] = SQLITE_INT_TO_PTR(res.nData);
- if( (rc&0xff)==SQLITE_ABORT ){
- sqlite3_free_table(&res.azResult[1]);
- if( res.zErrMsg ){
- if( pzErrMsg ){
- sqlite3_free(*pzErrMsg);
- *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
- }
- sqlite3_free(res.zErrMsg);
- }
- db->errCode = res.rc; /* Assume 32-bit assignment is atomic */
- return res.rc;
- }
- sqlite3_free(res.zErrMsg);
- if( rc!=SQLITE_OK ){
- sqlite3_free_table(&res.azResult[1]);
- return rc;
- }
- if( res.nAlloc>res.nData ){
- char **azNew;
- azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
- if( azNew==0 ){
- sqlite3_free_table(&res.azResult[1]);
- db->errCode = SQLITE_NOMEM;
- return SQLITE_NOMEM_BKPT;
- }
- res.azResult = azNew;
- }
- *pazResult = &res.azResult[1];
- if( pnColumn ) *pnColumn = res.nColumn;
- if( pnRow ) *pnRow = res.nRow;
- return rc;
-}
-
-/*
-** This routine frees the space the sqlite3_get_table() malloced.
-*/
-void sqlite3_free_table(
- char **azResult /* Result returned from sqlite3_get_table() */
-){
- if( azResult ){
- int i, n;
- azResult--;
- assert( azResult!=0 );
- n = SQLITE_PTR_TO_INT(azResult[0]);
- for(i=1; i<n; i++){ if( azResult[i] ) sqlite3_free(azResult[i]); }
- sqlite3_free(azResult);
- }
-}
-
-#endif /* SQLITE_OMIT_GET_TABLE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/tclsqlite.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/tclsqlite.c
deleted file mode 100644
index e5984ec804c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/tclsqlite.c
+++ /dev/null
@@ -1,3776 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** A TCL Interface to SQLite. Append this file to sqlite3.c and
-** compile the whole thing to build a TCL-enabled version of SQLite.
-**
-** Compile-time options:
-**
-** -DTCLSH Add a "main()" routine that works as a tclsh.
-**
-** -DTCLSH_INIT_PROC=name
-**
-** Invoke name(interp) to initialize the Tcl interpreter.
-** If name(interp) returns a non-NULL string, then run
-** that string as a Tcl script to launch the application.
-** If name(interp) returns NULL, then run the regular
-** tclsh-emulator code.
-*/
-#ifdef TCLSH_INIT_PROC
-# define TCLSH 1
-#endif
-
-/*
-** If requested, include the SQLite compiler options file for MSVC.
-*/
-#if defined(INCLUDE_MSVC_H)
-# include "msvc.h"
-#endif
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-#include <errno.h>
-
-/*
-** Some additional include files are needed if this file is not
-** appended to the amalgamation.
-*/
-#ifndef SQLITE_AMALGAMATION
-# include "sqlite3.h"
-# include <stdlib.h>
-# include <string.h>
-# include <assert.h>
- typedef unsigned char u8;
-#endif
-#include <ctype.h>
-
-/* Used to get the current process ID */
-#if !defined(_WIN32)
-# include <unistd.h>
-# define GETPID getpid
-#elif !defined(_WIN32_WCE)
-# ifndef SQLITE_AMALGAMATION
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-# endif
-# include <windows.h>
-# endif
-# define GETPID (int)GetCurrentProcessId
-#endif
-
-/*
- * Windows needs to know which symbols to export. Unix does not.
- * BUILD_sqlite should be undefined for Unix.
- */
-#ifdef BUILD_sqlite
-#undef TCL_STORAGE_CLASS
-#define TCL_STORAGE_CLASS DLLEXPORT
-#endif /* BUILD_sqlite */
-
-#define NUM_PREPARED_STMTS 10
-#define MAX_PREPARED_STMTS 100
-
-/* Forward declaration */
-typedef struct SqliteDb SqliteDb;
-
-/*
-** New SQL functions can be created as TCL scripts. Each such function
-** is described by an instance of the following structure.
-*/
-typedef struct SqlFunc SqlFunc;
-struct SqlFunc {
- Tcl_Interp *interp; /* The TCL interpret to execute the function */
- Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */
- SqliteDb *pDb; /* Database connection that owns this function */
- int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */
- char *zName; /* Name of this function */
- SqlFunc *pNext; /* Next function on the list of them all */
-};
-
-/*
-** New collation sequences function can be created as TCL scripts. Each such
-** function is described by an instance of the following structure.
-*/
-typedef struct SqlCollate SqlCollate;
-struct SqlCollate {
- Tcl_Interp *interp; /* The TCL interpret to execute the function */
- char *zScript; /* The script to be run */
- SqlCollate *pNext; /* Next function on the list of them all */
-};
-
-/*
-** Prepared statements are cached for faster execution. Each prepared
-** statement is described by an instance of the following structure.
-*/
-typedef struct SqlPreparedStmt SqlPreparedStmt;
-struct SqlPreparedStmt {
- SqlPreparedStmt *pNext; /* Next in linked list */
- SqlPreparedStmt *pPrev; /* Previous on the list */
- sqlite3_stmt *pStmt; /* The prepared statement */
- int nSql; /* chars in zSql[] */
- const char *zSql; /* Text of the SQL statement */
- int nParm; /* Size of apParm array */
- Tcl_Obj **apParm; /* Array of referenced object pointers */
-};
-
-typedef struct IncrblobChannel IncrblobChannel;
-
-/*
-** There is one instance of this structure for each SQLite database
-** that has been opened by the SQLite TCL interface.
-**
-** If this module is built with SQLITE_TEST defined (to create the SQLite
-** testfixture executable), then it may be configured to use either
-** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements.
-** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used.
-*/
-struct SqliteDb {
- sqlite3 *db; /* The "real" database structure. MUST BE FIRST */
- Tcl_Interp *interp; /* The interpreter used for this database */
- char *zBusy; /* The busy callback routine */
- char *zCommit; /* The commit hook callback routine */
- char *zTrace; /* The trace callback routine */
- char *zTraceV2; /* The trace_v2 callback routine */
- char *zProfile; /* The profile callback routine */
- char *zProgress; /* The progress callback routine */
- char *zAuth; /* The authorization callback routine */
- int disableAuth; /* Disable the authorizer if it exists */
- char *zNull; /* Text to substitute for an SQL NULL value */
- SqlFunc *pFunc; /* List of SQL functions */
- Tcl_Obj *pUpdateHook; /* Update hook script (if any) */
- Tcl_Obj *pPreUpdateHook; /* Pre-update hook script (if any) */
- Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */
- Tcl_Obj *pWalHook; /* WAL hook script (if any) */
- Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */
- SqlCollate *pCollate; /* List of SQL collation functions */
- int rc; /* Return code of most recent sqlite3_exec() */
- Tcl_Obj *pCollateNeeded; /* Collation needed script */
- SqlPreparedStmt *stmtList; /* List of prepared statements*/
- SqlPreparedStmt *stmtLast; /* Last statement in the list */
- int maxStmt; /* The next maximum number of stmtList */
- int nStmt; /* Number of statements in stmtList */
- IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
- int nStep, nSort, nIndex; /* Statistics for most recent operation */
- int nVMStep; /* Another statistic for most recent operation */
- int nTransaction; /* Number of nested [transaction] methods */
- int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */
-#ifdef SQLITE_TEST
- int bLegacyPrepare; /* True to use sqlite3_prepare() */
-#endif
-};
-
-struct IncrblobChannel {
- sqlite3_blob *pBlob; /* sqlite3 blob handle */
- SqliteDb *pDb; /* Associated database connection */
- int iSeek; /* Current seek offset */
- Tcl_Channel channel; /* Channel identifier */
- IncrblobChannel *pNext; /* Linked list of all open incrblob channels */
- IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */
-};
-
-/*
-** Compute a string length that is limited to what can be stored in
-** lower 30 bits of a 32-bit signed integer.
-*/
-static int strlen30(const char *z){
- const char *z2 = z;
- while( *z2 ){ z2++; }
- return 0x3fffffff & (int)(z2 - z);
-}
-
-
-#ifndef SQLITE_OMIT_INCRBLOB
-/*
-** Close all incrblob channels opened using database connection pDb.
-** This is called when shutting down the database connection.
-*/
-static void closeIncrblobChannels(SqliteDb *pDb){
- IncrblobChannel *p;
- IncrblobChannel *pNext;
-
- for(p=pDb->pIncrblob; p; p=pNext){
- pNext = p->pNext;
-
- /* Note: Calling unregister here call Tcl_Close on the incrblob channel,
- ** which deletes the IncrblobChannel structure at *p. So do not
- ** call Tcl_Free() here.
- */
- Tcl_UnregisterChannel(pDb->interp, p->channel);
- }
-}
-
-/*
-** Close an incremental blob channel.
-*/
-static int SQLITE_TCLAPI incrblobClose(
- ClientData instanceData,
- Tcl_Interp *interp
-){
- IncrblobChannel *p = (IncrblobChannel *)instanceData;
- int rc = sqlite3_blob_close(p->pBlob);
- sqlite3 *db = p->pDb->db;
-
- /* Remove the channel from the SqliteDb.pIncrblob list. */
- if( p->pNext ){
- p->pNext->pPrev = p->pPrev;
- }
- if( p->pPrev ){
- p->pPrev->pNext = p->pNext;
- }
- if( p->pDb->pIncrblob==p ){
- p->pDb->pIncrblob = p->pNext;
- }
-
- /* Free the IncrblobChannel structure */
- Tcl_Free((char *)p);
-
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Read data from an incremental blob channel.
-*/
-static int SQLITE_TCLAPI incrblobInput(
- ClientData instanceData,
- char *buf,
- int bufSize,
- int *errorCodePtr
-){
- IncrblobChannel *p = (IncrblobChannel *)instanceData;
- int nRead = bufSize; /* Number of bytes to read */
- int nBlob; /* Total size of the blob */
- int rc; /* sqlite error code */
-
- nBlob = sqlite3_blob_bytes(p->pBlob);
- if( (p->iSeek+nRead)>nBlob ){
- nRead = nBlob-p->iSeek;
- }
- if( nRead<=0 ){
- return 0;
- }
-
- rc = sqlite3_blob_read(p->pBlob, (void *)buf, nRead, p->iSeek);
- if( rc!=SQLITE_OK ){
- *errorCodePtr = rc;
- return -1;
- }
-
- p->iSeek += nRead;
- return nRead;
-}
-
-/*
-** Write data to an incremental blob channel.
-*/
-static int SQLITE_TCLAPI incrblobOutput(
- ClientData instanceData,
- CONST char *buf,
- int toWrite,
- int *errorCodePtr
-){
- IncrblobChannel *p = (IncrblobChannel *)instanceData;
- int nWrite = toWrite; /* Number of bytes to write */
- int nBlob; /* Total size of the blob */
- int rc; /* sqlite error code */
-
- nBlob = sqlite3_blob_bytes(p->pBlob);
- if( (p->iSeek+nWrite)>nBlob ){
- *errorCodePtr = EINVAL;
- return -1;
- }
- if( nWrite<=0 ){
- return 0;
- }
-
- rc = sqlite3_blob_write(p->pBlob, (void *)buf, nWrite, p->iSeek);
- if( rc!=SQLITE_OK ){
- *errorCodePtr = EIO;
- return -1;
- }
-
- p->iSeek += nWrite;
- return nWrite;
-}
-
-/*
-** Seek an incremental blob channel.
-*/
-static int SQLITE_TCLAPI incrblobSeek(
- ClientData instanceData,
- long offset,
- int seekMode,
- int *errorCodePtr
-){
- IncrblobChannel *p = (IncrblobChannel *)instanceData;
-
- switch( seekMode ){
- case SEEK_SET:
- p->iSeek = offset;
- break;
- case SEEK_CUR:
- p->iSeek += offset;
- break;
- case SEEK_END:
- p->iSeek = sqlite3_blob_bytes(p->pBlob) + offset;
- break;
-
- default: assert(!"Bad seekMode");
- }
-
- return p->iSeek;
-}
-
-
-static void SQLITE_TCLAPI incrblobWatch(
- ClientData instanceData,
- int mode
-){
- /* NO-OP */
-}
-static int SQLITE_TCLAPI incrblobHandle(
- ClientData instanceData,
- int dir,
- ClientData *hPtr
-){
- return TCL_ERROR;
-}
-
-static Tcl_ChannelType IncrblobChannelType = {
- "incrblob", /* typeName */
- TCL_CHANNEL_VERSION_2, /* version */
- incrblobClose, /* closeProc */
- incrblobInput, /* inputProc */
- incrblobOutput, /* outputProc */
- incrblobSeek, /* seekProc */
- 0, /* setOptionProc */
- 0, /* getOptionProc */
- incrblobWatch, /* watchProc (this is a no-op) */
- incrblobHandle, /* getHandleProc (always returns error) */
- 0, /* close2Proc */
- 0, /* blockModeProc */
- 0, /* flushProc */
- 0, /* handlerProc */
- 0, /* wideSeekProc */
-};
-
-/*
-** Create a new incrblob channel.
-*/
-static int createIncrblobChannel(
- Tcl_Interp *interp,
- SqliteDb *pDb,
- const char *zDb,
- const char *zTable,
- const char *zColumn,
- sqlite_int64 iRow,
- int isReadonly
-){
- IncrblobChannel *p;
- sqlite3 *db = pDb->db;
- sqlite3_blob *pBlob;
- int rc;
- int flags = TCL_READABLE|(isReadonly ? 0 : TCL_WRITABLE);
-
- /* This variable is used to name the channels: "incrblob_[incr count]" */
- static int count = 0;
- char zChannel[64];
-
- rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob);
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
- return TCL_ERROR;
- }
-
- p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel));
- p->iSeek = 0;
- p->pBlob = pBlob;
-
- sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count);
- p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags);
- Tcl_RegisterChannel(interp, p->channel);
-
- /* Link the new channel into the SqliteDb.pIncrblob list. */
- p->pNext = pDb->pIncrblob;
- p->pPrev = 0;
- if( p->pNext ){
- p->pNext->pPrev = p;
- }
- pDb->pIncrblob = p;
- p->pDb = pDb;
-
- Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE);
- return TCL_OK;
-}
-#else /* else clause for "#ifndef SQLITE_OMIT_INCRBLOB" */
- #define closeIncrblobChannels(pDb)
-#endif
-
-/*
-** Look at the script prefix in pCmd. We will be executing this script
-** after first appending one or more arguments. This routine analyzes
-** the script to see if it is safe to use Tcl_EvalObjv() on the script
-** rather than the more general Tcl_EvalEx(). Tcl_EvalObjv() is much
-** faster.
-**
-** Scripts that are safe to use with Tcl_EvalObjv() consists of a
-** command name followed by zero or more arguments with no [...] or $
-** or {...} or ; to be seen anywhere. Most callback scripts consist
-** of just a single procedure name and they meet this requirement.
-*/
-static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){
- /* We could try to do something with Tcl_Parse(). But we will instead
- ** just do a search for forbidden characters. If any of the forbidden
- ** characters appear in pCmd, we will report the string as unsafe.
- */
- const char *z;
- int n;
- z = Tcl_GetStringFromObj(pCmd, &n);
- while( n-- > 0 ){
- int c = *(z++);
- if( c=='$' || c=='[' || c==';' ) return 0;
- }
- return 1;
-}
-
-/*
-** Find an SqlFunc structure with the given name. Or create a new
-** one if an existing one cannot be found. Return a pointer to the
-** structure.
-*/
-static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
- SqlFunc *p, *pNew;
- int nName = strlen30(zName);
- pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + nName + 1 );
- pNew->zName = (char*)&pNew[1];
- memcpy(pNew->zName, zName, nName+1);
- for(p=pDb->pFunc; p; p=p->pNext){
- if( sqlite3_stricmp(p->zName, pNew->zName)==0 ){
- Tcl_Free((char*)pNew);
- return p;
- }
- }
- pNew->interp = pDb->interp;
- pNew->pDb = pDb;
- pNew->pScript = 0;
- pNew->pNext = pDb->pFunc;
- pDb->pFunc = pNew;
- return pNew;
-}
-
-/*
-** Free a single SqlPreparedStmt object.
-*/
-static void dbFreeStmt(SqlPreparedStmt *pStmt){
-#ifdef SQLITE_TEST
- if( sqlite3_sql(pStmt->pStmt)==0 ){
- Tcl_Free((char *)pStmt->zSql);
- }
-#endif
- sqlite3_finalize(pStmt->pStmt);
- Tcl_Free((char *)pStmt);
-}
-
-/*
-** Finalize and free a list of prepared statements
-*/
-static void flushStmtCache(SqliteDb *pDb){
- SqlPreparedStmt *pPreStmt;
- SqlPreparedStmt *pNext;
-
- for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pNext){
- pNext = pPreStmt->pNext;
- dbFreeStmt(pPreStmt);
- }
- pDb->nStmt = 0;
- pDb->stmtLast = 0;
- pDb->stmtList = 0;
-}
-
-/*
-** TCL calls this procedure when an sqlite3 database command is
-** deleted.
-*/
-static void SQLITE_TCLAPI DbDeleteCmd(void *db){
- SqliteDb *pDb = (SqliteDb*)db;
- flushStmtCache(pDb);
- closeIncrblobChannels(pDb);
- sqlite3_close(pDb->db);
- while( pDb->pFunc ){
- SqlFunc *pFunc = pDb->pFunc;
- pDb->pFunc = pFunc->pNext;
- assert( pFunc->pDb==pDb );
- Tcl_DecrRefCount(pFunc->pScript);
- Tcl_Free((char*)pFunc);
- }
- while( pDb->pCollate ){
- SqlCollate *pCollate = pDb->pCollate;
- pDb->pCollate = pCollate->pNext;
- Tcl_Free((char*)pCollate);
- }
- if( pDb->zBusy ){
- Tcl_Free(pDb->zBusy);
- }
- if( pDb->zTrace ){
- Tcl_Free(pDb->zTrace);
- }
- if( pDb->zTraceV2 ){
- Tcl_Free(pDb->zTraceV2);
- }
- if( pDb->zProfile ){
- Tcl_Free(pDb->zProfile);
- }
- if( pDb->zAuth ){
- Tcl_Free(pDb->zAuth);
- }
- if( pDb->zNull ){
- Tcl_Free(pDb->zNull);
- }
- if( pDb->pUpdateHook ){
- Tcl_DecrRefCount(pDb->pUpdateHook);
- }
- if( pDb->pPreUpdateHook ){
- Tcl_DecrRefCount(pDb->pPreUpdateHook);
- }
- if( pDb->pRollbackHook ){
- Tcl_DecrRefCount(pDb->pRollbackHook);
- }
- if( pDb->pWalHook ){
- Tcl_DecrRefCount(pDb->pWalHook);
- }
- if( pDb->pCollateNeeded ){
- Tcl_DecrRefCount(pDb->pCollateNeeded);
- }
- Tcl_Free((char*)pDb);
-}
-
-/*
-** This routine is called when a database file is locked while trying
-** to execute SQL.
-*/
-static int DbBusyHandler(void *cd, int nTries){
- SqliteDb *pDb = (SqliteDb*)cd;
- int rc;
- char zVal[30];
-
- sqlite3_snprintf(sizeof(zVal), zVal, "%d", nTries);
- rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0);
- if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
- return 0;
- }
- return 1;
-}
-
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
-/*
-** This routine is invoked as the 'progress callback' for the database.
-*/
-static int DbProgressHandler(void *cd){
- SqliteDb *pDb = (SqliteDb*)cd;
- int rc;
-
- assert( pDb->zProgress );
- rc = Tcl_Eval(pDb->interp, pDb->zProgress);
- if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
- return 1;
- }
- return 0;
-}
-#endif
-
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
- !defined(SQLITE_OMIT_DEPRECATED)
-/*
-** This routine is called by the SQLite trace handler whenever a new
-** block of SQL is executed. The TCL script in pDb->zTrace is executed.
-*/
-static void DbTraceHandler(void *cd, const char *zSql){
- SqliteDb *pDb = (SqliteDb*)cd;
- Tcl_DString str;
-
- Tcl_DStringInit(&str);
- Tcl_DStringAppend(&str, pDb->zTrace, -1);
- Tcl_DStringAppendElement(&str, zSql);
- Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
- Tcl_DStringFree(&str);
- Tcl_ResetResult(pDb->interp);
-}
-#endif
-
-#ifndef SQLITE_OMIT_TRACE
-/*
-** This routine is called by the SQLite trace_v2 handler whenever a new
-** supported event is generated. Unsupported event types are ignored.
-** The TCL script in pDb->zTraceV2 is executed, with the arguments for
-** the event appended to it (as list elements).
-*/
-static int DbTraceV2Handler(
- unsigned type, /* One of the SQLITE_TRACE_* event types. */
- void *cd, /* The original context data pointer. */
- void *pd, /* Primary event data, depends on event type. */
- void *xd /* Extra event data, depends on event type. */
-){
- SqliteDb *pDb = (SqliteDb*)cd;
- Tcl_Obj *pCmd;
-
- switch( type ){
- case SQLITE_TRACE_STMT: {
- sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
- char *zSql = (char *)xd;
-
- pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
- Tcl_IncrRefCount(pCmd);
- Tcl_ListObjAppendElement(pDb->interp, pCmd,
- Tcl_NewWideIntObj((Tcl_WideInt)pStmt));
- Tcl_ListObjAppendElement(pDb->interp, pCmd,
- Tcl_NewStringObj(zSql, -1));
- Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pCmd);
- Tcl_ResetResult(pDb->interp);
- break;
- }
- case SQLITE_TRACE_PROFILE: {
- sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
- sqlite3_int64 ns = *(sqlite3_int64*)xd;
-
- pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
- Tcl_IncrRefCount(pCmd);
- Tcl_ListObjAppendElement(pDb->interp, pCmd,
- Tcl_NewWideIntObj((Tcl_WideInt)pStmt));
- Tcl_ListObjAppendElement(pDb->interp, pCmd,
- Tcl_NewWideIntObj((Tcl_WideInt)ns));
- Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pCmd);
- Tcl_ResetResult(pDb->interp);
- break;
- }
- case SQLITE_TRACE_ROW: {
- sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
-
- pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
- Tcl_IncrRefCount(pCmd);
- Tcl_ListObjAppendElement(pDb->interp, pCmd,
- Tcl_NewWideIntObj((Tcl_WideInt)pStmt));
- Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pCmd);
- Tcl_ResetResult(pDb->interp);
- break;
- }
- case SQLITE_TRACE_CLOSE: {
- sqlite3 *db = (sqlite3 *)pd;
-
- pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
- Tcl_IncrRefCount(pCmd);
- Tcl_ListObjAppendElement(pDb->interp, pCmd,
- Tcl_NewWideIntObj((Tcl_WideInt)db));
- Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pCmd);
- Tcl_ResetResult(pDb->interp);
- break;
- }
- }
- return SQLITE_OK;
-}
-#endif
-
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
- !defined(SQLITE_OMIT_DEPRECATED)
-/*
-** This routine is called by the SQLite profile handler after a statement
-** SQL has executed. The TCL script in pDb->zProfile is evaluated.
-*/
-static void DbProfileHandler(void *cd, const char *zSql, sqlite_uint64 tm){
- SqliteDb *pDb = (SqliteDb*)cd;
- Tcl_DString str;
- char zTm[100];
-
- sqlite3_snprintf(sizeof(zTm)-1, zTm, "%lld", tm);
- Tcl_DStringInit(&str);
- Tcl_DStringAppend(&str, pDb->zProfile, -1);
- Tcl_DStringAppendElement(&str, zSql);
- Tcl_DStringAppendElement(&str, zTm);
- Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
- Tcl_DStringFree(&str);
- Tcl_ResetResult(pDb->interp);
-}
-#endif
-
-/*
-** This routine is called when a transaction is committed. The
-** TCL script in pDb->zCommit is executed. If it returns non-zero or
-** if it throws an exception, the transaction is rolled back instead
-** of being committed.
-*/
-static int DbCommitHandler(void *cd){
- SqliteDb *pDb = (SqliteDb*)cd;
- int rc;
-
- rc = Tcl_Eval(pDb->interp, pDb->zCommit);
- if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
- return 1;
- }
- return 0;
-}
-
-static void DbRollbackHandler(void *clientData){
- SqliteDb *pDb = (SqliteDb*)clientData;
- assert(pDb->pRollbackHook);
- if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){
- Tcl_BackgroundError(pDb->interp);
- }
-}
-
-/*
-** This procedure handles wal_hook callbacks.
-*/
-static int DbWalHandler(
- void *clientData,
- sqlite3 *db,
- const char *zDb,
- int nEntry
-){
- int ret = SQLITE_OK;
- Tcl_Obj *p;
- SqliteDb *pDb = (SqliteDb*)clientData;
- Tcl_Interp *interp = pDb->interp;
- assert(pDb->pWalHook);
-
- assert( db==pDb->db );
- p = Tcl_DuplicateObj(pDb->pWalHook);
- Tcl_IncrRefCount(p);
- Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1));
- Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry));
- if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0)
- || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret)
- ){
- Tcl_BackgroundError(interp);
- }
- Tcl_DecrRefCount(p);
-
- return ret;
-}
-
-#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
-static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){
- char zBuf[64];
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iArg);
- Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nArg);
- Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY);
-}
-#else
-# define setTestUnlockNotifyVars(x,y,z)
-#endif
-
-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
-static void DbUnlockNotify(void **apArg, int nArg){
- int i;
- for(i=0; i<nArg; i++){
- const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
- SqliteDb *pDb = (SqliteDb *)apArg[i];
- setTestUnlockNotifyVars(pDb->interp, i, nArg);
- assert( pDb->pUnlockNotify);
- Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags);
- Tcl_DecrRefCount(pDb->pUnlockNotify);
- pDb->pUnlockNotify = 0;
- }
-}
-#endif
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-/*
-** Pre-update hook callback.
-*/
-static void DbPreUpdateHandler(
- void *p,
- sqlite3 *db,
- int op,
- const char *zDb,
- const char *zTbl,
- sqlite_int64 iKey1,
- sqlite_int64 iKey2
-){
- SqliteDb *pDb = (SqliteDb *)p;
- Tcl_Obj *pCmd;
- static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"};
-
- assert( (SQLITE_DELETE-1)/9 == 0 );
- assert( (SQLITE_INSERT-1)/9 == 1 );
- assert( (SQLITE_UPDATE-1)/9 == 2 );
- assert( pDb->pPreUpdateHook );
- assert( db==pDb->db );
- assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
-
- pCmd = Tcl_DuplicateObj(pDb->pPreUpdateHook);
- Tcl_IncrRefCount(pCmd);
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey1));
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey2));
- Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pCmd);
-}
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
-
-static void DbUpdateHandler(
- void *p,
- int op,
- const char *zDb,
- const char *zTbl,
- sqlite_int64 rowid
-){
- SqliteDb *pDb = (SqliteDb *)p;
- Tcl_Obj *pCmd;
- static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"};
-
- assert( (SQLITE_DELETE-1)/9 == 0 );
- assert( (SQLITE_INSERT-1)/9 == 1 );
- assert( (SQLITE_UPDATE-1)/9 == 2 );
-
- assert( pDb->pUpdateHook );
- assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
-
- pCmd = Tcl_DuplicateObj(pDb->pUpdateHook);
- Tcl_IncrRefCount(pCmd);
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
- Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid));
- Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pCmd);
-}
-
-static void tclCollateNeeded(
- void *pCtx,
- sqlite3 *db,
- int enc,
- const char *zName
-){
- SqliteDb *pDb = (SqliteDb *)pCtx;
- Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded);
- Tcl_IncrRefCount(pScript);
- Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1));
- Tcl_EvalObjEx(pDb->interp, pScript, 0);
- Tcl_DecrRefCount(pScript);
-}
-
-/*
-** This routine is called to evaluate an SQL collation function implemented
-** using TCL script.
-*/
-static int tclSqlCollate(
- void *pCtx,
- int nA,
- const void *zA,
- int nB,
- const void *zB
-){
- SqlCollate *p = (SqlCollate *)pCtx;
- Tcl_Obj *pCmd;
-
- pCmd = Tcl_NewStringObj(p->zScript, -1);
- Tcl_IncrRefCount(pCmd);
- Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA));
- Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB));
- Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pCmd);
- return (atoi(Tcl_GetStringResult(p->interp)));
-}
-
-/*
-** This routine is called to evaluate an SQL function implemented
-** using TCL script.
-*/
-static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
- SqlFunc *p = sqlite3_user_data(context);
- Tcl_Obj *pCmd;
- int i;
- int rc;
-
- if( argc==0 ){
- /* If there are no arguments to the function, call Tcl_EvalObjEx on the
- ** script object directly. This allows the TCL compiler to generate
- ** bytecode for the command on the first invocation and thus make
- ** subsequent invocations much faster. */
- pCmd = p->pScript;
- Tcl_IncrRefCount(pCmd);
- rc = Tcl_EvalObjEx(p->interp, pCmd, 0);
- Tcl_DecrRefCount(pCmd);
- }else{
- /* If there are arguments to the function, make a shallow copy of the
- ** script object, lappend the arguments, then evaluate the copy.
- **
- ** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated.
- ** The new Tcl_Obj contains pointers to the original list elements.
- ** That way, when Tcl_EvalObjv() is run and shimmers the first element
- ** of the list to tclCmdNameType, that alternate representation will
- ** be preserved and reused on the next invocation.
- */
- Tcl_Obj **aArg;
- int nArg;
- if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){
- sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
- return;
- }
- pCmd = Tcl_NewListObj(nArg, aArg);
- Tcl_IncrRefCount(pCmd);
- for(i=0; i<argc; i++){
- sqlite3_value *pIn = argv[i];
- Tcl_Obj *pVal;
-
- /* Set pVal to contain the i'th column of this row. */
- switch( sqlite3_value_type(pIn) ){
- case SQLITE_BLOB: {
- int bytes = sqlite3_value_bytes(pIn);
- pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite_int64 v = sqlite3_value_int64(pIn);
- if( v>=-2147483647 && v<=2147483647 ){
- pVal = Tcl_NewIntObj((int)v);
- }else{
- pVal = Tcl_NewWideIntObj(v);
- }
- break;
- }
- case SQLITE_FLOAT: {
- double r = sqlite3_value_double(pIn);
- pVal = Tcl_NewDoubleObj(r);
- break;
- }
- case SQLITE_NULL: {
- pVal = Tcl_NewStringObj(p->pDb->zNull, -1);
- break;
- }
- default: {
- int bytes = sqlite3_value_bytes(pIn);
- pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes);
- break;
- }
- }
- rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal);
- if( rc ){
- Tcl_DecrRefCount(pCmd);
- sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
- return;
- }
- }
- if( !p->useEvalObjv ){
- /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd
- ** is a list without a string representation. To prevent this from
- ** happening, make sure pCmd has a valid string representation */
- Tcl_GetString(pCmd);
- }
- rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pCmd);
- }
-
- if( rc && rc!=TCL_RETURN ){
- sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
- }else{
- Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
- int n;
- u8 *data;
- const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
- char c = zType[0];
- if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
- /* Only return a BLOB type if the Tcl variable is a bytearray and
- ** has no string representation. */
- data = Tcl_GetByteArrayFromObj(pVar, &n);
- sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
- }else if( c=='b' && strcmp(zType,"boolean")==0 ){
- Tcl_GetIntFromObj(0, pVar, &n);
- sqlite3_result_int(context, n);
- }else if( c=='d' && strcmp(zType,"double")==0 ){
- double r;
- Tcl_GetDoubleFromObj(0, pVar, &r);
- sqlite3_result_double(context, r);
- }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
- (c=='i' && strcmp(zType,"int")==0) ){
- Tcl_WideInt v;
- Tcl_GetWideIntFromObj(0, pVar, &v);
- sqlite3_result_int64(context, v);
- }else{
- data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
- sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT);
- }
- }
-}
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
-/*
-** This is the authentication function. It appends the authentication
-** type code and the two arguments to zCmd[] then invokes the result
-** on the interpreter. The reply is examined to determine if the
-** authentication fails or succeeds.
-*/
-static int auth_callback(
- void *pArg,
- int code,
- const char *zArg1,
- const char *zArg2,
- const char *zArg3,
- const char *zArg4
-#ifdef SQLITE_USER_AUTHENTICATION
- ,const char *zArg5
-#endif
-){
- const char *zCode;
- Tcl_DString str;
- int rc;
- const char *zReply;
- /* EVIDENCE-OF: R-38590-62769 The first parameter to the authorizer
- ** callback is a copy of the third parameter to the
- ** sqlite3_set_authorizer() interface.
- */
- SqliteDb *pDb = (SqliteDb*)pArg;
- if( pDb->disableAuth ) return SQLITE_OK;
-
- /* EVIDENCE-OF: R-56518-44310 The second parameter to the callback is an
- ** integer action code that specifies the particular action to be
- ** authorized. */
- switch( code ){
- case SQLITE_COPY : zCode="SQLITE_COPY"; break;
- case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break;
- case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break;
- case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break;
- case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break;
- case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break;
- case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break;
- case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break;
- case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break;
- case SQLITE_DELETE : zCode="SQLITE_DELETE"; break;
- case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break;
- case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break;
- case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break;
- case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break;
- case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break;
- case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break;
- case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break;
- case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break;
- case SQLITE_INSERT : zCode="SQLITE_INSERT"; break;
- case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break;
- case SQLITE_READ : zCode="SQLITE_READ"; break;
- case SQLITE_SELECT : zCode="SQLITE_SELECT"; break;
- case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break;
- case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break;
- case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break;
- case SQLITE_DETACH : zCode="SQLITE_DETACH"; break;
- case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break;
- case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break;
- case SQLITE_ANALYZE : zCode="SQLITE_ANALYZE"; break;
- case SQLITE_CREATE_VTABLE : zCode="SQLITE_CREATE_VTABLE"; break;
- case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break;
- case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break;
- case SQLITE_SAVEPOINT : zCode="SQLITE_SAVEPOINT"; break;
- case SQLITE_RECURSIVE : zCode="SQLITE_RECURSIVE"; break;
- default : zCode="????"; break;
- }
- Tcl_DStringInit(&str);
- Tcl_DStringAppend(&str, pDb->zAuth, -1);
- Tcl_DStringAppendElement(&str, zCode);
- Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : "");
- Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
- Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
- Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
-#ifdef SQLITE_USER_AUTHENTICATION
- Tcl_DStringAppendElement(&str, zArg5 ? zArg5 : "");
-#endif
- rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
- Tcl_DStringFree(&str);
- zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
- if( strcmp(zReply,"SQLITE_OK")==0 ){
- rc = SQLITE_OK;
- }else if( strcmp(zReply,"SQLITE_DENY")==0 ){
- rc = SQLITE_DENY;
- }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){
- rc = SQLITE_IGNORE;
- }else{
- rc = 999;
- }
- return rc;
-}
-#endif /* SQLITE_OMIT_AUTHORIZATION */
-
-/*
-** This routine reads a line of text from FILE in, stores
-** the text in memory obtained from malloc() and returns a pointer
-** to the text. NULL is returned at end of file, or if malloc()
-** fails.
-**
-** The interface is like "readline" but no command-line editing
-** is done.
-**
-** copied from shell.c from '.import' command
-*/
-static char *local_getline(char *zPrompt, FILE *in){
- char *zLine;
- int nLine;
- int n;
-
- nLine = 100;
- zLine = malloc( nLine );
- if( zLine==0 ) return 0;
- n = 0;
- while( 1 ){
- if( n+100>nLine ){
- nLine = nLine*2 + 100;
- zLine = realloc(zLine, nLine);
- if( zLine==0 ) return 0;
- }
- if( fgets(&zLine[n], nLine - n, in)==0 ){
- if( n==0 ){
- free(zLine);
- return 0;
- }
- zLine[n] = 0;
- break;
- }
- while( zLine[n] ){ n++; }
- if( n>0 && zLine[n-1]=='\n' ){
- n--;
- zLine[n] = 0;
- break;
- }
- }
- zLine = realloc( zLine, n+1 );
- return zLine;
-}
-
-
-/*
-** This function is part of the implementation of the command:
-**
-** $db transaction [-deferred|-immediate|-exclusive] SCRIPT
-**
-** It is invoked after evaluating the script SCRIPT to commit or rollback
-** the transaction or savepoint opened by the [transaction] command.
-*/
-static int SQLITE_TCLAPI DbTransPostCmd(
- ClientData data[], /* data[0] is the Sqlite3Db* for $db */
- Tcl_Interp *interp, /* Tcl interpreter */
- int result /* Result of evaluating SCRIPT */
-){
- static const char *const azEnd[] = {
- "RELEASE _tcl_transaction", /* rc==TCL_ERROR, nTransaction!=0 */
- "COMMIT", /* rc!=TCL_ERROR, nTransaction==0 */
- "ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction",
- "ROLLBACK" /* rc==TCL_ERROR, nTransaction==0 */
- };
- SqliteDb *pDb = (SqliteDb*)data[0];
- int rc = result;
- const char *zEnd;
-
- pDb->nTransaction--;
- zEnd = azEnd[(rc==TCL_ERROR)*2 + (pDb->nTransaction==0)];
-
- pDb->disableAuth++;
- if( sqlite3_exec(pDb->db, zEnd, 0, 0, 0) ){
- /* This is a tricky scenario to handle. The most likely cause of an
- ** error is that the exec() above was an attempt to commit the
- ** top-level transaction that returned SQLITE_BUSY. Or, less likely,
- ** that an IO-error has occurred. In either case, throw a Tcl exception
- ** and try to rollback the transaction.
- **
- ** But it could also be that the user executed one or more BEGIN,
- ** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing
- ** this method's logic. Not clear how this would be best handled.
- */
- if( rc!=TCL_ERROR ){
- Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
- rc = TCL_ERROR;
- }
- sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
- }
- pDb->disableAuth--;
-
- return rc;
-}
-
-/*
-** Unless SQLITE_TEST is defined, this function is a simple wrapper around
-** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either
-** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending
-** on whether or not the [db_use_legacy_prepare] command has been used to
-** configure the connection.
-*/
-static int dbPrepare(
- SqliteDb *pDb, /* Database object */
- const char *zSql, /* SQL to compile */
- sqlite3_stmt **ppStmt, /* OUT: Prepared statement */
- const char **pzOut /* OUT: Pointer to next SQL statement */
-){
- unsigned int prepFlags = 0;
-#ifdef SQLITE_TEST
- if( pDb->bLegacyPrepare ){
- return sqlite3_prepare(pDb->db, zSql, -1, ppStmt, pzOut);
- }
-#endif
- /* If the statement cache is large, use the SQLITE_PREPARE_PERSISTENT
- ** flags, which uses less lookaside memory. But if the cache is small,
- ** omit that flag to make full use of lookaside */
- if( pDb->maxStmt>5 ) prepFlags = SQLITE_PREPARE_PERSISTENT;
-
- return sqlite3_prepare_v3(pDb->db, zSql, -1, prepFlags, ppStmt, pzOut);
-}
-
-/*
-** Search the cache for a prepared-statement object that implements the
-** first SQL statement in the buffer pointed to by parameter zIn. If
-** no such prepared-statement can be found, allocate and prepare a new
-** one. In either case, bind the current values of the relevant Tcl
-** variables to any $var, :var or @var variables in the statement. Before
-** returning, set *ppPreStmt to point to the prepared-statement object.
-**
-** Output parameter *pzOut is set to point to the next SQL statement in
-** buffer zIn, or to the '\0' byte at the end of zIn if there is no
-** next statement.
-**
-** If successful, TCL_OK is returned. Otherwise, TCL_ERROR is returned
-** and an error message loaded into interpreter pDb->interp.
-*/
-static int dbPrepareAndBind(
- SqliteDb *pDb, /* Database object */
- char const *zIn, /* SQL to compile */
- char const **pzOut, /* OUT: Pointer to next SQL statement */
- SqlPreparedStmt **ppPreStmt /* OUT: Object used to cache statement */
-){
- const char *zSql = zIn; /* Pointer to first SQL statement in zIn */
- sqlite3_stmt *pStmt = 0; /* Prepared statement object */
- SqlPreparedStmt *pPreStmt; /* Pointer to cached statement */
- int nSql; /* Length of zSql in bytes */
- int nVar = 0; /* Number of variables in statement */
- int iParm = 0; /* Next free entry in apParm */
- char c;
- int i;
- Tcl_Interp *interp = pDb->interp;
-
- *ppPreStmt = 0;
-
- /* Trim spaces from the start of zSql and calculate the remaining length. */
- while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; }
- nSql = strlen30(zSql);
-
- for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){
- int n = pPreStmt->nSql;
- if( nSql>=n
- && memcmp(pPreStmt->zSql, zSql, n)==0
- && (zSql[n]==0 || zSql[n-1]==';')
- ){
- pStmt = pPreStmt->pStmt;
- *pzOut = &zSql[pPreStmt->nSql];
-
- /* When a prepared statement is found, unlink it from the
- ** cache list. It will later be added back to the beginning
- ** of the cache list in order to implement LRU replacement.
- */
- if( pPreStmt->pPrev ){
- pPreStmt->pPrev->pNext = pPreStmt->pNext;
- }else{
- pDb->stmtList = pPreStmt->pNext;
- }
- if( pPreStmt->pNext ){
- pPreStmt->pNext->pPrev = pPreStmt->pPrev;
- }else{
- pDb->stmtLast = pPreStmt->pPrev;
- }
- pDb->nStmt--;
- nVar = sqlite3_bind_parameter_count(pStmt);
- break;
- }
- }
-
- /* If no prepared statement was found. Compile the SQL text. Also allocate
- ** a new SqlPreparedStmt structure. */
- if( pPreStmt==0 ){
- int nByte;
-
- if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
- return TCL_ERROR;
- }
- if( pStmt==0 ){
- if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
- /* A compile-time error in the statement. */
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
- return TCL_ERROR;
- }else{
- /* The statement was a no-op. Continue to the next statement
- ** in the SQL string.
- */
- return TCL_OK;
- }
- }
-
- assert( pPreStmt==0 );
- nVar = sqlite3_bind_parameter_count(pStmt);
- nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *);
- pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte);
- memset(pPreStmt, 0, nByte);
-
- pPreStmt->pStmt = pStmt;
- pPreStmt->nSql = (int)(*pzOut - zSql);
- pPreStmt->zSql = sqlite3_sql(pStmt);
- pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1];
-#ifdef SQLITE_TEST
- if( pPreStmt->zSql==0 ){
- char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1);
- memcpy(zCopy, zSql, pPreStmt->nSql);
- zCopy[pPreStmt->nSql] = '\0';
- pPreStmt->zSql = zCopy;
- }
-#endif
- }
- assert( pPreStmt );
- assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql );
- assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) );
-
- /* Bind values to parameters that begin with $ or : */
- for(i=1; i<=nVar; i++){
- const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
- if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
- Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
- if( pVar ){
- int n;
- u8 *data;
- const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
- c = zType[0];
- if( zVar[0]=='@' ||
- (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){
- /* Load a BLOB type if the Tcl variable is a bytearray and
- ** it has no string representation or the host
- ** parameter name begins with "@". */
- data = Tcl_GetByteArrayFromObj(pVar, &n);
- sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);
- Tcl_IncrRefCount(pVar);
- pPreStmt->apParm[iParm++] = pVar;
- }else if( c=='b' && strcmp(zType,"boolean")==0 ){
- Tcl_GetIntFromObj(interp, pVar, &n);
- sqlite3_bind_int(pStmt, i, n);
- }else if( c=='d' && strcmp(zType,"double")==0 ){
- double r;
- Tcl_GetDoubleFromObj(interp, pVar, &r);
- sqlite3_bind_double(pStmt, i, r);
- }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
- (c=='i' && strcmp(zType,"int")==0) ){
- Tcl_WideInt v;
- Tcl_GetWideIntFromObj(interp, pVar, &v);
- sqlite3_bind_int64(pStmt, i, v);
- }else{
- data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
- sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC);
- Tcl_IncrRefCount(pVar);
- pPreStmt->apParm[iParm++] = pVar;
- }
- }else{
- sqlite3_bind_null(pStmt, i);
- }
- }
- }
- pPreStmt->nParm = iParm;
- *ppPreStmt = pPreStmt;
-
- return TCL_OK;
-}
-
-/*
-** Release a statement reference obtained by calling dbPrepareAndBind().
-** There should be exactly one call to this function for each call to
-** dbPrepareAndBind().
-**
-** If the discard parameter is non-zero, then the statement is deleted
-** immediately. Otherwise it is added to the LRU list and may be returned
-** by a subsequent call to dbPrepareAndBind().
-*/
-static void dbReleaseStmt(
- SqliteDb *pDb, /* Database handle */
- SqlPreparedStmt *pPreStmt, /* Prepared statement handle to release */
- int discard /* True to delete (not cache) the pPreStmt */
-){
- int i;
-
- /* Free the bound string and blob parameters */
- for(i=0; i<pPreStmt->nParm; i++){
- Tcl_DecrRefCount(pPreStmt->apParm[i]);
- }
- pPreStmt->nParm = 0;
-
- if( pDb->maxStmt<=0 || discard ){
- /* If the cache is turned off, deallocated the statement */
- dbFreeStmt(pPreStmt);
- }else{
- /* Add the prepared statement to the beginning of the cache list. */
- pPreStmt->pNext = pDb->stmtList;
- pPreStmt->pPrev = 0;
- if( pDb->stmtList ){
- pDb->stmtList->pPrev = pPreStmt;
- }
- pDb->stmtList = pPreStmt;
- if( pDb->stmtLast==0 ){
- assert( pDb->nStmt==0 );
- pDb->stmtLast = pPreStmt;
- }else{
- assert( pDb->nStmt>0 );
- }
- pDb->nStmt++;
-
- /* If we have too many statement in cache, remove the surplus from
- ** the end of the cache list. */
- while( pDb->nStmt>pDb->maxStmt ){
- SqlPreparedStmt *pLast = pDb->stmtLast;
- pDb->stmtLast = pLast->pPrev;
- pDb->stmtLast->pNext = 0;
- pDb->nStmt--;
- dbFreeStmt(pLast);
- }
- }
-}
-
-/*
-** Structure used with dbEvalXXX() functions:
-**
-** dbEvalInit()
-** dbEvalStep()
-** dbEvalFinalize()
-** dbEvalRowInfo()
-** dbEvalColumnValue()
-*/
-typedef struct DbEvalContext DbEvalContext;
-struct DbEvalContext {
- SqliteDb *pDb; /* Database handle */
- Tcl_Obj *pSql; /* Object holding string zSql */
- const char *zSql; /* Remaining SQL to execute */
- SqlPreparedStmt *pPreStmt; /* Current statement */
- int nCol; /* Number of columns returned by pStmt */
- int evalFlags; /* Flags used */
- Tcl_Obj *pArray; /* Name of array variable */
- Tcl_Obj **apColName; /* Array of column names */
-};
-
-#define SQLITE_EVAL_WITHOUTNULLS 0x00001 /* Unset array(*) for NULL */
-
-/*
-** Release any cache of column names currently held as part of
-** the DbEvalContext structure passed as the first argument.
-*/
-static void dbReleaseColumnNames(DbEvalContext *p){
- if( p->apColName ){
- int i;
- for(i=0; i<p->nCol; i++){
- Tcl_DecrRefCount(p->apColName[i]);
- }
- Tcl_Free((char *)p->apColName);
- p->apColName = 0;
- }
- p->nCol = 0;
-}
-
-/*
-** Initialize a DbEvalContext structure.
-**
-** If pArray is not NULL, then it contains the name of a Tcl array
-** variable. The "*" member of this array is set to a list containing
-** the names of the columns returned by the statement as part of each
-** call to dbEvalStep(), in order from left to right. e.g. if the names
-** of the returned columns are a, b and c, it does the equivalent of the
-** tcl command:
-**
-** set ${pArray}(*) {a b c}
-*/
-static void dbEvalInit(
- DbEvalContext *p, /* Pointer to structure to initialize */
- SqliteDb *pDb, /* Database handle */
- Tcl_Obj *pSql, /* Object containing SQL script */
- Tcl_Obj *pArray, /* Name of Tcl array to set (*) element of */
- int evalFlags /* Flags controlling evaluation */
-){
- memset(p, 0, sizeof(DbEvalContext));
- p->pDb = pDb;
- p->zSql = Tcl_GetString(pSql);
- p->pSql = pSql;
- Tcl_IncrRefCount(pSql);
- if( pArray ){
- p->pArray = pArray;
- Tcl_IncrRefCount(pArray);
- }
- p->evalFlags = evalFlags;
-}
-
-/*
-** Obtain information about the row that the DbEvalContext passed as the
-** first argument currently points to.
-*/
-static void dbEvalRowInfo(
- DbEvalContext *p, /* Evaluation context */
- int *pnCol, /* OUT: Number of column names */
- Tcl_Obj ***papColName /* OUT: Array of column names */
-){
- /* Compute column names */
- if( 0==p->apColName ){
- sqlite3_stmt *pStmt = p->pPreStmt->pStmt;
- int i; /* Iterator variable */
- int nCol; /* Number of columns returned by pStmt */
- Tcl_Obj **apColName = 0; /* Array of column names */
-
- p->nCol = nCol = sqlite3_column_count(pStmt);
- if( nCol>0 && (papColName || p->pArray) ){
- apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
- for(i=0; i<nCol; i++){
- apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
- Tcl_IncrRefCount(apColName[i]);
- }
- p->apColName = apColName;
- }
-
- /* If results are being stored in an array variable, then create
- ** the array(*) entry for that array
- */
- if( p->pArray ){
- Tcl_Interp *interp = p->pDb->interp;
- Tcl_Obj *pColList = Tcl_NewObj();
- Tcl_Obj *pStar = Tcl_NewStringObj("*", -1);
-
- for(i=0; i<nCol; i++){
- Tcl_ListObjAppendElement(interp, pColList, apColName[i]);
- }
- Tcl_IncrRefCount(pStar);
- Tcl_ObjSetVar2(interp, p->pArray, pStar, pColList, 0);
- Tcl_DecrRefCount(pStar);
- }
- }
-
- if( papColName ){
- *papColName = p->apColName;
- }
- if( pnCol ){
- *pnCol = p->nCol;
- }
-}
-
-/*
-** Return one of TCL_OK, TCL_BREAK or TCL_ERROR. If TCL_ERROR is
-** returned, then an error message is stored in the interpreter before
-** returning.
-**
-** A return value of TCL_OK means there is a row of data available. The
-** data may be accessed using dbEvalRowInfo() and dbEvalColumnValue(). This
-** is analogous to a return of SQLITE_ROW from sqlite3_step(). If TCL_BREAK
-** is returned, then the SQL script has finished executing and there are
-** no further rows available. This is similar to SQLITE_DONE.
-*/
-static int dbEvalStep(DbEvalContext *p){
- const char *zPrevSql = 0; /* Previous value of p->zSql */
-
- while( p->zSql[0] || p->pPreStmt ){
- int rc;
- if( p->pPreStmt==0 ){
- zPrevSql = (p->zSql==zPrevSql ? 0 : p->zSql);
- rc = dbPrepareAndBind(p->pDb, p->zSql, &p->zSql, &p->pPreStmt);
- if( rc!=TCL_OK ) return rc;
- }else{
- int rcs;
- SqliteDb *pDb = p->pDb;
- SqlPreparedStmt *pPreStmt = p->pPreStmt;
- sqlite3_stmt *pStmt = pPreStmt->pStmt;
-
- rcs = sqlite3_step(pStmt);
- if( rcs==SQLITE_ROW ){
- return TCL_OK;
- }
- if( p->pArray ){
- dbEvalRowInfo(p, 0, 0);
- }
- rcs = sqlite3_reset(pStmt);
-
- pDb->nStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_FULLSCAN_STEP,1);
- pDb->nSort = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_SORT,1);
- pDb->nIndex = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_AUTOINDEX,1);
- pDb->nVMStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_VM_STEP,1);
- dbReleaseColumnNames(p);
- p->pPreStmt = 0;
-
- if( rcs!=SQLITE_OK ){
- /* If a run-time error occurs, report the error and stop reading
- ** the SQL. */
- dbReleaseStmt(pDb, pPreStmt, 1);
-#if SQLITE_TEST
- if( p->pDb->bLegacyPrepare && rcs==SQLITE_SCHEMA && zPrevSql ){
- /* If the runtime error was an SQLITE_SCHEMA, and the database
- ** handle is configured to use the legacy sqlite3_prepare()
- ** interface, retry prepare()/step() on the same SQL statement.
- ** This only happens once. If there is a second SQLITE_SCHEMA
- ** error, the error will be returned to the caller. */
- p->zSql = zPrevSql;
- continue;
- }
-#endif
- Tcl_SetObjResult(pDb->interp,
- Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
- return TCL_ERROR;
- }else{
- dbReleaseStmt(pDb, pPreStmt, 0);
- }
- }
- }
-
- /* Finished */
- return TCL_BREAK;
-}
-
-/*
-** Free all resources currently held by the DbEvalContext structure passed
-** as the first argument. There should be exactly one call to this function
-** for each call to dbEvalInit().
-*/
-static void dbEvalFinalize(DbEvalContext *p){
- if( p->pPreStmt ){
- sqlite3_reset(p->pPreStmt->pStmt);
- dbReleaseStmt(p->pDb, p->pPreStmt, 0);
- p->pPreStmt = 0;
- }
- if( p->pArray ){
- Tcl_DecrRefCount(p->pArray);
- p->pArray = 0;
- }
- Tcl_DecrRefCount(p->pSql);
- dbReleaseColumnNames(p);
-}
-
-/*
-** Return a pointer to a Tcl_Obj structure with ref-count 0 that contains
-** the value for the iCol'th column of the row currently pointed to by
-** the DbEvalContext structure passed as the first argument.
-*/
-static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){
- sqlite3_stmt *pStmt = p->pPreStmt->pStmt;
- switch( sqlite3_column_type(pStmt, iCol) ){
- case SQLITE_BLOB: {
- int bytes = sqlite3_column_bytes(pStmt, iCol);
- const char *zBlob = sqlite3_column_blob(pStmt, iCol);
- if( !zBlob ) bytes = 0;
- return Tcl_NewByteArrayObj((u8*)zBlob, bytes);
- }
- case SQLITE_INTEGER: {
- sqlite_int64 v = sqlite3_column_int64(pStmt, iCol);
- if( v>=-2147483647 && v<=2147483647 ){
- return Tcl_NewIntObj((int)v);
- }else{
- return Tcl_NewWideIntObj(v);
- }
- }
- case SQLITE_FLOAT: {
- return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol));
- }
- case SQLITE_NULL: {
- return Tcl_NewStringObj(p->pDb->zNull, -1);
- }
- }
-
- return Tcl_NewStringObj((char*)sqlite3_column_text(pStmt, iCol), -1);
-}
-
-/*
-** If using Tcl version 8.6 or greater, use the NR functions to avoid
-** recursive evalution of scripts by the [db eval] and [db trans]
-** commands. Even if the headers used while compiling the extension
-** are 8.6 or newer, the code still tests the Tcl version at runtime.
-** This allows stubs-enabled builds to be used with older Tcl libraries.
-*/
-#if TCL_MAJOR_VERSION>8 || (TCL_MAJOR_VERSION==8 && TCL_MINOR_VERSION>=6)
-# define SQLITE_TCL_NRE 1
-static int DbUseNre(void){
- int major, minor;
- Tcl_GetVersion(&major, &minor, 0, 0);
- return( (major==8 && minor>=6) || major>8 );
-}
-#else
-/*
-** Compiling using headers earlier than 8.6. In this case NR cannot be
-** used, so DbUseNre() to always return zero. Add #defines for the other
-** Tcl_NRxxx() functions to prevent them from causing compilation errors,
-** even though the only invocations of them are within conditional blocks
-** of the form:
-**
-** if( DbUseNre() ) { ... }
-*/
-# define SQLITE_TCL_NRE 0
-# define DbUseNre() 0
-# define Tcl_NRAddCallback(a,b,c,d,e,f) (void)0
-# define Tcl_NREvalObj(a,b,c) 0
-# define Tcl_NRCreateCommand(a,b,c,d,e,f) (void)0
-#endif
-
-/*
-** This function is part of the implementation of the command:
-**
-** $db eval SQL ?ARRAYNAME? SCRIPT
-*/
-static int SQLITE_TCLAPI DbEvalNextCmd(
- ClientData data[], /* data[0] is the (DbEvalContext*) */
- Tcl_Interp *interp, /* Tcl interpreter */
- int result /* Result so far */
-){
- int rc = result; /* Return code */
-
- /* The first element of the data[] array is a pointer to a DbEvalContext
- ** structure allocated using Tcl_Alloc(). The second element of data[]
- ** is a pointer to a Tcl_Obj containing the script to run for each row
- ** returned by the queries encapsulated in data[0]. */
- DbEvalContext *p = (DbEvalContext *)data[0];
- Tcl_Obj *pScript = (Tcl_Obj *)data[1];
- Tcl_Obj *pArray = p->pArray;
-
- while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){
- int i;
- int nCol;
- Tcl_Obj **apColName;
- dbEvalRowInfo(p, &nCol, &apColName);
- for(i=0; i<nCol; i++){
- if( pArray==0 ){
- Tcl_ObjSetVar2(interp, apColName[i], 0, dbEvalColumnValue(p,i), 0);
- }else if( (p->evalFlags & SQLITE_EVAL_WITHOUTNULLS)!=0
- && sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL
- ){
- Tcl_UnsetVar2(interp, Tcl_GetString(pArray),
- Tcl_GetString(apColName[i]), 0);
- }else{
- Tcl_ObjSetVar2(interp, pArray, apColName[i], dbEvalColumnValue(p,i), 0);
- }
- }
-
- /* The required interpreter variables are now populated with the data
- ** from the current row. If using NRE, schedule callbacks to evaluate
- ** script pScript, then to invoke this function again to fetch the next
- ** row (or clean up if there is no next row or the script throws an
- ** exception). After scheduling the callbacks, return control to the
- ** caller.
- **
- ** If not using NRE, evaluate pScript directly and continue with the
- ** next iteration of this while(...) loop. */
- if( DbUseNre() ){
- Tcl_NRAddCallback(interp, DbEvalNextCmd, (void*)p, (void*)pScript, 0, 0);
- return Tcl_NREvalObj(interp, pScript, 0);
- }else{
- rc = Tcl_EvalObjEx(interp, pScript, 0);
- }
- }
-
- Tcl_DecrRefCount(pScript);
- dbEvalFinalize(p);
- Tcl_Free((char *)p);
-
- if( rc==TCL_OK || rc==TCL_BREAK ){
- Tcl_ResetResult(interp);
- rc = TCL_OK;
- }
- return rc;
-}
-
-/*
-** This function is used by the implementations of the following database
-** handle sub-commands:
-**
-** $db update_hook ?SCRIPT?
-** $db wal_hook ?SCRIPT?
-** $db commit_hook ?SCRIPT?
-** $db preupdate hook ?SCRIPT?
-*/
-static void DbHookCmd(
- Tcl_Interp *interp, /* Tcl interpreter */
- SqliteDb *pDb, /* Database handle */
- Tcl_Obj *pArg, /* SCRIPT argument (or NULL) */
- Tcl_Obj **ppHook /* Pointer to member of SqliteDb */
-){
- sqlite3 *db = pDb->db;
-
- if( *ppHook ){
- Tcl_SetObjResult(interp, *ppHook);
- if( pArg ){
- Tcl_DecrRefCount(*ppHook);
- *ppHook = 0;
- }
- }
- if( pArg ){
- assert( !(*ppHook) );
- if( Tcl_GetCharLength(pArg)>0 ){
- *ppHook = pArg;
- Tcl_IncrRefCount(*ppHook);
- }
- }
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- sqlite3_preupdate_hook(db, (pDb->pPreUpdateHook?DbPreUpdateHandler:0), pDb);
-#endif
- sqlite3_update_hook(db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb);
- sqlite3_rollback_hook(db, (pDb->pRollbackHook?DbRollbackHandler:0), pDb);
- sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb);
-}
-
-/*
-** The "sqlite" command below creates a new Tcl command for each
-** connection it opens to an SQLite database. This routine is invoked
-** whenever one of those connection-specific commands is executed
-** in Tcl. For example, if you run Tcl code like this:
-**
-** sqlite3 db1 "my_database"
-** db1 close
-**
-** The first command opens a connection to the "my_database" database
-** and calls that connection "db1". The second command causes this
-** subroutine to be invoked.
-*/
-static int SQLITE_TCLAPI DbObjCmd(
- void *cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const*objv
-){
- SqliteDb *pDb = (SqliteDb*)cd;
- int choice;
- int rc = TCL_OK;
- static const char *DB_strs[] = {
- "authorizer", "backup", "busy",
- "cache", "changes", "close",
- "collate", "collation_needed", "commit_hook",
- "complete", "copy", "deserialize",
- "enable_load_extension", "errorcode", "eval",
- "exists", "function", "incrblob",
- "interrupt", "last_insert_rowid", "nullvalue",
- "onecolumn", "preupdate", "profile",
- "progress", "rekey", "restore",
- "rollback_hook", "serialize", "status",
- "timeout", "total_changes", "trace",
- "trace_v2", "transaction", "unlock_notify",
- "update_hook", "version", "wal_hook",
- 0
- };
- enum DB_enum {
- DB_AUTHORIZER, DB_BACKUP, DB_BUSY,
- DB_CACHE, DB_CHANGES, DB_CLOSE,
- DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
- DB_COMPLETE, DB_COPY, DB_DESERIALIZE,
- DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL,
- DB_EXISTS, DB_FUNCTION, DB_INCRBLOB,
- DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE,
- DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE,
- DB_PROGRESS, DB_REKEY, DB_RESTORE,
- DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS,
- DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
- DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY,
- DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK
- };
- /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
- return TCL_ERROR;
- }
- if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){
- return TCL_ERROR;
- }
-
- switch( (enum DB_enum)choice ){
-
- /* $db authorizer ?CALLBACK?
- **
- ** Invoke the given callback to authorize each SQL operation as it is
- ** compiled. 5 arguments are appended to the callback before it is
- ** invoked:
- **
- ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...)
- ** (2) First descriptive name (depends on authorization type)
- ** (3) Second descriptive name
- ** (4) Name of the database (ex: "main", "temp")
- ** (5) Name of trigger that is doing the access
- **
- ** The callback should return on of the following strings: SQLITE_OK,
- ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error.
- **
- ** If this method is invoked with no arguments, the current authorization
- ** callback string is returned.
- */
- case DB_AUTHORIZER: {
-#ifdef SQLITE_OMIT_AUTHORIZATION
- Tcl_AppendResult(interp, "authorization not available in this build",
- (char*)0);
- return TCL_ERROR;
-#else
- if( objc>3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
- return TCL_ERROR;
- }else if( objc==2 ){
- if( pDb->zAuth ){
- Tcl_AppendResult(interp, pDb->zAuth, (char*)0);
- }
- }else{
- char *zAuth;
- int len;
- if( pDb->zAuth ){
- Tcl_Free(pDb->zAuth);
- }
- zAuth = Tcl_GetStringFromObj(objv[2], &len);
- if( zAuth && len>0 ){
- pDb->zAuth = Tcl_Alloc( len + 1 );
- memcpy(pDb->zAuth, zAuth, len+1);
- }else{
- pDb->zAuth = 0;
- }
- if( pDb->zAuth ){
- typedef int (*sqlite3_auth_cb)(
- void*,int,const char*,const char*,
- const char*,const char*);
- pDb->interp = interp;
- sqlite3_set_authorizer(pDb->db,(sqlite3_auth_cb)auth_callback,pDb);
- }else{
- sqlite3_set_authorizer(pDb->db, 0, 0);
- }
- }
-#endif
- break;
- }
-
- /* $db backup ?DATABASE? FILENAME
- **
- ** Open or create a database file named FILENAME. Transfer the
- ** content of local database DATABASE (default: "main") into the
- ** FILENAME database.
- */
- case DB_BACKUP: {
- const char *zDestFile;
- const char *zSrcDb;
- sqlite3 *pDest;
- sqlite3_backup *pBackup;
-
- if( objc==3 ){
- zSrcDb = "main";
- zDestFile = Tcl_GetString(objv[2]);
- }else if( objc==4 ){
- zSrcDb = Tcl_GetString(objv[2]);
- zDestFile = Tcl_GetString(objv[3]);
- }else{
- Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
- return TCL_ERROR;
- }
- rc = sqlite3_open_v2(zDestFile, &pDest,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE| pDb->openFlags, 0);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "cannot open target database: ",
- sqlite3_errmsg(pDest), (char*)0);
- sqlite3_close(pDest);
- return TCL_ERROR;
- }
- pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb);
- if( pBackup==0 ){
- Tcl_AppendResult(interp, "backup failed: ",
- sqlite3_errmsg(pDest), (char*)0);
- sqlite3_close(pDest);
- return TCL_ERROR;
- }
- while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
- sqlite3_backup_finish(pBackup);
- if( rc==SQLITE_DONE ){
- rc = TCL_OK;
- }else{
- Tcl_AppendResult(interp, "backup failed: ",
- sqlite3_errmsg(pDest), (char*)0);
- rc = TCL_ERROR;
- }
- sqlite3_close(pDest);
- break;
- }
-
- /* $db busy ?CALLBACK?
- **
- ** Invoke the given callback if an SQL statement attempts to open
- ** a locked database file.
- */
- case DB_BUSY: {
- if( objc>3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK");
- return TCL_ERROR;
- }else if( objc==2 ){
- if( pDb->zBusy ){
- Tcl_AppendResult(interp, pDb->zBusy, (char*)0);
- }
- }else{
- char *zBusy;
- int len;
- if( pDb->zBusy ){
- Tcl_Free(pDb->zBusy);
- }
- zBusy = Tcl_GetStringFromObj(objv[2], &len);
- if( zBusy && len>0 ){
- pDb->zBusy = Tcl_Alloc( len + 1 );
- memcpy(pDb->zBusy, zBusy, len+1);
- }else{
- pDb->zBusy = 0;
- }
- if( pDb->zBusy ){
- pDb->interp = interp;
- sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb);
- }else{
- sqlite3_busy_handler(pDb->db, 0, 0);
- }
- }
- break;
- }
-
- /* $db cache flush
- ** $db cache size n
- **
- ** Flush the prepared statement cache, or set the maximum number of
- ** cached statements.
- */
- case DB_CACHE: {
- char *subCmd;
- int n;
-
- if( objc<=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?");
- return TCL_ERROR;
- }
- subCmd = Tcl_GetStringFromObj( objv[2], 0 );
- if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "flush");
- return TCL_ERROR;
- }else{
- flushStmtCache( pDb );
- }
- }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "size n");
- return TCL_ERROR;
- }else{
- if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){
- Tcl_AppendResult( interp, "cannot convert \"",
- Tcl_GetStringFromObj(objv[3],0), "\" to integer", (char*)0);
- return TCL_ERROR;
- }else{
- if( n<0 ){
- flushStmtCache( pDb );
- n = 0;
- }else if( n>MAX_PREPARED_STMTS ){
- n = MAX_PREPARED_STMTS;
- }
- pDb->maxStmt = n;
- }
- }
- }else{
- Tcl_AppendResult( interp, "bad option \"",
- Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size",
- (char*)0);
- return TCL_ERROR;
- }
- break;
- }
-
- /* $db changes
- **
- ** Return the number of rows that were modified, inserted, or deleted by
- ** the most recent INSERT, UPDATE or DELETE statement, not including
- ** any changes made by trigger programs.
- */
- case DB_CHANGES: {
- Tcl_Obj *pResult;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
- pResult = Tcl_GetObjResult(interp);
- Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db));
- break;
- }
-
- /* $db close
- **
- ** Shutdown the database
- */
- case DB_CLOSE: {
- Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0));
- break;
- }
-
- /*
- ** $db collate NAME SCRIPT
- **
- ** Create a new SQL collation function called NAME. Whenever
- ** that function is called, invoke SCRIPT to evaluate the function.
- */
- case DB_COLLATE: {
- SqlCollate *pCollate;
- char *zName;
- char *zScript;
- int nScript;
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
- return TCL_ERROR;
- }
- zName = Tcl_GetStringFromObj(objv[2], 0);
- zScript = Tcl_GetStringFromObj(objv[3], &nScript);
- pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 );
- if( pCollate==0 ) return TCL_ERROR;
- pCollate->interp = interp;
- pCollate->pNext = pDb->pCollate;
- pCollate->zScript = (char*)&pCollate[1];
- pDb->pCollate = pCollate;
- memcpy(pCollate->zScript, zScript, nScript+1);
- if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,
- pCollate, tclSqlCollate) ){
- Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
- return TCL_ERROR;
- }
- break;
- }
-
- /*
- ** $db collation_needed SCRIPT
- **
- ** Create a new SQL collation function called NAME. Whenever
- ** that function is called, invoke SCRIPT to evaluate the function.
- */
- case DB_COLLATION_NEEDED: {
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT");
- return TCL_ERROR;
- }
- if( pDb->pCollateNeeded ){
- Tcl_DecrRefCount(pDb->pCollateNeeded);
- }
- pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]);
- Tcl_IncrRefCount(pDb->pCollateNeeded);
- sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded);
- break;
- }
-
- /* $db commit_hook ?CALLBACK?
- **
- ** Invoke the given callback just before committing every SQL transaction.
- ** If the callback throws an exception or returns non-zero, then the
- ** transaction is aborted. If CALLBACK is an empty string, the callback
- ** is disabled.
- */
- case DB_COMMIT_HOOK: {
- if( objc>3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
- return TCL_ERROR;
- }else if( objc==2 ){
- if( pDb->zCommit ){
- Tcl_AppendResult(interp, pDb->zCommit, (char*)0);
- }
- }else{
- const char *zCommit;
- int len;
- if( pDb->zCommit ){
- Tcl_Free(pDb->zCommit);
- }
- zCommit = Tcl_GetStringFromObj(objv[2], &len);
- if( zCommit && len>0 ){
- pDb->zCommit = Tcl_Alloc( len + 1 );
- memcpy(pDb->zCommit, zCommit, len+1);
- }else{
- pDb->zCommit = 0;
- }
- if( pDb->zCommit ){
- pDb->interp = interp;
- sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb);
- }else{
- sqlite3_commit_hook(pDb->db, 0, 0);
- }
- }
- break;
- }
-
- /* $db complete SQL
- **
- ** Return TRUE if SQL is a complete SQL statement. Return FALSE if
- ** additional lines of input are needed. This is similar to the
- ** built-in "info complete" command of Tcl.
- */
- case DB_COMPLETE: {
-#ifndef SQLITE_OMIT_COMPLETE
- Tcl_Obj *pResult;
- int isComplete;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "SQL");
- return TCL_ERROR;
- }
- isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) );
- pResult = Tcl_GetObjResult(interp);
- Tcl_SetBooleanObj(pResult, isComplete);
-#endif
- break;
- }
-
- /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
- **
- ** Copy data into table from filename, optionally using SEPARATOR
- ** as column separators. If a column contains a null string, or the
- ** value of NULLINDICATOR, a NULL is inserted for the column.
- ** conflict-algorithm is one of the sqlite conflict algorithms:
- ** rollback, abort, fail, ignore, replace
- ** On success, return the number of lines processed, not necessarily same
- ** as 'db changes' due to conflict-algorithm selected.
- **
- ** This code is basically an implementation/enhancement of
- ** the sqlite3 shell.c ".import" command.
- **
- ** This command usage is equivalent to the sqlite2.x COPY statement,
- ** which imports file data into a table using the PostgreSQL COPY file format:
- ** $db copy $conflit_algo $table_name $filename \t \\N
- */
- case DB_COPY: {
- char *zTable; /* Insert data into this table */
- char *zFile; /* The file from which to extract data */
- char *zConflict; /* The conflict algorithm to use */
- sqlite3_stmt *pStmt; /* A statement */
- int nCol; /* Number of columns in the table */
- int nByte; /* Number of bytes in an SQL string */
- int i, j; /* Loop counters */
- int nSep; /* Number of bytes in zSep[] */
- int nNull; /* Number of bytes in zNull[] */
- char *zSql; /* An SQL statement */
- char *zLine; /* A single line of input from the file */
- char **azCol; /* zLine[] broken up into columns */
- const char *zCommit; /* How to commit changes */
- FILE *in; /* The input file */
- int lineno = 0; /* Line number of input file */
- char zLineNum[80]; /* Line number print buffer */
- Tcl_Obj *pResult; /* interp result */
-
- const char *zSep;
- const char *zNull;
- if( objc<5 || objc>7 ){
- Tcl_WrongNumArgs(interp, 2, objv,
- "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
- return TCL_ERROR;
- }
- if( objc>=6 ){
- zSep = Tcl_GetStringFromObj(objv[5], 0);
- }else{
- zSep = "\t";
- }
- if( objc>=7 ){
- zNull = Tcl_GetStringFromObj(objv[6], 0);
- }else{
- zNull = "";
- }
- zConflict = Tcl_GetStringFromObj(objv[2], 0);
- zTable = Tcl_GetStringFromObj(objv[3], 0);
- zFile = Tcl_GetStringFromObj(objv[4], 0);
- nSep = strlen30(zSep);
- nNull = strlen30(zNull);
- if( nSep==0 ){
- Tcl_AppendResult(interp,"Error: non-null separator required for copy",
- (char*)0);
- return TCL_ERROR;
- }
- if(strcmp(zConflict, "rollback") != 0 &&
- strcmp(zConflict, "abort" ) != 0 &&
- strcmp(zConflict, "fail" ) != 0 &&
- strcmp(zConflict, "ignore" ) != 0 &&
- strcmp(zConflict, "replace" ) != 0 ) {
- Tcl_AppendResult(interp, "Error: \"", zConflict,
- "\", conflict-algorithm must be one of: rollback, "
- "abort, fail, ignore, or replace", (char*)0);
- return TCL_ERROR;
- }
- zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
- if( zSql==0 ){
- Tcl_AppendResult(interp, "Error: no such table: ", zTable, (char*)0);
- return TCL_ERROR;
- }
- nByte = strlen30(zSql);
- rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ){
- Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);
- nCol = 0;
- }else{
- nCol = sqlite3_column_count(pStmt);
- }
- sqlite3_finalize(pStmt);
- if( nCol==0 ) {
- return TCL_ERROR;
- }
- zSql = malloc( nByte + 50 + nCol*2 );
- if( zSql==0 ) {
- Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
- return TCL_ERROR;
- }
- sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
- zConflict, zTable);
- j = strlen30(zSql);
- for(i=1; i<nCol; i++){
- zSql[j++] = ',';
- zSql[j++] = '?';
- }
- zSql[j++] = ')';
- zSql[j] = 0;
- rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
- free(zSql);
- if( rc ){
- Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);
- sqlite3_finalize(pStmt);
- return TCL_ERROR;
- }
- in = fopen(zFile, "rb");
- if( in==0 ){
- Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, (char*)0);
- sqlite3_finalize(pStmt);
- return TCL_ERROR;
- }
- azCol = malloc( sizeof(azCol[0])*(nCol+1) );
- if( azCol==0 ) {
- Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
- fclose(in);
- return TCL_ERROR;
- }
- (void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0);
- zCommit = "COMMIT";
- while( (zLine = local_getline(0, in))!=0 ){
- char *z;
- lineno++;
- azCol[0] = zLine;
- for(i=0, z=zLine; *z; z++){
- if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
- *z = 0;
- i++;
- if( i<nCol ){
- azCol[i] = &z[nSep];
- z += nSep-1;
- }
- }
- }
- if( i+1!=nCol ){
- char *zErr;
- int nErr = strlen30(zFile) + 200;
- zErr = malloc(nErr);
- if( zErr ){
- sqlite3_snprintf(nErr, zErr,
- "Error: %s line %d: expected %d columns of data but found %d",
- zFile, lineno, nCol, i+1);
- Tcl_AppendResult(interp, zErr, (char*)0);
- free(zErr);
- }
- zCommit = "ROLLBACK";
- break;
- }
- for(i=0; i<nCol; i++){
- /* check for null data, if so, bind as null */
- if( (nNull>0 && strcmp(azCol[i], zNull)==0)
- || strlen30(azCol[i])==0
- ){
- sqlite3_bind_null(pStmt, i+1);
- }else{
- sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
- }
- }
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- free(zLine);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0);
- zCommit = "ROLLBACK";
- break;
- }
- }
- free(azCol);
- fclose(in);
- sqlite3_finalize(pStmt);
- (void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0);
-
- if( zCommit[0] == 'C' ){
- /* success, set result as number of lines processed */
- pResult = Tcl_GetObjResult(interp);
- Tcl_SetIntObj(pResult, lineno);
- rc = TCL_OK;
- }else{
- /* failure, append lineno where failed */
- sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno);
- Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,
- (char*)0);
- rc = TCL_ERROR;
- }
- break;
- }
-
- /*
- ** $db deserialize ?DATABASE? VALUE
- **
- ** Reopen DATABASE (default "main") using the content in $VALUE
- */
- case DB_DESERIALIZE: {
-#ifndef SQLITE_ENABLE_DESERIALIZE
- Tcl_AppendResult(interp, "MEMDB not available in this build",
- (char*)0);
- rc = TCL_ERROR;
-#else
- const char *zSchema;
- Tcl_Obj *pValue;
- unsigned char *pBA;
- unsigned char *pData;
- int len, xrc;
-
- if( objc==3 ){
- zSchema = 0;
- pValue = objv[2];
- }else if( objc==4 ){
- zSchema = Tcl_GetString(objv[2]);
- pValue = objv[3];
- }else{
- Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? VALUE");
- rc = TCL_ERROR;
- break;
- }
- pBA = Tcl_GetByteArrayFromObj(pValue, &len);
- pData = sqlite3_malloc64( len );
- if( pData==0 && len>0 ){
- Tcl_AppendResult(interp, "out of memory", (char*)0);
- rc = TCL_ERROR;
- }else{
- if( len>0 ) memcpy(pData, pBA, len);
- xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len,
- SQLITE_DESERIALIZE_FREEONCLOSE |
- SQLITE_DESERIALIZE_RESIZEABLE);
- if( xrc ){
- Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0);
- rc = TCL_ERROR;
- }
- }
-#endif
- break;
- }
-
- /*
- ** $db enable_load_extension BOOLEAN
- **
- ** Turn the extension loading feature on or off. It if off by
- ** default.
- */
- case DB_ENABLE_LOAD_EXTENSION: {
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- int onoff;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN");
- return TCL_ERROR;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
- return TCL_ERROR;
- }
- sqlite3_enable_load_extension(pDb->db, onoff);
- break;
-#else
- Tcl_AppendResult(interp, "extension loading is turned off at compile-time",
- (char*)0);
- return TCL_ERROR;
-#endif
- }
-
- /*
- ** $db errorcode
- **
- ** Return the numeric error code that was returned by the most recent
- ** call to sqlite3_exec().
- */
- case DB_ERRORCODE: {
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db)));
- break;
- }
-
- /*
- ** $db exists $sql
- ** $db onecolumn $sql
- **
- ** The onecolumn method is the equivalent of:
- ** lindex [$db eval $sql] 0
- */
- case DB_EXISTS:
- case DB_ONECOLUMN: {
- Tcl_Obj *pResult = 0;
- DbEvalContext sEval;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "SQL");
- return TCL_ERROR;
- }
-
- dbEvalInit(&sEval, pDb, objv[2], 0, 0);
- rc = dbEvalStep(&sEval);
- if( choice==DB_ONECOLUMN ){
- if( rc==TCL_OK ){
- pResult = dbEvalColumnValue(&sEval, 0);
- }else if( rc==TCL_BREAK ){
- Tcl_ResetResult(interp);
- }
- }else if( rc==TCL_BREAK || rc==TCL_OK ){
- pResult = Tcl_NewBooleanObj(rc==TCL_OK);
- }
- dbEvalFinalize(&sEval);
- if( pResult ) Tcl_SetObjResult(interp, pResult);
-
- if( rc==TCL_BREAK ){
- rc = TCL_OK;
- }
- break;
- }
-
- /*
- ** $db eval ?options? $sql ?array? ?{ ...code... }?
- **
- ** The SQL statement in $sql is evaluated. For each row, the values are
- ** placed in elements of the array named "array" and ...code... is executed.
- ** If "array" and "code" are omitted, then no callback is every invoked.
- ** If "array" is an empty string, then the values are placed in variables
- ** that have the same name as the fields extracted by the query.
- */
- case DB_EVAL: {
- int evalFlags = 0;
- const char *zOpt;
- while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){
- if( strcmp(zOpt, "-withoutnulls")==0 ){
- evalFlags |= SQLITE_EVAL_WITHOUTNULLS;
- }
- else{
- Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0);
- return TCL_ERROR;
- }
- objc--;
- objv++;
- }
- if( objc<3 || objc>5 ){
- Tcl_WrongNumArgs(interp, 2, objv,
- "?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?");
- return TCL_ERROR;
- }
-
- if( objc==3 ){
- DbEvalContext sEval;
- Tcl_Obj *pRet = Tcl_NewObj();
- Tcl_IncrRefCount(pRet);
- dbEvalInit(&sEval, pDb, objv[2], 0, 0);
- while( TCL_OK==(rc = dbEvalStep(&sEval)) ){
- int i;
- int nCol;
- dbEvalRowInfo(&sEval, &nCol, 0);
- for(i=0; i<nCol; i++){
- Tcl_ListObjAppendElement(interp, pRet, dbEvalColumnValue(&sEval, i));
- }
- }
- dbEvalFinalize(&sEval);
- if( rc==TCL_BREAK ){
- Tcl_SetObjResult(interp, pRet);
- rc = TCL_OK;
- }
- Tcl_DecrRefCount(pRet);
- }else{
- ClientData cd2[2];
- DbEvalContext *p;
- Tcl_Obj *pArray = 0;
- Tcl_Obj *pScript;
-
- if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){
- pArray = objv[3];
- }
- pScript = objv[objc-1];
- Tcl_IncrRefCount(pScript);
-
- p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
- dbEvalInit(p, pDb, objv[2], pArray, evalFlags);
-
- cd2[0] = (void *)p;
- cd2[1] = (void *)pScript;
- rc = DbEvalNextCmd(cd2, interp, TCL_OK);
- }
- break;
- }
-
- /*
- ** $db function NAME [-argcount N] [-deterministic] SCRIPT
- **
- ** Create a new SQL function called NAME. Whenever that function is
- ** called, invoke SCRIPT to evaluate the function.
- */
- case DB_FUNCTION: {
- int flags = SQLITE_UTF8;
- SqlFunc *pFunc;
- Tcl_Obj *pScript;
- char *zName;
- int nArg = -1;
- int i;
- if( objc<4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
- return TCL_ERROR;
- }
- for(i=3; i<(objc-1); i++){
- const char *z = Tcl_GetString(objv[i]);
- int n = strlen30(z);
- if( n>2 && strncmp(z, "-argcount",n)==0 ){
- if( i==(objc-2) ){
- Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR;
- if( nArg<0 ){
- Tcl_AppendResult(interp, "number of arguments must be non-negative",
- (char*)0);
- return TCL_ERROR;
- }
- i++;
- }else
- if( n>2 && strncmp(z, "-deterministic",n)==0 ){
- flags |= SQLITE_DETERMINISTIC;
- }else{
- Tcl_AppendResult(interp, "bad option \"", z,
- "\": must be -argcount or -deterministic", (char*)0
- );
- return TCL_ERROR;
- }
- }
-
- pScript = objv[objc-1];
- zName = Tcl_GetStringFromObj(objv[2], 0);
- pFunc = findSqlFunc(pDb, zName);
- if( pFunc==0 ) return TCL_ERROR;
- if( pFunc->pScript ){
- Tcl_DecrRefCount(pFunc->pScript);
- }
- pFunc->pScript = pScript;
- Tcl_IncrRefCount(pScript);
- pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
- rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
- pFunc, tclSqlFunc, 0, 0);
- if( rc!=SQLITE_OK ){
- rc = TCL_ERROR;
- Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
- }
- break;
- }
-
- /*
- ** $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID
- */
- case DB_INCRBLOB: {
-#ifdef SQLITE_OMIT_INCRBLOB
- Tcl_AppendResult(interp, "incrblob not available in this build", (char*)0);
- return TCL_ERROR;
-#else
- int isReadonly = 0;
- const char *zDb = "main";
- const char *zTable;
- const char *zColumn;
- Tcl_WideInt iRow;
-
- /* Check for the -readonly option */
- if( objc>3 && strcmp(Tcl_GetString(objv[2]), "-readonly")==0 ){
- isReadonly = 1;
- }
-
- if( objc!=(5+isReadonly) && objc!=(6+isReadonly) ){
- Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? ?DB? TABLE COLUMN ROWID");
- return TCL_ERROR;
- }
-
- if( objc==(6+isReadonly) ){
- zDb = Tcl_GetString(objv[2]);
- }
- zTable = Tcl_GetString(objv[objc-3]);
- zColumn = Tcl_GetString(objv[objc-2]);
- rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow);
-
- if( rc==TCL_OK ){
- rc = createIncrblobChannel(
- interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly
- );
- }
-#endif
- break;
- }
-
- /*
- ** $db interrupt
- **
- ** Interrupt the execution of the inner-most SQL interpreter. This
- ** causes the SQL statement to return an error of SQLITE_INTERRUPT.
- */
- case DB_INTERRUPT: {
- sqlite3_interrupt(pDb->db);
- break;
- }
-
- /*
- ** $db nullvalue ?STRING?
- **
- ** Change text used when a NULL comes back from the database. If ?STRING?
- ** is not present, then the current string used for NULL is returned.
- ** If STRING is present, then STRING is returned.
- **
- */
- case DB_NULLVALUE: {
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE");
- return TCL_ERROR;
- }
- if( objc==3 ){
- int len;
- char *zNull = Tcl_GetStringFromObj(objv[2], &len);
- if( pDb->zNull ){
- Tcl_Free(pDb->zNull);
- }
- if( zNull && len>0 ){
- pDb->zNull = Tcl_Alloc( len + 1 );
- memcpy(pDb->zNull, zNull, len);
- pDb->zNull[len] = '\0';
- }else{
- pDb->zNull = 0;
- }
- }
- Tcl_SetObjResult(interp, Tcl_NewStringObj(pDb->zNull, -1));
- break;
- }
-
- /*
- ** $db last_insert_rowid
- **
- ** Return an integer which is the ROWID for the most recent insert.
- */
- case DB_LAST_INSERT_ROWID: {
- Tcl_Obj *pResult;
- Tcl_WideInt rowid;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
- rowid = sqlite3_last_insert_rowid(pDb->db);
- pResult = Tcl_GetObjResult(interp);
- Tcl_SetWideIntObj(pResult, rowid);
- break;
- }
-
- /*
- ** The DB_ONECOLUMN method is implemented together with DB_EXISTS.
- */
-
- /* $db progress ?N CALLBACK?
- **
- ** Invoke the given callback every N virtual machine opcodes while executing
- ** queries.
- */
- case DB_PROGRESS: {
- if( objc==2 ){
- if( pDb->zProgress ){
- Tcl_AppendResult(interp, pDb->zProgress, (char*)0);
- }
- }else if( objc==4 ){
- char *zProgress;
- int len;
- int N;
- if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){
- return TCL_ERROR;
- };
- if( pDb->zProgress ){
- Tcl_Free(pDb->zProgress);
- }
- zProgress = Tcl_GetStringFromObj(objv[3], &len);
- if( zProgress && len>0 ){
- pDb->zProgress = Tcl_Alloc( len + 1 );
- memcpy(pDb->zProgress, zProgress, len+1);
- }else{
- pDb->zProgress = 0;
- }
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- if( pDb->zProgress ){
- pDb->interp = interp;
- sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb);
- }else{
- sqlite3_progress_handler(pDb->db, 0, 0, 0);
- }
-#endif
- }else{
- Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK");
- return TCL_ERROR;
- }
- break;
- }
-
- /* $db profile ?CALLBACK?
- **
- ** Make arrangements to invoke the CALLBACK routine after each SQL statement
- ** that has run. The text of the SQL and the amount of elapse time are
- ** appended to CALLBACK before the script is run.
- */
- case DB_PROFILE: {
- if( objc>3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
- return TCL_ERROR;
- }else if( objc==2 ){
- if( pDb->zProfile ){
- Tcl_AppendResult(interp, pDb->zProfile, (char*)0);
- }
- }else{
- char *zProfile;
- int len;
- if( pDb->zProfile ){
- Tcl_Free(pDb->zProfile);
- }
- zProfile = Tcl_GetStringFromObj(objv[2], &len);
- if( zProfile && len>0 ){
- pDb->zProfile = Tcl_Alloc( len + 1 );
- memcpy(pDb->zProfile, zProfile, len+1);
- }else{
- pDb->zProfile = 0;
- }
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
- !defined(SQLITE_OMIT_DEPRECATED)
- if( pDb->zProfile ){
- pDb->interp = interp;
- sqlite3_profile(pDb->db, DbProfileHandler, pDb);
- }else{
- sqlite3_profile(pDb->db, 0, 0);
- }
-#endif
- }
- break;
- }
-
- /*
- ** $db rekey KEY
- **
- ** Change the encryption key on the currently open database.
- */
- case DB_REKEY: {
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
- int nKey;
- void *pKey;
-#endif
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "KEY");
- return TCL_ERROR;
- }
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
- pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
- rc = sqlite3_rekey(pDb->db, pKey, nKey);
- if( rc ){
- Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
- rc = TCL_ERROR;
- }
-#endif
- break;
- }
-
- /* $db restore ?DATABASE? FILENAME
- **
- ** Open a database file named FILENAME. Transfer the content
- ** of FILENAME into the local database DATABASE (default: "main").
- */
- case DB_RESTORE: {
- const char *zSrcFile;
- const char *zDestDb;
- sqlite3 *pSrc;
- sqlite3_backup *pBackup;
- int nTimeout = 0;
-
- if( objc==3 ){
- zDestDb = "main";
- zSrcFile = Tcl_GetString(objv[2]);
- }else if( objc==4 ){
- zDestDb = Tcl_GetString(objv[2]);
- zSrcFile = Tcl_GetString(objv[3]);
- }else{
- Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
- return TCL_ERROR;
- }
- rc = sqlite3_open_v2(zSrcFile, &pSrc,
- SQLITE_OPEN_READONLY | pDb->openFlags, 0);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "cannot open source database: ",
- sqlite3_errmsg(pSrc), (char*)0);
- sqlite3_close(pSrc);
- return TCL_ERROR;
- }
- pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main");
- if( pBackup==0 ){
- Tcl_AppendResult(interp, "restore failed: ",
- sqlite3_errmsg(pDb->db), (char*)0);
- sqlite3_close(pSrc);
- return TCL_ERROR;
- }
- while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
- || rc==SQLITE_BUSY ){
- if( rc==SQLITE_BUSY ){
- if( nTimeout++ >= 3 ) break;
- sqlite3_sleep(100);
- }
- }
- sqlite3_backup_finish(pBackup);
- if( rc==SQLITE_DONE ){
- rc = TCL_OK;
- }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
- Tcl_AppendResult(interp, "restore failed: source database busy",
- (char*)0);
- rc = TCL_ERROR;
- }else{
- Tcl_AppendResult(interp, "restore failed: ",
- sqlite3_errmsg(pDb->db), (char*)0);
- rc = TCL_ERROR;
- }
- sqlite3_close(pSrc);
- break;
- }
-
- /*
- ** $db serialize ?DATABASE?
- **
- ** Return a serialization of a database.
- */
- case DB_SERIALIZE: {
-#ifndef SQLITE_ENABLE_DESERIALIZE
- Tcl_AppendResult(interp, "MEMDB not available in this build",
- (char*)0);
- rc = TCL_ERROR;
-#else
- const char *zSchema = objc>=3 ? Tcl_GetString(objv[2]) : "main";
- sqlite3_int64 sz = 0;
- unsigned char *pData;
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE?");
- rc = TCL_ERROR;
- }else{
- int needFree;
- pData = sqlite3_serialize(pDb->db, zSchema, &sz, SQLITE_SERIALIZE_NOCOPY);
- if( pData ){
- needFree = 0;
- }else{
- pData = sqlite3_serialize(pDb->db, zSchema, &sz, 0);
- needFree = 1;
- }
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz));
- if( needFree ) sqlite3_free(pData);
- }
-#endif
- break;
- }
-
- /*
- ** $db status (step|sort|autoindex|vmstep)
- **
- ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or
- ** SQLITE_STMTSTATUS_SORT for the most recent eval.
- */
- case DB_STATUS: {
- int v;
- const char *zOp;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "(step|sort|autoindex)");
- return TCL_ERROR;
- }
- zOp = Tcl_GetString(objv[2]);
- if( strcmp(zOp, "step")==0 ){
- v = pDb->nStep;
- }else if( strcmp(zOp, "sort")==0 ){
- v = pDb->nSort;
- }else if( strcmp(zOp, "autoindex")==0 ){
- v = pDb->nIndex;
- }else if( strcmp(zOp, "vmstep")==0 ){
- v = pDb->nVMStep;
- }else{
- Tcl_AppendResult(interp,
- "bad argument: should be autoindex, step, sort or vmstep",
- (char*)0);
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
- break;
- }
-
- /*
- ** $db timeout MILLESECONDS
- **
- ** Delay for the number of milliseconds specified when a file is locked.
- */
- case DB_TIMEOUT: {
- int ms;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR;
- sqlite3_busy_timeout(pDb->db, ms);
- break;
- }
-
- /*
- ** $db total_changes
- **
- ** Return the number of rows that were modified, inserted, or deleted
- ** since the database handle was created.
- */
- case DB_TOTAL_CHANGES: {
- Tcl_Obj *pResult;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
- pResult = Tcl_GetObjResult(interp);
- Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db));
- break;
- }
-
- /* $db trace ?CALLBACK?
- **
- ** Make arrangements to invoke the CALLBACK routine for each SQL statement
- ** that is executed. The text of the SQL is appended to CALLBACK before
- ** it is executed.
- */
- case DB_TRACE: {
- if( objc>3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
- return TCL_ERROR;
- }else if( objc==2 ){
- if( pDb->zTrace ){
- Tcl_AppendResult(interp, pDb->zTrace, (char*)0);
- }
- }else{
- char *zTrace;
- int len;
- if( pDb->zTrace ){
- Tcl_Free(pDb->zTrace);
- }
- zTrace = Tcl_GetStringFromObj(objv[2], &len);
- if( zTrace && len>0 ){
- pDb->zTrace = Tcl_Alloc( len + 1 );
- memcpy(pDb->zTrace, zTrace, len+1);
- }else{
- pDb->zTrace = 0;
- }
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
- !defined(SQLITE_OMIT_DEPRECATED)
- if( pDb->zTrace ){
- pDb->interp = interp;
- sqlite3_trace(pDb->db, DbTraceHandler, pDb);
- }else{
- sqlite3_trace(pDb->db, 0, 0);
- }
-#endif
- }
- break;
- }
-
- /* $db trace_v2 ?CALLBACK? ?MASK?
- **
- ** Make arrangements to invoke the CALLBACK routine for each trace event
- ** matching the mask that is generated. The parameters are appended to
- ** CALLBACK before it is executed.
- */
- case DB_TRACE_V2: {
- if( objc>4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK? ?MASK?");
- return TCL_ERROR;
- }else if( objc==2 ){
- if( pDb->zTraceV2 ){
- Tcl_AppendResult(interp, pDb->zTraceV2, (char*)0);
- }
- }else{
- char *zTraceV2;
- int len;
- Tcl_WideInt wMask = 0;
- if( objc==4 ){
- static const char *TTYPE_strs[] = {
- "statement", "profile", "row", "close", 0
- };
- enum TTYPE_enum {
- TTYPE_STMT, TTYPE_PROFILE, TTYPE_ROW, TTYPE_CLOSE
- };
- int i;
- if( TCL_OK!=Tcl_ListObjLength(interp, objv[3], &len) ){
- return TCL_ERROR;
- }
- for(i=0; i<len; i++){
- Tcl_Obj *pObj;
- int ttype;
- if( TCL_OK!=Tcl_ListObjIndex(interp, objv[3], i, &pObj) ){
- return TCL_ERROR;
- }
- if( Tcl_GetIndexFromObj(interp, pObj, TTYPE_strs, "trace type",
- 0, &ttype)!=TCL_OK ){
- Tcl_WideInt wType;
- Tcl_Obj *pError = Tcl_DuplicateObj(Tcl_GetObjResult(interp));
- Tcl_IncrRefCount(pError);
- if( TCL_OK==Tcl_GetWideIntFromObj(interp, pObj, &wType) ){
- Tcl_DecrRefCount(pError);
- wMask |= wType;
- }else{
- Tcl_SetObjResult(interp, pError);
- Tcl_DecrRefCount(pError);
- return TCL_ERROR;
- }
- }else{
- switch( (enum TTYPE_enum)ttype ){
- case TTYPE_STMT: wMask |= SQLITE_TRACE_STMT; break;
- case TTYPE_PROFILE: wMask |= SQLITE_TRACE_PROFILE; break;
- case TTYPE_ROW: wMask |= SQLITE_TRACE_ROW; break;
- case TTYPE_CLOSE: wMask |= SQLITE_TRACE_CLOSE; break;
- }
- }
- }
- }else{
- wMask = SQLITE_TRACE_STMT; /* use the "legacy" default */
- }
- if( pDb->zTraceV2 ){
- Tcl_Free(pDb->zTraceV2);
- }
- zTraceV2 = Tcl_GetStringFromObj(objv[2], &len);
- if( zTraceV2 && len>0 ){
- pDb->zTraceV2 = Tcl_Alloc( len + 1 );
- memcpy(pDb->zTraceV2, zTraceV2, len+1);
- }else{
- pDb->zTraceV2 = 0;
- }
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
- if( pDb->zTraceV2 ){
- pDb->interp = interp;
- sqlite3_trace_v2(pDb->db, (unsigned)wMask, DbTraceV2Handler, pDb);
- }else{
- sqlite3_trace_v2(pDb->db, 0, 0, 0);
- }
-#endif
- }
- break;
- }
-
- /* $db transaction [-deferred|-immediate|-exclusive] SCRIPT
- **
- ** Start a new transaction (if we are not already in the midst of a
- ** transaction) and execute the TCL script SCRIPT. After SCRIPT
- ** completes, either commit the transaction or roll it back if SCRIPT
- ** throws an exception. Or if no new transation was started, do nothing.
- ** pass the exception on up the stack.
- **
- ** This command was inspired by Dave Thomas's talk on Ruby at the
- ** 2005 O'Reilly Open Source Convention (OSCON).
- */
- case DB_TRANSACTION: {
- Tcl_Obj *pScript;
- const char *zBegin = "SAVEPOINT _tcl_transaction";
- if( objc!=3 && objc!=4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT");
- return TCL_ERROR;
- }
-
- if( pDb->nTransaction==0 && objc==4 ){
- static const char *TTYPE_strs[] = {
- "deferred", "exclusive", "immediate", 0
- };
- enum TTYPE_enum {
- TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE
- };
- int ttype;
- if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type",
- 0, &ttype) ){
- return TCL_ERROR;
- }
- switch( (enum TTYPE_enum)ttype ){
- case TTYPE_DEFERRED: /* no-op */; break;
- case TTYPE_EXCLUSIVE: zBegin = "BEGIN EXCLUSIVE"; break;
- case TTYPE_IMMEDIATE: zBegin = "BEGIN IMMEDIATE"; break;
- }
- }
- pScript = objv[objc-1];
-
- /* Run the SQLite BEGIN command to open a transaction or savepoint. */
- pDb->disableAuth++;
- rc = sqlite3_exec(pDb->db, zBegin, 0, 0, 0);
- pDb->disableAuth--;
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
- return TCL_ERROR;
- }
- pDb->nTransaction++;
-
- /* If using NRE, schedule a callback to invoke the script pScript, then
- ** a second callback to commit (or rollback) the transaction or savepoint
- ** opened above. If not using NRE, evaluate the script directly, then
- ** call function DbTransPostCmd() to commit (or rollback) the transaction
- ** or savepoint. */
- if( DbUseNre() ){
- Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
- (void)Tcl_NREvalObj(interp, pScript, 0);
- }else{
- rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0));
- }
- break;
- }
-
- /*
- ** $db unlock_notify ?script?
- */
- case DB_UNLOCK_NOTIFY: {
-#ifndef SQLITE_ENABLE_UNLOCK_NOTIFY
- Tcl_AppendResult(interp, "unlock_notify not available in this build",
- (char*)0);
- rc = TCL_ERROR;
-#else
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
- rc = TCL_ERROR;
- }else{
- void (*xNotify)(void **, int) = 0;
- void *pNotifyArg = 0;
-
- if( pDb->pUnlockNotify ){
- Tcl_DecrRefCount(pDb->pUnlockNotify);
- pDb->pUnlockNotify = 0;
- }
-
- if( objc==3 ){
- xNotify = DbUnlockNotify;
- pNotifyArg = (void *)pDb;
- pDb->pUnlockNotify = objv[2];
- Tcl_IncrRefCount(pDb->pUnlockNotify);
- }
-
- if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
- Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
- rc = TCL_ERROR;
- }
- }
-#endif
- break;
- }
-
- /*
- ** $db preupdate_hook count
- ** $db preupdate_hook hook ?SCRIPT?
- ** $db preupdate_hook new INDEX
- ** $db preupdate_hook old INDEX
- */
- case DB_PREUPDATE: {
-#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
- Tcl_AppendResult(interp, "preupdate_hook was omitted at compile-time",
- (char*)0);
- rc = TCL_ERROR;
-#else
- static const char *azSub[] = {"count", "depth", "hook", "new", "old", 0};
- enum DbPreupdateSubCmd {
- PRE_COUNT, PRE_DEPTH, PRE_HOOK, PRE_NEW, PRE_OLD
- };
- int iSub;
-
- if( objc<3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "SUB-COMMAND ?ARGS?");
- }
- if( Tcl_GetIndexFromObj(interp, objv[2], azSub, "sub-command", 0, &iSub) ){
- return TCL_ERROR;
- }
-
- switch( (enum DbPreupdateSubCmd)iSub ){
- case PRE_COUNT: {
- int nCol = sqlite3_preupdate_count(pDb->db);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nCol));
- break;
- }
-
- case PRE_HOOK: {
- if( objc>4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "hook ?SCRIPT?");
- return TCL_ERROR;
- }
- DbHookCmd(interp, pDb, (objc==4 ? objv[3] : 0), &pDb->pPreUpdateHook);
- break;
- }
-
- case PRE_DEPTH: {
- Tcl_Obj *pRet;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 3, objv, "");
- return TCL_ERROR;
- }
- pRet = Tcl_NewIntObj(sqlite3_preupdate_depth(pDb->db));
- Tcl_SetObjResult(interp, pRet);
- break;
- }
-
- case PRE_NEW:
- case PRE_OLD: {
- int iIdx;
- sqlite3_value *pValue;
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 3, objv, "INDEX");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[3], &iIdx) ){
- return TCL_ERROR;
- }
-
- if( iSub==PRE_OLD ){
- rc = sqlite3_preupdate_old(pDb->db, iIdx, &pValue);
- }else{
- assert( iSub==PRE_NEW );
- rc = sqlite3_preupdate_new(pDb->db, iIdx, &pValue);
- }
-
- if( rc==SQLITE_OK ){
- Tcl_Obj *pObj;
- pObj = Tcl_NewStringObj((char*)sqlite3_value_text(pValue), -1);
- Tcl_SetObjResult(interp, pObj);
- }else{
- Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
- return TCL_ERROR;
- }
- }
- }
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
- break;
- }
-
- /*
- ** $db wal_hook ?script?
- ** $db update_hook ?script?
- ** $db rollback_hook ?script?
- */
- case DB_WAL_HOOK:
- case DB_UPDATE_HOOK:
- case DB_ROLLBACK_HOOK: {
- /* set ppHook to point at pUpdateHook or pRollbackHook, depending on
- ** whether [$db update_hook] or [$db rollback_hook] was invoked.
- */
- Tcl_Obj **ppHook = 0;
- if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook;
- if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook;
- if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook;
- if( objc>3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
- return TCL_ERROR;
- }
-
- DbHookCmd(interp, pDb, (objc==3 ? objv[2] : 0), ppHook);
- break;
- }
-
- /* $db version
- **
- ** Return the version string for this database.
- */
- case DB_VERSION: {
- int i;
- for(i=2; i<objc; i++){
- const char *zArg = Tcl_GetString(objv[i]);
- /* Optional arguments to $db version are used for testing purpose */
-#ifdef SQLITE_TEST
- /* $db version -use-legacy-prepare BOOLEAN
- **
- ** Turn the use of legacy sqlite3_prepare() on or off.
- */
- if( strcmp(zArg, "-use-legacy-prepare")==0 && i+1<objc ){
- i++;
- if( Tcl_GetBooleanFromObj(interp, objv[i], &pDb->bLegacyPrepare) ){
- return TCL_ERROR;
- }
- }else
-
- /* $db version -last-stmt-ptr
- **
- ** Return a string which is a hex encoding of the pointer to the
- ** most recent sqlite3_stmt in the statement cache.
- */
- if( strcmp(zArg, "-last-stmt-ptr")==0 ){
- char zBuf[100];
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%p",
- pDb->stmtList ? pDb->stmtList->pStmt: 0);
- Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
- }else
-#endif /* SQLITE_TEST */
- {
- Tcl_AppendResult(interp, "unknown argument: ", zArg, (char*)0);
- return TCL_ERROR;
- }
- }
- if( i==2 ){
- Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC);
- }
- break;
- }
-
-
- } /* End of the SWITCH statement */
- return rc;
-}
-
-#if SQLITE_TCL_NRE
-/*
-** Adaptor that provides an objCmd interface to the NRE-enabled
-** interface implementation.
-*/
-static int SQLITE_TCLAPI DbObjCmdAdaptor(
- void *cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const*objv
-){
- return Tcl_NRCallObjProc(interp, DbObjCmd, cd, objc, objv);
-}
-#endif /* SQLITE_TCL_NRE */
-
-/*
-** Issue the usage message when the "sqlite3" command arguments are
-** incorrect.
-*/
-static int sqliteCmdUsage(
- Tcl_Interp *interp,
- Tcl_Obj *const*objv
-){
- Tcl_WrongNumArgs(interp, 1, objv,
- "HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
- " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
- " ?-key CODECKEY?"
-#endif
- );
- return TCL_ERROR;
-}
-
-/*
-** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN?
-** ?-create BOOLEAN? ?-nomutex BOOLEAN?
-**
-** This is the main Tcl command. When the "sqlite" Tcl command is
-** invoked, this routine runs to process that command.
-**
-** The first argument, DBNAME, is an arbitrary name for a new
-** database connection. This command creates a new command named
-** DBNAME that is used to control that connection. The database
-** connection is deleted when the DBNAME command is deleted.
-**
-** The second argument is the name of the database file.
-**
-*/
-static int SQLITE_TCLAPI DbMain(
- void *cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const*objv
-){
- SqliteDb *p;
- const char *zArg;
- char *zErrMsg;
- int i;
- const char *zFile = 0;
- const char *zVfs = 0;
- int flags;
- Tcl_DString translatedFilename;
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
- void *pKey = 0;
- int nKey = 0;
-#endif
- int rc;
-
- /* In normal use, each TCL interpreter runs in a single thread. So
- ** by default, we can turn off mutexing on SQLite database connections.
- ** However, for testing purposes it is useful to have mutexes turned
- ** on. So, by default, mutexes default off. But if compiled with
- ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on.
- */
-#ifdef SQLITE_TCL_DEFAULT_FULLMUTEX
- flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
-#else
- flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
-#endif
-
- if( objc==2 ){
- zArg = Tcl_GetStringFromObj(objv[1], 0);
- if( strcmp(zArg,"-version")==0 ){
- Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0);
- return TCL_OK;
- }
- if( strcmp(zArg,"-sourceid")==0 ){
- Tcl_AppendResult(interp,sqlite3_sourceid(), (char*)0);
- return TCL_OK;
- }
- if( strcmp(zArg,"-has-codec")==0 ){
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
- Tcl_AppendResult(interp,"1",(char*)0);
-#else
- Tcl_AppendResult(interp,"0",(char*)0);
-#endif
- return TCL_OK;
- }
- if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv);
- }
- for(i=2; i<objc; i++){
- zArg = Tcl_GetString(objv[i]);
- if( zArg[0]!='-' ){
- if( zFile!=0 ) return sqliteCmdUsage(interp, objv);
- zFile = zArg;
- continue;
- }
- if( i==objc-1 ) return sqliteCmdUsage(interp, objv);
- i++;
- if( strcmp(zArg,"-key")==0 ){
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
- pKey = Tcl_GetByteArrayFromObj(objv[i], &nKey);
-#endif
- }else if( strcmp(zArg, "-vfs")==0 ){
- zVfs = Tcl_GetString(objv[i]);
- }else if( strcmp(zArg, "-readonly")==0 ){
- int b;
- if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
- if( b ){
- flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
- flags |= SQLITE_OPEN_READONLY;
- }else{
- flags &= ~SQLITE_OPEN_READONLY;
- flags |= SQLITE_OPEN_READWRITE;
- }
- }else if( strcmp(zArg, "-create")==0 ){
- int b;
- if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
- if( b && (flags & SQLITE_OPEN_READONLY)==0 ){
- flags |= SQLITE_OPEN_CREATE;
- }else{
- flags &= ~SQLITE_OPEN_CREATE;
- }
- }else if( strcmp(zArg, "-nomutex")==0 ){
- int b;
- if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
- if( b ){
- flags |= SQLITE_OPEN_NOMUTEX;
- flags &= ~SQLITE_OPEN_FULLMUTEX;
- }else{
- flags &= ~SQLITE_OPEN_NOMUTEX;
- }
- }else if( strcmp(zArg, "-fullmutex")==0 ){
- int b;
- if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
- if( b ){
- flags |= SQLITE_OPEN_FULLMUTEX;
- flags &= ~SQLITE_OPEN_NOMUTEX;
- }else{
- flags &= ~SQLITE_OPEN_FULLMUTEX;
- }
- }else if( strcmp(zArg, "-uri")==0 ){
- int b;
- if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
- if( b ){
- flags |= SQLITE_OPEN_URI;
- }else{
- flags &= ~SQLITE_OPEN_URI;
- }
- }else{
- Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
- return TCL_ERROR;
- }
- }
- zErrMsg = 0;
- p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
- memset(p, 0, sizeof(*p));
- if( zFile==0 ) zFile = "";
- zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
- rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
- Tcl_DStringFree(&translatedFilename);
- if( p->db ){
- if( SQLITE_OK!=sqlite3_errcode(p->db) ){
- zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
- sqlite3_close(p->db);
- p->db = 0;
- }
- }else{
- zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
- }
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
- if( p->db ){
- sqlite3_key(p->db, pKey, nKey);
- }
-#endif
- if( p->db==0 ){
- Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
- Tcl_Free((char*)p);
- sqlite3_free(zErrMsg);
- return TCL_ERROR;
- }
- p->maxStmt = NUM_PREPARED_STMTS;
- p->openFlags = flags & SQLITE_OPEN_URI;
- p->interp = interp;
- zArg = Tcl_GetStringFromObj(objv[1], 0);
- if( DbUseNre() ){
- Tcl_NRCreateCommand(interp, zArg, DbObjCmdAdaptor, DbObjCmd,
- (char*)p, DbDeleteCmd);
- }else{
- Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
- }
- return TCL_OK;
-}
-
-/*
-** Provide a dummy Tcl_InitStubs if we are using this as a static
-** library.
-*/
-#ifndef USE_TCL_STUBS
-# undef Tcl_InitStubs
-# define Tcl_InitStubs(a,b,c) TCL_VERSION
-#endif
-
-/*
-** Make sure we have a PACKAGE_VERSION macro defined. This will be
-** defined automatically by the TEA makefile. But other makefiles
-** do not define it.
-*/
-#ifndef PACKAGE_VERSION
-# define PACKAGE_VERSION SQLITE_VERSION
-#endif
-
-/*
-** Initialize this module.
-**
-** This Tcl module contains only a single new Tcl command named "sqlite".
-** (Hence there is no namespace. There is no point in using a namespace
-** if the extension only supplies one new name!) The "sqlite" command is
-** used to open a new SQLite database. See the DbMain() routine above
-** for additional information.
-**
-** The EXTERN macros are required by TCL in order to work on windows.
-*/
-EXTERN int Sqlite3_Init(Tcl_Interp *interp){
- int rc = Tcl_InitStubs(interp, "8.4", 0) ? TCL_OK : TCL_ERROR;
- if( rc==TCL_OK ){
- Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
-#ifndef SQLITE_3_SUFFIX_ONLY
- /* The "sqlite" alias is undocumented. It is here only to support
- ** legacy scripts. All new scripts should use only the "sqlite3"
- ** command. */
- Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
-#endif
- rc = Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION);
- }
- return rc;
-}
-EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
-EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
-EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
-
-/* Because it accesses the file-system and uses persistent state, SQLite
-** is not considered appropriate for safe interpreters. Hence, we cause
-** the _SafeInit() interfaces return TCL_ERROR.
-*/
-EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; }
-EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;}
-
-
-
-#ifndef SQLITE_3_SUFFIX_ONLY
-int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
-int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
-int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
-int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
-#endif
-
-/*
-** If the TCLSH macro is defined, add code to make a stand-alone program.
-*/
-#if defined(TCLSH)
-
-/* This is the main routine for an ordinary TCL shell. If there are
-** are arguments, run the first argument as a script. Otherwise,
-** read TCL commands from standard input
-*/
-static const char *tclsh_main_loop(void){
- static const char zMainloop[] =
- "if {[llength $argv]>=1} {\n"
- "set argv0 [lindex $argv 0]\n"
- "set argv [lrange $argv 1 end]\n"
- "source $argv0\n"
- "} else {\n"
- "set line {}\n"
- "while {![eof stdin]} {\n"
- "if {$line!=\"\"} {\n"
- "puts -nonewline \"> \"\n"
- "} else {\n"
- "puts -nonewline \"% \"\n"
- "}\n"
- "flush stdout\n"
- "append line [gets stdin]\n"
- "if {[info complete $line]} {\n"
- "if {[catch {uplevel #0 $line} result]} {\n"
- "puts stderr \"Error: $result\"\n"
- "} elseif {$result!=\"\"} {\n"
- "puts $result\n"
- "}\n"
- "set line {}\n"
- "} else {\n"
- "append line \\n\n"
- "}\n"
- "}\n"
- "}\n"
- ;
- return zMainloop;
-}
-
-#define TCLSH_MAIN main /* Needed to fake out mktclapp */
-int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){
- Tcl_Interp *interp;
- int i;
- const char *zScript = 0;
- char zArgc[32];
-#if defined(TCLSH_INIT_PROC)
- extern const char *TCLSH_INIT_PROC(Tcl_Interp*);
-#endif
-
-#if !defined(_WIN32_WCE)
- if( getenv("BREAK") ){
- fprintf(stderr,
- "attach debugger to process %d and press any key to continue.\n",
- GETPID());
- fgetc(stdin);
- }
-#endif
-
- /* Call sqlite3_shutdown() once before doing anything else. This is to
- ** test that sqlite3_shutdown() can be safely called by a process before
- ** sqlite3_initialize() is. */
- sqlite3_shutdown();
-
- Tcl_FindExecutable(argv[0]);
- Tcl_SetSystemEncoding(NULL, "utf-8");
- interp = Tcl_CreateInterp();
- Sqlite3_Init(interp);
-
- sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-1);
- Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
- for(i=1; i<argc; i++){
- Tcl_SetVar(interp, "argv", argv[i],
- TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
- }
-#if defined(TCLSH_INIT_PROC)
- zScript = TCLSH_INIT_PROC(interp);
-#endif
- if( zScript==0 ){
- zScript = tclsh_main_loop();
- }
- if( Tcl_GlobalEval(interp, zScript)!=TCL_OK ){
- const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp);
- fprintf(stderr,"%s: %s\n", *argv, zInfo);
- return 1;
- }
- return 0;
-}
-#endif /* TCLSH */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test1.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test1.c
deleted file mode 100644
index f2511d259a2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test1.c
+++ /dev/null
@@ -1,7892 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Code for testing all sorts of SQLite interfaces. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library.
-*/
-#include "sqliteInt.h"
-#if SQLITE_OS_WIN
-# include "os_win.h"
-#endif
-
-#include "vdbeInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-/*
-** This is a copy of the first part of the SqliteDb structure in
-** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
-** can extract the sqlite3* pointer from an existing Tcl SQLite
-** connection.
-*/
-struct SqliteDb {
- sqlite3 *db;
-};
-
-/*
-** Convert text generated by the "%p" conversion format back into
-** a pointer.
-*/
-static int testHexToInt(int h){
- if( h>='0' && h<='9' ){
- return h - '0';
- }else if( h>='a' && h<='f' ){
- return h - 'a' + 10;
- }else{
- assert( h>='A' && h<='F' );
- return h - 'A' + 10;
- }
-}
-void *sqlite3TestTextToPtr(const char *z){
- void *p;
- u64 v;
- u32 v2;
- if( z[0]=='0' && z[1]=='x' ){
- z += 2;
- }
- v = 0;
- while( *z ){
- v = (v<<4) + testHexToInt(*z);
- z++;
- }
- if( sizeof(p)==sizeof(v) ){
- memcpy(&p, &v, sizeof(p));
- }else{
- assert( sizeof(p)==sizeof(v2) );
- v2 = (u32)v;
- memcpy(&p, &v2, sizeof(p));
- }
- return p;
-}
-
-
-/*
-** A TCL command that returns the address of the sqlite* pointer
-** for an sqlite connection instance. Bad things happen if the
-** input is not an sqlite connection.
-*/
-static int SQLITE_TCLAPI get_sqlite_pointer(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- struct SqliteDb *p;
- Tcl_CmdInfo cmdInfo;
- char zBuf[100];
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
- return TCL_ERROR;
- }
- if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
- Tcl_AppendResult(interp, "command not found: ",
- Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- p = (struct SqliteDb*)cmdInfo.objClientData;
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p->db);
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
- struct SqliteDb *p;
- Tcl_CmdInfo cmdInfo;
- if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
- p = (struct SqliteDb*)cmdInfo.objClientData;
- *ppDb = p->db;
- }else{
- *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
- }
- return TCL_OK;
-}
-
-#if SQLITE_OS_WIN
-/*
-** Decode a Win32 HANDLE object.
-*/
-int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
- *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
- return TCL_OK;
-}
-#endif
-
-extern const char *sqlite3ErrName(int);
-#define t1ErrorName sqlite3ErrName
-
-/*
-** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
-** fact that the sqlite3* is the first field in the Vdbe structure.
-*/
-#define StmtToDb(X) sqlite3_db_handle(X)
-
-/*
-** Check a return value to make sure it agrees with the results
-** from sqlite3_errcode.
-*/
-int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
- if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK
- && sqlite3_errcode(db)!=rc ){
- char zBuf[200];
- int r2 = sqlite3_errcode(db);
- sqlite3_snprintf(sizeof(zBuf), zBuf,
- "error code %s (%d) does not match sqlite3_errcode %s (%d)",
- t1ErrorName(rc), rc, t1ErrorName(r2), r2);
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, zBuf, 0);
- return 1;
- }
- return 0;
-}
-
-/*
-** Decode a pointer to an sqlite3_stmt object.
-*/
-static int getStmtPointer(
- Tcl_Interp *interp,
- const char *zArg,
- sqlite3_stmt **ppStmt
-){
- *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg);
- return TCL_OK;
-}
-
-/*
-** Generate a text representation of a pointer that can be understood
-** by the getDbPointer and getVmPointer routines above.
-**
-** The problem is, on some machines (Solaris) if you do a printf with
-** "%p" you cannot turn around and do a scanf with the same "%p" and
-** get your pointer back. You have to prepend a "0x" before it will
-** work. Or at least that is what is reported to me (drh). But this
-** behavior varies from machine to machine. The solution used her is
-** to test the string right after it is generated to see if it can be
-** understood by scanf, and if not, try prepending an "0x" to see if
-** that helps. If nothing works, a fatal error is generated.
-*/
-int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
- sqlite3_snprintf(100, zPtr, "%p", p);
- return TCL_OK;
-}
-
-/*
-** The callback routine for sqlite3_exec_printf().
-*/
-static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
- Tcl_DString *str = (Tcl_DString*)pArg;
- int i;
-
- if( Tcl_DStringLength(str)==0 ){
- for(i=0; i<argc; i++){
- Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
- }
- }
- for(i=0; i<argc; i++){
- Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
- }
- return 0;
-}
-
-/*
-** The I/O tracing callback.
-*/
-#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
-static FILE *iotrace_file = 0;
-static void io_trace_callback(const char *zFormat, ...){
- va_list ap;
- va_start(ap, zFormat);
- vfprintf(iotrace_file, zFormat, ap);
- va_end(ap);
- fflush(iotrace_file);
-}
-#endif
-
-/*
-** Usage: io_trace FILENAME
-**
-** Turn I/O tracing on or off. If FILENAME is not an empty string,
-** I/O tracing begins going into FILENAME. If FILENAME is an empty
-** string, I/O tracing is turned off.
-*/
-static int SQLITE_TCLAPI test_io_trace(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
-#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME\"", 0);
- return TCL_ERROR;
- }
- if( iotrace_file ){
- if( iotrace_file!=stdout && iotrace_file!=stderr ){
- fclose(iotrace_file);
- }
- iotrace_file = 0;
- sqlite3IoTrace = 0;
- }
- if( argv[1][0] ){
- if( strcmp(argv[1],"stdout")==0 ){
- iotrace_file = stdout;
- }else if( strcmp(argv[1],"stderr")==0 ){
- iotrace_file = stderr;
- }else{
- iotrace_file = fopen(argv[1], "w");
- }
- sqlite3IoTrace = io_trace_callback;
- }
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: clang_sanitize_address
-**
-** Returns true if the program was compiled using clang with the
-** -fsanitize=address switch on the command line. False otherwise.
-**
-** Also return true if the OMIT_MISUSE environment variable exists.
-*/
-static int SQLITE_TCLAPI clang_sanitize_address(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int res = 0;
-#if defined(__has_feature)
-# if __has_feature(address_sanitizer)
- res = 1;
-# endif
-#endif
-#ifdef __SANITIZE_ADDRESS__
- res = 1;
-#endif
- if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1;
- Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_exec_printf DB FORMAT STRING
-**
-** Invoke the sqlite3_exec_printf() interface using the open database
-** DB. The SQL is the string FORMAT. The format string should contain
-** one %s or %q. STRING is the value inserted into %s or %q.
-*/
-static int SQLITE_TCLAPI test_exec_printf(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- Tcl_DString str;
- int rc;
- char *zErr = 0;
- char *zSql;
- char zBuf[30];
- if( argc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB FORMAT STRING", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- Tcl_DStringInit(&str);
- zSql = sqlite3_mprintf(argv[2], argv[3]);
- rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
- sqlite3_free(zSql);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
- Tcl_AppendElement(interp, zBuf);
- Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
- Tcl_DStringFree(&str);
- if( zErr ) sqlite3_free(zErr);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_exec_hex DB HEX
-**
-** Invoke the sqlite3_exec() on a string that is obtained by translating
-** HEX into ASCII. Most characters are translated as is. %HH becomes
-** a hex character.
-*/
-static int SQLITE_TCLAPI test_exec_hex(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- Tcl_DString str;
- int rc, i, j;
- char *zErr = 0;
- char *zHex;
- char zSql[501];
- char zBuf[30];
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB HEX", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- zHex = argv[2];
- for(i=j=0; i<(sizeof(zSql)-1) && zHex[j]; i++, j++){
- if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
- zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
- j += 2;
- }else{
- zSql[i] = zHex[j];
- }
- }
- zSql[i] = 0;
- Tcl_DStringInit(&str);
- rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
- Tcl_AppendElement(interp, zBuf);
- Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
- Tcl_DStringFree(&str);
- if( zErr ) sqlite3_free(zErr);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-}
-
-/*
-** Usage: db_enter DB
-** db_leave DB
-**
-** Enter or leave the mutex on a database connection.
-*/
-static int SQLITE_TCLAPI db_enter(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- sqlite3_mutex_enter(db->mutex);
- return TCL_OK;
-}
-static int SQLITE_TCLAPI db_leave(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- sqlite3_mutex_leave(db->mutex);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_exec DB SQL
-**
-** Invoke the sqlite3_exec interface using the open database DB
-*/
-static int SQLITE_TCLAPI test_exec(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- Tcl_DString str;
- int rc;
- char *zErr = 0;
- char *zSql;
- int i, j;
- char zBuf[30];
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB SQL", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- Tcl_DStringInit(&str);
- zSql = sqlite3_mprintf("%s", argv[2]);
- for(i=j=0; zSql[i];){
- if( zSql[i]=='%' ){
- zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
- i += 3;
- }else{
- zSql[j++] = zSql[i++];
- }
- }
- zSql[j] = 0;
- rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
- sqlite3_free(zSql);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
- Tcl_AppendElement(interp, zBuf);
- Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
- Tcl_DStringFree(&str);
- if( zErr ) sqlite3_free(zErr);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_exec_nr DB SQL
-**
-** Invoke the sqlite3_exec interface using the open database DB. Discard
-** all results
-*/
-static int SQLITE_TCLAPI test_exec_nr(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- int rc;
- char *zErr = 0;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB SQL", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
-**
-** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to
-** concatenate arg0 through argn using separator as the separator.
-** Return the result.
-*/
-static int SQLITE_TCLAPI test_mprintf_z(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- char *zResult = 0;
- int i;
-
- for(i=2; i<argc && (i==2 || zResult); i++){
- zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]);
- }
- Tcl_AppendResult(interp, zResult, 0);
- sqlite3_free(zResult);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_n_test STRING
-**
-** Test the %n format of sqlite_mprintf(). Return the length of the
-** input string.
-*/
-static int SQLITE_TCLAPI test_mprintf_n(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- char *zStr;
- int n = 0;
- zStr = sqlite3_mprintf("%s%n", argv[1], &n);
- sqlite3_free(zStr);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_snprintf_int SIZE FORMAT INT
-**
-** Test the of sqlite3_snprintf() routine. SIZE is the size of the
-** output buffer in bytes. The maximum size is 100. FORMAT is the
-** format string. INT is a single integer argument. The FORMAT
-** string must require no more than this one integer argument. If
-** You pass in a format string that requires more than one argument,
-** bad things will happen.
-*/
-static int SQLITE_TCLAPI test_snprintf_int(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- char zStr[100];
- int n = atoi(argv[1]);
- const char *zFormat = argv[2];
- int a1 = atoi(argv[3]);
- if( n>sizeof(zStr) ) n = sizeof(zStr);
- sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
- sqlite3_snprintf(n, zStr, zFormat, a1);
- Tcl_AppendResult(interp, zStr, 0);
- return TCL_OK;
-}
-
-#ifndef SQLITE_OMIT_GET_TABLE
-
-/*
-** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts?
-**
-** Invoke the sqlite3_get_table_printf() interface using the open database
-** DB. The SQL is the string FORMAT. The format string should contain
-** one %s or %q. STRING is the value inserted into %s or %q.
-*/
-static int SQLITE_TCLAPI test_get_table_printf(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- Tcl_DString str;
- int rc;
- char *zErr = 0;
- int nRow = 0, nCol = 0;
- char **aResult;
- int i;
- char zBuf[30];
- char *zSql;
- int resCount = -1;
- if( argc==5 ){
- if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
- }
- if( argc!=4 && argc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB FORMAT STRING ?COUNT?", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- Tcl_DStringInit(&str);
- zSql = sqlite3_mprintf(argv[2],argv[3]);
- if( argc==5 ){
- rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr);
- }else{
- rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
- resCount = (nRow+1)*nCol;
- }
- sqlite3_free(zSql);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
- Tcl_AppendElement(interp, zBuf);
- if( rc==SQLITE_OK ){
- if( argc==4 ){
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nRow);
- Tcl_AppendElement(interp, zBuf);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nCol);
- Tcl_AppendElement(interp, zBuf);
- }
- for(i=0; i<resCount; i++){
- Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
- }
- }else{
- Tcl_AppendElement(interp, zErr);
- }
- sqlite3_free_table(aResult);
- if( zErr ) sqlite3_free(zErr);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-}
-
-#endif /* SQLITE_OMIT_GET_TABLE */
-
-
-/*
-** Usage: sqlite3_last_insert_rowid DB
-**
-** Returns the integer ROWID of the most recent insert.
-*/
-static int SQLITE_TCLAPI test_last_rowid(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- char zBuf[30];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", sqlite3_last_insert_rowid(db));
- Tcl_AppendResult(interp, zBuf, 0);
- return SQLITE_OK;
-}
-
-/*
-** Usage: sqlite3_key DB KEY
-**
-** Set the codec key.
-*/
-static int SQLITE_TCLAPI test_key(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
- sqlite3 *db;
- const char *zKey;
- int nKey;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME\"", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- zKey = argv[2];
- nKey = strlen(zKey);
- sqlite3_key(db, zKey, nKey);
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_rekey DB KEY
-**
-** Change the codec key.
-*/
-static int SQLITE_TCLAPI test_rekey(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
-#ifdef SQLITE_HAS_CODEC
- sqlite3 *db;
- const char *zKey;
- int nKey;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME\"", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- zKey = argv[2];
- nKey = strlen(zKey);
- sqlite3_rekey(db, zKey, nKey);
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_close DB
-**
-** Closes the database opened by sqlite3_open.
-*/
-static int SQLITE_TCLAPI sqlite_test_close(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME\"", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- rc = sqlite3_close(db);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_close_v2 DB
-**
-** Closes the database opened by sqlite3_open.
-*/
-static int SQLITE_TCLAPI sqlite_test_close_v2(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME\"", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- rc = sqlite3_close_v2(db);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-
-/*
-** Implementation of the x_coalesce() function.
-** Return the first argument non-NULL argument.
-*/
-static void t1_ifnullFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int i;
- for(i=0; i<argc; i++){
- if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
- int n = sqlite3_value_bytes(argv[i]);
- sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
- n, SQLITE_TRANSIENT);
- break;
- }
- }
-}
-
-/*
-** These are test functions. hex8() interprets its argument as
-** UTF8 and returns a hex encoding. hex16le() interprets its argument
-** as UTF16le and returns a hex encoding.
-*/
-static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
- const unsigned char *z;
- int i;
- char zBuf[200];
- z = sqlite3_value_text(argv[0]);
- for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
- sqlite3_snprintf(sizeof(zBuf)-i*2, &zBuf[i*2], "%02x", z[i]);
- }
- zBuf[i*2] = 0;
- sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
-}
-#ifndef SQLITE_OMIT_UTF16
-static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
- const unsigned short int *z;
- int i;
- char zBuf[400];
- z = sqlite3_value_text16(argv[0]);
- for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
- sqlite3_snprintf(sizeof(zBuf)-i*4, &zBuf[i*4],"%04x", z[i]&0xff);
- }
- zBuf[i*4] = 0;
- sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
-}
-#endif
-
-/*
-** A structure into which to accumulate text.
-*/
-struct dstr {
- int nAlloc; /* Space allocated */
- int nUsed; /* Space used */
- char *z; /* The space */
-};
-
-/*
-** Append text to a dstr
-*/
-static void dstrAppend(struct dstr *p, const char *z, int divider){
- int n = (int)strlen(z);
- if( p->nUsed + n + 2 > p->nAlloc ){
- char *zNew;
- p->nAlloc = p->nAlloc*2 + n + 200;
- zNew = sqlite3_realloc(p->z, p->nAlloc);
- if( zNew==0 ){
- sqlite3_free(p->z);
- memset(p, 0, sizeof(*p));
- return;
- }
- p->z = zNew;
- }
- if( divider && p->nUsed>0 ){
- p->z[p->nUsed++] = divider;
- }
- memcpy(&p->z[p->nUsed], z, n+1);
- p->nUsed += n;
-}
-
-/*
-** Invoked for each callback from sqlite3ExecFunc
-*/
-static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
- struct dstr *p = (struct dstr*)pData;
- int i;
- for(i=0; i<argc; i++){
- if( argv[i]==0 ){
- dstrAppend(p, "NULL", ' ');
- }else{
- dstrAppend(p, argv[i], ' ');
- }
- }
- return 0;
-}
-
-/*
-** Implementation of the x_sqlite_exec() function. This function takes
-** a single argument and attempts to execute that argument as SQL code.
-** This is illegal and should set the SQLITE_MISUSE flag on the database.
-**
-** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
-** from within a function call.
-**
-** This routine simulates the effect of having two threads attempt to
-** use the same database at the same time.
-*/
-static void sqlite3ExecFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- struct dstr x;
- memset(&x, 0, sizeof(x));
- (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
- (char*)sqlite3_value_text(argv[0]),
- execFuncCallback, &x, 0);
- sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
- sqlite3_free(x.z);
-}
-
-/*
-** Implementation of tkt2213func(), a scalar function that takes exactly
-** one argument. It has two interesting features:
-**
-** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
-** If the three pointers returned are not the same an SQL error is raised.
-**
-** * Otherwise it returns a copy of the text representation of its
-** argument in such a way as the VDBE representation is a Mem* cell
-** with the MEM_Term flag clear.
-**
-** Ticket #2213 can therefore be tested by evaluating the following
-** SQL expression:
-**
-** tkt2213func(tkt2213func('a string'));
-*/
-static void tkt2213Function(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int nText;
- unsigned char const *zText1;
- unsigned char const *zText2;
- unsigned char const *zText3;
-
- nText = sqlite3_value_bytes(argv[0]);
- zText1 = sqlite3_value_text(argv[0]);
- zText2 = sqlite3_value_text(argv[0]);
- zText3 = sqlite3_value_text(argv[0]);
-
- if( zText1!=zText2 || zText2!=zText3 ){
- sqlite3_result_error(context, "tkt2213 is not fixed", -1);
- }else{
- char *zCopy = (char *)sqlite3_malloc(nText);
- memcpy(zCopy, zText1, nText);
- sqlite3_result_text(context, zCopy, nText, sqlite3_free);
- }
-}
-
-/*
-** The following SQL function takes 4 arguments. The 2nd and
-** 4th argument must be one of these strings: 'text', 'text16',
-** or 'blob' corresponding to API functions
-**
-** sqlite3_value_text()
-** sqlite3_value_text16()
-** sqlite3_value_blob()
-**
-** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
-** corresponding to APIs:
-**
-** sqlite3_value_bytes()
-** sqlite3_value_bytes16()
-** noop
-**
-** The APIs designated by the 2nd through 4th arguments are applied
-** to the first argument in order. If the pointers returned by the
-** second and fourth are different, this routine returns 1. Otherwise,
-** this routine returns 0.
-**
-** This function is used to test to see when returned pointers from
-** the _text(), _text16() and _blob() APIs become invalidated.
-*/
-static void ptrChngFunction(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const void *p1, *p2;
- const char *zCmd;
- if( argc!=4 ) return;
- zCmd = (const char*)sqlite3_value_text(argv[1]);
- if( zCmd==0 ) return;
- if( strcmp(zCmd,"text")==0 ){
- p1 = (const void*)sqlite3_value_text(argv[0]);
-#ifndef SQLITE_OMIT_UTF16
- }else if( strcmp(zCmd, "text16")==0 ){
- p1 = (const void*)sqlite3_value_text16(argv[0]);
-#endif
- }else if( strcmp(zCmd, "blob")==0 ){
- p1 = (const void*)sqlite3_value_blob(argv[0]);
- }else{
- return;
- }
- zCmd = (const char*)sqlite3_value_text(argv[2]);
- if( zCmd==0 ) return;
- if( strcmp(zCmd,"bytes")==0 ){
- sqlite3_value_bytes(argv[0]);
-#ifndef SQLITE_OMIT_UTF16
- }else if( strcmp(zCmd, "bytes16")==0 ){
- sqlite3_value_bytes16(argv[0]);
-#endif
- }else if( strcmp(zCmd, "noop")==0 ){
- /* do nothing */
- }else{
- return;
- }
- zCmd = (const char*)sqlite3_value_text(argv[3]);
- if( zCmd==0 ) return;
- if( strcmp(zCmd,"text")==0 ){
- p2 = (const void*)sqlite3_value_text(argv[0]);
-#ifndef SQLITE_OMIT_UTF16
- }else if( strcmp(zCmd, "text16")==0 ){
- p2 = (const void*)sqlite3_value_text16(argv[0]);
-#endif
- }else if( strcmp(zCmd, "blob")==0 ){
- p2 = (const void*)sqlite3_value_blob(argv[0]);
- }else{
- return;
- }
- sqlite3_result_int(context, p1!=p2);
-}
-
-/*
-** This SQL function returns a different answer each time it is called, even if
-** the arguments are the same.
-*/
-static void nondeterministicFunction(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- static int cnt = 0;
- sqlite3_result_int(context, cnt++);
-}
-
-/*
-** Usage: sqlite3_create_function DB
-**
-** Call the sqlite3_create_function API on the given database in order
-** to create a function named "x_coalesce". This function does the same thing
-** as the "coalesce" function. This function also registers an SQL function
-** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
-** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
-** The effect is similar to trying to use the same database connection from
-** two threads at the same time.
-**
-** The original motivation for this routine was to be able to call the
-** sqlite3_create_function function while a query is in progress in order
-** to test the SQLITE_MISUSE detection logic.
-*/
-static int SQLITE_TCLAPI test_create_function(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int rc;
- sqlite3 *db;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB\"", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
- t1_ifnullFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
- 0, hex8Func, 0, 0);
- }
-#ifndef SQLITE_OMIT_UTF16
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
- 0, hex16Func, 0, 0);
- }
-#endif
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
- tkt2213Function, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0,
- ptrChngFunction, 0, 0);
- }
-
- /* Functions counter1() and counter2() have the same implementation - they
- ** both return an ascending integer with each call. But counter1() is marked
- ** as non-deterministic and counter2() is marked as deterministic.
- */
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
- 0, nondeterministicFunction, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
- 0, nondeterministicFunction, 0, 0);
- }
-
-#ifndef SQLITE_OMIT_UTF16
- /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
- ** because it is not tested anywhere else. */
- if( rc==SQLITE_OK ){
- const void *zUtf16;
- sqlite3_value *pVal;
- sqlite3_mutex_enter(db->mutex);
- pVal = sqlite3ValueNew(db);
- sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
- zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
- if( db->mallocFailed ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_create_function16(db, zUtf16,
- 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
- }
- sqlite3ValueFree(pVal);
- sqlite3_mutex_leave(db->mutex);
- }
-#endif
-
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
- return TCL_OK;
-}
-
-/*
-** Routines to implement the x_count() aggregate function.
-**
-** x_count() counts the number of non-null arguments. But there are
-** some twists for testing purposes.
-**
-** If the argument to x_count() is 40 then a UTF-8 error is reported
-** on the step function. If x_count(41) is seen, then a UTF-16 error
-** is reported on the step function. If the total count is 42, then
-** a UTF-8 error is reported on the finalize function.
-*/
-typedef struct t1CountCtx t1CountCtx;
-struct t1CountCtx {
- int n;
-};
-static void t1CountStep(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- t1CountCtx *p;
- p = sqlite3_aggregate_context(context, sizeof(*p));
- if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
- p->n++;
- }
- if( argc>0 ){
- int v = sqlite3_value_int(argv[0]);
- if( v==40 ){
- sqlite3_result_error(context, "value of 40 handed to x_count", -1);
-#ifndef SQLITE_OMIT_UTF16
- }else if( v==41 ){
- const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
- sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
-#endif
- }
- }
-}
-static void t1CountFinalize(sqlite3_context *context){
- t1CountCtx *p;
- p = sqlite3_aggregate_context(context, sizeof(*p));
- if( p ){
- if( p->n==42 ){
- sqlite3_result_error(context, "x_count totals to 42", -1);
- }else{
- sqlite3_result_int(context, p ? p->n : 0);
- }
- }
-}
-
-#ifndef SQLITE_OMIT_DEPRECATED
-static void legacyCountStep(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- /* no-op */
-}
-
-static void legacyCountFinalize(sqlite3_context *context){
- sqlite3_result_int(context, sqlite3_aggregate_count(context));
-}
-#endif
-
-/*
-** Usage: sqlite3_create_aggregate DB
-**
-** Call the sqlite3_create_function API on the given database in order
-** to create a function named "x_count". This function is similar
-** to the built-in count() function, with a few special quirks
-** for testing the sqlite3_result_error() APIs.
-**
-** The original motivation for this routine was to be able to call the
-** sqlite3_create_aggregate function while a query is in progress in order
-** to test the SQLITE_MISUSE detection logic. See misuse.test.
-**
-** This routine was later extended to test the use of sqlite3_result_error()
-** within aggregate functions.
-**
-** Later: It is now also extended to register the aggregate function
-** "legacy_count()" with the supplied database handle. This is used
-** to test the deprecated sqlite3_aggregate_count() API.
-*/
-static int SQLITE_TCLAPI test_create_aggregate(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME\"", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
- t1CountStep,t1CountFinalize);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
- t1CountStep,t1CountFinalize);
- }
-#ifndef SQLITE_OMIT_DEPRECATED
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
- legacyCountStep, legacyCountFinalize
- );
- }
-#endif
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
- return TCL_OK;
-}
-
-
-/*
-** Usage: printf TEXT
-**
-** Send output to printf. Use this rather than puts to merge the output
-** in the correct sequence with debugging printfs inserted into C code.
-** Puts uses a separate buffer and debugging statements will be out of
-** sequence if it is used.
-*/
-static int SQLITE_TCLAPI test_printf(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " TEXT\"", 0);
- return TCL_ERROR;
- }
- printf("%s\n", argv[1]);
- return TCL_OK;
-}
-
-
-
-/*
-** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
-**
-** Call mprintf with three integer arguments
-*/
-static int SQLITE_TCLAPI sqlite3_mprintf_int(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int a[3], i;
- char *z;
- if( argc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FORMAT INT INT INT\"", 0);
- return TCL_ERROR;
- }
- for(i=2; i<5; i++){
- if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
- }
- z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
-**
-** Call mprintf with three 64-bit integer arguments
-*/
-static int SQLITE_TCLAPI sqlite3_mprintf_int64(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int i;
- sqlite_int64 a[3];
- char *z;
- if( argc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FORMAT INT INT INT\"", 0);
- return TCL_ERROR;
- }
- for(i=2; i<5; i++){
- if( sqlite3Atoi64(argv[i], &a[i-2], sqlite3Strlen30(argv[i]), SQLITE_UTF8) ){
- Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
- return TCL_ERROR;
- }
- }
- z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
-**
-** Call mprintf with three long integer arguments. This might be the
-** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
-** platform.
-*/
-static int SQLITE_TCLAPI sqlite3_mprintf_long(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int i;
- long int a[3];
- int b[3];
- char *z;
- if( argc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FORMAT INT INT INT\"", 0);
- return TCL_ERROR;
- }
- for(i=2; i<5; i++){
- if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR;
- a[i-2] = (long int)b[i-2];
- a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1;
- }
- z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
-**
-** Call mprintf with two integer arguments and one string argument
-*/
-static int SQLITE_TCLAPI sqlite3_mprintf_str(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int a[3], i;
- char *z;
- if( argc<4 || argc>5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FORMAT INT INT ?STRING?\"", 0);
- return TCL_ERROR;
- }
- for(i=2; i<4; i++){
- if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
- }
- z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
-**
-** Call mprintf with two integer arguments and one string argument
-*/
-static int SQLITE_TCLAPI sqlite3_snprintf_str(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int a[3], i;
- int n;
- char *z;
- if( argc<5 || argc>6 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " INT FORMAT INT INT ?STRING?\"", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
- if( n<0 ){
- Tcl_AppendResult(interp, "N must be non-negative", 0);
- return TCL_ERROR;
- }
- for(i=3; i<5; i++){
- if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
- }
- z = sqlite3_malloc( n+1 );
- sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
-**
-** Call mprintf with two integer arguments and one double argument
-*/
-static int SQLITE_TCLAPI sqlite3_mprintf_double(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int a[3], i;
- double r;
- char *z;
- if( argc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FORMAT INT INT DOUBLE\"", 0);
- return TCL_ERROR;
- }
- for(i=2; i<4; i++){
- if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
- }
- if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
- z = sqlite3_mprintf(argv[1], a[0], a[1], r);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
-**
-** Call mprintf with a single double argument which is the product of the
-** two arguments given above. This is used to generate overflow and underflow
-** doubles to test that they are converted properly.
-*/
-static int SQLITE_TCLAPI sqlite3_mprintf_scaled(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- int i;
- double r[2];
- char *z;
- if( argc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FORMAT DOUBLE DOUBLE\"", 0);
- return TCL_ERROR;
- }
- for(i=2; i<4; i++){
- if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
- }
- z = sqlite3_mprintf(argv[1], r[0]*r[1]);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_stronly FORMAT STRING
-**
-** Call mprintf with a single double argument which is the product of the
-** two arguments given above. This is used to generate overflow and underflow
-** doubles to test that they are converted properly.
-*/
-static int SQLITE_TCLAPI sqlite3_mprintf_stronly(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- char *z;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FORMAT STRING\"", 0);
- return TCL_ERROR;
- }
- z = sqlite3_mprintf(argv[1], argv[2]);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
-**
-** Call mprintf with a single double argument which is derived from the
-** hexadecimal encoding of an IEEE double.
-*/
-static int SQLITE_TCLAPI sqlite3_mprintf_hexdouble(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- char *z;
- double r;
- unsigned int x1, x2;
- sqlite_uint64 d;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FORMAT STRING\"", 0);
- return TCL_ERROR;
- }
- if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
- Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
- return TCL_ERROR;
- }
- d = x2;
- d = (d<<32) + x1;
- memcpy(&r, &d, sizeof(r));
- z = sqlite3_mprintf(argv[1], r);
- Tcl_AppendResult(interp, z, 0);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
-**
-*/
-#if !defined(SQLITE_OMIT_SHARED_CACHE)
-static int SQLITE_TCLAPI test_enable_shared(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int rc;
- int enable;
- int ret = 0;
-
- if( objc!=2 && objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
- return TCL_ERROR;
- }
- ret = sqlite3GlobalConfig.sharedCacheEnabled;
-
- if( objc==2 ){
- if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
- return TCL_ERROR;
- }
- rc = sqlite3_enable_shared_cache(enable);
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
- return TCL_ERROR;
- }
- }
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
- return TCL_OK;
-}
-#endif
-
-
-
-/*
-** Usage: sqlite3_extended_result_codes DB BOOLEAN
-**
-*/
-static int SQLITE_TCLAPI test_extended_result_codes(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int enable;
- sqlite3 *db;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
- sqlite3_extended_result_codes(db, enable);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_libversion_number
-**
-*/
-static int SQLITE_TCLAPI test_libversion_number(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_table_column_metadata DB dbname tblname colname
-**
-*/
-static int SQLITE_TCLAPI test_table_column_metadata(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- const char *zDb;
- const char *zTbl;
- const char *zCol;
- int rc;
- Tcl_Obj *pRet;
-
- const char *zDatatype;
- const char *zCollseq;
- int notnull;
- int primarykey;
- int autoincrement;
-
- if( objc!=5 && objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zDb = Tcl_GetString(objv[2]);
- zTbl = Tcl_GetString(objv[3]);
- zCol = objc==5 ? Tcl_GetString(objv[4]) : 0;
-
- if( strlen(zDb)==0 ) zDb = 0;
-
- rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
- &zDatatype, &zCollseq, &notnull, &primarykey, &autoincrement);
-
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
-
- pRet = Tcl_NewObj();
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
- Tcl_SetObjResult(interp, pRet);
-
- return TCL_OK;
-}
-
-#ifndef SQLITE_OMIT_INCRBLOB
-
-static int SQLITE_TCLAPI blobHandleFromObj(
- Tcl_Interp *interp,
- Tcl_Obj *pObj,
- sqlite3_blob **ppBlob
-){
- char *z;
- int n;
-
- z = Tcl_GetStringFromObj(pObj, &n);
- if( n==0 ){
- *ppBlob = 0;
- }else{
- int notUsed;
- Tcl_Channel channel;
- ClientData instanceData;
-
- channel = Tcl_GetChannel(interp, z, &notUsed);
- if( !channel ) return TCL_ERROR;
-
- Tcl_Flush(channel);
- Tcl_Seek(channel, 0, SEEK_SET);
-
- instanceData = Tcl_GetChannelInstanceData(channel);
- *ppBlob = *((sqlite3_blob **)instanceData);
- }
-
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_blob_reopen(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- Tcl_WideInt iRowid;
- sqlite3_blob *pBlob;
- int rc;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID");
- return TCL_ERROR;
- }
-
- if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
- if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR;
-
- rc = sqlite3_blob_reopen(pBlob, iRowid);
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- }
-
- return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
-}
-
-#endif
-
-/*
-** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
-**
-** This Tcl proc is used for testing the experimental
-** sqlite3_create_collation_v2() interface.
-*/
-struct TestCollationX {
- Tcl_Interp *interp;
- Tcl_Obj *pCmp;
- Tcl_Obj *pDel;
-};
-typedef struct TestCollationX TestCollationX;
-static void testCreateCollationDel(void *pCtx){
- TestCollationX *p = (TestCollationX *)pCtx;
-
- int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
- if( rc!=TCL_OK ){
- Tcl_BackgroundError(p->interp);
- }
-
- Tcl_DecrRefCount(p->pCmp);
- Tcl_DecrRefCount(p->pDel);
- sqlite3_free((void *)p);
-}
-static int testCreateCollationCmp(
- void *pCtx,
- int nLeft,
- const void *zLeft,
- int nRight,
- const void *zRight
-){
- TestCollationX *p = (TestCollationX *)pCtx;
- Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp);
- int iRes = 0;
-
- Tcl_IncrRefCount(pScript);
- Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft));
- Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight));
-
- if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL)
- || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes)
- ){
- Tcl_BackgroundError(p->interp);
- }
- Tcl_DecrRefCount(pScript);
-
- return iRes;
-}
-static int SQLITE_TCLAPI test_create_collation_v2(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- TestCollationX *p;
- sqlite3 *db;
- int rc;
-
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-
- p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX));
- p->pCmp = objv[3];
- p->pDel = objv[4];
- p->interp = interp;
- Tcl_IncrRefCount(p->pCmp);
- Tcl_IncrRefCount(p->pDel);
-
- rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16,
- (void *)p, testCreateCollationCmp, testCreateCollationDel
- );
- if( rc!=SQLITE_MISUSE ){
- Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect "
- "an invalid encoding", (char*)0);
- return TCL_ERROR;
- }
- rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8,
- (void *)p, testCreateCollationCmp, testCreateCollationDel
- );
- return TCL_OK;
-}
-
-/*
-** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
-**
-** Available switches are:
-**
-** -func SCRIPT
-** -step SCRIPT
-** -final SCRIPT
-** -destroy SCRIPT
-*/
-typedef struct CreateFunctionV2 CreateFunctionV2;
-struct CreateFunctionV2 {
- Tcl_Interp *interp;
- Tcl_Obj *pFunc; /* Script for function invocation */
- Tcl_Obj *pStep; /* Script for agg. step invocation */
- Tcl_Obj *pFinal; /* Script for agg. finalization invocation */
- Tcl_Obj *pDestroy; /* Destructor script */
-};
-static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
-}
-static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
-}
-static void cf2Final(sqlite3_context *ctx){
-}
-static void cf2Destroy(void *pUser){
- CreateFunctionV2 *p = (CreateFunctionV2 *)pUser;
-
- if( p->interp && p->pDestroy ){
- int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0);
- if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
- }
-
- if( p->pFunc ) Tcl_DecrRefCount(p->pFunc);
- if( p->pStep ) Tcl_DecrRefCount(p->pStep);
- if( p->pFinal ) Tcl_DecrRefCount(p->pFinal);
- if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy);
- sqlite3_free(p);
-}
-static int SQLITE_TCLAPI test_create_function_v2(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The invoking TCL interpreter */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- const char *zFunc;
- int nArg;
- int enc;
- CreateFunctionV2 *p;
- int i;
- int rc;
-
- struct EncTable {
- const char *zEnc;
- int enc;
- } aEnc[] = {
- {"utf8", SQLITE_UTF8 },
- {"utf16", SQLITE_UTF16 },
- {"utf16le", SQLITE_UTF16LE },
- {"utf16be", SQLITE_UTF16BE },
- {"any", SQLITE_ANY },
- {"0", 0 }
- };
-
- if( objc<5 || (objc%2)==0 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
- return TCL_ERROR;
- }
-
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zFunc = Tcl_GetString(objv[2]);
- if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR;
- if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]),
- "encoding", 0, &enc)
- ){
- return TCL_ERROR;
- }
- enc = aEnc[enc].enc;
-
- p = sqlite3_malloc(sizeof(CreateFunctionV2));
- assert( p );
- memset(p, 0, sizeof(CreateFunctionV2));
- p->interp = interp;
-
- for(i=5; i<objc; i+=2){
- int iSwitch;
- const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0};
- if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){
- sqlite3_free(p);
- return TCL_ERROR;
- }
-
- switch( iSwitch ){
- case 0: p->pFunc = objv[i+1]; break;
- case 1: p->pStep = objv[i+1]; break;
- case 2: p->pFinal = objv[i+1]; break;
- case 3: p->pDestroy = objv[i+1]; break;
- }
- }
- if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc);
- if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep);
- if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal);
- if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy);
-
- if( p->pFunc ) Tcl_IncrRefCount(p->pFunc);
- if( p->pStep ) Tcl_IncrRefCount(p->pStep);
- if( p->pFinal ) Tcl_IncrRefCount(p->pFinal);
- if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy);
-
- rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p,
- (p->pFunc ? cf2Func : 0),
- (p->pStep ? cf2Step : 0),
- (p->pFinal ? cf2Final : 0),
- cf2Destroy
- );
- if( rc!=SQLITE_OK ){
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
-*/
-static int SQLITE_TCLAPI test_load_extension(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- Tcl_CmdInfo cmdInfo;
- sqlite3 *db;
- int rc;
- char *zDb;
- char *zFile;
- char *zProc = 0;
- char *zErr = 0;
-
- if( objc!=4 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
- return TCL_ERROR;
- }
- zDb = Tcl_GetString(objv[1]);
- zFile = Tcl_GetString(objv[2]);
- if( objc==4 ){
- zProc = Tcl_GetString(objv[3]);
- }
-
- /* Extract the C database handle from the Tcl command name */
- if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
- Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
- return TCL_ERROR;
- }
- db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
- assert(db);
-
- /* Call the underlying C function. If an error occurs, set rc to
- ** TCL_ERROR and load any error string into the interpreter. If no
- ** error occurs, set rc to TCL_OK.
- */
-#ifdef SQLITE_OMIT_LOAD_EXTENSION
- rc = SQLITE_ERROR;
- zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
- (void)zProc;
- (void)zFile;
-#else
- rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
-#endif
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
- rc = TCL_ERROR;
- }else{
- rc = TCL_OK;
- }
- sqlite3_free(zErr);
-
- return rc;
-}
-
-/*
-** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
-*/
-static int SQLITE_TCLAPI test_enable_load(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- Tcl_CmdInfo cmdInfo;
- sqlite3 *db;
- char *zDb;
- int onoff;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
- return TCL_ERROR;
- }
- zDb = Tcl_GetString(objv[1]);
-
- /* Extract the C database handle from the Tcl command name */
- if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
- Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
- return TCL_ERROR;
- }
- db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
- assert(db);
-
- /* Get the onoff parameter */
- if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
- return TCL_ERROR;
- }
-
-#ifdef SQLITE_OMIT_LOAD_EXTENSION
- Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
- return TCL_ERROR;
-#else
- sqlite3_enable_load_extension(db, onoff);
- return TCL_OK;
-#endif
-}
-
-/*
-** Usage: sqlite_abort
-**
-** Shutdown the process immediately. This is not a clean shutdown.
-** This command is used to test the recoverability of a database in
-** the event of a program crash.
-*/
-static int SQLITE_TCLAPI sqlite_abort(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
-#if defined(_MSC_VER)
- /* We do this, otherwise the test will halt with a popup message
- * that we have to click away before the test will continue.
- */
- _set_abort_behavior( 0, _CALL_REPORTFAULT );
-#endif
- exit(255);
- assert( interp==0 ); /* This will always fail */
- return TCL_OK;
-}
-
-/*
-** The following routine is a user-defined SQL function whose purpose
-** is to test the sqlite_set_result() API.
-*/
-static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- while( argc>=2 ){
- const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
- if( zArg0 ){
- if( 0==sqlite3StrICmp(zArg0, "int") ){
- sqlite3_result_int(context, sqlite3_value_int(argv[1]));
- }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
- sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
- }else if( sqlite3StrICmp(zArg0,"string")==0 ){
- sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
- SQLITE_TRANSIENT);
- }else if( sqlite3StrICmp(zArg0,"double")==0 ){
- sqlite3_result_double(context, sqlite3_value_double(argv[1]));
- }else if( sqlite3StrICmp(zArg0,"null")==0 ){
- sqlite3_result_null(context);
- }else if( sqlite3StrICmp(zArg0,"value")==0 ){
- sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
- }else{
- goto error_out;
- }
- }else{
- goto error_out;
- }
- argc -= 2;
- argv += 2;
- }
- return;
-
-error_out:
- sqlite3_result_error(context,"first argument should be one of: "
- "int int64 string double null value", -1);
-}
-
-/*
-** Usage: sqlite_register_test_function DB NAME
-**
-** Register the test SQL function on the database DB under the name NAME.
-*/
-static int SQLITE_TCLAPI test_register_func(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3 *db;
- int rc;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB FUNCTION-NAME", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
- testFunc, 0, 0);
- if( rc!=0 ){
- Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
- return TCL_ERROR;
- }
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_finalize STMT
-**
-** Finalize a statement handle.
-*/
-static int SQLITE_TCLAPI test_finalize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int rc;
- sqlite3 *db = 0;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
-
- if( pStmt ){
- db = StmtToDb(pStmt);
- }
- rc = sqlite3_finalize(pStmt);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_stmt_status STMT CODE RESETFLAG
-**
-** Get the value of a status counter from a statement.
-*/
-static int SQLITE_TCLAPI test_stmt_status(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int iValue;
- int i, op = 0, resetFlag;
- const char *zOpName;
- sqlite3_stmt *pStmt;
-
- static const struct {
- const char *zName;
- int op;
- } aOp[] = {
- { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP },
- { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT },
- { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX },
- { "SQLITE_STMTSTATUS_VM_STEP", SQLITE_STMTSTATUS_VM_STEP },
- { "SQLITE_STMTSTATUS_REPREPARE", SQLITE_STMTSTATUS_REPREPARE },
- { "SQLITE_STMTSTATUS_RUN", SQLITE_STMTSTATUS_RUN },
- { "SQLITE_STMTSTATUS_MEMUSED", SQLITE_STMTSTATUS_MEMUSED },
- };
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- zOpName = Tcl_GetString(objv[2]);
- for(i=0; i<ArraySize(aOp); i++){
- if( strcmp(aOp[i].zName, zOpName)==0 ){
- op = aOp[i].op;
- break;
- }
- }
- if( i>=ArraySize(aOp) ){
- if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
- iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
- return TCL_OK;
-}
-
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
-/*
-** Usage: sqlite3_stmt_scanstatus STMT IDX
-*/
-static int SQLITE_TCLAPI test_stmt_scanstatus(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt; /* First argument */
- int idx; /* Second argument */
-
- const char *zName;
- const char *zExplain;
- sqlite3_int64 nLoop;
- sqlite3_int64 nVisit;
- double rEst;
- int res;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
-
- res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
- if( res==0 ){
- Tcl_Obj *pRet = Tcl_NewObj();
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
- sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
- sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
- sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
- sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
- Tcl_SetObjResult(interp, pRet);
- }else{
- Tcl_ResetResult(interp);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_stmt_scanstatus_reset STMT
-*/
-static int SQLITE_TCLAPI test_stmt_scanstatus_reset(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt; /* First argument */
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT");
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- sqlite3_stmt_scanstatus_reset(pStmt);
- return TCL_OK;
-}
-#endif
-
-#ifdef SQLITE_ENABLE_SQLLOG
-/*
-** Usage: sqlite3_config_sqllog
-**
-** Zero the SQLITE_CONFIG_SQLLOG configuration
-*/
-static int SQLITE_TCLAPI test_config_sqllog(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
- sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0);
- return TCL_OK;
-}
-#endif
-
-/*
-** Usage: sqlite3_config_sorterref
-**
-** Set the SQLITE_CONFIG_SORTERREF_SIZE configuration option
-*/
-static int SQLITE_TCLAPI test_config_sorterref(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int iVal;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &iVal) ) return TCL_ERROR;
- sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, iVal);
- return TCL_OK;
-}
-
-/*
-** Usage: vfs_current_time_int64
-**
-** Return the value returned by the default VFS's xCurrentTimeInt64 method.
-*/
-static int SQLITE_TCLAPI vfsCurrentTimeInt64(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- i64 t;
- sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
- pVfs->xCurrentTimeInt64(pVfs, &t);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t));
- return TCL_OK;
-}
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Usage: sqlite3_snapshot_get DB DBNAME
-*/
-static int SQLITE_TCLAPI test_snapshot_get(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db;
- char *zName;
- sqlite3_snapshot *pSnapshot = 0;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zName = Tcl_GetString(objv[2]);
-
- rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }else{
- char zBuf[100];
- if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1));
- }
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Usage: sqlite3_snapshot_recover DB DBNAME
-*/
-static int SQLITE_TCLAPI test_snapshot_recover(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db;
- char *zName;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zName = Tcl_GetString(objv[2]);
-
- rc = sqlite3_snapshot_recover(db, zName);
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }else{
- Tcl_ResetResult(interp);
- }
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT
-*/
-static int SQLITE_TCLAPI test_snapshot_open(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db;
- char *zName;
- sqlite3_snapshot *pSnapshot;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zName = Tcl_GetString(objv[2]);
- pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[3]));
-
- rc = sqlite3_snapshot_open(db, zName, pSnapshot);
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Usage: sqlite3_snapshot_free SNAPSHOT
-*/
-static int SQLITE_TCLAPI test_snapshot_free(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_snapshot *pSnapshot;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT");
- return TCL_ERROR;
- }
- pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- sqlite3_snapshot_free(pSnapshot);
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2
-*/
-static int SQLITE_TCLAPI test_snapshot_cmp(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int res;
- sqlite3_snapshot *p1;
- sqlite3_snapshot *p2;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
- return TCL_ERROR;
- }
- p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2]));
- res = sqlite3_snapshot_cmp(p1, p2);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Usage: sqlite3_snapshot_get_blob DB DBNAME
-*/
-static int SQLITE_TCLAPI test_snapshot_get_blob(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db;
- char *zName;
- sqlite3_snapshot *pSnapshot = 0;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zName = Tcl_GetString(objv[2]);
-
- rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }else{
- Tcl_SetObjResult(interp,
- Tcl_NewByteArrayObj((unsigned char*)pSnapshot, sizeof(sqlite3_snapshot))
- );
- sqlite3_snapshot_free(pSnapshot);
- }
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
- /*
- ** Usage: sqlite3_snapshot_open_blob DB DBNAME SNAPSHOT
-*/
-static int SQLITE_TCLAPI test_snapshot_open_blob(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db;
- char *zName;
- unsigned char *pBlob;
- int nBlob;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zName = Tcl_GetString(objv[2]);
- pBlob = Tcl_GetByteArrayFromObj(objv[3], &nBlob);
- if( nBlob!=sizeof(sqlite3_snapshot) ){
- Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
- return TCL_ERROR;
- }
- rc = sqlite3_snapshot_open(db, zName, (sqlite3_snapshot*)pBlob);
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Usage: sqlite3_snapshot_cmp_blob SNAPSHOT1 SNAPSHOT2
-*/
-static int SQLITE_TCLAPI test_snapshot_cmp_blob(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int res;
- unsigned char *p1;
- unsigned char *p2;
- int n1;
- int n2;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
- return TCL_ERROR;
- }
-
- p1 = Tcl_GetByteArrayFromObj(objv[1], &n1);
- p2 = Tcl_GetByteArrayFromObj(objv[2], &n2);
-
- if( n1!=sizeof(sqlite3_snapshot) || n1!=n2 ){
- Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
- return TCL_ERROR;
- }
-
- res = sqlite3_snapshot_cmp((sqlite3_snapshot*)p1, (sqlite3_snapshot*)p2);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
- return TCL_OK;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-/*
-** Usage: sqlite3_delete_database FILENAME
-*/
-int sqlite3_delete_database(const char*); /* in test_delete.c */
-static int SQLITE_TCLAPI test_delete_database(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- const char *zFile;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILE");
- return TCL_ERROR;
- }
- zFile = (const char*)Tcl_GetString(objv[1]);
- rc = sqlite3_delete_database(zFile);
-
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_OK;
-}
-
-/*
-** Usage: atomic_batch_write PATH
-*/
-static int SQLITE_TCLAPI test_atomic_batch_write(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- char *zFile = 0; /* Path to file to test */
- sqlite3 *db = 0; /* Database handle */
- sqlite3_file *pFd = 0; /* SQLite fd open on zFile */
- int bRes = 0; /* Integer result of this command */
- int dc = 0; /* Device-characteristics mask */
- int rc; /* sqlite3_open() return code */
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PATH");
- return TCL_ERROR;
- }
- zFile = Tcl_GetString(objv[1]);
-
- rc = sqlite3_open(zFile, &db);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
- sqlite3_close(db);
- return TCL_ERROR;
- }
-
- rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
- dc = pFd->pMethods->xDeviceCharacteristics(pFd);
- if( dc & SQLITE_IOCAP_BATCH_ATOMIC ){
- bRes = 1;
- }
-
- Tcl_SetObjResult(interp, Tcl_NewIntObj(bRes));
- sqlite3_close(db);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_next_stmt DB STMT
-**
-** Return the next statment in sequence after STMT.
-*/
-static int SQLITE_TCLAPI test_next_stmt(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- sqlite3 *db = 0;
- char zBuf[50];
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0);
- return TCL_ERROR;
- }
-
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR;
- pStmt = sqlite3_next_stmt(db, pStmt);
- if( pStmt ){
- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_stmt_readonly STMT
-**
-** Return true if STMT is a NULL pointer or a pointer to a statement
-** that is guaranteed to leave the database unmodified.
-*/
-static int SQLITE_TCLAPI test_stmt_readonly(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- rc = sqlite3_stmt_readonly(pStmt);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_stmt_busy STMT
-**
-** Return true if STMT is a non-NULL pointer to a statement
-** that has been stepped but not to completion.
-*/
-static int SQLITE_TCLAPI test_stmt_busy(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- rc = sqlite3_stmt_busy(pStmt);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
- return TCL_OK;
-}
-
-/*
-** Usage: uses_stmt_journal STMT
-**
-** Return true if STMT uses a statement journal.
-*/
-static int SQLITE_TCLAPI uses_stmt_journal(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- sqlite3_stmt_readonly(pStmt);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
- return TCL_OK;
-}
-
-
-/*
-** Usage: sqlite3_reset STMT
-**
-** Reset a statement handle.
-*/
-static int SQLITE_TCLAPI test_reset(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
-
- rc = sqlite3_reset(pStmt);
- if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
- return TCL_ERROR;
- }
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
-/*
- if( rc ){
- return TCL_ERROR;
- }
-*/
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_expired STMT
-**
-** Return TRUE if a recompilation of the statement is recommended.
-*/
-static int SQLITE_TCLAPI test_expired(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_stmt *pStmt;
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
-**
-** Transfer all bindings from FROMSTMT over to TOSTMT
-*/
-static int SQLITE_TCLAPI test_transfer_bind(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_stmt *pStmt1, *pStmt2;
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
- if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
- Tcl_SetObjResult(interp,
- Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_changes DB
-**
-** Return the number of changes made to the database by the last SQL
-** execution.
-*/
-static int SQLITE_TCLAPI test_changes(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
- return TCL_OK;
-}
-
-/*
-** This is the "static_bind_value" that variables are bound to when
-** the FLAG option of sqlite3_bind is "static"
-*/
-static char *sqlite_static_bind_value = 0;
-static int sqlite_static_bind_nbyte = 0;
-
-/*
-** Usage: sqlite3_bind VM IDX VALUE FLAGS
-**
-** Sets the value of the IDX-th occurrence of "?" in the original SQL
-** string. VALUE is the new value. If FLAGS=="null" then VALUE is
-** ignored and the value is set to NULL. If FLAGS=="static" then
-** the value is set to the value of a static variable named
-** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
-** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
-** an a 10-byte blob "abc\000xyz\000pq" is inserted.
-*/
-static int SQLITE_TCLAPI test_bind(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- sqlite3_stmt *pStmt;
- int rc;
- int idx;
- if( argc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " VM IDX VALUE (null|static|normal)\"", 0);
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
- if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
- if( strcmp(argv[4],"null")==0 ){
- rc = sqlite3_bind_null(pStmt, idx);
- }else if( strcmp(argv[4],"static")==0 ){
- rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
- }else if( strcmp(argv[4],"static-nbytes")==0 ){
- rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
- sqlite_static_bind_nbyte, 0);
- }else if( strcmp(argv[4],"normal")==0 ){
- rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
- }else if( strcmp(argv[4],"blob10")==0 ){
- rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
- }else{
- Tcl_AppendResult(interp, "4th argument should be "
- "\"null\" or \"static\" or \"normal\"", 0);
- return TCL_ERROR;
- }
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc ){
- char zBuf[50];
- sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
- Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
-**
-** This function is used to test that SQLite selects the correct collation
-** sequence callback when multiple versions (for different text encodings)
-** are available.
-**
-** Calling this routine registers the collation sequence "test_collate"
-** with database handle <db>. The second argument must be a list of three
-** boolean values. If the first is true, then a version of test_collate is
-** registered for UTF-8, if the second is true, a version is registered for
-** UTF-16le, if the third is true, a UTF-16be version is available.
-** Previous versions of test_collate are deleted.
-**
-** The collation sequence test_collate is implemented by calling the
-** following TCL script:
-**
-** "test_collate <enc> <lhs> <rhs>"
-**
-** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
-** The <enc> parameter is the encoding of the collation function that
-** SQLite selected to call. The TCL test script implements the
-** "test_collate" proc.
-**
-** Note that this will only work with one interpreter at a time, as the
-** interp pointer to use when evaluating the TCL script is stored in
-** pTestCollateInterp.
-*/
-static Tcl_Interp* pTestCollateInterp;
-static int test_collate_func(
- void *pCtx,
- int nA, const void *zA,
- int nB, const void *zB
-){
- Tcl_Interp *i = pTestCollateInterp;
- int encin = SQLITE_PTR_TO_INT(pCtx);
- int res;
- int n;
-
- sqlite3_value *pVal;
- Tcl_Obj *pX;
-
- pX = Tcl_NewStringObj("test_collate", -1);
- Tcl_IncrRefCount(pX);
-
- switch( encin ){
- case SQLITE_UTF8:
- Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
- break;
- case SQLITE_UTF16LE:
- Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
- break;
- case SQLITE_UTF16BE:
- Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
- break;
- default:
- assert(0);
- }
-
- sqlite3BeginBenignMalloc();
- pVal = sqlite3ValueNew(0);
- if( pVal ){
- sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
- n = sqlite3_value_bytes(pVal);
- Tcl_ListObjAppendElement(i,pX,
- Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
- sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
- n = sqlite3_value_bytes(pVal);
- Tcl_ListObjAppendElement(i,pX,
- Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
- sqlite3ValueFree(pVal);
- }
- sqlite3EndBenignMalloc();
-
- Tcl_EvalObjEx(i, pX, 0);
- Tcl_DecrRefCount(pX);
- Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
- return res;
-}
-static int SQLITE_TCLAPI test_collate(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int val;
- sqlite3_value *pVal;
- int rc;
-
- if( objc!=5 ) goto bad_args;
- pTestCollateInterp = interp;
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-
- if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
- rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
- (void *)SQLITE_UTF8, val?test_collate_func:0);
- if( rc==SQLITE_OK ){
- const void *zUtf16;
- if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
- rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
- (void *)SQLITE_UTF16LE, val?test_collate_func:0);
- if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
-
-#if 0
- if( sqlite3_iMallocFail>0 ){
- sqlite3_iMallocFail++;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- pVal = sqlite3ValueNew(db);
- sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
- zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
- if( db->mallocFailed ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,
- (void *)SQLITE_UTF16BE, val?test_collate_func:0);
- }
- sqlite3ValueFree(pVal);
- sqlite3_mutex_leave(db->mutex);
- }
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
-
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-
-bad_args:
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
- return TCL_ERROR;
-}
-
-/*
-** Usage: add_test_utf16bin_collate <db ptr>
-**
-** Add a utf-16 collation sequence named "utf16bin" to the database
-** handle. This collation sequence compares arguments in the same way as the
-** built-in collation "binary".
-*/
-static int test_utf16bin_collate_func(
- void *pCtx,
- int nA, const void *zA,
- int nB, const void *zB
-){
- int nCmp = (nA>nB ? nB : nA);
- int res = memcmp(zA, zB, nCmp);
- if( res==0 ) res = nA - nB;
- return res;
-}
-static int SQLITE_TCLAPI test_utf16bin_collate(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ) goto bad_args;
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-
- rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
- test_utf16bin_collate_func
- );
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-
-bad_args:
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
-}
-
-/*
-** When the collation needed callback is invoked, record the name of
-** the requested collating function here. The recorded name is linked
-** to a TCL variable and used to make sure that the requested collation
-** name is correct.
-*/
-static char zNeededCollation[200];
-static char *pzNeededCollation = zNeededCollation;
-
-
-/*
-** Called when a collating sequence is needed. Registered using
-** sqlite3_collation_needed16().
-*/
-static void test_collate_needed_cb(
- void *pCtx,
- sqlite3 *db,
- int eTextRep,
- const void *pName
-){
- int enc = ENC(db);
- int i;
- char *z;
- for(z = (char*)pName, i=0; *z || z[1]; z++){
- if( *z ) zNeededCollation[i++] = *z;
- }
- zNeededCollation[i] = 0;
- sqlite3_create_collation(
- db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func);
-}
-
-/*
-** Usage: add_test_collate_needed DB
-*/
-static int SQLITE_TCLAPI test_collate_needed(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ) goto bad_args;
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
- zNeededCollation[0] = 0;
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- return TCL_OK;
-
-bad_args:
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
-}
-
-/*
-** tclcmd: add_alignment_test_collations DB
-**
-** Add two new collating sequences to the database DB
-**
-** utf16_aligned
-** utf16_unaligned
-**
-** Both collating sequences use the same sort order as BINARY.
-** The only difference is that the utf16_aligned collating
-** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
-** Both collating functions increment the unaligned utf16 counter
-** whenever they see a string that begins on an odd byte boundary.
-*/
-static int unaligned_string_counter = 0;
-static int alignmentCollFunc(
- void *NotUsed,
- int nKey1, const void *pKey1,
- int nKey2, const void *pKey2
-){
- int rc, n;
- n = nKey1<nKey2 ? nKey1 : nKey2;
- if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++;
- if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++;
- rc = memcmp(pKey1, pKey2, n);
- if( rc==0 ){
- rc = nKey1 - nKey2;
- }
- return rc;
-}
-static int SQLITE_TCLAPI add_alignment_test_collations(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- if( objc>=2 ){
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16,
- 0, alignmentCollFunc);
- sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED,
- 0, alignmentCollFunc);
- }
- return SQLITE_OK;
-}
-#endif /* !defined(SQLITE_OMIT_UTF16) */
-
-/*
-** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
-**
-** This function is used to test that SQLite selects the correct user
-** function callback when multiple versions (for different text encodings)
-** are available.
-**
-** Calling this routine registers up to three versions of the user function
-** "test_function" with database handle <db>. If the second argument is
-** true, then a version of test_function is registered for UTF-8, if the
-** third is true, a version is registered for UTF-16le, if the fourth is
-** true, a UTF-16be version is available. Previous versions of
-** test_function are deleted.
-**
-** The user function is implemented by calling the following TCL script:
-**
-** "test_function <enc> <arg>"
-**
-** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
-** single argument passed to the SQL function. The value returned by
-** the TCL script is used as the return value of the SQL function. It
-** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
-** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
-** prefers UTF-16BE.
-*/
-#ifndef SQLITE_OMIT_UTF16
-static void test_function_utf8(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- Tcl_Interp *interp;
- Tcl_Obj *pX;
- sqlite3_value *pVal;
- interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
- pX = Tcl_NewStringObj("test_function", -1);
- Tcl_IncrRefCount(pX);
- Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
- Tcl_ListObjAppendElement(interp, pX,
- Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
- Tcl_EvalObjEx(interp, pX, 0);
- Tcl_DecrRefCount(pX);
- sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
- pVal = sqlite3ValueNew(0);
- sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
- SQLITE_UTF8, SQLITE_STATIC);
- sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
- -1, SQLITE_TRANSIENT);
- sqlite3ValueFree(pVal);
-}
-static void test_function_utf16le(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- Tcl_Interp *interp;
- Tcl_Obj *pX;
- sqlite3_value *pVal;
- interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
- pX = Tcl_NewStringObj("test_function", -1);
- Tcl_IncrRefCount(pX);
- Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
- Tcl_ListObjAppendElement(interp, pX,
- Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
- Tcl_EvalObjEx(interp, pX, 0);
- Tcl_DecrRefCount(pX);
- pVal = sqlite3ValueNew(0);
- sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
- SQLITE_UTF8, SQLITE_STATIC);
- sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
- sqlite3ValueFree(pVal);
-}
-static void test_function_utf16be(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- Tcl_Interp *interp;
- Tcl_Obj *pX;
- sqlite3_value *pVal;
- interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
- pX = Tcl_NewStringObj("test_function", -1);
- Tcl_IncrRefCount(pX);
- Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
- Tcl_ListObjAppendElement(interp, pX,
- Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
- Tcl_EvalObjEx(interp, pX, 0);
- Tcl_DecrRefCount(pX);
- pVal = sqlite3ValueNew(0);
- sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
- SQLITE_UTF8, SQLITE_STATIC);
- sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal),
- -1, SQLITE_TRANSIENT);
- sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal),
- -1, SQLITE_TRANSIENT);
- sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
- -1, SQLITE_TRANSIENT);
- sqlite3ValueFree(pVal);
-}
-#endif /* SQLITE_OMIT_UTF16 */
-static int SQLITE_TCLAPI test_function(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_UTF16
- sqlite3 *db;
- int val;
-
- if( objc!=5 ) goto bad_args;
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-
- if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
- if( val ){
- sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
- interp, test_function_utf8, 0, 0);
- }
- if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
- if( val ){
- sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
- interp, test_function_utf16le, 0, 0);
- }
- if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
- if( val ){
- sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
- interp, test_function_utf16be, 0, 0);
- }
-
- return TCL_OK;
-bad_args:
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
-#endif /* SQLITE_OMIT_UTF16 */
- return TCL_ERROR;
-}
-
-/*
-** Usage: sqlite3_test_errstr <err code>
-**
-** Test that the english language string equivalents for sqlite error codes
-** are sane. The parameter is an integer representing an sqlite error code.
-** The result is a list of two elements, the string representation of the
-** error code and the english language explanation.
-*/
-static int SQLITE_TCLAPI test_errstr(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- char *zCode;
- int i;
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
- }
-
- zCode = Tcl_GetString(objv[1]);
- for(i=0; i<200; i++){
- if( 0==strcmp(t1ErrorName(i), zCode) ) break;
- }
- Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
- return TCL_OK;
-}
-
-/*
-** Usage: breakpoint
-**
-** This routine exists for one purpose - to provide a place to put a
-** breakpoint with GDB that can be triggered using TCL code. The use
-** for this is when a particular test fails on (say) the 1485th iteration.
-** In the TCL test script, we can add code like this:
-**
-** if {$i==1485} breakpoint
-**
-** Then run testfixture in the debugger and wait for the breakpoint to
-** fire. Then additional breakpoints can be set to trace down the bug.
-*/
-static int SQLITE_TCLAPI test_breakpoint(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- char **argv /* Text of each argument */
-){
- return TCL_OK; /* Do nothing */
-}
-
-/*
-** Usage: sqlite3_bind_zeroblob STMT IDX N
-**
-** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement.
-** IDX is the index of a wildcard in the prepared statement. This command
-** binds a N-byte zero-filled BLOB to the wildcard.
-*/
-static int SQLITE_TCLAPI test_bind_zeroblob(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int idx;
- int n;
- int rc;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
-
- rc = sqlite3_bind_zeroblob(pStmt, idx, n);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_zeroblob64 STMT IDX N
-**
-** Test the sqlite3_bind_zeroblob64 interface. STMT is a prepared statement.
-** IDX is the index of a wildcard in the prepared statement. This command
-** binds a N-byte zero-filled BLOB to the wildcard.
-*/
-static int SQLITE_TCLAPI test_bind_zeroblob64(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int idx;
- Tcl_WideInt n;
- int rc;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
- if( Tcl_GetWideIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
-
- rc = sqlite3_bind_zeroblob64(pStmt, idx, n);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_int STMT N VALUE
-**
-** Test the sqlite3_bind_int interface. STMT is a prepared statement.
-** N is the index of a wildcard in the prepared statement. This command
-** binds a 32-bit integer VALUE to that wildcard.
-*/
-static int SQLITE_TCLAPI test_bind_int(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int idx;
- int value;
- int rc;
-
- if( objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
-
- rc = sqlite3_bind_int(pStmt, idx, value);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
-** Usage: intarray_addr INT ...
-**
-** Return the address of a C-language array of 32-bit integers.
-**
-** Space to hold the array is obtained from malloc(). Call this procedure once
-** with no arguments in order to release memory. Each call to this procedure
-** overwrites the previous array.
-*/
-static int SQLITE_TCLAPI test_intarray_addr(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int i;
- static int *p = 0;
-
- sqlite3_free(p);
- p = 0;
- if( objc>1 ){
- p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
- if( p==0 ) return TCL_ERROR;
- for(i=0; i<objc-1; i++){
- if( Tcl_GetIntFromObj(interp, objv[1+i], &p[i]) ){
- sqlite3_free(p);
- p = 0;
- return TCL_ERROR;
- }
- }
- }
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
- return TCL_OK;
-}
-/*
-** Usage: intarray_addr INT ...
-**
-** Return the address of a C-language array of 32-bit integers.
-**
-** Space to hold the array is obtained from malloc(). Call this procedure once
-** with no arguments in order to release memory. Each call to this procedure
-** overwrites the previous array.
-*/
-static int SQLITE_TCLAPI test_int64array_addr(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int i;
- static sqlite3_int64 *p = 0;
-
- sqlite3_free(p);
- p = 0;
- if( objc>1 ){
- p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
- if( p==0 ) return TCL_ERROR;
- for(i=0; i<objc-1; i++){
- Tcl_WideInt v;
- if( Tcl_GetWideIntFromObj(interp, objv[1+i], &v) ){
- sqlite3_free(p);
- p = 0;
- return TCL_ERROR;
- }
- p[i] = v;
- }
- }
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
- return TCL_OK;
-}
-/*
-** Usage: doublearray_addr INT ...
-**
-** Return the address of a C-language array of doubles.
-**
-** Space to hold the array is obtained from malloc(). Call this procedure once
-** with no arguments in order to release memory. Each call to this procedure
-** overwrites the previous array.
-*/
-static int SQLITE_TCLAPI test_doublearray_addr(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int i;
- static double *p = 0;
-
- sqlite3_free(p);
- p = 0;
- if( objc>1 ){
- p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
- if( p==0 ) return TCL_ERROR;
- for(i=0; i<objc-1; i++){
- if( Tcl_GetDoubleFromObj(interp, objv[1+i], &p[i]) ){
- sqlite3_free(p);
- p = 0;
- return TCL_ERROR;
- }
- }
- }
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
- return TCL_OK;
-}
-/*
-** Usage: textarray_addr TEXT ...
-**
-** Return the address of a C-language array of strings.
-**
-** Space to hold the array is obtained from malloc(). Call this procedure once
-** with no arguments in order to release memory. Each call to this procedure
-** overwrites the previous array.
-*/
-static int SQLITE_TCLAPI test_textarray_addr(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int i;
- static int n = 0;
- static char **p = 0;
-
- for(i=0; i<n; i++) sqlite3_free(p[i]);
- sqlite3_free(p);
- p = 0;
- if( objc>1 ){
- p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
- if( p==0 ) return TCL_ERROR;
- for(i=0; i<objc-1; i++){
- p[i] = sqlite3_mprintf("%s", Tcl_GetString(objv[1+i]));
- }
- }
- n = objc-1;
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
- return TCL_OK;
-}
-
-
-/*
-** Usage: sqlite3_bind_int64 STMT N VALUE
-**
-** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
-** N is the index of a wildcard in the prepared statement. This command
-** binds a 64-bit integer VALUE to that wildcard.
-*/
-static int SQLITE_TCLAPI test_bind_int64(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int idx;
- Tcl_WideInt value;
- int rc;
-
- if( objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
- if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
-
- rc = sqlite3_bind_int64(pStmt, idx, value);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
-** Usage: sqlite3_bind_double STMT N VALUE
-**
-** Test the sqlite3_bind_double interface. STMT is a prepared statement.
-** N is the index of a wildcard in the prepared statement. This command
-** binds a 64-bit integer VALUE to that wildcard.
-*/
-static int SQLITE_TCLAPI test_bind_double(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int idx;
- double value = 0;
- int rc;
- const char *zVal;
- int i;
- static const struct {
- const char *zName; /* Name of the special floating point value */
- unsigned int iUpper; /* Upper 32 bits */
- unsigned int iLower; /* Lower 32 bits */
- } aSpecialFp[] = {
- { "NaN", 0x7fffffff, 0xffffffff },
- { "SNaN", 0x7ff7ffff, 0xffffffff },
- { "-NaN", 0xffffffff, 0xffffffff },
- { "-SNaN", 0xfff7ffff, 0xffffffff },
- { "+Inf", 0x7ff00000, 0x00000000 },
- { "-Inf", 0xfff00000, 0x00000000 },
- { "Epsilon", 0x00000000, 0x00000001 },
- { "-Epsilon", 0x80000000, 0x00000001 },
- { "NaN0", 0x7ff80000, 0x00000000 },
- { "-NaN0", 0xfff80000, 0x00000000 },
- };
-
- if( objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
-
- /* Intercept the string "NaN" and generate a NaN value for it.
- ** All other strings are passed through to Tcl_GetDoubleFromObj().
- ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
- ** contain a bug.
- */
- zVal = Tcl_GetString(objv[3]);
- for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
- if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
- sqlite3_uint64 x;
- x = aSpecialFp[i].iUpper;
- x <<= 32;
- x |= aSpecialFp[i].iLower;
- assert( sizeof(value)==8 );
- assert( sizeof(x)==8 );
- memcpy(&value, &x, 8);
- break;
- }
- }
- if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
- Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
- return TCL_ERROR;
- }
- rc = sqlite3_bind_double(pStmt, idx, value);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_null STMT N
-**
-** Test the sqlite3_bind_null interface. STMT is a prepared statement.
-** N is the index of a wildcard in the prepared statement. This command
-** binds a NULL to the wildcard.
-*/
-static int SQLITE_TCLAPI test_bind_null(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int idx;
- int rc;
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
-
- rc = sqlite3_bind_null(pStmt, idx);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_text STMT N STRING BYTES
-**
-** Test the sqlite3_bind_text interface. STMT is a prepared statement.
-** N is the index of a wildcard in the prepared statement. This command
-** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
-** long.
-*/
-static int SQLITE_TCLAPI test_bind_text(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int idx;
- int bytes;
- char *value;
- int rc;
-
- if( objc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
- value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
- if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
-
- rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
-**
-** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
-** N is the index of a wildcard in the prepared statement. This command
-** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
-** long.
-*/
-static int SQLITE_TCLAPI test_bind_text16(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_UTF16
- sqlite3_stmt *pStmt;
- int idx;
- int bytes;
- char *value;
- int rc;
-
- void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
- Tcl_Obj *oStmt = objv[objc-4];
- Tcl_Obj *oN = objv[objc-3];
- Tcl_Obj *oString = objv[objc-2];
- Tcl_Obj *oBytes = objv[objc-1];
-
- if( objc!=5 && objc!=6){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
- value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
- if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
-
- rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
-
-#endif /* SQLITE_OMIT_UTF16 */
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES
-**
-** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
-** N is the index of a wildcard in the prepared statement. This command
-** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
-*/
-static int SQLITE_TCLAPI test_bind_blob(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int len, idx;
- int bytes;
- char *value;
- int rc;
- sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT;
-
- if( objc!=5 && objc!=6 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
- return TCL_ERROR;
- }
-
- if( objc==6 ){
- xDestructor = SQLITE_STATIC;
- objv++;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
-
- value = (char*)Tcl_GetByteArrayFromObj(objv[3], &len);
- if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
-
- if( bytes>len ){
- char zBuf[200];
- sqlite3_snprintf(sizeof(zBuf), zBuf,
- "cannot use %d blob bytes, have %d", bytes, len);
- Tcl_AppendResult(interp, zBuf, -1);
- return TCL_ERROR;
- }
-
- rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_parameter_count STMT
-**
-** Return the number of wildcards in the given statement.
-*/
-static int SQLITE_TCLAPI test_bind_parameter_count(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT");
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_parameter_name STMT N
-**
-** Return the name of the Nth wildcard. The first wildcard is 1.
-** An empty string is returned if N is out of range or if the wildcard
-** is nameless.
-*/
-static int SQLITE_TCLAPI test_bind_parameter_name(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int i;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
- );
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_bind_parameter_index STMT NAME
-**
-** Return the index of the wildcard called NAME. Return 0 if there is
-** no such wildcard.
-*/
-static int SQLITE_TCLAPI test_bind_parameter_index(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- Tcl_SetObjResult(interp,
- Tcl_NewIntObj(
- sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
- )
- );
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_clear_bindings STMT
-**
-*/
-static int SQLITE_TCLAPI test_clear_bindings(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT");
- return TCL_ERROR;
- }
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_sleep MILLISECONDS
-*/
-static int SQLITE_TCLAPI test_sleep(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int ms;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_extended_errcode DB
-**
-** Return the string representation of the most recent sqlite3_* API
-** error code. e.g. "SQLITE_ERROR".
-*/
-static int SQLITE_TCLAPI test_ex_errcode(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_extended_errcode(db);
- Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
- return TCL_OK;
-}
-
-
-/*
-** Usage: sqlite3_errcode DB
-**
-** Return the string representation of the most recent sqlite3_* API
-** error code. e.g. "SQLITE_ERROR".
-*/
-static int SQLITE_TCLAPI test_errcode(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_errcode(db);
- Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_errmsg DB
-**
-** Returns the UTF-8 representation of the error message string for the
-** most recent sqlite3_* API call.
-*/
-static int SQLITE_TCLAPI test_errmsg(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- const char *zErr;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-
- zErr = sqlite3_errmsg(db);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
- return TCL_OK;
-}
-
-/*
-** Usage: test_errmsg16 DB
-**
-** Returns the UTF-16 representation of the error message string for the
-** most recent sqlite3_* API call. This is a byte array object at the TCL
-** level, and it includes the 0x00 0x00 terminator bytes at the end of the
-** UTF-16 string.
-*/
-static int SQLITE_TCLAPI test_errmsg16(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_UTF16
- sqlite3 *db;
- const void *zErr;
- const char *z;
- int bytes = 0;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-
- zErr = sqlite3_errmsg16(db);
- if( zErr ){
- z = zErr;
- for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){}
- }
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
-#endif /* SQLITE_OMIT_UTF16 */
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_prepare DB sql bytes ?tailvar?
-**
-** Compile up to <bytes> bytes of the supplied SQL string <sql> using
-** database handle <DB>. The parameter <tailval> is the name of a global
-** variable that is set to the unused portion of <sql> (if any). A
-** STMT handle is returned.
-*/
-static int SQLITE_TCLAPI test_prepare(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- const char *zSql;
- int bytes;
- const char *zTail = 0;
- sqlite3_stmt *pStmt = 0;
- char zBuf[50];
- int rc;
-
- if( objc!=5 && objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zSql = Tcl_GetString(objv[2]);
- if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
-
- rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
- Tcl_ResetResult(interp);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- if( zTail && objc>=5 ){
- if( bytes>=0 ){
- bytes = bytes - (int)(zTail-zSql);
- }
- if( (int)strlen(zTail)<bytes ){
- bytes = (int)strlen(zTail);
- }
- Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
- }
- if( rc!=SQLITE_OK ){
- assert( pStmt==0 );
- sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
- Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
-
- if( pStmt ){
- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
-**
-** Compile up to <bytes> bytes of the supplied SQL string <sql> using
-** database handle <DB>. The parameter <tailval> is the name of a global
-** variable that is set to the unused portion of <sql> (if any). A
-** STMT handle is returned.
-*/
-static int SQLITE_TCLAPI test_prepare_v2(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- const char *zSql;
- char *zCopy = 0; /* malloc() copy of zSql */
- int bytes;
- const char *zTail = 0;
- sqlite3_stmt *pStmt = 0;
- char zBuf[50];
- int rc;
-
- if( objc!=5 && objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zSql = Tcl_GetString(objv[2]);
- if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
-
- /* Instead of using zSql directly, make a copy into a buffer obtained
- ** directly from malloc(). The idea is to make it easier for valgrind
- ** to spot buffer overreads. */
- if( bytes>=0 ){
- zCopy = malloc(bytes);
- memcpy(zCopy, zSql, bytes);
- }else{
- int n = (int)strlen(zSql) + 1;
- zCopy = malloc(n);
- memcpy(zCopy, zSql, n);
- }
- rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
- free(zCopy);
- zTail = &zSql[(zTail - zCopy)];
-
- assert(rc==SQLITE_OK || pStmt==0);
- Tcl_ResetResult(interp);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- if( rc==SQLITE_OK && zTail && objc>=5 ){
- if( bytes>=0 ){
- bytes = bytes - (int)(zTail-zSql);
- }
- Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
- }
- if( rc!=SQLITE_OK ){
- assert( pStmt==0 );
- sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
- Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
-
- if( pStmt ){
- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_prepare_tkt3134 DB
-**
-** Generate a prepared statement for a zero-byte string as a test
-** for ticket #3134. The string should be preceded by a zero byte.
-*/
-static int SQLITE_TCLAPI test_prepare_tkt3134(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- static const char zSql[] = "\000SELECT 1";
- sqlite3_stmt *pStmt = 0;
- char zBuf[50];
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0);
- assert(rc==SQLITE_OK || pStmt==0);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- if( rc!=SQLITE_OK ){
- assert( pStmt==0 );
- sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
- Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
-
- if( pStmt ){
- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_prepare16 DB sql bytes tailvar
-**
-** Compile up to <bytes> bytes of the supplied SQL string <sql> using
-** database handle <DB>. The parameter <tailval> is the name of a global
-** variable that is set to the unused portion of <sql> (if any). A
-** STMT handle is returned.
-*/
-static int SQLITE_TCLAPI test_prepare16(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_UTF16
- sqlite3 *db;
- const void *zSql;
- const void *zTail = 0;
- Tcl_Obj *pTail = 0;
- sqlite3_stmt *pStmt = 0;
- char zBuf[50];
- int rc;
- int bytes; /* The integer specified as arg 3 */
- int objlen; /* The byte-array length of arg 2 */
-
- if( objc!=5 && objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
- if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
-
- rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- if( rc ){
- return TCL_ERROR;
- }
-
- if( objc>=5 ){
- if( zTail ){
- objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
- }else{
- objlen = 0;
- }
- pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
- Tcl_IncrRefCount(pTail);
- Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
- Tcl_DecrRefCount(pTail);
- }
-
- if( pStmt ){
- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
- }
- Tcl_AppendResult(interp, zBuf, 0);
-#endif /* SQLITE_OMIT_UTF16 */
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
-**
-** Compile up to <bytes> bytes of the supplied SQL string <sql> using
-** database handle <DB>. The parameter <tailval> is the name of a global
-** variable that is set to the unused portion of <sql> (if any). A
-** STMT handle is returned.
-*/
-static int SQLITE_TCLAPI test_prepare16_v2(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_UTF16
- sqlite3 *db;
- const void *zSql;
- const void *zTail = 0;
- Tcl_Obj *pTail = 0;
- sqlite3_stmt *pStmt = 0;
- char zBuf[50];
- int rc;
- int bytes; /* The integer specified as arg 3 */
- int objlen; /* The byte-array length of arg 2 */
-
- if( objc!=5 && objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
- if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
-
- rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
- if( rc ){
- return TCL_ERROR;
- }
-
- if( objc>=5 ){
- if( zTail ){
- objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
- }else{
- objlen = 0;
- }
- pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
- Tcl_IncrRefCount(pTail);
- Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
- Tcl_DecrRefCount(pTail);
- }
-
- if( pStmt ){
- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
- }
- Tcl_AppendResult(interp, zBuf, 0);
-#endif /* SQLITE_OMIT_UTF16 */
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_open filename ?options-list?
-*/
-static int SQLITE_TCLAPI test_open(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zFilename;
- sqlite3 *db;
- char zBuf[100];
-
- if( objc!=3 && objc!=2 && objc!=1 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " filename options-list", 0);
- return TCL_ERROR;
- }
-
- zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
- sqlite3_open(zFilename, &db);
-
- if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
-*/
-static int SQLITE_TCLAPI test_open_v2(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zFilename;
- const char *zVfs;
- int flags = 0;
- sqlite3 *db;
- int rc;
- char zBuf[100];
-
- int nFlag;
- Tcl_Obj **apFlag;
- int i;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
- return TCL_ERROR;
- }
- zFilename = Tcl_GetString(objv[1]);
- zVfs = Tcl_GetString(objv[3]);
- if( zVfs[0]==0x00 ) zVfs = 0;
-
- rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
- if( rc!=TCL_OK ) return rc;
- for(i=0; i<nFlag; i++){
- int iFlag;
- struct OpenFlag {
- const char *zFlag;
- int flag;
- } aFlag[] = {
- { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
- { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
- { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
- { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
- { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
- { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
- { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
- { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
- { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
- { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
- { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
- { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
- { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
- { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
- { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
- { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
- { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
- { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
- { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
- { 0, 0 }
- };
- rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
- "flag", 0, &iFlag
- );
- if( rc!=TCL_OK ) return rc;
- flags |= aFlag[iFlag].flag;
- }
-
- rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
- if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_open16 filename options
-*/
-static int SQLITE_TCLAPI test_open16(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_UTF16
- const void *zFilename;
- sqlite3 *db;
- char zBuf[100];
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " filename options-list", 0);
- return TCL_ERROR;
- }
-
- zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
- sqlite3_open16(zFilename, &db);
-
- if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
-#endif /* SQLITE_OMIT_UTF16 */
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_complete16 <UTF-16 string>
-**
-** Return 1 if the supplied argument is a complete SQL statement, or zero
-** otherwise.
-*/
-static int SQLITE_TCLAPI test_complete16(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
- char *zBuf;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
- return TCL_ERROR;
- }
-
- zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
-#endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_normalize SQL
-**
-** Return the normalized value for an SQL statement.
-*/
-static int SQLITE_TCLAPI test_normalize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- char *zSql;
- char *zNorm;
- extern char *sqlite3_normalize(const char*);
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SQL");
- return TCL_ERROR;
- }
-
- zSql = (char*)Tcl_GetString(objv[1]);
- zNorm = sqlite3_normalize(zSql);
- if( zNorm ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zNorm, -1));
- sqlite3_free(zNorm);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_step STMT
-**
-** Advance the statement to the next row.
-*/
-static int SQLITE_TCLAPI test_step(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- rc = sqlite3_step(pStmt);
-
- /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_sql(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT");
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
- return TCL_OK;
-}
-static int SQLITE_TCLAPI test_ex_sql(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- char *z;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT");
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- z = sqlite3_expanded_sql(pStmt);
- Tcl_SetResult(interp, z, TCL_VOLATILE);
- sqlite3_free(z);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_column_count STMT
-**
-** Return the number of columns returned by the sql statement STMT.
-*/
-static int SQLITE_TCLAPI test_column_count(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
-
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_column_type STMT column
-**
-** Return the type of the data in column 'column' of the current row.
-*/
-static int SQLITE_TCLAPI test_column_type(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int col;
- int tp;
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
-
- tp = sqlite3_column_type(pStmt, col);
- switch( tp ){
- case SQLITE_INTEGER:
- Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
- break;
- case SQLITE_NULL:
- Tcl_SetResult(interp, "NULL", TCL_STATIC);
- break;
- case SQLITE_FLOAT:
- Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
- break;
- case SQLITE_TEXT:
- Tcl_SetResult(interp, "TEXT", TCL_STATIC);
- break;
- case SQLITE_BLOB:
- Tcl_SetResult(interp, "BLOB", TCL_STATIC);
- break;
- default:
- assert(0);
- }
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_column_int64 STMT column
-**
-** Return the data in column 'column' of the current row cast as an
-** wide (64-bit) integer.
-*/
-static int SQLITE_TCLAPI test_column_int64(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int col;
- i64 iVal;
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
-
- iVal = sqlite3_column_int64(pStmt, col);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_column_blob STMT column
-*/
-static int SQLITE_TCLAPI test_column_blob(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int col;
-
- int len;
- const void *pBlob;
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
-
- len = sqlite3_column_bytes(pStmt, col);
- pBlob = sqlite3_column_blob(pStmt, col);
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_column_double STMT column
-**
-** Return the data in column 'column' of the current row cast as a double.
-*/
-static int SQLITE_TCLAPI test_column_double(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int col;
- double rVal;
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
-
- rVal = sqlite3_column_double(pStmt, col);
- Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_data_count STMT
-**
-** Return the number of columns returned by the sql statement STMT.
-*/
-static int SQLITE_TCLAPI test_data_count(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
-
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_column_text STMT column
-**
-** Usage: sqlite3_column_decltype STMT column
-**
-** Usage: sqlite3_column_name STMT column
-*/
-static int SQLITE_TCLAPI test_stmt_utf8(
- void * clientData, /* Pointer to SQLite API function to be invoke */
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int col;
- const char *(*xFunc)(sqlite3_stmt*, int);
- const char *zRet;
-
- xFunc = (const char *(*)(sqlite3_stmt*, int))clientData;
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
- zRet = xFunc(pStmt, col);
- if( zRet ){
- Tcl_SetResult(interp, (char *)zRet, 0);
- }
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_global_recover(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_DEPRECATED
- int rc;
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
- rc = sqlite3_global_recover();
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_column_text STMT column
-**
-** Usage: sqlite3_column_decltype STMT column
-**
-** Usage: sqlite3_column_name STMT column
-*/
-static int SQLITE_TCLAPI test_stmt_utf16(
- void * clientData, /* Pointer to SQLite API function to be invoked */
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_UTF16
- sqlite3_stmt *pStmt;
- int col;
- Tcl_Obj *pRet;
- const void *zName16;
- const void *(*xFunc)(sqlite3_stmt*, int);
-
- xFunc = (const void *(*)(sqlite3_stmt*, int))clientData;
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
-
- zName16 = xFunc(pStmt, col);
- if( zName16 ){
- int n;
- const char *z = zName16;
- for(n=0; z[n] || z[n+1]; n+=2){}
- pRet = Tcl_NewByteArrayObj(zName16, n+2);
- Tcl_SetObjResult(interp, pRet);
- }
-#endif /* SQLITE_OMIT_UTF16 */
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_column_int STMT column
-**
-** Usage: sqlite3_column_bytes STMT column
-**
-** Usage: sqlite3_column_bytes16 STMT column
-**
-*/
-static int SQLITE_TCLAPI test_stmt_int(
- void * clientData, /* Pointer to SQLite API function to be invoked */
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_stmt *pStmt;
- int col;
- int (*xFunc)(sqlite3_stmt*, int);
-
- xFunc = (int (*)(sqlite3_stmt*, int))clientData;
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " STMT column", 0);
- return TCL_ERROR;
- }
-
- if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
-
- Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite_set_magic DB MAGIC-NUMBER
-**
-** Set the db->magic value. This is used to test error recovery logic.
-*/
-static int SQLITE_TCLAPI sqlite_set_magic(
- void * clientData,
- Tcl_Interp *interp,
- int argc,
- char **argv
-){
- sqlite3 *db;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB MAGIC", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
- db->magic = SQLITE_MAGIC_OPEN;
- }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
- db->magic = SQLITE_MAGIC_CLOSED;
- }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
- db->magic = SQLITE_MAGIC_BUSY;
- }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
- db->magic = SQLITE_MAGIC_ERROR;
- }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_interrupt DB
-**
-** Trigger an interrupt on DB
-*/
-static int SQLITE_TCLAPI test_interrupt(
- void * clientData,
- Tcl_Interp *interp,
- int argc,
- char **argv
-){
- sqlite3 *db;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- sqlite3_interrupt(db);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite_delete_function DB function-name
-**
-** Delete the user function 'function-name' from database handle DB. It
-** is assumed that the user function was created as UTF8, any number of
-** arguments (the way the TCL interface does it).
-*/
-static int SQLITE_TCLAPI delete_function(
- void * clientData,
- Tcl_Interp *interp,
- int argc,
- char **argv
-){
- int rc;
- sqlite3 *db;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB function-name", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite_delete_collation DB collation-name
-**
-** Delete the collation sequence 'collation-name' from database handle
-** DB. It is assumed that the collation sequence was created as UTF8 (the
-** way the TCL interface does it).
-*/
-static int SQLITE_TCLAPI delete_collation(
- void * clientData,
- Tcl_Interp *interp,
- int argc,
- char **argv
-){
- int rc;
- sqlite3 *db;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB function-name", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_get_autocommit DB
-**
-** Return true if the database DB is currently in auto-commit mode.
-** Return false if not.
-*/
-static int SQLITE_TCLAPI get_autocommit(
- void * clientData,
- Tcl_Interp *interp,
- int argc,
- char **argv
-){
- char zBuf[30];
- sqlite3 *db;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3_get_autocommit(db));
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_busy_timeout DB MS
-**
-** Set the busy timeout. This is more easily done using the timeout
-** method of the TCL interface. But we need a way to test the case
-** where it returns SQLITE_MISUSE.
-*/
-static int SQLITE_TCLAPI test_busy_timeout(
- void * clientData,
- Tcl_Interp *interp,
- int argc,
- char **argv
-){
- int rc, ms;
- sqlite3 *db;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
- if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
- rc = sqlite3_busy_timeout(db, ms);
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_OK;
-}
-
-/*
-** Usage: tcl_variable_type VARIABLENAME
-**
-** Return the name of the internal representation for the
-** value of the given variable.
-*/
-static int SQLITE_TCLAPI tcl_variable_type(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_Obj *pVar;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
- return TCL_ERROR;
- }
- pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
- if( pVar==0 ) return TCL_ERROR;
- if( pVar->typePtr ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_release_memory ?N?
-**
-** Attempt to release memory currently held but not actually required.
-** The integer N is the number of bytes we are trying to release. The
-** return value is the amount of memory actually released.
-*/
-static int SQLITE_TCLAPI test_release_memory(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
- int N;
- int amt;
- if( objc!=1 && objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?N?");
- return TCL_ERROR;
- }
- if( objc==2 ){
- if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
- }else{
- N = -1;
- }
- amt = sqlite3_release_memory(N);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
-#endif
- return TCL_OK;
-}
-
-
-/*
-** Usage: sqlite3_db_release_memory DB
-**
-** Attempt to release memory currently held by database DB. Return the
-** result code (which in the current implementation is always zero).
-*/
-static int SQLITE_TCLAPI test_db_release_memory(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int rc;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_db_release_memory(db);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_db_cacheflush DB
-**
-** Attempt to flush any dirty pages to disk.
-*/
-static int SQLITE_TCLAPI test_db_cacheflush(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int rc;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_db_cacheflush(db);
- if( rc ){
- Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
- return TCL_ERROR;
- }
-
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_system_errno DB
-**
-** Return the low-level system errno value.
-*/
-static int SQLITE_TCLAPI test_system_errno(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int iErrno;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- iErrno = sqlite3_system_errno(db);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(iErrno));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_db_filename DB DBNAME
-**
-** Return the name of a file associated with a database.
-*/
-static int SQLITE_TCLAPI test_db_filename(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- const char *zDbName;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zDbName = Tcl_GetString(objv[2]);
- Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_db_readonly DB DBNAME
-**
-** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does
-** not exist.
-*/
-static int SQLITE_TCLAPI test_db_readonly(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- const char *zDbName;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zDbName = Tcl_GetString(objv[2]);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName)));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_soft_heap_limit ?N?
-**
-** Query or set the soft heap limit for the current thread. The
-** limit is only changed if the N is present. The previous limit
-** is returned.
-*/
-static int SQLITE_TCLAPI test_soft_heap_limit(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_int64 amt;
- Tcl_WideInt N = -1;
- if( objc!=1 && objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?N?");
- return TCL_ERROR;
- }
- if( objc==2 ){
- if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
- }
- amt = sqlite3_soft_heap_limit64(N);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_thread_cleanup
-**
-** Call the sqlite3_thread_cleanup API.
-*/
-static int SQLITE_TCLAPI test_thread_cleanup(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_thread_cleanup();
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_pager_refcounts DB
-**
-** Return a list of numbers which are the PagerRefcount for all
-** pagers on each database connection.
-*/
-static int SQLITE_TCLAPI test_pager_refcounts(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- int i;
- int v, *a;
- Tcl_Obj *pResult;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- pResult = Tcl_NewObj();
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt==0 ){
- v = -1;
- }else{
- sqlite3_mutex_enter(db->mutex);
- a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
- v = a[0];
- sqlite3_mutex_leave(db->mutex);
- }
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
- }
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
-}
-
-
-/*
-** tclcmd: working_64bit_int
-**
-** Some TCL builds (ex: cygwin) do not support 64-bit integers. This
-** leads to a number of test failures. The present command checks the
-** TCL build to see whether or not it supports 64-bit integers. It
-** returns TRUE if it does and FALSE if not.
-**
-** This command is used to warn users that their TCL build is defective
-** and that the errors they are seeing in the test scripts might be
-** a result of their defective TCL rather than problems in SQLite.
-*/
-static int SQLITE_TCLAPI working_64bit_int(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- Tcl_Obj *pTestObj;
- int working = 0;
-
- pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
- working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
- Tcl_DecrRefCount(pTestObj);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
- return TCL_OK;
-}
-
-
-/*
-** tclcmd: vfs_unlink_test
-**
-** This TCL command unregisters the primary VFS and then registers
-** it back again. This is used to test the ability to register a
-** VFS when none are previously registered, and the ability to
-** unregister the only available VFS. Ticket #2738
-*/
-static int SQLITE_TCLAPI vfs_unlink_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int i;
- sqlite3_vfs *pMain;
- sqlite3_vfs *apVfs[20];
- sqlite3_vfs one, two;
-
- sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */
- one.zName = "__one";
- two.zName = "__two";
-
- /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
- ** change the default VFS
- */
- pMain = sqlite3_vfs_find(0);
- sqlite3_vfs_register(&one, 0);
- assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
- sqlite3_vfs_register(&two, 0);
- assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
-
- /* We can find a VFS by its name */
- assert( sqlite3_vfs_find("__one")==&one );
- assert( sqlite3_vfs_find("__two")==&two );
-
- /* Calling sqlite_vfs_register with non-zero second parameter changes the
- ** default VFS, even if the 1st parameter is an existig VFS that is
- ** previously registered as the non-default.
- */
- sqlite3_vfs_register(&one, 1);
- assert( sqlite3_vfs_find("__one")==&one );
- assert( sqlite3_vfs_find("__two")==&two );
- assert( sqlite3_vfs_find(0)==&one );
- sqlite3_vfs_register(&two, 1);
- assert( sqlite3_vfs_find("__one")==&one );
- assert( sqlite3_vfs_find("__two")==&two );
- assert( sqlite3_vfs_find(0)==&two );
- if( pMain ){
- sqlite3_vfs_register(pMain, 1);
- assert( sqlite3_vfs_find("__one")==&one );
- assert( sqlite3_vfs_find("__two")==&two );
- assert( sqlite3_vfs_find(0)==pMain );
- }
-
- /* Unlink the default VFS. Repeat until there are no more VFSes
- ** registered.
- */
- for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
- apVfs[i] = sqlite3_vfs_find(0);
- if( apVfs[i] ){
- assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
- sqlite3_vfs_unregister(apVfs[i]);
- assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
- }
- }
- assert( 0==sqlite3_vfs_find(0) );
-
- /* Register the main VFS as non-default (will be made default, since
- ** it'll be the only one in existence).
- */
- sqlite3_vfs_register(pMain, 0);
- assert( sqlite3_vfs_find(0)==pMain );
-
- /* Un-register the main VFS again to restore an empty VFS list */
- sqlite3_vfs_unregister(pMain);
- assert( 0==sqlite3_vfs_find(0) );
-
- /* Relink all VFSes in reverse order. */
- for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
- if( apVfs[i] ){
- sqlite3_vfs_register(apVfs[i], 1);
- assert( apVfs[i]==sqlite3_vfs_find(0) );
- assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
- }
- }
-
- /* Unregister out sample VFSes. */
- sqlite3_vfs_unregister(&one);
- sqlite3_vfs_unregister(&two);
-
- /* Unregistering a VFS that is not currently registered is harmless */
- sqlite3_vfs_unregister(&one);
- sqlite3_vfs_unregister(&two);
- assert( sqlite3_vfs_find("__one")==0 );
- assert( sqlite3_vfs_find("__two")==0 );
-
- /* We should be left with the original default VFS back as the
- ** original */
- assert( sqlite3_vfs_find(0)==pMain );
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: vfs_initfail_test
-**
-** This TCL command attempts to vfs_find and vfs_register when the
-** sqlite3_initialize() interface is failing. All calls should fail.
-*/
-static int SQLITE_TCLAPI vfs_initfail_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_vfs one;
- one.zName = "__one";
-
- if( sqlite3_vfs_find(0) ) return TCL_ERROR;
- sqlite3_vfs_register(&one, 0);
- if( sqlite3_vfs_find(0) ) return TCL_ERROR;
- sqlite3_vfs_register(&one, 1);
- if( sqlite3_vfs_find(0) ) return TCL_ERROR;
- return TCL_OK;
-}
-
-/*
-** Saved VFSes
-*/
-static sqlite3_vfs *apVfs[20];
-static int nVfs = 0;
-
-/*
-** tclcmd: vfs_unregister_all
-**
-** Unregister all VFSes.
-*/
-static int SQLITE_TCLAPI vfs_unregister_all(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int i;
- for(i=0; i<ArraySize(apVfs); i++){
- apVfs[i] = sqlite3_vfs_find(0);
- if( apVfs[i]==0 ) break;
- sqlite3_vfs_unregister(apVfs[i]);
- }
- nVfs = i;
- return TCL_OK;
-}
-/*
-** tclcmd: vfs_reregister_all
-**
-** Restore all VFSes that were removed using vfs_unregister_all. Taking
-** care to put the linked list back together in the same order as it was
-** in before vfs_unregister_all was invoked.
-*/
-static int SQLITE_TCLAPI vfs_reregister_all(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int i;
- for(i=nVfs-1; i>=0; i--){
- sqlite3_vfs_register(apVfs[i], 1);
- }
- return TCL_OK;
-}
-
-
-/*
-** tclcmd: file_control_test DB
-**
-** This TCL command runs the sqlite3_file_control interface and
-** verifies correct operation of the same.
-*/
-static int SQLITE_TCLAPI file_control_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int iArg = 0;
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_file_control(db, 0, 0, &iArg);
- assert( rc==SQLITE_NOTFOUND );
- rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
- assert( rc==SQLITE_ERROR );
- rc = sqlite3_file_control(db, "main", -1, &iArg);
- assert( rc==SQLITE_NOTFOUND );
- rc = sqlite3_file_control(db, "temp", -1, &iArg);
- assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
-
- return TCL_OK;
-}
-
-
-/*
-** tclcmd: file_control_lasterrno_test DB
-**
-** This TCL command runs the sqlite3_file_control interface and
-** verifies correct operation of the SQLITE_LAST_ERRNO verb.
-*/
-static int SQLITE_TCLAPI file_control_lasterrno_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int iArg = 0;
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg);
- if( rc ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_ERROR;
- }
- if( iArg!=0 ) {
- Tcl_AppendResult(interp, "Unexpected non-zero errno: ",
- Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** tclcmd: file_control_chunksize_test DB DBNAME SIZE
-**
-** This TCL command runs the sqlite3_file_control interface and
-** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
-** SQLITE_SET_LOCKPROXYFILE verbs.
-*/
-static int SQLITE_TCLAPI file_control_chunksize_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int nSize; /* New chunk size */
- char *zDb; /* Db name ("main", "temp" etc.) */
- sqlite3 *db; /* Database handle */
- int rc; /* file_control() return code */
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
- || Tcl_GetIntFromObj(interp, objv[3], &nSize)
- ){
- return TCL_ERROR;
- }
- zDb = Tcl_GetString(objv[2]);
- if( zDb[0]=='\0' ) zDb = NULL;
-
- rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
- if( rc ){
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** tclcmd: file_control_sizehint_test DB DBNAME SIZE
-**
-** This TCL command runs the sqlite3_file_control interface
-** with SQLITE_FCNTL_SIZE_HINT
-*/
-static int SQLITE_TCLAPI file_control_sizehint_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- Tcl_WideInt nSize; /* Hinted size */
- char *zDb; /* Db name ("main", "temp" etc.) */
- sqlite3 *db; /* Database handle */
- int rc; /* file_control() return code */
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
- || Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
- ){
- return TCL_ERROR;
- }
- zDb = Tcl_GetString(objv[2]);
- if( zDb[0]=='\0' ) zDb = NULL;
-
- rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
- if( rc ){
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** tclcmd: file_control_lockproxy_test DB PWD
-**
-** This TCL command runs the sqlite3_file_control interface and
-** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
-** SQLITE_SET_LOCKPROXYFILE verbs.
-*/
-static int SQLITE_TCLAPI file_control_lockproxy_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
-
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-# if defined(__APPLE__)
-# define SQLITE_ENABLE_LOCKING_STYLE 1
-# else
-# define SQLITE_ENABLE_LOCKING_STYLE 0
-# endif
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- {
- char *testPath;
- int rc;
- int nPwd;
- const char *zPwd;
- char proxyPath[400];
-
- zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
- if( sizeof(proxyPath)<nPwd+20 ){
- Tcl_AppendResult(interp, "PWD too big", (void*)0);
- return TCL_ERROR;
- }
- sqlite3_snprintf(sizeof(proxyPath), proxyPath, "%s/test.proxy", zPwd);
- rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
- if( rc ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_ERROR;
- }
- rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
- if( strncmp(proxyPath,testPath,11) ){
- Tcl_AppendResult(interp, "Lock proxy file did not match the "
- "previously assigned value", 0);
- return TCL_ERROR;
- }
- if( rc ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_ERROR;
- }
- rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
- if( rc ){
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_ERROR;
- }
- }
-#endif
- return TCL_OK;
-}
-
-#if SQLITE_OS_WIN
-/*
-** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
-**
-** This TCL command runs the sqlite3_file_control interface with
-** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
-*/
-static int SQLITE_TCLAPI file_control_win32_av_retry(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
- int a[2];
- char z[100];
-
- if( objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
- rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
- sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
- Tcl_AppendResult(interp, z, (char*)0);
- return TCL_OK;
-}
-
-/*
-** tclcmd: file_control_win32_get_handle DB
-**
-** This TCL command runs the sqlite3_file_control interface with
-** the SQLITE_FCNTL_WIN32_GET_HANDLE opcode.
-*/
-static int file_control_win32_get_handle(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
- HANDLE hFile = NULL;
- char z[100];
-
- if( objc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_GET_HANDLE,
- (void*)&hFile);
- sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
- Tcl_AppendResult(interp, z, (char*)0);
- return TCL_OK;
-}
-
-/*
-** tclcmd: file_control_win32_set_handle DB HANDLE
-**
-** This TCL command runs the sqlite3_file_control interface with
-** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
-*/
-static int SQLITE_TCLAPI file_control_win32_set_handle(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
- HANDLE hFile = NULL;
- char z[100];
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
- return TCL_ERROR;
- }
- rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
- (void*)&hFile);
- sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
- Tcl_AppendResult(interp, z, (char*)0);
- return TCL_OK;
-}
-#endif
-
-/*
-** tclcmd: file_control_persist_wal DB PERSIST-FLAG
-**
-** This TCL command runs the sqlite3_file_control interface with
-** the SQLITE_FCNTL_PERSIST_WAL opcode.
-*/
-static int SQLITE_TCLAPI file_control_persist_wal(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
- int bPersist;
- char z[100];
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
- rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
- sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
- Tcl_AppendResult(interp, z, (char*)0);
- return TCL_OK;
-}
-
-/*
-** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG
-**
-** This TCL command runs the sqlite3_file_control interface with
-** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
-*/
-static int SQLITE_TCLAPI file_control_powersafe_overwrite(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
- int b;
- char z[100];
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
- rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
- sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
- Tcl_AppendResult(interp, z, (char*)0);
- return TCL_OK;
-}
-
-
-/*
-** tclcmd: file_control_vfsname DB ?AUXDB?
-**
-** Return a string that describes the stack of VFSes.
-*/
-static int SQLITE_TCLAPI file_control_vfsname(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- const char *zDbName = "main";
- char *zVfsName = 0;
-
- if( objc!=2 && objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- if( objc==3 ){
- zDbName = Tcl_GetString(objv[2]);
- }
- sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
- Tcl_AppendResult(interp, zVfsName, (char*)0);
- sqlite3_free(zVfsName);
- return TCL_OK;
-}
-
-/*
-** tclcmd: file_control_tempfilename DB ?AUXDB?
-**
-** Return a string that is a temporary filename
-*/
-static int SQLITE_TCLAPI file_control_tempfilename(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- const char *zDbName = "main";
- char *zTName = 0;
-
- if( objc!=2 && objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- if( objc==3 ){
- zDbName = Tcl_GetString(objv[2]);
- }
- sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
- Tcl_AppendResult(interp, zTName, (char*)0);
- sqlite3_free(zTName);
- return TCL_OK;
-}
-
-
-/*
-** tclcmd: sqlite3_vfs_list
-**
-** Return a tcl list containing the names of all registered vfs's.
-*/
-static int SQLITE_TCLAPI vfs_list(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_vfs *pVfs;
- Tcl_Obj *pRet = Tcl_NewObj();
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
- for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
- }
- Tcl_SetObjResult(interp, pRet);
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_limit DB ID VALUE
-**
-** This TCL command runs the sqlite3_limit interface and
-** verifies correct operation of the same.
-*/
-static int SQLITE_TCLAPI test_limit(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
- static const struct {
- char *zName;
- int id;
- } aId[] = {
- { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
- { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
- { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
- { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
- { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
- { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
- { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
- { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
- { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
- { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
- { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
- { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
-
- /* Out of range test cases */
- { "SQLITE_LIMIT_TOOSMALL", -1, },
- { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
- };
- int i, id = 0;
- int val;
- const char *zId;
-
- if( objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zId = Tcl_GetString(objv[2]);
- for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
- if( strcmp(zId, aId[i].zName)==0 ){
- id = aId[i].id;
- break;
- }
- }
- if( i>=sizeof(aId)/sizeof(aId[0]) ){
- Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
- rc = sqlite3_limit(db, id, val);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** tclcmd: save_prng_state
-**
-** Save the state of the pseudo-random number generator.
-** At the same time, verify that sqlite3_test_control works even when
-** called with an out-of-range opcode.
-*/
-static int SQLITE_TCLAPI save_prng_state(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int rc = sqlite3_test_control(9999);
- assert( rc==0 );
- rc = sqlite3_test_control(-1);
- assert( rc==0 );
- sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE);
- return TCL_OK;
-}
-/*
-** tclcmd: restore_prng_state
-*/
-static int SQLITE_TCLAPI restore_prng_state(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE);
- return TCL_OK;
-}
-/*
-** tclcmd: reset_prng_state
-*/
-static int SQLITE_TCLAPI reset_prng_state(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
- return TCL_OK;
-}
-
-/*
-** tclcmd: database_may_be_corrupt
-**
-** Indicate that database files might be corrupt. In other words, set the normal
-** state of operation.
-*/
-static int SQLITE_TCLAPI database_may_be_corrupt(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0);
- return TCL_OK;
-}
-/*
-** tclcmd: database_never_corrupt
-**
-** Indicate that database files are always well-formed. This enables extra assert()
-** statements that test conditions that are always true for well-formed databases.
-*/
-static int SQLITE_TCLAPI database_never_corrupt(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1);
- return TCL_OK;
-}
-
-/*
-** tclcmd: pcache_stats
-*/
-static int SQLITE_TCLAPI test_pcache_stats(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int nMin;
- int nMax;
- int nCurrent;
- int nRecyclable;
- Tcl_Obj *pRet;
-
- sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
-
- pRet = Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
-
- Tcl_SetObjResult(interp, pRet);
-
- return TCL_OK;
-}
-
-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
-static void test_unlock_notify_cb(void **aArg, int nArg){
- int ii;
- for(ii=0; ii<nArg; ii++){
- Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL);
- }
-}
-#endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
-
-/*
-** tclcmd: sqlite3_unlock_notify db
-*/
-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
-static int SQLITE_TCLAPI test_unlock_notify(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
-
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-#endif
-
-/*
-** tclcmd: sqlite3_wal_checkpoint db ?NAME?
-*/
-static int SQLITE_TCLAPI test_wal_checkpoint(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- char *zDb = 0;
- sqlite3 *db;
- int rc;
-
- if( objc!=3 && objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?");
- return TCL_ERROR;
- }
-
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- if( objc==3 ){
- zDb = Tcl_GetString(objv[2]);
- }
- rc = sqlite3_wal_checkpoint(db, zDb);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME?
-**
-** This command calls the wal_checkpoint_v2() function with the specified
-** mode argument (passive, full or restart). If present, the database name
-** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
-** NAME argument is not present, a NULL pointer is passed instead.
-**
-** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
-** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
-** to the error message obtained from sqlite3_errmsg().
-**
-** Otherwise, this command returns a list of three integers. The first integer
-** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
-** are the values returned via the output parameters by wal_checkpoint_v2() -
-** the number of frames in the log and the number of frames in the log
-** that have been checkpointed.
-*/
-static int SQLITE_TCLAPI test_wal_checkpoint_v2(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- char *zDb = 0;
- sqlite3 *db;
- int rc;
-
- int eMode;
- int nLog = -555;
- int nCkpt = -555;
- Tcl_Obj *pRet;
-
- const char * aMode[] = { "passive", "full", "restart", "truncate", 0 };
- assert( SQLITE_CHECKPOINT_PASSIVE==0 );
- assert( SQLITE_CHECKPOINT_FULL==1 );
- assert( SQLITE_CHECKPOINT_RESTART==2 );
- assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
-
- if( objc!=3 && objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
- return TCL_ERROR;
- }
-
- if( objc==4 ){
- zDb = Tcl_GetString(objv[3]);
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || (
- TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode)
- && TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
- )){
- return TCL_ERROR;
- }
-
- rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
- if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
- const char *zErrCode = sqlite3ErrName(rc);
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
-
- pRet = Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
- Tcl_SetObjResult(interp, pRet);
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_wal_autocheckpoint db VALUE
-*/
-static int SQLITE_TCLAPI test_wal_autocheckpoint(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
- int iVal;
-
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE");
- return TCL_ERROR;
- }
-
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
- || Tcl_GetIntFromObj(0, objv[2], &iVal)
- ){
- return TCL_ERROR;
- }
-
- rc = sqlite3_wal_autocheckpoint(db, iVal);
- Tcl_ResetResult(interp);
- if( rc!=SQLITE_OK ){
- const char *zErrCode = sqlite3ErrName(rc);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1));
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
-** tclcmd: test_sqlite3_log ?SCRIPT?
-*/
-static struct LogCallback {
- Tcl_Interp *pInterp;
- Tcl_Obj *pObj;
-} logcallback = {0, 0};
-static void xLogcallback(void *unused, int err, char *zMsg){
- Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
- Tcl_IncrRefCount(pNew);
- Tcl_ListObjAppendElement(
- 0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1)
- );
- Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
- Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(pNew);
-}
-static int SQLITE_TCLAPI test_sqlite3_log(
- ClientData clientData,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- if( objc>2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
- return TCL_ERROR;
- }
- if( logcallback.pObj ){
- Tcl_DecrRefCount(logcallback.pObj);
- logcallback.pObj = 0;
- logcallback.pInterp = 0;
- sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0);
- }
- if( objc>1 ){
- logcallback.pObj = objv[1];
- Tcl_IncrRefCount(logcallback.pObj);
- logcallback.pInterp = interp;
- sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0);
- }
- return TCL_OK;
-}
-
-/*
-** tcl_objproc COMMANDNAME ARGS...
-**
-** Run a TCL command using its objProc interface. Throw an error if
-** the command has no objProc interface.
-*/
-static int SQLITE_TCLAPI runAsObjProc(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_CmdInfo cmdInfo;
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ...");
- return TCL_ERROR;
- }
- if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
- Tcl_AppendResult(interp, "command not found: ",
- Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- if( cmdInfo.objProc==0 ){
- Tcl_AppendResult(interp, "command has no objProc: ",
- Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1);
-}
-
-#ifndef SQLITE_OMIT_EXPLAIN
-/*
-** WARNING: The following function, printExplainQueryPlan() is an exact
-** copy of example code from eqp.in (eqp.html). If this code is modified,
-** then the documentation copy needs to be modified as well.
-*/
-/*
-** Argument pStmt is a prepared SQL statement. This function compiles
-** an EXPLAIN QUERY PLAN command to report on the prepared statement,
-** and prints the report to stdout using printf().
-*/
-int printExplainQueryPlan(sqlite3_stmt *pStmt){
- const char *zSql; /* Input SQL */
- char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */
- sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */
- int rc; /* Return code from sqlite3_prepare_v2() */
-
- zSql = sqlite3_sql(pStmt);
- if( zSql==0 ) return SQLITE_ERROR;
-
- zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql);
- if( zExplain==0 ) return SQLITE_NOMEM;
-
- rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0);
- sqlite3_free(zExplain);
- if( rc!=SQLITE_OK ) return rc;
-
- while( SQLITE_ROW==sqlite3_step(pExplain) ){
- int iSelectid = sqlite3_column_int(pExplain, 0);
- int iOrder = sqlite3_column_int(pExplain, 1);
- int iFrom = sqlite3_column_int(pExplain, 2);
- const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3);
-
- printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail);
- }
-
- return sqlite3_finalize(pExplain);
-}
-
-static int SQLITE_TCLAPI test_print_eqp(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3_stmt *pStmt;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT");
- return TCL_ERROR;
- }
- 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;
-}
-#endif /* SQLITE_OMIT_EXPLAIN */
-
-/*
-** sqlite3_test_control VERB ARGS...
-*/
-static int SQLITE_TCLAPI test_test_control(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- struct Verb {
- const char *zName;
- int i;
- } aVerb[] = {
- { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
- { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
- { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
- };
- int iVerb;
- int iFlag;
- int rc;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
- return TCL_ERROR;
- }
-
- rc = Tcl_GetIndexFromObjStruct(
- interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
- );
- if( rc!=TCL_OK ) return rc;
-
- iFlag = aVerb[iVerb].i;
- switch( iFlag ){
- case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
- int val;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
- return TCL_ERROR;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
- sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
- break;
- }
-
- case SQLITE_TESTCTRL_SORTER_MMAP: {
- int val;
- sqlite3 *db;
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
- sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
- break;
- }
-
- case SQLITE_TESTCTRL_IMPOSTER: {
- int onOff, tnum;
- const char *zDbName;
- sqlite3 *db;
- if( objc!=6 ){
- Tcl_WrongNumArgs(interp, 2, objv, "DB dbName onOff tnum");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
- zDbName = Tcl_GetString(objv[3]);
- if( Tcl_GetIntFromObj(interp, objv[4], &onOff) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[5], &tnum) ) return TCL_ERROR;
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum);
- break;
- }
- }
-
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-#if SQLITE_OS_UNIX
-#include <sys/time.h>
-#include <sys/resource.h>
-
-static int SQLITE_TCLAPI test_getrusage(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- char buf[1024];
- struct rusage r;
- memset(&r, 0, sizeof(r));
- getrusage(RUSAGE_SELF, &r);
-
- sqlite3_snprintf(sizeof(buf), buf,
- "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
- (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec,
- (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec,
- (int)r.ru_minflt, (int)r.ru_majflt
- );
- Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
- return TCL_OK;
-}
-#endif
-
-#if SQLITE_OS_WIN
-/*
-** Information passed from the main thread into the windows file locker
-** background thread.
-*/
-struct win32FileLocker {
- char *evName; /* Name of event to signal thread startup */
- HANDLE h; /* Handle of the file to be locked */
- int delay1; /* Delay before locking */
- int delay2; /* Delay before unlocking */
- int ok; /* Finished ok */
- int err; /* True if an error occurs */
-};
-#endif
-
-
-#if SQLITE_OS_WIN
-#include <process.h>
-/*
-** The background thread that does file locking.
-*/
-static void SQLITE_CDECL win32_file_locker(void *pAppData){
- struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
- if( p->evName ){
- HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
- if ( ev ){
- SetEvent(ev);
- CloseHandle(ev);
- }
- }
- if( p->delay1 ) Sleep(p->delay1);
- if( LockFile(p->h, 0, 0, 100000000, 0) ){
- Sleep(p->delay2);
- UnlockFile(p->h, 0, 0, 100000000, 0);
- p->ok = 1;
- }else{
- p->err = 1;
- }
- CloseHandle(p->h);
- p->h = 0;
- p->delay1 = 0;
- p->delay2 = 0;
-}
-#endif
-
-#if SQLITE_OS_WIN
-/*
-** lock_win32_file FILENAME DELAY1 DELAY2
-**
-** Get an exclusive manditory lock on file for DELAY2 milliseconds.
-** Wait DELAY1 milliseconds before acquiring the lock.
-*/
-static int SQLITE_TCLAPI win32_file_lock(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
- const char *zFilename;
- char zBuf[200];
- int retry = 0;
- HANDLE ev;
- DWORD wResult;
-
- if( objc!=4 && objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
- return TCL_ERROR;
- }
- if( objc==1 ){
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
- x.ok, x.err, x.delay1, x.delay2, x.h);
- Tcl_AppendResult(interp, zBuf, (char*)0);
- return TCL_OK;
- }
- while( x.h && retry<30 ){
- retry++;
- Sleep(100);
- }
- if( x.h ){
- Tcl_AppendResult(interp, "busy", (char*)0);
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
- zFilename = Tcl_GetString(objv[1]);
- x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, 0);
- if( !x.h ){
- Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
- return TCL_ERROR;
- }
- ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
- if ( !ev ){
- Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
- return TCL_ERROR;
- }
- _beginthread(win32_file_locker, 0, (void*)&x);
- Sleep(0);
- if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
- sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
- Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
- CloseHandle(ev);
- return TCL_ERROR;
- }
- CloseHandle(ev);
- return TCL_OK;
-}
-
-/*
-** exists_win32_path PATH
-**
-** Returns non-zero if the specified path exists, whose fully qualified name
-** may exceed 260 characters if it is prefixed with "\\?\".
-*/
-static int SQLITE_TCLAPI win32_exists_path(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PATH");
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
- GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES ));
- return TCL_OK;
-}
-
-/*
-** find_win32_file PATTERN
-**
-** Returns a list of entries in a directory that match the specified pattern,
-** whose fully qualified name may exceed 248 characters if it is prefixed with
-** "\\?\".
-*/
-static int SQLITE_TCLAPI win32_find_file(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- HANDLE hFindFile = INVALID_HANDLE_VALUE;
- WIN32_FIND_DATAW findData;
- Tcl_Obj *listObj;
- DWORD lastErrno;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PATTERN");
- return TCL_ERROR;
- }
- hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData);
- if( hFindFile==INVALID_HANDLE_VALUE ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- listObj = Tcl_NewObj();
- Tcl_IncrRefCount(listObj);
- do {
- Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj(
- findData.cFileName, -1));
- Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(
- findData.dwFileAttributes));
- } while( FindNextFileW(hFindFile, &findData) );
- lastErrno = GetLastError();
- if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){
- FindClose(hFindFile);
- Tcl_DecrRefCount(listObj);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- FindClose(hFindFile);
- Tcl_SetObjResult(interp, listObj);
- return TCL_OK;
-}
-
-/*
-** delete_win32_file FILENAME
-**
-** Deletes the specified file, whose fully qualified name may exceed 260
-** characters if it is prefixed with "\\?\".
-*/
-static int SQLITE_TCLAPI win32_delete_file(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
- return TCL_ERROR;
- }
- if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/*
-** make_win32_dir DIRECTORY
-**
-** Creates the specified directory, whose fully qualified name may exceed 248
-** characters if it is prefixed with "\\?\".
-*/
-static int SQLITE_TCLAPI win32_mkdir(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
- return TCL_ERROR;
- }
- if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/*
-** remove_win32_dir DIRECTORY
-**
-** Removes the specified directory, whose fully qualified name may exceed 248
-** characters if it is prefixed with "\\?\".
-*/
-static int SQLITE_TCLAPI win32_rmdir(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
- return TCL_ERROR;
- }
- if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-#endif
-
-
-/*
-** optimization_control DB OPT BOOLEAN
-**
-** Enable or disable query optimizations using the sqlite3_test_control()
-** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
-** OPT is the name of the optimization to be disabled.
-*/
-static int SQLITE_TCLAPI optimization_control(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int i;
- sqlite3 *db;
- const char *zOpt;
- int onoff;
- int mask = 0;
- static const struct {
- const char *zOptName;
- int mask;
- } aOpt[] = {
- { "all", SQLITE_AllOpts },
- { "none", 0 },
- { "query-flattener", SQLITE_QueryFlattener },
- { "column-cache", SQLITE_ColumnCache },
- { "groupby-order", SQLITE_GroupByOrder },
- { "factor-constants", SQLITE_FactorOutConst },
- { "distinct-opt", SQLITE_DistinctOpt },
- { "cover-idx-scan", SQLITE_CoverIdxScan },
- { "order-by-idx-join", SQLITE_OrderByIdxJoin },
- { "transitive", SQLITE_Transitive },
- { "omit-noop-join", SQLITE_OmitNoopJoin },
- { "stat3", SQLITE_Stat34 },
- { "stat4", SQLITE_Stat34 },
- };
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
- zOpt = Tcl_GetString(objv[2]);
- for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
- if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
- mask = aOpt[i].mask;
- break;
- }
- }
- if( onoff ) mask = ~mask;
- if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
- Tcl_AppendResult(interp, "unknown optimization - should be one of:",
- (char*)0);
- for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
- Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
- }
- return TCL_ERROR;
- }
- sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
- return TCL_OK;
-}
-
-/*
-** load_static_extension DB NAME ...
-**
-** Load one or more statically linked extensions.
-*/
-static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
- extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
-#ifdef SQLITE_HAVE_ZLIB
- extern int sqlite3_zipfile_init(sqlite3*,char**,const sqlite3_api_routines*);
-#endif
- static const struct {
- const char *zExtName;
- int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
- } aExtension[] = {
- { "amatch", sqlite3_amatch_init },
- { "carray", sqlite3_carray_init },
- { "closure", sqlite3_closure_init },
- { "csv", sqlite3_csv_init },
- { "eval", sqlite3_eval_init },
- { "fileio", sqlite3_fileio_init },
- { "fuzzer", sqlite3_fuzzer_init },
- { "ieee754", sqlite3_ieee_init },
- { "nextchar", sqlite3_nextchar_init },
- { "percentile", sqlite3_percentile_init },
- { "regexp", sqlite3_regexp_init },
- { "remember", sqlite3_remember_init },
- { "series", sqlite3_series_init },
- { "spellfix", sqlite3_spellfix_init },
- { "totype", sqlite3_totype_init },
- { "unionvtab", sqlite3_unionvtab_init },
- { "wholenumber", sqlite3_wholenumber_init },
-#ifdef SQLITE_HAVE_ZLIB
- { "zipfile", sqlite3_zipfile_init },
-#endif
- };
- sqlite3 *db;
- const char *zName;
- int i, j, rc;
- char *zErrMsg = 0;
- if( objc<3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ...");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- for(j=2; j<objc; j++){
- zName = Tcl_GetString(objv[j]);
- for(i=0; i<ArraySize(aExtension); i++){
- if( strcmp(zName, aExtension[i].zExtName)==0 ) break;
- }
- if( i>=ArraySize(aExtension) ){
- Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
- return TCL_ERROR;
- }
- if( aExtension[i].pInit ){
- rc = aExtension[i].pInit(db, &zErrMsg, 0);
- }else{
- rc = SQLITE_OK;
- }
- if( rc!=SQLITE_OK || zErrMsg ){
- Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
- (char*)0);
- sqlite3_free(zErrMsg);
- return TCL_ERROR;
- }
- }
- return TCL_OK;
-}
-
-/*
-** sorter_test_fakeheap BOOL
-**
-*/
-static int SQLITE_TCLAPI sorter_test_fakeheap(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int bArg;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
- return TCL_ERROR;
- }
-
- if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
- return TCL_ERROR;
- }
-
- if( bArg ){
- if( sqlite3GlobalConfig.pHeap==0 ){
- sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
- }
- }else{
- if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
- sqlite3GlobalConfig.pHeap = 0;
- }
- }
-
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/*
-** sorter_test_sort4_helper DB SQL1 NSTEP SQL2
-**
-** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
-** check that the leftmost and rightmost columns returned are both integers,
-** and that both contain the same value.
-**
-** Then execute statement $SQL2. Check that the statement returns the same
-** set of integers in the same order as in the previous step (using $SQL1).
-*/
-static int SQLITE_TCLAPI sorter_test_sort4_helper(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zSql1;
- const char *zSql2;
- int nStep;
- int iStep;
- unsigned int iCksum1 = 0;
- unsigned int iCksum2 = 0;
- int rc;
- int iB;
- sqlite3 *db;
- sqlite3_stmt *pStmt;
-
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
- return TCL_ERROR;
- }
-
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zSql1 = Tcl_GetString(objv[2]);
- if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
- zSql2 = Tcl_GetString(objv[4]);
-
- rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ) goto sql_error;
-
- iB = sqlite3_column_count(pStmt)-1;
- for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
- int a = sqlite3_column_int(pStmt, 0);
- if( a!=sqlite3_column_int(pStmt, iB) ){
- Tcl_AppendResult(interp, "data error: (a!=b)", 0);
- return TCL_ERROR;
- }
-
- iCksum1 += (iCksum1 << 3) + (unsigned int)a;
- }
- rc = sqlite3_finalize(pStmt);
- if( rc!=SQLITE_OK ) goto sql_error;
-
- rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ) goto sql_error;
- for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
- int a = sqlite3_column_int(pStmt, 0);
- iCksum2 += (iCksum2 << 3) + (unsigned int)a;
- }
- rc = sqlite3_finalize(pStmt);
- if( rc!=SQLITE_OK ) goto sql_error;
-
- if( iCksum1!=iCksum2 ){
- Tcl_AppendResult(interp, "checksum mismatch", 0);
- return TCL_ERROR;
- }
-
- return TCL_OK;
- sql_error:
- Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
- return TCL_ERROR;
-}
-
-
-#ifdef SQLITE_USER_AUTHENTICATION
-#include "sqlite3userauth.h"
-/*
-** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD
-*/
-static int SQLITE_TCLAPI test_user_authenticate(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- char *zUser = 0;
- char *zPasswd = 0;
- int nPasswd = 0;
- sqlite3 *db;
- int rc;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- zUser = Tcl_GetString(objv[2]);
- zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
- rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-#endif /* SQLITE_USER_AUTHENTICATION */
-
-#ifdef SQLITE_USER_AUTHENTICATION
-/*
-** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN
-*/
-static int SQLITE_TCLAPI test_user_add(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- char *zUser = 0;
- char *zPasswd = 0;
- int nPasswd = 0;
- int isAdmin = 0;
- sqlite3 *db;
- int rc;
-
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- zUser = Tcl_GetString(objv[2]);
- zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
- Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
- rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-#endif /* SQLITE_USER_AUTHENTICATION */
-
-#ifdef SQLITE_USER_AUTHENTICATION
-/*
-** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN
-*/
-static int SQLITE_TCLAPI test_user_change(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- char *zUser = 0;
- char *zPasswd = 0;
- int nPasswd = 0;
- int isAdmin = 0;
- sqlite3 *db;
- int rc;
-
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- zUser = Tcl_GetString(objv[2]);
- zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
- Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
- rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-#endif /* SQLITE_USER_AUTHENTICATION */
-
-#ifdef SQLITE_USER_AUTHENTICATION
-/*
-** tclcmd: sqlite3_user_delete DB USERNAME
-*/
-static int SQLITE_TCLAPI test_user_delete(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- char *zUser = 0;
- sqlite3 *db;
- int rc;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
- return TCL_ERROR;
- }
- zUser = Tcl_GetString(objv[2]);
- rc = sqlite3_user_delete(db, zUser);
- Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
- return TCL_OK;
-}
-#endif /* SQLITE_USER_AUTHENTICATION */
-
-/*
-** tclcmd: bad_behavior TYPE
-**
-** Do some things that should trigger a valgrind or -fsanitize=undefined
-** warning. This is used to verify that errors and warnings output by those
-** tools are detected by the test scripts.
-**
-** TYPE BEHAVIOR
-** 1 Overflow a signed integer
-** 2 Jump based on an uninitialized variable
-** 3 Read after free
-** 4 Panic
-*/
-static int SQLITE_TCLAPI test_bad_behavior(
- ClientData clientData, /* Pointer to an integer containing zero */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int iType;
- int xyz;
- int i = *(int*)clientData;
- int j;
- int w[10];
- int *a;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "TYPE");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR;
- switch( iType ){
- case 1: {
- xyz = 0x7fffff00 - i;
- xyz += 0x100;
- Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz));
- break;
- }
- case 2: {
- w[1] = 5;
- if( w[i]>0 ) w[1]++;
- Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1]));
- break;
- }
- case 3: {
- a = malloc( sizeof(int)*10 );
- for(j=0; j<10; j++) a[j] = j;
- free(a);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i]));
- break;
- }
- case 4: {
- Tcl_Panic("Deliberate panic");
- break;
- }
- }
- return TCL_OK;
-}
-
-/*
-** tclcmd: register_dbstat_vtab DB
-**
-** Cause the dbstat virtual table to be available on the connection DB
-*/
-static int SQLITE_TCLAPI test_register_dbstat_vtab(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifdef SQLITE_OMIT_VIRTUALTABLE
- Tcl_AppendResult(interp, "dbstat not available because of "
- "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
- return TCL_ERROR;
-#else
- struct SqliteDb { sqlite3 *db; };
- char *zDb;
- Tcl_CmdInfo cmdInfo;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
-
- zDb = Tcl_GetString(objv[1]);
- if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
- sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
- sqlite3DbstatRegister(db);
- }
- return TCL_OK;
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-}
-
-/*
-** tclcmd: sqlite3_db_config DB SETTING VALUE
-**
-** Invoke sqlite3_db_config() for one of the setting values.
-*/
-static int SQLITE_TCLAPI test_sqlite3_db_config(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- static const struct {
- const char *zName;
- int eVal;
- } aSetting[] = {
- { "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY },
- { "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER },
- { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
- { "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
- { "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
- { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG },
- { "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP },
- { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE },
- };
- int i;
- int v;
- const char *zSetting;
- sqlite3 *db;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB SETTING VALUE");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zSetting = Tcl_GetString(objv[2]);
- if( sqlite3_strglob("SQLITE_*", zSetting)==0 ) zSetting += 7;
- if( sqlite3_strglob("DBCONFIG_*", zSetting)==0 ) zSetting += 9;
- if( sqlite3_strglob("ENABLE_*", zSetting)==0 ) zSetting += 7;
- for(i=0; i<ArraySize(aSetting); i++){
- if( strcmp(zSetting, aSetting[i].zName)==0 ) break;
- }
- if( i>=ArraySize(aSetting) ){
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("unknown sqlite3_db_config setting", -1));
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[3], &v) ) return TCL_ERROR;
- sqlite3_db_config(db, aSetting[i].eVal, v, &v);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
- return TCL_OK;
-}
-
-/*
-** Change the name of the main database schema from "main" to "icecube".
-*/
-static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db;
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }else{
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "icecube");
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
- }
-}
-
-/*
-** Usage: sqlite3_mmap_warm DB DBNAME
-*/
-static int SQLITE_TCLAPI test_mmap_warm(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- extern int sqlite3_mmap_warm(sqlite3 *db, const char *);
-
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB ?DBNAME?");
- return TCL_ERROR;
- }else{
- int rc;
- sqlite3 *db;
- const char *zDb = 0;
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- if( objc==3 ){
- zDb = Tcl_GetString(objv[2]);
- }
- rc = sqlite3_mmap_warm(db, zDb);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_OK;
- }
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest1_Init(Tcl_Interp *interp){
- extern int sqlite3_search_count;
- extern int sqlite3_found_count;
- extern int sqlite3_interrupt_count;
- extern int sqlite3_open_file_count;
- extern int sqlite3_sort_count;
- extern int sqlite3_current_time;
-#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- extern int sqlite3_hostid_num;
-#endif
- extern int sqlite3_max_blobsize;
- extern int SQLITE_TCLAPI sqlite3BtreeSharedCacheReport(void*,
- Tcl_Interp*,int,Tcl_Obj*CONST*);
- static int iZero = 0;
- static struct {
- char *zName;
- Tcl_CmdProc *xProc;
- } aCmd[] = {
- { "db_enter", (Tcl_CmdProc*)db_enter },
- { "db_leave", (Tcl_CmdProc*)db_leave },
- { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
- { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
- { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long },
- { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
- { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str },
- { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
- { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
- { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
- { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
- { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
- { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n },
- { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int },
- { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
- { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
- { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex },
- { "sqlite3_exec", (Tcl_CmdProc*)test_exec },
- { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr },
-#ifndef SQLITE_OMIT_GET_TABLE
- { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
-#endif
- { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
- { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 },
- { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
- { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
- { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
- { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
- { "sqlite_bind", (Tcl_CmdProc*)test_bind },
- { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
- { "sqlite3_key", (Tcl_CmdProc*)test_key },
- { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
- { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
- { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
- { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
- { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
- { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
- { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
- { "printf", (Tcl_CmdProc*)test_printf },
- { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
- { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address },
- };
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- void *clientData;
- } aObjCmd[] = {
- { "sqlite3_db_config", test_sqlite3_db_config, 0 },
- { "bad_behavior", test_bad_behavior, (void*)&iZero },
- { "register_dbstat_vtab", test_register_dbstat_vtab },
- { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
- { "intarray_addr", test_intarray_addr, 0 },
- { "int64array_addr", test_int64array_addr, 0 },
- { "doublearray_addr", test_doublearray_addr, 0 },
- { "textarray_addr", test_textarray_addr, 0 },
- { "sqlite3_bind_int", test_bind_int, 0 },
- { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
- { "sqlite3_bind_zeroblob64", test_bind_zeroblob64, 0 },
- { "sqlite3_bind_int64", test_bind_int64, 0 },
- { "sqlite3_bind_double", test_bind_double, 0 },
- { "sqlite3_bind_null", test_bind_null ,0 },
- { "sqlite3_bind_text", test_bind_text ,0 },
- { "sqlite3_bind_text16", test_bind_text16 ,0 },
- { "sqlite3_bind_blob", test_bind_blob ,0 },
- { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
- { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
- { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
- { "sqlite3_clear_bindings", test_clear_bindings, 0},
- { "sqlite3_sleep", test_sleep, 0},
- { "sqlite3_errcode", test_errcode ,0 },
- { "sqlite3_extended_errcode", test_ex_errcode ,0 },
- { "sqlite3_errmsg", test_errmsg ,0 },
- { "sqlite3_errmsg16", test_errmsg16 ,0 },
- { "sqlite3_open", test_open ,0 },
- { "sqlite3_open16", test_open16 ,0 },
- { "sqlite3_open_v2", test_open_v2 ,0 },
- { "sqlite3_complete16", test_complete16 ,0 },
- { "sqlite3_normalize", test_normalize ,0 },
-
- { "sqlite3_prepare", test_prepare ,0 },
- { "sqlite3_prepare16", test_prepare16 ,0 },
- { "sqlite3_prepare_v2", test_prepare_v2 ,0 },
- { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0},
- { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 },
- { "sqlite3_finalize", test_finalize ,0 },
- { "sqlite3_stmt_status", test_stmt_status ,0 },
- { "sqlite3_reset", test_reset ,0 },
- { "sqlite3_expired", test_expired ,0 },
- { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
- { "sqlite3_changes", test_changes ,0 },
- { "sqlite3_step", test_step ,0 },
- { "sqlite3_sql", test_sql ,0 },
- { "sqlite3_expanded_sql", test_ex_sql ,0 },
- { "sqlite3_next_stmt", test_next_stmt ,0 },
- { "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
- { "sqlite3_stmt_busy", test_stmt_busy ,0 },
- { "uses_stmt_journal", uses_stmt_journal ,0 },
-
- { "sqlite3_release_memory", test_release_memory, 0},
- { "sqlite3_db_release_memory", test_db_release_memory, 0},
- { "sqlite3_db_cacheflush", test_db_cacheflush, 0},
- { "sqlite3_system_errno", test_system_errno, 0},
- { "sqlite3_db_filename", test_db_filename, 0},
- { "sqlite3_db_readonly", test_db_readonly, 0},
- { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
- { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
- { "sqlite3_pager_refcounts", test_pager_refcounts, 0},
-
- { "sqlite3_load_extension", test_load_extension, 0},
- { "sqlite3_enable_load_extension", test_enable_load, 0},
- { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
- { "sqlite3_limit", test_limit, 0},
- { "dbconfig_maindbname_icecube", test_dbconfig_maindbname_icecube },
-
- { "save_prng_state", save_prng_state, 0 },
- { "restore_prng_state", restore_prng_state, 0 },
- { "reset_prng_state", reset_prng_state, 0 },
- { "database_never_corrupt", database_never_corrupt, 0},
- { "database_may_be_corrupt", database_may_be_corrupt, 0},
- { "optimization_control", optimization_control,0},
-#if SQLITE_OS_WIN
- { "lock_win32_file", win32_file_lock, 0 },
- { "exists_win32_path", win32_exists_path, 0 },
- { "find_win32_file", win32_find_file, 0 },
- { "delete_win32_file", win32_delete_file, 0 },
- { "make_win32_dir", win32_mkdir, 0 },
- { "remove_win32_dir", win32_rmdir, 0 },
-#endif
- { "tcl_objproc", runAsObjProc, 0 },
-
- /* sqlite3_column_*() API */
- { "sqlite3_column_count", test_column_count ,0 },
- { "sqlite3_data_count", test_data_count ,0 },
- { "sqlite3_column_type", test_column_type ,0 },
- { "sqlite3_column_blob", test_column_blob ,0 },
- { "sqlite3_column_double", test_column_double ,0 },
- { "sqlite3_column_int64", test_column_int64 ,0 },
- { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text },
- { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name },
- { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int },
- { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes},
-#ifndef SQLITE_OMIT_DECLTYPE
- { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype},
-#endif
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
-{ "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name},
-{ "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name},
-{ "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name},
-#endif
-
-#ifndef SQLITE_OMIT_UTF16
- { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 },
- { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16},
- { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16},
- { "add_alignment_test_collations", add_alignment_test_collations, 0 },
-#ifndef SQLITE_OMIT_DECLTYPE
- { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16},
-#endif
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
-{"sqlite3_column_database_name16",
- test_stmt_utf16, (void*)sqlite3_column_database_name16},
-{"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
-{"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
-#endif
-#endif
- { "sqlite3_create_collation_v2", test_create_collation_v2, 0 },
- { "sqlite3_global_recover", test_global_recover, 0 },
- { "working_64bit_int", working_64bit_int, 0 },
- { "vfs_unlink_test", vfs_unlink_test, 0 },
- { "vfs_initfail_test", vfs_initfail_test, 0 },
- { "vfs_unregister_all", vfs_unregister_all, 0 },
- { "vfs_reregister_all", vfs_reregister_all, 0 },
- { "file_control_test", file_control_test, 0 },
- { "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
- { "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
- { "file_control_chunksize_test", file_control_chunksize_test, 0 },
- { "file_control_sizehint_test", file_control_sizehint_test, 0 },
-#if SQLITE_OS_WIN
- { "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
- { "file_control_win32_get_handle", file_control_win32_get_handle, 0 },
- { "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
-#endif
- { "file_control_persist_wal", file_control_persist_wal, 0 },
- { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
- { "file_control_vfsname", file_control_vfsname, 0 },
- { "file_control_tempfilename", file_control_tempfilename, 0 },
- { "sqlite3_vfs_list", vfs_list, 0 },
- { "sqlite3_create_function_v2", test_create_function_v2, 0 },
-
- /* Functions from os.h */
-#ifndef SQLITE_OMIT_UTF16
- { "add_test_collate", test_collate, 0 },
- { "add_test_collate_needed", test_collate_needed, 0 },
- { "add_test_function", test_function, 0 },
- { "add_test_utf16bin_collate", test_utf16bin_collate, 0 },
-#endif
- { "sqlite3_test_errstr", test_errstr, 0 },
- { "tcl_variable_type", tcl_variable_type, 0 },
-#ifndef SQLITE_OMIT_SHARED_CACHE
- { "sqlite3_enable_shared_cache", test_enable_shared, 0 },
- { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
-#endif
- { "sqlite3_libversion_number", test_libversion_number, 0 },
- { "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
-#ifndef SQLITE_OMIT_INCRBLOB
- { "sqlite3_blob_reopen", test_blob_reopen, 0 },
-#endif
- { "pcache_stats", test_pcache_stats, 0 },
-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
- { "sqlite3_unlock_notify", test_unlock_notify, 0 },
-#endif
- { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
- { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
- { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 },
- { "test_sqlite3_log", test_sqlite3_log, 0 },
-#ifndef SQLITE_OMIT_EXPLAIN
- { "print_explain_query_plan", test_print_eqp, 0 },
-#endif
- { "sqlite3_test_control", test_test_control },
-#if SQLITE_OS_UNIX
- { "getrusage", test_getrusage },
-#endif
- { "load_static_extension", tclLoadStaticExtensionCmd },
- { "sorter_test_fakeheap", sorter_test_fakeheap },
- { "sorter_test_sort4_helper", sorter_test_sort4_helper },
-#ifdef SQLITE_USER_AUTHENTICATION
- { "sqlite3_user_authenticate", test_user_authenticate, 0 },
- { "sqlite3_user_add", test_user_add, 0 },
- { "sqlite3_user_change", test_user_change, 0 },
- { "sqlite3_user_delete", test_user_delete, 0 },
-#endif
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- { "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 },
- { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 },
-#endif
-#ifdef SQLITE_ENABLE_SQLLOG
- { "sqlite3_config_sqllog", test_config_sqllog, 0 },
-#endif
- { "vfs_current_time_int64", vfsCurrentTimeInt64, 0 },
-#ifdef SQLITE_ENABLE_SNAPSHOT
- { "sqlite3_snapshot_get", test_snapshot_get, 0 },
- { "sqlite3_snapshot_open", test_snapshot_open, 0 },
- { "sqlite3_snapshot_free", test_snapshot_free, 0 },
- { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
- { "sqlite3_snapshot_recover", test_snapshot_recover, 0 },
- { "sqlite3_snapshot_get_blob", test_snapshot_get_blob, 0 },
- { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 },
- { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 },
-#endif
- { "sqlite3_delete_database", test_delete_database, 0 },
- { "atomic_batch_write", test_atomic_batch_write, 0 },
- { "sqlite3_mmap_warm", test_mmap_warm, 0 },
- { "sqlite3_config_sorterref", test_config_sorterref, 0 },
- };
- static int bitmask_size = sizeof(Bitmask)*8;
- static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
- int i;
- extern int sqlite3_sync_count, sqlite3_fullsync_count;
- extern int sqlite3_opentemp_count;
- extern int sqlite3_like_count;
- extern int sqlite3_xferopt_count;
- extern int sqlite3_pager_readdb_count;
- extern int sqlite3_pager_writedb_count;
- extern int sqlite3_pager_writej_count;
-#if SQLITE_OS_WIN
- extern LONG volatile sqlite3_os_type;
-#endif
-#ifdef SQLITE_DEBUG
- extern int sqlite3WhereTrace;
- extern int sqlite3OSTrace;
- extern int sqlite3WalTrace;
-#endif
-#ifdef SQLITE_TEST
-#ifdef SQLITE_ENABLE_FTS3
- extern int sqlite3_fts3_enable_parentheses;
-#endif
-#endif
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
- aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
- }
- Tcl_LinkVar(interp, "sqlite_search_count",
- (char*)&sqlite3_search_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_found_count",
- (char*)&sqlite3_found_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_sort_count",
- (char*)&sqlite3_sort_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite3_max_blobsize",
- (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_like_count",
- (char*)&sqlite3_like_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_interrupt_count",
- (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_open_file_count",
- (char*)&sqlite3_open_file_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_current_time",
- (char*)&sqlite3_current_time, TCL_LINK_INT);
-#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- Tcl_LinkVar(interp, "sqlite_hostid_num",
- (char*)&sqlite3_hostid_num, TCL_LINK_INT);
-#endif
- Tcl_LinkVar(interp, "sqlite3_xferopt_count",
- (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
- (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
- (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
- (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
-#ifndef SQLITE_OMIT_UTF16
- Tcl_LinkVar(interp, "unaligned_string_counter",
- (char*)&unaligned_string_counter, TCL_LINK_INT);
-#endif
-#ifndef SQLITE_OMIT_UTF16
- Tcl_LinkVar(interp, "sqlite_last_needed_collation",
- (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
-#endif
-#if SQLITE_OS_WIN
- Tcl_LinkVar(interp, "sqlite_os_type",
- (char*)&sqlite3_os_type, TCL_LINK_LONG);
-#endif
-#ifdef SQLITE_TEST
- {
- static const char *query_plan = "*** OBSOLETE VARIABLE ***";
- Tcl_LinkVar(interp, "sqlite_query_plan",
- (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
- }
-#endif
-#ifdef SQLITE_DEBUG
- Tcl_LinkVar(interp, "sqlite_where_trace",
- (char*)&sqlite3WhereTrace, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_os_trace",
- (char*)&sqlite3OSTrace, TCL_LINK_INT);
-#ifndef SQLITE_OMIT_WAL
- Tcl_LinkVar(interp, "sqlite_wal_trace",
- (char*)&sqlite3WalTrace, TCL_LINK_INT);
-#endif
-#endif
-#ifndef SQLITE_OMIT_DISKIO
- Tcl_LinkVar(interp, "sqlite_opentemp_count",
- (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
-#endif
- Tcl_LinkVar(interp, "sqlite_static_bind_value",
- (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
- Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
- (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_temp_directory",
- (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
- Tcl_LinkVar(interp, "sqlite_data_directory",
- (char*)&sqlite3_data_directory, TCL_LINK_STRING);
- Tcl_LinkVar(interp, "bitmask_size",
- (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
- Tcl_LinkVar(interp, "longdouble_size",
- (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
- Tcl_LinkVar(interp, "sqlite_sync_count",
- (char*)&sqlite3_sync_count, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_fullsync_count",
- (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
-#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
- Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
- (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
-#endif
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test2.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test2.c
deleted file mode 100644
index 850e1e1a044..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test2.c
+++ /dev/null
@@ -1,752 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the pager.c module in SQLite. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-extern const char *sqlite3ErrName(int);
-
-/*
-** Page size and reserved size used for testing.
-*/
-static int test_pagesize = 1024;
-
-/*
-** Dummy page reinitializer
-*/
-static void pager_test_reiniter(DbPage *pNotUsed){
- return;
-}
-
-/*
-** Usage: pager_open FILENAME N-PAGE
-**
-** Open a new pager
-*/
-static int SQLITE_TCLAPI pager_open(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- u32 pageSize;
- Pager *pPager;
- int nPage;
- int rc;
- char zBuf[100];
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME N-PAGE\"", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
- rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB,
- pager_test_reiniter);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- sqlite3PagerSetCachesize(pPager, nPage);
- pageSize = test_pagesize;
- sqlite3PagerSetPagesize(pPager, &pageSize, -1);
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager);
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: pager_close ID
-**
-** Close the given pager.
-*/
-static int SQLITE_TCLAPI pager_close(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- rc = sqlite3PagerClose(pPager, 0);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: pager_rollback ID
-**
-** Rollback changes
-*/
-static int SQLITE_TCLAPI pager_rollback(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- rc = sqlite3PagerRollback(pPager);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: pager_commit ID
-**
-** Commit all changes
-*/
-static int SQLITE_TCLAPI pager_commit(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- rc = sqlite3PagerCommitPhaseTwo(pPager);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: pager_stmt_begin ID
-**
-** Start a new checkpoint.
-*/
-static int SQLITE_TCLAPI pager_stmt_begin(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- rc = sqlite3PagerOpenSavepoint(pPager, 1);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: pager_stmt_rollback ID
-**
-** Rollback changes to a checkpoint
-*/
-static int SQLITE_TCLAPI pager_stmt_rollback(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, 0);
- sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: pager_stmt_commit ID
-**
-** Commit changes to a checkpoint
-*/
-static int SQLITE_TCLAPI pager_stmt_commit(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: pager_stats ID
-**
-** Return pager statistics.
-*/
-static int SQLITE_TCLAPI pager_stats(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- int i, *a;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- a = sqlite3PagerStats(pPager);
- for(i=0; i<9; i++){
- static char *zName[] = {
- "ref", "page", "max", "size", "state", "err",
- "hit", "miss", "ovfl",
- };
- char zBuf[100];
- Tcl_AppendElement(interp, zName[i]);
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]);
- Tcl_AppendElement(interp, zBuf);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: pager_pagecount ID
-**
-** Return the size of the database file.
-*/
-static int SQLITE_TCLAPI pager_pagecount(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- char zBuf[100];
- int nPage;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- sqlite3PagerPagecount(pPager, &nPage);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nPage);
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: page_get ID PGNO
-**
-** Return a pointer to a page from the database.
-*/
-static int SQLITE_TCLAPI page_get(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- char zBuf[100];
- DbPage *pPage = 0;
- int pgno;
- int rc;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID PGNO\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
- rc = sqlite3PagerSharedLock(pPager);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerGet(pPager, pgno, &pPage, 0);
- }
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: page_lookup ID PGNO
-**
-** Return a pointer to a page if the page is already in cache.
-** If not in cache, return an empty string.
-*/
-static int SQLITE_TCLAPI page_lookup(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- char zBuf[100];
- DbPage *pPage;
- int pgno;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID PGNO\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
- pPage = sqlite3PagerLookup(pPager, pgno);
- if( pPage ){
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
- Tcl_AppendResult(interp, zBuf, 0);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: pager_truncate ID PGNO
-*/
-static int SQLITE_TCLAPI pager_truncate(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Pager *pPager;
- int pgno;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID PGNO\"", 0);
- return TCL_ERROR;
- }
- pPager = sqlite3TestTextToPtr(argv[1]);
- if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
- sqlite3PagerTruncateImage(pPager, pgno);
- return TCL_OK;
-}
-
-
-/*
-** Usage: page_unref PAGE
-**
-** Drop a pointer to a page.
-*/
-static int SQLITE_TCLAPI page_unref(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- DbPage *pPage;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " PAGE\"", 0);
- return TCL_ERROR;
- }
- pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
- sqlite3PagerUnref(pPage);
- return TCL_OK;
-}
-
-/*
-** Usage: page_read PAGE
-**
-** Return the content of a page
-*/
-static int SQLITE_TCLAPI page_read(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- char zBuf[100];
- DbPage *pPage;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " PAGE\"", 0);
- return TCL_ERROR;
- }
- pPage = sqlite3TestTextToPtr(argv[1]);
- memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf));
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: page_number PAGE
-**
-** Return the page number for a page.
-*/
-static int SQLITE_TCLAPI page_number(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- char zBuf[100];
- DbPage *pPage;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " PAGE\"", 0);
- return TCL_ERROR;
- }
- pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage));
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: page_write PAGE DATA
-**
-** Write something into a page.
-*/
-static int SQLITE_TCLAPI page_write(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- DbPage *pPage;
- char *pData;
- int rc;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " PAGE DATA\"", 0);
- return TCL_ERROR;
- }
- pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
- rc = sqlite3PagerWrite(pPage);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- pData = sqlite3PagerGetData(pPage);
- strncpy(pData, argv[2], test_pagesize-1);
- pData[test_pagesize-1] = 0;
- return TCL_OK;
-}
-
-#ifndef SQLITE_OMIT_DISKIO
-/*
-** Usage: fake_big_file N FILENAME
-**
-** Write a few bytes at the N megabyte point of FILENAME. This will
-** create a large file. If the file was a valid SQLite database, then
-** the next time the database is opened, SQLite will begin allocating
-** new pages after N. If N is 2096 or bigger, this will test the
-** ability of SQLite to write to large files.
-*/
-static int SQLITE_TCLAPI fake_big_file(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- sqlite3_vfs *pVfs;
- sqlite3_file *fd = 0;
- int rc;
- int n;
- i64 offset;
- char *zFile;
- int nFile;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " N-MEGABYTES FILE\"", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
-
- pVfs = sqlite3_vfs_find(0);
- nFile = (int)strlen(argv[2]);
- zFile = sqlite3_malloc( nFile+2 );
- if( zFile==0 ) return TCL_ERROR;
- memcpy(zFile, argv[2], nFile+1);
- zFile[nFile+1] = 0;
- rc = sqlite3OsOpenMalloc(pVfs, zFile, &fd,
- (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0
- );
- if( rc ){
- Tcl_AppendResult(interp, "open failed: ", sqlite3ErrName(rc), 0);
- sqlite3_free(zFile);
- return TCL_ERROR;
- }
- offset = n;
- offset *= 1024*1024;
- rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
- sqlite3OsCloseFree(fd);
- sqlite3_free(zFile);
- if( rc ){
- Tcl_AppendResult(interp, "write failed: ", sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-#endif
-
-
-/*
-** test_control_pending_byte PENDING_BYTE
-**
-** Set the PENDING_BYTE using the sqlite3_test_control() interface.
-*/
-static int SQLITE_TCLAPI testPendingByte(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int pbyte;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " PENDING-BYTE\"", (void*)0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[1], &pbyte) ) return TCL_ERROR;
- rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** The sqlite3FaultSim() callback:
-*/
-static Tcl_Interp *faultSimInterp = 0;
-static int faultSimScriptSize = 0;
-static char *faultSimScript;
-static int faultSimCallback(int x){
- char zInt[30];
- int i;
- int isNeg;
- int rc;
- if( x==0 ){
- memcpy(faultSimScript+faultSimScriptSize, "0", 2);
- }else{
- /* Convert x to text without using any sqlite3 routines */
- if( x<0 ){
- isNeg = 1;
- x = -x;
- }else{
- isNeg = 0;
- }
- zInt[sizeof(zInt)-1] = 0;
- for(i=sizeof(zInt)-2; i>0 && x>0; i--, x /= 10){
- zInt[i] = (x%10) + '0';
- }
- if( isNeg ) zInt[i--] = '-';
- memcpy(faultSimScript+faultSimScriptSize, zInt+i+1, sizeof(zInt)-i);
- }
- rc = Tcl_Eval(faultSimInterp, faultSimScript);
- if( rc ){
- fprintf(stderr, "fault simulator script failed: [%s]", faultSimScript);
- rc = SQLITE_ERROR;
- }else{
- rc = atoi(Tcl_GetStringResult(faultSimInterp));
- }
- Tcl_ResetResult(faultSimInterp);
- return rc;
-}
-
-/*
-** sqlite3_test_control_fault_install SCRIPT
-**
-** Arrange to invoke SCRIPT with the integer argument to sqlite3FaultSim()
-** appended, whenever sqlite3FaultSim() is called. Or, if SCRIPT is the
-** empty string, cancel the sqlite3FaultSim() callback.
-*/
-static int SQLITE_TCLAPI faultInstallCmd(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- const char *zScript;
- int nScript;
- int rc;
- if( argc!=1 && argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " SCRIPT\"", (void*)0);
- }
- zScript = argc==2 ? argv[1] : "";
- nScript = (int)strlen(zScript);
- if( faultSimScript ){
- free(faultSimScript);
- faultSimScript = 0;
- }
- if( nScript==0 ){
- rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, 0);
- }else{
- faultSimScript = malloc( nScript+100 );
- if( faultSimScript==0 ){
- Tcl_AppendResult(interp, "out of memory", (void*)0);
- return SQLITE_ERROR;
- }
- memcpy(faultSimScript, zScript, nScript);
- faultSimScript[nScript] = ' ';
- faultSimScriptSize = nScript+1;
- faultSimInterp = interp;
- rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, faultSimCallback);
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return SQLITE_OK;
-}
-
-/*
-** sqlite3BitvecBuiltinTest SIZE PROGRAM
-**
-** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control.
-** See comments on sqlite3BitvecBuiltinTest() for additional information.
-*/
-static int SQLITE_TCLAPI testBitvecBuiltinTest(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int sz, rc;
- int nProg = 0;
- int aProg[100];
- const char *z;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " SIZE PROGRAM\"", (void*)0);
- }
- if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR;
- z = argv[2];
- while( nProg<99 && *z ){
- while( *z && !sqlite3Isdigit(*z) ){ z++; }
- if( *z==0 ) break;
- aProg[nProg++] = atoi(z);
- while( sqlite3Isdigit(*z) ){ z++; }
- }
- aProg[nProg] = 0;
- rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest2_Init(Tcl_Interp *interp){
- extern int sqlite3_io_error_persist;
- extern int sqlite3_io_error_pending;
- extern int sqlite3_io_error_hit;
- extern int sqlite3_io_error_hardhit;
- extern int sqlite3_diskfull_pending;
- extern int sqlite3_diskfull;
- static struct {
- char *zName;
- Tcl_CmdProc *xProc;
- } aCmd[] = {
- { "pager_open", (Tcl_CmdProc*)pager_open },
- { "pager_close", (Tcl_CmdProc*)pager_close },
- { "pager_commit", (Tcl_CmdProc*)pager_commit },
- { "pager_rollback", (Tcl_CmdProc*)pager_rollback },
- { "pager_stmt_begin", (Tcl_CmdProc*)pager_stmt_begin },
- { "pager_stmt_commit", (Tcl_CmdProc*)pager_stmt_commit },
- { "pager_stmt_rollback", (Tcl_CmdProc*)pager_stmt_rollback },
- { "pager_stats", (Tcl_CmdProc*)pager_stats },
- { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount },
- { "page_get", (Tcl_CmdProc*)page_get },
- { "page_lookup", (Tcl_CmdProc*)page_lookup },
- { "page_unref", (Tcl_CmdProc*)page_unref },
- { "page_read", (Tcl_CmdProc*)page_read },
- { "page_write", (Tcl_CmdProc*)page_write },
- { "page_number", (Tcl_CmdProc*)page_number },
- { "pager_truncate", (Tcl_CmdProc*)pager_truncate },
-#ifndef SQLITE_OMIT_DISKIO
- { "fake_big_file", (Tcl_CmdProc*)fake_big_file },
-#endif
- { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest },
- { "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte },
- { "sqlite3_test_control_fault_install", (Tcl_CmdProc*)faultInstallCmd },
- };
- int i;
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
- Tcl_LinkVar(interp, "sqlite_io_error_pending",
- (char*)&sqlite3_io_error_pending, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_io_error_persist",
- (char*)&sqlite3_io_error_persist, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_io_error_hit",
- (char*)&sqlite3_io_error_hit, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_io_error_hardhit",
- (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_diskfull_pending",
- (char*)&sqlite3_diskfull_pending, TCL_LINK_INT);
- Tcl_LinkVar(interp, "sqlite_diskfull",
- (char*)&sqlite3_diskfull, TCL_LINK_INT);
-#ifndef SQLITE_OMIT_WSD
- Tcl_LinkVar(interp, "sqlite_pending_byte",
- (char*)&sqlite3PendingByte, TCL_LINK_INT | TCL_LINK_READ_ONLY);
-#endif
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test3.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test3.c
deleted file mode 100644
index 0de19469a44..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test3.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the btree.c module in SQLite. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library.
-*/
-#include "sqliteInt.h"
-#include "btreeInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-extern const char *sqlite3ErrName(int);
-
-/*
-** A bogus sqlite3 connection structure for use in the btree
-** tests.
-*/
-static sqlite3 sDb;
-static int nRefSqlite3 = 0;
-
-/*
-** Usage: btree_open FILENAME NCACHE
-**
-** Open a new database
-*/
-static int SQLITE_TCLAPI btree_open(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Btree *pBt;
- int rc, nCache;
- char zBuf[100];
- int n;
- char *zFilename;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME NCACHE FLAGS\"", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
- nRefSqlite3++;
- if( nRefSqlite3==1 ){
- sDb.pVfs = sqlite3_vfs_find(0);
- sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
- sqlite3_mutex_enter(sDb.mutex);
- }
- n = (int)strlen(argv[1]);
- zFilename = sqlite3_malloc( n+2 );
- if( zFilename==0 ) return TCL_ERROR;
- memcpy(zFilename, argv[1], n+1);
- zFilename[n+1] = 0;
- rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
- sqlite3_free(zFilename);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- sqlite3BtreeSetCacheSize(pBt, nCache);
- sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: btree_close ID
-**
-** Close the given database.
-*/
-static int SQLITE_TCLAPI btree_close(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Btree *pBt;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pBt = sqlite3TestTextToPtr(argv[1]);
- rc = sqlite3BtreeClose(pBt);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- nRefSqlite3--;
- if( nRefSqlite3==0 ){
- sqlite3_mutex_leave(sDb.mutex);
- sqlite3_mutex_free(sDb.mutex);
- sDb.mutex = 0;
- sDb.pVfs = 0;
- }
- return TCL_OK;
-}
-
-
-/*
-** Usage: btree_begin_transaction ID
-**
-** Start a new transaction
-*/
-static int SQLITE_TCLAPI btree_begin_transaction(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Btree *pBt;
- int rc;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pBt = sqlite3TestTextToPtr(argv[1]);
- sqlite3BtreeEnter(pBt);
- rc = sqlite3BtreeBeginTrans(pBt, 1);
- sqlite3BtreeLeave(pBt);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** Usage: btree_pager_stats ID
-**
-** Returns pager statistics
-*/
-static int SQLITE_TCLAPI btree_pager_stats(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Btree *pBt;
- int i;
- int *a;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pBt = sqlite3TestTextToPtr(argv[1]);
-
- /* Normally in this file, with a b-tree handle opened using the
- ** [btree_open] command it is safe to call sqlite3BtreeEnter() directly.
- ** But this function is sometimes called with a btree handle obtained
- ** from an open SQLite connection (using [btree_from_db]). In this case
- ** we need to obtain the mutex for the controlling SQLite handle before
- ** it is safe to call sqlite3BtreeEnter().
- */
- sqlite3_mutex_enter(pBt->db->mutex);
-
- sqlite3BtreeEnter(pBt);
- a = sqlite3PagerStats(sqlite3BtreePager(pBt));
- for(i=0; i<11; i++){
- static char *zName[] = {
- "ref", "page", "max", "size", "state", "err",
- "hit", "miss", "ovfl", "read", "write"
- };
- char zBuf[100];
- Tcl_AppendElement(interp, zName[i]);
- sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]);
- Tcl_AppendElement(interp, zBuf);
- }
- sqlite3BtreeLeave(pBt);
-
- /* Release the mutex on the SQLite handle that controls this b-tree */
- sqlite3_mutex_leave(pBt->db->mutex);
- return TCL_OK;
-}
-
-/*
-** Usage: btree_cursor ID TABLENUM WRITEABLE
-**
-** Create a new cursor. Return the ID for the cursor.
-*/
-static int SQLITE_TCLAPI btree_cursor(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Btree *pBt;
- int iTable;
- BtCursor *pCur;
- int rc = SQLITE_OK;
- int wrFlag;
- char zBuf[30];
-
- if( argc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID TABLENUM WRITEABLE\"", 0);
- return TCL_ERROR;
- }
- pBt = sqlite3TestTextToPtr(argv[1]);
- if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
- if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
- if( wrFlag ) wrFlag = BTREE_WRCSR;
- pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
- memset(pCur, 0, sqlite3BtreeCursorSize());
- sqlite3_mutex_enter(pBt->db->mutex);
- sqlite3BtreeEnter(pBt);
-#ifndef SQLITE_OMIT_SHARED_CACHE
- rc = sqlite3BtreeLockTable(pBt, iTable, !!wrFlag);
-#endif
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
- }
- sqlite3BtreeLeave(pBt);
- sqlite3_mutex_leave(pBt->db->mutex);
- if( rc ){
- ckfree((char *)pCur);
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
- Tcl_AppendResult(interp, zBuf, 0);
- return SQLITE_OK;
-}
-
-/*
-** Usage: btree_close_cursor ID
-**
-** Close a cursor opened using btree_cursor.
-*/
-static int SQLITE_TCLAPI btree_close_cursor(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- BtCursor *pCur;
- int rc;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pCur = sqlite3TestTextToPtr(argv[1]);
-#if SQLITE_THREADSAFE>0
- {
- Btree *pBt = pCur->pBtree;
- sqlite3_mutex_enter(pBt->db->mutex);
- sqlite3BtreeEnter(pBt);
- rc = sqlite3BtreeCloseCursor(pCur);
- sqlite3BtreeLeave(pBt);
- sqlite3_mutex_leave(pBt->db->mutex);
- }
-#else
- rc = sqlite3BtreeCloseCursor(pCur);
-#endif
- ckfree((char *)pCur);
- if( rc ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return SQLITE_OK;
-}
-
-/*
-** Usage: btree_next ID
-**
-** Move the cursor to the next entry in the table. Return 0 on success
-** or 1 if the cursor was already on the last entry in the table or if
-** the table is empty.
-*/
-static int SQLITE_TCLAPI btree_next(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- BtCursor *pCur;
- int rc;
- int res = 0;
- char zBuf[100];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pCur = sqlite3TestTextToPtr(argv[1]);
- sqlite3BtreeEnter(pCur->pBtree);
- rc = sqlite3BtreeNext(pCur, 0);
- if( rc==SQLITE_DONE ){
- res = 1;
- rc = SQLITE_OK;
- }
- sqlite3BtreeLeave(pCur->pBtree);
- if( rc ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
- Tcl_AppendResult(interp, zBuf, 0);
- return SQLITE_OK;
-}
-
-/*
-** Usage: btree_first ID
-**
-** Move the cursor to the first entry in the table. Return 0 if the
-** cursor was left point to something and 1 if the table is empty.
-*/
-static int SQLITE_TCLAPI btree_first(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- BtCursor *pCur;
- int rc;
- int res = 0;
- char zBuf[100];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pCur = sqlite3TestTextToPtr(argv[1]);
- sqlite3BtreeEnter(pCur->pBtree);
- rc = sqlite3BtreeFirst(pCur, &res);
- sqlite3BtreeLeave(pCur->pBtree);
- if( rc ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
- Tcl_AppendResult(interp, zBuf, 0);
- return SQLITE_OK;
-}
-
-/*
-** Usage: btree_eof ID
-**
-** Return TRUE if the given cursor is not pointing at a valid entry.
-** Return FALSE if the cursor does point to a valid entry.
-*/
-static int SQLITE_TCLAPI btree_eof(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- BtCursor *pCur;
- int rc;
- char zBuf[50];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pCur = sqlite3TestTextToPtr(argv[1]);
- sqlite3BtreeEnter(pCur->pBtree);
- rc = sqlite3BtreeEof(pCur);
- sqlite3BtreeLeave(pCur->pBtree);
- sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", rc);
- Tcl_AppendResult(interp, zBuf, 0);
- return SQLITE_OK;
-}
-
-/*
-** Usage: btree_payload_size ID
-**
-** Return the number of bytes of payload
-*/
-static int SQLITE_TCLAPI btree_payload_size(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- BtCursor *pCur;
- u32 n;
- char zBuf[50];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pCur = sqlite3TestTextToPtr(argv[1]);
- sqlite3BtreeEnter(pCur->pBtree);
- n = sqlite3BtreePayloadSize(pCur);
- sqlite3BtreeLeave(pCur->pBtree);
- sqlite3_snprintf(sizeof(zBuf),zBuf, "%u", n);
- Tcl_AppendResult(interp, zBuf, 0);
- return SQLITE_OK;
-}
-
-/*
-** usage: varint_test START MULTIPLIER COUNT INCREMENT
-**
-** This command tests the putVarint() and getVarint()
-** routines, both for accuracy and for speed.
-**
-** An integer is written using putVarint() and read back with
-** getVarint() and varified to be unchanged. This repeats COUNT
-** times. The first integer is START*MULTIPLIER. Each iteration
-** increases the integer by INCREMENT.
-**
-** This command returns nothing if it works. It returns an error message
-** if something goes wrong.
-*/
-static int SQLITE_TCLAPI btree_varint_test(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- u32 start, mult, count, incr;
- u64 in, out;
- int n1, n2, i, j;
- unsigned char zBuf[100];
- if( argc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " START MULTIPLIER COUNT INCREMENT\"", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR;
- if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR;
- if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR;
- if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR;
- in = start;
- in *= mult;
- for(i=0; i<(int)count; i++){
- char zErr[200];
- n1 = putVarint(zBuf, in);
- if( n1>9 || n1<1 ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "putVarint returned %d - should be between 1 and 9", n1);
- Tcl_AppendResult(interp, zErr, 0);
- return TCL_ERROR;
- }
- n2 = getVarint(zBuf, &out);
- if( n1!=n2 ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "putVarint returned %d and getVarint returned %d", n1, n2);
- Tcl_AppendResult(interp, zErr, 0);
- return TCL_ERROR;
- }
- if( in!=out ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "Wrote 0x%016llx and got back 0x%016llx", in, out);
- Tcl_AppendResult(interp, zErr, 0);
- return TCL_ERROR;
- }
- if( (in & 0xffffffff)==in ){
- u32 out32;
- n2 = getVarint32(zBuf, out32);
- out = out32;
- if( n1!=n2 ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "putVarint returned %d and GetVarint32 returned %d",
- n1, n2);
- Tcl_AppendResult(interp, zErr, 0);
- return TCL_ERROR;
- }
- if( in!=out ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "Wrote 0x%016llx and got back 0x%016llx from GetVarint32",
- in, out);
- Tcl_AppendResult(interp, zErr, 0);
- return TCL_ERROR;
- }
- }
-
- /* In order to get realistic timings, run getVarint 19 more times.
- ** This is because getVarint is called about 20 times more often
- ** than putVarint.
- */
- for(j=0; j<19; j++){
- getVarint(zBuf, &out);
- }
- in += incr;
- }
- return TCL_OK;
-}
-
-/*
-** usage: btree_from_db DB-HANDLE
-**
-** This command returns the btree handle for the main database associated
-** with the database-handle passed as the argument. Example usage:
-**
-** sqlite3 db test.db
-** set bt [btree_from_db db]
-*/
-static int SQLITE_TCLAPI btree_from_db(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- char zBuf[100];
- Tcl_CmdInfo info;
- sqlite3 *db;
- Btree *pBt;
- int iDb = 0;
-
- if( argc!=2 && argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " DB-HANDLE ?N?\"", 0);
- return TCL_ERROR;
- }
-
- if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){
- Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0);
- return TCL_ERROR;
- }
- if( argc==3 ){
- iDb = atoi(argv[2]);
- }
-
- db = *((sqlite3 **)info.objClientData);
- assert( db );
-
- pBt = db->aDb[iDb].pBt;
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt);
- Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
- return TCL_OK;
-}
-
-/*
-** Usage: btree_ismemdb ID
-**
-** Return true if the B-Tree is currently stored entirely in memory.
-*/
-static int SQLITE_TCLAPI btree_ismemdb(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- Btree *pBt;
- int res;
- sqlite3_file *pFile;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID\"", 0);
- return TCL_ERROR;
- }
- pBt = sqlite3TestTextToPtr(argv[1]);
- sqlite3_mutex_enter(pBt->db->mutex);
- sqlite3BtreeEnter(pBt);
- pFile = sqlite3PagerFile(sqlite3BtreePager(pBt));
- res = (pFile->pMethods==0);
- sqlite3BtreeLeave(pBt);
- sqlite3_mutex_leave(pBt->db->mutex);
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
- return SQLITE_OK;
-}
-
-/*
-** usage: btree_set_cache_size ID NCACHE
-**
-** Set the size of the cache used by btree $ID.
-*/
-static int SQLITE_TCLAPI btree_set_cache_size(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int nCache;
- Btree *pBt;
-
- if( argc!=3 ){
- Tcl_AppendResult(
- interp, "wrong # args: should be \"", argv[0], " BT NCACHE\"", 0);
- return TCL_ERROR;
- }
- pBt = sqlite3TestTextToPtr(argv[1]);
- if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
-
- sqlite3_mutex_enter(pBt->db->mutex);
- sqlite3BtreeEnter(pBt);
- sqlite3BtreeSetCacheSize(pBt, nCache);
- sqlite3BtreeLeave(pBt);
- sqlite3_mutex_leave(pBt->db->mutex);
- return TCL_OK;
-}
-
-/*
-** usage: btree_insert CSR ?KEY? VALUE
-**
-** Set the size of the cache used by btree $ID.
-*/
-static int SQLITE_TCLAPI btree_insert(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const objv[]
-){
- BtCursor *pCur;
- int rc;
- BtreePayload x;
-
- if( objc!=4 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?-intkey? CSR KEY VALUE");
- return TCL_ERROR;
- }
-
- memset(&x, 0, sizeof(x));
- if( objc==4 ){
- if( Tcl_GetIntFromObj(interp, objv[2], &rc) ) return TCL_ERROR;
- x.nKey = rc;
- x.pData = (void*)Tcl_GetByteArrayFromObj(objv[3], &x.nData);
- }else{
- x.pKey = (void*)Tcl_GetByteArrayFromObj(objv[2], &rc);
- x.nKey = rc;
- }
- pCur = (BtCursor*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
-
- sqlite3_mutex_enter(pCur->pBtree->db->mutex);
- sqlite3BtreeEnter(pCur->pBtree);
- rc = sqlite3BtreeInsert(pCur, &x, 0, 0);
- sqlite3BtreeLeave(pCur->pBtree);
- sqlite3_mutex_leave(pCur->pBtree->db->mutex);
-
- Tcl_ResetResult(interp);
- if( rc ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest3_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_CmdProc *xProc;
- } aCmd[] = {
- { "btree_open", (Tcl_CmdProc*)btree_open },
- { "btree_close", (Tcl_CmdProc*)btree_close },
- { "btree_begin_transaction", (Tcl_CmdProc*)btree_begin_transaction },
- { "btree_pager_stats", (Tcl_CmdProc*)btree_pager_stats },
- { "btree_cursor", (Tcl_CmdProc*)btree_cursor },
- { "btree_close_cursor", (Tcl_CmdProc*)btree_close_cursor },
- { "btree_next", (Tcl_CmdProc*)btree_next },
- { "btree_eof", (Tcl_CmdProc*)btree_eof },
- { "btree_payload_size", (Tcl_CmdProc*)btree_payload_size },
- { "btree_first", (Tcl_CmdProc*)btree_first },
- { "btree_varint_test", (Tcl_CmdProc*)btree_varint_test },
- { "btree_from_db", (Tcl_CmdProc*)btree_from_db },
- { "btree_ismemdb", (Tcl_CmdProc*)btree_ismemdb },
- { "btree_set_cache_size", (Tcl_CmdProc*)btree_set_cache_size }
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
-
- Tcl_CreateObjCommand(interp, "btree_insert", btree_insert, 0, 0);
-
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test4.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test4.c
deleted file mode 100644
index c5b5ec12cc4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test4.c
+++ /dev/null
@@ -1,726 +0,0 @@
-/*
-** 2003 December 18
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the SQLite library in a multithreaded environment.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <sched.h>
-#include <ctype.h>
-
-extern const char *sqlite3ErrName(int);
-
-/*
-** Each thread is controlled by an instance of the following
-** structure.
-*/
-typedef struct Thread Thread;
-struct Thread {
- /* The first group of fields are writable by the master and read-only
- ** to the thread. */
- char *zFilename; /* Name of database file */
- void (*xOp)(Thread*); /* next operation to do */
- char *zArg; /* argument usable by xOp */
- int opnum; /* Operation number */
- int busy; /* True if this thread is in use */
-
- /* The next group of fields are writable by the thread but read-only to the
- ** master. */
- int completed; /* Number of operations completed */
- sqlite3 *db; /* Open database */
- sqlite3_stmt *pStmt; /* Pending operation */
- char *zErr; /* operation error */
- char *zStaticErr; /* Static error message */
- int rc; /* operation return code */
- int argc; /* number of columns in result */
- const char *argv[100]; /* result columns */
- const char *colv[100]; /* result column names */
-};
-
-/*
-** There can be as many as 26 threads running at once. Each is named
-** by a capital letter: A, B, C, ..., Y, Z.
-*/
-#define N_THREAD 26
-static Thread threadset[N_THREAD];
-
-
-/*
-** The main loop for a thread. Threads use busy waiting.
-*/
-static void *thread_main(void *pArg){
- Thread *p = (Thread*)pArg;
- if( p->db ){
- sqlite3_close(p->db);
- }
- sqlite3_open(p->zFilename, &p->db);
- if( SQLITE_OK!=sqlite3_errcode(p->db) ){
- p->zErr = strdup(sqlite3_errmsg(p->db));
- sqlite3_close(p->db);
- p->db = 0;
- }
- p->pStmt = 0;
- p->completed = 1;
- while( p->opnum<=p->completed ) sched_yield();
- while( p->xOp ){
- if( p->zErr && p->zErr!=p->zStaticErr ){
- sqlite3_free(p->zErr);
- p->zErr = 0;
- }
- (*p->xOp)(p);
- p->completed++;
- while( p->opnum<=p->completed ) sched_yield();
- }
- if( p->pStmt ){
- sqlite3_finalize(p->pStmt);
- p->pStmt = 0;
- }
- if( p->db ){
- sqlite3_close(p->db);
- p->db = 0;
- }
- if( p->zErr && p->zErr!=p->zStaticErr ){
- sqlite3_free(p->zErr);
- p->zErr = 0;
- }
- p->completed++;
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_thread_cleanup();
-#endif
- return 0;
-}
-
-/*
-** Get a thread ID which is an upper case letter. Return the index.
-** If the argument is not a valid thread ID put an error message in
-** the interpreter and return -1.
-*/
-static int parse_thread_id(Tcl_Interp *interp, const char *zArg){
- if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){
- Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0);
- return -1;
- }
- return zArg[0] - 'A';
-}
-
-/*
-** Usage: thread_create NAME FILENAME
-**
-** NAME should be an upper case letter. Start the thread running with
-** an open connection to the given database.
-*/
-static int SQLITE_TCLAPI tcl_thread_create(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- pthread_t x;
- int rc;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID FILENAME", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( threadset[i].busy ){
- Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0);
- return TCL_ERROR;
- }
- threadset[i].busy = 1;
- sqlite3_free(threadset[i].zFilename);
- threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]);
- threadset[i].opnum = 1;
- threadset[i].completed = 0;
- rc = pthread_create(&x, 0, thread_main, &threadset[i]);
- if( rc ){
- Tcl_AppendResult(interp, "failed to create the thread", 0);
- sqlite3_free(threadset[i].zFilename);
- threadset[i].busy = 0;
- return TCL_ERROR;
- }
- pthread_detach(x);
- return TCL_OK;
-}
-
-/*
-** Wait for a thread to reach its idle state.
-*/
-static void thread_wait(Thread *p){
- while( p->opnum>p->completed ) sched_yield();
-}
-
-/*
-** Usage: thread_wait ID
-**
-** Wait on thread ID to reach its idle state.
-*/
-static int SQLITE_TCLAPI tcl_thread_wait(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- return TCL_OK;
-}
-
-/*
-** Stop a thread.
-*/
-static void stop_thread(Thread *p){
- thread_wait(p);
- p->xOp = 0;
- p->opnum++;
- thread_wait(p);
- sqlite3_free(p->zArg);
- p->zArg = 0;
- sqlite3_free(p->zFilename);
- p->zFilename = 0;
- p->busy = 0;
-}
-
-/*
-** Usage: thread_halt ID
-**
-** Cause a thread to shut itself down. Wait for the shutdown to be
-** completed. If ID is "*" then stop all threads.
-*/
-static int SQLITE_TCLAPI tcl_thread_halt(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- if( argv[1][0]=='*' && argv[1][1]==0 ){
- for(i=0; i<N_THREAD; i++){
- if( threadset[i].busy ) stop_thread(&threadset[i]);
- }
- }else{
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- stop_thread(&threadset[i]);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: thread_argc ID
-**
-** Wait on the most recent thread_step to complete, then return the
-** number of columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_thread_argc(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- char zBuf[100];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", threadset[i].argc);
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: thread_argv ID N
-**
-** Wait on the most recent thread_step to complete, then return the
-** value of the N-th columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_thread_argv(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- int n;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID N", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
- thread_wait(&threadset[i]);
- if( n<0 || n>=threadset[i].argc ){
- Tcl_AppendResult(interp, "column number out of range", 0);
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, threadset[i].argv[n], 0);
- return TCL_OK;
-}
-
-/*
-** Usage: thread_colname ID N
-**
-** Wait on the most recent thread_step to complete, then return the
-** name of the N-th columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_thread_colname(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- int n;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID N", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
- thread_wait(&threadset[i]);
- if( n<0 || n>=threadset[i].argc ){
- Tcl_AppendResult(interp, "column number out of range", 0);
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, threadset[i].colv[n], 0);
- return TCL_OK;
-}
-
-/*
-** Usage: thread_result ID
-**
-** Wait on the most recent operation to complete, then return the
-** result code from that operation.
-*/
-static int SQLITE_TCLAPI tcl_thread_result(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- const char *zName;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- zName = sqlite3ErrName(threadset[i].rc);
- Tcl_AppendResult(interp, zName, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: thread_error ID
-**
-** Wait on the most recent operation to complete, then return the
-** error string.
-*/
-static int SQLITE_TCLAPI tcl_thread_error(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- Tcl_AppendResult(interp, threadset[i].zErr, 0);
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to compile an SQL statement.
-*/
-static void do_compile(Thread *p){
- if( p->db==0 ){
- p->zErr = p->zStaticErr = "no database is open";
- p->rc = SQLITE_ERROR;
- return;
- }
- if( p->pStmt ){
- sqlite3_finalize(p->pStmt);
- p->pStmt = 0;
- }
- p->rc = sqlite3_prepare(p->db, p->zArg, -1, &p->pStmt, 0);
-}
-
-/*
-** Usage: thread_compile ID SQL
-**
-** Compile a new virtual machine.
-*/
-static int SQLITE_TCLAPI tcl_thread_compile(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID SQL", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- threadset[i].xOp = do_compile;
- sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = sqlite3_mprintf("%s", argv[2]);
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to step the virtual machine.
-*/
-static void do_step(Thread *p){
- int i;
- if( p->pStmt==0 ){
- p->zErr = p->zStaticErr = "no virtual machine available";
- p->rc = SQLITE_ERROR;
- return;
- }
- p->rc = sqlite3_step(p->pStmt);
- if( p->rc==SQLITE_ROW ){
- p->argc = sqlite3_column_count(p->pStmt);
- for(i=0; i<sqlite3_data_count(p->pStmt); i++){
- p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i);
- }
- for(i=0; i<p->argc; i++){
- p->colv[i] = sqlite3_column_name(p->pStmt, i);
- }
- }
-}
-
-/*
-** Usage: thread_step ID
-**
-** Advance the virtual machine by one step
-*/
-static int SQLITE_TCLAPI tcl_thread_step(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " IDL", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- threadset[i].xOp = do_step;
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to finalize a virtual machine.
-*/
-static void do_finalize(Thread *p){
- if( p->pStmt==0 ){
- p->zErr = p->zStaticErr = "no virtual machine available";
- p->rc = SQLITE_ERROR;
- return;
- }
- p->rc = sqlite3_finalize(p->pStmt);
- p->pStmt = 0;
-}
-
-/*
-** Usage: thread_finalize ID
-**
-** Finalize the virtual machine.
-*/
-static int SQLITE_TCLAPI tcl_thread_finalize(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " IDL", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- threadset[i].xOp = do_finalize;
- sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = 0;
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** Usage: thread_swap ID ID
-**
-** Interchange the sqlite* pointer between two threads.
-*/
-static int SQLITE_TCLAPI tcl_thread_swap(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i, j;
- sqlite3 *temp;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID1 ID2", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- j = parse_thread_id(interp, argv[2]);
- if( j<0 ) return TCL_ERROR;
- if( !threadset[j].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[j]);
- temp = threadset[i].db;
- threadset[i].db = threadset[j].db;
- threadset[j].db = temp;
- return TCL_OK;
-}
-
-/*
-** Usage: thread_db_get ID
-**
-** Return the database connection pointer for the given thread. Then
-** remove the pointer from the thread itself. Afterwards, the thread
-** can be stopped and the connection can be used by the main thread.
-*/
-static int SQLITE_TCLAPI tcl_thread_db_get(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- char zBuf[100];
- extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- sqlite3TestMakePointerStr(interp, zBuf, threadset[i].db);
- threadset[i].db = 0;
- Tcl_AppendResult(interp, zBuf, (char*)0);
- return TCL_OK;
-}
-
-/*
-** Usage: thread_db_put ID DB
-**
-*/
-static int SQLITE_TCLAPI tcl_thread_db_put(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
- extern void *sqlite3TestTextToPtr(const char *);
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID DB", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- assert( !threadset[i].db );
- threadset[i].db = (sqlite3*)sqlite3TestTextToPtr(argv[2]);
- return TCL_OK;
-}
-
-/*
-** Usage: thread_stmt_get ID
-**
-** Return the database stmt pointer for the given thread. Then
-** remove the pointer from the thread itself.
-*/
-static int SQLITE_TCLAPI tcl_thread_stmt_get(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- char zBuf[100];
- extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_thread_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- thread_wait(&threadset[i]);
- sqlite3TestMakePointerStr(interp, zBuf, threadset[i].pStmt);
- threadset[i].pStmt = 0;
- Tcl_AppendResult(interp, zBuf, (char*)0);
- return TCL_OK;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest4_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_CmdProc *xProc;
- } aCmd[] = {
- { "thread_create", (Tcl_CmdProc*)tcl_thread_create },
- { "thread_wait", (Tcl_CmdProc*)tcl_thread_wait },
- { "thread_halt", (Tcl_CmdProc*)tcl_thread_halt },
- { "thread_argc", (Tcl_CmdProc*)tcl_thread_argc },
- { "thread_argv", (Tcl_CmdProc*)tcl_thread_argv },
- { "thread_colname", (Tcl_CmdProc*)tcl_thread_colname },
- { "thread_result", (Tcl_CmdProc*)tcl_thread_result },
- { "thread_error", (Tcl_CmdProc*)tcl_thread_error },
- { "thread_compile", (Tcl_CmdProc*)tcl_thread_compile },
- { "thread_step", (Tcl_CmdProc*)tcl_thread_step },
- { "thread_finalize", (Tcl_CmdProc*)tcl_thread_finalize },
- { "thread_swap", (Tcl_CmdProc*)tcl_thread_swap },
- { "thread_db_get", (Tcl_CmdProc*)tcl_thread_db_get },
- { "thread_db_put", (Tcl_CmdProc*)tcl_thread_db_put },
- { "thread_stmt_get", (Tcl_CmdProc*)tcl_thread_stmt_get },
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
- return TCL_OK;
-}
-#else
-int Sqlitetest4_Init(Tcl_Interp *interp){ return TCL_OK; }
-#endif /* SQLITE_OS_UNIX */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test5.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test5.c
deleted file mode 100644
index 0d9242862bc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test5.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the utf.c module in SQLite. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library. Specifically, the code in this file
-** is used for testing the SQLite routines for converting between
-** the various supported unicode encodings.
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-/*
-** The first argument is a TCL UTF-8 string. Return the byte array
-** object with the encoded representation of the string, including
-** the NULL terminator.
-*/
-static int SQLITE_TCLAPI binarize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int len;
- char *bytes;
- Tcl_Obj *pRet;
- assert(objc==2);
-
- bytes = Tcl_GetStringFromObj(objv[1], &len);
- pRet = Tcl_NewByteArrayObj((u8*)bytes, len+1);
- Tcl_SetObjResult(interp, pRet);
- return TCL_OK;
-}
-
-/*
-** Usage: test_value_overhead <repeat-count> <do-calls>.
-**
-** This routine is used to test the overhead of calls to
-** sqlite3_value_text(), on a value that contains a UTF-8 string. The idea
-** is to figure out whether or not it is a problem to use sqlite3_value
-** structures with collation sequence functions.
-**
-** If <do-calls> is 0, then the calls to sqlite3_value_text() are not
-** actually made.
-*/
-static int SQLITE_TCLAPI test_value_overhead(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int do_calls;
- int repeat_count;
- int i;
- Mem val;
-
- if( objc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0), " <repeat-count> <do-calls>", 0);
- return TCL_ERROR;
- }
-
- if( Tcl_GetIntFromObj(interp, objv[1], &repeat_count) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &do_calls) ) return TCL_ERROR;
-
- val.flags = MEM_Str|MEM_Term|MEM_Static;
- val.z = "hello world";
- val.enc = SQLITE_UTF8;
-
- for(i=0; i<repeat_count; i++){
- if( do_calls ){
- sqlite3_value_text(&val);
- }
- }
-
- return TCL_OK;
-}
-
-static u8 name_to_enc(Tcl_Interp *interp, Tcl_Obj *pObj){
- struct EncName {
- char *zName;
- u8 enc;
- } encnames[] = {
- { "UTF8", SQLITE_UTF8 },
- { "UTF16LE", SQLITE_UTF16LE },
- { "UTF16BE", SQLITE_UTF16BE },
- { "UTF16", SQLITE_UTF16 },
- { 0, 0 }
- };
- struct EncName *pEnc;
- char *z = Tcl_GetString(pObj);
- for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
- if( 0==sqlite3StrICmp(z, pEnc->zName) ){
- break;
- }
- }
- if( !pEnc->enc ){
- Tcl_AppendResult(interp, "No such encoding: ", z, 0);
- }
- if( pEnc->enc==SQLITE_UTF16 ){
- return SQLITE_UTF16NATIVE;
- }
- return pEnc->enc;
-}
-
-/*
-** Usage: test_translate <string/blob> <from enc> <to enc> ?<transient>?
-**
-*/
-static int SQLITE_TCLAPI test_translate(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- u8 enc_from;
- u8 enc_to;
- sqlite3_value *pVal;
-
- char *z;
- int len;
- void (*xDel)(void *p) = SQLITE_STATIC;
-
- if( objc!=4 && objc!=5 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], 0),
- " <string/blob> <from enc> <to enc>", 0
- );
- return TCL_ERROR;
- }
- if( objc==5 ){
- xDel = sqlite3_free;
- }
-
- enc_from = name_to_enc(interp, objv[2]);
- if( !enc_from ) return TCL_ERROR;
- enc_to = name_to_enc(interp, objv[3]);
- if( !enc_to ) return TCL_ERROR;
-
- pVal = sqlite3ValueNew(0);
-
- if( enc_from==SQLITE_UTF8 ){
- z = Tcl_GetString(objv[1]);
- if( objc==5 ){
- z = sqlite3_mprintf("%s", z);
- }
- sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel);
- }else{
- z = (char*)Tcl_GetByteArrayFromObj(objv[1], &len);
- if( objc==5 ){
- char *zTmp = z;
- z = sqlite3_malloc(len);
- memcpy(z, zTmp, len);
- }
- sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel);
- }
-
- z = (char *)sqlite3ValueText(pVal, enc_to);
- len = sqlite3ValueBytes(pVal, enc_to) + (enc_to==SQLITE_UTF8?1:2);
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((u8*)z, len));
-
- sqlite3ValueFree(pVal);
-
- return TCL_OK;
-}
-
-/*
-** Usage: translate_selftest
-**
-** Call sqlite3UtfSelfTest() to run the internal tests for unicode
-** translation. If there is a problem an assert() will fail.
-**/
-void sqlite3UtfSelfTest(void);
-static int SQLITE_TCLAPI test_translate_selftest(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_UTF16
- sqlite3UtfSelfTest();
-#endif
- return SQLITE_OK;
-}
-
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest5_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aCmd[] = {
- { "binarize", (Tcl_ObjCmdProc*)binarize },
- { "test_value_overhead", (Tcl_ObjCmdProc*)test_value_overhead },
- { "test_translate", (Tcl_ObjCmdProc*)test_translate },
- { "translate_selftest", (Tcl_ObjCmdProc*)test_translate_selftest},
- };
- int i;
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
- return SQLITE_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test6.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test6.c
deleted file mode 100644
index 9a3aa093f06..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test6.c
+++ /dev/null
@@ -1,1103 +0,0 @@
-/*
-** 2004 May 22
-**
-** 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 contains code that modified the OS layer in order to simulate
-** the effect on the database file of an OS crash or power failure. This
-** is used to test the ability of SQLite to recover from those situations.
-*/
-#if SQLITE_TEST /* This file is used for testing only */
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-#ifndef SQLITE_OMIT_DISKIO /* This file is a no-op if disk I/O is disabled */
-
-/* #define TRACE_CRASHTEST */
-
-typedef struct CrashFile CrashFile;
-typedef struct CrashGlobal CrashGlobal;
-typedef struct WriteBuffer WriteBuffer;
-
-/*
-** Method:
-**
-** This layer is implemented as a wrapper around the "real"
-** sqlite3_file object for the host system. Each time data is
-** written to the file object, instead of being written to the
-** underlying file, the write operation is stored in an in-memory
-** structure (type WriteBuffer). This structure is placed at the
-** end of a global ordered list (the write-list).
-**
-** When data is read from a file object, the requested region is
-** first retrieved from the real file. The write-list is then
-** traversed and data copied from any overlapping WriteBuffer
-** structures to the output buffer. i.e. a read() operation following
-** one or more write() operations works as expected, even if no
-** data has actually been written out to the real file.
-**
-** When a fsync() operation is performed, an operating system crash
-** may be simulated, in which case exit(-1) is called (the call to
-** xSync() never returns). Whether or not a crash is simulated,
-** the data associated with a subset of the WriteBuffer structures
-** stored in the write-list is written to the real underlying files
-** and the entries removed from the write-list. If a crash is simulated,
-** a subset of the buffers may be corrupted before the data is written.
-**
-** The exact subset of the write-list written and/or corrupted is
-** determined by the simulated device characteristics and sector-size.
-**
-** "Normal" mode:
-**
-** Normal mode is used when the simulated device has none of the
-** SQLITE_IOCAP_XXX flags set.
-**
-** In normal mode, if the fsync() is not a simulated crash, the
-** write-list is traversed from beginning to end. Each WriteBuffer
-** structure associated with the file handle used to call xSync()
-** is written to the real file and removed from the write-list.
-**
-** If a crash is simulated, one of the following takes place for
-** each WriteBuffer in the write-list, regardless of which
-** file-handle it is associated with:
-**
-** 1. The buffer is correctly written to the file, just as if
-** a crash were not being simulated.
-**
-** 2. Nothing is done.
-**
-** 3. Garbage data is written to all sectors of the file that
-** overlap the region specified by the WriteBuffer. Or garbage
-** data is written to some contiguous section within the
-** overlapped sectors.
-**
-** Device Characteristic flag handling:
-**
-** If the IOCAP_ATOMIC flag is set, then option (3) above is
-** never selected.
-**
-** If the IOCAP_ATOMIC512 flag is set, and the WriteBuffer represents
-** an aligned write() of an integer number of 512 byte regions, then
-** option (3) above is never selected. Instead, each 512 byte region
-** is either correctly written or left completely untouched. Similar
-** logic governs the behavior if any of the other ATOMICXXX flags
-** is set.
-**
-** If either the IOCAP_SAFEAPPEND or IOCAP_SEQUENTIAL flags are set
-** and a crash is being simulated, then an entry of the write-list is
-** selected at random. Everything in the list after the selected entry
-** is discarded before processing begins.
-**
-** If IOCAP_SEQUENTIAL is set and a crash is being simulated, option
-** (1) is selected for all write-list entries except the last. If a
-** crash is not being simulated, then all entries in the write-list
-** that occur before at least one write() on the file-handle specified
-** as part of the xSync() are written to their associated real files.
-**
-** If IOCAP_SAFEAPPEND is set and the first byte written by the write()
-** operation is one byte past the current end of the file, then option
-** (1) is always selected.
-*/
-
-/*
-** Each write operation in the write-list is represented by an instance
-** of the following structure.
-**
-** If zBuf is 0, then this structure represents a call to xTruncate(),
-** not xWrite(). In that case, iOffset is the size that the file is
-** truncated to.
-*/
-struct WriteBuffer {
- i64 iOffset; /* Byte offset of the start of this write() */
- int nBuf; /* Number of bytes written */
- u8 *zBuf; /* Pointer to copy of written data */
- CrashFile *pFile; /* File this write() applies to */
-
- WriteBuffer *pNext; /* Next in CrashGlobal.pWriteList */
-};
-
-struct CrashFile {
- const sqlite3_io_methods *pMethod; /* Must be first */
- sqlite3_file *pRealFile; /* Underlying "real" file handle */
- char *zName;
- int flags; /* Flags the file was opened with */
-
- /* Cache of the entire file. This is used to speed up OsRead() and
- ** OsFileSize() calls. Although both could be done by traversing the
- ** write-list, in practice this is impractically slow.
- */
- u8 *zData; /* Buffer containing file contents */
- int nData; /* Size of buffer allocated at zData */
- i64 iSize; /* Size of file in bytes */
-};
-
-struct CrashGlobal {
- WriteBuffer *pWriteList; /* Head of write-list */
- WriteBuffer *pWriteListEnd; /* End of write-list */
-
- int iSectorSize; /* Value of simulated sector size */
- int iDeviceCharacteristics; /* Value of simulated device characteristics */
-
- int iCrash; /* Crash on the iCrash'th call to xSync() */
- char zCrashFile[500]; /* Crash during an xSync() on this file */
-};
-
-static CrashGlobal g = {0, 0, SQLITE_DEFAULT_SECTOR_SIZE, 0, 0};
-
-/*
-** Set this global variable to 1 to enable crash testing.
-*/
-static int sqlite3CrashTestEnable = 0;
-
-static void *crash_malloc(int nByte){
- return (void *)Tcl_AttemptAlloc((size_t)nByte);
-}
-static void crash_free(void *p){
- Tcl_Free(p);
-}
-static void *crash_realloc(void *p, int n){
- return (void *)Tcl_AttemptRealloc(p, (size_t)n);
-}
-
-/*
-** Wrapper around the sqlite3OsWrite() function that avoids writing to the
-** 512 byte block begining at offset PENDING_BYTE.
-*/
-static int writeDbFile(CrashFile *p, u8 *z, i64 iAmt, i64 iOff){
- int rc = SQLITE_OK;
- int iSkip = 0;
- if( (iAmt-iSkip)>0 ){
- rc = sqlite3OsWrite(p->pRealFile, &z[iSkip], (int)(iAmt-iSkip), iOff+iSkip);
- }
- return rc;
-}
-
-/*
-** Flush the write-list as if xSync() had been called on file handle
-** pFile. If isCrash is true, simulate a crash.
-*/
-static int writeListSync(CrashFile *pFile, int isCrash){
- int rc = SQLITE_OK;
- int iDc = g.iDeviceCharacteristics;
-
- WriteBuffer *pWrite;
- WriteBuffer **ppPtr;
-
- /* If this is not a crash simulation, set pFinal to point to the
- ** last element of the write-list that is associated with file handle
- ** pFile.
- **
- ** If this is a crash simulation, set pFinal to an arbitrarily selected
- ** element of the write-list.
- */
- WriteBuffer *pFinal = 0;
- if( !isCrash ){
- for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext){
- if( pWrite->pFile==pFile ){
- pFinal = pWrite;
- }
- }
- }else if( iDc&(SQLITE_IOCAP_SEQUENTIAL|SQLITE_IOCAP_SAFE_APPEND) ){
- int nWrite = 0;
- int iFinal;
- for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext) nWrite++;
- sqlite3_randomness(sizeof(int), &iFinal);
- iFinal = ((iFinal<0)?-1*iFinal:iFinal)%nWrite;
- for(pWrite=g.pWriteList; iFinal>0; pWrite=pWrite->pNext) iFinal--;
- pFinal = pWrite;
- }
-
-#ifdef TRACE_CRASHTEST
- if( pFile ){
- printf("Sync %s (is %s crash)\n", pFile->zName, (isCrash?"a":"not a"));
- }
-#endif
-
- ppPtr = &g.pWriteList;
- for(pWrite=*ppPtr; rc==SQLITE_OK && pWrite; pWrite=*ppPtr){
- sqlite3_file *pRealFile = pWrite->pFile->pRealFile;
-
- /* (eAction==1) -> write block out normally,
- ** (eAction==2) -> do nothing,
- ** (eAction==3) -> trash sectors.
- */
- int eAction = 0;
- if( !isCrash ){
- eAction = 2;
- if( (pWrite->pFile==pFile || iDc&SQLITE_IOCAP_SEQUENTIAL) ){
- eAction = 1;
- }
- }else{
- char random;
- sqlite3_randomness(1, &random);
-
- /* Do not select option 3 (sector trashing) if the IOCAP_ATOMIC flag
- ** is set or this is an OsTruncate(), not an Oswrite().
- */
- if( (iDc&SQLITE_IOCAP_ATOMIC) || (pWrite->zBuf==0) ){
- random &= 0x01;
- }
-
- /* If IOCAP_SEQUENTIAL is set and this is not the final entry
- ** in the truncated write-list, always select option 1 (write
- ** out correctly).
- */
- if( (iDc&SQLITE_IOCAP_SEQUENTIAL && pWrite!=pFinal) ){
- random = 0;
- }
-
- /* If IOCAP_SAFE_APPEND is set and this OsWrite() operation is
- ** an append (first byte of the written region is 1 byte past the
- ** current EOF), always select option 1 (write out correctly).
- */
- if( iDc&SQLITE_IOCAP_SAFE_APPEND && pWrite->zBuf ){
- i64 iSize;
- sqlite3OsFileSize(pRealFile, &iSize);
- if( iSize==pWrite->iOffset ){
- random = 0;
- }
- }
-
- if( (random&0x06)==0x06 ){
- eAction = 3;
- }else{
- eAction = ((random&0x01)?2:1);
- }
- }
-
- switch( eAction ){
- case 1: { /* Write out correctly */
- if( pWrite->zBuf ){
- rc = writeDbFile(
- pWrite->pFile, pWrite->zBuf, pWrite->nBuf, pWrite->iOffset
- );
- }else{
- rc = sqlite3OsTruncate(pRealFile, pWrite->iOffset);
- }
- *ppPtr = pWrite->pNext;
-#ifdef TRACE_CRASHTEST
- if( isCrash ){
- printf("Writing %d bytes @ %d (%s)\n",
- pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName
- );
- }
-#endif
- crash_free(pWrite);
- break;
- }
- case 2: { /* Do nothing */
- ppPtr = &pWrite->pNext;
-#ifdef TRACE_CRASHTEST
- if( isCrash ){
- printf("Omiting %d bytes @ %d (%s)\n",
- pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName
- );
- }
-#endif
- break;
- }
- case 3: { /* Trash sectors */
- u8 *zGarbage;
- int iFirst = (int)(pWrite->iOffset/g.iSectorSize);
- int iLast = (int)((pWrite->iOffset+pWrite->nBuf-1)/g.iSectorSize);
-
- assert(pWrite->zBuf);
-
-#ifdef TRACE_CRASHTEST
- printf("Trashing %d sectors (%d bytes) @ %lld (sector %d) (%s)\n",
- 1+iLast-iFirst, (1+iLast-iFirst)*g.iSectorSize,
- pWrite->iOffset, iFirst, pWrite->pFile->zName
- );
-#endif
-
- zGarbage = crash_malloc(g.iSectorSize);
- if( zGarbage ){
- sqlite3_int64 i;
- for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){
- sqlite3_randomness(g.iSectorSize, zGarbage);
- rc = writeDbFile(
- pWrite->pFile, zGarbage, g.iSectorSize, i*g.iSectorSize
- );
- }
- crash_free(zGarbage);
- }else{
- rc = SQLITE_NOMEM;
- }
-
- ppPtr = &pWrite->pNext;
- break;
- }
-
- default:
- assert(!"Cannot happen");
- }
-
- if( pWrite==pFinal ) break;
- }
-
- if( rc==SQLITE_OK && isCrash ){
- exit(-1);
- }
-
- for(pWrite=g.pWriteList; pWrite && pWrite->pNext; pWrite=pWrite->pNext);
- g.pWriteListEnd = pWrite;
-
- return rc;
-}
-
-/*
-** Add an entry to the end of the write-list.
-*/
-static int writeListAppend(
- sqlite3_file *pFile,
- sqlite3_int64 iOffset,
- const u8 *zBuf,
- int nBuf
-){
- WriteBuffer *pNew;
-
- assert((zBuf && nBuf) || (!nBuf && !zBuf));
-
- pNew = (WriteBuffer *)crash_malloc(sizeof(WriteBuffer) + nBuf);
- if( pNew==0 ){
- fprintf(stderr, "out of memory in the crash simulator\n");
- }
- memset(pNew, 0, sizeof(WriteBuffer)+nBuf);
- pNew->iOffset = iOffset;
- pNew->nBuf = nBuf;
- pNew->pFile = (CrashFile *)pFile;
- if( zBuf ){
- pNew->zBuf = (u8 *)&pNew[1];
- memcpy(pNew->zBuf, zBuf, nBuf);
- }
-
- if( g.pWriteList ){
- assert(g.pWriteListEnd);
- g.pWriteListEnd->pNext = pNew;
- }else{
- g.pWriteList = pNew;
- }
- g.pWriteListEnd = pNew;
-
- return SQLITE_OK;
-}
-
-/*
-** Close a crash-file.
-*/
-static int cfClose(sqlite3_file *pFile){
- CrashFile *pCrash = (CrashFile *)pFile;
- writeListSync(pCrash, 0);
- sqlite3OsClose(pCrash->pRealFile);
- return SQLITE_OK;
-}
-
-/*
-** Read data from a crash-file.
-*/
-static int cfRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- CrashFile *pCrash = (CrashFile *)pFile;
- int nCopy = (int)MIN((i64)iAmt, (pCrash->iSize - iOfst));
-
- if( nCopy>0 ){
- memcpy(zBuf, &pCrash->zData[iOfst], nCopy);
- }
-
- /* Check the file-size to see if this is a short-read */
- if( nCopy<iAmt ){
- return SQLITE_IOERR_SHORT_READ;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Write data to a crash-file.
-*/
-static int cfWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- CrashFile *pCrash = (CrashFile *)pFile;
- if( iAmt+iOfst>pCrash->iSize ){
- pCrash->iSize = (int)(iAmt+iOfst);
- }
- while( pCrash->iSize>pCrash->nData ){
- u8 *zNew;
- int nNew = (pCrash->nData*2) + 4096;
- zNew = crash_realloc(pCrash->zData, nNew);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- memset(&zNew[pCrash->nData], 0, nNew-pCrash->nData);
- pCrash->nData = nNew;
- pCrash->zData = zNew;
- }
- memcpy(&pCrash->zData[iOfst], zBuf, iAmt);
- return writeListAppend(pFile, iOfst, zBuf, iAmt);
-}
-
-/*
-** Truncate a crash-file.
-*/
-static int cfTruncate(sqlite3_file *pFile, sqlite_int64 size){
- CrashFile *pCrash = (CrashFile *)pFile;
- assert(size>=0);
- if( pCrash->iSize>size ){
- pCrash->iSize = (int)size;
- }
- return writeListAppend(pFile, size, 0, 0);
-}
-
-/*
-** Sync a crash-file.
-*/
-static int cfSync(sqlite3_file *pFile, int flags){
- CrashFile *pCrash = (CrashFile *)pFile;
- int isCrash = 0;
-
- const char *zName = pCrash->zName;
- const char *zCrashFile = g.zCrashFile;
- int nName = (int)strlen(zName);
- int nCrashFile = (int)strlen(zCrashFile);
-
- if( nCrashFile>0 && zCrashFile[nCrashFile-1]=='*' ){
- nCrashFile--;
- if( nName>nCrashFile ) nName = nCrashFile;
- }
-
-#ifdef TRACE_CRASHTEST
- printf("cfSync(): nName = %d, nCrashFile = %d, zName = %s, zCrashFile = %s\n",
- nName, nCrashFile, zName, zCrashFile);
-#endif
-
- if( nName==nCrashFile && 0==memcmp(zName, zCrashFile, nName) ){
-#ifdef TRACE_CRASHTEST
- printf("cfSync(): name matched, g.iCrash = %d\n", g.iCrash);
-#endif
- if( (--g.iCrash)==0 ) isCrash = 1;
- }
-
- return writeListSync(pCrash, isCrash);
-}
-
-/*
-** Return the current file-size of the crash-file.
-*/
-static int cfFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- CrashFile *pCrash = (CrashFile *)pFile;
- *pSize = (i64)pCrash->iSize;
- return SQLITE_OK;
-}
-
-/*
-** Calls related to file-locks are passed on to the real file handle.
-*/
-static int cfLock(sqlite3_file *pFile, int eLock){
- return sqlite3OsLock(((CrashFile *)pFile)->pRealFile, eLock);
-}
-static int cfUnlock(sqlite3_file *pFile, int eLock){
- return sqlite3OsUnlock(((CrashFile *)pFile)->pRealFile, eLock);
-}
-static int cfCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- return sqlite3OsCheckReservedLock(((CrashFile *)pFile)->pRealFile, pResOut);
-}
-static int cfFileControl(sqlite3_file *pFile, int op, void *pArg){
- if( op==SQLITE_FCNTL_SIZE_HINT ){
- CrashFile *pCrash = (CrashFile *)pFile;
- i64 nByte = *(i64 *)pArg;
- if( nByte>pCrash->iSize ){
- if( SQLITE_OK==writeListAppend(pFile, nByte, 0, 0) ){
- pCrash->iSize = (int)nByte;
- }
- }
- return SQLITE_OK;
- }
- return sqlite3OsFileControl(((CrashFile *)pFile)->pRealFile, op, pArg);
-}
-
-/*
-** The xSectorSize() and xDeviceCharacteristics() functions return
-** the global values configured by the [sqlite_crashparams] tcl
-* interface.
-*/
-static int cfSectorSize(sqlite3_file *pFile){
- return g.iSectorSize;
-}
-static int cfDeviceCharacteristics(sqlite3_file *pFile){
- return g.iDeviceCharacteristics;
-}
-
-/*
-** Pass-throughs for WAL support.
-*/
-static int cfShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
- return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, ofst, n, flags);
-}
-static void cfShmBarrier(sqlite3_file *pFile){
- sqlite3OsShmBarrier(((CrashFile*)pFile)->pRealFile);
-}
-static int cfShmUnmap(sqlite3_file *pFile, int delFlag){
- return sqlite3OsShmUnmap(((CrashFile*)pFile)->pRealFile, delFlag);
-}
-static int cfShmMap(
- sqlite3_file *pFile, /* Handle open on database file */
- int iRegion, /* Region to retrieve */
- int sz, /* Size of regions */
- int w, /* True to extend file if necessary */
- void volatile **pp /* OUT: Mapped memory */
-){
- return sqlite3OsShmMap(((CrashFile*)pFile)->pRealFile, iRegion, sz, w, pp);
-}
-
-static const sqlite3_io_methods CrashFileVtab = {
- 2, /* iVersion */
- cfClose, /* xClose */
- cfRead, /* xRead */
- cfWrite, /* xWrite */
- cfTruncate, /* xTruncate */
- cfSync, /* xSync */
- cfFileSize, /* xFileSize */
- cfLock, /* xLock */
- cfUnlock, /* xUnlock */
- cfCheckReservedLock, /* xCheckReservedLock */
- cfFileControl, /* xFileControl */
- cfSectorSize, /* xSectorSize */
- cfDeviceCharacteristics, /* xDeviceCharacteristics */
- cfShmMap, /* xShmMap */
- cfShmLock, /* xShmLock */
- cfShmBarrier, /* xShmBarrier */
- cfShmUnmap /* xShmUnmap */
-};
-
-/*
-** Application data for the crash VFS
-*/
-struct crashAppData {
- sqlite3_vfs *pOrig; /* Wrapped vfs structure */
-};
-
-/*
-** Open a crash-file file handle.
-**
-** The caller will have allocated pVfs->szOsFile bytes of space
-** at pFile. This file uses this space for the CrashFile structure
-** and allocates space for the "real" file structure using
-** sqlite3_malloc(). The assumption here is (pVfs->szOsFile) is
-** equal or greater than sizeof(CrashFile).
-*/
-static int cfOpen(
- sqlite3_vfs *pCfVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- int rc;
- CrashFile *pWrapper = (CrashFile *)pFile;
- sqlite3_file *pReal = (sqlite3_file*)&pWrapper[1];
-
- memset(pWrapper, 0, sizeof(CrashFile));
- rc = sqlite3OsOpen(pVfs, zName, pReal, flags, pOutFlags);
-
- if( rc==SQLITE_OK ){
- i64 iSize;
- pWrapper->pMethod = &CrashFileVtab;
- pWrapper->zName = (char *)zName;
- pWrapper->pRealFile = pReal;
- rc = sqlite3OsFileSize(pReal, &iSize);
- pWrapper->iSize = (int)iSize;
- pWrapper->flags = flags;
- }
- if( rc==SQLITE_OK ){
- pWrapper->nData = (int)(4096 + pWrapper->iSize);
- pWrapper->zData = crash_malloc(pWrapper->nData);
- if( pWrapper->zData ){
- /* os_unix.c contains an assert() that fails if the caller attempts
- ** to read data from the 512-byte locking region of a file opened
- ** with the SQLITE_OPEN_MAIN_DB flag. This region of a database file
- ** never contains valid data anyhow. So avoid doing such a read here.
- **
- ** UPDATE: It also contains an assert() verifying that each call
- ** to the xRead() method reads less than 128KB of data.
- */
- i64 iOff;
-
- memset(pWrapper->zData, 0, pWrapper->nData);
- for(iOff=0; iOff<pWrapper->iSize; iOff += 512){
- int nRead = (int)(pWrapper->iSize - iOff);
- if( nRead>512 ) nRead = 512;
- rc = sqlite3OsRead(pReal, &pWrapper->zData[iOff], nRead, iOff);
- }
- }else{
- rc = SQLITE_NOMEM;
- }
- }
- if( rc!=SQLITE_OK && pWrapper->pMethod ){
- sqlite3OsClose(pFile);
- }
- return rc;
-}
-
-static int cfDelete(sqlite3_vfs *pCfVfs, const char *zPath, int dirSync){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xDelete(pVfs, zPath, dirSync);
-}
-static int cfAccess(
- sqlite3_vfs *pCfVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xAccess(pVfs, zPath, flags, pResOut);
-}
-static int cfFullPathname(
- sqlite3_vfs *pCfVfs,
- const char *zPath,
- int nPathOut,
- char *zPathOut
-){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
-}
-static void *cfDlOpen(sqlite3_vfs *pCfVfs, const char *zPath){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xDlOpen(pVfs, zPath);
-}
-static void cfDlError(sqlite3_vfs *pCfVfs, int nByte, char *zErrMsg){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- pVfs->xDlError(pVfs, nByte, zErrMsg);
-}
-static void (*cfDlSym(sqlite3_vfs *pCfVfs, void *pH, const char *zSym))(void){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xDlSym(pVfs, pH, zSym);
-}
-static void cfDlClose(sqlite3_vfs *pCfVfs, void *pHandle){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- pVfs->xDlClose(pVfs, pHandle);
-}
-static int cfRandomness(sqlite3_vfs *pCfVfs, int nByte, char *zBufOut){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xRandomness(pVfs, nByte, zBufOut);
-}
-static int cfSleep(sqlite3_vfs *pCfVfs, int nMicro){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xSleep(pVfs, nMicro);
-}
-static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xCurrentTime(pVfs, pTimeOut);
-}
-static int cfGetLastError(sqlite3_vfs *pCfVfs, int n, char *z){
- sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
- return pVfs->xGetLastError(pVfs, n, z);
-}
-
-static int processDevSymArgs(
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[],
- int *piDeviceChar,
- int *piSectorSize
-){
- struct DeviceFlag {
- char *zName;
- int iValue;
- } aFlag[] = {
- { "atomic", SQLITE_IOCAP_ATOMIC },
- { "atomic512", SQLITE_IOCAP_ATOMIC512 },
- { "atomic1k", SQLITE_IOCAP_ATOMIC1K },
- { "atomic2k", SQLITE_IOCAP_ATOMIC2K },
- { "atomic4k", SQLITE_IOCAP_ATOMIC4K },
- { "atomic8k", SQLITE_IOCAP_ATOMIC8K },
- { "atomic16k", SQLITE_IOCAP_ATOMIC16K },
- { "atomic32k", SQLITE_IOCAP_ATOMIC32K },
- { "atomic64k", SQLITE_IOCAP_ATOMIC64K },
- { "sequential", SQLITE_IOCAP_SEQUENTIAL },
- { "safe_append", SQLITE_IOCAP_SAFE_APPEND },
- { "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
- { "batch-atomic", SQLITE_IOCAP_BATCH_ATOMIC },
- { 0, 0 }
- };
-
- int i;
- int iDc = 0;
- int iSectorSize = 0;
- int setSectorsize = 0;
- int setDeviceChar = 0;
-
- for(i=0; i<objc; i+=2){
- int nOpt;
- char *zOpt = Tcl_GetStringFromObj(objv[i], &nOpt);
-
- if( (nOpt>11 || nOpt<2 || strncmp("-sectorsize", zOpt, nOpt))
- && (nOpt>16 || nOpt<2 || strncmp("-characteristics", zOpt, nOpt))
- ){
- Tcl_AppendResult(interp,
- "Bad option: \"", zOpt,
- "\" - must be \"-characteristics\" or \"-sectorsize\"", 0
- );
- return TCL_ERROR;
- }
- if( i==objc-1 ){
- Tcl_AppendResult(interp, "Option requires an argument: \"", zOpt, "\"",0);
- return TCL_ERROR;
- }
-
- if( zOpt[1]=='s' ){
- if( Tcl_GetIntFromObj(interp, objv[i+1], &iSectorSize) ){
- return TCL_ERROR;
- }
- setSectorsize = 1;
- }else{
- int j;
- Tcl_Obj **apObj;
- int nObj;
- if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){
- return TCL_ERROR;
- }
- for(j=0; j<nObj; j++){
- int rc;
- int iChoice;
- Tcl_Obj *pFlag = Tcl_DuplicateObj(apObj[j]);
- Tcl_IncrRefCount(pFlag);
- Tcl_UtfToLower(Tcl_GetString(pFlag));
-
- rc = Tcl_GetIndexFromObjStruct(
- interp, pFlag, aFlag, sizeof(aFlag[0]), "no such flag", 0, &iChoice
- );
- Tcl_DecrRefCount(pFlag);
- if( rc ){
- return TCL_ERROR;
- }
-
- iDc |= aFlag[iChoice].iValue;
- }
- setDeviceChar = 1;
- }
- }
-
- if( setDeviceChar ){
- *piDeviceChar = iDc;
- }
- if( setSectorsize ){
- *piSectorSize = iSectorSize;
- }
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_crash_now
-**
-** Simulate a crash immediately. This function does not return
-** (writeListSync() calls exit(-1)).
-*/
-static int SQLITE_TCLAPI crashNowCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
- writeListSync(0, 1);
- assert( 0 );
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite_crash_enable ENABLE ?DEFAULT?
-**
-** Parameter ENABLE must be a boolean value. If true, then the "crash"
-** vfs is added to the system. If false, it is removed.
-*/
-static int SQLITE_TCLAPI crashEnableCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int isEnable;
- int isDefault = 0;
- static sqlite3_vfs crashVfs = {
- 2, /* iVersion */
- 0, /* szOsFile */
- 0, /* mxPathname */
- 0, /* pNext */
- "crash", /* zName */
- 0, /* pAppData */
-
- cfOpen, /* xOpen */
- cfDelete, /* xDelete */
- cfAccess, /* xAccess */
- cfFullPathname, /* xFullPathname */
- cfDlOpen, /* xDlOpen */
- cfDlError, /* xDlError */
- cfDlSym, /* xDlSym */
- cfDlClose, /* xDlClose */
- cfRandomness, /* xRandomness */
- cfSleep, /* xSleep */
- cfCurrentTime, /* xCurrentTime */
- cfGetLastError, /* xGetLastError */
- 0, /* xCurrentTimeInt64 */
- };
-
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "ENABLE ?DEFAULT?");
- return TCL_ERROR;
- }
-
- if( Tcl_GetBooleanFromObj(interp, objv[1], &isEnable) ){
- return TCL_ERROR;
- }
- if( objc==3 && Tcl_GetBooleanFromObj(interp, objv[2], &isDefault) ){
- return TCL_ERROR;
- }
-
- if( (isEnable && crashVfs.pAppData) || (!isEnable && !crashVfs.pAppData) ){
- return TCL_OK;
- }
-
- if( crashVfs.pAppData==0 ){
- sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0);
- crashVfs.mxPathname = pOriginalVfs->mxPathname;
- crashVfs.pAppData = (void *)pOriginalVfs;
- crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile;
- sqlite3_vfs_register(&crashVfs, isDefault);
- }else{
- crashVfs.pAppData = 0;
- sqlite3_vfs_unregister(&crashVfs);
- }
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite_crashparams ?OPTIONS? DELAY CRASHFILE
-**
-** This procedure implements a TCL command that enables crash testing
-** in testfixture. Once enabled, crash testing cannot be disabled.
-**
-** Available options are "-characteristics" and "-sectorsize". Both require
-** an argument. For -sectorsize, this is the simulated sector size in
-** bytes. For -characteristics, the argument must be a list of io-capability
-** flags to simulate. Valid flags are "atomic", "atomic512", "atomic1K",
-** "atomic2K", "atomic4K", "atomic8K", "atomic16K", "atomic32K",
-** "atomic64K", "sequential" and "safe_append".
-**
-** Example:
-**
-** sqlite_crashparams -sect 1024 -char {atomic sequential} ./test.db 1
-**
-*/
-static int SQLITE_TCLAPI crashParamsObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int iDelay;
- const char *zCrashFile;
- int nCrashFile, iDc, iSectorSize;
-
- iDc = -1;
- iSectorSize = -1;
-
- if( objc<3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE");
- goto error;
- }
-
- zCrashFile = Tcl_GetStringFromObj(objv[objc-1], &nCrashFile);
- if( nCrashFile>=sizeof(g.zCrashFile) ){
- Tcl_AppendResult(interp, "Filename is too long: \"", zCrashFile, "\"", 0);
- goto error;
- }
- if( Tcl_GetIntFromObj(interp, objv[objc-2], &iDelay) ){
- goto error;
- }
-
- if( processDevSymArgs(interp, objc-3, &objv[1], &iDc, &iSectorSize) ){
- return TCL_ERROR;
- }
-
- if( iDc>=0 ){
- g.iDeviceCharacteristics = iDc;
- }
- if( iSectorSize>=0 ){
- g.iSectorSize = iSectorSize;
- }
-
- g.iCrash = iDelay;
- memcpy(g.zCrashFile, zCrashFile, nCrashFile+1);
- sqlite3CrashTestEnable = 1;
- return TCL_OK;
-
-error:
- return TCL_ERROR;
-}
-
-static int SQLITE_TCLAPI devSymObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void devsym_register(int iDeviceChar, int iSectorSize);
-
- int iDc = -1;
- int iSectorSize = -1;
-
- if( processDevSymArgs(interp, objc-1, &objv[1], &iDc, &iSectorSize) ){
- return TCL_ERROR;
- }
- devsym_register(iDc, iSectorSize);
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_crash_on_write N
-*/
-static int SQLITE_TCLAPI writeCrashObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void devsym_crash_on_write(int);
- int nWrite = 0;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NWRITE");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &nWrite) ){
- return TCL_ERROR;
- }
-
- devsym_crash_on_write(nWrite);
- return TCL_OK;
-}
-
-/*
-** tclcmd: unregister_devsim
-*/
-static int SQLITE_TCLAPI dsUnregisterObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void devsym_unregister(void);
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- devsym_unregister();
- return TCL_OK;
-}
-
-/*
-** tclcmd: register_jt_vfs ?-default? PARENT-VFS
-*/
-static int SQLITE_TCLAPI jtObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int jt_register(char *, int);
- char *zParent = 0;
-
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?-default? PARENT-VFS");
- return TCL_ERROR;
- }
- zParent = Tcl_GetString(objv[1]);
- if( objc==3 ){
- if( strcmp(zParent, "-default") ){
- Tcl_AppendResult(interp,
- "bad option \"", zParent, "\": must be -default", 0
- );
- return TCL_ERROR;
- }
- zParent = Tcl_GetString(objv[2]);
- }
-
- if( !(*zParent) ){
- zParent = 0;
- }
- if( jt_register(zParent, objc==3) ){
- Tcl_AppendResult(interp, "Error in jt_register", 0);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: unregister_jt_vfs
-*/
-static int SQLITE_TCLAPI jtUnregisterObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void jt_unregister(void);
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- jt_unregister();
- return TCL_OK;
-}
-
-#endif /* SQLITE_OMIT_DISKIO */
-
-/*
-** This procedure registers the TCL procedures defined in this file.
-*/
-int Sqlitetest6_Init(Tcl_Interp *interp){
-#ifndef SQLITE_OMIT_DISKIO
- Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_crash_now", crashNowCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_crash_on_write", writeCrashObjCmd,0,0);
- Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);
-#endif
- return TCL_OK;
-}
-
-#endif /* SQLITE_TEST */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test7.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test7.c
deleted file mode 100644
index d57e4b826b8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test7.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
-** 2006 January 09
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the client/server version of the SQLite library.
-** Derived from test4.c.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-/*
-** This test only works on UNIX with a SQLITE_THREADSAFE build that includes
-** the SQLITE_SERVER option.
-*/
-#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE) && \
- SQLITE_OS_UNIX && SQLITE_THREADSAFE
-
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <sched.h>
-#include <ctype.h>
-
-/*
-** Interfaces defined in server.c
-*/
-int sqlite3_client_open(const char*, sqlite3**);
-int sqlite3_client_prepare(sqlite3*,const char*,int,
- sqlite3_stmt**,const char**);
-int sqlite3_client_step(sqlite3_stmt*);
-int sqlite3_client_reset(sqlite3_stmt*);
-int sqlite3_client_finalize(sqlite3_stmt*);
-int sqlite3_client_close(sqlite3*);
-int sqlite3_server_start(void);
-int sqlite3_server_stop(void);
-void sqlite3_server_start2(int *pnDecr);
-
-/*
-** Each thread is controlled by an instance of the following
-** structure.
-*/
-typedef struct Thread Thread;
-struct Thread {
- /* The first group of fields are writable by the supervisor thread
- ** and read-only to the client threads
- */
- char *zFilename; /* Name of database file */
- void (*xOp)(Thread*); /* next operation to do */
- char *zArg; /* argument usable by xOp */
- volatile int opnum; /* Operation number */
- volatile int busy; /* True if this thread is in use */
-
- /* The next group of fields are writable by the client threads
- ** but read-only to the superviser thread.
- */
- volatile int completed; /* Number of operations completed */
- sqlite3 *db; /* Open database */
- sqlite3_stmt *pStmt; /* Pending operation */
- char *zErr; /* operation error */
- char *zStaticErr; /* Static error message */
- int rc; /* operation return code */
- int argc; /* number of columns in result */
- const char *argv[100]; /* result columns */
- const char *colv[100]; /* result column names */
-
- /* Initialized to 1 by the supervisor thread when the client is
- ** created, and then deemed read-only to the supervisor thread.
- ** Is set to 0 by the server thread belonging to this client
- ** just before it exits.
- */
- int nServer; /* Number of server threads running */
-};
-
-/*
-** There can be as many as 26 threads running at once. Each is named
-** by a capital letter: A, B, C, ..., Y, Z.
-*/
-#define N_THREAD 26
-static Thread threadset[N_THREAD];
-
-/*
-** The main loop for a thread. Threads use busy waiting.
-*/
-static void *client_main(void *pArg){
- Thread *p = (Thread*)pArg;
- if( p->db ){
- sqlite3_client_close(p->db);
- }
- sqlite3_client_open(p->zFilename, &p->db);
- if( SQLITE_OK!=sqlite3_errcode(p->db) ){
- p->zErr = strdup(sqlite3_errmsg(p->db));
- sqlite3_client_close(p->db);
- p->db = 0;
- }
- p->pStmt = 0;
- p->completed = 1;
- while( p->opnum<=p->completed ) sched_yield();
- while( p->xOp ){
- if( p->zErr && p->zErr!=p->zStaticErr ){
- sqlite3_free(p->zErr);
- p->zErr = 0;
- }
- (*p->xOp)(p);
- p->completed++;
- while( p->opnum<=p->completed ) sched_yield();
- }
- if( p->pStmt ){
- sqlite3_client_finalize(p->pStmt);
- p->pStmt = 0;
- }
- if( p->db ){
- sqlite3_client_close(p->db);
- p->db = 0;
- }
- if( p->zErr && p->zErr!=p->zStaticErr ){
- sqlite3_free(p->zErr);
- p->zErr = 0;
- }
- p->completed++;
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_thread_cleanup();
-#endif
- return 0;
-}
-
-/*
-** Get a thread ID which is an upper case letter. Return the index.
-** If the argument is not a valid thread ID put an error message in
-** the interpreter and return -1.
-*/
-static int parse_client_id(Tcl_Interp *interp, const char *zArg){
- if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){
- Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0);
- return -1;
- }
- return zArg[0] - 'A';
-}
-
-/*
-** Usage: client_create NAME FILENAME
-**
-** NAME should be an upper case letter. Start the thread running with
-** an open connection to the given database.
-*/
-static int SQLITE_TCLAPI tcl_client_create(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- pthread_t x;
- int rc;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID FILENAME", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( threadset[i].busy ){
- Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0);
- return TCL_ERROR;
- }
- threadset[i].busy = 1;
- sqlite3_free(threadset[i].zFilename);
- threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]);
- threadset[i].opnum = 1;
- threadset[i].completed = 0;
- rc = pthread_create(&x, 0, client_main, &threadset[i]);
- if( rc ){
- Tcl_AppendResult(interp, "failed to create the thread", 0);
- sqlite3_free(threadset[i].zFilename);
- threadset[i].busy = 0;
- return TCL_ERROR;
- }
- pthread_detach(x);
- if( threadset[i].nServer==0 ){
- threadset[i].nServer = 1;
- sqlite3_server_start2(&threadset[i].nServer);
- }
- return TCL_OK;
-}
-
-/*
-** Wait for a thread to reach its idle state.
-*/
-static void client_wait(Thread *p){
- while( p->opnum>p->completed ) sched_yield();
-}
-
-/*
-** Usage: client_wait ID
-**
-** Wait on thread ID to reach its idle state.
-*/
-static int SQLITE_TCLAPI tcl_client_wait(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- return TCL_OK;
-}
-
-/*
-** Stop a thread.
-*/
-static void stop_thread(Thread *p){
- client_wait(p);
- p->xOp = 0;
- p->opnum++;
- client_wait(p);
- sqlite3_free(p->zArg);
- p->zArg = 0;
- sqlite3_free(p->zFilename);
- p->zFilename = 0;
- p->busy = 0;
-}
-
-/*
-** Usage: client_halt ID
-**
-** Cause a client thread to shut itself down. Wait for the shutdown to be
-** completed. If ID is "*" then stop all client threads.
-*/
-static int SQLITE_TCLAPI tcl_client_halt(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- if( argv[1][0]=='*' && argv[1][1]==0 ){
- for(i=0; i<N_THREAD; i++){
- if( threadset[i].busy ){
- stop_thread(&threadset[i]);
- }
- }
- }else{
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- stop_thread(&threadset[i]);
- }
-
- /* If no client threads are still running, also stop the server */
- for(i=0; i<N_THREAD && threadset[i].busy==0; i++){}
- if( i>=N_THREAD ){
- sqlite3_server_stop();
- while( 1 ){
- for(i=0; i<N_THREAD && threadset[i].nServer==0; i++);
- if( i==N_THREAD ) break;
- sched_yield();
- }
- }
- return TCL_OK;
-}
-
-/*
-** Usage: client_argc ID
-**
-** Wait on the most recent client_step to complete, then return the
-** number of columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_client_argc(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- char zBuf[100];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", threadset[i].argc);
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: client_argv ID N
-**
-** Wait on the most recent client_step to complete, then return the
-** value of the N-th columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_client_argv(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- int n;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID N", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
- client_wait(&threadset[i]);
- if( n<0 || n>=threadset[i].argc ){
- Tcl_AppendResult(interp, "column number out of range", 0);
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, threadset[i].argv[n], 0);
- return TCL_OK;
-}
-
-/*
-** Usage: client_colname ID N
-**
-** Wait on the most recent client_step to complete, then return the
-** name of the N-th columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_client_colname(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- int n;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID N", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
- client_wait(&threadset[i]);
- if( n<0 || n>=threadset[i].argc ){
- Tcl_AppendResult(interp, "column number out of range", 0);
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, threadset[i].colv[n], 0);
- return TCL_OK;
-}
-
-extern const char *sqlite3ErrName(int);
-
-/*
-** Usage: client_result ID
-**
-** Wait on the most recent operation to complete, then return the
-** result code from that operation.
-*/
-static int SQLITE_TCLAPI tcl_client_result(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- const char *zName;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- zName = sqlite3ErrName(threadset[i].rc);
- Tcl_AppendResult(interp, zName, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: client_error ID
-**
-** Wait on the most recent operation to complete, then return the
-** error string.
-*/
-static int SQLITE_TCLAPI tcl_client_error(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- Tcl_AppendResult(interp, threadset[i].zErr, 0);
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to compile an SQL statement.
-*/
-static void do_compile(Thread *p){
- if( p->db==0 ){
- p->zErr = p->zStaticErr = "no database is open";
- p->rc = SQLITE_ERROR;
- return;
- }
- if( p->pStmt ){
- sqlite3_client_finalize(p->pStmt);
- p->pStmt = 0;
- }
- p->rc = sqlite3_client_prepare(p->db, p->zArg, -1, &p->pStmt, 0);
-}
-
-/*
-** Usage: client_compile ID SQL
-**
-** Compile a new virtual machine.
-*/
-static int SQLITE_TCLAPI tcl_client_compile(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID SQL", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- threadset[i].xOp = do_compile;
- sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = sqlite3_mprintf("%s", argv[2]);
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to step the virtual machine.
-*/
-static void do_step(Thread *p){
- int i;
- if( p->pStmt==0 ){
- p->zErr = p->zStaticErr = "no virtual machine available";
- p->rc = SQLITE_ERROR;
- return;
- }
- p->rc = sqlite3_client_step(p->pStmt);
- if( p->rc==SQLITE_ROW ){
- p->argc = sqlite3_column_count(p->pStmt);
- for(i=0; i<sqlite3_data_count(p->pStmt); i++){
- p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i);
- }
- for(i=0; i<p->argc; i++){
- p->colv[i] = sqlite3_column_name(p->pStmt, i);
- }
- }
-}
-
-/*
-** Usage: client_step ID
-**
-** Advance the virtual machine by one step
-*/
-static int SQLITE_TCLAPI tcl_client_step(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " IDL", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- threadset[i].xOp = do_step;
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to finalize a virtual machine.
-*/
-static void do_finalize(Thread *p){
- if( p->pStmt==0 ){
- p->zErr = p->zStaticErr = "no virtual machine available";
- p->rc = SQLITE_ERROR;
- return;
- }
- p->rc = sqlite3_client_finalize(p->pStmt);
- p->pStmt = 0;
-}
-
-/*
-** Usage: client_finalize ID
-**
-** Finalize the virtual machine.
-*/
-static int SQLITE_TCLAPI tcl_client_finalize(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " IDL", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- threadset[i].xOp = do_finalize;
- sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = 0;
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to reset a virtual machine.
-*/
-static void do_reset(Thread *p){
- if( p->pStmt==0 ){
- p->zErr = p->zStaticErr = "no virtual machine available";
- p->rc = SQLITE_ERROR;
- return;
- }
- p->rc = sqlite3_client_reset(p->pStmt);
- p->pStmt = 0;
-}
-
-/*
-** Usage: client_reset ID
-**
-** Finalize the virtual machine.
-*/
-static int SQLITE_TCLAPI tcl_client_reset(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " IDL", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- threadset[i].xOp = do_reset;
- sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = 0;
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** Usage: client_swap ID ID
-**
-** Interchange the sqlite* pointer between two threads.
-*/
-static int SQLITE_TCLAPI tcl_client_swap(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i, j;
- sqlite3 *temp;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID1 ID2", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- j = parse_client_id(interp, argv[2]);
- if( j<0 ) return TCL_ERROR;
- if( !threadset[j].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[j]);
- temp = threadset[i].db;
- threadset[i].db = threadset[j].db;
- threadset[j].db = temp;
- return TCL_OK;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest7_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_CmdProc *xProc;
- } aCmd[] = {
- { "client_create", (Tcl_CmdProc*)tcl_client_create },
- { "client_wait", (Tcl_CmdProc*)tcl_client_wait },
- { "client_halt", (Tcl_CmdProc*)tcl_client_halt },
- { "client_argc", (Tcl_CmdProc*)tcl_client_argc },
- { "client_argv", (Tcl_CmdProc*)tcl_client_argv },
- { "client_colname", (Tcl_CmdProc*)tcl_client_colname },
- { "client_result", (Tcl_CmdProc*)tcl_client_result },
- { "client_error", (Tcl_CmdProc*)tcl_client_error },
- { "client_compile", (Tcl_CmdProc*)tcl_client_compile },
- { "client_step", (Tcl_CmdProc*)tcl_client_step },
- { "client_reset", (Tcl_CmdProc*)tcl_client_reset },
- { "client_finalize", (Tcl_CmdProc*)tcl_client_finalize },
- { "client_swap", (Tcl_CmdProc*)tcl_client_swap },
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
- return TCL_OK;
-}
-#else
-int Sqlitetest7_Init(Tcl_Interp *interp){ return TCL_OK; }
-#endif /* SQLITE_OS_UNIX */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test8.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test8.c
deleted file mode 100644
index 2684f801fa7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test8.c
+++ /dev/null
@@ -1,1444 +0,0 @@
-/*
-** 2006 June 10
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the virtual table interfaces. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-typedef struct echo_vtab echo_vtab;
-typedef struct echo_cursor echo_cursor;
-
-/*
-** The test module defined in this file uses four global Tcl variables to
-** commicate with test-scripts:
-**
-** $::echo_module
-** $::echo_module_sync_fail
-** $::echo_module_begin_fail
-** $::echo_module_cost
-**
-** The variable ::echo_module is a list. Each time one of the following
-** methods is called, one or more elements are appended to the list.
-** This is used for automated testing of virtual table modules.
-**
-** The ::echo_module_sync_fail variable is set by test scripts and read
-** by code in this file. If it is set to the name of a real table in the
-** the database, then all xSync operations on echo virtual tables that
-** use the named table as a backing store will fail.
-*/
-
-/*
-** Errors can be provoked within the following echo virtual table methods:
-**
-** xBestIndex xOpen xFilter xNext
-** xColumn xRowid xUpdate xSync
-** xBegin xRename
-**
-** This is done by setting the global tcl variable:
-**
-** echo_module_fail($method,$tbl)
-**
-** where $method is set to the name of the virtual table method to fail
-** (i.e. "xBestIndex") and $tbl is the name of the table being echoed (not
-** the name of the virtual table, the name of the underlying real table).
-*/
-
-/*
-** An echo virtual-table object.
-**
-** echo.vtab.aIndex is an array of booleans. The nth entry is true if
-** the nth column of the real table is the left-most column of an index
-** (implicit or otherwise). In other words, if SQLite can optimize
-** a query like "SELECT * FROM real_table WHERE col = ?".
-**
-** Member variable aCol[] contains copies of the column names of the real
-** table.
-*/
-struct echo_vtab {
- sqlite3_vtab base;
- Tcl_Interp *interp; /* Tcl interpreter containing debug variables */
- sqlite3 *db; /* Database connection */
-
- int isPattern;
- int inTransaction; /* True if within a transaction */
- char *zThis; /* Name of the echo table */
- char *zTableName; /* Name of the real table */
- char *zLogName; /* Name of the log table */
- int nCol; /* Number of columns in the real table */
- int *aIndex; /* Array of size nCol. True if column has an index */
- char **aCol; /* Array of size nCol. Column names */
-};
-
-/* An echo cursor object */
-struct echo_cursor {
- sqlite3_vtab_cursor base;
- sqlite3_stmt *pStmt;
-};
-
-static int simulateVtabError(echo_vtab *p, const char *zMethod){
- const char *zErr;
- char zVarname[128];
- zVarname[127] = '\0';
- sqlite3_snprintf(127, zVarname, "echo_module_fail(%s,%s)", zMethod, p->zTableName);
- zErr = Tcl_GetVar(p->interp, zVarname, TCL_GLOBAL_ONLY);
- if( zErr ){
- p->base.zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", zErr);
- }
- return (zErr!=0);
-}
-
-/*
-** Convert an SQL-style quoted string into a normal string by removing
-** the quote characters. The conversion is done in-place. If the
-** input does not begin with a quote character, then this routine
-** is a no-op.
-**
-** Examples:
-**
-** "abc" becomes abc
-** 'xyz' becomes xyz
-** [pqr] becomes pqr
-** `mno` becomes mno
-*/
-static void dequoteString(char *z){
- int quote;
- int i, j;
- if( z==0 ) return;
- quote = z[0];
- switch( quote ){
- case '\'': break;
- case '"': break;
- case '`': break; /* For MySQL compatibility */
- case '[': quote = ']'; break; /* For MS SqlServer compatibility */
- default: return;
- }
- for(i=1, j=0; z[i]; i++){
- if( z[i]==quote ){
- if( z[i+1]==quote ){
- z[j++] = quote;
- i++;
- }else{
- z[j++] = 0;
- break;
- }
- }else{
- z[j++] = z[i];
- }
- }
-}
-
-/*
-** Retrieve the column names for the table named zTab via database
-** connection db. SQLITE_OK is returned on success, or an sqlite error
-** code otherwise.
-**
-** If successful, the number of columns is written to *pnCol. *paCol is
-** set to point at sqlite3_malloc()'d space containing the array of
-** nCol column names. The caller is responsible for calling sqlite3_free
-** on *paCol.
-*/
-static int getColumnNames(
- sqlite3 *db,
- const char *zTab,
- char ***paCol,
- int *pnCol
-){
- char **aCol = 0;
- char *zSql;
- sqlite3_stmt *pStmt = 0;
- int rc = SQLITE_OK;
- int nCol = 0;
-
- /* Prepare the statement "SELECT * FROM <tbl>". The column names
- ** of the result set of the compiled SELECT will be the same as
- ** the column names of table <tbl>.
- */
- zSql = sqlite3_mprintf("SELECT * FROM %Q", zTab);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- goto out;
- }
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
-
- if( rc==SQLITE_OK ){
- int ii;
- int nBytes;
- char *zSpace;
- nCol = sqlite3_column_count(pStmt);
-
- /* Figure out how much space to allocate for the array of column names
- ** (including space for the strings themselves). Then allocate it.
- */
- nBytes = sizeof(char *) * nCol;
- for(ii=0; ii<nCol; ii++){
- const char *zName = sqlite3_column_name(pStmt, ii);
- if( !zName ){
- rc = SQLITE_NOMEM;
- goto out;
- }
- nBytes += (int)strlen(zName)+1;
- }
- aCol = (char **)sqlite3MallocZero(nBytes);
- if( !aCol ){
- rc = SQLITE_NOMEM;
- goto out;
- }
-
- /* Copy the column names into the allocated space and set up the
- ** pointers in the aCol[] array.
- */
- zSpace = (char *)(&aCol[nCol]);
- for(ii=0; ii<nCol; ii++){
- aCol[ii] = zSpace;
- sqlite3_snprintf(nBytes, zSpace, "%s", sqlite3_column_name(pStmt,ii));
- zSpace += (int)strlen(zSpace) + 1;
- }
- assert( (zSpace-nBytes)==(char *)aCol );
- }
-
- *paCol = aCol;
- *pnCol = nCol;
-
-out:
- sqlite3_finalize(pStmt);
- return rc;
-}
-
-/*
-** Parameter zTab is the name of a table in database db with nCol
-** columns. This function allocates an array of integers nCol in
-** size and populates it according to any implicit or explicit
-** indices on table zTab.
-**
-** If successful, SQLITE_OK is returned and *paIndex set to point
-** at the allocated array. Otherwise, an error code is returned.
-**
-** See comments associated with the member variable aIndex above
-** "struct echo_vtab" for details of the contents of the array.
-*/
-static int getIndexArray(
- sqlite3 *db, /* Database connection */
- const char *zTab, /* Name of table in database db */
- int nCol,
- int **paIndex
-){
- sqlite3_stmt *pStmt = 0;
- int *aIndex = 0;
- int rc;
- char *zSql;
-
- /* Allocate space for the index array */
- aIndex = (int *)sqlite3MallocZero(sizeof(int) * nCol);
- if( !aIndex ){
- rc = SQLITE_NOMEM;
- goto get_index_array_out;
- }
-
- /* Compile an sqlite pragma to loop through all indices on table zTab */
- zSql = sqlite3_mprintf("PRAGMA index_list(%s)", zTab);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- goto get_index_array_out;
- }
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
-
- /* For each index, figure out the left-most column and set the
- ** corresponding entry in aIndex[] to 1.
- */
- while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zIdx = (const char *)sqlite3_column_text(pStmt, 1);
- sqlite3_stmt *pStmt2 = 0;
- if( zIdx==0 ) continue;
- zSql = sqlite3_mprintf("PRAGMA index_info(%s)", zIdx);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- goto get_index_array_out;
- }
- rc = sqlite3_prepare(db, zSql, -1, &pStmt2, 0);
- sqlite3_free(zSql);
- if( pStmt2 && sqlite3_step(pStmt2)==SQLITE_ROW ){
- int cid = sqlite3_column_int(pStmt2, 1);
- assert( cid>=0 && cid<nCol );
- aIndex[cid] = 1;
- }
- if( pStmt2 ){
- rc = sqlite3_finalize(pStmt2);
- }
- if( rc!=SQLITE_OK ){
- goto get_index_array_out;
- }
- }
-
-
-get_index_array_out:
- if( pStmt ){
- int rc2 = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
- if( rc!=SQLITE_OK ){
- sqlite3_free(aIndex);
- aIndex = 0;
- }
- *paIndex = aIndex;
- return rc;
-}
-
-/*
-** Global Tcl variable $echo_module is a list. This routine appends
-** the string element zArg to that list in interpreter interp.
-*/
-static void appendToEchoModule(Tcl_Interp *interp, const char *zArg){
- int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "echo_module", (zArg?zArg:""), flags);
-}
-
-/*
-** This function is called from within the echo-modules xCreate and
-** xConnect methods. The argc and argv arguments are copies of those
-** passed to the calling method. This function is responsible for
-** calling sqlite3_declare_vtab() to declare the schema of the virtual
-** table being created or connected.
-**
-** If the constructor was passed just one argument, i.e.:
-**
-** CREATE TABLE t1 AS echo(t2);
-**
-** Then t2 is assumed to be the name of a *real* database table. The
-** schema of the virtual table is declared by passing a copy of the
-** CREATE TABLE statement for the real table to sqlite3_declare_vtab().
-** Hence, the virtual table should have exactly the same column names and
-** types as the real table.
-*/
-static int echoDeclareVtab(
- echo_vtab *pVtab,
- sqlite3 *db
-){
- int rc = SQLITE_OK;
-
- if( pVtab->zTableName ){
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare(db,
- "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",
- -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_text(pStmt, 1, pVtab->zTableName, -1, 0);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- int rc2;
- const char *zCreateTable = (const char *)sqlite3_column_text(pStmt, 0);
- rc = sqlite3_declare_vtab(db, zCreateTable);
- rc2 = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- } else {
- rc = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ){
- rc = SQLITE_ERROR;
- }
- }
- if( rc==SQLITE_OK ){
- rc = getColumnNames(db, pVtab->zTableName, &pVtab->aCol, &pVtab->nCol);
- }
- if( rc==SQLITE_OK ){
- rc = getIndexArray(db, pVtab->zTableName, pVtab->nCol, &pVtab->aIndex);
- }
- }
- }
-
- return rc;
-}
-
-/*
-** This function frees all runtime structures associated with the virtual
-** table pVtab.
-*/
-static int echoDestructor(sqlite3_vtab *pVtab){
- echo_vtab *p = (echo_vtab*)pVtab;
- sqlite3_free(p->aIndex);
- sqlite3_free(p->aCol);
- sqlite3_free(p->zThis);
- sqlite3_free(p->zTableName);
- sqlite3_free(p->zLogName);
- sqlite3_free(p);
- return 0;
-}
-
-typedef struct EchoModule EchoModule;
-struct EchoModule {
- Tcl_Interp *interp;
-};
-
-/*
-** This function is called to do the work of the xConnect() method -
-** to allocate the required in-memory structures for a newly connected
-** virtual table.
-*/
-static int echoConstructor(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- int rc;
- int i;
- echo_vtab *pVtab;
-
- /* Allocate the sqlite3_vtab/echo_vtab structure itself */
- pVtab = sqlite3MallocZero( sizeof(*pVtab) );
- if( !pVtab ){
- return SQLITE_NOMEM;
- }
- pVtab->interp = ((EchoModule *)pAux)->interp;
- pVtab->db = db;
-
- /* Allocate echo_vtab.zThis */
- pVtab->zThis = sqlite3_mprintf("%s", argv[2]);
- if( !pVtab->zThis ){
- echoDestructor((sqlite3_vtab *)pVtab);
- return SQLITE_NOMEM;
- }
-
- /* Allocate echo_vtab.zTableName */
- if( argc>3 ){
- pVtab->zTableName = sqlite3_mprintf("%s", argv[3]);
- dequoteString(pVtab->zTableName);
- if( pVtab->zTableName && pVtab->zTableName[0]=='*' ){
- char *z = sqlite3_mprintf("%s%s", argv[2], &(pVtab->zTableName[1]));
- sqlite3_free(pVtab->zTableName);
- pVtab->zTableName = z;
- pVtab->isPattern = 1;
- }
- if( !pVtab->zTableName ){
- echoDestructor((sqlite3_vtab *)pVtab);
- return SQLITE_NOMEM;
- }
- }
-
- /* Log the arguments to this function to Tcl var ::echo_module */
- for(i=0; i<argc; i++){
- appendToEchoModule(pVtab->interp, argv[i]);
- }
-
- /* Invoke sqlite3_declare_vtab and set up other members of the echo_vtab
- ** structure. If an error occurs, delete the sqlite3_vtab structure and
- ** return an error code.
- */
- rc = echoDeclareVtab(pVtab, db);
- if( rc!=SQLITE_OK ){
- echoDestructor((sqlite3_vtab *)pVtab);
- return rc;
- }
-
- /* Success. Set *ppVtab and return */
- *ppVtab = &pVtab->base;
- return SQLITE_OK;
-}
-
-/*
-** Echo virtual table module xCreate method.
-*/
-static int echoCreate(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- int rc = SQLITE_OK;
- appendToEchoModule(((EchoModule *)pAux)->interp, "xCreate");
- rc = echoConstructor(db, pAux, argc, argv, ppVtab, pzErr);
-
- /* If there were two arguments passed to the module at the SQL level
- ** (i.e. "CREATE VIRTUAL TABLE tbl USING echo(arg1, arg2)"), then
- ** the second argument is used as a table name. Attempt to create
- ** such a table with a single column, "logmsg". This table will
- ** be used to log calls to the xUpdate method. It will be deleted
- ** when the virtual table is DROPed.
- **
- ** Note: The main point of this is to test that we can drop tables
- ** from within an xDestroy method call.
- */
- if( rc==SQLITE_OK && argc==5 ){
- char *zSql;
- echo_vtab *pVtab = *(echo_vtab **)ppVtab;
- pVtab->zLogName = sqlite3_mprintf("%s", argv[4]);
- zSql = sqlite3_mprintf("CREATE TABLE %Q(logmsg)", pVtab->zLogName);
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }
- }
-
- if( *ppVtab && rc!=SQLITE_OK ){
- echoDestructor(*ppVtab);
- *ppVtab = 0;
- }
-
- if( rc==SQLITE_OK ){
- (*(echo_vtab**)ppVtab)->inTransaction = 1;
- }
-
- return rc;
-}
-
-/*
-** Echo virtual table module xConnect method.
-*/
-static int echoConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- appendToEchoModule(((EchoModule *)pAux)->interp, "xConnect");
- return echoConstructor(db, pAux, argc, argv, ppVtab, pzErr);
-}
-
-/*
-** Echo virtual table module xDisconnect method.
-*/
-static int echoDisconnect(sqlite3_vtab *pVtab){
- appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDisconnect");
- return echoDestructor(pVtab);
-}
-
-/*
-** Echo virtual table module xDestroy method.
-*/
-static int echoDestroy(sqlite3_vtab *pVtab){
- int rc = SQLITE_OK;
- echo_vtab *p = (echo_vtab *)pVtab;
- appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDestroy");
-
- /* Drop the "log" table, if one exists (see echoCreate() for details) */
- if( p && p->zLogName ){
- char *zSql;
- zSql = sqlite3_mprintf("DROP TABLE %Q", p->zLogName);
- rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
-
- if( rc==SQLITE_OK ){
- rc = echoDestructor(pVtab);
- }
- return rc;
-}
-
-/*
-** Echo virtual table module xOpen method.
-*/
-static int echoOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- echo_cursor *pCur;
- if( simulateVtabError((echo_vtab *)pVTab, "xOpen") ){
- return SQLITE_ERROR;
- }
- pCur = sqlite3MallocZero(sizeof(echo_cursor));
- *ppCursor = (sqlite3_vtab_cursor *)pCur;
- return (pCur ? SQLITE_OK : SQLITE_NOMEM);
-}
-
-/*
-** Echo virtual table module xClose method.
-*/
-static int echoClose(sqlite3_vtab_cursor *cur){
- int rc;
- echo_cursor *pCur = (echo_cursor *)cur;
- sqlite3_stmt *pStmt = pCur->pStmt;
- pCur->pStmt = 0;
- sqlite3_free(pCur);
- rc = sqlite3_finalize(pStmt);
- return rc;
-}
-
-/*
-** Return non-zero if the cursor does not currently point to a valid record
-** (i.e if the scan has finished), or zero otherwise.
-*/
-static int echoEof(sqlite3_vtab_cursor *cur){
- return (((echo_cursor *)cur)->pStmt ? 0 : 1);
-}
-
-/*
-** Echo virtual table module xNext method.
-*/
-static int echoNext(sqlite3_vtab_cursor *cur){
- int rc = SQLITE_OK;
- echo_cursor *pCur = (echo_cursor *)cur;
-
- if( simulateVtabError((echo_vtab *)(cur->pVtab), "xNext") ){
- return SQLITE_ERROR;
- }
-
- if( pCur->pStmt ){
- rc = sqlite3_step(pCur->pStmt);
- if( rc==SQLITE_ROW ){
- rc = SQLITE_OK;
- }else{
- rc = sqlite3_finalize(pCur->pStmt);
- pCur->pStmt = 0;
- }
- }
-
- return rc;
-}
-
-/*
-** Echo virtual table module xColumn method.
-*/
-static int echoColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- int iCol = i + 1;
- sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt;
-
- if( simulateVtabError((echo_vtab *)(cur->pVtab), "xColumn") ){
- return SQLITE_ERROR;
- }
-
- if( !pStmt ){
- sqlite3_result_null(ctx);
- }else{
- assert( sqlite3_data_count(pStmt)>iCol );
- sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol));
- }
- return SQLITE_OK;
-}
-
-/*
-** Echo virtual table module xRowid method.
-*/
-static int echoRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt;
-
- if( simulateVtabError((echo_vtab *)(cur->pVtab), "xRowid") ){
- return SQLITE_ERROR;
- }
-
- *pRowid = sqlite3_column_int64(pStmt, 0);
- return SQLITE_OK;
-}
-
-/*
-** Compute a simple hash of the null terminated string zString.
-**
-** This module uses only sqlite3_index_info.idxStr, not
-** sqlite3_index_info.idxNum. So to test idxNum, when idxStr is set
-** in echoBestIndex(), idxNum is set to the corresponding hash value.
-** In echoFilter(), code assert()s that the supplied idxNum value is
-** indeed the hash of the supplied idxStr.
-*/
-static int hashString(const char *zString){
- u32 val = 0;
- int ii;
- for(ii=0; zString[ii]; ii++){
- val = (val << 3) + (int)zString[ii];
- }
- return (int)(val&0x7fffffff);
-}
-
-/*
-** Echo virtual table module xFilter method.
-*/
-static int echoFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- int rc;
- int i;
-
- echo_cursor *pCur = (echo_cursor *)pVtabCursor;
- echo_vtab *pVtab = (echo_vtab *)pVtabCursor->pVtab;
- sqlite3 *db = pVtab->db;
-
- if( simulateVtabError(pVtab, "xFilter") ){
- return SQLITE_ERROR;
- }
-
- /* Check that idxNum matches idxStr */
- assert( idxNum==hashString(idxStr) );
-
- /* Log arguments to the ::echo_module Tcl variable */
- appendToEchoModule(pVtab->interp, "xFilter");
- appendToEchoModule(pVtab->interp, idxStr);
- for(i=0; i<argc; i++){
- appendToEchoModule(pVtab->interp, (const char*)sqlite3_value_text(argv[i]));
- }
-
- sqlite3_finalize(pCur->pStmt);
- pCur->pStmt = 0;
-
- /* Prepare the SQL statement created by echoBestIndex and bind the
- ** runtime parameters passed to this function to it.
- */
- rc = sqlite3_prepare(db, idxStr, -1, &pCur->pStmt, 0);
- assert( pCur->pStmt || rc!=SQLITE_OK );
- for(i=0; rc==SQLITE_OK && i<argc; i++){
- rc = sqlite3_bind_value(pCur->pStmt, i+1, argv[i]);
- }
-
- /* If everything was successful, advance to the first row of the scan */
- if( rc==SQLITE_OK ){
- rc = echoNext(pVtabCursor);
- }
-
- return rc;
-}
-
-
-/*
-** A helper function used by echoUpdate() and echoBestIndex() for
-** manipulating strings in concert with the sqlite3_mprintf() function.
-**
-** Parameter pzStr points to a pointer to a string allocated with
-** sqlite3_mprintf. The second parameter, zAppend, points to another
-** string. The two strings are concatenated together and *pzStr
-** set to point at the result. The initial buffer pointed to by *pzStr
-** is deallocated via sqlite3_free().
-**
-** If the third argument, doFree, is true, then sqlite3_free() is
-** also called to free the buffer pointed to by zAppend.
-*/
-static void string_concat(char **pzStr, char *zAppend, int doFree, int *pRc){
- char *zIn = *pzStr;
- if( !zAppend && doFree && *pRc==SQLITE_OK ){
- *pRc = SQLITE_NOMEM;
- }
- if( *pRc!=SQLITE_OK ){
- sqlite3_free(zIn);
- zIn = 0;
- }else{
- if( zIn ){
- char *zTemp = zIn;
- zIn = sqlite3_mprintf("%s%s", zIn, zAppend);
- sqlite3_free(zTemp);
- }else{
- zIn = sqlite3_mprintf("%s", zAppend);
- }
- if( !zIn ){
- *pRc = SQLITE_NOMEM;
- }
- }
- *pzStr = zIn;
- if( doFree ){
- sqlite3_free(zAppend);
- }
-}
-
-/*
-** This function returns a pointer to an sqlite3_malloc()ed buffer
-** containing the select-list (the thing between keywords SELECT and FROM)
-** to query the underlying real table with for the scan described by
-** argument pIdxInfo.
-**
-** If the current SQLite version is earlier than 3.10.0, this is just "*"
-** (select all columns). Or, for version 3.10.0 and greater, the list of
-** columns identified by the pIdxInfo->colUsed mask.
-*/
-static char *echoSelectList(echo_vtab *pTab, sqlite3_index_info *pIdxInfo){
- char *zRet = 0;
- if( sqlite3_libversion_number()<3010000 ){
- zRet = sqlite3_mprintf(", *");
- }else{
- int i;
- for(i=0; i<pTab->nCol; i++){
- if( pIdxInfo->colUsed & ((sqlite3_uint64)1 << (i>=63 ? 63 : i)) ){
- zRet = sqlite3_mprintf("%z, %s", zRet, pTab->aCol[i]);
- }else{
- zRet = sqlite3_mprintf("%z, NULL", zRet);
- }
- if( !zRet ) break;
- }
- }
- return zRet;
-}
-
-/*
-** The echo module implements the subset of query constraints and sort
-** orders that may take advantage of SQLite indices on the underlying
-** real table. For example, if the real table is declared as:
-**
-** CREATE TABLE real(a, b, c);
-** CREATE INDEX real_index ON real(b);
-**
-** then the echo module handles WHERE or ORDER BY clauses that refer
-** to the column "b", but not "a" or "c". If a multi-column index is
-** present, only its left most column is considered.
-**
-** This xBestIndex method encodes the proposed search strategy as
-** an SQL query on the real table underlying the virtual echo module
-** table and stores the query in sqlite3_index_info.idxStr. The SQL
-** statement is of the form:
-**
-** SELECT rowid, * FROM <real-table> ?<where-clause>? ?<order-by-clause>?
-**
-** where the <where-clause> and <order-by-clause> are determined
-** by the contents of the structure pointed to by the pIdxInfo argument.
-*/
-static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int ii;
- char *zQuery = 0;
- char *zCol = 0;
- char *zNew;
- int nArg = 0;
- const char *zSep = "WHERE";
- echo_vtab *pVtab = (echo_vtab *)tab;
- sqlite3_stmt *pStmt = 0;
- Tcl_Interp *interp = pVtab->interp;
-
- int nRow = 0;
- int useIdx = 0;
- int rc = SQLITE_OK;
- int useCost = 0;
- double cost = 0;
- int isIgnoreUsable = 0;
- if( Tcl_GetVar(interp, "echo_module_ignore_usable", TCL_GLOBAL_ONLY) ){
- isIgnoreUsable = 1;
- }
-
- if( simulateVtabError(pVtab, "xBestIndex") ){
- return SQLITE_ERROR;
- }
-
- /* Determine the number of rows in the table and store this value in local
- ** variable nRow. The 'estimated-cost' of the scan will be the number of
- ** rows in the table for a linear scan, or the log (base 2) of the
- ** number of rows if the proposed scan uses an index.
- */
- if( Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY) ){
- cost = atof(Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY));
- useCost = 1;
- } else {
- zQuery = sqlite3_mprintf("SELECT count(*) FROM %Q", pVtab->zTableName);
- if( !zQuery ){
- return SQLITE_NOMEM;
- }
- rc = sqlite3_prepare(pVtab->db, zQuery, -1, &pStmt, 0);
- sqlite3_free(zQuery);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- sqlite3_step(pStmt);
- nRow = sqlite3_column_int(pStmt, 0);
- rc = sqlite3_finalize(pStmt);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
-
- zCol = echoSelectList(pVtab, pIdxInfo);
- if( !zCol ) return SQLITE_NOMEM;
- zQuery = sqlite3_mprintf("SELECT rowid%z FROM %Q", zCol, pVtab->zTableName);
- if( !zQuery ) return SQLITE_NOMEM;
-
- for(ii=0; ii<pIdxInfo->nConstraint; ii++){
- const struct sqlite3_index_constraint *pConstraint;
- struct sqlite3_index_constraint_usage *pUsage;
- int iCol;
-
- pConstraint = &pIdxInfo->aConstraint[ii];
- pUsage = &pIdxInfo->aConstraintUsage[ii];
-
- if( !isIgnoreUsable && !pConstraint->usable ) continue;
-
- iCol = pConstraint->iColumn;
- if( iCol<0 || pVtab->aIndex[iCol] ){
- char *zNewCol = iCol>=0 ? pVtab->aCol[iCol] : "rowid";
- char *zOp = 0;
- useIdx = 1;
- switch( pConstraint->op ){
- case SQLITE_INDEX_CONSTRAINT_EQ:
- zOp = "="; break;
- case SQLITE_INDEX_CONSTRAINT_LT:
- zOp = "<"; break;
- case SQLITE_INDEX_CONSTRAINT_GT:
- zOp = ">"; break;
- case SQLITE_INDEX_CONSTRAINT_LE:
- zOp = "<="; break;
- case SQLITE_INDEX_CONSTRAINT_GE:
- zOp = ">="; break;
- case SQLITE_INDEX_CONSTRAINT_MATCH:
- /* Purposely translate the MATCH operator into a LIKE, which
- ** will be used by the next block of code to construct a new
- ** query. It should also be noted here that the next block
- ** of code requires the first letter of this operator to be
- ** in upper-case to trigger the special MATCH handling (i.e.
- ** wrapping the bound parameter with literal '%'s).
- */
- zOp = "LIKE"; break;
- case SQLITE_INDEX_CONSTRAINT_LIKE:
- zOp = "like"; break;
- case SQLITE_INDEX_CONSTRAINT_GLOB:
- zOp = "glob"; break;
- case SQLITE_INDEX_CONSTRAINT_REGEXP:
- zOp = "regexp"; break;
- }
- if( zOp ){
- if( zOp[0]=='L' ){
- zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')",
- zSep, zNewCol);
- } else {
- zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zNewCol, zOp);
- }
- string_concat(&zQuery, zNew, 1, &rc);
- zSep = "AND";
- pUsage->argvIndex = ++nArg;
- pUsage->omit = 1;
- }
- }
- }
-
- /* If there is only one term in the ORDER BY clause, and it is
- ** on a column that this virtual table has an index for, then consume
- ** the ORDER BY clause.
- */
- if( pIdxInfo->nOrderBy==1 && (
- pIdxInfo->aOrderBy->iColumn<0 ||
- pVtab->aIndex[pIdxInfo->aOrderBy->iColumn]) ){
- int iCol = pIdxInfo->aOrderBy->iColumn;
- char *zNewCol = iCol>=0 ? pVtab->aCol[iCol] : "rowid";
- char *zDir = pIdxInfo->aOrderBy->desc?"DESC":"ASC";
- zNew = sqlite3_mprintf(" ORDER BY %s %s", zNewCol, zDir);
- string_concat(&zQuery, zNew, 1, &rc);
- pIdxInfo->orderByConsumed = 1;
- }
-
- appendToEchoModule(pVtab->interp, "xBestIndex");;
- appendToEchoModule(pVtab->interp, zQuery);
-
- if( !zQuery ){
- return rc;
- }
- pIdxInfo->idxNum = hashString(zQuery);
- pIdxInfo->idxStr = zQuery;
- pIdxInfo->needToFreeIdxStr = 1;
- if( useCost ){
- pIdxInfo->estimatedCost = cost;
- }else if( useIdx ){
- /* Approximation of log2(nRow). */
- for( ii=0; ii<(sizeof(int)*8)-1; ii++ ){
- if( nRow & (1<<ii) ){
- pIdxInfo->estimatedCost = (double)ii;
- }
- }
- }else{
- pIdxInfo->estimatedCost = (double)nRow;
- }
- return rc;
-}
-
-/*
-** The xUpdate method for echo module virtual tables.
-**
-** apData[0] apData[1] apData[2..]
-**
-** INTEGER DELETE
-**
-** INTEGER NULL (nCol args) UPDATE (do not set rowid)
-** INTEGER INTEGER (nCol args) UPDATE (with SET rowid = <arg1>)
-**
-** NULL NULL (nCol args) INSERT INTO (automatic rowid value)
-** NULL INTEGER (nCol args) INSERT (incl. rowid value)
-**
-*/
-int echoUpdate(
- sqlite3_vtab *tab,
- int nData,
- sqlite3_value **apData,
- sqlite_int64 *pRowid
-){
- echo_vtab *pVtab = (echo_vtab *)tab;
- sqlite3 *db = pVtab->db;
- int rc = SQLITE_OK;
-
- sqlite3_stmt *pStmt = 0;
- char *z = 0; /* SQL statement to execute */
- int bindArgZero = 0; /* True to bind apData[0] to sql var no. nData */
- int bindArgOne = 0; /* True to bind apData[1] to sql var no. 1 */
- int i; /* Counter variable used by for loops */
-
- assert( nData==pVtab->nCol+2 || nData==1 );
-
- /* Ticket #3083 - make sure we always start a transaction prior to
- ** making any changes to a virtual table */
- assert( pVtab->inTransaction );
-
- if( simulateVtabError(pVtab, "xUpdate") ){
- return SQLITE_ERROR;
- }
-
- /* If apData[0] is an integer and nData>1 then do an UPDATE */
- if( nData>1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){
- char *zSep = " SET";
- z = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName);
- if( !z ){
- rc = SQLITE_NOMEM;
- }
-
- bindArgOne = (apData[1] && sqlite3_value_type(apData[1])==SQLITE_INTEGER);
- bindArgZero = 1;
-
- if( bindArgOne ){
- string_concat(&z, " SET rowid=?1 ", 0, &rc);
- zSep = ",";
- }
- for(i=2; i<nData; i++){
- if( apData[i]==0 ) continue;
- string_concat(&z, sqlite3_mprintf(
- "%s %Q=?%d", zSep, pVtab->aCol[i-2], i), 1, &rc);
- zSep = ",";
- }
- string_concat(&z, sqlite3_mprintf(" WHERE rowid=?%d", nData), 1, &rc);
- }
-
- /* If apData[0] is an integer and nData==1 then do a DELETE */
- else if( nData==1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){
- z = sqlite3_mprintf("DELETE FROM %Q WHERE rowid = ?1", pVtab->zTableName);
- if( !z ){
- rc = SQLITE_NOMEM;
- }
- bindArgZero = 1;
- }
-
- /* If the first argument is NULL and there are more than two args, INSERT */
- else if( nData>2 && sqlite3_value_type(apData[0])==SQLITE_NULL ){
- int ii;
- char *zInsert = 0;
- char *zValues = 0;
-
- zInsert = sqlite3_mprintf("INSERT INTO %Q (", pVtab->zTableName);
- if( !zInsert ){
- rc = SQLITE_NOMEM;
- }
- if( sqlite3_value_type(apData[1])==SQLITE_INTEGER ){
- bindArgOne = 1;
- zValues = sqlite3_mprintf("?");
- string_concat(&zInsert, "rowid", 0, &rc);
- }
-
- assert((pVtab->nCol+2)==nData);
- for(ii=2; ii<nData; ii++){
- string_concat(&zInsert,
- sqlite3_mprintf("%s%Q", zValues?", ":"", pVtab->aCol[ii-2]), 1, &rc);
- string_concat(&zValues,
- sqlite3_mprintf("%s?%d", zValues?", ":"", ii), 1, &rc);
- }
-
- string_concat(&z, zInsert, 1, &rc);
- string_concat(&z, ") VALUES(", 0, &rc);
- string_concat(&z, zValues, 1, &rc);
- string_concat(&z, ")", 0, &rc);
- }
-
- /* Anything else is an error */
- else{
- assert(0);
- return SQLITE_ERROR;
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare(db, z, -1, &pStmt, 0);
- }
- assert( rc!=SQLITE_OK || pStmt );
- sqlite3_free(z);
- if( rc==SQLITE_OK ) {
- if( bindArgZero ){
- sqlite3_bind_value(pStmt, nData, apData[0]);
- }
- if( bindArgOne ){
- sqlite3_bind_value(pStmt, 1, apData[1]);
- }
- for(i=2; i<nData && rc==SQLITE_OK; i++){
- if( apData[i] ) rc = sqlite3_bind_value(pStmt, i, apData[i]);
- }
- if( rc==SQLITE_OK ){
- sqlite3_step(pStmt);
- rc = sqlite3_finalize(pStmt);
- }else{
- sqlite3_finalize(pStmt);
- }
- }
-
- if( pRowid && rc==SQLITE_OK ){
- *pRowid = sqlite3_last_insert_rowid(db);
- }
- if( rc!=SQLITE_OK ){
- tab->zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", sqlite3_errmsg(db));
- }
-
- return rc;
-}
-
-/*
-** xBegin, xSync, xCommit and xRollback callbacks for echo module
-** virtual tables. Do nothing other than add the name of the callback
-** to the $::echo_module Tcl variable.
-*/
-static int echoTransactionCall(sqlite3_vtab *tab, const char *zCall){
- char *z;
- echo_vtab *pVtab = (echo_vtab *)tab;
- z = sqlite3_mprintf("echo(%s)", pVtab->zTableName);
- if( z==0 ) return SQLITE_NOMEM;
- appendToEchoModule(pVtab->interp, zCall);
- appendToEchoModule(pVtab->interp, z);
- sqlite3_free(z);
- return SQLITE_OK;
-}
-static int echoBegin(sqlite3_vtab *tab){
- int rc;
- echo_vtab *pVtab = (echo_vtab *)tab;
- Tcl_Interp *interp = pVtab->interp;
- const char *zVal;
-
- /* Ticket #3083 - do not start a transaction if we are already in
- ** a transaction */
- assert( !pVtab->inTransaction );
-
- if( simulateVtabError(pVtab, "xBegin") ){
- return SQLITE_ERROR;
- }
-
- rc = echoTransactionCall(tab, "xBegin");
-
- if( rc==SQLITE_OK ){
- /* Check if the $::echo_module_begin_fail variable is defined. If it is,
- ** and it is set to the name of the real table underlying this virtual
- ** echo module table, then cause this xSync operation to fail.
- */
- zVal = Tcl_GetVar(interp, "echo_module_begin_fail", TCL_GLOBAL_ONLY);
- if( zVal && 0==strcmp(zVal, pVtab->zTableName) ){
- rc = SQLITE_ERROR;
- }
- }
- if( rc==SQLITE_OK ){
- pVtab->inTransaction = 1;
- }
- return rc;
-}
-static int echoSync(sqlite3_vtab *tab){
- int rc;
- echo_vtab *pVtab = (echo_vtab *)tab;
- Tcl_Interp *interp = pVtab->interp;
- const char *zVal;
-
- /* Ticket #3083 - Only call xSync if we have previously started a
- ** transaction */
- assert( pVtab->inTransaction );
-
- if( simulateVtabError(pVtab, "xSync") ){
- return SQLITE_ERROR;
- }
-
- rc = echoTransactionCall(tab, "xSync");
-
- if( rc==SQLITE_OK ){
- /* Check if the $::echo_module_sync_fail variable is defined. If it is,
- ** and it is set to the name of the real table underlying this virtual
- ** echo module table, then cause this xSync operation to fail.
- */
- zVal = Tcl_GetVar(interp, "echo_module_sync_fail", TCL_GLOBAL_ONLY);
- if( zVal && 0==strcmp(zVal, pVtab->zTableName) ){
- rc = -1;
- }
- }
- return rc;
-}
-static int echoCommit(sqlite3_vtab *tab){
- echo_vtab *pVtab = (echo_vtab*)tab;
- int rc;
-
- /* Ticket #3083 - Only call xCommit if we have previously started
- ** a transaction */
- assert( pVtab->inTransaction );
-
- if( simulateVtabError(pVtab, "xCommit") ){
- return SQLITE_ERROR;
- }
-
- sqlite3BeginBenignMalloc();
- rc = echoTransactionCall(tab, "xCommit");
- sqlite3EndBenignMalloc();
- pVtab->inTransaction = 0;
- return rc;
-}
-static int echoRollback(sqlite3_vtab *tab){
- int rc;
- echo_vtab *pVtab = (echo_vtab*)tab;
-
- /* Ticket #3083 - Only call xRollback if we have previously started
- ** a transaction */
- assert( pVtab->inTransaction );
-
- rc = echoTransactionCall(tab, "xRollback");
- pVtab->inTransaction = 0;
- return rc;
-}
-
-/*
-** Implementation of "GLOB" function on the echo module. Pass
-** all arguments to the ::echo_glob_overload procedure of TCL
-** and return the result of that procedure as a string.
-*/
-static void overloadedGlobFunction(
- sqlite3_context *pContext,
- int nArg,
- sqlite3_value **apArg
-){
- Tcl_Interp *interp = sqlite3_user_data(pContext);
- Tcl_DString str;
- int i;
- int rc;
- Tcl_DStringInit(&str);
- Tcl_DStringAppendElement(&str, "::echo_glob_overload");
- for(i=0; i<nArg; i++){
- Tcl_DStringAppendElement(&str, (char*)sqlite3_value_text(apArg[i]));
- }
- rc = Tcl_Eval(interp, Tcl_DStringValue(&str));
- Tcl_DStringFree(&str);
- if( rc ){
- sqlite3_result_error(pContext, Tcl_GetStringResult(interp), -1);
- }else{
- sqlite3_result_text(pContext, Tcl_GetStringResult(interp),
- -1, SQLITE_TRANSIENT);
- }
- Tcl_ResetResult(interp);
-}
-
-/*
-** This is the xFindFunction implementation for the echo module.
-** SQLite calls this routine when the first argument of a function
-** is a column of an echo virtual table. This routine can optionally
-** override the implementation of that function. It will choose to
-** do so if the function is named "glob", and a TCL command named
-** ::echo_glob_overload exists.
-*/
-static int echoFindFunction(
- sqlite3_vtab *vtab,
- int nArg,
- const char *zFuncName,
- void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
- void **ppArg
-){
- echo_vtab *pVtab = (echo_vtab *)vtab;
- Tcl_Interp *interp = pVtab->interp;
- Tcl_CmdInfo info;
- if( strcmp(zFuncName,"glob")!=0 ){
- return 0;
- }
- if( Tcl_GetCommandInfo(interp, "::echo_glob_overload", &info)==0 ){
- return 0;
- }
- *pxFunc = overloadedGlobFunction;
- *ppArg = interp;
- return 1;
-}
-
-static int echoRename(sqlite3_vtab *vtab, const char *zNewName){
- int rc = SQLITE_OK;
- echo_vtab *p = (echo_vtab *)vtab;
-
- if( simulateVtabError(p, "xRename") ){
- return SQLITE_ERROR;
- }
-
- if( p->isPattern ){
- int nThis = (int)strlen(p->zThis);
- char *zSql = sqlite3_mprintf("ALTER TABLE %s RENAME TO %s%s",
- p->zTableName, zNewName, &p->zTableName[nThis]
- );
- rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
-
- return rc;
-}
-
-static int echoSavepoint(sqlite3_vtab *pVTab, int iSavepoint){
- assert( pVTab );
- return SQLITE_OK;
-}
-
-static int echoRelease(sqlite3_vtab *pVTab, int iSavepoint){
- assert( pVTab );
- return SQLITE_OK;
-}
-
-static int echoRollbackTo(sqlite3_vtab *pVTab, int iSavepoint){
- assert( pVTab );
- return SQLITE_OK;
-}
-
-/*
-** A virtual table module that merely "echos" the contents of another
-** table (like an SQL VIEW).
-*/
-static sqlite3_module echoModule = {
- 1, /* iVersion */
- echoCreate,
- echoConnect,
- echoBestIndex,
- echoDisconnect,
- echoDestroy,
- echoOpen, /* xOpen - open a cursor */
- echoClose, /* xClose - close a cursor */
- echoFilter, /* xFilter - configure scan constraints */
- echoNext, /* xNext - advance a cursor */
- echoEof, /* xEof */
- echoColumn, /* xColumn - read data */
- echoRowid, /* xRowid - read data */
- echoUpdate, /* xUpdate - write data */
- echoBegin, /* xBegin - begin transaction */
- echoSync, /* xSync - sync transaction */
- echoCommit, /* xCommit - commit transaction */
- echoRollback, /* xRollback - rollback transaction */
- echoFindFunction, /* xFindFunction - function overloading */
- echoRename /* xRename - rename the table */
-};
-
-static sqlite3_module echoModuleV2 = {
- 2, /* iVersion */
- echoCreate,
- echoConnect,
- echoBestIndex,
- echoDisconnect,
- echoDestroy,
- echoOpen, /* xOpen - open a cursor */
- echoClose, /* xClose - close a cursor */
- echoFilter, /* xFilter - configure scan constraints */
- echoNext, /* xNext - advance a cursor */
- echoEof, /* xEof */
- echoColumn, /* xColumn - read data */
- echoRowid, /* xRowid - read data */
- echoUpdate, /* xUpdate - write data */
- echoBegin, /* xBegin - begin transaction */
- echoSync, /* xSync - sync transaction */
- echoCommit, /* xCommit - commit transaction */
- echoRollback, /* xRollback - rollback transaction */
- echoFindFunction, /* xFindFunction - function overloading */
- echoRename, /* xRename - rename the table */
- echoSavepoint,
- echoRelease,
- echoRollbackTo
-};
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
-extern const char *sqlite3ErrName(int);
-
-static void moduleDestroy(void *p){
- sqlite3_free(p);
-}
-
-/*
-** Register the echo virtual table module.
-*/
-static int SQLITE_TCLAPI register_echo_module(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int rc;
- sqlite3 *db;
- EchoModule *pMod;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-
- /* Virtual table module "echo" */
- pMod = sqlite3_malloc(sizeof(EchoModule));
- pMod->interp = interp;
- rc = sqlite3_create_module_v2(
- db, "echo", &echoModule, (void*)pMod, moduleDestroy
- );
-
- /* Virtual table module "echo_v2" */
- if( rc==SQLITE_OK ){
- pMod = sqlite3_malloc(sizeof(EchoModule));
- pMod->interp = interp;
- rc = sqlite3_create_module_v2(db, "echo_v2",
- &echoModuleV2, (void*)pMod, moduleDestroy
- );
- }
-
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
- return TCL_OK;
-}
-
-/*
-** Tcl interface to sqlite3_declare_vtab, invoked as follows from Tcl:
-**
-** sqlite3_declare_vtab DB SQL
-*/
-static int SQLITE_TCLAPI declare_vtab(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- int rc;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB SQL");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_declare_vtab(db, Tcl_GetString(objv[2]));
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest8_Init(Tcl_Interp *interp){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- void *clientData;
- } aObjCmd[] = {
- { "register_echo_module", register_echo_module, 0 },
- { "sqlite3_declare_vtab", declare_vtab, 0 },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
- aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
- }
-#endif
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test9.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test9.c
deleted file mode 100644
index 5b139e8a56f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test9.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
-** 2007 March 29
-**
-** 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 contains obscure tests of the C-interface required
-** for completeness. Test code is written in C for these cases
-** as there is not much point in binding to Tcl.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-/*
-** c_collation_test
-*/
-static int SQLITE_TCLAPI c_collation_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- const char *zErrFunction = "N/A";
- sqlite3 *db;
-
- int rc;
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- /* Open a database. */
- rc = sqlite3_open(":memory:", &db);
- if( rc!=SQLITE_OK ){
- zErrFunction = "sqlite3_open";
- goto error_out;
- }
-
- rc = sqlite3_create_collation(db, "collate", 456, 0, 0);
- if( rc!=SQLITE_MISUSE ){
- sqlite3_close(db);
- zErrFunction = "sqlite3_create_collation";
- goto error_out;
- }
-
- sqlite3_close(db);
- return TCL_OK;
-
-error_out:
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
- return TCL_ERROR;
-}
-
-/*
-** c_realloc_test
-*/
-static int SQLITE_TCLAPI c_realloc_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- void *p;
- const char *zErrFunction = "N/A";
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- p = sqlite3_malloc(5);
- if( !p ){
- zErrFunction = "sqlite3_malloc";
- goto error_out;
- }
-
- /* Test that realloc()ing a block of memory to a negative size is
- ** the same as free()ing that memory.
- */
- p = sqlite3_realloc(p, -1);
- if( p ){
- zErrFunction = "sqlite3_realloc";
- goto error_out;
- }
-
- return TCL_OK;
-
-error_out:
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
- return TCL_ERROR;
-}
-
-
-/*
-** c_misuse_test
-*/
-static int SQLITE_TCLAPI c_misuse_test(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- const char *zErrFunction = "N/A";
- sqlite3 *db = 0;
- sqlite3_stmt *pStmt;
- int rc;
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- /* Open a database. Then close it again. We need to do this so that
- ** we have a "closed database handle" to pass to various API functions.
- */
- rc = sqlite3_open(":memory:", &db);
- if( rc!=SQLITE_OK ){
- zErrFunction = "sqlite3_open";
- goto error_out;
- }
- sqlite3_close(db);
-
-
- rc = sqlite3_errcode(db);
- if( rc!=SQLITE_MISUSE ){
- zErrFunction = "sqlite3_errcode";
- goto error_out;
- }
-
- pStmt = (sqlite3_stmt*)1234;
- rc = sqlite3_prepare(db, 0, 0, &pStmt, 0);
- if( rc!=SQLITE_MISUSE ){
- zErrFunction = "sqlite3_prepare";
- goto error_out;
- }
- assert( pStmt==0 ); /* Verify that pStmt is zeroed even on a MISUSE error */
-
- pStmt = (sqlite3_stmt*)1234;
- rc = sqlite3_prepare_v2(db, 0, 0, &pStmt, 0);
- if( rc!=SQLITE_MISUSE ){
- zErrFunction = "sqlite3_prepare_v2";
- goto error_out;
- }
- assert( pStmt==0 );
-
-#ifndef SQLITE_OMIT_UTF16
- pStmt = (sqlite3_stmt*)1234;
- rc = sqlite3_prepare16(db, 0, 0, &pStmt, 0);
- if( rc!=SQLITE_MISUSE ){
- zErrFunction = "sqlite3_prepare16";
- goto error_out;
- }
- assert( pStmt==0 );
- pStmt = (sqlite3_stmt*)1234;
- rc = sqlite3_prepare16_v2(db, 0, 0, &pStmt, 0);
- if( rc!=SQLITE_MISUSE ){
- zErrFunction = "sqlite3_prepare16_v2";
- goto error_out;
- }
- assert( pStmt==0 );
-#endif
-
- return TCL_OK;
-
-error_out:
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
- return TCL_ERROR;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest9_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- void *clientData;
- } aObjCmd[] = {
- { "c_misuse_test", c_misuse_test, 0 },
- { "c_realloc_test", c_realloc_test, 0 },
- { "c_collation_test", c_collation_test, 0 },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
- aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
- }
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_async.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_async.c
deleted file mode 100644
index c32c74c6608..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_async.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
-** 2005 December 14
-**
-** 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 contains a binding of the asynchronous IO extension interface
-** (defined in ext/async/sqlite3async.h) to Tcl.
-*/
-
-#define TCL_THREADS
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-#ifdef SQLITE_ENABLE_ASYNCIO
-
-#include "sqlite3async.h"
-#include "sqlite3.h"
-#include <assert.h>
-
-/* From main.c */
-extern const char *sqlite3ErrName(int);
-
-
-struct TestAsyncGlobal {
- int isInstalled; /* True when async VFS is installed */
-} testasync_g = { 0 };
-
-TCL_DECLARE_MUTEX(testasync_g_writerMutex);
-
-/*
-** sqlite3async_initialize PARENT-VFS ISDEFAULT
-*/
-static int SQLITE_TCLAPI testAsyncInit(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zParent;
- int isDefault;
- int rc;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PARENT-VFS ISDEFAULT");
- return TCL_ERROR;
- }
- zParent = Tcl_GetString(objv[1]);
- if( !*zParent ) {
- zParent = 0;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[2], &isDefault) ){
- return TCL_ERROR;
- }
-
- rc = sqlite3async_initialize(zParent, isDefault);
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
-** sqlite3async_shutdown
-*/
-static int SQLITE_TCLAPI testAsyncShutdown(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3async_shutdown();
- return TCL_OK;
-}
-
-static Tcl_ThreadCreateType tclWriterThread(ClientData pIsStarted){
- Tcl_MutexLock(&testasync_g_writerMutex);
- *((int *)pIsStarted) = 1;
- sqlite3async_run();
- Tcl_MutexUnlock(&testasync_g_writerMutex);
- Tcl_ExitThread(0);
- TCL_THREAD_CREATE_RETURN;
-}
-
-/*
-** sqlite3async_start
-**
-** Start a new writer thread.
-*/
-static int SQLITE_TCLAPI testAsyncStart(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- volatile int isStarted = 0;
- ClientData threadData = (ClientData)&isStarted;
-
- Tcl_ThreadId x;
- const int nStack = TCL_THREAD_STACK_DEFAULT;
- const int flags = TCL_THREAD_NOFLAGS;
- int rc;
-
- rc = Tcl_CreateThread(&x, tclWriterThread, threadData, nStack, flags);
- if( rc!=TCL_OK ){
- Tcl_AppendResult(interp, "Tcl_CreateThread() failed", 0);
- return TCL_ERROR;
- }
-
- while( isStarted==0 ) { /* Busy loop */ }
- return TCL_OK;
-}
-
-/*
-** sqlite3async_wait
-**
-** Wait for the current writer thread to terminate.
-**
-** If the current writer thread is set to run forever then this
-** command would block forever. To prevent that, an error is returned.
-*/
-static int SQLITE_TCLAPI testAsyncWait(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int eCond;
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- sqlite3async_control(SQLITEASYNC_GET_HALT, &eCond);
- if( eCond==SQLITEASYNC_HALT_NEVER ){
- Tcl_AppendResult(interp, "would block forever", (char*)0);
- return TCL_ERROR;
- }
-
- Tcl_MutexLock(&testasync_g_writerMutex);
- Tcl_MutexUnlock(&testasync_g_writerMutex);
- return TCL_OK;
-}
-
-/*
-** sqlite3async_control OPTION ?VALUE?
-*/
-static int SQLITE_TCLAPI testAsyncControl(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = SQLITE_OK;
- int aeOpt[] = { SQLITEASYNC_HALT, SQLITEASYNC_DELAY, SQLITEASYNC_LOCKFILES };
- const char *azOpt[] = { "halt", "delay", "lockfiles", 0 };
- const char *az[] = { "never", "now", "idle", 0 };
- int iVal;
- int eOpt;
-
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "OPTION ?VALUE?");
- return TCL_ERROR;
- }
- if( Tcl_GetIndexFromObj(interp, objv[1], azOpt, "option", 0, &eOpt) ){
- return TCL_ERROR;
- }
- eOpt = aeOpt[eOpt];
-
- if( objc==3 ){
- switch( eOpt ){
- case SQLITEASYNC_HALT: {
- assert( SQLITEASYNC_HALT_NEVER==0 );
- assert( SQLITEASYNC_HALT_NOW==1 );
- assert( SQLITEASYNC_HALT_IDLE==2 );
- if( Tcl_GetIndexFromObj(interp, objv[2], az, "value", 0, &iVal) ){
- return TCL_ERROR;
- }
- break;
- }
- case SQLITEASYNC_DELAY:
- if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ){
- return TCL_ERROR;
- }
- break;
-
- case SQLITEASYNC_LOCKFILES:
- if( Tcl_GetBooleanFromObj(interp, objv[2], &iVal) ){
- return TCL_ERROR;
- }
- break;
- }
-
- rc = sqlite3async_control(eOpt, iVal);
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3async_control(
- eOpt==SQLITEASYNC_HALT ? SQLITEASYNC_GET_HALT :
- eOpt==SQLITEASYNC_DELAY ? SQLITEASYNC_GET_DELAY :
- SQLITEASYNC_GET_LOCKFILES, &iVal);
- }
-
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }
-
- if( eOpt==SQLITEASYNC_HALT ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(az[iVal], -1));
- }else{
- Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
- }
-
- return TCL_OK;
-}
-
-#endif /* SQLITE_ENABLE_ASYNCIO */
-
-/*
-** This routine registers the custom TCL commands defined in this
-** module. This should be the only procedure visible from outside
-** of this module.
-*/
-int Sqlitetestasync_Init(Tcl_Interp *interp){
-#ifdef SQLITE_ENABLE_ASYNCIO
- Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0);
- Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0);
-
- Tcl_CreateObjCommand(interp,"sqlite3async_control",testAsyncControl,0,0);
- Tcl_CreateObjCommand(interp,"sqlite3async_initialize",testAsyncInit,0,0);
- Tcl_CreateObjCommand(interp,"sqlite3async_shutdown",testAsyncShutdown,0,0);
-#endif /* SQLITE_ENABLE_ASYNCIO */
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_autoext.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_autoext.c
deleted file mode 100644
index e23e41a08a8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_autoext.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
-** 2006 August 23
-**
-** 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.
-**
-*************************************************************************
-** Test extension for testing the sqlite3_auto_extension() function.
-*/
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-#include "sqlite3ext.h"
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-SQLITE_EXTENSION_INIT1
-
-/*
-** The sqr() SQL function returns the square of its input value.
-*/
-static void sqrFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- double r = sqlite3_value_double(argv[0]);
- sqlite3_result_double(context, r*r);
-}
-
-/*
-** This is the entry point to register the extension for the sqr() function.
-*/
-static int sqr_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- sqlite3_create_function(db, "sqr", 1, SQLITE_ANY, 0, sqrFunc, 0, 0);
- return 0;
-}
-
-/*
-** The cube() SQL function returns the cube of its input value.
-*/
-static void cubeFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- double r = sqlite3_value_double(argv[0]);
- sqlite3_result_double(context, r*r*r);
-}
-
-/*
-** This is the entry point to register the extension for the cube() function.
-*/
-static int cube_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- sqlite3_create_function(db, "cube", 1, SQLITE_ANY, 0, cubeFunc, 0, 0);
- return 0;
-}
-
-/*
-** This is a broken extension entry point
-*/
-static int broken_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- char *zErr;
- SQLITE_EXTENSION_INIT2(pApi);
- zErr = sqlite3_mprintf("broken autoext!");
- *pzErrMsg = zErr;
- return 1;
-}
-
-/*
-** tclcmd: sqlite3_auto_extension_sqr
-**
-** Register the "sqr" extension to be loaded automatically.
-*/
-static int SQLITE_TCLAPI autoExtSqrObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = sqlite3_auto_extension((void(*)(void))sqr_init);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return SQLITE_OK;
-}
-
-/*
-** tclcmd: sqlite3_cancel_auto_extension_sqr
-**
-** Unregister the "sqr" extension.
-*/
-static int SQLITE_TCLAPI cancelAutoExtSqrObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = sqlite3_cancel_auto_extension((void(*)(void))sqr_init);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return SQLITE_OK;
-}
-
-/*
-** tclcmd: sqlite3_auto_extension_cube
-**
-** Register the "cube" extension to be loaded automatically.
-*/
-static int SQLITE_TCLAPI autoExtCubeObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = sqlite3_auto_extension((void(*)(void))cube_init);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return SQLITE_OK;
-}
-
-/*
-** tclcmd: sqlite3_cancel_auto_extension_cube
-**
-** Unregister the "cube" extension.
-*/
-static int SQLITE_TCLAPI cancelAutoExtCubeObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = sqlite3_cancel_auto_extension((void(*)(void))cube_init);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return SQLITE_OK;
-}
-
-/*
-** tclcmd: sqlite3_auto_extension_broken
-**
-** Register the broken extension to be loaded automatically.
-*/
-static int SQLITE_TCLAPI autoExtBrokenObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = sqlite3_auto_extension((void(*)(void))broken_init);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return SQLITE_OK;
-}
-
-/*
-** tclcmd: sqlite3_cancel_auto_extension_broken
-**
-** Unregister the broken extension.
-*/
-static int SQLITE_TCLAPI cancelAutoExtBrokenObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = sqlite3_cancel_auto_extension((void(*)(void))broken_init);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return SQLITE_OK;
-}
-
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-
-
-/*
-** tclcmd: sqlite3_reset_auto_extension
-**
-** Reset all auto-extensions
-*/
-static int SQLITE_TCLAPI resetAutoExtObjCmd(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_reset_auto_extension();
- return SQLITE_OK;
-}
-
-
-/*
-** This procedure registers the TCL procs defined in this file.
-*/
-int Sqlitetest_autoext_Init(Tcl_Interp *interp){
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_sqr",
- autoExtSqrObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_cube",
- autoExtCubeObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_broken",
- autoExtBrokenObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_sqr",
- cancelAutoExtSqrObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_cube",
- cancelAutoExtCubeObjCmd, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_broken",
- cancelAutoExtBrokenObjCmd, 0, 0);
-#endif
- Tcl_CreateObjCommand(interp, "sqlite3_reset_auto_extension",
- resetAutoExtObjCmd, 0, 0);
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_backup.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_backup.c
deleted file mode 100644
index 9b684a28f6b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_backup.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-** 2009 January 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 contains test logic for the sqlite3_backup() interface.
-**
-*/
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-#include "sqlite3.h"
-#include <assert.h>
-
-/* These functions are implemented in main.c. */
-extern const char *sqlite3ErrName(int);
-
-/* These functions are implemented in test1.c. */
-extern int getDbPointer(Tcl_Interp *, const char *, sqlite3 **);
-
-static int SQLITE_TCLAPI backupTestCmd(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const*objv
-){
- enum BackupSubCommandEnum {
- BACKUP_STEP, BACKUP_FINISH, BACKUP_REMAINING, BACKUP_PAGECOUNT
- };
- struct BackupSubCommand {
- const char *zCmd;
- enum BackupSubCommandEnum eCmd;
- int nArg;
- const char *zArg;
- } aSub[] = {
- {"step", BACKUP_STEP , 1, "npage" },
- {"finish", BACKUP_FINISH , 0, "" },
- {"remaining", BACKUP_REMAINING , 0, "" },
- {"pagecount", BACKUP_PAGECOUNT , 0, "" },
- {0, 0, 0, 0}
- };
-
- sqlite3_backup *p = (sqlite3_backup *)clientData;
- int iCmd;
- int rc;
-
- rc = Tcl_GetIndexFromObjStruct(
- interp, objv[1], aSub, sizeof(aSub[0]), "option", 0, &iCmd
- );
- if( rc!=TCL_OK ){
- return rc;
- }
- if( objc!=(2 + aSub[iCmd].nArg) ){
- Tcl_WrongNumArgs(interp, 2, objv, aSub[iCmd].zArg);
- return TCL_ERROR;
- }
-
- switch( aSub[iCmd].eCmd ){
-
- case BACKUP_FINISH: {
- const char *zCmdName;
- Tcl_CmdInfo cmdInfo;
- zCmdName = Tcl_GetString(objv[0]);
- Tcl_GetCommandInfo(interp, zCmdName, &cmdInfo);
- cmdInfo.deleteProc = 0;
- Tcl_SetCommandInfo(interp, zCmdName, &cmdInfo);
- Tcl_DeleteCommand(interp, zCmdName);
-
- rc = sqlite3_backup_finish(p);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
- break;
- }
-
- case BACKUP_STEP: {
- int nPage;
- if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &nPage) ){
- return TCL_ERROR;
- }
- rc = sqlite3_backup_step(p, nPage);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
- break;
- }
-
- case BACKUP_REMAINING:
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_backup_remaining(p)));
- break;
-
- case BACKUP_PAGECOUNT:
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_backup_pagecount(p)));
- break;
- }
-
- return TCL_OK;
-}
-
-static void SQLITE_TCLAPI backupTestFinish(ClientData clientData){
- sqlite3_backup *pBackup = (sqlite3_backup *)clientData;
- sqlite3_backup_finish(pBackup);
-}
-
-/*
-** sqlite3_backup CMDNAME DESTHANDLE DESTNAME SRCHANDLE SRCNAME
-**
-*/
-static int SQLITE_TCLAPI backupTestInit(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const*objv
-){
- sqlite3_backup *pBackup;
- sqlite3 *pDestDb;
- sqlite3 *pSrcDb;
- const char *zDestName;
- const char *zSrcName;
- const char *zCmd;
-
- if( objc!=6 ){
- Tcl_WrongNumArgs(
- interp, 1, objv, "CMDNAME DESTHANDLE DESTNAME SRCHANDLE SRCNAME"
- );
- return TCL_ERROR;
- }
-
- zCmd = Tcl_GetString(objv[1]);
- getDbPointer(interp, Tcl_GetString(objv[2]), &pDestDb);
- zDestName = Tcl_GetString(objv[3]);
- getDbPointer(interp, Tcl_GetString(objv[4]), &pSrcDb);
- zSrcName = Tcl_GetString(objv[5]);
-
- pBackup = sqlite3_backup_init(pDestDb, zDestName, pSrcDb, zSrcName);
- if( !pBackup ){
- Tcl_AppendResult(interp, "sqlite3_backup_init() failed", 0);
- return TCL_ERROR;
- }
-
- Tcl_CreateObjCommand(interp, zCmd, backupTestCmd, pBackup, backupTestFinish);
- Tcl_SetObjResult(interp, objv[1]);
- return TCL_OK;
-}
-
-int Sqlitetestbackup_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "sqlite3_backup", backupTestInit, 0, 0);
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_bestindex.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_bestindex.c
deleted file mode 100644
index 2cd79baf2bc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_bestindex.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
-** 2016-03-01
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the virtual table xBestIndex method and the query
-** planner.
-*/
-
-
-/*
-** INSTRUCTIONS
-**
-** This module exports a single tcl command - [register_tcl_module]. When
-** invoked, it registers a special virtual table module with a database
-** connection.
-**
-** The virtual table is currently read-only. And always returns zero rows.
-** It is created with a single argument - the name of a Tcl command - as
-** follows:
-**
-** CREATE VIRTUAL TABLE x1 USING tcl(tcl_command);
-**
-** The command [tcl_command] is invoked when the table is first created (or
-** connected), when the xBestIndex() method is invoked and when the xFilter()
-** method is called. When it is created (or connected), it is invoked as
-** follows:
-**
-** tcl_command xConnect
-**
-** In this case the return value of the script is passed to the
-** sqlite3_declare_vtab() function to create the virtual table schema.
-**
-** When the xBestIndex() method is called by SQLite, the Tcl command is
-** invoked as:
-**
-** tcl_command xBestIndex CONSTRAINTS ORDERBY MASK
-**
-** where CONSTRAINTS is a tcl representation of the aConstraints[] array,
-** ORDERBY is a representation of the contents of the aOrderBy[] array and
-** MASK is a copy of sqlite3_index_info.colUsed. For example if the virtual
-** table is declared as:
-**
-** CREATE TABLE x1(a, b, c)
-**
-** and the query is:
-**
-** SELECT * FROM x1 WHERE a=? AND c<? ORDER BY b, c;
-**
-** then the Tcl command is:
-**
-** tcl_command xBestIndex \
-** {{op eq column 0 usable 1} {op lt column 2 usable 1}} \
-** {{column 1 desc 0} {column 2 desc 0}} \
-** 7
-**
-** The return value of the script is a list of key-value pairs used to
-** populate the output fields of the sqlite3_index_info structure. Possible
-** keys and the usage of the accompanying values are:
-**
-** "orderby" (value of orderByConsumed flag)
-** "cost" (value of estimatedCost field)
-** "rows" (value of estimatedRows field)
-** "use" (index of used constraint in aConstraint[])
-** "omit" (like "use", but also sets omit flag)
-** "idxnum" (value of idxNum field)
-** "idxstr" (value of idxStr field)
-**
-** Refer to code below for further details.
-**
-** When SQLite calls the xFilter() method, this module invokes the following
-** Tcl script:
-**
-** tcl_command xFilter IDXNUM IDXSTR ARGLIST
-**
-** IDXNUM and IDXSTR are the values of the idxNum and idxStr parameters
-** passed to xFilter. ARGLIST is a Tcl list containing each of the arguments
-** passed to xFilter in text form.
-**
-** As with xBestIndex(), the return value of the script is interpreted as a
-** list of key-value pairs. There is currently only one key defined - "sql".
-** The value must be the full text of an SQL statement that returns the data
-** for the current scan. The leftmost column returned by the SELECT is assumed
-** to contain the rowid. Other columns must follow, in order from left to
-** right.
-*/
-
-
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-typedef struct tcl_vtab tcl_vtab;
-typedef struct tcl_cursor tcl_cursor;
-
-/*
-** A fs virtual-table object
-*/
-struct tcl_vtab {
- sqlite3_vtab base;
- Tcl_Interp *interp;
- Tcl_Obj *pCmd;
- sqlite3 *db;
-};
-
-/* A tcl cursor object */
-struct tcl_cursor {
- sqlite3_vtab_cursor base;
- sqlite3_stmt *pStmt; /* Read data from here */
-};
-
-/*
-** Dequote string z in place.
-*/
-static void tclDequote(char *z){
- char q = z[0];
-
- /* Set stack variable q to the close-quote character */
- if( q=='[' || q=='\'' || q=='"' || q=='`' ){
- int iIn = 1;
- int iOut = 0;
- if( q=='[' ) q = ']';
-
- while( ALWAYS(z[iIn]) ){
- if( z[iIn]==q ){
- if( z[iIn+1]!=q ){
- /* Character iIn was the close quote. */
- iIn++;
- break;
- }else{
- /* Character iIn and iIn+1 form an escaped quote character. Skip
- ** the input cursor past both and copy a single quote character
- ** to the output buffer. */
- iIn += 2;
- z[iOut++] = q;
- }
- }else{
- z[iOut++] = z[iIn++];
- }
- }
-
- z[iOut] = '\0';
- }
-}
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the fs virtual table.
-**
-** The argv[] array contains the following:
-**
-** argv[0] -> module name ("fs")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> other module argument fields.
-*/
-static int tclConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- Tcl_Interp *interp = (Tcl_Interp*)pAux;
- tcl_vtab *pTab = 0;
- char *zCmd = 0;
- Tcl_Obj *pScript = 0;
- int rc = SQLITE_OK;
-
- if( argc!=4 ){
- *pzErr = sqlite3_mprintf("wrong number of arguments");
- return SQLITE_ERROR;
- }
-
- zCmd = sqlite3_malloc64(strlen(argv[3])+1);
- pTab = (tcl_vtab*)sqlite3_malloc64(sizeof(tcl_vtab));
- if( zCmd && pTab ){
- memcpy(zCmd, argv[3], strlen(argv[3])+1);
- tclDequote(zCmd);
- memset(pTab, 0, sizeof(tcl_vtab));
-
- pTab->pCmd = Tcl_NewStringObj(zCmd, -1);
- pTab->interp = interp;
- pTab->db = db;
- Tcl_IncrRefCount(pTab->pCmd);
-
- pScript = Tcl_DuplicateObj(pTab->pCmd);
- Tcl_IncrRefCount(pScript);
- Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xConnect", -1));
-
- rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
- if( rc!=TCL_OK ){
- *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp));
- rc = SQLITE_ERROR;
- }else{
- rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp));
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3_free(pTab);
- pTab = 0;
- }
- }else{
- rc = SQLITE_NOMEM;
- }
-
- sqlite3_free(zCmd);
- *ppVtab = &pTab->base;
- return rc;
-}
-
-/* The xDisconnect and xDestroy methods are also the same */
-static int tclDisconnect(sqlite3_vtab *pVtab){
- tcl_vtab *pTab = (tcl_vtab*)pVtab;
- Tcl_DecrRefCount(pTab->pCmd);
- sqlite3_free(pTab);
- return SQLITE_OK;
-}
-
-/*
-** Open a new tcl cursor.
-*/
-static int tclOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- tcl_cursor *pCur;
- pCur = sqlite3_malloc(sizeof(tcl_cursor));
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(tcl_cursor));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a tcl cursor.
-*/
-static int tclClose(sqlite3_vtab_cursor *cur){
- tcl_cursor *pCur = (tcl_cursor *)cur;
- if( pCur ){
- sqlite3_finalize(pCur->pStmt);
- sqlite3_free(pCur);
- }
- return SQLITE_OK;
-}
-
-static int tclNext(sqlite3_vtab_cursor *pVtabCursor){
- tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor;
- if( pCsr->pStmt ){
- tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab);
- int rc = sqlite3_step(pCsr->pStmt);
- if( rc!=SQLITE_ROW ){
- const char *zErr;
- rc = sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- if( rc!=SQLITE_OK ){
- zErr = sqlite3_errmsg(pTab->db);
- pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
- }
- }
- }
- return SQLITE_OK;
-}
-
-static int tclFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor;
- tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab);
- Tcl_Interp *interp = pTab->interp;
- Tcl_Obj *pScript;
- Tcl_Obj *pArg;
- int ii;
- int rc;
-
- pScript = Tcl_DuplicateObj(pTab->pCmd);
- Tcl_IncrRefCount(pScript);
- Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xFilter", -1));
- Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(idxNum));
- if( idxStr ){
- Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(idxStr, -1));
- }else{
- Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("", -1));
- }
-
- pArg = Tcl_NewObj();
- Tcl_IncrRefCount(pArg);
- for(ii=0; ii<argc; ii++){
- const char *zVal = (const char*)sqlite3_value_text(argv[ii]);
- Tcl_Obj *pVal;
- if( zVal==0 ){
- pVal = Tcl_NewObj();
- }else{
- pVal = Tcl_NewStringObj(zVal, -1);
- }
- Tcl_ListObjAppendElement(interp, pArg, pVal);
- }
- Tcl_ListObjAppendElement(interp, pScript, pArg);
- Tcl_DecrRefCount(pArg);
-
- rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
- if( rc!=TCL_OK ){
- const char *zErr = Tcl_GetStringResult(interp);
- rc = SQLITE_ERROR;
- pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
- }else{
- /* Analyze the scripts return value. The return value should be a tcl
- ** list object with an even number of elements. The first element of each
- ** pair must be one of:
- **
- ** "sql" (SQL statement to return data)
- */
- Tcl_Obj *pRes = Tcl_GetObjResult(interp);
- Tcl_Obj **apElem = 0;
- int nElem;
- rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem);
- if( rc!=TCL_OK ){
- const char *zErr = Tcl_GetStringResult(interp);
- rc = SQLITE_ERROR;
- pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
- }else{
- for(ii=0; rc==SQLITE_OK && ii<nElem; ii+=2){
- const char *zCmd = Tcl_GetString(apElem[ii]);
- Tcl_Obj *p = apElem[ii+1];
- if( sqlite3_stricmp("sql", zCmd)==0 ){
- const char *zSql = Tcl_GetString(p);
- rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
- if( rc!=SQLITE_OK ){
- const char *zErr = sqlite3_errmsg(pTab->db);
- pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zErr);
- }
- }else{
- rc = SQLITE_ERROR;
- pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd);
- }
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = tclNext(pVtabCursor);
- }
- return rc;
-}
-
-static int tclColumn(
- sqlite3_vtab_cursor *pVtabCursor,
- sqlite3_context *ctx,
- int i
-){
- tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor;
- sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1));
- return SQLITE_OK;
-}
-
-static int tclRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
- tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor;
- *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
- return SQLITE_OK;
-}
-
-static int tclEof(sqlite3_vtab_cursor *pVtabCursor){
- tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor;
- return (pCsr->pStmt==0);
-}
-
-static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- tcl_vtab *pTab = (tcl_vtab*)tab;
- Tcl_Interp *interp = pTab->interp;
- Tcl_Obj *pArg;
- Tcl_Obj *pScript;
- int ii;
- int rc = SQLITE_OK;
-
- pScript = Tcl_DuplicateObj(pTab->pCmd);
- Tcl_IncrRefCount(pScript);
- Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xBestIndex", -1));
-
- pArg = Tcl_NewObj();
- Tcl_IncrRefCount(pArg);
- for(ii=0; ii<pIdxInfo->nConstraint; ii++){
- struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
- Tcl_Obj *pElem = Tcl_NewObj();
- const char *zOp = "?";
-
- Tcl_IncrRefCount(pElem);
-
- switch( pCons->op ){
- case SQLITE_INDEX_CONSTRAINT_EQ:
- zOp = "eq"; break;
- case SQLITE_INDEX_CONSTRAINT_GT:
- zOp = "gt"; break;
- case SQLITE_INDEX_CONSTRAINT_LE:
- zOp = "le"; break;
- case SQLITE_INDEX_CONSTRAINT_LT:
- zOp = "lt"; break;
- case SQLITE_INDEX_CONSTRAINT_GE:
- zOp = "ge"; break;
- case SQLITE_INDEX_CONSTRAINT_MATCH:
- zOp = "match"; break;
- case SQLITE_INDEX_CONSTRAINT_LIKE:
- zOp = "like"; break;
- case SQLITE_INDEX_CONSTRAINT_GLOB:
- zOp = "glob"; break;
- case SQLITE_INDEX_CONSTRAINT_REGEXP:
- zOp = "regexp"; break;
- case SQLITE_INDEX_CONSTRAINT_NE:
- zOp = "ne"; break;
- case SQLITE_INDEX_CONSTRAINT_ISNOT:
- zOp = "isnot"; break;
- case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
- zOp = "isnotnull"; break;
- case SQLITE_INDEX_CONSTRAINT_ISNULL:
- zOp = "isnull"; break;
- case SQLITE_INDEX_CONSTRAINT_IS:
- zOp = "is"; break;
- }
-
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1));
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zOp, -1));
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1));
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->iColumn));
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("usable", -1));
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->usable));
-
- Tcl_ListObjAppendElement(0, pArg, pElem);
- Tcl_DecrRefCount(pElem);
- }
-
- Tcl_ListObjAppendElement(0, pScript, pArg);
- Tcl_DecrRefCount(pArg);
-
- pArg = Tcl_NewObj();
- Tcl_IncrRefCount(pArg);
- for(ii=0; ii<pIdxInfo->nOrderBy; ii++){
- struct sqlite3_index_orderby const *pOrder = &pIdxInfo->aOrderBy[ii];
- Tcl_Obj *pElem = Tcl_NewObj();
- Tcl_IncrRefCount(pElem);
-
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1));
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->iColumn));
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("desc", -1));
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->desc));
-
- Tcl_ListObjAppendElement(0, pArg, pElem);
- Tcl_DecrRefCount(pElem);
- }
-
- Tcl_ListObjAppendElement(0, pScript, pArg);
- Tcl_DecrRefCount(pArg);
-
- Tcl_ListObjAppendElement(0, pScript, Tcl_NewWideIntObj(pIdxInfo->colUsed));
-
- rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
- Tcl_DecrRefCount(pScript);
- if( rc!=TCL_OK ){
- const char *zErr = Tcl_GetStringResult(interp);
- rc = SQLITE_ERROR;
- pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
- }else{
- /* Analyze the scripts return value. The return value should be a tcl
- ** list object with an even number of elements. The first element of each
- ** pair must be one of:
- **
- ** "orderby" (value of orderByConsumed flag)
- ** "cost" (value of estimatedCost field)
- ** "rows" (value of estimatedRows field)
- ** "use" (index of used constraint in aConstraint[])
- ** "idxnum" (value of idxNum field)
- ** "idxstr" (value of idxStr field)
- ** "omit" (index of omitted constraint in aConstraint[])
- */
- Tcl_Obj *pRes = Tcl_GetObjResult(interp);
- Tcl_Obj **apElem = 0;
- int nElem;
- rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem);
- if( rc!=TCL_OK ){
- const char *zErr = Tcl_GetStringResult(interp);
- rc = SQLITE_ERROR;
- pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
- }else{
- int iArgv = 1;
- for(ii=0; rc==SQLITE_OK && ii<nElem; ii+=2){
- const char *zCmd = Tcl_GetString(apElem[ii]);
- Tcl_Obj *p = apElem[ii+1];
- if( sqlite3_stricmp("cost", zCmd)==0 ){
- rc = Tcl_GetDoubleFromObj(interp, p, &pIdxInfo->estimatedCost);
- }else
- if( sqlite3_stricmp("orderby", zCmd)==0 ){
- rc = Tcl_GetIntFromObj(interp, p, &pIdxInfo->orderByConsumed);
- }else
- if( sqlite3_stricmp("idxnum", zCmd)==0 ){
- rc = Tcl_GetIntFromObj(interp, p, &pIdxInfo->idxNum);
- }else
- if( sqlite3_stricmp("idxstr", zCmd)==0 ){
- sqlite3_free(pIdxInfo->idxStr);
- pIdxInfo->idxStr = sqlite3_mprintf("%s", Tcl_GetString(p));
- pIdxInfo->needToFreeIdxStr = 1;
- }else
- if( sqlite3_stricmp("rows", zCmd)==0 ){
- Tcl_WideInt x = 0;
- rc = Tcl_GetWideIntFromObj(interp, p, &x);
- pIdxInfo->estimatedRows = (tRowcnt)x;
- }else
- if( sqlite3_stricmp("use", zCmd)==0
- || sqlite3_stricmp("omit", zCmd)==0
- ){
- int iCons;
- rc = Tcl_GetIntFromObj(interp, p, &iCons);
- if( rc==SQLITE_OK ){
- if( iCons<0 || iCons>=pIdxInfo->nConstraint ){
- rc = SQLITE_ERROR;
- pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %d", iCons);
- }else{
- int bOmit = (zCmd[0]=='o' || zCmd[0]=='O');
- pIdxInfo->aConstraintUsage[iCons].argvIndex = iArgv++;
- pIdxInfo->aConstraintUsage[iCons].omit = bOmit;
- }
- }
- }else{
- rc = SQLITE_ERROR;
- pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd);
- }
- if( rc!=SQLITE_OK && pTab->base.zErrMsg==0 ){
- const char *zErr = Tcl_GetStringResult(interp);
- pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
- }
- }
- }
- }
-
- return rc;
-}
-
-/*
-** A virtual table module that provides read-only access to a
-** Tcl global variable namespace.
-*/
-static sqlite3_module tclModule = {
- 0, /* iVersion */
- tclConnect,
- tclConnect,
- tclBestIndex,
- tclDisconnect,
- tclDisconnect,
- tclOpen, /* xOpen - open a cursor */
- tclClose, /* xClose - close a cursor */
- tclFilter, /* xFilter - configure scan constraints */
- tclNext, /* xNext - advance a cursor */
- tclEof, /* xEof - check for end of scan */
- tclColumn, /* xColumn - read data */
- tclRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
-
-/*
-** Register the echo virtual table module.
-*/
-static int SQLITE_TCLAPI register_tcl_module(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_create_module(db, "tcl", &tclModule, (void *)interp);
-#endif
- return TCL_OK;
-}
-
-#endif
-
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetesttcl_Init(Tcl_Interp *interp){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- void *clientData;
- } aObjCmd[] = {
- { "register_tcl_module", register_tcl_module, 0 },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
- aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
- }
-#endif
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_blob.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_blob.c
deleted file mode 100644
index cbdf9f069f7..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_blob.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
-** 2014 October 30
-**
-** 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.
-**
-*************************************************************************
-**
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#ifndef SQLITE_OMIT_INCRBLOB
-
-/* These functions are implemented in main.c. */
-extern const char *sqlite3ErrName(int);
-
-/* From test1.c: */
-extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
-extern void *sqlite3TestTextToPtr(const char *z);
-
-/*
-** Return a pointer to a buffer containing a text representation of the
-** pointer passed as the only argument. The original pointer may be extracted
-** from the text using sqlite3TestTextToPtr().
-*/
-static char *ptrToText(void *p){
- static char buf[100];
- sqlite3_snprintf(sizeof(buf)-1, buf, "%p", p);
- return buf;
-}
-
-/*
-** Attempt to extract a blob handle (type sqlite3_blob*) from the Tcl
-** object passed as the second argument. If successful, set *ppBlob to
-** point to the blob handle and return TCL_OK. Otherwise, store an error
-** message in the tcl interpreter and return TCL_ERROR. The final value
-** of *ppBlob is undefined in this case.
-**
-** If the object contains a string that begins with "incrblob_", then it
-** is assumed to be the name of a Tcl channel opened using the [db incrblob]
-** command (see tclsqlite.c). Otherwise, it is assumed to be a pointer
-** encoded using the ptrToText() routine or similar.
-*/
-static int blobHandleFromObj(
- Tcl_Interp *interp,
- Tcl_Obj *pObj,
- sqlite3_blob **ppBlob
-){
- char *z;
- int n;
-
- z = Tcl_GetStringFromObj(pObj, &n);
- if( n==0 ){
- *ppBlob = 0;
- }else if( n>9 && 0==memcmp("incrblob_", z, 9) ){
- int notUsed;
- Tcl_Channel channel;
- ClientData instanceData;
-
- channel = Tcl_GetChannel(interp, z, &notUsed);
- if( !channel ) return TCL_ERROR;
-
- Tcl_Flush(channel);
- Tcl_Seek(channel, 0, SEEK_SET);
-
- instanceData = Tcl_GetChannelInstanceData(channel);
- *ppBlob = *((sqlite3_blob **)instanceData);
- }else{
- *ppBlob = (sqlite3_blob*)sqlite3TestTextToPtr(z);
- }
-
- return TCL_OK;
-}
-
-/*
-** Like Tcl_GetString(), except that if the string is 0 bytes in size, a
-** NULL Pointer is returned.
-*/
-static char *blobStringFromObj(Tcl_Obj *pObj){
- int n;
- char *z;
- z = Tcl_GetStringFromObj(pObj, &n);
- return (n ? z : 0);
-}
-
-/*
-** sqlite3_blob_open DB DATABASE TABLE COLUMN ROWID FLAGS VARNAME
-**
-** Tcl test harness for the sqlite3_blob_open() function.
-*/
-static int SQLITE_TCLAPI test_blob_open(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* Calling TCL interpreter */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- const char *zDb;
- const char *zTable;
- const char *zColumn;
- Tcl_WideInt iRowid;
- int flags;
- const char *zVarname;
- int nVarname;
-
- sqlite3_blob *pBlob = (sqlite3_blob*)&flags; /* Non-zero initialization */
- int rc;
-
- if( objc!=8 ){
- const char *zUsage = "DB DATABASE TABLE COLUMN ROWID FLAGS VARNAME";
- Tcl_WrongNumArgs(interp, 1, objv, zUsage);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zDb = Tcl_GetString(objv[2]);
- zTable = blobStringFromObj(objv[3]);
- zColumn = Tcl_GetString(objv[4]);
- if( Tcl_GetWideIntFromObj(interp, objv[5], &iRowid) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[6], &flags) ) return TCL_ERROR;
- zVarname = Tcl_GetStringFromObj(objv[7], &nVarname);
-
- if( nVarname>0 ){
- rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRowid, flags, &pBlob);
- Tcl_SetVar(interp, zVarname, ptrToText(pBlob), 0);
- }else{
- rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRowid, flags, 0);
- }
-
- if( rc==SQLITE_OK ){
- Tcl_ResetResult(interp);
- }else{
- Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-
-/*
-** sqlite3_blob_close HANDLE
-*/
-static int SQLITE_TCLAPI test_blob_close(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_blob *pBlob;
- int rc;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
-
- if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
- rc = sqlite3_blob_close(pBlob);
-
- if( rc ){
- Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
- }else{
- Tcl_ResetResult(interp);
- }
- return TCL_OK;
-}
-
-/*
-** sqlite3_blob_bytes HANDLE
-*/
-static int SQLITE_TCLAPI test_blob_bytes(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_blob *pBlob;
- int nByte;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
-
- if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
- nByte = sqlite3_blob_bytes(pBlob);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte));
-
- return TCL_OK;
-}
-
-/*
-** sqlite3_blob_read CHANNEL OFFSET N
-**
-** This command is used to test the sqlite3_blob_read() in ways that
-** the Tcl channel interface does not. The first argument should
-** be the name of a valid channel created by the [incrblob] method
-** of a database handle. This function calls sqlite3_blob_read()
-** to read N bytes from offset OFFSET from the underlying SQLite
-** blob handle.
-**
-** On success, a byte-array object containing the read data is
-** returned. On failure, the interpreter result is set to the
-** text representation of the returned error code (i.e. "SQLITE_NOMEM")
-** and a Tcl exception is thrown.
-*/
-static int SQLITE_TCLAPI test_blob_read(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_blob *pBlob;
- int nByte;
- int iOffset;
- unsigned char *zBuf = 0;
- int rc;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N");
- return TCL_ERROR;
- }
-
- if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
- if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset)
- || TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte)
- ){
- return TCL_ERROR;
- }
-
- if( nByte>0 ){
- zBuf = (unsigned char *)Tcl_AttemptAlloc(nByte);
- if( zBuf==0 ){
- Tcl_AppendResult(interp, "out of memory in " __FILE__, 0);
- return TCL_ERROR;
- }
- }
- rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset);
- if( rc==SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte));
- }else{
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- }
- Tcl_Free((char *)zBuf);
-
- return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
-}
-
-/*
-** sqlite3_blob_write HANDLE OFFSET DATA ?NDATA?
-**
-** This command is used to test the sqlite3_blob_write() in ways that
-** the Tcl channel interface does not. The first argument should
-** be the name of a valid channel created by the [incrblob] method
-** of a database handle. This function calls sqlite3_blob_write()
-** to write the DATA byte-array to the underlying SQLite blob handle.
-** at offset OFFSET.
-**
-** On success, an empty string is returned. On failure, the interpreter
-** result is set to the text representation of the returned error code
-** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown.
-*/
-static int SQLITE_TCLAPI test_blob_write(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_blob *pBlob;
- int iOffset;
- int rc;
-
- unsigned char *zBuf;
- int nBuf;
-
- if( objc!=4 && objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE OFFSET DATA ?NDATA?");
- return TCL_ERROR;
- }
-
- if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
- if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){
- return TCL_ERROR;
- }
-
- zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
- if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
- return TCL_ERROR;
- }
- rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
- if( rc!=SQLITE_OK ){
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- }
-
- return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
-}
-#endif /* SQLITE_OMIT_INCRBLOB */
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest_blob_Init(Tcl_Interp *interp){
-#ifndef SQLITE_OMIT_INCRBLOB
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aObjCmd[] = {
- { "sqlite3_blob_open", test_blob_open },
- { "sqlite3_blob_close", test_blob_close },
- { "sqlite3_blob_bytes", test_blob_bytes },
- { "sqlite3_blob_read", test_blob_read },
- { "sqlite3_blob_write", test_blob_write },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
- }
-#endif /* SQLITE_OMIT_INCRBLOB */
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_btree.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_btree.c
deleted file mode 100644
index 03b8b207c98..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_btree.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-** 2007 May 05
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the btree.c module in SQLite. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library.
-*/
-#include "btreeInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-/*
-** Usage: sqlite3_shared_cache_report
-**
-** Return a list of file that are shared and the number of
-** references to each file.
-*/
-int SQLITE_TCLAPI sqlite3BtreeSharedCacheReport(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_OMIT_SHARED_CACHE
- extern BtShared *sqlite3SharedCacheList;
- BtShared *pBt;
- Tcl_Obj *pRet = Tcl_NewObj();
- for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
- const char *zFile = sqlite3PagerFilename(pBt->pPager, 1);
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef));
- }
- Tcl_SetObjResult(interp, pRet);
-#endif
- return TCL_OK;
-}
-
-/*
-** Print debugging information about all cursors to standard output.
-*/
-void sqlite3BtreeCursorList(Btree *p){
-#ifdef SQLITE_DEBUG
- BtCursor *pCur;
- BtShared *pBt = p->pBt;
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- MemPage *pPage = pCur->apPage[pCur->iPage];
- char *zMode = (pCur->curFlags & BTCF_WriteFlag) ? "rw" : "ro";
- sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n",
- pCur, pCur->pgnoRoot, zMode,
- pPage ? pPage->pgno : 0, pCur->aiIdx[pCur->iPage],
- (pCur->eState==CURSOR_VALID) ? "" : " eof"
- );
- }
-#endif
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_config.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_config.c
deleted file mode 100644
index aa0626ab2da..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_config.c
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
-** 2007 May 7
-**
-** 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 contains code used for testing the SQLite system.
-** None of the code in this file goes into a deliverable build.
-**
-** The focus of this file is providing the TCL testing layer
-** access to compile-time constants.
-*/
-
-#include "sqliteLimit.h"
-
-#include "sqliteInt.h"
-#if SQLITE_OS_WIN
-# include "os_win.h"
-#endif
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-/*
-** Macro to stringify the results of the evaluation a pre-processor
-** macro. i.e. so that STRINGVALUE(SQLITE_NOMEM) -> "7".
-*/
-#define STRINGVALUE2(x) #x
-#define STRINGVALUE(x) STRINGVALUE2(x)
-
-/*
-** This routine sets entries in the global ::sqlite_options() array variable
-** according to the compile-time configuration of the database. Test
-** procedures use this to determine when tests should be omitted.
-*/
-static void set_options(Tcl_Interp *interp){
-#if HAVE_MALLOC_USABLE_SIZE
- Tcl_SetVar2(interp, "sqlite_options", "malloc_usable_size", "1",
- TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "malloc_usable_size", "0",
- TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_32BIT_ROWID
- Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_CASE_SENSITIVE_LIKE
- Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
-#endif
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- Tcl_SetVar2(interp, "sqlite_options", "curdir", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "curdir", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_WIN32_MALLOC
- Tcl_SetVar2(interp, "sqlite_options", "win32malloc", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "win32malloc", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_DEBUG
- Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC
- Tcl_SetVar2(interp, "sqlite_options", "default_ckptfullfsync",
- SQLITE_DEFAULT_CKPTFULLFSYNC ? "1" : "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "default_ckptfullfsync", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- Tcl_SetVar2(interp, "sqlite_options", "direct_read", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "direct_read", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_DISABLE_DIRSYNC
- Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_DISABLE_LFS
- Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
- Tcl_SetVar2(interp, "sqlite_options", "pagecache_overflow_stats","0",TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "pagecache_overflow_stats","1",TCL_GLOBAL_ONLY);
-#endif
-
-#if SQLITE_MAX_MMAP_SIZE>0
- Tcl_SetVar2(interp, "sqlite_options", "mmap", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "mmap", "0", TCL_GLOBAL_ONLY);
-#endif
-
- Tcl_SetVar2(interp, "sqlite_options", "worker_threads",
- STRINGVALUE(SQLITE_MAX_WORKER_THREADS), TCL_GLOBAL_ONLY
- );
-
-#if 1 /* def SQLITE_MEMDEBUG */
- Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_8_3_NAMES
- Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
- Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
- Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_DESERIALIZE
- Tcl_SetVar2(interp, "sqlite_options", "deserialize", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "deserialize", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_MEMSYS3
- Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "mem3", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_MEMSYS5
- Tcl_SetVar2(interp, "sqlite_options", "mem5", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "mem5", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
- Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","1",TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "preupdate", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
- Tcl_SetVar2(interp, "sqlite_options", "snapshot", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "snapshot", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_MUTEX_OMIT
- Tcl_SetVar2(interp, "sqlite_options", "mutex", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "mutex", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_MUTEX_NOOP
- Tcl_SetVar2(interp, "sqlite_options", "mutex_noop", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "mutex_noop", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_ALTERTABLE
- Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_ANALYZE
- Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- Tcl_SetVar2(interp, "sqlite_options", "api_armor", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "api_armor", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
- Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_JSON1
- Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_HAS_CODEC
- Tcl_SetVar2(interp, "sqlite_options", "has_codec", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "has_codec", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- Tcl_SetVar2(interp, "sqlite_options", "like_match_blobs", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "like_match_blobs", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_ATTACH
- Tcl_SetVar2(interp, "sqlite_options", "attach", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "attach", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_AUTHORIZATION
- Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_AUTOINCREMENT
- Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
- Tcl_SetVar2(interp, "sqlite_options", "autoindex", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "autoindex", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_AUTORESET
- Tcl_SetVar2(interp, "sqlite_options", "autoreset", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "autoreset", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_AUTOVACUUM
- Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
-#endif /* SQLITE_OMIT_AUTOVACUUM */
-#if !defined(SQLITE_DEFAULT_AUTOVACUUM)
- Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "default_autovacuum",
- STRINGVALUE(SQLITE_DEFAULT_AUTOVACUUM), TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
- Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_UNTESTABLE
- Tcl_SetVar2(interp, "sqlite_options", "builtin_test", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "builtin_test", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_BLOB_LITERAL
- Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_CAST
- Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_CHECK
- Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_CTE
- Tcl_SetVar2(interp, "sqlite_options", "cte", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "cte", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
- Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
- Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "1",
- TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "0",
- TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
- Tcl_SetVar2(interp, "sqlite_options", "compileoption_diags", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "compileoption_diags", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_COMPLETE
- Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_COMPOUND_SELECT
- Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
-#endif
-
- Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
- Tcl_SetVar2(interp, "sqlite_options", "crashtest", "1", TCL_GLOBAL_ONLY);
-
-#ifdef SQLITE_OMIT_DATETIME_FUNCS
- Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_DECLTYPE
- Tcl_SetVar2(interp, "sqlite_options", "decltype", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "decltype", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_DEPRECATED
- Tcl_SetVar2(interp, "sqlite_options", "deprecated", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "deprecated", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_DISKIO
- Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_EXPLAIN
- Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_FLOATING_POINT
- Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_FOREIGN_KEY
- Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_FTS1
- Tcl_SetVar2(interp, "sqlite_options", "fts1", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "fts1", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_FTS2
- Tcl_SetVar2(interp, "sqlite_options", "fts2", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "fts2", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_FTS3
- Tcl_SetVar2(interp, "sqlite_options", "fts3", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "fts3", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_FTS5
- Tcl_SetVar2(interp, "sqlite_options", "fts5", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "fts5", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_DISABLE_FTS3_UNICODE)
- Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_DISABLE_FTS4_DEFERRED
- Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_GET_TABLE
- Tcl_SetVar2(interp, "sqlite_options", "gettable", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "gettable", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_ICU
- Tcl_SetVar2(interp, "sqlite_options", "icu", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "icu", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_ICU_COLLATIONS
- Tcl_SetVar2(interp, "sqlite_options", "icu_collations", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "icu_collations", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_INCRBLOB
- Tcl_SetVar2(interp, "sqlite_options", "incrblob", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "incrblob", "1", TCL_GLOBAL_ONLY);
-#endif /* SQLITE_OMIT_AUTOVACUUM */
-
-#ifdef SQLITE_OMIT_INTEGRITY_CHECK
- Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#if defined(SQLITE_DEFAULT_FILE_FORMAT) && SQLITE_DEFAULT_FILE_FORMAT==1
- Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
- Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_LOAD_EXTENSION
- Tcl_SetVar2(interp, "sqlite_options", "load_ext", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "load_ext", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_LOCALTIME
- Tcl_SetVar2(interp, "sqlite_options", "localtime", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "localtime", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_LOOKASIDE
- Tcl_SetVar2(interp, "sqlite_options", "lookaside", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "lookaside", "1", TCL_GLOBAL_ONLY);
-#endif
-
-Tcl_SetVar2(interp, "sqlite_options", "long_double",
- sizeof(LONGDOUBLE_TYPE)>sizeof(double) ? "1" : "0",
- TCL_GLOBAL_ONLY);
-
-#ifdef SQLITE_OMIT_MEMORYDB
- Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "0", TCL_GLOBAL_ONLY);
-#endif
-
-Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
-
-#ifdef SQLITE_ENABLE_NULL_TRIM
- Tcl_SetVar2(interp, "sqlite_options", "null_trim", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "null_trim", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_OR_OPTIMIZATION
- Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_RBU
- Tcl_SetVar2(interp, "sqlite_options", "rbu", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "rbu", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_PAGER_PRAGMAS
- Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS)
- Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
- Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
- Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_REINDEX
- Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_RTREE
- Tcl_SetVar2(interp, "sqlite_options", "rtree", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "rtree", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_RTREE_INT_ONLY
- Tcl_SetVar2(interp, "sqlite_options", "rtree_int_only", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "rtree_int_only", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
- Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
- Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_SESSION
- Tcl_SetVar2(interp, "sqlite_options", "session", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "session", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_STAT4
- Tcl_SetVar2(interp, "sqlite_options", "stat4", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY);
-#endif
-#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
- Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#if defined(SQLITE_ENABLE_STMTVTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
- Tcl_SetVar2(interp, "sqlite_options", "stmtvtab", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "stmtvtab", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- Tcl_SetVar2(interp, "sqlite_options", "scanstatus", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "scanstatus", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-# if defined(__APPLE__)
-# define SQLITE_ENABLE_LOCKING_STYLE 1
-# else
-# define SQLITE_ENABLE_LOCKING_STYLE 0
-# endif
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","1",TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","0",TCL_GLOBAL_ONLY);
-#endif
-#if defined(SQLITE_PREFER_PROXY_LOCKING) && defined(__APPLE__)
- Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","1",TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","0",TCL_GLOBAL_ONLY);
-#endif
-
-
-#ifdef SQLITE_OMIT_SHARED_CACHE
- Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_SUBQUERY
- Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_TCL_VARIABLE
- Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
-#endif
-
- Tcl_SetVar2(interp, "sqlite_options", "threadsafe",
- SQLITE_THREADSAFE ? "1" : "0", TCL_GLOBAL_ONLY);
- Tcl_SetVar2(interp, "sqlite_options", "threadsafe1",
- SQLITE_THREADSAFE==1 ? "1" : "0", TCL_GLOBAL_ONLY);
- Tcl_SetVar2(interp, "sqlite_options", "threadsafe2",
- SQLITE_THREADSAFE==2 ? "1" : "0", TCL_GLOBAL_ONLY);
- assert( sqlite3_threadsafe()==SQLITE_THREADSAFE );
-
-#ifdef SQLITE_OMIT_TEMPDB
- Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_TRACE
- Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_TRIGGER
- Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
- Tcl_SetVar2(interp, "sqlite_options", "truncate_opt", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "truncate_opt", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_UTF16
- Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#if defined(SQLITE_OMIT_VACUUM) || defined(SQLITE_OMIT_ATTACH)
- Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_VIEW
- Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_VIRTUALTABLE
- Tcl_SetVar2(interp, "sqlite_options", "vtab", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_WAL
- Tcl_SetVar2(interp, "sqlite_options", "wal", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "wal", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_OMIT_WSD
- Tcl_SetVar2(interp, "sqlite_options", "wsd", "0", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "wsd", "1", TCL_GLOBAL_ONLY);
-#endif
-
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
- Tcl_SetVar2(interp, "sqlite_options", "update_delete_limit", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "update_delete_limit", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#if defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
- Tcl_SetVar2(interp, "sqlite_options", "unlock_notify", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "unlock_notify", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_FAST_SECURE_DELETE
- Tcl_SetVar2(interp, "sqlite_options", "fast_secure_delete", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "fast_secure_delete", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_SECURE_DELETE
- Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_USER_AUTHENTICATION
- Tcl_SetVar2(interp, "sqlite_options", "userauth", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "userauth", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_MULTIPLEX_EXT_OVWR
- Tcl_SetVar2(interp, "sqlite_options", "multiplex_ext_overwrite", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "multiplex_ext_overwrite", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef YYTRACKMAXSTACKDEPTH
- Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_SQLLOG
- Tcl_SetVar2(interp, "sqlite_options", "sqllog", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "sqllog", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#ifdef SQLITE_ENABLE_URI_00_ERROR
- Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY);
-#endif
-
-#define LINKVAR(x) { \
- static const int cv_ ## x = SQLITE_ ## x; \
- Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
- TCL_LINK_INT | TCL_LINK_READ_ONLY); }
-
- LINKVAR( MAX_LENGTH );
- LINKVAR( MAX_COLUMN );
- LINKVAR( MAX_SQL_LENGTH );
- LINKVAR( MAX_EXPR_DEPTH );
- LINKVAR( MAX_COMPOUND_SELECT );
- LINKVAR( MAX_VDBE_OP );
- LINKVAR( MAX_FUNCTION_ARG );
- LINKVAR( MAX_VARIABLE_NUMBER );
- LINKVAR( MAX_PAGE_SIZE );
- LINKVAR( MAX_PAGE_COUNT );
- LINKVAR( MAX_LIKE_PATTERN_LENGTH );
- LINKVAR( MAX_TRIGGER_DEPTH );
- LINKVAR( DEFAULT_CACHE_SIZE );
- LINKVAR( DEFAULT_PAGE_SIZE );
- LINKVAR( DEFAULT_FILE_FORMAT );
- LINKVAR( DEFAULT_SYNCHRONOUS );
- LINKVAR( DEFAULT_WAL_SYNCHRONOUS );
- LINKVAR( MAX_ATTACHED );
- LINKVAR( MAX_DEFAULT_PAGE_SIZE );
- LINKVAR( MAX_WORKER_THREADS );
-
- {
- static const int cv_TEMP_STORE = SQLITE_TEMP_STORE;
- Tcl_LinkVar(interp, "TEMP_STORE", (char *)&(cv_TEMP_STORE),
- TCL_LINK_INT | TCL_LINK_READ_ONLY);
- }
-
-#ifdef _MSC_VER
- {
- static const int cv__MSC_VER = 1;
- Tcl_LinkVar(interp, "_MSC_VER", (char *)&(cv__MSC_VER),
- TCL_LINK_INT | TCL_LINK_READ_ONLY);
- }
-#endif
-#ifdef __GNUC__
- {
- static const int cv___GNUC__ = 1;
- Tcl_LinkVar(interp, "__GNUC__", (char *)&(cv___GNUC__),
- TCL_LINK_INT | TCL_LINK_READ_ONLY);
- }
-#endif
-}
-
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqliteconfig_Init(Tcl_Interp *interp){
- set_options(interp);
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_delete.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_delete.c
deleted file mode 100644
index 68fdbc6a757..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_delete.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-** 2016 September 10
-**
-** 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 contains test code to delete an SQLite database and all
-** of its associated files. Associated files include:
-**
-** * The journal file.
-** * The wal file.
-** * The SQLITE_ENABLE_8_3_NAMES version of the db, journal or wal files.
-** * Files created by the test_multiplex.c module to extend any of the
-** above.
-*/
-
-#ifndef SQLITE_OS_WIN
-# include <unistd.h>
-# include <errno.h>
-#endif
-#include <string.h>
-#include <assert.h>
-#include "sqlite3.h"
-
-/* The following #defines are copied from test_multiplex.c */
-#ifndef MX_CHUNK_NUMBER
-# define MX_CHUNK_NUMBER 299
-#endif
-#ifndef SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET
-# define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
-#endif
-#ifndef SQLITE_MULTIPLEX_WAL_8_3_OFFSET
-# define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700
-#endif
-
-/*
-** This routine is a copy of (most of) the code from SQLite function
-** sqlite3FileSuffix3(). It modifies the filename in buffer z in the
-** same way as SQLite does when in 8.3 filenames mode.
-*/
-static void sqlite3Delete83Name(char *z){
- int i, sz;
- sz = (int)strlen(z);
- for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
- if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
-}
-
-/*
-** zFile is a filename. Assuming no error occurs, if this file exists,
-** set *pbExists to true and unlink it. Or, if the file does not exist,
-** set *pbExists to false before returning.
-**
-** If an error occurs, non-zero is returned. Or, if no error occurs, zero.
-*/
-static int sqlite3DeleteUnlinkIfExists(
- sqlite3_vfs *pVfs,
- const char *zFile,
- int *pbExists
-){
- int rc = SQLITE_ERROR;
-#if SQLITE_OS_WIN
- if( pVfs ){
- if( pbExists ) *pbExists = 1;
- rc = pVfs->xDelete(pVfs, zFile, 0);
- if( rc==SQLITE_IOERR_DELETE_NOENT ){
- if( pbExists ) *pbExists = 0;
- rc = SQLITE_OK;
- }
- }
-#else
- assert( pVfs==0 );
- rc = access(zFile, F_OK);
- if( rc ){
- if( errno==ENOENT ){
- if( pbExists ) *pbExists = 0;
- rc = SQLITE_OK;
- }
- }else{
- if( pbExists ) *pbExists = 1;
- rc = unlink(zFile);
- }
-#endif
- return rc;
-}
-
-/*
-** Delete the database file identified by the string argument passed to this
-** function. The string must contain a filename, not an SQLite URI.
-*/
-SQLITE_API int sqlite3_delete_database(
- const char *zFile /* File to delete */
-){
- char *zBuf; /* Buffer to sprintf() filenames to */
- int nBuf; /* Size of buffer in bytes */
- int rc = 0; /* System error code */
- int i; /* Iterate through azFmt[] and aMFile[] */
-
- const char *azFmt[] = { "%s", "%s-journal", "%s-wal", "%s-shm" };
-
- struct MFile {
- const char *zFmt;
- int iOffset;
- int b83;
- } aMFile[] = {
- { "%s%03d", 0, 0 },
- { "%s-journal%03d", 0, 0 },
- { "%s-wal%03d", 0, 0 },
- { "%s%03d", 0, 1 },
- { "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 },
- { "%s-wal%03d", SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 },
- };
-
-#ifdef SQLITE_OS_WIN
- sqlite3_vfs *pVfs = sqlite3_vfs_find("win32");
-#else
- sqlite3_vfs *pVfs = 0;
-#endif
-
- /* Allocate a buffer large enough for any of the files that need to be
- ** deleted. */
- nBuf = (int)strlen(zFile) + 100;
- zBuf = (char*)sqlite3_malloc(nBuf);
- if( zBuf==0 ) return SQLITE_NOMEM;
-
- /* Delete both the regular and 8.3 filenames versions of the database,
- ** journal, wal and shm files. */
- for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){
- sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile);
- rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0);
- if( rc==0 && i!=0 ){
- sqlite3Delete83Name(zBuf);
- rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0);
- }
- }
-
- /* Delete any multiplexor files */
- for(i=0; rc==0 && i<sizeof(aMFile)/sizeof(aMFile[0]); i++){
- struct MFile *p = &aMFile[i];
- int iChunk;
- for(iChunk=1; iChunk<=MX_CHUNK_NUMBER; iChunk++){
- int bExists;
- sqlite3_snprintf(nBuf, zBuf, p->zFmt, zFile, iChunk+p->iOffset);
- if( p->b83 ) sqlite3Delete83Name(zBuf);
- rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, &bExists);
- if( bExists==0 || rc!=0 ) break;
- }
- }
-
- sqlite3_free(zBuf);
- return (rc ? SQLITE_ERROR : SQLITE_OK);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_demovfs.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_demovfs.c
deleted file mode 100644
index ba7af863cde..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_demovfs.c
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
-** 2010 April 7
-**
-** 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 an example of a simple VFS implementation that
-** omits complex features often not required or not possible on embedded
-** platforms. Code is included to buffer writes to the journal file,
-** which can be a significant performance improvement on some embedded
-** platforms.
-**
-** OVERVIEW
-**
-** The code in this file implements a minimal SQLite VFS that can be
-** used on Linux and other posix-like operating systems. The following
-** system calls are used:
-**
-** File-system: access(), unlink(), getcwd()
-** File IO: open(), read(), write(), fsync(), close(), fstat()
-** Other: sleep(), usleep(), time()
-**
-** The following VFS features are omitted:
-**
-** 1. File locking. The user must ensure that there is at most one
-** connection to each database when using this VFS. Multiple
-** connections to a single shared-cache count as a single connection
-** for the purposes of the previous statement.
-**
-** 2. The loading of dynamic extensions (shared libraries).
-**
-** 3. Temporary files. The user must configure SQLite to use in-memory
-** temp files when using this VFS. The easiest way to do this is to
-** compile with:
-**
-** -DSQLITE_TEMP_STORE=3
-**
-** 4. File truncation. As of version 3.6.24, SQLite may run without
-** a working xTruncate() call, providing the user does not configure
-** SQLite to use "journal_mode=truncate", or use both
-** "journal_mode=persist" and ATTACHed databases.
-**
-** It is assumed that the system uses UNIX-like path-names. Specifically,
-** that '/' characters are used to separate path components and that
-** a path-name is a relative path unless it begins with a '/'. And that
-** no UTF-8 encoded paths are greater than 512 bytes in length.
-**
-** JOURNAL WRITE-BUFFERING
-**
-** To commit a transaction to the database, SQLite first writes rollback
-** information into the journal file. This usually consists of 4 steps:
-**
-** 1. The rollback information is sequentially written into the journal
-** file, starting at the start of the file.
-** 2. The journal file is synced to disk.
-** 3. A modification is made to the first few bytes of the journal file.
-** 4. The journal file is synced to disk again.
-**
-** Most of the data is written in step 1 using a series of calls to the
-** VFS xWrite() method. The buffers passed to the xWrite() calls are of
-** various sizes. For example, as of version 3.6.24, when committing a
-** transaction that modifies 3 pages of a database file that uses 4096
-** byte pages residing on a media with 512 byte sectors, SQLite makes
-** eleven calls to the xWrite() method to create the rollback journal,
-** as follows:
-**
-** Write offset | Bytes written
-** ----------------------------
-** 0 512
-** 512 4
-** 516 4096
-** 4612 4
-** 4616 4
-** 4620 4096
-** 8716 4
-** 8720 4
-** 8724 4096
-** 12820 4
-** ++++++++++++SYNC+++++++++++
-** 0 12
-** ++++++++++++SYNC+++++++++++
-**
-** On many operating systems, this is an efficient way to write to a file.
-** However, on some embedded systems that do not cache writes in OS
-** buffers it is much more efficient to write data in blocks that are
-** an integer multiple of the sector-size in size and aligned at the
-** start of a sector.
-**
-** To work around this, the code in this file allocates a fixed size
-** buffer of SQLITE_DEMOVFS_BUFFERSZ using sqlite3_malloc() whenever a
-** journal file is opened. It uses the buffer to coalesce sequential
-** writes into aligned SQLITE_DEMOVFS_BUFFERSZ blocks. When SQLite
-** invokes the xSync() method to sync the contents of the file to disk,
-** all accumulated data is written out, even if it does not constitute
-** a complete block. This means the actual IO to create the rollback
-** journal for the example transaction above is this:
-**
-** Write offset | Bytes written
-** ----------------------------
-** 0 8192
-** 8192 4632
-** ++++++++++++SYNC+++++++++++
-** 0 12
-** ++++++++++++SYNC+++++++++++
-**
-** Much more efficient if the underlying OS is not caching write
-** operations.
-*/
-
-#if !defined(SQLITE_TEST) || SQLITE_OS_UNIX
-
-#include "sqlite3.h"
-
-#include <assert.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <sys/param.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <fcntl.h>
-
-/*
-** Size of the write buffer used by journal files in bytes.
-*/
-#ifndef SQLITE_DEMOVFS_BUFFERSZ
-# define SQLITE_DEMOVFS_BUFFERSZ 8192
-#endif
-
-/*
-** The maximum pathname length supported by this VFS.
-*/
-#define MAXPATHNAME 512
-
-/*
-** When using this VFS, the sqlite3_file* handles that SQLite uses are
-** actually pointers to instances of type DemoFile.
-*/
-typedef struct DemoFile DemoFile;
-struct DemoFile {
- sqlite3_file base; /* Base class. Must be first. */
- int fd; /* File descriptor */
-
- char *aBuffer; /* Pointer to malloc'd buffer */
- int nBuffer; /* Valid bytes of data in zBuffer */
- sqlite3_int64 iBufferOfst; /* Offset in file of zBuffer[0] */
-};
-
-/*
-** Write directly to the file passed as the first argument. Even if the
-** file has a write-buffer (DemoFile.aBuffer), ignore it.
-*/
-static int demoDirectWrite(
- DemoFile *p, /* File handle */
- const void *zBuf, /* Buffer containing data to write */
- int iAmt, /* Size of data to write in bytes */
- sqlite_int64 iOfst /* File offset to write to */
-){
- off_t ofst; /* Return value from lseek() */
- size_t nWrite; /* Return value from write() */
-
- ofst = lseek(p->fd, iOfst, SEEK_SET);
- if( ofst!=iOfst ){
- return SQLITE_IOERR_WRITE;
- }
-
- nWrite = write(p->fd, zBuf, iAmt);
- if( nWrite!=iAmt ){
- return SQLITE_IOERR_WRITE;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Flush the contents of the DemoFile.aBuffer buffer to disk. This is a
-** no-op if this particular file does not have a buffer (i.e. it is not
-** a journal file) or if the buffer is currently empty.
-*/
-static int demoFlushBuffer(DemoFile *p){
- int rc = SQLITE_OK;
- if( p->nBuffer ){
- rc = demoDirectWrite(p, p->aBuffer, p->nBuffer, p->iBufferOfst);
- p->nBuffer = 0;
- }
- return rc;
-}
-
-/*
-** Close a file.
-*/
-static int demoClose(sqlite3_file *pFile){
- int rc;
- DemoFile *p = (DemoFile*)pFile;
- rc = demoFlushBuffer(p);
- sqlite3_free(p->aBuffer);
- close(p->fd);
- return rc;
-}
-
-/*
-** Read data from a file.
-*/
-static int demoRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- DemoFile *p = (DemoFile*)pFile;
- off_t ofst; /* Return value from lseek() */
- int nRead; /* Return value from read() */
- int rc; /* Return code from demoFlushBuffer() */
-
- /* Flush any data in the write buffer to disk in case this operation
- ** is trying to read data the file-region currently cached in the buffer.
- ** It would be possible to detect this case and possibly save an
- ** unnecessary write here, but in practice SQLite will rarely read from
- ** a journal file when there is data cached in the write-buffer.
- */
- rc = demoFlushBuffer(p);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- ofst = lseek(p->fd, iOfst, SEEK_SET);
- if( ofst!=iOfst ){
- return SQLITE_IOERR_READ;
- }
- nRead = read(p->fd, zBuf, iAmt);
-
- if( nRead==iAmt ){
- return SQLITE_OK;
- }else if( nRead>=0 ){
- return SQLITE_IOERR_SHORT_READ;
- }
-
- return SQLITE_IOERR_READ;
-}
-
-/*
-** Write data to a crash-file.
-*/
-static int demoWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- DemoFile *p = (DemoFile*)pFile;
-
- if( p->aBuffer ){
- char *z = (char *)zBuf; /* Pointer to remaining data to write */
- int n = iAmt; /* Number of bytes at z */
- sqlite3_int64 i = iOfst; /* File offset to write to */
-
- while( n>0 ){
- int nCopy; /* Number of bytes to copy into buffer */
-
- /* If the buffer is full, or if this data is not being written directly
- ** following the data already buffered, flush the buffer. Flushing
- ** the buffer is a no-op if it is empty.
- */
- if( p->nBuffer==SQLITE_DEMOVFS_BUFFERSZ || p->iBufferOfst+p->nBuffer!=i ){
- int rc = demoFlushBuffer(p);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- assert( p->nBuffer==0 || p->iBufferOfst+p->nBuffer==i );
- p->iBufferOfst = i - p->nBuffer;
-
- /* Copy as much data as possible into the buffer. */
- nCopy = SQLITE_DEMOVFS_BUFFERSZ - p->nBuffer;
- if( nCopy>n ){
- nCopy = n;
- }
- memcpy(&p->aBuffer[p->nBuffer], z, nCopy);
- p->nBuffer += nCopy;
-
- n -= nCopy;
- i += nCopy;
- z += nCopy;
- }
- }else{
- return demoDirectWrite(p, zBuf, iAmt, iOfst);
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Truncate a file. This is a no-op for this VFS (see header comments at
-** the top of the file).
-*/
-static int demoTruncate(sqlite3_file *pFile, sqlite_int64 size){
-#if 0
- if( ftruncate(((DemoFile *)pFile)->fd, size) ) return SQLITE_IOERR_TRUNCATE;
-#endif
- return SQLITE_OK;
-}
-
-/*
-** Sync the contents of the file to the persistent media.
-*/
-static int demoSync(sqlite3_file *pFile, int flags){
- DemoFile *p = (DemoFile*)pFile;
- int rc;
-
- rc = demoFlushBuffer(p);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- rc = fsync(p->fd);
- return (rc==0 ? SQLITE_OK : SQLITE_IOERR_FSYNC);
-}
-
-/*
-** Write the size of the file in bytes to *pSize.
-*/
-static int demoFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- DemoFile *p = (DemoFile*)pFile;
- int rc; /* Return code from fstat() call */
- struct stat sStat; /* Output of fstat() call */
-
- /* Flush the contents of the buffer to disk. As with the flush in the
- ** demoRead() method, it would be possible to avoid this and save a write
- ** here and there. But in practice this comes up so infrequently it is
- ** not worth the trouble.
- */
- rc = demoFlushBuffer(p);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- rc = fstat(p->fd, &sStat);
- if( rc!=0 ) return SQLITE_IOERR_FSTAT;
- *pSize = sStat.st_size;
- return SQLITE_OK;
-}
-
-/*
-** Locking functions. The xLock() and xUnlock() methods are both no-ops.
-** The xCheckReservedLock() always indicates that no other process holds
-** a reserved lock on the database file. This ensures that if a hot-journal
-** file is found in the file-system it is rolled back.
-*/
-static int demoLock(sqlite3_file *pFile, int eLock){
- return SQLITE_OK;
-}
-static int demoUnlock(sqlite3_file *pFile, int eLock){
- return SQLITE_OK;
-}
-static int demoCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- *pResOut = 0;
- return SQLITE_OK;
-}
-
-/*
-** No xFileControl() verbs are implemented by this VFS.
-*/
-static int demoFileControl(sqlite3_file *pFile, int op, void *pArg){
- return SQLITE_OK;
-}
-
-/*
-** The xSectorSize() and xDeviceCharacteristics() methods. These two
-** may return special values allowing SQLite to optimize file-system
-** access to some extent. But it is also safe to simply return 0.
-*/
-static int demoSectorSize(sqlite3_file *pFile){
- return 0;
-}
-static int demoDeviceCharacteristics(sqlite3_file *pFile){
- return 0;
-}
-
-/*
-** Open a file handle.
-*/
-static int demoOpen(
- sqlite3_vfs *pVfs, /* VFS */
- const char *zName, /* File to open, or 0 for a temp file */
- sqlite3_file *pFile, /* Pointer to DemoFile struct to populate */
- int flags, /* Input SQLITE_OPEN_XXX flags */
- int *pOutFlags /* Output SQLITE_OPEN_XXX flags (or NULL) */
-){
- static const sqlite3_io_methods demoio = {
- 1, /* iVersion */
- demoClose, /* xClose */
- demoRead, /* xRead */
- demoWrite, /* xWrite */
- demoTruncate, /* xTruncate */
- demoSync, /* xSync */
- demoFileSize, /* xFileSize */
- demoLock, /* xLock */
- demoUnlock, /* xUnlock */
- demoCheckReservedLock, /* xCheckReservedLock */
- demoFileControl, /* xFileControl */
- demoSectorSize, /* xSectorSize */
- demoDeviceCharacteristics /* xDeviceCharacteristics */
- };
-
- DemoFile *p = (DemoFile*)pFile; /* Populate this structure */
- int oflags = 0; /* flags to pass to open() call */
- char *aBuf = 0;
-
- if( zName==0 ){
- return SQLITE_IOERR;
- }
-
- if( flags&SQLITE_OPEN_MAIN_JOURNAL ){
- aBuf = (char *)sqlite3_malloc(SQLITE_DEMOVFS_BUFFERSZ);
- if( !aBuf ){
- return SQLITE_NOMEM;
- }
- }
-
- if( flags&SQLITE_OPEN_EXCLUSIVE ) oflags |= O_EXCL;
- if( flags&SQLITE_OPEN_CREATE ) oflags |= O_CREAT;
- if( flags&SQLITE_OPEN_READONLY ) oflags |= O_RDONLY;
- if( flags&SQLITE_OPEN_READWRITE ) oflags |= O_RDWR;
-
- memset(p, 0, sizeof(DemoFile));
- p->fd = open(zName, oflags, 0600);
- if( p->fd<0 ){
- sqlite3_free(aBuf);
- return SQLITE_CANTOPEN;
- }
- p->aBuffer = aBuf;
-
- if( pOutFlags ){
- *pOutFlags = flags;
- }
- p->base.pMethods = &demoio;
- return SQLITE_OK;
-}
-
-/*
-** Delete the file identified by argument zPath. If the dirSync parameter
-** is non-zero, then ensure the file-system modification to delete the
-** file has been synced to disk before returning.
-*/
-static int demoDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- int rc; /* Return code */
-
- rc = unlink(zPath);
- if( rc!=0 && errno==ENOENT ) return SQLITE_OK;
-
- if( rc==0 && dirSync ){
- int dfd; /* File descriptor open on directory */
- int i; /* Iterator variable */
- char zDir[MAXPATHNAME+1]; /* Name of directory containing file zPath */
-
- /* Figure out the directory name from the path of the file deleted. */
- sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath);
- zDir[MAXPATHNAME] = '\0';
- for(i=strlen(zDir); i>1 && zDir[i]!='/'; i++);
- zDir[i] = '\0';
-
- /* Open a file-descriptor on the directory. Sync. Close. */
- dfd = open(zDir, O_RDONLY, 0);
- if( dfd<0 ){
- rc = -1;
- }else{
- rc = fsync(dfd);
- close(dfd);
- }
- }
- return (rc==0 ? SQLITE_OK : SQLITE_IOERR_DELETE);
-}
-
-#ifndef F_OK
-# define F_OK 0
-#endif
-#ifndef R_OK
-# define R_OK 4
-#endif
-#ifndef W_OK
-# define W_OK 2
-#endif
-
-/*
-** Query the file-system to see if the named file exists, is readable or
-** is both readable and writable.
-*/
-static int demoAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- int rc; /* access() return code */
- int eAccess = F_OK; /* Second argument to access() */
-
- assert( flags==SQLITE_ACCESS_EXISTS /* access(zPath, F_OK) */
- || flags==SQLITE_ACCESS_READ /* access(zPath, R_OK) */
- || flags==SQLITE_ACCESS_READWRITE /* access(zPath, R_OK|W_OK) */
- );
-
- if( flags==SQLITE_ACCESS_READWRITE ) eAccess = R_OK|W_OK;
- if( flags==SQLITE_ACCESS_READ ) eAccess = R_OK;
-
- rc = access(zPath, eAccess);
- *pResOut = (rc==0);
- return SQLITE_OK;
-}
-
-/*
-** Argument zPath points to a nul-terminated string containing a file path.
-** If zPath is an absolute path, then it is copied as is into the output
-** buffer. Otherwise, if it is a relative path, then the equivalent full
-** path is written to the output buffer.
-**
-** This function assumes that paths are UNIX style. Specifically, that:
-**
-** 1. Path components are separated by a '/'. and
-** 2. Full paths begin with a '/' character.
-*/
-static int demoFullPathname(
- sqlite3_vfs *pVfs, /* VFS */
- const char *zPath, /* Input path (possibly a relative path) */
- int nPathOut, /* Size of output buffer in bytes */
- char *zPathOut /* Pointer to output buffer */
-){
- char zDir[MAXPATHNAME+1];
- if( zPath[0]=='/' ){
- zDir[0] = '\0';
- }else{
- if( getcwd(zDir, sizeof(zDir))==0 ) return SQLITE_IOERR;
- }
- zDir[MAXPATHNAME] = '\0';
-
- sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath);
- zPathOut[nPathOut-1] = '\0';
-
- return SQLITE_OK;
-}
-
-/*
-** The following four VFS methods:
-**
-** xDlOpen
-** xDlError
-** xDlSym
-** xDlClose
-**
-** are supposed to implement the functionality needed by SQLite to load
-** extensions compiled as shared objects. This simple VFS does not support
-** this functionality, so the following functions are no-ops.
-*/
-static void *demoDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return 0;
-}
-static void demoDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- sqlite3_snprintf(nByte, zErrMsg, "Loadable extensions are not supported");
- zErrMsg[nByte-1] = '\0';
-}
-static void (*demoDlSym(sqlite3_vfs *pVfs, void *pH, const char *z))(void){
- return 0;
-}
-static void demoDlClose(sqlite3_vfs *pVfs, void *pHandle){
- return;
-}
-
-/*
-** Parameter zByte points to a buffer nByte bytes in size. Populate this
-** buffer with pseudo-random data.
-*/
-static int demoRandomness(sqlite3_vfs *pVfs, int nByte, char *zByte){
- return SQLITE_OK;
-}
-
-/*
-** Sleep for at least nMicro microseconds. Return the (approximate) number
-** of microseconds slept for.
-*/
-static int demoSleep(sqlite3_vfs *pVfs, int nMicro){
- sleep(nMicro / 1000000);
- usleep(nMicro % 1000000);
- return nMicro;
-}
-
-/*
-** Set *pTime to the current UTC time expressed as a Julian day. Return
-** SQLITE_OK if successful, or an error code otherwise.
-**
-** http://en.wikipedia.org/wiki/Julian_day
-**
-** This implementation is not very good. The current time is rounded to
-** an integer number of seconds. Also, assuming time_t is a signed 32-bit
-** value, it will stop working some time in the year 2038 AD (the so-called
-** "year 2038" problem that afflicts systems that store time this way).
-*/
-static int demoCurrentTime(sqlite3_vfs *pVfs, double *pTime){
- time_t t = time(0);
- *pTime = t/86400.0 + 2440587.5;
- return SQLITE_OK;
-}
-
-/*
-** This function returns a pointer to the VFS implemented in this file.
-** To make the VFS available to SQLite:
-**
-** sqlite3_vfs_register(sqlite3_demovfs(), 0);
-*/
-sqlite3_vfs *sqlite3_demovfs(void){
- static sqlite3_vfs demovfs = {
- 1, /* iVersion */
- sizeof(DemoFile), /* szOsFile */
- MAXPATHNAME, /* mxPathname */
- 0, /* pNext */
- "demo", /* zName */
- 0, /* pAppData */
- demoOpen, /* xOpen */
- demoDelete, /* xDelete */
- demoAccess, /* xAccess */
- demoFullPathname, /* xFullPathname */
- demoDlOpen, /* xDlOpen */
- demoDlError, /* xDlError */
- demoDlSym, /* xDlSym */
- demoDlClose, /* xDlClose */
- demoRandomness, /* xRandomness */
- demoSleep, /* xSleep */
- demoCurrentTime, /* xCurrentTime */
- };
- return &demovfs;
-}
-
-#endif /* !defined(SQLITE_TEST) || SQLITE_OS_UNIX */
-
-
-#ifdef SQLITE_TEST
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-#if SQLITE_OS_UNIX
-static int SQLITE_TCLAPI register_demovfs(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_vfs_register(sqlite3_demovfs(), 1);
- return TCL_OK;
-}
-static int SQLITE_TCLAPI unregister_demovfs(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_vfs_unregister(sqlite3_demovfs());
- return TCL_OK;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest_demovfs_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "register_demovfs", register_demovfs, 0, 0);
- Tcl_CreateObjCommand(interp, "unregister_demovfs", unregister_demovfs, 0, 0);
- return TCL_OK;
-}
-
-#else
-int Sqlitetest_demovfs_Init(Tcl_Interp *interp){ return TCL_OK; }
-#endif
-
-#endif /* SQLITE_TEST */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_devsym.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_devsym.c
deleted file mode 100644
index 0da6671cf4c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_devsym.c
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
-** 2008 Jan 22
-**
-** 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 contains code that modified the OS layer in order to simulate
-** different device types (by overriding the return values of the
-** xDeviceCharacteristics() and xSectorSize() methods).
-*/
-#if SQLITE_TEST /* This file is used for testing only */
-
-#include "sqlite3.h"
-#include "sqliteInt.h"
-
-/*
-** Maximum pathname length supported by the devsym backend.
-*/
-#define DEVSYM_MAX_PATHNAME 512
-
-/*
-** Name used to identify this VFS.
-*/
-#define DEVSYM_VFS_NAME "devsym"
-#define WRITECRASH_NAME "writecrash"
-
-typedef struct devsym_file devsym_file;
-struct devsym_file {
- sqlite3_file base;
- sqlite3_file *pReal;
-};
-
-/*
-** Method declarations for devsym_file.
-*/
-static int devsymClose(sqlite3_file*);
-static int devsymRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int devsymWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int devsymTruncate(sqlite3_file*, sqlite3_int64 size);
-static int devsymSync(sqlite3_file*, int flags);
-static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int devsymLock(sqlite3_file*, int);
-static int devsymUnlock(sqlite3_file*, int);
-static int devsymCheckReservedLock(sqlite3_file*, int *);
-static int devsymFileControl(sqlite3_file*, int op, void *pArg);
-static int devsymSectorSize(sqlite3_file*);
-static int devsymDeviceCharacteristics(sqlite3_file*);
-static int devsymShmLock(sqlite3_file*,int,int,int);
-static int devsymShmMap(sqlite3_file*,int,int,int, void volatile **);
-static void devsymShmBarrier(sqlite3_file*);
-static int devsymShmUnmap(sqlite3_file*,int);
-
-/*
-** Method declarations for devsym_vfs.
-*/
-static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int devsymFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-static void *devsymDlOpen(sqlite3_vfs*, const char *zFilename);
-static void devsymDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
-static void devsymDlClose(sqlite3_vfs*, void*);
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int devsymSleep(sqlite3_vfs*, int microseconds);
-static int devsymCurrentTime(sqlite3_vfs*, double*);
-
-struct DevsymGlobal {
- sqlite3_vfs *pVfs;
- int iDeviceChar;
- int iSectorSize;
- int nWriteCrash;
-};
-struct DevsymGlobal g = {0, 0, 512, 0};
-
-/*
-** Close an devsym-file.
-*/
-static int devsymClose(sqlite3_file *pFile){
- devsym_file *p = (devsym_file *)pFile;
- sqlite3OsClose(p->pReal);
- return SQLITE_OK;
-}
-
-/*
-** Read data from an devsym-file.
-*/
-static int devsymRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
-}
-
-/*
-** Write data to an devsym-file.
-*/
-static int devsymWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
-}
-
-/*
-** Truncate an devsym-file.
-*/
-static int devsymTruncate(sqlite3_file *pFile, sqlite_int64 size){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsTruncate(p->pReal, size);
-}
-
-/*
-** Sync an devsym-file.
-*/
-static int devsymSync(sqlite3_file *pFile, int flags){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsSync(p->pReal, flags);
-}
-
-/*
-** Return the current file-size of an devsym-file.
-*/
-static int devsymFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsFileSize(p->pReal, pSize);
-}
-
-/*
-** Lock an devsym-file.
-*/
-static int devsymLock(sqlite3_file *pFile, int eLock){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsLock(p->pReal, eLock);
-}
-
-/*
-** Unlock an devsym-file.
-*/
-static int devsymUnlock(sqlite3_file *pFile, int eLock){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsUnlock(p->pReal, eLock);
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an devsym-file.
-*/
-static int devsymCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsCheckReservedLock(p->pReal, pResOut);
-}
-
-/*
-** File control method. For custom operations on an devsym-file.
-*/
-static int devsymFileControl(sqlite3_file *pFile, int op, void *pArg){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsFileControl(p->pReal, op, pArg);
-}
-
-/*
-** Return the sector-size in bytes for an devsym-file.
-*/
-static int devsymSectorSize(sqlite3_file *pFile){
- return g.iSectorSize;
-}
-
-/*
-** Return the device characteristic flags supported by an devsym-file.
-*/
-static int devsymDeviceCharacteristics(sqlite3_file *pFile){
- return g.iDeviceChar;
-}
-
-/*
-** Shared-memory methods are all pass-thrus.
-*/
-static int devsymShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsShmLock(p->pReal, ofst, n, flags);
-}
-static int devsymShmMap(
- sqlite3_file *pFile,
- int iRegion,
- int szRegion,
- int isWrite,
- void volatile **pp
-){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
-}
-static void devsymShmBarrier(sqlite3_file *pFile){
- devsym_file *p = (devsym_file *)pFile;
- sqlite3OsShmBarrier(p->pReal);
-}
-static int devsymShmUnmap(sqlite3_file *pFile, int delFlag){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsShmUnmap(p->pReal, delFlag);
-}
-
-
-
-/*
-** Open an devsym file handle.
-*/
-static int devsymOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
-static sqlite3_io_methods devsym_io_methods = {
- 2, /* iVersion */
- devsymClose, /* xClose */
- devsymRead, /* xRead */
- devsymWrite, /* xWrite */
- devsymTruncate, /* xTruncate */
- devsymSync, /* xSync */
- devsymFileSize, /* xFileSize */
- devsymLock, /* xLock */
- devsymUnlock, /* xUnlock */
- devsymCheckReservedLock, /* xCheckReservedLock */
- devsymFileControl, /* xFileControl */
- devsymSectorSize, /* xSectorSize */
- devsymDeviceCharacteristics, /* xDeviceCharacteristics */
- devsymShmMap, /* xShmMap */
- devsymShmLock, /* xShmLock */
- devsymShmBarrier, /* xShmBarrier */
- devsymShmUnmap /* xShmUnmap */
-};
-
- int rc;
- devsym_file *p = (devsym_file *)pFile;
- p->pReal = (sqlite3_file *)&p[1];
- rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags);
- if( p->pReal->pMethods ){
- pFile->pMethods = &devsym_io_methods;
- }
- return rc;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int devsymDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- return sqlite3OsDelete(g.pVfs, zPath, dirSync);
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int devsymAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut);
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
-*/
-static int devsymFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- return sqlite3OsFullPathname(g.pVfs, zPath, nOut, zOut);
-}
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *devsymDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return sqlite3OsDlOpen(g.pVfs, zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void devsymDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- sqlite3OsDlError(g.pVfs, nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*devsymDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return sqlite3OsDlSym(g.pVfs, p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void devsymDlClose(sqlite3_vfs *pVfs, void *pHandle){
- sqlite3OsDlClose(g.pVfs, pHandle);
-}
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int devsymRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return sqlite3OsRandomness(g.pVfs, nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int devsymSleep(sqlite3_vfs *pVfs, int nMicro){
- return sqlite3OsSleep(g.pVfs, nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
-}
-
-/*
-** Return the sector-size in bytes for an writecrash-file.
-*/
-static int writecrashSectorSize(sqlite3_file *pFile){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsSectorSize(p->pReal);
-}
-
-/*
-** Return the device characteristic flags supported by an writecrash-file.
-*/
-static int writecrashDeviceCharacteristics(sqlite3_file *pFile){
- devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsDeviceCharacteristics(p->pReal);
-}
-
-/*
-** Write data to an writecrash-file.
-*/
-static int writecrashWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- devsym_file *p = (devsym_file *)pFile;
- if( g.nWriteCrash>0 ){
- g.nWriteCrash--;
- if( g.nWriteCrash==0 ) abort();
- }
- return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
-}
-
-/*
-** Open an writecrash file handle.
-*/
-static int writecrashOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
-static sqlite3_io_methods writecrash_io_methods = {
- 2, /* iVersion */
- devsymClose, /* xClose */
- devsymRead, /* xRead */
- writecrashWrite, /* xWrite */
- devsymTruncate, /* xTruncate */
- devsymSync, /* xSync */
- devsymFileSize, /* xFileSize */
- devsymLock, /* xLock */
- devsymUnlock, /* xUnlock */
- devsymCheckReservedLock, /* xCheckReservedLock */
- devsymFileControl, /* xFileControl */
- writecrashSectorSize, /* xSectorSize */
- writecrashDeviceCharacteristics, /* xDeviceCharacteristics */
- devsymShmMap, /* xShmMap */
- devsymShmLock, /* xShmLock */
- devsymShmBarrier, /* xShmBarrier */
- devsymShmUnmap /* xShmUnmap */
-};
-
- int rc;
- devsym_file *p = (devsym_file *)pFile;
- p->pReal = (sqlite3_file *)&p[1];
- rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags);
- if( p->pReal->pMethods ){
- pFile->pMethods = &writecrash_io_methods;
- }
- return rc;
-}
-
-static sqlite3_vfs devsym_vfs = {
- 2, /* iVersion */
- sizeof(devsym_file), /* szOsFile */
- DEVSYM_MAX_PATHNAME, /* mxPathname */
- 0, /* pNext */
- DEVSYM_VFS_NAME, /* zName */
- 0, /* pAppData */
- devsymOpen, /* xOpen */
- devsymDelete, /* xDelete */
- devsymAccess, /* xAccess */
- devsymFullPathname, /* xFullPathname */
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- devsymDlOpen, /* xDlOpen */
- devsymDlError, /* xDlError */
- devsymDlSym, /* xDlSym */
- devsymDlClose, /* xDlClose */
-#else
- 0, /* xDlOpen */
- 0, /* xDlError */
- 0, /* xDlSym */
- 0, /* xDlClose */
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
- devsymRandomness, /* xRandomness */
- devsymSleep, /* xSleep */
- devsymCurrentTime, /* xCurrentTime */
- 0, /* xGetLastError */
- 0 /* xCurrentTimeInt64 */
-};
-
-static sqlite3_vfs writecrash_vfs = {
- 2, /* iVersion */
- sizeof(devsym_file), /* szOsFile */
- DEVSYM_MAX_PATHNAME, /* mxPathname */
- 0, /* pNext */
- WRITECRASH_NAME, /* zName */
- 0, /* pAppData */
- writecrashOpen, /* xOpen */
- devsymDelete, /* xDelete */
- devsymAccess, /* xAccess */
- devsymFullPathname, /* xFullPathname */
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- devsymDlOpen, /* xDlOpen */
- devsymDlError, /* xDlError */
- devsymDlSym, /* xDlSym */
- devsymDlClose, /* xDlClose */
-#else
- 0, /* xDlOpen */
- 0, /* xDlError */
- 0, /* xDlSym */
- 0, /* xDlClose */
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
- devsymRandomness, /* xRandomness */
- devsymSleep, /* xSleep */
- devsymCurrentTime, /* xCurrentTime */
- 0, /* xGetLastError */
- 0 /* xCurrentTimeInt64 */
-};
-
-
-/*
-** This procedure registers the devsym vfs with SQLite. If the argument is
-** true, the devsym vfs becomes the new default vfs. It is the only publicly
-** available function in this file.
-*/
-void devsym_register(int iDeviceChar, int iSectorSize){
-
- if( g.pVfs==0 ){
- g.pVfs = sqlite3_vfs_find(0);
- devsym_vfs.szOsFile += g.pVfs->szOsFile;
- writecrash_vfs.szOsFile += g.pVfs->szOsFile;
- sqlite3_vfs_register(&devsym_vfs, 0);
- sqlite3_vfs_register(&writecrash_vfs, 0);
- }
- if( iDeviceChar>=0 ){
- g.iDeviceChar = iDeviceChar;
- }else{
- g.iDeviceChar = 0;
- }
- if( iSectorSize>=0 ){
- g.iSectorSize = iSectorSize;
- }else{
- g.iSectorSize = 512;
- }
-}
-
-void devsym_unregister(){
- sqlite3_vfs_unregister(&devsym_vfs);
- g.pVfs = 0;
- g.iDeviceChar = 0;
- g.iSectorSize = 0;
-}
-
-void devsym_crash_on_write(int nWrite){
- if( g.pVfs==0 ){
- g.pVfs = sqlite3_vfs_find(0);
- devsym_vfs.szOsFile += g.pVfs->szOsFile;
- writecrash_vfs.szOsFile += g.pVfs->szOsFile;
- sqlite3_vfs_register(&devsym_vfs, 0);
- sqlite3_vfs_register(&writecrash_vfs, 0);
- }
- g.nWriteCrash = nWrite;
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_fs.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_fs.c
deleted file mode 100644
index 8192beb99bd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_fs.c
+++ /dev/null
@@ -1,925 +0,0 @@
-/*
-** 2013 Jan 11
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the virtual table interfaces. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library.
-**
-** The FS virtual table is created as follows:
-**
-** CREATE VIRTUAL TABLE tbl USING fs(idx);
-**
-** where idx is the name of a table in the db with 2 columns. The virtual
-** table also has two columns - file path and file contents.
-**
-** The first column of table idx must be an IPK, and the second contains file
-** paths. For example:
-**
-** CREATE TABLE idx(id INTEGER PRIMARY KEY, path TEXT);
-** INSERT INTO idx VALUES(4, '/etc/passwd');
-**
-** Adding the row to the idx table automatically creates a row in the
-** virtual table with rowid=4, path=/etc/passwd and a text field that
-** contains data read from file /etc/passwd on disk.
-**
-*************************************************************************
-** Virtual table module "fsdir"
-**
-** This module is designed to be used as a read-only eponymous virtual table.
-** Its schema is as follows:
-**
-** CREATE TABLE fsdir(dir TEXT, name TEXT);
-**
-** When queried, a WHERE term of the form "dir = $dir" must be provided. The
-** virtual table then appears to have one row for each entry in file-system
-** directory $dir. Column dir contains a copy of $dir, and column "name"
-** contains the name of the directory entry.
-**
-** If the specified $dir cannot be opened or is not a directory, it is not
-** an error. The virtual table appears to be empty in this case.
-**
-*************************************************************************
-** Virtual table module "fstree"
-**
-** This module is also a read-only eponymous virtual table with the
-** following schema:
-**
-** CREATE TABLE fstree(path TEXT, size INT, data BLOB);
-**
-** Running a "SELECT * FROM fstree" query on this table returns the entire
-** contents of the file-system, starting at "/". To restrict the search
-** space, the virtual table supports LIKE and GLOB constraints on the
-** 'path' column. For example:
-**
-** SELECT * FROM fstree WHERE path LIKE '/home/dan/sqlite/%'
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#if SQLITE_OS_UNIX || defined(__MINGW_H)
-# include <unistd.h>
-# include <dirent.h>
-# ifndef DIRENT
-# define DIRENT dirent
-# endif
-#endif
-#if SQLITE_OS_WIN
-# include <io.h>
-# if !defined(__MINGW_H)
-# include "test_windirent.h"
-# endif
-# ifndef S_ISREG
-# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-# endif
-#endif
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-typedef struct fs_vtab fs_vtab;
-typedef struct fs_cursor fs_cursor;
-
-/*
-** A fs virtual-table object
-*/
-struct fs_vtab {
- sqlite3_vtab base;
- sqlite3 *db;
- char *zDb; /* Name of db containing zTbl */
- char *zTbl; /* Name of docid->file map table */
-};
-
-/* A fs cursor object */
-struct fs_cursor {
- sqlite3_vtab_cursor base;
- sqlite3_stmt *pStmt;
- char *zBuf;
- int nBuf;
- int nAlloc;
-};
-
-/*************************************************************************
-** Start of fsdir implementation.
-*/
-typedef struct FsdirVtab FsdirVtab;
-typedef struct FsdirCsr FsdirCsr;
-struct FsdirVtab {
- sqlite3_vtab base;
-};
-
-struct FsdirCsr {
- sqlite3_vtab_cursor base;
- char *zDir; /* Buffer containing directory scanned */
- DIR *pDir; /* Open directory */
- sqlite3_int64 iRowid;
- struct DIRENT entry; /* Current entry */
-};
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the fsdir virtual table.
-**
-** The argv[] array contains the following:
-**
-** argv[0] -> module name ("fs")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> other module argument fields.
-*/
-static int fsdirConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- FsdirVtab *pTab;
-
- if( argc!=3 ){
- *pzErr = sqlite3_mprintf("wrong number of arguments");
- return SQLITE_ERROR;
- }
-
- pTab = (FsdirVtab *)sqlite3_malloc(sizeof(FsdirVtab));
- if( !pTab ) return SQLITE_NOMEM;
- memset(pTab, 0, sizeof(FsdirVtab));
-
- *ppVtab = &pTab->base;
- sqlite3_declare_vtab(db, "CREATE TABLE xyz(dir, name);");
-
- return SQLITE_OK;
-}
-
-/*
-** xDestroy/xDisconnect implementation.
-*/
-static int fsdirDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** xBestIndex implementation. The only constraint supported is:
-**
-** (dir = ?)
-*/
-static int fsdirBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int ii;
-
- pIdxInfo->estimatedCost = 1000000000.0;
-
- for(ii=0; ii<pIdxInfo->nConstraint; ii++){
- struct sqlite3_index_constraint const *p = &pIdxInfo->aConstraint[ii];
- if( p->iColumn==0 && p->usable && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
- struct sqlite3_index_constraint_usage *pUsage;
- pUsage = &pIdxInfo->aConstraintUsage[ii];
- pUsage->omit = 1;
- pUsage->argvIndex = 1;
- pIdxInfo->idxNum = 1;
- pIdxInfo->estimatedCost = 1.0;
- break;
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** xOpen implementation.
-**
-** Open a new fsdir cursor.
-*/
-static int fsdirOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- FsdirCsr *pCur;
- /* Allocate an extra 256 bytes because it is undefined how big dirent.d_name
- ** is and we need enough space. Linux provides plenty already, but
- ** Solaris only provides one byte. */
- pCur = (FsdirCsr*)sqlite3_malloc(sizeof(FsdirCsr)+256);
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(FsdirCsr));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a fsdir cursor.
-*/
-static int fsdirClose(sqlite3_vtab_cursor *cur){
- FsdirCsr *pCur = (FsdirCsr*)cur;
- if( pCur->pDir ) closedir(pCur->pDir);
- sqlite3_free(pCur->zDir);
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Skip the cursor to the next entry.
-*/
-static int fsdirNext(sqlite3_vtab_cursor *cur){
- FsdirCsr *pCsr = (FsdirCsr*)cur;
-
- if( pCsr->pDir ){
- struct DIRENT *pRes = 0;
-#if defined(__MINGW_H)
- pRes = readdir(pCsr->pDir);
- if( pRes!=0 ){
- memcpy(&pCsr->entry, pRes, sizeof(struct DIRENT));
- }
-#else
- readdir_r(pCsr->pDir, &pCsr->entry, &pRes);
-#endif
- if( pRes==0 ){
- closedir(pCsr->pDir);
- pCsr->pDir = 0;
- }
- pCsr->iRowid++;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** xFilter method implementation.
-*/
-static int fsdirFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- FsdirCsr *pCsr = (FsdirCsr*)pVtabCursor;
- const char *zDir;
- int nDir;
-
-
- if( idxNum!=1 || argc!=1 ){
- return SQLITE_ERROR;
- }
-
- pCsr->iRowid = 0;
- sqlite3_free(pCsr->zDir);
- if( pCsr->pDir ){
- closedir(pCsr->pDir);
- pCsr->pDir = 0;
- }
-
- zDir = (const char*)sqlite3_value_text(argv[0]);
- nDir = sqlite3_value_bytes(argv[0]);
- pCsr->zDir = sqlite3_malloc(nDir+1);
- if( pCsr->zDir==0 ) return SQLITE_NOMEM;
- memcpy(pCsr->zDir, zDir, nDir+1);
-
- pCsr->pDir = opendir(pCsr->zDir);
- return fsdirNext(pVtabCursor);
-}
-
-/*
-** xEof method implementation.
-*/
-static int fsdirEof(sqlite3_vtab_cursor *cur){
- FsdirCsr *pCsr = (FsdirCsr*)cur;
- return pCsr->pDir==0;
-}
-
-/*
-** xColumn method implementation.
-*/
-static int fsdirColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- FsdirCsr *pCsr = (FsdirCsr*)cur;
- switch( i ){
- case 0: /* dir */
- sqlite3_result_text(ctx, pCsr->zDir, -1, SQLITE_STATIC);
- break;
-
- case 1: /* name */
- sqlite3_result_text(ctx, pCsr->entry.d_name, -1, SQLITE_TRANSIENT);
- break;
-
- default:
- assert( 0 );
- }
-
- return SQLITE_OK;
-}
-
-/*
-** xRowid method implementation.
-*/
-static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- FsdirCsr *pCsr = (FsdirCsr*)cur;
- *pRowid = pCsr->iRowid;
- return SQLITE_OK;
-}
-/*
-** End of fsdir implementation.
-*************************************************************************/
-
-/*************************************************************************
-** Start of fstree implementation.
-*/
-typedef struct FstreeVtab FstreeVtab;
-typedef struct FstreeCsr FstreeCsr;
-struct FstreeVtab {
- sqlite3_vtab base;
- sqlite3 *db;
-};
-
-struct FstreeCsr {
- sqlite3_vtab_cursor base;
- sqlite3_stmt *pStmt; /* Statement to list paths */
- int fd; /* File descriptor open on current path */
-};
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the fstree virtual table.
-**
-** The argv[] array contains the following:
-**
-** argv[0] -> module name ("fs")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> other module argument fields.
-*/
-static int fstreeConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- FstreeVtab *pTab;
-
- if( argc!=3 ){
- *pzErr = sqlite3_mprintf("wrong number of arguments");
- return SQLITE_ERROR;
- }
-
- pTab = (FstreeVtab *)sqlite3_malloc(sizeof(FstreeVtab));
- if( !pTab ) return SQLITE_NOMEM;
- memset(pTab, 0, sizeof(FstreeVtab));
- pTab->db = db;
-
- *ppVtab = &pTab->base;
- sqlite3_declare_vtab(db, "CREATE TABLE xyz(path, size, data);");
-
- return SQLITE_OK;
-}
-
-/*
-** xDestroy/xDisconnect implementation.
-*/
-static int fstreeDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** xBestIndex implementation. The only constraint supported is:
-**
-** (dir = ?)
-*/
-static int fstreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int ii;
-
- for(ii=0; ii<pIdxInfo->nConstraint; ii++){
- struct sqlite3_index_constraint const *p = &pIdxInfo->aConstraint[ii];
- if( p->iColumn==0 && p->usable && (
- p->op==SQLITE_INDEX_CONSTRAINT_GLOB
- || p->op==SQLITE_INDEX_CONSTRAINT_LIKE
- || p->op==SQLITE_INDEX_CONSTRAINT_EQ
- )){
- struct sqlite3_index_constraint_usage *pUsage;
- pUsage = &pIdxInfo->aConstraintUsage[ii];
- pIdxInfo->idxNum = p->op;
- pUsage->argvIndex = 1;
- pIdxInfo->estimatedCost = 100000.0;
- return SQLITE_OK;
- }
- }
-
- pIdxInfo->estimatedCost = 1000000000.0;
- return SQLITE_OK;
-}
-
-/*
-** xOpen implementation.
-**
-** Open a new fstree cursor.
-*/
-static int fstreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- FstreeCsr *pCur;
- pCur = (FstreeCsr*)sqlite3_malloc(sizeof(FstreeCsr));
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(FstreeCsr));
- pCur->fd = -1;
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-static void fstreeCloseFd(FstreeCsr *pCsr){
- if( pCsr->fd>=0 ){
- close(pCsr->fd);
- pCsr->fd = -1;
- }
-}
-
-/*
-** Close a fstree cursor.
-*/
-static int fstreeClose(sqlite3_vtab_cursor *cur){
- FstreeCsr *pCsr = (FstreeCsr*)cur;
- sqlite3_finalize(pCsr->pStmt);
- fstreeCloseFd(pCsr);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Skip the cursor to the next entry.
-*/
-static int fstreeNext(sqlite3_vtab_cursor *cur){
- FstreeCsr *pCsr = (FstreeCsr*)cur;
- int rc;
-
- fstreeCloseFd(pCsr);
- rc = sqlite3_step(pCsr->pStmt);
- if( rc!=SQLITE_ROW ){
- rc = sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- }else{
- rc = SQLITE_OK;
- pCsr->fd = open((const char*)sqlite3_column_text(pCsr->pStmt, 0), O_RDONLY);
- }
-
- return rc;
-}
-
-/*
-** xFilter method implementation.
-*/
-static int fstreeFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- FstreeCsr *pCsr = (FstreeCsr*)pVtabCursor;
- FstreeVtab *pTab = (FstreeVtab*)(pCsr->base.pVtab);
- int rc;
- const char *zSql =
-"WITH r(d) AS ("
-" SELECT CASE WHEN dir=?2 THEN ?3 ELSE dir END || '/' || name "
-" FROM fsdir WHERE dir=?1 AND name NOT LIKE '.%'"
-" UNION ALL"
-" SELECT dir || '/' || name FROM r, fsdir WHERE dir=d AND name NOT LIKE '.%'"
-") SELECT d FROM r;";
-
- char *zRoot;
- int nRoot;
- char *zPrefix;
- int nPrefix;
- const char *zDir;
- int nDir;
- char aWild[2] = { '\0', '\0' };
-
-#if SQLITE_OS_WIN
- const char *zDrive = windirent_getenv("fstreeDrive");
- if( zDrive==0 ){
- zDrive = windirent_getenv("SystemDrive");
- }
- zRoot = sqlite3_mprintf("%s%c", zDrive, '/');
- nRoot = sqlite3Strlen30(zRoot);
- zPrefix = sqlite3_mprintf("%s", zDrive);
- nPrefix = sqlite3Strlen30(zPrefix);
-#else
- zRoot = "/";
- nRoot = 1;
- zPrefix = "";
- nPrefix = 0;
-#endif
-
- zDir = zRoot;
- nDir = nRoot;
-
- fstreeCloseFd(pCsr);
- sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
- if( rc!=SQLITE_OK ) return rc;
-
- if( idxNum ){
- const char *zQuery = (const char*)sqlite3_value_text(argv[0]);
- switch( idxNum ){
- case SQLITE_INDEX_CONSTRAINT_GLOB:
- aWild[0] = '*';
- aWild[1] = '?';
- break;
- case SQLITE_INDEX_CONSTRAINT_LIKE:
- aWild[0] = '_';
- aWild[1] = '%';
- break;
- }
-
- if( sqlite3_strnicmp(zQuery, zPrefix, nPrefix)==0 ){
- int i;
- for(i=nPrefix; zQuery[i]; i++){
- if( zQuery[i]==aWild[0] || zQuery[i]==aWild[1] ) break;
- if( zQuery[i]=='/' ) nDir = i;
- }
- zDir = zQuery;
- }
- }
- if( nDir==0 ) nDir = 1;
-
- sqlite3_bind_text(pCsr->pStmt, 1, zDir, nDir, SQLITE_TRANSIENT);
- sqlite3_bind_text(pCsr->pStmt, 2, zRoot, nRoot, SQLITE_TRANSIENT);
- sqlite3_bind_text(pCsr->pStmt, 3, zPrefix, nPrefix, SQLITE_TRANSIENT);
-
-#if SQLITE_OS_WIN
- sqlite3_free(zPrefix);
- sqlite3_free(zRoot);
-#endif
-
- return fstreeNext(pVtabCursor);
-}
-
-/*
-** xEof method implementation.
-*/
-static int fstreeEof(sqlite3_vtab_cursor *cur){
- FstreeCsr *pCsr = (FstreeCsr*)cur;
- return pCsr->pStmt==0;
-}
-
-/*
-** xColumn method implementation.
-*/
-static int fstreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- FstreeCsr *pCsr = (FstreeCsr*)cur;
- if( i==0 ){ /* path */
- sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, 0));
- }else{
- struct stat sBuf;
- fstat(pCsr->fd, &sBuf);
-
- if( S_ISREG(sBuf.st_mode) ){
- if( i==1 ){
- sqlite3_result_int64(ctx, sBuf.st_size);
- }else{
- int nRead;
- char *aBuf = sqlite3_malloc(sBuf.st_mode+1);
- if( !aBuf ) return SQLITE_NOMEM;
- nRead = read(pCsr->fd, aBuf, sBuf.st_mode);
- if( nRead!=sBuf.st_mode ){
- return SQLITE_IOERR;
- }
- sqlite3_result_blob(ctx, aBuf, nRead, SQLITE_TRANSIENT);
- sqlite3_free(aBuf);
- }
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** xRowid method implementation.
-*/
-static int fstreeRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- *pRowid = 0;
- return SQLITE_OK;
-}
-/*
-** End of fstree implementation.
-*************************************************************************/
-
-
-
-
-/*
-** This function is the implementation of both the xConnect and xCreate
-** methods of the fs virtual table.
-**
-** The argv[] array contains the following:
-**
-** argv[0] -> module name ("fs")
-** argv[1] -> database name
-** argv[2] -> table name
-** argv[...] -> other module argument fields.
-*/
-static int fsConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- fs_vtab *pVtab;
- int nByte;
- const char *zTbl;
- const char *zDb = argv[1];
-
- if( argc!=4 ){
- *pzErr = sqlite3_mprintf("wrong number of arguments");
- return SQLITE_ERROR;
- }
- zTbl = argv[3];
-
- nByte = sizeof(fs_vtab) + (int)strlen(zTbl) + 1 + (int)strlen(zDb) + 1;
- pVtab = (fs_vtab *)sqlite3MallocZero( nByte );
- if( !pVtab ) return SQLITE_NOMEM;
-
- pVtab->zTbl = (char *)&pVtab[1];
- pVtab->zDb = &pVtab->zTbl[strlen(zTbl)+1];
- pVtab->db = db;
- memcpy(pVtab->zTbl, zTbl, strlen(zTbl));
- memcpy(pVtab->zDb, zDb, strlen(zDb));
- *ppVtab = &pVtab->base;
- sqlite3_declare_vtab(db, "CREATE TABLE x(path TEXT, data TEXT)");
-
- return SQLITE_OK;
-}
-/* Note that for this virtual table, the xCreate and xConnect
-** methods are identical. */
-
-static int fsDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-/* The xDisconnect and xDestroy methods are also the same */
-
-/*
-** Open a new fs cursor.
-*/
-static int fsOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- fs_cursor *pCur;
- pCur = sqlite3MallocZero(sizeof(fs_cursor));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a fs cursor.
-*/
-static int fsClose(sqlite3_vtab_cursor *cur){
- fs_cursor *pCur = (fs_cursor *)cur;
- sqlite3_finalize(pCur->pStmt);
- sqlite3_free(pCur->zBuf);
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-static int fsNext(sqlite3_vtab_cursor *cur){
- fs_cursor *pCur = (fs_cursor *)cur;
- int rc;
-
- rc = sqlite3_step(pCur->pStmt);
- if( rc==SQLITE_ROW || rc==SQLITE_DONE ) rc = SQLITE_OK;
-
- return rc;
-}
-
-static int fsFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- int rc;
- fs_cursor *pCur = (fs_cursor *)pVtabCursor;
- fs_vtab *p = (fs_vtab *)(pVtabCursor->pVtab);
-
- assert( (idxNum==0 && argc==0) || (idxNum==1 && argc==1) );
- if( idxNum==1 ){
- char *zStmt = sqlite3_mprintf(
- "SELECT * FROM %Q.%Q WHERE rowid=?", p->zDb, p->zTbl);
- if( !zStmt ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v2(p->db, zStmt, -1, &pCur->pStmt, 0);
- sqlite3_free(zStmt);
- if( rc==SQLITE_OK ){
- sqlite3_bind_value(pCur->pStmt, 1, argv[0]);
- }
- }else{
- char *zStmt = sqlite3_mprintf("SELECT * FROM %Q.%Q", p->zDb, p->zTbl);
- if( !zStmt ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v2(p->db, zStmt, -1, &pCur->pStmt, 0);
- sqlite3_free(zStmt);
- }
-
- if( rc==SQLITE_OK ){
- rc = fsNext(pVtabCursor);
- }
- return rc;
-}
-
-static int fsColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- fs_cursor *pCur = (fs_cursor*)cur;
-
- assert( i==0 || i==1 || i==2 );
- if( i==0 ){
- sqlite3_result_value(ctx, sqlite3_column_value(pCur->pStmt, 0));
- }else{
- const char *zFile = (const char *)sqlite3_column_text(pCur->pStmt, 1);
- struct stat sbuf;
- int fd;
-
- int n;
- fd = open(zFile, O_RDONLY);
- if( fd<0 ) return SQLITE_IOERR;
- fstat(fd, &sbuf);
-
- if( sbuf.st_size>=pCur->nAlloc ){
- int nNew = sbuf.st_size*2;
- char *zNew;
- if( nNew<1024 ) nNew = 1024;
-
- zNew = sqlite3Realloc(pCur->zBuf, nNew);
- if( zNew==0 ){
- close(fd);
- return SQLITE_NOMEM;
- }
- pCur->zBuf = zNew;
- pCur->nAlloc = nNew;
- }
-
- n = (int)read(fd, pCur->zBuf, sbuf.st_size);
- close(fd);
- if( n!=sbuf.st_size ) return SQLITE_ERROR;
- pCur->nBuf = sbuf.st_size;
- pCur->zBuf[pCur->nBuf] = '\0';
-
- sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT);
- }
- return SQLITE_OK;
-}
-
-static int fsRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- fs_cursor *pCur = (fs_cursor*)cur;
- *pRowid = sqlite3_column_int64(pCur->pStmt, 0);
- return SQLITE_OK;
-}
-
-static int fsEof(sqlite3_vtab_cursor *cur){
- fs_cursor *pCur = (fs_cursor*)cur;
- return (sqlite3_data_count(pCur->pStmt)==0);
-}
-
-static int fsBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- int ii;
-
- for(ii=0; ii<pIdxInfo->nConstraint; ii++){
- struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
- if( pCons->iColumn<0 && pCons->usable
- && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
- struct sqlite3_index_constraint_usage *pUsage;
- pUsage = &pIdxInfo->aConstraintUsage[ii];
- pUsage->omit = 0;
- pUsage->argvIndex = 1;
- pIdxInfo->idxNum = 1;
- pIdxInfo->estimatedCost = 1.0;
- break;
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** A virtual table module that provides read-only access to a
-** Tcl global variable namespace.
-*/
-static sqlite3_module fsModule = {
- 0, /* iVersion */
- fsConnect,
- fsConnect,
- fsBestIndex,
- fsDisconnect,
- fsDisconnect,
- fsOpen, /* xOpen - open a cursor */
- fsClose, /* xClose - close a cursor */
- fsFilter, /* xFilter - configure scan constraints */
- fsNext, /* xNext - advance a cursor */
- fsEof, /* xEof - check for end of scan */
- fsColumn, /* xColumn - read data */
- fsRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-static sqlite3_module fsdirModule = {
- 0, /* iVersion */
- fsdirConnect, /* xCreate */
- fsdirConnect, /* xConnect */
- fsdirBestIndex, /* xBestIndex */
- fsdirDisconnect, /* xDisconnect */
- fsdirDisconnect, /* xDestroy */
- fsdirOpen, /* xOpen - open a cursor */
- fsdirClose, /* xClose - close a cursor */
- fsdirFilter, /* xFilter - configure scan constraints */
- fsdirNext, /* xNext - advance a cursor */
- fsdirEof, /* xEof - check for end of scan */
- fsdirColumn, /* xColumn - read data */
- fsdirRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-static sqlite3_module fstreeModule = {
- 0, /* iVersion */
- fstreeConnect, /* xCreate */
- fstreeConnect, /* xConnect */
- fstreeBestIndex, /* xBestIndex */
- fstreeDisconnect, /* xDisconnect */
- fstreeDisconnect, /* xDestroy */
- fstreeOpen, /* xOpen - open a cursor */
- fstreeClose, /* xClose - close a cursor */
- fstreeFilter, /* xFilter - configure scan constraints */
- fstreeNext, /* xNext - advance a cursor */
- fstreeEof, /* xEof - check for end of scan */
- fstreeColumn, /* xColumn - read data */
- fstreeRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
-
-/*
-** Register the echo virtual table module.
-*/
-static int SQLITE_TCLAPI register_fs_module(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_create_module(db, "fs", &fsModule, (void *)interp);
- sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
- sqlite3_create_module(db, "fstree", &fstreeModule, 0);
-#endif
- return TCL_OK;
-}
-
-#endif
-
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetestfs_Init(Tcl_Interp *interp){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- void *clientData;
- } aObjCmd[] = {
- { "register_fs_module", register_fs_module, 0 },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
- aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
- }
-#endif
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_func.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_func.c
deleted file mode 100644
index 2a7103f88ef..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_func.c
+++ /dev/null
@@ -1,933 +0,0 @@
-/*
-** 2008 March 19
-**
-** 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.
-**
-*************************************************************************
-** Code for testing all sorts of SQLite interfaces. This code
-** implements new SQL functions used by the test scripts.
-*/
-#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-/*
-** Allocate nByte bytes of space using sqlite3_malloc(). If the
-** allocation fails, call sqlite3_result_error_nomem() to notify
-** the database handle that malloc() has failed.
-*/
-static void *testContextMalloc(sqlite3_context *context, int nByte){
- char *z = sqlite3_malloc(nByte);
- if( !z && nByte>0 ){
- sqlite3_result_error_nomem(context);
- }
- return z;
-}
-
-/*
-** This function generates a string of random characters. Used for
-** generating test data.
-*/
-static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){
- static const unsigned char zSrc[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789"
- ".-!,:*^+=_|?/<> ";
- int iMin, iMax, n, r, i;
- unsigned char zBuf[1000];
-
- /* It used to be possible to call randstr() with any number of arguments,
- ** but now it is registered with SQLite as requiring exactly 2.
- */
- assert(argc==2);
-
- iMin = sqlite3_value_int(argv[0]);
- if( iMin<0 ) iMin = 0;
- if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
- iMax = sqlite3_value_int(argv[1]);
- if( iMax<iMin ) iMax = iMin;
- if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
- n = iMin;
- if( iMax>iMin ){
- sqlite3_randomness(sizeof(r), &r);
- r &= 0x7fffffff;
- n += r%(iMax + 1 - iMin);
- }
- assert( n<sizeof(zBuf) );
- sqlite3_randomness(n, zBuf);
- for(i=0; i<n; i++){
- zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
- }
- zBuf[n] = 0;
- sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT);
-}
-
-/*
-** The following two SQL functions are used to test returning a text
-** result with a destructor. Function 'test_destructor' takes one argument
-** and returns the same argument interpreted as TEXT. A destructor is
-** passed with the sqlite3_result_text() call.
-**
-** SQL function 'test_destructor_count' returns the number of outstanding
-** allocations made by 'test_destructor';
-**
-** WARNING: Not threadsafe.
-*/
-static int test_destructor_count_var = 0;
-static void destructor(void *p){
- char *zVal = (char *)p;
- assert(zVal);
- zVal--;
- sqlite3_free(zVal);
- test_destructor_count_var--;
-}
-static void test_destructor(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- char *zVal;
- int len;
-
- test_destructor_count_var++;
- assert( nArg==1 );
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- len = sqlite3_value_bytes(argv[0]);
- zVal = testContextMalloc(pCtx, len+3);
- if( !zVal ){
- return;
- }
- zVal[len+1] = 0;
- zVal[len+2] = 0;
- zVal++;
- memcpy(zVal, sqlite3_value_text(argv[0]), len);
- sqlite3_result_text(pCtx, zVal, -1, destructor);
-}
-#ifndef SQLITE_OMIT_UTF16
-static void test_destructor16(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- char *zVal;
- int len;
-
- test_destructor_count_var++;
- assert( nArg==1 );
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- len = sqlite3_value_bytes16(argv[0]);
- zVal = testContextMalloc(pCtx, len+3);
- if( !zVal ){
- return;
- }
- zVal[len+1] = 0;
- zVal[len+2] = 0;
- zVal++;
- memcpy(zVal, sqlite3_value_text16(argv[0]), len);
- sqlite3_result_text16(pCtx, zVal, -1, destructor);
-}
-#endif
-static void test_destructor_count(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- sqlite3_result_int(pCtx, test_destructor_count_var);
-}
-
-/*
-** The following aggregate function, test_agg_errmsg16(), takes zero
-** arguments. It returns the text value returned by the sqlite3_errmsg16()
-** API function.
-*/
-#ifndef SQLITE_UNTESTABLE
-void sqlite3BeginBenignMalloc(void);
-void sqlite3EndBenignMalloc(void);
-#else
- #define sqlite3BeginBenignMalloc()
- #define sqlite3EndBenignMalloc()
-#endif
-static void test_agg_errmsg16_step(sqlite3_context *a, int b,sqlite3_value **c){
-}
-static void test_agg_errmsg16_final(sqlite3_context *ctx){
-#ifndef SQLITE_OMIT_UTF16
- const void *z;
- sqlite3 * db = sqlite3_context_db_handle(ctx);
- sqlite3_aggregate_context(ctx, 2048);
- z = sqlite3_errmsg16(db);
- sqlite3_result_text16(ctx, z, -1, SQLITE_TRANSIENT);
-#endif
-}
-
-/*
-** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata()
-** interface.
-**
-** The test_auxdata() SQL function attempts to register each of its arguments
-** as auxiliary data. If there are no prior registrations of aux data for
-** that argument (meaning the argument is not a constant or this is its first
-** call) then the result for that argument is 0. If there is a prior
-** registration, the result for that argument is 1. The overall result
-** is the individual argument results separated by spaces.
-*/
-static void free_test_auxdata(void *p) {sqlite3_free(p);}
-static void test_auxdata(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- int i;
- char *zRet = testContextMalloc(pCtx, nArg*2);
- if( !zRet ) return;
- memset(zRet, 0, nArg*2);
- for(i=0; i<nArg; i++){
- char const *z = (char*)sqlite3_value_text(argv[i]);
- if( z ){
- int n;
- char *zAux = sqlite3_get_auxdata(pCtx, i);
- if( zAux ){
- zRet[i*2] = '1';
- assert( strcmp(zAux,z)==0 );
- }else {
- zRet[i*2] = '0';
- }
- n = (int)strlen(z) + 1;
- zAux = testContextMalloc(pCtx, n);
- if( zAux ){
- memcpy(zAux, z, n);
- sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
- }
- zRet[i*2+1] = ' ';
- }
- }
- sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
-}
-
-/*
-** A function to test error reporting from user functions. This function
-** returns a copy of its first argument as the error message. If the
-** second argument exists, it becomes the error code.
-*/
-static void test_error(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), -1);
- if( nArg==2 ){
- sqlite3_result_error_code(pCtx, sqlite3_value_int(argv[1]));
- }
-}
-
-/*
-** Implementation of the counter(X) function. If X is an integer
-** constant, then the first invocation will return X. The second X+1.
-** and so forth. Can be used (for example) to provide a sequence number
-** in a result set.
-*/
-static void counterFunc(
- sqlite3_context *pCtx, /* Function context */
- int nArg, /* Number of function arguments */
- sqlite3_value **argv /* Values for all function arguments */
-){
- int *pCounter = (int*)sqlite3_get_auxdata(pCtx, 0);
- if( pCounter==0 ){
- pCounter = sqlite3_malloc( sizeof(*pCounter) );
- if( pCounter==0 ){
- sqlite3_result_error_nomem(pCtx);
- return;
- }
- *pCounter = sqlite3_value_int(argv[0]);
- sqlite3_set_auxdata(pCtx, 0, pCounter, sqlite3_free);
- }else{
- ++*pCounter;
- }
- sqlite3_result_int(pCtx, *pCounter);
-}
-
-
-/*
-** This function takes two arguments. It performance UTF-8/16 type
-** conversions on the first argument then returns a copy of the second
-** argument.
-**
-** This function is used in cases such as the following:
-**
-** SELECT test_isolation(x,x) FROM t1;
-**
-** We want to verify that the type conversions that occur on the
-** first argument do not invalidate the second argument.
-*/
-static void test_isolation(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
-#ifndef SQLITE_OMIT_UTF16
- sqlite3_value_text16(argv[0]);
- sqlite3_value_text(argv[0]);
- sqlite3_value_text16(argv[0]);
- sqlite3_value_text(argv[0]);
-#endif
- sqlite3_result_value(pCtx, argv[1]);
-}
-
-/*
-** Invoke an SQL statement recursively. The function result is the
-** first column of the first row of the result set.
-*/
-static void test_eval(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- sqlite3_stmt *pStmt;
- int rc;
- sqlite3 *db = sqlite3_context_db_handle(pCtx);
- const char *zSql;
-
- zSql = (char*)sqlite3_value_text(argv[0]);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_step(pStmt);
- if( rc==SQLITE_ROW ){
- sqlite3_result_value(pCtx, sqlite3_column_value(pStmt, 0));
- }
- rc = sqlite3_finalize(pStmt);
- }
- if( rc ){
- char *zErr;
- assert( pStmt==0 );
- zErr = sqlite3_mprintf("sqlite3_prepare_v2() error: %s",sqlite3_errmsg(db));
- sqlite3_result_text(pCtx, zErr, -1, sqlite3_free);
- sqlite3_result_error_code(pCtx, rc);
- }
-}
-
-
-/*
-** convert one character from hex to binary
-*/
-static int testHexChar(char c){
- if( c>='0' && c<='9' ){
- return c - '0';
- }else if( c>='a' && c<='f' ){
- return c - 'a' + 10;
- }else if( c>='A' && c<='F' ){
- return c - 'A' + 10;
- }
- return 0;
-}
-
-/*
-** Convert hex to binary.
-*/
-static void testHexToBin(const char *zIn, char *zOut){
- while( zIn[0] && zIn[1] ){
- *(zOut++) = (testHexChar(zIn[0])<<4) + testHexChar(zIn[1]);
- zIn += 2;
- }
-}
-
-/*
-** hex_to_utf16be(HEX)
-**
-** Convert the input string from HEX into binary. Then return the
-** result using sqlite3_result_text16le().
-*/
-#ifndef SQLITE_OMIT_UTF16
-static void testHexToUtf16be(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- int n;
- const char *zIn;
- char *zOut;
- assert( nArg==1 );
- n = sqlite3_value_bytes(argv[0]);
- zIn = (const char*)sqlite3_value_text(argv[0]);
- zOut = sqlite3_malloc( n/2 );
- if( zOut==0 ){
- sqlite3_result_error_nomem(pCtx);
- }else{
- testHexToBin(zIn, zOut);
- sqlite3_result_text16be(pCtx, zOut, n/2, sqlite3_free);
- }
-}
-#endif
-
-/*
-** hex_to_utf8(HEX)
-**
-** Convert the input string from HEX into binary. Then return the
-** result using sqlite3_result_text16le().
-*/
-static void testHexToUtf8(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- int n;
- const char *zIn;
- char *zOut;
- assert( nArg==1 );
- n = sqlite3_value_bytes(argv[0]);
- zIn = (const char*)sqlite3_value_text(argv[0]);
- zOut = sqlite3_malloc( n/2 );
- if( zOut==0 ){
- sqlite3_result_error_nomem(pCtx);
- }else{
- testHexToBin(zIn, zOut);
- sqlite3_result_text(pCtx, zOut, n/2, sqlite3_free);
- }
-}
-
-/*
-** hex_to_utf16le(HEX)
-**
-** Convert the input string from HEX into binary. Then return the
-** result using sqlite3_result_text16le().
-*/
-#ifndef SQLITE_OMIT_UTF16
-static void testHexToUtf16le(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- int n;
- const char *zIn;
- char *zOut;
- assert( nArg==1 );
- n = sqlite3_value_bytes(argv[0]);
- zIn = (const char*)sqlite3_value_text(argv[0]);
- zOut = sqlite3_malloc( n/2 );
- if( zOut==0 ){
- sqlite3_result_error_nomem(pCtx);
- }else{
- testHexToBin(zIn, zOut);
- sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free);
- }
-}
-#endif
-
-/*
-** SQL function: real2hex(X)
-**
-** If argument X is a real number, then convert it into a string which is
-** the big-endian hexadecimal representation of the ieee754 encoding of
-** that number. If X is not a real number, return NULL.
-*/
-static void real2hex(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- union {
- sqlite3_uint64 i;
- double r;
- unsigned char x[8];
- } v;
- char zOut[20];
- int i;
- int bigEndian;
- v.i = 1;
- bigEndian = v.x[0]==0;
- v.r = sqlite3_value_double(argv[0]);
- for(i=0; i<8; i++){
- if( bigEndian ){
- zOut[i*2] = "0123456789abcdef"[v.x[i]>>4];
- zOut[i*2+1] = "0123456789abcdef"[v.x[i]&0xf];
- }else{
- zOut[14-i*2] = "0123456789abcdef"[v.x[i]>>4];
- zOut[14-i*2+1] = "0123456789abcdef"[v.x[i]&0xf];
- }
- }
- zOut[16] = 0;
- sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT);
-}
-
-/*
-** test_extract(record, field)
-**
-** This function implements an SQL user-function that accepts a blob
-** containing a formatted database record as the first argument. The
-** second argument is the index of the field within that record to
-** extract and return.
-*/
-static void test_extract(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- u8 *pRec;
- u8 *pEndHdr; /* Points to one byte past record header */
- u8 *pHdr; /* Current point in record header */
- u8 *pBody; /* Current point in record data */
- u64 nHdr; /* Bytes in record header */
- int iIdx; /* Required field */
- int iCurrent = 0; /* Current field */
-
- assert( argc==2 );
- pRec = (u8*)sqlite3_value_blob(argv[0]);
- iIdx = sqlite3_value_int(argv[1]);
-
- pHdr = pRec + sqlite3GetVarint(pRec, &nHdr);
- pBody = pEndHdr = &pRec[nHdr];
-
- for(iCurrent=0; pHdr<pEndHdr && iCurrent<=iIdx; iCurrent++){
- u64 iSerialType;
- Mem mem;
-
- memset(&mem, 0, sizeof(mem));
- mem.db = db;
- mem.enc = ENC(db);
- pHdr += sqlite3GetVarint(pHdr, &iSerialType);
- pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
-
- if( iCurrent==iIdx ){
- sqlite3_result_value(context, &mem);
- }
-
- if( mem.szMalloc ) sqlite3DbFree(db, mem.zMalloc);
- }
-}
-
-/*
-** test_decode(record)
-**
-** This function implements an SQL user-function that accepts a blob
-** containing a formatted database record as its only argument. It returns
-** a tcl list (type SQLITE_TEXT) containing each of the values stored
-** in the record.
-*/
-static void test_decode(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- u8 *pRec;
- u8 *pEndHdr; /* Points to one byte past record header */
- u8 *pHdr; /* Current point in record header */
- u8 *pBody; /* Current point in record data */
- u64 nHdr; /* Bytes in record header */
- Tcl_Obj *pRet; /* Return value */
-
- pRet = Tcl_NewObj();
- Tcl_IncrRefCount(pRet);
-
- assert( argc==1 );
- pRec = (u8*)sqlite3_value_blob(argv[0]);
-
- pHdr = pRec + sqlite3GetVarint(pRec, &nHdr);
- pBody = pEndHdr = &pRec[nHdr];
- while( pHdr<pEndHdr ){
- Tcl_Obj *pVal = 0;
- u64 iSerialType;
- Mem mem;
-
- memset(&mem, 0, sizeof(mem));
- mem.db = db;
- mem.enc = ENC(db);
- pHdr += sqlite3GetVarint(pHdr, &iSerialType);
- pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
-
- switch( sqlite3_value_type(&mem) ){
- case SQLITE_TEXT:
- pVal = Tcl_NewStringObj((const char*)sqlite3_value_text(&mem), -1);
- break;
-
- case SQLITE_BLOB: {
- char hexdigit[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
- };
- int n = sqlite3_value_bytes(&mem);
- u8 *z = (u8*)sqlite3_value_blob(&mem);
- int i;
- pVal = Tcl_NewStringObj("x'", -1);
- for(i=0; i<n; i++){
- char hex[3];
- hex[0] = hexdigit[((z[i] >> 4) & 0x0F)];
- hex[1] = hexdigit[(z[i] & 0x0F)];
- hex[2] = '\0';
- Tcl_AppendStringsToObj(pVal, hex, 0);
- }
- Tcl_AppendStringsToObj(pVal, "'", 0);
- break;
- }
-
- case SQLITE_FLOAT:
- pVal = Tcl_NewDoubleObj(sqlite3_value_double(&mem));
- break;
-
- case SQLITE_INTEGER:
- pVal = Tcl_NewWideIntObj(sqlite3_value_int64(&mem));
- break;
-
- case SQLITE_NULL:
- pVal = Tcl_NewStringObj("NULL", -1);
- break;
-
- default:
- assert( 0 );
- }
-
- Tcl_ListObjAppendElement(0, pRet, pVal);
-
- if( mem.szMalloc ){
- sqlite3DbFree(db, mem.zMalloc);
- }
- }
-
- sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT);
- Tcl_DecrRefCount(pRet);
-}
-
-/*
-** test_zeroblob(N)
-**
-** The implementation of scalar SQL function "test_zeroblob()". This is
-** similar to the built-in zeroblob() function, except that it does not
-** check that the integer parameter is within range before passing it
-** to sqlite3_result_zeroblob().
-*/
-static void test_zeroblob(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int nZero = sqlite3_value_int(argv[0]);
- sqlite3_result_zeroblob(context, nZero);
-}
-
-/* test_getsubtype(V)
-**
-** Return the subtype for value V.
-*/
-static void test_getsubtype(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3_result_int(context, (int)sqlite3_value_subtype(argv[0]));
-}
-
-/* test_setsubtype(V, T)
-**
-** Return the value V with its subtype changed to T
-*/
-static void test_setsubtype(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3_result_value(context, argv[0]);
- sqlite3_result_subtype(context, (unsigned int)sqlite3_value_int(argv[1]));
-}
-
-static int registerTestFunctions(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pThunk
-){
- static const struct {
- char *zName;
- signed char nArg;
- unsigned int eTextRep; /* 1: UTF-16. 0: UTF-8 */
- void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
- } aFuncs[] = {
- { "randstr", 2, SQLITE_UTF8, randStr },
- { "test_destructor", 1, SQLITE_UTF8, test_destructor},
-#ifndef SQLITE_OMIT_UTF16
- { "test_destructor16", 1, SQLITE_UTF8, test_destructor16},
- { "hex_to_utf16be", 1, SQLITE_UTF8, testHexToUtf16be},
- { "hex_to_utf16le", 1, SQLITE_UTF8, testHexToUtf16le},
-#endif
- { "hex_to_utf8", 1, SQLITE_UTF8, testHexToUtf8},
- { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count},
- { "test_auxdata", -1, SQLITE_UTF8, test_auxdata},
- { "test_error", 1, SQLITE_UTF8, test_error},
- { "test_error", 2, SQLITE_UTF8, test_error},
- { "test_eval", 1, SQLITE_UTF8, test_eval},
- { "test_isolation", 2, SQLITE_UTF8, test_isolation},
- { "test_counter", 1, SQLITE_UTF8, counterFunc},
- { "real2hex", 1, SQLITE_UTF8, real2hex},
- { "test_decode", 1, SQLITE_UTF8, test_decode},
- { "test_extract", 2, SQLITE_UTF8, test_extract},
- { "test_zeroblob", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob},
- { "test_getsubtype", 1, SQLITE_UTF8, test_getsubtype},
- { "test_setsubtype", 2, SQLITE_UTF8, test_setsubtype},
- };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
- aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0);
- }
-
- sqlite3_create_function(db, "test_agg_errmsg16", 0, SQLITE_ANY, 0, 0,
- test_agg_errmsg16_step, test_agg_errmsg16_final);
-
- return SQLITE_OK;
-}
-
-/*
-** TCLCMD: autoinstall_test_functions
-**
-** Invoke this TCL command to use sqlite3_auto_extension() to cause
-** the standard set of test functions to be loaded into each new
-** database connection.
-*/
-static int SQLITE_TCLAPI autoinstall_test_funcs(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);
- int rc = sqlite3_auto_extension((void(*)(void))registerTestFunctions);
- if( rc==SQLITE_OK ){
- rc = sqlite3_auto_extension((void(*)(void))Md5_Register);
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** A bogus step function and finalizer function.
-*/
-static void tStep(sqlite3_context *a, int b, sqlite3_value **c){}
-static void tFinal(sqlite3_context *a){}
-
-
-/*
-** tclcmd: abuse_create_function
-**
-** Make various calls to sqlite3_create_function that do not have valid
-** parameters. Verify that the error condition is detected and reported.
-*/
-static int SQLITE_TCLAPI abuse_create_function(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- sqlite3 *db;
- int rc;
- int mxArg;
-
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-
- rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep,tStep,tFinal);
- if( rc!=SQLITE_MISUSE ) goto abuse_err;
-
- rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep, tStep, 0);
- if( rc!=SQLITE_MISUSE ) goto abuse_err;
-
- rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep, 0, tFinal);
- if( rc!=SQLITE_MISUSE) goto abuse_err;
-
- rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, 0, 0, tFinal);
- if( rc!=SQLITE_MISUSE ) goto abuse_err;
-
- rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, 0, tStep, 0);
- if( rc!=SQLITE_MISUSE ) goto abuse_err;
-
- rc = sqlite3_create_function(db, "tx", -2, SQLITE_UTF8, 0, tStep, 0, 0);
- if( rc!=SQLITE_MISUSE ) goto abuse_err;
-
- rc = sqlite3_create_function(db, "tx", 128, SQLITE_UTF8, 0, tStep, 0, 0);
- if( rc!=SQLITE_MISUSE ) goto abuse_err;
-
- rc = sqlite3_create_function(db, "funcxx"
- "_123456789_123456789_123456789_123456789_123456789"
- "_123456789_123456789_123456789_123456789_123456789"
- "_123456789_123456789_123456789_123456789_123456789"
- "_123456789_123456789_123456789_123456789_123456789"
- "_123456789_123456789_123456789_123456789_123456789",
- 1, SQLITE_UTF8, 0, tStep, 0, 0);
- if( rc!=SQLITE_MISUSE ) goto abuse_err;
-
- /* This last function registration should actually work. Generate
- ** a no-op function (that always returns NULL) and which has the
- ** maximum-length function name and the maximum number of parameters.
- */
- sqlite3_limit(db, SQLITE_LIMIT_FUNCTION_ARG, 10000);
- mxArg = sqlite3_limit(db, SQLITE_LIMIT_FUNCTION_ARG, -1);
- rc = sqlite3_create_function(db, "nullx"
- "_123456789_123456789_123456789_123456789_123456789"
- "_123456789_123456789_123456789_123456789_123456789"
- "_123456789_123456789_123456789_123456789_123456789"
- "_123456789_123456789_123456789_123456789_123456789"
- "_123456789_123456789_123456789_123456789_123456789",
- mxArg, SQLITE_UTF8, 0, tStep, 0, 0);
- if( rc!=SQLITE_OK ) goto abuse_err;
-
- return TCL_OK;
-
-abuse_err:
- Tcl_AppendResult(interp, "sqlite3_create_function abused test failed",
- (char*)0);
- return TCL_ERROR;
-}
-
-
-/*
-** SQLite user defined function to use with matchinfo() to calculate the
-** relevancy of an FTS match. The value returned is the relevancy score
-** (a real value greater than or equal to zero). A larger value indicates
-** a more relevant document.
-**
-** The overall relevancy returned is the sum of the relevancies of each
-** column value in the FTS table. The relevancy of a column value is the
-** sum of the following for each reportable phrase in the FTS query:
-**
-** (<hit count> / <global hit count>) * <column weight>
-**
-** where <hit count> is the number of instances of the phrase in the
-** column value of the current row and <global hit count> is the number
-** of instances of the phrase in the same column of all rows in the FTS
-** table. The <column weight> is a weighting factor assigned to each
-** column by the caller (see below).
-**
-** The first argument to this function must be the return value of the FTS
-** matchinfo() function. Following this must be one argument for each column
-** of the FTS table containing a numeric weight factor for the corresponding
-** column. Example:
-**
-** CREATE VIRTUAL TABLE documents USING fts3(title, content)
-**
-** The following query returns the docids of documents that match the full-text
-** query <query> sorted from most to least relevant. When calculating
-** relevance, query term instances in the 'title' column are given twice the
-** weighting of those in the 'content' column.
-**
-** SELECT docid FROM documents
-** WHERE documents MATCH <query>
-** ORDER BY rank(matchinfo(documents), 1.0, 0.5) DESC
-*/
-static void rankfunc(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
- int *aMatchinfo; /* Return value of matchinfo() */
- int nMatchinfo; /* Number of elements in aMatchinfo[] */
- int nCol = 0; /* Number of columns in the table */
- int nPhrase = 0; /* Number of phrases in the query */
- int iPhrase; /* Current phrase */
- double score = 0.0; /* Value to return */
-
- assert( sizeof(int)==4 );
-
- /* Check that the number of arguments passed to this function is correct.
- ** If not, jump to wrong_number_args. Set aMatchinfo to point to the array
- ** of unsigned integer values returned by FTS function matchinfo. Set
- ** nPhrase to contain the number of reportable phrases in the users full-text
- ** query, and nCol to the number of columns in the table. Then check that the
- ** size of the matchinfo blob is as expected. Return an error if it is not.
- */
- if( nVal<1 ) goto wrong_number_args;
- aMatchinfo = (int*)sqlite3_value_blob(apVal[0]);
- nMatchinfo = sqlite3_value_bytes(apVal[0]) / sizeof(int);
- if( nMatchinfo>=2 ){
- nPhrase = aMatchinfo[0];
- nCol = aMatchinfo[1];
- }
- if( nMatchinfo!=(2+3*nCol*nPhrase) ){
- sqlite3_result_error(pCtx,
- "invalid matchinfo blob passed to function rank()", -1);
- return;
- }
- if( nVal!=(1+nCol) ) goto wrong_number_args;
-
- /* Iterate through each phrase in the users query. */
- for(iPhrase=0; iPhrase<nPhrase; iPhrase++){
- int iCol; /* Current column */
-
- /* Now iterate through each column in the users query. For each column,
- ** increment the relevancy score by:
- **
- ** (<hit count> / <global hit count>) * <column weight>
- **
- ** aPhraseinfo[] points to the start of the data for phrase iPhrase. So
- ** the hit count and global hit counts for each column are found in
- ** aPhraseinfo[iCol*3] and aPhraseinfo[iCol*3+1], respectively.
- */
- int *aPhraseinfo = &aMatchinfo[2 + iPhrase*nCol*3];
- for(iCol=0; iCol<nCol; iCol++){
- int nHitCount = aPhraseinfo[3*iCol];
- int nGlobalHitCount = aPhraseinfo[3*iCol+1];
- double weight = sqlite3_value_double(apVal[iCol+1]);
- if( nHitCount>0 ){
- score += ((double)nHitCount / (double)nGlobalHitCount) * weight;
- }
- }
- }
-
- sqlite3_result_double(pCtx, score);
- return;
-
- /* Jump here if the wrong number of arguments are passed to this function */
-wrong_number_args:
- sqlite3_result_error(pCtx, "wrong number of arguments to function rank()", -1);
-}
-
-static int SQLITE_TCLAPI install_fts3_rank_function(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- sqlite3 *db;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
-
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- sqlite3_create_function(db, "rank", -1, SQLITE_UTF8, 0, rankfunc, 0, 0);
- return TCL_OK;
-}
-
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest_func_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aObjCmd[] = {
- { "autoinstall_test_functions", autoinstall_test_funcs },
- { "abuse_create_function", abuse_create_function },
- { "install_fts3_rank_function", install_fts3_rank_function },
- };
- int i;
- extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);
-
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
- }
- sqlite3_initialize();
- sqlite3_auto_extension((void(*)(void))registerTestFunctions);
- sqlite3_auto_extension((void(*)(void))Md5_Register);
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_hexio.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_hexio.c
deleted file mode 100644
index 7b62ea08bc8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_hexio.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
-** 2007 April 6
-**
-** 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.
-**
-*************************************************************************
-** Code for testing all sorts of SQLite interfaces. This code
-** implements TCL commands for reading and writing the binary
-** database files and displaying the content of those files as
-** hexadecimal. We could, in theory, use the built-in "binary"
-** command of TCL to do a lot of this, but there are some issues
-** with historical versions of the "binary" command. So it seems
-** easier and safer to build our own mechanism.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-
-/*
-** Convert binary to hex. The input zBuf[] contains N bytes of
-** binary data. zBuf[] is 2*n+1 bytes long. Overwrite zBuf[]
-** with a hexadecimal representation of its original binary input.
-*/
-void sqlite3TestBinToHex(unsigned char *zBuf, int N){
- const unsigned char zHex[] = "0123456789ABCDEF";
- int i, j;
- unsigned char c;
- i = N*2;
- zBuf[i--] = 0;
- for(j=N-1; j>=0; j--){
- c = zBuf[j];
- zBuf[i--] = zHex[c&0xf];
- zBuf[i--] = zHex[c>>4];
- }
- assert( i==-1 );
-}
-
-/*
-** Convert hex to binary. The input zIn[] contains N bytes of
-** hexadecimal. Convert this into binary and write aOut[] with
-** the binary data. Spaces in the original input are ignored.
-** Return the number of bytes of binary rendered.
-*/
-int sqlite3TestHexToBin(const unsigned char *zIn, int N, unsigned char *aOut){
- const unsigned char aMap[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 0, 0, 0, 0, 0, 0,
- 0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- };
- int i, j;
- int hi=1;
- unsigned char c;
-
- for(i=j=0; i<N; i++){
- c = aMap[zIn[i]];
- if( c==0 ) continue;
- if( hi ){
- aOut[j] = (c-1)<<4;
- hi = 0;
- }else{
- aOut[j++] |= c-1;
- hi = 1;
- }
- }
- return j;
-}
-
-
-/*
-** Usage: hexio_read FILENAME OFFSET AMT
-**
-** Read AMT bytes from file FILENAME beginning at OFFSET from the
-** beginning of the file. Convert that information to hexadecimal
-** and return the resulting HEX string.
-*/
-static int SQLITE_TCLAPI hexio_read(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int offset;
- int amt, got;
- const char *zFile;
- unsigned char *zBuf;
- FILE *in;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET AMT");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &amt) ) return TCL_ERROR;
- zFile = Tcl_GetString(objv[1]);
- zBuf = sqlite3_malloc( amt*2+1 );
- if( zBuf==0 ){
- return TCL_ERROR;
- }
- in = fopen(zFile, "rb");
- if( in==0 ){
- in = fopen(zFile, "r");
- }
- if( in==0 ){
- Tcl_AppendResult(interp, "cannot open input file ", zFile, 0);
- return TCL_ERROR;
- }
- fseek(in, offset, SEEK_SET);
- got = (int)fread(zBuf, 1, amt, in);
- fclose(in);
- if( got<0 ){
- got = 0;
- }
- sqlite3TestBinToHex(zBuf, got);
- Tcl_AppendResult(interp, zBuf, 0);
- sqlite3_free(zBuf);
- return TCL_OK;
-}
-
-
-/*
-** Usage: hexio_write FILENAME OFFSET DATA
-**
-** Write DATA into file FILENAME beginning at OFFSET from the
-** beginning of the file. DATA is expressed in hexadecimal.
-*/
-static int SQLITE_TCLAPI hexio_write(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int offset;
- int nIn, nOut, written;
- const char *zFile;
- const unsigned char *zIn;
- unsigned char *aOut;
- FILE *out;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET HEXDATA");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR;
- zFile = Tcl_GetString(objv[1]);
- zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[3], &nIn);
- aOut = sqlite3_malloc( nIn/2 );
- if( aOut==0 ){
- return TCL_ERROR;
- }
- nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
- out = fopen(zFile, "r+b");
- if( out==0 ){
- out = fopen(zFile, "r+");
- }
- if( out==0 ){
- Tcl_AppendResult(interp, "cannot open output file ", zFile, 0);
- return TCL_ERROR;
- }
- fseek(out, offset, SEEK_SET);
- written = (int)fwrite(aOut, 1, nOut, out);
- sqlite3_free(aOut);
- fclose(out);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(written));
- return TCL_OK;
-}
-
-/*
-** USAGE: hexio_get_int HEXDATA
-**
-** Interpret the HEXDATA argument as a big-endian integer. Return
-** the value of that integer. HEXDATA can contain between 2 and 8
-** hexadecimal digits.
-*/
-static int SQLITE_TCLAPI hexio_get_int(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int val;
- int nIn, nOut;
- const unsigned char *zIn;
- unsigned char *aOut;
- unsigned char aNum[4];
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HEXDATA");
- return TCL_ERROR;
- }
- zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn);
- aOut = sqlite3_malloc( nIn/2 );
- if( aOut==0 ){
- return TCL_ERROR;
- }
- nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
- if( nOut>=4 ){
- memcpy(aNum, aOut, 4);
- }else{
- memset(aNum, 0, sizeof(aNum));
- memcpy(&aNum[4-nOut], aOut, nOut);
- }
- sqlite3_free(aOut);
- val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3];
- Tcl_SetObjResult(interp, Tcl_NewIntObj(val));
- return TCL_OK;
-}
-
-
-/*
-** USAGE: hexio_render_int16 INTEGER
-**
-** Render INTEGER has a 16-bit big-endian integer in hexadecimal.
-*/
-static int SQLITE_TCLAPI hexio_render_int16(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int val;
- unsigned char aNum[10];
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "INTEGER");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &val) ) return TCL_ERROR;
- aNum[0] = val>>8;
- aNum[1] = val;
- sqlite3TestBinToHex(aNum, 2);
- Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)aNum, 4));
- return TCL_OK;
-}
-
-
-/*
-** USAGE: hexio_render_int32 INTEGER
-**
-** Render INTEGER has a 32-bit big-endian integer in hexadecimal.
-*/
-static int SQLITE_TCLAPI hexio_render_int32(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int val;
- unsigned char aNum[10];
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "INTEGER");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &val) ) return TCL_ERROR;
- aNum[0] = val>>24;
- aNum[1] = val>>16;
- aNum[2] = val>>8;
- aNum[3] = val;
- sqlite3TestBinToHex(aNum, 4);
- Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)aNum, 8));
- return TCL_OK;
-}
-
-/*
-** USAGE: utf8_to_utf8 HEX
-**
-** The argument is a UTF8 string represented in hexadecimal.
-** The UTF8 might not be well-formed. Run this string through
-** sqlite3Utf8to8() convert it back to hex and return the result.
-*/
-static int SQLITE_TCLAPI utf8_to_utf8(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifdef SQLITE_DEBUG
- int n;
- int nOut;
- const unsigned char *zOrig;
- unsigned char *z;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HEX");
- return TCL_ERROR;
- }
- zOrig = (unsigned char *)Tcl_GetStringFromObj(objv[1], &n);
- z = sqlite3_malloc( n+3 );
- n = sqlite3TestHexToBin(zOrig, n, z);
- z[n] = 0;
- nOut = sqlite3Utf8To8(z);
- sqlite3TestBinToHex(z,nOut);
- Tcl_AppendResult(interp, (char*)z, 0);
- sqlite3_free(z);
- return TCL_OK;
-#else
- Tcl_AppendResult(interp,
- "[utf8_to_utf8] unavailable - SQLITE_DEBUG not defined", 0
- );
- return TCL_ERROR;
-#endif
-}
-
-static int getFts3Varint(const char *p, sqlite_int64 *v){
- const unsigned char *q = (const unsigned char *) p;
- sqlite_uint64 x = 0, y = 1;
- while( (*q & 0x80) == 0x80 ){
- x += y * (*q++ & 0x7f);
- y <<= 7;
- }
- x += y * (*q++);
- *v = (sqlite_int64) x;
- return (int) (q - (unsigned char *)p);
-}
-
-
-/*
-** USAGE: read_fts3varint BLOB VARNAME
-**
-** Read a varint from the start of BLOB. Set variable VARNAME to contain
-** the interpreted value. Return the number of bytes of BLOB consumed.
-*/
-static int SQLITE_TCLAPI read_fts3varint(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int nBlob;
- unsigned char *zBlob;
- sqlite3_int64 iVal;
- int nVal;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BLOB VARNAME");
- return TCL_ERROR;
- }
- zBlob = Tcl_GetByteArrayFromObj(objv[1], &nBlob);
-
- nVal = getFts3Varint((char*)zBlob, (sqlite3_int64 *)(&iVal));
- Tcl_ObjSetVar2(interp, objv[2], 0, Tcl_NewWideIntObj(iVal), 0);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nVal));
- return TCL_OK;
-}
-
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest_hexio_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aObjCmd[] = {
- { "hexio_read", hexio_read },
- { "hexio_write", hexio_write },
- { "hexio_get_int", hexio_get_int },
- { "hexio_render_int16", hexio_render_int16 },
- { "hexio_render_int32", hexio_render_int32 },
- { "utf8_to_utf8", utf8_to_utf8 },
- { "read_fts3varint", read_fts3varint },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
- }
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_init.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_init.c
deleted file mode 100644
index 58465785d82..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_init.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
-** 2009 August 17
-**
-** 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.
-**
-*************************************************************************
-**
-** The code in this file is used for testing SQLite. It is not part of
-** the source code used in production systems.
-**
-** Specifically, this file tests the effect of errors while initializing
-** the various pluggable sub-systems from within sqlite3_initialize().
-** If an error occurs in sqlite3_initialize() the following should be
-** true:
-**
-** 1) An error code is returned to the user, and
-** 2) A subsequent call to sqlite3_shutdown() calls the shutdown method
-** of those subsystems that were initialized, and
-** 3) A subsequent call to sqlite3_initialize() attempts to initialize
-** the remaining, uninitialized, subsystems.
-*/
-
-#include "sqliteInt.h"
-#include <string.h>
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-static struct Wrapped {
- sqlite3_pcache_methods2 pcache;
- sqlite3_mem_methods mem;
- sqlite3_mutex_methods mutex;
-
- int mem_init; /* True if mem subsystem is initalized */
- int mem_fail; /* True to fail mem subsystem inialization */
- int mutex_init; /* True if mutex subsystem is initalized */
- int mutex_fail; /* True to fail mutex subsystem inialization */
- int pcache_init; /* True if pcache subsystem is initalized */
- int pcache_fail; /* True to fail pcache subsystem inialization */
-} wrapped;
-
-static int wrMemInit(void *pAppData){
- int rc;
- if( wrapped.mem_fail ){
- rc = SQLITE_ERROR;
- }else{
- rc = wrapped.mem.xInit(wrapped.mem.pAppData);
- }
- if( rc==SQLITE_OK ){
- wrapped.mem_init = 1;
- }
- return rc;
-}
-static void wrMemShutdown(void *pAppData){
- wrapped.mem.xShutdown(wrapped.mem.pAppData);
- wrapped.mem_init = 0;
-}
-static void *wrMemMalloc(int n) {return wrapped.mem.xMalloc(n);}
-static void wrMemFree(void *p) {wrapped.mem.xFree(p);}
-static void *wrMemRealloc(void *p, int n) {return wrapped.mem.xRealloc(p, n);}
-static int wrMemSize(void *p) {return wrapped.mem.xSize(p);}
-static int wrMemRoundup(int n) {return wrapped.mem.xRoundup(n);}
-
-
-static int wrMutexInit(void){
- int rc;
- if( wrapped.mutex_fail ){
- rc = SQLITE_ERROR;
- }else{
- rc = wrapped.mutex.xMutexInit();
- }
- if( rc==SQLITE_OK ){
- wrapped.mutex_init = 1;
- }
- return rc;
-}
-static int wrMutexEnd(void){
- wrapped.mutex.xMutexEnd();
- wrapped.mutex_init = 0;
- return SQLITE_OK;
-}
-static sqlite3_mutex *wrMutexAlloc(int e){
- return wrapped.mutex.xMutexAlloc(e);
-}
-static void wrMutexFree(sqlite3_mutex *p){
- wrapped.mutex.xMutexFree(p);
-}
-static void wrMutexEnter(sqlite3_mutex *p){
- wrapped.mutex.xMutexEnter(p);
-}
-static int wrMutexTry(sqlite3_mutex *p){
- return wrapped.mutex.xMutexTry(p);
-}
-static void wrMutexLeave(sqlite3_mutex *p){
- wrapped.mutex.xMutexLeave(p);
-}
-static int wrMutexHeld(sqlite3_mutex *p){
- return wrapped.mutex.xMutexHeld(p);
-}
-static int wrMutexNotheld(sqlite3_mutex *p){
- return wrapped.mutex.xMutexNotheld(p);
-}
-
-
-
-static int wrPCacheInit(void *pArg){
- int rc;
- if( wrapped.pcache_fail ){
- rc = SQLITE_ERROR;
- }else{
- rc = wrapped.pcache.xInit(wrapped.pcache.pArg);
- }
- if( rc==SQLITE_OK ){
- wrapped.pcache_init = 1;
- }
- return rc;
-}
-static void wrPCacheShutdown(void *pArg){
- wrapped.pcache.xShutdown(wrapped.pcache.pArg);
- wrapped.pcache_init = 0;
-}
-
-static sqlite3_pcache *wrPCacheCreate(int a, int b, int c){
- return wrapped.pcache.xCreate(a, b, c);
-}
-static void wrPCacheCachesize(sqlite3_pcache *p, int n){
- wrapped.pcache.xCachesize(p, n);
-}
-static int wrPCachePagecount(sqlite3_pcache *p){
- return wrapped.pcache.xPagecount(p);
-}
-static sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){
- return wrapped.pcache.xFetch(p, a, b);
-}
-static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){
- wrapped.pcache.xUnpin(p, a, b);
-}
-static void wrPCacheRekey(
- sqlite3_pcache *p,
- sqlite3_pcache_page *a,
- unsigned b,
- unsigned c
-){
- wrapped.pcache.xRekey(p, a, b, c);
-}
-static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){
- wrapped.pcache.xTruncate(p, a);
-}
-static void wrPCacheDestroy(sqlite3_pcache *p){
- wrapped.pcache.xDestroy(p);
-}
-
-static void installInitWrappers(void){
- sqlite3_mutex_methods mutexmethods = {
- wrMutexInit, wrMutexEnd, wrMutexAlloc,
- wrMutexFree, wrMutexEnter, wrMutexTry,
- wrMutexLeave, wrMutexHeld, wrMutexNotheld
- };
- sqlite3_pcache_methods2 pcachemethods = {
- 1, 0,
- wrPCacheInit, wrPCacheShutdown, wrPCacheCreate,
- wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch,
- wrPCacheUnpin, wrPCacheRekey, wrPCacheTruncate,
- wrPCacheDestroy
- };
- sqlite3_mem_methods memmethods = {
- wrMemMalloc, wrMemFree, wrMemRealloc,
- wrMemSize, wrMemRoundup, wrMemInit,
- wrMemShutdown,
- 0
- };
-
- memset(&wrapped, 0, sizeof(wrapped));
-
- sqlite3_shutdown();
- sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex);
- sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem);
- sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &wrapped.pcache);
- sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods);
- sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods);
- sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcachemethods);
-}
-
-static int SQLITE_TCLAPI init_wrapper_install(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int i;
- installInitWrappers();
- for(i=1; i<objc; i++){
- char *z = Tcl_GetString(objv[i]);
- if( strcmp(z, "mem")==0 ){
- wrapped.mem_fail = 1;
- }else if( strcmp(z, "mutex")==0 ){
- wrapped.mutex_fail = 1;
- }else if( strcmp(z, "pcache")==0 ){
- wrapped.pcache_fail = 1;
- }else{
- Tcl_AppendResult(interp, "Unknown argument: \"", z, "\"");
- return TCL_ERROR;
- }
- }
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI init_wrapper_uninstall(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- sqlite3_shutdown();
- sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex);
- sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem);
- sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache);
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI init_wrapper_clear(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- wrapped.mem_fail = 0;
- wrapped.mutex_fail = 0;
- wrapped.pcache_fail = 0;
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI init_wrapper_query(
- ClientData clientData, /* Unused */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- Tcl_Obj *pRet;
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- pRet = Tcl_NewObj();
- if( wrapped.mutex_init ){
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mutex", -1));
- }
- if( wrapped.mem_init ){
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mem", -1));
- }
- if( wrapped.pcache_init ){
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("pcache", -1));
- }
-
- Tcl_SetObjResult(interp, pRet);
- return TCL_OK;
-}
-
-int Sqlitetest_init_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aObjCmd[] = {
- {"init_wrapper_install", init_wrapper_install},
- {"init_wrapper_query", init_wrapper_query },
- {"init_wrapper_uninstall", init_wrapper_uninstall},
- {"init_wrapper_clear", init_wrapper_clear}
- };
- int i;
-
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
- }
-
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_intarray.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_intarray.c
deleted file mode 100644
index ddfb13fe20b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_intarray.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
-** 2009 November 10
-**
-** 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 a read-only VIRTUAL TABLE that contains the
-** content of a C-language array of integer values. See the corresponding
-** header file for full details.
-*/
-#include "test_intarray.h"
-#include <string.h>
-#include <assert.h>
-
-
-/*
-** Definition of the sqlite3_intarray object.
-**
-** The internal representation of an intarray object is subject
-** to change, is not externally visible, and should be used by
-** the implementation of intarray only. This object is opaque
-** to users.
-*/
-struct sqlite3_intarray {
- int n; /* Number of elements in the array */
- sqlite3_int64 *a; /* Contents of the array */
- void (*xFree)(void*); /* Function used to free a[] */
-};
-
-/* Objects used internally by the virtual table implementation */
-typedef struct intarray_vtab intarray_vtab;
-typedef struct intarray_cursor intarray_cursor;
-
-/* An intarray table object */
-struct intarray_vtab {
- sqlite3_vtab base; /* Base class */
- sqlite3_intarray *pContent; /* Content of the integer array */
-};
-
-/* An intarray cursor object */
-struct intarray_cursor {
- sqlite3_vtab_cursor base; /* Base class */
- int i; /* Current cursor position */
-};
-
-/*
-** None of this works unless we have virtual tables.
-*/
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Free an sqlite3_intarray object.
-*/
-static void intarrayFree(sqlite3_intarray *p){
- if( p->xFree ){
- p->xFree(p->a);
- }
- sqlite3_free(p);
-}
-
-/*
-** Table destructor for the intarray module.
-*/
-static int intarrayDestroy(sqlite3_vtab *p){
- intarray_vtab *pVtab = (intarray_vtab*)p;
- sqlite3_free(pVtab);
- return 0;
-}
-
-/*
-** Table constructor for the intarray module.
-*/
-static int intarrayCreate(
- sqlite3 *db, /* Database where module is created */
- void *pAux, /* clientdata for the module */
- int argc, /* Number of arguments */
- const char *const*argv, /* Value for all arguments */
- sqlite3_vtab **ppVtab, /* Write the new virtual table object here */
- char **pzErr /* Put error message text here */
-){
- int rc = SQLITE_NOMEM;
- intarray_vtab *pVtab = sqlite3_malloc64(sizeof(intarray_vtab));
-
- if( pVtab ){
- memset(pVtab, 0, sizeof(intarray_vtab));
- pVtab->pContent = (sqlite3_intarray*)pAux;
- rc = sqlite3_declare_vtab(db, "CREATE TABLE x(value INTEGER PRIMARY KEY)");
- }
- *ppVtab = (sqlite3_vtab *)pVtab;
- return rc;
-}
-
-/*
-** Open a new cursor on the intarray table.
-*/
-static int intarrayOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- int rc = SQLITE_NOMEM;
- intarray_cursor *pCur;
- pCur = sqlite3_malloc64(sizeof(intarray_cursor));
- if( pCur ){
- memset(pCur, 0, sizeof(intarray_cursor));
- *ppCursor = (sqlite3_vtab_cursor *)pCur;
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-/*
-** Close a intarray table cursor.
-*/
-static int intarrayClose(sqlite3_vtab_cursor *cur){
- intarray_cursor *pCur = (intarray_cursor *)cur;
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Retrieve a column of data.
-*/
-static int intarrayColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- intarray_cursor *pCur = (intarray_cursor*)cur;
- intarray_vtab *pVtab = (intarray_vtab*)cur->pVtab;
- if( pCur->i>=0 && pCur->i<pVtab->pContent->n ){
- sqlite3_result_int64(ctx, pVtab->pContent->a[pCur->i]);
- }
- return SQLITE_OK;
-}
-
-/*
-** Retrieve the current rowid.
-*/
-static int intarrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- intarray_cursor *pCur = (intarray_cursor *)cur;
- *pRowid = pCur->i;
- return SQLITE_OK;
-}
-
-static int intarrayEof(sqlite3_vtab_cursor *cur){
- intarray_cursor *pCur = (intarray_cursor *)cur;
- intarray_vtab *pVtab = (intarray_vtab *)cur->pVtab;
- return pCur->i>=pVtab->pContent->n;
-}
-
-/*
-** Advance the cursor to the next row.
-*/
-static int intarrayNext(sqlite3_vtab_cursor *cur){
- intarray_cursor *pCur = (intarray_cursor *)cur;
- pCur->i++;
- return SQLITE_OK;
-}
-
-/*
-** Reset a intarray table cursor.
-*/
-static int intarrayFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- intarray_cursor *pCur = (intarray_cursor *)pVtabCursor;
- pCur->i = 0;
- return SQLITE_OK;
-}
-
-/*
-** Analyse the WHERE condition.
-*/
-static int intarrayBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- return SQLITE_OK;
-}
-
-/*
-** A virtual table module that merely echos method calls into TCL
-** variables.
-*/
-static sqlite3_module intarrayModule = {
- 0, /* iVersion */
- intarrayCreate, /* xCreate - create a new virtual table */
- intarrayCreate, /* xConnect - connect to an existing vtab */
- intarrayBestIndex, /* xBestIndex - find the best query index */
- intarrayDestroy, /* xDisconnect - disconnect a vtab */
- intarrayDestroy, /* xDestroy - destroy a vtab */
- intarrayOpen, /* xOpen - open a cursor */
- intarrayClose, /* xClose - close a cursor */
- intarrayFilter, /* xFilter - configure scan constraints */
- intarrayNext, /* xNext - advance a cursor */
- intarrayEof, /* xEof */
- intarrayColumn, /* xColumn - read data */
- intarrayRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
-
-/*
-** Invoke this routine to create a specific instance of an intarray object.
-** The new intarray object is returned by the 3rd parameter.
-**
-** Each intarray object corresponds to a virtual table in the TEMP table
-** with a name of zName.
-**
-** Destroy the intarray object by dropping the virtual table. If not done
-** explicitly by the application, the virtual table will be dropped implicitly
-** by the system when the database connection is closed.
-*/
-SQLITE_API int sqlite3_intarray_create(
- sqlite3 *db,
- const char *zName,
- sqlite3_intarray **ppReturn
-){
- int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_intarray *p;
-
- *ppReturn = p = sqlite3_malloc64( sizeof(*p) );
- if( p==0 ){
- return SQLITE_NOMEM;
- }
- memset(p, 0, sizeof(*p));
- rc = sqlite3_create_module_v2(db, zName, &intarrayModule, p,
- (void(*)(void*))intarrayFree);
- if( rc==SQLITE_OK ){
- char *zSql;
- zSql = sqlite3_mprintf("CREATE VIRTUAL TABLE temp.%Q USING %Q",
- zName, zName);
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
-#endif
- return rc;
-}
-
-/*
-** Bind a new array array of integers to a specific intarray object.
-**
-** The array of integers bound must be unchanged for the duration of
-** any query against the corresponding virtual table. If the integer
-** array does change or is deallocated undefined behavior will result.
-*/
-SQLITE_API int sqlite3_intarray_bind(
- sqlite3_intarray *pIntArray, /* The intarray object to bind to */
- int nElements, /* Number of elements in the intarray */
- sqlite3_int64 *aElements, /* Content of the intarray */
- void (*xFree)(void*) /* How to dispose of the intarray when done */
-){
- if( pIntArray->xFree ){
- pIntArray->xFree(pIntArray->a);
- }
- pIntArray->n = nElements;
- pIntArray->a = aElements;
- pIntArray->xFree = xFree;
- return SQLITE_OK;
-}
-
-
-/*****************************************************************************
-** Everything below is interface for testing this module.
-*/
-#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-/*
-** Routines to encode and decode pointers
-*/
-extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
-extern void *sqlite3TestTextToPtr(const char*);
-extern int sqlite3TestMakePointerStr(Tcl_Interp*, char *zPtr, void*);
-extern const char *sqlite3ErrName(int);
-
-/*
-** sqlite3_intarray_create DB NAME
-**
-** Invoke the sqlite3_intarray_create interface. A string that becomes
-** the first parameter to sqlite3_intarray_bind.
-*/
-static int SQLITE_TCLAPI test_intarray_create(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- const char *zName;
- sqlite3_intarray *pArray;
- int rc = SQLITE_OK;
- char zPtr[100];
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zName = Tcl_GetString(objv[2]);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_intarray_create(db, zName, &pArray);
-#endif
- if( rc!=SQLITE_OK ){
- assert( pArray==0 );
- Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0);
- return TCL_ERROR;
- }
- sqlite3TestMakePointerStr(interp, zPtr, pArray);
- Tcl_AppendResult(interp, zPtr, (char*)0);
- return TCL_OK;
-}
-
-/*
-** sqlite3_intarray_bind INTARRAY ?VALUE ...?
-**
-** Invoke the sqlite3_intarray_bind interface on the given array of integers.
-*/
-static int SQLITE_TCLAPI test_intarray_bind(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3_intarray *pArray;
- int rc = SQLITE_OK;
- int i, n;
- sqlite3_int64 *a;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "INTARRAY");
- return TCL_ERROR;
- }
- pArray = (sqlite3_intarray*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- n = objc - 2;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- a = sqlite3_malloc64( sizeof(a[0])*n );
- if( a==0 ){
- Tcl_AppendResult(interp, "SQLITE_NOMEM", (char*)0);
- return TCL_ERROR;
- }
- for(i=0; i<n; i++){
- Tcl_WideInt x = 0;
- Tcl_GetWideIntFromObj(0, objv[i+2], &x);
- a[i] = x;
- }
- rc = sqlite3_intarray_bind(pArray, n, a, sqlite3_free);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0);
- return TCL_ERROR;
- }
-#endif
- return TCL_OK;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetestintarray_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- void *clientData;
- } aObjCmd[] = {
- { "sqlite3_intarray_create", test_intarray_create, 0 },
- { "sqlite3_intarray_bind", test_intarray_bind, 0 },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
- aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
- }
- return TCL_OK;
-}
-
-#endif /* SQLITE_TEST */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_intarray.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_intarray.h
deleted file mode 100644
index cee55b5dae8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_intarray.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-** 2009 November 10
-**
-** 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 is the C-language interface definition for the "intarray" or
-** integer array virtual table for SQLite.
-**
-** The intarray virtual table is designed to facilitate using an
-** array of integers as the right-hand side of an IN operator. So
-** instead of doing a prepared statement like this:
-**
-** SELECT * FROM table WHERE x IN (?,?,?,...,?);
-**
-** And then binding indivdual integers to each of ? slots, a C-language
-** application can create an intarray object (named "ex1" in the following
-** example), prepare a statement like this:
-**
-** SELECT * FROM table WHERE x IN ex1;
-**
-** Then bind an ordinary C/C++ array of integer values to the ex1 object
-** to run the statement.
-**
-** USAGE:
-**
-** One or more intarray objects can be created as follows:
-**
-** sqlite3_intarray *p1, *p2, *p3;
-** sqlite3_intarray_create(db, "ex1", &p1);
-** sqlite3_intarray_create(db, "ex2", &p2);
-** sqlite3_intarray_create(db, "ex3", &p3);
-**
-** Each call to sqlite3_intarray_create() generates a new virtual table
-** module and a singleton of that virtual table module in the TEMP
-** database. Both the module and the virtual table instance use the
-** name given by the second parameter. The virtual tables can then be
-** used in prepared statements:
-**
-** SELECT * FROM t1, t2, t3
-** WHERE t1.x IN ex1
-** AND t2.y IN ex2
-** AND t3.z IN ex3;
-**
-** Each integer array is initially empty. New arrays can be bound to
-** an integer array as follows:
-**
-** sqlite3_int64 a1[] = { 1, 2, 3, 4 };
-** sqlite3_int64 a2[] = { 5, 6, 7, 8, 9, 10, 11 };
-** sqlite3_int64 *a3 = sqlite3_malloc( 100*sizeof(sqlite3_int64) );
-** // Fill in content of a3[]
-** sqlite3_intarray_bind(p1, 4, a1, 0);
-** sqlite3_intarray_bind(p2, 7, a2, 0);
-** sqlite3_intarray_bind(p3, 100, a3, sqlite3_free);
-**
-** A single intarray object can be rebound multiple times. But do not
-** attempt to change the bindings of an intarray while it is in the middle
-** of a query.
-**
-** The array that holds the integers is automatically freed by the function
-** in the fourth parameter to sqlite3_intarray_bind() when the array is no
-** longer needed. The application must not change the intarray values
-** while an intarray is in the middle of a query.
-**
-** The intarray object is automatically destroyed when its corresponding
-** virtual table is dropped. Since the virtual tables are created in the
-** TEMP database, they are automatically dropped when the database connection
-** closes so the application does not normally need to take any special
-** action to free the intarray objects.
-*/
-#include "sqlite3.h"
-#ifndef SQLITE_INTARRAY_H
-#define SQLITE_INTARRAY_H
-
-/*
-** Make sure we can call this stuff from C++.
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** An sqlite3_intarray is an abstract type to stores an instance of
-** an integer array.
-*/
-typedef struct sqlite3_intarray sqlite3_intarray;
-
-/*
-** Invoke this routine to create a specific instance of an intarray object.
-** The new intarray object is returned by the 3rd parameter.
-**
-** Each intarray object corresponds to a virtual table in the TEMP table
-** with a name of zName.
-**
-** Destroy the intarray object by dropping the virtual table. If not done
-** explicitly by the application, the virtual table will be dropped implicitly
-** by the system when the database connection is closed.
-*/
-SQLITE_API int sqlite3_intarray_create(
- sqlite3 *db,
- const char *zName,
- sqlite3_intarray **ppReturn
-);
-
-/*
-** Bind a new array array of integers to a specific intarray object.
-**
-** The array of integers bound must be unchanged for the duration of
-** any query against the corresponding virtual table. If the integer
-** array does change or is deallocated undefined behavior will result.
-*/
-SQLITE_API int sqlite3_intarray_bind(
- sqlite3_intarray *pIntArray, /* The intarray object to bind to */
- int nElements, /* Number of elements in the intarray */
- sqlite3_int64 *aElements, /* Content of the intarray */
- void (*xFree)(void*) /* How to dispose of the intarray when done */
-);
-
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-#endif /* SQLITE_INTARRAY_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_journal.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_journal.c
deleted file mode 100644
index 8a449e888c4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_journal.c
+++ /dev/null
@@ -1,869 +0,0 @@
-/*
-** 2008 Jan 22
-**
-** 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 contains code for a VFS layer that acts as a wrapper around
-** an existing VFS. The code in this file attempts to verify that SQLite
-** correctly populates and syncs a journal file before writing to a
-** corresponding database file.
-**
-** INTERFACE
-**
-** The public interface to this wrapper VFS is two functions:
-**
-** jt_register()
-** jt_unregister()
-**
-** See header comments associated with those two functions below for
-** details.
-**
-** LIMITATIONS
-**
-** This wrapper will not work if "PRAGMA synchronous = off" is used.
-**
-** OPERATION
-**
-** Starting a Transaction:
-**
-** When a write-transaction is started, the contents of the database is
-** inspected and the following data stored as part of the database file
-** handle (type struct jt_file):
-**
-** a) The page-size of the database file.
-** b) The number of pages that are in the database file.
-** c) The set of page numbers corresponding to free-list leaf pages.
-** d) A check-sum for every page in the database file.
-**
-** The start of a write-transaction is deemed to have occurred when a
-** 28-byte journal header is written to byte offset 0 of the journal
-** file.
-**
-** Syncing the Journal File:
-**
-** Whenever the xSync method is invoked to sync a journal-file, the
-** contents of the journal file are read. For each page written to
-** the journal file, a check-sum is calculated and compared to the
-** check-sum calculated for the corresponding database page when the
-** write-transaction was initialized. The success of the comparison
-** is assert()ed. So if SQLite has written something other than the
-** original content to the database file, an assert() will fail.
-**
-** Additionally, the set of page numbers for which records exist in
-** the journal file is added to (unioned with) the set of page numbers
-** corresponding to free-list leaf pages collected when the
-** write-transaction was initialized. This set comprises the page-numbers
-** corresponding to those pages that SQLite may now safely modify.
-**
-** Writing to the Database File:
-**
-** When a block of data is written to a database file, the following
-** invariants are asserted:
-**
-** a) That the block of data is an aligned block of page-size bytes.
-**
-** b) That if the page being written did not exist when the
-** transaction was started (i.e. the database file is growing), then
-** the journal-file must have been synced at least once since
-** the start of the transaction.
-**
-** c) That if the page being written did exist when the transaction
-** was started, then the page must have either been a free-list
-** leaf page at the start of the transaction, or else must have
-** been stored in the journal file prior to the most recent sync.
-**
-** Closing a Transaction:
-**
-** When a transaction is closed, all data collected at the start of
-** the transaction, or following an xSync of a journal-file, is
-** discarded. The end of a transaction is recognized when any one
-** of the following occur:
-**
-** a) A block of zeroes (or anything else that is not a valid
-** journal-header) is written to the start of the journal file.
-**
-** b) A journal file is truncated to zero bytes in size using xTruncate.
-**
-** c) The journal file is deleted using xDelete.
-*/
-#if SQLITE_TEST /* This file is used for testing only */
-
-#include "sqlite3.h"
-#include "sqliteInt.h"
-
-/*
-** Maximum pathname length supported by the jt backend.
-*/
-#define JT_MAX_PATHNAME 512
-
-/*
-** Name used to identify this VFS.
-*/
-#define JT_VFS_NAME "jt"
-
-typedef struct jt_file jt_file;
-struct jt_file {
- sqlite3_file base;
- const char *zName; /* Name of open file */
- int flags; /* Flags the file was opened with */
-
- /* The following are only used by database file file handles */
- int eLock; /* Current lock held on the file */
- u32 nPage; /* Size of file in pages when transaction started */
- u32 nPagesize; /* Page size when transaction started */
- Bitvec *pWritable; /* Bitvec of pages that may be written to the file */
- u32 *aCksum; /* Checksum for first nPage pages */
- int nSync; /* Number of times journal file has been synced */
-
- /* Only used by journal file-handles */
- sqlite3_int64 iMaxOff; /* Maximum offset written to this transaction */
-
- jt_file *pNext; /* All files are stored in a linked list */
- sqlite3_file *pReal; /* The file handle for the underlying vfs */
-};
-
-/*
-** Method declarations for jt_file.
-*/
-static int jtClose(sqlite3_file*);
-static int jtRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int jtWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int jtTruncate(sqlite3_file*, sqlite3_int64 size);
-static int jtSync(sqlite3_file*, int flags);
-static int jtFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int jtLock(sqlite3_file*, int);
-static int jtUnlock(sqlite3_file*, int);
-static int jtCheckReservedLock(sqlite3_file*, int *);
-static int jtFileControl(sqlite3_file*, int op, void *pArg);
-static int jtSectorSize(sqlite3_file*);
-static int jtDeviceCharacteristics(sqlite3_file*);
-
-/*
-** Method declarations for jt_vfs.
-*/
-static int jtOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int jtDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int jtAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int jtFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-static void *jtDlOpen(sqlite3_vfs*, const char *zFilename);
-static void jtDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*jtDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
-static void jtDlClose(sqlite3_vfs*, void*);
-static int jtRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int jtSleep(sqlite3_vfs*, int microseconds);
-static int jtCurrentTime(sqlite3_vfs*, double*);
-static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-static int jtGetLastError(sqlite3_vfs*, int, char*);
-
-static sqlite3_vfs jt_vfs = {
- 2, /* iVersion */
- sizeof(jt_file), /* szOsFile */
- JT_MAX_PATHNAME, /* mxPathname */
- 0, /* pNext */
- JT_VFS_NAME, /* zName */
- 0, /* pAppData */
- jtOpen, /* xOpen */
- jtDelete, /* xDelete */
- jtAccess, /* xAccess */
- jtFullPathname, /* xFullPathname */
- jtDlOpen, /* xDlOpen */
- jtDlError, /* xDlError */
- jtDlSym, /* xDlSym */
- jtDlClose, /* xDlClose */
- jtRandomness, /* xRandomness */
- jtSleep, /* xSleep */
- jtCurrentTime, /* xCurrentTime */
- jtGetLastError, /* xGetLastError */
- jtCurrentTimeInt64 /* xCurrentTimeInt64 */
-};
-
-static sqlite3_io_methods jt_io_methods = {
- 1, /* iVersion */
- jtClose, /* xClose */
- jtRead, /* xRead */
- jtWrite, /* xWrite */
- jtTruncate, /* xTruncate */
- jtSync, /* xSync */
- jtFileSize, /* xFileSize */
- jtLock, /* xLock */
- jtUnlock, /* xUnlock */
- jtCheckReservedLock, /* xCheckReservedLock */
- jtFileControl, /* xFileControl */
- jtSectorSize, /* xSectorSize */
- jtDeviceCharacteristics /* xDeviceCharacteristics */
-};
-
-struct JtGlobal {
- sqlite3_vfs *pVfs; /* Parent VFS */
- jt_file *pList; /* List of all open files */
-};
-static struct JtGlobal g = {0, 0};
-
-/*
-** Functions to obtain and relinquish a mutex to protect g.pList. The
-** STATIC_PRNG mutex is reused, purely for the sake of convenience.
-*/
-static void enterJtMutex(void){
- sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG));
-}
-static void leaveJtMutex(void){
- sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG));
-}
-
-extern int sqlite3_io_error_pending;
-extern int sqlite3_io_error_hit;
-static void stop_ioerr_simulation(int *piSave, int *piSave2){
- *piSave = sqlite3_io_error_pending;
- *piSave2 = sqlite3_io_error_hit;
- sqlite3_io_error_pending = -1;
- sqlite3_io_error_hit = 0;
-}
-static void start_ioerr_simulation(int iSave, int iSave2){
- sqlite3_io_error_pending = iSave;
- sqlite3_io_error_hit = iSave2;
-}
-
-/*
-** The jt_file pointed to by the argument may or may not be a file-handle
-** open on a main database file. If it is, and a transaction is currently
-** opened on the file, then discard all transaction related data.
-*/
-static void closeTransaction(jt_file *p){
- sqlite3BitvecDestroy(p->pWritable);
- sqlite3_free(p->aCksum);
- p->pWritable = 0;
- p->aCksum = 0;
- p->nSync = 0;
-}
-
-/*
-** Close an jt-file.
-*/
-static int jtClose(sqlite3_file *pFile){
- jt_file **pp;
- jt_file *p = (jt_file *)pFile;
-
- closeTransaction(p);
- enterJtMutex();
- if( p->zName ){
- for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext);
- *pp = p->pNext;
- }
- leaveJtMutex();
- sqlite3OsClose(p->pReal);
- return SQLITE_OK;
-}
-
-/*
-** Read data from an jt-file.
-*/
-static int jtRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- jt_file *p = (jt_file *)pFile;
- return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
-}
-
-/*
-** Parameter zJournal is the name of a journal file that is currently
-** open. This function locates and returns the handle opened on the
-** corresponding database file by the pager that currently has the
-** journal file opened. This file-handle is identified by the
-** following properties:
-**
-** a) SQLITE_OPEN_MAIN_DB was specified when the file was opened.
-**
-** b) The file-name specified when the file was opened matches
-** all but the final 8 characters of the journal file name.
-**
-** c) There is currently a reserved lock on the file. This
-** condition is waived if the noLock argument is non-zero.
-**/
-static jt_file *locateDatabaseHandle(const char *zJournal, int noLock){
- jt_file *pMain = 0;
- enterJtMutex();
- for(pMain=g.pList; pMain; pMain=pMain->pNext){
- int nName = (int)(strlen(zJournal) - strlen("-journal"));
- if( (pMain->flags&SQLITE_OPEN_MAIN_DB)
- && ((int)strlen(pMain->zName)==nName)
- && 0==memcmp(pMain->zName, zJournal, nName)
- && ((pMain->eLock>=SQLITE_LOCK_RESERVED) || noLock)
- ){
- break;
- }
- }
- leaveJtMutex();
- return pMain;
-}
-
-/*
-** Parameter z points to a buffer of 4 bytes in size containing a
-** unsigned 32-bit integer stored in big-endian format. Decode the
-** integer and return its value.
-*/
-static u32 decodeUint32(const unsigned char *z){
- return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3];
-}
-
-/*
-** Calculate a checksum from the buffer of length n bytes pointed to
-** by parameter z.
-*/
-static u32 genCksum(const unsigned char *z, int n){
- int i;
- u32 cksum = 0;
- for(i=0; i<n; i++){
- cksum = cksum + z[i] + (cksum<<3);
- }
- return cksum;
-}
-
-/*
-** The first argument, zBuf, points to a buffer containing a 28 byte
-** serialized journal header. This function deserializes four of the
-** integer fields contained in the journal header and writes their
-** values to the output variables.
-**
-** SQLITE_OK is returned if the journal-header is successfully
-** decoded. Otherwise, SQLITE_ERROR.
-*/
-static int decodeJournalHdr(
- const unsigned char *zBuf, /* Input: 28 byte journal header */
- u32 *pnRec, /* Out: Number of journalled records */
- u32 *pnPage, /* Out: Original database page count */
- u32 *pnSector, /* Out: Sector size in bytes */
- u32 *pnPagesize /* Out: Page size in bytes */
-){
- unsigned char aMagic[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7 };
- if( memcmp(aMagic, zBuf, 8) ) return SQLITE_ERROR;
- if( pnRec ) *pnRec = decodeUint32(&zBuf[8]);
- if( pnPage ) *pnPage = decodeUint32(&zBuf[16]);
- if( pnSector ) *pnSector = decodeUint32(&zBuf[20]);
- if( pnPagesize ) *pnPagesize = decodeUint32(&zBuf[24]);
- return SQLITE_OK;
-}
-
-/*
-** This function is called when a new transaction is opened, just after
-** the first journal-header is written to the journal file.
-*/
-static int openTransaction(jt_file *pMain, jt_file *pJournal){
- unsigned char *aData;
- sqlite3_file *p = pMain->pReal;
- int rc = SQLITE_OK;
-
- closeTransaction(pMain);
- aData = sqlite3_malloc(pMain->nPagesize);
- pMain->pWritable = sqlite3BitvecCreate(pMain->nPage);
- pMain->aCksum = sqlite3_malloc(sizeof(u32) * (pMain->nPage + 1));
- pJournal->iMaxOff = 0;
-
- if( !pMain->pWritable || !pMain->aCksum || !aData ){
- rc = SQLITE_IOERR_NOMEM;
- }else if( pMain->nPage>0 ){
- u32 iTrunk;
- int iSave;
- int iSave2;
-
- stop_ioerr_simulation(&iSave, &iSave2);
-
- /* Read the database free-list. Add the page-number for each free-list
- ** leaf to the jt_file.pWritable bitvec.
- */
- rc = sqlite3OsRead(p, aData, pMain->nPagesize, 0);
- if( rc==SQLITE_OK ){
- u32 nDbsize = decodeUint32(&aData[28]);
- if( nDbsize>0 && memcmp(&aData[24], &aData[92], 4)==0 ){
- u32 iPg;
- for(iPg=nDbsize+1; iPg<=pMain->nPage; iPg++){
- sqlite3BitvecSet(pMain->pWritable, iPg);
- }
- }
- }
- iTrunk = decodeUint32(&aData[32]);
- while( rc==SQLITE_OK && iTrunk>0 ){
- u32 nLeaf;
- u32 iLeaf;
- sqlite3_int64 iOff = (i64)(iTrunk-1)*pMain->nPagesize;
- rc = sqlite3OsRead(p, aData, pMain->nPagesize, iOff);
- nLeaf = decodeUint32(&aData[4]);
- for(iLeaf=0; rc==SQLITE_OK && iLeaf<nLeaf; iLeaf++){
- u32 pgno = decodeUint32(&aData[8+4*iLeaf]);
- sqlite3BitvecSet(pMain->pWritable, pgno);
- }
- iTrunk = decodeUint32(aData);
- }
-
- /* Calculate and store a checksum for each page in the database file. */
- if( rc==SQLITE_OK ){
- int ii;
- for(ii=0; rc==SQLITE_OK && ii<(int)pMain->nPage; ii++){
- i64 iOff = (i64)(pMain->nPagesize) * (i64)ii;
- if( iOff==PENDING_BYTE ) continue;
- rc = sqlite3OsRead(pMain->pReal, aData, pMain->nPagesize, iOff);
- pMain->aCksum[ii] = genCksum(aData, pMain->nPagesize);
- if( ii+1==(int)pMain->nPage && rc==SQLITE_IOERR_SHORT_READ ){
- rc = SQLITE_OK;
- }
- }
- }
-
- start_ioerr_simulation(iSave, iSave2);
- }
-
- sqlite3_free(aData);
- return rc;
-}
-
-/*
-** The first argument to this function is a handle open on a journal file.
-** This function reads the journal file and adds the page number for each
-** page in the journal to the Bitvec object passed as the second argument.
-*/
-static int readJournalFile(jt_file *p, jt_file *pMain){
- int rc = SQLITE_OK;
- unsigned char zBuf[28];
- sqlite3_file *pReal = p->pReal;
- sqlite3_int64 iOff = 0;
- sqlite3_int64 iSize = p->iMaxOff;
- unsigned char *aPage;
- int iSave;
- int iSave2;
-
- aPage = sqlite3_malloc(pMain->nPagesize);
- if( !aPage ){
- return SQLITE_IOERR_NOMEM;
- }
-
- stop_ioerr_simulation(&iSave, &iSave2);
-
- while( rc==SQLITE_OK && iOff<iSize ){
- u32 nRec, nPage, nSector, nPagesize;
- u32 ii;
-
- /* Read and decode the next journal-header from the journal file. */
- rc = sqlite3OsRead(pReal, zBuf, 28, iOff);
- if( rc!=SQLITE_OK
- || decodeJournalHdr(zBuf, &nRec, &nPage, &nSector, &nPagesize)
- ){
- goto finish_rjf;
- }
- iOff += nSector;
-
- if( nRec==0 ){
- /* A trick. There might be another journal-header immediately
- ** following this one. In this case, 0 records means 0 records,
- ** not "read until the end of the file". See also ticket #2565.
- */
- if( iSize>=(iOff+nSector) ){
- rc = sqlite3OsRead(pReal, zBuf, 28, iOff);
- if( rc!=SQLITE_OK || 0==decodeJournalHdr(zBuf, 0, 0, 0, 0) ){
- continue;
- }
- }
- nRec = (u32)((iSize-iOff) / (pMain->nPagesize+8));
- }
-
- /* Read all the records that follow the journal-header just read. */
- for(ii=0; rc==SQLITE_OK && ii<nRec && iOff<iSize; ii++){
- u32 pgno;
- rc = sqlite3OsRead(pReal, zBuf, 4, iOff);
- if( rc==SQLITE_OK ){
- pgno = decodeUint32(zBuf);
- if( pgno>0 && pgno<=pMain->nPage ){
- if( 0==sqlite3BitvecTest(pMain->pWritable, pgno) ){
- rc = sqlite3OsRead(pReal, aPage, pMain->nPagesize, iOff+4);
- if( rc==SQLITE_OK ){
- u32 cksum = genCksum(aPage, pMain->nPagesize);
- assert( cksum==pMain->aCksum[pgno-1] );
- }
- }
- sqlite3BitvecSet(pMain->pWritable, pgno);
- }
- iOff += (8 + pMain->nPagesize);
- }
- }
-
- iOff = ((iOff + (nSector-1)) / nSector) * nSector;
- }
-
-finish_rjf:
- start_ioerr_simulation(iSave, iSave2);
- sqlite3_free(aPage);
- if( rc==SQLITE_IOERR_SHORT_READ ){
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-/*
-** Write data to an jt-file.
-*/
-static int jtWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc;
- jt_file *p = (jt_file *)pFile;
- if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){
- if( iOfst==0 ){
- jt_file *pMain = locateDatabaseHandle(p->zName, 0);
- assert( pMain );
-
- if( iAmt==28 ){
- /* Zeroing the first journal-file header. This is the end of a
- ** transaction. */
- closeTransaction(pMain);
- }else if( iAmt!=12 ){
- /* Writing the first journal header to a journal file. This happens
- ** when a transaction is first started. */
- u8 *z = (u8 *)zBuf;
- pMain->nPage = decodeUint32(&z[16]);
- pMain->nPagesize = decodeUint32(&z[24]);
- if( SQLITE_OK!=(rc=openTransaction(pMain, p)) ){
- return rc;
- }
- }
- }
- if( p->iMaxOff<(iOfst + iAmt) ){
- p->iMaxOff = iOfst + iAmt;
- }
- }
-
- if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){
- if( iAmt<(int)p->nPagesize
- && p->nPagesize%iAmt==0
- && iOfst>=(PENDING_BYTE+512)
- && iOfst+iAmt<=PENDING_BYTE+p->nPagesize
- ){
- /* No-op. This special case is hit when the backup code is copying a
- ** to a database with a larger page-size than the source database and
- ** it needs to fill in the non-locking-region part of the original
- ** pending-byte page.
- */
- }else{
- u32 pgno = (u32)(iOfst/p->nPagesize + 1);
- assert( (iAmt==1||iAmt==(int)p->nPagesize) &&
- ((iOfst+iAmt)%p->nPagesize)==0 );
- /* The following assert() statements may fail if this layer is used
- ** with a connection in "PRAGMA synchronous=off" mode. If they
- ** fail with sync=normal or sync=full, this may indicate problem. */
- assert( pgno<=p->nPage || p->nSync>0 );
- assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) );
- }
- }
-
- rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
- if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){
- jt_file *pMain = locateDatabaseHandle(p->zName, 0);
- int rc2 = readJournalFile(p, pMain);
- if( rc==SQLITE_OK ) rc = rc2;
- }
- return rc;
-}
-
-/*
-** Truncate an jt-file.
-*/
-static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){
- jt_file *p = (jt_file *)pFile;
- if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){
- /* Truncating a journal file. This is the end of a transaction. */
- jt_file *pMain = locateDatabaseHandle(p->zName, 0);
- closeTransaction(pMain);
- }
- if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){
- u32 pgno;
- u32 locking_page = (u32)(PENDING_BYTE/p->nPagesize+1);
- for(pgno=(u32)(size/p->nPagesize+1); pgno<=p->nPage; pgno++){
- assert( pgno==locking_page || sqlite3BitvecTest(p->pWritable, pgno) );
- }
- }
- return sqlite3OsTruncate(p->pReal, size);
-}
-
-/*
-** Sync an jt-file.
-*/
-static int jtSync(sqlite3_file *pFile, int flags){
- jt_file *p = (jt_file *)pFile;
-
- if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){
- int rc;
- jt_file *pMain; /* The associated database file */
-
- /* The journal file is being synced. At this point, we inspect the
- ** contents of the file up to this point and set each bit in the
- ** jt_file.pWritable bitvec of the main database file associated with
- ** this journal file.
- */
- pMain = locateDatabaseHandle(p->zName, 0);
-
- /* Set the bitvec values */
- if( pMain && pMain->pWritable ){
- pMain->nSync++;
- rc = readJournalFile(p, pMain);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- }
-
- return sqlite3OsSync(p->pReal, flags);
-}
-
-/*
-** Return the current file-size of an jt-file.
-*/
-static int jtFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- jt_file *p = (jt_file *)pFile;
- return sqlite3OsFileSize(p->pReal, pSize);
-}
-
-/*
-** Lock an jt-file.
-*/
-static int jtLock(sqlite3_file *pFile, int eLock){
- int rc;
- jt_file *p = (jt_file *)pFile;
- rc = sqlite3OsLock(p->pReal, eLock);
- if( rc==SQLITE_OK && eLock>p->eLock ){
- p->eLock = eLock;
- }
- return rc;
-}
-
-/*
-** Unlock an jt-file.
-*/
-static int jtUnlock(sqlite3_file *pFile, int eLock){
- int rc;
- jt_file *p = (jt_file *)pFile;
- rc = sqlite3OsUnlock(p->pReal, eLock);
- if( rc==SQLITE_OK && eLock<p->eLock ){
- p->eLock = eLock;
- }
- return rc;
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an jt-file.
-*/
-static int jtCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- jt_file *p = (jt_file *)pFile;
- return sqlite3OsCheckReservedLock(p->pReal, pResOut);
-}
-
-/*
-** File control method. For custom operations on an jt-file.
-*/
-static int jtFileControl(sqlite3_file *pFile, int op, void *pArg){
- jt_file *p = (jt_file *)pFile;
- return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
-}
-
-/*
-** Return the sector-size in bytes for an jt-file.
-*/
-static int jtSectorSize(sqlite3_file *pFile){
- jt_file *p = (jt_file *)pFile;
- return sqlite3OsSectorSize(p->pReal);
-}
-
-/*
-** Return the device characteristic flags supported by an jt-file.
-*/
-static int jtDeviceCharacteristics(sqlite3_file *pFile){
- jt_file *p = (jt_file *)pFile;
- return sqlite3OsDeviceCharacteristics(p->pReal);
-}
-
-/*
-** Open an jt file handle.
-*/
-static int jtOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- int rc;
- jt_file *p = (jt_file *)pFile;
- pFile->pMethods = 0;
- p->pReal = (sqlite3_file *)&p[1];
- p->pReal->pMethods = 0;
- rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags);
- assert( rc==SQLITE_OK || p->pReal->pMethods==0 );
- if( rc==SQLITE_OK ){
- pFile->pMethods = &jt_io_methods;
- p->eLock = 0;
- p->zName = zName;
- p->flags = flags;
- p->pNext = 0;
- p->pWritable = 0;
- p->aCksum = 0;
- enterJtMutex();
- if( zName ){
- p->pNext = g.pList;
- g.pList = p;
- }
- leaveJtMutex();
- }
- return rc;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- int nPath = (int)strlen(zPath);
- if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){
- /* Deleting a journal file. The end of a transaction. */
- jt_file *pMain = locateDatabaseHandle(zPath, 0);
- if( pMain ){
- closeTransaction(pMain);
- }
- }
-
- return sqlite3OsDelete(g.pVfs, zPath, dirSync);
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int jtAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut);
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (JT_MAX_PATHNAME+1) bytes.
-*/
-static int jtFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- return sqlite3OsFullPathname(g.pVfs, zPath, nOut, zOut);
-}
-
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *jtDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return g.pVfs->xDlOpen(g.pVfs, zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void jtDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- g.pVfs->xDlError(g.pVfs, nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*jtDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return g.pVfs->xDlSym(g.pVfs, p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void jtDlClose(sqlite3_vfs *pVfs, void *pHandle){
- g.pVfs->xDlClose(g.pVfs, pHandle);
-}
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int jtRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return sqlite3OsRandomness(g.pVfs, nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int jtSleep(sqlite3_vfs *pVfs, int nMicro){
- return sqlite3OsSleep(g.pVfs, nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int jtCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
-}
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int jtCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
- return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut);
-}
-
-static int jtGetLastError(sqlite3_vfs *pVfs, int n, char *z){
- return g.pVfs->xGetLastError(g.pVfs, n, z);
-}
-
-/**************************************************************************
-** Start of public API.
-*/
-
-/*
-** Configure the jt VFS as a wrapper around the VFS named by parameter
-** zWrap. If the isDefault parameter is true, then the jt VFS is installed
-** as the new default VFS for SQLite connections. If isDefault is not
-** true, then the jt VFS is installed as non-default. In this case it
-** is available via its name, "jt".
-*/
-int jt_register(char *zWrap, int isDefault){
- g.pVfs = sqlite3_vfs_find(zWrap);
- if( g.pVfs==0 ){
- return SQLITE_ERROR;
- }
- jt_vfs.szOsFile = sizeof(jt_file) + g.pVfs->szOsFile;
- if( g.pVfs->iVersion==1 ){
- jt_vfs.iVersion = 1;
- }else if( g.pVfs->xCurrentTimeInt64==0 ){
- jt_vfs.xCurrentTimeInt64 = 0;
- }
- sqlite3_vfs_register(&jt_vfs, isDefault);
- return SQLITE_OK;
-}
-
-/*
-** Uninstall the jt VFS, if it is installed.
-*/
-void jt_unregister(void){
- sqlite3_vfs_unregister(&jt_vfs);
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_loadext.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_loadext.c
deleted file mode 100644
index 6404a69714e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_loadext.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-** 2006 June 14
-**
-** 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.
-**
-*************************************************************************
-** Test extension for testing the sqlite3_load_extension() function.
-*/
-#include <string.h>
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-/*
-** The half() SQL function returns half of its input value.
-*/
-static void halfFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3_result_double(context, 0.5*sqlite3_value_double(argv[0]));
-}
-
-/*
-** SQL functions to call the sqlite3_status function and return results.
-*/
-static void statusFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int op = 0, mx, cur, resetFlag, rc;
- if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
- op = sqlite3_value_int(argv[0]);
- }else if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
- int i;
- const char *zName;
- static const struct {
- const char *zName;
- int op;
- } aOp[] = {
- { "MEMORY_USED", SQLITE_STATUS_MEMORY_USED },
- { "PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED },
- { "PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW },
- { "SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED },
- { "SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW },
- { "MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE },
- };
- int nOp = sizeof(aOp)/sizeof(aOp[0]);
- zName = (const char*)sqlite3_value_text(argv[0]);
- for(i=0; i<nOp; i++){
- if( strcmp(aOp[i].zName, zName)==0 ){
- op = aOp[i].op;
- break;
- }
- }
- if( i>=nOp ){
- char *zMsg = sqlite3_mprintf("unknown status property: %s", zName);
- sqlite3_result_error(context, zMsg, -1);
- sqlite3_free(zMsg);
- return;
- }
- }else{
- sqlite3_result_error(context, "unknown status type", -1);
- return;
- }
- if( argc==2 ){
- resetFlag = sqlite3_value_int(argv[1]);
- }else{
- resetFlag = 0;
- }
- rc = sqlite3_status(op, &cur, &mx, resetFlag);
- if( rc!=SQLITE_OK ){
- char *zMsg = sqlite3_mprintf("sqlite3_status(%d,...) returns %d", op, rc);
- sqlite3_result_error(context, zMsg, -1);
- sqlite3_free(zMsg);
- return;
- }
- if( argc==2 ){
- sqlite3_result_int(context, mx);
- }else{
- sqlite3_result_int(context, cur);
- }
-}
-
-/*
-** Extension load function.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int testloadext_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int nErr = 0;
- SQLITE_EXTENSION_INIT2(pApi);
- nErr |= sqlite3_create_function(db, "half", 1, SQLITE_ANY, 0, halfFunc, 0, 0);
- nErr |= sqlite3_create_function(db, "sqlite3_status", 1, SQLITE_ANY, 0,
- statusFunc, 0, 0);
- nErr |= sqlite3_create_function(db, "sqlite3_status", 2, SQLITE_ANY, 0,
- statusFunc, 0, 0);
- return nErr ? SQLITE_ERROR : SQLITE_OK;
-}
-
-/*
-** Another extension entry point. This one always fails.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int testbrokenext_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- char *zErr;
- SQLITE_EXTENSION_INIT2(pApi);
- zErr = sqlite3_mprintf("broken!");
- *pzErrMsg = zErr;
- return 1;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_malloc.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_malloc.c
deleted file mode 100644
index 32a03e71911..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_malloc.c
+++ /dev/null
@@ -1,1546 +0,0 @@
-/*
-** 2007 August 15
-**
-** 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 contains code used to implement test interfaces to the
-** memory allocation subsystem.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-/*
-** This structure is used to encapsulate the global state variables used
-** by malloc() fault simulation.
-*/
-static struct MemFault {
- int iCountdown; /* Number of pending successes before a failure */
- int nRepeat; /* Number of times to repeat the failure */
- int nBenign; /* Number of benign failures seen since last config */
- int nFail; /* Number of failures seen since last config */
- int nOkBefore; /* Successful allocations prior to the first fault */
- int nOkAfter; /* Successful allocations after a fault */
- u8 enable; /* True if enabled */
- int isInstalled; /* True if the fault simulation layer is installed */
- int isBenignMode; /* True if malloc failures are considered benign */
- sqlite3_mem_methods m; /* 'Real' malloc implementation */
-} memfault;
-
-/*
-** This routine exists as a place to set a breakpoint that will
-** fire on any simulated malloc() failure.
-*/
-static void sqlite3Fault(void){
- static int cnt = 0;
- cnt++;
-}
-
-/*
-** This routine exists as a place to set a breakpoint that will
-** fire the first time any malloc() fails on a single test case.
-** The sqlite3Fault() routine above runs on every malloc() failure.
-** This routine only runs on the first such failure.
-*/
-static void sqlite3FirstFault(void){
- static int cnt2 = 0;
- cnt2++;
-}
-
-/*
-** Check to see if a fault should be simulated. Return true to simulate
-** the fault. Return false if the fault should not be simulated.
-*/
-static int faultsimStep(void){
- if( likely(!memfault.enable) ){
- memfault.nOkAfter++;
- return 0;
- }
- if( memfault.iCountdown>0 ){
- memfault.iCountdown--;
- memfault.nOkBefore++;
- return 0;
- }
- if( memfault.nFail==0 ) sqlite3FirstFault();
- sqlite3Fault();
- memfault.nFail++;
- if( memfault.isBenignMode>0 ){
- memfault.nBenign++;
- }
- memfault.nRepeat--;
- if( memfault.nRepeat<=0 ){
- memfault.enable = 0;
- }
- return 1;
-}
-
-/*
-** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation
-** logic.
-*/
-static void *faultsimMalloc(int n){
- void *p = 0;
- if( !faultsimStep() ){
- p = memfault.m.xMalloc(n);
- }
- return p;
-}
-
-
-/*
-** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation
-** logic.
-*/
-static void *faultsimRealloc(void *pOld, int n){
- void *p = 0;
- if( !faultsimStep() ){
- p = memfault.m.xRealloc(pOld, n);
- }
- return p;
-}
-
-/*
-** The following method calls are passed directly through to the underlying
-** malloc system:
-**
-** xFree
-** xSize
-** xRoundup
-** xInit
-** xShutdown
-*/
-static void faultsimFree(void *p){
- memfault.m.xFree(p);
-}
-static int faultsimSize(void *p){
- return memfault.m.xSize(p);
-}
-static int faultsimRoundup(int n){
- return memfault.m.xRoundup(n);
-}
-static int faultsimInit(void *p){
- return memfault.m.xInit(memfault.m.pAppData);
-}
-static void faultsimShutdown(void *p){
- memfault.m.xShutdown(memfault.m.pAppData);
-}
-
-/*
-** This routine configures the malloc failure simulation. After
-** calling this routine, the next nDelay mallocs will succeed, followed
-** by a block of nRepeat failures, after which malloc() calls will begin
-** to succeed again.
-*/
-static void faultsimConfig(int nDelay, int nRepeat){
- memfault.iCountdown = nDelay;
- memfault.nRepeat = nRepeat;
- memfault.nBenign = 0;
- memfault.nFail = 0;
- memfault.nOkBefore = 0;
- memfault.nOkAfter = 0;
- memfault.enable = nDelay>=0;
-
- /* Sometimes, when running multi-threaded tests, the isBenignMode
- ** variable is not properly incremented/decremented so that it is
- ** 0 when not inside a benign malloc block. This doesn't affect
- ** the multi-threaded tests, as they do not use this system. But
- ** it does affect OOM tests run later in the same process. So
- ** zero the variable here, just to be sure.
- */
- memfault.isBenignMode = 0;
-}
-
-/*
-** Return the number of faults (both hard and benign faults) that have
-** occurred since the injector was last configured.
-*/
-static int faultsimFailures(void){
- return memfault.nFail;
-}
-
-/*
-** Return the number of benign faults that have occurred since the
-** injector was last configured.
-*/
-static int faultsimBenignFailures(void){
- return memfault.nBenign;
-}
-
-/*
-** Return the number of successes that will occur before the next failure.
-** If no failures are scheduled, return -1.
-*/
-static int faultsimPending(void){
- if( memfault.enable ){
- return memfault.iCountdown;
- }else{
- return -1;
- }
-}
-
-
-static void faultsimBeginBenign(void){
- memfault.isBenignMode++;
-}
-static void faultsimEndBenign(void){
- memfault.isBenignMode--;
-}
-
-/*
-** Add or remove the fault-simulation layer using sqlite3_config(). If
-** the argument is non-zero, the
-*/
-static int faultsimInstall(int install){
- static struct sqlite3_mem_methods m = {
- faultsimMalloc, /* xMalloc */
- faultsimFree, /* xFree */
- faultsimRealloc, /* xRealloc */
- faultsimSize, /* xSize */
- faultsimRoundup, /* xRoundup */
- faultsimInit, /* xInit */
- faultsimShutdown, /* xShutdown */
- 0 /* pAppData */
- };
- int rc;
-
- install = (install ? 1 : 0);
- assert(memfault.isInstalled==1 || memfault.isInstalled==0);
-
- if( install==memfault.isInstalled ){
- return SQLITE_ERROR;
- }
-
- if( install ){
- rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
- assert(memfault.m.xMalloc);
- if( rc==SQLITE_OK ){
- rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
- }
- sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
- faultsimBeginBenign, faultsimEndBenign
- );
- }else{
- sqlite3_mem_methods m2;
- assert(memfault.m.xMalloc);
-
- /* One should be able to reset the default memory allocator by storing
- ** a zeroed allocator then calling GETMALLOC. */
- memset(&m2, 0, sizeof(m2));
- sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
- sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
- assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
-
- rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
- sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
- (void*)0, (void*)0);
- }
-
- if( rc==SQLITE_OK ){
- memfault.isInstalled = 1;
- }
- return rc;
-}
-
-#ifdef SQLITE_TEST
-
-/*
-** This function is implemented in main.c. Returns a pointer to a static
-** buffer containing the symbolic SQLite error code that corresponds to
-** the least-significant 8-bits of the integer passed as an argument.
-** For example:
-**
-** sqlite3ErrName(1) -> "SQLITE_ERROR"
-*/
-extern const char *sqlite3ErrName(int);
-
-/*
-** Transform pointers to text and back again
-*/
-static void pointerToText(void *p, char *z){
- static const char zHex[] = "0123456789abcdef";
- int i, k;
- unsigned int u;
- sqlite3_uint64 n;
- if( p==0 ){
- strcpy(z, "0");
- return;
- }
- if( sizeof(n)==sizeof(p) ){
- memcpy(&n, &p, sizeof(p));
- }else if( sizeof(u)==sizeof(p) ){
- memcpy(&u, &p, sizeof(u));
- n = u;
- }else{
- assert( 0 );
- }
- for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){
- z[k] = zHex[n&0xf];
- n >>= 4;
- }
- z[sizeof(p)*2] = 0;
-}
-static int hexToInt(int h){
- if( h>='0' && h<='9' ){
- return h - '0';
- }else if( h>='a' && h<='f' ){
- return h - 'a' + 10;
- }else{
- return -1;
- }
-}
-static int textToPointer(const char *z, void **pp){
- sqlite3_uint64 n = 0;
- int i;
- unsigned int u;
- for(i=0; i<sizeof(void*)*2 && z[0]; i++){
- int v;
- v = hexToInt(*z++);
- if( v<0 ) return TCL_ERROR;
- n = n*16 + v;
- }
- if( *z!=0 ) return TCL_ERROR;
- if( sizeof(n)==sizeof(*pp) ){
- memcpy(pp, &n, sizeof(n));
- }else if( sizeof(u)==sizeof(*pp) ){
- u = (unsigned int)n;
- memcpy(pp, &u, sizeof(u));
- }else{
- assert( 0 );
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_malloc NBYTES
-**
-** Raw test interface for sqlite3_malloc().
-*/
-static int SQLITE_TCLAPI test_malloc(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int nByte;
- void *p;
- char zOut[100];
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NBYTES");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR;
- p = sqlite3_malloc((unsigned)nByte);
- pointerToText(p, zOut);
- Tcl_AppendResult(interp, zOut, NULL);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_realloc PRIOR NBYTES
-**
-** Raw test interface for sqlite3_realloc().
-*/
-static int SQLITE_TCLAPI test_realloc(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int nByte;
- void *pPrior, *p;
- char zOut[100];
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR;
- if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
- Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- p = sqlite3_realloc(pPrior, (unsigned)nByte);
- pointerToText(p, zOut);
- Tcl_AppendResult(interp, zOut, NULL);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_free PRIOR
-**
-** Raw test interface for sqlite3_free().
-*/
-static int SQLITE_TCLAPI test_free(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void *pPrior;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PRIOR");
- return TCL_ERROR;
- }
- if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
- Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- sqlite3_free(pPrior);
- return TCL_OK;
-}
-
-/*
-** These routines are in test_hexio.c
-*/
-int sqlite3TestHexToBin(const char *, int, char *);
-int sqlite3TestBinToHex(char*,int);
-
-/*
-** Usage: memset ADDRESS SIZE HEX
-**
-** Set a chunk of memory (obtained from malloc, probably) to a
-** specified hex pattern.
-*/
-static int SQLITE_TCLAPI test_memset(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void *p;
- int size, n, i;
- char *zHex;
- char *zOut;
- char zBin[100];
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX");
- return TCL_ERROR;
- }
- if( textToPointer(Tcl_GetString(objv[1]), &p) ){
- Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
- return TCL_ERROR;
- }
- if( size<=0 ){
- Tcl_AppendResult(interp, "size must be positive", (char*)0);
- return TCL_ERROR;
- }
- zHex = Tcl_GetStringFromObj(objv[3], &n);
- if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;
- n = sqlite3TestHexToBin(zHex, n, zBin);
- if( n==0 ){
- Tcl_AppendResult(interp, "no data", (char*)0);
- return TCL_ERROR;
- }
- zOut = p;
- for(i=0; i<size; i++){
- zOut[i] = zBin[i%n];
- }
- return TCL_OK;
-}
-
-/*
-** Usage: memget ADDRESS SIZE
-**
-** Return memory as hexadecimal text.
-*/
-static int SQLITE_TCLAPI test_memget(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void *p;
- int size, n;
- char *zBin;
- char zHex[100];
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE");
- return TCL_ERROR;
- }
- if( textToPointer(Tcl_GetString(objv[1]), &p) ){
- Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
- return TCL_ERROR;
- }
- if( size<=0 ){
- Tcl_AppendResult(interp, "size must be positive", (char*)0);
- return TCL_ERROR;
- }
- zBin = p;
- while( size>0 ){
- if( size>(sizeof(zHex)-1)/2 ){
- n = (sizeof(zHex)-1)/2;
- }else{
- n = size;
- }
- memcpy(zHex, zBin, n);
- zBin += n;
- size -= n;
- sqlite3TestBinToHex(zHex, n);
- Tcl_AppendResult(interp, zHex, (char*)0);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_memory_used
-**
-** Raw test interface for sqlite3_memory_used().
-*/
-static int SQLITE_TCLAPI test_memory_used(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used()));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_memory_highwater ?RESETFLAG?
-**
-** Raw test interface for sqlite3_memory_highwater().
-*/
-static int SQLITE_TCLAPI test_memory_highwater(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int resetFlag = 0;
- if( objc!=1 && objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?RESET?");
- return TCL_ERROR;
- }
- if( objc==2 ){
- if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR;
- }
- Tcl_SetObjResult(interp,
- Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag)));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_memdebug_backtrace DEPTH
-**
-** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined
-** then this routine is a no-op.
-*/
-static int SQLITE_TCLAPI test_memdebug_backtrace(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int depth;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DEPT");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR;
-#ifdef SQLITE_MEMDEBUG
- {
- extern void sqlite3MemdebugBacktrace(int);
- sqlite3MemdebugBacktrace(depth);
- }
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_memdebug_dump FILENAME
-**
-** Write a summary of unfreed memory to FILENAME.
-*/
-static int SQLITE_TCLAPI test_memdebug_dump(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
- return TCL_ERROR;
- }
-#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \
- || defined(SQLITE_POW2_MEMORY_SIZE)
- {
- extern void sqlite3MemdebugDump(const char*);
- sqlite3MemdebugDump(Tcl_GetString(objv[1]));
- }
-#endif
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_memdebug_malloc_count
-**
-** Return the total number of times malloc() has been called.
-*/
-static int SQLITE_TCLAPI test_memdebug_malloc_count(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int nMalloc = -1;
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-#if defined(SQLITE_MEMDEBUG)
- {
- extern int sqlite3MemdebugMallocCount();
- nMalloc = sqlite3MemdebugMallocCount();
- }
-#endif
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc));
- return TCL_OK;
-}
-
-
-/*
-** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS?
-**
-** where options are:
-**
-** -repeat <count>
-** -benigncnt <varname>
-**
-** Arrange for a simulated malloc() failure after COUNTER successes.
-** If a repeat count is specified, the fault is repeated that many
-** times.
-**
-** Each call to this routine overrides the prior counter value.
-** This routine returns the number of simulated failures that have
-** happened since the previous call to this routine.
-**
-** To disable simulated failures, use a COUNTER of -1.
-*/
-static int SQLITE_TCLAPI test_memdebug_fail(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int ii;
- int iFail;
- int nRepeat = 1;
- Tcl_Obj *pBenignCnt = 0;
- int nBenign;
- int nFail = 0;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR;
-
- for(ii=2; ii<objc; ii+=2){
- int nOption;
- char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption);
- char *zErr = 0;
-
- if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){
- if( ii==(objc-1) ){
- zErr = "option requires an argument: ";
- }else{
- if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){
- return TCL_ERROR;
- }
- }
- }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){
- if( ii==(objc-1) ){
- zErr = "option requires an argument: ";
- }else{
- pBenignCnt = objv[ii+1];
- }
- }else{
- zErr = "unknown option: ";
- }
-
- if( zErr ){
- Tcl_AppendResult(interp, zErr, zOption, 0);
- return TCL_ERROR;
- }
- }
-
- nBenign = faultsimBenignFailures();
- nFail = faultsimFailures();
- faultsimConfig(iFail, nRepeat);
-
- if( pBenignCnt ){
- Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_memdebug_pending
-**
-** Return the number of malloc() calls that will succeed before a
-** simulated failure occurs. A negative return value indicates that
-** no malloc() failure is scheduled.
-*/
-static int SQLITE_TCLAPI test_memdebug_pending(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int nPending;
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
- nPending = faultsimPending();
- Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
- return TCL_OK;
-}
-
-/*
-** The following global variable keeps track of the number of tests
-** that have run. This variable is only useful when running in the
-** debugger.
-*/
-static int sqlite3_memdebug_title_count = 0;
-
-/*
-** Usage: sqlite3_memdebug_settitle TITLE
-**
-** Set a title string stored with each allocation. The TITLE is
-** typically the name of the test that was running when the
-** allocation occurred. The TITLE is stored with the allocation
-** and can be used to figure out which tests are leaking memory.
-**
-** Each title overwrite the previous.
-*/
-static int SQLITE_TCLAPI test_memdebug_settitle(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_memdebug_title_count++;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "TITLE");
- return TCL_ERROR;
- }
-#ifdef SQLITE_MEMDEBUG
- {
- const char *zTitle;
- extern int sqlite3MemdebugSettitle(const char*);
- zTitle = Tcl_GetString(objv[1]);
- sqlite3MemdebugSettitle(zTitle);
- }
-#endif
- return TCL_OK;
-}
-
-#define MALLOC_LOG_FRAMES 10
-#define MALLOC_LOG_KEYINTS ( \
- 10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int)) \
-)
-static Tcl_HashTable aMallocLog;
-static int mallocLogEnabled = 0;
-
-typedef struct MallocLog MallocLog;
-struct MallocLog {
- int nCall;
- int nByte;
-};
-
-#ifdef SQLITE_MEMDEBUG
-static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){
- if( mallocLogEnabled ){
- MallocLog *pLog;
- Tcl_HashEntry *pEntry;
- int isNew;
-
- int aKey[MALLOC_LOG_KEYINTS];
- unsigned int nKey = sizeof(int)*MALLOC_LOG_KEYINTS;
-
- memset(aKey, 0, nKey);
- if( (sizeof(void*)*nFrame)<nKey ){
- nKey = nFrame*sizeof(void*);
- }
- memcpy(aKey, aFrame, nKey);
-
- pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew);
- if( isNew ){
- pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog));
- memset(pLog, 0, sizeof(MallocLog));
- Tcl_SetHashValue(pEntry, (ClientData)pLog);
- }else{
- pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
- }
-
- pLog->nCall++;
- pLog->nByte += nByte;
- }
-}
-#endif /* SQLITE_MEMDEBUG */
-
-static void test_memdebug_log_clear(void){
- Tcl_HashSearch search;
- Tcl_HashEntry *pEntry;
- for(
- pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
- pEntry;
- pEntry=Tcl_NextHashEntry(&search)
- ){
- MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
- Tcl_Free((char *)pLog);
- }
- Tcl_DeleteHashTable(&aMallocLog);
- Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
-}
-
-static int SQLITE_TCLAPI test_memdebug_log(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- static int isInit = 0;
- int iSub;
-
- static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" };
- enum MB_enum {
- MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC
- };
-
- if( !isInit ){
-#ifdef SQLITE_MEMDEBUG
- extern void sqlite3MemdebugBacktraceCallback(
- void (*xBacktrace)(int, int, void **));
- sqlite3MemdebugBacktraceCallback(test_memdebug_callback);
-#endif
- Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
- isInit = 1;
- }
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
- }
- if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){
- return TCL_ERROR;
- }
-
- switch( (enum MB_enum)iSub ){
- case MB_LOG_START:
- mallocLogEnabled = 1;
- break;
- case MB_LOG_STOP:
- mallocLogEnabled = 0;
- break;
- case MB_LOG_DUMP: {
- Tcl_HashSearch search;
- Tcl_HashEntry *pEntry;
- Tcl_Obj *pRet = Tcl_NewObj();
-
- assert(sizeof(Tcl_WideInt)>=sizeof(void*));
-
- for(
- pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
- pEntry;
- pEntry=Tcl_NextHashEntry(&search)
- ){
- Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2];
- MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
- Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry);
- int ii;
-
- apElem[0] = Tcl_NewIntObj(pLog->nCall);
- apElem[1] = Tcl_NewIntObj(pLog->nByte);
- for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){
- apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]);
- }
-
- Tcl_ListObjAppendElement(interp, pRet,
- Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem)
- );
- }
-
- Tcl_SetObjResult(interp, pRet);
- break;
- }
- case MB_LOG_CLEAR: {
- test_memdebug_log_clear();
- break;
- }
-
- case MB_LOG_SYNC: {
-#ifdef SQLITE_MEMDEBUG
- extern void sqlite3MemdebugSync();
- test_memdebug_log_clear();
- mallocLogEnabled = 1;
- sqlite3MemdebugSync();
-#endif
- break;
- }
- }
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_pagecache SIZE N
-**
-** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
-** The buffer is static and is of limited size. N might be
-** adjusted downward as needed to accommodate the requested size.
-** The revised value of N is returned.
-**
-** A negative SIZE causes the buffer pointer to be NULL.
-*/
-static int SQLITE_TCLAPI test_config_pagecache(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int sz, N;
- Tcl_Obj *pRes;
- static char *buf = 0;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
- free(buf);
- buf = 0;
-
- /* Set the return value */
- pRes = Tcl_NewObj();
- Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.szPage));
- Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.nPage));
- Tcl_SetObjResult(interp, pRes);
-
- if( sz<0 ){
- sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, 0);
- }else{
- buf = malloc( sz*N );
- sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED
-**
-** Set up the alternative test page cache. Install if INSTALL_FLAG is
-** true and uninstall (reverting to the default page cache) if INSTALL_FLAG
-** is false. DISCARD_CHANGE is an integer between 0 and 100 inclusive
-** which determines the chance of discarding a page when unpinned. 100
-** is certainty. 0 is never. PRNG_SEED is the pseudo-random number generator
-** seed.
-*/
-static int SQLITE_TCLAPI test_alt_pcache(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int installFlag;
- int discardChance = 0;
- int prngSeed = 0;
- int highStress = 0;
- extern void installTestPCache(int,unsigned,unsigned,unsigned);
- if( objc<2 || objc>5 ){
- Tcl_WrongNumArgs(interp, 1, objv,
- "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL_ERROR;
- if( objc>=3 && Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){
- return TCL_ERROR;
- }
- if( objc>=4 && Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){
- return TCL_ERROR;
- }
- if( objc>=5 && Tcl_GetIntFromObj(interp, objv[4], &highStress) ){
- return TCL_ERROR;
- }
- if( discardChance<0 || discardChance>100 ){
- Tcl_AppendResult(interp, "discard-chance should be between 0 and 100",
- (char*)0);
- return TCL_ERROR;
- }
- installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed,
- (unsigned)highStress);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_memstatus BOOLEAN
-**
-** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS.
-*/
-static int SQLITE_TCLAPI test_config_memstatus(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int enable, rc;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
- return TCL_ERROR;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR;
- rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_lookaside SIZE COUNT
-**
-*/
-static int SQLITE_TCLAPI test_config_lookaside(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int sz, cnt;
- Tcl_Obj *pRet;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR;
- pRet = Tcl_NewObj();
- Tcl_ListObjAppendElement(
- interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.szLookaside)
- );
- Tcl_ListObjAppendElement(
- interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.nLookaside)
- );
- sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt);
- Tcl_SetObjResult(interp, pRet);
- return TCL_OK;
-}
-
-
-/*
-** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT
-**
-** There are two static buffers with BUFID 1 and 2. Each static buffer
-** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL
-** which will cause sqlite3_db_config() to allocate space on its own.
-*/
-static int SQLITE_TCLAPI test_db_config_lookaside(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- int sz, cnt;
- sqlite3 *db;
- int bufid;
- static char azBuf[2][10000];
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR;
- if( bufid==0 ){
- rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, (void*)0, sz, cnt);
- }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){
- rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt);
- }else{
- Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0);
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_heap NBYTE NMINALLOC
-*/
-static int SQLITE_TCLAPI test_config_heap(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- static char *zBuf; /* Use this memory */
- int nByte; /* Size of buffer to pass to sqlite3_config() */
- int nMinAlloc; /* Size of minimum allocation */
- int rc; /* Return code of sqlite3_config() */
-
- Tcl_Obj * CONST *aArg = &objv[1];
- int nArg = objc-1;
-
- if( nArg!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR;
-
- if( nByte==0 ){
- free( zBuf );
- zBuf = 0;
- rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0);
- }else{
- zBuf = realloc(zBuf, nByte);
- rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc);
- }
-
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_heap_size NBYTE
-*/
-static int SQLITE_TCLAPI test_config_heap_size(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int nByte; /* Size to pass to sqlite3_config() */
- int rc; /* Return code of sqlite3_config() */
-
- Tcl_Obj * CONST *aArg = &objv[1];
- int nArg = objc-1;
-
- if( nArg!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
-
- rc = sqlite3_config(SQLITE_CONFIG_WIN32_HEAPSIZE, nByte);
-
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_error [DB]
-**
-** Invoke sqlite3_config() or sqlite3_db_config() with invalid
-** opcodes and verify that they return errors.
-*/
-static int SQLITE_TCLAPI test_config_error(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
-
- if( objc!=2 && objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "[DB]");
- return TCL_ERROR;
- }
- if( objc==2 ){
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){
- Tcl_AppendResult(interp,
- "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR",
- (char*)0);
- return TCL_ERROR;
- }
- }else{
- if( sqlite3_config(99999)!=SQLITE_ERROR ){
- Tcl_AppendResult(interp,
- "sqlite3_config(99999) does not return SQLITE_ERROR",
- (char*)0);
- return TCL_ERROR;
- }
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_uri BOOLEAN
-**
-** Enables or disables interpretation of URI parameters by default using
-** SQLITE_CONFIG_URI.
-*/
-static int SQLITE_TCLAPI test_config_uri(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- int bOpenUri;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
- return TCL_ERROR;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
- return TCL_ERROR;
- }
-
- rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_cis BOOLEAN
-**
-** Enables or disables the use of the covering-index scan optimization.
-** SQLITE_CONFIG_COVERING_INDEX_SCAN.
-*/
-static int SQLITE_TCLAPI test_config_cis(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- int bUseCis;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
- return TCL_ERROR;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){
- return TCL_ERROR;
- }
-
- rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
-
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_config_pmasz INTEGER
-**
-** Set the minimum PMA size.
-*/
-static int SQLITE_TCLAPI test_config_pmasz(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- int iPmaSz;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &iPmaSz) ){
- return TCL_ERROR;
- }
-
- rc = sqlite3_config(SQLITE_CONFIG_PMASZ, iPmaSz);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
-
- return TCL_OK;
-}
-
-
-/*
-** Usage: sqlite3_dump_memsys3 FILENAME
-** sqlite3_dump_memsys5 FILENAME
-**
-** Write a summary of unfreed memsys3 allocations to FILENAME.
-*/
-static int SQLITE_TCLAPI test_dump_memsys3(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
- return TCL_ERROR;
- }
-
- switch( SQLITE_PTR_TO_INT(clientData) ){
- case 3: {
-#ifdef SQLITE_ENABLE_MEMSYS3
- extern void sqlite3Memsys3Dump(const char*);
- sqlite3Memsys3Dump(Tcl_GetString(objv[1]));
- break;
-#endif
- }
- case 5: {
-#ifdef SQLITE_ENABLE_MEMSYS5
- extern void sqlite3Memsys5Dump(const char*);
- sqlite3Memsys5Dump(Tcl_GetString(objv[1]));
- break;
-#endif
- }
- }
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_status OPCODE RESETFLAG
-**
-** Return a list of three elements which are the sqlite3_status() return
-** code, the current value, and the high-water mark value.
-*/
-static int SQLITE_TCLAPI test_status(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc, iValue, mxValue;
- int i, op = 0, resetFlag;
- const char *zOpName;
- static const struct {
- const char *zName;
- int op;
- } aOp[] = {
- { "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED },
- { "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE },
- { "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED },
- { "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW },
- { "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE },
- { "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED },
- { "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW },
- { "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE },
- { "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK },
- { "SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT },
- };
- Tcl_Obj *pResult;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
- return TCL_ERROR;
- }
- zOpName = Tcl_GetString(objv[1]);
- for(i=0; i<ArraySize(aOp); i++){
- if( strcmp(aOp[i].zName, zOpName)==0 ){
- op = aOp[i].op;
- break;
- }
- }
- if( i>=ArraySize(aOp) ){
- if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR;
- iValue = 0;
- mxValue = 0;
- rc = sqlite3_status(op, &iValue, &mxValue, resetFlag);
- pResult = Tcl_NewObj();
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG
-**
-** Return a list of three elements which are the sqlite3_db_status() return
-** code, the current value, and the high-water mark value.
-*/
-static int SQLITE_TCLAPI test_db_status(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc, iValue, mxValue;
- int i, op = 0, resetFlag;
- const char *zOpName;
- sqlite3 *db;
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- static const struct {
- const char *zName;
- int op;
- } aOp[] = {
- { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
- { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED },
- { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED },
- { "STMT_USED", SQLITE_DBSTATUS_STMT_USED },
- { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT },
- { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE },
- { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL },
- { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT },
- { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS },
- { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE },
- { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS },
- { "CACHE_USED_SHARED", SQLITE_DBSTATUS_CACHE_USED_SHARED },
- { "CACHE_SPILL", SQLITE_DBSTATUS_CACHE_SPILL },
- };
- Tcl_Obj *pResult;
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zOpName = Tcl_GetString(objv[2]);
- if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7;
- if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9;
- for(i=0; i<ArraySize(aOp); i++){
- if( strcmp(aOp[i].zName, zOpName)==0 ){
- op = aOp[i].op;
- break;
- }
- }
- if( i>=ArraySize(aOp) ){
- if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
- }
- if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
- iValue = 0;
- mxValue = 0;
- rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag);
- pResult = Tcl_NewObj();
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
-}
-
-/*
-** install_malloc_faultsim BOOLEAN
-*/
-static int SQLITE_TCLAPI test_install_malloc_faultsim(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- int isInstall;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
- return TCL_ERROR;
- }
- if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
- return TCL_ERROR;
- }
- rc = faultsimInstall(isInstall);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_OK;
-}
-
-/*
-** sqlite3_install_memsys3
-*/
-static int SQLITE_TCLAPI test_install_memsys3(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = SQLITE_MISUSE;
-#ifdef SQLITE_ENABLE_MEMSYS3
- const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
- rc = sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetMemsys3());
-#endif
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_vfs_oom_test(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- extern int sqlite3_memdebug_vfs_oom_test;
- if( objc>2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "?INTEGER?");
- return TCL_ERROR;
- }else if( objc==2 ){
- int iNew;
- if( Tcl_GetIntFromObj(interp, objv[1], &iNew) ) return TCL_ERROR;
- sqlite3_memdebug_vfs_oom_test = iNew;
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_vfs_oom_test));
- return TCL_OK;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest_malloc_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- int clientData;
- } aObjCmd[] = {
- { "sqlite3_malloc", test_malloc ,0 },
- { "sqlite3_realloc", test_realloc ,0 },
- { "sqlite3_free", test_free ,0 },
- { "memset", test_memset ,0 },
- { "memget", test_memget ,0 },
- { "sqlite3_memory_used", test_memory_used ,0 },
- { "sqlite3_memory_highwater", test_memory_highwater ,0 },
- { "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 },
- { "sqlite3_memdebug_dump", test_memdebug_dump ,0 },
- { "sqlite3_memdebug_fail", test_memdebug_fail ,0 },
- { "sqlite3_memdebug_pending", test_memdebug_pending ,0 },
- { "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 },
- { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 },
- { "sqlite3_memdebug_log", test_memdebug_log ,0 },
- { "sqlite3_config_pagecache", test_config_pagecache ,0 },
- { "sqlite3_config_alt_pcache", test_alt_pcache ,0 },
- { "sqlite3_status", test_status ,0 },
- { "sqlite3_db_status", test_db_status ,0 },
- { "install_malloc_faultsim", test_install_malloc_faultsim ,0 },
- { "sqlite3_config_heap", test_config_heap ,0 },
- { "sqlite3_config_heap_size", test_config_heap_size ,0 },
- { "sqlite3_config_memstatus", test_config_memstatus ,0 },
- { "sqlite3_config_lookaside", test_config_lookaside ,0 },
- { "sqlite3_config_error", test_config_error ,0 },
- { "sqlite3_config_uri", test_config_uri ,0 },
- { "sqlite3_config_cis", test_config_cis ,0 },
- { "sqlite3_config_pmasz", test_config_pmasz ,0 },
- { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
- { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
- { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
- { "sqlite3_install_memsys3", test_install_memsys3 ,0 },
- { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData);
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);
- }
- return TCL_OK;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_md5.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_md5.c
deleted file mode 100644
index b670026861a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_md5.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
-** 2017-10-13
-**
-** 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 contains code to implement an MD5 extension to TCL.
-*/
-#include "sqlite3.h"
-#include <stdlib.h>
-#include <string.h>
-#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-/*
- * If compiled on a machine that doesn't have a 32-bit integer,
- * you just set "uint32" to the appropriate datatype for an
- * unsigned 32-bit integer. For example:
- *
- * cc -Duint32='unsigned long' md5.c
- *
- */
-#ifndef uint32
-# define uint32 unsigned int
-#endif
-
-struct MD5Context {
- int isInit;
- uint32 buf[4];
- uint32 bits[2];
- unsigned char in[64];
-};
-typedef struct MD5Context MD5Context;
-
-/*
- * Note: this code is harmless on little-endian machines.
- */
-static void byteReverse (unsigned char *buf, unsigned longs){
- uint32 t;
- do {
- t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
- ((unsigned)buf[1]<<8 | buf[0]);
- *(uint32 *)buf = t;
- buf += 4;
- } while (--longs);
-}
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(uint32 buf[4], const uint32 in[16]){
- register uint32 a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-/*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-static void MD5Init(MD5Context *ctx){
- ctx->isInit = 1;
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-static
-void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
- uint32 t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if ( t ) {
- unsigned char *p = (unsigned char *)ctx->in + t;
-
- t = 64-t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- buf += t;
- len -= t;
- }
-
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-static void MD5Final(unsigned char digest[16], MD5Context *ctx){
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count-8);
- }
- byteReverse(ctx->in, 14);
-
- /* Append length in bits and transform */
- memcpy(ctx->in + 14*4, ctx->bits, 8);
-
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- byteReverse((unsigned char *)ctx->buf, 4);
- memcpy(digest, ctx->buf, 16);
-}
-
-/*
-** Convert a 128-bit MD5 digest into a 32-digit base-16 number.
-*/
-static void MD5DigestToBase16(unsigned char *digest, char *zBuf){
- static char const zEncode[] = "0123456789abcdef";
- int i, j;
-
- for(j=i=0; i<16; i++){
- int a = digest[i];
- zBuf[j++] = zEncode[(a>>4)&0xf];
- zBuf[j++] = zEncode[a & 0xf];
- }
- zBuf[j] = 0;
-}
-
-
-/*
-** Convert a 128-bit MD5 digest into sequency of eight 5-digit integers
-** each representing 16 bits of the digest and separated from each
-** other by a "-" character.
-*/
-static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){
- int i, j;
- unsigned int x;
- for(i=j=0; i<16; i+=2){
- x = digest[i]*256 + digest[i+1];
- if( i>0 ) zDigest[j++] = '-';
- sqlite3_snprintf(50-j, &zDigest[j], "%05u", x);
- j += 5;
- }
- zDigest[j] = 0;
-}
-
-/*
-** A TCL command for md5. The argument is the text to be hashed. The
-** Result is the hash in base64.
-*/
-static int SQLITE_TCLAPI md5_cmd(
- void*cd,
- Tcl_Interp *interp,
- int argc,
- const char **argv
-){
- MD5Context ctx;
- unsigned char digest[16];
- char zBuf[50];
- void (*converter)(unsigned char*, char*);
-
- if( argc!=2 ){
- Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
- " TEXT\"", (char*)0);
- return TCL_ERROR;
- }
- MD5Init(&ctx);
- MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1]));
- MD5Final(digest, &ctx);
- converter = (void(*)(unsigned char*,char*))cd;
- converter(digest, zBuf);
- Tcl_AppendResult(interp, zBuf, (char*)0);
- return TCL_OK;
-}
-
-/*
-** A TCL command to take the md5 hash of a file. The argument is the
-** name of the file.
-*/
-static int SQLITE_TCLAPI md5file_cmd(
- void*cd,
- Tcl_Interp *interp,
- int argc,
- const char **argv
-){
- FILE *in;
- int ofst;
- int amt;
- MD5Context ctx;
- void (*converter)(unsigned char*, char*);
- unsigned char digest[16];
- char zBuf[10240];
-
- if( argc!=2 && argc!=4 ){
- Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
- " FILENAME [OFFSET AMT]\"", (char*)0);
- return TCL_ERROR;
- }
- if( argc==4 ){
- ofst = atoi(argv[2]);
- amt = atoi(argv[3]);
- }else{
- ofst = 0;
- amt = 2147483647;
- }
- in = fopen(argv[1],"rb");
- if( in==0 ){
- Tcl_AppendResult(interp,"unable to open file \"", argv[1],
- "\" for reading", (char*)0);
- return TCL_ERROR;
- }
- fseek(in, ofst, SEEK_SET);
- MD5Init(&ctx);
- while( amt>0 ){
- int n;
- n = (int)fread(zBuf, 1, sizeof(zBuf)<=amt ? sizeof(zBuf) : amt, in);
- if( n<=0 ) break;
- MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
- amt -= n;
- }
- fclose(in);
- MD5Final(digest, &ctx);
- converter = (void(*)(unsigned char*,char*))cd;
- converter(digest, zBuf);
- Tcl_AppendResult(interp, zBuf, (char*)0);
- return TCL_OK;
-}
-
-/*
-** Register the four new TCL commands for generating MD5 checksums
-** with the TCL interpreter.
-*/
-int Md5_Init(Tcl_Interp *interp){
- Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd,
- MD5DigestToBase16, 0);
- Tcl_CreateCommand(interp, "md5-10x8", (Tcl_CmdProc*)md5_cmd,
- MD5DigestToBase10x8, 0);
- Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd,
- MD5DigestToBase16, 0);
- Tcl_CreateCommand(interp, "md5file-10x8", (Tcl_CmdProc*)md5file_cmd,
- MD5DigestToBase10x8, 0);
- return TCL_OK;
-}
-
-/*
-** During testing, the special md5sum() aggregate function is available.
-** inside SQLite. The following routines implement that function.
-*/
-static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
- MD5Context *p;
- int i;
- if( argc<1 ) return;
- p = sqlite3_aggregate_context(context, sizeof(*p));
- if( p==0 ) return;
- if( !p->isInit ){
- MD5Init(p);
- }
- for(i=0; i<argc; i++){
- const char *zData = (char*)sqlite3_value_text(argv[i]);
- if( zData ){
- MD5Update(p, (unsigned char*)zData, (int)strlen(zData));
- }
- }
-}
-static void md5finalize(sqlite3_context *context){
- MD5Context *p;
- unsigned char digest[16];
- char zBuf[33];
- p = sqlite3_aggregate_context(context, sizeof(*p));
- MD5Final(digest,p);
- MD5DigestToBase16(digest, zBuf);
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
-}
-int Md5_Register(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pThunk
-){
- int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
- md5step, md5finalize);
- sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */
- return rc;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_multiplex.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_multiplex.c
deleted file mode 100644
index ed8c9f7fa7e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_multiplex.c
+++ /dev/null
@@ -1,1320 +0,0 @@
-/*
-** 2010 October 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 contains a VFS "shim" - a layer that sits in between the
-** pager and the real VFS - that breaks up a very large database file
-** into two or more smaller files on disk. This is useful, for example,
-** in order to support large, multi-gigabyte databases on older filesystems
-** that limit the maximum file size to 2 GiB.
-**
-** USAGE:
-**
-** Compile this source file and link it with your application. Then
-** at start-time, invoke the following procedure:
-**
-** int sqlite3_multiplex_initialize(
-** const char *zOrigVfsName, // The underlying real VFS
-** int makeDefault // True to make multiplex the default VFS
-** );
-**
-** The procedure call above will create and register a new VFS shim named
-** "multiplex". The multiplex VFS will use the VFS named by zOrigVfsName to
-** do the actual disk I/O. (The zOrigVfsName parameter may be NULL, in
-** which case the default VFS at the moment sqlite3_multiplex_initialize()
-** is called will be used as the underlying real VFS.)
-**
-** If the makeDefault parameter is TRUE then multiplex becomes the new
-** default VFS. Otherwise, you can use the multiplex VFS by specifying
-** "multiplex" as the 4th parameter to sqlite3_open_v2() or by employing
-** URI filenames and adding "vfs=multiplex" as a parameter to the filename
-** URI.
-**
-** The multiplex VFS allows databases up to 32 GiB in size. But it splits
-** the files up into smaller pieces, so that they will work even on
-** filesystems that do not support large files. The default chunk size
-** is 2147418112 bytes (which is 64KiB less than 2GiB) but this can be
-** changed at compile-time by defining the SQLITE_MULTIPLEX_CHUNK_SIZE
-** macro. Use the "chunksize=NNNN" query parameter with a URI filename
-** in order to select an alternative chunk size for individual connections
-** at run-time.
-*/
-#include "sqlite3.h"
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-#include "test_multiplex.h"
-
-#ifndef SQLITE_CORE
- #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
-#endif
-#include "sqlite3ext.h"
-
-/*
-** These should be defined to be the same as the values in
-** sqliteInt.h. They are defined separately here so that
-** the multiplex VFS shim can be built as a loadable
-** module.
-*/
-#define UNUSED_PARAMETER(x) (void)(x)
-#define MAX_PAGE_SIZE 0x10000
-#define DEFAULT_SECTOR_SIZE 0x1000
-
-/* Maximum chunk number */
-#define MX_CHUNK_NUMBER 299
-
-/* First chunk for rollback journal files */
-#define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
-#define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700
-
-
-/************************ Shim Definitions ******************************/
-
-#ifndef SQLITE_MULTIPLEX_VFS_NAME
-# define SQLITE_MULTIPLEX_VFS_NAME "multiplex"
-#endif
-
-/* This is the limit on the chunk size. It may be changed by calling
-** the xFileControl() interface. It will be rounded up to a
-** multiple of MAX_PAGE_SIZE. We default it here to 2GiB less 64KiB.
-*/
-#ifndef SQLITE_MULTIPLEX_CHUNK_SIZE
-# define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112
-#endif
-
-/* This used to be the default limit on number of chunks, but
-** it is no longer enforced. There is currently no limit to the
-** number of chunks.
-**
-** May be changed by calling the xFileControl() interface.
-*/
-#ifndef SQLITE_MULTIPLEX_MAX_CHUNKS
-# define SQLITE_MULTIPLEX_MAX_CHUNKS 12
-#endif
-
-/************************ Object Definitions ******************************/
-
-/* Forward declaration of all object types */
-typedef struct multiplexGroup multiplexGroup;
-typedef struct multiplexConn multiplexConn;
-
-/*
-** A "multiplex group" is a collection of files that collectively
-** makeup a single SQLite DB file. This allows the size of the DB
-** to exceed the limits imposed by the file system.
-**
-** There is an instance of the following object for each defined multiplex
-** group.
-*/
-struct multiplexGroup {
- struct multiplexReal { /* For each chunk */
- sqlite3_file *p; /* Handle for the chunk */
- char *z; /* Name of this chunk */
- } *aReal; /* list of all chunks */
- int nReal; /* Number of chunks */
- char *zName; /* Base filename of this group */
- int nName; /* Length of base filename */
- int flags; /* Flags used for original opening */
- unsigned int szChunk; /* Chunk size used for this group */
- unsigned char bEnabled; /* TRUE to use Multiplex VFS for this file */
- unsigned char bTruncate; /* TRUE to enable truncation of databases */
-};
-
-/*
-** An instance of the following object represents each open connection
-** to a file that is multiplex'ed. This object is a
-** subclass of sqlite3_file. The sqlite3_file object for the underlying
-** VFS is appended to this structure.
-*/
-struct multiplexConn {
- sqlite3_file base; /* Base class - must be first */
- multiplexGroup *pGroup; /* The underlying group of files */
-};
-
-/************************* Global Variables **********************************/
-/*
-** All global variables used by this file are containing within the following
-** gMultiplex structure.
-*/
-static struct {
- /* The pOrigVfs is the real, original underlying VFS implementation.
- ** Most operations pass-through to the real VFS. This value is read-only
- ** during operation. It is only modified at start-time and thus does not
- ** require a mutex.
- */
- sqlite3_vfs *pOrigVfs;
-
- /* The sThisVfs is the VFS structure used by this shim. It is initialized
- ** at start-time and thus does not require a mutex
- */
- sqlite3_vfs sThisVfs;
-
- /* The sIoMethods defines the methods used by sqlite3_file objects
- ** associated with this shim. It is initialized at start-time and does
- ** not require a mutex.
- **
- ** When the underlying VFS is called to open a file, it might return
- ** either a version 1 or a version 2 sqlite3_file object. This shim
- ** has to create a wrapper sqlite3_file of the same version. Hence
- ** there are two I/O method structures, one for version 1 and the other
- ** for version 2.
- */
- sqlite3_io_methods sIoMethodsV1;
- sqlite3_io_methods sIoMethodsV2;
-
- /* True when this shim has been initialized.
- */
- int isInitialized;
-} gMultiplex;
-
-/************************* Utility Routines *********************************/
-/*
-** Compute a string length that is limited to what can be stored in
-** lower 30 bits of a 32-bit signed integer.
-**
-** The value returned will never be negative. Nor will it ever be greater
-** than the actual length of the string. For very long strings (greater
-** than 1GiB) the value returned might be less than the true string length.
-*/
-static int multiplexStrlen30(const char *z){
- const char *z2 = z;
- if( z==0 ) return 0;
- while( *z2 ){ z2++; }
- return 0x3fffffff & (int)(z2 - z);
-}
-
-/*
-** Generate the file-name for chunk iChunk of the group with base name
-** zBase. The file-name is written to buffer zOut before returning. Buffer
-** zOut must be allocated by the caller so that it is at least (nBase+5)
-** bytes in size, where nBase is the length of zBase, not including the
-** nul-terminator.
-**
-** If iChunk is 0 (or 400 - the number for the first journal file chunk),
-** the output is a copy of the input string. Otherwise, if
-** SQLITE_ENABLE_8_3_NAMES is not defined or the input buffer does not contain
-** a "." character, then the output is a copy of the input string with the
-** three-digit zero-padded decimal representation if iChunk appended to it.
-** For example:
-**
-** zBase="test.db", iChunk=4 -> zOut="test.db004"
-**
-** Or, if SQLITE_ENABLE_8_3_NAMES is defined and the input buffer contains
-** a "." character, then everything after the "." is replaced by the
-** three-digit representation of iChunk.
-**
-** zBase="test.db", iChunk=4 -> zOut="test.004"
-**
-** The output buffer string is terminated by 2 0x00 bytes. This makes it safe
-** to pass to sqlite3_uri_parameter() and similar.
-*/
-static void multiplexFilename(
- const char *zBase, /* Filename for chunk 0 */
- int nBase, /* Size of zBase in bytes (without \0) */
- int flags, /* Flags used to open file */
- int iChunk, /* Chunk to generate filename for */
- char *zOut /* Buffer to write generated name to */
-){
- int n = nBase;
- memcpy(zOut, zBase, n+1);
- if( iChunk!=0 && iChunk<=MX_CHUNK_NUMBER ){
-#ifdef SQLITE_ENABLE_8_3_NAMES
- int i;
- for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){}
- if( i>=n-4 ) n = i+1;
- if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
- /* The extensions on overflow files for main databases are 001, 002,
- ** 003 and so forth. To avoid name collisions, add 400 to the
- ** extensions of journal files so that they are 401, 402, 403, ....
- */
- iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
- }else if( flags & SQLITE_OPEN_WAL ){
- /* To avoid name collisions, add 700 to the
- ** extensions of WAL files so that they are 701, 702, 703, ....
- */
- iChunk += SQLITE_MULTIPLEX_WAL_8_3_OFFSET;
- }
-#endif
- sqlite3_snprintf(4,&zOut[n],"%03d",iChunk);
- n += 3;
- }
-
- assert( zOut[n]=='\0' );
- zOut[n+1] = '\0';
-}
-
-/* Compute the filename for the iChunk-th chunk
-*/
-static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
- if( iChunk>=pGroup->nReal ){
- struct multiplexReal *p;
- p = sqlite3_realloc64(pGroup->aReal, (iChunk+1)*sizeof(*p));
- if( p==0 ){
- return SQLITE_NOMEM;
- }
- memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
- pGroup->aReal = p;
- pGroup->nReal = iChunk+1;
- }
- if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
- char *z;
- int n = pGroup->nName;
- pGroup->aReal[iChunk].z = z = sqlite3_malloc64( n+5 );
- if( z==0 ){
- return SQLITE_NOMEM;
- }
- multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
- }
- return SQLITE_OK;
-}
-
-/* Translate an sqlite3_file* that is really a multiplexGroup* into
-** the sqlite3_file* for the underlying original VFS.
-**
-** For chunk 0, the pGroup->flags determines whether or not a new file
-** is created if it does not already exist. For chunks 1 and higher, the
-** file is created only if createFlag is 1.
-*/
-static sqlite3_file *multiplexSubOpen(
- multiplexGroup *pGroup, /* The multiplexor group */
- int iChunk, /* Which chunk to open. 0==original file */
- int *rc, /* Result code in and out */
- int *pOutFlags, /* Output flags */
- int createFlag /* True to create if iChunk>0 */
-){
- sqlite3_file *pSubOpen = 0;
- sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
-
-#ifdef SQLITE_ENABLE_8_3_NAMES
- /* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are
- ** part of a database journal are named db.401, db.402, and so on. A
- ** database may therefore not grow to larger than 400 chunks. Attempting
- ** to open chunk 401 indicates the database is full. */
- if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
- sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", pGroup->zName);
- *rc = SQLITE_FULL;
- return 0;
- }
-#endif
-
- *rc = multiplexSubFilename(pGroup, iChunk);
- if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
- int flags, bExists;
- flags = pGroup->flags;
- if( createFlag ){
- flags |= SQLITE_OPEN_CREATE;
- }else if( iChunk==0 ){
- /* Fall through */
- }else if( pGroup->aReal[iChunk].z==0 ){
- return 0;
- }else{
- *rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z,
- SQLITE_ACCESS_EXISTS, &bExists);
- if( *rc || !bExists ){
- if( *rc ){
- sqlite3_log(*rc, "multiplexor.xAccess failure on %s",
- pGroup->aReal[iChunk].z);
- }
- return 0;
- }
- flags &= ~SQLITE_OPEN_CREATE;
- }
- pSubOpen = sqlite3_malloc64( pOrigVfs->szOsFile );
- if( pSubOpen==0 ){
- *rc = SQLITE_IOERR_NOMEM;
- return 0;
- }
- pGroup->aReal[iChunk].p = pSubOpen;
- *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen,
- flags, pOutFlags);
- if( (*rc)!=SQLITE_OK ){
- sqlite3_log(*rc, "multiplexor.xOpen failure on %s",
- pGroup->aReal[iChunk].z);
- sqlite3_free(pSubOpen);
- pGroup->aReal[iChunk].p = 0;
- return 0;
- }
- }
- return pSubOpen;
-}
-
-/*
-** Return the size, in bytes, of chunk number iChunk. If that chunk
-** does not exist, then return 0. This function does not distingish between
-** non-existant files and zero-length files.
-*/
-static sqlite3_int64 multiplexSubSize(
- multiplexGroup *pGroup, /* The multiplexor group */
- int iChunk, /* Which chunk to open. 0==original file */
- int *rc /* Result code in and out */
-){
- sqlite3_file *pSub;
- sqlite3_int64 sz = 0;
-
- if( *rc ) return 0;
- pSub = multiplexSubOpen(pGroup, iChunk, rc, NULL, 0);
- if( pSub==0 ) return 0;
- *rc = pSub->pMethods->xFileSize(pSub, &sz);
- return sz;
-}
-
-/*
-** This is the implementation of the multiplex_control() SQL function.
-*/
-static void multiplexControlFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int rc = SQLITE_OK;
- sqlite3 *db = sqlite3_context_db_handle(context);
- int op = 0;
- int iVal;
-
- if( !db || argc!=2 ){
- rc = SQLITE_ERROR;
- }else{
- /* extract params */
- op = sqlite3_value_int(argv[0]);
- iVal = sqlite3_value_int(argv[1]);
- /* map function op to file_control op */
- switch( op ){
- case 1:
- op = MULTIPLEX_CTRL_ENABLE;
- break;
- case 2:
- op = MULTIPLEX_CTRL_SET_CHUNK_SIZE;
- break;
- case 3:
- op = MULTIPLEX_CTRL_SET_MAX_CHUNKS;
- break;
- default:
- rc = SQLITE_NOTFOUND;
- break;
- }
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_file_control(db, 0, op, &iVal);
- }
- sqlite3_result_error_code(context, rc);
-}
-
-/*
-** This is the entry point to register the auto-extension for the
-** multiplex_control() function.
-*/
-static int multiplexFuncInit(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc;
- rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY,
- 0, multiplexControlFunc, 0, 0);
- return rc;
-}
-
-/*
-** Close a single sub-file in the connection group.
-*/
-static void multiplexSubClose(
- multiplexGroup *pGroup,
- int iChunk,
- sqlite3_vfs *pOrigVfs
-){
- sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p;
- if( pSubOpen ){
- pSubOpen->pMethods->xClose(pSubOpen);
- if( pOrigVfs && pGroup->aReal[iChunk].z ){
- pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
- }
- sqlite3_free(pGroup->aReal[iChunk].p);
- }
- sqlite3_free(pGroup->aReal[iChunk].z);
- memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk]));
-}
-
-/*
-** Deallocate memory held by a multiplexGroup
-*/
-static void multiplexFreeComponents(multiplexGroup *pGroup){
- int i;
- for(i=0; i<pGroup->nReal; i++){ multiplexSubClose(pGroup, i, 0); }
- sqlite3_free(pGroup->aReal);
- pGroup->aReal = 0;
- pGroup->nReal = 0;
-}
-
-
-/************************* VFS Method Wrappers *****************************/
-
-/*
-** This is the xOpen method used for the "multiplex" VFS.
-**
-** Most of the work is done by the underlying original VFS. This method
-** simply links the new file into the appropriate multiplex group if it is a
-** file that needs to be tracked.
-*/
-static int multiplexOpen(
- sqlite3_vfs *pVfs, /* The multiplex VFS */
- const char *zName, /* Name of file to be opened */
- sqlite3_file *pConn, /* Fill in this file descriptor */
- int flags, /* Flags to control the opening */
- int *pOutFlags /* Flags showing results of opening */
-){
- int rc = SQLITE_OK; /* Result code */
- multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */
- multiplexGroup *pGroup = 0; /* Corresponding multiplexGroup object */
- sqlite3_file *pSubOpen = 0; /* Real file descriptor */
- sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
- int nName = 0;
- int sz = 0;
- char *zToFree = 0;
-
- UNUSED_PARAMETER(pVfs);
- memset(pConn, 0, pVfs->szOsFile);
- assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) );
-
- /* We need to create a group structure and manage
- ** access to this group of files.
- */
- pMultiplexOpen = (multiplexConn*)pConn;
-
- if( rc==SQLITE_OK ){
- /* allocate space for group */
- nName = zName ? multiplexStrlen30(zName) : 0;
- sz = sizeof(multiplexGroup) /* multiplexGroup */
- + nName + 1; /* zName */
- pGroup = sqlite3_malloc64( sz );
- if( pGroup==0 ){
- rc = SQLITE_NOMEM;
- }
- }
-
- if( rc==SQLITE_OK ){
- const char *zUri = (flags & SQLITE_OPEN_URI) ? zName : 0;
- /* assign pointers to extra space allocated */
- memset(pGroup, 0, sz);
- pMultiplexOpen->pGroup = pGroup;
- pGroup->bEnabled = (unsigned char)-1;
- pGroup->bTruncate = (unsigned char)sqlite3_uri_boolean(zUri, "truncate",
- (flags & SQLITE_OPEN_MAIN_DB)==0);
- pGroup->szChunk = (int)sqlite3_uri_int64(zUri, "chunksize",
- SQLITE_MULTIPLEX_CHUNK_SIZE);
- pGroup->szChunk = (pGroup->szChunk+0xffff)&~0xffff;
- if( zName ){
- char *p = (char *)&pGroup[1];
- pGroup->zName = p;
- memcpy(pGroup->zName, zName, nName+1);
- pGroup->nName = nName;
- }
- if( pGroup->bEnabled ){
- /* Make sure that the chunksize is such that the pending byte does not
- ** falls at the end of a chunk. A region of up to 64K following
- ** the pending byte is never written, so if the pending byte occurs
- ** near the end of a chunk, that chunk will be too small. */
-#ifndef SQLITE_OMIT_WSD
- extern int sqlite3PendingByte;
-#else
- int sqlite3PendingByte = 0x40000000;
-#endif
- while( (sqlite3PendingByte % pGroup->szChunk)>=(pGroup->szChunk-65536) ){
- pGroup->szChunk += 65536;
- }
- }
- pGroup->flags = flags;
- rc = multiplexSubFilename(pGroup, 1);
- if( rc==SQLITE_OK ){
- pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags, 0);
- if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN;
- }
- if( rc==SQLITE_OK ){
- sqlite3_int64 sz64;
-
- rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz64);
- if( rc==SQLITE_OK && zName ){
- int bExists;
- if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
- pGroup->bEnabled = 0;
- }else
- if( sz64==0 ){
- if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
- /* If opening a main journal file and the first chunk is zero
- ** bytes in size, delete any subsequent chunks from the
- ** file-system. */
- int iChunk = 1;
- do {
- rc = pOrigVfs->xAccess(pOrigVfs,
- pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists
- );
- if( rc==SQLITE_OK && bExists ){
- rc = pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
- if( rc==SQLITE_OK ){
- rc = multiplexSubFilename(pGroup, ++iChunk);
- }
- }
- }while( rc==SQLITE_OK && bExists );
- }
- }else{
- /* If the first overflow file exists and if the size of the main file
- ** is different from the chunk size, that means the chunk size is set
- ** set incorrectly. So fix it.
- **
- ** Or, if the first overflow file does not exist and the main file is
- ** larger than the chunk size, that means the chunk size is too small.
- ** But we have no way of determining the intended chunk size, so
- ** just disable the multiplexor all togethre.
- */
- rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
- SQLITE_ACCESS_EXISTS, &bExists);
- bExists = multiplexSubSize(pGroup, 1, &rc)>0;
- if( rc==SQLITE_OK && bExists && sz64==(sz64&0xffff0000) && sz64>0
- && sz64!=pGroup->szChunk ){
- pGroup->szChunk = (int)sz64;
- }else if( rc==SQLITE_OK && !bExists && sz64>pGroup->szChunk ){
- pGroup->bEnabled = 0;
- }
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- if( pSubOpen->pMethods->iVersion==1 ){
- pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
- }else{
- pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2;
- }
- }else{
- multiplexFreeComponents(pGroup);
- sqlite3_free(pGroup);
- }
- }
- sqlite3_free(zToFree);
- return rc;
-}
-
-/*
-** This is the xDelete method used for the "multiplex" VFS.
-** It attempts to delete the filename specified.
-*/
-static int multiplexDelete(
- sqlite3_vfs *pVfs, /* The multiplex VFS */
- const char *zName, /* Name of file to delete */
- int syncDir
-){
- int rc;
- sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
- rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
- if( rc==SQLITE_OK ){
- /* If the main chunk was deleted successfully, also delete any subsequent
- ** chunks - starting with the last (highest numbered).
- */
- int nName = (int)strlen(zName);
- char *z;
- z = sqlite3_malloc64(nName + 5);
- if( z==0 ){
- rc = SQLITE_IOERR_NOMEM;
- }else{
- int iChunk = 0;
- int bExists;
- do{
- multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, ++iChunk, z);
- rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
- }while( rc==SQLITE_OK && bExists );
- while( rc==SQLITE_OK && iChunk>1 ){
- multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, --iChunk, z);
- rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
- }
- if( rc==SQLITE_OK ){
- iChunk = 0;
- do{
- multiplexFilename(zName, nName, SQLITE_OPEN_WAL, ++iChunk, z);
- rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
- }while( rc==SQLITE_OK && bExists );
- while( rc==SQLITE_OK && iChunk>1 ){
- multiplexFilename(zName, nName, SQLITE_OPEN_WAL, --iChunk, z);
- rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
- }
- }
- }
- sqlite3_free(z);
- }
- return rc;
-}
-
-static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
- return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, b, c, d);
-}
-static int multiplexFullPathname(sqlite3_vfs *a, const char *b, int c, char *d){
- return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, b, c, d);
-}
-static void *multiplexDlOpen(sqlite3_vfs *a, const char *b){
- return gMultiplex.pOrigVfs->xDlOpen(gMultiplex.pOrigVfs, b);
-}
-static void multiplexDlError(sqlite3_vfs *a, int b, char *c){
- gMultiplex.pOrigVfs->xDlError(gMultiplex.pOrigVfs, b, c);
-}
-static void (*multiplexDlSym(sqlite3_vfs *a, void *b, const char *c))(void){
- return gMultiplex.pOrigVfs->xDlSym(gMultiplex.pOrigVfs, b, c);
-}
-static void multiplexDlClose(sqlite3_vfs *a, void *b){
- gMultiplex.pOrigVfs->xDlClose(gMultiplex.pOrigVfs, b);
-}
-static int multiplexRandomness(sqlite3_vfs *a, int b, char *c){
- return gMultiplex.pOrigVfs->xRandomness(gMultiplex.pOrigVfs, b, c);
-}
-static int multiplexSleep(sqlite3_vfs *a, int b){
- return gMultiplex.pOrigVfs->xSleep(gMultiplex.pOrigVfs, b);
-}
-static int multiplexCurrentTime(sqlite3_vfs *a, double *b){
- return gMultiplex.pOrigVfs->xCurrentTime(gMultiplex.pOrigVfs, b);
-}
-static int multiplexGetLastError(sqlite3_vfs *a, int b, char *c){
- if( gMultiplex.pOrigVfs->xGetLastError ){
- return gMultiplex.pOrigVfs->xGetLastError(gMultiplex.pOrigVfs, b, c);
- }else{
- return 0;
- }
-}
-static int multiplexCurrentTimeInt64(sqlite3_vfs *a, sqlite3_int64 *b){
- return gMultiplex.pOrigVfs->xCurrentTimeInt64(gMultiplex.pOrigVfs, b);
-}
-
-/************************ I/O Method Wrappers *******************************/
-
-/* xClose requests get passed through to the original VFS.
-** We loop over all open chunk handles and close them.
-** The group structure for this file is unlinked from
-** our list of groups and freed.
-*/
-static int multiplexClose(sqlite3_file *pConn){
- multiplexConn *p = (multiplexConn*)pConn;
- multiplexGroup *pGroup = p->pGroup;
- int rc = SQLITE_OK;
- multiplexFreeComponents(pGroup);
- sqlite3_free(pGroup);
- return rc;
-}
-
-/* Pass xRead requests thru to the original VFS after
-** determining the correct chunk to operate on.
-** Break up reads across chunk boundaries.
-*/
-static int multiplexRead(
- sqlite3_file *pConn,
- void *pBuf,
- int iAmt,
- sqlite3_int64 iOfst
-){
- multiplexConn *p = (multiplexConn*)pConn;
- multiplexGroup *pGroup = p->pGroup;
- int rc = SQLITE_OK;
- if( !pGroup->bEnabled ){
- sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
- if( pSubOpen==0 ){
- rc = SQLITE_IOERR_READ;
- }else{
- rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst);
- }
- }else{
- while( iAmt > 0 ){
- int i = (int)(iOfst / pGroup->szChunk);
- sqlite3_file *pSubOpen;
- pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
- if( pSubOpen ){
- int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk;
- if( extra<0 ) extra = 0;
- iAmt -= extra;
- rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt,
- iOfst % pGroup->szChunk);
- if( rc!=SQLITE_OK ) break;
- pBuf = (char *)pBuf + iAmt;
- iOfst += iAmt;
- iAmt = extra;
- }else{
- rc = SQLITE_IOERR_READ;
- break;
- }
- }
- }
-
- return rc;
-}
-
-/* Pass xWrite requests thru to the original VFS after
-** determining the correct chunk to operate on.
-** Break up writes across chunk boundaries.
-*/
-static int multiplexWrite(
- sqlite3_file *pConn,
- const void *pBuf,
- int iAmt,
- sqlite3_int64 iOfst
-){
- multiplexConn *p = (multiplexConn*)pConn;
- multiplexGroup *pGroup = p->pGroup;
- int rc = SQLITE_OK;
- if( !pGroup->bEnabled ){
- sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
- if( pSubOpen==0 ){
- rc = SQLITE_IOERR_WRITE;
- }else{
- rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst);
- }
- }else{
- while( rc==SQLITE_OK && iAmt>0 ){
- int i = (int)(iOfst / pGroup->szChunk);
- sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
- if( pSubOpen ){
- int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) -
- pGroup->szChunk;
- if( extra<0 ) extra = 0;
- iAmt -= extra;
- rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt,
- iOfst % pGroup->szChunk);
- pBuf = (char *)pBuf + iAmt;
- iOfst += iAmt;
- iAmt = extra;
- }
- }
- }
- return rc;
-}
-
-/* Pass xTruncate requests thru to the original VFS after
-** determining the correct chunk to operate on. Delete any
-** chunks above the truncate mark.
-*/
-static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
- multiplexConn *p = (multiplexConn*)pConn;
- multiplexGroup *pGroup = p->pGroup;
- int rc = SQLITE_OK;
- if( !pGroup->bEnabled ){
- sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
- if( pSubOpen==0 ){
- rc = SQLITE_IOERR_TRUNCATE;
- }else{
- rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
- }
- }else{
- int i;
- int iBaseGroup = (int)(size / pGroup->szChunk);
- sqlite3_file *pSubOpen;
- sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
- /* delete the chunks above the truncate limit */
- for(i = pGroup->nReal-1; i>iBaseGroup && rc==SQLITE_OK; i--){
- if( pGroup->bTruncate ){
- multiplexSubClose(pGroup, i, pOrigVfs);
- }else{
- pSubOpen = multiplexSubOpen(pGroup, i, &rc, 0, 0);
- if( pSubOpen ){
- rc = pSubOpen->pMethods->xTruncate(pSubOpen, 0);
- }
- }
- }
- if( rc==SQLITE_OK ){
- pSubOpen = multiplexSubOpen(pGroup, iBaseGroup, &rc, 0, 0);
- if( pSubOpen ){
- rc = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
- }
- }
- if( rc ) rc = SQLITE_IOERR_TRUNCATE;
- }
- return rc;
-}
-
-/* Pass xSync requests through to the original VFS without change
-*/
-static int multiplexSync(sqlite3_file *pConn, int flags){
- multiplexConn *p = (multiplexConn*)pConn;
- multiplexGroup *pGroup = p->pGroup;
- int rc = SQLITE_OK;
- int i;
- for(i=0; i<pGroup->nReal; i++){
- sqlite3_file *pSubOpen = pGroup->aReal[i].p;
- if( pSubOpen ){
- int rc2 = pSubOpen->pMethods->xSync(pSubOpen, flags);
- if( rc2!=SQLITE_OK ) rc = rc2;
- }
- }
- return rc;
-}
-
-/* Pass xFileSize requests through to the original VFS.
-** Aggregate the size of all the chunks before returning.
-*/
-static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
- multiplexConn *p = (multiplexConn*)pConn;
- multiplexGroup *pGroup = p->pGroup;
- int rc = SQLITE_OK;
- int i;
- if( !pGroup->bEnabled ){
- sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
- if( pSubOpen==0 ){
- rc = SQLITE_IOERR_FSTAT;
- }else{
- rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
- }
- }else{
- *pSize = 0;
- for(i=0; rc==SQLITE_OK; i++){
- sqlite3_int64 sz = multiplexSubSize(pGroup, i, &rc);
- if( sz==0 ) break;
- *pSize = i*(sqlite3_int64)pGroup->szChunk + sz;
- }
- }
- return rc;
-}
-
-/* Pass xLock requests through to the original VFS unchanged.
-*/
-static int multiplexLock(sqlite3_file *pConn, int lock){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- return pSubOpen->pMethods->xLock(pSubOpen, lock);
- }
- return SQLITE_BUSY;
-}
-
-/* Pass xUnlock requests through to the original VFS unchanged.
-*/
-static int multiplexUnlock(sqlite3_file *pConn, int lock){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
- }
- return SQLITE_IOERR_UNLOCK;
-}
-
-/* Pass xCheckReservedLock requests through to the original VFS unchanged.
-*/
-static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
- }
- return SQLITE_IOERR_CHECKRESERVEDLOCK;
-}
-
-/* Pass xFileControl requests through to the original VFS unchanged,
-** except for any MULTIPLEX_CTRL_* requests here.
-*/
-static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
- multiplexConn *p = (multiplexConn*)pConn;
- multiplexGroup *pGroup = p->pGroup;
- int rc = SQLITE_ERROR;
- sqlite3_file *pSubOpen;
-
- if( !gMultiplex.isInitialized ) return SQLITE_MISUSE;
- switch( op ){
- case MULTIPLEX_CTRL_ENABLE:
- if( pArg ) {
- int bEnabled = *(int *)pArg;
- pGroup->bEnabled = (unsigned char)bEnabled;
- rc = SQLITE_OK;
- }
- break;
- case MULTIPLEX_CTRL_SET_CHUNK_SIZE:
- if( pArg ) {
- unsigned int szChunk = *(unsigned*)pArg;
- if( szChunk<1 ){
- rc = SQLITE_MISUSE;
- }else{
- /* Round up to nearest multiple of MAX_PAGE_SIZE. */
- szChunk = (szChunk + (MAX_PAGE_SIZE-1));
- szChunk &= ~(MAX_PAGE_SIZE-1);
- pGroup->szChunk = szChunk;
- rc = SQLITE_OK;
- }
- }
- break;
- case MULTIPLEX_CTRL_SET_MAX_CHUNKS:
- rc = SQLITE_OK;
- break;
- case SQLITE_FCNTL_SIZE_HINT:
- case SQLITE_FCNTL_CHUNK_SIZE:
- /* no-op these */
- rc = SQLITE_OK;
- break;
- case SQLITE_FCNTL_PRAGMA: {
- char **aFcntl = (char**)pArg;
- /*
- ** EVIDENCE-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
- ** file control is an array of pointers to strings (char**) in which the
- ** second element of the array is the name of the pragma and the third
- ** element is the argument to the pragma or NULL if the pragma has no
- ** argument.
- */
- if( aFcntl[1] && sqlite3_stricmp(aFcntl[1],"multiplex_truncate")==0 ){
- if( aFcntl[2] && aFcntl[2][0] ){
- if( sqlite3_stricmp(aFcntl[2], "on")==0
- || sqlite3_stricmp(aFcntl[2], "1")==0 ){
- pGroup->bTruncate = 1;
- }else
- if( sqlite3_stricmp(aFcntl[2], "off")==0
- || sqlite3_stricmp(aFcntl[2], "0")==0 ){
- pGroup->bTruncate = 0;
- }
- }
- /* EVIDENCE-OF: R-27806-26076 The handler for an SQLITE_FCNTL_PRAGMA
- ** file control can optionally make the first element of the char**
- ** argument point to a string obtained from sqlite3_mprintf() or the
- ** equivalent and that string will become the result of the pragma
- ** or the error message if the pragma fails.
- */
- aFcntl[0] = sqlite3_mprintf(pGroup->bTruncate ? "on" : "off");
- rc = SQLITE_OK;
- break;
- }
- /* If the multiplexor does not handle the pragma, pass it through
- ** into the default case. */
- }
- default:
- pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
- if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
- *(char**)pArg = sqlite3_mprintf("multiplex/%z", *(char**)pArg);
- }
- }
- break;
- }
- return rc;
-}
-
-/* Pass xSectorSize requests through to the original VFS unchanged.
-*/
-static int multiplexSectorSize(sqlite3_file *pConn){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen && pSubOpen->pMethods->xSectorSize ){
- return pSubOpen->pMethods->xSectorSize(pSubOpen);
- }
- return DEFAULT_SECTOR_SIZE;
-}
-
-/* Pass xDeviceCharacteristics requests through to the original VFS unchanged.
-*/
-static int multiplexDeviceCharacteristics(sqlite3_file *pConn){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
- }
- return 0;
-}
-
-/* Pass xShmMap requests through to the original VFS unchanged.
-*/
-static int multiplexShmMap(
- sqlite3_file *pConn, /* Handle open on database file */
- int iRegion, /* Region to retrieve */
- int szRegion, /* Size of regions */
- int bExtend, /* True to extend file if necessary */
- void volatile **pp /* OUT: Mapped memory */
-){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp);
- }
- return SQLITE_IOERR;
-}
-
-/* Pass xShmLock requests through to the original VFS unchanged.
-*/
-static int multiplexShmLock(
- sqlite3_file *pConn, /* Database file holding the shared memory */
- int ofst, /* First lock to acquire or release */
- int n, /* Number of locks to acquire or release */
- int flags /* What to do with the lock */
-){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
- }
- return SQLITE_BUSY;
-}
-
-/* Pass xShmBarrier requests through to the original VFS unchanged.
-*/
-static void multiplexShmBarrier(sqlite3_file *pConn){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- pSubOpen->pMethods->xShmBarrier(pSubOpen);
- }
-}
-
-/* Pass xShmUnmap requests through to the original VFS unchanged.
-*/
-static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){
- multiplexConn *p = (multiplexConn*)pConn;
- int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
- if( pSubOpen ){
- return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
- }
- return SQLITE_OK;
-}
-
-/************************** Public Interfaces *****************************/
-/*
-** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize()
-**
-** Use the VFS named zOrigVfsName as the VFS that does the actual work.
-** Use the default if zOrigVfsName==NULL.
-**
-** The multiplex VFS shim is named "multiplex". It will become the default
-** VFS if makeDefault is non-zero.
-**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once
-** during start-up.
-*/
-int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){
- sqlite3_vfs *pOrigVfs;
- if( gMultiplex.isInitialized ) return SQLITE_MISUSE;
- pOrigVfs = sqlite3_vfs_find(zOrigVfsName);
- if( pOrigVfs==0 ) return SQLITE_ERROR;
- assert( pOrigVfs!=&gMultiplex.sThisVfs );
- gMultiplex.isInitialized = 1;
- gMultiplex.pOrigVfs = pOrigVfs;
- gMultiplex.sThisVfs = *pOrigVfs;
- gMultiplex.sThisVfs.szOsFile += sizeof(multiplexConn);
- gMultiplex.sThisVfs.zName = SQLITE_MULTIPLEX_VFS_NAME;
- gMultiplex.sThisVfs.xOpen = multiplexOpen;
- gMultiplex.sThisVfs.xDelete = multiplexDelete;
- gMultiplex.sThisVfs.xAccess = multiplexAccess;
- gMultiplex.sThisVfs.xFullPathname = multiplexFullPathname;
- gMultiplex.sThisVfs.xDlOpen = multiplexDlOpen;
- gMultiplex.sThisVfs.xDlError = multiplexDlError;
- gMultiplex.sThisVfs.xDlSym = multiplexDlSym;
- gMultiplex.sThisVfs.xDlClose = multiplexDlClose;
- gMultiplex.sThisVfs.xRandomness = multiplexRandomness;
- gMultiplex.sThisVfs.xSleep = multiplexSleep;
- gMultiplex.sThisVfs.xCurrentTime = multiplexCurrentTime;
- gMultiplex.sThisVfs.xGetLastError = multiplexGetLastError;
- gMultiplex.sThisVfs.xCurrentTimeInt64 = multiplexCurrentTimeInt64;
-
- gMultiplex.sIoMethodsV1.iVersion = 1;
- gMultiplex.sIoMethodsV1.xClose = multiplexClose;
- gMultiplex.sIoMethodsV1.xRead = multiplexRead;
- gMultiplex.sIoMethodsV1.xWrite = multiplexWrite;
- gMultiplex.sIoMethodsV1.xTruncate = multiplexTruncate;
- gMultiplex.sIoMethodsV1.xSync = multiplexSync;
- gMultiplex.sIoMethodsV1.xFileSize = multiplexFileSize;
- gMultiplex.sIoMethodsV1.xLock = multiplexLock;
- gMultiplex.sIoMethodsV1.xUnlock = multiplexUnlock;
- gMultiplex.sIoMethodsV1.xCheckReservedLock = multiplexCheckReservedLock;
- gMultiplex.sIoMethodsV1.xFileControl = multiplexFileControl;
- gMultiplex.sIoMethodsV1.xSectorSize = multiplexSectorSize;
- gMultiplex.sIoMethodsV1.xDeviceCharacteristics =
- multiplexDeviceCharacteristics;
- gMultiplex.sIoMethodsV2 = gMultiplex.sIoMethodsV1;
- gMultiplex.sIoMethodsV2.iVersion = 2;
- gMultiplex.sIoMethodsV2.xShmMap = multiplexShmMap;
- gMultiplex.sIoMethodsV2.xShmLock = multiplexShmLock;
- gMultiplex.sIoMethodsV2.xShmBarrier = multiplexShmBarrier;
- gMultiplex.sIoMethodsV2.xShmUnmap = multiplexShmUnmap;
- sqlite3_vfs_register(&gMultiplex.sThisVfs, makeDefault);
-
- sqlite3_auto_extension((void(*)(void))multiplexFuncInit);
-
- return SQLITE_OK;
-}
-
-/*
-** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown()
-**
-** All SQLite database connections must be closed before calling this
-** routine.
-**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while
-** shutting down in order to free all remaining multiplex groups.
-*/
-int sqlite3_multiplex_shutdown(int eForce){
- int rc = SQLITE_OK;
- if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE;
- gMultiplex.isInitialized = 0;
- sqlite3_vfs_unregister(&gMultiplex.sThisVfs);
- memset(&gMultiplex, 0, sizeof(gMultiplex));
- return rc;
-}
-
-/***************************** Test Code ***********************************/
-#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-extern const char *sqlite3ErrName(int);
-
-
-/*
-** tclcmd: sqlite3_multiplex_initialize NAME MAKEDEFAULT
-*/
-static int SQLITE_TCLAPI test_multiplex_initialize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zName; /* Name of new multiplex VFS */
- int makeDefault; /* True to make the new VFS the default */
- int rc; /* Value returned by multiplex_initialize() */
-
- UNUSED_PARAMETER(clientData);
-
- /* Process arguments */
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME MAKEDEFAULT");
- return TCL_ERROR;
- }
- zName = Tcl_GetString(objv[1]);
- if( Tcl_GetBooleanFromObj(interp, objv[2], &makeDefault) ) return TCL_ERROR;
- if( zName[0]=='\0' ) zName = 0;
-
- /* Call sqlite3_multiplex_initialize() */
- rc = sqlite3_multiplex_initialize(zName, makeDefault);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_multiplex_shutdown
-*/
-static int SQLITE_TCLAPI test_multiplex_shutdown(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc; /* Value returned by multiplex_shutdown() */
-
- UNUSED_PARAMETER(clientData);
-
- if( objc==2 && strcmp(Tcl_GetString(objv[1]),"-force")!=0 ){
- objc = 3;
- }
- if( (objc!=1 && objc!=2) ){
- Tcl_WrongNumArgs(interp, 1, objv, "?-force?");
- return TCL_ERROR;
- }
-
- /* Call sqlite3_multiplex_shutdown() */
- rc = sqlite3_multiplex_shutdown(objc==2);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
-
- return TCL_OK;
-}
-
-/*
-** Tclcmd: test_multiplex_control HANDLE DBNAME SUB-COMMAND ?INT-VALUE?
-*/
-static int SQLITE_TCLAPI test_multiplex_control(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc; /* Return code from file_control() */
- int idx; /* Index in aSub[] */
- Tcl_CmdInfo cmdInfo; /* Command info structure for HANDLE */
- sqlite3 *db; /* Underlying db handle for HANDLE */
- int iValue = 0;
- void *pArg = 0;
-
- struct SubCommand {
- const char *zName;
- int op;
- int argtype;
- } aSub[] = {
- { "enable", MULTIPLEX_CTRL_ENABLE, 1 },
- { "chunk_size", MULTIPLEX_CTRL_SET_CHUNK_SIZE, 1 },
- { "max_chunks", MULTIPLEX_CTRL_SET_MAX_CHUNKS, 1 },
- { 0, 0, 0 }
- };
-
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE DBNAME SUB-COMMAND INT-VALUE");
- return TCL_ERROR;
- }
-
- if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
- Tcl_AppendResult(interp, "expected database handle, got \"", 0);
- Tcl_AppendResult(interp, Tcl_GetString(objv[1]), "\"", 0);
- return TCL_ERROR;
- }else{
- db = *(sqlite3 **)cmdInfo.objClientData;
- }
-
- rc = Tcl_GetIndexFromObjStruct(
- interp, objv[3], aSub, sizeof(aSub[0]), "sub-command", 0, &idx
- );
- if( rc!=TCL_OK ) return rc;
-
- switch( aSub[idx].argtype ){
- case 1:
- if( Tcl_GetIntFromObj(interp, objv[4], &iValue) ){
- return TCL_ERROR;
- }
- pArg = (void *)&iValue;
- break;
- default:
- Tcl_WrongNumArgs(interp, 4, objv, "SUB-COMMAND");
- return TCL_ERROR;
- }
-
- rc = sqlite3_file_control(db, Tcl_GetString(objv[2]), aSub[idx].op, pArg);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
- return (rc==SQLITE_OK) ? TCL_OK : TCL_ERROR;
-}
-
-/*
-** This routine registers the custom TCL commands defined in this
-** module. This should be the only procedure visible from outside
-** of this module.
-*/
-int Sqlitemultiplex_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aCmd[] = {
- { "sqlite3_multiplex_initialize", test_multiplex_initialize },
- { "sqlite3_multiplex_shutdown", test_multiplex_shutdown },
- { "sqlite3_multiplex_control", test_multiplex_control },
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
-
- return TCL_OK;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_multiplex.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_multiplex.h
deleted file mode 100644
index 790c778a359..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_multiplex.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-** 2011 March 18
-**
-** 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 contains a VFS "shim" - a layer that sits in between the
-** pager and the real VFS.
-**
-** This particular shim enforces a multiplex system on DB files.
-** This shim shards/partitions a single DB file into smaller
-** "chunks" such that the total DB file size may exceed the maximum
-** file size of the underlying file system.
-**
-*/
-
-#ifndef SQLITE_TEST_MULTIPLEX_H
-#define SQLITE_TEST_MULTIPLEX_H
-
-/*
-** CAPI: File-control Operations Supported by Multiplex VFS
-**
-** Values interpreted by the xFileControl method of a Multiplex VFS db file-handle.
-**
-** MULTIPLEX_CTRL_ENABLE:
-** This file control is used to enable or disable the multiplex
-** shim.
-**
-** MULTIPLEX_CTRL_SET_CHUNK_SIZE:
-** This file control is used to set the maximum allowed chunk
-** size for a multiplex file set. The chunk size should be
-** a multiple of SQLITE_MAX_PAGE_SIZE, and will be rounded up
-** if not.
-**
-** MULTIPLEX_CTRL_SET_MAX_CHUNKS:
-** This file control is used to set the maximum number of chunks
-** allowed to be used for a mutliplex file set.
-*/
-#define MULTIPLEX_CTRL_ENABLE 214014
-#define MULTIPLEX_CTRL_SET_CHUNK_SIZE 214015
-#define MULTIPLEX_CTRL_SET_MAX_CHUNKS 214016
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize()
-**
-** Use the VFS named zOrigVfsName as the VFS that does the actual work.
-** Use the default if zOrigVfsName==NULL.
-**
-** The multiplex VFS shim is named "multiplex". It will become the default
-** VFS if makeDefault is non-zero.
-**
-** An auto-extension is registered which will make the function
-** multiplex_control() available to database connections. This
-** function gives access to the xFileControl interface of the
-** multiplex VFS shim.
-**
-** SELECT multiplex_control(<op>,<val>);
-**
-** <op>=1 MULTIPLEX_CTRL_ENABLE
-** <val>=0 disable
-** <val>=1 enable
-**
-** <op>=2 MULTIPLEX_CTRL_SET_CHUNK_SIZE
-** <val> int, chunk size
-**
-** <op>=3 MULTIPLEX_CTRL_SET_MAX_CHUNKS
-** <val> int, max chunks
-**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once
-** during start-up.
-*/
-extern int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault);
-
-/*
-** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown()
-**
-** All SQLite database connections must be closed before calling this
-** routine.
-**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while
-** shutting down in order to free all remaining multiplex groups.
-*/
-extern int sqlite3_multiplex_shutdown(int eForce);
-
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-
-#endif /* SQLITE_TEST_MULTIPLEX_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_mutex.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_mutex.c
deleted file mode 100644
index 8f43e5ad30e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_mutex.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
-** 2008 June 18
-**
-** 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 contains test logic for the sqlite3_mutex interfaces.
-*/
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include "sqlite3.h"
-#include "sqliteInt.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-#define MAX_MUTEXES (SQLITE_MUTEX_STATIC_VFS3+1)
-#define STATIC_MUTEXES (MAX_MUTEXES-(SQLITE_MUTEX_RECURSIVE+1))
-
-/* defined in main.c */
-extern const char *sqlite3ErrName(int);
-
-static const char *aName[MAX_MUTEXES+1] = {
- "fast", "recursive", "static_master", "static_mem",
- "static_open", "static_prng", "static_lru", "static_pmem",
- "static_app1", "static_app2", "static_app3", "static_vfs1",
- "static_vfs2", "static_vfs3", 0
-};
-
-/* A countable mutex */
-struct sqlite3_mutex {
- sqlite3_mutex *pReal;
- int eType;
-};
-
-/* State variables */
-static struct test_mutex_globals {
- int isInstalled; /* True if installed */
- int disableInit; /* True to cause sqlite3_initalize() to fail */
- int disableTry; /* True to force sqlite3_mutex_try() to fail */
- int isInit; /* True if initialized */
- sqlite3_mutex_methods m; /* Interface to "real" mutex system */
- int aCounter[MAX_MUTEXES]; /* Number of grabs of each type of mutex */
- sqlite3_mutex aStatic[STATIC_MUTEXES]; /* The static mutexes */
-} g = {0};
-
-/* Return true if the countable mutex is currently held */
-static int counterMutexHeld(sqlite3_mutex *p){
- return g.m.xMutexHeld(p->pReal);
-}
-
-/* Return true if the countable mutex is not currently held */
-static int counterMutexNotheld(sqlite3_mutex *p){
- return g.m.xMutexNotheld(p->pReal);
-}
-
-/* Initialize the countable mutex interface
-** Or, if g.disableInit is non-zero, then do not initialize but instead
-** return the value of g.disableInit as the result code. This can be used
-** to simulate an initialization failure.
-*/
-static int counterMutexInit(void){
- int rc;
- if( g.disableInit ) return g.disableInit;
- rc = g.m.xMutexInit();
- g.isInit = 1;
- return rc;
-}
-
-/*
-** Uninitialize the mutex subsystem
-*/
-static int counterMutexEnd(void){
- g.isInit = 0;
- return g.m.xMutexEnd();
-}
-
-/*
-** Allocate a countable mutex
-*/
-static sqlite3_mutex *counterMutexAlloc(int eType){
- sqlite3_mutex *pReal;
- sqlite3_mutex *pRet = 0;
-
- assert( g.isInit );
- assert( eType>=SQLITE_MUTEX_FAST );
- assert( eType<=SQLITE_MUTEX_STATIC_VFS3 );
-
- pReal = g.m.xMutexAlloc(eType);
- if( !pReal ) return 0;
-
- if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){
- pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex));
- }else{
- int eStaticType = eType - (MAX_MUTEXES - STATIC_MUTEXES);
- assert( eStaticType>=0 );
- assert( eStaticType<STATIC_MUTEXES );
- pRet = &g.aStatic[eStaticType];
- }
-
- pRet->eType = eType;
- pRet->pReal = pReal;
- return pRet;
-}
-
-/*
-** Free a countable mutex
-*/
-static void counterMutexFree(sqlite3_mutex *p){
- assert( g.isInit );
- g.m.xMutexFree(p->pReal);
- if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){
- free(p);
- }
-}
-
-/*
-** Enter a countable mutex. Block until entry is safe.
-*/
-static void counterMutexEnter(sqlite3_mutex *p){
- assert( g.isInit );
- assert( p->eType>=0 );
- assert( p->eType<MAX_MUTEXES );
- g.aCounter[p->eType]++;
- g.m.xMutexEnter(p->pReal);
-}
-
-/*
-** Try to enter a mutex. Return true on success.
-*/
-static int counterMutexTry(sqlite3_mutex *p){
- assert( g.isInit );
- assert( p->eType>=0 );
- assert( p->eType<MAX_MUTEXES );
- g.aCounter[p->eType]++;
- if( g.disableTry ) return SQLITE_BUSY;
- return g.m.xMutexTry(p->pReal);
-}
-
-/* Leave a mutex
-*/
-static void counterMutexLeave(sqlite3_mutex *p){
- assert( g.isInit );
- g.m.xMutexLeave(p->pReal);
-}
-
-/*
-** sqlite3_shutdown
-*/
-static int SQLITE_TCLAPI test_shutdown(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- rc = sqlite3_shutdown();
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_OK;
-}
-
-/*
-** sqlite3_initialize
-*/
-static int SQLITE_TCLAPI test_initialize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- rc = sqlite3_initialize();
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_OK;
-}
-
-/*
-** install_mutex_counters BOOLEAN
-*/
-static int SQLITE_TCLAPI test_install_mutex_counters(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc = SQLITE_OK;
- int isInstall;
-
- sqlite3_mutex_methods counter_methods = {
- counterMutexInit,
- counterMutexEnd,
- counterMutexAlloc,
- counterMutexFree,
- counterMutexEnter,
- counterMutexTry,
- counterMutexLeave,
- counterMutexHeld,
- counterMutexNotheld
- };
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
- return TCL_ERROR;
- }
- if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
- return TCL_ERROR;
- }
-
- assert(isInstall==0 || isInstall==1);
- assert(g.isInstalled==0 || g.isInstalled==1);
- if( isInstall==g.isInstalled ){
- Tcl_AppendResult(interp, "mutex counters are ", 0);
- Tcl_AppendResult(interp, isInstall?"already installed":"not installed", 0);
- return TCL_ERROR;
- }
-
- if( isInstall ){
- assert( g.m.xMutexAlloc==0 );
- rc = sqlite3_config(SQLITE_CONFIG_GETMUTEX, &g.m);
- if( rc==SQLITE_OK ){
- sqlite3_config(SQLITE_CONFIG_MUTEX, &counter_methods);
- }
- g.disableTry = 0;
- }else{
- assert( g.m.xMutexAlloc );
- rc = sqlite3_config(SQLITE_CONFIG_MUTEX, &g.m);
- memset(&g.m, 0, sizeof(sqlite3_mutex_methods));
- }
-
- if( rc==SQLITE_OK ){
- g.isInstalled = isInstall;
- }
-
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_OK;
-}
-
-/*
-** read_mutex_counters
-*/
-static int SQLITE_TCLAPI test_read_mutex_counters(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_Obj *pRet;
- int ii;
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- pRet = Tcl_NewObj();
- Tcl_IncrRefCount(pRet);
- for(ii=0; ii<MAX_MUTEXES; ii++){
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii]));
- }
- Tcl_SetObjResult(interp, pRet);
- Tcl_DecrRefCount(pRet);
-
- return TCL_OK;
-}
-
-/*
-** clear_mutex_counters
-*/
-static int SQLITE_TCLAPI test_clear_mutex_counters(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int ii;
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- for(ii=0; ii<MAX_MUTEXES; ii++){
- g.aCounter[ii] = 0;
- }
- return TCL_OK;
-}
-
-/*
-** Create and free a mutex. Return the mutex pointer. The pointer
-** will be invalid since the mutex has already been freed. The
-** return pointer just checks to see if the mutex really was allocated.
-*/
-static int SQLITE_TCLAPI test_alloc_mutex(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#if SQLITE_THREADSAFE
- sqlite3_mutex *p = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- char zBuf[100];
- sqlite3_mutex_free(p);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p);
- Tcl_AppendResult(interp, zBuf, (char*)0);
-#endif
- return TCL_OK;
-}
-
-/*
-** sqlite3_config OPTION
-**
-** OPTION can be either one of the keywords:
-**
-** SQLITE_CONFIG_SINGLETHREAD
-** SQLITE_CONFIG_MULTITHREAD
-** SQLITE_CONFIG_SERIALIZED
-**
-** Or OPTION can be an raw integer.
-*/
-static int SQLITE_TCLAPI test_config(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- struct ConfigOption {
- const char *zName;
- int iValue;
- } aOpt[] = {
- {"singlethread", SQLITE_CONFIG_SINGLETHREAD},
- {"multithread", SQLITE_CONFIG_MULTITHREAD},
- {"serialized", SQLITE_CONFIG_SERIALIZED},
- {0, 0}
- };
- int s = sizeof(struct ConfigOption);
- int i;
- int rc;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){
- if( Tcl_GetIntFromObj(interp, objv[1], &i) ){
- return TCL_ERROR;
- }
- }else{
- i = aOpt[i].iValue;
- }
-
- rc = sqlite3_config(i);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
- return TCL_OK;
-}
-
-static sqlite3 *getDbPointer(Tcl_Interp *pInterp, Tcl_Obj *pObj){
- sqlite3 *db;
- Tcl_CmdInfo info;
- char *zCmd = Tcl_GetString(pObj);
- if( Tcl_GetCommandInfo(pInterp, zCmd, &info) ){
- db = *((sqlite3 **)info.objClientData);
- }else{
- db = (sqlite3*)sqlite3TestTextToPtr(zCmd);
- }
- assert( db );
- return db;
-}
-
-static sqlite3_mutex *getStaticMutexPointer(
- Tcl_Interp *pInterp,
- Tcl_Obj *pObj
-){
- int iMutex;
- if( Tcl_GetIndexFromObj(pInterp, pObj, aName, "mutex name", 0, &iMutex) ){
- return 0;
- }
- assert( iMutex!=SQLITE_MUTEX_FAST && iMutex!=SQLITE_MUTEX_RECURSIVE );
- return counterMutexAlloc(iMutex);
-}
-
-static int SQLITE_TCLAPI test_enter_static_mutex(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_mutex *pMutex;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME");
- return TCL_ERROR;
- }
- pMutex = getStaticMutexPointer(interp, objv[1]);
- if( !pMutex ){
- return TCL_ERROR;
- }
- sqlite3_mutex_enter(pMutex);
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_leave_static_mutex(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_mutex *pMutex;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME");
- return TCL_ERROR;
- }
- pMutex = getStaticMutexPointer(interp, objv[1]);
- if( !pMutex ){
- return TCL_ERROR;
- }
- sqlite3_mutex_leave(pMutex);
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_enter_db_mutex(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- db = getDbPointer(interp, objv[1]);
- if( !db ){
- return TCL_ERROR;
- }
- sqlite3_mutex_enter(sqlite3_db_mutex(db));
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_leave_db_mutex(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- db = getDbPointer(interp, objv[1]);
- if( !db ){
- return TCL_ERROR;
- }
- sqlite3_mutex_leave(sqlite3_db_mutex(db));
- return TCL_OK;
-}
-
-int Sqlitetest_mutex_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aCmd[] = {
- { "sqlite3_shutdown", (Tcl_ObjCmdProc*)test_shutdown },
- { "sqlite3_initialize", (Tcl_ObjCmdProc*)test_initialize },
- { "sqlite3_config", (Tcl_ObjCmdProc*)test_config },
-
- { "enter_static_mutex", (Tcl_ObjCmdProc*)test_enter_static_mutex },
- { "leave_static_mutex", (Tcl_ObjCmdProc*)test_leave_static_mutex },
-
- { "enter_db_mutex", (Tcl_ObjCmdProc*)test_enter_db_mutex },
- { "leave_db_mutex", (Tcl_ObjCmdProc*)test_leave_db_mutex },
-
- { "alloc_dealloc_mutex", (Tcl_ObjCmdProc*)test_alloc_mutex },
- { "install_mutex_counters", (Tcl_ObjCmdProc*)test_install_mutex_counters },
- { "read_mutex_counters", (Tcl_ObjCmdProc*)test_read_mutex_counters },
- { "clear_mutex_counters", (Tcl_ObjCmdProc*)test_clear_mutex_counters },
- };
- int i;
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
-
- Tcl_LinkVar(interp, "disable_mutex_init",
- (char*)&g.disableInit, TCL_LINK_INT);
- Tcl_LinkVar(interp, "disable_mutex_try",
- (char*)&g.disableTry, TCL_LINK_INT);
- return SQLITE_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_onefile.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_onefile.c
deleted file mode 100644
index 46c8bc9c839..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_onefile.c
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
-** 2007 September 14
-**
-** 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.
-**
-*************************************************************************
-**
-** OVERVIEW:
-**
-** This file contains some example code demonstrating how the SQLite
-** vfs feature can be used to have SQLite operate directly on an
-** embedded media, without using an intermediate file system.
-**
-** Because this is only a demo designed to run on a workstation, the
-** underlying media is simulated using a regular file-system file. The
-** size of the file is fixed when it is first created (default size 10 MB).
-** From SQLite's point of view, this space is used to store a single
-** database file and the journal file.
-**
-** Any statement journal created is stored in volatile memory obtained
-** from sqlite3_malloc(). Any attempt to create a temporary database file
-** will fail (SQLITE_IOERR). To prevent SQLite from attempting this,
-** it should be configured to store all temporary database files in
-** main memory (see pragma "temp_store" or the SQLITE_TEMP_STORE compile
-** time option).
-**
-** ASSUMPTIONS:
-**
-** After it has been created, the blob file is accessed using the
-** following three functions only:
-**
-** mediaRead(); - Read a 512 byte block from the file.
-** mediaWrite(); - Write a 512 byte block to the file.
-** mediaSync(); - Tell the media hardware to sync.
-**
-** It is assumed that these can be easily implemented by any "real"
-** media vfs driver adapting this code.
-**
-** FILE FORMAT:
-**
-** The basic principle is that the "database file" is stored at the
-** beginning of the 10 MB blob and grows in a forward direction. The
-** "journal file" is stored at the end of the 10MB blob and grows
-** in the reverse direction. If, during a transaction, insufficient
-** space is available to expand either the journal or database file,
-** an SQLITE_FULL error is returned. The database file is never allowed
-** to consume more than 90% of the blob space. If SQLite tries to
-** create a file larger than this, SQLITE_FULL is returned.
-**
-** No allowance is made for "wear-leveling", as is required by.
-** embedded devices in the absence of equivalent hardware features.
-**
-** The first 512 block byte of the file is reserved for storing the
-** size of the "database file". It is updated as part of the sync()
-** operation. On startup, it can only be trusted if no journal file
-** exists. If a journal-file does exist, then it stores the real size
-** of the database region. The second and subsequent blocks store the
-** actual database content.
-**
-** The size of the "journal file" is not stored persistently in the
-** file. When the system is running, the size of the journal file is
-** stored in volatile memory. When recovering from a crash, this vfs
-** reports a very large size for the journal file. The normal journal
-** header and checksum mechanisms serve to prevent SQLite from
-** processing any data that lies past the logical end of the journal.
-**
-** When SQLite calls OsDelete() to delete the journal file, the final
-** 512 bytes of the blob (the area containing the first journal header)
-** are zeroed.
-**
-** LOCKING:
-**
-** File locking is a no-op. Only one connection may be open at any one
-** time using this demo vfs.
-*/
-
-#include "sqlite3.h"
-#include <assert.h>
-#include <string.h>
-
-/*
-** Maximum pathname length supported by the fs backend.
-*/
-#define BLOCKSIZE 512
-#define BLOBSIZE 10485760
-
-/*
-** Name used to identify this VFS.
-*/
-#define FS_VFS_NAME "fs"
-
-typedef struct fs_real_file fs_real_file;
-struct fs_real_file {
- sqlite3_file *pFile;
- const char *zName;
- int nDatabase; /* Current size of database region */
- int nJournal; /* Current size of journal region */
- int nBlob; /* Total size of allocated blob */
- int nRef; /* Number of pointers to this structure */
- fs_real_file *pNext;
- fs_real_file **ppThis;
-};
-
-typedef struct fs_file fs_file;
-struct fs_file {
- sqlite3_file base;
- int eType;
- fs_real_file *pReal;
-};
-
-typedef struct tmp_file tmp_file;
-struct tmp_file {
- sqlite3_file base;
- int nSize;
- int nAlloc;
- char *zAlloc;
-};
-
-/* Values for fs_file.eType. */
-#define DATABASE_FILE 1
-#define JOURNAL_FILE 2
-
-/*
-** Method declarations for fs_file.
-*/
-static int fsClose(sqlite3_file*);
-static int fsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int fsWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
-static int fsTruncate(sqlite3_file*, sqlite3_int64 size);
-static int fsSync(sqlite3_file*, int flags);
-static int fsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int fsLock(sqlite3_file*, int);
-static int fsUnlock(sqlite3_file*, int);
-static int fsCheckReservedLock(sqlite3_file*, int *pResOut);
-static int fsFileControl(sqlite3_file*, int op, void *pArg);
-static int fsSectorSize(sqlite3_file*);
-static int fsDeviceCharacteristics(sqlite3_file*);
-
-/*
-** Method declarations for tmp_file.
-*/
-static int tmpClose(sqlite3_file*);
-static int tmpRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int tmpWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
-static int tmpTruncate(sqlite3_file*, sqlite3_int64 size);
-static int tmpSync(sqlite3_file*, int flags);
-static int tmpFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int tmpLock(sqlite3_file*, int);
-static int tmpUnlock(sqlite3_file*, int);
-static int tmpCheckReservedLock(sqlite3_file*, int *pResOut);
-static int tmpFileControl(sqlite3_file*, int op, void *pArg);
-static int tmpSectorSize(sqlite3_file*);
-static int tmpDeviceCharacteristics(sqlite3_file*);
-
-/*
-** Method declarations for fs_vfs.
-*/
-static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
-static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);
-static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*fsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
-static void fsDlClose(sqlite3_vfs*, void*);
-static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int fsSleep(sqlite3_vfs*, int microseconds);
-static int fsCurrentTime(sqlite3_vfs*, double*);
-
-
-typedef struct fs_vfs_t fs_vfs_t;
-struct fs_vfs_t {
- sqlite3_vfs base;
- fs_real_file *pFileList;
- sqlite3_vfs *pParent;
-};
-
-static fs_vfs_t fs_vfs = {
- {
- 1, /* iVersion */
- 0, /* szOsFile */
- 0, /* mxPathname */
- 0, /* pNext */
- FS_VFS_NAME, /* zName */
- 0, /* pAppData */
- fsOpen, /* xOpen */
- fsDelete, /* xDelete */
- fsAccess, /* xAccess */
- fsFullPathname, /* xFullPathname */
- fsDlOpen, /* xDlOpen */
- fsDlError, /* xDlError */
- fsDlSym, /* xDlSym */
- fsDlClose, /* xDlClose */
- fsRandomness, /* xRandomness */
- fsSleep, /* xSleep */
- fsCurrentTime, /* xCurrentTime */
- 0 /* xCurrentTimeInt64 */
- },
- 0, /* pFileList */
- 0 /* pParent */
-};
-
-static sqlite3_io_methods fs_io_methods = {
- 1, /* iVersion */
- fsClose, /* xClose */
- fsRead, /* xRead */
- fsWrite, /* xWrite */
- fsTruncate, /* xTruncate */
- fsSync, /* xSync */
- fsFileSize, /* xFileSize */
- fsLock, /* xLock */
- fsUnlock, /* xUnlock */
- fsCheckReservedLock, /* xCheckReservedLock */
- fsFileControl, /* xFileControl */
- fsSectorSize, /* xSectorSize */
- fsDeviceCharacteristics, /* xDeviceCharacteristics */
- 0, /* xShmMap */
- 0, /* xShmLock */
- 0, /* xShmBarrier */
- 0 /* xShmUnmap */
-};
-
-
-static sqlite3_io_methods tmp_io_methods = {
- 1, /* iVersion */
- tmpClose, /* xClose */
- tmpRead, /* xRead */
- tmpWrite, /* xWrite */
- tmpTruncate, /* xTruncate */
- tmpSync, /* xSync */
- tmpFileSize, /* xFileSize */
- tmpLock, /* xLock */
- tmpUnlock, /* xUnlock */
- tmpCheckReservedLock, /* xCheckReservedLock */
- tmpFileControl, /* xFileControl */
- tmpSectorSize, /* xSectorSize */
- tmpDeviceCharacteristics, /* xDeviceCharacteristics */
- 0, /* xShmMap */
- 0, /* xShmLock */
- 0, /* xShmBarrier */
- 0 /* xShmUnmap */
-};
-
-/* Useful macros used in several places */
-#define MIN(x,y) ((x)<(y)?(x):(y))
-#define MAX(x,y) ((x)>(y)?(x):(y))
-
-
-/*
-** Close a tmp-file.
-*/
-static int tmpClose(sqlite3_file *pFile){
- tmp_file *pTmp = (tmp_file *)pFile;
- sqlite3_free(pTmp->zAlloc);
- return SQLITE_OK;
-}
-
-/*
-** Read data from a tmp-file.
-*/
-static int tmpRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- tmp_file *pTmp = (tmp_file *)pFile;
- if( (iAmt+iOfst)>pTmp->nSize ){
- return SQLITE_IOERR_SHORT_READ;
- }
- memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt);
- return SQLITE_OK;
-}
-
-/*
-** Write data to a tmp-file.
-*/
-static int tmpWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- tmp_file *pTmp = (tmp_file *)pFile;
- if( (iAmt+iOfst)>pTmp->nAlloc ){
- int nNew = (int)(2*(iAmt+iOfst+pTmp->nAlloc));
- char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- pTmp->zAlloc = zNew;
- pTmp->nAlloc = nNew;
- }
- memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt);
- pTmp->nSize = (int)MAX(pTmp->nSize, iOfst+iAmt);
- return SQLITE_OK;
-}
-
-/*
-** Truncate a tmp-file.
-*/
-static int tmpTruncate(sqlite3_file *pFile, sqlite_int64 size){
- tmp_file *pTmp = (tmp_file *)pFile;
- pTmp->nSize = (int)MIN(pTmp->nSize, size);
- return SQLITE_OK;
-}
-
-/*
-** Sync a tmp-file.
-*/
-static int tmpSync(sqlite3_file *pFile, int flags){
- return SQLITE_OK;
-}
-
-/*
-** Return the current file-size of a tmp-file.
-*/
-static int tmpFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- tmp_file *pTmp = (tmp_file *)pFile;
- *pSize = pTmp->nSize;
- return SQLITE_OK;
-}
-
-/*
-** Lock a tmp-file.
-*/
-static int tmpLock(sqlite3_file *pFile, int eLock){
- return SQLITE_OK;
-}
-
-/*
-** Unlock a tmp-file.
-*/
-static int tmpUnlock(sqlite3_file *pFile, int eLock){
- return SQLITE_OK;
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on a tmp-file.
-*/
-static int tmpCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- *pResOut = 0;
- return SQLITE_OK;
-}
-
-/*
-** File control method. For custom operations on a tmp-file.
-*/
-static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){
- return SQLITE_OK;
-}
-
-/*
-** Return the sector-size in bytes for a tmp-file.
-*/
-static int tmpSectorSize(sqlite3_file *pFile){
- return 0;
-}
-
-/*
-** Return the device characteristic flags supported by a tmp-file.
-*/
-static int tmpDeviceCharacteristics(sqlite3_file *pFile){
- return 0;
-}
-
-/*
-** Close an fs-file.
-*/
-static int fsClose(sqlite3_file *pFile){
- int rc = SQLITE_OK;
- fs_file *p = (fs_file *)pFile;
- fs_real_file *pReal = p->pReal;
-
- /* Decrement the real_file ref-count. */
- pReal->nRef--;
- assert(pReal->nRef>=0);
-
- /* When the ref-count reaches 0, destroy the structure */
- if( pReal->nRef==0 ){
- *pReal->ppThis = pReal->pNext;
- if( pReal->pNext ){
- pReal->pNext->ppThis = pReal->ppThis;
- }
- rc = pReal->pFile->pMethods->xClose(pReal->pFile);
- sqlite3_free(pReal);
- }
-
- return rc;
-}
-
-/*
-** Read data from an fs-file.
-*/
-static int fsRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc = SQLITE_OK;
- fs_file *p = (fs_file *)pFile;
- fs_real_file *pReal = p->pReal;
- sqlite3_file *pF = pReal->pFile;
-
- if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase)
- || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal)
- ){
- rc = SQLITE_IOERR_SHORT_READ;
- }else if( p->eType==DATABASE_FILE ){
- rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
- }else{
- /* Journal file. */
- int iRem = iAmt;
- int iBuf = 0;
- int ii = (int)iOfst;
- while( iRem>0 && rc==SQLITE_OK ){
- int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
- int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
-
- rc = pF->pMethods->xRead(pF, &((char *)zBuf)[iBuf], iRealAmt, iRealOff);
- ii += iRealAmt;
- iBuf += iRealAmt;
- iRem -= iRealAmt;
- }
- }
-
- return rc;
-}
-
-/*
-** Write data to an fs-file.
-*/
-static int fsWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc = SQLITE_OK;
- fs_file *p = (fs_file *)pFile;
- fs_real_file *pReal = p->pReal;
- sqlite3_file *pF = pReal->pFile;
-
- if( p->eType==DATABASE_FILE ){
- if( (iAmt+iOfst+BLOCKSIZE)>(pReal->nBlob-pReal->nJournal) ){
- rc = SQLITE_FULL;
- }else{
- rc = pF->pMethods->xWrite(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
- if( rc==SQLITE_OK ){
- pReal->nDatabase = (int)MAX(pReal->nDatabase, iAmt+iOfst);
- }
- }
- }else{
- /* Journal file. */
- int iRem = iAmt;
- int iBuf = 0;
- int ii = (int)iOfst;
- while( iRem>0 && rc==SQLITE_OK ){
- int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
- int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
-
- if( iRealOff<(pReal->nDatabase+BLOCKSIZE) ){
- rc = SQLITE_FULL;
- }else{
- rc = pF->pMethods->xWrite(pF, &((char *)zBuf)[iBuf], iRealAmt,iRealOff);
- ii += iRealAmt;
- iBuf += iRealAmt;
- iRem -= iRealAmt;
- }
- }
- if( rc==SQLITE_OK ){
- pReal->nJournal = (int)MAX(pReal->nJournal, iAmt+iOfst);
- }
- }
-
- return rc;
-}
-
-/*
-** Truncate an fs-file.
-*/
-static int fsTruncate(sqlite3_file *pFile, sqlite_int64 size){
- fs_file *p = (fs_file *)pFile;
- fs_real_file *pReal = p->pReal;
- if( p->eType==DATABASE_FILE ){
- pReal->nDatabase = (int)MIN(pReal->nDatabase, size);
- }else{
- pReal->nJournal = (int)MIN(pReal->nJournal, size);
- }
- return SQLITE_OK;
-}
-
-/*
-** Sync an fs-file.
-*/
-static int fsSync(sqlite3_file *pFile, int flags){
- fs_file *p = (fs_file *)pFile;
- fs_real_file *pReal = p->pReal;
- sqlite3_file *pRealFile = pReal->pFile;
- int rc = SQLITE_OK;
-
- if( p->eType==DATABASE_FILE ){
- unsigned char zSize[4];
- zSize[0] = (pReal->nDatabase&0xFF000000)>>24;
- zSize[1] = (unsigned char)((pReal->nDatabase&0x00FF0000)>>16);
- zSize[2] = (pReal->nDatabase&0x0000FF00)>>8;
- zSize[3] = (pReal->nDatabase&0x000000FF);
- rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0);
- }
- if( rc==SQLITE_OK ){
- rc = pRealFile->pMethods->xSync(pRealFile, flags&(~SQLITE_SYNC_DATAONLY));
- }
-
- return rc;
-}
-
-/*
-** Return the current file-size of an fs-file.
-*/
-static int fsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- fs_file *p = (fs_file *)pFile;
- fs_real_file *pReal = p->pReal;
- if( p->eType==DATABASE_FILE ){
- *pSize = pReal->nDatabase;
- }else{
- *pSize = pReal->nJournal;
- }
- return SQLITE_OK;
-}
-
-/*
-** Lock an fs-file.
-*/
-static int fsLock(sqlite3_file *pFile, int eLock){
- return SQLITE_OK;
-}
-
-/*
-** Unlock an fs-file.
-*/
-static int fsUnlock(sqlite3_file *pFile, int eLock){
- return SQLITE_OK;
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an fs-file.
-*/
-static int fsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- *pResOut = 0;
- return SQLITE_OK;
-}
-
-/*
-** File control method. For custom operations on an fs-file.
-*/
-static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){
- return SQLITE_OK;
-}
-
-/*
-** Return the sector-size in bytes for an fs-file.
-*/
-static int fsSectorSize(sqlite3_file *pFile){
- return BLOCKSIZE;
-}
-
-/*
-** Return the device characteristic flags supported by an fs-file.
-*/
-static int fsDeviceCharacteristics(sqlite3_file *pFile){
- return 0;
-}
-
-/*
-** Open an fs file handle.
-*/
-static int fsOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
- fs_file *p = (fs_file *)pFile;
- fs_real_file *pReal = 0;
- int eType;
- int nName;
- int rc = SQLITE_OK;
-
- if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){
- tmp_file *p2 = (tmp_file *)pFile;
- memset(p2, 0, sizeof(*p2));
- p2->base.pMethods = &tmp_io_methods;
- return SQLITE_OK;
- }
-
- eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE);
- p->base.pMethods = &fs_io_methods;
- p->eType = eType;
-
- assert(strlen("-journal")==8);
- nName = (int)strlen(zName)-((eType==JOURNAL_FILE)?8:0);
- pReal=pFsVfs->pFileList;
- for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext);
-
- if( !pReal ){
- int real_flags = (flags&~(SQLITE_OPEN_MAIN_DB))|SQLITE_OPEN_TEMP_DB;
- sqlite3_int64 size;
- sqlite3_file *pRealFile;
- sqlite3_vfs *pParent = pFsVfs->pParent;
- assert(eType==DATABASE_FILE);
-
- pReal = (fs_real_file *)sqlite3_malloc(sizeof(*pReal)+pParent->szOsFile);
- if( !pReal ){
- rc = SQLITE_NOMEM;
- goto open_out;
- }
- memset(pReal, 0, sizeof(*pReal)+pParent->szOsFile);
- pReal->zName = zName;
- pReal->pFile = (sqlite3_file *)(&pReal[1]);
-
- rc = pParent->xOpen(pParent, zName, pReal->pFile, real_flags, pOutFlags);
- if( rc!=SQLITE_OK ){
- goto open_out;
- }
- pRealFile = pReal->pFile;
-
- rc = pRealFile->pMethods->xFileSize(pRealFile, &size);
- if( rc!=SQLITE_OK ){
- goto open_out;
- }
- if( size==0 ){
- rc = pRealFile->pMethods->xWrite(pRealFile, "\0", 1, BLOBSIZE-1);
- pReal->nBlob = BLOBSIZE;
- }else{
- unsigned char zS[4];
- pReal->nBlob = (int)size;
- rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, 0);
- pReal->nDatabase = (zS[0]<<24)+(zS[1]<<16)+(zS[2]<<8)+zS[3];
- if( rc==SQLITE_OK ){
- rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, pReal->nBlob-4);
- if( zS[0] || zS[1] || zS[2] || zS[3] ){
- pReal->nJournal = pReal->nBlob;
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- pReal->pNext = pFsVfs->pFileList;
- if( pReal->pNext ){
- pReal->pNext->ppThis = &pReal->pNext;
- }
- pReal->ppThis = &pFsVfs->pFileList;
- pFsVfs->pFileList = pReal;
- }
- }
-
-open_out:
- if( pReal ){
- if( rc==SQLITE_OK ){
- p->pReal = pReal;
- pReal->nRef++;
- }else{
- if( pReal->pFile->pMethods ){
- pReal->pFile->pMethods->xClose(pReal->pFile);
- }
- sqlite3_free(pReal);
- }
- }
- return rc;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- int rc = SQLITE_OK;
- fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
- fs_real_file *pReal;
- sqlite3_file *pF;
- int nName = (int)strlen(zPath) - 8;
-
- assert(strlen("-journal")==8);
- assert(strcmp("-journal", &zPath[nName])==0);
-
- pReal = pFsVfs->pFileList;
- for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
- if( pReal ){
- pF = pReal->pFile;
- rc = pF->pMethods->xWrite(pF, "\0\0\0\0", 4, pReal->nBlob-BLOCKSIZE);
- if( rc==SQLITE_OK ){
- pReal->nJournal = 0;
- }
- }
- return rc;
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int fsAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
- fs_real_file *pReal;
- int isJournal = 0;
- int nName = (int)strlen(zPath);
-
- if( flags!=SQLITE_ACCESS_EXISTS ){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- return pParent->xAccess(pParent, zPath, flags, pResOut);
- }
-
- assert(strlen("-journal")==8);
- if( nName>8 && strcmp("-journal", &zPath[nName-8])==0 ){
- nName -= 8;
- isJournal = 1;
- }
-
- pReal = pFsVfs->pFileList;
- for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
-
- *pResOut = (pReal && (!isJournal || pReal->nJournal>0));
- return SQLITE_OK;
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (FS_MAX_PATHNAME+1) bytes.
-*/
-static int fsFullPathname(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- const char *zPath, /* Possibly relative input path */
- int nOut, /* Size of output buffer in bytes */
- char *zOut /* Output buffer */
-){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- return pParent->xFullPathname(pParent, zPath, nOut, zOut);
-}
-
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *fsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- return pParent->xDlOpen(pParent, zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void fsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- pParent->xDlError(pParent, nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*fsDlSym(sqlite3_vfs *pVfs, void *pH, const char *zSym))(void){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- return pParent->xDlSym(pParent, pH, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void fsDlClose(sqlite3_vfs *pVfs, void *pHandle){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- pParent->xDlClose(pParent, pHandle);
-}
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- return pParent->xRandomness(pParent, nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int fsSleep(sqlite3_vfs *pVfs, int nMicro){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- return pParent->xSleep(pParent, nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int fsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
- return pParent->xCurrentTime(pParent, pTimeOut);
-}
-
-/*
-** This procedure registers the fs vfs with SQLite. If the argument is
-** true, the fs vfs becomes the new default vfs. It is the only publicly
-** available function in this file.
-*/
-int fs_register(void){
- if( fs_vfs.pParent ) return SQLITE_OK;
- fs_vfs.pParent = sqlite3_vfs_find(0);
- fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname;
- fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file));
- return sqlite3_vfs_register(&fs_vfs.base, 0);
-}
-
-#ifdef SQLITE_TEST
- int SqlitetestOnefile_Init() {return fs_register();}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_osinst.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_osinst.c
deleted file mode 100644
index a008baba45d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_osinst.c
+++ /dev/null
@@ -1,1224 +0,0 @@
-/*
-** 2008 April 10
-**
-** 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 contains the implementation of an SQLite vfs wrapper that
-** adds instrumentation to all vfs and file methods. C and Tcl interfaces
-** are provided to control the instrumentation.
-*/
-
-/*
-** This module contains code for a wrapper VFS that causes a log of
-** most VFS calls to be written into a nominated file on disk. The log
-** is stored in a compressed binary format to reduce the amount of IO
-** overhead introduced into the application by logging.
-**
-** All calls on sqlite3_file objects except xFileControl() are logged.
-** Additionally, calls to the xAccess(), xOpen(), and xDelete()
-** methods are logged. The other sqlite3_vfs object methods (xDlXXX,
-** xRandomness, xSleep, xCurrentTime, xGetLastError and xCurrentTimeInt64)
-** are not logged.
-**
-** The binary log files are read using a virtual table implementation
-** also contained in this file.
-**
-** CREATING LOG FILES:
-**
-** int sqlite3_vfslog_new(
-** const char *zVfs, // Name of new VFS
-** const char *zParentVfs, // Name of parent VFS (or NULL)
-** const char *zLog // Name of log file to write to
-** );
-**
-** int sqlite3_vfslog_finalize(const char *zVfs);
-**
-** ANNOTATING LOG FILES:
-**
-** To write an arbitrary message into a log file:
-**
-** int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg);
-**
-** READING LOG FILES:
-**
-** Log files are read using the "vfslog" virtual table implementation
-** in this file. To register the virtual table with SQLite, use:
-**
-** int sqlite3_vfslog_register(sqlite3 *db);
-**
-** Then, if the log file is named "vfs.log", the following SQL command:
-**
-** CREATE VIRTUAL TABLE v USING vfslog('vfs.log');
-**
-** creates a virtual table with 6 columns, as follows:
-**
-** CREATE TABLE v(
-** event TEXT, // "xOpen", "xRead" etc.
-** file TEXT, // Name of file this call applies to
-** clicks INTEGER, // Time spent in call
-** rc INTEGER, // Return value
-** size INTEGER, // Bytes read or written
-** offset INTEGER // File offset read or written
-** );
-*/
-
-#include "sqlite3.h"
-
-#include "os_setup.h"
-#if SQLITE_OS_WIN
-# include "os_win.h"
-#endif
-
-#include <string.h>
-#include <assert.h>
-
-
-/*
-** Maximum pathname length supported by the vfslog backend.
-*/
-#define INST_MAX_PATHNAME 512
-
-#define OS_ACCESS 1
-#define OS_CHECKRESERVEDLOCK 2
-#define OS_CLOSE 3
-#define OS_CURRENTTIME 4
-#define OS_DELETE 5
-#define OS_DEVCHAR 6
-#define OS_FILECONTROL 7
-#define OS_FILESIZE 8
-#define OS_FULLPATHNAME 9
-#define OS_LOCK 11
-#define OS_OPEN 12
-#define OS_RANDOMNESS 13
-#define OS_READ 14
-#define OS_SECTORSIZE 15
-#define OS_SLEEP 16
-#define OS_SYNC 17
-#define OS_TRUNCATE 18
-#define OS_UNLOCK 19
-#define OS_WRITE 20
-#define OS_SHMUNMAP 22
-#define OS_SHMMAP 23
-#define OS_SHMLOCK 25
-#define OS_SHMBARRIER 26
-#define OS_ANNOTATE 28
-
-#define OS_NUMEVENTS 29
-
-#define VFSLOG_BUFFERSIZE 8192
-
-typedef struct VfslogVfs VfslogVfs;
-typedef struct VfslogFile VfslogFile;
-
-struct VfslogVfs {
- sqlite3_vfs base; /* VFS methods */
- sqlite3_vfs *pVfs; /* Parent VFS */
- int iNextFileId; /* Next file id */
- sqlite3_file *pLog; /* Log file handle */
- sqlite3_int64 iOffset; /* Log file offset of start of write buffer */
- int nBuf; /* Number of valid bytes in aBuf[] */
- char aBuf[VFSLOG_BUFFERSIZE]; /* Write buffer */
-};
-
-struct VfslogFile {
- sqlite3_file base; /* IO methods */
- sqlite3_file *pReal; /* Underlying file handle */
- sqlite3_vfs *pVfslog; /* Associated VsflogVfs object */
- int iFileId; /* File id number */
-};
-
-#define REALVFS(p) (((VfslogVfs *)(p))->pVfs)
-
-
-
-/*
-** Method declarations for vfslog_file.
-*/
-static int vfslogClose(sqlite3_file*);
-static int vfslogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int vfslogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int vfslogTruncate(sqlite3_file*, sqlite3_int64 size);
-static int vfslogSync(sqlite3_file*, int flags);
-static int vfslogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int vfslogLock(sqlite3_file*, int);
-static int vfslogUnlock(sqlite3_file*, int);
-static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut);
-static int vfslogFileControl(sqlite3_file*, int op, void *pArg);
-static int vfslogSectorSize(sqlite3_file*);
-static int vfslogDeviceCharacteristics(sqlite3_file*);
-
-static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags);
-static int vfslogShmMap(sqlite3_file *pFile,int,int,int,volatile void **);
-static void vfslogShmBarrier(sqlite3_file*);
-static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag);
-
-/*
-** Method declarations for vfslog_vfs.
-*/
-static int vfslogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int vfslogDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int vfslogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int vfslogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-static void *vfslogDlOpen(sqlite3_vfs*, const char *zFilename);
-static void vfslogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
-static void vfslogDlClose(sqlite3_vfs*, void*);
-static int vfslogRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int vfslogSleep(sqlite3_vfs*, int microseconds);
-static int vfslogCurrentTime(sqlite3_vfs*, double*);
-
-static int vfslogGetLastError(sqlite3_vfs*, int, char *);
-static int vfslogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-
-static sqlite3_vfs vfslog_vfs = {
- 1, /* iVersion */
- sizeof(VfslogFile), /* szOsFile */
- INST_MAX_PATHNAME, /* mxPathname */
- 0, /* pNext */
- 0, /* zName */
- 0, /* pAppData */
- vfslogOpen, /* xOpen */
- vfslogDelete, /* xDelete */
- vfslogAccess, /* xAccess */
- vfslogFullPathname, /* xFullPathname */
- vfslogDlOpen, /* xDlOpen */
- vfslogDlError, /* xDlError */
- vfslogDlSym, /* xDlSym */
- vfslogDlClose, /* xDlClose */
- vfslogRandomness, /* xRandomness */
- vfslogSleep, /* xSleep */
- vfslogCurrentTime, /* xCurrentTime */
- vfslogGetLastError, /* xGetLastError */
- vfslogCurrentTimeInt64 /* xCurrentTime */
-};
-
-static sqlite3_io_methods vfslog_io_methods = {
- 2, /* iVersion */
- vfslogClose, /* xClose */
- vfslogRead, /* xRead */
- vfslogWrite, /* xWrite */
- vfslogTruncate, /* xTruncate */
- vfslogSync, /* xSync */
- vfslogFileSize, /* xFileSize */
- vfslogLock, /* xLock */
- vfslogUnlock, /* xUnlock */
- vfslogCheckReservedLock, /* xCheckReservedLock */
- vfslogFileControl, /* xFileControl */
- vfslogSectorSize, /* xSectorSize */
- vfslogDeviceCharacteristics, /* xDeviceCharacteristics */
- vfslogShmMap, /* xShmMap */
- vfslogShmLock, /* xShmLock */
- vfslogShmBarrier, /* xShmBarrier */
- vfslogShmUnmap /* xShmUnmap */
-};
-
-#if SQLITE_OS_UNIX && !defined(NO_GETTOD)
-#include <sys/time.h>
-static sqlite3_uint64 vfslog_time(){
- struct timeval sTime;
- gettimeofday(&sTime, 0);
- return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
-}
-#elif SQLITE_OS_WIN
-#include <time.h>
-static sqlite3_uint64 vfslog_time(){
- FILETIME ft;
- sqlite3_uint64 u64time = 0;
-
- GetSystemTimeAsFileTime(&ft);
-
- u64time |= ft.dwHighDateTime;
- u64time <<= 32;
- u64time |= ft.dwLowDateTime;
-
- /* ft is 100-nanosecond intervals, we want microseconds */
- return u64time /(sqlite3_uint64)10;
-}
-#else
-static sqlite3_uint64 vfslog_time(){
- return 0;
-}
-#endif
-
-static void vfslog_call(sqlite3_vfs *, int, int, sqlite3_int64, int, int, int);
-static void vfslog_string(sqlite3_vfs *, const char *);
-
-/*
-** Close an vfslog-file.
-*/
-static int vfslogClose(sqlite3_file *pFile){
- sqlite3_uint64 t;
- int rc = SQLITE_OK;
- VfslogFile *p = (VfslogFile *)pFile;
-
- t = vfslog_time();
- if( p->pReal->pMethods ){
- rc = p->pReal->pMethods->xClose(p->pReal);
- }
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_CLOSE, p->iFileId, t, rc, 0, 0);
- return rc;
-}
-
-/*
-** Read data from an vfslog-file.
-*/
-static int vfslogRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_READ, p->iFileId, t, rc, iAmt, (int)iOfst);
- return rc;
-}
-
-/*
-** Write data to an vfslog-file.
-*/
-static int vfslogWrite(
- sqlite3_file *pFile,
- const void *z,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_WRITE, p->iFileId, t, rc, iAmt, (int)iOfst);
- return rc;
-}
-
-/*
-** Truncate an vfslog-file.
-*/
-static int vfslogTruncate(sqlite3_file *pFile, sqlite_int64 size){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xTruncate(p->pReal, size);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_TRUNCATE, p->iFileId, t, rc, 0, (int)size);
- return rc;
-}
-
-/*
-** Sync an vfslog-file.
-*/
-static int vfslogSync(sqlite3_file *pFile, int flags){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xSync(p->pReal, flags);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_SYNC, p->iFileId, t, rc, flags, 0);
- return rc;
-}
-
-/*
-** Return the current file-size of an vfslog-file.
-*/
-static int vfslogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_FILESIZE, p->iFileId, t, rc, 0, (int)*pSize);
- return rc;
-}
-
-/*
-** Lock an vfslog-file.
-*/
-static int vfslogLock(sqlite3_file *pFile, int eLock){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xLock(p->pReal, eLock);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_LOCK, p->iFileId, t, rc, eLock, 0);
- return rc;
-}
-
-/*
-** Unlock an vfslog-file.
-*/
-static int vfslogUnlock(sqlite3_file *pFile, int eLock){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_UNLOCK, p->iFileId, t, rc, eLock, 0);
- return rc;
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an vfslog-file.
-*/
-static int vfslogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_CHECKRESERVEDLOCK, p->iFileId, t, rc, *pResOut, 0);
- return rc;
-}
-
-/*
-** File control method. For custom operations on an vfslog-file.
-*/
-static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){
- VfslogFile *p = (VfslogFile *)pFile;
- int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
- if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
- *(char**)pArg = sqlite3_mprintf("vfslog/%z", *(char**)pArg);
- }
- return rc;
-}
-
-/*
-** Return the sector-size in bytes for an vfslog-file.
-*/
-static int vfslogSectorSize(sqlite3_file *pFile){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xSectorSize(p->pReal);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_SECTORSIZE, p->iFileId, t, rc, 0, 0);
- return rc;
-}
-
-/*
-** Return the device characteristic flags supported by an vfslog-file.
-*/
-static int vfslogDeviceCharacteristics(sqlite3_file *pFile){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_DEVCHAR, p->iFileId, t, rc, 0, 0);
- return rc;
-}
-
-static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_SHMLOCK, p->iFileId, t, rc, 0, 0);
- return rc;
-}
-static int vfslogShmMap(
- sqlite3_file *pFile,
- int iRegion,
- int szRegion,
- int isWrite,
- volatile void **pp
-){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_SHMMAP, p->iFileId, t, rc, 0, 0);
- return rc;
-}
-static void vfslogShmBarrier(sqlite3_file *pFile){
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- p->pReal->pMethods->xShmBarrier(p->pReal);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_SHMBARRIER, p->iFileId, t, SQLITE_OK, 0, 0);
-}
-static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- t = vfslog_time();
- rc = p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
- t = vfslog_time() - t;
- vfslog_call(p->pVfslog, OS_SHMUNMAP, p->iFileId, t, rc, 0, 0);
- return rc;
-}
-
-
-/*
-** Open an vfslog file handle.
-*/
-static int vfslogOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- int rc;
- sqlite3_uint64 t;
- VfslogFile *p = (VfslogFile *)pFile;
- VfslogVfs *pLog = (VfslogVfs *)pVfs;
-
- pFile->pMethods = &vfslog_io_methods;
- p->pReal = (sqlite3_file *)&p[1];
- p->pVfslog = pVfs;
- p->iFileId = ++pLog->iNextFileId;
-
- t = vfslog_time();
- rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
- t = vfslog_time() - t;
-
- vfslog_call(pVfs, OS_OPEN, p->iFileId, t, rc, 0, 0);
- vfslog_string(pVfs, zName);
- return rc;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int vfslogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- int rc;
- sqlite3_uint64 t;
- t = vfslog_time();
- rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
- t = vfslog_time() - t;
- vfslog_call(pVfs, OS_DELETE, 0, t, rc, dirSync, 0);
- vfslog_string(pVfs, zPath);
- return rc;
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int vfslogAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- int rc;
- sqlite3_uint64 t;
- t = vfslog_time();
- rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
- t = vfslog_time() - t;
- vfslog_call(pVfs, OS_ACCESS, 0, t, rc, flags, *pResOut);
- vfslog_string(pVfs, zPath);
- return rc;
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (INST_MAX_PATHNAME+1) bytes.
-*/
-static int vfslogFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
-}
-
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *vfslogDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void vfslogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void vfslogDlClose(sqlite3_vfs *pVfs, void *pHandle){
- REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
-}
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int vfslogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int vfslogSleep(sqlite3_vfs *pVfs, int nMicro){
- return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int vfslogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
-}
-
-static int vfslogGetLastError(sqlite3_vfs *pVfs, int a, char *b){
- return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
-}
-static int vfslogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
- return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
-}
-
-static void vfslog_flush(VfslogVfs *p){
-#ifdef SQLITE_TEST
- extern int sqlite3_io_error_pending;
- extern int sqlite3_io_error_persist;
- extern int sqlite3_diskfull_pending;
-
- int pending = sqlite3_io_error_pending;
- int persist = sqlite3_io_error_persist;
- int diskfull = sqlite3_diskfull_pending;
-
- sqlite3_io_error_pending = 0;
- sqlite3_io_error_persist = 0;
- sqlite3_diskfull_pending = 0;
-#endif
-
- if( p->nBuf ){
- p->pLog->pMethods->xWrite(p->pLog, p->aBuf, p->nBuf, p->iOffset);
- p->iOffset += p->nBuf;
- p->nBuf = 0;
- }
-
-#ifdef SQLITE_TEST
- sqlite3_io_error_pending = pending;
- sqlite3_io_error_persist = persist;
- sqlite3_diskfull_pending = diskfull;
-#endif
-}
-
-static void put32bits(unsigned char *p, unsigned int v){
- p[0] = v>>24;
- p[1] = (unsigned char)(v>>16);
- p[2] = (unsigned char)(v>>8);
- p[3] = (unsigned char)v;
-}
-
-static void vfslog_call(
- sqlite3_vfs *pVfs,
- int eEvent,
- int iFileid,
- sqlite3_int64 nClick,
- int return_code,
- int size,
- int offset
-){
- VfslogVfs *p = (VfslogVfs *)pVfs;
- unsigned char *zRec;
- if( (24+p->nBuf)>sizeof(p->aBuf) ){
- vfslog_flush(p);
- }
- zRec = (unsigned char *)&p->aBuf[p->nBuf];
- put32bits(&zRec[0], eEvent);
- put32bits(&zRec[4], iFileid);
- put32bits(&zRec[8], (unsigned int)(nClick&0xffff));
- put32bits(&zRec[12], return_code);
- put32bits(&zRec[16], size);
- put32bits(&zRec[20], offset);
- p->nBuf += 24;
-}
-
-static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){
- VfslogVfs *p = (VfslogVfs *)pVfs;
- unsigned char *zRec;
- int nStr = zStr ? (int)strlen(zStr) : 0;
- if( (4+nStr+p->nBuf)>sizeof(p->aBuf) ){
- vfslog_flush(p);
- }
- zRec = (unsigned char *)&p->aBuf[p->nBuf];
- put32bits(&zRec[0], nStr);
- if( zStr ){
- memcpy(&zRec[4], zStr, nStr);
- }
- p->nBuf += (4 + nStr);
-}
-
-static void vfslog_finalize(VfslogVfs *p){
- if( p->pLog->pMethods ){
- vfslog_flush(p);
- p->pLog->pMethods->xClose(p->pLog);
- }
- sqlite3_free(p);
-}
-
-int sqlite3_vfslog_finalize(const char *zVfs){
- sqlite3_vfs *pVfs;
- pVfs = sqlite3_vfs_find(zVfs);
- if( !pVfs || pVfs->xOpen!=vfslogOpen ){
- return SQLITE_ERROR;
- }
- sqlite3_vfs_unregister(pVfs);
- vfslog_finalize((VfslogVfs *)pVfs);
- return SQLITE_OK;
-}
-
-int sqlite3_vfslog_new(
- const char *zVfs, /* New VFS name */
- const char *zParentVfs, /* Parent VFS name (or NULL) */
- const char *zLog /* Log file name */
-){
- VfslogVfs *p;
- sqlite3_vfs *pParent;
- int nByte;
- int flags;
- int rc;
- char *zFile;
- int nVfs;
-
- pParent = sqlite3_vfs_find(zParentVfs);
- if( !pParent ){
- return SQLITE_ERROR;
- }
-
- nVfs = (int)strlen(zVfs);
- nByte = sizeof(VfslogVfs) + pParent->szOsFile + nVfs+1+pParent->mxPathname+1;
- p = (VfslogVfs *)sqlite3_malloc(nByte);
- memset(p, 0, nByte);
-
- p->pVfs = pParent;
- p->pLog = (sqlite3_file *)&p[1];
- memcpy(&p->base, &vfslog_vfs, sizeof(sqlite3_vfs));
- p->base.zName = &((char *)p->pLog)[pParent->szOsFile];
- p->base.szOsFile += pParent->szOsFile;
- memcpy((char *)p->base.zName, zVfs, nVfs);
-
- zFile = (char *)&p->base.zName[nVfs+1];
- pParent->xFullPathname(pParent, zLog, pParent->mxPathname, zFile);
-
- flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL;
- pParent->xDelete(pParent, zFile, 0);
- rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags);
- if( rc==SQLITE_OK ){
- memcpy(p->aBuf, "sqlite_ostrace1.....", 20);
- p->iOffset = 0;
- p->nBuf = 20;
- rc = sqlite3_vfs_register((sqlite3_vfs *)p, 1);
- }
- if( rc ){
- vfslog_finalize(p);
- }
- return rc;
-}
-
-int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg){
- sqlite3_vfs *pVfs;
- pVfs = sqlite3_vfs_find(zVfs);
- if( !pVfs || pVfs->xOpen!=vfslogOpen ){
- return SQLITE_ERROR;
- }
- vfslog_call(pVfs, OS_ANNOTATE, 0, 0, 0, 0, 0);
- vfslog_string(pVfs, zMsg);
- return SQLITE_OK;
-}
-
-static const char *vfslog_eventname(int eEvent){
- const char *zEvent = 0;
-
- switch( eEvent ){
- case OS_CLOSE: zEvent = "xClose"; break;
- case OS_READ: zEvent = "xRead"; break;
- case OS_WRITE: zEvent = "xWrite"; break;
- case OS_TRUNCATE: zEvent = "xTruncate"; break;
- case OS_SYNC: zEvent = "xSync"; break;
- case OS_FILESIZE: zEvent = "xFilesize"; break;
- case OS_LOCK: zEvent = "xLock"; break;
- case OS_UNLOCK: zEvent = "xUnlock"; break;
- case OS_CHECKRESERVEDLOCK: zEvent = "xCheckResLock"; break;
- case OS_FILECONTROL: zEvent = "xFileControl"; break;
- case OS_SECTORSIZE: zEvent = "xSectorSize"; break;
- case OS_DEVCHAR: zEvent = "xDeviceChar"; break;
- case OS_OPEN: zEvent = "xOpen"; break;
- case OS_DELETE: zEvent = "xDelete"; break;
- case OS_ACCESS: zEvent = "xAccess"; break;
- case OS_FULLPATHNAME: zEvent = "xFullPathname"; break;
- case OS_RANDOMNESS: zEvent = "xRandomness"; break;
- case OS_SLEEP: zEvent = "xSleep"; break;
- case OS_CURRENTTIME: zEvent = "xCurrentTime"; break;
-
- case OS_SHMUNMAP: zEvent = "xShmUnmap"; break;
- case OS_SHMLOCK: zEvent = "xShmLock"; break;
- case OS_SHMBARRIER: zEvent = "xShmBarrier"; break;
- case OS_SHMMAP: zEvent = "xShmMap"; break;
-
- case OS_ANNOTATE: zEvent = "annotation"; break;
- }
-
- return zEvent;
-}
-
-typedef struct VfslogVtab VfslogVtab;
-typedef struct VfslogCsr VfslogCsr;
-
-/*
-** Virtual table type for the vfslog reader module.
-*/
-struct VfslogVtab {
- sqlite3_vtab base; /* Base class */
- sqlite3_file *pFd; /* File descriptor open on vfslog file */
- sqlite3_int64 nByte; /* Size of file in bytes */
- char *zFile; /* File name for pFd */
-};
-
-/*
-** Virtual table cursor type for the vfslog reader module.
-*/
-struct VfslogCsr {
- sqlite3_vtab_cursor base; /* Base class */
- sqlite3_int64 iRowid; /* Current rowid. */
- sqlite3_int64 iOffset; /* Offset of next record in file */
- char *zTransient; /* Transient 'file' string */
- int nFile; /* Size of array azFile[] */
- char **azFile; /* File strings */
- unsigned char aBuf[1024]; /* Current vfs log entry (read from file) */
-};
-
-static unsigned int get32bits(unsigned char *p){
- return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3];
-}
-
-/*
-** The argument must point to a buffer containing a nul-terminated string.
-** If the string begins with an SQL quote character it is overwritten by
-** the dequoted version. Otherwise the buffer is left unmodified.
-*/
-static void dequote(char *z){
- char quote; /* Quote character (if any ) */
- quote = z[0];
- if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
- int iIn = 1; /* Index of next byte to read from input */
- int iOut = 0; /* Index of next byte to write to output */
- if( quote=='[' ) quote = ']';
- while( z[iIn] ){
- if( z[iIn]==quote ){
- if( z[iIn+1]!=quote ) break;
- z[iOut++] = quote;
- iIn += 2;
- }else{
- z[iOut++] = z[iIn++];
- }
- }
- z[iOut] = '\0';
- }
-}
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*
-** Connect to or create a vfslog virtual table.
-*/
-static int vlogConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3_vfs *pVfs; /* VFS used to read log file */
- int flags; /* flags passed to pVfs->xOpen() */
- VfslogVtab *p;
- int rc;
- int nByte;
- char *zFile;
-
- *ppVtab = 0;
- pVfs = sqlite3_vfs_find(0);
- nByte = sizeof(VfslogVtab) + pVfs->szOsFile + pVfs->mxPathname;
- p = sqlite3_malloc(nByte);
- if( p==0 ) return SQLITE_NOMEM;
- memset(p, 0, nByte);
-
- p->pFd = (sqlite3_file *)&p[1];
- p->zFile = &((char *)p->pFd)[pVfs->szOsFile];
-
- zFile = sqlite3_mprintf("%s", argv[3]);
- if( !zFile ){
- sqlite3_free(p);
- return SQLITE_NOMEM;
- }
- dequote(zFile);
- pVfs->xFullPathname(pVfs, zFile, pVfs->mxPathname, p->zFile);
- sqlite3_free(zFile);
-
- flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MASTER_JOURNAL;
- rc = pVfs->xOpen(pVfs, p->zFile, p->pFd, flags, &flags);
-
- if( rc==SQLITE_OK ){
- p->pFd->pMethods->xFileSize(p->pFd, &p->nByte);
- sqlite3_declare_vtab(db,
- "CREATE TABLE xxx(event, file, click, rc, size, offset)"
- );
- *ppVtab = &p->base;
- }else{
- sqlite3_free(p);
- }
-
- return rc;
-}
-
-/*
-** There is no "best-index". This virtual table always does a linear
-** scan of the binary VFS log file.
-*/
-static int vlogBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- pIdxInfo->estimatedCost = 10.0;
- return SQLITE_OK;
-}
-
-/*
-** Disconnect from or destroy a vfslog virtual table.
-*/
-static int vlogDisconnect(sqlite3_vtab *pVtab){
- VfslogVtab *p = (VfslogVtab *)pVtab;
- if( p->pFd->pMethods ){
- p->pFd->pMethods->xClose(p->pFd);
- p->pFd->pMethods = 0;
- }
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Open a new vfslog cursor.
-*/
-static int vlogOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- VfslogCsr *pCsr; /* Newly allocated cursor object */
-
- pCsr = sqlite3_malloc(sizeof(VfslogCsr));
- if( !pCsr ) return SQLITE_NOMEM;
- memset(pCsr, 0, sizeof(VfslogCsr));
- *ppCursor = &pCsr->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a vfslog cursor.
-*/
-static int vlogClose(sqlite3_vtab_cursor *pCursor){
- VfslogCsr *p = (VfslogCsr *)pCursor;
- int i;
- for(i=0; i<p->nFile; i++){
- sqlite3_free(p->azFile[i]);
- }
- sqlite3_free(p->azFile);
- sqlite3_free(p->zTransient);
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Move a vfslog cursor to the next entry in the file.
-*/
-static int vlogNext(sqlite3_vtab_cursor *pCursor){
- VfslogCsr *pCsr = (VfslogCsr *)pCursor;
- VfslogVtab *p = (VfslogVtab *)pCursor->pVtab;
- int rc = SQLITE_OK;
- int nRead;
-
- sqlite3_free(pCsr->zTransient);
- pCsr->zTransient = 0;
-
- nRead = 24;
- if( pCsr->iOffset+nRead<=p->nByte ){
- int eEvent;
- rc = p->pFd->pMethods->xRead(p->pFd, pCsr->aBuf, nRead, pCsr->iOffset);
-
- eEvent = get32bits(pCsr->aBuf);
- if( (rc==SQLITE_OK)
- && (eEvent==OS_OPEN || eEvent==OS_DELETE || eEvent==OS_ACCESS)
- ){
- char buf[4];
- rc = p->pFd->pMethods->xRead(p->pFd, buf, 4, pCsr->iOffset+nRead);
- nRead += 4;
- if( rc==SQLITE_OK ){
- int nStr = get32bits((unsigned char *)buf);
- char *zStr = sqlite3_malloc(nStr+1);
- rc = p->pFd->pMethods->xRead(p->pFd, zStr, nStr, pCsr->iOffset+nRead);
- zStr[nStr] = '\0';
- nRead += nStr;
-
- if( eEvent==OS_OPEN ){
- int iFileid = get32bits(&pCsr->aBuf[4]);
- if( iFileid>=pCsr->nFile ){
- int nNew = sizeof(pCsr->azFile[0])*(iFileid+1);
- pCsr->azFile = (char **)sqlite3_realloc(pCsr->azFile, nNew);
- nNew -= sizeof(pCsr->azFile[0])*pCsr->nFile;
- memset(&pCsr->azFile[pCsr->nFile], 0, nNew);
- pCsr->nFile = iFileid+1;
- }
- sqlite3_free(pCsr->azFile[iFileid]);
- pCsr->azFile[iFileid] = zStr;
- }else{
- pCsr->zTransient = zStr;
- }
- }
- }
- }
-
- pCsr->iRowid += 1;
- pCsr->iOffset += nRead;
- return rc;
-}
-
-static int vlogEof(sqlite3_vtab_cursor *pCursor){
- VfslogCsr *pCsr = (VfslogCsr *)pCursor;
- VfslogVtab *p = (VfslogVtab *)pCursor->pVtab;
- return (pCsr->iOffset>=p->nByte);
-}
-
-static int vlogFilter(
- sqlite3_vtab_cursor *pCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- VfslogCsr *pCsr = (VfslogCsr *)pCursor;
- pCsr->iRowid = 0;
- pCsr->iOffset = 20;
- return vlogNext(pCursor);
-}
-
-static int vlogColumn(
- sqlite3_vtab_cursor *pCursor,
- sqlite3_context *ctx,
- int i
-){
- unsigned int val;
- VfslogCsr *pCsr = (VfslogCsr *)pCursor;
-
- assert( i<7 );
- val = get32bits(&pCsr->aBuf[4*i]);
-
- switch( i ){
- case 0: {
- sqlite3_result_text(ctx, vfslog_eventname(val), -1, SQLITE_STATIC);
- break;
- }
- case 1: {
- char *zStr = pCsr->zTransient;
- if( val!=0 && val<(unsigned)pCsr->nFile ){
- zStr = pCsr->azFile[val];
- }
- sqlite3_result_text(ctx, zStr, -1, SQLITE_TRANSIENT);
- break;
- }
- default:
- sqlite3_result_int(ctx, val);
- break;
- }
-
- return SQLITE_OK;
-}
-
-static int vlogRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
- VfslogCsr *pCsr = (VfslogCsr *)pCursor;
- *pRowid = pCsr->iRowid;
- return SQLITE_OK;
-}
-
-int sqlite3_vfslog_register(sqlite3 *db){
- static sqlite3_module vfslog_module = {
- 0, /* iVersion */
- vlogConnect, /* xCreate */
- vlogConnect, /* xConnect */
- vlogBestIndex, /* xBestIndex */
- vlogDisconnect, /* xDisconnect */
- vlogDisconnect, /* xDestroy */
- vlogOpen, /* xOpen - open a cursor */
- vlogClose, /* xClose - close a cursor */
- vlogFilter, /* xFilter - configure scan constraints */
- vlogNext, /* xNext - advance a cursor */
- vlogEof, /* xEof - check for end of scan */
- vlogColumn, /* xColumn - read data */
- vlogRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- };
-
- sqlite3_create_module(db, "vfslog", &vfslog_module, 0);
- return SQLITE_OK;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/**************************************************************************
-***************************************************************************
-** Tcl interface starts here.
-*/
-
-#if defined(SQLITE_TEST) || defined(TCLSH)
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-static int SQLITE_TCLAPI test_vfslog(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- struct SqliteDb { sqlite3 *db; };
- sqlite3 *db;
- Tcl_CmdInfo cmdInfo;
- int rc = SQLITE_ERROR;
-
- static const char *strs[] = { "annotate", "finalize", "new", "register", 0 };
- enum VL_enum { VL_ANNOTATE, VL_FINALIZE, VL_NEW, VL_REGISTER };
- int iSub;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
- return TCL_ERROR;
- }
- if( Tcl_GetIndexFromObj(interp, objv[1], strs, "sub-command", 0, &iSub) ){
- return TCL_ERROR;
- }
-
- switch( (enum VL_enum)iSub ){
- case VL_ANNOTATE: {
- char *zVfs;
- char *zMsg;
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 3, objv, "VFS");
- return TCL_ERROR;
- }
- zVfs = Tcl_GetString(objv[2]);
- zMsg = Tcl_GetString(objv[3]);
- rc = sqlite3_vfslog_annotate(zVfs, zMsg);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "failed", 0);
- return TCL_ERROR;
- }
- break;
- }
- case VL_FINALIZE: {
- char *zVfs;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "VFS");
- return TCL_ERROR;
- }
- zVfs = Tcl_GetString(objv[2]);
- rc = sqlite3_vfslog_finalize(zVfs);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "failed", 0);
- return TCL_ERROR;
- }
- break;
- };
-
- case VL_NEW: {
- char *zVfs;
- char *zParent;
- char *zLog;
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 2, objv, "VFS PARENT LOGFILE");
- return TCL_ERROR;
- }
- zVfs = Tcl_GetString(objv[2]);
- zParent = Tcl_GetString(objv[3]);
- zLog = Tcl_GetString(objv[4]);
- if( *zParent=='\0' ) zParent = 0;
- rc = sqlite3_vfslog_new(zVfs, zParent, zLog);
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "failed", 0);
- return TCL_ERROR;
- }
- break;
- };
-
- case VL_REGISTER: {
- char *zDb;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "DB");
- return TCL_ERROR;
- }
-#ifdef SQLITE_OMIT_VIRTUALTABLE
- Tcl_AppendResult(interp, "vfslog not available because of "
- "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
- return TCL_ERROR;
-#else
- zDb = Tcl_GetString(objv[2]);
- if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
- db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
- rc = sqlite3_vfslog_register(db);
- }
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "bad sqlite3 handle: ", zDb, (void*)0);
- return TCL_ERROR;
- }
- break;
-#endif
- }
- }
-
- return TCL_OK;
-}
-
-int SqlitetestOsinst_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "vfslog", test_vfslog, 0, 0);
- return TCL_OK;
-}
-
-#endif /* SQLITE_TEST */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_pcache.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_pcache.c
deleted file mode 100644
index 8fcfe7e26e3..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_pcache.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
-** 2008 November 18
-**
-** 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 contains code used for testing the SQLite system.
-** None of the code in this file goes into a deliverable build.
-**
-** This file contains an application-defined pager cache
-** implementation that can be plugged in in place of the
-** default pcache. This alternative pager cache will throw
-** some errors that the default cache does not.
-**
-** This pagecache implementation is designed for simplicity
-** not speed.
-*/
-#include "sqlite3.h"
-#include <string.h>
-#include <assert.h>
-
-/*
-** Global data used by this test implementation. There is no
-** mutexing, which means this page cache will not work in a
-** multi-threaded test.
-*/
-typedef struct testpcacheGlobalType testpcacheGlobalType;
-struct testpcacheGlobalType {
- void *pDummy; /* Dummy allocation to simulate failures */
- int nInstance; /* Number of current instances */
- unsigned discardChance; /* Chance of discarding on an unpin (0-100) */
- unsigned prngSeed; /* Seed for the PRNG */
- unsigned highStress; /* Call xStress agressively */
-};
-static testpcacheGlobalType testpcacheGlobal;
-
-/*
-** Initializer.
-**
-** Verify that the initializer is only called when the system is
-** uninitialized. Allocate some memory and report SQLITE_NOMEM if
-** the allocation fails. This provides a means to test the recovery
-** from a failed initialization attempt. It also verifies that the
-** the destructor always gets call - otherwise there would be a
-** memory leak.
-*/
-static int testpcacheInit(void *pArg){
- assert( pArg==(void*)&testpcacheGlobal );
- assert( testpcacheGlobal.pDummy==0 );
- assert( testpcacheGlobal.nInstance==0 );
- testpcacheGlobal.pDummy = sqlite3_malloc(10);
- return testpcacheGlobal.pDummy==0 ? SQLITE_NOMEM : SQLITE_OK;
-}
-
-/*
-** Destructor
-**
-** Verify that this is only called after initialization.
-** Free the memory allocated by the initializer.
-*/
-static void testpcacheShutdown(void *pArg){
- assert( pArg==(void*)&testpcacheGlobal );
- assert( testpcacheGlobal.pDummy!=0 );
- assert( testpcacheGlobal.nInstance==0 );
- sqlite3_free( testpcacheGlobal.pDummy );
- testpcacheGlobal.pDummy = 0;
-}
-
-/*
-** Number of pages in a cache.
-**
-** The number of pages is a hard upper bound in this test module.
-** If more pages are requested, sqlite3PcacheFetch() returns NULL.
-**
-** If testing with in-memory temp tables, provide a larger pcache.
-** Some of the test cases need this.
-*/
-#if defined(SQLITE_TEMP_STORE) && SQLITE_TEMP_STORE>=2
-# define TESTPCACHE_NPAGE 499
-#else
-# define TESTPCACHE_NPAGE 217
-#endif
-#define TESTPCACHE_RESERVE 17
-
-/*
-** Magic numbers used to determine validity of the page cache.
-*/
-#define TESTPCACHE_VALID 0x364585fd
-#define TESTPCACHE_CLEAR 0xd42670d4
-
-/*
-** Private implementation of a page cache.
-*/
-typedef struct testpcache testpcache;
-struct testpcache {
- int szPage; /* Size of each page. Multiple of 8. */
- int szExtra; /* Size of extra data that accompanies each page */
- int bPurgeable; /* True if the page cache is purgeable */
- int nFree; /* Number of unused slots in a[] */
- int nPinned; /* Number of pinned slots in a[] */
- unsigned iRand; /* State of the PRNG */
- unsigned iMagic; /* Magic number for sanity checking */
- struct testpcachePage {
- sqlite3_pcache_page page; /* Base class */
- unsigned key; /* The key for this page. 0 means unallocated */
- int isPinned; /* True if the page is pinned */
- } a[TESTPCACHE_NPAGE]; /* All pages in the cache */
-};
-
-/*
-** Get a random number using the PRNG in the given page cache.
-*/
-static unsigned testpcacheRandom(testpcache *p){
- unsigned x = 0;
- int i;
- for(i=0; i<4; i++){
- p->iRand = (p->iRand*69069 + 5);
- x = (x<<8) | ((p->iRand>>16)&0xff);
- }
- return x;
-}
-
-
-/*
-** Allocate a new page cache instance.
-*/
-static sqlite3_pcache *testpcacheCreate(
- int szPage,
- int szExtra,
- int bPurgeable
-){
- int nMem;
- char *x;
- testpcache *p;
- int i;
- assert( testpcacheGlobal.pDummy!=0 );
- szPage = (szPage+7)&~7;
- nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*(szPage+szExtra);
- p = sqlite3_malloc( nMem );
- if( p==0 ) return 0;
- x = (char*)&p[1];
- p->szPage = szPage;
- p->szExtra = szExtra;
- p->nFree = TESTPCACHE_NPAGE;
- p->nPinned = 0;
- p->iRand = testpcacheGlobal.prngSeed;
- p->bPurgeable = bPurgeable;
- p->iMagic = TESTPCACHE_VALID;
- for(i=0; i<TESTPCACHE_NPAGE; i++, x += (szPage+szExtra)){
- p->a[i].key = 0;
- p->a[i].isPinned = 0;
- p->a[i].page.pBuf = (void*)x;
- p->a[i].page.pExtra = (void*)&x[szPage];
- }
- testpcacheGlobal.nInstance++;
- return (sqlite3_pcache*)p;
-}
-
-/*
-** Set the cache size
-*/
-static void testpcacheCachesize(sqlite3_pcache *pCache, int newSize){
- testpcache *p = (testpcache*)pCache;
- assert( p->iMagic==TESTPCACHE_VALID );
- assert( testpcacheGlobal.pDummy!=0 );
- assert( testpcacheGlobal.nInstance>0 );
-}
-
-/*
-** Return the number of pages in the cache that are being used.
-** This includes both pinned and unpinned pages.
-*/
-static int testpcachePagecount(sqlite3_pcache *pCache){
- testpcache *p = (testpcache*)pCache;
- assert( p->iMagic==TESTPCACHE_VALID );
- assert( testpcacheGlobal.pDummy!=0 );
- assert( testpcacheGlobal.nInstance>0 );
- return TESTPCACHE_NPAGE - p->nFree;
-}
-
-/*
-** Fetch a page.
-*/
-static sqlite3_pcache_page *testpcacheFetch(
- sqlite3_pcache *pCache,
- unsigned key,
- int createFlag
-){
- testpcache *p = (testpcache*)pCache;
- int i, j;
- assert( p->iMagic==TESTPCACHE_VALID );
- assert( testpcacheGlobal.pDummy!=0 );
- assert( testpcacheGlobal.nInstance>0 );
-
- /* See if the page is already in cache. Return immediately if it is */
- for(i=0; i<TESTPCACHE_NPAGE; i++){
- if( p->a[i].key==key ){
- if( !p->a[i].isPinned ){
- p->nPinned++;
- assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
- p->a[i].isPinned = 1;
- }
- return &p->a[i].page;
- }
- }
-
- /* If createFlag is 0, never allocate a new page */
- if( createFlag==0 ){
- return 0;
- }
-
- /* If no pages are available, always fail */
- if( p->nPinned==TESTPCACHE_NPAGE ){
- return 0;
- }
-
- /* Do not allocate the last TESTPCACHE_RESERVE pages unless createFlag is 2 */
- if( p->nPinned>=TESTPCACHE_NPAGE-TESTPCACHE_RESERVE && createFlag<2 ){
- return 0;
- }
-
- /* Do not allocate if highStress is enabled and createFlag is not 2.
- **
- ** The highStress setting causes pagerStress() to be called much more
- ** often, which exercises the pager logic more intensely.
- */
- if( testpcacheGlobal.highStress && createFlag<2 ){
- return 0;
- }
-
- /* Find a free page to allocate if there are any free pages.
- ** Withhold TESTPCACHE_RESERVE free pages until createFlag is 2.
- */
- if( p->nFree>TESTPCACHE_RESERVE || (createFlag==2 && p->nFree>0) ){
- j = testpcacheRandom(p) % TESTPCACHE_NPAGE;
- for(i=0; i<TESTPCACHE_NPAGE; i++, j = (j+1)%TESTPCACHE_NPAGE){
- if( p->a[j].key==0 ){
- p->a[j].key = key;
- p->a[j].isPinned = 1;
- memset(p->a[j].page.pBuf, 0, p->szPage);
- memset(p->a[j].page.pExtra, 0, p->szExtra);
- p->nPinned++;
- p->nFree--;
- assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
- return &p->a[j].page;
- }
- }
-
- /* The prior loop always finds a freepage to allocate */
- assert( 0 );
- }
-
- /* If this cache is not purgeable then we have to fail.
- */
- if( p->bPurgeable==0 ){
- return 0;
- }
-
- /* If there are no free pages, recycle a page. The page to
- ** recycle is selected at random from all unpinned pages.
- */
- j = testpcacheRandom(p) % TESTPCACHE_NPAGE;
- for(i=0; i<TESTPCACHE_NPAGE; i++, j = (j+1)%TESTPCACHE_NPAGE){
- if( p->a[j].key>0 && p->a[j].isPinned==0 ){
- p->a[j].key = key;
- p->a[j].isPinned = 1;
- memset(p->a[j].page.pBuf, 0, p->szPage);
- memset(p->a[j].page.pExtra, 0, p->szExtra);
- p->nPinned++;
- assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
- return &p->a[j].page;
- }
- }
-
- /* The previous loop always finds a page to recycle. */
- assert(0);
- return 0;
-}
-
-/*
-** Unpin a page.
-*/
-static void testpcacheUnpin(
- sqlite3_pcache *pCache,
- sqlite3_pcache_page *pOldPage,
- int discard
-){
- testpcache *p = (testpcache*)pCache;
- int i;
- assert( p->iMagic==TESTPCACHE_VALID );
- assert( testpcacheGlobal.pDummy!=0 );
- assert( testpcacheGlobal.nInstance>0 );
-
- /* Randomly discard pages as they are unpinned according to the
- ** discardChance setting. If discardChance is 0, the random discard
- ** never happens. If discardChance is 100, it always happens.
- */
- if( p->bPurgeable
- && (100-testpcacheGlobal.discardChance) <= (testpcacheRandom(p)%100)
- ){
- discard = 1;
- }
-
- for(i=0; i<TESTPCACHE_NPAGE; i++){
- if( &p->a[i].page==pOldPage ){
- /* The pOldPage pointer always points to a pinned page */
- assert( p->a[i].isPinned );
- p->a[i].isPinned = 0;
- p->nPinned--;
- assert( p->nPinned>=0 );
- if( discard ){
- p->a[i].key = 0;
- p->nFree++;
- assert( p->nFree<=TESTPCACHE_NPAGE );
- }
- return;
- }
- }
-
- /* The pOldPage pointer always points to a valid page */
- assert( 0 );
-}
-
-
-/*
-** Rekey a single page.
-*/
-static void testpcacheRekey(
- sqlite3_pcache *pCache,
- sqlite3_pcache_page *pOldPage,
- unsigned oldKey,
- unsigned newKey
-){
- testpcache *p = (testpcache*)pCache;
- int i;
- assert( p->iMagic==TESTPCACHE_VALID );
- assert( testpcacheGlobal.pDummy!=0 );
- assert( testpcacheGlobal.nInstance>0 );
-
- /* If there already exists another page at newKey, verify that
- ** the other page is unpinned and discard it.
- */
- for(i=0; i<TESTPCACHE_NPAGE; i++){
- if( p->a[i].key==newKey ){
- /* The new key is never a page that is already pinned */
- assert( p->a[i].isPinned==0 );
- p->a[i].key = 0;
- p->nFree++;
- assert( p->nFree<=TESTPCACHE_NPAGE );
- break;
- }
- }
-
- /* Find the page to be rekeyed and rekey it.
- */
- for(i=0; i<TESTPCACHE_NPAGE; i++){
- if( p->a[i].key==oldKey ){
- /* The oldKey and pOldPage parameters match */
- assert( &p->a[i].page==pOldPage );
- /* Page to be rekeyed must be pinned */
- assert( p->a[i].isPinned );
- p->a[i].key = newKey;
- return;
- }
- }
-
- /* Rekey is always given a valid page to work with */
- assert( 0 );
-}
-
-
-/*
-** Truncate the page cache. Every page with a key of iLimit or larger
-** is discarded.
-*/
-static void testpcacheTruncate(sqlite3_pcache *pCache, unsigned iLimit){
- testpcache *p = (testpcache*)pCache;
- unsigned int i;
- assert( p->iMagic==TESTPCACHE_VALID );
- assert( testpcacheGlobal.pDummy!=0 );
- assert( testpcacheGlobal.nInstance>0 );
- for(i=0; i<TESTPCACHE_NPAGE; i++){
- if( p->a[i].key>=iLimit ){
- p->a[i].key = 0;
- if( p->a[i].isPinned ){
- p->nPinned--;
- assert( p->nPinned>=0 );
- }
- p->nFree++;
- assert( p->nFree<=TESTPCACHE_NPAGE );
- }
- }
-}
-
-/*
-** Destroy a page cache.
-*/
-static void testpcacheDestroy(sqlite3_pcache *pCache){
- testpcache *p = (testpcache*)pCache;
- assert( p->iMagic==TESTPCACHE_VALID );
- assert( testpcacheGlobal.pDummy!=0 );
- assert( testpcacheGlobal.nInstance>0 );
- p->iMagic = TESTPCACHE_CLEAR;
- sqlite3_free(p);
- testpcacheGlobal.nInstance--;
-}
-
-
-/*
-** Invoke this routine to register or unregister the testing pager cache
-** implemented by this file.
-**
-** Install the test pager cache if installFlag is 1 and uninstall it if
-** installFlag is 0.
-**
-** When installing, discardChance is a number between 0 and 100 that
-** indicates the probability of discarding a page when unpinning the
-** page. 0 means never discard (unless the discard flag is set).
-** 100 means always discard.
-*/
-void installTestPCache(
- int installFlag, /* True to install. False to uninstall. */
- unsigned discardChance, /* 0-100. Chance to discard on unpin */
- unsigned prngSeed, /* Seed for the PRNG */
- unsigned highStress /* Call xStress agressively */
-){
- static const sqlite3_pcache_methods2 testPcache = {
- 1,
- (void*)&testpcacheGlobal,
- testpcacheInit,
- testpcacheShutdown,
- testpcacheCreate,
- testpcacheCachesize,
- testpcachePagecount,
- testpcacheFetch,
- testpcacheUnpin,
- testpcacheRekey,
- testpcacheTruncate,
- testpcacheDestroy,
- };
- static sqlite3_pcache_methods2 defaultPcache;
- static int isInstalled = 0;
-
- assert( testpcacheGlobal.nInstance==0 );
- assert( testpcacheGlobal.pDummy==0 );
- assert( discardChance<=100 );
- testpcacheGlobal.discardChance = discardChance;
- testpcacheGlobal.prngSeed = prngSeed ^ (prngSeed<<16);
- testpcacheGlobal.highStress = highStress;
- if( installFlag!=isInstalled ){
- if( installFlag ){
- sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &defaultPcache);
- assert( defaultPcache.xCreate!=testpcacheCreate );
- sqlite3_config(SQLITE_CONFIG_PCACHE2, &testPcache);
- }else{
- assert( defaultPcache.xCreate!=0 );
- sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultPcache);
- }
- isInstalled = installFlag;
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_quota.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_quota.c
deleted file mode 100644
index e87e9772f6c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_quota.c
+++ /dev/null
@@ -1,1979 +0,0 @@
-/*
-** 2010 September 31
-**
-** 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 contains a VFS "shim" - a layer that sits in between the
-** pager and the real VFS.
-**
-** This particular shim enforces a quota system on files. One or more
-** database files are in a "quota group" that is defined by a GLOB
-** pattern. A quota is set for the combined size of all files in the
-** the group. A quota of zero means "no limit". If the total size
-** of all files in the quota group is greater than the limit, then
-** write requests that attempt to enlarge a file fail with SQLITE_FULL.
-**
-** However, before returning SQLITE_FULL, the write requests invoke
-** a callback function that is configurable for each quota group.
-** This callback has the opportunity to enlarge the quota. If the
-** callback does enlarge the quota such that the total size of all
-** files within the group is less than the new quota, then the write
-** continues as if nothing had happened.
-*/
-#include "test_quota.h"
-#include <string.h>
-#include <assert.h>
-
-/*
-** For an build without mutexes, no-op the mutex calls.
-*/
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
-#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
-#define sqlite3_mutex_free(X)
-#define sqlite3_mutex_enter(X)
-#define sqlite3_mutex_try(X) SQLITE_OK
-#define sqlite3_mutex_leave(X)
-#define sqlite3_mutex_held(X) ((void)(X),1)
-#define sqlite3_mutex_notheld(X) ((void)(X),1)
-#endif /* SQLITE_THREADSAFE==0 */
-
-#include "os_setup.h"
-
-#if SQLITE_OS_UNIX
-# include <unistd.h>
-#endif
-#if SQLITE_OS_WIN
-# include "os_win.h"
-# include <io.h>
-#endif
-
-
-/************************ Object Definitions ******************************/
-
-/* Forward declaration of all object types */
-typedef struct quotaGroup quotaGroup;
-typedef struct quotaConn quotaConn;
-typedef struct quotaFile quotaFile;
-
-/*
-** A "quota group" is a collection of files whose collective size we want
-** to limit. Each quota group is defined by a GLOB pattern.
-**
-** There is an instance of the following object for each defined quota
-** group. This object records the GLOB pattern that defines which files
-** belong to the quota group. The object also remembers the size limit
-** for the group (the quota) and the callback to be invoked when the
-** sum of the sizes of the files within the group goes over the limit.
-**
-** A quota group must be established (using sqlite3_quota_set(...))
-** prior to opening any of the database connections that access files
-** within the quota group.
-*/
-struct quotaGroup {
- const char *zPattern; /* Filename pattern to be quotaed */
- sqlite3_int64 iLimit; /* Upper bound on total file size */
- sqlite3_int64 iSize; /* Current size of all files */
- void (*xCallback)( /* Callback invoked when going over quota */
- const char *zFilename, /* Name of file whose size increases */
- sqlite3_int64 *piLimit, /* IN/OUT: The current limit */
- sqlite3_int64 iSize, /* Total size of all files in the group */
- void *pArg /* Client data */
- );
- void *pArg; /* Third argument to the xCallback() */
- void (*xDestroy)(void*); /* Optional destructor for pArg */
- quotaGroup *pNext, **ppPrev; /* Doubly linked list of all quota objects */
- quotaFile *pFiles; /* Files within this group */
-};
-
-/*
-** An instance of this structure represents a single file that is part
-** of a quota group. A single file can be opened multiple times. In
-** order keep multiple openings of the same file from causing the size
-** of the file to count against the quota multiple times, each file
-** has a unique instance of this object and multiple open connections
-** to the same file each point to a single instance of this object.
-*/
-struct quotaFile {
- char *zFilename; /* Name of this file */
- quotaGroup *pGroup; /* Quota group to which this file belongs */
- sqlite3_int64 iSize; /* Current size of this file */
- int nRef; /* Number of times this file is open */
- int deleteOnClose; /* True to delete this file when it closes */
- quotaFile *pNext, **ppPrev; /* Linked list of files in the same group */
-};
-
-/*
-** An instance of the following object represents each open connection
-** to a file that participates in quota tracking. This object is a
-** subclass of sqlite3_file. The sqlite3_file object for the underlying
-** VFS is appended to this structure.
-*/
-struct quotaConn {
- sqlite3_file base; /* Base class - must be first */
- quotaFile *pFile; /* The underlying file */
- /* The underlying VFS sqlite3_file is appended to this object */
-};
-
-/*
-** An instance of the following object records the state of an
-** open file. This object is opaque to all users - the internal
-** structure is only visible to the functions below.
-*/
-struct quota_FILE {
- FILE *f; /* Open stdio file pointer */
- sqlite3_int64 iOfst; /* Current offset into the file */
- quotaFile *pFile; /* The file record in the quota system */
-#if SQLITE_OS_WIN
- char *zMbcsName; /* Full MBCS pathname of the file */
-#endif
-};
-
-
-/************************* Global Variables **********************************/
-/*
-** All global variables used by this file are containing within the following
-** gQuota structure.
-*/
-static struct {
- /* The pOrigVfs is the real, original underlying VFS implementation.
- ** Most operations pass-through to the real VFS. This value is read-only
- ** during operation. It is only modified at start-time and thus does not
- ** require a mutex.
- */
- sqlite3_vfs *pOrigVfs;
-
- /* The sThisVfs is the VFS structure used by this shim. It is initialized
- ** at start-time and thus does not require a mutex
- */
- sqlite3_vfs sThisVfs;
-
- /* The sIoMethods defines the methods used by sqlite3_file objects
- ** associated with this shim. It is initialized at start-time and does
- ** not require a mutex.
- **
- ** When the underlying VFS is called to open a file, it might return
- ** either a version 1 or a version 2 sqlite3_file object. This shim
- ** has to create a wrapper sqlite3_file of the same version. Hence
- ** there are two I/O method structures, one for version 1 and the other
- ** for version 2.
- */
- sqlite3_io_methods sIoMethodsV1;
- sqlite3_io_methods sIoMethodsV2;
-
- /* True when this shim as been initialized.
- */
- int isInitialized;
-
- /* For run-time access any of the other global data structures in this
- ** shim, the following mutex must be held.
- */
- sqlite3_mutex *pMutex;
-
- /* List of quotaGroup objects.
- */
- quotaGroup *pGroup;
-
-} gQuota;
-
-/************************* Utility Routines *********************************/
-/*
-** Acquire and release the mutex used to serialize access to the
-** list of quotaGroups.
-*/
-static void quotaEnter(void){ sqlite3_mutex_enter(gQuota.pMutex); }
-static void quotaLeave(void){ sqlite3_mutex_leave(gQuota.pMutex); }
-
-/* Count the number of open files in a quotaGroup
-*/
-static int quotaGroupOpenFileCount(quotaGroup *pGroup){
- int N = 0;
- quotaFile *pFile = pGroup->pFiles;
- while( pFile ){
- if( pFile->nRef ) N++;
- pFile = pFile->pNext;
- }
- return N;
-}
-
-/* Remove a file from a quota group.
-*/
-static void quotaRemoveFile(quotaFile *pFile){
- quotaGroup *pGroup = pFile->pGroup;
- pGroup->iSize -= pFile->iSize;
- *pFile->ppPrev = pFile->pNext;
- if( pFile->pNext ) pFile->pNext->ppPrev = pFile->ppPrev;
- sqlite3_free(pFile);
-}
-
-/* Remove all files from a quota group. It is always the case that
-** all files will be closed when this routine is called.
-*/
-static void quotaRemoveAllFiles(quotaGroup *pGroup){
- while( pGroup->pFiles ){
- assert( pGroup->pFiles->nRef==0 );
- quotaRemoveFile(pGroup->pFiles);
- }
-}
-
-
-/* If the reference count and threshold for a quotaGroup are both
-** zero, then destroy the quotaGroup.
-*/
-static void quotaGroupDeref(quotaGroup *pGroup){
- if( pGroup->iLimit==0 && quotaGroupOpenFileCount(pGroup)==0 ){
- quotaRemoveAllFiles(pGroup);
- *pGroup->ppPrev = pGroup->pNext;
- if( pGroup->pNext ) pGroup->pNext->ppPrev = pGroup->ppPrev;
- if( pGroup->xDestroy ) pGroup->xDestroy(pGroup->pArg);
- sqlite3_free(pGroup);
- }
-}
-
-/*
-** Return TRUE if string z matches glob pattern zGlob.
-**
-** Globbing rules:
-**
-** '*' Matches any sequence of zero or more characters.
-**
-** '?' Matches exactly one character.
-**
-** [...] Matches one character from the enclosed list of
-** characters.
-**
-** [^...] Matches one character not in the enclosed list.
-**
-** / Matches "/" or "\\"
-**
-*/
-static int quotaStrglob(const char *zGlob, const char *z){
- int c, c2, cx;
- int invert;
- int seen;
-
- while( (c = (*(zGlob++)))!=0 ){
- if( c=='*' ){
- while( (c=(*(zGlob++))) == '*' || c=='?' ){
- if( c=='?' && (*(z++))==0 ) return 0;
- }
- if( c==0 ){
- return 1;
- }else if( c=='[' ){
- while( *z && quotaStrglob(zGlob-1,z)==0 ){
- z++;
- }
- return (*z)!=0;
- }
- cx = (c=='/') ? '\\' : c;
- while( (c2 = (*(z++)))!=0 ){
- while( c2!=c && c2!=cx ){
- c2 = *(z++);
- if( c2==0 ) return 0;
- }
- if( quotaStrglob(zGlob,z) ) return 1;
- }
- return 0;
- }else if( c=='?' ){
- if( (*(z++))==0 ) return 0;
- }else if( c=='[' ){
- int prior_c = 0;
- seen = 0;
- invert = 0;
- c = *(z++);
- if( c==0 ) return 0;
- c2 = *(zGlob++);
- if( c2=='^' ){
- invert = 1;
- c2 = *(zGlob++);
- }
- if( c2==']' ){
- if( c==']' ) seen = 1;
- c2 = *(zGlob++);
- }
- while( c2 && c2!=']' ){
- if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
- c2 = *(zGlob++);
- if( c>=prior_c && c<=c2 ) seen = 1;
- prior_c = 0;
- }else{
- if( c==c2 ){
- seen = 1;
- }
- prior_c = c2;
- }
- c2 = *(zGlob++);
- }
- if( c2==0 || (seen ^ invert)==0 ) return 0;
- }else if( c=='/' ){
- if( z[0]!='/' && z[0]!='\\' ) return 0;
- z++;
- }else{
- if( c!=(*(z++)) ) return 0;
- }
- }
- return *z==0;
-}
-
-
-/* Find a quotaGroup given the filename.
-**
-** Return a pointer to the quotaGroup object. Return NULL if not found.
-*/
-static quotaGroup *quotaGroupFind(const char *zFilename){
- quotaGroup *p;
- for(p=gQuota.pGroup; p && quotaStrglob(p->zPattern, zFilename)==0;
- p=p->pNext){}
- return p;
-}
-
-/* Translate an sqlite3_file* that is really a quotaConn* into
-** the sqlite3_file* for the underlying original VFS.
-*/
-static sqlite3_file *quotaSubOpen(sqlite3_file *pConn){
- quotaConn *p = (quotaConn*)pConn;
- return (sqlite3_file*)&p[1];
-}
-
-/* Find a file in a quota group and return a pointer to that file.
-** Return NULL if the file is not in the group.
-*/
-static quotaFile *quotaFindFile(
- quotaGroup *pGroup, /* Group in which to look for the file */
- const char *zName, /* Full pathname of the file */
- int createFlag /* Try to create the file if not found */
-){
- quotaFile *pFile = pGroup->pFiles;
- while( pFile && strcmp(pFile->zFilename, zName)!=0 ){
- pFile = pFile->pNext;
- }
- if( pFile==0 && createFlag ){
- int nName = (int)(strlen(zName) & 0x3fffffff);
- pFile = (quotaFile *)sqlite3_malloc( sizeof(*pFile) + nName + 1 );
- if( pFile ){
- memset(pFile, 0, sizeof(*pFile));
- pFile->zFilename = (char*)&pFile[1];
- memcpy(pFile->zFilename, zName, nName+1);
- pFile->pNext = pGroup->pFiles;
- if( pGroup->pFiles ) pGroup->pFiles->ppPrev = &pFile->pNext;
- pFile->ppPrev = &pGroup->pFiles;
- pGroup->pFiles = pFile;
- pFile->pGroup = pGroup;
- }
- }
- return pFile;
-}
-/*
-** Translate UTF8 to MBCS for use in fopen() calls. Return a pointer to the
-** translated text.. Call quota_mbcs_free() to deallocate any memory
-** used to store the returned pointer when done.
-*/
-static char *quota_utf8_to_mbcs(const char *zUtf8){
-#if SQLITE_OS_WIN
- size_t n; /* Bytes in zUtf8 */
- int nWide; /* number of UTF-16 characters */
- int nMbcs; /* Bytes of MBCS */
- LPWSTR zTmpWide; /* The UTF16 text */
- char *zMbcs; /* The MBCS text */
- int codepage; /* Code page used by fopen() */
-
- n = strlen(zUtf8);
- nWide = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, NULL, 0);
- if( nWide==0 ) return 0;
- zTmpWide = (LPWSTR)sqlite3_malloc( (nWide+1)*sizeof(zTmpWide[0]) );
- if( zTmpWide==0 ) return 0;
- MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zTmpWide, nWide);
- codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
- nMbcs = WideCharToMultiByte(codepage, 0, zTmpWide, nWide, 0, 0, 0, 0);
- zMbcs = nMbcs ? (char*)sqlite3_malloc( nMbcs+1 ) : 0;
- if( zMbcs ){
- WideCharToMultiByte(codepage, 0, zTmpWide, nWide, zMbcs, nMbcs, 0, 0);
- }
- sqlite3_free(zTmpWide);
- return zMbcs;
-#else
- return (char*)zUtf8; /* No-op on unix */
-#endif
-}
-
-/*
-** Deallocate any memory allocated by quota_utf8_to_mbcs().
-*/
-static void quota_mbcs_free(char *zOld){
-#if SQLITE_OS_WIN
- sqlite3_free(zOld);
-#else
- /* No-op on unix */
-#endif
-}
-
-/************************* VFS Method Wrappers *****************************/
-/*
-** This is the xOpen method used for the "quota" VFS.
-**
-** Most of the work is done by the underlying original VFS. This method
-** simply links the new file into the appropriate quota group if it is a
-** file that needs to be tracked.
-*/
-static int quotaOpen(
- sqlite3_vfs *pVfs, /* The quota VFS */
- const char *zName, /* Name of file to be opened */
- sqlite3_file *pConn, /* Fill in this file descriptor */
- int flags, /* Flags to control the opening */
- int *pOutFlags /* Flags showing results of opening */
-){
- int rc; /* Result code */
- quotaConn *pQuotaOpen; /* The new quota file descriptor */
- quotaFile *pFile; /* Corresponding quotaFile obj */
- quotaGroup *pGroup; /* The group file belongs to */
- sqlite3_file *pSubOpen; /* Real file descriptor */
- sqlite3_vfs *pOrigVfs = gQuota.pOrigVfs; /* Real VFS */
-
- /* If the file is not a main database file or a WAL, then use the
- ** normal xOpen method.
- */
- if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_WAL))==0 ){
- return pOrigVfs->xOpen(pOrigVfs, zName, pConn, flags, pOutFlags);
- }
-
- /* If the name of the file does not match any quota group, then
- ** use the normal xOpen method.
- */
- quotaEnter();
- pGroup = quotaGroupFind(zName);
- if( pGroup==0 ){
- rc = pOrigVfs->xOpen(pOrigVfs, zName, pConn, flags, pOutFlags);
- }else{
- /* If we get to this point, it means the file needs to be quota tracked.
- */
- pQuotaOpen = (quotaConn*)pConn;
- pSubOpen = quotaSubOpen(pConn);
- rc = pOrigVfs->xOpen(pOrigVfs, zName, pSubOpen, flags, pOutFlags);
- if( rc==SQLITE_OK ){
- pFile = quotaFindFile(pGroup, zName, 1);
- if( pFile==0 ){
- quotaLeave();
- pSubOpen->pMethods->xClose(pSubOpen);
- return SQLITE_NOMEM;
- }
- pFile->deleteOnClose = (flags & SQLITE_OPEN_DELETEONCLOSE)!=0;
- pFile->nRef++;
- pQuotaOpen->pFile = pFile;
- if( pSubOpen->pMethods->iVersion==1 ){
- pQuotaOpen->base.pMethods = &gQuota.sIoMethodsV1;
- }else{
- pQuotaOpen->base.pMethods = &gQuota.sIoMethodsV2;
- }
- }
- }
- quotaLeave();
- return rc;
-}
-
-/*
-** This is the xDelete method used for the "quota" VFS.
-**
-** If the file being deleted is part of the quota group, then reduce
-** the size of the quota group accordingly. And remove the file from
-** the set of files in the quota group.
-*/
-static int quotaDelete(
- sqlite3_vfs *pVfs, /* The quota VFS */
- const char *zName, /* Name of file to be deleted */
- int syncDir /* Do a directory sync after deleting */
-){
- int rc; /* Result code */
- quotaFile *pFile; /* Files in the quota */
- quotaGroup *pGroup; /* The group file belongs to */
- sqlite3_vfs *pOrigVfs = gQuota.pOrigVfs; /* Real VFS */
-
- /* Do the actual file delete */
- rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
-
- /* If the file just deleted is a member of a quota group, then remove
- ** it from that quota group.
- */
- if( rc==SQLITE_OK ){
- quotaEnter();
- pGroup = quotaGroupFind(zName);
- if( pGroup ){
- pFile = quotaFindFile(pGroup, zName, 0);
- if( pFile ){
- if( pFile->nRef ){
- pFile->deleteOnClose = 1;
- }else{
- quotaRemoveFile(pFile);
- quotaGroupDeref(pGroup);
- }
- }
- }
- quotaLeave();
- }
- return rc;
-}
-
-
-/************************ I/O Method Wrappers *******************************/
-
-/* xClose requests get passed through to the original VFS. But we
-** also have to unlink the quotaConn from the quotaFile and quotaGroup.
-** The quotaFile and/or quotaGroup are freed if they are no longer in use.
-*/
-static int quotaClose(sqlite3_file *pConn){
- quotaConn *p = (quotaConn*)pConn;
- quotaFile *pFile = p->pFile;
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- int rc;
- rc = pSubOpen->pMethods->xClose(pSubOpen);
- quotaEnter();
- pFile->nRef--;
- if( pFile->nRef==0 ){
- quotaGroup *pGroup = pFile->pGroup;
- if( pFile->deleteOnClose ){
- gQuota.pOrigVfs->xDelete(gQuota.pOrigVfs, pFile->zFilename, 0);
- quotaRemoveFile(pFile);
- }
- quotaGroupDeref(pGroup);
- }
- quotaLeave();
- return rc;
-}
-
-/* Pass xRead requests directory thru to the original VFS without
-** further processing.
-*/
-static int quotaRead(
- sqlite3_file *pConn,
- void *pBuf,
- int iAmt,
- sqlite3_int64 iOfst
-){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst);
-}
-
-/* Check xWrite requests to see if they expand the file. If they do,
-** the perform a quota check before passing them through to the
-** original VFS.
-*/
-static int quotaWrite(
- sqlite3_file *pConn,
- const void *pBuf,
- int iAmt,
- sqlite3_int64 iOfst
-){
- quotaConn *p = (quotaConn*)pConn;
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- sqlite3_int64 iEnd = iOfst+iAmt;
- quotaGroup *pGroup;
- quotaFile *pFile = p->pFile;
- sqlite3_int64 szNew;
-
- if( pFile->iSize<iEnd ){
- pGroup = pFile->pGroup;
- quotaEnter();
- szNew = pGroup->iSize - pFile->iSize + iEnd;
- if( szNew>pGroup->iLimit && pGroup->iLimit>0 ){
- if( pGroup->xCallback ){
- pGroup->xCallback(pFile->zFilename, &pGroup->iLimit, szNew,
- pGroup->pArg);
- }
- if( szNew>pGroup->iLimit && pGroup->iLimit>0 ){
- quotaLeave();
- return SQLITE_FULL;
- }
- }
- pGroup->iSize = szNew;
- pFile->iSize = iEnd;
- quotaLeave();
- }
- return pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst);
-}
-
-/* Pass xTruncate requests thru to the original VFS. If the
-** success, update the file size.
-*/
-static int quotaTruncate(sqlite3_file *pConn, sqlite3_int64 size){
- quotaConn *p = (quotaConn*)pConn;
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- int rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
- quotaFile *pFile = p->pFile;
- quotaGroup *pGroup;
- if( rc==SQLITE_OK ){
- quotaEnter();
- pGroup = pFile->pGroup;
- pGroup->iSize -= pFile->iSize;
- pFile->iSize = size;
- pGroup->iSize += size;
- quotaLeave();
- }
- return rc;
-}
-
-/* Pass xSync requests through to the original VFS without change
-*/
-static int quotaSync(sqlite3_file *pConn, int flags){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xSync(pSubOpen, flags);
-}
-
-/* Pass xFileSize requests through to the original VFS but then
-** update the quotaGroup with the new size before returning.
-*/
-static int quotaFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
- quotaConn *p = (quotaConn*)pConn;
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- quotaFile *pFile = p->pFile;
- quotaGroup *pGroup;
- sqlite3_int64 sz;
- int rc;
-
- rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
- if( rc==SQLITE_OK ){
- quotaEnter();
- pGroup = pFile->pGroup;
- pGroup->iSize -= pFile->iSize;
- pFile->iSize = sz;
- pGroup->iSize += sz;
- quotaLeave();
- *pSize = sz;
- }
- return rc;
-}
-
-/* Pass xLock requests through to the original VFS unchanged.
-*/
-static int quotaLock(sqlite3_file *pConn, int lock){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xLock(pSubOpen, lock);
-}
-
-/* Pass xUnlock requests through to the original VFS unchanged.
-*/
-static int quotaUnlock(sqlite3_file *pConn, int lock){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
-}
-
-/* Pass xCheckReservedLock requests through to the original VFS unchanged.
-*/
-static int quotaCheckReservedLock(sqlite3_file *pConn, int *pResOut){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
-}
-
-/* Pass xFileControl requests through to the original VFS unchanged.
-*/
-static int quotaFileControl(sqlite3_file *pConn, int op, void *pArg){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- int rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
-#if defined(SQLITE_FCNTL_VFSNAME)
- if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
- *(char**)pArg = sqlite3_mprintf("quota/%z", *(char**)pArg);
- }
-#endif
- return rc;
-}
-
-/* Pass xSectorSize requests through to the original VFS unchanged.
-*/
-static int quotaSectorSize(sqlite3_file *pConn){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xSectorSize(pSubOpen);
-}
-
-/* Pass xDeviceCharacteristics requests through to the original VFS unchanged.
-*/
-static int quotaDeviceCharacteristics(sqlite3_file *pConn){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
-}
-
-/* Pass xShmMap requests through to the original VFS unchanged.
-*/
-static int quotaShmMap(
- sqlite3_file *pConn, /* Handle open on database file */
- int iRegion, /* Region to retrieve */
- int szRegion, /* Size of regions */
- int bExtend, /* True to extend file if necessary */
- void volatile **pp /* OUT: Mapped memory */
-){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend, pp);
-}
-
-/* Pass xShmLock requests through to the original VFS unchanged.
-*/
-static int quotaShmLock(
- sqlite3_file *pConn, /* Database file holding the shared memory */
- int ofst, /* First lock to acquire or release */
- int n, /* Number of locks to acquire or release */
- int flags /* What to do with the lock */
-){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
-}
-
-/* Pass xShmBarrier requests through to the original VFS unchanged.
-*/
-static void quotaShmBarrier(sqlite3_file *pConn){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- pSubOpen->pMethods->xShmBarrier(pSubOpen);
-}
-
-/* Pass xShmUnmap requests through to the original VFS unchanged.
-*/
-static int quotaShmUnmap(sqlite3_file *pConn, int deleteFlag){
- sqlite3_file *pSubOpen = quotaSubOpen(pConn);
- return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
-}
-
-/************************** Public Interfaces *****************************/
-/*
-** Initialize the quota VFS shim. Use the VFS named zOrigVfsName
-** as the VFS that does the actual work. Use the default if
-** zOrigVfsName==NULL.
-**
-** The quota VFS shim is named "quota". It will become the default
-** VFS if makeDefault is non-zero.
-**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once
-** during start-up.
-*/
-int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault){
- sqlite3_vfs *pOrigVfs;
- if( gQuota.isInitialized ) return SQLITE_MISUSE;
- pOrigVfs = sqlite3_vfs_find(zOrigVfsName);
- if( pOrigVfs==0 ) return SQLITE_ERROR;
- assert( pOrigVfs!=&gQuota.sThisVfs );
- gQuota.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( !gQuota.pMutex ){
- return SQLITE_NOMEM;
- }
- gQuota.isInitialized = 1;
- gQuota.pOrigVfs = pOrigVfs;
- gQuota.sThisVfs = *pOrigVfs;
- gQuota.sThisVfs.xOpen = quotaOpen;
- gQuota.sThisVfs.xDelete = quotaDelete;
- gQuota.sThisVfs.szOsFile += sizeof(quotaConn);
- gQuota.sThisVfs.zName = "quota";
- gQuota.sIoMethodsV1.iVersion = 1;
- gQuota.sIoMethodsV1.xClose = quotaClose;
- gQuota.sIoMethodsV1.xRead = quotaRead;
- gQuota.sIoMethodsV1.xWrite = quotaWrite;
- gQuota.sIoMethodsV1.xTruncate = quotaTruncate;
- gQuota.sIoMethodsV1.xSync = quotaSync;
- gQuota.sIoMethodsV1.xFileSize = quotaFileSize;
- gQuota.sIoMethodsV1.xLock = quotaLock;
- gQuota.sIoMethodsV1.xUnlock = quotaUnlock;
- gQuota.sIoMethodsV1.xCheckReservedLock = quotaCheckReservedLock;
- gQuota.sIoMethodsV1.xFileControl = quotaFileControl;
- gQuota.sIoMethodsV1.xSectorSize = quotaSectorSize;
- gQuota.sIoMethodsV1.xDeviceCharacteristics = quotaDeviceCharacteristics;
- gQuota.sIoMethodsV2 = gQuota.sIoMethodsV1;
- gQuota.sIoMethodsV2.iVersion = 2;
- gQuota.sIoMethodsV2.xShmMap = quotaShmMap;
- gQuota.sIoMethodsV2.xShmLock = quotaShmLock;
- gQuota.sIoMethodsV2.xShmBarrier = quotaShmBarrier;
- gQuota.sIoMethodsV2.xShmUnmap = quotaShmUnmap;
- sqlite3_vfs_register(&gQuota.sThisVfs, makeDefault);
- return SQLITE_OK;
-}
-
-/*
-** Shutdown the quota system.
-**
-** All SQLite database connections must be closed before calling this
-** routine.
-**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while
-** shutting down in order to free all remaining quota groups.
-*/
-int sqlite3_quota_shutdown(void){
- quotaGroup *pGroup;
- if( gQuota.isInitialized==0 ) return SQLITE_MISUSE;
- for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){
- if( quotaGroupOpenFileCount(pGroup)>0 ) return SQLITE_MISUSE;
- }
- while( gQuota.pGroup ){
- pGroup = gQuota.pGroup;
- gQuota.pGroup = pGroup->pNext;
- pGroup->iLimit = 0;
- assert( quotaGroupOpenFileCount(pGroup)==0 );
- quotaGroupDeref(pGroup);
- }
- gQuota.isInitialized = 0;
- sqlite3_mutex_free(gQuota.pMutex);
- sqlite3_vfs_unregister(&gQuota.sThisVfs);
- memset(&gQuota, 0, sizeof(gQuota));
- return SQLITE_OK;
-}
-
-/*
-** Create or destroy a quota group.
-**
-** The quota group is defined by the zPattern. When calling this routine
-** with a zPattern for a quota group that already exists, this routine
-** merely updates the iLimit, xCallback, and pArg values for that quota
-** group. If zPattern is new, then a new quota group is created.
-**
-** If the iLimit for a quota group is set to zero, then the quota group
-** is disabled and will be deleted when the last database connection using
-** the quota group is closed.
-**
-** Calling this routine on a zPattern that does not exist and with a
-** zero iLimit is a no-op.
-**
-** A quota group must exist with a non-zero iLimit prior to opening
-** database connections if those connections are to participate in the
-** quota group. Creating a quota group does not affect database connections
-** that are already open.
-*/
-int sqlite3_quota_set(
- const char *zPattern, /* The filename pattern */
- sqlite3_int64 iLimit, /* New quota to set for this quota group */
- void (*xCallback)( /* Callback invoked when going over quota */
- const char *zFilename, /* Name of file whose size increases */
- sqlite3_int64 *piLimit, /* IN/OUT: The current limit */
- sqlite3_int64 iSize, /* Total size of all files in the group */
- void *pArg /* Client data */
- ),
- void *pArg, /* client data passed thru to callback */
- void (*xDestroy)(void*) /* Optional destructor for pArg */
-){
- quotaGroup *pGroup;
- quotaEnter();
- pGroup = gQuota.pGroup;
- while( pGroup && strcmp(pGroup->zPattern, zPattern)!=0 ){
- pGroup = pGroup->pNext;
- }
- if( pGroup==0 ){
- int nPattern = (int)(strlen(zPattern) & 0x3fffffff);
- if( iLimit<=0 ){
- quotaLeave();
- return SQLITE_OK;
- }
- pGroup = (quotaGroup *)sqlite3_malloc( sizeof(*pGroup) + nPattern + 1 );
- if( pGroup==0 ){
- quotaLeave();
- return SQLITE_NOMEM;
- }
- memset(pGroup, 0, sizeof(*pGroup));
- pGroup->zPattern = (char*)&pGroup[1];
- memcpy((char *)pGroup->zPattern, zPattern, nPattern+1);
- if( gQuota.pGroup ) gQuota.pGroup->ppPrev = &pGroup->pNext;
- pGroup->pNext = gQuota.pGroup;
- pGroup->ppPrev = &gQuota.pGroup;
- gQuota.pGroup = pGroup;
- }
- pGroup->iLimit = iLimit;
- pGroup->xCallback = xCallback;
- if( pGroup->xDestroy && pGroup->pArg!=pArg ){
- pGroup->xDestroy(pGroup->pArg);
- }
- pGroup->pArg = pArg;
- pGroup->xDestroy = xDestroy;
- quotaGroupDeref(pGroup);
- quotaLeave();
- return SQLITE_OK;
-}
-
-/*
-** Bring the named file under quota management. Or if it is already under
-** management, update its size.
-*/
-int sqlite3_quota_file(const char *zFilename){
- char *zFull = 0;
- sqlite3_file *fd;
- int rc;
- int outFlags = 0;
- sqlite3_int64 iSize;
- int nAlloc = gQuota.sThisVfs.szOsFile + gQuota.sThisVfs.mxPathname+2;
-
- /* Allocate space for a file-handle and the full path for file zFilename */
- fd = (sqlite3_file *)sqlite3_malloc(nAlloc);
- if( fd==0 ){
- rc = SQLITE_NOMEM;
- }else{
- zFull = &((char *)fd)[gQuota.sThisVfs.szOsFile];
- rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename,
- gQuota.sThisVfs.mxPathname+1, zFull);
- }
-
- if( rc==SQLITE_OK ){
- zFull[strlen(zFull)+1] = '\0';
- rc = quotaOpen(&gQuota.sThisVfs, zFull, fd,
- SQLITE_OPEN_READONLY | SQLITE_OPEN_MAIN_DB, &outFlags);
- if( rc==SQLITE_OK ){
- fd->pMethods->xFileSize(fd, &iSize);
- fd->pMethods->xClose(fd);
- }else if( rc==SQLITE_CANTOPEN ){
- quotaGroup *pGroup;
- quotaFile *pFile;
- quotaEnter();
- pGroup = quotaGroupFind(zFull);
- if( pGroup ){
- pFile = quotaFindFile(pGroup, zFull, 0);
- if( pFile ) quotaRemoveFile(pFile);
- }
- quotaLeave();
- }
- }
-
- sqlite3_free(fd);
- return rc;
-}
-
-/*
-** Open a potentially quotaed file for I/O.
-*/
-quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){
- quota_FILE *p = 0;
- char *zFull = 0;
- char *zFullTranslated = 0;
- int rc;
- quotaGroup *pGroup;
- quotaFile *pFile;
-
- zFull = (char*)sqlite3_malloc(gQuota.sThisVfs.mxPathname + 1);
- if( zFull==0 ) return 0;
- rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename,
- gQuota.sThisVfs.mxPathname+1, zFull);
- if( rc ) goto quota_fopen_error;
- p = (quota_FILE*)sqlite3_malloc(sizeof(*p));
- if( p==0 ) goto quota_fopen_error;
- memset(p, 0, sizeof(*p));
- zFullTranslated = quota_utf8_to_mbcs(zFull);
- if( zFullTranslated==0 ) goto quota_fopen_error;
- p->f = fopen(zFullTranslated, zMode);
- if( p->f==0 ) goto quota_fopen_error;
- quotaEnter();
- pGroup = quotaGroupFind(zFull);
- if( pGroup ){
- pFile = quotaFindFile(pGroup, zFull, 1);
- if( pFile==0 ){
- quotaLeave();
- goto quota_fopen_error;
- }
- pFile->nRef++;
- p->pFile = pFile;
- }
- quotaLeave();
- sqlite3_free(zFull);
-#if SQLITE_OS_WIN
- p->zMbcsName = zFullTranslated;
-#endif
- return p;
-
-quota_fopen_error:
- quota_mbcs_free(zFullTranslated);
- sqlite3_free(zFull);
- if( p && p->f ) fclose(p->f);
- sqlite3_free(p);
- return 0;
-}
-
-/*
-** Read content from a quota_FILE
-*/
-size_t sqlite3_quota_fread(
- void *pBuf, /* Store the content here */
- size_t size, /* Size of each element */
- size_t nmemb, /* Number of elements to read */
- quota_FILE *p /* Read from this quota_FILE object */
-){
- return fread(pBuf, size, nmemb, p->f);
-}
-
-/*
-** Write content into a quota_FILE. Invoke the quota callback and block
-** the write if we exceed quota.
-*/
-size_t sqlite3_quota_fwrite(
- const void *pBuf, /* Take content to write from here */
- size_t size, /* Size of each element */
- size_t nmemb, /* Number of elements */
- quota_FILE *p /* Write to this quota_FILE objecct */
-){
- sqlite3_int64 iOfst;
- sqlite3_int64 iEnd;
- sqlite3_int64 szNew;
- quotaFile *pFile;
- size_t rc;
-
- iOfst = ftell(p->f);
- iEnd = iOfst + size*nmemb;
- pFile = p->pFile;
- if( pFile && pFile->iSize<iEnd ){
- quotaGroup *pGroup = pFile->pGroup;
- quotaEnter();
- szNew = pGroup->iSize - pFile->iSize + iEnd;
- if( szNew>pGroup->iLimit && pGroup->iLimit>0 ){
- if( pGroup->xCallback ){
- pGroup->xCallback(pFile->zFilename, &pGroup->iLimit, szNew,
- pGroup->pArg);
- }
- if( szNew>pGroup->iLimit && pGroup->iLimit>0 ){
- iEnd = pGroup->iLimit - pGroup->iSize + pFile->iSize;
- nmemb = (size_t)((iEnd - iOfst)/size);
- iEnd = iOfst + size*nmemb;
- szNew = pGroup->iSize - pFile->iSize + iEnd;
- }
- }
- pGroup->iSize = szNew;
- pFile->iSize = iEnd;
- quotaLeave();
- }else{
- pFile = 0;
- }
- rc = fwrite(pBuf, size, nmemb, p->f);
-
- /* If the write was incomplete, adjust the file size and group size
- ** downward */
- if( rc<nmemb && pFile ){
- size_t nWritten = rc;
- sqlite3_int64 iNewEnd = iOfst + size*nWritten;
- if( iNewEnd<iEnd ) iNewEnd = iEnd;
- quotaEnter();
- pFile->pGroup->iSize += iNewEnd - pFile->iSize;
- pFile->iSize = iNewEnd;
- quotaLeave();
- }
- return rc;
-}
-
-/*
-** Close an open quota_FILE stream.
-*/
-int sqlite3_quota_fclose(quota_FILE *p){
- int rc;
- quotaFile *pFile;
- rc = fclose(p->f);
- pFile = p->pFile;
- if( pFile ){
- quotaEnter();
- pFile->nRef--;
- if( pFile->nRef==0 ){
- quotaGroup *pGroup = pFile->pGroup;
- if( pFile->deleteOnClose ){
- gQuota.pOrigVfs->xDelete(gQuota.pOrigVfs, pFile->zFilename, 0);
- quotaRemoveFile(pFile);
- }
- quotaGroupDeref(pGroup);
- }
- quotaLeave();
- }
-#if SQLITE_OS_WIN
- quota_mbcs_free(p->zMbcsName);
-#endif
- sqlite3_free(p);
- return rc;
-}
-
-/*
-** Flush memory buffers for a quota_FILE to disk.
-*/
-int sqlite3_quota_fflush(quota_FILE *p, int doFsync){
- int rc;
- rc = fflush(p->f);
- if( rc==0 && doFsync ){
-#if SQLITE_OS_UNIX
- rc = fsync(fileno(p->f));
-#endif
-#if SQLITE_OS_WIN
- rc = _commit(_fileno(p->f));
-#endif
- }
- return rc!=0;
-}
-
-/*
-** Seek on a quota_FILE stream.
-*/
-int sqlite3_quota_fseek(quota_FILE *p, long offset, int whence){
- return fseek(p->f, offset, whence);
-}
-
-/*
-** rewind a quota_FILE stream.
-*/
-void sqlite3_quota_rewind(quota_FILE *p){
- rewind(p->f);
-}
-
-/*
-** Tell the current location of a quota_FILE stream.
-*/
-long sqlite3_quota_ftell(quota_FILE *p){
- return ftell(p->f);
-}
-
-/*
-** Test the error indicator for the given file.
-*/
-int sqlite3_quota_ferror(quota_FILE *p){
- return ferror(p->f);
-}
-
-/*
-** Truncate a file to szNew bytes.
-*/
-int sqlite3_quota_ftruncate(quota_FILE *p, sqlite3_int64 szNew){
- quotaFile *pFile = p->pFile;
- int rc;
- if( (pFile = p->pFile)!=0 && pFile->iSize<szNew ){
- quotaGroup *pGroup;
- if( pFile->iSize<szNew ){
- /* This routine cannot be used to extend a file that is under
- ** quota management. Only true truncation is allowed. */
- return -1;
- }
- pGroup = pFile->pGroup;
- quotaEnter();
- pGroup->iSize += szNew - pFile->iSize;
- quotaLeave();
- }
-#if SQLITE_OS_UNIX
- rc = ftruncate(fileno(p->f), szNew);
-#endif
-#if SQLITE_OS_WIN
-# if defined(__MINGW32__) && defined(SQLITE_TEST)
- /* _chsize_s() is missing from MingW (as of 2012-11-06). Use
- ** _chsize() as a work-around for testing purposes. */
- rc = _chsize(_fileno(p->f), (long)szNew);
-# else
- rc = _chsize_s(_fileno(p->f), szNew);
-# endif
-#endif
- if( pFile && rc==0 ){
- quotaGroup *pGroup = pFile->pGroup;
- quotaEnter();
- pGroup->iSize += szNew - pFile->iSize;
- pFile->iSize = szNew;
- quotaLeave();
- }
- return rc;
-}
-
-/*
-** Determine the time that the given file was last modified, in
-** seconds size 1970. Write the result into *pTime. Return 0 on
-** success and non-zero on any kind of error.
-*/
-int sqlite3_quota_file_mtime(quota_FILE *p, time_t *pTime){
- int rc;
-#if SQLITE_OS_UNIX
- struct stat buf;
- rc = fstat(fileno(p->f), &buf);
-#endif
-#if SQLITE_OS_WIN
- struct _stati64 buf;
- rc = _stati64(p->zMbcsName, &buf);
-#endif
- if( rc==0 ) *pTime = buf.st_mtime;
- return rc;
-}
-
-/*
-** Return the true size of the file, as reported by the operating
-** system.
-*/
-sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE *p){
- int rc;
-#if SQLITE_OS_UNIX
- struct stat buf;
- rc = fstat(fileno(p->f), &buf);
-#endif
-#if SQLITE_OS_WIN
- struct _stati64 buf;
- rc = _stati64(p->zMbcsName, &buf);
-#endif
- return rc==0 ? buf.st_size : -1;
-}
-
-/*
-** Return the size of the file, as it is known to the quota subsystem.
-*/
-sqlite3_int64 sqlite3_quota_file_size(quota_FILE *p){
- return p->pFile ? p->pFile->iSize : -1;
-}
-
-/*
-** Determine the amount of data in bytes available for reading
-** in the given file.
-*/
-long sqlite3_quota_file_available(quota_FILE *p){
- FILE* f = p->f;
- long pos1, pos2;
- int rc;
- pos1 = ftell(f);
- if ( pos1 < 0 ) return -1;
- rc = fseek(f, 0, SEEK_END);
- if ( rc != 0 ) return -1;
- pos2 = ftell(f);
- if ( pos2 < 0 ) return -1;
- rc = fseek(f, pos1, SEEK_SET);
- if ( rc != 0 ) return -1;
- return pos2 - pos1;
-}
-
-/*
-** Remove a managed file. Update quotas accordingly.
-*/
-int sqlite3_quota_remove(const char *zFilename){
- char *zFull; /* Full pathname for zFilename */
- size_t nFull; /* Number of bytes in zFilename */
- int rc; /* Result code */
- quotaGroup *pGroup; /* Group containing zFilename */
- quotaFile *pFile; /* A file in the group */
- quotaFile *pNextFile; /* next file in the group */
- int diff; /* Difference between filenames */
- char c; /* First character past end of pattern */
-
- zFull = (char*)sqlite3_malloc(gQuota.sThisVfs.mxPathname + 1);
- if( zFull==0 ) return SQLITE_NOMEM;
- rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename,
- gQuota.sThisVfs.mxPathname+1, zFull);
- if( rc ){
- sqlite3_free(zFull);
- return rc;
- }
-
- /* Figure out the length of the full pathname. If the name ends with
- ** / (or \ on windows) then remove the trailing /.
- */
- nFull = strlen(zFull);
- if( nFull>0 && (zFull[nFull-1]=='/' || zFull[nFull-1]=='\\') ){
- nFull--;
- zFull[nFull] = 0;
- }
-
- quotaEnter();
- pGroup = quotaGroupFind(zFull);
- if( pGroup ){
- for(pFile=pGroup->pFiles; pFile && rc==SQLITE_OK; pFile=pNextFile){
- pNextFile = pFile->pNext;
- diff = strncmp(zFull, pFile->zFilename, nFull);
- if( diff==0 && ((c = pFile->zFilename[nFull])==0 || c=='/' || c=='\\') ){
- if( pFile->nRef ){
- pFile->deleteOnClose = 1;
- }else{
- rc = gQuota.pOrigVfs->xDelete(gQuota.pOrigVfs, pFile->zFilename, 0);
- quotaRemoveFile(pFile);
- quotaGroupDeref(pGroup);
- }
- }
- }
- }
- quotaLeave();
- sqlite3_free(zFull);
- return rc;
-}
-
-/***************************** Test Code ***********************************/
-#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-/*
-** Argument passed to a TCL quota-over-limit callback.
-*/
-typedef struct TclQuotaCallback TclQuotaCallback;
-struct TclQuotaCallback {
- Tcl_Interp *interp; /* Interpreter in which to run the script */
- Tcl_Obj *pScript; /* Script to be run */
-};
-
-extern const char *sqlite3ErrName(int);
-
-
-/*
-** This is the callback from a quota-over-limit.
-*/
-static void tclQuotaCallback(
- const char *zFilename, /* Name of file whose size increases */
- sqlite3_int64 *piLimit, /* IN/OUT: The current limit */
- sqlite3_int64 iSize, /* Total size of all files in the group */
- void *pArg /* Client data */
-){
- TclQuotaCallback *p; /* Callback script object */
- Tcl_Obj *pEval; /* Script to evaluate */
- Tcl_Obj *pVarname; /* Name of variable to pass as 2nd arg */
- unsigned int rnd; /* Random part of pVarname */
- int rc; /* Tcl error code */
-
- p = (TclQuotaCallback *)pArg;
- if( p==0 ) return;
-
- pVarname = Tcl_NewStringObj("::piLimit_", -1);
- Tcl_IncrRefCount(pVarname);
- sqlite3_randomness(sizeof(rnd), (void *)&rnd);
- Tcl_AppendObjToObj(pVarname, Tcl_NewIntObj((int)(rnd&0x7FFFFFFF)));
- Tcl_ObjSetVar2(p->interp, pVarname, 0, Tcl_NewWideIntObj(*piLimit), 0);
-
- pEval = Tcl_DuplicateObj(p->pScript);
- Tcl_IncrRefCount(pEval);
- Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(zFilename, -1));
- Tcl_ListObjAppendElement(0, pEval, pVarname);
- Tcl_ListObjAppendElement(0, pEval, Tcl_NewWideIntObj(iSize));
- rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
-
- if( rc==TCL_OK ){
- Tcl_WideInt x;
- Tcl_Obj *pLimit = Tcl_ObjGetVar2(p->interp, pVarname, 0, 0);
- rc = Tcl_GetWideIntFromObj(p->interp, pLimit, &x);
- *piLimit = x;
- Tcl_UnsetVar(p->interp, Tcl_GetString(pVarname), 0);
- }
-
- Tcl_DecrRefCount(pEval);
- Tcl_DecrRefCount(pVarname);
- if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
-}
-
-/*
-** Destructor for a TCL quota-over-limit callback.
-*/
-static void tclCallbackDestructor(void *pObj){
- TclQuotaCallback *p = (TclQuotaCallback*)pObj;
- if( p ){
- Tcl_DecrRefCount(p->pScript);
- sqlite3_free((char *)p);
- }
-}
-
-/*
-** tclcmd: sqlite3_quota_initialize NAME MAKEDEFAULT
-*/
-static int SQLITE_TCLAPI test_quota_initialize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zName; /* Name of new quota VFS */
- int makeDefault; /* True to make the new VFS the default */
- int rc; /* Value returned by quota_initialize() */
-
- /* Process arguments */
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME MAKEDEFAULT");
- return TCL_ERROR;
- }
- zName = Tcl_GetString(objv[1]);
- if( Tcl_GetBooleanFromObj(interp, objv[2], &makeDefault) ) return TCL_ERROR;
- if( zName[0]=='\0' ) zName = 0;
-
- /* Call sqlite3_quota_initialize() */
- rc = sqlite3_quota_initialize(zName, makeDefault);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_shutdown
-*/
-static int SQLITE_TCLAPI test_quota_shutdown(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc; /* Value returned by quota_shutdown() */
-
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
-
- /* Call sqlite3_quota_shutdown() */
- rc = sqlite3_quota_shutdown();
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
-
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_set PATTERN LIMIT SCRIPT
-*/
-static int SQLITE_TCLAPI test_quota_set(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zPattern; /* File pattern to configure */
- Tcl_WideInt iLimit; /* Initial quota in bytes */
- Tcl_Obj *pScript; /* Tcl script to invoke to increase quota */
- int rc; /* Value returned by quota_set() */
- TclQuotaCallback *p; /* Callback object */
- int nScript; /* Length of callback script */
- void (*xDestroy)(void*); /* Optional destructor for pArg */
- void (*xCallback)(const char *, sqlite3_int64 *, sqlite3_int64, void *);
-
- /* Process arguments */
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PATTERN LIMIT SCRIPT");
- return TCL_ERROR;
- }
- zPattern = Tcl_GetString(objv[1]);
- if( Tcl_GetWideIntFromObj(interp, objv[2], &iLimit) ) return TCL_ERROR;
- pScript = objv[3];
- Tcl_GetStringFromObj(pScript, &nScript);
-
- if( nScript>0 ){
- /* Allocate a TclQuotaCallback object */
- p = (TclQuotaCallback *)sqlite3_malloc(sizeof(TclQuotaCallback));
- if( !p ){
- Tcl_SetResult(interp, (char *)"SQLITE_NOMEM", TCL_STATIC);
- return TCL_OK;
- }
- memset(p, 0, sizeof(TclQuotaCallback));
- p->interp = interp;
- Tcl_IncrRefCount(pScript);
- p->pScript = pScript;
- xDestroy = tclCallbackDestructor;
- xCallback = tclQuotaCallback;
- }else{
- p = 0;
- xDestroy = 0;
- xCallback = 0;
- }
-
- /* Invoke sqlite3_quota_set() */
- rc = sqlite3_quota_set(zPattern, iLimit, xCallback, (void*)p, xDestroy);
-
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_file FILENAME
-*/
-static int SQLITE_TCLAPI test_quota_file(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zFilename; /* File pattern to configure */
- int rc; /* Value returned by quota_file() */
-
- /* Process arguments */
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
- return TCL_ERROR;
- }
- zFilename = Tcl_GetString(objv[1]);
-
- /* Invoke sqlite3_quota_file() */
- rc = sqlite3_quota_file(zFilename);
-
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_dump
-*/
-static int SQLITE_TCLAPI test_quota_dump(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_Obj *pResult;
- Tcl_Obj *pGroupTerm;
- Tcl_Obj *pFileTerm;
- quotaGroup *pGroup;
- quotaFile *pFile;
-
- pResult = Tcl_NewObj();
- quotaEnter();
- for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){
- pGroupTerm = Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, pGroupTerm,
- Tcl_NewStringObj(pGroup->zPattern, -1));
- Tcl_ListObjAppendElement(interp, pGroupTerm,
- Tcl_NewWideIntObj(pGroup->iLimit));
- Tcl_ListObjAppendElement(interp, pGroupTerm,
- Tcl_NewWideIntObj(pGroup->iSize));
- for(pFile=pGroup->pFiles; pFile; pFile=pFile->pNext){
- int i;
- char zTemp[1000];
- pFileTerm = Tcl_NewObj();
- sqlite3_snprintf(sizeof(zTemp), zTemp, "%s", pFile->zFilename);
- for(i=0; zTemp[i]; i++){ if( zTemp[i]=='\\' ) zTemp[i] = '/'; }
- Tcl_ListObjAppendElement(interp, pFileTerm,
- Tcl_NewStringObj(zTemp, -1));
- Tcl_ListObjAppendElement(interp, pFileTerm,
- Tcl_NewWideIntObj(pFile->iSize));
- Tcl_ListObjAppendElement(interp, pFileTerm,
- Tcl_NewWideIntObj(pFile->nRef));
- Tcl_ListObjAppendElement(interp, pFileTerm,
- Tcl_NewWideIntObj(pFile->deleteOnClose));
- Tcl_ListObjAppendElement(interp, pGroupTerm, pFileTerm);
- }
- Tcl_ListObjAppendElement(interp, pResult, pGroupTerm);
- }
- quotaLeave();
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_fopen FILENAME MODE
-*/
-static int SQLITE_TCLAPI test_quota_fopen(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zFilename; /* File pattern to configure */
- const char *zMode; /* Mode string */
- quota_FILE *p; /* Open string object */
- char zReturn[50]; /* Name of pointer to return */
-
- /* Process arguments */
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME MODE");
- return TCL_ERROR;
- }
- zFilename = Tcl_GetString(objv[1]);
- zMode = Tcl_GetString(objv[2]);
- p = sqlite3_quota_fopen(zFilename, zMode);
- sqlite3_snprintf(sizeof(zReturn), zReturn, "%p", p);
- Tcl_SetResult(interp, zReturn, TCL_VOLATILE);
- return TCL_OK;
-}
-
-/* Defined in test1.c */
-extern void *sqlite3TestTextToPtr(const char*);
-
-/*
-** tclcmd: sqlite3_quota_fread HANDLE SIZE NELEM
-*/
-static int SQLITE_TCLAPI test_quota_fread(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- char *zBuf;
- int sz;
- int nElem;
- size_t got;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE NELEM");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &nElem) ) return TCL_ERROR;
- zBuf = (char*)sqlite3_malloc( sz*nElem + 1 );
- if( zBuf==0 ){
- Tcl_SetResult(interp, "out of memory", TCL_STATIC);
- return TCL_ERROR;
- }
- got = sqlite3_quota_fread(zBuf, sz, nElem, p);
- zBuf[got*sz] = 0;
- Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
- sqlite3_free(zBuf);
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_fwrite HANDLE SIZE NELEM CONTENT
-*/
-static int SQLITE_TCLAPI test_quota_fwrite(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- char *zBuf;
- int sz;
- int nElem;
- size_t got;
-
- if( objc!=5 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE NELEM CONTENT");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[3], &nElem) ) return TCL_ERROR;
- zBuf = Tcl_GetString(objv[4]);
- got = sqlite3_quota_fwrite(zBuf, sz, nElem, p);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(got));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_fclose HANDLE
-*/
-static int SQLITE_TCLAPI test_quota_fclose(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- int rc;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- rc = sqlite3_quota_fclose(p);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_fflush HANDLE ?HARDSYNC?
-*/
-static int SQLITE_TCLAPI test_quota_fflush(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- int rc;
- int doSync = 0;
-
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE ?HARDSYNC?");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- if( objc==3 ){
- if( Tcl_GetBooleanFromObj(interp, objv[2], &doSync) ) return TCL_ERROR;
- }
- rc = sqlite3_quota_fflush(p, doSync);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_fseek HANDLE OFFSET WHENCE
-*/
-static int SQLITE_TCLAPI test_quota_fseek(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- int ofst;
- const char *zWhence;
- int whence;
- int rc;
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE OFFSET WHENCE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- if( Tcl_GetIntFromObj(interp, objv[2], &ofst) ) return TCL_ERROR;
- zWhence = Tcl_GetString(objv[3]);
- if( strcmp(zWhence, "SEEK_SET")==0 ){
- whence = SEEK_SET;
- }else if( strcmp(zWhence, "SEEK_CUR")==0 ){
- whence = SEEK_CUR;
- }else if( strcmp(zWhence, "SEEK_END")==0 ){
- whence = SEEK_END;
- }else{
- Tcl_AppendResult(interp,
- "WHENCE should be SEEK_SET, SEEK_CUR, or SEEK_END", (char*)0);
- return TCL_ERROR;
- }
- rc = sqlite3_quota_fseek(p, ofst, whence);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_rewind HANDLE
-*/
-static int SQLITE_TCLAPI test_quota_rewind(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- sqlite3_quota_rewind(p);
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_ftell HANDLE
-*/
-static int SQLITE_TCLAPI test_quota_ftell(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- sqlite3_int64 x;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- x = sqlite3_quota_ftell(p);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_ftruncate HANDLE SIZE
-*/
-static int SQLITE_TCLAPI test_quota_ftruncate(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- sqlite3_int64 x;
- Tcl_WideInt w;
- int rc;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- if( Tcl_GetWideIntFromObj(interp, objv[2], &w) ) return TCL_ERROR;
- x = (sqlite3_int64)w;
- rc = sqlite3_quota_ftruncate(p, x);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_file_size HANDLE
-*/
-static int SQLITE_TCLAPI test_quota_file_size(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- sqlite3_int64 x;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- x = sqlite3_quota_file_size(p);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_file_truesize HANDLE
-*/
-static int SQLITE_TCLAPI test_quota_file_truesize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- sqlite3_int64 x;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- x = sqlite3_quota_file_truesize(p);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_file_mtime HANDLE
-*/
-static int SQLITE_TCLAPI test_quota_file_mtime(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- time_t t;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- t = 0;
- sqlite3_quota_file_mtime(p, &t);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t));
- return TCL_OK;
-}
-
-
-/*
-** tclcmd: sqlite3_quota_remove FILENAME
-*/
-static int SQLITE_TCLAPI test_quota_remove(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zFilename; /* File pattern to configure */
- int rc;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
- return TCL_ERROR;
- }
- zFilename = Tcl_GetString(objv[1]);
- rc = sqlite3_quota_remove(zFilename);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_glob PATTERN TEXT
-**
-** Test the glob pattern matching. Return 1 if TEXT matches PATTERN
-** and return 0 if it does not.
-*/
-static int SQLITE_TCLAPI test_quota_glob(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zPattern; /* The glob pattern */
- const char *zText; /* Text to compare agains the pattern */
- int rc;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PATTERN TEXT");
- return TCL_ERROR;
- }
- zPattern = Tcl_GetString(objv[1]);
- zText = Tcl_GetString(objv[2]);
- rc = quotaStrglob(zPattern, zText);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_file_available HANDLE
-**
-** Return the number of bytes from the current file point to the end of
-** the file.
-*/
-static int SQLITE_TCLAPI test_quota_file_available(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- sqlite3_int64 x;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- x = sqlite3_quota_file_available(p);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
- return TCL_OK;
-}
-
-/*
-** tclcmd: sqlite3_quota_ferror HANDLE
-**
-** Return true if the file handle is in the error state.
-*/
-static int SQLITE_TCLAPI test_quota_ferror(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- quota_FILE *p;
- int x;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
- return TCL_ERROR;
- }
- p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- x = sqlite3_quota_ferror(p);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
- return TCL_OK;
-}
-
-/*
-** This routine registers the custom TCL commands defined in this
-** module. This should be the only procedure visible from outside
-** of this module.
-*/
-int Sqlitequota_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- } aCmd[] = {
- { "sqlite3_quota_initialize", test_quota_initialize },
- { "sqlite3_quota_shutdown", test_quota_shutdown },
- { "sqlite3_quota_set", test_quota_set },
- { "sqlite3_quota_file", test_quota_file },
- { "sqlite3_quota_dump", test_quota_dump },
- { "sqlite3_quota_fopen", test_quota_fopen },
- { "sqlite3_quota_fread", test_quota_fread },
- { "sqlite3_quota_fwrite", test_quota_fwrite },
- { "sqlite3_quota_fclose", test_quota_fclose },
- { "sqlite3_quota_fflush", test_quota_fflush },
- { "sqlite3_quota_fseek", test_quota_fseek },
- { "sqlite3_quota_rewind", test_quota_rewind },
- { "sqlite3_quota_ftell", test_quota_ftell },
- { "sqlite3_quota_ftruncate", test_quota_ftruncate },
- { "sqlite3_quota_file_size", test_quota_file_size },
- { "sqlite3_quota_file_truesize", test_quota_file_truesize },
- { "sqlite3_quota_file_mtime", test_quota_file_mtime },
- { "sqlite3_quota_remove", test_quota_remove },
- { "sqlite3_quota_glob", test_quota_glob },
- { "sqlite3_quota_file_available",test_quota_file_available },
- { "sqlite3_quota_ferror", test_quota_ferror },
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
-
- return TCL_OK;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_quota.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_quota.h
deleted file mode 100644
index c17e15adca1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_quota.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
-** 2011 December 1
-**
-** 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 contains the interface definition for the quota a VFS shim.
-**
-** This particular shim enforces a quota system on files. One or more
-** database files are in a "quota group" that is defined by a GLOB
-** pattern. A quota is set for the combined size of all files in the
-** the group. A quota of zero means "no limit". If the total size
-** of all files in the quota group is greater than the limit, then
-** write requests that attempt to enlarge a file fail with SQLITE_FULL.
-**
-** However, before returning SQLITE_FULL, the write requests invoke
-** a callback function that is configurable for each quota group.
-** This callback has the opportunity to enlarge the quota. If the
-** callback does enlarge the quota such that the total size of all
-** files within the group is less than the new quota, then the write
-** continues as if nothing had happened.
-*/
-#ifndef _QUOTA_H_
-#include "sqlite3.h"
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-/* Make this callable from C++ */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** Initialize the quota VFS shim. Use the VFS named zOrigVfsName
-** as the VFS that does the actual work. Use the default if
-** zOrigVfsName==NULL.
-**
-** The quota VFS shim is named "quota". It will become the default
-** VFS if makeDefault is non-zero.
-**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once
-** during start-up.
-*/
-int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault);
-
-/*
-** Shutdown the quota system.
-**
-** All SQLite database connections must be closed before calling this
-** routine.
-**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while
-** shutting down in order to free all remaining quota groups.
-*/
-int sqlite3_quota_shutdown(void);
-
-/*
-** Create or destroy a quota group.
-**
-** The quota group is defined by the zPattern. When calling this routine
-** with a zPattern for a quota group that already exists, this routine
-** merely updates the iLimit, xCallback, and pArg values for that quota
-** group. If zPattern is new, then a new quota group is created.
-**
-** The zPattern is always compared against the full pathname of the file.
-** Even if APIs are called with relative pathnames, SQLite converts the
-** name to a full pathname before comparing it against zPattern. zPattern
-** is a glob pattern with the following matching rules:
-**
-** '*' Matches any sequence of zero or more characters.
-**
-** '?' Matches exactly one character.
-**
-** [...] Matches one character from the enclosed list of
-** characters. "]" can be part of the list if it is
-** the first character. Within the list "X-Y" matches
-** characters X or Y or any character in between the
-** two. Ex: "[0-9]" matches any digit.
-**
-** [^...] Matches one character not in the enclosed list.
-**
-** / Matches either / or \. This allows glob patterns
-** containing / to work on both unix and windows.
-**
-** Note that, unlike unix shell globbing, the directory separator "/"
-** can match a wildcard. So, for example, the pattern "/abc/xyz/" "*"
-** matches any files anywhere in the directory hierarchy beneath
-** /abc/xyz.
-**
-** The glob algorithm works on bytes. Multi-byte UTF8 characters are
-** matched as if each byte were a separate character.
-**
-** If the iLimit for a quota group is set to zero, then the quota group
-** is disabled and will be deleted when the last database connection using
-** the quota group is closed.
-**
-** Calling this routine on a zPattern that does not exist and with a
-** zero iLimit is a no-op.
-**
-** A quota group must exist with a non-zero iLimit prior to opening
-** database connections if those connections are to participate in the
-** quota group. Creating a quota group does not affect database connections
-** that are already open.
-**
-** The patterns that define the various quota groups should be distinct.
-** If the same filename matches more than one quota group pattern, then
-** the behavior of this package is undefined.
-*/
-int sqlite3_quota_set(
- const char *zPattern, /* The filename pattern */
- sqlite3_int64 iLimit, /* New quota to set for this quota group */
- void (*xCallback)( /* Callback invoked when going over quota */
- const char *zFilename, /* Name of file whose size increases */
- sqlite3_int64 *piLimit, /* IN/OUT: The current limit */
- sqlite3_int64 iSize, /* Total size of all files in the group */
- void *pArg /* Client data */
- ),
- void *pArg, /* client data passed thru to callback */
- void (*xDestroy)(void*) /* Optional destructor for pArg */
-);
-
-/*
-** Bring the named file under quota management, assuming its name matches
-** the glob pattern of some quota group. Or if it is already under
-** management, update its size. If zFilename does not match the glob
-** pattern of any quota group, this routine is a no-op.
-*/
-int sqlite3_quota_file(const char *zFilename);
-
-/*
-** The following object serves the same role as FILE in the standard C
-** library. It represents an open connection to a file on disk for I/O.
-**
-** A single quota_FILE should not be used by two or more threads at the
-** same time. Multiple threads can be using different quota_FILE objects
-** simultaneously, but not the same quota_FILE object.
-*/
-typedef struct quota_FILE quota_FILE;
-
-/*
-** Create a new quota_FILE object used to read and/or write to the
-** file zFilename. The zMode parameter is as with standard library zMode.
-*/
-quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode);
-
-/*
-** Perform I/O against a quota_FILE object. When doing writes, the
-** quota mechanism may result in a short write, in order to prevent
-** the sum of sizes of all files from going over quota.
-*/
-size_t sqlite3_quota_fread(void*, size_t, size_t, quota_FILE*);
-size_t sqlite3_quota_fwrite(const void*, size_t, size_t, quota_FILE*);
-
-/*
-** Flush all written content held in memory buffers out to disk.
-** This is the equivalent of fflush() in the standard library.
-**
-** If the hardSync parameter is true (non-zero) then this routine
-** also forces OS buffers to disk - the equivalent of fsync().
-**
-** This routine return zero on success and non-zero if something goes
-** wrong.
-*/
-int sqlite3_quota_fflush(quota_FILE*, int hardSync);
-
-/*
-** Close a quota_FILE object and free all associated resources. The
-** file remains under quota management.
-*/
-int sqlite3_quota_fclose(quota_FILE*);
-
-/*
-** Move the read/write pointer for a quota_FILE object. Or tell the
-** current location of the read/write pointer.
-*/
-int sqlite3_quota_fseek(quota_FILE*, long, int);
-void sqlite3_quota_rewind(quota_FILE*);
-long sqlite3_quota_ftell(quota_FILE*);
-
-/*
-** Test the error indicator for the given file.
-**
-** Return non-zero if the error indicator is set.
-*/
-int sqlite3_quota_ferror(quota_FILE*);
-
-/*
-** Truncate a file previously opened by sqlite3_quota_fopen(). Return
-** zero on success and non-zero on any kind of failure.
-**
-** The newSize argument must be less than or equal to the current file size.
-** Any attempt to "truncate" a file to a larger size results in
-** undefined behavior.
-*/
-int sqlite3_quota_ftruncate(quota_FILE*, sqlite3_int64 newSize);
-
-/*
-** Return the last modification time of the opened file, in seconds
-** since 1970.
-*/
-int sqlite3_quota_file_mtime(quota_FILE*, time_t *pTime);
-
-/*
-** Return the size of the file as it is known to the quota system.
-**
-** This size might be different from the true size of the file on
-** disk if some outside process has modified the file without using the
-** quota mechanism, or if calls to sqlite3_quota_fwrite() have occurred
-** which have increased the file size, but those writes have not yet been
-** forced to disk using sqlite3_quota_fflush().
-**
-** Return -1 if the file is not participating in quota management.
-*/
-sqlite3_int64 sqlite3_quota_file_size(quota_FILE*);
-
-/*
-** Return the true size of the file.
-**
-** The true size should be the same as the size of the file as known
-** to the quota system, however the sizes might be different if the
-** file has been extended or truncated via some outside process or if
-** pending writes have not yet been flushed to disk.
-**
-** Return -1 if the file does not exist or if the size of the file
-** cannot be determined for some reason.
-*/
-sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE*);
-
-/*
-** Determine the amount of data in bytes available for reading
-** in the given file.
-**
-** Return -1 if the amount cannot be determined for some reason.
-*/
-long sqlite3_quota_file_available(quota_FILE*);
-
-/*
-** Delete a file from the disk, if that file is under quota management.
-** Adjust quotas accordingly.
-**
-** If zFilename is the name of a directory that matches one of the
-** quota glob patterns, then all files under quota management that
-** are contained within that directory are deleted.
-**
-** A standard SQLite result code is returned (SQLITE_OK, SQLITE_NOMEM, etc.)
-** When deleting a directory of files, if the deletion of any one
-** file fails (for example due to an I/O error), then this routine
-** returns immediately, with the error code, and does not try to
-** delete any of the other files in the specified directory.
-**
-** All files are removed from quota management and deleted from disk.
-** However, no attempt is made to remove empty directories.
-**
-** This routine is a no-op for files that are not under quota management.
-*/
-int sqlite3_quota_remove(const char *zFilename);
-
-#ifdef __cplusplus
-} /* end of the 'extern "C"' block */
-#endif
-#endif /* _QUOTA_H_ */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_rtree.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_rtree.c
deleted file mode 100644
index 0c6dbf3cd73..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_rtree.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
-** 2010 August 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.
-**
-*************************************************************************
-** Code for testing all sorts of SQLite interfaces. This code
-** is not included in the SQLite library.
-*/
-
-#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-/* Solely for the UNUSED_PARAMETER() macro. */
-#include "sqliteInt.h"
-
-#ifdef SQLITE_ENABLE_RTREE
-/*
-** Type used to cache parameter information for the "circle" r-tree geometry
-** callback.
-*/
-typedef struct Circle Circle;
-struct Circle {
- struct Box {
- double xmin;
- double xmax;
- double ymin;
- double ymax;
- } aBox[2];
- double centerx;
- double centery;
- double radius;
- double mxArea;
- int eScoreType;
-};
-
-/*
-** Destructor function for Circle objects allocated by circle_geom().
-*/
-static void circle_del(void *p){
- sqlite3_free(p);
-}
-
-/*
-** Implementation of "circle" r-tree geometry callback.
-*/
-static int circle_geom(
- sqlite3_rtree_geometry *p,
- int nCoord,
- sqlite3_rtree_dbl *aCoord,
- int *pRes
-){
- int i; /* Iterator variable */
- Circle *pCircle; /* Structure defining circular region */
- double xmin, xmax; /* X dimensions of box being tested */
- double ymin, ymax; /* X dimensions of box being tested */
-
- xmin = aCoord[0];
- xmax = aCoord[1];
- ymin = aCoord[2];
- ymax = aCoord[3];
- pCircle = (Circle *)p->pUser;
- if( pCircle==0 ){
- /* If pUser is still 0, then the parameter values have not been tested
- ** for correctness or stored into a Circle structure yet. Do this now. */
-
- /* This geometry callback is for use with a 2-dimensional r-tree table.
- ** Return an error if the table does not have exactly 2 dimensions. */
- if( nCoord!=4 ) return SQLITE_ERROR;
-
- /* Test that the correct number of parameters (3) have been supplied,
- ** and that the parameters are in range (that the radius of the circle
- ** radius is greater than zero). */
- if( p->nParam!=3 || p->aParam[2]<0.0 ) return SQLITE_ERROR;
-
- /* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM
- ** if the allocation fails. */
- pCircle = (Circle *)(p->pUser = sqlite3_malloc(sizeof(Circle)));
- if( !pCircle ) return SQLITE_NOMEM;
- p->xDelUser = circle_del;
-
- /* Record the center and radius of the circular region. One way that
- ** tested bounding boxes that intersect the circular region are detected
- ** is by testing if each corner of the bounding box lies within radius
- ** units of the center of the circle. */
- pCircle->centerx = p->aParam[0];
- pCircle->centery = p->aParam[1];
- pCircle->radius = p->aParam[2];
-
- /* Define two bounding box regions. The first, aBox[0], extends to
- ** infinity in the X dimension. It covers the same range of the Y dimension
- ** as the circular region. The second, aBox[1], extends to infinity in
- ** the Y dimension and is constrained to the range of the circle in the
- ** X dimension.
- **
- ** Then imagine each box is split in half along its short axis by a line
- ** that intersects the center of the circular region. A bounding box
- ** being tested can be said to intersect the circular region if it contains
- ** points from each half of either of the two infinite bounding boxes.
- */
- pCircle->aBox[0].xmin = pCircle->centerx;
- pCircle->aBox[0].xmax = pCircle->centerx;
- pCircle->aBox[0].ymin = pCircle->centery + pCircle->radius;
- pCircle->aBox[0].ymax = pCircle->centery - pCircle->radius;
- pCircle->aBox[1].xmin = pCircle->centerx + pCircle->radius;
- pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius;
- pCircle->aBox[1].ymin = pCircle->centery;
- pCircle->aBox[1].ymax = pCircle->centery;
- pCircle->mxArea = (xmax - xmin)*(ymax - ymin) + 1.0;
- }
-
- /* Check if any of the 4 corners of the bounding-box being tested lie
- ** inside the circular region. If they do, then the bounding-box does
- ** intersect the region of interest. Set the output variable to true and
- ** return SQLITE_OK in this case. */
- for(i=0; i<4; i++){
- double x = (i&0x01) ? xmax : xmin;
- double y = (i&0x02) ? ymax : ymin;
- double d2;
-
- d2 = (x-pCircle->centerx)*(x-pCircle->centerx);
- d2 += (y-pCircle->centery)*(y-pCircle->centery);
- if( d2<(pCircle->radius*pCircle->radius) ){
- *pRes = 1;
- return SQLITE_OK;
- }
- }
-
- /* Check if the bounding box covers any other part of the circular region.
- ** See comments above for a description of how this test works. If it does
- ** cover part of the circular region, set the output variable to true
- ** and return SQLITE_OK. */
- for(i=0; i<2; i++){
- if( xmin<=pCircle->aBox[i].xmin
- && xmax>=pCircle->aBox[i].xmax
- && ymin<=pCircle->aBox[i].ymin
- && ymax>=pCircle->aBox[i].ymax
- ){
- *pRes = 1;
- return SQLITE_OK;
- }
- }
-
- /* The specified bounding box does not intersect the circular region. Set
- ** the output variable to zero and return SQLITE_OK. */
- *pRes = 0;
- return SQLITE_OK;
-}
-
-/*
-** Implementation of "circle" r-tree geometry callback using the
-** 2nd-generation interface that allows scoring.
-**
-** Two calling forms:
-**
-** Qcircle(X,Y,Radius,eType) -- All values are doubles
-** Qcircle('x:X y:Y r:R e:ETYPE') -- Single string parameter
-*/
-static int circle_query_func(sqlite3_rtree_query_info *p){
- int i; /* Iterator variable */
- Circle *pCircle; /* Structure defining circular region */
- double xmin, xmax; /* X dimensions of box being tested */
- double ymin, ymax; /* X dimensions of box being tested */
- int nWithin = 0; /* Number of corners inside the circle */
-
- xmin = p->aCoord[0];
- xmax = p->aCoord[1];
- ymin = p->aCoord[2];
- ymax = p->aCoord[3];
- pCircle = (Circle *)p->pUser;
- if( pCircle==0 ){
- /* If pUser is still 0, then the parameter values have not been tested
- ** for correctness or stored into a Circle structure yet. Do this now. */
-
- /* This geometry callback is for use with a 2-dimensional r-tree table.
- ** Return an error if the table does not have exactly 2 dimensions. */
- if( p->nCoord!=4 ) return SQLITE_ERROR;
-
- /* Test that the correct number of parameters (1 or 4) have been supplied.
- */
- if( p->nParam!=4 && p->nParam!=1 ) return SQLITE_ERROR;
-
- /* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM
- ** if the allocation fails. */
- pCircle = (Circle *)(p->pUser = sqlite3_malloc(sizeof(Circle)));
- if( !pCircle ) return SQLITE_NOMEM;
- p->xDelUser = circle_del;
-
- /* Record the center and radius of the circular region. One way that
- ** tested bounding boxes that intersect the circular region are detected
- ** is by testing if each corner of the bounding box lies within radius
- ** units of the center of the circle. */
- if( p->nParam==4 ){
- pCircle->centerx = p->aParam[0];
- pCircle->centery = p->aParam[1];
- pCircle->radius = p->aParam[2];
- pCircle->eScoreType = (int)p->aParam[3];
- }else{
- const char *z = (const char*)sqlite3_value_text(p->apSqlParam[0]);
- pCircle->centerx = 0.0;
- pCircle->centery = 0.0;
- pCircle->radius = 0.0;
- pCircle->eScoreType = 0;
- while( z && z[0] ){
- if( z[0]=='r' && z[1]==':' ){
- pCircle->radius = atof(&z[2]);
- }else if( z[0]=='x' && z[1]==':' ){
- pCircle->centerx = atof(&z[2]);
- }else if( z[0]=='y' && z[1]==':' ){
- pCircle->centery = atof(&z[2]);
- }else if( z[0]=='e' && z[1]==':' ){
- pCircle->eScoreType = (int)atof(&z[2]);
- }else if( z[0]==' ' ){
- z++;
- continue;
- }
- while( z[0]!=0 && z[0]!=' ' ) z++;
- while( z[0]==' ' ) z++;
- }
- }
- if( pCircle->radius<0.0 ){
- sqlite3_free(pCircle);
- return SQLITE_NOMEM;
- }
-
- /* Define two bounding box regions. The first, aBox[0], extends to
- ** infinity in the X dimension. It covers the same range of the Y dimension
- ** as the circular region. The second, aBox[1], extends to infinity in
- ** the Y dimension and is constrained to the range of the circle in the
- ** X dimension.
- **
- ** Then imagine each box is split in half along its short axis by a line
- ** that intersects the center of the circular region. A bounding box
- ** being tested can be said to intersect the circular region if it contains
- ** points from each half of either of the two infinite bounding boxes.
- */
- pCircle->aBox[0].xmin = pCircle->centerx;
- pCircle->aBox[0].xmax = pCircle->centerx;
- pCircle->aBox[0].ymin = pCircle->centery + pCircle->radius;
- pCircle->aBox[0].ymax = pCircle->centery - pCircle->radius;
- pCircle->aBox[1].xmin = pCircle->centerx + pCircle->radius;
- pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius;
- pCircle->aBox[1].ymin = pCircle->centery;
- pCircle->aBox[1].ymax = pCircle->centery;
- pCircle->mxArea = 200.0*200.0;
- }
-
- /* Check if any of the 4 corners of the bounding-box being tested lie
- ** inside the circular region. If they do, then the bounding-box does
- ** intersect the region of interest. Set the output variable to true and
- ** return SQLITE_OK in this case. */
- for(i=0; i<4; i++){
- double x = (i&0x01) ? xmax : xmin;
- double y = (i&0x02) ? ymax : ymin;
- double d2;
-
- d2 = (x-pCircle->centerx)*(x-pCircle->centerx);
- d2 += (y-pCircle->centery)*(y-pCircle->centery);
- if( d2<(pCircle->radius*pCircle->radius) ) nWithin++;
- }
-
- /* Check if the bounding box covers any other part of the circular region.
- ** See comments above for a description of how this test works. If it does
- ** cover part of the circular region, set the output variable to true
- ** and return SQLITE_OK. */
- if( nWithin==0 ){
- for(i=0; i<2; i++){
- if( xmin<=pCircle->aBox[i].xmin
- && xmax>=pCircle->aBox[i].xmax
- && ymin<=pCircle->aBox[i].ymin
- && ymax>=pCircle->aBox[i].ymax
- ){
- nWithin = 1;
- break;
- }
- }
- }
-
- if( pCircle->eScoreType==1 ){
- /* Depth first search */
- p->rScore = p->iLevel;
- }else if( pCircle->eScoreType==2 ){
- /* Breadth first search */
- p->rScore = 100 - p->iLevel;
- }else if( pCircle->eScoreType==3 ){
- /* Depth-first search, except sort the leaf nodes by area with
- ** the largest area first */
- if( p->iLevel==1 ){
- p->rScore = 1.0 - (xmax-xmin)*(ymax-ymin)/pCircle->mxArea;
- if( p->rScore<0.01 ) p->rScore = 0.01;
- }else{
- p->rScore = 0.0;
- }
- }else if( pCircle->eScoreType==4 ){
- /* Depth-first search, except exclude odd rowids */
- p->rScore = p->iLevel;
- if( p->iRowid&1 ) nWithin = 0;
- }else{
- /* Breadth-first search, except exclude odd rowids */
- p->rScore = 100 - p->iLevel;
- if( p->iRowid&1 ) nWithin = 0;
- }
- if( nWithin==0 ){
- p->eWithin = NOT_WITHIN;
- }else if( nWithin>=4 ){
- p->eWithin = FULLY_WITHIN;
- }else{
- p->eWithin = PARTLY_WITHIN;
- }
- return SQLITE_OK;
-}
-/*
-** Implementation of "breadthfirstsearch" r-tree geometry callback using the
-** 2nd-generation interface that allows scoring.
-**
-** ... WHERE id MATCH breadthfirstsearch($x0,$x1,$y0,$y1) ...
-**
-** It returns all entries whose bounding boxes overlap with $x0,$x1,$y0,$y1.
-*/
-static int bfs_query_func(sqlite3_rtree_query_info *p){
- double x0,x1,y0,y1; /* Dimensions of box being tested */
- double bx0,bx1,by0,by1; /* Boundary of the query function */
-
- if( p->nParam!=4 ) return SQLITE_ERROR;
- x0 = p->aCoord[0];
- x1 = p->aCoord[1];
- y0 = p->aCoord[2];
- y1 = p->aCoord[3];
- bx0 = p->aParam[0];
- bx1 = p->aParam[1];
- by0 = p->aParam[2];
- by1 = p->aParam[3];
- p->rScore = 100 - p->iLevel;
- if( p->eParentWithin==FULLY_WITHIN ){
- p->eWithin = FULLY_WITHIN;
- }else if( x0>=bx0 && x1<=bx1 && y0>=by0 && y1<=by1 ){
- p->eWithin = FULLY_WITHIN;
- }else if( x1>=bx0 && x0<=bx1 && y1>=by0 && y0<=by1 ){
- p->eWithin = PARTLY_WITHIN;
- }else{
- p->eWithin = NOT_WITHIN;
- }
- return SQLITE_OK;
-}
-
-/* END of implementation of "circle" geometry callback.
-**************************************************************************
-*************************************************************************/
-
-#include <assert.h>
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-typedef struct Cube Cube;
-struct Cube {
- double x;
- double y;
- double z;
- double width;
- double height;
- double depth;
-};
-
-static void cube_context_free(void *p){
- sqlite3_free(p);
-}
-
-/*
-** The context pointer registered along with the 'cube' callback is
-** always ((void *)&gHere). This is just to facilitate testing, it is not
-** actually used for anything.
-*/
-static int gHere = 42;
-
-/*
-** Implementation of a simple r-tree geom callback to test for intersection
-** of r-tree rows with a "cube" shape. Cubes are defined by six scalar
-** coordinates as follows:
-**
-** cube(x, y, z, width, height, depth)
-**
-** The width, height and depth parameters must all be greater than zero.
-*/
-static int cube_geom(
- sqlite3_rtree_geometry *p,
- int nCoord,
- sqlite3_rtree_dbl *aCoord,
- int *piRes
-){
- Cube *pCube = (Cube *)p->pUser;
-
- assert( p->pContext==(void *)&gHere );
-
- if( pCube==0 ){
- if( p->nParam!=6 || nCoord!=6
- || p->aParam[3]<=0.0 || p->aParam[4]<=0.0 || p->aParam[5]<=0.0
- ){
- return SQLITE_ERROR;
- }
- pCube = (Cube *)sqlite3_malloc(sizeof(Cube));
- if( !pCube ){
- return SQLITE_NOMEM;
- }
- pCube->x = p->aParam[0];
- pCube->y = p->aParam[1];
- pCube->z = p->aParam[2];
- pCube->width = p->aParam[3];
- pCube->height = p->aParam[4];
- pCube->depth = p->aParam[5];
-
- p->pUser = (void *)pCube;
- p->xDelUser = cube_context_free;
- }
-
- assert( nCoord==6 );
- *piRes = 0;
- if( aCoord[0]<=(pCube->x+pCube->width)
- && aCoord[1]>=pCube->x
- && aCoord[2]<=(pCube->y+pCube->height)
- && aCoord[3]>=pCube->y
- && aCoord[4]<=(pCube->z+pCube->depth)
- && aCoord[5]>=pCube->z
- ){
- *piRes = 1;
- }
-
- return SQLITE_OK;
-}
-#endif /* SQLITE_ENABLE_RTREE */
-
-static int SQLITE_TCLAPI register_cube_geom(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_ENABLE_RTREE
- UNUSED_PARAMETER(clientData);
- UNUSED_PARAMETER(interp);
- UNUSED_PARAMETER(objc);
- UNUSED_PARAMETER(objv);
-#else
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- extern const char *sqlite3ErrName(int);
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_rtree_geometry_callback(db, "cube", cube_geom, (void *)&gHere);
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
-#endif
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI register_circle_geom(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-#ifndef SQLITE_ENABLE_RTREE
- UNUSED_PARAMETER(clientData);
- UNUSED_PARAMETER(interp);
- UNUSED_PARAMETER(objc);
- UNUSED_PARAMETER(objv);
-#else
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- extern const char *sqlite3ErrName(int);
- sqlite3 *db;
- int rc;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_rtree_geometry_callback(db, "circle", circle_geom, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_rtree_query_callback(db, "Qcircle",
- circle_query_func, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_rtree_query_callback(db, "breadthfirstsearch",
- bfs_query_func, 0, 0);
- }
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
-#endif
- return TCL_OK;
-}
-
-int Sqlitetestrtree_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "register_cube_geom", register_cube_geom, 0, 0);
- Tcl_CreateObjCommand(interp, "register_circle_geom",register_circle_geom,0,0);
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_schema.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_schema.c
deleted file mode 100644
index cdf085797f0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_schema.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
-** 2006 June 10
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the virtual table interfaces. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library.
-*/
-
-/* The code in this file defines a sqlite3 virtual-table module that
-** provides a read-only view of the current database schema. There is one
-** row in the schema table for each column in the database schema.
-*/
-#define SCHEMA \
-"CREATE TABLE x(" \
- "database," /* Name of database (i.e. main, temp etc.) */ \
- "tablename," /* Name of table */ \
- "cid," /* Column number (from left-to-right, 0 upward) */ \
- "name," /* Column name */ \
- "type," /* Specified type (i.e. VARCHAR(32)) */ \
- "not_null," /* Boolean. True if NOT NULL was specified */ \
- "dflt_value," /* Default value for this column */ \
- "pk" /* True if this column is part of the primary key */ \
-")"
-
-/* If SQLITE_TEST is defined this code is preprocessed for use as part
-** of the sqlite test binary "testfixture". Otherwise it is preprocessed
-** to be compiled into an sqlite dynamic extension.
-*/
-#ifdef SQLITE_TEST
-# include "sqliteInt.h"
-# if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-# else
-# include "tcl.h"
-# endif
-#else
-# include "sqlite3ext.h"
- SQLITE_EXTENSION_INIT1
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-typedef struct schema_vtab schema_vtab;
-typedef struct schema_cursor schema_cursor;
-
-/* A schema table object */
-struct schema_vtab {
- sqlite3_vtab base;
- sqlite3 *db;
-};
-
-/* A schema table cursor object */
-struct schema_cursor {
- sqlite3_vtab_cursor base;
- sqlite3_stmt *pDbList;
- sqlite3_stmt *pTableList;
- sqlite3_stmt *pColumnList;
- int rowid;
-};
-
-/*
-** None of this works unless we have virtual tables.
-*/
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Table destructor for the schema module.
-*/
-static int schemaDestroy(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return 0;
-}
-
-/*
-** Table constructor for the schema module.
-*/
-static int schemaCreate(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- int rc = SQLITE_NOMEM;
- schema_vtab *pVtab = sqlite3_malloc(sizeof(schema_vtab));
- if( pVtab ){
- memset(pVtab, 0, sizeof(schema_vtab));
- pVtab->db = db;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_declare_vtab(db, SCHEMA);
-#endif
- }
- *ppVtab = (sqlite3_vtab *)pVtab;
- return rc;
-}
-
-/*
-** Open a new cursor on the schema table.
-*/
-static int schemaOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- int rc = SQLITE_NOMEM;
- schema_cursor *pCur;
- pCur = sqlite3_malloc(sizeof(schema_cursor));
- if( pCur ){
- memset(pCur, 0, sizeof(schema_cursor));
- *ppCursor = (sqlite3_vtab_cursor *)pCur;
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-/*
-** Close a schema table cursor.
-*/
-static int schemaClose(sqlite3_vtab_cursor *cur){
- schema_cursor *pCur = (schema_cursor *)cur;
- sqlite3_finalize(pCur->pDbList);
- sqlite3_finalize(pCur->pTableList);
- sqlite3_finalize(pCur->pColumnList);
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Retrieve a column of data.
-*/
-static int schemaColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- schema_cursor *pCur = (schema_cursor *)cur;
- switch( i ){
- case 0:
- sqlite3_result_value(ctx, sqlite3_column_value(pCur->pDbList, 1));
- break;
- case 1:
- sqlite3_result_value(ctx, sqlite3_column_value(pCur->pTableList, 0));
- break;
- default:
- sqlite3_result_value(ctx, sqlite3_column_value(pCur->pColumnList, i-2));
- break;
- }
- return SQLITE_OK;
-}
-
-/*
-** Retrieve the current rowid.
-*/
-static int schemaRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- schema_cursor *pCur = (schema_cursor *)cur;
- *pRowid = pCur->rowid;
- return SQLITE_OK;
-}
-
-static int finalize(sqlite3_stmt **ppStmt){
- int rc = sqlite3_finalize(*ppStmt);
- *ppStmt = 0;
- return rc;
-}
-
-static int schemaEof(sqlite3_vtab_cursor *cur){
- schema_cursor *pCur = (schema_cursor *)cur;
- return (pCur->pDbList ? 0 : 1);
-}
-
-/*
-** Advance the cursor to the next row.
-*/
-static int schemaNext(sqlite3_vtab_cursor *cur){
- int rc = SQLITE_OK;
- schema_cursor *pCur = (schema_cursor *)cur;
- schema_vtab *pVtab = (schema_vtab *)(cur->pVtab);
- char *zSql = 0;
-
- while( !pCur->pColumnList || SQLITE_ROW!=sqlite3_step(pCur->pColumnList) ){
- if( SQLITE_OK!=(rc = finalize(&pCur->pColumnList)) ) goto next_exit;
-
- while( !pCur->pTableList || SQLITE_ROW!=sqlite3_step(pCur->pTableList) ){
- if( SQLITE_OK!=(rc = finalize(&pCur->pTableList)) ) goto next_exit;
-
- assert(pCur->pDbList);
- while( SQLITE_ROW!=sqlite3_step(pCur->pDbList) ){
- rc = finalize(&pCur->pDbList);
- goto next_exit;
- }
-
- /* Set zSql to the SQL to pull the list of tables from the
- ** sqlite_master (or sqlite_temp_master) table of the database
- ** identified by the row pointed to by the SQL statement pCur->pDbList
- ** (iterating through a "PRAGMA database_list;" statement).
- */
- if( sqlite3_column_int(pCur->pDbList, 0)==1 ){
- zSql = sqlite3_mprintf(
- "SELECT name FROM sqlite_temp_master WHERE type='table'"
- );
- }else{
- sqlite3_stmt *pDbList = pCur->pDbList;
- zSql = sqlite3_mprintf(
- "SELECT name FROM %Q.sqlite_master WHERE type='table'",
- sqlite3_column_text(pDbList, 1)
- );
- }
- if( !zSql ){
- rc = SQLITE_NOMEM;
- goto next_exit;
- }
-
- rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pTableList, 0);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK ) goto next_exit;
- }
-
- /* Set zSql to the SQL to the table_info pragma for the table currently
- ** identified by the rows pointed to by statements pCur->pDbList and
- ** pCur->pTableList.
- */
- zSql = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)",
- sqlite3_column_text(pCur->pDbList, 1),
- sqlite3_column_text(pCur->pTableList, 0)
- );
-
- if( !zSql ){
- rc = SQLITE_NOMEM;
- goto next_exit;
- }
- rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pColumnList, 0);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK ) goto next_exit;
- }
- pCur->rowid++;
-
-next_exit:
- /* TODO: Handle rc */
- return rc;
-}
-
-/*
-** Reset a schema table cursor.
-*/
-static int schemaFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- int rc;
- schema_vtab *pVtab = (schema_vtab *)(pVtabCursor->pVtab);
- schema_cursor *pCur = (schema_cursor *)pVtabCursor;
- pCur->rowid = 0;
- finalize(&pCur->pTableList);
- finalize(&pCur->pColumnList);
- finalize(&pCur->pDbList);
- rc = sqlite3_prepare(pVtab->db,"PRAGMA database_list", -1, &pCur->pDbList, 0);
- return (rc==SQLITE_OK ? schemaNext(pVtabCursor) : rc);
-}
-
-/*
-** Analyse the WHERE condition.
-*/
-static int schemaBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- return SQLITE_OK;
-}
-
-/*
-** A virtual table module that merely echos method calls into TCL
-** variables.
-*/
-static sqlite3_module schemaModule = {
- 0, /* iVersion */
- schemaCreate,
- schemaCreate,
- schemaBestIndex,
- schemaDestroy,
- schemaDestroy,
- schemaOpen, /* xOpen - open a cursor */
- schemaClose, /* xClose - close a cursor */
- schemaFilter, /* xFilter - configure scan constraints */
- schemaNext, /* xNext - advance a cursor */
- schemaEof, /* xEof */
- schemaColumn, /* xColumn - read data */
- schemaRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
-
-#ifdef SQLITE_TEST
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
-
-/*
-** Register the schema virtual table module.
-*/
-static int SQLITE_TCLAPI register_schema_module(
- ClientData clientData, /* Not used */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- sqlite3 *db;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_create_module(db, "schema", &schemaModule, 0);
-#endif
- return TCL_OK;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetestschema_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- void *clientData;
- } aObjCmd[] = {
- { "register_schema_module", register_schema_module, 0 },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
- aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
- }
- return TCL_OK;
-}
-
-#else
-
-/*
-** Extension load function.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_schema_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_create_module(db, "schema", &schemaModule, 0);
-#endif
- return 0;
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_server.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_server.c
deleted file mode 100644
index 4eb1cf19660..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_server.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
-** 2006 January 07
-**
-** 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 contains demonstration code. Nothing in this file gets compiled
-** or linked into the SQLite library unless you use a non-standard option:
-**
-** -DSQLITE_SERVER=1
-**
-** The configure script will never generate a Makefile with the option
-** above. You will need to manually modify the Makefile if you want to
-** include any of the code from this file in your project. Or, at your
-** option, you may copy and paste the code from this file and
-** thereby avoiding a recompile of SQLite.
-**
-**
-** This source file demonstrates how to use SQLite to create an SQL database
-** server thread in a multiple-threaded program. One or more client threads
-** send messages to the server thread and the server thread processes those
-** messages in the order received and returns the results to the client.
-**
-** One might ask: "Why bother? Why not just let each thread connect
-** to the database directly?" There are a several of reasons to
-** prefer the client/server approach.
-**
-** (1) Some systems (ex: Redhat9) have broken threading implementations
-** that prevent SQLite database connections from being used in
-** a thread different from the one where they were created. With
-** the client/server approach, all database connections are created
-** and used within the server thread. Client calls to the database
-** can be made from multiple threads (though not at the same time!)
-**
-** (2) Beginning with SQLite version 3.3.0, when two or more
-** connections to the same database occur within the same thread,
-** they can optionally share their database cache. This reduces
-** I/O and memory requirements. Cache shared is controlled using
-** the sqlite3_enable_shared_cache() API.
-**
-** (3) Database connections on a shared cache use table-level locking
-** instead of file-level locking for improved concurrency.
-**
-** (4) Database connections on a shared cache can by optionally
-** set to READ UNCOMMITTED isolation. (The default isolation for
-** SQLite is SERIALIZABLE.) When this occurs, readers will
-** never be blocked by a writer and writers will not be
-** blocked by readers. There can still only be a single writer
-** at a time, but multiple readers can simultaneously exist with
-** that writer. This is a huge increase in concurrency.
-**
-** To summarize the rational for using a client/server approach: prior
-** to SQLite version 3.3.0 it probably was not worth the trouble. But
-** with SQLite version 3.3.0 and beyond you can get significant performance
-** and concurrency improvements and memory usage reductions by going
-** client/server.
-**
-** Note: The extra features of version 3.3.0 described by points (2)
-** through (4) above are only available if you compile without the
-** option -DSQLITE_OMIT_SHARED_CACHE.
-**
-** Here is how the client/server approach works: The database server
-** thread is started on this procedure:
-**
-** void *sqlite3_server(void *NotUsed);
-**
-** The sqlite_server procedure runs as long as the g.serverHalt variable
-** is false. A mutex is used to make sure no more than one server runs
-** at a time. The server waits for messages to arrive on a message
-** queue and processes the messages in order.
-**
-** Two convenience routines are provided for starting and stopping the
-** server thread:
-**
-** void sqlite3_server_start(void);
-** void sqlite3_server_stop(void);
-**
-** Both of the convenience routines return immediately. Neither will
-** ever give an error. If a server is already started or already halted,
-** then the routines are effectively no-ops.
-**
-** Clients use the following interfaces:
-**
-** sqlite3_client_open
-** sqlite3_client_prepare
-** sqlite3_client_step
-** sqlite3_client_reset
-** sqlite3_client_finalize
-** sqlite3_client_close
-**
-** These interfaces work exactly like the standard core SQLite interfaces
-** having the same names without the "_client_" infix. Many other SQLite
-** interfaces can be used directly without having to send messages to the
-** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined.
-** The following interfaces fall into this second category:
-**
-** sqlite3_bind_*
-** sqlite3_changes
-** sqlite3_clear_bindings
-** sqlite3_column_*
-** sqlite3_complete
-** sqlite3_create_collation
-** sqlite3_create_function
-** sqlite3_data_count
-** sqlite3_db_handle
-** sqlite3_errcode
-** sqlite3_errmsg
-** sqlite3_last_insert_rowid
-** sqlite3_total_changes
-** sqlite3_transfer_bindings
-**
-** A single SQLite connection (an sqlite3* object) or an SQLite statement
-** (an sqlite3_stmt* object) should only be passed to a single interface
-** function at a time. The connections and statements can be passed from
-** any thread to any of the functions listed in the second group above as
-** long as the same connection is not in use by two threads at once and
-** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional
-** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is
-** below.
-**
-** The busy handler for all database connections should remain turned
-** off. That means that any lock contention will cause the associated
-** sqlite3_client_step() call to return immediately with an SQLITE_BUSY
-** error code. If a busy handler is enabled and lock contention occurs,
-** then the entire server thread will block. This will cause not only
-** the requesting client to block but every other database client as
-** well. It is possible to enhance the code below so that lock
-** contention will cause the message to be placed back on the top of
-** the queue to be tried again later. But such enhanced processing is
-** not included here, in order to keep the example simple.
-**
-** This example code assumes the use of pthreads. Pthreads
-** implementations are available for windows. (See, for example
-** http://sourceware.org/pthreads-win32/announcement.html.) Or, you
-** can translate the locking and thread synchronization code to use
-** windows primitives easily enough. The details are left as an
-** exercise to the reader.
-**
-**** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT ****
-**
-** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then
-** SQLite includes code that tracks how much memory is being used by
-** each thread. These memory counts can become confused if memory
-** is allocated by one thread and then freed by another. For that
-** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations
-** that might allocate or free memory should be performanced in the same
-** thread that originally created the database connection. In that case,
-** many of the operations that are listed above as safe to be performed
-** in separate threads would need to be sent over to the server to be
-** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then
-** the following functions can be used safely from different threads
-** without messing up the allocation counts:
-**
-** sqlite3_bind_parameter_name
-** sqlite3_bind_parameter_index
-** sqlite3_changes
-** sqlite3_column_blob
-** sqlite3_column_count
-** sqlite3_complete
-** sqlite3_data_count
-** sqlite3_db_handle
-** sqlite3_errcode
-** sqlite3_errmsg
-** sqlite3_last_insert_rowid
-** sqlite3_total_changes
-**
-** The remaining functions are not thread-safe when memory management
-** is enabled. So one would have to define some new interface routines
-** along the following lines:
-**
-** sqlite3_client_bind_*
-** sqlite3_client_clear_bindings
-** sqlite3_client_column_*
-** sqlite3_client_create_collation
-** sqlite3_client_create_function
-** sqlite3_client_transfer_bindings
-**
-** The example code in this file is intended for use with memory
-** management turned off. So the implementation of these additional
-** client interfaces is left as an exercise to the reader.
-**
-** It may seem surprising to the reader that the list of safe functions
-** above does not include things like sqlite3_bind_int() or
-** sqlite3_column_int(). But those routines might, in fact, allocate
-** or deallocate memory. In the case of sqlite3_bind_int(), if the
-** parameter was previously bound to a string that string might need
-** to be deallocated before the new integer value is inserted. In
-** the case of sqlite3_column_int(), the value of the column might be
-** a UTF-16 string which will need to be converted to UTF-8 then into
-** an integer.
-*/
-
-/* Include this to get the definition of SQLITE_THREADSAFE, in the
-** case that default values are used.
-*/
-#include "sqliteInt.h"
-
-/*
-** Only compile the code in this file on UNIX with a SQLITE_THREADSAFE build
-** and only if the SQLITE_SERVER macro is defined.
-*/
-#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE)
-#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
-
-/*
-** We require only pthreads and the public interface of SQLite.
-*/
-#include <pthread.h>
-#include "sqlite3.h"
-
-/*
-** Messages are passed from client to server and back again as
-** instances of the following structure.
-*/
-typedef struct SqlMessage SqlMessage;
-struct SqlMessage {
- int op; /* Opcode for the message */
- sqlite3 *pDb; /* The SQLite connection */
- sqlite3_stmt *pStmt; /* A specific statement */
- int errCode; /* Error code returned */
- const char *zIn; /* Input filename or SQL statement */
- int nByte; /* Size of the zIn parameter for prepare() */
- const char *zOut; /* Tail of the SQL statement */
- SqlMessage *pNext; /* Next message in the queue */
- SqlMessage *pPrev; /* Previous message in the queue */
- pthread_mutex_t clientMutex; /* Hold this mutex to access the message */
- pthread_cond_t clientWakeup; /* Signal to wake up the client */
-};
-
-/*
-** Legal values for SqlMessage.op
-*/
-#define MSG_Open 1 /* sqlite3_open(zIn, &pDb) */
-#define MSG_Prepare 2 /* sqlite3_prepare(pDb, zIn, nByte, &pStmt, &zOut) */
-#define MSG_Step 3 /* sqlite3_step(pStmt) */
-#define MSG_Reset 4 /* sqlite3_reset(pStmt) */
-#define MSG_Finalize 5 /* sqlite3_finalize(pStmt) */
-#define MSG_Close 6 /* sqlite3_close(pDb) */
-#define MSG_Done 7 /* Server has finished with this message */
-
-
-/*
-** State information about the server is stored in a static variable
-** named "g" as follows:
-*/
-static struct ServerState {
- pthread_mutex_t queueMutex; /* Hold this mutex to access the msg queue */
- pthread_mutex_t serverMutex; /* Held by the server while it is running */
- pthread_cond_t serverWakeup; /* Signal this condvar to wake up the server */
- volatile int serverHalt; /* Server halts itself when true */
- SqlMessage *pQueueHead; /* Head of the message queue */
- SqlMessage *pQueueTail; /* Tail of the message queue */
-} g = {
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_COND_INITIALIZER,
-};
-
-/*
-** Send a message to the server. Block until we get a reply.
-**
-** The mutex and condition variable in the message are uninitialized
-** when this routine is called. This routine takes care of
-** initializing them and destroying them when it has finished.
-*/
-static void sendToServer(SqlMessage *pMsg){
- /* Initialize the mutex and condition variable on the message
- */
- pthread_mutex_init(&pMsg->clientMutex, 0);
- pthread_cond_init(&pMsg->clientWakeup, 0);
-
- /* Add the message to the head of the server's message queue.
- */
- pthread_mutex_lock(&g.queueMutex);
- pMsg->pNext = g.pQueueHead;
- if( g.pQueueHead==0 ){
- g.pQueueTail = pMsg;
- }else{
- g.pQueueHead->pPrev = pMsg;
- }
- pMsg->pPrev = 0;
- g.pQueueHead = pMsg;
- pthread_mutex_unlock(&g.queueMutex);
-
- /* Signal the server that the new message has be queued, then
- ** block waiting for the server to process the message.
- */
- pthread_mutex_lock(&pMsg->clientMutex);
- pthread_cond_signal(&g.serverWakeup);
- while( pMsg->op!=MSG_Done ){
- pthread_cond_wait(&pMsg->clientWakeup, &pMsg->clientMutex);
- }
- pthread_mutex_unlock(&pMsg->clientMutex);
-
- /* Destroy the mutex and condition variable of the message.
- */
- pthread_mutex_destroy(&pMsg->clientMutex);
- pthread_cond_destroy(&pMsg->clientWakeup);
-}
-
-/*
-** The following 6 routines are client-side implementations of the
-** core SQLite interfaces:
-**
-** sqlite3_open
-** sqlite3_prepare
-** sqlite3_step
-** sqlite3_reset
-** sqlite3_finalize
-** sqlite3_close
-**
-** Clients should use the following client-side routines instead of
-** the core routines above.
-**
-** sqlite3_client_open
-** sqlite3_client_prepare
-** sqlite3_client_step
-** sqlite3_client_reset
-** sqlite3_client_finalize
-** sqlite3_client_close
-**
-** Each of these routines creates a message for the desired operation,
-** sends that message to the server, waits for the server to process
-** then message and return a response.
-*/
-int sqlite3_client_open(const char *zDatabaseName, sqlite3 **ppDb){
- SqlMessage msg;
- msg.op = MSG_Open;
- msg.zIn = zDatabaseName;
- sendToServer(&msg);
- *ppDb = msg.pDb;
- return msg.errCode;
-}
-int sqlite3_client_prepare(
- sqlite3 *pDb,
- const char *zSql,
- int nByte,
- sqlite3_stmt **ppStmt,
- const char **pzTail
-){
- SqlMessage msg;
- msg.op = MSG_Prepare;
- msg.pDb = pDb;
- msg.zIn = zSql;
- msg.nByte = nByte;
- sendToServer(&msg);
- *ppStmt = msg.pStmt;
- if( pzTail ) *pzTail = msg.zOut;
- return msg.errCode;
-}
-int sqlite3_client_step(sqlite3_stmt *pStmt){
- SqlMessage msg;
- msg.op = MSG_Step;
- msg.pStmt = pStmt;
- sendToServer(&msg);
- return msg.errCode;
-}
-int sqlite3_client_reset(sqlite3_stmt *pStmt){
- SqlMessage msg;
- msg.op = MSG_Reset;
- msg.pStmt = pStmt;
- sendToServer(&msg);
- return msg.errCode;
-}
-int sqlite3_client_finalize(sqlite3_stmt *pStmt){
- SqlMessage msg;
- msg.op = MSG_Finalize;
- msg.pStmt = pStmt;
- sendToServer(&msg);
- return msg.errCode;
-}
-int sqlite3_client_close(sqlite3 *pDb){
- SqlMessage msg;
- msg.op = MSG_Close;
- msg.pDb = pDb;
- sendToServer(&msg);
- return msg.errCode;
-}
-
-/*
-** This routine implements the server. To start the server, first
-** make sure g.serverHalt is false, then create a new detached thread
-** on this procedure. See the sqlite3_server_start() routine below
-** for an example. This procedure loops until g.serverHalt becomes
-** true.
-*/
-void *sqlite3_server(void *NotUsed){
- if( pthread_mutex_trylock(&g.serverMutex) ){
- return 0; /* Another server is already running */
- }
- sqlite3_enable_shared_cache(1);
- while( !g.serverHalt ){
- SqlMessage *pMsg;
-
- /* Remove the last message from the message queue.
- */
- pthread_mutex_lock(&g.queueMutex);
- while( g.pQueueTail==0 && g.serverHalt==0 ){
- pthread_cond_wait(&g.serverWakeup, &g.queueMutex);
- }
- pMsg = g.pQueueTail;
- if( pMsg ){
- if( pMsg->pPrev ){
- pMsg->pPrev->pNext = 0;
- }else{
- g.pQueueHead = 0;
- }
- g.pQueueTail = pMsg->pPrev;
- }
- pthread_mutex_unlock(&g.queueMutex);
- if( pMsg==0 ) break;
-
- /* Process the message just removed
- */
- pthread_mutex_lock(&pMsg->clientMutex);
- switch( pMsg->op ){
- case MSG_Open: {
- pMsg->errCode = sqlite3_open(pMsg->zIn, &pMsg->pDb);
- break;
- }
- case MSG_Prepare: {
- pMsg->errCode = sqlite3_prepare(pMsg->pDb, pMsg->zIn, pMsg->nByte,
- &pMsg->pStmt, &pMsg->zOut);
- break;
- }
- case MSG_Step: {
- pMsg->errCode = sqlite3_step(pMsg->pStmt);
- break;
- }
- case MSG_Reset: {
- pMsg->errCode = sqlite3_reset(pMsg->pStmt);
- break;
- }
- case MSG_Finalize: {
- pMsg->errCode = sqlite3_finalize(pMsg->pStmt);
- break;
- }
- case MSG_Close: {
- pMsg->errCode = sqlite3_close(pMsg->pDb);
- break;
- }
- }
-
- /* Signal the client that the message has been processed.
- */
- pMsg->op = MSG_Done;
- pthread_mutex_unlock(&pMsg->clientMutex);
- pthread_cond_signal(&pMsg->clientWakeup);
- }
- pthread_mutex_unlock(&g.serverMutex);
- return 0;
-}
-
-/*
-** Start a server thread if one is not already running. If there
-** is aleady a server thread running, the new thread will quickly
-** die and this routine is effectively a no-op.
-*/
-void sqlite3_server_start(void){
- pthread_t x;
- int rc;
- g.serverHalt = 0;
- rc = pthread_create(&x, 0, sqlite3_server, 0);
- if( rc==0 ){
- pthread_detach(x);
- }
-}
-
-/*
-** A wrapper around sqlite3_server() that decrements the int variable
-** pointed to by the first argument after the sqlite3_server() call
-** returns.
-*/
-static void *serverWrapper(void *pnDecr){
- void *p = sqlite3_server(0);
- (*(int*)pnDecr)--;
- return p;
-}
-
-/*
-** This function is the similar to sqlite3_server_start(), except that
-** the integer pointed to by the first argument is decremented when
-** the server thread exits.
-*/
-void sqlite3_server_start2(int *pnDecr){
- pthread_t x;
- int rc;
- g.serverHalt = 0;
- rc = pthread_create(&x, 0, serverWrapper, (void*)pnDecr);
- if( rc==0 ){
- pthread_detach(x);
- }
-}
-
-/*
-** If a server thread is running, then stop it. If no server is
-** running, this routine is effectively a no-op.
-**
-** This routine waits until the server has actually stopped before
-** returning.
-*/
-void sqlite3_server_stop(void){
- g.serverHalt = 1;
- pthread_cond_broadcast(&g.serverWakeup);
- pthread_mutex_lock(&g.serverMutex);
- pthread_mutex_unlock(&g.serverMutex);
-}
-
-#endif /* SQLITE_OS_UNIX && SQLITE_THREADSAFE */
-#endif /* defined(SQLITE_SERVER) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_sqllog.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_sqllog.c
deleted file mode 100644
index 9b207cf07ba..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_sqllog.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
-** 2012 November 26
-**
-** 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.
-**
-*************************************************************************
-**
-** OVERVIEW
-**
-** This file contains experimental code used to record data from live
-** SQLite applications that may be useful for offline analysis.
-** Specifically, this module can be used to capture the following
-** information:
-**
-** 1) The initial contents of all database files opened by the
-** application, and
-**
-** 2) All SQL statements executed by the application.
-**
-** The captured information can then be used to run (for example)
-** performance analysis looking for slow queries or to look for
-** optimization opportunities in either the application or in SQLite
-** itself.
-**
-** USAGE
-**
-** To use this module, SQLite must be compiled with the SQLITE_ENABLE_SQLLOG
-** pre-processor symbol defined and this file linked into the application.
-** One way to link this file into the application is to append the content
-** of this file onto the end of the "sqlite3.c" amalgamation and then
-** recompile the application as normal except with the addition of the
-** -DSQLITE_ENABLE_SQLLOG option.
-**
-** At runtime, logging is enabled by setting environment variable
-** SQLITE_SQLLOG_DIR to the name of a directory in which to store logged
-** data. The logging directory must already exist.
-**
-** Usually, if the application opens the same database file more than once
-** (either by attaching it or by using more than one database handle), only
-** a single copy is made. This behavior may be overridden (so that a
-** separate copy is taken each time the database file is opened or attached)
-** by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0.
-**
-** If the environment variable SQLITE_SQLLOG_CONDITIONAL is defined, then
-** logging is only done for database connections if a file named
-** "<database>-sqllog" exists in the same directly as the main database
-** file when it is first opened ("<database>" is replaced by the actual
-** name of the main database file).
-**
-** OUTPUT:
-**
-** The SQLITE_SQLLOG_DIR is populated with three types of files:
-**
-** sqllog_N.db - Copies of database files. N may be any integer.
-**
-** sqllog_N.sql - A list of SQL statements executed by a single
-** connection. N may be any integer.
-**
-** sqllog.idx - An index mapping from integer N to a database
-** file name - indicating the full path of the
-** database from which sqllog_N.db was copied.
-**
-** ERROR HANDLING:
-**
-** This module attempts to make a best effort to continue logging if an
-** IO or other error is encountered. For example, if a log file cannot
-** be opened logs are not collected for that connection, but other
-** logging proceeds as expected. Errors are logged by calling sqlite3_log().
-*/
-
-#ifndef _SQLITE3_H_
-#include "sqlite3.h"
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-static int getProcessId(void){
-#if SQLITE_OS_WIN
- return (int)_getpid();
-#else
- return (int)getpid();
-#endif
-}
-
-/* Names of environment variables to be used */
-#define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR"
-#define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES"
-#define ENVIRONMENT_VARIABLE3_NAME "SQLITE_SQLLOG_CONDITIONAL"
-
-/* Assume that all database and database file names are shorted than this. */
-#define SQLLOG_NAMESZ 512
-
-/* Maximum number of simultaneous database connections the process may
-** open (if any more are opened an error is logged using sqlite3_log()
-** and processing is halted).
-*/
-#define MAX_CONNECTIONS 256
-
-/* There is one instance of this object for each SQLite database connection
-** that is being logged.
-*/
-struct SLConn {
- int isErr; /* True if an error has occurred */
- sqlite3 *db; /* Connection handle */
- int iLog; /* First integer value used in file names */
- FILE *fd; /* File descriptor for log file */
-};
-
-/* This object is a singleton that keeps track of all data loggers.
-*/
-static struct SLGlobal {
- /* Protected by MUTEX_STATIC_MASTER */
- sqlite3_mutex *mutex; /* Recursive mutex */
- int nConn; /* Size of aConn[] array */
-
- /* Protected by SLGlobal.mutex */
- int bConditional; /* Only trace if *-sqllog file is present */
- int bReuse; /* True to avoid extra copies of db files */
- char zPrefix[SQLLOG_NAMESZ]; /* Prefix for all created files */
- char zIdx[SQLLOG_NAMESZ]; /* Full path to *.idx file */
- int iNextLog; /* Used to allocate file names */
- int iNextDb; /* Used to allocate database file names */
- int bRec; /* True if testSqllog() is called rec. */
- int iClock; /* Clock value */
- struct SLConn aConn[MAX_CONNECTIONS];
-} sqllogglobal;
-
-/*
-** Return true if c is an ASCII whitespace character.
-*/
-static int sqllog_isspace(char c){
- return (c==' ' || c=='\t' || c=='\n' || c=='\v' || c=='\f' || c=='\r');
-}
-
-/*
-** The first argument points to a nul-terminated string containing an SQL
-** command. Before returning, this function sets *pz to point to the start
-** of the first token in this command, and *pn to the number of bytes in
-** the token. This is used to check if the SQL command is an "ATTACH" or
-** not.
-*/
-static void sqllogTokenize(const char *z, const char **pz, int *pn){
- const char *p = z;
- int n;
-
- /* Skip past any whitespace */
- while( sqllog_isspace(*p) ){
- p++;
- }
-
- /* Figure out how long the first token is */
- *pz = p;
- n = 0;
- while( (p[n]>='a' && p[n]<='z') || (p[n]>='A' && p[n]<='Z') ) n++;
- *pn = n;
-}
-
-/*
-** Check if the logs directory already contains a copy of database file
-** zFile. If so, return a pointer to the full path of the copy. Otherwise,
-** return NULL.
-**
-** If a non-NULL value is returned, then the caller must arrange to
-** eventually free it using sqlite3_free().
-*/
-static char *sqllogFindFile(const char *zFile){
- char *zRet = 0;
- FILE *fd = 0;
-
- /* Open the index file for reading */
- fd = fopen(sqllogglobal.zIdx, "r");
- if( fd==0 ){
- sqlite3_log(SQLITE_IOERR, "sqllogFindFile(): error in fopen()");
- return 0;
- }
-
- /* Loop through each entry in the index file. If zFile is not NULL and the
- ** entry is a match, then set zRet to point to the filename of the existing
- ** copy and break out of the loop. */
- while( feof(fd)==0 ){
- char zLine[SQLLOG_NAMESZ*2+5];
- if( fgets(zLine, sizeof(zLine), fd) ){
- int n;
- char *z;
-
- zLine[sizeof(zLine)-1] = '\0';
- z = zLine;
- while( *z>='0' && *z<='9' ) z++;
- while( *z==' ' ) z++;
-
- n = strlen(z);
- while( n>0 && sqllog_isspace(z[n-1]) ) n--;
-
- if( n==strlen(zFile) && 0==memcmp(zFile, z, n) ){
- char zBuf[16];
- memset(zBuf, 0, sizeof(zBuf));
- z = zLine;
- while( *z>='0' && *z<='9' ){
- zBuf[z-zLine] = *z;
- z++;
- }
- zRet = sqlite3_mprintf("%s_%s.db", sqllogglobal.zPrefix, zBuf);
- break;
- }
- }
- }
-
- if( ferror(fd) ){
- sqlite3_log(SQLITE_IOERR, "sqllogFindFile(): error reading index file");
- }
-
- fclose(fd);
- return zRet;
-}
-
-static int sqllogFindAttached(
- sqlite3 *db, /* Database connection */
- const char *zSearch, /* Name to search for (or NULL) */
- char *zName, /* OUT: Name of attached database */
- char *zFile /* OUT: Name of attached file */
-){
- sqlite3_stmt *pStmt;
- int rc;
-
- /* The "PRAGMA database_list" command returns a list of databases in the
- ** order that they were attached. So a newly attached database is
- ** described by the last row returned. */
- assert( sqllogglobal.bRec==0 );
- sqllogglobal.bRec = 1;
- rc = sqlite3_prepare_v2(db, "PRAGMA database_list", -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- const char *zVal1; int nVal1;
- const char *zVal2; int nVal2;
-
- zVal1 = (const char*)sqlite3_column_text(pStmt, 1);
- nVal1 = sqlite3_column_bytes(pStmt, 1);
- if( zName ){
- memcpy(zName, zVal1, nVal1+1);
- }
-
- zVal2 = (const char*)sqlite3_column_text(pStmt, 2);
- nVal2 = sqlite3_column_bytes(pStmt, 2);
- memcpy(zFile, zVal2, nVal2+1);
-
- if( zSearch && strlen(zSearch)==nVal1
- && 0==sqlite3_strnicmp(zSearch, zVal1, nVal1)
- ){
- break;
- }
- }
- rc = sqlite3_finalize(pStmt);
- }
- sqllogglobal.bRec = 0;
-
- if( rc!=SQLITE_OK ){
- sqlite3_log(rc, "sqllogFindAttached(): error in \"PRAGMA database_list\"");
- }
- return rc;
-}
-
-
-/*
-** Parameter zSearch is the name of a database attached to the database
-** connection associated with the first argument. This function creates
-** a backup of this database in the logs directory.
-**
-** The name used for the backup file is automatically generated. Call
-** it zFile.
-**
-** If the bLog parameter is true, then a statement of the following form
-** is written to the log file associated with *p:
-**
-** ATTACH 'zFile' AS 'zName';
-**
-** Otherwise, if bLog is false, a comment is added to the log file:
-**
-** -- Main database file is 'zFile'
-**
-** The SLGlobal.mutex mutex is always held when this function is called.
-*/
-static void sqllogCopydb(struct SLConn *p, const char *zSearch, int bLog){
- char zName[SQLLOG_NAMESZ]; /* Attached database name */
- char zFile[SQLLOG_NAMESZ]; /* Database file name */
- char *zFree;
- char *zInit = 0;
- int rc;
-
- rc = sqllogFindAttached(p->db, zSearch, zName, zFile);
- if( rc!=SQLITE_OK ) return;
-
- if( zFile[0]=='\0' ){
- zInit = sqlite3_mprintf("");
- }else{
- if( sqllogglobal.bReuse ){
- zInit = sqllogFindFile(zFile);
- }else{
- zInit = 0;
- }
- if( zInit==0 ){
- int rc;
- sqlite3 *copy = 0;
- int iDb;
-
- /* Generate a file-name to use for the copy of this database */
- iDb = sqllogglobal.iNextDb++;
- zInit = sqlite3_mprintf("%s_%02d.db", sqllogglobal.zPrefix, iDb);
-
- /* Create the backup */
- assert( sqllogglobal.bRec==0 );
- sqllogglobal.bRec = 1;
- rc = sqlite3_open(zInit, &copy);
- if( rc==SQLITE_OK ){
- sqlite3_backup *pBak;
- sqlite3_exec(copy, "PRAGMA synchronous = 0", 0, 0, 0);
- pBak = sqlite3_backup_init(copy, "main", p->db, zName);
- if( pBak ){
- sqlite3_backup_step(pBak, -1);
- rc = sqlite3_backup_finish(pBak);
- }else{
- rc = sqlite3_errcode(copy);
- }
- sqlite3_close(copy);
- }
- sqllogglobal.bRec = 0;
-
- if( rc==SQLITE_OK ){
- /* Write an entry into the database index file */
- FILE *fd = fopen(sqllogglobal.zIdx, "a");
- if( fd ){
- fprintf(fd, "%d %s\n", iDb, zFile);
- fclose(fd);
- }
- }else{
- sqlite3_log(rc, "sqllogCopydb(): error backing up database");
- }
- }
- }
-
- if( bLog ){
- zFree = sqlite3_mprintf("ATTACH '%q' AS '%q'; -- clock=%d\n",
- zInit, zName, sqllogglobal.iClock++
- );
- }else{
- zFree = sqlite3_mprintf("-- Main database is '%q'\n", zInit);
- }
- fprintf(p->fd, "%s", zFree);
- sqlite3_free(zFree);
-
- sqlite3_free(zInit);
-}
-
-/*
-** If it is not already open, open the log file for connection *p.
-**
-** The SLGlobal.mutex mutex is always held when this function is called.
-*/
-static void sqllogOpenlog(struct SLConn *p){
- /* If the log file has not yet been opened, open it now. */
- if( p->fd==0 ){
- char *zLog;
-
- /* If it is still NULL, have global.zPrefix point to a copy of
- ** environment variable $ENVIRONMENT_VARIABLE1_NAME. */
- if( sqllogglobal.zPrefix[0]==0 ){
- FILE *fd;
- char *zVar = getenv(ENVIRONMENT_VARIABLE1_NAME);
- if( zVar==0 || strlen(zVar)+10>=(sizeof(sqllogglobal.zPrefix)) ) return;
- sqlite3_snprintf(sizeof(sqllogglobal.zPrefix), sqllogglobal.zPrefix,
- "%s/sqllog_%05d", zVar, getProcessId());
- sqlite3_snprintf(sizeof(sqllogglobal.zIdx), sqllogglobal.zIdx,
- "%s.idx", sqllogglobal.zPrefix);
- if( getenv(ENVIRONMENT_VARIABLE2_NAME) ){
- sqllogglobal.bReuse = atoi(getenv(ENVIRONMENT_VARIABLE2_NAME));
- }
- fd = fopen(sqllogglobal.zIdx, "w");
- if( fd ) fclose(fd);
- }
-
- /* Open the log file */
- zLog = sqlite3_mprintf("%s_%05d.sql", sqllogglobal.zPrefix, p->iLog);
- p->fd = fopen(zLog, "w");
- sqlite3_free(zLog);
- if( p->fd==0 ){
- sqlite3_log(SQLITE_IOERR, "sqllogOpenlog(): Failed to open log file");
- }
- }
-}
-
-/*
-** This function is called if the SQLLOG callback is invoked to report
-** execution of an SQL statement. Parameter p is the connection the statement
-** was executed by and parameter zSql is the text of the statement itself.
-*/
-static void testSqllogStmt(struct SLConn *p, const char *zSql){
- const char *zFirst; /* Pointer to first token in zSql */
- int nFirst; /* Size of token zFirst in bytes */
-
- sqllogTokenize(zSql, &zFirst, &nFirst);
- if( nFirst!=6 || 0!=sqlite3_strnicmp("ATTACH", zFirst, 6) ){
- /* Not an ATTACH statement. Write this directly to the log. */
- fprintf(p->fd, "%s; -- clock=%d\n", zSql, sqllogglobal.iClock++);
- }else{
- /* This is an ATTACH statement. Copy the database. */
- sqllogCopydb(p, 0, 1);
- }
-}
-
-/*
-** The database handle passed as the only argument has just been opened.
-** Return true if this module should log initial databases and SQL
-** statements for this connection, or false otherwise.
-**
-** If an error occurs, sqlite3_log() is invoked to report it to the user
-** and zero returned.
-*/
-static int sqllogTraceDb(sqlite3 *db){
- int bRet = 1;
- if( sqllogglobal.bConditional ){
- char zFile[SQLLOG_NAMESZ]; /* Attached database name */
- int rc = sqllogFindAttached(db, "main", 0, zFile);
- if( rc==SQLITE_OK ){
- int nFile = strlen(zFile);
- if( (SQLLOG_NAMESZ-nFile)<8 ){
- sqlite3_log(SQLITE_IOERR,
- "sqllogTraceDb(): database name too long (%d bytes)", nFile
- );
- bRet = 0;
- }else{
- memcpy(&zFile[nFile], "-sqllog", 8);
- bRet = !access(zFile, F_OK);
- }
- }
- }
- return bRet;
-}
-
-/*
-** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog().
-**
-** The eType parameter has the following values:
-**
-** 0: Opening a new database connection. zSql is the name of the
-** file being opened. db is a pointer to the newly created database
-** connection.
-**
-** 1: An SQL statement has run to completion. zSql is the text of the
-** SQL statement with all parameters expanded to their actual values.
-**
-** 2: Closing a database connection. zSql is NULL. The db pointer to
-** the database connection being closed has already been shut down
-** and cannot be used for any further SQL.
-**
-** The pCtx parameter is a copy of the pointer that was originally passed
-** into the sqlite3_config(SQLITE_CONFIG_SQLLOG) statement. In this
-** particular implementation, pCtx is always a pointer to the
-** sqllogglobal global variable define above.
-*/
-static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
- struct SLConn *p = 0;
- sqlite3_mutex *master = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
-
- assert( eType==0 || eType==1 || eType==2 );
- assert( (eType==2)==(zSql==0) );
-
- /* This is a database open command. */
- if( eType==0 ){
- sqlite3_mutex_enter(master);
- if( sqllogglobal.mutex==0 ){
- sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
- }
- sqlite3_mutex_leave(master);
-
- sqlite3_mutex_enter(sqllogglobal.mutex);
- if( sqllogglobal.bRec==0 && sqllogTraceDb(db) ){
-
- sqlite3_mutex_enter(master);
- p = &sqllogglobal.aConn[sqllogglobal.nConn++];
- p->fd = 0;
- p->db = db;
- p->iLog = sqllogglobal.iNextLog++;
- sqlite3_mutex_leave(master);
-
- /* Open the log and take a copy of the main database file */
- sqllogOpenlog(p);
- if( p->fd ) sqllogCopydb(p, "main", 0);
- }
- sqlite3_mutex_leave(sqllogglobal.mutex);
- }
-
- else{
-
- int i;
- for(i=0; i<sqllogglobal.nConn; i++){
- p = &sqllogglobal.aConn[i];
- if( p->db==db ) break;
- }
-
- /* A database handle close command */
- if( eType==2 ){
- sqlite3_mutex_enter(master);
- if( i<sqllogglobal.nConn ){
- if( p->fd ) fclose(p->fd);
- p->db = 0;
- p->fd = 0;
- sqllogglobal.nConn--;
- }
-
- if( sqllogglobal.nConn==0 ){
- sqlite3_mutex_free(sqllogglobal.mutex);
- sqllogglobal.mutex = 0;
- }else if( i<sqllogglobal.nConn ){
- int nShift = &sqllogglobal.aConn[sqllogglobal.nConn] - p;
- if( nShift>0 ){
- memmove(p, &p[1], nShift*sizeof(struct SLConn));
- }
- }
- sqlite3_mutex_leave(master);
-
- /* An ordinary SQL command. */
- }else if( i<sqllogglobal.nConn && p->fd ){
- sqlite3_mutex_enter(sqllogglobal.mutex);
- if( sqllogglobal.bRec==0 ){
- testSqllogStmt(p, zSql);
- }
- sqlite3_mutex_leave(sqllogglobal.mutex);
- }
- }
-}
-
-/*
-** This function is called either before sqlite3_initialized() or by it.
-** It checks if the SQLITE_SQLLOG_DIR variable is defined, and if so
-** registers an SQLITE_CONFIG_SQLLOG callback to record the applications
-** database activity.
-*/
-void sqlite3_init_sqllog(void){
- if( getenv(ENVIRONMENT_VARIABLE1_NAME) ){
- if( SQLITE_OK==sqlite3_config(SQLITE_CONFIG_SQLLOG, testSqllog, 0) ){
- memset(&sqllogglobal, 0, sizeof(sqllogglobal));
- sqllogglobal.bReuse = 1;
- if( getenv(ENVIRONMENT_VARIABLE3_NAME) ){
- sqllogglobal.bConditional = 1;
- }
- }
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_superlock.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_superlock.c
deleted file mode 100644
index 45d0d623a03..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_superlock.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
-** 2010 November 19
-**
-** 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.
-**
-*************************************************************************
-** Example code for obtaining an exclusive lock on an SQLite database
-** file. This method is complicated, but works for both WAL and rollback
-** mode database files. The interface to the example code in this file
-** consists of the following two functions:
-**
-** sqlite3demo_superlock()
-** sqlite3demo_superunlock()
-*/
-
-#include "sqlite3.h"
-#include <string.h> /* memset(), strlen() */
-#include <assert.h> /* assert() */
-
-/*
-** A structure to collect a busy-handler callback and argument and a count
-** of the number of times it has been invoked.
-*/
-struct SuperlockBusy {
- int (*xBusy)(void*,int); /* Pointer to busy-handler function */
- void *pBusyArg; /* First arg to pass to xBusy */
- int nBusy; /* Number of times xBusy has been invoked */
-};
-typedef struct SuperlockBusy SuperlockBusy;
-
-/*
-** An instance of the following structure is allocated for each active
-** superlock. The opaque handle returned by sqlite3demo_superlock() is
-** actually a pointer to an instance of this structure.
-*/
-struct Superlock {
- sqlite3 *db; /* Database handle used to lock db */
- int bWal; /* True if db is a WAL database */
-};
-typedef struct Superlock Superlock;
-
-/*
-** The pCtx pointer passed to this function is actually a pointer to a
-** SuperlockBusy structure. Invoke the busy-handler function encapsulated
-** by the structure and return the result.
-*/
-static int superlockBusyHandler(void *pCtx, int UNUSED){
- SuperlockBusy *pBusy = (SuperlockBusy *)pCtx;
- if( pBusy->xBusy==0 ) return 0;
- return pBusy->xBusy(pBusy->pBusyArg, pBusy->nBusy++);
-}
-
-/*
-** This function is used to determine if the main database file for
-** connection db is open in WAL mode or not. If no error occurs and the
-** database file is in WAL mode, set *pbWal to true and return SQLITE_OK.
-** If it is not in WAL mode, set *pbWal to false.
-**
-** If an error occurs, return an SQLite error code. The value of *pbWal
-** is undefined in this case.
-*/
-static int superlockIsWal(Superlock *pLock){
- int rc; /* Return Code */
- sqlite3_stmt *pStmt; /* Compiled PRAGMA journal_mode statement */
-
- rc = sqlite3_prepare(pLock->db, "PRAGMA main.journal_mode", -1, &pStmt, 0);
- if( rc!=SQLITE_OK ) return rc;
-
- pLock->bWal = 0;
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- const char *zMode = (const char *)sqlite3_column_text(pStmt, 0);
- if( zMode && strlen(zMode)==3 && sqlite3_strnicmp("wal", zMode, 3)==0 ){
- pLock->bWal = 1;
- }
- }
-
- return sqlite3_finalize(pStmt);
-}
-
-/*
-** Obtain an exclusive shm-lock on nByte bytes starting at offset idx
-** of the file fd. If the lock cannot be obtained immediately, invoke
-** the busy-handler until either it is obtained or the busy-handler
-** callback returns 0.
-*/
-static int superlockShmLock(
- sqlite3_file *fd, /* Database file handle */
- int idx, /* Offset of shm-lock to obtain */
- int nByte, /* Number of consective bytes to lock */
- SuperlockBusy *pBusy /* Busy-handler wrapper object */
-){
- int rc;
- int (*xShmLock)(sqlite3_file*, int, int, int) = fd->pMethods->xShmLock;
- do {
- rc = xShmLock(fd, idx, nByte, SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE);
- }while( rc==SQLITE_BUSY && superlockBusyHandler((void *)pBusy, 0) );
- return rc;
-}
-
-/*
-** Obtain the extra locks on the database file required for WAL databases.
-** Invoke the supplied busy-handler as required.
-*/
-static int superlockWalLock(
- sqlite3 *db, /* Database handle open on WAL database */
- SuperlockBusy *pBusy /* Busy handler wrapper object */
-){
- int rc; /* Return code */
- sqlite3_file *fd = 0; /* Main database file handle */
- void volatile *p = 0; /* Pointer to first page of shared memory */
-
- /* Obtain a pointer to the sqlite3_file object open on the main db file. */
- rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Obtain the "recovery" lock. Normally, this lock is only obtained by
- ** clients running database recovery.
- */
- rc = superlockShmLock(fd, 2, 1, pBusy);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Zero the start of the first shared-memory page. This means that any
- ** clients that open read or write transactions from this point on will
- ** have to run recovery before proceeding. Since they need the "recovery"
- ** lock that this process is holding to do that, no new read or write
- ** transactions may now be opened. Nor can a checkpoint be run, for the
- ** same reason.
- */
- rc = fd->pMethods->xShmMap(fd, 0, 32*1024, 1, &p);
- if( rc!=SQLITE_OK ) return rc;
- memset((void *)p, 0, 32);
-
- /* Obtain exclusive locks on all the "read-lock" slots. Once these locks
- ** are held, it is guaranteed that there are no active reader, writer or
- ** checkpointer clients.
- */
- rc = superlockShmLock(fd, 3, SQLITE_SHM_NLOCK-3, pBusy);
- return rc;
-}
-
-/*
-** Release a superlock held on a database file. The argument passed to
-** this function must have been obtained from a successful call to
-** sqlite3demo_superlock().
-*/
-void sqlite3demo_superunlock(void *pLock){
- Superlock *p = (Superlock *)pLock;
- if( p->bWal ){
- int rc; /* Return code */
- int flags = SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE;
- sqlite3_file *fd = 0;
- rc = sqlite3_file_control(p->db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd);
- if( rc==SQLITE_OK ){
- fd->pMethods->xShmLock(fd, 2, 1, flags);
- fd->pMethods->xShmLock(fd, 3, SQLITE_SHM_NLOCK-3, flags);
- }
- }
- sqlite3_close(p->db);
- sqlite3_free(p);
-}
-
-/*
-** Obtain a superlock on the database file identified by zPath, using the
-** locking primitives provided by VFS zVfs. If successful, SQLITE_OK is
-** returned and output variable *ppLock is populated with an opaque handle
-** that may be used with sqlite3demo_superunlock() to release the lock.
-**
-** If an error occurs, *ppLock is set to 0 and an SQLite error code
-** (e.g. SQLITE_BUSY) is returned.
-**
-** If a required lock cannot be obtained immediately and the xBusy parameter
-** to this function is not NULL, then xBusy is invoked in the same way
-** as a busy-handler registered with SQLite (using sqlite3_busy_handler())
-** until either the lock can be obtained or the busy-handler function returns
-** 0 (indicating "give up").
-*/
-int sqlite3demo_superlock(
- const char *zPath, /* Path to database file to lock */
- const char *zVfs, /* VFS to use to access database file */
- int (*xBusy)(void*,int), /* Busy handler callback */
- void *pBusyArg, /* Context arg for busy handler */
- void **ppLock /* OUT: Context to pass to superunlock() */
-){
- SuperlockBusy busy = {0, 0, 0}; /* Busy handler wrapper object */
- int rc; /* Return code */
- Superlock *pLock;
-
- pLock = sqlite3_malloc(sizeof(Superlock));
- if( !pLock ) return SQLITE_NOMEM;
- memset(pLock, 0, sizeof(Superlock));
-
- /* Open a database handle on the file to superlock. */
- rc = sqlite3_open_v2(
- zPath, &pLock->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs
- );
-
- /* Install a busy-handler and execute a BEGIN EXCLUSIVE. If this is not
- ** a WAL database, this is all we need to do.
- **
- ** A wrapper function is used to invoke the busy-handler instead of
- ** registering the busy-handler function supplied by the user directly
- ** with SQLite. This is because the same busy-handler function may be
- ** invoked directly later on when attempting to obtain the extra locks
- ** required in WAL mode. By using the wrapper, we are able to guarantee
- ** that the "nBusy" integer parameter passed to the users busy-handler
- ** represents the total number of busy-handler invocations made within
- ** this call to sqlite3demo_superlock(), including any made during the
- ** "BEGIN EXCLUSIVE".
- */
- if( rc==SQLITE_OK ){
- busy.xBusy = xBusy;
- busy.pBusyArg = pBusyArg;
- sqlite3_busy_handler(pLock->db, superlockBusyHandler, (void *)&busy);
- rc = sqlite3_exec(pLock->db, "BEGIN EXCLUSIVE", 0, 0, 0);
- }
-
- /* If the BEGIN EXCLUSIVE was executed successfully and this is a WAL
- ** database, call superlockWalLock() to obtain the extra locks required
- ** to prevent readers, writers and/or checkpointers from accessing the
- ** db while this process is holding the superlock.
- **
- ** Before attempting any WAL locks, commit the transaction started above
- ** to drop the WAL read and write locks currently held. Otherwise, the
- ** new WAL locks may conflict with the old.
- */
- if( rc==SQLITE_OK ){
- if( SQLITE_OK==(rc = superlockIsWal(pLock)) && pLock->bWal ){
- rc = sqlite3_exec(pLock->db, "COMMIT", 0, 0, 0);
- if( rc==SQLITE_OK ){
- rc = superlockWalLock(pLock->db, &busy);
- }
- }
- }
-
- if( rc!=SQLITE_OK ){
- sqlite3demo_superunlock(pLock);
- *ppLock = 0;
- }else{
- *ppLock = pLock;
- }
-
- return rc;
-}
-
-/*
-** End of example code. Everything below here is the test harness.
-**************************************************************************
-**************************************************************************
-*************************************************************************/
-
-
-#ifdef SQLITE_TEST
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-struct InterpAndScript {
- Tcl_Interp *interp;
- Tcl_Obj *pScript;
-};
-typedef struct InterpAndScript InterpAndScript;
-
-static void SQLITE_TCLAPI superunlock_del(ClientData cd){
- sqlite3demo_superunlock((void *)cd);
-}
-
-static int SQLITE_TCLAPI superunlock_cmd(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
- return TCL_ERROR;
- }
- Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
- return TCL_OK;
-}
-
-static int superlock_busy(void *pCtx, int nBusy){
- InterpAndScript *p = (InterpAndScript *)pCtx;
- Tcl_Obj *pEval; /* Script to evaluate */
- int iVal = 0; /* Value to return */
-
- pEval = Tcl_DuplicateObj(p->pScript);
- Tcl_IncrRefCount(pEval);
- Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(nBusy));
- Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
- Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iVal);
- Tcl_DecrRefCount(pEval);
-
- return iVal;
-}
-
-/*
-** Tclcmd: sqlite3demo_superlock CMDNAME PATH VFS BUSY-HANDLER-SCRIPT
-*/
-static int SQLITE_TCLAPI superlock_cmd(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- void *pLock; /* Lock context */
- char *zPath;
- char *zVfs = 0;
- InterpAndScript busy = {0, 0};
- int (*xBusy)(void*,int) = 0; /* Busy handler callback */
- int rc; /* Return code from sqlite3demo_superlock() */
-
- if( objc<3 || objc>5 ){
- Tcl_WrongNumArgs(
- interp, 1, objv, "CMDNAME PATH ?VFS? ?BUSY-HANDLER-SCRIPT?");
- return TCL_ERROR;
- }
-
- zPath = Tcl_GetString(objv[2]);
-
- if( objc>3 ){
- zVfs = Tcl_GetString(objv[3]);
- if( strlen(zVfs)==0 ) zVfs = 0;
- }
- if( objc>4 ){
- busy.interp = interp;
- busy.pScript = objv[4];
- xBusy = superlock_busy;
- }
-
- rc = sqlite3demo_superlock(zPath, zVfs, xBusy, &busy, &pLock);
- assert( rc==SQLITE_OK || pLock==0 );
- assert( rc!=SQLITE_OK || pLock!=0 );
-
- if( rc!=SQLITE_OK ){
- extern const char *sqlite3ErrStr(int);
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
- return TCL_ERROR;
- }
-
- Tcl_CreateObjCommand(
- interp, Tcl_GetString(objv[1]), superunlock_cmd, pLock, superunlock_del
- );
- Tcl_SetObjResult(interp, objv[1]);
- return TCL_OK;
-}
-
-int SqliteSuperlock_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "sqlite3demo_superlock", superlock_cmd, 0, 0);
- return TCL_OK;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_syscall.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_syscall.c
deleted file mode 100644
index 947f9a9d9d0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_syscall.c
+++ /dev/null
@@ -1,765 +0,0 @@
-/*
-** 2011 March 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.
-**
-*************************************************************************
-**
-** The code in this file implements a Tcl interface used to test error
-** handling in the os_unix.c module. Wrapper functions that support fault
-** injection are registered as the low-level OS functions using the
-** xSetSystemCall() method of the VFS. The Tcl interface is as follows:
-**
-**
-** test_syscall install LIST
-** Install wrapper functions for all system calls in argument LIST.
-** LIST must be a list consisting of zero or more of the following
-** literal values:
-**
-** open close access getcwd stat fstat
-** ftruncate fcntl read pread pread64 write
-** pwrite pwrite64 fchmod fallocate mmap
-**
-** test_syscall uninstall
-** Uninstall all wrapper functions.
-**
-** test_syscall fault ?COUNT PERSIST?
-** If [test_syscall fault] is invoked without the two arguments, fault
-** injection is disabled. Otherwise, fault injection is configured to
-** cause a failure on the COUNT'th next call to a system call with a
-** wrapper function installed. A COUNT value of 1 means fail the next
-** system call.
-**
-** Argument PERSIST is interpreted as a boolean. If true, the all
-** system calls following the initial failure also fail. Otherwise, only
-** the single transient failure is injected.
-**
-** test_syscall errno CALL ERRNO
-** Set the value that the global "errno" is set to following a fault
-** in call CALL. Argument CALL must be one of the system call names
-** listed above (under [test_syscall install]). ERRNO is a symbolic
-** name (i.e. "EACCES"). Not all errno codes are supported. Add extra
-** to the aErrno table in function test_syscall_errno() below as
-** required.
-**
-** test_syscall reset ?SYSTEM-CALL?
-** With no argument, this is an alias for the [uninstall] command. However,
-** this command uses a VFS call of the form:
-**
-** xSetSystemCall(pVfs, 0, 0);
-**
-** To restore the default system calls. The [uninstall] command restores
-** each system call individually by calling (i.e.):
-**
-** xSetSystemCall(pVfs, "open", 0);
-**
-** With an argument, this command attempts to reset the system call named
-** by the parameter using the same method as [uninstall].
-**
-** test_syscall exists SYSTEM-CALL
-** Return true if the named system call exists. Or false otherwise.
-**
-** test_syscall list
-** Return a list of all system calls. The list is constructed using
-** the xNextSystemCall() VFS method.
-**
-** test_syscall pagesize PGSZ
-** If PGSZ is a power of two greater than 256, install a wrapper around
-** OS function getpagesize() that reports the system page size as PGSZ.
-** Or, if PGSZ is less than zero, remove any wrapper already installed.
-*/
-
-#include "sqliteInt.h"
-#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#if SQLITE_OS_UNIX
-
-/* From main.c */
-extern const char *sqlite3ErrName(int);
-
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <errno.h>
-
-static struct TestSyscallGlobal {
- int bPersist; /* 1 for persistent errors, 0 for transient */
- int nCount; /* Fail after this many more calls */
- int nFail; /* Number of failures that have occurred */
- int pgsz;
- sqlite3_syscall_ptr orig_getpagesize;
-} gSyscall = { 0, 0, 0, 0, 0 };
-
-static int ts_open(const char *, int, int);
-static int ts_close(int fd);
-static int ts_access(const char *zPath, int mode);
-static char *ts_getcwd(char *zPath, size_t nPath);
-static int ts_stat(const char *zPath, struct stat *p);
-static int ts_fstat(int fd, struct stat *p);
-static int ts_ftruncate(int fd, off_t n);
-static int ts_fcntl(int fd, int cmd, ... );
-static int ts_read(int fd, void *aBuf, size_t nBuf);
-static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
-/* Note: pread64() and pwrite64() actually use off64_t as the type on their
-** last parameter. But that datatype is not defined on many systems
-** (ex: Mac, OpenBSD). So substitute a likely equivalent: sqlite3_uint64 */
-static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off);
-static int ts_write(int fd, const void *aBuf, size_t nBuf);
-static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
-static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off);
-static int ts_fchmod(int fd, mode_t mode);
-static int ts_fallocate(int fd, off_t off, off_t len);
-static void *ts_mmap(void *, size_t, int, int, int, off_t);
-static void *ts_mremap(void*, size_t, size_t, int, ...);
-
-struct TestSyscallArray {
- const char *zName;
- sqlite3_syscall_ptr xTest;
- sqlite3_syscall_ptr xOrig;
- int default_errno; /* Default value for errno following errors */
- int custom_errno; /* Current value for errno if error */
-} aSyscall[] = {
- /* 0 */ { "open", (sqlite3_syscall_ptr)ts_open, 0, EACCES, 0 },
- /* 1 */ { "close", (sqlite3_syscall_ptr)ts_close, 0, 0, 0 },
- /* 2 */ { "access", (sqlite3_syscall_ptr)ts_access, 0, 0, 0 },
- /* 3 */ { "getcwd", (sqlite3_syscall_ptr)ts_getcwd, 0, 0, 0 },
- /* 4 */ { "stat", (sqlite3_syscall_ptr)ts_stat, 0, 0, 0 },
- /* 5 */ { "fstat", (sqlite3_syscall_ptr)ts_fstat, 0, 0, 0 },
- /* 6 */ { "ftruncate", (sqlite3_syscall_ptr)ts_ftruncate, 0, EIO, 0 },
- /* 7 */ { "fcntl", (sqlite3_syscall_ptr)ts_fcntl, 0, EACCES, 0 },
- /* 8 */ { "read", (sqlite3_syscall_ptr)ts_read, 0, 0, 0 },
- /* 9 */ { "pread", (sqlite3_syscall_ptr)ts_pread, 0, 0, 0 },
- /* 10 */ { "pread64", (sqlite3_syscall_ptr)ts_pread64, 0, 0, 0 },
- /* 11 */ { "write", (sqlite3_syscall_ptr)ts_write, 0, 0, 0 },
- /* 12 */ { "pwrite", (sqlite3_syscall_ptr)ts_pwrite, 0, 0, 0 },
- /* 13 */ { "pwrite64", (sqlite3_syscall_ptr)ts_pwrite64, 0, 0, 0 },
- /* 14 */ { "fchmod", (sqlite3_syscall_ptr)ts_fchmod, 0, 0, 0 },
- /* 15 */ { "fallocate", (sqlite3_syscall_ptr)ts_fallocate, 0, 0, 0 },
- /* 16 */ { "mmap", (sqlite3_syscall_ptr)ts_mmap, 0, 0, 0 },
- /* 17 */ { "mremap", (sqlite3_syscall_ptr)ts_mremap, 0, 0, 0 },
- { 0, 0, 0, 0, 0 }
-};
-
-#define orig_open ((int(*)(const char *, int, int))aSyscall[0].xOrig)
-#define orig_close ((int(*)(int))aSyscall[1].xOrig)
-#define orig_access ((int(*)(const char*,int))aSyscall[2].xOrig)
-#define orig_getcwd ((char*(*)(char*,size_t))aSyscall[3].xOrig)
-#define orig_stat ((int(*)(const char*,struct stat*))aSyscall[4].xOrig)
-#define orig_fstat ((int(*)(int,struct stat*))aSyscall[5].xOrig)
-#define orig_ftruncate ((int(*)(int,off_t))aSyscall[6].xOrig)
-#define orig_fcntl ((int(*)(int,int,...))aSyscall[7].xOrig)
-#define orig_read ((ssize_t(*)(int,void*,size_t))aSyscall[8].xOrig)
-#define orig_pread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].xOrig)
-#define orig_pread64 ((ssize_t(*)(int,void*,size_t,sqlite3_uint64))aSyscall[10].xOrig)
-#define orig_write ((ssize_t(*)(int,const void*,size_t))aSyscall[11].xOrig)
-#define orig_pwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
- aSyscall[12].xOrig)
-#define orig_pwrite64 ((ssize_t(*)(int,const void*,size_t,sqlite3_uint64))\
- aSyscall[13].xOrig)
-#define orig_fchmod ((int(*)(int,mode_t))aSyscall[14].xOrig)
-#define orig_fallocate ((int(*)(int,off_t,off_t))aSyscall[15].xOrig)
-#define orig_mmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[16].xOrig)
-#define orig_mremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[17].xOrig)
-
-/*
-** This function is called exactly once from within each invocation of a
-** system call wrapper in this file. It returns 1 if the function should
-** fail, or 0 if it should succeed.
-*/
-static int tsIsFail(void){
- gSyscall.nCount--;
- if( gSyscall.nCount==0 || (gSyscall.nFail && gSyscall.bPersist) ){
- gSyscall.nFail++;
- return 1;
- }
- return 0;
-}
-
-/*
-** Return the current error-number value for function zFunc. zFunc must be
-** the name of a system call in the aSyscall[] table.
-**
-** Usually, the current error-number is the value that errno should be set
-** to if the named system call fails. The exception is "fallocate". See
-** comments above the implementation of ts_fallocate() for details.
-*/
-static int tsErrno(const char *zFunc){
- int i;
- int nFunc = strlen(zFunc);
- for(i=0; aSyscall[i].zName; i++){
- if( strlen(aSyscall[i].zName)!=nFunc ) continue;
- if( memcmp(aSyscall[i].zName, zFunc, nFunc) ) continue;
- return aSyscall[i].custom_errno;
- }
-
- assert(0);
- return 0;
-}
-
-/*
-** A wrapper around tsIsFail(). If tsIsFail() returns non-zero, set the
-** value of errno before returning.
-*/
-static int tsIsFailErrno(const char *zFunc){
- if( tsIsFail() ){
- errno = tsErrno(zFunc);
- return 1;
- }
- return 0;
-}
-
-/*
-** A wrapper around open().
-*/
-static int ts_open(const char *zFile, int flags, int mode){
- if( tsIsFailErrno("open") ){
- return -1;
- }
- return orig_open(zFile, flags, mode);
-}
-
-/*
-** A wrapper around close().
-*/
-static int ts_close(int fd){
- if( tsIsFail() ){
- /* Even if simulating an error, close the original file-descriptor.
- ** This is to stop the test process from running out of file-descriptors
- ** when running a long test. If a call to close() appears to fail, SQLite
- ** never attempts to use the file-descriptor afterwards (or even to close
- ** it a second time). */
- orig_close(fd);
- return -1;
- }
- return orig_close(fd);
-}
-
-/*
-** A wrapper around access().
-*/
-static int ts_access(const char *zPath, int mode){
- if( tsIsFail() ){
- return -1;
- }
- return orig_access(zPath, mode);
-}
-
-/*
-** A wrapper around getcwd().
-*/
-static char *ts_getcwd(char *zPath, size_t nPath){
- if( tsIsFail() ){
- return NULL;
- }
- return orig_getcwd(zPath, nPath);
-}
-
-/*
-** A wrapper around stat().
-*/
-static int ts_stat(const char *zPath, struct stat *p){
- if( tsIsFail() ){
- return -1;
- }
- return orig_stat(zPath, p);
-}
-
-/*
-** A wrapper around fstat().
-*/
-static int ts_fstat(int fd, struct stat *p){
- if( tsIsFailErrno("fstat") ){
- return -1;
- }
- return orig_fstat(fd, p);
-}
-
-/*
-** A wrapper around ftruncate().
-*/
-static int ts_ftruncate(int fd, off_t n){
- if( tsIsFailErrno("ftruncate") ){
- return -1;
- }
- return orig_ftruncate(fd, n);
-}
-
-/*
-** A wrapper around fcntl().
-*/
-static int ts_fcntl(int fd, int cmd, ... ){
- va_list ap;
- void *pArg;
- if( tsIsFailErrno("fcntl") ){
- return -1;
- }
- va_start(ap, cmd);
- pArg = va_arg(ap, void *);
- return orig_fcntl(fd, cmd, pArg);
-}
-
-/*
-** A wrapper around read().
-*/
-static int ts_read(int fd, void *aBuf, size_t nBuf){
- if( tsIsFailErrno("read") ){
- return -1;
- }
- return orig_read(fd, aBuf, nBuf);
-}
-
-/*
-** A wrapper around pread().
-*/
-static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
- if( tsIsFailErrno("pread") ){
- return -1;
- }
- return orig_pread(fd, aBuf, nBuf, off);
-}
-
-/*
-** A wrapper around pread64().
-*/
-static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off){
- if( tsIsFailErrno("pread64") ){
- return -1;
- }
- return orig_pread64(fd, aBuf, nBuf, off);
-}
-
-/*
-** A wrapper around write().
-*/
-static int ts_write(int fd, const void *aBuf, size_t nBuf){
- if( tsIsFailErrno("write") ){
- if( tsErrno("write")==EINTR ) orig_write(fd, aBuf, nBuf/2);
- return -1;
- }
- return orig_write(fd, aBuf, nBuf);
-}
-
-/*
-** A wrapper around pwrite().
-*/
-static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
- if( tsIsFailErrno("pwrite") ){
- return -1;
- }
- return orig_pwrite(fd, aBuf, nBuf, off);
-}
-
-/*
-** A wrapper around pwrite64().
-*/
-static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off){
- if( tsIsFailErrno("pwrite64") ){
- return -1;
- }
- return orig_pwrite64(fd, aBuf, nBuf, off);
-}
-
-/*
-** A wrapper around fchmod().
-*/
-static int ts_fchmod(int fd, mode_t mode){
- if( tsIsFail() ){
- return -1;
- }
- return orig_fchmod(fd, mode);
-}
-
-/*
-** A wrapper around fallocate().
-**
-** SQLite assumes that the fallocate() function is compatible with
-** posix_fallocate(). According to the Linux man page (2009-09-30):
-**
-** posix_fallocate() returns zero on success, or an error number on
-** failure. Note that errno is not set.
-*/
-static int ts_fallocate(int fd, off_t off, off_t len){
- if( tsIsFail() ){
- return tsErrno("fallocate");
- }
- return orig_fallocate(fd, off, len);
-}
-
-static void *ts_mmap(
- void *pAddr,
- size_t nByte,
- int prot,
- int flags,
- int fd,
- off_t iOff
-){
- if( tsIsFailErrno("mmap") ){
- return MAP_FAILED;
- }
- return orig_mmap(pAddr, nByte, prot, flags, fd, iOff);
-}
-
-static void *ts_mremap(void *a, size_t b, size_t c, int d, ...){
- va_list ap;
- void *pArg;
- if( tsIsFailErrno("mremap") ){
- return MAP_FAILED;
- }
- va_start(ap, d);
- pArg = va_arg(ap, void *);
- return orig_mremap(a, b, c, d, pArg);
-}
-
-static int SQLITE_TCLAPI test_syscall_install(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_vfs *pVfs;
- int nElem;
- int i;
- Tcl_Obj **apElem;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "SYSCALL-LIST");
- return TCL_ERROR;
- }
- if( Tcl_ListObjGetElements(interp, objv[2], &nElem, &apElem) ){
- return TCL_ERROR;
- }
- pVfs = sqlite3_vfs_find(0);
-
- for(i=0; i<nElem; i++){
- int iCall;
- int rc = Tcl_GetIndexFromObjStruct(interp,
- apElem[i], aSyscall, sizeof(aSyscall[0]), "system-call", 0, &iCall
- );
- if( rc ) return rc;
- if( aSyscall[iCall].xOrig==0 ){
- aSyscall[iCall].xOrig = pVfs->xGetSystemCall(pVfs, aSyscall[iCall].zName);
- pVfs->xSetSystemCall(pVfs, aSyscall[iCall].zName, aSyscall[iCall].xTest);
- }
- aSyscall[iCall].custom_errno = aSyscall[iCall].default_errno;
- }
-
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_syscall_uninstall(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_vfs *pVfs;
- int i;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
-
- pVfs = sqlite3_vfs_find(0);
- for(i=0; aSyscall[i].zName; i++){
- if( aSyscall[i].xOrig ){
- pVfs->xSetSystemCall(pVfs, aSyscall[i].zName, 0);
- aSyscall[i].xOrig = 0;
- }
- }
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_syscall_reset(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_vfs *pVfs;
- int i;
- int rc;
-
- if( objc!=2 && objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
-
- pVfs = sqlite3_vfs_find(0);
- if( objc==2 ){
- rc = pVfs->xSetSystemCall(pVfs, 0, 0);
- for(i=0; aSyscall[i].zName; i++) aSyscall[i].xOrig = 0;
- }else{
- int nFunc;
- char *zFunc = Tcl_GetStringFromObj(objv[2], &nFunc);
- rc = pVfs->xSetSystemCall(pVfs, Tcl_GetString(objv[2]), 0);
- for(i=0; rc==SQLITE_OK && aSyscall[i].zName; i++){
- if( strlen(aSyscall[i].zName)!=nFunc ) continue;
- if( memcmp(aSyscall[i].zName, zFunc, nFunc) ) continue;
- aSyscall[i].xOrig = 0;
- }
- }
- if( rc!=SQLITE_OK ){
- Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
- return TCL_ERROR;
- }
-
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_syscall_exists(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_vfs *pVfs;
- sqlite3_syscall_ptr x;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
-
- pVfs = sqlite3_vfs_find(0);
- x = pVfs->xGetSystemCall(pVfs, Tcl_GetString(objv[2]));
-
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(x!=0));
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_syscall_fault(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int nCount = 0;
- int bPersist = 0;
-
- if( objc!=2 && objc!=4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?COUNT PERSIST?");
- return TCL_ERROR;
- }
-
- if( objc==4 ){
- if( Tcl_GetIntFromObj(interp, objv[2], &nCount)
- || Tcl_GetBooleanFromObj(interp, objv[3], &bPersist)
- ){
- return TCL_ERROR;
- }
- }
-
- Tcl_SetObjResult(interp, Tcl_NewIntObj(gSyscall.nFail));
- gSyscall.nCount = nCount;
- gSyscall.bPersist = bPersist;
- gSyscall.nFail = 0;
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_syscall_errno(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int iCall;
- int iErrno;
- int rc;
-
- struct Errno {
- const char *z;
- int i;
- } aErrno[] = {
- { "EACCES", EACCES },
- { "EINTR", EINTR },
- { "EIO", EIO },
- { "EOVERFLOW", EOVERFLOW },
- { "ENOMEM", ENOMEM },
- { "EAGAIN", EAGAIN },
- { "ETIMEDOUT", ETIMEDOUT },
- { "EBUSY", EBUSY },
- { "EPERM", EPERM },
- { "EDEADLK", EDEADLK },
- { "ENOLCK", ENOLCK },
- { 0, 0 }
- };
-
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "SYSCALL ERRNO");
- return TCL_ERROR;
- }
-
- rc = Tcl_GetIndexFromObjStruct(interp,
- objv[2], aSyscall, sizeof(aSyscall[0]), "system-call", 0, &iCall
- );
- if( rc!=TCL_OK ) return rc;
- rc = Tcl_GetIndexFromObjStruct(interp,
- objv[3], aErrno, sizeof(aErrno[0]), "errno", 0, &iErrno
- );
- if( rc!=TCL_OK ) return rc;
-
- aSyscall[iCall].custom_errno = aErrno[iErrno].i;
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_syscall_list(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zSys;
- sqlite3_vfs *pVfs;
- Tcl_Obj *pList;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
-
- pVfs = sqlite3_vfs_find(0);
- pList = Tcl_NewObj();
- Tcl_IncrRefCount(pList);
- for(zSys = pVfs->xNextSystemCall(pVfs, 0);
- zSys!=0;
- zSys = pVfs->xNextSystemCall(pVfs, zSys)
- ){
- Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(zSys, -1));
- }
-
- Tcl_SetObjResult(interp, pList);
- Tcl_DecrRefCount(pList);
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_syscall_defaultvfs(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_vfs *pVfs;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
-
- pVfs = sqlite3_vfs_find(0);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(pVfs->zName, -1));
- return TCL_OK;
-}
-
-static int ts_getpagesize(void){
- return gSyscall.pgsz;
-}
-
-static int SQLITE_TCLAPI test_syscall_pagesize(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
- int pgsz;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "PGSZ");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[2], &pgsz) ){
- return TCL_ERROR;
- }
-
- if( pgsz<0 ){
- if( gSyscall.orig_getpagesize ){
- pVfs->xSetSystemCall(pVfs, "getpagesize", gSyscall.orig_getpagesize);
- }
- }else{
- if( pgsz<512 || (pgsz & (pgsz-1)) ){
- Tcl_AppendResult(interp, "pgsz out of range", 0);
- return TCL_ERROR;
- }
- gSyscall.orig_getpagesize = pVfs->xGetSystemCall(pVfs, "getpagesize");
- gSyscall.pgsz = pgsz;
- pVfs->xSetSystemCall(
- pVfs, "getpagesize", (sqlite3_syscall_ptr)ts_getpagesize
- );
- }
-
- return TCL_OK;
-}
-
-static int SQLITE_TCLAPI test_syscall(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- struct SyscallCmd {
- const char *zName;
- Tcl_ObjCmdProc *xCmd;
- } aCmd[] = {
- { "fault", test_syscall_fault },
- { "install", test_syscall_install },
- { "uninstall", test_syscall_uninstall },
- { "reset", test_syscall_reset },
- { "errno", test_syscall_errno },
- { "exists", test_syscall_exists },
- { "list", test_syscall_list },
- { "defaultvfs", test_syscall_defaultvfs },
- { "pagesize", test_syscall_pagesize },
- { 0, 0 }
- };
- int iCmd;
- int rc;
- sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
- return TCL_ERROR;
- }
- if( pVfs->iVersion<3 || pVfs->xSetSystemCall==0 ){
- Tcl_AppendResult(interp, "VFS does not support xSetSystemCall", 0);
- rc = TCL_ERROR;
- }else{
- rc = Tcl_GetIndexFromObjStruct(interp,
- objv[1], aCmd, sizeof(aCmd[0]), "sub-command", 0, &iCmd
- );
- }
- if( rc!=TCL_OK ) return rc;
- return aCmd[iCmd].xCmd(clientData, interp, objc, objv);
-}
-
-int SqlitetestSyscall_Init(Tcl_Interp *interp){
- struct SyscallCmd {
- const char *zName;
- Tcl_ObjCmdProc *xCmd;
- } aCmd[] = {
- { "test_syscall", test_syscall},
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xCmd, 0, 0);
- }
- return TCL_OK;
-}
-#else
-int SqlitetestSyscall_Init(Tcl_Interp *interp){
- return TCL_OK;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_tclsh.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_tclsh.c
deleted file mode 100644
index 97f7f5d7a10..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_tclsh.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
-** 2017-10-13
-**
-** 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 contains extensions to the the "tclsqlite.c" module used for
-** testing. Basically, all of the other "test_*.c" modules are linked
-** into the enhanced tclsh used for testing (and named "testfixture" or
-** "testfixture.exe") using logic encoded by this file.
-**
-** The code in this file used to be found in tclsqlite3.c, contained within
-** #if SQLITE_TEST ... #endif. It is factored out into this separate module
-** in an effort to keep the tclsqlite.c file pure.
-*/
-#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
-
-/* Needed for the setrlimit() system call on unix */
-#if defined(unix)
-#include <sys/resource.h>
-#endif
-
-/* Forward declaration */
-static int SQLITE_TCLAPI load_testfixture_extensions(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-);
-
-/*
-** This routine is the primary export of this file.
-**
-** Configure the interpreter passed as the first argument to have access
-** to the commands and linked variables that make up:
-**
-** * the [sqlite3] extension itself,
-**
-** * If SQLITE_TCLMD5 or SQLITE_TEST is defined, the Md5 commands, and
-**
-** * If SQLITE_TEST is set, the various test interfaces used by the Tcl
-** test suite.
-*/
-const char *sqlite3TestInit(Tcl_Interp *interp){
- extern int Sqlite3_Init(Tcl_Interp*);
- extern int Sqliteconfig_Init(Tcl_Interp*);
- extern int Sqlitetest1_Init(Tcl_Interp*);
- extern int Sqlitetest2_Init(Tcl_Interp*);
- extern int Sqlitetest3_Init(Tcl_Interp*);
- extern int Sqlitetest4_Init(Tcl_Interp*);
- extern int Sqlitetest5_Init(Tcl_Interp*);
- extern int Sqlitetest6_Init(Tcl_Interp*);
- extern int Sqlitetest7_Init(Tcl_Interp*);
- extern int Sqlitetest8_Init(Tcl_Interp*);
- extern int Sqlitetest9_Init(Tcl_Interp*);
- extern int Sqlitetestasync_Init(Tcl_Interp*);
- extern int Sqlitetest_autoext_Init(Tcl_Interp*);
- extern int Sqlitetest_blob_Init(Tcl_Interp*);
- extern int Sqlitetest_demovfs_Init(Tcl_Interp *);
- extern int Sqlitetest_func_Init(Tcl_Interp*);
- extern int Sqlitetest_hexio_Init(Tcl_Interp*);
- extern int Sqlitetest_init_Init(Tcl_Interp*);
- extern int Sqlitetest_malloc_Init(Tcl_Interp*);
- extern int Sqlitetest_mutex_Init(Tcl_Interp*);
- extern int Sqlitetestschema_Init(Tcl_Interp*);
- extern int Sqlitetestsse_Init(Tcl_Interp*);
- extern int Sqlitetesttclvar_Init(Tcl_Interp*);
- extern int Sqlitetestfs_Init(Tcl_Interp*);
- extern int SqlitetestThread_Init(Tcl_Interp*);
- extern int SqlitetestOnefile_Init();
- extern int SqlitetestOsinst_Init(Tcl_Interp*);
- extern int Sqlitetestbackup_Init(Tcl_Interp*);
- extern int Sqlitetestintarray_Init(Tcl_Interp*);
- extern int Sqlitetestvfs_Init(Tcl_Interp *);
- extern int Sqlitetestrtree_Init(Tcl_Interp*);
- extern int Sqlitequota_Init(Tcl_Interp*);
- extern int Sqlitemultiplex_Init(Tcl_Interp*);
- extern int SqliteSuperlock_Init(Tcl_Interp*);
- extern int SqlitetestSyscall_Init(Tcl_Interp*);
-#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
- extern int TestSession_Init(Tcl_Interp*);
-#endif
- extern int Md5_Init(Tcl_Interp*);
- extern int Fts5tcl_Init(Tcl_Interp *);
- extern int SqliteRbu_Init(Tcl_Interp*);
- extern int Sqlitetesttcl_Init(Tcl_Interp*);
-#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
- extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
-#endif
-#ifdef SQLITE_ENABLE_ZIPVFS
- extern int Zipvfs_Init(Tcl_Interp*);
-#endif
- extern int TestExpert_Init(Tcl_Interp*);
-
- Tcl_CmdInfo cmdInfo;
-
- /* Since the primary use case for this binary is testing of SQLite,
- ** be sure to generate core files if we crash */
-#if defined(unix)
- { struct rlimit x;
- getrlimit(RLIMIT_CORE, &x);
- x.rlim_cur = x.rlim_max;
- setrlimit(RLIMIT_CORE, &x);
- }
-#endif /* unix */
-
- if( Tcl_GetCommandInfo(interp, "sqlite3", &cmdInfo)==0 ){
- Sqlite3_Init(interp);
- }
-#ifdef SQLITE_ENABLE_ZIPVFS
- Zipvfs_Init(interp);
-#endif
- Md5_Init(interp);
- Sqliteconfig_Init(interp);
- Sqlitetest1_Init(interp);
- Sqlitetest2_Init(interp);
- Sqlitetest3_Init(interp);
- Sqlitetest4_Init(interp);
- Sqlitetest5_Init(interp);
- Sqlitetest6_Init(interp);
- Sqlitetest7_Init(interp);
- Sqlitetest8_Init(interp);
- Sqlitetest9_Init(interp);
- Sqlitetestasync_Init(interp);
- Sqlitetest_autoext_Init(interp);
- Sqlitetest_blob_Init(interp);
- Sqlitetest_demovfs_Init(interp);
- Sqlitetest_func_Init(interp);
- Sqlitetest_hexio_Init(interp);
- Sqlitetest_init_Init(interp);
- Sqlitetest_malloc_Init(interp);
- Sqlitetest_mutex_Init(interp);
- Sqlitetestschema_Init(interp);
- Sqlitetesttclvar_Init(interp);
- Sqlitetestfs_Init(interp);
- SqlitetestThread_Init(interp);
- SqlitetestOnefile_Init();
- SqlitetestOsinst_Init(interp);
- Sqlitetestbackup_Init(interp);
- Sqlitetestintarray_Init(interp);
- Sqlitetestvfs_Init(interp);
- Sqlitetestrtree_Init(interp);
- Sqlitequota_Init(interp);
- Sqlitemultiplex_Init(interp);
- SqliteSuperlock_Init(interp);
- SqlitetestSyscall_Init(interp);
-#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
- TestSession_Init(interp);
-#endif
- Fts5tcl_Init(interp);
- SqliteRbu_Init(interp);
- Sqlitetesttcl_Init(interp);
-
-#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
- Sqlitetestfts3_Init(interp);
-#endif
- TestExpert_Init(interp);
-
- Tcl_CreateObjCommand(
- interp, "load_testfixture_extensions", load_testfixture_extensions,0,0
- );
- return 0;
-}
-
-/* tclcmd: load_testfixture_extensions
-*/
-static int SQLITE_TCLAPI load_testfixture_extensions(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-
- Tcl_Interp *slave;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SLAVE");
- return TCL_ERROR;
- }
-
- slave = Tcl_GetSlave(interp, Tcl_GetString(objv[1]));
- if( !slave ){
- return TCL_ERROR;
- }
-
- (void)sqlite3TestInit(slave);
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_tclvar.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_tclvar.c
deleted file mode 100644
index bf99a8eadbd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_tclvar.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
-** 2006 June 13
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the virtual table interfaces. This code
-** is not included in the SQLite library. It is used for automated
-** testing of the SQLite library.
-**
-** The emphasis of this file is a virtual table that provides
-** access to TCL variables.
-**
-** The TCLVAR eponymous virtual table has a schema like this:
-**
-** CREATE TABLE tclvar(
-** name TEXT, -- base name of the variable: "x" in "$x(y)"
-** arrayname TEXT, -- array index name: "y" in "$x(y)"
-** value TEXT, -- the value of the variable
-** fullname TEXT, -- the full name of the variable
-** PRIMARY KEY(fullname)
-** ) WITHOUT ROWID;
-**
-** DELETE, INSERT, and UPDATE operations use the "fullname" field to
-** determine the variable to be modified. Changing "value" to NULL
-** deletes the variable.
-**
-** For SELECT operations, the "name" and "arrayname" fields will always
-** match the "fullname" field. For DELETE, INSERT, and UPDATE, the
-** "name" and "arrayname" fields are ignored and the variable is modified
-** according to "fullname" and "value" only.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Characters that make up the idxStr created by xBestIndex for xFilter.
-*/
-#define TCLVAR_NAME_EQ 'e'
-#define TCLVAR_NAME_MATCH 'm'
-#define TCLVAR_VALUE_GLOB 'g'
-#define TCLVAR_VALUE_REGEXP 'r'
-#define TCLVAR_VALUE_LIKE 'l'
-
-typedef struct tclvar_vtab tclvar_vtab;
-typedef struct tclvar_cursor tclvar_cursor;
-
-/*
-** A tclvar virtual-table object
-*/
-struct tclvar_vtab {
- sqlite3_vtab base;
- Tcl_Interp *interp;
-};
-
-/* A tclvar cursor object */
-struct tclvar_cursor {
- sqlite3_vtab_cursor base;
-
- Tcl_Obj *pList1; /* Result of [info vars ?pattern?] */
- Tcl_Obj *pList2; /* Result of [array names [lindex $pList1 $i1]] */
- int i1; /* Current item in pList1 */
- int i2; /* Current item (if any) in pList2 */
-};
-
-/* Methods for the tclvar module */
-static int tclvarConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- tclvar_vtab *pVtab;
- static const char zSchema[] =
- "CREATE TABLE x("
- " name TEXT," /* Base name */
- " arrayname TEXT," /* Array index */
- " value TEXT," /* Value */
- " fullname TEXT PRIMARY KEY" /* base(index) name */
- ") WITHOUT ROWID";
- pVtab = sqlite3MallocZero( sizeof(*pVtab) );
- if( pVtab==0 ) return SQLITE_NOMEM;
- *ppVtab = &pVtab->base;
- pVtab->interp = (Tcl_Interp *)pAux;
- sqlite3_declare_vtab(db, zSchema);
- return SQLITE_OK;
-}
-/* Note that for this virtual table, the xCreate and xConnect
-** methods are identical. */
-
-static int tclvarDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-/* The xDisconnect and xDestroy methods are also the same */
-
-/*
-** Open a new tclvar cursor.
-*/
-static int tclvarOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
- tclvar_cursor *pCur;
- pCur = sqlite3MallocZero(sizeof(tclvar_cursor));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Close a tclvar cursor.
-*/
-static int tclvarClose(sqlite3_vtab_cursor *cur){
- tclvar_cursor *pCur = (tclvar_cursor *)cur;
- if( pCur->pList1 ){
- Tcl_DecrRefCount(pCur->pList1);
- }
- if( pCur->pList2 ){
- Tcl_DecrRefCount(pCur->pList2);
- }
- sqlite3_free(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Returns 1 if data is ready, or 0 if not.
-*/
-static int next2(Tcl_Interp *interp, tclvar_cursor *pCur, Tcl_Obj *pObj){
- Tcl_Obj *p;
-
- if( pObj ){
- if( !pCur->pList2 ){
- p = Tcl_NewStringObj("array names", -1);
- Tcl_IncrRefCount(p);
- Tcl_ListObjAppendElement(0, p, pObj);
- Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL);
- Tcl_DecrRefCount(p);
- pCur->pList2 = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(pCur->pList2);
- assert( pCur->i2==0 );
- }else{
- int n = 0;
- pCur->i2++;
- Tcl_ListObjLength(0, pCur->pList2, &n);
- if( pCur->i2>=n ){
- Tcl_DecrRefCount(pCur->pList2);
- pCur->pList2 = 0;
- pCur->i2 = 0;
- return 0;
- }
- }
- }
-
- return 1;
-}
-
-static int tclvarNext(sqlite3_vtab_cursor *cur){
- Tcl_Obj *pObj;
- int n = 0;
- int ok = 0;
-
- tclvar_cursor *pCur = (tclvar_cursor *)cur;
- Tcl_Interp *interp = ((tclvar_vtab *)(cur->pVtab))->interp;
-
- Tcl_ListObjLength(0, pCur->pList1, &n);
- while( !ok && pCur->i1<n ){
- Tcl_ListObjIndex(0, pCur->pList1, pCur->i1, &pObj);
- ok = next2(interp, pCur, pObj);
- if( !ok ){
- pCur->i1++;
- }
- }
-
- return 0;
-}
-
-static int tclvarFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- tclvar_cursor *pCur = (tclvar_cursor *)pVtabCursor;
- Tcl_Interp *interp = ((tclvar_vtab *)(pVtabCursor->pVtab))->interp;
- Tcl_Obj *p = Tcl_NewStringObj("tclvar_filter_cmd", -1);
-
- const char *zEq = "";
- const char *zMatch = "";
- const char *zGlob = "";
- const char *zRegexp = "";
- const char *zLike = "";
- int i;
-
- for(i=0; idxStr[i]; i++){
- switch( idxStr[i] ){
- case TCLVAR_NAME_EQ:
- zEq = (const char*)sqlite3_value_text(argv[i]);
- break;
- case TCLVAR_NAME_MATCH:
- zMatch = (const char*)sqlite3_value_text(argv[i]);
- break;
- case TCLVAR_VALUE_GLOB:
- zGlob = (const char*)sqlite3_value_text(argv[i]);
- break;
- case TCLVAR_VALUE_REGEXP:
- zRegexp = (const char*)sqlite3_value_text(argv[i]);
- break;
- case TCLVAR_VALUE_LIKE:
- zLike = (const char*)sqlite3_value_text(argv[i]);
- break;
- default:
- assert( 0 );
- }
- }
-
- Tcl_IncrRefCount(p);
- Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zEq, -1));
- Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zMatch, -1));
- Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zGlob, -1));
- Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zRegexp, -1));
- Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zLike, -1));
-
- Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL);
- if( pCur->pList1 ){
- Tcl_DecrRefCount(pCur->pList1);
- }
- if( pCur->pList2 ){
- Tcl_DecrRefCount(pCur->pList2);
- pCur->pList2 = 0;
- }
- pCur->i1 = 0;
- pCur->i2 = 0;
- pCur->pList1 = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(pCur->pList1);
-
- Tcl_DecrRefCount(p);
- return tclvarNext(pVtabCursor);
-}
-
-static int tclvarColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
- Tcl_Obj *p1;
- Tcl_Obj *p2;
- const char *z1;
- const char *z2 = "";
- tclvar_cursor *pCur = (tclvar_cursor*)cur;
- Tcl_Interp *interp = ((tclvar_vtab *)cur->pVtab)->interp;
-
- Tcl_ListObjIndex(interp, pCur->pList1, pCur->i1, &p1);
- Tcl_ListObjIndex(interp, pCur->pList2, pCur->i2, &p2);
- z1 = Tcl_GetString(p1);
- if( p2 ){
- z2 = Tcl_GetString(p2);
- }
- switch (i) {
- case 0: {
- sqlite3_result_text(ctx, z1, -1, SQLITE_TRANSIENT);
- break;
- }
- case 1: {
- sqlite3_result_text(ctx, z2, -1, SQLITE_TRANSIENT);
- break;
- }
- case 2: {
- Tcl_Obj *pVal = Tcl_GetVar2Ex(interp, z1, *z2?z2:0, TCL_GLOBAL_ONLY);
- sqlite3_result_text(ctx, Tcl_GetString(pVal), -1, SQLITE_TRANSIENT);
- break;
- }
- case 3: {
- char *z3;
- if( p2 ){
- z3 = sqlite3_mprintf("%s(%s)", z1, z2);
- sqlite3_result_text(ctx, z3, -1, sqlite3_free);
- }else{
- sqlite3_result_text(ctx, z1, -1, SQLITE_TRANSIENT);
- }
- break;
- }
- }
- return SQLITE_OK;
-}
-
-static int tclvarRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- *pRowid = 0;
- return SQLITE_OK;
-}
-
-static int tclvarEof(sqlite3_vtab_cursor *cur){
- tclvar_cursor *pCur = (tclvar_cursor*)cur;
- return (pCur->pList2?0:1);
-}
-
-/*
-** If nul-terminated string zStr does not already contain the character
-** passed as the second argument, append it and return 0. Or, if there is
-** already an instance of x in zStr, do nothing return 1;
-**
-** There is guaranteed to be enough room in the buffer pointed to by zStr
-** for the new character and nul-terminator.
-*/
-static int tclvarAddToIdxstr(char *zStr, char x){
- int i;
- for(i=0; zStr[i]; i++){
- if( zStr[i]==x ) return 1;
- }
- zStr[i] = x;
- zStr[i+1] = '\0';
- return 0;
-}
-
-/*
-** Return true if variable $::tclvar_set_omit exists and is set to true.
-** False otherwise.
-*/
-static int tclvarSetOmit(Tcl_Interp *interp){
- int rc;
- int res = 0;
- Tcl_Obj *pRes;
- rc = Tcl_Eval(interp,
- "expr {[info exists ::tclvar_set_omit] && $::tclvar_set_omit}"
- );
- if( rc==TCL_OK ){
- pRes = Tcl_GetObjResult(interp);
- rc = Tcl_GetBooleanFromObj(0, pRes, &res);
- }
- return (rc==TCL_OK && res);
-}
-
-/*
-** The xBestIndex() method. This virtual table supports the following
-** operators:
-**
-** name = ? (omit flag clear)
-** name MATCH ? (omit flag set)
-** value GLOB ? (omit flag set iff $::tclvar_set_omit)
-** value REGEXP ? (omit flag set iff $::tclvar_set_omit)
-** value LIKE ? (omit flag set iff $::tclvar_set_omit)
-**
-** For each constraint present, the corresponding TCLVAR_XXX character is
-** appended to the idxStr value.
-*/
-static int tclvarBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
- tclvar_vtab *pTab = (tclvar_vtab*)tab;
- int ii;
- char *zStr = sqlite3_malloc(32);
- int iStr = 0;
-
- if( zStr==0 ) return SQLITE_NOMEM;
- zStr[0] = '\0';
-
- for(ii=0; ii<pIdxInfo->nConstraint; ii++){
- struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
- struct sqlite3_index_constraint_usage *pUsage;
-
- pUsage = &pIdxInfo->aConstraintUsage[ii];
- if( pCons->usable ){
- /* name = ? */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && pCons->iColumn==0 ){
- if( 0==tclvarAddToIdxstr(zStr, TCLVAR_NAME_EQ) ){
- pUsage->argvIndex = ++iStr;
- pUsage->omit = 0;
- }
- }
-
- /* name MATCH ? */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH && pCons->iColumn==0 ){
- if( 0==tclvarAddToIdxstr(zStr, TCLVAR_NAME_MATCH) ){
- pUsage->argvIndex = ++iStr;
- pUsage->omit = 1;
- }
- }
-
- /* value GLOB ? */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_GLOB && pCons->iColumn==2 ){
- if( 0==tclvarAddToIdxstr(zStr, TCLVAR_VALUE_GLOB) ){
- pUsage->argvIndex = ++iStr;
- pUsage->omit = tclvarSetOmit(pTab->interp);
- }
- }
-
- /* value REGEXP ? */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_REGEXP && pCons->iColumn==2 ){
- if( 0==tclvarAddToIdxstr(zStr, TCLVAR_VALUE_REGEXP) ){
- pUsage->argvIndex = ++iStr;
- pUsage->omit = tclvarSetOmit(pTab->interp);
- }
- }
-
- /* value LIKE ? */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_LIKE && pCons->iColumn==2 ){
- if( 0==tclvarAddToIdxstr(zStr, TCLVAR_VALUE_LIKE) ){
- pUsage->argvIndex = ++iStr;
- pUsage->omit = tclvarSetOmit(pTab->interp);
- }
- }
- }
- }
- pIdxInfo->idxStr = zStr;
- pIdxInfo->needToFreeIdxStr = 1;
-
- return SQLITE_OK;
-}
-
-/*
-** Invoked for any UPDATE, INSERT, or DELETE against a tclvar table
-*/
-static int tclvarUpdate(
- sqlite3_vtab *tab,
- int argc,
- sqlite3_value **argv,
- sqlite_int64 *pRowid
-){
- tclvar_vtab *pTab = (tclvar_vtab*)tab;
- if( argc==1 ){
- /* A DELETE operation. The variable to be deleted is stored in argv[0] */
- const char *zVar = (const char*)sqlite3_value_text(argv[0]);
- Tcl_UnsetVar(pTab->interp, zVar, TCL_GLOBAL_ONLY);
- return SQLITE_OK;
- }
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
- /* An INSERT operation */
- const char *zValue = (const char*)sqlite3_value_text(argv[4]);
- const char *zName;
- if( sqlite3_value_type(argv[5])!=SQLITE_TEXT ){
- tab->zErrMsg = sqlite3_mprintf("the 'fullname' column must be TEXT");
- return SQLITE_ERROR;
- }
- zName = (const char*)sqlite3_value_text(argv[5]);
- if( zValue ){
- Tcl_SetVar(pTab->interp, zName, zValue, TCL_GLOBAL_ONLY);
- }else{
- Tcl_UnsetVar(pTab->interp, zName, TCL_GLOBAL_ONLY);
- }
- return SQLITE_OK;
- }
- if( sqlite3_value_type(argv[0])==SQLITE_TEXT
- && sqlite3_value_type(argv[1])==SQLITE_TEXT
- ){
- /* An UPDATE operation */
- const char *zOldName = (const char*)sqlite3_value_text(argv[0]);
- const char *zNewName = (const char*)sqlite3_value_text(argv[1]);
- const char *zValue = (const char*)sqlite3_value_text(argv[4]);
-
- if( strcmp(zOldName, zNewName)!=0 || zValue==0 ){
- Tcl_UnsetVar(pTab->interp, zOldName, TCL_GLOBAL_ONLY);
- }
- if( zValue!=0 ){
- Tcl_SetVar(pTab->interp, zNewName, zValue, TCL_GLOBAL_ONLY);
- }
- return SQLITE_OK;
- }
- tab->zErrMsg = sqlite3_mprintf("prohibited TCL variable change");
- return SQLITE_ERROR;
-}
-
-/*
-** A virtual table module that provides read-only access to a
-** Tcl global variable namespace.
-*/
-static sqlite3_module tclvarModule = {
- 0, /* iVersion */
- tclvarConnect,
- tclvarConnect,
- tclvarBestIndex,
- tclvarDisconnect,
- tclvarDisconnect,
- tclvarOpen, /* xOpen - open a cursor */
- tclvarClose, /* xClose - close a cursor */
- tclvarFilter, /* xFilter - configure scan constraints */
- tclvarNext, /* xNext - advance a cursor */
- tclvarEof, /* xEof - check for end of scan */
- tclvarColumn, /* xColumn - read data */
- tclvarRowid, /* xRowid - read data */
- tclvarUpdate, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
-
-/*
-** Register the echo virtual table module.
-*/
-static int SQLITE_TCLAPI register_tclvar_module(
- ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[] /* Command arguments */
-){
- int rc = TCL_OK;
- sqlite3 *db;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_create_module(db, "tclvar", &tclvarModule, (void*)interp);
- rc = Tcl_Eval(interp,
- "proc like {pattern str} {\n"
- " set p [string map {% * _ ?} $pattern]\n"
- " string match $p $str\n"
- "}\n"
- "proc tclvar_filter_cmd {eq match glob regexp like} {\n"
- " set res {}\n"
- " set pattern $eq\n"
- " if {$pattern=={}} { set pattern $match }\n"
- " if {$pattern=={}} { set pattern * }\n"
- " foreach v [uplevel #0 info vars $pattern] {\n"
- " if {($glob=={} || [string match $glob [uplevel #0 set $v]])\n"
- " && ($like=={} || [like $like [uplevel #0 set $v]])\n"
- " && ($regexp=={} || [regexp $regexp [uplevel #0 set $v]])\n"
- " } {\n"
- " lappend res $v\n"
- " }\n"
- " }\n"
- " set res\n"
- "}\n"
- );
-#endif
- return rc;
-}
-
-#endif
-
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetesttclvar_Init(Tcl_Interp *interp){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- static struct {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- void *clientData;
- } aObjCmd[] = {
- { "register_tclvar_module", register_tclvar_module, 0 },
- };
- int i;
- for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
- aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
- }
-#endif
- return TCL_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_thread.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_thread.c
deleted file mode 100644
index 20b4cf148bf..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_thread.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
-** 2007 September 9
-**
-** 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 contains the implementation of some Tcl commands used to
-** test that sqlite3 database handles may be concurrently accessed by
-** multiple threads. Right now this only works on unix.
-*/
-
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-#if SQLITE_THREADSAFE
-
-#include <errno.h>
-
-#if !defined(_MSC_VER)
-#include <unistd.h>
-#endif
-
-/*
-** One of these is allocated for each thread created by [sqlthread spawn].
-*/
-typedef struct SqlThread SqlThread;
-struct SqlThread {
- Tcl_ThreadId parent; /* Thread id of parent thread */
- Tcl_Interp *interp; /* Parent interpreter */
- char *zScript; /* The script to execute. */
- char *zVarname; /* Varname in parent script */
-};
-
-/*
-** A custom Tcl_Event type used by this module. When the event is
-** handled, script zScript is evaluated in interpreter interp. If
-** the evaluation throws an exception (returns TCL_ERROR), then the
-** error is handled by Tcl_BackgroundError(). If no error occurs,
-** the result is simply discarded.
-*/
-typedef struct EvalEvent EvalEvent;
-struct EvalEvent {
- Tcl_Event base; /* Base class of type Tcl_Event */
- char *zScript; /* The script to execute. */
- Tcl_Interp *interp; /* The interpreter to execute it in. */
-};
-
-static Tcl_ObjCmdProc sqlthread_proc;
-static Tcl_ObjCmdProc clock_seconds_proc;
-#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
-static Tcl_ObjCmdProc blocking_step_proc;
-static Tcl_ObjCmdProc blocking_prepare_v2_proc;
-#endif
-int Sqlitetest1_Init(Tcl_Interp *);
-int Sqlite3_Init(Tcl_Interp *);
-
-/* Functions from main.c */
-extern const char *sqlite3ErrName(int);
-
-/* Functions from test1.c */
-extern void *sqlite3TestTextToPtr(const char *);
-extern int getDbPointer(Tcl_Interp *, const char *, sqlite3 **);
-extern int sqlite3TestMakePointerStr(Tcl_Interp *, char *, void *);
-extern int sqlite3TestErrCode(Tcl_Interp *, sqlite3 *, int);
-
-/*
-** Handler for events of type EvalEvent.
-*/
-static int SQLITE_TCLAPI tclScriptEvent(Tcl_Event *evPtr, int flags){
- int rc;
- EvalEvent *p = (EvalEvent *)evPtr;
- rc = Tcl_Eval(p->interp, p->zScript);
- if( rc!=TCL_OK ){
- Tcl_BackgroundError(p->interp);
- }
- UNUSED_PARAMETER(flags);
- return 1;
-}
-
-/*
-** Register an EvalEvent to evaluate the script pScript in the
-** parent interpreter/thread of SqlThread p.
-*/
-static void postToParent(SqlThread *p, Tcl_Obj *pScript){
- EvalEvent *pEvent;
- char *zMsg;
- int nMsg;
-
- zMsg = Tcl_GetStringFromObj(pScript, &nMsg);
- pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1);
- pEvent->base.nextPtr = 0;
- pEvent->base.proc = tclScriptEvent;
- pEvent->zScript = (char *)&pEvent[1];
- memcpy(pEvent->zScript, zMsg, nMsg+1);
- pEvent->interp = p->interp;
-
- Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL);
- Tcl_ThreadAlert(p->parent);
-}
-
-/*
-** The main function for threads created with [sqlthread spawn].
-*/
-static Tcl_ThreadCreateType tclScriptThread(ClientData pSqlThread){
- Tcl_Interp *interp;
- Tcl_Obj *pRes;
- Tcl_Obj *pList;
- int rc;
- SqlThread *p = (SqlThread *)pSqlThread;
- extern int Sqlitetest_mutex_Init(Tcl_Interp*);
-
- interp = Tcl_CreateInterp();
- Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0);
- Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, pSqlThread, 0);
-#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
- Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0);
- Tcl_CreateObjCommand(interp,
- "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0);
- Tcl_CreateObjCommand(interp,
- "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0);
-#endif
- Sqlitetest1_Init(interp);
- Sqlitetest_mutex_Init(interp);
- Sqlite3_Init(interp);
-
- rc = Tcl_Eval(interp, p->zScript);
- pRes = Tcl_GetObjResult(interp);
- pList = Tcl_NewObj();
- Tcl_IncrRefCount(pList);
- Tcl_IncrRefCount(pRes);
-
- if( rc!=TCL_OK ){
- Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("error", -1));
- Tcl_ListObjAppendElement(interp, pList, pRes);
- postToParent(p, pList);
- Tcl_DecrRefCount(pList);
- pList = Tcl_NewObj();
- }
-
- Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("set", -1));
- Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(p->zVarname, -1));
- Tcl_ListObjAppendElement(interp, pList, pRes);
- postToParent(p, pList);
-
- ckfree((void *)p);
- Tcl_DecrRefCount(pList);
- Tcl_DecrRefCount(pRes);
- Tcl_DeleteInterp(interp);
- while( Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT) );
- Tcl_ExitThread(0);
- TCL_THREAD_CREATE_RETURN;
-}
-
-/*
-** sqlthread spawn VARNAME SCRIPT
-**
-** Spawn a new thread with its own Tcl interpreter and run the
-** specified SCRIPT(s) in it. The thread terminates after running
-** the script. The result of the script is stored in the variable
-** VARNAME.
-**
-** The caller can wait for the script to terminate using [vwait VARNAME].
-*/
-static int SQLITE_TCLAPI sqlthread_spawn(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_ThreadId x;
- SqlThread *pNew;
- int rc;
-
- int nVarname; char *zVarname;
- int nScript; char *zScript;
-
- /* Parameters for thread creation */
- const int nStack = TCL_THREAD_STACK_DEFAULT;
- const int flags = TCL_THREAD_NOFLAGS;
-
- assert(objc==4);
- UNUSED_PARAMETER(clientData);
- UNUSED_PARAMETER(objc);
-
- zVarname = Tcl_GetStringFromObj(objv[2], &nVarname);
- zScript = Tcl_GetStringFromObj(objv[3], &nScript);
-
- pNew = (SqlThread *)ckalloc(sizeof(SqlThread)+nVarname+nScript+2);
- pNew->zVarname = (char *)&pNew[1];
- pNew->zScript = (char *)&pNew->zVarname[nVarname+1];
- memcpy(pNew->zVarname, zVarname, nVarname+1);
- memcpy(pNew->zScript, zScript, nScript+1);
- pNew->parent = Tcl_GetCurrentThread();
- pNew->interp = interp;
-
- rc = Tcl_CreateThread(&x, tclScriptThread, (void *)pNew, nStack, flags);
- if( rc!=TCL_OK ){
- Tcl_AppendResult(interp, "Error in Tcl_CreateThread()", 0);
- ckfree((char *)pNew);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
-** sqlthread parent SCRIPT
-**
-** This can be called by spawned threads only. It sends the specified
-** script back to the parent thread for execution. The result of
-** evaluating the SCRIPT is returned. The parent thread must enter
-** the event loop for this to work - otherwise the caller will
-** block indefinitely.
-**
-** NOTE: At the moment, this doesn't work. FIXME.
-*/
-static int SQLITE_TCLAPI sqlthread_parent(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- EvalEvent *pEvent;
- char *zMsg;
- int nMsg;
- SqlThread *p = (SqlThread *)clientData;
-
- assert(objc==3);
- UNUSED_PARAMETER(objc);
-
- if( p==0 ){
- Tcl_AppendResult(interp, "no parent thread", 0);
- return TCL_ERROR;
- }
-
- zMsg = Tcl_GetStringFromObj(objv[2], &nMsg);
- pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1);
- pEvent->base.nextPtr = 0;
- pEvent->base.proc = tclScriptEvent;
- pEvent->zScript = (char *)&pEvent[1];
- memcpy(pEvent->zScript, zMsg, nMsg+1);
- pEvent->interp = p->interp;
- Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL);
- Tcl_ThreadAlert(p->parent);
-
- return TCL_OK;
-}
-
-static int xBusy(void *pArg, int nBusy){
- UNUSED_PARAMETER(pArg);
- UNUSED_PARAMETER(nBusy);
- sqlite3_sleep(50);
- return 1; /* Try again... */
-}
-
-/*
-** sqlthread open
-**
-** Open a database handle and return the string representation of
-** the pointer value.
-*/
-static int SQLITE_TCLAPI sqlthread_open(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p);
-
- const char *zFilename;
- sqlite3 *db;
- char zBuf[100];
- extern int Md5_Register(sqlite3*,char**,const sqlite3_api_routines*);
-
- UNUSED_PARAMETER(clientData);
- UNUSED_PARAMETER(objc);
-
- zFilename = Tcl_GetString(objv[2]);
- sqlite3_open(zFilename, &db);
-#ifdef SQLITE_HAS_CODEC
- if( db && objc>=4 ){
- const char *zKey;
- int nKey;
- int rc;
- zKey = Tcl_GetStringFromObj(objv[3], &nKey);
- rc = sqlite3_key(db, zKey, nKey);
- if( rc!=SQLITE_OK ){
- char *zErrMsg = sqlite3_mprintf("error %d: %s", rc, sqlite3_errmsg(db));
- sqlite3_close(db);
- Tcl_AppendResult(interp, zErrMsg, (char*)0);
- sqlite3_free(zErrMsg);
- return TCL_ERROR;
- }
- }
-#endif
- Md5_Register(db, 0, 0);
- sqlite3_busy_handler(db, xBusy, 0);
-
- if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
-
- return TCL_OK;
-}
-
-
-/*
-** sqlthread open
-**
-** Return the current thread-id (Tcl_GetCurrentThread()) cast to
-** an integer.
-*/
-static int SQLITE_TCLAPI sqlthread_id(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_ThreadId id = Tcl_GetCurrentThread();
- Tcl_SetObjResult(interp, Tcl_NewIntObj(SQLITE_PTR_TO_INT(id)));
- UNUSED_PARAMETER(clientData);
- UNUSED_PARAMETER(objc);
- UNUSED_PARAMETER(objv);
- return TCL_OK;
-}
-
-
-/*
-** Dispatch routine for the sub-commands of [sqlthread].
-*/
-static int SQLITE_TCLAPI sqlthread_proc(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- struct SubCommand {
- char *zName;
- Tcl_ObjCmdProc *xProc;
- int nArg;
- char *zUsage;
- } aSub[] = {
- {"parent", sqlthread_parent, 1, "SCRIPT"},
- {"spawn", sqlthread_spawn, 2, "VARNAME SCRIPT"},
- {"open", sqlthread_open, 1, "DBNAME"},
- {"id", sqlthread_id, 0, ""},
- {0, 0, 0}
- };
- struct SubCommand *pSub;
- int rc;
- int iIndex;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND");
- return TCL_ERROR;
- }
-
- rc = Tcl_GetIndexFromObjStruct(
- interp, objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iIndex
- );
- if( rc!=TCL_OK ) return rc;
- pSub = &aSub[iIndex];
-
- if( objc<(pSub->nArg+2) ){
- Tcl_WrongNumArgs(interp, 2, objv, pSub->zUsage);
- return TCL_ERROR;
- }
-
- return pSub->xProc(clientData, interp, objc, objv);
-}
-
-/*
-** The [clock_seconds] command. This is more or less the same as the
-** regular tcl [clock seconds], except that it is available in testfixture
-** when linked against both Tcl 8.4 and 8.5. Because [clock seconds] is
-** implemented as a script in Tcl 8.5, it is not usually available to
-** testfixture.
-*/
-static int SQLITE_TCLAPI clock_seconds_proc(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_Time now;
- Tcl_GetTime(&now);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(now.sec));
- UNUSED_PARAMETER(clientData);
- UNUSED_PARAMETER(objc);
- UNUSED_PARAMETER(objv);
- return TCL_OK;
-}
-
-/*************************************************************************
-** This block contains the implementation of the [sqlite3_blocking_step]
-** command available to threads created by [sqlthread spawn] commands. It
-** is only available on UNIX for now. This is because pthread condition
-** variables are used.
-**
-** The source code for the C functions sqlite3_blocking_step(),
-** blocking_step_notify() and the structure UnlockNotification is
-** automatically extracted from this file and used as part of the
-** documentation for the sqlite3_unlock_notify() API function. This
-** should be considered if these functions are to be extended (i.e. to
-** support windows) in the future.
-*/
-#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
-
-/* BEGIN_SQLITE_BLOCKING_STEP */
-/* This example uses the pthreads API */
-#include <pthread.h>
-
-/*
-** A pointer to an instance of this structure is passed as the user-context
-** pointer when registering for an unlock-notify callback.
-*/
-typedef struct UnlockNotification UnlockNotification;
-struct UnlockNotification {
- int fired; /* True after unlock event has occurred */
- pthread_cond_t cond; /* Condition variable to wait on */
- pthread_mutex_t mutex; /* Mutex to protect structure */
-};
-
-/*
-** This function is an unlock-notify callback registered with SQLite.
-*/
-static void unlock_notify_cb(void **apArg, int nArg){
- int i;
- for(i=0; i<nArg; i++){
- UnlockNotification *p = (UnlockNotification *)apArg[i];
- pthread_mutex_lock(&p->mutex);
- p->fired = 1;
- pthread_cond_signal(&p->cond);
- pthread_mutex_unlock(&p->mutex);
- }
-}
-
-/*
-** This function assumes that an SQLite API call (either sqlite3_prepare_v2()
-** or sqlite3_step()) has just returned SQLITE_LOCKED. The argument is the
-** associated database connection.
-**
-** This function calls sqlite3_unlock_notify() to register for an
-** unlock-notify callback, then blocks until that callback is delivered
-** and returns SQLITE_OK. The caller should then retry the failed operation.
-**
-** Or, if sqlite3_unlock_notify() indicates that to block would deadlock
-** the system, then this function returns SQLITE_LOCKED immediately. In
-** this case the caller should not retry the operation and should roll
-** back the current transaction (if any).
-*/
-static int wait_for_unlock_notify(sqlite3 *db){
- int rc;
- UnlockNotification un;
-
- /* Initialize the UnlockNotification structure. */
- un.fired = 0;
- pthread_mutex_init(&un.mutex, 0);
- pthread_cond_init(&un.cond, 0);
-
- /* Register for an unlock-notify callback. */
- rc = sqlite3_unlock_notify(db, unlock_notify_cb, (void *)&un);
- assert( rc==SQLITE_LOCKED || rc==SQLITE_OK );
-
- /* The call to sqlite3_unlock_notify() always returns either SQLITE_LOCKED
- ** or SQLITE_OK.
- **
- ** If SQLITE_LOCKED was returned, then the system is deadlocked. In this
- ** case this function needs to return SQLITE_LOCKED to the caller so
- ** that the current transaction can be rolled back. Otherwise, block
- ** until the unlock-notify callback is invoked, then return SQLITE_OK.
- */
- if( rc==SQLITE_OK ){
- pthread_mutex_lock(&un.mutex);
- if( !un.fired ){
- pthread_cond_wait(&un.cond, &un.mutex);
- }
- pthread_mutex_unlock(&un.mutex);
- }
-
- /* Destroy the mutex and condition variables. */
- pthread_cond_destroy(&un.cond);
- pthread_mutex_destroy(&un.mutex);
-
- return rc;
-}
-
-/*
-** This function is a wrapper around the SQLite function sqlite3_step().
-** It functions in the same way as step(), except that if a required
-** shared-cache lock cannot be obtained, this function may block waiting for
-** the lock to become available. In this scenario the normal API step()
-** function always returns SQLITE_LOCKED.
-**
-** If this function returns SQLITE_LOCKED, the caller should rollback
-** the current transaction (if any) and try again later. Otherwise, the
-** system may become deadlocked.
-*/
-int sqlite3_blocking_step(sqlite3_stmt *pStmt){
- int rc;
- while( SQLITE_LOCKED==(rc = sqlite3_step(pStmt)) ){
- rc = wait_for_unlock_notify(sqlite3_db_handle(pStmt));
- if( rc!=SQLITE_OK ) break;
- sqlite3_reset(pStmt);
- }
- return rc;
-}
-
-/*
-** This function is a wrapper around the SQLite function sqlite3_prepare_v2().
-** It functions in the same way as prepare_v2(), except that if a required
-** shared-cache lock cannot be obtained, this function may block waiting for
-** the lock to become available. In this scenario the normal API prepare_v2()
-** function always returns SQLITE_LOCKED.
-**
-** If this function returns SQLITE_LOCKED, the caller should rollback
-** the current transaction (if any) and try again later. Otherwise, the
-** system may become deadlocked.
-*/
-int sqlite3_blocking_prepare_v2(
- sqlite3 *db, /* Database handle. */
- const char *zSql, /* UTF-8 encoded SQL statement. */
- int nSql, /* Length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const char **pz /* OUT: End of parsed string */
-){
- int rc;
- while( SQLITE_LOCKED==(rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, pz)) ){
- rc = wait_for_unlock_notify(db);
- if( rc!=SQLITE_OK ) break;
- }
- return rc;
-}
-/* END_SQLITE_BLOCKING_STEP */
-
-/*
-** Usage: sqlite3_blocking_step STMT
-**
-** Advance the statement to the next row.
-*/
-static int SQLITE_TCLAPI blocking_step_proc(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-
- sqlite3_stmt *pStmt;
- int rc;
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "STMT");
- return TCL_ERROR;
- }
-
- pStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
- rc = sqlite3_blocking_step(pStmt);
-
- Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), 0);
- return TCL_OK;
-}
-
-/*
-** Usage: sqlite3_blocking_prepare_v2 DB sql bytes ?tailvar?
-** Usage: sqlite3_nonblocking_prepare_v2 DB sql bytes ?tailvar?
-*/
-static int SQLITE_TCLAPI blocking_prepare_v2_proc(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- sqlite3 *db;
- const char *zSql;
- int bytes;
- const char *zTail = 0;
- sqlite3_stmt *pStmt = 0;
- char zBuf[50];
- int rc;
- int isBlocking = !(clientData==0);
-
- if( objc!=5 && objc!=4 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
- return TCL_ERROR;
- }
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- zSql = Tcl_GetString(objv[2]);
- if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
-
- if( isBlocking ){
- rc = sqlite3_blocking_prepare_v2(db, zSql, bytes, &pStmt, &zTail);
- }else{
- rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, &zTail);
- }
-
- assert(rc==SQLITE_OK || pStmt==0);
- if( zTail && objc>=5 ){
- if( bytes>=0 ){
- bytes = bytes - (zTail-zSql);
- }
- Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
- }
- if( rc!=SQLITE_OK ){
- assert( pStmt==0 );
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%s ", (char *)sqlite3ErrName(rc));
- Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
- return TCL_ERROR;
- }
-
- if( pStmt ){
- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
- Tcl_AppendResult(interp, zBuf, 0);
- }
- return TCL_OK;
-}
-
-#endif /* SQLITE_OS_UNIX && SQLITE_ENABLE_UNLOCK_NOTIFY */
-/*
-** End of implementation of [sqlite3_blocking_step].
-************************************************************************/
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int SqlitetestThread_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, 0, 0);
- Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0);
-#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
- Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0);
- Tcl_CreateObjCommand(interp,
- "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0);
- Tcl_CreateObjCommand(interp,
- "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0);
-#endif
- return TCL_OK;
-}
-#else
-int SqlitetestThread_Init(Tcl_Interp *interp){
- return TCL_OK;
-}
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_vfs.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_vfs.c
deleted file mode 100644
index fb987a6163a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_vfs.c
+++ /dev/null
@@ -1,1545 +0,0 @@
-/*
-** 2010 May 05
-**
-** 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 contains the implementation of the Tcl [testvfs] command,
-** used to create SQLite VFS implementations with various properties and
-** instrumentation to support testing SQLite.
-**
-** testvfs VFSNAME ?OPTIONS?
-**
-** Available options are:
-**
-** -noshm BOOLEAN (True to omit shm methods. Default false)
-** -default BOOLEAN (True to make the vfs default. Default false)
-** -szosfile INTEGER (Value for sqlite3_vfs.szOsFile)
-** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname)
-** -iversion INTEGER (Value for sqlite3_vfs.iVersion)
-*/
-#if SQLITE_TEST /* This file is used for testing only */
-
-#include "sqlite3.h"
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-typedef struct Testvfs Testvfs;
-typedef struct TestvfsShm TestvfsShm;
-typedef struct TestvfsBuffer TestvfsBuffer;
-typedef struct TestvfsFile TestvfsFile;
-typedef struct TestvfsFd TestvfsFd;
-
-/*
-** An open file handle.
-*/
-struct TestvfsFile {
- sqlite3_file base; /* Base class. Must be first */
- TestvfsFd *pFd; /* File data */
-};
-#define tvfsGetFd(pFile) (((TestvfsFile *)pFile)->pFd)
-
-struct TestvfsFd {
- sqlite3_vfs *pVfs; /* The VFS */
- const char *zFilename; /* Filename as passed to xOpen() */
- sqlite3_file *pReal; /* The real, underlying file descriptor */
- Tcl_Obj *pShmId; /* Shared memory id for Tcl callbacks */
-
- TestvfsBuffer *pShm; /* Shared memory buffer */
- u32 excllock; /* Mask of exclusive locks */
- u32 sharedlock; /* Mask of shared locks */
- TestvfsFd *pNext; /* Next handle opened on the same file */
-};
-
-
-#define FAULT_INJECT_NONE 0
-#define FAULT_INJECT_TRANSIENT 1
-#define FAULT_INJECT_PERSISTENT 2
-
-typedef struct TestFaultInject TestFaultInject;
-struct TestFaultInject {
- int iCnt; /* Remaining calls before fault injection */
- int eFault; /* A FAULT_INJECT_* value */
- int nFail; /* Number of faults injected */
-};
-
-/*
-** An instance of this structure is allocated for each VFS created. The
-** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite
-** is set to point to it.
-*/
-struct Testvfs {
- char *zName; /* Name of this VFS */
- sqlite3_vfs *pParent; /* The VFS to use for file IO */
- sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */
- Tcl_Interp *interp; /* Interpreter to run script in */
- Tcl_Obj *pScript; /* Script to execute */
- TestvfsBuffer *pBuffer; /* List of shared buffers */
- int isNoshm;
- int isFullshm;
-
- int mask; /* Mask controlling [script] and [ioerr] */
-
- TestFaultInject ioerr_err;
- TestFaultInject full_err;
- TestFaultInject cantopen_err;
-
-#if 0
- int iIoerrCnt;
- int ioerr;
- int nIoerrFail;
- int iFullCnt;
- int fullerr;
- int nFullFail;
-#endif
-
- int iDevchar;
- int iSectorsize;
-};
-
-/*
-** The Testvfs.mask variable is set to a combination of the following.
-** If a bit is clear in Testvfs.mask, then calls made by SQLite to the
-** corresponding VFS method is ignored for purposes of:
-**
-** + Simulating IO errors, and
-** + Invoking the Tcl callback script.
-*/
-#define TESTVFS_SHMOPEN_MASK 0x00000001
-#define TESTVFS_SHMLOCK_MASK 0x00000010
-#define TESTVFS_SHMMAP_MASK 0x00000020
-#define TESTVFS_SHMBARRIER_MASK 0x00000040
-#define TESTVFS_SHMCLOSE_MASK 0x00000080
-
-#define TESTVFS_OPEN_MASK 0x00000100
-#define TESTVFS_SYNC_MASK 0x00000200
-#define TESTVFS_DELETE_MASK 0x00000400
-#define TESTVFS_CLOSE_MASK 0x00000800
-#define TESTVFS_WRITE_MASK 0x00001000
-#define TESTVFS_TRUNCATE_MASK 0x00002000
-#define TESTVFS_ACCESS_MASK 0x00004000
-#define TESTVFS_FULLPATHNAME_MASK 0x00008000
-#define TESTVFS_READ_MASK 0x00010000
-#define TESTVFS_UNLOCK_MASK 0x00020000
-#define TESTVFS_LOCK_MASK 0x00040000
-#define TESTVFS_CKLOCK_MASK 0x00080000
-
-#define TESTVFS_ALL_MASK 0x000FFFFF
-
-
-#define TESTVFS_MAX_PAGES 1024
-
-/*
-** A shared-memory buffer. There is one of these objects for each shared
-** memory region opened by clients. If two clients open the same file,
-** there are two TestvfsFile structures but only one TestvfsBuffer structure.
-*/
-struct TestvfsBuffer {
- char *zFile; /* Associated file name */
- int pgsz; /* Page size */
- u8 *aPage[TESTVFS_MAX_PAGES]; /* Array of ckalloc'd pages */
- TestvfsFd *pFile; /* List of open handles */
- TestvfsBuffer *pNext; /* Next in linked list of all buffers */
-};
-
-
-#define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent)
-
-#define TESTVFS_MAX_ARGS 12
-
-
-/*
-** Method declarations for TestvfsFile.
-*/
-static int tvfsClose(sqlite3_file*);
-static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size);
-static int tvfsSync(sqlite3_file*, int flags);
-static int tvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int tvfsLock(sqlite3_file*, int);
-static int tvfsUnlock(sqlite3_file*, int);
-static int tvfsCheckReservedLock(sqlite3_file*, int *);
-static int tvfsFileControl(sqlite3_file*, int op, void *pArg);
-static int tvfsSectorSize(sqlite3_file*);
-static int tvfsDeviceCharacteristics(sqlite3_file*);
-
-/*
-** Method declarations for tvfs_vfs.
-*/
-static int tvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int tvfsDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int tvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int tvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-static void *tvfsDlOpen(sqlite3_vfs*, const char *zFilename);
-static void tvfsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*tvfsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
-static void tvfsDlClose(sqlite3_vfs*, void*);
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int tvfsSleep(sqlite3_vfs*, int microseconds);
-static int tvfsCurrentTime(sqlite3_vfs*, double*);
-
-static int tvfsShmOpen(sqlite3_file*);
-static int tvfsShmLock(sqlite3_file*, int , int, int);
-static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **);
-static void tvfsShmBarrier(sqlite3_file*);
-static int tvfsShmUnmap(sqlite3_file*, int);
-
-static int tvfsFetch(sqlite3_file*, sqlite3_int64, int, void**);
-static int tvfsUnfetch(sqlite3_file*, sqlite3_int64, void*);
-
-static sqlite3_io_methods tvfs_io_methods = {
- 3, /* iVersion */
- tvfsClose, /* xClose */
- tvfsRead, /* xRead */
- tvfsWrite, /* xWrite */
- tvfsTruncate, /* xTruncate */
- tvfsSync, /* xSync */
- tvfsFileSize, /* xFileSize */
- tvfsLock, /* xLock */
- tvfsUnlock, /* xUnlock */
- tvfsCheckReservedLock, /* xCheckReservedLock */
- tvfsFileControl, /* xFileControl */
- tvfsSectorSize, /* xSectorSize */
- tvfsDeviceCharacteristics, /* xDeviceCharacteristics */
- tvfsShmMap, /* xShmMap */
- tvfsShmLock, /* xShmLock */
- tvfsShmBarrier, /* xShmBarrier */
- tvfsShmUnmap, /* xShmUnmap */
- tvfsFetch,
- tvfsUnfetch
-};
-
-static int tvfsResultCode(Testvfs *p, int *pRc){
- struct errcode {
- int eCode;
- const char *zCode;
- } aCode[] = {
- { SQLITE_OK, "SQLITE_OK" },
- { SQLITE_ERROR, "SQLITE_ERROR" },
- { SQLITE_IOERR, "SQLITE_IOERR" },
- { SQLITE_LOCKED, "SQLITE_LOCKED" },
- { SQLITE_BUSY, "SQLITE_BUSY" },
- };
-
- const char *z;
- int i;
-
- z = Tcl_GetStringResult(p->interp);
- for(i=0; i<ArraySize(aCode); i++){
- if( 0==strcmp(z, aCode[i].zCode) ){
- *pRc = aCode[i].eCode;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int tvfsInjectFault(TestFaultInject *p){
- int ret = 0;
- if( p->eFault ){
- p->iCnt--;
- if( p->iCnt==0 || (p->iCnt<0 && p->eFault==FAULT_INJECT_PERSISTENT ) ){
- ret = 1;
- p->nFail++;
- }
- }
- return ret;
-}
-
-
-static int tvfsInjectIoerr(Testvfs *p){
- return tvfsInjectFault(&p->ioerr_err);
-}
-
-static int tvfsInjectFullerr(Testvfs *p){
- return tvfsInjectFault(&p->full_err);
-}
-static int tvfsInjectCantopenerr(Testvfs *p){
- return tvfsInjectFault(&p->cantopen_err);
-}
-
-
-static void tvfsExecTcl(
- Testvfs *p,
- const char *zMethod,
- Tcl_Obj *arg1,
- Tcl_Obj *arg2,
- Tcl_Obj *arg3,
- Tcl_Obj *arg4
-){
- int rc; /* Return code from Tcl_EvalObj() */
- Tcl_Obj *pEval;
- assert( p->pScript );
-
- assert( zMethod );
- assert( p );
- assert( arg2==0 || arg1!=0 );
- assert( arg3==0 || arg2!=0 );
-
- pEval = Tcl_DuplicateObj(p->pScript);
- Tcl_IncrRefCount(p->pScript);
- Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zMethod, -1));
- if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1);
- if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2);
- if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3);
- if( arg4 ) Tcl_ListObjAppendElement(p->interp, pEval, arg4);
-
- rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
- if( rc!=TCL_OK ){
- Tcl_BackgroundError(p->interp);
- Tcl_ResetResult(p->interp);
- }
-}
-
-
-/*
-** Close an tvfs-file.
-*/
-static int tvfsClose(sqlite3_file *pFile){
- TestvfsFile *pTestfile = (TestvfsFile *)pFile;
- TestvfsFd *pFd = pTestfile->pFd;
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
-
- if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){
- tvfsExecTcl(p, "xClose",
- Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
- );
- }
-
- if( pFd->pShmId ){
- Tcl_DecrRefCount(pFd->pShmId);
- pFd->pShmId = 0;
- }
- if( pFile->pMethods ){
- ckfree((char *)pFile->pMethods);
- }
- sqlite3OsClose(pFd->pReal);
- ckfree((char *)pFd);
- pTestfile->pFd = 0;
- return SQLITE_OK;
-}
-
-/*
-** Read data from an tvfs-file.
-*/
-static int tvfsRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc = SQLITE_OK;
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
- if( p->pScript && p->mask&TESTVFS_READ_MASK ){
- tvfsExecTcl(p, "xRead",
- Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
- );
- tvfsResultCode(p, &rc);
- }
- if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){
- rc = SQLITE_IOERR;
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3OsRead(pFd->pReal, zBuf, iAmt, iOfst);
- }
- return rc;
-}
-
-/*
-** Write data to an tvfs-file.
-*/
-static int tvfsWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- int rc = SQLITE_OK;
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
-
- if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
- tvfsExecTcl(p, "xWrite",
- Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
- Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt)
- );
- tvfsResultCode(p, &rc);
- }
-
- if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){
- rc = SQLITE_FULL;
- }
- if( rc==SQLITE_OK && p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
- rc = SQLITE_IOERR;
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pFd->pReal, zBuf, iAmt, iOfst);
- }
- return rc;
-}
-
-/*
-** Truncate an tvfs-file.
-*/
-static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
- int rc = SQLITE_OK;
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
-
- if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){
- tvfsExecTcl(p, "xTruncate",
- Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
- );
- tvfsResultCode(p, &rc);
- }
-
- if( rc==SQLITE_OK ){
- rc = sqlite3OsTruncate(pFd->pReal, size);
- }
- return rc;
-}
-
-/*
-** Sync an tvfs-file.
-*/
-static int tvfsSync(sqlite3_file *pFile, int flags){
- int rc = SQLITE_OK;
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
-
- if( p->pScript && p->mask&TESTVFS_SYNC_MASK ){
- char *zFlags = 0;
-
- switch( flags ){
- case SQLITE_SYNC_NORMAL:
- zFlags = "normal";
- break;
- case SQLITE_SYNC_FULL:
- zFlags = "full";
- break;
- case SQLITE_SYNC_NORMAL|SQLITE_SYNC_DATAONLY:
- zFlags = "normal|dataonly";
- break;
- case SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY:
- zFlags = "full|dataonly";
- break;
- default:
- assert(0);
- }
-
- tvfsExecTcl(p, "xSync",
- Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
- Tcl_NewStringObj(zFlags, -1), 0
- );
- tvfsResultCode(p, &rc);
- }
-
- if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL;
-
- if( rc==SQLITE_OK ){
- rc = sqlite3OsSync(pFd->pReal, flags);
- }
-
- return rc;
-}
-
-/*
-** Return the current file-size of an tvfs-file.
-*/
-static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- TestvfsFd *p = tvfsGetFd(pFile);
- return sqlite3OsFileSize(p->pReal, pSize);
-}
-
-/*
-** Lock an tvfs-file.
-*/
-static int tvfsLock(sqlite3_file *pFile, int eLock){
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
- if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){
- char zLock[30];
- sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
- tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1),
- Tcl_NewStringObj(zLock, -1), 0, 0);
- }
- return sqlite3OsLock(pFd->pReal, eLock);
-}
-
-/*
-** Unlock an tvfs-file.
-*/
-static int tvfsUnlock(sqlite3_file *pFile, int eLock){
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
- if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){
- char zLock[30];
- sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
- tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1),
- Tcl_NewStringObj(zLock, -1), 0, 0);
- }
- if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
- return SQLITE_IOERR_UNLOCK;
- }
- return sqlite3OsUnlock(pFd->pReal, eLock);
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an tvfs-file.
-*/
-static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
- if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){
- tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1),
- 0, 0, 0);
- }
- return sqlite3OsCheckReservedLock(pFd->pReal, pResOut);
-}
-
-/*
-** File control method. For custom operations on an tvfs-file.
-*/
-static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
- TestvfsFd *p = tvfsGetFd(pFile);
- if( op==SQLITE_FCNTL_PRAGMA ){
- char **argv = (char**)pArg;
- if( sqlite3_stricmp(argv[1],"error")==0 ){
- int rc = SQLITE_ERROR;
- if( argv[2] ){
- const char *z = argv[2];
- int x = atoi(z);
- if( x ){
- rc = x;
- while( sqlite3Isdigit(z[0]) ){ z++; }
- while( sqlite3Isspace(z[0]) ){ z++; }
- }
- if( z[0] ) argv[0] = sqlite3_mprintf("%s", z);
- }
- return rc;
- }
- if( sqlite3_stricmp(argv[1], "filename")==0 ){
- argv[0] = sqlite3_mprintf("%s", p->zFilename);
- return SQLITE_OK;
- }
- }
- return sqlite3OsFileControl(p->pReal, op, pArg);
-}
-
-/*
-** Return the sector-size in bytes for an tvfs-file.
-*/
-static int tvfsSectorSize(sqlite3_file *pFile){
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
- if( p->iSectorsize>=0 ){
- return p->iSectorsize;
- }
- return sqlite3OsSectorSize(pFd->pReal);
-}
-
-/*
-** Return the device characteristic flags supported by an tvfs-file.
-*/
-static int tvfsDeviceCharacteristics(sqlite3_file *pFile){
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
- if( p->iDevchar>=0 ){
- return p->iDevchar;
- }
- return sqlite3OsDeviceCharacteristics(pFd->pReal);
-}
-
-/*
-** Open an tvfs file handle.
-*/
-static int tvfsOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- int rc;
- TestvfsFile *pTestfile = (TestvfsFile *)pFile;
- TestvfsFd *pFd;
- Tcl_Obj *pId = 0;
- Testvfs *p = (Testvfs *)pVfs->pAppData;
-
- pFd = (TestvfsFd *)ckalloc(sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile);
- memset(pFd, 0, sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile);
- pFd->pShm = 0;
- pFd->pShmId = 0;
- pFd->zFilename = zName;
- pFd->pVfs = pVfs;
- pFd->pReal = (sqlite3_file *)&pFd[1];
- memset(pTestfile, 0, sizeof(TestvfsFile));
- pTestfile->pFd = pFd;
-
- /* Evaluate the Tcl script:
- **
- ** SCRIPT xOpen FILENAME KEY-VALUE-ARGS
- **
- ** If the script returns an SQLite error code other than SQLITE_OK, an
- ** error is returned to the caller. If it returns SQLITE_OK, the new
- ** connection is named "anon". Otherwise, the value returned by the
- ** script is used as the connection name.
- */
- Tcl_ResetResult(p->interp);
- if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){
- Tcl_Obj *pArg = Tcl_NewObj();
- Tcl_IncrRefCount(pArg);
- if( flags&SQLITE_OPEN_MAIN_DB ){
- const char *z = &zName[strlen(zName)+1];
- while( *z ){
- Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
- z += strlen(z) + 1;
- Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
- z += strlen(z) + 1;
- }
- }
- tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0);
- Tcl_DecrRefCount(pArg);
- if( tvfsResultCode(p, &rc) ){
- if( rc!=SQLITE_OK ) return rc;
- }else{
- pId = Tcl_GetObjResult(p->interp);
- }
- }
-
- if( (p->mask&TESTVFS_OPEN_MASK) && tvfsInjectIoerr(p) ) return SQLITE_IOERR;
- if( tvfsInjectCantopenerr(p) ) return SQLITE_CANTOPEN;
- if( tvfsInjectFullerr(p) ) return SQLITE_FULL;
-
- if( !pId ){
- pId = Tcl_NewStringObj("anon", -1);
- }
- Tcl_IncrRefCount(pId);
- pFd->pShmId = pId;
- Tcl_ResetResult(p->interp);
-
- rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd->pReal, flags, pOutFlags);
- if( pFd->pReal->pMethods ){
- sqlite3_io_methods *pMethods;
- int nByte;
-
- if( pVfs->iVersion>1 ){
- nByte = sizeof(sqlite3_io_methods);
- }else{
- nByte = offsetof(sqlite3_io_methods, xShmMap);
- }
-
- pMethods = (sqlite3_io_methods *)ckalloc(nByte);
- memcpy(pMethods, &tvfs_io_methods, nByte);
- pMethods->iVersion = pFd->pReal->pMethods->iVersion;
- if( pMethods->iVersion>pVfs->iVersion ){
- pMethods->iVersion = pVfs->iVersion;
- }
- if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){
- pMethods->xShmUnmap = 0;
- pMethods->xShmLock = 0;
- pMethods->xShmBarrier = 0;
- pMethods->xShmMap = 0;
- }
- pFile->pMethods = pMethods;
- }
-
- return rc;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- int rc = SQLITE_OK;
- Testvfs *p = (Testvfs *)pVfs->pAppData;
-
- if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){
- tvfsExecTcl(p, "xDelete",
- Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0
- );
- tvfsResultCode(p, &rc);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync);
- }
- return rc;
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int tvfsAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- Testvfs *p = (Testvfs *)pVfs->pAppData;
- if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){
- int rc;
- char *zArg = 0;
- if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS";
- if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE";
- if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ";
- tvfsExecTcl(p, "xAccess",
- Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0
- );
- if( tvfsResultCode(p, &rc) ){
- if( rc!=SQLITE_OK ) return rc;
- }else{
- Tcl_Interp *interp = p->interp;
- if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){
- return SQLITE_OK;
- }
- }
- }
- return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut);
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
-*/
-static int tvfsFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- Testvfs *p = (Testvfs *)pVfs->pAppData;
- if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
- int rc;
- tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0);
- if( tvfsResultCode(p, &rc) ){
- if( rc!=SQLITE_OK ) return rc;
- }
- }
- return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
-}
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *tvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- return sqlite3OsDlOpen(PARENTVFS(pVfs), zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void tvfsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- sqlite3OsDlError(PARENTVFS(pVfs), nByte, zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*tvfsDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
- return sqlite3OsDlSym(PARENTVFS(pVfs), p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void tvfsDlClose(sqlite3_vfs *pVfs, void *pHandle){
- sqlite3OsDlClose(PARENTVFS(pVfs), pHandle);
-}
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int tvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return sqlite3OsRandomness(PARENTVFS(pVfs), nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int tvfsSleep(sqlite3_vfs *pVfs, int nMicro){
- return sqlite3OsSleep(PARENTVFS(pVfs), nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut);
-}
-
-static int tvfsShmOpen(sqlite3_file *pFile){
- Testvfs *p;
- int rc = SQLITE_OK; /* Return code */
- TestvfsBuffer *pBuffer; /* Buffer to open connection to */
- TestvfsFd *pFd; /* The testvfs file structure */
-
- pFd = tvfsGetFd(pFile);
- p = (Testvfs *)pFd->pVfs->pAppData;
- assert( 0==p->isFullshm );
- assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 );
-
- /* Evaluate the Tcl script:
- **
- ** SCRIPT xShmOpen FILENAME
- */
- Tcl_ResetResult(p->interp);
- if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){
- tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0, 0);
- if( tvfsResultCode(p, &rc) ){
- if( rc!=SQLITE_OK ) return rc;
- }
- }
-
- assert( rc==SQLITE_OK );
- if( p->mask&TESTVFS_SHMOPEN_MASK && tvfsInjectIoerr(p) ){
- return SQLITE_IOERR;
- }
-
- /* Search for a TestvfsBuffer. Create a new one if required. */
- for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
- if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break;
- }
- if( !pBuffer ){
- int szName = (int)strlen(pFd->zFilename);
- int nByte = sizeof(TestvfsBuffer) + szName + 1;
- pBuffer = (TestvfsBuffer *)ckalloc(nByte);
- memset(pBuffer, 0, nByte);
- pBuffer->zFile = (char *)&pBuffer[1];
- memcpy(pBuffer->zFile, pFd->zFilename, szName+1);
- pBuffer->pNext = p->pBuffer;
- p->pBuffer = pBuffer;
- }
-
- /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */
- pFd->pNext = pBuffer->pFile;
- pBuffer->pFile = pFd;
- pFd->pShm = pBuffer;
- return SQLITE_OK;
-}
-
-static void tvfsAllocPage(TestvfsBuffer *p, int iPage, int pgsz){
- assert( iPage<TESTVFS_MAX_PAGES );
- if( p->aPage[iPage]==0 ){
- p->aPage[iPage] = (u8 *)ckalloc(pgsz);
- memset(p->aPage[iPage], 0, pgsz);
- p->pgsz = pgsz;
- }
-}
-
-static int tvfsShmMap(
- sqlite3_file *pFile, /* Handle open on database file */
- int iPage, /* Page to retrieve */
- int pgsz, /* Size of pages */
- int isWrite, /* True to extend file if necessary */
- void volatile **pp /* OUT: Mapped memory */
-){
- int rc = SQLITE_OK;
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
-
- if( p->isFullshm ){
- return sqlite3OsShmMap(pFd->pReal, iPage, pgsz, isWrite, pp);
- }
-
- if( 0==pFd->pShm ){
- rc = tvfsShmOpen(pFile);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
-
- if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){
- Tcl_Obj *pArg = Tcl_NewObj();
- Tcl_IncrRefCount(pArg);
- Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage));
- Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz));
- Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite));
- tvfsExecTcl(p, "xShmMap",
- Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg, 0
- );
- tvfsResultCode(p, &rc);
- Tcl_DecrRefCount(pArg);
- }
- if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){
- rc = SQLITE_IOERR;
- }
-
- if( rc==SQLITE_OK && isWrite && !pFd->pShm->aPage[iPage] ){
- tvfsAllocPage(pFd->pShm, iPage, pgsz);
- }
- *pp = (void volatile *)pFd->pShm->aPage[iPage];
-
- return rc;
-}
-
-
-static int tvfsShmLock(
- sqlite3_file *pFile,
- int ofst,
- int n,
- int flags
-){
- int rc = SQLITE_OK;
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
- int nLock;
- char zLock[80];
-
- if( p->isFullshm ){
- return sqlite3OsShmLock(pFd->pReal, ofst, n, flags);
- }
-
- if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){
- sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n);
- nLock = (int)strlen(zLock);
- if( flags & SQLITE_SHM_LOCK ){
- strcpy(&zLock[nLock], " lock");
- }else{
- strcpy(&zLock[nLock], " unlock");
- }
- nLock += (int)strlen(&zLock[nLock]);
- if( flags & SQLITE_SHM_SHARED ){
- strcpy(&zLock[nLock], " shared");
- }else{
- strcpy(&zLock[nLock], " exclusive");
- }
- tvfsExecTcl(p, "xShmLock",
- Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
- Tcl_NewStringObj(zLock, -1), 0
- );
- tvfsResultCode(p, &rc);
- }
-
- if( rc==SQLITE_OK && p->mask&TESTVFS_SHMLOCK_MASK && tvfsInjectIoerr(p) ){
- rc = SQLITE_IOERR;
- }
-
- if( rc==SQLITE_OK ){
- int isLock = (flags & SQLITE_SHM_LOCK);
- int isExcl = (flags & SQLITE_SHM_EXCLUSIVE);
- u32 mask = (((1<<n)-1) << ofst);
- if( isLock ){
- TestvfsFd *p2;
- for(p2=pFd->pShm->pFile; p2; p2=p2->pNext){
- if( p2==pFd ) continue;
- if( (p2->excllock&mask) || (isExcl && p2->sharedlock&mask) ){
- rc = SQLITE_BUSY;
- break;
- }
- }
- if( rc==SQLITE_OK ){
- if( isExcl ) pFd->excllock |= mask;
- if( !isExcl ) pFd->sharedlock |= mask;
- }
- }else{
- if( isExcl ) pFd->excllock &= (~mask);
- if( !isExcl ) pFd->sharedlock &= (~mask);
- }
- }
-
- return rc;
-}
-
-static void tvfsShmBarrier(sqlite3_file *pFile){
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
-
- if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
- const char *z = pFd->pShm ? pFd->pShm->zFile : "";
- tvfsExecTcl(p, "xShmBarrier", Tcl_NewStringObj(z, -1), pFd->pShmId, 0, 0);
- }
-
- if( p->isFullshm ){
- sqlite3OsShmBarrier(pFd->pReal);
- return;
- }
-}
-
-static int tvfsShmUnmap(
- sqlite3_file *pFile,
- int deleteFlag
-){
- int rc = SQLITE_OK;
- TestvfsFd *pFd = tvfsGetFd(pFile);
- Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
- TestvfsBuffer *pBuffer = pFd->pShm;
- TestvfsFd **ppFd;
-
- if( p->isFullshm ){
- return sqlite3OsShmUnmap(pFd->pReal, deleteFlag);
- }
-
- if( !pBuffer ) return SQLITE_OK;
- assert( pFd->pShmId && pFd->pShm );
-
- if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){
- tvfsExecTcl(p, "xShmUnmap",
- Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
- );
- tvfsResultCode(p, &rc);
- }
-
- for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext));
- assert( (*ppFd)==pFd );
- *ppFd = pFd->pNext;
- pFd->pNext = 0;
-
- if( pBuffer->pFile==0 ){
- int i;
- TestvfsBuffer **pp;
- for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext));
- *pp = (*pp)->pNext;
- for(i=0; pBuffer->aPage[i]; i++){
- ckfree((char *)pBuffer->aPage[i]);
- }
- ckfree((char *)pBuffer);
- }
- pFd->pShm = 0;
-
- return rc;
-}
-
-static int tvfsFetch(
- sqlite3_file *pFile,
- sqlite3_int64 iOfst,
- int iAmt,
- void **pp
-){
- TestvfsFd *pFd = tvfsGetFd(pFile);
- return sqlite3OsFetch(pFd->pReal, iOfst, iAmt, pp);
-}
-
-static int tvfsUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *p){
- TestvfsFd *pFd = tvfsGetFd(pFile);
- return sqlite3OsUnfetch(pFd->pReal, iOfst, p);
-}
-
-static int SQLITE_TCLAPI testvfs_obj_cmd(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Testvfs *p = (Testvfs *)cd;
-
- enum DB_enum {
- CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT,
- CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR, CMD_CANTOPENERR
- };
- struct TestvfsSubcmd {
- char *zName;
- enum DB_enum eCmd;
- } aSubcmd[] = {
- { "shm", CMD_SHM },
- { "delete", CMD_DELETE },
- { "filter", CMD_FILTER },
- { "ioerr", CMD_IOERR },
- { "fullerr", CMD_FULLERR },
- { "cantopenerr", CMD_CANTOPENERR },
- { "script", CMD_SCRIPT },
- { "devchar", CMD_DEVCHAR },
- { "sectorsize", CMD_SECTORSIZE },
- { 0, 0 }
- };
- int i;
-
- if( objc<2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
- return TCL_ERROR;
- }
- if( Tcl_GetIndexFromObjStruct(
- interp, objv[1], aSubcmd, sizeof(aSubcmd[0]), "subcommand", 0, &i)
- ){
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
-
- switch( aSubcmd[i].eCmd ){
- case CMD_SHM: {
- Tcl_Obj *pObj;
- int rc;
- TestvfsBuffer *pBuffer;
- char *zName;
- if( objc!=3 && objc!=4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "FILE ?VALUE?");
- return TCL_ERROR;
- }
- zName = ckalloc(p->pParent->mxPathname);
- rc = p->pParent->xFullPathname(
- p->pParent, Tcl_GetString(objv[2]),
- p->pParent->mxPathname, zName
- );
- if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, "failed to get full path: ",
- Tcl_GetString(objv[2]), 0);
- ckfree(zName);
- return TCL_ERROR;
- }
- for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
- if( 0==strcmp(pBuffer->zFile, zName) ) break;
- }
- ckfree(zName);
- if( !pBuffer ){
- Tcl_AppendResult(interp, "no such file: ", Tcl_GetString(objv[2]), 0);
- return TCL_ERROR;
- }
- if( objc==4 ){
- int n;
- u8 *a = Tcl_GetByteArrayFromObj(objv[3], &n);
- int pgsz = pBuffer->pgsz;
- if( pgsz==0 ) pgsz = 65536;
- for(i=0; i*pgsz<n; i++){
- int nByte = pgsz;
- tvfsAllocPage(pBuffer, i, pgsz);
- if( n-i*pgsz<pgsz ){
- nByte = n;
- }
- memcpy(pBuffer->aPage[i], &a[i*pgsz], nByte);
- }
- }
-
- pObj = Tcl_NewObj();
- for(i=0; pBuffer->aPage[i]; i++){
- int pgsz = pBuffer->pgsz;
- if( pgsz==0 ) pgsz = 65536;
- Tcl_AppendObjToObj(pObj, Tcl_NewByteArrayObj(pBuffer->aPage[i], pgsz));
- }
- Tcl_SetObjResult(interp, pObj);
- break;
- }
-
- /* TESTVFS filter METHOD-LIST
- **
- ** Activate special processing for those methods contained in the list
- */
- case CMD_FILTER: {
- static struct VfsMethod {
- char *zName;
- int mask;
- } vfsmethod [] = {
- { "xShmOpen", TESTVFS_SHMOPEN_MASK },
- { "xShmLock", TESTVFS_SHMLOCK_MASK },
- { "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
- { "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
- { "xShmMap", TESTVFS_SHMMAP_MASK },
- { "xSync", TESTVFS_SYNC_MASK },
- { "xDelete", TESTVFS_DELETE_MASK },
- { "xWrite", TESTVFS_WRITE_MASK },
- { "xRead", TESTVFS_READ_MASK },
- { "xTruncate", TESTVFS_TRUNCATE_MASK },
- { "xOpen", TESTVFS_OPEN_MASK },
- { "xClose", TESTVFS_CLOSE_MASK },
- { "xAccess", TESTVFS_ACCESS_MASK },
- { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
- { "xUnlock", TESTVFS_UNLOCK_MASK },
- { "xLock", TESTVFS_LOCK_MASK },
- { "xCheckReservedLock", TESTVFS_CKLOCK_MASK },
- };
- Tcl_Obj **apElem = 0;
- int nElem = 0;
- int mask = 0;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "LIST");
- return TCL_ERROR;
- }
- if( Tcl_ListObjGetElements(interp, objv[2], &nElem, &apElem) ){
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- for(i=0; i<nElem; i++){
- int iMethod;
- char *zElem = Tcl_GetString(apElem[i]);
- for(iMethod=0; iMethod<ArraySize(vfsmethod); iMethod++){
- if( strcmp(zElem, vfsmethod[iMethod].zName)==0 ){
- mask |= vfsmethod[iMethod].mask;
- break;
- }
- }
- if( iMethod==ArraySize(vfsmethod) ){
- Tcl_AppendResult(interp, "unknown method: ", zElem, 0);
- return TCL_ERROR;
- }
- }
- p->mask = mask;
- break;
- }
-
- /*
- ** TESTVFS script ?SCRIPT?
- **
- ** Query or set the script to be run when filtered VFS events
- ** occur.
- */
- case CMD_SCRIPT: {
- if( objc==3 ){
- int nByte;
- if( p->pScript ){
- Tcl_DecrRefCount(p->pScript);
- p->pScript = 0;
- }
- Tcl_GetStringFromObj(objv[2], &nByte);
- if( nByte>0 ){
- p->pScript = Tcl_DuplicateObj(objv[2]);
- Tcl_IncrRefCount(p->pScript);
- }
- }else if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
- return TCL_ERROR;
- }
-
- Tcl_ResetResult(interp);
- if( p->pScript ) Tcl_SetObjResult(interp, p->pScript);
-
- break;
- }
-
- /*
- ** TESTVFS ioerr ?IFAIL PERSIST?
- **
- ** Where IFAIL is an integer and PERSIST is boolean.
- */
- case CMD_CANTOPENERR:
- case CMD_IOERR:
- case CMD_FULLERR: {
- TestFaultInject *pTest = 0;
- int iRet;
-
- switch( aSubcmd[i].eCmd ){
- case CMD_IOERR: pTest = &p->ioerr_err; break;
- case CMD_FULLERR: pTest = &p->full_err; break;
- case CMD_CANTOPENERR: pTest = &p->cantopen_err; break;
- default: assert(0);
- }
- iRet = pTest->nFail;
- pTest->nFail = 0;
- pTest->eFault = 0;
- pTest->iCnt = 0;
-
- if( objc==4 ){
- int iCnt, iPersist;
- if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iCnt)
- || TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &iPersist)
- ){
- return TCL_ERROR;
- }
- pTest->eFault = iPersist?FAULT_INJECT_PERSISTENT:FAULT_INJECT_TRANSIENT;
- pTest->iCnt = iCnt;
- }else if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?CNT PERSIST?");
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(iRet));
- break;
- }
-
- case CMD_DELETE: {
- Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
- break;
- }
-
- case CMD_DEVCHAR: {
- struct DeviceFlag {
- char *zName;
- int iValue;
- } aFlag[] = {
- { "default", -1 },
- { "atomic", SQLITE_IOCAP_ATOMIC },
- { "atomic512", SQLITE_IOCAP_ATOMIC512 },
- { "atomic1k", SQLITE_IOCAP_ATOMIC1K },
- { "atomic2k", SQLITE_IOCAP_ATOMIC2K },
- { "atomic4k", SQLITE_IOCAP_ATOMIC4K },
- { "atomic8k", SQLITE_IOCAP_ATOMIC8K },
- { "atomic16k", SQLITE_IOCAP_ATOMIC16K },
- { "atomic32k", SQLITE_IOCAP_ATOMIC32K },
- { "atomic64k", SQLITE_IOCAP_ATOMIC64K },
- { "sequential", SQLITE_IOCAP_SEQUENTIAL },
- { "safe_append", SQLITE_IOCAP_SAFE_APPEND },
- { "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN },
- { "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
- { "immutable", SQLITE_IOCAP_IMMUTABLE },
- { 0, 0 }
- };
- Tcl_Obj *pRet;
- int iFlag;
-
- if( objc>3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?ATTR-LIST?");
- return TCL_ERROR;
- }
- if( objc==3 ){
- int j;
- int iNew = 0;
- Tcl_Obj **flags = 0;
- int nFlags = 0;
-
- if( Tcl_ListObjGetElements(interp, objv[2], &nFlags, &flags) ){
- return TCL_ERROR;
- }
-
- for(j=0; j<nFlags; j++){
- int idx = 0;
- if( Tcl_GetIndexFromObjStruct(interp, flags[j], aFlag,
- sizeof(aFlag[0]), "flag", 0, &idx)
- ){
- return TCL_ERROR;
- }
- if( aFlag[idx].iValue<0 && nFlags>1 ){
- Tcl_AppendResult(interp, "bad flags: ", Tcl_GetString(objv[2]), 0);
- return TCL_ERROR;
- }
- iNew |= aFlag[idx].iValue;
- }
-
- p->iDevchar = iNew| 0x10000000;
- }
-
- pRet = Tcl_NewObj();
- for(iFlag=0; iFlag<sizeof(aFlag)/sizeof(aFlag[0]); iFlag++){
- if( p->iDevchar & aFlag[iFlag].iValue ){
- Tcl_ListObjAppendElement(
- interp, pRet, Tcl_NewStringObj(aFlag[iFlag].zName, -1)
- );
- }
- }
- Tcl_SetObjResult(interp, pRet);
-
- break;
- }
-
- case CMD_SECTORSIZE: {
- if( objc>3 ){
- Tcl_WrongNumArgs(interp, 2, objv, "?VALUE?");
- return TCL_ERROR;
- }
- if( objc==3 ){
- int iNew = 0;
- if( Tcl_GetIntFromObj(interp, objv[2], &iNew) ){
- return TCL_ERROR;
- }
- p->iSectorsize = iNew;
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(p->iSectorsize));
- break;
- }
- }
-
- return TCL_OK;
-}
-
-static void SQLITE_TCLAPI testvfs_obj_del(ClientData cd){
- Testvfs *p = (Testvfs *)cd;
- if( p->pScript ) Tcl_DecrRefCount(p->pScript);
- sqlite3_vfs_unregister(p->pVfs);
- ckfree((char *)p->pVfs);
- ckfree((char *)p);
-}
-
-/*
-** Usage: testvfs VFSNAME ?SWITCHES?
-**
-** Switches are:
-**
-** -noshm BOOLEAN (True to omit shm methods. Default false)
-** -default BOOLEAN (True to make the vfs default. Default false)
-**
-** This command creates two things when it is invoked: an SQLite VFS, and
-** a Tcl command. Both are named VFSNAME. The VFS is installed. It is not
-** installed as the default VFS.
-**
-** The VFS passes all file I/O calls through to the underlying VFS.
-**
-** Whenever the xShmMap method of the VFS
-** is invoked, the SCRIPT is executed as follows:
-**
-** SCRIPT xShmMap FILENAME ID
-**
-** The value returned by the invocation of SCRIPT above is interpreted as
-** an SQLite error code and returned to SQLite. Either a symbolic
-** "SQLITE_OK" or numeric "0" value may be returned.
-**
-** The contents of the shared-memory buffer associated with a given file
-** may be read and set using the following command:
-**
-** VFSNAME shm FILENAME ?NEWVALUE?
-**
-** When the xShmLock method is invoked by SQLite, the following script is
-** run:
-**
-** SCRIPT xShmLock FILENAME ID LOCK
-**
-** where LOCK is of the form "OFFSET NBYTE lock/unlock shared/exclusive"
-*/
-static int SQLITE_TCLAPI testvfs_cmd(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- static sqlite3_vfs tvfs_vfs = {
- 3, /* iVersion */
- 0, /* szOsFile */
- 0, /* mxPathname */
- 0, /* pNext */
- 0, /* zName */
- 0, /* pAppData */
- tvfsOpen, /* xOpen */
- tvfsDelete, /* xDelete */
- tvfsAccess, /* xAccess */
- tvfsFullPathname, /* xFullPathname */
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- tvfsDlOpen, /* xDlOpen */
- tvfsDlError, /* xDlError */
- tvfsDlSym, /* xDlSym */
- tvfsDlClose, /* xDlClose */
-#else
- 0, /* xDlOpen */
- 0, /* xDlError */
- 0, /* xDlSym */
- 0, /* xDlClose */
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
- tvfsRandomness, /* xRandomness */
- tvfsSleep, /* xSleep */
- tvfsCurrentTime, /* xCurrentTime */
- 0, /* xGetLastError */
- 0, /* xCurrentTimeInt64 */
- 0, /* xSetSystemCall */
- 0, /* xGetSystemCall */
- 0, /* xNextSystemCall */
- };
-
- Testvfs *p; /* New object */
- sqlite3_vfs *pVfs; /* New VFS */
- char *zVfs;
- int nByte; /* Bytes of space to allocate at p */
-
- int i;
- int isNoshm = 0; /* True if -noshm is passed */
- int isFullshm = 0; /* True if -fullshm is passed */
- int isDefault = 0; /* True if -default is passed */
- int szOsFile = 0; /* Value passed to -szosfile */
- int mxPathname = -1; /* Value passed to -mxpathname */
- int iVersion = 3; /* Value passed to -iversion */
-
- if( objc<2 || 0!=(objc%2) ) goto bad_args;
- for(i=2; i<objc; i += 2){
- int nSwitch;
- char *zSwitch;
- zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch);
-
- if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){
- if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){
- return TCL_ERROR;
- }
- if( isNoshm ) isFullshm = 0;
- }
- else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){
- if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){
- return TCL_ERROR;
- }
- }
- else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){
- if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){
- return TCL_ERROR;
- }
- }
- else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){
- if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){
- return TCL_ERROR;
- }
- }
- else if( nSwitch>2 && 0==strncmp("-iversion", zSwitch, nSwitch) ){
- if( Tcl_GetIntFromObj(interp, objv[i+1], &iVersion) ){
- return TCL_ERROR;
- }
- }
- else if( nSwitch>2 && 0==strncmp("-fullshm", zSwitch, nSwitch) ){
- if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isFullshm) ){
- return TCL_ERROR;
- }
- if( isFullshm ) isNoshm = 0;
- }
- else{
- goto bad_args;
- }
- }
-
- if( szOsFile<sizeof(TestvfsFile) ){
- szOsFile = sizeof(TestvfsFile);
- }
-
- zVfs = Tcl_GetString(objv[1]);
- nByte = sizeof(Testvfs) + (int)strlen(zVfs)+1;
- p = (Testvfs *)ckalloc(nByte);
- memset(p, 0, nByte);
- p->iDevchar = -1;
- p->iSectorsize = -1;
-
- /* Create the new object command before querying SQLite for a default VFS
- ** to use for 'real' IO operations. This is because creating the new VFS
- ** may delete an existing [testvfs] VFS of the same name. If such a VFS
- ** is currently the default, the new [testvfs] may end up calling the
- ** methods of a deleted object.
- */
- Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del);
- p->pParent = sqlite3_vfs_find(0);
- p->interp = interp;
-
- p->zName = (char *)&p[1];
- memcpy(p->zName, zVfs, strlen(zVfs)+1);
-
- pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs));
- memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs));
- pVfs->pAppData = (void *)p;
- pVfs->iVersion = iVersion;
- pVfs->zName = p->zName;
- pVfs->mxPathname = p->pParent->mxPathname;
- if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){
- pVfs->mxPathname = mxPathname;
- }
- pVfs->szOsFile = szOsFile;
- p->pVfs = pVfs;
- p->isNoshm = isNoshm;
- p->isFullshm = isFullshm;
- p->mask = TESTVFS_ALL_MASK;
-
- sqlite3_vfs_register(pVfs, isDefault);
-
- return TCL_OK;
-
- bad_args:
- Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-fullshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?");
- return TCL_ERROR;
-}
-
-int Sqlitetestvfs_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0);
- return TCL_OK;
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_vfstrace.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_vfstrace.c
deleted file mode 100644
index d0bc29f0c3c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_vfstrace.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
-** 2011 March 16
-**
-** 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 contains code implements a VFS shim that writes diagnostic
-** output for each VFS call, similar to "strace".
-**
-** USAGE:
-**
-** This source file exports a single symbol which is the name of a
-** function:
-**
-** int vfstrace_register(
-** const char *zTraceName, // Name of the newly constructed VFS
-** const char *zOldVfsName, // Name of the underlying VFS
-** int (*xOut)(const char*,void*), // Output routine. ex: fputs
-** void *pOutArg, // 2nd argument to xOut. ex: stderr
-** int makeDefault // Make the new VFS the default
-** );
-**
-** Applications that want to trace their VFS usage must provide a callback
-** function with this prototype:
-**
-** int traceOutput(const char *zMessage, void *pAppData);
-**
-** This function will "output" the trace messages, where "output" can
-** mean different things to different applications. The traceOutput function
-** for the command-line shell (see shell.c) is "fputs" from the standard
-** library, which means that all trace output is written on the stream
-** specified by the second argument. In the case of the command-line shell
-** the second argument is stderr. Other applications might choose to output
-** trace information to a file, over a socket, or write it into a buffer.
-**
-** The vfstrace_register() function creates a new "shim" VFS named by
-** the zTraceName parameter. A "shim" VFS is an SQLite backend that does
-** not really perform the duties of a true backend, but simply filters or
-** interprets VFS calls before passing them off to another VFS which does
-** the actual work. In this case the other VFS - the one that does the
-** real work - is identified by the second parameter, zOldVfsName. If
-** the 2nd parameter is NULL then the default VFS is used. The common
-** case is for the 2nd parameter to be NULL.
-**
-** The third and fourth parameters are the pointer to the output function
-** and the second argument to the output function. For the SQLite
-** command-line shell, when the -vfstrace option is used, these parameters
-** are fputs and stderr, respectively.
-**
-** The fifth argument is true (non-zero) to cause the newly created VFS
-** to become the default VFS. The common case is for the fifth parameter
-** to be true.
-**
-** The call to vfstrace_register() simply creates the shim VFS that does
-** tracing. The application must also arrange to use the new VFS for
-** all database connections that are created and for which tracing is
-** desired. This can be done by specifying the trace VFS using URI filename
-** notation, or by specifying the trace VFS as the 4th parameter to
-** sqlite3_open_v2() or by making the trace VFS be the default (by setting
-** the 5th parameter of vfstrace_register() to 1).
-**
-**
-** ENABLING VFSTRACE IN A COMMAND-LINE SHELL
-**
-** The SQLite command line shell implemented by the shell.c source file
-** can be used with this module. To compile in -vfstrace support, first
-** gather this file (test_vfstrace.c), the shell source file (shell.c),
-** and the SQLite amalgamation source files (sqlite3.c, sqlite3.h) into
-** the working directory. Then compile using a command like the following:
-**
-** gcc -o sqlite3 -Os -I. -DSQLITE_ENABLE_VFSTRACE \
-** -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
-** -DHAVE_READLINE -DHAVE_USLEEP=1 \
-** shell.c test_vfstrace.c sqlite3.c -ldl -lreadline -lncurses
-**
-** The gcc command above works on Linux and provides (in addition to the
-** -vfstrace option) support for FTS3 and FTS4, RTREE, and command-line
-** editing using the readline library. The command-line shell does not
-** use threads so we added -DSQLITE_THREADSAFE=0 just to make the code
-** run a little faster. For compiling on a Mac, you'll probably need
-** to omit the -DHAVE_READLINE, the -lreadline, and the -lncurses options.
-** The compilation could be simplified to just this:
-**
-** gcc -DSQLITE_ENABLE_VFSTRACE \
-** shell.c test_vfstrace.c sqlite3.c -ldl -lpthread
-**
-** In this second example, all unnecessary options have been removed
-** Note that since the code is now threadsafe, we had to add the -lpthread
-** option to pull in the pthreads library.
-**
-** To cross-compile for windows using MinGW, a command like this might
-** work:
-**
-** /opt/mingw/bin/i386-mingw32msvc-gcc -o sqlite3.exe -Os -I \
-** -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_VFSTRACE \
-** shell.c test_vfstrace.c sqlite3.c
-**
-** Similar compiler commands will work on different systems. The key
-** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
-** the shell.c source file will know to include the -vfstrace command-line
-** option and (2) you must compile and link the three source files
-** shell,c, test_vfstrace.c, and sqlite3.c.
-*/
-#include <stdlib.h>
-#include <string.h>
-#include "sqlite3.h"
-
-/*
-** An instance of this structure is attached to the each trace VFS to
-** provide auxiliary information.
-*/
-typedef struct vfstrace_info vfstrace_info;
-struct vfstrace_info {
- sqlite3_vfs *pRootVfs; /* The underlying real VFS */
- int (*xOut)(const char*, void*); /* Send output here */
- void *pOutArg; /* First argument to xOut */
- const char *zVfsName; /* Name of this trace-VFS */
- sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */
-};
-
-/*
-** The sqlite3_file object for the trace VFS
-*/
-typedef struct vfstrace_file vfstrace_file;
-struct vfstrace_file {
- sqlite3_file base; /* Base class. Must be first */
- vfstrace_info *pInfo; /* The trace-VFS to which this file belongs */
- const char *zFName; /* Base name of the file */
- sqlite3_file *pReal; /* The real underlying file */
-};
-
-/*
-** Method declarations for vfstrace_file.
-*/
-static int vfstraceClose(sqlite3_file*);
-static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int vfstraceWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
-static int vfstraceTruncate(sqlite3_file*, sqlite3_int64 size);
-static int vfstraceSync(sqlite3_file*, int flags);
-static int vfstraceFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int vfstraceLock(sqlite3_file*, int);
-static int vfstraceUnlock(sqlite3_file*, int);
-static int vfstraceCheckReservedLock(sqlite3_file*, int *);
-static int vfstraceFileControl(sqlite3_file*, int op, void *pArg);
-static int vfstraceSectorSize(sqlite3_file*);
-static int vfstraceDeviceCharacteristics(sqlite3_file*);
-static int vfstraceShmLock(sqlite3_file*,int,int,int);
-static int vfstraceShmMap(sqlite3_file*,int,int,int, void volatile **);
-static void vfstraceShmBarrier(sqlite3_file*);
-static int vfstraceShmUnmap(sqlite3_file*,int);
-
-/*
-** Method declarations for vfstrace_vfs.
-*/
-static int vfstraceOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int vfstraceDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int vfstraceAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int vfstraceFullPathname(sqlite3_vfs*, const char *zName, int, char *);
-static void *vfstraceDlOpen(sqlite3_vfs*, const char *zFilename);
-static void vfstraceDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*vfstraceDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
-static void vfstraceDlClose(sqlite3_vfs*, void*);
-static int vfstraceRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int vfstraceSleep(sqlite3_vfs*, int microseconds);
-static int vfstraceCurrentTime(sqlite3_vfs*, double*);
-static int vfstraceGetLastError(sqlite3_vfs*, int, char*);
-static int vfstraceCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-static int vfstraceSetSystemCall(sqlite3_vfs*,const char*, sqlite3_syscall_ptr);
-static sqlite3_syscall_ptr vfstraceGetSystemCall(sqlite3_vfs*, const char *);
-static const char *vfstraceNextSystemCall(sqlite3_vfs*, const char *zName);
-
-/*
-** Return a pointer to the tail of the pathname. Examples:
-**
-** /home/drh/xyzzy.txt -> xyzzy.txt
-** xyzzy.txt -> xyzzy.txt
-*/
-static const char *fileTail(const char *z){
- int i;
- if( z==0 ) return 0;
- i = strlen(z)-1;
- while( i>0 && z[i-1]!='/' ){ i--; }
- return &z[i];
-}
-
-/*
-** Send trace output defined by zFormat and subsequent arguments.
-*/
-static void vfstrace_printf(
- vfstrace_info *pInfo,
- const char *zFormat,
- ...
-){
- va_list ap;
- char *zMsg;
- va_start(ap, zFormat);
- zMsg = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- pInfo->xOut(zMsg, pInfo->pOutArg);
- sqlite3_free(zMsg);
-}
-
-/*
-** Convert value rc into a string and print it using zFormat. zFormat
-** should have exactly one %s
-*/
-static void vfstrace_print_errcode(
- vfstrace_info *pInfo,
- const char *zFormat,
- int rc
-){
- char zBuf[50];
- char *zVal;
- switch( rc ){
- case SQLITE_OK: zVal = "SQLITE_OK"; break;
- case SQLITE_ERROR: zVal = "SQLITE_ERROR"; break;
- case SQLITE_PERM: zVal = "SQLITE_PERM"; break;
- case SQLITE_ABORT: zVal = "SQLITE_ABORT"; break;
- case SQLITE_BUSY: zVal = "SQLITE_BUSY"; break;
- case SQLITE_NOMEM: zVal = "SQLITE_NOMEM"; break;
- case SQLITE_READONLY: zVal = "SQLITE_READONLY"; break;
- case SQLITE_INTERRUPT: zVal = "SQLITE_INTERRUPT"; break;
- case SQLITE_IOERR: zVal = "SQLITE_IOERR"; break;
- case SQLITE_CORRUPT: zVal = "SQLITE_CORRUPT"; break;
- case SQLITE_FULL: zVal = "SQLITE_FULL"; break;
- case SQLITE_CANTOPEN: zVal = "SQLITE_CANTOPEN"; break;
- case SQLITE_PROTOCOL: zVal = "SQLITE_PROTOCOL"; break;
- case SQLITE_EMPTY: zVal = "SQLITE_EMPTY"; break;
- case SQLITE_SCHEMA: zVal = "SQLITE_SCHEMA"; break;
- case SQLITE_CONSTRAINT: zVal = "SQLITE_CONSTRAINT"; break;
- case SQLITE_MISMATCH: zVal = "SQLITE_MISMATCH"; break;
- case SQLITE_MISUSE: zVal = "SQLITE_MISUSE"; break;
- case SQLITE_NOLFS: zVal = "SQLITE_NOLFS"; break;
- case SQLITE_IOERR_READ: zVal = "SQLITE_IOERR_READ"; break;
- case SQLITE_IOERR_SHORT_READ: zVal = "SQLITE_IOERR_SHORT_READ"; break;
- case SQLITE_IOERR_WRITE: zVal = "SQLITE_IOERR_WRITE"; break;
- case SQLITE_IOERR_FSYNC: zVal = "SQLITE_IOERR_FSYNC"; break;
- case SQLITE_IOERR_DIR_FSYNC: zVal = "SQLITE_IOERR_DIR_FSYNC"; break;
- case SQLITE_IOERR_TRUNCATE: zVal = "SQLITE_IOERR_TRUNCATE"; break;
- case SQLITE_IOERR_FSTAT: zVal = "SQLITE_IOERR_FSTAT"; break;
- case SQLITE_IOERR_UNLOCK: zVal = "SQLITE_IOERR_UNLOCK"; break;
- case SQLITE_IOERR_RDLOCK: zVal = "SQLITE_IOERR_RDLOCK"; break;
- case SQLITE_IOERR_DELETE: zVal = "SQLITE_IOERR_DELETE"; break;
- case SQLITE_IOERR_BLOCKED: zVal = "SQLITE_IOERR_BLOCKED"; break;
- case SQLITE_IOERR_NOMEM: zVal = "SQLITE_IOERR_NOMEM"; break;
- case SQLITE_IOERR_ACCESS: zVal = "SQLITE_IOERR_ACCESS"; break;
- case SQLITE_IOERR_CHECKRESERVEDLOCK:
- zVal = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
- case SQLITE_IOERR_LOCK: zVal = "SQLITE_IOERR_LOCK"; break;
- case SQLITE_IOERR_CLOSE: zVal = "SQLITE_IOERR_CLOSE"; break;
- case SQLITE_IOERR_DIR_CLOSE: zVal = "SQLITE_IOERR_DIR_CLOSE"; break;
- case SQLITE_IOERR_SHMOPEN: zVal = "SQLITE_IOERR_SHMOPEN"; break;
- case SQLITE_IOERR_SHMSIZE: zVal = "SQLITE_IOERR_SHMSIZE"; break;
- case SQLITE_IOERR_SHMLOCK: zVal = "SQLITE_IOERR_SHMLOCK"; break;
- case SQLITE_IOERR_SHMMAP: zVal = "SQLITE_IOERR_SHMMAP"; break;
- case SQLITE_IOERR_SEEK: zVal = "SQLITE_IOERR_SEEK"; break;
- case SQLITE_IOERR_GETTEMPPATH: zVal = "SQLITE_IOERR_GETTEMPPATH"; break;
- case SQLITE_IOERR_CONVPATH: zVal = "SQLITE_IOERR_CONVPATH"; break;
- case SQLITE_READONLY_DBMOVED: zVal = "SQLITE_READONLY_DBMOVED"; break;
- case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break;
- case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break;
- case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break;
- default: {
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
- zVal = zBuf;
- break;
- }
- }
- vfstrace_printf(pInfo, zFormat, zVal);
-}
-
-/*
-** Append to a buffer.
-*/
-static void strappend(char *z, int *pI, const char *zAppend){
- int i = *pI;
- while( zAppend[0] ){ z[i++] = *(zAppend++); }
- z[i] = 0;
- *pI = i;
-}
-
-/*
-** Close an vfstrace-file.
-*/
-static int vfstraceClose(sqlite3_file *pFile){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
- rc = p->pReal->pMethods->xClose(p->pReal);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- if( rc==SQLITE_OK ){
- sqlite3_free((void*)p->base.pMethods);
- p->base.pMethods = 0;
- }
- return rc;
-}
-
-/*
-** Read data from an vfstrace-file.
-*/
-static int vfstraceRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
- pInfo->zVfsName, p->zFName, iAmt, iOfst);
- rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- return rc;
-}
-
-/*
-** Write data to an vfstrace-file.
-*/
-static int vfstraceWrite(
- sqlite3_file *pFile,
- const void *zBuf,
- int iAmt,
- sqlite_int64 iOfst
-){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
- pInfo->zVfsName, p->zFName, iAmt, iOfst);
- rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- return rc;
-}
-
-/*
-** Truncate an vfstrace-file.
-*/
-static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
- size);
- rc = p->pReal->pMethods->xTruncate(p->pReal, size);
- vfstrace_printf(pInfo, " -> %d\n", rc);
- return rc;
-}
-
-/*
-** Sync an vfstrace-file.
-*/
-static int vfstraceSync(sqlite3_file *pFile, int flags){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- int i;
- char zBuf[100];
- memcpy(zBuf, "|0", 3);
- i = 0;
- if( flags & SQLITE_SYNC_FULL ) strappend(zBuf, &i, "|FULL");
- else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL");
- if( flags & SQLITE_SYNC_DATAONLY ) strappend(zBuf, &i, "|DATAONLY");
- if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
- sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
- }
- vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
- &zBuf[1]);
- rc = p->pReal->pMethods->xSync(p->pReal, flags);
- vfstrace_printf(pInfo, " -> %d\n", rc);
- return rc;
-}
-
-/*
-** Return the current file-size of an vfstrace-file.
-*/
-static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
- rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
- vfstrace_print_errcode(pInfo, " -> %s,", rc);
- vfstrace_printf(pInfo, " size=%lld\n", *pSize);
- return rc;
-}
-
-/*
-** Return the name of a lock.
-*/
-static const char *lockName(int eLock){
- const char *azLockNames[] = {
- "NONE", "SHARED", "RESERVED", "PENDING", "EXCLUSIVE"
- };
- if( eLock<0 || eLock>=sizeof(azLockNames)/sizeof(azLockNames[0]) ){
- return "???";
- }else{
- return azLockNames[eLock];
- }
-}
-
-/*
-** Lock an vfstrace-file.
-*/
-static int vfstraceLock(sqlite3_file *pFile, int eLock){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
- lockName(eLock));
- rc = p->pReal->pMethods->xLock(p->pReal, eLock);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- return rc;
-}
-
-/*
-** Unlock an vfstrace-file.
-*/
-static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
- lockName(eLock));
- rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- return rc;
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an vfstrace-file.
-*/
-static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)",
- pInfo->zVfsName, p->zFName);
- rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
- vfstrace_print_errcode(pInfo, " -> %s", rc);
- vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
- return rc;
-}
-
-/*
-** File control method. For custom operations on an vfstrace-file.
-*/
-static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- char zBuf[100];
- char *zOp;
- switch( op ){
- case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
- case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
- case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break;
- case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break;
- case SQLITE_FCNTL_SIZE_HINT: {
- sqlite3_snprintf(sizeof(zBuf), zBuf, "SIZE_HINT,%lld",
- *(sqlite3_int64*)pArg);
- zOp = zBuf;
- break;
- }
- case SQLITE_FCNTL_CHUNK_SIZE: {
- sqlite3_snprintf(sizeof(zBuf), zBuf, "CHUNK_SIZE,%d", *(int*)pArg);
- zOp = zBuf;
- break;
- }
- case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break;
- case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED"; break;
- case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break;
- case SQLITE_FCNTL_PERSIST_WAL: zOp = "PERSIST_WAL"; break;
- case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break;
- case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break;
- case SQLITE_FCNTL_TEMPFILENAME: zOp = "TEMPFILENAME"; break;
- case 0xca093fa0: zOp = "DB_UNCHANGED"; break;
- case SQLITE_FCNTL_PRAGMA: {
- const char *const* a = (const char*const*)pArg;
- sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
- zOp = zBuf;
- break;
- }
- default: {
- sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
- zOp = zBuf;
- break;
- }
- }
- vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)",
- pInfo->zVfsName, p->zFName, zOp);
- rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
- *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
- pInfo->zVfsName, *(char**)pArg);
- }
- if( (op==SQLITE_FCNTL_PRAGMA || op==SQLITE_FCNTL_TEMPFILENAME)
- && rc==SQLITE_OK && *(char**)pArg ){
- vfstrace_printf(pInfo, "%s.xFileControl(%s,%s) returns %s",
- pInfo->zVfsName, p->zFName, zOp, *(char**)pArg);
- }
- return rc;
-}
-
-/*
-** Return the sector-size in bytes for an vfstrace-file.
-*/
-static int vfstraceSectorSize(sqlite3_file *pFile){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
- rc = p->pReal->pMethods->xSectorSize(p->pReal);
- vfstrace_printf(pInfo, " -> %d\n", rc);
- return rc;
-}
-
-/*
-** Return the device characteristic flags supported by an vfstrace-file.
-*/
-static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
- pInfo->zVfsName, p->zFName);
- rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
- vfstrace_printf(pInfo, " -> 0x%08x\n", rc);
- return rc;
-}
-
-/*
-** Shared-memory operations.
-*/
-static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- char zLck[100];
- int i = 0;
- memcpy(zLck, "|0", 3);
- if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK");
- if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK");
- if( flags & SQLITE_SHM_SHARED ) strappend(zLck, &i, "|SHARED");
- if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE");
- if( flags & ~(0xf) ){
- sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
- }
- vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)",
- pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]);
- rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- return rc;
-}
-static int vfstraceShmMap(
- sqlite3_file *pFile,
- int iRegion,
- int szRegion,
- int isWrite,
- void volatile **pp
-){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
- pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
- rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- return rc;
-}
-static void vfstraceShmBarrier(sqlite3_file *pFile){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
- p->pReal->pMethods->xShmBarrier(p->pReal);
-}
-static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = p->pInfo;
- int rc;
- vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
- pInfo->zVfsName, p->zFName, delFlag);
- rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- return rc;
-}
-
-
-
-/*
-** Open an vfstrace file handle.
-*/
-static int vfstraceOpen(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
-){
- int rc;
- vfstrace_file *p = (vfstrace_file *)pFile;
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- p->pInfo = pInfo;
- p->zFName = zName ? fileTail(zName) : "<temp>";
- p->pReal = (sqlite3_file *)&p[1];
- rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
- vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
- pInfo->zVfsName, p->zFName, flags);
- if( p->pReal->pMethods ){
- sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) );
- const sqlite3_io_methods *pSub = p->pReal->pMethods;
- memset(pNew, 0, sizeof(*pNew));
- pNew->iVersion = pSub->iVersion;
- pNew->xClose = vfstraceClose;
- pNew->xRead = vfstraceRead;
- pNew->xWrite = vfstraceWrite;
- pNew->xTruncate = vfstraceTruncate;
- pNew->xSync = vfstraceSync;
- pNew->xFileSize = vfstraceFileSize;
- pNew->xLock = vfstraceLock;
- pNew->xUnlock = vfstraceUnlock;
- pNew->xCheckReservedLock = vfstraceCheckReservedLock;
- pNew->xFileControl = vfstraceFileControl;
- pNew->xSectorSize = vfstraceSectorSize;
- pNew->xDeviceCharacteristics = vfstraceDeviceCharacteristics;
- if( pNew->iVersion>=2 ){
- pNew->xShmMap = pSub->xShmMap ? vfstraceShmMap : 0;
- pNew->xShmLock = pSub->xShmLock ? vfstraceShmLock : 0;
- pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0;
- pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0;
- }
- pFile->pMethods = pNew;
- }
- vfstrace_print_errcode(pInfo, " -> %s", rc);
- if( pOutFlags ){
- vfstrace_printf(pInfo, ", outFlags=0x%x\n", *pOutFlags);
- }else{
- vfstrace_printf(pInfo, "\n");
- }
- return rc;
-}
-
-/*
-** Delete the file located at zPath. If the dirSync argument is true,
-** ensure the file-system modifications are synced to disk before
-** returning.
-*/
-static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- int rc;
- vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
- pInfo->zVfsName, zPath, dirSync);
- rc = pRoot->xDelete(pRoot, zPath, dirSync);
- vfstrace_print_errcode(pInfo, " -> %s\n", rc);
- return rc;
-}
-
-/*
-** Test for access permissions. Return true if the requested permission
-** is available, or false otherwise.
-*/
-static int vfstraceAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
- int *pResOut
-){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- int rc;
- vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
- pInfo->zVfsName, zPath, flags);
- rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
- vfstrace_print_errcode(pInfo, " -> %s", rc);
- vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
- return rc;
-}
-
-/*
-** Populate buffer zOut with the full canonical pathname corresponding
-** to the pathname in zPath. zOut is guaranteed to point to a buffer
-** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
-*/
-static int vfstraceFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
- char *zOut
-){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- int rc;
- vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
- pInfo->zVfsName, zPath);
- rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
- vfstrace_print_errcode(pInfo, " -> %s", rc);
- vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut);
- return rc;
-}
-
-/*
-** Open the dynamic library located at zPath and return a handle.
-*/
-static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
- return pRoot->xDlOpen(pRoot, zPath);
-}
-
-/*
-** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
-** with dynamic libraries.
-*/
-static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
- pRoot->xDlError(pRoot, nByte, zErrMsg);
- vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
-}
-
-/*
-** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
-*/
-static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- vfstrace_printf(pInfo, "%s.xDlSym(\"%s\")\n", pInfo->zVfsName, zSym);
- return pRoot->xDlSym(pRoot, p, zSym);
-}
-
-/*
-** Close the dynamic library handle pHandle.
-*/
-static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
- pRoot->xDlClose(pRoot, pHandle);
-}
-
-/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
-** random data.
-*/
-static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
- return pRoot->xRandomness(pRoot, nByte, zBufOut);
-}
-
-/*
-** Sleep for nMicro microseconds. Return the number of microseconds
-** actually slept.
-*/
-static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- return pRoot->xSleep(pRoot, nMicro);
-}
-
-/*
-** Return the current time as a Julian Day number in *pTimeOut.
-*/
-static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- return pRoot->xCurrentTime(pRoot, pTimeOut);
-}
-static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
-}
-
-/*
-** Return th3 emost recent error code and message
-*/
-static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- return pRoot->xGetLastError(pRoot, iErr, zErr);
-}
-
-/*
-** Override system calls.
-*/
-static int vfstraceSetSystemCall(
- sqlite3_vfs *pVfs,
- const char *zName,
- sqlite3_syscall_ptr pFunc
-){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- return pRoot->xSetSystemCall(pRoot, zName, pFunc);
-}
-static sqlite3_syscall_ptr vfstraceGetSystemCall(
- sqlite3_vfs *pVfs,
- const char *zName
-){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- return pRoot->xGetSystemCall(pRoot, zName);
-}
-static const char *vfstraceNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
- vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
- sqlite3_vfs *pRoot = pInfo->pRootVfs;
- return pRoot->xNextSystemCall(pRoot, zName);
-}
-
-
-/*
-** Clients invoke this routine to construct a new trace-vfs shim.
-**
-** Return SQLITE_OK on success.
-**
-** SQLITE_NOMEM is returned in the case of a memory allocation error.
-** SQLITE_NOTFOUND is returned if zOldVfsName does not exist.
-*/
-int vfstrace_register(
- const char *zTraceName, /* Name of the newly constructed VFS */
- const char *zOldVfsName, /* Name of the underlying VFS */
- int (*xOut)(const char*,void*), /* Output routine. ex: fputs */
- void *pOutArg, /* 2nd argument to xOut. ex: stderr */
- int makeDefault /* True to make the new VFS the default */
-){
- sqlite3_vfs *pNew;
- sqlite3_vfs *pRoot;
- vfstrace_info *pInfo;
- int nName;
- int nByte;
-
- pRoot = sqlite3_vfs_find(zOldVfsName);
- if( pRoot==0 ) return SQLITE_NOTFOUND;
- nName = strlen(zTraceName);
- nByte = sizeof(*pNew) + sizeof(*pInfo) + nName + 1;
- pNew = sqlite3_malloc( nByte );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, nByte);
- pInfo = (vfstrace_info*)&pNew[1];
- pNew->iVersion = pRoot->iVersion;
- pNew->szOsFile = pRoot->szOsFile + sizeof(vfstrace_file);
- pNew->mxPathname = pRoot->mxPathname;
- pNew->zName = (char*)&pInfo[1];
- memcpy((char*)&pInfo[1], zTraceName, nName+1);
- pNew->pAppData = pInfo;
- pNew->xOpen = vfstraceOpen;
- pNew->xDelete = vfstraceDelete;
- pNew->xAccess = vfstraceAccess;
- pNew->xFullPathname = vfstraceFullPathname;
- pNew->xDlOpen = pRoot->xDlOpen==0 ? 0 : vfstraceDlOpen;
- pNew->xDlError = pRoot->xDlError==0 ? 0 : vfstraceDlError;
- pNew->xDlSym = pRoot->xDlSym==0 ? 0 : vfstraceDlSym;
- pNew->xDlClose = pRoot->xDlClose==0 ? 0 : vfstraceDlClose;
- pNew->xRandomness = vfstraceRandomness;
- pNew->xSleep = vfstraceSleep;
- pNew->xCurrentTime = vfstraceCurrentTime;
- pNew->xGetLastError = pRoot->xGetLastError==0 ? 0 : vfstraceGetLastError;
- if( pNew->iVersion>=2 ){
- pNew->xCurrentTimeInt64 = pRoot->xCurrentTimeInt64==0 ? 0 :
- vfstraceCurrentTimeInt64;
- if( pNew->iVersion>=3 ){
- pNew->xSetSystemCall = pRoot->xSetSystemCall==0 ? 0 :
- vfstraceSetSystemCall;
- pNew->xGetSystemCall = pRoot->xGetSystemCall==0 ? 0 :
- vfstraceGetSystemCall;
- pNew->xNextSystemCall = pRoot->xNextSystemCall==0 ? 0 :
- vfstraceNextSystemCall;
- }
- }
- pInfo->pRootVfs = pRoot;
- pInfo->xOut = xOut;
- pInfo->pOutArg = pOutArg;
- pInfo->zVfsName = pNew->zName;
- pInfo->pTraceVfs = pNew;
- vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
- pInfo->zVfsName, pRoot->zName);
- return sqlite3_vfs_register(pNew, makeDefault);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_windirent.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_windirent.c
deleted file mode 100644
index 62165c4bea5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_windirent.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
-** 2015 November 30
-**
-** 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 contains code to implement most of the opendir() family of
-** POSIX functions on Win32 using the MSVCRT.
-*/
-
-#if defined(_WIN32) && defined(_MSC_VER)
-#include "test_windirent.h"
-
-/*
-** Implementation of the POSIX getenv() function using the Win32 API.
-** This function is not thread-safe.
-*/
-const char *windirent_getenv(
- const char *name
-){
- static char value[32768]; /* Maximum length, per MSDN */
- DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
- DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
-
- memset(value, 0, sizeof(value));
- dwRet = GetEnvironmentVariableA(name, value, dwSize);
- if( dwRet==0 || dwRet>dwSize ){
- /*
- ** The function call to GetEnvironmentVariableA() failed -OR-
- ** the buffer is not large enough. Either way, return NULL.
- */
- return 0;
- }else{
- /*
- ** The function call to GetEnvironmentVariableA() succeeded
- ** -AND- the buffer contains the entire value.
- */
- return value;
- }
-}
-
-/*
-** Implementation of the POSIX opendir() function using the MSVCRT.
-*/
-LPDIR opendir(
- const char *dirname
-){
- struct _finddata_t data;
- LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
- SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
-
- if( dirp==NULL ) return NULL;
- memset(dirp, 0, sizeof(DIR));
-
- /* TODO: Remove this if Unix-style root paths are not used. */
- if( sqlite3_stricmp(dirname, "/")==0 ){
- dirname = windirent_getenv("SystemDrive");
- }
-
- memset(&data, 0, sizeof(struct _finddata_t));
- _snprintf(data.name, namesize, "%s\\*", dirname);
- dirp->d_handle = _findfirst(data.name, &data);
-
- if( dirp->d_handle==BAD_INTPTR_T ){
- closedir(dirp);
- return NULL;
- }
-
- /* TODO: Remove this block to allow hidden and/or system files. */
- if( is_filtered(data) ){
-next:
-
- memset(&data, 0, sizeof(struct _finddata_t));
- if( _findnext(dirp->d_handle, &data)==-1 ){
- closedir(dirp);
- return NULL;
- }
-
- /* TODO: Remove this block to allow hidden and/or system files. */
- if( is_filtered(data) ) goto next;
- }
-
- dirp->d_first.d_attributes = data.attrib;
- strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
- dirp->d_first.d_name[NAME_MAX] = '\0';
-
- return dirp;
-}
-
-/*
-** Implementation of the POSIX readdir() function using the MSVCRT.
-*/
-LPDIRENT readdir(
- LPDIR dirp
-){
- struct _finddata_t data;
-
- if( dirp==NULL ) return NULL;
-
- if( dirp->d_first.d_ino==0 ){
- dirp->d_first.d_ino++;
- dirp->d_next.d_ino++;
-
- return &dirp->d_first;
- }
-
-next:
-
- memset(&data, 0, sizeof(struct _finddata_t));
- if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
-
- /* TODO: Remove this block to allow hidden and/or system files. */
- if( is_filtered(data) ) goto next;
-
- dirp->d_next.d_ino++;
- dirp->d_next.d_attributes = data.attrib;
- strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
- dirp->d_next.d_name[NAME_MAX] = '\0';
-
- return &dirp->d_next;
-}
-
-/*
-** Implementation of the POSIX readdir_r() function using the MSVCRT.
-*/
-INT readdir_r(
- LPDIR dirp,
- LPDIRENT entry,
- LPDIRENT *result
-){
- struct _finddata_t data;
-
- if( dirp==NULL ) return EBADF;
-
- if( dirp->d_first.d_ino==0 ){
- dirp->d_first.d_ino++;
- dirp->d_next.d_ino++;
-
- entry->d_ino = dirp->d_first.d_ino;
- entry->d_attributes = dirp->d_first.d_attributes;
- strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
- entry->d_name[NAME_MAX] = '\0';
-
- *result = entry;
- return 0;
- }
-
-next:
-
- memset(&data, 0, sizeof(struct _finddata_t));
- if( _findnext(dirp->d_handle, &data)==-1 ){
- *result = NULL;
- return ENOENT;
- }
-
- /* TODO: Remove this block to allow hidden and/or system files. */
- if( is_filtered(data) ) goto next;
-
- entry->d_ino = (ino_t)-1; /* not available */
- entry->d_attributes = data.attrib;
- strncpy(entry->d_name, data.name, NAME_MAX);
- entry->d_name[NAME_MAX] = '\0';
-
- *result = entry;
- return 0;
-}
-
-/*
-** Implementation of the POSIX closedir() function using the MSVCRT.
-*/
-INT closedir(
- LPDIR dirp
-){
- INT result = 0;
-
- if( dirp==NULL ) return EINVAL;
-
- if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
- result = _findclose(dirp->d_handle);
- }
-
- sqlite3_free(dirp);
- return result;
-}
-
-#endif /* defined(WIN32) && defined(_MSC_VER) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_windirent.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_windirent.h
deleted file mode 100644
index ada53225309..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_windirent.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-** 2015 November 30
-**
-** 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 contains declarations for most of the opendir() family of
-** POSIX functions on Win32 using the MSVCRT.
-*/
-
-#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
-#define SQLITE_WINDIRENT_H
-
-/*
-** We need several data types from the Windows SDK header.
-*/
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#include "windows.h"
-
-/*
-** We need several support functions from the SQLite core.
-*/
-
-#include "sqlite3.h"
-
-/*
-** We need several things from the ANSI and MSVCRT headers.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <io.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-/*
-** We may need several defines that should have been in "sys/stat.h".
-*/
-
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
-
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
-#endif
-
-#ifndef S_ISLNK
-#define S_ISLNK(mode) (0)
-#endif
-
-/*
-** We may need to provide the "mode_t" type.
-*/
-
-#ifndef MODE_T_DEFINED
- #define MODE_T_DEFINED
- typedef unsigned short mode_t;
-#endif
-
-/*
-** We may need to provide the "ino_t" type.
-*/
-
-#ifndef INO_T_DEFINED
- #define INO_T_DEFINED
- typedef unsigned short ino_t;
-#endif
-
-/*
-** We need to define "NAME_MAX" if it was not present in "limits.h".
-*/
-
-#ifndef NAME_MAX
-# ifdef FILENAME_MAX
-# define NAME_MAX (FILENAME_MAX)
-# else
-# define NAME_MAX (260)
-# endif
-#endif
-
-/*
-** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
-*/
-
-#ifndef NULL_INTPTR_T
-# define NULL_INTPTR_T ((intptr_t)(0))
-#endif
-
-#ifndef BAD_INTPTR_T
-# define BAD_INTPTR_T ((intptr_t)(-1))
-#endif
-
-/*
-** We need to provide the necessary structures and related types.
-*/
-
-#ifndef DIRENT_DEFINED
-#define DIRENT_DEFINED
-typedef struct DIRENT DIRENT;
-typedef DIRENT *LPDIRENT;
-struct DIRENT {
- ino_t d_ino; /* Sequence number, do not use. */
- unsigned d_attributes; /* Win32 file attributes. */
- char d_name[NAME_MAX + 1]; /* Name within the directory. */
-};
-#endif
-
-#ifndef DIR_DEFINED
-#define DIR_DEFINED
-typedef struct DIR DIR;
-typedef DIR *LPDIR;
-struct DIR {
- intptr_t d_handle; /* Value returned by "_findfirst". */
- DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
- DIRENT d_next; /* DIRENT constructed based on "_findnext". */
-};
-#endif
-
-/*
-** Provide a macro, for use by the implementation, to determine if a
-** particular directory entry should be skipped over when searching for
-** the next directory entry that should be returned by the readdir() or
-** readdir_r() functions.
-*/
-
-#ifndef is_filtered
-# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
-#endif
-
-/*
-** Provide the function prototype for the POSIX compatiable getenv()
-** function. This function is not thread-safe.
-*/
-
-extern const char *windirent_getenv(const char *name);
-
-/*
-** Finally, we can provide the function prototypes for the opendir(),
-** readdir(), readdir_r(), and closedir() POSIX functions.
-*/
-
-extern LPDIR opendir(const char *dirname);
-extern LPDIRENT readdir(LPDIR dirp);
-extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
-extern INT closedir(LPDIR dirp);
-
-#endif /* defined(WIN32) && defined(_MSC_VER) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_wsd.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/test_wsd.c
deleted file mode 100644
index 99e4a056581..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/test_wsd.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-** 2008 September 1
-**
-** 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.
-**
-*************************************************************************
-**
-** The code in this file contains sample implementations of the
-** sqlite3_wsd_init() and sqlite3_wsd_find() functions required if the
-** SQLITE_OMIT_WSD symbol is defined at build time.
-*/
-
-#if defined(SQLITE_OMIT_WSD) && defined(SQLITE_TEST)
-
-#include "sqliteInt.h"
-
-#define PLS_HASHSIZE 43
-
-typedef struct ProcessLocalStorage ProcessLocalStorage;
-typedef struct ProcessLocalVar ProcessLocalVar;
-
-struct ProcessLocalStorage {
- ProcessLocalVar *aData[PLS_HASHSIZE];
- int nFree;
- u8 *pFree;
-};
-
-struct ProcessLocalVar {
- void *pKey;
- ProcessLocalVar *pNext;
-};
-
-static ProcessLocalStorage *pGlobal = 0;
-
-int sqlite3_wsd_init(int N, int J){
- if( !pGlobal ){
- int nMalloc = N + sizeof(ProcessLocalStorage) + J*sizeof(ProcessLocalVar);
- pGlobal = (ProcessLocalStorage *)malloc(nMalloc);
- if( pGlobal ){
- memset(pGlobal, 0, sizeof(ProcessLocalStorage));
- pGlobal->nFree = nMalloc - sizeof(ProcessLocalStorage);
- pGlobal->pFree = (u8 *)&pGlobal[1];
- }
- }
-
- return pGlobal ? SQLITE_OK : SQLITE_NOMEM;
-}
-
-void *sqlite3_wsd_find(void *K, int L){
- int i;
- int iHash = 0;
- ProcessLocalVar *pVar;
-
- /* Calculate a hash of K */
- for(i=0; i<sizeof(void*); i++){
- iHash = (iHash<<3) + ((unsigned char *)&K)[i];
- }
- iHash = iHash%PLS_HASHSIZE;
-
- /* Search the hash table for K. */
- for(pVar=pGlobal->aData[iHash]; pVar && pVar->pKey!=K; pVar=pVar->pNext);
-
- /* If no entry for K was found, create and populate a new one. */
- if( !pVar ){
- int nByte = ROUND8(sizeof(ProcessLocalVar) + L);
- assert( pGlobal->nFree>=nByte );
- pVar = (ProcessLocalVar *)pGlobal->pFree;
- pVar->pKey = K;
- pVar->pNext = pGlobal->aData[iHash];
- pGlobal->aData[iHash] = pVar;
- pGlobal->nFree -= nByte;
- pGlobal->pFree += nByte;
- memcpy(&pVar[1], K, L);
- }
-
- return (void *)&pVar[1];
-}
-
-#endif
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/threads.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/threads.c
deleted file mode 100644
index f128d69fc23..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/threads.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
-** 2012 July 21
-**
-** 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 presents a simple cross-platform threading interface for
-** use internally by SQLite.
-**
-** A "thread" can be created using sqlite3ThreadCreate(). This thread
-** runs independently of its creator until it is joined using
-** sqlite3ThreadJoin(), at which point it terminates.
-**
-** Threads do not have to be real. It could be that the work of the
-** "thread" is done by the main thread at either the sqlite3ThreadCreate()
-** or sqlite3ThreadJoin() call. This is, in fact, what happens in
-** single threaded systems. Nothing in SQLite requires multiple threads.
-** This interface exists so that applications that want to take advantage
-** of multiple cores can do so, while also allowing applications to stay
-** single-threaded if desired.
-*/
-#include "sqliteInt.h"
-#if SQLITE_OS_WIN
-# include "os_win.h"
-#endif
-
-#if SQLITE_MAX_WORKER_THREADS>0
-
-/********************************* Unix Pthreads ****************************/
-#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0
-
-#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
-#include <pthread.h>
-
-/* A running thread */
-struct SQLiteThread {
- pthread_t tid; /* Thread ID */
- int done; /* Set to true when thread finishes */
- void *pOut; /* Result returned by the thread */
- void *(*xTask)(void*); /* The thread routine */
- void *pIn; /* Argument to the thread */
-};
-
-/* Create a new thread */
-int sqlite3ThreadCreate(
- SQLiteThread **ppThread, /* OUT: Write the thread object here */
- void *(*xTask)(void*), /* Routine to run in a separate thread */
- void *pIn /* Argument passed into xTask() */
-){
- SQLiteThread *p;
- int rc;
-
- assert( ppThread!=0 );
- assert( xTask!=0 );
- /* This routine is never used in single-threaded mode */
- assert( sqlite3GlobalConfig.bCoreMutex!=0 );
-
- *ppThread = 0;
- p = sqlite3Malloc(sizeof(*p));
- if( p==0 ) return SQLITE_NOMEM_BKPT;
- memset(p, 0, sizeof(*p));
- p->xTask = xTask;
- p->pIn = pIn;
- /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
- ** function that returns SQLITE_ERROR when passed the argument 200, that
- ** forces worker threads to run sequentially and deterministically
- ** for testing purposes. */
- if( sqlite3FaultSim(200) ){
- rc = 1;
- }else{
- rc = pthread_create(&p->tid, 0, xTask, pIn);
- }
- if( rc ){
- p->done = 1;
- p->pOut = xTask(pIn);
- }
- *ppThread = p;
- return SQLITE_OK;
-}
-
-/* Get the results of the thread */
-int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
- int rc;
-
- assert( ppOut!=0 );
- if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
- if( p->done ){
- *ppOut = p->pOut;
- rc = SQLITE_OK;
- }else{
- rc = pthread_join(p->tid, ppOut) ? SQLITE_ERROR : SQLITE_OK;
- }
- sqlite3_free(p);
- return rc;
-}
-
-#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
-/******************************** End Unix Pthreads *************************/
-
-
-/********************************* Win32 Threads ****************************/
-#if SQLITE_OS_WIN_THREADS
-
-#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
-#include <process.h>
-
-/* A running thread */
-struct SQLiteThread {
- void *tid; /* The thread handle */
- unsigned id; /* The thread identifier */
- void *(*xTask)(void*); /* The routine to run as a thread */
- void *pIn; /* Argument to xTask */
- void *pResult; /* Result of xTask */
-};
-
-/* Thread procedure Win32 compatibility shim */
-static unsigned __stdcall sqlite3ThreadProc(
- void *pArg /* IN: Pointer to the SQLiteThread structure */
-){
- SQLiteThread *p = (SQLiteThread *)pArg;
-
- assert( p!=0 );
-#if 0
- /*
- ** This assert appears to trigger spuriously on certain
- ** versions of Windows, possibly due to _beginthreadex()
- ** and/or CreateThread() not fully setting their thread
- ** ID parameter before starting the thread.
- */
- assert( p->id==GetCurrentThreadId() );
-#endif
- assert( p->xTask!=0 );
- p->pResult = p->xTask(p->pIn);
-
- _endthreadex(0);
- return 0; /* NOT REACHED */
-}
-
-/* Create a new thread */
-int sqlite3ThreadCreate(
- SQLiteThread **ppThread, /* OUT: Write the thread object here */
- void *(*xTask)(void*), /* Routine to run in a separate thread */
- void *pIn /* Argument passed into xTask() */
-){
- SQLiteThread *p;
-
- assert( ppThread!=0 );
- assert( xTask!=0 );
- *ppThread = 0;
- p = sqlite3Malloc(sizeof(*p));
- if( p==0 ) return SQLITE_NOMEM_BKPT;
- /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
- ** function that returns SQLITE_ERROR when passed the argument 200, that
- ** forces worker threads to run sequentially and deterministically
- ** (via the sqlite3FaultSim() term of the conditional) for testing
- ** purposes. */
- if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){
- memset(p, 0, sizeof(*p));
- }else{
- p->xTask = xTask;
- p->pIn = pIn;
- p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id);
- if( p->tid==0 ){
- memset(p, 0, sizeof(*p));
- }
- }
- if( p->xTask==0 ){
- p->id = GetCurrentThreadId();
- p->pResult = xTask(pIn);
- }
- *ppThread = p;
- return SQLITE_OK;
-}
-
-DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */
-
-/* Get the results of the thread */
-int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
- DWORD rc;
- BOOL bRc;
-
- assert( ppOut!=0 );
- if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
- if( p->xTask==0 ){
- /* assert( p->id==GetCurrentThreadId() ); */
- rc = WAIT_OBJECT_0;
- assert( p->tid==0 );
- }else{
- assert( p->id!=0 && p->id!=GetCurrentThreadId() );
- rc = sqlite3Win32Wait((HANDLE)p->tid);
- assert( rc!=WAIT_IO_COMPLETION );
- bRc = CloseHandle((HANDLE)p->tid);
- assert( bRc );
- }
- if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
- sqlite3_free(p);
- return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
-}
-
-#endif /* SQLITE_OS_WIN_THREADS */
-/******************************** End Win32 Threads *************************/
-
-
-/********************************* Single-Threaded **************************/
-#ifndef SQLITE_THREADS_IMPLEMENTED
-/*
-** This implementation does not actually create a new thread. It does the
-** work of the thread in the main thread, when either the thread is created
-** or when it is joined
-*/
-
-/* A running thread */
-struct SQLiteThread {
- void *(*xTask)(void*); /* The routine to run as a thread */
- void *pIn; /* Argument to xTask */
- void *pResult; /* Result of xTask */
-};
-
-/* Create a new thread */
-int sqlite3ThreadCreate(
- SQLiteThread **ppThread, /* OUT: Write the thread object here */
- void *(*xTask)(void*), /* Routine to run in a separate thread */
- void *pIn /* Argument passed into xTask() */
-){
- SQLiteThread *p;
-
- assert( ppThread!=0 );
- assert( xTask!=0 );
- *ppThread = 0;
- p = sqlite3Malloc(sizeof(*p));
- if( p==0 ) return SQLITE_NOMEM_BKPT;
- if( (SQLITE_PTR_TO_INT(p)/17)&1 ){
- p->xTask = xTask;
- p->pIn = pIn;
- }else{
- p->xTask = 0;
- p->pResult = xTask(pIn);
- }
- *ppThread = p;
- return SQLITE_OK;
-}
-
-/* Get the results of the thread */
-int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
-
- assert( ppOut!=0 );
- if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
- if( p->xTask ){
- *ppOut = p->xTask(p->pIn);
- }else{
- *ppOut = p->pResult;
- }
- sqlite3_free(p);
-
-#if defined(SQLITE_TEST)
- {
- void *pTstAlloc = sqlite3Malloc(10);
- if (!pTstAlloc) return SQLITE_NOMEM_BKPT;
- sqlite3_free(pTstAlloc);
- }
-#endif
-
- return SQLITE_OK;
-}
-
-#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */
-/****************************** End Single-Threaded *************************/
-#endif /* SQLITE_MAX_WORKER_THREADS>0 */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/tokenize.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/tokenize.c
deleted file mode 100644
index b591d222388..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/tokenize.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** An tokenizer for SQL
-**
-** This file contains C code that splits an SQL input string up into
-** individual tokens and sends those tokens one-by-one over to the
-** parser for analysis.
-*/
-#include "sqliteInt.h"
-#include <stdlib.h>
-
-/* Character classes for tokenizing
-**
-** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented
-** using a lookup table, whereas a switch() directly on c uses a binary search.
-** The lookup table is much faster. To maximize speed, and to ensure that
-** a lookup table is used, all of the classes need to be small integers and
-** all of them need to be used within the switch.
-*/
-#define CC_X 0 /* The letter 'x', or start of BLOB literal */
-#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */
-#define CC_ID 2 /* unicode characters usable in IDs */
-#define CC_DIGIT 3 /* Digits */
-#define CC_DOLLAR 4 /* '$' */
-#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */
-#define CC_VARNUM 6 /* '?'. Numeric SQL variables */
-#define CC_SPACE 7 /* Space characters */
-#define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */
-#define CC_QUOTE2 9 /* '['. [...] style quoted ids */
-#define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */
-#define CC_MINUS 11 /* '-'. Minus or SQL-style comment */
-#define CC_LT 12 /* '<'. Part of < or <= or <> */
-#define CC_GT 13 /* '>'. Part of > or >= */
-#define CC_EQ 14 /* '='. Part of = or == */
-#define CC_BANG 15 /* '!'. Part of != */
-#define CC_SLASH 16 /* '/'. / or c-style comment */
-#define CC_LP 17 /* '(' */
-#define CC_RP 18 /* ')' */
-#define CC_SEMI 19 /* ';' */
-#define CC_PLUS 20 /* '+' */
-#define CC_STAR 21 /* '*' */
-#define CC_PERCENT 22 /* '%' */
-#define CC_COMMA 23 /* ',' */
-#define CC_AND 24 /* '&' */
-#define CC_TILDA 25 /* '~' */
-#define CC_DOT 26 /* '.' */
-#define CC_ILLEGAL 27 /* Illegal character */
-
-static const unsigned char aiClass[] = {
-#ifdef SQLITE_ASCII
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
-/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
-/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1,
-/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27,
-/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
-#endif
-#ifdef SQLITE_EBCDIC
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10,
-/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27,
-/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6,
-/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8,
-/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27,
-/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27,
-#endif
-};
-
-/*
-** The charMap() macro maps alphabetic characters (only) into their
-** lower-case ASCII equivalent. On ASCII machines, this is just
-** an upper-to-lower case map. On EBCDIC machines we also need
-** to adjust the encoding. The mapping is only valid for alphabetics
-** which are the only characters for which this feature is used.
-**
-** Used by keywordhash.h
-*/
-#ifdef SQLITE_ASCII
-# define charMap(X) sqlite3UpperToLower[(unsigned char)X]
-#endif
-#ifdef SQLITE_EBCDIC
-# define charMap(X) ebcdicToAscii[(unsigned char)X]
-const unsigned char ebcdicToAscii[] = {
-/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
- 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */
- 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */
- 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
- 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */
- 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */
- 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */
-};
-#endif
-
-/*
-** The sqlite3KeywordCode function looks up an identifier to determine if
-** it is a keyword. If it is a keyword, the token code of that keyword is
-** returned. If the input is not a keyword, TK_ID is returned.
-**
-** The implementation of this routine was generated by a program,
-** mkkeywordhash.c, located in the tool subdirectory of the distribution.
-** The output of the mkkeywordhash.c program is written into a file
-** named keywordhash.h and then included into this source file by
-** the #include below.
-*/
-#include "keywordhash.h"
-
-
-/*
-** If X is a character that can be used in an identifier then
-** IdChar(X) will be true. Otherwise it is false.
-**
-** For ASCII, any character with the high-order bit set is
-** allowed in an identifier. For 7-bit characters,
-** sqlite3IsIdChar[X] must be 1.
-**
-** For EBCDIC, the rules are more complex but have the same
-** end result.
-**
-** Ticket #1066. the SQL standard does not allow '$' in the
-** middle of identifiers. But many SQL implementations do.
-** SQLite will allow '$' in identifiers for compatibility.
-** But the feature is undocumented.
-*/
-#ifdef SQLITE_ASCII
-#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
-#endif
-#ifdef SQLITE_EBCDIC
-const char sqlite3IsEbcdicIdChar[] = {
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */
- 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */
-};
-#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
-#endif
-
-/* Make the IdChar function accessible from ctime.c */
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-int sqlite3IsIdChar(u8 c){ return IdChar(c); }
-#endif
-
-
-/*
-** Return the length (in bytes) of the token that begins at z[0].
-** Store the token type in *tokenType before returning.
-*/
-int sqlite3GetToken(const unsigned char *z, int *tokenType){
- int i, c;
- switch( aiClass[*z] ){ /* Switch on the character-class of the first byte
- ** of the token. See the comment on the CC_ defines
- ** above. */
- case CC_SPACE: {
- testcase( z[0]==' ' );
- testcase( z[0]=='\t' );
- testcase( z[0]=='\n' );
- testcase( z[0]=='\f' );
- testcase( z[0]=='\r' );
- for(i=1; sqlite3Isspace(z[i]); i++){}
- *tokenType = TK_SPACE;
- return i;
- }
- case CC_MINUS: {
- if( z[1]=='-' ){
- for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
- *tokenType = TK_SPACE; /* IMP: R-22934-25134 */
- return i;
- }
- *tokenType = TK_MINUS;
- return 1;
- }
- case CC_LP: {
- *tokenType = TK_LP;
- return 1;
- }
- case CC_RP: {
- *tokenType = TK_RP;
- return 1;
- }
- case CC_SEMI: {
- *tokenType = TK_SEMI;
- return 1;
- }
- case CC_PLUS: {
- *tokenType = TK_PLUS;
- return 1;
- }
- case CC_STAR: {
- *tokenType = TK_STAR;
- return 1;
- }
- case CC_SLASH: {
- if( z[1]!='*' || z[2]==0 ){
- *tokenType = TK_SLASH;
- return 1;
- }
- for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
- if( c ) i++;
- *tokenType = TK_SPACE; /* IMP: R-22934-25134 */
- return i;
- }
- case CC_PERCENT: {
- *tokenType = TK_REM;
- return 1;
- }
- case CC_EQ: {
- *tokenType = TK_EQ;
- return 1 + (z[1]=='=');
- }
- case CC_LT: {
- if( (c=z[1])=='=' ){
- *tokenType = TK_LE;
- return 2;
- }else if( c=='>' ){
- *tokenType = TK_NE;
- return 2;
- }else if( c=='<' ){
- *tokenType = TK_LSHIFT;
- return 2;
- }else{
- *tokenType = TK_LT;
- return 1;
- }
- }
- case CC_GT: {
- if( (c=z[1])=='=' ){
- *tokenType = TK_GE;
- return 2;
- }else if( c=='>' ){
- *tokenType = TK_RSHIFT;
- return 2;
- }else{
- *tokenType = TK_GT;
- return 1;
- }
- }
- case CC_BANG: {
- if( z[1]!='=' ){
- *tokenType = TK_ILLEGAL;
- return 1;
- }else{
- *tokenType = TK_NE;
- return 2;
- }
- }
- case CC_PIPE: {
- if( z[1]!='|' ){
- *tokenType = TK_BITOR;
- return 1;
- }else{
- *tokenType = TK_CONCAT;
- return 2;
- }
- }
- case CC_COMMA: {
- *tokenType = TK_COMMA;
- return 1;
- }
- case CC_AND: {
- *tokenType = TK_BITAND;
- return 1;
- }
- case CC_TILDA: {
- *tokenType = TK_BITNOT;
- return 1;
- }
- case CC_QUOTE: {
- int delim = z[0];
- testcase( delim=='`' );
- testcase( delim=='\'' );
- testcase( delim=='"' );
- for(i=1; (c=z[i])!=0; i++){
- if( c==delim ){
- if( z[i+1]==delim ){
- i++;
- }else{
- break;
- }
- }
- }
- if( c=='\'' ){
- *tokenType = TK_STRING;
- return i+1;
- }else if( c!=0 ){
- *tokenType = TK_ID;
- return i+1;
- }else{
- *tokenType = TK_ILLEGAL;
- return i;
- }
- }
- case CC_DOT: {
-#ifndef SQLITE_OMIT_FLOATING_POINT
- if( !sqlite3Isdigit(z[1]) )
-#endif
- {
- *tokenType = TK_DOT;
- return 1;
- }
- /* If the next character is a digit, this is a floating point
- ** number that begins with ".". Fall thru into the next case */
- }
- case CC_DIGIT: {
- testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
- testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' );
- testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
- testcase( z[0]=='9' );
- *tokenType = TK_INTEGER;
-#ifndef SQLITE_OMIT_HEX_INTEGER
- if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
- for(i=3; sqlite3Isxdigit(z[i]); i++){}
- return i;
- }
-#endif
- for(i=0; sqlite3Isdigit(z[i]); i++){}
-#ifndef SQLITE_OMIT_FLOATING_POINT
- if( z[i]=='.' ){
- i++;
- while( sqlite3Isdigit(z[i]) ){ i++; }
- *tokenType = TK_FLOAT;
- }
- if( (z[i]=='e' || z[i]=='E') &&
- ( sqlite3Isdigit(z[i+1])
- || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
- )
- ){
- i += 2;
- while( sqlite3Isdigit(z[i]) ){ i++; }
- *tokenType = TK_FLOAT;
- }
-#endif
- while( IdChar(z[i]) ){
- *tokenType = TK_ILLEGAL;
- i++;
- }
- return i;
- }
- case CC_QUOTE2: {
- for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
- *tokenType = c==']' ? TK_ID : TK_ILLEGAL;
- return i;
- }
- case CC_VARNUM: {
- *tokenType = TK_VARIABLE;
- for(i=1; sqlite3Isdigit(z[i]); i++){}
- return i;
- }
- case CC_DOLLAR:
- case CC_VARALPHA: {
- int n = 0;
- testcase( z[0]=='$' ); testcase( z[0]=='@' );
- testcase( z[0]==':' ); testcase( z[0]=='#' );
- *tokenType = TK_VARIABLE;
- for(i=1; (c=z[i])!=0; i++){
- if( IdChar(c) ){
- n++;
-#ifndef SQLITE_OMIT_TCL_VARIABLE
- }else if( c=='(' && n>0 ){
- do{
- i++;
- }while( (c=z[i])!=0 && !sqlite3Isspace(c) && c!=')' );
- if( c==')' ){
- i++;
- }else{
- *tokenType = TK_ILLEGAL;
- }
- break;
- }else if( c==':' && z[i+1]==':' ){
- i++;
-#endif
- }else{
- break;
- }
- }
- if( n==0 ) *tokenType = TK_ILLEGAL;
- return i;
- }
- case CC_KYWD: {
- for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
- if( IdChar(z[i]) ){
- /* This token started out using characters that can appear in keywords,
- ** but z[i] is a character not allowed within keywords, so this must
- ** be an identifier instead */
- i++;
- break;
- }
- *tokenType = TK_ID;
- return keywordCode((char*)z, i, tokenType);
- }
- case CC_X: {
-#ifndef SQLITE_OMIT_BLOB_LITERAL
- testcase( z[0]=='x' ); testcase( z[0]=='X' );
- if( z[1]=='\'' ){
- *tokenType = TK_BLOB;
- for(i=2; sqlite3Isxdigit(z[i]); i++){}
- if( z[i]!='\'' || i%2 ){
- *tokenType = TK_ILLEGAL;
- while( z[i] && z[i]!='\'' ){ i++; }
- }
- if( z[i] ) i++;
- return i;
- }
-#endif
- /* If it is not a BLOB literal, then it must be an ID, since no
- ** SQL keywords start with the letter 'x'. Fall through */
- }
- case CC_ID: {
- i = 1;
- break;
- }
- default: {
- *tokenType = TK_ILLEGAL;
- return 1;
- }
- }
- while( IdChar(z[i]) ){ i++; }
- *tokenType = TK_ID;
- return i;
-}
-
-/*
-** Run the parser on the given SQL string. The parser structure is
-** passed in. An SQLITE_ status code is returned. If an error occurs
-** then an and attempt is made to write an error message into
-** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that
-** error message.
-*/
-int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
- int nErr = 0; /* Number of errors encountered */
- void *pEngine; /* The LEMON-generated LALR(1) parser */
- int n = 0; /* Length of the next token token */
- int tokenType; /* type of the next token */
- int lastTokenParsed = -1; /* type of the previous token */
- sqlite3 *db = pParse->db; /* The database connection */
- int mxSqlLen; /* Max length of an SQL string */
-#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
- yyParser sEngine; /* Space to hold the Lemon-generated Parser object */
-#endif
-
- assert( zSql!=0 );
- mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
- if( db->nVdbeActive==0 ){
- db->u1.isInterrupted = 0;
- }
- pParse->rc = SQLITE_OK;
- pParse->zTail = zSql;
- assert( pzErrMsg!=0 );
- /* sqlite3ParserTrace(stdout, "parser: "); */
-#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
- pEngine = &sEngine;
- sqlite3ParserInit(pEngine, pParse);
-#else
- pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse);
- if( pEngine==0 ){
- sqlite3OomFault(db);
- return SQLITE_NOMEM_BKPT;
- }
-#endif
- assert( pParse->pNewTable==0 );
- assert( pParse->pNewTrigger==0 );
- assert( pParse->nVar==0 );
- assert( pParse->pVList==0 );
- while( 1 ){
- if( zSql[0]!=0 ){
- n = sqlite3GetToken((u8*)zSql, &tokenType);
- mxSqlLen -= n;
- if( mxSqlLen<0 ){
- pParse->rc = SQLITE_TOOBIG;
- break;
- }
- }else{
- /* Upon reaching the end of input, call the parser two more times
- ** with tokens TK_SEMI and 0, in that order. */
- if( lastTokenParsed==TK_SEMI ){
- tokenType = 0;
- }else if( lastTokenParsed==0 ){
- break;
- }else{
- tokenType = TK_SEMI;
- }
- n = 0;
- }
- if( tokenType>=TK_SPACE ){
- assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
- if( db->u1.isInterrupted ){
- pParse->rc = SQLITE_INTERRUPT;
- break;
- }
- if( tokenType==TK_ILLEGAL ){
- sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql);
- break;
- }
- zSql += n;
- }else{
- pParse->sLastToken.z = zSql;
- pParse->sLastToken.n = n;
- sqlite3Parser(pEngine, tokenType, pParse->sLastToken);
- lastTokenParsed = tokenType;
- zSql += n;
- if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
- }
- }
- assert( nErr==0 );
- pParse->zTail = zSql;
-#ifdef YYTRACKMAXSTACKDEPTH
- sqlite3_mutex_enter(sqlite3MallocMutex());
- sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
- sqlite3ParserStackPeak(pEngine)
- );
- sqlite3_mutex_leave(sqlite3MallocMutex());
-#endif /* YYDEBUG */
-#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
- sqlite3ParserFinalize(pEngine);
-#else
- sqlite3ParserFree(pEngine, sqlite3_free);
-#endif
- if( db->mallocFailed ){
- pParse->rc = SQLITE_NOMEM_BKPT;
- }
- if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
- pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
- }
- assert( pzErrMsg!=0 );
- if( pParse->zErrMsg ){
- *pzErrMsg = pParse->zErrMsg;
- sqlite3_log(pParse->rc, "%s", *pzErrMsg);
- pParse->zErrMsg = 0;
- nErr++;
- }
- if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
- sqlite3VdbeDelete(pParse->pVdbe);
- pParse->pVdbe = 0;
- }
-#ifndef SQLITE_OMIT_SHARED_CACHE
- if( pParse->nested==0 ){
- sqlite3DbFree(db, pParse->aTableLock);
- pParse->aTableLock = 0;
- pParse->nTableLock = 0;
- }
-#endif
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_free(pParse->apVtabLock);
-#endif
-
- if( !IN_DECLARE_VTAB ){
- /* If the pParse->declareVtab flag is set, do not delete any table
- ** structure built up in pParse->pNewTable. The calling code (see vtab.c)
- ** will take responsibility for freeing the Table structure.
- */
- sqlite3DeleteTable(db, pParse->pNewTable);
- }
-
- if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
- sqlite3DeleteTrigger(db, pParse->pNewTrigger);
- sqlite3DbFree(db, pParse->pVList);
- while( pParse->pAinc ){
- AutoincInfo *p = pParse->pAinc;
- pParse->pAinc = p->pNext;
- sqlite3DbFreeNN(db, p);
- }
- while( pParse->pZombieTab ){
- Table *p = pParse->pZombieTab;
- pParse->pZombieTab = p->pNextZombie;
- sqlite3DeleteTable(db, p);
- }
- assert( nErr==0 || pParse->rc!=SQLITE_OK );
- return nErr;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/treeview.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/treeview.c
deleted file mode 100644
index 970d85eba4d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/treeview.c
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
-** 2015-06-08
-**
-** 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 contains C code to implement the TreeView debugging routines.
-** These routines print a parse tree to standard output for debugging and
-** analysis.
-**
-** The interfaces in this file is only available when compiling
-** with SQLITE_DEBUG.
-*/
-#include "sqliteInt.h"
-#ifdef SQLITE_DEBUG
-
-/*
-** Add a new subitem to the tree. The moreToFollow flag indicates that this
-** is not the last item in the tree.
-*/
-static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
- if( p==0 ){
- p = sqlite3_malloc64( sizeof(*p) );
- if( p==0 ) return 0;
- memset(p, 0, sizeof(*p));
- }else{
- p->iLevel++;
- }
- assert( moreToFollow==0 || moreToFollow==1 );
- if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
- return p;
-}
-
-/*
-** Finished with one layer of the tree
-*/
-static void sqlite3TreeViewPop(TreeView *p){
- if( p==0 ) return;
- p->iLevel--;
- if( p->iLevel<0 ) sqlite3_free(p);
-}
-
-/*
-** Generate a single line of output for the tree, with a prefix that contains
-** all the appropriate tree lines
-*/
-static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
- va_list ap;
- int i;
- StrAccum acc;
- char zBuf[500];
- sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
- if( p ){
- for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
- sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4);
- }
- sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
- }
- if( zFormat!=0 ){
- va_start(ap, zFormat);
- sqlite3_str_vappendf(&acc, zFormat, ap);
- va_end(ap);
- assert( acc.nChar>0 );
- sqlite3_str_append(&acc, "\n", 1);
- }
- sqlite3StrAccumFinish(&acc);
- fprintf(stdout,"%s", zBuf);
- fflush(stdout);
-}
-
-/*
-** Shorthand for starting a new tree item that consists of a single label
-*/
-static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
- p = sqlite3TreeViewPush(p, moreFollows);
- sqlite3TreeViewLine(p, "%s", zLabel);
-}
-
-/*
-** Generate a human-readable description of a WITH clause.
-*/
-void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
- int i;
- if( pWith==0 ) return;
- if( pWith->nCte==0 ) return;
- if( pWith->pOuter ){
- sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
- }else{
- sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
- }
- if( pWith->nCte>0 ){
- pView = sqlite3TreeViewPush(pView, 1);
- for(i=0; i<pWith->nCte; i++){
- StrAccum x;
- char zLine[1000];
- const struct Cte *pCte = &pWith->a[i];
- sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlite3_str_appendf(&x, "%s", pCte->zName);
- if( pCte->pCols && pCte->pCols->nExpr>0 ){
- char cSep = '(';
- int j;
- for(j=0; j<pCte->pCols->nExpr; j++){
- sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
- cSep = ',';
- }
- sqlite3_str_appendf(&x, ")");
- }
- sqlite3_str_appendf(&x, " AS");
- sqlite3StrAccumFinish(&x);
- sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
- sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
- sqlite3TreeViewPop(pView);
- }
- sqlite3TreeViewPop(pView);
- }
-}
-
-
-/*
-** Generate a human-readable description of a Select object.
-*/
-void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
- int n = 0;
- int cnt = 0;
- if( p==0 ){
- sqlite3TreeViewLine(pView, "nil-SELECT");
- return;
- }
- pView = sqlite3TreeViewPush(pView, moreToFollow);
- if( p->pWith ){
- sqlite3TreeViewWith(pView, p->pWith, 1);
- cnt = 1;
- sqlite3TreeViewPush(pView, 1);
- }
- do{
-#if SELECTTRACE_ENABLED
- sqlite3TreeViewLine(pView,
- "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d",
- ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
- ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
- p->zSelName, p, p->selFlags,
- (int)p->nSelectRow
- );
-#else
- sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d",
- ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
- ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags,
- (int)p->nSelectRow
- );
-#endif
- if( cnt++ ) sqlite3TreeViewPop(pView);
- if( p->pPrior ){
- n = 1000;
- }else{
- n = 0;
- if( p->pSrc && p->pSrc->nSrc ) n++;
- if( p->pWhere ) n++;
- if( p->pGroupBy ) n++;
- if( p->pHaving ) n++;
- if( p->pOrderBy ) n++;
- if( p->pLimit ) n++;
- }
- sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
- if( p->pSrc && p->pSrc->nSrc ){
- int i;
- pView = sqlite3TreeViewPush(pView, (n--)>0);
- sqlite3TreeViewLine(pView, "FROM");
- for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
- StrAccum x;
- char zLine[100];
- sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
- if( pItem->zDatabase ){
- sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
- }else if( pItem->zName ){
- sqlite3_str_appendf(&x, " %s", pItem->zName);
- }
- if( pItem->pTab ){
- sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
- }
- if( pItem->zAlias ){
- sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
- }
- if( pItem->fg.jointype & JT_LEFT ){
- sqlite3_str_appendf(&x, " LEFT-JOIN");
- }
- sqlite3StrAccumFinish(&x);
- sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
- if( pItem->pSelect ){
- sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
- }
- if( pItem->fg.isTabFunc ){
- sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
- }
- sqlite3TreeViewPop(pView);
- }
- sqlite3TreeViewPop(pView);
- }
- if( p->pWhere ){
- sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
- sqlite3TreeViewExpr(pView, p->pWhere, 0);
- sqlite3TreeViewPop(pView);
- }
- if( p->pGroupBy ){
- sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
- }
- if( p->pHaving ){
- sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
- sqlite3TreeViewExpr(pView, p->pHaving, 0);
- sqlite3TreeViewPop(pView);
- }
- if( p->pOrderBy ){
- sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
- }
- if( p->pLimit ){
- sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
- sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
- if( p->pLimit->pRight ){
- sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
- sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
- sqlite3TreeViewPop(pView);
- }
- sqlite3TreeViewPop(pView);
- }
- if( p->pPrior ){
- const char *zOp = "UNION";
- switch( p->op ){
- case TK_ALL: zOp = "UNION ALL"; break;
- case TK_INTERSECT: zOp = "INTERSECT"; break;
- case TK_EXCEPT: zOp = "EXCEPT"; break;
- }
- sqlite3TreeViewItem(pView, zOp, 1);
- }
- p = p->pPrior;
- }while( p!=0 );
- sqlite3TreeViewPop(pView);
-}
-
-/*
-** Generate a human-readable explanation of an expression tree.
-*/
-void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
- const char *zBinOp = 0; /* Binary operator */
- const char *zUniOp = 0; /* Unary operator */
- char zFlgs[60];
- pView = sqlite3TreeViewPush(pView, moreToFollow);
- if( pExpr==0 ){
- sqlite3TreeViewLine(pView, "nil");
- sqlite3TreeViewPop(pView);
- return;
- }
- if( pExpr->flags ){
- if( ExprHasProperty(pExpr, EP_FromJoin) ){
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x iRJT=%d",
- pExpr->flags, pExpr->iRightJoinTable);
- }else{
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
- }
- }else{
- zFlgs[0] = 0;
- }
- switch( pExpr->op ){
- case TK_AGG_COLUMN: {
- sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",
- pExpr->iTable, pExpr->iColumn, zFlgs);
- break;
- }
- case TK_COLUMN: {
- if( pExpr->iTable<0 ){
- /* This only happens when coding check constraints */
- sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs);
- }else{
- sqlite3TreeViewLine(pView, "{%d:%d}%s",
- pExpr->iTable, pExpr->iColumn, zFlgs);
- }
- break;
- }
- case TK_INTEGER: {
- if( pExpr->flags & EP_IntValue ){
- sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
- }else{
- sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
- }
- break;
- }
-#ifndef SQLITE_OMIT_FLOATING_POINT
- case TK_FLOAT: {
- sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
- break;
- }
-#endif
- case TK_STRING: {
- sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
- break;
- }
- case TK_NULL: {
- sqlite3TreeViewLine(pView,"NULL");
- break;
- }
- case TK_TRUEFALSE: {
- sqlite3TreeViewLine(pView,
- sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE");
- break;
- }
-#ifndef SQLITE_OMIT_BLOB_LITERAL
- case TK_BLOB: {
- sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
- break;
- }
-#endif
- case TK_VARIABLE: {
- sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
- pExpr->u.zToken, pExpr->iColumn);
- break;
- }
- case TK_REGISTER: {
- sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
- break;
- }
- case TK_ID: {
- sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
- break;
- }
-#ifndef SQLITE_OMIT_CAST
- case TK_CAST: {
- /* Expressions of the form: CAST(pLeft AS token) */
- sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
- break;
- }
-#endif /* SQLITE_OMIT_CAST */
- case TK_LT: zBinOp = "LT"; break;
- case TK_LE: zBinOp = "LE"; break;
- case TK_GT: zBinOp = "GT"; break;
- case TK_GE: zBinOp = "GE"; break;
- case TK_NE: zBinOp = "NE"; break;
- case TK_EQ: zBinOp = "EQ"; break;
- case TK_IS: zBinOp = "IS"; break;
- case TK_ISNOT: zBinOp = "ISNOT"; break;
- case TK_AND: zBinOp = "AND"; break;
- case TK_OR: zBinOp = "OR"; break;
- case TK_PLUS: zBinOp = "ADD"; break;
- case TK_STAR: zBinOp = "MUL"; break;
- case TK_MINUS: zBinOp = "SUB"; break;
- case TK_REM: zBinOp = "REM"; break;
- case TK_BITAND: zBinOp = "BITAND"; break;
- case TK_BITOR: zBinOp = "BITOR"; break;
- case TK_SLASH: zBinOp = "DIV"; break;
- case TK_LSHIFT: zBinOp = "LSHIFT"; break;
- case TK_RSHIFT: zBinOp = "RSHIFT"; break;
- case TK_CONCAT: zBinOp = "CONCAT"; break;
- case TK_DOT: zBinOp = "DOT"; break;
-
- case TK_UMINUS: zUniOp = "UMINUS"; break;
- case TK_UPLUS: zUniOp = "UPLUS"; break;
- case TK_BITNOT: zUniOp = "BITNOT"; break;
- case TK_NOT: zUniOp = "NOT"; break;
- case TK_ISNULL: zUniOp = "ISNULL"; break;
- case TK_NOTNULL: zUniOp = "NOTNULL"; break;
-
- case TK_TRUTH: {
- int x;
- const char *azOp[] = {
- "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
- };
- assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
- assert( pExpr->pRight );
- assert( pExpr->pRight->op==TK_TRUEFALSE );
- x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
- zUniOp = azOp[x];
- break;
- }
-
- case TK_SPAN: {
- sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
- break;
- }
-
- case TK_COLLATE: {
- sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
- break;
- }
-
- case TK_AGG_FUNCTION:
- case TK_FUNCTION: {
- ExprList *pFarg; /* List of function arguments */
- if( ExprHasProperty(pExpr, EP_TokenOnly) ){
- pFarg = 0;
- }else{
- pFarg = pExpr->x.pList;
- }
- if( pExpr->op==TK_AGG_FUNCTION ){
- sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
- pExpr->op2, pExpr->u.zToken);
- }else{
- sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
- }
- if( pFarg ){
- sqlite3TreeViewExprList(pView, pFarg, 0, 0);
- }
- break;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_EXISTS: {
- sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
- sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
- break;
- }
- case TK_SELECT: {
- sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags);
- sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
- break;
- }
- case TK_IN: {
- sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
- }else{
- sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
- }
- break;
- }
-#endif /* SQLITE_OMIT_SUBQUERY */
-
- /*
- ** x BETWEEN y AND z
- **
- ** This is equivalent to
- **
- ** x>=y AND x<=z
- **
- ** X is stored in pExpr->pLeft.
- ** Y is stored in pExpr->pList->a[0].pExpr.
- ** Z is stored in pExpr->pList->a[1].pExpr.
- */
- case TK_BETWEEN: {
- Expr *pX = pExpr->pLeft;
- Expr *pY = pExpr->x.pList->a[0].pExpr;
- Expr *pZ = pExpr->x.pList->a[1].pExpr;
- sqlite3TreeViewLine(pView, "BETWEEN");
- sqlite3TreeViewExpr(pView, pX, 1);
- sqlite3TreeViewExpr(pView, pY, 1);
- sqlite3TreeViewExpr(pView, pZ, 0);
- break;
- }
- case TK_TRIGGER: {
- /* If the opcode is TK_TRIGGER, then the expression is a reference
- ** to a column in the new.* or old.* pseudo-tables available to
- ** trigger programs. In this case Expr.iTable is set to 1 for the
- ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
- ** is set to the column of the pseudo-table to read, or to -1 to
- ** read the rowid field.
- */
- sqlite3TreeViewLine(pView, "%s(%d)",
- pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
- break;
- }
- case TK_CASE: {
- sqlite3TreeViewLine(pView, "CASE");
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
- sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
- break;
- }
-#ifndef SQLITE_OMIT_TRIGGER
- case TK_RAISE: {
- const char *zType = "unk";
- switch( pExpr->affinity ){
- case OE_Rollback: zType = "rollback"; break;
- case OE_Abort: zType = "abort"; break;
- case OE_Fail: zType = "fail"; break;
- case OE_Ignore: zType = "ignore"; break;
- }
- sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
- break;
- }
-#endif
- case TK_MATCH: {
- sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
- pExpr->iTable, pExpr->iColumn, zFlgs);
- sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
- break;
- }
- case TK_VECTOR: {
- sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR");
- break;
- }
- case TK_SELECT_COLUMN: {
- sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn);
- sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
- break;
- }
- case TK_IF_NULL_ROW: {
- sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
- break;
- }
- default: {
- sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
- break;
- }
- }
- if( zBinOp ){
- sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
- sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
- }else if( zUniOp ){
- sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
- }
- sqlite3TreeViewPop(pView);
-}
-
-
-/*
-** Generate a human-readable explanation of an expression list.
-*/
-void sqlite3TreeViewBareExprList(
- TreeView *pView,
- const ExprList *pList,
- const char *zLabel
-){
- if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
- if( pList==0 ){
- sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
- }else{
- int i;
- sqlite3TreeViewLine(pView, "%s", zLabel);
- for(i=0; i<pList->nExpr; i++){
- int j = pList->a[i].u.x.iOrderByCol;
- char *zName = pList->a[i].zName;
- int moreToFollow = i<pList->nExpr - 1;
- if( j || zName ){
- sqlite3TreeViewPush(pView, moreToFollow);
- moreToFollow = 0;
- sqlite3TreeViewLine(pView, 0);
- if( zName ){
- fprintf(stdout, "AS %s ", zName);
- }
- if( j ){
- fprintf(stdout, "iOrderByCol=%d", j);
- }
- fprintf(stdout, "\n");
- fflush(stdout);
- }
- sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
- if( j || zName ){
- sqlite3TreeViewPop(pView);
- }
- }
- }
-}
-void sqlite3TreeViewExprList(
- TreeView *pView,
- const ExprList *pList,
- u8 moreToFollow,
- const char *zLabel
-){
- pView = sqlite3TreeViewPush(pView, moreToFollow);
- sqlite3TreeViewBareExprList(pView, pList, zLabel);
- sqlite3TreeViewPop(pView);
-}
-
-#endif /* SQLITE_DEBUG */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/trigger.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/trigger.c
deleted file mode 100644
index 044f256aeba..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/trigger.c
+++ /dev/null
@@ -1,1144 +0,0 @@
-/*
-**
-** 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 contains the implementation for TRIGGERs
-*/
-#include "sqliteInt.h"
-
-#ifndef SQLITE_OMIT_TRIGGER
-/*
-** Delete a linked list of TriggerStep structures.
-*/
-void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
- while( pTriggerStep ){
- TriggerStep * pTmp = pTriggerStep;
- pTriggerStep = pTriggerStep->pNext;
-
- sqlite3ExprDelete(db, pTmp->pWhere);
- sqlite3ExprListDelete(db, pTmp->pExprList);
- sqlite3SelectDelete(db, pTmp->pSelect);
- sqlite3IdListDelete(db, pTmp->pIdList);
- sqlite3UpsertDelete(db, pTmp->pUpsert);
- sqlite3DbFree(db, pTmp->zSpan);
-
- sqlite3DbFree(db, pTmp);
- }
-}
-
-/*
-** Given table pTab, return a list of all the triggers attached to
-** the table. The list is connected by Trigger.pNext pointers.
-**
-** All of the triggers on pTab that are in the same database as pTab
-** are already attached to pTab->pTrigger. But there might be additional
-** triggers on pTab in the TEMP schema. This routine prepends all
-** TEMP triggers on pTab to the beginning of the pTab->pTrigger list
-** and returns the combined list.
-**
-** To state it another way: This routine returns a list of all triggers
-** that fire off of pTab. The list will include any TEMP triggers on
-** pTab as well as the triggers lised in pTab->pTrigger.
-*/
-Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
- Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
- Trigger *pList = 0; /* List of triggers to return */
-
- if( pParse->disableTriggers ){
- return 0;
- }
-
- if( pTmpSchema!=pTab->pSchema ){
- HashElem *p;
- assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
- for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
- Trigger *pTrig = (Trigger *)sqliteHashData(p);
- if( pTrig->pTabSchema==pTab->pSchema
- && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
- ){
- pTrig->pNext = (pList ? pList : pTab->pTrigger);
- pList = pTrig;
- }
- }
- }
-
- return (pList ? pList : pTab->pTrigger);
-}
-
-/*
-** This is called by the parser when it sees a CREATE TRIGGER statement
-** up to the point of the BEGIN before the trigger actions. A Trigger
-** structure is generated based on the information available and stored
-** in pParse->pNewTrigger. After the trigger actions have been parsed, the
-** sqlite3FinishTrigger() function is called to complete the trigger
-** construction process.
-*/
-void sqlite3BeginTrigger(
- Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
- Token *pName1, /* The name of the trigger */
- Token *pName2, /* The name of the trigger */
- int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
- int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
- IdList *pColumns, /* column list if this is an UPDATE OF trigger */
- SrcList *pTableName,/* The name of the table/view the trigger applies to */
- Expr *pWhen, /* WHEN clause */
- int isTemp, /* True if the TEMPORARY keyword is present */
- int noErr /* Suppress errors if the trigger already exists */
-){
- Trigger *pTrigger = 0; /* The new trigger */
- Table *pTab; /* Table that the trigger fires off of */
- char *zName = 0; /* Name of the trigger */
- sqlite3 *db = pParse->db; /* The database connection */
- int iDb; /* The database to store the trigger in */
- Token *pName; /* The unqualified db name */
- DbFixer sFix; /* State vector for the DB fixer */
-
- assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */
- assert( pName2!=0 );
- assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE );
- assert( op>0 && op<0xff );
- if( isTemp ){
- /* If TEMP was specified, then the trigger name may not be qualified. */
- if( pName2->n>0 ){
- sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
- goto trigger_cleanup;
- }
- iDb = 1;
- pName = pName1;
- }else{
- /* Figure out the db that the trigger will be created in */
- iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
- if( iDb<0 ){
- goto trigger_cleanup;
- }
- }
- if( !pTableName || db->mallocFailed ){
- goto trigger_cleanup;
- }
-
- /* A long-standing parser bug is that this syntax was allowed:
- **
- ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
- ** ^^^^^^^^
- **
- ** To maintain backwards compatibility, ignore the database
- ** name on pTableName if we are reparsing out of SQLITE_MASTER.
- */
- if( db->init.busy && iDb!=1 ){
- sqlite3DbFree(db, pTableName->a[0].zDatabase);
- pTableName->a[0].zDatabase = 0;
- }
-
- /* If the trigger name was unqualified, and the table is a temp table,
- ** then set iDb to 1 to create the trigger in the temporary database.
- ** If sqlite3SrcListLookup() returns 0, indicating the table does not
- ** exist, the error is caught by the block below.
- */
- pTab = sqlite3SrcListLookup(pParse, pTableName);
- if( db->init.busy==0 && pName2->n==0 && pTab
- && pTab->pSchema==db->aDb[1].pSchema ){
- iDb = 1;
- }
-
- /* Ensure the table name matches database name and that the table exists */
- if( db->mallocFailed ) goto trigger_cleanup;
- assert( pTableName->nSrc==1 );
- sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
- if( sqlite3FixSrcList(&sFix, pTableName) ){
- goto trigger_cleanup;
- }
- pTab = sqlite3SrcListLookup(pParse, pTableName);
- if( !pTab ){
- /* The table does not exist. */
- if( db->init.iDb==1 ){
- /* Ticket #3810.
- ** Normally, whenever a table is dropped, all associated triggers are
- ** dropped too. But if a TEMP trigger is created on a non-TEMP table
- ** and the table is dropped by a different database connection, the
- ** trigger is not visible to the database connection that does the
- ** drop so the trigger cannot be dropped. This results in an
- ** "orphaned trigger" - a trigger whose associated table is missing.
- */
- db->init.orphanTrigger = 1;
- }
- goto trigger_cleanup;
- }
- if( IsVirtual(pTab) ){
- sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
- goto trigger_cleanup;
- }
-
- /* Check that the trigger name is not reserved and that no trigger of the
- ** specified name exists */
- zName = sqlite3NameFromToken(db, pName);
- if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
- goto trigger_cleanup;
- }
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
- if( !noErr ){
- sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
- }else{
- assert( !db->init.busy );
- sqlite3CodeVerifySchema(pParse, iDb);
- }
- goto trigger_cleanup;
- }
-
- /* Do not create a trigger on a system table */
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
- sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
- goto trigger_cleanup;
- }
-
- /* INSTEAD of triggers are only for views and views only support INSTEAD
- ** of triggers.
- */
- if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
- sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
- (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
- goto trigger_cleanup;
- }
- if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
- sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
- " trigger on table: %S", pTableName, 0);
- goto trigger_cleanup;
- }
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- int code = SQLITE_CREATE_TRIGGER;
- const char *zDb = db->aDb[iTabDb].zDbSName;
- const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb;
- if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
- if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
- goto trigger_cleanup;
- }
- if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
- goto trigger_cleanup;
- }
- }
-#endif
-
- /* INSTEAD OF triggers can only appear on views and BEFORE triggers
- ** cannot appear on views. So we might as well translate every
- ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code
- ** elsewhere.
- */
- if (tr_tm == TK_INSTEAD){
- tr_tm = TK_BEFORE;
- }
-
- /* Build the Trigger object */
- pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
- if( pTrigger==0 ) goto trigger_cleanup;
- pTrigger->zName = zName;
- zName = 0;
- pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
- pTrigger->pSchema = db->aDb[iDb].pSchema;
- pTrigger->pTabSchema = pTab->pSchema;
- pTrigger->op = (u8)op;
- pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
- pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
- pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
- assert( pParse->pNewTrigger==0 );
- pParse->pNewTrigger = pTrigger;
-
-trigger_cleanup:
- sqlite3DbFree(db, zName);
- sqlite3SrcListDelete(db, pTableName);
- sqlite3IdListDelete(db, pColumns);
- sqlite3ExprDelete(db, pWhen);
- if( !pParse->pNewTrigger ){
- sqlite3DeleteTrigger(db, pTrigger);
- }else{
- assert( pParse->pNewTrigger==pTrigger );
- }
-}
-
-/*
-** This routine is called after all of the trigger actions have been parsed
-** in order to complete the process of building the trigger.
-*/
-void sqlite3FinishTrigger(
- Parse *pParse, /* Parser context */
- TriggerStep *pStepList, /* The triggered program */
- Token *pAll /* Token that describes the complete CREATE TRIGGER */
-){
- Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
- char *zName; /* Name of trigger */
- sqlite3 *db = pParse->db; /* The database */
- DbFixer sFix; /* Fixer object */
- int iDb; /* Database containing the trigger */
- Token nameToken; /* Trigger name for error reporting */
-
- pParse->pNewTrigger = 0;
- if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
- zName = pTrig->zName;
- iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
- pTrig->step_list = pStepList;
- while( pStepList ){
- pStepList->pTrig = pTrig;
- pStepList = pStepList->pNext;
- }
- sqlite3TokenInit(&nameToken, pTrig->zName);
- sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
- if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
- || sqlite3FixExpr(&sFix, pTrig->pWhen)
- ){
- goto triggerfinish_cleanup;
- }
-
- /* if we are not initializing,
- ** build the sqlite_master entry
- */
- if( !db->init.busy ){
- Vdbe *v;
- char *z;
-
- /* Make an entry in the sqlite_master table */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto triggerfinish_cleanup;
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
- testcase( z==0 );
- sqlite3NestedParse(pParse,
- "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
- db->aDb[iDb].zDbSName, MASTER_NAME, zName,
- pTrig->table, z);
- sqlite3DbFree(db, z);
- sqlite3ChangeCookie(pParse, iDb);
- sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
- }
-
- if( db->init.busy ){
- Trigger *pLink = pTrig;
- Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pTrig = sqlite3HashInsert(pHash, zName, pTrig);
- if( pTrig ){
- sqlite3OomFault(db);
- }else if( pLink->pSchema==pLink->pTabSchema ){
- Table *pTab;
- pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table);
- assert( pTab!=0 );
- pLink->pNext = pTab->pTrigger;
- pTab->pTrigger = pLink;
- }
- }
-
-triggerfinish_cleanup:
- sqlite3DeleteTrigger(db, pTrig);
- assert( !pParse->pNewTrigger );
- sqlite3DeleteTriggerStep(db, pStepList);
-}
-
-/*
-** Duplicate a range of text from an SQL statement, then convert all
-** whitespace characters into ordinary space characters.
-*/
-static char *triggerSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
- char *z = sqlite3DbSpanDup(db, zStart, zEnd);
- int i;
- if( z ) for(i=0; z[i]; i++) if( sqlite3Isspace(z[i]) ) z[i] = ' ';
- return z;
-}
-
-/*
-** Turn a SELECT statement (that the pSelect parameter points to) into
-** a trigger step. Return a pointer to a TriggerStep structure.
-**
-** The parser calls this routine when it finds a SELECT statement in
-** body of a TRIGGER.
-*/
-TriggerStep *sqlite3TriggerSelectStep(
- sqlite3 *db, /* Database connection */
- Select *pSelect, /* The SELECT statement */
- const char *zStart, /* Start of SQL text */
- const char *zEnd /* End of SQL text */
-){
- TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
- if( pTriggerStep==0 ) {
- sqlite3SelectDelete(db, pSelect);
- return 0;
- }
- pTriggerStep->op = TK_SELECT;
- pTriggerStep->pSelect = pSelect;
- pTriggerStep->orconf = OE_Default;
- pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd);
- return pTriggerStep;
-}
-
-/*
-** Allocate space to hold a new trigger step. The allocated space
-** holds both the TriggerStep object and the TriggerStep.target.z string.
-**
-** If an OOM error occurs, NULL is returned and db->mallocFailed is set.
-*/
-static TriggerStep *triggerStepAllocate(
- sqlite3 *db, /* Database connection */
- u8 op, /* Trigger opcode */
- Token *pName, /* The target name */
- const char *zStart, /* Start of SQL text */
- const char *zEnd /* End of SQL text */
-){
- TriggerStep *pTriggerStep;
-
- pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
- if( pTriggerStep ){
- char *z = (char*)&pTriggerStep[1];
- memcpy(z, pName->z, pName->n);
- sqlite3Dequote(z);
- pTriggerStep->zTarget = z;
- pTriggerStep->op = op;
- pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd);
- }
- return pTriggerStep;
-}
-
-/*
-** Build a trigger step out of an INSERT statement. Return a pointer
-** to the new trigger step.
-**
-** The parser calls this routine when it sees an INSERT inside the
-** body of a trigger.
-*/
-TriggerStep *sqlite3TriggerInsertStep(
- sqlite3 *db, /* The database connection */
- Token *pTableName, /* Name of the table into which we insert */
- IdList *pColumn, /* List of columns in pTableName to insert into */
- Select *pSelect, /* A SELECT statement that supplies values */
- u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
- Upsert *pUpsert, /* ON CONFLICT clauses for upsert */
- const char *zStart, /* Start of SQL text */
- const char *zEnd /* End of SQL text */
-){
- TriggerStep *pTriggerStep;
-
- assert(pSelect != 0 || db->mallocFailed);
-
- pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd);
- if( pTriggerStep ){
- pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
- pTriggerStep->pIdList = pColumn;
- pTriggerStep->pUpsert = pUpsert;
- pTriggerStep->orconf = orconf;
- }else{
- testcase( pColumn );
- sqlite3IdListDelete(db, pColumn);
- testcase( pUpsert );
- sqlite3UpsertDelete(db, pUpsert);
- }
- sqlite3SelectDelete(db, pSelect);
-
- return pTriggerStep;
-}
-
-/*
-** Construct a trigger step that implements an UPDATE statement and return
-** a pointer to that trigger step. The parser calls this routine when it
-** sees an UPDATE statement inside the body of a CREATE TRIGGER.
-*/
-TriggerStep *sqlite3TriggerUpdateStep(
- sqlite3 *db, /* The database connection */
- Token *pTableName, /* Name of the table to be updated */
- ExprList *pEList, /* The SET clause: list of column and new values */
- Expr *pWhere, /* The WHERE clause */
- u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
- const char *zStart, /* Start of SQL text */
- const char *zEnd /* End of SQL text */
-){
- TriggerStep *pTriggerStep;
-
- pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName, zStart, zEnd);
- if( pTriggerStep ){
- pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
- pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
- pTriggerStep->orconf = orconf;
- }
- sqlite3ExprListDelete(db, pEList);
- sqlite3ExprDelete(db, pWhere);
- return pTriggerStep;
-}
-
-/*
-** Construct a trigger step that implements a DELETE statement and return
-** a pointer to that trigger step. The parser calls this routine when it
-** sees a DELETE statement inside the body of a CREATE TRIGGER.
-*/
-TriggerStep *sqlite3TriggerDeleteStep(
- sqlite3 *db, /* Database connection */
- Token *pTableName, /* The table from which rows are deleted */
- Expr *pWhere, /* The WHERE clause */
- const char *zStart, /* Start of SQL text */
- const char *zEnd /* End of SQL text */
-){
- TriggerStep *pTriggerStep;
-
- pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName, zStart, zEnd);
- if( pTriggerStep ){
- pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
- pTriggerStep->orconf = OE_Default;
- }
- sqlite3ExprDelete(db, pWhere);
- return pTriggerStep;
-}
-
-/*
-** Recursively delete a Trigger structure
-*/
-void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
- if( pTrigger==0 ) return;
- sqlite3DeleteTriggerStep(db, pTrigger->step_list);
- sqlite3DbFree(db, pTrigger->zName);
- sqlite3DbFree(db, pTrigger->table);
- sqlite3ExprDelete(db, pTrigger->pWhen);
- sqlite3IdListDelete(db, pTrigger->pColumns);
- sqlite3DbFree(db, pTrigger);
-}
-
-/*
-** This function is called to drop a trigger from the database schema.
-**
-** This may be called directly from the parser and therefore identifies
-** the trigger by name. The sqlite3DropTriggerPtr() routine does the
-** same job as this routine except it takes a pointer to the trigger
-** instead of the trigger name.
-**/
-void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
- Trigger *pTrigger = 0;
- int i;
- const char *zDb;
- const char *zName;
- sqlite3 *db = pParse->db;
-
- if( db->mallocFailed ) goto drop_trigger_cleanup;
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- goto drop_trigger_cleanup;
- }
-
- assert( pName->nSrc==1 );
- zDb = pName->a[0].zDatabase;
- zName = pName->a[0].zName;
- assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue;
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
- pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
- if( pTrigger ) break;
- }
- if( !pTrigger ){
- if( !noErr ){
- sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
- }else{
- sqlite3CodeVerifyNamedSchema(pParse, zDb);
- }
- pParse->checkSchema = 1;
- goto drop_trigger_cleanup;
- }
- sqlite3DropTriggerPtr(pParse, pTrigger);
-
-drop_trigger_cleanup:
- sqlite3SrcListDelete(db, pName);
-}
-
-/*
-** Return a pointer to the Table structure for the table that a trigger
-** is set on.
-*/
-static Table *tableOfTrigger(Trigger *pTrigger){
- return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table);
-}
-
-
-/*
-** Drop a trigger given a pointer to that trigger.
-*/
-void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
- Table *pTable;
- Vdbe *v;
- sqlite3 *db = pParse->db;
- int iDb;
-
- iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
- assert( iDb>=0 && iDb<db->nDb );
- pTable = tableOfTrigger(pTrigger);
- assert( pTable );
- assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int code = SQLITE_DROP_TRIGGER;
- const char *zDb = db->aDb[iDb].zDbSName;
- const char *zTab = SCHEMA_TABLE(iDb);
- if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
- if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) ||
- sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
- return;
- }
- }
-#endif
-
- /* Generate code to destroy the database record of the trigger.
- */
- assert( pTable!=0 );
- if( (v = sqlite3GetVdbe(pParse))!=0 ){
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
- db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName
- );
- sqlite3ChangeCookie(pParse, iDb);
- sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
- }
-}
-
-/*
-** Remove a trigger from the hash tables of the sqlite* pointer.
-*/
-void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
- Trigger *pTrigger;
- Hash *pHash;
-
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pHash = &(db->aDb[iDb].pSchema->trigHash);
- pTrigger = sqlite3HashInsert(pHash, zName, 0);
- if( ALWAYS(pTrigger) ){
- if( pTrigger->pSchema==pTrigger->pTabSchema ){
- Table *pTab = tableOfTrigger(pTrigger);
- Trigger **pp;
- for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
- *pp = (*pp)->pNext;
- }
- sqlite3DeleteTrigger(db, pTrigger);
- db->mDbFlags |= DBFLAG_SchemaChange;
- }
-}
-
-/*
-** pEList is the SET clause of an UPDATE statement. Each entry
-** in pEList is of the format <id>=<expr>. If any of the entries
-** in pEList have an <id> which matches an identifier in pIdList,
-** then return TRUE. If pIdList==NULL, then it is considered a
-** wildcard that matches anything. Likewise if pEList==NULL then
-** it matches anything so always return true. Return false only
-** if there is no match.
-*/
-static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
- int e;
- if( pIdList==0 || NEVER(pEList==0) ) return 1;
- for(e=0; e<pEList->nExpr; e++){
- if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
- }
- return 0;
-}
-
-/*
-** Return a list of all triggers on table pTab if there exists at least
-** one trigger that must be fired when an operation of type 'op' is
-** performed on the table, and, if that operation is an UPDATE, if at
-** least one of the columns in pChanges is being modified.
-*/
-Trigger *sqlite3TriggersExist(
- Parse *pParse, /* Parse context */
- Table *pTab, /* The table the contains the triggers */
- int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
- ExprList *pChanges, /* Columns that change in an UPDATE statement */
- int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
-){
- int mask = 0;
- Trigger *pList = 0;
- Trigger *p;
-
- if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){
- pList = sqlite3TriggerList(pParse, pTab);
- }
- assert( pList==0 || IsVirtual(pTab)==0 );
- for(p=pList; p; p=p->pNext){
- if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
- mask |= p->tr_tm;
- }
- }
- if( pMask ){
- *pMask = mask;
- }
- return (mask ? pList : 0);
-}
-
-/*
-** Convert the pStep->zTarget string into a SrcList and return a pointer
-** to that SrcList.
-**
-** This routine adds a specific database name, if needed, to the target when
-** forming the SrcList. This prevents a trigger in one database from
-** referring to a target in another database. An exception is when the
-** trigger is in TEMP in which case it can refer to any other database it
-** wants.
-*/
-static SrcList *targetSrcList(
- Parse *pParse, /* The parsing context */
- TriggerStep *pStep /* The trigger containing the target token */
-){
- sqlite3 *db = pParse->db;
- int iDb; /* Index of the database to use */
- SrcList *pSrc; /* SrcList to be returned */
-
- pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pSrc ){
- assert( pSrc->nSrc>0 );
- pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
- iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
- if( iDb==0 || iDb>=2 ){
- const char *zDb;
- assert( iDb<db->nDb );
- zDb = db->aDb[iDb].zDbSName;
- pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb);
- }
- }
- return pSrc;
-}
-
-/*
-** Generate VDBE code for the statements inside the body of a single
-** trigger.
-*/
-static int codeTriggerProgram(
- Parse *pParse, /* The parser context */
- TriggerStep *pStepList, /* List of statements inside the trigger body */
- int orconf /* Conflict algorithm. (OE_Abort, etc) */
-){
- TriggerStep *pStep;
- Vdbe *v = pParse->pVdbe;
- sqlite3 *db = pParse->db;
-
- assert( pParse->pTriggerTab && pParse->pToplevel );
- assert( pStepList );
- assert( v!=0 );
- for(pStep=pStepList; pStep; pStep=pStep->pNext){
- /* Figure out the ON CONFLICT policy that will be used for this step
- ** of the trigger program. If the statement that caused this trigger
- ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use
- ** the ON CONFLICT policy that was specified as part of the trigger
- ** step statement. Example:
- **
- ** CREATE TRIGGER AFTER INSERT ON t1 BEGIN;
- ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b);
- ** END;
- **
- ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy
- ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy
- */
- pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
- assert( pParse->okConstFactor==0 );
-
-#ifndef SQLITE_OMIT_TRACE
- if( pStep->zSpan ){
- sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0,
- sqlite3MPrintf(db, "-- %s", pStep->zSpan),
- P4_DYNAMIC);
- }
-#endif
-
- switch( pStep->op ){
- case TK_UPDATE: {
- sqlite3Update(pParse,
- targetSrcList(pParse, pStep),
- sqlite3ExprListDup(db, pStep->pExprList, 0),
- sqlite3ExprDup(db, pStep->pWhere, 0),
- pParse->eOrconf, 0, 0, 0
- );
- break;
- }
- case TK_INSERT: {
- sqlite3Insert(pParse,
- targetSrcList(pParse, pStep),
- sqlite3SelectDup(db, pStep->pSelect, 0),
- sqlite3IdListDup(db, pStep->pIdList),
- pParse->eOrconf,
- sqlite3UpsertDup(db, pStep->pUpsert)
- );
- break;
- }
- case TK_DELETE: {
- sqlite3DeleteFrom(pParse,
- targetSrcList(pParse, pStep),
- sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
- );
- break;
- }
- default: assert( pStep->op==TK_SELECT ); {
- SelectDest sDest;
- Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0);
- sqlite3SelectDestInit(&sDest, SRT_Discard, 0);
- sqlite3Select(pParse, pSelect, &sDest);
- sqlite3SelectDelete(db, pSelect);
- break;
- }
- }
- if( pStep->op!=TK_SELECT ){
- sqlite3VdbeAddOp0(v, OP_ResetCount);
- }
- }
-
- return 0;
-}
-
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
-/*
-** This function is used to add VdbeComment() annotations to a VDBE
-** program. It is not used in production code, only for debugging.
-*/
-static const char *onErrorText(int onError){
- switch( onError ){
- case OE_Abort: return "abort";
- case OE_Rollback: return "rollback";
- case OE_Fail: return "fail";
- case OE_Replace: return "replace";
- case OE_Ignore: return "ignore";
- case OE_Default: return "default";
- }
- return "n/a";
-}
-#endif
-
-/*
-** Parse context structure pFrom has just been used to create a sub-vdbe
-** (trigger program). If an error has occurred, transfer error information
-** from pFrom to pTo.
-*/
-static void transferParseError(Parse *pTo, Parse *pFrom){
- assert( pFrom->zErrMsg==0 || pFrom->nErr );
- assert( pTo->zErrMsg==0 || pTo->nErr );
- if( pTo->nErr==0 ){
- pTo->zErrMsg = pFrom->zErrMsg;
- pTo->nErr = pFrom->nErr;
- pTo->rc = pFrom->rc;
- }else{
- sqlite3DbFree(pFrom->db, pFrom->zErrMsg);
- }
-}
-
-/*
-** Create and populate a new TriggerPrg object with a sub-program
-** implementing trigger pTrigger with ON CONFLICT policy orconf.
-*/
-static TriggerPrg *codeRowTrigger(
- Parse *pParse, /* Current parse context */
- Trigger *pTrigger, /* Trigger to code */
- Table *pTab, /* The table pTrigger is attached to */
- int orconf /* ON CONFLICT policy to code trigger program with */
-){
- Parse *pTop = sqlite3ParseToplevel(pParse);
- sqlite3 *db = pParse->db; /* Database handle */
- TriggerPrg *pPrg; /* Value to return */
- Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */
- Vdbe *v; /* Temporary VM */
- NameContext sNC; /* Name context for sub-vdbe */
- SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
- Parse *pSubParse; /* Parse context for sub-vdbe */
- int iEndTrigger = 0; /* Label to jump to if WHEN is false */
-
- assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
- assert( pTop->pVdbe );
-
- /* Allocate the TriggerPrg and SubProgram objects. To ensure that they
- ** are freed if an error occurs, link them into the Parse.pTriggerPrg
- ** list of the top-level Parse object sooner rather than later. */
- pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));
- if( !pPrg ) return 0;
- pPrg->pNext = pTop->pTriggerPrg;
- pTop->pTriggerPrg = pPrg;
- pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram));
- if( !pProgram ) return 0;
- sqlite3VdbeLinkSubProgram(pTop->pVdbe, pProgram);
- pPrg->pTrigger = pTrigger;
- pPrg->orconf = orconf;
- pPrg->aColmask[0] = 0xffffffff;
- pPrg->aColmask[1] = 0xffffffff;
-
- /* Allocate and populate a new Parse context to use for coding the
- ** trigger sub-program. */
- pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
- if( !pSubParse ) return 0;
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pSubParse;
- pSubParse->db = db;
- pSubParse->pTriggerTab = pTab;
- pSubParse->pToplevel = pTop;
- pSubParse->zAuthContext = pTrigger->zName;
- pSubParse->eTriggerOp = pTrigger->op;
- pSubParse->nQueryLoop = pParse->nQueryLoop;
-
- v = sqlite3GetVdbe(pSubParse);
- if( v ){
- VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
- pTrigger->zName, onErrorText(orconf),
- (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
- (pTrigger->op==TK_UPDATE ? "UPDATE" : ""),
- (pTrigger->op==TK_INSERT ? "INSERT" : ""),
- (pTrigger->op==TK_DELETE ? "DELETE" : ""),
- pTab->zName
- ));
-#ifndef SQLITE_OMIT_TRACE
- if( pTrigger->zName ){
- sqlite3VdbeChangeP4(v, -1,
- sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC
- );
- }
-#endif
-
- /* If one was specified, code the WHEN clause. If it evaluates to false
- ** (or NULL) the sub-vdbe is immediately halted by jumping to the
- ** OP_Halt inserted at the end of the program. */
- if( pTrigger->pWhen ){
- pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
- if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
- && db->mallocFailed==0
- ){
- iEndTrigger = sqlite3VdbeMakeLabel(v);
- sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
- }
- sqlite3ExprDelete(db, pWhen);
- }
-
- /* Code the trigger program into the sub-vdbe. */
- codeTriggerProgram(pSubParse, pTrigger->step_list, orconf);
-
- /* Insert an OP_Halt at the end of the sub-program. */
- if( iEndTrigger ){
- sqlite3VdbeResolveLabel(v, iEndTrigger);
- }
- sqlite3VdbeAddOp0(v, OP_Halt);
- VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));
-
- transferParseError(pParse, pSubParse);
- if( db->mallocFailed==0 && pParse->nErr==0 ){
- pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg);
- }
- pProgram->nMem = pSubParse->nMem;
- pProgram->nCsr = pSubParse->nTab;
- pProgram->token = (void *)pTrigger;
- pPrg->aColmask[0] = pSubParse->oldmask;
- pPrg->aColmask[1] = pSubParse->newmask;
- sqlite3VdbeDelete(v);
- }
-
- assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
- assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
- sqlite3ParserReset(pSubParse);
- sqlite3StackFree(db, pSubParse);
-
- return pPrg;
-}
-
-/*
-** Return a pointer to a TriggerPrg object containing the sub-program for
-** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such
-** TriggerPrg object exists, a new object is allocated and populated before
-** being returned.
-*/
-static TriggerPrg *getRowTrigger(
- Parse *pParse, /* Current parse context */
- Trigger *pTrigger, /* Trigger to code */
- Table *pTab, /* The table trigger pTrigger is attached to */
- int orconf /* ON CONFLICT algorithm. */
-){
- Parse *pRoot = sqlite3ParseToplevel(pParse);
- TriggerPrg *pPrg;
-
- assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
-
- /* It may be that this trigger has already been coded (or is in the
- ** process of being coded). If this is the case, then an entry with
- ** a matching TriggerPrg.pTrigger field will be present somewhere
- ** in the Parse.pTriggerPrg list. Search for such an entry. */
- for(pPrg=pRoot->pTriggerPrg;
- pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf);
- pPrg=pPrg->pNext
- );
-
- /* If an existing TriggerPrg could not be located, create a new one. */
- if( !pPrg ){
- pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf);
- }
-
- return pPrg;
-}
-
-/*
-** Generate code for the trigger program associated with trigger p on
-** table pTab. The reg, orconf and ignoreJump parameters passed to this
-** function are the same as those described in the header function for
-** sqlite3CodeRowTrigger()
-*/
-void sqlite3CodeRowTriggerDirect(
- Parse *pParse, /* Parse context */
- Trigger *p, /* Trigger to code */
- Table *pTab, /* The table to code triggers from */
- int reg, /* Reg array containing OLD.* and NEW.* values */
- int orconf, /* ON CONFLICT policy */
- int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
-){
- Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
- TriggerPrg *pPrg;
- pPrg = getRowTrigger(pParse, p, pTab, orconf);
- assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
-
- /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
- ** is a pointer to the sub-vdbe containing the trigger program. */
- if( pPrg ){
- int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers));
-
- sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem,
- (const char *)pPrg->pProgram, P4_SUBPROGRAM);
- VdbeComment(
- (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf)));
-
- /* Set the P5 operand of the OP_Program instruction to non-zero if
- ** recursive invocation of this trigger program is disallowed. Recursive
- ** invocation is disallowed if (a) the sub-program is really a trigger,
- ** not a foreign key action, and (b) the flag to enable recursive triggers
- ** is clear. */
- sqlite3VdbeChangeP5(v, (u8)bRecursive);
- }
-}
-
-/*
-** This is called to code the required FOR EACH ROW triggers for an operation
-** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE)
-** is given by the op parameter. The tr_tm parameter determines whether the
-** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then
-** parameter pChanges is passed the list of columns being modified.
-**
-** If there are no triggers that fire at the specified time for the specified
-** operation on pTab, this function is a no-op.
-**
-** The reg argument is the address of the first in an array of registers
-** that contain the values substituted for the new.* and old.* references
-** in the trigger program. If N is the number of columns in table pTab
-** (a copy of pTab->nCol), then registers are populated as follows:
-**
-** Register Contains
-** ------------------------------------------------------
-** reg+0 OLD.rowid
-** reg+1 OLD.* value of left-most column of pTab
-** ... ...
-** reg+N OLD.* value of right-most column of pTab
-** reg+N+1 NEW.rowid
-** reg+N+2 OLD.* value of left-most column of pTab
-** ... ...
-** reg+N+N+1 NEW.* value of right-most column of pTab
-**
-** For ON DELETE triggers, the registers containing the NEW.* values will
-** never be accessed by the trigger program, so they are not allocated or
-** populated by the caller (there is no data to populate them with anyway).
-** Similarly, for ON INSERT triggers the values stored in the OLD.* registers
-** are never accessed, and so are not allocated by the caller. So, for an
-** ON INSERT trigger, the value passed to this function as parameter reg
-** is not a readable register, although registers (reg+N) through
-** (reg+N+N+1) are.
-**
-** Parameter orconf is the default conflict resolution algorithm for the
-** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump
-** is the instruction that control should jump to if a trigger program
-** raises an IGNORE exception.
-*/
-void sqlite3CodeRowTrigger(
- Parse *pParse, /* Parse context */
- Trigger *pTrigger, /* List of triggers on table pTab */
- int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
- ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
- int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
- Table *pTab, /* The table to code triggers from */
- int reg, /* The first in an array of registers (see above) */
- int orconf, /* ON CONFLICT policy */
- int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
-){
- Trigger *p; /* Used to iterate through pTrigger list */
-
- assert( op==TK_UPDATE || op==TK_INSERT || op==TK_DELETE );
- assert( tr_tm==TRIGGER_BEFORE || tr_tm==TRIGGER_AFTER );
- assert( (op==TK_UPDATE)==(pChanges!=0) );
-
- for(p=pTrigger; p; p=p->pNext){
-
- /* Sanity checking: The schema for the trigger and for the table are
- ** always defined. The trigger must be in the same schema as the table
- ** or else it must be a TEMP trigger. */
- assert( p->pSchema!=0 );
- assert( p->pTabSchema!=0 );
- assert( p->pSchema==p->pTabSchema
- || p->pSchema==pParse->db->aDb[1].pSchema );
-
- /* Determine whether we should code this trigger */
- if( p->op==op
- && p->tr_tm==tr_tm
- && checkColumnOverlap(p->pColumns, pChanges)
- ){
- sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
- }
- }
-}
-
-/*
-** Triggers may access values stored in the old.* or new.* pseudo-table.
-** This function returns a 32-bit bitmask indicating which columns of the
-** old.* or new.* tables actually are used by triggers. This information
-** may be used by the caller, for example, to avoid having to load the entire
-** old.* record into memory when executing an UPDATE or DELETE command.
-**
-** Bit 0 of the returned mask is set if the left-most column of the
-** table may be accessed using an [old|new].<col> reference. Bit 1 is set if
-** the second leftmost column value is required, and so on. If there
-** are more than 32 columns in the table, and at least one of the columns
-** with an index greater than 32 may be accessed, 0xffffffff is returned.
-**
-** It is not possible to determine if the old.rowid or new.rowid column is
-** accessed by triggers. The caller must always assume that it is.
-**
-** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned
-** applies to the old.* table. If 1, the new.* table.
-**
-** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE
-** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only
-** included in the returned mask if the TRIGGER_BEFORE bit is set in the
-** tr_tm parameter. Similarly, values accessed by AFTER triggers are only
-** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm.
-*/
-u32 sqlite3TriggerColmask(
- Parse *pParse, /* Parse context */
- Trigger *pTrigger, /* List of triggers on table pTab */
- ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
- int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */
- int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
- Table *pTab, /* The table to code triggers from */
- int orconf /* Default ON CONFLICT policy for trigger steps */
-){
- const int op = pChanges ? TK_UPDATE : TK_DELETE;
- u32 mask = 0;
- Trigger *p;
-
- assert( isNew==1 || isNew==0 );
- for(p=pTrigger; p; p=p->pNext){
- if( p->op==op && (tr_tm&p->tr_tm)
- && checkColumnOverlap(p->pColumns,pChanges)
- ){
- TriggerPrg *pPrg;
- pPrg = getRowTrigger(pParse, p, pTab, orconf);
- if( pPrg ){
- mask |= pPrg->aColmask[isNew];
- }
- }
- }
-
- return mask;
-}
-
-#endif /* !defined(SQLITE_OMIT_TRIGGER) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/update.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/update.c
deleted file mode 100644
index 9860943c0e6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/update.c
+++ /dev/null
@@ -1,946 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 contains C code routines that are called by the parser
-** to handle UPDATE statements.
-*/
-#include "sqliteInt.h"
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Forward declaration */
-static void updateVirtualTable(
- Parse *pParse, /* The parsing context */
- SrcList *pSrc, /* The virtual table to be modified */
- Table *pTab, /* The virtual table */
- ExprList *pChanges, /* The columns to change in the UPDATE statement */
- Expr *pRowidExpr, /* Expression used to recompute the rowid */
- int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
- Expr *pWhere, /* WHERE clause of the UPDATE statement */
- int onError /* ON CONFLICT strategy */
-);
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/*
-** The most recently coded instruction was an OP_Column to retrieve the
-** i-th column of table pTab. This routine sets the P4 parameter of the
-** OP_Column to the default value, if any.
-**
-** The default value of a column is specified by a DEFAULT clause in the
-** column definition. This was either supplied by the user when the table
-** was created, or added later to the table definition by an ALTER TABLE
-** command. If the latter, then the row-records in the table btree on disk
-** may not contain a value for the column and the default value, taken
-** from the P4 parameter of the OP_Column instruction, is returned instead.
-** If the former, then all row-records are guaranteed to include a value
-** for the column and the P4 value is not required.
-**
-** Column definitions created by an ALTER TABLE command may only have
-** literal default values specified: a number, null or a string. (If a more
-** complicated default expression value was provided, it is evaluated
-** when the ALTER TABLE is executed and one of the literal values written
-** into the sqlite_master table.)
-**
-** Therefore, the P4 parameter is only required if the default value for
-** the column is a literal number, string or null. The sqlite3ValueFromExpr()
-** function is capable of transforming these types of expressions into
-** sqlite3_value objects.
-**
-** If parameter iReg is not negative, code an OP_RealAffinity instruction
-** on register iReg. This is used when an equivalent integer value is
-** stored in place of an 8-byte floating point value in order to save
-** space.
-*/
-void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
- assert( pTab!=0 );
- if( !pTab->pSelect ){
- sqlite3_value *pValue = 0;
- u8 enc = ENC(sqlite3VdbeDb(v));
- Column *pCol = &pTab->aCol[i];
- VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
- assert( i<pTab->nCol );
- sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
- pCol->affinity, &pValue);
- if( pValue ){
- sqlite3VdbeAppendP4(v, pValue, P4_MEM);
- }
- }
-#ifndef SQLITE_OMIT_FLOATING_POINT
- if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
- sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
- }
-#endif
-}
-
-/*
-** Process an UPDATE statement.
-**
-** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
-** \_______/ \________/ \______/ \________________/
-* onError pTabList pChanges pWhere
-*/
-void sqlite3Update(
- Parse *pParse, /* The parser context */
- SrcList *pTabList, /* The table in which we should change things */
- ExprList *pChanges, /* Things to be changed */
- Expr *pWhere, /* The WHERE clause. May be null */
- int onError, /* How to handle constraint errors */
- ExprList *pOrderBy, /* ORDER BY clause. May be null */
- Expr *pLimit, /* LIMIT clause. May be null */
- Upsert *pUpsert /* ON CONFLICT clause, or null */
-){
- int i, j; /* Loop counters */
- Table *pTab; /* The table to be updated */
- int addrTop = 0; /* VDBE instruction address of the start of the loop */
- WhereInfo *pWInfo; /* Information about the WHERE clause */
- Vdbe *v; /* The virtual database engine */
- Index *pIdx; /* For looping over indices */
- Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
- int nIdx; /* Number of indices that need updating */
- int iBaseCur; /* Base cursor number */
- int iDataCur; /* Cursor for the canonical data btree */
- int iIdxCur; /* Cursor for the first index */
- sqlite3 *db; /* The database structure */
- int *aRegIdx = 0; /* First register in array assigned to each index */
- int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
- ** an expression for the i-th column of the table.
- ** aXRef[i]==-1 if the i-th column is not changed. */
- u8 *aToOpen; /* 1 for tables and indices to be opened */
- u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */
- u8 chngRowid; /* Rowid changed in a normal table */
- u8 chngKey; /* Either chngPk or chngRowid */
- Expr *pRowidExpr = 0; /* Expression defining the new record number */
- AuthContext sContext; /* The authorization context */
- NameContext sNC; /* The name-context to resolve expressions in */
- int iDb; /* Database containing the table being updated */
- int eOnePass; /* ONEPASS_XXX value from where.c */
- int hasFK; /* True if foreign key processing is required */
- int labelBreak; /* Jump here to break out of UPDATE loop */
- int labelContinue; /* Jump here to continue next step of UPDATE loop */
- int flags; /* Flags for sqlite3WhereBegin() */
-
-#ifndef SQLITE_OMIT_TRIGGER
- int isView; /* True when updating a view (INSTEAD OF trigger) */
- Trigger *pTrigger; /* List of triggers on pTab, if required */
- int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
-#endif
- int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */
- int iEph = 0; /* Ephemeral table holding all primary key values */
- int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */
- int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
- int addrOpen = 0; /* Address of OP_OpenEphemeral */
- int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */
- i16 nPk = 0; /* Number of components of the PRIMARY KEY */
- int bReplace = 0; /* True if REPLACE conflict resolution might happen */
-
- /* Register Allocations */
- int regRowCount = 0; /* A count of rows changed */
- int regOldRowid = 0; /* The old rowid */
- int regNewRowid = 0; /* The new rowid */
- int regNew = 0; /* Content of the NEW.* table in triggers */
- int regOld = 0; /* Content of OLD.* table in triggers */
- int regRowSet = 0; /* Rowset of rows to be updated */
- int regKey = 0; /* composite PRIMARY KEY value */
-
- memset(&sContext, 0, sizeof(sContext));
- db = pParse->db;
- if( pParse->nErr || db->mallocFailed ){
- goto update_cleanup;
- }
- assert( pTabList->nSrc==1 );
-
- /* Locate the table which we want to update.
- */
- pTab = sqlite3SrcListLookup(pParse, pTabList);
- if( pTab==0 ) goto update_cleanup;
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
-
- /* Figure out if we have any triggers and if the table being
- ** updated is a view.
- */
-#ifndef SQLITE_OMIT_TRIGGER
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
- isView = pTab->pSelect!=0;
- assert( pTrigger || tmask==0 );
-#else
-# define pTrigger 0
-# define isView 0
-# define tmask 0
-#endif
-#ifdef SQLITE_OMIT_VIEW
-# undef isView
-# define isView 0
-#endif
-
-#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- if( !isView ){
- pWhere = sqlite3LimitWhere(
- pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE"
- );
- pOrderBy = 0;
- pLimit = 0;
- }
-#endif
-
- if( sqlite3ViewGetColumnNames(pParse, pTab) ){
- goto update_cleanup;
- }
- if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
- goto update_cleanup;
- }
-
- /* Allocate a cursors for the main database table and for all indices.
- ** The index cursors might not be used, but if they are used they
- ** need to occur right after the database cursor. So go ahead and
- ** allocate enough space, just in case.
- */
- iBaseCur = iDataCur = pParse->nTab++;
- iIdxCur = iDataCur+1;
- pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
- testcase( pPk!=0 && pPk!=pTab->pIndex );
- for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
- if( pPk==pIdx ){
- iDataCur = pParse->nTab;
- }
- pParse->nTab++;
- }
- if( pUpsert ){
- /* On an UPSERT, reuse the same cursors already opened by INSERT */
- iDataCur = pUpsert->iDataCur;
- iIdxCur = pUpsert->iIdxCur;
- pParse->nTab = iBaseCur;
- }
- pTabList->a[0].iCursor = iDataCur;
-
- /* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
- ** Initialize aXRef[] and aToOpen[] to their default values.
- */
- aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
- if( aXRef==0 ) goto update_cleanup;
- aRegIdx = aXRef+pTab->nCol;
- aToOpen = (u8*)(aRegIdx+nIdx);
- memset(aToOpen, 1, nIdx+1);
- aToOpen[nIdx+1] = 0;
- for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
-
- /* Initialize the name-context */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- sNC.pSrcList = pTabList;
- sNC.uNC.pUpsert = pUpsert;
- sNC.ncFlags = NC_UUpsert;
-
- /* Resolve the column names in all the expressions of the
- ** of the UPDATE statement. Also find the column index
- ** for each column to be updated in the pChanges array. For each
- ** column to be updated, make sure we have authorization to change
- ** that column.
- */
- chngRowid = chngPk = 0;
- for(i=0; i<pChanges->nExpr; i++){
- if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
- goto update_cleanup;
- }
- for(j=0; j<pTab->nCol; j++){
- if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
- if( j==pTab->iPKey ){
- chngRowid = 1;
- pRowidExpr = pChanges->a[i].pExpr;
- }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
- chngPk = 1;
- }
- aXRef[j] = i;
- break;
- }
- }
- if( j>=pTab->nCol ){
- if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
- j = -1;
- chngRowid = 1;
- pRowidExpr = pChanges->a[i].pExpr;
- }else{
- sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
- pParse->checkSchema = 1;
- goto update_cleanup;
- }
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int rc;
- rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
- j<0 ? "ROWID" : pTab->aCol[j].zName,
- db->aDb[iDb].zDbSName);
- if( rc==SQLITE_DENY ){
- goto update_cleanup;
- }else if( rc==SQLITE_IGNORE ){
- aXRef[j] = -1;
- }
- }
-#endif
- }
- assert( (chngRowid & chngPk)==0 );
- assert( chngRowid==0 || chngRowid==1 );
- assert( chngPk==0 || chngPk==1 );
- chngKey = chngRowid + chngPk;
-
- /* The SET expressions are not actually used inside the WHERE loop.
- ** So reset the colUsed mask. Unless this is a virtual table. In that
- ** case, set all bits of the colUsed mask (to ensure that the virtual
- ** table implementation makes all columns available).
- */
- pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0;
-
- hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
-
- /* There is one entry in the aRegIdx[] array for each index on the table
- ** being updated. Fill in aRegIdx[] with a register number that will hold
- ** the key for accessing each index.
- **
- ** FIXME: Be smarter about omitting indexes that use expressions.
- */
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- int reg;
- if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){
- reg = ++pParse->nMem;
- pParse->nMem += pIdx->nColumn;
- }else{
- reg = 0;
- for(i=0; i<pIdx->nKeyCol; i++){
- i16 iIdxCol = pIdx->aiColumn[i];
- if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
- reg = ++pParse->nMem;
- pParse->nMem += pIdx->nColumn;
- if( (onError==OE_Replace)
- || (onError==OE_Default && pIdx->onError==OE_Replace)
- ){
- bReplace = 1;
- }
- break;
- }
- }
- }
- if( reg==0 ) aToOpen[j+1] = 0;
- aRegIdx[j] = reg;
- }
- if( bReplace ){
- /* If REPLACE conflict resolution might be invoked, open cursors on all
- ** indexes in case they are needed to delete records. */
- memset(aToOpen, 1, nIdx+1);
- }
-
- /* Begin generating code. */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto update_cleanup;
- if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
- sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);
-
- /* Allocate required registers. */
- if( !IsVirtual(pTab) ){
- regRowSet = ++pParse->nMem;
- regOldRowid = regNewRowid = ++pParse->nMem;
- if( chngPk || pTrigger || hasFK ){
- regOld = pParse->nMem + 1;
- pParse->nMem += pTab->nCol;
- }
- if( chngKey || pTrigger || hasFK ){
- regNewRowid = ++pParse->nMem;
- }
- regNew = pParse->nMem + 1;
- pParse->nMem += pTab->nCol;
- }
-
- /* Start the view context. */
- if( isView ){
- sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
- }
-
- /* If we are trying to update a view, realize that view into
- ** an ephemeral table.
- */
-#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
- if( isView ){
- sqlite3MaterializeView(pParse, pTab,
- pWhere, pOrderBy, pLimit, iDataCur
- );
- pOrderBy = 0;
- pLimit = 0;
- }
-#endif
-
- /* Resolve the column names in all the expressions in the
- ** WHERE clause.
- */
- if( sqlite3ResolveExprNames(&sNC, pWhere) ){
- goto update_cleanup;
- }
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- /* Virtual tables must be handled separately */
- if( IsVirtual(pTab) ){
- updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
- pWhere, onError);
- goto update_cleanup;
- }
-#endif
-
- /* Jump to labelBreak to abandon further processing of this UPDATE */
- labelContinue = labelBreak = sqlite3VdbeMakeLabel(v);
-
- /* Not an UPSERT. Normal processing. Begin by
- ** initialize the count of updated rows */
- if( (db->flags&SQLITE_CountRows)!=0
- && !pParse->pTriggerTab
- && !pParse->nested
- && pUpsert==0
- ){
- regRowCount = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
- }
-
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
- }else{
- assert( pPk!=0 );
- nPk = pPk->nKeyCol;
- iPk = pParse->nMem+1;
- pParse->nMem += nPk;
- regKey = ++pParse->nMem;
- if( pUpsert==0 ){
- iEph = pParse->nTab++;
- sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1);
- addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
- sqlite3VdbeSetP4KeyInfo(pParse, pPk);
- }
- }
-
- if( pUpsert ){
- /* If this is an UPSERT, then all cursors have already been opened by
- ** the outer INSERT and the data cursor should be pointing at the row
- ** that is to be updated. So bypass the code that searches for the
- ** row(s) to be updated.
- */
- pWInfo = 0;
- eOnePass = ONEPASS_SINGLE;
- sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
- }else{
- /* Begin the database scan.
- **
- ** Do not consider a single-pass strategy for a multi-row update if
- ** there are any triggers or foreign keys to process, or rows may
- ** be deleted as a result of REPLACE conflict handling. Any of these
- ** things might disturb a cursor being used to scan through the table
- ** or index, causing a single-pass approach to malfunction. */
- flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
- if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
- flags |= WHERE_ONEPASS_MULTIROW;
- }
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur);
- if( pWInfo==0 ) goto update_cleanup;
-
- /* A one-pass strategy that might update more than one row may not
- ** be used if any column of the index used for the scan is being
- ** updated. Otherwise, if there is an index on "b", statements like
- ** the following could create an infinite loop:
- **
- ** UPDATE t1 SET b=b+1 WHERE b>?
- **
- ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI
- ** strategy that uses an index for which one or more columns are being
- ** updated. */
- eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
- if( eOnePass!=ONEPASS_SINGLE ){
- sqlite3MultiWrite(pParse);
- if( eOnePass==ONEPASS_MULTI ){
- int iCur = aiCurOnePass[1];
- if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
- eOnePass = ONEPASS_OFF;
- }
- assert( iCur!=iDataCur || !HasRowid(pTab) );
- }
- }
- }
-
- if( HasRowid(pTab) ){
- /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF
- ** mode, write the rowid into the FIFO. In either of the one-pass modes,
- ** leave it in register regOldRowid. */
- sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
- if( eOnePass==ONEPASS_OFF ){
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
- }
- }else{
- /* Read the PK of the current row into an array of registers. In
- ** ONEPASS_OFF mode, serialize the array into a record and store it in
- ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change
- ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table
- ** is not required) and leave the PK fields in the array of registers. */
- for(i=0; i<nPk; i++){
- assert( pPk->aiColumn[i]>=0 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i);
- }
- if( eOnePass ){
- if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
- nKey = nPk;
- regKey = iPk;
- }else{
- sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
- sqlite3IndexAffinityStr(db, pPk), nPk);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk);
- }
- }
-
- if( pUpsert==0 ){
- if( eOnePass!=ONEPASS_MULTI ){
- sqlite3WhereEnd(pWInfo);
- }
-
- if( !isView ){
- int addrOnce = 0;
-
- /* Open every index that needs updating. */
- if( eOnePass!=ONEPASS_OFF ){
- if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
- if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
- }
-
- if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){
- addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- }
- sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur,
- aToOpen, 0, 0);
- if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
- }
-
- /* Top of the update loop */
- if( eOnePass!=ONEPASS_OFF ){
- if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
- assert( pPk );
- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
- VdbeCoverageNeverTaken(v);
- }
- if( eOnePass!=ONEPASS_SINGLE ){
- labelContinue = sqlite3VdbeMakeLabel(v);
- }
- sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
- VdbeCoverageIf(v, pPk==0);
- VdbeCoverageIf(v, pPk!=0);
- }else if( pPk ){
- labelContinue = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
- addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey);
- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
- VdbeCoverage(v);
- }else{
- labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak,
- regOldRowid);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
- VdbeCoverage(v);
- }
- }
-
- /* If the rowid value will change, set register regNewRowid to
- ** contain the new value. If the rowid is not being modified,
- ** then regNewRowid is the same register as regOldRowid, which is
- ** already populated. */
- assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid );
- if( chngRowid ){
- sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
- sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v);
- }
-
- /* Compute the old pre-UPDATE content of the row being changed, if that
- ** information is needed */
- if( chngPk || hasFK || pTrigger ){
- u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
- oldmask |= sqlite3TriggerColmask(pParse,
- pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
- );
- for(i=0; i<pTab->nCol; i++){
- if( oldmask==0xffffffff
- || (i<32 && (oldmask & MASKBIT32(i))!=0)
- || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
- ){
- testcase( oldmask!=0xffffffff && i==31 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
- }else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
- }
- }
- if( chngRowid==0 && pPk==0 ){
- sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
- }
- }
-
- /* Populate the array of registers beginning at regNew with the new
- ** row data. This array is used to check constants, create the new
- ** table and index records, and as the values for any new.* references
- ** made by triggers.
- **
- ** If there are one or more BEFORE triggers, then do not populate the
- ** registers associated with columns that are (a) not modified by
- ** this UPDATE statement and (b) not accessed by new.* references. The
- ** values for registers not modified by the UPDATE must be reloaded from
- ** the database after the BEFORE triggers are fired anyway (as the trigger
- ** may have modified them). So not loading those that are not going to
- ** be used eliminates some redundant opcodes.
- */
- newmask = sqlite3TriggerColmask(
- pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
- );
- for(i=0; i<pTab->nCol; i++){
- if( i==pTab->iPKey ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
- }else{
- j = aXRef[i];
- if( j>=0 ){
- sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
- }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
- /* This branch loads the value of a column that will not be changed
- ** into a register. This is done if there are no BEFORE triggers, or
- ** if there are one or more BEFORE triggers that use this value via
- ** a new.* reference in a trigger program.
- */
- testcase( i==31 );
- testcase( i==32 );
- sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
- if( tmask & TRIGGER_BEFORE ){
- /* This value will be recomputed in After-BEFORE-trigger-reload-loop
- ** below, so make sure that it is not cached and reused.
- ** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */
- sqlite3ExprCacheRemove(pParse, regNew+i, 1);
- }
- }else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
- }
- }
- }
-
- /* Fire any BEFORE UPDATE triggers. This happens before constraints are
- ** verified. One could argue that this is wrong.
- */
- if( tmask&TRIGGER_BEFORE ){
- sqlite3TableAffinity(v, pTab, regNew);
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
- TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue);
-
- /* The row-trigger may have deleted the row being updated. In this
- ** case, jump to the next row. No updates or AFTER triggers are
- ** required. This behavior - what happens when the row being updated
- ** is deleted or renamed by a BEFORE trigger - is left undefined in the
- ** documentation.
- */
- if( pPk ){
- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey);
- VdbeCoverage(v);
- }else{
- sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
- VdbeCoverage(v);
- }
-
- /* After-BEFORE-trigger-reload-loop:
- ** If it did not delete it, the BEFORE trigger may still have modified
- ** some of the columns of the row being updated. Load the values for
- ** all columns not modified by the update statement into their registers
- ** in case this has happened. Only unmodified columns are reloaded.
- ** The values computed for modified columns use the values before the
- ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26)
- ** for an example.
- */
- for(i=0; i<pTab->nCol; i++){
- if( aXRef[i]<0 && i!=pTab->iPKey ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
- }
- }
- }
-
- if( !isView ){
- int addr1 = 0; /* Address of jump instruction */
-
- /* Do constraint checks. */
- assert( regOldRowid>0 );
- sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
- regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,
- aXRef, 0);
-
- /* Do FK constraint checks. */
- if( hasFK ){
- sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
- }
-
- /* Delete the index entries associated with the current record. */
- if( bReplace || chngKey ){
- if( pPk ){
- addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
- }else{
- addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
- }
- VdbeCoverageNeverTaken(v);
- }
- sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);
-
- /* If changing the rowid value, or if there are foreign key constraints
- ** to process, delete the old record. Otherwise, add a noop OP_Delete
- ** to invoke the pre-update hook.
- **
- ** That (regNew==regnewRowid+1) is true is also important for the
- ** pre-update hook. If the caller invokes preupdate_new(), the returned
- ** value is copied from memory cell (regNewRowid+1+iCol), where iCol
- ** is the column index supplied by the user.
- */
- assert( regNew==regNewRowid+1 );
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- sqlite3VdbeAddOp3(v, OP_Delete, iDataCur,
- OPFLAG_ISUPDATE | ((hasFK>1 || chngKey) ? 0 : OPFLAG_ISNOOP),
- regNewRowid
- );
- if( eOnePass==ONEPASS_MULTI ){
- assert( hasFK==0 && chngKey==0 );
- sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
- }
- if( !pParse->nested ){
- sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
- }
-#else
- if( hasFK>1 || chngKey ){
- sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
- }
-#endif
- if( bReplace || chngKey ){
- sqlite3VdbeJumpHere(v, addr1);
- }
-
- if( hasFK ){
- sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);
- }
-
- /* Insert the new index entries and the new record. */
- sqlite3CompleteInsertion(
- pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx,
- OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0),
- 0, 0
- );
-
- /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
- ** handle rows (possibly in other tables) that refer via a foreign key
- ** to the row just updated. */
- if( hasFK ){
- sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey);
- }
- }
-
- /* Increment the row counter
- */
- if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
- }
-
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
- TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue);
-
- /* Repeat the above with the next record to be updated, until
- ** all record selected by the WHERE clause have been updated.
- */
- if( eOnePass==ONEPASS_SINGLE ){
- /* Nothing to do at end-of-loop for a single-pass */
- }else if( eOnePass==ONEPASS_MULTI ){
- sqlite3VdbeResolveLabel(v, labelContinue);
- sqlite3WhereEnd(pWInfo);
- }else if( pPk ){
- sqlite3VdbeResolveLabel(v, labelContinue);
- sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
- }else{
- sqlite3VdbeGoto(v, labelContinue);
- }
- sqlite3VdbeResolveLabel(v, labelBreak);
-
- /* Update the sqlite_sequence table by storing the content of the
- ** maximum rowid counter values recorded while inserting into
- ** autoincrement tables.
- */
- if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){
- sqlite3AutoincrementEnd(pParse);
- }
-
- /*
- ** Return the number of rows that were changed, if we are tracking
- ** that information.
- */
- if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
- }
-
-update_cleanup:
- sqlite3AuthContextPop(&sContext);
- sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */
- sqlite3SrcListDelete(db, pTabList);
- sqlite3ExprListDelete(db, pChanges);
- sqlite3ExprDelete(db, pWhere);
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
- sqlite3ExprListDelete(db, pOrderBy);
- sqlite3ExprDelete(db, pLimit);
-#endif
- return;
-}
-/* Make sure "isView" and other macros defined above are undefined. Otherwise
-** they may interfere with compilation of other functions in this file
-** (or in another file, if this file becomes part of the amalgamation). */
-#ifdef isView
- #undef isView
-#endif
-#ifdef pTrigger
- #undef pTrigger
-#endif
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*
-** Generate code for an UPDATE of a virtual table.
-**
-** There are two possible strategies - the default and the special
-** "onepass" strategy. Onepass is only used if the virtual table
-** implementation indicates that pWhere may match at most one row.
-**
-** The default strategy is to create an ephemeral table that contains
-** for each row to be changed:
-**
-** (A) The original rowid of that row.
-** (B) The revised rowid for the row.
-** (C) The content of every column in the row.
-**
-** Then loop through the contents of this ephemeral table executing a
-** VUpdate for each row. When finished, drop the ephemeral table.
-**
-** The "onepass" strategy does not use an ephemeral table. Instead, it
-** stores the same values (A, B and C above) in a register array and
-** makes a single invocation of VUpdate.
-*/
-static void updateVirtualTable(
- Parse *pParse, /* The parsing context */
- SrcList *pSrc, /* The virtual table to be modified */
- Table *pTab, /* The virtual table */
- ExprList *pChanges, /* The columns to change in the UPDATE statement */
- Expr *pRowid, /* Expression used to recompute the rowid */
- int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
- Expr *pWhere, /* WHERE clause of the UPDATE statement */
- int onError /* ON CONFLICT strategy */
-){
- Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
- int ephemTab; /* Table holding the result of the SELECT */
- int i; /* Loop counter */
- sqlite3 *db = pParse->db; /* Database connection */
- const char *pVTab = (const char*)sqlite3GetVTable(db, pTab);
- WhereInfo *pWInfo;
- int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */
- int regArg; /* First register in VUpdate arg array */
- int regRec; /* Register in which to assemble record */
- int regRowid; /* Register for ephem table rowid */
- int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */
- int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */
- int eOnePass; /* True to use onepass strategy */
- int addr; /* Address of OP_OpenEphemeral */
-
- /* Allocate nArg registers in which to gather the arguments for VUpdate. Then
- ** create and open the ephemeral table in which the records created from
- ** these arguments will be temporarily stored. */
- assert( v );
- ephemTab = pParse->nTab++;
- addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
- regArg = pParse->nMem + 1;
- pParse->nMem += nArg;
- regRec = ++pParse->nMem;
- regRowid = ++pParse->nMem;
-
- /* Start scanning the virtual table */
- pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0);
- if( pWInfo==0 ) return;
-
- /* Populate the argument registers. */
- for(i=0; i<pTab->nCol; i++){
- if( aXRef[i]>=0 ){
- sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
- }else{
- sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
- sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
- }
- }
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
- if( pRowid ){
- sqlite3ExprCode(pParse, pRowid, regArg+1);
- }else{
- sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
- }
- }else{
- Index *pPk; /* PRIMARY KEY index */
- i16 iPk; /* PRIMARY KEY column */
- pPk = sqlite3PrimaryKeyIndex(pTab);
- assert( pPk!=0 );
- assert( pPk->nKeyCol==1 );
- iPk = pPk->aiColumn[0];
- sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg);
- sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
- }
-
- eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
-
- /* There is no ONEPASS_MULTI on virtual tables */
- assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
-
- if( eOnePass ){
- /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
- ** above. */
- sqlite3VdbeChangeToNoop(v, addr);
- sqlite3VdbeAddOp1(v, OP_Close, iCsr);
- }else{
- /* Create a record from the argument register contents and insert it into
- ** the ephemeral table. */
- sqlite3MultiWrite(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
-#ifdef SQLITE_DEBUG
- /* Signal an assert() within OP_MakeRecord that it is allowed to
- ** accept no-change records with serial_type 10 */
- sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
-#endif
- sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
- }
-
-
- if( eOnePass==ONEPASS_OFF ){
- /* End the virtual table scan */
- sqlite3WhereEnd(pWInfo);
-
- /* Begin scannning through the ephemeral table. */
- addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v);
-
- /* Extract arguments from the current row of the ephemeral table and
- ** invoke the VUpdate method. */
- for(i=0; i<nArg; i++){
- sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i);
- }
- }
- sqlite3VtabMakeWritable(pParse, pTab);
- sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB);
- sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
- sqlite3MayAbort(pParse);
-
- /* End of the ephemeral table scan. Or, if using the onepass strategy,
- ** jump to here if the scan visited zero rows. */
- if( eOnePass==ONEPASS_OFF ){
- sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, addr);
- sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
- }else{
- sqlite3WhereEnd(pWInfo);
- }
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/upsert.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/upsert.c
deleted file mode 100644
index 31a905dd6c9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/upsert.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
-** 2018-04-12
-**
-** 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 contains code to implement various aspects of UPSERT
-** processing and handling of the Upsert object.
-*/
-#include "sqliteInt.h"
-
-#ifndef SQLITE_OMIT_UPSERT
-/*
-** Free a list of Upsert objects
-*/
-void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
- if( p ){
- sqlite3ExprListDelete(db, p->pUpsertTarget);
- sqlite3ExprDelete(db, p->pUpsertTargetWhere);
- sqlite3ExprListDelete(db, p->pUpsertSet);
- sqlite3ExprDelete(db, p->pUpsertWhere);
- sqlite3DbFree(db, p);
- }
-}
-
-/*
-** Duplicate an Upsert object.
-*/
-Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){
- if( p==0 ) return 0;
- return sqlite3UpsertNew(db,
- sqlite3ExprListDup(db, p->pUpsertTarget, 0),
- sqlite3ExprDup(db, p->pUpsertTargetWhere, 0),
- sqlite3ExprListDup(db, p->pUpsertSet, 0),
- sqlite3ExprDup(db, p->pUpsertWhere, 0)
- );
-}
-
-/*
-** Create a new Upsert object.
-*/
-Upsert *sqlite3UpsertNew(
- sqlite3 *db, /* Determines which memory allocator to use */
- ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */
- Expr *pTargetWhere, /* Optional WHERE clause on the target */
- ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */
- Expr *pWhere /* WHERE clause for the ON CONFLICT UPDATE */
-){
- Upsert *pNew;
- pNew = sqlite3DbMallocRaw(db, sizeof(Upsert));
- if( pNew==0 ){
- sqlite3ExprListDelete(db, pTarget);
- sqlite3ExprDelete(db, pTargetWhere);
- sqlite3ExprListDelete(db, pSet);
- sqlite3ExprDelete(db, pWhere);
- return 0;
- }else{
- pNew->pUpsertTarget = pTarget;
- pNew->pUpsertTargetWhere = pTargetWhere;
- pNew->pUpsertSet = pSet;
- pNew->pUpsertWhere = pWhere;
- pNew->pUpsertIdx = 0;
- }
- return pNew;
-}
-
-/*
-** Analyze the ON CONFLICT clause described by pUpsert. Resolve all
-** symbols in the conflict-target.
-**
-** Return SQLITE_OK if everything works, or an error code is something
-** is wrong.
-*/
-int sqlite3UpsertAnalyzeTarget(
- Parse *pParse, /* The parsing context */
- SrcList *pTabList, /* Table into which we are inserting */
- Upsert *pUpsert /* The ON CONFLICT clauses */
-){
- Table *pTab; /* That table into which we are inserting */
- int rc; /* Result code */
- int iCursor; /* Cursor used by pTab */
- Index *pIdx; /* One of the indexes of pTab */
- ExprList *pTarget; /* The conflict-target clause */
- Expr *pTerm; /* One term of the conflict-target clause */
- NameContext sNC; /* Context for resolving symbolic names */
- Expr sCol[2]; /* Index column converted into an Expr */
-
- assert( pTabList->nSrc==1 );
- assert( pTabList->a[0].pTab!=0 );
- assert( pUpsert!=0 );
- assert( pUpsert->pUpsertTarget!=0 );
-
- /* Resolve all symbolic names in the conflict-target clause, which
- ** includes both the list of columns and the optional partial-index
- ** WHERE clause.
- */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- sNC.pSrcList = pTabList;
- rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
- if( rc ) return rc;
- rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
- if( rc ) return rc;
-
- /* Check to see if the conflict target matches the rowid. */
- pTab = pTabList->a[0].pTab;
- pTarget = pUpsert->pUpsertTarget;
- iCursor = pTabList->a[0].iCursor;
- if( HasRowid(pTab)
- && pTarget->nExpr==1
- && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
- && pTerm->iColumn==XN_ROWID
- ){
- /* The conflict-target is the rowid of the primary table */
- assert( pUpsert->pUpsertIdx==0 );
- return SQLITE_OK;
- }
-
- /* Initialize sCol[0..1] to be an expression parse tree for a
- ** single column of an index. The sCol[0] node will be the TK_COLLATE
- ** operator and sCol[1] will be the TK_COLUMN operator. Code below
- ** will populate the specific collation and column number values
- ** prior to comparing against the conflict-target expression.
- */
- memset(sCol, 0, sizeof(sCol));
- sCol[0].op = TK_COLLATE;
- sCol[0].pLeft = &sCol[1];
- sCol[1].op = TK_COLUMN;
- sCol[1].iTable = pTabList->a[0].iCursor;
-
- /* Check for matches against other indexes */
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int ii, jj, nn;
- if( !IsUniqueIndex(pIdx) ) continue;
- if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
- if( pIdx->pPartIdxWhere ){
- if( pUpsert->pUpsertTargetWhere==0 ) continue;
- if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
- pIdx->pPartIdxWhere, iCursor)!=0 ){
- continue;
- }
- }
- nn = pIdx->nKeyCol;
- for(ii=0; ii<nn; ii++){
- Expr *pExpr;
- sCol[0].u.zToken = (char*)pIdx->azColl[ii];
- if( pIdx->aiColumn[ii]==XN_EXPR ){
- assert( pIdx->aColExpr!=0 );
- assert( pIdx->aColExpr->nExpr>ii );
- pExpr = pIdx->aColExpr->a[ii].pExpr;
- if( pExpr->op!=TK_COLLATE ){
- sCol[0].pLeft = pExpr;
- pExpr = &sCol[0];
- }
- }else{
- sCol[0].pLeft = &sCol[1];
- sCol[1].iColumn = pIdx->aiColumn[ii];
- pExpr = &sCol[0];
- }
- for(jj=0; jj<nn; jj++){
- if( sqlite3ExprCompare(pParse, pTarget->a[jj].pExpr, pExpr,iCursor)<2 ){
- break; /* Column ii of the index matches column jj of target */
- }
- }
- if( jj>=nn ){
- /* The target contains no match for column jj of the index */
- break;
- }
- }
- if( ii<nn ){
- /* Column ii of the index did not match any term of the conflict target.
- ** Continue the search with the next index. */
- continue;
- }
- pUpsert->pUpsertIdx = pIdx;
- return SQLITE_OK;
- }
- sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any "
- "PRIMARY KEY or UNIQUE constraint");
- return SQLITE_ERROR;
-}
-
-/*
-** Generate bytecode that does an UPDATE as part of an upsert.
-**
-** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK.
-** In this case parameter iCur is a cursor open on the table b-tree that
-** currently points to the conflicting table row. Otherwise, if pIdx
-** is not NULL, then pIdx is the constraint that failed and iCur is a
-** cursor points to the conflicting row.
-*/
-void sqlite3UpsertDoUpdate(
- Parse *pParse, /* The parsing and code-generating context */
- Upsert *pUpsert, /* The ON CONFLICT clause for the upsert */
- Table *pTab, /* The table being updated */
- Index *pIdx, /* The UNIQUE constraint that failed */
- int iCur /* Cursor for pIdx (or pTab if pIdx==NULL) */
-){
- Vdbe *v = pParse->pVdbe;
- sqlite3 *db = pParse->db;
- SrcList *pSrc; /* FROM clause for the UPDATE */
- int iDataCur = pUpsert->iDataCur;
-
- assert( v!=0 );
- VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
- if( pIdx && iCur!=iDataCur ){
- if( HasRowid(pTab) ){
- int regRowid = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid);
- sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid);
- VdbeCoverage(v);
- sqlite3ReleaseTempReg(pParse, regRowid);
- }else{
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- int nPk = pPk->nKeyCol;
- int iPk = pParse->nMem+1;
- int i;
- pParse->nMem += nPk;
- for(i=0; i<nPk; i++){
- int k;
- assert( pPk->aiColumn[i]>=0 );
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
- sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
- VdbeComment((v, "%s.%s", pIdx->zName,
- pTab->aCol[pPk->aiColumn[i]].zName));
- }
- sqlite3VdbeVerifyAbortable(v, OE_Abort);
- i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
- VdbeCoverage(v);
- sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
- "corrupt database", P4_STATIC);
- sqlite3VdbeJumpHere(v, i);
- }
- }
- /* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So
- ** we have to make a copy before passing it down into sqlite3Update() */
- pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0);
- sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet,
- pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert);
- pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */
- pUpsert->pUpsertWhere = 0; /* Will have been deleted by sqlite3Update() */
- VdbeNoopComment((v, "End DO UPDATE of UPSERT"));
-}
-
-#endif /* SQLITE_OMIT_UPSERT */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/utf.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/utf.c
deleted file mode 100644
index 4b04c9e2829..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/utf.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
-** 2004 April 13
-**
-** 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 contains routines used to translate between UTF-8,
-** UTF-16, UTF-16BE, and UTF-16LE.
-**
-** Notes on UTF-8:
-**
-** Byte-0 Byte-1 Byte-2 Byte-3 Value
-** 0xxxxxxx 00000000 00000000 0xxxxxxx
-** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx
-** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx
-** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx
-**
-**
-** Notes on UTF-16: (with wwww+1==uuuuu)
-**
-** Word-0 Word-1 Value
-** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx
-** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx
-**
-**
-** BOM or Byte Order Mark:
-** 0xff 0xfe little-endian utf-16 follows
-** 0xfe 0xff big-endian utf-16 follows
-**
-*/
-#include "sqliteInt.h"
-#include <assert.h>
-#include "vdbeInt.h"
-
-#if !defined(SQLITE_AMALGAMATION) && SQLITE_BYTEORDER==0
-/*
-** The following constant value is used by the SQLITE_BIGENDIAN and
-** SQLITE_LITTLEENDIAN macros.
-*/
-const int sqlite3one = 1;
-#endif /* SQLITE_AMALGAMATION && SQLITE_BYTEORDER==0 */
-
-/*
-** This lookup table is used to help decode the first byte of
-** a multi-byte UTF8 character.
-*/
-static const unsigned char sqlite3Utf8Trans1[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
-};
-
-
-#define WRITE_UTF8(zOut, c) { \
- if( c<0x00080 ){ \
- *zOut++ = (u8)(c&0xFF); \
- } \
- else if( c<0x00800 ){ \
- *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- } \
- else if( c<0x10000 ){ \
- *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- }else{ \
- *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
- *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- } \
-}
-
-#define WRITE_UTF16LE(zOut, c) { \
- if( c<=0xFFFF ){ \
- *zOut++ = (u8)(c&0x00FF); \
- *zOut++ = (u8)((c>>8)&0x00FF); \
- }else{ \
- *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
- *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
- *zOut++ = (u8)(c&0x00FF); \
- *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
- } \
-}
-
-#define WRITE_UTF16BE(zOut, c) { \
- if( c<=0xFFFF ){ \
- *zOut++ = (u8)((c>>8)&0x00FF); \
- *zOut++ = (u8)(c&0x00FF); \
- }else{ \
- *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
- *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
- *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
- *zOut++ = (u8)(c&0x00FF); \
- } \
-}
-
-#define READ_UTF16LE(zIn, TERM, c){ \
- c = (*zIn++); \
- c += ((*zIn++)<<8); \
- if( c>=0xD800 && c<0xE000 && TERM ){ \
- int c2 = (*zIn++); \
- c2 += ((*zIn++)<<8); \
- c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
- } \
-}
-
-#define READ_UTF16BE(zIn, TERM, c){ \
- c = ((*zIn++)<<8); \
- c += (*zIn++); \
- if( c>=0xD800 && c<0xE000 && TERM ){ \
- int c2 = ((*zIn++)<<8); \
- c2 += (*zIn++); \
- c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
- } \
-}
-
-/*
-** Translate a single UTF-8 character. Return the unicode value.
-**
-** During translation, assume that the byte that zTerm points
-** is a 0x00.
-**
-** Write a pointer to the next unread byte back into *pzNext.
-**
-** Notes On Invalid UTF-8:
-**
-** * This routine never allows a 7-bit character (0x00 through 0x7f) to
-** be encoded as a multi-byte character. Any multi-byte character that
-** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
-**
-** * This routine never allows a UTF16 surrogate value to be encoded.
-** If a multi-byte character attempts to encode a value between
-** 0xd800 and 0xe000 then it is rendered as 0xfffd.
-**
-** * Bytes in the range of 0x80 through 0xbf which occur as the first
-** byte of a character are interpreted as single-byte characters
-** and rendered as themselves even though they are technically
-** invalid characters.
-**
-** * This routine accepts over-length UTF8 encodings
-** for unicode values 0x80 and greater. It does not change over-length
-** encodings to 0xfffd as some systems recommend.
-*/
-#define READ_UTF8(zIn, zTerm, c) \
- c = *(zIn++); \
- if( c>=0xc0 ){ \
- c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
- c = (c<<6) + (0x3f & *(zIn++)); \
- } \
- if( c<0x80 \
- || (c&0xFFFFF800)==0xD800 \
- || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
- }
-u32 sqlite3Utf8Read(
- const unsigned char **pz /* Pointer to string from which to read char */
-){
- unsigned int c;
-
- /* Same as READ_UTF8() above but without the zTerm parameter.
- ** For this routine, we assume the UTF8 string is always zero-terminated.
- */
- c = *((*pz)++);
- if( c>=0xc0 ){
- c = sqlite3Utf8Trans1[c-0xc0];
- while( (*(*pz) & 0xc0)==0x80 ){
- c = (c<<6) + (0x3f & *((*pz)++));
- }
- if( c<0x80
- || (c&0xFFFFF800)==0xD800
- || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
- }
- return c;
-}
-
-
-
-
-/*
-** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
-** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
-*/
-/* #define TRANSLATE_TRACE 1 */
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** This routine transforms the internal text encoding used by pMem to
-** desiredEnc. It is an error if the string is already of the desired
-** encoding, or if *pMem does not contain a string value.
-*/
-SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
- int len; /* Maximum length of output string in bytes */
- unsigned char *zOut; /* Output buffer */
- unsigned char *zIn; /* Input iterator */
- unsigned char *zTerm; /* End of input */
- unsigned char *z; /* Output iterator */
- unsigned int c;
-
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( pMem->flags&MEM_Str );
- assert( pMem->enc!=desiredEnc );
- assert( pMem->enc!=0 );
- assert( pMem->n>=0 );
-
-#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
- {
- char zBuf[100];
- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
- fprintf(stderr, "INPUT: %s\n", zBuf);
- }
-#endif
-
- /* If the translation is between UTF-16 little and big endian, then
- ** all that is required is to swap the byte order. This case is handled
- ** differently from the others.
- */
- if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){
- u8 temp;
- int rc;
- rc = sqlite3VdbeMemMakeWriteable(pMem);
- if( rc!=SQLITE_OK ){
- assert( rc==SQLITE_NOMEM );
- return SQLITE_NOMEM_BKPT;
- }
- zIn = (u8*)pMem->z;
- zTerm = &zIn[pMem->n&~1];
- while( zIn<zTerm ){
- temp = *zIn;
- *zIn = *(zIn+1);
- zIn++;
- *zIn++ = temp;
- }
- pMem->enc = desiredEnc;
- goto translate_out;
- }
-
- /* Set len to the maximum number of bytes required in the output buffer. */
- if( desiredEnc==SQLITE_UTF8 ){
- /* When converting from UTF-16, the maximum growth results from
- ** translating a 2-byte character to a 4-byte UTF-8 character.
- ** A single byte is required for the output string
- ** nul-terminator.
- */
- pMem->n &= ~1;
- len = pMem->n * 2 + 1;
- }else{
- /* When converting from UTF-8 to UTF-16 the maximum growth is caused
- ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
- ** character. Two bytes are required in the output buffer for the
- ** nul-terminator.
- */
- len = pMem->n * 2 + 2;
- }
-
- /* Set zIn to point at the start of the input buffer and zTerm to point 1
- ** byte past the end.
- **
- ** Variable zOut is set to point at the output buffer, space obtained
- ** from sqlite3_malloc().
- */
- zIn = (u8*)pMem->z;
- zTerm = &zIn[pMem->n];
- zOut = sqlite3DbMallocRaw(pMem->db, len);
- if( !zOut ){
- return SQLITE_NOMEM_BKPT;
- }
- z = zOut;
-
- if( pMem->enc==SQLITE_UTF8 ){
- if( desiredEnc==SQLITE_UTF16LE ){
- /* UTF-8 -> UTF-16 Little-endian */
- while( zIn<zTerm ){
- READ_UTF8(zIn, zTerm, c);
- WRITE_UTF16LE(z, c);
- }
- }else{
- assert( desiredEnc==SQLITE_UTF16BE );
- /* UTF-8 -> UTF-16 Big-endian */
- while( zIn<zTerm ){
- READ_UTF8(zIn, zTerm, c);
- WRITE_UTF16BE(z, c);
- }
- }
- pMem->n = (int)(z - zOut);
- *z++ = 0;
- }else{
- assert( desiredEnc==SQLITE_UTF8 );
- if( pMem->enc==SQLITE_UTF16LE ){
- /* UTF-16 Little-endian -> UTF-8 */
- while( zIn<zTerm ){
- READ_UTF16LE(zIn, zIn<zTerm, c);
- WRITE_UTF8(z, c);
- }
- }else{
- /* UTF-16 Big-endian -> UTF-8 */
- while( zIn<zTerm ){
- READ_UTF16BE(zIn, zIn<zTerm, c);
- WRITE_UTF8(z, c);
- }
- }
- pMem->n = (int)(z - zOut);
- }
- *z = 0;
- assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
-
- c = pMem->flags;
- sqlite3VdbeMemRelease(pMem);
- pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype));
- pMem->enc = desiredEnc;
- pMem->z = (char*)zOut;
- pMem->zMalloc = pMem->z;
- pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z);
-
-translate_out:
-#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
- {
- char zBuf[100];
- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
- fprintf(stderr, "OUTPUT: %s\n", zBuf);
- }
-#endif
- return SQLITE_OK;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** This routine checks for a byte-order mark at the beginning of the
-** UTF-16 string stored in *pMem. If one is present, it is removed and
-** the encoding of the Mem adjusted. This routine does not do any
-** byte-swapping, it just sets Mem.enc appropriately.
-**
-** The allocation (static, dynamic etc.) and encoding of the Mem may be
-** changed by this function.
-*/
-int sqlite3VdbeMemHandleBom(Mem *pMem){
- int rc = SQLITE_OK;
- u8 bom = 0;
-
- assert( pMem->n>=0 );
- if( pMem->n>1 ){
- u8 b1 = *(u8 *)pMem->z;
- u8 b2 = *(((u8 *)pMem->z) + 1);
- if( b1==0xFE && b2==0xFF ){
- bom = SQLITE_UTF16BE;
- }
- if( b1==0xFF && b2==0xFE ){
- bom = SQLITE_UTF16LE;
- }
- }
-
- if( bom ){
- rc = sqlite3VdbeMemMakeWriteable(pMem);
- if( rc==SQLITE_OK ){
- pMem->n -= 2;
- memmove(pMem->z, &pMem->z[2], pMem->n);
- pMem->z[pMem->n] = '\0';
- pMem->z[pMem->n+1] = '\0';
- pMem->flags |= MEM_Term;
- pMem->enc = bom;
- }
- }
- return rc;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-
-/*
-** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
-** return the number of unicode characters in pZ up to (but not including)
-** the first 0x00 byte. If nByte is not less than zero, return the
-** number of unicode characters in the first nByte of pZ (or up to
-** the first 0x00, whichever comes first).
-*/
-int sqlite3Utf8CharLen(const char *zIn, int nByte){
- int r = 0;
- const u8 *z = (const u8*)zIn;
- const u8 *zTerm;
- if( nByte>=0 ){
- zTerm = &z[nByte];
- }else{
- zTerm = (const u8*)(-1);
- }
- assert( z<=zTerm );
- while( *z!=0 && z<zTerm ){
- SQLITE_SKIP_UTF8(z);
- r++;
- }
- return r;
-}
-
-/* This test function is not currently used by the automated test-suite.
-** Hence it is only available in debug builds.
-*/
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-/*
-** Translate UTF-8 to UTF-8.
-**
-** This has the effect of making sure that the string is well-formed
-** UTF-8. Miscoded characters are removed.
-**
-** The translation is done in-place and aborted if the output
-** overruns the input.
-*/
-int sqlite3Utf8To8(unsigned char *zIn){
- unsigned char *zOut = zIn;
- unsigned char *zStart = zIn;
- u32 c;
-
- while( zIn[0] && zOut<=zIn ){
- c = sqlite3Utf8Read((const u8**)&zIn);
- if( c!=0xfffd ){
- WRITE_UTF8(zOut, c);
- }
- }
- *zOut = 0;
- return (int)(zOut - zStart);
-}
-#endif
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** Convert a UTF-16 string in the native encoding into a UTF-8 string.
-** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
-** be freed by the calling function.
-**
-** NULL is returned if there is an allocation error.
-*/
-char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
- Mem m;
- memset(&m, 0, sizeof(m));
- m.db = db;
- sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
- sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
- if( db->mallocFailed ){
- sqlite3VdbeMemRelease(&m);
- m.z = 0;
- }
- assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
- assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
- assert( m.z || db->mallocFailed );
- return m.z;
-}
-
-/*
-** zIn is a UTF-16 encoded unicode string at least nChar characters long.
-** Return the number of bytes in the first nChar unicode characters
-** in pZ. nChar must be non-negative.
-*/
-int sqlite3Utf16ByteLen(const void *zIn, int nChar){
- int c;
- unsigned char const *z = zIn;
- int n = 0;
-
- if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
- while( n<nChar ){
- READ_UTF16BE(z, 1, c);
- n++;
- }
- }else{
- while( n<nChar ){
- READ_UTF16LE(z, 1, c);
- n++;
- }
- }
- return (int)(z-(unsigned char const *)zIn);
-}
-
-#if defined(SQLITE_TEST)
-/*
-** This routine is called from the TCL test function "translate_selftest".
-** It checks that the primitives for serializing and deserializing
-** characters in each encoding are inverses of each other.
-*/
-void sqlite3UtfSelfTest(void){
- unsigned int i, t;
- unsigned char zBuf[20];
- unsigned char *z;
- int n;
- unsigned int c;
-
- for(i=0; i<0x00110000; i++){
- z = zBuf;
- WRITE_UTF8(z, i);
- n = (int)(z-zBuf);
- assert( n>0 && n<=4 );
- z[0] = 0;
- z = zBuf;
- c = sqlite3Utf8Read((const u8**)&z);
- t = i;
- if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
- if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
- assert( c==t );
- assert( (z-zBuf)==n );
- }
- for(i=0; i<0x00110000; i++){
- if( i>=0xD800 && i<0xE000 ) continue;
- z = zBuf;
- WRITE_UTF16LE(z, i);
- n = (int)(z-zBuf);
- assert( n>0 && n<=4 );
- z[0] = 0;
- z = zBuf;
- READ_UTF16LE(z, 1, c);
- assert( c==i );
- assert( (z-zBuf)==n );
- }
- for(i=0; i<0x00110000; i++){
- if( i>=0xD800 && i<0xE000 ) continue;
- z = zBuf;
- WRITE_UTF16BE(z, i);
- n = (int)(z-zBuf);
- assert( n>0 && n<=4 );
- z[0] = 0;
- z = zBuf;
- READ_UTF16BE(z, 1, c);
- assert( c==i );
- assert( (z-zBuf)==n );
- }
-}
-#endif /* SQLITE_TEST */
-#endif /* SQLITE_OMIT_UTF16 */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/util.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/util.c
deleted file mode 100644
index 54f9b938875..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/util.c
+++ /dev/null
@@ -1,1624 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Utility functions used throughout sqlite.
-**
-** This file contains functions for allocating memory, comparing
-** strings, and stuff like that.
-**
-*/
-#include "sqliteInt.h"
-#include <stdarg.h>
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
-# include <math.h>
-#endif
-
-/*
-** Routine needed to support the testcase() macro.
-*/
-#ifdef SQLITE_COVERAGE_TEST
-void sqlite3Coverage(int x){
- static unsigned dummy = 0;
- dummy += (unsigned)x;
-}
-#endif
-
-/*
-** Give a callback to the test harness that can be used to simulate faults
-** in places where it is difficult or expensive to do so purely by means
-** of inputs.
-**
-** The intent of the integer argument is to let the fault simulator know
-** which of multiple sqlite3FaultSim() calls has been hit.
-**
-** Return whatever integer value the test callback returns, or return
-** SQLITE_OK if no test callback is installed.
-*/
-#ifndef SQLITE_UNTESTABLE
-int sqlite3FaultSim(int iTest){
- int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
- return xCallback ? xCallback(iTest) : SQLITE_OK;
-}
-#endif
-
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/*
-** Return true if the floating point value is Not a Number (NaN).
-**
-** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
-** Otherwise, we have our own implementation that works on most systems.
-*/
-int sqlite3IsNaN(double x){
- int rc; /* The value return */
-#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN
- /*
- ** Systems that support the isnan() library function should probably
- ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have
- ** found that many systems do not have a working isnan() function so
- ** this implementation is provided as an alternative.
- **
- ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
- ** On the other hand, the use of -ffast-math comes with the following
- ** warning:
- **
- ** This option [-ffast-math] should never be turned on by any
- ** -O option since it can result in incorrect output for programs
- ** which depend on an exact implementation of IEEE or ISO
- ** rules/specifications for math functions.
- **
- ** Under MSVC, this NaN test may fail if compiled with a floating-
- ** point precision mode other than /fp:precise. From the MSDN
- ** documentation:
- **
- ** The compiler [with /fp:precise] will properly handle comparisons
- ** involving NaN. For example, x != x evaluates to true if x is NaN
- ** ...
- */
-#ifdef __FAST_MATH__
-# error SQLite will not work correctly with the -ffast-math option of GCC.
-#endif
- volatile double y = x;
- volatile double z = y;
- rc = (y!=z);
-#else /* if HAVE_ISNAN */
- rc = isnan(x);
-#endif /* HAVE_ISNAN */
- testcase( rc );
- return rc;
-}
-#endif /* SQLITE_OMIT_FLOATING_POINT */
-
-/*
-** Compute a string length that is limited to what can be stored in
-** lower 30 bits of a 32-bit signed integer.
-**
-** The value returned will never be negative. Nor will it ever be greater
-** than the actual length of the string. For very long strings (greater
-** than 1GiB) the value returned might be less than the true string length.
-*/
-int sqlite3Strlen30(const char *z){
- if( z==0 ) return 0;
- return 0x3fffffff & (int)strlen(z);
-}
-
-/*
-** Return the declared type of a column. Or return zDflt if the column
-** has no declared type.
-**
-** The column type is an extra string stored after the zero-terminator on
-** the column name if and only if the COLFLAG_HASTYPE flag is set.
-*/
-char *sqlite3ColumnType(Column *pCol, char *zDflt){
- if( (pCol->colFlags & COLFLAG_HASTYPE)==0 ) return zDflt;
- return pCol->zName + strlen(pCol->zName) + 1;
-}
-
-/*
-** Helper function for sqlite3Error() - called rarely. Broken out into
-** a separate routine to avoid unnecessary register saves on entry to
-** sqlite3Error().
-*/
-static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){
- if( db->pErr ) sqlite3ValueSetNull(db->pErr);
- sqlite3SystemError(db, err_code);
-}
-
-/*
-** Set the current error code to err_code and clear any prior error message.
-** Also set iSysErrno (by calling sqlite3System) if the err_code indicates
-** that would be appropriate.
-*/
-void sqlite3Error(sqlite3 *db, int err_code){
- assert( db!=0 );
- db->errCode = err_code;
- if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code);
-}
-
-/*
-** Load the sqlite3.iSysErrno field if that is an appropriate thing
-** to do based on the SQLite error code in rc.
-*/
-void sqlite3SystemError(sqlite3 *db, int rc){
- if( rc==SQLITE_IOERR_NOMEM ) return;
- rc &= 0xff;
- if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){
- db->iSysErrno = sqlite3OsGetLastError(db->pVfs);
- }
-}
-
-/*
-** Set the most recent error code and error string for the sqlite
-** handle "db". The error code is set to "err_code".
-**
-** If it is not NULL, string zFormat specifies the format of the
-** error string in the style of the printf functions: The following
-** format characters are allowed:
-**
-** %s Insert a string
-** %z A string that should be freed after use
-** %d Insert an integer
-** %T Insert a token
-** %S Insert the first element of a SrcList
-**
-** zFormat and any string tokens that follow it are assumed to be
-** encoded in UTF-8.
-**
-** To clear the most recent error for sqlite handle "db", sqlite3Error
-** should be called with err_code set to SQLITE_OK and zFormat set
-** to NULL.
-*/
-void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){
- assert( db!=0 );
- db->errCode = err_code;
- sqlite3SystemError(db, err_code);
- if( zFormat==0 ){
- sqlite3Error(db, err_code);
- }else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){
- char *z;
- va_list ap;
- va_start(ap, zFormat);
- z = sqlite3VMPrintf(db, zFormat, ap);
- va_end(ap);
- sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
- }
-}
-
-/*
-** Add an error message to pParse->zErrMsg and increment pParse->nErr.
-** The following formatting characters are allowed:
-**
-** %s Insert a string
-** %z A string that should be freed after use
-** %d Insert an integer
-** %T Insert a token
-** %S Insert the first element of a SrcList
-**
-** This function should be used to report any error that occurs while
-** compiling an SQL statement (i.e. within sqlite3_prepare()). The
-** last thing the sqlite3_prepare() function does is copy the error
-** stored by this function into the database handle using sqlite3Error().
-** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used
-** during statement execution (sqlite3_step() etc.).
-*/
-void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
- char *zMsg;
- va_list ap;
- sqlite3 *db = pParse->db;
- va_start(ap, zFormat);
- zMsg = sqlite3VMPrintf(db, zFormat, ap);
- va_end(ap);
- if( db->suppressErr ){
- sqlite3DbFree(db, zMsg);
- }else{
- pParse->nErr++;
- sqlite3DbFree(db, pParse->zErrMsg);
- pParse->zErrMsg = zMsg;
- pParse->rc = SQLITE_ERROR;
- }
-}
-
-/*
-** Convert an SQL-style quoted string into a normal string by removing
-** the quote characters. The conversion is done in-place. If the
-** input does not begin with a quote character, then this routine
-** is a no-op.
-**
-** The input string must be zero-terminated. A new zero-terminator
-** is added to the dequoted string.
-**
-** The return value is -1 if no dequoting occurs or the length of the
-** dequoted string, exclusive of the zero terminator, if dequoting does
-** occur.
-**
-** 2002-Feb-14: This routine is extended to remove MS-Access style
-** brackets from around identifiers. For example: "[a-b-c]" becomes
-** "a-b-c".
-*/
-void sqlite3Dequote(char *z){
- char quote;
- int i, j;
- if( z==0 ) return;
- quote = z[0];
- if( !sqlite3Isquote(quote) ) return;
- if( quote=='[' ) quote = ']';
- for(i=1, j=0;; i++){
- assert( z[i] );
- if( z[i]==quote ){
- if( z[i+1]==quote ){
- z[j++] = quote;
- i++;
- }else{
- break;
- }
- }else{
- z[j++] = z[i];
- }
- }
- z[j] = 0;
-}
-
-/*
-** Generate a Token object from a string
-*/
-void sqlite3TokenInit(Token *p, char *z){
- p->z = z;
- p->n = sqlite3Strlen30(z);
-}
-
-/* Convenient short-hand */
-#define UpperToLower sqlite3UpperToLower
-
-/*
-** Some systems have stricmp(). Others have strcasecmp(). Because
-** there is no consistency, we will define our own.
-**
-** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
-** sqlite3_strnicmp() APIs allow applications and extensions to compare
-** the contents of two buffers containing UTF-8 strings in a
-** case-independent fashion, using the same definition of "case
-** independence" that SQLite uses internally when comparing identifiers.
-*/
-int sqlite3_stricmp(const char *zLeft, const char *zRight){
- if( zLeft==0 ){
- return zRight ? -1 : 0;
- }else if( zRight==0 ){
- return 1;
- }
- return sqlite3StrICmp(zLeft, zRight);
-}
-int sqlite3StrICmp(const char *zLeft, const char *zRight){
- unsigned char *a, *b;
- int c;
- a = (unsigned char *)zLeft;
- b = (unsigned char *)zRight;
- for(;;){
- c = (int)UpperToLower[*a] - (int)UpperToLower[*b];
- if( c || *a==0 ) break;
- a++;
- b++;
- }
- return c;
-}
-int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
- register unsigned char *a, *b;
- if( zLeft==0 ){
- return zRight ? -1 : 0;
- }else if( zRight==0 ){
- return 1;
- }
- a = (unsigned char *)zLeft;
- b = (unsigned char *)zRight;
- while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
- return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
-}
-
-/*
-** Compute 10 to the E-th power. Examples: E==1 results in 10.
-** E==2 results in 100. E==50 results in 1.0e50.
-**
-** This routine only works for values of E between 1 and 341.
-*/
-static LONGDOUBLE_TYPE sqlite3Pow10(int E){
-#if defined(_MSC_VER)
- static const LONGDOUBLE_TYPE x[] = {
- 1.0e+001,
- 1.0e+002,
- 1.0e+004,
- 1.0e+008,
- 1.0e+016,
- 1.0e+032,
- 1.0e+064,
- 1.0e+128,
- 1.0e+256
- };
- LONGDOUBLE_TYPE r = 1.0;
- int i;
- assert( E>=0 && E<=307 );
- for(i=0; E!=0; i++, E >>=1){
- if( E & 1 ) r *= x[i];
- }
- return r;
-#else
- LONGDOUBLE_TYPE x = 10.0;
- LONGDOUBLE_TYPE r = 1.0;
- while(1){
- if( E & 1 ) r *= x;
- E >>= 1;
- if( E==0 ) break;
- x *= x;
- }
- return r;
-#endif
-}
-
-/*
-** The string z[] is an text representation of a real number.
-** Convert this string to a double and write it into *pResult.
-**
-** The string z[] is length bytes in length (bytes, not characters) and
-** uses the encoding enc. The string is not necessarily zero-terminated.
-**
-** Return TRUE if the result is a valid real number (or integer) and FALSE
-** if the string is empty or contains extraneous text. Valid numbers
-** are in one of these formats:
-**
-** [+-]digits[E[+-]digits]
-** [+-]digits.[digits][E[+-]digits]
-** [+-].digits[E[+-]digits]
-**
-** Leading and trailing whitespace is ignored for the purpose of determining
-** validity.
-**
-** If some prefix of the input string is a valid number, this routine
-** returns FALSE but it still converts the prefix and writes the result
-** into *pResult.
-*/
-int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
-#ifndef SQLITE_OMIT_FLOATING_POINT
- int incr;
- const char *zEnd = z + length;
- /* sign * significand * (10 ^ (esign * exponent)) */
- int sign = 1; /* sign of significand */
- i64 s = 0; /* significand */
- int d = 0; /* adjust exponent for shifting decimal point */
- int esign = 1; /* sign of exponent */
- int e = 0; /* exponent */
- int eValid = 1; /* True exponent is either not used or is well-formed */
- double result;
- int nDigits = 0;
- int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
-
- assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
- *pResult = 0.0; /* Default return value, in case of an error */
-
- if( enc==SQLITE_UTF8 ){
- incr = 1;
- }else{
- int i;
- incr = 2;
- assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
- for(i=3-enc; i<length && z[i]==0; i+=2){}
- nonNum = i<length;
- zEnd = &z[i^1];
- z += (enc&1);
- }
-
- /* skip leading spaces */
- while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
- if( z>=zEnd ) return 0;
-
- /* get sign of significand */
- if( *z=='-' ){
- sign = -1;
- z+=incr;
- }else if( *z=='+' ){
- z+=incr;
- }
-
- /* copy max significant digits to significand */
- while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
- s = s*10 + (*z - '0');
- z+=incr; nDigits++;
- }
-
- /* skip non-significant significand digits
- ** (increase exponent by d to shift decimal left) */
- while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; nDigits++; d++; }
- if( z>=zEnd ) goto do_atof_calc;
-
- /* if decimal point is present */
- if( *z=='.' ){
- z+=incr;
- /* copy digits from after decimal to significand
- ** (decrease exponent by d to shift decimal right) */
- while( z<zEnd && sqlite3Isdigit(*z) ){
- if( s<((LARGEST_INT64-9)/10) ){
- s = s*10 + (*z - '0');
- d--;
- }
- z+=incr; nDigits++;
- }
- }
- if( z>=zEnd ) goto do_atof_calc;
-
- /* if exponent is present */
- if( *z=='e' || *z=='E' ){
- z+=incr;
- eValid = 0;
-
- /* This branch is needed to avoid a (harmless) buffer overread. The
- ** special comment alerts the mutation tester that the correct answer
- ** is obtained even if the branch is omitted */
- if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
-
- /* get sign of exponent */
- if( *z=='-' ){
- esign = -1;
- z+=incr;
- }else if( *z=='+' ){
- z+=incr;
- }
- /* copy digits to exponent */
- while( z<zEnd && sqlite3Isdigit(*z) ){
- e = e<10000 ? (e*10 + (*z - '0')) : 10000;
- z+=incr;
- eValid = 1;
- }
- }
-
- /* skip trailing spaces */
- while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
-
-do_atof_calc:
- /* adjust exponent by d, and update sign */
- e = (e*esign) + d;
- if( e<0 ) {
- esign = -1;
- e *= -1;
- } else {
- esign = 1;
- }
-
- if( s==0 ) {
- /* In the IEEE 754 standard, zero is signed. */
- result = sign<0 ? -(double)0 : (double)0;
- } else {
- /* Attempt to reduce exponent.
- **
- ** Branches that are not required for the correct answer but which only
- ** help to obtain the correct answer faster are marked with special
- ** comments, as a hint to the mutation tester.
- */
- while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/
- if( esign>0 ){
- if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/
- s *= 10;
- }else{
- if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/
- s /= 10;
- }
- e--;
- }
-
- /* adjust the sign of significand */
- s = sign<0 ? -s : s;
-
- if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
- result = (double)s;
- }else{
- /* attempt to handle extremely small/large numbers better */
- if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
- if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
- LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308);
- if( esign<0 ){
- result = s / scale;
- result /= 1.0e+308;
- }else{
- result = s * scale;
- result *= 1.0e+308;
- }
- }else{ assert( e>=342 );
- if( esign<0 ){
- result = 0.0*s;
- }else{
-#ifdef INFINITY
- result = INFINITY*s;
-#else
- result = 1e308*1e308*s; /* Infinity */
-#endif
- }
- }
- }else{
- LONGDOUBLE_TYPE scale = sqlite3Pow10(e);
- if( esign<0 ){
- result = s / scale;
- }else{
- result = s * scale;
- }
- }
- }
- }
-
- /* store the result */
- *pResult = result;
-
- /* return true if number and no extra non-whitespace chracters after */
- return z==zEnd && nDigits>0 && eValid && nonNum==0;
-#else
- return !sqlite3Atoi64(z, pResult, length, enc);
-#endif /* SQLITE_OMIT_FLOATING_POINT */
-}
-
-/*
-** Compare the 19-character string zNum against the text representation
-** value 2^63: 9223372036854775808. Return negative, zero, or positive
-** if zNum is less than, equal to, or greater than the string.
-** Note that zNum must contain exactly 19 characters.
-**
-** Unlike memcmp() this routine is guaranteed to return the difference
-** in the values of the last digit if the only difference is in the
-** last digit. So, for example,
-**
-** compare2pow63("9223372036854775800", 1)
-**
-** will return -8.
-*/
-static int compare2pow63(const char *zNum, int incr){
- int c = 0;
- int i;
- /* 012345678901234567 */
- const char *pow63 = "922337203685477580";
- for(i=0; c==0 && i<18; i++){
- c = (zNum[i*incr]-pow63[i])*10;
- }
- if( c==0 ){
- c = zNum[18*incr] - '8';
- testcase( c==(-1) );
- testcase( c==0 );
- testcase( c==(+1) );
- }
- return c;
-}
-
-/*
-** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
-** routine does *not* accept hexadecimal notation.
-**
-** Returns:
-**
-** 0 Successful transformation. Fits in a 64-bit signed integer.
-** 1 Excess non-space text after the integer value
-** 2 Integer too large for a 64-bit signed integer or is malformed
-** 3 Special case of 9223372036854775808
-**
-** length is the number of bytes in the string (bytes, not characters).
-** The string is not necessarily zero-terminated. The encoding is
-** given by enc.
-*/
-int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
- int incr;
- u64 u = 0;
- int neg = 0; /* assume positive */
- int i;
- int c = 0;
- int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
- int rc; /* Baseline return code */
- const char *zStart;
- const char *zEnd = zNum + length;
- assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
- if( enc==SQLITE_UTF8 ){
- incr = 1;
- }else{
- incr = 2;
- assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
- for(i=3-enc; i<length && zNum[i]==0; i+=2){}
- nonNum = i<length;
- zEnd = &zNum[i^1];
- zNum += (enc&1);
- }
- while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
- if( zNum<zEnd ){
- if( *zNum=='-' ){
- neg = 1;
- zNum+=incr;
- }else if( *zNum=='+' ){
- zNum+=incr;
- }
- }
- zStart = zNum;
- while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
- for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
- u = u*10 + c - '0';
- }
- testcase( i==18*incr );
- testcase( i==19*incr );
- testcase( i==20*incr );
- if( u>LARGEST_INT64 ){
- /* This test and assignment is needed only to suppress UB warnings
- ** from clang and -fsanitize=undefined. This test and assignment make
- ** the code a little larger and slower, and no harm comes from omitting
- ** them, but we must appaise the undefined-behavior pharisees. */
- *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
- }else if( neg ){
- *pNum = -(i64)u;
- }else{
- *pNum = (i64)u;
- }
- rc = 0;
- if( (i==0 && zStart==zNum) /* No digits */
- || nonNum /* UTF16 with high-order bytes non-zero */
- ){
- rc = 1;
- }else if( &zNum[i]<zEnd ){ /* Extra bytes at the end */
- int jj = i;
- do{
- if( !sqlite3Isspace(zNum[jj]) ){
- rc = 1; /* Extra non-space text after the integer */
- break;
- }
- jj += incr;
- }while( &zNum[jj]<zEnd );
- }
- if( i<19*incr ){
- /* Less than 19 digits, so we know that it fits in 64 bits */
- assert( u<=LARGEST_INT64 );
- return rc;
- }else{
- /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
- c = i>19*incr ? 1 : compare2pow63(zNum, incr);
- if( c<0 ){
- /* zNum is less than 9223372036854775808 so it fits */
- assert( u<=LARGEST_INT64 );
- return rc;
- }else{
- *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
- if( c>0 ){
- /* zNum is greater than 9223372036854775808 so it overflows */
- return 2;
- }else{
- /* zNum is exactly 9223372036854775808. Fits if negative. The
- ** special case 2 overflow if positive */
- assert( u-1==LARGEST_INT64 );
- return neg ? rc : 3;
- }
- }
- }
-}
-
-/*
-** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
-** into a 64-bit signed integer. This routine accepts hexadecimal literals,
-** whereas sqlite3Atoi64() does not.
-**
-** Returns:
-**
-** 0 Successful transformation. Fits in a 64-bit signed integer.
-** 1 Excess text after the integer value
-** 2 Integer too large for a 64-bit signed integer or is malformed
-** 3 Special case of 9223372036854775808
-*/
-int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
-#ifndef SQLITE_OMIT_HEX_INTEGER
- if( z[0]=='0'
- && (z[1]=='x' || z[1]=='X')
- ){
- u64 u = 0;
- int i, k;
- for(i=2; z[i]=='0'; i++){}
- for(k=i; sqlite3Isxdigit(z[k]); k++){
- u = u*16 + sqlite3HexToInt(z[k]);
- }
- memcpy(pOut, &u, 8);
- return (z[k]==0 && k-i<=16) ? 0 : 2;
- }else
-#endif /* SQLITE_OMIT_HEX_INTEGER */
- {
- return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
- }
-}
-
-/*
-** If zNum represents an integer that will fit in 32-bits, then set
-** *pValue to that integer and return true. Otherwise return false.
-**
-** This routine accepts both decimal and hexadecimal notation for integers.
-**
-** Any non-numeric characters that following zNum are ignored.
-** This is different from sqlite3Atoi64() which requires the
-** input number to be zero-terminated.
-*/
-int sqlite3GetInt32(const char *zNum, int *pValue){
- sqlite_int64 v = 0;
- int i, c;
- int neg = 0;
- if( zNum[0]=='-' ){
- neg = 1;
- zNum++;
- }else if( zNum[0]=='+' ){
- zNum++;
- }
-#ifndef SQLITE_OMIT_HEX_INTEGER
- else if( zNum[0]=='0'
- && (zNum[1]=='x' || zNum[1]=='X')
- && sqlite3Isxdigit(zNum[2])
- ){
- u32 u = 0;
- zNum += 2;
- while( zNum[0]=='0' ) zNum++;
- for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){
- u = u*16 + sqlite3HexToInt(zNum[i]);
- }
- if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){
- memcpy(pValue, &u, 4);
- return 1;
- }else{
- return 0;
- }
- }
-#endif
- if( !sqlite3Isdigit(zNum[0]) ) return 0;
- while( zNum[0]=='0' ) zNum++;
- for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
- v = v*10 + c;
- }
-
- /* The longest decimal representation of a 32 bit integer is 10 digits:
- **
- ** 1234567890
- ** 2^31 -> 2147483648
- */
- testcase( i==10 );
- if( i>10 ){
- return 0;
- }
- testcase( v-neg==2147483647 );
- if( v-neg>2147483647 ){
- return 0;
- }
- if( neg ){
- v = -v;
- }
- *pValue = (int)v;
- return 1;
-}
-
-/*
-** Return a 32-bit integer value extracted from a string. If the
-** string is not an integer, just return 0.
-*/
-int sqlite3Atoi(const char *z){
- int x = 0;
- if( z ) sqlite3GetInt32(z, &x);
- return x;
-}
-
-/*
-** The variable-length integer encoding is as follows:
-**
-** KEY:
-** A = 0xxxxxxx 7 bits of data and one flag bit
-** B = 1xxxxxxx 7 bits of data and one flag bit
-** C = xxxxxxxx 8 bits of data
-**
-** 7 bits - A
-** 14 bits - BA
-** 21 bits - BBA
-** 28 bits - BBBA
-** 35 bits - BBBBA
-** 42 bits - BBBBBA
-** 49 bits - BBBBBBA
-** 56 bits - BBBBBBBA
-** 64 bits - BBBBBBBBC
-*/
-
-/*
-** Write a 64-bit variable-length integer to memory starting at p[0].
-** The length of data write will be between 1 and 9 bytes. The number
-** of bytes written is returned.
-**
-** A variable-length integer consists of the lower 7 bits of each byte
-** for all bytes that have the 8th bit set and one byte with the 8th
-** bit clear. Except, if we get to the 9th byte, it stores the full
-** 8 bits and is the last byte.
-*/
-static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){
- int i, j, n;
- u8 buf[10];
- if( v & (((u64)0xff000000)<<32) ){
- p[8] = (u8)v;
- v >>= 8;
- for(i=7; i>=0; i--){
- p[i] = (u8)((v & 0x7f) | 0x80);
- v >>= 7;
- }
- return 9;
- }
- n = 0;
- do{
- buf[n++] = (u8)((v & 0x7f) | 0x80);
- v >>= 7;
- }while( v!=0 );
- buf[0] &= 0x7f;
- assert( n<=9 );
- for(i=0, j=n-1; j>=0; j--, i++){
- p[i] = buf[j];
- }
- return n;
-}
-int sqlite3PutVarint(unsigned char *p, u64 v){
- if( v<=0x7f ){
- p[0] = v&0x7f;
- return 1;
- }
- if( v<=0x3fff ){
- p[0] = ((v>>7)&0x7f)|0x80;
- p[1] = v&0x7f;
- return 2;
- }
- return putVarint64(p,v);
-}
-
-/*
-** Bitmasks used by sqlite3GetVarint(). These precomputed constants
-** are defined here rather than simply putting the constant expressions
-** inline in order to work around bugs in the RVT compiler.
-**
-** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
-**
-** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
-*/
-#define SLOT_2_0 0x001fc07f
-#define SLOT_4_2_0 0xf01fc07f
-
-
-/*
-** Read a 64-bit variable-length integer from memory starting at p[0].
-** Return the number of bytes read. The value is stored in *v.
-*/
-u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
- u32 a,b,s;
-
- a = *p;
- /* a: p0 (unmasked) */
- if (!(a&0x80))
- {
- *v = a;
- return 1;
- }
-
- p++;
- b = *p;
- /* b: p1 (unmasked) */
- if (!(b&0x80))
- {
- a &= 0x7f;
- a = a<<7;
- a |= b;
- *v = a;
- return 2;
- }
-
- /* Verify that constants are precomputed correctly */
- assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
- assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<14 | p2 (unmasked) */
- if (!(a&0x80))
- {
- a &= SLOT_2_0;
- b &= 0x7f;
- b = b<<7;
- a |= b;
- *v = a;
- return 3;
- }
-
- /* CSE1 from below */
- a &= SLOT_2_0;
- p++;
- b = b<<14;
- b |= *p;
- /* b: p1<<14 | p3 (unmasked) */
- if (!(b&0x80))
- {
- b &= SLOT_2_0;
- /* moved CSE1 up */
- /* a &= (0x7f<<14)|(0x7f); */
- a = a<<7;
- a |= b;
- *v = a;
- return 4;
- }
-
- /* a: p0<<14 | p2 (masked) */
- /* b: p1<<14 | p3 (unmasked) */
- /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
- /* moved CSE1 up */
- /* a &= (0x7f<<14)|(0x7f); */
- b &= SLOT_2_0;
- s = a;
- /* s: p0<<14 | p2 (masked) */
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<28 | p2<<14 | p4 (unmasked) */
- if (!(a&0x80))
- {
- /* we can skip these cause they were (effectively) done above
- ** while calculating s */
- /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
- /* b &= (0x7f<<14)|(0x7f); */
- b = b<<7;
- a |= b;
- s = s>>18;
- *v = ((u64)s)<<32 | a;
- return 5;
- }
-
- /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
- s = s<<7;
- s |= b;
- /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
-
- p++;
- b = b<<14;
- b |= *p;
- /* b: p1<<28 | p3<<14 | p5 (unmasked) */
- if (!(b&0x80))
- {
- /* we can skip this cause it was (effectively) done above in calc'ing s */
- /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
- a &= SLOT_2_0;
- a = a<<7;
- a |= b;
- s = s>>18;
- *v = ((u64)s)<<32 | a;
- return 6;
- }
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p2<<28 | p4<<14 | p6 (unmasked) */
- if (!(a&0x80))
- {
- a &= SLOT_4_2_0;
- b &= SLOT_2_0;
- b = b<<7;
- a |= b;
- s = s>>11;
- *v = ((u64)s)<<32 | a;
- return 7;
- }
-
- /* CSE2 from below */
- a &= SLOT_2_0;
- p++;
- b = b<<14;
- b |= *p;
- /* b: p3<<28 | p5<<14 | p7 (unmasked) */
- if (!(b&0x80))
- {
- b &= SLOT_4_2_0;
- /* moved CSE2 up */
- /* a &= (0x7f<<14)|(0x7f); */
- a = a<<7;
- a |= b;
- s = s>>4;
- *v = ((u64)s)<<32 | a;
- return 8;
- }
-
- p++;
- a = a<<15;
- a |= *p;
- /* a: p4<<29 | p6<<15 | p8 (unmasked) */
-
- /* moved CSE2 up */
- /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
- b &= SLOT_2_0;
- b = b<<8;
- a |= b;
-
- s = s<<4;
- b = p[-4];
- b &= 0x7f;
- b = b>>3;
- s |= b;
-
- *v = ((u64)s)<<32 | a;
-
- return 9;
-}
-
-/*
-** Read a 32-bit variable-length integer from memory starting at p[0].
-** Return the number of bytes read. The value is stored in *v.
-**
-** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
-** integer, then set *v to 0xffffffff.
-**
-** A MACRO version, getVarint32, is provided which inlines the
-** single-byte case. All code should use the MACRO version as
-** this function assumes the single-byte case has already been handled.
-*/
-u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
- u32 a,b;
-
- /* The 1-byte case. Overwhelmingly the most common. Handled inline
- ** by the getVarin32() macro */
- a = *p;
- /* a: p0 (unmasked) */
-#ifndef getVarint32
- if (!(a&0x80))
- {
- /* Values between 0 and 127 */
- *v = a;
- return 1;
- }
-#endif
-
- /* The 2-byte case */
- p++;
- b = *p;
- /* b: p1 (unmasked) */
- if (!(b&0x80))
- {
- /* Values between 128 and 16383 */
- a &= 0x7f;
- a = a<<7;
- *v = a | b;
- return 2;
- }
-
- /* The 3-byte case */
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<14 | p2 (unmasked) */
- if (!(a&0x80))
- {
- /* Values between 16384 and 2097151 */
- a &= (0x7f<<14)|(0x7f);
- b &= 0x7f;
- b = b<<7;
- *v = a | b;
- return 3;
- }
-
- /* A 32-bit varint is used to store size information in btrees.
- ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
- ** A 3-byte varint is sufficient, for example, to record the size
- ** of a 1048569-byte BLOB or string.
- **
- ** We only unroll the first 1-, 2-, and 3- byte cases. The very
- ** rare larger cases can be handled by the slower 64-bit varint
- ** routine.
- */
-#if 1
- {
- u64 v64;
- u8 n;
-
- p -= 2;
- n = sqlite3GetVarint(p, &v64);
- assert( n>3 && n<=9 );
- if( (v64 & SQLITE_MAX_U32)!=v64 ){
- *v = 0xffffffff;
- }else{
- *v = (u32)v64;
- }
- return n;
- }
-
-#else
- /* For following code (kept for historical record only) shows an
- ** unrolling for the 3- and 4-byte varint cases. This code is
- ** slightly faster, but it is also larger and much harder to test.
- */
- p++;
- b = b<<14;
- b |= *p;
- /* b: p1<<14 | p3 (unmasked) */
- if (!(b&0x80))
- {
- /* Values between 2097152 and 268435455 */
- b &= (0x7f<<14)|(0x7f);
- a &= (0x7f<<14)|(0x7f);
- a = a<<7;
- *v = a | b;
- return 4;
- }
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<28 | p2<<14 | p4 (unmasked) */
- if (!(a&0x80))
- {
- /* Values between 268435456 and 34359738367 */
- a &= SLOT_4_2_0;
- b &= SLOT_4_2_0;
- b = b<<7;
- *v = a | b;
- return 5;
- }
-
- /* We can only reach this point when reading a corrupt database
- ** file. In that case we are not in any hurry. Use the (relatively
- ** slow) general-purpose sqlite3GetVarint() routine to extract the
- ** value. */
- {
- u64 v64;
- u8 n;
-
- p -= 4;
- n = sqlite3GetVarint(p, &v64);
- assert( n>5 && n<=9 );
- *v = (u32)v64;
- return n;
- }
-#endif
-}
-
-/*
-** Return the number of bytes that will be needed to store the given
-** 64-bit integer.
-*/
-int sqlite3VarintLen(u64 v){
- int i;
- for(i=1; (v >>= 7)!=0; i++){ assert( i<10 ); }
- return i;
-}
-
-
-/*
-** Read or write a four-byte big-endian integer value.
-*/
-u32 sqlite3Get4byte(const u8 *p){
-#if SQLITE_BYTEORDER==4321
- u32 x;
- memcpy(&x,p,4);
- return x;
-#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
- u32 x;
- memcpy(&x,p,4);
- return __builtin_bswap32(x);
-#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
- u32 x;
- memcpy(&x,p,4);
- return _byteswap_ulong(x);
-#else
- testcase( p[0]&0x80 );
- return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
-#endif
-}
-void sqlite3Put4byte(unsigned char *p, u32 v){
-#if SQLITE_BYTEORDER==4321
- memcpy(p,&v,4);
-#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
- u32 x = __builtin_bswap32(v);
- memcpy(p,&x,4);
-#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
- u32 x = _byteswap_ulong(v);
- memcpy(p,&x,4);
-#else
- p[0] = (u8)(v>>24);
- p[1] = (u8)(v>>16);
- p[2] = (u8)(v>>8);
- p[3] = (u8)v;
-#endif
-}
-
-
-
-/*
-** Translate a single byte of Hex into an integer.
-** This routine only works if h really is a valid hexadecimal
-** character: 0..9a..fA..F
-*/
-u8 sqlite3HexToInt(int h){
- assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
-#ifdef SQLITE_ASCII
- h += 9*(1&(h>>6));
-#endif
-#ifdef SQLITE_EBCDIC
- h += 9*(1&~(h>>4));
-#endif
- return (u8)(h & 0xf);
-}
-
-#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
-/*
-** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
-** value. Return a pointer to its binary value. Space to hold the
-** binary value has been obtained from malloc and must be freed by
-** the calling routine.
-*/
-void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
- char *zBlob;
- int i;
-
- zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1);
- n--;
- if( zBlob ){
- for(i=0; i<n; i+=2){
- zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
- }
- zBlob[i/2] = 0;
- }
- return zBlob;
-}
-#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
-
-/*
-** Log an error that is an API call on a connection pointer that should
-** not have been used. The "type" of connection pointer is given as the
-** argument. The zType is a word like "NULL" or "closed" or "invalid".
-*/
-static void logBadConnection(const char *zType){
- sqlite3_log(SQLITE_MISUSE,
- "API call with %s database connection pointer",
- zType
- );
-}
-
-/*
-** Check to make sure we have a valid db pointer. This test is not
-** foolproof but it does provide some measure of protection against
-** misuse of the interface such as passing in db pointers that are
-** NULL or which have been previously closed. If this routine returns
-** 1 it means that the db pointer is valid and 0 if it should not be
-** dereferenced for any reason. The calling function should invoke
-** SQLITE_MISUSE immediately.
-**
-** sqlite3SafetyCheckOk() requires that the db pointer be valid for
-** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
-** open properly and is not fit for general use but which can be
-** used as an argument to sqlite3_errmsg() or sqlite3_close().
-*/
-int sqlite3SafetyCheckOk(sqlite3 *db){
- u32 magic;
- if( db==0 ){
- logBadConnection("NULL");
- return 0;
- }
- magic = db->magic;
- if( magic!=SQLITE_MAGIC_OPEN ){
- if( sqlite3SafetyCheckSickOrOk(db) ){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- logBadConnection("unopened");
- }
- return 0;
- }else{
- return 1;
- }
-}
-int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
- u32 magic;
- magic = db->magic;
- if( magic!=SQLITE_MAGIC_SICK &&
- magic!=SQLITE_MAGIC_OPEN &&
- magic!=SQLITE_MAGIC_BUSY ){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- logBadConnection("invalid");
- return 0;
- }else{
- return 1;
- }
-}
-
-/*
-** Attempt to add, substract, or multiply the 64-bit signed value iB against
-** the other 64-bit signed integer at *pA and store the result in *pA.
-** Return 0 on success. Or if the operation would have resulted in an
-** overflow, leave *pA unchanged and return 1.
-*/
-int sqlite3AddInt64(i64 *pA, i64 iB){
-#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
- return __builtin_add_overflow(*pA, iB, pA);
-#else
- i64 iA = *pA;
- testcase( iA==0 ); testcase( iA==1 );
- testcase( iB==-1 ); testcase( iB==0 );
- if( iB>=0 ){
- testcase( iA>0 && LARGEST_INT64 - iA == iB );
- testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
- if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
- }else{
- testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
- testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
- if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
- }
- *pA += iB;
- return 0;
-#endif
-}
-int sqlite3SubInt64(i64 *pA, i64 iB){
-#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
- return __builtin_sub_overflow(*pA, iB, pA);
-#else
- testcase( iB==SMALLEST_INT64+1 );
- if( iB==SMALLEST_INT64 ){
- testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
- if( (*pA)>=0 ) return 1;
- *pA -= iB;
- return 0;
- }else{
- return sqlite3AddInt64(pA, -iB);
- }
-#endif
-}
-int sqlite3MulInt64(i64 *pA, i64 iB){
-#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
- return __builtin_mul_overflow(*pA, iB, pA);
-#else
- i64 iA = *pA;
- if( iB>0 ){
- if( iA>LARGEST_INT64/iB ) return 1;
- if( iA<SMALLEST_INT64/iB ) return 1;
- }else if( iB<0 ){
- if( iA>0 ){
- if( iB<SMALLEST_INT64/iA ) return 1;
- }else if( iA<0 ){
- if( iB==SMALLEST_INT64 ) return 1;
- if( iA==SMALLEST_INT64 ) return 1;
- if( -iA>LARGEST_INT64/-iB ) return 1;
- }
- }
- *pA = iA*iB;
- return 0;
-#endif
-}
-
-/*
-** Compute the absolute value of a 32-bit signed integer, of possible. Or
-** if the integer has a value of -2147483648, return +2147483647
-*/
-int sqlite3AbsInt32(int x){
- if( x>=0 ) return x;
- if( x==(int)0x80000000 ) return 0x7fffffff;
- return -x;
-}
-
-#ifdef SQLITE_ENABLE_8_3_NAMES
-/*
-** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
-** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
-** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
-** three characters, then shorten the suffix on z[] to be the last three
-** characters of the original suffix.
-**
-** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
-** do the suffix shortening regardless of URI parameter.
-**
-** Examples:
-**
-** test.db-journal => test.nal
-** test.db-wal => test.wal
-** test.db-shm => test.shm
-** test.db-mj7f3319fa => test.9fa
-*/
-void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
-#if SQLITE_ENABLE_8_3_NAMES<2
- if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
-#endif
- {
- int i, sz;
- sz = sqlite3Strlen30(z);
- for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
- if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
- }
-}
-#endif
-
-/*
-** Find (an approximate) sum of two LogEst values. This computation is
-** not a simple "+" operator because LogEst is stored as a logarithmic
-** value.
-**
-*/
-LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
- static const unsigned char x[] = {
- 10, 10, /* 0,1 */
- 9, 9, /* 2,3 */
- 8, 8, /* 4,5 */
- 7, 7, 7, /* 6,7,8 */
- 6, 6, 6, /* 9,10,11 */
- 5, 5, 5, /* 12-14 */
- 4, 4, 4, 4, /* 15-18 */
- 3, 3, 3, 3, 3, 3, /* 19-24 */
- 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
- };
- if( a>=b ){
- if( a>b+49 ) return a;
- if( a>b+31 ) return a+1;
- return a+x[a-b];
- }else{
- if( b>a+49 ) return b;
- if( b>a+31 ) return b+1;
- return b+x[b-a];
- }
-}
-
-/*
-** Convert an integer into a LogEst. In other words, compute an
-** approximation for 10*log2(x).
-*/
-LogEst sqlite3LogEst(u64 x){
- static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
- LogEst y = 40;
- if( x<8 ){
- if( x<2 ) return 0;
- while( x<8 ){ y -= 10; x <<= 1; }
- }else{
-#if GCC_VERSION>=5004000
- int i = 60 - __builtin_clzll(x);
- y += i*10;
- x >>= i;
-#else
- while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
- while( x>15 ){ y += 10; x >>= 1; }
-#endif
- }
- return a[x&7] + y - 10;
-}
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*
-** Convert a double into a LogEst
-** In other words, compute an approximation for 10*log2(x).
-*/
-LogEst sqlite3LogEstFromDouble(double x){
- u64 a;
- LogEst e;
- assert( sizeof(x)==8 && sizeof(a)==8 );
- if( x<=1 ) return 0;
- if( x<=2000000000 ) return sqlite3LogEst((u64)x);
- memcpy(&a, &x, 8);
- e = (a>>52) - 1022;
- return e*10;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
- defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
-/*
-** Convert a LogEst into an integer.
-**
-** Note that this routine is only used when one or more of various
-** non-standard compile-time options is enabled.
-*/
-u64 sqlite3LogEstToInt(LogEst x){
- u64 n;
- n = x%10;
- x /= 10;
- if( n>=5 ) n -= 2;
- else if( n>=1 ) n -= 1;
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
- if( x>60 ) return (u64)LARGEST_INT64;
-#else
- /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input
- ** possible to this routine is 310, resulting in a maximum x of 31 */
- assert( x<=60 );
-#endif
- return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
-}
-#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */
-
-/*
-** Add a new name/number pair to a VList. This might require that the
-** VList object be reallocated, so return the new VList. If an OOM
-** error occurs, the original VList returned and the
-** db->mallocFailed flag is set.
-**
-** A VList is really just an array of integers. To destroy a VList,
-** simply pass it to sqlite3DbFree().
-**
-** The first integer is the number of integers allocated for the whole
-** VList. The second integer is the number of integers actually used.
-** Each name/number pair is encoded by subsequent groups of 3 or more
-** integers.
-**
-** Each name/number pair starts with two integers which are the numeric
-** value for the pair and the size of the name/number pair, respectively.
-** The text name overlays one or more following integers. The text name
-** is always zero-terminated.
-**
-** Conceptually:
-**
-** struct VList {
-** int nAlloc; // Number of allocated slots
-** int nUsed; // Number of used slots
-** struct VListEntry {
-** int iValue; // Value for this entry
-** int nSlot; // Slots used by this entry
-** // ... variable name goes here
-** } a[0];
-** }
-**
-** During code generation, pointers to the variable names within the
-** VList are taken. When that happens, nAlloc is set to zero as an
-** indication that the VList may never again be enlarged, since the
-** accompanying realloc() would invalidate the pointers.
-*/
-VList *sqlite3VListAdd(
- sqlite3 *db, /* The database connection used for malloc() */
- VList *pIn, /* The input VList. Might be NULL */
- const char *zName, /* Name of symbol to add */
- int nName, /* Bytes of text in zName */
- int iVal /* Value to associate with zName */
-){
- int nInt; /* number of sizeof(int) objects needed for zName */
- char *z; /* Pointer to where zName will be stored */
- int i; /* Index in pIn[] where zName is stored */
-
- nInt = nName/4 + 3;
- assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */
- if( pIn==0 || pIn[1]+nInt > pIn[0] ){
- /* Enlarge the allocation */
- int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt;
- VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int));
- if( pOut==0 ) return pIn;
- if( pIn==0 ) pOut[1] = 2;
- pIn = pOut;
- pIn[0] = nAlloc;
- }
- i = pIn[1];
- pIn[i] = iVal;
- pIn[i+1] = nInt;
- z = (char*)&pIn[i+2];
- pIn[1] = i+nInt;
- assert( pIn[1]<=pIn[0] );
- memcpy(z, zName, nName);
- z[nName] = 0;
- return pIn;
-}
-
-/*
-** Return a pointer to the name of a variable in the given VList that
-** has the value iVal. Or return a NULL if there is no such variable in
-** the list
-*/
-const char *sqlite3VListNumToName(VList *pIn, int iVal){
- int i, mx;
- if( pIn==0 ) return 0;
- mx = pIn[1];
- i = 2;
- do{
- if( pIn[i]==iVal ) return (char*)&pIn[i+2];
- i += pIn[i+1];
- }while( i<mx );
- return 0;
-}
-
-/*
-** Return the number of the variable named zName, if it is in VList.
-** or return 0 if there is no such variable.
-*/
-int sqlite3VListNameToNum(VList *pIn, const char *zName, int nName){
- int i, mx;
- if( pIn==0 ) return 0;
- mx = pIn[1];
- i = 2;
- do{
- const char *z = (const char*)&pIn[i+2];
- if( strncmp(z,zName,nName)==0 && z[nName]==0 ) return pIn[i];
- i += pIn[i+1];
- }while( i<mx );
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vacuum.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vacuum.c
deleted file mode 100644
index fe295147c56..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vacuum.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
-** 2003 April 6
-**
-** 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 contains code used to implement the VACUUM command.
-**
-** Most of the code in this file may be omitted by defining the
-** SQLITE_OMIT_VACUUM macro.
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
-
-/*
-** Execute zSql on database db.
-**
-** If zSql returns rows, then each row will have exactly one
-** column. (This will only happen if zSql begins with "SELECT".)
-** Take each row of result and call execSql() again recursively.
-**
-** The execSqlF() routine does the same thing, except it accepts
-** a format string as its third argument
-*/
-static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
- sqlite3_stmt *pStmt;
- int rc;
-
- /* printf("SQL: [%s]\n", zSql); fflush(stdout); */
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ) return rc;
- while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
- const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0);
- assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 );
- /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX,
- ** or INSERT. Historically there have been attacks that first
- ** corrupt the sqlite_master.sql field with other kinds of statements
- ** then run VACUUM to get those statements to execute at inappropriate
- ** times. */
- if( zSubSql
- && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0)
- ){
- rc = execSql(db, pzErrMsg, zSubSql);
- if( rc!=SQLITE_OK ) break;
- }
- }
- assert( rc!=SQLITE_ROW );
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- if( rc ){
- sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
- }
- (void)sqlite3_finalize(pStmt);
- return rc;
-}
-static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){
- char *z;
- va_list ap;
- int rc;
- va_start(ap, zSql);
- z = sqlite3VMPrintf(db, zSql, ap);
- va_end(ap);
- if( z==0 ) return SQLITE_NOMEM;
- rc = execSql(db, pzErrMsg, z);
- sqlite3DbFree(db, z);
- return rc;
-}
-
-/*
-** The VACUUM command is used to clean up the database,
-** collapse free space, etc. It is modelled after the VACUUM command
-** in PostgreSQL. The VACUUM command works as follows:
-**
-** (1) Create a new transient database file
-** (2) Copy all content from the database being vacuumed into
-** the new transient database file
-** (3) Copy content from the transient database back into the
-** original database.
-**
-** The transient database requires temporary disk space approximately
-** equal to the size of the original database. The copy operation of
-** step (3) requires additional temporary disk space approximately equal
-** to the size of the original database for the rollback journal.
-** Hence, temporary disk space that is approximately 2x the size of the
-** original database is required. Every page of the database is written
-** approximately 3 times: Once for step (2) and twice for step (3).
-** Two writes per page are required in step (3) because the original
-** database content must be written into the rollback journal prior to
-** overwriting the database with the vacuumed content.
-**
-** Only 1x temporary space and only 1x writes would be required if
-** the copy of step (3) were replaced by deleting the original database
-** and renaming the transient database as the original. But that will
-** not work if other processes are attached to the original database.
-** And a power loss in between deleting the original and renaming the
-** transient would cause the database file to appear to be deleted
-** following reboot.
-*/
-void sqlite3Vacuum(Parse *pParse, Token *pNm){
- Vdbe *v = sqlite3GetVdbe(pParse);
- int iDb = 0;
- if( v==0 ) return;
- if( pNm ){
-#ifndef SQLITE_BUG_COMPATIBLE_20160819
- /* Default behavior: Report an error if the argument to VACUUM is
- ** not recognized */
- iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm);
- if( iDb<0 ) return;
-#else
- /* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
- ** to VACUUM are silently ignored. This is a back-out of a bug fix that
- ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270).
- ** The buggy behavior is required for binary compatibility with some
- ** legacy applications. */
- iDb = sqlite3FindDb(pParse->db, pNm);
- if( iDb<0 ) iDb = 0;
-#endif
- }
- if( iDb!=1 ){
- sqlite3VdbeAddOp1(v, OP_Vacuum, iDb);
- sqlite3VdbeUsesBtree(v, iDb);
- }
- return;
-}
-
-/*
-** This routine implements the OP_Vacuum opcode of the VDBE.
-*/
-int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
- int rc = SQLITE_OK; /* Return code from service routines */
- Btree *pMain; /* The database being vacuumed */
- Btree *pTemp; /* The temporary database we vacuum into */
- u16 saved_mDbFlags; /* Saved value of db->mDbFlags */
- u32 saved_flags; /* Saved value of db->flags */
- int saved_nChange; /* Saved value of db->nChange */
- int saved_nTotalChange; /* Saved value of db->nTotalChange */
- u8 saved_mTrace; /* Saved trace settings */
- Db *pDb = 0; /* Database to detach at end of vacuum */
- int isMemDb; /* True if vacuuming a :memory: database */
- int nRes; /* Bytes of reserved space at the end of each page */
- int nDb; /* Number of attached databases */
- const char *zDbMain; /* Schema name of database to vacuum */
-
- if( !db->autoCommit ){
- sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
- return SQLITE_ERROR;
- }
- if( db->nVdbeActive>1 ){
- sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
- return SQLITE_ERROR;
- }
-
- /* Save the current value of the database flags so that it can be
- ** restored before returning. Then set the writable-schema flag, and
- ** disable CHECK and foreign key constraints. */
- saved_flags = db->flags;
- saved_mDbFlags = db->mDbFlags;
- saved_nChange = db->nChange;
- saved_nTotalChange = db->nTotalChange;
- saved_mTrace = db->mTrace;
- db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
- db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
- db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows);
- db->mTrace = 0;
-
- zDbMain = db->aDb[iDb].zDbSName;
- pMain = db->aDb[iDb].pBt;
- isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
-
- /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
- ** can be set to 'off' for this file, as it is not recovered if a crash
- ** occurs anyway. The integrity of the database is maintained by a
- ** (possibly synchronous) transaction opened on the main database before
- ** sqlite3BtreeCopyFile() is called.
- **
- ** An optimisation would be to use a non-journaled pager.
- ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
- ** that actually made the VACUUM run slower. Very little journalling
- ** actually occurs when doing a vacuum since the vacuum_db is initially
- ** empty. Only the journal header is written. Apparently it takes more
- ** time to parse and run the PRAGMA to turn journalling off than it does
- ** to write the journal header file.
- */
- nDb = db->nDb;
- rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db");
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- assert( (db->nDb-1)==nDb );
- pDb = &db->aDb[nDb];
- assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
- pTemp = pDb->pBt;
-
- /* The call to execSql() to attach the temp database has left the file
- ** locked (as there was more than one active statement when the transaction
- ** to read the schema was concluded. Unlock it here so that this doesn't
- ** cause problems for the call to BtreeSetPageSize() below. */
- sqlite3BtreeCommit(pTemp);
-
- nRes = sqlite3BtreeGetOptimalReserve(pMain);
-
- /* A VACUUM cannot change the pagesize of an encrypted database. */
-#ifdef SQLITE_HAS_CODEC
- if( db->nextPagesize ){
- extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
- int nKey;
- char *zKey;
- sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey);
- if( nKey ) db->nextPagesize = 0;
- }
-#endif
-
- sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
- sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
- sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL);
-
- /* Begin a transaction and take an exclusive lock on the main database
- ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
- ** to ensure that we do not try to change the page-size on a WAL database.
- */
- rc = execSql(db, pzErrMsg, "BEGIN");
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = sqlite3BtreeBeginTrans(pMain, 2);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
-
- /* Do not attempt to change the page size for a WAL database */
- if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
- ==PAGER_JOURNALMODE_WAL ){
- db->nextPagesize = 0;
- }
-
- if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
- || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
- || NEVER(db->mallocFailed)
- ){
- rc = SQLITE_NOMEM_BKPT;
- goto end_of_vacuum;
- }
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
- sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac :
- sqlite3BtreeGetAutoVacuum(pMain));
-#endif
-
- /* Query the schema of the main database. Create a mirror schema
- ** in the temporary database.
- */
- db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */
- rc = execSqlF(db, pzErrMsg,
- "SELECT sql FROM \"%w\".sqlite_master"
- " WHERE type='table'AND name<>'sqlite_sequence'"
- " AND coalesce(rootpage,1)>0",
- zDbMain
- );
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = execSqlF(db, pzErrMsg,
- "SELECT sql FROM \"%w\".sqlite_master"
- " WHERE type='index'",
- zDbMain
- );
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- db->init.iDb = 0;
-
- /* Loop through the tables in the main database. For each, do
- ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
- ** the contents to the temporary database.
- */
- rc = execSqlF(db, pzErrMsg,
- "SELECT'INSERT INTO vacuum_db.'||quote(name)"
- "||' SELECT*FROM\"%w\".'||quote(name)"
- "FROM vacuum_db.sqlite_master "
- "WHERE type='table'AND coalesce(rootpage,1)>0",
- zDbMain
- );
- assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
- db->mDbFlags &= ~DBFLAG_Vacuum;
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
-
- /* Copy the triggers, views, and virtual tables from the main database
- ** over to the temporary database. None of these objects has any
- ** associated storage, so all we have to do is copy their entries
- ** from the SQLITE_MASTER table.
- */
- rc = execSqlF(db, pzErrMsg,
- "INSERT INTO vacuum_db.sqlite_master"
- " SELECT*FROM \"%w\".sqlite_master"
- " WHERE type IN('view','trigger')"
- " OR(type='table'AND rootpage=0)",
- zDbMain
- );
- if( rc ) goto end_of_vacuum;
-
- /* At this point, there is a write transaction open on both the
- ** vacuum database and the main database. Assuming no error occurs,
- ** both transactions are closed by this block - the main database
- ** transaction by sqlite3BtreeCopyFile() and the other by an explicit
- ** call to sqlite3BtreeCommit().
- */
- {
- u32 meta;
- int i;
-
- /* This array determines which meta meta values are preserved in the
- ** vacuum. Even entries are the meta value number and odd entries
- ** are an increment to apply to the meta value after the vacuum.
- ** The increment is used to increase the schema cookie so that other
- ** connections to the same database will know to reread the schema.
- */
- static const unsigned char aCopy[] = {
- BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */
- BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */
- BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */
- BTREE_USER_VERSION, 0, /* Preserve the user version */
- BTREE_APPLICATION_ID, 0, /* Preserve the application id */
- };
-
- assert( 1==sqlite3BtreeIsInTrans(pTemp) );
- assert( 1==sqlite3BtreeIsInTrans(pMain) );
-
- /* Copy Btree meta values */
- for(i=0; i<ArraySize(aCopy); i+=2){
- /* GetMeta() and UpdateMeta() cannot fail in this context because
- ** we already have page 1 loaded into cache and marked dirty. */
- sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
- rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
- if( NEVER(rc!=SQLITE_OK) ) goto end_of_vacuum;
- }
-
- rc = sqlite3BtreeCopyFile(pMain, pTemp);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = sqlite3BtreeCommit(pTemp);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
-#endif
- }
-
- assert( rc==SQLITE_OK );
- rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
-
-end_of_vacuum:
- /* Restore the original value of db->flags */
- db->init.iDb = 0;
- db->mDbFlags = saved_mDbFlags;
- db->flags = saved_flags;
- db->nChange = saved_nChange;
- db->nTotalChange = saved_nTotalChange;
- db->mTrace = saved_mTrace;
- sqlite3BtreeSetPageSize(pMain, -1, -1, 1);
-
- /* Currently there is an SQL level transaction open on the vacuum
- ** database. No locks are held on any other files (since the main file
- ** was committed at the btree level). So it safe to end the transaction
- ** by manually setting the autoCommit flag to true and detaching the
- ** vacuum database. The vacuum_db journal file is deleted when the pager
- ** is closed by the DETACH.
- */
- db->autoCommit = 1;
-
- if( pDb ){
- sqlite3BtreeClose(pDb->pBt);
- pDb->pBt = 0;
- pDb->pSchema = 0;
- }
-
- /* This both clears the schemas and reduces the size of the db->aDb[]
- ** array. */
- sqlite3ResetAllSchemasOfConnection(db);
-
- return rc;
-}
-
-#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbe.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbe.c
deleted file mode 100644
index cab69b56b4c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbe.c
+++ /dev/null
@@ -1,7375 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** The code in this file implements the function that runs the
-** bytecode of a prepared statement.
-**
-** Various scripts scan this source file in order to generate HTML
-** documentation, headers files, or other derived files. The formatting
-** of the code in this file is, therefore, important. See other comments
-** in this file for details. If in doubt, do not deviate from existing
-** commenting and indentation practices when changing or adding code.
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-/*
-** Invoke this macro on memory cells just prior to changing the
-** value of the cell. This macro verifies that shallow copies are
-** not misused. A shallow copy of a string or blob just copies a
-** pointer to the string or blob, not the content. If the original
-** is changed while the copy is still in use, the string or blob might
-** be changed out from under the copy. This macro verifies that nothing
-** like that ever happens.
-*/
-#ifdef SQLITE_DEBUG
-# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
-#else
-# define memAboutToChange(P,M)
-#endif
-
-/*
-** The following global variable is incremented every time a cursor
-** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
-** procedures use this information to make sure that indices are
-** working correctly. This variable has no function other than to
-** help verify the correct operation of the library.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_search_count = 0;
-#endif
-
-/*
-** When this global variable is positive, it gets decremented once before
-** each instruction in the VDBE. When it reaches zero, the u1.isInterrupted
-** field of the sqlite3 structure is set in order to simulate an interrupt.
-**
-** This facility is used for testing purposes only. It does not function
-** in an ordinary build.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_interrupt_count = 0;
-#endif
-
-/*
-** The next global variable is incremented each type the OP_Sort opcode
-** is executed. The test procedures use this information to make sure that
-** sorting is occurring or not occurring at appropriate times. This variable
-** has no function other than to help verify the correct operation of the
-** library.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_sort_count = 0;
-#endif
-
-/*
-** The next global variable records the size of the largest MEM_Blob
-** or MEM_Str that has been used by a VDBE opcode. The test procedures
-** use this information to make sure that the zero-blob functionality
-** is working correctly. This variable has no function other than to
-** help verify the correct operation of the library.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_max_blobsize = 0;
-static void updateMaxBlobsize(Mem *p){
- if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){
- sqlite3_max_blobsize = p->n;
- }
-}
-#endif
-
-/*
-** This macro evaluates to true if either the update hook or the preupdate
-** hook are enabled for database connect DB.
-*/
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-# define HAS_UPDATE_HOOK(DB) ((DB)->xPreUpdateCallback||(DB)->xUpdateCallback)
-#else
-# define HAS_UPDATE_HOOK(DB) ((DB)->xUpdateCallback)
-#endif
-
-/*
-** The next global variable is incremented each time the OP_Found opcode
-** is executed. This is used to test whether or not the foreign key
-** operation implemented using OP_FkIsZero is working. This variable
-** has no function other than to help verify the correct operation of the
-** library.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_found_count = 0;
-#endif
-
-/*
-** Test a register to see if it exceeds the current maximum blob size.
-** If it does, record the new maximum blob size.
-*/
-#if defined(SQLITE_TEST) && !defined(SQLITE_UNTESTABLE)
-# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P)
-#else
-# define UPDATE_MAX_BLOBSIZE(P)
-#endif
-
-/*
-** Invoke the VDBE coverage callback, if that callback is defined. This
-** feature is used for test suite validation only and does not appear an
-** production builds.
-**
-** M is an integer, 2 or 3, that indices how many different ways the
-** branch can go. It is usually 2. "I" is the direction the branch
-** goes. 0 means falls through. 1 means branch is taken. 2 means the
-** second alternative branch is taken.
-**
-** iSrcLine is the source code line (from the __LINE__ macro) that
-** generated the VDBE instruction. This instrumentation assumes that all
-** source code is in a single file (the amalgamation). Special values 1
-** and 2 for the iSrcLine parameter mean that this particular branch is
-** always taken or never taken, respectively.
-*/
-#if !defined(SQLITE_VDBE_COVERAGE)
-# define VdbeBranchTaken(I,M)
-#else
-# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
- static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){
- if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){
- M = iSrcLine;
- /* Assert the truth of VdbeCoverageAlwaysTaken() and
- ** VdbeCoverageNeverTaken() */
- assert( (M & I)==I );
- }else{
- if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
- sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
- iSrcLine,I,M);
- }
- }
-#endif
-
-/*
-** Convert the given register into a string if it isn't one
-** already. Return non-zero if a malloc() fails.
-*/
-#define Stringify(P, enc) \
- if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \
- { goto no_mem; }
-
-/*
-** An ephemeral string value (signified by the MEM_Ephem flag) contains
-** a pointer to a dynamically allocated string where some other entity
-** is responsible for deallocating that string. Because the register
-** does not control the string, it might be deleted without the register
-** knowing it.
-**
-** This routine converts an ephemeral string into a dynamically allocated
-** string that the register itself controls. In other words, it
-** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
-*/
-#define Deephemeralize(P) \
- if( ((P)->flags&MEM_Ephem)!=0 \
- && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
-
-/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
-#define isSorter(x) ((x)->eCurType==CURTYPE_SORTER)
-
-/*
-** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
-** if we run out of memory.
-*/
-static VdbeCursor *allocateCursor(
- Vdbe *p, /* The virtual machine */
- int iCur, /* Index of the new VdbeCursor */
- int nField, /* Number of fields in the table or index */
- int iDb, /* Database the cursor belongs to, or -1 */
- u8 eCurType /* Type of the new cursor */
-){
- /* Find the memory cell that will be used to store the blob of memory
- ** required for this VdbeCursor structure. It is convenient to use a
- ** vdbe memory cell to manage the memory allocation required for a
- ** VdbeCursor structure for the following reasons:
- **
- ** * Sometimes cursor numbers are used for a couple of different
- ** purposes in a vdbe program. The different uses might require
- ** different sized allocations. Memory cells provide growable
- ** allocations.
- **
- ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can
- ** be freed lazily via the sqlite3_release_memory() API. This
- ** minimizes the number of malloc calls made by the system.
- **
- ** The memory cell for cursor 0 is aMem[0]. The rest are allocated from
- ** the top of the register space. Cursor 1 is at Mem[p->nMem-1].
- ** Cursor 2 is at Mem[p->nMem-2]. And so forth.
- */
- Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;
-
- int nByte;
- VdbeCursor *pCx = 0;
- nByte =
- ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
- (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
-
- assert( iCur>=0 && iCur<p->nCursor );
- if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
- sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
- p->apCsr[iCur] = 0;
- }
- if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
- p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
- pCx->eCurType = eCurType;
- pCx->iDb = iDb;
- pCx->nField = nField;
- pCx->aOffset = &pCx->aType[nField];
- if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
- sqlite3BtreeCursorZero(pCx->uc.pCursor);
- }
- }
- return pCx;
-}
-
-/*
-** Try to convert a value into a numeric representation if we can
-** do so without loss of information. In other words, if the string
-** looks like a number, convert it into a number. If it does not
-** look like a number, leave it alone.
-**
-** If the bTryForInt flag is true, then extra effort is made to give
-** an integer representation. Strings that look like floating point
-** values but which have no fractional component (example: '48.00')
-** will have a MEM_Int representation when bTryForInt is true.
-**
-** If bTryForInt is false, then if the input string contains a decimal
-** point or exponential notation, the result is only MEM_Real, even
-** if there is an exact integer representation of the quantity.
-*/
-static void applyNumericAffinity(Mem *pRec, int bTryForInt){
- double rValue;
- i64 iValue;
- u8 enc = pRec->enc;
- assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str );
- if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
- if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
- pRec->u.i = iValue;
- pRec->flags |= MEM_Int;
- }else{
- pRec->u.r = rValue;
- pRec->flags |= MEM_Real;
- if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec);
- }
- /* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the
- ** string representation after computing a numeric equivalent, because the
- ** string representation might not be the canonical representation for the
- ** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */
- pRec->flags &= ~MEM_Str;
-}
-
-/*
-** Processing is determine by the affinity parameter:
-**
-** SQLITE_AFF_INTEGER:
-** SQLITE_AFF_REAL:
-** SQLITE_AFF_NUMERIC:
-** Try to convert pRec to an integer representation or a
-** floating-point representation if an integer representation
-** is not possible. Note that the integer representation is
-** always preferred, even if the affinity is REAL, because
-** an integer representation is more space efficient on disk.
-**
-** SQLITE_AFF_TEXT:
-** Convert pRec to a text representation.
-**
-** SQLITE_AFF_BLOB:
-** No-op. pRec is unchanged.
-*/
-static void applyAffinity(
- Mem *pRec, /* The value to apply affinity to */
- char affinity, /* The affinity to be applied */
- u8 enc /* Use this text encoding */
-){
- if( affinity>=SQLITE_AFF_NUMERIC ){
- assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
- || affinity==SQLITE_AFF_NUMERIC );
- if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/
- if( (pRec->flags & MEM_Real)==0 ){
- if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1);
- }else{
- sqlite3VdbeIntegerAffinity(pRec);
- }
- }
- }else if( affinity==SQLITE_AFF_TEXT ){
- /* Only attempt the conversion to TEXT if there is an integer or real
- ** representation (blob and NULL do not get converted) but no string
- ** representation. It would be harmless to repeat the conversion if
- ** there is already a string rep, but it is pointless to waste those
- ** CPU cycles. */
- if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/
- if( (pRec->flags&(MEM_Real|MEM_Int)) ){
- sqlite3VdbeMemStringify(pRec, enc, 1);
- }
- }
- pRec->flags &= ~(MEM_Real|MEM_Int);
- }
-}
-
-/*
-** Try to convert the type of a function argument or a result column
-** into a numeric representation. Use either INTEGER or REAL whichever
-** is appropriate. But only do the conversion if it is possible without
-** loss of information and return the revised type of the argument.
-*/
-int sqlite3_value_numeric_type(sqlite3_value *pVal){
- int eType = sqlite3_value_type(pVal);
- if( eType==SQLITE_TEXT ){
- Mem *pMem = (Mem*)pVal;
- applyNumericAffinity(pMem, 0);
- eType = sqlite3_value_type(pVal);
- }
- return eType;
-}
-
-/*
-** Exported version of applyAffinity(). This one works on sqlite3_value*,
-** not the internal Mem* type.
-*/
-void sqlite3ValueApplyAffinity(
- sqlite3_value *pVal,
- u8 affinity,
- u8 enc
-){
- applyAffinity((Mem *)pVal, affinity, enc);
-}
-
-/*
-** pMem currently only holds a string type (or maybe a BLOB that we can
-** interpret as a string if we want to). Compute its corresponding
-** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields
-** accordingly.
-*/
-static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
- assert( (pMem->flags & (MEM_Int|MEM_Real))==0 );
- assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
- if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
- return 0;
- }
- if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){
- return MEM_Int;
- }
- return MEM_Real;
-}
-
-/*
-** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or
-** none.
-**
-** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
-** But it does set pMem->u.r and pMem->u.i appropriately.
-*/
-static u16 numericType(Mem *pMem){
- if( pMem->flags & (MEM_Int|MEM_Real) ){
- return pMem->flags & (MEM_Int|MEM_Real);
- }
- if( pMem->flags & (MEM_Str|MEM_Blob) ){
- return computeNumericType(pMem);
- }
- return 0;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** Write a nice string representation of the contents of cell pMem
-** into buffer zBuf, length nBuf.
-*/
-void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
- char *zCsr = zBuf;
- int f = pMem->flags;
-
- static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"};
-
- if( f&MEM_Blob ){
- int i;
- char c;
- if( f & MEM_Dyn ){
- c = 'z';
- assert( (f & (MEM_Static|MEM_Ephem))==0 );
- }else if( f & MEM_Static ){
- c = 't';
- assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
- }else if( f & MEM_Ephem ){
- c = 'e';
- assert( (f & (MEM_Static|MEM_Dyn))==0 );
- }else{
- c = 's';
- }
- *(zCsr++) = c;
- sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
- zCsr += sqlite3Strlen30(zCsr);
- for(i=0; i<16 && i<pMem->n; i++){
- sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
- zCsr += sqlite3Strlen30(zCsr);
- }
- for(i=0; i<16 && i<pMem->n; i++){
- char z = pMem->z[i];
- if( z<32 || z>126 ) *zCsr++ = '.';
- else *zCsr++ = z;
- }
- *(zCsr++) = ']';
- if( f & MEM_Zero ){
- sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
- zCsr += sqlite3Strlen30(zCsr);
- }
- *zCsr = '\0';
- }else if( f & MEM_Str ){
- int j, k;
- zBuf[0] = ' ';
- if( f & MEM_Dyn ){
- zBuf[1] = 'z';
- assert( (f & (MEM_Static|MEM_Ephem))==0 );
- }else if( f & MEM_Static ){
- zBuf[1] = 't';
- assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
- }else if( f & MEM_Ephem ){
- zBuf[1] = 'e';
- assert( (f & (MEM_Static|MEM_Dyn))==0 );
- }else{
- zBuf[1] = 's';
- }
- k = 2;
- sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
- k += sqlite3Strlen30(&zBuf[k]);
- zBuf[k++] = '[';
- for(j=0; j<15 && j<pMem->n; j++){
- u8 c = pMem->z[j];
- if( c>=0x20 && c<0x7f ){
- zBuf[k++] = c;
- }else{
- zBuf[k++] = '.';
- }
- }
- zBuf[k++] = ']';
- sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);
- k += sqlite3Strlen30(&zBuf[k]);
- zBuf[k++] = 0;
- }
-}
-#endif
-
-#ifdef SQLITE_DEBUG
-/*
-** Print the value of a register for tracing purposes:
-*/
-static void memTracePrint(Mem *p){
- if( p->flags & MEM_Undefined ){
- printf(" undefined");
- }else if( p->flags & MEM_Null ){
- printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL");
- }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
- printf(" si:%lld", p->u.i);
- }else if( p->flags & MEM_Int ){
- printf(" i:%lld", p->u.i);
-#ifndef SQLITE_OMIT_FLOATING_POINT
- }else if( p->flags & MEM_Real ){
- printf(" r:%g", p->u.r);
-#endif
- }else if( p->flags & MEM_RowSet ){
- printf(" (rowset)");
- }else{
- char zBuf[200];
- sqlite3VdbeMemPrettyPrint(p, zBuf);
- printf(" %s", zBuf);
- }
- if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype);
-}
-static void registerTrace(int iReg, Mem *p){
- printf("REG[%d] = ", iReg);
- memTracePrint(p);
- printf("\n");
- sqlite3VdbeCheckMemInvariants(p);
-}
-#endif
-
-#ifdef SQLITE_DEBUG
-# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
-#else
-# define REGISTER_TRACE(R,M)
-#endif
-
-
-#ifdef VDBE_PROFILE
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-#include "hwtime.h"
-
-#endif
-
-#ifndef NDEBUG
-/*
-** This function is only called from within an assert() expression. It
-** checks that the sqlite3.nTransaction variable is correctly set to
-** the number of non-transaction savepoints currently in the
-** linked list starting at sqlite3.pSavepoint.
-**
-** Usage:
-**
-** assert( checkSavepointCount(db) );
-*/
-static int checkSavepointCount(sqlite3 *db){
- int n = 0;
- Savepoint *p;
- for(p=db->pSavepoint; p; p=p->pNext) n++;
- assert( n==(db->nSavepoint + db->isTransactionSavepoint) );
- return 1;
-}
-#endif
-
-/*
-** Return the register of pOp->p2 after first preparing it to be
-** overwritten with an integer value.
-*/
-static SQLITE_NOINLINE Mem *out2PrereleaseWithClear(Mem *pOut){
- sqlite3VdbeMemSetNull(pOut);
- pOut->flags = MEM_Int;
- return pOut;
-}
-static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
- Mem *pOut;
- assert( pOp->p2>0 );
- assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
- pOut = &p->aMem[pOp->p2];
- memAboutToChange(p, pOut);
- if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/
- return out2PrereleaseWithClear(pOut);
- }else{
- pOut->flags = MEM_Int;
- return pOut;
- }
-}
-
-
-/*
-** Execute as much of a VDBE program as we can.
-** This is the core of sqlite3_step().
-*/
-int sqlite3VdbeExec(
- Vdbe *p /* The VDBE */
-){
- Op *aOp = p->aOp; /* Copy of p->aOp */
- Op *pOp = aOp; /* Current operation */
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
- Op *pOrigOp; /* Value of pOp at the top of the loop */
-#endif
-#ifdef SQLITE_DEBUG
- int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */
-#endif
- int rc = SQLITE_OK; /* Value to return */
- sqlite3 *db = p->db; /* The database */
- u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
- u8 encoding = ENC(db); /* The database encoding */
- int iCompare = 0; /* Result of last comparison */
- unsigned nVmStep = 0; /* Number of virtual machine steps */
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- unsigned nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */
-#endif
- Mem *aMem = p->aMem; /* Copy of p->aMem */
- Mem *pIn1 = 0; /* 1st input operand */
- Mem *pIn2 = 0; /* 2nd input operand */
- Mem *pIn3 = 0; /* 3rd input operand */
- Mem *pOut = 0; /* Output operand */
-#ifdef VDBE_PROFILE
- u64 start; /* CPU clock count at start of opcode */
-#endif
- /*** INSERT STACK UNION HERE ***/
-
- assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
- sqlite3VdbeEnter(p);
- if( p->rc==SQLITE_NOMEM ){
- /* This happens if a malloc() inside a call to sqlite3_column_text() or
- ** sqlite3_column_text16() failed. */
- goto no_mem;
- }
- assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
- assert( p->bIsReader || p->readOnly!=0 );
- p->iCurrentTime = 0;
- assert( p->explain==0 );
- p->pResultSet = 0;
- db->busyHandler.nBusy = 0;
- if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
- sqlite3VdbeIOTraceSql(p);
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- if( db->xProgress ){
- u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
- assert( 0 < db->nProgressOps );
- nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
- }else{
- nProgressLimit = 0xffffffff;
- }
-#endif
-#ifdef SQLITE_DEBUG
- sqlite3BeginBenignMalloc();
- if( p->pc==0
- && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
- ){
- int i;
- int once = 1;
- sqlite3VdbePrintSql(p);
- if( p->db->flags & SQLITE_VdbeListing ){
- printf("VDBE Program Listing:\n");
- for(i=0; i<p->nOp; i++){
- sqlite3VdbePrintOp(stdout, i, &aOp[i]);
- }
- }
- if( p->db->flags & SQLITE_VdbeEQP ){
- for(i=0; i<p->nOp; i++){
- if( aOp[i].opcode==OP_Explain ){
- if( once ) printf("VDBE Query Plan:\n");
- printf("%s\n", aOp[i].p4.z);
- once = 0;
- }
- }
- }
- if( p->db->flags & SQLITE_VdbeTrace ) printf("VDBE Trace:\n");
- }
- sqlite3EndBenignMalloc();
-#endif
- for(pOp=&aOp[p->pc]; 1; pOp++){
- /* Errors are detected by individual opcodes, with an immediate
- ** jumps to abort_due_to_error. */
- assert( rc==SQLITE_OK );
-
- assert( pOp>=aOp && pOp<&aOp[p->nOp]);
-#ifdef VDBE_PROFILE
- start = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
-#endif
- nVmStep++;
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- if( p->anExec ) p->anExec[(int)(pOp-aOp)]++;
-#endif
-
- /* Only allow tracing if SQLITE_DEBUG is defined.
- */
-#ifdef SQLITE_DEBUG
- if( db->flags & SQLITE_VdbeTrace ){
- sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp);
- }
-#endif
-
-
- /* Check to see if we need to simulate an interrupt. This only happens
- ** if we have a special test build.
- */
-#ifdef SQLITE_TEST
- if( sqlite3_interrupt_count>0 ){
- sqlite3_interrupt_count--;
- if( sqlite3_interrupt_count==0 ){
- sqlite3_interrupt(db);
- }
- }
-#endif
-
- /* Sanity checking on other operands */
-#ifdef SQLITE_DEBUG
- {
- u8 opProperty = sqlite3OpcodeProperty[pOp->opcode];
- if( (opProperty & OPFLG_IN1)!=0 ){
- assert( pOp->p1>0 );
- assert( pOp->p1<=(p->nMem+1 - p->nCursor) );
- assert( memIsValid(&aMem[pOp->p1]) );
- assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
- REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
- }
- if( (opProperty & OPFLG_IN2)!=0 ){
- assert( pOp->p2>0 );
- assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
- assert( memIsValid(&aMem[pOp->p2]) );
- assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
- REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
- }
- if( (opProperty & OPFLG_IN3)!=0 ){
- assert( pOp->p3>0 );
- assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
- assert( memIsValid(&aMem[pOp->p3]) );
- assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
- REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
- }
- if( (opProperty & OPFLG_OUT2)!=0 ){
- assert( pOp->p2>0 );
- assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
- memAboutToChange(p, &aMem[pOp->p2]);
- }
- if( (opProperty & OPFLG_OUT3)!=0 ){
- assert( pOp->p3>0 );
- assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
- memAboutToChange(p, &aMem[pOp->p3]);
- }
- }
-#endif
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
- pOrigOp = pOp;
-#endif
-
- switch( pOp->opcode ){
-
-/*****************************************************************************
-** What follows is a massive switch statement where each case implements a
-** separate instruction in the virtual machine. If we follow the usual
-** indentation conventions, each case should be indented by 6 spaces. But
-** that is a lot of wasted space on the left margin. So the code within
-** the switch statement will break with convention and be flush-left. Another
-** big comment (similar to this one) will mark the point in the code where
-** we transition back to normal indentation.
-**
-** The formatting of each case is important. The makefile for SQLite
-** generates two C files "opcodes.h" and "opcodes.c" by scanning this
-** file looking for lines that begin with "case OP_". The opcodes.h files
-** will be filled with #defines that give unique integer values to each
-** opcode and the opcodes.c file is filled with an array of strings where
-** each string is the symbolic name for the corresponding opcode. If the
-** case statement is followed by a comment of the form "/# same as ... #/"
-** that comment is used to determine the particular value of the opcode.
-**
-** Other keywords in the comment that follows each case are used to
-** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[].
-** Keywords include: in1, in2, in3, out2, out3. See
-** the mkopcodeh.awk script for additional information.
-**
-** Documentation about VDBE opcodes is generated by scanning this file
-** for lines of that contain "Opcode:". That line and all subsequent
-** comment lines are used in the generation of the opcode.html documentation
-** file.
-**
-** SUMMARY:
-**
-** Formatting is important to scripts that scan this file.
-** Do not deviate from the formatting style currently in use.
-**
-*****************************************************************************/
-
-/* Opcode: Goto * P2 * * *
-**
-** An unconditional jump to address P2.
-** The next instruction executed will be
-** the one at index P2 from the beginning of
-** the program.
-**
-** The P1 parameter is not actually used by this opcode. However, it
-** is sometimes set to 1 instead of 0 as a hint to the command-line shell
-** that this Goto is the bottom of a loop and that the lines from P2 down
-** to the current line should be indented for EXPLAIN output.
-*/
-case OP_Goto: { /* jump */
-jump_to_p2_and_check_for_interrupt:
- pOp = &aOp[pOp->p2 - 1];
-
- /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
- ** OP_VNext, or OP_SorterNext) all jump here upon
- ** completion. Check to see if sqlite3_interrupt() has been called
- ** or if the progress callback needs to be invoked.
- **
- ** This code uses unstructured "goto" statements and does not look clean.
- ** But that is not due to sloppy coding habits. The code is written this
- ** way for performance, to avoid having to run the interrupt and progress
- ** checks on every opcode. This helps sqlite3_step() to run about 1.5%
- ** faster according to "valgrind --tool=cachegrind" */
-check_for_interrupt:
- if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- /* Call the progress callback if it is configured and the required number
- ** of VDBE ops have been executed (either since this invocation of
- ** sqlite3VdbeExec() or since last time the progress callback was called).
- ** If the progress callback returns non-zero, exit the virtual machine with
- ** a return code SQLITE_ABORT.
- */
- if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
- assert( db->nProgressOps!=0 );
- nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
- if( db->xProgress(db->pProgressArg) ){
- rc = SQLITE_INTERRUPT;
- goto abort_due_to_error;
- }
- }
-#endif
-
- break;
-}
-
-/* Opcode: Gosub P1 P2 * * *
-**
-** Write the current address onto register P1
-** and then jump to address P2.
-*/
-case OP_Gosub: { /* jump */
- assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
- pIn1 = &aMem[pOp->p1];
- assert( VdbeMemDynamic(pIn1)==0 );
- memAboutToChange(p, pIn1);
- pIn1->flags = MEM_Int;
- pIn1->u.i = (int)(pOp-aOp);
- REGISTER_TRACE(pOp->p1, pIn1);
-
- /* Most jump operations do a goto to this spot in order to update
- ** the pOp pointer. */
-jump_to_p2:
- pOp = &aOp[pOp->p2 - 1];
- break;
-}
-
-/* Opcode: Return P1 * * * *
-**
-** Jump to the next instruction after the address in register P1. After
-** the jump, register P1 becomes undefined.
-*/
-case OP_Return: { /* in1 */
- pIn1 = &aMem[pOp->p1];
- assert( pIn1->flags==MEM_Int );
- pOp = &aOp[pIn1->u.i];
- pIn1->flags = MEM_Undefined;
- break;
-}
-
-/* Opcode: InitCoroutine P1 P2 P3 * *
-**
-** Set up register P1 so that it will Yield to the coroutine
-** located at address P3.
-**
-** If P2!=0 then the coroutine implementation immediately follows
-** this opcode. So jump over the coroutine implementation to
-** address P2.
-**
-** See also: EndCoroutine
-*/
-case OP_InitCoroutine: { /* jump */
- assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
- assert( pOp->p2>=0 && pOp->p2<p->nOp );
- assert( pOp->p3>=0 && pOp->p3<p->nOp );
- pOut = &aMem[pOp->p1];
- assert( !VdbeMemDynamic(pOut) );
- pOut->u.i = pOp->p3 - 1;
- pOut->flags = MEM_Int;
- if( pOp->p2 ) goto jump_to_p2;
- break;
-}
-
-/* Opcode: EndCoroutine P1 * * * *
-**
-** The instruction at the address in register P1 is a Yield.
-** Jump to the P2 parameter of that Yield.
-** After the jump, register P1 becomes undefined.
-**
-** See also: InitCoroutine
-*/
-case OP_EndCoroutine: { /* in1 */
- VdbeOp *pCaller;
- pIn1 = &aMem[pOp->p1];
- assert( pIn1->flags==MEM_Int );
- assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
- pCaller = &aOp[pIn1->u.i];
- assert( pCaller->opcode==OP_Yield );
- assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
- pOp = &aOp[pCaller->p2 - 1];
- pIn1->flags = MEM_Undefined;
- break;
-}
-
-/* Opcode: Yield P1 P2 * * *
-**
-** Swap the program counter with the value in register P1. This
-** has the effect of yielding to a coroutine.
-**
-** If the coroutine that is launched by this instruction ends with
-** Yield or Return then continue to the next instruction. But if
-** the coroutine launched by this instruction ends with
-** EndCoroutine, then jump to P2 rather than continuing with the
-** next instruction.
-**
-** See also: InitCoroutine
-*/
-case OP_Yield: { /* in1, jump */
- int pcDest;
- pIn1 = &aMem[pOp->p1];
- assert( VdbeMemDynamic(pIn1)==0 );
- pIn1->flags = MEM_Int;
- pcDest = (int)pIn1->u.i;
- pIn1->u.i = (int)(pOp - aOp);
- REGISTER_TRACE(pOp->p1, pIn1);
- pOp = &aOp[pcDest];
- break;
-}
-
-/* Opcode: HaltIfNull P1 P2 P3 P4 P5
-** Synopsis: if r[P3]=null halt
-**
-** Check the value in register P3. If it is NULL then Halt using
-** parameter P1, P2, and P4 as if this were a Halt instruction. If the
-** value in register P3 is not NULL, then this routine is a no-op.
-** The P5 parameter should be 1.
-*/
-case OP_HaltIfNull: { /* in3 */
- pIn3 = &aMem[pOp->p3];
-#ifdef SQLITE_DEBUG
- if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
-#endif
- if( (pIn3->flags & MEM_Null)==0 ) break;
- /* Fall through into OP_Halt */
-}
-
-/* Opcode: Halt P1 P2 * P4 P5
-**
-** Exit immediately. All open cursors, etc are closed
-** automatically.
-**
-** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
-** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0).
-** For errors, it can be some other value. If P1!=0 then P2 will determine
-** whether or not to rollback the current transaction. Do not rollback
-** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
-** then back out all changes that have occurred during this execution of the
-** VDBE, but do not rollback the transaction.
-**
-** If P4 is not null then it is an error message string.
-**
-** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
-**
-** 0: (no change)
-** 1: NOT NULL contraint failed: P4
-** 2: UNIQUE constraint failed: P4
-** 3: CHECK constraint failed: P4
-** 4: FOREIGN KEY constraint failed: P4
-**
-** If P5 is not zero and P4 is NULL, then everything after the ":" is
-** omitted.
-**
-** There is an implied "Halt 0 0 0" instruction inserted at the very end of
-** every program. So a jump past the last instruction of the program
-** is the same as executing Halt.
-*/
-case OP_Halt: {
- VdbeFrame *pFrame;
- int pcx;
-
- pcx = (int)(pOp - aOp);
-#ifdef SQLITE_DEBUG
- if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
-#endif
- if( pOp->p1==SQLITE_OK && p->pFrame ){
- /* Halt the sub-program. Return control to the parent frame. */
- pFrame = p->pFrame;
- p->pFrame = pFrame->pParent;
- p->nFrame--;
- sqlite3VdbeSetChanges(db, p->nChange);
- pcx = sqlite3VdbeFrameRestore(pFrame);
- if( pOp->p2==OE_Ignore ){
- /* Instruction pcx is the OP_Program that invoked the sub-program
- ** currently being halted. If the p2 instruction of this OP_Halt
- ** instruction is set to OE_Ignore, then the sub-program is throwing
- ** an IGNORE exception. In this case jump to the address specified
- ** as the p2 of the calling OP_Program. */
- pcx = p->aOp[pcx].p2-1;
- }
- aOp = p->aOp;
- aMem = p->aMem;
- pOp = &aOp[pcx];
- break;
- }
- p->rc = pOp->p1;
- p->errorAction = (u8)pOp->p2;
- p->pc = pcx;
- assert( pOp->p5<=4 );
- if( p->rc ){
- if( pOp->p5 ){
- static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
- "FOREIGN KEY" };
- testcase( pOp->p5==1 );
- testcase( pOp->p5==2 );
- testcase( pOp->p5==3 );
- testcase( pOp->p5==4 );
- sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]);
- if( pOp->p4.z ){
- p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z);
- }
- }else{
- sqlite3VdbeError(p, "%s", pOp->p4.z);
- }
- sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
- }
- rc = sqlite3VdbeHalt(p);
- assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
- if( rc==SQLITE_BUSY ){
- p->rc = SQLITE_BUSY;
- }else{
- assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
- assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
- rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
- }
- goto vdbe_return;
-}
-
-/* Opcode: Integer P1 P2 * * *
-** Synopsis: r[P2]=P1
-**
-** The 32-bit integer value P1 is written into register P2.
-*/
-case OP_Integer: { /* out2 */
- pOut = out2Prerelease(p, pOp);
- pOut->u.i = pOp->p1;
- break;
-}
-
-/* Opcode: Int64 * P2 * P4 *
-** Synopsis: r[P2]=P4
-**
-** P4 is a pointer to a 64-bit integer value.
-** Write that value into register P2.
-*/
-case OP_Int64: { /* out2 */
- pOut = out2Prerelease(p, pOp);
- assert( pOp->p4.pI64!=0 );
- pOut->u.i = *pOp->p4.pI64;
- break;
-}
-
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/* Opcode: Real * P2 * P4 *
-** Synopsis: r[P2]=P4
-**
-** P4 is a pointer to a 64-bit floating point value.
-** Write that value into register P2.
-*/
-case OP_Real: { /* same as TK_FLOAT, out2 */
- pOut = out2Prerelease(p, pOp);
- pOut->flags = MEM_Real;
- assert( !sqlite3IsNaN(*pOp->p4.pReal) );
- pOut->u.r = *pOp->p4.pReal;
- break;
-}
-#endif
-
-/* Opcode: String8 * P2 * P4 *
-** Synopsis: r[P2]='P4'
-**
-** P4 points to a nul terminated UTF-8 string. This opcode is transformed
-** into a String opcode before it is executed for the first time. During
-** this transformation, the length of string P4 is computed and stored
-** as the P1 parameter.
-*/
-case OP_String8: { /* same as TK_STRING, out2 */
- assert( pOp->p4.z!=0 );
- pOut = out2Prerelease(p, pOp);
- pOp->opcode = OP_String;
- pOp->p1 = sqlite3Strlen30(pOp->p4.z);
-
-#ifndef SQLITE_OMIT_UTF16
- if( encoding!=SQLITE_UTF8 ){
- rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
- assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG );
- if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
- assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
- assert( VdbeMemDynamic(pOut)==0 );
- pOut->szMalloc = 0;
- pOut->flags |= MEM_Static;
- if( pOp->p4type==P4_DYNAMIC ){
- sqlite3DbFree(db, pOp->p4.z);
- }
- pOp->p4type = P4_DYNAMIC;
- pOp->p4.z = pOut->z;
- pOp->p1 = pOut->n;
- }
- testcase( rc==SQLITE_TOOBIG );
-#endif
- if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
- assert( rc==SQLITE_OK );
- /* Fall through to the next case, OP_String */
-}
-
-/* Opcode: String P1 P2 P3 P4 P5
-** Synopsis: r[P2]='P4' (len=P1)
-**
-** The string value P4 of length P1 (bytes) is stored in register P2.
-**
-** If P3 is not zero and the content of register P3 is equal to P5, then
-** the datatype of the register P2 is converted to BLOB. The content is
-** the same sequence of bytes, it is merely interpreted as a BLOB instead
-** of a string, as if it had been CAST. In other words:
-**
-** if( P3!=0 and reg[P3]==P5 ) reg[P2] := CAST(reg[P2] as BLOB)
-*/
-case OP_String: { /* out2 */
- assert( pOp->p4.z!=0 );
- pOut = out2Prerelease(p, pOp);
- pOut->flags = MEM_Str|MEM_Static|MEM_Term;
- pOut->z = pOp->p4.z;
- pOut->n = pOp->p1;
- pOut->enc = encoding;
- UPDATE_MAX_BLOBSIZE(pOut);
-#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- if( pOp->p3>0 ){
- assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
- pIn3 = &aMem[pOp->p3];
- assert( pIn3->flags & MEM_Int );
- if( pIn3->u.i==pOp->p5 ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
- }
-#endif
- break;
-}
-
-/* Opcode: Null P1 P2 P3 * *
-** Synopsis: r[P2..P3]=NULL
-**
-** Write a NULL into registers P2. If P3 greater than P2, then also write
-** NULL into register P3 and every register in between P2 and P3. If P3
-** is less than P2 (typically P3 is zero) then only register P2 is
-** set to NULL.
-**
-** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
-** NULL values will not compare equal even if SQLITE_NULLEQ is set on
-** OP_Ne or OP_Eq.
-*/
-case OP_Null: { /* out2 */
- int cnt;
- u16 nullFlag;
- pOut = out2Prerelease(p, pOp);
- cnt = pOp->p3-pOp->p2;
- assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
- pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
- pOut->n = 0;
- while( cnt>0 ){
- pOut++;
- memAboutToChange(p, pOut);
- sqlite3VdbeMemSetNull(pOut);
- pOut->flags = nullFlag;
- pOut->n = 0;
- cnt--;
- }
- break;
-}
-
-/* Opcode: SoftNull P1 * * * *
-** Synopsis: r[P1]=NULL
-**
-** Set register P1 to have the value NULL as seen by the OP_MakeRecord
-** instruction, but do not free any string or blob memory associated with
-** the register, so that if the value was a string or blob that was
-** previously copied using OP_SCopy, the copies will continue to be valid.
-*/
-case OP_SoftNull: {
- assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
- pOut = &aMem[pOp->p1];
- pOut->flags = (pOut->flags&~(MEM_Undefined|MEM_AffMask))|MEM_Null;
- break;
-}
-
-/* Opcode: Blob P1 P2 * P4 *
-** Synopsis: r[P2]=P4 (len=P1)
-**
-** P4 points to a blob of data P1 bytes long. Store this
-** blob in register P2.
-*/
-case OP_Blob: { /* out2 */
- assert( pOp->p1 <= SQLITE_MAX_LENGTH );
- pOut = out2Prerelease(p, pOp);
- sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
- pOut->enc = encoding;
- UPDATE_MAX_BLOBSIZE(pOut);
- break;
-}
-
-/* Opcode: Variable P1 P2 * P4 *
-** Synopsis: r[P2]=parameter(P1,P4)
-**
-** Transfer the values of bound parameter P1 into register P2
-**
-** If the parameter is named, then its name appears in P4.
-** The P4 value is used by sqlite3_bind_parameter_name().
-*/
-case OP_Variable: { /* out2 */
- Mem *pVar; /* Value being transferred */
-
- assert( pOp->p1>0 && pOp->p1<=p->nVar );
- assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) );
- pVar = &p->aVar[pOp->p1 - 1];
- if( sqlite3VdbeMemTooBig(pVar) ){
- goto too_big;
- }
- pOut = &aMem[pOp->p2];
- sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
- UPDATE_MAX_BLOBSIZE(pOut);
- break;
-}
-
-/* Opcode: Move P1 P2 P3 * *
-** Synopsis: r[P2@P3]=r[P1@P3]
-**
-** Move the P3 values in register P1..P1+P3-1 over into
-** registers P2..P2+P3-1. Registers P1..P1+P3-1 are
-** left holding a NULL. It is an error for register ranges
-** P1..P1+P3-1 and P2..P2+P3-1 to overlap. It is an error
-** for P3 to be less than 1.
-*/
-case OP_Move: {
- int n; /* Number of registers left to copy */
- int p1; /* Register to copy from */
- int p2; /* Register to copy to */
-
- n = pOp->p3;
- p1 = pOp->p1;
- p2 = pOp->p2;
- assert( n>0 && p1>0 && p2>0 );
- assert( p1+n<=p2 || p2+n<=p1 );
-
- pIn1 = &aMem[p1];
- pOut = &aMem[p2];
- do{
- assert( pOut<=&aMem[(p->nMem+1 - p->nCursor)] );
- assert( pIn1<=&aMem[(p->nMem+1 - p->nCursor)] );
- assert( memIsValid(pIn1) );
- memAboutToChange(p, pOut);
- sqlite3VdbeMemMove(pOut, pIn1);
-#ifdef SQLITE_DEBUG
- if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<pOut ){
- pOut->pScopyFrom += pOp->p2 - p1;
- }
-#endif
- Deephemeralize(pOut);
- REGISTER_TRACE(p2++, pOut);
- pIn1++;
- pOut++;
- }while( --n );
- break;
-}
-
-/* Opcode: Copy P1 P2 P3 * *
-** Synopsis: r[P2@P3+1]=r[P1@P3+1]
-**
-** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
-**
-** This instruction makes a deep copy of the value. A duplicate
-** is made of any string or blob constant. See also OP_SCopy.
-*/
-case OP_Copy: {
- int n;
-
- n = pOp->p3;
- pIn1 = &aMem[pOp->p1];
- pOut = &aMem[pOp->p2];
- assert( pOut!=pIn1 );
- while( 1 ){
- sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
- Deephemeralize(pOut);
-#ifdef SQLITE_DEBUG
- pOut->pScopyFrom = 0;
-#endif
- REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut);
- if( (n--)==0 ) break;
- pOut++;
- pIn1++;
- }
- break;
-}
-
-/* Opcode: SCopy P1 P2 * * *
-** Synopsis: r[P2]=r[P1]
-**
-** Make a shallow copy of register P1 into register P2.
-**
-** This instruction makes a shallow copy of the value. If the value
-** is a string or blob, then the copy is only a pointer to the
-** original and hence if the original changes so will the copy.
-** Worse, if the original is deallocated, the copy becomes invalid.
-** Thus the program must guarantee that the original will not change
-** during the lifetime of the copy. Use OP_Copy to make a complete
-** copy.
-*/
-case OP_SCopy: { /* out2 */
- pIn1 = &aMem[pOp->p1];
- pOut = &aMem[pOp->p2];
- assert( pOut!=pIn1 );
- sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
-#ifdef SQLITE_DEBUG
- if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
-#endif
- break;
-}
-
-/* Opcode: IntCopy P1 P2 * * *
-** Synopsis: r[P2]=r[P1]
-**
-** Transfer the integer value held in register P1 into register P2.
-**
-** This is an optimized version of SCopy that works only for integer
-** values.
-*/
-case OP_IntCopy: { /* out2 */
- pIn1 = &aMem[pOp->p1];
- assert( (pIn1->flags & MEM_Int)!=0 );
- pOut = &aMem[pOp->p2];
- sqlite3VdbeMemSetInt64(pOut, pIn1->u.i);
- break;
-}
-
-/* Opcode: ResultRow P1 P2 * * *
-** Synopsis: output=r[P1@P2]
-**
-** The registers P1 through P1+P2-1 contain a single row of
-** results. This opcode causes the sqlite3_step() call to terminate
-** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
-** structure to provide access to the r(P1)..r(P1+P2-1) values as
-** the result row.
-*/
-case OP_ResultRow: {
- Mem *pMem;
- int i;
- assert( p->nResColumn==pOp->p2 );
- assert( pOp->p1>0 );
- assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
-
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- /* Run the progress counter just before returning.
- */
- if( db->xProgress!=0
- && nVmStep>=nProgressLimit
- && db->xProgress(db->pProgressArg)!=0
- ){
- rc = SQLITE_INTERRUPT;
- goto abort_due_to_error;
- }
-#endif
-
- /* If this statement has violated immediate foreign key constraints, do
- ** not return the number of rows modified. And do not RELEASE the statement
- ** transaction. It needs to be rolled back. */
- if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
- assert( db->flags&SQLITE_CountRows );
- assert( p->usesStmtJournal );
- goto abort_due_to_error;
- }
-
- /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
- ** DML statements invoke this opcode to return the number of rows
- ** modified to the user. This is the only way that a VM that
- ** opens a statement transaction may invoke this opcode.
- **
- ** In case this is such a statement, close any statement transaction
- ** opened by this VM before returning control to the user. This is to
- ** ensure that statement-transactions are always nested, not overlapping.
- ** If the open statement-transaction is not closed here, then the user
- ** may step another VM that opens its own statement transaction. This
- ** may lead to overlapping statement transactions.
- **
- ** The statement transaction is never a top-level transaction. Hence
- ** the RELEASE call below can never fail.
- */
- assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
- rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
- assert( rc==SQLITE_OK );
-
- /* Invalidate all ephemeral cursor row caches */
- p->cacheCtr = (p->cacheCtr + 2)|1;
-
- /* Make sure the results of the current row are \000 terminated
- ** and have an assigned type. The results are de-ephemeralized as
- ** a side effect.
- */
- pMem = p->pResultSet = &aMem[pOp->p1];
- for(i=0; i<pOp->p2; i++){
- assert( memIsValid(&pMem[i]) );
- Deephemeralize(&pMem[i]);
- assert( (pMem[i].flags & MEM_Ephem)==0
- || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
- sqlite3VdbeMemNulTerminate(&pMem[i]);
- REGISTER_TRACE(pOp->p1+i, &pMem[i]);
- }
- if( db->mallocFailed ) goto no_mem;
-
- if( db->mTrace & SQLITE_TRACE_ROW ){
- db->xTrace(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
- }
-
- /* Return SQLITE_ROW
- */
- p->pc = (int)(pOp - aOp) + 1;
- rc = SQLITE_ROW;
- goto vdbe_return;
-}
-
-/* Opcode: Concat P1 P2 P3 * *
-** Synopsis: r[P3]=r[P2]+r[P1]
-**
-** Add the text in register P1 onto the end of the text in
-** register P2 and store the result in register P3.
-** If either the P1 or P2 text are NULL then store NULL in P3.
-**
-** P3 = P2 || P1
-**
-** It is illegal for P1 and P3 to be the same register. Sometimes,
-** if P3 is the same register as P2, the implementation is able
-** to avoid a memcpy().
-*/
-case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
- i64 nByte;
-
- pIn1 = &aMem[pOp->p1];
- pIn2 = &aMem[pOp->p2];
- pOut = &aMem[pOp->p3];
- assert( pIn1!=pOut );
- if( (pIn1->flags | pIn2->flags) & MEM_Null ){
- sqlite3VdbeMemSetNull(pOut);
- break;
- }
- if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
- Stringify(pIn1, encoding);
- Stringify(pIn2, encoding);
- nByte = pIn1->n + pIn2->n;
- if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
- if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
- goto no_mem;
- }
- MemSetTypeFlag(pOut, MEM_Str);
- if( pOut!=pIn2 ){
- memcpy(pOut->z, pIn2->z, pIn2->n);
- }
- memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
- pOut->z[nByte]=0;
- pOut->z[nByte+1] = 0;
- pOut->flags |= MEM_Term;
- pOut->n = (int)nByte;
- pOut->enc = encoding;
- UPDATE_MAX_BLOBSIZE(pOut);
- break;
-}
-
-/* Opcode: Add P1 P2 P3 * *
-** Synopsis: r[P3]=r[P1]+r[P2]
-**
-** Add the value in register P1 to the value in register P2
-** and store the result in register P3.
-** If either input is NULL, the result is NULL.
-*/
-/* Opcode: Multiply P1 P2 P3 * *
-** Synopsis: r[P3]=r[P1]*r[P2]
-**
-**
-** Multiply the value in register P1 by the value in register P2
-** and store the result in register P3.
-** If either input is NULL, the result is NULL.
-*/
-/* Opcode: Subtract P1 P2 P3 * *
-** Synopsis: r[P3]=r[P2]-r[P1]
-**
-** Subtract the value in register P1 from the value in register P2
-** and store the result in register P3.
-** If either input is NULL, the result is NULL.
-*/
-/* Opcode: Divide P1 P2 P3 * *
-** Synopsis: r[P3]=r[P2]/r[P1]
-**
-** Divide the value in register P1 by the value in register P2
-** and store the result in register P3 (P3=P2/P1). If the value in
-** register P1 is zero, then the result is NULL. If either input is
-** NULL, the result is NULL.
-*/
-/* Opcode: Remainder P1 P2 P3 * *
-** Synopsis: r[P3]=r[P2]%r[P1]
-**
-** Compute the remainder after integer register P2 is divided by
-** register P1 and store the result in register P3.
-** If the value in register P1 is zero the result is NULL.
-** If either operand is NULL, the result is NULL.
-*/
-case OP_Add: /* same as TK_PLUS, in1, in2, out3 */
-case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
-case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
-case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
-case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
- char bIntint; /* Started out as two integer operands */
- u16 flags; /* Combined MEM_* flags from both inputs */
- u16 type1; /* Numeric type of left operand */
- u16 type2; /* Numeric type of right operand */
- i64 iA; /* Integer value of left operand */
- i64 iB; /* Integer value of right operand */
- double rA; /* Real value of left operand */
- double rB; /* Real value of right operand */
-
- pIn1 = &aMem[pOp->p1];
- type1 = numericType(pIn1);
- pIn2 = &aMem[pOp->p2];
- type2 = numericType(pIn2);
- pOut = &aMem[pOp->p3];
- flags = pIn1->flags | pIn2->flags;
- if( (type1 & type2 & MEM_Int)!=0 ){
- iA = pIn1->u.i;
- iB = pIn2->u.i;
- bIntint = 1;
- switch( pOp->opcode ){
- case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break;
- case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break;
- case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break;
- case OP_Divide: {
- if( iA==0 ) goto arithmetic_result_is_null;
- if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math;
- iB /= iA;
- break;
- }
- default: {
- if( iA==0 ) goto arithmetic_result_is_null;
- if( iA==-1 ) iA = 1;
- iB %= iA;
- break;
- }
- }
- pOut->u.i = iB;
- MemSetTypeFlag(pOut, MEM_Int);
- }else if( (flags & MEM_Null)!=0 ){
- goto arithmetic_result_is_null;
- }else{
- bIntint = 0;
-fp_math:
- rA = sqlite3VdbeRealValue(pIn1);
- rB = sqlite3VdbeRealValue(pIn2);
- switch( pOp->opcode ){
- case OP_Add: rB += rA; break;
- case OP_Subtract: rB -= rA; break;
- case OP_Multiply: rB *= rA; break;
- case OP_Divide: {
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- if( rA==(double)0 ) goto arithmetic_result_is_null;
- rB /= rA;
- break;
- }
- default: {
- iA = (i64)rA;
- iB = (i64)rB;
- if( iA==0 ) goto arithmetic_result_is_null;
- if( iA==-1 ) iA = 1;
- rB = (double)(iB % iA);
- break;
- }
- }
-#ifdef SQLITE_OMIT_FLOATING_POINT
- pOut->u.i = rB;
- MemSetTypeFlag(pOut, MEM_Int);
-#else
- if( sqlite3IsNaN(rB) ){
- goto arithmetic_result_is_null;
- }
- pOut->u.r = rB;
- MemSetTypeFlag(pOut, MEM_Real);
- if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
- sqlite3VdbeIntegerAffinity(pOut);
- }
-#endif
- }
- break;
-
-arithmetic_result_is_null:
- sqlite3VdbeMemSetNull(pOut);
- break;
-}
-
-/* Opcode: CollSeq P1 * * P4
-**
-** P4 is a pointer to a CollSeq object. If the next call to a user function
-** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
-** be returned. This is used by the built-in min(), max() and nullif()
-** functions.
-**
-** If P1 is not zero, then it is a register that a subsequent min() or
-** max() aggregate will set to 1 if the current row is not the minimum or
-** maximum. The P1 register is initialized to 0 by this instruction.
-**
-** The interface used by the implementation of the aforementioned functions
-** to retrieve the collation sequence set by this opcode is not available
-** publicly. Only built-in functions have access to this feature.
-*/
-case OP_CollSeq: {
- assert( pOp->p4type==P4_COLLSEQ );
- if( pOp->p1 ){
- sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0);
- }
- break;
-}
-
-/* Opcode: BitAnd P1 P2 P3 * *
-** Synopsis: r[P3]=r[P1]&r[P2]
-**
-** Take the bit-wise AND of the values in register P1 and P2 and
-** store the result in register P3.
-** If either input is NULL, the result is NULL.
-*/
-/* Opcode: BitOr P1 P2 P3 * *
-** Synopsis: r[P3]=r[P1]|r[P2]
-**
-** Take the bit-wise OR of the values in register P1 and P2 and
-** store the result in register P3.
-** If either input is NULL, the result is NULL.
-*/
-/* Opcode: ShiftLeft P1 P2 P3 * *
-** Synopsis: r[P3]=r[P2]<<r[P1]
-**
-** Shift the integer value in register P2 to the left by the
-** number of bits specified by the integer in register P1.
-** Store the result in register P3.
-** If either input is NULL, the result is NULL.
-*/
-/* Opcode: ShiftRight P1 P2 P3 * *
-** Synopsis: r[P3]=r[P2]>>r[P1]
-**
-** Shift the integer value in register P2 to the right by the
-** number of bits specified by the integer in register P1.
-** Store the result in register P3.
-** If either input is NULL, the result is NULL.
-*/
-case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */
-case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */
-case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */
-case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
- i64 iA;
- u64 uA;
- i64 iB;
- u8 op;
-
- pIn1 = &aMem[pOp->p1];
- pIn2 = &aMem[pOp->p2];
- pOut = &aMem[pOp->p3];
- if( (pIn1->flags | pIn2->flags) & MEM_Null ){
- sqlite3VdbeMemSetNull(pOut);
- break;
- }
- iA = sqlite3VdbeIntValue(pIn2);
- iB = sqlite3VdbeIntValue(pIn1);
- op = pOp->opcode;
- if( op==OP_BitAnd ){
- iA &= iB;
- }else if( op==OP_BitOr ){
- iA |= iB;
- }else if( iB!=0 ){
- assert( op==OP_ShiftRight || op==OP_ShiftLeft );
-
- /* If shifting by a negative amount, shift in the other direction */
- if( iB<0 ){
- assert( OP_ShiftRight==OP_ShiftLeft+1 );
- op = 2*OP_ShiftLeft + 1 - op;
- iB = iB>(-64) ? -iB : 64;
- }
-
- if( iB>=64 ){
- iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1;
- }else{
- memcpy(&uA, &iA, sizeof(uA));
- if( op==OP_ShiftLeft ){
- uA <<= iB;
- }else{
- uA >>= iB;
- /* Sign-extend on a right shift of a negative number */
- if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB);
- }
- memcpy(&iA, &uA, sizeof(iA));
- }
- }
- pOut->u.i = iA;
- MemSetTypeFlag(pOut, MEM_Int);
- break;
-}
-
-/* Opcode: AddImm P1 P2 * * *
-** Synopsis: r[P1]=r[P1]+P2
-**
-** Add the constant P2 to the value in register P1.
-** The result is always an integer.
-**
-** To force any register to be an integer, just add 0.
-*/
-case OP_AddImm: { /* in1 */
- pIn1 = &aMem[pOp->p1];
- memAboutToChange(p, pIn1);
- sqlite3VdbeMemIntegerify(pIn1);
- pIn1->u.i += pOp->p2;
- break;
-}
-
-/* Opcode: MustBeInt P1 P2 * * *
-**
-** Force the value in register P1 to be an integer. If the value
-** in P1 is not an integer and cannot be converted into an integer
-** without data loss, then jump immediately to P2, or if P2==0
-** raise an SQLITE_MISMATCH exception.
-*/
-case OP_MustBeInt: { /* jump, in1 */
- pIn1 = &aMem[pOp->p1];
- if( (pIn1->flags & MEM_Int)==0 ){
- applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
- VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
- if( (pIn1->flags & MEM_Int)==0 ){
- if( pOp->p2==0 ){
- rc = SQLITE_MISMATCH;
- goto abort_due_to_error;
- }else{
- goto jump_to_p2;
- }
- }
- }
- MemSetTypeFlag(pIn1, MEM_Int);
- break;
-}
-
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/* Opcode: RealAffinity P1 * * * *
-**
-** If register P1 holds an integer convert it to a real value.
-**
-** This opcode is used when extracting information from a column that
-** has REAL affinity. Such column values may still be stored as
-** integers, for space efficiency, but after extraction we want them
-** to have only a real value.
-*/
-case OP_RealAffinity: { /* in1 */
- pIn1 = &aMem[pOp->p1];
- if( pIn1->flags & MEM_Int ){
- sqlite3VdbeMemRealify(pIn1);
- }
- break;
-}
-#endif
-
-#ifndef SQLITE_OMIT_CAST
-/* Opcode: Cast P1 P2 * * *
-** Synopsis: affinity(r[P1])
-**
-** Force the value in register P1 to be the type defined by P2.
-**
-** <ul>
-** <li> P2=='A' &rarr; BLOB
-** <li> P2=='B' &rarr; TEXT
-** <li> P2=='C' &rarr; NUMERIC
-** <li> P2=='D' &rarr; INTEGER
-** <li> P2=='E' &rarr; REAL
-** </ul>
-**
-** A NULL value is not changed by this routine. It remains NULL.
-*/
-case OP_Cast: { /* in1 */
- assert( pOp->p2>=SQLITE_AFF_BLOB && pOp->p2<=SQLITE_AFF_REAL );
- testcase( pOp->p2==SQLITE_AFF_TEXT );
- testcase( pOp->p2==SQLITE_AFF_BLOB );
- testcase( pOp->p2==SQLITE_AFF_NUMERIC );
- testcase( pOp->p2==SQLITE_AFF_INTEGER );
- testcase( pOp->p2==SQLITE_AFF_REAL );
- pIn1 = &aMem[pOp->p1];
- memAboutToChange(p, pIn1);
- rc = ExpandBlob(pIn1);
- sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
- UPDATE_MAX_BLOBSIZE(pIn1);
- if( rc ) goto abort_due_to_error;
- break;
-}
-#endif /* SQLITE_OMIT_CAST */
-
-/* Opcode: Eq P1 P2 P3 P4 P5
-** Synopsis: IF r[P3]==r[P1]
-**
-** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then
-** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5, then
-** store the result of comparison in register P2.
-**
-** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
-** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
-** to coerce both inputs according to this affinity before the
-** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
-** affinity is used. Note that the affinity conversions are stored
-** back into the input registers P1 and P3. So this opcode can cause
-** persistent changes to registers P1 and P3.
-**
-** Once any conversions have taken place, and neither value is NULL,
-** the values are compared. If both values are blobs then memcmp() is
-** used to determine the results of the comparison. If both values
-** are text, then the appropriate collating function specified in
-** P4 is used to do the comparison. If P4 is not specified then
-** memcmp() is used to compare text string. If both values are
-** numeric, then a numeric comparison is used. If the two values
-** are of different types, then numbers are considered less than
-** strings and strings are considered less than blobs.
-**
-** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
-** true or false and is never NULL. If both operands are NULL then the result
-** of comparison is true. If either operand is NULL then the result is false.
-** If neither operand is NULL the result is the same as it would be if
-** the SQLITE_NULLEQ flag were omitted from P5.
-**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 0 (false).
-** In other words, a prior r[P2] value will not be overwritten by 1 (true).
-*/
-/* Opcode: Ne P1 P2 P3 P4 P5
-** Synopsis: IF r[P3]!=r[P1]
-**
-** This works just like the Eq opcode except that the jump is taken if
-** the operands in registers P1 and P3 are not equal. See the Eq opcode for
-** additional information.
-**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 1 (true).
-** In other words, a prior r[P2] value will not be overwritten by 0 (false).
-*/
-/* Opcode: Lt P1 P2 P3 P4 P5
-** Synopsis: IF r[P3]<r[P1]
-**
-** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then
-** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5 store
-** the result of comparison (0 or 1 or NULL) into register P2.
-**
-** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
-** reg(P3) is NULL then the take the jump. If the SQLITE_JUMPIFNULL
-** bit is clear then fall through if either operand is NULL.
-**
-** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
-** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
-** to coerce both inputs according to this affinity before the
-** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
-** affinity is used. Note that the affinity conversions are stored
-** back into the input registers P1 and P3. So this opcode can cause
-** persistent changes to registers P1 and P3.
-**
-** Once any conversions have taken place, and neither value is NULL,
-** the values are compared. If both values are blobs then memcmp() is
-** used to determine the results of the comparison. If both values
-** are text, then the appropriate collating function specified in
-** P4 is used to do the comparison. If P4 is not specified then
-** memcmp() is used to compare text string. If both values are
-** numeric, then a numeric comparison is used. If the two values
-** are of different types, then numbers are considered less than
-** strings and strings are considered less than blobs.
-*/
-/* Opcode: Le P1 P2 P3 P4 P5
-** Synopsis: IF r[P3]<=r[P1]
-**
-** This works just like the Lt opcode except that the jump is taken if
-** the content of register P3 is less than or equal to the content of
-** register P1. See the Lt opcode for additional information.
-*/
-/* Opcode: Gt P1 P2 P3 P4 P5
-** Synopsis: IF r[P3]>r[P1]
-**
-** This works just like the Lt opcode except that the jump is taken if
-** the content of register P3 is greater than the content of
-** register P1. See the Lt opcode for additional information.
-*/
-/* Opcode: Ge P1 P2 P3 P4 P5
-** Synopsis: IF r[P3]>=r[P1]
-**
-** This works just like the Lt opcode except that the jump is taken if
-** the content of register P3 is greater than or equal to the content of
-** register P1. See the Lt opcode for additional information.
-*/
-case OP_Eq: /* same as TK_EQ, jump, in1, in3 */
-case OP_Ne: /* same as TK_NE, jump, in1, in3 */
-case OP_Lt: /* same as TK_LT, jump, in1, in3 */
-case OP_Le: /* same as TK_LE, jump, in1, in3 */
-case OP_Gt: /* same as TK_GT, jump, in1, in3 */
-case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
- int res, res2; /* Result of the comparison of pIn1 against pIn3 */
- char affinity; /* Affinity to use for comparison */
- u16 flags1; /* Copy of initial value of pIn1->flags */
- u16 flags3; /* Copy of initial value of pIn3->flags */
-
- pIn1 = &aMem[pOp->p1];
- pIn3 = &aMem[pOp->p3];
- flags1 = pIn1->flags;
- flags3 = pIn3->flags;
- if( (flags1 | flags3)&MEM_Null ){
- /* One or both operands are NULL */
- if( pOp->p5 & SQLITE_NULLEQ ){
- /* If SQLITE_NULLEQ is set (which will only happen if the operator is
- ** OP_Eq or OP_Ne) then take the jump or not depending on whether
- ** or not both operands are null.
- */
- assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
- assert( (flags1 & MEM_Cleared)==0 );
- assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
- if( (flags1&flags3&MEM_Null)!=0
- && (flags3&MEM_Cleared)==0
- ){
- res = 0; /* Operands are equal */
- }else{
- res = 1; /* Operands are not equal */
- }
- }else{
- /* SQLITE_NULLEQ is clear and at least one operand is NULL,
- ** then the result is always NULL.
- ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
- */
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = 1; /* Operands are not equal */
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Null);
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(2,3);
- if( pOp->p5 & SQLITE_JUMPIFNULL ){
- goto jump_to_p2;
- }
- }
- break;
- }
- }else{
- /* Neither operand is NULL. Do a comparison. */
- affinity = pOp->p5 & SQLITE_AFF_MASK;
- if( affinity>=SQLITE_AFF_NUMERIC ){
- if( (flags1 | flags3)&MEM_Str ){
- if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
- applyNumericAffinity(pIn1,0);
- testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */
- flags3 = pIn3->flags;
- }
- if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
- applyNumericAffinity(pIn3,0);
- }
- }
- /* Handle the common case of integer comparison here, as an
- ** optimization, to avoid a call to sqlite3MemCompare() */
- if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
- if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
- if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
- res = 0;
- goto compare_op;
- }
- }else if( affinity==SQLITE_AFF_TEXT ){
- if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
- testcase( pIn1->flags & MEM_Int );
- testcase( pIn1->flags & MEM_Real );
- sqlite3VdbeMemStringify(pIn1, encoding, 1);
- testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
- flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
- assert( pIn1!=pIn3 );
- }
- if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
- testcase( pIn3->flags & MEM_Int );
- testcase( pIn3->flags & MEM_Real );
- sqlite3VdbeMemStringify(pIn3, encoding, 1);
- testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
- flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
- }
- }
- assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
- res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
- }
-compare_op:
- /* At this point, res is negative, zero, or positive if reg[P1] is
- ** less than, equal to, or greater than reg[P3], respectively. Compute
- ** the answer to this operator in res2, depending on what the comparison
- ** operator actually is. The next block of code depends on the fact
- ** that the 6 comparison operators are consecutive integers in this
- ** order: NE, EQ, GT, LE, LT, GE */
- assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
- assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
- if( res<0 ){ /* ne, eq, gt, le, lt, ge */
- static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 };
- res2 = aLTb[pOp->opcode - OP_Ne];
- }else if( res==0 ){
- static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 };
- res2 = aEQb[pOp->opcode - OP_Ne];
- }else{
- static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 };
- res2 = aGTb[pOp->opcode - OP_Ne];
- }
-
- /* Undo any changes made by applyAffinity() to the input registers. */
- assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
- pIn1->flags = flags1;
- assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
- pIn3->flags = flags3;
-
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = res;
- if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
- /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
- ** and prevents OP_Ne from overwriting NULL with 0. This flag
- ** is only used in contexts where either:
- ** (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0)
- ** (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1)
- ** Therefore it is not necessary to check the content of r[P2] for
- ** NULL. */
- assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
- assert( res2==0 || res2==1 );
- testcase( res2==0 && pOp->opcode==OP_Eq );
- testcase( res2==1 && pOp->opcode==OP_Eq );
- testcase( res2==0 && pOp->opcode==OP_Ne );
- testcase( res2==1 && pOp->opcode==OP_Ne );
- if( (pOp->opcode==OP_Eq)==res2 ) break;
- }
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = res2;
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
- if( res2 ){
- goto jump_to_p2;
- }
- }
- break;
-}
-
-/* Opcode: ElseNotEq * P2 * * *
-**
-** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator.
-** If result of an OP_Eq comparison on the same two operands
-** would have be NULL or false (0), then then jump to P2.
-** If the result of an OP_Eq comparison on the two previous operands
-** would have been true (1), then fall through.
-*/
-case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
- assert( pOp>aOp );
- assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt );
- assert( pOp[-1].p5 & SQLITE_STOREP2 );
- VdbeBranchTaken(iCompare!=0, 2);
- if( iCompare!=0 ) goto jump_to_p2;
- break;
-}
-
-
-/* Opcode: Permutation * * * P4 *
-**
-** Set the permutation used by the OP_Compare operator in the next
-** instruction. The permutation is stored in the P4 operand.
-**
-** The permutation is only valid until the next OP_Compare that has
-** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
-** occur immediately prior to the OP_Compare.
-**
-** The first integer in the P4 integer array is the length of the array
-** and does not become part of the permutation.
-*/
-case OP_Permutation: {
- assert( pOp->p4type==P4_INTARRAY );
- assert( pOp->p4.ai );
- assert( pOp[1].opcode==OP_Compare );
- assert( pOp[1].p5 & OPFLAG_PERMUTE );
- break;
-}
-
-/* Opcode: Compare P1 P2 P3 P4 P5
-** Synopsis: r[P1@P3] <-> r[P2@P3]
-**
-** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
-** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
-** the comparison for use by the next OP_Jump instruct.
-**
-** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
-** determined by the most recent OP_Permutation operator. If the
-** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
-** order.
-**
-** P4 is a KeyInfo structure that defines collating sequences and sort
-** orders for the comparison. The permutation applies to registers
-** only. The KeyInfo elements are used sequentially.
-**
-** The comparison is a sort comparison, so NULLs compare equal,
-** NULLs are less than numbers, numbers are less than strings,
-** and strings are less than blobs.
-*/
-case OP_Compare: {
- int n;
- int i;
- int p1;
- int p2;
- const KeyInfo *pKeyInfo;
- int idx;
- CollSeq *pColl; /* Collating sequence to use on this term */
- int bRev; /* True for DESCENDING sort order */
- int *aPermute; /* The permutation */
-
- if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){
- aPermute = 0;
- }else{
- assert( pOp>aOp );
- assert( pOp[-1].opcode==OP_Permutation );
- assert( pOp[-1].p4type==P4_INTARRAY );
- aPermute = pOp[-1].p4.ai + 1;
- assert( aPermute!=0 );
- }
- n = pOp->p3;
- pKeyInfo = pOp->p4.pKeyInfo;
- assert( n>0 );
- assert( pKeyInfo!=0 );
- p1 = pOp->p1;
- p2 = pOp->p2;
-#ifdef SQLITE_DEBUG
- if( aPermute ){
- int k, mx = 0;
- for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
- assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 );
- assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 );
- }else{
- assert( p1>0 && p1+n<=(p->nMem+1 - p->nCursor)+1 );
- assert( p2>0 && p2+n<=(p->nMem+1 - p->nCursor)+1 );
- }
-#endif /* SQLITE_DEBUG */
- for(i=0; i<n; i++){
- idx = aPermute ? aPermute[i] : i;
- assert( memIsValid(&aMem[p1+idx]) );
- assert( memIsValid(&aMem[p2+idx]) );
- REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
- REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
- assert( i<pKeyInfo->nKeyField );
- pColl = pKeyInfo->aColl[i];
- bRev = pKeyInfo->aSortOrder[i];
- iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
- if( iCompare ){
- if( bRev ) iCompare = -iCompare;
- break;
- }
- }
- break;
-}
-
-/* Opcode: Jump P1 P2 P3 * *
-**
-** Jump to the instruction at address P1, P2, or P3 depending on whether
-** in the most recent OP_Compare instruction the P1 vector was less than
-** equal to, or greater than the P2 vector, respectively.
-*/
-case OP_Jump: { /* jump */
- if( iCompare<0 ){
- VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1];
- }else if( iCompare==0 ){
- VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1];
- }else{
- VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1];
- }
- break;
-}
-
-/* Opcode: And P1 P2 P3 * *
-** Synopsis: r[P3]=(r[P1] && r[P2])
-**
-** Take the logical AND of the values in registers P1 and P2 and
-** write the result into register P3.
-**
-** If either P1 or P2 is 0 (false) then the result is 0 even if
-** the other input is NULL. A NULL and true or two NULLs give
-** a NULL output.
-*/
-/* Opcode: Or P1 P2 P3 * *
-** Synopsis: r[P3]=(r[P1] || r[P2])
-**
-** Take the logical OR of the values in register P1 and P2 and
-** store the answer in register P3.
-**
-** If either P1 or P2 is nonzero (true) then the result is 1 (true)
-** even if the other input is NULL. A NULL and false or two NULLs
-** give a NULL output.
-*/
-case OP_And: /* same as TK_AND, in1, in2, out3 */
-case OP_Or: { /* same as TK_OR, in1, in2, out3 */
- int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
- int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-
- v1 = sqlite3VdbeBooleanValue(&aMem[pOp->p1], 2);
- v2 = sqlite3VdbeBooleanValue(&aMem[pOp->p2], 2);
- if( pOp->opcode==OP_And ){
- static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
- v1 = and_logic[v1*3+v2];
- }else{
- static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
- v1 = or_logic[v1*3+v2];
- }
- pOut = &aMem[pOp->p3];
- if( v1==2 ){
- MemSetTypeFlag(pOut, MEM_Null);
- }else{
- pOut->u.i = v1;
- MemSetTypeFlag(pOut, MEM_Int);
- }
- break;
-}
-
-/* Opcode: IsTrue P1 P2 P3 P4 *
-** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4
-**
-** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and
-** IS NOT FALSE operators.
-**
-** Interpret the value in register P1 as a boolean value. Store that
-** boolean (a 0 or 1) in register P2. Or if the value in register P1 is
-** NULL, then the P3 is stored in register P2. Invert the answer if P4
-** is 1.
-**
-** The logic is summarized like this:
-**
-** <ul>
-** <li> If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE
-** <li> If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE
-** <li> If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE
-** <li> If P3==1 and P4==0 then r[P2] := r[P1] IS NOT FALSE
-** </ul>
-*/
-case OP_IsTrue: { /* in1, out2 */
- assert( pOp->p4type==P4_INT32 );
- assert( pOp->p4.i==0 || pOp->p4.i==1 );
- assert( pOp->p3==0 || pOp->p3==1 );
- sqlite3VdbeMemSetInt64(&aMem[pOp->p2],
- sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i);
- break;
-}
-
-/* Opcode: Not P1 P2 * * *
-** Synopsis: r[P2]= !r[P1]
-**
-** Interpret the value in register P1 as a boolean value. Store the
-** boolean complement in register P2. If the value in register P1 is
-** NULL, then a NULL is stored in P2.
-*/
-case OP_Not: { /* same as TK_NOT, in1, out2 */
- pIn1 = &aMem[pOp->p1];
- pOut = &aMem[pOp->p2];
- if( (pIn1->flags & MEM_Null)==0 ){
- sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeBooleanValue(pIn1,0));
- }else{
- sqlite3VdbeMemSetNull(pOut);
- }
- break;
-}
-
-/* Opcode: BitNot P1 P2 * * *
-** Synopsis: r[P1]= ~r[P1]
-**
-** Interpret the content of register P1 as an integer. Store the
-** ones-complement of the P1 value into register P2. If P1 holds
-** a NULL then store a NULL in P2.
-*/
-case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
- pIn1 = &aMem[pOp->p1];
- pOut = &aMem[pOp->p2];
- sqlite3VdbeMemSetNull(pOut);
- if( (pIn1->flags & MEM_Null)==0 ){
- pOut->flags = MEM_Int;
- pOut->u.i = ~sqlite3VdbeIntValue(pIn1);
- }
- break;
-}
-
-/* Opcode: Once P1 P2 * * *
-**
-** Fall through to the next instruction the first time this opcode is
-** encountered on each invocation of the byte-code program. Jump to P2
-** on the second and all subsequent encounters during the same invocation.
-**
-** Top-level programs determine first invocation by comparing the P1
-** operand against the P1 operand on the OP_Init opcode at the beginning
-** of the program. If the P1 values differ, then fall through and make
-** the P1 of this opcode equal to the P1 of OP_Init. If P1 values are
-** the same then take the jump.
-**
-** For subprograms, there is a bitmask in the VdbeFrame that determines
-** whether or not the jump should be taken. The bitmask is necessary
-** because the self-altering code trick does not work for recursive
-** triggers.
-*/
-case OP_Once: { /* jump */
- u32 iAddr; /* Address of this instruction */
- assert( p->aOp[0].opcode==OP_Init );
- if( p->pFrame ){
- iAddr = (int)(pOp - p->aOp);
- if( (p->pFrame->aOnce[iAddr/8] & (1<<(iAddr & 7)))!=0 ){
- VdbeBranchTaken(1, 2);
- goto jump_to_p2;
- }
- p->pFrame->aOnce[iAddr/8] |= 1<<(iAddr & 7);
- }else{
- if( p->aOp[0].p1==pOp->p1 ){
- VdbeBranchTaken(1, 2);
- goto jump_to_p2;
- }
- }
- VdbeBranchTaken(0, 2);
- pOp->p1 = p->aOp[0].p1;
- break;
-}
-
-/* Opcode: If P1 P2 P3 * *
-**
-** Jump to P2 if the value in register P1 is true. The value
-** is considered true if it is numeric and non-zero. If the value
-** in P1 is NULL then take the jump if and only if P3 is non-zero.
-*/
-case OP_If: { /* jump, in1 */
- int c;
- c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3);
- VdbeBranchTaken(c!=0, 2);
- if( c ) goto jump_to_p2;
- break;
-}
-
-/* Opcode: IfNot P1 P2 P3 * *
-**
-** Jump to P2 if the value in register P1 is False. The value
-** is considered false if it has a numeric value of zero. If the value
-** in P1 is NULL then take the jump if and only if P3 is non-zero.
-*/
-case OP_IfNot: { /* jump, in1 */
- int c;
- c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3);
- VdbeBranchTaken(c!=0, 2);
- if( c ) goto jump_to_p2;
- break;
-}
-
-/* Opcode: IsNull P1 P2 * * *
-** Synopsis: if r[P1]==NULL goto P2
-**
-** Jump to P2 if the value in register P1 is NULL.
-*/
-case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
- pIn1 = &aMem[pOp->p1];
- VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
- if( (pIn1->flags & MEM_Null)!=0 ){
- goto jump_to_p2;
- }
- break;
-}
-
-/* Opcode: NotNull P1 P2 * * *
-** Synopsis: if r[P1]!=NULL goto P2
-**
-** Jump to P2 if the value in register P1 is not NULL.
-*/
-case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
- pIn1 = &aMem[pOp->p1];
- VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2);
- if( (pIn1->flags & MEM_Null)==0 ){
- goto jump_to_p2;
- }
- break;
-}
-
-/* Opcode: IfNullRow P1 P2 P3 * *
-** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2
-**
-** Check the cursor P1 to see if it is currently pointing at a NULL row.
-** If it is, then set register P3 to NULL and jump immediately to P2.
-** If P1 is not on a NULL row, then fall through without making any
-** changes.
-*/
-case OP_IfNullRow: { /* jump */
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( p->apCsr[pOp->p1]!=0 );
- if( p->apCsr[pOp->p1]->nullRow ){
- sqlite3VdbeMemSetNull(aMem + pOp->p3);
- goto jump_to_p2;
- }
- break;
-}
-
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
-/* Opcode: Offset P1 P2 P3 * *
-** Synopsis: r[P3] = sqlite_offset(P1)
-**
-** Store in register r[P3] the byte offset into the database file that is the
-** start of the payload for the record at which that cursor P1 is currently
-** pointing.
-**
-** P2 is the column number for the argument to the sqlite_offset() function.
-** This opcode does not use P2 itself, but the P2 value is used by the
-** code generator. The P1, P2, and P3 operands to this opcode are the
-** same as for OP_Column.
-**
-** This opcode is only available if SQLite is compiled with the
-** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option.
-*/
-case OP_Offset: { /* out3 */
- VdbeCursor *pC; /* The VDBE cursor */
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- pOut = &p->aMem[pOp->p3];
- if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){
- sqlite3VdbeMemSetNull(pOut);
- }else{
- sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
- }
- break;
-}
-#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
-
-/* Opcode: Column P1 P2 P3 P4 P5
-** Synopsis: r[P3]=PX
-**
-** Interpret the data that cursor P1 points to as a structure built using
-** the MakeRecord instruction. (See the MakeRecord opcode for additional
-** information about the format of the data.) Extract the P2-th column
-** from this record. If there are less that (P2+1)
-** values in the record, extract a NULL.
-**
-** The value extracted is stored in register P3.
-**
-** If the record contains fewer than P2 fields, then extract a NULL. Or,
-** if the P4 argument is a P4_MEM use the value of the P4 argument as
-** the result.
-**
-** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
-** then the cache of the cursor is reset prior to extracting the column.
-** The first OP_Column against a pseudo-table after the value of the content
-** register has changed should have this bit set.
-**
-** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
-** the result is guaranteed to only be used as the argument of a length()
-** or typeof() function, respectively. The loading of large blobs can be
-** skipped for length() and all content loading can be skipped for typeof().
-*/
-case OP_Column: {
- int p2; /* column number to retrieve */
- VdbeCursor *pC; /* The VDBE cursor */
- BtCursor *pCrsr; /* The BTree cursor */
- u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
- int len; /* The length of the serialized data for the column */
- int i; /* Loop counter */
- Mem *pDest; /* Where to write the extracted value */
- Mem sMem; /* For storing the record being decoded */
- const u8 *zData; /* Part of the record being decoded */
- const u8 *zHdr; /* Next unparsed byte of the header */
- const u8 *zEndHdr; /* Pointer to first byte after the header */
- u64 offset64; /* 64-bit offset */
- u32 t; /* A type code from the record header */
- Mem *pReg; /* PseudoTable input register */
-
- pC = p->apCsr[pOp->p1];
- p2 = pOp->p2;
-
- /* If the cursor cache is stale (meaning it is not currently point at
- ** the correct row) then bring it up-to-date by doing the necessary
- ** B-Tree seek. */
- rc = sqlite3VdbeCursorMoveto(&pC, &p2);
- if( rc ) goto abort_due_to_error;
-
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- pDest = &aMem[pOp->p3];
- memAboutToChange(p, pDest);
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( pC!=0 );
- assert( p2<pC->nField );
- aOffset = pC->aOffset;
- assert( pC->eCurType!=CURTYPE_VTAB );
- assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
- assert( pC->eCurType!=CURTYPE_SORTER );
-
- if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/
- if( pC->nullRow ){
- if( pC->eCurType==CURTYPE_PSEUDO ){
- /* For the special case of as pseudo-cursor, the seekResult field
- ** identifies the register that holds the record */
- assert( pC->seekResult>0 );
- pReg = &aMem[pC->seekResult];
- assert( pReg->flags & MEM_Blob );
- assert( memIsValid(pReg) );
- pC->payloadSize = pC->szRow = pReg->n;
- pC->aRow = (u8*)pReg->z;
- }else{
- sqlite3VdbeMemSetNull(pDest);
- goto op_column_out;
- }
- }else{
- pCrsr = pC->uc.pCursor;
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pCrsr );
- assert( sqlite3BtreeCursorIsValid(pCrsr) );
- pC->payloadSize = sqlite3BtreePayloadSize(pCrsr);
- pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow);
- assert( pC->szRow<=pC->payloadSize );
- assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */
- if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
- }
- pC->cacheStatus = p->cacheCtr;
- pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]);
- pC->nHdrParsed = 0;
-
-
- if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/
- /* pC->aRow does not have to hold the entire row, but it does at least
- ** need to cover the header of the record. If pC->aRow does not contain
- ** the complete header, then set it to zero, forcing the header to be
- ** dynamically allocated. */
- pC->aRow = 0;
- pC->szRow = 0;
-
- /* Make sure a corrupt database has not given us an oversize header.
- ** Do this now to avoid an oversize memory allocation.
- **
- ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
- ** types use so much data space that there can only be 4096 and 32 of
- ** them, respectively. So the maximum header length results from a
- ** 3-byte type for each of the maximum of 32768 columns plus three
- ** extra bytes for the header length itself. 32768*3 + 3 = 98307.
- */
- if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){
- goto op_column_corrupt;
- }
- }else{
- /* This is an optimization. By skipping over the first few tests
- ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a
- ** measurable performance gain.
- **
- ** This branch is taken even if aOffset[0]==0. Such a record is never
- ** generated by SQLite, and could be considered corruption, but we
- ** accept it for historical reasons. When aOffset[0]==0, the code this
- ** branch jumps to reads past the end of the record, but never more
- ** than a few bytes. Even if the record occurs at the end of the page
- ** content area, the "page header" comes after the page content and so
- ** this overread is harmless. Similar overreads can occur for a corrupt
- ** database file.
- */
- zData = pC->aRow;
- assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */
- testcase( aOffset[0]==0 );
- goto op_column_read_header;
- }
- }
-
- /* Make sure at least the first p2+1 entries of the header have been
- ** parsed and valid information is in aOffset[] and pC->aType[].
- */
- if( pC->nHdrParsed<=p2 ){
- /* If there is more header available for parsing in the record, try
- ** to extract additional fields up through the p2+1-th field
- */
- if( pC->iHdrOffset<aOffset[0] ){
- /* Make sure zData points to enough of the record to cover the header. */
- if( pC->aRow==0 ){
- memset(&sMem, 0, sizeof(sMem));
- rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- zData = (u8*)sMem.z;
- }else{
- zData = pC->aRow;
- }
-
- /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */
- op_column_read_header:
- i = pC->nHdrParsed;
- offset64 = aOffset[i];
- zHdr = zData + pC->iHdrOffset;
- zEndHdr = zData + aOffset[0];
- testcase( zHdr>=zEndHdr );
- do{
- if( (t = zHdr[0])<0x80 ){
- zHdr++;
- offset64 += sqlite3VdbeOneByteSerialTypeLen(t);
- }else{
- zHdr += sqlite3GetVarint32(zHdr, &t);
- offset64 += sqlite3VdbeSerialTypeLen(t);
- }
- pC->aType[i++] = t;
- aOffset[i] = (u32)(offset64 & 0xffffffff);
- }while( i<=p2 && zHdr<zEndHdr );
-
- /* The record is corrupt if any of the following are true:
- ** (1) the bytes of the header extend past the declared header size
- ** (2) the entire header was used but not all data was used
- ** (3) the end of the data extends beyond the end of the record.
- */
- if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize))
- || (offset64 > pC->payloadSize)
- ){
- if( aOffset[0]==0 ){
- i = 0;
- zHdr = zEndHdr;
- }else{
- if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
- goto op_column_corrupt;
- }
- }
-
- pC->nHdrParsed = i;
- pC->iHdrOffset = (u32)(zHdr - zData);
- if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
- }else{
- t = 0;
- }
-
- /* If after trying to extract new entries from the header, nHdrParsed is
- ** still not up to p2, that means that the record has fewer than p2
- ** columns. So the result will be either the default value or a NULL.
- */
- if( pC->nHdrParsed<=p2 ){
- if( pOp->p4type==P4_MEM ){
- sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
- }else{
- sqlite3VdbeMemSetNull(pDest);
- }
- goto op_column_out;
- }
- }else{
- t = pC->aType[p2];
- }
-
- /* Extract the content for the p2+1-th column. Control can only
- ** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are
- ** all valid.
- */
- assert( p2<pC->nHdrParsed );
- assert( rc==SQLITE_OK );
- assert( sqlite3VdbeCheckMemInvariants(pDest) );
- if( VdbeMemDynamic(pDest) ){
- sqlite3VdbeMemSetNull(pDest);
- }
- assert( t==pC->aType[p2] );
- if( pC->szRow>=aOffset[p2+1] ){
- /* This is the common case where the desired content fits on the original
- ** page - where the content is not on an overflow page */
- zData = pC->aRow + aOffset[p2];
- if( t<12 ){
- sqlite3VdbeSerialGet(zData, t, pDest);
- }else{
- /* If the column value is a string, we need a persistent value, not
- ** a MEM_Ephem value. This branch is a fast short-cut that is equivalent
- ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize().
- */
- static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
- pDest->n = len = (t-12)/2;
- pDest->enc = encoding;
- if( pDest->szMalloc < len+2 ){
- pDest->flags = MEM_Null;
- if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
- }else{
- pDest->z = pDest->zMalloc;
- }
- memcpy(pDest->z, zData, len);
- pDest->z[len] = 0;
- pDest->z[len+1] = 0;
- pDest->flags = aFlag[t&1];
- }
- }else{
- pDest->enc = encoding;
- /* This branch happens only when content is on overflow pages */
- if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
- && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
- || (len = sqlite3VdbeSerialTypeLen(t))==0
- ){
- /* Content is irrelevant for
- ** 1. the typeof() function,
- ** 2. the length(X) function if X is a blob, and
- ** 3. if the content length is zero.
- ** So we might as well use bogus content rather than reading
- ** content from disk.
- **
- ** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the
- ** buffer passed to it, debugging function VdbeMemPrettyPrint() may
- ** read up to 16. So 16 bytes of bogus content is supplied.
- */
- static u8 aZero[16]; /* This is the bogus content */
- sqlite3VdbeSerialGet(aZero, t, pDest);
- }else{
- rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
- pDest->flags &= ~MEM_Ephem;
- }
- }
-
-op_column_out:
- UPDATE_MAX_BLOBSIZE(pDest);
- REGISTER_TRACE(pOp->p3, pDest);
- break;
-
-op_column_corrupt:
- if( aOp[0].p3>0 ){
- pOp = &aOp[aOp[0].p3-1];
- break;
- }else{
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
- }
-}
-
-/* Opcode: Affinity P1 P2 * P4 *
-** Synopsis: affinity(r[P1@P2])
-**
-** Apply affinities to a range of P2 registers starting with P1.
-**
-** P4 is a string that is P2 characters long. The N-th character of the
-** string indicates the column affinity that should be used for the N-th
-** memory cell in the range.
-*/
-case OP_Affinity: {
- const char *zAffinity; /* The affinity to be applied */
-
- zAffinity = pOp->p4.z;
- assert( zAffinity!=0 );
- assert( pOp->p2>0 );
- assert( zAffinity[pOp->p2]==0 );
- pIn1 = &aMem[pOp->p1];
- do{
- assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] );
- assert( memIsValid(pIn1) );
- applyAffinity(pIn1, *(zAffinity++), encoding);
- pIn1++;
- }while( zAffinity[0] );
- break;
-}
-
-/* Opcode: MakeRecord P1 P2 P3 P4 *
-** Synopsis: r[P3]=mkrec(r[P1@P2])
-**
-** Convert P2 registers beginning with P1 into the [record format]
-** use as a data record in a database table or as a key
-** in an index. The OP_Column opcode can decode the record later.
-**
-** P4 may be a string that is P2 characters long. The N-th character of the
-** string indicates the column affinity that should be used for the N-th
-** field of the index key.
-**
-** The mapping from character to affinity is given by the SQLITE_AFF_
-** macros defined in sqliteInt.h.
-**
-** If P4 is NULL then all index fields have the affinity BLOB.
-*/
-case OP_MakeRecord: {
- u8 *zNewRecord; /* A buffer to hold the data for the new record */
- Mem *pRec; /* The new record */
- u64 nData; /* Number of bytes of data space */
- int nHdr; /* Number of bytes of header space */
- i64 nByte; /* Data space required for this record */
- i64 nZero; /* Number of zero bytes at the end of the record */
- int nVarint; /* Number of bytes in a varint */
- u32 serial_type; /* Type field */
- Mem *pData0; /* First field to be combined into the record */
- Mem *pLast; /* Last field of the record */
- int nField; /* Number of fields in the record */
- char *zAffinity; /* The affinity string for the record */
- int file_format; /* File format to use for encoding */
- int i; /* Space used in zNewRecord[] header */
- int j; /* Space used in zNewRecord[] content */
- u32 len; /* Length of a field */
-
- /* Assuming the record contains N fields, the record format looks
- ** like this:
- **
- ** ------------------------------------------------------------------------
- ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 |
- ** ------------------------------------------------------------------------
- **
- ** Data(0) is taken from register P1. Data(1) comes from register P1+1
- ** and so forth.
- **
- ** Each type field is a varint representing the serial type of the
- ** corresponding data element (see sqlite3VdbeSerialType()). The
- ** hdr-size field is also a varint which is the offset from the beginning
- ** of the record to data0.
- */
- nData = 0; /* Number of bytes of data space */
- nHdr = 0; /* Number of bytes of header space */
- nZero = 0; /* Number of zero bytes at the end of the record */
- nField = pOp->p1;
- zAffinity = pOp->p4.z;
- assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem+1 - p->nCursor)+1 );
- pData0 = &aMem[nField];
- nField = pOp->p2;
- pLast = &pData0[nField-1];
- file_format = p->minWriteFileFormat;
-
- /* Identify the output register */
- assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
- pOut = &aMem[pOp->p3];
- memAboutToChange(p, pOut);
-
- /* Apply the requested affinity to all inputs
- */
- assert( pData0<=pLast );
- if( zAffinity ){
- pRec = pData0;
- do{
- applyAffinity(pRec++, *(zAffinity++), encoding);
- assert( zAffinity[0]==0 || pRec<=pLast );
- }while( zAffinity[0] );
- }
-
-#ifdef SQLITE_ENABLE_NULL_TRIM
- /* NULLs can be safely trimmed from the end of the record, as long as
- ** as the schema format is 2 or more and none of the omitted columns
- ** have a non-NULL default value. Also, the record must be left with
- ** at least one field. If P5>0 then it will be one more than the
- ** index of the right-most column with a non-NULL default value */
- if( pOp->p5 ){
- while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){
- pLast--;
- nField--;
- }
- }
-#endif
-
- /* Loop through the elements that will make up the record to figure
- ** out how much space is required for the new record.
- */
- pRec = pLast;
- do{
- assert( memIsValid(pRec) );
- serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
- if( pRec->flags & MEM_Zero ){
- if( serial_type==0 ){
- /* Values with MEM_Null and MEM_Zero are created by xColumn virtual
- ** table methods that never invoke sqlite3_result_xxxxx() while
- ** computing an unchanging column value in an UPDATE statement.
- ** Give such values a special internal-use-only serial-type of 10
- ** so that they can be passed through to xUpdate and have
- ** a true sqlite3_value_nochange(). */
- assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
- serial_type = 10;
- }else if( nData ){
- if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
- }else{
- nZero += pRec->u.nZero;
- len -= pRec->u.nZero;
- }
- }
- nData += len;
- testcase( serial_type==127 );
- testcase( serial_type==128 );
- nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
- pRec->uTemp = serial_type;
- if( pRec==pData0 ) break;
- pRec--;
- }while(1);
-
- /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint
- ** which determines the total number of bytes in the header. The varint
- ** value is the size of the header in bytes including the size varint
- ** itself. */
- testcase( nHdr==126 );
- testcase( nHdr==127 );
- if( nHdr<=126 ){
- /* The common case */
- nHdr += 1;
- }else{
- /* Rare case of a really large header */
- nVarint = sqlite3VarintLen(nHdr);
- nHdr += nVarint;
- if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
- }
- nByte = nHdr+nData;
- if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
-
- /* Make sure the output register has a buffer large enough to store
- ** the new record. The output register (pOp->p3) is not allowed to
- ** be one of the input registers (because the following call to
- ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used).
- */
- if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
- goto no_mem;
- }
- zNewRecord = (u8 *)pOut->z;
-
- /* Write the record */
- i = putVarint32(zNewRecord, nHdr);
- j = nHdr;
- assert( pData0<=pLast );
- pRec = pData0;
- do{
- serial_type = pRec->uTemp;
- /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more
- ** additional varints, one per column. */
- i += putVarint32(&zNewRecord[i], serial_type); /* serial type */
- /* EVIDENCE-OF: R-64536-51728 The values for each column in the record
- ** immediately follow the header. */
- j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */
- }while( (++pRec)<=pLast );
- assert( i==nHdr );
- assert( j==nByte );
-
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- pOut->n = (int)nByte;
- pOut->flags = MEM_Blob;
- if( nZero ){
- pOut->u.nZero = nZero;
- pOut->flags |= MEM_Zero;
- }
- REGISTER_TRACE(pOp->p3, pOut);
- UPDATE_MAX_BLOBSIZE(pOut);
- break;
-}
-
-/* Opcode: Count P1 P2 * * *
-** Synopsis: r[P2]=count()
-**
-** Store the number of entries (an integer value) in the table or index
-** opened by cursor P1 in register P2
-*/
-#ifndef SQLITE_OMIT_BTREECOUNT
-case OP_Count: { /* out2 */
- i64 nEntry;
- BtCursor *pCrsr;
-
- assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
- pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
- assert( pCrsr );
- nEntry = 0; /* Not needed. Only used to silence a warning. */
- rc = sqlite3BtreeCount(pCrsr, &nEntry);
- if( rc ) goto abort_due_to_error;
- pOut = out2Prerelease(p, pOp);
- pOut->u.i = nEntry;
- break;
-}
-#endif
-
-/* Opcode: Savepoint P1 * * P4 *
-**
-** Open, release or rollback the savepoint named by parameter P4, depending
-** on the value of P1. To open a new savepoint, P1==0. To release (commit) an
-** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
-*/
-case OP_Savepoint: {
- int p1; /* Value of P1 operand */
- char *zName; /* Name of savepoint */
- int nName;
- Savepoint *pNew;
- Savepoint *pSavepoint;
- Savepoint *pTmp;
- int iSavepoint;
- int ii;
-
- p1 = pOp->p1;
- zName = pOp->p4.z;
-
- /* Assert that the p1 parameter is valid. Also that if there is no open
- ** transaction, then there cannot be any savepoints.
- */
- assert( db->pSavepoint==0 || db->autoCommit==0 );
- assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK );
- assert( db->pSavepoint || db->isTransactionSavepoint==0 );
- assert( checkSavepointCount(db) );
- assert( p->bIsReader );
-
- if( p1==SAVEPOINT_BEGIN ){
- if( db->nVdbeWrite>0 ){
- /* A new savepoint cannot be created if there are active write
- ** statements (i.e. open read/write incremental blob handles).
- */
- sqlite3VdbeError(p, "cannot open savepoint - SQL statements in progress");
- rc = SQLITE_BUSY;
- }else{
- nName = sqlite3Strlen30(zName);
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- /* This call is Ok even if this savepoint is actually a transaction
- ** savepoint (and therefore should not prompt xSavepoint()) callbacks.
- ** If this is a transaction savepoint being opened, it is guaranteed
- ** that the db->aVTrans[] array is empty. */
- assert( db->autoCommit==0 || db->nVTrans==0 );
- rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN,
- db->nStatement+db->nSavepoint);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
-#endif
-
- /* Create a new savepoint structure. */
- pNew = sqlite3DbMallocRawNN(db, sizeof(Savepoint)+nName+1);
- if( pNew ){
- pNew->zName = (char *)&pNew[1];
- memcpy(pNew->zName, zName, nName+1);
-
- /* If there is no open transaction, then mark this as a special
- ** "transaction savepoint". */
- if( db->autoCommit ){
- db->autoCommit = 0;
- db->isTransactionSavepoint = 1;
- }else{
- db->nSavepoint++;
- }
-
- /* Link the new savepoint into the database handle's list. */
- pNew->pNext = db->pSavepoint;
- db->pSavepoint = pNew;
- pNew->nDeferredCons = db->nDeferredCons;
- pNew->nDeferredImmCons = db->nDeferredImmCons;
- }
- }
- }else{
- iSavepoint = 0;
-
- /* Find the named savepoint. If there is no such savepoint, then an
- ** an error is returned to the user. */
- for(
- pSavepoint = db->pSavepoint;
- pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName);
- pSavepoint = pSavepoint->pNext
- ){
- iSavepoint++;
- }
- if( !pSavepoint ){
- sqlite3VdbeError(p, "no such savepoint: %s", zName);
- rc = SQLITE_ERROR;
- }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){
- /* It is not possible to release (commit) a savepoint if there are
- ** active write statements.
- */
- sqlite3VdbeError(p, "cannot release savepoint - "
- "SQL statements in progress");
- rc = SQLITE_BUSY;
- }else{
-
- /* Determine whether or not this is a transaction savepoint. If so,
- ** and this is a RELEASE command, then the current transaction
- ** is committed.
- */
- int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint;
- if( isTransaction && p1==SAVEPOINT_RELEASE ){
- if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
- goto vdbe_return;
- }
- db->autoCommit = 1;
- if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
- p->pc = (int)(pOp - aOp);
- db->autoCommit = 0;
- p->rc = rc = SQLITE_BUSY;
- goto vdbe_return;
- }
- db->isTransactionSavepoint = 0;
- rc = p->rc;
- }else{
- int isSchemaChange;
- iSavepoint = db->nSavepoint - iSavepoint - 1;
- if( p1==SAVEPOINT_ROLLBACK ){
- isSchemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0;
- for(ii=0; ii<db->nDb; ii++){
- rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt,
- SQLITE_ABORT_ROLLBACK,
- isSchemaChange==0);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- }
- }else{
- isSchemaChange = 0;
- }
- for(ii=0; ii<db->nDb; ii++){
- rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- }
- if( isSchemaChange ){
- sqlite3ExpirePreparedStatements(db);
- sqlite3ResetAllSchemasOfConnection(db);
- db->mDbFlags |= DBFLAG_SchemaChange;
- }
- }
-
- /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
- ** savepoints nested inside of the savepoint being operated on. */
- while( db->pSavepoint!=pSavepoint ){
- pTmp = db->pSavepoint;
- db->pSavepoint = pTmp->pNext;
- sqlite3DbFree(db, pTmp);
- db->nSavepoint--;
- }
-
- /* If it is a RELEASE, then destroy the savepoint being operated on
- ** too. If it is a ROLLBACK TO, then set the number of deferred
- ** constraint violations present in the database to the value stored
- ** when the savepoint was created. */
- if( p1==SAVEPOINT_RELEASE ){
- assert( pSavepoint==db->pSavepoint );
- db->pSavepoint = pSavepoint->pNext;
- sqlite3DbFree(db, pSavepoint);
- if( !isTransaction ){
- db->nSavepoint--;
- }
- }else{
- db->nDeferredCons = pSavepoint->nDeferredCons;
- db->nDeferredImmCons = pSavepoint->nDeferredImmCons;
- }
-
- if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){
- rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- }
- }
- }
- if( rc ) goto abort_due_to_error;
-
- break;
-}
-
-/* Opcode: AutoCommit P1 P2 * * *
-**
-** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll
-** back any currently active btree transactions. If there are any active
-** VMs (apart from this one), then a ROLLBACK fails. A COMMIT fails if
-** there are active writing VMs or active VMs that use shared cache.
-**
-** This instruction causes the VM to halt.
-*/
-case OP_AutoCommit: {
- int desiredAutoCommit;
- int iRollback;
-
- desiredAutoCommit = pOp->p1;
- iRollback = pOp->p2;
- assert( desiredAutoCommit==1 || desiredAutoCommit==0 );
- assert( desiredAutoCommit==1 || iRollback==0 );
- assert( db->nVdbeActive>0 ); /* At least this one VM is active */
- assert( p->bIsReader );
-
- if( desiredAutoCommit!=db->autoCommit ){
- if( iRollback ){
- assert( desiredAutoCommit==1 );
- sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
- db->autoCommit = 1;
- }else if( desiredAutoCommit && db->nVdbeWrite>0 ){
- /* If this instruction implements a COMMIT and other VMs are writing
- ** return an error indicating that the other VMs must complete first.
- */
- sqlite3VdbeError(p, "cannot commit transaction - "
- "SQL statements in progress");
- rc = SQLITE_BUSY;
- goto abort_due_to_error;
- }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
- goto vdbe_return;
- }else{
- db->autoCommit = (u8)desiredAutoCommit;
- }
- if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
- p->pc = (int)(pOp - aOp);
- db->autoCommit = (u8)(1-desiredAutoCommit);
- p->rc = rc = SQLITE_BUSY;
- goto vdbe_return;
- }
- assert( db->nStatement==0 );
- sqlite3CloseSavepoints(db);
- if( p->rc==SQLITE_OK ){
- rc = SQLITE_DONE;
- }else{
- rc = SQLITE_ERROR;
- }
- goto vdbe_return;
- }else{
- sqlite3VdbeError(p,
- (!desiredAutoCommit)?"cannot start a transaction within a transaction":(
- (iRollback)?"cannot rollback - no transaction is active":
- "cannot commit - no transaction is active"));
-
- rc = SQLITE_ERROR;
- goto abort_due_to_error;
- }
- break;
-}
-
-/* Opcode: Transaction P1 P2 P3 P4 P5
-**
-** Begin a transaction on database P1 if a transaction is not already
-** active.
-** If P2 is non-zero, then a write-transaction is started, or if a
-** read-transaction is already active, it is upgraded to a write-transaction.
-** If P2 is zero, then a read-transaction is started.
-**
-** P1 is the index of the database file on which the transaction is
-** started. Index 0 is the main database file and index 1 is the
-** file used for temporary tables. Indices of 2 or more are used for
-** attached databases.
-**
-** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
-** true (this flag is set if the Vdbe may modify more than one row and may
-** throw an ABORT exception), a statement transaction may also be opened.
-** More specifically, a statement transaction is opened iff the database
-** connection is currently not in autocommit mode, or if there are other
-** active statements. A statement transaction allows the changes made by this
-** VDBE to be rolled back after an error without having to roll back the
-** entire transaction. If no error is encountered, the statement transaction
-** will automatically commit when the VDBE halts.
-**
-** If P5!=0 then this opcode also checks the schema cookie against P3
-** and the schema generation counter against P4.
-** The cookie changes its value whenever the database schema changes.
-** This operation is used to detect when that the cookie has changed
-** and that the current process needs to reread the schema. If the schema
-** cookie in P3 differs from the schema cookie in the database header or
-** if the schema generation counter in P4 differs from the current
-** generation counter, then an SQLITE_SCHEMA error is raised and execution
-** halts. The sqlite3_step() wrapper function might then reprepare the
-** statement and rerun it from the beginning.
-*/
-case OP_Transaction: {
- Btree *pBt;
- int iMeta;
- int iGen;
-
- assert( p->bIsReader );
- assert( p->readOnly==0 || pOp->p2==0 );
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( DbMaskTest(p->btreeMask, pOp->p1) );
- if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
- rc = SQLITE_READONLY;
- goto abort_due_to_error;
- }
- pBt = db->aDb[pOp->p1].pBt;
-
- if( pBt ){
- rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
- testcase( rc==SQLITE_BUSY_SNAPSHOT );
- testcase( rc==SQLITE_BUSY_RECOVERY );
- if( rc!=SQLITE_OK ){
- if( (rc&0xff)==SQLITE_BUSY ){
- p->pc = (int)(pOp - aOp);
- p->rc = rc;
- goto vdbe_return;
- }
- goto abort_due_to_error;
- }
-
- if( pOp->p2 && p->usesStmtJournal
- && (db->autoCommit==0 || db->nVdbeRead>1)
- ){
- assert( sqlite3BtreeIsInTrans(pBt) );
- if( p->iStatement==0 ){
- assert( db->nStatement>=0 && db->nSavepoint>=0 );
- db->nStatement++;
- p->iStatement = db->nSavepoint + db->nStatement;
- }
-
- rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
- }
-
- /* Store the current value of the database handles deferred constraint
- ** counter. If the statement transaction needs to be rolled back,
- ** the value of this counter needs to be restored too. */
- p->nStmtDefCons = db->nDeferredCons;
- p->nStmtDefImmCons = db->nDeferredImmCons;
- }
-
- /* Gather the schema version number for checking:
- ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
- ** version is checked to ensure that the schema has not changed since the
- ** SQL statement was prepared.
- */
- sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
- iGen = db->aDb[pOp->p1].pSchema->iGeneration;
- }else{
- iGen = iMeta = 0;
- }
- assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
- if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
- /* If the schema-cookie from the database file matches the cookie
- ** stored with the in-memory representation of the schema, do
- ** not reload the schema from the database file.
- **
- ** If virtual-tables are in use, this is not just an optimization.
- ** Often, v-tables store their data in other SQLite tables, which
- ** are queried from within xNext() and other v-table methods using
- ** prepared queries. If such a query is out-of-date, we do not want to
- ** discard the database schema, as the user code implementing the
- ** v-table would have to be ready for the sqlite3_vtab structure itself
- ** to be invalidated whenever sqlite3_step() is called from within
- ** a v-table method.
- */
- if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
- sqlite3ResetOneSchema(db, pOp->p1);
- }
- p->expired = 1;
- rc = SQLITE_SCHEMA;
- }
- if( rc ) goto abort_due_to_error;
- break;
-}
-
-/* Opcode: ReadCookie P1 P2 P3 * *
-**
-** Read cookie number P3 from database P1 and write it into register P2.
-** P3==1 is the schema version. P3==2 is the database format.
-** P3==3 is the recommended pager cache size, and so forth. P1==0 is
-** the main database file and P1==1 is the database file used to store
-** temporary tables.
-**
-** There must be a read-lock on the database (either a transaction
-** must be started or there must be an open cursor) before
-** executing this instruction.
-*/
-case OP_ReadCookie: { /* out2 */
- int iMeta;
- int iDb;
- int iCookie;
-
- assert( p->bIsReader );
- iDb = pOp->p1;
- iCookie = pOp->p3;
- assert( pOp->p3<SQLITE_N_BTREE_META );
- assert( iDb>=0 && iDb<db->nDb );
- assert( db->aDb[iDb].pBt!=0 );
- assert( DbMaskTest(p->btreeMask, iDb) );
-
- sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
- pOut = out2Prerelease(p, pOp);
- pOut->u.i = iMeta;
- break;
-}
-
-/* Opcode: SetCookie P1 P2 P3 * *
-**
-** Write the integer value P3 into cookie number P2 of database P1.
-** P2==1 is the schema version. P2==2 is the database format.
-** P2==3 is the recommended pager cache
-** size, and so forth. P1==0 is the main database file and P1==1 is the
-** database file used to store temporary tables.
-**
-** A transaction must be started before executing this opcode.
-*/
-case OP_SetCookie: {
- Db *pDb;
-
- sqlite3VdbeIncrWriteCounter(p, 0);
- assert( pOp->p2<SQLITE_N_BTREE_META );
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( DbMaskTest(p->btreeMask, pOp->p1) );
- assert( p->readOnly==0 );
- pDb = &db->aDb[pOp->p1];
- assert( pDb->pBt!=0 );
- assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
- /* See note about index shifting on OP_ReadCookie */
- rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3);
- if( pOp->p2==BTREE_SCHEMA_VERSION ){
- /* When the schema cookie changes, record the new cookie internally */
- pDb->pSchema->schema_cookie = pOp->p3;
- db->mDbFlags |= DBFLAG_SchemaChange;
- }else if( pOp->p2==BTREE_FILE_FORMAT ){
- /* Record changes in the file format */
- pDb->pSchema->file_format = pOp->p3;
- }
- if( pOp->p1==1 ){
- /* Invalidate all prepared statements whenever the TEMP database
- ** schema is changed. Ticket #1644 */
- sqlite3ExpirePreparedStatements(db);
- p->expired = 0;
- }
- if( rc ) goto abort_due_to_error;
- break;
-}
-
-/* Opcode: OpenRead P1 P2 P3 P4 P5
-** Synopsis: root=P2 iDb=P3
-**
-** Open a read-only cursor for the database table whose root page is
-** P2 in a database file. The database file is determined by P3.
-** P3==0 means the main database, P3==1 means the database used for
-** temporary tables, and P3>1 means used the corresponding attached
-** database. Give the new cursor an identifier of P1. The P1
-** values need not be contiguous but all P1 values should be small integers.
-** It is an error for P1 to be negative.
-**
-** If P5!=0 then use the content of register P2 as the root page, not
-** the value of P2 itself.
-**
-** There will be a read lock on the database whenever there is an
-** open cursor. If the database was unlocked prior to this instruction
-** then a read lock is acquired as part of this instruction. A read
-** lock allows other processes to read the database but prohibits
-** any other process from modifying the database. The read lock is
-** released when all cursors are closed. If this instruction attempts
-** to get a read lock but fails, the script terminates with an
-** SQLITE_BUSY error code.
-**
-** The P4 value may be either an integer (P4_INT32) or a pointer to
-** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
-** structure, then said structure defines the content and collating
-** sequence of the index being opened. Otherwise, if P4 is an integer
-** value, it is set to the number of columns in the table.
-**
-** See also: OpenWrite, ReopenIdx
-*/
-/* Opcode: ReopenIdx P1 P2 P3 P4 P5
-** Synopsis: root=P2 iDb=P3
-**
-** The ReopenIdx opcode works exactly like ReadOpen except that it first
-** checks to see if the cursor on P1 is already open with a root page
-** number of P2 and if it is this opcode becomes a no-op. In other words,
-** if the cursor is already open, do not reopen it.
-**
-** The ReopenIdx opcode may only be used with P5==0 and with P4 being
-** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
-** every other ReopenIdx or OpenRead for the same cursor number.
-**
-** See the OpenRead opcode documentation for additional information.
-*/
-/* Opcode: OpenWrite P1 P2 P3 P4 P5
-** Synopsis: root=P2 iDb=P3
-**
-** Open a read/write cursor named P1 on the table or index whose root
-** page is P2. Or if P5!=0 use the content of register P2 to find the
-** root page.
-**
-** The P4 value may be either an integer (P4_INT32) or a pointer to
-** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
-** structure, then said structure defines the content and collating
-** sequence of the index being opened. Otherwise, if P4 is an integer
-** value, it is set to the number of columns in the table, or to the
-** largest index of any column of the table that is actually used.
-**
-** This instruction works just like OpenRead except that it opens the cursor
-** in read/write mode. For a given table, there can be one or more read-only
-** cursors or a single read/write cursor but not both.
-**
-** See also OpenRead.
-*/
-case OP_ReopenIdx: {
- int nField;
- KeyInfo *pKeyInfo;
- int p2;
- int iDb;
- int wrFlag;
- Btree *pX;
- VdbeCursor *pCur;
- Db *pDb;
-
- assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
- assert( pOp->p4type==P4_KEYINFO );
- pCur = p->apCsr[pOp->p1];
- if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
- assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
- goto open_cursor_set_hints;
- }
- /* If the cursor is not currently open or is open on a different
- ** index, then fall through into OP_OpenRead to force a reopen */
-case OP_OpenRead:
-case OP_OpenWrite:
-
- assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
- assert( p->bIsReader );
- assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
- || p->readOnly==0 );
-
- if( p->expired ){
- rc = SQLITE_ABORT_ROLLBACK;
- goto abort_due_to_error;
- }
-
- nField = 0;
- pKeyInfo = 0;
- p2 = pOp->p2;
- iDb = pOp->p3;
- assert( iDb>=0 && iDb<db->nDb );
- assert( DbMaskTest(p->btreeMask, iDb) );
- pDb = &db->aDb[iDb];
- pX = pDb->pBt;
- assert( pX!=0 );
- if( pOp->opcode==OP_OpenWrite ){
- assert( OPFLAG_FORDELETE==BTREE_FORDELETE );
- wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- if( pDb->pSchema->file_format < p->minWriteFileFormat ){
- p->minWriteFileFormat = pDb->pSchema->file_format;
- }
- }else{
- wrFlag = 0;
- }
- if( pOp->p5 & OPFLAG_P2ISREG ){
- assert( p2>0 );
- assert( p2<=(p->nMem+1 - p->nCursor) );
- pIn2 = &aMem[p2];
- assert( memIsValid(pIn2) );
- assert( (pIn2->flags & MEM_Int)!=0 );
- sqlite3VdbeMemIntegerify(pIn2);
- p2 = (int)pIn2->u.i;
- /* The p2 value always comes from a prior OP_CreateBtree opcode and
- ** that opcode will always set the p2 value to 2 or more or else fail.
- ** If there were a failure, the prepared statement would have halted
- ** before reaching this instruction. */
- assert( p2>=2 );
- }
- if( pOp->p4type==P4_KEYINFO ){
- pKeyInfo = pOp->p4.pKeyInfo;
- assert( pKeyInfo->enc==ENC(db) );
- assert( pKeyInfo->db==db );
- nField = pKeyInfo->nAllField;
- }else if( pOp->p4type==P4_INT32 ){
- nField = pOp->p4.i;
- }
- assert( pOp->p1>=0 );
- assert( nField>=0 );
- testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
- pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE);
- if( pCur==0 ) goto no_mem;
- pCur->nullRow = 1;
- pCur->isOrdered = 1;
- pCur->pgnoRoot = p2;
-#ifdef SQLITE_DEBUG
- pCur->wrFlag = wrFlag;
-#endif
- rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor);
- pCur->pKeyInfo = pKeyInfo;
- /* Set the VdbeCursor.isTable variable. Previous versions of
- ** SQLite used to check if the root-page flags were sane at this point
- ** and report database corruption if they were not, but this check has
- ** since moved into the btree layer. */
- pCur->isTable = pOp->p4type!=P4_KEYINFO;
-
-open_cursor_set_hints:
- assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
- assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
- testcase( pOp->p5 & OPFLAG_BULKCSR );
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
- testcase( pOp->p2 & OPFLAG_SEEKEQ );
-#endif
- sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
- (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
- if( rc ) goto abort_due_to_error;
- break;
-}
-
-/* Opcode: OpenDup P1 P2 * * *
-**
-** Open a new cursor P1 that points to the same ephemeral table as
-** cursor P2. The P2 cursor must have been opened by a prior OP_OpenEphemeral
-** opcode. Only ephemeral cursors may be duplicated.
-**
-** Duplicate ephemeral cursors are used for self-joins of materialized views.
-*/
-case OP_OpenDup: {
- VdbeCursor *pOrig; /* The original cursor to be duplicated */
- VdbeCursor *pCx; /* The new cursor */
-
- pOrig = p->apCsr[pOp->p2];
- assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
-
- pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
- if( pCx==0 ) goto no_mem;
- pCx->nullRow = 1;
- pCx->isEphemeral = 1;
- pCx->pKeyInfo = pOrig->pKeyInfo;
- pCx->isTable = pOrig->isTable;
- rc = sqlite3BtreeCursor(pOrig->pBtx, MASTER_ROOT, BTREE_WRCSR,
- pCx->pKeyInfo, pCx->uc.pCursor);
- /* The sqlite3BtreeCursor() routine can only fail for the first cursor
- ** opened for a database. Since there is already an open cursor when this
- ** opcode is run, the sqlite3BtreeCursor() cannot fail */
- assert( rc==SQLITE_OK );
- break;
-}
-
-
-/* Opcode: OpenEphemeral P1 P2 * P4 P5
-** Synopsis: nColumn=P2
-**
-** Open a new cursor P1 to a transient table.
-** The cursor is always opened read/write even if
-** the main database is read-only. The ephemeral
-** table is deleted automatically when the cursor is closed.
-**
-** P2 is the number of columns in the ephemeral table.
-** The cursor points to a BTree table if P4==0 and to a BTree index
-** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
-** that defines the format of keys in the index.
-**
-** The P5 parameter can be a mask of the BTREE_* flags defined
-** in btree.h. These flags control aspects of the operation of
-** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
-** added automatically.
-*/
-/* Opcode: OpenAutoindex P1 P2 * P4 *
-** Synopsis: nColumn=P2
-**
-** This opcode works the same as OP_OpenEphemeral. It has a
-** different name to distinguish its use. Tables created using
-** by this opcode will be used for automatically created transient
-** indices in joins.
-*/
-case OP_OpenAutoindex:
-case OP_OpenEphemeral: {
- VdbeCursor *pCx;
- KeyInfo *pKeyInfo;
-
- static const int vfsFlags =
- SQLITE_OPEN_READWRITE |
- SQLITE_OPEN_CREATE |
- SQLITE_OPEN_EXCLUSIVE |
- SQLITE_OPEN_DELETEONCLOSE |
- SQLITE_OPEN_TRANSIENT_DB;
- assert( pOp->p1>=0 );
- assert( pOp->p2>=0 );
- pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
- if( pCx==0 ) goto no_mem;
- pCx->nullRow = 1;
- pCx->isEphemeral = 1;
- rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
- BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1);
- }
- if( rc==SQLITE_OK ){
- /* If a transient index is required, create it by calling
- ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
- ** opening it. If a transient table is required, just use the
- ** automatically created table with root-page 1 (an BLOB_INTKEY table).
- */
- if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
- int pgno;
- assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5);
- if( rc==SQLITE_OK ){
- assert( pgno==MASTER_ROOT+1 );
- assert( pKeyInfo->db==db );
- assert( pKeyInfo->enc==ENC(db) );
- rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR,
- pKeyInfo, pCx->uc.pCursor);
- }
- pCx->isTable = 0;
- }else{
- rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR,
- 0, pCx->uc.pCursor);
- pCx->isTable = 1;
- }
- }
- if( rc ) goto abort_due_to_error;
- pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
- break;
-}
-
-/* Opcode: SorterOpen P1 P2 P3 P4 *
-**
-** This opcode works like OP_OpenEphemeral except that it opens
-** a transient index that is specifically designed to sort large
-** tables using an external merge-sort algorithm.
-**
-** If argument P3 is non-zero, then it indicates that the sorter may
-** assume that a stable sort considering the first P3 fields of each
-** key is sufficient to produce the required results.
-*/
-case OP_SorterOpen: {
- VdbeCursor *pCx;
-
- assert( pOp->p1>=0 );
- assert( pOp->p2>=0 );
- pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER);
- if( pCx==0 ) goto no_mem;
- pCx->pKeyInfo = pOp->p4.pKeyInfo;
- assert( pCx->pKeyInfo->db==db );
- assert( pCx->pKeyInfo->enc==ENC(db) );
- rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx);
- if( rc ) goto abort_due_to_error;
- break;
-}
-
-/* Opcode: SequenceTest P1 P2 * * *
-** Synopsis: if( cursor[P1].ctr++ ) pc = P2
-**
-** P1 is a sorter cursor. If the sequence counter is currently zero, jump
-** to P2. Regardless of whether or not the jump is taken, increment the
-** the sequence value.
-*/
-case OP_SequenceTest: {
- VdbeCursor *pC;
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( isSorter(pC) );
- if( (pC->seqCount++)==0 ){
- goto jump_to_p2;
- }
- break;
-}
-
-/* Opcode: OpenPseudo P1 P2 P3 * *
-** Synopsis: P3 columns in r[P2]
-**
-** Open a new cursor that points to a fake table that contains a single
-** row of data. The content of that one row is the content of memory
-** register P2. In other words, cursor P1 becomes an alias for the
-** MEM_Blob content contained in register P2.
-**
-** A pseudo-table created by this opcode is used to hold a single
-** row output from the sorter so that the row can be decomposed into
-** individual columns using the OP_Column opcode. The OP_Column opcode
-** is the only cursor opcode that works with a pseudo-table.
-**
-** P3 is the number of fields in the records that will be stored by
-** the pseudo-table.
-*/
-case OP_OpenPseudo: {
- VdbeCursor *pCx;
-
- assert( pOp->p1>=0 );
- assert( pOp->p3>=0 );
- pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO);
- if( pCx==0 ) goto no_mem;
- pCx->nullRow = 1;
- pCx->seekResult = pOp->p2;
- pCx->isTable = 1;
- /* Give this pseudo-cursor a fake BtCursor pointer so that pCx
- ** can be safely passed to sqlite3VdbeCursorMoveto(). This avoids a test
- ** for pCx->eCurType==CURTYPE_BTREE inside of sqlite3VdbeCursorMoveto()
- ** which is a performance optimization */
- pCx->uc.pCursor = sqlite3BtreeFakeValidCursor();
- assert( pOp->p5==0 );
- break;
-}
-
-/* Opcode: Close P1 * * * *
-**
-** Close a cursor previously opened as P1. If P1 is not
-** currently open, this instruction is a no-op.
-*/
-case OP_Close: {
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
- p->apCsr[pOp->p1] = 0;
- break;
-}
-
-#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
-/* Opcode: ColumnsUsed P1 * * P4 *
-**
-** This opcode (which only exists if SQLite was compiled with
-** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the
-** table or index for cursor P1 are used. P4 is a 64-bit integer
-** (P4_INT64) in which the first 63 bits are one for each of the
-** first 63 columns of the table or index that are actually used
-** by the cursor. The high-order bit is set if any column after
-** the 64th is used.
-*/
-case OP_ColumnsUsed: {
- VdbeCursor *pC;
- pC = p->apCsr[pOp->p1];
- assert( pC->eCurType==CURTYPE_BTREE );
- pC->maskUsed = *(u64*)pOp->p4.pI64;
- break;
-}
-#endif
-
-/* Opcode: SeekGE P1 P2 P3 P4 *
-** Synopsis: key=r[P3@P4]
-**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as the key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
-**
-** Reposition cursor P1 so that it points to the smallest entry that
-** is greater than or equal to the key value. If there are no records
-** greater than or equal to the key and P2 is not zero, then jump to P2.
-**
-** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
-** opcode will always land on a record that equally equals the key, or
-** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
-** opcode must be followed by an IdxLE opcode with the same arguments.
-** The IdxLE opcode will be skipped if this opcode succeeds, but the
-** IdxLE opcode will be used on subsequent loop iterations.
-**
-** This opcode leaves the cursor configured to move in forward order,
-** from the beginning toward the end. In other words, the cursor is
-** configured to use Next, not Prev.
-**
-** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
-*/
-/* Opcode: SeekGT P1 P2 P3 P4 *
-** Synopsis: key=r[P3@P4]
-**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
-**
-** Reposition cursor P1 so that it points to the smallest entry that
-** is greater than the key value. If there are no records greater than
-** the key and P2 is not zero, then jump to P2.
-**
-** This opcode leaves the cursor configured to move in forward order,
-** from the beginning toward the end. In other words, the cursor is
-** configured to use Next, not Prev.
-**
-** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
-*/
-/* Opcode: SeekLT P1 P2 P3 P4 *
-** Synopsis: key=r[P3@P4]
-**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
-**
-** Reposition cursor P1 so that it points to the largest entry that
-** is less than the key value. If there are no records less than
-** the key and P2 is not zero, then jump to P2.
-**
-** This opcode leaves the cursor configured to move in reverse order,
-** from the end toward the beginning. In other words, the cursor is
-** configured to use Prev, not Next.
-**
-** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
-*/
-/* Opcode: SeekLE P1 P2 P3 P4 *
-** Synopsis: key=r[P3@P4]
-**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
-**
-** Reposition cursor P1 so that it points to the largest entry that
-** is less than or equal to the key value. If there are no records
-** less than or equal to the key and P2 is not zero, then jump to P2.
-**
-** This opcode leaves the cursor configured to move in reverse order,
-** from the end toward the beginning. In other words, the cursor is
-** configured to use Prev, not Next.
-**
-** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
-** opcode will always land on a record that equally equals the key, or
-** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
-** opcode must be followed by an IdxGE opcode with the same arguments.
-** The IdxGE opcode will be skipped if this opcode succeeds, but the
-** IdxGE opcode will be used on subsequent loop iterations.
-**
-** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
-*/
-case OP_SeekLT: /* jump, in3 */
-case OP_SeekLE: /* jump, in3 */
-case OP_SeekGE: /* jump, in3 */
-case OP_SeekGT: { /* jump, in3 */
- int res; /* Comparison result */
- int oc; /* Opcode */
- VdbeCursor *pC; /* The cursor to seek */
- UnpackedRecord r; /* The key to seek for */
- int nField; /* Number of columns or fields in the key */
- i64 iKey; /* The rowid we are to seek to */
- int eqOnly; /* Only interested in == results */
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( pOp->p2!=0 );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( OP_SeekLE == OP_SeekLT+1 );
- assert( OP_SeekGE == OP_SeekLT+2 );
- assert( OP_SeekGT == OP_SeekLT+3 );
- assert( pC->isOrdered );
- assert( pC->uc.pCursor!=0 );
- oc = pOp->opcode;
- eqOnly = 0;
- pC->nullRow = 0;
-#ifdef SQLITE_DEBUG
- pC->seekOp = pOp->opcode;
-#endif
-
- if( pC->isTable ){
- /* The BTREE_SEEK_EQ flag is only set on index cursors */
- assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
- || CORRUPT_DB );
-
- /* The input value in P3 might be of any type: integer, real, string,
- ** blob, or NULL. But it needs to be an integer before we can do
- ** the seek, so convert it. */
- pIn3 = &aMem[pOp->p3];
- if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
- applyNumericAffinity(pIn3, 0);
- }
- iKey = sqlite3VdbeIntValue(pIn3);
-
- /* If the P3 value could not be converted into an integer without
- ** loss of information, then special processing is required... */
- if( (pIn3->flags & MEM_Int)==0 ){
- if( (pIn3->flags & MEM_Real)==0 ){
- /* If the P3 value cannot be converted into any kind of a number,
- ** then the seek is not possible, so jump to P2 */
- VdbeBranchTaken(1,2); goto jump_to_p2;
- break;
- }
-
- /* If the approximation iKey is larger than the actual real search
- ** term, substitute >= for > and < for <=. e.g. if the search term
- ** is 4.9 and the integer approximation 5:
- **
- ** (x > 4.9) -> (x >= 5)
- ** (x <= 4.9) -> (x < 5)
- */
- if( pIn3->u.r<(double)iKey ){
- assert( OP_SeekGE==(OP_SeekGT-1) );
- assert( OP_SeekLT==(OP_SeekLE-1) );
- assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
- if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
- }
-
- /* If the approximation iKey is smaller than the actual real search
- ** term, substitute <= for < and > for >=. */
- else if( pIn3->u.r>(double)iKey ){
- assert( OP_SeekLE==(OP_SeekLT+1) );
- assert( OP_SeekGT==(OP_SeekGE+1) );
- assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
- if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
- }
- }
- rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res);
- pC->movetoTarget = iKey; /* Used by OP_Delete */
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- }else{
- /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
- ** OP_SeekLE opcodes are allowed, and these must be immediately followed
- ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
- */
- if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){
- eqOnly = 1;
- assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
- assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
- assert( pOp[1].p1==pOp[0].p1 );
- assert( pOp[1].p2==pOp[0].p2 );
- assert( pOp[1].p3==pOp[0].p3 );
- assert( pOp[1].p4.i==pOp[0].p4.i );
- }
-
- nField = pOp->p4.i;
- assert( pOp->p4type==P4_INT32 );
- assert( nField>0 );
- r.pKeyInfo = pC->pKeyInfo;
- r.nField = (u16)nField;
-
- /* The next line of code computes as follows, only faster:
- ** if( oc==OP_SeekGT || oc==OP_SeekLE ){
- ** r.default_rc = -1;
- ** }else{
- ** r.default_rc = +1;
- ** }
- */
- r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1);
- assert( oc!=OP_SeekGT || r.default_rc==-1 );
- assert( oc!=OP_SeekLE || r.default_rc==-1 );
- assert( oc!=OP_SeekGE || r.default_rc==+1 );
- assert( oc!=OP_SeekLT || r.default_rc==+1 );
-
- r.aMem = &aMem[pOp->p3];
-#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
-#endif
- r.eqSeen = 0;
- rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- if( eqOnly && r.eqSeen==0 ){
- assert( res!=0 );
- goto seek_not_found;
- }
- }
- pC->deferredMoveto = 0;
- pC->cacheStatus = CACHE_STALE;
-#ifdef SQLITE_TEST
- sqlite3_search_count++;
-#endif
- if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT );
- if( res<0 || (res==0 && oc==OP_SeekGT) ){
- res = 0;
- rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- res = 1;
- }else{
- goto abort_due_to_error;
- }
- }
- }else{
- res = 0;
- }
- }else{
- assert( oc==OP_SeekLT || oc==OP_SeekLE );
- if( res>0 || (res==0 && oc==OP_SeekLT) ){
- res = 0;
- rc = sqlite3BtreePrevious(pC->uc.pCursor, 0);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- res = 1;
- }else{
- goto abort_due_to_error;
- }
- }
- }else{
- /* res might be negative because the table is empty. Check to
- ** see if this is the case.
- */
- res = sqlite3BtreeEof(pC->uc.pCursor);
- }
- }
-seek_not_found:
- assert( pOp->p2>0 );
- VdbeBranchTaken(res!=0,2);
- if( res ){
- goto jump_to_p2;
- }else if( eqOnly ){
- assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
- pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
- }
- break;
-}
-
-/* Opcode: Found P1 P2 P3 P4 *
-** Synopsis: key=r[P3@P4]
-**
-** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
-** P4>0 then register P3 is the first of P4 registers that form an unpacked
-** record.
-**
-** Cursor P1 is on an index btree. If the record identified by P3 and P4
-** is a prefix of any entry in P1 then a jump is made to P2 and
-** P1 is left pointing at the matching entry.
-**
-** This operation leaves the cursor in a state where it can be
-** advanced in the forward direction. The Next instruction will work,
-** but not the Prev instruction.
-**
-** See also: NotFound, NoConflict, NotExists. SeekGe
-*/
-/* Opcode: NotFound P1 P2 P3 P4 *
-** Synopsis: key=r[P3@P4]
-**
-** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
-** P4>0 then register P3 is the first of P4 registers that form an unpacked
-** record.
-**
-** Cursor P1 is on an index btree. If the record identified by P3 and P4
-** is not the prefix of any entry in P1 then a jump is made to P2. If P1
-** does contain an entry whose prefix matches the P3/P4 record then control
-** falls through to the next instruction and P1 is left pointing at the
-** matching entry.
-**
-** This operation leaves the cursor in a state where it cannot be
-** advanced in either direction. In other words, the Next and Prev
-** opcodes do not work after this operation.
-**
-** See also: Found, NotExists, NoConflict
-*/
-/* Opcode: NoConflict P1 P2 P3 P4 *
-** Synopsis: key=r[P3@P4]
-**
-** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
-** P4>0 then register P3 is the first of P4 registers that form an unpacked
-** record.
-**
-** Cursor P1 is on an index btree. If the record identified by P3 and P4
-** contains any NULL value, jump immediately to P2. If all terms of the
-** record are not-NULL then a check is done to determine if any row in the
-** P1 index btree has a matching key prefix. If there are no matches, jump
-** immediately to P2. If there is a match, fall through and leave the P1
-** cursor pointing to the matching row.
-**
-** This opcode is similar to OP_NotFound with the exceptions that the
-** branch is always taken if any part of the search key input is NULL.
-**
-** This operation leaves the cursor in a state where it cannot be
-** advanced in either direction. In other words, the Next and Prev
-** opcodes do not work after this operation.
-**
-** See also: NotFound, Found, NotExists
-*/
-case OP_NoConflict: /* jump, in3 */
-case OP_NotFound: /* jump, in3 */
-case OP_Found: { /* jump, in3 */
- int alreadyExists;
- int takeJump;
- int ii;
- VdbeCursor *pC;
- int res;
- UnpackedRecord *pFree;
- UnpackedRecord *pIdxKey;
- UnpackedRecord r;
-
-#ifdef SQLITE_TEST
- if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
-#endif
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( pOp->p4type==P4_INT32 );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
-#ifdef SQLITE_DEBUG
- pC->seekOp = pOp->opcode;
-#endif
- pIn3 = &aMem[pOp->p3];
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pC->uc.pCursor!=0 );
- assert( pC->isTable==0 );
- if( pOp->p4.i>0 ){
- r.pKeyInfo = pC->pKeyInfo;
- r.nField = (u16)pOp->p4.i;
- r.aMem = pIn3;
-#ifdef SQLITE_DEBUG
- for(ii=0; ii<r.nField; ii++){
- assert( memIsValid(&r.aMem[ii]) );
- assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
- if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
- }
-#endif
- pIdxKey = &r;
- pFree = 0;
- }else{
- assert( pIn3->flags & MEM_Blob );
- rc = ExpandBlob(pIn3);
- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
- if( rc ) goto no_mem;
- pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
- if( pIdxKey==0 ) goto no_mem;
- sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
- }
- pIdxKey->default_rc = 0;
- takeJump = 0;
- if( pOp->opcode==OP_NoConflict ){
- /* For the OP_NoConflict opcode, take the jump if any of the
- ** input fields are NULL, since any key with a NULL will not
- ** conflict */
- for(ii=0; ii<pIdxKey->nField; ii++){
- if( pIdxKey->aMem[ii].flags & MEM_Null ){
- takeJump = 1;
- break;
- }
- }
- }
- rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
- if( pFree ) sqlite3DbFreeNN(db, pFree);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- pC->seekResult = res;
- alreadyExists = (res==0);
- pC->nullRow = 1-alreadyExists;
- pC->deferredMoveto = 0;
- pC->cacheStatus = CACHE_STALE;
- if( pOp->opcode==OP_Found ){
- VdbeBranchTaken(alreadyExists!=0,2);
- if( alreadyExists ) goto jump_to_p2;
- }else{
- VdbeBranchTaken(takeJump||alreadyExists==0,2);
- if( takeJump || !alreadyExists ) goto jump_to_p2;
- }
- break;
-}
-
-/* Opcode: SeekRowid P1 P2 P3 * *
-** Synopsis: intkey=r[P3]
-**
-** P1 is the index of a cursor open on an SQL table btree (with integer
-** keys). If register P3 does not contain an integer or if P1 does not
-** contain a record with rowid P3 then jump immediately to P2.
-** Or, if P2 is 0, raise an SQLITE_CORRUPT error. If P1 does contain
-** a record with rowid P3 then
-** leave the cursor pointing at that record and fall through to the next
-** instruction.
-**
-** The OP_NotExists opcode performs the same operation, but with OP_NotExists
-** the P3 register must be guaranteed to contain an integer value. With this
-** opcode, register P3 might not contain an integer.
-**
-** The OP_NotFound opcode performs the same operation on index btrees
-** (with arbitrary multi-value keys).
-**
-** This opcode leaves the cursor in a state where it cannot be advanced
-** in either direction. In other words, the Next and Prev opcodes will
-** not work following this opcode.
-**
-** See also: Found, NotFound, NoConflict, SeekRowid
-*/
-/* Opcode: NotExists P1 P2 P3 * *
-** Synopsis: intkey=r[P3]
-**
-** P1 is the index of a cursor open on an SQL table btree (with integer
-** keys). P3 is an integer rowid. If P1 does not contain a record with
-** rowid P3 then jump immediately to P2. Or, if P2 is 0, raise an
-** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then
-** leave the cursor pointing at that record and fall through to the next
-** instruction.
-**
-** The OP_SeekRowid opcode performs the same operation but also allows the
-** P3 register to contain a non-integer value, in which case the jump is
-** always taken. This opcode requires that P3 always contain an integer.
-**
-** The OP_NotFound opcode performs the same operation on index btrees
-** (with arbitrary multi-value keys).
-**
-** This opcode leaves the cursor in a state where it cannot be advanced
-** in either direction. In other words, the Next and Prev opcodes will
-** not work following this opcode.
-**
-** See also: Found, NotFound, NoConflict, SeekRowid
-*/
-case OP_SeekRowid: { /* jump, in3 */
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
- u64 iKey;
-
- pIn3 = &aMem[pOp->p3];
- if( (pIn3->flags & MEM_Int)==0 ){
- applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding);
- if( (pIn3->flags & MEM_Int)==0 ) goto jump_to_p2;
- }
- /* Fall through into OP_NotExists */
-case OP_NotExists: /* jump, in3 */
- pIn3 = &aMem[pOp->p3];
- assert( pIn3->flags & MEM_Int );
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
-#ifdef SQLITE_DEBUG
- pC->seekOp = 0;
-#endif
- assert( pC->isTable );
- assert( pC->eCurType==CURTYPE_BTREE );
- pCrsr = pC->uc.pCursor;
- assert( pCrsr!=0 );
- res = 0;
- iKey = pIn3->u.i;
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
- assert( rc==SQLITE_OK || res==0 );
- pC->movetoTarget = iKey; /* Used by OP_Delete */
- pC->nullRow = 0;
- pC->cacheStatus = CACHE_STALE;
- pC->deferredMoveto = 0;
- VdbeBranchTaken(res!=0,2);
- pC->seekResult = res;
- if( res!=0 ){
- assert( rc==SQLITE_OK );
- if( pOp->p2==0 ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- goto jump_to_p2;
- }
- }
- if( rc ) goto abort_due_to_error;
- break;
-}
-
-/* Opcode: Sequence P1 P2 * * *
-** Synopsis: r[P2]=cursor[P1].ctr++
-**
-** Find the next available sequence number for cursor P1.
-** Write the sequence number into register P2.
-** The sequence number on the cursor is incremented after this
-** instruction.
-*/
-case OP_Sequence: { /* out2 */
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( p->apCsr[pOp->p1]!=0 );
- assert( p->apCsr[pOp->p1]->eCurType!=CURTYPE_VTAB );
- pOut = out2Prerelease(p, pOp);
- pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
- break;
-}
-
-
-/* Opcode: NewRowid P1 P2 P3 * *
-** Synopsis: r[P2]=rowid
-**
-** Get a new integer record number (a.k.a "rowid") used as the key to a table.
-** The record number is not previously used as a key in the database
-** table that cursor P1 points to. The new record number is written
-** written to register P2.
-**
-** If P3>0 then P3 is a register in the root frame of this VDBE that holds
-** the largest previously generated record number. No new record numbers are
-** allowed to be less than this value. When this value reaches its maximum,
-** an SQLITE_FULL error is generated. The P3 register is updated with the '
-** generated record number. This P3 mechanism is used to help implement the
-** AUTOINCREMENT feature.
-*/
-case OP_NewRowid: { /* out2 */
- i64 v; /* The new rowid */
- VdbeCursor *pC; /* Cursor of table to get the new rowid */
- int res; /* Result of an sqlite3BtreeLast() */
- int cnt; /* Counter to limit the number of searches */
- Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
- VdbeFrame *pFrame; /* Root frame of VDBE */
-
- v = 0;
- res = 0;
- pOut = out2Prerelease(p, pOp);
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->isTable );
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pC->uc.pCursor!=0 );
- {
- /* The next rowid or record number (different terms for the same
- ** thing) is obtained in a two-step algorithm.
- **
- ** First we attempt to find the largest existing rowid and add one
- ** to that. But if the largest existing rowid is already the maximum
- ** positive integer, we have to fall through to the second
- ** probabilistic algorithm
- **
- ** The second algorithm is to select a rowid at random and see if
- ** it already exists in the table. If it does not exist, we have
- ** succeeded. If the random rowid does exist, we select a new one
- ** and try again, up to 100 times.
- */
- assert( pC->isTable );
-
-#ifdef SQLITE_32BIT_ROWID
-# define MAX_ROWID 0x7fffffff
-#else
- /* Some compilers complain about constants of the form 0x7fffffffffffffff.
- ** Others complain about 0x7ffffffffffffffffLL. The following macro seems
- ** to provide the constant while making all compilers happy.
- */
-# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
-#endif
-
- if( !pC->useRandomRowid ){
- rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- if( res ){
- v = 1; /* IMP: R-61914-48074 */
- }else{
- assert( sqlite3BtreeCursorIsValid(pC->uc.pCursor) );
- v = sqlite3BtreeIntegerKey(pC->uc.pCursor);
- if( v>=MAX_ROWID ){
- pC->useRandomRowid = 1;
- }else{
- v++; /* IMP: R-29538-34987 */
- }
- }
- }
-
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- if( pOp->p3 ){
- /* Assert that P3 is a valid memory cell. */
- assert( pOp->p3>0 );
- if( p->pFrame ){
- for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
- /* Assert that P3 is a valid memory cell. */
- assert( pOp->p3<=pFrame->nMem );
- pMem = &pFrame->aMem[pOp->p3];
- }else{
- /* Assert that P3 is a valid memory cell. */
- assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
- pMem = &aMem[pOp->p3];
- memAboutToChange(p, pMem);
- }
- assert( memIsValid(pMem) );
-
- REGISTER_TRACE(pOp->p3, pMem);
- sqlite3VdbeMemIntegerify(pMem);
- assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
- if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
- rc = SQLITE_FULL; /* IMP: R-17817-00630 */
- goto abort_due_to_error;
- }
- if( v<pMem->u.i+1 ){
- v = pMem->u.i + 1;
- }
- pMem->u.i = v;
- }
-#endif
- if( pC->useRandomRowid ){
- /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
- ** largest possible integer (9223372036854775807) then the database
- ** engine starts picking positive candidate ROWIDs at random until
- ** it finds one that is not previously used. */
- assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
- ** an AUTOINCREMENT table. */
- cnt = 0;
- do{
- sqlite3_randomness(sizeof(v), &v);
- v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
- }while( ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v,
- 0, &res))==SQLITE_OK)
- && (res==0)
- && (++cnt<100));
- if( rc ) goto abort_due_to_error;
- if( res==0 ){
- rc = SQLITE_FULL; /* IMP: R-38219-53002 */
- goto abort_due_to_error;
- }
- assert( v>0 ); /* EV: R-40812-03570 */
- }
- pC->deferredMoveto = 0;
- pC->cacheStatus = CACHE_STALE;
- }
- pOut->u.i = v;
- break;
-}
-
-/* Opcode: Insert P1 P2 P3 P4 P5
-** Synopsis: intkey=r[P3] data=r[P2]
-**
-** Write an entry into the table of cursor P1. A new entry is
-** created if it doesn't already exist or the data for an existing
-** entry is overwritten. The data is the value MEM_Blob stored in register
-** number P2. The key is stored in register P3. The key must
-** be a MEM_Int.
-**
-** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
-** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set,
-** then rowid is stored for subsequent return by the
-** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
-**
-** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
-** run faster by avoiding an unnecessary seek on cursor P1. However,
-** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
-** seeks on the cursor or if the most recent seek used a key equal to P3.
-**
-** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
-** UPDATE operation. Otherwise (if the flag is clear) then this opcode
-** is part of an INSERT operation. The difference is only important to
-** the update hook.
-**
-** Parameter P4 may point to a Table structure, or may be NULL. If it is
-** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked
-** following a successful insert.
-**
-** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically
-** allocated, then ownership of P2 is transferred to the pseudo-cursor
-** and register P2 becomes ephemeral. If the cursor is changed, the
-** value of register P2 will then change. Make sure this does not
-** cause any problems.)
-**
-** This instruction only works on tables. The equivalent instruction
-** for indices is OP_IdxInsert.
-*/
-/* Opcode: InsertInt P1 P2 P3 P4 P5
-** Synopsis: intkey=P3 data=r[P2]
-**
-** This works exactly like OP_Insert except that the key is the
-** integer value P3, not the value of the integer stored in register P3.
-*/
-case OP_Insert:
-case OP_InsertInt: {
- Mem *pData; /* MEM cell holding data for the record to be inserted */
- Mem *pKey; /* MEM cell holding key for the record */
- VdbeCursor *pC; /* Cursor to table into which insert is written */
- int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
- const char *zDb; /* database name - used by the update hook */
- Table *pTab; /* Table structure - used by update and pre-update hooks */
- BtreePayload x; /* Payload to be inserted */
-
- pData = &aMem[pOp->p2];
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( memIsValid(pData) );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pC->uc.pCursor!=0 );
- assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
- assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
- REGISTER_TRACE(pOp->p2, pData);
- sqlite3VdbeIncrWriteCounter(p, pC);
-
- if( pOp->opcode==OP_Insert ){
- pKey = &aMem[pOp->p3];
- assert( pKey->flags & MEM_Int );
- assert( memIsValid(pKey) );
- REGISTER_TRACE(pOp->p3, pKey);
- x.nKey = pKey->u.i;
- }else{
- assert( pOp->opcode==OP_InsertInt );
- x.nKey = pOp->p3;
- }
-
- if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
- assert( pC->iDb>=0 );
- zDb = db->aDb[pC->iDb].zDbSName;
- pTab = pOp->p4.pTab;
- assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
- }else{
- pTab = 0;
- zDb = 0; /* Not needed. Silence a compiler warning. */
- }
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- /* Invoke the pre-update hook, if any */
- if( pTab ){
- if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
- sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
- }
- if( db->xUpdateCallback==0 || pTab->aCol==0 ){
- /* Prevent post-update hook from running in cases when it should not */
- pTab = 0;
- }
- }
- if( pOp->p5 & OPFLAG_ISNOOP ) break;
-#endif
-
- if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
- assert( pData->flags & (MEM_Blob|MEM_Str) );
- x.pData = pData->z;
- x.nData = pData->n;
- seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
- if( pData->flags & MEM_Zero ){
- x.nZero = pData->u.nZero;
- }else{
- x.nZero = 0;
- }
- x.pKey = 0;
- rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
- );
- pC->deferredMoveto = 0;
- pC->cacheStatus = CACHE_STALE;
-
- /* Invoke the update-hook if required. */
- if( rc ) goto abort_due_to_error;
- if( pTab ){
- assert( db->xUpdateCallback!=0 );
- assert( pTab->aCol!=0 );
- db->xUpdateCallback(db->pUpdateArg,
- (pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT,
- zDb, pTab->zName, x.nKey);
- }
- break;
-}
-
-/* Opcode: Delete P1 P2 P3 P4 P5
-**
-** Delete the record at which the P1 cursor is currently pointing.
-**
-** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then
-** the cursor will be left pointing at either the next or the previous
-** record in the table. If it is left pointing at the next record, then
-** the next Next instruction will be a no-op. As a result, in this case
-** it is ok to delete a record from within a Next loop. If
-** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be
-** left in an undefined state.
-**
-** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this
-** delete one of several associated with deleting a table row and all its
-** associated index entries. Exactly one of those deletes is the "primary"
-** delete. The others are all on OPFLAG_FORDELETE cursors or else are
-** marked with the AUXDELETE flag.
-**
-** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row
-** change count is incremented (otherwise not).
-**
-** P1 must not be pseudo-table. It has to be a real table with
-** multiple rows.
-**
-** If P4 is not NULL then it points to a Table object. In this case either
-** the update or pre-update hook, or both, may be invoked. The P1 cursor must
-** have been positioned using OP_NotFound prior to invoking this opcode in
-** this case. Specifically, if one is configured, the pre-update hook is
-** invoked if P4 is not NULL. The update-hook is invoked if one is configured,
-** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2.
-**
-** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address
-** of the memory cell that contains the value that the rowid of the row will
-** be set to by the update.
-*/
-case OP_Delete: {
- VdbeCursor *pC;
- const char *zDb;
- Table *pTab;
- int opflags;
-
- opflags = pOp->p2;
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pC->uc.pCursor!=0 );
- assert( pC->deferredMoveto==0 );
- sqlite3VdbeIncrWriteCounter(p, pC);
-
-#ifdef SQLITE_DEBUG
- if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){
- /* If p5 is zero, the seek operation that positioned the cursor prior to
- ** OP_Delete will have also set the pC->movetoTarget field to the rowid of
- ** the row that is being deleted */
- i64 iKey = sqlite3BtreeIntegerKey(pC->uc.pCursor);
- assert( pC->movetoTarget==iKey );
- }
-#endif
-
- /* If the update-hook or pre-update-hook will be invoked, set zDb to
- ** the name of the db to pass as to it. Also set local pTab to a copy
- ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was
- ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set
- ** VdbeCursor.movetoTarget to the current rowid. */
- if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
- assert( pC->iDb>=0 );
- assert( pOp->p4.pTab!=0 );
- zDb = db->aDb[pC->iDb].zDbSName;
- pTab = pOp->p4.pTab;
- if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){
- pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor);
- }
- }else{
- zDb = 0; /* Not needed. Silence a compiler warning. */
- pTab = 0; /* Not needed. Silence a compiler warning. */
- }
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- /* Invoke the pre-update-hook if required. */
- if( db->xPreUpdateCallback && pOp->p4.pTab ){
- assert( !(opflags & OPFLAG_ISUPDATE)
- || HasRowid(pTab)==0
- || (aMem[pOp->p3].flags & MEM_Int)
- );
- sqlite3VdbePreUpdateHook(p, pC,
- (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
- zDb, pTab, pC->movetoTarget,
- pOp->p3
- );
- }
- if( opflags & OPFLAG_ISNOOP ) break;
-#endif
-
- /* Only flags that can be set are SAVEPOISTION and AUXDELETE */
- assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 );
- assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION );
- assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE );
-
-#ifdef SQLITE_DEBUG
- if( p->pFrame==0 ){
- if( pC->isEphemeral==0
- && (pOp->p5 & OPFLAG_AUXDELETE)==0
- && (pC->wrFlag & OPFLAG_FORDELETE)==0
- ){
- nExtraDelete++;
- }
- if( pOp->p2 & OPFLAG_NCHANGE ){
- nExtraDelete--;
- }
- }
-#endif
-
- rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5);
- pC->cacheStatus = CACHE_STALE;
- pC->seekResult = 0;
- if( rc ) goto abort_due_to_error;
-
- /* Invoke the update-hook if required. */
- if( opflags & OPFLAG_NCHANGE ){
- p->nChange++;
- if( db->xUpdateCallback && HasRowid(pTab) ){
- db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,
- pC->movetoTarget);
- assert( pC->iDb>=0 );
- }
- }
-
- break;
-}
-/* Opcode: ResetCount * * * * *
-**
-** The value of the change counter is copied to the database handle
-** change counter (returned by subsequent calls to sqlite3_changes()).
-** Then the VMs internal change counter resets to 0.
-** This is used by trigger programs.
-*/
-case OP_ResetCount: {
- sqlite3VdbeSetChanges(db, p->nChange);
- p->nChange = 0;
- break;
-}
-
-/* Opcode: SorterCompare P1 P2 P3 P4
-** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2
-**
-** P1 is a sorter cursor. This instruction compares a prefix of the
-** record blob in register P3 against a prefix of the entry that
-** the sorter cursor currently points to. Only the first P4 fields
-** of r[P3] and the sorter record are compared.
-**
-** If either P3 or the sorter contains a NULL in one of their significant
-** fields (not counting the P4 fields at the end which are ignored) then
-** the comparison is assumed to be equal.
-**
-** Fall through to next instruction if the two records compare equal to
-** each other. Jump to P2 if they are different.
-*/
-case OP_SorterCompare: {
- VdbeCursor *pC;
- int res;
- int nKeyCol;
-
- pC = p->apCsr[pOp->p1];
- assert( isSorter(pC) );
- assert( pOp->p4type==P4_INT32 );
- pIn3 = &aMem[pOp->p3];
- nKeyCol = pOp->p4.i;
- res = 0;
- rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res);
- VdbeBranchTaken(res!=0,2);
- if( rc ) goto abort_due_to_error;
- if( res ) goto jump_to_p2;
- break;
-};
-
-/* Opcode: SorterData P1 P2 P3 * *
-** Synopsis: r[P2]=data
-**
-** Write into register P2 the current sorter data for sorter cursor P1.
-** Then clear the column header cache on cursor P3.
-**
-** This opcode is normally use to move a record out of the sorter and into
-** a register that is the source for a pseudo-table cursor created using
-** OpenPseudo. That pseudo-table cursor is the one that is identified by
-** parameter P3. Clearing the P3 column cache as part of this opcode saves
-** us from having to issue a separate NullRow instruction to clear that cache.
-*/
-case OP_SorterData: {
- VdbeCursor *pC;
-
- pOut = &aMem[pOp->p2];
- pC = p->apCsr[pOp->p1];
- assert( isSorter(pC) );
- rc = sqlite3VdbeSorterRowkey(pC, pOut);
- assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) );
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- if( rc ) goto abort_due_to_error;
- p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE;
- break;
-}
-
-/* Opcode: RowData P1 P2 P3 * *
-** Synopsis: r[P2]=data
-**
-** Write into register P2 the complete row content for the row at
-** which cursor P1 is currently pointing.
-** There is no interpretation of the data.
-** It is just copied onto the P2 register exactly as
-** it is found in the database file.
-**
-** If cursor P1 is an index, then the content is the key of the row.
-** If cursor P2 is a table, then the content extracted is the data.
-**
-** If the P1 cursor must be pointing to a valid row (not a NULL row)
-** of a real table, not a pseudo-table.
-**
-** If P3!=0 then this opcode is allowed to make an ephemeral pointer
-** into the database page. That means that the content of the output
-** register will be invalidated as soon as the cursor moves - including
-** moves caused by other cursors that "save" the current cursors
-** position in order that they can write to the same table. If P3==0
-** then a copy of the data is made into memory. P3!=0 is faster, but
-** P3==0 is safer.
-**
-** If P3!=0 then the content of the P2 register is unsuitable for use
-** in OP_Result and any OP_Result will invalidate the P2 register content.
-** The P2 register content is invalidated by opcodes like OP_Function or
-** by any use of another cursor pointing to the same table.
-*/
-case OP_RowData: {
- VdbeCursor *pC;
- BtCursor *pCrsr;
- u32 n;
-
- pOut = out2Prerelease(p, pOp);
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( isSorter(pC)==0 );
- assert( pC->nullRow==0 );
- assert( pC->uc.pCursor!=0 );
- pCrsr = pC->uc.pCursor;
-
- /* The OP_RowData opcodes always follow OP_NotExists or
- ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
- ** that might invalidate the cursor.
- ** If this where not the case, on of the following assert()s
- ** would fail. Should this ever change (because of changes in the code
- ** generator) then the fix would be to insert a call to
- ** sqlite3VdbeCursorMoveto().
- */
- assert( pC->deferredMoveto==0 );
- assert( sqlite3BtreeCursorIsValid(pCrsr) );
-#if 0 /* Not required due to the previous to assert() statements */
- rc = sqlite3VdbeCursorMoveto(pC);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
-#endif
-
- n = sqlite3BtreePayloadSize(pCrsr);
- if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
- testcase( n==0 );
- rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut);
- if( rc ) goto abort_due_to_error;
- if( !pOp->p3 ) Deephemeralize(pOut);
- UPDATE_MAX_BLOBSIZE(pOut);
- REGISTER_TRACE(pOp->p2, pOut);
- break;
-}
-
-/* Opcode: Rowid P1 P2 * * *
-** Synopsis: r[P2]=rowid
-**
-** Store in register P2 an integer which is the key of the table entry that
-** P1 is currently point to.
-**
-** P1 can be either an ordinary table or a virtual table. There used to
-** be a separate OP_VRowid opcode for use with virtual tables, but this
-** one opcode now works for both table types.
-*/
-case OP_Rowid: { /* out2 */
- VdbeCursor *pC;
- i64 v;
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
-
- pOut = out2Prerelease(p, pOp);
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
- if( pC->nullRow ){
- pOut->flags = MEM_Null;
- break;
- }else if( pC->deferredMoveto ){
- v = pC->movetoTarget;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- }else if( pC->eCurType==CURTYPE_VTAB ){
- assert( pC->uc.pVCur!=0 );
- pVtab = pC->uc.pVCur->pVtab;
- pModule = pVtab->pModule;
- assert( pModule->xRowid );
- rc = pModule->xRowid(pC->uc.pVCur, &v);
- sqlite3VtabImportErrmsg(p, pVtab);
- if( rc ) goto abort_due_to_error;
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
- }else{
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pC->uc.pCursor!=0 );
- rc = sqlite3VdbeCursorRestore(pC);
- if( rc ) goto abort_due_to_error;
- if( pC->nullRow ){
- pOut->flags = MEM_Null;
- break;
- }
- v = sqlite3BtreeIntegerKey(pC->uc.pCursor);
- }
- pOut->u.i = v;
- break;
-}
-
-/* Opcode: NullRow P1 * * * *
-**
-** Move the cursor P1 to a null row. Any OP_Column operations
-** that occur while the cursor is on the null row will always
-** write a NULL.
-*/
-case OP_NullRow: {
- VdbeCursor *pC;
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- pC->nullRow = 1;
- pC->cacheStatus = CACHE_STALE;
- if( pC->eCurType==CURTYPE_BTREE ){
- assert( pC->uc.pCursor!=0 );
- sqlite3BtreeClearCursor(pC->uc.pCursor);
- }
- break;
-}
-
-/* Opcode: SeekEnd P1 * * * *
-**
-** Position cursor P1 at the end of the btree for the purpose of
-** appending a new entry onto the btree.
-**
-** It is assumed that the cursor is used only for appending and so
-** if the cursor is valid, then the cursor must already be pointing
-** at the end of the btree and so no changes are made to
-** the cursor.
-*/
-/* Opcode: Last P1 P2 * * *
-**
-** The next use of the Rowid or Column or Prev instruction for P1
-** will refer to the last entry in the database table or index.
-** If the table or index is empty and P2>0, then jump immediately to P2.
-** If P2 is 0 or if the table or index is not empty, fall through
-** to the following instruction.
-**
-** This opcode leaves the cursor configured to move in reverse order,
-** from the end toward the beginning. In other words, the cursor is
-** configured to use Prev, not Next.
-*/
-case OP_SeekEnd:
-case OP_Last: { /* jump */
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->eCurType==CURTYPE_BTREE );
- pCrsr = pC->uc.pCursor;
- res = 0;
- assert( pCrsr!=0 );
-#ifdef SQLITE_DEBUG
- pC->seekOp = pOp->opcode;
-#endif
- if( pOp->opcode==OP_SeekEnd ){
- assert( pOp->p2==0 );
- pC->seekResult = -1;
- if( sqlite3BtreeCursorIsValidNN(pCrsr) ){
- break;
- }
- }
- rc = sqlite3BtreeLast(pCrsr, &res);
- pC->nullRow = (u8)res;
- pC->deferredMoveto = 0;
- pC->cacheStatus = CACHE_STALE;
- if( rc ) goto abort_due_to_error;
- if( pOp->p2>0 ){
- VdbeBranchTaken(res!=0,2);
- if( res ) goto jump_to_p2;
- }
- break;
-}
-
-/* Opcode: IfSmaller P1 P2 P3 * *
-**
-** Estimate the number of rows in the table P1. Jump to P2 if that
-** estimate is less than approximately 2**(0.1*P3).
-*/
-case OP_IfSmaller: { /* jump */
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
- i64 sz;
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- pCrsr = pC->uc.pCursor;
- assert( pCrsr );
- rc = sqlite3BtreeFirst(pCrsr, &res);
- if( rc ) goto abort_due_to_error;
- if( res==0 ){
- sz = sqlite3BtreeRowCountEst(pCrsr);
- if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)<pOp->p3 ) res = 1;
- }
- VdbeBranchTaken(res!=0,2);
- if( res ) goto jump_to_p2;
- break;
-}
-
-
-/* Opcode: SorterSort P1 P2 * * *
-**
-** After all records have been inserted into the Sorter object
-** identified by P1, invoke this opcode to actually do the sorting.
-** Jump to P2 if there are no records to be sorted.
-**
-** This opcode is an alias for OP_Sort and OP_Rewind that is used
-** for Sorter objects.
-*/
-/* Opcode: Sort P1 P2 * * *
-**
-** This opcode does exactly the same thing as OP_Rewind except that
-** it increments an undocumented global variable used for testing.
-**
-** Sorting is accomplished by writing records into a sorting index,
-** then rewinding that index and playing it back from beginning to
-** end. We use the OP_Sort opcode instead of OP_Rewind to do the
-** rewinding so that the global variable will be incremented and
-** regression tests can determine whether or not the optimizer is
-** correctly optimizing out sorts.
-*/
-case OP_SorterSort: /* jump */
-case OP_Sort: { /* jump */
-#ifdef SQLITE_TEST
- sqlite3_sort_count++;
- sqlite3_search_count--;
-#endif
- p->aCounter[SQLITE_STMTSTATUS_SORT]++;
- /* Fall through into OP_Rewind */
-}
-/* Opcode: Rewind P1 P2 * * *
-**
-** The next use of the Rowid or Column or Next instruction for P1
-** will refer to the first entry in the database table or index.
-** If the table or index is empty, jump immediately to P2.
-** If the table or index is not empty, fall through to the following
-** instruction.
-**
-** This opcode leaves the cursor configured to move in forward order,
-** from the beginning toward the end. In other words, the cursor is
-** configured to use Next, not Prev.
-*/
-case OP_Rewind: { /* jump */
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
- res = 1;
-#ifdef SQLITE_DEBUG
- pC->seekOp = OP_Rewind;
-#endif
- if( isSorter(pC) ){
- rc = sqlite3VdbeSorterRewind(pC, &res);
- }else{
- assert( pC->eCurType==CURTYPE_BTREE );
- pCrsr = pC->uc.pCursor;
- assert( pCrsr );
- rc = sqlite3BtreeFirst(pCrsr, &res);
- pC->deferredMoveto = 0;
- pC->cacheStatus = CACHE_STALE;
- }
- if( rc ) goto abort_due_to_error;
- pC->nullRow = (u8)res;
- assert( pOp->p2>0 && pOp->p2<p->nOp );
- VdbeBranchTaken(res!=0,2);
- if( res ) goto jump_to_p2;
- break;
-}
-
-/* Opcode: Next P1 P2 P3 P4 P5
-**
-** Advance cursor P1 so that it points to the next key/data pair in its
-** table or index. If there are no more key/value pairs then fall through
-** to the following instruction. But if the cursor advance was successful,
-** jump immediately to P2.
-**
-** The Next opcode is only valid following an SeekGT, SeekGE, or
-** OP_Rewind opcode used to position the cursor. Next is not allowed
-** to follow SeekLT, SeekLE, or OP_Last.
-**
-** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
-** been opened prior to this opcode or the program will segfault.
-**
-** The P3 value is a hint to the btree implementation. If P3==1, that
-** means P1 is an SQL index and that this instruction could have been
-** omitted if that index had been unique. P3 is usually 0. P3 is
-** always either 0 or 1.
-**
-** P4 is always of type P4_ADVANCE. The function pointer points to
-** sqlite3BtreeNext().
-**
-** If P5 is positive and the jump is taken, then event counter
-** number P5-1 in the prepared statement is incremented.
-**
-** See also: Prev, NextIfOpen
-*/
-/* Opcode: NextIfOpen P1 P2 P3 P4 P5
-**
-** This opcode works just like Next except that if cursor P1 is not
-** open it behaves a no-op.
-*/
-/* Opcode: Prev P1 P2 P3 P4 P5
-**
-** Back up cursor P1 so that it points to the previous key/data pair in its
-** table or index. If there is no previous key/value pairs then fall through
-** to the following instruction. But if the cursor backup was successful,
-** jump immediately to P2.
-**
-**
-** The Prev opcode is only valid following an SeekLT, SeekLE, or
-** OP_Last opcode used to position the cursor. Prev is not allowed
-** to follow SeekGT, SeekGE, or OP_Rewind.
-**
-** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
-** not open then the behavior is undefined.
-**
-** The P3 value is a hint to the btree implementation. If P3==1, that
-** means P1 is an SQL index and that this instruction could have been
-** omitted if that index had been unique. P3 is usually 0. P3 is
-** always either 0 or 1.
-**
-** P4 is always of type P4_ADVANCE. The function pointer points to
-** sqlite3BtreePrevious().
-**
-** If P5 is positive and the jump is taken, then event counter
-** number P5-1 in the prepared statement is incremented.
-*/
-/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
-**
-** This opcode works just like Prev except that if cursor P1 is not
-** open it behaves a no-op.
-*/
-/* Opcode: SorterNext P1 P2 * * P5
-**
-** This opcode works just like OP_Next except that P1 must be a
-** sorter object for which the OP_SorterSort opcode has been
-** invoked. This opcode advances the cursor to the next sorted
-** record, or jumps to P2 if there are no more sorted records.
-*/
-case OP_SorterNext: { /* jump */
- VdbeCursor *pC;
-
- pC = p->apCsr[pOp->p1];
- assert( isSorter(pC) );
- rc = sqlite3VdbeSorterNext(db, pC);
- goto next_tail;
-case OP_PrevIfOpen: /* jump */
-case OP_NextIfOpen: /* jump */
- if( p->apCsr[pOp->p1]==0 ) break;
- /* Fall through */
-case OP_Prev: /* jump */
-case OP_Next: /* jump */
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( pOp->p5<ArraySize(p->aCounter) );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->deferredMoveto==0 );
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
- assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
- assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
- assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
-
- /* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
- ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
- assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
- || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
- || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
- assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
- || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
- || pC->seekOp==OP_Last );
-
- rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
-next_tail:
- pC->cacheStatus = CACHE_STALE;
- VdbeBranchTaken(rc==SQLITE_OK,2);
- if( rc==SQLITE_OK ){
- pC->nullRow = 0;
- p->aCounter[pOp->p5]++;
-#ifdef SQLITE_TEST
- sqlite3_search_count++;
-#endif
- goto jump_to_p2_and_check_for_interrupt;
- }
- if( rc!=SQLITE_DONE ) goto abort_due_to_error;
- rc = SQLITE_OK;
- pC->nullRow = 1;
- goto check_for_interrupt;
-}
-
-/* Opcode: IdxInsert P1 P2 P3 P4 P5
-** Synopsis: key=r[P2]
-**
-** Register P2 holds an SQL index key made using the
-** MakeRecord instructions. This opcode writes that key
-** into the index P1. Data for the entry is nil.
-**
-** If P4 is not zero, then it is the number of values in the unpacked
-** key of reg(P2). In that case, P3 is the index of the first register
-** for the unpacked key. The availability of the unpacked key can sometimes
-** be an optimization.
-**
-** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer
-** that this insert is likely to be an append.
-**
-** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
-** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear,
-** then the change counter is unchanged.
-**
-** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
-** run faster by avoiding an unnecessary seek on cursor P1. However,
-** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
-** seeks on the cursor or if the most recent seek used a key equivalent
-** to P2.
-**
-** This instruction only works for indices. The equivalent instruction
-** for tables is OP_Insert.
-*/
-/* Opcode: SorterInsert P1 P2 * * *
-** Synopsis: key=r[P2]
-**
-** Register P2 holds an SQL index key made using the
-** MakeRecord instructions. This opcode writes that key
-** into the sorter P1. Data for the entry is nil.
-*/
-case OP_SorterInsert: /* in2 */
-case OP_IdxInsert: { /* in2 */
- VdbeCursor *pC;
- BtreePayload x;
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- sqlite3VdbeIncrWriteCounter(p, pC);
- assert( pC!=0 );
- assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
- pIn2 = &aMem[pOp->p2];
- assert( pIn2->flags & MEM_Blob );
- if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- assert( pC->eCurType==CURTYPE_BTREE || pOp->opcode==OP_SorterInsert );
- assert( pC->isTable==0 );
- rc = ExpandBlob(pIn2);
- if( rc ) goto abort_due_to_error;
- if( pOp->opcode==OP_SorterInsert ){
- rc = sqlite3VdbeSorterWrite(pC, pIn2);
- }else{
- x.nKey = pIn2->n;
- x.pKey = pIn2->z;
- x.aMem = aMem + pOp->p3;
- x.nMem = (u16)pOp->p4.i;
- rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
- );
- assert( pC->deferredMoveto==0 );
- pC->cacheStatus = CACHE_STALE;
- }
- if( rc) goto abort_due_to_error;
- break;
-}
-
-/* Opcode: IdxDelete P1 P2 P3 * *
-** Synopsis: key=r[P2@P3]
-**
-** The content of P3 registers starting at register P2 form
-** an unpacked index key. This opcode removes that entry from the
-** index opened by cursor P1.
-*/
-case OP_IdxDelete: {
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
- UnpackedRecord r;
-
- assert( pOp->p3>0 );
- assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->eCurType==CURTYPE_BTREE );
- sqlite3VdbeIncrWriteCounter(p, pC);
- pCrsr = pC->uc.pCursor;
- assert( pCrsr!=0 );
- assert( pOp->p5==0 );
- r.pKeyInfo = pC->pKeyInfo;
- r.nField = (u16)pOp->p3;
- r.default_rc = 0;
- r.aMem = &aMem[pOp->p2];
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
- if( rc ) goto abort_due_to_error;
- if( res==0 ){
- rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
- if( rc ) goto abort_due_to_error;
- }
- assert( pC->deferredMoveto==0 );
- pC->cacheStatus = CACHE_STALE;
- pC->seekResult = 0;
- break;
-}
-
-/* Opcode: DeferredSeek P1 * P3 P4 *
-** Synopsis: Move P3 to P1.rowid if needed
-**
-** P1 is an open index cursor and P3 is a cursor on the corresponding
-** table. This opcode does a deferred seek of the P3 table cursor
-** to the row that corresponds to the current row of P1.
-**
-** This is a deferred seek. Nothing actually happens until
-** the cursor is used to read a record. That way, if no reads
-** occur, no unnecessary I/O happens.
-**
-** P4 may be an array of integers (type P4_INTARRAY) containing
-** one entry for each column in the P3 table. If array entry a(i)
-** is non-zero, then reading column a(i)-1 from cursor P3 is
-** equivalent to performing the deferred seek and then reading column i
-** from P1. This information is stored in P3 and used to redirect
-** reads against P3 over to P1, thus possibly avoiding the need to
-** seek and read cursor P3.
-*/
-/* Opcode: IdxRowid P1 P2 * * *
-** Synopsis: r[P2]=rowid
-**
-** Write into register P2 an integer which is the last entry in the record at
-** the end of the index key pointed to by cursor P1. This integer should be
-** the rowid of the table entry to which this index entry points.
-**
-** See also: Rowid, MakeRecord.
-*/
-case OP_DeferredSeek:
-case OP_IdxRowid: { /* out2 */
- VdbeCursor *pC; /* The P1 index cursor */
- VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */
- i64 rowid; /* Rowid that P1 current points to */
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pC->uc.pCursor!=0 );
- assert( pC->isTable==0 );
- assert( pC->deferredMoveto==0 );
- assert( !pC->nullRow || pOp->opcode==OP_IdxRowid );
-
- /* The IdxRowid and Seek opcodes are combined because of the commonality
- ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */
- rc = sqlite3VdbeCursorRestore(pC);
-
- /* sqlite3VbeCursorRestore() can only fail if the record has been deleted
- ** out from under the cursor. That will never happens for an IdxRowid
- ** or Seek opcode */
- if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
-
- if( !pC->nullRow ){
- rowid = 0; /* Not needed. Only used to silence a warning. */
- rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- if( pOp->opcode==OP_DeferredSeek ){
- assert( pOp->p3>=0 && pOp->p3<p->nCursor );
- pTabCur = p->apCsr[pOp->p3];
- assert( pTabCur!=0 );
- assert( pTabCur->eCurType==CURTYPE_BTREE );
- assert( pTabCur->uc.pCursor!=0 );
- assert( pTabCur->isTable );
- pTabCur->nullRow = 0;
- pTabCur->movetoTarget = rowid;
- pTabCur->deferredMoveto = 1;
- assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
- pTabCur->aAltMap = pOp->p4.ai;
- pTabCur->pAltCursor = pC;
- }else{
- pOut = out2Prerelease(p, pOp);
- pOut->u.i = rowid;
- }
- }else{
- assert( pOp->opcode==OP_IdxRowid );
- sqlite3VdbeMemSetNull(&aMem[pOp->p2]);
- }
- break;
-}
-
-/* Opcode: IdxGE P1 P2 P3 P4 P5
-** Synopsis: key=r[P3@P4]
-**
-** The P4 register values beginning with P3 form an unpacked index
-** key that omits the PRIMARY KEY. Compare this key value against the index
-** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID
-** fields at the end.
-**
-** If the P1 index entry is greater than or equal to the key value
-** then jump to P2. Otherwise fall through to the next instruction.
-*/
-/* Opcode: IdxGT P1 P2 P3 P4 P5
-** Synopsis: key=r[P3@P4]
-**
-** The P4 register values beginning with P3 form an unpacked index
-** key that omits the PRIMARY KEY. Compare this key value against the index
-** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID
-** fields at the end.
-**
-** If the P1 index entry is greater than the key value
-** then jump to P2. Otherwise fall through to the next instruction.
-*/
-/* Opcode: IdxLT P1 P2 P3 P4 P5
-** Synopsis: key=r[P3@P4]
-**
-** The P4 register values beginning with P3 form an unpacked index
-** key that omits the PRIMARY KEY or ROWID. Compare this key value against
-** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
-** ROWID on the P1 index.
-**
-** If the P1 index entry is less than the key value then jump to P2.
-** Otherwise fall through to the next instruction.
-*/
-/* Opcode: IdxLE P1 P2 P3 P4 P5
-** Synopsis: key=r[P3@P4]
-**
-** The P4 register values beginning with P3 form an unpacked index
-** key that omits the PRIMARY KEY or ROWID. Compare this key value against
-** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
-** ROWID on the P1 index.
-**
-** If the P1 index entry is less than or equal to the key value then jump
-** to P2. Otherwise fall through to the next instruction.
-*/
-case OP_IdxLE: /* jump */
-case OP_IdxGT: /* jump */
-case OP_IdxLT: /* jump */
-case OP_IdxGE: { /* jump */
- VdbeCursor *pC;
- int res;
- UnpackedRecord r;
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- assert( pC->isOrdered );
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pC->uc.pCursor!=0);
- assert( pC->deferredMoveto==0 );
- assert( pOp->p5==0 || pOp->p5==1 );
- assert( pOp->p4type==P4_INT32 );
- r.pKeyInfo = pC->pKeyInfo;
- r.nField = (u16)pOp->p4.i;
- if( pOp->opcode<OP_IdxLT ){
- assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
- r.default_rc = -1;
- }else{
- assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
- r.default_rc = 0;
- }
- r.aMem = &aMem[pOp->p3];
-#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
-#endif
- res = 0; /* Not needed. Only used to silence a warning. */
- rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
- assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
- if( (pOp->opcode&1)==(OP_IdxLT&1) ){
- assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
- res = -res;
- }else{
- assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT );
- res++;
- }
- VdbeBranchTaken(res>0,2);
- if( rc ) goto abort_due_to_error;
- if( res>0 ) goto jump_to_p2;
- break;
-}
-
-/* Opcode: Destroy P1 P2 P3 * *
-**
-** Delete an entire database table or index whose root page in the database
-** file is given by P1.
-**
-** The table being destroyed is in the main database file if P3==0. If
-** P3==1 then the table to be clear is in the auxiliary database file
-** that is used to store tables create using CREATE TEMPORARY TABLE.
-**
-** If AUTOVACUUM is enabled then it is possible that another root page
-** might be moved into the newly deleted root page in order to keep all
-** root pages contiguous at the beginning of the database. The former
-** value of the root page that moved - its value before the move occurred -
-** is stored in register P2. If no page movement was required (because the
-** table being dropped was already the last one in the database) then a
-** zero is stored in register P2. If AUTOVACUUM is disabled then a zero
-** is stored in register P2.
-**
-** This opcode throws an error if there are any active reader VMs when
-** it is invoked. This is done to avoid the difficulty associated with
-** updating existing cursors when a root page is moved in an AUTOVACUUM
-** database. This error is thrown even if the database is not an AUTOVACUUM
-** db in order to avoid introducing an incompatibility between autovacuum
-** and non-autovacuum modes.
-**
-** See also: Clear
-*/
-case OP_Destroy: { /* out2 */
- int iMoved;
- int iDb;
-
- sqlite3VdbeIncrWriteCounter(p, 0);
- assert( p->readOnly==0 );
- assert( pOp->p1>1 );
- pOut = out2Prerelease(p, pOp);
- pOut->flags = MEM_Null;
- if( db->nVdbeRead > db->nVDestroy+1 ){
- rc = SQLITE_LOCKED;
- p->errorAction = OE_Abort;
- goto abort_due_to_error;
- }else{
- iDb = pOp->p3;
- assert( DbMaskTest(p->btreeMask, iDb) );
- iMoved = 0; /* Not needed. Only to silence a warning. */
- rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
- pOut->flags = MEM_Int;
- pOut->u.i = iMoved;
- if( rc ) goto abort_due_to_error;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( iMoved!=0 ){
- sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1);
- /* All OP_Destroy operations occur on the same btree */
- assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 );
- resetSchemaOnFault = iDb+1;
- }
-#endif
- }
- break;
-}
-
-/* Opcode: Clear P1 P2 P3
-**
-** Delete all contents of the database table or index whose root page
-** in the database file is given by P1. But, unlike Destroy, do not
-** remove the table or index from the database file.
-**
-** The table being clear is in the main database file if P2==0. If
-** P2==1 then the table to be clear is in the auxiliary database file
-** that is used to store tables create using CREATE TEMPORARY TABLE.
-**
-** If the P3 value is non-zero, then the table referred to must be an
-** intkey table (an SQL table, not an index). In this case the row change
-** count is incremented by the number of rows in the table being cleared.
-** If P3 is greater than zero, then the value stored in register P3 is
-** also incremented by the number of rows in the table being cleared.
-**
-** See also: Destroy
-*/
-case OP_Clear: {
- int nChange;
-
- sqlite3VdbeIncrWriteCounter(p, 0);
- nChange = 0;
- assert( p->readOnly==0 );
- assert( DbMaskTest(p->btreeMask, pOp->p2) );
- rc = sqlite3BtreeClearTable(
- db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
- );
- if( pOp->p3 ){
- p->nChange += nChange;
- if( pOp->p3>0 ){
- assert( memIsValid(&aMem[pOp->p3]) );
- memAboutToChange(p, &aMem[pOp->p3]);
- aMem[pOp->p3].u.i += nChange;
- }
- }
- if( rc ) goto abort_due_to_error;
- break;
-}
-
-/* Opcode: ResetSorter P1 * * * *
-**
-** Delete all contents from the ephemeral table or sorter
-** that is open on cursor P1.
-**
-** This opcode only works for cursors used for sorting and
-** opened with OP_OpenEphemeral or OP_SorterOpen.
-*/
-case OP_ResetSorter: {
- VdbeCursor *pC;
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
- if( isSorter(pC) ){
- sqlite3VdbeSorterReset(db, pC->uc.pSorter);
- }else{
- assert( pC->eCurType==CURTYPE_BTREE );
- assert( pC->isEphemeral );
- rc = sqlite3BtreeClearTableOfCursor(pC->uc.pCursor);
- if( rc ) goto abort_due_to_error;
- }
- break;
-}
-
-/* Opcode: CreateBtree P1 P2 P3 * *
-** Synopsis: r[P2]=root iDb=P1 flags=P3
-**
-** Allocate a new b-tree in the main database file if P1==0 or in the
-** TEMP database file if P1==1 or in an attached database if
-** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table
-** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table.
-** The root page number of the new b-tree is stored in register P2.
-*/
-case OP_CreateBtree: { /* out2 */
- int pgno;
- Db *pDb;
-
- sqlite3VdbeIncrWriteCounter(p, 0);
- pOut = out2Prerelease(p, pOp);
- pgno = 0;
- assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( DbMaskTest(p->btreeMask, pOp->p1) );
- assert( p->readOnly==0 );
- pDb = &db->aDb[pOp->p1];
- assert( pDb->pBt!=0 );
- rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, pOp->p3);
- if( rc ) goto abort_due_to_error;
- pOut->u.i = pgno;
- break;
-}
-
-/* Opcode: SqlExec * * * P4 *
-**
-** Run the SQL statement or statements specified in the P4 string.
-*/
-case OP_SqlExec: {
- sqlite3VdbeIncrWriteCounter(p, 0);
- db->nSqlExec++;
- rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0);
- db->nSqlExec--;
- if( rc ) goto abort_due_to_error;
- break;
-}
-
-/* Opcode: ParseSchema P1 * * P4 *
-**
-** Read and parse all entries from the SQLITE_MASTER table of database P1
-** that match the WHERE clause P4.
-**
-** This opcode invokes the parser to create a new virtual machine,
-** then runs the new virtual machine. It is thus a re-entrant opcode.
-*/
-case OP_ParseSchema: {
- int iDb;
- const char *zMaster;
- char *zSql;
- InitData initData;
-
- /* Any prepared statement that invokes this opcode will hold mutexes
- ** on every btree. This is a prerequisite for invoking
- ** sqlite3InitCallback().
- */
-#ifdef SQLITE_DEBUG
- for(iDb=0; iDb<db->nDb; iDb++){
- assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
- }
-#endif
-
- iDb = pOp->p1;
- assert( iDb>=0 && iDb<db->nDb );
- assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
- /* Used to be a conditional */ {
- zMaster = MASTER_NAME;
- initData.db = db;
- initData.iDb = pOp->p1;
- initData.pzErrMsg = &p->zErrMsg;
- zSql = sqlite3MPrintf(db,
- "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
- db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
- if( zSql==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- assert( db->init.busy==0 );
- db->init.busy = 1;
- initData.rc = SQLITE_OK;
- assert( !db->mallocFailed );
- rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
- if( rc==SQLITE_OK ) rc = initData.rc;
- sqlite3DbFreeNN(db, zSql);
- db->init.busy = 0;
- }
- }
- if( rc ){
- sqlite3ResetAllSchemasOfConnection(db);
- if( rc==SQLITE_NOMEM ){
- goto no_mem;
- }
- goto abort_due_to_error;
- }
- break;
-}
-
-#if !defined(SQLITE_OMIT_ANALYZE)
-/* Opcode: LoadAnalysis P1 * * * *
-**
-** Read the sqlite_stat1 table for database P1 and load the content
-** of that table into the internal index hash table. This will cause
-** the analysis to be used when preparing all subsequent queries.
-*/
-case OP_LoadAnalysis: {
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- rc = sqlite3AnalysisLoad(db, pOp->p1);
- if( rc ) goto abort_due_to_error;
- break;
-}
-#endif /* !defined(SQLITE_OMIT_ANALYZE) */
-
-/* Opcode: DropTable P1 * * P4 *
-**
-** Remove the internal (in-memory) data structures that describe
-** the table named P4 in database P1. This is called after a table
-** is dropped from disk (using the Destroy opcode) in order to keep
-** the internal representation of the
-** schema consistent with what is on disk.
-*/
-case OP_DropTable: {
- sqlite3VdbeIncrWriteCounter(p, 0);
- sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
- break;
-}
-
-/* Opcode: DropIndex P1 * * P4 *
-**
-** Remove the internal (in-memory) data structures that describe
-** the index named P4 in database P1. This is called after an index
-** is dropped from disk (using the Destroy opcode)
-** in order to keep the internal representation of the
-** schema consistent with what is on disk.
-*/
-case OP_DropIndex: {
- sqlite3VdbeIncrWriteCounter(p, 0);
- sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
- break;
-}
-
-/* Opcode: DropTrigger P1 * * P4 *
-**
-** Remove the internal (in-memory) data structures that describe
-** the trigger named P4 in database P1. This is called after a trigger
-** is dropped from disk (using the Destroy opcode) in order to keep
-** the internal representation of the
-** schema consistent with what is on disk.
-*/
-case OP_DropTrigger: {
- sqlite3VdbeIncrWriteCounter(p, 0);
- sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
- break;
-}
-
-
-#ifndef SQLITE_OMIT_INTEGRITY_CHECK
-/* Opcode: IntegrityCk P1 P2 P3 P4 P5
-**
-** Do an analysis of the currently open database. Store in
-** register P1 the text of an error message describing any problems.
-** If no problems are found, store a NULL in register P1.
-**
-** The register P3 contains one less than the maximum number of allowed errors.
-** At most reg(P3) errors will be reported.
-** In other words, the analysis stops as soon as reg(P1) errors are
-** seen. Reg(P1) is updated with the number of errors remaining.
-**
-** The root page numbers of all tables in the database are integers
-** stored in P4_INTARRAY argument.
-**
-** If P5 is not zero, the check is done on the auxiliary database
-** file, not the main database file.
-**
-** This opcode is used to implement the integrity_check pragma.
-*/
-case OP_IntegrityCk: {
- int nRoot; /* Number of tables to check. (Number of root pages.) */
- int *aRoot; /* Array of rootpage numbers for tables to be checked */
- int nErr; /* Number of errors reported */
- char *z; /* Text of the error report */
- Mem *pnErr; /* Register keeping track of errors remaining */
-
- assert( p->bIsReader );
- nRoot = pOp->p2;
- aRoot = pOp->p4.ai;
- assert( nRoot>0 );
- assert( aRoot[0]==nRoot );
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- pnErr = &aMem[pOp->p3];
- assert( (pnErr->flags & MEM_Int)!=0 );
- assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
- pIn1 = &aMem[pOp->p1];
- assert( pOp->p5<db->nDb );
- assert( DbMaskTest(p->btreeMask, pOp->p5) );
- z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
- (int)pnErr->u.i+1, &nErr);
- sqlite3VdbeMemSetNull(pIn1);
- if( nErr==0 ){
- assert( z==0 );
- }else if( z==0 ){
- goto no_mem;
- }else{
- pnErr->u.i -= nErr-1;
- sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
- }
- UPDATE_MAX_BLOBSIZE(pIn1);
- sqlite3VdbeChangeEncoding(pIn1, encoding);
- break;
-}
-#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
-
-/* Opcode: RowSetAdd P1 P2 * * *
-** Synopsis: rowset(P1)=r[P2]
-**
-** Insert the integer value held by register P2 into a RowSet object
-** held in register P1.
-**
-** An assertion fails if P2 is not an integer.
-*/
-case OP_RowSetAdd: { /* in1, in2 */
- pIn1 = &aMem[pOp->p1];
- pIn2 = &aMem[pOp->p2];
- assert( (pIn2->flags & MEM_Int)!=0 );
- if( (pIn1->flags & MEM_RowSet)==0 ){
- sqlite3VdbeMemSetRowSet(pIn1);
- if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
- }
- sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i);
- break;
-}
-
-/* Opcode: RowSetRead P1 P2 P3 * *
-** Synopsis: r[P3]=rowset(P1)
-**
-** Extract the smallest value from the RowSet object in P1
-** and put that value into register P3.
-** Or, if RowSet object P1 is initially empty, leave P3
-** unchanged and jump to instruction P2.
-*/
-case OP_RowSetRead: { /* jump, in1, out3 */
- i64 val;
-
- pIn1 = &aMem[pOp->p1];
- if( (pIn1->flags & MEM_RowSet)==0
- || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
- ){
- /* The boolean index is empty */
- sqlite3VdbeMemSetNull(pIn1);
- VdbeBranchTaken(1,2);
- goto jump_to_p2_and_check_for_interrupt;
- }else{
- /* A value was pulled from the index */
- VdbeBranchTaken(0,2);
- sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
- }
- goto check_for_interrupt;
-}
-
-/* Opcode: RowSetTest P1 P2 P3 P4
-** Synopsis: if r[P3] in rowset(P1) goto P2
-**
-** Register P3 is assumed to hold a 64-bit integer value. If register P1
-** contains a RowSet object and that RowSet object contains
-** the value held in P3, jump to register P2. Otherwise, insert the
-** integer in P3 into the RowSet and continue on to the
-** next opcode.
-**
-** The RowSet object is optimized for the case where sets of integers
-** are inserted in distinct phases, which each set contains no duplicates.
-** Each set is identified by a unique P4 value. The first set
-** must have P4==0, the final set must have P4==-1, and for all other sets
-** must have P4>0.
-**
-** This allows optimizations: (a) when P4==0 there is no need to test
-** the RowSet object for P3, as it is guaranteed not to contain it,
-** (b) when P4==-1 there is no need to insert the value, as it will
-** never be tested for, and (c) when a value that is part of set X is
-** inserted, there is no need to search to see if the same value was
-** previously inserted as part of set X (only if it was previously
-** inserted as part of some other set).
-*/
-case OP_RowSetTest: { /* jump, in1, in3 */
- int iSet;
- int exists;
-
- pIn1 = &aMem[pOp->p1];
- pIn3 = &aMem[pOp->p3];
- iSet = pOp->p4.i;
- assert( pIn3->flags&MEM_Int );
-
- /* If there is anything other than a rowset object in memory cell P1,
- ** delete it now and initialize P1 with an empty rowset
- */
- if( (pIn1->flags & MEM_RowSet)==0 ){
- sqlite3VdbeMemSetRowSet(pIn1);
- if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
- }
-
- assert( pOp->p4type==P4_INT32 );
- assert( iSet==-1 || iSet>=0 );
- if( iSet ){
- exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i);
- VdbeBranchTaken(exists!=0,2);
- if( exists ) goto jump_to_p2;
- }
- if( iSet>=0 ){
- sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
- }
- break;
-}
-
-
-#ifndef SQLITE_OMIT_TRIGGER
-
-/* Opcode: Program P1 P2 P3 P4 P5
-**
-** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
-**
-** P1 contains the address of the memory cell that contains the first memory
-** cell in an array of values used as arguments to the sub-program. P2
-** contains the address to jump to if the sub-program throws an IGNORE
-** exception using the RAISE() function. Register P3 contains the address
-** of a memory cell in this (the parent) VM that is used to allocate the
-** memory required by the sub-vdbe at runtime.
-**
-** P4 is a pointer to the VM containing the trigger program.
-**
-** If P5 is non-zero, then recursive program invocation is enabled.
-*/
-case OP_Program: { /* jump */
- int nMem; /* Number of memory registers for sub-program */
- int nByte; /* Bytes of runtime space required for sub-program */
- Mem *pRt; /* Register to allocate runtime space */
- Mem *pMem; /* Used to iterate through memory cells */
- Mem *pEnd; /* Last memory cell in new array */
- VdbeFrame *pFrame; /* New vdbe frame to execute in */
- SubProgram *pProgram; /* Sub-program to execute */
- void *t; /* Token identifying trigger */
-
- pProgram = pOp->p4.pProgram;
- pRt = &aMem[pOp->p3];
- assert( pProgram->nOp>0 );
-
- /* If the p5 flag is clear, then recursive invocation of triggers is
- ** disabled for backwards compatibility (p5 is set if this sub-program
- ** is really a trigger, not a foreign key action, and the flag set
- ** and cleared by the "PRAGMA recursive_triggers" command is clear).
- **
- ** It is recursive invocation of triggers, at the SQL level, that is
- ** disabled. In some cases a single trigger may generate more than one
- ** SubProgram (if the trigger may be executed with more than one different
- ** ON CONFLICT algorithm). SubProgram structures associated with a
- ** single trigger all have the same value for the SubProgram.token
- ** variable. */
- if( pOp->p5 ){
- t = pProgram->token;
- for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
- if( pFrame ) break;
- }
-
- if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
- rc = SQLITE_ERROR;
- sqlite3VdbeError(p, "too many levels of trigger recursion");
- goto abort_due_to_error;
- }
-
- /* Register pRt is used to store the memory required to save the state
- ** of the current program, and the memory required at runtime to execute
- ** the trigger program. If this trigger has been fired before, then pRt
- ** is already allocated. Otherwise, it must be initialized. */
- if( (pRt->flags&MEM_Frame)==0 ){
- /* SubProgram.nMem is set to the number of memory cells used by the
- ** program stored in SubProgram.aOp. As well as these, one memory
- ** cell is required for each cursor used by the program. Set local
- ** variable nMem (and later, VdbeFrame.nChildMem) to this value.
- */
- nMem = pProgram->nMem + pProgram->nCsr;
- assert( nMem>0 );
- if( pProgram->nCsr==0 ) nMem++;
- nByte = ROUND8(sizeof(VdbeFrame))
- + nMem * sizeof(Mem)
- + pProgram->nCsr * sizeof(VdbeCursor*)
- + (pProgram->nOp + 7)/8;
- pFrame = sqlite3DbMallocZero(db, nByte);
- if( !pFrame ){
- goto no_mem;
- }
- sqlite3VdbeMemRelease(pRt);
- pRt->flags = MEM_Frame;
- pRt->u.pFrame = pFrame;
-
- pFrame->v = p;
- pFrame->nChildMem = nMem;
- pFrame->nChildCsr = pProgram->nCsr;
- pFrame->pc = (int)(pOp - aOp);
- pFrame->aMem = p->aMem;
- pFrame->nMem = p->nMem;
- pFrame->apCsr = p->apCsr;
- pFrame->nCursor = p->nCursor;
- pFrame->aOp = p->aOp;
- pFrame->nOp = p->nOp;
- pFrame->token = pProgram->token;
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- pFrame->anExec = p->anExec;
-#endif
-
- pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
- for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
- pMem->flags = MEM_Undefined;
- pMem->db = db;
- }
- }else{
- pFrame = pRt->u.pFrame;
- assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem
- || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) );
- assert( pProgram->nCsr==pFrame->nChildCsr );
- assert( (int)(pOp - aOp)==pFrame->pc );
- }
-
- p->nFrame++;
- pFrame->pParent = p->pFrame;
- pFrame->lastRowid = db->lastRowid;
- pFrame->nChange = p->nChange;
- pFrame->nDbChange = p->db->nChange;
- assert( pFrame->pAuxData==0 );
- pFrame->pAuxData = p->pAuxData;
- p->pAuxData = 0;
- p->nChange = 0;
- p->pFrame = pFrame;
- p->aMem = aMem = VdbeFrameMem(pFrame);
- p->nMem = pFrame->nChildMem;
- p->nCursor = (u16)pFrame->nChildCsr;
- p->apCsr = (VdbeCursor **)&aMem[p->nMem];
- pFrame->aOnce = (u8*)&p->apCsr[pProgram->nCsr];
- memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8);
- p->aOp = aOp = pProgram->aOp;
- p->nOp = pProgram->nOp;
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- p->anExec = 0;
-#endif
- pOp = &aOp[-1];
-
- break;
-}
-
-/* Opcode: Param P1 P2 * * *
-**
-** This opcode is only ever present in sub-programs called via the
-** OP_Program instruction. Copy a value currently stored in a memory
-** cell of the calling (parent) frame to cell P2 in the current frames
-** address space. This is used by trigger programs to access the new.*
-** and old.* values.
-**
-** The address of the cell in the parent frame is determined by adding
-** the value of the P1 argument to the value of the P1 argument to the
-** calling OP_Program instruction.
-*/
-case OP_Param: { /* out2 */
- VdbeFrame *pFrame;
- Mem *pIn;
- pOut = out2Prerelease(p, pOp);
- pFrame = p->pFrame;
- pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1];
- sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem);
- break;
-}
-
-#endif /* #ifndef SQLITE_OMIT_TRIGGER */
-
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-/* Opcode: FkCounter P1 P2 * * *
-** Synopsis: fkctr[P1]+=P2
-**
-** Increment a "constraint counter" by P2 (P2 may be negative or positive).
-** If P1 is non-zero, the database constraint counter is incremented
-** (deferred foreign key constraints). Otherwise, if P1 is zero, the
-** statement counter is incremented (immediate foreign key constraints).
-*/
-case OP_FkCounter: {
- if( db->flags & SQLITE_DeferFKs ){
- db->nDeferredImmCons += pOp->p2;
- }else if( pOp->p1 ){
- db->nDeferredCons += pOp->p2;
- }else{
- p->nFkConstraint += pOp->p2;
- }
- break;
-}
-
-/* Opcode: FkIfZero P1 P2 * * *
-** Synopsis: if fkctr[P1]==0 goto P2
-**
-** This opcode tests if a foreign key constraint-counter is currently zero.
-** If so, jump to instruction P2. Otherwise, fall through to the next
-** instruction.
-**
-** If P1 is non-zero, then the jump is taken if the database constraint-counter
-** is zero (the one that counts deferred constraint violations). If P1 is
-** zero, the jump is taken if the statement constraint-counter is zero
-** (immediate foreign key constraint violations).
-*/
-case OP_FkIfZero: { /* jump */
- if( pOp->p1 ){
- VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2);
- if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2;
- }else{
- VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2);
- if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2;
- }
- break;
-}
-#endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */
-
-#ifndef SQLITE_OMIT_AUTOINCREMENT
-/* Opcode: MemMax P1 P2 * * *
-** Synopsis: r[P1]=max(r[P1],r[P2])
-**
-** P1 is a register in the root frame of this VM (the root frame is
-** different from the current frame if this instruction is being executed
-** within a sub-program). Set the value of register P1 to the maximum of
-** its current value and the value in register P2.
-**
-** This instruction throws an error if the memory cell is not initially
-** an integer.
-*/
-case OP_MemMax: { /* in2 */
- VdbeFrame *pFrame;
- if( p->pFrame ){
- for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
- pIn1 = &pFrame->aMem[pOp->p1];
- }else{
- pIn1 = &aMem[pOp->p1];
- }
- assert( memIsValid(pIn1) );
- sqlite3VdbeMemIntegerify(pIn1);
- pIn2 = &aMem[pOp->p2];
- sqlite3VdbeMemIntegerify(pIn2);
- if( pIn1->u.i<pIn2->u.i){
- pIn1->u.i = pIn2->u.i;
- }
- break;
-}
-#endif /* SQLITE_OMIT_AUTOINCREMENT */
-
-/* Opcode: IfPos P1 P2 P3 * *
-** Synopsis: if r[P1]>0 then r[P1]-=P3, goto P2
-**
-** Register P1 must contain an integer.
-** If the value of register P1 is 1 or greater, subtract P3 from the
-** value in P1 and jump to P2.
-**
-** If the initial value of register P1 is less than 1, then the
-** value is unchanged and control passes through to the next instruction.
-*/
-case OP_IfPos: { /* jump, in1 */
- pIn1 = &aMem[pOp->p1];
- assert( pIn1->flags&MEM_Int );
- VdbeBranchTaken( pIn1->u.i>0, 2);
- if( pIn1->u.i>0 ){
- pIn1->u.i -= pOp->p3;
- goto jump_to_p2;
- }
- break;
-}
-
-/* Opcode: OffsetLimit P1 P2 P3 * *
-** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)
-**
-** This opcode performs a commonly used computation associated with
-** LIMIT and OFFSET process. r[P1] holds the limit counter. r[P3]
-** holds the offset counter. The opcode computes the combined value
-** of the LIMIT and OFFSET and stores that value in r[P2]. The r[P2]
-** value computed is the total number of rows that will need to be
-** visited in order to complete the query.
-**
-** If r[P3] is zero or negative, that means there is no OFFSET
-** and r[P2] is set to be the value of the LIMIT, r[P1].
-**
-** if r[P1] is zero or negative, that means there is no LIMIT
-** and r[P2] is set to -1.
-**
-** Otherwise, r[P2] is set to the sum of r[P1] and r[P3].
-*/
-case OP_OffsetLimit: { /* in1, out2, in3 */
- i64 x;
- pIn1 = &aMem[pOp->p1];
- pIn3 = &aMem[pOp->p3];
- pOut = out2Prerelease(p, pOp);
- assert( pIn1->flags & MEM_Int );
- assert( pIn3->flags & MEM_Int );
- x = pIn1->u.i;
- if( x<=0 || sqlite3AddInt64(&x, pIn3->u.i>0?pIn3->u.i:0) ){
- /* If the LIMIT is less than or equal to zero, loop forever. This
- ** is documented. But also, if the LIMIT+OFFSET exceeds 2^63 then
- ** also loop forever. This is undocumented. In fact, one could argue
- ** that the loop should terminate. But assuming 1 billion iterations
- ** per second (far exceeding the capabilities of any current hardware)
- ** it would take nearly 300 years to actually reach the limit. So
- ** looping forever is a reasonable approximation. */
- pOut->u.i = -1;
- }else{
- pOut->u.i = x;
- }
- break;
-}
-
-/* Opcode: IfNotZero P1 P2 * * *
-** Synopsis: if r[P1]!=0 then r[P1]--, goto P2
-**
-** Register P1 must contain an integer. If the content of register P1 is
-** initially greater than zero, then decrement the value in register P1.
-** If it is non-zero (negative or positive) and then also jump to P2.
-** If register P1 is initially zero, leave it unchanged and fall through.
-*/
-case OP_IfNotZero: { /* jump, in1 */
- pIn1 = &aMem[pOp->p1];
- assert( pIn1->flags&MEM_Int );
- VdbeBranchTaken(pIn1->u.i<0, 2);
- if( pIn1->u.i ){
- if( pIn1->u.i>0 ) pIn1->u.i--;
- goto jump_to_p2;
- }
- break;
-}
-
-/* Opcode: DecrJumpZero P1 P2 * * *
-** Synopsis: if (--r[P1])==0 goto P2
-**
-** Register P1 must hold an integer. Decrement the value in P1
-** and jump to P2 if the new value is exactly zero.
-*/
-case OP_DecrJumpZero: { /* jump, in1 */
- pIn1 = &aMem[pOp->p1];
- assert( pIn1->flags&MEM_Int );
- if( pIn1->u.i>SMALLEST_INT64 ) pIn1->u.i--;
- VdbeBranchTaken(pIn1->u.i==0, 2);
- if( pIn1->u.i==0 ) goto jump_to_p2;
- break;
-}
-
-
-/* Opcode: AggStep0 * P2 P3 P4 P5
-** Synopsis: accum=r[P3] step(r[P2@P5])
-**
-** Execute the step function for an aggregate. The
-** function has P5 arguments. P4 is a pointer to the FuncDef
-** structure that specifies the function. Register P3 is the
-** accumulator.
-**
-** The P5 arguments are taken from register P2 and its
-** successors.
-*/
-/* Opcode: AggStep * P2 P3 P4 P5
-** Synopsis: accum=r[P3] step(r[P2@P5])
-**
-** Execute the step function for an aggregate. The
-** function has P5 arguments. P4 is a pointer to an sqlite3_context
-** object that is used to run the function. Register P3 is
-** as the accumulator.
-**
-** The P5 arguments are taken from register P2 and its
-** successors.
-**
-** This opcode is initially coded as OP_AggStep0. On first evaluation,
-** the FuncDef stored in P4 is converted into an sqlite3_context and
-** the opcode is changed. In this way, the initialization of the
-** sqlite3_context only happens once, instead of on each call to the
-** step function.
-*/
-case OP_AggStep0: {
- int n;
- sqlite3_context *pCtx;
-
- assert( pOp->p4type==P4_FUNCDEF );
- n = pOp->p5;
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
- assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) +
- (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*)));
- if( pCtx==0 ) goto no_mem;
- pCtx->pMem = 0;
- pCtx->pOut = (Mem*)&(pCtx->argv[n]);
- sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
- pCtx->pFunc = pOp->p4.pFunc;
- pCtx->iOp = (int)(pOp - aOp);
- pCtx->pVdbe = p;
- pCtx->skipFlag = 0;
- pCtx->isError = 0;
- pCtx->argc = n;
- pOp->p4type = P4_FUNCCTX;
- pOp->p4.pCtx = pCtx;
- pOp->opcode = OP_AggStep;
- /* Fall through into OP_AggStep */
-}
-case OP_AggStep: {
- int i;
- sqlite3_context *pCtx;
- Mem *pMem;
-
- assert( pOp->p4type==P4_FUNCCTX );
- pCtx = pOp->p4.pCtx;
- pMem = &aMem[pOp->p3];
-
- /* If this function is inside of a trigger, the register array in aMem[]
- ** might change from one evaluation to the next. The next block of code
- ** checks to see if the register array has changed, and if so it
- ** reinitializes the relavant parts of the sqlite3_context object */
- if( pCtx->pMem != pMem ){
- pCtx->pMem = pMem;
- for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
- }
-
-#ifdef SQLITE_DEBUG
- for(i=0; i<pCtx->argc; i++){
- assert( memIsValid(pCtx->argv[i]) );
- REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
- }
-#endif
-
- pMem->n++;
- assert( pCtx->pOut->flags==MEM_Null );
- assert( pCtx->isError==0 );
- assert( pCtx->skipFlag==0 );
- (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
- if( pCtx->isError ){
- if( pCtx->isError>0 ){
- sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
- rc = pCtx->isError;
- }
- if( pCtx->skipFlag ){
- assert( pOp[-1].opcode==OP_CollSeq );
- i = pOp[-1].p1;
- if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
- pCtx->skipFlag = 0;
- }
- sqlite3VdbeMemRelease(pCtx->pOut);
- pCtx->pOut->flags = MEM_Null;
- pCtx->isError = 0;
- if( rc ) goto abort_due_to_error;
- }
- assert( pCtx->pOut->flags==MEM_Null );
- assert( pCtx->skipFlag==0 );
- break;
-}
-
-/* Opcode: AggFinal P1 P2 * P4 *
-** Synopsis: accum=r[P1] N=P2
-**
-** Execute the finalizer function for an aggregate. P1 is
-** the memory location that is the accumulator for the aggregate.
-**
-** P2 is the number of arguments that the step function takes and
-** P4 is a pointer to the FuncDef for this function. The P2
-** argument is not used by this opcode. It is only there to disambiguate
-** functions that can take varying numbers of arguments. The
-** P4 argument is only needed for the degenerate case where
-** the step function was not previously called.
-*/
-case OP_AggFinal: {
- Mem *pMem;
- assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
- pMem = &aMem[pOp->p1];
- assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
- rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
- if( rc ){
- sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
- goto abort_due_to_error;
- }
- sqlite3VdbeChangeEncoding(pMem, encoding);
- UPDATE_MAX_BLOBSIZE(pMem);
- if( sqlite3VdbeMemTooBig(pMem) ){
- goto too_big;
- }
- break;
-}
-
-#ifndef SQLITE_OMIT_WAL
-/* Opcode: Checkpoint P1 P2 P3 * *
-**
-** Checkpoint database P1. This is a no-op if P1 is not currently in
-** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL,
-** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns
-** SQLITE_BUSY or not, respectively. Write the number of pages in the
-** WAL after the checkpoint into mem[P3+1] and the number of pages
-** in the WAL that have been checkpointed after the checkpoint
-** completes into mem[P3+2]. However on an error, mem[P3+1] and
-** mem[P3+2] are initialized to -1.
-*/
-case OP_Checkpoint: {
- int i; /* Loop counter */
- int aRes[3]; /* Results */
- Mem *pMem; /* Write results here */
-
- assert( p->readOnly==0 );
- aRes[0] = 0;
- aRes[1] = aRes[2] = -1;
- assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
- || pOp->p2==SQLITE_CHECKPOINT_FULL
- || pOp->p2==SQLITE_CHECKPOINT_RESTART
- || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE
- );
- rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]);
- if( rc ){
- if( rc!=SQLITE_BUSY ) goto abort_due_to_error;
- rc = SQLITE_OK;
- aRes[0] = 1;
- }
- for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){
- sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]);
- }
- break;
-};
-#endif
-
-#ifndef SQLITE_OMIT_PRAGMA
-/* Opcode: JournalMode P1 P2 P3 * *
-**
-** Change the journal mode of database P1 to P3. P3 must be one of the
-** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
-** modes (delete, truncate, persist, off and memory), this is a simple
-** operation. No IO is required.
-**
-** If changing into or out of WAL mode the procedure is more complicated.
-**
-** Write a string containing the final journal-mode to register P2.
-*/
-case OP_JournalMode: { /* out2 */
- Btree *pBt; /* Btree to change journal mode of */
- Pager *pPager; /* Pager associated with pBt */
- int eNew; /* New journal mode */
- int eOld; /* The old journal mode */
-#ifndef SQLITE_OMIT_WAL
- const char *zFilename; /* Name of database file for pPager */
-#endif
-
- pOut = out2Prerelease(p, pOp);
- eNew = pOp->p3;
- assert( eNew==PAGER_JOURNALMODE_DELETE
- || eNew==PAGER_JOURNALMODE_TRUNCATE
- || eNew==PAGER_JOURNALMODE_PERSIST
- || eNew==PAGER_JOURNALMODE_OFF
- || eNew==PAGER_JOURNALMODE_MEMORY
- || eNew==PAGER_JOURNALMODE_WAL
- || eNew==PAGER_JOURNALMODE_QUERY
- );
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( p->readOnly==0 );
-
- pBt = db->aDb[pOp->p1].pBt;
- pPager = sqlite3BtreePager(pBt);
- eOld = sqlite3PagerGetJournalMode(pPager);
- if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
- if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
-
-#ifndef SQLITE_OMIT_WAL
- zFilename = sqlite3PagerFilename(pPager, 1);
-
- /* Do not allow a transition to journal_mode=WAL for a database
- ** in temporary storage or if the VFS does not support shared memory
- */
- if( eNew==PAGER_JOURNALMODE_WAL
- && (sqlite3Strlen30(zFilename)==0 /* Temp file */
- || !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */
- ){
- eNew = eOld;
- }
-
- if( (eNew!=eOld)
- && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL)
- ){
- if( !db->autoCommit || db->nVdbeRead>1 ){
- rc = SQLITE_ERROR;
- sqlite3VdbeError(p,
- "cannot change %s wal mode from within a transaction",
- (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
- );
- goto abort_due_to_error;
- }else{
-
- if( eOld==PAGER_JOURNALMODE_WAL ){
- /* If leaving WAL mode, close the log file. If successful, the call
- ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
- ** file. An EXCLUSIVE lock may still be held on the database file
- ** after a successful return.
- */
- rc = sqlite3PagerCloseWal(pPager, db);
- if( rc==SQLITE_OK ){
- sqlite3PagerSetJournalMode(pPager, eNew);
- }
- }else if( eOld==PAGER_JOURNALMODE_MEMORY ){
- /* Cannot transition directly from MEMORY to WAL. Use mode OFF
- ** as an intermediate */
- sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
- }
-
- /* Open a transaction on the database file. Regardless of the journal
- ** mode, this transaction always uses a rollback journal.
- */
- assert( sqlite3BtreeIsInTrans(pBt)==0 );
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
- }
- }
- }
-#endif /* ifndef SQLITE_OMIT_WAL */
-
- if( rc ) eNew = eOld;
- eNew = sqlite3PagerSetJournalMode(pPager, eNew);
-
- pOut->flags = MEM_Str|MEM_Static|MEM_Term;
- pOut->z = (char *)sqlite3JournalModename(eNew);
- pOut->n = sqlite3Strlen30(pOut->z);
- pOut->enc = SQLITE_UTF8;
- sqlite3VdbeChangeEncoding(pOut, encoding);
- if( rc ) goto abort_due_to_error;
- break;
-};
-#endif /* SQLITE_OMIT_PRAGMA */
-
-#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
-/* Opcode: Vacuum P1 * * * *
-**
-** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more
-** for an attached database. The "temp" database may not be vacuumed.
-*/
-case OP_Vacuum: {
- assert( p->readOnly==0 );
- rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1);
- if( rc ) goto abort_due_to_error;
- break;
-}
-#endif
-
-#if !defined(SQLITE_OMIT_AUTOVACUUM)
-/* Opcode: IncrVacuum P1 P2 * * *
-**
-** Perform a single step of the incremental vacuum procedure on
-** the P1 database. If the vacuum has finished, jump to instruction
-** P2. Otherwise, fall through to the next instruction.
-*/
-case OP_IncrVacuum: { /* jump */
- Btree *pBt;
-
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( DbMaskTest(p->btreeMask, pOp->p1) );
- assert( p->readOnly==0 );
- pBt = db->aDb[pOp->p1].pBt;
- rc = sqlite3BtreeIncrVacuum(pBt);
- VdbeBranchTaken(rc==SQLITE_DONE,2);
- if( rc ){
- if( rc!=SQLITE_DONE ) goto abort_due_to_error;
- rc = SQLITE_OK;
- goto jump_to_p2;
- }
- break;
-}
-#endif
-
-/* Opcode: Expire P1 * * * *
-**
-** Cause precompiled statements to expire. When an expired statement
-** is executed using sqlite3_step() it will either automatically
-** reprepare itself (if it was originally created using sqlite3_prepare_v2())
-** or it will fail with SQLITE_SCHEMA.
-**
-** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
-** then only the currently executing statement is expired.
-*/
-case OP_Expire: {
- if( !pOp->p1 ){
- sqlite3ExpirePreparedStatements(db);
- }else{
- p->expired = 1;
- }
- break;
-}
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/* Opcode: TableLock P1 P2 P3 P4 *
-** Synopsis: iDb=P1 root=P2 write=P3
-**
-** Obtain a lock on a particular table. This instruction is only used when
-** the shared-cache feature is enabled.
-**
-** P1 is the index of the database in sqlite3.aDb[] of the database
-** on which the lock is acquired. A readlock is obtained if P3==0 or
-** a write lock if P3==1.
-**
-** P2 contains the root-page of the table to lock.
-**
-** P4 contains a pointer to the name of the table being locked. This is only
-** used to generate an error message if the lock cannot be obtained.
-*/
-case OP_TableLock: {
- u8 isWriteLock = (u8)pOp->p3;
- if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){
- int p1 = pOp->p1;
- assert( p1>=0 && p1<db->nDb );
- assert( DbMaskTest(p->btreeMask, p1) );
- assert( isWriteLock==0 || isWriteLock==1 );
- rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
- if( rc ){
- if( (rc&0xFF)==SQLITE_LOCKED ){
- const char *z = pOp->p4.z;
- sqlite3VdbeError(p, "database table is locked: %s", z);
- }
- goto abort_due_to_error;
- }
- }
- break;
-}
-#endif /* SQLITE_OMIT_SHARED_CACHE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VBegin * * * P4 *
-**
-** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
-** xBegin method for that table.
-**
-** Also, whether or not P4 is set, check that this is not being called from
-** within a callback to a virtual table xSync() method. If it is, the error
-** code will be set to SQLITE_LOCKED.
-*/
-case OP_VBegin: {
- VTable *pVTab;
- pVTab = pOp->p4.pVtab;
- rc = sqlite3VtabBegin(db, pVTab);
- if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab);
- if( rc ) goto abort_due_to_error;
- break;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VCreate P1 P2 * * *
-**
-** P2 is a register that holds the name of a virtual table in database
-** P1. Call the xCreate method for that table.
-*/
-case OP_VCreate: {
- Mem sMem; /* For storing the record being decoded */
- const char *zTab; /* Name of the virtual table */
-
- memset(&sMem, 0, sizeof(sMem));
- sMem.db = db;
- /* Because P2 is always a static string, it is impossible for the
- ** sqlite3VdbeMemCopy() to fail */
- assert( (aMem[pOp->p2].flags & MEM_Str)!=0 );
- assert( (aMem[pOp->p2].flags & MEM_Static)!=0 );
- rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]);
- assert( rc==SQLITE_OK );
- zTab = (const char*)sqlite3_value_text(&sMem);
- assert( zTab || db->mallocFailed );
- if( zTab ){
- rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg);
- }
- sqlite3VdbeMemRelease(&sMem);
- if( rc ) goto abort_due_to_error;
- break;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VDestroy P1 * * P4 *
-**
-** P4 is the name of a virtual table in database P1. Call the xDestroy method
-** of that table.
-*/
-case OP_VDestroy: {
- db->nVDestroy++;
- rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
- db->nVDestroy--;
- if( rc ) goto abort_due_to_error;
- break;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VOpen P1 * * P4 *
-**
-** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
-** P1 is a cursor number. This opcode opens a cursor to the virtual
-** table and stores that cursor in P1.
-*/
-case OP_VOpen: {
- VdbeCursor *pCur;
- sqlite3_vtab_cursor *pVCur;
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
-
- assert( p->bIsReader );
- pCur = 0;
- pVCur = 0;
- pVtab = pOp->p4.pVtab->pVtab;
- if( pVtab==0 || NEVER(pVtab->pModule==0) ){
- rc = SQLITE_LOCKED;
- goto abort_due_to_error;
- }
- pModule = pVtab->pModule;
- rc = pModule->xOpen(pVtab, &pVCur);
- sqlite3VtabImportErrmsg(p, pVtab);
- if( rc ) goto abort_due_to_error;
-
- /* Initialize sqlite3_vtab_cursor base class */
- pVCur->pVtab = pVtab;
-
- /* Initialize vdbe cursor object */
- pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB);
- if( pCur ){
- pCur->uc.pVCur = pVCur;
- pVtab->nRef++;
- }else{
- assert( db->mallocFailed );
- pModule->xClose(pVCur);
- goto no_mem;
- }
- break;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VFilter P1 P2 P3 P4 *
-** Synopsis: iplan=r[P3] zplan='P4'
-**
-** P1 is a cursor opened using VOpen. P2 is an address to jump to if
-** the filtered result set is empty.
-**
-** P4 is either NULL or a string that was generated by the xBestIndex
-** method of the module. The interpretation of the P4 string is left
-** to the module implementation.
-**
-** This opcode invokes the xFilter method on the virtual table specified
-** by P1. The integer query plan parameter to xFilter is stored in register
-** P3. Register P3+1 stores the argc parameter to be passed to the
-** xFilter method. Registers P3+2..P3+1+argc are the argc
-** additional parameters which are passed to
-** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
-**
-** A jump is made to P2 if the result set after filtering would be empty.
-*/
-case OP_VFilter: { /* jump */
- int nArg;
- int iQuery;
- const sqlite3_module *pModule;
- Mem *pQuery;
- Mem *pArgc;
- sqlite3_vtab_cursor *pVCur;
- sqlite3_vtab *pVtab;
- VdbeCursor *pCur;
- int res;
- int i;
- Mem **apArg;
-
- pQuery = &aMem[pOp->p3];
- pArgc = &pQuery[1];
- pCur = p->apCsr[pOp->p1];
- assert( memIsValid(pQuery) );
- REGISTER_TRACE(pOp->p3, pQuery);
- assert( pCur->eCurType==CURTYPE_VTAB );
- pVCur = pCur->uc.pVCur;
- pVtab = pVCur->pVtab;
- pModule = pVtab->pModule;
-
- /* Grab the index number and argc parameters */
- assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
- nArg = (int)pArgc->u.i;
- iQuery = (int)pQuery->u.i;
-
- /* Invoke the xFilter method */
- res = 0;
- apArg = p->apArg;
- for(i = 0; i<nArg; i++){
- apArg[i] = &pArgc[i+1];
- }
- rc = pModule->xFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg);
- sqlite3VtabImportErrmsg(p, pVtab);
- if( rc ) goto abort_due_to_error;
- res = pModule->xEof(pVCur);
- pCur->nullRow = 0;
- VdbeBranchTaken(res!=0,2);
- if( res ) goto jump_to_p2;
- break;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VColumn P1 P2 P3 * P5
-** Synopsis: r[P3]=vcolumn(P2)
-**
-** Store in register P3 the value of the P2-th column of
-** the current row of the virtual-table of cursor P1.
-**
-** If the VColumn opcode is being used to fetch the value of
-** an unchanging column during an UPDATE operation, then the P5
-** value is 1. Otherwise, P5 is 0. The P5 value is returned
-** by sqlite3_vtab_nochange() routine and can be used
-** by virtual table implementations to return special "no-change"
-** marks which can be more efficient, depending on the virtual table.
-*/
-case OP_VColumn: {
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
- Mem *pDest;
- sqlite3_context sContext;
-
- VdbeCursor *pCur = p->apCsr[pOp->p1];
- assert( pCur->eCurType==CURTYPE_VTAB );
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- pDest = &aMem[pOp->p3];
- memAboutToChange(p, pDest);
- if( pCur->nullRow ){
- sqlite3VdbeMemSetNull(pDest);
- break;
- }
- pVtab = pCur->uc.pVCur->pVtab;
- pModule = pVtab->pModule;
- assert( pModule->xColumn );
- memset(&sContext, 0, sizeof(sContext));
- sContext.pOut = pDest;
- if( pOp->p5 ){
- sqlite3VdbeMemSetNull(pDest);
- pDest->flags = MEM_Null|MEM_Zero;
- pDest->u.nZero = 0;
- }else{
- MemSetTypeFlag(pDest, MEM_Null);
- }
- rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
- sqlite3VtabImportErrmsg(p, pVtab);
- if( sContext.isError>0 ){
- sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest));
- rc = sContext.isError;
- }
- sqlite3VdbeChangeEncoding(pDest, encoding);
- REGISTER_TRACE(pOp->p3, pDest);
- UPDATE_MAX_BLOBSIZE(pDest);
-
- if( sqlite3VdbeMemTooBig(pDest) ){
- goto too_big;
- }
- if( rc ) goto abort_due_to_error;
- break;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VNext P1 P2 * * *
-**
-** Advance virtual table P1 to the next row in its result set and
-** jump to instruction P2. Or, if the virtual table has reached
-** the end of its result set, then fall through to the next instruction.
-*/
-case OP_VNext: { /* jump */
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
- int res;
- VdbeCursor *pCur;
-
- res = 0;
- pCur = p->apCsr[pOp->p1];
- assert( pCur->eCurType==CURTYPE_VTAB );
- if( pCur->nullRow ){
- break;
- }
- pVtab = pCur->uc.pVCur->pVtab;
- pModule = pVtab->pModule;
- assert( pModule->xNext );
-
- /* Invoke the xNext() method of the module. There is no way for the
- ** underlying implementation to return an error if one occurs during
- ** xNext(). Instead, if an error occurs, true is returned (indicating that
- ** data is available) and the error code returned when xColumn or
- ** some other method is next invoked on the save virtual table cursor.
- */
- rc = pModule->xNext(pCur->uc.pVCur);
- sqlite3VtabImportErrmsg(p, pVtab);
- if( rc ) goto abort_due_to_error;
- res = pModule->xEof(pCur->uc.pVCur);
- VdbeBranchTaken(!res,2);
- if( !res ){
- /* If there is data, jump to P2 */
- goto jump_to_p2_and_check_for_interrupt;
- }
- goto check_for_interrupt;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VRename P1 * * P4 *
-**
-** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
-** This opcode invokes the corresponding xRename method. The value
-** in register P1 is passed as the zName argument to the xRename method.
-*/
-case OP_VRename: {
- sqlite3_vtab *pVtab;
- Mem *pName;
-
- pVtab = pOp->p4.pVtab->pVtab;
- pName = &aMem[pOp->p1];
- assert( pVtab->pModule->xRename );
- assert( memIsValid(pName) );
- assert( p->readOnly==0 );
- REGISTER_TRACE(pOp->p1, pName);
- assert( pName->flags & MEM_Str );
- testcase( pName->enc==SQLITE_UTF8 );
- testcase( pName->enc==SQLITE_UTF16BE );
- testcase( pName->enc==SQLITE_UTF16LE );
- rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
- if( rc ) goto abort_due_to_error;
- rc = pVtab->pModule->xRename(pVtab, pName->z);
- sqlite3VtabImportErrmsg(p, pVtab);
- p->expired = 0;
- if( rc ) goto abort_due_to_error;
- break;
-}
-#endif
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VUpdate P1 P2 P3 P4 P5
-** Synopsis: data=r[P3@P2]
-**
-** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
-** This opcode invokes the corresponding xUpdate method. P2 values
-** are contiguous memory cells starting at P3 to pass to the xUpdate
-** invocation. The value in register (P3+P2-1) corresponds to the
-** p2th element of the argv array passed to xUpdate.
-**
-** The xUpdate method will do a DELETE or an INSERT or both.
-** The argv[0] element (which corresponds to memory cell P3)
-** is the rowid of a row to delete. If argv[0] is NULL then no
-** deletion occurs. The argv[1] element is the rowid of the new
-** row. This can be NULL to have the virtual table select the new
-** rowid for itself. The subsequent elements in the array are
-** the values of columns in the new row.
-**
-** If P2==1 then no insert is performed. argv[0] is the rowid of
-** a row to delete.
-**
-** P1 is a boolean flag. If it is set to true and the xUpdate call
-** is successful, then the value returned by sqlite3_last_insert_rowid()
-** is set to the value of the rowid for the row just inserted.
-**
-** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to
-** apply in the case of a constraint failure on an insert or update.
-*/
-case OP_VUpdate: {
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
- int nArg;
- int i;
- sqlite_int64 rowid;
- Mem **apArg;
- Mem *pX;
-
- assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
- || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
- );
- assert( p->readOnly==0 );
- sqlite3VdbeIncrWriteCounter(p, 0);
- pVtab = pOp->p4.pVtab->pVtab;
- if( pVtab==0 || NEVER(pVtab->pModule==0) ){
- rc = SQLITE_LOCKED;
- goto abort_due_to_error;
- }
- pModule = pVtab->pModule;
- nArg = pOp->p2;
- assert( pOp->p4type==P4_VTAB );
- if( ALWAYS(pModule->xUpdate) ){
- u8 vtabOnConflict = db->vtabOnConflict;
- apArg = p->apArg;
- pX = &aMem[pOp->p3];
- for(i=0; i<nArg; i++){
- assert( memIsValid(pX) );
- memAboutToChange(p, pX);
- apArg[i] = pX;
- pX++;
- }
- db->vtabOnConflict = pOp->p5;
- rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
- db->vtabOnConflict = vtabOnConflict;
- sqlite3VtabImportErrmsg(p, pVtab);
- if( rc==SQLITE_OK && pOp->p1 ){
- assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
- db->lastRowid = rowid;
- }
- if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
- if( pOp->p5==OE_Ignore ){
- rc = SQLITE_OK;
- }else{
- p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
- }
- }else{
- p->nChange++;
- }
- if( rc ) goto abort_due_to_error;
- }
- break;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-/* Opcode: Pagecount P1 P2 * * *
-**
-** Write the current number of pages in database P1 to memory cell P2.
-*/
-case OP_Pagecount: { /* out2 */
- pOut = out2Prerelease(p, pOp);
- pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt);
- break;
-}
-#endif
-
-
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-/* Opcode: MaxPgcnt P1 P2 P3 * *
-**
-** Try to set the maximum page count for database P1 to the value in P3.
-** Do not let the maximum page count fall below the current page count and
-** do not change the maximum page count value if P3==0.
-**
-** Store the maximum page count after the change in register P2.
-*/
-case OP_MaxPgcnt: { /* out2 */
- unsigned int newMax;
- Btree *pBt;
-
- pOut = out2Prerelease(p, pOp);
- pBt = db->aDb[pOp->p1].pBt;
- newMax = 0;
- if( pOp->p3 ){
- newMax = sqlite3BtreeLastPage(pBt);
- if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3;
- }
- pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax);
- break;
-}
-#endif
-
-/* Opcode: Function0 P1 P2 P3 P4 P5
-** Synopsis: r[P3]=func(r[P2@P5])
-**
-** Invoke a user function (P4 is a pointer to a FuncDef object that
-** defines the function) with P5 arguments taken from register P2 and
-** successors. The result of the function is stored in register P3.
-** Register P3 must not be one of the function inputs.
-**
-** P1 is a 32-bit bitmask indicating whether or not each argument to the
-** function was determined to be constant at compile time. If the first
-** argument was constant then bit 0 of P1 is set. This is used to determine
-** whether meta data associated with a user function argument using the
-** sqlite3_set_auxdata() API may be safely retained until the next
-** invocation of this opcode.
-**
-** See also: Function, AggStep, AggFinal
-*/
-/* Opcode: Function P1 P2 P3 P4 P5
-** Synopsis: r[P3]=func(r[P2@P5])
-**
-** Invoke a user function (P4 is a pointer to an sqlite3_context object that
-** contains a pointer to the function to be run) with P5 arguments taken
-** from register P2 and successors. The result of the function is stored
-** in register P3. Register P3 must not be one of the function inputs.
-**
-** P1 is a 32-bit bitmask indicating whether or not each argument to the
-** function was determined to be constant at compile time. If the first
-** argument was constant then bit 0 of P1 is set. This is used to determine
-** whether meta data associated with a user function argument using the
-** sqlite3_set_auxdata() API may be safely retained until the next
-** invocation of this opcode.
-**
-** SQL functions are initially coded as OP_Function0 with P4 pointing
-** to a FuncDef object. But on first evaluation, the P4 operand is
-** automatically converted into an sqlite3_context object and the operation
-** changed to this OP_Function opcode. In this way, the initialization of
-** the sqlite3_context object occurs only once, rather than once for each
-** evaluation of the function.
-**
-** See also: Function0, AggStep, AggFinal
-*/
-case OP_PureFunc0:
-case OP_Function0: {
- int n;
- sqlite3_context *pCtx;
-
- assert( pOp->p4type==P4_FUNCDEF );
- n = pOp->p5;
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
- assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
- if( pCtx==0 ) goto no_mem;
- pCtx->pOut = 0;
- pCtx->pFunc = pOp->p4.pFunc;
- pCtx->iOp = (int)(pOp - aOp);
- pCtx->pVdbe = p;
- pCtx->isError = 0;
- pCtx->argc = n;
- pOp->p4type = P4_FUNCCTX;
- pOp->p4.pCtx = pCtx;
- assert( OP_PureFunc == OP_PureFunc0+2 );
- assert( OP_Function == OP_Function0+2 );
- pOp->opcode += 2;
- /* Fall through into OP_Function */
-}
-case OP_PureFunc:
-case OP_Function: {
- int i;
- sqlite3_context *pCtx;
-
- assert( pOp->p4type==P4_FUNCCTX );
- pCtx = pOp->p4.pCtx;
-
- /* If this function is inside of a trigger, the register array in aMem[]
- ** might change from one evaluation to the next. The next block of code
- ** checks to see if the register array has changed, and if so it
- ** reinitializes the relavant parts of the sqlite3_context object */
- pOut = &aMem[pOp->p3];
- if( pCtx->pOut != pOut ){
- pCtx->pOut = pOut;
- for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
- }
-
- memAboutToChange(p, pOut);
-#ifdef SQLITE_DEBUG
- for(i=0; i<pCtx->argc; i++){
- assert( memIsValid(pCtx->argv[i]) );
- REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
- }
-#endif
- MemSetTypeFlag(pOut, MEM_Null);
- assert( pCtx->isError==0 );
- (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
-
- /* If the function returned an error, throw an exception */
- if( pCtx->isError ){
- if( pCtx->isError>0 ){
- sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
- rc = pCtx->isError;
- }
- sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
- pCtx->isError = 0;
- if( rc ) goto abort_due_to_error;
- }
-
- /* Copy the result of the function into register P3 */
- if( pOut->flags & (MEM_Str|MEM_Blob) ){
- sqlite3VdbeChangeEncoding(pOut, encoding);
- if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
- }
-
- REGISTER_TRACE(pOp->p3, pOut);
- UPDATE_MAX_BLOBSIZE(pOut);
- break;
-}
-
-/* Opcode: Trace P1 P2 * P4 *
-**
-** Write P4 on the statement trace output if statement tracing is
-** enabled.
-**
-** Operand P1 must be 0x7fffffff and P2 must positive.
-*/
-/* Opcode: Init P1 P2 P3 P4 *
-** Synopsis: Start at P2
-**
-** Programs contain a single instance of this opcode as the very first
-** opcode.
-**
-** If tracing is enabled (by the sqlite3_trace()) interface, then
-** the UTF-8 string contained in P4 is emitted on the trace callback.
-** Or if P4 is blank, use the string returned by sqlite3_sql().
-**
-** If P2 is not zero, jump to instruction P2.
-**
-** Increment the value of P1 so that OP_Once opcodes will jump the
-** first time they are evaluated for this run.
-**
-** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT
-** error is encountered.
-*/
-case OP_Trace:
-case OP_Init: { /* jump */
- int i;
-#ifndef SQLITE_OMIT_TRACE
- char *zTrace;
-#endif
-
- /* If the P4 argument is not NULL, then it must be an SQL comment string.
- ** The "--" string is broken up to prevent false-positives with srcck1.c.
- **
- ** This assert() provides evidence for:
- ** EVIDENCE-OF: R-50676-09860 The callback can compute the same text that
- ** would have been returned by the legacy sqlite3_trace() interface by
- ** using the X argument when X begins with "--" and invoking
- ** sqlite3_expanded_sql(P) otherwise.
- */
- assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 );
-
- /* OP_Init is always instruction 0 */
- assert( pOp==p->aOp || pOp->opcode==OP_Trace );
-
-#ifndef SQLITE_OMIT_TRACE
- if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
- && !p->doingRerun
- && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
- ){
-#ifndef SQLITE_OMIT_DEPRECATED
- if( db->mTrace & SQLITE_TRACE_LEGACY ){
- void (*x)(void*,const char*) = (void(*)(void*,const char*))db->xTrace;
- char *z = sqlite3VdbeExpandSql(p, zTrace);
- x(db->pTraceArg, z);
- sqlite3_free(z);
- }else
-#endif
- if( db->nVdbeExec>1 ){
- char *z = sqlite3MPrintf(db, "-- %s", zTrace);
- (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, z);
- sqlite3DbFree(db, z);
- }else{
- (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
- }
- }
-#ifdef SQLITE_USE_FCNTL_TRACE
- zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
- if( zTrace ){
- int j;
- for(j=0; j<db->nDb; j++){
- if( DbMaskTest(p->btreeMask, j)==0 ) continue;
- sqlite3_file_control(db, db->aDb[j].zDbSName, SQLITE_FCNTL_TRACE, zTrace);
- }
- }
-#endif /* SQLITE_USE_FCNTL_TRACE */
-#ifdef SQLITE_DEBUG
- if( (db->flags & SQLITE_SqlTrace)!=0
- && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
- ){
- sqlite3DebugPrintf("SQL-trace: %s\n", zTrace);
- }
-#endif /* SQLITE_DEBUG */
-#endif /* SQLITE_OMIT_TRACE */
- assert( pOp->p2>0 );
- if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){
- if( pOp->opcode==OP_Trace ) break;
- for(i=1; i<p->nOp; i++){
- if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0;
- }
- pOp->p1 = 0;
- }
- pOp->p1++;
- p->aCounter[SQLITE_STMTSTATUS_RUN]++;
- goto jump_to_p2;
-}
-
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
-/* Opcode: CursorHint P1 * * P4 *
-**
-** Provide a hint to cursor P1 that it only needs to return rows that
-** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer
-** to values currently held in registers. TK_COLUMN terms in the P4
-** expression refer to columns in the b-tree to which cursor P1 is pointing.
-*/
-case OP_CursorHint: {
- VdbeCursor *pC;
-
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( pOp->p4type==P4_EXPR );
- pC = p->apCsr[pOp->p1];
- if( pC ){
- assert( pC->eCurType==CURTYPE_BTREE );
- sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE,
- pOp->p4.pExpr, aMem);
- }
- break;
-}
-#endif /* SQLITE_ENABLE_CURSOR_HINTS */
-
-#ifdef SQLITE_DEBUG
-/* Opcode: Abortable * * * * *
-**
-** Verify that an Abort can happen. Assert if an Abort at this point
-** might cause database corruption. This opcode only appears in debugging
-** builds.
-**
-** An Abort is safe if either there have been no writes, or if there is
-** an active statement journal.
-*/
-case OP_Abortable: {
- sqlite3VdbeAssertAbortable(p);
- break;
-}
-#endif
-
-/* Opcode: Noop * * * * *
-**
-** Do nothing. This instruction is often useful as a jump
-** destination.
-*/
-/*
-** The magic Explain opcode are only inserted when explain==2 (which
-** is to say when the EXPLAIN QUERY PLAN syntax is used.)
-** This opcode records information from the optimizer. It is the
-** the same as a no-op. This opcodesnever appears in a real VM program.
-*/
-default: { /* This is really OP_Noop, OP_Explain */
- assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
-
- break;
-}
-
-/*****************************************************************************
-** The cases of the switch statement above this line should all be indented
-** by 6 spaces. But the left-most 6 spaces have been removed to improve the
-** readability. From this point on down, the normal indentation rules are
-** restored.
-*****************************************************************************/
- }
-
-#ifdef VDBE_PROFILE
- {
- u64 endTime = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
- if( endTime>start ) pOrigOp->cycles += endTime - start;
- pOrigOp->cnt++;
- }
-#endif
-
- /* The following code adds nothing to the actual functionality
- ** of the program. It is only here for testing and debugging.
- ** On the other hand, it does burn CPU cycles every time through
- ** the evaluator loop. So we can leave it out when NDEBUG is defined.
- */
-#ifndef NDEBUG
- assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] );
-
-#ifdef SQLITE_DEBUG
- if( db->flags & SQLITE_VdbeTrace ){
- u8 opProperty = sqlite3OpcodeProperty[pOrigOp->opcode];
- if( rc!=0 ) printf("rc=%d\n",rc);
- if( opProperty & (OPFLG_OUT2) ){
- registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]);
- }
- if( opProperty & OPFLG_OUT3 ){
- registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]);
- }
- }
-#endif /* SQLITE_DEBUG */
-#endif /* NDEBUG */
- } /* The end of the for(;;) loop the loops through opcodes */
-
- /* If we reach this point, it means that execution is finished with
- ** an error of some kind.
- */
-abort_due_to_error:
- if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT;
- assert( rc );
- if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){
- sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
- }
- p->rc = rc;
- sqlite3SystemError(db, rc);
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(rc, "statement aborts at %d: [%s] %s",
- (int)(pOp - aOp), p->zSql, p->zErrMsg);
- sqlite3VdbeHalt(p);
- if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
- rc = SQLITE_ERROR;
- if( resetSchemaOnFault>0 ){
- sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
- }
-
- /* This is the only way out of this procedure. We have to
- ** release the mutexes on btrees that were acquired at the
- ** top. */
-vdbe_return:
- testcase( nVmStep>0 );
- p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
- sqlite3VdbeLeave(p);
- assert( rc!=SQLITE_OK || nExtraDelete==0
- || sqlite3_strlike("DELETE%",p->zSql,0)!=0
- );
- return rc;
-
- /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
- ** is encountered.
- */
-too_big:
- sqlite3VdbeError(p, "string or blob too big");
- rc = SQLITE_TOOBIG;
- goto abort_due_to_error;
-
- /* Jump to here if a malloc() fails.
- */
-no_mem:
- sqlite3OomFault(db);
- sqlite3VdbeError(p, "out of memory");
- rc = SQLITE_NOMEM_BKPT;
- goto abort_due_to_error;
-
- /* Jump to here if the sqlite3_interrupt() API sets the interrupt
- ** flag.
- */
-abort_due_to_interrupt:
- assert( db->u1.isInterrupted );
- rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
- p->rc = rc;
- sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
- goto abort_due_to_error;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbe.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbe.h
deleted file mode 100644
index 51bbdf96ccb..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbe.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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.
-**
-*************************************************************************
-** Header file for the Virtual DataBase Engine (VDBE)
-**
-** This header defines the interface to the virtual database engine
-** or VDBE. The VDBE implements an abstract machine that runs a
-** simple program to access and modify the underlying database.
-*/
-#ifndef SQLITE_VDBE_H
-#define SQLITE_VDBE_H
-#include <stdio.h>
-
-/*
-** A single VDBE is an opaque structure named "Vdbe". Only routines
-** in the source file sqliteVdbe.c are allowed to see the insides
-** of this structure.
-*/
-typedef struct Vdbe Vdbe;
-
-/*
-** The names of the following types declared in vdbeInt.h are required
-** for the VdbeOp definition.
-*/
-typedef struct sqlite3_value Mem;
-typedef struct SubProgram SubProgram;
-
-/*
-** A single instruction of the virtual machine has an opcode
-** and as many as three operands. The instruction is recorded
-** as an instance of the following structure:
-*/
-struct VdbeOp {
- u8 opcode; /* What operation to perform */
- signed char p4type; /* One of the P4_xxx constants for p4 */
- u16 p5; /* Fifth parameter is an unsigned 16-bit integer */
- int p1; /* First operand */
- int p2; /* Second parameter (often the jump destination) */
- int p3; /* The third parameter */
- union p4union { /* fourth parameter */
- int i; /* Integer value if p4type==P4_INT32 */
- void *p; /* Generic pointer */
- char *z; /* Pointer to data for string (char array) types */
- i64 *pI64; /* Used when p4type is P4_INT64 */
- double *pReal; /* Used when p4type is P4_REAL */
- FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
- sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */
- CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
- Mem *pMem; /* Used when p4type is P4_MEM */
- VTable *pVtab; /* Used when p4type is P4_VTAB */
- KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
- int *ai; /* Used when p4type is P4_INTARRAY */
- SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
- Table *pTab; /* Used when p4type is P4_TABLE */
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
- Expr *pExpr; /* Used when p4type is P4_EXPR */
-#endif
- int (*xAdvance)(BtCursor *, int);
- } p4;
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- char *zComment; /* Comment to improve readability */
-#endif
-#ifdef VDBE_PROFILE
- u32 cnt; /* Number of times this instruction was executed */
- u64 cycles; /* Total time spent executing this instruction */
-#endif
-#ifdef SQLITE_VDBE_COVERAGE
- int iSrcLine; /* Source-code line that generated this opcode */
-#endif
-};
-typedef struct VdbeOp VdbeOp;
-
-
-/*
-** A sub-routine used to implement a trigger program.
-*/
-struct SubProgram {
- VdbeOp *aOp; /* Array of opcodes for sub-program */
- int nOp; /* Elements in aOp[] */
- int nMem; /* Number of memory cells required */
- int nCsr; /* Number of cursors required */
- u8 *aOnce; /* Array of OP_Once flags */
- void *token; /* id that may be used to recursive triggers */
- SubProgram *pNext; /* Next sub-program already visited */
-};
-
-/*
-** A smaller version of VdbeOp used for the VdbeAddOpList() function because
-** it takes up less space.
-*/
-struct VdbeOpList {
- u8 opcode; /* What operation to perform */
- signed char p1; /* First operand */
- signed char p2; /* Second parameter (often the jump destination) */
- signed char p3; /* Third parameter */
-};
-typedef struct VdbeOpList VdbeOpList;
-
-/*
-** Allowed values of VdbeOp.p4type
-*/
-#define P4_NOTUSED 0 /* The P4 parameter is not used */
-#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
-#define P4_STATIC (-1) /* Pointer to a static string */
-#define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */
-#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */
-#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */
-#define P4_ADVANCE (-5) /* P4 is a pointer to BtreeNext() or BtreePrev() */
-#define P4_TABLE (-6) /* P4 is a pointer to a Table structure */
-/* Above do not own any resources. Must free those below */
-#define P4_FREE_IF_LE (-7)
-#define P4_DYNAMIC (-7) /* Pointer to memory from sqliteMalloc() */
-#define P4_FUNCDEF (-8) /* P4 is a pointer to a FuncDef structure */
-#define P4_KEYINFO (-9) /* P4 is a pointer to a KeyInfo structure */
-#define P4_EXPR (-10) /* P4 is a pointer to an Expr tree */
-#define P4_MEM (-11) /* P4 is a pointer to a Mem* structure */
-#define P4_VTAB (-12) /* P4 is a pointer to an sqlite3_vtab structure */
-#define P4_REAL (-13) /* P4 is a 64-bit floating point value */
-#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */
-#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
-#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */
-#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */
-
-/* Error message codes for OP_Halt */
-#define P5_ConstraintNotNull 1
-#define P5_ConstraintUnique 2
-#define P5_ConstraintCheck 3
-#define P5_ConstraintFK 4
-
-/*
-** The Vdbe.aColName array contains 5n Mem structures, where n is the
-** number of columns of data returned by the statement.
-*/
-#define COLNAME_NAME 0
-#define COLNAME_DECLTYPE 1
-#define COLNAME_DATABASE 2
-#define COLNAME_TABLE 3
-#define COLNAME_COLUMN 4
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
-# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */
-#else
-# ifdef SQLITE_OMIT_DECLTYPE
-# define COLNAME_N 1 /* Store only the name */
-# else
-# define COLNAME_N 2 /* Store the name and decltype */
-# endif
-#endif
-
-/*
-** The following macro converts a relative address in the p2 field
-** of a VdbeOp structure into a negative number so that
-** sqlite3VdbeAddOpList() knows that the address is relative. Calling
-** the macro again restores the address.
-*/
-#define ADDR(X) (-1-(X))
-
-/*
-** The makefile scans the vdbe.c source file and creates the "opcodes.h"
-** header file that defines a number for each opcode used by the VDBE.
-*/
-#include "opcodes.h"
-
-/*
-** Additional non-public SQLITE_PREPARE_* flags
-*/
-#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
-#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
-
-/*
-** Prototypes for the VDBE interface. See comments on the implementation
-** for a description of what each of these routines does.
-*/
-Vdbe *sqlite3VdbeCreate(Parse*);
-int sqlite3VdbeAddOp0(Vdbe*,int);
-int sqlite3VdbeAddOp1(Vdbe*,int,int);
-int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
-int sqlite3VdbeGoto(Vdbe*,int);
-int sqlite3VdbeLoadString(Vdbe*,int,const char*);
-void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...);
-int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
-int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
-int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
-int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
-void sqlite3VdbeEndCoroutine(Vdbe*,int);
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
- void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
- void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
-#else
-# define sqlite3VdbeVerifyNoMallocRequired(A,B)
-# define sqlite3VdbeVerifyNoResultRow(A)
-#endif
-#if defined(SQLITE_DEBUG)
- void sqlite3VdbeVerifyAbortable(Vdbe *p, int);
-#else
-# define sqlite3VdbeVerifyAbortable(A,B)
-#endif
-VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
-#ifndef SQLITE_OMIT_EXPLAIN
- void sqlite3VdbeExplain(Parse*,u8,const char*,...);
- void sqlite3VdbeExplainPop(Parse*);
- int sqlite3VdbeExplainParent(Parse*);
-# define ExplainQueryPlan(P) sqlite3VdbeExplain P
-# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P)
-# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P)
-#else
-# define ExplainQueryPlan(P)
-# define ExplainQueryPlanPop(P)
-# define ExplainQueryPlanParent(P) 0
-#endif
-void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
-void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
-void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
-void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
-void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
-void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
-void sqlite3VdbeJumpHere(Vdbe*, int addr);
-int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
-int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
-void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
-void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
-void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
-void sqlite3VdbeUsesBtree(Vdbe*, int);
-VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
-int sqlite3VdbeMakeLabel(Vdbe*);
-void sqlite3VdbeRunOnlyOnce(Vdbe*);
-void sqlite3VdbeReusable(Vdbe*);
-void sqlite3VdbeDelete(Vdbe*);
-void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
-void sqlite3VdbeMakeReady(Vdbe*,Parse*);
-int sqlite3VdbeFinalize(Vdbe*);
-void sqlite3VdbeResolveLabel(Vdbe*, int);
-#ifdef SQLITE_COVERAGE_TEST
- int sqlite3VdbeLabelHasBeenResolved(Vdbe*,int);
-#endif
-int sqlite3VdbeCurrentAddr(Vdbe*);
-#ifdef SQLITE_DEBUG
- int sqlite3VdbeAssertMayAbort(Vdbe *, int);
-#endif
-void sqlite3VdbeResetStepResult(Vdbe*);
-void sqlite3VdbeRewind(Vdbe*);
-int sqlite3VdbeReset(Vdbe*);
-void sqlite3VdbeSetNumCols(Vdbe*,int);
-int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
-void sqlite3VdbeCountChanges(Vdbe*);
-sqlite3 *sqlite3VdbeDb(Vdbe*);
-u8 sqlite3VdbePrepareFlags(Vdbe*);
-void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
-void sqlite3VdbeSwap(Vdbe*,Vdbe*);
-VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
-sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
-void sqlite3VdbeSetVarmask(Vdbe*, int);
-#ifndef SQLITE_OMIT_TRACE
- char *sqlite3VdbeExpandSql(Vdbe*, const char*);
-#endif
-int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
-
-void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
-int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
-int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
-UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
-
-typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
-RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
-
-#ifndef SQLITE_OMIT_TRIGGER
-void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
-#endif
-
-int sqlite3NotPureFunc(sqlite3_context*);
-
-/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
-** each VDBE opcode.
-**
-** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
-** comments in VDBE programs that show key decision points in the code
-** generator.
-*/
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- void sqlite3VdbeComment(Vdbe*, const char*, ...);
-# define VdbeComment(X) sqlite3VdbeComment X
- void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
-# define VdbeNoopComment(X) sqlite3VdbeNoopComment X
-# ifdef SQLITE_ENABLE_MODULE_COMMENTS
-# define VdbeModuleComment(X) sqlite3VdbeNoopComment X
-# else
-# define VdbeModuleComment(X)
-# endif
-#else
-# define VdbeComment(X)
-# define VdbeNoopComment(X)
-# define VdbeModuleComment(X)
-#endif
-
-/*
-** The VdbeCoverage macros are used to set a coverage testing point
-** for VDBE branch instructions. The coverage testing points are line
-** numbers in the sqlite3.c source file. VDBE branch coverage testing
-** only works with an amalagmation build. That's ok since a VDBE branch
-** coverage build designed for testing the test suite only. No application
-** should ever ship with VDBE branch coverage measuring turned on.
-**
-** VdbeCoverage(v) // Mark the previously coded instruction
-** // as a branch
-**
-** VdbeCoverageIf(v, conditional) // Mark previous if conditional true
-**
-** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken
-**
-** VdbeCoverageNeverTaken(v) // Previous branch is never taken
-**
-** Every VDBE branch operation must be tagged with one of the macros above.
-** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
-** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch()
-** routine in vdbe.c, alerting the developer to the missed tag.
-*/
-#ifdef SQLITE_VDBE_COVERAGE
- void sqlite3VdbeSetLineNumber(Vdbe*,int);
-# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
-# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
-# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2);
-# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1);
-# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
-#else
-# define VdbeCoverage(v)
-# define VdbeCoverageIf(v,x)
-# define VdbeCoverageAlwaysTaken(v)
-# define VdbeCoverageNeverTaken(v)
-# define VDBE_OFFSET_LINENO(x) 0
-#endif
-
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
-void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*);
-#else
-# define sqlite3VdbeScanStatus(a,b,c,d,e)
-#endif
-
-#endif /* SQLITE_VDBE_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeInt.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeInt.h
deleted file mode 100644
index 0f10e3759dd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeInt.h
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
-** 2003 September 6
-**
-** 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 is the header file for information that is private to the
-** VDBE. This information used to all be at the top of the single
-** source code file "vdbe.c". When that file became too big (over
-** 6000 lines long) it was split up into several smaller files and
-** this header information was factored out.
-*/
-#ifndef SQLITE_VDBEINT_H
-#define SQLITE_VDBEINT_H
-
-/*
-** 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 50
-#endif
-
-/*
-** VDBE_DISPLAY_P4 is true or false depending on whether or not the
-** "explain" P4 display logic is enabled.
-*/
-#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
- || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
-# define VDBE_DISPLAY_P4 1
-#else
-# define VDBE_DISPLAY_P4 0
-#endif
-
-/*
-** SQL is translated into a sequence of instructions to be
-** executed by a virtual machine. Each instruction is an instance
-** of the following structure.
-*/
-typedef struct VdbeOp Op;
-
-/*
-** Boolean values
-*/
-typedef unsigned Bool;
-
-/* Opaque type used by code in vdbesort.c */
-typedef struct VdbeSorter VdbeSorter;
-
-/* Elements of the linked list at Vdbe.pAuxData */
-typedef struct AuxData AuxData;
-
-/* Types of VDBE cursors */
-#define CURTYPE_BTREE 0
-#define CURTYPE_SORTER 1
-#define CURTYPE_VTAB 2
-#define CURTYPE_PSEUDO 3
-
-/*
-** A VdbeCursor is an superclass (a wrapper) for various cursor objects:
-**
-** * A b-tree cursor
-** - In the main database or in an ephemeral database
-** - On either an index or a table
-** * A sorter
-** * A virtual table
-** * A one-row "pseudotable" stored in a single register
-*/
-typedef struct VdbeCursor VdbeCursor;
-struct VdbeCursor {
- u8 eCurType; /* One of the CURTYPE_* values above */
- i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
- u8 nullRow; /* True if pointing to a row with no data */
- u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
- u8 isTable; /* True for rowid tables. False for indexes */
-#ifdef SQLITE_DEBUG
- u8 seekOp; /* Most recent seek operation on this cursor */
- u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
-#endif
- Bool isEphemeral:1; /* True for an ephemeral table */
- Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
- Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
- Btree *pBtx; /* Separate file holding temporary table */
- i64 seqCount; /* Sequence counter */
- int *aAltMap; /* Mapping from table to index column numbers */
-
- /* Cached OP_Column parse information is only valid if cacheStatus matches
- ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
- ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that
- ** the cache is out of date. */
- u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
- int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0
- ** if there have been no prior seeks on the cursor. */
- /* seekResult does not distinguish between "no seeks have ever occurred
- ** on this cursor" and "the most recent seek was an exact match".
- ** For CURTYPE_PSEUDO, seekResult is the register holding the record */
-
- /* When a new VdbeCursor is allocated, only the fields above are zeroed.
- ** The fields that follow are uninitialized, and must be individually
- ** initialized prior to first use. */
- VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
- union {
- BtCursor *pCursor; /* CURTYPE_BTREE or _PSEUDO. Btree cursor */
- sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */
- VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */
- } uc;
- KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
- u32 iHdrOffset; /* Offset to next unparsed byte of the header */
- Pgno pgnoRoot; /* Root page of the open btree cursor */
- i16 nField; /* Number of fields in the header */
- u16 nHdrParsed; /* Number of header fields parsed so far */
- i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
- u32 *aOffset; /* Pointer to aType[nField] */
- const u8 *aRow; /* Data for the current row, if all on one page */
- u32 payloadSize; /* Total number of bytes in the record */
- u32 szRow; /* Byte available in aRow */
-#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
- u64 maskUsed; /* Mask of columns used by this cursor */
-#endif
-
- /* 2*nField extra array elements allocated for aType[], beyond the one
- ** static element declared in the structure. nField total array slots for
- ** aType[] and nField+1 array slots for aOffset[] */
- u32 aType[1]; /* Type values record decode. MUST BE LAST */
-};
-
-
-/*
-** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
-*/
-#define CACHE_STALE 0
-
-/*
-** When a sub-program is executed (OP_Program), a structure of this type
-** is allocated to store the current value of the program counter, as
-** well as the current memory cell array and various other frame specific
-** values stored in the Vdbe struct. When the sub-program is finished,
-** these values are copied back to the Vdbe from the VdbeFrame structure,
-** restoring the state of the VM to as it was before the sub-program
-** began executing.
-**
-** The memory for a VdbeFrame object is allocated and managed by a memory
-** cell in the parent (calling) frame. When the memory cell is deleted or
-** overwritten, the VdbeFrame object is not freed immediately. Instead, it
-** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
-** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
-** this instead of deleting the VdbeFrame immediately is to avoid recursive
-** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
-** child frame are released.
-**
-** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
-** set to NULL if the currently executing frame is the main program.
-*/
-typedef struct VdbeFrame VdbeFrame;
-struct VdbeFrame {
- Vdbe *v; /* VM this frame belongs to */
- VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
- Op *aOp; /* Program instructions for parent frame */
- i64 *anExec; /* Event counters from parent frame */
- Mem *aMem; /* Array of memory cells for parent frame */
- VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
- u8 *aOnce; /* Bitmask used by OP_Once */
- void *token; /* Copy of SubProgram.token */
- i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
- AuxData *pAuxData; /* Linked list of auxdata allocations */
- int nCursor; /* Number of entries in apCsr */
- int pc; /* Program Counter in parent (calling) frame */
- int nOp; /* Size of aOp array */
- int nMem; /* Number of entries in aMem */
- int nChildMem; /* Number of memory cells for child frame */
- int nChildCsr; /* Number of cursors for child frame */
- int nChange; /* Statement changes (Vdbe.nChange) */
- int nDbChange; /* Value of db->nChange */
-};
-
-#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
-
-/*
-** Internally, the vdbe manipulates nearly all SQL values as Mem
-** structures. Each Mem struct may cache multiple representations (string,
-** integer etc.) of the same value.
-*/
-struct sqlite3_value {
- union MemValue {
- double r; /* Real value used when MEM_Real is set in flags */
- i64 i; /* Integer value used when MEM_Int is set in flags */
- int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */
- const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
- FuncDef *pDef; /* Used only when flags==MEM_Agg */
- RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
- VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
- } u;
- u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
- u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
- u8 eSubtype; /* Subtype for this value */
- int n; /* Number of characters in string value, excluding '\0' */
- char *z; /* String or BLOB value */
- /* ShallowCopy only needs to copy the information above */
- char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
- int szMalloc; /* Size of the zMalloc allocation */
- u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */
- sqlite3 *db; /* The associated database connection */
- void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
-#ifdef SQLITE_DEBUG
- Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
- void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
-#endif
-};
-
-/*
-** Size of struct Mem not including the Mem.zMalloc member or anything that
-** follows.
-*/
-#define MEMCELLSIZE offsetof(Mem,zMalloc)
-
-/* One or more of the following flags are set to indicate the validOK
-** representations of the value stored in the Mem struct.
-**
-** If the MEM_Null flag is set, then the value is an SQL NULL value.
-** For a pointer type created using sqlite3_bind_pointer() or
-** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
-**
-** If the MEM_Str flag is set then Mem.z points at a string representation.
-** Usually this is encoded in the same unicode encoding as the main
-** database (see below for exceptions). If the MEM_Term flag is also
-** set, then the string is nul terminated. The MEM_Int and MEM_Real
-** flags may coexist with the MEM_Str flag.
-*/
-#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
-#define MEM_Str 0x0002 /* Value is a string */
-#define MEM_Int 0x0004 /* Value is an integer */
-#define MEM_Real 0x0008 /* Value is a real number */
-#define MEM_Blob 0x0010 /* Value is a BLOB */
-#define MEM_AffMask 0x001f /* Mask of affinity bits */
-#define MEM_RowSet 0x0020 /* Value is a RowSet object */
-#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
-#define MEM_Undefined 0x0080 /* Value is undefined */
-#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
-#define MEM_TypeMask 0xc1ff /* Mask of type bits */
-
-
-/* Whenever Mem contains a valid string or blob representation, one of
-** the following flags must be set to determine the memory management
-** policy for Mem.z. The MEM_Term flag tells us whether or not the
-** string is \000 or \u0000 terminated
-*/
-#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */
-#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
-#define MEM_Static 0x0800 /* Mem.z points to a static string */
-#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
-#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
-#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
-#define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */
-#ifdef SQLITE_OMIT_INCRBLOB
- #undef MEM_Zero
- #define MEM_Zero 0x0000
-#endif
-
-/* Return TRUE if Mem X contains dynamically allocated content - anything
-** that needs to be deallocated to avoid a leak.
-*/
-#define VdbeMemDynamic(X) \
- (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0)
-
-/*
-** Clear any existing type flags from a Mem and replace them with f
-*/
-#define MemSetTypeFlag(p, f) \
- ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
-
-/*
-** Return true if a memory cell is not marked as invalid. This macro
-** is for use inside assert() statements only.
-*/
-#ifdef SQLITE_DEBUG
-#define memIsValid(M) ((M)->flags & MEM_Undefined)==0
-#endif
-
-/*
-** Each auxiliary data pointer stored by a user defined function
-** implementation calling sqlite3_set_auxdata() is stored in an instance
-** of this structure. All such structures associated with a single VM
-** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
-** when the VM is halted (if not before).
-*/
-struct AuxData {
- int iAuxOp; /* Instruction number of OP_Function opcode */
- int iAuxArg; /* Index of function argument. */
- void *pAux; /* Aux data pointer */
- void (*xDeleteAux)(void*); /* Destructor for the aux data */
- AuxData *pNextAux; /* Next element in list */
-};
-
-/*
-** The "context" argument for an installable function. A pointer to an
-** instance of this structure is the first argument to the routines used
-** implement the SQL functions.
-**
-** There is a typedef for this structure in sqlite.h. So all routines,
-** even the public interface to SQLite, can use a pointer to this structure.
-** But this file is the only place where the internal details of this
-** structure are known.
-**
-** This structure is defined inside of vdbeInt.h because it uses substructures
-** (Mem) which are only defined there.
-*/
-struct sqlite3_context {
- Mem *pOut; /* The return value is stored here */
- FuncDef *pFunc; /* Pointer to function information */
- Mem *pMem; /* Memory cell used to store aggregate context */
- Vdbe *pVdbe; /* The VM that owns this context */
- int iOp; /* Instruction number of OP_Function */
- int isError; /* Error code returned by the function. */
- u8 skipFlag; /* Skip accumulator loading if true */
- u8 argc; /* Number of arguments */
- sqlite3_value *argv[1]; /* Argument set */
-};
-
-/* A bitfield type for use inside of structures. Always follow with :N where
-** N is the number of bits.
-*/
-typedef unsigned bft; /* Bit Field Type */
-
-typedef struct ScanStatus ScanStatus;
-struct ScanStatus {
- int addrExplain; /* OP_Explain for loop */
- int addrLoop; /* Address of "loops" counter */
- int addrVisit; /* Address of "rows visited" counter */
- int iSelectID; /* The "Select-ID" for this loop */
- LogEst nEst; /* Estimated output rows per loop */
- char *zName; /* Name of table or index */
-};
-
-/*
-** An instance of the virtual machine. This structure contains the complete
-** state of the virtual machine.
-**
-** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
-** is really a pointer to an instance of this structure.
-*/
-struct Vdbe {
- sqlite3 *db; /* The database connection that owns this statement */
- Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
- Parse *pParse; /* Parsing context used to create this Vdbe */
- ynVar nVar; /* Number of entries in aVar[] */
- u32 magic; /* Magic number for sanity checking */
- int nMem; /* Number of memory locations currently allocated */
- int nCursor; /* Number of slots in apCsr[] */
- u32 cacheCtr; /* VdbeCursor row cache generation counter */
- int pc; /* The program counter */
- int rc; /* Value to return */
- int nChange; /* Number of db changes made since last reset */
- int iStatement; /* Statement number (or 0 if has not opened stmt) */
- i64 iCurrentTime; /* Value of julianday('now') for this statement */
- i64 nFkConstraint; /* Number of imm. FK constraints this VM */
- i64 nStmtDefCons; /* Number of def. constraints when stmt started */
- i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
-
- /* When allocating a new Vdbe object, all of the fields below should be
- ** initialized to zero or NULL */
-
- Op *aOp; /* Space to hold the virtual machine's program */
- Mem *aMem; /* The memory locations */
- Mem **apArg; /* Arguments to currently executing user function */
- Mem *aColName; /* Column names to return */
- Mem *pResultSet; /* Pointer to an array of results */
- char *zErrMsg; /* Error message written here */
- VdbeCursor **apCsr; /* One element of this array for each open cursor */
- Mem *aVar; /* Values for the OP_Variable opcode. */
- VList *pVList; /* Name of variables */
-#ifndef SQLITE_OMIT_TRACE
- i64 startTime; /* Time when query started - used for profiling */
-#endif
- int nOp; /* Number of instructions in the program */
-#ifdef SQLITE_DEBUG
- int rcApp; /* errcode set by sqlite3_result_error_code() */
- u32 nWrite; /* Number of write operations that have occurred */
-#endif
- u16 nResColumn; /* Number of columns in one row of the result set */
- u8 errorAction; /* Recovery action to do in case of an error */
- u8 minWriteFileFormat; /* Minimum file format for writable database files */
- u8 prepFlags; /* SQLITE_PREPARE_* flags */
- bft expired:1; /* True if the VM needs to be recompiled */
- bft doingRerun:1; /* True if rerunning after an auto-reprepare */
- bft explain:2; /* True if EXPLAIN present on SQL command */
- bft changeCntOn:1; /* True to update the change-counter */
- bft runOnlyOnce:1; /* Automatically expire on reset */
- bft usesStmtJournal:1; /* True if uses a statement journal */
- bft readOnly:1; /* True for statements that do not write */
- bft bIsReader:1; /* True for statements that read */
- yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
- yDbMask lockMask; /* Subset of btreeMask that requires a lock */
- u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
- char *zSql; /* Text of the SQL statement that generated this */
- void *pFree; /* Free this when deleting the vdbe */
- VdbeFrame *pFrame; /* Parent frame */
- VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
- int nFrame; /* Number of frames in pFrame list */
- u32 expmask; /* Binding to these vars invalidates VM */
- SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
- AuxData *pAuxData; /* Linked list of auxdata allocations */
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- i64 *anExec; /* Number of times each op has been executed */
- int nScan; /* Entries in aScan[] */
- ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */
-#endif
-};
-
-/*
-** The following are allowed values for Vdbe.magic
-*/
-#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */
-#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */
-#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */
-#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */
-#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */
-
-/*
-** Structure used to store the context required by the
-** sqlite3_preupdate_*() API functions.
-*/
-struct PreUpdate {
- Vdbe *v;
- VdbeCursor *pCsr; /* Cursor to read old values from */
- int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
- u8 *aRecord; /* old.* database record */
- KeyInfo keyinfo;
- UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
- UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
- int iNewReg; /* Register for new.* values */
- i64 iKey1; /* First key value passed to hook */
- i64 iKey2; /* Second key value passed to hook */
- Mem *aNew; /* Array of new.* values */
- Table *pTab; /* Schema object being upated */
- Index *pPk; /* PK index if pTab is WITHOUT ROWID */
-};
-
-/*
-** Function prototypes
-*/
-void sqlite3VdbeError(Vdbe*, const char *, ...);
-void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
-void sqliteVdbePopStack(Vdbe*,int);
-int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
-int sqlite3VdbeCursorRestore(VdbeCursor*);
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
-void sqlite3VdbePrintOp(FILE*, int, Op*);
-#endif
-u32 sqlite3VdbeSerialTypeLen(u32);
-u8 sqlite3VdbeOneByteSerialTypeLen(u8);
-u32 sqlite3VdbeSerialType(Mem*, int, u32*);
-u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
-u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
-void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);
-
-int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
-int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
-int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
-int sqlite3VdbeExec(Vdbe*);
-int sqlite3VdbeList(Vdbe*);
-int sqlite3VdbeHalt(Vdbe*);
-int sqlite3VdbeChangeEncoding(Mem *, int);
-int sqlite3VdbeMemTooBig(Mem*);
-int sqlite3VdbeMemCopy(Mem*, const Mem*);
-void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
-void sqlite3VdbeMemMove(Mem*, Mem*);
-int sqlite3VdbeMemNulTerminate(Mem*);
-int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
-void sqlite3VdbeMemSetInt64(Mem*, i64);
-#ifdef SQLITE_OMIT_FLOATING_POINT
-# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
-#else
- void sqlite3VdbeMemSetDouble(Mem*, double);
-#endif
-void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
-void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
-void sqlite3VdbeMemSetNull(Mem*);
-void sqlite3VdbeMemSetZeroBlob(Mem*,int);
-void sqlite3VdbeMemSetRowSet(Mem*);
-int sqlite3VdbeMemMakeWriteable(Mem*);
-int sqlite3VdbeMemStringify(Mem*, u8, u8);
-i64 sqlite3VdbeIntValue(Mem*);
-int sqlite3VdbeMemIntegerify(Mem*);
-double sqlite3VdbeRealValue(Mem*);
-int sqlite3VdbeBooleanValue(Mem*, int ifNull);
-void sqlite3VdbeIntegerAffinity(Mem*);
-int sqlite3VdbeMemRealify(Mem*);
-int sqlite3VdbeMemNumerify(Mem*);
-void sqlite3VdbeMemCast(Mem*,u8,u8);
-int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
-void sqlite3VdbeMemRelease(Mem *p);
-int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
-const char *sqlite3OpcodeName(int);
-int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
-int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
-int sqlite3VdbeCloseStatement(Vdbe *, int);
-void sqlite3VdbeFrameDelete(VdbeFrame*);
-int sqlite3VdbeFrameRestore(VdbeFrame *);
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
-#endif
-int sqlite3VdbeTransferError(Vdbe *p);
-
-int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
-void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
-void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
-int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
-int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *);
-int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
-int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
-int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
-
-#ifdef SQLITE_DEBUG
- void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
- void sqlite3VdbeAssertAbortable(Vdbe*);
-#else
-# define sqlite3VdbeIncrWriteCounter(V,C)
-# define sqlite3VdbeAssertAbortable(V)
-#endif
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE)
- void sqlite3VdbeEnter(Vdbe*);
-#else
-# define sqlite3VdbeEnter(X)
-#endif
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
- void sqlite3VdbeLeave(Vdbe*);
-#else
-# define sqlite3VdbeLeave(X)
-#endif
-
-#ifdef SQLITE_DEBUG
-void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
-int sqlite3VdbeCheckMemInvariants(Mem*);
-#endif
-
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-int sqlite3VdbeCheckFk(Vdbe *, int);
-#else
-# define sqlite3VdbeCheckFk(p,i) 0
-#endif
-
-#ifdef SQLITE_DEBUG
- void sqlite3VdbePrintSql(Vdbe*);
- void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
-#endif
-#ifndef SQLITE_OMIT_UTF16
- int sqlite3VdbeMemTranslate(Mem*, u8);
- int sqlite3VdbeMemHandleBom(Mem *pMem);
-#endif
-
-#ifndef SQLITE_OMIT_INCRBLOB
- int sqlite3VdbeMemExpandBlob(Mem *);
- #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
-#else
- #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK
- #define ExpandBlob(P) SQLITE_OK
-#endif
-
-#endif /* !defined(SQLITE_VDBEINT_H) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeapi.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeapi.c
deleted file mode 100644
index ced3e901441..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeapi.c
+++ /dev/null
@@ -1,1958 +0,0 @@
-/*
-** 2004 May 26
-**
-** 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 contains code use to implement APIs that are part of the
-** VDBE.
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** Return TRUE (non-zero) of the statement supplied as an argument needs
-** to be recompiled. A statement needs to be recompiled whenever the
-** execution environment changes in a way that would alter the program
-** that sqlite3_prepare() generates. For example, if new functions or
-** collating sequences are registered or if an authorizer function is
-** added or changed.
-*/
-int sqlite3_expired(sqlite3_stmt *pStmt){
- Vdbe *p = (Vdbe*)pStmt;
- return p==0 || p->expired;
-}
-#endif
-
-/*
-** Check on a Vdbe to make sure it has not been finalized. Log
-** an error and return true if it has been finalized (or is otherwise
-** invalid). Return false if it is ok.
-*/
-static int vdbeSafety(Vdbe *p){
- if( p->db==0 ){
- sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
- return 1;
- }else{
- return 0;
- }
-}
-static int vdbeSafetyNotNull(Vdbe *p){
- if( p==0 ){
- sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
- return 1;
- }else{
- return vdbeSafety(p);
- }
-}
-
-#ifndef SQLITE_OMIT_TRACE
-/*
-** Invoke the profile callback. This routine is only called if we already
-** know that the profile callback is defined and needs to be invoked.
-*/
-static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
- sqlite3_int64 iNow;
- sqlite3_int64 iElapse;
- assert( p->startTime>0 );
- assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 );
- assert( db->init.busy==0 );
- assert( p->zSql!=0 );
- sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
- iElapse = (iNow - p->startTime)*1000000;
- if( db->xProfile ){
- db->xProfile(db->pProfileArg, p->zSql, iElapse);
- }
- if( db->mTrace & SQLITE_TRACE_PROFILE ){
- db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
- }
- p->startTime = 0;
-}
-/*
-** The checkProfileCallback(DB,P) macro checks to see if a profile callback
-** is needed, and it invokes the callback if it is needed.
-*/
-# define checkProfileCallback(DB,P) \
- if( ((P)->startTime)>0 ){ invokeProfileCallback(DB,P); }
-#else
-# define checkProfileCallback(DB,P) /*no-op*/
-#endif
-
-/*
-** The following routine destroys a virtual machine that is created by
-** the sqlite3_compile() routine. The integer returned is an SQLITE_
-** success/failure code that describes the result of executing the virtual
-** machine.
-**
-** This routine sets the error code and string returned by
-** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
-*/
-int sqlite3_finalize(sqlite3_stmt *pStmt){
- int rc;
- if( pStmt==0 ){
- /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL
- ** pointer is a harmless no-op. */
- rc = SQLITE_OK;
- }else{
- Vdbe *v = (Vdbe*)pStmt;
- sqlite3 *db = v->db;
- if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
- sqlite3_mutex_enter(db->mutex);
- checkProfileCallback(db, v);
- rc = sqlite3VdbeFinalize(v);
- rc = sqlite3ApiExit(db, rc);
- sqlite3LeaveMutexAndCloseZombie(db);
- }
- return rc;
-}
-
-/*
-** Terminate the current execution of an SQL statement and reset it
-** back to its starting state so that it can be reused. A success code from
-** the prior execution is returned.
-**
-** This routine sets the error code and string returned by
-** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
-*/
-int sqlite3_reset(sqlite3_stmt *pStmt){
- int rc;
- if( pStmt==0 ){
- rc = SQLITE_OK;
- }else{
- Vdbe *v = (Vdbe*)pStmt;
- sqlite3 *db = v->db;
- sqlite3_mutex_enter(db->mutex);
- checkProfileCallback(db, v);
- rc = sqlite3VdbeReset(v);
- sqlite3VdbeRewind(v);
- assert( (rc & (db->errMask))==rc );
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- }
- return rc;
-}
-
-/*
-** Set all the parameters in the compiled SQL statement to NULL.
-*/
-int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
- int i;
- int rc = SQLITE_OK;
- Vdbe *p = (Vdbe*)pStmt;
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
-#endif
- sqlite3_mutex_enter(mutex);
- for(i=0; i<p->nVar; i++){
- sqlite3VdbeMemRelease(&p->aVar[i]);
- p->aVar[i].flags = MEM_Null;
- }
- assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
- if( p->expmask ){
- p->expired = 1;
- }
- sqlite3_mutex_leave(mutex);
- return rc;
-}
-
-
-/**************************** sqlite3_value_ *******************************
-** The following routines extract information from a Mem or sqlite3_value
-** structure.
-*/
-const void *sqlite3_value_blob(sqlite3_value *pVal){
- Mem *p = (Mem*)pVal;
- if( p->flags & (MEM_Blob|MEM_Str) ){
- if( ExpandBlob(p)!=SQLITE_OK ){
- assert( p->flags==MEM_Null && p->z==0 );
- return 0;
- }
- p->flags |= MEM_Blob;
- return p->n ? p->z : 0;
- }else{
- return sqlite3_value_text(pVal);
- }
-}
-int sqlite3_value_bytes(sqlite3_value *pVal){
- return sqlite3ValueBytes(pVal, SQLITE_UTF8);
-}
-int sqlite3_value_bytes16(sqlite3_value *pVal){
- return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE);
-}
-double sqlite3_value_double(sqlite3_value *pVal){
- return sqlite3VdbeRealValue((Mem*)pVal);
-}
-int sqlite3_value_int(sqlite3_value *pVal){
- return (int)sqlite3VdbeIntValue((Mem*)pVal);
-}
-sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
- return sqlite3VdbeIntValue((Mem*)pVal);
-}
-unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
- Mem *pMem = (Mem*)pVal;
- return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0);
-}
-void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){
- Mem *p = (Mem*)pVal;
- if( (p->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) ==
- (MEM_Null|MEM_Term|MEM_Subtype)
- && zPType!=0
- && p->eSubtype=='p'
- && strcmp(p->u.zPType, zPType)==0
- ){
- return (void*)p->z;
- }else{
- return 0;
- }
-}
-const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
- return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
-}
-#ifndef SQLITE_OMIT_UTF16
-const void *sqlite3_value_text16(sqlite3_value* pVal){
- return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
-}
-const void *sqlite3_value_text16be(sqlite3_value *pVal){
- return sqlite3ValueText(pVal, SQLITE_UTF16BE);
-}
-const void *sqlite3_value_text16le(sqlite3_value *pVal){
- return sqlite3ValueText(pVal, SQLITE_UTF16LE);
-}
-#endif /* SQLITE_OMIT_UTF16 */
-/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five
-** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating
-** point number string BLOB NULL
-*/
-int sqlite3_value_type(sqlite3_value* pVal){
- static const u8 aType[] = {
- SQLITE_BLOB, /* 0x00 */
- SQLITE_NULL, /* 0x01 */
- SQLITE_TEXT, /* 0x02 */
- SQLITE_NULL, /* 0x03 */
- SQLITE_INTEGER, /* 0x04 */
- SQLITE_NULL, /* 0x05 */
- SQLITE_INTEGER, /* 0x06 */
- SQLITE_NULL, /* 0x07 */
- SQLITE_FLOAT, /* 0x08 */
- SQLITE_NULL, /* 0x09 */
- SQLITE_FLOAT, /* 0x0a */
- SQLITE_NULL, /* 0x0b */
- SQLITE_INTEGER, /* 0x0c */
- SQLITE_NULL, /* 0x0d */
- SQLITE_INTEGER, /* 0x0e */
- SQLITE_NULL, /* 0x0f */
- SQLITE_BLOB, /* 0x10 */
- SQLITE_NULL, /* 0x11 */
- SQLITE_TEXT, /* 0x12 */
- SQLITE_NULL, /* 0x13 */
- SQLITE_INTEGER, /* 0x14 */
- SQLITE_NULL, /* 0x15 */
- SQLITE_INTEGER, /* 0x16 */
- SQLITE_NULL, /* 0x17 */
- SQLITE_FLOAT, /* 0x18 */
- SQLITE_NULL, /* 0x19 */
- SQLITE_FLOAT, /* 0x1a */
- SQLITE_NULL, /* 0x1b */
- SQLITE_INTEGER, /* 0x1c */
- SQLITE_NULL, /* 0x1d */
- SQLITE_INTEGER, /* 0x1e */
- SQLITE_NULL, /* 0x1f */
- };
- return aType[pVal->flags&MEM_AffMask];
-}
-
-/* Return true if a parameter to xUpdate represents an unchanged column */
-int sqlite3_value_nochange(sqlite3_value *pVal){
- return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
-}
-
-/* Make a copy of an sqlite3_value object
-*/
-sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
- sqlite3_value *pNew;
- if( pOrig==0 ) return 0;
- pNew = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return 0;
- memset(pNew, 0, sizeof(*pNew));
- memcpy(pNew, pOrig, MEMCELLSIZE);
- pNew->flags &= ~MEM_Dyn;
- pNew->db = 0;
- if( pNew->flags&(MEM_Str|MEM_Blob) ){
- pNew->flags &= ~(MEM_Static|MEM_Dyn);
- pNew->flags |= MEM_Ephem;
- if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){
- sqlite3ValueFree(pNew);
- pNew = 0;
- }
- }
- return pNew;
-}
-
-/* Destroy an sqlite3_value object previously obtained from
-** sqlite3_value_dup().
-*/
-void sqlite3_value_free(sqlite3_value *pOld){
- sqlite3ValueFree(pOld);
-}
-
-
-/**************************** sqlite3_result_ *******************************
-** The following routines are used by user-defined functions to specify
-** the function result.
-**
-** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the
-** result as a string or blob but if the string or blob is too large, it
-** then sets the error code to SQLITE_TOOBIG
-**
-** The invokeValueDestructor(P,X) routine invokes destructor function X()
-** on value P is not going to be used and need to be destroyed.
-*/
-static void setResultStrOrError(
- sqlite3_context *pCtx, /* Function context */
- const char *z, /* String pointer */
- int n, /* Bytes in string, or negative */
- u8 enc, /* Encoding of z. 0 for BLOBs */
- void (*xDel)(void*) /* Destructor function */
-){
- if( sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){
- sqlite3_result_error_toobig(pCtx);
- }
-}
-static int invokeValueDestructor(
- const void *p, /* Value to destroy */
- void (*xDel)(void*), /* The destructor */
- sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */
-){
- assert( xDel!=SQLITE_DYNAMIC );
- if( xDel==0 ){
- /* noop */
- }else if( xDel==SQLITE_TRANSIENT ){
- /* noop */
- }else{
- xDel((void*)p);
- }
- if( pCtx ) sqlite3_result_error_toobig(pCtx);
- return SQLITE_TOOBIG;
-}
-void sqlite3_result_blob(
- sqlite3_context *pCtx,
- const void *z,
- int n,
- void (*xDel)(void *)
-){
- assert( n>=0 );
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- setResultStrOrError(pCtx, z, n, 0, xDel);
-}
-void sqlite3_result_blob64(
- sqlite3_context *pCtx,
- const void *z,
- sqlite3_uint64 n,
- void (*xDel)(void *)
-){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- assert( xDel!=SQLITE_DYNAMIC );
- if( n>0x7fffffff ){
- (void)invokeValueDestructor(z, xDel, pCtx);
- }else{
- setResultStrOrError(pCtx, z, (int)n, 0, xDel);
- }
-}
-void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlite3VdbeMemSetDouble(pCtx->pOut, rVal);
-}
-void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- pCtx->isError = SQLITE_ERROR;
- sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
-}
-#ifndef SQLITE_OMIT_UTF16
-void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- pCtx->isError = SQLITE_ERROR;
- sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
-}
-#endif
-void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal);
-}
-void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlite3VdbeMemSetInt64(pCtx->pOut, iVal);
-}
-void sqlite3_result_null(sqlite3_context *pCtx){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlite3VdbeMemSetNull(pCtx->pOut);
-}
-void sqlite3_result_pointer(
- sqlite3_context *pCtx,
- void *pPtr,
- const char *zPType,
- void (*xDestructor)(void*)
-){
- Mem *pOut = pCtx->pOut;
- assert( sqlite3_mutex_held(pOut->db->mutex) );
- sqlite3VdbeMemRelease(pOut);
- pOut->flags = MEM_Null;
- sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor);
-}
-void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
- Mem *pOut = pCtx->pOut;
- assert( sqlite3_mutex_held(pOut->db->mutex) );
- pOut->eSubtype = eSubtype & 0xff;
- pOut->flags |= MEM_Subtype;
-}
-void sqlite3_result_text(
- sqlite3_context *pCtx,
- const char *z,
- int n,
- void (*xDel)(void *)
-){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
-}
-void sqlite3_result_text64(
- sqlite3_context *pCtx,
- const char *z,
- sqlite3_uint64 n,
- void (*xDel)(void *),
- unsigned char enc
-){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- assert( xDel!=SQLITE_DYNAMIC );
- if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
- if( n>0x7fffffff ){
- (void)invokeValueDestructor(z, xDel, pCtx);
- }else{
- setResultStrOrError(pCtx, z, (int)n, enc, xDel);
- }
-}
-#ifndef SQLITE_OMIT_UTF16
-void sqlite3_result_text16(
- sqlite3_context *pCtx,
- const void *z,
- int n,
- void (*xDel)(void *)
-){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
-}
-void sqlite3_result_text16be(
- sqlite3_context *pCtx,
- const void *z,
- int n,
- void (*xDel)(void *)
-){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
-}
-void sqlite3_result_text16le(
- sqlite3_context *pCtx,
- const void *z,
- int n,
- void (*xDel)(void *)
-){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
-}
-#endif /* SQLITE_OMIT_UTF16 */
-void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlite3VdbeMemCopy(pCtx->pOut, pValue);
-}
-void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n);
-}
-int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
- Mem *pOut = pCtx->pOut;
- assert( sqlite3_mutex_held(pOut->db->mutex) );
- if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){
- return SQLITE_TOOBIG;
- }
- sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
- return SQLITE_OK;
-}
-void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
- pCtx->isError = errCode ? errCode : -1;
-#ifdef SQLITE_DEBUG
- if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
-#endif
- if( pCtx->pOut->flags & MEM_Null ){
- sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1,
- SQLITE_UTF8, SQLITE_STATIC);
- }
-}
-
-/* Force an SQLITE_TOOBIG error. */
-void sqlite3_result_error_toobig(sqlite3_context *pCtx){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- pCtx->isError = SQLITE_TOOBIG;
- sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1,
- SQLITE_UTF8, SQLITE_STATIC);
-}
-
-/* An SQLITE_NOMEM error. */
-void sqlite3_result_error_nomem(sqlite3_context *pCtx){
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlite3VdbeMemSetNull(pCtx->pOut);
- pCtx->isError = SQLITE_NOMEM_BKPT;
- sqlite3OomFault(pCtx->pOut->db);
-}
-
-/*
-** This function is called after a transaction has been committed. It
-** invokes callbacks registered with sqlite3_wal_hook() as required.
-*/
-static int doWalCallbacks(sqlite3 *db){
- int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_WAL
- int i;
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- int nEntry;
- sqlite3BtreeEnter(pBt);
- nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
- sqlite3BtreeLeave(pBt);
- if( nEntry>0 && db->xWalCallback && rc==SQLITE_OK ){
- rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry);
- }
- }
- }
-#endif
- return rc;
-}
-
-
-/*
-** Execute the statement pStmt, either until a row of data is ready, the
-** statement is completely executed or an error occurs.
-**
-** This routine implements the bulk of the logic behind the sqlite_step()
-** API. The only thing omitted is the automatic recompile if a
-** schema change has occurred. That detail is handled by the
-** outer sqlite3_step() wrapper procedure.
-*/
-static int sqlite3Step(Vdbe *p){
- sqlite3 *db;
- int rc;
-
- assert(p);
- if( p->magic!=VDBE_MAGIC_RUN ){
- /* We used to require that sqlite3_reset() be called before retrying
- ** sqlite3_step() after any error or after SQLITE_DONE. But beginning
- ** with version 3.7.0, we changed this so that sqlite3_reset() would
- ** be called automatically instead of throwing the SQLITE_MISUSE error.
- ** This "automatic-reset" change is not technically an incompatibility,
- ** since any application that receives an SQLITE_MISUSE is broken by
- ** definition.
- **
- ** Nevertheless, some published applications that were originally written
- ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
- ** returns, and those were broken by the automatic-reset change. As a
- ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
- ** legacy behavior of returning SQLITE_MISUSE for cases where the
- ** previous sqlite3_step() returned something other than a SQLITE_LOCKED
- ** or SQLITE_BUSY error.
- */
-#ifdef SQLITE_OMIT_AUTORESET
- if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
- sqlite3_reset((sqlite3_stmt*)p);
- }else{
- return SQLITE_MISUSE_BKPT;
- }
-#else
- sqlite3_reset((sqlite3_stmt*)p);
-#endif
- }
-
- /* Check that malloc() has not failed. If it has, return early. */
- db = p->db;
- if( db->mallocFailed ){
- p->rc = SQLITE_NOMEM;
- return SQLITE_NOMEM_BKPT;
- }
-
- if( p->pc<=0 && p->expired ){
- p->rc = SQLITE_SCHEMA;
- rc = SQLITE_ERROR;
- goto end_of_step;
- }
- if( p->pc<0 ){
- /* If there are no other statements currently running, then
- ** reset the interrupt flag. This prevents a call to sqlite3_interrupt
- ** from interrupting a statement that has not yet started.
- */
- if( db->nVdbeActive==0 ){
- db->u1.isInterrupted = 0;
- }
-
- assert( db->nVdbeWrite>0 || db->autoCommit==0
- || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
- );
-
-#ifndef SQLITE_OMIT_TRACE
- if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0)
- && !db->init.busy && p->zSql ){
- sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
- }else{
- assert( p->startTime==0 );
- }
-#endif
-
- db->nVdbeActive++;
- if( p->readOnly==0 ) db->nVdbeWrite++;
- if( p->bIsReader ) db->nVdbeRead++;
- p->pc = 0;
- }
-#ifdef SQLITE_DEBUG
- p->rcApp = SQLITE_OK;
-#endif
-#ifndef SQLITE_OMIT_EXPLAIN
- if( p->explain ){
- rc = sqlite3VdbeList(p);
- }else
-#endif /* SQLITE_OMIT_EXPLAIN */
- {
- db->nVdbeExec++;
- rc = sqlite3VdbeExec(p);
- db->nVdbeExec--;
- }
-
-#ifndef SQLITE_OMIT_TRACE
- /* If the statement completed successfully, invoke the profile callback */
- if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
-#endif
-
- if( rc==SQLITE_DONE && db->autoCommit ){
- assert( p->rc==SQLITE_OK );
- p->rc = doWalCallbacks(db);
- if( p->rc!=SQLITE_OK ){
- rc = SQLITE_ERROR;
- }
- }
-
- db->errCode = rc;
- if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
- p->rc = SQLITE_NOMEM_BKPT;
- }
-end_of_step:
- /* At this point local variable rc holds the value that should be
- ** returned if this statement was compiled using the legacy
- ** sqlite3_prepare() interface. According to the docs, this can only
- ** be one of the values in the first assert() below. Variable p->rc
- ** contains the value that would be returned if sqlite3_finalize()
- ** were called on statement p.
- */
- assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
- || (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
- );
- assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
- if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
- && rc!=SQLITE_ROW
- && rc!=SQLITE_DONE
- ){
- /* If this statement was prepared using saved SQL and an
- ** error has occurred, then return the error code in p->rc to the
- ** caller. Set the error code in the database handle to the same value.
- */
- rc = sqlite3VdbeTransferError(p);
- }
- return (rc&db->errMask);
-}
-
-/*
-** This is the top-level implementation of sqlite3_step(). Call
-** sqlite3Step() to do most of the work. If a schema error occurs,
-** call sqlite3Reprepare() and try again.
-*/
-int sqlite3_step(sqlite3_stmt *pStmt){
- int rc = SQLITE_OK; /* Result from sqlite3Step() */
- Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
- int cnt = 0; /* Counter to prevent infinite loop of reprepares */
- sqlite3 *db; /* The database connection */
-
- if( vdbeSafetyNotNull(v) ){
- return SQLITE_MISUSE_BKPT;
- }
- db = v->db;
- sqlite3_mutex_enter(db->mutex);
- v->doingRerun = 0;
- while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
- && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){
- int savedPc = v->pc;
- rc = sqlite3Reprepare(v);
- if( rc!=SQLITE_OK ){
- /* This case occurs after failing to recompile an sql statement.
- ** The error message from the SQL compiler has already been loaded
- ** into the database handle. This block copies the error message
- ** from the database handle into the statement and sets the statement
- ** program counter to 0 to ensure that when the statement is
- ** finalized or reset the parser error message is available via
- ** sqlite3_errmsg() and sqlite3_errcode().
- */
- const char *zErr = (const char *)sqlite3_value_text(db->pErr);
- sqlite3DbFree(db, v->zErrMsg);
- if( !db->mallocFailed ){
- v->zErrMsg = sqlite3DbStrDup(db, zErr);
- v->rc = rc = sqlite3ApiExit(db, rc);
- } else {
- v->zErrMsg = 0;
- v->rc = rc = SQLITE_NOMEM_BKPT;
- }
- break;
- }
- sqlite3_reset(pStmt);
- if( savedPc>=0 ) v->doingRerun = 1;
- assert( v->expired==0 );
- }
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-
-/*
-** Extract the user data from a sqlite3_context structure and return a
-** pointer to it.
-*/
-void *sqlite3_user_data(sqlite3_context *p){
- assert( p && p->pFunc );
- return p->pFunc->pUserData;
-}
-
-/*
-** Extract the user data from a sqlite3_context structure and return a
-** pointer to it.
-**
-** IMPLEMENTATION-OF: R-46798-50301 The sqlite3_context_db_handle() interface
-** returns a copy of the pointer to the database connection (the 1st
-** parameter) of the sqlite3_create_function() and
-** sqlite3_create_function16() routines that originally registered the
-** application defined function.
-*/
-sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
- assert( p && p->pOut );
- return p->pOut->db;
-}
-
-/*
-** If this routine is invoked from within an xColumn method of a virtual
-** table, then it returns true if and only if the the call is during an
-** UPDATE operation and the value of the column will not be modified
-** by the UPDATE.
-**
-** If this routine is called from any context other than within the
-** xColumn method of a virtual table, then the return value is meaningless
-** and arbitrary.
-**
-** Virtual table implements might use this routine to optimize their
-** performance by substituting a NULL result, or some other light-weight
-** value, as a signal to the xUpdate routine that the column is unchanged.
-*/
-int sqlite3_vtab_nochange(sqlite3_context *p){
- assert( p );
- return sqlite3_value_nochange(p->pOut);
-}
-
-/*
-** Return the current time for a statement. If the current time
-** is requested more than once within the same run of a single prepared
-** statement, the exact same time is returned for each invocation regardless
-** of the amount of time that elapses between invocations. In other words,
-** the time returned is always the time of the first call.
-*/
-sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
- int rc;
-#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
- sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
- assert( p->pVdbe!=0 );
-#else
- sqlite3_int64 iTime = 0;
- sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime;
-#endif
- if( *piTime==0 ){
- rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime);
- if( rc ) *piTime = 0;
- }
- return *piTime;
-}
-
-/*
-** Create a new aggregate context for p and return a pointer to
-** its pMem->z element.
-*/
-static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){
- Mem *pMem = p->pMem;
- assert( (pMem->flags & MEM_Agg)==0 );
- if( nByte<=0 ){
- sqlite3VdbeMemSetNull(pMem);
- pMem->z = 0;
- }else{
- sqlite3VdbeMemClearAndResize(pMem, nByte);
- pMem->flags = MEM_Agg;
- pMem->u.pDef = p->pFunc;
- if( pMem->z ){
- memset(pMem->z, 0, nByte);
- }
- }
- return (void*)pMem->z;
-}
-
-/*
-** Allocate or return the aggregate context for a user function. A new
-** context is allocated on the first call. Subsequent calls return the
-** same context that was returned on prior calls.
-*/
-void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
- assert( p && p->pFunc && p->pFunc->xFinalize );
- assert( sqlite3_mutex_held(p->pOut->db->mutex) );
- testcase( nByte<0 );
- if( (p->pMem->flags & MEM_Agg)==0 ){
- return createAggContext(p, nByte);
- }else{
- return (void*)p->pMem->z;
- }
-}
-
-/*
-** Return the auxiliary data pointer, if any, for the iArg'th argument to
-** the user-function defined by pCtx.
-**
-** The left-most argument is 0.
-**
-** Undocumented behavior: If iArg is negative then access a cache of
-** auxiliary data pointers that is available to all functions within a
-** single prepared statement. The iArg values must match.
-*/
-void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
- AuxData *pAuxData;
-
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-#if SQLITE_ENABLE_STAT3_OR_STAT4
- if( pCtx->pVdbe==0 ) return 0;
-#else
- assert( pCtx->pVdbe!=0 );
-#endif
- for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
- if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
- return pAuxData->pAux;
- }
- }
- return 0;
-}
-
-/*
-** Set the auxiliary data pointer and delete function, for the iArg'th
-** argument to the user-function defined by pCtx. Any previous value is
-** deleted by calling the delete function specified when it was set.
-**
-** The left-most argument is 0.
-**
-** Undocumented behavior: If iArg is negative then make the data available
-** to all functions within the current prepared statement using iArg as an
-** access code.
-*/
-void sqlite3_set_auxdata(
- sqlite3_context *pCtx,
- int iArg,
- void *pAux,
- void (*xDelete)(void*)
-){
- AuxData *pAuxData;
- Vdbe *pVdbe = pCtx->pVdbe;
-
- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( pVdbe==0 ) goto failed;
-#else
- assert( pVdbe!=0 );
-#endif
-
- for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
- if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
- break;
- }
- }
- if( pAuxData==0 ){
- pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
- if( !pAuxData ) goto failed;
- pAuxData->iAuxOp = pCtx->iOp;
- pAuxData->iAuxArg = iArg;
- pAuxData->pNextAux = pVdbe->pAuxData;
- pVdbe->pAuxData = pAuxData;
- if( pCtx->isError==0 ) pCtx->isError = -1;
- }else if( pAuxData->xDeleteAux ){
- pAuxData->xDeleteAux(pAuxData->pAux);
- }
-
- pAuxData->pAux = pAux;
- pAuxData->xDeleteAux = xDelete;
- return;
-
-failed:
- if( xDelete ){
- xDelete(pAux);
- }
-}
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** Return the number of times the Step function of an aggregate has been
-** called.
-**
-** This function is deprecated. Do not use it for new code. It is
-** provide only to avoid breaking legacy code. New aggregate function
-** implementations should keep their own counts within their aggregate
-** context.
-*/
-int sqlite3_aggregate_count(sqlite3_context *p){
- assert( p && p->pMem && p->pFunc && p->pFunc->xFinalize );
- return p->pMem->n;
-}
-#endif
-
-/*
-** Return the number of columns in the result set for the statement pStmt.
-*/
-int sqlite3_column_count(sqlite3_stmt *pStmt){
- Vdbe *pVm = (Vdbe *)pStmt;
- return pVm ? pVm->nResColumn : 0;
-}
-
-/*
-** Return the number of values available from the current row of the
-** currently executing statement pStmt.
-*/
-int sqlite3_data_count(sqlite3_stmt *pStmt){
- Vdbe *pVm = (Vdbe *)pStmt;
- if( pVm==0 || pVm->pResultSet==0 ) return 0;
- return pVm->nResColumn;
-}
-
-/*
-** Return a pointer to static memory containing an SQL NULL value.
-*/
-static const Mem *columnNullValue(void){
- /* Even though the Mem structure contains an element
- ** of type i64, on certain architectures (x86) with certain compiler
- ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
- ** instead of an 8-byte one. This all works fine, except that when
- ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
- ** that a Mem structure is located on an 8-byte boundary. To prevent
- ** these assert()s from failing, when building with SQLITE_DEBUG defined
- ** using gcc, we force nullMem to be 8-byte aligned using the magical
- ** __attribute__((aligned(8))) macro. */
- static const Mem nullMem
-#if defined(SQLITE_DEBUG) && defined(__GNUC__)
- __attribute__((aligned(8)))
-#endif
- = {
- /* .u = */ {0},
- /* .flags = */ (u16)MEM_Null,
- /* .enc = */ (u8)0,
- /* .eSubtype = */ (u8)0,
- /* .n = */ (int)0,
- /* .z = */ (char*)0,
- /* .zMalloc = */ (char*)0,
- /* .szMalloc = */ (int)0,
- /* .uTemp = */ (u32)0,
- /* .db = */ (sqlite3*)0,
- /* .xDel = */ (void(*)(void*))0,
-#ifdef SQLITE_DEBUG
- /* .pScopyFrom = */ (Mem*)0,
- /* .pFiller = */ (void*)0,
-#endif
- };
- return &nullMem;
-}
-
-/*
-** Check to see if column iCol of the given statement is valid. If
-** it is, return a pointer to the Mem for the value of that column.
-** If iCol is not valid, return a pointer to a Mem which has a value
-** of NULL.
-*/
-static Mem *columnMem(sqlite3_stmt *pStmt, int i){
- Vdbe *pVm;
- Mem *pOut;
-
- pVm = (Vdbe *)pStmt;
- if( pVm==0 ) return (Mem*)columnNullValue();
- assert( pVm->db );
- sqlite3_mutex_enter(pVm->db->mutex);
- if( pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
- pOut = &pVm->pResultSet[i];
- }else{
- sqlite3Error(pVm->db, SQLITE_RANGE);
- pOut = (Mem*)columnNullValue();
- }
- return pOut;
-}
-
-/*
-** This function is called after invoking an sqlite3_value_XXX function on a
-** column value (i.e. a value returned by evaluating an SQL expression in the
-** select list of a SELECT statement) that may cause a malloc() failure. If
-** malloc() has failed, the threads mallocFailed flag is cleared and the result
-** code of statement pStmt set to SQLITE_NOMEM.
-**
-** Specifically, this is called from within:
-**
-** sqlite3_column_int()
-** sqlite3_column_int64()
-** sqlite3_column_text()
-** sqlite3_column_text16()
-** sqlite3_column_real()
-** sqlite3_column_bytes()
-** sqlite3_column_bytes16()
-** sqiite3_column_blob()
-*/
-static void columnMallocFailure(sqlite3_stmt *pStmt)
-{
- /* If malloc() failed during an encoding conversion within an
- ** sqlite3_column_XXX API, then set the return code of the statement to
- ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR
- ** and _finalize() will return NOMEM.
- */
- Vdbe *p = (Vdbe *)pStmt;
- if( p ){
- assert( p->db!=0 );
- assert( sqlite3_mutex_held(p->db->mutex) );
- p->rc = sqlite3ApiExit(p->db, p->rc);
- sqlite3_mutex_leave(p->db->mutex);
- }
-}
-
-/**************************** sqlite3_column_ *******************************
-** The following routines are used to access elements of the current row
-** in the result set.
-*/
-const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
- const void *val;
- val = sqlite3_value_blob( columnMem(pStmt,i) );
- /* Even though there is no encoding conversion, value_blob() might
- ** need to call malloc() to expand the result of a zeroblob()
- ** expression.
- */
- columnMallocFailure(pStmt);
- return val;
-}
-int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){
- int val = sqlite3_value_bytes( columnMem(pStmt,i) );
- columnMallocFailure(pStmt);
- return val;
-}
-int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){
- int val = sqlite3_value_bytes16( columnMem(pStmt,i) );
- columnMallocFailure(pStmt);
- return val;
-}
-double sqlite3_column_double(sqlite3_stmt *pStmt, int i){
- double val = sqlite3_value_double( columnMem(pStmt,i) );
- columnMallocFailure(pStmt);
- return val;
-}
-int sqlite3_column_int(sqlite3_stmt *pStmt, int i){
- int val = sqlite3_value_int( columnMem(pStmt,i) );
- columnMallocFailure(pStmt);
- return val;
-}
-sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
- sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) );
- columnMallocFailure(pStmt);
- return val;
-}
-const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
- const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) );
- columnMallocFailure(pStmt);
- return val;
-}
-sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
- Mem *pOut = columnMem(pStmt, i);
- if( pOut->flags&MEM_Static ){
- pOut->flags &= ~MEM_Static;
- pOut->flags |= MEM_Ephem;
- }
- columnMallocFailure(pStmt);
- return (sqlite3_value *)pOut;
-}
-#ifndef SQLITE_OMIT_UTF16
-const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
- const void *val = sqlite3_value_text16( columnMem(pStmt,i) );
- columnMallocFailure(pStmt);
- return val;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
- int iType = sqlite3_value_type( columnMem(pStmt,i) );
- columnMallocFailure(pStmt);
- return iType;
-}
-
-/*
-** Convert the N-th element of pStmt->pColName[] into a string using
-** xFunc() then return that string. If N is out of range, return 0.
-**
-** There are up to 5 names for each column. useType determines which
-** name is returned. Here are the names:
-**
-** 0 The column name as it should be displayed for output
-** 1 The datatype name for the column
-** 2 The name of the database that the column derives from
-** 3 The name of the table that the column derives from
-** 4 The name of the table column that the result column derives from
-**
-** If the result is not a simple column reference (if it is an expression
-** or a constant) then useTypes 2, 3, and 4 return NULL.
-*/
-static const void *columnName(
- sqlite3_stmt *pStmt,
- int N,
- const void *(*xFunc)(Mem*),
- int useType
-){
- const void *ret;
- Vdbe *p;
- int n;
- sqlite3 *db;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( pStmt==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- ret = 0;
- p = (Vdbe *)pStmt;
- db = p->db;
- assert( db!=0 );
- n = sqlite3_column_count(pStmt);
- if( N<n && N>=0 ){
- N += useType*n;
- sqlite3_mutex_enter(db->mutex);
- assert( db->mallocFailed==0 );
- ret = xFunc(&p->aColName[N]);
- /* A malloc may have failed inside of the xFunc() call. If this
- ** is the case, clear the mallocFailed flag and return NULL.
- */
- if( db->mallocFailed ){
- sqlite3OomClear(db);
- ret = 0;
- }
- sqlite3_mutex_leave(db->mutex);
- }
- return ret;
-}
-
-/*
-** Return the name of the Nth column of the result set returned by SQL
-** statement pStmt.
-*/
-const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME);
-}
-#ifndef SQLITE_OMIT_UTF16
-const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME);
-}
-#endif
-
-/*
-** Constraint: If you have ENABLE_COLUMN_METADATA then you must
-** not define OMIT_DECLTYPE.
-*/
-#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA)
-# error "Must not define both SQLITE_OMIT_DECLTYPE \
- and SQLITE_ENABLE_COLUMN_METADATA"
-#endif
-
-#ifndef SQLITE_OMIT_DECLTYPE
-/*
-** Return the column declaration type (if applicable) of the 'i'th column
-** of the result set of SQL statement pStmt.
-*/
-const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE);
-}
-#ifndef SQLITE_OMIT_UTF16
-const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
-}
-#endif /* SQLITE_OMIT_UTF16 */
-#endif /* SQLITE_OMIT_DECLTYPE */
-
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
-/*
-** Return the name of the database from which a result column derives.
-** NULL is returned if the result column is an expression or constant or
-** anything else which is not an unambiguous reference to a database column.
-*/
-const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE);
-}
-#ifndef SQLITE_OMIT_UTF16
-const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE);
-}
-#endif /* SQLITE_OMIT_UTF16 */
-
-/*
-** Return the name of the table from which a result column derives.
-** NULL is returned if the result column is an expression or constant or
-** anything else which is not an unambiguous reference to a database column.
-*/
-const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE);
-}
-#ifndef SQLITE_OMIT_UTF16
-const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE);
-}
-#endif /* SQLITE_OMIT_UTF16 */
-
-/*
-** Return the name of the table column from which a result column derives.
-** NULL is returned if the result column is an expression or constant or
-** anything else which is not an unambiguous reference to a database column.
-*/
-const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN);
-}
-#ifndef SQLITE_OMIT_UTF16
-const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN);
-}
-#endif /* SQLITE_OMIT_UTF16 */
-#endif /* SQLITE_ENABLE_COLUMN_METADATA */
-
-
-/******************************* sqlite3_bind_ ***************************
-**
-** Routines used to attach values to wildcards in a compiled SQL statement.
-*/
-/*
-** Unbind the value bound to variable i in virtual machine p. This is the
-** the same as binding a NULL value to the column. If the "i" parameter is
-** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
-**
-** A successful evaluation of this routine acquires the mutex on p.
-** the mutex is released if any kind of error occurs.
-**
-** The error code stored in database p->db is overwritten with the return
-** value in any case.
-*/
-static int vdbeUnbind(Vdbe *p, int i){
- Mem *pVar;
- if( vdbeSafetyNotNull(p) ){
- return SQLITE_MISUSE_BKPT;
- }
- sqlite3_mutex_enter(p->db->mutex);
- if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
- sqlite3Error(p->db, SQLITE_MISUSE);
- sqlite3_mutex_leave(p->db->mutex);
- sqlite3_log(SQLITE_MISUSE,
- "bind on a busy prepared statement: [%s]", p->zSql);
- return SQLITE_MISUSE_BKPT;
- }
- if( i<1 || i>p->nVar ){
- sqlite3Error(p->db, SQLITE_RANGE);
- sqlite3_mutex_leave(p->db->mutex);
- return SQLITE_RANGE;
- }
- i--;
- pVar = &p->aVar[i];
- sqlite3VdbeMemRelease(pVar);
- pVar->flags = MEM_Null;
- sqlite3Error(p->db, SQLITE_OK);
-
- /* If the bit corresponding to this variable in Vdbe.expmask is set, then
- ** binding a new value to this variable invalidates the current query plan.
- **
- ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
- ** parameter in the WHERE clause might influence the choice of query plan
- ** for a statement, then the statement will be automatically recompiled,
- ** as if there had been a schema change, on the first sqlite3_step() call
- ** following any change to the bindings of that parameter.
- */
- assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
- if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<<i))!=0 ){
- p->expired = 1;
- }
- return SQLITE_OK;
-}
-
-/*
-** Bind a text or BLOB value.
-*/
-static int bindText(
- sqlite3_stmt *pStmt, /* The statement to bind against */
- int i, /* Index of the parameter to bind */
- const void *zData, /* Pointer to the data to be bound */
- int nData, /* Number of bytes of data to be bound */
- void (*xDel)(void*), /* Destructor for the data */
- u8 encoding /* Encoding for the data */
-){
- Vdbe *p = (Vdbe *)pStmt;
- Mem *pVar;
- int rc;
-
- rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- if( zData!=0 ){
- pVar = &p->aVar[i-1];
- rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
- if( rc==SQLITE_OK && encoding!=0 ){
- rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
- }
- if( rc ){
- sqlite3Error(p->db, rc);
- rc = sqlite3ApiExit(p->db, rc);
- }
- }
- sqlite3_mutex_leave(p->db->mutex);
- }else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
- xDel((void*)zData);
- }
- return rc;
-}
-
-
-/*
-** Bind a blob value to an SQL statement variable.
-*/
-int sqlite3_bind_blob(
- sqlite3_stmt *pStmt,
- int i,
- const void *zData,
- int nData,
- void (*xDel)(void*)
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( nData<0 ) return SQLITE_MISUSE_BKPT;
-#endif
- return bindText(pStmt, i, zData, nData, xDel, 0);
-}
-int sqlite3_bind_blob64(
- sqlite3_stmt *pStmt,
- int i,
- const void *zData,
- sqlite3_uint64 nData,
- void (*xDel)(void*)
-){
- assert( xDel!=SQLITE_DYNAMIC );
- if( nData>0x7fffffff ){
- return invokeValueDestructor(zData, xDel, 0);
- }else{
- return bindText(pStmt, i, zData, (int)nData, xDel, 0);
- }
-}
-int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
- int rc;
- Vdbe *p = (Vdbe *)pStmt;
- rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
- sqlite3_mutex_leave(p->db->mutex);
- }
- return rc;
-}
-int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
- return sqlite3_bind_int64(p, i, (i64)iValue);
-}
-int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
- int rc;
- Vdbe *p = (Vdbe *)pStmt;
- rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
- sqlite3_mutex_leave(p->db->mutex);
- }
- return rc;
-}
-int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
- int rc;
- Vdbe *p = (Vdbe*)pStmt;
- rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- sqlite3_mutex_leave(p->db->mutex);
- }
- return rc;
-}
-int sqlite3_bind_pointer(
- sqlite3_stmt *pStmt,
- int i,
- void *pPtr,
- const char *zPTtype,
- void (*xDestructor)(void*)
-){
- int rc;
- Vdbe *p = (Vdbe*)pStmt;
- rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
- sqlite3_mutex_leave(p->db->mutex);
- }else if( xDestructor ){
- xDestructor(pPtr);
- }
- return rc;
-}
-int sqlite3_bind_text(
- sqlite3_stmt *pStmt,
- int i,
- const char *zData,
- int nData,
- void (*xDel)(void*)
-){
- return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
-}
-int sqlite3_bind_text64(
- sqlite3_stmt *pStmt,
- int i,
- const char *zData,
- sqlite3_uint64 nData,
- void (*xDel)(void*),
- unsigned char enc
-){
- assert( xDel!=SQLITE_DYNAMIC );
- if( nData>0x7fffffff ){
- return invokeValueDestructor(zData, xDel, 0);
- }else{
- if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
- return bindText(pStmt, i, zData, (int)nData, xDel, enc);
- }
-}
-#ifndef SQLITE_OMIT_UTF16
-int sqlite3_bind_text16(
- sqlite3_stmt *pStmt,
- int i,
- const void *zData,
- int nData,
- void (*xDel)(void*)
-){
- return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
-}
-#endif /* SQLITE_OMIT_UTF16 */
-int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
- int rc;
- switch( sqlite3_value_type((sqlite3_value*)pValue) ){
- case SQLITE_INTEGER: {
- rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
- break;
- }
- case SQLITE_FLOAT: {
- rc = sqlite3_bind_double(pStmt, i, pValue->u.r);
- break;
- }
- case SQLITE_BLOB: {
- if( pValue->flags & MEM_Zero ){
- rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero);
- }else{
- rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT);
- }
- break;
- }
- case SQLITE_TEXT: {
- rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT,
- pValue->enc);
- break;
- }
- default: {
- rc = sqlite3_bind_null(pStmt, i);
- break;
- }
- }
- return rc;
-}
-int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
- int rc;
- Vdbe *p = (Vdbe *)pStmt;
- rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
- sqlite3_mutex_leave(p->db->mutex);
- }
- return rc;
-}
-int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){
- int rc;
- Vdbe *p = (Vdbe *)pStmt;
- sqlite3_mutex_enter(p->db->mutex);
- if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){
- rc = SQLITE_TOOBIG;
- }else{
- assert( (n & 0x7FFFFFFF)==n );
- rc = sqlite3_bind_zeroblob(pStmt, i, n);
- }
- rc = sqlite3ApiExit(p->db, rc);
- sqlite3_mutex_leave(p->db->mutex);
- return rc;
-}
-
-/*
-** Return the number of wildcards that can be potentially bound to.
-** This routine is added to support DBD::SQLite.
-*/
-int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
- Vdbe *p = (Vdbe*)pStmt;
- return p ? p->nVar : 0;
-}
-
-/*
-** Return the name of a wildcard parameter. Return NULL if the index
-** is out of range or if the wildcard is unnamed.
-**
-** The result is always UTF-8.
-*/
-const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
- Vdbe *p = (Vdbe*)pStmt;
- if( p==0 ) return 0;
- return sqlite3VListNumToName(p->pVList, i);
-}
-
-/*
-** Given a wildcard parameter name, return the index of the variable
-** with that name. If there is no variable with the given name,
-** return 0.
-*/
-int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
- if( p==0 || zName==0 ) return 0;
- return sqlite3VListNameToNum(p->pVList, zName, nName);
-}
-int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
- return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
-}
-
-/*
-** Transfer all bindings from the first statement over to the second.
-*/
-int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
- Vdbe *pFrom = (Vdbe*)pFromStmt;
- Vdbe *pTo = (Vdbe*)pToStmt;
- int i;
- assert( pTo->db==pFrom->db );
- assert( pTo->nVar==pFrom->nVar );
- sqlite3_mutex_enter(pTo->db->mutex);
- for(i=0; i<pFrom->nVar; i++){
- sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
- }
- sqlite3_mutex_leave(pTo->db->mutex);
- return SQLITE_OK;
-}
-
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** Deprecated external interface. Internal/core SQLite code
-** should call sqlite3TransferBindings.
-**
-** It is misuse to call this routine with statements from different
-** database connections. But as this is a deprecated interface, we
-** will not bother to check for that condition.
-**
-** If the two statements contain a different number of bindings, then
-** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise
-** SQLITE_OK is returned.
-*/
-int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
- Vdbe *pFrom = (Vdbe*)pFromStmt;
- Vdbe *pTo = (Vdbe*)pToStmt;
- if( pFrom->nVar!=pTo->nVar ){
- return SQLITE_ERROR;
- }
- assert( (pTo->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pTo->expmask==0 );
- if( pTo->expmask ){
- pTo->expired = 1;
- }
- assert( (pFrom->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pFrom->expmask==0 );
- if( pFrom->expmask ){
- pFrom->expired = 1;
- }
- return sqlite3TransferBindings(pFromStmt, pToStmt);
-}
-#endif
-
-/*
-** Return the sqlite3* database handle to which the prepared statement given
-** in the argument belongs. This is the same database handle that was
-** the first argument to the sqlite3_prepare() that was used to create
-** the statement in the first place.
-*/
-sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
- return pStmt ? ((Vdbe*)pStmt)->db : 0;
-}
-
-/*
-** Return true if the prepared statement is guaranteed to not modify the
-** database.
-*/
-int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
- return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
-}
-
-/*
-** Return true if the prepared statement is in need of being reset.
-*/
-int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
- Vdbe *v = (Vdbe*)pStmt;
- return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
-}
-
-/*
-** Return a pointer to the next prepared statement after pStmt associated
-** with database connection pDb. If pStmt is NULL, return the first
-** prepared statement for the database connection. Return NULL if there
-** are no more.
-*/
-sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
- sqlite3_stmt *pNext;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(pDb) ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- sqlite3_mutex_enter(pDb->mutex);
- if( pStmt==0 ){
- pNext = (sqlite3_stmt*)pDb->pVdbe;
- }else{
- pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext;
- }
- sqlite3_mutex_leave(pDb->mutex);
- return pNext;
-}
-
-/*
-** Return the value of a status counter for a prepared statement
-*/
-int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
- Vdbe *pVdbe = (Vdbe*)pStmt;
- u32 v;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !pStmt
- || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter)))
- ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- if( op==SQLITE_STMTSTATUS_MEMUSED ){
- sqlite3 *db = pVdbe->db;
- sqlite3_mutex_enter(db->mutex);
- v = 0;
- db->pnBytesFreed = (int*)&v;
- sqlite3VdbeClearObject(db, pVdbe);
- sqlite3DbFree(db, pVdbe);
- db->pnBytesFreed = 0;
- sqlite3_mutex_leave(db->mutex);
- }else{
- v = pVdbe->aCounter[op];
- if( resetFlag ) pVdbe->aCounter[op] = 0;
- }
- return (int)v;
-}
-
-/*
-** Return the SQL associated with a prepared statement
-*/
-const char *sqlite3_sql(sqlite3_stmt *pStmt){
- Vdbe *p = (Vdbe *)pStmt;
- return p ? p->zSql : 0;
-}
-
-/*
-** Return the SQL associated with a prepared statement with
-** bound parameters expanded. Space to hold the returned string is
-** obtained from sqlite3_malloc(). The caller is responsible for
-** freeing the returned string by passing it to sqlite3_free().
-**
-** The SQLITE_TRACE_SIZE_LIMIT puts an upper bound on the size of
-** expanded bound parameters.
-*/
-char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
-#ifdef SQLITE_OMIT_TRACE
- return 0;
-#else
- char *z = 0;
- const char *zSql = sqlite3_sql(pStmt);
- if( zSql ){
- Vdbe *p = (Vdbe *)pStmt;
- sqlite3_mutex_enter(p->db->mutex);
- z = sqlite3VdbeExpandSql(p, zSql);
- sqlite3_mutex_leave(p->db->mutex);
- }
- return z;
-#endif
-}
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-/*
-** Allocate and populate an UnpackedRecord structure based on the serialized
-** record in nKey/pKey. Return a pointer to the new UnpackedRecord structure
-** if successful, or a NULL pointer if an OOM error is encountered.
-*/
-static UnpackedRecord *vdbeUnpackRecord(
- KeyInfo *pKeyInfo,
- int nKey,
- const void *pKey
-){
- UnpackedRecord *pRet; /* Return value */
-
- pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
- if( pRet ){
- memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
- sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
- }
- return pRet;
-}
-
-/*
-** This function is called from within a pre-update callback to retrieve
-** a field of the row currently being updated or deleted.
-*/
-int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
- PreUpdate *p = db->pPreUpdate;
- Mem *pMem;
- int rc = SQLITE_OK;
-
- /* Test that this call is being made from within an SQLITE_DELETE or
- ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */
- if( !p || p->op==SQLITE_INSERT ){
- rc = SQLITE_MISUSE_BKPT;
- goto preupdate_old_out;
- }
- if( p->pPk ){
- iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
- }
- if( iIdx>=p->pCsr->nField || iIdx<0 ){
- rc = SQLITE_RANGE;
- goto preupdate_old_out;
- }
-
- /* If the old.* record has not yet been loaded into memory, do so now. */
- if( p->pUnpacked==0 ){
- u32 nRec;
- u8 *aRec;
-
- nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
- aRec = sqlite3DbMallocRaw(db, nRec);
- if( !aRec ) goto preupdate_old_out;
- rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
- if( rc==SQLITE_OK ){
- p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
- if( !p->pUnpacked ) rc = SQLITE_NOMEM;
- }
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, aRec);
- goto preupdate_old_out;
- }
- p->aRecord = aRec;
- }
-
- pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey1);
- }else if( iIdx>=p->pUnpacked->nField ){
- *ppValue = (sqlite3_value *)columnNullValue();
- }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
- if( pMem->flags & MEM_Int ){
- sqlite3VdbeMemRealify(pMem);
- }
- }
-
- preupdate_old_out:
- sqlite3Error(db, rc);
- return sqlite3ApiExit(db, rc);
-}
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-/*
-** This function is called from within a pre-update callback to retrieve
-** the number of columns in the row being updated, deleted or inserted.
-*/
-int sqlite3_preupdate_count(sqlite3 *db){
- PreUpdate *p = db->pPreUpdate;
- return (p ? p->keyinfo.nKeyField : 0);
-}
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-/*
-** This function is designed to be called from within a pre-update callback
-** only. It returns zero if the change that caused the callback was made
-** immediately by a user SQL statement. Or, if the change was made by a
-** trigger program, it returns the number of trigger programs currently
-** on the stack (1 for a top-level trigger, 2 for a trigger fired by a
-** top-level trigger etc.).
-**
-** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL
-** or SET DEFAULT action is considered a trigger.
-*/
-int sqlite3_preupdate_depth(sqlite3 *db){
- PreUpdate *p = db->pPreUpdate;
- return (p ? p->v->nFrame : 0);
-}
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-/*
-** This function is called from within a pre-update callback to retrieve
-** a field of the row currently being updated or inserted.
-*/
-int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
- PreUpdate *p = db->pPreUpdate;
- int rc = SQLITE_OK;
- Mem *pMem;
-
- if( !p || p->op==SQLITE_DELETE ){
- rc = SQLITE_MISUSE_BKPT;
- goto preupdate_new_out;
- }
- if( p->pPk && p->op!=SQLITE_UPDATE ){
- iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
- }
- if( iIdx>=p->pCsr->nField || iIdx<0 ){
- rc = SQLITE_RANGE;
- goto preupdate_new_out;
- }
-
- if( p->op==SQLITE_INSERT ){
- /* For an INSERT, memory cell p->iNewReg contains the serialized record
- ** that is being inserted. Deserialize it. */
- UnpackedRecord *pUnpack = p->pNewUnpacked;
- if( !pUnpack ){
- Mem *pData = &p->v->aMem[p->iNewReg];
- rc = ExpandBlob(pData);
- if( rc!=SQLITE_OK ) goto preupdate_new_out;
- pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z);
- if( !pUnpack ){
- rc = SQLITE_NOMEM;
- goto preupdate_new_out;
- }
- p->pNewUnpacked = pUnpack;
- }
- pMem = &pUnpack->aMem[iIdx];
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey2);
- }else if( iIdx>=pUnpack->nField ){
- pMem = (sqlite3_value *)columnNullValue();
- }
- }else{
- /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
- ** value. Make a copy of the cell contents and return a pointer to it.
- ** It is not safe to return a pointer to the memory cell itself as the
- ** caller may modify the value text encoding.
- */
- assert( p->op==SQLITE_UPDATE );
- if( !p->aNew ){
- p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField);
- if( !p->aNew ){
- rc = SQLITE_NOMEM;
- goto preupdate_new_out;
- }
- }
- assert( iIdx>=0 && iIdx<p->pCsr->nField );
- pMem = &p->aNew[iIdx];
- if( pMem->flags==0 ){
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey2);
- }else{
- rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
- if( rc!=SQLITE_OK ) goto preupdate_new_out;
- }
- }
- }
- *ppValue = pMem;
-
- preupdate_new_out:
- sqlite3Error(db, rc);
- return sqlite3ApiExit(db, rc);
-}
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
-
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
-/*
-** Return status data for a single loop within query pStmt.
-*/
-int sqlite3_stmt_scanstatus(
- sqlite3_stmt *pStmt, /* Prepared statement being queried */
- int idx, /* Index of loop to report on */
- int iScanStatusOp, /* Which metric to return */
- void *pOut /* OUT: Write the answer here */
-){
- Vdbe *p = (Vdbe*)pStmt;
- ScanStatus *pScan;
- if( idx<0 || idx>=p->nScan ) return 1;
- pScan = &p->aScan[idx];
- switch( iScanStatusOp ){
- case SQLITE_SCANSTAT_NLOOP: {
- *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop];
- break;
- }
- case SQLITE_SCANSTAT_NVISIT: {
- *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit];
- break;
- }
- case SQLITE_SCANSTAT_EST: {
- double r = 1.0;
- LogEst x = pScan->nEst;
- while( x<100 ){
- x += 10;
- r *= 0.5;
- }
- *(double*)pOut = r*sqlite3LogEstToInt(x);
- break;
- }
- case SQLITE_SCANSTAT_NAME: {
- *(const char**)pOut = pScan->zName;
- break;
- }
- case SQLITE_SCANSTAT_EXPLAIN: {
- if( pScan->addrExplain ){
- *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z;
- }else{
- *(const char**)pOut = 0;
- }
- break;
- }
- case SQLITE_SCANSTAT_SELECTID: {
- if( pScan->addrExplain ){
- *(int*)pOut = p->aOp[ pScan->addrExplain ].p1;
- }else{
- *(int*)pOut = -1;
- }
- break;
- }
- default: {
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** Zero all counters associated with the sqlite3_stmt_scanstatus() data.
-*/
-void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
- Vdbe *p = (Vdbe*)pStmt;
- memset(p->anExec, 0, p->nOp * sizeof(i64));
-}
-#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeaux.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeaux.c
deleted file mode 100644
index 38ef85f0ec5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeaux.c
+++ /dev/null
@@ -1,4848 +0,0 @@
-/*
-** 2003 September 6
-**
-** 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 contains code used for creating, destroying, and populating
-** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-/*
-** Create a new virtual database engine.
-*/
-Vdbe *sqlite3VdbeCreate(Parse *pParse){
- sqlite3 *db = pParse->db;
- Vdbe *p;
- p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) );
- if( p==0 ) return 0;
- memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp));
- p->db = db;
- if( db->pVdbe ){
- db->pVdbe->pPrev = p;
- }
- p->pNext = db->pVdbe;
- p->pPrev = 0;
- db->pVdbe = p;
- p->magic = VDBE_MAGIC_INIT;
- p->pParse = pParse;
- pParse->pVdbe = p;
- assert( pParse->aLabel==0 );
- assert( pParse->nLabel==0 );
- assert( pParse->nOpAlloc==0 );
- assert( pParse->szOpAlloc==0 );
- sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
- return p;
-}
-
-/*
-** Change the error string stored in Vdbe.zErrMsg
-*/
-void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
- va_list ap;
- sqlite3DbFree(p->db, p->zErrMsg);
- va_start(ap, zFormat);
- p->zErrMsg = sqlite3VMPrintf(p->db, zFormat, ap);
- va_end(ap);
-}
-
-/*
-** Remember the SQL string for a prepared statement.
-*/
-void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){
- if( p==0 ) return;
- p->prepFlags = prepFlags;
- if( (prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){
- p->expmask = 0;
- }
- assert( p->zSql==0 );
- p->zSql = sqlite3DbStrNDup(p->db, z, n);
-}
-
-/*
-** Swap all content between two VDBE structures.
-*/
-void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
- Vdbe tmp, *pTmp;
- char *zTmp;
- assert( pA->db==pB->db );
- tmp = *pA;
- *pA = *pB;
- *pB = tmp;
- pTmp = pA->pNext;
- pA->pNext = pB->pNext;
- pB->pNext = pTmp;
- pTmp = pA->pPrev;
- pA->pPrev = pB->pPrev;
- pB->pPrev = pTmp;
- zTmp = pA->zSql;
- pA->zSql = pB->zSql;
- pB->zSql = zTmp;
- pB->expmask = pA->expmask;
- pB->prepFlags = pA->prepFlags;
- memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
- pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++;
-}
-
-/*
-** Resize the Vdbe.aOp array so that it is at least nOp elements larger
-** than its current size. nOp is guaranteed to be less than or equal
-** to 1024/sizeof(Op).
-**
-** If an out-of-memory error occurs while resizing the array, return
-** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain
-** unchanged (this is so that any opcodes already allocated can be
-** correctly deallocated along with the rest of the Vdbe).
-*/
-static int growOpArray(Vdbe *v, int nOp){
- VdbeOp *pNew;
- Parse *p = v->pParse;
-
- /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
- ** more frequent reallocs and hence provide more opportunities for
- ** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used
- ** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array
- ** by the minimum* amount required until the size reaches 512. Normal
- ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
- ** size of the op array or add 1KB of space, whichever is smaller. */
-#ifdef SQLITE_TEST_REALLOC_STRESS
- int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
-#else
- int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
- UNUSED_PARAMETER(nOp);
-#endif
-
- /* Ensure that the size of a VDBE does not grow too large */
- if( nNew > p->db->aLimit[SQLITE_LIMIT_VDBE_OP] ){
- sqlite3OomFault(p->db);
- return SQLITE_NOMEM;
- }
-
- assert( nOp<=(1024/sizeof(Op)) );
- assert( nNew>=(p->nOpAlloc+nOp) );
- pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
- if( pNew ){
- p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
- p->nOpAlloc = p->szOpAlloc/sizeof(Op);
- v->aOp = pNew;
- }
- return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT);
-}
-
-#ifdef SQLITE_DEBUG
-/* This routine is just a convenient place to set a breakpoint that will
-** fire after each opcode is inserted and displayed using
-** "PRAGMA vdbe_addoptrace=on".
-*/
-static void test_addop_breakpoint(void){
- static int n = 0;
- n++;
-}
-#endif
-
-/*
-** Add a new instruction to the list of instructions current in the
-** VDBE. Return the address of the new instruction.
-**
-** Parameters:
-**
-** p Pointer to the VDBE
-**
-** op The opcode for this instruction
-**
-** p1, p2, p3 Operands
-**
-** Use the sqlite3VdbeResolveLabel() function to fix an address and
-** the sqlite3VdbeChangeP4() function to change the value of the P4
-** operand.
-*/
-static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
- assert( p->pParse->nOpAlloc<=p->nOp );
- if( growOpArray(p, 1) ) return 1;
- assert( p->pParse->nOpAlloc>p->nOp );
- return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
-}
-int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
- int i;
- VdbeOp *pOp;
-
- i = p->nOp;
- assert( p->magic==VDBE_MAGIC_INIT );
- assert( op>=0 && op<0xff );
- if( p->pParse->nOpAlloc<=i ){
- return growOp3(p, op, p1, p2, p3);
- }
- p->nOp++;
- pOp = &p->aOp[i];
- pOp->opcode = (u8)op;
- pOp->p5 = 0;
- pOp->p1 = p1;
- pOp->p2 = p2;
- pOp->p3 = p3;
- pOp->p4.p = 0;
- pOp->p4type = P4_NOTUSED;
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- pOp->zComment = 0;
-#endif
-#ifdef SQLITE_DEBUG
- if( p->db->flags & SQLITE_VdbeAddopTrace ){
- int jj, kk;
- Parse *pParse = p->pParse;
- for(jj=kk=0; jj<pParse->nColCache; jj++){
- struct yColCache *x = pParse->aColCache + jj;
- printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
- kk++;
- }
- if( kk ) printf("\n");
- sqlite3VdbePrintOp(0, i, &p->aOp[i]);
- test_addop_breakpoint();
- }
-#endif
-#ifdef VDBE_PROFILE
- pOp->cycles = 0;
- pOp->cnt = 0;
-#endif
-#ifdef SQLITE_VDBE_COVERAGE
- pOp->iSrcLine = 0;
-#endif
- return i;
-}
-int sqlite3VdbeAddOp0(Vdbe *p, int op){
- return sqlite3VdbeAddOp3(p, op, 0, 0, 0);
-}
-int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){
- return sqlite3VdbeAddOp3(p, op, p1, 0, 0);
-}
-int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){
- return sqlite3VdbeAddOp3(p, op, p1, p2, 0);
-}
-
-/* Generate code for an unconditional jump to instruction iDest
-*/
-int sqlite3VdbeGoto(Vdbe *p, int iDest){
- return sqlite3VdbeAddOp3(p, OP_Goto, 0, iDest, 0);
-}
-
-/* Generate code to cause the string zStr to be loaded into
-** register iDest
-*/
-int sqlite3VdbeLoadString(Vdbe *p, int iDest, const char *zStr){
- return sqlite3VdbeAddOp4(p, OP_String8, 0, iDest, 0, zStr, 0);
-}
-
-/*
-** Generate code that initializes multiple registers to string or integer
-** constants. The registers begin with iDest and increase consecutively.
-** One register is initialized for each characgter in zTypes[]. For each
-** "s" character in zTypes[], the register is a string if the argument is
-** not NULL, or OP_Null if the value is a null pointer. For each "i" character
-** in zTypes[], the register is initialized to an integer.
-**
-** If the input string does not end with "X" then an OP_ResultRow instruction
-** is generated for the values inserted.
-*/
-void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, ...){
- va_list ap;
- int i;
- char c;
- va_start(ap, zTypes);
- for(i=0; (c = zTypes[i])!=0; i++){
- if( c=='s' ){
- const char *z = va_arg(ap, const char*);
- sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest+i, 0, z, 0);
- }else if( c=='i' ){
- sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest+i);
- }else{
- goto skip_op_resultrow;
- }
- }
- sqlite3VdbeAddOp2(p, OP_ResultRow, iDest, i);
-skip_op_resultrow:
- va_end(ap);
-}
-
-/*
-** Add an opcode that includes the p4 value as a pointer.
-*/
-int sqlite3VdbeAddOp4(
- Vdbe *p, /* Add the opcode to this VM */
- int op, /* The new opcode */
- int p1, /* The P1 operand */
- int p2, /* The P2 operand */
- int p3, /* The P3 operand */
- const char *zP4, /* The P4 operand */
- int p4type /* P4 operand type */
-){
- int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
- sqlite3VdbeChangeP4(p, addr, zP4, p4type);
- return addr;
-}
-
-/*
-** Add an opcode that includes the p4 value with a P4_INT64 or
-** P4_REAL type.
-*/
-int sqlite3VdbeAddOp4Dup8(
- Vdbe *p, /* Add the opcode to this VM */
- int op, /* The new opcode */
- int p1, /* The P1 operand */
- int p2, /* The P2 operand */
- int p3, /* The P3 operand */
- const u8 *zP4, /* The P4 operand */
- int p4type /* P4 operand type */
-){
- char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8);
- if( p4copy ) memcpy(p4copy, zP4, 8);
- return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
-}
-
-#ifndef SQLITE_OMIT_EXPLAIN
-/*
-** Return the address of the current EXPLAIN QUERY PLAN baseline.
-** 0 means "none".
-*/
-int sqlite3VdbeExplainParent(Parse *pParse){
- VdbeOp *pOp;
- if( pParse->addrExplain==0 ) return 0;
- pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain);
- return pOp->p2;
-}
-
-/*
-** Add a new OP_Explain opcode.
-**
-** If the bPush flag is true, then make this opcode the parent for
-** subsequent Explains until sqlite3VdbeExplainPop() is called.
-*/
-void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
- if( pParse->explain==2 ){
- char *zMsg;
- Vdbe *v = pParse->pVdbe;
- va_list ap;
- int iThis;
- va_start(ap, zFmt);
- zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap);
- va_end(ap);
- v = pParse->pVdbe;
- iThis = v->nOp;
- sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
- zMsg, P4_DYNAMIC);
- if( bPush) pParse->addrExplain = iThis;
- }
-}
-
-/*
-** Pop the EXPLAIN QUERY PLAN stack one level.
-*/
-void sqlite3VdbeExplainPop(Parse *pParse){
- pParse->addrExplain = sqlite3VdbeExplainParent(pParse);
-}
-#endif /* SQLITE_OMIT_EXPLAIN */
-
-/*
-** Add an OP_ParseSchema opcode. This routine is broken out from
-** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
-** as having been used.
-**
-** The zWhere string must have been obtained from sqlite3_malloc().
-** This routine will take ownership of the allocated memory.
-*/
-void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
- int j;
- sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
- for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
-}
-
-/*
-** Add an opcode that includes the p4 value as an integer.
-*/
-int sqlite3VdbeAddOp4Int(
- Vdbe *p, /* Add the opcode to this VM */
- int op, /* The new opcode */
- int p1, /* The P1 operand */
- int p2, /* The P2 operand */
- int p3, /* The P3 operand */
- int p4 /* The P4 operand as an integer */
-){
- int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
- if( p->db->mallocFailed==0 ){
- VdbeOp *pOp = &p->aOp[addr];
- pOp->p4type = P4_INT32;
- pOp->p4.i = p4;
- }
- return addr;
-}
-
-/* Insert the end of a co-routine
-*/
-void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){
- sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield);
-
- /* Clear the temporary register cache, thereby ensuring that each
- ** co-routine has its own independent set of registers, because co-routines
- ** might expect their registers to be preserved across an OP_Yield, and
- ** that could cause problems if two or more co-routines are using the same
- ** temporary register.
- */
- v->pParse->nTempReg = 0;
- v->pParse->nRangeReg = 0;
-}
-
-/*
-** Create a new symbolic label for an instruction that has yet to be
-** coded. The symbolic label is really just a negative number. The
-** label can be used as the P2 value of an operation. Later, when
-** the label is resolved to a specific address, the VDBE will scan
-** through its operation list and change all values of P2 which match
-** the label into the resolved address.
-**
-** The VDBE knows that a P2 value is a label because labels are
-** always negative and P2 values are suppose to be non-negative.
-** Hence, a negative P2 value is a label that has yet to be resolved.
-**
-** Zero is returned if a malloc() fails.
-*/
-int sqlite3VdbeMakeLabel(Vdbe *v){
- Parse *p = v->pParse;
- int i = p->nLabel++;
- assert( v->magic==VDBE_MAGIC_INIT );
- if( (i & (i-1))==0 ){
- p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
- (i*2+1)*sizeof(p->aLabel[0]));
- }
- if( p->aLabel ){
- p->aLabel[i] = -1;
- }
- return ADDR(i);
-}
-
-/*
-** Resolve label "x" to be the address of the next instruction to
-** be inserted. The parameter "x" must have been obtained from
-** a prior call to sqlite3VdbeMakeLabel().
-*/
-void sqlite3VdbeResolveLabel(Vdbe *v, int x){
- Parse *p = v->pParse;
- int j = ADDR(x);
- assert( v->magic==VDBE_MAGIC_INIT );
- assert( j<p->nLabel );
- assert( j>=0 );
- if( p->aLabel ){
-#ifdef SQLITE_DEBUG
- if( p->db->flags & SQLITE_VdbeAddopTrace ){
- printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
- }
-#endif
- assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */
- p->aLabel[j] = v->nOp;
- }
-}
-
-#ifdef SQLITE_COVERAGE_TEST
-/*
-** Return TRUE if and only if the label x has already been resolved.
-** Return FALSE (zero) if label x is still unresolved.
-**
-** This routine is only used inside of testcase() macros, and so it
-** only exists when measuring test coverage.
-*/
-int sqlite3VdbeLabelHasBeenResolved(Vdbe *v, int x){
- return v->pParse->aLabel && v->pParse->aLabel[ADDR(x)]>=0;
-}
-#endif /* SQLITE_COVERAGE_TEST */
-
-/*
-** Mark the VDBE as one that can only be run one time.
-*/
-void sqlite3VdbeRunOnlyOnce(Vdbe *p){
- p->runOnlyOnce = 1;
-}
-
-/*
-** Mark the VDBE as one that can only be run multiple times.
-*/
-void sqlite3VdbeReusable(Vdbe *p){
- p->runOnlyOnce = 0;
-}
-
-#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
-
-/*
-** The following type and function are used to iterate through all opcodes
-** in a Vdbe main program and each of the sub-programs (triggers) it may
-** invoke directly or indirectly. It should be used as follows:
-**
-** Op *pOp;
-** VdbeOpIter sIter;
-**
-** memset(&sIter, 0, sizeof(sIter));
-** sIter.v = v; // v is of type Vdbe*
-** while( (pOp = opIterNext(&sIter)) ){
-** // Do something with pOp
-** }
-** sqlite3DbFree(v->db, sIter.apSub);
-**
-*/
-typedef struct VdbeOpIter VdbeOpIter;
-struct VdbeOpIter {
- Vdbe *v; /* Vdbe to iterate through the opcodes of */
- SubProgram **apSub; /* Array of subprograms */
- int nSub; /* Number of entries in apSub */
- int iAddr; /* Address of next instruction to return */
- int iSub; /* 0 = main program, 1 = first sub-program etc. */
-};
-static Op *opIterNext(VdbeOpIter *p){
- Vdbe *v = p->v;
- Op *pRet = 0;
- Op *aOp;
- int nOp;
-
- if( p->iSub<=p->nSub ){
-
- if( p->iSub==0 ){
- aOp = v->aOp;
- nOp = v->nOp;
- }else{
- aOp = p->apSub[p->iSub-1]->aOp;
- nOp = p->apSub[p->iSub-1]->nOp;
- }
- assert( p->iAddr<nOp );
-
- pRet = &aOp[p->iAddr];
- p->iAddr++;
- if( p->iAddr==nOp ){
- p->iSub++;
- p->iAddr = 0;
- }
-
- if( pRet->p4type==P4_SUBPROGRAM ){
- int nByte = (p->nSub+1)*sizeof(SubProgram*);
- int j;
- for(j=0; j<p->nSub; j++){
- if( p->apSub[j]==pRet->p4.pProgram ) break;
- }
- if( j==p->nSub ){
- p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte);
- if( !p->apSub ){
- pRet = 0;
- }else{
- p->apSub[p->nSub++] = pRet->p4.pProgram;
- }
- }
- }
- }
-
- return pRet;
-}
-
-/*
-** Check if the program stored in the VM associated with pParse may
-** throw an ABORT exception (causing the statement, but not entire transaction
-** to be rolled back). This condition is true if the main program or any
-** sub-programs contains any of the following:
-**
-** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
-** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
-** * OP_Destroy
-** * OP_VUpdate
-** * OP_VRename
-** * OP_FkCounter with P2==0 (immediate foreign key constraint)
-** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine
-** (for CREATE TABLE AS SELECT ...)
-**
-** Then check that the value of Parse.mayAbort is true if an
-** ABORT may be thrown, or false otherwise. Return true if it does
-** match, or false otherwise. This function is intended to be used as
-** part of an assert statement in the compiler. Similar to:
-**
-** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
-*/
-int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
- int hasAbort = 0;
- int hasFkCounter = 0;
- int hasCreateTable = 0;
- int hasInitCoroutine = 0;
- Op *pOp;
- VdbeOpIter sIter;
- memset(&sIter, 0, sizeof(sIter));
- sIter.v = v;
-
- while( (pOp = opIterNext(&sIter))!=0 ){
- int opcode = pOp->opcode;
- if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
- || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
- && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
- ){
- hasAbort = 1;
- break;
- }
- if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
- if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
- hasFkCounter = 1;
- }
-#endif
- }
- sqlite3DbFree(v->db, sIter.apSub);
-
- /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
- ** If malloc failed, then the while() loop above may not have iterated
- ** through all opcodes and hasAbort may be set incorrectly. Return
- ** true for this case to prevent the assert() in the callers frame
- ** from failing. */
- return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter
- || (hasCreateTable && hasInitCoroutine) );
-}
-#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
-
-#ifdef SQLITE_DEBUG
-/*
-** Increment the nWrite counter in the VDBE if the cursor is not an
-** ephemeral cursor, or if the cursor argument is NULL.
-*/
-void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){
- if( pC==0
- || (pC->eCurType!=CURTYPE_SORTER
- && pC->eCurType!=CURTYPE_PSEUDO
- && !pC->isEphemeral)
- ){
- p->nWrite++;
- }
-}
-#endif
-
-#ifdef SQLITE_DEBUG
-/*
-** Assert if an Abort at this point in time might result in a corrupt
-** database.
-*/
-void sqlite3VdbeAssertAbortable(Vdbe *p){
- assert( p->nWrite==0 || p->usesStmtJournal );
-}
-#endif
-
-/*
-** This routine is called after all opcodes have been inserted. It loops
-** through all the opcodes and fixes up some details.
-**
-** (1) For each jump instruction with a negative P2 value (a label)
-** resolve the P2 value to an actual address.
-**
-** (2) Compute the maximum number of arguments used by any SQL function
-** and store that value in *pMaxFuncArgs.
-**
-** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
-** indicate what the prepared statement actually does.
-**
-** (4) Initialize the p4.xAdvance pointer on opcodes that use it.
-**
-** (5) Reclaim the memory allocated for storing labels.
-**
-** This routine will only function correctly if the mkopcodeh.tcl generator
-** script numbers the opcodes correctly. Changes to this routine must be
-** coordinated with changes to mkopcodeh.tcl.
-*/
-static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
- int nMaxArgs = *pMaxFuncArgs;
- Op *pOp;
- Parse *pParse = p->pParse;
- int *aLabel = pParse->aLabel;
- p->readOnly = 1;
- p->bIsReader = 0;
- pOp = &p->aOp[p->nOp-1];
- while(1){
-
- /* Only JUMP opcodes and the short list of special opcodes in the switch
- ** below need to be considered. The mkopcodeh.tcl generator script groups
- ** all these opcodes together near the front of the opcode list. Skip
- ** any opcode that does not need processing by virtual of the fact that
- ** it is larger than SQLITE_MX_JUMP_OPCODE, as a performance optimization.
- */
- if( pOp->opcode<=SQLITE_MX_JUMP_OPCODE ){
- /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing
- ** cases from this switch! */
- switch( pOp->opcode ){
- case OP_Transaction: {
- if( pOp->p2!=0 ) p->readOnly = 0;
- /* fall thru */
- }
- case OP_AutoCommit:
- case OP_Savepoint: {
- p->bIsReader = 1;
- break;
- }
-#ifndef SQLITE_OMIT_WAL
- case OP_Checkpoint:
-#endif
- case OP_Vacuum:
- case OP_JournalMode: {
- p->readOnly = 0;
- p->bIsReader = 1;
- break;
- }
- case OP_Next:
- case OP_NextIfOpen:
- case OP_SorterNext: {
- pOp->p4.xAdvance = sqlite3BtreeNext;
- pOp->p4type = P4_ADVANCE;
- /* The code generator never codes any of these opcodes as a jump
- ** to a label. They are always coded as a jump backwards to a
- ** known address */
- assert( pOp->p2>=0 );
- break;
- }
- case OP_Prev:
- case OP_PrevIfOpen: {
- pOp->p4.xAdvance = sqlite3BtreePrevious;
- pOp->p4type = P4_ADVANCE;
- /* The code generator never codes any of these opcodes as a jump
- ** to a label. They are always coded as a jump backwards to a
- ** known address */
- assert( pOp->p2>=0 );
- break;
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- case OP_VUpdate: {
- if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
- break;
- }
- case OP_VFilter: {
- int n;
- assert( (pOp - p->aOp) >= 3 );
- assert( pOp[-1].opcode==OP_Integer );
- n = pOp[-1].p1;
- if( n>nMaxArgs ) nMaxArgs = n;
- /* Fall through into the default case */
- }
-#endif
- default: {
- if( pOp->p2<0 ){
- /* The mkopcodeh.tcl script has so arranged things that the only
- ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
- ** have non-negative values for P2. */
- assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 );
- assert( ADDR(pOp->p2)<pParse->nLabel );
- pOp->p2 = aLabel[ADDR(pOp->p2)];
- }
- break;
- }
- }
- /* The mkopcodeh.tcl script has so arranged things that the only
- ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
- ** have non-negative values for P2. */
- assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0);
- }
- if( pOp==p->aOp ) break;
- pOp--;
- }
- sqlite3DbFree(p->db, pParse->aLabel);
- pParse->aLabel = 0;
- pParse->nLabel = 0;
- *pMaxFuncArgs = nMaxArgs;
- assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
-}
-
-/*
-** Return the address of the next instruction to be inserted.
-*/
-int sqlite3VdbeCurrentAddr(Vdbe *p){
- assert( p->magic==VDBE_MAGIC_INIT );
- return p->nOp;
-}
-
-/*
-** Verify that at least N opcode slots are available in p without
-** having to malloc for more space (except when compiled using
-** SQLITE_TEST_REALLOC_STRESS). This interface is used during testing
-** to verify that certain calls to sqlite3VdbeAddOpList() can never
-** fail due to a OOM fault and hence that the return value from
-** sqlite3VdbeAddOpList() will always be non-NULL.
-*/
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
-void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){
- assert( p->nOp + N <= p->pParse->nOpAlloc );
-}
-#endif
-
-/*
-** Verify that the VM passed as the only argument does not contain
-** an OP_ResultRow opcode. Fail an assert() if it does. This is used
-** by code in pragma.c to ensure that the implementation of certain
-** pragmas comports with the flags specified in the mkpragmatab.tcl
-** script.
-*/
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
-void sqlite3VdbeVerifyNoResultRow(Vdbe *p){
- int i;
- for(i=0; i<p->nOp; i++){
- assert( p->aOp[i].opcode!=OP_ResultRow );
- }
-}
-#endif
-
-/*
-** Generate code (a single OP_Abortable opcode) that will
-** verify that the VDBE program can safely call Abort in the current
-** context.
-*/
-#if defined(SQLITE_DEBUG)
-void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){
- if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable);
-}
-#endif
-
-/*
-** This function returns a pointer to the array of opcodes associated with
-** the Vdbe passed as the first argument. It is the callers responsibility
-** to arrange for the returned array to be eventually freed using the
-** vdbeFreeOpArray() function.
-**
-** Before returning, *pnOp is set to the number of entries in the returned
-** array. Also, *pnMaxArg is set to the larger of its current value and
-** the number of entries in the Vdbe.apArg[] array required to execute the
-** returned program.
-*/
-VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
- VdbeOp *aOp = p->aOp;
- assert( aOp && !p->db->mallocFailed );
-
- /* Check that sqlite3VdbeUsesBtree() was not called on this VM */
- assert( DbMaskAllZero(p->btreeMask) );
-
- resolveP2Values(p, pnMaxArg);
- *pnOp = p->nOp;
- p->aOp = 0;
- return aOp;
-}
-
-/*
-** Add a whole list of operations to the operation stack. Return a
-** pointer to the first operation inserted.
-**
-** Non-zero P2 arguments to jump instructions are automatically adjusted
-** so that the jump target is relative to the first operation inserted.
-*/
-VdbeOp *sqlite3VdbeAddOpList(
- Vdbe *p, /* Add opcodes to the prepared statement */
- int nOp, /* Number of opcodes to add */
- VdbeOpList const *aOp, /* The opcodes to be added */
- int iLineno /* Source-file line number of first opcode */
-){
- int i;
- VdbeOp *pOut, *pFirst;
- assert( nOp>0 );
- assert( p->magic==VDBE_MAGIC_INIT );
- if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
- return 0;
- }
- pFirst = pOut = &p->aOp[p->nOp];
- for(i=0; i<nOp; i++, aOp++, pOut++){
- pOut->opcode = aOp->opcode;
- pOut->p1 = aOp->p1;
- pOut->p2 = aOp->p2;
- assert( aOp->p2>=0 );
- if( (sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP)!=0 && aOp->p2>0 ){
- pOut->p2 += p->nOp;
- }
- pOut->p3 = aOp->p3;
- pOut->p4type = P4_NOTUSED;
- pOut->p4.p = 0;
- pOut->p5 = 0;
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- pOut->zComment = 0;
-#endif
-#ifdef SQLITE_VDBE_COVERAGE
- pOut->iSrcLine = iLineno+i;
-#else
- (void)iLineno;
-#endif
-#ifdef SQLITE_DEBUG
- if( p->db->flags & SQLITE_VdbeAddopTrace ){
- sqlite3VdbePrintOp(0, i+p->nOp, &p->aOp[i+p->nOp]);
- }
-#endif
- }
- p->nOp += nOp;
- return pFirst;
-}
-
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-/*
-** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus().
-*/
-void sqlite3VdbeScanStatus(
- Vdbe *p, /* VM to add scanstatus() to */
- int addrExplain, /* Address of OP_Explain (or 0) */
- int addrLoop, /* Address of loop counter */
- int addrVisit, /* Address of rows visited counter */
- LogEst nEst, /* Estimated number of output rows */
- const char *zName /* Name of table or index being scanned */
-){
- int nByte = (p->nScan+1) * sizeof(ScanStatus);
- ScanStatus *aNew;
- aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
- if( aNew ){
- ScanStatus *pNew = &aNew[p->nScan++];
- pNew->addrExplain = addrExplain;
- pNew->addrLoop = addrLoop;
- pNew->addrVisit = addrVisit;
- pNew->nEst = nEst;
- pNew->zName = sqlite3DbStrDup(p->db, zName);
- p->aScan = aNew;
- }
-}
-#endif
-
-
-/*
-** Change the value of the opcode, or P1, P2, P3, or P5 operands
-** for a specific instruction.
-*/
-void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){
- sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode;
-}
-void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
- sqlite3VdbeGetOp(p,addr)->p1 = val;
-}
-void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
- sqlite3VdbeGetOp(p,addr)->p2 = val;
-}
-void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
- sqlite3VdbeGetOp(p,addr)->p3 = val;
-}
-void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
- assert( p->nOp>0 || p->db->mallocFailed );
- if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
-}
-
-/*
-** Change the P2 operand of instruction addr so that it points to
-** the address of the next instruction to be coded.
-*/
-void sqlite3VdbeJumpHere(Vdbe *p, int addr){
- sqlite3VdbeChangeP2(p, addr, p->nOp);
-}
-
-
-/*
-** If the input FuncDef structure is ephemeral, then free it. If
-** the FuncDef is not ephermal, then do nothing.
-*/
-static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
- if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
- sqlite3DbFreeNN(db, pDef);
- }
-}
-
-static void vdbeFreeOpArray(sqlite3 *, Op *, int);
-
-/*
-** Delete a P4 value if necessary.
-*/
-static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
- if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
- sqlite3DbFreeNN(db, p);
-}
-static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
- freeEphemeralFunction(db, p->pFunc);
- sqlite3DbFreeNN(db, p);
-}
-static void freeP4(sqlite3 *db, int p4type, void *p4){
- assert( db );
- switch( p4type ){
- case P4_FUNCCTX: {
- freeP4FuncCtx(db, (sqlite3_context*)p4);
- break;
- }
- case P4_REAL:
- case P4_INT64:
- case P4_DYNAMIC:
- case P4_DYNBLOB:
- case P4_INTARRAY: {
- sqlite3DbFree(db, p4);
- break;
- }
- case P4_KEYINFO: {
- if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
- break;
- }
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
- case P4_EXPR: {
- sqlite3ExprDelete(db, (Expr*)p4);
- break;
- }
-#endif
- case P4_FUNCDEF: {
- freeEphemeralFunction(db, (FuncDef*)p4);
- break;
- }
- case P4_MEM: {
- if( db->pnBytesFreed==0 ){
- sqlite3ValueFree((sqlite3_value*)p4);
- }else{
- freeP4Mem(db, (Mem*)p4);
- }
- break;
- }
- case P4_VTAB : {
- if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
- break;
- }
- }
-}
-
-/*
-** Free the space allocated for aOp and any p4 values allocated for the
-** opcodes contained within. If aOp is not NULL it is assumed to contain
-** nOp entries.
-*/
-static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
- if( aOp ){
- Op *pOp;
- for(pOp=&aOp[nOp-1]; pOp>=aOp; pOp--){
- if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p);
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- sqlite3DbFree(db, pOp->zComment);
-#endif
- }
- sqlite3DbFreeNN(db, aOp);
- }
-}
-
-/*
-** Link the SubProgram object passed as the second argument into the linked
-** list at Vdbe.pSubProgram. This list is used to delete all sub-program
-** objects when the VM is no longer required.
-*/
-void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
- p->pNext = pVdbe->pProgram;
- pVdbe->pProgram = p;
-}
-
-/*
-** Change the opcode at addr into OP_Noop
-*/
-int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
- VdbeOp *pOp;
- if( p->db->mallocFailed ) return 0;
- assert( addr>=0 && addr<p->nOp );
- pOp = &p->aOp[addr];
- freeP4(p->db, pOp->p4type, pOp->p4.p);
- pOp->p4type = P4_NOTUSED;
- pOp->p4.z = 0;
- pOp->opcode = OP_Noop;
- return 1;
-}
-
-/*
-** If the last opcode is "op" and it is not a jump destination,
-** then remove it. Return true if and only if an opcode was removed.
-*/
-int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
- if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){
- return sqlite3VdbeChangeToNoop(p, p->nOp-1);
- }else{
- return 0;
- }
-}
-
-/*
-** Change the value of the P4 operand for a specific instruction.
-** This routine is useful when a large program is loaded from a
-** static array using sqlite3VdbeAddOpList but we want to make a
-** few minor changes to the program.
-**
-** If n>=0 then the P4 operand is dynamic, meaning that a copy of
-** the string is made into memory obtained from sqlite3_malloc().
-** A value of n==0 means copy bytes of zP4 up to and including the
-** first null byte. If n>0 then copy n+1 bytes of zP4.
-**
-** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
-** to a string or structure that is guaranteed to exist for the lifetime of
-** the Vdbe. In these cases we can just copy the pointer.
-**
-** If addr<0 then change P4 on the most recently inserted instruction.
-*/
-static void SQLITE_NOINLINE vdbeChangeP4Full(
- Vdbe *p,
- Op *pOp,
- const char *zP4,
- int n
-){
- if( pOp->p4type ){
- freeP4(p->db, pOp->p4type, pOp->p4.p);
- pOp->p4type = 0;
- pOp->p4.p = 0;
- }
- if( n<0 ){
- sqlite3VdbeChangeP4(p, (int)(pOp - p->aOp), zP4, n);
- }else{
- if( n==0 ) n = sqlite3Strlen30(zP4);
- pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
- pOp->p4type = P4_DYNAMIC;
- }
-}
-void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
- Op *pOp;
- sqlite3 *db;
- assert( p!=0 );
- db = p->db;
- assert( p->magic==VDBE_MAGIC_INIT );
- assert( p->aOp!=0 || db->mallocFailed );
- if( db->mallocFailed ){
- if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
- return;
- }
- assert( p->nOp>0 );
- assert( addr<p->nOp );
- if( addr<0 ){
- addr = p->nOp - 1;
- }
- pOp = &p->aOp[addr];
- if( n>=0 || pOp->p4type ){
- vdbeChangeP4Full(p, pOp, zP4, n);
- return;
- }
- if( n==P4_INT32 ){
- /* Note: this cast is safe, because the origin data point was an int
- ** that was cast to a (const char *). */
- pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
- pOp->p4type = P4_INT32;
- }else if( zP4!=0 ){
- assert( n<0 );
- pOp->p4.p = (void*)zP4;
- pOp->p4type = (signed char)n;
- if( n==P4_VTAB ) sqlite3VtabLock((VTable*)zP4);
- }
-}
-
-/*
-** Change the P4 operand of the most recently coded instruction
-** to the value defined by the arguments. This is a high-speed
-** version of sqlite3VdbeChangeP4().
-**
-** The P4 operand must not have been previously defined. And the new
-** P4 must not be P4_INT32. Use sqlite3VdbeChangeP4() in either of
-** those cases.
-*/
-void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){
- VdbeOp *pOp;
- assert( n!=P4_INT32 && n!=P4_VTAB );
- assert( n<=0 );
- if( p->db->mallocFailed ){
- freeP4(p->db, n, pP4);
- }else{
- assert( pP4!=0 );
- assert( p->nOp>0 );
- pOp = &p->aOp[p->nOp-1];
- assert( pOp->p4type==P4_NOTUSED );
- pOp->p4type = n;
- pOp->p4.p = pP4;
- }
-}
-
-/*
-** Set the P4 on the most recently added opcode to the KeyInfo for the
-** index given.
-*/
-void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
- Vdbe *v = pParse->pVdbe;
- KeyInfo *pKeyInfo;
- assert( v!=0 );
- assert( pIdx!=0 );
- pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pIdx);
- if( pKeyInfo ) sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
-}
-
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
-/*
-** Change the comment on the most recently coded instruction. Or
-** insert a No-op and add the comment to that new instruction. This
-** makes the code easier to read during debugging. None of this happens
-** in a production build.
-*/
-static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
- assert( p->nOp>0 || p->aOp==0 );
- assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
- if( p->nOp ){
- assert( p->aOp );
- sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
- p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap);
- }
-}
-void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
- va_list ap;
- if( p ){
- va_start(ap, zFormat);
- vdbeVComment(p, zFormat, ap);
- va_end(ap);
- }
-}
-void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
- va_list ap;
- if( p ){
- sqlite3VdbeAddOp0(p, OP_Noop);
- va_start(ap, zFormat);
- vdbeVComment(p, zFormat, ap);
- va_end(ap);
- }
-}
-#endif /* NDEBUG */
-
-#ifdef SQLITE_VDBE_COVERAGE
-/*
-** Set the value if the iSrcLine field for the previously coded instruction.
-*/
-void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
- sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine;
-}
-#endif /* SQLITE_VDBE_COVERAGE */
-
-/*
-** Return the opcode for a given address. If the address is -1, then
-** return the most recently inserted opcode.
-**
-** If a memory allocation error has occurred prior to the calling of this
-** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
-** is readable but not writable, though it is cast to a writable value.
-** The return of a dummy opcode allows the call to continue functioning
-** after an OOM fault without having to check to see if the return from
-** this routine is a valid pointer. But because the dummy.opcode is 0,
-** dummy will never be written to. This is verified by code inspection and
-** by running with Valgrind.
-*/
-VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
- /* C89 specifies that the constant "dummy" will be initialized to all
- ** zeros, which is correct. MSVC generates a warning, nevertheless. */
- static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
- assert( p->magic==VDBE_MAGIC_INIT );
- if( addr<0 ){
- addr = p->nOp - 1;
- }
- assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
- if( p->db->mallocFailed ){
- return (VdbeOp*)&dummy;
- }else{
- return &p->aOp[addr];
- }
-}
-
-#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
-/*
-** Return an integer value for one of the parameters to the opcode pOp
-** determined by character c.
-*/
-static int translateP(char c, const Op *pOp){
- if( c=='1' ) return pOp->p1;
- if( c=='2' ) return pOp->p2;
- if( c=='3' ) return pOp->p3;
- if( c=='4' ) return pOp->p4.i;
- return pOp->p5;
-}
-
-/*
-** Compute a string for the "comment" field of a VDBE opcode listing.
-**
-** The Synopsis: field in comments in the vdbe.c source file gets converted
-** to an extra string that is appended to the sqlite3OpcodeName(). In the
-** absence of other comments, this synopsis becomes the comment on the opcode.
-** Some translation occurs:
-**
-** "PX" -> "r[X]"
-** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1
-** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
-** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
-*/
-static int displayComment(
- const Op *pOp, /* The opcode to be commented */
- const char *zP4, /* Previously obtained value for P4 */
- char *zTemp, /* Write result here */
- int nTemp /* Space available in zTemp[] */
-){
- const char *zOpName;
- const char *zSynopsis;
- int nOpName;
- int ii, jj;
- char zAlt[50];
- zOpName = sqlite3OpcodeName(pOp->opcode);
- nOpName = sqlite3Strlen30(zOpName);
- if( zOpName[nOpName+1] ){
- int seenCom = 0;
- char c;
- zSynopsis = zOpName += nOpName + 1;
- if( strncmp(zSynopsis,"IF ",3)==0 ){
- if( pOp->p5 & SQLITE_STOREP2 ){
- sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3);
- }else{
- sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
- }
- zSynopsis = zAlt;
- }
- for(ii=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
- if( c=='P' ){
- c = zSynopsis[++ii];
- if( c=='4' ){
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
- }else if( c=='X' ){
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
- seenCom = 1;
- }else{
- int v1 = translateP(c, pOp);
- int v2;
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
- if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
- ii += 3;
- jj += sqlite3Strlen30(zTemp+jj);
- v2 = translateP(zSynopsis[ii], pOp);
- if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
- ii += 2;
- v2++;
- }
- if( v2>1 ){
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
- }
- }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
- ii += 4;
- }
- }
- jj += sqlite3Strlen30(zTemp+jj);
- }else{
- zTemp[jj++] = c;
- }
- }
- if( !seenCom && jj<nTemp-5 && pOp->zComment ){
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
- jj += sqlite3Strlen30(zTemp+jj);
- }
- if( jj<nTemp ) zTemp[jj] = 0;
- }else if( pOp->zComment ){
- sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment);
- jj = sqlite3Strlen30(zTemp);
- }else{
- zTemp[0] = 0;
- jj = 0;
- }
- return jj;
-}
-#endif /* SQLITE_DEBUG */
-
-#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
-/*
-** Translate the P4.pExpr value for an OP_CursorHint opcode into text
-** that can be displayed in the P4 column of EXPLAIN output.
-*/
-static void displayP4Expr(StrAccum *p, Expr *pExpr){
- const char *zOp = 0;
- switch( pExpr->op ){
- case TK_STRING:
- sqlite3_str_appendf(p, "%Q", pExpr->u.zToken);
- break;
- case TK_INTEGER:
- sqlite3_str_appendf(p, "%d", pExpr->u.iValue);
- break;
- case TK_NULL:
- sqlite3_str_appendf(p, "NULL");
- break;
- case TK_REGISTER: {
- sqlite3_str_appendf(p, "r[%d]", pExpr->iTable);
- break;
- }
- case TK_COLUMN: {
- if( pExpr->iColumn<0 ){
- sqlite3_str_appendf(p, "rowid");
- }else{
- sqlite3_str_appendf(p, "c%d", (int)pExpr->iColumn);
- }
- break;
- }
- case TK_LT: zOp = "LT"; break;
- case TK_LE: zOp = "LE"; break;
- case TK_GT: zOp = "GT"; break;
- case TK_GE: zOp = "GE"; break;
- case TK_NE: zOp = "NE"; break;
- case TK_EQ: zOp = "EQ"; break;
- case TK_IS: zOp = "IS"; break;
- case TK_ISNOT: zOp = "ISNOT"; break;
- case TK_AND: zOp = "AND"; break;
- case TK_OR: zOp = "OR"; break;
- case TK_PLUS: zOp = "ADD"; break;
- case TK_STAR: zOp = "MUL"; break;
- case TK_MINUS: zOp = "SUB"; break;
- case TK_REM: zOp = "REM"; break;
- case TK_BITAND: zOp = "BITAND"; break;
- case TK_BITOR: zOp = "BITOR"; break;
- case TK_SLASH: zOp = "DIV"; break;
- case TK_LSHIFT: zOp = "LSHIFT"; break;
- case TK_RSHIFT: zOp = "RSHIFT"; break;
- case TK_CONCAT: zOp = "CONCAT"; break;
- case TK_UMINUS: zOp = "MINUS"; break;
- case TK_UPLUS: zOp = "PLUS"; break;
- case TK_BITNOT: zOp = "BITNOT"; break;
- case TK_NOT: zOp = "NOT"; break;
- case TK_ISNULL: zOp = "ISNULL"; break;
- case TK_NOTNULL: zOp = "NOTNULL"; break;
-
- default:
- sqlite3_str_appendf(p, "%s", "expr");
- break;
- }
-
- if( zOp ){
- sqlite3_str_appendf(p, "%s(", zOp);
- displayP4Expr(p, pExpr->pLeft);
- if( pExpr->pRight ){
- sqlite3_str_append(p, ",", 1);
- displayP4Expr(p, pExpr->pRight);
- }
- sqlite3_str_append(p, ")", 1);
- }
-}
-#endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */
-
-
-#if VDBE_DISPLAY_P4
-/*
-** Compute a string that describes the P4 parameter for an opcode.
-** Use zTemp for any required temporary buffer space.
-*/
-static char *displayP4(Op *pOp, char *zTemp, int nTemp){
- char *zP4 = zTemp;
- StrAccum x;
- assert( nTemp>=20 );
- sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
- switch( pOp->p4type ){
- case P4_KEYINFO: {
- int j;
- KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
- assert( pKeyInfo->aSortOrder!=0 );
- sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField);
- for(j=0; j<pKeyInfo->nKeyField; j++){
- CollSeq *pColl = pKeyInfo->aColl[j];
- const char *zColl = pColl ? pColl->zName : "";
- if( strcmp(zColl, "BINARY")==0 ) zColl = "B";
- sqlite3_str_appendf(&x, ",%s%s",
- pKeyInfo->aSortOrder[j] ? "-" : "", zColl);
- }
- sqlite3_str_append(&x, ")", 1);
- break;
- }
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
- case P4_EXPR: {
- displayP4Expr(&x, pOp->p4.pExpr);
- break;
- }
-#endif
- case P4_COLLSEQ: {
- CollSeq *pColl = pOp->p4.pColl;
- sqlite3_str_appendf(&x, "(%.20s)", pColl->zName);
- break;
- }
- case P4_FUNCDEF: {
- FuncDef *pDef = pOp->p4.pFunc;
- sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
- break;
- }
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
- case P4_FUNCCTX: {
- FuncDef *pDef = pOp->p4.pCtx->pFunc;
- sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
- break;
- }
-#endif
- case P4_INT64: {
- sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64);
- break;
- }
- case P4_INT32: {
- sqlite3_str_appendf(&x, "%d", pOp->p4.i);
- break;
- }
- case P4_REAL: {
- sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal);
- break;
- }
- case P4_MEM: {
- Mem *pMem = pOp->p4.pMem;
- if( pMem->flags & MEM_Str ){
- zP4 = pMem->z;
- }else if( pMem->flags & MEM_Int ){
- sqlite3_str_appendf(&x, "%lld", pMem->u.i);
- }else if( pMem->flags & MEM_Real ){
- sqlite3_str_appendf(&x, "%.16g", pMem->u.r);
- }else if( pMem->flags & MEM_Null ){
- zP4 = "NULL";
- }else{
- assert( pMem->flags & MEM_Blob );
- zP4 = "(blob)";
- }
- break;
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- case P4_VTAB: {
- sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab;
- sqlite3_str_appendf(&x, "vtab:%p", pVtab);
- break;
- }
-#endif
- case P4_INTARRAY: {
- int i;
- int *ai = pOp->p4.ai;
- int n = ai[0]; /* The first element of an INTARRAY is always the
- ** count of the number of elements to follow */
- for(i=1; i<=n; i++){
- sqlite3_str_appendf(&x, ",%d", ai[i]);
- }
- zTemp[0] = '[';
- sqlite3_str_append(&x, "]", 1);
- break;
- }
- case P4_SUBPROGRAM: {
- sqlite3_str_appendf(&x, "program");
- break;
- }
- case P4_DYNBLOB:
- case P4_ADVANCE: {
- zTemp[0] = 0;
- break;
- }
- case P4_TABLE: {
- sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName);
- break;
- }
- default: {
- zP4 = pOp->p4.z;
- if( zP4==0 ){
- zP4 = zTemp;
- zTemp[0] = 0;
- }
- }
- }
- sqlite3StrAccumFinish(&x);
- assert( zP4!=0 );
- return zP4;
-}
-#endif /* VDBE_DISPLAY_P4 */
-
-/*
-** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
-**
-** The prepared statements need to know in advance the complete set of
-** attached databases that will be use. A mask of these databases
-** is maintained in p->btreeMask. The p->lockMask value is the subset of
-** p->btreeMask of databases that will require a lock.
-*/
-void sqlite3VdbeUsesBtree(Vdbe *p, int i){
- assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
- assert( i<(int)sizeof(p->btreeMask)*8 );
- DbMaskSet(p->btreeMask, i);
- if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
- DbMaskSet(p->lockMask, i);
- }
-}
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE)
-/*
-** If SQLite is compiled to support shared-cache mode and to be threadsafe,
-** this routine obtains the mutex associated with each BtShared structure
-** that may be accessed by the VM passed as an argument. In doing so it also
-** sets the BtShared.db member of each of the BtShared structures, ensuring
-** that the correct busy-handler callback is invoked if required.
-**
-** If SQLite is not threadsafe but does support shared-cache mode, then
-** sqlite3BtreeEnter() is invoked to set the BtShared.db variables
-** of all of BtShared structures accessible via the database handle
-** associated with the VM.
-**
-** If SQLite is not threadsafe and does not support shared-cache mode, this
-** function is a no-op.
-**
-** The p->btreeMask field is a bitmask of all btrees that the prepared
-** statement p will ever use. Let N be the number of bits in p->btreeMask
-** corresponding to btrees that use shared cache. Then the runtime of
-** this routine is N*N. But as N is rarely more than 1, this should not
-** be a problem.
-*/
-void sqlite3VdbeEnter(Vdbe *p){
- int i;
- sqlite3 *db;
- Db *aDb;
- int nDb;
- if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
- db = p->db;
- aDb = db->aDb;
- nDb = db->nDb;
- for(i=0; i<nDb; i++){
- if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
- sqlite3BtreeEnter(aDb[i].pBt);
- }
- }
-}
-#endif
-
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
-/*
-** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
-*/
-static SQLITE_NOINLINE void vdbeLeave(Vdbe *p){
- int i;
- sqlite3 *db;
- Db *aDb;
- int nDb;
- db = p->db;
- aDb = db->aDb;
- nDb = db->nDb;
- for(i=0; i<nDb; i++){
- if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
- sqlite3BtreeLeave(aDb[i].pBt);
- }
- }
-}
-void sqlite3VdbeLeave(Vdbe *p){
- if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
- vdbeLeave(p);
-}
-#endif
-
-#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
-/*
-** Print a single opcode. This routine is used for debugging only.
-*/
-void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
- char *zP4;
- char zPtr[50];
- char zCom[100];
- static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
- if( pOut==0 ) pOut = stdout;
- zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- displayComment(pOp, zP4, zCom, sizeof(zCom));
-#else
- zCom[0] = 0;
-#endif
- /* NB: The sqlite3OpcodeName() function is implemented by code created
- ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
- ** information from the vdbe.c source text */
- fprintf(pOut, zFormat1, pc,
- sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
- zCom
- );
- fflush(pOut);
-}
-#endif
-
-/*
-** Initialize an array of N Mem element.
-*/
-static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
- while( (N--)>0 ){
- p->db = db;
- p->flags = flags;
- p->szMalloc = 0;
-#ifdef SQLITE_DEBUG
- p->pScopyFrom = 0;
-#endif
- p++;
- }
-}
-
-/*
-** Release an array of N Mem elements
-*/
-static void releaseMemArray(Mem *p, int N){
- if( p && N ){
- Mem *pEnd = &p[N];
- sqlite3 *db = p->db;
- if( db->pnBytesFreed ){
- do{
- if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
- }while( (++p)<pEnd );
- return;
- }
- do{
- assert( (&p[1])==pEnd || p[0].db==p[1].db );
- assert( sqlite3VdbeCheckMemInvariants(p) );
-
- /* This block is really an inlined version of sqlite3VdbeMemRelease()
- ** that takes advantage of the fact that the memory cell value is
- ** being set to NULL after releasing any dynamic resources.
- **
- ** The justification for duplicating code is that according to
- ** callgrind, this causes a certain test case to hit the CPU 4.7
- ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
- ** sqlite3MemRelease() were called from here. With -O2, this jumps
- ** to 6.6 percent. The test case is inserting 1000 rows into a table
- ** with no indexes using a single prepared INSERT statement, bind()
- ** and reset(). Inserts are grouped into a transaction.
- */
- testcase( p->flags & MEM_Agg );
- testcase( p->flags & MEM_Dyn );
- testcase( p->flags & MEM_Frame );
- testcase( p->flags & MEM_RowSet );
- if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
- sqlite3VdbeMemRelease(p);
- }else if( p->szMalloc ){
- sqlite3DbFreeNN(db, p->zMalloc);
- p->szMalloc = 0;
- }
-
- p->flags = MEM_Undefined;
- }while( (++p)<pEnd );
- }
-}
-
-/*
-** Delete a VdbeFrame object and its contents. VdbeFrame objects are
-** allocated by the OP_Program opcode in sqlite3VdbeExec().
-*/
-void sqlite3VdbeFrameDelete(VdbeFrame *p){
- int i;
- Mem *aMem = VdbeFrameMem(p);
- VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
- for(i=0; i<p->nChildCsr; i++){
- sqlite3VdbeFreeCursor(p->v, apCsr[i]);
- }
- releaseMemArray(aMem, p->nChildMem);
- sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0);
- sqlite3DbFree(p->v->db, p);
-}
-
-#ifndef SQLITE_OMIT_EXPLAIN
-/*
-** Give a listing of the program in the virtual machine.
-**
-** The interface is the same as sqlite3VdbeExec(). But instead of
-** running the code, it invokes the callback once for each instruction.
-** This feature is used to implement "EXPLAIN".
-**
-** When p->explain==1, each instruction is listed. When
-** p->explain==2, only OP_Explain instructions are listed and these
-** are shown in a different format. p->explain==2 is used to implement
-** EXPLAIN QUERY PLAN.
-** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers
-** are also shown, so that the boundaries between the main program and
-** each trigger are clear.
-**
-** When p->explain==1, first the main program is listed, then each of
-** the trigger subprograms are listed one by one.
-*/
-int sqlite3VdbeList(
- Vdbe *p /* The VDBE */
-){
- int nRow; /* Stop when row count reaches this */
- int nSub = 0; /* Number of sub-vdbes seen so far */
- SubProgram **apSub = 0; /* Array of sub-vdbes */
- Mem *pSub = 0; /* Memory cell hold array of subprogs */
- sqlite3 *db = p->db; /* The database connection */
- int i; /* Loop counter */
- int rc = SQLITE_OK; /* Return code */
- Mem *pMem = &p->aMem[1]; /* First Mem of result set */
- int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
- Op *pOp = 0;
-
- assert( p->explain );
- assert( p->magic==VDBE_MAGIC_RUN );
- assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
-
- /* Even though this opcode does not use dynamic strings for
- ** the result, result columns may become dynamic if the user calls
- ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
- */
- releaseMemArray(pMem, 8);
- p->pResultSet = 0;
-
- if( p->rc==SQLITE_NOMEM ){
- /* This happens if a malloc() inside a call to sqlite3_column_text() or
- ** sqlite3_column_text16() failed. */
- sqlite3OomFault(db);
- return SQLITE_ERROR;
- }
-
- /* When the number of output rows reaches nRow, that means the
- ** listing has finished and sqlite3_step() should return SQLITE_DONE.
- ** nRow is the sum of the number of rows in the main program, plus
- ** the sum of the number of rows in all trigger subprograms encountered
- ** so far. The nRow value will increase as new trigger subprograms are
- ** encountered, but p->pc will eventually catch up to nRow.
- */
- nRow = p->nOp;
- if( bListSubprogs ){
- /* The first 8 memory cells are used for the result set. So we will
- ** commandeer the 9th cell to use as storage for an array of pointers
- ** to trigger subprograms. The VDBE is guaranteed to have at least 9
- ** cells. */
- assert( p->nMem>9 );
- pSub = &p->aMem[9];
- if( pSub->flags&MEM_Blob ){
- /* On the first call to sqlite3_step(), pSub will hold a NULL. It is
- ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
- nSub = pSub->n/sizeof(Vdbe*);
- apSub = (SubProgram **)pSub->z;
- }
- for(i=0; i<nSub; i++){
- nRow += apSub[i]->nOp;
- }
- }
-
- while(1){ /* Loop exits via break */
- i = p->pc++;
- if( i>=nRow ){
- p->rc = SQLITE_OK;
- rc = SQLITE_DONE;
- break;
- }
- if( i<p->nOp ){
- /* The output line number is small enough that we are still in the
- ** main program. */
- pOp = &p->aOp[i];
- }else{
- /* We are currently listing subprograms. Figure out which one and
- ** pick up the appropriate opcode. */
- int j;
- i -= p->nOp;
- for(j=0; i>=apSub[j]->nOp; j++){
- i -= apSub[j]->nOp;
- }
- pOp = &apSub[j]->aOp[i];
- }
-
- /* When an OP_Program opcode is encounter (the only opcode that has
- ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
- ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
- ** has not already been seen.
- */
- if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
- int nByte = (nSub+1)*sizeof(SubProgram*);
- int j;
- for(j=0; j<nSub; j++){
- if( apSub[j]==pOp->p4.pProgram ) break;
- }
- if( j==nSub ){
- p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
- if( p->rc!=SQLITE_OK ){
- rc = SQLITE_ERROR;
- break;
- }
- apSub = (SubProgram **)pSub->z;
- apSub[nSub++] = pOp->p4.pProgram;
- pSub->flags |= MEM_Blob;
- pSub->n = nSub*sizeof(SubProgram*);
- nRow += pOp->p4.pProgram->nOp;
- }
- }
- if( p->explain<2 ) break;
- if( pOp->opcode==OP_Explain ) break;
- if( pOp->opcode==OP_Init && p->pc>1 ) break;
- }
-
- if( rc==SQLITE_OK ){
- if( db->u1.isInterrupted ){
- p->rc = SQLITE_INTERRUPT;
- rc = SQLITE_ERROR;
- sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
- }else{
- char *zP4;
- if( p->explain==1 ){
- pMem->flags = MEM_Int;
- pMem->u.i = i; /* Program counter */
- pMem++;
-
- pMem->flags = MEM_Static|MEM_Str|MEM_Term;
- pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
- assert( pMem->z!=0 );
- pMem->n = sqlite3Strlen30(pMem->z);
- pMem->enc = SQLITE_UTF8;
- pMem++;
- }
-
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p1; /* P1 */
- pMem++;
-
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p2; /* P2 */
- pMem++;
-
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p3; /* P3 */
- pMem++;
-
- if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
- assert( p->db->mallocFailed );
- return SQLITE_ERROR;
- }
- pMem->flags = MEM_Str|MEM_Term;
- zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
- if( zP4!=pMem->z ){
- pMem->n = 0;
- sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
- }else{
- assert( pMem->z!=0 );
- pMem->n = sqlite3Strlen30(pMem->z);
- pMem->enc = SQLITE_UTF8;
- }
- pMem++;
-
- if( p->explain==1 ){
- if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
- assert( p->db->mallocFailed );
- return SQLITE_ERROR;
- }
- pMem->flags = MEM_Str|MEM_Term;
- pMem->n = 2;
- sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
- pMem->enc = SQLITE_UTF8;
- pMem++;
-
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
- assert( p->db->mallocFailed );
- return SQLITE_ERROR;
- }
- pMem->flags = MEM_Str|MEM_Term;
- pMem->n = displayComment(pOp, zP4, pMem->z, 500);
- pMem->enc = SQLITE_UTF8;
-#else
- pMem->flags = MEM_Null; /* Comment */
-#endif
- }
-
- p->nResColumn = 8 - 4*(p->explain-1);
- p->pResultSet = &p->aMem[1];
- p->rc = SQLITE_OK;
- rc = SQLITE_ROW;
- }
- }
- return rc;
-}
-#endif /* SQLITE_OMIT_EXPLAIN */
-
-#ifdef SQLITE_DEBUG
-/*
-** Print the SQL that was used to generate a VDBE program.
-*/
-void sqlite3VdbePrintSql(Vdbe *p){
- const char *z = 0;
- if( p->zSql ){
- z = p->zSql;
- }else if( p->nOp>=1 ){
- const VdbeOp *pOp = &p->aOp[0];
- if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
- z = pOp->p4.z;
- while( sqlite3Isspace(*z) ) z++;
- }
- }
- if( z ) printf("SQL: [%s]\n", z);
-}
-#endif
-
-#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
-/*
-** Print an IOTRACE message showing SQL content.
-*/
-void sqlite3VdbeIOTraceSql(Vdbe *p){
- int nOp = p->nOp;
- VdbeOp *pOp;
- if( sqlite3IoTrace==0 ) return;
- if( nOp<1 ) return;
- pOp = &p->aOp[0];
- if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
- int i, j;
- char z[1000];
- sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z);
- for(i=0; sqlite3Isspace(z[i]); i++){}
- for(j=0; z[i]; i++){
- if( sqlite3Isspace(z[i]) ){
- if( z[i-1]!=' ' ){
- z[j++] = ' ';
- }
- }else{
- z[j++] = z[i];
- }
- }
- z[j] = 0;
- sqlite3IoTrace("SQL %s\n", z);
- }
-}
-#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
-
-/* An instance of this object describes bulk memory available for use
-** by subcomponents of a prepared statement. Space is allocated out
-** of a ReusableSpace object by the allocSpace() routine below.
-*/
-struct ReusableSpace {
- u8 *pSpace; /* Available memory */
- int nFree; /* Bytes of available memory */
- int nNeeded; /* Total bytes that could not be allocated */
-};
-
-/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf
-** from the ReusableSpace object. Return a pointer to the allocated
-** memory on success. If insufficient memory is available in the
-** ReusableSpace object, increase the ReusableSpace.nNeeded
-** value by the amount needed and return NULL.
-**
-** If pBuf is not initially NULL, that means that the memory has already
-** been allocated by a prior call to this routine, so just return a copy
-** of pBuf and leave ReusableSpace unchanged.
-**
-** This allocator is employed to repurpose unused slots at the end of the
-** opcode array of prepared state for other memory needs of the prepared
-** statement.
-*/
-static void *allocSpace(
- struct ReusableSpace *p, /* Bulk memory available for allocation */
- void *pBuf, /* Pointer to a prior allocation */
- int nByte /* Bytes of memory needed */
-){
- assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) );
- if( pBuf==0 ){
- nByte = ROUND8(nByte);
- if( nByte <= p->nFree ){
- p->nFree -= nByte;
- pBuf = &p->pSpace[p->nFree];
- }else{
- p->nNeeded += nByte;
- }
- }
- assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
- return pBuf;
-}
-
-/*
-** Rewind the VDBE back to the beginning in preparation for
-** running it.
-*/
-void sqlite3VdbeRewind(Vdbe *p){
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
- int i;
-#endif
- assert( p!=0 );
- assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
-
- /* There should be at least one opcode.
- */
- assert( p->nOp>0 );
-
- /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
- p->magic = VDBE_MAGIC_RUN;
-
-#ifdef SQLITE_DEBUG
- for(i=0; i<p->nMem; i++){
- assert( p->aMem[i].db==p->db );
- }
-#endif
- p->pc = -1;
- p->rc = SQLITE_OK;
- p->errorAction = OE_Abort;
- p->nChange = 0;
- p->cacheCtr = 1;
- p->minWriteFileFormat = 255;
- p->iStatement = 0;
- p->nFkConstraint = 0;
-#ifdef VDBE_PROFILE
- for(i=0; i<p->nOp; i++){
- p->aOp[i].cnt = 0;
- p->aOp[i].cycles = 0;
- }
-#endif
-}
-
-/*
-** Prepare a virtual machine for execution for the first time after
-** creating the virtual machine. This involves things such
-** as allocating registers and initializing the program counter.
-** After the VDBE has be prepped, it can be executed by one or more
-** calls to sqlite3VdbeExec().
-**
-** This function may be called exactly once on each virtual machine.
-** After this routine is called the VM has been "packaged" and is ready
-** to run. After this routine is called, further calls to
-** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
-** the Vdbe from the Parse object that helped generate it so that the
-** the Vdbe becomes an independent entity and the Parse object can be
-** destroyed.
-**
-** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back
-** to its initial state after it has been run.
-*/
-void sqlite3VdbeMakeReady(
- Vdbe *p, /* The VDBE */
- Parse *pParse /* Parsing context */
-){
- sqlite3 *db; /* The database connection */
- int nVar; /* Number of parameters */
- int nMem; /* Number of VM memory registers */
- int nCursor; /* Number of cursors required */
- int nArg; /* Number of arguments in subprograms */
- int n; /* Loop counter */
- struct ReusableSpace x; /* Reusable bulk memory */
-
- assert( p!=0 );
- assert( p->nOp>0 );
- assert( pParse!=0 );
- assert( p->magic==VDBE_MAGIC_INIT );
- assert( pParse==p->pParse );
- db = p->db;
- assert( db->mallocFailed==0 );
- nVar = pParse->nVar;
- nMem = pParse->nMem;
- nCursor = pParse->nTab;
- nArg = pParse->nMaxArg;
-
- /* Each cursor uses a memory cell. The first cursor (cursor 0) can
- ** use aMem[0] which is not otherwise used by the VDBE program. Allocate
- ** space at the end of aMem[] for cursors 1 and greater.
- ** See also: allocateCursor().
- */
- nMem += nCursor;
- if( nCursor==0 && nMem>0 ) nMem++; /* Space for aMem[0] even if not used */
-
- /* Figure out how much reusable memory is available at the end of the
- ** opcode array. This extra memory will be reallocated for other elements
- ** of the prepared statement.
- */
- n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
- x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
- assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
- x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
- assert( x.nFree>=0 );
- assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
-
- resolveP2Values(p, &nArg);
- p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
- if( pParse->explain && nMem<10 ){
- nMem = 10;
- }
- p->expired = 0;
-
- /* Memory for registers, parameters, cursor, etc, is allocated in one or two
- ** passes. On the first pass, we try to reuse unused memory at the
- ** end of the opcode array. If we are unable to satisfy all memory
- ** requirements by reusing the opcode array tail, then the second
- ** pass will fill in the remainder using a fresh memory allocation.
- **
- ** This two-pass approach that reuses as much memory as possible from
- ** the leftover memory at the end of the opcode array. This can significantly
- ** reduce the amount of memory held by a prepared statement.
- */
- do {
- x.nNeeded = 0;
- p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
- p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
- p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
- p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
-#endif
- if( x.nNeeded==0 ) break;
- x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
- x.nFree = x.nNeeded;
- }while( !db->mallocFailed );
-
- p->pVList = pParse->pVList;
- pParse->pVList = 0;
- p->explain = pParse->explain;
- if( db->mallocFailed ){
- p->nVar = 0;
- p->nCursor = 0;
- p->nMem = 0;
- }else{
- p->nCursor = nCursor;
- p->nVar = (ynVar)nVar;
- initMemArray(p->aVar, nVar, db, MEM_Null);
- p->nMem = nMem;
- initMemArray(p->aMem, nMem, db, MEM_Undefined);
- memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*));
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- memset(p->anExec, 0, p->nOp*sizeof(i64));
-#endif
- }
- sqlite3VdbeRewind(p);
-}
-
-/*
-** Close a VDBE cursor and release all the resources that cursor
-** happens to hold.
-*/
-void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
- if( pCx==0 ){
- return;
- }
- assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
- switch( pCx->eCurType ){
- case CURTYPE_SORTER: {
- sqlite3VdbeSorterClose(p->db, pCx);
- break;
- }
- case CURTYPE_BTREE: {
- if( pCx->isEphemeral ){
- if( pCx->pBtx ) sqlite3BtreeClose(pCx->pBtx);
- /* The pCx->pCursor will be close automatically, if it exists, by
- ** the call above. */
- }else{
- assert( pCx->uc.pCursor!=0 );
- sqlite3BtreeCloseCursor(pCx->uc.pCursor);
- }
- break;
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- case CURTYPE_VTAB: {
- sqlite3_vtab_cursor *pVCur = pCx->uc.pVCur;
- const sqlite3_module *pModule = pVCur->pVtab->pModule;
- assert( pVCur->pVtab->nRef>0 );
- pVCur->pVtab->nRef--;
- pModule->xClose(pVCur);
- break;
- }
-#endif
- }
-}
-
-/*
-** Close all cursors in the current frame.
-*/
-static void closeCursorsInFrame(Vdbe *p){
- if( p->apCsr ){
- int i;
- for(i=0; i<p->nCursor; i++){
- VdbeCursor *pC = p->apCsr[i];
- if( pC ){
- sqlite3VdbeFreeCursor(p, pC);
- p->apCsr[i] = 0;
- }
- }
- }
-}
-
-/*
-** Copy the values stored in the VdbeFrame structure to its Vdbe. This
-** is used, for example, when a trigger sub-program is halted to restore
-** control to the main program.
-*/
-int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
- Vdbe *v = pFrame->v;
- closeCursorsInFrame(v);
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- v->anExec = pFrame->anExec;
-#endif
- v->aOp = pFrame->aOp;
- v->nOp = pFrame->nOp;
- v->aMem = pFrame->aMem;
- v->nMem = pFrame->nMem;
- v->apCsr = pFrame->apCsr;
- v->nCursor = pFrame->nCursor;
- v->db->lastRowid = pFrame->lastRowid;
- v->nChange = pFrame->nChange;
- v->db->nChange = pFrame->nDbChange;
- sqlite3VdbeDeleteAuxData(v->db, &v->pAuxData, -1, 0);
- v->pAuxData = pFrame->pAuxData;
- pFrame->pAuxData = 0;
- return pFrame->pc;
-}
-
-/*
-** Close all cursors.
-**
-** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
-** cell array. This is necessary as the memory cell array may contain
-** pointers to VdbeFrame objects, which may in turn contain pointers to
-** open cursors.
-*/
-static void closeAllCursors(Vdbe *p){
- if( p->pFrame ){
- VdbeFrame *pFrame;
- for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
- sqlite3VdbeFrameRestore(pFrame);
- p->pFrame = 0;
- p->nFrame = 0;
- }
- assert( p->nFrame==0 );
- closeCursorsInFrame(p);
- if( p->aMem ){
- releaseMemArray(p->aMem, p->nMem);
- }
- while( p->pDelFrame ){
- VdbeFrame *pDel = p->pDelFrame;
- p->pDelFrame = pDel->pParent;
- sqlite3VdbeFrameDelete(pDel);
- }
-
- /* Delete any auxdata allocations made by the VM */
- if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p->db, &p->pAuxData, -1, 0);
- assert( p->pAuxData==0 );
-}
-
-/*
-** Set the number of result columns that will be returned by this SQL
-** statement. This is now set at compile time, rather than during
-** execution of the vdbe program so that sqlite3_column_count() can
-** be called on an SQL statement before sqlite3_step().
-*/
-void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
- int n;
- sqlite3 *db = p->db;
-
- if( p->nResColumn ){
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
- sqlite3DbFree(db, p->aColName);
- }
- n = nResColumn*COLNAME_N;
- p->nResColumn = (u16)nResColumn;
- p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
- if( p->aColName==0 ) return;
- initMemArray(p->aColName, n, db, MEM_Null);
-}
-
-/*
-** Set the name of the idx'th column to be returned by the SQL statement.
-** zName must be a pointer to a nul terminated string.
-**
-** This call must be made after a call to sqlite3VdbeSetNumCols().
-**
-** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC
-** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed
-** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed.
-*/
-int sqlite3VdbeSetColName(
- Vdbe *p, /* Vdbe being configured */
- int idx, /* Index of column zName applies to */
- int var, /* One of the COLNAME_* constants */
- const char *zName, /* Pointer to buffer containing name */
- void (*xDel)(void*) /* Memory management strategy for zName */
-){
- int rc;
- Mem *pColName;
- assert( idx<p->nResColumn );
- assert( var<COLNAME_N );
- if( p->db->mallocFailed ){
- assert( !zName || xDel!=SQLITE_DYNAMIC );
- return SQLITE_NOMEM_BKPT;
- }
- assert( p->aColName!=0 );
- pColName = &(p->aColName[idx+var*p->nResColumn]);
- rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel);
- assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
- return rc;
-}
-
-/*
-** A read or write transaction may or may not be active on database handle
-** db. If a transaction is active, commit it. If there is a
-** write-transaction spanning more than one database file, this routine
-** takes care of the master journal trickery.
-*/
-static int vdbeCommit(sqlite3 *db, Vdbe *p){
- int i;
- int nTrans = 0; /* Number of databases with an active write-transaction
- ** that are candidates for a two-phase commit using a
- ** master-journal */
- int rc = SQLITE_OK;
- int needXcommit = 0;
-
-#ifdef SQLITE_OMIT_VIRTUALTABLE
- /* With this option, sqlite3VtabSync() is defined to be simply
- ** SQLITE_OK so p is not used.
- */
- UNUSED_PARAMETER(p);
-#endif
-
- /* Before doing anything else, call the xSync() callback for any
- ** virtual module tables written in this transaction. This has to
- ** be done before determining whether a master journal file is
- ** required, as an xSync() callback may add an attached database
- ** to the transaction.
- */
- rc = sqlite3VtabSync(db, p);
-
- /* This loop determines (a) if the commit hook should be invoked and
- ** (b) how many database files have open write transactions, not
- ** including the temp database. (b) is important because if more than
- ** one database file has an open write transaction, a master journal
- ** file is required for an atomic commit.
- */
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
- /* Whether or not a database might need a master journal depends upon
- ** its journal mode (among other things). This matrix determines which
- ** journal modes use a master journal and which do not */
- static const u8 aMJNeeded[] = {
- /* DELETE */ 1,
- /* PERSIST */ 1,
- /* OFF */ 0,
- /* TRUNCATE */ 1,
- /* MEMORY */ 0,
- /* WAL */ 0
- };
- Pager *pPager; /* Pager associated with pBt */
- needXcommit = 1;
- sqlite3BtreeEnter(pBt);
- pPager = sqlite3BtreePager(pBt);
- if( db->aDb[i].safety_level!=PAGER_SYNCHRONOUS_OFF
- && aMJNeeded[sqlite3PagerGetJournalMode(pPager)]
- && sqlite3PagerIsMemdb(pPager)==0
- ){
- assert( i!=1 );
- nTrans++;
- }
- rc = sqlite3PagerExclusiveLock(pPager);
- sqlite3BtreeLeave(pBt);
- }
- }
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* If there are any write-transactions at all, invoke the commit hook */
- if( needXcommit && db->xCommitCallback ){
- rc = db->xCommitCallback(db->pCommitArg);
- if( rc ){
- return SQLITE_CONSTRAINT_COMMITHOOK;
- }
- }
-
- /* The simple case - no more than one database file (not counting the
- ** TEMP database) has a transaction active. There is no need for the
- ** master-journal.
- **
- ** If the return value of sqlite3BtreeGetFilename() is a zero length
- ** string, it means the main database is :memory: or a temp file. In
- ** that case we do not support atomic multi-file commits, so use the
- ** simple case then too.
- */
- if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt))
- || nTrans<=1
- ){
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
- }
- }
-
- /* Do the commit only if all databases successfully complete phase 1.
- ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an
- ** IO error while deleting or truncating a journal file. It is unlikely,
- ** but could happen. In this case abandon processing and return the error.
- */
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- rc = sqlite3BtreeCommitPhaseTwo(pBt, 0);
- }
- }
- if( rc==SQLITE_OK ){
- sqlite3VtabCommit(db);
- }
- }
-
- /* The complex case - There is a multi-file write-transaction active.
- ** This requires a master journal file to ensure the transaction is
- ** committed atomically.
- */
-#ifndef SQLITE_OMIT_DISKIO
- else{
- sqlite3_vfs *pVfs = db->pVfs;
- char *zMaster = 0; /* File-name for the master journal */
- char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
- sqlite3_file *pMaster = 0;
- i64 offset = 0;
- int res;
- int retryCount = 0;
- int nMainFile;
-
- /* Select a master journal file name */
- nMainFile = sqlite3Strlen30(zMainFile);
- zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile);
- if( zMaster==0 ) return SQLITE_NOMEM_BKPT;
- do {
- u32 iRandom;
- if( retryCount ){
- if( retryCount>100 ){
- sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
- sqlite3OsDelete(pVfs, zMaster, 0);
- break;
- }else if( retryCount==1 ){
- sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster);
- }
- }
- retryCount++;
- sqlite3_randomness(sizeof(iRandom), &iRandom);
- sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X",
- (iRandom>>8)&0xffffff, iRandom&0xff);
- /* The antipenultimate character of the master journal name must
- ** be "9" to avoid name collisions when using 8+3 filenames. */
- assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' );
- sqlite3FileSuffix3(zMainFile, zMaster);
- rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
- }while( rc==SQLITE_OK && res );
- if( rc==SQLITE_OK ){
- /* Open the master journal. */
- rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
- SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
- SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
- );
- }
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, zMaster);
- return rc;
- }
-
- /* Write the name of each database file in the transaction into the new
- ** master journal file. If an error occurs at this point close
- ** and delete the master journal file. All the individual journal files
- ** still have 'null' as the master journal pointer, so they will roll
- ** back independently if a failure occurs.
- */
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
- char const *zFile = sqlite3BtreeGetJournalname(pBt);
- if( zFile==0 ){
- continue; /* Ignore TEMP and :memory: databases */
- }
- assert( zFile[0]!=0 );
- rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
- offset += sqlite3Strlen30(zFile)+1;
- if( rc!=SQLITE_OK ){
- sqlite3OsCloseFree(pMaster);
- sqlite3OsDelete(pVfs, zMaster, 0);
- sqlite3DbFree(db, zMaster);
- return rc;
- }
- }
- }
-
- /* Sync the master journal file. If the IOCAP_SEQUENTIAL device
- ** flag is set this is not required.
- */
- if( 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
- && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
- ){
- sqlite3OsCloseFree(pMaster);
- sqlite3OsDelete(pVfs, zMaster, 0);
- sqlite3DbFree(db, zMaster);
- return rc;
- }
-
- /* Sync all the db files involved in the transaction. The same call
- ** sets the master journal pointer in each individual journal. If
- ** an error occurs here, do not delete the master journal file.
- **
- ** If the error occurs during the first call to
- ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the
- ** master journal file will be orphaned. But we cannot delete it,
- ** in case the master journal file name was written into the journal
- ** file before the failure occurred.
- */
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
- }
- }
- sqlite3OsCloseFree(pMaster);
- assert( rc!=SQLITE_BUSY );
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, zMaster);
- return rc;
- }
-
- /* Delete the master journal file. This commits the transaction. After
- ** doing this the directory is synced again before any individual
- ** transaction files are deleted.
- */
- rc = sqlite3OsDelete(pVfs, zMaster, 1);
- sqlite3DbFree(db, zMaster);
- zMaster = 0;
- if( rc ){
- return rc;
- }
-
- /* All files and directories have already been synced, so the following
- ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and
- ** deleting or truncating journals. If something goes wrong while
- ** this is happening we don't really care. The integrity of the
- ** transaction is already guaranteed, but some stray 'cold' journals
- ** may be lying around. Returning an error code won't help matters.
- */
- disable_simulated_io_errors();
- sqlite3BeginBenignMalloc();
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- sqlite3BtreeCommitPhaseTwo(pBt, 1);
- }
- }
- sqlite3EndBenignMalloc();
- enable_simulated_io_errors();
-
- sqlite3VtabCommit(db);
- }
-#endif
-
- return rc;
-}
-
-/*
-** This routine checks that the sqlite3.nVdbeActive count variable
-** matches the number of vdbe's in the list sqlite3.pVdbe that are
-** currently active. An assertion fails if the two counts do not match.
-** This is an internal self-check only - it is not an essential processing
-** step.
-**
-** This is a no-op if NDEBUG is defined.
-*/
-#ifndef NDEBUG
-static void checkActiveVdbeCnt(sqlite3 *db){
- Vdbe *p;
- int cnt = 0;
- int nWrite = 0;
- int nRead = 0;
- p = db->pVdbe;
- while( p ){
- if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){
- cnt++;
- if( p->readOnly==0 ) nWrite++;
- if( p->bIsReader ) nRead++;
- }
- p = p->pNext;
- }
- assert( cnt==db->nVdbeActive );
- assert( nWrite==db->nVdbeWrite );
- assert( nRead==db->nVdbeRead );
-}
-#else
-#define checkActiveVdbeCnt(x)
-#endif
-
-/*
-** If the Vdbe passed as the first argument opened a statement-transaction,
-** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
-** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
-** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
-** statement transaction is committed.
-**
-** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
-** Otherwise SQLITE_OK.
-*/
-static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
- sqlite3 *const db = p->db;
- int rc = SQLITE_OK;
- int i;
- const int iSavepoint = p->iStatement-1;
-
- assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
- assert( db->nStatement>0 );
- assert( p->iStatement==(db->nStatement+db->nSavepoint) );
-
- for(i=0; i<db->nDb; i++){
- int rc2 = SQLITE_OK;
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- if( eOp==SAVEPOINT_ROLLBACK ){
- rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
- }
- if( rc2==SQLITE_OK ){
- rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
- }
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
- }
- db->nStatement--;
- p->iStatement = 0;
-
- if( rc==SQLITE_OK ){
- if( eOp==SAVEPOINT_ROLLBACK ){
- rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
- }
- }
-
- /* If the statement transaction is being rolled back, also restore the
- ** database handles deferred constraint counter to the value it had when
- ** the statement transaction was opened. */
- if( eOp==SAVEPOINT_ROLLBACK ){
- db->nDeferredCons = p->nStmtDefCons;
- db->nDeferredImmCons = p->nStmtDefImmCons;
- }
- return rc;
-}
-int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
- if( p->db->nStatement && p->iStatement ){
- return vdbeCloseStatement(p, eOp);
- }
- return SQLITE_OK;
-}
-
-
-/*
-** This function is called when a transaction opened by the database
-** handle associated with the VM passed as an argument is about to be
-** committed. If there are outstanding deferred foreign key constraint
-** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
-**
-** If there are outstanding FK violations and this function returns
-** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
-** and write an error message to it. Then return SQLITE_ERROR.
-*/
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
- sqlite3 *db = p->db;
- if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
- || (!deferred && p->nFkConstraint>0)
- ){
- p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
- p->errorAction = OE_Abort;
- sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-#endif
-
-/*
-** This routine is called the when a VDBE tries to halt. If the VDBE
-** has made changes and is in autocommit mode, then commit those
-** changes. If a rollback is needed, then do the rollback.
-**
-** This routine is the only way to move the state of a VM from
-** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to
-** call this on a VM that is in the SQLITE_MAGIC_HALT state.
-**
-** Return an error code. If the commit could not complete because of
-** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
-** means the close did not happen and needs to be repeated.
-*/
-int sqlite3VdbeHalt(Vdbe *p){
- int rc; /* Used to store transient return codes */
- sqlite3 *db = p->db;
-
- /* This function contains the logic that determines if a statement or
- ** transaction will be committed or rolled back as a result of the
- ** execution of this virtual machine.
- **
- ** If any of the following errors occur:
- **
- ** SQLITE_NOMEM
- ** SQLITE_IOERR
- ** SQLITE_FULL
- ** SQLITE_INTERRUPT
- **
- ** Then the internal cache might have been left in an inconsistent
- ** state. We need to rollback the statement transaction, if there is
- ** one, or the complete transaction if there is no statement transaction.
- */
-
- if( p->magic!=VDBE_MAGIC_RUN ){
- return SQLITE_OK;
- }
- if( db->mallocFailed ){
- p->rc = SQLITE_NOMEM_BKPT;
- }
- closeAllCursors(p);
- checkActiveVdbeCnt(db);
-
- /* No commit or rollback needed if the program never started or if the
- ** SQL statement does not read or write a database file. */
- if( p->pc>=0 && p->bIsReader ){
- int mrc; /* Primary error code from p->rc */
- int eStatementOp = 0;
- int isSpecialError; /* Set to true if a 'special' error */
-
- /* Lock all btrees used by the statement */
- sqlite3VdbeEnter(p);
-
- /* Check for one of the special errors */
- mrc = p->rc & 0xff;
- isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
- || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
- if( isSpecialError ){
- /* If the query was read-only and the error code is SQLITE_INTERRUPT,
- ** no rollback is necessary. Otherwise, at least a savepoint
- ** transaction must be rolled back to restore the database to a
- ** consistent state.
- **
- ** Even if the statement is read-only, it is important to perform
- ** a statement or transaction rollback operation. If the error
- ** occurred while writing to the journal, sub-journal or database
- ** file as part of an effort to free up cache space (see function
- ** pagerStress() in pager.c), the rollback is required to restore
- ** the pager to a consistent state.
- */
- if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
- if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){
- eStatementOp = SAVEPOINT_ROLLBACK;
- }else{
- /* We are forced to roll back the active transaction. Before doing
- ** so, abort any other statements this handle currently has active.
- */
- sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
- sqlite3CloseSavepoints(db);
- db->autoCommit = 1;
- p->nChange = 0;
- }
- }
- }
-
- /* Check for immediate foreign key violations. */
- if( p->rc==SQLITE_OK ){
- sqlite3VdbeCheckFk(p, 0);
- }
-
- /* If the auto-commit flag is set and this is the only active writer
- ** VM, then we do either a commit or rollback of the current transaction.
- **
- ** Note: This block also runs if one of the special errors handled
- ** above has occurred.
- */
- if( !sqlite3VtabInSync(db)
- && db->autoCommit
- && db->nVdbeWrite==(p->readOnly==0)
- ){
- if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
- rc = sqlite3VdbeCheckFk(p, 1);
- if( rc!=SQLITE_OK ){
- if( NEVER(p->readOnly) ){
- sqlite3VdbeLeave(p);
- return SQLITE_ERROR;
- }
- rc = SQLITE_CONSTRAINT_FOREIGNKEY;
- }else{
- /* The auto-commit flag is true, the vdbe program was successful
- ** or hit an 'OR FAIL' constraint and there are no deferred foreign
- ** key constraints to hold up the transaction. This means a commit
- ** is required. */
- rc = vdbeCommit(db, p);
- }
- if( rc==SQLITE_BUSY && p->readOnly ){
- sqlite3VdbeLeave(p);
- return SQLITE_BUSY;
- }else if( rc!=SQLITE_OK ){
- p->rc = rc;
- sqlite3RollbackAll(db, SQLITE_OK);
- p->nChange = 0;
- }else{
- db->nDeferredCons = 0;
- db->nDeferredImmCons = 0;
- db->flags &= ~SQLITE_DeferFKs;
- sqlite3CommitInternalChanges(db);
- }
- }else{
- sqlite3RollbackAll(db, SQLITE_OK);
- p->nChange = 0;
- }
- db->nStatement = 0;
- }else if( eStatementOp==0 ){
- if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
- eStatementOp = SAVEPOINT_RELEASE;
- }else if( p->errorAction==OE_Abort ){
- eStatementOp = SAVEPOINT_ROLLBACK;
- }else{
- sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
- sqlite3CloseSavepoints(db);
- db->autoCommit = 1;
- p->nChange = 0;
- }
- }
-
- /* If eStatementOp is non-zero, then a statement transaction needs to
- ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
- ** do so. If this operation returns an error, and the current statement
- ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
- ** current statement error code.
- */
- if( eStatementOp ){
- rc = sqlite3VdbeCloseStatement(p, eStatementOp);
- if( rc ){
- if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){
- p->rc = rc;
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
- }
- sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
- sqlite3CloseSavepoints(db);
- db->autoCommit = 1;
- p->nChange = 0;
- }
- }
-
- /* If this was an INSERT, UPDATE or DELETE and no statement transaction
- ** has been rolled back, update the database connection change-counter.
- */
- if( p->changeCntOn ){
- if( eStatementOp!=SAVEPOINT_ROLLBACK ){
- sqlite3VdbeSetChanges(db, p->nChange);
- }else{
- sqlite3VdbeSetChanges(db, 0);
- }
- p->nChange = 0;
- }
-
- /* Release the locks */
- sqlite3VdbeLeave(p);
- }
-
- /* We have successfully halted and closed the VM. Record this fact. */
- if( p->pc>=0 ){
- db->nVdbeActive--;
- if( !p->readOnly ) db->nVdbeWrite--;
- if( p->bIsReader ) db->nVdbeRead--;
- assert( db->nVdbeActive>=db->nVdbeRead );
- assert( db->nVdbeRead>=db->nVdbeWrite );
- assert( db->nVdbeWrite>=0 );
- }
- p->magic = VDBE_MAGIC_HALT;
- checkActiveVdbeCnt(db);
- if( db->mallocFailed ){
- p->rc = SQLITE_NOMEM_BKPT;
- }
-
- /* If the auto-commit flag is set to true, then any locks that were held
- ** by connection db have now been released. Call sqlite3ConnectionUnlocked()
- ** to invoke any required unlock-notify callbacks.
- */
- if( db->autoCommit ){
- sqlite3ConnectionUnlocked(db);
- }
-
- assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 );
- return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK);
-}
-
-
-/*
-** Each VDBE holds the result of the most recent sqlite3_step() call
-** in p->rc. This routine sets that result back to SQLITE_OK.
-*/
-void sqlite3VdbeResetStepResult(Vdbe *p){
- p->rc = SQLITE_OK;
-}
-
-/*
-** Copy the error code and error message belonging to the VDBE passed
-** as the first argument to its database handle (so that they will be
-** returned by calls to sqlite3_errcode() and sqlite3_errmsg()).
-**
-** This function does not clear the VDBE error code or message, just
-** copies them to the database handle.
-*/
-int sqlite3VdbeTransferError(Vdbe *p){
- sqlite3 *db = p->db;
- int rc = p->rc;
- if( p->zErrMsg ){
- db->bBenignMalloc++;
- sqlite3BeginBenignMalloc();
- if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db);
- sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
- sqlite3EndBenignMalloc();
- db->bBenignMalloc--;
- }else if( db->pErr ){
- sqlite3ValueSetNull(db->pErr);
- }
- db->errCode = rc;
- return rc;
-}
-
-#ifdef SQLITE_ENABLE_SQLLOG
-/*
-** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run,
-** invoke it.
-*/
-static void vdbeInvokeSqllog(Vdbe *v){
- if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){
- char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql);
- assert( v->db->init.busy==0 );
- if( zExpanded ){
- sqlite3GlobalConfig.xSqllog(
- sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1
- );
- sqlite3DbFree(v->db, zExpanded);
- }
- }
-}
-#else
-# define vdbeInvokeSqllog(x)
-#endif
-
-/*
-** Clean up a VDBE after execution but do not delete the VDBE just yet.
-** Write any error messages into *pzErrMsg. Return the result code.
-**
-** After this routine is run, the VDBE should be ready to be executed
-** again.
-**
-** To look at it another way, this routine resets the state of the
-** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
-** VDBE_MAGIC_INIT.
-*/
-int sqlite3VdbeReset(Vdbe *p){
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
- int i;
-#endif
-
- sqlite3 *db;
- db = p->db;
-
- /* If the VM did not run to completion or if it encountered an
- ** error, then it might not have been halted properly. So halt
- ** it now.
- */
- sqlite3VdbeHalt(p);
-
- /* If the VDBE has be run even partially, then transfer the error code
- ** and error message from the VDBE into the main database structure. But
- ** if the VDBE has just been set to run but has not actually executed any
- ** instructions yet, leave the main database error information unchanged.
- */
- if( p->pc>=0 ){
- vdbeInvokeSqllog(p);
- sqlite3VdbeTransferError(p);
- if( p->runOnlyOnce ) p->expired = 1;
- }else if( p->rc && p->expired ){
- /* The expired flag was set on the VDBE before the first call
- ** to sqlite3_step(). For consistency (since sqlite3_step() was
- ** called), set the database error in this case as well.
- */
- sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
- }
-
- /* Reset register contents and reclaim error message memory.
- */
-#ifdef SQLITE_DEBUG
- /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
- ** Vdbe.aMem[] arrays have already been cleaned up. */
- if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
- if( p->aMem ){
- for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
- }
-#endif
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
- p->pResultSet = 0;
-#ifdef SQLITE_DEBUG
- p->nWrite = 0;
-#endif
-
- /* Save profiling information from this VDBE run.
- */
-#ifdef VDBE_PROFILE
- {
- FILE *out = fopen("vdbe_profile.out", "a");
- if( out ){
- fprintf(out, "---- ");
- for(i=0; i<p->nOp; i++){
- fprintf(out, "%02x", p->aOp[i].opcode);
- }
- fprintf(out, "\n");
- if( p->zSql ){
- char c, pc = 0;
- fprintf(out, "-- ");
- for(i=0; (c = p->zSql[i])!=0; i++){
- if( pc=='\n' ) fprintf(out, "-- ");
- putc(c, out);
- pc = c;
- }
- if( pc!='\n' ) fprintf(out, "\n");
- }
- for(i=0; i<p->nOp; i++){
- char zHdr[100];
- sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ",
- p->aOp[i].cnt,
- p->aOp[i].cycles,
- p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
- );
- fprintf(out, "%s", zHdr);
- sqlite3VdbePrintOp(out, i, &p->aOp[i]);
- }
- fclose(out);
- }
- }
-#endif
- p->magic = VDBE_MAGIC_RESET;
- return p->rc & db->errMask;
-}
-
-/*
-** Clean up and delete a VDBE after execution. Return an integer which is
-** the result code. Write any error message text into *pzErrMsg.
-*/
-int sqlite3VdbeFinalize(Vdbe *p){
- int rc = SQLITE_OK;
- if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
- rc = sqlite3VdbeReset(p);
- assert( (rc & p->db->errMask)==rc );
- }
- sqlite3VdbeDelete(p);
- return rc;
-}
-
-/*
-** If parameter iOp is less than zero, then invoke the destructor for
-** all auxiliary data pointers currently cached by the VM passed as
-** the first argument.
-**
-** Or, if iOp is greater than or equal to zero, then the destructor is
-** only invoked for those auxiliary data pointers created by the user
-** function invoked by the OP_Function opcode at instruction iOp of
-** VM pVdbe, and only then if:
-**
-** * the associated function parameter is the 32nd or later (counting
-** from left to right), or
-**
-** * the corresponding bit in argument mask is clear (where the first
-** function parameter corresponds to bit 0 etc.).
-*/
-void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp, int mask){
- while( *pp ){
- AuxData *pAux = *pp;
- if( (iOp<0)
- || (pAux->iAuxOp==iOp
- && pAux->iAuxArg>=0
- && (pAux->iAuxArg>31 || !(mask & MASKBIT32(pAux->iAuxArg))))
- ){
- testcase( pAux->iAuxArg==31 );
- if( pAux->xDeleteAux ){
- pAux->xDeleteAux(pAux->pAux);
- }
- *pp = pAux->pNextAux;
- sqlite3DbFree(db, pAux);
- }else{
- pp= &pAux->pNextAux;
- }
- }
-}
-
-/*
-** Free all memory associated with the Vdbe passed as the second argument,
-** except for object itself, which is preserved.
-**
-** The difference between this function and sqlite3VdbeDelete() is that
-** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
-** the database connection and frees the object itself.
-*/
-void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
- SubProgram *pSub, *pNext;
- assert( p->db==0 || p->db==db );
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
- for(pSub=p->pProgram; pSub; pSub=pNext){
- pNext = pSub->pNext;
- vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
- sqlite3DbFree(db, pSub);
- }
- if( p->magic!=VDBE_MAGIC_INIT ){
- releaseMemArray(p->aVar, p->nVar);
- sqlite3DbFree(db, p->pVList);
- sqlite3DbFree(db, p->pFree);
- }
- vdbeFreeOpArray(db, p->aOp, p->nOp);
- sqlite3DbFree(db, p->aColName);
- sqlite3DbFree(db, p->zSql);
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- {
- int i;
- for(i=0; i<p->nScan; i++){
- sqlite3DbFree(db, p->aScan[i].zName);
- }
- sqlite3DbFree(db, p->aScan);
- }
-#endif
-}
-
-/*
-** Delete an entire VDBE.
-*/
-void sqlite3VdbeDelete(Vdbe *p){
- sqlite3 *db;
-
- assert( p!=0 );
- db = p->db;
- assert( sqlite3_mutex_held(db->mutex) );
- sqlite3VdbeClearObject(db, p);
- if( p->pPrev ){
- p->pPrev->pNext = p->pNext;
- }else{
- assert( db->pVdbe==p );
- db->pVdbe = p->pNext;
- }
- if( p->pNext ){
- p->pNext->pPrev = p->pPrev;
- }
- p->magic = VDBE_MAGIC_DEAD;
- p->db = 0;
- sqlite3DbFreeNN(db, p);
-}
-
-/*
-** The cursor "p" has a pending seek operation that has not yet been
-** carried out. Seek the cursor now. If an error occurs, return
-** the appropriate error code.
-*/
-static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
- int res, rc;
-#ifdef SQLITE_TEST
- extern int sqlite3_search_count;
-#endif
- assert( p->deferredMoveto );
- assert( p->isTable );
- assert( p->eCurType==CURTYPE_BTREE );
- rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res);
- if( rc ) return rc;
- if( res!=0 ) return SQLITE_CORRUPT_BKPT;
-#ifdef SQLITE_TEST
- sqlite3_search_count++;
-#endif
- p->deferredMoveto = 0;
- p->cacheStatus = CACHE_STALE;
- return SQLITE_OK;
-}
-
-/*
-** Something has moved cursor "p" out of place. Maybe the row it was
-** pointed to was deleted out from under it. Or maybe the btree was
-** rebalanced. Whatever the cause, try to restore "p" to the place it
-** is supposed to be pointing. If the row was deleted out from under the
-** cursor, set the cursor to point to a NULL row.
-*/
-static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){
- int isDifferentRow, rc;
- assert( p->eCurType==CURTYPE_BTREE );
- assert( p->uc.pCursor!=0 );
- assert( sqlite3BtreeCursorHasMoved(p->uc.pCursor) );
- rc = sqlite3BtreeCursorRestore(p->uc.pCursor, &isDifferentRow);
- p->cacheStatus = CACHE_STALE;
- if( isDifferentRow ) p->nullRow = 1;
- return rc;
-}
-
-/*
-** Check to ensure that the cursor is valid. Restore the cursor
-** if need be. Return any I/O error from the restore operation.
-*/
-int sqlite3VdbeCursorRestore(VdbeCursor *p){
- assert( p->eCurType==CURTYPE_BTREE );
- if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
- return handleMovedCursor(p);
- }
- return SQLITE_OK;
-}
-
-/*
-** Make sure the cursor p is ready to read or write the row to which it
-** was last positioned. Return an error code if an OOM fault or I/O error
-** prevents us from positioning the cursor to its correct position.
-**
-** If a MoveTo operation is pending on the given cursor, then do that
-** MoveTo now. If no move is pending, check to see if the row has been
-** deleted out from under the cursor and if it has, mark the row as
-** a NULL row.
-**
-** If the cursor is already pointing to the correct row and that row has
-** not been deleted out from under the cursor, then this routine is a no-op.
-*/
-int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
- VdbeCursor *p = *pp;
- assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
- if( p->deferredMoveto ){
- int iMap;
- if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
- *pp = p->pAltCursor;
- *piCol = iMap - 1;
- return SQLITE_OK;
- }
- return handleDeferredMoveto(p);
- }
- if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
- return handleMovedCursor(p);
- }
- return SQLITE_OK;
-}
-
-/*
-** The following functions:
-**
-** sqlite3VdbeSerialType()
-** sqlite3VdbeSerialTypeLen()
-** sqlite3VdbeSerialLen()
-** sqlite3VdbeSerialPut()
-** sqlite3VdbeSerialGet()
-**
-** encapsulate the code that serializes values for storage in SQLite
-** data and index records. Each serialized value consists of a
-** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
-** integer, stored as a varint.
-**
-** In an SQLite index record, the serial type is stored directly before
-** the blob of data that it corresponds to. In a table record, all serial
-** types are stored at the start of the record, and the blobs of data at
-** the end. Hence these functions allow the caller to handle the
-** serial-type and data blob separately.
-**
-** The following table describes the various storage classes for data:
-**
-** serial type bytes of data type
-** -------------- --------------- ---------------
-** 0 0 NULL
-** 1 1 signed integer
-** 2 2 signed integer
-** 3 3 signed integer
-** 4 4 signed integer
-** 5 6 signed integer
-** 6 8 signed integer
-** 7 8 IEEE float
-** 8 0 Integer constant 0
-** 9 0 Integer constant 1
-** 10,11 reserved for expansion
-** N>=12 and even (N-12)/2 BLOB
-** N>=13 and odd (N-13)/2 text
-**
-** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions
-** of SQLite will not understand those serial types.
-*/
-
-/*
-** Return the serial-type for the value stored in pMem.
-*/
-u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
- int flags = pMem->flags;
- u32 n;
-
- assert( pLen!=0 );
- if( flags&MEM_Null ){
- *pLen = 0;
- return 0;
- }
- if( flags&MEM_Int ){
- /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
-# define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
- i64 i = pMem->u.i;
- u64 u;
- if( i<0 ){
- u = ~i;
- }else{
- u = i;
- }
- if( u<=127 ){
- if( (i&1)==i && file_format>=4 ){
- *pLen = 0;
- return 8+(u32)u;
- }else{
- *pLen = 1;
- return 1;
- }
- }
- if( u<=32767 ){ *pLen = 2; return 2; }
- if( u<=8388607 ){ *pLen = 3; return 3; }
- if( u<=2147483647 ){ *pLen = 4; return 4; }
- if( u<=MAX_6BYTE ){ *pLen = 6; return 5; }
- *pLen = 8;
- return 6;
- }
- if( flags&MEM_Real ){
- *pLen = 8;
- return 7;
- }
- assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
- assert( pMem->n>=0 );
- n = (u32)pMem->n;
- if( flags & MEM_Zero ){
- n += pMem->u.nZero;
- }
- *pLen = n;
- return ((n*2) + 12 + ((flags&MEM_Str)!=0));
-}
-
-/*
-** The sizes for serial types less than 128
-*/
-static const u8 sqlite3SmallTypeSizes[] = {
- /* 0 1 2 3 4 5 6 7 8 9 */
-/* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0,
-/* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
-/* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
-/* 30 */ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
-/* 40 */ 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
-/* 50 */ 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
-/* 60 */ 24, 24, 25, 25, 26, 26, 27, 27, 28, 28,
-/* 70 */ 29, 29, 30, 30, 31, 31, 32, 32, 33, 33,
-/* 80 */ 34, 34, 35, 35, 36, 36, 37, 37, 38, 38,
-/* 90 */ 39, 39, 40, 40, 41, 41, 42, 42, 43, 43,
-/* 100 */ 44, 44, 45, 45, 46, 46, 47, 47, 48, 48,
-/* 110 */ 49, 49, 50, 50, 51, 51, 52, 52, 53, 53,
-/* 120 */ 54, 54, 55, 55, 56, 56, 57, 57
-};
-
-/*
-** Return the length of the data corresponding to the supplied serial-type.
-*/
-u32 sqlite3VdbeSerialTypeLen(u32 serial_type){
- if( serial_type>=128 ){
- return (serial_type-12)/2;
- }else{
- assert( serial_type<12
- || sqlite3SmallTypeSizes[serial_type]==(serial_type - 12)/2 );
- return sqlite3SmallTypeSizes[serial_type];
- }
-}
-u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){
- assert( serial_type<128 );
- return sqlite3SmallTypeSizes[serial_type];
-}
-
-/*
-** If we are on an architecture with mixed-endian floating
-** points (ex: ARM7) then swap the lower 4 bytes with the
-** upper 4 bytes. Return the result.
-**
-** For most architectures, this is a no-op.
-**
-** (later): It is reported to me that the mixed-endian problem
-** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems
-** that early versions of GCC stored the two words of a 64-bit
-** float in the wrong order. And that error has been propagated
-** ever since. The blame is not necessarily with GCC, though.
-** GCC might have just copying the problem from a prior compiler.
-** I am also told that newer versions of GCC that follow a different
-** ABI get the byte order right.
-**
-** Developers using SQLite on an ARM7 should compile and run their
-** application using -DSQLITE_DEBUG=1 at least once. With DEBUG
-** enabled, some asserts below will ensure that the byte order of
-** floating point values is correct.
-**
-** (2007-08-30) Frank van Vugt has studied this problem closely
-** and has send his findings to the SQLite developers. Frank
-** writes that some Linux kernels offer floating point hardware
-** emulation that uses only 32-bit mantissas instead of a full
-** 48-bits as required by the IEEE standard. (This is the
-** CONFIG_FPE_FASTFPE option.) On such systems, floating point
-** byte swapping becomes very complicated. To avoid problems,
-** the necessary byte swapping is carried out using a 64-bit integer
-** rather than a 64-bit float. Frank assures us that the code here
-** works for him. We, the developers, have no way to independently
-** verify this, but Frank seems to know what he is talking about
-** so we trust him.
-*/
-#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
-static u64 floatSwap(u64 in){
- union {
- u64 r;
- u32 i[2];
- } u;
- u32 t;
-
- u.r = in;
- t = u.i[0];
- u.i[0] = u.i[1];
- u.i[1] = t;
- return u.r;
-}
-# define swapMixedEndianFloat(X) X = floatSwap(X)
-#else
-# define swapMixedEndianFloat(X)
-#endif
-
-/*
-** Write the serialized data blob for the value stored in pMem into
-** buf. It is assumed that the caller has allocated sufficient space.
-** Return the number of bytes written.
-**
-** nBuf is the amount of space left in buf[]. The caller is responsible
-** for allocating enough space to buf[] to hold the entire field, exclusive
-** of the pMem->u.nZero bytes for a MEM_Zero value.
-**
-** Return the number of bytes actually written into buf[]. The number
-** of bytes in the zero-filled tail is included in the return value only
-** if those bytes were zeroed in buf[].
-*/
-u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
- u32 len;
-
- /* Integer and Real */
- if( serial_type<=7 && serial_type>0 ){
- u64 v;
- u32 i;
- if( serial_type==7 ){
- assert( sizeof(v)==sizeof(pMem->u.r) );
- memcpy(&v, &pMem->u.r, sizeof(v));
- swapMixedEndianFloat(v);
- }else{
- v = pMem->u.i;
- }
- len = i = sqlite3SmallTypeSizes[serial_type];
- assert( i>0 );
- do{
- buf[--i] = (u8)(v&0xFF);
- v >>= 8;
- }while( i );
- return len;
- }
-
- /* String or blob */
- if( serial_type>=12 ){
- assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
- == (int)sqlite3VdbeSerialTypeLen(serial_type) );
- len = pMem->n;
- if( len>0 ) memcpy(buf, pMem->z, len);
- return len;
- }
-
- /* NULL or constants 0 or 1 */
- return 0;
-}
-
-/* Input "x" is a sequence of unsigned characters that represent a
-** big-endian integer. Return the equivalent native integer
-*/
-#define ONE_BYTE_INT(x) ((i8)(x)[0])
-#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
-#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
-#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
-#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
-
-/*
-** Deserialize the data blob pointed to by buf as serial type serial_type
-** and store the result in pMem. Return the number of bytes read.
-**
-** This function is implemented as two separate routines for performance.
-** The few cases that require local variables are broken out into a separate
-** routine so that in most cases the overhead of moving the stack pointer
-** is avoided.
-*/
-static u32 SQLITE_NOINLINE serialGet(
- const unsigned char *buf, /* Buffer to deserialize from */
- u32 serial_type, /* Serial type to deserialize */
- Mem *pMem /* Memory cell to write value into */
-){
- u64 x = FOUR_BYTE_UINT(buf);
- u32 y = FOUR_BYTE_UINT(buf+4);
- x = (x<<32) + y;
- if( serial_type==6 ){
- /* EVIDENCE-OF: R-29851-52272 Value is a big-endian 64-bit
- ** twos-complement integer. */
- pMem->u.i = *(i64*)&x;
- pMem->flags = MEM_Int;
- testcase( pMem->u.i<0 );
- }else{
- /* EVIDENCE-OF: R-57343-49114 Value is a big-endian IEEE 754-2008 64-bit
- ** floating point number. */
-#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
- /* Verify that integers and floating point values use the same
- ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
- ** defined that 64-bit floating point values really are mixed
- ** endian.
- */
- static const u64 t1 = ((u64)0x3ff00000)<<32;
- static const double r1 = 1.0;
- u64 t2 = t1;
- swapMixedEndianFloat(t2);
- assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
-#endif
- assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
- swapMixedEndianFloat(x);
- memcpy(&pMem->u.r, &x, sizeof(x));
- pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real;
- }
- return 8;
-}
-u32 sqlite3VdbeSerialGet(
- const unsigned char *buf, /* Buffer to deserialize from */
- u32 serial_type, /* Serial type to deserialize */
- Mem *pMem /* Memory cell to write value into */
-){
- switch( serial_type ){
- case 10: { /* Internal use only: NULL with virtual table
- ** UPDATE no-change flag set */
- pMem->flags = MEM_Null|MEM_Zero;
- pMem->n = 0;
- pMem->u.nZero = 0;
- break;
- }
- case 11: /* Reserved for future use */
- case 0: { /* Null */
- /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
- pMem->flags = MEM_Null;
- break;
- }
- case 1: {
- /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement
- ** integer. */
- pMem->u.i = ONE_BYTE_INT(buf);
- pMem->flags = MEM_Int;
- testcase( pMem->u.i<0 );
- return 1;
- }
- case 2: { /* 2-byte signed integer */
- /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit
- ** twos-complement integer. */
- pMem->u.i = TWO_BYTE_INT(buf);
- pMem->flags = MEM_Int;
- testcase( pMem->u.i<0 );
- return 2;
- }
- case 3: { /* 3-byte signed integer */
- /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit
- ** twos-complement integer. */
- pMem->u.i = THREE_BYTE_INT(buf);
- pMem->flags = MEM_Int;
- testcase( pMem->u.i<0 );
- return 3;
- }
- case 4: { /* 4-byte signed integer */
- /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit
- ** twos-complement integer. */
- pMem->u.i = FOUR_BYTE_INT(buf);
-#ifdef __HP_cc
- /* Work around a sign-extension bug in the HP compiler for HP/UX */
- if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL;
-#endif
- pMem->flags = MEM_Int;
- testcase( pMem->u.i<0 );
- return 4;
- }
- case 5: { /* 6-byte signed integer */
- /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit
- ** twos-complement integer. */
- pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
- pMem->flags = MEM_Int;
- testcase( pMem->u.i<0 );
- return 6;
- }
- case 6: /* 8-byte signed integer */
- case 7: { /* IEEE floating point */
- /* These use local variables, so do them in a separate routine
- ** to avoid having to move the frame pointer in the common case */
- return serialGet(buf,serial_type,pMem);
- }
- case 8: /* Integer 0 */
- case 9: { /* Integer 1 */
- /* EVIDENCE-OF: R-12976-22893 Value is the integer 0. */
- /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */
- pMem->u.i = serial_type-8;
- pMem->flags = MEM_Int;
- return 0;
- }
- default: {
- /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in
- ** length.
- ** EVIDENCE-OF: R-28401-00140 Value is a string in the text encoding and
- ** (N-13)/2 bytes in length. */
- static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
- pMem->z = (char *)buf;
- pMem->n = (serial_type-12)/2;
- pMem->flags = aFlag[serial_type&1];
- return pMem->n;
- }
- }
- return 0;
-}
-/*
-** This routine is used to allocate sufficient space for an UnpackedRecord
-** structure large enough to be used with sqlite3VdbeRecordUnpack() if
-** the first argument is a pointer to KeyInfo structure pKeyInfo.
-**
-** The space is either allocated using sqlite3DbMallocRaw() or from within
-** the unaligned buffer passed via the second and third arguments (presumably
-** stack space). If the former, then *ppFree is set to a pointer that should
-** be eventually freed by the caller using sqlite3DbFree(). Or, if the
-** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
-** before returning.
-**
-** If an OOM error occurs, NULL is returned.
-*/
-UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
- KeyInfo *pKeyInfo /* Description of the record */
-){
- UnpackedRecord *p; /* Unpacked record to return */
- int nByte; /* Number of bytes required for *p */
- nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
- p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
- if( !p ) return 0;
- p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
- assert( pKeyInfo->aSortOrder!=0 );
- p->pKeyInfo = pKeyInfo;
- p->nField = pKeyInfo->nKeyField + 1;
- return p;
-}
-
-/*
-** Given the nKey-byte encoding of a record in pKey[], populate the
-** UnpackedRecord structure indicated by the fourth argument with the
-** contents of the decoded record.
-*/
-void sqlite3VdbeRecordUnpack(
- KeyInfo *pKeyInfo, /* Information about the record format */
- int nKey, /* Size of the binary record */
- const void *pKey, /* The binary record */
- UnpackedRecord *p /* Populate this structure before returning. */
-){
- const unsigned char *aKey = (const unsigned char *)pKey;
- int d;
- u32 idx; /* Offset in aKey[] to read from */
- u16 u; /* Unsigned loop counter */
- u32 szHdr;
- Mem *pMem = p->aMem;
-
- p->default_rc = 0;
- assert( EIGHT_BYTE_ALIGNMENT(pMem) );
- idx = getVarint32(aKey, szHdr);
- d = szHdr;
- u = 0;
- while( idx<szHdr && d<=nKey ){
- u32 serial_type;
-
- idx += getVarint32(&aKey[idx], serial_type);
- pMem->enc = pKeyInfo->enc;
- pMem->db = pKeyInfo->db;
- /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
- pMem->szMalloc = 0;
- pMem->z = 0;
- d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
- pMem++;
- if( (++u)>=p->nField ) break;
- }
- assert( u<=pKeyInfo->nKeyField + 1 );
- p->nField = u;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** This function compares two index or table record keys in the same way
-** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
-** this function deserializes and compares values using the
-** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
-** in assert() statements to ensure that the optimized code in
-** sqlite3VdbeRecordCompare() returns results with these two primitives.
-**
-** Return true if the result of comparison is equivalent to desiredResult.
-** Return false if there is a disagreement.
-*/
-static int vdbeRecordCompareDebug(
- int nKey1, const void *pKey1, /* Left key */
- const UnpackedRecord *pPKey2, /* Right key */
- int desiredResult /* Correct answer */
-){
- u32 d1; /* Offset into aKey[] of next data element */
- u32 idx1; /* Offset into aKey[] of next header element */
- u32 szHdr1; /* Number of bytes in header */
- int i = 0;
- int rc = 0;
- const unsigned char *aKey1 = (const unsigned char *)pKey1;
- KeyInfo *pKeyInfo;
- Mem mem1;
-
- pKeyInfo = pPKey2->pKeyInfo;
- if( pKeyInfo->db==0 ) return 1;
- mem1.enc = pKeyInfo->enc;
- mem1.db = pKeyInfo->db;
- /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
- VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
-
- /* Compilers may complain that mem1.u.i is potentially uninitialized.
- ** We could initialize it, as shown here, to silence those complaints.
- ** But in fact, mem1.u.i will never actually be used uninitialized, and doing
- ** the unnecessary initialization has a measurable negative performance
- ** impact, since this routine is a very high runner. And so, we choose
- ** to ignore the compiler warnings and leave this variable uninitialized.
- */
- /* mem1.u.i = 0; // not needed, here to silence compiler warning */
-
- idx1 = getVarint32(aKey1, szHdr1);
- if( szHdr1>98307 ) return SQLITE_CORRUPT;
- d1 = szHdr1;
- assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB );
- assert( pKeyInfo->aSortOrder!=0 );
- assert( pKeyInfo->nKeyField>0 );
- assert( idx1<=szHdr1 || CORRUPT_DB );
- do{
- u32 serial_type1;
-
- /* Read the serial types for the next element in each key. */
- idx1 += getVarint32( aKey1+idx1, serial_type1 );
-
- /* Verify that there is enough key space remaining to avoid
- ** a buffer overread. The "d1+serial_type1+2" subexpression will
- ** always be greater than or equal to the amount of required key space.
- ** Use that approximation to avoid the more expensive call to
- ** sqlite3VdbeSerialTypeLen() in the common case.
- */
- if( d1+serial_type1+2>(u32)nKey1
- && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1
- ){
- break;
- }
-
- /* Extract the values to be compared.
- */
- d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
-
- /* Do the comparison
- */
- rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
- if( rc!=0 ){
- assert( mem1.szMalloc==0 ); /* See comment below */
- if( pKeyInfo->aSortOrder[i] ){
- rc = -rc; /* Invert the result for DESC sort order. */
- }
- goto debugCompareEnd;
- }
- i++;
- }while( idx1<szHdr1 && i<pPKey2->nField );
-
- /* No memory allocation is ever used on mem1. Prove this using
- ** the following assert(). If the assert() fails, it indicates a
- ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
- */
- assert( mem1.szMalloc==0 );
-
- /* rc==0 here means that one of the keys ran out of fields and
- ** all the fields up to that point were equal. Return the default_rc
- ** value. */
- rc = pPKey2->default_rc;
-
-debugCompareEnd:
- if( desiredResult==0 && rc==0 ) return 1;
- if( desiredResult<0 && rc<0 ) return 1;
- if( desiredResult>0 && rc>0 ) return 1;
- if( CORRUPT_DB ) return 1;
- if( pKeyInfo->db->mallocFailed ) return 1;
- return 0;
-}
-#endif
-
-#ifdef SQLITE_DEBUG
-/*
-** Count the number of fields (a.k.a. columns) in the record given by
-** pKey,nKey. The verify that this count is less than or equal to the
-** limit given by pKeyInfo->nAllField.
-**
-** If this constraint is not satisfied, it means that the high-speed
-** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will
-** not work correctly. If this assert() ever fires, it probably means
-** that the KeyInfo.nKeyField or KeyInfo.nAllField values were computed
-** incorrectly.
-*/
-static void vdbeAssertFieldCountWithinLimits(
- int nKey, const void *pKey, /* The record to verify */
- const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */
-){
- int nField = 0;
- u32 szHdr;
- u32 idx;
- u32 notUsed;
- const unsigned char *aKey = (const unsigned char*)pKey;
-
- if( CORRUPT_DB ) return;
- idx = getVarint32(aKey, szHdr);
- assert( nKey>=0 );
- assert( szHdr<=(u32)nKey );
- while( idx<szHdr ){
- idx += getVarint32(aKey+idx, notUsed);
- nField++;
- }
- assert( nField <= pKeyInfo->nAllField );
-}
-#else
-# define vdbeAssertFieldCountWithinLimits(A,B,C)
-#endif
-
-/*
-** Both *pMem1 and *pMem2 contain string values. Compare the two values
-** using the collation sequence pColl. As usual, return a negative , zero
-** or positive value if *pMem1 is less than, equal to or greater than
-** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
-*/
-static int vdbeCompareMemString(
- const Mem *pMem1,
- const Mem *pMem2,
- const CollSeq *pColl,
- u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */
-){
- if( pMem1->enc==pColl->enc ){
- /* The strings are already in the correct encoding. Call the
- ** comparison function directly */
- return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
- }else{
- int rc;
- const void *v1, *v2;
- Mem c1;
- Mem c2;
- sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
- sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null);
- sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
- sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
- v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
- v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
- if( (v1==0 || v2==0) ){
- if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
- rc = 0;
- }else{
- rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2);
- }
- sqlite3VdbeMemRelease(&c1);
- sqlite3VdbeMemRelease(&c2);
- return rc;
- }
-}
-
-/*
-** The input pBlob is guaranteed to be a Blob that is not marked
-** with MEM_Zero. Return true if it could be a zero-blob.
-*/
-static int isAllZero(const char *z, int n){
- int i;
- for(i=0; i<n; i++){
- if( z[i] ) return 0;
- }
- return 1;
-}
-
-/*
-** Compare two blobs. Return negative, zero, or positive if the first
-** is less than, equal to, or greater than the second, respectively.
-** If one blob is a prefix of the other, then the shorter is the lessor.
-*/
-static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
- int c;
- int n1 = pB1->n;
- int n2 = pB2->n;
-
- /* It is possible to have a Blob value that has some non-zero content
- ** followed by zero content. But that only comes up for Blobs formed
- ** by the OP_MakeRecord opcode, and such Blobs never get passed into
- ** sqlite3MemCompare(). */
- assert( (pB1->flags & MEM_Zero)==0 || n1==0 );
- assert( (pB2->flags & MEM_Zero)==0 || n2==0 );
-
- if( (pB1->flags|pB2->flags) & MEM_Zero ){
- if( pB1->flags & pB2->flags & MEM_Zero ){
- return pB1->u.nZero - pB2->u.nZero;
- }else if( pB1->flags & MEM_Zero ){
- if( !isAllZero(pB2->z, pB2->n) ) return -1;
- return pB1->u.nZero - n2;
- }else{
- if( !isAllZero(pB1->z, pB1->n) ) return +1;
- return n1 - pB2->u.nZero;
- }
- }
- c = memcmp(pB1->z, pB2->z, n1>n2 ? n2 : n1);
- if( c ) return c;
- return n1 - n2;
-}
-
-/*
-** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
-** number. Return negative, zero, or positive if the first (i64) is less than,
-** equal to, or greater than the second (double).
-*/
-static int sqlite3IntFloatCompare(i64 i, double r){
- if( sizeof(LONGDOUBLE_TYPE)>8 ){
- LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
- if( x<r ) return -1;
- if( x>r ) return +1;
- return 0;
- }else{
- i64 y;
- double s;
- if( r<-9223372036854775808.0 ) return +1;
- if( r>=9223372036854775808.0 ) return -1;
- y = (i64)r;
- if( i<y ) return -1;
- if( i>y ) return +1;
- s = (double)i;
- if( s<r ) return -1;
- if( s>r ) return +1;
- return 0;
- }
-}
-
-/*
-** Compare the values contained by the two memory cells, returning
-** negative, zero or positive if pMem1 is less than, equal to, or greater
-** than pMem2. Sorting order is NULL's first, followed by numbers (integers
-** and reals) sorted numerically, followed by text ordered by the collating
-** sequence pColl and finally blob's ordered by memcmp().
-**
-** Two NULL values are considered equal by this function.
-*/
-int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
- int f1, f2;
- int combined_flags;
-
- f1 = pMem1->flags;
- f2 = pMem2->flags;
- combined_flags = f1|f2;
- assert( (combined_flags & MEM_RowSet)==0 );
-
- /* If one value is NULL, it is less than the other. If both values
- ** are NULL, return 0.
- */
- if( combined_flags&MEM_Null ){
- return (f2&MEM_Null) - (f1&MEM_Null);
- }
-
- /* At least one of the two values is a number
- */
- if( combined_flags&(MEM_Int|MEM_Real) ){
- if( (f1 & f2 & MEM_Int)!=0 ){
- if( pMem1->u.i < pMem2->u.i ) return -1;
- if( pMem1->u.i > pMem2->u.i ) return +1;
- return 0;
- }
- if( (f1 & f2 & MEM_Real)!=0 ){
- if( pMem1->u.r < pMem2->u.r ) return -1;
- if( pMem1->u.r > pMem2->u.r ) return +1;
- return 0;
- }
- if( (f1&MEM_Int)!=0 ){
- if( (f2&MEM_Real)!=0 ){
- return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r);
- }else{
- return -1;
- }
- }
- if( (f1&MEM_Real)!=0 ){
- if( (f2&MEM_Int)!=0 ){
- return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r);
- }else{
- return -1;
- }
- }
- return +1;
- }
-
- /* If one value is a string and the other is a blob, the string is less.
- ** If both are strings, compare using the collating functions.
- */
- if( combined_flags&MEM_Str ){
- if( (f1 & MEM_Str)==0 ){
- return 1;
- }
- if( (f2 & MEM_Str)==0 ){
- return -1;
- }
-
- assert( pMem1->enc==pMem2->enc || pMem1->db->mallocFailed );
- assert( pMem1->enc==SQLITE_UTF8 ||
- pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
-
- /* The collation sequence must be defined at this point, even if
- ** the user deletes the collation sequence after the vdbe program is
- ** compiled (this was not always the case).
- */
- assert( !pColl || pColl->xCmp );
-
- if( pColl ){
- return vdbeCompareMemString(pMem1, pMem2, pColl, 0);
- }
- /* If a NULL pointer was passed as the collate function, fall through
- ** to the blob case and use memcmp(). */
- }
-
- /* Both values must be blobs. Compare using memcmp(). */
- return sqlite3BlobCompare(pMem1, pMem2);
-}
-
-
-/*
-** The first argument passed to this function is a serial-type that
-** corresponds to an integer - all values between 1 and 9 inclusive
-** except 7. The second points to a buffer containing an integer value
-** serialized according to serial_type. This function deserializes
-** and returns the value.
-*/
-static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
- u32 y;
- assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
- switch( serial_type ){
- case 0:
- case 1:
- testcase( aKey[0]&0x80 );
- return ONE_BYTE_INT(aKey);
- case 2:
- testcase( aKey[0]&0x80 );
- return TWO_BYTE_INT(aKey);
- case 3:
- testcase( aKey[0]&0x80 );
- return THREE_BYTE_INT(aKey);
- case 4: {
- testcase( aKey[0]&0x80 );
- y = FOUR_BYTE_UINT(aKey);
- return (i64)*(int*)&y;
- }
- case 5: {
- testcase( aKey[0]&0x80 );
- return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
- }
- case 6: {
- u64 x = FOUR_BYTE_UINT(aKey);
- testcase( aKey[0]&0x80 );
- x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
- return (i64)*(i64*)&x;
- }
- }
-
- return (serial_type - 8);
-}
-
-/*
-** This function compares the two table rows or index records
-** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
-** or positive integer if key1 is less than, equal to or
-** greater than key2. The {nKey1, pKey1} key must be a blob
-** created by the OP_MakeRecord opcode of the VDBE. The pPKey2
-** key must be a parsed key such as obtained from
-** sqlite3VdbeParseRecord.
-**
-** If argument bSkip is non-zero, it is assumed that the caller has already
-** determined that the first fields of the keys are equal.
-**
-** Key1 and Key2 do not have to contain the same number of fields. If all
-** fields that appear in both keys are equal, then pPKey2->default_rc is
-** returned.
-**
-** If database corruption is discovered, set pPKey2->errCode to
-** SQLITE_CORRUPT and return 0. If an OOM error is encountered,
-** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
-** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
-*/
-int sqlite3VdbeRecordCompareWithSkip(
- int nKey1, const void *pKey1, /* Left key */
- UnpackedRecord *pPKey2, /* Right key */
- int bSkip /* If true, skip the first field */
-){
- u32 d1; /* Offset into aKey[] of next data element */
- int i; /* Index of next field to compare */
- u32 szHdr1; /* Size of record header in bytes */
- u32 idx1; /* Offset of first type in header */
- int rc = 0; /* Return value */
- Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
- KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
- const unsigned char *aKey1 = (const unsigned char *)pKey1;
- Mem mem1;
-
- /* If bSkip is true, then the caller has already determined that the first
- ** two elements in the keys are equal. Fix the various stack variables so
- ** that this routine begins comparing at the second field. */
- if( bSkip ){
- u32 s1;
- idx1 = 1 + getVarint32(&aKey1[1], s1);
- szHdr1 = aKey1[0];
- d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
- i = 1;
- pRhs++;
- }else{
- idx1 = getVarint32(aKey1, szHdr1);
- d1 = szHdr1;
- if( d1>(unsigned)nKey1 ){
- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
- return 0; /* Corruption */
- }
- i = 0;
- }
-
- VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
- assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
- || CORRUPT_DB );
- assert( pPKey2->pKeyInfo->aSortOrder!=0 );
- assert( pPKey2->pKeyInfo->nKeyField>0 );
- assert( idx1<=szHdr1 || CORRUPT_DB );
- do{
- u32 serial_type;
-
- /* RHS is an integer */
- if( pRhs->flags & MEM_Int ){
- serial_type = aKey1[idx1];
- testcase( serial_type==12 );
- if( serial_type>=10 ){
- rc = +1;
- }else if( serial_type==0 ){
- rc = -1;
- }else if( serial_type==7 ){
- sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
- rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
- }else{
- i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
- i64 rhs = pRhs->u.i;
- if( lhs<rhs ){
- rc = -1;
- }else if( lhs>rhs ){
- rc = +1;
- }
- }
- }
-
- /* RHS is real */
- else if( pRhs->flags & MEM_Real ){
- serial_type = aKey1[idx1];
- if( serial_type>=10 ){
- /* Serial types 12 or greater are strings and blobs (greater than
- ** numbers). Types 10 and 11 are currently "reserved for future
- ** use", so it doesn't really matter what the results of comparing
- ** them to numberic values are. */
- rc = +1;
- }else if( serial_type==0 ){
- rc = -1;
- }else{
- sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
- if( serial_type==7 ){
- if( mem1.u.r<pRhs->u.r ){
- rc = -1;
- }else if( mem1.u.r>pRhs->u.r ){
- rc = +1;
- }
- }else{
- rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
- }
- }
- }
-
- /* RHS is a string */
- else if( pRhs->flags & MEM_Str ){
- getVarint32(&aKey1[idx1], serial_type);
- testcase( serial_type==12 );
- if( serial_type<12 ){
- rc = -1;
- }else if( !(serial_type & 0x01) ){
- rc = +1;
- }else{
- mem1.n = (serial_type - 12) / 2;
- testcase( (d1+mem1.n)==(unsigned)nKey1 );
- testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
- if( (d1+mem1.n) > (unsigned)nKey1 ){
- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
- return 0; /* Corruption */
- }else if( pKeyInfo->aColl[i] ){
- mem1.enc = pKeyInfo->enc;
- mem1.db = pKeyInfo->db;
- mem1.flags = MEM_Str;
- mem1.z = (char*)&aKey1[d1];
- rc = vdbeCompareMemString(
- &mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode
- );
- }else{
- int nCmp = MIN(mem1.n, pRhs->n);
- rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
- if( rc==0 ) rc = mem1.n - pRhs->n;
- }
- }
- }
-
- /* RHS is a blob */
- else if( pRhs->flags & MEM_Blob ){
- assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 );
- getVarint32(&aKey1[idx1], serial_type);
- testcase( serial_type==12 );
- if( serial_type<12 || (serial_type & 0x01) ){
- rc = -1;
- }else{
- int nStr = (serial_type - 12) / 2;
- testcase( (d1+nStr)==(unsigned)nKey1 );
- testcase( (d1+nStr+1)==(unsigned)nKey1 );
- if( (d1+nStr) > (unsigned)nKey1 ){
- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
- return 0; /* Corruption */
- }else if( pRhs->flags & MEM_Zero ){
- if( !isAllZero((const char*)&aKey1[d1],nStr) ){
- rc = 1;
- }else{
- rc = nStr - pRhs->u.nZero;
- }
- }else{
- int nCmp = MIN(nStr, pRhs->n);
- rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
- if( rc==0 ) rc = nStr - pRhs->n;
- }
- }
- }
-
- /* RHS is null */
- else{
- serial_type = aKey1[idx1];
- rc = (serial_type!=0);
- }
-
- if( rc!=0 ){
- if( pKeyInfo->aSortOrder[i] ){
- rc = -rc;
- }
- assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
- assert( mem1.szMalloc==0 ); /* See comment below */
- return rc;
- }
-
- i++;
- pRhs++;
- d1 += sqlite3VdbeSerialTypeLen(serial_type);
- idx1 += sqlite3VarintLen(serial_type);
- }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
-
- /* No memory allocation is ever used on mem1. Prove this using
- ** the following assert(). If the assert() fails, it indicates a
- ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */
- assert( mem1.szMalloc==0 );
-
- /* rc==0 here means that one or both of the keys ran out of fields and
- ** all the fields up to that point were equal. Return the default_rc
- ** value. */
- assert( CORRUPT_DB
- || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)
- || pKeyInfo->db->mallocFailed
- );
- pPKey2->eqSeen = 1;
- return pPKey2->default_rc;
-}
-int sqlite3VdbeRecordCompare(
- int nKey1, const void *pKey1, /* Left key */
- UnpackedRecord *pPKey2 /* Right key */
-){
- return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
-}
-
-
-/*
-** This function is an optimized version of sqlite3VdbeRecordCompare()
-** that (a) the first field of pPKey2 is an integer, and (b) the
-** size-of-header varint at the start of (pKey1/nKey1) fits in a single
-** byte (i.e. is less than 128).
-**
-** To avoid concerns about buffer overreads, this routine is only used
-** on schemas where the maximum valid header size is 63 bytes or less.
-*/
-static int vdbeRecordCompareInt(
- int nKey1, const void *pKey1, /* Left key */
- UnpackedRecord *pPKey2 /* Right key */
-){
- const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
- int serial_type = ((const u8*)pKey1)[1];
- int res;
- u32 y;
- u64 x;
- i64 v;
- i64 lhs;
-
- vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
- assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
- switch( serial_type ){
- case 1: { /* 1-byte signed integer */
- lhs = ONE_BYTE_INT(aKey);
- testcase( lhs<0 );
- break;
- }
- case 2: { /* 2-byte signed integer */
- lhs = TWO_BYTE_INT(aKey);
- testcase( lhs<0 );
- break;
- }
- case 3: { /* 3-byte signed integer */
- lhs = THREE_BYTE_INT(aKey);
- testcase( lhs<0 );
- break;
- }
- case 4: { /* 4-byte signed integer */
- y = FOUR_BYTE_UINT(aKey);
- lhs = (i64)*(int*)&y;
- testcase( lhs<0 );
- break;
- }
- case 5: { /* 6-byte signed integer */
- lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
- testcase( lhs<0 );
- break;
- }
- case 6: { /* 8-byte signed integer */
- x = FOUR_BYTE_UINT(aKey);
- x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
- lhs = *(i64*)&x;
- testcase( lhs<0 );
- break;
- }
- case 8:
- lhs = 0;
- break;
- case 9:
- lhs = 1;
- break;
-
- /* This case could be removed without changing the results of running
- ** this code. Including it causes gcc to generate a faster switch
- ** statement (since the range of switch targets now starts at zero and
- ** is contiguous) but does not cause any duplicate code to be generated
- ** (as gcc is clever enough to combine the two like cases). Other
- ** compilers might be similar. */
- case 0: case 7:
- return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
-
- default:
- return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
- }
-
- v = pPKey2->aMem[0].u.i;
- if( v>lhs ){
- res = pPKey2->r1;
- }else if( v<lhs ){
- res = pPKey2->r2;
- }else if( pPKey2->nField>1 ){
- /* The first fields of the two keys are equal. Compare the trailing
- ** fields. */
- res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
- }else{
- /* The first fields of the two keys are equal and there are no trailing
- ** fields. Return pPKey2->default_rc in this case. */
- res = pPKey2->default_rc;
- pPKey2->eqSeen = 1;
- }
-
- assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) );
- return res;
-}
-
-/*
-** This function is an optimized version of sqlite3VdbeRecordCompare()
-** that (a) the first field of pPKey2 is a string, that (b) the first field
-** uses the collation sequence BINARY and (c) that the size-of-header varint
-** at the start of (pKey1/nKey1) fits in a single byte.
-*/
-static int vdbeRecordCompareString(
- int nKey1, const void *pKey1, /* Left key */
- UnpackedRecord *pPKey2 /* Right key */
-){
- const u8 *aKey1 = (const u8*)pKey1;
- int serial_type;
- int res;
-
- assert( pPKey2->aMem[0].flags & MEM_Str );
- vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
- getVarint32(&aKey1[1], serial_type);
- if( serial_type<12 ){
- res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
- }else if( !(serial_type & 0x01) ){
- res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
- }else{
- int nCmp;
- int nStr;
- int szHdr = aKey1[0];
-
- nStr = (serial_type-12) / 2;
- if( (szHdr + nStr) > nKey1 ){
- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
- return 0; /* Corruption */
- }
- nCmp = MIN( pPKey2->aMem[0].n, nStr );
- res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
-
- if( res==0 ){
- res = nStr - pPKey2->aMem[0].n;
- if( res==0 ){
- if( pPKey2->nField>1 ){
- res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
- }else{
- res = pPKey2->default_rc;
- pPKey2->eqSeen = 1;
- }
- }else if( res>0 ){
- res = pPKey2->r2;
- }else{
- res = pPKey2->r1;
- }
- }else if( res>0 ){
- res = pPKey2->r2;
- }else{
- res = pPKey2->r1;
- }
- }
-
- assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res)
- || CORRUPT_DB
- || pPKey2->pKeyInfo->db->mallocFailed
- );
- return res;
-}
-
-/*
-** Return a pointer to an sqlite3VdbeRecordCompare() compatible function
-** suitable for comparing serialized records to the unpacked record passed
-** as the only argument.
-*/
-RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
- /* varintRecordCompareInt() and varintRecordCompareString() both assume
- ** that the size-of-header varint that occurs at the start of each record
- ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
- ** also assumes that it is safe to overread a buffer by at least the
- ** maximum possible legal header size plus 8 bytes. Because there is
- ** guaranteed to be at least 74 (but not 136) bytes of padding following each
- ** buffer passed to varintRecordCompareInt() this makes it convenient to
- ** limit the size of the header to 64 bytes in cases where the first field
- ** is an integer.
- **
- ** The easiest way to enforce this limit is to consider only records with
- ** 13 fields or less. If the first field is an integer, the maximum legal
- ** header size is (12*5 + 1 + 1) bytes. */
- if( p->pKeyInfo->nAllField<=13 ){
- int flags = p->aMem[0].flags;
- if( p->pKeyInfo->aSortOrder[0] ){
- p->r1 = 1;
- p->r2 = -1;
- }else{
- p->r1 = -1;
- p->r2 = 1;
- }
- if( (flags & MEM_Int) ){
- return vdbeRecordCompareInt;
- }
- testcase( flags & MEM_Real );
- testcase( flags & MEM_Null );
- testcase( flags & MEM_Blob );
- if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){
- assert( flags & MEM_Str );
- return vdbeRecordCompareString;
- }
- }
-
- return sqlite3VdbeRecordCompare;
-}
-
-/*
-** pCur points at an index entry created using the OP_MakeRecord opcode.
-** Read the rowid (the last field in the record) and store it in *rowid.
-** Return SQLITE_OK if everything works, or an error code otherwise.
-**
-** pCur might be pointing to text obtained from a corrupt database file.
-** So the content cannot be trusted. Do appropriate checks on the content.
-*/
-int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
- i64 nCellKey = 0;
- int rc;
- u32 szHdr; /* Size of the header */
- u32 typeRowid; /* Serial type of the rowid */
- u32 lenRowid; /* Size of the rowid */
- Mem m, v;
-
- /* Get the size of the index entry. Only indices entries of less
- ** than 2GiB are support - anything large must be database corruption.
- ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
- ** this code can safely assume that nCellKey is 32-bits
- */
- assert( sqlite3BtreeCursorIsValid(pCur) );
- nCellKey = sqlite3BtreePayloadSize(pCur);
- assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
-
- /* Read in the complete content of the index entry */
- sqlite3VdbeMemInit(&m, db, 0);
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
- if( rc ){
- return rc;
- }
-
- /* The index entry must begin with a header size */
- (void)getVarint32((u8*)m.z, szHdr);
- testcase( szHdr==3 );
- testcase( szHdr==m.n );
- if( unlikely(szHdr<3 || (int)szHdr>m.n) ){
- goto idx_rowid_corruption;
- }
-
- /* The last field of the index should be an integer - the ROWID.
- ** Verify that the last entry really is an integer. */
- (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
- testcase( typeRowid==1 );
- testcase( typeRowid==2 );
- testcase( typeRowid==3 );
- testcase( typeRowid==4 );
- testcase( typeRowid==5 );
- testcase( typeRowid==6 );
- testcase( typeRowid==8 );
- testcase( typeRowid==9 );
- if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){
- goto idx_rowid_corruption;
- }
- lenRowid = sqlite3SmallTypeSizes[typeRowid];
- testcase( (u32)m.n==szHdr+lenRowid );
- if( unlikely((u32)m.n<szHdr+lenRowid) ){
- goto idx_rowid_corruption;
- }
-
- /* Fetch the integer off the end of the index record */
- sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
- *rowid = v.u.i;
- sqlite3VdbeMemRelease(&m);
- return SQLITE_OK;
-
- /* Jump here if database corruption is detected after m has been
- ** allocated. Free the m object and return SQLITE_CORRUPT. */
-idx_rowid_corruption:
- testcase( m.szMalloc!=0 );
- sqlite3VdbeMemRelease(&m);
- return SQLITE_CORRUPT_BKPT;
-}
-
-/*
-** Compare the key of the index entry that cursor pC is pointing to against
-** the key string in pUnpacked. Write into *pRes a number
-** that is negative, zero, or positive if pC is less than, equal to,
-** or greater than pUnpacked. Return SQLITE_OK on success.
-**
-** pUnpacked is either created without a rowid or is truncated so that it
-** omits the rowid at the end. The rowid at the end of the index entry
-** is ignored as well. Hence, this routine only compares the prefixes
-** of the keys prior to the final rowid, not the entire key.
-*/
-int sqlite3VdbeIdxKeyCompare(
- sqlite3 *db, /* Database connection */
- VdbeCursor *pC, /* The cursor to compare against */
- UnpackedRecord *pUnpacked, /* Unpacked version of key */
- int *res /* Write the comparison result here */
-){
- i64 nCellKey = 0;
- int rc;
- BtCursor *pCur;
- Mem m;
-
- assert( pC->eCurType==CURTYPE_BTREE );
- pCur = pC->uc.pCursor;
- assert( sqlite3BtreeCursorIsValid(pCur) );
- nCellKey = sqlite3BtreePayloadSize(pCur);
- /* nCellKey will always be between 0 and 0xffffffff because of the way
- ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
- if( nCellKey<=0 || nCellKey>0x7fffffff ){
- *res = 0;
- return SQLITE_CORRUPT_BKPT;
- }
- sqlite3VdbeMemInit(&m, db, 0);
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
- if( rc ){
- return rc;
- }
- *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
- sqlite3VdbeMemRelease(&m);
- return SQLITE_OK;
-}
-
-/*
-** This routine sets the value to be returned by subsequent calls to
-** sqlite3_changes() on the database handle 'db'.
-*/
-void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
- assert( sqlite3_mutex_held(db->mutex) );
- db->nChange = nChange;
- db->nTotalChange += nChange;
-}
-
-/*
-** Set a flag in the vdbe to update the change counter when it is finalised
-** or reset.
-*/
-void sqlite3VdbeCountChanges(Vdbe *v){
- v->changeCntOn = 1;
-}
-
-/*
-** Mark every prepared statement associated with a database connection
-** as expired.
-**
-** An expired statement means that recompilation of the statement is
-** recommend. Statements expire when things happen that make their
-** programs obsolete. Removing user-defined functions or collating
-** sequences, or changing an authorization function are the types of
-** things that make prepared statements obsolete.
-*/
-void sqlite3ExpirePreparedStatements(sqlite3 *db){
- Vdbe *p;
- for(p = db->pVdbe; p; p=p->pNext){
- p->expired = 1;
- }
-}
-
-/*
-** Return the database associated with the Vdbe.
-*/
-sqlite3 *sqlite3VdbeDb(Vdbe *v){
- return v->db;
-}
-
-/*
-** Return the SQLITE_PREPARE flags for a Vdbe.
-*/
-u8 sqlite3VdbePrepareFlags(Vdbe *v){
- return v->prepFlags;
-}
-
-/*
-** Return a pointer to an sqlite3_value structure containing the value bound
-** parameter iVar of VM v. Except, if the value is an SQL NULL, return
-** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_*
-** constants) to the value before returning it.
-**
-** The returned value must be freed by the caller using sqlite3ValueFree().
-*/
-sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
- assert( iVar>0 );
- if( v ){
- Mem *pMem = &v->aVar[iVar-1];
- assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
- if( 0==(pMem->flags & MEM_Null) ){
- sqlite3_value *pRet = sqlite3ValueNew(v->db);
- if( pRet ){
- sqlite3VdbeMemCopy((Mem *)pRet, pMem);
- sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
- }
- return pRet;
- }
- }
- return 0;
-}
-
-/*
-** Configure SQL variable iVar so that binding a new value to it signals
-** to sqlite3_reoptimize() that re-preparing the statement may result
-** in a better query plan.
-*/
-void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
- assert( iVar>0 );
- assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
- if( iVar>=32 ){
- v->expmask |= 0x80000000;
- }else{
- v->expmask |= ((u32)1 << (iVar-1));
- }
-}
-
-/*
-** Cause a function to throw an error if it was call from OP_PureFunc
-** rather than OP_Function.
-**
-** OP_PureFunc means that the function must be deterministic, and should
-** throw an error if it is given inputs that would make it non-deterministic.
-** This routine is invoked by date/time functions that use non-deterministic
-** features such as 'now'.
-*/
-int sqlite3NotPureFunc(sqlite3_context *pCtx){
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( pCtx->pVdbe==0 ) return 1;
-#endif
- if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
- sqlite3_result_error(pCtx,
- "non-deterministic function in index expression or CHECK constraint",
- -1);
- return 0;
- }
- return 1;
-}
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*
-** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
-** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
-** in memory obtained from sqlite3DbMalloc).
-*/
-void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
- if( pVtab->zErrMsg ){
- sqlite3 *db = p->db;
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
- sqlite3_free(pVtab->zErrMsg);
- pVtab->zErrMsg = 0;
- }
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-
-/*
-** If the second argument is not NULL, release any allocations associated
-** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord
-** structure itself, using sqlite3DbFree().
-**
-** This function is used to free UnpackedRecord structures allocated by
-** the vdbeUnpackRecord() function found in vdbeapi.c.
-*/
-static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
- if( p ){
- int i;
- for(i=0; i<nField; i++){
- Mem *pMem = &p->aMem[i];
- if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem);
- }
- sqlite3DbFreeNN(db, p);
- }
-}
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-/*
-** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call,
-** then cursor passed as the second argument should point to the row about
-** to be update or deleted. If the application calls sqlite3_preupdate_old(),
-** the required value will be read from the row the cursor points to.
-*/
-void sqlite3VdbePreUpdateHook(
- Vdbe *v, /* Vdbe pre-update hook is invoked by */
- VdbeCursor *pCsr, /* Cursor to grab old.* values from */
- int op, /* SQLITE_INSERT, UPDATE or DELETE */
- const char *zDb, /* Database name */
- Table *pTab, /* Modified table */
- i64 iKey1, /* Initial key value */
- int iReg /* Register for new.* record */
-){
- sqlite3 *db = v->db;
- i64 iKey2;
- PreUpdate preupdate;
- const char *zTbl = pTab->zName;
- static const u8 fakeSortOrder = 0;
-
- assert( db->pPreUpdate==0 );
- memset(&preupdate, 0, sizeof(PreUpdate));
- if( HasRowid(pTab)==0 ){
- iKey1 = iKey2 = 0;
- preupdate.pPk = sqlite3PrimaryKeyIndex(pTab);
- }else{
- if( op==SQLITE_UPDATE ){
- iKey2 = v->aMem[iReg].u.i;
- }else{
- iKey2 = iKey1;
- }
- }
-
- assert( pCsr->nField==pTab->nCol
- || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1)
- );
-
- preupdate.v = v;
- preupdate.pCsr = pCsr;
- preupdate.op = op;
- preupdate.iNewReg = iReg;
- preupdate.keyinfo.db = db;
- preupdate.keyinfo.enc = ENC(db);
- preupdate.keyinfo.nKeyField = pTab->nCol;
- preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
- preupdate.iKey1 = iKey1;
- preupdate.iKey2 = iKey2;
- preupdate.pTab = pTab;
-
- db->pPreUpdate = &preupdate;
- db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
- db->pPreUpdate = 0;
- sqlite3DbFree(db, preupdate.aRecord);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
- if( preupdate.aNew ){
- int i;
- for(i=0; i<pCsr->nField; i++){
- sqlite3VdbeMemRelease(&preupdate.aNew[i]);
- }
- sqlite3DbFreeNN(db, preupdate.aNew);
- }
-}
-#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeblob.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeblob.c
deleted file mode 100644
index 42797926965..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbeblob.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
-** 2007 May 1
-**
-** 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 contains code used to implement incremental BLOB I/O.
-*/
-
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-#ifndef SQLITE_OMIT_INCRBLOB
-
-/*
-** Valid sqlite3_blob* handles point to Incrblob structures.
-*/
-typedef struct Incrblob Incrblob;
-struct Incrblob {
- int nByte; /* Size of open blob, in bytes */
- int iOffset; /* Byte offset of blob in cursor data */
- u16 iCol; /* Table column this handle is open on */
- BtCursor *pCsr; /* Cursor pointing at blob row */
- sqlite3_stmt *pStmt; /* Statement holding cursor open */
- sqlite3 *db; /* The associated database */
- char *zDb; /* Database name */
- Table *pTab; /* Table object */
-};
-
-
-/*
-** This function is used by both blob_open() and blob_reopen(). It seeks
-** the b-tree cursor associated with blob handle p to point to row iRow.
-** If successful, SQLITE_OK is returned and subsequent calls to
-** sqlite3_blob_read() or sqlite3_blob_write() access the specified row.
-**
-** If an error occurs, or if the specified row does not exist or does not
-** contain a value of type TEXT or BLOB in the column nominated when the
-** blob handle was opened, then an error code is returned and *pzErr may
-** be set to point to a buffer containing an error message. It is the
-** responsibility of the caller to free the error message buffer using
-** sqlite3DbFree().
-**
-** If an error does occur, then the b-tree cursor is closed. All subsequent
-** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will
-** immediately return SQLITE_ABORT.
-*/
-static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
- int rc; /* Error code */
- char *zErr = 0; /* Error message */
- Vdbe *v = (Vdbe *)p->pStmt;
-
- /* Set the value of register r[1] in the SQL statement to integer iRow.
- ** This is done directly as a performance optimization
- */
- v->aMem[1].flags = MEM_Int;
- v->aMem[1].u.i = iRow;
-
- /* If the statement has been run before (and is paused at the OP_ResultRow)
- ** then back it up to the point where it does the OP_NotExists. This could
- ** have been down with an extra OP_Goto, but simply setting the program
- ** counter is faster. */
- if( v->pc>4 ){
- v->pc = 4;
- assert( v->aOp[v->pc].opcode==OP_NotExists );
- rc = sqlite3VdbeExec(v);
- }else{
- rc = sqlite3_step(p->pStmt);
- }
- if( rc==SQLITE_ROW ){
- VdbeCursor *pC = v->apCsr[0];
- u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
- testcase( pC->nHdrParsed==p->iCol );
- testcase( pC->nHdrParsed==p->iCol+1 );
- if( type<12 ){
- zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
- type==0?"null": type==7?"real": "integer"
- );
- rc = SQLITE_ERROR;
- sqlite3_finalize(p->pStmt);
- p->pStmt = 0;
- }else{
- p->iOffset = pC->aType[p->iCol + pC->nField];
- p->nByte = sqlite3VdbeSerialTypeLen(type);
- p->pCsr = pC->uc.pCursor;
- sqlite3BtreeIncrblobCursor(p->pCsr);
- }
- }
-
- if( rc==SQLITE_ROW ){
- rc = SQLITE_OK;
- }else if( p->pStmt ){
- rc = sqlite3_finalize(p->pStmt);
- p->pStmt = 0;
- if( rc==SQLITE_OK ){
- zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow);
- rc = SQLITE_ERROR;
- }else{
- zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db));
- }
- }
-
- assert( rc!=SQLITE_OK || zErr==0 );
- assert( rc!=SQLITE_ROW && rc!=SQLITE_DONE );
-
- *pzErr = zErr;
- return rc;
-}
-
-/*
-** Open a blob handle.
-*/
-int sqlite3_blob_open(
- sqlite3* db, /* The database connection */
- const char *zDb, /* The attached database containing the blob */
- const char *zTable, /* The table containing the blob */
- const char *zColumn, /* The column containing the blob */
- sqlite_int64 iRow, /* The row containing the glob */
- int wrFlag, /* True -> read/write access, false -> read-only */
- sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */
-){
- int nAttempt = 0;
- int iCol; /* Index of zColumn in row-record */
- int rc = SQLITE_OK;
- char *zErr = 0;
- Table *pTab;
- Incrblob *pBlob = 0;
- Parse sParse;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( ppBlob==0 ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- *ppBlob = 0;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zTable==0 ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */
-
- sqlite3_mutex_enter(db->mutex);
-
- pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
- do {
- memset(&sParse, 0, sizeof(Parse));
- if( !pBlob ) goto blob_open_out;
- sParse.db = db;
- sqlite3DbFree(db, zErr);
- zErr = 0;
-
- sqlite3BtreeEnterAll(db);
- pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb);
- if( pTab && IsVirtual(pTab) ){
- pTab = 0;
- sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable);
- }
- if( pTab && !HasRowid(pTab) ){
- pTab = 0;
- sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
- }
-#ifndef SQLITE_OMIT_VIEW
- if( pTab && pTab->pSelect ){
- pTab = 0;
- sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
- }
-#endif
- if( !pTab ){
- if( sParse.zErrMsg ){
- sqlite3DbFree(db, zErr);
- zErr = sParse.zErrMsg;
- sParse.zErrMsg = 0;
- }
- rc = SQLITE_ERROR;
- sqlite3BtreeLeaveAll(db);
- goto blob_open_out;
- }
- pBlob->pTab = pTab;
- pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
-
- /* Now search pTab for the exact column. */
- for(iCol=0; iCol<pTab->nCol; iCol++) {
- if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
- break;
- }
- }
- if( iCol==pTab->nCol ){
- sqlite3DbFree(db, zErr);
- zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
- rc = SQLITE_ERROR;
- sqlite3BtreeLeaveAll(db);
- goto blob_open_out;
- }
-
- /* If the value is being opened for writing, check that the
- ** column is not indexed, and that it is not part of a foreign key.
- */
- if( wrFlag ){
- const char *zFault = 0;
- Index *pIdx;
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- if( db->flags&SQLITE_ForeignKeys ){
- /* Check that the column is not part of an FK child key definition. It
- ** is not necessary to check if it is part of a parent key, as parent
- ** key columns must be indexed. The check below will pick up this
- ** case. */
- FKey *pFKey;
- for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
- int j;
- for(j=0; j<pFKey->nCol; j++){
- if( pFKey->aCol[j].iFrom==iCol ){
- zFault = "foreign key";
- }
- }
- }
- }
-#endif
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int j;
- for(j=0; j<pIdx->nKeyCol; j++){
- /* FIXME: Be smarter about indexes that use expressions */
- if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){
- zFault = "indexed";
- }
- }
- }
- if( zFault ){
- sqlite3DbFree(db, zErr);
- zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
- rc = SQLITE_ERROR;
- sqlite3BtreeLeaveAll(db);
- goto blob_open_out;
- }
- }
-
- pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(&sParse);
- assert( pBlob->pStmt || db->mallocFailed );
- if( pBlob->pStmt ){
-
- /* This VDBE program seeks a btree cursor to the identified
- ** db/table/row entry. The reason for using a vdbe program instead
- ** of writing code to use the b-tree layer directly is that the
- ** vdbe program will take advantage of the various transaction,
- ** locking and error handling infrastructure built into the vdbe.
- **
- ** After seeking the cursor, the vdbe executes an OP_ResultRow.
- ** Code external to the Vdbe then "borrows" the b-tree cursor and
- ** uses it to implement the blob_read(), blob_write() and
- ** blob_bytes() functions.
- **
- ** The sqlite3_blob_close() function finalizes the vdbe program,
- ** which closes the b-tree cursor and (possibly) commits the
- ** transaction.
- */
- static const int iLn = VDBE_OFFSET_LINENO(2);
- static const VdbeOpList openBlob[] = {
- {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */
- {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */
- /* blobSeekToRow() will initialize r[1] to the desired rowid */
- {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */
- {OP_Column, 0, 0, 1}, /* 3 */
- {OP_ResultRow, 1, 0, 0}, /* 4 */
- {OP_Halt, 0, 0, 0}, /* 5 */
- };
- Vdbe *v = (Vdbe *)pBlob->pStmt;
- int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- VdbeOp *aOp;
-
- sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
- pTab->pSchema->schema_cookie,
- pTab->pSchema->iGeneration);
- sqlite3VdbeChangeP5(v, 1);
- assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed );
- aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
-
- /* Make sure a mutex is held on the table to be accessed */
- sqlite3VdbeUsesBtree(v, iDb);
-
- if( db->mallocFailed==0 ){
- assert( aOp!=0 );
- /* Configure the OP_TableLock instruction */
-#ifdef SQLITE_OMIT_SHARED_CACHE
- aOp[0].opcode = OP_Noop;
-#else
- aOp[0].p1 = iDb;
- aOp[0].p2 = pTab->tnum;
- aOp[0].p3 = wrFlag;
- sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
- }
- if( db->mallocFailed==0 ){
-#endif
-
- /* Remove either the OP_OpenWrite or OpenRead. Set the P2
- ** parameter of the other to pTab->tnum. */
- if( wrFlag ) aOp[1].opcode = OP_OpenWrite;
- aOp[1].p2 = pTab->tnum;
- aOp[1].p3 = iDb;
-
- /* Configure the number of columns. Configure the cursor to
- ** think that the table has one more column than it really
- ** does. An OP_Column to retrieve this imaginary column will
- ** always return an SQL NULL. This is useful because it means
- ** we can invoke OP_Column to fill in the vdbe cursors type
- ** and offset cache without causing any IO.
- */
- aOp[1].p4type = P4_INT32;
- aOp[1].p4.i = pTab->nCol+1;
- aOp[3].p2 = pTab->nCol;
-
- sParse.nVar = 0;
- sParse.nMem = 1;
- sParse.nTab = 1;
- sqlite3VdbeMakeReady(v, &sParse);
- }
- }
-
- pBlob->iCol = iCol;
- pBlob->db = db;
- sqlite3BtreeLeaveAll(db);
- if( db->mallocFailed ){
- goto blob_open_out;
- }
- rc = blobSeekToRow(pBlob, iRow, &zErr);
- } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
-
-blob_open_out:
- if( rc==SQLITE_OK && db->mallocFailed==0 ){
- *ppBlob = (sqlite3_blob *)pBlob;
- }else{
- if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
- sqlite3DbFree(db, pBlob);
- }
- sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
- sqlite3DbFree(db, zErr);
- sqlite3ParserReset(&sParse);
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** Close a blob handle that was previously created using
-** sqlite3_blob_open().
-*/
-int sqlite3_blob_close(sqlite3_blob *pBlob){
- Incrblob *p = (Incrblob *)pBlob;
- int rc;
- sqlite3 *db;
-
- if( p ){
- db = p->db;
- sqlite3_mutex_enter(db->mutex);
- rc = sqlite3_finalize(p->pStmt);
- sqlite3DbFree(db, p);
- sqlite3_mutex_leave(db->mutex);
- }else{
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-/*
-** Perform a read or write operation on a blob
-*/
-static int blobReadWrite(
- sqlite3_blob *pBlob,
- void *z,
- int n,
- int iOffset,
- int (*xCall)(BtCursor*, u32, u32, void*)
-){
- int rc;
- Incrblob *p = (Incrblob *)pBlob;
- Vdbe *v;
- sqlite3 *db;
-
- if( p==0 ) return SQLITE_MISUSE_BKPT;
- db = p->db;
- sqlite3_mutex_enter(db->mutex);
- v = (Vdbe*)p->pStmt;
-
- if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){
- /* Request is out of range. Return a transient error. */
- rc = SQLITE_ERROR;
- }else if( v==0 ){
- /* If there is no statement handle, then the blob-handle has
- ** already been invalidated. Return SQLITE_ABORT in this case.
- */
- rc = SQLITE_ABORT;
- }else{
- /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
- ** returned, clean-up the statement handle.
- */
- assert( db == v->db );
- sqlite3BtreeEnterCursor(p->pCsr);
-
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
- if( xCall==sqlite3BtreePutData && db->xPreUpdateCallback ){
- /* If a pre-update hook is registered and this is a write cursor,
- ** invoke it here.
- **
- ** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this
- ** operation should really be an SQLITE_UPDATE. This is probably
- ** incorrect, but is convenient because at this point the new.* values
- ** are not easily obtainable. And for the sessions module, an
- ** SQLITE_UPDATE where the PK columns do not change is handled in the
- ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually
- ** slightly more efficient). Since you cannot write to a PK column
- ** using the incremental-blob API, this works. For the sessions module
- ** anyhow.
- */
- sqlite3_int64 iKey;
- iKey = sqlite3BtreeIntegerKey(p->pCsr);
- sqlite3VdbePreUpdateHook(
- v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1
- );
- }
-#endif
-
- rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
- sqlite3BtreeLeaveCursor(p->pCsr);
- if( rc==SQLITE_ABORT ){
- sqlite3VdbeFinalize(v);
- p->pStmt = 0;
- }else{
- v->rc = rc;
- }
- }
- sqlite3Error(db, rc);
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** Read data from a blob handle.
-*/
-int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
- return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreePayloadChecked);
-}
-
-/*
-** Write data to a blob handle.
-*/
-int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
- return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
-}
-
-/*
-** Query a blob handle for the size of the data.
-**
-** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
-** so no mutex is required for access.
-*/
-int sqlite3_blob_bytes(sqlite3_blob *pBlob){
- Incrblob *p = (Incrblob *)pBlob;
- return (p && p->pStmt) ? p->nByte : 0;
-}
-
-/*
-** Move an existing blob handle to point to a different row of the same
-** database table.
-**
-** If an error occurs, or if the specified row does not exist or does not
-** contain a blob or text value, then an error code is returned and the
-** database handle error code and message set. If this happens, then all
-** subsequent calls to sqlite3_blob_xxx() functions (except blob_close())
-** immediately return SQLITE_ABORT.
-*/
-int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
- int rc;
- Incrblob *p = (Incrblob *)pBlob;
- sqlite3 *db;
-
- if( p==0 ) return SQLITE_MISUSE_BKPT;
- db = p->db;
- sqlite3_mutex_enter(db->mutex);
-
- if( p->pStmt==0 ){
- /* If there is no statement handle, then the blob-handle has
- ** already been invalidated. Return SQLITE_ABORT in this case.
- */
- rc = SQLITE_ABORT;
- }else{
- char *zErr;
- rc = blobSeekToRow(p, iRow, &zErr);
- if( rc!=SQLITE_OK ){
- sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
- sqlite3DbFree(db, zErr);
- }
- assert( rc!=SQLITE_SCHEMA );
- }
-
- rc = sqlite3ApiExit(db, rc);
- assert( rc==SQLITE_OK || p->pStmt==0 );
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbemem.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbemem.c
deleted file mode 100644
index 933eee0b535..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbemem.c
+++ /dev/null
@@ -1,1840 +0,0 @@
-/*
-** 2004 May 26
-**
-** 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 contains code use to manipulate "Mem" structure. A "Mem"
-** stores a single value in the VDBE. Mem is an opaque structure visible
-** only within the VDBE. Interface routines refer to a Mem using the
-** name sqlite_value
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-#ifdef SQLITE_DEBUG
-/*
-** Check invariants on a Mem object.
-**
-** This routine is intended for use inside of assert() statements, like
-** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
-*/
-int sqlite3VdbeCheckMemInvariants(Mem *p){
- /* If MEM_Dyn is set then Mem.xDel!=0.
- ** Mem.xDel might not be initialized if MEM_Dyn is clear.
- */
- assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
-
- /* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we
- ** ensure that if Mem.szMalloc>0 then it is safe to do
- ** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn.
- ** That saves a few cycles in inner loops. */
- assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 );
-
- /* Cannot be both MEM_Int and MEM_Real at the same time */
- assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
-
- if( p->flags & MEM_Null ){
- /* Cannot be both MEM_Null and some other type */
- assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
- |MEM_RowSet|MEM_Frame|MEM_Agg))==0 );
-
- /* If MEM_Null is set, then either the value is a pure NULL (the usual
- ** case) or it is a pointer set using sqlite3_bind_pointer() or
- ** sqlite3_result_pointer(). If a pointer, then MEM_Term must also be
- ** set.
- */
- if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){
- /* This is a pointer type. There may be a flag to indicate what to
- ** do with the pointer. */
- assert( ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
- ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
- ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 );
-
- /* No other bits set */
- assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype
- |MEM_Dyn|MEM_Ephem|MEM_Static))==0 );
- }else{
- /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn,
- ** MEM_Ephem, MEM_Cleared, or MEM_Subtype */
- }
- }else{
- /* The MEM_Cleared bit is only allowed on NULLs */
- assert( (p->flags & MEM_Cleared)==0 );
- }
-
- /* The szMalloc field holds the correct memory allocation size */
- assert( p->szMalloc==0
- || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
-
- /* If p holds a string or blob, the Mem.z must point to exactly
- ** one of the following:
- **
- ** (1) Memory in Mem.zMalloc and managed by the Mem object
- ** (2) Memory to be freed using Mem.xDel
- ** (3) An ephemeral string or blob
- ** (4) A static string or blob
- */
- if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){
- assert(
- ((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) +
- ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
- ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
- ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
- );
- }
- return 1;
-}
-#endif
-
-#ifdef SQLITE_DEBUG
-/*
-** Check that string value of pMem agrees with its integer or real value.
-**
-** A single int or real value always converts to the same strings. But
-** many different strings can be converted into the same int or real.
-** If a table contains a numeric value and an index is based on the
-** corresponding string value, then it is important that the string be
-** derived from the numeric value, not the other way around, to ensure
-** that the index and table are consistent. See ticket
-** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for
-** an example.
-**
-** This routine looks at pMem to verify that if it has both a numeric
-** representation and a string representation then the string rep has
-** been derived from the numeric and not the other way around. It returns
-** true if everything is ok and false if there is a problem.
-**
-** This routine is for use inside of assert() statements only.
-*/
-int sqlite3VdbeMemConsistentDualRep(Mem *p){
- char zBuf[100];
- char *z;
- int i, j, incr;
- if( (p->flags & MEM_Str)==0 ) return 1;
- if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1;
- if( p->flags & MEM_Int ){
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i);
- }else{
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r);
- }
- z = p->z;
- i = j = 0;
- incr = 1;
- if( p->enc!=SQLITE_UTF8 ){
- incr = 2;
- if( p->enc==SQLITE_UTF16BE ) z++;
- }
- while( zBuf[j] ){
- if( zBuf[j++]!=z[i] ) return 0;
- i += incr;
- }
- return 1;
-}
-#endif /* SQLITE_DEBUG */
-
-/*
-** If pMem is an object with a valid string representation, this routine
-** ensures the internal encoding for the string representation is
-** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
-**
-** If pMem is not a string object, or the encoding of the string
-** representation is already stored using the requested encoding, then this
-** routine is a no-op.
-**
-** SQLITE_OK is returned if the conversion is successful (or not required).
-** SQLITE_NOMEM may be returned if a malloc() fails during conversion
-** between formats.
-*/
-int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
-#ifndef SQLITE_OMIT_UTF16
- int rc;
-#endif
- assert( (pMem->flags&MEM_RowSet)==0 );
- assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
- || desiredEnc==SQLITE_UTF16BE );
- if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
- return SQLITE_OK;
- }
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
-#ifdef SQLITE_OMIT_UTF16
- return SQLITE_ERROR;
-#else
-
- /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
- ** then the encoding of the value may not have changed.
- */
- rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc);
- assert(rc==SQLITE_OK || rc==SQLITE_NOMEM);
- assert(rc==SQLITE_OK || pMem->enc!=desiredEnc);
- assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
- return rc;
-#endif
-}
-
-/*
-** Make sure pMem->z points to a writable allocation of at least
-** min(n,32) bytes.
-**
-** If the bPreserve argument is true, then copy of the content of
-** pMem->z into the new allocation. pMem must be either a string or
-** blob if bPreserve is true. If bPreserve is false, any prior content
-** in pMem->z is discarded.
-*/
-SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
- assert( sqlite3VdbeCheckMemInvariants(pMem) );
- assert( (pMem->flags&MEM_RowSet)==0 );
- testcase( pMem->db==0 );
-
- /* If the bPreserve flag is set to true, then the memory cell must already
- ** contain a valid string or blob value. */
- assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
- testcase( bPreserve && pMem->z==0 );
-
- assert( pMem->szMalloc==0
- || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
- if( n<32 ) n = 32;
- if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
- pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
- bPreserve = 0;
- }else{
- if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
- pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
- }
- if( pMem->zMalloc==0 ){
- sqlite3VdbeMemSetNull(pMem);
- pMem->z = 0;
- pMem->szMalloc = 0;
- return SQLITE_NOMEM_BKPT;
- }else{
- pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
- }
-
- if( bPreserve && pMem->z ){
- assert( pMem->z!=pMem->zMalloc );
- memcpy(pMem->zMalloc, pMem->z, pMem->n);
- }
- if( (pMem->flags&MEM_Dyn)!=0 ){
- assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
- pMem->xDel((void *)(pMem->z));
- }
-
- pMem->z = pMem->zMalloc;
- pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
- return SQLITE_OK;
-}
-
-/*
-** Change the pMem->zMalloc allocation to be at least szNew bytes.
-** If pMem->zMalloc already meets or exceeds the requested size, this
-** routine is a no-op.
-**
-** Any prior string or blob content in the pMem object may be discarded.
-** The pMem->xDel destructor is called, if it exists. Though MEM_Str
-** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null
-** values are preserved.
-**
-** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM)
-** if unable to complete the resizing.
-*/
-int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
- assert( szNew>0 );
- assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 );
- if( pMem->szMalloc<szNew ){
- return sqlite3VdbeMemGrow(pMem, szNew, 0);
- }
- assert( (pMem->flags & MEM_Dyn)==0 );
- pMem->z = pMem->zMalloc;
- pMem->flags &= (MEM_Null|MEM_Int|MEM_Real);
- return SQLITE_OK;
-}
-
-/*
-** It is already known that pMem contains an unterminated string.
-** Add the zero terminator.
-*/
-static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
- if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
- return SQLITE_NOMEM_BKPT;
- }
- pMem->z[pMem->n] = 0;
- pMem->z[pMem->n+1] = 0;
- pMem->flags |= MEM_Term;
- return SQLITE_OK;
-}
-
-/*
-** Change pMem so that its MEM_Str or MEM_Blob value is stored in
-** MEM.zMalloc, where it can be safely written.
-**
-** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
-*/
-int sqlite3VdbeMemMakeWriteable(Mem *pMem){
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( (pMem->flags&MEM_RowSet)==0 );
- if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
- if( ExpandBlob(pMem) ) return SQLITE_NOMEM;
- if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){
- int rc = vdbeMemAddTerminator(pMem);
- if( rc ) return rc;
- }
- }
- pMem->flags &= ~MEM_Ephem;
-#ifdef SQLITE_DEBUG
- pMem->pScopyFrom = 0;
-#endif
-
- return SQLITE_OK;
-}
-
-/*
-** If the given Mem* has a zero-filled tail, turn it into an ordinary
-** blob stored in dynamically allocated space.
-*/
-#ifndef SQLITE_OMIT_INCRBLOB
-int sqlite3VdbeMemExpandBlob(Mem *pMem){
- int nByte;
- assert( pMem->flags & MEM_Zero );
- assert( pMem->flags&MEM_Blob );
- assert( (pMem->flags&MEM_RowSet)==0 );
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
-
- /* Set nByte to the number of bytes required to store the expanded blob. */
- nByte = pMem->n + pMem->u.nZero;
- if( nByte<=0 ){
- nByte = 1;
- }
- if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
- return SQLITE_NOMEM_BKPT;
- }
-
- memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
- pMem->n += pMem->u.nZero;
- pMem->flags &= ~(MEM_Zero|MEM_Term);
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Make sure the given Mem is \u0000 terminated.
-*/
-int sqlite3VdbeMemNulTerminate(Mem *pMem){
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) );
- testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 );
- if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){
- return SQLITE_OK; /* Nothing to do */
- }else{
- return vdbeMemAddTerminator(pMem);
- }
-}
-
-/*
-** Add MEM_Str to the set of representations for the given Mem. Numbers
-** are converted using sqlite3_snprintf(). Converting a BLOB to a string
-** is a no-op.
-**
-** Existing representations MEM_Int and MEM_Real are invalidated if
-** bForce is true but are retained if bForce is false.
-**
-** A MEM_Null value will never be passed to this function. This function is
-** used for converting values to text for returning to the user (i.e. via
-** sqlite3_value_text()), or for ensuring that values to be used as btree
-** keys are strings. In the former case a NULL pointer is returned the
-** user and the latter is an internal programming error.
-*/
-int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
- int fg = pMem->flags;
- const int nByte = 32;
-
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( !(fg&MEM_Zero) );
- assert( !(fg&(MEM_Str|MEM_Blob)) );
- assert( fg&(MEM_Int|MEM_Real) );
- assert( (pMem->flags&MEM_RowSet)==0 );
- assert( EIGHT_BYTE_ALIGNMENT(pMem) );
-
-
- if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){
- pMem->enc = 0;
- return SQLITE_NOMEM_BKPT;
- }
-
- /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
- ** string representation of the value. Then, if the required encoding
- ** is UTF-16le or UTF-16be do a translation.
- **
- ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
- */
- if( fg & MEM_Int ){
- sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
- }else{
- assert( fg & MEM_Real );
- sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r);
- }
- pMem->n = sqlite3Strlen30(pMem->z);
- pMem->enc = SQLITE_UTF8;
- pMem->flags |= MEM_Str|MEM_Term;
- if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real);
- sqlite3VdbeChangeEncoding(pMem, enc);
- return SQLITE_OK;
-}
-
-/*
-** Memory cell pMem contains the context of an aggregate function.
-** This routine calls the finalize method for that function. The
-** result of the aggregate is stored back into pMem.
-**
-** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK
-** otherwise.
-*/
-int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
- sqlite3_context ctx;
- Mem t;
- assert( pFunc!=0 );
- assert( pFunc->xFinalize!=0 );
- assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- memset(&ctx, 0, sizeof(ctx));
- memset(&t, 0, sizeof(t));
- t.flags = MEM_Null;
- t.db = pMem->db;
- ctx.pOut = &t;
- ctx.pMem = pMem;
- ctx.pFunc = pFunc;
- pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
- assert( (pMem->flags & MEM_Dyn)==0 );
- if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
- memcpy(pMem, &t, sizeof(t));
- return ctx.isError;
-}
-
-/*
-** If the memory cell contains a value that must be freed by
-** invoking the external callback in Mem.xDel, then this routine
-** will free that value. It also sets Mem.flags to MEM_Null.
-**
-** This is a helper routine for sqlite3VdbeMemSetNull() and
-** for sqlite3VdbeMemRelease(). Use those other routines as the
-** entry point for releasing Mem resources.
-*/
-static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){
- assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
- assert( VdbeMemDynamic(p) );
- if( p->flags&MEM_Agg ){
- sqlite3VdbeMemFinalize(p, p->u.pDef);
- assert( (p->flags & MEM_Agg)==0 );
- testcase( p->flags & MEM_Dyn );
- }
- if( p->flags&MEM_Dyn ){
- assert( (p->flags&MEM_RowSet)==0 );
- assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
- p->xDel((void *)p->z);
- }else if( p->flags&MEM_RowSet ){
- sqlite3RowSetClear(p->u.pRowSet);
- }else if( p->flags&MEM_Frame ){
- VdbeFrame *pFrame = p->u.pFrame;
- pFrame->pParent = pFrame->v->pDelFrame;
- pFrame->v->pDelFrame = pFrame;
- }
- p->flags = MEM_Null;
-}
-
-/*
-** Release memory held by the Mem p, both external memory cleared
-** by p->xDel and memory in p->zMalloc.
-**
-** This is a helper routine invoked by sqlite3VdbeMemRelease() in
-** the unusual case where there really is memory in p that needs
-** to be freed.
-*/
-static SQLITE_NOINLINE void vdbeMemClear(Mem *p){
- if( VdbeMemDynamic(p) ){
- vdbeMemClearExternAndSetNull(p);
- }
- if( p->szMalloc ){
- sqlite3DbFreeNN(p->db, p->zMalloc);
- p->szMalloc = 0;
- }
- p->z = 0;
-}
-
-/*
-** Release any memory resources held by the Mem. Both the memory that is
-** free by Mem.xDel and the Mem.zMalloc allocation are freed.
-**
-** Use this routine prior to clean up prior to abandoning a Mem, or to
-** reset a Mem back to its minimum memory utilization.
-**
-** Use sqlite3VdbeMemSetNull() to release just the Mem.xDel space
-** prior to inserting new content into the Mem.
-*/
-void sqlite3VdbeMemRelease(Mem *p){
- assert( sqlite3VdbeCheckMemInvariants(p) );
- if( VdbeMemDynamic(p) || p->szMalloc ){
- vdbeMemClear(p);
- }
-}
-
-/*
-** Convert a 64-bit IEEE double into a 64-bit signed integer.
-** If the double is out of range of a 64-bit signed integer then
-** return the closest available 64-bit signed integer.
-*/
-static SQLITE_NOINLINE i64 doubleToInt64(double r){
-#ifdef SQLITE_OMIT_FLOATING_POINT
- /* When floating-point is omitted, double and int64 are the same thing */
- return r;
-#else
- /*
- ** Many compilers we encounter do not define constants for the
- ** minimum and maximum 64-bit integers, or they define them
- ** inconsistently. And many do not understand the "LL" notation.
- ** So we define our own static constants here using nothing
- ** larger than a 32-bit integer constant.
- */
- static const i64 maxInt = LARGEST_INT64;
- static const i64 minInt = SMALLEST_INT64;
-
- if( r<=(double)minInt ){
- return minInt;
- }else if( r>=(double)maxInt ){
- return maxInt;
- }else{
- return (i64)r;
- }
-#endif
-}
-
-/*
-** Return some kind of integer value which is the best we can do
-** at representing the value that *pMem describes as an integer.
-** If pMem is an integer, then the value is exact. If pMem is
-** a floating-point then the value returned is the integer part.
-** If pMem is a string or blob, then we make an attempt to convert
-** it into an integer and return that. If pMem represents an
-** an SQL-NULL value, return 0.
-**
-** If pMem represents a string value, its encoding might be changed.
-*/
-static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){
- i64 value = 0;
- sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
- return value;
-}
-i64 sqlite3VdbeIntValue(Mem *pMem){
- int flags;
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( EIGHT_BYTE_ALIGNMENT(pMem) );
- flags = pMem->flags;
- if( flags & MEM_Int ){
- return pMem->u.i;
- }else if( flags & MEM_Real ){
- return doubleToInt64(pMem->u.r);
- }else if( flags & (MEM_Str|MEM_Blob) ){
- assert( pMem->z || pMem->n==0 );
- return memIntValue(pMem);
- }else{
- return 0;
- }
-}
-
-/*
-** Return the best representation of pMem that we can get into a
-** double. If pMem is already a double or an integer, return its
-** value. If it is a string or blob, try to convert it to a double.
-** If it is a NULL, return 0.0.
-*/
-static SQLITE_NOINLINE double memRealValue(Mem *pMem){
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- double val = (double)0;
- sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
- return val;
-}
-double sqlite3VdbeRealValue(Mem *pMem){
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( EIGHT_BYTE_ALIGNMENT(pMem) );
- if( pMem->flags & MEM_Real ){
- return pMem->u.r;
- }else if( pMem->flags & MEM_Int ){
- return (double)pMem->u.i;
- }else if( pMem->flags & (MEM_Str|MEM_Blob) ){
- return memRealValue(pMem);
- }else{
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- return (double)0;
- }
-}
-
-/*
-** Return 1 if pMem represents true, and return 0 if pMem represents false.
-** Return the value ifNull if pMem is NULL.
-*/
-int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){
- if( pMem->flags & MEM_Int ) return pMem->u.i!=0;
- if( pMem->flags & MEM_Null ) return ifNull;
- return sqlite3VdbeRealValue(pMem)!=0.0;
-}
-
-/*
-** The MEM structure is already a MEM_Real. Try to also make it a
-** MEM_Int if we can.
-*/
-void sqlite3VdbeIntegerAffinity(Mem *pMem){
- i64 ix;
- assert( pMem->flags & MEM_Real );
- assert( (pMem->flags & MEM_RowSet)==0 );
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( EIGHT_BYTE_ALIGNMENT(pMem) );
-
- ix = doubleToInt64(pMem->u.r);
-
- /* Only mark the value as an integer if
- **
- ** (1) the round-trip conversion real->int->real is a no-op, and
- ** (2) The integer is neither the largest nor the smallest
- ** possible integer (ticket #3922)
- **
- ** The second and third terms in the following conditional enforces
- ** the second condition under the assumption that addition overflow causes
- ** values to wrap around.
- */
- if( pMem->u.r==ix && ix>SMALLEST_INT64 && ix<LARGEST_INT64 ){
- pMem->u.i = ix;
- MemSetTypeFlag(pMem, MEM_Int);
- }
-}
-
-/*
-** Convert pMem to type integer. Invalidate any prior representations.
-*/
-int sqlite3VdbeMemIntegerify(Mem *pMem){
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( (pMem->flags & MEM_RowSet)==0 );
- assert( EIGHT_BYTE_ALIGNMENT(pMem) );
-
- pMem->u.i = sqlite3VdbeIntValue(pMem);
- MemSetTypeFlag(pMem, MEM_Int);
- return SQLITE_OK;
-}
-
-/*
-** Convert pMem so that it is of type MEM_Real.
-** Invalidate any prior representations.
-*/
-int sqlite3VdbeMemRealify(Mem *pMem){
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( EIGHT_BYTE_ALIGNMENT(pMem) );
-
- pMem->u.r = sqlite3VdbeRealValue(pMem);
- MemSetTypeFlag(pMem, MEM_Real);
- return SQLITE_OK;
-}
-
-/* Compare a floating point value to an integer. Return true if the two
-** values are the same within the precision of the floating point value.
-**
-** For some versions of GCC on 32-bit machines, if you do the more obvious
-** comparison of "r1==(double)i" you sometimes get an answer of false even
-** though the r1 and (double)i values are bit-for-bit the same.
-*/
-static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
- double r2 = (double)i;
- return memcmp(&r1, &r2, sizeof(r1))==0;
-}
-
-/*
-** Convert pMem so that it has types MEM_Real or MEM_Int or both.
-** Invalidate any prior representations.
-**
-** Every effort is made to force the conversion, even if the input
-** is a string that does not look completely like a number. Convert
-** as much of the string as we can and ignore the rest.
-*/
-int sqlite3VdbeMemNumerify(Mem *pMem){
- if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
- int rc;
- assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc);
- if( rc==0 ){
- MemSetTypeFlag(pMem, MEM_Int);
- }else{
- i64 i = pMem->u.i;
- sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
- if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){
- pMem->u.i = i;
- MemSetTypeFlag(pMem, MEM_Int);
- }else{
- MemSetTypeFlag(pMem, MEM_Real);
- }
- }
- }
- assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
- pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero);
- return SQLITE_OK;
-}
-
-/*
-** Cast the datatype of the value in pMem according to the affinity
-** "aff". Casting is different from applying affinity in that a cast
-** is forced. In other words, the value is converted into the desired
-** affinity even if that results in loss of data. This routine is
-** used (for example) to implement the SQL "cast()" operator.
-*/
-void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
- if( pMem->flags & MEM_Null ) return;
- switch( aff ){
- case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
- if( (pMem->flags & MEM_Blob)==0 ){
- sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
- assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
- if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob);
- }else{
- pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
- }
- break;
- }
- case SQLITE_AFF_NUMERIC: {
- sqlite3VdbeMemNumerify(pMem);
- break;
- }
- case SQLITE_AFF_INTEGER: {
- sqlite3VdbeMemIntegerify(pMem);
- break;
- }
- case SQLITE_AFF_REAL: {
- sqlite3VdbeMemRealify(pMem);
- break;
- }
- default: {
- assert( aff==SQLITE_AFF_TEXT );
- assert( MEM_Str==(MEM_Blob>>3) );
- pMem->flags |= (pMem->flags&MEM_Blob)>>3;
- sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
- assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
- pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero);
- break;
- }
- }
-}
-
-/*
-** Initialize bulk memory to be a consistent Mem object.
-**
-** The minimum amount of initialization feasible is performed.
-*/
-void sqlite3VdbeMemInit(Mem *pMem, sqlite3 *db, u16 flags){
- assert( (flags & ~MEM_TypeMask)==0 );
- pMem->flags = flags;
- pMem->db = db;
- pMem->szMalloc = 0;
-}
-
-
-/*
-** Delete any previous value and set the value stored in *pMem to NULL.
-**
-** This routine calls the Mem.xDel destructor to dispose of values that
-** require the destructor. But it preserves the Mem.zMalloc memory allocation.
-** To free all resources, use sqlite3VdbeMemRelease(), which both calls this
-** routine to invoke the destructor and deallocates Mem.zMalloc.
-**
-** Use this routine to reset the Mem prior to insert a new value.
-**
-** Use sqlite3VdbeMemRelease() to complete erase the Mem prior to abandoning it.
-*/
-void sqlite3VdbeMemSetNull(Mem *pMem){
- if( VdbeMemDynamic(pMem) ){
- vdbeMemClearExternAndSetNull(pMem);
- }else{
- pMem->flags = MEM_Null;
- }
-}
-void sqlite3ValueSetNull(sqlite3_value *p){
- sqlite3VdbeMemSetNull((Mem*)p);
-}
-
-/*
-** Delete any previous value and set the value to be a BLOB of length
-** n containing all zeros.
-*/
-void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
- sqlite3VdbeMemRelease(pMem);
- pMem->flags = MEM_Blob|MEM_Zero;
- pMem->n = 0;
- if( n<0 ) n = 0;
- pMem->u.nZero = n;
- pMem->enc = SQLITE_UTF8;
- pMem->z = 0;
-}
-
-/*
-** The pMem is known to contain content that needs to be destroyed prior
-** to a value change. So invoke the destructor, then set the value to
-** a 64-bit integer.
-*/
-static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){
- sqlite3VdbeMemSetNull(pMem);
- pMem->u.i = val;
- pMem->flags = MEM_Int;
-}
-
-/*
-** Delete any previous value and set the value stored in *pMem to val,
-** manifest type INTEGER.
-*/
-void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
- if( VdbeMemDynamic(pMem) ){
- vdbeReleaseAndSetInt64(pMem, val);
- }else{
- pMem->u.i = val;
- pMem->flags = MEM_Int;
- }
-}
-
-/* A no-op destructor */
-void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
-
-/*
-** Set the value stored in *pMem should already be a NULL.
-** Also store a pointer to go with it.
-*/
-void sqlite3VdbeMemSetPointer(
- Mem *pMem,
- void *pPtr,
- const char *zPType,
- void (*xDestructor)(void*)
-){
- assert( pMem->flags==MEM_Null );
- pMem->u.zPType = zPType ? zPType : "";
- pMem->z = pPtr;
- pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
- pMem->eSubtype = 'p';
- pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor;
-}
-
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/*
-** Delete any previous value and set the value stored in *pMem to val,
-** manifest type REAL.
-*/
-void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
- sqlite3VdbeMemSetNull(pMem);
- if( !sqlite3IsNaN(val) ){
- pMem->u.r = val;
- pMem->flags = MEM_Real;
- }
-}
-#endif
-
-/*
-** Delete any previous value and set the value of pMem to be an
-** empty boolean index.
-*/
-void sqlite3VdbeMemSetRowSet(Mem *pMem){
- sqlite3 *db = pMem->db;
- assert( db!=0 );
- assert( (pMem->flags & MEM_RowSet)==0 );
- sqlite3VdbeMemRelease(pMem);
- pMem->zMalloc = sqlite3DbMallocRawNN(db, 64);
- if( db->mallocFailed ){
- pMem->flags = MEM_Null;
- pMem->szMalloc = 0;
- }else{
- assert( pMem->zMalloc );
- pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc);
- pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc);
- assert( pMem->u.pRowSet!=0 );
- pMem->flags = MEM_RowSet;
- }
-}
-
-/*
-** Return true if the Mem object contains a TEXT or BLOB that is
-** too large - whose size exceeds SQLITE_MAX_LENGTH.
-*/
-int sqlite3VdbeMemTooBig(Mem *p){
- assert( p->db!=0 );
- if( p->flags & (MEM_Str|MEM_Blob) ){
- int n = p->n;
- if( p->flags & MEM_Zero ){
- n += p->u.nZero;
- }
- return n>p->db->aLimit[SQLITE_LIMIT_LENGTH];
- }
- return 0;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** This routine prepares a memory cell for modification by breaking
-** its link to a shallow copy and by marking any current shallow
-** copies of this cell as invalid.
-**
-** This is used for testing and debugging only - to make sure shallow
-** copies are not misused.
-*/
-void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
- int i;
- Mem *pX;
- for(i=0, pX=pVdbe->aMem; i<pVdbe->nMem; i++, pX++){
- if( pX->pScopyFrom==pMem ){
- pX->flags |= MEM_Undefined;
- pX->pScopyFrom = 0;
- }
- }
- pMem->pScopyFrom = 0;
-}
-#endif /* SQLITE_DEBUG */
-
-
-/*
-** Make an shallow copy of pFrom into pTo. Prior contents of
-** pTo are freed. The pFrom->z field is not duplicated. If
-** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
-** and flags gets srcType (either MEM_Ephem or MEM_Static).
-*/
-static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){
- vdbeMemClearExternAndSetNull(pTo);
- assert( !VdbeMemDynamic(pTo) );
- sqlite3VdbeMemShallowCopy(pTo, pFrom, eType);
-}
-void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
- assert( (pFrom->flags & MEM_RowSet)==0 );
- assert( pTo->db==pFrom->db );
- if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; }
- memcpy(pTo, pFrom, MEMCELLSIZE);
- if( (pFrom->flags&MEM_Static)==0 ){
- pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
- assert( srcType==MEM_Ephem || srcType==MEM_Static );
- pTo->flags |= srcType;
- }
-}
-
-/*
-** Make a full copy of pFrom into pTo. Prior contents of pTo are
-** freed before the copy is made.
-*/
-int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
- int rc = SQLITE_OK;
-
- assert( (pFrom->flags & MEM_RowSet)==0 );
- if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo);
- memcpy(pTo, pFrom, MEMCELLSIZE);
- pTo->flags &= ~MEM_Dyn;
- if( pTo->flags&(MEM_Str|MEM_Blob) ){
- if( 0==(pFrom->flags&MEM_Static) ){
- pTo->flags |= MEM_Ephem;
- rc = sqlite3VdbeMemMakeWriteable(pTo);
- }
- }
-
- return rc;
-}
-
-/*
-** Transfer the contents of pFrom to pTo. Any existing value in pTo is
-** freed. If pFrom contains ephemeral data, a copy is made.
-**
-** pFrom contains an SQL NULL when this routine returns.
-*/
-void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
- assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) );
- assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) );
- assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db );
-
- sqlite3VdbeMemRelease(pTo);
- memcpy(pTo, pFrom, sizeof(Mem));
- pFrom->flags = MEM_Null;
- pFrom->szMalloc = 0;
-}
-
-/*
-** Change the value of a Mem to be a string or a BLOB.
-**
-** The memory management strategy depends on the value of the xDel
-** parameter. If the value passed is SQLITE_TRANSIENT, then the
-** string is copied into a (possibly existing) buffer managed by the
-** Mem structure. Otherwise, any existing buffer is freed and the
-** pointer copied.
-**
-** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
-** size limit) then no memory allocation occurs. If the string can be
-** stored without allocating memory, then it is. If a memory allocation
-** is required to store the string, then value of pMem is unchanged. In
-** either case, SQLITE_TOOBIG is returned.
-*/
-int sqlite3VdbeMemSetStr(
- Mem *pMem, /* Memory cell to set to string value */
- const char *z, /* String pointer */
- int n, /* Bytes in string, or negative */
- u8 enc, /* Encoding of z. 0 for BLOBs */
- void (*xDel)(void*) /* Destructor function */
-){
- int nByte = n; /* New value for pMem->n */
- int iLimit; /* Maximum allowed string or blob size */
- u16 flags = 0; /* New value for pMem->flags */
-
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( (pMem->flags & MEM_RowSet)==0 );
-
- /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
- if( !z ){
- sqlite3VdbeMemSetNull(pMem);
- return SQLITE_OK;
- }
-
- if( pMem->db ){
- iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH];
- }else{
- iLimit = SQLITE_MAX_LENGTH;
- }
- flags = (enc==0?MEM_Blob:MEM_Str);
- if( nByte<0 ){
- assert( enc!=0 );
- if( enc==SQLITE_UTF8 ){
- nByte = 0x7fffffff & (int)strlen(z);
- if( nByte>iLimit ) nByte = iLimit+1;
- }else{
- for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
- }
- flags |= MEM_Term;
- }
-
- /* The following block sets the new values of Mem.z and Mem.xDel. It
- ** also sets a flag in local variable "flags" to indicate the memory
- ** management (one of MEM_Dyn or MEM_Static).
- */
- if( xDel==SQLITE_TRANSIENT ){
- int nAlloc = nByte;
- if( flags&MEM_Term ){
- nAlloc += (enc==SQLITE_UTF8?1:2);
- }
- if( nByte>iLimit ){
- return SQLITE_TOOBIG;
- }
- testcase( nAlloc==0 );
- testcase( nAlloc==31 );
- testcase( nAlloc==32 );
- if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){
- return SQLITE_NOMEM_BKPT;
- }
- memcpy(pMem->z, z, nAlloc);
- }else if( xDel==SQLITE_DYNAMIC ){
- sqlite3VdbeMemRelease(pMem);
- pMem->zMalloc = pMem->z = (char *)z;
- pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
- }else{
- sqlite3VdbeMemRelease(pMem);
- pMem->z = (char *)z;
- pMem->xDel = xDel;
- flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
- }
-
- pMem->n = nByte;
- pMem->flags = flags;
- pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
-
-#ifndef SQLITE_OMIT_UTF16
- if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
- return SQLITE_NOMEM_BKPT;
- }
-#endif
-
- if( nByte>iLimit ){
- return SQLITE_TOOBIG;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Move data out of a btree key or data field and into a Mem structure.
-** The data is payload from the entry that pCur is currently pointing
-** to. offset and amt determine what portion of the data or key to retrieve.
-** The result is written into the pMem element.
-**
-** The pMem object must have been initialized. This routine will use
-** pMem->zMalloc to hold the content from the btree, if possible. New
-** pMem->zMalloc space will be allocated if necessary. The calling routine
-** is responsible for making sure that the pMem object is eventually
-** destroyed.
-**
-** If this routine fails for any reason (malloc returns NULL or unable
-** to read from the disk) then the pMem is left in an inconsistent state.
-*/
-static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
- BtCursor *pCur, /* Cursor pointing at record to retrieve. */
- u32 offset, /* Offset from the start of data to return bytes from. */
- u32 amt, /* Number of bytes to return. */
- Mem *pMem /* OUT: Return data in this Mem structure. */
-){
- int rc;
- pMem->flags = MEM_Null;
- if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
- rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
- if( rc==SQLITE_OK ){
- pMem->z[amt] = 0; /* Overrun area used when reading malformed records */
- pMem->flags = MEM_Blob;
- pMem->n = (int)amt;
- }else{
- sqlite3VdbeMemRelease(pMem);
- }
- }
- return rc;
-}
-int sqlite3VdbeMemFromBtree(
- BtCursor *pCur, /* Cursor pointing at record to retrieve. */
- u32 offset, /* Offset from the start of data to return bytes from. */
- u32 amt, /* Number of bytes to return. */
- Mem *pMem /* OUT: Return data in this Mem structure. */
-){
- char *zData; /* Data from the btree layer */
- u32 available = 0; /* Number of bytes available on the local btree page */
- int rc = SQLITE_OK; /* Return code */
-
- assert( sqlite3BtreeCursorIsValid(pCur) );
- assert( !VdbeMemDynamic(pMem) );
-
- /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
- ** that both the BtShared and database handle mutexes are held. */
- assert( (pMem->flags & MEM_RowSet)==0 );
- zData = (char *)sqlite3BtreePayloadFetch(pCur, &available);
- assert( zData!=0 );
-
- if( offset+amt<=available ){
- pMem->z = &zData[offset];
- pMem->flags = MEM_Blob|MEM_Ephem;
- pMem->n = (int)amt;
- }else{
- rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem);
- }
-
- return rc;
-}
-
-/*
-** The pVal argument is known to be a value other than NULL.
-** Convert it into a string with encoding enc and return a pointer
-** to a zero-terminated version of that string.
-*/
-static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
- assert( pVal!=0 );
- assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
- assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
- assert( (pVal->flags & MEM_RowSet)==0 );
- assert( (pVal->flags & (MEM_Null))==0 );
- if( pVal->flags & (MEM_Blob|MEM_Str) ){
- if( ExpandBlob(pVal) ) return 0;
- pVal->flags |= MEM_Str;
- if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){
- sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
- }
- if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){
- assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );
- if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){
- return 0;
- }
- }
- sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */
- }else{
- sqlite3VdbeMemStringify(pVal, enc, 0);
- assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) );
- }
- assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
- || pVal->db->mallocFailed );
- if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
- assert( sqlite3VdbeMemConsistentDualRep(pVal) );
- return pVal->z;
- }else{
- return 0;
- }
-}
-
-/* This function is only available internally, it is not part of the
-** external API. It works in a similar way to sqlite3_value_text(),
-** except the data returned is in the encoding specified by the second
-** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or
-** SQLITE_UTF8.
-**
-** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED.
-** If that is the case, then the result must be aligned on an even byte
-** boundary.
-*/
-const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
- if( !pVal ) return 0;
- assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
- assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
- assert( (pVal->flags & MEM_RowSet)==0 );
- if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){
- assert( sqlite3VdbeMemConsistentDualRep(pVal) );
- return pVal->z;
- }
- if( pVal->flags&MEM_Null ){
- return 0;
- }
- return valueToText(pVal, enc);
-}
-
-/*
-** Create a new sqlite3_value object.
-*/
-sqlite3_value *sqlite3ValueNew(sqlite3 *db){
- Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
- if( p ){
- p->flags = MEM_Null;
- p->db = db;
- }
- return p;
-}
-
-/*
-** Context object passed by sqlite3Stat4ProbeSetValue() through to
-** valueNew(). See comments above valueNew() for details.
-*/
-struct ValueNewStat4Ctx {
- Parse *pParse;
- Index *pIdx;
- UnpackedRecord **ppRec;
- int iVal;
-};
-
-/*
-** Allocate and return a pointer to a new sqlite3_value object. If
-** the second argument to this function is NULL, the object is allocated
-** by calling sqlite3ValueNew().
-**
-** Otherwise, if the second argument is non-zero, then this function is
-** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
-** already been allocated, allocate the UnpackedRecord structure that
-** that function will return to its caller here. Then return a pointer to
-** an sqlite3_value within the UnpackedRecord.a[] array.
-*/
-static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( p ){
- UnpackedRecord *pRec = p->ppRec[0];
-
- if( pRec==0 ){
- Index *pIdx = p->pIdx; /* Index being probed */
- int nByte; /* Bytes of space to allocate */
- int i; /* Counter variable */
- int nCol = pIdx->nColumn; /* Number of index columns including rowid */
-
- nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord));
- pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
- if( pRec ){
- pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
- if( pRec->pKeyInfo ){
- assert( pRec->pKeyInfo->nAllField==nCol );
- assert( pRec->pKeyInfo->enc==ENC(db) );
- pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
- for(i=0; i<nCol; i++){
- pRec->aMem[i].flags = MEM_Null;
- pRec->aMem[i].db = db;
- }
- }else{
- sqlite3DbFreeNN(db, pRec);
- pRec = 0;
- }
- }
- if( pRec==0 ) return 0;
- p->ppRec[0] = pRec;
- }
-
- pRec->nField = p->iVal+1;
- return &pRec->aMem[p->iVal];
- }
-#else
- UNUSED_PARAMETER(p);
-#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
- return sqlite3ValueNew(db);
-}
-
-/*
-** The expression object indicated by the second argument is guaranteed
-** to be a scalar SQL function. If
-**
-** * all function arguments are SQL literals,
-** * one of the SQLITE_FUNC_CONSTANT or _SLOCHNG function flags is set, and
-** * the SQLITE_FUNC_NEEDCOLL function flag is not set,
-**
-** then this routine attempts to invoke the SQL function. Assuming no
-** error occurs, output parameter (*ppVal) is set to point to a value
-** object containing the result before returning SQLITE_OK.
-**
-** Affinity aff is applied to the result of the function before returning.
-** If the result is a text value, the sqlite3_value object uses encoding
-** enc.
-**
-** If the conditions above are not met, this function returns SQLITE_OK
-** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
-** NULL and an SQLite error code returned.
-*/
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-static int valueFromFunction(
- sqlite3 *db, /* The database connection */
- Expr *p, /* The expression to evaluate */
- u8 enc, /* Encoding to use */
- u8 aff, /* Affinity to use */
- sqlite3_value **ppVal, /* Write the new value here */
- struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */
-){
- sqlite3_context ctx; /* Context object for function invocation */
- sqlite3_value **apVal = 0; /* Function arguments */
- int nVal = 0; /* Size of apVal[] array */
- FuncDef *pFunc = 0; /* Function definition */
- sqlite3_value *pVal = 0; /* New value */
- int rc = SQLITE_OK; /* Return code */
- ExprList *pList = 0; /* Function arguments */
- int i; /* Iterator variable */
-
- assert( pCtx!=0 );
- assert( (p->flags & EP_TokenOnly)==0 );
- pList = p->x.pList;
- if( pList ) nVal = pList->nExpr;
- pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0);
- assert( pFunc );
- if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
- || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
- ){
- return SQLITE_OK;
- }
-
- if( pList ){
- apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal);
- if( apVal==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto value_from_function_out;
- }
- for(i=0; i<nVal; i++){
- rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]);
- if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
- }
- }
-
- pVal = valueNew(db, pCtx);
- if( pVal==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto value_from_function_out;
- }
-
- assert( pCtx->pParse->rc==SQLITE_OK );
- memset(&ctx, 0, sizeof(ctx));
- ctx.pOut = pVal;
- ctx.pFunc = pFunc;
- pFunc->xSFunc(&ctx, nVal, apVal);
- if( ctx.isError ){
- rc = ctx.isError;
- sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
- }else{
- sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
- assert( rc==SQLITE_OK );
- rc = sqlite3VdbeChangeEncoding(pVal, enc);
- if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
- rc = SQLITE_TOOBIG;
- pCtx->pParse->nErr++;
- }
- }
- pCtx->pParse->rc = rc;
-
- value_from_function_out:
- if( rc!=SQLITE_OK ){
- pVal = 0;
- }
- if( apVal ){
- for(i=0; i<nVal; i++){
- sqlite3ValueFree(apVal[i]);
- }
- sqlite3DbFreeNN(db, apVal);
- }
-
- *ppVal = pVal;
- return rc;
-}
-#else
-# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
-#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
-
-/*
-** Extract a value from the supplied expression in the manner described
-** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
-** using valueNew().
-**
-** If pCtx is NULL and an error occurs after the sqlite3_value object
-** has been allocated, it is freed before returning. Or, if pCtx is not
-** NULL, it is assumed that the caller will free any allocated object
-** in all cases.
-*/
-static int valueFromExpr(
- sqlite3 *db, /* The database connection */
- Expr *pExpr, /* The expression to evaluate */
- u8 enc, /* Encoding to use */
- u8 affinity, /* Affinity to use */
- sqlite3_value **ppVal, /* Write the new value here */
- struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */
-){
- int op;
- char *zVal = 0;
- sqlite3_value *pVal = 0;
- int negInt = 1;
- const char *zNeg = "";
- int rc = SQLITE_OK;
-
- assert( pExpr!=0 );
- while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
-#if defined(SQLITE_ENABLE_STAT3_OR_STAT4)
- if( op==TK_REGISTER ) op = pExpr->op2;
-#else
- if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
-#endif
-
- /* Compressed expressions only appear when parsing the DEFAULT clause
- ** on a table column definition, and hence only when pCtx==0. This
- ** check ensures that an EP_TokenOnly expression is never passed down
- ** into valueFromFunction(). */
- assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );
-
- if( op==TK_CAST ){
- u8 aff = sqlite3AffinityType(pExpr->u.zToken,0);
- rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
- testcase( rc!=SQLITE_OK );
- if( *ppVal ){
- sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8);
- sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8);
- }
- return rc;
- }
-
- /* Handle negative integers in a single step. This is needed in the
- ** case when the value is -9223372036854775808.
- */
- if( op==TK_UMINUS
- && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
- pExpr = pExpr->pLeft;
- op = pExpr->op;
- negInt = -1;
- zNeg = "-";
- }
-
- if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
- pVal = valueNew(db, pCtx);
- if( pVal==0 ) goto no_mem;
- if( ExprHasProperty(pExpr, EP_IntValue) ){
- sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
- }else{
- zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
- if( zVal==0 ) goto no_mem;
- sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
- }
- if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){
- sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
- }else{
- sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
- }
- if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
- if( enc!=SQLITE_UTF8 ){
- rc = sqlite3VdbeChangeEncoding(pVal, enc);
- }
- }else if( op==TK_UMINUS ) {
- /* This branch happens for multiple negative signs. Ex: -(-5) */
- if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx)
- && pVal!=0
- ){
- sqlite3VdbeMemNumerify(pVal);
- if( pVal->flags & MEM_Real ){
- pVal->u.r = -pVal->u.r;
- }else if( pVal->u.i==SMALLEST_INT64 ){
- pVal->u.r = -(double)SMALLEST_INT64;
- MemSetTypeFlag(pVal, MEM_Real);
- }else{
- pVal->u.i = -pVal->u.i;
- }
- sqlite3ValueApplyAffinity(pVal, affinity, enc);
- }
- }else if( op==TK_NULL ){
- pVal = valueNew(db, pCtx);
- if( pVal==0 ) goto no_mem;
- sqlite3VdbeMemNumerify(pVal);
- }
-#ifndef SQLITE_OMIT_BLOB_LITERAL
- else if( op==TK_BLOB ){
- int nVal;
- assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
- assert( pExpr->u.zToken[1]=='\'' );
- pVal = valueNew(db, pCtx);
- if( !pVal ) goto no_mem;
- zVal = &pExpr->u.zToken[2];
- nVal = sqlite3Strlen30(zVal)-1;
- assert( zVal[nVal]=='\'' );
- sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
- 0, SQLITE_DYNAMIC);
- }
-#endif
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- else if( op==TK_FUNCTION && pCtx!=0 ){
- rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
- }
-#endif
- else if( op==TK_TRUEFALSE ){
- pVal = valueNew(db, pCtx);
- pVal->flags = MEM_Int;
- pVal->u.i = pExpr->u.zToken[4]==0;
- }
-
- *ppVal = pVal;
- return rc;
-
-no_mem:
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( pCtx==0 || pCtx->pParse->nErr==0 )
-#endif
- sqlite3OomFault(db);
- sqlite3DbFree(db, zVal);
- assert( *ppVal==0 );
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( pCtx==0 ) sqlite3ValueFree(pVal);
-#else
- assert( pCtx==0 ); sqlite3ValueFree(pVal);
-#endif
- return SQLITE_NOMEM_BKPT;
-}
-
-/*
-** Create a new sqlite3_value object, containing the value of pExpr.
-**
-** This only works for very simple expressions that consist of one constant
-** token (i.e. "5", "5.1", "'a string'"). If the expression can
-** be converted directly into a value, then the value is allocated and
-** a pointer written to *ppVal. The caller is responsible for deallocating
-** the value by passing it to sqlite3ValueFree() later on. If the expression
-** cannot be converted to a value, then *ppVal is set to NULL.
-*/
-int sqlite3ValueFromExpr(
- sqlite3 *db, /* The database connection */
- Expr *pExpr, /* The expression to evaluate */
- u8 enc, /* Encoding to use */
- u8 affinity, /* Affinity to use */
- sqlite3_value **ppVal /* Write the new value here */
-){
- return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
-}
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** The implementation of the sqlite_record() function. This function accepts
-** a single argument of any type. The return value is a formatted database
-** record (a blob) containing the argument value.
-**
-** This is used to convert the value stored in the 'sample' column of the
-** sqlite_stat3 table to the record format SQLite uses internally.
-*/
-static void recordFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const int file_format = 1;
- u32 iSerial; /* Serial type */
- int nSerial; /* Bytes of space for iSerial as varint */
- u32 nVal; /* Bytes of space required for argv[0] */
- int nRet;
- sqlite3 *db;
- u8 *aRet;
-
- UNUSED_PARAMETER( argc );
- iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
- nSerial = sqlite3VarintLen(iSerial);
- db = sqlite3_context_db_handle(context);
-
- nRet = 1 + nSerial + nVal;
- aRet = sqlite3DbMallocRawNN(db, nRet);
- if( aRet==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- aRet[0] = nSerial+1;
- putVarint32(&aRet[1], iSerial);
- sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
- sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
- sqlite3DbFreeNN(db, aRet);
- }
-}
-
-/*
-** Register built-in functions used to help read ANALYZE data.
-*/
-void sqlite3AnalyzeFunctions(void){
- static FuncDef aAnalyzeTableFuncs[] = {
- FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
- };
- sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs, ArraySize(aAnalyzeTableFuncs));
-}
-
-/*
-** Attempt to extract a value from pExpr and use it to construct *ppVal.
-**
-** If pAlloc is not NULL, then an UnpackedRecord object is created for
-** pAlloc if one does not exist and the new value is added to the
-** UnpackedRecord object.
-**
-** A value is extracted in the following cases:
-**
-** * (pExpr==0). In this case the value is assumed to be an SQL NULL,
-**
-** * The expression is a bound variable, and this is a reprepare, or
-**
-** * The expression is a literal value.
-**
-** On success, *ppVal is made to point to the extracted value. The caller
-** is responsible for ensuring that the value is eventually freed.
-*/
-static int stat4ValueFromExpr(
- Parse *pParse, /* Parse context */
- Expr *pExpr, /* The expression to extract a value from */
- u8 affinity, /* Affinity to use */
- struct ValueNewStat4Ctx *pAlloc,/* How to allocate space. Or NULL */
- sqlite3_value **ppVal /* OUT: New value object (or NULL) */
-){
- int rc = SQLITE_OK;
- sqlite3_value *pVal = 0;
- sqlite3 *db = pParse->db;
-
- /* Skip over any TK_COLLATE nodes */
- pExpr = sqlite3ExprSkipCollate(pExpr);
-
- assert( pExpr==0 || pExpr->op!=TK_REGISTER || pExpr->op2!=TK_VARIABLE );
- if( !pExpr ){
- pVal = valueNew(db, pAlloc);
- if( pVal ){
- sqlite3VdbeMemSetNull((Mem*)pVal);
- }
- }else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
- Vdbe *v;
- int iBindVar = pExpr->iColumn;
- sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
- if( (v = pParse->pReprepare)!=0 ){
- pVal = valueNew(db, pAlloc);
- if( pVal ){
- rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
- sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
- pVal->db = pParse->db;
- }
- }
- }else{
- rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, pAlloc);
- }
-
- assert( pVal==0 || pVal->db==db );
- *ppVal = pVal;
- return rc;
-}
-
-/*
-** This function is used to allocate and populate UnpackedRecord
-** structures intended to be compared against sample index keys stored
-** in the sqlite_stat4 table.
-**
-** A single call to this function populates zero or more fields of the
-** record starting with field iVal (fields are numbered from left to
-** right starting with 0). A single field is populated if:
-**
-** * (pExpr==0). In this case the value is assumed to be an SQL NULL,
-**
-** * The expression is a bound variable, and this is a reprepare, or
-**
-** * The sqlite3ValueFromExpr() function is able to extract a value
-** from the expression (i.e. the expression is a literal value).
-**
-** Or, if pExpr is a TK_VECTOR, one field is populated for each of the
-** vector components that match either of the two latter criteria listed
-** above.
-**
-** Before any value is appended to the record, the affinity of the
-** corresponding column within index pIdx is applied to it. Before
-** this function returns, output parameter *pnExtract is set to the
-** number of values appended to the record.
-**
-** When this function is called, *ppRec must either point to an object
-** allocated by an earlier call to this function, or must be NULL. If it
-** is NULL and a value can be successfully extracted, a new UnpackedRecord
-** is allocated (and *ppRec set to point to it) before returning.
-**
-** Unless an error is encountered, SQLITE_OK is returned. It is not an
-** error if a value cannot be extracted from pExpr. If an error does
-** occur, an SQLite error code is returned.
-*/
-int sqlite3Stat4ProbeSetValue(
- Parse *pParse, /* Parse context */
- Index *pIdx, /* Index being probed */
- UnpackedRecord **ppRec, /* IN/OUT: Probe record */
- Expr *pExpr, /* The expression to extract a value from */
- int nElem, /* Maximum number of values to append */
- int iVal, /* Array element to populate */
- int *pnExtract /* OUT: Values appended to the record */
-){
- int rc = SQLITE_OK;
- int nExtract = 0;
-
- if( pExpr==0 || pExpr->op!=TK_SELECT ){
- int i;
- struct ValueNewStat4Ctx alloc;
-
- alloc.pParse = pParse;
- alloc.pIdx = pIdx;
- alloc.ppRec = ppRec;
-
- for(i=0; i<nElem; i++){
- sqlite3_value *pVal = 0;
- Expr *pElem = (pExpr ? sqlite3VectorFieldSubexpr(pExpr, i) : 0);
- u8 aff = sqlite3IndexColumnAffinity(pParse->db, pIdx, iVal+i);
- alloc.iVal = iVal+i;
- rc = stat4ValueFromExpr(pParse, pElem, aff, &alloc, &pVal);
- if( !pVal ) break;
- nExtract++;
- }
- }
-
- *pnExtract = nExtract;
- return rc;
-}
-
-/*
-** Attempt to extract a value from expression pExpr using the methods
-** as described for sqlite3Stat4ProbeSetValue() above.
-**
-** If successful, set *ppVal to point to a new value object and return
-** SQLITE_OK. If no value can be extracted, but no other error occurs
-** (e.g. OOM), return SQLITE_OK and set *ppVal to NULL. Or, if an error
-** does occur, return an SQLite error code. The final value of *ppVal
-** is undefined in this case.
-*/
-int sqlite3Stat4ValueFromExpr(
- Parse *pParse, /* Parse context */
- Expr *pExpr, /* The expression to extract a value from */
- u8 affinity, /* Affinity to use */
- sqlite3_value **ppVal /* OUT: New value object (or NULL) */
-){
- return stat4ValueFromExpr(pParse, pExpr, affinity, 0, ppVal);
-}
-
-/*
-** Extract the iCol-th column from the nRec-byte record in pRec. Write
-** the column value into *ppVal. If *ppVal is initially NULL then a new
-** sqlite3_value object is allocated.
-**
-** If *ppVal is initially NULL then the caller is responsible for
-** ensuring that the value written into *ppVal is eventually freed.
-*/
-int sqlite3Stat4Column(
- sqlite3 *db, /* Database handle */
- const void *pRec, /* Pointer to buffer containing record */
- int nRec, /* Size of buffer pRec in bytes */
- int iCol, /* Column to extract */
- sqlite3_value **ppVal /* OUT: Extracted value */
-){
- u32 t; /* a column type code */
- int nHdr; /* Size of the header in the record */
- int iHdr; /* Next unread header byte */
- int iField; /* Next unread data byte */
- int szField; /* Size of the current data field */
- int i; /* Column index */
- u8 *a = (u8*)pRec; /* Typecast byte array */
- Mem *pMem = *ppVal; /* Write result into this Mem object */
-
- assert( iCol>0 );
- iHdr = getVarint32(a, nHdr);
- if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
- iField = nHdr;
- for(i=0; i<=iCol; i++){
- iHdr += getVarint32(&a[iHdr], t);
- testcase( iHdr==nHdr );
- testcase( iHdr==nHdr+1 );
- if( iHdr>nHdr ) return SQLITE_CORRUPT_BKPT;
- szField = sqlite3VdbeSerialTypeLen(t);
- iField += szField;
- }
- testcase( iField==nRec );
- testcase( iField==nRec+1 );
- if( iField>nRec ) return SQLITE_CORRUPT_BKPT;
- if( pMem==0 ){
- pMem = *ppVal = sqlite3ValueNew(db);
- if( pMem==0 ) return SQLITE_NOMEM_BKPT;
- }
- sqlite3VdbeSerialGet(&a[iField-szField], t, pMem);
- pMem->enc = ENC(db);
- return SQLITE_OK;
-}
-
-/*
-** Unless it is NULL, the argument must be an UnpackedRecord object returned
-** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes
-** the object.
-*/
-void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
- if( pRec ){
- int i;
- int nCol = pRec->pKeyInfo->nAllField;
- Mem *aMem = pRec->aMem;
- sqlite3 *db = aMem[0].db;
- for(i=0; i<nCol; i++){
- sqlite3VdbeMemRelease(&aMem[i]);
- }
- sqlite3KeyInfoUnref(pRec->pKeyInfo);
- sqlite3DbFreeNN(db, pRec);
- }
-}
-#endif /* ifdef SQLITE_ENABLE_STAT4 */
-
-/*
-** Change the string value of an sqlite3_value object
-*/
-void sqlite3ValueSetStr(
- sqlite3_value *v, /* Value to be set */
- int n, /* Length of string z */
- const void *z, /* Text of the new string */
- u8 enc, /* Encoding to use */
- void (*xDel)(void*) /* Destructor for the string */
-){
- if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel);
-}
-
-/*
-** Free an sqlite3_value object
-*/
-void sqlite3ValueFree(sqlite3_value *v){
- if( !v ) return;
- sqlite3VdbeMemRelease((Mem *)v);
- sqlite3DbFreeNN(((Mem*)v)->db, v);
-}
-
-/*
-** The sqlite3ValueBytes() routine returns the number of bytes in the
-** sqlite3_value object assuming that it uses the encoding "enc".
-** The valueBytes() routine is a helper function.
-*/
-static SQLITE_NOINLINE int valueBytes(sqlite3_value *pVal, u8 enc){
- return valueToText(pVal, enc)!=0 ? pVal->n : 0;
-}
-int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
- Mem *p = (Mem*)pVal;
- assert( (p->flags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 );
- if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){
- return p->n;
- }
- if( (p->flags & MEM_Blob)!=0 ){
- if( p->flags & MEM_Zero ){
- return p->n + p->u.nZero;
- }else{
- return p->n;
- }
- }
- if( p->flags & MEM_Null ) return 0;
- return valueBytes(pVal, enc);
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbesort.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbesort.c
deleted file mode 100644
index ef5715d2498..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbesort.c
+++ /dev/null
@@ -1,2750 +0,0 @@
-/*
-** 2011-07-09
-**
-** 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 contains code for the VdbeSorter object, used in concert with
-** a VdbeCursor to sort large numbers of keys for CREATE INDEX statements
-** or by SELECT statements with ORDER BY clauses that cannot be satisfied
-** using indexes and without LIMIT clauses.
-**
-** The VdbeSorter object implements a multi-threaded external merge sort
-** algorithm that is efficient even if the number of elements being sorted
-** exceeds the available memory.
-**
-** Here is the (internal, non-API) interface between this module and the
-** rest of the SQLite system:
-**
-** sqlite3VdbeSorterInit() Create a new VdbeSorter object.
-**
-** sqlite3VdbeSorterWrite() Add a single new row to the VdbeSorter
-** object. The row is a binary blob in the
-** OP_MakeRecord format that contains both
-** the ORDER BY key columns and result columns
-** in the case of a SELECT w/ ORDER BY, or
-** the complete record for an index entry
-** in the case of a CREATE INDEX.
-**
-** sqlite3VdbeSorterRewind() Sort all content previously added.
-** Position the read cursor on the
-** first sorted element.
-**
-** sqlite3VdbeSorterNext() Advance the read cursor to the next sorted
-** element.
-**
-** sqlite3VdbeSorterRowkey() Return the complete binary blob for the
-** row currently under the read cursor.
-**
-** sqlite3VdbeSorterCompare() Compare the binary blob for the row
-** currently under the read cursor against
-** another binary blob X and report if
-** X is strictly less than the read cursor.
-** Used to enforce uniqueness in a
-** CREATE UNIQUE INDEX statement.
-**
-** sqlite3VdbeSorterClose() Close the VdbeSorter object and reclaim
-** all resources.
-**
-** sqlite3VdbeSorterReset() Refurbish the VdbeSorter for reuse. This
-** is like Close() followed by Init() only
-** much faster.
-**
-** The interfaces above must be called in a particular order. Write() can
-** only occur in between Init()/Reset() and Rewind(). Next(), Rowkey(), and
-** Compare() can only occur in between Rewind() and Close()/Reset(). i.e.
-**
-** Init()
-** for each record: Write()
-** Rewind()
-** Rowkey()/Compare()
-** Next()
-** Close()
-**
-** Algorithm:
-**
-** Records passed to the sorter via calls to Write() are initially held
-** unsorted in main memory. Assuming the amount of memory used never exceeds
-** a threshold, when Rewind() is called the set of records is sorted using
-** an in-memory merge sort. In this case, no temporary files are required
-** and subsequent calls to Rowkey(), Next() and Compare() read records
-** directly from main memory.
-**
-** If the amount of space used to store records in main memory exceeds the
-** threshold, then the set of records currently in memory are sorted and
-** written to a temporary file in "Packed Memory Array" (PMA) format.
-** A PMA created at this point is known as a "level-0 PMA". Higher levels
-** of PMAs may be created by merging existing PMAs together - for example
-** merging two or more level-0 PMAs together creates a level-1 PMA.
-**
-** The threshold for the amount of main memory to use before flushing
-** records to a PMA is roughly the same as the limit configured for the
-** page-cache of the main database. Specifically, the threshold is set to
-** the value returned by "PRAGMA main.page_size" multipled by
-** that returned by "PRAGMA main.cache_size", in bytes.
-**
-** If the sorter is running in single-threaded mode, then all PMAs generated
-** are appended to a single temporary file. Or, if the sorter is running in
-** multi-threaded mode then up to (N+1) temporary files may be opened, where
-** N is the configured number of worker threads. In this case, instead of
-** sorting the records and writing the PMA to a temporary file itself, the
-** calling thread usually launches a worker thread to do so. Except, if
-** there are already N worker threads running, the main thread does the work
-** itself.
-**
-** The sorter is running in multi-threaded mode if (a) the library was built
-** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater
-** than zero, and (b) worker threads have been enabled at runtime by calling
-** "PRAGMA threads=N" with some value of N greater than 0.
-**
-** When Rewind() is called, any data remaining in memory is flushed to a
-** final PMA. So at this point the data is stored in some number of sorted
-** PMAs within temporary files on disk.
-**
-** If there are fewer than SORTER_MAX_MERGE_COUNT PMAs in total and the
-** sorter is running in single-threaded mode, then these PMAs are merged
-** incrementally as keys are retreived from the sorter by the VDBE. The
-** MergeEngine object, described in further detail below, performs this
-** merge.
-**
-** Or, if running in multi-threaded mode, then a background thread is
-** launched to merge the existing PMAs. Once the background thread has
-** merged T bytes of data into a single sorted PMA, the main thread
-** begins reading keys from that PMA while the background thread proceeds
-** with merging the next T bytes of data. And so on.
-**
-** Parameter T is set to half the value of the memory threshold used
-** by Write() above to determine when to create a new PMA.
-**
-** If there are more than SORTER_MAX_MERGE_COUNT PMAs in total when
-** Rewind() is called, then a hierarchy of incremental-merges is used.
-** First, T bytes of data from the first SORTER_MAX_MERGE_COUNT PMAs on
-** disk are merged together. Then T bytes of data from the second set, and
-** so on, such that no operation ever merges more than SORTER_MAX_MERGE_COUNT
-** PMAs at a time. This done is to improve locality.
-**
-** If running in multi-threaded mode and there are more than
-** SORTER_MAX_MERGE_COUNT PMAs on disk when Rewind() is called, then more
-** than one background thread may be created. Specifically, there may be
-** one background thread for each temporary file on disk, and one background
-** thread to merge the output of each of the others to a single PMA for
-** the main thread to read from.
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-/*
-** If SQLITE_DEBUG_SORTER_THREADS is defined, this module outputs various
-** messages to stderr that may be helpful in understanding the performance
-** characteristics of the sorter in multi-threaded mode.
-*/
-#if 0
-# define SQLITE_DEBUG_SORTER_THREADS 1
-#endif
-
-/*
-** Hard-coded maximum amount of data to accumulate in memory before flushing
-** to a level 0 PMA. The purpose of this limit is to prevent various integer
-** overflows. 512MiB.
-*/
-#define SQLITE_MAX_PMASZ (1<<29)
-
-/*
-** Private objects used by the sorter
-*/
-typedef struct MergeEngine MergeEngine; /* Merge PMAs together */
-typedef struct PmaReader PmaReader; /* Incrementally read one PMA */
-typedef struct PmaWriter PmaWriter; /* Incrementally write one PMA */
-typedef struct SorterRecord SorterRecord; /* A record being sorted */
-typedef struct SortSubtask SortSubtask; /* A sub-task in the sort process */
-typedef struct SorterFile SorterFile; /* Temporary file object wrapper */
-typedef struct SorterList SorterList; /* In-memory list of records */
-typedef struct IncrMerger IncrMerger; /* Read & merge multiple PMAs */
-
-/*
-** A container for a temp file handle and the current amount of data
-** stored in the file.
-*/
-struct SorterFile {
- sqlite3_file *pFd; /* File handle */
- i64 iEof; /* Bytes of data stored in pFd */
-};
-
-/*
-** An in-memory list of objects to be sorted.
-**
-** If aMemory==0 then each object is allocated separately and the objects
-** are connected using SorterRecord.u.pNext. If aMemory!=0 then all objects
-** are stored in the aMemory[] bulk memory, one right after the other, and
-** are connected using SorterRecord.u.iNext.
-*/
-struct SorterList {
- SorterRecord *pList; /* Linked list of records */
- u8 *aMemory; /* If non-NULL, bulk memory to hold pList */
- int szPMA; /* Size of pList as PMA in bytes */
-};
-
-/*
-** The MergeEngine object is used to combine two or more smaller PMAs into
-** one big PMA using a merge operation. Separate PMAs all need to be
-** combined into one big PMA in order to be able to step through the sorted
-** records in order.
-**
-** The aReadr[] array contains a PmaReader object for each of the PMAs being
-** merged. An aReadr[] object either points to a valid key or else is at EOF.
-** ("EOF" means "End Of File". When aReadr[] is at EOF there is no more data.)
-** For the purposes of the paragraphs below, we assume that the array is
-** actually N elements in size, where N is the smallest power of 2 greater
-** to or equal to the number of PMAs being merged. The extra aReadr[] elements
-** are treated as if they are empty (always at EOF).
-**
-** The aTree[] array is also N elements in size. The value of N is stored in
-** the MergeEngine.nTree variable.
-**
-** The final (N/2) elements of aTree[] contain the results of comparing
-** pairs of PMA keys together. Element i contains the result of
-** comparing aReadr[2*i-N] and aReadr[2*i-N+1]. Whichever key is smaller, the
-** aTree element is set to the index of it.
-**
-** For the purposes of this comparison, EOF is considered greater than any
-** other key value. If the keys are equal (only possible with two EOF
-** values), it doesn't matter which index is stored.
-**
-** The (N/4) elements of aTree[] that precede the final (N/2) described
-** above contains the index of the smallest of each block of 4 PmaReaders
-** And so on. So that aTree[1] contains the index of the PmaReader that
-** currently points to the smallest key value. aTree[0] is unused.
-**
-** Example:
-**
-** aReadr[0] -> Banana
-** aReadr[1] -> Feijoa
-** aReadr[2] -> Elderberry
-** aReadr[3] -> Currant
-** aReadr[4] -> Grapefruit
-** aReadr[5] -> Apple
-** aReadr[6] -> Durian
-** aReadr[7] -> EOF
-**
-** aTree[] = { X, 5 0, 5 0, 3, 5, 6 }
-**
-** The current element is "Apple" (the value of the key indicated by
-** PmaReader 5). When the Next() operation is invoked, PmaReader 5 will
-** be advanced to the next key in its segment. Say the next key is
-** "Eggplant":
-**
-** aReadr[5] -> Eggplant
-**
-** The contents of aTree[] are updated first by comparing the new PmaReader
-** 5 key to the current key of PmaReader 4 (still "Grapefruit"). The PmaReader
-** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree.
-** The value of PmaReader 6 - "Durian" - is now smaller than that of PmaReader
-** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Banana<Durian),
-** so the value written into element 1 of the array is 0. As follows:
-**
-** aTree[] = { X, 0 0, 6 0, 3, 5, 6 }
-**
-** In other words, each time we advance to the next sorter element, log2(N)
-** key comparison operations are required, where N is the number of segments
-** being merged (rounded up to the next power of 2).
-*/
-struct MergeEngine {
- int nTree; /* Used size of aTree/aReadr (power of 2) */
- SortSubtask *pTask; /* Used by this thread only */
- int *aTree; /* Current state of incremental merge */
- PmaReader *aReadr; /* Array of PmaReaders to merge data from */
-};
-
-/*
-** This object represents a single thread of control in a sort operation.
-** Exactly VdbeSorter.nTask instances of this object are allocated
-** as part of each VdbeSorter object. Instances are never allocated any
-** other way. VdbeSorter.nTask is set to the number of worker threads allowed
-** (see SQLITE_CONFIG_WORKER_THREADS) plus one (the main thread). Thus for
-** single-threaded operation, there is exactly one instance of this object
-** and for multi-threaded operation there are two or more instances.
-**
-** Essentially, this structure contains all those fields of the VdbeSorter
-** structure for which each thread requires a separate instance. For example,
-** each thread requries its own UnpackedRecord object to unpack records in
-** as part of comparison operations.
-**
-** Before a background thread is launched, variable bDone is set to 0. Then,
-** right before it exits, the thread itself sets bDone to 1. This is used for
-** two purposes:
-**
-** 1. When flushing the contents of memory to a level-0 PMA on disk, to
-** attempt to select a SortSubtask for which there is not already an
-** active background thread (since doing so causes the main thread
-** to block until it finishes).
-**
-** 2. If SQLITE_DEBUG_SORTER_THREADS is defined, to determine if a call
-** to sqlite3ThreadJoin() is likely to block. Cases that are likely to
-** block provoke debugging output.
-**
-** In both cases, the effects of the main thread seeing (bDone==0) even
-** after the thread has finished are not dire. So we don't worry about
-** memory barriers and such here.
-*/
-typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int);
-struct SortSubtask {
- SQLiteThread *pThread; /* Background thread, if any */
- int bDone; /* Set if thread is finished but not joined */
- VdbeSorter *pSorter; /* Sorter that owns this sub-task */
- UnpackedRecord *pUnpacked; /* Space to unpack a record */
- SorterList list; /* List for thread to write to a PMA */
- int nPMA; /* Number of PMAs currently in file */
- SorterCompare xCompare; /* Compare function to use */
- SorterFile file; /* Temp file for level-0 PMAs */
- SorterFile file2; /* Space for other PMAs */
-};
-
-
-/*
-** Main sorter structure. A single instance of this is allocated for each
-** sorter cursor created by the VDBE.
-**
-** mxKeysize:
-** As records are added to the sorter by calls to sqlite3VdbeSorterWrite(),
-** this variable is updated so as to be set to the size on disk of the
-** largest record in the sorter.
-*/
-struct VdbeSorter {
- int mnPmaSize; /* Minimum PMA size, in bytes */
- int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */
- int mxKeysize; /* Largest serialized key seen so far */
- int pgsz; /* Main database page size */
- PmaReader *pReader; /* Readr data from here after Rewind() */
- MergeEngine *pMerger; /* Or here, if bUseThreads==0 */
- sqlite3 *db; /* Database connection */
- KeyInfo *pKeyInfo; /* How to compare records */
- UnpackedRecord *pUnpacked; /* Used by VdbeSorterCompare() */
- SorterList list; /* List of in-memory records */
- int iMemory; /* Offset of free space in list.aMemory */
- int nMemory; /* Size of list.aMemory allocation in bytes */
- u8 bUsePMA; /* True if one or more PMAs created */
- u8 bUseThreads; /* True to use background threads */
- u8 iPrev; /* Previous thread used to flush PMA */
- u8 nTask; /* Size of aTask[] array */
- u8 typeMask;
- SortSubtask aTask[1]; /* One or more subtasks */
-};
-
-#define SORTER_TYPE_INTEGER 0x01
-#define SORTER_TYPE_TEXT 0x02
-
-/*
-** An instance of the following object is used to read records out of a
-** PMA, in sorted order. The next key to be read is cached in nKey/aKey.
-** aKey might point into aMap or into aBuffer. If neither of those locations
-** contain a contiguous representation of the key, then aAlloc is allocated
-** and the key is copied into aAlloc and aKey is made to poitn to aAlloc.
-**
-** pFd==0 at EOF.
-*/
-struct PmaReader {
- i64 iReadOff; /* Current read offset */
- i64 iEof; /* 1 byte past EOF for this PmaReader */
- int nAlloc; /* Bytes of space at aAlloc */
- int nKey; /* Number of bytes in key */
- sqlite3_file *pFd; /* File handle we are reading from */
- u8 *aAlloc; /* Space for aKey if aBuffer and pMap wont work */
- u8 *aKey; /* Pointer to current key */
- u8 *aBuffer; /* Current read buffer */
- int nBuffer; /* Size of read buffer in bytes */
- u8 *aMap; /* Pointer to mapping of entire file */
- IncrMerger *pIncr; /* Incremental merger */
-};
-
-/*
-** Normally, a PmaReader object iterates through an existing PMA stored
-** within a temp file. However, if the PmaReader.pIncr variable points to
-** an object of the following type, it may be used to iterate/merge through
-** multiple PMAs simultaneously.
-**
-** There are two types of IncrMerger object - single (bUseThread==0) and
-** multi-threaded (bUseThread==1).
-**
-** A multi-threaded IncrMerger object uses two temporary files - aFile[0]
-** and aFile[1]. Neither file is allowed to grow to more than mxSz bytes in
-** size. When the IncrMerger is initialized, it reads enough data from
-** pMerger to populate aFile[0]. It then sets variables within the
-** corresponding PmaReader object to read from that file and kicks off
-** a background thread to populate aFile[1] with the next mxSz bytes of
-** sorted record data from pMerger.
-**
-** When the PmaReader reaches the end of aFile[0], it blocks until the
-** background thread has finished populating aFile[1]. It then exchanges
-** the contents of the aFile[0] and aFile[1] variables within this structure,
-** sets the PmaReader fields to read from the new aFile[0] and kicks off
-** another background thread to populate the new aFile[1]. And so on, until
-** the contents of pMerger are exhausted.
-**
-** A single-threaded IncrMerger does not open any temporary files of its
-** own. Instead, it has exclusive access to mxSz bytes of space beginning
-** at offset iStartOff of file pTask->file2. And instead of using a
-** background thread to prepare data for the PmaReader, with a single
-** threaded IncrMerger the allocate part of pTask->file2 is "refilled" with
-** keys from pMerger by the calling thread whenever the PmaReader runs out
-** of data.
-*/
-struct IncrMerger {
- SortSubtask *pTask; /* Task that owns this merger */
- MergeEngine *pMerger; /* Merge engine thread reads data from */
- i64 iStartOff; /* Offset to start writing file at */
- int mxSz; /* Maximum bytes of data to store */
- int bEof; /* Set to true when merge is finished */
- int bUseThread; /* True to use a bg thread for this object */
- SorterFile aFile[2]; /* aFile[0] for reading, [1] for writing */
-};
-
-/*
-** An instance of this object is used for writing a PMA.
-**
-** The PMA is written one record at a time. Each record is of an arbitrary
-** size. But I/O is more efficient if it occurs in page-sized blocks where
-** each block is aligned on a page boundary. This object caches writes to
-** the PMA so that aligned, page-size blocks are written.
-*/
-struct PmaWriter {
- int eFWErr; /* Non-zero if in an error state */
- u8 *aBuffer; /* Pointer to write buffer */
- int nBuffer; /* Size of write buffer in bytes */
- int iBufStart; /* First byte of buffer to write */
- int iBufEnd; /* Last byte of buffer to write */
- i64 iWriteOff; /* Offset of start of buffer in file */
- sqlite3_file *pFd; /* File handle to write to */
-};
-
-/*
-** This object is the header on a single record while that record is being
-** held in memory and prior to being written out as part of a PMA.
-**
-** How the linked list is connected depends on how memory is being managed
-** by this module. If using a separate allocation for each in-memory record
-** (VdbeSorter.list.aMemory==0), then the list is always connected using the
-** SorterRecord.u.pNext pointers.
-**
-** Or, if using the single large allocation method (VdbeSorter.list.aMemory!=0),
-** then while records are being accumulated the list is linked using the
-** SorterRecord.u.iNext offset. This is because the aMemory[] array may
-** be sqlite3Realloc()ed while records are being accumulated. Once the VM
-** has finished passing records to the sorter, or when the in-memory buffer
-** is full, the list is sorted. As part of the sorting process, it is
-** converted to use the SorterRecord.u.pNext pointers. See function
-** vdbeSorterSort() for details.
-*/
-struct SorterRecord {
- int nVal; /* Size of the record in bytes */
- union {
- SorterRecord *pNext; /* Pointer to next record in list */
- int iNext; /* Offset within aMemory of next record */
- } u;
- /* The data for the record immediately follows this header */
-};
-
-/* Return a pointer to the buffer containing the record data for SorterRecord
-** object p. Should be used as if:
-**
-** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; }
-*/
-#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1))
-
-
-/* Maximum number of PMAs that a single MergeEngine can merge */
-#define SORTER_MAX_MERGE_COUNT 16
-
-static int vdbeIncrSwap(IncrMerger*);
-static void vdbeIncrFree(IncrMerger *);
-
-/*
-** Free all memory belonging to the PmaReader object passed as the
-** argument. All structure fields are set to zero before returning.
-*/
-static void vdbePmaReaderClear(PmaReader *pReadr){
- sqlite3_free(pReadr->aAlloc);
- sqlite3_free(pReadr->aBuffer);
- if( pReadr->aMap ) sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap);
- vdbeIncrFree(pReadr->pIncr);
- memset(pReadr, 0, sizeof(PmaReader));
-}
-
-/*
-** Read the next nByte bytes of data from the PMA p.
-** If successful, set *ppOut to point to a buffer containing the data
-** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite
-** error code.
-**
-** The buffer returned in *ppOut is only valid until the
-** next call to this function.
-*/
-static int vdbePmaReadBlob(
- PmaReader *p, /* PmaReader from which to take the blob */
- int nByte, /* Bytes of data to read */
- u8 **ppOut /* OUT: Pointer to buffer containing data */
-){
- int iBuf; /* Offset within buffer to read from */
- int nAvail; /* Bytes of data available in buffer */
-
- if( p->aMap ){
- *ppOut = &p->aMap[p->iReadOff];
- p->iReadOff += nByte;
- return SQLITE_OK;
- }
-
- assert( p->aBuffer );
-
- /* If there is no more data to be read from the buffer, read the next
- ** p->nBuffer bytes of data from the file into it. Or, if there are less
- ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */
- iBuf = p->iReadOff % p->nBuffer;
- if( iBuf==0 ){
- int nRead; /* Bytes to read from disk */
- int rc; /* sqlite3OsRead() return code */
-
- /* Determine how many bytes of data to read. */
- if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){
- nRead = p->nBuffer;
- }else{
- nRead = (int)(p->iEof - p->iReadOff);
- }
- assert( nRead>0 );
-
- /* Readr data from the file. Return early if an error occurs. */
- rc = sqlite3OsRead(p->pFd, p->aBuffer, nRead, p->iReadOff);
- assert( rc!=SQLITE_IOERR_SHORT_READ );
- if( rc!=SQLITE_OK ) return rc;
- }
- nAvail = p->nBuffer - iBuf;
-
- if( nByte<=nAvail ){
- /* The requested data is available in the in-memory buffer. In this
- ** case there is no need to make a copy of the data, just return a
- ** pointer into the buffer to the caller. */
- *ppOut = &p->aBuffer[iBuf];
- p->iReadOff += nByte;
- }else{
- /* The requested data is not all available in the in-memory buffer.
- ** In this case, allocate space at p->aAlloc[] to copy the requested
- ** range into. Then return a copy of pointer p->aAlloc to the caller. */
- int nRem; /* Bytes remaining to copy */
-
- /* Extend the p->aAlloc[] allocation if required. */
- if( p->nAlloc<nByte ){
- u8 *aNew;
- int nNew = MAX(128, p->nAlloc*2);
- while( nByte>nNew ) nNew = nNew*2;
- aNew = sqlite3Realloc(p->aAlloc, nNew);
- if( !aNew ) return SQLITE_NOMEM_BKPT;
- p->nAlloc = nNew;
- p->aAlloc = aNew;
- }
-
- /* Copy as much data as is available in the buffer into the start of
- ** p->aAlloc[]. */
- memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail);
- p->iReadOff += nAvail;
- nRem = nByte - nAvail;
-
- /* The following loop copies up to p->nBuffer bytes per iteration into
- ** the p->aAlloc[] buffer. */
- while( nRem>0 ){
- int rc; /* vdbePmaReadBlob() return code */
- int nCopy; /* Number of bytes to copy */
- u8 *aNext; /* Pointer to buffer to copy data from */
-
- nCopy = nRem;
- if( nRem>p->nBuffer ) nCopy = p->nBuffer;
- rc = vdbePmaReadBlob(p, nCopy, &aNext);
- if( rc!=SQLITE_OK ) return rc;
- assert( aNext!=p->aAlloc );
- memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
- nRem -= nCopy;
- }
-
- *ppOut = p->aAlloc;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Read a varint from the stream of data accessed by p. Set *pnOut to
-** the value read.
-*/
-static int vdbePmaReadVarint(PmaReader *p, u64 *pnOut){
- int iBuf;
-
- if( p->aMap ){
- p->iReadOff += sqlite3GetVarint(&p->aMap[p->iReadOff], pnOut);
- }else{
- iBuf = p->iReadOff % p->nBuffer;
- if( iBuf && (p->nBuffer-iBuf)>=9 ){
- p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut);
- }else{
- u8 aVarint[16], *a;
- int i = 0, rc;
- do{
- rc = vdbePmaReadBlob(p, 1, &a);
- if( rc ) return rc;
- aVarint[(i++)&0xf] = a[0];
- }while( (a[0]&0x80)!=0 );
- sqlite3GetVarint(aVarint, pnOut);
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Attempt to memory map file pFile. If successful, set *pp to point to the
-** new mapping and return SQLITE_OK. If the mapping is not attempted
-** (because the file is too large or the VFS layer is configured not to use
-** mmap), return SQLITE_OK and set *pp to NULL.
-**
-** Or, if an error occurs, return an SQLite error code. The final value of
-** *pp is undefined in this case.
-*/
-static int vdbeSorterMapFile(SortSubtask *pTask, SorterFile *pFile, u8 **pp){
- int rc = SQLITE_OK;
- if( pFile->iEof<=(i64)(pTask->pSorter->db->nMaxSorterMmap) ){
- sqlite3_file *pFd = pFile->pFd;
- if( pFd->pMethods->iVersion>=3 ){
- rc = sqlite3OsFetch(pFd, 0, (int)pFile->iEof, (void**)pp);
- testcase( rc!=SQLITE_OK );
- }
- }
- return rc;
-}
-
-/*
-** Attach PmaReader pReadr to file pFile (if it is not already attached to
-** that file) and seek it to offset iOff within the file. Return SQLITE_OK
-** if successful, or an SQLite error code if an error occurs.
-*/
-static int vdbePmaReaderSeek(
- SortSubtask *pTask, /* Task context */
- PmaReader *pReadr, /* Reader whose cursor is to be moved */
- SorterFile *pFile, /* Sorter file to read from */
- i64 iOff /* Offset in pFile */
-){
- int rc = SQLITE_OK;
-
- assert( pReadr->pIncr==0 || pReadr->pIncr->bEof==0 );
-
- if( sqlite3FaultSim(201) ) return SQLITE_IOERR_READ;
- if( pReadr->aMap ){
- sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap);
- pReadr->aMap = 0;
- }
- pReadr->iReadOff = iOff;
- pReadr->iEof = pFile->iEof;
- pReadr->pFd = pFile->pFd;
-
- rc = vdbeSorterMapFile(pTask, pFile, &pReadr->aMap);
- if( rc==SQLITE_OK && pReadr->aMap==0 ){
- int pgsz = pTask->pSorter->pgsz;
- int iBuf = pReadr->iReadOff % pgsz;
- if( pReadr->aBuffer==0 ){
- pReadr->aBuffer = (u8*)sqlite3Malloc(pgsz);
- if( pReadr->aBuffer==0 ) rc = SQLITE_NOMEM_BKPT;
- pReadr->nBuffer = pgsz;
- }
- if( rc==SQLITE_OK && iBuf ){
- int nRead = pgsz - iBuf;
- if( (pReadr->iReadOff + nRead) > pReadr->iEof ){
- nRead = (int)(pReadr->iEof - pReadr->iReadOff);
- }
- rc = sqlite3OsRead(
- pReadr->pFd, &pReadr->aBuffer[iBuf], nRead, pReadr->iReadOff
- );
- testcase( rc!=SQLITE_OK );
- }
- }
-
- return rc;
-}
-
-/*
-** Advance PmaReader pReadr to the next key in its PMA. Return SQLITE_OK if
-** no error occurs, or an SQLite error code if one does.
-*/
-static int vdbePmaReaderNext(PmaReader *pReadr){
- int rc = SQLITE_OK; /* Return Code */
- u64 nRec = 0; /* Size of record in bytes */
-
-
- if( pReadr->iReadOff>=pReadr->iEof ){
- IncrMerger *pIncr = pReadr->pIncr;
- int bEof = 1;
- if( pIncr ){
- rc = vdbeIncrSwap(pIncr);
- if( rc==SQLITE_OK && pIncr->bEof==0 ){
- rc = vdbePmaReaderSeek(
- pIncr->pTask, pReadr, &pIncr->aFile[0], pIncr->iStartOff
- );
- bEof = 0;
- }
- }
-
- if( bEof ){
- /* This is an EOF condition */
- vdbePmaReaderClear(pReadr);
- testcase( rc!=SQLITE_OK );
- return rc;
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = vdbePmaReadVarint(pReadr, &nRec);
- }
- if( rc==SQLITE_OK ){
- pReadr->nKey = (int)nRec;
- rc = vdbePmaReadBlob(pReadr, (int)nRec, &pReadr->aKey);
- testcase( rc!=SQLITE_OK );
- }
-
- return rc;
-}
-
-/*
-** Initialize PmaReader pReadr to scan through the PMA stored in file pFile
-** starting at offset iStart and ending at offset iEof-1. This function
-** leaves the PmaReader pointing to the first key in the PMA (or EOF if the
-** PMA is empty).
-**
-** If the pnByte parameter is NULL, then it is assumed that the file
-** contains a single PMA, and that that PMA omits the initial length varint.
-*/
-static int vdbePmaReaderInit(
- SortSubtask *pTask, /* Task context */
- SorterFile *pFile, /* Sorter file to read from */
- i64 iStart, /* Start offset in pFile */
- PmaReader *pReadr, /* PmaReader to populate */
- i64 *pnByte /* IN/OUT: Increment this value by PMA size */
-){
- int rc;
-
- assert( pFile->iEof>iStart );
- assert( pReadr->aAlloc==0 && pReadr->nAlloc==0 );
- assert( pReadr->aBuffer==0 );
- assert( pReadr->aMap==0 );
-
- rc = vdbePmaReaderSeek(pTask, pReadr, pFile, iStart);
- if( rc==SQLITE_OK ){
- u64 nByte = 0; /* Size of PMA in bytes */
- rc = vdbePmaReadVarint(pReadr, &nByte);
- pReadr->iEof = pReadr->iReadOff + nByte;
- *pnByte += nByte;
- }
-
- if( rc==SQLITE_OK ){
- rc = vdbePmaReaderNext(pReadr);
- }
- return rc;
-}
-
-/*
-** A version of vdbeSorterCompare() that assumes that it has already been
-** determined that the first field of key1 is equal to the first field of
-** key2.
-*/
-static int vdbeSorterCompareTail(
- SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
- int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
- const void *pKey1, int nKey1, /* Left side of comparison */
- const void *pKey2, int nKey2 /* Right side of comparison */
-){
- UnpackedRecord *r2 = pTask->pUnpacked;
- if( *pbKey2Cached==0 ){
- sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
- *pbKey2Cached = 1;
- }
- return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
-}
-
-/*
-** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
-** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences
-** used by the comparison. Return the result of the comparison.
-**
-** If IN/OUT parameter *pbKey2Cached is true when this function is called,
-** it is assumed that (pTask->pUnpacked) contains the unpacked version
-** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked
-** version of key2 and *pbKey2Cached set to true before returning.
-**
-** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set
-** to SQLITE_NOMEM.
-*/
-static int vdbeSorterCompare(
- SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
- int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
- const void *pKey1, int nKey1, /* Left side of comparison */
- const void *pKey2, int nKey2 /* Right side of comparison */
-){
- UnpackedRecord *r2 = pTask->pUnpacked;
- if( !*pbKey2Cached ){
- sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
- *pbKey2Cached = 1;
- }
- return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
-}
-
-/*
-** A specially optimized version of vdbeSorterCompare() that assumes that
-** the first field of each key is a TEXT value and that the collation
-** sequence to compare them with is BINARY.
-*/
-static int vdbeSorterCompareText(
- SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
- int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
- const void *pKey1, int nKey1, /* Left side of comparison */
- const void *pKey2, int nKey2 /* Right side of comparison */
-){
- const u8 * const p1 = (const u8 * const)pKey1;
- const u8 * const p2 = (const u8 * const)pKey2;
- const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
- const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
-
- int n1;
- int n2;
- int res;
-
- getVarint32(&p1[1], n1);
- getVarint32(&p2[1], n2);
- res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2);
- if( res==0 ){
- res = n1 - n2;
- }
-
- if( res==0 ){
- if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
- res = vdbeSorterCompareTail(
- pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
- );
- }
- }else{
- if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
- res = res * -1;
- }
- }
-
- return res;
-}
-
-/*
-** A specially optimized version of vdbeSorterCompare() that assumes that
-** the first field of each key is an INTEGER value.
-*/
-static int vdbeSorterCompareInt(
- SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
- int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
- const void *pKey1, int nKey1, /* Left side of comparison */
- const void *pKey2, int nKey2 /* Right side of comparison */
-){
- const u8 * const p1 = (const u8 * const)pKey1;
- const u8 * const p2 = (const u8 * const)pKey2;
- const int s1 = p1[1]; /* Left hand serial type */
- const int s2 = p2[1]; /* Right hand serial type */
- const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
- const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
- int res; /* Return value */
-
- assert( (s1>0 && s1<7) || s1==8 || s1==9 );
- assert( (s2>0 && s2<7) || s2==8 || s2==9 );
-
- if( s1==s2 ){
- /* The two values have the same sign. Compare using memcmp(). */
- static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8, 0, 0, 0 };
- const u8 n = aLen[s1];
- int i;
- res = 0;
- for(i=0; i<n; i++){
- if( (res = v1[i] - v2[i])!=0 ){
- if( ((v1[0] ^ v2[0]) & 0x80)!=0 ){
- res = v1[0] & 0x80 ? -1 : +1;
- }
- break;
- }
- }
- }else if( s1>7 && s2>7 ){
- res = s1 - s2;
- }else{
- if( s2>7 ){
- res = +1;
- }else if( s1>7 ){
- res = -1;
- }else{
- res = s1 - s2;
- }
- assert( res!=0 );
-
- if( res>0 ){
- if( *v1 & 0x80 ) res = -1;
- }else{
- if( *v2 & 0x80 ) res = +1;
- }
- }
-
- if( res==0 ){
- if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
- res = vdbeSorterCompareTail(
- pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
- );
- }
- }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
- res = res * -1;
- }
-
- return res;
-}
-
-/*
-** Initialize the temporary index cursor just opened as a sorter cursor.
-**
-** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField)
-** to determine the number of fields that should be compared from the
-** records being sorted. However, if the value passed as argument nField
-** is non-zero and the sorter is able to guarantee a stable sort, nField
-** is used instead. This is used when sorting records for a CREATE INDEX
-** statement. In this case, keys are always delivered to the sorter in
-** order of the primary key, which happens to be make up the final part
-** of the records being sorted. So if the sort is stable, there is never
-** any reason to compare PK fields and they can be ignored for a small
-** performance boost.
-**
-** The sorter can guarantee a stable sort when running in single-threaded
-** mode, but not in multi-threaded mode.
-**
-** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
-*/
-int sqlite3VdbeSorterInit(
- sqlite3 *db, /* Database connection (for malloc()) */
- int nField, /* Number of key fields in each record */
- VdbeCursor *pCsr /* Cursor that holds the new sorter */
-){
- int pgsz; /* Page size of main database */
- int i; /* Used to iterate through aTask[] */
- VdbeSorter *pSorter; /* The new sorter */
- KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
- int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
- int sz; /* Size of pSorter in bytes */
- int rc = SQLITE_OK;
-#if SQLITE_MAX_WORKER_THREADS==0
-# define nWorker 0
-#else
- int nWorker;
-#endif
-
- /* Initialize the upper limit on the number of worker threads */
-#if SQLITE_MAX_WORKER_THREADS>0
- if( sqlite3TempInMemory(db) || sqlite3GlobalConfig.bCoreMutex==0 ){
- nWorker = 0;
- }else{
- nWorker = db->aLimit[SQLITE_LIMIT_WORKER_THREADS];
- }
-#endif
-
- /* Do not allow the total number of threads (main thread + all workers)
- ** to exceed the maximum merge count */
-#if SQLITE_MAX_WORKER_THREADS>=SORTER_MAX_MERGE_COUNT
- if( nWorker>=SORTER_MAX_MERGE_COUNT ){
- nWorker = SORTER_MAX_MERGE_COUNT-1;
- }
-#endif
-
- assert( pCsr->pKeyInfo && pCsr->pBtx==0 );
- assert( pCsr->eCurType==CURTYPE_SORTER );
- szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
- sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
-
- pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
- pCsr->uc.pSorter = pSorter;
- if( pSorter==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
- memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
- pKeyInfo->db = 0;
- if( nField && nWorker==0 ){
- pKeyInfo->nKeyField = nField;
- }
- pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
- pSorter->nTask = nWorker + 1;
- pSorter->iPrev = (u8)(nWorker - 1);
- pSorter->bUseThreads = (pSorter->nTask>1);
- pSorter->db = db;
- for(i=0; i<pSorter->nTask; i++){
- SortSubtask *pTask = &pSorter->aTask[i];
- pTask->pSorter = pSorter;
- }
-
- if( !sqlite3TempInMemory(db) ){
- i64 mxCache; /* Cache size in bytes*/
- u32 szPma = sqlite3GlobalConfig.szPma;
- pSorter->mnPmaSize = szPma * pgsz;
-
- mxCache = db->aDb[0].pSchema->cache_size;
- if( mxCache<0 ){
- /* A negative cache-size value C indicates that the cache is abs(C)
- ** KiB in size. */
- mxCache = mxCache * -1024;
- }else{
- mxCache = mxCache * pgsz;
- }
- mxCache = MIN(mxCache, SQLITE_MAX_PMASZ);
- pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache);
-
- /* Avoid large memory allocations if the application has requested
- ** SQLITE_CONFIG_SMALL_MALLOC. */
- if( sqlite3GlobalConfig.bSmallMalloc==0 ){
- assert( pSorter->iMemory==0 );
- pSorter->nMemory = pgsz;
- pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz);
- if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM_BKPT;
- }
- }
-
- if( pKeyInfo->nAllField<13
- && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
- ){
- pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
- }
- }
-
- return rc;
-}
-#undef nWorker /* Defined at the top of this function */
-
-/*
-** Free the list of sorted records starting at pRecord.
-*/
-static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
- SorterRecord *p;
- SorterRecord *pNext;
- for(p=pRecord; p; p=pNext){
- pNext = p->u.pNext;
- sqlite3DbFree(db, p);
- }
-}
-
-/*
-** Free all resources owned by the object indicated by argument pTask. All
-** fields of *pTask are zeroed before returning.
-*/
-static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){
- sqlite3DbFree(db, pTask->pUnpacked);
-#if SQLITE_MAX_WORKER_THREADS>0
- /* pTask->list.aMemory can only be non-zero if it was handed memory
- ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */
- if( pTask->list.aMemory ){
- sqlite3_free(pTask->list.aMemory);
- }else
-#endif
- {
- assert( pTask->list.aMemory==0 );
- vdbeSorterRecordFree(0, pTask->list.pList);
- }
- if( pTask->file.pFd ){
- sqlite3OsCloseFree(pTask->file.pFd);
- }
- if( pTask->file2.pFd ){
- sqlite3OsCloseFree(pTask->file2.pFd);
- }
- memset(pTask, 0, sizeof(SortSubtask));
-}
-
-#ifdef SQLITE_DEBUG_SORTER_THREADS
-static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){
- i64 t;
- int iTask = (pTask - pTask->pSorter->aTask);
- sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
- fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
-}
-static void vdbeSorterRewindDebug(const char *zEvent){
- i64 t;
- sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t);
- fprintf(stderr, "%lld:X %s\n", t, zEvent);
-}
-static void vdbeSorterPopulateDebug(
- SortSubtask *pTask,
- const char *zEvent
-){
- i64 t;
- int iTask = (pTask - pTask->pSorter->aTask);
- sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
- fprintf(stderr, "%lld:bg%d %s\n", t, iTask, zEvent);
-}
-static void vdbeSorterBlockDebug(
- SortSubtask *pTask,
- int bBlocked,
- const char *zEvent
-){
- if( bBlocked ){
- i64 t;
- sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
- fprintf(stderr, "%lld:main %s\n", t, zEvent);
- }
-}
-#else
-# define vdbeSorterWorkDebug(x,y)
-# define vdbeSorterRewindDebug(y)
-# define vdbeSorterPopulateDebug(x,y)
-# define vdbeSorterBlockDebug(x,y,z)
-#endif
-
-#if SQLITE_MAX_WORKER_THREADS>0
-/*
-** Join thread pTask->thread.
-*/
-static int vdbeSorterJoinThread(SortSubtask *pTask){
- int rc = SQLITE_OK;
- if( pTask->pThread ){
-#ifdef SQLITE_DEBUG_SORTER_THREADS
- int bDone = pTask->bDone;
-#endif
- void *pRet = SQLITE_INT_TO_PTR(SQLITE_ERROR);
- vdbeSorterBlockDebug(pTask, !bDone, "enter");
- (void)sqlite3ThreadJoin(pTask->pThread, &pRet);
- vdbeSorterBlockDebug(pTask, !bDone, "exit");
- rc = SQLITE_PTR_TO_INT(pRet);
- assert( pTask->bDone==1 );
- pTask->bDone = 0;
- pTask->pThread = 0;
- }
- return rc;
-}
-
-/*
-** Launch a background thread to run xTask(pIn).
-*/
-static int vdbeSorterCreateThread(
- SortSubtask *pTask, /* Thread will use this task object */
- void *(*xTask)(void*), /* Routine to run in a separate thread */
- void *pIn /* Argument passed into xTask() */
-){
- assert( pTask->pThread==0 && pTask->bDone==0 );
- return sqlite3ThreadCreate(&pTask->pThread, xTask, pIn);
-}
-
-/*
-** Join all outstanding threads launched by SorterWrite() to create
-** level-0 PMAs.
-*/
-static int vdbeSorterJoinAll(VdbeSorter *pSorter, int rcin){
- int rc = rcin;
- int i;
-
- /* This function is always called by the main user thread.
- **
- ** If this function is being called after SorterRewind() has been called,
- ** it is possible that thread pSorter->aTask[pSorter->nTask-1].pThread
- ** is currently attempt to join one of the other threads. To avoid a race
- ** condition where this thread also attempts to join the same object, join
- ** thread pSorter->aTask[pSorter->nTask-1].pThread first. */
- for(i=pSorter->nTask-1; i>=0; i--){
- SortSubtask *pTask = &pSorter->aTask[i];
- int rc2 = vdbeSorterJoinThread(pTask);
- if( rc==SQLITE_OK ) rc = rc2;
- }
- return rc;
-}
-#else
-# define vdbeSorterJoinAll(x,rcin) (rcin)
-# define vdbeSorterJoinThread(pTask) SQLITE_OK
-#endif
-
-/*
-** Allocate a new MergeEngine object capable of handling up to
-** nReader PmaReader inputs.
-**
-** nReader is automatically rounded up to the next power of two.
-** nReader may not exceed SORTER_MAX_MERGE_COUNT even after rounding up.
-*/
-static MergeEngine *vdbeMergeEngineNew(int nReader){
- int N = 2; /* Smallest power of two >= nReader */
- int nByte; /* Total bytes of space to allocate */
- MergeEngine *pNew; /* Pointer to allocated object to return */
-
- assert( nReader<=SORTER_MAX_MERGE_COUNT );
-
- while( N<nReader ) N += N;
- nByte = sizeof(MergeEngine) + N * (sizeof(int) + sizeof(PmaReader));
-
- pNew = sqlite3FaultSim(100) ? 0 : (MergeEngine*)sqlite3MallocZero(nByte);
- if( pNew ){
- pNew->nTree = N;
- pNew->pTask = 0;
- pNew->aReadr = (PmaReader*)&pNew[1];
- pNew->aTree = (int*)&pNew->aReadr[N];
- }
- return pNew;
-}
-
-/*
-** Free the MergeEngine object passed as the only argument.
-*/
-static void vdbeMergeEngineFree(MergeEngine *pMerger){
- int i;
- if( pMerger ){
- for(i=0; i<pMerger->nTree; i++){
- vdbePmaReaderClear(&pMerger->aReadr[i]);
- }
- }
- sqlite3_free(pMerger);
-}
-
-/*
-** Free all resources associated with the IncrMerger object indicated by
-** the first argument.
-*/
-static void vdbeIncrFree(IncrMerger *pIncr){
- if( pIncr ){
-#if SQLITE_MAX_WORKER_THREADS>0
- if( pIncr->bUseThread ){
- vdbeSorterJoinThread(pIncr->pTask);
- if( pIncr->aFile[0].pFd ) sqlite3OsCloseFree(pIncr->aFile[0].pFd);
- if( pIncr->aFile[1].pFd ) sqlite3OsCloseFree(pIncr->aFile[1].pFd);
- }
-#endif
- vdbeMergeEngineFree(pIncr->pMerger);
- sqlite3_free(pIncr);
- }
-}
-
-/*
-** Reset a sorting cursor back to its original empty state.
-*/
-void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
- int i;
- (void)vdbeSorterJoinAll(pSorter, SQLITE_OK);
- assert( pSorter->bUseThreads || pSorter->pReader==0 );
-#if SQLITE_MAX_WORKER_THREADS>0
- if( pSorter->pReader ){
- vdbePmaReaderClear(pSorter->pReader);
- sqlite3DbFree(db, pSorter->pReader);
- pSorter->pReader = 0;
- }
-#endif
- vdbeMergeEngineFree(pSorter->pMerger);
- pSorter->pMerger = 0;
- for(i=0; i<pSorter->nTask; i++){
- SortSubtask *pTask = &pSorter->aTask[i];
- vdbeSortSubtaskCleanup(db, pTask);
- pTask->pSorter = pSorter;
- }
- if( pSorter->list.aMemory==0 ){
- vdbeSorterRecordFree(0, pSorter->list.pList);
- }
- pSorter->list.pList = 0;
- pSorter->list.szPMA = 0;
- pSorter->bUsePMA = 0;
- pSorter->iMemory = 0;
- pSorter->mxKeysize = 0;
- sqlite3DbFree(db, pSorter->pUnpacked);
- pSorter->pUnpacked = 0;
-}
-
-/*
-** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
-*/
-void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
- VdbeSorter *pSorter;
- assert( pCsr->eCurType==CURTYPE_SORTER );
- pSorter = pCsr->uc.pSorter;
- if( pSorter ){
- sqlite3VdbeSorterReset(db, pSorter);
- sqlite3_free(pSorter->list.aMemory);
- sqlite3DbFree(db, pSorter);
- pCsr->uc.pSorter = 0;
- }
-}
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/*
-** The first argument is a file-handle open on a temporary file. The file
-** is guaranteed to be nByte bytes or smaller in size. This function
-** attempts to extend the file to nByte bytes in size and to ensure that
-** the VFS has memory mapped it.
-**
-** Whether or not the file does end up memory mapped of course depends on
-** the specific VFS implementation.
-*/
-static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
- if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
- void *p = 0;
- int chunksize = 4*1024;
- sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
- sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
- sqlite3OsFetch(pFd, 0, (int)nByte, &p);
- sqlite3OsUnfetch(pFd, 0, p);
- }
-}
-#else
-# define vdbeSorterExtendFile(x,y,z)
-#endif
-
-/*
-** Allocate space for a file-handle and open a temporary file. If successful,
-** set *ppFd to point to the malloc'd file-handle and return SQLITE_OK.
-** Otherwise, set *ppFd to 0 and return an SQLite error code.
-*/
-static int vdbeSorterOpenTempFile(
- sqlite3 *db, /* Database handle doing sort */
- i64 nExtend, /* Attempt to extend file to this size */
- sqlite3_file **ppFd
-){
- int rc;
- if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS;
- rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd,
- SQLITE_OPEN_TEMP_JOURNAL |
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
- SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &rc
- );
- if( rc==SQLITE_OK ){
- i64 max = SQLITE_MAX_MMAP_SIZE;
- sqlite3OsFileControlHint(*ppFd, SQLITE_FCNTL_MMAP_SIZE, (void*)&max);
- if( nExtend>0 ){
- vdbeSorterExtendFile(db, *ppFd, nExtend);
- }
- }
- return rc;
-}
-
-/*
-** If it has not already been allocated, allocate the UnpackedRecord
-** structure at pTask->pUnpacked. Return SQLITE_OK if successful (or
-** if no allocation was required), or SQLITE_NOMEM otherwise.
-*/
-static int vdbeSortAllocUnpacked(SortSubtask *pTask){
- if( pTask->pUnpacked==0 ){
- pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo);
- if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT;
- pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nKeyField;
- pTask->pUnpacked->errCode = 0;
- }
- return SQLITE_OK;
-}
-
-
-/*
-** Merge the two sorted lists p1 and p2 into a single list.
-*/
-static SorterRecord *vdbeSorterMerge(
- SortSubtask *pTask, /* Calling thread context */
- SorterRecord *p1, /* First list to merge */
- SorterRecord *p2 /* Second list to merge */
-){
- SorterRecord *pFinal = 0;
- SorterRecord **pp = &pFinal;
- int bCached = 0;
-
- assert( p1!=0 && p2!=0 );
- for(;;){
- int res;
- res = pTask->xCompare(
- pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal
- );
-
- if( res<=0 ){
- *pp = p1;
- pp = &p1->u.pNext;
- p1 = p1->u.pNext;
- if( p1==0 ){
- *pp = p2;
- break;
- }
- }else{
- *pp = p2;
- pp = &p2->u.pNext;
- p2 = p2->u.pNext;
- bCached = 0;
- if( p2==0 ){
- *pp = p1;
- break;
- }
- }
- }
- return pFinal;
-}
-
-/*
-** Return the SorterCompare function to compare values collected by the
-** sorter object passed as the only argument.
-*/
-static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){
- if( p->typeMask==SORTER_TYPE_INTEGER ){
- return vdbeSorterCompareInt;
- }else if( p->typeMask==SORTER_TYPE_TEXT ){
- return vdbeSorterCompareText;
- }
- return vdbeSorterCompare;
-}
-
-/*
-** Sort the linked list of records headed at pTask->pList. Return
-** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if
-** an error occurs.
-*/
-static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
- int i;
- SorterRecord **aSlot;
- SorterRecord *p;
- int rc;
-
- rc = vdbeSortAllocUnpacked(pTask);
- if( rc!=SQLITE_OK ) return rc;
-
- p = pList->pList;
- pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);
-
- aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
- if( !aSlot ){
- return SQLITE_NOMEM_BKPT;
- }
-
- while( p ){
- SorterRecord *pNext;
- if( pList->aMemory ){
- if( (u8*)p==pList->aMemory ){
- pNext = 0;
- }else{
- assert( p->u.iNext<sqlite3MallocSize(pList->aMemory) );
- pNext = (SorterRecord*)&pList->aMemory[p->u.iNext];
- }
- }else{
- pNext = p->u.pNext;
- }
-
- p->u.pNext = 0;
- for(i=0; aSlot[i]; i++){
- p = vdbeSorterMerge(pTask, p, aSlot[i]);
- aSlot[i] = 0;
- }
- aSlot[i] = p;
- p = pNext;
- }
-
- p = 0;
- for(i=0; i<64; i++){
- if( aSlot[i]==0 ) continue;
- p = p ? vdbeSorterMerge(pTask, p, aSlot[i]) : aSlot[i];
- }
- pList->pList = p;
-
- sqlite3_free(aSlot);
- assert( pTask->pUnpacked->errCode==SQLITE_OK
- || pTask->pUnpacked->errCode==SQLITE_NOMEM
- );
- return pTask->pUnpacked->errCode;
-}
-
-/*
-** Initialize a PMA-writer object.
-*/
-static void vdbePmaWriterInit(
- sqlite3_file *pFd, /* File handle to write to */
- PmaWriter *p, /* Object to populate */
- int nBuf, /* Buffer size */
- i64 iStart /* Offset of pFd to begin writing at */
-){
- memset(p, 0, sizeof(PmaWriter));
- p->aBuffer = (u8*)sqlite3Malloc(nBuf);
- if( !p->aBuffer ){
- p->eFWErr = SQLITE_NOMEM_BKPT;
- }else{
- p->iBufEnd = p->iBufStart = (iStart % nBuf);
- p->iWriteOff = iStart - p->iBufStart;
- p->nBuffer = nBuf;
- p->pFd = pFd;
- }
-}
-
-/*
-** Write nData bytes of data to the PMA. Return SQLITE_OK
-** if successful, or an SQLite error code if an error occurs.
-*/
-static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){
- int nRem = nData;
- while( nRem>0 && p->eFWErr==0 ){
- int nCopy = nRem;
- if( nCopy>(p->nBuffer - p->iBufEnd) ){
- nCopy = p->nBuffer - p->iBufEnd;
- }
-
- memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy);
- p->iBufEnd += nCopy;
- if( p->iBufEnd==p->nBuffer ){
- p->eFWErr = sqlite3OsWrite(p->pFd,
- &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
- p->iWriteOff + p->iBufStart
- );
- p->iBufStart = p->iBufEnd = 0;
- p->iWriteOff += p->nBuffer;
- }
- assert( p->iBufEnd<p->nBuffer );
-
- nRem -= nCopy;
- }
-}
-
-/*
-** Flush any buffered data to disk and clean up the PMA-writer object.
-** The results of using the PMA-writer after this call are undefined.
-** Return SQLITE_OK if flushing the buffered data succeeds or is not
-** required. Otherwise, return an SQLite error code.
-**
-** Before returning, set *piEof to the offset immediately following the
-** last byte written to the file.
-*/
-static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof){
- int rc;
- if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){
- p->eFWErr = sqlite3OsWrite(p->pFd,
- &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
- p->iWriteOff + p->iBufStart
- );
- }
- *piEof = (p->iWriteOff + p->iBufEnd);
- sqlite3_free(p->aBuffer);
- rc = p->eFWErr;
- memset(p, 0, sizeof(PmaWriter));
- return rc;
-}
-
-/*
-** Write value iVal encoded as a varint to the PMA. Return
-** SQLITE_OK if successful, or an SQLite error code if an error occurs.
-*/
-static void vdbePmaWriteVarint(PmaWriter *p, u64 iVal){
- int nByte;
- u8 aByte[10];
- nByte = sqlite3PutVarint(aByte, iVal);
- vdbePmaWriteBlob(p, aByte, nByte);
-}
-
-/*
-** Write the current contents of in-memory linked-list pList to a level-0
-** PMA in the temp file belonging to sub-task pTask. Return SQLITE_OK if
-** successful, or an SQLite error code otherwise.
-**
-** The format of a PMA is:
-**
-** * A varint. This varint contains the total number of bytes of content
-** in the PMA (not including the varint itself).
-**
-** * One or more records packed end-to-end in order of ascending keys.
-** Each record consists of a varint followed by a blob of data (the
-** key). The varint is the number of bytes in the blob of data.
-*/
-static int vdbeSorterListToPMA(SortSubtask *pTask, SorterList *pList){
- sqlite3 *db = pTask->pSorter->db;
- int rc = SQLITE_OK; /* Return code */
- PmaWriter writer; /* Object used to write to the file */
-
-#ifdef SQLITE_DEBUG
- /* Set iSz to the expected size of file pTask->file after writing the PMA.
- ** This is used by an assert() statement at the end of this function. */
- i64 iSz = pList->szPMA + sqlite3VarintLen(pList->szPMA) + pTask->file.iEof;
-#endif
-
- vdbeSorterWorkDebug(pTask, "enter");
- memset(&writer, 0, sizeof(PmaWriter));
- assert( pList->szPMA>0 );
-
- /* If the first temporary PMA file has not been opened, open it now. */
- if( pTask->file.pFd==0 ){
- rc = vdbeSorterOpenTempFile(db, 0, &pTask->file.pFd);
- assert( rc!=SQLITE_OK || pTask->file.pFd );
- assert( pTask->file.iEof==0 );
- assert( pTask->nPMA==0 );
- }
-
- /* Try to get the file to memory map */
- if( rc==SQLITE_OK ){
- vdbeSorterExtendFile(db, pTask->file.pFd, pTask->file.iEof+pList->szPMA+9);
- }
-
- /* Sort the list */
- if( rc==SQLITE_OK ){
- rc = vdbeSorterSort(pTask, pList);
- }
-
- if( rc==SQLITE_OK ){
- SorterRecord *p;
- SorterRecord *pNext = 0;
-
- vdbePmaWriterInit(pTask->file.pFd, &writer, pTask->pSorter->pgsz,
- pTask->file.iEof);
- pTask->nPMA++;
- vdbePmaWriteVarint(&writer, pList->szPMA);
- for(p=pList->pList; p; p=pNext){
- pNext = p->u.pNext;
- vdbePmaWriteVarint(&writer, p->nVal);
- vdbePmaWriteBlob(&writer, SRVAL(p), p->nVal);
- if( pList->aMemory==0 ) sqlite3_free(p);
- }
- pList->pList = p;
- rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof);
- }
-
- vdbeSorterWorkDebug(pTask, "exit");
- assert( rc!=SQLITE_OK || pList->pList==0 );
- assert( rc!=SQLITE_OK || pTask->file.iEof==iSz );
- return rc;
-}
-
-/*
-** Advance the MergeEngine to its next entry.
-** Set *pbEof to true there is no next entry because
-** the MergeEngine has reached the end of all its inputs.
-**
-** Return SQLITE_OK if successful or an error code if an error occurs.
-*/
-static int vdbeMergeEngineStep(
- MergeEngine *pMerger, /* The merge engine to advance to the next row */
- int *pbEof /* Set TRUE at EOF. Set false for more content */
-){
- int rc;
- int iPrev = pMerger->aTree[1];/* Index of PmaReader to advance */
- SortSubtask *pTask = pMerger->pTask;
-
- /* Advance the current PmaReader */
- rc = vdbePmaReaderNext(&pMerger->aReadr[iPrev]);
-
- /* Update contents of aTree[] */
- if( rc==SQLITE_OK ){
- int i; /* Index of aTree[] to recalculate */
- PmaReader *pReadr1; /* First PmaReader to compare */
- PmaReader *pReadr2; /* Second PmaReader to compare */
- int bCached = 0;
-
- /* Find the first two PmaReaders to compare. The one that was just
- ** advanced (iPrev) and the one next to it in the array. */
- pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)];
- pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)];
-
- for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){
- /* Compare pReadr1 and pReadr2. Store the result in variable iRes. */
- int iRes;
- if( pReadr1->pFd==0 ){
- iRes = +1;
- }else if( pReadr2->pFd==0 ){
- iRes = -1;
- }else{
- iRes = pTask->xCompare(pTask, &bCached,
- pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey
- );
- }
-
- /* If pReadr1 contained the smaller value, set aTree[i] to its index.
- ** Then set pReadr2 to the next PmaReader to compare to pReadr1. In this
- ** case there is no cache of pReadr2 in pTask->pUnpacked, so set
- ** pKey2 to point to the record belonging to pReadr2.
- **
- ** Alternatively, if pReadr2 contains the smaller of the two values,
- ** set aTree[i] to its index and update pReadr1. If vdbeSorterCompare()
- ** was actually called above, then pTask->pUnpacked now contains
- ** a value equivalent to pReadr2. So set pKey2 to NULL to prevent
- ** vdbeSorterCompare() from decoding pReadr2 again.
- **
- ** If the two values were equal, then the value from the oldest
- ** PMA should be considered smaller. The VdbeSorter.aReadr[] array
- ** is sorted from oldest to newest, so pReadr1 contains older values
- ** than pReadr2 iff (pReadr1<pReadr2). */
- if( iRes<0 || (iRes==0 && pReadr1<pReadr2) ){
- pMerger->aTree[i] = (int)(pReadr1 - pMerger->aReadr);
- pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
- bCached = 0;
- }else{
- if( pReadr1->pFd ) bCached = 0;
- pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr);
- pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
- }
- }
- *pbEof = (pMerger->aReadr[pMerger->aTree[1]].pFd==0);
- }
-
- return (rc==SQLITE_OK ? pTask->pUnpacked->errCode : rc);
-}
-
-#if SQLITE_MAX_WORKER_THREADS>0
-/*
-** The main routine for background threads that write level-0 PMAs.
-*/
-static void *vdbeSorterFlushThread(void *pCtx){
- SortSubtask *pTask = (SortSubtask*)pCtx;
- int rc; /* Return code */
- assert( pTask->bDone==0 );
- rc = vdbeSorterListToPMA(pTask, &pTask->list);
- pTask->bDone = 1;
- return SQLITE_INT_TO_PTR(rc);
-}
-#endif /* SQLITE_MAX_WORKER_THREADS>0 */
-
-/*
-** Flush the current contents of VdbeSorter.list to a new PMA, possibly
-** using a background thread.
-*/
-static int vdbeSorterFlushPMA(VdbeSorter *pSorter){
-#if SQLITE_MAX_WORKER_THREADS==0
- pSorter->bUsePMA = 1;
- return vdbeSorterListToPMA(&pSorter->aTask[0], &pSorter->list);
-#else
- int rc = SQLITE_OK;
- int i;
- SortSubtask *pTask = 0; /* Thread context used to create new PMA */
- int nWorker = (pSorter->nTask-1);
-
- /* Set the flag to indicate that at least one PMA has been written.
- ** Or will be, anyhow. */
- pSorter->bUsePMA = 1;
-
- /* Select a sub-task to sort and flush the current list of in-memory
- ** records to disk. If the sorter is running in multi-threaded mode,
- ** round-robin between the first (pSorter->nTask-1) tasks. Except, if
- ** the background thread from a sub-tasks previous turn is still running,
- ** skip it. If the first (pSorter->nTask-1) sub-tasks are all still busy,
- ** fall back to using the final sub-task. The first (pSorter->nTask-1)
- ** sub-tasks are prefered as they use background threads - the final
- ** sub-task uses the main thread. */
- for(i=0; i<nWorker; i++){
- int iTest = (pSorter->iPrev + i + 1) % nWorker;
- pTask = &pSorter->aTask[iTest];
- if( pTask->bDone ){
- rc = vdbeSorterJoinThread(pTask);
- }
- if( rc!=SQLITE_OK || pTask->pThread==0 ) break;
- }
-
- if( rc==SQLITE_OK ){
- if( i==nWorker ){
- /* Use the foreground thread for this operation */
- rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list);
- }else{
- /* Launch a background thread for this operation */
- u8 *aMem = pTask->list.aMemory;
- void *pCtx = (void*)pTask;
-
- assert( pTask->pThread==0 && pTask->bDone==0 );
- assert( pTask->list.pList==0 );
- assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 );
-
- pSorter->iPrev = (u8)(pTask - pSorter->aTask);
- pTask->list = pSorter->list;
- pSorter->list.pList = 0;
- pSorter->list.szPMA = 0;
- if( aMem ){
- pSorter->list.aMemory = aMem;
- pSorter->nMemory = sqlite3MallocSize(aMem);
- }else if( pSorter->list.aMemory ){
- pSorter->list.aMemory = sqlite3Malloc(pSorter->nMemory);
- if( !pSorter->list.aMemory ) return SQLITE_NOMEM_BKPT;
- }
-
- rc = vdbeSorterCreateThread(pTask, vdbeSorterFlushThread, pCtx);
- }
- }
-
- return rc;
-#endif /* SQLITE_MAX_WORKER_THREADS!=0 */
-}
-
-/*
-** Add a record to the sorter.
-*/
-int sqlite3VdbeSorterWrite(
- const VdbeCursor *pCsr, /* Sorter cursor */
- Mem *pVal /* Memory cell containing record */
-){
- VdbeSorter *pSorter;
- int rc = SQLITE_OK; /* Return Code */
- SorterRecord *pNew; /* New list element */
- int bFlush; /* True to flush contents of memory to PMA */
- int nReq; /* Bytes of memory required */
- int nPMA; /* Bytes of PMA space required */
- int t; /* serial type of first record field */
-
- assert( pCsr->eCurType==CURTYPE_SORTER );
- pSorter = pCsr->uc.pSorter;
- getVarint32((const u8*)&pVal->z[1], t);
- if( t>0 && t<10 && t!=7 ){
- pSorter->typeMask &= SORTER_TYPE_INTEGER;
- }else if( t>10 && (t & 0x01) ){
- pSorter->typeMask &= SORTER_TYPE_TEXT;
- }else{
- pSorter->typeMask = 0;
- }
-
- assert( pSorter );
-
- /* Figure out whether or not the current contents of memory should be
- ** flushed to a PMA before continuing. If so, do so.
- **
- ** If using the single large allocation mode (pSorter->aMemory!=0), then
- ** flush the contents of memory to a new PMA if (a) at least one value is
- ** already in memory and (b) the new value will not fit in memory.
- **
- ** Or, if using separate allocations for each record, flush the contents
- ** of memory to a PMA if either of the following are true:
- **
- ** * The total memory allocated for the in-memory list is greater
- ** than (page-size * cache-size), or
- **
- ** * The total memory allocated for the in-memory list is greater
- ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
- */
- nReq = pVal->n + sizeof(SorterRecord);
- nPMA = pVal->n + sqlite3VarintLen(pVal->n);
- if( pSorter->mxPmaSize ){
- if( pSorter->list.aMemory ){
- bFlush = pSorter->iMemory && (pSorter->iMemory+nReq) > pSorter->mxPmaSize;
- }else{
- bFlush = (
- (pSorter->list.szPMA > pSorter->mxPmaSize)
- || (pSorter->list.szPMA > pSorter->mnPmaSize && sqlite3HeapNearlyFull())
- );
- }
- if( bFlush ){
- rc = vdbeSorterFlushPMA(pSorter);
- pSorter->list.szPMA = 0;
- pSorter->iMemory = 0;
- assert( rc!=SQLITE_OK || pSorter->list.pList==0 );
- }
- }
-
- pSorter->list.szPMA += nPMA;
- if( nPMA>pSorter->mxKeysize ){
- pSorter->mxKeysize = nPMA;
- }
-
- if( pSorter->list.aMemory ){
- int nMin = pSorter->iMemory + nReq;
-
- if( nMin>pSorter->nMemory ){
- u8 *aNew;
- int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory;
- int nNew = pSorter->nMemory * 2;
- while( nNew < nMin ) nNew = nNew*2;
- if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize;
- if( nNew < nMin ) nNew = nMin;
-
- aNew = sqlite3Realloc(pSorter->list.aMemory, nNew);
- if( !aNew ) return SQLITE_NOMEM_BKPT;
- pSorter->list.pList = (SorterRecord*)&aNew[iListOff];
- pSorter->list.aMemory = aNew;
- pSorter->nMemory = nNew;
- }
-
- pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory];
- pSorter->iMemory += ROUND8(nReq);
- if( pSorter->list.pList ){
- pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory);
- }
- }else{
- pNew = (SorterRecord *)sqlite3Malloc(nReq);
- if( pNew==0 ){
- return SQLITE_NOMEM_BKPT;
- }
- pNew->u.pNext = pSorter->list.pList;
- }
-
- memcpy(SRVAL(pNew), pVal->z, pVal->n);
- pNew->nVal = pVal->n;
- pSorter->list.pList = pNew;
-
- return rc;
-}
-
-/*
-** Read keys from pIncr->pMerger and populate pIncr->aFile[1]. The format
-** of the data stored in aFile[1] is the same as that used by regular PMAs,
-** except that the number-of-bytes varint is omitted from the start.
-*/
-static int vdbeIncrPopulate(IncrMerger *pIncr){
- int rc = SQLITE_OK;
- int rc2;
- i64 iStart = pIncr->iStartOff;
- SorterFile *pOut = &pIncr->aFile[1];
- SortSubtask *pTask = pIncr->pTask;
- MergeEngine *pMerger = pIncr->pMerger;
- PmaWriter writer;
- assert( pIncr->bEof==0 );
-
- vdbeSorterPopulateDebug(pTask, "enter");
-
- vdbePmaWriterInit(pOut->pFd, &writer, pTask->pSorter->pgsz, iStart);
- while( rc==SQLITE_OK ){
- int dummy;
- PmaReader *pReader = &pMerger->aReadr[ pMerger->aTree[1] ];
- int nKey = pReader->nKey;
- i64 iEof = writer.iWriteOff + writer.iBufEnd;
-
- /* Check if the output file is full or if the input has been exhausted.
- ** In either case exit the loop. */
- if( pReader->pFd==0 ) break;
- if( (iEof + nKey + sqlite3VarintLen(nKey))>(iStart + pIncr->mxSz) ) break;
-
- /* Write the next key to the output. */
- vdbePmaWriteVarint(&writer, nKey);
- vdbePmaWriteBlob(&writer, pReader->aKey, nKey);
- assert( pIncr->pMerger->pTask==pTask );
- rc = vdbeMergeEngineStep(pIncr->pMerger, &dummy);
- }
-
- rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof);
- if( rc==SQLITE_OK ) rc = rc2;
- vdbeSorterPopulateDebug(pTask, "exit");
- return rc;
-}
-
-#if SQLITE_MAX_WORKER_THREADS>0
-/*
-** The main routine for background threads that populate aFile[1] of
-** multi-threaded IncrMerger objects.
-*/
-static void *vdbeIncrPopulateThread(void *pCtx){
- IncrMerger *pIncr = (IncrMerger*)pCtx;
- void *pRet = SQLITE_INT_TO_PTR( vdbeIncrPopulate(pIncr) );
- pIncr->pTask->bDone = 1;
- return pRet;
-}
-
-/*
-** Launch a background thread to populate aFile[1] of pIncr.
-*/
-static int vdbeIncrBgPopulate(IncrMerger *pIncr){
- void *p = (void*)pIncr;
- assert( pIncr->bUseThread );
- return vdbeSorterCreateThread(pIncr->pTask, vdbeIncrPopulateThread, p);
-}
-#endif
-
-/*
-** This function is called when the PmaReader corresponding to pIncr has
-** finished reading the contents of aFile[0]. Its purpose is to "refill"
-** aFile[0] such that the PmaReader should start rereading it from the
-** beginning.
-**
-** For single-threaded objects, this is accomplished by literally reading
-** keys from pIncr->pMerger and repopulating aFile[0].
-**
-** For multi-threaded objects, all that is required is to wait until the
-** background thread is finished (if it is not already) and then swap
-** aFile[0] and aFile[1] in place. If the contents of pMerger have not
-** been exhausted, this function also launches a new background thread
-** to populate the new aFile[1].
-**
-** SQLITE_OK is returned on success, or an SQLite error code otherwise.
-*/
-static int vdbeIncrSwap(IncrMerger *pIncr){
- int rc = SQLITE_OK;
-
-#if SQLITE_MAX_WORKER_THREADS>0
- if( pIncr->bUseThread ){
- rc = vdbeSorterJoinThread(pIncr->pTask);
-
- if( rc==SQLITE_OK ){
- SorterFile f0 = pIncr->aFile[0];
- pIncr->aFile[0] = pIncr->aFile[1];
- pIncr->aFile[1] = f0;
- }
-
- if( rc==SQLITE_OK ){
- if( pIncr->aFile[0].iEof==pIncr->iStartOff ){
- pIncr->bEof = 1;
- }else{
- rc = vdbeIncrBgPopulate(pIncr);
- }
- }
- }else
-#endif
- {
- rc = vdbeIncrPopulate(pIncr);
- pIncr->aFile[0] = pIncr->aFile[1];
- if( pIncr->aFile[0].iEof==pIncr->iStartOff ){
- pIncr->bEof = 1;
- }
- }
-
- return rc;
-}
-
-/*
-** Allocate and return a new IncrMerger object to read data from pMerger.
-**
-** If an OOM condition is encountered, return NULL. In this case free the
-** pMerger argument before returning.
-*/
-static int vdbeIncrMergerNew(
- SortSubtask *pTask, /* The thread that will be using the new IncrMerger */
- MergeEngine *pMerger, /* The MergeEngine that the IncrMerger will control */
- IncrMerger **ppOut /* Write the new IncrMerger here */
-){
- int rc = SQLITE_OK;
- IncrMerger *pIncr = *ppOut = (IncrMerger*)
- (sqlite3FaultSim(100) ? 0 : sqlite3MallocZero(sizeof(*pIncr)));
- if( pIncr ){
- pIncr->pMerger = pMerger;
- pIncr->pTask = pTask;
- pIncr->mxSz = MAX(pTask->pSorter->mxKeysize+9,pTask->pSorter->mxPmaSize/2);
- pTask->file2.iEof += pIncr->mxSz;
- }else{
- vdbeMergeEngineFree(pMerger);
- rc = SQLITE_NOMEM_BKPT;
- }
- return rc;
-}
-
-#if SQLITE_MAX_WORKER_THREADS>0
-/*
-** Set the "use-threads" flag on object pIncr.
-*/
-static void vdbeIncrMergerSetThreads(IncrMerger *pIncr){
- pIncr->bUseThread = 1;
- pIncr->pTask->file2.iEof -= pIncr->mxSz;
-}
-#endif /* SQLITE_MAX_WORKER_THREADS>0 */
-
-
-
-/*
-** Recompute pMerger->aTree[iOut] by comparing the next keys on the
-** two PmaReaders that feed that entry. Neither of the PmaReaders
-** are advanced. This routine merely does the comparison.
-*/
-static void vdbeMergeEngineCompare(
- MergeEngine *pMerger, /* Merge engine containing PmaReaders to compare */
- int iOut /* Store the result in pMerger->aTree[iOut] */
-){
- int i1;
- int i2;
- int iRes;
- PmaReader *p1;
- PmaReader *p2;
-
- assert( iOut<pMerger->nTree && iOut>0 );
-
- if( iOut>=(pMerger->nTree/2) ){
- i1 = (iOut - pMerger->nTree/2) * 2;
- i2 = i1 + 1;
- }else{
- i1 = pMerger->aTree[iOut*2];
- i2 = pMerger->aTree[iOut*2+1];
- }
-
- p1 = &pMerger->aReadr[i1];
- p2 = &pMerger->aReadr[i2];
-
- if( p1->pFd==0 ){
- iRes = i2;
- }else if( p2->pFd==0 ){
- iRes = i1;
- }else{
- SortSubtask *pTask = pMerger->pTask;
- int bCached = 0;
- int res;
- assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */
- res = pTask->xCompare(
- pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey
- );
- if( res<=0 ){
- iRes = i1;
- }else{
- iRes = i2;
- }
- }
-
- pMerger->aTree[iOut] = iRes;
-}
-
-/*
-** Allowed values for the eMode parameter to vdbeMergeEngineInit()
-** and vdbePmaReaderIncrMergeInit().
-**
-** Only INCRINIT_NORMAL is valid in single-threaded builds (when
-** SQLITE_MAX_WORKER_THREADS==0). The other values are only used
-** when there exists one or more separate worker threads.
-*/
-#define INCRINIT_NORMAL 0
-#define INCRINIT_TASK 1
-#define INCRINIT_ROOT 2
-
-/*
-** Forward reference required as the vdbeIncrMergeInit() and
-** vdbePmaReaderIncrInit() routines are called mutually recursively when
-** building a merge tree.
-*/
-static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode);
-
-/*
-** Initialize the MergeEngine object passed as the second argument. Once this
-** function returns, the first key of merged data may be read from the
-** MergeEngine object in the usual fashion.
-**
-** If argument eMode is INCRINIT_ROOT, then it is assumed that any IncrMerge
-** objects attached to the PmaReader objects that the merger reads from have
-** already been populated, but that they have not yet populated aFile[0] and
-** set the PmaReader objects up to read from it. In this case all that is
-** required is to call vdbePmaReaderNext() on each PmaReader to point it at
-** its first key.
-**
-** Otherwise, if eMode is any value other than INCRINIT_ROOT, then use
-** vdbePmaReaderIncrMergeInit() to initialize each PmaReader that feeds data
-** to pMerger.
-**
-** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
-*/
-static int vdbeMergeEngineInit(
- SortSubtask *pTask, /* Thread that will run pMerger */
- MergeEngine *pMerger, /* MergeEngine to initialize */
- int eMode /* One of the INCRINIT_XXX constants */
-){
- int rc = SQLITE_OK; /* Return code */
- int i; /* For looping over PmaReader objects */
- int nTree = pMerger->nTree;
-
- /* eMode is always INCRINIT_NORMAL in single-threaded mode */
- assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL );
-
- /* Verify that the MergeEngine is assigned to a single thread */
- assert( pMerger->pTask==0 );
- pMerger->pTask = pTask;
-
- for(i=0; i<nTree; i++){
- if( SQLITE_MAX_WORKER_THREADS>0 && eMode==INCRINIT_ROOT ){
- /* PmaReaders should be normally initialized in order, as if they are
- ** reading from the same temp file this makes for more linear file IO.
- ** However, in the INCRINIT_ROOT case, if PmaReader aReadr[nTask-1] is
- ** in use it will block the vdbePmaReaderNext() call while it uses
- ** the main thread to fill its buffer. So calling PmaReaderNext()
- ** on this PmaReader before any of the multi-threaded PmaReaders takes
- ** better advantage of multi-processor hardware. */
- rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]);
- }else{
- rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL);
- }
- if( rc!=SQLITE_OK ) return rc;
- }
-
- for(i=pMerger->nTree-1; i>0; i--){
- vdbeMergeEngineCompare(pMerger, i);
- }
- return pTask->pUnpacked->errCode;
-}
-
-/*
-** The PmaReader passed as the first argument is guaranteed to be an
-** incremental-reader (pReadr->pIncr!=0). This function serves to open
-** and/or initialize the temp file related fields of the IncrMerge
-** object at (pReadr->pIncr).
-**
-** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders
-** in the sub-tree headed by pReadr are also initialized. Data is then
-** loaded into the buffers belonging to pReadr and it is set to point to
-** the first key in its range.
-**
-** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed
-** to be a multi-threaded PmaReader and this function is being called in a
-** background thread. In this case all PmaReaders in the sub-tree are
-** initialized as for INCRINIT_NORMAL and the aFile[1] buffer belonging to
-** pReadr is populated. However, pReadr itself is not set up to point
-** to its first key. A call to vdbePmaReaderNext() is still required to do
-** that.
-**
-** The reason this function does not call vdbePmaReaderNext() immediately
-** in the INCRINIT_TASK case is that vdbePmaReaderNext() assumes that it has
-** to block on thread (pTask->thread) before accessing aFile[1]. But, since
-** this entire function is being run by thread (pTask->thread), that will
-** lead to the current background thread attempting to join itself.
-**
-** Finally, if argument eMode is set to INCRINIT_ROOT, it may be assumed
-** that pReadr->pIncr is a multi-threaded IncrMerge objects, and that all
-** child-trees have already been initialized using IncrInit(INCRINIT_TASK).
-** In this case vdbePmaReaderNext() is called on all child PmaReaders and
-** the current PmaReader set to point to the first key in its range.
-**
-** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
-*/
-static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){
- int rc = SQLITE_OK;
- IncrMerger *pIncr = pReadr->pIncr;
- SortSubtask *pTask = pIncr->pTask;
- sqlite3 *db = pTask->pSorter->db;
-
- /* eMode is always INCRINIT_NORMAL in single-threaded mode */
- assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL );
-
- rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
-
- /* Set up the required files for pIncr. A multi-theaded IncrMerge object
- ** requires two temp files to itself, whereas a single-threaded object
- ** only requires a region of pTask->file2. */
- if( rc==SQLITE_OK ){
- int mxSz = pIncr->mxSz;
-#if SQLITE_MAX_WORKER_THREADS>0
- if( pIncr->bUseThread ){
- rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd);
- if( rc==SQLITE_OK ){
- rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd);
- }
- }else
-#endif
- /*if( !pIncr->bUseThread )*/{
- if( pTask->file2.pFd==0 ){
- assert( pTask->file2.iEof>0 );
- rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd);
- pTask->file2.iEof = 0;
- }
- if( rc==SQLITE_OK ){
- pIncr->aFile[1].pFd = pTask->file2.pFd;
- pIncr->iStartOff = pTask->file2.iEof;
- pTask->file2.iEof += mxSz;
- }
- }
- }
-
-#if SQLITE_MAX_WORKER_THREADS>0
- if( rc==SQLITE_OK && pIncr->bUseThread ){
- /* Use the current thread to populate aFile[1], even though this
- ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object,
- ** then this function is already running in background thread
- ** pIncr->pTask->thread.
- **
- ** If this is the INCRINIT_ROOT object, then it is running in the
- ** main VDBE thread. But that is Ok, as that thread cannot return
- ** control to the VDBE or proceed with anything useful until the
- ** first results are ready from this merger object anyway.
- */
- assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK );
- rc = vdbeIncrPopulate(pIncr);
- }
-#endif
-
- if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){
- rc = vdbePmaReaderNext(pReadr);
- }
-
- return rc;
-}
-
-#if SQLITE_MAX_WORKER_THREADS>0
-/*
-** The main routine for vdbePmaReaderIncrMergeInit() operations run in
-** background threads.
-*/
-static void *vdbePmaReaderBgIncrInit(void *pCtx){
- PmaReader *pReader = (PmaReader*)pCtx;
- void *pRet = SQLITE_INT_TO_PTR(
- vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK)
- );
- pReader->pIncr->pTask->bDone = 1;
- return pRet;
-}
-#endif
-
-/*
-** If the PmaReader passed as the first argument is not an incremental-reader
-** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes
-** the vdbePmaReaderIncrMergeInit() function with the parameters passed to
-** this routine to initialize the incremental merge.
-**
-** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1),
-** then a background thread is launched to call vdbePmaReaderIncrMergeInit().
-** Or, if the IncrMerger is single threaded, the same function is called
-** using the current thread.
-*/
-static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){
- IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */
- int rc = SQLITE_OK; /* Return code */
- if( pIncr ){
-#if SQLITE_MAX_WORKER_THREADS>0
- assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK );
- if( pIncr->bUseThread ){
- void *pCtx = (void*)pReadr;
- rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx);
- }else
-#endif
- {
- rc = vdbePmaReaderIncrMergeInit(pReadr, eMode);
- }
- }
- return rc;
-}
-
-/*
-** Allocate a new MergeEngine object to merge the contents of nPMA level-0
-** PMAs from pTask->file. If no error occurs, set *ppOut to point to
-** the new object and return SQLITE_OK. Or, if an error does occur, set *ppOut
-** to NULL and return an SQLite error code.
-**
-** When this function is called, *piOffset is set to the offset of the
-** first PMA to read from pTask->file. Assuming no error occurs, it is
-** set to the offset immediately following the last byte of the last
-** PMA before returning. If an error does occur, then the final value of
-** *piOffset is undefined.
-*/
-static int vdbeMergeEngineLevel0(
- SortSubtask *pTask, /* Sorter task to read from */
- int nPMA, /* Number of PMAs to read */
- i64 *piOffset, /* IN/OUT: Readr offset in pTask->file */
- MergeEngine **ppOut /* OUT: New merge-engine */
-){
- MergeEngine *pNew; /* Merge engine to return */
- i64 iOff = *piOffset;
- int i;
- int rc = SQLITE_OK;
-
- *ppOut = pNew = vdbeMergeEngineNew(nPMA);
- if( pNew==0 ) rc = SQLITE_NOMEM_BKPT;
-
- for(i=0; i<nPMA && rc==SQLITE_OK; i++){
- i64 nDummy = 0;
- PmaReader *pReadr = &pNew->aReadr[i];
- rc = vdbePmaReaderInit(pTask, &pTask->file, iOff, pReadr, &nDummy);
- iOff = pReadr->iEof;
- }
-
- if( rc!=SQLITE_OK ){
- vdbeMergeEngineFree(pNew);
- *ppOut = 0;
- }
- *piOffset = iOff;
- return rc;
-}
-
-/*
-** Return the depth of a tree comprising nPMA PMAs, assuming a fanout of
-** SORTER_MAX_MERGE_COUNT. The returned value does not include leaf nodes.
-**
-** i.e.
-**
-** nPMA<=16 -> TreeDepth() == 0
-** nPMA<=256 -> TreeDepth() == 1
-** nPMA<=65536 -> TreeDepth() == 2
-*/
-static int vdbeSorterTreeDepth(int nPMA){
- int nDepth = 0;
- i64 nDiv = SORTER_MAX_MERGE_COUNT;
- while( nDiv < (i64)nPMA ){
- nDiv = nDiv * SORTER_MAX_MERGE_COUNT;
- nDepth++;
- }
- return nDepth;
-}
-
-/*
-** pRoot is the root of an incremental merge-tree with depth nDepth (according
-** to vdbeSorterTreeDepth()). pLeaf is the iSeq'th leaf to be added to the
-** tree, counting from zero. This function adds pLeaf to the tree.
-**
-** If successful, SQLITE_OK is returned. If an error occurs, an SQLite error
-** code is returned and pLeaf is freed.
-*/
-static int vdbeSorterAddToTree(
- SortSubtask *pTask, /* Task context */
- int nDepth, /* Depth of tree according to TreeDepth() */
- int iSeq, /* Sequence number of leaf within tree */
- MergeEngine *pRoot, /* Root of tree */
- MergeEngine *pLeaf /* Leaf to add to tree */
-){
- int rc = SQLITE_OK;
- int nDiv = 1;
- int i;
- MergeEngine *p = pRoot;
- IncrMerger *pIncr;
-
- rc = vdbeIncrMergerNew(pTask, pLeaf, &pIncr);
-
- for(i=1; i<nDepth; i++){
- nDiv = nDiv * SORTER_MAX_MERGE_COUNT;
- }
-
- for(i=1; i<nDepth && rc==SQLITE_OK; i++){
- int iIter = (iSeq / nDiv) % SORTER_MAX_MERGE_COUNT;
- PmaReader *pReadr = &p->aReadr[iIter];
-
- if( pReadr->pIncr==0 ){
- MergeEngine *pNew = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT);
- if( pNew==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- rc = vdbeIncrMergerNew(pTask, pNew, &pReadr->pIncr);
- }
- }
- if( rc==SQLITE_OK ){
- p = pReadr->pIncr->pMerger;
- nDiv = nDiv / SORTER_MAX_MERGE_COUNT;
- }
- }
-
- if( rc==SQLITE_OK ){
- p->aReadr[iSeq % SORTER_MAX_MERGE_COUNT].pIncr = pIncr;
- }else{
- vdbeIncrFree(pIncr);
- }
- return rc;
-}
-
-/*
-** This function is called as part of a SorterRewind() operation on a sorter
-** that has already written two or more level-0 PMAs to one or more temp
-** files. It builds a tree of MergeEngine/IncrMerger/PmaReader objects that
-** can be used to incrementally merge all PMAs on disk.
-**
-** If successful, SQLITE_OK is returned and *ppOut set to point to the
-** MergeEngine object at the root of the tree before returning. Or, if an
-** error occurs, an SQLite error code is returned and the final value
-** of *ppOut is undefined.
-*/
-static int vdbeSorterMergeTreeBuild(
- VdbeSorter *pSorter, /* The VDBE cursor that implements the sort */
- MergeEngine **ppOut /* Write the MergeEngine here */
-){
- MergeEngine *pMain = 0;
- int rc = SQLITE_OK;
- int iTask;
-
-#if SQLITE_MAX_WORKER_THREADS>0
- /* If the sorter uses more than one task, then create the top-level
- ** MergeEngine here. This MergeEngine will read data from exactly
- ** one PmaReader per sub-task. */
- assert( pSorter->bUseThreads || pSorter->nTask==1 );
- if( pSorter->nTask>1 ){
- pMain = vdbeMergeEngineNew(pSorter->nTask);
- if( pMain==0 ) rc = SQLITE_NOMEM_BKPT;
- }
-#endif
-
- for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
- SortSubtask *pTask = &pSorter->aTask[iTask];
- assert( pTask->nPMA>0 || SQLITE_MAX_WORKER_THREADS>0 );
- if( SQLITE_MAX_WORKER_THREADS==0 || pTask->nPMA ){
- MergeEngine *pRoot = 0; /* Root node of tree for this task */
- int nDepth = vdbeSorterTreeDepth(pTask->nPMA);
- i64 iReadOff = 0;
-
- if( pTask->nPMA<=SORTER_MAX_MERGE_COUNT ){
- rc = vdbeMergeEngineLevel0(pTask, pTask->nPMA, &iReadOff, &pRoot);
- }else{
- int i;
- int iSeq = 0;
- pRoot = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT);
- if( pRoot==0 ) rc = SQLITE_NOMEM_BKPT;
- for(i=0; i<pTask->nPMA && rc==SQLITE_OK; i += SORTER_MAX_MERGE_COUNT){
- MergeEngine *pMerger = 0; /* New level-0 PMA merger */
- int nReader; /* Number of level-0 PMAs to merge */
-
- nReader = MIN(pTask->nPMA - i, SORTER_MAX_MERGE_COUNT);
- rc = vdbeMergeEngineLevel0(pTask, nReader, &iReadOff, &pMerger);
- if( rc==SQLITE_OK ){
- rc = vdbeSorterAddToTree(pTask, nDepth, iSeq++, pRoot, pMerger);
- }
- }
- }
-
- if( rc==SQLITE_OK ){
-#if SQLITE_MAX_WORKER_THREADS>0
- if( pMain!=0 ){
- rc = vdbeIncrMergerNew(pTask, pRoot, &pMain->aReadr[iTask].pIncr);
- }else
-#endif
- {
- assert( pMain==0 );
- pMain = pRoot;
- }
- }else{
- vdbeMergeEngineFree(pRoot);
- }
- }
- }
-
- if( rc!=SQLITE_OK ){
- vdbeMergeEngineFree(pMain);
- pMain = 0;
- }
- *ppOut = pMain;
- return rc;
-}
-
-/*
-** This function is called as part of an sqlite3VdbeSorterRewind() operation
-** on a sorter that has written two or more PMAs to temporary files. It sets
-** up either VdbeSorter.pMerger (for single threaded sorters) or pReader
-** (for multi-threaded sorters) so that it can be used to iterate through
-** all records stored in the sorter.
-**
-** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
-*/
-static int vdbeSorterSetupMerge(VdbeSorter *pSorter){
- int rc; /* Return code */
- SortSubtask *pTask0 = &pSorter->aTask[0];
- MergeEngine *pMain = 0;
-#if SQLITE_MAX_WORKER_THREADS
- sqlite3 *db = pTask0->pSorter->db;
- int i;
- SorterCompare xCompare = vdbeSorterGetCompare(pSorter);
- for(i=0; i<pSorter->nTask; i++){
- pSorter->aTask[i].xCompare = xCompare;
- }
-#endif
-
- rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);
- if( rc==SQLITE_OK ){
-#if SQLITE_MAX_WORKER_THREADS
- assert( pSorter->bUseThreads==0 || pSorter->nTask>1 );
- if( pSorter->bUseThreads ){
- int iTask;
- PmaReader *pReadr = 0;
- SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1];
- rc = vdbeSortAllocUnpacked(pLast);
- if( rc==SQLITE_OK ){
- pReadr = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader));
- pSorter->pReader = pReadr;
- if( pReadr==0 ) rc = SQLITE_NOMEM_BKPT;
- }
- if( rc==SQLITE_OK ){
- rc = vdbeIncrMergerNew(pLast, pMain, &pReadr->pIncr);
- if( rc==SQLITE_OK ){
- vdbeIncrMergerSetThreads(pReadr->pIncr);
- for(iTask=0; iTask<(pSorter->nTask-1); iTask++){
- IncrMerger *pIncr;
- if( (pIncr = pMain->aReadr[iTask].pIncr) ){
- vdbeIncrMergerSetThreads(pIncr);
- assert( pIncr->pTask!=pLast );
- }
- }
- for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
- /* Check that:
- **
- ** a) The incremental merge object is configured to use the
- ** right task, and
- ** b) If it is using task (nTask-1), it is configured to run
- ** in single-threaded mode. This is important, as the
- ** root merge (INCRINIT_ROOT) will be using the same task
- ** object.
- */
- PmaReader *p = &pMain->aReadr[iTask];
- assert( p->pIncr==0 || (
- (p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */
- && (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */
- ));
- rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK);
- }
- }
- pMain = 0;
- }
- if( rc==SQLITE_OK ){
- rc = vdbePmaReaderIncrMergeInit(pReadr, INCRINIT_ROOT);
- }
- }else
-#endif
- {
- rc = vdbeMergeEngineInit(pTask0, pMain, INCRINIT_NORMAL);
- pSorter->pMerger = pMain;
- pMain = 0;
- }
- }
-
- if( rc!=SQLITE_OK ){
- vdbeMergeEngineFree(pMain);
- }
- return rc;
-}
-
-
-/*
-** Once the sorter has been populated by calls to sqlite3VdbeSorterWrite,
-** this function is called to prepare for iterating through the records
-** in sorted order.
-*/
-int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){
- VdbeSorter *pSorter;
- int rc = SQLITE_OK; /* Return code */
-
- assert( pCsr->eCurType==CURTYPE_SORTER );
- pSorter = pCsr->uc.pSorter;
- assert( pSorter );
-
- /* If no data has been written to disk, then do not do so now. Instead,
- ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly
- ** from the in-memory list. */
- if( pSorter->bUsePMA==0 ){
- if( pSorter->list.pList ){
- *pbEof = 0;
- rc = vdbeSorterSort(&pSorter->aTask[0], &pSorter->list);
- }else{
- *pbEof = 1;
- }
- return rc;
- }
-
- /* Write the current in-memory list to a PMA. When the VdbeSorterWrite()
- ** function flushes the contents of memory to disk, it immediately always
- ** creates a new list consisting of a single key immediately afterwards.
- ** So the list is never empty at this point. */
- assert( pSorter->list.pList );
- rc = vdbeSorterFlushPMA(pSorter);
-
- /* Join all threads */
- rc = vdbeSorterJoinAll(pSorter, rc);
-
- vdbeSorterRewindDebug("rewind");
-
- /* Assuming no errors have occurred, set up a merger structure to
- ** incrementally read and merge all remaining PMAs. */
- assert( pSorter->pReader==0 );
- if( rc==SQLITE_OK ){
- rc = vdbeSorterSetupMerge(pSorter);
- *pbEof = 0;
- }
-
- vdbeSorterRewindDebug("rewinddone");
- return rc;
-}
-
-/*
-** Advance to the next element in the sorter. Return value:
-**
-** SQLITE_OK success
-** SQLITE_DONE end of data
-** otherwise some kind of error.
-*/
-int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr){
- VdbeSorter *pSorter;
- int rc; /* Return code */
-
- assert( pCsr->eCurType==CURTYPE_SORTER );
- pSorter = pCsr->uc.pSorter;
- assert( pSorter->bUsePMA || (pSorter->pReader==0 && pSorter->pMerger==0) );
- if( pSorter->bUsePMA ){
- assert( pSorter->pReader==0 || pSorter->pMerger==0 );
- assert( pSorter->bUseThreads==0 || pSorter->pReader );
- assert( pSorter->bUseThreads==1 || pSorter->pMerger );
-#if SQLITE_MAX_WORKER_THREADS>0
- if( pSorter->bUseThreads ){
- rc = vdbePmaReaderNext(pSorter->pReader);
- if( rc==SQLITE_OK && pSorter->pReader->pFd==0 ) rc = SQLITE_DONE;
- }else
-#endif
- /*if( !pSorter->bUseThreads )*/ {
- int res = 0;
- assert( pSorter->pMerger!=0 );
- assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) );
- rc = vdbeMergeEngineStep(pSorter->pMerger, &res);
- if( rc==SQLITE_OK && res ) rc = SQLITE_DONE;
- }
- }else{
- SorterRecord *pFree = pSorter->list.pList;
- pSorter->list.pList = pFree->u.pNext;
- pFree->u.pNext = 0;
- if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree);
- rc = pSorter->list.pList ? SQLITE_OK : SQLITE_DONE;
- }
- return rc;
-}
-
-/*
-** Return a pointer to a buffer owned by the sorter that contains the
-** current key.
-*/
-static void *vdbeSorterRowkey(
- const VdbeSorter *pSorter, /* Sorter object */
- int *pnKey /* OUT: Size of current key in bytes */
-){
- void *pKey;
- if( pSorter->bUsePMA ){
- PmaReader *pReader;
-#if SQLITE_MAX_WORKER_THREADS>0
- if( pSorter->bUseThreads ){
- pReader = pSorter->pReader;
- }else
-#endif
- /*if( !pSorter->bUseThreads )*/{
- pReader = &pSorter->pMerger->aReadr[pSorter->pMerger->aTree[1]];
- }
- *pnKey = pReader->nKey;
- pKey = pReader->aKey;
- }else{
- *pnKey = pSorter->list.pList->nVal;
- pKey = SRVAL(pSorter->list.pList);
- }
- return pKey;
-}
-
-/*
-** Copy the current sorter key into the memory cell pOut.
-*/
-int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
- VdbeSorter *pSorter;
- void *pKey; int nKey; /* Sorter key to copy into pOut */
-
- assert( pCsr->eCurType==CURTYPE_SORTER );
- pSorter = pCsr->uc.pSorter;
- pKey = vdbeSorterRowkey(pSorter, &nKey);
- if( sqlite3VdbeMemClearAndResize(pOut, nKey) ){
- return SQLITE_NOMEM_BKPT;
- }
- pOut->n = nKey;
- MemSetTypeFlag(pOut, MEM_Blob);
- memcpy(pOut->z, pKey, nKey);
-
- return SQLITE_OK;
-}
-
-/*
-** Compare the key in memory cell pVal with the key that the sorter cursor
-** passed as the first argument currently points to. For the purposes of
-** the comparison, ignore the rowid field at the end of each record.
-**
-** If the sorter cursor key contains any NULL values, consider it to be
-** less than pVal. Even if pVal also contains NULL values.
-**
-** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
-** Otherwise, set *pRes to a negative, zero or positive value if the
-** key in pVal is smaller than, equal to or larger than the current sorter
-** key.
-**
-** This routine forms the core of the OP_SorterCompare opcode, which in
-** turn is used to verify uniqueness when constructing a UNIQUE INDEX.
-*/
-int sqlite3VdbeSorterCompare(
- const VdbeCursor *pCsr, /* Sorter cursor */
- Mem *pVal, /* Value to compare to current sorter key */
- int nKeyCol, /* Compare this many columns */
- int *pRes /* OUT: Result of comparison */
-){
- VdbeSorter *pSorter;
- UnpackedRecord *r2;
- KeyInfo *pKeyInfo;
- int i;
- void *pKey; int nKey; /* Sorter key to compare pVal with */
-
- assert( pCsr->eCurType==CURTYPE_SORTER );
- pSorter = pCsr->uc.pSorter;
- r2 = pSorter->pUnpacked;
- pKeyInfo = pCsr->pKeyInfo;
- if( r2==0 ){
- r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
- if( r2==0 ) return SQLITE_NOMEM_BKPT;
- r2->nField = nKeyCol;
- }
- assert( r2->nField==nKeyCol );
-
- pKey = vdbeSorterRowkey(pSorter, &nKey);
- sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2);
- for(i=0; i<nKeyCol; i++){
- if( r2->aMem[i].flags & MEM_Null ){
- *pRes = -1;
- return SQLITE_OK;
- }
- }
-
- *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2);
- return SQLITE_OK;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbetrace.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbetrace.c
deleted file mode 100644
index b6d93813367..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vdbetrace.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
-** 2009 November 25
-**
-** 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 contains code used to insert the values of host parameters
-** (aka "wildcards") into the SQL text output by sqlite3_trace().
-**
-** The Vdbe parse-tree explainer is also found here.
-*/
-#include "sqliteInt.h"
-#include "vdbeInt.h"
-
-#ifndef SQLITE_OMIT_TRACE
-
-/*
-** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of
-** bytes in this text up to but excluding the first character in
-** a host parameter. If the text contains no host parameters, return
-** the total number of bytes in the text.
-*/
-static int findNextHostParameter(const char *zSql, int *pnToken){
- int tokenType;
- int nTotal = 0;
- int n;
-
- *pnToken = 0;
- while( zSql[0] ){
- n = sqlite3GetToken((u8*)zSql, &tokenType);
- assert( n>0 && tokenType!=TK_ILLEGAL );
- if( tokenType==TK_VARIABLE ){
- *pnToken = n;
- break;
- }
- nTotal += n;
- zSql += n;
- }
- return nTotal;
-}
-
-/*
-** This function returns a pointer to a nul-terminated string in memory
-** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the
-** string contains a copy of zRawSql but with host parameters expanded to
-** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1,
-** then the returned string holds a copy of zRawSql with "-- " prepended
-** to each line of text.
-**
-** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then
-** then long strings and blobs are truncated to that many bytes. This
-** can be used to prevent unreasonably large trace strings when dealing
-** with large (multi-megabyte) strings and blobs.
-**
-** The calling function is responsible for making sure the memory returned
-** is eventually freed.
-**
-** ALGORITHM: Scan the input string looking for host parameters in any of
-** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within
-** string literals, quoted identifier names, and comments. For text forms,
-** the host parameter index is found by scanning the prepared
-** statement for the corresponding OP_Variable opcode. Once the host
-** parameter index is known, locate the value in p->aVar[]. Then render
-** the value as a literal in place of the host parameter name.
-*/
-char *sqlite3VdbeExpandSql(
- Vdbe *p, /* The prepared statement being evaluated */
- const char *zRawSql /* Raw text of the SQL statement */
-){
- sqlite3 *db; /* The database connection */
- int idx = 0; /* Index of a host parameter */
- int nextIndex = 1; /* Index of next ? host parameter */
- int n; /* Length of a token prefix */
- int nToken; /* Length of the parameter token */
- int i; /* Loop counter */
- Mem *pVar; /* Value of a host parameter */
- StrAccum out; /* Accumulate the output here */
-#ifndef SQLITE_OMIT_UTF16
- Mem utf8; /* Used to convert UTF16 into UTF8 for display */
-#endif
- char zBase[100]; /* Initial working space */
-
- db = p->db;
- sqlite3StrAccumInit(&out, 0, zBase, sizeof(zBase),
- db->aLimit[SQLITE_LIMIT_LENGTH]);
- if( db->nVdbeExec>1 ){
- while( *zRawSql ){
- const char *zStart = zRawSql;
- while( *(zRawSql++)!='\n' && *zRawSql );
- sqlite3_str_append(&out, "-- ", 3);
- assert( (zRawSql - zStart) > 0 );
- sqlite3_str_append(&out, zStart, (int)(zRawSql-zStart));
- }
- }else if( p->nVar==0 ){
- sqlite3_str_append(&out, zRawSql, sqlite3Strlen30(zRawSql));
- }else{
- while( zRawSql[0] ){
- n = findNextHostParameter(zRawSql, &nToken);
- assert( n>0 );
- sqlite3_str_append(&out, zRawSql, n);
- zRawSql += n;
- assert( zRawSql[0] || nToken==0 );
- if( nToken==0 ) break;
- if( zRawSql[0]=='?' ){
- if( nToken>1 ){
- assert( sqlite3Isdigit(zRawSql[1]) );
- sqlite3GetInt32(&zRawSql[1], &idx);
- }else{
- idx = nextIndex;
- }
- }else{
- assert( zRawSql[0]==':' || zRawSql[0]=='$' ||
- zRawSql[0]=='@' || zRawSql[0]=='#' );
- testcase( zRawSql[0]==':' );
- testcase( zRawSql[0]=='$' );
- testcase( zRawSql[0]=='@' );
- testcase( zRawSql[0]=='#' );
- idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
- assert( idx>0 );
- }
- zRawSql += nToken;
- nextIndex = idx + 1;
- assert( idx>0 && idx<=p->nVar );
- pVar = &p->aVar[idx-1];
- if( pVar->flags & MEM_Null ){
- sqlite3_str_append(&out, "NULL", 4);
- }else if( pVar->flags & MEM_Int ){
- sqlite3_str_appendf(&out, "%lld", pVar->u.i);
- }else if( pVar->flags & MEM_Real ){
- sqlite3_str_appendf(&out, "%!.15g", pVar->u.r);
- }else if( pVar->flags & MEM_Str ){
- int nOut; /* Number of bytes of the string text to include in output */
-#ifndef SQLITE_OMIT_UTF16
- u8 enc = ENC(db);
- if( enc!=SQLITE_UTF8 ){
- memset(&utf8, 0, sizeof(utf8));
- utf8.db = db;
- sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
- if( SQLITE_NOMEM==sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8) ){
- out.accError = SQLITE_NOMEM;
- out.nAlloc = 0;
- }
- pVar = &utf8;
- }
-#endif
- nOut = pVar->n;
-#ifdef SQLITE_TRACE_SIZE_LIMIT
- if( nOut>SQLITE_TRACE_SIZE_LIMIT ){
- nOut = SQLITE_TRACE_SIZE_LIMIT;
- while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
- }
-#endif
- sqlite3_str_appendf(&out, "'%.*q'", nOut, pVar->z);
-#ifdef SQLITE_TRACE_SIZE_LIMIT
- if( nOut<pVar->n ){
- sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut);
- }
-#endif
-#ifndef SQLITE_OMIT_UTF16
- if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
-#endif
- }else if( pVar->flags & MEM_Zero ){
- sqlite3_str_appendf(&out, "zeroblob(%d)", pVar->u.nZero);
- }else{
- int nOut; /* Number of bytes of the blob to include in output */
- assert( pVar->flags & MEM_Blob );
- sqlite3_str_append(&out, "x'", 2);
- nOut = pVar->n;
-#ifdef SQLITE_TRACE_SIZE_LIMIT
- if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
-#endif
- for(i=0; i<nOut; i++){
- sqlite3_str_appendf(&out, "%02x", pVar->z[i]&0xff);
- }
- sqlite3_str_append(&out, "'", 1);
-#ifdef SQLITE_TRACE_SIZE_LIMIT
- if( nOut<pVar->n ){
- sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut);
- }
-#endif
- }
- }
- }
- if( out.accError ) sqlite3_str_reset(&out);
- return sqlite3StrAccumFinish(&out);
-}
-
-#endif /* #ifndef SQLITE_OMIT_TRACE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vtab.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/vtab.c
deleted file mode 100644
index 7894bbc8b88..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vtab.c
+++ /dev/null
@@ -1,1246 +0,0 @@
-/*
-** 2006 June 10
-**
-** 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 contains code used to help implement virtual tables.
-*/
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-#include "sqliteInt.h"
-
-/*
-** Before a virtual table xCreate() or xConnect() method is invoked, the
-** sqlite3.pVtabCtx member variable is set to point to an instance of
-** this struct allocated on the stack. It is used by the implementation of
-** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
-** are invoked only from within xCreate and xConnect methods.
-*/
-struct VtabCtx {
- VTable *pVTable; /* The virtual table being constructed */
- Table *pTab; /* The Table object to which the virtual table belongs */
- VtabCtx *pPrior; /* Parent context (if any) */
- int bDeclared; /* True after sqlite3_declare_vtab() is called */
-};
-
-/*
-** Construct and install a Module object for a virtual table. When this
-** routine is called, it is guaranteed that all appropriate locks are held
-** and the module is not already part of the connection.
-*/
-Module *sqlite3VtabCreateModule(
- sqlite3 *db, /* Database in which module is registered */
- const char *zName, /* Name assigned to this module */
- const sqlite3_module *pModule, /* The definition of the module */
- void *pAux, /* Context pointer for xCreate/xConnect */
- void (*xDestroy)(void *) /* Module destructor function */
-){
- Module *pMod;
- int nName = sqlite3Strlen30(zName);
- pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1);
- if( pMod==0 ){
- sqlite3OomFault(db);
- }else{
- Module *pDel;
- char *zCopy = (char *)(&pMod[1]);
- memcpy(zCopy, zName, nName+1);
- pMod->zName = zCopy;
- pMod->pModule = pModule;
- pMod->pAux = pAux;
- pMod->xDestroy = xDestroy;
- pMod->pEpoTab = 0;
- pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
- assert( pDel==0 || pDel==pMod );
- if( pDel ){
- sqlite3OomFault(db);
- sqlite3DbFree(db, pDel);
- pMod = 0;
- }
- }
- return pMod;
-}
-
-/*
-** The actual function that does the work of creating a new module.
-** This function implements the sqlite3_create_module() and
-** sqlite3_create_module_v2() interfaces.
-*/
-static int createModule(
- sqlite3 *db, /* Database in which module is registered */
- const char *zName, /* Name assigned to this module */
- const sqlite3_module *pModule, /* The definition of the module */
- void *pAux, /* Context pointer for xCreate/xConnect */
- void (*xDestroy)(void *) /* Module destructor function */
-){
- int rc = SQLITE_OK;
-
- sqlite3_mutex_enter(db->mutex);
- if( sqlite3HashFind(&db->aModule, zName) ){
- rc = SQLITE_MISUSE_BKPT;
- }else{
- (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
- }
- rc = sqlite3ApiExit(db, rc);
- if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-
-/*
-** External API function used to create a new virtual-table module.
-*/
-int sqlite3_create_module(
- sqlite3 *db, /* Database in which module is registered */
- const char *zName, /* Name assigned to this module */
- const sqlite3_module *pModule, /* The definition of the module */
- void *pAux /* Context pointer for xCreate/xConnect */
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- return createModule(db, zName, pModule, pAux, 0);
-}
-
-/*
-** External API function used to create a new virtual-table module.
-*/
-int sqlite3_create_module_v2(
- sqlite3 *db, /* Database in which module is registered */
- const char *zName, /* Name assigned to this module */
- const sqlite3_module *pModule, /* The definition of the module */
- void *pAux, /* Context pointer for xCreate/xConnect */
- void (*xDestroy)(void *) /* Module destructor function */
-){
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
-#endif
- return createModule(db, zName, pModule, pAux, xDestroy);
-}
-
-/*
-** Lock the virtual table so that it cannot be disconnected.
-** Locks nest. Every lock should have a corresponding unlock.
-** If an unlock is omitted, resources leaks will occur.
-**
-** If a disconnect is attempted while a virtual table is locked,
-** the disconnect is deferred until all locks have been removed.
-*/
-void sqlite3VtabLock(VTable *pVTab){
- pVTab->nRef++;
-}
-
-
-/*
-** pTab is a pointer to a Table structure representing a virtual-table.
-** Return a pointer to the VTable object used by connection db to access
-** this virtual-table, if one has been created, or NULL otherwise.
-*/
-VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
- VTable *pVtab;
- assert( IsVirtual(pTab) );
- for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
- return pVtab;
-}
-
-/*
-** Decrement the ref-count on a virtual table object. When the ref-count
-** reaches zero, call the xDisconnect() method to delete the object.
-*/
-void sqlite3VtabUnlock(VTable *pVTab){
- sqlite3 *db = pVTab->db;
-
- assert( db );
- assert( pVTab->nRef>0 );
- assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE );
-
- pVTab->nRef--;
- if( pVTab->nRef==0 ){
- sqlite3_vtab *p = pVTab->pVtab;
- if( p ){
- p->pModule->xDisconnect(p);
- }
- sqlite3DbFree(db, pVTab);
- }
-}
-
-/*
-** Table p is a virtual table. This function moves all elements in the
-** p->pVTable list to the sqlite3.pDisconnect lists of their associated
-** database connections to be disconnected at the next opportunity.
-** Except, if argument db is not NULL, then the entry associated with
-** connection db is left in the p->pVTable list.
-*/
-static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
- VTable *pRet = 0;
- VTable *pVTable = p->pVTable;
- p->pVTable = 0;
-
- /* Assert that the mutex (if any) associated with the BtShared database
- ** that contains table p is held by the caller. See header comments
- ** above function sqlite3VtabUnlockList() for an explanation of why
- ** this makes it safe to access the sqlite3.pDisconnect list of any
- ** database connection that may have an entry in the p->pVTable list.
- */
- assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
-
- while( pVTable ){
- sqlite3 *db2 = pVTable->db;
- VTable *pNext = pVTable->pNext;
- assert( db2 );
- if( db2==db ){
- pRet = pVTable;
- p->pVTable = pRet;
- pRet->pNext = 0;
- }else{
- pVTable->pNext = db2->pDisconnect;
- db2->pDisconnect = pVTable;
- }
- pVTable = pNext;
- }
-
- assert( !db || pRet );
- return pRet;
-}
-
-/*
-** Table *p is a virtual table. This function removes the VTable object
-** for table *p associated with database connection db from the linked
-** list in p->pVTab. It also decrements the VTable ref count. This is
-** used when closing database connection db to free all of its VTable
-** objects without disturbing the rest of the Schema object (which may
-** be being used by other shared-cache connections).
-*/
-void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
- VTable **ppVTab;
-
- assert( IsVirtual(p) );
- assert( sqlite3BtreeHoldsAllMutexes(db) );
- assert( sqlite3_mutex_held(db->mutex) );
-
- for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
- if( (*ppVTab)->db==db ){
- VTable *pVTab = *ppVTab;
- *ppVTab = pVTab->pNext;
- sqlite3VtabUnlock(pVTab);
- break;
- }
- }
-}
-
-
-/*
-** Disconnect all the virtual table objects in the sqlite3.pDisconnect list.
-**
-** This function may only be called when the mutexes associated with all
-** shared b-tree databases opened using connection db are held by the
-** caller. This is done to protect the sqlite3.pDisconnect list. The
-** sqlite3.pDisconnect list is accessed only as follows:
-**
-** 1) By this function. In this case, all BtShared mutexes and the mutex
-** associated with the database handle itself must be held.
-**
-** 2) By function vtabDisconnectAll(), when it adds a VTable entry to
-** the sqlite3.pDisconnect list. In this case either the BtShared mutex
-** associated with the database the virtual table is stored in is held
-** or, if the virtual table is stored in a non-sharable database, then
-** the database handle mutex is held.
-**
-** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously
-** by multiple threads. It is thread-safe.
-*/
-void sqlite3VtabUnlockList(sqlite3 *db){
- VTable *p = db->pDisconnect;
- db->pDisconnect = 0;
-
- assert( sqlite3BtreeHoldsAllMutexes(db) );
- assert( sqlite3_mutex_held(db->mutex) );
-
- if( p ){
- sqlite3ExpirePreparedStatements(db);
- do {
- VTable *pNext = p->pNext;
- sqlite3VtabUnlock(p);
- p = pNext;
- }while( p );
- }
-}
-
-/*
-** Clear any and all virtual-table information from the Table record.
-** This routine is called, for example, just before deleting the Table
-** record.
-**
-** Since it is a virtual-table, the Table structure contains a pointer
-** to the head of a linked list of VTable structures. Each VTable
-** structure is associated with a single sqlite3* user of the schema.
-** The reference count of the VTable structure associated with database
-** connection db is decremented immediately (which may lead to the
-** structure being xDisconnected and free). Any other VTable structures
-** in the list are moved to the sqlite3.pDisconnect list of the associated
-** database connection.
-*/
-void sqlite3VtabClear(sqlite3 *db, Table *p){
- if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
- if( p->azModuleArg ){
- int i;
- for(i=0; i<p->nModuleArg; i++){
- if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
- }
- sqlite3DbFree(db, p->azModuleArg);
- }
-}
-
-/*
-** Add a new module argument to pTable->azModuleArg[].
-** The string is not copied - the pointer is stored. The
-** string will be freed automatically when the table is
-** deleted.
-*/
-static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){
- int nBytes = sizeof(char *)*(2+pTable->nModuleArg);
- char **azModuleArg;
- azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
- if( azModuleArg==0 ){
- sqlite3DbFree(db, zArg);
- }else{
- int i = pTable->nModuleArg++;
- azModuleArg[i] = zArg;
- azModuleArg[i+1] = 0;
- pTable->azModuleArg = azModuleArg;
- }
-}
-
-/*
-** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
-** statement. The module name has been parsed, but the optional list
-** of parameters that follow the module name are still pending.
-*/
-void sqlite3VtabBeginParse(
- Parse *pParse, /* Parsing context */
- Token *pName1, /* Name of new table, or database name */
- Token *pName2, /* Name of new table or NULL */
- Token *pModuleName, /* Name of the module for the virtual table */
- int ifNotExists /* No error if the table already exists */
-){
- int iDb; /* The database the table is being created in */
- Table *pTable; /* The new virtual table */
- sqlite3 *db; /* Database connection */
-
- sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists);
- pTable = pParse->pNewTable;
- if( pTable==0 ) return;
- assert( 0==pTable->pIndex );
-
- db = pParse->db;
- iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
- assert( iDb>=0 );
-
- assert( pTable->nModuleArg==0 );
- addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
- addModuleArgument(db, pTable, 0);
- addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
- assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0)
- || (pParse->sNameToken.z==pName1->z && pName2->z==0)
- );
- pParse->sNameToken.n = (int)(
- &pModuleName->z[pModuleName->n] - pParse->sNameToken.z
- );
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- /* Creating a virtual table invokes the authorization callback twice.
- ** The first invocation, to obtain permission to INSERT a row into the
- ** sqlite_master table, has already been made by sqlite3StartTable().
- ** The second call, to obtain permission to create the table, is made now.
- */
- if( pTable->azModuleArg ){
- sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
- pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
- }
-#endif
-}
-
-/*
-** This routine takes the module argument that has been accumulating
-** in pParse->zArg[] and appends it to the list of arguments on the
-** virtual table currently under construction in pParse->pTable.
-*/
-static void addArgumentToVtab(Parse *pParse){
- if( pParse->sArg.z && pParse->pNewTable ){
- const char *z = (const char*)pParse->sArg.z;
- int n = pParse->sArg.n;
- sqlite3 *db = pParse->db;
- addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
- }
-}
-
-/*
-** The parser calls this routine after the CREATE VIRTUAL TABLE statement
-** has been completely parsed.
-*/
-void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
- Table *pTab = pParse->pNewTable; /* The table being constructed */
- sqlite3 *db = pParse->db; /* The database connection */
-
- if( pTab==0 ) return;
- addArgumentToVtab(pParse);
- pParse->sArg.z = 0;
- if( pTab->nModuleArg<1 ) return;
-
- /* If the CREATE VIRTUAL TABLE statement is being entered for the
- ** first time (in other words if the virtual table is actually being
- ** created now instead of just being read out of sqlite_master) then
- ** do additional initialization work and store the statement text
- ** in the sqlite_master table.
- */
- if( !db->init.busy ){
- char *zStmt;
- char *zWhere;
- int iDb;
- int iReg;
- Vdbe *v;
-
- /* Compute the complete text of the CREATE VIRTUAL TABLE statement */
- if( pEnd ){
- pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n;
- }
- zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
-
- /* A slot for the record has already been allocated in the
- ** SQLITE_MASTER table. We just need to update that slot with all
- ** the information we've collected.
- **
- ** The VM register number pParse->regRowid holds the rowid of an
- ** entry in the sqlite_master table tht was created for this vtab
- ** by sqlite3StartTable().
- */
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- sqlite3NestedParse(pParse,
- "UPDATE %Q.%s "
- "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
- "WHERE rowid=#%d",
- db->aDb[iDb].zDbSName, MASTER_NAME,
- pTab->zName,
- pTab->zName,
- zStmt,
- pParse->regRowid
- );
- sqlite3DbFree(db, zStmt);
- v = sqlite3GetVdbe(pParse);
- sqlite3ChangeCookie(pParse, iDb);
-
- sqlite3VdbeAddOp0(v, OP_Expire);
- zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
- sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
-
- iReg = ++pParse->nMem;
- sqlite3VdbeLoadString(v, iReg, pTab->zName);
- sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg);
- }
-
- /* If we are rereading the sqlite_master table create the in-memory
- ** record of the table. The xConnect() method is not called until
- ** the first time the virtual table is used in an SQL statement. This
- ** allows a schema that contains virtual tables to be loaded before
- ** the required virtual table implementations are registered. */
- else {
- Table *pOld;
- Schema *pSchema = pTab->pSchema;
- const char *zName = pTab->zName;
- assert( sqlite3SchemaMutexHeld(db, 0, pSchema) );
- pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab);
- if( pOld ){
- sqlite3OomFault(db);
- assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
- return;
- }
- pParse->pNewTable = 0;
- }
-}
-
-/*
-** The parser calls this routine when it sees the first token
-** of an argument to the module name in a CREATE VIRTUAL TABLE statement.
-*/
-void sqlite3VtabArgInit(Parse *pParse){
- addArgumentToVtab(pParse);
- pParse->sArg.z = 0;
- pParse->sArg.n = 0;
-}
-
-/*
-** The parser calls this routine for each token after the first token
-** in an argument to the module name in a CREATE VIRTUAL TABLE statement.
-*/
-void sqlite3VtabArgExtend(Parse *pParse, Token *p){
- Token *pArg = &pParse->sArg;
- if( pArg->z==0 ){
- pArg->z = p->z;
- pArg->n = p->n;
- }else{
- assert(pArg->z <= p->z);
- pArg->n = (int)(&p->z[p->n] - pArg->z);
- }
-}
-
-/*
-** Invoke a virtual table constructor (either xCreate or xConnect). The
-** pointer to the function to invoke is passed as the fourth parameter
-** to this procedure.
-*/
-static int vtabCallConstructor(
- sqlite3 *db,
- Table *pTab,
- Module *pMod,
- int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
- char **pzErr
-){
- VtabCtx sCtx;
- VTable *pVTable;
- int rc;
- const char *const*azArg = (const char *const*)pTab->azModuleArg;
- int nArg = pTab->nModuleArg;
- char *zErr = 0;
- char *zModuleName;
- int iDb;
- VtabCtx *pCtx;
-
- /* Check that the virtual-table is not already being initialized */
- for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
- if( pCtx->pTab==pTab ){
- *pzErr = sqlite3MPrintf(db,
- "vtable constructor called recursively: %s", pTab->zName
- );
- return SQLITE_LOCKED;
- }
- }
-
- zModuleName = sqlite3DbStrDup(db, pTab->zName);
- if( !zModuleName ){
- return SQLITE_NOMEM_BKPT;
- }
-
- pVTable = sqlite3MallocZero(sizeof(VTable));
- if( !pVTable ){
- sqlite3OomFault(db);
- sqlite3DbFree(db, zModuleName);
- return SQLITE_NOMEM_BKPT;
- }
- pVTable->db = db;
- pVTable->pMod = pMod;
-
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
-
- /* Invoke the virtual table constructor */
- assert( &db->pVtabCtx );
- assert( xConstruct );
- sCtx.pTab = pTab;
- sCtx.pVTable = pVTable;
- sCtx.pPrior = db->pVtabCtx;
- sCtx.bDeclared = 0;
- db->pVtabCtx = &sCtx;
- rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
- db->pVtabCtx = sCtx.pPrior;
- if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
- assert( sCtx.pTab==pTab );
-
- if( SQLITE_OK!=rc ){
- if( zErr==0 ){
- *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
- }else {
- *pzErr = sqlite3MPrintf(db, "%s", zErr);
- sqlite3_free(zErr);
- }
- sqlite3DbFree(db, pVTable);
- }else if( ALWAYS(pVTable->pVtab) ){
- /* Justification of ALWAYS(): A correct vtab constructor must allocate
- ** the sqlite3_vtab object if successful. */
- memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
- pVTable->pVtab->pModule = pMod->pModule;
- pVTable->nRef = 1;
- if( sCtx.bDeclared==0 ){
- const char *zFormat = "vtable constructor did not declare schema: %s";
- *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
- sqlite3VtabUnlock(pVTable);
- rc = SQLITE_ERROR;
- }else{
- int iCol;
- u8 oooHidden = 0;
- /* If everything went according to plan, link the new VTable structure
- ** into the linked list headed by pTab->pVTable. Then loop through the
- ** columns of the table to see if any of them contain the token "hidden".
- ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
- ** the type string. */
- pVTable->pNext = pTab->pVTable;
- pTab->pVTable = pVTable;
-
- for(iCol=0; iCol<pTab->nCol; iCol++){
- char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
- int nType;
- int i = 0;
- nType = sqlite3Strlen30(zType);
- for(i=0; i<nType; i++){
- if( 0==sqlite3StrNICmp("hidden", &zType[i], 6)
- && (i==0 || zType[i-1]==' ')
- && (zType[i+6]=='\0' || zType[i+6]==' ')
- ){
- break;
- }
- }
- if( i<nType ){
- int j;
- int nDel = 6 + (zType[i+6] ? 1 : 0);
- for(j=i; (j+nDel)<=nType; j++){
- zType[j] = zType[j+nDel];
- }
- if( zType[i]=='\0' && i>0 ){
- assert(zType[i-1]==' ');
- zType[i-1] = '\0';
- }
- pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
- oooHidden = TF_OOOHidden;
- }else{
- pTab->tabFlags |= oooHidden;
- }
- }
- }
- }
-
- sqlite3DbFree(db, zModuleName);
- return rc;
-}
-
-/*
-** This function is invoked by the parser to call the xConnect() method
-** of the virtual table pTab. If an error occurs, an error code is returned
-** and an error left in pParse.
-**
-** This call is a no-op if table pTab is not a virtual table.
-*/
-int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
- sqlite3 *db = pParse->db;
- const char *zMod;
- Module *pMod;
- int rc;
-
- assert( pTab );
- if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){
- return SQLITE_OK;
- }
-
- /* Locate the required virtual table module */
- zMod = pTab->azModuleArg[0];
- pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
-
- if( !pMod ){
- const char *zModule = pTab->azModuleArg[0];
- sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
- rc = SQLITE_ERROR;
- }else{
- char *zErr = 0;
- rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
- if( rc!=SQLITE_OK ){
- sqlite3ErrorMsg(pParse, "%s", zErr);
- pParse->rc = rc;
- }
- sqlite3DbFree(db, zErr);
- }
-
- return rc;
-}
-/*
-** Grow the db->aVTrans[] array so that there is room for at least one
-** more v-table. Return SQLITE_NOMEM if a malloc fails, or SQLITE_OK otherwise.
-*/
-static int growVTrans(sqlite3 *db){
- const int ARRAY_INCR = 5;
-
- /* Grow the sqlite3.aVTrans array if required */
- if( (db->nVTrans%ARRAY_INCR)==0 ){
- VTable **aVTrans;
- int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR);
- aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes);
- if( !aVTrans ){
- return SQLITE_NOMEM_BKPT;
- }
- memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR);
- db->aVTrans = aVTrans;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Add the virtual table pVTab to the array sqlite3.aVTrans[]. Space should
-** have already been reserved using growVTrans().
-*/
-static void addToVTrans(sqlite3 *db, VTable *pVTab){
- /* Add pVtab to the end of sqlite3.aVTrans */
- db->aVTrans[db->nVTrans++] = pVTab;
- sqlite3VtabLock(pVTab);
-}
-
-/*
-** This function is invoked by the vdbe to call the xCreate method
-** of the virtual table named zTab in database iDb.
-**
-** If an error occurs, *pzErr is set to point to an English language
-** description of the error and an SQLITE_XXX error code is returned.
-** In this case the caller must call sqlite3DbFree(db, ) on *pzErr.
-*/
-int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
- int rc = SQLITE_OK;
- Table *pTab;
- Module *pMod;
- const char *zMod;
-
- pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
- assert( pTab && IsVirtual(pTab) && !pTab->pVTable );
-
- /* Locate the required virtual table module */
- zMod = pTab->azModuleArg[0];
- pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
-
- /* If the module has been registered and includes a Create method,
- ** invoke it now. If the module has not been registered, return an
- ** error. Otherwise, do nothing.
- */
- if( pMod==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){
- *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod);
- rc = SQLITE_ERROR;
- }else{
- rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
- }
-
- /* Justification of ALWAYS(): The xConstructor method is required to
- ** create a valid sqlite3_vtab if it returns SQLITE_OK. */
- if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){
- rc = growVTrans(db);
- if( rc==SQLITE_OK ){
- addToVTrans(db, sqlite3GetVTable(db, pTab));
- }
- }
-
- return rc;
-}
-
-/*
-** This function is used to set the schema of a virtual table. It is only
-** valid to call this function from within the xCreate() or xConnect() of a
-** virtual table module.
-*/
-int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
- VtabCtx *pCtx;
- int rc = SQLITE_OK;
- Table *pTab;
- char *zErr = 0;
- Parse sParse;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
- return SQLITE_MISUSE_BKPT;
- }
-#endif
- sqlite3_mutex_enter(db->mutex);
- pCtx = db->pVtabCtx;
- if( !pCtx || pCtx->bDeclared ){
- sqlite3Error(db, SQLITE_MISUSE);
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_MISUSE_BKPT;
- }
- pTab = pCtx->pTab;
- assert( IsVirtual(pTab) );
-
- memset(&sParse, 0, sizeof(sParse));
- sParse.declareVtab = 1;
- sParse.db = db;
- sParse.nQueryLoop = 1;
- if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr)
- && sParse.pNewTable
- && !db->mallocFailed
- && !sParse.pNewTable->pSelect
- && !IsVirtual(sParse.pNewTable)
- ){
- if( !pTab->aCol ){
- Table *pNew = sParse.pNewTable;
- Index *pIdx;
- pTab->aCol = pNew->aCol;
- pTab->nCol = pNew->nCol;
- pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
- pNew->nCol = 0;
- pNew->aCol = 0;
- assert( pTab->pIndex==0 );
- assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 );
- if( !HasRowid(pNew)
- && pCtx->pVTable->pMod->pModule->xUpdate!=0
- && sqlite3PrimaryKeyIndex(pNew)->nKeyCol!=1
- ){
- /* WITHOUT ROWID virtual tables must either be read-only (xUpdate==0)
- ** or else must have a single-column PRIMARY KEY */
- rc = SQLITE_ERROR;
- }
- pIdx = pNew->pIndex;
- if( pIdx ){
- assert( pIdx->pNext==0 );
- pTab->pIndex = pIdx;
- pNew->pIndex = 0;
- pIdx->pTable = pTab;
- }
- }
- pCtx->bDeclared = 1;
- }else{
- sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
- sqlite3DbFree(db, zErr);
- rc = SQLITE_ERROR;
- }
- sParse.declareVtab = 0;
-
- if( sParse.pVdbe ){
- sqlite3VdbeFinalize(sParse.pVdbe);
- }
- sqlite3DeleteTable(db, sParse.pNewTable);
- sqlite3ParserReset(&sParse);
-
- assert( (rc&0xff)==rc );
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-/*
-** This function is invoked by the vdbe to call the xDestroy method
-** of the virtual table named zTab in database iDb. This occurs
-** when a DROP TABLE is mentioned.
-**
-** This call is a no-op if zTab is not a virtual table.
-*/
-int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
- int rc = SQLITE_OK;
- Table *pTab;
-
- pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
- if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){
- VTable *p;
- int (*xDestroy)(sqlite3_vtab *);
- for(p=pTab->pVTable; p; p=p->pNext){
- assert( p->pVtab );
- if( p->pVtab->nRef>0 ){
- return SQLITE_LOCKED;
- }
- }
- p = vtabDisconnectAll(db, pTab);
- xDestroy = p->pMod->pModule->xDestroy;
- assert( xDestroy!=0 ); /* Checked before the virtual table is created */
- rc = xDestroy(p->pVtab);
- /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
- if( rc==SQLITE_OK ){
- assert( pTab->pVTable==p && p->pNext==0 );
- p->pVtab = 0;
- pTab->pVTable = 0;
- sqlite3VtabUnlock(p);
- }
- }
-
- return rc;
-}
-
-/*
-** This function invokes either the xRollback or xCommit method
-** of each of the virtual tables in the sqlite3.aVTrans array. The method
-** called is identified by the second argument, "offset", which is
-** the offset of the method to call in the sqlite3_module structure.
-**
-** The array is cleared after invoking the callbacks.
-*/
-static void callFinaliser(sqlite3 *db, int offset){
- int i;
- if( db->aVTrans ){
- VTable **aVTrans = db->aVTrans;
- db->aVTrans = 0;
- for(i=0; i<db->nVTrans; i++){
- VTable *pVTab = aVTrans[i];
- sqlite3_vtab *p = pVTab->pVtab;
- if( p ){
- int (*x)(sqlite3_vtab *);
- x = *(int (**)(sqlite3_vtab *))((char *)p->pModule + offset);
- if( x ) x(p);
- }
- pVTab->iSavepoint = 0;
- sqlite3VtabUnlock(pVTab);
- }
- sqlite3DbFree(db, aVTrans);
- db->nVTrans = 0;
- }
-}
-
-/*
-** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans
-** array. Return the error code for the first error that occurs, or
-** SQLITE_OK if all xSync operations are successful.
-**
-** If an error message is available, leave it in p->zErrMsg.
-*/
-int sqlite3VtabSync(sqlite3 *db, Vdbe *p){
- int i;
- int rc = SQLITE_OK;
- VTable **aVTrans = db->aVTrans;
-
- db->aVTrans = 0;
- for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
- int (*x)(sqlite3_vtab *);
- sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
- if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
- rc = x(pVtab);
- sqlite3VtabImportErrmsg(p, pVtab);
- }
- }
- db->aVTrans = aVTrans;
- return rc;
-}
-
-/*
-** Invoke the xRollback method of all virtual tables in the
-** sqlite3.aVTrans array. Then clear the array itself.
-*/
-int sqlite3VtabRollback(sqlite3 *db){
- callFinaliser(db, offsetof(sqlite3_module,xRollback));
- return SQLITE_OK;
-}
-
-/*
-** Invoke the xCommit method of all virtual tables in the
-** sqlite3.aVTrans array. Then clear the array itself.
-*/
-int sqlite3VtabCommit(sqlite3 *db){
- callFinaliser(db, offsetof(sqlite3_module,xCommit));
- return SQLITE_OK;
-}
-
-/*
-** If the virtual table pVtab supports the transaction interface
-** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is
-** not currently open, invoke the xBegin method now.
-**
-** If the xBegin call is successful, place the sqlite3_vtab pointer
-** in the sqlite3.aVTrans array.
-*/
-int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){
- int rc = SQLITE_OK;
- const sqlite3_module *pModule;
-
- /* Special case: If db->aVTrans is NULL and db->nVTrans is greater
- ** than zero, then this function is being called from within a
- ** virtual module xSync() callback. It is illegal to write to
- ** virtual module tables in this case, so return SQLITE_LOCKED.
- */
- if( sqlite3VtabInSync(db) ){
- return SQLITE_LOCKED;
- }
- if( !pVTab ){
- return SQLITE_OK;
- }
- pModule = pVTab->pVtab->pModule;
-
- if( pModule->xBegin ){
- int i;
-
- /* If pVtab is already in the aVTrans array, return early */
- for(i=0; i<db->nVTrans; i++){
- if( db->aVTrans[i]==pVTab ){
- return SQLITE_OK;
- }
- }
-
- /* Invoke the xBegin method. If successful, add the vtab to the
- ** sqlite3.aVTrans[] array. */
- rc = growVTrans(db);
- if( rc==SQLITE_OK ){
- rc = pModule->xBegin(pVTab->pVtab);
- if( rc==SQLITE_OK ){
- int iSvpt = db->nStatement + db->nSavepoint;
- addToVTrans(db, pVTab);
- if( iSvpt && pModule->xSavepoint ){
- pVTab->iSavepoint = iSvpt;
- rc = pModule->xSavepoint(pVTab->pVtab, iSvpt-1);
- }
- }
- }
- }
- return rc;
-}
-
-/*
-** Invoke either the xSavepoint, xRollbackTo or xRelease method of all
-** virtual tables that currently have an open transaction. Pass iSavepoint
-** as the second argument to the virtual table method invoked.
-**
-** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is
-** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is
-** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with
-** an open transaction is invoked.
-**
-** If any virtual table method returns an error code other than SQLITE_OK,
-** processing is abandoned and the error returned to the caller of this
-** function immediately. If all calls to virtual table methods are successful,
-** SQLITE_OK is returned.
-*/
-int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
- int rc = SQLITE_OK;
-
- assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
- assert( iSavepoint>=-1 );
- if( db->aVTrans ){
- int i;
- for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
- VTable *pVTab = db->aVTrans[i];
- const sqlite3_module *pMod = pVTab->pMod->pModule;
- if( pVTab->pVtab && pMod->iVersion>=2 ){
- int (*xMethod)(sqlite3_vtab *, int);
- switch( op ){
- case SAVEPOINT_BEGIN:
- xMethod = pMod->xSavepoint;
- pVTab->iSavepoint = iSavepoint+1;
- break;
- case SAVEPOINT_ROLLBACK:
- xMethod = pMod->xRollbackTo;
- break;
- default:
- xMethod = pMod->xRelease;
- break;
- }
- if( xMethod && pVTab->iSavepoint>iSavepoint ){
- rc = xMethod(pVTab->pVtab, iSavepoint);
- }
- }
- }
- }
- return rc;
-}
-
-/*
-** The first parameter (pDef) is a function implementation. The
-** second parameter (pExpr) is the first argument to this function.
-** If pExpr is a column in a virtual table, then let the virtual
-** table implementation have an opportunity to overload the function.
-**
-** This routine is used to allow virtual table implementations to
-** overload MATCH, LIKE, GLOB, and REGEXP operators.
-**
-** Return either the pDef argument (indicating no change) or a
-** new FuncDef structure that is marked as ephemeral using the
-** SQLITE_FUNC_EPHEM flag.
-*/
-FuncDef *sqlite3VtabOverloadFunction(
- sqlite3 *db, /* Database connection for reporting malloc problems */
- FuncDef *pDef, /* Function to possibly overload */
- int nArg, /* Number of arguments to the function */
- Expr *pExpr /* First argument to the function */
-){
- Table *pTab;
- sqlite3_vtab *pVtab;
- sqlite3_module *pMod;
- void (*xSFunc)(sqlite3_context*,int,sqlite3_value**) = 0;
- void *pArg = 0;
- FuncDef *pNew;
- int rc = 0;
-
- /* Check to see the left operand is a column in a virtual table */
- if( NEVER(pExpr==0) ) return pDef;
- if( pExpr->op!=TK_COLUMN ) return pDef;
- pTab = pExpr->pTab;
- if( pTab==0 ) return pDef;
- if( !IsVirtual(pTab) ) return pDef;
- pVtab = sqlite3GetVTable(db, pTab)->pVtab;
- assert( pVtab!=0 );
- assert( pVtab->pModule!=0 );
- pMod = (sqlite3_module *)pVtab->pModule;
- if( pMod->xFindFunction==0 ) return pDef;
-
- /* Call the xFindFunction method on the virtual table implementation
- ** to see if the implementation wants to overload this function.
- **
- ** Though undocumented, we have historically always invoked xFindFunction
- ** with an all lower-case function name. Continue in this tradition to
- ** avoid any chance of an incompatibility.
- */
-#ifdef SQLITE_DEBUG
- {
- int i;
- for(i=0; pDef->zName[i]; i++){
- unsigned char x = (unsigned char)pDef->zName[i];
- assert( x==sqlite3UpperToLower[x] );
- }
- }
-#endif
- rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg);
- if( rc==0 ){
- return pDef;
- }
-
- /* Create a new ephemeral function definition for the overloaded
- ** function */
- pNew = sqlite3DbMallocZero(db, sizeof(*pNew)
- + sqlite3Strlen30(pDef->zName) + 1);
- if( pNew==0 ){
- return pDef;
- }
- *pNew = *pDef;
- pNew->zName = (const char*)&pNew[1];
- memcpy((char*)&pNew[1], pDef->zName, sqlite3Strlen30(pDef->zName)+1);
- pNew->xSFunc = xSFunc;
- pNew->pUserData = pArg;
- pNew->funcFlags |= SQLITE_FUNC_EPHEM;
- return pNew;
-}
-
-/*
-** Make sure virtual table pTab is contained in the pParse->apVirtualLock[]
-** array so that an OP_VBegin will get generated for it. Add pTab to the
-** array if it is missing. If pTab is already in the array, this routine
-** is a no-op.
-*/
-void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
- int i, n;
- Table **apVtabLock;
-
- assert( IsVirtual(pTab) );
- for(i=0; i<pToplevel->nVtabLock; i++){
- if( pTab==pToplevel->apVtabLock[i] ) return;
- }
- n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
- apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
- if( apVtabLock ){
- pToplevel->apVtabLock = apVtabLock;
- pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
- }else{
- sqlite3OomFault(pToplevel->db);
- }
-}
-
-/*
-** Check to see if virtual table module pMod can be have an eponymous
-** virtual table instance. If it can, create one if one does not already
-** exist. Return non-zero if the eponymous virtual table instance exists
-** when this routine returns, and return zero if it does not exist.
-**
-** An eponymous virtual table instance is one that is named after its
-** module, and more importantly, does not require a CREATE VIRTUAL TABLE
-** statement in order to come into existance. Eponymous virtual table
-** instances always exist. They cannot be DROP-ed.
-**
-** Any virtual table module for which xConnect and xCreate are the same
-** method can have an eponymous virtual table instance.
-*/
-int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
- const sqlite3_module *pModule = pMod->pModule;
- Table *pTab;
- char *zErr = 0;
- int rc;
- sqlite3 *db = pParse->db;
- if( pMod->pEpoTab ) return 1;
- if( pModule->xCreate!=0 && pModule->xCreate!=pModule->xConnect ) return 0;
- pTab = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return 0;
- pTab->zName = sqlite3DbStrDup(db, pMod->zName);
- if( pTab->zName==0 ){
- sqlite3DbFree(db, pTab);
- return 0;
- }
- pMod->pEpoTab = pTab;
- pTab->nTabRef = 1;
- pTab->pSchema = db->aDb[0].pSchema;
- assert( pTab->nModuleArg==0 );
- pTab->iPKey = -1;
- addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
- addModuleArgument(db, pTab, 0);
- addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
- rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
- if( rc ){
- sqlite3ErrorMsg(pParse, "%s", zErr);
- sqlite3DbFree(db, zErr);
- sqlite3VtabEponymousTableClear(db, pMod);
- return 0;
- }
- return 1;
-}
-
-/*
-** Erase the eponymous virtual table instance associated with
-** virtual table module pMod, if it exists.
-*/
-void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){
- Table *pTab = pMod->pEpoTab;
- if( pTab!=0 ){
- /* Mark the table as Ephemeral prior to deleting it, so that the
- ** sqlite3DeleteTable() routine will know that it is not stored in
- ** the schema. */
- pTab->tabFlags |= TF_Ephemeral;
- sqlite3DeleteTable(db, pTab);
- pMod->pEpoTab = 0;
- }
-}
-
-/*
-** Return the ON CONFLICT resolution mode in effect for the virtual
-** table update operation currently in progress.
-**
-** The results of this routine are undefined unless it is called from
-** within an xUpdate method.
-*/
-int sqlite3_vtab_on_conflict(sqlite3 *db){
- static const unsigned char aMap[] = {
- SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
- };
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
- assert( OE_Ignore==4 && OE_Replace==5 );
- assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
- return (int)aMap[db->vtabOnConflict-1];
-}
-
-/*
-** Call from within the xCreate() or xConnect() methods to provide
-** the SQLite core with additional information about the behavior
-** of the virtual table being implemented.
-*/
-int sqlite3_vtab_config(sqlite3 *db, int op, ...){
- va_list ap;
- int rc = SQLITE_OK;
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
-#endif
- sqlite3_mutex_enter(db->mutex);
- va_start(ap, op);
- switch( op ){
- case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
- VtabCtx *p = db->pVtabCtx;
- if( !p ){
- rc = SQLITE_MISUSE_BKPT;
- }else{
- assert( p->pTab==0 || IsVirtual(p->pTab) );
- p->pVTable->bConstraint = (u8)va_arg(ap, int);
- }
- break;
- }
- default:
- rc = SQLITE_MISUSE_BKPT;
- break;
- }
- va_end(ap);
-
- if( rc!=SQLITE_OK ) sqlite3Error(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-}
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/vxworks.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/vxworks.h
deleted file mode 100644
index e7013c3f667..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/vxworks.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-** 2015-03-02
-**
-** 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 contains code that is specific to Wind River's VxWorks
-*/
-#if defined(__RTP__) || defined(_WRS_KERNEL)
-/* This is VxWorks. Set up things specially for that OS
-*/
-#include <vxWorks.h>
-#include <pthread.h> /* amalgamator: dontcache */
-#define OS_VXWORKS 1
-#define SQLITE_OS_OTHER 0
-#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1
-#define SQLITE_OMIT_LOAD_EXTENSION 1
-#define SQLITE_ENABLE_LOCKING_STYLE 0
-#define HAVE_UTIME 1
-#else
-/* This is not VxWorks. */
-#define OS_VXWORKS 0
-#define HAVE_FCHOWN 1
-#define HAVE_READLINK 1
-#define HAVE_LSTAT 1
-#endif /* defined(_WRS_KERNEL) */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/wal.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/wal.c
deleted file mode 100644
index 69a89a709b2..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/wal.c
+++ /dev/null
@@ -1,3795 +0,0 @@
-/*
-** 2010 February 1
-**
-** 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 contains the implementation of a write-ahead log (WAL) used in
-** "journal_mode=WAL" mode.
-**
-** WRITE-AHEAD LOG (WAL) FILE FORMAT
-**
-** A WAL file consists of a header followed by zero or more "frames".
-** Each frame records the revised content of a single page from the
-** database file. All changes to the database are recorded by writing
-** frames into the WAL. Transactions commit when a frame is written that
-** contains a commit marker. A single WAL can and usually does record
-** multiple transactions. Periodically, the content of the WAL is
-** transferred back into the database file in an operation called a
-** "checkpoint".
-**
-** A single WAL file can be used multiple times. In other words, the
-** WAL can fill up with frames and then be checkpointed and then new
-** frames can overwrite the old ones. A WAL always grows from beginning
-** toward the end. Checksums and counters attached to each frame are
-** used to determine which frames within the WAL are valid and which
-** are leftovers from prior checkpoints.
-**
-** The WAL header is 32 bytes in size and consists of the following eight
-** big-endian 32-bit unsigned integer values:
-**
-** 0: Magic number. 0x377f0682 or 0x377f0683
-** 4: File format version. Currently 3007000
-** 8: Database page size. Example: 1024
-** 12: Checkpoint sequence number
-** 16: Salt-1, random integer incremented with each checkpoint
-** 20: Salt-2, a different random integer changing with each ckpt
-** 24: Checksum-1 (first part of checksum for first 24 bytes of header).
-** 28: Checksum-2 (second part of checksum for first 24 bytes of header).
-**
-** Immediately following the wal-header are zero or more frames. Each
-** frame consists of a 24-byte frame-header followed by a <page-size> bytes
-** of page data. The frame-header is six big-endian 32-bit unsigned
-** integer values, as follows:
-**
-** 0: Page number.
-** 4: For commit records, the size of the database image in pages
-** after the commit. For all other records, zero.
-** 8: Salt-1 (copied from the header)
-** 12: Salt-2 (copied from the header)
-** 16: Checksum-1.
-** 20: Checksum-2.
-**
-** A frame is considered valid if and only if the following conditions are
-** true:
-**
-** (1) The salt-1 and salt-2 values in the frame-header match
-** salt values in the wal-header
-**
-** (2) The checksum values in the final 8 bytes of the frame-header
-** exactly match the checksum computed consecutively on the
-** WAL header and the first 8 bytes and the content of all frames
-** up to and including the current frame.
-**
-** The checksum is computed using 32-bit big-endian integers if the
-** magic number in the first 4 bytes of the WAL is 0x377f0683 and it
-** is computed using little-endian if the magic number is 0x377f0682.
-** The checksum values are always stored in the frame header in a
-** big-endian format regardless of which byte order is used to compute
-** the checksum. The checksum is computed by interpreting the input as
-** an even number of unsigned 32-bit integers: x[0] through x[N]. The
-** algorithm used for the checksum is as follows:
-**
-** for i from 0 to n-1 step 2:
-** s0 += x[i] + s1;
-** s1 += x[i+1] + s0;
-** endfor
-**
-** Note that s0 and s1 are both weighted checksums using fibonacci weights
-** in reverse order (the largest fibonacci weight occurs on the first element
-** of the sequence being summed.) The s1 value spans all 32-bit
-** terms of the sequence whereas s0 omits the final term.
-**
-** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
-** WAL is transferred into the database, then the database is VFS.xSync-ed.
-** The VFS.xSync operations serve as write barriers - all writes launched
-** before the xSync must complete before any write that launches after the
-** xSync begins.
-**
-** After each checkpoint, the salt-1 value is incremented and the salt-2
-** value is randomized. This prevents old and new frames in the WAL from
-** being considered valid at the same time and being checkpointing together
-** following a crash.
-**
-** READER ALGORITHM
-**
-** To read a page from the database (call it page number P), a reader
-** first checks the WAL to see if it contains page P. If so, then the
-** last valid instance of page P that is a followed by a commit frame
-** or is a commit frame itself becomes the value read. If the WAL
-** contains no copies of page P that are valid and which are a commit
-** frame or are followed by a commit frame, then page P is read from
-** the database file.
-**
-** To start a read transaction, the reader records the index of the last
-** valid frame in the WAL. The reader uses this recorded "mxFrame" value
-** for all subsequent read operations. New transactions can be appended
-** to the WAL, but as long as the reader uses its original mxFrame value
-** and ignores the newly appended content, it will see a consistent snapshot
-** of the database from a single point in time. This technique allows
-** multiple concurrent readers to view different versions of the database
-** content simultaneously.
-**
-** The reader algorithm in the previous paragraphs works correctly, but
-** because frames for page P can appear anywhere within the WAL, the
-** reader has to scan the entire WAL looking for page P frames. If the
-** WAL is large (multiple megabytes is typical) that scan can be slow,
-** and read performance suffers. To overcome this problem, a separate
-** data structure called the wal-index is maintained to expedite the
-** search for frames of a particular page.
-**
-** WAL-INDEX FORMAT
-**
-** Conceptually, the wal-index is shared memory, though VFS implementations
-** might choose to implement the wal-index using a mmapped file. Because
-** the wal-index is shared memory, SQLite does not support journal_mode=WAL
-** on a network filesystem. All users of the database must be able to
-** share memory.
-**
-** In the default unix and windows implementation, the wal-index is a mmapped
-** file whose name is the database name with a "-shm" suffix added. For that
-** reason, the wal-index is sometimes called the "shm" file.
-**
-** The wal-index is transient. After a crash, the wal-index can (and should
-** be) reconstructed from the original WAL file. In fact, the VFS is required
-** to either truncate or zero the header of the wal-index when the last
-** connection to it closes. Because the wal-index is transient, it can
-** use an architecture-specific format; it does not have to be cross-platform.
-** Hence, unlike the database and WAL file formats which store all values
-** as big endian, the wal-index can store multi-byte values in the native
-** byte order of the host computer.
-**
-** The purpose of the wal-index is to answer this question quickly: Given
-** a page number P and a maximum frame index M, return the index of the
-** last frame in the wal before frame M for page P in the WAL, or return
-** NULL if there are no frames for page P in the WAL prior to M.
-**
-** The wal-index consists of a header region, followed by an one or
-** more index blocks.
-**
-** The wal-index header contains the total number of frames within the WAL
-** in the mxFrame field.
-**
-** Each index block except for the first contains information on
-** HASHTABLE_NPAGE frames. The first index block contains information on
-** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
-** HASHTABLE_NPAGE are selected so that together the wal-index header and
-** first index block are the same size as all other index blocks in the
-** wal-index.
-**
-** Each index block contains two sections, a page-mapping that contains the
-** database page number associated with each wal frame, and a hash-table
-** that allows readers to query an index block for a specific page number.
-** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
-** for the first index block) 32-bit page numbers. The first entry in the
-** first index-block contains the database page number corresponding to the
-** first frame in the WAL file. The first entry in the second index block
-** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in
-** the log, and so on.
-**
-** The last index block in a wal-index usually contains less than the full
-** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers,
-** depending on the contents of the WAL file. This does not change the
-** allocated size of the page-mapping array - the page-mapping array merely
-** contains unused entries.
-**
-** Even without using the hash table, the last frame for page P
-** can be found by scanning the page-mapping sections of each index block
-** starting with the last index block and moving toward the first, and
-** within each index block, starting at the end and moving toward the
-** beginning. The first entry that equals P corresponds to the frame
-** holding the content for that page.
-**
-** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers.
-** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the
-** hash table for each page number in the mapping section, so the hash
-** table is never more than half full. The expected number of collisions
-** prior to finding a match is 1. Each entry of the hash table is an
-** 1-based index of an entry in the mapping section of the same
-** index block. Let K be the 1-based index of the largest entry in
-** the mapping section. (For index blocks other than the last, K will
-** always be exactly HASHTABLE_NPAGE (4096) and for the last index block
-** K will be (mxFrame%HASHTABLE_NPAGE).) Unused slots of the hash table
-** contain a value of 0.
-**
-** To look for page P in the hash table, first compute a hash iKey on
-** P as follows:
-**
-** iKey = (P * 383) % HASHTABLE_NSLOT
-**
-** Then start scanning entries of the hash table, starting with iKey
-** (wrapping around to the beginning when the end of the hash table is
-** reached) until an unused hash slot is found. Let the first unused slot
-** be at index iUnused. (iUnused might be less than iKey if there was
-** wrap-around.) Because the hash table is never more than half full,
-** the search is guaranteed to eventually hit an unused entry. Let
-** iMax be the value between iKey and iUnused, closest to iUnused,
-** where aHash[iMax]==P. If there is no iMax entry (if there exists
-** no hash slot such that aHash[i]==p) then page P is not in the
-** current index block. Otherwise the iMax-th mapping entry of the
-** current index block corresponds to the last entry that references
-** page P.
-**
-** A hash search begins with the last index block and moves toward the
-** first index block, looking for entries corresponding to page P. On
-** average, only two or three slots in each index block need to be
-** examined in order to either find the last entry for page P, or to
-** establish that no such entry exists in the block. Each index block
-** holds over 4000 entries. So two or three index blocks are sufficient
-** to cover a typical 10 megabyte WAL file, assuming 1K pages. 8 or 10
-** comparisons (on average) suffice to either locate a frame in the
-** WAL or to establish that the frame does not exist in the WAL. This
-** is much faster than scanning the entire 10MB WAL.
-**
-** Note that entries are added in order of increasing K. Hence, one
-** reader might be using some value K0 and a second reader that started
-** at a later time (after additional transactions were added to the WAL
-** and to the wal-index) might be using a different value K1, where K1>K0.
-** Both readers can use the same hash table and mapping section to get
-** the correct result. There may be entries in the hash table with
-** K>K0 but to the first reader, those entries will appear to be unused
-** slots in the hash table and so the first reader will get an answer as
-** if no values greater than K0 had ever been inserted into the hash table
-** in the first place - which is what reader one wants. Meanwhile, the
-** second reader using K1 will see additional values that were inserted
-** later, which is exactly what reader two wants.
-**
-** When a rollback occurs, the value of K is decreased. Hash table entries
-** that correspond to frames greater than the new K value are removed
-** from the hash table at this point.
-*/
-#ifndef SQLITE_OMIT_WAL
-
-#include "wal.h"
-
-/*
-** Trace output macros
-*/
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-int sqlite3WalTrace = 0;
-# define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X
-#else
-# define WALTRACE(X)
-#endif
-
-/*
-** The maximum (and only) versions of the wal and wal-index formats
-** that may be interpreted by this version of SQLite.
-**
-** If a client begins recovering a WAL file and finds that (a) the checksum
-** values in the wal-header are correct and (b) the version field is not
-** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
-**
-** Similarly, if a client successfully reads a wal-index header (i.e. the
-** checksum test is successful) and finds that the version field is not
-** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
-** returns SQLITE_CANTOPEN.
-*/
-#define WAL_MAX_VERSION 3007000
-#define WALINDEX_MAX_VERSION 3007000
-
-/*
-** Index numbers for various locking bytes. WAL_NREADER is the number
-** of available reader locks and should be at least 3. The default
-** is SQLITE_SHM_NLOCK==8 and WAL_NREADER==5.
-**
-** Technically, the various VFSes are free to implement these locks however
-** they see fit. However, compatibility is encouraged so that VFSes can
-** interoperate. The standard implemention used on both unix and windows
-** is for the index number to indicate a byte offset into the
-** WalCkptInfo.aLock[] array in the wal-index header. In other words, all
-** locks are on the shm file. The WALINDEX_LOCK_OFFSET constant (which
-** should be 120) is the location in the shm file for the first locking
-** byte.
-*/
-#define WAL_WRITE_LOCK 0
-#define WAL_ALL_BUT_WRITE 1
-#define WAL_CKPT_LOCK 1
-#define WAL_RECOVER_LOCK 2
-#define WAL_READ_LOCK(I) (3+(I))
-#define WAL_NREADER (SQLITE_SHM_NLOCK-3)
-
-
-/* Object declarations */
-typedef struct WalIndexHdr WalIndexHdr;
-typedef struct WalIterator WalIterator;
-typedef struct WalCkptInfo WalCkptInfo;
-
-
-/*
-** The following object holds a copy of the wal-index header content.
-**
-** The actual header in the wal-index consists of two copies of this
-** object followed by one instance of the WalCkptInfo object.
-** For all versions of SQLite through 3.10.0 and probably beyond,
-** the locking bytes (WalCkptInfo.aLock) start at offset 120 and
-** the total header size is 136 bytes.
-**
-** The szPage value can be any power of 2 between 512 and 32768, inclusive.
-** Or it can be 1 to represent a 65536-byte page. The latter case was
-** added in 3.7.1 when support for 64K pages was added.
-*/
-struct WalIndexHdr {
- u32 iVersion; /* Wal-index version */
- u32 unused; /* Unused (padding) field */
- u32 iChange; /* Counter incremented each transaction */
- u8 isInit; /* 1 when initialized */
- u8 bigEndCksum; /* True if checksums in WAL are big-endian */
- u16 szPage; /* Database page size in bytes. 1==64K */
- u32 mxFrame; /* Index of last valid frame in the WAL */
- u32 nPage; /* Size of database in pages */
- u32 aFrameCksum[2]; /* Checksum of last frame in log */
- u32 aSalt[2]; /* Two salt values copied from WAL header */
- u32 aCksum[2]; /* Checksum over all prior fields */
-};
-
-/*
-** A copy of the following object occurs in the wal-index immediately
-** following the second copy of the WalIndexHdr. This object stores
-** information used by checkpoint.
-**
-** nBackfill is the number of frames in the WAL that have been written
-** back into the database. (We call the act of moving content from WAL to
-** database "backfilling".) The nBackfill number is never greater than
-** WalIndexHdr.mxFrame. nBackfill can only be increased by threads
-** holding the WAL_CKPT_LOCK lock (which includes a recovery thread).
-** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from
-** mxFrame back to zero when the WAL is reset.
-**
-** nBackfillAttempted is the largest value of nBackfill that a checkpoint
-** has attempted to achieve. Normally nBackfill==nBackfillAtempted, however
-** the nBackfillAttempted is set before any backfilling is done and the
-** nBackfill is only set after all backfilling completes. So if a checkpoint
-** crashes, nBackfillAttempted might be larger than nBackfill. The
-** WalIndexHdr.mxFrame must never be less than nBackfillAttempted.
-**
-** The aLock[] field is a set of bytes used for locking. These bytes should
-** never be read or written.
-**
-** There is one entry in aReadMark[] for each reader lock. If a reader
-** holds read-lock K, then the value in aReadMark[K] is no greater than
-** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff)
-** for any aReadMark[] means that entry is unused. aReadMark[0] is
-** a special case; its value is never used and it exists as a place-holder
-** to avoid having to offset aReadMark[] indexs by one. Readers holding
-** WAL_READ_LOCK(0) always ignore the entire WAL and read all content
-** directly from the database.
-**
-** The value of aReadMark[K] may only be changed by a thread that
-** is holding an exclusive lock on WAL_READ_LOCK(K). Thus, the value of
-** aReadMark[K] cannot changed while there is a reader is using that mark
-** since the reader will be holding a shared lock on WAL_READ_LOCK(K).
-**
-** The checkpointer may only transfer frames from WAL to database where
-** the frame numbers are less than or equal to every aReadMark[] that is
-** in use (that is, every aReadMark[j] for which there is a corresponding
-** WAL_READ_LOCK(j)). New readers (usually) pick the aReadMark[] with the
-** largest value and will increase an unused aReadMark[] to mxFrame if there
-** is not already an aReadMark[] equal to mxFrame. The exception to the
-** previous sentence is when nBackfill equals mxFrame (meaning that everything
-** in the WAL has been backfilled into the database) then new readers
-** will choose aReadMark[0] which has value 0 and hence such reader will
-** get all their all content directly from the database file and ignore
-** the WAL.
-**
-** Writers normally append new frames to the end of the WAL. However,
-** if nBackfill equals mxFrame (meaning that all WAL content has been
-** written back into the database) and if no readers are using the WAL
-** (in other words, if there are no WAL_READ_LOCK(i) where i>0) then
-** the writer will first "reset" the WAL back to the beginning and start
-** writing new content beginning at frame 1.
-**
-** We assume that 32-bit loads are atomic and so no locks are needed in
-** order to read from any aReadMark[] entries.
-*/
-struct WalCkptInfo {
- u32 nBackfill; /* Number of WAL frames backfilled into DB */
- u32 aReadMark[WAL_NREADER]; /* Reader marks */
- u8 aLock[SQLITE_SHM_NLOCK]; /* Reserved space for locks */
- u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */
- u32 notUsed0; /* Available for future enhancements */
-};
-#define READMARK_NOT_USED 0xffffffff
-
-
-/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
-** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
-** only support mandatory file-locks, we do not read or write data
-** from the region of the file on which locks are applied.
-*/
-#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2+offsetof(WalCkptInfo,aLock))
-#define WALINDEX_HDR_SIZE (sizeof(WalIndexHdr)*2+sizeof(WalCkptInfo))
-
-/* Size of header before each frame in wal */
-#define WAL_FRAME_HDRSIZE 24
-
-/* Size of write ahead log header, including checksum. */
-#define WAL_HDRSIZE 32
-
-/* WAL magic value. Either this value, or the same value with the least
-** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit
-** big-endian format in the first 4 bytes of a WAL file.
-**
-** If the LSB is set, then the checksums for each frame within the WAL
-** file are calculated by treating all data as an array of 32-bit
-** big-endian words. Otherwise, they are calculated by interpreting
-** all data as 32-bit little-endian words.
-*/
-#define WAL_MAGIC 0x377f0682
-
-/*
-** Return the offset of frame iFrame in the write-ahead log file,
-** assuming a database page size of szPage bytes. The offset returned
-** is to the start of the write-ahead log frame-header.
-*/
-#define walFrameOffset(iFrame, szPage) ( \
- WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \
-)
-
-/*
-** An open write-ahead log file is represented by an instance of the
-** following object.
-*/
-struct Wal {
- sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
- sqlite3_file *pDbFd; /* File handle for the database file */
- sqlite3_file *pWalFd; /* File handle for WAL file */
- u32 iCallback; /* Value to pass to log callback (or 0) */
- i64 mxWalSize; /* Truncate WAL to this size upon reset */
- int nWiData; /* Size of array apWiData */
- int szFirstBlock; /* Size of first block written to WAL file */
- volatile u32 **apWiData; /* Pointer to wal-index content in memory */
- u32 szPage; /* Database page size */
- i16 readLock; /* Which read lock is being held. -1 for none */
- u8 syncFlags; /* Flags to use to sync header writes */
- u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
- u8 writeLock; /* True if in a write transaction */
- u8 ckptLock; /* True if holding a checkpoint lock */
- u8 readOnly; /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */
- u8 truncateOnCommit; /* True to truncate WAL file on commit */
- u8 syncHeader; /* Fsync the WAL header if true */
- u8 padToSectorBoundary; /* Pad transactions out to the next sector */
- u8 bShmUnreliable; /* SHM content is read-only and unreliable */
- WalIndexHdr hdr; /* Wal-index header for current transaction */
- u32 minFrame; /* Ignore wal frames before this one */
- u32 iReCksum; /* On commit, recalculate checksums from here */
- const char *zWalName; /* Name of WAL file */
- u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
-#ifdef SQLITE_DEBUG
- u8 lockError; /* True if a locking error has occurred */
-#endif
-#ifdef SQLITE_ENABLE_SNAPSHOT
- WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
-#endif
-};
-
-/*
-** Candidate values for Wal.exclusiveMode.
-*/
-#define WAL_NORMAL_MODE 0
-#define WAL_EXCLUSIVE_MODE 1
-#define WAL_HEAPMEMORY_MODE 2
-
-/*
-** Possible values for WAL.readOnly
-*/
-#define WAL_RDWR 0 /* Normal read/write connection */
-#define WAL_RDONLY 1 /* The WAL file is readonly */
-#define WAL_SHM_RDONLY 2 /* The SHM file is readonly */
-
-/*
-** Each page of the wal-index mapping contains a hash-table made up of
-** an array of HASHTABLE_NSLOT elements of the following type.
-*/
-typedef u16 ht_slot;
-
-/*
-** This structure is used to implement an iterator that loops through
-** all frames in the WAL in database page order. Where two or more frames
-** correspond to the same database page, the iterator visits only the
-** frame most recently written to the WAL (in other words, the frame with
-** the largest index).
-**
-** The internals of this structure are only accessed by:
-**
-** walIteratorInit() - Create a new iterator,
-** walIteratorNext() - Step an iterator,
-** walIteratorFree() - Free an iterator.
-**
-** This functionality is used by the checkpoint code (see walCheckpoint()).
-*/
-struct WalIterator {
- int iPrior; /* Last result returned from the iterator */
- int nSegment; /* Number of entries in aSegment[] */
- struct WalSegment {
- int iNext; /* Next slot in aIndex[] not yet returned */
- ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
- u32 *aPgno; /* Array of page numbers. */
- int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
- int iZero; /* Frame number associated with aPgno[0] */
- } aSegment[1]; /* One for every 32KB page in the wal-index */
-};
-
-/*
-** Define the parameters of the hash tables in the wal-index file. There
-** is a hash-table following every HASHTABLE_NPAGE page numbers in the
-** wal-index.
-**
-** Changing any of these constants will alter the wal-index format and
-** create incompatibilities.
-*/
-#define HASHTABLE_NPAGE 4096 /* Must be power of 2 */
-#define HASHTABLE_HASH_1 383 /* Should be prime */
-#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */
-
-/*
-** The block of page numbers associated with the first hash-table in a
-** wal-index is smaller than usual. This is so that there is a complete
-** hash-table on each aligned 32KB page of the wal-index.
-*/
-#define HASHTABLE_NPAGE_ONE (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32)))
-
-/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */
-#define WALINDEX_PGSZ ( \
- sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
-)
-
-/*
-** Obtain a pointer to the iPage'th page of the wal-index. The wal-index
-** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
-** numbered from zero.
-**
-** If the wal-index is currently smaller the iPage pages then the size
-** of the wal-index might be increased, but only if it is safe to do
-** so. It is safe to enlarge the wal-index if pWal->writeLock is true
-** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE.
-**
-** If this call is successful, *ppPage is set to point to the wal-index
-** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
-** then an SQLite error code is returned and *ppPage is set to 0.
-*/
-static SQLITE_NOINLINE int walIndexPageRealloc(
- Wal *pWal, /* The WAL context */
- int iPage, /* The page we seek */
- volatile u32 **ppPage /* Write the page pointer here */
-){
- int rc = SQLITE_OK;
-
- /* Enlarge the pWal->apWiData[] array if required */
- if( pWal->nWiData<=iPage ){
- int nByte = sizeof(u32*)*(iPage+1);
- volatile u32 **apNew;
- apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
- if( !apNew ){
- *ppPage = 0;
- return SQLITE_NOMEM_BKPT;
- }
- memset((void*)&apNew[pWal->nWiData], 0,
- sizeof(u32*)*(iPage+1-pWal->nWiData));
- pWal->apWiData = apNew;
- pWal->nWiData = iPage+1;
- }
-
- /* Request a pointer to the required page from the VFS */
- assert( pWal->apWiData[iPage]==0 );
- if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
- pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
- if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
- }else{
- rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
- pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
- );
- assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
- testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
- if( (rc&0xff)==SQLITE_READONLY ){
- pWal->readOnly |= WAL_SHM_RDONLY;
- if( rc==SQLITE_READONLY ){
- rc = SQLITE_OK;
- }
- }
- }
-
- *ppPage = pWal->apWiData[iPage];
- assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
- return rc;
-}
-static int walIndexPage(
- Wal *pWal, /* The WAL context */
- int iPage, /* The page we seek */
- volatile u32 **ppPage /* Write the page pointer here */
-){
- if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){
- return walIndexPageRealloc(pWal, iPage, ppPage);
- }
- return SQLITE_OK;
-}
-
-/*
-** Return a pointer to the WalCkptInfo structure in the wal-index.
-*/
-static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
- assert( pWal->nWiData>0 && pWal->apWiData[0] );
- return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
-}
-
-/*
-** Return a pointer to the WalIndexHdr structure in the wal-index.
-*/
-static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
- assert( pWal->nWiData>0 && pWal->apWiData[0] );
- return (volatile WalIndexHdr*)pWal->apWiData[0];
-}
-
-/*
-** The argument to this macro must be of type u32. On a little-endian
-** architecture, it returns the u32 value that results from interpreting
-** the 4 bytes as a big-endian value. On a big-endian architecture, it
-** returns the value that would be produced by interpreting the 4 bytes
-** of the input value as a little-endian integer.
-*/
-#define BYTESWAP32(x) ( \
- (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \
- + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \
-)
-
-/*
-** Generate or extend an 8 byte checksum based on the data in
-** array aByte[] and the initial values of aIn[0] and aIn[1] (or
-** initial values of 0 and 0 if aIn==NULL).
-**
-** The checksum is written back into aOut[] before returning.
-**
-** nByte must be a positive multiple of 8.
-*/
-static void walChecksumBytes(
- int nativeCksum, /* True for native byte-order, false for non-native */
- u8 *a, /* Content to be checksummed */
- int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */
- const u32 *aIn, /* Initial checksum value input */
- u32 *aOut /* OUT: Final checksum value output */
-){
- u32 s1, s2;
- u32 *aData = (u32 *)a;
- u32 *aEnd = (u32 *)&a[nByte];
-
- if( aIn ){
- s1 = aIn[0];
- s2 = aIn[1];
- }else{
- s1 = s2 = 0;
- }
-
- assert( nByte>=8 );
- assert( (nByte&0x00000007)==0 );
-
- if( nativeCksum ){
- do {
- s1 += *aData++ + s2;
- s2 += *aData++ + s1;
- }while( aData<aEnd );
- }else{
- do {
- s1 += BYTESWAP32(aData[0]) + s2;
- s2 += BYTESWAP32(aData[1]) + s1;
- aData += 2;
- }while( aData<aEnd );
- }
-
- aOut[0] = s1;
- aOut[1] = s2;
-}
-
-static void walShmBarrier(Wal *pWal){
- if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
- sqlite3OsShmBarrier(pWal->pDbFd);
- }
-}
-
-/*
-** Write the header information in pWal->hdr into the wal-index.
-**
-** The checksum on pWal->hdr is updated before it is written.
-*/
-static void walIndexWriteHdr(Wal *pWal){
- volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
- const int nCksum = offsetof(WalIndexHdr, aCksum);
-
- assert( pWal->writeLock );
- pWal->hdr.isInit = 1;
- pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
- walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
- memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
- walShmBarrier(pWal);
- memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
-}
-
-/*
-** This function encodes a single frame header and writes it to a buffer
-** supplied by the caller. A frame-header is made up of a series of
-** 4-byte big-endian integers, as follows:
-**
-** 0: Page number.
-** 4: For commit records, the size of the database image in pages
-** after the commit. For all other records, zero.
-** 8: Salt-1 (copied from the wal-header)
-** 12: Salt-2 (copied from the wal-header)
-** 16: Checksum-1.
-** 20: Checksum-2.
-*/
-static void walEncodeFrame(
- Wal *pWal, /* The write-ahead log */
- u32 iPage, /* Database page number for frame */
- u32 nTruncate, /* New db size (or 0 for non-commit frames) */
- u8 *aData, /* Pointer to page data */
- u8 *aFrame /* OUT: Write encoded frame here */
-){
- int nativeCksum; /* True for native byte-order checksums */
- u32 *aCksum = pWal->hdr.aFrameCksum;
- assert( WAL_FRAME_HDRSIZE==24 );
- sqlite3Put4byte(&aFrame[0], iPage);
- sqlite3Put4byte(&aFrame[4], nTruncate);
- if( pWal->iReCksum==0 ){
- memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
-
- nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
- walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
- walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
-
- sqlite3Put4byte(&aFrame[16], aCksum[0]);
- sqlite3Put4byte(&aFrame[20], aCksum[1]);
- }else{
- memset(&aFrame[8], 0, 16);
- }
-}
-
-/*
-** Check to see if the frame with header in aFrame[] and content
-** in aData[] is valid. If it is a valid frame, fill *piPage and
-** *pnTruncate and return true. Return if the frame is not valid.
-*/
-static int walDecodeFrame(
- Wal *pWal, /* The write-ahead log */
- u32 *piPage, /* OUT: Database page number for frame */
- u32 *pnTruncate, /* OUT: New db size (or 0 if not commit) */
- u8 *aData, /* Pointer to page data (for checksum) */
- u8 *aFrame /* Frame data */
-){
- int nativeCksum; /* True for native byte-order checksums */
- u32 *aCksum = pWal->hdr.aFrameCksum;
- u32 pgno; /* Page number of the frame */
- assert( WAL_FRAME_HDRSIZE==24 );
-
- /* A frame is only valid if the salt values in the frame-header
- ** match the salt values in the wal-header.
- */
- if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){
- return 0;
- }
-
- /* A frame is only valid if the page number is creater than zero.
- */
- pgno = sqlite3Get4byte(&aFrame[0]);
- if( pgno==0 ){
- return 0;
- }
-
- /* A frame is only valid if a checksum of the WAL header,
- ** all prior frams, the first 16 bytes of this frame-header,
- ** and the frame-data matches the checksum in the last 8
- ** bytes of this frame-header.
- */
- nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
- walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
- walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
- if( aCksum[0]!=sqlite3Get4byte(&aFrame[16])
- || aCksum[1]!=sqlite3Get4byte(&aFrame[20])
- ){
- /* Checksum failed. */
- return 0;
- }
-
- /* If we reach this point, the frame is valid. Return the page number
- ** and the new database size.
- */
- *piPage = pgno;
- *pnTruncate = sqlite3Get4byte(&aFrame[4]);
- return 1;
-}
-
-
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-/*
-** Names of locks. This routine is used to provide debugging output and is not
-** a part of an ordinary build.
-*/
-static const char *walLockName(int lockIdx){
- if( lockIdx==WAL_WRITE_LOCK ){
- return "WRITE-LOCK";
- }else if( lockIdx==WAL_CKPT_LOCK ){
- return "CKPT-LOCK";
- }else if( lockIdx==WAL_RECOVER_LOCK ){
- return "RECOVER-LOCK";
- }else{
- static char zName[15];
- sqlite3_snprintf(sizeof(zName), zName, "READ-LOCK[%d]",
- lockIdx-WAL_READ_LOCK(0));
- return zName;
- }
-}
-#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
-
-
-/*
-** Set or release locks on the WAL. Locks are either shared or exclusive.
-** A lock cannot be moved directly between shared and exclusive - it must go
-** through the unlocked state first.
-**
-** In locking_mode=EXCLUSIVE, all of these routines become no-ops.
-*/
-static int walLockShared(Wal *pWal, int lockIdx){
- int rc;
- if( pWal->exclusiveMode ) return SQLITE_OK;
- rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
- SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
- WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
- walLockName(lockIdx), rc ? "failed" : "ok"));
- VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
- return rc;
-}
-static void walUnlockShared(Wal *pWal, int lockIdx){
- if( pWal->exclusiveMode ) return;
- (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
- SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
- WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
-}
-static int walLockExclusive(Wal *pWal, int lockIdx, int n){
- int rc;
- if( pWal->exclusiveMode ) return SQLITE_OK;
- rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
- SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
- WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
- walLockName(lockIdx), n, rc ? "failed" : "ok"));
- VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
- return rc;
-}
-static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
- if( pWal->exclusiveMode ) return;
- (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
- SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
- WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
- walLockName(lockIdx), n));
-}
-
-/*
-** Compute a hash on a page number. The resulting hash value must land
-** between 0 and (HASHTABLE_NSLOT-1). The walHashNext() function advances
-** the hash to the next value in the event of a collision.
-*/
-static int walHash(u32 iPage){
- assert( iPage>0 );
- assert( (HASHTABLE_NSLOT & (HASHTABLE_NSLOT-1))==0 );
- return (iPage*HASHTABLE_HASH_1) & (HASHTABLE_NSLOT-1);
-}
-static int walNextHash(int iPriorHash){
- return (iPriorHash+1)&(HASHTABLE_NSLOT-1);
-}
-
-/*
-** Return pointers to the hash table and page number array stored on
-** page iHash of the wal-index. The wal-index is broken into 32KB pages
-** numbered starting from 0.
-**
-** Set output variable *paHash to point to the start of the hash table
-** in the wal-index file. Set *piZero to one less than the frame
-** number of the first frame indexed by this hash table. If a
-** slot in the hash table is set to N, it refers to frame number
-** (*piZero+N) in the log.
-**
-** Finally, set *paPgno so that *paPgno[1] is the page number of the
-** first frame indexed by the hash table, frame (*piZero+1).
-*/
-static int walHashGet(
- Wal *pWal, /* WAL handle */
- int iHash, /* Find the iHash'th table */
- volatile ht_slot **paHash, /* OUT: Pointer to hash index */
- volatile u32 **paPgno, /* OUT: Pointer to page number array */
- u32 *piZero /* OUT: Frame associated with *paPgno[0] */
-){
- int rc; /* Return code */
- volatile u32 *aPgno;
-
- rc = walIndexPage(pWal, iHash, &aPgno);
- assert( rc==SQLITE_OK || iHash>0 );
-
- if( rc==SQLITE_OK ){
- u32 iZero;
- volatile ht_slot *aHash;
-
- aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE];
- if( iHash==0 ){
- aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
- iZero = 0;
- }else{
- iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
- }
-
- *paPgno = &aPgno[-1];
- *paHash = aHash;
- *piZero = iZero;
- }
- return rc;
-}
-
-/*
-** Return the number of the wal-index page that contains the hash-table
-** and page-number array that contain entries corresponding to WAL frame
-** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages
-** are numbered starting from 0.
-*/
-static int walFramePage(u32 iFrame){
- int iHash = (iFrame+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1) / HASHTABLE_NPAGE;
- assert( (iHash==0 || iFrame>HASHTABLE_NPAGE_ONE)
- && (iHash>=1 || iFrame<=HASHTABLE_NPAGE_ONE)
- && (iHash<=1 || iFrame>(HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE))
- && (iHash>=2 || iFrame<=HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE)
- && (iHash<=2 || iFrame>(HASHTABLE_NPAGE_ONE+2*HASHTABLE_NPAGE))
- );
- return iHash;
-}
-
-/*
-** Return the page number associated with frame iFrame in this WAL.
-*/
-static u32 walFramePgno(Wal *pWal, u32 iFrame){
- int iHash = walFramePage(iFrame);
- if( iHash==0 ){
- return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1];
- }
- return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE];
-}
-
-/*
-** Remove entries from the hash table that point to WAL slots greater
-** than pWal->hdr.mxFrame.
-**
-** This function is called whenever pWal->hdr.mxFrame is decreased due
-** to a rollback or savepoint.
-**
-** At most only the hash table containing pWal->hdr.mxFrame needs to be
-** updated. Any later hash tables will be automatically cleared when
-** pWal->hdr.mxFrame advances to the point where those hash tables are
-** actually needed.
-*/
-static void walCleanupHash(Wal *pWal){
- volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */
- volatile u32 *aPgno = 0; /* Page number array for hash table */
- u32 iZero = 0; /* frame == (aHash[x]+iZero) */
- int iLimit = 0; /* Zero values greater than this */
- int nByte; /* Number of bytes to zero in aPgno[] */
- int i; /* Used to iterate through aHash[] */
-
- assert( pWal->writeLock );
- testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
- testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE );
- testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 );
-
- if( pWal->hdr.mxFrame==0 ) return;
-
- /* Obtain pointers to the hash-table and page-number array containing
- ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
- ** that the page said hash-table and array reside on is already mapped.
- */
- assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
- assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
- walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero);
-
- /* Zero all hash-table entries that correspond to frame numbers greater
- ** than pWal->hdr.mxFrame.
- */
- iLimit = pWal->hdr.mxFrame - iZero;
- assert( iLimit>0 );
- for(i=0; i<HASHTABLE_NSLOT; i++){
- if( aHash[i]>iLimit ){
- aHash[i] = 0;
- }
- }
-
- /* Zero the entries in the aPgno array that correspond to frames with
- ** frame numbers greater than pWal->hdr.mxFrame.
- */
- nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
- memset((void *)&aPgno[iLimit+1], 0, nByte);
-
-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
- /* Verify that the every entry in the mapping region is still reachable
- ** via the hash table even after the cleanup.
- */
- if( iLimit ){
- int j; /* Loop counter */
- int iKey; /* Hash key */
- for(j=1; j<=iLimit; j++){
- for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){
- if( aHash[iKey]==j ) break;
- }
- assert( aHash[iKey]==j );
- }
- }
-#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
-}
-
-
-/*
-** Set an entry in the wal-index that will map database page number
-** pPage into WAL frame iFrame.
-*/
-static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
- int rc; /* Return code */
- u32 iZero = 0; /* One less than frame number of aPgno[1] */
- volatile u32 *aPgno = 0; /* Page number array */
- volatile ht_slot *aHash = 0; /* Hash table */
-
- rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero);
-
- /* Assuming the wal-index file was successfully mapped, populate the
- ** page number array and hash table entry.
- */
- if( rc==SQLITE_OK ){
- int iKey; /* Hash table key */
- int idx; /* Value to write to hash-table slot */
- int nCollide; /* Number of hash collisions */
-
- idx = iFrame - iZero;
- assert( idx <= HASHTABLE_NSLOT/2 + 1 );
-
- /* If this is the first entry to be added to this hash-table, zero the
- ** entire hash table and aPgno[] array before proceeding.
- */
- if( idx==1 ){
- int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
- memset((void*)&aPgno[1], 0, nByte);
- }
-
- /* If the entry in aPgno[] is already set, then the previous writer
- ** must have exited unexpectedly in the middle of a transaction (after
- ** writing one or more dirty pages to the WAL to free up memory).
- ** Remove the remnants of that writers uncommitted transaction from
- ** the hash-table before writing any new entries.
- */
- if( aPgno[idx] ){
- walCleanupHash(pWal);
- assert( !aPgno[idx] );
- }
-
- /* Write the aPgno[] array entry and the hash-table slot. */
- nCollide = idx;
- for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){
- if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
- }
- aPgno[idx] = iPage;
- aHash[iKey] = (ht_slot)idx;
-
-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
- /* Verify that the number of entries in the hash table exactly equals
- ** the number of entries in the mapping region.
- */
- {
- int i; /* Loop counter */
- int nEntry = 0; /* Number of entries in the hash table */
- for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; }
- assert( nEntry==idx );
- }
-
- /* Verify that the every entry in the mapping region is reachable
- ** via the hash table. This turns out to be a really, really expensive
- ** thing to check, so only do this occasionally - not on every
- ** iteration.
- */
- if( (idx&0x3ff)==0 ){
- int i; /* Loop counter */
- for(i=1; i<=idx; i++){
- for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){
- if( aHash[iKey]==i ) break;
- }
- assert( aHash[iKey]==i );
- }
- }
-#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
- }
-
-
- return rc;
-}
-
-
-/*
-** Recover the wal-index by reading the write-ahead log file.
-**
-** This routine first tries to establish an exclusive lock on the
-** wal-index to prevent other threads/processes from doing anything
-** with the WAL or wal-index while recovery is running. The
-** WAL_RECOVER_LOCK is also held so that other threads will know
-** that this thread is running recovery. If unable to establish
-** the necessary locks, this routine returns SQLITE_BUSY.
-*/
-static int walIndexRecover(Wal *pWal){
- int rc; /* Return Code */
- i64 nSize; /* Size of log file */
- u32 aFrameCksum[2] = {0, 0};
- int iLock; /* Lock offset to lock for checkpoint */
-
- /* Obtain an exclusive lock on all byte in the locking range not already
- ** locked by the caller. The caller is guaranteed to have locked the
- ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
- ** If successful, the same bytes that are locked here are unlocked before
- ** this function returns.
- */
- assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
- assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
- assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
- assert( pWal->writeLock );
- iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
- rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
- if( rc==SQLITE_OK ){
- rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
- if( rc!=SQLITE_OK ){
- walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
- }
- }
- if( rc ){
- return rc;
- }
-
- WALTRACE(("WAL%p: recovery begin...\n", pWal));
-
- memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
-
- rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
- if( rc!=SQLITE_OK ){
- goto recovery_error;
- }
-
- if( nSize>WAL_HDRSIZE ){
- u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */
- u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */
- int szFrame; /* Number of bytes in buffer aFrame[] */
- u8 *aData; /* Pointer to data part of aFrame buffer */
- int iFrame; /* Index of last frame read */
- i64 iOffset; /* Next offset to read from log file */
- int szPage; /* Page size according to the log */
- u32 magic; /* Magic value read from WAL header */
- u32 version; /* Magic value read from WAL header */
- int isValid; /* True if this frame is valid */
-
- /* Read in the WAL header. */
- rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
- if( rc!=SQLITE_OK ){
- goto recovery_error;
- }
-
- /* If the database page size is not a power of two, or is greater than
- ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid
- ** data. Similarly, if the 'magic' value is invalid, ignore the whole
- ** WAL file.
- */
- magic = sqlite3Get4byte(&aBuf[0]);
- szPage = sqlite3Get4byte(&aBuf[8]);
- if( (magic&0xFFFFFFFE)!=WAL_MAGIC
- || szPage&(szPage-1)
- || szPage>SQLITE_MAX_PAGE_SIZE
- || szPage<512
- ){
- goto finished;
- }
- pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
- pWal->szPage = szPage;
- pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
- memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
-
- /* Verify that the WAL header checksum is correct */
- walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
- aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
- );
- if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24])
- || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28])
- ){
- goto finished;
- }
-
- /* Verify that the version number on the WAL format is one that
- ** are able to understand */
- version = sqlite3Get4byte(&aBuf[4]);
- if( version!=WAL_MAX_VERSION ){
- rc = SQLITE_CANTOPEN_BKPT;
- goto finished;
- }
-
- /* Malloc a buffer to read frames into. */
- szFrame = szPage + WAL_FRAME_HDRSIZE;
- aFrame = (u8 *)sqlite3_malloc64(szFrame);
- if( !aFrame ){
- rc = SQLITE_NOMEM_BKPT;
- goto recovery_error;
- }
- aData = &aFrame[WAL_FRAME_HDRSIZE];
-
- /* Read all frames from the log file. */
- iFrame = 0;
- for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){
- u32 pgno; /* Database page number for frame */
- u32 nTruncate; /* dbsize field from frame header */
-
- /* Read and decode the next log frame. */
- iFrame++;
- rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
- if( rc!=SQLITE_OK ) break;
- isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame);
- if( !isValid ) break;
- rc = walIndexAppend(pWal, iFrame, pgno);
- if( rc!=SQLITE_OK ) break;
-
- /* If nTruncate is non-zero, this is a commit record. */
- if( nTruncate ){
- pWal->hdr.mxFrame = iFrame;
- pWal->hdr.nPage = nTruncate;
- pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
- testcase( szPage<=32768 );
- testcase( szPage>=65536 );
- aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
- aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
- }
- }
-
- sqlite3_free(aFrame);
- }
-
-finished:
- if( rc==SQLITE_OK ){
- volatile WalCkptInfo *pInfo;
- int i;
- pWal->hdr.aFrameCksum[0] = aFrameCksum[0];
- pWal->hdr.aFrameCksum[1] = aFrameCksum[1];
- walIndexWriteHdr(pWal);
-
- /* Reset the checkpoint-header. This is safe because this thread is
- ** currently holding locks that exclude all other readers, writers and
- ** checkpointers.
- */
- pInfo = walCkptInfo(pWal);
- pInfo->nBackfill = 0;
- pInfo->nBackfillAttempted = pWal->hdr.mxFrame;
- pInfo->aReadMark[0] = 0;
- for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
- if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
-
- /* If more than one frame was recovered from the log file, report an
- ** event via sqlite3_log(). This is to help with identifying performance
- ** problems caused by applications routinely shutting down without
- ** checkpointing the log file.
- */
- if( pWal->hdr.nPage ){
- sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
- "recovered %d frames from WAL file %s",
- pWal->hdr.mxFrame, pWal->zWalName
- );
- }
- }
-
-recovery_error:
- WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
- walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
- walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
- return rc;
-}
-
-/*
-** Close an open wal-index.
-*/
-static void walIndexClose(Wal *pWal, int isDelete){
- if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE || pWal->bShmUnreliable ){
- int i;
- for(i=0; i<pWal->nWiData; i++){
- sqlite3_free((void *)pWal->apWiData[i]);
- pWal->apWiData[i] = 0;
- }
- }
- if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
- sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
- }
-}
-
-/*
-** Open a connection to the WAL file zWalName. The database file must
-** already be opened on connection pDbFd. The buffer that zWalName points
-** to must remain valid for the lifetime of the returned Wal* handle.
-**
-** A SHARED lock should be held on the database file when this function
-** is called. The purpose of this SHARED lock is to prevent any other
-** client from unlinking the WAL or wal-index file. If another process
-** were to do this just after this client opened one of these files, the
-** system would be badly broken.
-**
-** If the log file is successfully opened, SQLITE_OK is returned and
-** *ppWal is set to point to a new WAL handle. If an error occurs,
-** an SQLite error code is returned and *ppWal is left unmodified.
-*/
-int sqlite3WalOpen(
- sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
- sqlite3_file *pDbFd, /* The open database file */
- const char *zWalName, /* Name of the WAL file */
- int bNoShm, /* True to run in heap-memory mode */
- i64 mxWalSize, /* Truncate WAL to this size on reset */
- Wal **ppWal /* OUT: Allocated Wal handle */
-){
- int rc; /* Return Code */
- Wal *pRet; /* Object to allocate and return */
- int flags; /* Flags passed to OsOpen() */
-
- assert( zWalName && zWalName[0] );
- assert( pDbFd );
-
- /* In the amalgamation, the os_unix.c and os_win.c source files come before
- ** this source file. Verify that the #defines of the locking byte offsets
- ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
- ** For that matter, if the lock offset ever changes from its initial design
- ** value of 120, we need to know that so there is an assert() to check it.
- */
- assert( 120==WALINDEX_LOCK_OFFSET );
- assert( 136==WALINDEX_HDR_SIZE );
-#ifdef WIN_SHM_BASE
- assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
-#endif
-#ifdef UNIX_SHM_BASE
- assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
-#endif
-
-
- /* Allocate an instance of struct Wal to return. */
- *ppWal = 0;
- pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile);
- if( !pRet ){
- return SQLITE_NOMEM_BKPT;
- }
-
- pRet->pVfs = pVfs;
- pRet->pWalFd = (sqlite3_file *)&pRet[1];
- pRet->pDbFd = pDbFd;
- pRet->readLock = -1;
- pRet->mxWalSize = mxWalSize;
- pRet->zWalName = zWalName;
- pRet->syncHeader = 1;
- pRet->padToSectorBoundary = 1;
- pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
-
- /* Open file handle on the write-ahead log file. */
- flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
- rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
- if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
- pRet->readOnly = WAL_RDONLY;
- }
-
- if( rc!=SQLITE_OK ){
- walIndexClose(pRet, 0);
- sqlite3OsClose(pRet->pWalFd);
- sqlite3_free(pRet);
- }else{
- int iDC = sqlite3OsDeviceCharacteristics(pDbFd);
- if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
- if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
- pRet->padToSectorBoundary = 0;
- }
- *ppWal = pRet;
- WALTRACE(("WAL%d: opened\n", pRet));
- }
- return rc;
-}
-
-/*
-** Change the size to which the WAL file is trucated on each reset.
-*/
-void sqlite3WalLimit(Wal *pWal, i64 iLimit){
- if( pWal ) pWal->mxWalSize = iLimit;
-}
-
-/*
-** Find the smallest page number out of all pages held in the WAL that
-** has not been returned by any prior invocation of this method on the
-** same WalIterator object. Write into *piFrame the frame index where
-** that page was last written into the WAL. Write into *piPage the page
-** number.
-**
-** Return 0 on success. If there are no pages in the WAL with a page
-** number larger than *piPage, then return 1.
-*/
-static int walIteratorNext(
- WalIterator *p, /* Iterator */
- u32 *piPage, /* OUT: The page number of the next page */
- u32 *piFrame /* OUT: Wal frame index of next page */
-){
- u32 iMin; /* Result pgno must be greater than iMin */
- u32 iRet = 0xFFFFFFFF; /* 0xffffffff is never a valid page number */
- int i; /* For looping through segments */
-
- iMin = p->iPrior;
- assert( iMin<0xffffffff );
- for(i=p->nSegment-1; i>=0; i--){
- struct WalSegment *pSegment = &p->aSegment[i];
- while( pSegment->iNext<pSegment->nEntry ){
- u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
- if( iPg>iMin ){
- if( iPg<iRet ){
- iRet = iPg;
- *piFrame = pSegment->iZero + pSegment->aIndex[pSegment->iNext];
- }
- break;
- }
- pSegment->iNext++;
- }
- }
-
- *piPage = p->iPrior = iRet;
- return (iRet==0xFFFFFFFF);
-}
-
-/*
-** This function merges two sorted lists into a single sorted list.
-**
-** aLeft[] and aRight[] are arrays of indices. The sort key is
-** aContent[aLeft[]] and aContent[aRight[]]. Upon entry, the following
-** is guaranteed for all J<K:
-**
-** aContent[aLeft[J]] < aContent[aLeft[K]]
-** aContent[aRight[J]] < aContent[aRight[K]]
-**
-** This routine overwrites aRight[] with a new (probably longer) sequence
-** of indices such that the aRight[] contains every index that appears in
-** either aLeft[] or the old aRight[] and such that the second condition
-** above is still met.
-**
-** The aContent[aLeft[X]] values will be unique for all X. And the
-** aContent[aRight[X]] values will be unique too. But there might be
-** one or more combinations of X and Y such that
-**
-** aLeft[X]!=aRight[Y] && aContent[aLeft[X]] == aContent[aRight[Y]]
-**
-** When that happens, omit the aLeft[X] and use the aRight[Y] index.
-*/
-static void walMerge(
- const u32 *aContent, /* Pages in wal - keys for the sort */
- ht_slot *aLeft, /* IN: Left hand input list */
- int nLeft, /* IN: Elements in array *paLeft */
- ht_slot **paRight, /* IN/OUT: Right hand input list */
- int *pnRight, /* IN/OUT: Elements in *paRight */
- ht_slot *aTmp /* Temporary buffer */
-){
- int iLeft = 0; /* Current index in aLeft */
- int iRight = 0; /* Current index in aRight */
- int iOut = 0; /* Current index in output buffer */
- int nRight = *pnRight;
- ht_slot *aRight = *paRight;
-
- assert( nLeft>0 && nRight>0 );
- while( iRight<nRight || iLeft<nLeft ){
- ht_slot logpage;
- Pgno dbpage;
-
- if( (iLeft<nLeft)
- && (iRight>=nRight || aContent[aLeft[iLeft]]<aContent[aRight[iRight]])
- ){
- logpage = aLeft[iLeft++];
- }else{
- logpage = aRight[iRight++];
- }
- dbpage = aContent[logpage];
-
- aTmp[iOut++] = logpage;
- if( iLeft<nLeft && aContent[aLeft[iLeft]]==dbpage ) iLeft++;
-
- assert( iLeft>=nLeft || aContent[aLeft[iLeft]]>dbpage );
- assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage );
- }
-
- *paRight = aLeft;
- *pnRight = iOut;
- memcpy(aLeft, aTmp, sizeof(aTmp[0])*iOut);
-}
-
-/*
-** Sort the elements in list aList using aContent[] as the sort key.
-** Remove elements with duplicate keys, preferring to keep the
-** larger aList[] values.
-**
-** The aList[] entries are indices into aContent[]. The values in
-** aList[] are to be sorted so that for all J<K:
-**
-** aContent[aList[J]] < aContent[aList[K]]
-**
-** For any X and Y such that
-**
-** aContent[aList[X]] == aContent[aList[Y]]
-**
-** Keep the larger of the two values aList[X] and aList[Y] and discard
-** the smaller.
-*/
-static void walMergesort(
- const u32 *aContent, /* Pages in wal */
- ht_slot *aBuffer, /* Buffer of at least *pnList items to use */
- ht_slot *aList, /* IN/OUT: List to sort */
- int *pnList /* IN/OUT: Number of elements in aList[] */
-){
- struct Sublist {
- int nList; /* Number of elements in aList */
- ht_slot *aList; /* Pointer to sub-list content */
- };
-
- const int nList = *pnList; /* Size of input list */
- int nMerge = 0; /* Number of elements in list aMerge */
- ht_slot *aMerge = 0; /* List to be merged */
- int iList; /* Index into input list */
- u32 iSub = 0; /* Index into aSub array */
- struct Sublist aSub[13]; /* Array of sub-lists */
-
- memset(aSub, 0, sizeof(aSub));
- assert( nList<=HASHTABLE_NPAGE && nList>0 );
- assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) );
-
- for(iList=0; iList<nList; iList++){
- nMerge = 1;
- aMerge = &aList[iList];
- for(iSub=0; iList & (1<<iSub); iSub++){
- struct Sublist *p;
- assert( iSub<ArraySize(aSub) );
- p = &aSub[iSub];
- assert( p->aList && p->nList<=(1<<iSub) );
- assert( p->aList==&aList[iList&~((2<<iSub)-1)] );
- walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer);
- }
- aSub[iSub].aList = aMerge;
- aSub[iSub].nList = nMerge;
- }
-
- for(iSub++; iSub<ArraySize(aSub); iSub++){
- if( nList & (1<<iSub) ){
- struct Sublist *p;
- assert( iSub<ArraySize(aSub) );
- p = &aSub[iSub];
- assert( p->nList<=(1<<iSub) );
- assert( p->aList==&aList[nList&~((2<<iSub)-1)] );
- walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer);
- }
- }
- assert( aMerge==aList );
- *pnList = nMerge;
-
-#ifdef SQLITE_DEBUG
- {
- int i;
- for(i=1; i<*pnList; i++){
- assert( aContent[aList[i]] > aContent[aList[i-1]] );
- }
- }
-#endif
-}
-
-/*
-** Free an iterator allocated by walIteratorInit().
-*/
-static void walIteratorFree(WalIterator *p){
- sqlite3_free(p);
-}
-
-/*
-** Construct a WalInterator object that can be used to loop over all
-** pages in the WAL following frame nBackfill in ascending order. Frames
-** nBackfill or earlier may be included - excluding them is an optimization
-** only. The caller must hold the checkpoint lock.
-**
-** On success, make *pp point to the newly allocated WalInterator object
-** return SQLITE_OK. Otherwise, return an error code. If this routine
-** returns an error, the value of *pp is undefined.
-**
-** The calling routine should invoke walIteratorFree() to destroy the
-** WalIterator object when it has finished with it.
-*/
-static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
- WalIterator *p; /* Return value */
- int nSegment; /* Number of segments to merge */
- u32 iLast; /* Last frame in log */
- int nByte; /* Number of bytes to allocate */
- int i; /* Iterator variable */
- ht_slot *aTmp; /* Temp space used by merge-sort */
- int rc = SQLITE_OK; /* Return Code */
-
- /* This routine only runs while holding the checkpoint lock. And
- ** it only runs if there is actually content in the log (mxFrame>0).
- */
- assert( pWal->ckptLock && pWal->hdr.mxFrame>0 );
- iLast = pWal->hdr.mxFrame;
-
- /* Allocate space for the WalIterator object. */
- nSegment = walFramePage(iLast) + 1;
- nByte = sizeof(WalIterator)
- + (nSegment-1)*sizeof(struct WalSegment)
- + iLast*sizeof(ht_slot);
- p = (WalIterator *)sqlite3_malloc64(nByte);
- if( !p ){
- return SQLITE_NOMEM_BKPT;
- }
- memset(p, 0, nByte);
- p->nSegment = nSegment;
-
- /* Allocate temporary space used by the merge-sort routine. This block
- ** of memory will be freed before this function returns.
- */
- aTmp = (ht_slot *)sqlite3_malloc64(
- sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
- );
- if( !aTmp ){
- rc = SQLITE_NOMEM_BKPT;
- }
-
- for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
- volatile ht_slot *aHash;
- u32 iZero;
- volatile u32 *aPgno;
-
- rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero);
- if( rc==SQLITE_OK ){
- int j; /* Counter variable */
- int nEntry; /* Number of entries in this segment */
- ht_slot *aIndex; /* Sorted index for this segment */
-
- aPgno++;
- if( (i+1)==nSegment ){
- nEntry = (int)(iLast - iZero);
- }else{
- nEntry = (int)((u32*)aHash - (u32*)aPgno);
- }
- aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
- iZero++;
-
- for(j=0; j<nEntry; j++){
- aIndex[j] = (ht_slot)j;
- }
- walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry);
- p->aSegment[i].iZero = iZero;
- p->aSegment[i].nEntry = nEntry;
- p->aSegment[i].aIndex = aIndex;
- p->aSegment[i].aPgno = (u32 *)aPgno;
- }
- }
- sqlite3_free(aTmp);
-
- if( rc!=SQLITE_OK ){
- walIteratorFree(p);
- p = 0;
- }
- *pp = p;
- return rc;
-}
-
-/*
-** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
-** n. If the attempt fails and parameter xBusy is not NULL, then it is a
-** busy-handler function. Invoke it and retry the lock until either the
-** lock is successfully obtained or the busy-handler returns 0.
-*/
-static int walBusyLock(
- Wal *pWal, /* WAL connection */
- int (*xBusy)(void*), /* Function to call when busy */
- void *pBusyArg, /* Context argument for xBusyHandler */
- int lockIdx, /* Offset of first byte to lock */
- int n /* Number of bytes to lock */
-){
- int rc;
- do {
- rc = walLockExclusive(pWal, lockIdx, n);
- }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
- return rc;
-}
-
-/*
-** The cache of the wal-index header must be valid to call this function.
-** Return the page-size in bytes used by the database.
-*/
-static int walPagesize(Wal *pWal){
- return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
-}
-
-/*
-** The following is guaranteed when this function is called:
-**
-** a) the WRITER lock is held,
-** b) the entire log file has been checkpointed, and
-** c) any existing readers are reading exclusively from the database
-** file - there are no readers that may attempt to read a frame from
-** the log file.
-**
-** This function updates the shared-memory structures so that the next
-** client to write to the database (which may be this one) does so by
-** writing frames into the start of the log file.
-**
-** The value of parameter salt1 is used as the aSalt[1] value in the
-** new wal-index header. It should be passed a pseudo-random value (i.e.
-** one obtained from sqlite3_randomness()).
-*/
-static void walRestartHdr(Wal *pWal, u32 salt1){
- volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
- int i; /* Loop counter */
- u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */
- pWal->nCkpt++;
- pWal->hdr.mxFrame = 0;
- sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
- memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
- walIndexWriteHdr(pWal);
- pInfo->nBackfill = 0;
- pInfo->nBackfillAttempted = 0;
- pInfo->aReadMark[1] = 0;
- for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
- assert( pInfo->aReadMark[0]==0 );
-}
-
-/*
-** Copy as much content as we can from the WAL back into the database file
-** in response to an sqlite3_wal_checkpoint() request or the equivalent.
-**
-** The amount of information copies from WAL to database might be limited
-** by active readers. This routine will never overwrite a database page
-** that a concurrent reader might be using.
-**
-** All I/O barrier operations (a.k.a fsyncs) occur in this routine when
-** SQLite is in WAL-mode in synchronous=NORMAL. That means that if
-** checkpoints are always run by a background thread or background
-** process, foreground threads will never block on a lengthy fsync call.
-**
-** Fsync is called on the WAL before writing content out of the WAL and
-** into the database. This ensures that if the new content is persistent
-** in the WAL and can be recovered following a power-loss or hard reset.
-**
-** Fsync is also called on the database file if (and only if) the entire
-** WAL content is copied into the database file. This second fsync makes
-** it safe to delete the WAL since the new content will persist in the
-** database file.
-**
-** This routine uses and updates the nBackfill field of the wal-index header.
-** This is the only routine that will increase the value of nBackfill.
-** (A WAL reset or recovery will revert nBackfill to zero, but not increase
-** its value.)
-**
-** The caller must be holding sufficient locks to ensure that no other
-** checkpoint is running (in any other thread or process) at the same
-** time.
-*/
-static int walCheckpoint(
- Wal *pWal, /* Wal connection */
- sqlite3 *db, /* Check for interrupts on this handle */
- int eMode, /* One of PASSIVE, FULL or RESTART */
- int (*xBusy)(void*), /* Function to call when busy */
- void *pBusyArg, /* Context argument for xBusyHandler */
- int sync_flags, /* Flags for OsSync() (or 0) */
- u8 *zBuf /* Temporary buffer to use */
-){
- int rc = SQLITE_OK; /* Return code */
- int szPage; /* Database page-size */
- WalIterator *pIter = 0; /* Wal iterator context */
- u32 iDbpage = 0; /* Next database page to write */
- u32 iFrame = 0; /* Wal frame containing data for iDbpage */
- u32 mxSafeFrame; /* Max frame that can be backfilled */
- u32 mxPage; /* Max database page to write */
- int i; /* Loop counter */
- volatile WalCkptInfo *pInfo; /* The checkpoint status information */
-
- szPage = walPagesize(pWal);
- testcase( szPage<=32768 );
- testcase( szPage>=65536 );
- pInfo = walCkptInfo(pWal);
- if( pInfo->nBackfill<pWal->hdr.mxFrame ){
-
- /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
- ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
- assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
-
- /* Compute in mxSafeFrame the index of the last frame of the WAL that is
- ** safe to write into the database. Frames beyond mxSafeFrame might
- ** overwrite database pages that are in use by active readers and thus
- ** cannot be backfilled from the WAL.
- */
- mxSafeFrame = pWal->hdr.mxFrame;
- mxPage = pWal->hdr.nPage;
- for(i=1; i<WAL_NREADER; i++){
- /* Thread-sanitizer reports that the following is an unsafe read,
- ** as some other thread may be in the process of updating the value
- ** of the aReadMark[] slot. The assumption here is that if that is
- ** happening, the other client may only be increasing the value,
- ** not decreasing it. So assuming either that either the "old" or
- ** "new" version of the value is read, and not some arbitrary value
- ** that would never be written by a real client, things are still
- ** safe. */
- u32 y = pInfo->aReadMark[i];
- if( mxSafeFrame>y ){
- assert( y<=pWal->hdr.mxFrame );
- rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
- if( rc==SQLITE_OK ){
- pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
- walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
- }else if( rc==SQLITE_BUSY ){
- mxSafeFrame = y;
- xBusy = 0;
- }else{
- goto walcheckpoint_out;
- }
- }
- }
-
- /* Allocate the iterator */
- if( pInfo->nBackfill<mxSafeFrame ){
- rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
- assert( rc==SQLITE_OK || pIter==0 );
- }
-
- if( pIter
- && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
- ){
- i64 nSize; /* Current size of database file */
- u32 nBackfill = pInfo->nBackfill;
-
- pInfo->nBackfillAttempted = mxSafeFrame;
-
- /* Sync the WAL to disk */
- rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
-
- /* If the database may grow as a result of this checkpoint, hint
- ** about the eventual size of the db file to the VFS layer.
- */
- if( rc==SQLITE_OK ){
- i64 nReq = ((i64)mxPage * szPage);
- rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
- if( rc==SQLITE_OK && nSize<nReq ){
- sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
- }
- }
-
-
- /* Iterate through the contents of the WAL, copying data to the db file */
- while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
- i64 iOffset;
- assert( walFramePgno(pWal, iFrame)==iDbpage );
- if( db->u1.isInterrupted ){
- rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
- break;
- }
- if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
- continue;
- }
- iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
- /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
- rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
- if( rc!=SQLITE_OK ) break;
- iOffset = (iDbpage-1)*(i64)szPage;
- testcase( IS_BIG_INT(iOffset) );
- rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
- if( rc!=SQLITE_OK ) break;
- }
-
- /* If work was actually accomplished... */
- if( rc==SQLITE_OK ){
- if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
- i64 szDb = pWal->hdr.nPage*(i64)szPage;
- testcase( IS_BIG_INT(szDb) );
- rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
- }
- }
- if( rc==SQLITE_OK ){
- pInfo->nBackfill = mxSafeFrame;
- }
- }
-
- /* Release the reader lock held while backfilling */
- walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
- }
-
- if( rc==SQLITE_BUSY ){
- /* Reset the return code so as not to report a checkpoint failure
- ** just because there are active readers. */
- rc = SQLITE_OK;
- }
- }
-
- /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the
- ** entire wal file has been copied into the database file, then block
- ** until all readers have finished using the wal file. This ensures that
- ** the next process to write to the database restarts the wal file.
- */
- if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
- assert( pWal->writeLock );
- if( pInfo->nBackfill<pWal->hdr.mxFrame ){
- rc = SQLITE_BUSY;
- }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
- u32 salt1;
- sqlite3_randomness(4, &salt1);
- assert( pInfo->nBackfill==pWal->hdr.mxFrame );
- rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
- if( rc==SQLITE_OK ){
- if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){
- /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as
- ** SQLITE_CHECKPOINT_RESTART with the addition that it also
- ** truncates the log file to zero bytes just prior to a
- ** successful return.
- **
- ** In theory, it might be safe to do this without updating the
- ** wal-index header in shared memory, as all subsequent reader or
- ** writer clients should see that the entire log file has been
- ** checkpointed and behave accordingly. This seems unsafe though,
- ** as it would leave the system in a state where the contents of
- ** the wal-index header do not match the contents of the
- ** file-system. To avoid this, update the wal-index header to
- ** indicate that the log file contains zero valid frames. */
- walRestartHdr(pWal, salt1);
- rc = sqlite3OsTruncate(pWal->pWalFd, 0);
- }
- walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
- }
- }
- }
-
- walcheckpoint_out:
- walIteratorFree(pIter);
- return rc;
-}
-
-/*
-** If the WAL file is currently larger than nMax bytes in size, truncate
-** it to exactly nMax bytes. If an error occurs while doing so, ignore it.
-*/
-static void walLimitSize(Wal *pWal, i64 nMax){
- i64 sz;
- int rx;
- sqlite3BeginBenignMalloc();
- rx = sqlite3OsFileSize(pWal->pWalFd, &sz);
- if( rx==SQLITE_OK && (sz > nMax ) ){
- rx = sqlite3OsTruncate(pWal->pWalFd, nMax);
- }
- sqlite3EndBenignMalloc();
- if( rx ){
- sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
- }
-}
-
-/*
-** Close a connection to a log file.
-*/
-int sqlite3WalClose(
- Wal *pWal, /* Wal to close */
- sqlite3 *db, /* For interrupt flag */
- int sync_flags, /* Flags to pass to OsSync() (or 0) */
- int nBuf,
- u8 *zBuf /* Buffer of at least nBuf bytes */
-){
- int rc = SQLITE_OK;
- if( pWal ){
- int isDelete = 0; /* True to unlink wal and wal-index files */
-
- /* If an EXCLUSIVE lock can be obtained on the database file (using the
- ** ordinary, rollback-mode locking methods, this guarantees that the
- ** connection associated with this log file is the only connection to
- ** the database. In this case checkpoint the database and unlink both
- ** the wal and wal-index files.
- **
- ** The EXCLUSIVE lock is not released before returning.
- */
- if( zBuf!=0
- && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE))
- ){
- if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
- pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
- }
- rc = sqlite3WalCheckpoint(pWal, db,
- SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
- );
- if( rc==SQLITE_OK ){
- int bPersist = -1;
- sqlite3OsFileControlHint(
- pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
- );
- if( bPersist!=1 ){
- /* Try to delete the WAL file if the checkpoint completed and
- ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal
- ** mode (!bPersist) */
- isDelete = 1;
- }else if( pWal->mxWalSize>=0 ){
- /* Try to truncate the WAL file to zero bytes if the checkpoint
- ** completed and fsynced (rc==SQLITE_OK) and we are in persistent
- ** WAL mode (bPersist) and if the PRAGMA journal_size_limit is a
- ** non-negative value (pWal->mxWalSize>=0). Note that we truncate
- ** to zero bytes as truncating to the journal_size_limit might
- ** leave a corrupt WAL file on disk. */
- walLimitSize(pWal, 0);
- }
- }
- }
-
- walIndexClose(pWal, isDelete);
- sqlite3OsClose(pWal->pWalFd);
- if( isDelete ){
- sqlite3BeginBenignMalloc();
- sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
- sqlite3EndBenignMalloc();
- }
- WALTRACE(("WAL%p: closed\n", pWal));
- sqlite3_free((void *)pWal->apWiData);
- sqlite3_free(pWal);
- }
- return rc;
-}
-
-/*
-** Try to read the wal-index header. Return 0 on success and 1 if
-** there is a problem.
-**
-** The wal-index is in shared memory. Another thread or process might
-** be writing the header at the same time this procedure is trying to
-** read it, which might result in inconsistency. A dirty read is detected
-** by verifying that both copies of the header are the same and also by
-** a checksum on the header.
-**
-** If and only if the read is consistent and the header is different from
-** pWal->hdr, then pWal->hdr is updated to the content of the new header
-** and *pChanged is set to 1.
-**
-** If the checksum cannot be verified return non-zero. If the header
-** is read successfully and the checksum verified, return zero.
-*/
-static int walIndexTryHdr(Wal *pWal, int *pChanged){
- u32 aCksum[2]; /* Checksum on the header content */
- WalIndexHdr h1, h2; /* Two copies of the header content */
- WalIndexHdr volatile *aHdr; /* Header in shared memory */
-
- /* The first page of the wal-index must be mapped at this point. */
- assert( pWal->nWiData>0 && pWal->apWiData[0] );
-
- /* Read the header. This might happen concurrently with a write to the
- ** same area of shared memory on a different CPU in a SMP,
- ** meaning it is possible that an inconsistent snapshot is read
- ** from the file. If this happens, return non-zero.
- **
- ** There are two copies of the header at the beginning of the wal-index.
- ** When reading, read [0] first then [1]. Writes are in the reverse order.
- ** Memory barriers are used to prevent the compiler or the hardware from
- ** reordering the reads and writes.
- */
- aHdr = walIndexHdr(pWal);
- memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
- walShmBarrier(pWal);
- memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
-
- if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
- return 1; /* Dirty read */
- }
- if( h1.isInit==0 ){
- return 1; /* Malformed header - probably all zeros */
- }
- walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
- if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
- return 1; /* Checksum does not match */
- }
-
- if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
- *pChanged = 1;
- memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr));
- pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
- testcase( pWal->szPage<=32768 );
- testcase( pWal->szPage>=65536 );
- }
-
- /* The header was successfully read. Return zero. */
- return 0;
-}
-
-/*
-** This is the value that walTryBeginRead returns when it needs to
-** be retried.
-*/
-#define WAL_RETRY (-1)
-
-/*
-** Read the wal-index header from the wal-index and into pWal->hdr.
-** If the wal-header appears to be corrupt, try to reconstruct the
-** wal-index from the WAL before returning.
-**
-** Set *pChanged to 1 if the wal-index header value in pWal->hdr is
-** changed by this operation. If pWal->hdr is unchanged, set *pChanged
-** to 0.
-**
-** If the wal-index header is successfully read, return SQLITE_OK.
-** Otherwise an SQLite error code.
-*/
-static int walIndexReadHdr(Wal *pWal, int *pChanged){
- int rc; /* Return code */
- int badHdr; /* True if a header read failed */
- volatile u32 *page0; /* Chunk of wal-index containing header */
-
- /* Ensure that page 0 of the wal-index (the page that contains the
- ** wal-index header) is mapped. Return early if an error occurs here.
- */
- assert( pChanged );
- rc = walIndexPage(pWal, 0, &page0);
- if( rc!=SQLITE_OK ){
- assert( rc!=SQLITE_READONLY ); /* READONLY changed to OK in walIndexPage */
- if( rc==SQLITE_READONLY_CANTINIT ){
- /* The SQLITE_READONLY_CANTINIT return means that the shared-memory
- ** was openable but is not writable, and this thread is unable to
- ** confirm that another write-capable connection has the shared-memory
- ** open, and hence the content of the shared-memory is unreliable,
- ** since the shared-memory might be inconsistent with the WAL file
- ** and there is no writer on hand to fix it. */
- assert( page0==0 );
- assert( pWal->writeLock==0 );
- assert( pWal->readOnly & WAL_SHM_RDONLY );
- pWal->bShmUnreliable = 1;
- pWal->exclusiveMode = WAL_HEAPMEMORY_MODE;
- *pChanged = 1;
- }else{
- return rc; /* Any other non-OK return is just an error */
- }
- }else{
- /* page0 can be NULL if the SHM is zero bytes in size and pWal->writeLock
- ** is zero, which prevents the SHM from growing */
- testcase( page0!=0 );
- }
- assert( page0!=0 || pWal->writeLock==0 );
-
- /* If the first page of the wal-index has been mapped, try to read the
- ** wal-index header immediately, without holding any lock. This usually
- ** works, but may fail if the wal-index header is corrupt or currently
- ** being modified by another thread or process.
- */
- badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
-
- /* If the first attempt failed, it might have been due to a race
- ** with a writer. So get a WRITE lock and try again.
- */
- assert( badHdr==0 || pWal->writeLock==0 );
- if( badHdr ){
- if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
- if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
- walUnlockShared(pWal, WAL_WRITE_LOCK);
- rc = SQLITE_READONLY_RECOVERY;
- }
- }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
- pWal->writeLock = 1;
- if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
- badHdr = walIndexTryHdr(pWal, pChanged);
- if( badHdr ){
- /* If the wal-index header is still malformed even while holding
- ** a WRITE lock, it can only mean that the header is corrupted and
- ** needs to be reconstructed. So run recovery to do exactly that.
- */
- rc = walIndexRecover(pWal);
- *pChanged = 1;
- }
- }
- pWal->writeLock = 0;
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
- }
- }
-
- /* If the header is read successfully, check the version number to make
- ** sure the wal-index was not constructed with some future format that
- ** this version of SQLite cannot understand.
- */
- if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
- rc = SQLITE_CANTOPEN_BKPT;
- }
- if( pWal->bShmUnreliable ){
- if( rc!=SQLITE_OK ){
- walIndexClose(pWal, 0);
- pWal->bShmUnreliable = 0;
- assert( pWal->nWiData>0 && pWal->apWiData[0]==0 );
- /* walIndexRecover() might have returned SHORT_READ if a concurrent
- ** writer truncated the WAL out from under it. If that happens, it
- ** indicates that a writer has fixed the SHM file for us, so retry */
- if( rc==SQLITE_IOERR_SHORT_READ ) rc = WAL_RETRY;
- }
- pWal->exclusiveMode = WAL_NORMAL_MODE;
- }
-
- return rc;
-}
-
-/*
-** Open a transaction in a connection where the shared-memory is read-only
-** and where we cannot verify that there is a separate write-capable connection
-** on hand to keep the shared-memory up-to-date with the WAL file.
-**
-** This can happen, for example, when the shared-memory is implemented by
-** memory-mapping a *-shm file, where a prior writer has shut down and
-** left the *-shm file on disk, and now the present connection is trying
-** to use that database but lacks write permission on the *-shm file.
-** Other scenarios are also possible, depending on the VFS implementation.
-**
-** Precondition:
-**
-** The *-wal file has been read and an appropriate wal-index has been
-** constructed in pWal->apWiData[] using heap memory instead of shared
-** memory.
-**
-** If this function returns SQLITE_OK, then the read transaction has
-** been successfully opened. In this case output variable (*pChanged)
-** is set to true before returning if the caller should discard the
-** contents of the page cache before proceeding. Or, if it returns
-** WAL_RETRY, then the heap memory wal-index has been discarded and
-** the caller should retry opening the read transaction from the
-** beginning (including attempting to map the *-shm file).
-**
-** If an error occurs, an SQLite error code is returned.
-*/
-static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
- i64 szWal; /* Size of wal file on disk in bytes */
- i64 iOffset; /* Current offset when reading wal file */
- u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */
- u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */
- int szFrame; /* Number of bytes in buffer aFrame[] */
- u8 *aData; /* Pointer to data part of aFrame buffer */
- volatile void *pDummy; /* Dummy argument for xShmMap */
- int rc; /* Return code */
- u32 aSaveCksum[2]; /* Saved copy of pWal->hdr.aFrameCksum */
-
- assert( pWal->bShmUnreliable );
- assert( pWal->readOnly & WAL_SHM_RDONLY );
- assert( pWal->nWiData>0 && pWal->apWiData[0] );
-
- /* Take WAL_READ_LOCK(0). This has the effect of preventing any
- ** writers from running a checkpoint, but does not stop them
- ** from running recovery. */
- rc = walLockShared(pWal, WAL_READ_LOCK(0));
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_BUSY ) rc = WAL_RETRY;
- goto begin_unreliable_shm_out;
- }
- pWal->readLock = 0;
-
- /* Check to see if a separate writer has attached to the shared-memory area,
- ** thus making the shared-memory "reliable" again. Do this by invoking
- ** the xShmMap() routine of the VFS and looking to see if the return
- ** is SQLITE_READONLY instead of SQLITE_READONLY_CANTINIT.
- **
- ** If the shared-memory is now "reliable" return WAL_RETRY, which will
- ** cause the heap-memory WAL-index to be discarded and the actual
- ** shared memory to be used in its place.
- **
- ** This step is important because, even though this connection is holding
- ** the WAL_READ_LOCK(0) which prevents a checkpoint, a writer might
- ** have already checkpointed the WAL file and, while the current
- ** is active, wrap the WAL and start overwriting frames that this
- ** process wants to use.
- **
- ** Once sqlite3OsShmMap() has been called for an sqlite3_file and has
- ** returned any SQLITE_READONLY value, it must return only SQLITE_READONLY
- ** or SQLITE_READONLY_CANTINIT or some error for all subsequent invocations,
- ** even if some external agent does a "chmod" to make the shared-memory
- ** writable by us, until sqlite3OsShmUnmap() has been called.
- ** This is a requirement on the VFS implementation.
- */
- rc = sqlite3OsShmMap(pWal->pDbFd, 0, WALINDEX_PGSZ, 0, &pDummy);
- assert( rc!=SQLITE_OK ); /* SQLITE_OK not possible for read-only connection */
- if( rc!=SQLITE_READONLY_CANTINIT ){
- rc = (rc==SQLITE_READONLY ? WAL_RETRY : rc);
- goto begin_unreliable_shm_out;
- }
-
- /* We reach this point only if the real shared-memory is still unreliable.
- ** Assume the in-memory WAL-index substitute is correct and load it
- ** into pWal->hdr.
- */
- memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr));
-
- /* Make sure some writer hasn't come in and changed the WAL file out
- ** from under us, then disconnected, while we were not looking.
- */
- rc = sqlite3OsFileSize(pWal->pWalFd, &szWal);
- if( rc!=SQLITE_OK ){
- goto begin_unreliable_shm_out;
- }
- if( szWal<WAL_HDRSIZE ){
- /* If the wal file is too small to contain a wal-header and the
- ** wal-index header has mxFrame==0, then it must be safe to proceed
- ** reading the database file only. However, the page cache cannot
- ** be trusted, as a read/write connection may have connected, written
- ** the db, run a checkpoint, truncated the wal file and disconnected
- ** since this client's last read transaction. */
- *pChanged = 1;
- rc = (pWal->hdr.mxFrame==0 ? SQLITE_OK : WAL_RETRY);
- goto begin_unreliable_shm_out;
- }
-
- /* Check the salt keys at the start of the wal file still match. */
- rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
- if( rc!=SQLITE_OK ){
- goto begin_unreliable_shm_out;
- }
- if( memcmp(&pWal->hdr.aSalt, &aBuf[16], 8) ){
- /* Some writer has wrapped the WAL file while we were not looking.
- ** Return WAL_RETRY which will cause the in-memory WAL-index to be
- ** rebuilt. */
- rc = WAL_RETRY;
- goto begin_unreliable_shm_out;
- }
-
- /* Allocate a buffer to read frames into */
- szFrame = pWal->hdr.szPage + WAL_FRAME_HDRSIZE;
- aFrame = (u8 *)sqlite3_malloc64(szFrame);
- if( aFrame==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto begin_unreliable_shm_out;
- }
- aData = &aFrame[WAL_FRAME_HDRSIZE];
-
- /* Check to see if a complete transaction has been appended to the
- ** wal file since the heap-memory wal-index was created. If so, the
- ** heap-memory wal-index is discarded and WAL_RETRY returned to
- ** the caller. */
- aSaveCksum[0] = pWal->hdr.aFrameCksum[0];
- aSaveCksum[1] = pWal->hdr.aFrameCksum[1];
- for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage);
- iOffset+szFrame<=szWal;
- iOffset+=szFrame
- ){
- u32 pgno; /* Database page number for frame */
- u32 nTruncate; /* dbsize field from frame header */
-
- /* Read and decode the next log frame. */
- rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
- if( rc!=SQLITE_OK ) break;
- if( !walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame) ) break;
-
- /* If nTruncate is non-zero, then a complete transaction has been
- ** appended to this wal file. Set rc to WAL_RETRY and break out of
- ** the loop. */
- if( nTruncate ){
- rc = WAL_RETRY;
- break;
- }
- }
- pWal->hdr.aFrameCksum[0] = aSaveCksum[0];
- pWal->hdr.aFrameCksum[1] = aSaveCksum[1];
-
- begin_unreliable_shm_out:
- sqlite3_free(aFrame);
- if( rc!=SQLITE_OK ){
- int i;
- for(i=0; i<pWal->nWiData; i++){
- sqlite3_free((void*)pWal->apWiData[i]);
- pWal->apWiData[i] = 0;
- }
- pWal->bShmUnreliable = 0;
- sqlite3WalEndReadTransaction(pWal);
- *pChanged = 1;
- }
- return rc;
-}
-
-/*
-** Attempt to start a read transaction. This might fail due to a race or
-** other transient condition. When that happens, it returns WAL_RETRY to
-** indicate to the caller that it is safe to retry immediately.
-**
-** On success return SQLITE_OK. On a permanent failure (such an
-** I/O error or an SQLITE_BUSY because another process is running
-** recovery) return a positive error code.
-**
-** The useWal parameter is true to force the use of the WAL and disable
-** the case where the WAL is bypassed because it has been completely
-** checkpointed. If useWal==0 then this routine calls walIndexReadHdr()
-** to make a copy of the wal-index header into pWal->hdr. If the
-** wal-index header has changed, *pChanged is set to 1 (as an indication
-** to the caller that the local page cache is obsolete and needs to be
-** flushed.) When useWal==1, the wal-index header is assumed to already
-** be loaded and the pChanged parameter is unused.
-**
-** The caller must set the cnt parameter to the number of prior calls to
-** this routine during the current read attempt that returned WAL_RETRY.
-** This routine will start taking more aggressive measures to clear the
-** race conditions after multiple WAL_RETRY returns, and after an excessive
-** number of errors will ultimately return SQLITE_PROTOCOL. The
-** SQLITE_PROTOCOL return indicates that some other process has gone rogue
-** and is not honoring the locking protocol. There is a vanishingly small
-** chance that SQLITE_PROTOCOL could be returned because of a run of really
-** bad luck when there is lots of contention for the wal-index, but that
-** possibility is so small that it can be safely neglected, we believe.
-**
-** On success, this routine obtains a read lock on
-** WAL_READ_LOCK(pWal->readLock). The pWal->readLock integer is
-** in the range 0 <= pWal->readLock < WAL_NREADER. If pWal->readLock==(-1)
-** that means the Wal does not hold any read lock. The reader must not
-** access any database page that is modified by a WAL frame up to and
-** including frame number aReadMark[pWal->readLock]. The reader will
-** use WAL frames up to and including pWal->hdr.mxFrame if pWal->readLock>0
-** Or if pWal->readLock==0, then the reader will ignore the WAL
-** completely and get all content directly from the database file.
-** If the useWal parameter is 1 then the WAL will never be ignored and
-** this routine will always set pWal->readLock>0 on success.
-** When the read transaction is completed, the caller must release the
-** lock on WAL_READ_LOCK(pWal->readLock) and set pWal->readLock to -1.
-**
-** This routine uses the nBackfill and aReadMark[] fields of the header
-** to select a particular WAL_READ_LOCK() that strives to let the
-** checkpoint process do as much work as possible. This routine might
-** update values of the aReadMark[] array in the header, but if it does
-** so it takes care to hold an exclusive lock on the corresponding
-** WAL_READ_LOCK() while changing values.
-*/
-static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
- volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
- u32 mxReadMark; /* Largest aReadMark[] value */
- int mxI; /* Index of largest aReadMark[] value */
- int i; /* Loop counter */
- int rc = SQLITE_OK; /* Return code */
- u32 mxFrame; /* Wal frame to lock to */
-
- assert( pWal->readLock<0 ); /* Not currently locked */
-
- /* useWal may only be set for read/write connections */
- assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 );
-
- /* Take steps to avoid spinning forever if there is a protocol error.
- **
- ** Circumstances that cause a RETRY should only last for the briefest
- ** instances of time. No I/O or other system calls are done while the
- ** locks are held, so the locks should not be held for very long. But
- ** if we are unlucky, another process that is holding a lock might get
- ** paged out or take a page-fault that is time-consuming to resolve,
- ** during the few nanoseconds that it is holding the lock. In that case,
- ** it might take longer than normal for the lock to free.
- **
- ** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few
- ** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this
- ** is more of a scheduler yield than an actual delay. But on the 10th
- ** an subsequent retries, the delays start becoming longer and longer,
- ** so that on the 100th (and last) RETRY we delay for 323 milliseconds.
- ** The total delay time before giving up is less than 10 seconds.
- */
- if( cnt>5 ){
- int nDelay = 1; /* Pause time in microseconds */
- if( cnt>100 ){
- VVA_ONLY( pWal->lockError = 1; )
- return SQLITE_PROTOCOL;
- }
- if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39;
- sqlite3OsSleep(pWal->pVfs, nDelay);
- }
-
- if( !useWal ){
- assert( rc==SQLITE_OK );
- if( pWal->bShmUnreliable==0 ){
- rc = walIndexReadHdr(pWal, pChanged);
- }
- if( rc==SQLITE_BUSY ){
- /* If there is not a recovery running in another thread or process
- ** then convert BUSY errors to WAL_RETRY. If recovery is known to
- ** be running, convert BUSY to BUSY_RECOVERY. There is a race here
- ** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY
- ** would be technically correct. But the race is benign since with
- ** WAL_RETRY this routine will be called again and will probably be
- ** right on the second iteration.
- */
- if( pWal->apWiData[0]==0 ){
- /* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
- ** We assume this is a transient condition, so return WAL_RETRY. The
- ** xShmMap() implementation used by the default unix and win32 VFS
- ** modules may return SQLITE_BUSY due to a race condition in the
- ** code that determines whether or not the shared-memory region
- ** must be zeroed before the requested page is returned.
- */
- rc = WAL_RETRY;
- }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){
- walUnlockShared(pWal, WAL_RECOVER_LOCK);
- rc = WAL_RETRY;
- }else if( rc==SQLITE_BUSY ){
- rc = SQLITE_BUSY_RECOVERY;
- }
- }
- if( rc!=SQLITE_OK ){
- return rc;
- }
- else if( pWal->bShmUnreliable ){
- return walBeginShmUnreliable(pWal, pChanged);
- }
- }
-
- assert( pWal->nWiData>0 );
- assert( pWal->apWiData[0]!=0 );
- pInfo = walCkptInfo(pWal);
- if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
-#ifdef SQLITE_ENABLE_SNAPSHOT
- && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
-#endif
- ){
- /* The WAL has been completely backfilled (or it is empty).
- ** and can be safely ignored.
- */
- rc = walLockShared(pWal, WAL_READ_LOCK(0));
- walShmBarrier(pWal);
- if( rc==SQLITE_OK ){
- if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
- /* It is not safe to allow the reader to continue here if frames
- ** may have been appended to the log before READ_LOCK(0) was obtained.
- ** When holding READ_LOCK(0), the reader ignores the entire log file,
- ** which implies that the database file contains a trustworthy
- ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
- ** happening, this is usually correct.
- **
- ** However, if frames have been appended to the log (or if the log
- ** is wrapped and written for that matter) before the READ_LOCK(0)
- ** is obtained, that is not necessarily true. A checkpointer may
- ** have started to backfill the appended frames but crashed before
- ** it finished. Leaving a corrupt image in the database file.
- */
- walUnlockShared(pWal, WAL_READ_LOCK(0));
- return WAL_RETRY;
- }
- pWal->readLock = 0;
- return SQLITE_OK;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
- }
- }
-
- /* If we get this far, it means that the reader will want to use
- ** the WAL to get at content from recent commits. The job now is
- ** to select one of the aReadMark[] entries that is closest to
- ** but not exceeding pWal->hdr.mxFrame and lock that entry.
- */
- mxReadMark = 0;
- mxI = 0;
- mxFrame = pWal->hdr.mxFrame;
-#ifdef SQLITE_ENABLE_SNAPSHOT
- if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){
- mxFrame = pWal->pSnapshot->mxFrame;
- }
-#endif
- for(i=1; i<WAL_NREADER; i++){
- u32 thisMark = pInfo->aReadMark[i];
- if( mxReadMark<=thisMark && thisMark<=mxFrame ){
- assert( thisMark!=READMARK_NOT_USED );
- mxReadMark = thisMark;
- mxI = i;
- }
- }
- if( (pWal->readOnly & WAL_SHM_RDONLY)==0
- && (mxReadMark<mxFrame || mxI==0)
- ){
- for(i=1; i<WAL_NREADER; i++){
- rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
- if( rc==SQLITE_OK ){
- mxReadMark = pInfo->aReadMark[i] = mxFrame;
- mxI = i;
- walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
- break;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
- }
- }
- }
- if( mxI==0 ){
- assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
- return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
- }
-
- rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
- if( rc ){
- return rc==SQLITE_BUSY ? WAL_RETRY : rc;
- }
- /* Now that the read-lock has been obtained, check that neither the
- ** value in the aReadMark[] array or the contents of the wal-index
- ** header have changed.
- **
- ** It is necessary to check that the wal-index header did not change
- ** between the time it was read and when the shared-lock was obtained
- ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
- ** that the log file may have been wrapped by a writer, or that frames
- ** that occur later in the log than pWal->hdr.mxFrame may have been
- ** copied into the database by a checkpointer. If either of these things
- ** happened, then reading the database with the current value of
- ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
- ** instead.
- **
- ** Before checking that the live wal-index header has not changed
- ** since it was read, set Wal.minFrame to the first frame in the wal
- ** file that has not yet been checkpointed. This client will not need
- ** to read any frames earlier than minFrame from the wal file - they
- ** can be safely read directly from the database file.
- **
- ** Because a ShmBarrier() call is made between taking the copy of
- ** nBackfill and checking that the wal-header in shared-memory still
- ** matches the one cached in pWal->hdr, it is guaranteed that the
- ** checkpointer that set nBackfill was not working with a wal-index
- ** header newer than that cached in pWal->hdr. If it were, that could
- ** cause a problem. The checkpointer could omit to checkpoint
- ** a version of page X that lies before pWal->minFrame (call that version
- ** A) on the basis that there is a newer version (version B) of the same
- ** page later in the wal file. But if version B happens to like past
- ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
- ** that it can read version A from the database file. However, since
- ** we can guarantee that the checkpointer that set nBackfill could not
- ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
- */
- pWal->minFrame = pInfo->nBackfill+1;
- walShmBarrier(pWal);
- if( pInfo->aReadMark[mxI]!=mxReadMark
- || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
- ){
- walUnlockShared(pWal, WAL_READ_LOCK(mxI));
- return WAL_RETRY;
- }else{
- assert( mxReadMark<=pWal->hdr.mxFrame );
- pWal->readLock = (i16)mxI;
- }
- return rc;
-}
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/*
-** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted
-** variable so that older snapshots can be accessed. To do this, loop
-** through all wal frames from nBackfillAttempted to (nBackfill+1),
-** comparing their content to the corresponding page with the database
-** file, if any. Set nBackfillAttempted to the frame number of the
-** first frame for which the wal file content matches the db file.
-**
-** This is only really safe if the file-system is such that any page
-** writes made by earlier checkpointers were atomic operations, which
-** is not always true. It is also possible that nBackfillAttempted
-** may be left set to a value larger than expected, if a wal frame
-** contains content that duplicate of an earlier version of the same
-** page.
-**
-** SQLITE_OK is returned if successful, or an SQLite error code if an
-** error occurs. It is not an error if nBackfillAttempted cannot be
-** decreased at all.
-*/
-int sqlite3WalSnapshotRecover(Wal *pWal){
- int rc;
-
- assert( pWal->readLock>=0 );
- rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
- if( rc==SQLITE_OK ){
- volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
- int szPage = (int)pWal->szPage;
- i64 szDb; /* Size of db file in bytes */
-
- rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
- if( rc==SQLITE_OK ){
- void *pBuf1 = sqlite3_malloc(szPage);
- void *pBuf2 = sqlite3_malloc(szPage);
- if( pBuf1==0 || pBuf2==0 ){
- rc = SQLITE_NOMEM;
- }else{
- u32 i = pInfo->nBackfillAttempted;
- for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
- volatile ht_slot *dummy;
- volatile u32 *aPgno; /* Array of page numbers */
- u32 iZero; /* Frame corresponding to aPgno[0] */
- u32 pgno; /* Page number in db file */
- i64 iDbOff; /* Offset of db file entry */
- i64 iWalOff; /* Offset of wal file entry */
-
- rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero);
- if( rc!=SQLITE_OK ) break;
- pgno = aPgno[i-iZero];
- iDbOff = (i64)(pgno-1) * szPage;
-
- if( iDbOff+szPage<=szDb ){
- iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
- rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
- }
-
- if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
- break;
- }
- }
-
- pInfo->nBackfillAttempted = i-1;
- }
- }
-
- sqlite3_free(pBuf1);
- sqlite3_free(pBuf2);
- }
- walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
- }
-
- return rc;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-/*
-** Begin a read transaction on the database.
-**
-** This routine used to be called sqlite3OpenSnapshot() and with good reason:
-** it takes a snapshot of the state of the WAL and wal-index for the current
-** instant in time. The current thread will continue to use this snapshot.
-** Other threads might append new content to the WAL and wal-index but
-** that extra content is ignored by the current thread.
-**
-** If the database contents have changes since the previous read
-** transaction, then *pChanged is set to 1 before returning. The
-** Pager layer will use this to know that is cache is stale and
-** needs to be flushed.
-*/
-int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
- int rc; /* Return code */
- int cnt = 0; /* Number of TryBeginRead attempts */
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
- int bChanged = 0;
- WalIndexHdr *pSnapshot = pWal->pSnapshot;
- if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
- bChanged = 1;
- }
-#endif
-
- do{
- rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
- }while( rc==WAL_RETRY );
- testcase( (rc&0xff)==SQLITE_BUSY );
- testcase( (rc&0xff)==SQLITE_IOERR );
- testcase( rc==SQLITE_PROTOCOL );
- testcase( rc==SQLITE_OK );
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
- if( rc==SQLITE_OK ){
- if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
- /* At this point the client has a lock on an aReadMark[] slot holding
- ** a value equal to or smaller than pSnapshot->mxFrame, but pWal->hdr
- ** is populated with the wal-index header corresponding to the head
- ** of the wal file. Verify that pSnapshot is still valid before
- ** continuing. Reasons why pSnapshot might no longer be valid:
- **
- ** (1) The WAL file has been reset since the snapshot was taken.
- ** In this case, the salt will have changed.
- **
- ** (2) A checkpoint as been attempted that wrote frames past
- ** pSnapshot->mxFrame into the database file. Note that the
- ** checkpoint need not have completed for this to cause problems.
- */
- volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
-
- assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 );
- assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame );
-
- /* It is possible that there is a checkpointer thread running
- ** concurrent with this code. If this is the case, it may be that the
- ** checkpointer has already determined that it will checkpoint
- ** snapshot X, where X is later in the wal file than pSnapshot, but
- ** has not yet set the pInfo->nBackfillAttempted variable to indicate
- ** its intent. To avoid the race condition this leads to, ensure that
- ** there is no checkpointer process by taking a shared CKPT lock
- ** before checking pInfo->nBackfillAttempted.
- **
- ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing
- ** this already?
- */
- rc = walLockShared(pWal, WAL_CKPT_LOCK);
-
- if( rc==SQLITE_OK ){
- /* Check that the wal file has not been wrapped. Assuming that it has
- ** not, also check that no checkpointer has attempted to checkpoint any
- ** frames beyond pSnapshot->mxFrame. If either of these conditions are
- ** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr
- ** with *pSnapshot and set *pChanged as appropriate for opening the
- ** snapshot. */
- if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
- && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
- ){
- assert( pWal->readLock>0 );
- memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
- *pChanged = bChanged;
- }else{
- rc = SQLITE_BUSY_SNAPSHOT;
- }
-
- /* Release the shared CKPT lock obtained above. */
- walUnlockShared(pWal, WAL_CKPT_LOCK);
- }
-
-
- if( rc!=SQLITE_OK ){
- sqlite3WalEndReadTransaction(pWal);
- }
- }
- }
-#endif
- return rc;
-}
-
-/*
-** Finish with a read transaction. All this does is release the
-** read-lock.
-*/
-void sqlite3WalEndReadTransaction(Wal *pWal){
- sqlite3WalEndWriteTransaction(pWal);
- if( pWal->readLock>=0 ){
- walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
- pWal->readLock = -1;
- }
-}
-
-/*
-** Search the wal file for page pgno. If found, set *piRead to the frame that
-** contains the page. Otherwise, if pgno is not in the wal file, set *piRead
-** to zero.
-**
-** Return SQLITE_OK if successful, or an error code if an error occurs. If an
-** error does occur, the final value of *piRead is undefined.
-*/
-int sqlite3WalFindFrame(
- Wal *pWal, /* WAL handle */
- Pgno pgno, /* Database page number to read data for */
- u32 *piRead /* OUT: Frame number (or zero) */
-){
- u32 iRead = 0; /* If !=0, WAL frame to return data from */
- u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */
- int iHash; /* Used to loop through N hash tables */
- int iMinHash;
-
- /* This routine is only be called from within a read transaction. */
- assert( pWal->readLock>=0 || pWal->lockError );
-
- /* If the "last page" field of the wal-index header snapshot is 0, then
- ** no data will be read from the wal under any circumstances. Return early
- ** in this case as an optimization. Likewise, if pWal->readLock==0,
- ** then the WAL is ignored by the reader so return early, as if the
- ** WAL were empty.
- */
- if( iLast==0 || (pWal->readLock==0 && pWal->bShmUnreliable==0) ){
- *piRead = 0;
- return SQLITE_OK;
- }
-
- /* Search the hash table or tables for an entry matching page number
- ** pgno. Each iteration of the following for() loop searches one
- ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
- **
- ** This code might run concurrently to the code in walIndexAppend()
- ** that adds entries to the wal-index (and possibly to this hash
- ** table). This means the value just read from the hash
- ** slot (aHash[iKey]) may have been added before or after the
- ** current read transaction was opened. Values added after the
- ** read transaction was opened may have been written incorrectly -
- ** i.e. these slots may contain garbage data. However, we assume
- ** that any slots written before the current read transaction was
- ** opened remain unmodified.
- **
- ** For the reasons above, the if(...) condition featured in the inner
- ** loop of the following block is more stringent that would be required
- ** if we had exclusive access to the hash-table:
- **
- ** (aPgno[iFrame]==pgno):
- ** This condition filters out normal hash-table collisions.
- **
- ** (iFrame<=iLast):
- ** This condition filters out entries that were added to the hash
- ** table after the current read-transaction had started.
- */
- iMinHash = walFramePage(pWal->minFrame);
- for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
- volatile ht_slot *aHash; /* Pointer to hash table */
- volatile u32 *aPgno; /* Pointer to array of page numbers */
- u32 iZero; /* Frame number corresponding to aPgno[0] */
- int iKey; /* Hash slot index */
- int nCollide; /* Number of hash collisions remaining */
- int rc; /* Error code */
-
- rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- nCollide = HASHTABLE_NSLOT;
- for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
- u32 iFrame = aHash[iKey] + iZero;
- if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){
- assert( iFrame>iRead || CORRUPT_DB );
- iRead = iFrame;
- }
- if( (nCollide--)==0 ){
- return SQLITE_CORRUPT_BKPT;
- }
- }
- if( iRead ) break;
- }
-
-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
- /* If expensive assert() statements are available, do a linear search
- ** of the wal-index file content. Make sure the results agree with the
- ** result obtained using the hash indexes above. */
- {
- u32 iRead2 = 0;
- u32 iTest;
- assert( pWal->bShmUnreliable || pWal->minFrame>0 );
- for(iTest=iLast; iTest>=pWal->minFrame && iTest>0; iTest--){
- if( walFramePgno(pWal, iTest)==pgno ){
- iRead2 = iTest;
- break;
- }
- }
- assert( iRead==iRead2 );
- }
-#endif
-
- *piRead = iRead;
- return SQLITE_OK;
-}
-
-/*
-** Read the contents of frame iRead from the wal file into buffer pOut
-** (which is nOut bytes in size). Return SQLITE_OK if successful, or an
-** error code otherwise.
-*/
-int sqlite3WalReadFrame(
- Wal *pWal, /* WAL handle */
- u32 iRead, /* Frame to read */
- int nOut, /* Size of buffer pOut in bytes */
- u8 *pOut /* Buffer to write page data to */
-){
- int sz;
- i64 iOffset;
- sz = pWal->hdr.szPage;
- sz = (sz&0xfe00) + ((sz&0x0001)<<16);
- testcase( sz<=32768 );
- testcase( sz>=65536 );
- iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
- /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
- return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
-}
-
-/*
-** Return the size of the database in pages (or zero, if unknown).
-*/
-Pgno sqlite3WalDbsize(Wal *pWal){
- if( pWal && ALWAYS(pWal->readLock>=0) ){
- return pWal->hdr.nPage;
- }
- return 0;
-}
-
-
-/*
-** This function starts a write transaction on the WAL.
-**
-** A read transaction must have already been started by a prior call
-** to sqlite3WalBeginReadTransaction().
-**
-** If another thread or process has written into the database since
-** the read transaction was started, then it is not possible for this
-** thread to write as doing so would cause a fork. So this routine
-** returns SQLITE_BUSY in that case and no write transaction is started.
-**
-** There can only be a single writer active at a time.
-*/
-int sqlite3WalBeginWriteTransaction(Wal *pWal){
- int rc;
-
- /* Cannot start a write transaction without first holding a read
- ** transaction. */
- assert( pWal->readLock>=0 );
- assert( pWal->writeLock==0 && pWal->iReCksum==0 );
-
- if( pWal->readOnly ){
- return SQLITE_READONLY;
- }
-
- /* Only one writer allowed at a time. Get the write lock. Return
- ** SQLITE_BUSY if unable.
- */
- rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
- if( rc ){
- return rc;
- }
- pWal->writeLock = 1;
-
- /* If another connection has written to the database file since the
- ** time the read transaction on this connection was started, then
- ** the write is disallowed.
- */
- if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
- pWal->writeLock = 0;
- rc = SQLITE_BUSY_SNAPSHOT;
- }
-
- return rc;
-}
-
-/*
-** End a write transaction. The commit has already been done. This
-** routine merely releases the lock.
-*/
-int sqlite3WalEndWriteTransaction(Wal *pWal){
- if( pWal->writeLock ){
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
- pWal->writeLock = 0;
- pWal->iReCksum = 0;
- pWal->truncateOnCommit = 0;
- }
- return SQLITE_OK;
-}
-
-/*
-** If any data has been written (but not committed) to the log file, this
-** function moves the write-pointer back to the start of the transaction.
-**
-** Additionally, the callback function is invoked for each frame written
-** to the WAL since the start of the transaction. If the callback returns
-** other than SQLITE_OK, it is not invoked again and the error code is
-** returned to the caller.
-**
-** Otherwise, if the callback function does not return an error, this
-** function returns SQLITE_OK.
-*/
-int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
- int rc = SQLITE_OK;
- if( ALWAYS(pWal->writeLock) ){
- Pgno iMax = pWal->hdr.mxFrame;
- Pgno iFrame;
-
- /* Restore the clients cache of the wal-index header to the state it
- ** was in before the client began writing to the database.
- */
- memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
-
- for(iFrame=pWal->hdr.mxFrame+1;
- ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
- iFrame++
- ){
- /* This call cannot fail. Unless the page for which the page number
- ** is passed as the second argument is (a) in the cache and
- ** (b) has an outstanding reference, then xUndo is either a no-op
- ** (if (a) is false) or simply expels the page from the cache (if (b)
- ** is false).
- **
- ** If the upper layer is doing a rollback, it is guaranteed that there
- ** are no outstanding references to any page other than page 1. And
- ** page 1 is never written to the log until the transaction is
- ** committed. As a result, the call to xUndo may not fail.
- */
- assert( walFramePgno(pWal, iFrame)!=1 );
- rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
- }
- if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
- }
- return rc;
-}
-
-/*
-** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32
-** values. This function populates the array with values required to
-** "rollback" the write position of the WAL handle back to the current
-** point in the event of a savepoint rollback (via WalSavepointUndo()).
-*/
-void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){
- assert( pWal->writeLock );
- aWalData[0] = pWal->hdr.mxFrame;
- aWalData[1] = pWal->hdr.aFrameCksum[0];
- aWalData[2] = pWal->hdr.aFrameCksum[1];
- aWalData[3] = pWal->nCkpt;
-}
-
-/*
-** Move the write position of the WAL back to the point identified by
-** the values in the aWalData[] array. aWalData must point to an array
-** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated
-** by a call to WalSavepoint().
-*/
-int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
- int rc = SQLITE_OK;
-
- assert( pWal->writeLock );
- assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame );
-
- if( aWalData[3]!=pWal->nCkpt ){
- /* This savepoint was opened immediately after the write-transaction
- ** was started. Right after that, the writer decided to wrap around
- ** to the start of the log. Update the savepoint values to match.
- */
- aWalData[0] = 0;
- aWalData[3] = pWal->nCkpt;
- }
-
- if( aWalData[0]<pWal->hdr.mxFrame ){
- pWal->hdr.mxFrame = aWalData[0];
- pWal->hdr.aFrameCksum[0] = aWalData[1];
- pWal->hdr.aFrameCksum[1] = aWalData[2];
- walCleanupHash(pWal);
- }
-
- return rc;
-}
-
-/*
-** This function is called just before writing a set of frames to the log
-** file (see sqlite3WalFrames()). It checks to see if, instead of appending
-** to the current log file, it is possible to overwrite the start of the
-** existing log file with the new frames (i.e. "reset" the log). If so,
-** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left
-** unchanged.
-**
-** SQLITE_OK is returned if no error is encountered (regardless of whether
-** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned
-** if an error occurs.
-*/
-static int walRestartLog(Wal *pWal){
- int rc = SQLITE_OK;
- int cnt;
-
- if( pWal->readLock==0 ){
- volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
- assert( pInfo->nBackfill==pWal->hdr.mxFrame );
- if( pInfo->nBackfill>0 ){
- u32 salt1;
- sqlite3_randomness(4, &salt1);
- rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
- if( rc==SQLITE_OK ){
- /* If all readers are using WAL_READ_LOCK(0) (in other words if no
- ** readers are currently using the WAL), then the transactions
- ** frames will overwrite the start of the existing log. Update the
- ** wal-index header to reflect this.
- **
- ** In theory it would be Ok to update the cache of the header only
- ** at this point. But updating the actual wal-index header is also
- ** safe and means there is no special case for sqlite3WalUndo()
- ** to handle if this transaction is rolled back. */
- walRestartHdr(pWal, salt1);
- walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
- }else if( rc!=SQLITE_BUSY ){
- return rc;
- }
- }
- walUnlockShared(pWal, WAL_READ_LOCK(0));
- pWal->readLock = -1;
- cnt = 0;
- do{
- int notUsed;
- rc = walTryBeginRead(pWal, &notUsed, 1, ++cnt);
- }while( rc==WAL_RETRY );
- assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */
- testcase( (rc&0xff)==SQLITE_IOERR );
- testcase( rc==SQLITE_PROTOCOL );
- testcase( rc==SQLITE_OK );
- }
- return rc;
-}
-
-/*
-** Information about the current state of the WAL file and where
-** the next fsync should occur - passed from sqlite3WalFrames() into
-** walWriteToLog().
-*/
-typedef struct WalWriter {
- Wal *pWal; /* The complete WAL information */
- sqlite3_file *pFd; /* The WAL file to which we write */
- sqlite3_int64 iSyncPoint; /* Fsync at this offset */
- int syncFlags; /* Flags for the fsync */
- int szPage; /* Size of one page */
-} WalWriter;
-
-/*
-** Write iAmt bytes of content into the WAL file beginning at iOffset.
-** Do a sync when crossing the p->iSyncPoint boundary.
-**
-** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt,
-** first write the part before iSyncPoint, then sync, then write the
-** rest.
-*/
-static int walWriteToLog(
- WalWriter *p, /* WAL to write to */
- void *pContent, /* Content to be written */
- int iAmt, /* Number of bytes to write */
- sqlite3_int64 iOffset /* Start writing at this offset */
-){
- int rc;
- if( iOffset<p->iSyncPoint && iOffset+iAmt>=p->iSyncPoint ){
- int iFirstAmt = (int)(p->iSyncPoint - iOffset);
- rc = sqlite3OsWrite(p->pFd, pContent, iFirstAmt, iOffset);
- if( rc ) return rc;
- iOffset += iFirstAmt;
- iAmt -= iFirstAmt;
- pContent = (void*)(iFirstAmt + (char*)pContent);
- assert( WAL_SYNC_FLAGS(p->syncFlags)!=0 );
- rc = sqlite3OsSync(p->pFd, WAL_SYNC_FLAGS(p->syncFlags));
- if( iAmt==0 || rc ) return rc;
- }
- rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
- return rc;
-}
-
-/*
-** Write out a single frame of the WAL
-*/
-static int walWriteOneFrame(
- WalWriter *p, /* Where to write the frame */
- PgHdr *pPage, /* The page of the frame to be written */
- int nTruncate, /* The commit flag. Usually 0. >0 for commit */
- sqlite3_int64 iOffset /* Byte offset at which to write */
-){
- int rc; /* Result code from subfunctions */
- void *pData; /* Data actually written */
- u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
-#if defined(SQLITE_HAS_CODEC)
- if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;
-#else
- pData = pPage->pData;
-#endif
- walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
- rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
- if( rc ) return rc;
- /* Write the page data */
- rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
- return rc;
-}
-
-/*
-** This function is called as part of committing a transaction within which
-** one or more frames have been overwritten. It updates the checksums for
-** all frames written to the wal file by the current transaction starting
-** with the earliest to have been overwritten.
-**
-** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
-*/
-static int walRewriteChecksums(Wal *pWal, u32 iLast){
- const int szPage = pWal->szPage;/* Database page size */
- int rc = SQLITE_OK; /* Return code */
- u8 *aBuf; /* Buffer to load data from wal file into */
- u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-headers in */
- u32 iRead; /* Next frame to read from wal file */
- i64 iCksumOff;
-
- aBuf = sqlite3_malloc(szPage + WAL_FRAME_HDRSIZE);
- if( aBuf==0 ) return SQLITE_NOMEM_BKPT;
-
- /* Find the checksum values to use as input for the recalculating the
- ** first checksum. If the first frame is frame 1 (implying that the current
- ** transaction restarted the wal file), these values must be read from the
- ** wal-file header. Otherwise, read them from the frame header of the
- ** previous frame. */
- assert( pWal->iReCksum>0 );
- if( pWal->iReCksum==1 ){
- iCksumOff = 24;
- }else{
- iCksumOff = walFrameOffset(pWal->iReCksum-1, szPage) + 16;
- }
- rc = sqlite3OsRead(pWal->pWalFd, aBuf, sizeof(u32)*2, iCksumOff);
- pWal->hdr.aFrameCksum[0] = sqlite3Get4byte(aBuf);
- pWal->hdr.aFrameCksum[1] = sqlite3Get4byte(&aBuf[sizeof(u32)]);
-
- iRead = pWal->iReCksum;
- pWal->iReCksum = 0;
- for(; rc==SQLITE_OK && iRead<=iLast; iRead++){
- i64 iOff = walFrameOffset(iRead, szPage);
- rc = sqlite3OsRead(pWal->pWalFd, aBuf, szPage+WAL_FRAME_HDRSIZE, iOff);
- if( rc==SQLITE_OK ){
- u32 iPgno, nDbSize;
- iPgno = sqlite3Get4byte(aBuf);
- nDbSize = sqlite3Get4byte(&aBuf[4]);
-
- walEncodeFrame(pWal, iPgno, nDbSize, &aBuf[WAL_FRAME_HDRSIZE], aFrame);
- rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOff);
- }
- }
-
- sqlite3_free(aBuf);
- return rc;
-}
-
-/*
-** Write a set of frames to the log. The caller must hold the write-lock
-** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
-*/
-int sqlite3WalFrames(
- Wal *pWal, /* Wal handle to write to */
- int szPage, /* Database page-size in bytes */
- PgHdr *pList, /* List of dirty pages to write */
- Pgno nTruncate, /* Database size after this commit */
- int isCommit, /* True if this is a commit */
- int sync_flags /* Flags to pass to OsSync() (or 0) */
-){
- int rc; /* Used to catch return codes */
- u32 iFrame; /* Next frame address */
- PgHdr *p; /* Iterator to run through pList with. */
- PgHdr *pLast = 0; /* Last frame in list */
- int nExtra = 0; /* Number of extra copies of last page */
- int szFrame; /* The size of a single frame */
- i64 iOffset; /* Next byte to write in WAL file */
- WalWriter w; /* The writer */
- u32 iFirst = 0; /* First frame that may be overwritten */
- WalIndexHdr *pLive; /* Pointer to shared header */
-
- assert( pList );
- assert( pWal->writeLock );
-
- /* If this frame set completes a transaction, then nTruncate>0. If
- ** nTruncate==0 then this frame set does not complete the transaction. */
- assert( (isCommit!=0)==(nTruncate!=0) );
-
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
- { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
- WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
- pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
- }
-#endif
-
- pLive = (WalIndexHdr*)walIndexHdr(pWal);
- if( memcmp(&pWal->hdr, (void *)pLive, sizeof(WalIndexHdr))!=0 ){
- iFirst = pLive->mxFrame+1;
- }
-
- /* See if it is possible to write these frames into the start of the
- ** log file, instead of appending to it at pWal->hdr.mxFrame.
- */
- if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
- return rc;
- }
-
- /* If this is the first frame written into the log, write the WAL
- ** header to the start of the WAL file. See comments at the top of
- ** this source file for a description of the WAL header format.
- */
- iFrame = pWal->hdr.mxFrame;
- if( iFrame==0 ){
- u8 aWalHdr[WAL_HDRSIZE]; /* Buffer to assemble wal-header in */
- u32 aCksum[2]; /* Checksum for wal-header */
-
- sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN));
- sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION);
- sqlite3Put4byte(&aWalHdr[8], szPage);
- sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt);
- if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt);
- memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8);
- walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum);
- sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
- sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
-
- pWal->szPage = szPage;
- pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
- pWal->hdr.aFrameCksum[0] = aCksum[0];
- pWal->hdr.aFrameCksum[1] = aCksum[1];
- pWal->truncateOnCommit = 1;
-
- rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0);
- WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok"));
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless
- ** all syncing is turned off by PRAGMA synchronous=OFF). Otherwise
- ** an out-of-order write following a WAL restart could result in
- ** database corruption. See the ticket:
- **
- ** https://sqlite.org/src/info/ff5be73dee
- */
- if( pWal->syncHeader ){
- rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
- if( rc ) return rc;
- }
- }
- assert( (int)pWal->szPage==szPage );
-
- /* Setup information needed to write frames into the WAL */
- w.pWal = pWal;
- w.pFd = pWal->pWalFd;
- w.iSyncPoint = 0;
- w.syncFlags = sync_flags;
- w.szPage = szPage;
- iOffset = walFrameOffset(iFrame+1, szPage);
- szFrame = szPage + WAL_FRAME_HDRSIZE;
-
- /* Write all frames into the log file exactly once */
- for(p=pList; p; p=p->pDirty){
- int nDbSize; /* 0 normally. Positive == commit flag */
-
- /* Check if this page has already been written into the wal file by
- ** the current transaction. If so, overwrite the existing frame and
- ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that
- ** checksums must be recomputed when the transaction is committed. */
- if( iFirst && (p->pDirty || isCommit==0) ){
- u32 iWrite = 0;
- VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite);
- assert( rc==SQLITE_OK || iWrite==0 );
- if( iWrite>=iFirst ){
- i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
- void *pData;
- if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){
- pWal->iReCksum = iWrite;
- }
-#if defined(SQLITE_HAS_CODEC)
- if( (pData = sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM;
-#else
- pData = p->pData;
-#endif
- rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff);
- if( rc ) return rc;
- p->flags &= ~PGHDR_WAL_APPEND;
- continue;
- }
- }
-
- iFrame++;
- assert( iOffset==walFrameOffset(iFrame, szPage) );
- nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0;
- rc = walWriteOneFrame(&w, p, nDbSize, iOffset);
- if( rc ) return rc;
- pLast = p;
- iOffset += szFrame;
- p->flags |= PGHDR_WAL_APPEND;
- }
-
- /* Recalculate checksums within the wal file if required. */
- if( isCommit && pWal->iReCksum ){
- rc = walRewriteChecksums(pWal, iFrame);
- if( rc ) return rc;
- }
-
- /* If this is the end of a transaction, then we might need to pad
- ** the transaction and/or sync the WAL file.
- **
- ** Padding and syncing only occur if this set of frames complete a
- ** transaction and if PRAGMA synchronous=FULL. If synchronous==NORMAL
- ** or synchronous==OFF, then no padding or syncing are needed.
- **
- ** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not
- ** needed and only the sync is done. If padding is needed, then the
- ** final frame is repeated (with its commit mark) until the next sector
- ** boundary is crossed. Only the part of the WAL prior to the last
- ** sector boundary is synced; the part of the last frame that extends
- ** past the sector boundary is written after the sync.
- */
- if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){
- int bSync = 1;
- if( pWal->padToSectorBoundary ){
- int sectorSize = sqlite3SectorSize(pWal->pWalFd);
- w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
- bSync = (w.iSyncPoint==iOffset);
- testcase( bSync );
- while( iOffset<w.iSyncPoint ){
- rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
- if( rc ) return rc;
- iOffset += szFrame;
- nExtra++;
- }
- }
- if( bSync ){
- assert( rc==SQLITE_OK );
- rc = sqlite3OsSync(w.pFd, WAL_SYNC_FLAGS(sync_flags));
- }
- }
-
- /* If this frame set completes the first transaction in the WAL and
- ** if PRAGMA journal_size_limit is set, then truncate the WAL to the
- ** journal size limit, if possible.
- */
- if( isCommit && pWal->truncateOnCommit && pWal->mxWalSize>=0 ){
- i64 sz = pWal->mxWalSize;
- if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){
- sz = walFrameOffset(iFrame+nExtra+1, szPage);
- }
- walLimitSize(pWal, sz);
- pWal->truncateOnCommit = 0;
- }
-
- /* Append data to the wal-index. It is not necessary to lock the
- ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index
- ** guarantees that there are no other writers, and no data that may
- ** be in use by existing readers is being overwritten.
- */
- iFrame = pWal->hdr.mxFrame;
- for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
- if( (p->flags & PGHDR_WAL_APPEND)==0 ) continue;
- iFrame++;
- rc = walIndexAppend(pWal, iFrame, p->pgno);
- }
- while( rc==SQLITE_OK && nExtra>0 ){
- iFrame++;
- nExtra--;
- rc = walIndexAppend(pWal, iFrame, pLast->pgno);
- }
-
- if( rc==SQLITE_OK ){
- /* Update the private copy of the header. */
- pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
- testcase( szPage<=32768 );
- testcase( szPage>=65536 );
- pWal->hdr.mxFrame = iFrame;
- if( isCommit ){
- pWal->hdr.iChange++;
- pWal->hdr.nPage = nTruncate;
- }
- /* If this is a commit, update the wal-index header too. */
- if( isCommit ){
- walIndexWriteHdr(pWal);
- pWal->iCallback = iFrame;
- }
- }
-
- WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok"));
- return rc;
-}
-
-/*
-** This routine is called to implement sqlite3_wal_checkpoint() and
-** related interfaces.
-**
-** Obtain a CHECKPOINT lock and then backfill as much information as
-** we can from WAL into the database.
-**
-** If parameter xBusy is not NULL, it is a pointer to a busy-handler
-** callback. In this case this function runs a blocking checkpoint.
-*/
-int sqlite3WalCheckpoint(
- Wal *pWal, /* Wal connection */
- sqlite3 *db, /* Check this handle's interrupt flag */
- int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
- int (*xBusy)(void*), /* Function to call when busy */
- void *pBusyArg, /* Context argument for xBusyHandler */
- int sync_flags, /* Flags to sync db file with (or 0) */
- int nBuf, /* Size of temporary buffer */
- u8 *zBuf, /* Temporary buffer to use */
- int *pnLog, /* OUT: Number of frames in WAL */
- int *pnCkpt /* OUT: Number of backfilled frames in WAL */
-){
- int rc; /* Return code */
- int isChanged = 0; /* True if a new wal-index header is loaded */
- int eMode2 = eMode; /* Mode to pass to walCheckpoint() */
- int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */
-
- assert( pWal->ckptLock==0 );
- assert( pWal->writeLock==0 );
-
- /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
- ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
- assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
-
- if( pWal->readOnly ) return SQLITE_READONLY;
- WALTRACE(("WAL%p: checkpoint begins\n", pWal));
-
- /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
- ** "checkpoint" lock on the database file. */
- rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
- if( rc ){
- /* EVIDENCE-OF: R-10421-19736 If any other process is running a
- ** checkpoint operation at the same time, the lock cannot be obtained and
- ** SQLITE_BUSY is returned.
- ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
- ** it will not be invoked in this case.
- */
- testcase( rc==SQLITE_BUSY );
- testcase( xBusy!=0 );
- return rc;
- }
- pWal->ckptLock = 1;
-
- /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
- ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
- ** file.
- **
- ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
- ** immediately, and a busy-handler is configured, it is invoked and the
- ** writer lock retried until either the busy-handler returns 0 or the
- ** lock is successfully obtained.
- */
- if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
- rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
- if( rc==SQLITE_OK ){
- pWal->writeLock = 1;
- }else if( rc==SQLITE_BUSY ){
- eMode2 = SQLITE_CHECKPOINT_PASSIVE;
- xBusy2 = 0;
- rc = SQLITE_OK;
- }
- }
-
- /* Read the wal-index header. */
- if( rc==SQLITE_OK ){
- rc = walIndexReadHdr(pWal, &isChanged);
- if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
- sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
- }
- }
-
- /* Copy data from the log to the database file. */
- if( rc==SQLITE_OK ){
-
- if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
- }
-
- /* If no error occurred, set the output variables. */
- if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
- if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
- if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
- }
- }
-
- if( isChanged ){
- /* If a new wal-index header was loaded before the checkpoint was
- ** performed, then the pager-cache associated with pWal is now
- ** out of date. So zero the cached wal-index header to ensure that
- ** next time the pager opens a snapshot on this database it knows that
- ** the cache needs to be reset.
- */
- memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
- }
-
- /* Release the locks. */
- sqlite3WalEndWriteTransaction(pWal);
- walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
- pWal->ckptLock = 0;
- WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
- return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
-}
-
-/* Return the value to pass to a sqlite3_wal_hook callback, the
-** number of frames in the WAL at the point of the last commit since
-** sqlite3WalCallback() was called. If no commits have occurred since
-** the last call, then return 0.
-*/
-int sqlite3WalCallback(Wal *pWal){
- u32 ret = 0;
- if( pWal ){
- ret = pWal->iCallback;
- pWal->iCallback = 0;
- }
- return (int)ret;
-}
-
-/*
-** This function is called to change the WAL subsystem into or out
-** of locking_mode=EXCLUSIVE.
-**
-** If op is zero, then attempt to change from locking_mode=EXCLUSIVE
-** into locking_mode=NORMAL. This means that we must acquire a lock
-** on the pWal->readLock byte. If the WAL is already in locking_mode=NORMAL
-** or if the acquisition of the lock fails, then return 0. If the
-** transition out of exclusive-mode is successful, return 1. This
-** operation must occur while the pager is still holding the exclusive
-** lock on the main database file.
-**
-** If op is one, then change from locking_mode=NORMAL into
-** locking_mode=EXCLUSIVE. This means that the pWal->readLock must
-** be released. Return 1 if the transition is made and 0 if the
-** WAL is already in exclusive-locking mode - meaning that this
-** routine is a no-op. The pager must already hold the exclusive lock
-** on the main database file before invoking this operation.
-**
-** If op is negative, then do a dry-run of the op==1 case but do
-** not actually change anything. The pager uses this to see if it
-** should acquire the database exclusive lock prior to invoking
-** the op==1 case.
-*/
-int sqlite3WalExclusiveMode(Wal *pWal, int op){
- int rc;
- assert( pWal->writeLock==0 );
- assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
-
- /* pWal->readLock is usually set, but might be -1 if there was a
- ** prior error while attempting to acquire are read-lock. This cannot
- ** happen if the connection is actually in exclusive mode (as no xShmLock
- ** locks are taken in this case). Nor should the pager attempt to
- ** upgrade to exclusive-mode following such an error.
- */
- assert( pWal->readLock>=0 || pWal->lockError );
- assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
-
- if( op==0 ){
- if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){
- pWal->exclusiveMode = WAL_NORMAL_MODE;
- if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){
- pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
- }
- rc = pWal->exclusiveMode==WAL_NORMAL_MODE;
- }else{
- /* Already in locking_mode=NORMAL */
- rc = 0;
- }
- }else if( op>0 ){
- assert( pWal->exclusiveMode==WAL_NORMAL_MODE );
- assert( pWal->readLock>=0 );
- walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
- pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
- rc = 1;
- }else{
- rc = pWal->exclusiveMode==WAL_NORMAL_MODE;
- }
- return rc;
-}
-
-/*
-** Return true if the argument is non-NULL and the WAL module is using
-** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
-** WAL module is using shared-memory, return false.
-*/
-int sqlite3WalHeapMemory(Wal *pWal){
- return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
-}
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-/* Create a snapshot object. The content of a snapshot is opaque to
-** every other subsystem, so the WAL module can put whatever it needs
-** in the object.
-*/
-int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){
- int rc = SQLITE_OK;
- WalIndexHdr *pRet;
- static const u32 aZero[4] = { 0, 0, 0, 0 };
-
- assert( pWal->readLock>=0 && pWal->writeLock==0 );
-
- if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,16)==0 ){
- *ppSnapshot = 0;
- return SQLITE_ERROR;
- }
- pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr));
- if( pRet==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr));
- *ppSnapshot = (sqlite3_snapshot*)pRet;
- }
-
- return rc;
-}
-
-/* Try to open on pSnapshot when the next read-transaction starts
-*/
-void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
- pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
-}
-
-/*
-** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
-** p1 is older than p2 and zero if p1 and p2 are the same snapshot.
-*/
-int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
- WalIndexHdr *pHdr1 = (WalIndexHdr*)p1;
- WalIndexHdr *pHdr2 = (WalIndexHdr*)p2;
-
- /* aSalt[0] is a copy of the value stored in the wal file header. It
- ** is incremented each time the wal file is restarted. */
- if( pHdr1->aSalt[0]<pHdr2->aSalt[0] ) return -1;
- if( pHdr1->aSalt[0]>pHdr2->aSalt[0] ) return +1;
- if( pHdr1->mxFrame<pHdr2->mxFrame ) return -1;
- if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1;
- return 0;
-}
-#endif /* SQLITE_ENABLE_SNAPSHOT */
-
-#ifdef SQLITE_ENABLE_ZIPVFS
-/*
-** If the argument is not NULL, it points to a Wal object that holds a
-** read-lock. This function returns the database page-size if it is known,
-** or zero if it is not (or if pWal is NULL).
-*/
-int sqlite3WalFramesize(Wal *pWal){
- assert( pWal==0 || pWal->readLock>=0 );
- return (pWal ? pWal->szPage : 0);
-}
-#endif
-
-/* Return the sqlite3_file object for the WAL file
-*/
-sqlite3_file *sqlite3WalFile(Wal *pWal){
- return pWal->pWalFd;
-}
-
-#endif /* #ifndef SQLITE_OMIT_WAL */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/wal.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/wal.h
deleted file mode 100644
index d97300a6847..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/wal.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-** 2010 February 1
-**
-** 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 header file defines the interface to the write-ahead logging
-** system. Refer to the comments below and the header comment attached to
-** the implementation of each function in log.c for further details.
-*/
-
-#ifndef SQLITE_WAL_H
-#define SQLITE_WAL_H
-
-#include "sqliteInt.h"
-
-/* Macros for extracting appropriate sync flags for either transaction
-** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)):
-*/
-#define WAL_SYNC_FLAGS(X) ((X)&0x03)
-#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03)
-
-#ifdef SQLITE_OMIT_WAL
-# define sqlite3WalOpen(x,y,z) 0
-# define sqlite3WalLimit(x,y)
-# define sqlite3WalClose(v,w,x,y,z) 0
-# define sqlite3WalBeginReadTransaction(y,z) 0
-# define sqlite3WalEndReadTransaction(z)
-# define sqlite3WalDbsize(y) 0
-# define sqlite3WalBeginWriteTransaction(y) 0
-# define sqlite3WalEndWriteTransaction(x) 0
-# define sqlite3WalUndo(x,y,z) 0
-# define sqlite3WalSavepoint(y,z)
-# define sqlite3WalSavepointUndo(y,z) 0
-# define sqlite3WalFrames(u,v,w,x,y,z) 0
-# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0
-# define sqlite3WalCallback(z) 0
-# define sqlite3WalExclusiveMode(y,z) 0
-# define sqlite3WalHeapMemory(z) 0
-# define sqlite3WalFramesize(z) 0
-# define sqlite3WalFindFrame(x,y,z) 0
-# define sqlite3WalFile(x) 0
-#else
-
-#define WAL_SAVEPOINT_NDATA 4
-
-/* Connection to a write-ahead log (WAL) file.
-** There is one object of this type for each pager.
-*/
-typedef struct Wal Wal;
-
-/* Open and close a connection to a write-ahead log. */
-int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
-int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *);
-
-/* Set the limiting size of a WAL file. */
-void sqlite3WalLimit(Wal*, i64);
-
-/* Used by readers to open (lock) and close (unlock) a snapshot. A
-** snapshot is like a read-transaction. It is the state of the database
-** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
-** preserves the current state even if the other threads or processes
-** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
-** transaction and releases the lock.
-*/
-int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
-void sqlite3WalEndReadTransaction(Wal *pWal);
-
-/* Read a page from the write-ahead log, if it is present. */
-int sqlite3WalFindFrame(Wal *, Pgno, u32 *);
-int sqlite3WalReadFrame(Wal *, u32, int, u8 *);
-
-/* If the WAL is not empty, return the size of the database. */
-Pgno sqlite3WalDbsize(Wal *pWal);
-
-/* Obtain or release the WRITER lock. */
-int sqlite3WalBeginWriteTransaction(Wal *pWal);
-int sqlite3WalEndWriteTransaction(Wal *pWal);
-
-/* Undo any frames written (but not committed) to the log */
-int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
-
-/* Return an integer that records the current (uncommitted) write
-** position in the WAL */
-void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData);
-
-/* Move the write position of the WAL back to iFrame. Called in
-** response to a ROLLBACK TO command. */
-int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
-
-/* Write a frame or frames to the log. */
-int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
-
-/* Copy pages from the log to the database file */
-int sqlite3WalCheckpoint(
- Wal *pWal, /* Write-ahead log connection */
- sqlite3 *db, /* Check this handle's interrupt flag */
- int eMode, /* One of PASSIVE, FULL and RESTART */
- int (*xBusy)(void*), /* Function to call when busy */
- void *pBusyArg, /* Context argument for xBusyHandler */
- int sync_flags, /* Flags to sync db file with (or 0) */
- int nBuf, /* Size of buffer nBuf */
- u8 *zBuf, /* Temporary buffer to use */
- int *pnLog, /* OUT: Number of frames in WAL */
- int *pnCkpt /* OUT: Number of backfilled frames in WAL */
-);
-
-/* Return the value to pass to a sqlite3_wal_hook callback, the
-** number of frames in the WAL at the point of the last commit since
-** sqlite3WalCallback() was called. If no commits have occurred since
-** the last call, then return 0.
-*/
-int sqlite3WalCallback(Wal *pWal);
-
-/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released)
-** by the pager layer on the database file.
-*/
-int sqlite3WalExclusiveMode(Wal *pWal, int op);
-
-/* Return true if the argument is non-NULL and the WAL module is using
-** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
-** WAL module is using shared-memory, return false.
-*/
-int sqlite3WalHeapMemory(Wal *pWal);
-
-#ifdef SQLITE_ENABLE_SNAPSHOT
-int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot);
-void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot);
-int sqlite3WalSnapshotRecover(Wal *pWal);
-#endif
-
-#ifdef SQLITE_ENABLE_ZIPVFS
-/* If the WAL file is not empty, return the number of bytes of content
-** stored in each frame (i.e. the db page-size when the WAL was created).
-*/
-int sqlite3WalFramesize(Wal *pWal);
-#endif
-
-/* Return the sqlite3_file object for the WAL file */
-sqlite3_file *sqlite3WalFile(Wal *pWal);
-
-#endif /* ifndef SQLITE_OMIT_WAL */
-#endif /* SQLITE_WAL_H */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/walker.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/walker.c
deleted file mode 100644
index 60bf8226fef..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/walker.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-** 2008 August 16
-**
-** 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 contains routines used for walking the parser tree for
-** an SQL statement.
-*/
-#include "sqliteInt.h"
-#include <stdlib.h>
-#include <string.h>
-
-
-/*
-** Walk an expression tree. Invoke the callback once for each node
-** of the expression, while descending. (In other words, the callback
-** is invoked before visiting children.)
-**
-** The return value from the callback should be one of the WRC_*
-** constants to specify how to proceed with the walk.
-**
-** WRC_Continue Continue descending down the tree.
-**
-** WRC_Prune Do not descend into child nodes, but allow
-** the walk to continue with sibling nodes.
-**
-** WRC_Abort Do no more callbacks. Unwind the stack and
-** return from the top-level walk call.
-**
-** The return value from this routine is WRC_Abort to abandon the tree walk
-** and WRC_Continue to continue.
-*/
-static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
- int rc;
- testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
- testcase( ExprHasProperty(pExpr, EP_Reduced) );
- while(1){
- rc = pWalker->xExprCallback(pWalker, pExpr);
- if( rc ) return rc & WRC_Abort;
- if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
- if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
- assert( pExpr->x.pList==0 || pExpr->pRight==0 );
- if( pExpr->pRight ){
- pExpr = pExpr->pRight;
- continue;
- }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
- }else if( pExpr->x.pList ){
- if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
- }
- }
- break;
- }
- return WRC_Continue;
-}
-int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
- return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue;
-}
-
-/*
-** Call sqlite3WalkExpr() for every expression in list p or until
-** an abort request is seen.
-*/
-int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
- int i;
- struct ExprList_item *pItem;
- if( p ){
- for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
- if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
- }
- }
- return WRC_Continue;
-}
-
-/*
-** Walk all expressions associated with SELECT statement p. Do
-** not invoke the SELECT callback on p, but do (of course) invoke
-** any expr callbacks and SELECT callbacks that come from subqueries.
-** Return WRC_Abort or WRC_Continue.
-*/
-int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
- if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
- if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
- if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
- return WRC_Continue;
-}
-
-/*
-** Walk the parse trees associated with all subqueries in the
-** FROM clause of SELECT statement p. Do not invoke the select
-** callback on p, but do invoke it on each FROM clause subquery
-** and on any subqueries further down in the tree. Return
-** WRC_Abort or WRC_Continue;
-*/
-int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
- SrcList *pSrc;
- int i;
- struct SrcList_item *pItem;
-
- pSrc = p->pSrc;
- assert( pSrc!=0 );
- for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
- return WRC_Abort;
- }
- if( pItem->fg.isTabFunc
- && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
- ){
- return WRC_Abort;
- }
- }
- return WRC_Continue;
-}
-
-/*
-** Call sqlite3WalkExpr() for every expression in Select statement p.
-** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
-** on the compound select chain, p->pPrior.
-**
-** If it is not NULL, the xSelectCallback() callback is invoked before
-** the walk of the expressions and FROM clause. The xSelectCallback2()
-** method is invoked following the walk of the expressions and FROM clause,
-** but only if both xSelectCallback and xSelectCallback2 are both non-NULL
-** and if the expressions and FROM clause both return WRC_Continue;
-**
-** Return WRC_Continue under normal conditions. Return WRC_Abort if
-** there is an abort request.
-**
-** If the Walker does not have an xSelectCallback() then this routine
-** is a no-op returning WRC_Continue.
-*/
-int sqlite3WalkSelect(Walker *pWalker, Select *p){
- int rc;
- if( p==0 ) return WRC_Continue;
- if( pWalker->xSelectCallback==0 ) return WRC_Continue;
- do{
- rc = pWalker->xSelectCallback(pWalker, p);
- if( rc ) return rc & WRC_Abort;
- if( sqlite3WalkSelectExpr(pWalker, p)
- || sqlite3WalkSelectFrom(pWalker, p)
- ){
- return WRC_Abort;
- }
- if( pWalker->xSelectCallback2 ){
- pWalker->xSelectCallback2(pWalker, p);
- }
- p = p->pPrior;
- }while( p!=0 );
- return WRC_Continue;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/where.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/where.c
deleted file mode 100644
index b83915e2646..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/where.c
+++ /dev/null
@@ -1,5217 +0,0 @@
-/*
-** 2001 September 15
-**
-** 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 module contains C code that generates VDBE code used to process
-** the WHERE clause of SQL statements. This module is responsible for
-** generating the code that loops through a table looking for applicable
-** rows. Indices are selected and used to speed the search when doing
-** so is applicable. Because this module is responsible for selecting
-** indices, you might also think of this module as the "query optimizer".
-*/
-#include "sqliteInt.h"
-#include "whereInt.h"
-
-/*
-** Extra information appended to the end of sqlite3_index_info but not
-** visible to the xBestIndex function, at least not directly. The
-** sqlite3_vtab_collation() interface knows how to reach it, however.
-**
-** This object is not an API and can be changed from one release to the
-** next. As long as allocateIndexInfo() and sqlite3_vtab_collation()
-** agree on the structure, all will be well.
-*/
-typedef struct HiddenIndexInfo HiddenIndexInfo;
-struct HiddenIndexInfo {
- WhereClause *pWC; /* The Where clause being analyzed */
- Parse *pParse; /* The parsing context */
-};
-
-/* Forward declaration of methods */
-static int whereLoopResize(sqlite3*, WhereLoop*, int);
-
-/* Test variable that can be set to enable WHERE tracing */
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ int sqlite3WhereTrace = 0;
-#endif
-
-
-/*
-** Return the estimated number of output rows from a WHERE clause
-*/
-LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
- return pWInfo->nRowOut;
-}
-
-/*
-** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
-** WHERE clause returns outputs for DISTINCT processing.
-*/
-int sqlite3WhereIsDistinct(WhereInfo *pWInfo){
- return pWInfo->eDistinct;
-}
-
-/*
-** Return TRUE if the WHERE clause returns rows in ORDER BY order.
-** Return FALSE if the output needs to be sorted.
-*/
-int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
- return pWInfo->nOBSat;
-}
-
-/*
-** Return TRUE if the innermost loop of the WHERE clause implementation
-** returns rows in ORDER BY order for complete run of the inner loop.
-**
-** Across multiple iterations of outer loops, the output rows need not be
-** sorted. As long as rows are sorted for just the innermost loop, this
-** routine can return TRUE.
-*/
-int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){
- return pWInfo->bOrderedInnerLoop;
-}
-
-/*
-** Return the VDBE address or label to jump to in order to continue
-** immediately with the next row of a WHERE clause.
-*/
-int sqlite3WhereContinueLabel(WhereInfo *pWInfo){
- assert( pWInfo->iContinue!=0 );
- return pWInfo->iContinue;
-}
-
-/*
-** Return the VDBE address or label to jump to in order to break
-** out of a WHERE loop.
-*/
-int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
- return pWInfo->iBreak;
-}
-
-/*
-** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to
-** operate directly on the rowis returned by a WHERE clause. Return
-** ONEPASS_SINGLE (1) if the statement can operation directly because only
-** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass
-** optimization can be used on multiple
-**
-** If the ONEPASS optimization is used (if this routine returns true)
-** then also write the indices of open cursors used by ONEPASS
-** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
-** table and iaCur[1] gets the cursor used by an auxiliary index.
-** Either value may be -1, indicating that cursor is not used.
-** Any cursors returned will have been opened for writing.
-**
-** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is
-** unable to use the ONEPASS optimization.
-*/
-int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
- memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2);
-#ifdef WHERETRACE_ENABLED
- if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){
- sqlite3DebugPrintf("%s cursors: %d %d\n",
- pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI",
- aiCur[0], aiCur[1]);
- }
-#endif
- return pWInfo->eOnePass;
-}
-
-/*
-** Move the content of pSrc into pDest
-*/
-static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
- pDest->n = pSrc->n;
- memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
-}
-
-/*
-** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet.
-**
-** The new entry might overwrite an existing entry, or it might be
-** appended, or it might be discarded. Do whatever is the right thing
-** so that pSet keeps the N_OR_COST best entries seen so far.
-*/
-static int whereOrInsert(
- WhereOrSet *pSet, /* The WhereOrSet to be updated */
- Bitmask prereq, /* Prerequisites of the new entry */
- LogEst rRun, /* Run-cost of the new entry */
- LogEst nOut /* Number of outputs for the new entry */
-){
- u16 i;
- WhereOrCost *p;
- for(i=pSet->n, p=pSet->a; i>0; i--, p++){
- if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
- goto whereOrInsert_done;
- }
- if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){
- return 0;
- }
- }
- if( pSet->n<N_OR_COST ){
- p = &pSet->a[pSet->n++];
- p->nOut = nOut;
- }else{
- p = pSet->a;
- for(i=1; i<pSet->n; i++){
- if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i;
- }
- if( p->rRun<=rRun ) return 0;
- }
-whereOrInsert_done:
- p->prereq = prereq;
- p->rRun = rRun;
- if( p->nOut>nOut ) p->nOut = nOut;
- return 1;
-}
-
-/*
-** Return the bitmask for the given cursor number. Return 0 if
-** iCursor is not in the set.
-*/
-Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){
- int i;
- assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
- for(i=0; i<pMaskSet->n; i++){
- if( pMaskSet->ix[i]==iCursor ){
- return MASKBIT(i);
- }
- }
- return 0;
-}
-
-/*
-** Create a new mask for cursor iCursor.
-**
-** There is one cursor per table in the FROM clause. The number of
-** tables in the FROM clause is limited by a test early in the
-** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[]
-** array will never overflow.
-*/
-static void createMask(WhereMaskSet *pMaskSet, int iCursor){
- assert( pMaskSet->n < ArraySize(pMaskSet->ix) );
- pMaskSet->ix[pMaskSet->n++] = iCursor;
-}
-
-/*
-** Advance to the next WhereTerm that matches according to the criteria
-** established when the pScan object was initialized by whereScanInit().
-** Return NULL if there are no more matching WhereTerms.
-*/
-static WhereTerm *whereScanNext(WhereScan *pScan){
- int iCur; /* The cursor on the LHS of the term */
- i16 iColumn; /* The column on the LHS of the term. -1 for IPK */
- Expr *pX; /* An expression being tested */
- WhereClause *pWC; /* Shorthand for pScan->pWC */
- WhereTerm *pTerm; /* The term being tested */
- int k = pScan->k; /* Where to start scanning */
-
- assert( pScan->iEquiv<=pScan->nEquiv );
- pWC = pScan->pWC;
- while(1){
- iColumn = pScan->aiColumn[pScan->iEquiv-1];
- iCur = pScan->aiCur[pScan->iEquiv-1];
- assert( pWC!=0 );
- do{
- for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
- if( pTerm->leftCursor==iCur
- && pTerm->u.leftColumn==iColumn
- && (iColumn!=XN_EXPR
- || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
- pScan->pIdxExpr,iCur)==0)
- && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
- ){
- if( (pTerm->eOperator & WO_EQUIV)!=0
- && pScan->nEquiv<ArraySize(pScan->aiCur)
- && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
- ){
- int j;
- for(j=0; j<pScan->nEquiv; j++){
- if( pScan->aiCur[j]==pX->iTable
- && pScan->aiColumn[j]==pX->iColumn ){
- break;
- }
- }
- if( j==pScan->nEquiv ){
- pScan->aiCur[j] = pX->iTable;
- pScan->aiColumn[j] = pX->iColumn;
- pScan->nEquiv++;
- }
- }
- if( (pTerm->eOperator & pScan->opMask)!=0 ){
- /* Verify the affinity and collating sequence match */
- if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
- CollSeq *pColl;
- Parse *pParse = pWC->pWInfo->pParse;
- pX = pTerm->pExpr;
- if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
- continue;
- }
- assert(pX->pLeft);
- pColl = sqlite3BinaryCompareCollSeq(pParse,
- pX->pLeft, pX->pRight);
- if( pColl==0 ) pColl = pParse->db->pDfltColl;
- if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
- continue;
- }
- }
- if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
- && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
- && pX->iTable==pScan->aiCur[0]
- && pX->iColumn==pScan->aiColumn[0]
- ){
- testcase( pTerm->eOperator & WO_IS );
- continue;
- }
- pScan->pWC = pWC;
- pScan->k = k+1;
- return pTerm;
- }
- }
- }
- pWC = pWC->pOuter;
- k = 0;
- }while( pWC!=0 );
- if( pScan->iEquiv>=pScan->nEquiv ) break;
- pWC = pScan->pOrigWC;
- k = 0;
- pScan->iEquiv++;
- }
- return 0;
-}
-
-/*
-** Initialize a WHERE clause scanner object. Return a pointer to the
-** first match. Return NULL if there are no matches.
-**
-** The scanner will be searching the WHERE clause pWC. It will look
-** for terms of the form "X <op> <expr>" where X is column iColumn of table
-** iCur. Or if pIdx!=0 then X is column iColumn of index pIdx. pIdx
-** must be one of the indexes of table iCur.
-**
-** The <op> must be one of the operators described by opMask.
-**
-** If the search is for X and the WHERE clause contains terms of the
-** form X=Y then this routine might also return terms of the form
-** "Y <op> <expr>". The number of levels of transitivity is limited,
-** but is enough to handle most commonly occurring SQL statements.
-**
-** If X is not the INTEGER PRIMARY KEY then X must be compatible with
-** index pIdx.
-*/
-static WhereTerm *whereScanInit(
- WhereScan *pScan, /* The WhereScan object being initialized */
- WhereClause *pWC, /* The WHERE clause to be scanned */
- int iCur, /* Cursor to scan for */
- int iColumn, /* Column to scan for */
- u32 opMask, /* Operator(s) to scan for */
- Index *pIdx /* Must be compatible with this index */
-){
- pScan->pOrigWC = pWC;
- pScan->pWC = pWC;
- pScan->pIdxExpr = 0;
- pScan->idxaff = 0;
- pScan->zCollName = 0;
- if( pIdx ){
- int j = iColumn;
- iColumn = pIdx->aiColumn[j];
- if( iColumn==XN_EXPR ){
- pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
- pScan->zCollName = pIdx->azColl[j];
- }else if( iColumn==pIdx->pTable->iPKey ){
- iColumn = XN_ROWID;
- }else if( iColumn>=0 ){
- pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
- pScan->zCollName = pIdx->azColl[j];
- }
- }else if( iColumn==XN_EXPR ){
- return 0;
- }
- pScan->opMask = opMask;
- pScan->k = 0;
- pScan->aiCur[0] = iCur;
- pScan->aiColumn[0] = iColumn;
- pScan->nEquiv = 1;
- pScan->iEquiv = 1;
- return whereScanNext(pScan);
-}
-
-/*
-** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
-** where X is a reference to the iColumn of table iCur or of index pIdx
-** if pIdx!=0 and <op> is one of the WO_xx operator codes specified by
-** the op parameter. Return a pointer to the term. Return 0 if not found.
-**
-** If pIdx!=0 then it must be one of the indexes of table iCur.
-** Search for terms matching the iColumn-th column of pIdx
-** rather than the iColumn-th column of table iCur.
-**
-** The term returned might by Y=<expr> if there is another constraint in
-** the WHERE clause that specifies that X=Y. Any such constraints will be
-** identified by the WO_EQUIV bit in the pTerm->eOperator field. The
-** aiCur[]/iaColumn[] arrays hold X and all its equivalents. There are 11
-** slots in aiCur[]/aiColumn[] so that means we can look for X plus up to 10
-** other equivalent values. Hence a search for X will return <expr> if X=A1
-** and A1=A2 and A2=A3 and ... and A9=A10 and A10=<expr>.
-**
-** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
-** then try for the one with no dependencies on <expr> - in other words where
-** <expr> is a constant expression of some kind. Only return entries of
-** the form "X <op> Y" where Y is a column in another table if no terms of
-** the form "X <op> <const-expr>" exist. If no terms with a constant RHS
-** exist, try to return a term that does not use WO_EQUIV.
-*/
-WhereTerm *sqlite3WhereFindTerm(
- WhereClause *pWC, /* The WHERE clause to be searched */
- int iCur, /* Cursor number of LHS */
- int iColumn, /* Column number of LHS */
- Bitmask notReady, /* RHS must not overlap with this mask */
- u32 op, /* Mask of WO_xx values describing operator */
- Index *pIdx /* Must be compatible with this index, if not NULL */
-){
- WhereTerm *pResult = 0;
- WhereTerm *p;
- WhereScan scan;
-
- p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx);
- op &= WO_EQ|WO_IS;
- while( p ){
- if( (p->prereqRight & notReady)==0 ){
- if( p->prereqRight==0 && (p->eOperator&op)!=0 ){
- testcase( p->eOperator & WO_IS );
- return p;
- }
- if( pResult==0 ) pResult = p;
- }
- p = whereScanNext(&scan);
- }
- return pResult;
-}
-
-/*
-** This function searches pList for an entry that matches the iCol-th column
-** of index pIdx.
-**
-** If such an expression is found, its index in pList->a[] is returned. If
-** no expression is found, -1 is returned.
-*/
-static int findIndexCol(
- Parse *pParse, /* Parse context */
- ExprList *pList, /* Expression list to search */
- int iBase, /* Cursor for table associated with pIdx */
- Index *pIdx, /* Index to match column of */
- int iCol /* Column of index to match */
-){
- int i;
- const char *zColl = pIdx->azColl[iCol];
-
- for(i=0; i<pList->nExpr; i++){
- Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
- if( p->op==TK_COLUMN
- && p->iColumn==pIdx->aiColumn[iCol]
- && p->iTable==iBase
- ){
- CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
- if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
- return i;
- }
- }
- }
-
- return -1;
-}
-
-/*
-** Return TRUE if the iCol-th column of index pIdx is NOT NULL
-*/
-static int indexColumnNotNull(Index *pIdx, int iCol){
- int j;
- assert( pIdx!=0 );
- assert( iCol>=0 && iCol<pIdx->nColumn );
- j = pIdx->aiColumn[iCol];
- if( j>=0 ){
- return pIdx->pTable->aCol[j].notNull;
- }else if( j==(-1) ){
- return 1;
- }else{
- assert( j==(-2) );
- return 0; /* Assume an indexed expression can always yield a NULL */
-
- }
-}
-
-/*
-** Return true if the DISTINCT expression-list passed as the third argument
-** is redundant.
-**
-** A DISTINCT list is redundant if any subset of the columns in the
-** DISTINCT list are collectively unique and individually non-null.
-*/
-static int isDistinctRedundant(
- Parse *pParse, /* Parsing context */
- SrcList *pTabList, /* The FROM clause */
- WhereClause *pWC, /* The WHERE clause */
- ExprList *pDistinct /* The result set that needs to be DISTINCT */
-){
- Table *pTab;
- Index *pIdx;
- int i;
- int iBase;
-
- /* If there is more than one table or sub-select in the FROM clause of
- ** this query, then it will not be possible to show that the DISTINCT
- ** clause is redundant. */
- if( pTabList->nSrc!=1 ) return 0;
- iBase = pTabList->a[0].iCursor;
- pTab = pTabList->a[0].pTab;
-
- /* If any of the expressions is an IPK column on table iBase, then return
- ** true. Note: The (p->iTable==iBase) part of this test may be false if the
- ** current SELECT is a correlated sub-query.
- */
- for(i=0; i<pDistinct->nExpr; i++){
- Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
- if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
- }
-
- /* Loop through all indices on the table, checking each to see if it makes
- ** the DISTINCT qualifier redundant. It does so if:
- **
- ** 1. The index is itself UNIQUE, and
- **
- ** 2. All of the columns in the index are either part of the pDistinct
- ** list, or else the WHERE clause contains a term of the form "col=X",
- ** where X is a constant value. The collation sequences of the
- ** comparison and select-list expressions must match those of the index.
- **
- ** 3. All of those index columns for which the WHERE clause does not
- ** contain a "col=X" term are subject to a NOT NULL constraint.
- */
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( !IsUniqueIndex(pIdx) ) continue;
- for(i=0; i<pIdx->nKeyCol; i++){
- if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
- if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
- if( indexColumnNotNull(pIdx, i)==0 ) break;
- }
- }
- if( i==pIdx->nKeyCol ){
- /* This index implies that the DISTINCT qualifier is redundant. */
- return 1;
- }
- }
-
- return 0;
-}
-
-
-/*
-** Estimate the logarithm of the input value to base 2.
-*/
-static LogEst estLog(LogEst N){
- return N<=10 ? 0 : sqlite3LogEst(N) - 33;
-}
-
-/*
-** Convert OP_Column opcodes to OP_Copy in previously generated code.
-**
-** This routine runs over generated VDBE code and translates OP_Column
-** opcodes into OP_Copy when the table is being accessed via co-routine
-** instead of via table lookup.
-**
-** If the bIncrRowid parameter is 0, then any OP_Rowid instructions on
-** cursor iTabCur are transformed into OP_Null. Or, if bIncrRowid is non-zero,
-** then each OP_Rowid is transformed into an instruction to increment the
-** value stored in its output register.
-*/
-static void translateColumnToCopy(
- Parse *pParse, /* Parsing context */
- int iStart, /* Translate from this opcode to the end */
- int iTabCur, /* OP_Column/OP_Rowid references to this table */
- int iRegister, /* The first column is in this register */
- int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */
-){
- Vdbe *v = pParse->pVdbe;
- VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
- int iEnd = sqlite3VdbeCurrentAddr(v);
- if( pParse->db->mallocFailed ) return;
- for(; iStart<iEnd; iStart++, pOp++){
- if( pOp->p1!=iTabCur ) continue;
- if( pOp->opcode==OP_Column ){
- pOp->opcode = OP_Copy;
- pOp->p1 = pOp->p2 + iRegister;
- pOp->p2 = pOp->p3;
- pOp->p3 = 0;
- }else if( pOp->opcode==OP_Rowid ){
- if( bIncrRowid ){
- /* Increment the value stored in the P2 operand of the OP_Rowid. */
- pOp->opcode = OP_AddImm;
- pOp->p1 = pOp->p2;
- pOp->p2 = 1;
- }else{
- pOp->opcode = OP_Null;
- pOp->p1 = 0;
- pOp->p3 = 0;
- }
- }
- }
-}
-
-/*
-** Two routines for printing the content of an sqlite3_index_info
-** structure. Used for testing and debugging only. If neither
-** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
-** are no-ops.
-*/
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
-static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
- int i;
- if( !sqlite3WhereTrace ) return;
- for(i=0; i<p->nConstraint; i++){
- sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
- i,
- p->aConstraint[i].iColumn,
- p->aConstraint[i].iTermOffset,
- p->aConstraint[i].op,
- p->aConstraint[i].usable);
- }
- for(i=0; i<p->nOrderBy; i++){
- sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n",
- i,
- p->aOrderBy[i].iColumn,
- p->aOrderBy[i].desc);
- }
-}
-static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
- int i;
- if( !sqlite3WhereTrace ) return;
- for(i=0; i<p->nConstraint; i++){
- sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n",
- i,
- p->aConstraintUsage[i].argvIndex,
- p->aConstraintUsage[i].omit);
- }
- sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum);
- sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr);
- sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed);
- sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost);
- sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
-}
-#else
-#define TRACE_IDX_INPUTS(A)
-#define TRACE_IDX_OUTPUTS(A)
-#endif
-
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-/*
-** Return TRUE if the WHERE clause term pTerm is of a form where it
-** could be used with an index to access pSrc, assuming an appropriate
-** index existed.
-*/
-static int termCanDriveIndex(
- WhereTerm *pTerm, /* WHERE clause term to check */
- struct SrcList_item *pSrc, /* Table we are trying to access */
- Bitmask notReady /* Tables in outer loops of the join */
-){
- char aff;
- if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
- if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
- if( (pSrc->fg.jointype & JT_LEFT)
- && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- && (pTerm->eOperator & WO_IS)
- ){
- /* Cannot use an IS term from the WHERE clause as an index driver for
- ** the RHS of a LEFT JOIN. Such a term can only be used if it is from
- ** the ON clause. */
- return 0;
- }
- if( (pTerm->prereqRight & notReady)!=0 ) return 0;
- if( pTerm->u.leftColumn<0 ) return 0;
- aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
- if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
- testcase( pTerm->pExpr->op==TK_IS );
- return 1;
-}
-#endif
-
-
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-/*
-** Generate code to construct the Index object for an automatic index
-** and to set up the WhereLevel object pLevel so that the code generator
-** makes use of the automatic index.
-*/
-static void constructAutomaticIndex(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to get the next index */
- Bitmask notReady, /* Mask of cursors that are not available */
- WhereLevel *pLevel /* Write new index here */
-){
- int nKeyCol; /* Number of columns in the constructed index */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
- WhereTerm *pWCEnd; /* End of pWC->a[] */
- Index *pIdx; /* Object describing the transient index */
- Vdbe *v; /* Prepared statement under construction */
- int addrInit; /* Address of the initialization bypass jump */
- Table *pTable; /* The table being indexed */
- int addrTop; /* Top of the index fill loop */
- int regRecord; /* Register holding an index record */
- int n; /* Column counter */
- int i; /* Loop counter */
- int mxBitCol; /* Maximum column in pSrc->colUsed */
- CollSeq *pColl; /* Collating sequence to on a column */
- WhereLoop *pLoop; /* The Loop object */
- char *zNotUsed; /* Extra space on the end of pIdx */
- Bitmask idxCols; /* Bitmap of columns used for indexing */
- Bitmask extraCols; /* Bitmap of additional columns */
- u8 sentWarning = 0; /* True if a warnning has been issued */
- Expr *pPartial = 0; /* Partial Index Expression */
- int iContinue = 0; /* Jump here to skip excluded rows */
- struct SrcList_item *pTabItem; /* FROM clause term being indexed */
- int addrCounter = 0; /* Address where integer counter is initialized */
- int regBase; /* Array of registers where record is assembled */
-
- /* Generate code to skip over the creation and initialization of the
- ** transient index on 2nd and subsequent iterations of the loop. */
- v = pParse->pVdbe;
- assert( v!=0 );
- addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
-
- /* Count the number of columns that will be added to the index
- ** and used to match WHERE clause constraints */
- nKeyCol = 0;
- pTable = pSrc->pTab;
- pWCEnd = &pWC->a[pWC->nTerm];
- pLoop = pLevel->pWLoop;
- idxCols = 0;
- for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
- Expr *pExpr = pTerm->pExpr;
- assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */
- || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */
- || pLoop->prereq!=0 ); /* table of a LEFT JOIN */
- if( pLoop->prereq==0
- && (pTerm->wtFlags & TERM_VIRTUAL)==0
- && !ExprHasProperty(pExpr, EP_FromJoin)
- && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){
- pPartial = sqlite3ExprAnd(pParse->db, pPartial,
- sqlite3ExprDup(pParse->db, pExpr, 0));
- }
- if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.leftColumn;
- Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
- testcase( iCol==BMS );
- testcase( iCol==BMS-1 );
- if( !sentWarning ){
- sqlite3_log(SQLITE_WARNING_AUTOINDEX,
- "automatic index on %s(%s)", pTable->zName,
- pTable->aCol[iCol].zName);
- sentWarning = 1;
- }
- if( (idxCols & cMask)==0 ){
- if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){
- goto end_auto_index_create;
- }
- pLoop->aLTerm[nKeyCol++] = pTerm;
- idxCols |= cMask;
- }
- }
- }
- assert( nKeyCol>0 );
- pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
- pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
- | WHERE_AUTO_INDEX;
-
- /* Count the number of additional columns needed to create a
- ** covering index. A "covering index" is an index that contains all
- ** columns that are needed by the query. With a covering index, the
- ** original table never needs to be accessed. Automatic indices must
- ** be a covering index because the index will not be updated if the
- ** original table changes and the index and table cannot both be used
- ** if they go out of sync.
- */
- extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
- mxBitCol = MIN(BMS-1,pTable->nCol);
- testcase( pTable->nCol==BMS-1 );
- testcase( pTable->nCol==BMS-2 );
- for(i=0; i<mxBitCol; i++){
- if( extraCols & MASKBIT(i) ) nKeyCol++;
- }
- if( pSrc->colUsed & MASKBIT(BMS-1) ){
- nKeyCol += pTable->nCol - BMS + 1;
- }
-
- /* Construct the Index object to describe this index */
- pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed);
- if( pIdx==0 ) goto end_auto_index_create;
- pLoop->u.btree.pIndex = pIdx;
- pIdx->zName = "auto-index";
- pIdx->pTable = pTable;
- n = 0;
- idxCols = 0;
- for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
- if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.leftColumn;
- Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
- testcase( iCol==BMS-1 );
- testcase( iCol==BMS );
- if( (idxCols & cMask)==0 ){
- Expr *pX = pTerm->pExpr;
- idxCols |= cMask;
- pIdx->aiColumn[n] = pTerm->u.leftColumn;
- pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
- pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
- n++;
- }
- }
- }
- assert( (u32)n==pLoop->u.btree.nEq );
-
- /* Add additional columns needed to make the automatic index into
- ** a covering index */
- for(i=0; i<mxBitCol; i++){
- if( extraCols & MASKBIT(i) ){
- pIdx->aiColumn[n] = i;
- pIdx->azColl[n] = sqlite3StrBINARY;
- n++;
- }
- }
- if( pSrc->colUsed & MASKBIT(BMS-1) ){
- for(i=BMS-1; i<pTable->nCol; i++){
- pIdx->aiColumn[n] = i;
- pIdx->azColl[n] = sqlite3StrBINARY;
- n++;
- }
- }
- assert( n==nKeyCol );
- pIdx->aiColumn[n] = XN_ROWID;
- pIdx->azColl[n] = sqlite3StrBINARY;
-
- /* Create the automatic index */
- assert( pLevel->iIdxCur>=0 );
- pLevel->iIdxCur = pParse->nTab++;
- sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
- sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
- VdbeComment((v, "for %s", pTable->zName));
-
- /* Fill the automatic index with content */
- sqlite3ExprCachePush(pParse);
- pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
- if( pTabItem->fg.viaCoroutine ){
- int regYield = pTabItem->regReturn;
- addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
- addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
- VdbeCoverage(v);
- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
- }else{
- addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
- }
- if( pPartial ){
- iContinue = sqlite3VdbeMakeLabel(v);
- sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL);
- pLoop->wsFlags |= WHERE_PARTIALIDX;
- }
- regRecord = sqlite3GetTempReg(pParse);
- regBase = sqlite3GenerateIndexKey(
- pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
- );
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
- if( pTabItem->fg.viaCoroutine ){
- sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
- testcase( pParse->db->mallocFailed );
- translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
- pTabItem->regResult, 1);
- sqlite3VdbeGoto(v, addrTop);
- pTabItem->fg.viaCoroutine = 0;
- }else{
- sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
- }
- sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
- sqlite3VdbeJumpHere(v, addrTop);
- sqlite3ReleaseTempReg(pParse, regRecord);
- sqlite3ExprCachePop(pParse);
-
- /* Jump here when skipping the initialization */
- sqlite3VdbeJumpHere(v, addrInit);
-
-end_auto_index_create:
- sqlite3ExprDelete(pParse->db, pPartial);
-}
-#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*
-** Allocate and populate an sqlite3_index_info structure. It is the
-** responsibility of the caller to eventually release the structure
-** by passing the pointer returned by this function to sqlite3_free().
-*/
-static sqlite3_index_info *allocateIndexInfo(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause being analyzed */
- Bitmask mUnusable, /* Ignore terms with these prereqs */
- struct SrcList_item *pSrc, /* The FROM clause term that is the vtab */
- ExprList *pOrderBy, /* The ORDER BY clause */
- u16 *pmNoOmit /* Mask of terms not to omit */
-){
- int i, j;
- int nTerm;
- struct sqlite3_index_constraint *pIdxCons;
- struct sqlite3_index_orderby *pIdxOrderBy;
- struct sqlite3_index_constraint_usage *pUsage;
- struct HiddenIndexInfo *pHidden;
- WhereTerm *pTerm;
- int nOrderBy;
- sqlite3_index_info *pIdxInfo;
- u16 mNoOmit = 0;
-
- /* Count the number of possible WHERE clause constraints referring
- ** to this virtual table */
- for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( pTerm->prereqRight & mUnusable ) continue;
- assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
- testcase( pTerm->eOperator & WO_IN );
- testcase( pTerm->eOperator & WO_ISNULL );
- testcase( pTerm->eOperator & WO_IS );
- testcase( pTerm->eOperator & WO_ALL );
- if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
- if( pTerm->wtFlags & TERM_VNULL ) continue;
- assert( pTerm->u.leftColumn>=(-1) );
- nTerm++;
- }
-
- /* If the ORDER BY clause contains only columns in the current
- ** virtual table then allocate space for the aOrderBy part of
- ** the sqlite3_index_info structure.
- */
- nOrderBy = 0;
- if( pOrderBy ){
- int n = pOrderBy->nExpr;
- for(i=0; i<n; i++){
- Expr *pExpr = pOrderBy->a[i].pExpr;
- if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
- }
- if( i==n){
- nOrderBy = n;
- }
- }
-
- /* Allocate the sqlite3_index_info structure
- */
- pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
- + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
- + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) );
- if( pIdxInfo==0 ){
- sqlite3ErrorMsg(pParse, "out of memory");
- return 0;
- }
-
- /* Initialize the structure. The sqlite3_index_info structure contains
- ** many fields that are declared "const" to prevent xBestIndex from
- ** changing them. We have to do some funky casting in order to
- ** initialize those fields.
- */
- pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
- pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1];
- pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
- pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
- *(int*)&pIdxInfo->nConstraint = nTerm;
- *(int*)&pIdxInfo->nOrderBy = nOrderBy;
- *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
- *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
- *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
- pUsage;
-
- pHidden->pWC = pWC;
- pHidden->pParse = pParse;
- for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- u16 op;
- if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( pTerm->prereqRight & mUnusable ) continue;
- assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
- testcase( pTerm->eOperator & WO_IN );
- testcase( pTerm->eOperator & WO_IS );
- testcase( pTerm->eOperator & WO_ISNULL );
- testcase( pTerm->eOperator & WO_ALL );
- if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
- if( pTerm->wtFlags & TERM_VNULL ) continue;
- assert( pTerm->u.leftColumn>=(-1) );
- pIdxCons[j].iColumn = pTerm->u.leftColumn;
- pIdxCons[j].iTermOffset = i;
- op = pTerm->eOperator & WO_ALL;
- if( op==WO_IN ) op = WO_EQ;
- if( op==WO_AUX ){
- pIdxCons[j].op = pTerm->eMatchOp;
- }else if( op & (WO_ISNULL|WO_IS) ){
- if( op==WO_ISNULL ){
- pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
- }else{
- pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
- }
- }else{
- pIdxCons[j].op = (u8)op;
- /* The direct assignment in the previous line is possible only because
- ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
- ** following asserts verify this fact. */
- assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
- assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
- assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
- assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
- assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
- assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
-
- if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
- && sqlite3ExprIsVector(pTerm->pExpr->pRight)
- ){
- if( i<16 ) mNoOmit |= (1 << i);
- if( op==WO_LT ) pIdxCons[j].op = WO_LE;
- if( op==WO_GT ) pIdxCons[j].op = WO_GE;
- }
- }
-
- j++;
- }
- for(i=0; i<nOrderBy; i++){
- Expr *pExpr = pOrderBy->a[i].pExpr;
- pIdxOrderBy[i].iColumn = pExpr->iColumn;
- pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
- }
-
- *pmNoOmit = mNoOmit;
- return pIdxInfo;
-}
-
-/*
-** The table object reference passed as the second argument to this function
-** must represent a virtual table. This function invokes the xBestIndex()
-** method of the virtual table with the sqlite3_index_info object that
-** comes in as the 3rd argument to this function.
-**
-** If an error occurs, pParse is populated with an error message and a
-** non-zero value is returned. Otherwise, 0 is returned and the output
-** part of the sqlite3_index_info structure is left populated.
-**
-** Whether or not an error is returned, it is the responsibility of the
-** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
-** that this is required.
-*/
-static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
- sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
- int rc;
-
- TRACE_IDX_INPUTS(p);
- rc = pVtab->pModule->xBestIndex(pVtab, p);
- TRACE_IDX_OUTPUTS(p);
-
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ){
- sqlite3OomFault(pParse->db);
- }else if( !pVtab->zErrMsg ){
- sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
- }else{
- sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
- }
- }
- sqlite3_free(pVtab->zErrMsg);
- pVtab->zErrMsg = 0;
-
-#if 0
- /* This error is now caught by the caller.
- ** Search for "xBestIndex malfunction" below */
- for(i=0; i<p->nConstraint; i++){
- if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
- sqlite3ErrorMsg(pParse,
- "table %s: xBestIndex returned an invalid plan", pTab->zName);
- }
- }
-#endif
-
- return pParse->nErr;
-}
-#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** Estimate the location of a particular key among all keys in an
-** index. Store the results in aStat as follows:
-**
-** aStat[0] Est. number of rows less than pRec
-** aStat[1] Est. number of rows equal to pRec
-**
-** Return the index of the sample that is the smallest sample that
-** is greater than or equal to pRec. Note that this index is not an index
-** into the aSample[] array - it is an index into a virtual set of samples
-** based on the contents of aSample[] and the number of fields in record
-** pRec.
-*/
-static int whereKeyStats(
- Parse *pParse, /* Database connection */
- Index *pIdx, /* Index to consider domain of */
- UnpackedRecord *pRec, /* Vector of values to consider */
- int roundUp, /* Round up if true. Round down if false */
- tRowcnt *aStat /* OUT: stats written here */
-){
- IndexSample *aSample = pIdx->aSample;
- int iCol; /* Index of required stats in anEq[] etc. */
- int i; /* Index of first sample >= pRec */
- int iSample; /* Smallest sample larger than or equal to pRec */
- int iMin = 0; /* Smallest sample not yet tested */
- int iTest; /* Next sample to test */
- int res; /* Result of comparison operation */
- int nField; /* Number of fields in pRec */
- tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */
-
-#ifndef SQLITE_DEBUG
- UNUSED_PARAMETER( pParse );
-#endif
- assert( pRec!=0 );
- assert( pIdx->nSample>0 );
- assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol );
-
- /* Do a binary search to find the first sample greater than or equal
- ** to pRec. If pRec contains a single field, the set of samples to search
- ** is simply the aSample[] array. If the samples in aSample[] contain more
- ** than one fields, all fields following the first are ignored.
- **
- ** If pRec contains N fields, where N is more than one, then as well as the
- ** samples in aSample[] (truncated to N fields), the search also has to
- ** consider prefixes of those samples. For example, if the set of samples
- ** in aSample is:
- **
- ** aSample[0] = (a, 5)
- ** aSample[1] = (a, 10)
- ** aSample[2] = (b, 5)
- ** aSample[3] = (c, 100)
- ** aSample[4] = (c, 105)
- **
- ** Then the search space should ideally be the samples above and the
- ** unique prefixes [a], [b] and [c]. But since that is hard to organize,
- ** the code actually searches this set:
- **
- ** 0: (a)
- ** 1: (a, 5)
- ** 2: (a, 10)
- ** 3: (a, 10)
- ** 4: (b)
- ** 5: (b, 5)
- ** 6: (c)
- ** 7: (c, 100)
- ** 8: (c, 105)
- ** 9: (c, 105)
- **
- ** For each sample in the aSample[] array, N samples are present in the
- ** effective sample array. In the above, samples 0 and 1 are based on
- ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc.
- **
- ** Often, sample i of each block of N effective samples has (i+1) fields.
- ** Except, each sample may be extended to ensure that it is greater than or
- ** equal to the previous sample in the array. For example, in the above,
- ** sample 2 is the first sample of a block of N samples, so at first it
- ** appears that it should be 1 field in size. However, that would make it
- ** smaller than sample 1, so the binary search would not work. As a result,
- ** it is extended to two fields. The duplicates that this creates do not
- ** cause any problems.
- */
- nField = pRec->nField;
- iCol = 0;
- iSample = pIdx->nSample * nField;
- do{
- int iSamp; /* Index in aSample[] of test sample */
- int n; /* Number of fields in test sample */
-
- iTest = (iMin+iSample)/2;
- iSamp = iTest / nField;
- if( iSamp>0 ){
- /* The proposed effective sample is a prefix of sample aSample[iSamp].
- ** Specifically, the shortest prefix of at least (1 + iTest%nField)
- ** fields that is greater than the previous effective sample. */
- for(n=(iTest % nField) + 1; n<nField; n++){
- if( aSample[iSamp-1].anLt[n-1]!=aSample[iSamp].anLt[n-1] ) break;
- }
- }else{
- n = iTest + 1;
- }
-
- pRec->nField = n;
- res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec);
- if( res<0 ){
- iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1];
- iMin = iTest+1;
- }else if( res==0 && n<nField ){
- iLower = aSample[iSamp].anLt[n-1];
- iMin = iTest+1;
- res = -1;
- }else{
- iSample = iTest;
- iCol = n-1;
- }
- }while( res && iMin<iSample );
- i = iSample / nField;
-
-#ifdef SQLITE_DEBUG
- /* The following assert statements check that the binary search code
- ** above found the right answer. This block serves no purpose other
- ** than to invoke the asserts. */
- if( pParse->db->mallocFailed==0 ){
- if( res==0 ){
- /* If (res==0) is true, then pRec must be equal to sample i. */
- assert( i<pIdx->nSample );
- assert( iCol==nField-1 );
- pRec->nField = nField;
- assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
- || pParse->db->mallocFailed
- );
- }else{
- /* Unless i==pIdx->nSample, indicating that pRec is larger than
- ** all samples in the aSample[] array, pRec must be smaller than the
- ** (iCol+1) field prefix of sample i. */
- assert( i<=pIdx->nSample && i>=0 );
- pRec->nField = iCol+1;
- assert( i==pIdx->nSample
- || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
- || pParse->db->mallocFailed );
-
- /* if i==0 and iCol==0, then record pRec is smaller than all samples
- ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must
- ** be greater than or equal to the (iCol) field prefix of sample i.
- ** If (i>0), then pRec must also be greater than sample (i-1). */
- if( iCol>0 ){
- pRec->nField = iCol;
- assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0
- || pParse->db->mallocFailed );
- }
- if( i>0 ){
- pRec->nField = nField;
- assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
- || pParse->db->mallocFailed );
- }
- }
- }
-#endif /* ifdef SQLITE_DEBUG */
-
- if( res==0 ){
- /* Record pRec is equal to sample i */
- assert( iCol==nField-1 );
- aStat[0] = aSample[i].anLt[iCol];
- aStat[1] = aSample[i].anEq[iCol];
- }else{
- /* At this point, the (iCol+1) field prefix of aSample[i] is the first
- ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec
- ** is larger than all samples in the array. */
- tRowcnt iUpper, iGap;
- if( i>=pIdx->nSample ){
- iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
- }else{
- iUpper = aSample[i].anLt[iCol];
- }
-
- if( iLower>=iUpper ){
- iGap = 0;
- }else{
- iGap = iUpper - iLower;
- }
- if( roundUp ){
- iGap = (iGap*2)/3;
- }else{
- iGap = iGap/3;
- }
- aStat[0] = iLower + iGap;
- aStat[1] = pIdx->aAvgEq[nField-1];
- }
-
- /* Restore the pRec->nField value before returning. */
- pRec->nField = nField;
- return i;
-}
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-
-/*
-** If it is not NULL, pTerm is a term that provides an upper or lower
-** bound on a range scan. Without considering pTerm, it is estimated
-** that the scan will visit nNew rows. This function returns the number
-** estimated to be visited after taking pTerm into account.
-**
-** If the user explicitly specified a likelihood() value for this term,
-** then the return value is the likelihood multiplied by the number of
-** input rows. Otherwise, this function assumes that an "IS NOT NULL" term
-** has a likelihood of 0.50, and any other term a likelihood of 0.25.
-*/
-static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){
- LogEst nRet = nNew;
- if( pTerm ){
- if( pTerm->truthProb<=0 ){
- nRet += pTerm->truthProb;
- }else if( (pTerm->wtFlags & TERM_VNULL)==0 ){
- nRet -= 20; assert( 20==sqlite3LogEst(4) );
- }
- }
- return nRet;
-}
-
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** Return the affinity for a single column of an index.
-*/
-char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
- assert( iCol>=0 && iCol<pIdx->nColumn );
- if( !pIdx->zColAff ){
- if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
- }
- return pIdx->zColAff[iCol];
-}
-#endif
-
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** This function is called to estimate the number of rows visited by a
-** range-scan on a skip-scan index. For example:
-**
-** CREATE INDEX i1 ON t1(a, b, c);
-** SELECT * FROM t1 WHERE a=? AND c BETWEEN ? AND ?;
-**
-** Value pLoop->nOut is currently set to the estimated number of rows
-** visited for scanning (a=? AND b=?). This function reduces that estimate
-** by some factor to account for the (c BETWEEN ? AND ?) expression based
-** on the stat4 data for the index. this scan will be peformed multiple
-** times (once for each (a,b) combination that matches a=?) is dealt with
-** by the caller.
-**
-** It does this by scanning through all stat4 samples, comparing values
-** extracted from pLower and pUpper with the corresponding column in each
-** sample. If L and U are the number of samples found to be less than or
-** equal to the values extracted from pLower and pUpper respectively, and
-** N is the total number of samples, the pLoop->nOut value is adjusted
-** as follows:
-**
-** nOut = nOut * ( min(U - L, 1) / N )
-**
-** If pLower is NULL, or a value cannot be extracted from the term, L is
-** set to zero. If pUpper is NULL, or a value cannot be extracted from it,
-** U is set to N.
-**
-** Normally, this function sets *pbDone to 1 before returning. However,
-** if no value can be extracted from either pLower or pUpper (and so the
-** estimate of the number of rows delivered remains unchanged), *pbDone
-** is left as is.
-**
-** If an error occurs, an SQLite error code is returned. Otherwise,
-** SQLITE_OK.
-*/
-static int whereRangeSkipScanEst(
- Parse *pParse, /* Parsing & code generating context */
- WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
- WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
- WhereLoop *pLoop, /* Update the .nOut value of this loop */
- int *pbDone /* Set to true if at least one expr. value extracted */
-){
- Index *p = pLoop->u.btree.pIndex;
- int nEq = pLoop->u.btree.nEq;
- sqlite3 *db = pParse->db;
- int nLower = -1;
- int nUpper = p->nSample+1;
- int rc = SQLITE_OK;
- u8 aff = sqlite3IndexColumnAffinity(db, p, nEq);
- CollSeq *pColl;
-
- sqlite3_value *p1 = 0; /* Value extracted from pLower */
- sqlite3_value *p2 = 0; /* Value extracted from pUpper */
- sqlite3_value *pVal = 0; /* Value extracted from record */
-
- pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]);
- if( pLower ){
- rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1);
- nLower = 0;
- }
- if( pUpper && rc==SQLITE_OK ){
- rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2);
- nUpper = p2 ? 0 : p->nSample;
- }
-
- if( p1 || p2 ){
- int i;
- int nDiff;
- for(i=0; rc==SQLITE_OK && i<p->nSample; i++){
- rc = sqlite3Stat4Column(db, p->aSample[i].p, p->aSample[i].n, nEq, &pVal);
- if( rc==SQLITE_OK && p1 ){
- int res = sqlite3MemCompare(p1, pVal, pColl);
- if( res>=0 ) nLower++;
- }
- if( rc==SQLITE_OK && p2 ){
- int res = sqlite3MemCompare(p2, pVal, pColl);
- if( res>=0 ) nUpper++;
- }
- }
- nDiff = (nUpper - nLower);
- if( nDiff<=0 ) nDiff = 1;
-
- /* If there is both an upper and lower bound specified, and the
- ** comparisons indicate that they are close together, use the fallback
- ** method (assume that the scan visits 1/64 of the rows) for estimating
- ** the number of rows visited. Otherwise, estimate the number of rows
- ** using the method described in the header comment for this function. */
- if( nDiff!=1 || pUpper==0 || pLower==0 ){
- int nAdjust = (sqlite3LogEst(p->nSample) - sqlite3LogEst(nDiff));
- pLoop->nOut -= nAdjust;
- *pbDone = 1;
- WHERETRACE(0x10, ("range skip-scan regions: %u..%u adjust=%d est=%d\n",
- nLower, nUpper, nAdjust*-1, pLoop->nOut));
- }
-
- }else{
- assert( *pbDone==0 );
- }
-
- sqlite3ValueFree(p1);
- sqlite3ValueFree(p2);
- sqlite3ValueFree(pVal);
-
- return rc;
-}
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-
-/*
-** This function is used to estimate the number of rows that will be visited
-** by scanning an index for a range of values. The range may have an upper
-** bound, a lower bound, or both. The WHERE clause terms that set the upper
-** and lower bounds are represented by pLower and pUpper respectively. For
-** example, assuming that index p is on t1(a):
-**
-** ... FROM t1 WHERE a > ? AND a < ? ...
-** |_____| |_____|
-** | |
-** pLower pUpper
-**
-** If either of the upper or lower bound is not present, then NULL is passed in
-** place of the corresponding WhereTerm.
-**
-** The value in (pBuilder->pNew->u.btree.nEq) is the number of the index
-** column subject to the range constraint. Or, equivalently, the number of
-** equality constraints optimized by the proposed index scan. For example,
-** assuming index p is on t1(a, b), and the SQL query is:
-**
-** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ...
-**
-** then nEq is set to 1 (as the range restricted column, b, is the second
-** left-most column of the index). Or, if the query is:
-**
-** ... FROM t1 WHERE a > ? AND a < ? ...
-**
-** then nEq is set to 0.
-**
-** When this function is called, *pnOut is set to the sqlite3LogEst() of the
-** number of rows that the index scan is expected to visit without
-** considering the range constraints. If nEq is 0, then *pnOut is the number of
-** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
-** to account for the range constraints pLower and pUpper.
-**
-** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be
-** used, a single range inequality reduces the search space by a factor of 4.
-** and a pair of constraints (x>? AND x<?) reduces the expected number of
-** rows visited by a factor of 64.
-*/
-static int whereRangeScanEst(
- Parse *pParse, /* Parsing & code generating context */
- WhereLoopBuilder *pBuilder,
- WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
- WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
- WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */
-){
- int rc = SQLITE_OK;
- int nOut = pLoop->nOut;
- LogEst nNew;
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- Index *p = pLoop->u.btree.pIndex;
- int nEq = pLoop->u.btree.nEq;
-
- if( p->nSample>0 && nEq<p->nSampleCol ){
- if( nEq==pBuilder->nRecValid ){
- UnpackedRecord *pRec = pBuilder->pRec;
- tRowcnt a[2];
- int nBtm = pLoop->u.btree.nBtm;
- int nTop = pLoop->u.btree.nTop;
-
- /* Variable iLower will be set to the estimate of the number of rows in
- ** the index that are less than the lower bound of the range query. The
- ** lower bound being the concatenation of $P and $L, where $P is the
- ** key-prefix formed by the nEq values matched against the nEq left-most
- ** columns of the index, and $L is the value in pLower.
- **
- ** Or, if pLower is NULL or $L cannot be extracted from it (because it
- ** is not a simple variable or literal value), the lower bound of the
- ** range is $P. Due to a quirk in the way whereKeyStats() works, even
- ** if $L is available, whereKeyStats() is called for both ($P) and
- ** ($P:$L) and the larger of the two returned values is used.
- **
- ** Similarly, iUpper is to be set to the estimate of the number of rows
- ** less than the upper bound of the range query. Where the upper bound
- ** is either ($P) or ($P:$U). Again, even if $U is available, both values
- ** of iUpper are requested of whereKeyStats() and the smaller used.
- **
- ** The number of rows between the two bounds is then just iUpper-iLower.
- */
- tRowcnt iLower; /* Rows less than the lower bound */
- tRowcnt iUpper; /* Rows less than the upper bound */
- int iLwrIdx = -2; /* aSample[] for the lower bound */
- int iUprIdx = -1; /* aSample[] for the upper bound */
-
- if( pRec ){
- testcase( pRec->nField!=pBuilder->nRecValid );
- pRec->nField = pBuilder->nRecValid;
- }
- /* Determine iLower and iUpper using ($P) only. */
- if( nEq==0 ){
- iLower = 0;
- iUpper = p->nRowEst0;
- }else{
- /* Note: this call could be optimized away - since the same values must
- ** have been requested when testing key $P in whereEqualScanEst(). */
- whereKeyStats(pParse, p, pRec, 0, a);
- iLower = a[0];
- iUpper = a[0] + a[1];
- }
-
- assert( pLower==0 || (pLower->eOperator & (WO_GT|WO_GE))!=0 );
- assert( pUpper==0 || (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
- assert( p->aSortOrder!=0 );
- if( p->aSortOrder[nEq] ){
- /* The roles of pLower and pUpper are swapped for a DESC index */
- SWAP(WhereTerm*, pLower, pUpper);
- SWAP(int, nBtm, nTop);
- }
-
- /* If possible, improve on the iLower estimate using ($P:$L). */
- if( pLower ){
- int n; /* Values extracted from pExpr */
- Expr *pExpr = pLower->pExpr->pRight;
- rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n);
- if( rc==SQLITE_OK && n ){
- tRowcnt iNew;
- u16 mask = WO_GT|WO_LE;
- if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT);
- iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a);
- iNew = a[0] + ((pLower->eOperator & mask) ? a[1] : 0);
- if( iNew>iLower ) iLower = iNew;
- nOut--;
- pLower = 0;
- }
- }
-
- /* If possible, improve on the iUpper estimate using ($P:$U). */
- if( pUpper ){
- int n; /* Values extracted from pExpr */
- Expr *pExpr = pUpper->pExpr->pRight;
- rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n);
- if( rc==SQLITE_OK && n ){
- tRowcnt iNew;
- u16 mask = WO_GT|WO_LE;
- if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT);
- iUprIdx = whereKeyStats(pParse, p, pRec, 1, a);
- iNew = a[0] + ((pUpper->eOperator & mask) ? a[1] : 0);
- if( iNew<iUpper ) iUpper = iNew;
- nOut--;
- pUpper = 0;
- }
- }
-
- pBuilder->pRec = pRec;
- if( rc==SQLITE_OK ){
- if( iUpper>iLower ){
- nNew = sqlite3LogEst(iUpper - iLower);
- /* TUNING: If both iUpper and iLower are derived from the same
- ** sample, then assume they are 4x more selective. This brings
- ** the estimated selectivity more in line with what it would be
- ** if estimated without the use of STAT3/4 tables. */
- if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) );
- }else{
- nNew = 10; assert( 10==sqlite3LogEst(2) );
- }
- if( nNew<nOut ){
- nOut = nNew;
- }
- WHERETRACE(0x10, ("STAT4 range scan: %u..%u est=%d\n",
- (u32)iLower, (u32)iUpper, nOut));
- }
- }else{
- int bDone = 0;
- rc = whereRangeSkipScanEst(pParse, pLower, pUpper, pLoop, &bDone);
- if( bDone ) return rc;
- }
- }
-#else
- UNUSED_PARAMETER(pParse);
- UNUSED_PARAMETER(pBuilder);
- assert( pLower || pUpper );
-#endif
- assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 );
- nNew = whereRangeAdjust(pLower, nOut);
- nNew = whereRangeAdjust(pUpper, nNew);
-
- /* TUNING: If there is both an upper and lower limit and neither limit
- ** has an application-defined likelihood(), assume the range is
- ** reduced by an additional 75%. This means that, by default, an open-ended
- ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the
- ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to
- ** match 1/64 of the index. */
- if( pLower && pLower->truthProb>0 && pUpper && pUpper->truthProb>0 ){
- nNew -= 20;
- }
-
- nOut -= (pLower!=0) + (pUpper!=0);
- if( nNew<10 ) nNew = 10;
- if( nNew<nOut ) nOut = nNew;
-#if defined(WHERETRACE_ENABLED)
- if( pLoop->nOut>nOut ){
- WHERETRACE(0x10,("Range scan lowers nOut from %d to %d\n",
- pLoop->nOut, nOut));
- }
-#endif
- pLoop->nOut = (LogEst)nOut;
- return rc;
-}
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** Estimate the number of rows that will be returned based on
-** an equality constraint x=VALUE and where that VALUE occurs in
-** the histogram data. This only works when x is the left-most
-** column of an index and sqlite_stat3 histogram data is available
-** for that index. When pExpr==NULL that means the constraint is
-** "x IS NULL" instead of "x=VALUE".
-**
-** Write the estimated row count into *pnRow and return SQLITE_OK.
-** If unable to make an estimate, leave *pnRow unchanged and return
-** non-zero.
-**
-** This routine can fail if it is unable to load a collating sequence
-** required for string comparison, or if unable to allocate memory
-** for a UTF conversion required for comparison. The error is stored
-** in the pParse structure.
-*/
-static int whereEqualScanEst(
- Parse *pParse, /* Parsing & code generating context */
- WhereLoopBuilder *pBuilder,
- Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */
- tRowcnt *pnRow /* Write the revised row estimate here */
-){
- Index *p = pBuilder->pNew->u.btree.pIndex;
- int nEq = pBuilder->pNew->u.btree.nEq;
- UnpackedRecord *pRec = pBuilder->pRec;
- int rc; /* Subfunction return code */
- tRowcnt a[2]; /* Statistics */
- int bOk;
-
- assert( nEq>=1 );
- assert( nEq<=p->nColumn );
- assert( p->aSample!=0 );
- assert( p->nSample>0 );
- assert( pBuilder->nRecValid<nEq );
-
- /* If values are not available for all fields of the index to the left
- ** of this one, no estimate can be made. Return SQLITE_NOTFOUND. */
- if( pBuilder->nRecValid<(nEq-1) ){
- return SQLITE_NOTFOUND;
- }
-
- /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue()
- ** below would return the same value. */
- if( nEq>=p->nColumn ){
- *pnRow = 1;
- return SQLITE_OK;
- }
-
- rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, 1, nEq-1, &bOk);
- pBuilder->pRec = pRec;
- if( rc!=SQLITE_OK ) return rc;
- if( bOk==0 ) return SQLITE_NOTFOUND;
- pBuilder->nRecValid = nEq;
-
- whereKeyStats(pParse, p, pRec, 0, a);
- WHERETRACE(0x10,("equality scan regions %s(%d): %d\n",
- p->zName, nEq-1, (int)a[1]));
- *pnRow = a[1];
-
- return rc;
-}
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** Estimate the number of rows that will be returned based on
-** an IN constraint where the right-hand side of the IN operator
-** is a list of values. Example:
-**
-** WHERE x IN (1,2,3,4)
-**
-** Write the estimated row count into *pnRow and return SQLITE_OK.
-** If unable to make an estimate, leave *pnRow unchanged and return
-** non-zero.
-**
-** This routine can fail if it is unable to load a collating sequence
-** required for string comparison, or if unable to allocate memory
-** for a UTF conversion required for comparison. The error is stored
-** in the pParse structure.
-*/
-static int whereInScanEst(
- Parse *pParse, /* Parsing & code generating context */
- WhereLoopBuilder *pBuilder,
- ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
- tRowcnt *pnRow /* Write the revised row estimate here */
-){
- Index *p = pBuilder->pNew->u.btree.pIndex;
- i64 nRow0 = sqlite3LogEstToInt(p->aiRowLogEst[0]);
- int nRecValid = pBuilder->nRecValid;
- int rc = SQLITE_OK; /* Subfunction return code */
- tRowcnt nEst; /* Number of rows for a single term */
- tRowcnt nRowEst = 0; /* New estimate of the number of rows */
- int i; /* Loop counter */
-
- assert( p->aSample!=0 );
- for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){
- nEst = nRow0;
- rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst);
- nRowEst += nEst;
- pBuilder->nRecValid = nRecValid;
- }
-
- if( rc==SQLITE_OK ){
- if( nRowEst > nRow0 ) nRowEst = nRow0;
- *pnRow = nRowEst;
- WHERETRACE(0x10,("IN row estimate: est=%d\n", nRowEst));
- }
- assert( pBuilder->nRecValid==nRecValid );
- return rc;
-}
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-
-
-#ifdef WHERETRACE_ENABLED
-/*
-** Print the content of a WhereTerm object
-*/
-static void whereTermPrint(WhereTerm *pTerm, int iTerm){
- if( pTerm==0 ){
- sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
- }else{
- char zType[4];
- char zLeft[50];
- memcpy(zType, "...", 4);
- if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
- if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
- if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
- if( pTerm->eOperator & WO_SINGLE ){
- sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
- pTerm->leftCursor, pTerm->u.leftColumn);
- }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
- sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld",
- pTerm->u.pOrInfo->indexable);
- }else{
- sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
- }
- sqlite3DebugPrintf(
- "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x",
- iTerm, pTerm, zType, zLeft, pTerm->truthProb,
- pTerm->eOperator, pTerm->wtFlags);
- if( pTerm->iField ){
- sqlite3DebugPrintf(" iField=%d\n", pTerm->iField);
- }else{
- sqlite3DebugPrintf("\n");
- }
- sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
- }
-}
-#endif
-
-#ifdef WHERETRACE_ENABLED
-/*
-** Show the complete content of a WhereClause
-*/
-void sqlite3WhereClausePrint(WhereClause *pWC){
- int i;
- for(i=0; i<pWC->nTerm; i++){
- whereTermPrint(&pWC->a[i], i);
- }
-}
-#endif
-
-#ifdef WHERETRACE_ENABLED
-/*
-** Print a WhereLoop object for debugging purposes
-*/
-static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
- WhereInfo *pWInfo = pWC->pWInfo;
- int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
- struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
- Table *pTab = pItem->pTab;
- Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
- sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
- p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
- sqlite3DebugPrintf(" %12s",
- pItem->zAlias ? pItem->zAlias : pTab->zName);
- if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
- const char *zName;
- if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){
- if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){
- int i = sqlite3Strlen30(zName) - 1;
- while( zName[i]!='_' ) i--;
- zName += i;
- }
- sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq);
- }else{
- sqlite3DebugPrintf("%20s","");
- }
- }else{
- char *z;
- if( p->u.vtab.idxStr ){
- z = sqlite3_mprintf("(%d,\"%s\",%x)",
- p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
- }else{
- z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
- }
- sqlite3DebugPrintf(" %-19s", z);
- sqlite3_free(z);
- }
- if( p->wsFlags & WHERE_SKIPSCAN ){
- sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip);
- }else{
- sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm);
- }
- sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
- if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){
- int i;
- for(i=0; i<p->nLTerm; i++){
- whereTermPrint(p->aLTerm[i], i);
- }
- }
-}
-#endif
-
-/*
-** Convert bulk memory into a valid WhereLoop that can be passed
-** to whereLoopClear harmlessly.
-*/
-static void whereLoopInit(WhereLoop *p){
- p->aLTerm = p->aLTermSpace;
- p->nLTerm = 0;
- p->nLSlot = ArraySize(p->aLTermSpace);
- p->wsFlags = 0;
-}
-
-/*
-** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact.
-*/
-static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
- if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){
- if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){
- sqlite3_free(p->u.vtab.idxStr);
- p->u.vtab.needFree = 0;
- p->u.vtab.idxStr = 0;
- }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
- sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
- sqlite3DbFreeNN(db, p->u.btree.pIndex);
- p->u.btree.pIndex = 0;
- }
- }
-}
-
-/*
-** Deallocate internal memory used by a WhereLoop object
-*/
-static void whereLoopClear(sqlite3 *db, WhereLoop *p){
- if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm);
- whereLoopClearUnion(db, p);
- whereLoopInit(p);
-}
-
-/*
-** Increase the memory allocation for pLoop->aLTerm[] to be at least n.
-*/
-static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
- WhereTerm **paNew;
- if( p->nLSlot>=n ) return SQLITE_OK;
- n = (n+7)&~7;
- paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n);
- if( paNew==0 ) return SQLITE_NOMEM_BKPT;
- memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
- if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm);
- p->aLTerm = paNew;
- p->nLSlot = n;
- return SQLITE_OK;
-}
-
-/*
-** Transfer content from the second pLoop into the first.
-*/
-static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
- whereLoopClearUnion(db, pTo);
- if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
- memset(&pTo->u, 0, sizeof(pTo->u));
- return SQLITE_NOMEM_BKPT;
- }
- memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
- memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
- if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){
- pFrom->u.vtab.needFree = 0;
- }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){
- pFrom->u.btree.pIndex = 0;
- }
- return SQLITE_OK;
-}
-
-/*
-** Delete a WhereLoop object
-*/
-static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
- whereLoopClear(db, p);
- sqlite3DbFreeNN(db, p);
-}
-
-/*
-** Free a WhereInfo structure
-*/
-static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
- int i;
- assert( pWInfo!=0 );
- for(i=0; i<pWInfo->nLevel; i++){
- WhereLevel *pLevel = &pWInfo->a[i];
- if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
- sqlite3DbFree(db, pLevel->u.in.aInLoop);
- }
- }
- sqlite3WhereClauseClear(&pWInfo->sWC);
- while( pWInfo->pLoops ){
- WhereLoop *p = pWInfo->pLoops;
- pWInfo->pLoops = p->pNextLoop;
- whereLoopDelete(db, p);
- }
- sqlite3DbFreeNN(db, pWInfo);
-}
-
-/*
-** Return TRUE if all of the following are true:
-**
-** (1) X has the same or lower cost that Y
-** (2) X uses fewer WHERE clause terms than Y
-** (3) Every WHERE clause term used by X is also used by Y
-** (4) X skips at least as many columns as Y
-** (5) If X is a covering index, than Y is too
-**
-** Conditions (2) and (3) mean that X is a "proper subset" of Y.
-** If X is a proper subset of Y then Y is a better choice and ought
-** to have a lower cost. This routine returns TRUE when that cost
-** relationship is inverted and needs to be adjusted. Constraint (4)
-** was added because if X uses skip-scan less than Y it still might
-** deserve a lower cost even if it is a proper subset of Y. Constraint (5)
-** was added because a covering index probably deserves to have a lower cost
-** than a non-covering index even if it is a proper subset.
-*/
-static int whereLoopCheaperProperSubset(
- const WhereLoop *pX, /* First WhereLoop to compare */
- const WhereLoop *pY /* Compare against this WhereLoop */
-){
- int i, j;
- if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){
- return 0; /* X is not a subset of Y */
- }
- if( pY->nSkip > pX->nSkip ) return 0;
- if( pX->rRun >= pY->rRun ){
- if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */
- if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */
- }
- for(i=pX->nLTerm-1; i>=0; i--){
- if( pX->aLTerm[i]==0 ) continue;
- for(j=pY->nLTerm-1; j>=0; j--){
- if( pY->aLTerm[j]==pX->aLTerm[i] ) break;
- }
- if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */
- }
- if( (pX->wsFlags&WHERE_IDX_ONLY)!=0
- && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){
- return 0; /* Constraint (5) */
- }
- return 1; /* All conditions meet */
-}
-
-/*
-** Try to adjust the cost of WhereLoop pTemplate upwards or downwards so
-** that:
-**
-** (1) pTemplate costs less than any other WhereLoops that are a proper
-** subset of pTemplate
-**
-** (2) pTemplate costs more than any other WhereLoops for which pTemplate
-** is a proper subset.
-**
-** To say "WhereLoop X is a proper subset of Y" means that X uses fewer
-** WHERE clause terms than Y and that every WHERE clause term used by X is
-** also used by Y.
-*/
-static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
- if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return;
- for(; p; p=p->pNextLoop){
- if( p->iTab!=pTemplate->iTab ) continue;
- if( (p->wsFlags & WHERE_INDEXED)==0 ) continue;
- if( whereLoopCheaperProperSubset(p, pTemplate) ){
- /* Adjust pTemplate cost downward so that it is cheaper than its
- ** subset p. */
- WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
- pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1));
- pTemplate->rRun = p->rRun;
- pTemplate->nOut = p->nOut - 1;
- }else if( whereLoopCheaperProperSubset(pTemplate, p) ){
- /* Adjust pTemplate cost upward so that it is costlier than p since
- ** pTemplate is a proper subset of p */
- WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
- pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut+1));
- pTemplate->rRun = p->rRun;
- pTemplate->nOut = p->nOut + 1;
- }
- }
-}
-
-/*
-** Search the list of WhereLoops in *ppPrev looking for one that can be
-** replaced by pTemplate.
-**
-** Return NULL if pTemplate does not belong on the WhereLoop list.
-** In other words if pTemplate ought to be dropped from further consideration.
-**
-** If pX is a WhereLoop that pTemplate can replace, then return the
-** link that points to pX.
-**
-** If pTemplate cannot replace any existing element of the list but needs
-** to be added to the list as a new entry, then return a pointer to the
-** tail of the list.
-*/
-static WhereLoop **whereLoopFindLesser(
- WhereLoop **ppPrev,
- const WhereLoop *pTemplate
-){
- WhereLoop *p;
- for(p=(*ppPrev); p; ppPrev=&p->pNextLoop, p=*ppPrev){
- if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){
- /* If either the iTab or iSortIdx values for two WhereLoop are different
- ** then those WhereLoops need to be considered separately. Neither is
- ** a candidate to replace the other. */
- continue;
- }
- /* In the current implementation, the rSetup value is either zero
- ** or the cost of building an automatic index (NlogN) and the NlogN
- ** is the same for compatible WhereLoops. */
- assert( p->rSetup==0 || pTemplate->rSetup==0
- || p->rSetup==pTemplate->rSetup );
-
- /* whereLoopAddBtree() always generates and inserts the automatic index
- ** case first. Hence compatible candidate WhereLoops never have a larger
- ** rSetup. Call this SETUP-INVARIANT */
- assert( p->rSetup>=pTemplate->rSetup );
-
- /* Any loop using an appliation-defined index (or PRIMARY KEY or
- ** UNIQUE constraint) with one or more == constraints is better
- ** than an automatic index. Unless it is a skip-scan. */
- if( (p->wsFlags & WHERE_AUTO_INDEX)!=0
- && (pTemplate->nSkip)==0
- && (pTemplate->wsFlags & WHERE_INDEXED)!=0
- && (pTemplate->wsFlags & WHERE_COLUMN_EQ)!=0
- && (p->prereq & pTemplate->prereq)==pTemplate->prereq
- ){
- break;
- }
-
- /* If existing WhereLoop p is better than pTemplate, pTemplate can be
- ** discarded. WhereLoop p is better if:
- ** (1) p has no more dependencies than pTemplate, and
- ** (2) p has an equal or lower cost than pTemplate
- */
- if( (p->prereq & pTemplate->prereq)==p->prereq /* (1) */
- && p->rSetup<=pTemplate->rSetup /* (2a) */
- && p->rRun<=pTemplate->rRun /* (2b) */
- && p->nOut<=pTemplate->nOut /* (2c) */
- ){
- return 0; /* Discard pTemplate */
- }
-
- /* If pTemplate is always better than p, then cause p to be overwritten
- ** with pTemplate. pTemplate is better than p if:
- ** (1) pTemplate has no more dependences than p, and
- ** (2) pTemplate has an equal or lower cost than p.
- */
- if( (p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */
- && p->rRun>=pTemplate->rRun /* (2a) */
- && p->nOut>=pTemplate->nOut /* (2b) */
- ){
- assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */
- break; /* Cause p to be overwritten by pTemplate */
- }
- }
- return ppPrev;
-}
-
-/*
-** Insert or replace a WhereLoop entry using the template supplied.
-**
-** An existing WhereLoop entry might be overwritten if the new template
-** is better and has fewer dependencies. Or the template will be ignored
-** and no insert will occur if an existing WhereLoop is faster and has
-** fewer dependencies than the template. Otherwise a new WhereLoop is
-** added based on the template.
-**
-** If pBuilder->pOrSet is not NULL then we care about only the
-** prerequisites and rRun and nOut costs of the N best loops. That
-** information is gathered in the pBuilder->pOrSet object. This special
-** processing mode is used only for OR clause processing.
-**
-** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
-** still might overwrite similar loops with the new template if the
-** new template is better. Loops may be overwritten if the following
-** conditions are met:
-**
-** (1) They have the same iTab.
-** (2) They have the same iSortIdx.
-** (3) The template has same or fewer dependencies than the current loop
-** (4) The template has the same or lower cost than the current loop
-*/
-static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
- WhereLoop **ppPrev, *p;
- WhereInfo *pWInfo = pBuilder->pWInfo;
- sqlite3 *db = pWInfo->pParse->db;
- int rc;
-
- /* If pBuilder->pOrSet is defined, then only keep track of the costs
- ** and prereqs.
- */
- if( pBuilder->pOrSet!=0 ){
- if( pTemplate->nLTerm ){
-#if WHERETRACE_ENABLED
- u16 n = pBuilder->pOrSet->n;
- int x =
-#endif
- whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
- pTemplate->nOut);
-#if WHERETRACE_ENABLED /* 0x8 */
- if( sqlite3WhereTrace & 0x8 ){
- sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
- whereLoopPrint(pTemplate, pBuilder->pWC);
- }
-#endif
- }
- return SQLITE_OK;
- }
-
- /* Look for an existing WhereLoop to replace with pTemplate
- */
- whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
- ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);
-
- if( ppPrev==0 ){
- /* There already exists a WhereLoop on the list that is better
- ** than pTemplate, so just ignore pTemplate */
-#if WHERETRACE_ENABLED /* 0x8 */
- if( sqlite3WhereTrace & 0x8 ){
- sqlite3DebugPrintf(" skip: ");
- whereLoopPrint(pTemplate, pBuilder->pWC);
- }
-#endif
- return SQLITE_OK;
- }else{
- p = *ppPrev;
- }
-
- /* If we reach this point it means that either p[] should be overwritten
- ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
- ** WhereLoop and insert it.
- */
-#if WHERETRACE_ENABLED /* 0x8 */
- if( sqlite3WhereTrace & 0x8 ){
- if( p!=0 ){
- sqlite3DebugPrintf("replace: ");
- whereLoopPrint(p, pBuilder->pWC);
- sqlite3DebugPrintf(" with: ");
- }else{
- sqlite3DebugPrintf(" add: ");
- }
- whereLoopPrint(pTemplate, pBuilder->pWC);
- }
-#endif
- if( p==0 ){
- /* Allocate a new WhereLoop to add to the end of the list */
- *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop));
- if( p==0 ) return SQLITE_NOMEM_BKPT;
- whereLoopInit(p);
- p->pNextLoop = 0;
- }else{
- /* We will be overwriting WhereLoop p[]. But before we do, first
- ** go through the rest of the list and delete any other entries besides
- ** p[] that are also supplated by pTemplate */
- WhereLoop **ppTail = &p->pNextLoop;
- WhereLoop *pToDel;
- while( *ppTail ){
- ppTail = whereLoopFindLesser(ppTail, pTemplate);
- if( ppTail==0 ) break;
- pToDel = *ppTail;
- if( pToDel==0 ) break;
- *ppTail = pToDel->pNextLoop;
-#if WHERETRACE_ENABLED /* 0x8 */
- if( sqlite3WhereTrace & 0x8 ){
- sqlite3DebugPrintf(" delete: ");
- whereLoopPrint(pToDel, pBuilder->pWC);
- }
-#endif
- whereLoopDelete(db, pToDel);
- }
- }
- rc = whereLoopXfer(db, p, pTemplate);
- if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
- Index *pIndex = p->u.btree.pIndex;
- if( pIndex && pIndex->tnum==0 ){
- p->u.btree.pIndex = 0;
- }
- }
- return rc;
-}
-
-/*
-** Adjust the WhereLoop.nOut value downward to account for terms of the
-** WHERE clause that reference the loop but which are not used by an
-** index.
-*
-** For every WHERE clause term that is not used by the index
-** and which has a truth probability assigned by one of the likelihood(),
-** likely(), or unlikely() SQL functions, reduce the estimated number
-** of output rows by the probability specified.
-**
-** TUNING: For every WHERE clause term that is not used by the index
-** and which does not have an assigned truth probability, heuristics
-** described below are used to try to estimate the truth probability.
-** TODO --> Perhaps this is something that could be improved by better
-** table statistics.
-**
-** Heuristic 1: Estimate the truth probability as 93.75%. The 93.75%
-** value corresponds to -1 in LogEst notation, so this means decrement
-** the WhereLoop.nOut field for every such WHERE clause term.
-**
-** Heuristic 2: If there exists one or more WHERE clause terms of the
-** form "x==EXPR" and EXPR is not a constant 0 or 1, then make sure the
-** final output row estimate is no greater than 1/4 of the total number
-** of rows in the table. In other words, assume that x==EXPR will filter
-** out at least 3 out of 4 rows. If EXPR is -1 or 0 or 1, then maybe the
-** "x" column is boolean or else -1 or 0 or 1 is a common default value
-** on the "x" column and so in that case only cap the output row estimate
-** at 1/2 instead of 1/4.
-*/
-static void whereLoopOutputAdjust(
- WhereClause *pWC, /* The WHERE clause */
- WhereLoop *pLoop, /* The loop to adjust downward */
- LogEst nRow /* Number of rows in the entire table */
-){
- WhereTerm *pTerm, *pX;
- Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
- int i, j, k;
- LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */
-
- assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
- for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
- if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
- if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
- if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
- for(j=pLoop->nLTerm-1; j>=0; j--){
- pX = pLoop->aLTerm[j];
- if( pX==0 ) continue;
- if( pX==pTerm ) break;
- if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
- }
- if( j<0 ){
- if( pTerm->truthProb<=0 ){
- /* If a truth probability is specified using the likelihood() hints,
- ** then use the probability provided by the application. */
- pLoop->nOut += pTerm->truthProb;
- }else{
- /* In the absence of explicit truth probabilities, use heuristics to
- ** guess a reasonable truth probability. */
- pLoop->nOut--;
- if( pTerm->eOperator&(WO_EQ|WO_IS) ){
- Expr *pRight = pTerm->pExpr->pRight;
- testcase( pTerm->pExpr->op==TK_IS );
- if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
- k = 10;
- }else{
- k = 20;
- }
- if( iReduce<k ) iReduce = k;
- }
- }
- }
- }
- if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce;
-}
-
-/*
-** Term pTerm is a vector range comparison operation. The first comparison
-** in the vector can be optimized using column nEq of the index. This
-** function returns the total number of vector elements that can be used
-** as part of the range comparison.
-**
-** For example, if the query is:
-**
-** WHERE a = ? AND (b, c, d) > (?, ?, ?)
-**
-** and the index:
-**
-** CREATE INDEX ... ON (a, b, c, d, e)
-**
-** then this function would be invoked with nEq=1. The value returned in
-** this case is 3.
-*/
-static int whereRangeVectorLen(
- Parse *pParse, /* Parsing context */
- int iCur, /* Cursor open on pIdx */
- Index *pIdx, /* The index to be used for a inequality constraint */
- int nEq, /* Number of prior equality constraints on same index */
- WhereTerm *pTerm /* The vector inequality constraint */
-){
- int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft);
- int i;
-
- nCmp = MIN(nCmp, (pIdx->nColumn - nEq));
- for(i=1; i<nCmp; i++){
- /* Test if comparison i of pTerm is compatible with column (i+nEq)
- ** of the index. If not, exit the loop. */
- char aff; /* Comparison affinity */
- char idxaff = 0; /* Indexed columns affinity */
- CollSeq *pColl; /* Comparison collation sequence */
- Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
- Expr *pRhs = pTerm->pExpr->pRight;
- if( pRhs->flags & EP_xIsSelect ){
- pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
- }else{
- pRhs = pRhs->x.pList->a[i].pExpr;
- }
-
- /* Check that the LHS of the comparison is a column reference to
- ** the right column of the right source table. And that the sort
- ** order of the index column is the same as the sort order of the
- ** leftmost index column. */
- if( pLhs->op!=TK_COLUMN
- || pLhs->iTable!=iCur
- || pLhs->iColumn!=pIdx->aiColumn[i+nEq]
- || pIdx->aSortOrder[i+nEq]!=pIdx->aSortOrder[nEq]
- ){
- break;
- }
-
- testcase( pLhs->iColumn==XN_ROWID );
- aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs));
- idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
- if( aff!=idxaff ) break;
-
- pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
- if( pColl==0 ) break;
- if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
- }
- return i;
-}
-
-/*
-** Adjust the cost C by the costMult facter T. This only occurs if
-** compiled with -DSQLITE_ENABLE_COSTMULT
-*/
-#ifdef SQLITE_ENABLE_COSTMULT
-# define ApplyCostMultiplier(C,T) C += T
-#else
-# define ApplyCostMultiplier(C,T)
-#endif
-
-/*
-** We have so far matched pBuilder->pNew->u.btree.nEq terms of the
-** index pIndex. Try to match one more.
-**
-** When this function is called, pBuilder->pNew->nOut contains the
-** number of rows expected to be visited by filtering using the nEq
-** terms only. If it is modified, this value is restored before this
-** function returns.
-**
-** If pProbe->tnum==0, that means pIndex is a fake index used for the
-** INTEGER PRIMARY KEY.
-*/
-static int whereLoopAddBtreeIndex(
- WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
- struct SrcList_item *pSrc, /* FROM clause term being analyzed */
- Index *pProbe, /* An index on pSrc */
- LogEst nInMul /* log(Number of iterations due to IN) */
-){
- WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
- Parse *pParse = pWInfo->pParse; /* Parsing context */
- sqlite3 *db = pParse->db; /* Database connection malloc context */
- WhereLoop *pNew; /* Template WhereLoop under construction */
- WhereTerm *pTerm; /* A WhereTerm under consideration */
- int opMask; /* Valid operators for constraints */
- WhereScan scan; /* Iterator for WHERE terms */
- Bitmask saved_prereq; /* Original value of pNew->prereq */
- u16 saved_nLTerm; /* Original value of pNew->nLTerm */
- u16 saved_nEq; /* Original value of pNew->u.btree.nEq */
- u16 saved_nBtm; /* Original value of pNew->u.btree.nBtm */
- u16 saved_nTop; /* Original value of pNew->u.btree.nTop */
- u16 saved_nSkip; /* Original value of pNew->nSkip */
- u32 saved_wsFlags; /* Original value of pNew->wsFlags */
- LogEst saved_nOut; /* Original value of pNew->nOut */
- int rc = SQLITE_OK; /* Return code */
- LogEst rSize; /* Number of rows in the table */
- LogEst rLogSize; /* Logarithm of table size */
- WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
-
- pNew = pBuilder->pNew;
- if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
- WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n",
- pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq));
-
- assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
- assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
- if( pNew->wsFlags & WHERE_BTM_LIMIT ){
- opMask = WO_LT|WO_LE;
- }else{
- assert( pNew->u.btree.nBtm==0 );
- opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
- }
- if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
-
- assert( pNew->u.btree.nEq<pProbe->nColumn );
-
- saved_nEq = pNew->u.btree.nEq;
- saved_nBtm = pNew->u.btree.nBtm;
- saved_nTop = pNew->u.btree.nTop;
- saved_nSkip = pNew->nSkip;
- saved_nLTerm = pNew->nLTerm;
- saved_wsFlags = pNew->wsFlags;
- saved_prereq = pNew->prereq;
- saved_nOut = pNew->nOut;
- pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, saved_nEq,
- opMask, pProbe);
- pNew->rSetup = 0;
- rSize = pProbe->aiRowLogEst[0];
- rLogSize = estLog(rSize);
- for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
- u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */
- LogEst rCostIdx;
- LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */
- int nIn = 0;
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- int nRecValid = pBuilder->nRecValid;
-#endif
- if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
- && indexColumnNotNull(pProbe, saved_nEq)
- ){
- continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */
- }
- if( pTerm->prereqRight & pNew->maskSelf ) continue;
-
- /* Do not allow the upper bound of a LIKE optimization range constraint
- ** to mix with a lower range bound from some other source */
- if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
-
- /* Do not allow constraints from the WHERE clause to be used by the
- ** right table of a LEFT JOIN. Only constraints in the ON clause are
- ** allowed */
- if( (pSrc->fg.jointype & JT_LEFT)!=0
- && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- ){
- continue;
- }
-
- if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
- pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE;
- }else{
- pBuilder->bldFlags |= SQLITE_BLDF_INDEXED;
- }
- pNew->wsFlags = saved_wsFlags;
- pNew->u.btree.nEq = saved_nEq;
- pNew->u.btree.nBtm = saved_nBtm;
- pNew->u.btree.nTop = saved_nTop;
- pNew->nLTerm = saved_nLTerm;
- if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
- pNew->aLTerm[pNew->nLTerm++] = pTerm;
- pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;
-
- assert( nInMul==0
- || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0
- || (pNew->wsFlags & WHERE_COLUMN_IN)!=0
- || (pNew->wsFlags & WHERE_SKIPSCAN)!=0
- );
-
- if( eOp & WO_IN ){
- Expr *pExpr = pTerm->pExpr;
- pNew->wsFlags |= WHERE_COLUMN_IN;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
- int i;
- nIn = 46; assert( 46==sqlite3LogEst(25) );
-
- /* The expression may actually be of the form (x, y) IN (SELECT...).
- ** In this case there is a separate term for each of (x) and (y).
- ** However, the nIn multiplier should only be applied once, not once
- ** for each such term. The following loop checks that pTerm is the
- ** first such term in use, and sets nIn back to 0 if it is not. */
- for(i=0; i<pNew->nLTerm-1; i++){
- if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
- }
- }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
- /* "x IN (value, value, ...)" */
- nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
- assert( nIn>0 ); /* RHS always has 2 or more terms... The parser
- ** changes "x IN (?)" into "x=?". */
- }
- }else if( eOp & (WO_EQ|WO_IS) ){
- int iCol = pProbe->aiColumn[saved_nEq];
- pNew->wsFlags |= WHERE_COLUMN_EQ;
- assert( saved_nEq==pNew->u.btree.nEq );
- if( iCol==XN_ROWID
- || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
- ){
- if( iCol==XN_ROWID || pProbe->uniqNotNull
- || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
- ){
- pNew->wsFlags |= WHERE_ONEROW;
- }else{
- pNew->wsFlags |= WHERE_UNQ_WANTED;
- }
- }
- }else if( eOp & WO_ISNULL ){
- pNew->wsFlags |= WHERE_COLUMN_NULL;
- }else if( eOp & (WO_GT|WO_GE) ){
- testcase( eOp & WO_GT );
- testcase( eOp & WO_GE );
- pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
- pNew->u.btree.nBtm = whereRangeVectorLen(
- pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
- );
- pBtm = pTerm;
- pTop = 0;
- if( pTerm->wtFlags & TERM_LIKEOPT ){
- /* Range contraints that come from the LIKE optimization are
- ** always used in pairs. */
- pTop = &pTerm[1];
- assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
- assert( pTop->wtFlags & TERM_LIKEOPT );
- assert( pTop->eOperator==WO_LT );
- if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
- pNew->aLTerm[pNew->nLTerm++] = pTop;
- pNew->wsFlags |= WHERE_TOP_LIMIT;
- pNew->u.btree.nTop = 1;
- }
- }else{
- assert( eOp & (WO_LT|WO_LE) );
- testcase( eOp & WO_LT );
- testcase( eOp & WO_LE );
- pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
- pNew->u.btree.nTop = whereRangeVectorLen(
- pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
- );
- pTop = pTerm;
- pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
- pNew->aLTerm[pNew->nLTerm-2] : 0;
- }
-
- /* At this point pNew->nOut is set to the number of rows expected to
- ** be visited by the index scan before considering term pTerm, or the
- ** values of nIn and nInMul. In other words, assuming that all
- ** "x IN(...)" terms are replaced with "x = ?". This block updates
- ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */
- assert( pNew->nOut==saved_nOut );
- if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
- /* Adjust nOut using stat3/stat4 data. Or, if there is no stat3/stat4
- ** data, using some other estimate. */
- whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
- }else{
- int nEq = ++pNew->u.btree.nEq;
- assert( eOp & (WO_ISNULL|WO_EQ|WO_IN|WO_IS) );
-
- assert( pNew->nOut==saved_nOut );
- if( pTerm->truthProb<=0 && pProbe->aiColumn[saved_nEq]>=0 ){
- assert( (eOp & WO_IN) || nIn==0 );
- testcase( eOp & WO_IN );
- pNew->nOut += pTerm->truthProb;
- pNew->nOut -= nIn;
- }else{
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- tRowcnt nOut = 0;
- if( nInMul==0
- && pProbe->nSample
- && pNew->u.btree.nEq<=pProbe->nSampleCol
- && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
- ){
- Expr *pExpr = pTerm->pExpr;
- if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
- testcase( eOp & WO_EQ );
- testcase( eOp & WO_IS );
- testcase( eOp & WO_ISNULL );
- rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
- }else{
- rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
- }
- if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
- if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */
- if( nOut ){
- pNew->nOut = sqlite3LogEst(nOut);
- if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
- pNew->nOut -= nIn;
- }
- }
- if( nOut==0 )
-#endif
- {
- pNew->nOut += (pProbe->aiRowLogEst[nEq] - pProbe->aiRowLogEst[nEq-1]);
- if( eOp & WO_ISNULL ){
- /* TUNING: If there is no likelihood() value, assume that a
- ** "col IS NULL" expression matches twice as many rows
- ** as (col=?). */
- pNew->nOut += 10;
- }
- }
- }
- }
-
- /* Set rCostIdx to the cost of visiting selected rows in index. Add
- ** it to pNew->rRun, which is currently set to the cost of the index
- ** seek only. Then, if this is a non-covering index, add the cost of
- ** visiting the rows in the main table. */
- rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
- pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
- if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
- pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
- }
- ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
-
- nOutUnadjusted = pNew->nOut;
- pNew->rRun += nInMul + nIn;
- pNew->nOut += nInMul + nIn;
- whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize);
- rc = whereLoopInsert(pBuilder, pNew);
-
- if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
- pNew->nOut = saved_nOut;
- }else{
- pNew->nOut = nOutUnadjusted;
- }
-
- if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
- && pNew->u.btree.nEq<pProbe->nColumn
- ){
- whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
- }
- pNew->nOut = saved_nOut;
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- pBuilder->nRecValid = nRecValid;
-#endif
- }
- pNew->prereq = saved_prereq;
- pNew->u.btree.nEq = saved_nEq;
- pNew->u.btree.nBtm = saved_nBtm;
- pNew->u.btree.nTop = saved_nTop;
- pNew->nSkip = saved_nSkip;
- pNew->wsFlags = saved_wsFlags;
- pNew->nOut = saved_nOut;
- pNew->nLTerm = saved_nLTerm;
-
- /* Consider using a skip-scan if there are no WHERE clause constraints
- ** available for the left-most terms of the index, and if the average
- ** number of repeats in the left-most terms is at least 18.
- **
- ** The magic number 18 is selected on the basis that scanning 17 rows
- ** is almost always quicker than an index seek (even though if the index
- ** contains fewer than 2^17 rows we assume otherwise in other parts of
- ** the code). And, even if it is not, it should not be too much slower.
- ** On the other hand, the extra seeks could end up being significantly
- ** more expensive. */
- assert( 42==sqlite3LogEst(18) );
- if( saved_nEq==saved_nSkip
- && saved_nEq+1<pProbe->nKeyCol
- && pProbe->noSkipScan==0
- && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
- && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
- ){
- LogEst nIter;
- pNew->u.btree.nEq++;
- pNew->nSkip++;
- pNew->aLTerm[pNew->nLTerm++] = 0;
- pNew->wsFlags |= WHERE_SKIPSCAN;
- nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1];
- pNew->nOut -= nIter;
- /* TUNING: Because uncertainties in the estimates for skip-scan queries,
- ** add a 1.375 fudge factor to make skip-scan slightly less likely. */
- nIter += 5;
- whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul);
- pNew->nOut = saved_nOut;
- pNew->u.btree.nEq = saved_nEq;
- pNew->nSkip = saved_nSkip;
- pNew->wsFlags = saved_wsFlags;
- }
-
- WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n",
- pProbe->pTable->zName, pProbe->zName, saved_nEq, rc));
- return rc;
-}
-
-/*
-** Return True if it is possible that pIndex might be useful in
-** implementing the ORDER BY clause in pBuilder.
-**
-** Return False if pBuilder does not contain an ORDER BY clause or
-** if there is no way for pIndex to be useful in implementing that
-** ORDER BY clause.
-*/
-static int indexMightHelpWithOrderBy(
- WhereLoopBuilder *pBuilder,
- Index *pIndex,
- int iCursor
-){
- ExprList *pOB;
- ExprList *aColExpr;
- int ii, jj;
-
- if( pIndex->bUnordered ) return 0;
- if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
- for(ii=0; ii<pOB->nExpr; ii++){
- Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
- if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
- if( pExpr->iColumn<0 ) return 1;
- for(jj=0; jj<pIndex->nKeyCol; jj++){
- if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
- }
- }else if( (aColExpr = pIndex->aColExpr)!=0 ){
- for(jj=0; jj<pIndex->nKeyCol; jj++){
- if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
- if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
- return 1;
- }
- }
- }
- }
- return 0;
-}
-
-/*
-** Return a bitmask where 1s indicate that the corresponding column of
-** the table is used by an index. Only the first 63 columns are considered.
-*/
-static Bitmask columnsInIndex(Index *pIdx){
- Bitmask m = 0;
- int j;
- for(j=pIdx->nColumn-1; j>=0; j--){
- int x = pIdx->aiColumn[j];
- if( x>=0 ){
- testcase( x==BMS-1 );
- testcase( x==BMS-2 );
- if( x<BMS-1 ) m |= MASKBIT(x);
- }
- }
- return m;
-}
-
-/* Check to see if a partial index with pPartIndexWhere can be used
-** in the current query. Return true if it can be and false if not.
-*/
-static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
- int i;
- WhereTerm *pTerm;
- Parse *pParse = pWC->pWInfo->pParse;
- while( pWhere->op==TK_AND ){
- if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0;
- pWhere = pWhere->pRight;
- }
- if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
- for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- Expr *pExpr = pTerm->pExpr;
- if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
- && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
- ){
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** Add all WhereLoop objects for a single table of the join where the table
-** is identified by pBuilder->pNew->iTab. That table is guaranteed to be
-** a b-tree table, not a virtual table.
-**
-** The costs (WhereLoop.rRun) of the b-tree loops added by this function
-** are calculated as follows:
-**
-** For a full scan, assuming the table (or index) contains nRow rows:
-**
-** cost = nRow * 3.0 // full-table scan
-** cost = nRow * K // scan of covering index
-** cost = nRow * (K+3.0) // scan of non-covering index
-**
-** where K is a value between 1.1 and 3.0 set based on the relative
-** estimated average size of the index and table records.
-**
-** For an index scan, where nVisit is the number of index rows visited
-** by the scan, and nSeek is the number of seek operations required on
-** the index b-tree:
-**
-** cost = nSeek * (log(nRow) + K * nVisit) // covering index
-** cost = nSeek * (log(nRow) + (K+3.0) * nVisit) // non-covering index
-**
-** Normally, nSeek is 1. nSeek values greater than 1 come about if the
-** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when
-** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans.
-**
-** The estimated values (nRow, nVisit, nSeek) often contain a large amount
-** of uncertainty. For this reason, scoring is designed to pick plans that
-** "do the least harm" if the estimates are inaccurate. For example, a
-** log(nRow) factor is omitted from a non-covering index scan in order to
-** bias the scoring in favor of using an index, since the worst-case
-** performance of using an index is far better than the worst-case performance
-** of a full table scan.
-*/
-static int whereLoopAddBtree(
- WhereLoopBuilder *pBuilder, /* WHERE clause information */
- Bitmask mPrereq /* Extra prerequesites for using this table */
-){
- WhereInfo *pWInfo; /* WHERE analysis context */
- Index *pProbe; /* An index we are evaluating */
- Index sPk; /* A fake index object for the primary key */
- LogEst aiRowEstPk[2]; /* The aiRowLogEst[] value for the sPk index */
- i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */
- SrcList *pTabList; /* The FROM clause */
- struct SrcList_item *pSrc; /* The FROM clause btree term to add */
- WhereLoop *pNew; /* Template WhereLoop object */
- int rc = SQLITE_OK; /* Return code */
- int iSortIdx = 1; /* Index number */
- int b; /* A boolean value */
- LogEst rSize; /* number of rows in the table */
- LogEst rLogSize; /* Logarithm of the number of rows in the table */
- WhereClause *pWC; /* The parsed WHERE clause */
- Table *pTab; /* Table being queried */
-
- pNew = pBuilder->pNew;
- pWInfo = pBuilder->pWInfo;
- pTabList = pWInfo->pTabList;
- pSrc = pTabList->a + pNew->iTab;
- pTab = pSrc->pTab;
- pWC = pBuilder->pWC;
- assert( !IsVirtual(pSrc->pTab) );
-
- if( pSrc->pIBIndex ){
- /* An INDEXED BY clause specifies a particular index to use */
- pProbe = pSrc->pIBIndex;
- }else if( !HasRowid(pTab) ){
- pProbe = pTab->pIndex;
- }else{
- /* There is no INDEXED BY clause. Create a fake Index object in local
- ** variable sPk to represent the rowid primary key index. Make this
- ** fake index the first in a chain of Index objects with all of the real
- ** indices to follow */
- Index *pFirst; /* First of real indices on the table */
- memset(&sPk, 0, sizeof(Index));
- sPk.nKeyCol = 1;
- sPk.nColumn = 1;
- sPk.aiColumn = &aiColumnPk;
- sPk.aiRowLogEst = aiRowEstPk;
- sPk.onError = OE_Replace;
- sPk.pTable = pTab;
- sPk.szIdxRow = pTab->szTabRow;
- aiRowEstPk[0] = pTab->nRowLogEst;
- aiRowEstPk[1] = 0;
- pFirst = pSrc->pTab->pIndex;
- if( pSrc->fg.notIndexed==0 ){
- /* The real indices of the table are only considered if the
- ** NOT INDEXED qualifier is omitted from the FROM clause */
- sPk.pNext = pFirst;
- }
- pProbe = &sPk;
- }
- rSize = pTab->nRowLogEst;
- rLogSize = estLog(rSize);
-
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
- /* Automatic indexes */
- if( !pBuilder->pOrSet /* Not part of an OR optimization */
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
- && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
- && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */
- && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
- && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
- && !pSrc->fg.isCorrelated /* Not a correlated subquery */
- && !pSrc->fg.isRecursive /* Not a recursive common table expression. */
- ){
- /* Generate auto-index WhereLoops */
- WhereTerm *pTerm;
- WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
- for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
- if( pTerm->prereqRight & pNew->maskSelf ) continue;
- if( termCanDriveIndex(pTerm, pSrc, 0) ){
- pNew->u.btree.nEq = 1;
- pNew->nSkip = 0;
- pNew->u.btree.pIndex = 0;
- pNew->nLTerm = 1;
- pNew->aLTerm[0] = pTerm;
- /* TUNING: One-time cost for computing the automatic index is
- ** estimated to be X*N*log2(N) where N is the number of rows in
- ** the table being indexed and where X is 7 (LogEst=28) for normal
- ** tables or 0.5 (LogEst=-10) for views and subqueries. The value
- ** of X is smaller for views and subqueries so that the query planner
- ** will be more aggressive about generating automatic indexes for
- ** those objects, since there is no opportunity to add schema
- ** indexes on subqueries and views. */
- pNew->rSetup = rLogSize + rSize;
- if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
- pNew->rSetup += 28;
- }else{
- pNew->rSetup -= 10;
- }
- ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
- if( pNew->rSetup<0 ) pNew->rSetup = 0;
- /* TUNING: Each index lookup yields 20 rows in the table. This
- ** is more than the usual guess of 10 rows, since we have no way
- ** of knowing how selective the index will ultimately be. It would
- ** not be unreasonable to make this value much larger. */
- pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
- pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
- pNew->wsFlags = WHERE_AUTO_INDEX;
- pNew->prereq = mPrereq | pTerm->prereqRight;
- rc = whereLoopInsert(pBuilder, pNew);
- }
- }
- }
-#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
-
- /* Loop over all indices. If there was an INDEXED BY clause, then only
- ** consider index pProbe. */
- for(; rc==SQLITE_OK && pProbe;
- pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
- ){
- if( pProbe->pPartIdxWhere!=0
- && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){
- testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */
- continue; /* Partial index inappropriate for this query */
- }
- if( pProbe->bNoQuery ) continue;
- rSize = pProbe->aiRowLogEst[0];
- pNew->u.btree.nEq = 0;
- pNew->u.btree.nBtm = 0;
- pNew->u.btree.nTop = 0;
- pNew->nSkip = 0;
- pNew->nLTerm = 0;
- pNew->iSortIdx = 0;
- pNew->rSetup = 0;
- pNew->prereq = mPrereq;
- pNew->nOut = rSize;
- pNew->u.btree.pIndex = pProbe;
- b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
- /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
- assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
- if( pProbe->tnum<=0 ){
- /* Integer primary key index */
- pNew->wsFlags = WHERE_IPK;
-
- /* Full table scan */
- pNew->iSortIdx = b ? iSortIdx : 0;
- /* TUNING: Cost of full table scan is (N*3.0). */
- pNew->rRun = rSize + 16;
- ApplyCostMultiplier(pNew->rRun, pTab->costMult);
- whereLoopOutputAdjust(pWC, pNew, rSize);
- rc = whereLoopInsert(pBuilder, pNew);
- pNew->nOut = rSize;
- if( rc ) break;
- }else{
- Bitmask m;
- if( pProbe->isCovering ){
- pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
- m = 0;
- }else{
- m = pSrc->colUsed & ~columnsInIndex(pProbe);
- pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
- }
-
- /* Full scan via index */
- if( b
- || !HasRowid(pTab)
- || pProbe->pPartIdxWhere!=0
- || ( m==0
- && pProbe->bUnordered==0
- && (pProbe->szIdxRow<pTab->szTabRow)
- && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
- && sqlite3GlobalConfig.bUseCis
- && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
- )
- ){
- pNew->iSortIdx = b ? iSortIdx : 0;
-
- /* The cost of visiting the index rows is N*K, where K is
- ** between 1.1 and 3.0, depending on the relative sizes of the
- ** index and table rows. */
- pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
- if( m!=0 ){
- /* If this is a non-covering index scan, add in the cost of
- ** doing table lookups. The cost will be 3x the number of
- ** lookups. Take into account WHERE clause terms that can be
- ** satisfied using just the index, and that do not require a
- ** table lookup. */
- LogEst nLookup = rSize + 16; /* Base cost: N*3 */
- int ii;
- int iCur = pSrc->iCursor;
- WhereClause *pWC2 = &pWInfo->sWC;
- for(ii=0; ii<pWC2->nTerm; ii++){
- WhereTerm *pTerm = &pWC2->a[ii];
- if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
- break;
- }
- /* pTerm can be evaluated using just the index. So reduce
- ** the expected number of table lookups accordingly */
- if( pTerm->truthProb<=0 ){
- nLookup += pTerm->truthProb;
- }else{
- nLookup--;
- if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19;
- }
- }
-
- pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
- }
- ApplyCostMultiplier(pNew->rRun, pTab->costMult);
- whereLoopOutputAdjust(pWC, pNew, rSize);
- rc = whereLoopInsert(pBuilder, pNew);
- pNew->nOut = rSize;
- if( rc ) break;
- }
- }
-
- pBuilder->bldFlags = 0;
- rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
- if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){
- /* If a non-unique index is used, or if a prefix of the key for
- ** unique index is used (making the index functionally non-unique)
- ** then the sqlite_stat1 data becomes important for scoring the
- ** plan */
- pTab->tabFlags |= TF_StatsUsed;
- }
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- sqlite3Stat4ProbeFree(pBuilder->pRec);
- pBuilder->nRecValid = 0;
- pBuilder->pRec = 0;
-#endif
- }
- return rc;
-}
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/*
-** Argument pIdxInfo is already populated with all constraints that may
-** be used by the virtual table identified by pBuilder->pNew->iTab. This
-** function marks a subset of those constraints usable, invokes the
-** xBestIndex method and adds the returned plan to pBuilder.
-**
-** A constraint is marked usable if:
-**
-** * Argument mUsable indicates that its prerequisites are available, and
-**
-** * It is not one of the operators specified in the mExclude mask passed
-** as the fourth argument (which in practice is either WO_IN or 0).
-**
-** Argument mPrereq is a mask of tables that must be scanned before the
-** virtual table in question. These are added to the plans prerequisites
-** before it is added to pBuilder.
-**
-** Output parameter *pbIn is set to true if the plan added to pBuilder
-** uses one or more WO_IN terms, or false otherwise.
-*/
-static int whereLoopAddVirtualOne(
- WhereLoopBuilder *pBuilder,
- Bitmask mPrereq, /* Mask of tables that must be used. */
- Bitmask mUsable, /* Mask of usable tables */
- u16 mExclude, /* Exclude terms using these operators */
- sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */
- u16 mNoOmit, /* Do not omit these constraints */
- int *pbIn /* OUT: True if plan uses an IN(...) op */
-){
- WhereClause *pWC = pBuilder->pWC;
- struct sqlite3_index_constraint *pIdxCons;
- struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage;
- int i;
- int mxTerm;
- int rc = SQLITE_OK;
- WhereLoop *pNew = pBuilder->pNew;
- Parse *pParse = pBuilder->pWInfo->pParse;
- struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
- int nConstraint = pIdxInfo->nConstraint;
-
- assert( (mUsable & mPrereq)==mPrereq );
- *pbIn = 0;
- pNew->prereq = mPrereq;
-
- /* Set the usable flag on the subset of constraints identified by
- ** arguments mUsable and mExclude. */
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- for(i=0; i<nConstraint; i++, pIdxCons++){
- WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset];
- pIdxCons->usable = 0;
- if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
- && (pTerm->eOperator & mExclude)==0
- ){
- pIdxCons->usable = 1;
- }
- }
-
- /* Initialize the output fields of the sqlite3_index_info structure */
- memset(pUsage, 0, sizeof(pUsage[0])*nConstraint);
- assert( pIdxInfo->needToFreeIdxStr==0 );
- pIdxInfo->idxStr = 0;
- pIdxInfo->idxNum = 0;
- pIdxInfo->orderByConsumed = 0;
- pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
- pIdxInfo->estimatedRows = 25;
- pIdxInfo->idxFlags = 0;
- pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
-
- /* Invoke the virtual table xBestIndex() method */
- rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
- if( rc ) return rc;
-
- mxTerm = -1;
- assert( pNew->nLSlot>=nConstraint );
- for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
- pNew->u.vtab.omitMask = 0;
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- for(i=0; i<nConstraint; i++, pIdxCons++){
- int iTerm;
- if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
- WhereTerm *pTerm;
- int j = pIdxCons->iTermOffset;
- if( iTerm>=nConstraint
- || j<0
- || j>=pWC->nTerm
- || pNew->aLTerm[iTerm]!=0
- || pIdxCons->usable==0
- ){
- sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
- testcase( pIdxInfo->needToFreeIdxStr );
- return SQLITE_ERROR;
- }
- testcase( iTerm==nConstraint-1 );
- testcase( j==0 );
- testcase( j==pWC->nTerm-1 );
- pTerm = &pWC->a[j];
- pNew->prereq |= pTerm->prereqRight;
- assert( iTerm<pNew->nLSlot );
- pNew->aLTerm[iTerm] = pTerm;
- if( iTerm>mxTerm ) mxTerm = iTerm;
- testcase( iTerm==15 );
- testcase( iTerm==16 );
- if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
- if( (pTerm->eOperator & WO_IN)!=0 ){
- /* A virtual table that is constrained by an IN clause may not
- ** consume the ORDER BY clause because (1) the order of IN terms
- ** is not necessarily related to the order of output terms and
- ** (2) Multiple outputs from a single IN value will not merge
- ** together. */
- pIdxInfo->orderByConsumed = 0;
- pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
- *pbIn = 1; assert( (mExclude & WO_IN)==0 );
- }
- }
- }
- pNew->u.vtab.omitMask &= ~mNoOmit;
-
- pNew->nLTerm = mxTerm+1;
- for(i=0; i<=mxTerm; i++){
- if( pNew->aLTerm[i]==0 ){
- /* The non-zero argvIdx values must be contiguous. Raise an
- ** error if they are not */
- sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
- testcase( pIdxInfo->needToFreeIdxStr );
- return SQLITE_ERROR;
- }
- }
- assert( pNew->nLTerm<=pNew->nLSlot );
- pNew->u.vtab.idxNum = pIdxInfo->idxNum;
- pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
- pIdxInfo->needToFreeIdxStr = 0;
- pNew->u.vtab.idxStr = pIdxInfo->idxStr;
- pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
- pIdxInfo->nOrderBy : 0);
- pNew->rSetup = 0;
- pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
- pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
-
- /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated
- ** that the scan will visit at most one row. Clear it otherwise. */
- if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){
- pNew->wsFlags |= WHERE_ONEROW;
- }else{
- pNew->wsFlags &= ~WHERE_ONEROW;
- }
- rc = whereLoopInsert(pBuilder, pNew);
- if( pNew->u.vtab.needFree ){
- sqlite3_free(pNew->u.vtab.idxStr);
- pNew->u.vtab.needFree = 0;
- }
- WHERETRACE(0xffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n",
- *pbIn, (sqlite3_uint64)mPrereq,
- (sqlite3_uint64)(pNew->prereq & ~mPrereq)));
-
- return rc;
-}
-
-/*
-** If this function is invoked from within an xBestIndex() callback, it
-** returns a pointer to a buffer containing the name of the collation
-** sequence associated with element iCons of the sqlite3_index_info.aConstraint
-** array. Or, if iCons is out of range or there is no active xBestIndex
-** call, return NULL.
-*/
-const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){
- HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
- const char *zRet = 0;
- if( iCons>=0 && iCons<pIdxInfo->nConstraint ){
- CollSeq *pC = 0;
- int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
- Expr *pX = pHidden->pWC->a[iTerm].pExpr;
- if( pX->pLeft ){
- pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
- }
- zRet = (pC ? pC->zName : "BINARY");
- }
- return zRet;
-}
-
-/*
-** Add all WhereLoop objects for a table of the join identified by
-** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
-**
-** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and
-** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause
-** entries that occur before the virtual table in the FROM clause and are
-** separated from it by at least one LEFT or CROSS JOIN. Similarly, the
-** mUnusable mask contains all FROM clause entries that occur after the
-** virtual table and are separated from it by at least one LEFT or
-** CROSS JOIN.
-**
-** For example, if the query were:
-**
-** ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6;
-**
-** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6).
-**
-** All the tables in mPrereq must be scanned before the current virtual
-** table. So any terms for which all prerequisites are satisfied by
-** mPrereq may be specified as "usable" in all calls to xBestIndex.
-** Conversely, all tables in mUnusable must be scanned after the current
-** virtual table, so any terms for which the prerequisites overlap with
-** mUnusable should always be configured as "not-usable" for xBestIndex.
-*/
-static int whereLoopAddVirtual(
- WhereLoopBuilder *pBuilder, /* WHERE clause information */
- Bitmask mPrereq, /* Tables that must be scanned before this one */
- Bitmask mUnusable /* Tables that must be scanned after this one */
-){
- int rc = SQLITE_OK; /* Return code */
- WhereInfo *pWInfo; /* WHERE analysis context */
- Parse *pParse; /* The parsing context */
- WhereClause *pWC; /* The WHERE clause */
- struct SrcList_item *pSrc; /* The FROM clause term to search */
- sqlite3_index_info *p; /* Object to pass to xBestIndex() */
- int nConstraint; /* Number of constraints in p */
- int bIn; /* True if plan uses IN(...) operator */
- WhereLoop *pNew;
- Bitmask mBest; /* Tables used by best possible plan */
- u16 mNoOmit;
-
- assert( (mPrereq & mUnusable)==0 );
- pWInfo = pBuilder->pWInfo;
- pParse = pWInfo->pParse;
- pWC = pBuilder->pWC;
- pNew = pBuilder->pNew;
- pSrc = &pWInfo->pTabList->a[pNew->iTab];
- assert( IsVirtual(pSrc->pTab) );
- p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy,
- &mNoOmit);
- if( p==0 ) return SQLITE_NOMEM_BKPT;
- pNew->rSetup = 0;
- pNew->wsFlags = WHERE_VIRTUALTABLE;
- pNew->nLTerm = 0;
- pNew->u.vtab.needFree = 0;
- nConstraint = p->nConstraint;
- if( whereLoopResize(pParse->db, pNew, nConstraint) ){
- sqlite3DbFree(pParse->db, p);
- return SQLITE_NOMEM_BKPT;
- }
-
- /* First call xBestIndex() with all constraints usable. */
- WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName));
- WHERETRACE(0x40, (" VirtualOne: all usable\n"));
- rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn);
-
- /* If the call to xBestIndex() with all terms enabled produced a plan
- ** that does not require any source tables (IOW: a plan with mBest==0),
- ** then there is no point in making any further calls to xBestIndex()
- ** since they will all return the same result (if the xBestIndex()
- ** implementation is sane). */
- if( rc==SQLITE_OK && (mBest = (pNew->prereq & ~mPrereq))!=0 ){
- int seenZero = 0; /* True if a plan with no prereqs seen */
- int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */
- Bitmask mPrev = 0;
- Bitmask mBestNoIn = 0;
-
- /* If the plan produced by the earlier call uses an IN(...) term, call
- ** xBestIndex again, this time with IN(...) terms disabled. */
- if( bIn ){
- WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n"));
- rc = whereLoopAddVirtualOne(
- pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn);
- assert( bIn==0 );
- mBestNoIn = pNew->prereq & ~mPrereq;
- if( mBestNoIn==0 ){
- seenZero = 1;
- seenZeroNoIN = 1;
- }
- }
-
- /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq)
- ** in the set of terms that apply to the current virtual table. */
- while( rc==SQLITE_OK ){
- int i;
- Bitmask mNext = ALLBITS;
- assert( mNext>0 );
- for(i=0; i<nConstraint; i++){
- Bitmask mThis = (
- pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
- );
- if( mThis>mPrev && mThis<mNext ) mNext = mThis;
- }
- mPrev = mNext;
- if( mNext==ALLBITS ) break;
- if( mNext==mBest || mNext==mBestNoIn ) continue;
- WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n",
- (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext));
- rc = whereLoopAddVirtualOne(
- pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn);
- if( pNew->prereq==mPrereq ){
- seenZero = 1;
- if( bIn==0 ) seenZeroNoIN = 1;
- }
- }
-
- /* If the calls to xBestIndex() in the above loop did not find a plan
- ** that requires no source tables at all (i.e. one guaranteed to be
- ** usable), make a call here with all source tables disabled */
- if( rc==SQLITE_OK && seenZero==0 ){
- WHERETRACE(0x40, (" VirtualOne: all disabled\n"));
- rc = whereLoopAddVirtualOne(
- pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn);
- if( bIn==0 ) seenZeroNoIN = 1;
- }
-
- /* If the calls to xBestIndex() have so far failed to find a plan
- ** that requires no source tables at all and does not use an IN(...)
- ** operator, make a final call to obtain one here. */
- if( rc==SQLITE_OK && seenZeroNoIN==0 ){
- WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n"));
- rc = whereLoopAddVirtualOne(
- pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn);
- }
- }
-
- if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
- sqlite3DbFreeNN(pParse->db, p);
- WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
- return rc;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/*
-** Add WhereLoop entries to handle OR terms. This works for either
-** btrees or virtual tables.
-*/
-static int whereLoopAddOr(
- WhereLoopBuilder *pBuilder,
- Bitmask mPrereq,
- Bitmask mUnusable
-){
- WhereInfo *pWInfo = pBuilder->pWInfo;
- WhereClause *pWC;
- WhereLoop *pNew;
- WhereTerm *pTerm, *pWCEnd;
- int rc = SQLITE_OK;
- int iCur;
- WhereClause tempWC;
- WhereLoopBuilder sSubBuild;
- WhereOrSet sSum, sCur;
- struct SrcList_item *pItem;
-
- pWC = pBuilder->pWC;
- pWCEnd = pWC->a + pWC->nTerm;
- pNew = pBuilder->pNew;
- memset(&sSum, 0, sizeof(sSum));
- pItem = pWInfo->pTabList->a + pNew->iTab;
- iCur = pItem->iCursor;
-
- for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
- if( (pTerm->eOperator & WO_OR)!=0
- && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
- ){
- WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
- WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
- WhereTerm *pOrTerm;
- int once = 1;
- int i, j;
-
- sSubBuild = *pBuilder;
- sSubBuild.pOrderBy = 0;
- sSubBuild.pOrSet = &sCur;
-
- WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm));
- for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
- if( (pOrTerm->eOperator & WO_AND)!=0 ){
- sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
- }else if( pOrTerm->leftCursor==iCur ){
- tempWC.pWInfo = pWC->pWInfo;
- tempWC.pOuter = pWC;
- tempWC.op = TK_AND;
- tempWC.nTerm = 1;
- tempWC.a = pOrTerm;
- sSubBuild.pWC = &tempWC;
- }else{
- continue;
- }
- sCur.n = 0;
-#ifdef WHERETRACE_ENABLED
- WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n",
- (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm));
- if( sqlite3WhereTrace & 0x400 ){
- sqlite3WhereClausePrint(sSubBuild.pWC);
- }
-#endif
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pItem->pTab) ){
- rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable);
- }else
-#endif
- {
- rc = whereLoopAddBtree(&sSubBuild, mPrereq);
- }
- if( rc==SQLITE_OK ){
- rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
- }
- assert( rc==SQLITE_OK || sCur.n==0 );
- if( sCur.n==0 ){
- sSum.n = 0;
- break;
- }else if( once ){
- whereOrMove(&sSum, &sCur);
- once = 0;
- }else{
- WhereOrSet sPrev;
- whereOrMove(&sPrev, &sSum);
- sSum.n = 0;
- for(i=0; i<sPrev.n; i++){
- for(j=0; j<sCur.n; j++){
- whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
- sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
- sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
- }
- }
- }
- }
- pNew->nLTerm = 1;
- pNew->aLTerm[0] = pTerm;
- pNew->wsFlags = WHERE_MULTI_OR;
- pNew->rSetup = 0;
- pNew->iSortIdx = 0;
- memset(&pNew->u, 0, sizeof(pNew->u));
- for(i=0; rc==SQLITE_OK && i<sSum.n; i++){
- /* TUNING: Currently sSum.a[i].rRun is set to the sum of the costs
- ** of all sub-scans required by the OR-scan. However, due to rounding
- ** errors, it may be that the cost of the OR-scan is equal to its
- ** most expensive sub-scan. Add the smallest possible penalty
- ** (equivalent to multiplying the cost by 1.07) to ensure that
- ** this does not happen. Otherwise, for WHERE clauses such as the
- ** following where there is an index on "y":
- **
- ** WHERE likelihood(x=?, 0.99) OR y=?
- **
- ** the planner may elect to "OR" together a full-table scan and an
- ** index lookup. And other similarly odd results. */
- pNew->rRun = sSum.a[i].rRun + 1;
- pNew->nOut = sSum.a[i].nOut;
- pNew->prereq = sSum.a[i].prereq;
- rc = whereLoopInsert(pBuilder, pNew);
- }
- WHERETRACE(0x200, ("End processing OR-clause %p\n", pTerm));
- }
- }
- return rc;
-}
-
-/*
-** Add all WhereLoop objects for all tables
-*/
-static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
- WhereInfo *pWInfo = pBuilder->pWInfo;
- Bitmask mPrereq = 0;
- Bitmask mPrior = 0;
- int iTab;
- SrcList *pTabList = pWInfo->pTabList;
- struct SrcList_item *pItem;
- struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel];
- sqlite3 *db = pWInfo->pParse->db;
- int rc = SQLITE_OK;
- WhereLoop *pNew;
- u8 priorJointype = 0;
-
- /* Loop over the tables in the join, from left to right */
- pNew = pBuilder->pNew;
- whereLoopInit(pNew);
- for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
- Bitmask mUnusable = 0;
- pNew->iTab = iTab;
- pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
- if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
- /* This condition is true when pItem is the FROM clause term on the
- ** right-hand-side of a LEFT or CROSS JOIN. */
- mPrereq = mPrior;
- }
- priorJointype = pItem->fg.jointype;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pItem->pTab) ){
- struct SrcList_item *p;
- for(p=&pItem[1]; p<pEnd; p++){
- if( mUnusable || (p->fg.jointype & (JT_LEFT|JT_CROSS)) ){
- mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
- }
- }
- rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable);
- }else
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
- {
- rc = whereLoopAddBtree(pBuilder, mPrereq);
- }
- if( rc==SQLITE_OK ){
- rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
- }
- mPrior |= pNew->maskSelf;
- if( rc || db->mallocFailed ) break;
- }
-
- whereLoopClear(db, pNew);
- return rc;
-}
-
-/*
-** Examine a WherePath (with the addition of the extra WhereLoop of the 6th
-** parameters) to see if it outputs rows in the requested ORDER BY
-** (or GROUP BY) without requiring a separate sort operation. Return N:
-**
-** N>0: N terms of the ORDER BY clause are satisfied
-** N==0: No terms of the ORDER BY clause are satisfied
-** N<0: Unknown yet how many terms of ORDER BY might be satisfied.
-**
-** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
-** strict. With GROUP BY and DISTINCT the only requirement is that
-** equivalent rows appear immediately adjacent to one another. GROUP BY
-** and DISTINCT do not require rows to appear in any particular order as long
-** as equivalent rows are grouped together. Thus for GROUP BY and DISTINCT
-** the pOrderBy terms can be matched in any order. With ORDER BY, the
-** pOrderBy terms must be matched in strict left-to-right order.
-*/
-static i8 wherePathSatisfiesOrderBy(
- WhereInfo *pWInfo, /* The WHERE clause */
- ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */
- WherePath *pPath, /* The WherePath to check */
- u16 wctrlFlags, /* WHERE_GROUPBY or _DISTINCTBY or _ORDERBY_LIMIT */
- u16 nLoop, /* Number of entries in pPath->aLoop[] */
- WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */
- Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */
-){
- u8 revSet; /* True if rev is known */
- u8 rev; /* Composite sort order */
- u8 revIdx; /* Index sort order */
- u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */
- u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */
- u8 isMatch; /* iColumn matches a term of the ORDER BY clause */
- u16 eqOpMask; /* Allowed equality operators */
- u16 nKeyCol; /* Number of key columns in pIndex */
- u16 nColumn; /* Total number of ordered columns in the index */
- u16 nOrderBy; /* Number terms in the ORDER BY clause */
- int iLoop; /* Index of WhereLoop in pPath being processed */
- int i, j; /* Loop counters */
- int iCur; /* Cursor number for current WhereLoop */
- int iColumn; /* A column number within table iCur */
- WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
- Expr *pOBExpr; /* An expression from the ORDER BY clause */
- CollSeq *pColl; /* COLLATE function from an ORDER BY clause term */
- Index *pIndex; /* The index associated with pLoop */
- sqlite3 *db = pWInfo->pParse->db; /* Database connection */
- Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */
- Bitmask obDone; /* Mask of all ORDER BY terms */
- Bitmask orderDistinctMask; /* Mask of all well-ordered loops */
- Bitmask ready; /* Mask of inner loops */
-
- /*
- ** We say the WhereLoop is "one-row" if it generates no more than one
- ** row of output. A WhereLoop is one-row if all of the following are true:
- ** (a) All index columns match with WHERE_COLUMN_EQ.
- ** (b) The index is unique
- ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row.
- ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags.
- **
- ** We say the WhereLoop is "order-distinct" if the set of columns from
- ** that WhereLoop that are in the ORDER BY clause are different for every
- ** row of the WhereLoop. Every one-row WhereLoop is automatically
- ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause
- ** is not order-distinct. To be order-distinct is not quite the same as being
- ** UNIQUE since a UNIQUE column or index can have multiple rows that
- ** are NULL and NULL values are equivalent for the purpose of order-distinct.
- ** To be order-distinct, the columns must be UNIQUE and NOT NULL.
- **
- ** The rowid for a table is always UNIQUE and NOT NULL so whenever the
- ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is
- ** automatically order-distinct.
- */
-
- assert( pOrderBy!=0 );
- if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0;
-
- nOrderBy = pOrderBy->nExpr;
- testcase( nOrderBy==BMS-1 );
- if( nOrderBy>BMS-1 ) return 0; /* Cannot optimize overly large ORDER BYs */
- isOrderDistinct = 1;
- obDone = MASKBIT(nOrderBy)-1;
- orderDistinctMask = 0;
- ready = 0;
- eqOpMask = WO_EQ | WO_IS | WO_ISNULL;
- if( wctrlFlags & WHERE_ORDERBY_LIMIT ) eqOpMask |= WO_IN;
- for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
- if( iLoop>0 ) ready |= pLoop->maskSelf;
- if( iLoop<nLoop ){
- pLoop = pPath->aLoop[iLoop];
- if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue;
- }else{
- pLoop = pLast;
- }
- if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
- if( pLoop->u.vtab.isOrdered ) obSat = obDone;
- break;
- }else{
- pLoop->u.btree.nIdxCol = 0;
- }
- iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
-
- /* Mark off any ORDER BY term X that is a column in the table of
- ** the current loop for which there is term in the WHERE
- ** clause of the form X IS NULL or X=? that reference only outer
- ** loops.
- */
- for(i=0; i<nOrderBy; i++){
- if( MASKBIT(i) & obSat ) continue;
- pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
- if( pOBExpr->op!=TK_COLUMN ) continue;
- if( pOBExpr->iTable!=iCur ) continue;
- pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
- ~ready, eqOpMask, 0);
- if( pTerm==0 ) continue;
- if( pTerm->eOperator==WO_IN ){
- /* IN terms are only valid for sorting in the ORDER BY LIMIT
- ** optimization, and then only if they are actually used
- ** by the query plan */
- assert( wctrlFlags & WHERE_ORDERBY_LIMIT );
- for(j=0; j<pLoop->nLTerm && pTerm!=pLoop->aLTerm[j]; j++){}
- if( j>=pLoop->nLTerm ) continue;
- }
- if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
- if( sqlite3ExprCollSeqMatch(pWInfo->pParse,
- pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){
- continue;
- }
- testcase( pTerm->pExpr->op==TK_IS );
- }
- obSat |= MASKBIT(i);
- }
-
- if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
- if( pLoop->wsFlags & WHERE_IPK ){
- pIndex = 0;
- nKeyCol = 0;
- nColumn = 1;
- }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
- return 0;
- }else{
- nKeyCol = pIndex->nKeyCol;
- nColumn = pIndex->nColumn;
- assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
- assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
- || !HasRowid(pIndex->pTable));
- isOrderDistinct = IsUniqueIndex(pIndex);
- }
-
- /* Loop through all columns of the index and deal with the ones
- ** that are not constrained by == or IN.
- */
- rev = revSet = 0;
- distinctColumns = 0;
- for(j=0; j<nColumn; j++){
- u8 bOnce = 1; /* True to run the ORDER BY search loop */
-
- assert( j>=pLoop->u.btree.nEq
- || (pLoop->aLTerm[j]==0)==(j<pLoop->nSkip)
- );
- if( j<pLoop->u.btree.nEq && j>=pLoop->nSkip ){
- u16 eOp = pLoop->aLTerm[j]->eOperator;
-
- /* Skip over == and IS and ISNULL terms. (Also skip IN terms when
- ** doing WHERE_ORDERBY_LIMIT processing).
- **
- ** If the current term is a column of an ((?,?) IN (SELECT...))
- ** expression for which the SELECT returns more than one column,
- ** check that it is the only column used by this loop. Otherwise,
- ** if it is one of two or more, none of the columns can be
- ** considered to match an ORDER BY term. */
- if( (eOp & eqOpMask)!=0 ){
- if( eOp & WO_ISNULL ){
- testcase( isOrderDistinct );
- isOrderDistinct = 0;
- }
- continue;
- }else if( ALWAYS(eOp & WO_IN) ){
- /* ALWAYS() justification: eOp is an equality operator due to the
- ** j<pLoop->u.btree.nEq constraint above. Any equality other
- ** than WO_IN is captured by the previous "if". So this one
- ** always has to be WO_IN. */
- Expr *pX = pLoop->aLTerm[j]->pExpr;
- for(i=j+1; i<pLoop->u.btree.nEq; i++){
- if( pLoop->aLTerm[i]->pExpr==pX ){
- assert( (pLoop->aLTerm[i]->eOperator & WO_IN) );
- bOnce = 0;
- break;
- }
- }
- }
- }
-
- /* Get the column number in the table (iColumn) and sort order
- ** (revIdx) for the j-th column of the index.
- */
- if( pIndex ){
- iColumn = pIndex->aiColumn[j];
- revIdx = pIndex->aSortOrder[j];
- if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
- }else{
- iColumn = XN_ROWID;
- revIdx = 0;
- }
-
- /* An unconstrained column that might be NULL means that this
- ** WhereLoop is not well-ordered
- */
- if( isOrderDistinct
- && iColumn>=0
- && j>=pLoop->u.btree.nEq
- && pIndex->pTable->aCol[iColumn].notNull==0
- ){
- isOrderDistinct = 0;
- }
-
- /* Find the ORDER BY term that corresponds to the j-th column
- ** of the index and mark that ORDER BY term off
- */
- isMatch = 0;
- for(i=0; bOnce && i<nOrderBy; i++){
- if( MASKBIT(i) & obSat ) continue;
- pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
- testcase( wctrlFlags & WHERE_GROUPBY );
- testcase( wctrlFlags & WHERE_DISTINCTBY );
- if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
- if( iColumn>=XN_ROWID ){
- if( pOBExpr->op!=TK_COLUMN ) continue;
- if( pOBExpr->iTable!=iCur ) continue;
- if( pOBExpr->iColumn!=iColumn ) continue;
- }else{
- Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr;
- if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){
- continue;
- }
- }
- if( iColumn!=XN_ROWID ){
- pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
- if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
- }
- pLoop->u.btree.nIdxCol = j+1;
- isMatch = 1;
- break;
- }
- if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){
- /* Make sure the sort order is compatible in an ORDER BY clause.
- ** Sort order is irrelevant for a GROUP BY clause. */
- if( revSet ){
- if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0;
- }else{
- rev = revIdx ^ pOrderBy->a[i].sortOrder;
- if( rev ) *pRevMask |= MASKBIT(iLoop);
- revSet = 1;
- }
- }
- if( isMatch ){
- if( iColumn==XN_ROWID ){
- testcase( distinctColumns==0 );
- distinctColumns = 1;
- }
- obSat |= MASKBIT(i);
- }else{
- /* No match found */
- if( j==0 || j<nKeyCol ){
- testcase( isOrderDistinct!=0 );
- isOrderDistinct = 0;
- }
- break;
- }
- } /* end Loop over all index columns */
- if( distinctColumns ){
- testcase( isOrderDistinct==0 );
- isOrderDistinct = 1;
- }
- } /* end-if not one-row */
-
- /* Mark off any other ORDER BY terms that reference pLoop */
- if( isOrderDistinct ){
- orderDistinctMask |= pLoop->maskSelf;
- for(i=0; i<nOrderBy; i++){
- Expr *p;
- Bitmask mTerm;
- if( MASKBIT(i) & obSat ) continue;
- p = pOrderBy->a[i].pExpr;
- mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p);
- if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue;
- if( (mTerm&~orderDistinctMask)==0 ){
- obSat |= MASKBIT(i);
- }
- }
- }
- } /* End the loop over all WhereLoops from outer-most down to inner-most */
- if( obSat==obDone ) return (i8)nOrderBy;
- if( !isOrderDistinct ){
- for(i=nOrderBy-1; i>0; i--){
- Bitmask m = MASKBIT(i) - 1;
- if( (obSat&m)==m ) return i;
- }
- return 0;
- }
- return -1;
-}
-
-
-/*
-** If the WHERE_GROUPBY flag is set in the mask passed to sqlite3WhereBegin(),
-** the planner assumes that the specified pOrderBy list is actually a GROUP
-** BY clause - and so any order that groups rows as required satisfies the
-** request.
-**
-** Normally, in this case it is not possible for the caller to determine
-** whether or not the rows are really being delivered in sorted order, or
-** just in some other order that provides the required grouping. However,
-** if the WHERE_SORTBYGROUP flag is also passed to sqlite3WhereBegin(), then
-** this function may be called on the returned WhereInfo object. It returns
-** true if the rows really will be sorted in the specified order, or false
-** otherwise.
-**
-** For example, assuming:
-**
-** CREATE INDEX i1 ON t1(x, Y);
-**
-** then
-**
-** SELECT * FROM t1 GROUP BY x,y ORDER BY x,y; -- IsSorted()==1
-** SELECT * FROM t1 GROUP BY y,x ORDER BY y,x; -- IsSorted()==0
-*/
-int sqlite3WhereIsSorted(WhereInfo *pWInfo){
- assert( pWInfo->wctrlFlags & WHERE_GROUPBY );
- assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP );
- return pWInfo->sorted;
-}
-
-#ifdef WHERETRACE_ENABLED
-/* For debugging use only: */
-static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
- static char zName[65];
- int i;
- for(i=0; i<nLoop; i++){ zName[i] = pPath->aLoop[i]->cId; }
- if( pLast ) zName[i++] = pLast->cId;
- zName[i] = 0;
- return zName;
-}
-#endif
-
-/*
-** Return the cost of sorting nRow rows, assuming that the keys have
-** nOrderby columns and that the first nSorted columns are already in
-** order.
-*/
-static LogEst whereSortingCost(
- WhereInfo *pWInfo,
- LogEst nRow,
- int nOrderBy,
- int nSorted
-){
- /* TUNING: Estimated cost of a full external sort, where N is
- ** the number of rows to sort is:
- **
- ** cost = (3.0 * N * log(N)).
- **
- ** Or, if the order-by clause has X terms but only the last Y
- ** terms are out of order, then block-sorting will reduce the
- ** sorting cost to:
- **
- ** cost = (3.0 * N * log(N)) * (Y/X)
- **
- ** The (Y/X) term is implemented using stack variable rScale
- ** below. */
- LogEst rScale, rSortCost;
- assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
- rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
- rSortCost = nRow + rScale + 16;
-
- /* Multiple by log(M) where M is the number of output rows.
- ** Use the LIMIT for M if it is smaller */
- if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
- nRow = pWInfo->iLimit;
- }
- rSortCost += estLog(nRow);
- return rSortCost;
-}
-
-/*
-** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
-** attempts to find the lowest cost path that visits each WhereLoop
-** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
-**
-** Assume that the total number of output rows that will need to be sorted
-** will be nRowEst (in the 10*log2 representation). Or, ignore sorting
-** costs if nRowEst==0.
-**
-** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
-** error occurs.
-*/
-static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
- int mxChoice; /* Maximum number of simultaneous paths tracked */
- int nLoop; /* Number of terms in the join */
- Parse *pParse; /* Parsing context */
- sqlite3 *db; /* The database connection */
- int iLoop; /* Loop counter over the terms of the join */
- int ii, jj; /* Loop counters */
- int mxI = 0; /* Index of next entry to replace */
- int nOrderBy; /* Number of ORDER BY clause terms */
- LogEst mxCost = 0; /* Maximum cost of a set of paths */
- LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */
- int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
- WherePath *aFrom; /* All nFrom paths at the previous level */
- WherePath *aTo; /* The nTo best paths at the current level */
- WherePath *pFrom; /* An element of aFrom[] that we are working on */
- WherePath *pTo; /* An element of aTo[] that we are working on */
- WhereLoop *pWLoop; /* One of the WhereLoop objects */
- WhereLoop **pX; /* Used to divy up the pSpace memory */
- LogEst *aSortCost = 0; /* Sorting and partial sorting costs */
- char *pSpace; /* Temporary memory used by this routine */
- int nSpace; /* Bytes of space allocated at pSpace */
-
- pParse = pWInfo->pParse;
- db = pParse->db;
- nLoop = pWInfo->nLevel;
- /* TUNING: For simple queries, only the best path is tracked.
- ** For 2-way joins, the 5 best paths are followed.
- ** For joins of 3 or more tables, track the 10 best paths */
- mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
- assert( nLoop<=pWInfo->pTabList->nSrc );
- WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst));
-
- /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
- ** case the purpose of this call is to estimate the number of rows returned
- ** by the overall query. Once this estimate has been obtained, the caller
- ** will invoke this function a second time, passing the estimate as the
- ** nRowEst parameter. */
- if( pWInfo->pOrderBy==0 || nRowEst==0 ){
- nOrderBy = 0;
- }else{
- nOrderBy = pWInfo->pOrderBy->nExpr;
- }
-
- /* Allocate and initialize space for aTo, aFrom and aSortCost[] */
- nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
- nSpace += sizeof(LogEst) * nOrderBy;
- pSpace = sqlite3DbMallocRawNN(db, nSpace);
- if( pSpace==0 ) return SQLITE_NOMEM_BKPT;
- aTo = (WherePath*)pSpace;
- aFrom = aTo+mxChoice;
- memset(aFrom, 0, sizeof(aFrom[0]));
- pX = (WhereLoop**)(aFrom+mxChoice);
- for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
- pFrom->aLoop = pX;
- }
- if( nOrderBy ){
- /* If there is an ORDER BY clause and it is not being ignored, set up
- ** space for the aSortCost[] array. Each element of the aSortCost array
- ** is either zero - meaning it has not yet been initialized - or the
- ** cost of sorting nRowEst rows of data where the first X terms of
- ** the ORDER BY clause are already in order, where X is the array
- ** index. */
- aSortCost = (LogEst*)pX;
- memset(aSortCost, 0, sizeof(LogEst) * nOrderBy);
- }
- assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] );
- assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX );
-
- /* Seed the search with a single WherePath containing zero WhereLoops.
- **
- ** TUNING: Do not let the number of iterations go above 28. If the cost
- ** of computing an automatic index is not paid back within the first 28
- ** rows, then do not use the automatic index. */
- aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) );
- nFrom = 1;
- assert( aFrom[0].isOrdered==0 );
- if( nOrderBy ){
- /* If nLoop is zero, then there are no FROM terms in the query. Since
- ** in this case the query may return a maximum of one row, the results
- ** are already in the requested order. Set isOrdered to nOrderBy to
- ** indicate this. Or, if nLoop is greater than zero, set isOrdered to
- ** -1, indicating that the result set may or may not be ordered,
- ** depending on the loops added to the current plan. */
- aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy;
- }
-
- /* Compute successively longer WherePaths using the previous generation
- ** of WherePaths as the basis for the next. Keep track of the mxChoice
- ** best paths at each generation */
- for(iLoop=0; iLoop<nLoop; iLoop++){
- nTo = 0;
- for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
- for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
- LogEst nOut; /* Rows visited by (pFrom+pWLoop) */
- LogEst rCost; /* Cost of path (pFrom+pWLoop) */
- LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */
- i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */
- Bitmask maskNew; /* Mask of src visited by (..) */
- Bitmask revMask = 0; /* Mask of rev-order loops for (..) */
-
- if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
- if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
- if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){
- /* Do not use an automatic index if the this loop is expected
- ** to run less than 1.25 times. It is tempting to also exclude
- ** automatic index usage on an outer loop, but sometimes an automatic
- ** index is useful in the outer loop of a correlated subquery. */
- assert( 10==sqlite3LogEst(2) );
- continue;
- }
-
- /* At this point, pWLoop is a candidate to be the next loop.
- ** Compute its cost */
- rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
- rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
- nOut = pFrom->nRow + pWLoop->nOut;
- maskNew = pFrom->maskLoop | pWLoop->maskSelf;
- if( isOrdered<0 ){
- isOrdered = wherePathSatisfiesOrderBy(pWInfo,
- pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
- iLoop, pWLoop, &revMask);
- }else{
- revMask = pFrom->revLoop;
- }
- if( isOrdered>=0 && isOrdered<nOrderBy ){
- if( aSortCost[isOrdered]==0 ){
- aSortCost[isOrdered] = whereSortingCost(
- pWInfo, nRowEst, nOrderBy, isOrdered
- );
- }
- rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]);
-
- WHERETRACE(0x002,
- ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
- aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy,
- rUnsorted, rCost));
- }else{
- rCost = rUnsorted;
- rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */
- }
-
- /* Check to see if pWLoop should be added to the set of
- ** mxChoice best-so-far paths.
- **
- ** First look for an existing path among best-so-far paths
- ** that covers the same set of loops and has the same isOrdered
- ** setting as the current path candidate.
- **
- ** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
- ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
- ** of legal values for isOrdered, -1..64.
- */
- for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
- if( pTo->maskLoop==maskNew
- && ((pTo->isOrdered^isOrdered)&0x80)==0
- ){
- testcase( jj==nTo-1 );
- break;
- }
- }
- if( jj>=nTo ){
- /* None of the existing best-so-far paths match the candidate. */
- if( nTo>=mxChoice
- && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted))
- ){
- /* The current candidate is no better than any of the mxChoice
- ** paths currently in the best-so-far buffer. So discard
- ** this candidate as not viable. */
-#ifdef WHERETRACE_ENABLED /* 0x4 */
- if( sqlite3WhereTrace&0x4 ){
- sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
- isOrdered>=0 ? isOrdered+'0' : '?');
- }
-#endif
- continue;
- }
- /* If we reach this points it means that the new candidate path
- ** needs to be added to the set of best-so-far paths. */
- if( nTo<mxChoice ){
- /* Increase the size of the aTo set by one */
- jj = nTo++;
- }else{
- /* New path replaces the prior worst to keep count below mxChoice */
- jj = mxI;
- }
- pTo = &aTo[jj];
-#ifdef WHERETRACE_ENABLED /* 0x4 */
- if( sqlite3WhereTrace&0x4 ){
- sqlite3DebugPrintf("New %s cost=%-3d,%3d,%3d order=%c\n",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
- isOrdered>=0 ? isOrdered+'0' : '?');
- }
-#endif
- }else{
- /* Control reaches here if best-so-far path pTo=aTo[jj] covers the
- ** same set of loops and has the same isOrdered setting as the
- ** candidate path. Check to see if the candidate should replace
- ** pTo or if the candidate should be skipped.
- **
- ** The conditional is an expanded vector comparison equivalent to:
- ** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted)
- */
- if( pTo->rCost<rCost
- || (pTo->rCost==rCost
- && (pTo->nRow<nOut
- || (pTo->nRow==nOut && pTo->rUnsorted<=rUnsorted)
- )
- )
- ){
-#ifdef WHERETRACE_ENABLED /* 0x4 */
- if( sqlite3WhereTrace&0x4 ){
- sqlite3DebugPrintf(
- "Skip %s cost=%-3d,%3d,%3d order=%c",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
- isOrdered>=0 ? isOrdered+'0' : '?');
- sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n",
- wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
- }
-#endif
- /* Discard the candidate path from further consideration */
- testcase( pTo->rCost==rCost );
- continue;
- }
- testcase( pTo->rCost==rCost+1 );
- /* Control reaches here if the candidate path is better than the
- ** pTo path. Replace pTo with the candidate. */
-#ifdef WHERETRACE_ENABLED /* 0x4 */
- if( sqlite3WhereTrace&0x4 ){
- sqlite3DebugPrintf(
- "Update %s cost=%-3d,%3d,%3d order=%c",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
- isOrdered>=0 ? isOrdered+'0' : '?');
- sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n",
- wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
- }
-#endif
- }
- /* pWLoop is a winner. Add it to the set of best so far */
- pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
- pTo->revLoop = revMask;
- pTo->nRow = nOut;
- pTo->rCost = rCost;
- pTo->rUnsorted = rUnsorted;
- pTo->isOrdered = isOrdered;
- memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
- pTo->aLoop[iLoop] = pWLoop;
- if( nTo>=mxChoice ){
- mxI = 0;
- mxCost = aTo[0].rCost;
- mxUnsorted = aTo[0].nRow;
- for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
- if( pTo->rCost>mxCost
- || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted)
- ){
- mxCost = pTo->rCost;
- mxUnsorted = pTo->rUnsorted;
- mxI = jj;
- }
- }
- }
- }
- }
-
-#ifdef WHERETRACE_ENABLED /* >=2 */
- if( sqlite3WhereTrace & 0x02 ){
- sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
- for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
- sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
- wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
- if( pTo->isOrdered>0 ){
- sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
- }else{
- sqlite3DebugPrintf("\n");
- }
- }
- }
-#endif
-
- /* Swap the roles of aFrom and aTo for the next generation */
- pFrom = aTo;
- aTo = aFrom;
- aFrom = pFrom;
- nFrom = nTo;
- }
-
- if( nFrom==0 ){
- sqlite3ErrorMsg(pParse, "no query solution");
- sqlite3DbFreeNN(db, pSpace);
- return SQLITE_ERROR;
- }
-
- /* Find the lowest cost path. pFrom will be left pointing to that path */
- pFrom = aFrom;
- for(ii=1; ii<nFrom; ii++){
- if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
- }
- assert( pWInfo->nLevel==nLoop );
- /* Load the lowest cost path into pWInfo */
- for(iLoop=0; iLoop<nLoop; iLoop++){
- WhereLevel *pLevel = pWInfo->a + iLoop;
- pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop];
- pLevel->iFrom = pWLoop->iTab;
- pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
- }
- if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0
- && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
- && pWInfo->eDistinct==WHERE_DISTINCT_NOOP
- && nRowEst
- ){
- Bitmask notUsed;
- int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
- WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);
- if( rc==pWInfo->pResultSet->nExpr ){
- pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
- }
- }
- if( pWInfo->pOrderBy ){
- if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
- if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){
- pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
- }
- }else{
- pWInfo->nOBSat = pFrom->isOrdered;
- pWInfo->revMask = pFrom->revLoop;
- if( pWInfo->nOBSat<=0 ){
- pWInfo->nOBSat = 0;
- if( nLoop>0 ){
- u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags;
- if( (wsFlags & WHERE_ONEROW)==0
- && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN)
- ){
- Bitmask m = 0;
- int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
- WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
- testcase( wsFlags & WHERE_IPK );
- testcase( wsFlags & WHERE_COLUMN_IN );
- if( rc==pWInfo->pOrderBy->nExpr ){
- pWInfo->bOrderedInnerLoop = 1;
- pWInfo->revMask = m;
- }
- }
- }
- }
- }
- if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
- && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0
- ){
- Bitmask revMask = 0;
- int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy,
- pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &revMask
- );
- assert( pWInfo->sorted==0 );
- if( nOrder==pWInfo->pOrderBy->nExpr ){
- pWInfo->sorted = 1;
- pWInfo->revMask = revMask;
- }
- }
- }
-
-
- pWInfo->nRowOut = pFrom->nRow;
-
- /* Free temporary memory and return success */
- sqlite3DbFreeNN(db, pSpace);
- return SQLITE_OK;
-}
-
-/*
-** Most queries use only a single table (they are not joins) and have
-** simple == constraints against indexed fields. This routine attempts
-** to plan those simple cases using much less ceremony than the
-** general-purpose query planner, and thereby yield faster sqlite3_prepare()
-** times for the common case.
-**
-** Return non-zero on success, if this query can be handled by this
-** no-frills query planner. Return zero if this query needs the
-** general-purpose query planner.
-*/
-static int whereShortCut(WhereLoopBuilder *pBuilder){
- WhereInfo *pWInfo;
- struct SrcList_item *pItem;
- WhereClause *pWC;
- WhereTerm *pTerm;
- WhereLoop *pLoop;
- int iCur;
- int j;
- Table *pTab;
- Index *pIdx;
-
- pWInfo = pBuilder->pWInfo;
- if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0;
- assert( pWInfo->pTabList->nSrc>=1 );
- pItem = pWInfo->pTabList->a;
- pTab = pItem->pTab;
- if( IsVirtual(pTab) ) return 0;
- if( pItem->fg.isIndexedBy ) return 0;
- iCur = pItem->iCursor;
- pWC = &pWInfo->sWC;
- pLoop = pBuilder->pNew;
- pLoop->wsFlags = 0;
- pLoop->nSkip = 0;
- pTerm = sqlite3WhereFindTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0);
- if( pTerm ){
- testcase( pTerm->eOperator & WO_IS );
- pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
- pLoop->aLTerm[0] = pTerm;
- pLoop->nLTerm = 1;
- pLoop->u.btree.nEq = 1;
- /* TUNING: Cost of a rowid lookup is 10 */
- pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
- }else{
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int opMask;
- assert( pLoop->aLTermSpace==pLoop->aLTerm );
- if( !IsUniqueIndex(pIdx)
- || pIdx->pPartIdxWhere!=0
- || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace)
- ) continue;
- opMask = pIdx->uniqNotNull ? (WO_EQ|WO_IS) : WO_EQ;
- for(j=0; j<pIdx->nKeyCol; j++){
- pTerm = sqlite3WhereFindTerm(pWC, iCur, j, 0, opMask, pIdx);
- if( pTerm==0 ) break;
- testcase( pTerm->eOperator & WO_IS );
- pLoop->aLTerm[j] = pTerm;
- }
- if( j!=pIdx->nKeyCol ) continue;
- pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
- if( pIdx->isCovering || (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){
- pLoop->wsFlags |= WHERE_IDX_ONLY;
- }
- pLoop->nLTerm = j;
- pLoop->u.btree.nEq = j;
- pLoop->u.btree.pIndex = pIdx;
- /* TUNING: Cost of a unique index lookup is 15 */
- pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
- break;
- }
- }
- if( pLoop->wsFlags ){
- pLoop->nOut = (LogEst)1;
- pWInfo->a[0].pWLoop = pLoop;
- assert( pWInfo->sMaskSet.n==1 && iCur==pWInfo->sMaskSet.ix[0] );
- pLoop->maskSelf = 1; /* sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); */
- pWInfo->a[0].iTabCur = iCur;
- pWInfo->nRowOut = 1;
- if( pWInfo->pOrderBy ) pWInfo->nOBSat = pWInfo->pOrderBy->nExpr;
- if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
- pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
- }
-#ifdef SQLITE_DEBUG
- pLoop->cId = '0';
-#endif
- return 1;
- }
- return 0;
-}
-
-/*
-** Helper function for exprIsDeterministic().
-*/
-static int exprNodeIsDeterministic(Walker *pWalker, Expr *pExpr){
- if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_ConstFunc)==0 ){
- pWalker->eCode = 0;
- return WRC_Abort;
- }
- return WRC_Continue;
-}
-
-/*
-** Return true if the expression contains no non-deterministic SQL
-** functions. Do not consider non-deterministic SQL functions that are
-** part of sub-select statements.
-*/
-static int exprIsDeterministic(Expr *p){
- Walker w;
- memset(&w, 0, sizeof(w));
- w.eCode = 1;
- w.xExprCallback = exprNodeIsDeterministic;
- w.xSelectCallback = sqlite3SelectWalkFail;
- sqlite3WalkExpr(&w, p);
- return w.eCode;
-}
-
-/*
-** Generate the beginning of the loop used for WHERE clause processing.
-** The return value is a pointer to an opaque structure that contains
-** information needed to terminate the loop. Later, the calling routine
-** should invoke sqlite3WhereEnd() with the return value of this function
-** in order to complete the WHERE clause processing.
-**
-** If an error occurs, this routine returns NULL.
-**
-** The basic idea is to do a nested loop, one loop for each table in
-** the FROM clause of a select. (INSERT and UPDATE statements are the
-** same as a SELECT with only a single table in the FROM clause.) For
-** example, if the SQL is this:
-**
-** SELECT * FROM t1, t2, t3 WHERE ...;
-**
-** Then the code generated is conceptually like the following:
-**
-** foreach row1 in t1 do \ Code generated
-** foreach row2 in t2 do |-- by sqlite3WhereBegin()
-** foreach row3 in t3 do /
-** ...
-** end \ Code generated
-** end |-- by sqlite3WhereEnd()
-** end /
-**
-** Note that the loops might not be nested in the order in which they
-** appear in the FROM clause if a different order is better able to make
-** use of indices. Note also that when the IN operator appears in
-** the WHERE clause, it might result in additional nested loops for
-** scanning through all values on the right-hand side of the IN.
-**
-** There are Btree cursors associated with each table. t1 uses cursor
-** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor.
-** And so forth. This routine generates code to open those VDBE cursors
-** and sqlite3WhereEnd() generates the code to close them.
-**
-** The code that sqlite3WhereBegin() generates leaves the cursors named
-** in pTabList pointing at their appropriate entries. The [...] code
-** can use OP_Column and OP_Rowid opcodes on these cursors to extract
-** data from the various tables of the loop.
-**
-** If the WHERE clause is empty, the foreach loops must each scan their
-** entire tables. Thus a three-way join is an O(N^3) operation. But if
-** the tables have indices and there are terms in the WHERE clause that
-** refer to those indices, a complete table scan can be avoided and the
-** code will run much faster. Most of the work of this routine is checking
-** to see if there are indices that can be used to speed up the loop.
-**
-** Terms of the WHERE clause are also used to limit which rows actually
-** make it to the "..." in the middle of the loop. After each "foreach",
-** terms of the WHERE clause that use only terms in that loop and outer
-** loops are evaluated and if false a jump is made around all subsequent
-** inner loops (or around the "..." if the test occurs within the inner-
-** most loop)
-**
-** OUTER JOINS
-**
-** An outer join of tables t1 and t2 is conceptally coded as follows:
-**
-** foreach row1 in t1 do
-** flag = 0
-** foreach row2 in t2 do
-** start:
-** ...
-** flag = 1
-** end
-** if flag==0 then
-** move the row2 cursor to a null row
-** goto start
-** fi
-** end
-**
-** ORDER BY CLAUSE PROCESSING
-**
-** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause
-** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement
-** if there is one. If there is no ORDER BY clause or if this routine
-** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
-**
-** The iIdxCur parameter is the cursor number of an index. If
-** WHERE_OR_SUBCLAUSE is set, iIdxCur is the cursor number of an index
-** to use for OR clause processing. The WHERE clause should use this
-** specific cursor. If WHERE_ONEPASS_DESIRED is set, then iIdxCur is
-** the first cursor in an array of cursors for all indices. iIdxCur should
-** be used to compute the appropriate cursor depending on which index is
-** used.
-*/
-WhereInfo *sqlite3WhereBegin(
- Parse *pParse, /* The parser context */
- SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
- Expr *pWhere, /* The WHERE clause */
- ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
- ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */
- u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
- int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number
- ** If WHERE_USE_LIMIT, then the limit amount */
-){
- int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
- int nTabList; /* Number of elements in pTabList */
- WhereInfo *pWInfo; /* Will become the return value of this function */
- Vdbe *v = pParse->pVdbe; /* The virtual database engine */
- Bitmask notReady; /* Cursors that are not yet positioned */
- WhereLoopBuilder sWLB; /* The WhereLoop builder */
- WhereMaskSet *pMaskSet; /* The expression mask set */
- WhereLevel *pLevel; /* A single level in pWInfo->a[] */
- WhereLoop *pLoop; /* Pointer to a single WhereLoop object */
- int ii; /* Loop counter */
- sqlite3 *db; /* Database connection */
- int rc; /* Return code */
- u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */
-
- assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || (
- (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
- && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
- ));
-
- /* Only one of WHERE_OR_SUBCLAUSE or WHERE_USE_LIMIT */
- assert( (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
- || (wctrlFlags & WHERE_USE_LIMIT)==0 );
-
- /* Variable initialization */
- db = pParse->db;
- memset(&sWLB, 0, sizeof(sWLB));
-
- /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
- testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
- if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
- sWLB.pOrderBy = pOrderBy;
-
- /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
- ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
- if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
- wctrlFlags &= ~WHERE_WANT_DISTINCT;
- }
-
- /* The number of tables in the FROM clause is limited by the number of
- ** bits in a Bitmask
- */
- testcase( pTabList->nSrc==BMS );
- if( pTabList->nSrc>BMS ){
- sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
- return 0;
- }
-
- /* This function normally generates a nested loop for all tables in
- ** pTabList. But if the WHERE_OR_SUBCLAUSE flag is set, then we should
- ** only generate code for the first table in pTabList and assume that
- ** any cursors associated with subsequent tables are uninitialized.
- */
- nTabList = (wctrlFlags & WHERE_OR_SUBCLAUSE) ? 1 : pTabList->nSrc;
-
- /* Allocate and initialize the WhereInfo structure that will become the
- ** return value. A single allocation is used to store the WhereInfo
- ** struct, the contents of WhereInfo.a[], the WhereClause structure
- ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
- ** field (type Bitmask) it must be aligned on an 8-byte boundary on
- ** some architectures. Hence the ROUND8() below.
- */
- nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
- pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
- if( db->mallocFailed ){
- sqlite3DbFree(db, pWInfo);
- pWInfo = 0;
- goto whereBeginError;
- }
- pWInfo->pParse = pParse;
- pWInfo->pTabList = pTabList;
- pWInfo->pOrderBy = pOrderBy;
- pWInfo->pWhere = pWhere;
- pWInfo->pResultSet = pResultSet;
- pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
- pWInfo->nLevel = nTabList;
- pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
- pWInfo->wctrlFlags = wctrlFlags;
- pWInfo->iLimit = iAuxArg;
- pWInfo->savedNQueryLoop = pParse->nQueryLoop;
- memset(&pWInfo->nOBSat, 0,
- offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
- memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
- assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
- pMaskSet = &pWInfo->sMaskSet;
- sWLB.pWInfo = pWInfo;
- sWLB.pWC = &pWInfo->sWC;
- sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
- assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
- whereLoopInit(sWLB.pNew);
-#ifdef SQLITE_DEBUG
- sWLB.pNew->cId = '*';
-#endif
-
- /* Split the WHERE clause into separate subexpressions where each
- ** subexpression is separated by an AND operator.
- */
- initMaskSet(pMaskSet);
- sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo);
- sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND);
-
- /* Special case: No FROM clause
- */
- if( nTabList==0 ){
- if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
- if( wctrlFlags & WHERE_WANT_DISTINCT ){
- pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
- }
- ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
- }else{
- /* Assign a bit from the bitmask to every term in the FROM clause.
- **
- ** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
- **
- ** The rule of the previous sentence ensures thta if X is the bitmask for
- ** a table T, then X-1 is the bitmask for all other tables to the left of T.
- ** Knowing the bitmask for all tables to the left of a left join is
- ** important. Ticket #3015.
- **
- ** Note that bitmasks are created for all pTabList->nSrc tables in
- ** pTabList, not just the first nTabList tables. nTabList is normally
- ** equal to pTabList->nSrc but might be shortened to 1 if the
- ** WHERE_OR_SUBCLAUSE flag is set.
- */
- ii = 0;
- do{
- createMask(pMaskSet, pTabList->a[ii].iCursor);
- sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
- }while( (++ii)<pTabList->nSrc );
- #ifdef SQLITE_DEBUG
- {
- Bitmask mx = 0;
- for(ii=0; ii<pTabList->nSrc; ii++){
- Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor);
- assert( m>=mx );
- mx = m;
- }
- }
- #endif
- }
-
- /* Analyze all of the subexpressions. */
- sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
- if( db->mallocFailed ) goto whereBeginError;
-
- /* Special case: WHERE terms that do not refer to any tables in the join
- ** (constant expressions). Evaluate each such term, and jump over all the
- ** generated code if the result is not true.
- **
- ** Do not do this if the expression contains non-deterministic functions
- ** that are not within a sub-select. This is not strictly required, but
- ** preserves SQLite's legacy behaviour in the following two cases:
- **
- ** FROM ... WHERE random()>0; -- eval random() once per row
- ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall
- */
- for(ii=0; ii<sWLB.pWC->nTerm; ii++){
- WhereTerm *pT = &sWLB.pWC->a[ii];
- if( pT->wtFlags & TERM_VIRTUAL ) continue;
- if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){
- sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL);
- pT->wtFlags |= TERM_CODED;
- }
- }
-
- if( wctrlFlags & WHERE_WANT_DISTINCT ){
- if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
- /* The DISTINCT marking is pointless. Ignore it. */
- pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
- }else if( pOrderBy==0 ){
- /* Try to ORDER BY the result set to make distinct processing easier */
- pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
- pWInfo->pOrderBy = pResultSet;
- }
- }
-
- /* Construct the WhereLoop objects */
-#if defined(WHERETRACE_ENABLED)
- if( sqlite3WhereTrace & 0xffff ){
- sqlite3DebugPrintf("*** Optimizer Start *** (wctrlFlags: 0x%x",wctrlFlags);
- if( wctrlFlags & WHERE_USE_LIMIT ){
- sqlite3DebugPrintf(", limit: %d", iAuxArg);
- }
- sqlite3DebugPrintf(")\n");
- }
- if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
- sqlite3WhereClausePrint(sWLB.pWC);
- }
-#endif
-
- if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
- rc = whereLoopAddAll(&sWLB);
- if( rc ) goto whereBeginError;
-
-#ifdef WHERETRACE_ENABLED
- if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */
- WhereLoop *p;
- int i;
- static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
- "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
- for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
- p->cId = zLabel[i%(sizeof(zLabel)-1)];
- whereLoopPrint(p, sWLB.pWC);
- }
- }
-#endif
-
- wherePathSolver(pWInfo, 0);
- if( db->mallocFailed ) goto whereBeginError;
- if( pWInfo->pOrderBy ){
- wherePathSolver(pWInfo, pWInfo->nRowOut+1);
- if( db->mallocFailed ) goto whereBeginError;
- }
- }
- if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
- pWInfo->revMask = ALLBITS;
- }
- if( pParse->nErr || NEVER(db->mallocFailed) ){
- goto whereBeginError;
- }
-#ifdef WHERETRACE_ENABLED
- if( sqlite3WhereTrace ){
- sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
- if( pWInfo->nOBSat>0 ){
- sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask);
- }
- switch( pWInfo->eDistinct ){
- case WHERE_DISTINCT_UNIQUE: {
- sqlite3DebugPrintf(" DISTINCT=unique");
- break;
- }
- case WHERE_DISTINCT_ORDERED: {
- sqlite3DebugPrintf(" DISTINCT=ordered");
- break;
- }
- case WHERE_DISTINCT_UNORDERED: {
- sqlite3DebugPrintf(" DISTINCT=unordered");
- break;
- }
- }
- sqlite3DebugPrintf("\n");
- for(ii=0; ii<pWInfo->nLevel; ii++){
- whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
- }
- }
-#endif
-
- /* Attempt to omit tables from the join that do not affect the result.
- ** For a table to not affect the result, the following must be true:
- **
- ** 1) The query must not be an aggregate.
- ** 2) The table must be the RHS of a LEFT JOIN.
- ** 3) Either the query must be DISTINCT, or else the ON or USING clause
- ** must contain a constraint that limits the scan of the table to
- ** at most a single row.
- ** 4) The table must not be referenced by any part of the query apart
- ** from its own USING or ON clause.
- **
- ** For example, given:
- **
- ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
- ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
- ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3);
- **
- ** then table t2 can be omitted from the following:
- **
- ** SELECT v1, v3 FROM t1
- ** LEFT JOIN t2 USING (t1.ipk=t2.ipk)
- ** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
- **
- ** or from:
- **
- ** SELECT DISTINCT v1, v3 FROM t1
- ** LEFT JOIN t2
- ** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
- */
- notReady = ~(Bitmask)0;
- if( pWInfo->nLevel>=2
- && pResultSet!=0 /* guarantees condition (1) above */
- && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
- ){
- int i;
- Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
- if( sWLB.pOrderBy ){
- tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
- }
- for(i=pWInfo->nLevel-1; i>=1; i--){
- WhereTerm *pTerm, *pEnd;
- struct SrcList_item *pItem;
- pLoop = pWInfo->a[i].pWLoop;
- pItem = &pWInfo->pTabList->a[pLoop->iTab];
- if( (pItem->fg.jointype & JT_LEFT)==0 ) continue;
- if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
- && (pLoop->wsFlags & WHERE_ONEROW)==0
- ){
- continue;
- }
- if( (tabUsed & pLoop->maskSelf)!=0 ) continue;
- pEnd = sWLB.pWC->a + sWLB.pWC->nTerm;
- for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
- if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
- if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- || pTerm->pExpr->iRightJoinTable!=pItem->iCursor
- ){
- break;
- }
- }
- }
- if( pTerm<pEnd ) continue;
- WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
- notReady &= ~pLoop->maskSelf;
- for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
- if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
- pTerm->wtFlags |= TERM_CODED;
- }
- }
- if( i!=pWInfo->nLevel-1 ){
- int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
- memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
- }
- pWInfo->nLevel--;
- nTabList--;
- }
- }
- WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
- pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
-
- /* If the caller is an UPDATE or DELETE statement that is requesting
- ** to use a one-pass algorithm, determine if this is appropriate.
- **
- ** A one-pass approach can be used if the caller has requested one
- ** and either (a) the scan visits at most one row or (b) each
- ** of the following are true:
- **
- ** * the caller has indicated that a one-pass approach can be used
- ** with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and
- ** * the table is not a virtual table, and
- ** * either the scan does not use the OR optimization or the caller
- ** is a DELETE operation (WHERE_DUPLICATES_OK is only specified
- ** for DELETE).
- **
- ** The last qualification is because an UPDATE statement uses
- ** WhereInfo.aiCurOnePass[1] to determine whether or not it really can
- ** use a one-pass approach, and this is not set accurately for scans
- ** that use the OR optimization.
- */
- assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
- if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
- int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
- int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
- if( bOnerow || (
- 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW)
- && 0==(wsFlags & WHERE_VIRTUALTABLE)
- && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK))
- )){
- pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
- if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
- if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
- bFordelete = OPFLAG_FORDELETE;
- }
- pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY);
- }
- }
- }
-
- /* Open all tables in the pTabList and any indices selected for
- ** searching those tables.
- */
- for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
- Table *pTab; /* Table to open */
- int iDb; /* Index of database containing table/index */
- struct SrcList_item *pTabItem;
-
- pTabItem = &pTabList->a[pLevel->iFrom];
- pTab = pTabItem->pTab;
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- pLoop = pLevel->pWLoop;
- if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
- /* Do nothing */
- }else
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
- const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
- int iCur = pTabItem->iCursor;
- sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
- }else if( IsVirtual(pTab) ){
- /* noop */
- }else
-#endif
- if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
- && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
- int op = OP_OpenRead;
- if( pWInfo->eOnePass!=ONEPASS_OFF ){
- op = OP_OpenWrite;
- pWInfo->aiCurOnePass[0] = pTabItem->iCursor;
- };
- sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
- assert( pTabItem->iCursor==pLevel->iTabCur );
- testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 );
- testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS );
- if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){
- Bitmask b = pTabItem->colUsed;
- int n = 0;
- for(; b; b=b>>1, n++){}
- sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32);
- assert( n<=pTab->nCol );
- }
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
- if( pLoop->u.btree.pIndex!=0 ){
- sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete);
- }else
-#endif
- {
- sqlite3VdbeChangeP5(v, bFordelete);
- }
-#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
- sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0,
- (const u8*)&pTabItem->colUsed, P4_INT64);
-#endif
- }else{
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
- }
- if( pLoop->wsFlags & WHERE_INDEXED ){
- Index *pIx = pLoop->u.btree.pIndex;
- int iIndexCur;
- int op = OP_OpenRead;
- /* iAuxArg is always set to a positive value if ONEPASS is possible */
- assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
- if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx)
- && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0
- ){
- /* This is one term of an OR-optimization using the PRIMARY KEY of a
- ** WITHOUT ROWID table. No need for a separate index */
- iIndexCur = pLevel->iTabCur;
- op = 0;
- }else if( pWInfo->eOnePass!=ONEPASS_OFF ){
- Index *pJ = pTabItem->pTab->pIndex;
- iIndexCur = iAuxArg;
- assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
- while( ALWAYS(pJ) && pJ!=pIx ){
- iIndexCur++;
- pJ = pJ->pNext;
- }
- op = OP_OpenWrite;
- pWInfo->aiCurOnePass[1] = iIndexCur;
- }else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){
- iIndexCur = iAuxArg;
- op = OP_ReopenIdx;
- }else{
- iIndexCur = pParse->nTab++;
- }
- pLevel->iIdxCur = iIndexCur;
- assert( pIx->pSchema==pTab->pSchema );
- assert( iIndexCur>=0 );
- if( op ){
- sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
- sqlite3VdbeSetP4KeyInfo(pParse, pIx);
- if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
- && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
- && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
- && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
- ){
- sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
- }
- VdbeComment((v, "%s", pIx->zName));
-#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
- {
- u64 colUsed = 0;
- int ii, jj;
- for(ii=0; ii<pIx->nColumn; ii++){
- jj = pIx->aiColumn[ii];
- if( jj<0 ) continue;
- if( jj>63 ) jj = 63;
- if( (pTabItem->colUsed & MASKBIT(jj))==0 ) continue;
- colUsed |= ((u64)1)<<(ii<63 ? ii : 63);
- }
- sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0,
- (u8*)&colUsed, P4_INT64);
- }
-#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */
- }
- }
- if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
- }
- pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
- if( db->mallocFailed ) goto whereBeginError;
-
- /* Generate the code to do the search. Each iteration of the for
- ** loop below generates code for a single nested loop of the VM
- ** program.
- */
- for(ii=0; ii<nTabList; ii++){
- int addrExplain;
- int wsFlags;
- pLevel = &pWInfo->a[ii];
- wsFlags = pLevel->pWLoop->wsFlags;
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
- if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
- constructAutomaticIndex(pParse, &pWInfo->sWC,
- &pTabList->a[pLevel->iFrom], notReady, pLevel);
- if( db->mallocFailed ) goto whereBeginError;
- }
-#endif
- addrExplain = sqlite3WhereExplainOneScan(
- pParse, pTabList, pLevel, wctrlFlags
- );
- pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
- notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady);
- pWInfo->iContinue = pLevel->addrCont;
- if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){
- sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain);
- }
- }
-
- /* Done. */
- VdbeModuleComment((v, "Begin WHERE-core"));
- return pWInfo;
-
- /* Jump here if malloc fails */
-whereBeginError:
- if( pWInfo ){
- pParse->nQueryLoop = pWInfo->savedNQueryLoop;
- whereInfoFree(db, pWInfo);
- }
- return 0;
-}
-
-/*
-** Generate the end of the WHERE loop. See comments on
-** sqlite3WhereBegin() for additional information.
-*/
-void sqlite3WhereEnd(WhereInfo *pWInfo){
- Parse *pParse = pWInfo->pParse;
- Vdbe *v = pParse->pVdbe;
- int i;
- WhereLevel *pLevel;
- WhereLoop *pLoop;
- SrcList *pTabList = pWInfo->pTabList;
- sqlite3 *db = pParse->db;
-
- /* Generate loop termination code.
- */
- VdbeModuleComment((v, "End WHERE-core"));
- sqlite3ExprCacheClear(pParse);
- for(i=pWInfo->nLevel-1; i>=0; i--){
- int addr;
- pLevel = &pWInfo->a[i];
- pLoop = pLevel->pWLoop;
- if( pLevel->op!=OP_Noop ){
-#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
- int addrSeek = 0;
- Index *pIdx;
- int n;
- if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
- && i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */
- && (pLoop->wsFlags & WHERE_INDEXED)!=0
- && (pIdx = pLoop->u.btree.pIndex)->hasStat1
- && (n = pLoop->u.btree.nIdxCol)>0
- && pIdx->aiRowLogEst[n]>=36
- ){
- int r1 = pParse->nMem+1;
- int j, op;
- for(j=0; j<n; j++){
- sqlite3VdbeAddOp3(v, OP_Column, pLevel->iIdxCur, j, r1+j);
- }
- pParse->nMem += n+1;
- op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT;
- addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
- VdbeCoverageIf(v, op==OP_SeekLT);
- VdbeCoverageIf(v, op==OP_SeekGT);
- sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
- }
-#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
- /* The common case: Advance to the next row */
- sqlite3VdbeResolveLabel(v, pLevel->addrCont);
- sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
- sqlite3VdbeChangeP5(v, pLevel->p5);
- VdbeCoverage(v);
- VdbeCoverageIf(v, pLevel->op==OP_Next);
- VdbeCoverageIf(v, pLevel->op==OP_Prev);
- VdbeCoverageIf(v, pLevel->op==OP_VNext);
-#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
- if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
-#endif
- }else{
- sqlite3VdbeResolveLabel(v, pLevel->addrCont);
- }
- if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
- struct InLoop *pIn;
- int j;
- sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
- for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
- sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
- if( pIn->eEndLoopOp!=OP_Noop ){
- sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
- VdbeCoverage(v);
- VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
- VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
- }
- sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
- }
- }
- sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
- if( pLevel->addrSkip ){
- sqlite3VdbeGoto(v, pLevel->addrSkip);
- VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
- sqlite3VdbeJumpHere(v, pLevel->addrSkip);
- sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
- }
-#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- if( pLevel->addrLikeRep ){
- sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1),
- pLevel->addrLikeRep);
- VdbeCoverage(v);
- }
-#endif
- if( pLevel->iLeftJoin ){
- int ws = pLoop->wsFlags;
- addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
- assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
- if( (ws & WHERE_IDX_ONLY)==0 ){
- assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
- sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
- }
- if( (ws & WHERE_INDEXED)
- || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
- ){
- sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
- }
- if( pLevel->op==OP_Return ){
- sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
- }else{
- sqlite3VdbeGoto(v, pLevel->addrFirst);
- }
- sqlite3VdbeJumpHere(v, addr);
- }
- VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
- pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
- }
-
- /* The "break" point is here, just past the end of the outer loop.
- ** Set it.
- */
- sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
-
- assert( pWInfo->nLevel<=pTabList->nSrc );
- for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
- int k, last;
- VdbeOp *pOp;
- Index *pIdx = 0;
- struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
- Table *pTab = pTabItem->pTab;
- assert( pTab!=0 );
- pLoop = pLevel->pWLoop;
-
- /* For a co-routine, change all OP_Column references to the table of
- ** the co-routine into OP_Copy of result contained in a register.
- ** OP_Rowid becomes OP_Null.
- */
- if( pTabItem->fg.viaCoroutine ){
- testcase( pParse->db->mallocFailed );
- translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
- pTabItem->regResult, 0);
- continue;
- }
-
- /* If this scan uses an index, make VDBE code substitutions to read data
- ** from the index instead of from the table where possible. In some cases
- ** this optimization prevents the table from ever being read, which can
- ** yield a significant performance boost.
- **
- ** Calls to the code generator in between sqlite3WhereBegin and
- ** sqlite3WhereEnd will have created code that references the table
- ** directly. This loop scans all that code looking for opcodes
- ** that reference the table and converts them into opcodes that
- ** reference the index.
- */
- if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
- pIdx = pLoop->u.btree.pIndex;
- }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
- pIdx = pLevel->u.pCovidx;
- }
- if( pIdx
- && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
- && !db->mallocFailed
- ){
- last = sqlite3VdbeCurrentAddr(v);
- k = pLevel->addrBody;
- pOp = sqlite3VdbeGetOp(v, k);
- for(; k<last; k++, pOp++){
- if( pOp->p1!=pLevel->iTabCur ) continue;
- if( pOp->opcode==OP_Column
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
- || pOp->opcode==OP_Offset
-#endif
- ){
- int x = pOp->p2;
- assert( pIdx->pTable==pTab );
- if( !HasRowid(pTab) ){
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- x = pPk->aiColumn[x];
- assert( x>=0 );
- }
- x = sqlite3ColumnOfIndex(pIdx, x);
- if( x>=0 ){
- pOp->p2 = x;
- pOp->p1 = pLevel->iIdxCur;
- }
- assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0
- || pWInfo->eOnePass );
- }else if( pOp->opcode==OP_Rowid ){
- pOp->p1 = pLevel->iIdxCur;
- pOp->opcode = OP_IdxRowid;
- }else if( pOp->opcode==OP_IfNullRow ){
- pOp->p1 = pLevel->iIdxCur;
- }
- }
- }
- }
-
- /* Final cleanup
- */
- pParse->nQueryLoop = pWInfo->savedNQueryLoop;
- whereInfoFree(db, pWInfo);
- return;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/whereInt.h b/chromium/third_party/sqlite/sqlite-src-3240000/src/whereInt.h
deleted file mode 100644
index 4b6213af31e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/whereInt.h
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
-** 2013-11-12
-**
-** 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 contains structure and macro definitions for the query
-** planner logic in "where.c". These definitions are broken out into
-** a separate source file for easier editing.
-*/
-
-/*
-** Trace output macros
-*/
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ extern int sqlite3WhereTrace;
-#endif
-#if defined(SQLITE_DEBUG) \
- && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
-# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
-# define WHERETRACE_ENABLED 1
-#else
-# define WHERETRACE(K,X)
-#endif
-
-/* Forward references
-*/
-typedef struct WhereClause WhereClause;
-typedef struct WhereMaskSet WhereMaskSet;
-typedef struct WhereOrInfo WhereOrInfo;
-typedef struct WhereAndInfo WhereAndInfo;
-typedef struct WhereLevel WhereLevel;
-typedef struct WhereLoop WhereLoop;
-typedef struct WherePath WherePath;
-typedef struct WhereTerm WhereTerm;
-typedef struct WhereLoopBuilder WhereLoopBuilder;
-typedef struct WhereScan WhereScan;
-typedef struct WhereOrCost WhereOrCost;
-typedef struct WhereOrSet WhereOrSet;
-
-/*
-** This object contains information needed to implement a single nested
-** loop in WHERE clause.
-**
-** Contrast this object with WhereLoop. This object describes the
-** implementation of the loop. WhereLoop describes the algorithm.
-** This object contains a pointer to the WhereLoop algorithm as one of
-** its elements.
-**
-** The WhereInfo object contains a single instance of this object for
-** each term in the FROM clause (which is to say, for each of the
-** nested loops as implemented). The order of WhereLevel objects determines
-** the loop nested order, with WhereInfo.a[0] being the outer loop and
-** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop.
-*/
-struct WhereLevel {
- int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
- int iTabCur; /* The VDBE cursor used to access the table */
- int iIdxCur; /* The VDBE cursor used to access pIdx */
- int addrBrk; /* Jump here to break out of the loop */
- int addrNxt; /* Jump here to start the next IN combination */
- int addrSkip; /* Jump here for next iteration of skip-scan */
- int addrCont; /* Jump here to continue with the next loop cycle */
- int addrFirst; /* First instruction of interior of the loop */
- int addrBody; /* Beginning of the body of this loop */
-#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
- int addrLikeRep; /* LIKE range processing address */
-#endif
- u8 iFrom; /* Which entry in the FROM clause */
- u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
- int p1, p2; /* Operands of the opcode used to ends the loop */
- union { /* Information that depends on pWLoop->wsFlags */
- struct {
- int nIn; /* Number of entries in aInLoop[] */
- struct InLoop {
- int iCur; /* The VDBE cursor used by this IN operator */
- int addrInTop; /* Top of the IN loop */
- u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
- } *aInLoop; /* Information about each nested IN operator */
- } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
- Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
- } u;
- struct WhereLoop *pWLoop; /* The selected WhereLoop object */
- Bitmask notReady; /* FROM entries not usable at this level */
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- int addrVisit; /* Address at which row is visited */
-#endif
-};
-
-/*
-** Each instance of this object represents an algorithm for evaluating one
-** term of a join. Every term of the FROM clause will have at least
-** one corresponding WhereLoop object (unless INDEXED BY constraints
-** prevent a query solution - which is an error) and many terms of the
-** FROM clause will have multiple WhereLoop objects, each describing a
-** potential way of implementing that FROM-clause term, together with
-** dependencies and cost estimates for using the chosen algorithm.
-**
-** Query planning consists of building up a collection of these WhereLoop
-** objects, then computing a particular sequence of WhereLoop objects, with
-** one WhereLoop object per FROM clause term, that satisfy all dependencies
-** and that minimize the overall cost.
-*/
-struct WhereLoop {
- Bitmask prereq; /* Bitmask of other loops that must run first */
- Bitmask maskSelf; /* Bitmask identifying table iTab */
-#ifdef SQLITE_DEBUG
- char cId; /* Symbolic ID of this loop for debugging use */
-#endif
- u8 iTab; /* Position in FROM clause of table for this loop */
- u8 iSortIdx; /* Sorting index number. 0==None */
- LogEst rSetup; /* One-time setup cost (ex: create transient index) */
- LogEst rRun; /* Cost of running each loop */
- LogEst nOut; /* Estimated number of output rows */
- union {
- struct { /* Information for internal btree tables */
- u16 nEq; /* Number of equality constraints */
- u16 nBtm; /* Size of BTM vector */
- u16 nTop; /* Size of TOP vector */
- u16 nIdxCol; /* Index column used for ORDER BY */
- Index *pIndex; /* Index used, or NULL */
- } btree;
- struct { /* Information for virtual tables */
- int idxNum; /* Index number */
- u8 needFree; /* True if sqlite3_free(idxStr) is needed */
- i8 isOrdered; /* True if satisfies ORDER BY */
- u16 omitMask; /* Terms that may be omitted */
- char *idxStr; /* Index identifier string */
- } vtab;
- } u;
- u32 wsFlags; /* WHERE_* flags describing the plan */
- u16 nLTerm; /* Number of entries in aLTerm[] */
- u16 nSkip; /* Number of NULL aLTerm[] entries */
- /**** whereLoopXfer() copies fields above ***********************/
-# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
- u16 nLSlot; /* Number of slots allocated for aLTerm[] */
- WhereTerm **aLTerm; /* WhereTerms used */
- WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
- WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */
-};
-
-/* This object holds the prerequisites and the cost of running a
-** subquery on one operand of an OR operator in the WHERE clause.
-** See WhereOrSet for additional information
-*/
-struct WhereOrCost {
- Bitmask prereq; /* Prerequisites */
- LogEst rRun; /* Cost of running this subquery */
- LogEst nOut; /* Number of outputs for this subquery */
-};
-
-/* The WhereOrSet object holds a set of possible WhereOrCosts that
-** correspond to the subquery(s) of OR-clause processing. Only the
-** best N_OR_COST elements are retained.
-*/
-#define N_OR_COST 3
-struct WhereOrSet {
- u16 n; /* Number of valid a[] entries */
- WhereOrCost a[N_OR_COST]; /* Set of best costs */
-};
-
-/*
-** Each instance of this object holds a sequence of WhereLoop objects
-** that implement some or all of a query plan.
-**
-** Think of each WhereLoop object as a node in a graph with arcs
-** showing dependencies and costs for travelling between nodes. (That is
-** not a completely accurate description because WhereLoop costs are a
-** vector, not a scalar, and because dependencies are many-to-one, not
-** one-to-one as are graph nodes. But it is a useful visualization aid.)
-** Then a WherePath object is a path through the graph that visits some
-** or all of the WhereLoop objects once.
-**
-** The "solver" works by creating the N best WherePath objects of length
-** 1. Then using those as a basis to compute the N best WherePath objects
-** of length 2. And so forth until the length of WherePaths equals the
-** number of nodes in the FROM clause. The best (lowest cost) WherePath
-** at the end is the chosen query plan.
-*/
-struct WherePath {
- Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
- Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
- LogEst nRow; /* Estimated number of rows generated by this path */
- LogEst rCost; /* Total cost of this path */
- LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */
- i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
- WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
-};
-
-/*
-** The query generator uses an array of instances of this structure to
-** help it analyze the subexpressions of the WHERE clause. Each WHERE
-** clause subexpression is separated from the others by AND operators,
-** usually, or sometimes subexpressions separated by OR.
-**
-** All WhereTerms are collected into a single WhereClause structure.
-** The following identity holds:
-**
-** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm
-**
-** When a term is of the form:
-**
-** X <op> <expr>
-**
-** where X is a column name and <op> is one of certain operators,
-** then WhereTerm.leftCursor and WhereTerm.u.leftColumn record the
-** cursor number and column number for X. WhereTerm.eOperator records
-** the <op> using a bitmask encoding defined by WO_xxx below. The
-** use of a bitmask encoding for the operator allows us to search
-** quickly for terms that match any of several different operators.
-**
-** A WhereTerm might also be two or more subterms connected by OR:
-**
-** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
-**
-** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR
-** and the WhereTerm.u.pOrInfo field points to auxiliary information that
-** is collected about the OR clause.
-**
-** If a term in the WHERE clause does not match either of the two previous
-** categories, then eOperator==0. The WhereTerm.pExpr field is still set
-** to the original subexpression content and wtFlags is set up appropriately
-** but no other fields in the WhereTerm object are meaningful.
-**
-** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers,
-** but they do so indirectly. A single WhereMaskSet structure translates
-** cursor number into bits and the translated bit is stored in the prereq
-** fields. The translation is used in order to maximize the number of
-** bits that will fit in a Bitmask. The VDBE cursor numbers might be
-** spread out over the non-negative integers. For example, the cursor
-** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The WhereMaskSet
-** translates these sparse cursor numbers into consecutive integers
-** beginning with 0 in order to make the best possible use of the available
-** bits in the Bitmask. So, in the example above, the cursor numbers
-** would be mapped into integers 0 through 7.
-**
-** The number of terms in a join is limited by the number of bits
-** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
-** is only able to process joins with 64 or fewer tables.
-*/
-struct WhereTerm {
- Expr *pExpr; /* Pointer to the subexpression that is this term */
- WhereClause *pWC; /* The clause this term is part of */
- LogEst truthProb; /* Probability of truth for this expression */
- u16 wtFlags; /* TERM_xxx bit flags. See below */
- u16 eOperator; /* A WO_xx value describing <op> */
- u8 nChild; /* Number of children that must disable us */
- u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
- int iParent; /* Disable pWC->a[iParent] when this term disabled */
- int leftCursor; /* Cursor number of X in "X <op> <expr>" */
- int iField; /* Field in (?,?,?) IN (SELECT...) vector */
- union {
- int leftColumn; /* Column number of X in "X <op> <expr>" */
- WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
- WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
- } u;
- Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
- Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
-};
-
-/*
-** Allowed values of WhereTerm.wtFlags
-*/
-#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */
-#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */
-#define TERM_CODED 0x04 /* This term is already coded */
-#define TERM_COPIED 0x08 /* Has a child */
-#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
-#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
-#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
-#else
-# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
-#endif
-#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
-#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
-#define TERM_LIKE 0x400 /* The original LIKE operator */
-#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
-#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
-
-/*
-** An instance of the WhereScan object is used as an iterator for locating
-** terms in the WHERE clause that are useful to the query planner.
-*/
-struct WhereScan {
- WhereClause *pOrigWC; /* Original, innermost WhereClause */
- WhereClause *pWC; /* WhereClause currently being scanned */
- const char *zCollName; /* Required collating sequence, if not NULL */
- Expr *pIdxExpr; /* Search for this index expression */
- char idxaff; /* Must match this affinity, if zCollName!=NULL */
- unsigned char nEquiv; /* Number of entries in aEquiv[] */
- unsigned char iEquiv; /* Next unused slot in aEquiv[] */
- u32 opMask; /* Acceptable operators */
- int k; /* Resume scanning at this->pWC->a[this->k] */
- int aiCur[11]; /* Cursors in the equivalence class */
- i16 aiColumn[11]; /* Corresponding column number in the eq-class */
-};
-
-/*
-** An instance of the following structure holds all information about a
-** WHERE clause. Mostly this is a container for one or more WhereTerms.
-**
-** Explanation of pOuter: For a WHERE clause of the form
-**
-** a AND ((b AND c) OR (d AND e)) AND f
-**
-** There are separate WhereClause objects for the whole clause and for
-** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the
-** subclauses points to the WhereClause object for the whole clause.
-*/
-struct WhereClause {
- WhereInfo *pWInfo; /* WHERE clause processing context */
- WhereClause *pOuter; /* Outer conjunction */
- u8 op; /* Split operator. TK_AND or TK_OR */
- int nTerm; /* Number of terms */
- int nSlot; /* Number of entries in a[] */
- WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
-#if defined(SQLITE_SMALL_STACK)
- WhereTerm aStatic[1]; /* Initial static space for a[] */
-#else
- WhereTerm aStatic[8]; /* Initial static space for a[] */
-#endif
-};
-
-/*
-** A WhereTerm with eOperator==WO_OR has its u.pOrInfo pointer set to
-** a dynamically allocated instance of the following structure.
-*/
-struct WhereOrInfo {
- WhereClause wc; /* Decomposition into subterms */
- Bitmask indexable; /* Bitmask of all indexable tables in the clause */
-};
-
-/*
-** A WhereTerm with eOperator==WO_AND has its u.pAndInfo pointer set to
-** a dynamically allocated instance of the following structure.
-*/
-struct WhereAndInfo {
- WhereClause wc; /* The subexpression broken out */
-};
-
-/*
-** An instance of the following structure keeps track of a mapping
-** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
-**
-** The VDBE cursor numbers are small integers contained in
-** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE
-** clause, the cursor numbers might not begin with 0 and they might
-** contain gaps in the numbering sequence. But we want to make maximum
-** use of the bits in our bitmasks. This structure provides a mapping
-** from the sparse cursor numbers into consecutive integers beginning
-** with 0.
-**
-** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
-** corresponds VDBE cursor number B. The A-th bit of a bitmask is 1<<A.
-**
-** For example, if the WHERE clause expression used these VDBE
-** cursors: 4, 5, 8, 29, 57, 73. Then the WhereMaskSet structure
-** would map those cursor numbers into bits 0 through 5.
-**
-** Note that the mapping is not necessarily ordered. In the example
-** above, the mapping might go like this: 4->3, 5->1, 8->2, 29->0,
-** 57->5, 73->4. Or one of 719 other combinations might be used. It
-** does not really matter. What is important is that sparse cursor
-** numbers all get mapped into bit numbers that begin with 0 and contain
-** no gaps.
-*/
-struct WhereMaskSet {
- int bVarSelect; /* Used by sqlite3WhereExprUsage() */
- int n; /* Number of assigned cursor values */
- int ix[BMS]; /* Cursor assigned to each bit */
-};
-
-/*
-** Initialize a WhereMaskSet object
-*/
-#define initMaskSet(P) (P)->n=0
-
-/*
-** This object is a convenience wrapper holding all information needed
-** to construct WhereLoop objects for a particular query.
-*/
-struct WhereLoopBuilder {
- WhereInfo *pWInfo; /* Information about this WHERE */
- WhereClause *pWC; /* WHERE clause terms */
- ExprList *pOrderBy; /* ORDER BY clause */
- WhereLoop *pNew; /* Template WhereLoop */
- WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- UnpackedRecord *pRec; /* Probe for stat4 (if required) */
- int nRecValid; /* Number of valid fields currently in pRec */
-#endif
- unsigned int bldFlags; /* SQLITE_BLDF_* flags */
-};
-
-/* Allowed values for WhereLoopBuider.bldFlags */
-#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
-#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
-
-/*
-** The WHERE clause processing routine has two halves. The
-** first part does the start of the WHERE loop and the second
-** half does the tail of the WHERE loop. An instance of
-** this structure is returned by the first half and passed
-** into the second half to give some continuity.
-**
-** An instance of this object holds the complete state of the query
-** planner.
-*/
-struct WhereInfo {
- Parse *pParse; /* Parsing and code generating context */
- SrcList *pTabList; /* List of tables in the join */
- ExprList *pOrderBy; /* The ORDER BY clause or NULL */
- ExprList *pResultSet; /* Result set of the query */
- Expr *pWhere; /* The complete WHERE clause */
- LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
- int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
- int iContinue; /* Jump here to continue with next record */
- int iBreak; /* Jump here to break out of the loop */
- int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
- u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
- u8 nLevel; /* Number of nested loop */
- i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
- u8 sorted; /* True if really sorted (not just grouped) */
- u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
- u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
- u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
- u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
- int iTop; /* The very beginning of the WHERE loop */
- WhereLoop *pLoops; /* List of all WhereLoop objects */
- Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
- LogEst nRowOut; /* Estimated number of output rows */
- WhereClause sWC; /* Decomposition of the WHERE clause */
- WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
-};
-
-/*
-** Private interfaces - callable only by other where.c routines.
-**
-** where.c:
-*/
-Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
-#ifdef WHERETRACE_ENABLED
-void sqlite3WhereClausePrint(WhereClause *pWC);
-#endif
-WhereTerm *sqlite3WhereFindTerm(
- WhereClause *pWC, /* The WHERE clause to be searched */
- int iCur, /* Cursor number of LHS */
- int iColumn, /* Column number of LHS */
- Bitmask notReady, /* RHS must not overlap with this mask */
- u32 op, /* Mask of WO_xx values describing operator */
- Index *pIdx /* Must be compatible with this index, if not NULL */
-);
-
-/* wherecode.c: */
-#ifndef SQLITE_OMIT_EXPLAIN
-int sqlite3WhereExplainOneScan(
- Parse *pParse, /* Parse context */
- SrcList *pTabList, /* Table list this loop refers to */
- WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
- u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
-);
-#else
-# define sqlite3WhereExplainOneScan(u,v,w,x) 0
-#endif /* SQLITE_OMIT_EXPLAIN */
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
-void sqlite3WhereAddScanStatus(
- Vdbe *v, /* Vdbe to add scanstatus entry to */
- SrcList *pSrclist, /* FROM clause pLvl reads data from */
- WhereLevel *pLvl, /* Level to add scanstatus() entry for */
- int addrExplain /* Address of OP_Explain (or 0) */
-);
-#else
-# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d)
-#endif
-Bitmask sqlite3WhereCodeOneLoopStart(
- WhereInfo *pWInfo, /* Complete information about the WHERE clause */
- int iLevel, /* Which level of pWInfo->a[] should be coded */
- Bitmask notReady /* Which tables are currently available */
-);
-
-/* whereexpr.c: */
-void sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
-void sqlite3WhereClauseClear(WhereClause*);
-void sqlite3WhereSplit(WhereClause*,Expr*,u8);
-Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
-Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
-void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
-void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
-
-
-
-
-
-/*
-** Bitmasks for the operators on WhereTerm objects. These are all
-** operators that are of interest to the query planner. An
-** OR-ed combination of these values can be used when searching for
-** particular WhereTerms within a WhereClause.
-**
-** Value constraints:
-** WO_EQ == SQLITE_INDEX_CONSTRAINT_EQ
-** WO_LT == SQLITE_INDEX_CONSTRAINT_LT
-** WO_LE == SQLITE_INDEX_CONSTRAINT_LE
-** WO_GT == SQLITE_INDEX_CONSTRAINT_GT
-** WO_GE == SQLITE_INDEX_CONSTRAINT_GE
-*/
-#define WO_IN 0x0001
-#define WO_EQ 0x0002
-#define WO_LT (WO_EQ<<(TK_LT-TK_EQ))
-#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
-#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
-#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
-#define WO_AUX 0x0040 /* Op useful to virtual tables only */
-#define WO_IS 0x0080
-#define WO_ISNULL 0x0100
-#define WO_OR 0x0200 /* Two or more OR-connected terms */
-#define WO_AND 0x0400 /* Two or more AND-connected terms */
-#define WO_EQUIV 0x0800 /* Of the form A==B, both columns */
-#define WO_NOOP 0x1000 /* This term does not restrict search space */
-
-#define WO_ALL 0x1fff /* Mask of all possible WO_* values */
-#define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */
-
-/*
-** These are definitions of bits in the WhereLoop.wsFlags field.
-** The particular combination of bits in each WhereLoop help to
-** determine the algorithm that WhereLoop represents.
-*/
-#define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR */
-#define WHERE_COLUMN_RANGE 0x00000002 /* x<EXPR and/or x>EXPR */
-#define WHERE_COLUMN_IN 0x00000004 /* x IN (...) */
-#define WHERE_COLUMN_NULL 0x00000008 /* x IS NULL */
-#define WHERE_CONSTRAINT 0x0000000f /* Any of the WHERE_COLUMN_xxx values */
-#define WHERE_TOP_LIMIT 0x00000010 /* x<EXPR or x<=EXPR constraint */
-#define WHERE_BTM_LIMIT 0x00000020 /* x>EXPR or x>=EXPR constraint */
-#define WHERE_BOTH_LIMIT 0x00000030 /* Both x>EXPR and x<EXPR */
-#define WHERE_IDX_ONLY 0x00000040 /* Use index only - omit table */
-#define WHERE_IPK 0x00000100 /* x is the INTEGER PRIMARY KEY */
-#define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */
-#define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */
-#define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
-#define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
-#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
-#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
-#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
-#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
-#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/wherecode.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/wherecode.c
deleted file mode 100644
index c9edab7b0c1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/wherecode.c
+++ /dev/null
@@ -1,2234 +0,0 @@
-/*
-** 2015-06-06
-**
-** 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 module contains C code that generates VDBE code used to process
-** the WHERE clause of SQL statements.
-**
-** This file was split off from where.c on 2015-06-06 in order to reduce the
-** size of where.c and make it easier to edit. This file contains the routines
-** that actually generate the bulk of the WHERE loop code. The original where.c
-** file retains the code that does query planning and analysis.
-*/
-#include "sqliteInt.h"
-#include "whereInt.h"
-
-#ifndef SQLITE_OMIT_EXPLAIN
-
-/*
-** Return the name of the i-th column of the pIdx index.
-*/
-static const char *explainIndexColumnName(Index *pIdx, int i){
- i = pIdx->aiColumn[i];
- if( i==XN_EXPR ) return "<expr>";
- if( i==XN_ROWID ) return "rowid";
- return pIdx->pTable->aCol[i].zName;
-}
-
-/*
-** This routine is a helper for explainIndexRange() below
-**
-** pStr holds the text of an expression that we are building up one term
-** at a time. This routine adds a new term to the end of the expression.
-** Terms are separated by AND so add the "AND" text for second and subsequent
-** terms only.
-*/
-static void explainAppendTerm(
- StrAccum *pStr, /* The text expression being built */
- Index *pIdx, /* Index to read column names from */
- int nTerm, /* Number of terms */
- int iTerm, /* Zero-based index of first term. */
- int bAnd, /* Non-zero to append " AND " */
- const char *zOp /* Name of the operator */
-){
- int i;
-
- assert( nTerm>=1 );
- if( bAnd ) sqlite3_str_append(pStr, " AND ", 5);
-
- if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1);
- for(i=0; i<nTerm; i++){
- if( i ) sqlite3_str_append(pStr, ",", 1);
- sqlite3_str_appendall(pStr, explainIndexColumnName(pIdx, iTerm+i));
- }
- if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1);
-
- sqlite3_str_append(pStr, zOp, 1);
-
- if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1);
- for(i=0; i<nTerm; i++){
- if( i ) sqlite3_str_append(pStr, ",", 1);
- sqlite3_str_append(pStr, "?", 1);
- }
- if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1);
-}
-
-/*
-** Argument pLevel describes a strategy for scanning table pTab. This
-** function appends text to pStr that describes the subset of table
-** rows scanned by the strategy in the form of an SQL expression.
-**
-** For example, if the query:
-**
-** SELECT * FROM t1 WHERE a=1 AND b>2;
-**
-** is run and there is an index on (a, b), then this function returns a
-** string similar to:
-**
-** "a=? AND b>?"
-*/
-static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
- Index *pIndex = pLoop->u.btree.pIndex;
- u16 nEq = pLoop->u.btree.nEq;
- u16 nSkip = pLoop->nSkip;
- int i, j;
-
- if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return;
- sqlite3_str_append(pStr, " (", 2);
- for(i=0; i<nEq; i++){
- const char *z = explainIndexColumnName(pIndex, i);
- if( i ) sqlite3_str_append(pStr, " AND ", 5);
- sqlite3_str_appendf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z);
- }
-
- j = i;
- if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
- explainAppendTerm(pStr, pIndex, pLoop->u.btree.nBtm, j, i, ">");
- i = 1;
- }
- if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
- explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<");
- }
- sqlite3_str_append(pStr, ")", 1);
-}
-
-/*
-** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
-** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was
-** defined at compile-time. If it is not a no-op, a single OP_Explain opcode
-** is added to the output to describe the table scan strategy in pLevel.
-**
-** If an OP_Explain opcode is added to the VM, its address is returned.
-** Otherwise, if no OP_Explain is coded, zero is returned.
-*/
-int sqlite3WhereExplainOneScan(
- Parse *pParse, /* Parse context */
- SrcList *pTabList, /* Table list this loop refers to */
- WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
- u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
-){
- int ret = 0;
-#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
- if( sqlite3ParseToplevel(pParse)->explain==2 )
-#endif
- {
- struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
- Vdbe *v = pParse->pVdbe; /* VM being constructed */
- sqlite3 *db = pParse->db; /* Database handle */
- int isSearch; /* True for a SEARCH. False for SCAN. */
- WhereLoop *pLoop; /* The controlling WhereLoop object */
- u32 flags; /* Flags that describe this loop */
- char *zMsg; /* Text to add to EQP output */
- StrAccum str; /* EQP output string */
- char zBuf[100]; /* Initial space for EQP output string */
-
- pLoop = pLevel->pWLoop;
- flags = pLoop->wsFlags;
- if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;
-
- isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
- || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
- || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
-
- sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
- sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN");
- if( pItem->pSelect ){
- sqlite3_str_appendf(&str, " SUBQUERY 0x%p", pItem->pSelect);
- }else{
- sqlite3_str_appendf(&str, " TABLE %s", pItem->zName);
- }
-
- if( pItem->zAlias ){
- sqlite3_str_appendf(&str, " AS %s", pItem->zAlias);
- }
- if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
- const char *zFmt = 0;
- Index *pIdx;
-
- assert( pLoop->u.btree.pIndex!=0 );
- pIdx = pLoop->u.btree.pIndex;
- assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
- if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
- if( isSearch ){
- zFmt = "PRIMARY KEY";
- }
- }else if( flags & WHERE_PARTIALIDX ){
- zFmt = "AUTOMATIC PARTIAL COVERING INDEX";
- }else if( flags & WHERE_AUTO_INDEX ){
- zFmt = "AUTOMATIC COVERING INDEX";
- }else if( flags & WHERE_IDX_ONLY ){
- zFmt = "COVERING INDEX %s";
- }else{
- zFmt = "INDEX %s";
- }
- if( zFmt ){
- sqlite3_str_append(&str, " USING ", 7);
- sqlite3_str_appendf(&str, zFmt, pIdx->zName);
- explainIndexRange(&str, pLoop);
- }
- }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
- const char *zRangeOp;
- if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
- zRangeOp = "=";
- }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
- zRangeOp = ">? AND rowid<";
- }else if( flags&WHERE_BTM_LIMIT ){
- zRangeOp = ">";
- }else{
- assert( flags&WHERE_TOP_LIMIT);
- zRangeOp = "<";
- }
- sqlite3_str_appendf(&str,
- " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp);
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
- sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
- pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
- }
-#endif
-#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
- if( pLoop->nOut>=10 ){
- sqlite3_str_appendf(&str, " (~%llu rows)",
- sqlite3LogEstToInt(pLoop->nOut));
- }else{
- sqlite3_str_append(&str, " (~1 row)", 9);
- }
-#endif
- zMsg = sqlite3StrAccumFinish(&str);
- ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
- pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
- }
- return ret;
-}
-#endif /* SQLITE_OMIT_EXPLAIN */
-
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
-/*
-** Configure the VM passed as the first argument with an
-** sqlite3_stmt_scanstatus() entry corresponding to the scan used to
-** implement level pLvl. Argument pSrclist is a pointer to the FROM
-** clause that the scan reads data from.
-**
-** If argument addrExplain is not 0, it must be the address of an
-** OP_Explain instruction that describes the same loop.
-*/
-void sqlite3WhereAddScanStatus(
- Vdbe *v, /* Vdbe to add scanstatus entry to */
- SrcList *pSrclist, /* FROM clause pLvl reads data from */
- WhereLevel *pLvl, /* Level to add scanstatus() entry for */
- int addrExplain /* Address of OP_Explain (or 0) */
-){
- const char *zObj = 0;
- WhereLoop *pLoop = pLvl->pWLoop;
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){
- zObj = pLoop->u.btree.pIndex->zName;
- }else{
- zObj = pSrclist->a[pLvl->iFrom].zName;
- }
- sqlite3VdbeScanStatus(
- v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj
- );
-}
-#endif
-
-
-/*
-** Disable a term in the WHERE clause. Except, do not disable the term
-** if it controls a LEFT OUTER JOIN and it did not originate in the ON
-** or USING clause of that join.
-**
-** Consider the term t2.z='ok' in the following queries:
-**
-** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
-** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
-** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
-**
-** The t2.z='ok' is disabled in the in (2) because it originates
-** in the ON clause. The term is disabled in (3) because it is not part
-** of a LEFT OUTER JOIN. In (1), the term is not disabled.
-**
-** Disabling a term causes that term to not be tested in the inner loop
-** of the join. Disabling is an optimization. When terms are satisfied
-** by indices, we disable them to prevent redundant tests in the inner
-** loop. We would get the correct results if nothing were ever disabled,
-** but joins might run a little slower. The trick is to disable as much
-** as we can without disabling too much. If we disabled in (1), we'd get
-** the wrong answer. See ticket #813.
-**
-** If all the children of a term are disabled, then that term is also
-** automatically disabled. In this way, terms get disabled if derived
-** virtual terms are tested first. For example:
-**
-** x GLOB 'abc*' AND x>='abc' AND x<'acd'
-** \___________/ \______/ \_____/
-** parent child1 child2
-**
-** Only the parent term was in the original WHERE clause. The child1
-** and child2 terms were added by the LIKE optimization. If both of
-** the virtual child terms are valid, then testing of the parent can be
-** skipped.
-**
-** Usually the parent term is marked as TERM_CODED. But if the parent
-** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead.
-** The TERM_LIKECOND marking indicates that the term should be coded inside
-** a conditional such that is only evaluated on the second pass of a
-** LIKE-optimization loop, when scanning BLOBs instead of strings.
-*/
-static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
- int nLoop = 0;
- assert( pTerm!=0 );
- while( (pTerm->wtFlags & TERM_CODED)==0
- && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
- && (pLevel->notReady & pTerm->prereqAll)==0
- ){
- if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
- pTerm->wtFlags |= TERM_LIKECOND;
- }else{
- pTerm->wtFlags |= TERM_CODED;
- }
- if( pTerm->iParent<0 ) break;
- pTerm = &pTerm->pWC->a[pTerm->iParent];
- assert( pTerm!=0 );
- pTerm->nChild--;
- if( pTerm->nChild!=0 ) break;
- nLoop++;
- }
-}
-
-/*
-** Code an OP_Affinity opcode to apply the column affinity string zAff
-** to the n registers starting at base.
-**
-** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the
-** beginning and end of zAff are ignored. If all entries in zAff are
-** SQLITE_AFF_BLOB, then no code gets generated.
-**
-** This routine makes its own copy of zAff so that the caller is free
-** to modify zAff after this routine returns.
-*/
-static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
- Vdbe *v = pParse->pVdbe;
- if( zAff==0 ){
- assert( pParse->db->mallocFailed );
- return;
- }
- assert( v!=0 );
-
- /* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning
- ** and end of the affinity string.
- */
- while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){
- n--;
- base++;
- zAff++;
- }
- while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){
- n--;
- }
-
- /* Code the OP_Affinity opcode if there is anything left to do. */
- if( n>0 ){
- sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n);
- sqlite3ExprCacheAffinityChange(pParse, base, n);
- }
-}
-
-/*
-** Expression pRight, which is the RHS of a comparison operation, is
-** either a vector of n elements or, if n==1, a scalar expression.
-** Before the comparison operation, affinity zAff is to be applied
-** to the pRight values. This function modifies characters within the
-** affinity string to SQLITE_AFF_BLOB if either:
-**
-** * the comparison will be performed with no affinity, or
-** * the affinity change in zAff is guaranteed not to change the value.
-*/
-static void updateRangeAffinityStr(
- Expr *pRight, /* RHS of comparison */
- int n, /* Number of vector elements in comparison */
- char *zAff /* Affinity string to modify */
-){
- int i;
- for(i=0; i<n; i++){
- Expr *p = sqlite3VectorFieldSubexpr(pRight, i);
- if( sqlite3CompareAffinity(p, zAff[i])==SQLITE_AFF_BLOB
- || sqlite3ExprNeedsNoAffinityChange(p, zAff[i])
- ){
- zAff[i] = SQLITE_AFF_BLOB;
- }
- }
-}
-
-
-/*
-** pX is an expression of the form: (vector) IN (SELECT ...)
-** In other words, it is a vector IN operator with a SELECT clause on the
-** LHS. But not all terms in the vector are indexable and the terms might
-** not be in the correct order for indexing.
-**
-** This routine makes a copy of the input pX expression and then adjusts
-** the vector on the LHS with corresponding changes to the SELECT so that
-** the vector contains only index terms and those terms are in the correct
-** order. The modified IN expression is returned. The caller is responsible
-** for deleting the returned expression.
-**
-** Example:
-**
-** CREATE TABLE t1(a,b,c,d,e,f);
-** CREATE INDEX t1x1 ON t1(e,c);
-** SELECT * FROM t1 WHERE (a,b,c,d,e) IN (SELECT v,w,x,y,z FROM t2)
-** \_______________________________________/
-** The pX expression
-**
-** Since only columns e and c can be used with the index, in that order,
-** the modified IN expression that is returned will be:
-**
-** (e,c) IN (SELECT z,x FROM t2)
-**
-** The reduced pX is different from the original (obviously) and thus is
-** only used for indexing, to improve performance. The original unaltered
-** IN expression must also be run on each output row for correctness.
-*/
-static Expr *removeUnindexableInClauseTerms(
- Parse *pParse, /* The parsing context */
- int iEq, /* Look at loop terms starting here */
- WhereLoop *pLoop, /* The current loop */
- Expr *pX /* The IN expression to be reduced */
-){
- sqlite3 *db = pParse->db;
- Expr *pNew = sqlite3ExprDup(db, pX, 0);
- if( db->mallocFailed==0 ){
- ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */
- ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */
- ExprList *pRhs = 0; /* New RHS after modifications */
- ExprList *pLhs = 0; /* New LHS after mods */
- int i; /* Loop counter */
- Select *pSelect; /* Pointer to the SELECT on the RHS */
-
- for(i=iEq; i<pLoop->nLTerm; i++){
- if( pLoop->aLTerm[i]->pExpr==pX ){
- int iField = pLoop->aLTerm[i]->iField - 1;
- assert( pOrigRhs->a[iField].pExpr!=0 );
- pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
- pOrigRhs->a[iField].pExpr = 0;
- assert( pOrigLhs->a[iField].pExpr!=0 );
- pLhs = sqlite3ExprListAppend(pParse, pLhs, pOrigLhs->a[iField].pExpr);
- pOrigLhs->a[iField].pExpr = 0;
- }
- }
- sqlite3ExprListDelete(db, pOrigRhs);
- sqlite3ExprListDelete(db, pOrigLhs);
- pNew->pLeft->x.pList = pLhs;
- pNew->x.pSelect->pEList = pRhs;
- if( pLhs && pLhs->nExpr==1 ){
- /* Take care here not to generate a TK_VECTOR containing only a
- ** single value. Since the parser never creates such a vector, some
- ** of the subroutines do not handle this case. */
- Expr *p = pLhs->a[0].pExpr;
- pLhs->a[0].pExpr = 0;
- sqlite3ExprDelete(db, pNew->pLeft);
- pNew->pLeft = p;
- }
- pSelect = pNew->x.pSelect;
- if( pSelect->pOrderBy ){
- /* If the SELECT statement has an ORDER BY clause, zero the
- ** iOrderByCol variables. These are set to non-zero when an
- ** ORDER BY term exactly matches one of the terms of the
- ** result-set. Since the result-set of the SELECT statement may
- ** have been modified or reordered, these variables are no longer
- ** set correctly. Since setting them is just an optimization,
- ** it's easiest just to zero them here. */
- ExprList *pOrderBy = pSelect->pOrderBy;
- for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].u.x.iOrderByCol = 0;
- }
- }
-
-#if 0
- printf("For indexing, change the IN expr:\n");
- sqlite3TreeViewExpr(0, pX, 0);
- printf("Into:\n");
- sqlite3TreeViewExpr(0, pNew, 0);
-#endif
- }
- return pNew;
-}
-
-
-/*
-** Generate code for a single equality term of the WHERE clause. An equality
-** term can be either X=expr or X IN (...). pTerm is the term to be
-** coded.
-**
-** The current value for the constraint is left in a register, the index
-** of which is returned. An attempt is made store the result in iTarget but
-** this is only guaranteed for TK_ISNULL and TK_IN constraints. If the
-** constraint is a TK_EQ or TK_IS, then the current value might be left in
-** some other register and it is the caller's responsibility to compensate.
-**
-** For a constraint of the form X=expr, the expression is evaluated in
-** straight-line code. For constraints of the form X IN (...)
-** this routine sets up a loop that will iterate over all values of X.
-*/
-static int codeEqualityTerm(
- Parse *pParse, /* The parsing context */
- WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
- WhereLevel *pLevel, /* The level of the FROM clause we are working on */
- int iEq, /* Index of the equality term within this level */
- int bRev, /* True for reverse-order IN operations */
- int iTarget /* Attempt to leave results in this register */
-){
- Expr *pX = pTerm->pExpr;
- Vdbe *v = pParse->pVdbe;
- int iReg; /* Register holding results */
-
- assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
- assert( iTarget>0 );
- if( pX->op==TK_EQ || pX->op==TK_IS ){
- iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
- }else if( pX->op==TK_ISNULL ){
- iReg = iTarget;
- sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
-#ifndef SQLITE_OMIT_SUBQUERY
- }else{
- int eType = IN_INDEX_NOOP;
- int iTab;
- struct InLoop *pIn;
- WhereLoop *pLoop = pLevel->pWLoop;
- int i;
- int nEq = 0;
- int *aiMap = 0;
-
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
- && pLoop->u.btree.pIndex!=0
- && pLoop->u.btree.pIndex->aSortOrder[iEq]
- ){
- testcase( iEq==0 );
- testcase( bRev );
- bRev = !bRev;
- }
- assert( pX->op==TK_IN );
- iReg = iTarget;
-
- for(i=0; i<iEq; i++){
- if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
- disableTerm(pLevel, pTerm);
- return iTarget;
- }
- }
- for(i=iEq;i<pLoop->nLTerm; i++){
- assert( pLoop->aLTerm[i]!=0 );
- if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
- }
-
- if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0);
- }else{
- sqlite3 *db = pParse->db;
- pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
-
- if( !db->mallocFailed ){
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap);
- pTerm->pExpr->iTable = pX->iTable;
- }
- sqlite3ExprDelete(db, pX);
- pX = pTerm->pExpr;
- }
-
- if( eType==IN_INDEX_INDEX_DESC ){
- testcase( bRev );
- bRev = !bRev;
- }
- iTab = pX->iTable;
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
- VdbeCoverageIf(v, bRev);
- VdbeCoverageIf(v, !bRev);
- assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
-
- pLoop->wsFlags |= WHERE_IN_ABLE;
- if( pLevel->u.in.nIn==0 ){
- pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
- }
-
- i = pLevel->u.in.nIn;
- pLevel->u.in.nIn += nEq;
- pLevel->u.in.aInLoop =
- sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
- sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
- pIn = pLevel->u.in.aInLoop;
- if( pIn ){
- int iMap = 0; /* Index in aiMap[] */
- pIn += i;
- for(i=iEq;i<pLoop->nLTerm; i++){
- if( pLoop->aLTerm[i]->pExpr==pX ){
- int iOut = iReg + i - iEq;
- if( eType==IN_INDEX_ROWID ){
- testcase( nEq>1 ); /* Happens with a UNIQUE index on ROWID */
- pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
- }else{
- int iCol = aiMap ? aiMap[iMap++] : 0;
- pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
- }
- sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
- if( i==iEq ){
- pIn->iCur = iTab;
- pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
- }else{
- pIn->eEndLoopOp = OP_Noop;
- }
- pIn++;
- }
- }
- }else{
- pLevel->u.in.nIn = 0;
- }
- sqlite3DbFree(pParse->db, aiMap);
-#endif
- }
- disableTerm(pLevel, pTerm);
- return iReg;
-}
-
-/*
-** Generate code that will evaluate all == and IN constraints for an
-** index scan.
-**
-** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
-** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
-** The index has as many as three equality constraints, but in this
-** example, the third "c" value is an inequality. So only two
-** constraints are coded. This routine will generate code to evaluate
-** a==5 and b IN (1,2,3). The current values for a and b will be stored
-** in consecutive registers and the index of the first register is returned.
-**
-** In the example above nEq==2. But this subroutine works for any value
-** of nEq including 0. If nEq==0, this routine is nearly a no-op.
-** The only thing it does is allocate the pLevel->iMem memory cell and
-** compute the affinity string.
-**
-** The nExtraReg parameter is 0 or 1. It is 0 if all WHERE clause constraints
-** are == or IN and are covered by the nEq. nExtraReg is 1 if there is
-** an inequality constraint (such as the "c>=5 AND c<10" in the example) that
-** occurs after the nEq quality constraints.
-**
-** This routine allocates a range of nEq+nExtraReg memory cells and returns
-** the index of the first memory cell in that range. The code that
-** calls this routine will use that memory range to store keys for
-** start and termination conditions of the loop.
-** key value of the loop. If one or more IN operators appear, then
-** this routine allocates an additional nEq memory cells for internal
-** use.
-**
-** Before returning, *pzAff is set to point to a buffer containing a
-** copy of the column affinity string of the index allocated using
-** sqlite3DbMalloc(). Except, entries in the copy of the string associated
-** with equality constraints that use BLOB or NONE affinity are set to
-** SQLITE_AFF_BLOB. This is to deal with SQL such as the following:
-**
-** CREATE TABLE t1(a TEXT PRIMARY KEY, b);
-** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b;
-**
-** In the example above, the index on t1(a) has TEXT affinity. But since
-** the right hand side of the equality constraint (t2.b) has BLOB/NONE affinity,
-** no conversion should be attempted before using a t2.b value as part of
-** a key to search the index. Hence the first byte in the returned affinity
-** string in this example would be set to SQLITE_AFF_BLOB.
-*/
-static int codeAllEqualityTerms(
- Parse *pParse, /* Parsing context */
- WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
- int bRev, /* Reverse the order of IN operators */
- int nExtraReg, /* Number of extra registers to allocate */
- char **pzAff /* OUT: Set to point to affinity string */
-){
- u16 nEq; /* The number of == or IN constraints to code */
- u16 nSkip; /* Number of left-most columns to skip */
- Vdbe *v = pParse->pVdbe; /* The vm under construction */
- Index *pIdx; /* The index being used for this loop */
- WhereTerm *pTerm; /* A single constraint term */
- WhereLoop *pLoop; /* The WhereLoop object */
- int j; /* Loop counter */
- int regBase; /* Base register */
- int nReg; /* Number of registers to allocate */
- char *zAff; /* Affinity string to return */
-
- /* This module is only called on query plans that use an index. */
- pLoop = pLevel->pWLoop;
- assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
- nEq = pLoop->u.btree.nEq;
- nSkip = pLoop->nSkip;
- pIdx = pLoop->u.btree.pIndex;
- assert( pIdx!=0 );
-
- /* Figure out how many memory cells we will need then allocate them.
- */
- regBase = pParse->nMem + 1;
- nReg = pLoop->u.btree.nEq + nExtraReg;
- pParse->nMem += nReg;
-
- zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx));
- assert( zAff!=0 || pParse->db->mallocFailed );
-
- if( nSkip ){
- int iIdxCur = pLevel->iIdxCur;
- sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
- VdbeCoverageIf(v, bRev==0);
- VdbeCoverageIf(v, bRev!=0);
- VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
- j = sqlite3VdbeAddOp0(v, OP_Goto);
- pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
- iIdxCur, 0, regBase, nSkip);
- VdbeCoverageIf(v, bRev==0);
- VdbeCoverageIf(v, bRev!=0);
- sqlite3VdbeJumpHere(v, j);
- for(j=0; j<nSkip; j++){
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
- testcase( pIdx->aiColumn[j]==XN_EXPR );
- VdbeComment((v, "%s", explainIndexColumnName(pIdx, j)));
- }
- }
-
- /* Evaluate the equality constraints
- */
- assert( zAff==0 || (int)strlen(zAff)>=nEq );
- for(j=nSkip; j<nEq; j++){
- int r1;
- pTerm = pLoop->aLTerm[j];
- assert( pTerm!=0 );
- /* The following testcase is true for indices with redundant columns.
- ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
- testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
- testcase( pTerm->wtFlags & TERM_VIRTUAL );
- r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
- if( r1!=regBase+j ){
- if( nReg==1 ){
- sqlite3ReleaseTempReg(pParse, regBase);
- regBase = r1;
- }else{
- sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
- }
- }
- if( pTerm->eOperator & WO_IN ){
- if( pTerm->pExpr->flags & EP_xIsSelect ){
- /* No affinity ever needs to be (or should be) applied to a value
- ** from the RHS of an "? IN (SELECT ...)" expression. The
- ** sqlite3FindInIndex() routine has already ensured that the
- ** affinity of the comparison has been applied to the value. */
- if( zAff ) zAff[j] = SQLITE_AFF_BLOB;
- }
- }else if( (pTerm->eOperator & WO_ISNULL)==0 ){
- Expr *pRight = pTerm->pExpr->pRight;
- if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
- VdbeCoverage(v);
- }
- if( zAff ){
- if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
- zAff[j] = SQLITE_AFF_BLOB;
- }
- if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
- zAff[j] = SQLITE_AFF_BLOB;
- }
- }
- }
- }
- *pzAff = zAff;
- return regBase;
-}
-
-#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
-/*
-** If the most recently coded instruction is a constant range constraint
-** (a string literal) that originated from the LIKE optimization, then
-** set P3 and P5 on the OP_String opcode so that the string will be cast
-** to a BLOB at appropriate times.
-**
-** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range
-** expression: "x>='ABC' AND x<'abd'". But this requires that the range
-** scan loop run twice, once for strings and a second time for BLOBs.
-** The OP_String opcodes on the second pass convert the upper and lower
-** bound string constants to blobs. This routine makes the necessary changes
-** to the OP_String opcodes for that to happen.
-**
-** Except, of course, if SQLITE_LIKE_DOESNT_MATCH_BLOBS is defined, then
-** only the one pass through the string space is required, so this routine
-** becomes a no-op.
-*/
-static void whereLikeOptimizationStringFixup(
- Vdbe *v, /* prepared statement under construction */
- WhereLevel *pLevel, /* The loop that contains the LIKE operator */
- WhereTerm *pTerm /* The upper or lower bound just coded */
-){
- if( pTerm->wtFlags & TERM_LIKEOPT ){
- VdbeOp *pOp;
- assert( pLevel->iLikeRepCntr>0 );
- pOp = sqlite3VdbeGetOp(v, -1);
- assert( pOp!=0 );
- assert( pOp->opcode==OP_String8
- || pTerm->pWC->pWInfo->pParse->db->mallocFailed );
- pOp->p3 = (int)(pLevel->iLikeRepCntr>>1); /* Register holding counter */
- pOp->p5 = (u8)(pLevel->iLikeRepCntr&1); /* ASC or DESC */
- }
-}
-#else
-# define whereLikeOptimizationStringFixup(A,B,C)
-#endif
-
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
-/*
-** Information is passed from codeCursorHint() down to individual nodes of
-** the expression tree (by sqlite3WalkExpr()) using an instance of this
-** structure.
-*/
-struct CCurHint {
- int iTabCur; /* Cursor for the main table */
- int iIdxCur; /* Cursor for the index, if pIdx!=0. Unused otherwise */
- Index *pIdx; /* The index used to access the table */
-};
-
-/*
-** This function is called for every node of an expression that is a candidate
-** for a cursor hint on an index cursor. For TK_COLUMN nodes that reference
-** the table CCurHint.iTabCur, verify that the same column can be
-** accessed through the index. If it cannot, then set pWalker->eCode to 1.
-*/
-static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){
- struct CCurHint *pHint = pWalker->u.pCCurHint;
- assert( pHint->pIdx!=0 );
- if( pExpr->op==TK_COLUMN
- && pExpr->iTable==pHint->iTabCur
- && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0
- ){
- pWalker->eCode = 1;
- }
- return WRC_Continue;
-}
-
-/*
-** Test whether or not expression pExpr, which was part of a WHERE clause,
-** should be included in the cursor-hint for a table that is on the rhs
-** of a LEFT JOIN. Set Walker.eCode to non-zero before returning if the
-** expression is not suitable.
-**
-** An expression is unsuitable if it might evaluate to non NULL even if
-** a TK_COLUMN node that does affect the value of the expression is set
-** to NULL. For example:
-**
-** col IS NULL
-** col IS NOT NULL
-** coalesce(col, 1)
-** CASE WHEN col THEN 0 ELSE 1 END
-*/
-static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){
- if( pExpr->op==TK_IS
- || pExpr->op==TK_ISNULL || pExpr->op==TK_ISNOT
- || pExpr->op==TK_NOTNULL || pExpr->op==TK_CASE
- ){
- pWalker->eCode = 1;
- }else if( pExpr->op==TK_FUNCTION ){
- int d1;
- char d2[4];
- if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){
- pWalker->eCode = 1;
- }
- }
-
- return WRC_Continue;
-}
-
-
-/*
-** This function is called on every node of an expression tree used as an
-** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN
-** that accesses any table other than the one identified by
-** CCurHint.iTabCur, then do the following:
-**
-** 1) allocate a register and code an OP_Column instruction to read
-** the specified column into the new register, and
-**
-** 2) transform the expression node to a TK_REGISTER node that reads
-** from the newly populated register.
-**
-** Also, if the node is a TK_COLUMN that does access the table idenified
-** by pCCurHint.iTabCur, and an index is being used (which we will
-** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into
-** an access of the index rather than the original table.
-*/
-static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
- int rc = WRC_Continue;
- struct CCurHint *pHint = pWalker->u.pCCurHint;
- if( pExpr->op==TK_COLUMN ){
- if( pExpr->iTable!=pHint->iTabCur ){
- Vdbe *v = pWalker->pParse->pVdbe;
- int reg = ++pWalker->pParse->nMem; /* Register for column value */
- sqlite3ExprCodeGetColumnOfTable(
- v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg
- );
- pExpr->op = TK_REGISTER;
- pExpr->iTable = reg;
- }else if( pHint->pIdx!=0 ){
- pExpr->iTable = pHint->iIdxCur;
- pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn);
- assert( pExpr->iColumn>=0 );
- }
- }else if( pExpr->op==TK_AGG_FUNCTION ){
- /* An aggregate function in the WHERE clause of a query means this must
- ** be a correlated sub-query, and expression pExpr is an aggregate from
- ** the parent context. Do not walk the function arguments in this case.
- **
- ** todo: It should be possible to replace this node with a TK_REGISTER
- ** expression, as the result of the expression must be stored in a
- ** register at this point. The same holds for TK_AGG_COLUMN nodes. */
- rc = WRC_Prune;
- }
- return rc;
-}
-
-/*
-** Insert an OP_CursorHint instruction if it is appropriate to do so.
-*/
-static void codeCursorHint(
- struct SrcList_item *pTabItem, /* FROM clause item */
- WhereInfo *pWInfo, /* The where clause */
- WhereLevel *pLevel, /* Which loop to provide hints for */
- WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */
-){
- Parse *pParse = pWInfo->pParse;
- sqlite3 *db = pParse->db;
- Vdbe *v = pParse->pVdbe;
- Expr *pExpr = 0;
- WhereLoop *pLoop = pLevel->pWLoop;
- int iCur;
- WhereClause *pWC;
- WhereTerm *pTerm;
- int i, j;
- struct CCurHint sHint;
- Walker sWalker;
-
- if( OptimizationDisabled(db, SQLITE_CursorHints) ) return;
- iCur = pLevel->iTabCur;
- assert( iCur==pWInfo->pTabList->a[pLevel->iFrom].iCursor );
- sHint.iTabCur = iCur;
- sHint.iIdxCur = pLevel->iIdxCur;
- sHint.pIdx = pLoop->u.btree.pIndex;
- memset(&sWalker, 0, sizeof(sWalker));
- sWalker.pParse = pParse;
- sWalker.u.pCCurHint = &sHint;
- pWC = &pWInfo->sWC;
- for(i=0; i<pWC->nTerm; i++){
- pTerm = &pWC->a[i];
- if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
- if( pTerm->prereqAll & pLevel->notReady ) continue;
-
- /* Any terms specified as part of the ON(...) clause for any LEFT
- ** JOIN for which the current table is not the rhs are omitted
- ** from the cursor-hint.
- **
- ** If this table is the rhs of a LEFT JOIN, "IS" or "IS NULL" terms
- ** that were specified as part of the WHERE clause must be excluded.
- ** This is to address the following:
- **
- ** SELECT ... t1 LEFT JOIN t2 ON (t1.a=t2.b) WHERE t2.c IS NULL;
- **
- ** Say there is a single row in t2 that matches (t1.a=t2.b), but its
- ** t2.c values is not NULL. If the (t2.c IS NULL) constraint is
- ** pushed down to the cursor, this row is filtered out, causing
- ** SQLite to synthesize a row of NULL values. Which does match the
- ** WHERE clause, and so the query returns a row. Which is incorrect.
- **
- ** For the same reason, WHERE terms such as:
- **
- ** WHERE 1 = (t2.c IS NULL)
- **
- ** are also excluded. See codeCursorHintIsOrFunction() for details.
- */
- if( pTabItem->fg.jointype & JT_LEFT ){
- Expr *pExpr = pTerm->pExpr;
- if( !ExprHasProperty(pExpr, EP_FromJoin)
- || pExpr->iRightJoinTable!=pTabItem->iCursor
- ){
- sWalker.eCode = 0;
- sWalker.xExprCallback = codeCursorHintIsOrFunction;
- sqlite3WalkExpr(&sWalker, pTerm->pExpr);
- if( sWalker.eCode ) continue;
- }
- }else{
- if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue;
- }
-
- /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize
- ** the cursor. These terms are not needed as hints for a pure range
- ** scan (that has no == terms) so omit them. */
- if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){
- for(j=0; j<pLoop->nLTerm && pLoop->aLTerm[j]!=pTerm; j++){}
- if( j<pLoop->nLTerm ) continue;
- }
-
- /* No subqueries or non-deterministic functions allowed */
- if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue;
-
- /* For an index scan, make sure referenced columns are actually in
- ** the index. */
- if( sHint.pIdx!=0 ){
- sWalker.eCode = 0;
- sWalker.xExprCallback = codeCursorHintCheckExpr;
- sqlite3WalkExpr(&sWalker, pTerm->pExpr);
- if( sWalker.eCode ) continue;
- }
-
- /* If we survive all prior tests, that means this term is worth hinting */
- pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
- }
- if( pExpr!=0 ){
- sWalker.xExprCallback = codeCursorHintFixExpr;
- sqlite3WalkExpr(&sWalker, pExpr);
- sqlite3VdbeAddOp4(v, OP_CursorHint,
- (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0,
- (const char*)pExpr, P4_EXPR);
- }
-}
-#else
-# define codeCursorHint(A,B,C,D) /* No-op */
-#endif /* SQLITE_ENABLE_CURSOR_HINTS */
-
-/*
-** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains
-** a rowid value just read from cursor iIdxCur, open on index pIdx. This
-** function generates code to do a deferred seek of cursor iCur to the
-** rowid stored in register iRowid.
-**
-** Normally, this is just:
-**
-** OP_DeferredSeek $iCur $iRowid
-**
-** However, if the scan currently being coded is a branch of an OR-loop and
-** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek
-** is set to iIdxCur and P4 is set to point to an array of integers
-** containing one entry for each column of the table cursor iCur is open
-** on. For each table column, if the column is the i'th column of the
-** index, then the corresponding array entry is set to (i+1). If the column
-** does not appear in the index at all, the array entry is set to 0.
-*/
-static void codeDeferredSeek(
- WhereInfo *pWInfo, /* Where clause context */
- Index *pIdx, /* Index scan is using */
- int iCur, /* Cursor for IPK b-tree */
- int iIdxCur /* Index cursor */
-){
- Parse *pParse = pWInfo->pParse; /* Parse context */
- Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */
-
- assert( iIdxCur>0 );
- assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
-
- sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
- if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
- && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
- ){
- int i;
- Table *pTab = pIdx->pTable;
- int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1));
- if( ai ){
- ai[0] = pTab->nCol;
- for(i=0; i<pIdx->nColumn-1; i++){
- assert( pIdx->aiColumn[i]<pTab->nCol );
- if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1;
- }
- sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
- }
- }
-}
-
-/*
-** If the expression passed as the second argument is a vector, generate
-** code to write the first nReg elements of the vector into an array
-** of registers starting with iReg.
-**
-** If the expression is not a vector, then nReg must be passed 1. In
-** this case, generate code to evaluate the expression and leave the
-** result in register iReg.
-*/
-static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
- assert( nReg>0 );
- if( p && sqlite3ExprIsVector(p) ){
-#ifndef SQLITE_OMIT_SUBQUERY
- if( (p->flags & EP_xIsSelect) ){
- Vdbe *v = pParse->pVdbe;
- int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0);
- sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1);
- }else
-#endif
- {
- int i;
- ExprList *pList = p->x.pList;
- assert( nReg<=pList->nExpr );
- for(i=0; i<nReg; i++){
- sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i);
- }
- }
- }else{
- assert( nReg==1 );
- sqlite3ExprCode(pParse, p, iReg);
- }
-}
-
-/* An instance of the IdxExprTrans object carries information about a
-** mapping from an expression on table columns into a column in an index
-** down through the Walker.
-*/
-typedef struct IdxExprTrans {
- Expr *pIdxExpr; /* The index expression */
- int iTabCur; /* The cursor of the corresponding table */
- int iIdxCur; /* The cursor for the index */
- int iIdxCol; /* The column for the index */
-} IdxExprTrans;
-
-/* The walker node callback used to transform matching expressions into
-** a reference to an index column for an index on an expression.
-**
-** If pExpr matches, then transform it into a reference to the index column
-** that contains the value of pExpr.
-*/
-static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
- IdxExprTrans *pX = p->u.pIdxTrans;
- if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
- pExpr->op = TK_COLUMN;
- pExpr->iTable = pX->iIdxCur;
- pExpr->iColumn = pX->iIdxCol;
- pExpr->pTab = 0;
- return WRC_Prune;
- }else{
- return WRC_Continue;
- }
-}
-
-/*
-** For an indexes on expression X, locate every instance of expression X
-** in pExpr and change that subexpression into a reference to the appropriate
-** column of the index.
-*/
-static void whereIndexExprTrans(
- Index *pIdx, /* The Index */
- int iTabCur, /* Cursor of the table that is being indexed */
- int iIdxCur, /* Cursor of the index itself */
- WhereInfo *pWInfo /* Transform expressions in this WHERE clause */
-){
- int iIdxCol; /* Column number of the index */
- ExprList *aColExpr; /* Expressions that are indexed */
- Walker w;
- IdxExprTrans x;
- aColExpr = pIdx->aColExpr;
- if( aColExpr==0 ) return; /* Not an index on expressions */
- memset(&w, 0, sizeof(w));
- w.xExprCallback = whereIndexExprTransNode;
- w.u.pIdxTrans = &x;
- x.iTabCur = iTabCur;
- x.iIdxCur = iIdxCur;
- for(iIdxCol=0; iIdxCol<aColExpr->nExpr; iIdxCol++){
- if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue;
- assert( aColExpr->a[iIdxCol].pExpr!=0 );
- x.iIdxCol = iIdxCol;
- x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
- sqlite3WalkExpr(&w, pWInfo->pWhere);
- sqlite3WalkExprList(&w, pWInfo->pOrderBy);
- sqlite3WalkExprList(&w, pWInfo->pResultSet);
- }
-}
-
-/*
-** Generate code for the start of the iLevel-th loop in the WHERE clause
-** implementation described by pWInfo.
-*/
-Bitmask sqlite3WhereCodeOneLoopStart(
- WhereInfo *pWInfo, /* Complete information about the WHERE clause */
- int iLevel, /* Which level of pWInfo->a[] should be coded */
- Bitmask notReady /* Which tables are currently available */
-){
- int j, k; /* Loop counters */
- int iCur; /* The VDBE cursor for the table */
- int addrNxt; /* Where to jump to continue with the next IN case */
- int omitTable; /* True if we use the index only */
- int bRev; /* True if we need to scan in reverse order */
- WhereLevel *pLevel; /* The where level to be coded */
- WhereLoop *pLoop; /* The WhereLoop object being coded */
- WhereClause *pWC; /* Decomposition of the entire WHERE clause */
- WhereTerm *pTerm; /* A WHERE clause term */
- Parse *pParse; /* Parsing context */
- sqlite3 *db; /* Database connection */
- Vdbe *v; /* The prepared stmt under constructions */
- struct SrcList_item *pTabItem; /* FROM clause term being coded */
- int addrBrk; /* Jump here to break out of the loop */
- int addrHalt; /* addrBrk for the outermost loop */
- int addrCont; /* Jump here to continue with next cycle */
- int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
- int iReleaseReg = 0; /* Temp register to free before returning */
- Index *pIdx = 0; /* Index used by loop (if any) */
- int iLoop; /* Iteration of constraint generator loop */
-
- pParse = pWInfo->pParse;
- v = pParse->pVdbe;
- pWC = &pWInfo->sWC;
- db = pParse->db;
- pLevel = &pWInfo->a[iLevel];
- pLoop = pLevel->pWLoop;
- pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
- iCur = pTabItem->iCursor;
- pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
- bRev = (pWInfo->revMask>>iLevel)&1;
- omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0;
- VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
-
- /* Create labels for the "break" and "continue" instructions
- ** for the current loop. Jump to addrBrk to break out of a loop.
- ** Jump to cont to go immediately to the next iteration of the
- ** loop.
- **
- ** When there is an IN operator, we also have a "addrNxt" label that
- ** means to continue with the next IN value combination. When
- ** there are no IN operators in the constraints, the "addrNxt" label
- ** is the same as "addrBrk".
- */
- addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
- addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v);
-
- /* If this is the right table of a LEFT OUTER JOIN, allocate and
- ** initialize a memory cell that records if this table matches any
- ** row of the left table of the join.
- */
- assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
- || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
- );
- if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
- pLevel->iLeftJoin = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
- VdbeComment((v, "init LEFT JOIN no-match flag"));
- }
-
- /* Compute a safe address to jump to if we discover that the table for
- ** this loop is empty and can never contribute content. */
- for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){}
- addrHalt = pWInfo->a[j].addrBrk;
-
- /* Special case of a FROM clause subquery implemented as a co-routine */
- if( pTabItem->fg.viaCoroutine ){
- int regYield = pTabItem->regReturn;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
- pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
- VdbeCoverage(v);
- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
- pLevel->op = OP_Goto;
- }else
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
- /* Case 1: The table is a virtual-table. Use the VFilter and VNext
- ** to access the data.
- */
- int iReg; /* P3 Value for OP_VFilter */
- int addrNotFound;
- int nConstraint = pLoop->nLTerm;
- int iIn; /* Counter for IN constraints */
-
- sqlite3ExprCachePush(pParse);
- iReg = sqlite3GetTempRange(pParse, nConstraint+2);
- addrNotFound = pLevel->addrBrk;
- for(j=0; j<nConstraint; j++){
- int iTarget = iReg+j+2;
- pTerm = pLoop->aLTerm[j];
- if( NEVER(pTerm==0) ) continue;
- if( pTerm->eOperator & WO_IN ){
- codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
- addrNotFound = pLevel->addrNxt;
- }else{
- Expr *pRight = pTerm->pExpr->pRight;
- codeExprOrVector(pParse, pRight, iTarget, 1);
- }
- }
- sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
- sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
- sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
- pLoop->u.vtab.idxStr,
- pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
- VdbeCoverage(v);
- pLoop->u.vtab.needFree = 0;
- pLevel->p1 = iCur;
- pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
- pLevel->p2 = sqlite3VdbeCurrentAddr(v);
- iIn = pLevel->u.in.nIn;
- for(j=nConstraint-1; j>=0; j--){
- pTerm = pLoop->aLTerm[j];
- if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
- disableTerm(pLevel, pTerm);
- }else if( (pTerm->eOperator & WO_IN)!=0 ){
- Expr *pCompare; /* The comparison operator */
- Expr *pRight; /* RHS of the comparison */
- VdbeOp *pOp; /* Opcode to access the value of the IN constraint */
-
- /* Reload the constraint value into reg[iReg+j+2]. The same value
- ** was loaded into the same register prior to the OP_VFilter, but
- ** the xFilter implementation might have changed the datatype or
- ** encoding of the value in the register, so it *must* be reloaded. */
- assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
- if( !db->mallocFailed ){
- assert( iIn>0 );
- pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop);
- assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
- assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 );
- assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 );
- testcase( pOp->opcode==OP_Rowid );
- sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
- }
-
- /* Generate code that will continue to the next row if
- ** the IN constraint is not satisfied */
- pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0);
- assert( pCompare!=0 || db->mallocFailed );
- if( pCompare ){
- pCompare->pLeft = pTerm->pExpr->pLeft;
- pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
- if( pRight ){
- pRight->iTable = iReg+j+2;
- sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
- }
- pCompare->pLeft = 0;
- sqlite3ExprDelete(db, pCompare);
- }
- }
- }
- /* These registers need to be preserved in case there is an IN operator
- ** loop. So we could deallocate the registers here (and potentially
- ** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
- ** simpler and safer to simply not reuse the registers.
- **
- ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
- */
- sqlite3ExprCachePop(pParse);
- }else
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
- if( (pLoop->wsFlags & WHERE_IPK)!=0
- && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0
- ){
- /* Case 2: We can directly reference a single row using an
- ** equality comparison against the ROWID field. Or
- ** we reference multiple rows using a "rowid IN (...)"
- ** construct.
- */
- assert( pLoop->u.btree.nEq==1 );
- pTerm = pLoop->aLTerm[0];
- assert( pTerm!=0 );
- assert( pTerm->pExpr!=0 );
- assert( omitTable==0 );
- testcase( pTerm->wtFlags & TERM_VIRTUAL );
- iReleaseReg = ++pParse->nMem;
- iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
- if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
- addrNxt = pLevel->addrNxt;
- sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
- VdbeCoverage(v);
- sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
- VdbeComment((v, "pk"));
- pLevel->op = OP_Noop;
- }else if( (pLoop->wsFlags & WHERE_IPK)!=0
- && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
- ){
- /* Case 3: We have an inequality comparison against the ROWID field.
- */
- int testOp = OP_Noop;
- int start;
- int memEndValue = 0;
- WhereTerm *pStart, *pEnd;
-
- assert( omitTable==0 );
- j = 0;
- pStart = pEnd = 0;
- if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++];
- if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++];
- assert( pStart!=0 || pEnd!=0 );
- if( bRev ){
- pTerm = pStart;
- pStart = pEnd;
- pEnd = pTerm;
- }
- codeCursorHint(pTabItem, pWInfo, pLevel, pEnd);
- if( pStart ){
- Expr *pX; /* The expression that defines the start bound */
- int r1, rTemp; /* Registers for holding the start boundary */
- int op; /* Cursor seek operation */
-
- /* The following constant maps TK_xx codes into corresponding
- ** seek opcodes. It depends on a particular ordering of TK_xx
- */
- const u8 aMoveOp[] = {
- /* TK_GT */ OP_SeekGT,
- /* TK_LE */ OP_SeekLE,
- /* TK_LT */ OP_SeekLT,
- /* TK_GE */ OP_SeekGE
- };
- assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */
- assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */
- assert( TK_GE==TK_GT+3 ); /* ... is correcct. */
-
- assert( (pStart->wtFlags & TERM_VNULL)==0 );
- testcase( pStart->wtFlags & TERM_VIRTUAL );
- pX = pStart->pExpr;
- assert( pX!=0 );
- testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
- if( sqlite3ExprIsVector(pX->pRight) ){
- r1 = rTemp = sqlite3GetTempReg(pParse);
- codeExprOrVector(pParse, pX->pRight, r1, 1);
- testcase( pX->op==TK_GT );
- testcase( pX->op==TK_GE );
- testcase( pX->op==TK_LT );
- testcase( pX->op==TK_LE );
- op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1];
- assert( pX->op!=TK_GT || op==OP_SeekGE );
- assert( pX->op!=TK_GE || op==OP_SeekGE );
- assert( pX->op!=TK_LT || op==OP_SeekLE );
- assert( pX->op!=TK_LE || op==OP_SeekLE );
- }else{
- r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
- disableTerm(pLevel, pStart);
- op = aMoveOp[(pX->op - TK_GT)];
- }
- sqlite3VdbeAddOp3(v, op, iCur, addrBrk, r1);
- VdbeComment((v, "pk"));
- VdbeCoverageIf(v, pX->op==TK_GT);
- VdbeCoverageIf(v, pX->op==TK_LE);
- VdbeCoverageIf(v, pX->op==TK_LT);
- VdbeCoverageIf(v, pX->op==TK_GE);
- sqlite3ExprCacheAffinityChange(pParse, r1, 1);
- sqlite3ReleaseTempReg(pParse, rTemp);
- }else{
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
- VdbeCoverageIf(v, bRev==0);
- VdbeCoverageIf(v, bRev!=0);
- }
- if( pEnd ){
- Expr *pX;
- pX = pEnd->pExpr;
- assert( pX!=0 );
- assert( (pEnd->wtFlags & TERM_VNULL)==0 );
- testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */
- testcase( pEnd->wtFlags & TERM_VIRTUAL );
- memEndValue = ++pParse->nMem;
- codeExprOrVector(pParse, pX->pRight, memEndValue, 1);
- if( 0==sqlite3ExprIsVector(pX->pRight)
- && (pX->op==TK_LT || pX->op==TK_GT)
- ){
- testOp = bRev ? OP_Le : OP_Ge;
- }else{
- testOp = bRev ? OP_Lt : OP_Gt;
- }
- if( 0==sqlite3ExprIsVector(pX->pRight) ){
- disableTerm(pLevel, pEnd);
- }
- }
- start = sqlite3VdbeCurrentAddr(v);
- pLevel->op = bRev ? OP_Prev : OP_Next;
- pLevel->p1 = iCur;
- pLevel->p2 = start;
- assert( pLevel->p5==0 );
- if( testOp!=OP_Noop ){
- iRowidReg = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
- sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
- VdbeCoverageIf(v, testOp==OP_Le);
- VdbeCoverageIf(v, testOp==OP_Lt);
- VdbeCoverageIf(v, testOp==OP_Ge);
- VdbeCoverageIf(v, testOp==OP_Gt);
- sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
- }
- }else if( pLoop->wsFlags & WHERE_INDEXED ){
- /* Case 4: A scan using an index.
- **
- ** The WHERE clause may contain zero or more equality
- ** terms ("==" or "IN" operators) that refer to the N
- ** left-most columns of the index. It may also contain
- ** inequality constraints (>, <, >= or <=) on the indexed
- ** column that immediately follows the N equalities. Only
- ** the right-most column can be an inequality - the rest must
- ** use the "==" and "IN" operators. For example, if the
- ** index is on (x,y,z), then the following clauses are all
- ** optimized:
- **
- ** x=5
- ** x=5 AND y=10
- ** x=5 AND y<10
- ** x=5 AND y>5 AND y<10
- ** x=5 AND y=5 AND z<=10
- **
- ** The z<10 term of the following cannot be used, only
- ** the x=5 term:
- **
- ** x=5 AND z<10
- **
- ** N may be zero if there are inequality constraints.
- ** If there are no inequality constraints, then N is at
- ** least one.
- **
- ** This case is also used when there are no WHERE clause
- ** constraints but an index is selected anyway, in order
- ** to force the output order to conform to an ORDER BY.
- */
- static const u8 aStartOp[] = {
- 0,
- 0,
- OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */
- OP_Last, /* 3: (!start_constraints && startEq && bRev) */
- OP_SeekGT, /* 4: (start_constraints && !startEq && !bRev) */
- OP_SeekLT, /* 5: (start_constraints && !startEq && bRev) */
- OP_SeekGE, /* 6: (start_constraints && startEq && !bRev) */
- OP_SeekLE /* 7: (start_constraints && startEq && bRev) */
- };
- static const u8 aEndOp[] = {
- OP_IdxGE, /* 0: (end_constraints && !bRev && !endEq) */
- OP_IdxGT, /* 1: (end_constraints && !bRev && endEq) */
- OP_IdxLE, /* 2: (end_constraints && bRev && !endEq) */
- OP_IdxLT, /* 3: (end_constraints && bRev && endEq) */
- };
- u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */
- u16 nBtm = pLoop->u.btree.nBtm; /* Length of BTM vector */
- u16 nTop = pLoop->u.btree.nTop; /* Length of TOP vector */
- int regBase; /* Base register holding constraint values */
- WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */
- WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */
- int startEq; /* True if range start uses ==, >= or <= */
- int endEq; /* True if range end uses ==, >= or <= */
- int start_constraints; /* Start of range is constrained */
- int nConstraint; /* Number of constraint terms */
- int iIdxCur; /* The VDBE cursor for the index */
- int nExtraReg = 0; /* Number of extra registers needed */
- int op; /* Instruction opcode */
- char *zStartAff; /* Affinity for start of range constraint */
- char *zEndAff = 0; /* Affinity for end of range constraint */
- u8 bSeekPastNull = 0; /* True to seek past initial nulls */
- u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
-
- pIdx = pLoop->u.btree.pIndex;
- iIdxCur = pLevel->iIdxCur;
- assert( nEq>=pLoop->nSkip );
-
- /* If this loop satisfies a sort order (pOrderBy) request that
- ** was passed to this function to implement a "SELECT min(x) ..."
- ** query, then the caller will only allow the loop to run for
- ** a single iteration. This means that the first row returned
- ** should not have a NULL value stored in 'x'. If column 'x' is
- ** the first one after the nEq equality constraints in the index,
- ** this requires some special handling.
- */
- assert( pWInfo->pOrderBy==0
- || pWInfo->pOrderBy->nExpr==1
- || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 );
- if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
- && pWInfo->nOBSat>0
- && (pIdx->nKeyCol>nEq)
- ){
- assert( pLoop->nSkip==0 );
- bSeekPastNull = 1;
- nExtraReg = 1;
- }
-
- /* Find any inequality constraint terms for the start and end
- ** of the range.
- */
- j = nEq;
- if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
- pRangeStart = pLoop->aLTerm[j++];
- nExtraReg = MAX(nExtraReg, pLoop->u.btree.nBtm);
- /* Like optimization range constraints always occur in pairs */
- assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 ||
- (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 );
- }
- if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
- pRangeEnd = pLoop->aLTerm[j++];
- nExtraReg = MAX(nExtraReg, pLoop->u.btree.nTop);
-#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){
- assert( pRangeStart!=0 ); /* LIKE opt constraints */
- assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */
- pLevel->iLikeRepCntr = (u32)++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)pLevel->iLikeRepCntr);
- VdbeComment((v, "LIKE loop counter"));
- pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
- /* iLikeRepCntr actually stores 2x the counter register number. The
- ** bottom bit indicates whether the search order is ASC or DESC. */
- testcase( bRev );
- testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
- assert( (bRev & ~1)==0 );
- pLevel->iLikeRepCntr <<=1;
- pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
- }
-#endif
- if( pRangeStart==0 ){
- j = pIdx->aiColumn[nEq];
- if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
- bSeekPastNull = 1;
- }
- }
- }
- assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
-
- /* If we are doing a reverse order scan on an ascending index, or
- ** a forward order scan on a descending index, interchange the
- ** start and end terms (pRangeStart and pRangeEnd).
- */
- if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
- || (bRev && pIdx->nKeyCol==nEq)
- ){
- SWAP(WhereTerm *, pRangeEnd, pRangeStart);
- SWAP(u8, bSeekPastNull, bStopAtNull);
- SWAP(u8, nBtm, nTop);
- }
-
- /* Generate code to evaluate all constraint terms using == or IN
- ** and store the values of those terms in an array of registers
- ** starting at regBase.
- */
- codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd);
- regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
- assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
- if( zStartAff && nTop ){
- zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]);
- }
- addrNxt = pLevel->addrNxt;
-
- testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
- testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
- testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 );
- testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 );
- startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
- endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
- start_constraints = pRangeStart || nEq>0;
-
- /* Seek the index cursor to the start of the range. */
- nConstraint = nEq;
- if( pRangeStart ){
- Expr *pRight = pRangeStart->pExpr->pRight;
- codeExprOrVector(pParse, pRight, regBase+nEq, nBtm);
- whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
- if( (pRangeStart->wtFlags & TERM_VNULL)==0
- && sqlite3ExprCanBeNull(pRight)
- ){
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
- VdbeCoverage(v);
- }
- if( zStartAff ){
- updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
- }
- nConstraint += nBtm;
- testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
- if( sqlite3ExprIsVector(pRight)==0 ){
- disableTerm(pLevel, pRangeStart);
- }else{
- startEq = 1;
- }
- bSeekPastNull = 0;
- }else if( bSeekPastNull ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
- nConstraint++;
- startEq = 0;
- start_constraints = 1;
- }
- codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
- if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){
- /* The skip-scan logic inside the call to codeAllEqualityConstraints()
- ** above has already left the cursor sitting on the correct row,
- ** so no further seeking is needed */
- }else{
- op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
- assert( op!=0 );
- sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
- VdbeCoverage(v);
- VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
- VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last );
- VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT );
- VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
- VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
- VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT );
- }
-
- /* Load the value for the inequality constraint at the end of the
- ** range (if any).
- */
- nConstraint = nEq;
- if( pRangeEnd ){
- Expr *pRight = pRangeEnd->pExpr->pRight;
- sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
- codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
- whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
- if( (pRangeEnd->wtFlags & TERM_VNULL)==0
- && sqlite3ExprCanBeNull(pRight)
- ){
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
- VdbeCoverage(v);
- }
- if( zEndAff ){
- updateRangeAffinityStr(pRight, nTop, zEndAff);
- codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
- }else{
- assert( pParse->db->mallocFailed );
- }
- nConstraint += nTop;
- testcase( pRangeEnd->wtFlags & TERM_VIRTUAL );
-
- if( sqlite3ExprIsVector(pRight)==0 ){
- disableTerm(pLevel, pRangeEnd);
- }else{
- endEq = 1;
- }
- }else if( bStopAtNull ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
- sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
- endEq = 0;
- nConstraint++;
- }
- sqlite3DbFree(db, zStartAff);
- sqlite3DbFree(db, zEndAff);
-
- /* Top of the loop body */
- pLevel->p2 = sqlite3VdbeCurrentAddr(v);
-
- /* Check if the index cursor is past the end of the range. */
- if( nConstraint ){
- op = aEndOp[bRev*2 + endEq];
- sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
- testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
- testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
- testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
- testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
- }
-
- /* Seek the table cursor, if required */
- if( omitTable ){
- /* pIdx is a covering index. No need to access the main table. */
- }else if( HasRowid(pIdx->pTable) ){
- if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
- (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)
- && (pWInfo->eOnePass==ONEPASS_SINGLE)
- )){
- iRowidReg = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
- VdbeCoverage(v);
- }else{
- codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
- }
- }else if( iCur!=iIdxCur ){
- Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
- iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
- for(j=0; j<pPk->nKeyCol; j++){
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
- }
- sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
- iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
- }
-
- /* If pIdx is an index on one or more expressions, then look through
- ** all the expressions in pWInfo and try to transform matching expressions
- ** into reference to index columns.
- **
- ** Do not do this for the RHS of a LEFT JOIN. This is because the
- ** expression may be evaluated after OP_NullRow has been executed on
- ** the cursor. In this case it is important to do the full evaluation,
- ** as the result of the expression may not be NULL, even if all table
- ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
- */
- if( pLevel->iLeftJoin==0 ){
- whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
- }
-
- /* Record the instruction used to terminate the loop. */
- if( pLoop->wsFlags & WHERE_ONEROW ){
- pLevel->op = OP_Noop;
- }else if( bRev ){
- pLevel->op = OP_Prev;
- }else{
- pLevel->op = OP_Next;
- }
- pLevel->p1 = iIdxCur;
- pLevel->p3 = (pLoop->wsFlags&WHERE_UNQ_WANTED)!=0 ? 1:0;
- if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
- pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
- }else{
- assert( pLevel->p5==0 );
- }
- if( omitTable ) pIdx = 0;
- }else
-
-#ifndef SQLITE_OMIT_OR_OPTIMIZATION
- if( pLoop->wsFlags & WHERE_MULTI_OR ){
- /* Case 5: Two or more separately indexed terms connected by OR
- **
- ** Example:
- **
- ** CREATE TABLE t1(a,b,c,d);
- ** CREATE INDEX i1 ON t1(a);
- ** CREATE INDEX i2 ON t1(b);
- ** CREATE INDEX i3 ON t1(c);
- **
- ** SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13)
- **
- ** In the example, there are three indexed terms connected by OR.
- ** The top of the loop looks like this:
- **
- ** Null 1 # Zero the rowset in reg 1
- **
- ** Then, for each indexed term, the following. The arguments to
- ** RowSetTest are such that the rowid of the current row is inserted
- ** into the RowSet. If it is already present, control skips the
- ** Gosub opcode and jumps straight to the code generated by WhereEnd().
- **
- ** sqlite3WhereBegin(<term>)
- ** RowSetTest # Insert rowid into rowset
- ** Gosub 2 A
- ** sqlite3WhereEnd()
- **
- ** Following the above, code to terminate the loop. Label A, the target
- ** of the Gosub above, jumps to the instruction right after the Goto.
- **
- ** Null 1 # Zero the rowset in reg 1
- ** Goto B # The loop is finished.
- **
- ** A: <loop body> # Return data, whatever.
- **
- ** Return 2 # Jump back to the Gosub
- **
- ** B: <after the loop>
- **
- ** Added 2014-05-26: If the table is a WITHOUT ROWID table, then
- ** use an ephemeral index instead of a RowSet to record the primary
- ** keys of the rows we have already seen.
- **
- */
- WhereClause *pOrWc; /* The OR-clause broken out into subterms */
- SrcList *pOrTab; /* Shortened table list or OR-clause generation */
- Index *pCov = 0; /* Potential covering index (or NULL) */
- int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */
-
- int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
- int regRowset = 0; /* Register for RowSet object */
- int regRowid = 0; /* Register holding rowid */
- int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
- int iRetInit; /* Address of regReturn init */
- int untestedTerms = 0; /* Some terms not completely tested */
- int ii; /* Loop counter */
- u16 wctrlFlags; /* Flags for sub-WHERE clause */
- Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
- Table *pTab = pTabItem->pTab;
-
- pTerm = pLoop->aLTerm[0];
- assert( pTerm!=0 );
- assert( pTerm->eOperator & WO_OR );
- assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
- pOrWc = &pTerm->u.pOrInfo->wc;
- pLevel->op = OP_Return;
- pLevel->p1 = regReturn;
-
- /* Set up a new SrcList in pOrTab containing the table being scanned
- ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
- ** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
- */
- if( pWInfo->nLevel>1 ){
- int nNotReady; /* The number of notReady tables */
- struct SrcList_item *origSrc; /* Original list of tables */
- nNotReady = pWInfo->nLevel - iLevel - 1;
- pOrTab = sqlite3StackAllocRaw(db,
- sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
- if( pOrTab==0 ) return notReady;
- pOrTab->nAlloc = (u8)(nNotReady + 1);
- pOrTab->nSrc = pOrTab->nAlloc;
- memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
- origSrc = pWInfo->pTabList->a;
- for(k=1; k<=nNotReady; k++){
- memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
- }
- }else{
- pOrTab = pWInfo->pTabList;
- }
-
- /* Initialize the rowset register to contain NULL. An SQL NULL is
- ** equivalent to an empty rowset. Or, create an ephemeral index
- ** capable of holding primary keys in the case of a WITHOUT ROWID.
- **
- ** Also initialize regReturn to contain the address of the instruction
- ** immediately following the OP_Return at the bottom of the loop. This
- ** is required in a few obscure LEFT JOIN cases where control jumps
- ** over the top of the loop into the body of it. In this case the
- ** correct response for the end-of-loop code (the OP_Return) is to
- ** fall through to the next instruction, just as an OP_Next does if
- ** called on an uninitialized cursor.
- */
- if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
- if( HasRowid(pTab) ){
- regRowset = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
- }else{
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- regRowset = pParse->nTab++;
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol);
- sqlite3VdbeSetP4KeyInfo(pParse, pPk);
- }
- regRowid = ++pParse->nMem;
- }
- iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
-
- /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
- ** Then for every term xN, evaluate as the subexpression: xN AND z
- ** That way, terms in y that are factored into the disjunction will
- ** be picked up by the recursive calls to sqlite3WhereBegin() below.
- **
- ** Actually, each subexpression is converted to "xN AND w" where w is
- ** the "interesting" terms of z - terms that did not originate in the
- ** ON or USING clause of a LEFT JOIN, and terms that are usable as
- ** indices.
- **
- ** This optimization also only applies if the (x1 OR x2 OR ...) term
- ** is not contained in the ON clause of a LEFT JOIN.
- ** See ticket http://www.sqlite.org/src/info/f2369304e4
- */
- if( pWC->nTerm>1 ){
- int iTerm;
- for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
- Expr *pExpr = pWC->a[iTerm].pExpr;
- if( &pWC->a[iTerm] == pTerm ) continue;
- testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
- testcase( pWC->a[iTerm].wtFlags & TERM_CODED );
- if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue;
- if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
- testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
- pExpr = sqlite3ExprDup(db, pExpr, 0);
- pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
- }
- if( pAndExpr ){
- pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr);
- }
- }
-
- /* Run a separate WHERE clause for each term of the OR clause. After
- ** eliminating duplicates from other WHERE clauses, the action for each
- ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
- */
- wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
- ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
- for(ii=0; ii<pOrWc->nTerm; ii++){
- WhereTerm *pOrTerm = &pOrWc->a[ii];
- if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
- WhereInfo *pSubWInfo; /* Info for single OR-term scan */
- Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
- int jmp1 = 0; /* Address of jump operation */
- assert( (pTabItem[0].fg.jointype & JT_LEFT)==0
- || ExprHasProperty(pOrExpr, EP_FromJoin)
- );
- if( pAndExpr ){
- pAndExpr->pLeft = pOrExpr;
- pOrExpr = pAndExpr;
- }
- /* Loop through table entries that match term pOrTerm. */
- WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
- pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
- wctrlFlags, iCovCur);
- assert( pSubWInfo || pParse->nErr || db->mallocFailed );
- if( pSubWInfo ){
- WhereLoop *pSubLoop;
- int addrExplain = sqlite3WhereExplainOneScan(
- pParse, pOrTab, &pSubWInfo->a[0], 0
- );
- sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain);
-
- /* This is the sub-WHERE clause body. First skip over
- ** duplicate rows from prior sub-WHERE clauses, and record the
- ** rowid (or PRIMARY KEY) for the current row so that the same
- ** row will be skipped in subsequent sub-WHERE clauses.
- */
- if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
- int r;
- int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
- if( HasRowid(pTab) ){
- r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0);
- jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0,
- r,iSet);
- VdbeCoverage(v);
- }else{
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- int nPk = pPk->nKeyCol;
- int iPk;
-
- /* Read the PK into an array of temp registers. */
- r = sqlite3GetTempRange(pParse, nPk);
- for(iPk=0; iPk<nPk; iPk++){
- int iCol = pPk->aiColumn[iPk];
- sqlite3ExprCodeGetColumnToReg(pParse, pTab, iCol, iCur, r+iPk);
- }
-
- /* Check if the temp table already contains this key. If so,
- ** the row has already been included in the result set and
- ** can be ignored (by jumping past the Gosub below). Otherwise,
- ** insert the key into the temp table and proceed with processing
- ** the row.
- **
- ** Use some of the same optimizations as OP_RowSetTest: If iSet
- ** is zero, assume that the key cannot already be present in
- ** the temp table. And if iSet is -1, assume that there is no
- ** need to insert the key into the temp table, as it will never
- ** be tested for. */
- if( iSet ){
- jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk);
- VdbeCoverage(v);
- }
- if( iSet>=0 ){
- sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid,
- r, nPk);
- if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- }
-
- /* Release the array of temp registers */
- sqlite3ReleaseTempRange(pParse, r, nPk);
- }
- }
-
- /* Invoke the main loop body as a subroutine */
- sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
-
- /* Jump here (skipping the main loop body subroutine) if the
- ** current sub-WHERE row is a duplicate from prior sub-WHEREs. */
- if( jmp1 ) sqlite3VdbeJumpHere(v, jmp1);
-
- /* The pSubWInfo->untestedTerms flag means that this OR term
- ** contained one or more AND term from a notReady table. The
- ** terms from the notReady table could not be tested and will
- ** need to be tested later.
- */
- if( pSubWInfo->untestedTerms ) untestedTerms = 1;
-
- /* If all of the OR-connected terms are optimized using the same
- ** index, and the index is opened using the same cursor number
- ** by each call to sqlite3WhereBegin() made by this loop, it may
- ** be possible to use that index as a covering index.
- **
- ** If the call to sqlite3WhereBegin() above resulted in a scan that
- ** uses an index, and this is either the first OR-connected term
- ** processed or the index is the same as that used by all previous
- ** terms, set pCov to the candidate covering index. Otherwise, set
- ** pCov to NULL to indicate that no candidate covering index will
- ** be available.
- */
- pSubLoop = pSubWInfo->a[0].pWLoop;
- assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
- if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
- && (ii==0 || pSubLoop->u.btree.pIndex==pCov)
- && (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
- ){
- assert( pSubWInfo->a[0].iIdxCur==iCovCur );
- pCov = pSubLoop->u.btree.pIndex;
- }else{
- pCov = 0;
- }
-
- /* Finish the loop through table entries that match term pOrTerm. */
- sqlite3WhereEnd(pSubWInfo);
- }
- }
- }
- ExplainQueryPlanPop(pParse);
- pLevel->u.pCovidx = pCov;
- if( pCov ) pLevel->iIdxCur = iCovCur;
- if( pAndExpr ){
- pAndExpr->pLeft = 0;
- sqlite3ExprDelete(db, pAndExpr);
- }
- sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
- sqlite3VdbeGoto(v, pLevel->addrBrk);
- sqlite3VdbeResolveLabel(v, iLoopBody);
-
- if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab);
- if( !untestedTerms ) disableTerm(pLevel, pTerm);
- }else
-#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
-
- {
- /* Case 6: There is no usable index. We must do a complete
- ** scan of the entire table.
- */
- static const u8 aStep[] = { OP_Next, OP_Prev };
- static const u8 aStart[] = { OP_Rewind, OP_Last };
- assert( bRev==0 || bRev==1 );
- if( pTabItem->fg.isRecursive ){
- /* Tables marked isRecursive have only a single row that is stored in
- ** a pseudo-cursor. No need to Rewind or Next such cursors. */
- pLevel->op = OP_Noop;
- }else{
- codeCursorHint(pTabItem, pWInfo, pLevel, 0);
- pLevel->op = aStep[bRev];
- pLevel->p1 = iCur;
- pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt);
- VdbeCoverageIf(v, bRev==0);
- VdbeCoverageIf(v, bRev!=0);
- pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
- }
- }
-
-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- pLevel->addrVisit = sqlite3VdbeCurrentAddr(v);
-#endif
-
- /* Insert code to test every subexpression that can be completely
- ** computed using the current set of tables.
- **
- ** This loop may run between one and three times, depending on the
- ** constraints to be generated. The value of stack variable iLoop
- ** determines the constraints coded by each iteration, as follows:
- **
- ** iLoop==1: Code only expressions that are entirely covered by pIdx.
- ** iLoop==2: Code remaining expressions that do not contain correlated
- ** sub-queries.
- ** iLoop==3: Code all remaining expressions.
- **
- ** An effort is made to skip unnecessary iterations of the loop.
- */
- iLoop = (pIdx ? 1 : 2);
- do{
- int iNext = 0; /* Next value for iLoop */
- for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
- Expr *pE;
- int skipLikeAddr = 0;
- testcase( pTerm->wtFlags & TERM_VIRTUAL );
- testcase( pTerm->wtFlags & TERM_CODED );
- if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
- if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
- testcase( pWInfo->untestedTerms==0
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
- pWInfo->untestedTerms = 1;
- continue;
- }
- pE = pTerm->pExpr;
- assert( pE!=0 );
- if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){
- continue;
- }
-
- if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
- iNext = 2;
- continue;
- }
- if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){
- if( iNext==0 ) iNext = 3;
- continue;
- }
-
- if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){
- /* If the TERM_LIKECOND flag is set, that means that the range search
- ** is sufficient to guarantee that the LIKE operator is true, so we
- ** can skip the call to the like(A,B) function. But this only works
- ** for strings. So do not skip the call to the function on the pass
- ** that compares BLOBs. */
-#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- continue;
-#else
- u32 x = pLevel->iLikeRepCntr;
- if( x>0 ){
- skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1));
- }
- VdbeCoverage(v);
-#endif
- }
-#ifdef WHERETRACE_ENABLED /* 0xffff */
- if( sqlite3WhereTrace ){
- VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d",
- pWC->nTerm-j, pTerm, iLoop));
- }
-#endif
- sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
- if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
- pTerm->wtFlags |= TERM_CODED;
- }
- iLoop = iNext;
- }while( iLoop>0 );
-
- /* Insert code to test for implied constraints based on transitivity
- ** of the "==" operator.
- **
- ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123"
- ** and we are coding the t1 loop and the t2 loop has not yet coded,
- ** then we cannot use the "t1.a=t2.b" constraint, but we can code
- ** the implied "t1.a=123" constraint.
- */
- for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
- Expr *pE, sEAlt;
- WhereTerm *pAlt;
- if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
- if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
- if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
- if( pTerm->leftCursor!=iCur ) continue;
- if( pLevel->iLeftJoin ) continue;
- pE = pTerm->pExpr;
- assert( !ExprHasProperty(pE, EP_FromJoin) );
- assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
- pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
- WO_EQ|WO_IN|WO_IS, 0);
- if( pAlt==0 ) continue;
- if( pAlt->wtFlags & (TERM_CODED) ) continue;
- if( (pAlt->eOperator & WO_IN)
- && (pAlt->pExpr->flags & EP_xIsSelect)
- && (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
- ){
- continue;
- }
- testcase( pAlt->eOperator & WO_EQ );
- testcase( pAlt->eOperator & WO_IS );
- testcase( pAlt->eOperator & WO_IN );
- VdbeModuleComment((v, "begin transitive constraint"));
- sEAlt = *pAlt->pExpr;
- sEAlt.pLeft = pE->pLeft;
- sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
- }
-
- /* For a LEFT OUTER JOIN, generate code that will record the fact that
- ** at least one row of the right table has matched the left table.
- */
- if( pLevel->iLeftJoin ){
- pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
- VdbeComment((v, "record LEFT JOIN hit"));
- sqlite3ExprCacheClear(pParse);
- for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
- testcase( pTerm->wtFlags & TERM_VIRTUAL );
- testcase( pTerm->wtFlags & TERM_CODED );
- if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
- if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
- assert( pWInfo->untestedTerms );
- continue;
- }
- assert( pTerm->pExpr );
- sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
- pTerm->wtFlags |= TERM_CODED;
- }
- }
-
- return pLevel->notReady;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/src/whereexpr.c b/chromium/third_party/sqlite/sqlite-src-3240000/src/whereexpr.c
deleted file mode 100644
index 29750080a12..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/src/whereexpr.c
+++ /dev/null
@@ -1,1531 +0,0 @@
-/*
-** 2015-06-08
-**
-** 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 module contains C code that generates VDBE code used to process
-** the WHERE clause of SQL statements.
-**
-** This file was originally part of where.c but was split out to improve
-** readability and editabiliity. This file contains utility routines for
-** analyzing Expr objects in the WHERE clause.
-*/
-#include "sqliteInt.h"
-#include "whereInt.h"
-
-/* Forward declarations */
-static void exprAnalyze(SrcList*, WhereClause*, int);
-
-/*
-** Deallocate all memory associated with a WhereOrInfo object.
-*/
-static void whereOrInfoDelete(sqlite3 *db, WhereOrInfo *p){
- sqlite3WhereClauseClear(&p->wc);
- sqlite3DbFree(db, p);
-}
-
-/*
-** Deallocate all memory associated with a WhereAndInfo object.
-*/
-static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){
- sqlite3WhereClauseClear(&p->wc);
- sqlite3DbFree(db, p);
-}
-
-/*
-** Add a single new WhereTerm entry to the WhereClause object pWC.
-** The new WhereTerm object is constructed from Expr p and with wtFlags.
-** The index in pWC->a[] of the new WhereTerm is returned on success.
-** 0 is returned if the new WhereTerm could not be added due to a memory
-** allocation error. The memory allocation failure will be recorded in
-** the db->mallocFailed flag so that higher-level functions can detect it.
-**
-** This routine will increase the size of the pWC->a[] array as necessary.
-**
-** If the wtFlags argument includes TERM_DYNAMIC, then responsibility
-** for freeing the expression p is assumed by the WhereClause object pWC.
-** This is true even if this routine fails to allocate a new WhereTerm.
-**
-** WARNING: This routine might reallocate the space used to store
-** WhereTerms. All pointers to WhereTerms should be invalidated after
-** calling this routine. Such pointers may be reinitialized by referencing
-** the pWC->a[] array.
-*/
-static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
- WhereTerm *pTerm;
- int idx;
- testcase( wtFlags & TERM_VIRTUAL );
- if( pWC->nTerm>=pWC->nSlot ){
- WhereTerm *pOld = pWC->a;
- sqlite3 *db = pWC->pWInfo->pParse->db;
- pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
- if( pWC->a==0 ){
- if( wtFlags & TERM_DYNAMIC ){
- sqlite3ExprDelete(db, p);
- }
- pWC->a = pOld;
- return 0;
- }
- memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
- if( pOld!=pWC->aStatic ){
- sqlite3DbFree(db, pOld);
- }
- pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
- }
- pTerm = &pWC->a[idx = pWC->nTerm++];
- if( p && ExprHasProperty(p, EP_Unlikely) ){
- pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
- }else{
- pTerm->truthProb = 1;
- }
- pTerm->pExpr = sqlite3ExprSkipCollate(p);
- pTerm->wtFlags = wtFlags;
- pTerm->pWC = pWC;
- pTerm->iParent = -1;
- memset(&pTerm->eOperator, 0,
- sizeof(WhereTerm) - offsetof(WhereTerm,eOperator));
- return idx;
-}
-
-/*
-** Return TRUE if the given operator is one of the operators that is
-** allowed for an indexable WHERE clause term. The allowed operators are
-** "=", "<", ">", "<=", ">=", "IN", "IS", and "IS NULL"
-*/
-static int allowedOp(int op){
- assert( TK_GT>TK_EQ && TK_GT<TK_GE );
- assert( TK_LT>TK_EQ && TK_LT<TK_GE );
- assert( TK_LE>TK_EQ && TK_LE<TK_GE );
- assert( TK_GE==TK_EQ+4 );
- return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
-}
-
-/*
-** Commute a comparison operator. Expressions of the form "X op Y"
-** are converted into "Y op X".
-**
-** If left/right precedence rules come into play when determining the
-** collating sequence, then COLLATE operators are adjusted to ensure
-** that the collating sequence does not change. For example:
-** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
-** the left hand side of a comparison overrides any collation sequence
-** attached to the right. For the same reason the EP_Collate flag
-** is not commuted.
-*/
-static void exprCommute(Parse *pParse, Expr *pExpr){
- u16 expRight = (pExpr->pRight->flags & EP_Collate);
- u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
- assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
- if( expRight==expLeft ){
- /* Either X and Y both have COLLATE operator or neither do */
- if( expRight ){
- /* Both X and Y have COLLATE operators. Make sure X is always
- ** used by clearing the EP_Collate flag from Y. */
- pExpr->pRight->flags &= ~EP_Collate;
- }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
- /* Neither X nor Y have COLLATE operators, but X has a non-default
- ** collating sequence. So add the EP_Collate marker on X to cause
- ** it to be searched first. */
- pExpr->pLeft->flags |= EP_Collate;
- }
- }
- SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
- if( pExpr->op>=TK_GT ){
- assert( TK_LT==TK_GT+2 );
- assert( TK_GE==TK_LE+2 );
- assert( TK_GT>TK_EQ );
- assert( TK_GT<TK_LE );
- assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
- pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
- }
-}
-
-/*
-** Translate from TK_xx operator to WO_xx bitmask.
-*/
-static u16 operatorMask(int op){
- u16 c;
- assert( allowedOp(op) );
- if( op==TK_IN ){
- c = WO_IN;
- }else if( op==TK_ISNULL ){
- c = WO_ISNULL;
- }else if( op==TK_IS ){
- c = WO_IS;
- }else{
- assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
- c = (u16)(WO_EQ<<(op-TK_EQ));
- }
- assert( op!=TK_ISNULL || c==WO_ISNULL );
- assert( op!=TK_IN || c==WO_IN );
- assert( op!=TK_EQ || c==WO_EQ );
- assert( op!=TK_LT || c==WO_LT );
- assert( op!=TK_LE || c==WO_LE );
- assert( op!=TK_GT || c==WO_GT );
- assert( op!=TK_GE || c==WO_GE );
- assert( op!=TK_IS || c==WO_IS );
- return c;
-}
-
-
-#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
-/*
-** Check to see if the given expression is a LIKE or GLOB operator that
-** can be optimized using inequality constraints. Return TRUE if it is
-** so and false if not.
-**
-** In order for the operator to be optimizible, the RHS must be a string
-** literal that does not begin with a wildcard. The LHS must be a column
-** that may only be NULL, a string, or a BLOB, never a number. (This means
-** that virtual tables cannot participate in the LIKE optimization.) The
-** collating sequence for the column on the LHS must be appropriate for
-** the operator.
-*/
-static int isLikeOrGlob(
- Parse *pParse, /* Parsing and code generating context */
- Expr *pExpr, /* Test this expression */
- Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */
- int *pisComplete, /* True if the only wildcard is % in the last character */
- int *pnoCase /* True if uppercase is equivalent to lowercase */
-){
- const u8 *z = 0; /* String on RHS of LIKE operator */
- Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
- ExprList *pList; /* List of operands to the LIKE operator */
- int c; /* One character in z[] */
- int cnt; /* Number of non-wildcard prefix characters */
- char wc[4]; /* Wildcard characters */
- sqlite3 *db = pParse->db; /* Database connection */
- sqlite3_value *pVal = 0;
- int op; /* Opcode of pRight */
- int rc; /* Result code to return */
-
- if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
- return 0;
- }
-#ifdef SQLITE_EBCDIC
- if( *pnoCase ) return 0;
-#endif
- pList = pExpr->x.pList;
- pLeft = pList->a[1].pExpr;
-
- pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
- op = pRight->op;
- if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
- Vdbe *pReprepare = pParse->pReprepare;
- int iCol = pRight->iColumn;
- pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB);
- if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
- z = sqlite3_value_text(pVal);
- }
- sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
- assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
- }else if( op==TK_STRING ){
- z = (u8*)pRight->u.zToken;
- }
- if( z ){
-
- /* If the RHS begins with a digit or a minus sign, then the LHS must
- ** be an ordinary column (not a virtual table column) with TEXT affinity.
- ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false
- ** even though "lhs LIKE rhs" is true. But if the RHS does not start
- ** with a digit or '-', then "lhs LIKE rhs" will always be false if
- ** the LHS is numeric and so the optimization still works.
- */
- if( sqlite3Isdigit(z[0]) || z[0]=='-' ){
- if( pLeft->op!=TK_COLUMN
- || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
- || IsVirtual(pLeft->pTab) /* Value might be numeric */
- ){
- sqlite3ValueFree(pVal);
- return 0;
- }
- }
-
- /* Count the number of prefix characters prior to the first wildcard */
- cnt = 0;
- while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
- cnt++;
- if( c==wc[3] && z[cnt]!=0 ) cnt++;
- }
-
- /* The optimization is possible only if (1) the pattern does not begin
- ** with a wildcard and if (2) the non-wildcard prefix does not end with
- ** an (illegal 0xff) character. The second condition is necessary so
- ** that we can increment the prefix key to find an upper bound for the
- ** range search.
- */
- if( cnt!=0 && 255!=(u8)z[cnt-1] ){
- Expr *pPrefix;
-
- /* A "complete" match if the pattern ends with "*" or "%" */
- *pisComplete = c==wc[0] && z[cnt+1]==0;
-
- /* Get the pattern prefix. Remove all escapes from the prefix. */
- pPrefix = sqlite3Expr(db, TK_STRING, (char*)z);
- if( pPrefix ){
- int iFrom, iTo;
- char *zNew = pPrefix->u.zToken;
- zNew[cnt] = 0;
- for(iFrom=iTo=0; iFrom<cnt; iFrom++){
- if( zNew[iFrom]==wc[3] ) iFrom++;
- zNew[iTo++] = zNew[iFrom];
- }
- zNew[iTo] = 0;
- }
- *ppPrefix = pPrefix;
-
- /* If the RHS pattern is a bound parameter, make arrangements to
- ** reprepare the statement when that parameter is rebound */
- if( op==TK_VARIABLE ){
- Vdbe *v = pParse->pVdbe;
- sqlite3VdbeSetVarmask(v, pRight->iColumn);
- if( *pisComplete && pRight->u.zToken[1] ){
- /* If the rhs of the LIKE expression is a variable, and the current
- ** value of the variable means there is no need to invoke the LIKE
- ** function, then no OP_Variable will be added to the program.
- ** This causes problems for the sqlite3_bind_parameter_name()
- ** API. To work around them, add a dummy OP_Variable here.
- */
- int r1 = sqlite3GetTempReg(pParse);
- sqlite3ExprCodeTarget(pParse, pRight, r1);
- sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0);
- sqlite3ReleaseTempReg(pParse, r1);
- }
- }
- }else{
- z = 0;
- }
- }
-
- rc = (z!=0);
- sqlite3ValueFree(pVal);
- return rc;
-}
-#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
-
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*
-** Check to see if the pExpr expression is a form that needs to be passed
-** to the xBestIndex method of virtual tables. Forms of interest include:
-**
-** Expression Virtual Table Operator
-** ----------------------- ---------------------------------
-** 1. column MATCH expr SQLITE_INDEX_CONSTRAINT_MATCH
-** 2. column GLOB expr SQLITE_INDEX_CONSTRAINT_GLOB
-** 3. column LIKE expr SQLITE_INDEX_CONSTRAINT_LIKE
-** 4. column REGEXP expr SQLITE_INDEX_CONSTRAINT_REGEXP
-** 5. column != expr SQLITE_INDEX_CONSTRAINT_NE
-** 6. expr != column SQLITE_INDEX_CONSTRAINT_NE
-** 7. column IS NOT expr SQLITE_INDEX_CONSTRAINT_ISNOT
-** 8. expr IS NOT column SQLITE_INDEX_CONSTRAINT_ISNOT
-** 9. column IS NOT NULL SQLITE_INDEX_CONSTRAINT_ISNOTNULL
-**
-** In every case, "column" must be a column of a virtual table. If there
-** is a match, set *ppLeft to the "column" expression, set *ppRight to the
-** "expr" expression (even though in forms (6) and (8) the column is on the
-** right and the expression is on the left). Also set *peOp2 to the
-** appropriate virtual table operator. The return value is 1 or 2 if there
-** is a match. The usual return is 1, but if the RHS is also a column
-** of virtual table in forms (5) or (7) then return 2.
-**
-** If the expression matches none of the patterns above, return 0.
-*/
-static int isAuxiliaryVtabOperator(
- Expr *pExpr, /* Test this expression */
- unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */
- Expr **ppLeft, /* Column expression to left of MATCH/op2 */
- Expr **ppRight /* Expression to left of MATCH/op2 */
-){
- if( pExpr->op==TK_FUNCTION ){
- static const struct Op2 {
- const char *zOp;
- unsigned char eOp2;
- } aOp[] = {
- { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
- { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
- { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
- { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
- };
- ExprList *pList;
- Expr *pCol; /* Column reference */
- int i;
-
- pList = pExpr->x.pList;
- if( pList==0 || pList->nExpr!=2 ){
- return 0;
- }
- pCol = pList->a[1].pExpr;
- if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){
- return 0;
- }
- for(i=0; i<ArraySize(aOp); i++){
- if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
- *peOp2 = aOp[i].eOp2;
- *ppRight = pList->a[0].pExpr;
- *ppLeft = pCol;
- return 1;
- }
- }
- }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
- int res = 0;
- Expr *pLeft = pExpr->pLeft;
- Expr *pRight = pExpr->pRight;
- if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
- res++;
- }
- if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
- res++;
- SWAP(Expr*, pLeft, pRight);
- }
- *ppLeft = pLeft;
- *ppRight = pRight;
- if( pExpr->op==TK_NE ) *peOp2 = SQLITE_INDEX_CONSTRAINT_NE;
- if( pExpr->op==TK_ISNOT ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOT;
- if( pExpr->op==TK_NOTNULL ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOTNULL;
- return res;
- }
- return 0;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/*
-** If the pBase expression originated in the ON or USING clause of
-** a join, then transfer the appropriate markings over to derived.
-*/
-static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
- if( pDerived ){
- pDerived->flags |= pBase->flags & EP_FromJoin;
- pDerived->iRightJoinTable = pBase->iRightJoinTable;
- }
-}
-
-/*
-** Mark term iChild as being a child of term iParent
-*/
-static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
- pWC->a[iChild].iParent = iParent;
- pWC->a[iChild].truthProb = pWC->a[iParent].truthProb;
- pWC->a[iParent].nChild++;
-}
-
-/*
-** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not
-** a conjunction, then return just pTerm when N==0. If N is exceeds
-** the number of available subterms, return NULL.
-*/
-static WhereTerm *whereNthSubterm(WhereTerm *pTerm, int N){
- if( pTerm->eOperator!=WO_AND ){
- return N==0 ? pTerm : 0;
- }
- if( N<pTerm->u.pAndInfo->wc.nTerm ){
- return &pTerm->u.pAndInfo->wc.a[N];
- }
- return 0;
-}
-
-/*
-** Subterms pOne and pTwo are contained within WHERE clause pWC. The
-** two subterms are in disjunction - they are OR-ed together.
-**
-** If these two terms are both of the form: "A op B" with the same
-** A and B values but different operators and if the operators are
-** compatible (if one is = and the other is <, for example) then
-** add a new virtual AND term to pWC that is the combination of the
-** two.
-**
-** Some examples:
-**
-** x<y OR x=y --> x<=y
-** x=y OR x=y --> x=y
-** x<=y OR x<y --> x<=y
-**
-** The following is NOT generated:
-**
-** x<y OR x>y --> x!=y
-*/
-static void whereCombineDisjuncts(
- SrcList *pSrc, /* the FROM clause */
- WhereClause *pWC, /* The complete WHERE clause */
- WhereTerm *pOne, /* First disjunct */
- WhereTerm *pTwo /* Second disjunct */
-){
- u16 eOp = pOne->eOperator | pTwo->eOperator;
- sqlite3 *db; /* Database connection (for malloc) */
- Expr *pNew; /* New virtual expression */
- int op; /* Operator for the combined expression */
- int idxNew; /* Index in pWC of the next virtual term */
-
- if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
- if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
- if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
- && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
- assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
- assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
- if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
- if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return;
- /* If we reach this point, it means the two subterms can be combined */
- if( (eOp & (eOp-1))!=0 ){
- if( eOp & (WO_LT|WO_LE) ){
- eOp = WO_LE;
- }else{
- assert( eOp & (WO_GT|WO_GE) );
- eOp = WO_GE;
- }
- }
- db = pWC->pWInfo->pParse->db;
- pNew = sqlite3ExprDup(db, pOne->pExpr, 0);
- if( pNew==0 ) return;
- for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); }
- pNew->op = op;
- idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
- exprAnalyze(pSrc, pWC, idxNew);
-}
-
-#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
-/*
-** Analyze a term that consists of two or more OR-connected
-** subterms. So in:
-**
-** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13)
-** ^^^^^^^^^^^^^^^^^^^^
-**
-** This routine analyzes terms such as the middle term in the above example.
-** A WhereOrTerm object is computed and attached to the term under
-** analysis, regardless of the outcome of the analysis. Hence:
-**
-** WhereTerm.wtFlags |= TERM_ORINFO
-** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object
-**
-** The term being analyzed must have two or more of OR-connected subterms.
-** A single subterm might be a set of AND-connected sub-subterms.
-** Examples of terms under analysis:
-**
-** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5
-** (B) x=expr1 OR expr2=x OR x=expr3
-** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
-** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
-** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
-** (F) x>A OR (x=A AND y>=B)
-**
-** CASE 1:
-**
-** If all subterms are of the form T.C=expr for some single column of C and
-** a single table T (as shown in example B above) then create a new virtual
-** term that is an equivalent IN expression. In other words, if the term
-** being analyzed is:
-**
-** x = expr1 OR expr2 = x OR x = expr3
-**
-** then create a new virtual term like this:
-**
-** x IN (expr1,expr2,expr3)
-**
-** CASE 2:
-**
-** If there are exactly two disjuncts and one side has x>A and the other side
-** has x=A (for the same x and A) then add a new virtual conjunct term to the
-** WHERE clause of the form "x>=A". Example:
-**
-** x>A OR (x=A AND y>B) adds: x>=A
-**
-** The added conjunct can sometimes be helpful in query planning.
-**
-** CASE 3:
-**
-** If all subterms are indexable by a single table T, then set
-**
-** WhereTerm.eOperator = WO_OR
-** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T
-**
-** A subterm is "indexable" if it is of the form
-** "T.C <op> <expr>" where C is any column of table T and
-** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
-** A subterm is also indexable if it is an AND of two or more
-** subsubterms at least one of which is indexable. Indexable AND
-** subterms have their eOperator set to WO_AND and they have
-** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
-**
-** From another point of view, "indexable" means that the subterm could
-** potentially be used with an index if an appropriate index exists.
-** This analysis does not consider whether or not the index exists; that
-** is decided elsewhere. This analysis only looks at whether subterms
-** appropriate for indexing exist.
-**
-** All examples A through E above satisfy case 3. But if a term
-** also satisfies case 1 (such as B) we know that the optimizer will
-** always prefer case 1, so in that case we pretend that case 3 is not
-** satisfied.
-**
-** It might be the case that multiple tables are indexable. For example,
-** (E) above is indexable on tables P, Q, and R.
-**
-** Terms that satisfy case 3 are candidates for lookup by using
-** separate indices to find rowids for each subterm and composing
-** the union of all rowids using a RowSet object. This is similar
-** to "bitmap indices" in other database engines.
-**
-** OTHERWISE:
-**
-** If none of cases 1, 2, or 3 apply, then leave the eOperator set to
-** zero. This term is not useful for search.
-*/
-static void exprAnalyzeOrTerm(
- SrcList *pSrc, /* the FROM clause */
- WhereClause *pWC, /* the complete WHERE clause */
- int idxTerm /* Index of the OR-term to be analyzed */
-){
- WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
- Parse *pParse = pWInfo->pParse; /* Parser context */
- sqlite3 *db = pParse->db; /* Database connection */
- WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */
- Expr *pExpr = pTerm->pExpr; /* The expression of the term */
- int i; /* Loop counters */
- WhereClause *pOrWc; /* Breakup of pTerm into subterms */
- WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */
- WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */
- Bitmask chngToIN; /* Tables that might satisfy case 1 */
- Bitmask indexable; /* Tables that are indexable, satisfying case 2 */
-
- /*
- ** Break the OR clause into its separate subterms. The subterms are
- ** stored in a WhereClause structure containing within the WhereOrInfo
- ** object that is attached to the original OR clause term.
- */
- assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 );
- assert( pExpr->op==TK_OR );
- pTerm->u.pOrInfo = pOrInfo = sqlite3DbMallocZero(db, sizeof(*pOrInfo));
- if( pOrInfo==0 ) return;
- pTerm->wtFlags |= TERM_ORINFO;
- pOrWc = &pOrInfo->wc;
- memset(pOrWc->aStatic, 0, sizeof(pOrWc->aStatic));
- sqlite3WhereClauseInit(pOrWc, pWInfo);
- sqlite3WhereSplit(pOrWc, pExpr, TK_OR);
- sqlite3WhereExprAnalyze(pSrc, pOrWc);
- if( db->mallocFailed ) return;
- assert( pOrWc->nTerm>=2 );
-
- /*
- ** Compute the set of tables that might satisfy cases 1 or 3.
- */
- indexable = ~(Bitmask)0;
- chngToIN = ~(Bitmask)0;
- for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
- if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
- WhereAndInfo *pAndInfo;
- assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
- chngToIN = 0;
- pAndInfo = sqlite3DbMallocRawNN(db, sizeof(*pAndInfo));
- if( pAndInfo ){
- WhereClause *pAndWC;
- WhereTerm *pAndTerm;
- int j;
- Bitmask b = 0;
- pOrTerm->u.pAndInfo = pAndInfo;
- pOrTerm->wtFlags |= TERM_ANDINFO;
- pOrTerm->eOperator = WO_AND;
- pAndWC = &pAndInfo->wc;
- memset(pAndWC->aStatic, 0, sizeof(pAndWC->aStatic));
- sqlite3WhereClauseInit(pAndWC, pWC->pWInfo);
- sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
- sqlite3WhereExprAnalyze(pSrc, pAndWC);
- pAndWC->pOuter = pWC;
- if( !db->mallocFailed ){
- for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
- assert( pAndTerm->pExpr );
- if( allowedOp(pAndTerm->pExpr->op)
- || pAndTerm->eOperator==WO_AUX
- ){
- b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
- }
- }
- }
- indexable &= b;
- }
- }else if( pOrTerm->wtFlags & TERM_COPIED ){
- /* Skip this term for now. We revisit it when we process the
- ** corresponding TERM_VIRTUAL term */
- }else{
- Bitmask b;
- b = sqlite3WhereGetMask(&pWInfo->sMaskSet, pOrTerm->leftCursor);
- if( pOrTerm->wtFlags & TERM_VIRTUAL ){
- WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
- b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pOther->leftCursor);
- }
- indexable &= b;
- if( (pOrTerm->eOperator & WO_EQ)==0 ){
- chngToIN = 0;
- }else{
- chngToIN &= b;
- }
- }
- }
-
- /*
- ** Record the set of tables that satisfy case 3. The set might be
- ** empty.
- */
- pOrInfo->indexable = indexable;
- pTerm->eOperator = indexable==0 ? 0 : WO_OR;
-
- /* For a two-way OR, attempt to implementation case 2.
- */
- if( indexable && pOrWc->nTerm==2 ){
- int iOne = 0;
- WhereTerm *pOne;
- while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){
- int iTwo = 0;
- WhereTerm *pTwo;
- while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){
- whereCombineDisjuncts(pSrc, pWC, pOne, pTwo);
- }
- }
- }
-
- /*
- ** chngToIN holds a set of tables that *might* satisfy case 1. But
- ** we have to do some additional checking to see if case 1 really
- ** is satisfied.
- **
- ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means
- ** that there is no possibility of transforming the OR clause into an
- ** IN operator because one or more terms in the OR clause contain
- ** something other than == on a column in the single table. The 1-bit
- ** case means that every term of the OR clause is of the form
- ** "table.column=expr" for some single table. The one bit that is set
- ** will correspond to the common table. We still need to check to make
- ** sure the same column is used on all terms. The 2-bit case is when
- ** the all terms are of the form "table1.column=table2.column". It
- ** might be possible to form an IN operator with either table1.column
- ** or table2.column as the LHS if either is common to every term of
- ** the OR clause.
- **
- ** Note that terms of the form "table.column1=table.column2" (the
- ** same table on both sizes of the ==) cannot be optimized.
- */
- if( chngToIN ){
- int okToChngToIN = 0; /* True if the conversion to IN is valid */
- int iColumn = -1; /* Column index on lhs of IN operator */
- int iCursor = -1; /* Table cursor common to all terms */
- int j = 0; /* Loop counter */
-
- /* Search for a table and column that appears on one side or the
- ** other of the == operator in every subterm. That table and column
- ** will be recorded in iCursor and iColumn. There might not be any
- ** such table and column. Set okToChngToIN if an appropriate table
- ** and column is found but leave okToChngToIN false if not found.
- */
- for(j=0; j<2 && !okToChngToIN; j++){
- pOrTerm = pOrWc->a;
- for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
- assert( pOrTerm->eOperator & WO_EQ );
- pOrTerm->wtFlags &= ~TERM_OR_OK;
- if( pOrTerm->leftCursor==iCursor ){
- /* This is the 2-bit case and we are on the second iteration and
- ** current term is from the first iteration. So skip this term. */
- assert( j==1 );
- continue;
- }
- if( (chngToIN & sqlite3WhereGetMask(&pWInfo->sMaskSet,
- pOrTerm->leftCursor))==0 ){
- /* This term must be of the form t1.a==t2.b where t2 is in the
- ** chngToIN set but t1 is not. This term will be either preceded
- ** or follwed by an inverted copy (t2.b==t1.a). Skip this term
- ** and use its inversion. */
- testcase( pOrTerm->wtFlags & TERM_COPIED );
- testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
- assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
- continue;
- }
- iColumn = pOrTerm->u.leftColumn;
- iCursor = pOrTerm->leftCursor;
- break;
- }
- if( i<0 ){
- /* No candidate table+column was found. This can only occur
- ** on the second iteration */
- assert( j==1 );
- assert( IsPowerOfTwo(chngToIN) );
- assert( chngToIN==sqlite3WhereGetMask(&pWInfo->sMaskSet, iCursor) );
- break;
- }
- testcase( j==1 );
-
- /* We have found a candidate table and column. Check to see if that
- ** table and column is common to every term in the OR clause */
- okToChngToIN = 1;
- for(; i>=0 && okToChngToIN; i--, pOrTerm++){
- assert( pOrTerm->eOperator & WO_EQ );
- if( pOrTerm->leftCursor!=iCursor ){
- pOrTerm->wtFlags &= ~TERM_OR_OK;
- }else if( pOrTerm->u.leftColumn!=iColumn ){
- okToChngToIN = 0;
- }else{
- int affLeft, affRight;
- /* If the right-hand side is also a column, then the affinities
- ** of both right and left sides must be such that no type
- ** conversions are required on the right. (Ticket #2249)
- */
- affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight);
- affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
- if( affRight!=0 && affRight!=affLeft ){
- okToChngToIN = 0;
- }else{
- pOrTerm->wtFlags |= TERM_OR_OK;
- }
- }
- }
- }
-
- /* At this point, okToChngToIN is true if original pTerm satisfies
- ** case 1. In that case, construct a new virtual term that is
- ** pTerm converted into an IN operator.
- */
- if( okToChngToIN ){
- Expr *pDup; /* A transient duplicate expression */
- ExprList *pList = 0; /* The RHS of the IN operator */
- Expr *pLeft = 0; /* The LHS of the IN operator */
- Expr *pNew; /* The complete IN operator */
-
- for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
- if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
- assert( pOrTerm->eOperator & WO_EQ );
- assert( pOrTerm->leftCursor==iCursor );
- assert( pOrTerm->u.leftColumn==iColumn );
- pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
- pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
- pLeft = pOrTerm->pExpr->pLeft;
- }
- assert( pLeft!=0 );
- pDup = sqlite3ExprDup(db, pLeft, 0);
- pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
- if( pNew ){
- int idxNew;
- transferJoinMarkings(pNew, pExpr);
- assert( !ExprHasProperty(pNew, EP_xIsSelect) );
- pNew->x.pList = pList;
- idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
- testcase( idxNew==0 );
- exprAnalyze(pSrc, pWC, idxNew);
- pTerm = &pWC->a[idxTerm];
- markTermAsChild(pWC, idxNew, idxTerm);
- }else{
- sqlite3ExprListDelete(db, pList);
- }
- }
- }
-}
-#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
-
-/*
-** We already know that pExpr is a binary operator where both operands are
-** column references. This routine checks to see if pExpr is an equivalence
-** relation:
-** 1. The SQLITE_Transitive optimization must be enabled
-** 2. Must be either an == or an IS operator
-** 3. Not originating in the ON clause of an OUTER JOIN
-** 4. The affinities of A and B must be compatible
-** 5a. Both operands use the same collating sequence OR
-** 5b. The overall collating sequence is BINARY
-** If this routine returns TRUE, that means that the RHS can be substituted
-** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
-** This is an optimization. No harm comes from returning 0. But if 1 is
-** returned when it should not be, then incorrect answers might result.
-*/
-static int termIsEquivalence(Parse *pParse, Expr *pExpr){
- char aff1, aff2;
- CollSeq *pColl;
- if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
- if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
- if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
- aff1 = sqlite3ExprAffinity(pExpr->pLeft);
- aff2 = sqlite3ExprAffinity(pExpr->pRight);
- if( aff1!=aff2
- && (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
- ){
- return 0;
- }
- pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
- if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1;
- return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
-}
-
-/*
-** Recursively walk the expressions of a SELECT statement and generate
-** a bitmask indicating which tables are used in that expression
-** tree.
-*/
-static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
- Bitmask mask = 0;
- while( pS ){
- SrcList *pSrc = pS->pSrc;
- mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pEList);
- mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pGroupBy);
- mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pOrderBy);
- mask |= sqlite3WhereExprUsage(pMaskSet, pS->pWhere);
- mask |= sqlite3WhereExprUsage(pMaskSet, pS->pHaving);
- if( ALWAYS(pSrc!=0) ){
- int i;
- for(i=0; i<pSrc->nSrc; i++){
- mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
- mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn);
- if( pSrc->a[i].fg.isTabFunc ){
- mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg);
- }
- }
- }
- pS = pS->pPrior;
- }
- return mask;
-}
-
-/*
-** Expression pExpr is one operand of a comparison operator that might
-** be useful for indexing. This routine checks to see if pExpr appears
-** in any index. Return TRUE (1) if pExpr is an indexed term and return
-** FALSE (0) if not. If TRUE is returned, also set aiCurCol[0] to the cursor
-** number of the table that is indexed and aiCurCol[1] to the column number
-** of the column that is indexed, or XN_EXPR (-2) if an expression is being
-** indexed.
-**
-** If pExpr is a TK_COLUMN column reference, then this routine always returns
-** true even if that particular column is not indexed, because the column
-** might be added to an automatic index later.
-*/
-static SQLITE_NOINLINE int exprMightBeIndexed2(
- SrcList *pFrom, /* The FROM clause */
- Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */
- int *aiCurCol, /* Write the referenced table cursor and column here */
- Expr *pExpr /* An operand of a comparison operator */
-){
- Index *pIdx;
- int i;
- int iCur;
- for(i=0; mPrereq>1; i++, mPrereq>>=1){}
- iCur = pFrom->a[i].iCursor;
- for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->aColExpr==0 ) continue;
- for(i=0; i<pIdx->nKeyCol; i++){
- if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
- if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
- aiCurCol[0] = iCur;
- aiCurCol[1] = XN_EXPR;
- return 1;
- }
- }
- }
- return 0;
-}
-static int exprMightBeIndexed(
- SrcList *pFrom, /* The FROM clause */
- Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */
- int *aiCurCol, /* Write the referenced table cursor & column here */
- Expr *pExpr, /* An operand of a comparison operator */
- int op /* The specific comparison operator */
-){
- /* If this expression is a vector to the left or right of a
- ** inequality constraint (>, <, >= or <=), perform the processing
- ** on the first element of the vector. */
- assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE );
- assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
- assert( op<=TK_GE );
- if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
- pExpr = pExpr->x.pList->a[0].pExpr;
- }
-
- if( pExpr->op==TK_COLUMN ){
- aiCurCol[0] = pExpr->iTable;
- aiCurCol[1] = pExpr->iColumn;
- return 1;
- }
- if( mPrereq==0 ) return 0; /* No table references */
- if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */
- return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
-}
-
-/*
-** The input to this routine is an WhereTerm structure with only the
-** "pExpr" field filled in. The job of this routine is to analyze the
-** subexpression and populate all the other fields of the WhereTerm
-** structure.
-**
-** If the expression is of the form "<expr> <op> X" it gets commuted
-** to the standard form of "X <op> <expr>".
-**
-** If the expression is of the form "X <op> Y" where both X and Y are
-** columns, then the original expression is unchanged and a new virtual
-** term of the form "Y <op> X" is added to the WHERE clause and
-** analyzed separately. The original term is marked with TERM_COPIED
-** and the new term is marked with TERM_DYNAMIC (because it's pExpr
-** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it
-** is a commuted copy of a prior term.) The original term has nChild=1
-** and the copy has idxParent set to the index of the original term.
-*/
-static void exprAnalyze(
- SrcList *pSrc, /* the FROM clause */
- WhereClause *pWC, /* the WHERE clause */
- int idxTerm /* Index of the term to be analyzed */
-){
- WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
- WhereTerm *pTerm; /* The term to be analyzed */
- WhereMaskSet *pMaskSet; /* Set of table index masks */
- Expr *pExpr; /* The expression to be analyzed */
- Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
- Bitmask prereqAll; /* Prerequesites of pExpr */
- Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
- Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
- int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
- int noCase = 0; /* uppercase equivalent to lowercase */
- int op; /* Top-level operator. pExpr->op */
- Parse *pParse = pWInfo->pParse; /* Parsing context */
- sqlite3 *db = pParse->db; /* Database connection */
- unsigned char eOp2 = 0; /* op2 value for LIKE/REGEXP/GLOB */
- int nLeft; /* Number of elements on left side vector */
-
- if( db->mallocFailed ){
- return;
- }
- pTerm = &pWC->a[idxTerm];
- pMaskSet = &pWInfo->sMaskSet;
- pExpr = pTerm->pExpr;
- assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
- prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
- op = pExpr->op;
- if( op==TK_IN ){
- assert( pExpr->pRight==0 );
- if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
- }else{
- pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
- }
- }else if( op==TK_ISNULL ){
- pTerm->prereqRight = 0;
- }else{
- pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
- }
- pMaskSet->bVarSelect = 0;
- prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr);
- if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
- if( ExprHasProperty(pExpr, EP_FromJoin) ){
- Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
- prereqAll |= x;
- extraRight = x-1; /* ON clause terms may not be used with an index
- ** on left table of a LEFT JOIN. Ticket #3015 */
- if( (prereqAll>>1)>=x ){
- sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
- return;
- }
- }
- pTerm->prereqAll = prereqAll;
- pTerm->leftCursor = -1;
- pTerm->iParent = -1;
- pTerm->eOperator = 0;
- if( allowedOp(op) ){
- int aiCurCol[2];
- Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
- Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
- u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
-
- if( pTerm->iField>0 ){
- assert( op==TK_IN );
- assert( pLeft->op==TK_VECTOR );
- pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
- }
-
- if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
- pTerm->leftCursor = aiCurCol[0];
- pTerm->u.leftColumn = aiCurCol[1];
- pTerm->eOperator = operatorMask(op) & opMask;
- }
- if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
- if( pRight
- && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
- ){
- WhereTerm *pNew;
- Expr *pDup;
- u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
- assert( pTerm->iField==0 );
- if( pTerm->leftCursor>=0 ){
- int idxNew;
- pDup = sqlite3ExprDup(db, pExpr, 0);
- if( db->mallocFailed ){
- sqlite3ExprDelete(db, pDup);
- return;
- }
- idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
- if( idxNew==0 ) return;
- pNew = &pWC->a[idxNew];
- markTermAsChild(pWC, idxNew, idxTerm);
- if( op==TK_IS ) pNew->wtFlags |= TERM_IS;
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
-
- if( termIsEquivalence(pParse, pDup) ){
- pTerm->eOperator |= WO_EQUIV;
- eExtraOp = WO_EQUIV;
- }
- }else{
- pDup = pExpr;
- pNew = pTerm;
- }
- exprCommute(pParse, pDup);
- pNew->leftCursor = aiCurCol[0];
- pNew->u.leftColumn = aiCurCol[1];
- testcase( (prereqLeft | extraRight) != prereqLeft );
- pNew->prereqRight = prereqLeft | extraRight;
- pNew->prereqAll = prereqAll;
- pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
- }
- }
-
-#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
- /* If a term is the BETWEEN operator, create two new virtual terms
- ** that define the range that the BETWEEN implements. For example:
- **
- ** a BETWEEN b AND c
- **
- ** is converted into:
- **
- ** (a BETWEEN b AND c) AND (a>=b) AND (a<=c)
- **
- ** The two new terms are added onto the end of the WhereClause object.
- ** The new terms are "dynamic" and are children of the original BETWEEN
- ** term. That means that if the BETWEEN term is coded, the children are
- ** skipped. Or, if the children are satisfied by an index, the original
- ** BETWEEN term is skipped.
- */
- else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
- ExprList *pList = pExpr->x.pList;
- int i;
- static const u8 ops[] = {TK_GE, TK_LE};
- assert( pList!=0 );
- assert( pList->nExpr==2 );
- for(i=0; i<2; i++){
- Expr *pNewExpr;
- int idxNew;
- pNewExpr = sqlite3PExpr(pParse, ops[i],
- sqlite3ExprDup(db, pExpr->pLeft, 0),
- sqlite3ExprDup(db, pList->a[i].pExpr, 0));
- transferJoinMarkings(pNewExpr, pExpr);
- idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
- testcase( idxNew==0 );
- exprAnalyze(pSrc, pWC, idxNew);
- pTerm = &pWC->a[idxTerm];
- markTermAsChild(pWC, idxNew, idxTerm);
- }
- }
-#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */
-
-#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
- /* Analyze a term that is composed of two or more subterms connected by
- ** an OR operator.
- */
- else if( pExpr->op==TK_OR ){
- assert( pWC->op==TK_AND );
- exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
- pTerm = &pWC->a[idxTerm];
- }
-#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
-
-#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
- /* Add constraints to reduce the search space on a LIKE or GLOB
- ** operator.
- **
- ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints
- **
- ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%'
- **
- ** The last character of the prefix "abc" is incremented to form the
- ** termination condition "abd". If case is not significant (the default
- ** for LIKE) then the lower-bound is made all uppercase and the upper-
- ** bound is made all lowercase so that the bounds also work when comparing
- ** BLOBs.
- */
- if( pWC->op==TK_AND
- && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
- ){
- Expr *pLeft; /* LHS of LIKE/GLOB operator */
- Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */
- Expr *pNewExpr1;
- Expr *pNewExpr2;
- int idxNew1;
- int idxNew2;
- const char *zCollSeqName; /* Name of collating sequence */
- const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
-
- pLeft = pExpr->x.pList->a[1].pExpr;
- pStr2 = sqlite3ExprDup(db, pStr1, 0);
-
- /* Convert the lower bound to upper-case and the upper bound to
- ** lower-case (upper-case is less than lower-case in ASCII) so that
- ** the range constraints also work for BLOBs
- */
- if( noCase && !pParse->db->mallocFailed ){
- int i;
- char c;
- pTerm->wtFlags |= TERM_LIKE;
- for(i=0; (c = pStr1->u.zToken[i])!=0; i++){
- pStr1->u.zToken[i] = sqlite3Toupper(c);
- pStr2->u.zToken[i] = sqlite3Tolower(c);
- }
- }
-
- if( !db->mallocFailed ){
- u8 c, *pC; /* Last character before the first wildcard */
- pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
- c = *pC;
- if( noCase ){
- /* The point is to increment the last character before the first
- ** wildcard. But if we increment '@', that will push it into the
- ** alphabetic range where case conversions will mess up the
- ** inequality. To avoid this, make sure to also run the full
- ** LIKE on all candidate expressions by clearing the isComplete flag
- */
- if( c=='A'-1 ) isComplete = 0;
- c = sqlite3UpperToLower[c];
- }
- *pC = c + 1;
- }
- zCollSeqName = noCase ? "NOCASE" : "BINARY";
- pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
- pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
- sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName),
- pStr1);
- transferJoinMarkings(pNewExpr1, pExpr);
- idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags);
- testcase( idxNew1==0 );
- exprAnalyze(pSrc, pWC, idxNew1);
- pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
- pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
- sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName),
- pStr2);
- transferJoinMarkings(pNewExpr2, pExpr);
- idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags);
- testcase( idxNew2==0 );
- exprAnalyze(pSrc, pWC, idxNew2);
- pTerm = &pWC->a[idxTerm];
- if( isComplete ){
- markTermAsChild(pWC, idxNew1, idxTerm);
- markTermAsChild(pWC, idxNew2, idxTerm);
- }
- }
-#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- /* Add a WO_AUX auxiliary term to the constraint set if the
- ** current expression is of the form "column OP expr" where OP
- ** is an operator that gets passed into virtual tables but which is
- ** not normally optimized for ordinary tables. In other words, OP
- ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
- ** This information is used by the xBestIndex methods of
- ** virtual tables. The native query optimizer does not attempt
- ** to do anything with MATCH functions.
- */
- if( pWC->op==TK_AND ){
- Expr *pRight = 0, *pLeft = 0;
- int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight);
- while( res-- > 0 ){
- int idxNew;
- WhereTerm *pNewTerm;
- Bitmask prereqColumn, prereqExpr;
-
- prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
- prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
- if( (prereqExpr & prereqColumn)==0 ){
- Expr *pNewExpr;
- pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
- 0, sqlite3ExprDup(db, pRight, 0));
- if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
- ExprSetProperty(pNewExpr, EP_FromJoin);
- }
- idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
- testcase( idxNew==0 );
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = prereqExpr;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_AUX;
- pNewTerm->eMatchOp = eOp2;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
- }
- SWAP(Expr*, pLeft, pRight);
- }
- }
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
- /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
- ** new terms for each component comparison - "a = ?" and "b = ?". The
- ** new terms completely replace the original vector comparison, which is
- ** no longer used.
- **
- ** This is only required if at least one side of the comparison operation
- ** is not a sub-select. */
- if( pWC->op==TK_AND
- && (pExpr->op==TK_EQ || pExpr->op==TK_IS)
- && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
- && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
- && ( (pExpr->pLeft->flags & EP_xIsSelect)==0
- || (pExpr->pRight->flags & EP_xIsSelect)==0)
- ){
- int i;
- for(i=0; i<nLeft; i++){
- int idxNew;
- Expr *pNew;
- Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
- Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
-
- pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
- transferJoinMarkings(pNew, pExpr);
- idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
- exprAnalyze(pSrc, pWC, idxNew);
- }
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */
- pTerm->eOperator = 0;
- }
-
- /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
- ** a virtual term for each vector component. The expression object
- ** used by each such virtual term is pExpr (the full vector IN(...)
- ** expression). The WhereTerm.iField variable identifies the index within
- ** the vector on the LHS that the virtual term represents.
- **
- ** This only works if the RHS is a simple SELECT, not a compound
- */
- if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0
- && pExpr->pLeft->op==TK_VECTOR
- && pExpr->x.pSelect->pPrior==0
- ){
- int i;
- for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
- int idxNew;
- idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
- pWC->a[idxNew].iField = i+1;
- exprAnalyze(pSrc, pWC, idxNew);
- markTermAsChild(pWC, idxNew, idxTerm);
- }
- }
-
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- /* When sqlite_stat3 histogram data is available an operator of the
- ** form "x IS NOT NULL" can sometimes be evaluated more efficiently
- ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
- ** virtual term of that form.
- **
- ** Note that the virtual term must be tagged with TERM_VNULL.
- */
- if( pExpr->op==TK_NOTNULL
- && pExpr->pLeft->op==TK_COLUMN
- && pExpr->pLeft->iColumn>=0
- && OptimizationEnabled(db, SQLITE_Stat34)
- ){
- Expr *pNewExpr;
- Expr *pLeft = pExpr->pLeft;
- int idxNew;
- WhereTerm *pNewTerm;
-
- pNewExpr = sqlite3PExpr(pParse, TK_GT,
- sqlite3ExprDup(db, pLeft, 0),
- sqlite3ExprAlloc(db, TK_NULL, 0, 0));
-
- idxNew = whereClauseInsert(pWC, pNewExpr,
- TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
- if( idxNew ){
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = 0;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_GT;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
- }
- }
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-
- /* Prevent ON clause terms of a LEFT JOIN from being used to drive
- ** an index for tables to the left of the join.
- */
- testcase( pTerm!=&pWC->a[idxTerm] );
- pTerm = &pWC->a[idxTerm];
- pTerm->prereqRight |= extraRight;
-}
-
-/***************************************************************************
-** Routines with file scope above. Interface to the rest of the where.c
-** subsystem follows.
-***************************************************************************/
-
-/*
-** This routine identifies subexpressions in the WHERE clause where
-** each subexpression is separated by the AND operator or some other
-** operator specified in the op parameter. The WhereClause structure
-** is filled with pointers to subexpressions. For example:
-**
-** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22)
-** \________/ \_______________/ \________________/
-** slot[0] slot[1] slot[2]
-**
-** The original WHERE clause in pExpr is unaltered. All this routine
-** does is make slot[] entries point to substructure within pExpr.
-**
-** In the previous sentence and in the diagram, "slot[]" refers to
-** the WhereClause.a[] array. The slot[] array grows as needed to contain
-** all terms of the WHERE clause.
-*/
-void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
- Expr *pE2 = sqlite3ExprSkipCollate(pExpr);
- pWC->op = op;
- if( pE2==0 ) return;
- if( pE2->op!=op ){
- whereClauseInsert(pWC, pExpr, 0);
- }else{
- sqlite3WhereSplit(pWC, pE2->pLeft, op);
- sqlite3WhereSplit(pWC, pE2->pRight, op);
- }
-}
-
-/*
-** Initialize a preallocated WhereClause structure.
-*/
-void sqlite3WhereClauseInit(
- WhereClause *pWC, /* The WhereClause to be initialized */
- WhereInfo *pWInfo /* The WHERE processing context */
-){
- pWC->pWInfo = pWInfo;
- pWC->pOuter = 0;
- pWC->nTerm = 0;
- pWC->nSlot = ArraySize(pWC->aStatic);
- pWC->a = pWC->aStatic;
-}
-
-/*
-** Deallocate a WhereClause structure. The WhereClause structure
-** itself is not freed. This routine is the inverse of
-** sqlite3WhereClauseInit().
-*/
-void sqlite3WhereClauseClear(WhereClause *pWC){
- int i;
- WhereTerm *a;
- sqlite3 *db = pWC->pWInfo->pParse->db;
- for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
- if( a->wtFlags & TERM_DYNAMIC ){
- sqlite3ExprDelete(db, a->pExpr);
- }
- if( a->wtFlags & TERM_ORINFO ){
- whereOrInfoDelete(db, a->u.pOrInfo);
- }else if( a->wtFlags & TERM_ANDINFO ){
- whereAndInfoDelete(db, a->u.pAndInfo);
- }
- }
- if( pWC->a!=pWC->aStatic ){
- sqlite3DbFree(db, pWC->a);
- }
-}
-
-
-/*
-** These routines walk (recursively) an expression tree and generate
-** a bitmask indicating which tables are used in that expression
-** tree.
-*/
-Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
- Bitmask mask;
- if( p==0 ) return 0;
- if( p->op==TK_COLUMN ){
- return sqlite3WhereGetMask(pMaskSet, p->iTable);
- }
- mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
- assert( !ExprHasProperty(p, EP_TokenOnly) );
- if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
- if( p->pRight ){
- mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight);
- assert( p->x.pList==0 );
- }else if( ExprHasProperty(p, EP_xIsSelect) ){
- if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
- mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
- }else if( p->x.pList ){
- mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
- }
- return mask;
-}
-Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){
- int i;
- Bitmask mask = 0;
- if( pList ){
- for(i=0; i<pList->nExpr; i++){
- mask |= sqlite3WhereExprUsage(pMaskSet, pList->a[i].pExpr);
- }
- }
- return mask;
-}
-
-
-/*
-** Call exprAnalyze on all terms in a WHERE clause.
-**
-** Note that exprAnalyze() might add new virtual terms onto the
-** end of the WHERE clause. We do not want to analyze these new
-** virtual terms, so start analyzing at the end and work forward
-** so that the added virtual terms are never processed.
-*/
-void sqlite3WhereExprAnalyze(
- SrcList *pTabList, /* the FROM clause */
- WhereClause *pWC /* the WHERE clause to be analyzed */
-){
- int i;
- for(i=pWC->nTerm-1; i>=0; i--){
- exprAnalyze(pTabList, pWC, i);
- }
-}
-
-/*
-** For table-valued-functions, transform the function arguments into
-** new WHERE clause terms.
-**
-** Each function argument translates into an equality constraint against
-** a HIDDEN column in the table.
-*/
-void sqlite3WhereTabFuncArgs(
- Parse *pParse, /* Parsing context */
- struct SrcList_item *pItem, /* The FROM clause term to process */
- WhereClause *pWC /* Xfer function arguments to here */
-){
- Table *pTab;
- int j, k;
- ExprList *pArgs;
- Expr *pColRef;
- Expr *pTerm;
- if( pItem->fg.isTabFunc==0 ) return;
- pTab = pItem->pTab;
- assert( pTab!=0 );
- pArgs = pItem->u1.pFuncArg;
- if( pArgs==0 ) return;
- for(j=k=0; j<pArgs->nExpr; j++){
- while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;}
- if( k>=pTab->nCol ){
- sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d",
- pTab->zName, j);
- return;
- }
- pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
- if( pColRef==0 ) return;
- pColRef->iTable = pItem->iCursor;
- pColRef->iColumn = k++;
- pColRef->pTab = pTab;
- pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
- sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0));
- whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/GetFile.cs b/chromium/third_party/sqlite/sqlite-src-3240000/tool/GetFile.cs
deleted file mode 100644
index 2a62deb552d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/GetFile.cs
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
-** 2015 October 7
-**
-** 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 contains C# code to download a single file based on a URI.
-*/
-
-using System;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.IO;
-using System.Net;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Threading;
-
-///////////////////////////////////////////////////////////////////////////////
-
-#region Assembly Metadata
-[assembly: AssemblyTitle("GetFile Tool")]
-[assembly: AssemblyDescription("Download a single file based on a URI.")]
-[assembly: AssemblyCompany("SQLite Development Team")]
-[assembly: AssemblyProduct("SQLite")]
-[assembly: AssemblyCopyright("Public Domain")]
-[assembly: ComVisible(false)]
-[assembly: Guid("5c4b3728-1693-4a33-a218-8e6973ca15a6")]
-[assembly: AssemblyVersion("1.0.*")]
-
-#if DEBUG
-[assembly: AssemblyConfiguration("Debug")]
-#else
-[assembly: AssemblyConfiguration("Release")]
-#endif
-#endregion
-
-///////////////////////////////////////////////////////////////////////////////
-
-namespace GetFile
-{
- /// <summary>
- /// This enumeration is used to represent all the possible exit codes from
- /// this tool.
- /// </summary>
- internal enum ExitCode
- {
- /// <summary>
- /// The file download was a success.
- /// </summary>
- Success = 0,
-
- /// <summary>
- /// The command line arguments are missing (i.e. null). Generally,
- /// this should not happen.
- /// </summary>
- MissingArgs = 1,
-
- /// <summary>
- /// The wrong number of command line arguments was supplied.
- /// </summary>
- WrongNumArgs = 2,
-
- /// <summary>
- /// The URI specified on the command line could not be parsed as a
- /// supported absolute URI.
- /// </summary>
- BadUri = 3,
-
- /// <summary>
- /// The file name portion of the URI specified on the command line
- /// could not be extracted from it.
- /// </summary>
- BadFileName = 4,
-
- /// <summary>
- /// The temporary directory is either invalid (i.e. null) or does not
- /// represent an available directory.
- /// </summary>
- BadTempPath = 5,
-
- /// <summary>
- /// An exception was caught in <see cref="Main" />. Generally, this
- /// should not happen.
- /// </summary>
- Exception = 6,
-
- /// <summary>
- /// The file download was canceled. This tool does not make use of
- /// the <see cref="WebClient.CancelAsync" /> method; therefore, this
- /// should not happen.
- /// </summary>
- DownloadCanceled = 7,
-
- /// <summary>
- /// The file download encountered an error. Further information about
- /// this error should be displayed on the console.
- /// </summary>
- DownloadError = 8
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- internal static class Program
- {
- #region Private Data
- /// <summary>
- /// This is used to synchronize multithreaded access to the
- /// <see cref="previousPercent" /> and <see cref="exitCode"/>
- /// fields.
- /// </summary>
- private static readonly object syncRoot = new object();
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// This event will be signed when the file download has completed,
- /// even if the file download itself was canceled or unsuccessful.
- /// </summary>
- private static EventWaitHandle doneEvent;
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// The previous file download completion percentage seen by the
- /// <see cref="DownloadProgressChanged" /> event handler. This value
- /// is never decreased, nor is it ever reset to zero.
- /// </summary>
- private static int previousPercent = 0;
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// This will be the exit code returned by this tool after the file
- /// download completes, successfully or otherwise. This value is only
- /// changed by the <see cref="DownloadFileCompleted" /> event handler.
- /// </summary>
- private static ExitCode exitCode = ExitCode.Success;
- #endregion
-
- ///////////////////////////////////////////////////////////////////////
-
- #region Private Support Methods
- /// <summary>
- /// This method displays an error message to the console and/or
- /// displays the command line usage information for this tool.
- /// </summary>
- /// <param name="message">
- /// The error message to display, if any.
- /// </param>
- /// <param name="usage">
- /// Non-zero to display the command line usage information.
- /// </param>
- private static void Error(
- string message,
- bool usage
- )
- {
- if (message != null)
- Console.WriteLine(message);
-
- string fileName = Path.GetFileName(
- Process.GetCurrentProcess().MainModule.FileName);
-
- Console.WriteLine(String.Format("usage: {0} <uri>", fileName));
- }
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// This method attempts to determine the file name portion of the
- /// specified URI.
- /// </summary>
- /// <param name="uri">
- /// The URI to process.
- /// </param>
- /// <returns>
- /// The file name portion of the specified URI -OR- null if it cannot
- /// be determined.
- /// </returns>
- private static string GetFileName(
- Uri uri
- )
- {
- if (uri == null)
- return null;
-
- string pathAndQuery = uri.PathAndQuery;
-
- if (String.IsNullOrEmpty(pathAndQuery))
- return null;
-
- int index = pathAndQuery.LastIndexOf('/');
-
- if ((index < 0) || (index == pathAndQuery.Length))
- return null;
-
- return pathAndQuery.Substring(index + 1);
- }
- #endregion
-
- ///////////////////////////////////////////////////////////////////////
-
- #region Private Event Handlers
- /// <summary>
- /// This method is an event handler that is called when the file
- /// download completion percentage changes. It will display progress
- /// on the console. Special care is taken to make sure that progress
- /// events are not displayed out-of-order, even if duplicate and/or
- /// out-of-order events are received.
- /// </summary>
- /// <param name="sender">
- /// The source of the event.
- /// </param>
- /// <param name="e">
- /// Information for the event being processed.
- /// </param>
- private static void DownloadProgressChanged(
- object sender,
- DownloadProgressChangedEventArgs e
- )
- {
- if (e != null)
- {
- int percent = e.ProgressPercentage;
-
- lock (syncRoot)
- {
- if (percent > previousPercent)
- {
- Console.Write('.');
-
- if ((percent % 10) == 0)
- Console.Write(" {0}% ", percent);
-
- previousPercent = percent;
- }
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// This method is an event handler that is called when the file
- /// download has completed, successfully or otherwise. It will
- /// display the overall result of the file download on the console,
- /// including any <see cref="Exception" /> information, if applicable.
- /// The <see cref="exitCode" /> field is changed by this method to
- /// indicate the overall result of the file download and the event
- /// within the <see cref="doneEvent" /> field will be signaled.
- /// </summary>
- /// <param name="sender">
- /// The source of the event.
- /// </param>
- /// <param name="e">
- /// Information for the event being processed.
- /// </param>
- private static void DownloadFileCompleted(
- object sender,
- AsyncCompletedEventArgs e
- )
- {
- if (e != null)
- {
- lock (syncRoot)
- {
- if (previousPercent < 100)
- Console.Write(' ');
- }
-
- if (e.Cancelled)
- {
- Console.WriteLine("Canceled");
-
- lock (syncRoot)
- {
- exitCode = ExitCode.DownloadCanceled;
- }
- }
- else
- {
- Exception error = e.Error;
-
- if (error != null)
- {
- Console.WriteLine("Error: {0}", error);
-
- lock (syncRoot)
- {
- exitCode = ExitCode.DownloadError;
- }
- }
- else
- {
- Console.WriteLine("Done");
- }
- }
- }
-
- if (doneEvent != null)
- doneEvent.Set();
- }
- #endregion
-
- ///////////////////////////////////////////////////////////////////////
-
- #region Program Entry Point
- /// <summary>
- /// This is the entry-point for this tool. It handles processing the
- /// command line arguments, setting up the web client, downloading the
- /// file, and saving it to the file system.
- /// </summary>
- /// <param name="args">
- /// The command line arguments.
- /// </param>
- /// <returns>
- /// Zero upon success; non-zero on failure. This will be one of the
- /// values from the <see cref="ExitCode" /> enumeration.
- /// </returns>
- private static int Main(
- string[] args
- )
- {
- //
- // NOTE: Sanity check the command line arguments.
- //
- if (args == null)
- {
- Error(null, true);
- return (int)ExitCode.MissingArgs;
- }
-
- if (args.Length != 1)
- {
- Error(null, true);
- return (int)ExitCode.WrongNumArgs;
- }
-
- //
- // NOTE: Attempt to convert the first (and only) command line
- // argument to an absolute URI.
- //
- Uri uri;
-
- if (!Uri.TryCreate(args[0], UriKind.Absolute, out uri))
- {
- Error("Could not create absolute URI from argument.", false);
- return (int)ExitCode.BadUri;
- }
-
- //
- // NOTE: Attempt to extract the file name portion of the URI we
- // just created.
- //
- string fileName = GetFileName(uri);
-
- if (fileName == null)
- {
- Error("Could not extract the file name from the URI.", false);
- return (int)ExitCode.BadFileName;
- }
-
- //
- // NOTE: Grab the temporary path setup for this process. If it is
- // unavailable, we will not continue.
- //
- string directory = Path.GetTempPath();
-
- if (String.IsNullOrEmpty(directory) ||
- !Directory.Exists(directory))
- {
- Error("Temporary directory is invalid or unavailable.", false);
- return (int)ExitCode.BadTempPath;
- }
-
- try
- {
- using (WebClient webClient = new WebClient())
- {
- //
- // NOTE: Create the event used to signal completion of the
- // file download.
- //
- doneEvent = new ManualResetEvent(false);
-
- //
- // NOTE: Hookup the event handlers we care about on the web
- // client. These are necessary because the file is
- // downloaded asynchronously.
- //
- webClient.DownloadProgressChanged +=
- new DownloadProgressChangedEventHandler(
- DownloadProgressChanged);
-
- webClient.DownloadFileCompleted +=
- new AsyncCompletedEventHandler(
- DownloadFileCompleted);
-
- //
- // NOTE: Build the fully qualified path and file name,
- // within the temporary directory, where the file to
- // be downloaded will be saved.
- //
- fileName = Path.Combine(directory, fileName);
-
- //
- // NOTE: If the file name already exists (in the temporary)
- // directory, delete it.
- //
- // TODO: Perhaps an error should be raised here instead?
- //
- if (File.Exists(fileName))
- File.Delete(fileName);
-
- //
- // NOTE: After kicking off the asynchronous file download
- // process, wait [forever] until the "done" event is
- // signaled.
- //
- Console.WriteLine(
- "Downloading \"{0}\" to \"{1}\"...", uri, fileName);
-
- webClient.DownloadFileAsync(uri, fileName);
- doneEvent.WaitOne();
- }
-
- lock (syncRoot)
- {
- return (int)exitCode;
- }
- }
- catch (Exception e)
- {
- //
- // NOTE: An exception was caught. Report it via the console
- // and return failure.
- //
- Error(e.ToString(), false);
- return (int)ExitCode.Exception;
- }
- }
- #endregion
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/GetTclKit.bat b/chromium/third_party/sqlite/sqlite-src-3240000/tool/GetTclKit.bat
deleted file mode 100644
index a0077c470ce..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/GetTclKit.bat
+++ /dev/null
@@ -1,299 +0,0 @@
-@ECHO OFF
-
-::
-:: GetTclKit.bat --
-::
-:: TclKit Download Tool
-::
-
-SETLOCAL
-
-REM SET __ECHO=ECHO
-REM SET __ECHO2=ECHO
-REM SET __ECHO3=ECHO
-IF NOT DEFINED _AECHO (SET _AECHO=REM)
-IF NOT DEFINED _CECHO (SET _CECHO=REM)
-IF NOT DEFINED _VECHO (SET _VECHO=REM)
-
-SET OVERWRITE=^>
-IF DEFINED __ECHO SET OVERWRITE=^^^>
-
-SET APPEND=^>^>
-IF DEFINED __ECHO SET APPEND=^^^>^^^>
-
-SET PROCESSOR=%1
-
-IF DEFINED PROCESSOR (
- CALL :fn_UnquoteVariable PROCESSOR
-) ELSE (
- GOTO usage
-)
-
-SET PROCESSOR=%PROCESSOR:AMD64=x64%
-
-%_VECHO% Processor = '%PROCESSOR%'
-
-SET DUMMY2=%2
-
-IF DEFINED DUMMY2 (
- GOTO usage
-)
-
-SET ROOT=%~dp0\..
-SET ROOT=%ROOT:\\=\%
-
-%_VECHO% Root = '%ROOT%'
-
-SET TOOLS=%~dp0
-SET TOOLS=%TOOLS:~0,-1%
-
-%_VECHO% Tools = '%TOOLS%'
-
-IF NOT DEFINED windir (
- ECHO The windir environment variable must be set first.
- GOTO errors
-)
-
-%_VECHO% WinDir = '%windir%'
-
-IF NOT DEFINED TEMP (
- ECHO The TEMP environment variable must be set first.
- GOTO errors
-)
-
-%_VECHO% Temp = '%TEMP%'
-
-IF NOT DEFINED TCLKIT_URI (
- SET TCLKIT_URI=https://tclsh.com/
-)
-
-%_VECHO% TclKitUri = '%TCLKIT_URI%'
-
-IF /I "%PROCESSOR%" == "x86" (
- CALL :fn_TclKitX86Variables
-) ELSE IF /I "%PROCESSOR%" == "x64" (
- CALL :fn_TclKitX64Variables
-) ELSE (
- GOTO usage
-)
-
-%_VECHO% TclKitVersion = '%TCLKIT_VERSION%'
-%_VECHO% TclKitPatchLevel = '%TCLKIT_PATCHLEVEL%'
-%_VECHO% TclKitNoEnv = '%TCLKIT_NOENV%'
-%_VECHO% TclKitNoSdk = '%TCLKIT_NOSDK%'
-%_VECHO% TclKitExe = '%TCLKIT_EXE%'
-%_VECHO% TclKitLib = '%TCLKIT_LIB%'
-%_VECHO% TclKitLibStub = '%TCLKIT_LIB_STUB%'
-%_VECHO% TclKitSdk = '%TCLKIT_SDK%'
-%_VECHO% TclKitSdkZip = '%TCLKIT_SDK_ZIP%'
-%_VECHO% TclKitFiles = '%TCLKIT_FILES%'
-
-CALL :fn_ResetErrorLevel
-
-FOR %%T IN (csc.exe) DO (
- SET %%T_PATH=%%~dp$PATH:T
-)
-
-%_VECHO% Csc.exe_PATH = '%csc.exe_PATH%'
-
-IF DEFINED csc.exe_PATH (
- GOTO skip_addToPath
-)
-
-IF DEFINED FRAMEWORKDIR (
- REM Use the existing .NET Framework directory...
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v2.0.50727" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v2.0.50727
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v3.5" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v3.5
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v4.0.30319" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v4.0.30319
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v2.0.50727" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v2.0.50727
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v3.5" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v3.5
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v4.0.30319" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v4.0.30319
-) ELSE (
- ECHO No suitable version of the .NET Framework appears to be installed.
- GOTO errors
-)
-
-%_VECHO% FrameworkDir = '%FRAMEWORKDIR%'
-
-IF NOT EXIST "%FRAMEWORKDIR%\csc.exe" (
- ECHO The file "%FRAMEWORKDIR%\csc.exe" is missing.
- GOTO errors
-)
-
-CALL :fn_PrependToPath FRAMEWORKDIR
-
-:skip_addToPath
-
-IF NOT EXIST "%TEMP%\GetFile.exe" (
- %__ECHO% csc.exe "/out:%TEMP%\GetFile.exe" /target:exe "%TOOLS%\GetFile.cs"
-
- IF ERRORLEVEL 1 (
- ECHO Compilation of "%TOOLS%\GetFile.cs" failed.
- GOTO errors
- )
-)
-
-FOR %%F IN (%TCLKIT_FILES%) DO (
- IF NOT EXIST "%TEMP%\%%F" (
- %__ECHO% "%TEMP%\GetFile.exe" "%TCLKIT_URI%%%F"
-
- IF ERRORLEVEL 1 (
- ECHO Download of "%%F" from "%TCLKIT_URI%" failed.
- GOTO errors
- )
- )
-)
-
-IF DEFINED TCLKIT_NOENV GOTO skip_sdkUnZip
-IF DEFINED TCLKIT_NOSDK GOTO skip_sdkUnZip
-
-IF NOT EXIST "%TEMP%\%TCLKIT_SDK%" (
- %__ECHO% MKDIR "%TEMP%\%TCLKIT_SDK%"
-
- IF ERRORLEVEL 1 (
- ECHO Could not create directory "%TEMP%\%TCLKIT_SDK%".
- GOTO errors
- )
-)
-
-%__ECHO% "%TEMP%\unzip.exe" -n "%TEMP%\%TCLKIT_SDK_ZIP%" -d "%TEMP%\%TCLKIT_SDK%"
-
-IF ERRORLEVEL 1 (
- ECHO Could not unzip "%TEMP%\%TCLKIT_SDK_ZIP%" to "%TEMP%\%TCLKIT_SDK%".
- GOTO errors
-)
-
-:skip_sdkUnZip
-
-IF DEFINED TCLKIT_NOENV GOTO skip_sdkEnvironment
-
-%__ECHO% ECHO SET TCLSH_CMD=%TEMP%\%TCLKIT_EXE%%OVERWRITE%"%ROOT%\SetTclKitEnv.bat"
-
-IF DEFINED TCLKIT_NOSDK GOTO skip_sdkVariables
-
-%__ECHO% ECHO SET TCLINCDIR=%TEMP%\%TCLKIT_SDK%\include%APPEND%"%ROOT%\SetTclKitEnv.bat"
-%__ECHO% ECHO SET TCLLIBDIR=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ROOT%\SetTclKitEnv.bat"
-%__ECHO% ECHO SET LIBTCLPATH=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ROOT%\SetTclKitEnv.bat"
-%__ECHO% ECHO SET LIBTCL=%TCLKIT_LIB%%APPEND%"%ROOT%\SetTclKitEnv.bat"
-%__ECHO% ECHO SET LIBTCLSTUB=%TCLKIT_LIB_STUB%%APPEND%"%ROOT%\SetTclKitEnv.bat"
-
-:skip_sdkVariables
-
-ECHO.
-ECHO Wrote "%ROOT%\SetTclKitEnv.bat".
-ECHO Please run it to set the necessary Tcl environment variables.
-ECHO.
-
-:skip_sdkEnvironment
-
-GOTO no_errors
-
-:fn_TclKitX86Variables
- REM
- REM NOTE: By default, use latest available version of the TclKit SDK
- REM for x86. However, the "default" TclKit executable for x86
- REM is still used here because it is the only one "well-known"
- REM to be available for download.
- REM
- IF NOT DEFINED TCLKIT_PATCHLEVEL (
- SET TCLKIT_PATCHLEVEL=8.6.6
- )
- SET TCLKIT_VERSION=%TCLKIT_PATCHLEVEL:.=%
- SET TCLKIT_VERSION=%TCLKIT_VERSION:~0,2%
- REM SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
- SET TCLKIT_EXE=tclkit-8.6.4.exe
- SET TCLKIT_LIB=libtclkit%TCLKIT_PATCHLEVEL:.=%.lib
- SET TCLKIT_LIB_STUB=libtclstub%TCLKIT_VERSION:.=%.a
- SET TCLKIT_SDK=libtclkit-sdk-x86-%TCLKIT_PATCHLEVEL%
- SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
- SET TCLKIT_FILES=%TCLKIT_EXE%
- IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
- SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
- )
- GOTO :EOF
-
-:fn_TclKitX64Variables
- REM
- REM NOTE: By default, use latest available version of the TclKit SDK
- REM for x64. However, the "default" TclKit executable for x86
- REM is still used here because it is the only one "well-known"
- REM to be available for download.
- REM
- IF NOT DEFINED TCLKIT_PATCHLEVEL (
- SET TCLKIT_PATCHLEVEL=8.6.6
- )
- SET TCLKIT_VERSION=%TCLKIT_PATCHLEVEL:.=%
- SET TCLKIT_VERSION=%TCLKIT_VERSION:~0,2%
- REM SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
- SET TCLKIT_EXE=tclkit-8.6.4.exe
- SET TCLKIT_LIB=libtclkit%TCLKIT_PATCHLEVEL:.=%.lib
- SET TCLKIT_LIB_STUB=libtclstub%TCLKIT_VERSION:.=%.a
- SET TCLKIT_SDK=libtclkit-sdk-x64-%TCLKIT_PATCHLEVEL%
- SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
- SET TCLKIT_FILES=%TCLKIT_EXE%
- IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
- SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
- )
- GOTO :EOF
-
-:fn_UnquoteVariable
- IF NOT DEFINED %1 GOTO :EOF
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%1%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET VALUE=%%V
- )
- SET VALUE=%VALUE:"=%
- REM "
- ENDLOCAL && SET %1=%VALUE%
- GOTO :EOF
-
-:fn_PrependToPath
- IF NOT DEFINED %1 GOTO :EOF
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%1%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET VALUE=%%V
- )
- SET VALUE=%VALUE:"=%
- REM "
- ENDLOCAL && SET PATH=%VALUE%;%PATH%
- GOTO :EOF
-
-:fn_ResetErrorLevel
- VERIFY > NUL
- GOTO :EOF
-
-:fn_SetErrorLevel
- VERIFY MAYBE 2> NUL
- GOTO :EOF
-
-:usage
- ECHO.
- ECHO Usage: %~nx0 ^<processor^>
- ECHO.
- ECHO The only supported values for processor are "x86" and "x64".
- GOTO errors
-
-:errors
- CALL :fn_SetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Failure, errors were encountered.
- GOTO end_of_file
-
-:no_errors
- CALL :fn_ResetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Success, no errors were encountered.
- GOTO end_of_file
-
-:end_of_file
-%__ECHO% EXIT /B %ERRORLEVEL%
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/Replace.cs b/chromium/third_party/sqlite/sqlite-src-3240000/tool/Replace.cs
deleted file mode 100644
index 3475a47e6e8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/Replace.cs
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
-** 2016 February 26
-**
-** 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 contains C# code to perform regular expression replacements
-** using the standard input and output channels.
-*/
-
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
-
-///////////////////////////////////////////////////////////////////////////////
-
-#region Assembly Metadata
-[assembly: AssemblyTitle("Replace Tool")]
-[assembly: AssemblyDescription("Replace text using standard input/output.")]
-[assembly: AssemblyCompany("SQLite Development Team")]
-[assembly: AssemblyProduct("SQLite")]
-[assembly: AssemblyCopyright("Public Domain")]
-[assembly: ComVisible(false)]
-[assembly: Guid("95a0513f-8863-48cd-a76f-cb80868cb578")]
-[assembly: AssemblyVersion("1.0.*")]
-
-#if DEBUG
-[assembly: AssemblyConfiguration("Debug")]
-#else
-[assembly: AssemblyConfiguration("Release")]
-#endif
-#endregion
-
-///////////////////////////////////////////////////////////////////////////////
-
-namespace Replace
-{
- /// <summary>
- /// This enumeration is used to represent all the possible exit codes from
- /// this tool.
- /// </summary>
- internal enum ExitCode
- {
- /// <summary>
- /// The file download was a success.
- /// </summary>
- Success = 0,
-
- /// <summary>
- /// The command line arguments are missing (i.e. null). Generally,
- /// this should not happen.
- /// </summary>
- MissingArgs = 1,
-
- /// <summary>
- /// The wrong number of command line arguments was supplied.
- /// </summary>
- WrongNumArgs = 2,
-
- /// <summary>
- /// The "matchingOnly" flag could not be converted to a value of the
- /// <see cref="Boolean"/> type.
- /// </summary>
- BadMatchingOnlyFlag = 3,
-
- /// <summary>
- /// An exception was caught in <see cref="Main" />. Generally, this
- /// should not happen.
- /// </summary>
- Exception = 4
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- internal static class Replace
- {
- #region Private Support Methods
- /// <summary>
- /// This method displays an error message to the console and/or
- /// displays the command line usage information for this tool.
- /// </summary>
- /// <param name="message">
- /// The error message to display, if any.
- /// </param>
- /// <param name="usage">
- /// Non-zero to display the command line usage information.
- /// </param>
- private static void Error(
- string message,
- bool usage
- )
- {
- if (message != null)
- Console.WriteLine(message);
-
- string fileName = Path.GetFileName(
- Process.GetCurrentProcess().MainModule.FileName);
-
- Console.WriteLine(String.Format(
- "usage: {0} <regExPattern> <regExSubSpec> <matchingOnly>",
- fileName));
- }
- #endregion
-
- ///////////////////////////////////////////////////////////////////////
-
- #region Program Entry Point
- /// <summary>
- /// This is the entry-point for this tool. It handles processing the
- /// command line arguments, reading from the standard input channel,
- /// replacing any matching lines of text, and writing to the standard
- /// output channel.
- /// </summary>
- /// <param name="args">
- /// The command line arguments.
- /// </param>
- /// <returns>
- /// Zero upon success; non-zero on failure. This will be one of the
- /// values from the <see cref="ExitCode" /> enumeration.
- /// </returns>
- private static int Main(
- string[] args
- )
- {
- //
- // NOTE: Sanity check the command line arguments.
- //
- if (args == null)
- {
- Error(null, true);
- return (int)ExitCode.MissingArgs;
- }
-
- if (args.Length != 3)
- {
- Error(null, true);
- return (int)ExitCode.WrongNumArgs;
- }
-
- try
- {
- //
- // NOTE: Create a regular expression from the first command
- // line argument. Then, grab the replacement string,
- // which is the second argument.
- //
- Regex regEx = new Regex(args[0]);
- string replacement = args[1];
-
- //
- // NOTE: Attempt to convert the third argument to a boolean.
- //
- bool matchingOnly;
-
- if (!bool.TryParse(args[2], out matchingOnly))
- {
- Error(null, true);
- return (int)ExitCode.BadMatchingOnlyFlag;
- }
-
- //
- // NOTE: Grab the standard input and output channels from the
- // console.
- //
- TextReader inputTextReader = Console.In;
- TextWriter outputTextWriter = Console.Out;
-
- //
- // NOTE: Loop until end-of-file is hit on the standard input
- // stream.
- //
- while (true)
- {
- //
- // NOTE: Read a line from the standard input channel. If
- // null is returned here, there is no more input and
- // we are done.
- //
- string inputLine = inputTextReader.ReadLine();
-
- if (inputLine == null)
- break;
-
- //
- // NOTE: Perform regular expression replacements on this
- // line, if any. Then, write the modified line to
- // the standard output channel.
- //
- string outputLine = regEx.Replace(inputLine, replacement);
-
- if (!matchingOnly || !String.Equals(
- inputLine, outputLine, StringComparison.Ordinal))
- {
- outputTextWriter.WriteLine(outputLine);
- }
- }
-
- //
- // NOTE: At this point, everything has succeeded.
- //
- return (int)ExitCode.Success;
- }
- catch (Exception e)
- {
- //
- // NOTE: An exception was caught. Report it via the console
- // and return failure.
- //
- Error(e.ToString(), false);
- return (int)ExitCode.Exception;
- }
- }
- #endregion
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/addopcodes.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/addopcodes.tcl
deleted file mode 100644
index 070779029bd..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/addopcodes.tcl
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script appends additional token codes to the end of the
-# parse.h file that lemon generates. These extra token codes are
-# not used by the parser. But they are used by the tokenizer and/or
-# the code generator.
-#
-#
-set in [open [lindex $argv 0] rb]
-set max 0
-while {![eof $in]} {
- set line [gets $in]
- if {[regexp {^#define TK_} $line]} {
- puts $line
- set x [lindex $line 2]
- if {$x>$max} {set max $x}
- }
-}
-close $in
-
-# The following are the extra token codes to be added. SPACE and
-# ILLEGAL *must* be the last two token codes and they must be in that order.
-#
-set extras {
- TRUEFALSE
- ISNOT
- FUNCTION
- COLUMN
- AGG_FUNCTION
- AGG_COLUMN
- UMINUS
- UPLUS
- TRUTH
- REGISTER
- VECTOR
- SELECT_COLUMN
- IF_NULL_ROW
- ASTERISK
- SPAN
- END_OF_FILE
- UNCLOSED_STRING
- SPACE
- ILLEGAL
-}
-if {[lrange $extras end-1 end]!="SPACE ILLEGAL"} {
- error "SPACE and ILLEGAL must be the last two token codes and they\
- must be in that order"
-}
-foreach x $extras {
- incr max
- puts [format "#define TK_%-29s %4d" $x $max]
-}
-
-# Some additional #defines related to token codes.
-#
-puts "\n/* The token codes above must all fit in 8 bits */"
-puts [format "#define %-20s %-6s" TKFLG_MASK 0xff]
-puts "\n/* Flags that can be added to a token code when it is not"
-puts "** being stored in a u8: */"
-foreach {fg val comment} {
- TKFLG_DONTFOLD 0x100 {/* Omit constant folding optimizations */}
-} {
- puts [format "#define %-20s %-6s %s" $fg $val $comment]
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/build-all-msvc.bat b/chromium/third_party/sqlite/sqlite-src-3240000/tool/build-all-msvc.bat
deleted file mode 100755
index bdf055e6028..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/build-all-msvc.bat
+++ /dev/null
@@ -1,859 +0,0 @@
-@ECHO OFF
-
-::
-:: build-all-msvc.bat --
-::
-:: Multi-Platform Build Tool for MSVC
-::
-
-REM
-REM This batch script is used to build the SQLite DLL for multiple platforms
-REM and configurations using MSVC. The built SQLite DLLs, their associated
-REM import libraries, and optionally their symbols files, are placed within
-REM the directory specified on the command line, in sub-directories named for
-REM their respective platforms and configurations. This batch script must be
-REM run from inside a Visual Studio Command Prompt for the desired version of
-REM Visual Studio ^(the initial platform configured for the command prompt does
-REM not really matter^). Exactly one command line argument is required, the
-REM name of an existing directory to be used as the final destination directory
-REM for the generated output files, which will be placed in sub-directories
-REM created therein. Ideally, the directory specified should be empty.
-REM
-REM Example:
-REM
-REM CD /D C:\dev\sqlite\core
-REM CALL tool\build-all-msvc.bat C:\Temp
-REM
-REM In the example above, "C:\dev\sqlite\core" represents the root of the
-REM source tree for SQLite and "C:\Temp" represents the final destination
-REM directory for the generated output files.
-REM
-REM Please note that the SQLite build process performed by the Makefile
-REM associated with this batch script requires a Tcl shell to be present
-REM in a directory contained in the PATH environment variable unless a
-REM pre-existing amalgamation file is used.
-REM
-REM There are several environment variables that may be set to modify the
-REM behavior of this batch script and its associated Makefile. The list of
-REM platforms to build may be overriden by using the PLATFORMS environment
-REM variable, which should contain a list of platforms ^(e.g. x86 x86_amd64
-REM x86_arm^). All platforms must be supported by the version of Visual Studio
-REM being used. The list of configurations to build may be overridden by
-REM setting the CONFIGURATIONS environment variable, which should contain a
-REM list of configurations to build ^(e.g. Debug Retail^). Neither of these
-REM variable values may contain any double quotes, surrounding or embedded.
-REM
-REM Finally, the NCRTLIBPATH, NUCRTLIBPATH, and NSDKLIBPATH environment
-REM variables may be set to specify the location of the CRT, Universal CRT, and
-REM Windows SDK, respectively, that may be needed to compile executables native
-REM to the architecture of the build machine during any cross-compilation that
-REM may be necessary, depending on the platforms to be built. These values in
-REM these three variables should be surrounded by double quotes if they contain
-REM spaces.
-REM
-REM There are a few other environment variables that impact the build process
-REM when set ^(to anything^), they are:
-REM
-REM USE_AUTOCONF_MAKEFILE
-REM
-REM When set, the "autoconf" Makefile for MSVC will be used instead of the main
-REM Makefile for MSVC. It must exist at "%ROOT%\autoconf\Makefile.msc".
-REM
-REM NOCLEAN
-REM
-REM When set, the "clean" target will not be used during each build iteration.
-REM However, the target binaries, if any, will still be deleted manually prior
-REM to being rebuilt. Setting this environment variable is only rarely needed
-REM and could cause issues in some circumstances; therefore, setting it is not
-REM recommended.
-REM
-REM NOSYMBOLS
-REM
-REM When set, copying of symbol files ^(*.pdb^) created during the build will
-REM be skipped and they will not appear in the final destination directory.
-REM Setting this environment variable is never strictly needed and could cause
-REM issues in some circumstances; therefore, setting it is not recommended.
-REM
-REM NOMEMDEBUG
-REM
-REM When set, disables use of MEMDEBUG when building binaries for the "Debug"
-REM configuration.
-REM
-REM BUILD_ALL_SHELL
-REM
-REM When set, the command line shell will be built for each selected platform
-REM and configuration as well. In addition, the command line shell binaries
-REM will be copied, with their symbols, to the final destination directory.
-REM
-REM USE_WINV63_NSDKLIBPATH
-REM
-REM When set, modifies how the NSDKLIBPATH environment variable is built, based
-REM on the WindowsSdkDir environment variable. It forces this batch script to
-REM assume the Windows 8.1 SDK location should be used.
-REM
-REM USE_WINV100_NSDKLIBPATH
-REM
-REM When set, modifies how the NSDKLIBPATH environment variable is built, based
-REM on the WindowsSdkDir environment variable. It causes this batch script to
-REM assume the Windows 10.0 SDK location should be used.
-REM
-REM NMAKE_ARGS
-REM NMAKE_ARGS_DEBUG
-REM NMAKE_ARGS_RETAIL
-REM
-REM When set, these values are expanded and passed to the NMAKE command line,
-REM after its other arguments. These may be used to specify additional NMAKE
-REM options, for example:
-REM
-REM SET NMAKE_ARGS=FOR_WINRT=1
-REM SET NMAKE_ARGS_DEBUG=MEMDEBUG=1
-REM SET NMAKE_ARGS_RETAIL=WIN32HEAP=1
-REM
-REM Using the above command before running this tool will cause the compiled
-REM binaries to target the WinRT environment, which provides a subset of the
-REM Win32 API.
-REM
-REM DLL_FILE_NAME
-REM DLL_PDB_FILE_NAME
-REM LIB_FILE_NAME
-REM EXE_FILE_NAME
-REM EXE_PDB_FILE_NAME
-REM
-REM When set, these values will override the associated target file name used
-REM for the build.
-REM
-SETLOCAL
-
-REM SET __ECHO=ECHO
-REM SET __ECHO2=ECHO
-REM SET __ECHO3=ECHO
-IF NOT DEFINED _AECHO (SET _AECHO=REM)
-IF NOT DEFINED _CECHO (SET _CECHO=REM)
-IF NOT DEFINED _VECHO (SET _VECHO=REM)
-
-SET REDIRECT=^>
-IF DEFINED __ECHO SET REDIRECT=^^^>
-
-%_AECHO% Running %0 %*
-
-REM SET DFLAGS=/L
-
-%_VECHO% DFlags = '%DFLAGS%'
-
-SET FFLAGS=/V /F /G /H /I /R /Y /Z
-
-%_VECHO% FFlags = '%FFLAGS%'
-
-SET ROOT=%~dp0\..
-SET ROOT=%ROOT:\\=\%
-
-%_VECHO% Root = '%ROOT%'
-
-REM
-REM NOTE: The first and only argument to this batch file should be the output
-REM directory where the platform-specific binary directories should be
-REM created.
-REM
-SET BINARYDIRECTORY=%1
-
-IF NOT DEFINED BINARYDIRECTORY (
- GOTO usage
-)
-
-%_VECHO% BinaryDirectory = '%BINARYDIRECTORY%'
-
-SET DUMMY=%2
-
-IF DEFINED DUMMY (
- GOTO usage
-)
-
-REM
-REM NOTE: From this point, we need a clean error level. Reset it now.
-REM
-CALL :fn_ResetErrorLevel
-
-REM
-REM NOTE: Change the current directory to the root of the source tree, saving
-REM the current directory on the directory stack.
-REM
-%__ECHO2% PUSHD "%ROOT%"
-
-IF ERRORLEVEL 1 (
- ECHO Could not change directory to "%ROOT%".
- GOTO errors
-)
-
-REM
-REM NOTE: This batch file requires the ComSpec environment variable to be set,
-REM typically to something like "C:\Windows\System32\cmd.exe".
-REM
-IF NOT DEFINED ComSpec (
- ECHO The ComSpec environment variable must be defined.
- GOTO errors
-)
-
-REM
-REM NOTE: This batch file requires the VcInstallDir environment variable to be
-REM set. Tyipcally, this means this batch file needs to be run from an
-REM MSVC command prompt.
-REM
-IF NOT DEFINED VCINSTALLDIR (
- ECHO The VCINSTALLDIR environment variable must be defined.
- GOTO errors
-)
-
-REM
-REM NOTE: If the list of platforms is not already set, use the default list.
-REM
-IF NOT DEFINED PLATFORMS (
- SET PLATFORMS=x86 x86_amd64 x86_arm
-)
-
-%_VECHO% Platforms = '%PLATFORMS%'
-
-REM
-REM NOTE: If the list of configurations is not already set, use the default
-REM list.
-REM
-IF NOT DEFINED CONFIGURATIONS (
- SET CONFIGURATIONS=Debug Retail
-)
-
-%_VECHO% Configurations = '%CONFIGURATIONS%'
-
-REM
-REM NOTE: If the command used to invoke NMAKE is not already set, use the
-REM default.
-REM
-IF NOT DEFINED NMAKE_CMD (
- IF DEFINED USE_AUTOCONF_MAKEFILE (
- SET NMAKE_CMD=nmake -B -f autoconf\Makefile.msc
- ) ELSE (
- SET NMAKE_CMD=nmake -B -f Makefile.msc
- )
-)
-
-%_VECHO% NmakeCmd = '%NMAKE_CMD%'
-%_VECHO% NmakeArgs = '%NMAKE_ARGS%'
-%_VECHO% NmakeArgsDebug = '%NMAKE_ARGS_DEBUG%'
-%_VECHO% NmakeArgsRetail = '%NMAKE_ARGS_RETAIL%'
-
-REM
-REM NOTE: Setup environment variables to translate between the MSVC platform
-REM names and the names to be used for the platform-specific binary
-REM directories.
-REM
-SET amd64_NAME=x64
-SET arm_NAME=ARM
-SET x64_NAME=x64
-SET x86_NAME=x86
-SET x86_amd64_NAME=x64
-SET x86_arm_NAME=ARM
-SET x86_x64_NAME=x64
-
-%_VECHO% amd64_Name = '%amd64_NAME%'
-%_VECHO% arm_Name = '%arm_NAME%'
-%_VECHO% x64_Name = '%x64_NAME%'
-%_VECHO% x86_Name = '%x86_NAME%'
-%_VECHO% x86_amd64_Name = '%x86_amd64_NAME%'
-%_VECHO% x86_arm_Name = '%x86_arm_NAME%'
-%_VECHO% x86_x64_Name = '%x86_x64_NAME%'
-
-REM
-REM NOTE: Check for the external tools needed during the build process ^(i.e.
-REM those that do not get compiled as part of the build process itself^)
-REM along the PATH.
-REM
-IF DEFINED TCLSH_CMD (
- SET TCLSH_FILE=%TCLSH_CMD%
-) ELSE (
- SET TCLSH_FILE=tclsh.exe
-)
-
-FOR %%T IN (%TCLSH_FILE%) DO (
- SET %%T_PATH=%%~dp$PATH:T
-)
-
-REM
-REM NOTE: A Tcl shell executable is required during the SQLite build process
-REM unless a pre-existing amalgamation file is used.
-REM
-IF NOT DEFINED %TCLSH_FILE%_PATH (
- ECHO The Tcl shell executable "%TCLSH_FILE%" is required to be in the PATH.
- GOTO errors
-)
-
-REM
-REM NOTE: Setup the default names for the build targets we are creating. Any
-REM ^(or all^) of these may end up being overridden.
-REM
-IF NOT DEFINED DLL_FILE_NAME (
- SET DLL_FILE_NAME=sqlite3.dll
-)
-
-IF NOT DEFINED DLL_PDB_FILE_NAME (
- SET DLL_PDB_FILE_NAME=sqlite3.pdb
-)
-
-IF NOT DEFINED LIB_FILE_NAME (
- SET LIB_FILE_NAME=sqlite3.lib
-)
-
-IF NOT DEFINED EXE_FILE_NAME (
- SET EXE_FILE_NAME=sqlite3.exe
-)
-
-IF NOT DEFINED EXE_PDB_FILE_NAME (
- SET EXE_PDB_FILE_NAME=sqlite3sh.pdb
-)
-
-REM
-REM NOTE: Set the TOOLPATH variable to contain all the directories where the
-REM external tools were found in the search above.
-REM
-CALL :fn_CopyVariable %TCLSH_FILE%_PATH TOOLPATH
-
-%_VECHO% ToolPath = '%TOOLPATH%'
-
-REM
-REM NOTE: Setting the Windows SDK library path is only required for MSVC
-REM 2012, 2013, and 2015.
-REM
-CALL :fn_UnsetVariable SET_NSDKLIBPATH
-
-REM
-REM NOTE: Setting the Universal CRT library path is only required for MSVC
-REM 2015.
-REM
-CALL :fn_UnsetVariable SET_NUCRTLIBPATH
-
-REM
-REM NOTE: Check for MSVC 2012, 2013, and 2015 specially because the Windows
-REM SDK directory handling is slightly different for those versions.
-REM
-IF "%VisualStudioVersion%" == "11.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-) ELSE IF "%VisualStudioVersion%" == "12.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-) ELSE IF "%VisualStudioVersion%" == "14.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-
- REM
- REM NOTE: If the Universal CRT library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NUCRTLIBPATH (
- SET SET_NUCRTLIBPATH=1
- )
-)
-
-REM
-REM NOTE: This is the name of the sub-directory where the UCRT libraries may
-REM be found. It is only used when compiling against the UCRT.
-REM
-IF DEFINED UCRTVersion (
- SET NUCRTVER=%UCRTVersion%
-) ELSE (
- SET NUCRTVER=10.0.10586.0
-)
-
-REM
-REM NOTE: This is the name of the sub-directory where the Windows 10.0 SDK
-REM libraries may be found. It is only used when compiling with the
-REM Windows 10.0 SDK.
-REM
-IF DEFINED WindowsSDKLibVersion (
- SET WIN10SDKVER=%WindowsSDKLibVersion:\=%
-) ELSE (
- SET WIN10SDKVER=%NUCRTVER%
-)
-
-REM
-REM NOTE: Check if this is the Windows Phone SDK. If so, a different batch
-REM file is necessary to setup the build environment. Since the variable
-REM values involved here may contain parenthesis, using GOTO instead of
-REM an IF block is required.
-REM
-IF DEFINED WindowsPhoneKitDir GOTO set_vcvarsall_phone
-SET VCVARSALL=%VCINSTALLDIR%\vcvarsall.bat
-GOTO set_vcvarsall_done
-:set_vcvarsall_phone
-SET VCVARSALL=%VCINSTALLDIR%\WPSDK\WP80\vcvarsphoneall.bat
-:set_vcvarsall_done
-SET VCVARSALL=%VCVARSALL:\\=\%
-
-REM
-REM NOTE: This is the outer loop. There should be exactly one iteration per
-REM platform.
-REM
-FOR %%P IN (%PLATFORMS%) DO (
- REM
- REM NOTE: Using the MSVC platform name, lookup the simpler platform name to
- REM be used for the name of the platform-specific binary directory via
- REM the environment variables setup earlier.
- REM
- CALL :fn_CopyVariable %%P_NAME PLATFORMNAME
-
- REM
- REM NOTE: This is the second loop. There should be exactly one iteration.
- REM This loop is necessary because the PlatformName environment
- REM variable was set above and that value is needed by some of the
- REM commands contained in the inner loop. If these commands were
- REM directly contained in the outer loop, the PlatformName environment
- REM variable would be stuck with its initial empty value instead.
- REM
- FOR /F "tokens=2* delims==" %%D IN ('SET PLATFORMNAME') DO (
- REM
- REM NOTE: Attempt to clean the environment of all variables used by MSVC
- REM and/or Visual Studio. This block may need to be updated in the
- REM future to account for additional environment variables.
- REM
- CALL :fn_UnsetVariable CommandPromptType
- CALL :fn_UnsetVariable DevEnvDir
- CALL :fn_UnsetVariable DNX_HOME
- CALL :fn_UnsetVariable ExtensionSdkDir
- CALL :fn_UnsetVariable Framework35Version
- CALL :fn_UnsetVariable Framework40Version
- CALL :fn_UnsetVariable FrameworkDir
- CALL :fn_UnsetVariable FrameworkDir32
- CALL :fn_UnsetVariable FrameworkVersion
- CALL :fn_UnsetVariable FrameworkVersion32
- CALL :fn_UnsetVariable FSHARPINSTALLDIR
- CALL :fn_UnsetVariable INCLUDE
- CALL :fn_UnsetVariable LIB
- CALL :fn_UnsetVariable LIBPATH
- CALL :fn_UnsetVariable NETFXSDKDir
- CALL :fn_UnsetVariable Platform
- CALL :fn_UnsetVariable UCRTVersion
- CALL :fn_UnsetVariable UniversalCRTSdkDir
- REM CALL :fn_UnsetVariable VCINSTALLDIR
- CALL :fn_UnsetVariable VSINSTALLDIR
- CALL :fn_UnsetVariable WindowsLibPath
- CALL :fn_UnsetVariable WindowsPhoneKitDir
- CALL :fn_UnsetVariable WindowsSdkDir
- CALL :fn_UnsetVariable WindowsSdkDir_35
- CALL :fn_UnsetVariable WindowsSdkDir_old
- CALL :fn_UnsetVariable WindowsSDKLibVersion
- CALL :fn_UnsetVariable WindowsSDKVersion
- CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x86
- CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x64
-
- REM
- REM NOTE: Reset the PATH here to the absolute bare minimum required.
- REM
- CALL :fn_ResetPath
-
- REM
- REM NOTE: This is the inner loop. There are normally two iterations, one
- REM for each supported build configuration, e.g. Debug or Retail.
- REM
- FOR %%B IN (%CONFIGURATIONS%) DO (
- REM
- REM NOTE: When preparing the debug build, set the DEBUG and MEMDEBUG
- REM environment variables to be picked up by the MSVC makefile
- REM itself.
- REM
- %_AECHO% Building the %%B configuration for platform %%P with name %%D...
-
- IF /I "%%B" == "Debug" (
- REM
- REM NOTE: Using this level for the DEBUG environment variable should
- REM disable all compiler optimizations and prevent use of the
- REM NDEBUG define. Additionally, both SQLITE_ENABLE_API_ARMOR
- REM and SQLITE_DEBUG defines should be enabled.
- REM
- SET DEBUG=3
-
- REM
- REM NOTE: Setting this to non-zero should enable the SQLITE_MEMDEBUG
- REM define.
- REM
- IF NOT DEFINED NOMEMDEBUG (
- SET MEMDEBUG=1
- )
- ) ELSE (
- CALL :fn_UnsetVariable DEBUG
- CALL :fn_UnsetVariable MEMDEBUG
- )
-
- REM
- REM NOTE: Copy the extra NMAKE arguments for this configuration into the
- REM common variable used by the actual commands.
- REM
- CALL :fn_CopyVariable NMAKE_ARGS_%%B NMAKE_ARGS_CFG
-
- REM
- REM NOTE: Launch a nested command shell to perform the following steps:
- REM
- REM 1. Setup the MSVC environment for this platform using the
- REM official batch file.
- REM
- REM 2. Make sure that no stale build output files are present.
- REM
- REM 3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this
- REM platform.
- REM
- REM 4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this
- REM platform to the platform-specific directory beneath the
- REM binary directory.
- REM
- REM 5. Unless prevented from doing so, copy the "sqlite3.pdb"
- REM symbols file for this platform to the platform-specific
- REM directory beneath the binary directory.
- REM
- "%ComSpec%" /C (
- REM
- REM NOTE: Attempt to setup the MSVC environment for this platform.
- REM
- %__ECHO3% CALL "%VCVARSALL%" %%P
-
- IF ERRORLEVEL 1 (
- ECHO Failed to call "%VCVARSALL%" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: If this batch file is not running in "what-if" mode, check to
- REM be sure we were actually able to setup the MSVC environment
- REM as current versions of their official batch file do not set
- REM the exit code upon failure.
- REM
- IF NOT DEFINED __ECHO3 (
- IF NOT DEFINED WindowsPhoneKitDir (
- IF NOT DEFINED WindowsSdkDir (
- ECHO Cannot build, Windows SDK not found for platform %%P.
- GOTO errors
- )
- )
- )
-
- REM
- REM NOTE: When using MSVC 2012, 2013, or 2015, the native SDK path
- REM cannot simply be the "lib" sub-directory beneath the location
- REM specified in the WindowsSdkDir environment variable because
- REM that location does not actually contain the necessary library
- REM files for x86. This must be done for each iteration because
- REM it relies upon the WindowsSdkDir environment variable being
- REM set by the batch file used to setup the MSVC environment.
- REM
- IF DEFINED SET_NSDKLIBPATH (
- REM
- REM NOTE: The Windows Phone SDK has a slightly different directory
- REM structure and must be handled specially here.
- REM
- IF DEFINED WindowsPhoneKitDir (
- CALL :fn_CopyVariable WindowsPhoneKitDir NSDKLIBPATH
- CALL :fn_AppendVariable NSDKLIBPATH \lib\x86
- ) ELSE IF DEFINED WindowsSdkDir (
- CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH
-
- REM
- REM NOTE: The Windows 8.x and Windows 10.0 SDKs have a slightly
- REM different directory naming conventions.
- REM
- IF DEFINED USE_WINV100_NSDKLIBPATH (
- CALL :fn_AppendVariable NSDKLIBPATH \..\10\lib\%WIN10SDKVER%\um\x86
- CALL :fn_CopyVariable WindowsSdkDir PSDKLIBPATH
- CALL :fn_AppendVariable PSDKLIBPATH lib\%WIN10SDKVER%\um\%%D
- ) ELSE IF DEFINED USE_WINV63_NSDKLIBPATH (
- CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86
- ) ELSE IF "%VisualStudioVersion%" == "12.0" (
- CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
- ) ELSE IF "%VisualStudioVersion%" == "14.0" (
- CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
- ) ELSE (
- CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
- )
- )
- )
-
- REM
- REM NOTE: When using MSVC 2015, setting the Universal CRT library path
- REM for x86 may be required as well. This must also be done for
- REM each iteration because it relies upon the UniversalCRTSdkDir
- REM environment variable being set by the batch file used to
- REM setup the MSVC environment.
- REM
- IF DEFINED SET_NUCRTLIBPATH (
- IF DEFINED UniversalCRTSdkDir (
- CALL :fn_CopyVariable UniversalCRTSdkDir NUCRTLIBPATH
- CALL :fn_AppendVariable NUCRTLIBPATH \lib\%NUCRTVER%\ucrt\x86
- )
- )
-
- REM
- REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC
- REM makefile to clean any stale build output from previous
- REM iterations of this loop and/or previous runs of this batch
- REM file, etc.
- REM
- IF NOT DEFINED NOCLEAN (
- CALL :fn_MakeClean %%D
-
- IF ERRORLEVEL 1 (
- ECHO Failed to clean for platform %%P.
- GOTO errors
- )
- ) ELSE (
- REM
- REM NOTE: Even when the cleaning step has been disabled, we still
- REM need to remove the build output for all the files we are
- REM specifically wanting to build for each platform.
- REM
- %_AECHO% Cleaning final core library output files only...
- %__ECHO% DEL /Q *.lo "%DLL_FILE_NAME%" "%LIB_FILE_NAME%" "%DLL_PDB_FILE_NAME%" 2%REDIRECT% NUL
- )
-
- REM
- REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.dll"
- REM binary. The x86 compiler will be used to compile the native
- REM command line tools needed during the build process itself.
- REM Also, disable looking for and/or linking to the native Tcl
- REM runtime library.
- REM
- CALL :fn_MakeDll %%D
-
- IF ERRORLEVEL 1 (
- ECHO Failed to build %%B "%DLL_FILE_NAME%" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.dll" file to the appropriate directory for
- REM the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY "%DLL_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%DLL_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.lib" file to the appropriate directory for
- REM the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY "%LIB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%LIB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.pdb" file to the appropriate directory for
- REM the build and platform beneath the binary directory unless we
- REM are prevented from doing so.
- REM
- IF NOT DEFINED NOSYMBOLS (
- IF EXIST "%DLL_PDB_FILE_NAME%" (
- %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
- )
- )
-
- REM
- REM NOTE: If requested, also build the shell executable.
- REM
- IF DEFINED BUILD_ALL_SHELL (
- REM
- REM NOTE: If necessary, make sure any previous build output for the
- REM shell executable is deleted.
- REM
- IF DEFINED NOCLEAN (
- REM
- REM NOTE: Even when the cleaning step has been disabled, we still
- REM need to remove the build output for all the files we are
- REM specifically wanting to build for each platform.
- REM
- %_AECHO% Cleaning final shell executable output files only...
- %__ECHO% DEL /Q "%EXE_FILE_NAME%" "%EXE_PDB_FILE_NAME%" 2%REDIRECT% NUL
- )
-
- REM
- REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.exe"
- REM binary. The x86 compiler will be used to compile the native
- REM command line tools needed during the build process itself.
- REM Also, disable looking for and/or linking to the native Tcl
- REM runtime library.
- REM
- CALL :fn_MakeExe %%D
-
- IF ERRORLEVEL 1 (
- ECHO Failed to build %%B "%EXE_FILE_NAME%" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.exe" file to the appropriate directory
- REM for the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY "%EXE_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%EXE_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3sh.pdb" file to the appropriate directory
- REM for the build and platform beneath the binary directory
- REM unless we are prevented from doing so.
- REM
- IF NOT DEFINED NOSYMBOLS (
- IF EXIST "%EXE_PDB_FILE_NAME%" (
- %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
- )
- )
- )
- )
- )
- )
-
- REM
- REM NOTE: Handle any errors generated during the nested command shell.
- REM
- IF ERRORLEVEL 1 (
- GOTO errors
- )
-)
-
-REM
-REM NOTE: Restore the saved current directory from the directory stack.
-REM
-%__ECHO2% POPD
-
-IF ERRORLEVEL 1 (
- ECHO Could not restore directory.
- GOTO errors
-)
-
-REM
-REM NOTE: If we get to this point, we have succeeded.
-REM
-GOTO no_errors
-
-:fn_MakeClean
- %__ECHO% %NMAKE_CMD% clean "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
- GOTO :EOF
-
-:fn_MakeDll
- %__ECHO% %NMAKE_CMD% "%DLL_FILE_NAME%" "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
- GOTO :EOF
-
-:fn_MakeExe
- %__ECHO% %NMAKE_CMD% "%EXE_FILE_NAME%" "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
- GOTO :EOF
-
-:fn_ShowVariable
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%2%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- IF NOT "%%V" == "" (
- IF NOT "%%V" == "%%%2%%" (
- %_VECHO% %1 = '%%V'
- )
- )
- )
- ENDLOCAL
- GOTO :EOF
-
-:fn_ResetErrorLevel
- VERIFY > NUL
- GOTO :EOF
-
-:fn_SetErrorLevel
- VERIFY MAYBE 2> NUL
- GOTO :EOF
-
-:fn_CopyVariable
- IF NOT DEFINED %1 GOTO :EOF
- IF "%2" == "" GOTO :EOF
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%1%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET VALUE=%%V
- )
- ENDLOCAL && SET %2=%VALUE%
- GOTO :EOF
-
-:fn_UnsetVariable
- SETLOCAL
- SET VALUE=%1
- IF DEFINED VALUE (
- SET VALUE=
- ENDLOCAL
- SET %VALUE%=
- ) ELSE (
- ENDLOCAL
- )
- CALL :fn_ResetErrorLevel
- GOTO :EOF
-
-:fn_ResetPath
- SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
- GOTO :EOF
-
-:fn_AppendVariable
- SET __ECHO_CMD=ECHO %%%1%%
- IF DEFINED %1 (
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET %1=%%V%~2
- )
- ) ELSE (
- SET %1=%~2
- )
- SET __ECHO_CMD=
- CALL :fn_ResetErrorLevel
- GOTO :EOF
-
-:usage
- ECHO.
- ECHO Usage: %~nx0 ^<binaryDirectory^>
- ECHO.
- GOTO errors
-
-:errors
- CALL :fn_SetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Failure, errors were encountered.
- GOTO end_of_file
-
-:no_errors
- CALL :fn_ResetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Success, no errors were encountered.
- GOTO end_of_file
-
-:end_of_file
-%__ECHO% EXIT /B %ERRORLEVEL%
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/build-shell.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/build-shell.sh
deleted file mode 100644
index 6a48299d73b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/build-shell.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-#
-# This script demonstrates how to do a full-featured build of the sqlite3
-# command-line shell on Linux.
-#
-# SQLite source code should be in a sibling directory named "sqlite". For
-# example, put SQLite sources in ~/sqlite/sqlite and run this script from
-# ~/sqlite/bld. There should be an appropriate Makefile in the current
-# directory as well.
-#
-make sqlite3.c
-gcc -o sqlite3 -g -Os -I. \
- -DSQLITE_THREADSAFE=0 \
- -DSQLITE_ENABLE_VFSTRACE \
- -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_FTS4 \
- -DSQLITE_ENABLE_RTREE \
- -DHAVE_READLINE \
- -DHAVE_USLEEP=1 \
- ../sqlite/src/shell.c \
- ../sqlite/src/test_vfstrace.c \
- sqlite3.c -ldl -lreadline -lncurses
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/cg_anno.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/cg_anno.tcl
deleted file mode 100755
index 43d2b74fcd1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/cg_anno.tcl
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/tclsh
-#
-# A wrapper around cg_annotate that sets appropriate command-line options
-# and rearranges the output so that annotated files occur in a consistent
-# sorted order. Used by the speed-check.tcl script.
-#
-
-set in [open "|cg_annotate --show=Ir --auto=yes --context=40 $argv" r]
-set dest !
-set out(!) {}
-set linenum 0
-set cntlines 0 ;# true to remember cycle counts on each line
-set seenSqlite3 0 ;# true if we have seen the sqlite3.c file
-while {![eof $in]} {
- set line [string map {\t { }} [gets $in]]
- if {[regexp {^-- Auto-annotated source: (.*)} $line all name]} {
- set dest $name
- if {[string match */sqlite3.c $dest]} {
- set cntlines 1
- set seenSqlite3 1
- } else {
- set cntlines 0
- }
- } elseif {[regexp {^-- line (\d+) ------} $line all ln]} {
- set line [lreplace $line 2 2 {#}]
- set linenum [expr {$ln-1}]
- } elseif {[regexp {^The following files chosen for } $line]} {
- set dest !
- }
- append out($dest) $line\n
- if {$cntlines} {
- incr linenum
- if {[regexp {^ *([0-9,]+) } $line all x]} {
- set x [string map {, {}} $x]
- set cycles($linenum) $x
- }
- }
-}
-foreach x [lsort [array names out]] {
- puts $out($x)
-}
-
-# If the sqlite3.c file has been seen, then output a summary of the
-# cycle counts for each file that went into making up sqlite3.c
-#
-if {$seenSqlite3} {
- close $in
- set in [open sqlite3.c]
- set linenum 0
- set fn sqlite3.c
- set pattern1 {^/\*+ Begin file ([^ ]+) \*}
- set pattern2 {^/\*+ Continuing where we left off in ([^ ]+) \*}
- while {![eof $in]} {
- set line [gets $in]
- incr linenum
- if {[regexp $pattern1 $line all newfn]} {
- set fn $newfn
- } elseif {[regexp $pattern2 $line all newfn]} {
- set fn $newfn
- } elseif {[info exists cycles($linenum)]} {
- incr fcycles($fn) $cycles($linenum)
- }
- }
- close $in
- puts {**********************************************************************}
- set lx {}
- set sum 0
- foreach {fn cnt} [array get fcycles] {
- lappend lx [list $cnt $fn]
- incr sum $cnt
- }
- puts [format {%20s %14d %8.3f%%} TOTAL $sum 100]
- foreach entry [lsort -index 0 -integer -decreasing $lx] {
- foreach {cnt fn} $entry break
- puts [format {%20s %14d %8.3f%%} $fn $cnt [expr {$cnt*100.0/$sum}]]
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/checkSpacing.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/checkSpacing.c
deleted file mode 100644
index ce38b08ce4c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/checkSpacing.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-** This program checks for formatting problems in source code:
-**
-** * Any use of tab characters
-** * White space at the end of a line
-** * Blank lines at the end of a file
-**
-** Any violations are reported.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define CR_OK 0x001
-#define WSEOL_OK 0x002
-
-static void checkSpacing(const char *zFile, unsigned flags){
- FILE *in = fopen(zFile, "rb");
- int i;
- int seenSpace;
- int seenTab;
- int ln = 0;
- int lastNonspace = 0;
- char zLine[2000];
- if( in==0 ){
- printf("cannot open %s\n", zFile);
- return;
- }
- while( fgets(zLine, sizeof(zLine), in) ){
- seenSpace = 0;
- seenTab = 0;
- ln++;
- for(i=0; zLine[i]; i++){
- if( zLine[i]=='\t' && seenTab==0 ){
- printf("%s:%d: tab (\\t) character\n", zFile, ln);
- seenTab = 1;
- }else if( zLine[i]=='\r' ){
- if( (flags & CR_OK)==0 ){
- printf("%s:%d: carriage-return (\\r) character\n", zFile, ln);
- }
- }else if( zLine[i]==' ' ){
- seenSpace = 1;
- }else if( zLine[i]!='\n' ){
- lastNonspace = ln;
- seenSpace = 0;
- }
- }
- if( seenSpace && (flags & WSEOL_OK)==0 ){
- printf("%s:%d: whitespace at end-of-line\n", zFile, ln);
- }
- }
- fclose(in);
- if( lastNonspace<ln ){
- printf("%s:%d: blank lines at end of file (%d)\n",
- zFile, ln, ln - lastNonspace);
- }
-}
-
-int main(int argc, char **argv){
- int i;
- unsigned flags = WSEOL_OK;
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]=='-' ){
- while( z[0]=='-' ) z++;
- if( strcmp(z,"crok")==0 ){
- flags |= CR_OK;
- }else if( strcmp(z, "wseol")==0 ){
- flags &= ~WSEOL_OK;
- }else if( strcmp(z, "help")==0 ){
- printf("Usage: %s [options] FILE ...\n", argv[0]);
- printf(" --crok Do not report on carriage-returns\n");
- printf(" --wseol Complain about whitespace at end-of-line\n");
- printf(" --help This message\n");
- }else{
- printf("unknown command-line option: [%s]\n", argv[i]);
- printf("use --help for additional information\n");
- }
- }else{
- checkSpacing(argv[i], flags);
- }
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/dbhash.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/dbhash.c
deleted file mode 100644
index b1c72b3e36f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/dbhash.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
-** 2016-06-07
-**
-** 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 is a utility program that computes an SHA1 hash on the content
-** of an SQLite database.
-**
-** The hash is computed over just the content of the database. Free
-** space inside of the database file, and alternative on-disk representations
-** of the same content (ex: UTF8 vs UTF16) do not affect the hash. So,
-** for example, the database file page size, encoding, and auto_vacuum setting
-** can all be changed without changing the hash.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
-#include <assert.h>
-#include "sqlite3.h"
-
-/* Context for the SHA1 hash */
-typedef struct SHA1Context SHA1Context;
-struct SHA1Context {
- unsigned int state[5];
- unsigned int count[2];
- unsigned char buffer[64];
-};
-
-/*
-** All global variables are gathered into the "g" singleton.
-*/
-struct GlobalVars {
- const char *zArgv0; /* Name of program */
- unsigned fDebug; /* Debug flags */
- sqlite3 *db; /* The database connection */
- SHA1Context cx; /* SHA1 hash context */
-} g;
-
-/*
-** Debugging flags
-*/
-#define DEBUG_FULLTRACE 0x00000001 /* Trace hash to stderr */
-
-/******************************************************************************
-** The Hash Engine
-**
-** Modify these routines (and appropriate state fields in global variable 'g')
-** in order to compute a different (better?) hash of the database.
-*/
-/*
- * blk0() and blk() perform the initial expand.
- * I got the idea of expanding during the round function from SSLeay
- *
- * blk0le() for little-endian and blk0be() for big-endian.
- */
-#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
-/*
- * GCC by itself only generates left rotates. Use right rotates if
- * possible to be kinder to dinky implementations with iterative rotate
- * instructions.
- */
-#define SHA_ROT(op, x, k) \
- ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
-#define rol(x,k) SHA_ROT("roll", x, k)
-#define ror(x,k) SHA_ROT("rorl", x, k)
-
-#else
-/* Generic C equivalent */
-#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
-#define rol(x,k) SHA_ROT(x,k,32-(k))
-#define ror(x,k) SHA_ROT(x,32-(k),k)
-#endif
-
-
-#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
- |(rol(block[i],8)&0x00FF00FF))
-#define blk0be(i) block[i]
-#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
- ^block[(i+2)&15]^block[i&15],1))
-
-/*
- * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
- *
- * Rl0() for little-endian and Rb0() for big-endian. Endianness is
- * determined at run-time.
- */
-#define Rl0(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define Rb0(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define R1(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define R2(v,w,x,y,z,i) \
- z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
-#define R3(v,w,x,y,z,i) \
- z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
-#define R4(v,w,x,y,z,i) \
- z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
-
-/*
- * Hash a single 512-bit block. This is the core of the algorithm.
- */
-#define a qq[0]
-#define b qq[1]
-#define c qq[2]
-#define d qq[3]
-#define e qq[4]
-
-void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
- unsigned int qq[5]; /* a, b, c, d, e; */
- static int one = 1;
- unsigned int block[16];
- memcpy(block, buffer, 64);
- memcpy(qq,state,5*sizeof(unsigned int));
-
- /* Copy g.cx.state[] to working vars */
- /*
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- */
-
- /* 4 rounds of 20 operations each. Loop unrolled. */
- if( 1 == *(unsigned char*)&one ){
- Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
- Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
- Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
- Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
- }else{
- Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
- Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
- Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
- Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
- }
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
-}
-
-
-/* Initialize the SHA1 hash */
-static void hash_init(void){
- /* SHA1 initialization constants */
- g.cx.state[0] = 0x67452301;
- g.cx.state[1] = 0xEFCDAB89;
- g.cx.state[2] = 0x98BADCFE;
- g.cx.state[3] = 0x10325476;
- g.cx.state[4] = 0xC3D2E1F0;
- g.cx.count[0] = g.cx.count[1] = 0;
-}
-
-/* Add new content to the SHA1 hash */
-static void hash_step(const unsigned char *data, unsigned int len){
- unsigned int i, j;
-
- j = g.cx.count[0];
- if( (g.cx.count[0] += len << 3) < j ){
- g.cx.count[1] += (len>>29)+1;
- }
- j = (j >> 3) & 63;
- if( (j + len) > 63 ){
- (void)memcpy(&g.cx.buffer[j], data, (i = 64-j));
- SHA1Transform(g.cx.state, g.cx.buffer);
- for(; i + 63 < len; i += 64){
- SHA1Transform(g.cx.state, &data[i]);
- }
- j = 0;
- }else{
- i = 0;
- }
- (void)memcpy(&g.cx.buffer[j], &data[i], len - i);
-}
-
-
-/* Add padding and compute and output the message digest. */
-static void hash_finish(const char *zName){
- unsigned int i;
- unsigned char finalcount[8];
- unsigned char digest[20];
- static const char zEncode[] = "0123456789abcdef";
- char zOut[41];
-
- for (i = 0; i < 8; i++){
- finalcount[i] = (unsigned char)((g.cx.count[(i >= 4 ? 0 : 1)]
- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
- }
- hash_step((const unsigned char *)"\200", 1);
- while ((g.cx.count[0] & 504) != 448){
- hash_step((const unsigned char *)"\0", 1);
- }
- hash_step(finalcount, 8); /* Should cause a SHA1Transform() */
- for (i = 0; i < 20; i++){
- digest[i] = (unsigned char)((g.cx.state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
- for(i=0; i<20; i++){
- zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
- zOut[i*2+1] = zEncode[digest[i] & 0xf];
- }
- zOut[i*2]= 0;
- printf("%s %s\n", zOut, zName);
-}
-/* End of the hashing logic
-*******************************************************************************/
-
-/*
-** Print an error resulting from faulting command-line arguments and
-** abort the program.
-*/
-static void cmdlineError(const char *zFormat, ...){
- va_list ap;
- fprintf(stderr, "%s: ", g.zArgv0);
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n\"%s --help\" for more help\n", g.zArgv0);
- exit(1);
-}
-
-/*
-** Print an error message for an error that occurs at runtime, then
-** abort the program.
-*/
-static void runtimeError(const char *zFormat, ...){
- va_list ap;
- fprintf(stderr, "%s: ", g.zArgv0);
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-/*
-** Prepare a new SQL statement. Print an error and abort if anything
-** goes wrong.
-*/
-static sqlite3_stmt *db_vprepare(const char *zFormat, va_list ap){
- char *zSql;
- int rc;
- sqlite3_stmt *pStmt;
-
- zSql = sqlite3_vmprintf(zFormat, ap);
- if( zSql==0 ) runtimeError("out of memory");
- rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0);
- if( rc ){
- runtimeError("SQL statement error: %s\n\"%s\"", sqlite3_errmsg(g.db),
- zSql);
- }
- sqlite3_free(zSql);
- return pStmt;
-}
-static sqlite3_stmt *db_prepare(const char *zFormat, ...){
- va_list ap;
- sqlite3_stmt *pStmt;
- va_start(ap, zFormat);
- pStmt = db_vprepare(zFormat, ap);
- va_end(ap);
- return pStmt;
-}
-
-/*
-** Compute the hash for all rows of the query formed from the printf-style
-** zFormat and its argument.
-*/
-static void hash_one_query(const char *zFormat, ...){
- va_list ap;
- sqlite3_stmt *pStmt; /* The query defined by zFormat and "..." */
- int nCol; /* Number of columns in the result set */
- int i; /* Loop counter */
-
- /* Prepare the query defined by zFormat and "..." */
- va_start(ap, zFormat);
- pStmt = db_vprepare(zFormat, ap);
- va_end(ap);
- nCol = sqlite3_column_count(pStmt);
-
- /* Compute a hash over the result of the query */
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- for(i=0; i<nCol; i++){
- switch( sqlite3_column_type(pStmt,i) ){
- case SQLITE_NULL: {
- hash_step((const unsigned char*)"0",1);
- if( g.fDebug & DEBUG_FULLTRACE ) fprintf(stderr, "NULL\n");
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_uint64 u;
- int j;
- unsigned char x[8];
- sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
- memcpy(&u, &v, 8);
- for(j=7; j>=0; j--){
- x[j] = u & 0xff;
- u >>= 8;
- }
- hash_step((const unsigned char*)"1",1);
- hash_step(x,8);
- if( g.fDebug & DEBUG_FULLTRACE ){
- fprintf(stderr, "INT %s\n", sqlite3_column_text(pStmt,i));
- }
- break;
- }
- case SQLITE_FLOAT: {
- sqlite3_uint64 u;
- int j;
- unsigned char x[8];
- double r = sqlite3_column_double(pStmt,i);
- memcpy(&u, &r, 8);
- for(j=7; j>=0; j--){
- x[j] = u & 0xff;
- u >>= 8;
- }
- hash_step((const unsigned char*)"2",1);
- hash_step(x,8);
- if( g.fDebug & DEBUG_FULLTRACE ){
- fprintf(stderr, "FLOAT %s\n", sqlite3_column_text(pStmt,i));
- }
- break;
- }
- case SQLITE_TEXT: {
- int n = sqlite3_column_bytes(pStmt, i);
- const unsigned char *z = sqlite3_column_text(pStmt, i);
- hash_step((const unsigned char*)"3", 1);
- hash_step(z, n);
- if( g.fDebug & DEBUG_FULLTRACE ){
- fprintf(stderr, "TEXT '%s'\n", sqlite3_column_text(pStmt,i));
- }
- break;
- }
- case SQLITE_BLOB: {
- int n = sqlite3_column_bytes(pStmt, i);
- const unsigned char *z = sqlite3_column_blob(pStmt, i);
- hash_step((const unsigned char*)"4", 1);
- hash_step(z, n);
- if( g.fDebug & DEBUG_FULLTRACE ){
- fprintf(stderr, "BLOB (%d bytes)\n", n);
- }
- break;
- }
- }
- }
- }
- sqlite3_finalize(pStmt);
-}
-
-
-/*
-** Print sketchy documentation for this utility program
-*/
-static void showHelp(void){
- printf("Usage: %s [options] FILE ...\n", g.zArgv0);
- printf(
-"Compute a SHA1 hash on the content of database FILE. System tables such as\n"
-"sqlite_stat1, sqlite_stat4, and sqlite_sequence are omitted from the hash.\n"
-"Options:\n"
-" --debug N Set debugging flags to N (experts only)\n"
-" --like PATTERN Only hash tables whose name is LIKE the pattern\n"
-" --schema-only Only hash the schema - omit table content\n"
-" --without-schema Only hash table content - omit the schema\n"
- );
-}
-
-int main(int argc, char **argv){
- const char *zDb = 0; /* Name of the database currently being hashed */
- int i; /* Loop counter */
- int rc; /* Subroutine return code */
- char *zErrMsg; /* Error message when opening database */
- sqlite3_stmt *pStmt; /* An SQLite query */
- const char *zLike = 0; /* LIKE pattern of tables to hash */
- int omitSchema = 0; /* True to compute hash on content only */
- int omitContent = 0; /* True to compute hash on schema only */
- int nFile = 0; /* Number of input filenames seen */
-
- g.zArgv0 = argv[0];
- sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]=='-' ){
- z++;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"debug")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- g.fDebug = strtol(argv[++i], 0, 0);
- }else
- if( strcmp(z,"help")==0 ){
- showHelp();
- return 0;
- }else
- if( strcmp(z,"like")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- if( zLike!=0 ) cmdlineError("only one --like allowed");
- zLike = argv[++i];
- }else
- if( strcmp(z,"schema-only")==0 ){
- omitContent = 1;
- }else
- if( strcmp(z,"without-schema")==0 ){
- omitSchema = 1;
- }else
- {
- cmdlineError("unknown option: %s", argv[i]);
- }
- }else{
- nFile++;
- if( nFile<i ) argv[nFile] = argv[i];
- }
- }
- if( nFile==0 ){
- cmdlineError("no input files specified - nothing to do");
- }
- if( omitSchema && omitContent ){
- cmdlineError("only one of --without-schema and --omit-schema allowed");
- }
- if( zLike==0 ) zLike = "%";
-
- for(i=1; i<=nFile; i++){
- static const int openFlags =
- SQLITE_OPEN_READWRITE | /* Read/write so hot journals can recover */
- SQLITE_OPEN_URI
- ;
- zDb = argv[i];
- rc = sqlite3_open_v2(zDb, &g.db, openFlags, 0);
- if( rc ){
- fprintf(stderr, "cannot open database file '%s'\n", zDb);
- continue;
- }
- rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_master", 0, 0, &zErrMsg);
- if( rc || zErrMsg ){
- sqlite3_close(g.db);
- g.db = 0;
- fprintf(stderr, "'%s' is not a valid SQLite database\n", zDb);
- continue;
- }
-
- /* Start the hash */
- hash_init();
-
- /* Hash table content */
- if( !omitContent ){
- pStmt = db_prepare(
- "SELECT name FROM sqlite_master\n"
- " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
- " AND name NOT LIKE 'sqlite_%%'\n"
- " AND name LIKE '%q'\n"
- " ORDER BY name COLLATE nocase;\n",
- zLike
- );
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- /* We want rows of the table to be hashed in PRIMARY KEY order.
- ** Technically, an ORDER BY clause is required to guarantee that
- ** order. However, though not guaranteed by the documentation, every
- ** historical version of SQLite has always output rows in PRIMARY KEY
- ** order when there is no WHERE or GROUP BY clause, so the ORDER BY
- ** can be safely omitted. */
- hash_one_query("SELECT * FROM \"%w\"", sqlite3_column_text(pStmt,0));
- }
- sqlite3_finalize(pStmt);
- }
-
- /* Hash the database schema */
- if( !omitSchema ){
- hash_one_query(
- "SELECT type, name, tbl_name, sql FROM sqlite_master\n"
- " WHERE tbl_name LIKE '%q'\n"
- " ORDER BY name COLLATE nocase;\n",
- zLike
- );
- }
-
- /* Finish and output the hash and close the database connection. */
- hash_finish(zDb);
- sqlite3_close(g.db);
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/extract.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/extract.c
deleted file mode 100644
index 5bf5caa31c9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/extract.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-** Extract a range of bytes from a file.
-**
-** Usage:
-**
-** extract FILENAME OFFSET AMOUNT
-**
-** The bytes are written to standard output.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv){
- FILE *f;
- char *zBuf;
- int ofst;
- int n;
- size_t got;
-
- if( argc!=4 ){
- fprintf(stderr, "Usage: %s FILENAME OFFSET AMOUNT\n", *argv);
- return 1;
- }
- f = fopen(argv[1], "rb");
- if( f==0 ){
- fprintf(stderr, "cannot open \"%s\"\n", argv[1]);
- return 1;
- }
- ofst = atoi(argv[2]);
- n = atoi(argv[3]);
- zBuf = malloc( n );
- if( zBuf==0 ){
- fprintf(stderr, "out of memory\n");
- return 1;
- }
- fseek(f, ofst, SEEK_SET);
- got = fread(zBuf, 1, n, f);
- fclose(f);
- if( got<n ){
- fprintf(stderr, "got only %d of %d bytes\n", got, n);
- return 1;
- }else{
- fwrite(zBuf, 1, n, stdout);
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/fast_vacuum.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/fast_vacuum.c
deleted file mode 100644
index 6a50dcc6805..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/fast_vacuum.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
-** 2013-10-01
-**
-** 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 program implements a high-speed version of the VACUUM command.
-** It repacks an SQLite database to remove as much unused space as
-** possible and to relocate content sequentially in the file.
-**
-** This program runs faster and uses less temporary disk space than the
-** built-in VACUUM command. On the other hand, this program has a number
-** of important restrictions relative to the built-in VACUUM command.
-**
-** (1) The caller must ensure that no other processes are accessing the
-** database file while the vacuum is taking place. The usual SQLite
-** file locking is insufficient for this. The caller must use
-** external means to make sure only this one routine is reading and
-** writing the database.
-**
-** (2) Database reconfiguration such as page size or auto_vacuum changes
-** are not supported by this utility.
-**
-** (3) The database file might be renamed if a power loss or crash
-** occurs at just the wrong moment. Recovery must be prepared to
-** to deal with the possibly changed filename.
-**
-** This program is intended as a *Demonstration Only*. The intent of this
-** program is to provide example code that application developers can use
-** when creating similar functionality in their applications.
-**
-** To compile this program:
-**
-** cc fast_vacuum.c sqlite3.c
-**
-** Add whatever linker options are required. (Example: "-ldl -lpthread").
-** Then to run the program:
-**
-** ./a.out file-to-vacuum
-**
-*/
-#include "sqlite3.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-/*
-** Finalize a prepared statement. If an error has occurred, print the
-** error message and exit.
-*/
-static void vacuumFinalize(sqlite3_stmt *pStmt){
- sqlite3 *db = sqlite3_db_handle(pStmt);
- int rc = sqlite3_finalize(pStmt);
- if( rc ){
- fprintf(stderr, "finalize error: %s\n", sqlite3_errmsg(db));
- exit(1);
- }
-}
-
-/*
-** Execute zSql on database db. The SQL text is printed to standard
-** output. If an error occurs, print an error message and exit the
-** process.
-*/
-static void execSql(sqlite3 *db, const char *zSql){
- sqlite3_stmt *pStmt;
- if( !zSql ){
- fprintf(stderr, "out of memory!\n");
- exit(1);
- }
- printf("%s;\n", zSql);
- if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
- exit(1);
- }
- sqlite3_step(pStmt);
- vacuumFinalize(pStmt);
-}
-
-/*
-** Execute zSql on database db. The zSql statement returns exactly
-** one column. Execute this return value as SQL on the same database.
-**
-** The zSql statement is printed on standard output prior to being
-** run. If any errors occur, an error is printed and the process
-** exits.
-*/
-static void execExecSql(sqlite3 *db, const char *zSql){
- sqlite3_stmt *pStmt;
- int rc;
-
- printf("%s;\n", zSql);
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
- exit(1);
- }
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- execSql(db, (char*)sqlite3_column_text(pStmt, 0));
- }
- vacuumFinalize(pStmt);
-}
-
-
-int main(int argc, char **argv){
- sqlite3 *db; /* Connection to the database file */
- int rc; /* Return code from SQLite interface calls */
- sqlite3_uint64 r; /* A random number */
- const char *zDbToVacuum; /* Database to be vacuumed */
- char *zBackupDb; /* Backup copy of the original database */
- char *zTempDb; /* Temporary database */
- char *zSql; /* An SQL statement */
-
- if( argc!=2 ){
- fprintf(stderr, "Usage: %s DATABASE\n", argv[0]);
- return 1;
- }
-
- /* Identify the database file to be vacuumed and open it.
- */
- zDbToVacuum = argv[1];
- printf("-- open database file \"%s\"\n", zDbToVacuum);
- rc = sqlite3_open(zDbToVacuum, &db);
- if( rc ){
- fprintf(stderr, "%s: %s\n", zDbToVacuum, sqlite3_errstr(rc));
- return 1;
- }
-
- /* Create names for two other files. zTempDb will be a new database
- ** into which we construct a vacuumed copy of zDbToVacuum. zBackupDb
- ** will be a new name for zDbToVacuum after it is vacuumed.
- */
- sqlite3_randomness(sizeof(r), &r);
- zTempDb = sqlite3_mprintf("%s-vacuum-%016llx", zDbToVacuum, r);
- zBackupDb = sqlite3_mprintf("%s-backup-%016llx", zDbToVacuum, r);
-
- /* Attach the zTempDb database to the database connection.
- */
- zSql = sqlite3_mprintf("ATTACH '%q' AS vacuum_db;", zTempDb);
- execSql(db, zSql);
- sqlite3_free(zSql);
-
- /* TODO:
- ** Set the page_size and auto_vacuum mode for zTempDb here, if desired.
- */
-
- /* The vacuum will occur inside of a transaction. Set writable_schema
- ** to ON so that we can directly update the sqlite_master table in the
- ** zTempDb database.
- */
- execSql(db, "PRAGMA writable_schema=ON");
- execSql(db, "BEGIN");
-
-
- /* Query the schema of the main database. Create a mirror schema
- ** in the temporary database.
- */
- execExecSql(db,
- "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
- " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
- " AND rootpage>0"
- );
- execExecSql(db,
- "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
- " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %'"
- );
- execExecSql(db,
- "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
- " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"
- );
-
- /* Loop through the tables in the main database. For each, do
- ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
- ** the contents to the temporary database.
- */
- execExecSql(db,
- "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
- "|| ' SELECT * FROM main.' || quote(name) "
- "FROM main.sqlite_master "
- "WHERE type = 'table' AND name!='sqlite_sequence' "
- " AND rootpage>0"
- );
-
- /* Copy over the sequence table
- */
- execExecSql(db,
- "SELECT 'DELETE FROM vacuum_db.' || quote(name) "
- "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence'"
- );
- execExecSql(db,
- "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
- "|| ' SELECT * FROM main.' || quote(name) "
- "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence'"
- );
-
- /* Copy the triggers, views, and virtual tables from the main database
- ** over to the temporary database. None of these objects has any
- ** associated storage, so all we have to do is copy their entries
- ** from the SQLITE_MASTER table.
- */
- execSql(db,
- "INSERT INTO vacuum_db.sqlite_master "
- " SELECT type, name, tbl_name, rootpage, sql"
- " FROM main.sqlite_master"
- " WHERE type='view' OR type='trigger'"
- " OR (type='table' AND rootpage=0)"
- );
-
- /* Commit the transaction and close the database
- */
- execSql(db, "COMMIT");
- printf("-- close database\n");
- sqlite3_close(db);
-
-
- /* At this point, zDbToVacuum is unchanged. zTempDb contains a
- ** vacuumed copy of zDbToVacuum. Rearrange filenames so that
- ** zTempDb becomes thenew zDbToVacuum.
- */
- printf("-- rename \"%s\" to \"%s\"\n", zDbToVacuum, zBackupDb);
- rename(zDbToVacuum, zBackupDb);
- printf("-- rename \"%s\" to \"%s\"\n", zTempDb, zDbToVacuum);
- rename(zTempDb, zDbToVacuum);
-
- /* Release allocated memory */
- sqlite3_free(zTempDb);
- sqlite3_free(zBackupDb);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/fragck.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/fragck.tcl
deleted file mode 100644
index 35e76f482b6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/fragck.tcl
+++ /dev/null
@@ -1,149 +0,0 @@
-# Run this TCL script using "testfixture" to get a report that shows
-# the sequence of database pages used by a particular table or index.
-# This information is used for fragmentation analysis.
-#
-
-# Get the name of the database to analyze
-#
-
-if {[llength $argv]!=2} {
- puts stderr "Usage: $argv0 database-name table-or-index-name"
- exit 1
-}
-set file_to_analyze [lindex $argv 0]
-if {![file exists $file_to_analyze]} {
- puts stderr "No such file: $file_to_analyze"
- exit 1
-}
-if {![file readable $file_to_analyze]} {
- puts stderr "File is not readable: $file_to_analyze"
- exit 1
-}
-if {[file size $file_to_analyze]<512} {
- puts stderr "Empty or malformed database: $file_to_analyze"
- exit 1
-}
-set objname [lindex $argv 1]
-
-# Open the database
-#
-sqlite3 db [lindex $argv 0]
-set DB [btree_open [lindex $argv 0] 1000 0]
-
-# This proc is a wrapper around the btree_cursor_info command. The
-# second argument is an open btree cursor returned by [btree_cursor].
-# The first argument is the name of an array variable that exists in
-# the scope of the caller. If the third argument is non-zero, then
-# info is returned for the page that lies $up entries upwards in the
-# tree-structure. (i.e. $up==1 returns the parent page, $up==2 the
-# grandparent etc.)
-#
-# The following entries in that array are filled in with information retrieved
-# using [btree_cursor_info]:
-#
-# $arrayvar(page_no) = The page number
-# $arrayvar(entry_no) = The entry number
-# $arrayvar(page_entries) = Total number of entries on this page
-# $arrayvar(cell_size) = Cell size (local payload + header)
-# $arrayvar(page_freebytes) = Number of free bytes on this page
-# $arrayvar(page_freeblocks) = Number of free blocks on the page
-# $arrayvar(payload_bytes) = Total payload size (local + overflow)
-# $arrayvar(header_bytes) = Header size in bytes
-# $arrayvar(local_payload_bytes) = Local payload size
-# $arrayvar(parent) = Parent page number
-#
-proc cursor_info {arrayvar csr {up 0}} {
- upvar $arrayvar a
- foreach [list a(page_no) \
- a(entry_no) \
- a(page_entries) \
- a(cell_size) \
- a(page_freebytes) \
- a(page_freeblocks) \
- a(payload_bytes) \
- a(header_bytes) \
- a(local_payload_bytes) \
- a(parent) \
- a(first_ovfl) ] [btree_cursor_info $csr $up] break
-}
-
-# Determine the page-size of the database. This global variable is used
-# throughout the script.
-#
-set pageSize [db eval {PRAGMA page_size}]
-
-# Find the root page of table or index to be analyzed. Also find out
-# if the object is a table or an index.
-#
-if {$objname=="sqlite_master"} {
- set rootpage 1
- set type table
-} else {
- db eval {
- SELECT rootpage, type FROM sqlite_master
- WHERE name=$objname
- } break
- if {![info exists rootpage]} {
- puts stderr "no such table or index: $objname"
- exit 1
- }
- if {$type!="table" && $type!="index"} {
- puts stderr "$objname is something other than a table or index"
- exit 1
- }
- if {![string is integer -strict $rootpage]} {
- puts stderr "invalid root page for $objname: $rootpage"
- exit 1
- }
-}
-
-# The cursor $csr is pointing to an entry. Print out information
-# about the page that $up levels above that page that contains
-# the entry. If $up==0 use the page that contains the entry.
-#
-# If information about the page has been printed already, then
-# this is a no-op.
-#
-proc page_info {csr up} {
- global seen
- cursor_info ci $csr $up
- set pg $ci(page_no)
- if {[info exists seen($pg)]} return
- set seen($pg) 1
-
- # Do parent pages first
- #
- if {$ci(parent)} {
- page_info $csr [expr {$up+1}]
- }
-
- # Find the depth of this page
- #
- set depth 1
- set i $up
- while {$ci(parent)} {
- incr i
- incr depth
- cursor_info ci $csr $i
- }
-
- # print the results
- #
- puts [format {LEVEL %d: %6d} $depth $pg]
-}
-
-
-
-
-# Loop through the object and print out page numbers
-#
-set csr [btree_cursor $DB $rootpage 0]
-for {btree_first $csr} {![btree_eof $csr]} {btree_next $csr} {
- page_info $csr 0
- set i 1
- foreach pg [btree_ovfl_info $DB $csr] {
- puts [format {OVFL %3d: %6d} $i $pg]
- incr i
- }
-}
-exit 0
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/fuzzershell.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/fuzzershell.c
deleted file mode 100644
index 9a271035971..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/fuzzershell.c
+++ /dev/null
@@ -1,1262 +0,0 @@
-/*
-** 2015-04-17
-**
-** 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 is a utility program designed to aid running the SQLite library
-** against an external fuzzer, such as American Fuzzy Lop (AFL)
-** (http://lcamtuf.coredump.cx/afl/). Basically, this program reads
-** SQL text from standard input and passes it through to SQLite for evaluation,
-** just like the "sqlite3" command-line shell. Differences from the
-** command-line shell:
-**
-** (1) The complex "dot-command" extensions are omitted. This
-** prevents the fuzzer from discovering that it can run things
-** like ".shell rm -rf ~"
-**
-** (2) The database is opened with the SQLITE_OPEN_MEMORY flag so that
-** no disk I/O from the database is permitted. The ATTACH command
-** with a filename still uses an in-memory database.
-**
-** (3) The main in-memory database can be initialized from a template
-** disk database so that the fuzzer starts with a database containing
-** content.
-**
-** (4) The eval() SQL function is added, allowing the fuzzer to do
-** interesting recursive operations.
-**
-** (5) An error is raised if there is a memory leak.
-**
-** The input text can be divided into separate test cases using comments
-** of the form:
-**
-** |****<...>****|
-**
-** where the "..." is arbitrary text. (Except the "|" should really be "/".
-** "|" is used here to avoid compiler errors about nested comments.)
-** A separate in-memory SQLite database is created to run each test case.
-** This feature allows the "queue" of AFL to be captured into a single big
-** file using a command like this:
-**
-** (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
-**
-** (Once again, change the "|" to "/") Then all elements of the AFL queue
-** can be run in a single go (for regression testing, for example) by typing:
-**
-** fuzzershell -f ~/all-queue.txt
-**
-** After running each chunk of SQL, the database connection is closed. The
-** program aborts if the close fails or if there is any unfreed memory after
-** the close.
-**
-** New test cases can be appended to all-queue.txt at any time. If redundant
-** test cases are added, they can be eliminated by running:
-**
-** fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include "sqlite3.h"
-#define ISDIGIT(X) isdigit((unsigned char)(X))
-
-/*
-** All global variables are gathered into the "g" singleton.
-*/
-struct GlobalVars {
- const char *zArgv0; /* Name of program */
- sqlite3_mem_methods sOrigMem; /* Original memory methods */
- sqlite3_mem_methods sOomMem; /* Memory methods with OOM simulator */
- int iOomCntdown; /* Memory fails on 1 to 0 transition */
- int nOomFault; /* Increments for each OOM fault */
- int bOomOnce; /* Fail just once if true */
- int bOomEnable; /* True to enable OOM simulation */
- int nOomBrkpt; /* Number of calls to oomFault() */
- char zTestName[100]; /* Name of current test */
-} g;
-
-/*
-** Maximum number of iterations for an OOM test
-*/
-#ifndef OOM_MAX
-# define OOM_MAX 625
-#endif
-
-/*
-** This routine is called when a simulated OOM occurs. It exists as a
-** convenient place to set a debugger breakpoint.
-*/
-static void oomFault(void){
- g.nOomBrkpt++; /* Prevent oomFault() from being optimized out */
-}
-
-
-/* Versions of malloc() and realloc() that simulate OOM conditions */
-static void *oomMalloc(int nByte){
- if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
- g.iOomCntdown--;
- if( g.iOomCntdown==0 ){
- if( g.nOomFault==0 ) oomFault();
- g.nOomFault++;
- if( !g.bOomOnce ) g.iOomCntdown = 1;
- return 0;
- }
- }
- return g.sOrigMem.xMalloc(nByte);
-}
-static void *oomRealloc(void *pOld, int nByte){
- if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
- g.iOomCntdown--;
- if( g.iOomCntdown==0 ){
- if( g.nOomFault==0 ) oomFault();
- g.nOomFault++;
- if( !g.bOomOnce ) g.iOomCntdown = 1;
- return 0;
- }
- }
- return g.sOrigMem.xRealloc(pOld, nByte);
-}
-
-/*
-** Print an error message and abort in such a way to indicate to the
-** fuzzer that this counts as a crash.
-*/
-static void abendError(const char *zFormat, ...){
- va_list ap;
- if( g.zTestName[0] ){
- fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
- }else{
- fprintf(stderr, "%s: ", g.zArgv0);
- }
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- abort();
-}
-/*
-** Print an error message and quit, but not in a way that would look
-** like a crash.
-*/
-static void fatalError(const char *zFormat, ...){
- va_list ap;
- if( g.zTestName[0] ){
- fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
- }else{
- fprintf(stderr, "%s: ", g.zArgv0);
- }
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-/*
-** Evaluate some SQL. Abort if unable.
-*/
-static void sqlexec(sqlite3 *db, const char *zFormat, ...){
- va_list ap;
- char *zSql;
- char *zErrMsg = 0;
- int rc;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
- if( rc ) abendError("failed sql [%s]: %s", zSql, zErrMsg);
- sqlite3_free(zSql);
-}
-
-/*
-** This callback is invoked by sqlite3_log().
-*/
-static void shellLog(void *pNotUsed, int iErrCode, const char *zMsg){
- printf("LOG: (%d) %s\n", iErrCode, zMsg);
- fflush(stdout);
-}
-static void shellLogNoop(void *pNotUsed, int iErrCode, const char *zMsg){
- return;
-}
-
-/*
-** This callback is invoked by sqlite3_exec() to return query results.
-*/
-static int execCallback(void *NotUsed, int argc, char **argv, char **colv){
- int i;
- static unsigned cnt = 0;
- printf("ROW #%u:\n", ++cnt);
- if( argv ){
- for(i=0; i<argc; i++){
- printf(" %s=", colv[i]);
- if( argv[i] ){
- printf("[%s]\n", argv[i]);
- }else{
- printf("NULL\n");
- }
- }
- }
- fflush(stdout);
- return 0;
-}
-static int execNoop(void *NotUsed, int argc, char **argv, char **colv){
- return 0;
-}
-
-#ifndef SQLITE_OMIT_TRACE
-/*
-** This callback is invoked by sqlite3_trace() as each SQL statement
-** starts.
-*/
-static void traceCallback(void *NotUsed, const char *zMsg){
- printf("TRACE: %s\n", zMsg);
- fflush(stdout);
-}
-static void traceNoop(void *NotUsed, const char *zMsg){
- return;
-}
-#endif
-
-/***************************************************************************
-** String accumulator object
-*/
-typedef struct Str Str;
-struct Str {
- char *z; /* The string. Memory from malloc() */
- sqlite3_uint64 n; /* Bytes of input used */
- sqlite3_uint64 nAlloc; /* Bytes allocated to z[] */
- int oomErr; /* OOM error has been seen */
-};
-
-/* Initialize a Str object */
-static void StrInit(Str *p){
- memset(p, 0, sizeof(*p));
-}
-
-/* Append text to the end of a Str object */
-static void StrAppend(Str *p, const char *z){
- sqlite3_uint64 n = strlen(z);
- if( p->n + n >= p->nAlloc ){
- char *zNew;
- sqlite3_uint64 nNew;
- if( p->oomErr ) return;
- nNew = p->nAlloc*2 + 100 + n;
- zNew = sqlite3_realloc(p->z, (int)nNew);
- if( zNew==0 ){
- sqlite3_free(p->z);
- memset(p, 0, sizeof(*p));
- p->oomErr = 1;
- return;
- }
- p->z = zNew;
- p->nAlloc = nNew;
- }
- memcpy(p->z + p->n, z, (size_t)n);
- p->n += n;
- p->z[p->n] = 0;
-}
-
-/* Return the current string content */
-static char *StrStr(Str *p){
- return p->z;
-}
-
-/* Free the string */
-static void StrFree(Str *p){
- sqlite3_free(p->z);
- StrInit(p);
-}
-
-/***************************************************************************
-** eval() implementation copied from ../ext/misc/eval.c
-*/
-/*
-** Structure used to accumulate the output
-*/
-struct EvalResult {
- char *z; /* Accumulated output */
- const char *zSep; /* Separator */
- int szSep; /* Size of the separator string */
- sqlite3_int64 nAlloc; /* Number of bytes allocated for z[] */
- sqlite3_int64 nUsed; /* Number of bytes of z[] actually used */
-};
-
-/*
-** Callback from sqlite_exec() for the eval() function.
-*/
-static int callback(void *pCtx, int argc, char **argv, char **colnames){
- struct EvalResult *p = (struct EvalResult*)pCtx;
- int i;
- for(i=0; i<argc; i++){
- const char *z = argv[i] ? argv[i] : "";
- size_t sz = strlen(z);
- if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
- char *zNew;
- p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
- /* Using sqlite3_realloc64() would be better, but it is a recent
- ** addition and will cause a segfault if loaded by an older version
- ** of SQLite. */
- zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
- if( zNew==0 ){
- sqlite3_free(p->z);
- memset(p, 0, sizeof(*p));
- return 1;
- }
- p->z = zNew;
- }
- if( p->nUsed>0 ){
- memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
- p->nUsed += p->szSep;
- }
- memcpy(&p->z[p->nUsed], z, sz);
- p->nUsed += sz;
- }
- return 0;
-}
-
-/*
-** Implementation of the eval(X) and eval(X,Y) SQL functions.
-**
-** Evaluate the SQL text in X. Return the results, using string
-** Y as the separator. If Y is omitted, use a single space character.
-*/
-static void sqlEvalFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zSql;
- sqlite3 *db;
- char *zErr = 0;
- int rc;
- struct EvalResult x;
-
- memset(&x, 0, sizeof(x));
- x.zSep = " ";
- zSql = (const char*)sqlite3_value_text(argv[0]);
- if( zSql==0 ) return;
- if( argc>1 ){
- x.zSep = (const char*)sqlite3_value_text(argv[1]);
- if( x.zSep==0 ) return;
- }
- x.szSep = (int)strlen(x.zSep);
- db = sqlite3_context_db_handle(context);
- rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
- if( rc!=SQLITE_OK ){
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- }else if( x.zSep==0 ){
- sqlite3_result_error_nomem(context);
- sqlite3_free(x.z);
- }else{
- sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
- }
-}
-/* End of the eval() implementation
-******************************************************************************/
-
-/******************************************************************************
-** The generate_series(START,END,STEP) eponymous table-valued function.
-**
-** This code is copy/pasted from ext/misc/series.c in the SQLite source tree.
-*/
-/* series_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-typedef struct series_cursor series_cursor;
-struct series_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- int isDesc; /* True to count down rather than up */
- sqlite3_int64 iRowid; /* The rowid */
- sqlite3_int64 iValue; /* Current value ("value") */
- sqlite3_int64 mnValue; /* Mimimum value ("start") */
- sqlite3_int64 mxValue; /* Maximum value ("stop") */
- sqlite3_int64 iStep; /* Increment ("step") */
-};
-
-/*
-** The seriesConnect() method is invoked to create a new
-** series_vtab that describes the generate_series virtual table.
-**
-** Think of this routine as the constructor for series_vtab objects.
-**
-** All this routine needs to do is:
-**
-** (1) Allocate the series_vtab object and initialize all fields.
-**
-** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-** result set of queries against generate_series will look like.
-*/
-static int seriesConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3_vtab *pNew;
- int rc;
-
-/* Column numbers */
-#define SERIES_COLUMN_VALUE 0
-#define SERIES_COLUMN_START 1
-#define SERIES_COLUMN_STOP 2
-#define SERIES_COLUMN_STEP 3
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
- if( rc==SQLITE_OK ){
- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- }
- return rc;
-}
-
-/*
-** This method is the destructor for series_cursor objects.
-*/
-static int seriesDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new series_cursor object.
-*/
-static int seriesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- series_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Destructor for a series_cursor.
-*/
-static int seriesClose(sqlite3_vtab_cursor *cur){
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a series_cursor to its next row of output.
-*/
-static int seriesNext(sqlite3_vtab_cursor *cur){
- series_cursor *pCur = (series_cursor*)cur;
- if( pCur->isDesc ){
- pCur->iValue -= pCur->iStep;
- }else{
- pCur->iValue += pCur->iStep;
- }
- pCur->iRowid++;
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the series_cursor
-** is currently pointing.
-*/
-static int seriesColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- series_cursor *pCur = (series_cursor*)cur;
- sqlite3_int64 x = 0;
- switch( i ){
- case SERIES_COLUMN_START: x = pCur->mnValue; break;
- case SERIES_COLUMN_STOP: x = pCur->mxValue; break;
- case SERIES_COLUMN_STEP: x = pCur->iStep; break;
- default: x = pCur->iValue; break;
- }
- sqlite3_result_int64(ctx, x);
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** rowid is the same as the output value.
-*/
-static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- series_cursor *pCur = (series_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int seriesEof(sqlite3_vtab_cursor *cur){
- series_cursor *pCur = (series_cursor*)cur;
- if( pCur->isDesc ){
- return pCur->iValue < pCur->mnValue;
- }else{
- return pCur->iValue > pCur->mxValue;
- }
-}
-
-/* True to cause run-time checking of the start=, stop=, and/or step=
-** parameters. The only reason to do this is for testing the
-** constraint checking logic for virtual tables in the SQLite core.
-*/
-#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
-# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
-#endif
-
-/*
-** This method is called to "rewind" the series_cursor object back
-** to the first row of output. This method is always called at least
-** once prior to any call to seriesColumn() or seriesRowid() or
-** seriesEof().
-**
-** The query plan selected by seriesBestIndex is passed in the idxNum
-** parameter. (idxStr is not used in this implementation.) idxNum
-** is a bitmask showing which constraints are available:
-**
-** 1: start=VALUE
-** 2: stop=VALUE
-** 4: step=VALUE
-**
-** Also, if bit 8 is set, that means that the series should be output
-** in descending order rather than in ascending order.
-**
-** This routine should initialize the cursor and position it so that it
-** is pointing at the first row, or pointing off the end of the table
-** (so that seriesEof() will return true) if the table is empty.
-*/
-static int seriesFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- series_cursor *pCur = (series_cursor *)pVtabCursor;
- int i = 0;
- if( idxNum & 1 ){
- pCur->mnValue = sqlite3_value_int64(argv[i++]);
- }else{
- pCur->mnValue = 0;
- }
- if( idxNum & 2 ){
- pCur->mxValue = sqlite3_value_int64(argv[i++]);
- }else{
- pCur->mxValue = 0xffffffff;
- }
- if( idxNum & 4 ){
- pCur->iStep = sqlite3_value_int64(argv[i++]);
- if( pCur->iStep<1 ) pCur->iStep = 1;
- }else{
- pCur->iStep = 1;
- }
- if( idxNum & 8 ){
- pCur->isDesc = 1;
- pCur->iValue = pCur->mxValue;
- if( pCur->iStep>0 ){
- pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
- }
- }else{
- pCur->isDesc = 0;
- pCur->iValue = pCur->mnValue;
- }
- pCur->iRowid = 1;
- return SQLITE_OK;
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the generate_series virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** In this implementation idxNum is used to represent the
-** query plan. idxStr is unused.
-**
-** The query plan is represented by bits in idxNum:
-**
-** (1) start = $value -- constraint exists
-** (2) stop = $value -- constraint exists
-** (4) step = $value -- constraint exists
-** (8) output in descending order
-*/
-static int seriesBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i; /* Loop over constraints */
- int idxNum = 0; /* The query plan bitmask */
- int startIdx = -1; /* Index of the start= constraint, or -1 if none */
- int stopIdx = -1; /* Index of the stop= constraint, or -1 if none */
- int stepIdx = -1; /* Index of the step= constraint, or -1 if none */
- int nArg = 0; /* Number of arguments that seriesFilter() expects */
-
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case SERIES_COLUMN_START:
- startIdx = i;
- idxNum |= 1;
- break;
- case SERIES_COLUMN_STOP:
- stopIdx = i;
- idxNum |= 2;
- break;
- case SERIES_COLUMN_STEP:
- stepIdx = i;
- idxNum |= 4;
- break;
- }
- }
- if( startIdx>=0 ){
- pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( stopIdx>=0 ){
- pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( stepIdx>=0 ){
- pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[stepIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( (idxNum & 3)==3 ){
- /* Both start= and stop= boundaries are available. This is the
- ** the preferred case */
- pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
- pIdxInfo->estimatedRows = 1000;
- if( pIdxInfo->nOrderBy==1 ){
- if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
- pIdxInfo->orderByConsumed = 1;
- }
- }else{
- /* If either boundary is missing, we have to generate a huge span
- ** of numbers. Make this case very expensive so that the query
- ** planner will work hard to avoid it. */
- pIdxInfo->estimatedCost = (double)2147483647;
- pIdxInfo->estimatedRows = 2147483647;
- }
- pIdxInfo->idxNum = idxNum;
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** generate_series virtual table.
-*/
-static sqlite3_module seriesModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- seriesConnect, /* xConnect */
- seriesBestIndex, /* xBestIndex */
- seriesDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- seriesOpen, /* xOpen - open a cursor */
- seriesClose, /* xClose - close a cursor */
- seriesFilter, /* xFilter - configure scan constraints */
- seriesNext, /* xNext - advance a cursor */
- seriesEof, /* xEof - check for end of scan */
- seriesColumn, /* xColumn - read data */
- seriesRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-/* END the generate_series(START,END,STEP) implementation
-*********************************************************************************/
-
-/*
-** Print sketchy documentation for this utility program
-*/
-static void showHelp(void){
- printf("Usage: %s [options] ?FILE...?\n", g.zArgv0);
- printf(
-"Read SQL text from FILE... (or from standard input if FILE... is omitted)\n"
-"and then evaluate each block of SQL contained therein.\n"
-"Options:\n"
-" --autovacuum Enable AUTOVACUUM mode\n"
-" --database FILE Use database FILE instead of an in-memory database\n"
-" --disable-lookaside Turn off lookaside memory\n"
-" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
-" --help Show this help text\n"
-" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
-" --oom Run each test multiple times in a simulated OOM loop\n"
-" --pagesize N Set the page size to N\n"
-" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
-" -q Reduced output\n"
-" --quiet Reduced output\n"
-" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
-" --unique-cases FILE Write all unique test cases to FILE\n"
-" --utf16be Set text encoding to UTF-16BE\n"
-" --utf16le Set text encoding to UTF-16LE\n"
-" -v Increased output\n"
-" --verbose Increased output\n"
- );
-}
-
-/*
-** Return the value of a hexadecimal digit. Return -1 if the input
-** is not a hex digit.
-*/
-static int hexDigitValue(char c){
- if( c>='0' && c<='9' ) return c - '0';
- if( c>='a' && c<='f' ) return c - 'a' + 10;
- if( c>='A' && c<='F' ) return c - 'A' + 10;
- return -1;
-}
-
-/*
-** Interpret zArg as an integer value, possibly with suffixes.
-*/
-static int integerValue(const char *zArg){
- sqlite3_int64 v = 0;
- static const struct { char *zSuffix; int iMult; } aMult[] = {
- { "KiB", 1024 },
- { "MiB", 1024*1024 },
- { "GiB", 1024*1024*1024 },
- { "KB", 1000 },
- { "MB", 1000000 },
- { "GB", 1000000000 },
- { "K", 1000 },
- { "M", 1000000 },
- { "G", 1000000000 },
- };
- int i;
- int isNeg = 0;
- if( zArg[0]=='-' ){
- isNeg = 1;
- zArg++;
- }else if( zArg[0]=='+' ){
- zArg++;
- }
- if( zArg[0]=='0' && zArg[1]=='x' ){
- int x;
- zArg += 2;
- while( (x = hexDigitValue(zArg[0]))>=0 ){
- v = (v<<4) + x;
- zArg++;
- }
- }else{
- while( ISDIGIT(zArg[0]) ){
- v = v*10 + zArg[0] - '0';
- zArg++;
- }
- }
- for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
- if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
- v *= aMult[i].iMult;
- break;
- }
- }
- if( v>0x7fffffff ) abendError("parameter too large - max 2147483648");
- return (int)(isNeg? -v : v);
-}
-
-/* Return the current wall-clock time */
-static sqlite3_int64 timeOfDay(void){
- static sqlite3_vfs *clockVfs = 0;
- sqlite3_int64 t;
- if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
- if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
- clockVfs->xCurrentTimeInt64(clockVfs, &t);
- }else{
- double r;
- clockVfs->xCurrentTime(clockVfs, &r);
- t = (sqlite3_int64)(r*86400000.0);
- }
- return t;
-}
-
-int main(int argc, char **argv){
- char *zIn = 0; /* Input text */
- int nAlloc = 0; /* Number of bytes allocated for zIn[] */
- int nIn = 0; /* Number of bytes of zIn[] used */
- size_t got; /* Bytes read from input */
- int rc = SQLITE_OK; /* Result codes from API functions */
- int i; /* Loop counter */
- int iNext; /* Next block of SQL */
- sqlite3 *db; /* Open database */
- char *zErrMsg = 0; /* Error message returned from sqlite3_exec() */
- const char *zEncoding = 0; /* --utf16be or --utf16le */
- int nHeap = 0, mnHeap = 0; /* Heap size from --heap */
- int nLook = 0, szLook = 0; /* --lookaside configuration */
- int nPCache = 0, szPCache = 0;/* --pcache configuration */
- int nScratch = 0, szScratch=0;/* --scratch configuration */
- int pageSize = 0; /* Desired page size. 0 means default */
- void *pHeap = 0; /* Allocated heap space */
- void *pLook = 0; /* Allocated lookaside space */
- void *pPCache = 0; /* Allocated storage for pcache */
- void *pScratch = 0; /* Allocated storage for scratch */
- int doAutovac = 0; /* True for --autovacuum */
- char *zSql; /* SQL to run */
- char *zToFree = 0; /* Call sqlite3_free() on this afte running zSql */
- int verboseFlag = 0; /* --verbose or -v flag */
- int quietFlag = 0; /* --quiet or -q flag */
- int nTest = 0; /* Number of test cases run */
- int multiTest = 0; /* True if there will be multiple test cases */
- int lastPct = -1; /* Previous percentage done output */
- sqlite3 *dataDb = 0; /* Database holding compacted input data */
- sqlite3_stmt *pStmt = 0; /* Statement to insert testcase into dataDb */
- const char *zDataOut = 0; /* Write compacted data to this output file */
- int nHeader = 0; /* Bytes of header comment text on input file */
- int oomFlag = 0; /* --oom */
- int oomCnt = 0; /* Counter for the OOM loop */
- char zErrBuf[200]; /* Space for the error message */
- const char *zFailCode; /* Value of the TEST_FAILURE environment var */
- const char *zPrompt; /* Initial prompt when large-file fuzzing */
- int nInFile = 0; /* Number of input files to read */
- char **azInFile = 0; /* Array of input file names */
- int jj; /* Loop counter for azInFile[] */
- sqlite3_int64 iBegin; /* Start time for the whole program */
- sqlite3_int64 iStart, iEnd; /* Start and end-times for a test case */
- const char *zDbName = 0; /* Name of an on-disk database file to open */
-
- iBegin = timeOfDay();
- sqlite3_shutdown();
- zFailCode = getenv("TEST_FAILURE");
- g.zArgv0 = argv[0];
- zPrompt = "<stdin>";
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]=='-' ){
- z++;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"autovacuum")==0 ){
- doAutovac = 1;
- }else
- if( strcmp(z,"database")==0 ){
- if( i>=argc-1 ) abendError("missing argument on %s\n", argv[i]);
- zDbName = argv[i+1];
- i += 1;
- }else
- if( strcmp(z,"disable-lookaside")==0 ){
- nLook = 1;
- szLook = 0;
- }else
- if( strcmp(z, "f")==0 && i+1<argc ){
- i++;
- goto addNewInFile;
- }else
- if( strcmp(z,"heap")==0 ){
- if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
- nHeap = integerValue(argv[i+1]);
- mnHeap = integerValue(argv[i+2]);
- i += 2;
- }else
- if( strcmp(z,"help")==0 ){
- showHelp();
- return 0;
- }else
- if( strcmp(z,"lookaside")==0 ){
- if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
- nLook = integerValue(argv[i+1]);
- szLook = integerValue(argv[i+2]);
- i += 2;
- }else
- if( strcmp(z,"oom")==0 ){
- oomFlag = 1;
- }else
- if( strcmp(z,"pagesize")==0 ){
- if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
- pageSize = integerValue(argv[++i]);
- }else
- if( strcmp(z,"pcache")==0 ){
- if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
- nPCache = integerValue(argv[i+1]);
- szPCache = integerValue(argv[i+2]);
- i += 2;
- }else
- if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
- quietFlag = 1;
- verboseFlag = 0;
- }else
- if( strcmp(z,"scratch")==0 ){
- if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
- nScratch = integerValue(argv[i+1]);
- szScratch = integerValue(argv[i+2]);
- i += 2;
- }else
- if( strcmp(z, "unique-cases")==0 ){
- if( i>=argc-1 ) abendError("missing arguments on %s", argv[i]);
- if( zDataOut ) abendError("only one --minimize allowed");
- zDataOut = argv[++i];
- }else
- if( strcmp(z,"utf16le")==0 ){
- zEncoding = "utf16le";
- }else
- if( strcmp(z,"utf16be")==0 ){
- zEncoding = "utf16be";
- }else
- if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
- quietFlag = 0;
- verboseFlag = 1;
- }else
- {
- abendError("unknown option: %s", argv[i]);
- }
- }else{
- addNewInFile:
- nInFile++;
- azInFile = realloc(azInFile, sizeof(azInFile[0])*nInFile);
- if( azInFile==0 ) abendError("out of memory");
- azInFile[nInFile-1] = argv[i];
- }
- }
-
- /* Do global SQLite initialization */
- sqlite3_config(SQLITE_CONFIG_LOG, verboseFlag ? shellLog : shellLogNoop, 0);
- if( nHeap>0 ){
- pHeap = malloc( nHeap );
- if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
- rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
- if( rc ) abendError("heap configuration failed: %d\n", rc);
- }
- if( oomFlag ){
- sqlite3_config(SQLITE_CONFIG_GETMALLOC, &g.sOrigMem);
- g.sOomMem = g.sOrigMem;
- g.sOomMem.xMalloc = oomMalloc;
- g.sOomMem.xRealloc = oomRealloc;
- sqlite3_config(SQLITE_CONFIG_MALLOC, &g.sOomMem);
- }
- if( nLook>0 ){
- sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
- if( szLook>0 ){
- pLook = malloc( nLook*szLook );
- if( pLook==0 ) fatalError("out of memory");
- }
- }
- if( nScratch>0 && szScratch>0 ){
- pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
- if( pScratch==0 ) fatalError("cannot allocate %lld-byte scratch",
- nScratch*(sqlite3_int64)szScratch);
- rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
- if( rc ) abendError("scratch configuration failed: %d\n", rc);
- }
- if( nPCache>0 && szPCache>0 ){
- pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
- if( pPCache==0 ) fatalError("cannot allocate %lld-byte pcache",
- nPCache*(sqlite3_int64)szPCache);
- rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
- if( rc ) abendError("pcache configuration failed: %d", rc);
- }
-
- /* If the --unique-cases option was supplied, open the database that will
- ** be used to gather unique test cases.
- */
- if( zDataOut ){
- rc = sqlite3_open(":memory:", &dataDb);
- if( rc ) abendError("cannot open :memory: database");
- rc = sqlite3_exec(dataDb,
- "CREATE TABLE testcase(sql BLOB PRIMARY KEY, tm) WITHOUT ROWID;",0,0,0);
- if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
- rc = sqlite3_prepare_v2(dataDb,
- "INSERT OR IGNORE INTO testcase(sql,tm)VALUES(?1,?2)",
- -1, &pStmt, 0);
- if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
- }
-
- /* Initialize the input buffer used to hold SQL text */
- if( nInFile==0 ) nInFile = 1;
- nAlloc = 1000;
- zIn = malloc(nAlloc);
- if( zIn==0 ) fatalError("out of memory");
-
- /* Loop over all input files */
- for(jj=0; jj<nInFile; jj++){
-
- /* Read the complete content of the next input file into zIn[] */
- FILE *in;
- if( azInFile ){
- int j, k;
- in = fopen(azInFile[jj],"rb");
- if( in==0 ){
- abendError("cannot open %s for reading", azInFile[jj]);
- }
- zPrompt = azInFile[jj];
- for(j=k=0; zPrompt[j]; j++) if( zPrompt[j]=='/' ) k = j+1;
- zPrompt += k;
- }else{
- in = stdin;
- zPrompt = "<stdin>";
- }
- while( !feof(in) ){
- got = fread(zIn+nIn, 1, nAlloc-nIn-1, in);
- nIn += (int)got;
- zIn[nIn] = 0;
- if( got==0 ) break;
- if( nAlloc - nIn - 1 < 100 ){
- nAlloc += nAlloc+1000;
- zIn = realloc(zIn, nAlloc);
- if( zIn==0 ) fatalError("out of memory");
- }
- }
- if( in!=stdin ) fclose(in);
- lastPct = -1;
-
- /* Skip initial lines of the input file that begin with "#" */
- for(i=0; i<nIn; i=iNext+1){
- if( zIn[i]!='#' ) break;
- for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
- }
- nHeader = i;
-
- /* Process all test cases contained within the input file.
- */
- for(; i<nIn; i=iNext, nTest++, g.zTestName[0]=0){
- char cSaved;
- if( strncmp(&zIn[i], "/****<",6)==0 ){
- char *z = strstr(&zIn[i], ">****/");
- if( z ){
- z += 6;
- sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*s",
- (int)(z-&zIn[i]) - 12, &zIn[i+6]);
- if( verboseFlag ){
- printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
- fflush(stdout);
- }
- i += (int)(z-&zIn[i]);
- multiTest = 1;
- }
- }
- for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
- cSaved = zIn[iNext];
- zIn[iNext] = 0;
-
-
- /* Print out the SQL of the next test case is --verbose is enabled
- */
- zSql = &zIn[i];
- if( verboseFlag ){
- printf("INPUT (offset: %d, size: %d): [%s]\n",
- i, (int)strlen(&zIn[i]), &zIn[i]);
- }else if( multiTest && !quietFlag ){
- if( oomFlag ){
- printf("%s\n", g.zTestName);
- }else{
- int pct = (10*iNext)/nIn;
- if( pct!=lastPct ){
- if( lastPct<0 ) printf("%s:", zPrompt);
- printf(" %d%%", pct*10);
- lastPct = pct;
- }
- }
- }else if( nInFile>1 ){
- printf("%s\n", zPrompt);
- }
- fflush(stdout);
-
- /* Run the next test case. Run it multiple times in --oom mode
- */
- if( oomFlag ){
- oomCnt = g.iOomCntdown = 1;
- g.nOomFault = 0;
- g.bOomOnce = 1;
- if( verboseFlag ){
- printf("Once.%d\n", oomCnt);
- fflush(stdout);
- }
- }else{
- oomCnt = 0;
- }
- do{
- Str sql;
- StrInit(&sql);
- if( zDbName ){
- rc = sqlite3_open_v2(zDbName, &db, SQLITE_OPEN_READWRITE, 0);
- if( rc!=SQLITE_OK ){
- abendError("Cannot open database file %s", zDbName);
- }
- }else{
- rc = sqlite3_open_v2(
- "main.db", &db,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
- 0);
- if( rc!=SQLITE_OK ){
- abendError("Unable to open the in-memory database");
- }
- }
- if( pLook ){
- rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook);
- if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
- }
- #ifndef SQLITE_OMIT_TRACE
- sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
- #endif
- sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
- sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
- sqlite3_create_module(db, "generate_series", &seriesModule, 0);
- sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
- if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
- if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
- if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
- iStart = timeOfDay();
-
- /* If using an input database file and that database contains a table
- ** named "autoexec" with a column "sql", then replace the input SQL
- ** with the concatenated text of the autoexec table. In this way,
- ** if the database file is the input being fuzzed, the SQL text is
- ** fuzzed at the same time. */
- if( sqlite3_table_column_metadata(db,0,"autoexec","sql",0,0,0,0,0)==0 ){
- sqlite3_stmt *pStmt2;
- rc = sqlite3_prepare_v2(db,"SELECT sql FROM autoexec",-1,&pStmt2,0);
- if( rc==SQLITE_OK ){
- while( sqlite3_step(pStmt2)==SQLITE_ROW ){
- StrAppend(&sql, (const char*)sqlite3_column_text(pStmt2, 0));
- StrAppend(&sql, "\n");
- }
- }
- sqlite3_finalize(pStmt2);
- zSql = StrStr(&sql);
- }
-
- g.bOomEnable = 1;
- if( verboseFlag ){
- zErrMsg = 0;
- rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
- if( zErrMsg ){
- sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg);
- zErrMsg = 0;
- }
- }else {
- rc = sqlite3_exec(db, zSql, execNoop, 0, 0);
- }
- g.bOomEnable = 0;
- iEnd = timeOfDay();
- StrFree(&sql);
- rc = sqlite3_close(db);
- if( rc ){
- abendError("sqlite3_close() failed with rc=%d", rc);
- }
- if( !zDataOut && sqlite3_memory_used()>0 ){
- abendError("memory in use after close: %lld bytes",sqlite3_memory_used());
- }
- if( oomFlag ){
- /* Limit the number of iterations of the OOM loop to OOM_MAX. If the
- ** first pass (single failure) exceeds 2/3rds of OOM_MAX this skip the
- ** second pass (continuous failure after first) completely. */
- if( g.nOomFault==0 || oomCnt>OOM_MAX ){
- if( g.bOomOnce && oomCnt<=(OOM_MAX*2/3) ){
- oomCnt = g.iOomCntdown = 1;
- g.bOomOnce = 0;
- }else{
- oomCnt = 0;
- }
- }else{
- g.iOomCntdown = ++oomCnt;
- g.nOomFault = 0;
- }
- if( oomCnt ){
- if( verboseFlag ){
- printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt);
- fflush(stdout);
- }
- nTest++;
- }
- }
- }while( oomCnt>0 );
-
- /* Store unique test cases in the in the dataDb database if the
- ** --unique-cases flag is present
- */
- if( zDataOut ){
- sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
- sqlite3_bind_int64(pStmt, 2, iEnd - iStart);
- rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
- sqlite3_reset(pStmt);
- }
-
- /* Free the SQL from the current test case
- */
- if( zToFree ){
- sqlite3_free(zToFree);
- zToFree = 0;
- }
- zIn[iNext] = cSaved;
-
- /* Show test-case results in --verbose mode
- */
- if( verboseFlag ){
- printf("RESULT-CODE: %d\n", rc);
- if( zErrMsg ){
- printf("ERROR-MSG: [%s]\n", zErrBuf);
- }
- fflush(stdout);
- }
-
- /* Simulate an error if the TEST_FAILURE environment variable is "5".
- ** This is used to verify that automated test script really do spot
- ** errors that occur in this test program.
- */
- if( zFailCode ){
- if( zFailCode[0]=='5' && zFailCode[1]==0 ){
- abendError("simulated failure");
- }else if( zFailCode[0]!=0 ){
- /* If TEST_FAILURE is something other than 5, just exit the test
- ** early */
- printf("\nExit early due to TEST_FAILURE being set");
- break;
- }
- }
- }
- if( !verboseFlag && multiTest && !quietFlag && !oomFlag ) printf("\n");
- }
-
- /* Report total number of tests run
- */
- if( nTest>1 && !quietFlag ){
- sqlite3_int64 iElapse = timeOfDay() - iBegin;
- printf("%s: 0 errors out of %d tests in %d.%03d seconds\nSQLite %s %s\n",
- g.zArgv0, nTest, (int)(iElapse/1000), (int)(iElapse%1000),
- sqlite3_libversion(), sqlite3_sourceid());
- }
-
- /* Write the unique test cases if the --unique-cases flag was used
- */
- if( zDataOut ){
- int n = 0;
- FILE *out = fopen(zDataOut, "wb");
- if( out==0 ) abendError("cannot open %s for writing", zDataOut);
- if( nHeader>0 ) fwrite(zIn, nHeader, 1, out);
- sqlite3_finalize(pStmt);
- rc = sqlite3_prepare_v2(dataDb, "SELECT sql, tm FROM testcase ORDER BY tm, sql",
- -1, &pStmt, 0);
- if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- fprintf(out,"/****<%d:%dms>****/", ++n, sqlite3_column_int(pStmt,1));
- fwrite(sqlite3_column_blob(pStmt,0),sqlite3_column_bytes(pStmt,0),1,out);
- }
- fclose(out);
- sqlite3_finalize(pStmt);
- sqlite3_close(dataDb);
- }
-
- /* Clean up and exit.
- */
- free(azInFile);
- free(zIn);
- free(pHeap);
- free(pLook);
- free(pScratch);
- free(pPCache);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/genfkey.README b/chromium/third_party/sqlite/sqlite-src-3240000/tool/genfkey.README
deleted file mode 100644
index 57cdff87f8b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/genfkey.README
+++ /dev/null
@@ -1,137 +0,0 @@
-
-OVERVIEW
-
- The SQLite library is capable of parsing SQL foreign key constraints
- supplied as part of CREATE TABLE statements, but it does not actually
- implement them. However, most of the features of foreign keys may be
- implemented using SQL triggers, which SQLite does support. This text
- file describes a feature of the SQLite shell tool (sqlite3) that
- extracts foreign key definitions from an existing SQLite database and
- creates the set of CREATE TRIGGER statements required to implement
- the foreign key constraints.
-
-CAPABILITIES
-
- An SQL foreign key is a constraint that requires that each row in
- the "child" table corresponds to a row in the "parent" table. For
- example, the following schema:
-
- CREATE TABLE parent(a, b, c, PRIMARY KEY(a, b));
- CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent(a, b));
-
- implies that for each row in table "child", there must be a row in
- "parent" for which the expression (child.d==parent.a AND child.e==parent.b)
- is true. The columns in the parent table are required to be either the
- primary key columns or subject to a UNIQUE constraint. There is no such
- requirement for the columns of the child table.
-
- At this time, all foreign keys are implemented as if they were
- "MATCH NONE", even if the declaration specified "MATCH PARTIAL" or
- "MATCH FULL". "MATCH NONE" means that if any of the key columns in
- the child table are NULL, then there is no requirement for a corresponding
- row in the parent table. So, taking this into account, the expression that
- must be true for every row of the child table in the above example is
- actually:
-
- (child.d IS NULL) OR
- (child.e IS NULL) OR
- (child.d==parent.a AND child.e==parent.b)
-
- Attempting to insert or update a row in the child table so that the
- affected row violates this constraint results in an exception being
- thrown.
-
- The effect of attempting to delete or update a row in the parent table
- so that the constraint becomes untrue for one or more rows in the child
- table depends on the "ON DELETE" or "ON UPDATE" actions specified as
- part of the foreign key definition, respectively. Three different actions
- are supported: "RESTRICT" (the default), "CASCADE" and "SET NULL". SQLite
- will also parse the "SET DEFAULT" action, but this is not implemented
- and "RESTRICT" is used instead.
-
- RESTRICT: Attempting to update or delete a row in the parent table so
- that the constraint becomes untrue for one or more rows in
- the child table is not allowed. An exception is thrown.
-
- CASCADE: Instead of throwing an exception, all corresponding child table
- rows are either deleted (if the parent row is being deleted)
- or updated to match the new parent key values (if the parent
- row is being updated).
-
- SET NULL: Instead of throwing an exception, the foreign key fields of
- all corresponding child table rows are set to NULL.
-
-LIMITATIONS
-
- Apart from those limitiations described above:
-
- * Implicit mapping to composite primary keys is not supported. If
- a parent table has a composite primary key, then any child table
- that refers to it must explicitly map each column. For example, given
- the following definition of table "parent":
-
- CREATE TABLE parent(a, b, c, PRIMARY KEY(a, b));
-
- only the first of the following two definitions of table "child"
- is supported:
-
- CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent(a, b));
- CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent);
-
- An implicit reference to a composite primary key is detected as an
- error when the program is run (see below).
-
- * SQLite does not support recursive triggers, and therefore this program
- does not support recursive CASCADE or SET NULL foreign key
- relationships. If the parent and the child tables of a CASCADE or
- SET NULL foreign key are the same table, the generated triggers will
- malfunction. This is also true if the recursive foreign key constraint
- is indirect (for example if table A references table B which references
- table A with a CASCADE or SET NULL foreign key constraint).
-
- Recursive CASCADE or SET NULL foreign key relationships are *not*
- detected as errors when the program is run. Buyer beware.
-
-USAGE
-
- The functionality is accessed through an sqlite3 shell tool "dot-command":
-
- .genfkey ?--no-drop? ?--ignore-errors? ?--exec?
-
- When this command is run, it first checks the schema of the open SQLite
- database for foreign key related errors or inconsistencies. For example,
- a foreign key that refers to a parent table that does not exist, or
- a foreign key that refers to columns in a parent table that are not
- guaranteed to be unique. If such errors are found and the --ignore-errors
- option was not present, a message for each one is printed to stderr and
- no further processing takes place.
-
- If errors are found and the --ignore-errors option is passed, then
- no error messages are printed. No "CREATE TRIGGER" statements are generated
- for foriegn-key definitions that contained errors, they are silently
- ignored by subsequent processing.
-
- All triggers generated by this command have names that match the pattern
- "genfkey*". Unless the --no-drop option is specified, then the program
- also generates a "DROP TRIGGER" statement for each trigger that exists
- in the database with a name that matches this pattern. This allows the
- program to be used to upgrade a database schema for which foreign key
- triggers have already been installed (i.e. after new tables are created
- or existing tables dropped).
-
- Finally, a series of SQL trigger definitions (CREATE TRIGGER statements)
- that implement the foreign key constraints found in the database schema are
- generated.
-
- If the --exec option was passed, then all generated SQL is immediately
- executed on the database. Otherwise, the generated SQL strings are output
- in the same way as the results of SELECT queries are. Normally, this means
- they will be printed to stdout, but this can be configured using other
- dot-commands (i.e. ".output").
-
- The simplest way to activate the foriegn key definitions in a database
- is simply to open it using the shell tool and enter the command
- ".genfkey --exec":
-
- sqlite> .genfkey --exec
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/genfkey.test b/chromium/third_party/sqlite/sqlite-src-3240000/tool/genfkey.test
deleted file mode 100644
index 3c0073e953d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/genfkey.test
+++ /dev/null
@@ -1,354 +0,0 @@
-
-package require sqlite3
-
-proc do_test {name cmd expected} {
- puts -nonewline "$name ..."
- set res [uplevel $cmd]
- if {$res eq $expected} {
- puts Ok
- } else {
- puts Error
- puts " Got: $res"
- puts " Expected: $expected"
- exit
- }
-}
-
-proc execsql {sql} {
- uplevel [list db eval $sql]
-}
-
-proc catchsql {sql} {
- set rc [catch {uplevel [list db eval $sql]} msg]
- list $rc $msg
-}
-
-file delete -force test.db test.db.journal
-sqlite3 db test.db
-
-# The following tests - genfkey-1.* - test RESTRICT foreign keys.
-#
-do_test genfkey-1.1 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
- CREATE TABLE t2(e REFERENCES t1, f);
- CREATE TABLE t3(g, h, i, FOREIGN KEY (h, i) REFERENCES t1(b, c));
- }
-} {}
-do_test genfkey-1.2 {
- execsql [exec ./sqlite3 test.db .genfkey]
-} {}
-do_test genfkey-1.3 {
- catchsql { INSERT INTO t2 VALUES(1, 2) }
-} {1 {constraint failed}}
-do_test genfkey-1.4 {
- execsql {
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t2 VALUES(1, 2);
- }
-} {}
-do_test genfkey-1.5 {
- execsql { INSERT INTO t2 VALUES(NULL, 3) }
-} {}
-do_test genfkey-1.6 {
- catchsql { UPDATE t2 SET e = 5 WHERE e IS NULL }
-} {1 {constraint failed}}
-do_test genfkey-1.7 {
- execsql { UPDATE t2 SET e = 1 WHERE e IS NULL }
-} {}
-do_test genfkey-1.8 {
- execsql { UPDATE t2 SET e = NULL WHERE f = 3 }
-} {}
-do_test genfkey-1.9 {
- catchsql { UPDATE t1 SET a = 10 }
-} {1 {constraint failed}}
-do_test genfkey-1.9a {
- catchsql { UPDATE t1 SET a = NULL }
-} {1 {datatype mismatch}}
-do_test genfkey-1.10 {
- catchsql { DELETE FROM t1 }
-} {1 {constraint failed}}
-do_test genfkey-1.11 {
- execsql { UPDATE t2 SET e = NULL }
-} {}
-do_test genfkey-1.12 {
- execsql {
- UPDATE t1 SET a = 10 ;
- DELETE FROM t1;
- DELETE FROM t2;
- }
-} {}
-
-do_test genfkey-1.13 {
- execsql {
- INSERT INTO t3 VALUES(1, NULL, NULL);
- INSERT INTO t3 VALUES(1, 2, NULL);
- INSERT INTO t3 VALUES(1, NULL, 3);
- }
-} {}
-do_test genfkey-1.14 {
- catchsql { INSERT INTO t3 VALUES(3, 1, 4) }
-} {1 {constraint failed}}
-do_test genfkey-1.15 {
- execsql {
- INSERT INTO t1 VALUES(1, 1, 4);
- INSERT INTO t3 VALUES(3, 1, 4);
- }
-} {}
-do_test genfkey-1.16 {
- catchsql { DELETE FROM t1 }
-} {1 {constraint failed}}
-do_test genfkey-1.17 {
- catchsql { UPDATE t1 SET b = 10}
-} {1 {constraint failed}}
-do_test genfkey-1.18 {
- execsql { UPDATE t1 SET a = 10}
-} {}
-do_test genfkey-1.19 {
- catchsql { UPDATE t3 SET h = 'hello' WHERE i = 3}
-} {1 {constraint failed}}
-
-do_test genfkey-1.X {
- execsql {
- DROP TABLE t1;
- DROP TABLE t2;
- DROP TABLE t3;
- }
-} {}
-
-# The following tests - genfkey-2.* - test CASCADE foreign keys.
-#
-do_test genfkey-2.1 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
- CREATE TABLE t2(e REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE, f);
- CREATE TABLE t3(g, h, i,
- FOREIGN KEY (h, i)
- REFERENCES t1(b, c) ON UPDATE CASCADE ON DELETE CASCADE
- );
- }
-} {}
-do_test genfkey-2.2 {
- execsql [exec ./sqlite3 test.db .genfkey]
-} {}
-do_test genfkey-2.3 {
- execsql {
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t2 VALUES(1, 'one');
- INSERT INTO t2 VALUES(4, 'four');
- }
-} {}
-do_test genfkey-2.4 {
- execsql {
- UPDATE t1 SET a = 2 WHERE a = 1;
- SELECT * FROM t2;
- }
-} {2 one 4 four}
-do_test genfkey-2.5 {
- execsql {
- DELETE FROM t1 WHERE a = 4;
- SELECT * FROM t2;
- }
-} {2 one}
-do_test genfkey-2.6 {
- execsql {
- INSERT INTO t3 VALUES('hello', 2, 3);
- UPDATE t1 SET c = 2;
- SELECT * FROM t3;
- }
-} {hello 2 2}
-do_test genfkey-2.7 {
- execsql {
- DELETE FROM t1;
- SELECT * FROM t3;
- }
-} {}
-do_test genfkey-2.X {
- execsql {
- DROP TABLE t1;
- DROP TABLE t2;
- DROP TABLE t3;
- }
-} {}
-
-
-# The following tests - genfkey-3.* - test SET NULL foreign keys.
-#
-do_test genfkey-3.1 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(c, b));
- CREATE TABLE t2(e REFERENCES t1 ON UPDATE SET NULL ON DELETE SET NULL, f);
- CREATE TABLE t3(g, h, i,
- FOREIGN KEY (h, i)
- REFERENCES t1(b, c) ON UPDATE SET NULL ON DELETE SET NULL
- );
- }
-} {}
-do_test genfkey-3.2 {
- execsql [exec ./sqlite3 test.db .genfkey]
-} {}
-do_test genfkey-3.3 {
- execsql {
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t2 VALUES(1, 'one');
- INSERT INTO t2 VALUES(4, 'four');
- }
-} {}
-do_test genfkey-3.4 {
- execsql {
- UPDATE t1 SET a = 2 WHERE a = 1;
- SELECT * FROM t2;
- }
-} {{} one 4 four}
-do_test genfkey-3.5 {
- execsql {
- DELETE FROM t1 WHERE a = 4;
- SELECT * FROM t2;
- }
-} {{} one {} four}
-do_test genfkey-3.6 {
- execsql {
- INSERT INTO t3 VALUES('hello', 2, 3);
- UPDATE t1 SET c = 2;
- SELECT * FROM t3;
- }
-} {hello {} {}}
-do_test genfkey-2.7 {
- execsql {
- UPDATE t3 SET h = 2, i = 2;
- DELETE FROM t1;
- SELECT * FROM t3;
- }
-} {hello {} {}}
-do_test genfkey-3.X {
- execsql {
- DROP TABLE t1;
- DROP TABLE t2;
- DROP TABLE t3;
- }
-} {}
-
-# The following tests - genfkey-4.* - test that errors in the schema
-# are detected correctly.
-#
-do_test genfkey-4.1 {
- execsql {
- CREATE TABLE t1(a REFERENCES nosuchtable, b);
- CREATE TABLE t2(a REFERENCES t1, b);
-
- CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
- CREATE TABLE t4(a, b, c, FOREIGN KEY(c, b) REFERENCES t3);
-
- CREATE TABLE t5(a REFERENCES t4(d), b, c);
- CREATE TABLE t6(a REFERENCES t4(a), b, c);
- CREATE TABLE t7(a REFERENCES t3(a), b, c);
- CREATE TABLE t8(a REFERENCES nosuchtable(a), b, c);
- }
-} {}
-
-do_test genfkey-4.X {
- set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
- list $rc $msg
-} "1 {[string trim {
-Error in table t5: foreign key columns do not exist
-Error in table t8: foreign key columns do not exist
-Error in table t4: implicit mapping to composite primary key
-Error in table t1: implicit mapping to non-existant primary key
-Error in table t2: implicit mapping to non-existant primary key
-Error in table t6: foreign key is not unique
-Error in table t7: foreign key is not unique
-}]}"
-
-# Test that ticket #3800 has been resolved.
-#
-do_test genfkey-5.1 {
- execsql {
- DROP TABLE t1; DROP TABLE t2; DROP TABLE t3;
- DROP TABLE t4; DROP TABLE t5; DROP TABLE t6;
- DROP TABLE t7; DROP TABLE t8;
- }
-} {}
-do_test genfkey-5.2 {
- execsql {
- CREATE TABLE "t.3" (c1 PRIMARY KEY);
- CREATE TABLE t13 (c1, foreign key(c1) references "t.3"(c1));
- }
-} {}
-do_test genfkey-5.3 {
- set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
-} {0}
-do_test genfkey-5.4 {
- db eval $msg
-} {}
-do_test genfkey-5.5 {
- catchsql { INSERT INTO t13 VALUES(1) }
-} {1 {constraint failed}}
-do_test genfkey-5.5 {
- catchsql {
- INSERT INTO "t.3" VALUES(1);
- INSERT INTO t13 VALUES(1);
- }
-} {0 {}}
-
-# Test also column names that require quoting.
-do_test genfkey-6.1 {
- execsql {
- DROP TABLE "t.3";
- DROP TABLE t13;
- CREATE TABLE p(
- "a.1 first", "b.2 second",
- UNIQUE("a.1 first", "b.2 second")
- );
- CREATE TABLE c(
- "c.1 I", "d.2 II",
- FOREIGN KEY("c.1 I", "d.2 II")
- REFERENCES p("a.1 first", "b.2 second")
- ON UPDATE CASCADE ON DELETE CASCADE
- );
- }
-} {}
-do_test genfkey-6.2 {
- set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
-} {0}
-do_test genfkey-6.3 {
- execsql $msg
- execsql {
- INSERT INTO p VALUES('A', 'B');
- INSERT INTO p VALUES('C', 'D');
- INSERT INTO c VALUES('A', 'B');
- INSERT INTO c VALUES('C', 'D');
- UPDATE p SET "a.1 first" = 'X' WHERE rowid = 1;
- DELETE FROM p WHERE rowid = 2;
- }
- execsql { SELECT * FROM c }
-} {X B}
-
-do_test genfkey-6.4 {
- execsql {
- DROP TABLE p;
- DROP TABLE c;
- CREATE TABLE parent("a.1", PRIMARY KEY("a.1"));
- CREATE TABLE child("b.2", FOREIGN KEY("b.2") REFERENCES parent("a.1"));
- }
- set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
-} {0}
-do_test genfkey-6.5 {
- execsql $msg
- execsql {
- INSERT INTO parent VALUES(1);
- INSERT INTO child VALUES(1);
- }
- catchsql { UPDATE parent SET "a.1"=0 }
-} {1 {constraint failed}}
-do_test genfkey-6.6 {
- catchsql { UPDATE child SET "b.2"=7 }
-} {1 {constraint failed}}
-do_test genfkey-6.7 {
- execsql {
- SELECT * FROM parent;
- SELECT * FROM child;
- }
-} {1 1}
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/getlock.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/getlock.c
deleted file mode 100644
index 7eff04d7f97..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/getlock.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-** This utility program looks at an SQLite database and determines whether
-** or not it is locked, the kind of lock, and who is holding this lock.
-**
-** This only works on unix when the posix advisory locking method is used
-** (which is the default on unix) and when the PENDING_BYTE is in its
-** usual place.
-*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-static void usage(const char *argv0){
- fprintf(stderr, "Usage: %s database\n", argv0);
- exit(1);
-}
-
-/* Check for a conflicting lock. If one is found, print an this
-** on standard output using the format string given and return 1.
-** If there are no conflicting locks, return 0.
-*/
-static int isLocked(
- int h, /* File descriptor to check */
- int type, /* F_RDLCK or F_WRLCK */
- unsigned int iOfst, /* First byte of the lock */
- unsigned int iCnt, /* Number of bytes in the lock range */
- const char *zType /* Type of lock */
-){
- struct flock lk;
-
- memset(&lk, 0, sizeof(lk));
- lk.l_type = type;
- lk.l_whence = SEEK_SET;
- lk.l_start = iOfst;
- lk.l_len = iCnt;
- if( fcntl(h, F_GETLK, &lk)==(-1) ){
- fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno);
- exit(1);
- }
- if( lk.l_type==F_UNLCK ) return 0;
- printf("%s lock held by %d\n", zType, (int)lk.l_pid);
- return 1;
-}
-
-/*
-** Location of locking bytes in the database file
-*/
-#define PENDING_BYTE (0x40000000)
-#define RESERVED_BYTE (PENDING_BYTE+1)
-#define SHARED_FIRST (PENDING_BYTE+2)
-#define SHARED_SIZE 510
-
-/*
-** Lock locations for shared-memory locks used by WAL mode.
-*/
-#define SHM_BASE 120
-#define SHM_WRITE SHM_BASE
-#define SHM_CHECKPOINT (SHM_BASE+1)
-#define SHM_RECOVER (SHM_BASE+2)
-#define SHM_READ_FIRST (SHM_BASE+3)
-#define SHM_READ_SIZE 5
-
-
-int main(int argc, char **argv){
- int hDb; /* File descriptor for the open database file */
- int hShm; /* File descriptor for WAL shared-memory file */
- char *zShm; /* Name of the shared-memory file for WAL mode */
- ssize_t got; /* Bytes read from header */
- int isWal; /* True if in WAL mode */
- int nName; /* Length of filename */
- unsigned char aHdr[100]; /* Database header */
- int nLock = 0; /* Number of locks held */
- int i; /* Loop counter */
-
- if( argc!=2 ) usage(argv[0]);
- hDb = open(argv[1], O_RDONLY, 0);
- if( hDb<0 ){
- fprintf(stderr, "cannot open %s\n", argv[1]);
- return 1;
- }
-
- /* Make sure we are dealing with an database file */
- got = read(hDb, aHdr, 100);
- if( got!=100 || memcmp(aHdr, "SQLite format 3",16)!=0 ){
- fprintf(stderr, "not an SQLite database: %s\n", argv[1]);
- exit(1);
- }
-
- /* First check for an exclusive lock */
- if( isLocked(hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE") ){
- return 0;
- }
- isWal = aHdr[18]==2;
- if( isWal==0 ){
- /* Rollback mode */
- if( isLocked(hDb, F_RDLCK, PENDING_BYTE, 1, "PENDING") ) return 0;
- if( isLocked(hDb, F_RDLCK, RESERVED_BYTE, 1, "RESERVED") ) return 0;
- if( isLocked(hDb, F_WRLCK, SHARED_FIRST, SHARED_SIZE, "SHARED") ){
- return 0;
- }
- }else{
- /* WAL mode */
- nName = (int)strlen(argv[1]);
- zShm = malloc( nName + 100 );
- if( zShm==0 ){
- fprintf(stderr, "out of memory\n");
- exit(1);
- }
- memcpy(zShm, argv[1], nName);
- memcpy(&zShm[nName], "-shm", 5);
- hShm = open(zShm, O_RDONLY, 0);
- if( hShm<0 ){
- fprintf(stderr, "cannot open %s\n", zShm);
- return 1;
- }
- if( isLocked(hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ){
- return 0;
- }
- nLock += isLocked(hShm, F_RDLCK, SHM_CHECKPOINT, 1, "WAL-CHECKPOINT");
- nLock += isLocked(hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE");
- for(i=0; i<SHM_READ_SIZE; i++){
- nLock += isLocked(hShm, F_WRLCK, SHM_READ_FIRST+i, 1, "WAL-READ");
- }
- }
- if( nLock==0 ){
- printf("file is not locked\n");
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/kvtest-speed.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/kvtest-speed.sh
deleted file mode 100644
index 5f2c8345bee..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/kvtest-speed.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-#
-# A script for running speed tests using kvtest.
-#
-# The test database must be set up first. Recommended
-# command-line:
-#
-# ./kvtest init kvtest.db --count 100K --size 12K --variance 5K
-
-if test "$1" = ""
-then
- echo "Usage: $0 OUTPUTFILE [OPTIONS]"
- exit
-fi
-NAME=$1
-shift
-OPTS="-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DIRECT_OVERFLOW_READ -DUSE_PREAD"
-KVARGS="--count 100K --stats"
-gcc -g -Os -I. $OPTS $* kvtest.c sqlite3.c -o kvtest
-
-# First run using SQL
-rm cachegrind.out.[1-9][0-9]*
-valgrind --tool=cachegrind ./kvtest run kvtest.db $KVARGS 2>&1 | tee summary-kvtest-$NAME.txt
-mv cachegrind.out.[1-9][0-9]* cachegrind.out.sql-$NAME
-cg_anno.tcl cachegrind.out.sql-$NAME >cout-kvtest-sql-$NAME.txt
-
-# Second run using the sqlite3_blob object
-valgrind --tool=cachegrind ./kvtest run kvtest.db $KVARGS --blob-api 2>&1 | tee -a summary-kvtest-$NAME.txt
-mv cachegrind.out.[1-9][0-9]* cachegrind.out.$NAME
-cg_anno.tcl cachegrind.out.$NAME >cout-kvtest-$NAME.txt
-
-# Diff the sqlite3_blob API analysis for non-trunk runs.
-if test "$NAME" != "trunk"; then
- fossil test-diff --tk cout-kvtest-trunk.txt cout-kvtest-$NAME.txt &
-fi
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/lemon.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/lemon.c
deleted file mode 100644
index c2c9554c89e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/lemon.c
+++ /dev/null
@@ -1,5618 +0,0 @@
-/*
-** This file contains all sources (including headers) to the LEMON
-** LALR(1) parser generator. The sources have been combined into a
-** single file to make it easy to include LEMON in the source tree
-** and Makefile of another program.
-**
-** The author of this program disclaims copyright.
-*/
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#define ISSPACE(X) isspace((unsigned char)(X))
-#define ISDIGIT(X) isdigit((unsigned char)(X))
-#define ISALNUM(X) isalnum((unsigned char)(X))
-#define ISALPHA(X) isalpha((unsigned char)(X))
-#define ISUPPER(X) isupper((unsigned char)(X))
-#define ISLOWER(X) islower((unsigned char)(X))
-
-
-#ifndef __WIN32__
-# if defined(_WIN32) || defined(WIN32)
-# define __WIN32__
-# endif
-#endif
-
-#ifdef __WIN32__
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int access(const char *path, int mode);
-#ifdef __cplusplus
-}
-#endif
-#else
-#include <unistd.h>
-#endif
-
-/* #define PRIVATE static */
-#define PRIVATE
-
-#ifdef TEST
-#define MAXRHS 5 /* Set low to exercise exception code */
-#else
-#define MAXRHS 1000
-#endif
-
-static int showPrecedenceConflict = 0;
-static char *msort(char*,char**,int(*)(const char*,const char*));
-
-/*
-** Compilers are getting increasingly pedantic about type conversions
-** as C evolves ever closer to Ada.... To work around the latest problems
-** we have to define the following variant of strlen().
-*/
-#define lemonStrlen(X) ((int)strlen(X))
-
-/*
-** Compilers are starting to complain about the use of sprintf() and strcpy(),
-** saying they are unsafe. So we define our own versions of those routines too.
-**
-** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and
-** lemon_addtext(). The first two are replacements for sprintf() and vsprintf().
-** The third is a helper routine for vsnprintf() that adds texts to the end of a
-** buffer, making sure the buffer is always zero-terminated.
-**
-** The string formatter is a minimal subset of stdlib sprintf() supporting only
-** a few simply conversions:
-**
-** %d
-** %s
-** %.*s
-**
-*/
-static void lemon_addtext(
- char *zBuf, /* The buffer to which text is added */
- int *pnUsed, /* Slots of the buffer used so far */
- const char *zIn, /* Text to add */
- int nIn, /* Bytes of text to add. -1 to use strlen() */
- int iWidth /* Field width. Negative to left justify */
-){
- if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){}
- while( iWidth>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth--; }
- if( nIn==0 ) return;
- memcpy(&zBuf[*pnUsed], zIn, nIn);
- *pnUsed += nIn;
- while( (-iWidth)>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth++; }
- zBuf[*pnUsed] = 0;
-}
-static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){
- int i, j, k, c;
- int nUsed = 0;
- const char *z;
- char zTemp[50];
- str[0] = 0;
- for(i=j=0; (c = zFormat[i])!=0; i++){
- if( c=='%' ){
- int iWidth = 0;
- lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
- c = zFormat[++i];
- if( ISDIGIT(c) || (c=='-' && ISDIGIT(zFormat[i+1])) ){
- if( c=='-' ) i++;
- while( ISDIGIT(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0';
- if( c=='-' ) iWidth = -iWidth;
- c = zFormat[i];
- }
- if( c=='d' ){
- int v = va_arg(ap, int);
- if( v<0 ){
- lemon_addtext(str, &nUsed, "-", 1, iWidth);
- v = -v;
- }else if( v==0 ){
- lemon_addtext(str, &nUsed, "0", 1, iWidth);
- }
- k = 0;
- while( v>0 ){
- k++;
- zTemp[sizeof(zTemp)-k] = (v%10) + '0';
- v /= 10;
- }
- lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k, iWidth);
- }else if( c=='s' ){
- z = va_arg(ap, const char*);
- lemon_addtext(str, &nUsed, z, -1, iWidth);
- }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){
- i += 2;
- k = va_arg(ap, int);
- z = va_arg(ap, const char*);
- lemon_addtext(str, &nUsed, z, k, iWidth);
- }else if( c=='%' ){
- lemon_addtext(str, &nUsed, "%", 1, 0);
- }else{
- fprintf(stderr, "illegal format\n");
- exit(1);
- }
- j = i+1;
- }
- }
- lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
- return nUsed;
-}
-static int lemon_sprintf(char *str, const char *format, ...){
- va_list ap;
- int rc;
- va_start(ap, format);
- rc = lemon_vsprintf(str, format, ap);
- va_end(ap);
- return rc;
-}
-static void lemon_strcpy(char *dest, const char *src){
- while( (*(dest++) = *(src++))!=0 ){}
-}
-static void lemon_strcat(char *dest, const char *src){
- while( *dest ) dest++;
- lemon_strcpy(dest, src);
-}
-
-
-/* a few forward declarations... */
-struct rule;
-struct lemon;
-struct action;
-
-static struct action *Action_new(void);
-static struct action *Action_sort(struct action *);
-
-/********** From the file "build.h" ************************************/
-void FindRulePrecedences(struct lemon*);
-void FindFirstSets(struct lemon*);
-void FindStates(struct lemon*);
-void FindLinks(struct lemon*);
-void FindFollowSets(struct lemon*);
-void FindActions(struct lemon*);
-
-/********* From the file "configlist.h" *********************************/
-void Configlist_init(void);
-struct config *Configlist_add(struct rule *, int);
-struct config *Configlist_addbasis(struct rule *, int);
-void Configlist_closure(struct lemon *);
-void Configlist_sort(void);
-void Configlist_sortbasis(void);
-struct config *Configlist_return(void);
-struct config *Configlist_basis(void);
-void Configlist_eat(struct config *);
-void Configlist_reset(void);
-
-/********* From the file "error.h" ***************************************/
-void ErrorMsg(const char *, int,const char *, ...);
-
-/****** From the file "option.h" ******************************************/
-enum option_type { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
- OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR};
-struct s_options {
- enum option_type type;
- const char *label;
- char *arg;
- const char *message;
-};
-int OptInit(char**,struct s_options*,FILE*);
-int OptNArgs(void);
-char *OptArg(int);
-void OptErr(int);
-void OptPrint(void);
-
-/******** From the file "parse.h" *****************************************/
-void Parse(struct lemon *lemp);
-
-/********* From the file "plink.h" ***************************************/
-struct plink *Plink_new(void);
-void Plink_add(struct plink **, struct config *);
-void Plink_copy(struct plink **, struct plink *);
-void Plink_delete(struct plink *);
-
-/********** From the file "report.h" *************************************/
-void Reprint(struct lemon *);
-void ReportOutput(struct lemon *);
-void ReportTable(struct lemon *, int);
-void ReportHeader(struct lemon *);
-void CompressTables(struct lemon *);
-void ResortStates(struct lemon *);
-
-/********** From the file "set.h" ****************************************/
-void SetSize(int); /* All sets will be of size N */
-char *SetNew(void); /* A new set for element 0..N */
-void SetFree(char*); /* Deallocate a set */
-int SetAdd(char*,int); /* Add element to a set */
-int SetUnion(char *,char *); /* A <- A U B, thru element N */
-#define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
-
-/********** From the file "struct.h" *************************************/
-/*
-** Principal data structures for the LEMON parser generator.
-*/
-
-typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean;
-
-/* Symbols (terminals and nonterminals) of the grammar are stored
-** in the following: */
-enum symbol_type {
- TERMINAL,
- NONTERMINAL,
- MULTITERMINAL
-};
-enum e_assoc {
- LEFT,
- RIGHT,
- NONE,
- UNK
-};
-struct symbol {
- const char *name; /* Name of the symbol */
- int index; /* Index number for this symbol */
- enum symbol_type type; /* Symbols are all either TERMINALS or NTs */
- struct rule *rule; /* Linked list of rules of this (if an NT) */
- struct symbol *fallback; /* fallback token in case this token doesn't parse */
- int prec; /* Precedence if defined (-1 otherwise) */
- enum e_assoc assoc; /* Associativity if precedence is defined */
- char *firstset; /* First-set for all rules of this symbol */
- Boolean lambda; /* True if NT and can generate an empty string */
- int useCnt; /* Number of times used */
- char *destructor; /* Code which executes whenever this symbol is
- ** popped from the stack during error processing */
- int destLineno; /* Line number for start of destructor. Set to
- ** -1 for duplicate destructors. */
- char *datatype; /* The data type of information held by this
- ** object. Only used if type==NONTERMINAL */
- int dtnum; /* The data type number. In the parser, the value
- ** stack is a union. The .yy%d element of this
- ** union is the correct data type for this object */
- int bContent; /* True if this symbol ever carries content - if
- ** it is ever more than just syntax */
- /* The following fields are used by MULTITERMINALs only */
- int nsubsym; /* Number of constituent symbols in the MULTI */
- struct symbol **subsym; /* Array of constituent symbols */
-};
-
-/* Each production rule in the grammar is stored in the following
-** structure. */
-struct rule {
- struct symbol *lhs; /* Left-hand side of the rule */
- const char *lhsalias; /* Alias for the LHS (NULL if none) */
- int lhsStart; /* True if left-hand side is the start symbol */
- int ruleline; /* Line number for the rule */
- int nrhs; /* Number of RHS symbols */
- struct symbol **rhs; /* The RHS symbols */
- const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
- int line; /* Line number at which code begins */
- const char *code; /* The code executed when this rule is reduced */
- const char *codePrefix; /* Setup code before code[] above */
- const char *codeSuffix; /* Breakdown code after code[] above */
- int noCode; /* True if this rule has no associated C code */
- int codeEmitted; /* True if the code has been emitted already */
- struct symbol *precsym; /* Precedence symbol for this rule */
- int index; /* An index number for this rule */
- int iRule; /* Rule number as used in the generated tables */
- Boolean canReduce; /* True if this rule is ever reduced */
- Boolean doesReduce; /* Reduce actions occur after optimization */
- struct rule *nextlhs; /* Next rule with the same LHS */
- struct rule *next; /* Next rule in the global list */
-};
-
-/* A configuration is a production rule of the grammar together with
-** a mark (dot) showing how much of that rule has been processed so far.
-** Configurations also contain a follow-set which is a list of terminal
-** symbols which are allowed to immediately follow the end of the rule.
-** Every configuration is recorded as an instance of the following: */
-enum cfgstatus {
- COMPLETE,
- INCOMPLETE
-};
-struct config {
- struct rule *rp; /* The rule upon which the configuration is based */
- int dot; /* The parse point */
- char *fws; /* Follow-set for this configuration only */
- struct plink *fplp; /* Follow-set forward propagation links */
- struct plink *bplp; /* Follow-set backwards propagation links */
- struct state *stp; /* Pointer to state which contains this */
- enum cfgstatus status; /* used during followset and shift computations */
- struct config *next; /* Next configuration in the state */
- struct config *bp; /* The next basis configuration */
-};
-
-enum e_action {
- SHIFT,
- ACCEPT,
- REDUCE,
- ERROR,
- SSCONFLICT, /* A shift/shift conflict */
- SRCONFLICT, /* Was a reduce, but part of a conflict */
- RRCONFLICT, /* Was a reduce, but part of a conflict */
- SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
- RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
- NOT_USED, /* Deleted by compression */
- SHIFTREDUCE /* Shift first, then reduce */
-};
-
-/* Every shift or reduce operation is stored as one of the following */
-struct action {
- struct symbol *sp; /* The look-ahead symbol */
- enum e_action type;
- union {
- struct state *stp; /* The new state, if a shift */
- struct rule *rp; /* The rule, if a reduce */
- } x;
- struct symbol *spOpt; /* SHIFTREDUCE optimization to this symbol */
- struct action *next; /* Next action for this state */
- struct action *collide; /* Next action with the same hash */
-};
-
-/* Each state of the generated parser's finite state machine
-** is encoded as an instance of the following structure. */
-struct state {
- struct config *bp; /* The basis configurations for this state */
- struct config *cfp; /* All configurations in this set */
- int statenum; /* Sequential number for this state */
- struct action *ap; /* List of actions for this state */
- int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */
- int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */
- int iDfltReduce; /* Default action is to REDUCE by this rule */
- struct rule *pDfltReduce;/* The default REDUCE rule. */
- int autoReduce; /* True if this is an auto-reduce state */
-};
-#define NO_OFFSET (-2147483647)
-
-/* A followset propagation link indicates that the contents of one
-** configuration followset should be propagated to another whenever
-** the first changes. */
-struct plink {
- struct config *cfp; /* The configuration to which linked */
- struct plink *next; /* The next propagate link */
-};
-
-/* The state vector for the entire parser generator is recorded as
-** follows. (LEMON uses no global variables and makes little use of
-** static variables. Fields in the following structure can be thought
-** of as begin global variables in the program.) */
-struct lemon {
- struct state **sorted; /* Table of states sorted by state number */
- struct rule *rule; /* List of all rules */
- struct rule *startRule; /* First rule */
- int nstate; /* Number of states */
- int nxstate; /* nstate with tail degenerate states removed */
- int nrule; /* Number of rules */
- int nsymbol; /* Number of terminal and nonterminal symbols */
- int nterminal; /* Number of terminal symbols */
- int minShiftReduce; /* Minimum shift-reduce action value */
- int errAction; /* Error action value */
- int accAction; /* Accept action value */
- int noAction; /* No-op action value */
- int minReduce; /* Minimum reduce action */
- int maxAction; /* Maximum action value of any kind */
- struct symbol **symbols; /* Sorted array of pointers to symbols */
- int errorcnt; /* Number of errors */
- struct symbol *errsym; /* The error symbol */
- struct symbol *wildcard; /* Token that matches anything */
- char *name; /* Name of the generated parser */
- char *arg; /* Declaration of the 3th argument to parser */
- char *ctx; /* Declaration of 2nd argument to constructor */
- char *tokentype; /* Type of terminal symbols in the parser stack */
- char *vartype; /* The default type of non-terminal symbols */
- char *start; /* Name of the start symbol for the grammar */
- char *stacksize; /* Size of the parser stack */
- char *include; /* Code to put at the start of the C file */
- char *error; /* Code to execute when an error is seen */
- char *overflow; /* Code to execute on a stack overflow */
- char *failure; /* Code to execute on parser failure */
- char *accept; /* Code to execute when the parser excepts */
- char *extracode; /* Code appended to the generated file */
- char *tokendest; /* Code to execute to destroy token data */
- char *vardest; /* Code for the default non-terminal destructor */
- char *filename; /* Name of the input file */
- char *outname; /* Name of the current output file */
- char *tokenprefix; /* A prefix added to token names in the .h file */
- int nconflict; /* Number of parsing conflicts */
- int nactiontab; /* Number of entries in the yy_action[] table */
- int nlookaheadtab; /* Number of entries in yy_lookahead[] */
- int tablesize; /* Total table size of all tables in bytes */
- int basisflag; /* Print only basis configurations */
- int has_fallback; /* True if any %fallback is seen in the grammar */
- int nolinenosflag; /* True if #line statements should not be printed */
- char *argv0; /* Name of the program */
-};
-
-#define MemoryCheck(X) if((X)==0){ \
- extern void memory_error(); \
- memory_error(); \
-}
-
-/**************** From the file "table.h" *********************************/
-/*
-** All code in this file has been automatically generated
-** from a specification in the file
-** "table.q"
-** by the associative array code building program "aagen".
-** Do not edit this file! Instead, edit the specification
-** file, then rerun aagen.
-*/
-/*
-** Code for processing tables in the LEMON parser generator.
-*/
-/* Routines for handling a strings */
-
-const char *Strsafe(const char *);
-
-void Strsafe_init(void);
-int Strsafe_insert(const char *);
-const char *Strsafe_find(const char *);
-
-/* Routines for handling symbols of the grammar */
-
-struct symbol *Symbol_new(const char *);
-int Symbolcmpp(const void *, const void *);
-void Symbol_init(void);
-int Symbol_insert(struct symbol *, const char *);
-struct symbol *Symbol_find(const char *);
-struct symbol *Symbol_Nth(int);
-int Symbol_count(void);
-struct symbol **Symbol_arrayof(void);
-
-/* Routines to manage the state table */
-
-int Configcmp(const char *, const char *);
-struct state *State_new(void);
-void State_init(void);
-int State_insert(struct state *, struct config *);
-struct state *State_find(struct config *);
-struct state **State_arrayof(void);
-
-/* Routines used for efficiency in Configlist_add */
-
-void Configtable_init(void);
-int Configtable_insert(struct config *);
-struct config *Configtable_find(struct config *);
-void Configtable_clear(int(*)(struct config *));
-
-/****************** From the file "action.c" *******************************/
-/*
-** Routines processing parser actions in the LEMON parser generator.
-*/
-
-/* Allocate a new parser action */
-static struct action *Action_new(void){
- static struct action *freelist = 0;
- struct action *newaction;
-
- if( freelist==0 ){
- int i;
- int amt = 100;
- freelist = (struct action *)calloc(amt, sizeof(struct action));
- if( freelist==0 ){
- fprintf(stderr,"Unable to allocate memory for a new parser action.");
- exit(1);
- }
- for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
- freelist[amt-1].next = 0;
- }
- newaction = freelist;
- freelist = freelist->next;
- return newaction;
-}
-
-/* Compare two actions for sorting purposes. Return negative, zero, or
-** positive if the first action is less than, equal to, or greater than
-** the first
-*/
-static int actioncmp(
- struct action *ap1,
- struct action *ap2
-){
- int rc;
- rc = ap1->sp->index - ap2->sp->index;
- if( rc==0 ){
- rc = (int)ap1->type - (int)ap2->type;
- }
- if( rc==0 && (ap1->type==REDUCE || ap1->type==SHIFTREDUCE) ){
- rc = ap1->x.rp->index - ap2->x.rp->index;
- }
- if( rc==0 ){
- rc = (int) (ap2 - ap1);
- }
- return rc;
-}
-
-/* Sort parser actions */
-static struct action *Action_sort(
- struct action *ap
-){
- ap = (struct action *)msort((char *)ap,(char **)&ap->next,
- (int(*)(const char*,const char*))actioncmp);
- return ap;
-}
-
-void Action_add(
- struct action **app,
- enum e_action type,
- struct symbol *sp,
- char *arg
-){
- struct action *newaction;
- newaction = Action_new();
- newaction->next = *app;
- *app = newaction;
- newaction->type = type;
- newaction->sp = sp;
- newaction->spOpt = 0;
- if( type==SHIFT ){
- newaction->x.stp = (struct state *)arg;
- }else{
- newaction->x.rp = (struct rule *)arg;
- }
-}
-/********************** New code to implement the "acttab" module ***********/
-/*
-** This module implements routines use to construct the yy_action[] table.
-*/
-
-/*
-** The state of the yy_action table under construction is an instance of
-** the following structure.
-**
-** The yy_action table maps the pair (state_number, lookahead) into an
-** action_number. The table is an array of integers pairs. The state_number
-** determines an initial offset into the yy_action array. The lookahead
-** value is then added to this initial offset to get an index X into the
-** yy_action array. If the aAction[X].lookahead equals the value of the
-** of the lookahead input, then the value of the action_number output is
-** aAction[X].action. If the lookaheads do not match then the
-** default action for the state_number is returned.
-**
-** All actions associated with a single state_number are first entered
-** into aLookahead[] using multiple calls to acttab_action(). Then the
-** actions for that single state_number are placed into the aAction[]
-** array with a single call to acttab_insert(). The acttab_insert() call
-** also resets the aLookahead[] array in preparation for the next
-** state number.
-*/
-struct lookahead_action {
- int lookahead; /* Value of the lookahead token */
- int action; /* Action to take on the given lookahead */
-};
-typedef struct acttab acttab;
-struct acttab {
- int nAction; /* Number of used slots in aAction[] */
- int nActionAlloc; /* Slots allocated for aAction[] */
- struct lookahead_action
- *aAction, /* The yy_action[] table under construction */
- *aLookahead; /* A single new transaction set */
- int mnLookahead; /* Minimum aLookahead[].lookahead */
- int mnAction; /* Action associated with mnLookahead */
- int mxLookahead; /* Maximum aLookahead[].lookahead */
- int nLookahead; /* Used slots in aLookahead[] */
- int nLookaheadAlloc; /* Slots allocated in aLookahead[] */
- int nterminal; /* Number of terminal symbols */
- int nsymbol; /* total number of symbols */
-};
-
-/* Return the number of entries in the yy_action table */
-#define acttab_lookahead_size(X) ((X)->nAction)
-
-/* The value for the N-th entry in yy_action */
-#define acttab_yyaction(X,N) ((X)->aAction[N].action)
-
-/* The value for the N-th entry in yy_lookahead */
-#define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
-
-/* Free all memory associated with the given acttab */
-void acttab_free(acttab *p){
- free( p->aAction );
- free( p->aLookahead );
- free( p );
-}
-
-/* Allocate a new acttab structure */
-acttab *acttab_alloc(int nsymbol, int nterminal){
- acttab *p = (acttab *) calloc( 1, sizeof(*p) );
- if( p==0 ){
- fprintf(stderr,"Unable to allocate memory for a new acttab.");
- exit(1);
- }
- memset(p, 0, sizeof(*p));
- p->nsymbol = nsymbol;
- p->nterminal = nterminal;
- return p;
-}
-
-/* Add a new action to the current transaction set.
-**
-** This routine is called once for each lookahead for a particular
-** state.
-*/
-void acttab_action(acttab *p, int lookahead, int action){
- if( p->nLookahead>=p->nLookaheadAlloc ){
- p->nLookaheadAlloc += 25;
- p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead,
- sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
- if( p->aLookahead==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- }
- if( p->nLookahead==0 ){
- p->mxLookahead = lookahead;
- p->mnLookahead = lookahead;
- p->mnAction = action;
- }else{
- if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
- if( p->mnLookahead>lookahead ){
- p->mnLookahead = lookahead;
- p->mnAction = action;
- }
- }
- p->aLookahead[p->nLookahead].lookahead = lookahead;
- p->aLookahead[p->nLookahead].action = action;
- p->nLookahead++;
-}
-
-/*
-** Add the transaction set built up with prior calls to acttab_action()
-** into the current action table. Then reset the transaction set back
-** to an empty set in preparation for a new round of acttab_action() calls.
-**
-** Return the offset into the action table of the new transaction.
-**
-** If the makeItSafe parameter is true, then the offset is chosen so that
-** it is impossible to overread the yy_lookaside[] table regardless of
-** the lookaside token. This is done for the terminal symbols, as they
-** come from external inputs and can contain syntax errors. When makeItSafe
-** is false, there is more flexibility in selecting offsets, resulting in
-** a smaller table. For non-terminal symbols, which are never syntax errors,
-** makeItSafe can be false.
-*/
-int acttab_insert(acttab *p, int makeItSafe){
- int i, j, k, n, end;
- assert( p->nLookahead>0 );
-
- /* Make sure we have enough space to hold the expanded action table
- ** in the worst case. The worst case occurs if the transaction set
- ** must be appended to the current action table
- */
- n = p->nsymbol + 1;
- if( p->nAction + n >= p->nActionAlloc ){
- int oldAlloc = p->nActionAlloc;
- p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
- p->aAction = (struct lookahead_action *) realloc( p->aAction,
- sizeof(p->aAction[0])*p->nActionAlloc);
- if( p->aAction==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- for(i=oldAlloc; i<p->nActionAlloc; i++){
- p->aAction[i].lookahead = -1;
- p->aAction[i].action = -1;
- }
- }
-
- /* Scan the existing action table looking for an offset that is a
- ** duplicate of the current transaction set. Fall out of the loop
- ** if and when the duplicate is found.
- **
- ** i is the index in p->aAction[] where p->mnLookahead is inserted.
- */
- end = makeItSafe ? p->mnLookahead : 0;
- for(i=p->nAction-1; i>=end; i--){
- if( p->aAction[i].lookahead==p->mnLookahead ){
- /* All lookaheads and actions in the aLookahead[] transaction
- ** must match against the candidate aAction[i] entry. */
- if( p->aAction[i].action!=p->mnAction ) continue;
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- if( k<0 || k>=p->nAction ) break;
- if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
- if( p->aLookahead[j].action!=p->aAction[k].action ) break;
- }
- if( j<p->nLookahead ) continue;
-
- /* No possible lookahead value that is not in the aLookahead[]
- ** transaction is allowed to match aAction[i] */
- n = 0;
- for(j=0; j<p->nAction; j++){
- if( p->aAction[j].lookahead<0 ) continue;
- if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
- }
- if( n==p->nLookahead ){
- break; /* An exact match is found at offset i */
- }
- }
- }
-
- /* If no existing offsets exactly match the current transaction, find an
- ** an empty offset in the aAction[] table in which we can add the
- ** aLookahead[] transaction.
- */
- if( i<end ){
- /* Look for holes in the aAction[] table that fit the current
- ** aLookahead[] transaction. Leave i set to the offset of the hole.
- ** If no holes are found, i is left at p->nAction, which means the
- ** transaction will be appended. */
- i = makeItSafe ? p->mnLookahead : 0;
- for(; i<p->nActionAlloc - p->mxLookahead; i++){
- if( p->aAction[i].lookahead<0 ){
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- if( k<0 ) break;
- if( p->aAction[k].lookahead>=0 ) break;
- }
- if( j<p->nLookahead ) continue;
- for(j=0; j<p->nAction; j++){
- if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
- }
- if( j==p->nAction ){
- break; /* Fits in empty slots */
- }
- }
- }
- }
- /* Insert transaction set at index i. */
-#if 0
- printf("Acttab:");
- for(j=0; j<p->nLookahead; j++){
- printf(" %d", p->aLookahead[j].lookahead);
- }
- printf(" inserted at %d\n", i);
-#endif
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- p->aAction[k] = p->aLookahead[j];
- if( k>=p->nAction ) p->nAction = k+1;
- }
- if( makeItSafe && i+p->nterminal>=p->nAction ) p->nAction = i+p->nterminal+1;
- p->nLookahead = 0;
-
- /* Return the offset that is added to the lookahead in order to get the
- ** index into yy_action of the action */
- return i - p->mnLookahead;
-}
-
-/*
-** Return the size of the action table without the trailing syntax error
-** entries.
-*/
-int acttab_action_size(acttab *p){
- int n = p->nAction;
- while( n>0 && p->aAction[n-1].lookahead<0 ){ n--; }
- return n;
-}
-
-/********************** From the file "build.c" *****************************/
-/*
-** Routines to construction the finite state machine for the LEMON
-** parser generator.
-*/
-
-/* Find a precedence symbol of every rule in the grammar.
-**
-** Those rules which have a precedence symbol coded in the input
-** grammar using the "[symbol]" construct will already have the
-** rp->precsym field filled. Other rules take as their precedence
-** symbol the first RHS symbol with a defined precedence. If there
-** are not RHS symbols with a defined precedence, the precedence
-** symbol field is left blank.
-*/
-void FindRulePrecedences(struct lemon *xp)
-{
- struct rule *rp;
- for(rp=xp->rule; rp; rp=rp->next){
- if( rp->precsym==0 ){
- int i, j;
- for(i=0; i<rp->nrhs && rp->precsym==0; i++){
- struct symbol *sp = rp->rhs[i];
- if( sp->type==MULTITERMINAL ){
- for(j=0; j<sp->nsubsym; j++){
- if( sp->subsym[j]->prec>=0 ){
- rp->precsym = sp->subsym[j];
- break;
- }
- }
- }else if( sp->prec>=0 ){
- rp->precsym = rp->rhs[i];
- }
- }
- }
- }
- return;
-}
-
-/* Find all nonterminals which will generate the empty string.
-** Then go back and compute the first sets of every nonterminal.
-** The first set is the set of all terminal symbols which can begin
-** a string generated by that nonterminal.
-*/
-void FindFirstSets(struct lemon *lemp)
-{
- int i, j;
- struct rule *rp;
- int progress;
-
- for(i=0; i<lemp->nsymbol; i++){
- lemp->symbols[i]->lambda = LEMON_FALSE;
- }
- for(i=lemp->nterminal; i<lemp->nsymbol; i++){
- lemp->symbols[i]->firstset = SetNew();
- }
-
- /* First compute all lambdas */
- do{
- progress = 0;
- for(rp=lemp->rule; rp; rp=rp->next){
- if( rp->lhs->lambda ) continue;
- for(i=0; i<rp->nrhs; i++){
- struct symbol *sp = rp->rhs[i];
- assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE );
- if( sp->lambda==LEMON_FALSE ) break;
- }
- if( i==rp->nrhs ){
- rp->lhs->lambda = LEMON_TRUE;
- progress = 1;
- }
- }
- }while( progress );
-
- /* Now compute all first sets */
- do{
- struct symbol *s1, *s2;
- progress = 0;
- for(rp=lemp->rule; rp; rp=rp->next){
- s1 = rp->lhs;
- for(i=0; i<rp->nrhs; i++){
- s2 = rp->rhs[i];
- if( s2->type==TERMINAL ){
- progress += SetAdd(s1->firstset,s2->index);
- break;
- }else if( s2->type==MULTITERMINAL ){
- for(j=0; j<s2->nsubsym; j++){
- progress += SetAdd(s1->firstset,s2->subsym[j]->index);
- }
- break;
- }else if( s1==s2 ){
- if( s1->lambda==LEMON_FALSE ) break;
- }else{
- progress += SetUnion(s1->firstset,s2->firstset);
- if( s2->lambda==LEMON_FALSE ) break;
- }
- }
- }
- }while( progress );
- return;
-}
-
-/* Compute all LR(0) states for the grammar. Links
-** are added to between some states so that the LR(1) follow sets
-** can be computed later.
-*/
-PRIVATE struct state *getstate(struct lemon *); /* forward reference */
-void FindStates(struct lemon *lemp)
-{
- struct symbol *sp;
- struct rule *rp;
-
- Configlist_init();
-
- /* Find the start symbol */
- if( lemp->start ){
- sp = Symbol_find(lemp->start);
- if( sp==0 ){
- ErrorMsg(lemp->filename,0,
-"The specified start symbol \"%s\" is not \
-in a nonterminal of the grammar. \"%s\" will be used as the start \
-symbol instead.",lemp->start,lemp->startRule->lhs->name);
- lemp->errorcnt++;
- sp = lemp->startRule->lhs;
- }
- }else{
- sp = lemp->startRule->lhs;
- }
-
- /* Make sure the start symbol doesn't occur on the right-hand side of
- ** any rule. Report an error if it does. (YACC would generate a new
- ** start symbol in this case.) */
- for(rp=lemp->rule; rp; rp=rp->next){
- int i;
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhs[i]==sp ){ /* FIX ME: Deal with multiterminals */
- ErrorMsg(lemp->filename,0,
-"The start symbol \"%s\" occurs on the \
-right-hand side of a rule. This will result in a parser which \
-does not work properly.",sp->name);
- lemp->errorcnt++;
- }
- }
- }
-
- /* The basis configuration set for the first state
- ** is all rules which have the start symbol as their
- ** left-hand side */
- for(rp=sp->rule; rp; rp=rp->nextlhs){
- struct config *newcfp;
- rp->lhsStart = 1;
- newcfp = Configlist_addbasis(rp,0);
- SetAdd(newcfp->fws,0);
- }
-
- /* Compute the first state. All other states will be
- ** computed automatically during the computation of the first one.
- ** The returned pointer to the first state is not used. */
- (void)getstate(lemp);
- return;
-}
-
-/* Return a pointer to a state which is described by the configuration
-** list which has been built from calls to Configlist_add.
-*/
-PRIVATE void buildshifts(struct lemon *, struct state *); /* Forwd ref */
-PRIVATE struct state *getstate(struct lemon *lemp)
-{
- struct config *cfp, *bp;
- struct state *stp;
-
- /* Extract the sorted basis of the new state. The basis was constructed
- ** by prior calls to "Configlist_addbasis()". */
- Configlist_sortbasis();
- bp = Configlist_basis();
-
- /* Get a state with the same basis */
- stp = State_find(bp);
- if( stp ){
- /* A state with the same basis already exists! Copy all the follow-set
- ** propagation links from the state under construction into the
- ** preexisting state, then return a pointer to the preexisting state */
- struct config *x, *y;
- for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
- Plink_copy(&y->bplp,x->bplp);
- Plink_delete(x->fplp);
- x->fplp = x->bplp = 0;
- }
- cfp = Configlist_return();
- Configlist_eat(cfp);
- }else{
- /* This really is a new state. Construct all the details */
- Configlist_closure(lemp); /* Compute the configuration closure */
- Configlist_sort(); /* Sort the configuration closure */
- cfp = Configlist_return(); /* Get a pointer to the config list */
- stp = State_new(); /* A new state structure */
- MemoryCheck(stp);
- stp->bp = bp; /* Remember the configuration basis */
- stp->cfp = cfp; /* Remember the configuration closure */
- stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
- stp->ap = 0; /* No actions, yet. */
- State_insert(stp,stp->bp); /* Add to the state table */
- buildshifts(lemp,stp); /* Recursively compute successor states */
- }
- return stp;
-}
-
-/*
-** Return true if two symbols are the same.
-*/
-int same_symbol(struct symbol *a, struct symbol *b)
-{
- int i;
- if( a==b ) return 1;
- if( a->type!=MULTITERMINAL ) return 0;
- if( b->type!=MULTITERMINAL ) return 0;
- if( a->nsubsym!=b->nsubsym ) return 0;
- for(i=0; i<a->nsubsym; i++){
- if( a->subsym[i]!=b->subsym[i] ) return 0;
- }
- return 1;
-}
-
-/* Construct all successor states to the given state. A "successor"
-** state is any state which can be reached by a shift action.
-*/
-PRIVATE void buildshifts(struct lemon *lemp, struct state *stp)
-{
- struct config *cfp; /* For looping thru the config closure of "stp" */
- struct config *bcfp; /* For the inner loop on config closure of "stp" */
- struct config *newcfg; /* */
- struct symbol *sp; /* Symbol following the dot in configuration "cfp" */
- struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
- struct state *newstp; /* A pointer to a successor state */
-
- /* Each configuration becomes complete after it contibutes to a successor
- ** state. Initially, all configurations are incomplete */
- for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
-
- /* Loop through all configurations of the state "stp" */
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- if( cfp->status==COMPLETE ) continue; /* Already used by inner loop */
- if( cfp->dot>=cfp->rp->nrhs ) continue; /* Can't shift this config */
- Configlist_reset(); /* Reset the new config set */
- sp = cfp->rp->rhs[cfp->dot]; /* Symbol after the dot */
-
- /* For every configuration in the state "stp" which has the symbol "sp"
- ** following its dot, add the same configuration to the basis set under
- ** construction but with the dot shifted one symbol to the right. */
- for(bcfp=cfp; bcfp; bcfp=bcfp->next){
- if( bcfp->status==COMPLETE ) continue; /* Already used */
- if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
- bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
- if( !same_symbol(bsp,sp) ) continue; /* Must be same as for "cfp" */
- bcfp->status = COMPLETE; /* Mark this config as used */
- newcfg = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
- Plink_add(&newcfg->bplp,bcfp);
- }
-
- /* Get a pointer to the state described by the basis configuration set
- ** constructed in the preceding loop */
- newstp = getstate(lemp);
-
- /* The state "newstp" is reached from the state "stp" by a shift action
- ** on the symbol "sp" */
- if( sp->type==MULTITERMINAL ){
- int i;
- for(i=0; i<sp->nsubsym; i++){
- Action_add(&stp->ap,SHIFT,sp->subsym[i],(char*)newstp);
- }
- }else{
- Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
- }
- }
-}
-
-/*
-** Construct the propagation links
-*/
-void FindLinks(struct lemon *lemp)
-{
- int i;
- struct config *cfp, *other;
- struct state *stp;
- struct plink *plp;
-
- /* Housekeeping detail:
- ** Add to every propagate link a pointer back to the state to
- ** which the link is attached. */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- cfp->stp = stp;
- }
- }
-
- /* Convert all backlinks into forward links. Only the forward
- ** links are used in the follow-set computation. */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- for(plp=cfp->bplp; plp; plp=plp->next){
- other = plp->cfp;
- Plink_add(&other->fplp,cfp);
- }
- }
- }
-}
-
-/* Compute all followsets.
-**
-** A followset is the set of all symbols which can come immediately
-** after a configuration.
-*/
-void FindFollowSets(struct lemon *lemp)
-{
- int i;
- struct config *cfp;
- struct plink *plp;
- int progress;
- int change;
-
- for(i=0; i<lemp->nstate; i++){
- for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
- cfp->status = INCOMPLETE;
- }
- }
-
- do{
- progress = 0;
- for(i=0; i<lemp->nstate; i++){
- for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
- if( cfp->status==COMPLETE ) continue;
- for(plp=cfp->fplp; plp; plp=plp->next){
- change = SetUnion(plp->cfp->fws,cfp->fws);
- if( change ){
- plp->cfp->status = INCOMPLETE;
- progress = 1;
- }
- }
- cfp->status = COMPLETE;
- }
- }
- }while( progress );
-}
-
-static int resolve_conflict(struct action *,struct action *);
-
-/* Compute the reduce actions, and resolve conflicts.
-*/
-void FindActions(struct lemon *lemp)
-{
- int i,j;
- struct config *cfp;
- struct state *stp;
- struct symbol *sp;
- struct rule *rp;
-
- /* Add all of the reduce actions
- ** A reduce action is added for each element of the followset of
- ** a configuration which has its dot at the extreme right.
- */
- for(i=0; i<lemp->nstate; i++){ /* Loop over all states */
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */
- if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */
- for(j=0; j<lemp->nterminal; j++){
- if( SetFind(cfp->fws,j) ){
- /* Add a reduce action to the state "stp" which will reduce by the
- ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
- Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
- }
- }
- }
- }
- }
-
- /* Add the accepting token */
- if( lemp->start ){
- sp = Symbol_find(lemp->start);
- if( sp==0 ) sp = lemp->startRule->lhs;
- }else{
- sp = lemp->startRule->lhs;
- }
- /* Add to the first state (which is always the starting state of the
- ** finite state machine) an action to ACCEPT if the lookahead is the
- ** start nonterminal. */
- Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
-
- /* Resolve conflicts */
- for(i=0; i<lemp->nstate; i++){
- struct action *ap, *nap;
- stp = lemp->sorted[i];
- /* assert( stp->ap ); */
- stp->ap = Action_sort(stp->ap);
- for(ap=stp->ap; ap && ap->next; ap=ap->next){
- for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
- /* The two actions "ap" and "nap" have the same lookahead.
- ** Figure out which one should be used */
- lemp->nconflict += resolve_conflict(ap,nap);
- }
- }
- }
-
- /* Report an error for each rule that can never be reduced. */
- for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE;
- for(i=0; i<lemp->nstate; i++){
- struct action *ap;
- for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
- if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE;
- }
- }
- for(rp=lemp->rule; rp; rp=rp->next){
- if( rp->canReduce ) continue;
- ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
- lemp->errorcnt++;
- }
-}
-
-/* Resolve a conflict between the two given actions. If the
-** conflict can't be resolved, return non-zero.
-**
-** NO LONGER TRUE:
-** To resolve a conflict, first look to see if either action
-** is on an error rule. In that case, take the action which
-** is not associated with the error rule. If neither or both
-** actions are associated with an error rule, then try to
-** use precedence to resolve the conflict.
-**
-** If either action is a SHIFT, then it must be apx. This
-** function won't work if apx->type==REDUCE and apy->type==SHIFT.
-*/
-static int resolve_conflict(
- struct action *apx,
- struct action *apy
-){
- struct symbol *spx, *spy;
- int errcnt = 0;
- assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
- if( apx->type==SHIFT && apy->type==SHIFT ){
- apy->type = SSCONFLICT;
- errcnt++;
- }
- if( apx->type==SHIFT && apy->type==REDUCE ){
- spx = apx->sp;
- spy = apy->x.rp->precsym;
- if( spy==0 || spx->prec<0 || spy->prec<0 ){
- /* Not enough precedence information. */
- apy->type = SRCONFLICT;
- errcnt++;
- }else if( spx->prec>spy->prec ){ /* higher precedence wins */
- apy->type = RD_RESOLVED;
- }else if( spx->prec<spy->prec ){
- apx->type = SH_RESOLVED;
- }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
- apy->type = RD_RESOLVED; /* associativity */
- }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */
- apx->type = SH_RESOLVED;
- }else{
- assert( spx->prec==spy->prec && spx->assoc==NONE );
- apx->type = ERROR;
- }
- }else if( apx->type==REDUCE && apy->type==REDUCE ){
- spx = apx->x.rp->precsym;
- spy = apy->x.rp->precsym;
- if( spx==0 || spy==0 || spx->prec<0 ||
- spy->prec<0 || spx->prec==spy->prec ){
- apy->type = RRCONFLICT;
- errcnt++;
- }else if( spx->prec>spy->prec ){
- apy->type = RD_RESOLVED;
- }else if( spx->prec<spy->prec ){
- apx->type = RD_RESOLVED;
- }
- }else{
- assert(
- apx->type==SH_RESOLVED ||
- apx->type==RD_RESOLVED ||
- apx->type==SSCONFLICT ||
- apx->type==SRCONFLICT ||
- apx->type==RRCONFLICT ||
- apy->type==SH_RESOLVED ||
- apy->type==RD_RESOLVED ||
- apy->type==SSCONFLICT ||
- apy->type==SRCONFLICT ||
- apy->type==RRCONFLICT
- );
- /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
- ** REDUCEs on the list. If we reach this point it must be because
- ** the parser conflict had already been resolved. */
- }
- return errcnt;
-}
-/********************* From the file "configlist.c" *************************/
-/*
-** Routines to processing a configuration list and building a state
-** in the LEMON parser generator.
-*/
-
-static struct config *freelist = 0; /* List of free configurations */
-static struct config *current = 0; /* Top of list of configurations */
-static struct config **currentend = 0; /* Last on list of configs */
-static struct config *basis = 0; /* Top of list of basis configs */
-static struct config **basisend = 0; /* End of list of basis configs */
-
-/* Return a pointer to a new configuration */
-PRIVATE struct config *newconfig(void){
- struct config *newcfg;
- if( freelist==0 ){
- int i;
- int amt = 3;
- freelist = (struct config *)calloc( amt, sizeof(struct config) );
- if( freelist==0 ){
- fprintf(stderr,"Unable to allocate memory for a new configuration.");
- exit(1);
- }
- for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
- freelist[amt-1].next = 0;
- }
- newcfg = freelist;
- freelist = freelist->next;
- return newcfg;
-}
-
-/* The configuration "old" is no longer used */
-PRIVATE void deleteconfig(struct config *old)
-{
- old->next = freelist;
- freelist = old;
-}
-
-/* Initialized the configuration list builder */
-void Configlist_init(void){
- current = 0;
- currentend = &current;
- basis = 0;
- basisend = &basis;
- Configtable_init();
- return;
-}
-
-/* Initialized the configuration list builder */
-void Configlist_reset(void){
- current = 0;
- currentend = &current;
- basis = 0;
- basisend = &basis;
- Configtable_clear(0);
- return;
-}
-
-/* Add another configuration to the configuration list */
-struct config *Configlist_add(
- struct rule *rp, /* The rule */
- int dot /* Index into the RHS of the rule where the dot goes */
-){
- struct config *cfp, model;
-
- assert( currentend!=0 );
- model.rp = rp;
- model.dot = dot;
- cfp = Configtable_find(&model);
- if( cfp==0 ){
- cfp = newconfig();
- cfp->rp = rp;
- cfp->dot = dot;
- cfp->fws = SetNew();
- cfp->stp = 0;
- cfp->fplp = cfp->bplp = 0;
- cfp->next = 0;
- cfp->bp = 0;
- *currentend = cfp;
- currentend = &cfp->next;
- Configtable_insert(cfp);
- }
- return cfp;
-}
-
-/* Add a basis configuration to the configuration list */
-struct config *Configlist_addbasis(struct rule *rp, int dot)
-{
- struct config *cfp, model;
-
- assert( basisend!=0 );
- assert( currentend!=0 );
- model.rp = rp;
- model.dot = dot;
- cfp = Configtable_find(&model);
- if( cfp==0 ){
- cfp = newconfig();
- cfp->rp = rp;
- cfp->dot = dot;
- cfp->fws = SetNew();
- cfp->stp = 0;
- cfp->fplp = cfp->bplp = 0;
- cfp->next = 0;
- cfp->bp = 0;
- *currentend = cfp;
- currentend = &cfp->next;
- *basisend = cfp;
- basisend = &cfp->bp;
- Configtable_insert(cfp);
- }
- return cfp;
-}
-
-/* Compute the closure of the configuration list */
-void Configlist_closure(struct lemon *lemp)
-{
- struct config *cfp, *newcfp;
- struct rule *rp, *newrp;
- struct symbol *sp, *xsp;
- int i, dot;
-
- assert( currentend!=0 );
- for(cfp=current; cfp; cfp=cfp->next){
- rp = cfp->rp;
- dot = cfp->dot;
- if( dot>=rp->nrhs ) continue;
- sp = rp->rhs[dot];
- if( sp->type==NONTERMINAL ){
- if( sp->rule==0 && sp!=lemp->errsym ){
- ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
- sp->name);
- lemp->errorcnt++;
- }
- for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
- newcfp = Configlist_add(newrp,0);
- for(i=dot+1; i<rp->nrhs; i++){
- xsp = rp->rhs[i];
- if( xsp->type==TERMINAL ){
- SetAdd(newcfp->fws,xsp->index);
- break;
- }else if( xsp->type==MULTITERMINAL ){
- int k;
- for(k=0; k<xsp->nsubsym; k++){
- SetAdd(newcfp->fws, xsp->subsym[k]->index);
- }
- break;
- }else{
- SetUnion(newcfp->fws,xsp->firstset);
- if( xsp->lambda==LEMON_FALSE ) break;
- }
- }
- if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
- }
- }
- }
- return;
-}
-
-/* Sort the configuration list */
-void Configlist_sort(void){
- current = (struct config*)msort((char*)current,(char**)&(current->next),
- Configcmp);
- currentend = 0;
- return;
-}
-
-/* Sort the basis configuration list */
-void Configlist_sortbasis(void){
- basis = (struct config*)msort((char*)current,(char**)&(current->bp),
- Configcmp);
- basisend = 0;
- return;
-}
-
-/* Return a pointer to the head of the configuration list and
-** reset the list */
-struct config *Configlist_return(void){
- struct config *old;
- old = current;
- current = 0;
- currentend = 0;
- return old;
-}
-
-/* Return a pointer to the head of the configuration list and
-** reset the list */
-struct config *Configlist_basis(void){
- struct config *old;
- old = basis;
- basis = 0;
- basisend = 0;
- return old;
-}
-
-/* Free all elements of the given configuration list */
-void Configlist_eat(struct config *cfp)
-{
- struct config *nextcfp;
- for(; cfp; cfp=nextcfp){
- nextcfp = cfp->next;
- assert( cfp->fplp==0 );
- assert( cfp->bplp==0 );
- if( cfp->fws ) SetFree(cfp->fws);
- deleteconfig(cfp);
- }
- return;
-}
-/***************** From the file "error.c" *********************************/
-/*
-** Code for printing error message.
-*/
-
-void ErrorMsg(const char *filename, int lineno, const char *format, ...){
- va_list ap;
- fprintf(stderr, "%s:%d: ", filename, lineno);
- va_start(ap, format);
- vfprintf(stderr,format,ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-/**************** From the file "main.c" ************************************/
-/*
-** Main program file for the LEMON parser generator.
-*/
-
-/* Report an out-of-memory condition and abort. This function
-** is used mostly by the "MemoryCheck" macro in struct.h
-*/
-void memory_error(void){
- fprintf(stderr,"Out of memory. Aborting...\n");
- exit(1);
-}
-
-static int nDefine = 0; /* Number of -D options on the command line */
-static char **azDefine = 0; /* Name of the -D macros */
-
-/* This routine is called with the argument to each -D command-line option.
-** Add the macro defined to the azDefine array.
-*/
-static void handle_D_option(char *z){
- char **paz;
- nDefine++;
- azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine);
- if( azDefine==0 ){
- fprintf(stderr,"out of memory\n");
- exit(1);
- }
- paz = &azDefine[nDefine-1];
- *paz = (char *) malloc( lemonStrlen(z)+1 );
- if( *paz==0 ){
- fprintf(stderr,"out of memory\n");
- exit(1);
- }
- lemon_strcpy(*paz, z);
- for(z=*paz; *z && *z!='='; z++){}
- *z = 0;
-}
-
-/* Rember the name of the output directory
-*/
-static char *outputDir = NULL;
-static void handle_d_option(char *z){
- outputDir = (char *) malloc( lemonStrlen(z)+1 );
- if( outputDir==0 ){
- fprintf(stderr,"out of memory\n");
- exit(1);
- }
- lemon_strcpy(outputDir, z);
-}
-
-static char *user_templatename = NULL;
-static void handle_T_option(char *z){
- user_templatename = (char *) malloc( lemonStrlen(z)+1 );
- if( user_templatename==0 ){
- memory_error();
- }
- lemon_strcpy(user_templatename, z);
-}
-
-/* Merge together to lists of rules ordered by rule.iRule */
-static struct rule *Rule_merge(struct rule *pA, struct rule *pB){
- struct rule *pFirst = 0;
- struct rule **ppPrev = &pFirst;
- while( pA && pB ){
- if( pA->iRule<pB->iRule ){
- *ppPrev = pA;
- ppPrev = &pA->next;
- pA = pA->next;
- }else{
- *ppPrev = pB;
- ppPrev = &pB->next;
- pB = pB->next;
- }
- }
- if( pA ){
- *ppPrev = pA;
- }else{
- *ppPrev = pB;
- }
- return pFirst;
-}
-
-/*
-** Sort a list of rules in order of increasing iRule value
-*/
-static struct rule *Rule_sort(struct rule *rp){
- int i;
- struct rule *pNext;
- struct rule *x[32];
- memset(x, 0, sizeof(x));
- while( rp ){
- pNext = rp->next;
- rp->next = 0;
- for(i=0; i<sizeof(x)/sizeof(x[0]) && x[i]; i++){
- rp = Rule_merge(x[i], rp);
- x[i] = 0;
- }
- x[i] = rp;
- rp = pNext;
- }
- rp = 0;
- for(i=0; i<sizeof(x)/sizeof(x[0]); i++){
- rp = Rule_merge(x[i], rp);
- }
- return rp;
-}
-
-/* forward reference */
-static const char *minimum_size_type(int lwr, int upr, int *pnByte);
-
-/* Print a single line of the "Parser Stats" output
-*/
-static void stats_line(const char *zLabel, int iValue){
- int nLabel = lemonStrlen(zLabel);
- printf(" %s%.*s %5d\n", zLabel,
- 35-nLabel, "................................",
- iValue);
-}
-
-/* The main program. Parse the command line and do it... */
-int main(int argc, char **argv)
-{
- static int version = 0;
- static int rpflag = 0;
- static int basisflag = 0;
- static int compress = 0;
- static int quiet = 0;
- static int statistics = 0;
- static int mhflag = 0;
- static int nolinenosflag = 0;
- static int noResort = 0;
-
- static struct s_options options[] = {
- {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
- {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
- {OPT_FSTR, "d", (char*)&handle_d_option, "Output directory. Default '.'"},
- {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
- {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"},
- {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
- {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"},
- {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."},
- {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."},
- {OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)"},
- {OPT_FLAG, "p", (char*)&showPrecedenceConflict,
- "Show conflicts resolved by precedence rules"},
- {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
- {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
- {OPT_FLAG, "s", (char*)&statistics,
- "Print parser stats to standard output."},
- {OPT_FLAG, "x", (char*)&version, "Print the version number."},
- {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
- {OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"},
- {OPT_FLAG,0,0,0}
- };
- int i;
- int exitcode;
- struct lemon lem;
- struct rule *rp;
-
- OptInit(argv,options,stderr);
- if( version ){
- printf("Lemon version 1.0\n");
- exit(0);
- }
- if( OptNArgs()!=1 ){
- fprintf(stderr,"Exactly one filename argument is required.\n");
- exit(1);
- }
- memset(&lem, 0, sizeof(lem));
- lem.errorcnt = 0;
-
- /* Initialize the machine */
- Strsafe_init();
- Symbol_init();
- State_init();
- lem.argv0 = argv[0];
- lem.filename = OptArg(0);
- lem.basisflag = basisflag;
- lem.nolinenosflag = nolinenosflag;
- Symbol_new("$");
-
- /* Parse the input file */
- Parse(&lem);
- if( lem.errorcnt ) exit(lem.errorcnt);
- if( lem.nrule==0 ){
- fprintf(stderr,"Empty grammar.\n");
- exit(1);
- }
- lem.errsym = Symbol_find("error");
-
- /* Count and index the symbols of the grammar */
- Symbol_new("{default}");
- lem.nsymbol = Symbol_count();
- lem.symbols = Symbol_arrayof();
- for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
- qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp);
- for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
- while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; }
- assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 );
- lem.nsymbol = i - 1;
- for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++);
- lem.nterminal = i;
-
- /* Assign sequential rule numbers. Start with 0. Put rules that have no
- ** reduce action C-code associated with them last, so that the switch()
- ** statement that selects reduction actions will have a smaller jump table.
- */
- for(i=0, rp=lem.rule; rp; rp=rp->next){
- rp->iRule = rp->code ? i++ : -1;
- }
- for(rp=lem.rule; rp; rp=rp->next){
- if( rp->iRule<0 ) rp->iRule = i++;
- }
- lem.startRule = lem.rule;
- lem.rule = Rule_sort(lem.rule);
-
- /* Generate a reprint of the grammar, if requested on the command line */
- if( rpflag ){
- Reprint(&lem);
- }else{
- /* Initialize the size for all follow and first sets */
- SetSize(lem.nterminal+1);
-
- /* Find the precedence for every production rule (that has one) */
- FindRulePrecedences(&lem);
-
- /* Compute the lambda-nonterminals and the first-sets for every
- ** nonterminal */
- FindFirstSets(&lem);
-
- /* Compute all LR(0) states. Also record follow-set propagation
- ** links so that the follow-set can be computed later */
- lem.nstate = 0;
- FindStates(&lem);
- lem.sorted = State_arrayof();
-
- /* Tie up loose ends on the propagation links */
- FindLinks(&lem);
-
- /* Compute the follow set of every reducible configuration */
- FindFollowSets(&lem);
-
- /* Compute the action tables */
- FindActions(&lem);
-
- /* Compress the action tables */
- if( compress==0 ) CompressTables(&lem);
-
- /* Reorder and renumber the states so that states with fewer choices
- ** occur at the end. This is an optimization that helps make the
- ** generated parser tables smaller. */
- if( noResort==0 ) ResortStates(&lem);
-
- /* Generate a report of the parser generated. (the "y.output" file) */
- if( !quiet ) ReportOutput(&lem);
-
- /* Generate the source code for the parser */
- ReportTable(&lem, mhflag);
-
- /* Produce a header file for use by the scanner. (This step is
- ** omitted if the "-m" option is used because makeheaders will
- ** generate the file for us.) */
- if( !mhflag ) ReportHeader(&lem);
- }
- if( statistics ){
- printf("Parser statistics:\n");
- stats_line("terminal symbols", lem.nterminal);
- stats_line("non-terminal symbols", lem.nsymbol - lem.nterminal);
- stats_line("total symbols", lem.nsymbol);
- stats_line("rules", lem.nrule);
- stats_line("states", lem.nxstate);
- stats_line("conflicts", lem.nconflict);
- stats_line("action table entries", lem.nactiontab);
- stats_line("lookahead table entries", lem.nlookaheadtab);
- stats_line("total table size (bytes)", lem.tablesize);
- }
- if( lem.nconflict > 0 ){
- fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
- }
-
- /* return 0 on success, 1 on failure. */
- exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
- exit(exitcode);
- return (exitcode);
-}
-/******************** From the file "msort.c" *******************************/
-/*
-** A generic merge-sort program.
-**
-** USAGE:
-** Let "ptr" be a pointer to some structure which is at the head of
-** a null-terminated list. Then to sort the list call:
-**
-** ptr = msort(ptr,&(ptr->next),cmpfnc);
-**
-** In the above, "cmpfnc" is a pointer to a function which compares
-** two instances of the structure and returns an integer, as in
-** strcmp. The second argument is a pointer to the pointer to the
-** second element of the linked list. This address is used to compute
-** the offset to the "next" field within the structure. The offset to
-** the "next" field must be constant for all structures in the list.
-**
-** The function returns a new pointer which is the head of the list
-** after sorting.
-**
-** ALGORITHM:
-** Merge-sort.
-*/
-
-/*
-** Return a pointer to the next structure in the linked list.
-*/
-#define NEXT(A) (*(char**)(((char*)A)+offset))
-
-/*
-** Inputs:
-** a: A sorted, null-terminated linked list. (May be null).
-** b: A sorted, null-terminated linked list. (May be null).
-** cmp: A pointer to the comparison function.
-** offset: Offset in the structure to the "next" field.
-**
-** Return Value:
-** A pointer to the head of a sorted list containing the elements
-** of both a and b.
-**
-** Side effects:
-** The "next" pointers for elements in the lists a and b are
-** changed.
-*/
-static char *merge(
- char *a,
- char *b,
- int (*cmp)(const char*,const char*),
- int offset
-){
- char *ptr, *head;
-
- if( a==0 ){
- head = b;
- }else if( b==0 ){
- head = a;
- }else{
- if( (*cmp)(a,b)<=0 ){
- ptr = a;
- a = NEXT(a);
- }else{
- ptr = b;
- b = NEXT(b);
- }
- head = ptr;
- while( a && b ){
- if( (*cmp)(a,b)<=0 ){
- NEXT(ptr) = a;
- ptr = a;
- a = NEXT(a);
- }else{
- NEXT(ptr) = b;
- ptr = b;
- b = NEXT(b);
- }
- }
- if( a ) NEXT(ptr) = a;
- else NEXT(ptr) = b;
- }
- return head;
-}
-
-/*
-** Inputs:
-** list: Pointer to a singly-linked list of structures.
-** next: Pointer to pointer to the second element of the list.
-** cmp: A comparison function.
-**
-** Return Value:
-** A pointer to the head of a sorted list containing the elements
-** orginally in list.
-**
-** Side effects:
-** The "next" pointers for elements in list are changed.
-*/
-#define LISTSIZE 30
-static char *msort(
- char *list,
- char **next,
- int (*cmp)(const char*,const char*)
-){
- unsigned long offset;
- char *ep;
- char *set[LISTSIZE];
- int i;
- offset = (unsigned long)((char*)next - (char*)list);
- for(i=0; i<LISTSIZE; i++) set[i] = 0;
- while( list ){
- ep = list;
- list = NEXT(list);
- NEXT(ep) = 0;
- for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
- ep = merge(ep,set[i],cmp,offset);
- set[i] = 0;
- }
- set[i] = ep;
- }
- ep = 0;
- for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset);
- return ep;
-}
-/************************ From the file "option.c" **************************/
-static char **argv;
-static struct s_options *op;
-static FILE *errstream;
-
-#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
-
-/*
-** Print the command line with a carrot pointing to the k-th character
-** of the n-th field.
-*/
-static void errline(int n, int k, FILE *err)
-{
- int spcnt, i;
- if( argv[0] ) fprintf(err,"%s",argv[0]);
- spcnt = lemonStrlen(argv[0]) + 1;
- for(i=1; i<n && argv[i]; i++){
- fprintf(err," %s",argv[i]);
- spcnt += lemonStrlen(argv[i])+1;
- }
- spcnt += k;
- for(; argv[i]; i++) fprintf(err," %s",argv[i]);
- if( spcnt<20 ){
- fprintf(err,"\n%*s^-- here\n",spcnt,"");
- }else{
- fprintf(err,"\n%*shere --^\n",spcnt-7,"");
- }
-}
-
-/*
-** Return the index of the N-th non-switch argument. Return -1
-** if N is out of range.
-*/
-static int argindex(int n)
-{
- int i;
- int dashdash = 0;
- if( argv!=0 && *argv!=0 ){
- for(i=1; argv[i]; i++){
- if( dashdash || !ISOPT(argv[i]) ){
- if( n==0 ) return i;
- n--;
- }
- if( strcmp(argv[i],"--")==0 ) dashdash = 1;
- }
- }
- return -1;
-}
-
-static char emsg[] = "Command line syntax error: ";
-
-/*
-** Process a flag command line argument.
-*/
-static int handleflags(int i, FILE *err)
-{
- int v;
- int errcnt = 0;
- int j;
- for(j=0; op[j].label; j++){
- if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
- }
- v = argv[i][0]=='-' ? 1 : 0;
- if( op[j].label==0 ){
- if( err ){
- fprintf(err,"%sundefined option.\n",emsg);
- errline(i,1,err);
- }
- errcnt++;
- }else if( op[j].arg==0 ){
- /* Ignore this option */
- }else if( op[j].type==OPT_FLAG ){
- *((int*)op[j].arg) = v;
- }else if( op[j].type==OPT_FFLAG ){
- (*(void(*)(int))(op[j].arg))(v);
- }else if( op[j].type==OPT_FSTR ){
- (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
- }else{
- if( err ){
- fprintf(err,"%smissing argument on switch.\n",emsg);
- errline(i,1,err);
- }
- errcnt++;
- }
- return errcnt;
-}
-
-/*
-** Process a command line switch which has an argument.
-*/
-static int handleswitch(int i, FILE *err)
-{
- int lv = 0;
- double dv = 0.0;
- char *sv = 0, *end;
- char *cp;
- int j;
- int errcnt = 0;
- cp = strchr(argv[i],'=');
- assert( cp!=0 );
- *cp = 0;
- for(j=0; op[j].label; j++){
- if( strcmp(argv[i],op[j].label)==0 ) break;
- }
- *cp = '=';
- if( op[j].label==0 ){
- if( err ){
- fprintf(err,"%sundefined option.\n",emsg);
- errline(i,0,err);
- }
- errcnt++;
- }else{
- cp++;
- switch( op[j].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- if( err ){
- fprintf(err,"%soption requires an argument.\n",emsg);
- errline(i,0,err);
- }
- errcnt++;
- break;
- case OPT_DBL:
- case OPT_FDBL:
- dv = strtod(cp,&end);
- if( *end ){
- if( err ){
- fprintf(err,
- "%sillegal character in floating-point argument.\n",emsg);
- errline(i,(int)((char*)end-(char*)argv[i]),err);
- }
- errcnt++;
- }
- break;
- case OPT_INT:
- case OPT_FINT:
- lv = strtol(cp,&end,0);
- if( *end ){
- if( err ){
- fprintf(err,"%sillegal character in integer argument.\n",emsg);
- errline(i,(int)((char*)end-(char*)argv[i]),err);
- }
- errcnt++;
- }
- break;
- case OPT_STR:
- case OPT_FSTR:
- sv = cp;
- break;
- }
- switch( op[j].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- break;
- case OPT_DBL:
- *(double*)(op[j].arg) = dv;
- break;
- case OPT_FDBL:
- (*(void(*)(double))(op[j].arg))(dv);
- break;
- case OPT_INT:
- *(int*)(op[j].arg) = lv;
- break;
- case OPT_FINT:
- (*(void(*)(int))(op[j].arg))((int)lv);
- break;
- case OPT_STR:
- *(char**)(op[j].arg) = sv;
- break;
- case OPT_FSTR:
- (*(void(*)(char *))(op[j].arg))(sv);
- break;
- }
- }
- return errcnt;
-}
-
-int OptInit(char **a, struct s_options *o, FILE *err)
-{
- int errcnt = 0;
- argv = a;
- op = o;
- errstream = err;
- if( argv && *argv && op ){
- int i;
- for(i=1; argv[i]; i++){
- if( argv[i][0]=='+' || argv[i][0]=='-' ){
- errcnt += handleflags(i,err);
- }else if( strchr(argv[i],'=') ){
- errcnt += handleswitch(i,err);
- }
- }
- }
- if( errcnt>0 ){
- fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
- OptPrint();
- exit(1);
- }
- return 0;
-}
-
-int OptNArgs(void){
- int cnt = 0;
- int dashdash = 0;
- int i;
- if( argv!=0 && argv[0]!=0 ){
- for(i=1; argv[i]; i++){
- if( dashdash || !ISOPT(argv[i]) ) cnt++;
- if( strcmp(argv[i],"--")==0 ) dashdash = 1;
- }
- }
- return cnt;
-}
-
-char *OptArg(int n)
-{
- int i;
- i = argindex(n);
- return i>=0 ? argv[i] : 0;
-}
-
-void OptErr(int n)
-{
- int i;
- i = argindex(n);
- if( i>=0 ) errline(i,0,errstream);
-}
-
-void OptPrint(void){
- int i;
- int max, len;
- max = 0;
- for(i=0; op[i].label; i++){
- len = lemonStrlen(op[i].label) + 1;
- switch( op[i].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- break;
- case OPT_INT:
- case OPT_FINT:
- len += 9; /* length of "<integer>" */
- break;
- case OPT_DBL:
- case OPT_FDBL:
- len += 6; /* length of "<real>" */
- break;
- case OPT_STR:
- case OPT_FSTR:
- len += 8; /* length of "<string>" */
- break;
- }
- if( len>max ) max = len;
- }
- for(i=0; op[i].label; i++){
- switch( op[i].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message);
- break;
- case OPT_INT:
- case OPT_FINT:
- fprintf(errstream," -%s<integer>%*s %s\n",op[i].label,
- (int)(max-lemonStrlen(op[i].label)-9),"",op[i].message);
- break;
- case OPT_DBL:
- case OPT_FDBL:
- fprintf(errstream," -%s<real>%*s %s\n",op[i].label,
- (int)(max-lemonStrlen(op[i].label)-6),"",op[i].message);
- break;
- case OPT_STR:
- case OPT_FSTR:
- fprintf(errstream," -%s<string>%*s %s\n",op[i].label,
- (int)(max-lemonStrlen(op[i].label)-8),"",op[i].message);
- break;
- }
- }
-}
-/*********************** From the file "parse.c" ****************************/
-/*
-** Input file parser for the LEMON parser generator.
-*/
-
-/* The state of the parser */
-enum e_state {
- INITIALIZE,
- WAITING_FOR_DECL_OR_RULE,
- WAITING_FOR_DECL_KEYWORD,
- WAITING_FOR_DECL_ARG,
- WAITING_FOR_PRECEDENCE_SYMBOL,
- WAITING_FOR_ARROW,
- IN_RHS,
- LHS_ALIAS_1,
- LHS_ALIAS_2,
- LHS_ALIAS_3,
- RHS_ALIAS_1,
- RHS_ALIAS_2,
- PRECEDENCE_MARK_1,
- PRECEDENCE_MARK_2,
- RESYNC_AFTER_RULE_ERROR,
- RESYNC_AFTER_DECL_ERROR,
- WAITING_FOR_DESTRUCTOR_SYMBOL,
- WAITING_FOR_DATATYPE_SYMBOL,
- WAITING_FOR_FALLBACK_ID,
- WAITING_FOR_WILDCARD_ID,
- WAITING_FOR_CLASS_ID,
- WAITING_FOR_CLASS_TOKEN,
- WAITING_FOR_TOKEN_NAME
-};
-struct pstate {
- char *filename; /* Name of the input file */
- int tokenlineno; /* Linenumber at which current token starts */
- int errorcnt; /* Number of errors so far */
- char *tokenstart; /* Text of current token */
- struct lemon *gp; /* Global state vector */
- enum e_state state; /* The state of the parser */
- struct symbol *fallback; /* The fallback token */
- struct symbol *tkclass; /* Token class symbol */
- struct symbol *lhs; /* Left-hand side of current rule */
- const char *lhsalias; /* Alias for the LHS */
- int nrhs; /* Number of right-hand side symbols seen */
- struct symbol *rhs[MAXRHS]; /* RHS symbols */
- const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
- struct rule *prevrule; /* Previous rule parsed */
- const char *declkeyword; /* Keyword of a declaration */
- char **declargslot; /* Where the declaration argument should be put */
- int insertLineMacro; /* Add #line before declaration insert */
- int *decllinenoslot; /* Where to write declaration line number */
- enum e_assoc declassoc; /* Assign this association to decl arguments */
- int preccounter; /* Assign this precedence to decl arguments */
- struct rule *firstrule; /* Pointer to first rule in the grammar */
- struct rule *lastrule; /* Pointer to the most recently parsed rule */
-};
-
-/* Parse a single token */
-static void parseonetoken(struct pstate *psp)
-{
- const char *x;
- x = Strsafe(psp->tokenstart); /* Save the token permanently */
-#if 0
- printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
- x,psp->state);
-#endif
- switch( psp->state ){
- case INITIALIZE:
- psp->prevrule = 0;
- psp->preccounter = 0;
- psp->firstrule = psp->lastrule = 0;
- psp->gp->nrule = 0;
- /* Fall thru to next case */
- case WAITING_FOR_DECL_OR_RULE:
- if( x[0]=='%' ){
- psp->state = WAITING_FOR_DECL_KEYWORD;
- }else if( ISLOWER(x[0]) ){
- psp->lhs = Symbol_new(x);
- psp->nrhs = 0;
- psp->lhsalias = 0;
- psp->state = WAITING_FOR_ARROW;
- }else if( x[0]=='{' ){
- if( psp->prevrule==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"There is no prior rule upon which to attach the code \
-fragment which begins on this line.");
- psp->errorcnt++;
- }else if( psp->prevrule->code!=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"Code fragment beginning on this line is not the first \
-to follow the previous rule.");
- psp->errorcnt++;
- }else{
- psp->prevrule->line = psp->tokenlineno;
- psp->prevrule->code = &x[1];
- psp->prevrule->noCode = 0;
- }
- }else if( x[0]=='[' ){
- psp->state = PRECEDENCE_MARK_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Token \"%s\" should be either \"%%\" or a nonterminal name.",
- x);
- psp->errorcnt++;
- }
- break;
- case PRECEDENCE_MARK_1:
- if( !ISUPPER(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "The precedence symbol must be a terminal.");
- psp->errorcnt++;
- }else if( psp->prevrule==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "There is no prior rule to assign precedence \"[%s]\".",x);
- psp->errorcnt++;
- }else if( psp->prevrule->precsym!=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"Precedence mark on this line is not the first \
-to follow the previous rule.");
- psp->errorcnt++;
- }else{
- psp->prevrule->precsym = Symbol_new(x);
- }
- psp->state = PRECEDENCE_MARK_2;
- break;
- case PRECEDENCE_MARK_2:
- if( x[0]!=']' ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \"]\" on precedence mark.");
- psp->errorcnt++;
- }
- psp->state = WAITING_FOR_DECL_OR_RULE;
- break;
- case WAITING_FOR_ARROW:
- if( x[0]==':' && x[1]==':' && x[2]=='=' ){
- psp->state = IN_RHS;
- }else if( x[0]=='(' ){
- psp->state = LHS_ALIAS_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Expected to see a \":\" following the LHS symbol \"%s\".",
- psp->lhs->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_1:
- if( ISALPHA(x[0]) ){
- psp->lhsalias = x;
- psp->state = LHS_ALIAS_2;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "\"%s\" is not a valid alias for the LHS \"%s\"\n",
- x,psp->lhs->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_2:
- if( x[0]==')' ){
- psp->state = LHS_ALIAS_3;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_3:
- if( x[0]==':' && x[1]==':' && x[2]=='=' ){
- psp->state = IN_RHS;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \"->\" following: \"%s(%s)\".",
- psp->lhs->name,psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case IN_RHS:
- if( x[0]=='.' ){
- struct rule *rp;
- rp = (struct rule *)calloc( sizeof(struct rule) +
- sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
- if( rp==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Can't allocate enough memory for this rule.");
- psp->errorcnt++;
- psp->prevrule = 0;
- }else{
- int i;
- rp->ruleline = psp->tokenlineno;
- rp->rhs = (struct symbol**)&rp[1];
- rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]);
- for(i=0; i<psp->nrhs; i++){
- rp->rhs[i] = psp->rhs[i];
- rp->rhsalias[i] = psp->alias[i];
- if( rp->rhsalias[i]!=0 ){ rp->rhs[i]->bContent = 1; }
- }
- rp->lhs = psp->lhs;
- rp->lhsalias = psp->lhsalias;
- rp->nrhs = psp->nrhs;
- rp->code = 0;
- rp->noCode = 1;
- rp->precsym = 0;
- rp->index = psp->gp->nrule++;
- rp->nextlhs = rp->lhs->rule;
- rp->lhs->rule = rp;
- rp->next = 0;
- if( psp->firstrule==0 ){
- psp->firstrule = psp->lastrule = rp;
- }else{
- psp->lastrule->next = rp;
- psp->lastrule = rp;
- }
- psp->prevrule = rp;
- }
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( ISALPHA(x[0]) ){
- if( psp->nrhs>=MAXRHS ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Too many symbols on RHS of rule beginning at \"%s\".",
- x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }else{
- psp->rhs[psp->nrhs] = Symbol_new(x);
- psp->alias[psp->nrhs] = 0;
- psp->nrhs++;
- }
- }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
- struct symbol *msp = psp->rhs[psp->nrhs-1];
- if( msp->type!=MULTITERMINAL ){
- struct symbol *origsp = msp;
- msp = (struct symbol *) calloc(1,sizeof(*msp));
- memset(msp, 0, sizeof(*msp));
- msp->type = MULTITERMINAL;
- msp->nsubsym = 1;
- msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*));
- msp->subsym[0] = origsp;
- msp->name = origsp->name;
- psp->rhs[psp->nrhs-1] = msp;
- }
- msp->nsubsym++;
- msp->subsym = (struct symbol **) realloc(msp->subsym,
- sizeof(struct symbol*)*msp->nsubsym);
- msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
- if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Cannot form a compound containing a non-terminal");
- psp->errorcnt++;
- }
- }else if( x[0]=='(' && psp->nrhs>0 ){
- psp->state = RHS_ALIAS_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal character on RHS of rule: \"%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case RHS_ALIAS_1:
- if( ISALPHA(x[0]) ){
- psp->alias[psp->nrhs-1] = x;
- psp->state = RHS_ALIAS_2;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
- x,psp->rhs[psp->nrhs-1]->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case RHS_ALIAS_2:
- if( x[0]==')' ){
- psp->state = IN_RHS;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case WAITING_FOR_DECL_KEYWORD:
- if( ISALPHA(x[0]) ){
- psp->declkeyword = x;
- psp->declargslot = 0;
- psp->decllinenoslot = 0;
- psp->insertLineMacro = 1;
- psp->state = WAITING_FOR_DECL_ARG;
- if( strcmp(x,"name")==0 ){
- psp->declargslot = &(psp->gp->name);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"include")==0 ){
- psp->declargslot = &(psp->gp->include);
- }else if( strcmp(x,"code")==0 ){
- psp->declargslot = &(psp->gp->extracode);
- }else if( strcmp(x,"token_destructor")==0 ){
- psp->declargslot = &psp->gp->tokendest;
- }else if( strcmp(x,"default_destructor")==0 ){
- psp->declargslot = &psp->gp->vardest;
- }else if( strcmp(x,"token_prefix")==0 ){
- psp->declargslot = &psp->gp->tokenprefix;
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"syntax_error")==0 ){
- psp->declargslot = &(psp->gp->error);
- }else if( strcmp(x,"parse_accept")==0 ){
- psp->declargslot = &(psp->gp->accept);
- }else if( strcmp(x,"parse_failure")==0 ){
- psp->declargslot = &(psp->gp->failure);
- }else if( strcmp(x,"stack_overflow")==0 ){
- psp->declargslot = &(psp->gp->overflow);
- }else if( strcmp(x,"extra_argument")==0 ){
- psp->declargslot = &(psp->gp->arg);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"extra_context")==0 ){
- psp->declargslot = &(psp->gp->ctx);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"token_type")==0 ){
- psp->declargslot = &(psp->gp->tokentype);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"default_type")==0 ){
- psp->declargslot = &(psp->gp->vartype);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"stack_size")==0 ){
- psp->declargslot = &(psp->gp->stacksize);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"start_symbol")==0 ){
- psp->declargslot = &(psp->gp->start);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"left")==0 ){
- psp->preccounter++;
- psp->declassoc = LEFT;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"right")==0 ){
- psp->preccounter++;
- psp->declassoc = RIGHT;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"nonassoc")==0 ){
- psp->preccounter++;
- psp->declassoc = NONE;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"destructor")==0 ){
- psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
- }else if( strcmp(x,"type")==0 ){
- psp->state = WAITING_FOR_DATATYPE_SYMBOL;
- }else if( strcmp(x,"fallback")==0 ){
- psp->fallback = 0;
- psp->state = WAITING_FOR_FALLBACK_ID;
- }else if( strcmp(x,"token")==0 ){
- psp->state = WAITING_FOR_TOKEN_NAME;
- }else if( strcmp(x,"wildcard")==0 ){
- psp->state = WAITING_FOR_WILDCARD_ID;
- }else if( strcmp(x,"token_class")==0 ){
- psp->state = WAITING_FOR_CLASS_ID;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Unknown declaration keyword: \"%%%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal declaration keyword: \"%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- break;
- case WAITING_FOR_DESTRUCTOR_SYMBOL:
- if( !ISALPHA(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol name missing after %%destructor keyword");
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- struct symbol *sp = Symbol_new(x);
- psp->declargslot = &sp->destructor;
- psp->decllinenoslot = &sp->destLineno;
- psp->insertLineMacro = 1;
- psp->state = WAITING_FOR_DECL_ARG;
- }
- break;
- case WAITING_FOR_DATATYPE_SYMBOL:
- if( !ISALPHA(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol name missing after %%type keyword");
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- struct symbol *sp = Symbol_find(x);
- if((sp) && (sp->datatype)){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol %%type \"%s\" already defined", x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- if (!sp){
- sp = Symbol_new(x);
- }
- psp->declargslot = &sp->datatype;
- psp->insertLineMacro = 0;
- psp->state = WAITING_FOR_DECL_ARG;
- }
- }
- break;
- case WAITING_FOR_PRECEDENCE_SYMBOL:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( ISUPPER(x[0]) ){
- struct symbol *sp;
- sp = Symbol_new(x);
- if( sp->prec>=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol \"%s\" has already be given a precedence.",x);
- psp->errorcnt++;
- }else{
- sp->prec = psp->preccounter;
- sp->assoc = psp->declassoc;
- }
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Can't assign a precedence to \"%s\".",x);
- psp->errorcnt++;
- }
- break;
- case WAITING_FOR_DECL_ARG:
- if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) ){
- const char *zOld, *zNew;
- char *zBuf, *z;
- int nOld, n, nLine = 0, nNew, nBack;
- int addLineMacro;
- char zLine[50];
- zNew = x;
- if( zNew[0]=='"' || zNew[0]=='{' ) zNew++;
- nNew = lemonStrlen(zNew);
- if( *psp->declargslot ){
- zOld = *psp->declargslot;
- }else{
- zOld = "";
- }
- nOld = lemonStrlen(zOld);
- n = nOld + nNew + 20;
- addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro &&
- (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
- if( addLineMacro ){
- for(z=psp->filename, nBack=0; *z; z++){
- if( *z=='\\' ) nBack++;
- }
- lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
- nLine = lemonStrlen(zLine);
- n += nLine + lemonStrlen(psp->filename) + nBack;
- }
- *psp->declargslot = (char *) realloc(*psp->declargslot, n);
- zBuf = *psp->declargslot + nOld;
- if( addLineMacro ){
- if( nOld && zBuf[-1]!='\n' ){
- *(zBuf++) = '\n';
- }
- memcpy(zBuf, zLine, nLine);
- zBuf += nLine;
- *(zBuf++) = '"';
- for(z=psp->filename; *z; z++){
- if( *z=='\\' ){
- *(zBuf++) = '\\';
- }
- *(zBuf++) = *z;
- }
- *(zBuf++) = '"';
- *(zBuf++) = '\n';
- }
- if( psp->decllinenoslot && psp->decllinenoslot[0]==0 ){
- psp->decllinenoslot[0] = psp->tokenlineno;
- }
- memcpy(zBuf, zNew, nNew);
- zBuf += nNew;
- *zBuf = 0;
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal argument to %%%s: %s",psp->declkeyword,x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- break;
- case WAITING_FOR_FALLBACK_ID:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( !ISUPPER(x[0]) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%fallback argument \"%s\" should be a token", x);
- psp->errorcnt++;
- }else{
- struct symbol *sp = Symbol_new(x);
- if( psp->fallback==0 ){
- psp->fallback = sp;
- }else if( sp->fallback ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "More than one fallback assigned to token %s", x);
- psp->errorcnt++;
- }else{
- sp->fallback = psp->fallback;
- psp->gp->has_fallback = 1;
- }
- }
- break;
- case WAITING_FOR_TOKEN_NAME:
- /* Tokens do not have to be declared before use. But they can be
- ** in order to control their assigned integer number. The number for
- ** each token is assigned when it is first seen. So by including
- **
- ** %token ONE TWO THREE
- **
- ** early in the grammar file, that assigns small consecutive values
- ** to each of the tokens ONE TWO and THREE.
- */
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( !ISUPPER(x[0]) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%token argument \"%s\" should be a token", x);
- psp->errorcnt++;
- }else{
- (void)Symbol_new(x);
- }
- break;
- case WAITING_FOR_WILDCARD_ID:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( !ISUPPER(x[0]) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%wildcard argument \"%s\" should be a token", x);
- psp->errorcnt++;
- }else{
- struct symbol *sp = Symbol_new(x);
- if( psp->gp->wildcard==0 ){
- psp->gp->wildcard = sp;
- }else{
- ErrorMsg(psp->filename, psp->tokenlineno,
- "Extra wildcard to token: %s", x);
- psp->errorcnt++;
- }
- }
- break;
- case WAITING_FOR_CLASS_ID:
- if( !ISLOWER(x[0]) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%token_class must be followed by an identifier: ", x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else if( Symbol_find(x) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "Symbol \"%s\" already used", x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- psp->tkclass = Symbol_new(x);
- psp->tkclass->type = MULTITERMINAL;
- psp->state = WAITING_FOR_CLASS_TOKEN;
- }
- break;
- case WAITING_FOR_CLASS_TOKEN:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){
- struct symbol *msp = psp->tkclass;
- msp->nsubsym++;
- msp->subsym = (struct symbol **) realloc(msp->subsym,
- sizeof(struct symbol*)*msp->nsubsym);
- if( !ISUPPER(x[0]) ) x++;
- msp->subsym[msp->nsubsym-1] = Symbol_new(x);
- }else{
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%token_class argument \"%s\" should be a token", x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- break;
- case RESYNC_AFTER_RULE_ERROR:
-/* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
-** break; */
- case RESYNC_AFTER_DECL_ERROR:
- if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
- if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
- break;
- }
-}
-
-/* Run the preprocessor over the input file text. The global variables
-** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
-** macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and
-** comments them out. Text in between is also commented out as appropriate.
-*/
-static void preprocess_input(char *z){
- int i, j, k, n;
- int exclude = 0;
- int start = 0;
- int lineno = 1;
- int start_lineno = 1;
- for(i=0; z[i]; i++){
- if( z[i]=='\n' ) lineno++;
- if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue;
- if( strncmp(&z[i],"%endif",6)==0 && ISSPACE(z[i+6]) ){
- if( exclude ){
- exclude--;
- if( exclude==0 ){
- for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
- }
- }
- for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
- }else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6]))
- || (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){
- if( exclude ){
- exclude++;
- }else{
- for(j=i+7; ISSPACE(z[j]); j++){}
- for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){}
- exclude = 1;
- for(k=0; k<nDefine; k++){
- if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){
- exclude = 0;
- break;
- }
- }
- if( z[i+3]=='n' ) exclude = !exclude;
- if( exclude ){
- start = i;
- start_lineno = lineno;
- }
- }
- for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
- }
- }
- if( exclude ){
- fprintf(stderr,"unterminated %%ifdef starting on line %d\n", start_lineno);
- exit(1);
- }
-}
-
-/* In spite of its name, this function is really a scanner. It read
-** in the entire input file (all at once) then tokenizes it. Each
-** token is passed to the function "parseonetoken" which builds all
-** the appropriate data structures in the global state vector "gp".
-*/
-void Parse(struct lemon *gp)
-{
- struct pstate ps;
- FILE *fp;
- char *filebuf;
- unsigned int filesize;
- int lineno;
- int c;
- char *cp, *nextcp;
- int startline = 0;
-
- memset(&ps, '\0', sizeof(ps));
- ps.gp = gp;
- ps.filename = gp->filename;
- ps.errorcnt = 0;
- ps.state = INITIALIZE;
-
- /* Begin by reading the input file */
- fp = fopen(ps.filename,"rb");
- if( fp==0 ){
- ErrorMsg(ps.filename,0,"Can't open this file for reading.");
- gp->errorcnt++;
- return;
- }
- fseek(fp,0,2);
- filesize = ftell(fp);
- rewind(fp);
- filebuf = (char *)malloc( filesize+1 );
- if( filesize>100000000 || filebuf==0 ){
- ErrorMsg(ps.filename,0,"Input file too large.");
- gp->errorcnt++;
- fclose(fp);
- return;
- }
- if( fread(filebuf,1,filesize,fp)!=filesize ){
- ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
- filesize);
- free(filebuf);
- gp->errorcnt++;
- fclose(fp);
- return;
- }
- fclose(fp);
- filebuf[filesize] = 0;
-
- /* Make an initial pass through the file to handle %ifdef and %ifndef */
- preprocess_input(filebuf);
-
- /* Now scan the text of the input file */
- lineno = 1;
- for(cp=filebuf; (c= *cp)!=0; ){
- if( c=='\n' ) lineno++; /* Keep track of the line number */
- if( ISSPACE(c) ){ cp++; continue; } /* Skip all white space */
- if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */
- cp+=2;
- while( (c= *cp)!=0 && c!='\n' ) cp++;
- continue;
- }
- if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */
- cp+=2;
- while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
- if( c=='\n' ) lineno++;
- cp++;
- }
- if( c ) cp++;
- continue;
- }
- ps.tokenstart = cp; /* Mark the beginning of the token */
- ps.tokenlineno = lineno; /* Linenumber on which token begins */
- if( c=='\"' ){ /* String literals */
- cp++;
- while( (c= *cp)!=0 && c!='\"' ){
- if( c=='\n' ) lineno++;
- cp++;
- }
- if( c==0 ){
- ErrorMsg(ps.filename,startline,
-"String starting on this line is not terminated before the end of the file.");
- ps.errorcnt++;
- nextcp = cp;
- }else{
- nextcp = cp+1;
- }
- }else if( c=='{' ){ /* A block of C code */
- int level;
- cp++;
- for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
- if( c=='\n' ) lineno++;
- else if( c=='{' ) level++;
- else if( c=='}' ) level--;
- else if( c=='/' && cp[1]=='*' ){ /* Skip comments */
- int prevc;
- cp = &cp[2];
- prevc = 0;
- while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
- if( c=='\n' ) lineno++;
- prevc = c;
- cp++;
- }
- }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
- cp = &cp[2];
- while( (c= *cp)!=0 && c!='\n' ) cp++;
- if( c ) lineno++;
- }else if( c=='\'' || c=='\"' ){ /* String a character literals */
- int startchar, prevc;
- startchar = c;
- prevc = 0;
- for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
- if( c=='\n' ) lineno++;
- if( prevc=='\\' ) prevc = 0;
- else prevc = c;
- }
- }
- }
- if( c==0 ){
- ErrorMsg(ps.filename,ps.tokenlineno,
-"C code starting on this line is not terminated before the end of the file.");
- ps.errorcnt++;
- nextcp = cp;
- }else{
- nextcp = cp+1;
- }
- }else if( ISALNUM(c) ){ /* Identifiers */
- while( (c= *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++;
- nextcp = cp;
- }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
- cp += 3;
- nextcp = cp;
- }else if( (c=='/' || c=='|') && ISALPHA(cp[1]) ){
- cp += 2;
- while( (c = *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++;
- nextcp = cp;
- }else{ /* All other (one character) operators */
- cp++;
- nextcp = cp;
- }
- c = *cp;
- *cp = 0; /* Null terminate the token */
- parseonetoken(&ps); /* Parse the token */
- *cp = (char)c; /* Restore the buffer */
- cp = nextcp;
- }
- free(filebuf); /* Release the buffer after parsing */
- gp->rule = ps.firstrule;
- gp->errorcnt = ps.errorcnt;
-}
-/*************************** From the file "plink.c" *********************/
-/*
-** Routines processing configuration follow-set propagation links
-** in the LEMON parser generator.
-*/
-static struct plink *plink_freelist = 0;
-
-/* Allocate a new plink */
-struct plink *Plink_new(void){
- struct plink *newlink;
-
- if( plink_freelist==0 ){
- int i;
- int amt = 100;
- plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) );
- if( plink_freelist==0 ){
- fprintf(stderr,
- "Unable to allocate memory for a new follow-set propagation link.\n");
- exit(1);
- }
- for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
- plink_freelist[amt-1].next = 0;
- }
- newlink = plink_freelist;
- plink_freelist = plink_freelist->next;
- return newlink;
-}
-
-/* Add a plink to a plink list */
-void Plink_add(struct plink **plpp, struct config *cfp)
-{
- struct plink *newlink;
- newlink = Plink_new();
- newlink->next = *plpp;
- *plpp = newlink;
- newlink->cfp = cfp;
-}
-
-/* Transfer every plink on the list "from" to the list "to" */
-void Plink_copy(struct plink **to, struct plink *from)
-{
- struct plink *nextpl;
- while( from ){
- nextpl = from->next;
- from->next = *to;
- *to = from;
- from = nextpl;
- }
-}
-
-/* Delete every plink on the list */
-void Plink_delete(struct plink *plp)
-{
- struct plink *nextpl;
-
- while( plp ){
- nextpl = plp->next;
- plp->next = plink_freelist;
- plink_freelist = plp;
- plp = nextpl;
- }
-}
-/*********************** From the file "report.c" **************************/
-/*
-** Procedures for generating reports and tables in the LEMON parser generator.
-*/
-
-/* Generate a filename with the given suffix. Space to hold the
-** name comes from malloc() and must be freed by the calling
-** function.
-*/
-PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
-{
- char *name;
- char *cp;
- char *filename = lemp->filename;
- int sz;
-
- if( outputDir ){
- cp = strrchr(filename, '/');
- if( cp ) filename = cp + 1;
- }
- sz = lemonStrlen(filename);
- sz += lemonStrlen(suffix);
- if( outputDir ) sz += lemonStrlen(outputDir) + 1;
- sz += 5;
- name = (char*)malloc( sz );
- if( name==0 ){
- fprintf(stderr,"Can't allocate space for a filename.\n");
- exit(1);
- }
- name[0] = 0;
- if( outputDir ){
- lemon_strcpy(name, outputDir);
- lemon_strcat(name, "/");
- }
- lemon_strcat(name,filename);
- cp = strrchr(name,'.');
- if( cp ) *cp = 0;
- lemon_strcat(name,suffix);
- return name;
-}
-
-/* Open a file with a name based on the name of the input file,
-** but with a different (specified) suffix, and return a pointer
-** to the stream */
-PRIVATE FILE *file_open(
- struct lemon *lemp,
- const char *suffix,
- const char *mode
-){
- FILE *fp;
-
- if( lemp->outname ) free(lemp->outname);
- lemp->outname = file_makename(lemp, suffix);
- fp = fopen(lemp->outname,mode);
- if( fp==0 && *mode=='w' ){
- fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
- lemp->errorcnt++;
- return 0;
- }
- return fp;
-}
-
-/* Print the text of a rule
-*/
-void rule_print(FILE *out, struct rule *rp){
- int i, j;
- fprintf(out, "%s",rp->lhs->name);
- /* if( rp->lhsalias ) fprintf(out,"(%s)",rp->lhsalias); */
- fprintf(out," ::=");
- for(i=0; i<rp->nrhs; i++){
- struct symbol *sp = rp->rhs[i];
- if( sp->type==MULTITERMINAL ){
- fprintf(out," %s", sp->subsym[0]->name);
- for(j=1; j<sp->nsubsym; j++){
- fprintf(out,"|%s", sp->subsym[j]->name);
- }
- }else{
- fprintf(out," %s", sp->name);
- }
- /* if( rp->rhsalias[i] ) fprintf(out,"(%s)",rp->rhsalias[i]); */
- }
-}
-
-/* Duplicate the input file without comments and without actions
-** on rules */
-void Reprint(struct lemon *lemp)
-{
- struct rule *rp;
- struct symbol *sp;
- int i, j, maxlen, len, ncolumns, skip;
- printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
- maxlen = 10;
- for(i=0; i<lemp->nsymbol; i++){
- sp = lemp->symbols[i];
- len = lemonStrlen(sp->name);
- if( len>maxlen ) maxlen = len;
- }
- ncolumns = 76/(maxlen+5);
- if( ncolumns<1 ) ncolumns = 1;
- skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
- for(i=0; i<skip; i++){
- printf("//");
- for(j=i; j<lemp->nsymbol; j+=skip){
- sp = lemp->symbols[j];
- assert( sp->index==j );
- printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
- }
- printf("\n");
- }
- for(rp=lemp->rule; rp; rp=rp->next){
- rule_print(stdout, rp);
- printf(".");
- if( rp->precsym ) printf(" [%s]",rp->precsym->name);
- /* if( rp->code ) printf("\n %s",rp->code); */
- printf("\n");
- }
-}
-
-/* Print a single rule.
-*/
-void RulePrint(FILE *fp, struct rule *rp, int iCursor){
- struct symbol *sp;
- int i, j;
- fprintf(fp,"%s ::=",rp->lhs->name);
- for(i=0; i<=rp->nrhs; i++){
- if( i==iCursor ) fprintf(fp," *");
- if( i==rp->nrhs ) break;
- sp = rp->rhs[i];
- if( sp->type==MULTITERMINAL ){
- fprintf(fp," %s", sp->subsym[0]->name);
- for(j=1; j<sp->nsubsym; j++){
- fprintf(fp,"|%s",sp->subsym[j]->name);
- }
- }else{
- fprintf(fp," %s", sp->name);
- }
- }
-}
-
-/* Print the rule for a configuration.
-*/
-void ConfigPrint(FILE *fp, struct config *cfp){
- RulePrint(fp, cfp->rp, cfp->dot);
-}
-
-/* #define TEST */
-#if 0
-/* Print a set */
-PRIVATE void SetPrint(out,set,lemp)
-FILE *out;
-char *set;
-struct lemon *lemp;
-{
- int i;
- char *spacer;
- spacer = "";
- fprintf(out,"%12s[","");
- for(i=0; i<lemp->nterminal; i++){
- if( SetFind(set,i) ){
- fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
- spacer = " ";
- }
- }
- fprintf(out,"]\n");
-}
-
-/* Print a plink chain */
-PRIVATE void PlinkPrint(out,plp,tag)
-FILE *out;
-struct plink *plp;
-char *tag;
-{
- while( plp ){
- fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->statenum);
- ConfigPrint(out,plp->cfp);
- fprintf(out,"\n");
- plp = plp->next;
- }
-}
-#endif
-
-/* Print an action to the given file descriptor. Return FALSE if
-** nothing was actually printed.
-*/
-int PrintAction(
- struct action *ap, /* The action to print */
- FILE *fp, /* Print the action here */
- int indent /* Indent by this amount */
-){
- int result = 1;
- switch( ap->type ){
- case SHIFT: {
- struct state *stp = ap->x.stp;
- fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum);
- break;
- }
- case REDUCE: {
- struct rule *rp = ap->x.rp;
- fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->iRule);
- RulePrint(fp, rp, -1);
- break;
- }
- case SHIFTREDUCE: {
- struct rule *rp = ap->x.rp;
- fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->iRule);
- RulePrint(fp, rp, -1);
- break;
- }
- case ACCEPT:
- fprintf(fp,"%*s accept",indent,ap->sp->name);
- break;
- case ERROR:
- fprintf(fp,"%*s error",indent,ap->sp->name);
- break;
- case SRCONFLICT:
- case RRCONFLICT:
- fprintf(fp,"%*s reduce %-7d ** Parsing conflict **",
- indent,ap->sp->name,ap->x.rp->iRule);
- break;
- case SSCONFLICT:
- fprintf(fp,"%*s shift %-7d ** Parsing conflict **",
- indent,ap->sp->name,ap->x.stp->statenum);
- break;
- case SH_RESOLVED:
- if( showPrecedenceConflict ){
- fprintf(fp,"%*s shift %-7d -- dropped by precedence",
- indent,ap->sp->name,ap->x.stp->statenum);
- }else{
- result = 0;
- }
- break;
- case RD_RESOLVED:
- if( showPrecedenceConflict ){
- fprintf(fp,"%*s reduce %-7d -- dropped by precedence",
- indent,ap->sp->name,ap->x.rp->iRule);
- }else{
- result = 0;
- }
- break;
- case NOT_USED:
- result = 0;
- break;
- }
- if( result && ap->spOpt ){
- fprintf(fp," /* because %s==%s */", ap->sp->name, ap->spOpt->name);
- }
- return result;
-}
-
-/* Generate the "*.out" log file */
-void ReportOutput(struct lemon *lemp)
-{
- int i, n;
- struct state *stp;
- struct config *cfp;
- struct action *ap;
- struct rule *rp;
- FILE *fp;
-
- fp = file_open(lemp,".out","wb");
- if( fp==0 ) return;
- for(i=0; i<lemp->nxstate; i++){
- stp = lemp->sorted[i];
- fprintf(fp,"State %d:\n",stp->statenum);
- if( lemp->basisflag ) cfp=stp->bp;
- else cfp=stp->cfp;
- while( cfp ){
- char buf[20];
- if( cfp->dot==cfp->rp->nrhs ){
- lemon_sprintf(buf,"(%d)",cfp->rp->iRule);
- fprintf(fp," %5s ",buf);
- }else{
- fprintf(fp," ");
- }
- ConfigPrint(fp,cfp);
- fprintf(fp,"\n");
-#if 0
- SetPrint(fp,cfp->fws,lemp);
- PlinkPrint(fp,cfp->fplp,"To ");
- PlinkPrint(fp,cfp->bplp,"From");
-#endif
- if( lemp->basisflag ) cfp=cfp->bp;
- else cfp=cfp->next;
- }
- fprintf(fp,"\n");
- for(ap=stp->ap; ap; ap=ap->next){
- if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
- }
- fprintf(fp,"\n");
- }
- fprintf(fp, "----------------------------------------------------\n");
- fprintf(fp, "Symbols:\n");
- fprintf(fp, "The first-set of non-terminals is shown after the name.\n\n");
- for(i=0; i<lemp->nsymbol; i++){
- int j;
- struct symbol *sp;
-
- sp = lemp->symbols[i];
- fprintf(fp, " %3d: %s", i, sp->name);
- if( sp->type==NONTERMINAL ){
- fprintf(fp, ":");
- if( sp->lambda ){
- fprintf(fp, " <lambda>");
- }
- for(j=0; j<lemp->nterminal; j++){
- if( sp->firstset && SetFind(sp->firstset, j) ){
- fprintf(fp, " %s", lemp->symbols[j]->name);
- }
- }
- }
- if( sp->prec>=0 ) fprintf(fp," (precedence=%d)", sp->prec);
- fprintf(fp, "\n");
- }
- fprintf(fp, "----------------------------------------------------\n");
- fprintf(fp, "Syntax-only Symbols:\n");
- fprintf(fp, "The following symbols never carry semantic content.\n\n");
- for(i=n=0; i<lemp->nsymbol; i++){
- int w;
- struct symbol *sp = lemp->symbols[i];
- if( sp->bContent ) continue;
- w = (int)strlen(sp->name);
- if( n>0 && n+w>75 ){
- fprintf(fp,"\n");
- n = 0;
- }
- if( n>0 ){
- fprintf(fp, " ");
- n++;
- }
- fprintf(fp, "%s", sp->name);
- n += w;
- }
- if( n>0 ) fprintf(fp, "\n");
- fprintf(fp, "----------------------------------------------------\n");
- fprintf(fp, "Rules:\n");
- for(rp=lemp->rule; rp; rp=rp->next){
- fprintf(fp, "%4d: ", rp->iRule);
- rule_print(fp, rp);
- fprintf(fp,".");
- if( rp->precsym ){
- fprintf(fp," [%s precedence=%d]",
- rp->precsym->name, rp->precsym->prec);
- }
- fprintf(fp,"\n");
- }
- fclose(fp);
- return;
-}
-
-/* Search for the file "name" which is in the same directory as
-** the exacutable */
-PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
-{
- const char *pathlist;
- char *pathbufptr;
- char *pathbuf;
- char *path,*cp;
- char c;
-
-#ifdef __WIN32__
- cp = strrchr(argv0,'\\');
-#else
- cp = strrchr(argv0,'/');
-#endif
- if( cp ){
- c = *cp;
- *cp = 0;
- path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
- if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
- *cp = c;
- }else{
- pathlist = getenv("PATH");
- if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
- pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
- path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
- if( (pathbuf != 0) && (path!=0) ){
- pathbufptr = pathbuf;
- lemon_strcpy(pathbuf, pathlist);
- while( *pathbuf ){
- cp = strchr(pathbuf,':');
- if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)];
- c = *cp;
- *cp = 0;
- lemon_sprintf(path,"%s/%s",pathbuf,name);
- *cp = c;
- if( c==0 ) pathbuf[0] = 0;
- else pathbuf = &cp[1];
- if( access(path,modemask)==0 ) break;
- }
- free(pathbufptr);
- }
- }
- return path;
-}
-
-/* Given an action, compute the integer value for that action
-** which is to be put in the action table of the generated machine.
-** Return negative if no action should be generated.
-*/
-PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
-{
- int act;
- switch( ap->type ){
- case SHIFT: act = ap->x.stp->statenum; break;
- case SHIFTREDUCE: {
- /* Since a SHIFT is inherient after a prior REDUCE, convert any
- ** SHIFTREDUCE action with a nonterminal on the LHS into a simple
- ** REDUCE action: */
- if( ap->sp->index>=lemp->nterminal ){
- act = lemp->minReduce + ap->x.rp->iRule;
- }else{
- act = lemp->minShiftReduce + ap->x.rp->iRule;
- }
- break;
- }
- case REDUCE: act = lemp->minReduce + ap->x.rp->iRule; break;
- case ERROR: act = lemp->errAction; break;
- case ACCEPT: act = lemp->accAction; break;
- default: act = -1; break;
- }
- return act;
-}
-
-#define LINESIZE 1000
-/* The next cluster of routines are for reading the template file
-** and writing the results to the generated parser */
-/* The first function transfers data from "in" to "out" until
-** a line is seen which begins with "%%". The line number is
-** tracked.
-**
-** if name!=0, then any word that begin with "Parse" is changed to
-** begin with *name instead.
-*/
-PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
-{
- int i, iStart;
- char line[LINESIZE];
- while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
- (*lineno)++;
- iStart = 0;
- if( name ){
- for(i=0; line[i]; i++){
- if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
- && (i==0 || !ISALPHA(line[i-1]))
- ){
- if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
- fprintf(out,"%s",name);
- i += 4;
- iStart = i+1;
- }
- }
- }
- fprintf(out,"%s",&line[iStart]);
- }
-}
-
-/* The next function finds the template file and opens it, returning
-** a pointer to the opened file. */
-PRIVATE FILE *tplt_open(struct lemon *lemp)
-{
- static char templatename[] = "lempar.c";
- char buf[1000];
- FILE *in;
- char *tpltname;
- char *cp;
-
- /* first, see if user specified a template filename on the command line. */
- if (user_templatename != 0) {
- if( access(user_templatename,004)==-1 ){
- fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
- user_templatename);
- lemp->errorcnt++;
- return 0;
- }
- in = fopen(user_templatename,"rb");
- if( in==0 ){
- fprintf(stderr,"Can't open the template file \"%s\".\n",
- user_templatename);
- lemp->errorcnt++;
- return 0;
- }
- return in;
- }
-
- cp = strrchr(lemp->filename,'.');
- if( cp ){
- lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
- }else{
- lemon_sprintf(buf,"%s.lt",lemp->filename);
- }
- if( access(buf,004)==0 ){
- tpltname = buf;
- }else if( access(templatename,004)==0 ){
- tpltname = templatename;
- }else{
- tpltname = pathsearch(lemp->argv0,templatename,0);
- }
- if( tpltname==0 ){
- fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
- templatename);
- lemp->errorcnt++;
- return 0;
- }
- in = fopen(tpltname,"rb");
- if( in==0 ){
- fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
- lemp->errorcnt++;
- return 0;
- }
- return in;
-}
-
-/* Print a #line directive line to the output file. */
-PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename)
-{
- fprintf(out,"#line %d \"",lineno);
- while( *filename ){
- if( *filename == '\\' ) putc('\\',out);
- putc(*filename,out);
- filename++;
- }
- fprintf(out,"\"\n");
-}
-
-/* Print a string to the file and keep the linenumber up to date */
-PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, int *lineno)
-{
- if( str==0 ) return;
- while( *str ){
- putc(*str,out);
- if( *str=='\n' ) (*lineno)++;
- str++;
- }
- if( str[-1]!='\n' ){
- putc('\n',out);
- (*lineno)++;
- }
- if (!lemp->nolinenosflag) {
- (*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
- }
- return;
-}
-
-/*
-** The following routine emits code for the destructor for the
-** symbol sp
-*/
-void emit_destructor_code(
- FILE *out,
- struct symbol *sp,
- struct lemon *lemp,
- int *lineno
-){
- char *cp = 0;
-
- if( sp->type==TERMINAL ){
- cp = lemp->tokendest;
- if( cp==0 ) return;
- fprintf(out,"{\n"); (*lineno)++;
- }else if( sp->destructor ){
- cp = sp->destructor;
- fprintf(out,"{\n"); (*lineno)++;
- if( !lemp->nolinenosflag ){
- (*lineno)++;
- tplt_linedir(out,sp->destLineno,lemp->filename);
- }
- }else if( lemp->vardest ){
- cp = lemp->vardest;
- if( cp==0 ) return;
- fprintf(out,"{\n"); (*lineno)++;
- }else{
- assert( 0 ); /* Cannot happen */
- }
- for(; *cp; cp++){
- if( *cp=='$' && cp[1]=='$' ){
- fprintf(out,"(yypminor->yy%d)",sp->dtnum);
- cp++;
- continue;
- }
- if( *cp=='\n' ) (*lineno)++;
- fputc(*cp,out);
- }
- fprintf(out,"\n"); (*lineno)++;
- if (!lemp->nolinenosflag) {
- (*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
- }
- fprintf(out,"}\n"); (*lineno)++;
- return;
-}
-
-/*
-** Return TRUE (non-zero) if the given symbol has a destructor.
-*/
-int has_destructor(struct symbol *sp, struct lemon *lemp)
-{
- int ret;
- if( sp->type==TERMINAL ){
- ret = lemp->tokendest!=0;
- }else{
- ret = lemp->vardest!=0 || sp->destructor!=0;
- }
- return ret;
-}
-
-/*
-** Append text to a dynamically allocated string. If zText is 0 then
-** reset the string to be empty again. Always return the complete text
-** of the string (which is overwritten with each call).
-**
-** n bytes of zText are stored. If n==0 then all of zText up to the first
-** \000 terminator is stored. zText can contain up to two instances of
-** %d. The values of p1 and p2 are written into the first and second
-** %d.
-**
-** If n==-1, then the previous character is overwritten.
-*/
-PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
- static char empty[1] = { 0 };
- static char *z = 0;
- static int alloced = 0;
- static int used = 0;
- int c;
- char zInt[40];
- if( zText==0 ){
- if( used==0 && z!=0 ) z[0] = 0;
- used = 0;
- return z;
- }
- if( n<=0 ){
- if( n<0 ){
- used += n;
- assert( used>=0 );
- }
- n = lemonStrlen(zText);
- }
- if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
- alloced = n + sizeof(zInt)*2 + used + 200;
- z = (char *) realloc(z, alloced);
- }
- if( z==0 ) return empty;
- while( n-- > 0 ){
- c = *(zText++);
- if( c=='%' && n>0 && zText[0]=='d' ){
- lemon_sprintf(zInt, "%d", p1);
- p1 = p2;
- lemon_strcpy(&z[used], zInt);
- used += lemonStrlen(&z[used]);
- zText++;
- n--;
- }else{
- z[used++] = (char)c;
- }
- }
- z[used] = 0;
- return z;
-}
-
-/*
-** Write and transform the rp->code string so that symbols are expanded.
-** Populate the rp->codePrefix and rp->codeSuffix strings, as appropriate.
-**
-** Return 1 if the expanded code requires that "yylhsminor" local variable
-** to be defined.
-*/
-PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
- char *cp, *xp;
- int i;
- int rc = 0; /* True if yylhsminor is used */
- int dontUseRhs0 = 0; /* If true, use of left-most RHS label is illegal */
- const char *zSkip = 0; /* The zOvwrt comment within rp->code, or NULL */
- char lhsused = 0; /* True if the LHS element has been used */
- char lhsdirect; /* True if LHS writes directly into stack */
- char used[MAXRHS]; /* True for each RHS element which is used */
- char zLhs[50]; /* Convert the LHS symbol into this string */
- char zOvwrt[900]; /* Comment that to allow LHS to overwrite RHS */
-
- for(i=0; i<rp->nrhs; i++) used[i] = 0;
- lhsused = 0;
-
- if( rp->code==0 ){
- static char newlinestr[2] = { '\n', '\0' };
- rp->code = newlinestr;
- rp->line = rp->ruleline;
- rp->noCode = 1;
- }else{
- rp->noCode = 0;
- }
-
-
- if( rp->nrhs==0 ){
- /* If there are no RHS symbols, then writing directly to the LHS is ok */
- lhsdirect = 1;
- }else if( rp->rhsalias[0]==0 ){
- /* The left-most RHS symbol has no value. LHS direct is ok. But
- ** we have to call the distructor on the RHS symbol first. */
- lhsdirect = 1;
- if( has_destructor(rp->rhs[0],lemp) ){
- append_str(0,0,0,0);
- append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
- rp->rhs[0]->index,1-rp->nrhs);
- rp->codePrefix = Strsafe(append_str(0,0,0,0));
- rp->noCode = 0;
- }
- }else if( rp->lhsalias==0 ){
- /* There is no LHS value symbol. */
- lhsdirect = 1;
- }else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){
- /* The LHS symbol and the left-most RHS symbol are the same, so
- ** direct writing is allowed */
- lhsdirect = 1;
- lhsused = 1;
- used[0] = 1;
- if( rp->lhs->dtnum!=rp->rhs[0]->dtnum ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "%s(%s) and %s(%s) share the same label but have "
- "different datatypes.",
- rp->lhs->name, rp->lhsalias, rp->rhs[0]->name, rp->rhsalias[0]);
- lemp->errorcnt++;
- }
- }else{
- lemon_sprintf(zOvwrt, "/*%s-overwrites-%s*/",
- rp->lhsalias, rp->rhsalias[0]);
- zSkip = strstr(rp->code, zOvwrt);
- if( zSkip!=0 ){
- /* The code contains a special comment that indicates that it is safe
- ** for the LHS label to overwrite left-most RHS label. */
- lhsdirect = 1;
- }else{
- lhsdirect = 0;
- }
- }
- if( lhsdirect ){
- sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
- }else{
- rc = 1;
- sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
- }
-
- append_str(0,0,0,0);
-
- /* This const cast is wrong but harmless, if we're careful. */
- for(cp=(char *)rp->code; *cp; cp++){
- if( cp==zSkip ){
- append_str(zOvwrt,0,0,0);
- cp += lemonStrlen(zOvwrt)-1;
- dontUseRhs0 = 1;
- continue;
- }
- if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){
- char saved;
- for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++);
- saved = *xp;
- *xp = 0;
- if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
- append_str(zLhs,0,0,0);
- cp = xp;
- lhsused = 1;
- }else{
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
- if( i==0 && dontUseRhs0 ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "Label %s used after '%s'.",
- rp->rhsalias[0], zOvwrt);
- lemp->errorcnt++;
- }else if( cp!=rp->code && cp[-1]=='@' ){
- /* If the argument is of the form @X then substituted
- ** the token number of X, not the value of X */
- append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0);
- }else{
- struct symbol *sp = rp->rhs[i];
- int dtnum;
- if( sp->type==MULTITERMINAL ){
- dtnum = sp->subsym[0]->dtnum;
- }else{
- dtnum = sp->dtnum;
- }
- append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum);
- }
- cp = xp;
- used[i] = 1;
- break;
- }
- }
- }
- *xp = saved;
- }
- append_str(cp, 1, 0, 0);
- } /* End loop */
-
- /* Main code generation completed */
- cp = append_str(0,0,0,0);
- if( cp && cp[0] ) rp->code = Strsafe(cp);
- append_str(0,0,0,0);
-
- /* Check to make sure the LHS has been used */
- if( rp->lhsalias && !lhsused ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "Label \"%s\" for \"%s(%s)\" is never used.",
- rp->lhsalias,rp->lhs->name,rp->lhsalias);
- lemp->errorcnt++;
- }
-
- /* Generate destructor code for RHS minor values which are not referenced.
- ** Generate error messages for unused labels and duplicate labels.
- */
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhsalias[i] ){
- if( i>0 ){
- int j;
- if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "%s(%s) has the same label as the LHS but is not the left-most "
- "symbol on the RHS.",
- rp->rhs[i]->name, rp->rhsalias);
- lemp->errorcnt++;
- }
- for(j=0; j<i; j++){
- if( rp->rhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "Label %s used for multiple symbols on the RHS of a rule.",
- rp->rhsalias[i]);
- lemp->errorcnt++;
- break;
- }
- }
- }
- if( !used[i] ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "Label %s for \"%s(%s)\" is never used.",
- rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
- lemp->errorcnt++;
- }
- }else if( i>0 && has_destructor(rp->rhs[i],lemp) ){
- append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
- rp->rhs[i]->index,i-rp->nrhs+1);
- }
- }
-
- /* If unable to write LHS values directly into the stack, write the
- ** saved LHS value now. */
- if( lhsdirect==0 ){
- append_str(" yymsp[%d].minor.yy%d = ", 0, 1-rp->nrhs, rp->lhs->dtnum);
- append_str(zLhs, 0, 0, 0);
- append_str(";\n", 0, 0, 0);
- }
-
- /* Suffix code generation complete */
- cp = append_str(0,0,0,0);
- if( cp && cp[0] ){
- rp->codeSuffix = Strsafe(cp);
- rp->noCode = 0;
- }
-
- return rc;
-}
-
-/*
-** Generate code which executes when the rule "rp" is reduced. Write
-** the code to "out". Make sure lineno stays up-to-date.
-*/
-PRIVATE void emit_code(
- FILE *out,
- struct rule *rp,
- struct lemon *lemp,
- int *lineno
-){
- const char *cp;
-
- /* Setup code prior to the #line directive */
- if( rp->codePrefix && rp->codePrefix[0] ){
- fprintf(out, "{%s", rp->codePrefix);
- for(cp=rp->codePrefix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
- }
-
- /* Generate code to do the reduce action */
- if( rp->code ){
- if( !lemp->nolinenosflag ){
- (*lineno)++;
- tplt_linedir(out,rp->line,lemp->filename);
- }
- fprintf(out,"{%s",rp->code);
- for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
- fprintf(out,"}\n"); (*lineno)++;
- if( !lemp->nolinenosflag ){
- (*lineno)++;
- tplt_linedir(out,*lineno,lemp->outname);
- }
- }
-
- /* Generate breakdown code that occurs after the #line directive */
- if( rp->codeSuffix && rp->codeSuffix[0] ){
- fprintf(out, "%s", rp->codeSuffix);
- for(cp=rp->codeSuffix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
- }
-
- if( rp->codePrefix ){
- fprintf(out, "}\n"); (*lineno)++;
- }
-
- return;
-}
-
-/*
-** Print the definition of the union used for the parser's data stack.
-** This union contains fields for every possible data type for tokens
-** and nonterminals. In the process of computing and printing this
-** union, also set the ".dtnum" field of every terminal and nonterminal
-** symbol.
-*/
-void print_stack_union(
- FILE *out, /* The output stream */
- struct lemon *lemp, /* The main info structure for this parser */
- int *plineno, /* Pointer to the line number */
- int mhflag /* True if generating makeheaders output */
-){
- int lineno = *plineno; /* The line number of the output */
- char **types; /* A hash table of datatypes */
- int arraysize; /* Size of the "types" array */
- int maxdtlength; /* Maximum length of any ".datatype" field. */
- char *stddt; /* Standardized name for a datatype */
- int i,j; /* Loop counters */
- unsigned hash; /* For hashing the name of a type */
- const char *name; /* Name of the parser */
-
- /* Allocate and initialize types[] and allocate stddt[] */
- arraysize = lemp->nsymbol * 2;
- types = (char**)calloc( arraysize, sizeof(char*) );
- if( types==0 ){
- fprintf(stderr,"Out of memory.\n");
- exit(1);
- }
- for(i=0; i<arraysize; i++) types[i] = 0;
- maxdtlength = 0;
- if( lemp->vartype ){
- maxdtlength = lemonStrlen(lemp->vartype);
- }
- for(i=0; i<lemp->nsymbol; i++){
- int len;
- struct symbol *sp = lemp->symbols[i];
- if( sp->datatype==0 ) continue;
- len = lemonStrlen(sp->datatype);
- if( len>maxdtlength ) maxdtlength = len;
- }
- stddt = (char*)malloc( maxdtlength*2 + 1 );
- if( stddt==0 ){
- fprintf(stderr,"Out of memory.\n");
- exit(1);
- }
-
- /* Build a hash table of datatypes. The ".dtnum" field of each symbol
- ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
- ** used for terminal symbols. If there is no %default_type defined then
- ** 0 is also used as the .dtnum value for nonterminals which do not specify
- ** a datatype using the %type directive.
- */
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- char *cp;
- if( sp==lemp->errsym ){
- sp->dtnum = arraysize+1;
- continue;
- }
- if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
- sp->dtnum = 0;
- continue;
- }
- cp = sp->datatype;
- if( cp==0 ) cp = lemp->vartype;
- j = 0;
- while( ISSPACE(*cp) ) cp++;
- while( *cp ) stddt[j++] = *cp++;
- while( j>0 && ISSPACE(stddt[j-1]) ) j--;
- stddt[j] = 0;
- if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){
- sp->dtnum = 0;
- continue;
- }
- hash = 0;
- for(j=0; stddt[j]; j++){
- hash = hash*53 + stddt[j];
- }
- hash = (hash & 0x7fffffff)%arraysize;
- while( types[hash] ){
- if( strcmp(types[hash],stddt)==0 ){
- sp->dtnum = hash + 1;
- break;
- }
- hash++;
- if( hash>=(unsigned)arraysize ) hash = 0;
- }
- if( types[hash]==0 ){
- sp->dtnum = hash + 1;
- types[hash] = (char*)malloc( lemonStrlen(stddt)+1 );
- if( types[hash]==0 ){
- fprintf(stderr,"Out of memory.\n");
- exit(1);
- }
- lemon_strcpy(types[hash],stddt);
- }
- }
-
- /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
- name = lemp->name ? lemp->name : "Parse";
- lineno = *plineno;
- if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
- fprintf(out,"#define %sTOKENTYPE %s\n",name,
- lemp->tokentype?lemp->tokentype:"void*"); lineno++;
- if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
- fprintf(out,"typedef union {\n"); lineno++;
- fprintf(out," int yyinit;\n"); lineno++;
- fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++;
- for(i=0; i<arraysize; i++){
- if( types[i]==0 ) continue;
- fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
- free(types[i]);
- }
- if( lemp->errsym && lemp->errsym->useCnt ){
- fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
- }
- free(stddt);
- free(types);
- fprintf(out,"} YYMINORTYPE;\n"); lineno++;
- *plineno = lineno;
-}
-
-/*
-** Return the name of a C datatype able to represent values between
-** lwr and upr, inclusive. If pnByte!=NULL then also write the sizeof
-** for that type (1, 2, or 4) into *pnByte.
-*/
-static const char *minimum_size_type(int lwr, int upr, int *pnByte){
- const char *zType = "int";
- int nByte = 4;
- if( lwr>=0 ){
- if( upr<=255 ){
- zType = "unsigned char";
- nByte = 1;
- }else if( upr<65535 ){
- zType = "unsigned short int";
- nByte = 2;
- }else{
- zType = "unsigned int";
- nByte = 4;
- }
- }else if( lwr>=-127 && upr<=127 ){
- zType = "signed char";
- nByte = 1;
- }else if( lwr>=-32767 && upr<32767 ){
- zType = "short";
- nByte = 2;
- }
- if( pnByte ) *pnByte = nByte;
- return zType;
-}
-
-/*
-** Each state contains a set of token transaction and a set of
-** nonterminal transactions. Each of these sets makes an instance
-** of the following structure. An array of these structures is used
-** to order the creation of entries in the yy_action[] table.
-*/
-struct axset {
- struct state *stp; /* A pointer to a state */
- int isTkn; /* True to use tokens. False for non-terminals */
- int nAction; /* Number of actions */
- int iOrder; /* Original order of action sets */
-};
-
-/*
-** Compare to axset structures for sorting purposes
-*/
-static int axset_compare(const void *a, const void *b){
- struct axset *p1 = (struct axset*)a;
- struct axset *p2 = (struct axset*)b;
- int c;
- c = p2->nAction - p1->nAction;
- if( c==0 ){
- c = p1->iOrder - p2->iOrder;
- }
- assert( c!=0 || p1==p2 );
- return c;
-}
-
-/*
-** Write text on "out" that describes the rule "rp".
-*/
-static void writeRuleText(FILE *out, struct rule *rp){
- int j;
- fprintf(out,"%s ::=", rp->lhs->name);
- for(j=0; j<rp->nrhs; j++){
- struct symbol *sp = rp->rhs[j];
- if( sp->type!=MULTITERMINAL ){
- fprintf(out," %s", sp->name);
- }else{
- int k;
- fprintf(out," %s", sp->subsym[0]->name);
- for(k=1; k<sp->nsubsym; k++){
- fprintf(out,"|%s",sp->subsym[k]->name);
- }
- }
- }
-}
-
-
-/* Generate C source code for the parser */
-void ReportTable(
- struct lemon *lemp,
- int mhflag /* Output in makeheaders format if true */
-){
- FILE *out, *in;
- char line[LINESIZE];
- int lineno;
- struct state *stp;
- struct action *ap;
- struct rule *rp;
- struct acttab *pActtab;
- int i, j, n, sz;
- int szActionType; /* sizeof(YYACTIONTYPE) */
- int szCodeType; /* sizeof(YYCODETYPE) */
- const char *name;
- int mnTknOfst, mxTknOfst;
- int mnNtOfst, mxNtOfst;
- struct axset *ax;
-
- lemp->minShiftReduce = lemp->nstate;
- lemp->errAction = lemp->minShiftReduce + lemp->nrule;
- lemp->accAction = lemp->errAction + 1;
- lemp->noAction = lemp->accAction + 1;
- lemp->minReduce = lemp->noAction + 1;
- lemp->maxAction = lemp->minReduce + lemp->nrule;
-
- in = tplt_open(lemp);
- if( in==0 ) return;
- out = file_open(lemp,".c","wb");
- if( out==0 ){
- fclose(in);
- return;
- }
- lineno = 1;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the include code, if any */
- tplt_print(out,lemp,lemp->include,&lineno);
- if( mhflag ){
- char *incName = file_makename(lemp, ".h");
- fprintf(out,"#include \"%s\"\n", incName); lineno++;
- free(incName);
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate #defines for all tokens */
- if( mhflag ){
- const char *prefix;
- fprintf(out,"#if INTERFACE\n"); lineno++;
- if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
- else prefix = "";
- for(i=1; i<lemp->nterminal; i++){
- fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
- lineno++;
- }
- fprintf(out,"#endif\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the defines */
- fprintf(out,"#define YYCODETYPE %s\n",
- minimum_size_type(0, lemp->nsymbol, &szCodeType)); lineno++;
- fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol); lineno++;
- fprintf(out,"#define YYACTIONTYPE %s\n",
- minimum_size_type(0,lemp->maxAction,&szActionType)); lineno++;
- if( lemp->wildcard ){
- fprintf(out,"#define YYWILDCARD %d\n",
- lemp->wildcard->index); lineno++;
- }
- print_stack_union(out,lemp,&lineno,mhflag);
- fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++;
- if( lemp->stacksize ){
- fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
- }else{
- fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
- }
- fprintf(out, "#endif\n"); lineno++;
- if( mhflag ){
- fprintf(out,"#if INTERFACE\n"); lineno++;
- }
- name = lemp->name ? lemp->name : "Parse";
- if( lemp->arg && lemp->arg[0] ){
- i = lemonStrlen(lemp->arg);
- while( i>=1 && ISSPACE(lemp->arg[i-1]) ) i--;
- while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
- fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
- fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
- fprintf(out,"#define %sARG_PARAM ,%s\n",name,&lemp->arg[i]); lineno++;
- fprintf(out,"#define %sARG_FETCH %s=yypParser->%s;\n",
- name,lemp->arg,&lemp->arg[i]); lineno++;
- fprintf(out,"#define %sARG_STORE yypParser->%s=%s;\n",
- name,&lemp->arg[i],&lemp->arg[i]); lineno++;
- }else{
- fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
- fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
- fprintf(out,"#define %sARG_PARAM\n",name); lineno++;
- fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
- fprintf(out,"#define %sARG_STORE\n",name); lineno++;
- }
- if( lemp->ctx && lemp->ctx[0] ){
- i = lemonStrlen(lemp->ctx);
- while( i>=1 && ISSPACE(lemp->ctx[i-1]) ) i--;
- while( i>=1 && (ISALNUM(lemp->ctx[i-1]) || lemp->ctx[i-1]=='_') ) i--;
- fprintf(out,"#define %sCTX_SDECL %s;\n",name,lemp->ctx); lineno++;
- fprintf(out,"#define %sCTX_PDECL ,%s\n",name,lemp->ctx); lineno++;
- fprintf(out,"#define %sCTX_PARAM ,%s\n",name,&lemp->ctx[i]); lineno++;
- fprintf(out,"#define %sCTX_FETCH %s=yypParser->%s;\n",
- name,lemp->ctx,&lemp->ctx[i]); lineno++;
- fprintf(out,"#define %sCTX_STORE yypParser->%s=%s;\n",
- name,&lemp->ctx[i],&lemp->ctx[i]); lineno++;
- }else{
- fprintf(out,"#define %sCTX_SDECL\n",name); lineno++;
- fprintf(out,"#define %sCTX_PDECL\n",name); lineno++;
- fprintf(out,"#define %sCTX_PARAM\n",name); lineno++;
- fprintf(out,"#define %sCTX_FETCH\n",name); lineno++;
- fprintf(out,"#define %sCTX_STORE\n",name); lineno++;
- }
- if( mhflag ){
- fprintf(out,"#endif\n"); lineno++;
- }
- if( lemp->errsym && lemp->errsym->useCnt ){
- fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
- fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
- }
- if( lemp->has_fallback ){
- fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
- }
-
- /* Compute the action table, but do not output it yet. The action
- ** table must be computed before generating the YYNSTATE macro because
- ** we need to know how many states can be eliminated.
- */
- ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
- if( ax==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- for(i=0; i<lemp->nxstate; i++){
- stp = lemp->sorted[i];
- ax[i*2].stp = stp;
- ax[i*2].isTkn = 1;
- ax[i*2].nAction = stp->nTknAct;
- ax[i*2+1].stp = stp;
- ax[i*2+1].isTkn = 0;
- ax[i*2+1].nAction = stp->nNtAct;
- }
- mxTknOfst = mnTknOfst = 0;
- mxNtOfst = mnNtOfst = 0;
- /* In an effort to minimize the action table size, use the heuristic
- ** of placing the largest action sets first */
- for(i=0; i<lemp->nxstate*2; i++) ax[i].iOrder = i;
- qsort(ax, lemp->nxstate*2, sizeof(ax[0]), axset_compare);
- pActtab = acttab_alloc(lemp->nsymbol, lemp->nterminal);
- for(i=0; i<lemp->nxstate*2 && ax[i].nAction>0; i++){
- stp = ax[i].stp;
- if( ax[i].isTkn ){
- for(ap=stp->ap; ap; ap=ap->next){
- int action;
- if( ap->sp->index>=lemp->nterminal ) continue;
- action = compute_action(lemp, ap);
- if( action<0 ) continue;
- acttab_action(pActtab, ap->sp->index, action);
- }
- stp->iTknOfst = acttab_insert(pActtab, 1);
- if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
- if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
- }else{
- for(ap=stp->ap; ap; ap=ap->next){
- int action;
- if( ap->sp->index<lemp->nterminal ) continue;
- if( ap->sp->index==lemp->nsymbol ) continue;
- action = compute_action(lemp, ap);
- if( action<0 ) continue;
- acttab_action(pActtab, ap->sp->index, action);
- }
- stp->iNtOfst = acttab_insert(pActtab, 0);
- if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
- if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
- }
-#if 0 /* Uncomment for a trace of how the yy_action[] table fills out */
- { int jj, nn;
- for(jj=nn=0; jj<pActtab->nAction; jj++){
- if( pActtab->aAction[jj].action<0 ) nn++;
- }
- printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n",
- i, stp->statenum, ax[i].isTkn ? "Token" : "Var ",
- ax[i].nAction, pActtab->nAction, nn);
- }
-#endif
- }
- free(ax);
-
- /* Mark rules that are actually used for reduce actions after all
- ** optimizations have been applied
- */
- for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE;
- for(i=0; i<lemp->nxstate; i++){
- for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
- if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){
- ap->x.rp->doesReduce = 1;
- }
- }
- }
-
- /* Finish rendering the constants now that the action table has
- ** been computed */
- fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
- fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
- fprintf(out,"#define YYNTOKEN %d\n",lemp->nterminal); lineno++;
- fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++;
- i = lemp->minShiftReduce;
- fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",i); lineno++;
- i += lemp->nrule;
- fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++;
- fprintf(out,"#define YY_ERROR_ACTION %d\n", lemp->errAction); lineno++;
- fprintf(out,"#define YY_ACCEPT_ACTION %d\n", lemp->accAction); lineno++;
- fprintf(out,"#define YY_NO_ACTION %d\n", lemp->noAction); lineno++;
- fprintf(out,"#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++;
- i = lemp->minReduce + lemp->nrule;
- fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Now output the action table and its associates:
- **
- ** yy_action[] A single table containing all actions.
- ** yy_lookahead[] A table containing the lookahead for each entry in
- ** yy_action. Used to detect hash collisions.
- ** yy_shift_ofst[] For each state, the offset into yy_action for
- ** shifting terminals.
- ** yy_reduce_ofst[] For each state, the offset into yy_action for
- ** shifting non-terminals after a reduce.
- ** yy_default[] Default action for each state.
- */
-
- /* Output the yy_action table */
- lemp->nactiontab = n = acttab_action_size(pActtab);
- lemp->tablesize += n*szActionType;
- fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++;
- fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
- for(i=j=0; i<n; i++){
- int action = acttab_yyaction(pActtab, i);
- if( action<0 ) action = lemp->noAction;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", action);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_lookahead table */
- lemp->nlookaheadtab = n = acttab_lookahead_size(pActtab);
- lemp->tablesize += n*szCodeType;
- fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
- for(i=j=0; i<n; i++){
- int la = acttab_yylookahead(pActtab, i);
- if( la<0 ) la = lemp->nsymbol;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", la);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_shift_ofst[] table */
- n = lemp->nxstate;
- while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
- fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
- fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
- fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
- fprintf(out, "static const %s yy_shift_ofst[] = {\n",
- minimum_size_type(mnTknOfst, lemp->nterminal+lemp->nactiontab, &sz));
- lineno++;
- lemp->tablesize += n*sz;
- for(i=j=0; i<n; i++){
- int ofst;
- stp = lemp->sorted[i];
- ofst = stp->iTknOfst;
- if( ofst==NO_OFFSET ) ofst = lemp->nactiontab;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", ofst);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_reduce_ofst[] table */
- n = lemp->nxstate;
- while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
- fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++;
- fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++;
- fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++;
- fprintf(out, "static const %s yy_reduce_ofst[] = {\n",
- minimum_size_type(mnNtOfst-1, mxNtOfst, &sz)); lineno++;
- lemp->tablesize += n*sz;
- for(i=j=0; i<n; i++){
- int ofst;
- stp = lemp->sorted[i];
- ofst = stp->iNtOfst;
- if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", ofst);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the default action table */
- fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
- n = lemp->nxstate;
- lemp->tablesize += n*szActionType;
- for(i=j=0; i<n; i++){
- stp = lemp->sorted[i];
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- if( stp->iDfltReduce<0 ){
- fprintf(out, " %4d,", lemp->errAction);
- }else{
- fprintf(out, " %4d,", stp->iDfltReduce + lemp->minReduce);
- }
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the table of fallback tokens.
- */
- if( lemp->has_fallback ){
- int mx = lemp->nterminal - 1;
- while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
- lemp->tablesize += (mx+1)*szCodeType;
- for(i=0; i<=mx; i++){
- struct symbol *p = lemp->symbols[i];
- if( p->fallback==0 ){
- fprintf(out, " 0, /* %10s => nothing */\n", p->name);
- }else{
- fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index,
- p->name, p->fallback->name);
- }
- lineno++;
- }
- }
- tplt_xfer(lemp->name, in, out, &lineno);
-
- /* Generate a table containing the symbolic name of every symbol
- */
- for(i=0; i<lemp->nsymbol; i++){
- lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
- fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate a table containing a text string that describes every
- ** rule in the rule set of the grammar. This information is used
- ** when tracing REDUCE actions.
- */
- for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
- assert( rp->iRule==i );
- fprintf(out," /* %3d */ \"", i);
- writeRuleText(out, rp);
- fprintf(out,"\",\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes every time a symbol is popped from
- ** the stack while processing errors or while destroying the parser.
- ** (In other words, generate the %destructor actions)
- */
- if( lemp->tokendest ){
- int once = 1;
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type!=TERMINAL ) continue;
- if( once ){
- fprintf(out, " /* TERMINAL Destructor */\n"); lineno++;
- once = 0;
- }
- fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
- }
- for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
- if( i<lemp->nsymbol ){
- emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- }
- }
- if( lemp->vardest ){
- struct symbol *dflt_sp = 0;
- int once = 1;
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type==TERMINAL ||
- sp->index<=0 || sp->destructor!=0 ) continue;
- if( once ){
- fprintf(out, " /* Default NON-TERMINAL Destructor */\n");lineno++;
- once = 0;
- }
- fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
- dflt_sp = sp;
- }
- if( dflt_sp!=0 ){
- emit_destructor_code(out,dflt_sp,lemp,&lineno);
- }
- fprintf(out," break;\n"); lineno++;
- }
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
- if( sp->destLineno<0 ) continue; /* Already emitted */
- fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
-
- /* Combine duplicate destructors into a single case */
- for(j=i+1; j<lemp->nsymbol; j++){
- struct symbol *sp2 = lemp->symbols[j];
- if( sp2 && sp2->type!=TERMINAL && sp2->destructor
- && sp2->dtnum==sp->dtnum
- && strcmp(sp->destructor,sp2->destructor)==0 ){
- fprintf(out," case %d: /* %s */\n",
- sp2->index, sp2->name); lineno++;
- sp2->destLineno = -1; /* Avoid emitting this destructor again */
- }
- }
-
- emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes whenever the parser stack overflows */
- tplt_print(out,lemp,lemp->overflow,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the table of rule information
- **
- ** Note: This code depends on the fact that rules are number
- ** sequentually beginning with 0.
- */
- for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
- fprintf(out," { %4d, %4d }, /* (%d) ",rp->lhs->index,-rp->nrhs,i);
- rule_print(out, rp);
- fprintf(out," */\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which execution during each REDUCE action */
- i = 0;
- for(rp=lemp->rule; rp; rp=rp->next){
- i += translate_code(lemp, rp);
- }
- if( i ){
- fprintf(out," YYMINORTYPE yylhsminor;\n"); lineno++;
- }
- /* First output rules other than the default: rule */
- for(rp=lemp->rule; rp; rp=rp->next){
- struct rule *rp2; /* Other rules with the same action */
- if( rp->codeEmitted ) continue;
- if( rp->noCode ){
- /* No C code actions, so this will be part of the "default:" rule */
- continue;
- }
- fprintf(out," case %d: /* ", rp->iRule);
- writeRuleText(out, rp);
- fprintf(out, " */\n"); lineno++;
- for(rp2=rp->next; rp2; rp2=rp2->next){
- if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix
- && rp2->codeSuffix==rp->codeSuffix ){
- fprintf(out," case %d: /* ", rp2->iRule);
- writeRuleText(out, rp2);
- fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;
- rp2->codeEmitted = 1;
- }
- }
- emit_code(out,rp,lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- rp->codeEmitted = 1;
- }
- /* Finally, output the default: rule. We choose as the default: all
- ** empty actions. */
- fprintf(out," default:\n"); lineno++;
- for(rp=lemp->rule; rp; rp=rp->next){
- if( rp->codeEmitted ) continue;
- assert( rp->noCode );
- fprintf(out," /* (%d) ", rp->iRule);
- writeRuleText(out, rp);
- if( rp->doesReduce ){
- fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
- }else{
- fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n",
- rp->iRule); lineno++;
- }
- }
- fprintf(out," break;\n"); lineno++;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes if a parse fails */
- tplt_print(out,lemp,lemp->failure,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes when a syntax error occurs */
- tplt_print(out,lemp,lemp->error,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes when the parser accepts its input */
- tplt_print(out,lemp,lemp->accept,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Append any addition code the user desires */
- tplt_print(out,lemp,lemp->extracode,&lineno);
-
- fclose(in);
- fclose(out);
- return;
-}
-
-/* Generate a header file for the parser */
-void ReportHeader(struct lemon *lemp)
-{
- FILE *out, *in;
- const char *prefix;
- char line[LINESIZE];
- char pattern[LINESIZE];
- int i;
-
- if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
- else prefix = "";
- in = file_open(lemp,".h","rb");
- if( in ){
- int nextChar;
- for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
- lemon_sprintf(pattern,"#define %s%-30s %3d\n",
- prefix,lemp->symbols[i]->name,i);
- if( strcmp(line,pattern) ) break;
- }
- nextChar = fgetc(in);
- fclose(in);
- if( i==lemp->nterminal && nextChar==EOF ){
- /* No change in the file. Don't rewrite it. */
- return;
- }
- }
- out = file_open(lemp,".h","wb");
- if( out ){
- for(i=1; i<lemp->nterminal; i++){
- fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i);
- }
- fclose(out);
- }
- return;
-}
-
-/* Reduce the size of the action tables, if possible, by making use
-** of defaults.
-**
-** In this version, we take the most frequent REDUCE action and make
-** it the default. Except, there is no default if the wildcard token
-** is a possible look-ahead.
-*/
-void CompressTables(struct lemon *lemp)
-{
- struct state *stp;
- struct action *ap, *ap2, *nextap;
- struct rule *rp, *rp2, *rbest;
- int nbest, n;
- int i;
- int usesWildcard;
-
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- nbest = 0;
- rbest = 0;
- usesWildcard = 0;
-
- for(ap=stp->ap; ap; ap=ap->next){
- if( ap->type==SHIFT && ap->sp==lemp->wildcard ){
- usesWildcard = 1;
- }
- if( ap->type!=REDUCE ) continue;
- rp = ap->x.rp;
- if( rp->lhsStart ) continue;
- if( rp==rbest ) continue;
- n = 1;
- for(ap2=ap->next; ap2; ap2=ap2->next){
- if( ap2->type!=REDUCE ) continue;
- rp2 = ap2->x.rp;
- if( rp2==rbest ) continue;
- if( rp2==rp ) n++;
- }
- if( n>nbest ){
- nbest = n;
- rbest = rp;
- }
- }
-
- /* Do not make a default if the number of rules to default
- ** is not at least 1 or if the wildcard token is a possible
- ** lookahead.
- */
- if( nbest<1 || usesWildcard ) continue;
-
-
- /* Combine matching REDUCE actions into a single default */
- for(ap=stp->ap; ap; ap=ap->next){
- if( ap->type==REDUCE && ap->x.rp==rbest ) break;
- }
- assert( ap );
- ap->sp = Symbol_new("{default}");
- for(ap=ap->next; ap; ap=ap->next){
- if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
- }
- stp->ap = Action_sort(stp->ap);
-
- for(ap=stp->ap; ap; ap=ap->next){
- if( ap->type==SHIFT ) break;
- if( ap->type==REDUCE && ap->x.rp!=rbest ) break;
- }
- if( ap==0 ){
- stp->autoReduce = 1;
- stp->pDfltReduce = rbest;
- }
- }
-
- /* Make a second pass over all states and actions. Convert
- ** every action that is a SHIFT to an autoReduce state into
- ** a SHIFTREDUCE action.
- */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(ap=stp->ap; ap; ap=ap->next){
- struct state *pNextState;
- if( ap->type!=SHIFT ) continue;
- pNextState = ap->x.stp;
- if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){
- ap->type = SHIFTREDUCE;
- ap->x.rp = pNextState->pDfltReduce;
- }
- }
- }
-
- /* If a SHIFTREDUCE action specifies a rule that has a single RHS term
- ** (meaning that the SHIFTREDUCE will land back in the state where it
- ** started) and if there is no C-code associated with the reduce action,
- ** then we can go ahead and convert the action to be the same as the
- ** action for the RHS of the rule.
- */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(ap=stp->ap; ap; ap=nextap){
- nextap = ap->next;
- if( ap->type!=SHIFTREDUCE ) continue;
- rp = ap->x.rp;
- if( rp->noCode==0 ) continue;
- if( rp->nrhs!=1 ) continue;
-#if 1
- /* Only apply this optimization to non-terminals. It would be OK to
- ** apply it to terminal symbols too, but that makes the parser tables
- ** larger. */
- if( ap->sp->index<lemp->nterminal ) continue;
-#endif
- /* If we reach this point, it means the optimization can be applied */
- nextap = ap;
- for(ap2=stp->ap; ap2 && (ap2==ap || ap2->sp!=rp->lhs); ap2=ap2->next){}
- assert( ap2!=0 );
- ap->spOpt = ap2->sp;
- ap->type = ap2->type;
- ap->x = ap2->x;
- }
- }
-}
-
-
-/*
-** Compare two states for sorting purposes. The smaller state is the
-** one with the most non-terminal actions. If they have the same number
-** of non-terminal actions, then the smaller is the one with the most
-** token actions.
-*/
-static int stateResortCompare(const void *a, const void *b){
- const struct state *pA = *(const struct state**)a;
- const struct state *pB = *(const struct state**)b;
- int n;
-
- n = pB->nNtAct - pA->nNtAct;
- if( n==0 ){
- n = pB->nTknAct - pA->nTknAct;
- if( n==0 ){
- n = pB->statenum - pA->statenum;
- }
- }
- assert( n!=0 );
- return n;
-}
-
-
-/*
-** Renumber and resort states so that states with fewer choices
-** occur at the end. Except, keep state 0 as the first state.
-*/
-void ResortStates(struct lemon *lemp)
-{
- int i;
- struct state *stp;
- struct action *ap;
-
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- stp->nTknAct = stp->nNtAct = 0;
- stp->iDfltReduce = -1; /* Init dflt action to "syntax error" */
- stp->iTknOfst = NO_OFFSET;
- stp->iNtOfst = NO_OFFSET;
- for(ap=stp->ap; ap; ap=ap->next){
- int iAction = compute_action(lemp,ap);
- if( iAction>=0 ){
- if( ap->sp->index<lemp->nterminal ){
- stp->nTknAct++;
- }else if( ap->sp->index<lemp->nsymbol ){
- stp->nNtAct++;
- }else{
- assert( stp->autoReduce==0 || stp->pDfltReduce==ap->x.rp );
- stp->iDfltReduce = iAction;
- }
- }
- }
- }
- qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]),
- stateResortCompare);
- for(i=0; i<lemp->nstate; i++){
- lemp->sorted[i]->statenum = i;
- }
- lemp->nxstate = lemp->nstate;
- while( lemp->nxstate>1 && lemp->sorted[lemp->nxstate-1]->autoReduce ){
- lemp->nxstate--;
- }
-}
-
-
-/***************** From the file "set.c" ************************************/
-/*
-** Set manipulation routines for the LEMON parser generator.
-*/
-
-static int size = 0;
-
-/* Set the set size */
-void SetSize(int n)
-{
- size = n+1;
-}
-
-/* Allocate a new set */
-char *SetNew(void){
- char *s;
- s = (char*)calloc( size, 1);
- if( s==0 ){
- extern void memory_error();
- memory_error();
- }
- return s;
-}
-
-/* Deallocate a set */
-void SetFree(char *s)
-{
- free(s);
-}
-
-/* Add a new element to the set. Return TRUE if the element was added
-** and FALSE if it was already there. */
-int SetAdd(char *s, int e)
-{
- int rv;
- assert( e>=0 && e<size );
- rv = s[e];
- s[e] = 1;
- return !rv;
-}
-
-/* Add every element of s2 to s1. Return TRUE if s1 changes. */
-int SetUnion(char *s1, char *s2)
-{
- int i, progress;
- progress = 0;
- for(i=0; i<size; i++){
- if( s2[i]==0 ) continue;
- if( s1[i]==0 ){
- progress = 1;
- s1[i] = 1;
- }
- }
- return progress;
-}
-/********************** From the file "table.c" ****************************/
-/*
-** All code in this file has been automatically generated
-** from a specification in the file
-** "table.q"
-** by the associative array code building program "aagen".
-** Do not edit this file! Instead, edit the specification
-** file, then rerun aagen.
-*/
-/*
-** Code for processing tables in the LEMON parser generator.
-*/
-
-PRIVATE unsigned strhash(const char *x)
-{
- unsigned h = 0;
- while( *x ) h = h*13 + *(x++);
- return h;
-}
-
-/* Works like strdup, sort of. Save a string in malloced memory, but
-** keep strings in a table so that the same string is not in more
-** than one place.
-*/
-const char *Strsafe(const char *y)
-{
- const char *z;
- char *cpy;
-
- if( y==0 ) return 0;
- z = Strsafe_find(y);
- if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){
- lemon_strcpy(cpy,y);
- z = cpy;
- Strsafe_insert(z);
- }
- MemoryCheck(z);
- return z;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x1".
-*/
-struct s_x1 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x1node *tbl; /* The data stored here */
- struct s_x1node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x1".
-*/
-typedef struct s_x1node {
- const char *data; /* The data */
- struct s_x1node *next; /* Next entry with the same hash */
- struct s_x1node **from; /* Previous link */
-} x1node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x1 *x1a;
-
-/* Allocate a new associative array */
-void Strsafe_init(void){
- if( x1a ) return;
- x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
- if( x1a ){
- x1a->size = 1024;
- x1a->count = 0;
- x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*));
- if( x1a->tbl==0 ){
- free(x1a);
- x1a = 0;
- }else{
- int i;
- x1a->ht = (x1node**)&(x1a->tbl[1024]);
- for(i=0; i<1024; i++) x1a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Strsafe_insert(const char *data)
-{
- x1node *np;
- unsigned h;
- unsigned ph;
-
- if( x1a==0 ) return 0;
- ph = strhash(data);
- h = ph & (x1a->size-1);
- np = x1a->ht[h];
- while( np ){
- if( strcmp(np->data,data)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x1a->count>=x1a->size ){
- /* Need to make the hash table bigger */
- int i,arrSize;
- struct s_x1 array;
- array.size = arrSize = x1a->size*2;
- array.count = x1a->count;
- array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*));
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x1node**)&(array.tbl[arrSize]);
- for(i=0; i<arrSize; i++) array.ht[i] = 0;
- for(i=0; i<x1a->count; i++){
- x1node *oldnp, *newnp;
- oldnp = &(x1a->tbl[i]);
- h = strhash(oldnp->data) & (arrSize-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x1a->tbl);
- *x1a = array;
- }
- /* Insert the new data */
- h = ph & (x1a->size-1);
- np = &(x1a->tbl[x1a->count++]);
- np->data = data;
- if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
- np->next = x1a->ht[h];
- x1a->ht[h] = np;
- np->from = &(x1a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-const char *Strsafe_find(const char *key)
-{
- unsigned h;
- x1node *np;
-
- if( x1a==0 ) return 0;
- h = strhash(key) & (x1a->size-1);
- np = x1a->ht[h];
- while( np ){
- if( strcmp(np->data,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return a pointer to the (terminal or nonterminal) symbol "x".
-** Create a new symbol if this is the first time "x" has been seen.
-*/
-struct symbol *Symbol_new(const char *x)
-{
- struct symbol *sp;
-
- sp = Symbol_find(x);
- if( sp==0 ){
- sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
- MemoryCheck(sp);
- sp->name = Strsafe(x);
- sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL;
- sp->rule = 0;
- sp->fallback = 0;
- sp->prec = -1;
- sp->assoc = UNK;
- sp->firstset = 0;
- sp->lambda = LEMON_FALSE;
- sp->destructor = 0;
- sp->destLineno = 0;
- sp->datatype = 0;
- sp->useCnt = 0;
- Symbol_insert(sp,sp->name);
- }
- sp->useCnt++;
- return sp;
-}
-
-/* Compare two symbols for sorting purposes. Return negative,
-** zero, or positive if a is less then, equal to, or greater
-** than b.
-**
-** Symbols that begin with upper case letters (terminals or tokens)
-** must sort before symbols that begin with lower case letters
-** (non-terminals). And MULTITERMINAL symbols (created using the
-** %token_class directive) must sort at the very end. Other than
-** that, the order does not matter.
-**
-** We find experimentally that leaving the symbols in their original
-** order (the order they appeared in the grammar file) gives the
-** smallest parser tables in SQLite.
-*/
-int Symbolcmpp(const void *_a, const void *_b)
-{
- const struct symbol *a = *(const struct symbol **) _a;
- const struct symbol *b = *(const struct symbol **) _b;
- int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1;
- int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1;
- return i1==i2 ? a->index - b->index : i1 - i2;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x2".
-*/
-struct s_x2 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x2node *tbl; /* The data stored here */
- struct s_x2node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x2".
-*/
-typedef struct s_x2node {
- struct symbol *data; /* The data */
- const char *key; /* The key */
- struct s_x2node *next; /* Next entry with the same hash */
- struct s_x2node **from; /* Previous link */
-} x2node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x2 *x2a;
-
-/* Allocate a new associative array */
-void Symbol_init(void){
- if( x2a ) return;
- x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
- if( x2a ){
- x2a->size = 128;
- x2a->count = 0;
- x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*));
- if( x2a->tbl==0 ){
- free(x2a);
- x2a = 0;
- }else{
- int i;
- x2a->ht = (x2node**)&(x2a->tbl[128]);
- for(i=0; i<128; i++) x2a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Symbol_insert(struct symbol *data, const char *key)
-{
- x2node *np;
- unsigned h;
- unsigned ph;
-
- if( x2a==0 ) return 0;
- ph = strhash(key);
- h = ph & (x2a->size-1);
- np = x2a->ht[h];
- while( np ){
- if( strcmp(np->key,key)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x2a->count>=x2a->size ){
- /* Need to make the hash table bigger */
- int i,arrSize;
- struct s_x2 array;
- array.size = arrSize = x2a->size*2;
- array.count = x2a->count;
- array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*));
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x2node**)&(array.tbl[arrSize]);
- for(i=0; i<arrSize; i++) array.ht[i] = 0;
- for(i=0; i<x2a->count; i++){
- x2node *oldnp, *newnp;
- oldnp = &(x2a->tbl[i]);
- h = strhash(oldnp->key) & (arrSize-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->key = oldnp->key;
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x2a->tbl);
- *x2a = array;
- }
- /* Insert the new data */
- h = ph & (x2a->size-1);
- np = &(x2a->tbl[x2a->count++]);
- np->key = key;
- np->data = data;
- if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
- np->next = x2a->ht[h];
- x2a->ht[h] = np;
- np->from = &(x2a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct symbol *Symbol_find(const char *key)
-{
- unsigned h;
- x2node *np;
-
- if( x2a==0 ) return 0;
- h = strhash(key) & (x2a->size-1);
- np = x2a->ht[h];
- while( np ){
- if( strcmp(np->key,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return the n-th data. Return NULL if n is out of range. */
-struct symbol *Symbol_Nth(int n)
-{
- struct symbol *data;
- if( x2a && n>0 && n<=x2a->count ){
- data = x2a->tbl[n-1].data;
- }else{
- data = 0;
- }
- return data;
-}
-
-/* Return the size of the array */
-int Symbol_count()
-{
- return x2a ? x2a->count : 0;
-}
-
-/* Return an array of pointers to all data in the table.
-** The array is obtained from malloc. Return NULL if memory allocation
-** problems, or if the array is empty. */
-struct symbol **Symbol_arrayof()
-{
- struct symbol **array;
- int i,arrSize;
- if( x2a==0 ) return 0;
- arrSize = x2a->count;
- array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *));
- if( array ){
- for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data;
- }
- return array;
-}
-
-/* Compare two configurations */
-int Configcmp(const char *_a,const char *_b)
-{
- const struct config *a = (struct config *) _a;
- const struct config *b = (struct config *) _b;
- int x;
- x = a->rp->index - b->rp->index;
- if( x==0 ) x = a->dot - b->dot;
- return x;
-}
-
-/* Compare two states */
-PRIVATE int statecmp(struct config *a, struct config *b)
-{
- int rc;
- for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
- rc = a->rp->index - b->rp->index;
- if( rc==0 ) rc = a->dot - b->dot;
- }
- if( rc==0 ){
- if( a ) rc = 1;
- if( b ) rc = -1;
- }
- return rc;
-}
-
-/* Hash a state */
-PRIVATE unsigned statehash(struct config *a)
-{
- unsigned h=0;
- while( a ){
- h = h*571 + a->rp->index*37 + a->dot;
- a = a->bp;
- }
- return h;
-}
-
-/* Allocate a new state structure */
-struct state *State_new()
-{
- struct state *newstate;
- newstate = (struct state *)calloc(1, sizeof(struct state) );
- MemoryCheck(newstate);
- return newstate;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x3".
-*/
-struct s_x3 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x3node *tbl; /* The data stored here */
- struct s_x3node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x3".
-*/
-typedef struct s_x3node {
- struct state *data; /* The data */
- struct config *key; /* The key */
- struct s_x3node *next; /* Next entry with the same hash */
- struct s_x3node **from; /* Previous link */
-} x3node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x3 *x3a;
-
-/* Allocate a new associative array */
-void State_init(void){
- if( x3a ) return;
- x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
- if( x3a ){
- x3a->size = 128;
- x3a->count = 0;
- x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*));
- if( x3a->tbl==0 ){
- free(x3a);
- x3a = 0;
- }else{
- int i;
- x3a->ht = (x3node**)&(x3a->tbl[128]);
- for(i=0; i<128; i++) x3a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int State_insert(struct state *data, struct config *key)
-{
- x3node *np;
- unsigned h;
- unsigned ph;
-
- if( x3a==0 ) return 0;
- ph = statehash(key);
- h = ph & (x3a->size-1);
- np = x3a->ht[h];
- while( np ){
- if( statecmp(np->key,key)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x3a->count>=x3a->size ){
- /* Need to make the hash table bigger */
- int i,arrSize;
- struct s_x3 array;
- array.size = arrSize = x3a->size*2;
- array.count = x3a->count;
- array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*));
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x3node**)&(array.tbl[arrSize]);
- for(i=0; i<arrSize; i++) array.ht[i] = 0;
- for(i=0; i<x3a->count; i++){
- x3node *oldnp, *newnp;
- oldnp = &(x3a->tbl[i]);
- h = statehash(oldnp->key) & (arrSize-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->key = oldnp->key;
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x3a->tbl);
- *x3a = array;
- }
- /* Insert the new data */
- h = ph & (x3a->size-1);
- np = &(x3a->tbl[x3a->count++]);
- np->key = key;
- np->data = data;
- if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
- np->next = x3a->ht[h];
- x3a->ht[h] = np;
- np->from = &(x3a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct state *State_find(struct config *key)
-{
- unsigned h;
- x3node *np;
-
- if( x3a==0 ) return 0;
- h = statehash(key) & (x3a->size-1);
- np = x3a->ht[h];
- while( np ){
- if( statecmp(np->key,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return an array of pointers to all data in the table.
-** The array is obtained from malloc. Return NULL if memory allocation
-** problems, or if the array is empty. */
-struct state **State_arrayof(void)
-{
- struct state **array;
- int i,arrSize;
- if( x3a==0 ) return 0;
- arrSize = x3a->count;
- array = (struct state **)calloc(arrSize, sizeof(struct state *));
- if( array ){
- for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data;
- }
- return array;
-}
-
-/* Hash a configuration */
-PRIVATE unsigned confighash(struct config *a)
-{
- unsigned h=0;
- h = h*571 + a->rp->index*37 + a->dot;
- return h;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x4".
-*/
-struct s_x4 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x4node *tbl; /* The data stored here */
- struct s_x4node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x4".
-*/
-typedef struct s_x4node {
- struct config *data; /* The data */
- struct s_x4node *next; /* Next entry with the same hash */
- struct s_x4node **from; /* Previous link */
-} x4node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x4 *x4a;
-
-/* Allocate a new associative array */
-void Configtable_init(void){
- if( x4a ) return;
- x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
- if( x4a ){
- x4a->size = 64;
- x4a->count = 0;
- x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*));
- if( x4a->tbl==0 ){
- free(x4a);
- x4a = 0;
- }else{
- int i;
- x4a->ht = (x4node**)&(x4a->tbl[64]);
- for(i=0; i<64; i++) x4a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Configtable_insert(struct config *data)
-{
- x4node *np;
- unsigned h;
- unsigned ph;
-
- if( x4a==0 ) return 0;
- ph = confighash(data);
- h = ph & (x4a->size-1);
- np = x4a->ht[h];
- while( np ){
- if( Configcmp((const char *) np->data,(const char *) data)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x4a->count>=x4a->size ){
- /* Need to make the hash table bigger */
- int i,arrSize;
- struct s_x4 array;
- array.size = arrSize = x4a->size*2;
- array.count = x4a->count;
- array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*));
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x4node**)&(array.tbl[arrSize]);
- for(i=0; i<arrSize; i++) array.ht[i] = 0;
- for(i=0; i<x4a->count; i++){
- x4node *oldnp, *newnp;
- oldnp = &(x4a->tbl[i]);
- h = confighash(oldnp->data) & (arrSize-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x4a->tbl);
- *x4a = array;
- }
- /* Insert the new data */
- h = ph & (x4a->size-1);
- np = &(x4a->tbl[x4a->count++]);
- np->data = data;
- if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
- np->next = x4a->ht[h];
- x4a->ht[h] = np;
- np->from = &(x4a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct config *Configtable_find(struct config *key)
-{
- int h;
- x4node *np;
-
- if( x4a==0 ) return 0;
- h = confighash(key) & (x4a->size-1);
- np = x4a->ht[h];
- while( np ){
- if( Configcmp((const char *) np->data,(const char *) key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Remove all data from the table. Pass each data to the function "f"
-** as it is removed. ("f" may be null to avoid this step.) */
-void Configtable_clear(int(*f)(struct config *))
-{
- int i;
- if( x4a==0 || x4a->count==0 ) return;
- if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
- for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
- x4a->count = 0;
- return;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/lempar.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/lempar.c
deleted file mode 100644
index 885cefe1435..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/lempar.c
+++ /dev/null
@@ -1,1059 +0,0 @@
-/*
-** 2000-05-29
-**
-** 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.
-**
-*************************************************************************
-** Driver template for the LEMON parser generator.
-**
-** The "lemon" program processes an LALR(1) input grammar file, then uses
-** this template to construct a parser. The "lemon" program inserts text
-** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
-** interstitial "-" characters) contained in this template is changed into
-** the value of the %name directive from the grammar. Otherwise, the content
-** of this template is copied straight through into the generate parser
-** source file.
-**
-** The following is the concatenation of all %include directives from the
-** input grammar file:
-*/
-#include <stdio.h>
-/************ Begin %include sections from the grammar ************************/
-%%
-/**************** End of %include directives **********************************/
-/* These constants specify the various numeric values for terminal symbols
-** in a format understandable to "makeheaders". This section is blank unless
-** "lemon" is run with the "-m" command-line option.
-***************** Begin makeheaders token definitions *************************/
-%%
-/**************** End makeheaders token definitions ***************************/
-
-/* The next sections is a series of control #defines.
-** various aspects of the generated parser.
-** YYCODETYPE is the data type used to store the integer codes
-** that represent terminal and non-terminal symbols.
-** "unsigned char" is used if there are fewer than
-** 256 symbols. Larger types otherwise.
-** YYNOCODE is a number of type YYCODETYPE that is not used for
-** any terminal or nonterminal symbol.
-** YYFALLBACK If defined, this indicates that one or more tokens
-** (also known as: "terminal symbols") have fall-back
-** values which should be used if the original symbol
-** would not parse. This permits keywords to sometimes
-** be used as identifiers, for example.
-** YYACTIONTYPE is the data type used for "action codes" - numbers
-** that indicate what to do in response to the next
-** token.
-** ParseTOKENTYPE is the data type used for minor type for terminal
-** symbols. Background: A "minor type" is a semantic
-** value associated with a terminal or non-terminal
-** symbols. For example, for an "ID" terminal symbol,
-** the minor type might be the name of the identifier.
-** Each non-terminal can have a different minor type.
-** Terminal symbols all have the same minor type, though.
-** This macros defines the minor type for terminal
-** symbols.
-** YYMINORTYPE is the data type used for all minor types.
-** This is typically a union of many types, one of
-** which is ParseTOKENTYPE. The entry in the union
-** for terminal symbols is called "yy0".
-** YYSTACKDEPTH is the maximum depth of the parser's stack. If
-** zero the stack is dynamically sized using realloc()
-** ParseARG_SDECL A static variable declaration for the %extra_argument
-** ParseARG_PDECL A parameter declaration for the %extra_argument
-** ParseARG_PARAM Code to pass %extra_argument as a subroutine parameter
-** ParseARG_STORE Code to store %extra_argument into yypParser
-** ParseARG_FETCH Code to extract %extra_argument from yypParser
-** ParseCTX_* As ParseARG_ except for %extra_context
-** YYERRORSYMBOL is the code number of the error symbol. If not
-** defined, then do no error processing.
-** YYNSTATE the combined number of states.
-** YYNRULE the number of rules in the grammar
-** YYNTOKEN Number of terminal symbols
-** YY_MAX_SHIFT Maximum value for shift actions
-** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
-** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
-** YY_ERROR_ACTION The yy_action[] code for syntax error
-** YY_ACCEPT_ACTION The yy_action[] code for accept
-** YY_NO_ACTION The yy_action[] code for no-op
-** YY_MIN_REDUCE Minimum value for reduce actions
-** YY_MAX_REDUCE Maximum value for reduce actions
-*/
-#ifndef INTERFACE
-# define INTERFACE 1
-#endif
-/************* Begin control #defines *****************************************/
-%%
-/************* End control #defines *******************************************/
-
-/* Define the yytestcase() macro to be a no-op if is not already defined
-** otherwise.
-**
-** Applications can choose to define yytestcase() in the %include section
-** to a macro that can assist in verifying code coverage. For production
-** code the yytestcase() macro should be turned off. But it is useful
-** for testing.
-*/
-#ifndef yytestcase
-# define yytestcase(X)
-#endif
-
-
-/* Next are the tables used to determine what action to take based on the
-** current state and lookahead token. These tables are used to implement
-** functions that take a state number and lookahead value and return an
-** action integer.
-**
-** Suppose the action integer is N. Then the action is determined as
-** follows
-**
-** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
-** token onto the stack and goto state N.
-**
-** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
-** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
-**
-** N == YY_ERROR_ACTION A syntax error has occurred.
-**
-** N == YY_ACCEPT_ACTION The parser accepts its input.
-**
-** N == YY_NO_ACTION No such action. Denotes unused
-** slots in the yy_action[] table.
-**
-** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
-** and YY_MAX_REDUCE
-**
-** The action table is constructed as a single large table named yy_action[].
-** Given state S and lookahead X, the action is computed as either:
-**
-** (A) N = yy_action[ yy_shift_ofst[S] + X ]
-** (B) N = yy_default[S]
-**
-** The (A) formula is preferred. The B formula is used instead if
-** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X.
-**
-** The formulas above are for computing the action when the lookahead is
-** a terminal symbol. If the lookahead is a non-terminal (as occurs after
-** a reduce action) then the yy_reduce_ofst[] array is used in place of
-** the yy_shift_ofst[] array.
-**
-** The following are the tables generated in this section:
-**
-** yy_action[] A single table containing all actions.
-** yy_lookahead[] A table containing the lookahead for each entry in
-** yy_action. Used to detect hash collisions.
-** yy_shift_ofst[] For each state, the offset into yy_action for
-** shifting terminals.
-** yy_reduce_ofst[] For each state, the offset into yy_action for
-** shifting non-terminals after a reduce.
-** yy_default[] Default action for each state.
-**
-*********** Begin parsing tables **********************************************/
-%%
-/********** End of lemon-generated parsing tables *****************************/
-
-/* The next table maps tokens (terminal symbols) into fallback tokens.
-** If a construct like the following:
-**
-** %fallback ID X Y Z.
-**
-** appears in the grammar, then ID becomes a fallback token for X, Y,
-** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
-** but it does not parse, the type of the token is changed to ID and
-** the parse is retried before an error is thrown.
-**
-** This feature can be used, for example, to cause some keywords in a language
-** to revert to identifiers if they keyword does not apply in the context where
-** it appears.
-*/
-#ifdef YYFALLBACK
-static const YYCODETYPE yyFallback[] = {
-%%
-};
-#endif /* YYFALLBACK */
-
-/* The following structure represents a single element of the
-** parser's stack. Information stored includes:
-**
-** + The state number for the parser at this level of the stack.
-**
-** + The value of the token stored at this level of the stack.
-** (In other words, the "major" token.)
-**
-** + The semantic value stored at this level of the stack. This is
-** the information used by the action routines in the grammar.
-** It is sometimes called the "minor" token.
-**
-** After the "shift" half of a SHIFTREDUCE action, the stateno field
-** actually contains the reduce action for the second half of the
-** SHIFTREDUCE.
-*/
-struct yyStackEntry {
- YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
- YYCODETYPE major; /* The major token value. This is the code
- ** number for the token at this stack level */
- YYMINORTYPE minor; /* The user-supplied minor token value. This
- ** is the value of the token */
-};
-typedef struct yyStackEntry yyStackEntry;
-
-/* The state of the parser is completely contained in an instance of
-** the following structure */
-struct yyParser {
- yyStackEntry *yytos; /* Pointer to top element of the stack */
-#ifdef YYTRACKMAXSTACKDEPTH
- int yyhwm; /* High-water mark of the stack */
-#endif
-#ifndef YYNOERRORRECOVERY
- int yyerrcnt; /* Shifts left before out of the error */
-#endif
- ParseARG_SDECL /* A place to hold %extra_argument */
- ParseCTX_SDECL /* A place to hold %extra_context */
-#if YYSTACKDEPTH<=0
- int yystksz; /* Current side of the stack */
- yyStackEntry *yystack; /* The parser's stack */
- yyStackEntry yystk0; /* First stack entry */
-#else
- yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
- yyStackEntry *yystackEnd; /* Last entry in the stack */
-#endif
-};
-typedef struct yyParser yyParser;
-
-#ifndef NDEBUG
-#include <stdio.h>
-static FILE *yyTraceFILE = 0;
-static char *yyTracePrompt = 0;
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/*
-** Turn parser tracing on by giving a stream to which to write the trace
-** and a prompt to preface each trace message. Tracing is turned off
-** by making either argument NULL
-**
-** Inputs:
-** <ul>
-** <li> A FILE* to which trace output should be written.
-** If NULL, then tracing is turned off.
-** <li> A prefix string written at the beginning of every
-** line of trace output. If NULL, then tracing is
-** turned off.
-** </ul>
-**
-** Outputs:
-** None.
-*/
-void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
- yyTraceFILE = TraceFILE;
- yyTracePrompt = zTracePrompt;
- if( yyTraceFILE==0 ) yyTracePrompt = 0;
- else if( yyTracePrompt==0 ) yyTraceFILE = 0;
-}
-#endif /* NDEBUG */
-
-#if defined(YYCOVERAGE) || !defined(NDEBUG)
-/* For tracing shifts, the names of all terminals and nonterminals
-** are required. The following table supplies these names */
-static const char *const yyTokenName[] = {
-%%
-};
-#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
-
-#ifndef NDEBUG
-/* For tracing reduce actions, the names of all rules are required.
-*/
-static const char *const yyRuleName[] = {
-%%
-};
-#endif /* NDEBUG */
-
-
-#if YYSTACKDEPTH<=0
-/*
-** Try to increase the size of the parser stack. Return the number
-** of errors. Return 0 on success.
-*/
-static int yyGrowStack(yyParser *p){
- int newSize;
- int idx;
- yyStackEntry *pNew;
-
- newSize = p->yystksz*2 + 100;
- idx = p->yytos ? (int)(p->yytos - p->yystack) : 0;
- if( p->yystack==&p->yystk0 ){
- pNew = malloc(newSize*sizeof(pNew[0]));
- if( pNew ) pNew[0] = p->yystk0;
- }else{
- pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
- }
- if( pNew ){
- p->yystack = pNew;
- p->yytos = &p->yystack[idx];
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
- yyTracePrompt, p->yystksz, newSize);
- }
-#endif
- p->yystksz = newSize;
- }
- return pNew==0;
-}
-#endif
-
-/* Datatype of the argument to the memory allocated passed as the
-** second argument to ParseAlloc() below. This can be changed by
-** putting an appropriate #define in the %include section of the input
-** grammar.
-*/
-#ifndef YYMALLOCARGTYPE
-# define YYMALLOCARGTYPE size_t
-#endif
-
-/* Initialize a new parser that has already been allocated.
-*/
-void ParseInit(void *yypRawParser ParseCTX_PDECL){
- yyParser *yypParser = (yyParser*)yypRawParser;
- ParseCTX_STORE
-#ifdef YYTRACKMAXSTACKDEPTH
- yypParser->yyhwm = 0;
-#endif
-#if YYSTACKDEPTH<=0
- yypParser->yytos = NULL;
- yypParser->yystack = NULL;
- yypParser->yystksz = 0;
- if( yyGrowStack(yypParser) ){
- yypParser->yystack = &yypParser->yystk0;
- yypParser->yystksz = 1;
- }
-#endif
-#ifndef YYNOERRORRECOVERY
- yypParser->yyerrcnt = -1;
-#endif
- yypParser->yytos = yypParser->yystack;
- yypParser->yystack[0].stateno = 0;
- yypParser->yystack[0].major = 0;
-#if YYSTACKDEPTH>0
- yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
-#endif
-}
-
-#ifndef Parse_ENGINEALWAYSONSTACK
-/*
-** This function allocates a new parser.
-** The only argument is a pointer to a function which works like
-** malloc.
-**
-** Inputs:
-** A pointer to the function used to allocate memory.
-**
-** Outputs:
-** A pointer to a parser. This pointer is used in subsequent calls
-** to Parse and ParseFree.
-*/
-void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){
- yyParser *yypParser;
- yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
- if( yypParser ){
- ParseCTX_STORE
- ParseInit(yypParser ParseCTX_PARAM);
- }
- return (void*)yypParser;
-}
-#endif /* Parse_ENGINEALWAYSONSTACK */
-
-
-/* The following function deletes the "minor type" or semantic value
-** associated with a symbol. The symbol can be either a terminal
-** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
-** a pointer to the value to be deleted. The code used to do the
-** deletions is derived from the %destructor and/or %token_destructor
-** directives of the input grammar.
-*/
-static void yy_destructor(
- yyParser *yypParser, /* The parser */
- YYCODETYPE yymajor, /* Type code for object to destroy */
- YYMINORTYPE *yypminor /* The object to be destroyed */
-){
- ParseARG_FETCH
- ParseCTX_FETCH
- switch( yymajor ){
- /* Here is inserted the actions which take place when a
- ** terminal or non-terminal is destroyed. This can happen
- ** when the symbol is popped from the stack during a
- ** reduce or during error processing or when a parser is
- ** being destroyed before it is finished parsing.
- **
- ** Note: during a reduce, the only symbols destroyed are those
- ** which appear on the RHS of the rule, but which are *not* used
- ** inside the C code.
- */
-/********* Begin destructor definitions ***************************************/
-%%
-/********* End destructor definitions *****************************************/
- default: break; /* If no destructor action specified: do nothing */
- }
-}
-
-/*
-** Pop the parser's stack once.
-**
-** If there is a destructor routine associated with the token which
-** is popped from the stack, then call it.
-*/
-static void yy_pop_parser_stack(yyParser *pParser){
- yyStackEntry *yytos;
- assert( pParser->yytos!=0 );
- assert( pParser->yytos > pParser->yystack );
- yytos = pParser->yytos--;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sPopping %s\n",
- yyTracePrompt,
- yyTokenName[yytos->major]);
- }
-#endif
- yy_destructor(pParser, yytos->major, &yytos->minor);
-}
-
-/*
-** Clear all secondary memory allocations from the parser
-*/
-void ParseFinalize(void *p){
- yyParser *pParser = (yyParser*)p;
- while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
-#if YYSTACKDEPTH<=0
- if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
-#endif
-}
-
-#ifndef Parse_ENGINEALWAYSONSTACK
-/*
-** Deallocate and destroy a parser. Destructors are called for
-** all stack elements before shutting the parser down.
-**
-** If the YYPARSEFREENEVERNULL macro exists (for example because it
-** is defined in a %include section of the input grammar) then it is
-** assumed that the input pointer is never NULL.
-*/
-void ParseFree(
- void *p, /* The parser to be deleted */
- void (*freeProc)(void*) /* Function used to reclaim memory */
-){
-#ifndef YYPARSEFREENEVERNULL
- if( p==0 ) return;
-#endif
- ParseFinalize(p);
- (*freeProc)(p);
-}
-#endif /* Parse_ENGINEALWAYSONSTACK */
-
-/*
-** Return the peak depth of the stack for a parser.
-*/
-#ifdef YYTRACKMAXSTACKDEPTH
-int ParseStackPeak(void *p){
- yyParser *pParser = (yyParser*)p;
- return pParser->yyhwm;
-}
-#endif
-
-/* This array of booleans keeps track of the parser statement
-** coverage. The element yycoverage[X][Y] is set when the parser
-** is in state X and has a lookahead token Y. In a well-tested
-** systems, every element of this matrix should end up being set.
-*/
-#if defined(YYCOVERAGE)
-static unsigned char yycoverage[YYNSTATE][YYNTOKEN];
-#endif
-
-/*
-** Write into out a description of every state/lookahead combination that
-**
-** (1) has not been used by the parser, and
-** (2) is not a syntax error.
-**
-** Return the number of missed state/lookahead combinations.
-*/
-#if defined(YYCOVERAGE)
-int ParseCoverage(FILE *out){
- int stateno, iLookAhead, i;
- int nMissed = 0;
- for(stateno=0; stateno<YYNSTATE; stateno++){
- i = yy_shift_ofst[stateno];
- for(iLookAhead=0; iLookAhead<YYNTOKEN; iLookAhead++){
- if( yy_lookahead[i+iLookAhead]!=iLookAhead ) continue;
- if( yycoverage[stateno][iLookAhead]==0 ) nMissed++;
- if( out ){
- fprintf(out,"State %d lookahead %s %s\n", stateno,
- yyTokenName[iLookAhead],
- yycoverage[stateno][iLookAhead] ? "ok" : "missed");
- }
- }
- }
- return nMissed;
-}
-#endif
-
-/*
-** Find the appropriate action for a parser given the terminal
-** look-ahead token iLookAhead.
-*/
-static YYACTIONTYPE yy_find_shift_action(
- YYCODETYPE iLookAhead, /* The look-ahead token */
- YYACTIONTYPE stateno /* Current state number */
-){
- int i;
-
- if( stateno>YY_MAX_SHIFT ) return stateno;
- assert( stateno <= YY_SHIFT_COUNT );
-#if defined(YYCOVERAGE)
- yycoverage[stateno][iLookAhead] = 1;
-#endif
- do{
- i = yy_shift_ofst[stateno];
- assert( i>=0 );
- assert( i+YYNTOKEN<=(int)sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) );
- assert( iLookAhead!=YYNOCODE );
- assert( iLookAhead < YYNTOKEN );
- i += iLookAhead;
- if( yy_lookahead[i]!=iLookAhead ){
-#ifdef YYFALLBACK
- YYCODETYPE iFallback; /* Fallback token */
- if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
- && (iFallback = yyFallback[iLookAhead])!=0 ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
- yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
- }
-#endif
- assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
- iLookAhead = iFallback;
- continue;
- }
-#endif
-#ifdef YYWILDCARD
- {
- int j = i - iLookAhead + YYWILDCARD;
- if(
-#if YY_SHIFT_MIN+YYWILDCARD<0
- j>=0 &&
-#endif
-#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
- j<YY_ACTTAB_COUNT &&
-#endif
- yy_lookahead[j]==YYWILDCARD && iLookAhead>0
- ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
- yyTracePrompt, yyTokenName[iLookAhead],
- yyTokenName[YYWILDCARD]);
- }
-#endif /* NDEBUG */
- return yy_action[j];
- }
- }
-#endif /* YYWILDCARD */
- return yy_default[stateno];
- }else{
- return yy_action[i];
- }
- }while(1);
-}
-
-/*
-** Find the appropriate action for a parser given the non-terminal
-** look-ahead token iLookAhead.
-*/
-static int yy_find_reduce_action(
- YYACTIONTYPE stateno, /* Current state number */
- YYCODETYPE iLookAhead /* The look-ahead token */
-){
- int i;
-#ifdef YYERRORSYMBOL
- if( stateno>YY_REDUCE_COUNT ){
- return yy_default[stateno];
- }
-#else
- assert( stateno<=YY_REDUCE_COUNT );
-#endif
- i = yy_reduce_ofst[stateno];
- assert( iLookAhead!=YYNOCODE );
- i += iLookAhead;
-#ifdef YYERRORSYMBOL
- if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
- return yy_default[stateno];
- }
-#else
- assert( i>=0 && i<YY_ACTTAB_COUNT );
- assert( yy_lookahead[i]==iLookAhead );
-#endif
- return yy_action[i];
-}
-
-/*
-** The following routine is called if the stack overflows.
-*/
-static void yyStackOverflow(yyParser *yypParser){
- ParseARG_FETCH
- ParseCTX_FETCH
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will execute if the parser
- ** stack every overflows */
-/******** Begin %stack_overflow code ******************************************/
-%%
-/******** End %stack_overflow code ********************************************/
- ParseARG_STORE /* Suppress warning about unused %extra_argument var */
- ParseCTX_STORE
-}
-
-/*
-** Print tracing information for a SHIFT action
-*/
-#ifndef NDEBUG
-static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){
- if( yyTraceFILE ){
- if( yyNewState<YYNSTATE ){
- fprintf(yyTraceFILE,"%s%s '%s', go to state %d\n",
- yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major],
- yyNewState);
- }else{
- fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n",
- yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major],
- yyNewState - YY_MIN_REDUCE);
- }
- }
-}
-#else
-# define yyTraceShift(X,Y,Z)
-#endif
-
-/*
-** Perform a shift action.
-*/
-static void yy_shift(
- yyParser *yypParser, /* The parser to be shifted */
- YYACTIONTYPE yyNewState, /* The new state to shift in */
- YYCODETYPE yyMajor, /* The major token to shift in */
- ParseTOKENTYPE yyMinor /* The minor token to shift in */
-){
- yyStackEntry *yytos;
- yypParser->yytos++;
-#ifdef YYTRACKMAXSTACKDEPTH
- if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
- yypParser->yyhwm++;
- assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
- }
-#endif
-#if YYSTACKDEPTH>0
- if( yypParser->yytos>yypParser->yystackEnd ){
- yypParser->yytos--;
- yyStackOverflow(yypParser);
- return;
- }
-#else
- if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
- if( yyGrowStack(yypParser) ){
- yypParser->yytos--;
- yyStackOverflow(yypParser);
- return;
- }
- }
-#endif
- if( yyNewState > YY_MAX_SHIFT ){
- yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
- }
- yytos = yypParser->yytos;
- yytos->stateno = yyNewState;
- yytos->major = yyMajor;
- yytos->minor.yy0 = yyMinor;
- yyTraceShift(yypParser, yyNewState, "Shift");
-}
-
-/* The following table contains information about every rule that
-** is used during the reduce.
-*/
-static const struct {
- YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
- signed char nrhs; /* Negative of the number of RHS symbols in the rule */
-} yyRuleInfo[] = {
-%%
-};
-
-static void yy_accept(yyParser*); /* Forward Declaration */
-
-/*
-** Perform a reduce action and the shift that must immediately
-** follow the reduce.
-**
-** The yyLookahead and yyLookaheadToken parameters provide reduce actions
-** access to the lookahead token (if any). The yyLookahead will be YYNOCODE
-** if the lookahead token has already been consumed. As this procedure is
-** only called from one place, optimizing compilers will in-line it, which
-** means that the extra parameters have no performance impact.
-*/
-static YYACTIONTYPE yy_reduce(
- yyParser *yypParser, /* The parser */
- unsigned int yyruleno, /* Number of the rule by which to reduce */
- int yyLookahead, /* Lookahead token, or YYNOCODE if none */
- ParseTOKENTYPE yyLookaheadToken /* Value of the lookahead token */
- ParseCTX_PDECL /* %extra_context */
-){
- int yygoto; /* The next state */
- int yyact; /* The next action */
- yyStackEntry *yymsp; /* The top of the parser's stack */
- int yysize; /* Amount to pop the stack */
- ParseARG_FETCH
- (void)yyLookahead;
- (void)yyLookaheadToken;
- yymsp = yypParser->yytos;
-#ifndef NDEBUG
- if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
- yysize = yyRuleInfo[yyruleno].nrhs;
- if( yysize ){
- fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
- yyTracePrompt,
- yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno);
- }else{
- fprintf(yyTraceFILE, "%sReduce %d [%s].\n",
- yyTracePrompt, yyruleno, yyRuleName[yyruleno]);
- }
- }
-#endif /* NDEBUG */
-
- /* Check that the stack is large enough to grow by a single entry
- ** if the RHS of the rule is empty. This ensures that there is room
- ** enough on the stack to push the LHS value */
- if( yyRuleInfo[yyruleno].nrhs==0 ){
-#ifdef YYTRACKMAXSTACKDEPTH
- if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
- yypParser->yyhwm++;
- assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
- }
-#endif
-#if YYSTACKDEPTH>0
- if( yypParser->yytos>=yypParser->yystackEnd ){
- yyStackOverflow(yypParser);
- /* The call to yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
-#else
- if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
- if( yyGrowStack(yypParser) ){
- yyStackOverflow(yypParser);
- /* The call to yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
- yymsp = yypParser->yytos;
- }
-#endif
- }
-
- switch( yyruleno ){
- /* Beginning here are the reduction cases. A typical example
- ** follows:
- ** case 0:
- ** #line <lineno> <grammarfile>
- ** { ... } // User supplied code
- ** #line <lineno> <thisfile>
- ** break;
- */
-/********** Begin reduce actions **********************************************/
-%%
-/********** End reduce actions ************************************************/
- };
- assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
- yygoto = yyRuleInfo[yyruleno].lhs;
- yysize = yyRuleInfo[yyruleno].nrhs;
- yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
-
- /* There are no SHIFTREDUCE actions on nonterminals because the table
- ** generator has simplified them to pure REDUCE actions. */
- assert( !(yyact>YY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) );
-
- /* It is not possible for a REDUCE to be followed by an error */
- assert( yyact!=YY_ERROR_ACTION );
-
- yymsp += yysize+1;
- yypParser->yytos = yymsp;
- yymsp->stateno = (YYACTIONTYPE)yyact;
- yymsp->major = (YYCODETYPE)yygoto;
- yyTraceShift(yypParser, yyact, "... then shift");
- return yyact;
-}
-
-/*
-** The following code executes when the parse fails
-*/
-#ifndef YYNOERRORRECOVERY
-static void yy_parse_failed(
- yyParser *yypParser /* The parser */
-){
- ParseARG_FETCH
- ParseCTX_FETCH
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will be executed whenever the
- ** parser fails */
-/************ Begin %parse_failure code ***************************************/
-%%
-/************ End %parse_failure code *****************************************/
- ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
- ParseCTX_STORE
-}
-#endif /* YYNOERRORRECOVERY */
-
-/*
-** The following code executes when a syntax error first occurs.
-*/
-static void yy_syntax_error(
- yyParser *yypParser, /* The parser */
- int yymajor, /* The major type of the error token */
- ParseTOKENTYPE yyminor /* The minor type of the error token */
-){
- ParseARG_FETCH
- ParseCTX_FETCH
-#define TOKEN yyminor
-/************ Begin %syntax_error code ****************************************/
-%%
-/************ End %syntax_error code ******************************************/
- ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
- ParseCTX_STORE
-}
-
-/*
-** The following is executed when the parser accepts
-*/
-static void yy_accept(
- yyParser *yypParser /* The parser */
-){
- ParseARG_FETCH
- ParseCTX_FETCH
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
- }
-#endif
-#ifndef YYNOERRORRECOVERY
- yypParser->yyerrcnt = -1;
-#endif
- assert( yypParser->yytos==yypParser->yystack );
- /* Here code is inserted which will be executed whenever the
- ** parser accepts */
-/*********** Begin %parse_accept code *****************************************/
-%%
-/*********** End %parse_accept code *******************************************/
- ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
- ParseCTX_STORE
-}
-
-/* The main parser program.
-** The first argument is a pointer to a structure obtained from
-** "ParseAlloc" which describes the current state of the parser.
-** The second argument is the major token number. The third is
-** the minor token. The fourth optional argument is whatever the
-** user wants (and specified in the grammar) and is available for
-** use by the action routines.
-**
-** Inputs:
-** <ul>
-** <li> A pointer to the parser (an opaque structure.)
-** <li> The major token number.
-** <li> The minor token number.
-** <li> An option argument of a grammar-specified type.
-** </ul>
-**
-** Outputs:
-** None.
-*/
-void Parse(
- void *yyp, /* The parser */
- int yymajor, /* The major token code number */
- ParseTOKENTYPE yyminor /* The value for the token */
- ParseARG_PDECL /* Optional %extra_argument parameter */
-){
- YYMINORTYPE yyminorunion;
- YYACTIONTYPE yyact; /* The parser action. */
-#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
- int yyendofinput; /* True if we are at the end of input */
-#endif
-#ifdef YYERRORSYMBOL
- int yyerrorhit = 0; /* True if yymajor has invoked an error */
-#endif
- yyParser *yypParser = (yyParser*)yyp; /* The parser */
- ParseCTX_FETCH
- ParseARG_STORE
-
- assert( yypParser->yytos!=0 );
-#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
- yyendofinput = (yymajor==0);
-#endif
-
- yyact = yypParser->yytos->stateno;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- if( yyact < YY_MIN_REDUCE ){
- fprintf(yyTraceFILE,"%sInput '%s' in state %d\n",
- yyTracePrompt,yyTokenName[yymajor],yyact);
- }else{
- fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n",
- yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE);
- }
- }
-#endif
-
- do{
- assert( yyact==yypParser->yytos->stateno );
- yyact = yy_find_shift_action(yymajor,yyact);
- if( yyact >= YY_MIN_REDUCE ){
- yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,
- yyminor ParseCTX_PARAM);
- }else if( yyact <= YY_MAX_SHIFTREDUCE ){
- yy_shift(yypParser,yyact,yymajor,yyminor);
-#ifndef YYNOERRORRECOVERY
- yypParser->yyerrcnt--;
-#endif
- break;
- }else if( yyact==YY_ACCEPT_ACTION ){
- yypParser->yytos--;
- yy_accept(yypParser);
- return;
- }else{
- assert( yyact == YY_ERROR_ACTION );
- yyminorunion.yy0 = yyminor;
-#ifdef YYERRORSYMBOL
- int yymx;
-#endif
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
- }
-#endif
-#ifdef YYERRORSYMBOL
- /* A syntax error has occurred.
- ** The response to an error depends upon whether or not the
- ** grammar defines an error token "ERROR".
- **
- ** This is what we do if the grammar does define ERROR:
- **
- ** * Call the %syntax_error function.
- **
- ** * Begin popping the stack until we enter a state where
- ** it is legal to shift the error symbol, then shift
- ** the error symbol.
- **
- ** * Set the error count to three.
- **
- ** * Begin accepting and shifting new tokens. No new error
- ** processing will occur until three tokens have been
- ** shifted successfully.
- **
- */
- if( yypParser->yyerrcnt<0 ){
- yy_syntax_error(yypParser,yymajor,yyminor);
- }
- yymx = yypParser->yytos->major;
- if( yymx==YYERRORSYMBOL || yyerrorhit ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sDiscard input token %s\n",
- yyTracePrompt,yyTokenName[yymajor]);
- }
-#endif
- yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
- yymajor = YYNOCODE;
- }else{
- while( yypParser->yytos >= yypParser->yystack
- && yymx != YYERRORSYMBOL
- && (yyact = yy_find_reduce_action(
- yypParser->yytos->stateno,
- YYERRORSYMBOL)) >= YY_MIN_REDUCE
- ){
- yy_pop_parser_stack(yypParser);
- }
- if( yypParser->yytos < yypParser->yystack || yymajor==0 ){
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- yy_parse_failed(yypParser);
-#ifndef YYNOERRORRECOVERY
- yypParser->yyerrcnt = -1;
-#endif
- yymajor = YYNOCODE;
- }else if( yymx!=YYERRORSYMBOL ){
- yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor);
- }
- }
- yypParser->yyerrcnt = 3;
- yyerrorhit = 1;
- if( yymajor==YYNOCODE ) break;
- yyact = yypParser->yytos->stateno;
-#elif defined(YYNOERRORRECOVERY)
- /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
- ** do any kind of error recovery. Instead, simply invoke the syntax
- ** error routine and continue going as if nothing had happened.
- **
- ** Applications can set this macro (for example inside %include) if
- ** they intend to abandon the parse upon the first syntax error seen.
- */
- yy_syntax_error(yypParser,yymajor, yyminor);
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- break;
-#else /* YYERRORSYMBOL is not defined */
- /* This is what we do if the grammar does not define ERROR:
- **
- ** * Report an error message, and throw away the input token.
- **
- ** * If the input token is $, then fail the parse.
- **
- ** As before, subsequent error messages are suppressed until
- ** three input tokens have been successfully shifted.
- */
- if( yypParser->yyerrcnt<=0 ){
- yy_syntax_error(yypParser,yymajor, yyminor);
- }
- yypParser->yyerrcnt = 3;
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- if( yyendofinput ){
- yy_parse_failed(yypParser);
-#ifndef YYNOERRORRECOVERY
- yypParser->yyerrcnt = -1;
-#endif
- }
- break;
-#endif
- }
- }while( yypParser->yytos>yypParser->yystack );
-#ifndef NDEBUG
- if( yyTraceFILE ){
- yyStackEntry *i;
- char cDiv = '[';
- fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
- for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){
- fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]);
- cDiv = ' ';
- }
- fprintf(yyTraceFILE,"]\n");
- }
-#endif
- return;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/libvers.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/libvers.c
deleted file mode 100644
index 6911dbd07eb..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/libvers.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-** Compile this program against an SQLite library of unknown version
-** and then run this program, and it will print out the SQLite version
-** information.
-*/
-#include <stdio.h>
-
-extern const char *sqlite3_libversion(void);
-extern const char *sqlite3_sourceid(void);
-
-int main(int argc, char **argv){
- printf("SQLite version %s\n", sqlite3_libversion());
- printf("SQLite source %s\n", sqlite3_sourceid());
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/loadfts.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/loadfts.c
deleted file mode 100644
index 0000797b887..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/loadfts.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
-** 2014-07-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 a utility program that will load many disk
-** files (all files under a given directory) into a FTS table. This is
-** used for performance testing of FTS3, FTS4, and FTS5.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <dirent.h>
-#include "sqlite3.h"
-
-/*
-** Implementation of the "readtext(X)" SQL function. The entire content
-** of the file named X is read and returned as a TEXT value. It is assumed
-** the file contains UTF-8 text. NULL is returned if the file does not
-** exist or is unreadable.
-*/
-static void readfileFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zName;
- FILE *in;
- long nIn;
- void *pBuf;
-
- zName = (const char*)sqlite3_value_text(argv[0]);
- if( zName==0 ) return;
- in = fopen(zName, "rb");
- if( in==0 ) return;
- fseek(in, 0, SEEK_END);
- nIn = ftell(in);
- rewind(in);
- pBuf = sqlite3_malloc( nIn );
- if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
- sqlite3_result_text(context, pBuf, nIn, sqlite3_free);
- }else{
- sqlite3_free(pBuf);
- }
- fclose(in);
-}
-
-/*
-** Print usage text for this program and exit.
-*/
-static void showHelp(const char *zArgv0){
- printf("\n"
-"Usage: %s SWITCHES... DB\n"
-"\n"
-" This program opens the database named on the command line and attempts to\n"
-" create an FTS table named \"fts\" with a single column. If successful, it\n"
-" recursively traverses the directory named by the -dir option and inserts\n"
-" the contents of each file into the fts table. All files are assumed to\n"
-" contain UTF-8 text.\n"
-"\n"
-"Switches are:\n"
-" -fts [345] FTS version to use (default=5)\n"
-" -idx [01] Create a mapping from filename to rowid (default=0)\n"
-" -dir <path> Root of directory tree to load data from (default=.)\n"
-" -trans <integer> Number of inserts per transaction (default=1)\n"
-, zArgv0
-);
- exit(1);
-}
-
-/*
-** Exit with a message based on the argument and the current value of errno.
-*/
-static void error_out(const char *zText){
- fprintf(stderr, "%s: %s\n", zText, strerror(errno));
- exit(-1);
-}
-
-/*
-** Exit with a message based on the first argument and the error message
-** currently stored in database handle db.
-*/
-static void sqlite_error_out(const char *zText, sqlite3 *db){
- fprintf(stderr, "%s: %s\n", zText, sqlite3_errmsg(db));
- exit(-1);
-}
-
-/*
-** Context object for visit_file().
-*/
-typedef struct VisitContext VisitContext;
-struct VisitContext {
- int nRowPerTrans;
- sqlite3 *db; /* Database handle */
- sqlite3_stmt *pInsert; /* INSERT INTO fts VALUES(readtext(:1)) */
-};
-
-/*
-** Callback used with traverse(). The first argument points to an object
-** of type VisitContext. This function inserts the contents of the text
-** file zPath into the FTS table.
-*/
-void visit_file(void *pCtx, const char *zPath){
- int rc;
- VisitContext *p = (VisitContext*)pCtx;
- /* printf("%s\n", zPath); */
- sqlite3_bind_text(p->pInsert, 1, zPath, -1, SQLITE_STATIC);
- sqlite3_step(p->pInsert);
- rc = sqlite3_reset(p->pInsert);
- if( rc!=SQLITE_OK ){
- sqlite_error_out("insert", p->db);
- }else if( p->nRowPerTrans>0
- && (sqlite3_last_insert_rowid(p->db) % p->nRowPerTrans)==0
- ){
- sqlite3_exec(p->db, "COMMIT ; BEGIN", 0, 0, 0);
- }
-}
-
-/*
-** Recursively traverse directory zDir. For each file that is not a
-** directory, invoke the supplied callback with its path.
-*/
-static void traverse(
- const char *zDir, /* Directory to traverse */
- void *pCtx, /* First argument passed to callback */
- void (*xCallback)(void*, const char *zPath)
-){
- DIR *d;
- struct dirent *e;
-
- d = opendir(zDir);
- if( d==0 ) error_out("opendir()");
-
- for(e=readdir(d); e; e=readdir(d)){
- if( strcmp(e->d_name, ".")==0 || strcmp(e->d_name, "..")==0 ) continue;
- char *zPath = sqlite3_mprintf("%s/%s", zDir, e->d_name);
- if (e->d_type & DT_DIR) {
- traverse(zPath, pCtx, xCallback);
- }else{
- xCallback(pCtx, zPath);
- }
- sqlite3_free(zPath);
- }
-
- closedir(d);
-}
-
-int main(int argc, char **argv){
- int iFts = 5; /* Value of -fts option */
- int bMap = 0; /* True to create mapping table */
- const char *zDir = "."; /* Directory to scan */
- int i;
- int rc;
- int nRowPerTrans = 0;
- sqlite3 *db;
- char *zSql;
- VisitContext sCtx;
-
- int nCmd = 0;
- char **aCmd = 0;
-
- if( argc % 2 ) showHelp(argv[0]);
-
- for(i=1; i<(argc-1); i+=2){
- char *zOpt = argv[i];
- char *zArg = argv[i+1];
- if( strcmp(zOpt, "-fts")==0 ){
- iFts = atoi(zArg);
- if( iFts!=3 && iFts!=4 && iFts!= 5) showHelp(argv[0]);
- }
- else if( strcmp(zOpt, "-trans")==0 ){
- nRowPerTrans = atoi(zArg);
- }
- else if( strcmp(zOpt, "-idx")==0 ){
- bMap = atoi(zArg);
- if( bMap!=0 && bMap!=1 ) showHelp(argv[0]);
- }
- else if( strcmp(zOpt, "-dir")==0 ){
- zDir = zArg;
- }
- else if( strcmp(zOpt, "-special")==0 ){
- nCmd++;
- aCmd = sqlite3_realloc(aCmd, sizeof(char*) * nCmd);
- aCmd[nCmd-1] = zArg;
- }
- else{
- showHelp(argv[0]);
- }
- }
-
- /* Open the database file */
- rc = sqlite3_open(argv[argc-1], &db);
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_open()", db);
-
- rc = sqlite3_create_function(db, "readtext", 1, SQLITE_UTF8, 0,
- readfileFunc, 0, 0);
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_create_function()", db);
-
- /* Create the FTS table */
- zSql = sqlite3_mprintf("CREATE VIRTUAL TABLE fts USING fts%d(content)", iFts);
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_exec(1)", db);
- sqlite3_free(zSql);
-
- for(i=0; i<nCmd; i++){
- zSql = sqlite3_mprintf("INSERT INTO fts(fts) VALUES(%Q)", aCmd[i]);
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_exec(1)", db);
- sqlite3_free(zSql);
- }
-
- /* Compile the INSERT statement to write data to the FTS table. */
- memset(&sCtx, 0, sizeof(VisitContext));
- sCtx.db = db;
- sCtx.nRowPerTrans = nRowPerTrans;
- rc = sqlite3_prepare_v2(db,
- "INSERT INTO fts VALUES(readtext(?))", -1, &sCtx.pInsert, 0
- );
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_prepare_v2(1)", db);
-
- /* Load all files in the directory hierarchy into the FTS table. */
- if( sCtx.nRowPerTrans>0 ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
- traverse(zDir, (void*)&sCtx, visit_file);
- if( sCtx.nRowPerTrans>0 ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
-
- /* Clean up and exit. */
- sqlite3_finalize(sCtx.pInsert);
- sqlite3_close(db);
- sqlite3_free(aCmd);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/logest.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/logest.c
deleted file mode 100644
index e936e02cbee..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/logest.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-** 2013-06-10
-**
-** 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 contains a simple command-line utility for converting from
-** integers and LogEst values and back again and for doing simple
-** arithmetic operations (multiple and add) on LogEst values.
-**
-** Usage:
-**
-** ./LogEst ARGS
-**
-** See the showHelp() routine for a description of valid arguments.
-** Examples:
-**
-** To convert 123 from LogEst to integer:
-**
-** ./LogEst ^123
-**
-** To convert 123456 from integer to LogEst:
-**
-** ./LogEst 123456
-**
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>
-#include "sqlite3.h"
-
-typedef short int LogEst; /* 10 times log2() */
-
-LogEst logEstMultiply(LogEst a, LogEst b){ return a+b; }
-LogEst logEstAdd(LogEst a, LogEst b){
- static const unsigned char x[] = {
- 10, 10, /* 0,1 */
- 9, 9, /* 2,3 */
- 8, 8, /* 4,5 */
- 7, 7, 7, /* 6,7,8 */
- 6, 6, 6, /* 9,10,11 */
- 5, 5, 5, /* 12-14 */
- 4, 4, 4, 4, /* 15-18 */
- 3, 3, 3, 3, 3, 3, /* 19-24 */
- 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
- };
- if( a<b ){ LogEst t = a; a = b; b = t; }
- if( a>b+49 ) return a;
- if( a>b+31 ) return a+1;
- return a+x[a-b];
-}
-LogEst logEstFromInteger(sqlite3_uint64 x){
- static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
- LogEst y = 40;
- if( x<8 ){
- if( x<2 ) return 0;
- while( x<8 ){ y -= 10; x <<= 1; }
- }else{
- while( x>255 ){ y += 40; x >>= 4; }
- while( x>15 ){ y += 10; x >>= 1; }
- }
- return a[x&7] + y - 10;
-}
-static sqlite3_uint64 logEstToInt(LogEst x){
- sqlite3_uint64 n;
- if( x<10 ) return 1;
- n = x%10;
- x /= 10;
- if( n>=5 ) n -= 2;
- else if( n>=1 ) n -= 1;
- if( x>=3 ) return (n+8)<<(x-3);
- return (n+8)>>(3-x);
-}
-static LogEst logEstFromDouble(double x){
- sqlite3_uint64 a;
- LogEst e;
- assert( sizeof(x)==8 && sizeof(a)==8 );
- if( x<=0.0 ) return -32768;
- if( x<0.01 ) return -logEstFromDouble(1.0/x);
- if( x<1.0 ) return logEstFromDouble(100.0*x) - 66;
- if( x<1024.0 ) return logEstFromInteger((sqlite3_uint64)(1024.0*x)) - 100;
- if( x<=2000000000.0 ) return logEstFromInteger((sqlite3_uint64)x);
- memcpy(&a, &x, 8);
- e = (a>>52) - 1022;
- return e*10;
-}
-
-int isInteger(const char *z){
- while( z[0]>='0' && z[0]<='9' ) z++;
- return z[0]==0;
-}
-
-int isFloat(const char *z){
- char c;
- while( ((c=z[0])>='0' && c<='9') || c=='.' || c=='E' || c=='e'
- || c=='+' || c=='-' ) z++;
- return z[0]==0;
-}
-
-static void showHelp(const char *zArgv0){
- printf("Usage: %s ARGS...\n", zArgv0);
- printf("Arguments:\n"
- " NUM Convert NUM from integer to LogEst and push onto the stack\n"
- " ^NUM Interpret NUM as a LogEst and push onto stack\n"
- " x Multiple the top two elements of the stack\n"
- " + Add the top two elements of the stack\n"
- " dup Dupliate the top element on the stack\n"
- " inv Take the reciprocal of the top of stack. N = 1/N.\n"
- " log Find the LogEst of the number on top of stack\n"
- " nlogn Compute NlogN where N is the top of stack\n"
- );
- exit(1);
-}
-
-int main(int argc, char **argv){
- int i;
- int n = 0;
- LogEst a[100];
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( strcmp(z,"+")==0 ){
- if( n>=2 ){
- a[n-2] = logEstAdd(a[n-2],a[n-1]);
- n--;
- }
- }else if( strcmp(z,"x")==0 ){
- if( n>=2 ){
- a[n-2] = logEstMultiply(a[n-2],a[n-1]);
- n--;
- }
- }else if( strcmp(z,"dup")==0 ){
- if( n>0 ){
- a[n] = a[n-1];
- n++;
- }
- }else if( strcmp(z,"log")==0 ){
- if( n>0 ) a[n-1] = logEstFromInteger(a[n-1]) - 33;
- }else if( strcmp(z,"nlogn")==0 ){
- if( n>0 ) a[n-1] += logEstFromInteger(a[n-1]) - 33;
- }else if( strcmp(z,"inv")==0 ){
- if( n>0 ) a[n-1] = -a[n-1];
- }else if( z[0]=='^' ){
- a[n++] = (LogEst)atoi(z+1);
- }else if( isInteger(z) ){
- a[n++] = logEstFromInteger(atoi(z));
- }else if( isFloat(z) && z[0]!='-' ){
- a[n++] = logEstFromDouble(atof(z));
- }else{
- showHelp(argv[0]);
- }
- }
- for(i=n-1; i>=0; i--){
- if( a[i]<-40 ){
- printf("%5d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i]));
- }else if( a[i]<10 ){
- printf("%5d (%f)\n", a[i], logEstToInt(a[i]+100)/1024.0);
- }else{
- sqlite3_uint64 x = logEstToInt(a[i]+100)*100/1024;
- printf("%5d (%lld.%02lld)\n", a[i], x/100, x%100);
- }
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/max-limits.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/max-limits.c
deleted file mode 100644
index d019974426d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/max-limits.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-** Link this program against an SQLite library of unknown provenance in order
-** to display the compile-time maximum values for various settings.
-*/
-#include "sqlite3.h"
-#include <stdio.h>
-
-static const struct {
- int eCode;
- char *zName;
-} aLimit[] = {
- { SQLITE_LIMIT_LENGTH, "SQLITE_MAX_LENGTH" },
- { SQLITE_LIMIT_SQL_LENGTH, "SQLITE_MAX_SQL_LENGTH" },
- { SQLITE_LIMIT_COLUMN, "SQLITE_MAX_COLUMN" },
- { SQLITE_LIMIT_EXPR_DEPTH, "SQLITE_MAX_EXPR_DEPTH" },
- { SQLITE_LIMIT_COMPOUND_SELECT, "SQLITE_MAX_COMPOUND_SELECT" },
- { SQLITE_LIMIT_VDBE_OP, "SQLITE_MAX_VDBE_OP" },
- { SQLITE_LIMIT_FUNCTION_ARG, "SQLITE_MAX_FUNCTION_ARG" },
- { SQLITE_LIMIT_ATTACHED, "SQLITE_MAX_ATTACHED" },
- { SQLITE_LIMIT_LIKE_PATTERN_LENGTH, "SQLITE_MAX_LIKE_PATTERN_LENGTH" },
- { SQLITE_LIMIT_VARIABLE_NUMBER, "SQLITE_MAX_VARIABLE_NUMBER" },
- { SQLITE_LIMIT_TRIGGER_DEPTH, "SQLITE_MAX_TRIGGER_DEPTH" },
- { SQLITE_LIMIT_WORKER_THREADS, "SQLITE_MAX_WORKER_THREADS" },
-};
-
-static int maxLimit(sqlite3 *db, int eCode){
- int iOrig = sqlite3_limit(db, eCode, 0x7fffffff);
- return sqlite3_limit(db, eCode, iOrig);
-}
-
-int main(int argc, char **argv){
- sqlite3 *db;
- int j, rc;
- rc = sqlite3_open(":memory:", &db);
- if( rc==SQLITE_OK ){
- for(j=0; j<sizeof(aLimit)/sizeof(aLimit[0]); j++){
- printf("%-35s %10d\n", aLimit[j].zName, maxLimit(db, aLimit[j].eCode));
- }
- sqlite3_close(db);
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkautoconfamal.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkautoconfamal.sh
deleted file mode 100644
index 7cd7da35f67..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkautoconfamal.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/sh
-# This script is used to build the amalgamation autoconf package.
-# It assumes the following:
-#
-# 1. The files "sqlite3.c", "sqlite3.h" and "sqlite3ext.h"
-# are available in the current directory.
-#
-# 2. Variable $TOP is set to the full path of the root directory
-# of the SQLite source tree.
-#
-# 3. There is nothing of value in the ./mkpkg_tmp_dir directory.
-# This is important, as the script executes "rm -rf ./mkpkg_tmp_dir".
-#
-
-
-# Bail out of the script if any command returns a non-zero exit
-# status. Or if the script tries to use an unset variable. These
-# may fail for old /bin/sh interpreters.
-#
-set -e
-set -u
-
-TMPSPACE=./mkpkg_tmp_dir
-VERSION=`cat $TOP/VERSION`
-HASH=`sed 's/^\(..........\).*/\1/' $TOP/manifest.uuid`
-DATETIME=`grep '^D' $TOP/manifest | sed -e 's/[^0-9]//g' -e 's/\(............\).*/\1/'`
-
-# If this script is given an argument of --snapshot, then generate a
-# snapshot tarball named for the current checkout SHA1 hash, rather than
-# the version number.
-#
-if test "$#" -ge 1 -a x$1 != x--snapshot
-then
- # Set global variable $ARTIFACT to the "3xxyyzz" string incorporated
- # into artifact filenames. And $VERSION2 to the "3.x.y[.z]" form.
- xx=`echo $VERSION|sed 's/3\.\([0-9]*\)\..*/\1/'`
- yy=`echo $VERSION|sed 's/3\.[^.]*\.\([0-9]*\).*/\1/'`
- zz=0
- set +e
- zz=`echo $VERSION|sed 's/3\.[^.]*\.[^.]*\.\([0-9]*\).*/\1/'|grep -v '\.'`
- set -e
- TARBALLNAME=`printf "sqlite-autoconf-3%.2d%.2d%.2d" $xx $yy $zz`
-else
- TARBALLNAME=sqlite-snapshot-$DATETIME
-fi
-
-rm -rf $TMPSPACE
-cp -R $TOP/autoconf $TMPSPACE
-cp sqlite3.c $TMPSPACE
-cp sqlite3.h $TMPSPACE
-cp sqlite3ext.h $TMPSPACE
-cp $TOP/sqlite3.1 $TMPSPACE
-cp $TOP/sqlite3.pc.in $TMPSPACE
-cp shell.c $TMPSPACE
-cp $TOP/src/sqlite3.rc $TMPSPACE
-cp $TOP/tool/Replace.cs $TMPSPACE
-
-cat $TMPSPACE/configure.ac |
-sed "s/--SQLITE-VERSION--/$VERSION/" > $TMPSPACE/tmp
-mv $TMPSPACE/tmp $TMPSPACE/configure.ac
-
-cd $TMPSPACE
-autoreconf -i
-#libtoolize
-#aclocal
-#autoconf
-#automake --add-missing
-
-mkdir -p tea/generic
-echo "#ifdef USE_SYSTEM_SQLITE" > tea/generic/tclsqlite3.c
-echo "# include <sqlite3.h>" >> tea/generic/tclsqlite3.c
-echo "#else" >> tea/generic/tclsqlite3.c
-echo "#include \"sqlite3.c\"" >> tea/generic/tclsqlite3.c
-echo "#endif" >> tea/generic/tclsqlite3.c
-cat $TOP/src/tclsqlite.c >> tea/generic/tclsqlite3.c
-
-cat tea/configure.ac |
- sed "s/AC_INIT(\[sqlite\], .*)/AC_INIT([sqlite], [$VERSION])/" > tmp
-mv tmp tea/configure.ac
-
-cd tea
-autoconf
-rm -rf autom4te.cache
-
-cd ../
-./configure && make dist
-tar -xzf sqlite-$VERSION.tar.gz
-mv sqlite-$VERSION $TARBALLNAME
-tar -czf $TARBALLNAME.tar.gz $TARBALLNAME
-mv $TARBALLNAME.tar.gz ..
-cd ..
-ls -l $TARBALLNAME.tar.gz
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkccode.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkccode.tcl
deleted file mode 100755
index 41b09f1e810..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkccode.tcl
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Use this script to build C-language source code for a program that uses
-# tclsqlite.c together with custom TCL scripts and/or C extensions for
-# either SQLite or TCL.
-#
-# Usage example:
-#
-# tclsh mktclsqliteprog.tcl demoapp.c.in >demoapp.c
-#
-# The demoapp.c.in file contains a mixture of C code, TCL script, and
-# processing directives used by mktclsqliteprog.tcl to build the final C-code
-# output file. Most lines of demoapp.c.in are copied straight through into
-# the output. The following control directives are recognized:
-#
-# BEGIN_STRING
-#
-# This marks the beginning of large string literal - usually a TCL
-# script of some kind. Subsequent lines of text through the first
-# line that begins with END_STRING are converted into a C-language
-# string literal.
-#
-# INCLUDE path
-#
-# The path argument is the name of a file to be inserted in place of
-# the INCLUDE line. The path can begin with $ROOT to signify the
-# root of the SQLite source tree, or $HOME to signify the directory
-# that contains the demoapp.c.in input script itself. If the path does
-# not begin with either $ROOT or $HOME, then it is interpreted relative
-# to the current working directory.
-#
-# If the INCLUDE occurs in the middle of BEGIN_STRING...END_STRING
-# then all of the text in the input file is converted into C-language
-# string literals.
-#
-# None of the control directives described above will nest. Only the
-# top-level input file ("demoapp.c.in" in the example) is interpreted.
-# referenced files are copied verbatim.
-#
-if {[llength $argv]!=1} {
- puts stderr "Usage: $argv0 TEMPLATE >OUTPUT"
- exit 1
-}
-set infile [lindex $argv 0]
-set ROOT [file normalize [file dir $argv0]/..]
-set HOME [file normalize [file dir $infile]]
-set in [open $infile rb]
-puts [subst {/* DO NOT EDIT
-**
-** This file was generated by \"$argv0 $infile\".
-** To make changes, edit $infile then rerun the generator
-** command.
-*/}]
-set instr 0
-while {1} {
- set line [gets $in]
- if {[eof $in]} break
- if {[regexp {^INCLUDE (.*)} $line all path]} {
- regsub {^\$ROOT\y} $path $ROOT path
- regsub {^\$HOME\y} $path $HOME path
- set in2 [open $path rb]
- puts "/* INCLUDE $path */"
- if {$instr} {
- while {1} {
- set line [gets $in2]
- if {[eof $in2]} break
- set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
- puts "\"$x\\n\""
- }
- } else {
- puts [read $in2]
- }
- puts "/* END $path */"
- close $in2
- continue
- }
- if {[regexp {^BEGIN_STRING} $line]} {
- set instr 1
- puts "/* BEGIN_STRING */"
- continue
- }
- if {[regexp {^END_STRING} $line]} {
- set instr 0
- puts "/* END_STRING */"
- continue
- }
- if {$instr} {
- set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
- puts "\"$x\\n\""
- } else {
- puts $line
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkctimec.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkctimec.tcl
deleted file mode 100644
index 499d5a56391..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkctimec.tcl
+++ /dev/null
@@ -1,311 +0,0 @@
-#!/usr/bin/tclsh
-#
-# To build the
-#
-# const char **azCompileOpt[]
-#
-# declaration used in src/ctime.c, run this script.
-#
-
-# All Boolean compile time options.
-#
-set boolean_options {
- SQLITE_32BIT_ROWID
- SQLITE_4_BYTE_ALIGNED_MALLOC
- SQLITE_64BIT_STATS
- SQLITE_ALLOW_COVERING_INDEX_SCAN
- SQLITE_ALLOW_URI_AUTHORITY
- SQLITE_BUG_COMPATIBLE_20160819
- SQLITE_CASE_SENSITIVE_LIKE
- SQLITE_CHECK_PAGES
- SQLITE_COVERAGE_TEST
- SQLITE_DEBUG
- SQLITE_DEFAULT_AUTOMATIC_INDEX
- SQLITE_DEFAULT_AUTOVACUUM
- SQLITE_DEFAULT_CKPTFULLFSYNC
- SQLITE_DEFAULT_FOREIGN_KEYS
- SQLITE_DEFAULT_LOCKING_MODE
- SQLITE_DEFAULT_MEMSTATUS
- SQLITE_DEFAULT_RECURSIVE_TRIGGERS
- SQLITE_DEFAULT_SYNCHRONOUS
- SQLITE_DEFAULT_WAL_SYNCHRONOUS
- SQLITE_DIRECT_OVERFLOW_READ
- SQLITE_DISABLE_DIRSYNC
- SQLITE_DISABLE_FTS3_UNICODE
- SQLITE_DISABLE_FTS4_DEFERRED
- SQLITE_DISABLE_INTRINSIC
- SQLITE_DISABLE_LFS
- SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
- SQLITE_DISABLE_SKIPAHEAD_DISTINCT
- SQLITE_ENABLE_8_3_NAMES
- SQLITE_ENABLE_API_ARMOR
- SQLITE_ENABLE_ATOMIC_WRITE
- SQLITE_ENABLE_CEROD
- SQLITE_ENABLE_COLUMN_METADATA
- SQLITE_ENABLE_COLUMN_USED_MASK
- SQLITE_ENABLE_COSTMULT
- SQLITE_ENABLE_CURSOR_HINTS
- SQLITE_ENABLE_DBSTAT_VTAB
- SQLITE_ENABLE_EXPENSIVE_ASSERT
- SQLITE_ENABLE_FTS1
- SQLITE_ENABLE_FTS2
- SQLITE_ENABLE_FTS3
- SQLITE_ENABLE_FTS3_PARENTHESIS
- SQLITE_ENABLE_FTS3_TOKENIZER
- SQLITE_ENABLE_FTS4
- SQLITE_ENABLE_FTS5
- SQLITE_ENABLE_HIDDEN_COLUMNS
- SQLITE_ENABLE_ICU
- SQLITE_ENABLE_IOTRACE
- SQLITE_ENABLE_JSON1
- SQLITE_ENABLE_LOAD_EXTENSION
- SQLITE_ENABLE_LOCKING_STYLE
- SQLITE_ENABLE_MEMORY_MANAGEMENT
- SQLITE_ENABLE_MEMSYS3
- SQLITE_ENABLE_MEMSYS5
- SQLITE_ENABLE_MULTIPLEX
- SQLITE_ENABLE_NULL_TRIM
- SQLITE_ENABLE_OVERSIZE_CELL_CHECK
- SQLITE_ENABLE_PREUPDATE_HOOK
- SQLITE_ENABLE_RBU
- SQLITE_ENABLE_RTREE
- SQLITE_ENABLE_SELECTTRACE
- SQLITE_ENABLE_SESSION
- SQLITE_ENABLE_SNAPSHOT
- SQLITE_ENABLE_SQLLOG
- SQLITE_ENABLE_STMT_SCANSTATUS
- SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- SQLITE_ENABLE_UNLOCK_NOTIFY
- SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- SQLITE_ENABLE_URI_00_ERROR
- SQLITE_ENABLE_VFSTRACE
- SQLITE_ENABLE_WHERETRACE
- SQLITE_ENABLE_ZIPVFS
- SQLITE_EXPLAIN_ESTIMATED_ROWS
- SQLITE_EXTRA_IFNULLROW
- SQLITE_FTS5_ENABLE_TEST_MI
- SQLITE_FTS5_NO_WITHOUT_ROWID
- SQLITE_HAS_CODEC
- SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- SQLITE_IGNORE_AFP_LOCK_ERRORS
- SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- SQLITE_INLINE_MEMCPY
- SQLITE_INT64_TYPE
- SQLITE_LIKE_DOESNT_MATCH_BLOBS
- SQLITE_LOCK_TRACE
- SQLITE_LOG_CACHE_SPILL
- SQLITE_MEMDEBUG
- SQLITE_MIXED_ENDIAN_64BIT_FLOAT
- SQLITE_MMAP_READWRITE
- SQLITE_MUTEX_NOOP
- SQLITE_MUTEX_NREF
- SQLITE_MUTEX_OMIT
- SQLITE_MUTEX_PTHREADS
- SQLITE_MUTEX_W32
- SQLITE_NEED_ERR_NAME
- SQLITE_NOINLINE
- SQLITE_NO_SYNC
- SQLITE_OMIT_ALTERTABLE
- SQLITE_OMIT_ANALYZE
- SQLITE_OMIT_ATTACH
- SQLITE_OMIT_AUTHORIZATION
- SQLITE_OMIT_AUTOINCREMENT
- SQLITE_OMIT_AUTOINIT
- SQLITE_OMIT_AUTOMATIC_INDEX
- SQLITE_OMIT_AUTORESET
- SQLITE_OMIT_AUTOVACUUM
- SQLITE_OMIT_BETWEEN_OPTIMIZATION
- SQLITE_OMIT_BLOB_LITERAL
- SQLITE_OMIT_BTREECOUNT
- SQLITE_OMIT_CAST
- SQLITE_OMIT_CHECK
- SQLITE_OMIT_COMPLETE
- SQLITE_OMIT_COMPOUND_SELECT
- SQLITE_OMIT_CONFLICT_CLAUSE
- SQLITE_OMIT_CTE
- SQLITE_OMIT_DATETIME_FUNCS
- SQLITE_OMIT_DECLTYPE
- SQLITE_OMIT_DEPRECATED
- SQLITE_OMIT_DISKIO
- SQLITE_OMIT_EXPLAIN
- SQLITE_OMIT_FLAG_PRAGMAS
- SQLITE_OMIT_FLOATING_POINT
- SQLITE_OMIT_FOREIGN_KEY
- SQLITE_OMIT_GET_TABLE
- SQLITE_OMIT_HEX_INTEGER
- SQLITE_OMIT_INCRBLOB
- SQLITE_OMIT_INTEGRITY_CHECK
- SQLITE_OMIT_LIKE_OPTIMIZATION
- SQLITE_OMIT_LOAD_EXTENSION
- SQLITE_OMIT_LOCALTIME
- SQLITE_OMIT_LOOKASIDE
- SQLITE_OMIT_MEMORYDB
- SQLITE_OMIT_OR_OPTIMIZATION
- SQLITE_OMIT_PAGER_PRAGMAS
- SQLITE_OMIT_PARSER_TRACE
- SQLITE_OMIT_POPEN
- SQLITE_OMIT_PRAGMA
- SQLITE_OMIT_PROGRESS_CALLBACK
- SQLITE_OMIT_QUICKBALANCE
- SQLITE_OMIT_REINDEX
- SQLITE_OMIT_SCHEMA_PRAGMAS
- SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
- SQLITE_OMIT_SHARED_CACHE
- SQLITE_OMIT_SHUTDOWN_DIRECTORIES
- SQLITE_OMIT_SUBQUERY
- SQLITE_OMIT_TCL_VARIABLE
- SQLITE_OMIT_TEMPDB
- SQLITE_OMIT_TEST_CONTROL
- SQLITE_OMIT_TRACE
- SQLITE_OMIT_TRIGGER
- SQLITE_OMIT_TRUNCATE_OPTIMIZATION
- SQLITE_OMIT_UTF16
- SQLITE_OMIT_VACUUM
- SQLITE_OMIT_VIEW
- SQLITE_OMIT_VIRTUALTABLE
- SQLITE_OMIT_WAL
- SQLITE_OMIT_WSD
- SQLITE_OMIT_XFER_OPT
- SQLITE_PCACHE_SEPARATE_HEADER
- SQLITE_PERFORMANCE_TRACE
- SQLITE_POWERSAFE_OVERWRITE
- SQLITE_PREFER_PROXY_LOCKING
- SQLITE_PROXY_DEBUG
- SQLITE_REVERSE_UNORDERED_SELECTS
- SQLITE_RTREE_INT_ONLY
- SQLITE_SECURE_DELETE
- SQLITE_SMALL_STACK
- SQLITE_SOUNDEX
- SQLITE_SUBSTR_COMPATIBILITY
- SQLITE_SYSTEM_MALLOC
- SQLITE_TCL
- SQLITE_TEST
- SQLITE_UNLINK_AFTER_CLOSE
- SQLITE_UNTESTABLE
- SQLITE_USE_ALLOCA
- SQLITE_USE_FCNTL_TRACE
- SQLITE_USER_AUTHENTICATION
- SQLITE_USE_URI
- SQLITE_VDBE_COVERAGE
- SQLITE_WIN32_MALLOC
- SQLITE_ZERO_MALLOC
-}
-
-# All compile time options for which the assigned value is other than boolean.
-#
-set value_options {
- SQLITE_BITMASK_TYPE
- SQLITE_DEFAULT_CACHE_SIZE
- SQLITE_DEFAULT_FILE_FORMAT
- SQLITE_DEFAULT_FILE_PERMISSIONS
- SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
- SQLITE_DEFAULT_LOCKING_MODE
- SQLITE_DEFAULT_LOOKASIDE
- SQLITE_DEFAULT_MMAP_SIZE
- SQLITE_DEFAULT_PAGE_SIZE
- SQLITE_DEFAULT_PCACHE_INITSZ
- SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
- SQLITE_DEFAULT_ROWEST
- SQLITE_DEFAULT_SECTOR_SIZE
- SQLITE_DEFAULT_SYNCHRONOUS
- SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
- SQLITE_DEFAULT_WAL_SYNCHRONOUS
- SQLITE_DEFAULT_WORKER_THREADS
- SQLITE_ENABLE_8_3_NAMES
- SQLITE_ENABLE_LOCKING_STYLE
- SQLITE_EXTRA_INIT
- SQLITE_EXTRA_SHUTDOWN
- SQLITE_FTS3_MAX_EXPR_DEPTH
- SQLITE_INTEGRITY_CHECK_ERROR_MAX
- SQLITE_MALLOC_SOFT_LIMIT
- SQLITE_MAX_ATTACHED
- SQLITE_MAX_COLUMN
- SQLITE_MAX_COMPOUND_SELECT
- SQLITE_MAX_DEFAULT_PAGE_SIZE
- SQLITE_MAX_EXPR_DEPTH
- SQLITE_MAX_FUNCTION_ARG
- SQLITE_MAX_LENGTH
- SQLITE_MAX_LIKE_PATTERN_LENGTH
- SQLITE_MAX_MEMORY
- SQLITE_MAX_MMAP_SIZE
- SQLITE_MAX_MMAP_SIZE_
- SQLITE_MAX_PAGE_COUNT
- SQLITE_MAX_PAGE_SIZE
- SQLITE_MAX_SCHEMA_RETRY
- SQLITE_MAX_SQL_LENGTH
- SQLITE_MAX_TRIGGER_DEPTH
- SQLITE_MAX_VARIABLE_NUMBER
- SQLITE_MAX_VDBE_OP
- SQLITE_MAX_WORKER_THREADS
- SQLITE_SORTER_PMASZ
- SQLITE_STAT4_SAMPLES
- SQLITE_STMTJRNL_SPILL
- SQLITE_TEMP_STORE
-}
-
-# Options that require custom code.
-#
-set options(ENABLE_STAT3) {
-#if defined(SQLITE_ENABLE_STAT4)
- "ENABLE_STAT4",
-#elif defined(SQLITE_ENABLE_STAT3)
- "ENABLE_STAT3",
-#endif
-}
-set options(COMPILER) {
-#if defined(__clang__) && defined(__clang_major__)
- "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
- CTIMEOPT_VAL(__clang_minor__) "."
- CTIMEOPT_VAL(__clang_patchlevel__),
-#elif defined(_MSC_VER)
- "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
-#elif defined(__GNUC__) && defined(__VERSION__)
- "COMPILER=gcc-" __VERSION__,
-#endif
-}
-set options(HAVE_ISNAN) {
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
- "HAVE_ISNAN",
-#endif
-}
-set options(THREADSAFE) {
-#if defined(SQLITE_THREADSAFE)
- "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
-#elif defined(THREADSAFE)
- "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
-#else
- "THREADSAFE=1"
-#endif
-}
-
-proc trim_name {in} {
- set ret $in
- if {[string range $in 0 6]=="SQLITE_"} {
- set ret [string range $in 7 end]
- }
- return $ret
-}
-
-foreach b $boolean_options {
- set name [trim_name $b]
- set options($name) [subst {
-#if $b
- "$name",
-#endif
-}]
-}
-
-foreach v $value_options {
- set name [trim_name $v]
- set options($name) [subst {
-#ifdef $v
- "$name=" CTIMEOPT_VAL($v),
-#endif
-}]
-}
-
-foreach o [lsort [array names options]] {
- puts [string trim $options($o)]
-}
-
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkkeywordhash.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkkeywordhash.c
deleted file mode 100644
index ec85131b641..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkkeywordhash.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
-** Compile and run this standalone program in order to generate code that
-** implements a function that will translate alphabetic identifiers into
-** parser token codes.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-/*
-** A header comment placed at the beginning of generated code.
-*/
-static const char zHdr[] =
- "/***** This file contains automatically generated code ******\n"
- "**\n"
- "** The code in this file has been automatically generated by\n"
- "**\n"
- "** sqlite/tool/mkkeywordhash.c\n"
- "**\n"
- "** The code in this file implements a function that determines whether\n"
- "** or not a given identifier is really an SQL keyword. The same thing\n"
- "** might be implemented more directly using a hand-written hash table.\n"
- "** But by using this automatically generated code, the size of the code\n"
- "** is substantially reduced. This is important for embedded applications\n"
- "** on platforms with limited memory.\n"
- "*/\n"
-;
-
-/*
-** All the keywords of the SQL language are stored in a hash
-** table composed of instances of the following structure.
-*/
-typedef struct Keyword Keyword;
-struct Keyword {
- char *zName; /* The keyword name */
- char *zTokenType; /* Token value for this keyword */
- int mask; /* Code this keyword if non-zero */
- int id; /* Unique ID for this record */
- int hash; /* Hash on the keyword */
- int offset; /* Offset to start of name string */
- int len; /* Length of this keyword, not counting final \000 */
- int prefix; /* Number of characters in prefix */
- int longestSuffix; /* Longest suffix that is a prefix on another word */
- int iNext; /* Index in aKeywordTable[] of next with same hash */
- int substrId; /* Id to another keyword this keyword is embedded in */
- int substrOffset; /* Offset into substrId for start of this keyword */
- char zOrigName[20]; /* Original keyword name before processing */
-};
-
-/*
-** Define masks used to determine which keywords are allowed
-*/
-#ifdef SQLITE_OMIT_ALTERTABLE
-# define ALTER 0
-#else
-# define ALTER 0x00000001
-#endif
-#define ALWAYS 0x00000002
-#ifdef SQLITE_OMIT_ANALYZE
-# define ANALYZE 0
-#else
-# define ANALYZE 0x00000004
-#endif
-#ifdef SQLITE_OMIT_ATTACH
-# define ATTACH 0
-#else
-# define ATTACH 0x00000008
-#endif
-#ifdef SQLITE_OMIT_AUTOINCREMENT
-# define AUTOINCR 0
-#else
-# define AUTOINCR 0x00000010
-#endif
-#ifdef SQLITE_OMIT_CAST
-# define CAST 0
-#else
-# define CAST 0x00000020
-#endif
-#ifdef SQLITE_OMIT_COMPOUND_SELECT
-# define COMPOUND 0
-#else
-# define COMPOUND 0x00000040
-#endif
-#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
-# define CONFLICT 0
-#else
-# define CONFLICT 0x00000080
-#endif
-#ifdef SQLITE_OMIT_EXPLAIN
-# define EXPLAIN 0
-#else
-# define EXPLAIN 0x00000100
-#endif
-#ifdef SQLITE_OMIT_FOREIGN_KEY
-# define FKEY 0
-#else
-# define FKEY 0x00000200
-#endif
-#ifdef SQLITE_OMIT_PRAGMA
-# define PRAGMA 0
-#else
-# define PRAGMA 0x00000400
-#endif
-#ifdef SQLITE_OMIT_REINDEX
-# define REINDEX 0
-#else
-# define REINDEX 0x00000800
-#endif
-#ifdef SQLITE_OMIT_SUBQUERY
-# define SUBQUERY 0
-#else
-# define SUBQUERY 0x00001000
-#endif
-#ifdef SQLITE_OMIT_TRIGGER
-# define TRIGGER 0
-#else
-# define TRIGGER 0x00002000
-#endif
-#if defined(SQLITE_OMIT_AUTOVACUUM) && \
- (defined(SQLITE_OMIT_VACUUM) || defined(SQLITE_OMIT_ATTACH))
-# define VACUUM 0
-#else
-# define VACUUM 0x00004000
-#endif
-#ifdef SQLITE_OMIT_VIEW
-# define VIEW 0
-#else
-# define VIEW 0x00008000
-#endif
-#ifdef SQLITE_OMIT_VIRTUALTABLE
-# define VTAB 0
-#else
-# define VTAB 0x00010000
-#endif
-#ifdef SQLITE_OMIT_AUTOVACUUM
-# define AUTOVACUUM 0
-#else
-# define AUTOVACUUM 0x00020000
-#endif
-#ifdef SQLITE_OMIT_CTE
-# define CTE 0
-#else
-# define CTE 0x00040000
-#endif
-#ifdef SQLITE_OMIT_UPSERT
-# define UPSERT 0
-#else
-# define UPSERT 0x00080000
-#endif
-
-/*
-** These are the keywords
-*/
-static Keyword aKeywordTable[] = {
- { "ABORT", "TK_ABORT", CONFLICT|TRIGGER },
- { "ACTION", "TK_ACTION", FKEY },
- { "ADD", "TK_ADD", ALTER },
- { "AFTER", "TK_AFTER", TRIGGER },
- { "ALL", "TK_ALL", ALWAYS },
- { "ALTER", "TK_ALTER", ALTER },
- { "ANALYZE", "TK_ANALYZE", ANALYZE },
- { "AND", "TK_AND", ALWAYS },
- { "AS", "TK_AS", ALWAYS },
- { "ASC", "TK_ASC", ALWAYS },
- { "ATTACH", "TK_ATTACH", ATTACH },
- { "AUTOINCREMENT", "TK_AUTOINCR", AUTOINCR },
- { "BEFORE", "TK_BEFORE", TRIGGER },
- { "BEGIN", "TK_BEGIN", ALWAYS },
- { "BETWEEN", "TK_BETWEEN", ALWAYS },
- { "BY", "TK_BY", ALWAYS },
- { "CASCADE", "TK_CASCADE", FKEY },
- { "CASE", "TK_CASE", ALWAYS },
- { "CAST", "TK_CAST", CAST },
- { "CHECK", "TK_CHECK", ALWAYS },
- { "COLLATE", "TK_COLLATE", ALWAYS },
- { "COLUMN", "TK_COLUMNKW", ALTER },
- { "COMMIT", "TK_COMMIT", ALWAYS },
- { "CONFLICT", "TK_CONFLICT", CONFLICT },
- { "CONSTRAINT", "TK_CONSTRAINT", ALWAYS },
- { "CREATE", "TK_CREATE", ALWAYS },
- { "CROSS", "TK_JOIN_KW", ALWAYS },
- { "CURRENT_DATE", "TK_CTIME_KW", ALWAYS },
- { "CURRENT_TIME", "TK_CTIME_KW", ALWAYS },
- { "CURRENT_TIMESTAMP","TK_CTIME_KW", ALWAYS },
- { "DATABASE", "TK_DATABASE", ATTACH },
- { "DEFAULT", "TK_DEFAULT", ALWAYS },
- { "DEFERRED", "TK_DEFERRED", ALWAYS },
- { "DEFERRABLE", "TK_DEFERRABLE", FKEY },
- { "DELETE", "TK_DELETE", ALWAYS },
- { "DESC", "TK_DESC", ALWAYS },
- { "DETACH", "TK_DETACH", ATTACH },
- { "DISTINCT", "TK_DISTINCT", ALWAYS },
- { "DO", "TK_DO", UPSERT },
- { "DROP", "TK_DROP", ALWAYS },
- { "END", "TK_END", ALWAYS },
- { "EACH", "TK_EACH", TRIGGER },
- { "ELSE", "TK_ELSE", ALWAYS },
- { "ESCAPE", "TK_ESCAPE", ALWAYS },
- { "EXCEPT", "TK_EXCEPT", COMPOUND },
- { "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS },
- { "EXISTS", "TK_EXISTS", ALWAYS },
- { "EXPLAIN", "TK_EXPLAIN", EXPLAIN },
- { "FAIL", "TK_FAIL", CONFLICT|TRIGGER },
- { "FOR", "TK_FOR", TRIGGER },
- { "FOREIGN", "TK_FOREIGN", FKEY },
- { "FROM", "TK_FROM", ALWAYS },
- { "FULL", "TK_JOIN_KW", ALWAYS },
- { "GLOB", "TK_LIKE_KW", ALWAYS },
- { "GROUP", "TK_GROUP", ALWAYS },
- { "HAVING", "TK_HAVING", ALWAYS },
- { "IF", "TK_IF", ALWAYS },
- { "IGNORE", "TK_IGNORE", CONFLICT|TRIGGER },
- { "IMMEDIATE", "TK_IMMEDIATE", ALWAYS },
- { "IN", "TK_IN", ALWAYS },
- { "INDEX", "TK_INDEX", ALWAYS },
- { "INDEXED", "TK_INDEXED", ALWAYS },
- { "INITIALLY", "TK_INITIALLY", FKEY },
- { "INNER", "TK_JOIN_KW", ALWAYS },
- { "INSERT", "TK_INSERT", ALWAYS },
- { "INSTEAD", "TK_INSTEAD", TRIGGER },
- { "INTERSECT", "TK_INTERSECT", COMPOUND },
- { "INTO", "TK_INTO", ALWAYS },
- { "IS", "TK_IS", ALWAYS },
- { "ISNULL", "TK_ISNULL", ALWAYS },
- { "JOIN", "TK_JOIN", ALWAYS },
- { "KEY", "TK_KEY", ALWAYS },
- { "LEFT", "TK_JOIN_KW", ALWAYS },
- { "LIKE", "TK_LIKE_KW", ALWAYS },
- { "LIMIT", "TK_LIMIT", ALWAYS },
- { "MATCH", "TK_MATCH", ALWAYS },
- { "NATURAL", "TK_JOIN_KW", ALWAYS },
- { "NO", "TK_NO", FKEY },
- { "NOT", "TK_NOT", ALWAYS },
- { "NOTHING", "TK_NOTHING", UPSERT },
- { "NOTNULL", "TK_NOTNULL", ALWAYS },
- { "NULL", "TK_NULL", ALWAYS },
- { "OF", "TK_OF", ALWAYS },
- { "OFFSET", "TK_OFFSET", ALWAYS },
- { "ON", "TK_ON", ALWAYS },
- { "OR", "TK_OR", ALWAYS },
- { "ORDER", "TK_ORDER", ALWAYS },
- { "OUTER", "TK_JOIN_KW", ALWAYS },
- { "PLAN", "TK_PLAN", EXPLAIN },
- { "PRAGMA", "TK_PRAGMA", PRAGMA },
- { "PRIMARY", "TK_PRIMARY", ALWAYS },
- { "QUERY", "TK_QUERY", EXPLAIN },
- { "RAISE", "TK_RAISE", TRIGGER },
- { "RECURSIVE", "TK_RECURSIVE", CTE },
- { "REFERENCES", "TK_REFERENCES", FKEY },
- { "REGEXP", "TK_LIKE_KW", ALWAYS },
- { "REINDEX", "TK_REINDEX", REINDEX },
- { "RELEASE", "TK_RELEASE", ALWAYS },
- { "RENAME", "TK_RENAME", ALTER },
- { "REPLACE", "TK_REPLACE", CONFLICT },
- { "RESTRICT", "TK_RESTRICT", FKEY },
- { "RIGHT", "TK_JOIN_KW", ALWAYS },
- { "ROLLBACK", "TK_ROLLBACK", ALWAYS },
- { "ROW", "TK_ROW", TRIGGER },
- { "SAVEPOINT", "TK_SAVEPOINT", ALWAYS },
- { "SELECT", "TK_SELECT", ALWAYS },
- { "SET", "TK_SET", ALWAYS },
- { "TABLE", "TK_TABLE", ALWAYS },
- { "TEMP", "TK_TEMP", ALWAYS },
- { "TEMPORARY", "TK_TEMP", ALWAYS },
- { "THEN", "TK_THEN", ALWAYS },
- { "TO", "TK_TO", ALWAYS },
- { "TRANSACTION", "TK_TRANSACTION", ALWAYS },
- { "TRIGGER", "TK_TRIGGER", TRIGGER },
- { "UNION", "TK_UNION", COMPOUND },
- { "UNIQUE", "TK_UNIQUE", ALWAYS },
- { "UPDATE", "TK_UPDATE", ALWAYS },
- { "USING", "TK_USING", ALWAYS },
- { "VACUUM", "TK_VACUUM", VACUUM },
- { "VALUES", "TK_VALUES", ALWAYS },
- { "VIEW", "TK_VIEW", VIEW },
- { "VIRTUAL", "TK_VIRTUAL", VTAB },
- { "WITH", "TK_WITH", CTE },
- { "WITHOUT", "TK_WITHOUT", ALWAYS },
- { "WHEN", "TK_WHEN", ALWAYS },
- { "WHERE", "TK_WHERE", ALWAYS },
-};
-
-/* Number of keywords */
-static int nKeyword = (sizeof(aKeywordTable)/sizeof(aKeywordTable[0]));
-
-/* Map all alphabetic characters into lower-case for hashing. This is
-** only valid for alphabetics. In particular it does not work for '_'
-** and so the hash cannot be on a keyword position that might be an '_'.
-*/
-#define charMap(X) (0x20|(X))
-
-/*
-** Comparision function for two Keyword records
-*/
-static int keywordCompare1(const void *a, const void *b){
- const Keyword *pA = (Keyword*)a;
- const Keyword *pB = (Keyword*)b;
- int n = pA->len - pB->len;
- if( n==0 ){
- n = strcmp(pA->zName, pB->zName);
- }
- assert( n!=0 );
- return n;
-}
-static int keywordCompare2(const void *a, const void *b){
- const Keyword *pA = (Keyword*)a;
- const Keyword *pB = (Keyword*)b;
- int n = pB->longestSuffix - pA->longestSuffix;
- if( n==0 ){
- n = strcmp(pA->zName, pB->zName);
- }
- assert( n!=0 );
- return n;
-}
-static int keywordCompare3(const void *a, const void *b){
- const Keyword *pA = (Keyword*)a;
- const Keyword *pB = (Keyword*)b;
- int n = pA->offset - pB->offset;
- if( n==0 ) n = pB->id - pA->id;
- assert( n!=0 );
- return n;
-}
-
-/*
-** Return a KeywordTable entry with the given id
-*/
-static Keyword *findById(int id){
- int i;
- for(i=0; i<nKeyword; i++){
- if( aKeywordTable[i].id==id ) break;
- }
- return &aKeywordTable[i];
-}
-
-/*
-** This routine does the work. The generated code is printed on standard
-** output.
-*/
-int main(int argc, char **argv){
- int i, j, k, h;
- int bestSize, bestCount;
- int count;
- int nChar;
- int totalLen = 0;
- int aKWHash[1000]; /* 1000 is much bigger than nKeyword */
- char zKWText[2000];
-
- /* Remove entries from the list of keywords that have mask==0 */
- for(i=j=0; i<nKeyword; i++){
- if( aKeywordTable[i].mask==0 ) continue;
- if( j<i ){
- aKeywordTable[j] = aKeywordTable[i];
- }
- j++;
- }
- nKeyword = j;
-
- /* Fill in the lengths of strings and hashes for all entries. */
- for(i=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- p->len = (int)strlen(p->zName);
- assert( p->len<sizeof(p->zOrigName) );
- memcpy(p->zOrigName, p->zName, p->len+1);
- totalLen += p->len;
- p->hash = (charMap(p->zName[0])*4) ^
- (charMap(p->zName[p->len-1])*3) ^ (p->len*1);
- p->id = i+1;
- }
-
- /* Sort the table from shortest to longest keyword */
- qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare1);
-
- /* Look for short keywords embedded in longer keywords */
- for(i=nKeyword-2; i>=0; i--){
- Keyword *p = &aKeywordTable[i];
- for(j=nKeyword-1; j>i && p->substrId==0; j--){
- Keyword *pOther = &aKeywordTable[j];
- if( pOther->substrId ) continue;
- if( pOther->len<=p->len ) continue;
- for(k=0; k<=pOther->len-p->len; k++){
- if( memcmp(p->zName, &pOther->zName[k], p->len)==0 ){
- p->substrId = pOther->id;
- p->substrOffset = k;
- break;
- }
- }
- }
- }
-
- /* Compute the longestSuffix value for every word */
- for(i=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- if( p->substrId ) continue;
- for(j=0; j<nKeyword; j++){
- Keyword *pOther;
- if( j==i ) continue;
- pOther = &aKeywordTable[j];
- if( pOther->substrId ) continue;
- for(k=p->longestSuffix+1; k<p->len && k<pOther->len; k++){
- if( memcmp(&p->zName[p->len-k], pOther->zName, k)==0 ){
- p->longestSuffix = k;
- }
- }
- }
- }
-
- /* Sort the table into reverse order by length */
- qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare2);
-
- /* Fill in the offset for all entries */
- nChar = 0;
- for(i=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- if( p->offset>0 || p->substrId ) continue;
- p->offset = nChar;
- nChar += p->len;
- for(k=p->len-1; k>=1; k--){
- for(j=i+1; j<nKeyword; j++){
- Keyword *pOther = &aKeywordTable[j];
- if( pOther->offset>0 || pOther->substrId ) continue;
- if( pOther->len<=k ) continue;
- if( memcmp(&p->zName[p->len-k], pOther->zName, k)==0 ){
- p = pOther;
- p->offset = nChar - k;
- nChar = p->offset + p->len;
- p->zName += k;
- p->len -= k;
- p->prefix = k;
- j = i;
- k = p->len;
- }
- }
- }
- }
- for(i=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- if( p->substrId ){
- p->offset = findById(p->substrId)->offset + p->substrOffset;
- }
- }
-
- /* Sort the table by offset */
- qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare3);
-
- /* Figure out how big to make the hash table in order to minimize the
- ** number of collisions */
- bestSize = nKeyword;
- bestCount = nKeyword*nKeyword;
- for(i=nKeyword/2; i<=2*nKeyword; i++){
- for(j=0; j<i; j++) aKWHash[j] = 0;
- for(j=0; j<nKeyword; j++){
- h = aKeywordTable[j].hash % i;
- aKWHash[h] *= 2;
- aKWHash[h]++;
- }
- for(j=count=0; j<i; j++) count += aKWHash[j];
- if( count<bestCount ){
- bestCount = count;
- bestSize = i;
- }
- }
-
- /* Compute the hash */
- for(i=0; i<bestSize; i++) aKWHash[i] = 0;
- for(i=0; i<nKeyword; i++){
- h = aKeywordTable[i].hash % bestSize;
- aKeywordTable[i].iNext = aKWHash[h];
- aKWHash[h] = i+1;
- }
-
- /* Begin generating code */
- printf("%s", zHdr);
- printf("/* Hash score: %d */\n", bestCount);
- printf("/* zKWText[] encodes %d bytes of keyword text in %d bytes */\n",
- totalLen + nKeyword, nChar+1 );
- for(i=j=k=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- if( p->substrId ) continue;
- memcpy(&zKWText[k], p->zName, p->len);
- k += p->len;
- if( j+p->len>70 ){
- printf("%*s */\n", 74-j, "");
- j = 0;
- }
- if( j==0 ){
- printf("/* ");
- j = 8;
- }
- printf("%s", p->zName);
- j += p->len;
- }
- if( j>0 ){
- printf("%*s */\n", 74-j, "");
- }
- printf("static const char zKWText[%d] = {\n", nChar);
- zKWText[nChar] = 0;
- for(i=j=0; i<k; i++){
- if( j==0 ){
- printf(" ");
- }
- if( zKWText[i]==0 ){
- printf("0");
- }else{
- printf("'%c',", zKWText[i]);
- }
- j += 4;
- if( j>68 ){
- printf("\n");
- j = 0;
- }
- }
- if( j>0 ) printf("\n");
- printf("};\n");
-
- printf("/* aKWHash[i] is the hash value for the i-th keyword */\n");
- printf("static const unsigned char aKWHash[%d] = {\n", bestSize);
- for(i=j=0; i<bestSize; i++){
- if( j==0 ) printf(" ");
- printf(" %3d,", aKWHash[i]);
- j++;
- if( j>12 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s};\n", j==0 ? "" : "\n");
-
- printf("/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0\n");
- printf("** then the i-th keyword has no more hash collisions. Otherwise,\n");
- printf("** the next keyword with the same hash is aKWHash[i]-1. */\n");
- printf("static const unsigned char aKWNext[%d] = {\n", nKeyword);
- for(i=j=0; i<nKeyword; i++){
- if( j==0 ) printf(" ");
- printf(" %3d,", aKeywordTable[i].iNext);
- j++;
- if( j>12 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s};\n", j==0 ? "" : "\n");
-
- printf("/* aKWLen[i] is the length (in bytes) of the i-th keyword */\n");
- printf("static const unsigned char aKWLen[%d] = {\n", nKeyword);
- for(i=j=0; i<nKeyword; i++){
- if( j==0 ) printf(" ");
- printf(" %3d,", aKeywordTable[i].len+aKeywordTable[i].prefix);
- j++;
- if( j>12 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s};\n", j==0 ? "" : "\n");
-
- printf("/* aKWOffset[i] is the index into zKWText[] of the start of\n");
- printf("** the text for the i-th keyword. */\n");
- printf("static const unsigned short int aKWOffset[%d] = {\n", nKeyword);
- for(i=j=0; i<nKeyword; i++){
- if( j==0 ) printf(" ");
- printf(" %3d,", aKeywordTable[i].offset);
- j++;
- if( j>12 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s};\n", j==0 ? "" : "\n");
-
- printf("/* aKWCode[i] is the parser symbol code for the i-th keyword */\n");
- printf("static const unsigned char aKWCode[%d] = {\n", nKeyword);
- for(i=j=0; i<nKeyword; i++){
- char *zToken = aKeywordTable[i].zTokenType;
- if( j==0 ) printf(" ");
- printf("%s,%*s", zToken, (int)(14-strlen(zToken)), "");
- j++;
- if( j>=5 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s};\n", j==0 ? "" : "\n");
- printf("/* Check to see if z[0..n-1] is a keyword. If it is, write the\n");
- printf("** parser symbol code for that keyword into *pType. Always\n");
- printf("** return the integer n (the length of the token). */\n");
- printf("static int keywordCode(const char *z, int n, int *pType){\n");
- printf(" int i, j;\n");
- printf(" const char *zKW;\n");
- printf(" if( n>=2 ){\n");
- printf(" i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) %% %d;\n",
- bestSize);
- printf(" for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){\n");
- printf(" if( aKWLen[i]!=n ) continue;\n");
- printf(" j = 0;\n");
- printf(" zKW = &zKWText[aKWOffset[i]];\n");
- printf("#ifdef SQLITE_ASCII\n");
- printf(" while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; }\n");
- printf("#endif\n");
- printf("#ifdef SQLITE_EBCDIC\n");
- printf(" while( j<n && toupper(z[j])==zKW[j] ){ j++; }\n");
- printf("#endif\n");
- printf(" if( j<n ) continue;\n");
- for(i=0; i<nKeyword; i++){
- printf(" testcase( i==%d ); /* %s */\n",
- i, aKeywordTable[i].zOrigName);
- }
- printf(" *pType = aKWCode[i];\n");
- printf(" break;\n");
- printf(" }\n");
- printf(" }\n");
- printf(" return n;\n");
- printf("}\n");
- printf("int sqlite3KeywordCode(const unsigned char *z, int n){\n");
- printf(" int id = TK_ID;\n");
- printf(" keywordCode((char*)z, n, &id);\n");
- printf(" return id;\n");
- printf("}\n");
- printf("#define SQLITE_N_KEYWORD %d\n", nKeyword);
- printf("int sqlite3_keyword_name(int i,const char **pzName,int *pnName){\n");
- printf(" if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;\n");
- printf(" *pzName = zKWText + aKWOffset[i];\n");
- printf(" *pnName = aKWLen[i];\n");
- printf(" return SQLITE_OK;\n");
- printf("}\n");
- printf("int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; }\n");
- printf("int sqlite3_keyword_check(const char *zName, int nName){\n");
- printf(" return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName);\n");
- printf("}\n");
-
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkmsvcmin.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkmsvcmin.tcl
deleted file mode 100644
index 764641faee8..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkmsvcmin.tcl
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/tcl
-#
-# This script reads the regular MSVC makefile (../Makefile.msc) and outputs
-# a revised version of that Makefile that is "minimal" in the sense that
-# it uses the sqlite3.c amalgamation as input and does not require tclsh.
-# The resulting "../Makefile.min.msc" is suitable for use in the amalgamation
-# tarballs.
-#
-if {$argc==0} {
- set basedir [file dir [file dir [file normalize $argv0]]]
- set fromFileName [file join $basedir Makefile.msc]
- set toFileName [file join $basedir autoconf Makefile.msc]
-} else {
- set fromFileName [lindex $argv 0]
- if {![file exists $fromFileName]} {
- error "input file \"$fromFileName\" does not exist"
- }
- set toFileName [lindex $argv 1]
- if {[file exists $toFileName]} {
- error "output file \"$toFileName\" already exists"
- }
-}
-
-proc readFile { fileName } {
- set file_id [open $fileName RDONLY]
- fconfigure $file_id -encoding binary -translation binary
- set result [read $file_id]
- close $file_id
- return $result
-}
-
-proc writeFile { fileName data } {
- set file_id [open $fileName {WRONLY CREAT TRUNC}]
- fconfigure $file_id -encoding binary -translation binary
- puts -nonewline $file_id $data
- close $file_id
- return ""
-}
-
-proc escapeSubSpec { data } {
- regsub -all -- {&} $data {\\\&} data
- regsub -all -- {\\(\d+)} $data {\\\\\1} data
- return $data
-}
-
-proc substVars { data } {
- return [uplevel 1 [list subst -nocommands -nobackslashes $data]]
-}
-
-#
-# NOTE: This block is used to replace the section marked <<block1>> in
-# the Makefile, if it exists.
-#
-set blocks(1) [string trimleft [string map [list \\\\ \\] {
-_HASHCHAR=^#
-!IF ![echo !IFNDEF VERSION > rcver.vc] && \\
- ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| "%SystemRoot%\System32\find.exe" "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \\
- ![echo !ENDIF >> rcver.vc]
-!INCLUDE rcver.vc
-!ENDIF
-
-RESOURCE_VERSION = $(VERSION:^#=)
-RESOURCE_VERSION = $(RESOURCE_VERSION:define=)
-RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=)
-RESOURCE_VERSION = $(RESOURCE_VERSION:"=)
-RESOURCE_VERSION = $(RESOURCE_VERSION:.=,)
-
-$(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H)
- echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
- echo #define SQLITE_RESOURCE_VERSION $(RESOURCE_VERSION) >> sqlite3rc.h
- echo #endif >> sqlite3rc.h
- $(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc
-}]]
-
-#
-# NOTE: This block is used to replace the section marked <<block2>> in
-# the Makefile, if it exists.
-#
-set blocks(2) [string trimleft [string map [list \\\\ \\] {
-Replace.exe:
- $(CSC) /target:exe $(TOP)\Replace.cs
-
-sqlite3.def: Replace.exe $(LIBOBJ)
- echo EXPORTS > sqlite3.def
- dumpbin /all $(LIBOBJ) \\
- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
- | sort >> sqlite3.def
-}]]
-
-set data "#### DO NOT EDIT ####\n"
-append data "# This makefile is automatically "
-append data "generated from the [file tail $fromFileName] at\n"
-append data "# the root of the canonical SQLite source tree (not the\n"
-append data "# amalgamation tarball) using the tool/[file tail $argv0]\n"
-append data "# script.\n#\n\n"
-append data [readFile $fromFileName]
-
-regsub -all -- {# <<mark>>\n.*?# <</mark>>\n} \
- $data "" data
-
-foreach i [lsort -integer [array names blocks]] {
- regsub -all -- [substVars \
- {# <<block${i}>>\n.*?# <</block${i}>>\n}] \
- $data [escapeSubSpec $blocks($i)] data
-}
-
-set data [string map [list " -I\$(TOP)\\src" ""] $data]
-set data [string map [list " libsqlite3.lib" ""] $data]
-set data [string map [list " \$(ALL_TCL_TARGETS)" ""] $data]
-set data [string map [list "\$(TOP)\\src\\" "\$(TOP)\\"] $data]
-
-writeFile $toFileName $data
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopcodec.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopcodec.tcl
deleted file mode 100644
index abdeaaeb320..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopcodec.tcl
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This TCL script scans the opcodes.h file (which is itself generated by
-# another TCL script) and uses the information gleaned to create the
-# opcodes.c source file.
-#
-# Opcodes.c contains strings which are the symbolic names for the various
-# opcodes used by the VDBE. These strings are used when disassembling a
-# VDBE program during tracing or as a result of the EXPLAIN keyword.
-#
-puts "/* Automatically generated. Do not edit */"
-puts "/* See the tool/mkopcodec.tcl script for details. */"
-puts "#if !defined(SQLITE_OMIT_EXPLAIN) \\"
-puts " || defined(VDBE_PROFILE) \\"
-puts " || defined(SQLITE_DEBUG)"
-puts "#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG)"
-puts "# define OpHelp(X) \"\\0\" X"
-puts "#else"
-puts "# define OpHelp(X)"
-puts "#endif"
-puts "const char *sqlite3OpcodeName(int i)\173"
-puts " static const char *const azName\[\] = \173"
-set mx 0
-
-set in [open [lindex $argv 0] rb]
-while {![eof $in]} {
- set line [gets $in]
- if {[regexp {^#define OP_} $line]} {
- set name [lindex $line 1]
- regsub {^OP_} $name {} name
- set i [lindex $line 2]
- set label($i) $name
- if {$mx<$i} {set mx $i}
- if {[regexp {synopsis: (.*) \*/} $line all x]} {
- set synopsis($i) [string trim $x]
- } else {
- set synopsis($i) {}
- }
- }
-}
-close $in
-
-for {set i 0} {$i<=$mx} {incr i} {
- puts [format " /* %3d */ %-18s OpHelp(\"%s\")," \
- $i \"$label($i)\" $synopsis($i)]
-}
-puts " \175;"
-puts " return azName\[i\];"
-puts "\175"
-puts "#endif"
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopcodeh.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopcodeh.tcl
deleted file mode 100644
index b9e55fa243c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopcodeh.tcl
+++ /dev/null
@@ -1,270 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Generate the file opcodes.h.
-#
-# This TCL script scans a concatenation of the parse.h output file from the
-# parser and the vdbe.c source file in order to generate the opcodes numbers
-# for all opcodes.
-#
-# The lines of the vdbe.c that we are interested in are of the form:
-#
-# case OP_aaaa: /* same as TK_bbbbb */
-#
-# The TK_ comment is optional. If it is present, then the value assigned to
-# the OP_ is the same as the TK_ value. If missing, the OP_ value is assigned
-# a small integer that is different from every other OP_ value.
-#
-# We go to the trouble of making some OP_ values the same as TK_ values
-# as an optimization. During parsing, things like expression operators
-# are coded with TK_ values such as TK_ADD, TK_DIVIDE, and so forth. Later
-# during code generation, we need to generate corresponding opcodes like
-# OP_Add and OP_Divide. By making TK_ADD==OP_Add and TK_DIVIDE==OP_Divide,
-# code to translate from one to the other is avoided. This makes the
-# code generator smaller and faster.
-#
-# This script also scans for lines of the form:
-#
-# case OP_aaaa: /* jump, in1, in2, in3, out2-prerelease, out3 */
-#
-# When such comments are found on an opcode, it means that certain
-# properties apply to that opcode. Set corresponding flags using the
-# OPFLG_INITIALIZER macro.
-#
-
-set in stdin
-set currentOp {}
-set nOp 0
-while {![eof $in]} {
- set line [gets $in]
-
- # Remember the TK_ values from the parse.h file.
- # NB: The "TK_" prefix stands for "ToKen", not the graphical Tk toolkit
- # commonly associated with TCL.
- #
- if {[regexp {^#define TK_} $line]} {
- set tk([lindex $line 1]) [lindex $line 2]
- continue
- }
-
- # Find "/* Opcode: " lines in the vdbe.c file. Each one introduces
- # a new opcode. Remember which parameters are used.
- #
- if {[regexp {^.. Opcode: } $line]} {
- set currentOp OP_[lindex $line 2]
- set m 0
- foreach term $line {
- switch $term {
- P1 {incr m 1}
- P2 {incr m 2}
- P3 {incr m 4}
- P4 {incr m 8}
- P5 {incr m 16}
- }
- }
- set paramused($currentOp) $m
- }
-
- # Find "** Synopsis: " lines that follow Opcode:
- #
- if {[regexp {^.. Synopsis: (.*)} $line all x] && $currentOp!=""} {
- set synopsis($currentOp) [string trim $x]
- }
-
- # Scan for "case OP_aaaa:" lines in the vdbe.c file
- #
- if {[regexp {^case OP_} $line]} {
- set line [split $line]
- set name [string trim [lindex $line 1] :]
- if {$name=="OP_Abortable"} continue; # put OP_Abortable last
- set op($name) -1
- set jump($name) 0
- set in1($name) 0
- set in2($name) 0
- set in3($name) 0
- set out2($name) 0
- set out3($name) 0
- for {set i 3} {$i<[llength $line]-1} {incr i} {
- switch [string trim [lindex $line $i] ,] {
- same {
- incr i
- if {[lindex $line $i]=="as"} {
- incr i
- set sym [string trim [lindex $line $i] ,]
- set val $tk($sym)
- set op($name) $val
- set used($val) 1
- set sameas($val) $sym
- set def($val) $name
- }
- }
- jump {set jump($name) 1}
- in1 {set in1($name) 1}
- in2 {set in2($name) 1}
- in3 {set in3($name) 1}
- out2 {set out2($name) 1}
- out3 {set out3($name) 1}
- }
- }
- set order($nOp) $name
- incr nOp
- }
-}
-
-# Assign numbers to all opcodes and output the result.
-#
-puts "/* Automatically generated. Do not edit */"
-puts "/* See the tool/mkopcodeh.tcl script for details */"
-foreach name {OP_Noop OP_Explain OP_Abortable} {
- set jump($name) 0
- set in1($name) 0
- set in2($name) 0
- set in3($name) 0
- set out2($name) 0
- set out3($name) 0
- set op($name) -1
- set order($nOp) $name
- incr nOp
-}
-
-# The following are the opcodes that are processed by resolveP2Values()
-#
-set rp2v_ops {
- OP_Transaction
- OP_AutoCommit
- OP_Savepoint
- OP_Checkpoint
- OP_Vacuum
- OP_JournalMode
- OP_VUpdate
- OP_VFilter
- OP_Next
- OP_NextIfOpen
- OP_SorterNext
- OP_Prev
- OP_PrevIfOpen
-}
-
-# Assign small values to opcodes that are processed by resolveP2Values()
-# to make code generation for the switch() statement smaller and faster.
-#
-set cnt -1
-for {set i 0} {$i<$nOp} {incr i} {
- set name $order($i)
- if {[lsearch $rp2v_ops $name]>=0} {
- incr cnt
- while {[info exists used($cnt)]} {incr cnt}
- set op($name) $cnt
- set used($cnt) 1
- set def($cnt) $name
- }
-}
-
-# Assign the next group of values to JUMP opcodes
-#
-for {set i 0} {$i<$nOp} {incr i} {
- set name $order($i)
- if {$op($name)>=0} continue
- if {!$jump($name)} continue
- incr cnt
- while {[info exists used($cnt)]} {incr cnt}
- set op($name) $cnt
- set used($cnt) 1
- set def($cnt) $name
-}
-
-# Find the numeric value for the largest JUMP opcode
-#
-set mxJump -1
-for {set i 0} {$i<$nOp} {incr i} {
- set name $order($i)
- if {$jump($name) && $op($name)>$mxJump} {set mxJump $op($name)}
-}
-
-
-# Generate the numeric values for all remaining opcodes
-#
-for {set i 0} {$i<$nOp} {incr i} {
- set name $order($i)
- if {$op($name)<0} {
- incr cnt
- while {[info exists used($cnt)]} {incr cnt}
- set op($name) $cnt
- set used($cnt) 1
- set def($cnt) $name
- }
-}
-
-set max [lindex [lsort -decr -integer [array names used]] 0]
-for {set i 0} {$i<=$max} {incr i} {
- if {![info exists used($i)]} {
- set def($i) "OP_NotUsed_$i"
- }
- if {$i>$max} {set max $i}
- set name $def($i)
- puts -nonewline [format {#define %-16s %3d} $name $i]
- set com {}
- if {$jump($name)} {
- lappend com "jump"
- }
- if {[info exists sameas($i)]} {
- lappend com "same as $sameas($i)"
- }
- if {[info exists synopsis($name)]} {
- lappend com "synopsis: $synopsis($name)"
- }
- if {[llength $com]} {
- puts -nonewline [format " /* %-42s */" [join $com {, }]]
- }
- puts ""
-}
-
-if {$max>255} {
- error "More than 255 opcodes - VdbeOp.opcode is of type u8!"
-}
-
-# Generate the bitvectors:
-#
-set bv(0) 0
-for {set i 0} {$i<=$max} {incr i} {
- set x 0
- set name $def($i)
- if {[string match OP_NotUsed* $name]==0} {
- if {$jump($name)} {incr x 1}
- if {$in1($name)} {incr x 2}
- if {$in2($name)} {incr x 4}
- if {$in3($name)} {incr x 8}
- if {$out2($name)} {incr x 16}
- if {$out3($name)} {incr x 32}
- }
- set bv($i) $x
-}
-puts ""
-puts "/* Properties such as \"out2\" or \"jump\" that are specified in"
-puts "** comments following the \"case\" for each opcode in the vdbe.c"
-puts "** are encoded into bitvectors as follows:"
-puts "*/"
-puts "#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */"
-puts "#define OPFLG_IN1 0x02 /* in1: P1 is an input */"
-puts "#define OPFLG_IN2 0x04 /* in2: P2 is an input */"
-puts "#define OPFLG_IN3 0x08 /* in3: P3 is an input */"
-puts "#define OPFLG_OUT2 0x10 /* out2: P2 is an output */"
-puts "#define OPFLG_OUT3 0x20 /* out3: P3 is an output */"
-puts "#define OPFLG_INITIALIZER \173\\"
-for {set i 0} {$i<=$max} {incr i} {
- if {$i%8==0} {
- puts -nonewline [format "/* %3d */" $i]
- }
- puts -nonewline [format " 0x%02x," $bv($i)]
- if {$i%8==7} {
- puts "\\"
- }
-}
-puts "\175"
-puts ""
-puts "/* The sqlite3P2Values() routine is able to run faster if it knows"
-puts "** the value of the largest JUMP opcode. The smaller the maximum"
-puts "** JUMP opcode the better, so the mkopcodeh.tcl script that"
-puts "** generated this include file strives to group all JUMP opcodes"
-puts "** together near the beginning of the list."
-puts "*/"
-puts "#define SQLITE_MX_JUMP_OPCODE $mxJump /* Maximum JUMP opcode */"
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopts.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopts.tcl
deleted file mode 100644
index 88f645bbe30..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkopts.tcl
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script is used to generate the array of strings and the enum
-# that appear at the beginning of the C code implementation of a
-# a TCL command and that define the available subcommands for that
-# TCL command.
-
-set prefix {}
-while {![eof stdin]} {
- set line [gets stdin]
- if {$line==""} continue
- regsub -all "\[ \t\n,\]+" [string trim $line] { } line
- foreach token [split $line { }] {
- if {![regexp {(([a-zA-Z]+)_)?([_a-zA-Z0-9]+)} $token all px p2 name]} continue
- lappend namelist [string tolower $name]
- if {$px!=""} {set prefix $p2}
- }
-}
-
-puts " static const char *${prefix}_strs\[\] = \173"
-set col 0
-proc put_item x {
- global col
- if {$col==0} {puts -nonewline " "}
- if {$col<2} {
- puts -nonewline [format " %-25s" $x]
- incr col
- } else {
- puts $x
- set col 0
- }
-}
-proc finalize {} {
- global col
- if {$col>0} {puts {}}
- set col 0
-}
-
-foreach name [lsort $namelist] {
- put_item \"$name\",
-}
-put_item 0
-finalize
-puts " \175;"
-puts " enum ${prefix}_enum \173"
-foreach name [lsort $namelist] {
- regsub -all {@} $name {} name
- put_item ${prefix}_[string toupper $name],
-}
-finalize
-puts " \175;"
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkpragmatab.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkpragmatab.tcl
deleted file mode 100644
index 1bfbeb7c58b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkpragmatab.tcl
+++ /dev/null
@@ -1,589 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Run this script to generate the pragma name lookup table C code.
-#
-# To add new pragmas, first add the name and other relevant attributes
-# of the pragma to the "pragma_def" object below. Then run this script
-# to generate the ../src/pragma.h header file that contains macros and
-# the lookup table needed for pragma name lookup in the pragma.c module.
-# Then add the extra "case PragTyp_XXXXX:" and subsequent code for the
-# new pragma in ../src/pragma.c.
-#
-
-# Flag meanings:
-set flagMeaning(NeedSchema) {Force schema load before running}
-set flagMeaning(ReadOnly) {Read-only HEADER_VALUE}
-set flagMeaning(Result0) {Acts as query when no argument}
-set flagMeaning(Result1) {Acts as query when has one argument}
-set flagMeaning(SchemaReq) {Schema required - "main" is default}
-set flagMeaning(SchemaOpt) {Schema restricts name search if present}
-set flagMeaning(NoColumns) {OP_ResultRow called with zero columns}
-set flagMeaning(NoColumns1) {zero columns if RHS argument is present}
-
-set pragma_def {
- NAME: full_column_names
- TYPE: FLAG
- ARG: SQLITE_FullColNames
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: short_column_names
- TYPE: FLAG
- ARG: SQLITE_ShortColNames
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: count_changes
- TYPE: FLAG
- ARG: SQLITE_CountRows
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: empty_result_callbacks
- TYPE: FLAG
- ARG: SQLITE_NullCallback
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: legacy_file_format
- TYPE: FLAG
- ARG: SQLITE_LegacyFileFmt
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: fullfsync
- TYPE: FLAG
- ARG: SQLITE_FullFSync
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: checkpoint_fullfsync
- TYPE: FLAG
- ARG: SQLITE_CkptFullFSync
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: cache_spill
- FLAG: Result0 SchemaReq NoColumns1
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: reverse_unordered_selects
- TYPE: FLAG
- ARG: SQLITE_ReverseOrder
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: query_only
- TYPE: FLAG
- ARG: SQLITE_QueryOnly
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: automatic_index
- TYPE: FLAG
- ARG: SQLITE_AutoIndex
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
-
- NAME: sql_trace
- TYPE: FLAG
- ARG: SQLITE_SqlTrace
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_listing
- TYPE: FLAG
- ARG: SQLITE_VdbeListing
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_trace
- TYPE: FLAG
- ARG: SQLITE_VdbeTrace
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_addoptrace
- TYPE: FLAG
- ARG: SQLITE_VdbeAddopTrace
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_debug
- TYPE: FLAG
- ARG: SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_eqp
- TYPE: FLAG
- ARG: SQLITE_VdbeEQP
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: ignore_check_constraints
- TYPE: FLAG
- ARG: SQLITE_IgnoreChecks
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: !defined(SQLITE_OMIT_CHECK)
-
- NAME: writable_schema
- TYPE: FLAG
- ARG: SQLITE_WriteSchema
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: read_uncommitted
- TYPE: FLAG
- ARG: SQLITE_ReadUncommit
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: recursive_triggers
- TYPE: FLAG
- ARG: SQLITE_RecTriggers
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: foreign_keys
- TYPE: FLAG
- ARG: SQLITE_ForeignKeys
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-
- NAME: defer_foreign_keys
- TYPE: FLAG
- ARG: SQLITE_DeferFKs
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-
- NAME: cell_size_check
- TYPE: FLAG
- ARG: SQLITE_CellSizeCk
-
- NAME: default_cache_size
- FLAG: NeedSchema Result0 SchemaReq NoColumns1
- COLS: cache_size
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
-
- NAME: page_size
- FLAG: Result0 SchemaReq NoColumns1
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: secure_delete
- FLAG: Result0
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: page_count
- FLAG: NeedSchema Result0 SchemaReq
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: max_page_count
- TYPE: PAGE_COUNT
- FLAG: NeedSchema Result0 SchemaReq
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: locking_mode
- FLAG: Result0 SchemaReq
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: journal_mode
- FLAG: NeedSchema Result0 SchemaReq
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: journal_size_limit
- FLAG: Result0 SchemaReq
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: cache_size
- FLAG: NeedSchema Result0 SchemaReq NoColumns1
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: mmap_size
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: auto_vacuum
- FLAG: NeedSchema Result0 SchemaReq NoColumns1
- IF: !defined(SQLITE_OMIT_AUTOVACUUM)
-
- NAME: incremental_vacuum
- FLAG: NeedSchema NoColumns
- IF: !defined(SQLITE_OMIT_AUTOVACUUM)
-
- NAME: temp_store
- FLAG: Result0 NoColumns1
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: temp_store_directory
- FLAG: NoColumns1
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: data_store_directory
- FLAG: NoColumns1
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
-
- NAME: lock_proxy_file
- FLAG: NoColumns1
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
-
- NAME: synchronous
- FLAG: NeedSchema Result0 SchemaReq NoColumns1
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: table_info
- FLAG: NeedSchema Result1 SchemaOpt
- COLS: cid name type notnull dflt_value pk
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: stats
- FLAG: NeedSchema Result0 SchemaReq
- COLS: tbl idx wdth hght flgs
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
-
- NAME: index_info
- TYPE: INDEX_INFO
- ARG: 0
- FLAG: NeedSchema Result1 SchemaOpt
- COLS: seqno cid name
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: index_xinfo
- TYPE: INDEX_INFO
- ARG: 1
- FLAG: NeedSchema Result1 SchemaOpt
- COLS: seqno cid name desc coll key
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: index_list
- FLAG: NeedSchema Result1 SchemaOpt
- COLS: seq name unique origin partial
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: database_list
- FLAG: NeedSchema Result0
- COLS: seq name file
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: function_list
- FLAG: Result0
- COLS: name builtin
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- IF: defined(SQLITE_INTROSPECTION_PRAGMAS)
-
- NAME: module_list
- FLAG: Result0
- COLS: name
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- IF: !defined(SQLITE_OMIT_VIRTUALTABLE)
- IF: defined(SQLITE_INTROSPECTION_PRAGMAS)
-
- NAME: pragma_list
- FLAG: Result0
- COLS: name
- IF: defined(SQLITE_INTROSPECTION_PRAGMAS)
-
- NAME: collation_list
- FLAG: Result0
- COLS: seq name
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: foreign_key_list
- FLAG: NeedSchema Result1 SchemaOpt
- COLS: id seq table from to on_update on_delete match
- IF: !defined(SQLITE_OMIT_FOREIGN_KEY)
-
- NAME: foreign_key_check
- FLAG: NeedSchema Result0
- COLS: table rowid parent fkid
- IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-
- NAME: parser_trace
- IF: defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
-
- NAME: case_sensitive_like
- FLAG: NoColumns
-
- NAME: integrity_check
- FLAG: NeedSchema Result0 Result1
- IF: !defined(SQLITE_OMIT_INTEGRITY_CHECK)
-
- NAME: quick_check
- TYPE: INTEGRITY_CHECK
- FLAG: NeedSchema Result0 Result1
- IF: !defined(SQLITE_OMIT_INTEGRITY_CHECK)
-
- NAME: encoding
- FLAG: Result0 NoColumns1
- IF: !defined(SQLITE_OMIT_UTF16)
-
- NAME: schema_version
- TYPE: HEADER_VALUE
- ARG: BTREE_SCHEMA_VERSION
- FLAG: NoColumns1 Result0
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: user_version
- TYPE: HEADER_VALUE
- ARG: BTREE_USER_VERSION
- FLAG: NoColumns1 Result0
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: data_version
- TYPE: HEADER_VALUE
- ARG: BTREE_DATA_VERSION
- FLAG: ReadOnly Result0
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: freelist_count
- TYPE: HEADER_VALUE
- ARG: BTREE_FREE_PAGE_COUNT
- FLAG: ReadOnly Result0
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: application_id
- TYPE: HEADER_VALUE
- ARG: BTREE_APPLICATION_ID
- FLAG: NoColumns1 Result0
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: compile_options
- FLAG: Result0
- IF: !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
-
- NAME: wal_checkpoint
- FLAG: NeedSchema
- COLS: busy log checkpointed
- IF: !defined(SQLITE_OMIT_WAL)
-
- NAME: wal_autocheckpoint
- IF: !defined(SQLITE_OMIT_WAL)
-
- NAME: shrink_memory
- FLAG: NoColumns
-
- NAME: busy_timeout
- FLAG: Result0
- COLS: timeout
-
- NAME: lock_status
- FLAG: Result0
- COLS: database status
- IF: defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
-
- NAME: key
- IF: defined(SQLITE_HAS_CODEC)
-
- NAME: rekey
- IF: defined(SQLITE_HAS_CODEC)
-
- NAME: hexkey
- IF: defined(SQLITE_HAS_CODEC)
-
- NAME: hexrekey
- TYPE: HEXKEY
- IF: defined(SQLITE_HAS_CODEC)
-
- NAME: activate_extensions
- IF: defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
-
- NAME: soft_heap_limit
- FLAG: Result0
-
- NAME: threads
- FLAG: Result0
-
- NAME: optimize
- FLAG: Result1 NeedSchema
-}
-
-# Open the output file
-#
-set destfile "[file dir [file dir [file normal $argv0]]]/src/pragma.h"
-puts "Overwriting $destfile with new pragma table..."
-set fd [open $destfile wb]
-puts $fd {/* DO NOT EDIT!
-** This file is automatically generated by the script at
-** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit
-** that script and rerun it.
-*/}
-
-# Parse the PRAGMA table above.
-#
-set name {}
-set type {}
-set if {}
-set flags {}
-set cols {}
-set cols_list {}
-set arg 0
-proc record_one {} {
- global name type if arg allbyname typebyif flags cols allcols
- global cols_list colUsedBy
- if {$name==""} return
- if {$cols!=""} {
- if {![info exists allcols($cols)]} {
- lappend cols_list $cols
- set allcols($cols) [llength $cols_list]
- }
- set cx $allcols($cols)
- lappend colUsedBy($cols) $name
- } else {
- set cx 0
- }
- set allbyname($name) [list $type $arg $if $flags $cx]
- set name {}
- set type {}
- set if {}
- set flags {}
- set cols {}
- set arg 0
-}
-foreach line [split $pragma_def \n] {
- set line [string trim $line]
- if {$line==""} continue
- foreach {id val} [split $line :] break
- set val [string trim $val]
- if {$id=="NAME"} {
- record_one
- set name $val
- set type [string toupper $val]
- } elseif {$id=="TYPE"} {
- set type $val
- if {$type=="FLAG"} {
- lappend flags Result0 NoColumns1
- }
- } elseif {$id=="ARG"} {
- set arg $val
- } elseif {$id=="COLS"} {
- set cols $val
- } elseif {$id=="IF"} {
- lappend if $val
- } elseif {$id=="FLAG"} {
- foreach term [split $val] {
- lappend flags $term
- set allflags($term) 1
- }
- } else {
- error "bad pragma_def line: $line"
- }
-}
-record_one
-set allnames [lsort [array names allbyname]]
-
-# Generate #defines for all pragma type names. Group the pragmas that are
-# omit in default builds (defined(SQLITE_DEBUG) and defined(SQLITE_HAS_CODEC))
-# at the end.
-#
-puts $fd "\n/* The various pragma types */"
-set pnum 0
-foreach name $allnames {
- set type [lindex $allbyname($name) 0]
- if {[info exists seentype($type)]} continue
- set if [lindex $allbyname($name) 2]
- if {[regexp SQLITE_DEBUG $if] || [regexp SQLITE_HAS_CODEC $if]} continue
- set seentype($type) 1
- puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum]
- incr pnum
-}
-foreach name $allnames {
- set type [lindex $allbyname($name) 0]
- if {[info exists seentype($type)]} continue
- set if [lindex $allbyname($name) 2]
- if {[regexp SQLITE_DEBUG $if]} continue
- set seentype($type) 1
- puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum]
- incr pnum
-}
-foreach name $allnames {
- set type [lindex $allbyname($name) 0]
- if {[info exists seentype($type)]} continue
- set seentype($type) 1
- puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum]
- incr pnum
-}
-
-# Generate #defines for flags
-#
-puts $fd "\n/* Property flags associated with various pragma. */"
-set fv 1
-foreach f [lsort [array names allflags]] {
- puts $fd [format {#define PragFlg_%-10s 0x%02x /* %s */} \
- $f $fv $flagMeaning($f)]
- set fv [expr {$fv*2}]
-}
-
-# Generate the array of column names used by pragmas that act like
-# queries.
-#
-puts $fd "\n/* Names of columns for pragmas that return multi-column result"
-puts $fd "** or that return single-column results where the name of the"
-puts $fd "** result column is different from the name of the pragma\n*/"
-puts $fd "static const char *const pragCName\[\] = {"
-set offset 0
-foreach cols $cols_list {
- set cols_offset($allcols($cols)) $offset
- set ub " /* Used by: $colUsedBy($cols) */"
- foreach c $cols {
- puts $fd [format " /* %3d */ %-14s%s" $offset \"$c\", $ub]
- set ub ""
- incr offset
- }
-}
-puts $fd "\175;"
-
-# Generate the lookup table
-#
-puts $fd "\n/* Definitions of all built-in pragmas */"
-puts $fd "typedef struct PragmaName \173"
-puts $fd " const char *const zName; /* Name of pragma */"
-puts $fd " u8 ePragTyp; /* PragTyp_XXX value */"
-puts $fd " u8 mPragFlg; /* Zero or more PragFlg_XXX values */"
-puts $fd { u8 iPragCName; /* Start of column names in pragCName[] */}
-puts $fd " u8 nPragCName; \
-/* Num of col names. 0 means use pragma name */"
-puts $fd " u32 iArg; /* Extra argument */"
-puts $fd "\175 PragmaName;"
-puts $fd "static const PragmaName aPragmaName\[\] = \173"
-
-set current_if {}
-set spacer [format { %26s } {}]
-foreach name $allnames {
- foreach {type arg if flag cx} $allbyname($name) break
- if {$cx==0} {
- set cy 0
- set nx 0
- } else {
- set cy $cols_offset($cx)
- set nx [llength [lindex $cols_list [expr {$cx-1}]]]
- }
- if {$if!=$current_if} {
- if {$current_if!=""} {
- foreach this_if $current_if {
- puts $fd "#endif"
- }
- }
- set current_if $if
- if {$current_if!=""} {
- foreach this_if $current_if {
- puts $fd "#if $this_if"
- }
- }
- }
- set typex [format PragTyp_%-23s $type,]
- if {$flag==""} {
- set flagx "0"
- } else {
- set flagx PragFlg_[join $flag {|PragFlg_}]
- }
- puts $fd " \173/* zName: */ \"$name\","
- puts $fd " /* ePragTyp: */ PragTyp_$type,"
- puts $fd " /* ePragFlg: */ $flagx,"
- puts $fd " /* ColNames: */ $cy, $nx,"
- puts $fd " /* iArg: */ $arg \175,"
-}
-if {$current_if!=""} {
- foreach this_if $current_if {
- puts $fd "#endif"
- }
-}
-puts $fd "\175;"
-
-# count the number of pragmas, for information purposes
-#
-set allcnt 0
-set dfltcnt 0
-foreach name $allnames {
- incr allcnt
- set if [lindex $allbyname($name) 2]
- if {[regexp {^defined} $if] || [regexp {[^!]defined} $if]} continue
- incr dfltcnt
-}
-puts $fd "/* Number of pragmas: $dfltcnt on by default, $allcnt total. */"
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkshellc.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkshellc.tcl
deleted file mode 100644
index 534ac6156a4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkshellc.tcl
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Run this script to generate the "shell.c" source file from
-# constituent parts.
-#
-# No arguments are required. This script determines the location
-# of its input files relative to the location of the script itself.
-# This script should be tool/mkshellc.tcl. If the directory holding
-# the script is $DIR, then the component parts are located in $DIR/../src
-# and $DIR/../ext/misc.
-#
-set topdir [file dir [file dir [file normal $argv0]]]
-set out stdout
-puts $out {/* DO NOT EDIT!
-** This file is automatically generated by the script in the canonical
-** SQLite source tree at tool/mkshellc.tcl. That script combines source
-** code from various constituent source files of SQLite into this single
-** "shell.c" file used to implement the SQLite command-line shell.
-**
-** Most of the code found below comes from the "src/shell.c.in" file in
-** the canonical SQLite source tree. That main file contains "INCLUDE"
-** lines that specify other files in the canonical source tree that are
-** inserted to getnerate this complete program source file.
-**
-** The code from multiple files is combined into this single "shell.c"
-** source file to help make the command-line program easier to compile.
-**
-** To modify this program, get a copy of the canonical SQLite source tree,
-** edit the src/shell.c.in" and/or some of the other files that are included
-** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
-*/}
-set in [open $topdir/src/shell.c.in rb]
-proc omit_redundant_typedefs {line} {
- global typedef_seen
- if {[regexp {^typedef .*;} $line]} {
- if {[info exists typedef_seen($line)]} {
- return "/* $line */"
- }
- set typedef_seen($line) 1
- }
- return $line
-}
-while {1} {
- set lx [omit_redundant_typedefs [gets $in]]
- if {[eof $in]} break;
- if {[regexp {^INCLUDE } $lx]} {
- set cfile [lindex $lx 1]
- puts $out "/************************* Begin $cfile ******************/"
- set in2 [open $topdir/src/$cfile rb]
- while {![eof $in2]} {
- set lx [omit_redundant_typedefs [gets $in2]]
- if {[regexp {^#include "sqlite} $lx]} continue
- if {[regexp {^# *include "test_windirent.h"} $lx]} {
- set lx "/* $lx */"
- }
- set lx [string map [list __declspec(dllexport) {}] $lx]
- puts $out $lx
- }
- close $in2
- puts $out "/************************* End $cfile ********************/"
- continue
- }
- puts $out $lx
-}
-close $in
-close $out
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksourceid.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksourceid.c
deleted file mode 100644
index 282f5c44140..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksourceid.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/*
-** Run this program with a single argument which is the name of the
-** Fossil "manifest" file for a project, and this program will emit on
-** standard output the "source id" for for the program.
-**
-** (1) The "source id" is the date of check-in together with the
-** SHA3 hash of the manifest file.
-**
-** (2) All individual file hashes in the manifest are verified. If any
-** source file has changed, the SHA3 hash ends with "modified".
-**
-*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <ctype.h>
-
-/* Portable 64-bit unsigned integers */
-#if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef unsigned __int64 u64;
-#else
- typedef unsigned long long int u64;
-#endif
-
-
-/*
-** Macros to determine whether the machine is big or little endian,
-** and whether or not that determination is run-time or compile-time.
-**
-** For best performance, an attempt is made to guess at the byte-order
-** using C-preprocessor macros. If that is unsuccessful, or if
-** -DBYTEORDER=0 is set, then byte-order is determined
-** at run-time.
-*/
-#ifndef BYTEORDER
-# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
- defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)
-# define BYTEORDER 1234
-# elif defined(sparc) || defined(__ppc__)
-# define BYTEORDER 4321
-# else
-# define BYTEORDER 0
-# endif
-#endif
-
-
-
-/*
-** State structure for a SHA3 hash in progress
-*/
-typedef struct SHA3Context SHA3Context;
-struct SHA3Context {
- union {
- u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
- unsigned char x[1600]; /* ... or 1600 bytes */
- } u;
- unsigned nRate; /* Bytes of input accepted per Keccak iteration */
- unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
- unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
-};
-
-/*
-** A single step of the Keccak mixing function for a 1600-bit state
-*/
-static void KeccakF1600Step(SHA3Context *p){
- int i;
- u64 B0, B1, B2, B3, B4;
- u64 C0, C1, C2, C3, C4;
- u64 D0, D1, D2, D3, D4;
- static const u64 RC[] = {
- 0x0000000000000001ULL, 0x0000000000008082ULL,
- 0x800000000000808aULL, 0x8000000080008000ULL,
- 0x000000000000808bULL, 0x0000000080000001ULL,
- 0x8000000080008081ULL, 0x8000000000008009ULL,
- 0x000000000000008aULL, 0x0000000000000088ULL,
- 0x0000000080008009ULL, 0x000000008000000aULL,
- 0x000000008000808bULL, 0x800000000000008bULL,
- 0x8000000000008089ULL, 0x8000000000008003ULL,
- 0x8000000000008002ULL, 0x8000000000000080ULL,
- 0x000000000000800aULL, 0x800000008000000aULL,
- 0x8000000080008081ULL, 0x8000000000008080ULL,
- 0x0000000080000001ULL, 0x8000000080008008ULL
- };
-# define A00 (p->u.s[0])
-# define A01 (p->u.s[1])
-# define A02 (p->u.s[2])
-# define A03 (p->u.s[3])
-# define A04 (p->u.s[4])
-# define A10 (p->u.s[5])
-# define A11 (p->u.s[6])
-# define A12 (p->u.s[7])
-# define A13 (p->u.s[8])
-# define A14 (p->u.s[9])
-# define A20 (p->u.s[10])
-# define A21 (p->u.s[11])
-# define A22 (p->u.s[12])
-# define A23 (p->u.s[13])
-# define A24 (p->u.s[14])
-# define A30 (p->u.s[15])
-# define A31 (p->u.s[16])
-# define A32 (p->u.s[17])
-# define A33 (p->u.s[18])
-# define A34 (p->u.s[19])
-# define A40 (p->u.s[20])
-# define A41 (p->u.s[21])
-# define A42 (p->u.s[22])
-# define A43 (p->u.s[23])
-# define A44 (p->u.s[24])
-# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
-
- for(i=0; i<24; i+=4){
- C0 = A00^A10^A20^A30^A40;
- C1 = A01^A11^A21^A31^A41;
- C2 = A02^A12^A22^A32^A42;
- C3 = A03^A13^A23^A33^A43;
- C4 = A04^A14^A24^A34^A44;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
-
- B0 = (A00^D0);
- B1 = ROL64((A11^D1), 44);
- B2 = ROL64((A22^D2), 43);
- B3 = ROL64((A33^D3), 21);
- B4 = ROL64((A44^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i];
- A11 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
-
- B2 = ROL64((A20^D0), 3);
- B3 = ROL64((A31^D1), 45);
- B4 = ROL64((A42^D2), 61);
- B0 = ROL64((A03^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A20 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
-
- B4 = ROL64((A40^D0), 18);
- B0 = ROL64((A01^D1), 1);
- B1 = ROL64((A12^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A34^D4), 8);
- A40 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
-
- B1 = ROL64((A10^D0), 36);
- B2 = ROL64((A21^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A43^D3), 56);
- B0 = ROL64((A04^D4), 27);
- A10 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
-
- B3 = ROL64((A30^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A02^D2), 62);
- B1 = ROL64((A13^D3), 55);
- B2 = ROL64((A24^D4), 39);
- A30 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
-
- C0 = A00^A20^A40^A10^A30;
- C1 = A11^A31^A01^A21^A41;
- C2 = A22^A42^A12^A32^A02;
- C3 = A33^A03^A23^A43^A13;
- C4 = A44^A14^A34^A04^A24;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
-
- B0 = (A00^D0);
- B1 = ROL64((A31^D1), 44);
- B2 = ROL64((A12^D2), 43);
- B3 = ROL64((A43^D3), 21);
- B4 = ROL64((A24^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+1];
- A31 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
-
- B2 = ROL64((A40^D0), 3);
- B3 = ROL64((A21^D1), 45);
- B4 = ROL64((A02^D2), 61);
- B0 = ROL64((A33^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A40 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
-
- B4 = ROL64((A30^D0), 18);
- B0 = ROL64((A11^D1), 1);
- B1 = ROL64((A42^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A04^D4), 8);
- A30 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
-
- B1 = ROL64((A20^D0), 36);
- B2 = ROL64((A01^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A13^D3), 56);
- B0 = ROL64((A44^D4), 27);
- A20 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
-
- B3 = ROL64((A10^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A22^D2), 62);
- B1 = ROL64((A03^D3), 55);
- B2 = ROL64((A34^D4), 39);
- A10 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
-
- C0 = A00^A40^A30^A20^A10;
- C1 = A31^A21^A11^A01^A41;
- C2 = A12^A02^A42^A32^A22;
- C3 = A43^A33^A23^A13^A03;
- C4 = A24^A14^A04^A44^A34;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
-
- B0 = (A00^D0);
- B1 = ROL64((A21^D1), 44);
- B2 = ROL64((A42^D2), 43);
- B3 = ROL64((A13^D3), 21);
- B4 = ROL64((A34^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+2];
- A21 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
-
- B2 = ROL64((A30^D0), 3);
- B3 = ROL64((A01^D1), 45);
- B4 = ROL64((A22^D2), 61);
- B0 = ROL64((A43^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A30 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
-
- B4 = ROL64((A10^D0), 18);
- B0 = ROL64((A31^D1), 1);
- B1 = ROL64((A02^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A44^D4), 8);
- A10 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
-
- B1 = ROL64((A40^D0), 36);
- B2 = ROL64((A11^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A03^D3), 56);
- B0 = ROL64((A24^D4), 27);
- A40 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
-
- B3 = ROL64((A20^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A12^D2), 62);
- B1 = ROL64((A33^D3), 55);
- B2 = ROL64((A04^D4), 39);
- A20 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
-
- C0 = A00^A30^A10^A40^A20;
- C1 = A21^A01^A31^A11^A41;
- C2 = A42^A22^A02^A32^A12;
- C3 = A13^A43^A23^A03^A33;
- C4 = A34^A14^A44^A24^A04;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
-
- B0 = (A00^D0);
- B1 = ROL64((A01^D1), 44);
- B2 = ROL64((A02^D2), 43);
- B3 = ROL64((A03^D3), 21);
- B4 = ROL64((A04^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+3];
- A01 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
-
- B2 = ROL64((A10^D0), 3);
- B3 = ROL64((A11^D1), 45);
- B4 = ROL64((A12^D2), 61);
- B0 = ROL64((A13^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A10 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
-
- B4 = ROL64((A20^D0), 18);
- B0 = ROL64((A21^D1), 1);
- B1 = ROL64((A22^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A24^D4), 8);
- A20 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
-
- B1 = ROL64((A30^D0), 36);
- B2 = ROL64((A31^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A33^D3), 56);
- B0 = ROL64((A34^D4), 27);
- A30 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
-
- B3 = ROL64((A40^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A42^D2), 62);
- B1 = ROL64((A43^D3), 55);
- B2 = ROL64((A44^D4), 39);
- A40 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
- }
-}
-
-/*
-** Initialize a new hash. iSize determines the size of the hash
-** in bits and should be one of 224, 256, 384, or 512. Or iSize
-** can be zero to use the default hash size of 256 bits.
-*/
-static void SHA3Init(SHA3Context *p, int iSize){
- memset(p, 0, sizeof(*p));
- if( iSize>=128 && iSize<=512 ){
- p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
- }else{
- p->nRate = (1600 - 2*256)/8;
- }
-#if BYTEORDER==1234
- /* Known to be little-endian at compile-time. No-op */
-#elif BYTEORDER==4321
- p->ixMask = 7; /* Big-endian */
-#else
- {
- static unsigned int one = 1;
- if( 1==*(unsigned char*)&one ){
- /* Little endian. No byte swapping. */
- p->ixMask = 0;
- }else{
- /* Big endian. Byte swap. */
- p->ixMask = 7;
- }
- }
-#endif
-}
-
-/*
-** Make consecutive calls to the SHA3Update function to add new content
-** to the hash
-*/
-static void SHA3Update(
- SHA3Context *p,
- const unsigned char *aData,
- unsigned int nData
-){
- unsigned int i = 0;
-#if BYTEORDER==1234
- if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
- for(; i+7<nData; i+=8){
- p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
- p->nLoaded += 8;
- if( p->nLoaded>=p->nRate ){
- KeccakF1600Step(p);
- p->nLoaded = 0;
- }
- }
- }
-#endif
- for(; i<nData; i++){
-#if BYTEORDER==1234
- p->u.x[p->nLoaded] ^= aData[i];
-#elif BYTEORDER==4321
- p->u.x[p->nLoaded^0x07] ^= aData[i];
-#else
- p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
-#endif
- p->nLoaded++;
- if( p->nLoaded==p->nRate ){
- KeccakF1600Step(p);
- p->nLoaded = 0;
- }
- }
-}
-
-/*
-** After all content has been added, invoke SHA3Final() to compute
-** the final hash. The function returns a pointer to the binary
-** hash value.
-*/
-static unsigned char *SHA3Final(SHA3Context *p){
- unsigned int i;
- if( p->nLoaded==p->nRate-1 ){
- const unsigned char c1 = 0x86;
- SHA3Update(p, &c1, 1);
- }else{
- const unsigned char c2 = 0x06;
- const unsigned char c3 = 0x80;
- SHA3Update(p, &c2, 1);
- p->nLoaded = p->nRate - 1;
- SHA3Update(p, &c3, 1);
- }
- for(i=0; i<p->nRate; i++){
- p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
- }
- return &p->u.x[p->nRate];
-}
-
-/*
-** Convert a digest into base-16. digest should be declared as
-** "unsigned char digest[20]" in the calling function. The SHA3
-** digest is stored in the first 20 bytes. zBuf should
-** be "char zBuf[41]".
-*/
-static void DigestToBase16(unsigned char *digest, char *zBuf, int nByte){
- static const char zEncode[] = "0123456789abcdef";
- int ix;
-
- for(ix=0; ix<nByte; ix++){
- *zBuf++ = zEncode[(*digest>>4)&0xf];
- *zBuf++ = zEncode[*digest++ & 0xf];
- }
- *zBuf = '\0';
-}
-
-
-/*
-** Compute the SHA3 checksum of a file on disk. Store the resulting
-** checksum in the blob pCksum. pCksum is assumed to be initialized.
-**
-** Return the number of errors.
-*/
-static int sha3sum_file(const char *zFilename, int iSize, char *pCksum){
- FILE *in;
- SHA3Context ctx;
- char zBuf[10240];
-
- in = fopen(zFilename,"rb");
- if( in==0 ){
- return 1;
- }
- SHA3Init(&ctx, iSize);
- for(;;){
- int n = (int)fread(zBuf, 1, sizeof(zBuf), in);
- if( n<=0 ) break;
- SHA3Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
- }
- fclose(in);
- DigestToBase16(SHA3Final(&ctx), pCksum, iSize/8);
- return 0;
-}
-
-/*
-** The SHA1 implementation below is adapted from:
-**
-** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $
-** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $
-**
-** SHA-1 in C
-** By Steve Reid <steve@edmweb.com>
-** 100% Public Domain
-*/
-typedef struct SHA1Context SHA1Context;
-struct SHA1Context {
- unsigned int state[5];
- unsigned int count[2];
- unsigned char buffer[64];
-};
-
-/*
- * blk0() and blk() perform the initial expand.
- * I got the idea of expanding during the round function from SSLeay
- *
- * blk0le() for little-endian and blk0be() for big-endian.
- */
-#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
-/*
- * GCC by itself only generates left rotates. Use right rotates if
- * possible to be kinder to dinky implementations with iterative rotate
- * instructions.
- */
-#define SHA_ROT(op, x, k) \
- ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
-#define rol(x,k) SHA_ROT("roll", x, k)
-#define ror(x,k) SHA_ROT("rorl", x, k)
-
-#else
-/* Generic C equivalent */
-#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
-#define rol(x,k) SHA_ROT(x,k,32-(k))
-#define ror(x,k) SHA_ROT(x,32-(k),k)
-#endif
-
-
-
-
-
-#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
- |(rol(block[i],8)&0x00FF00FF))
-#define blk0be(i) block[i]
-#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
- ^block[(i+2)&15]^block[i&15],1))
-
-/*
- * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
- *
- * Rl0() for little-endian and Rb0() for big-endian. Endianness is
- * determined at run-time.
- */
-#define Rl0(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define Rb0(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define R1(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
-#define R2(v,w,x,y,z,i) \
- z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
-#define R3(v,w,x,y,z,i) \
- z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
-#define R4(v,w,x,y,z,i) \
- z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
-
-/*
- * Hash a single 512-bit block. This is the core of the algorithm.
- */
-#define a qq[0]
-#define b qq[1]
-#define c qq[2]
-#define d qq[3]
-#define e qq[4]
-
-static void SHA1Transform(
- unsigned int state[5],
- const unsigned char buffer[64]
-){
- unsigned int qq[5]; /* a, b, c, d, e; */
- static int one = 1;
- unsigned int block[16];
- memcpy(block, buffer, 64);
- memcpy(qq,state,5*sizeof(unsigned int));
-
- /* Copy context->state[] to working vars */
- /*
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- */
-
- /* 4 rounds of 20 operations each. Loop unrolled. */
- if( 1 == *(unsigned char*)&one ){
- Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
- Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
- Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
- Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
- }else{
- Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
- Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
- Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
- Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
- }
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
-}
-
-
-/*
- * SHA1Init - Initialize new context
- */
-static void SHA1Init(SHA1Context *context){
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
-}
-
-
-/*
- * Run your data through this.
- */
-static void SHA1Update(
- SHA1Context *context,
- const unsigned char *data,
- unsigned int len
-){
- unsigned int i, j;
-
- j = context->count[0];
- if ((context->count[0] += len << 3) < j)
- context->count[1] += (len>>29)+1;
- j = (j >> 3) & 63;
- if ((j + len) > 63) {
- (void)memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64)
- SHA1Transform(context->state, &data[i]);
- j = 0;
- } else {
- i = 0;
- }
- (void)memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/*
- * Add padding and return the message digest.
- */
-static void SHA1Final(unsigned char *digest, SHA1Context *context){
- unsigned int i;
- unsigned char finalcount[8];
-
- for (i = 0; i < 8; i++) {
- finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
- }
- SHA1Update(context, (const unsigned char *)"\200", 1);
- while ((context->count[0] & 504) != 448)
- SHA1Update(context, (const unsigned char *)"\0", 1);
- SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
-
- if (digest) {
- for (i = 0; i < 20; i++)
- digest[i] = (unsigned char)
- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
-}
-
-
-/*
-** Compute the SHA1 checksum of a file on disk. Store the resulting
-** checksum in the blob pCksum. pCksum is assumed to be initialized.
-**
-** Return the number of errors.
-*/
-static int sha1sum_file(const char *zFilename, char *pCksum){
- FILE *in;
- SHA1Context ctx;
- unsigned char zResult[20];
- char zBuf[10240];
-
- in = fopen(zFilename,"rb");
- if( in==0 ){
- return 1;
- }
- SHA1Init(&ctx);
- for(;;){
- int n = (int)fread(zBuf, 1, sizeof(zBuf), in);
- if( n<=0 ) break;
- SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
- }
- fclose(in);
- SHA1Final(zResult, &ctx);
- DigestToBase16(zResult, pCksum, 20);
- return 0;
-}
-
-/*
-** Print a usage comment and quit.
-*/
-static void usage(const char *argv0){
- fprintf(stderr,
- "Usage: %s manifest\n"
- "Options:\n"
- " -v Diagnostic output\n"
- , argv0);
- exit(1);
-}
-
-/*
-** Find the first whitespace character in a string. Set that whitespace
-** to a \000 terminator and return a pointer to the next character.
-*/
-static char *nextToken(char *z){
- while( *z && !isspace(*z) ) z++;
- if( *z==0 ) return z;
- *z = 0;
- return &z[1];
-}
-
-
-int main(int argc, char **argv){
- const char *zManifest = 0;
- int i;
- int bVerbose = 0;
- FILE *in;
- int allValid = 1;
- int rc;
- SHA3Context ctx;
- char zDate[50];
- char zHash[100];
- char zLine[20000];
-
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]=='-' ){
- if( z[1]=='-' ) z++;
- if( strcmp(z, "-v")==0 ){
- bVerbose = 1;
- }else
- {
- fprintf(stderr, "unknown option \"%s\"", argv[i]);
- exit(1);
- }
- }else if( zManifest!=0 ){
- usage(argv[0]);
- }else{
- zManifest = z;
- }
- }
- if( zManifest==0 ) usage(argv[0]);
- zDate[0] = 0;
- in = fopen(zManifest, "rb");
- if( in==0 ){
- fprintf(stderr, "cannot open \"%s\" for reading\n", zManifest);
- exit(1);
- }
- SHA3Init(&ctx, 256);
- while( fgets(zLine, sizeof(zLine), in) ){
- if( strncmp(zLine,"# Remove this line", 18)!=0 ){
- SHA3Update(&ctx, (unsigned char*)zLine, (unsigned)strlen(zLine));
- }
- if( strncmp(zLine, "D 20", 4)==0 ){
- memcpy(zDate, &zLine[2], 10);
- zDate[10] = ' ';
- memcpy(&zDate[11], &zLine[13], 8);
- zDate[19] = 0;
- continue;
- }
- if( strncmp(zLine, "F ", 2)==0 ){
- char *zFilename = &zLine[2];
- char *zMHash = nextToken(zFilename);
- nextToken(zMHash);
- if( strlen(zMHash)==40 ){
- rc = sha1sum_file(zFilename, zHash);
- }else{
- rc = sha3sum_file(zFilename, 256, zHash);
- }
- if( rc ){
- allValid = 0;
- if( bVerbose ){
- printf("hash failed: %s\n", zFilename);
- }
- }else if( strcmp(zHash, zMHash)!=0 ){
- allValid = 0;
- if( bVerbose ){
- printf("wrong hash: %s\n", zFilename);
- printf("... expected: %s\n", zMHash);
- printf("... got: %s\n", zHash);
- }
- }
- }
- }
- fclose(in);
- DigestToBase16(SHA3Final(&ctx), zHash, 256/8);
- if( !allValid ){
- printf("%s %.60salt1\n", zDate, zHash);
- }else{
- printf("%s %s\n", zDate, zHash);
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkspeedsql.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkspeedsql.tcl
deleted file mode 100644
index 04bafc04c1b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkspeedsql.tcl
+++ /dev/null
@@ -1,237 +0,0 @@
-# 2008 October 9
-#
-# 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 generates SQL text used for performance testing.
-#
-# $Id: mkspeedsql.tcl,v 1.1 2008/10/09 17:57:34 drh Exp $
-#
-
-# Set a uniform random seed
-expr srand(0)
-
-# The number_name procedure below converts its argment (an integer)
-# into a string which is the English-language name for that number.
-#
-# Example:
-#
-# puts [number_name 123] -> "one hundred twenty three"
-#
-set ones {zero one two three four five six seven eight nine
- ten eleven twelve thirteen fourteen fifteen sixteen seventeen
- eighteen nineteen}
-set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
-proc number_name {n} {
- if {$n>=1000} {
- set txt "[number_name [expr {$n/1000}]] thousand"
- set n [expr {$n%1000}]
- } else {
- set txt {}
- }
- if {$n>=100} {
- append txt " [lindex $::ones [expr {$n/100}]] hundred"
- set n [expr {$n%100}]
- }
- if {$n>=20} {
- append txt " [lindex $::tens [expr {$n/10}]]"
- set n [expr {$n%10}]
- }
- if {$n>0} {
- append txt " [lindex $::ones $n]"
- }
- set txt [string trim $txt]
- if {$txt==""} {set txt zero}
- return $txt
-}
-
-# Create a database schema.
-#
-puts {
- PRAGMA page_size=1024;
- PRAGMA cache_size=8192;
- PRAGMA locking_mode=EXCLUSIVE;
- CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT);
- CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT);
- CREATE INDEX i2a ON t2(a);
- CREATE INDEX i2b ON t2(b);
- SELECT name FROM sqlite_master ORDER BY 1;
-}
-
-
-# 50000 INSERTs on an unindexed table
-#
-set t1c_list {}
-puts {BEGIN;}
-for {set i 1} {$i<=50000} {incr i} {
- set r [expr {int(rand()*500000)}]
- set x [number_name $r]
- lappend t1c_list $x
- puts "INSERT INTO t1 VALUES($i,$r,'$x');"
-}
-puts {COMMIT;}
-
-# 50000 INSERTs on an indexed table
-#
-puts {BEGIN;}
-for {set i 1} {$i<=50000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts "INSERT INTO t2 VALUES($i,$r,'[number_name $r]');"
-}
-puts {COMMIT;}
-
-
-# 50 SELECTs on an integer comparison. There is no index so
-# a full table scan is required.
-#
-for {set i 0} {$i<50} {incr i} {
- set lwr [expr {$i*100}]
- set upr [expr {($i+10)*100}]
- puts "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
-}
-
-# 50 SELECTs on an LIKE comparison. There is no index so a full
-# table scan is required.
-#
-for {set i 0} {$i<50} {incr i} {
- puts "SELECT count(*), avg(b) FROM t1 WHERE c LIKE '%[number_name $i]%';"
-}
-
-# Create indices
-#
-puts {BEGIN;}
-puts {
- CREATE INDEX i1a ON t1(a);
- CREATE INDEX i1b ON t1(b);
- CREATE INDEX i1c ON t1(c);
-}
-puts {COMMIT;}
-
-# 5000 SELECTs on an integer comparison where the integer is
-# indexed.
-#
-set sql {}
-for {set i 0} {$i<5000} {incr i} {
- set lwr [expr {$i*100}]
- set upr [expr {($i+10)*100}]
- puts "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
-}
-
-# 100000 random SELECTs against rowid.
-#
-for {set i 1} {$i<=100000} {incr i} {
- set id [expr {int(rand()*50000)+1}]
- puts "SELECT c FROM t1 WHERE rowid=$id;"
-}
-
-# 100000 random SELECTs against a unique indexed column.
-#
-for {set i 1} {$i<=100000} {incr i} {
- set id [expr {int(rand()*50000)+1}]
- puts "SELECT c FROM t1 WHERE a=$id;"
-}
-
-# 50000 random SELECTs against an indexed column text column
-#
-set nt1c [llength $t1c_list]
-for {set i 0} {$i<50000} {incr i} {
- set r [expr {int(rand()*$nt1c)}]
- set c [lindex $t1c_list $i]
- puts "SELECT c FROM t1 WHERE c='$c';"
-}
-
-
-# Vacuum
-puts {VACUUM;}
-
-# 5000 updates of ranges where the field being compared is indexed.
-#
-puts {BEGIN;}
-for {set i 0} {$i<5000} {incr i} {
- set lwr [expr {$i*2}]
- set upr [expr {($i+1)*2}]
- puts "UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr;"
-}
-puts {COMMIT;}
-
-# 50000 single-row updates. An index is used to find the row quickly.
-#
-puts {BEGIN;}
-for {set i 0} {$i<50000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts "UPDATE t1 SET b=$r WHERE a=$i;"
-}
-puts {COMMIT;}
-
-# 1 big text update that touches every row in the table.
-#
-puts {
- UPDATE t1 SET c=a;
-}
-
-# Many individual text updates. Each row in the table is
-# touched through an index.
-#
-puts {BEGIN;}
-for {set i 1} {$i<=50000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts "UPDATE t1 SET c='[number_name $r]' WHERE a=$i;"
-}
-puts {COMMIT;}
-
-# Delete all content in a table.
-#
-puts {DELETE FROM t1;}
-
-# Copy one table into another
-#
-puts {INSERT INTO t1 SELECT * FROM t2;}
-
-# Delete all content in a table, one row at a time.
-#
-puts {DELETE FROM t1 WHERE 1;}
-
-# Refill the table yet again
-#
-puts {INSERT INTO t1 SELECT * FROM t2;}
-
-# Drop the table and recreate it without its indices.
-#
-puts {BEGIN;}
-puts {
- DROP TABLE t1;
- CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT);
-}
-puts {COMMIT;}
-
-# Refill the table yet again. This copy should be faster because
-# there are no indices to deal with.
-#
-puts {INSERT INTO t1 SELECT * FROM t2;}
-
-# Select 20000 rows from the table at random.
-#
-puts {
- SELECT rowid FROM t1 ORDER BY random() LIMIT 20000;
-}
-
-# Delete 20000 random rows from the table.
-#
-puts {
- DELETE FROM t1 WHERE rowid IN
- (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000);
-}
-puts {SELECT count(*) FROM t1;}
-
-# Delete 20000 more rows at random from the table.
-#
-puts {
- DELETE FROM t1 WHERE rowid IN
- (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000);
-}
-puts {SELECT count(*) FROM t1;}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3c-noext.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3c-noext.tcl
deleted file mode 100644
index a16b0591eb5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3c-noext.tcl
+++ /dev/null
@@ -1,366 +0,0 @@
-#!/usr/bin/tclsh
-#
-# To build a single huge source file holding all of SQLite (or at
-# least the core components - the test harness, shell, and TCL
-# interface are omitted.) first do
-#
-# make target_source
-#
-# The make target above moves all of the source code files into
-# a subdirectory named "tsrc". (This script expects to find the files
-# there and will not work if they are not found.) There are a few
-# generated C code files that are also added to the tsrc directory.
-# For example, the "parse.c" and "parse.h" files to implement the
-# the parser are derived from "parse.y" using lemon. And the
-# "keywordhash.h" files is generated by a program named "mkkeywordhash".
-#
-# After the "tsrc" directory has been created and populated, run
-# this script:
-#
-# tclsh mksqlite3c-noext.tcl
-#
-# The amalgamated SQLite code will be written into sqlite3.c
-#
-
-# Begin by reading the "sqlite3.h" header file. Extract the version number
-# from in this file. The version number is needed to generate the header
-# comment of the amalgamation.
-#
-set addstatic 1
-set linemacros 0
-set useapicall 0
-for {set i 0} {$i<[llength $argv]} {incr i} {
- set x [lindex $argv $i]
- if {[regexp {^-+nostatic$} $x]} {
- set addstatic 0
- } elseif {[regexp {^-+linemacros} $x]} {
- set linemacros 1
- } elseif {[regexp {^-+useapicall} $x]} {
- set useapicall 1
- } else {
- error "unknown command-line option: $x"
- }
-}
-set in [open tsrc/sqlite3.h]
-set cnt 0
-set VERSION ?????
-while {![eof $in]} {
- set line [gets $in]
- if {$line=="" && [eof $in]} break
- incr cnt
- regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
-}
-close $in
-
-# Open the output file and write a header comment at the beginning
-# of the file.
-#
-set out [open sqlite3.c w]
-# Force the output to use unix line endings, even on Windows.
-fconfigure $out -translation lf
-set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
-puts $out [subst \
-{/******************************************************************************
-** This file is an amalgamation of many separate C source files from SQLite
-** version $VERSION. By combining all the individual C code files into this
-** single large file, the entire code can be compiled as a single translation
-** unit. This allows many compilers to do optimizations that would not be
-** possible if the files were compiled separately. Performance improvements
-** of 5% or more are commonly seen when SQLite is compiled as a single
-** translation unit.
-**
-** This file is all you need to compile SQLite. To use SQLite in other
-** programs, you need this file and the "sqlite3.h" header file that defines
-** the programming interface to the SQLite library. (If you do not have
-** the "sqlite3.h" header file at hand, you will find a copy embedded within
-** the text of this file. Search for "Begin file sqlite3.h" to find the start
-** of the embedded sqlite3.h header file.) Additional code files may be needed
-** if you want a wrapper to interface SQLite with your choice of programming
-** language. The code for the "sqlite3" command-line shell is also in a
-** separate file. This file contains only code for the core SQLite library.
-*/
-#define SQLITE_CORE 1
-#define SQLITE_AMALGAMATION 1}]
-if {$addstatic} {
- puts $out \
-{#ifndef SQLITE_PRIVATE
-# define SQLITE_PRIVATE static
-#endif}
-}
-
-# These are the header files used by SQLite. The first time any of these
-# files are seen in a #include statement in the C code, include the complete
-# text of the file in-line. The file only needs to be included once.
-#
-foreach hdr {
- btree.h
- btreeInt.h
- hash.h
- hwtime.h
- keywordhash.h
- msvc.h
- mutex.h
- opcodes.h
- os_common.h
- os_setup.h
- os_win.h
- os.h
- pager.h
- parse.h
- pcache.h
- pragma.h
- sqlite3.h
- sqlite3ext.h
- sqliteicu.h
- sqliteInt.h
- sqliteLimit.h
- vdbe.h
- vdbeInt.h
- vxworks.h
- wal.h
- whereInt.h
-} {
- set available_hdr($hdr) 1
-}
-set available_hdr(sqliteInt.h) 0
-
-# These headers should be copied into the amalgamation without modifying any
-# of their function declarations or definitions.
-set varonly_hdr(sqlite3.h) 1
-
-# These are the functions that accept a variable number of arguments. They
-# always need to use the "cdecl" calling convention even when another calling
-# convention (e.g. "stcall") is being used for the rest of the library.
-set cdecllist {
- sqlite3_config
- sqlite3_db_config
- sqlite3_log
- sqlite3_mprintf
- sqlite3_snprintf
- sqlite3_test_control
- sqlite3_vtab_config
-}
-
-# 78 stars used for comment formatting.
-set s78 \
-{*****************************************************************************}
-
-# Insert a comment into the code
-#
-proc section_comment {text} {
- global out s78
- set n [string length $text]
- set nstar [expr {60 - $n}]
- set stars [string range $s78 0 $nstar]
- puts $out "/************** $text $stars/"
-}
-
-# Read the source file named $filename and write it into the
-# sqlite3.c output file. If any #include statements are seen,
-# process them appropriately.
-#
-proc copy_file {filename} {
- global seen_hdr available_hdr varonly_hdr cdecllist out
- global addstatic linemacros useapicall
- set ln 0
- set tail [file tail $filename]
- section_comment "Begin file $tail"
- if {$linemacros} {puts $out "#line 1 \"$filename\""}
- set in [open $filename r]
- set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
- set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
- if {[file extension $filename]==".h"} {
- set declpattern " *$declpattern"
- }
- set declpattern ^$declpattern\$
- while {![eof $in]} {
- set line [gets $in]
- incr ln
- if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
- if {[info exists available_hdr($hdr)]} {
- if {$available_hdr($hdr)} {
- if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
- set available_hdr($hdr) 0
- }
- section_comment "Include $hdr in the middle of $tail"
- copy_file tsrc/$hdr
- section_comment "Continuing where we left off in $tail"
- if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
- } else {
- # Comment out the entire line, replacing any nested comment
- # begin/end markers with the harmless substring "**".
- puts $out "/* [string map [list /* ** */ **] $line] */"
- }
- } elseif {![info exists seen_hdr($hdr)]} {
- if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
- set seen_hdr($hdr) 1
- }
- puts $out $line
- } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
- # This include file must be kept because there was a "keep"
- # directive inside of a line comment.
- puts $out $line
- } else {
- # Comment out the entire line, replacing any nested comment
- # begin/end markers with the harmless substring "**".
- puts $out "/* [string map [list /* ** */ **] $line] */"
- }
- } elseif {[regexp {^#ifdef __cplusplus} $line]} {
- puts $out "#if 0"
- } elseif {!$linemacros && [regexp {^#line} $line]} {
- # Skip #line directives.
- } elseif {$addstatic
- && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
- # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
- # functions if this header file does not need it.
- if {![info exists varonly_hdr($tail)]
- && [regexp $declpattern $line all rettype funcname rest]} {
- regsub {^SQLITE_API } $line {} line
- # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
- # so that linkage can be modified at compile-time.
- if {[regexp {^sqlite3[a-z]*_} $funcname]} {
- set line SQLITE_API
- append line " " [string trim $rettype]
- if {[string index $rettype end] ne "*"} {
- append line " "
- }
- if {$useapicall} {
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL " "
- } else {
- append line SQLITE_APICALL " "
- }
- }
- append line $funcname $rest
- puts $out $line
- } else {
- puts $out "SQLITE_PRIVATE $line"
- }
- } elseif {[regexp $varpattern $line all varname]} {
- # Add the SQLITE_PRIVATE before variable declarations or
- # definitions for internal use
- regsub {^SQLITE_API } $line {} line
- if {![regexp {^sqlite3_} $varname]} {
- regsub {^extern } $line {} line
- puts $out "SQLITE_PRIVATE $line"
- } else {
- if {[regexp {const char sqlite3_version\[\];} $line]} {
- set line {const char sqlite3_version[] = SQLITE_VERSION;}
- }
- regsub {^SQLITE_EXTERN } $line {} line
- puts $out "SQLITE_API $line"
- }
- } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
- regsub {^SQLITE_API } $line {} line
- regsub {^SQLITE_EXTERN } $line {} line
- puts $out $line
- } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
- regsub {^SQLITE_API } $line {} line
- puts $out "SQLITE_PRIVATE $line"
- } else {
- puts $out $line
- }
- } else {
- puts $out $line
- }
- }
- close $in
- section_comment "End of $tail"
-}
-
-
-# Process the source files. Process files containing commonly
-# used subroutines first in order to help the compiler find
-# inlining opportunities.
-#
-foreach file {
- sqliteInt.h
-
- global.c
- ctime.c
- status.c
- date.c
- os.c
-
- fault.c
- mem0.c
- mem1.c
- mem2.c
- mem3.c
- mem5.c
- mutex.c
- mutex_noop.c
- mutex_unix.c
- mutex_w32.c
- malloc.c
- printf.c
- treeview.c
- random.c
- threads.c
- utf.c
- util.c
- hash.c
- opcodes.c
-
- os_unix.c
- os_win.c
-
- bitvec.c
- pcache.c
- pcache1.c
- rowset.c
- pager.c
- wal.c
-
- btmutex.c
- btree.c
- backup.c
-
- vdbemem.c
- vdbeaux.c
- vdbeapi.c
- vdbetrace.c
- vdbe.c
- vdbeblob.c
- vdbesort.c
- memjournal.c
-
- walker.c
- resolve.c
- expr.c
- alter.c
- analyze.c
- attach.c
- auth.c
- build.c
- callback.c
- delete.c
- func.c
- fkey.c
- insert.c
- legacy.c
- loadext.c
- pragma.c
- prepare.c
- select.c
- table.c
- trigger.c
- update.c
- vacuum.c
- vtab.c
- wherecode.c
- whereexpr.c
- where.c
-
- parse.c
-
- tokenize.c
- complete.c
-
- main.c
- notify.c
-} {
- copy_file tsrc/$file
-}
-
-close $out
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3c.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3c.tcl
deleted file mode 100644
index 6c1dab6accc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3c.tcl
+++ /dev/null
@@ -1,438 +0,0 @@
-#!/usr/bin/tclsh
-#
-# To build a single huge source file holding all of SQLite (or at
-# least the core components - the test harness, shell, and TCL
-# interface are omitted.) first do
-#
-# make target_source
-#
-# The make target above moves all of the source code files into
-# a subdirectory named "tsrc". (This script expects to find the files
-# there and will not work if they are not found.) There are a few
-# generated C code files that are also added to the tsrc directory.
-# For example, the "parse.c" and "parse.h" files to implement the
-# the parser are derived from "parse.y" using lemon. And the
-# "keywordhash.h" files is generated by a program named "mkkeywordhash".
-#
-# After the "tsrc" directory has been created and populated, run
-# this script:
-#
-# tclsh mksqlite3c.tcl --srcdir $SRC
-#
-# The amalgamated SQLite code will be written into sqlite3.c
-#
-
-# Begin by reading the "sqlite3.h" header file. Extract the version number
-# from in this file. The version number is needed to generate the header
-# comment of the amalgamation.
-#
-set addstatic 1
-set linemacros 0
-set useapicall 0
-for {set i 0} {$i<[llength $argv]} {incr i} {
- set x [lindex $argv $i]
- if {[regexp {^-+nostatic$} $x]} {
- set addstatic 0
- } elseif {[regexp {^-+linemacros} $x]} {
- set linemacros 1
- } elseif {[regexp {^-+useapicall} $x]} {
- set useapicall 1
- } else {
- error "unknown command-line option: $x"
- }
-}
-set in [open tsrc/sqlite3.h]
-set cnt 0
-set VERSION ?????
-while {![eof $in]} {
- set line [gets $in]
- if {$line=="" && [eof $in]} break
- incr cnt
- regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
-}
-close $in
-
-# Open the output file and write a header comment at the beginning
-# of the file.
-#
-set out [open sqlite3.c w]
-# Force the output to use unix line endings, even on Windows.
-fconfigure $out -translation lf
-set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
-puts $out [subst \
-{/******************************************************************************
-** This file is an amalgamation of many separate C source files from SQLite
-** version $VERSION. By combining all the individual C code files into this
-** single large file, the entire code can be compiled as a single translation
-** unit. This allows many compilers to do optimizations that would not be
-** possible if the files were compiled separately. Performance improvements
-** of 5% or more are commonly seen when SQLite is compiled as a single
-** translation unit.
-**
-** This file is all you need to compile SQLite. To use SQLite in other
-** programs, you need this file and the "sqlite3.h" header file that defines
-** the programming interface to the SQLite library. (If you do not have
-** the "sqlite3.h" header file at hand, you will find a copy embedded within
-** the text of this file. Search for "Begin file sqlite3.h" to find the start
-** of the embedded sqlite3.h header file.) Additional code files may be needed
-** if you want a wrapper to interface SQLite with your choice of programming
-** language. The code for the "sqlite3" command-line shell is also in a
-** separate file. This file contains only code for the core SQLite library.
-*/
-#define SQLITE_CORE 1
-#define SQLITE_AMALGAMATION 1}]
-if {$addstatic} {
- puts $out \
-{#ifndef SQLITE_PRIVATE
-# define SQLITE_PRIVATE static
-#endif}
-}
-
-# These are the header files used by SQLite. The first time any of these
-# files are seen in a #include statement in the C code, include the complete
-# text of the file in-line. The file only needs to be included once.
-#
-foreach hdr {
- btree.h
- btreeInt.h
- fts3.h
- fts3Int.h
- fts3_hash.h
- fts3_tokenizer.h
- hash.h
- hwtime.h
- keywordhash.h
- msvc.h
- mutex.h
- opcodes.h
- os_common.h
- os_setup.h
- os_win.h
- os.h
- pager.h
- parse.h
- pcache.h
- pragma.h
- rtree.h
- sqlite3session.h
- sqlite3.h
- sqlite3ext.h
- sqlite3rbu.h
- sqliteicu.h
- sqliteInt.h
- sqliteLimit.h
- vdbe.h
- vdbeInt.h
- vxworks.h
- wal.h
- whereInt.h
-} {
- set available_hdr($hdr) 1
-}
-set available_hdr(sqliteInt.h) 0
-set available_hdr(sqlite3session.h) 0
-
-# These headers should be copied into the amalgamation without modifying any
-# of their function declarations or definitions.
-set varonly_hdr(sqlite3.h) 1
-
-# These are the functions that accept a variable number of arguments. They
-# always need to use the "cdecl" calling convention even when another calling
-# convention (e.g. "stcall") is being used for the rest of the library.
-set cdecllist {
- sqlite3_config
- sqlite3_db_config
- sqlite3_log
- sqlite3_mprintf
- sqlite3_snprintf
- sqlite3_test_control
- sqlite3_vtab_config
-}
-
-# 78 stars used for comment formatting.
-set s78 \
-{*****************************************************************************}
-
-# Insert a comment into the code
-#
-proc section_comment {text} {
- global out s78
- set n [string length $text]
- set nstar [expr {60 - $n}]
- set stars [string range $s78 0 $nstar]
- puts $out "/************** $text $stars/"
-}
-
-# Read the source file named $filename and write it into the
-# sqlite3.c output file. If any #include statements are seen,
-# process them appropriately.
-#
-proc copy_file {filename} {
- global seen_hdr available_hdr varonly_hdr cdecllist out
- global addstatic linemacros useapicall
- set ln 0
- set tail [file tail $filename]
- section_comment "Begin file $tail"
- if {$linemacros} {puts $out "#line 1 \"$filename\""}
- set in [open $filename r]
- set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
- set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
- if {[file extension $filename]==".h"} {
- set declpattern " *$declpattern"
- }
- set declpattern ^$declpattern\$
- while {![eof $in]} {
- set line [gets $in]
- incr ln
- if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
- if {[info exists available_hdr($hdr)]} {
- if {$available_hdr($hdr)} {
- if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
- set available_hdr($hdr) 0
- }
- section_comment "Include $hdr in the middle of $tail"
- copy_file tsrc/$hdr
- section_comment "Continuing where we left off in $tail"
- if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
- } else {
- # Comment out the entire line, replacing any nested comment
- # begin/end markers with the harmless substring "**".
- puts $out "/* [string map [list /* ** */ **] $line] */"
- }
- } elseif {![info exists seen_hdr($hdr)]} {
- if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
- set seen_hdr($hdr) 1
- }
- puts $out $line
- } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
- # This include file must be kept because there was a "keep"
- # directive inside of a line comment.
- puts $out $line
- } else {
- # Comment out the entire line, replacing any nested comment
- # begin/end markers with the harmless substring "**".
- puts $out "/* [string map [list /* ** */ **] $line] */"
- }
- } elseif {[regexp {^#ifdef __cplusplus} $line]} {
- puts $out "#if 0"
- } elseif {!$linemacros && [regexp {^#line} $line]} {
- # Skip #line directives.
- } elseif {$addstatic
- && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
- # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
- # functions if this header file does not need it.
- if {![info exists varonly_hdr($tail)]
- && [regexp $declpattern $line all rettype funcname rest]} {
- regsub {^SQLITE_API } $line {} line
- regsub {^SQLITE_API } $rettype {} rettype
-
- # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
- # so that linkage can be modified at compile-time.
- if {[regexp {^sqlite3[a-z]*_} $funcname]} {
- set line SQLITE_API
- append line " " [string trim $rettype]
- if {[string index $rettype end] ne "*"} {
- append line " "
- }
- if {$useapicall} {
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL " "
- } else {
- append line SQLITE_APICALL " "
- }
- }
- append line $funcname $rest
- if {$funcname=="sqlite3_sourceid" && !$linemacros} {
- # The sqlite3_sourceid() routine is synthesized at the end of
- # the amalgamation
- puts $out "/* $line */"
- } else {
- puts $out $line
- }
- } else {
- puts $out "SQLITE_PRIVATE $line"
- }
- } elseif {[regexp $varpattern $line all varname]} {
- # Add the SQLITE_PRIVATE before variable declarations or
- # definitions for internal use
- regsub {^SQLITE_API } $line {} line
- if {![regexp {^sqlite3_} $varname]} {
- regsub {^extern } $line {} line
- puts $out "SQLITE_PRIVATE $line"
- } else {
- if {[regexp {const char sqlite3_version\[\];} $line]} {
- set line {const char sqlite3_version[] = SQLITE_VERSION;}
- }
- regsub {^SQLITE_EXTERN } $line {} line
- puts $out "SQLITE_API $line"
- }
- } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
- regsub {^SQLITE_API } $line {} line
- regsub {^SQLITE_EXTERN } $line {} line
- puts $out $line
- } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
- regsub {^SQLITE_API } $line {} line
- puts $out "SQLITE_PRIVATE $line"
- } else {
- puts $out $line
- }
- } else {
- puts $out $line
- }
- }
- close $in
- section_comment "End of $tail"
-}
-
-
-# Process the source files. Process files containing commonly
-# used subroutines first in order to help the compiler find
-# inlining opportunities.
-#
-foreach file {
- ctime.c
- sqliteInt.h
-
- global.c
- status.c
- date.c
- os.c
-
- fault.c
- mem0.c
- mem1.c
- mem2.c
- mem3.c
- mem5.c
- mutex.c
- mutex_noop.c
- mutex_unix.c
- mutex_w32.c
- malloc.c
- printf.c
- treeview.c
- random.c
- threads.c
- utf.c
- util.c
- hash.c
- opcodes.c
-
- os_unix.c
- os_win.c
- memdb.c
-
- bitvec.c
- pcache.c
- pcache1.c
- rowset.c
- pager.c
- wal.c
-
- btmutex.c
- btree.c
- backup.c
-
- vdbemem.c
- vdbeaux.c
- vdbeapi.c
- vdbetrace.c
- vdbe.c
- vdbeblob.c
- vdbesort.c
- memjournal.c
-
- walker.c
- resolve.c
- expr.c
- alter.c
- analyze.c
- attach.c
- auth.c
- build.c
- callback.c
- delete.c
- func.c
- fkey.c
- insert.c
- legacy.c
- loadext.c
- pragma.c
- prepare.c
- select.c
- table.c
- trigger.c
- update.c
- upsert.c
- vacuum.c
- vtab.c
- wherecode.c
- whereexpr.c
- where.c
-
- parse.c
-
- tokenize.c
- complete.c
-
- main.c
- notify.c
-
- fts3.c
- fts3_aux.c
- fts3_expr.c
- fts3_hash.c
- fts3_porter.c
- fts3_tokenizer.c
- fts3_tokenizer1.c
- fts3_tokenize_vtab.c
- fts3_write.c
- fts3_snippet.c
- fts3_unicode.c
- fts3_unicode2.c
-
- rtree.c
- icu.c
- fts3_icu.c
- sqlite3rbu.c
- dbstat.c
- dbpage.c
- sqlite3session.c
- json1.c
- fts5.c
- stmt.c
-} {
- copy_file tsrc/$file
-}
-
-# Synthesize an alternative sqlite3_sourceid() implementation that
-# that tries to detects changes in the amalgamation source text
-# and modify returns a modified source-id if changes are detected.
-#
-# The only detection mechanism we have is the __LINE__ macro. So only
-# edits that changes the number of lines of source code are detected.
-#
-if {!$linemacros} {
- flush $out
- set in2 [open sqlite3.c]
- set cnt 0
- set oldsrcid {}
- while {![eof $in2]} {
- incr cnt
- gets $in2 line
- if {[regexp {^#define SQLITE_SOURCE_ID } $line]} {set oldsrcid $line}
- }
- close $in2
- regsub {[0-9a-flt]{4}"} $oldsrcid {alt2"} oldsrcid
- puts $out \
-"#if __LINE__!=[expr {$cnt+0}]
-#undef SQLITE_SOURCE_ID
-$oldsrcid
-#endif
-/* Return the source-id for this library */
-SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
-}
-puts $out \
-"/************************** End of sqlite3.c ******************************/"
-
-close $out
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3h.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3h.tcl
deleted file mode 100644
index 216bd4e60bf..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3h.tcl
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script constructs the "sqlite3.h" header file from the following
-# sources:
-#
-# 1) The src/sqlite.h.in source file. This is the template for sqlite3.h.
-# 2) The VERSION file containing the current SQLite version number.
-# 3) The manifest file from the fossil SCM. This gives use the date.
-# 4) The manifest.uuid file from the fossil SCM. This gives the SHA1 hash.
-#
-# Run this script by specifying the root directory of the source tree
-# on the command-line.
-#
-# This script performs processing on src/sqlite.h.in. It:
-#
-# 1) Adds SQLITE_EXTERN in front of the declaration of global variables,
-# 2) Adds SQLITE_API in front of the declaration of API functions,
-# 3) Replaces the string --VERS-- with the current library version,
-# formatted as a string (e.g. "3.6.17"), and
-# 4) Replaces the string --VERSION-NUMBER-- with current library version,
-# formatted as an integer (e.g. "3006017").
-# 5) Replaces the string --SOURCE-ID-- with the date and time and sha1
-# hash of the fossil-scm manifest for the source tree.
-# 6) Adds the SQLITE_CALLBACK calling convention macro in front of all
-# callback declarations.
-#
-# This script outputs to stdout.
-#
-# Example usage:
-#
-# tclsh mksqlite3h.tcl ../sqlite >sqlite3.h
-#
-
-
-# Get the source tree root directory from the command-line
-#
-set TOP [lindex $argv 0]
-
-# Enable use of SQLITE_APICALL macros at the right points?
-#
-set useapicall 0
-
-if {[lsearch -regexp [lrange $argv 1 end] {^-+useapicall}] != -1} {
- set useapicall 1
-}
-
-# Get the SQLite version number (ex: 3.6.18) from the $TOP/VERSION file.
-#
-set in [open $TOP/VERSION]
-set zVersion [string trim [read $in]]
-close $in
-set nVersion [eval format "%d%03d%03d" [split $zVersion .]]
-
-# Get the source-id
-#
-set PWD [pwd]
-cd $TOP
-set zSourceId [exec $PWD/mksourceid manifest]
-cd $PWD
-
-# Set up patterns for recognizing API declarations.
-#
-set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+sqlite3_[_a-zA-Z0-9]+(\[|;| =)}
-set declpattern1 {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3_[_a-zA-Z0-9]+)(\(.*)$}
-
-set declpattern2 \
- {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3session_[_a-zA-Z0-9]+)(\(.*)$}
-
-set declpattern3 \
- {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changeset_[_a-zA-Z0-9]+)(\(.*)$}
-
-set declpattern4 \
- {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changegroup_[_a-zA-Z0-9]+)(\(.*)$}
-
-set declpattern5 \
- {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3rebaser_[_a-zA-Z0-9]+)(\(.*)$}
-
-# Force the output to use unix line endings, even on Windows.
-fconfigure stdout -translation lf
-
-set filelist [subst {
- $TOP/src/sqlite.h.in
- $TOP/ext/rtree/sqlite3rtree.h
- $TOP/ext/session/sqlite3session.h
- $TOP/ext/fts5/fts5.h
-}]
-
-# These are the functions that accept a variable number of arguments. They
-# always need to use the "cdecl" calling convention even when another calling
-# convention (e.g. "stcall") is being used for the rest of the library.
-set cdecllist {
- sqlite3_config
- sqlite3_db_config
- sqlite3_log
- sqlite3_mprintf
- sqlite3_snprintf
- sqlite3_test_control
- sqlite3_vtab_config
-}
-
-# Process the source files.
-#
-foreach file $filelist {
- set in [open $file]
- if {![regexp {sqlite\.h\.in} $file]} {
- puts "/******** Begin file [file tail $file] *********/"
- }
- while {![eof $in]} {
-
- set line [gets $in]
-
- # File sqlite3rtree.h contains a line "#include <sqlite3.h>". Omit this
- # line when copying sqlite3rtree.h into sqlite3.h.
- #
- if {[string match {*#include*[<"]sqlite3.h[>"]*} $line]} continue
-
- regsub -- --VERS-- $line $zVersion line
- regsub -- --VERSION-NUMBER-- $line $nVersion line
- regsub -- --SOURCE-ID-- $line "$zSourceId" line
-
- if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} {
- set line "SQLITE_API $line"
- } else {
- if {[regexp $declpattern1 $line all rettype funcname rest] || \
- [regexp $declpattern2 $line all rettype funcname rest] || \
- [regexp $declpattern3 $line all rettype funcname rest] || \
- [regexp $declpattern4 $line all rettype funcname rest] || \
- [regexp $declpattern5 $line all rettype funcname rest]} {
- set line SQLITE_API
- append line " " [string trim $rettype]
- if {[string index $rettype end] ne "*"} {
- append line " "
- }
- if {$useapicall} {
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL " "
- } else {
- append line SQLITE_APICALL " "
- }
- }
- append line $funcname $rest
- }
- }
- if {$useapicall} {
- set line [string map [list (*sqlite3_syscall_ptr) \
- "(SQLITE_SYSAPI *sqlite3_syscall_ptr)"] $line]
- regsub {\(\*} $line {(SQLITE_CALLBACK *} line
- }
- puts $line
- }
- close $in
- if {![regexp {sqlite\.h\.in} $file]} {
- puts "/******** End of [file tail $file] *********/"
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3internalh.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3internalh.tcl
deleted file mode 100644
index 8db593fe756..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mksqlite3internalh.tcl
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/tclsh
-#
-# To build a single huge source file holding all of SQLite (or at
-# least the core components - the test harness, shell, and TCL
-# interface are omitted.) first do
-#
-# make target_source
-#
-# The make target above moves all of the source code files into
-# a subdirectory named "tsrc". (This script expects to find the files
-# there and will not work if they are not found.) There are a few
-# generated C code files that are also added to the tsrc directory.
-# For example, the "parse.c" and "parse.h" files to implement the
-# the parser are derived from "parse.y" using lemon. And the
-# "keywordhash.h" files is generated by a program named "mkkeywordhash".
-#
-# After the "tsrc" directory has been created and populated, run
-# this script:
-#
-# tclsh mksqlite3c.tcl
-#
-# The amalgamated SQLite code will be written into sqlite3.c
-#
-
-# Begin by reading the "sqlite3.h" header file. Count the number of lines
-# in this file and extract the version number. That information will be
-# needed in order to generate the header of the amalgamation.
-#
-set in [open tsrc/sqlite3.h]
-set cnt 0
-set VERSION ?????
-while {![eof $in]} {
- set line [gets $in]
- if {$line=="" && [eof $in]} break
- incr cnt
- regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
-}
-close $in
-
-# Open the output file and write a header comment at the beginning
-# of the file.
-#
-set out [open sqlite3internal.h w]
-set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
-puts $out [subst \
-{/******************************************************************************
-** This file is an amalgamation of many private header files from SQLite
-** version $VERSION.
-*/}]
-
-# These are the header files used by SQLite. The first time any of these
-# files are seen in a #include statement in the C code, include the complete
-# text of the file in-line. The file only needs to be included once.
-#
-foreach hdr {
- btree.h
- btreeInt.h
- hash.h
- hwtime.h
- keywordhash.h
- msvc.h
- opcodes.h
- os_common.h
- os_setup.h
- os_win.h
- os.h
- pager.h
- parse.h
- sqlite3ext.h
- sqlite3.h
- sqliteInt.h
- sqliteLimit.h
- vdbe.h
- vdbeInt.h
-} {
- set available_hdr($hdr) 1
-}
-
-# 78 stars used for comment formatting.
-set s78 \
-{*****************************************************************************}
-
-# Insert a comment into the code
-#
-proc section_comment {text} {
- global out s78
- set n [string length $text]
- set nstar [expr {60 - $n}]
- set stars [string range $s78 0 $nstar]
- puts $out "/************** $text $stars/"
-}
-
-# Read the source file named $filename and write it into the
-# sqlite3.c output file. If any #include statements are seen,
-# process them approprately.
-#
-proc copy_file {filename} {
- global seen_hdr available_hdr out
- set tail [file tail $filename]
- section_comment "Begin file $tail"
- set in [open $filename r]
- while {![eof $in]} {
- set line [gets $in]
- if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
- if {[info exists available_hdr($hdr)]} {
- if {$available_hdr($hdr)} {
- section_comment "Include $hdr in the middle of $tail"
- copy_file tsrc/$hdr
- section_comment "Continuing where we left off in $tail"
- }
- } elseif {![info exists seen_hdr($hdr)]} {
- set seen_hdr($hdr) 1
- puts $out $line
- }
- } elseif {[regexp {^#ifdef __cplusplus} $line]} {
- puts $out "#if 0"
- } elseif {[regexp {^#line} $line]} {
- # Skip #line directives.
- } else {
- puts $out $line
- }
- }
- close $in
- section_comment "End of $tail"
-}
-
-
-# Process the source files. Process files containing commonly
-# used subroutines first in order to help the compiler find
-# inlining opportunities.
-#
-foreach file {
- sqliteInt.h
- sqlite3.h
- btree.h
- hash.h
- os.h
- pager.h
- parse.h
- sqlite3ext.h
- vdbe.h
-} {
- if {$available_hdr($file)} {
- copy_file tsrc/$file
- }
-}
-
-close $out
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkvsix.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkvsix.tcl
deleted file mode 100644
index c874d538fbe..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/mkvsix.tcl
+++ /dev/null
@@ -1,840 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script is used to generate a VSIX (Visual Studio Extension) file for
-# SQLite usable by Visual Studio.
-#
-# PREREQUISITES
-#
-# 1. Tcl 8.4 and later are supported, earlier versions have not been tested.
-#
-# 2. The "sqlite3.h" file is assumed to exist in the parent directory of the
-# directory containing this script. The [optional] second command line
-# argument to this script may be used to specify an alternate location.
-# This script also assumes that the "sqlite3.h" file corresponds with the
-# version of the binaries to be packaged. This assumption is not verified
-# by this script.
-#
-# 3. The temporary directory specified in the TEMP or TMP environment variables
-# must refer to an existing directory writable by the current user.
-#
-# 4. The "zip" and "unzip" command line tools must be located either in a
-# directory contained in the PATH environment variable or specified as the
-# exact file names to execute in the "ZipTool" and "UnZipTool" environment
-# variables, respectively.
-#
-# 5. The template VSIX file (which is basically a zip file) must be located in
-# a "win" directory inside the directory containing this script. It should
-# not contain any executable binaries. It should only contain dynamic
-# textual content files to be processed using [subst] and/or static content
-# files to be copied verbatim.
-#
-# 6. The executable and other compiled binary files to be packaged into the
-# final VSIX file (e.g. DLLs, LIBs, and PDBs) must be located in a single
-# directory tree. The top-level directory of the tree must be specified as
-# the first command line argument to this script. The second level
-# sub-directory names must match those of the build configuration (e.g.
-# "Debug" or "Retail"). The third level sub-directory names must match
-# those of the platform (e.g. "x86", "x64", and "ARM"). For example, the
-# binary files to be packaged would need to be organized as follows when
-# packaging the "Debug" and "Retail" build configurations for the "x86" and
-# "x64" platforms (in this example, "C:\temp" is the top-level directory as
-# specified in the first command line argument):
-#
-# C:\Temp\Debug\x86\sqlite3.lib
-# C:\Temp\Debug\x86\sqlite3.dll
-# C:\Temp\Debug\x86\sqlite3.pdb
-# C:\Temp\Debug\x64\sqlite3.lib
-# C:\Temp\Debug\x64\sqlite3.dll
-# C:\Temp\Debug\x64\sqlite3.pdb
-# C:\Temp\Retail\x86\sqlite3.lib
-# C:\Temp\Retail\x86\sqlite3.dll
-# C:\Temp\Retail\x86\sqlite3.pdb
-# C:\Temp\Retail\x64\sqlite3.lib
-# C:\Temp\Retail\x64\sqlite3.dll
-# C:\Temp\Retail\x64\sqlite3.pdb
-#
-# The above directory tree organization is performed automatically if the
-# "tool\build-all-msvc.bat" batch script is used to build the binary files
-# to be packaged.
-#
-# USAGE
-#
-# The first argument to this script is required and must be the name of the
-# top-level directory containing the directories and files organized into a
-# tree as described in item 6 of the PREREQUISITES section, above. The second
-# argument is optional and if present must contain the name of the directory
-# containing the root of the source tree for SQLite. The third argument is
-# optional and if present must contain the flavor the VSIX package to build.
-# Currently, the only supported package flavors are "WinRT", "WinRT81", "WP80",
-# "WP81", and "Win32". The fourth argument is optional and if present must be
-# a string containing a list of platforms to include in the VSIX package. The
-# platform list is "platform1,platform2,platform3". The fifth argument is
-# optional and if present must contain the version of Visual Studio required by
-# the package. Currently, the only supported versions are "2012" and "2013".
-# The package flavors "WinRT81" and "WP81" are only supported when the Visual
-# Studio version is "2013". Typically, when on Windows, this script is
-# executed using commands similar to the following from a normal Windows
-# command prompt:
-#
-# CD /D C:\dev\sqlite\core
-# tclsh tool\mkvsix.tcl C:\Temp
-#
-# In the example above, "C:\dev\sqlite\core" represents the root of the source
-# tree for SQLite and "C:\Temp" represents the top-level directory containing
-# the executable and other compiled binary files, organized into a directory
-# tree as described in item 6 of the PREREQUISITES section, above.
-#
-# This script should work on non-Windows platforms as well, provided that all
-# the requirements listed in the PREREQUISITES section are met.
-#
-# NOTES
-#
-# The temporary directory is used as a staging area for the final VSIX file.
-# The template VSIX file is extracted, its contents processed, and then the
-# resulting files are packaged into the final VSIX file.
-#
-package require Tcl 8.4
-
-proc fail { {error ""} {usage false} } {
- if {[string length $error] > 0} then {
- puts stdout $error
- if {!$usage} then {exit 1}
- }
-
- puts stdout "usage:\
-[file tail [info nameofexecutable]]\
-[file tail [info script]] <binaryDirectory> \[sourceDirectory\]\
-\[packageFlavor\] \[platformNames\] \[vsVersion\]"
-
- exit 1
-}
-
-proc getEnvironmentVariable { name } {
- #
- # NOTE: Returns the value of the specified environment variable or an empty
- # string for environment variables that do not exist in the current
- # process environment.
- #
- return [expr {[info exists ::env($name)] ? $::env($name) : ""}]
-}
-
-proc getTemporaryPath {} {
- #
- # NOTE: Returns the normalized path to the first temporary directory found
- # in the typical set of environment variables used for that purpose
- # or an empty string to signal a failure to locate such a directory.
- #
- set names [list]
-
- foreach name [list TEMP TMP] {
- lappend names [string toupper $name] [string tolower $name] \
- [string totitle $name]
- }
-
- foreach name $names {
- set value [getEnvironmentVariable $name]
-
- if {[string length $value] > 0} then {
- return [file normalize $value]
- }
- }
-
- return ""
-}
-
-proc appendArgs { args } {
- #
- # NOTE: Returns all passed arguments joined together as a single string with
- # no intervening spaces between arguments.
- #
- eval append result $args
-}
-
-proc readFile { fileName } {
- #
- # NOTE: Reads and returns the entire contents of the specified file, which
- # may contain binary data.
- #
- set file_id [open $fileName RDONLY]
- fconfigure $file_id -encoding binary -translation binary
- set result [read $file_id]
- close $file_id
- return $result
-}
-
-proc writeFile { fileName data } {
- #
- # NOTE: Writes the entire contents of the specified file, which may contain
- # binary data.
- #
- set file_id [open $fileName {WRONLY CREAT TRUNC}]
- fconfigure $file_id -encoding binary -translation binary
- puts -nonewline $file_id $data
- close $file_id
- return ""
-}
-
-#
-# TODO: Modify this procedure when a new version of Visual Studio is released.
-#
-proc getMinVsVersionXmlChunk { vsVersion } {
- switch -exact $vsVersion {
- 2012 {
- return [appendArgs \
- "\r\n " {MinVSVersion="11.0"}]
- }
- 2013 {
- return [appendArgs \
- "\r\n " {MinVSVersion="12.0"}]
- }
- 2015 {
- return [appendArgs \
- "\r\n " {MinVSVersion="14.0"}]
- }
- default {
- return ""
- }
- }
-}
-
-#
-# TODO: Modify this procedure when a new version of Visual Studio is released.
-#
-proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } {
- #
- # NOTE: Only Visual Studio 2013 and later support this attribute within the
- # SDK manifest.
- #
- if {![string equal $vsVersion 2013] && \
- ![string equal $vsVersion 2015]} then {
- return ""
- }
-
- switch -exact $packageFlavor {
- WinRT {
- return [appendArgs \
- "\r\n " {MaxPlatformVersion="8.0"}]
- }
- WinRT81 {
- return [appendArgs \
- "\r\n " {MaxPlatformVersion="8.1"}]
- }
- WP80 {
- return [appendArgs \
- "\r\n " {MaxPlatformVersion="8.0"}]
- }
- WP81 {
- return [appendArgs \
- "\r\n " {MaxPlatformVersion="8.1"}]
- }
- default {
- return ""
- }
- }
-}
-
-#
-# TODO: Modify this procedure when a new version of Visual Studio is released.
-#
-proc getExtraFileListXmlChunk { packageFlavor vsVersion } {
- #
- # NOTE: Windows Phone 8.0 does not require any extra attributes in its VSIX
- # package SDK manifests; however, it appears that Windows Phone 8.1
- # does.
- #
- if {[string equal $packageFlavor WP80]} then {
- return ""
- }
-
- set appliesTo [expr {[string equal $packageFlavor Win32] ? \
- "VisualC" : "WindowsAppContainer"}]
-
- switch -exact $vsVersion {
- 2012 {
- return [appendArgs \
- "\r\n " AppliesTo=\" $appliesTo \" \
- "\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
- }
- 2013 {
- return [appendArgs \
- "\r\n " AppliesTo=\" $appliesTo \" \
- "\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
- }
- 2015 {
- return [appendArgs \
- "\r\n " AppliesTo=\" $appliesTo \" \
- "\r\n " {DependsOn="Microsoft.VCLibs, version=14.0"}]
- }
- default {
- return ""
- }
- }
-}
-
-proc replaceFileNameTokens { fileName name buildName platformName } {
- #
- # NOTE: Returns the specified file name containing the platform name instead
- # of platform placeholder tokens.
- #
- return [string map [list <build> $buildName <platform> $platformName \
- <name> $name] $fileName]
-}
-
-proc substFile { fileName } {
- #
- # NOTE: Performs all Tcl command, variable, and backslash substitutions in
- # the specified file and then rewrites the contents of that same file
- # with the substituted data.
- #
- return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
-}
-
-#
-# NOTE: This is the entry point for this script.
-#
-set script [file normalize [info script]]
-
-if {[string length $script] == 0} then {
- fail "script file currently being evaluated is unknown" true
-}
-
-set path [file dirname $script]
-set rootName [file rootname [file tail $script]]
-
-###############################################################################
-
-#
-# NOTE: Process and verify all the command line arguments.
-#
-set argc [llength $argv]
-if {$argc < 1 || $argc > 5} then {fail}
-
-set binaryDirectory [lindex $argv 0]
-
-if {[string length $binaryDirectory] == 0} then {
- fail "invalid binary directory"
-}
-
-if {![file exists $binaryDirectory] || \
- ![file isdirectory $binaryDirectory]} then {
- fail "binary directory does not exist"
-}
-
-if {$argc >= 2} then {
- set sourceDirectory [lindex $argv 1]
-} else {
- #
- # NOTE: Assume that the source directory is the parent directory of the one
- # that contains this script file.
- #
- set sourceDirectory [file dirname $path]
-}
-
-if {[string length $sourceDirectory] == 0} then {
- fail "invalid source directory"
-}
-
-if {![file exists $sourceDirectory] || \
- ![file isdirectory $sourceDirectory]} then {
- fail "source directory does not exist"
-}
-
-if {$argc >= 3} then {
- set packageFlavor [lindex $argv 2]
-} else {
- #
- # NOTE: Assume the package flavor is WinRT.
- #
- set packageFlavor WinRT
-}
-
-if {[string length $packageFlavor] == 0} then {
- fail "invalid package flavor"
-}
-
-if {$argc >= 4} then {
- set platformNames [list]
-
- foreach platformName [split [lindex $argv 3] ", "] {
- set platformName [string trim $platformName]
-
- if {[string length $platformName] > 0} then {
- lappend platformNames $platformName
- }
- }
-}
-
-if {$argc >= 5} then {
- set vsVersion [lindex $argv 4]
-} else {
- set vsVersion 2012
-}
-
-if {[string length $vsVersion] == 0} then {
- fail "invalid Visual Studio version"
-}
-
-if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013] && \
- ![string equal $vsVersion 2015]} then {
- fail [appendArgs \
- "unsupported Visual Studio version, must be one of: " \
- [list 2012 2013 2015]]
-}
-
-set shortNames(WinRT,2012) SQLite.WinRT
-set shortNames(WinRT,2013) SQLite.WinRT.2013
-set shortNames(WinRT81,2013) SQLite.WinRT81
-set shortNames(WP80,2012) SQLite.WP80
-set shortNames(WP80,2013) SQLite.WP80.2013
-set shortNames(WP81,2013) SQLite.WP81
-set shortNames(Win32,2012) SQLite.Win32
-set shortNames(Win32,2013) SQLite.Win32.2013
-set shortNames(UWP,2015) SQLite.UWP.2015
-
-set displayNames(WinRT,2012) "SQLite for Windows Runtime"
-set displayNames(WinRT,2013) "SQLite for Windows Runtime"
-set displayNames(WinRT81,2013) "SQLite for Windows Runtime (Windows 8.1)"
-set displayNames(WP80,2012) "SQLite for Windows Phone"
-set displayNames(WP80,2013) "SQLite for Windows Phone"
-set displayNames(WP81,2013) "SQLite for Windows Phone 8.1"
-set displayNames(Win32,2012) "SQLite for Windows"
-set displayNames(Win32,2013) "SQLite for Windows"
-set displayNames(UWP,2015) "SQLite for Universal Windows Platform"
-
-if {[string equal $packageFlavor WinRT]} then {
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier Windows
- set targetPlatformVersion v8.0
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath ""
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor WinRT81]} then {
- if {$vsVersion ne "2013"} then {
- fail [appendArgs \
- "unsupported combination, package flavor " $packageFlavor \
- " is only supported with Visual Studio 2013"]
- }
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier Windows
- set targetPlatformVersion v8.1
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath ""
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor WP80]} then {
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier "Windows Phone"
- set targetPlatformVersion v8.0
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath "\\..\\$targetPlatformIdentifier"
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor WP81]} then {
- if {$vsVersion ne "2013"} then {
- fail [appendArgs \
- "unsupported combination, package flavor " $packageFlavor \
- " is only supported with Visual Studio 2013"]
- }
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier WindowsPhoneApp
- set targetPlatformVersion v8.1
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath "\\..\\$targetPlatformIdentifier"
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor UWP]} then {
- if {$vsVersion ne "2015"} then {
- fail [appendArgs \
- "unsupported combination, package flavor " $packageFlavor \
- " is only supported with Visual Studio 2015"]
- }
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier UAP; # NOTE: Not "UWP".
- set targetPlatformVersion v0.8.0.0
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath "\\..\\$targetPlatformIdentifier"
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor Win32]} then {
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier Windows
- set targetPlatformVersion v8.0
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath ""
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} else {
- fail [appendArgs \
- "unsupported package flavor, must be one of: " \
- [list WinRT WinRT81 WP80 WP81 UWP Win32]]
-}
-
-###############################################################################
-
-#
-# NOTE: Evaluate the user-specific customizations file, if it exists.
-#
-set userFile [file join $path [appendArgs \
- $rootName . $tcl_platform(user) .tcl]]
-
-if {[file exists $userFile] && \
- [file isfile $userFile]} then {
- source $userFile
-}
-
-###############################################################################
-
-set templateFile [file join $path win sqlite.vsix]
-
-if {![file exists $templateFile] || \
- ![file isfile $templateFile]} then {
- fail [appendArgs "template file \"" $templateFile "\" does not exist"]
-}
-
-set currentDirectory [pwd]
-set outputFile [file join $currentDirectory [appendArgs sqlite- \
- $packageFlavor -output.vsix]]
-
-if {[file exists $outputFile]} then {
- fail [appendArgs "output file \"" $outputFile "\" already exists"]
-}
-
-###############################################################################
-
-#
-# NOTE: Make sure that a valid temporary directory exists.
-#
-set temporaryDirectory [getTemporaryPath]
-
-if {[string length $temporaryDirectory] == 0 || \
- ![file exists $temporaryDirectory] || \
- ![file isdirectory $temporaryDirectory]} then {
- fail "cannot locate a usable temporary directory"
-}
-
-#
-# NOTE: Setup the staging directory to have a unique name inside of the
-# configured temporary directory.
-#
-set stagingDirectory [file normalize [file join $temporaryDirectory \
- [appendArgs $rootName . [pid]]]]
-
-###############################################################################
-
-#
-# NOTE: Configure the external zipping tool. First, see if it has already
-# been pre-configured. If not, try to query it from the environment.
-# Finally, fallback on the default of simply "zip", which will then
-# be assumed to exist somewhere along the PATH.
-#
-if {![info exists zip]} then {
- if {[info exists env(ZipTool)]} then {
- set zip $env(ZipTool)
- }
- if {![info exists zip] || ![file exists $zip]} then {
- set zip zip
- }
-}
-
-#
-# NOTE: Configure the external unzipping tool. First, see if it has already
-# been pre-configured. If not, try to query it from the environment.
-# Finally, fallback on the default of simply "unzip", which will then
-# be assumed to exist somewhere along the PATH.
-#
-if {![info exists unzip]} then {
- if {[info exists env(UnZipTool)]} then {
- set unzip $env(UnZipTool)
- }
- if {![info exists unzip] || ![file exists $unzip]} then {
- set unzip unzip
- }
-}
-
-###############################################################################
-
-#
-# NOTE: Attempt to extract the SQLite version from the "sqlite3.h" header file
-# in the source directory. This script assumes that the header file has
-# already been generated by the build process.
-#
-set pattern {^#define\s+SQLITE_VERSION\s+"(.*)"$}
-set data [readFile [file join $sourceDirectory sqlite3.h]]
-
-if {![regexp -line -- $pattern $data dummy version]} then {
- fail [appendArgs "cannot locate SQLITE_VERSION value in \"" \
- [file join $sourceDirectory sqlite3.h] \"]
-}
-
-###############################################################################
-
-#
-# NOTE: Setup all the master file list data. This includes the source file
-# names, the destination file names, and the file processing flags. The
-# possible file processing flags are:
-#
-# "buildNeutral" -- This flag indicates the file location and content do
-# not depend on the build configuration.
-#
-# "platformNeutral" -- This flag indicates the file location and content
-# do not depend on the build platform.
-#
-# "subst" -- This flag indicates that the file contains dynamic textual
-# content that needs to be processed using [subst] prior to
-# packaging the file into the final VSIX package. The primary
-# use of this flag is to insert the name of the VSIX package,
-# some package flavor-specific value, or the SQLite version
-# into a file.
-#
-# "noDebug" -- This flag indicates that the file should be skipped when
-# processing the debug build.
-#
-# "noRetail" -- This flag indicates that the file should be skipped when
-# processing the retail build.
-#
-# "move" -- This flag indicates that the file should be moved from the
-# source to the destination instead of being copied.
-#
-# This file metadata may be overridden, either in whole or in part, via
-# the user-specific customizations file.
-#
-if {![info exists fileNames(source)]} then {
- set fileNames(source) [list "" "" \
- [file join $stagingDirectory DesignTime <build> <platform> sqlite3.props] \
- [file join $sourceDirectory sqlite3.h] \
- [file join $binaryDirectory <build> <platform> sqlite3.lib] \
- [file join $binaryDirectory <build> <platform> sqlite3.dll]]
-
- if {![info exists no(symbols)]} then {
- lappend fileNames(source) \
- [file join $binaryDirectory <build> <platform> sqlite3.pdb]
- }
-}
-
-if {![info exists fileNames(destination)]} then {
- set fileNames(destination) [list \
- [file join $stagingDirectory extension.vsixmanifest] \
- [file join $stagingDirectory SDKManifest.xml] \
- [file join $stagingDirectory DesignTime <build> <platform> <name>.props] \
- [file join $stagingDirectory DesignTime <build> <platform> sqlite3.h] \
- [file join $stagingDirectory DesignTime <build> <platform> sqlite3.lib] \
- [file join $stagingDirectory Redist <build> <platform> sqlite3.dll]]
-
- if {![info exists no(symbols)]} then {
- lappend fileNames(destination) \
- [file join $stagingDirectory Redist <build> <platform> sqlite3.pdb]
- }
-}
-
-if {![info exists fileNames(flags)]} then {
- set fileNames(flags) [list \
- [list buildNeutral platformNeutral subst] \
- [list buildNeutral platformNeutral subst] \
- [list buildNeutral platformNeutral subst move] \
- [list buildNeutral platformNeutral] \
- [list] [list] [list noRetail]]
-
- if {![info exists no(symbols)]} then {
- lappend fileNames(flags) [list noRetail]
- }
-}
-
-###############################################################################
-
-#
-# NOTE: Setup the list of builds supported by this script. These may be
-# overridden via the user-specific customizations file.
-#
-if {![info exists buildNames]} then {
- set buildNames [list Debug Retail]
-}
-
-###############################################################################
-
-#
-# NOTE: Setup the list of platforms supported by this script. These may be
-# overridden via the command line or the user-specific customizations
-# file.
-#
-if {![info exists platformNames] || [llength $platformNames] == 0} then {
- set platformNames [list x86 x64 ARM]
-}
-
-###############################################################################
-
-#
-# NOTE: Make sure the staging directory exists, creating it if necessary.
-#
-file mkdir $stagingDirectory
-
-#
-# NOTE: Build the Tcl command used to extract the template VSIX package to
-# the staging directory.
-#
-set extractCommand [list exec -- $unzip $templateFile -d $stagingDirectory]
-
-#
-# NOTE: Extract the template VSIX package to the staging directory.
-#
-eval $extractCommand
-
-###############################################################################
-
-#
-# NOTE: Process each file in the master file list. There are actually three
-# parallel lists that contain the source file names, the destination file
-# names, and the file processing flags. If the "buildNeutral" flag is
-# present, the file location and content do not depend on the build
-# configuration and "CommonConfiguration" will be used in place of the
-# build configuration name. If the "platformNeutral" flag is present,
-# the file location and content do not depend on the build platform and
-# "neutral" will be used in place of the build platform name. If the
-# "subst" flag is present, the file is assumed to be a text file that may
-# contain Tcl variable, command, and backslash replacements, to be
-# dynamically replaced during processing using the Tcl [subst] command.
-# If the "noDebug" flag is present, the file will be skipped when
-# processing for the debug build. If the "noRetail" flag is present, the
-# file will be skipped when processing for the retail build. If the
-# "move" flag is present, the source file will be deleted after it is
-# copied to the destination file. If the source file name is an empty
-# string, the destination file name will be assumed to already exist in
-# the staging directory and will not be copied; however, Tcl variable,
-# command, and backslash replacements may still be performed on the
-# destination file prior to the final VSIX package being built if the
-# "subst" flag is present.
-#
-foreach sourceFileName $fileNames(source) \
- destinationFileName $fileNames(destination) \
- fileFlags $fileNames(flags) {
- #
- # NOTE: Process the file flags into separate boolean variables that may be
- # used within the loop.
- #
- set isBuildNeutral [expr {[lsearch $fileFlags buildNeutral] != -1}]
- set isPlatformNeutral [expr {[lsearch $fileFlags platformNeutral] != -1}]
- set isMove [expr {[lsearch $fileFlags move] != -1}]
- set useSubst [expr {[lsearch $fileFlags subst] != -1}]
-
- #
- # NOTE: If the current file is build-neutral, then only one build will
- # be processed for it, namely "CommonConfiguration"; otherwise, each
- # supported build will be processed for it individually.
- #
- foreach buildName \
- [expr {$isBuildNeutral ? [list CommonConfiguration] : $buildNames}] {
- #
- # NOTE: Should the current file be skipped for this build?
- #
- if {[lsearch $fileFlags no${buildName}] != -1} then {
- continue
- }
-
- #
- # NOTE: If the current file is platform-neutral, then only one platform
- # will be processed for it, namely "neutral"; otherwise, each
- # supported platform will be processed for it individually.
- #
- foreach platformName \
- [expr {$isPlatformNeutral ? [list neutral] : $platformNames}] {
- #
- # NOTE: Use the actual platform name in the destination file name.
- #
- set newDestinationFileName [replaceFileNameTokens $destinationFileName \
- $shortName $buildName $platformName]
-
- #
- # NOTE: Does the source file need to be copied to the destination file?
- #
- if {[string length $sourceFileName] > 0} then {
- #
- # NOTE: First, make sure the destination directory exists.
- #
- file mkdir [file dirname $newDestinationFileName]
-
- #
- # NOTE: Then, copy the source file to the destination file verbatim.
- #
- set newSourceFileName [replaceFileNameTokens $sourceFileName \
- $shortName $buildName $platformName]
-
- file copy $newSourceFileName $newDestinationFileName
-
- #
- # NOTE: If this is a move instead of a copy, delete the source file
- # now.
- #
- if {$isMove} then {
- file delete $newSourceFileName
- }
- }
-
- #
- # NOTE: Does the destination file contain dynamic replacements that must
- # be processed now?
- #
- if {$useSubst} then {
- #
- # NOTE: Perform any dynamic replacements contained in the destination
- # file and then re-write it in-place.
- #
- substFile $newDestinationFileName
- }
- }
- }
-}
-
-###############################################################################
-
-#
-# NOTE: Change the current directory to the staging directory so that the
-# external archive building tool can pickup the necessary files using
-# relative paths.
-#
-cd $stagingDirectory
-
-#
-# NOTE: Build the Tcl command used to archive the final VSIX package in the
-# output directory.
-#
-set archiveCommand [list exec -- $zip -r $outputFile *]
-
-#
-# NOTE: Build the final VSIX package archive in the output directory.
-#
-eval $archiveCommand
-
-#
-# NOTE: Change back to the previously saved current directory.
-#
-cd $currentDirectory
-
-#
-# NOTE: Cleanup the temporary staging directory.
-#
-file delete -force $stagingDirectory
-
-###############################################################################
-
-#
-# NOTE: Success, emit the fully qualified path of the generated VSIX file.
-#
-puts stdout $outputFile
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/offsets.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/offsets.c
deleted file mode 100644
index 8e098e71cb9..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/offsets.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
-** This program searches an SQLite database file for the lengths and
-** offsets for all TEXT or BLOB entries for a particular column of a
-** particular table. The rowid, size and offset for the column are
-** written to standard output. There are three arguments, which are the
-** name of the database file, the table, and the column.
-*/
-#include "sqlite3.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-typedef unsigned char u8;
-typedef struct GState GState;
-
-#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
-
-/*
-** Global state information for this program.
-*/
-struct GState {
- char *zErr; /* Error message text */
- FILE *f; /* Open database file */
- int szPg; /* Page size for the database file */
- int iRoot; /* Root page of the table */
- int iCol; /* Column number for the column */
- int pgno; /* Current page number */
- u8 *aPage; /* Current page content */
- u8 *aStack[20]; /* Page stack */
- int aPgno[20]; /* Page number stack */
- int nStack; /* Depth of stack */
- int bTrace; /* True for tracing output */
-};
-
-/*
-** Write an error.
-*/
-static void ofstError(GState *p, const char *zFormat, ...){
- va_list ap;
- sqlite3_free(p->zErr);
- va_start(ap, zFormat);
- p->zErr = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
-}
-
-/*
-** Write a trace message
-*/
-static void ofstTrace(GState *p, const char *zFormat, ...){
- va_list ap;
- if( p->bTrace ){
- va_start(ap, zFormat);
- vprintf(zFormat, ap);
- va_end(ap);
- }
-}
-
-/*
-** Find the root page of the table and the column number of the column.
-*/
-static void ofstRootAndColumn(
- GState *p, /* Global state */
- const char *zFile, /* Name of the database file */
- const char *zTable, /* Name of the table */
- const char *zColumn /* Name of the column */
-){
- sqlite3 *db = 0;
- sqlite3_stmt *pStmt = 0;
- char *zSql = 0;
- int rc;
- if( p->zErr ) return;
- rc = sqlite3_open(zFile, &db);
- if( rc ){
- ofstError(p, "cannot open database file \"%s\"", zFile);
- goto rootAndColumn_exit;
- }
- zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master WHERE name=%Q",
- zTable);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql);
- sqlite3_free(zSql);
- if( p->zErr ) goto rootAndColumn_exit;
- if( sqlite3_step(pStmt)!=SQLITE_ROW ){
- ofstError(p, "cannot find table [%s]\n", zTable);
- sqlite3_finalize(pStmt);
- goto rootAndColumn_exit;
- }
- p->iRoot = sqlite3_column_int(pStmt , 0);
- sqlite3_finalize(pStmt);
-
- p->iCol = -1;
- zSql = sqlite3_mprintf("PRAGMA table_info(%Q)", zTable);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc ) ofstError(p, "%s: [%s}", sqlite3_errmsg(db), zSql);
- sqlite3_free(zSql);
- if( p->zErr ) goto rootAndColumn_exit;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zCol = sqlite3_column_text(pStmt, 1);
- if( strlen(zCol)==strlen(zColumn)
- && sqlite3_strnicmp(zCol, zColumn, strlen(zCol))==0
- ){
- p->iCol = sqlite3_column_int(pStmt, 0);
- break;
- }
- }
- sqlite3_finalize(pStmt);
- if( p->iCol<0 ){
- ofstError(p, "no such column: %s.%s", zTable, zColumn);
- goto rootAndColumn_exit;
- }
-
- zSql = sqlite3_mprintf("PRAGMA page_size");
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql);
- sqlite3_free(zSql);
- if( p->zErr ) goto rootAndColumn_exit;
- if( sqlite3_step(pStmt)!=SQLITE_ROW ){
- ofstError(p, "cannot find page size");
- }else{
- p->szPg = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
-
-rootAndColumn_exit:
- sqlite3_close(db);
- return;
-}
-
-/*
-** Pop a page from the stack
-*/
-static void ofstPopPage(GState *p){
- if( p->nStack<=0 ) return;
- p->nStack--;
- sqlite3_free(p->aStack[p->nStack]);
- p->pgno = p->aPgno[p->nStack-1];
- p->aPage = p->aStack[p->nStack-1];
-}
-
-
-/*
-** Push a new page onto the stack.
-*/
-static void ofstPushPage(GState *p, int pgno){
- u8 *pPage;
- size_t got;
- if( p->zErr ) return;
- if( p->nStack >= ArraySize(p->aStack) ){
- ofstError(p, "page stack overflow");
- return;
- }
- p->aPgno[p->nStack] = pgno;
- p->aStack[p->nStack] = pPage = sqlite3_malloc( p->szPg );
- if( pPage==0 ){
- fprintf(stderr, "out of memory\n");
- exit(1);
- }
- p->nStack++;
- p->aPage = pPage;
- p->pgno = pgno;
- fseek(p->f, (pgno-1)*p->szPg, SEEK_SET);
- got = fread(pPage, 1, p->szPg, p->f);
- if( got!=p->szPg ){
- ofstError(p, "unable to read page %d", pgno);
- ofstPopPage(p);
- }
-}
-
-/* Read a two-byte integer at the given offset into the current page */
-static int ofst2byte(GState *p, int ofst){
- int x = p->aPage[ofst];
- return (x<<8) + p->aPage[ofst+1];
-}
-
-/* Read a four-byte integer at the given offset into the current page */
-static int ofst4byte(GState *p, int ofst){
- int x = p->aPage[ofst];
- x = (x<<8) + p->aPage[ofst+1];
- x = (x<<8) + p->aPage[ofst+2];
- x = (x<<8) + p->aPage[ofst+3];
- return x;
-}
-
-/* Read a variable-length integer. Update the offset */
-static sqlite3_int64 ofstVarint(GState *p, int *pOfst){
- sqlite3_int64 x = 0;
- u8 *a = &p->aPage[*pOfst];
- int n = 0;
- while( n<8 && (a[0] & 0x80)!=0 ){
- x = (x<<7) + (a[0] & 0x7f);
- n++;
- a++;
- }
- if( n==8 ){
- x = (x<<8) + a[0];
- }else{
- x = (x<<7) + a[0];
- }
- *pOfst += (n+1);
- return x;
-}
-
-/* Return the absolute offset into a file for the given offset
-** into the current page */
-static int ofstInFile(GState *p, int ofst){
- return p->szPg*(p->pgno-1) + ofst;
-}
-
-/* Return the size (in bytes) of the data corresponding to the
-** given serial code */
-static int ofstSerialSize(int scode){
- if( scode<5 ) return scode;
- if( scode==5 ) return 6;
- if( scode<8 ) return 8;
- if( scode<12 ) return 0;
- return (scode-12)/2;
-}
-
-/* Forward reference */
-static void ofstWalkPage(GState*, int);
-
-/* Walk an interior btree page */
-static void ofstWalkInteriorPage(GState *p){
- int nCell;
- int i;
- int ofst;
- int iChild;
-
- nCell = ofst2byte(p, 3);
- for(i=0; i<nCell; i++){
- ofst = ofst2byte(p, 12+i*2);
- iChild = ofst4byte(p, ofst);
- ofstWalkPage(p, iChild);
- if( p->zErr ) return;
- }
- ofstWalkPage(p, ofst4byte(p, 8));
-}
-
-/* Walk a leaf btree page */
-static void ofstWalkLeafPage(GState *p){
- int nCell;
- int i;
- int ofst;
- int nPayload;
- sqlite3_int64 rowid;
- int nHdr;
- int j;
- int scode;
- int sz;
- int dataOfst;
- char zMsg[200];
-
- nCell = ofst2byte(p, 3);
- for(i=0; i<nCell; i++){
- ofst = ofst2byte(p, 8+i*2);
- nPayload = ofstVarint(p, &ofst);
- rowid = ofstVarint(p, &ofst);
- if( nPayload > p->szPg-35 ){
- sqlite3_snprintf(sizeof(zMsg), zMsg,
- "# overflow rowid %lld", rowid);
- printf("%s\n", zMsg);
- continue;
- }
- dataOfst = ofst;
- nHdr = ofstVarint(p, &ofst);
- dataOfst += nHdr;
- for(j=0; j<p->iCol; j++){
- scode = ofstVarint(p, &ofst);
- dataOfst += ofstSerialSize(scode);
- }
- scode = ofstVarint(p, &ofst);
- sz = ofstSerialSize(scode);
- sqlite3_snprintf(sizeof(zMsg), zMsg,
- "rowid %12lld size %5d offset %8d",
- rowid, sz, ofstInFile(p, dataOfst));
- printf("%s\n", zMsg);
- }
-}
-
-/*
-** Output results from a single page.
-*/
-static void ofstWalkPage(GState *p, int pgno){
- if( p->zErr ) return;
- ofstPushPage(p, pgno);
- if( p->zErr ) return;
- if( p->aPage[0]==5 ){
- ofstWalkInteriorPage(p);
- }else if( p->aPage[0]==13 ){
- ofstWalkLeafPage(p);
- }else{
- ofstError(p, "page %d has a faulty type byte: %d", pgno, p->aPage[0]);
- }
- ofstPopPage(p);
-}
-
-int main(int argc, char **argv){
- GState g;
- memset(&g, 0, sizeof(g));
- if( argc>2 && strcmp(argv[1],"--trace")==0 ){
- g.bTrace = 1;
- argc--;
- argv++;
- }
- if( argc!=4 ){
- fprintf(stderr, "Usage: %s DATABASE TABLE COLUMN\n", *argv);
- exit(1);
- }
- ofstRootAndColumn(&g, argv[1], argv[2], argv[3]);
- if( g.zErr ){
- fprintf(stderr, "%s\n", g.zErr);
- exit(1);
- }
- ofstTrace(&g, "# szPg = %d\n", g.szPg);
- ofstTrace(&g, "# iRoot = %d\n", g.iRoot);
- ofstTrace(&g, "# iCol = %d\n", g.iCol);
- g.f = fopen(argv[1], "rb");
- if( g.f==0 ){
- fprintf(stderr, "cannot open \"%s\"\n", argv[1]);
- exit(1);
- }
- ofstWalkPage(&g, g.iRoot);
- if( g.zErr ){
- fprintf(stderr, "%s\n", g.zErr);
- exit(1);
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/omittest.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/omittest.tcl
deleted file mode 100644
index c42519dd8c1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/omittest.tcl
+++ /dev/null
@@ -1,307 +0,0 @@
-# Documentation for this script. This may be output to stderr
-# if the script is invoked incorrectly.
-set ::USAGE_MESSAGE {
-This Tcl script is used to test the various compile time options
-available for omitting code (the SQLITE_OMIT_xxx options). It
-should be invoked as follows:
-
- <script> ?test-symbol? ?-makefile PATH-TO-MAKEFILE? ?-skip_run?
-
-The default value for ::MAKEFILE is "../Makefile.linux.gcc".
-
-If -skip_run option is given then only the compile part is attempted.
-
-This script builds the testfixture program and runs the SQLite test suite
-once with each SQLITE_OMIT_ option defined and then once with all options
-defined together. Each run is performed in a seperate directory created
-as a sub-directory of the current directory by the script. The output
-of the build is saved in <sub-directory>/build.log. The output of the
-test-suite is saved in <sub-directory>/test.log.
-
-Almost any SQLite makefile (except those generated by configure - see below)
-should work. The following properties are required:
-
- * The makefile should support the "testfixture" target.
- * The makefile should support the "test" target.
- * The makefile should support the variable "OPTS" as a way to pass
- options from the make command line to lemon and the C compiler.
-
-More precisely, the following two invocations must be supported:
-
- $::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.
-}
-
-
-# Build a testfixture executable and run quick.test using it. The first
-# parameter is the name of the directory to create and use to run the
-# test in. The second parameter is a list of OMIT symbols to define
-# when doing so. For example:
-#
-# run_quick_test /tmp/testdir {SQLITE_OMIT_TRIGGER SQLITE_OMIT_VIEW}
-#
-#
-proc run_quick_test {dir omit_symbol_list} {
- # Compile the value of the OPTS Makefile variable.
- set opts ""
- if {$::tcl_platform(platform)=="windows"} {
- append opts "OPTS += -DSQLITE_OS_WIN=1\n"
- set target "testfixture.exe"
- } else {
- append opts "OPTS += -DSQLITE_OS_UNIX=1\n"
- }
- foreach sym $omit_symbol_list {
- append opts "OPTS += -D${sym}=1\n"
- }
-
- # Create the directory and do the build. If an error occurs return
- # early without attempting to run the test suite.
- file mkdir $dir
- puts -nonewline "Building $dir..."
- flush stdout
- catch {
- file copy -force ./config.h $dir
- file copy -force ./libtool $dir
- }
- set fd [open $::MAKEFILE]
- set mkfile [read $fd]
- close $fd
- regsub {\ninclude} $mkfile "\n$opts\ninclude" mkfile
- set fd [open $dir/makefile w]
- puts $fd $mkfile
- close $fd
-
- set rc [catch {
- exec $::MAKEBIN -C $dir -f makefile clean $::TARGET >& $dir/build.log
- }]
- if {$rc} {
- puts "No good. See $dir/build.log."
- return
- } else {
- puts "Ok"
- }
-
- # Create an empty file "$dir/sqlite3". This is to trick the makefile out
- # of trying to build the sqlite shell. The sqlite shell won't build
- # with some of the OMIT options (i.e OMIT_COMPLETE).
- set sqlite3_dummy $dir/sqlite3
- if {$::tcl_platform(platform)=="windows"} {
- append sqlite3_dummy ".exe"
- }
- if {![file exists $sqlite3_dummy]} {
- set wr [open $sqlite3_dummy w]
- puts $wr "dummy"
- close $wr
- }
-
- if {$::SKIP_RUN} {
- puts "Skip testing $dir."
- } else {
- # Run the test suite.
- puts -nonewline "Testing $dir..."
- flush stdout
- set rc [catch {
- exec $::MAKEBIN -C $dir -f makefile test >& $dir/test.log
- }]
- if {$rc} {
- puts "No good. See $dir/test.log."
- } else {
- puts "Ok"
- }
- }
-}
-
-
-# This proc processes the command line options passed to this script.
-# Currently the only option supported is "-makefile", default
-# "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this
-# option.
-#
-proc process_options {argv} {
- set ::MAKEBIN make ;# Default value
- if {$::tcl_platform(platform)=="windows"} {
- set ::MAKEFILE ./Makefile ;# Default value on Windows
- } else {
- set ::MAKEFILE ./Makefile.linux-gcc ;# Default value
- }
- set ::SKIP_RUN 0 ;# Default to attempt test
- set ::TARGET testfixture ;# Default thing to build
-
- for {set i 0} {$i < [llength $argv]} {incr i} {
- switch -regexp -- [lindex $argv $i] {
- -{1,2}makefile {
- incr i
- set ::MAKEFILE [lindex $argv $i]
- }
-
- -{1,2}nmake {
- set ::MAKEBIN nmake
- set ::MAKEFILE ./Makefile.msc
- }
-
- -{1,2}target {
- incr i
- set ::TARGET [lindex $argv $i]
- }
-
- -{1,2}skip_run {
- set ::SKIP_RUN 1
- }
-
- -{1,2}help {
- puts $::USAGE_MESSAGE
- exit
- }
-
- -.* {
- puts stderr "Unknown option: [lindex $argv i]"
- puts stderr $::USAGE_MESSAGE
- exit 1
- }
-
- default {
- if {[info exists ::SYMBOL]} {
- puts stderr [string trim $::USAGE_MESSAGE]
- exit -1
- }
- set ::SYMBOL [lindex $argv $i]
- }
- }
- set ::MAKEFILE [file normalize $::MAKEFILE]
- }
-}
-
-# Main routine.
-#
-
-proc main {argv} {
- # List of SQLITE_OMIT_XXX symbols supported by SQLite.
- set ::OMIT_SYMBOLS [list \
- SQLITE_OMIT_ALTERTABLE \
- SQLITE_OMIT_ANALYZE \
- SQLITE_OMIT_ATTACH \
- SQLITE_OMIT_AUTHORIZATION \
- SQLITE_OMIT_AUTOINCREMENT \
- SQLITE_OMIT_AUTOINIT \
- SQLITE_OMIT_AUTOMATIC_INDEX \
- SQLITE_OMIT_AUTORESET \
- SQLITE_OMIT_AUTOVACUUM \
- SQLITE_OMIT_BETWEEN_OPTIMIZATION \
- SQLITE_OMIT_BLOB_LITERAL \
- SQLITE_OMIT_BTREECOUNT \
- SQLITE_OMIT_BUILTIN_TEST \
- SQLITE_OMIT_CAST \
- SQLITE_OMIT_CHECK \
- SQLITE_OMIT_COMPILEOPTION_DIAGS \
- SQLITE_OMIT_COMPLETE \
- SQLITE_OMIT_COMPOUND_SELECT \
- SQLITE_OMIT_CTE \
- SQLITE_OMIT_DATETIME_FUNCS \
- SQLITE_OMIT_DECLTYPE \
- SQLITE_OMIT_DEPRECATED \
- SQLITE_OMIT_EXPLAIN \
- SQLITE_OMIT_FLAG_PRAGMAS \
- SQLITE_OMIT_FLOATING_POINT \
- SQLITE_OMIT_FOREIGN_KEY \
- SQLITE_OMIT_GET_TABLE \
- SQLITE_OMIT_INCRBLOB \
- SQLITE_OMIT_INTEGRITY_CHECK \
- SQLITE_OMIT_LIKE_OPTIMIZATION \
- SQLITE_OMIT_LOAD_EXTENSION \
- SQLITE_OMIT_LOCALTIME \
- SQLITE_OMIT_LOOKASIDE \
- SQLITE_OMIT_MEMORYDB \
- SQLITE_OMIT_OR_OPTIMIZATION \
- SQLITE_OMIT_PAGER_PRAGMAS \
- SQLITE_OMIT_PRAGMA \
- SQLITE_OMIT_PROGRESS_CALLBACK \
- SQLITE_OMIT_QUICKBALANCE \
- SQLITE_OMIT_REINDEX \
- SQLITE_OMIT_SCHEMA_PRAGMAS \
- SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS \
- SQLITE_OMIT_SHARED_CACHE \
- SQLITE_OMIT_SUBQUERY \
- SQLITE_OMIT_TCL_VARIABLE \
- SQLITE_OMIT_TEMPDB \
- SQLITE_OMIT_TRACE \
- SQLITE_OMIT_TRIGGER \
- SQLITE_OMIT_TRUNCATE_OPTIMIZATION \
- SQLITE_OMIT_UNIQUE_ENFORCEMENT \
- SQLITE_OMIT_UTF16 \
- SQLITE_OMIT_VACUUM \
- SQLITE_OMIT_VIEW \
- SQLITE_OMIT_VIRTUALTABLE \
- SQLITE_OMIT_WAL \
- SQLITE_OMIT_WSD \
- SQLITE_OMIT_XFER_OPT \
- ]
-
- set ::ENABLE_SYMBOLS [list \
- SQLITE_DISABLE_DIRSYNC \
- SQLITE_DISABLE_LFS \
- SQLITE_ENABLE_ATOMIC_WRITE \
- SQLITE_ENABLE_COLUMN_METADATA \
- SQLITE_ENABLE_EXPENSIVE_ASSERT \
- SQLITE_ENABLE_FTS3 \
- SQLITE_ENABLE_FTS3_PARENTHESIS \
- SQLITE_ENABLE_FTS4 \
- SQLITE_ENABLE_IOTRACE \
- SQLITE_ENABLE_LOAD_EXTENSION \
- SQLITE_ENABLE_LOCKING_STYLE \
- SQLITE_ENABLE_MEMORY_MANAGEMENT \
- SQLITE_ENABLE_MEMSYS3 \
- SQLITE_ENABLE_MEMSYS5 \
- SQLITE_ENABLE_OVERSIZE_CELL_CHECK \
- SQLITE_ENABLE_RTREE \
- SQLITE_ENABLE_STAT3 \
- SQLITE_ENABLE_UNLOCK_NOTIFY \
- SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
- ]
-
- # Process any command line options.
- process_options $argv
-
- if {[info exists ::SYMBOL] } {
- set sym $::SYMBOL
-
- if {[lsearch $::OMIT_SYMBOLS $sym]<0 && [lsearch $::ENABLE_SYMBOLS $sym]<0} {
- puts stderr "No such symbol: $sym"
- exit -1
- }
-
- 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
- # and SQLITE_OMIT_PRAGMA defined. The former doesn't work (causes segfaults)
- # and the latter is currently incompatible with the test suite (this should
- # be fixed, but it will be a lot of work).
- set allsyms [list]
- foreach s $::OMIT_SYMBOLS {
- if {$s!="SQLITE_OMIT_FLOATING_POINT" && $s!="SQLITE_OMIT_PRAGMA"} {
- lappend allsyms $s
- }
- }
- run_quick_test test_OMIT_EVERYTHING $allsyms
-
- # Now try one quick.test with each of the OMIT symbols defined. Included
- # 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_[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_[regsub -nocase {^x*SQLITE_} $sym {}]"
- run_quick_test $dirname $sym
- }
- }
-}
-
-main $argv
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/opcodesum.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/opcodesum.tcl
deleted file mode 100644
index 47dff32b907..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/opcodesum.tcl
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Run this script, redirecting input from cachegrind output, to compute the
-# number of CPU cycles used by each VDBE opcode.
-#
-# The cachegrind output should be configured so that it reports a single
-# column of Ir at the left margin. Ex:
-#
-# cg_annotation --show=Ir --auto=yes cachegrind.out.* | tclsh opcodesum.tcl
-#
-set currentop x
-set ncycle(x) 0
-while {![eof stdin]} {
- set line [string map {\173 x \175 x \042 x} [gets stdin]]
- if {[regexp { \. case OP_.*:} $line]} {
- regexp {OP_(.+):} $line all currentop
- set ncycle($currentop) 0
- } elseif {[lindex $line 1]=="default:"
- && [regexp {really OP_Noop and OP_Explain} $line]} {
- break
- } elseif {[lindex $line 0]!="."} {
- regsub -all {[^0-9]} [lindex $line 0] {} n
- if {$n!=""} {incr ncycle($currentop) $n}
- }
-}
-unset ncycle(x)
-set results {}
-foreach op [lsort [array names ncycle]] {
- if {$ncycle($op)==0} continue
- lappend results [list $ncycle($op) $op]
-}
-foreach entry [lsort -index 0 -int -decr $results] {
- puts [format {%-16s %10d} [lindex $entry 1] [lindex $entry 0]]
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/pagesig.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/pagesig.c
deleted file mode 100644
index 540c9d72266..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/pagesig.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-** 2013-10-01
-**
-** 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.
-**
-******************************************************************************
-**
-** Compute hash signatures for every page of a database file. This utility
-** program is useful for analyzing the output logs generated by the
-** ext/misc/vfslog.c extension.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-
-/*
-** Compute signature for a block of content.
-**
-** For blocks of 16 or fewer bytes, the signature is just a hex dump of
-** the entire block.
-**
-** For blocks of more than 16 bytes, the signature is a hex dump of the
-** first 8 bytes followed by a 64-bit has of the entire block.
-*/
-static void vlogSignature(unsigned char *p, int n, char *zCksum){
- unsigned int s0 = 0, s1 = 0;
- unsigned int *pI;
- int i;
- if( n<=16 ){
- for(i=0; i<n; i++) sprintf(zCksum+i*2, "%02x", p[i]);
- }else{
- pI = (unsigned int*)p;
- for(i=0; i<n-7; i+=8){
- s0 += pI[0] + s1;
- s1 += pI[1] + s0;
- pI += 2;
- }
- for(i=0; i<8; i++) sprintf(zCksum+i*2, "%02x", p[i]);
- sprintf(zCksum+i*2, "-%08x%08x", s0, s1);
- }
-}
-
-/*
-** Open a file. Find its page size. Read each page, and compute and
-** display the page signature.
-*/
-static void computeSigs(const char *zFilename){
- FILE *in = fopen(zFilename, "rb");
- unsigned pgsz;
- size_t got;
- unsigned n;
- unsigned char aBuf[50];
- unsigned char aPage[65536];
-
- if( in==0 ){
- fprintf(stderr, "cannot open \"%s\"\n", zFilename);
- return;
- }
- got = fread(aBuf, 1, sizeof(aBuf), in);
- if( got!=sizeof(aBuf) ){
- goto endComputeSigs;
- }
- pgsz = aBuf[16]*256 + aBuf[17];
- if( pgsz==1 ) pgsz = 65536;
- if( (pgsz & (pgsz-1))!=0 ){
- fprintf(stderr, "invalid page size: %02x%02x\n", aBuf[16], aBuf[17]);
- goto endComputeSigs;
- }
- rewind(in);
- for(n=1; (got=fread(aPage, 1, pgsz, in))==pgsz; n++){
- vlogSignature(aPage, pgsz, aBuf);
- printf("%4d: %s\n", n, aBuf);
- }
-
-endComputeSigs:
- fclose(in);
-}
-
-/*
-** Find page signatures for all named files.
-*/
-int main(int argc, char **argv){
- int i;
- for(i=1; i<argc; i++) computeSigs(argv[i]);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/replace.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/replace.tcl
deleted file mode 100644
index 5a1ac5983c4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/replace.tcl
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/tcl
-#
-# Replace string with another string -OR- include
-# only lines successfully modified with a regular
-# expression.
-#
-fconfigure stdout -translation binary -encoding binary
-fconfigure stderr -translation binary -encoding binary
-set mode [string tolower [lindex $argv 0]]
-set from [lindex $argv 1]
-set to [lindex $argv 2]
-if {$mode ni [list exact regsub include]} {exit 1}
-if {[string length $from]==0} {exit 2}
-while {![eof stdin]} {
- set line [gets stdin]
- if {[eof stdin]} break
- switch -exact $mode {
- exact {set line [string map [list $from $to] $line]}
- regsub {regsub -all -- $from $line $to line}
- include {if {[regsub -all -- $from $line $to line]==0} continue}
- }
- puts stdout $line
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/restore_jrnl.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/restore_jrnl.tcl
deleted file mode 100644
index 65dee80ca27..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/restore_jrnl.tcl
+++ /dev/null
@@ -1,233 +0,0 @@
-# 2010 January 7
-#
-# 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 utility functions for SQLite library.
-#
-# This file attempts to restore the header of a journal.
-# This may be useful for rolling-back the last committed
-# transaction from a recovered journal.
-#
-
-package require sqlite3
-
-set parm_error 0
-set fix_chksums 0
-set dump_pages 0
-set db_name ""
-
-for {set i 0} {$i<$argc} {incr i} {
- if {[lindex $argv $i] == "-fix_chksums"} {
- set fix_chksums -1
- } elseif {[lindex $argv $i] == "-dump_pages"} {
- set dump_pages -1
- } elseif {$db_name == ""} {
- set db_name [lindex $argv $i]
- set jrnl_name $db_name-journal
- } else {
- set parm_error -1
- }
-}
-if {$parm_error || $db_name == ""} {
- puts "USAGE: restore_jrnl.tcl \[-fix_chksums\] \[-dump_pages\] db_name"
- puts "Example: restore_jrnl.tcl foo.sqlite"
- return
-}
-
-# is there a way to determine this?
-set sectsz 512
-
-# Copy file $from into $to
-#
-proc copy_file {from to} {
- file copy -force $from $to
-}
-
-# Execute some SQL
-#
-proc catchsql {sql} {
- set rc [catch {uplevel [list db eval $sql]} msg]
- list $rc $msg
-}
-
-# Perform a test
-#
-proc do_test {name cmd expected} {
- puts -nonewline "$name ..."
- set res [uplevel $cmd]
- if {$res eq $expected} {
- puts Ok
- } else {
- puts Error
- puts " Got: $res"
- puts " Expected: $expected"
- }
-}
-
-# Calc checksum nonce from journal page data.
-#
-proc calc_nonce {jrnl_pgno} {
- global sectsz
- global db_pgsz
- global jrnl_name
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
- set nonce [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]]
- for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} {
- set byte [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$i] 1]]
- set nonce [expr $nonce-$byte]
- }
- return $nonce
-}
-
-# Calc checksum from journal page data.
-#
-proc calc_chksum {jrnl_pgno} {
- global sectsz
- global db_pgsz
- global jrnl_name
- global nonce
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
- set chksum $nonce
- for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} {
- set byte [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$i] 1]]
- set chksum [expr $chksum+$byte]
- }
- return $chksum
-}
-
-# Print journal page data in hex dump form
-#
-proc dump_jrnl_page {jrnl_pgno} {
- global sectsz
- global db_pgsz
- global jrnl_name
-
- # print a header block for the page
- puts [string repeat "-" 79]
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
- set db_pgno [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset] 4]]
- set chksum [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]]
- set nonce [calc_nonce $jrnl_pgno]
- puts [ format {jrnl_pg_offset: %08x (%d) jrnl_pgno: %d db_pgno: %d} \
- $jrnl_pg_offset $jrnl_pg_offset \
- $jrnl_pgno $db_pgno]
- puts [ format {nonce: %08x chksum: %08x} \
- $nonce $chksum]
-
- # now hex dump the data
- # This is derived from the Tcler's WIKI
- set fid [open $jrnl_name r]
- fconfigure $fid -translation binary -encoding binary
- seek $fid [expr $jrnl_pg_offset+4]
- set data [read $fid $db_pgsz]
- close $fid
- for {set addr 0} {$addr<$db_pgsz} {set addr [expr $addr+16]} {
- # get 16 bytes of data
- set s [string range $data $addr [expr $addr+16]]
-
- # Convert the data to hex and to characters.
- binary scan $s H*@0a* hex ascii
-
- # Replace non-printing characters in the data.
- regsub -all -- {[^[:graph:] ]} $ascii {.} ascii
-
- # Split the 16 bytes into two 8-byte chunks
- regexp -- {(.{16})(.{0,16})} $hex -> hex1 hex2
-
- # Convert the hex to pairs of hex digits
- regsub -all -- {..} $hex1 {& } hex1
- regsub -all -- {..} $hex2 {& } hex2
-
- # Print the hex and ascii data
- puts [ format {%08x %-24s %-24s %-16s} \
- $addr $hex1 $hex2 $ascii ]
- }
-}
-
-# Setup for the tests. Make a backup copy of the files.
-#
-if [file exist $db_name.org] {
- puts "ERROR: during back-up: $db_name.org exists already."
- return;
-}
-if [file exist $jrnl_name.org] {
- puts "ERROR: during back-up: $jrnl_name.org exists already."
- return
-}
-copy_file $db_name $db_name.org
-copy_file $jrnl_name $jrnl_name.org
-
-set db_fsize [file size $db_name]
-set db_pgsz [hexio_get_int [hexio_read $db_name 16 2]]
-set db_npage [expr {$db_fsize / $db_pgsz}]
-
-set jrnl_fsize [file size $jrnl_name]
-set jrnl_npage [expr {($jrnl_fsize - $sectsz) / (4 + $db_pgsz + 4)}]
-
-# calculate checksum nonce for first page
-set nonce [calc_nonce 0]
-
-# verify all the pages in the journal use the same nonce
-for {set i 1} {$i<$jrnl_npage} {incr i} {
- set tnonce [calc_nonce $i]
- if {$tnonce != $nonce} {
- puts "WARNING: different nonces: 0=$nonce $i=$tnonce"
- if {$fix_chksums } {
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$i)]
- set tchksum [calc_chksum $i]
- hexio_write $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] [format %08x $tchksum]
- puts "INFO: fixing chksum: $i=$tchksum"
- }
- }
-}
-
-# verify all the page numbers in the journal
-for {set i 0} {$i<$jrnl_npage} {incr i} {
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$i)]
- set db_pgno [hexio_get_int [hexio_read $jrnl_name $jrnl_pg_offset 4]]
- if {$db_pgno < 1} {
- puts "WARNING: page number < 1: $i=$db_pgno"
- }
- if {$db_pgno >= $db_npage} {
- puts "WARNING: page number >= $db_npage: $i=$db_pgno"
- }
-}
-
-# dump page data
-if {$dump_pages} {
- for {set i 0} {$i<$jrnl_npage} {incr i} {
- dump_jrnl_page $i
- }
-}
-
-# write the 8 byte magic string
-hexio_write $jrnl_name 0 d9d505f920a163d7
-
-# write -1 for number of records
-hexio_write $jrnl_name 8 ffffffff
-
-# write 00 for checksum nonce
-hexio_write $jrnl_name 12 [format %08x $nonce]
-
-# write page count
-hexio_write $jrnl_name 16 [format %08x $db_npage]
-
-# write sector size
-hexio_write $jrnl_name 20 [format %08x $sectsz]
-
-# write page size
-hexio_write $jrnl_name 24 [format %08x $db_pgsz]
-
-# check the integrity of the database with the patched journal
-sqlite3 db $db_name
-do_test restore_jrnl-1.0 {
- catchsql {PRAGMA integrity_check}
-} {0 ok}
-db close
-
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/rollback-test.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/rollback-test.c
deleted file mode 100644
index 915d9d203da..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/rollback-test.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
-** This program is used to generate and verify databases with hot journals.
-** Use this program to generate a hot journal on one machine and verify
-** that it rolls back correctly on another machine with a different
-** architecture.
-**
-** Usage:
-**
-** rollback-test new [-utf8] [-utf16le] [-utf16be] [-pagesize=N] DATABASE
-** rollback-test check DATABASE
-** rollback-test crash [-wal] [-rollback] DATABASE
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sqlite3.h"
-
-static void usage(char *argv0){
- fprintf(stderr,
- "Usage: %s new [-utf8] [-utf16le] [-utf16be] [-pagesize=N] DATABASE\n"
- " %s check DATABASE\n"
- " %s crash [-wal] DATABASE\n",
- argv0, argv0, argv0
- );
- exit(1);
-}
-
-static sqlite3 *openDb(const char *zFilename){
- int rc;
- sqlite3 *db;
- rc = sqlite3_open(zFilename, &db);
- if( rc ){
- fprintf(stderr, "Cannot open \"%s\": %s\n",
- zFilename, sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
- return db;
-}
-
-static int nReply = 0;
-static char zReply[1000];
-
-static int execCallback(void *NotUsed, int nArg, char **azArg, char **azCol){
- int i, n;
- char *z;
- for(i=0; i<nArg; i++){
- z = azArg[i];
- if( z==0 ) z = "NULL";
- if( nReply>0 && nReply<sizeof(zReply)-1 ) zReply[nReply++] = ' ';
- n = strlen(z);
- if( nReply+n>=sizeof(zReply)-1 ) n = sizeof(zReply) - nReply - 1;
- memcpy(&zReply[nReply], z, n);
- nReply += n;
- zReply[nReply] = 0;
- }
- return 0;
-}
-
-static void runSql(sqlite3 *db, const char *zSql){
- char *zErr = 0;
- int rc;
- nReply = 0;
- rc = sqlite3_exec(db, zSql, execCallback, 0, &zErr);
- if( zErr ){
- fprintf(stderr, "SQL error: %s\n", zErr);
- exit(1);
- }
- if( rc ){
- fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
- exit(1);
- }
-}
-
-int main(int argc, char **argv){
- sqlite3 *db;
- int i;
-
- if( argc<3 ) usage(argv[0]);
- if( strcmp(argv[1], "new")==0 ){
- db = openDb(argv[argc-1]);
- for(i=2; i<argc-1; i++){
- if( strcmp(argv[i],"-utf8")==0 ){
- runSql(db, "PRAGMA encoding=UTF8");
- }else if( strcmp(argv[i], "-utf16le")==0 ){
- runSql(db, "PRAGMA encoding=UTF16LE");
- }else if( strcmp(argv[i], "-utf16be")==0 ){
- runSql(db, "PRAGMA encoding=UTF16BE");
- }else if( strncmp(argv[i], "-pagesize=", 10)==0 ){
- int szPg = atoi(&argv[i][10]);
- char zBuf[100];
- sprintf(zBuf, "PRAGMA pagesize=%d", szPg);
- runSql(db, zBuf);
- }else{
- fprintf(stderr, "unknown option %s\n", argv[i]);
- usage(argv[0]);
- }
- }
- runSql(db,
- "BEGIN;"
- "CREATE TABLE t1(x INTEGER PRIMARY KEY, y);"
- "INSERT INTO t1(y) VALUES('abcdefghijklmnopqrstuvwxyz');"
- "INSERT INTO t1(y) VALUES('abcdefghijklmnopqrstuvwxyz');"
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 4 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 8 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 16 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 32 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 64 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 128 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 256 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 512 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 1024 */
- "UPDATE t1 SET y=(y || x);"
- "CREATE INDEX t1y ON t1(y);"
- "COMMIT;"
- );
- sqlite3_close(db);
- }else if( strcmp(argv[1], "check")==0 ){
- db = openDb(argv[argc-1]);
- runSql(db, "PRAGMA integrity_check");
- if( strcmp(zReply, "ok")!=0 ){
- fprintf(stderr, "Integrity check: %s\n", zReply);
- exit(1);
- }
- runSql(db,
- "SELECT count(*) FROM t1 WHERE y<>('abcdefghijklmnopqrstuvwxyz' || x)"
- );
- if( strcmp(zReply, "0")!=0 ){
- fprintf(stderr, "Wrong content\n");
- exit(1);
- }
- printf("Ok\n");
- }else if( strcmp(argv[1], "crash")==0 ){
- db = openDb(argv[argc-1]);
- for(i=2; i<argc-1; i++){
- if( strcmp(argv[i],"-wal")==0 ){
- runSql(db, "PRAGMA journal_mode=WAL");
- }else if( strcmp(argv[i], "-rollback")==0 ){
- runSql(db, "PRAGMA journal_mode=DELETE");
- }else{
- fprintf(stderr, "unknown option %s\n", argv[i]);
- usage(argv[0]);
- }
- }
- runSql(db,
- "PRAGMA cache_size=10;"
- "BEGIN;"
- "UPDATE t1 SET y=(y || -x)"
- );
- exit(0);
- }else{
- usage(argv[0]);
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/run-speed-test.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/run-speed-test.sh
deleted file mode 100644
index 0e970ea0f60..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/run-speed-test.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/bash
-#
-# This is a template for a script used for day-to-day size and
-# performance monitoring of SQLite. Typical usage:
-#
-# sh run-speed-test.sh trunk # Baseline measurement of trunk
-# sh run-speed-test.sh x1 # Measure some experimental change
-# fossil test-diff --tk cout-trunk.txt cout-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
-# cout-$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"
-SPEEDTEST_OPTS="--shrink-memory --reprepare --heap 10000000 64"
-SIZE=5
-doExplain=0
-while test "$1" != ""; do
- case $1 in
- --reprepare)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --autovacuum)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --utf16be)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --stats)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --without-rowid)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --nomemstat)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --wal)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --journal wal"
- ;;
- --size)
- shift; SIZE=$1
- ;;
- --explain)
- doExplain=1
- ;;
- --heap)
- CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_MEMSYS5"
- shift;
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --heap $1 64"
- ;;
- *)
- CC_OPTS="$CC_OPTS $1"
- ;;
- esac
- shift
-done
-SPEEDTEST_OPTS="$SPEEDTEST_OPTS --size $SIZE"
-echo "NAME = $NAME" | tee summary-$NAME.txt
-echo "SPEEDTEST_OPTS = $SPEEDTEST_OPTS" | tee -a summary-$NAME.txt
-echo "CC_OPTS = $CC_OPTS" | tee -a summary-$NAME.txt
-rm -f cachegrind.out.* speedtest1 speedtest1.db sqlite3.o
-gcc -g -Os -Wall -I. $CC_OPTS -c sqlite3.c
-size sqlite3.o | tee -a summary-$NAME.txt
-if test $doExplain -eq 1; then
- gcc -g -Os -Wall -I. $CC_OPTS \
- -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
- ./shell.c ./sqlite3.c -o sqlite3 -ldl -lpthread
-fi
-SRC=./speedtest1.c
-gcc -g -Os -Wall -I. $CC_OPTS $SRC ./sqlite3.o -o speedtest1 -ldl -lpthread
-ls -l speedtest1 | tee -a summary-$NAME.txt
-valgrind --tool=cachegrind ./speedtest1 speedtest1.db \
- $SPEEDTEST_OPTS 2>&1 | tee -a summary-$NAME.txt
-size sqlite3.o | tee -a summary-$NAME.txt
-wc sqlite3.c
-cg_anno.tcl cachegrind.out.* >cout-$NAME.txt
-if test $doExplain -eq 1; then
- ./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt
-fi
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showdb.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/showdb.c
deleted file mode 100644
index ba7a362258d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showdb.c
+++ /dev/null
@@ -1,1179 +0,0 @@
-/*
-** A utility for printing all or part of an SQLite database file.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#define ISDIGIT(X) isdigit((unsigned char)(X))
-#define ISPRINT(X) isprint((unsigned char)(X))
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#if !defined(_MSC_VER)
-#include <unistd.h>
-#else
-#include <io.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "sqlite3.h"
-
-
-static struct GlobalData {
- int pagesize; /* Size of a database page */
- int dbfd; /* File descriptor for reading the DB */
- int mxPage; /* Last page number */
- int perLine; /* HEX elements to print per line */
- int bRaw; /* True to access db file via OS APIs */
- sqlite3_file *pFd; /* File descriptor for non-raw mode */
- sqlite3 *pDb; /* Database handle that owns pFd */
-} g = {1024, -1, 0, 16, 0, 0, 0};
-
-
-typedef long long int i64; /* Datatype for 64-bit integers */
-
-
-/*
-** Convert the var-int format into i64. Return the number of bytes
-** in the var-int. Write the var-int value into *pVal.
-*/
-static int decodeVarint(const unsigned char *z, i64 *pVal){
- i64 v = 0;
- int i;
- for(i=0; i<8; i++){
- v = (v<<7) + (z[i]&0x7f);
- if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
- }
- v = (v<<8) + (z[i]&0xff);
- *pVal = v;
- return 9;
-}
-
-/*
-** Extract a big-endian 32-bit integer
-*/
-static unsigned int decodeInt32(const unsigned char *z){
- return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3];
-}
-
-/* Report an out-of-memory error and die.
-*/
-static void out_of_memory(void){
- fprintf(stderr,"Out of memory...\n");
- exit(1);
-}
-
-/*
-** Open a database connection.
-*/
-static sqlite3 *openDatabase(const char *zPrg, const char *zName){
- sqlite3 *db = 0;
- int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
- int rc = sqlite3_open_v2(zName, &db, flags, 0);
- if( rc!=SQLITE_OK ){
- const char *zErr = sqlite3_errmsg(db);
- fprintf(stderr, "%s: can't open %s (%s)\n", zPrg, zName, zErr);
- sqlite3_close(db);
- exit(1);
- }
- return db;
-}
-
-/**************************************************************************
-** Beginning of low-level file access functions.
-**
-** All low-level access to the database file read by this program is
-** performed using the following four functions:
-**
-** fileOpen() - open the db file
-** fileClose() - close the db file
-** fileRead() - read raw data from the db file
-** fileGetsize() - return the size of the db file in bytes
-*/
-
-/*
-** Open the database file.
-*/
-static void fileOpen(const char *zPrg, const char *zName){
- assert( g.dbfd<0 );
- if( g.bRaw==0 ){
- int rc;
- void *pArg = (void *)(&g.pFd);
- g.pDb = openDatabase(zPrg, zName);
- rc = sqlite3_file_control(g.pDb, "main", SQLITE_FCNTL_FILE_POINTER, pArg);
- if( rc!=SQLITE_OK ){
- fprintf(stderr,
- "%s: failed to obtain fd for %s (SQLite too old?)\n", zPrg, zName
- );
- exit(1);
- }
- }else{
- g.dbfd = open(zName, O_RDONLY);
- if( g.dbfd<0 ){
- fprintf(stderr,"%s: can't open %s\n", zPrg, zName);
- exit(1);
- }
- }
-}
-
-/*
-** Close the database file opened by fileOpen()
-*/
-static void fileClose(){
- if( g.bRaw==0 ){
- sqlite3_close(g.pDb);
- g.pDb = 0;
- g.pFd = 0;
- }else{
- close(g.dbfd);
- g.dbfd = -1;
- }
-}
-
-/*
-** Read content from the file.
-**
-** Space to hold the content is obtained from sqlite3_malloc() and needs
-** to be freed by the caller.
-*/
-static unsigned char *fileRead(sqlite3_int64 ofst, int nByte){
- unsigned char *aData;
- int got;
- aData = sqlite3_malloc(nByte+32);
- if( aData==0 ) out_of_memory();
- memset(aData, 0, nByte+32);
- if( g.bRaw==0 ){
- int rc = g.pFd->pMethods->xRead(g.pFd, (void*)aData, nByte, ofst);
- if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
- fprintf(stderr, "error in xRead() - %d\n", rc);
- exit(1);
- }
- }else{
- lseek(g.dbfd, (long)ofst, SEEK_SET);
- got = read(g.dbfd, aData, nByte);
- if( got>0 && got<nByte ) memset(aData+got, 0, nByte-got);
- }
- return aData;
-}
-
-/*
-** Return the size of the file in byte.
-*/
-static sqlite3_int64 fileGetsize(void){
- sqlite3_int64 res = 0;
- if( g.bRaw==0 ){
- int rc = g.pFd->pMethods->xFileSize(g.pFd, &res);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "error in xFileSize() - %d\n", rc);
- exit(1);
- }
- }else{
- struct stat sbuf;
- fstat(g.dbfd, &sbuf);
- res = (sqlite3_int64)(sbuf.st_size);
- }
- return res;
-}
-
-/*
-** End of low-level file access functions.
-**************************************************************************/
-
-/*
-** Print a range of bytes as hex and as ascii.
-*/
-static unsigned char *print_byte_range(
- int ofst, /* First byte in the range of bytes to print */
- int nByte, /* Number of bytes to print */
- int printOfst /* Add this amount to the index on the left column */
-){
- unsigned char *aData;
- int i, j;
- const char *zOfstFmt;
-
- if( ((printOfst+nByte)&~0xfff)==0 ){
- zOfstFmt = " %03x: ";
- }else if( ((printOfst+nByte)&~0xffff)==0 ){
- zOfstFmt = " %04x: ";
- }else if( ((printOfst+nByte)&~0xfffff)==0 ){
- zOfstFmt = " %05x: ";
- }else if( ((printOfst+nByte)&~0xffffff)==0 ){
- zOfstFmt = " %06x: ";
- }else{
- zOfstFmt = " %08x: ";
- }
-
- aData = fileRead(ofst, nByte);
- for(i=0; i<nByte; i += g.perLine){
- fprintf(stdout, zOfstFmt, i+printOfst);
- for(j=0; j<g.perLine; j++){
- if( i+j>nByte ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%02x ", aData[i+j]);
- }
- }
- for(j=0; j<g.perLine; j++){
- if( i+j>nByte ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%c", ISPRINT(aData[i+j]) ? aData[i+j] : '.');
- }
- }
- fprintf(stdout,"\n");
- }
- return aData;
-}
-
-/*
-** Print an entire page of content as hex
-*/
-static void print_page(int iPg){
- int iStart;
- unsigned char *aData;
- iStart = (iPg-1)*g.pagesize;
- fprintf(stdout, "Page %d: (offsets 0x%x..0x%x)\n",
- iPg, iStart, iStart+g.pagesize-1);
- aData = print_byte_range(iStart, g.pagesize, 0);
- sqlite3_free(aData);
-}
-
-
-/* Print a line of decode output showing a 4-byte integer.
-*/
-static void print_decode_line(
- unsigned char *aData, /* Content being decoded */
- int ofst, int nByte, /* Start and size of decode */
- const char *zMsg /* Message to append */
-){
- int i, j;
- int val = aData[ofst];
- char zBuf[100];
- sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
- i = (int)strlen(zBuf);
- for(j=1; j<4; j++){
- if( j>=nByte ){
- sprintf(&zBuf[i], " ");
- }else{
- sprintf(&zBuf[i], " %02x", aData[ofst+j]);
- val = val*256 + aData[ofst+j];
- }
- i += (int)strlen(&zBuf[i]);
- }
- sprintf(&zBuf[i], " %9d", val);
- printf("%s %s\n", zBuf, zMsg);
-}
-
-/*
-** Decode the database header.
-*/
-static void print_db_header(void){
- unsigned char *aData;
- aData = print_byte_range(0, 100, 0);
- printf("Decoded:\n");
- print_decode_line(aData, 16, 2, "Database page size");
- print_decode_line(aData, 18, 1, "File format write version");
- print_decode_line(aData, 19, 1, "File format read version");
- print_decode_line(aData, 20, 1, "Reserved space at end of page");
- print_decode_line(aData, 24, 4, "File change counter");
- print_decode_line(aData, 28, 4, "Size of database in pages");
- print_decode_line(aData, 32, 4, "Page number of first freelist page");
- print_decode_line(aData, 36, 4, "Number of freelist pages");
- print_decode_line(aData, 40, 4, "Schema cookie");
- print_decode_line(aData, 44, 4, "Schema format version");
- print_decode_line(aData, 48, 4, "Default page cache size");
- print_decode_line(aData, 52, 4, "Largest auto-vac root page");
- print_decode_line(aData, 56, 4, "Text encoding");
- print_decode_line(aData, 60, 4, "User version");
- print_decode_line(aData, 64, 4, "Incremental-vacuum mode");
- print_decode_line(aData, 68, 4, "Application ID");
- print_decode_line(aData, 72, 4, "meta[8]");
- print_decode_line(aData, 76, 4, "meta[9]");
- print_decode_line(aData, 80, 4, "meta[10]");
- print_decode_line(aData, 84, 4, "meta[11]");
- print_decode_line(aData, 88, 4, "meta[12]");
- print_decode_line(aData, 92, 4, "Change counter for version number");
- print_decode_line(aData, 96, 4, "SQLite version number");
-}
-
-/*
-** Describe cell content.
-*/
-static i64 describeContent(
- unsigned char *a, /* Cell content */
- i64 nLocal, /* Bytes in a[] */
- char *zDesc /* Write description here */
-){
- i64 nDesc = 0;
- int n, j;
- i64 i, x, v;
- const unsigned char *pData;
- const unsigned char *pLimit;
- char sep = ' ';
-
- pLimit = &a[nLocal];
- n = decodeVarint(a, &x);
- pData = &a[x];
- a += n;
- i = x - n;
- while( i>0 && pData<=pLimit ){
- n = decodeVarint(a, &x);
- a += n;
- i -= n;
- nLocal -= n;
- zDesc[0] = sep;
- sep = ',';
- nDesc++;
- zDesc++;
- if( x==0 ){
- sprintf(zDesc, "*"); /* NULL is a "*" */
- }else if( x>=1 && x<=6 ){
- v = (signed char)pData[0];
- pData++;
- switch( x ){
- case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 4: v = (v<<8) + pData[0]; pData++;
- case 3: v = (v<<8) + pData[0]; pData++;
- case 2: v = (v<<8) + pData[0]; pData++;
- }
- sprintf(zDesc, "%lld", v);
- }else if( x==7 ){
- sprintf(zDesc, "real");
- pData += 8;
- }else if( x==8 ){
- sprintf(zDesc, "0");
- }else if( x==9 ){
- sprintf(zDesc, "1");
- }else if( x>=12 ){
- i64 size = (x-12)/2;
- if( (x&1)==0 ){
- sprintf(zDesc, "blob(%lld)", size);
- }else{
- sprintf(zDesc, "txt(%lld)", size);
- }
- pData += size;
- }
- j = (int)strlen(zDesc);
- zDesc += j;
- nDesc += j;
- }
- return nDesc;
-}
-
-/*
-** Compute the local payload size given the total payload size and
-** the page size.
-*/
-static i64 localPayload(i64 nPayload, char cType){
- i64 maxLocal;
- i64 minLocal;
- i64 surplus;
- i64 nLocal;
- if( cType==13 ){
- /* Table leaf */
- maxLocal = g.pagesize-35;
- minLocal = (g.pagesize-12)*32/255-23;
- }else{
- maxLocal = (g.pagesize-12)*64/255-23;
- minLocal = (g.pagesize-12)*32/255-23;
- }
- if( nPayload>maxLocal ){
- surplus = minLocal + (nPayload-minLocal)%(g.pagesize-4);
- if( surplus<=maxLocal ){
- nLocal = surplus;
- }else{
- nLocal = minLocal;
- }
- }else{
- nLocal = nPayload;
- }
- return nLocal;
-}
-
-
-/*
-** Create a description for a single cell.
-**
-** The return value is the local cell size.
-*/
-static i64 describeCell(
- unsigned char cType, /* Page type */
- unsigned char *a, /* Cell content */
- int showCellContent, /* Show cell content if true */
- char **pzDesc /* Store description here */
-){
- int i;
- i64 nDesc = 0;
- int n = 0;
- int leftChild;
- i64 nPayload;
- i64 rowid;
- i64 nLocal;
- static char zDesc[1000];
- i = 0;
- if( cType<=5 ){
- leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3];
- a += 4;
- n += 4;
- sprintf(zDesc, "lx: %d ", leftChild);
- nDesc = strlen(zDesc);
- }
- if( cType!=5 ){
- i = decodeVarint(a, &nPayload);
- a += i;
- n += i;
- sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
- nDesc += strlen(&zDesc[nDesc]);
- nLocal = localPayload(nPayload, cType);
- }else{
- nPayload = nLocal = 0;
- }
- if( cType==5 || cType==13 ){
- i = decodeVarint(a, &rowid);
- a += i;
- n += i;
- sprintf(&zDesc[nDesc], "r: %lld ", rowid);
- nDesc += strlen(&zDesc[nDesc]);
- }
- if( nLocal<nPayload ){
- int ovfl;
- unsigned char *b = &a[nLocal];
- ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3];
- sprintf(&zDesc[nDesc], "ov: %d ", ovfl);
- nDesc += strlen(&zDesc[nDesc]);
- n += 4;
- }
- if( showCellContent && cType!=5 ){
- nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
- }
- *pzDesc = zDesc;
- return nLocal+n;
-}
-
-/* Print an offset followed by nByte bytes. Add extra white-space
-** at the end so that subsequent text is aligned.
-*/
-static void printBytes(
- unsigned char *aData, /* Content being decoded */
- unsigned char *aStart, /* Start of content to be printed */
- int nByte /* Number of bytes to print */
-){
- int j;
- printf(" %03x: ", (int)(aStart-aData));
- for(j=0; j<9; j++){
- if( j>=nByte ){
- printf(" ");
- }else{
- printf("%02x ", aStart[j]);
- }
- }
-}
-
-
-/*
-** Write a full decode on stdout for the cell at a[ofst].
-** Assume the page contains a header of size szPgHdr bytes.
-*/
-static void decodeCell(
- unsigned char *a, /* Page content (without the page-1 header) */
- unsigned pgno, /* Page number */
- int iCell, /* Cell index */
- int szPgHdr, /* Size of the page header. 0 or 100 */
- int ofst /* Cell begins at a[ofst] */
-){
- int i, j = 0;
- int leftChild;
- i64 k;
- i64 nPayload;
- i64 rowid;
- i64 nHdr;
- i64 iType;
- i64 nLocal;
- unsigned char *x = a + ofst;
- unsigned char *end;
- unsigned char cType = a[0];
- int nCol = 0;
- int szCol[2000];
- int ofstCol[2000];
- int typeCol[2000];
-
- printf("Cell[%d]:\n", iCell);
- if( cType<=5 ){
- leftChild = ((x[0]*256 + x[1])*256 + x[2])*256 + x[3];
- printBytes(a, x, 4);
- printf("left child page:: %d\n", leftChild);
- x += 4;
- }
- if( cType!=5 ){
- i = decodeVarint(x, &nPayload);
- printBytes(a, x, i);
- nLocal = localPayload(nPayload, cType);
- if( nLocal==nPayload ){
- printf("payload-size: %lld\n", nPayload);
- }else{
- printf("payload-size: %lld (%lld local, %lld overflow)\n",
- nPayload, nLocal, nPayload-nLocal);
- }
- x += i;
- }else{
- nPayload = nLocal = 0;
- }
- end = x + nLocal;
- if( cType==5 || cType==13 ){
- i = decodeVarint(x, &rowid);
- printBytes(a, x, i);
- printf("rowid: %lld\n", rowid);
- x += i;
- }
- if( nLocal>0 ){
- i = decodeVarint(x, &nHdr);
- printBytes(a, x, i);
- printf("record-header-size: %d\n", (int)nHdr);
- j = i;
- nCol = 0;
- k = nHdr;
- while( x+j<=end && j<nHdr ){
- const char *zTypeName;
- int sz = 0;
- char zNm[30];
- i = decodeVarint(x+j, &iType);
- printBytes(a, x+j, i);
- printf("typecode[%d]: %d - ", nCol, (int)iType);
- switch( iType ){
- case 0: zTypeName = "NULL"; sz = 0; break;
- case 1: zTypeName = "int8"; sz = 1; break;
- case 2: zTypeName = "int16"; sz = 2; break;
- case 3: zTypeName = "int24"; sz = 3; break;
- case 4: zTypeName = "int32"; sz = 4; break;
- case 5: zTypeName = "int48"; sz = 6; break;
- case 6: zTypeName = "int64"; sz = 8; break;
- case 7: zTypeName = "double"; sz = 8; break;
- case 8: zTypeName = "zero"; sz = 0; break;
- case 9: zTypeName = "one"; sz = 0; break;
- case 10:
- case 11: zTypeName = "error"; sz = 0; break;
- default: {
- sz = (int)(iType-12)/2;
- sprintf(zNm, (iType&1)==0 ? "blob(%d)" : "text(%d)", sz);
- zTypeName = zNm;
- break;
- }
- }
- printf("%s\n", zTypeName);
- szCol[nCol] = sz;
- ofstCol[nCol] = (int)k;
- typeCol[nCol] = (int)iType;
- k += sz;
- nCol++;
- j += i;
- }
- for(i=0; i<nCol && ofstCol[i]+szCol[i]<=nLocal; i++){
- int s = ofstCol[i];
- i64 v;
- const unsigned char *pData;
- if( szCol[i]==0 ) continue;
- printBytes(a, x+s, szCol[i]);
- printf("data[%d]: ", i);
- pData = x+s;
- if( typeCol[i]<=7 ){
- v = (signed char)pData[0];
- for(k=1; k<szCol[i]; k++){
- v = (v<<8) + pData[k];
- }
- if( typeCol[i]==7 ){
- double r;
- memcpy(&r, &v, sizeof(r));
- printf("%#g\n", r);
- }else{
- printf("%lld\n", v);
- }
- }else{
- int ii, jj;
- char zConst[32];
- if( (typeCol[i]&1)==0 ){
- zConst[0] = 'x';
- zConst[1] = '\'';
- for(ii=2, jj=0; jj<szCol[i] && ii<24; jj++, ii+=2){
- sprintf(zConst+ii, "%02x", pData[jj]);
- }
- }else{
- zConst[0] = '\'';
- for(ii=1, jj=0; jj<szCol[i] && ii<24; jj++, ii++){
- zConst[ii] = ISPRINT(pData[jj]) ? pData[jj] : '.';
- }
- zConst[ii] = 0;
- }
- if( jj<szCol[i] ){
- memcpy(zConst+ii, "...'", 5);
- }else{
- memcpy(zConst+ii, "'", 2);
- }
- printf("%s\n", zConst);
- }
- j = ofstCol[i] + szCol[i];
- }
- }
- if( j<nLocal ){
- printBytes(a, x+j, 0);
- printf("... %lld bytes of content ...\n", nLocal-j);
- }
- if( nLocal<nPayload ){
- printBytes(a, x+nLocal, 4);
- printf("overflow-page: %d\n", decodeInt32(x+nLocal));
- }
-}
-
-
-/*
-** Decode a btree page
-*/
-static void decode_btree_page(
- unsigned char *a, /* Page content */
- int pgno, /* Page number */
- int hdrSize, /* Size of the page header. 0 or 100 */
- char *zArgs /* Flags to control formatting */
-){
- const char *zType = "unknown";
- int nCell;
- int i, j;
- int iCellPtr;
- int showCellContent = 0;
- int showMap = 0;
- int cellToDecode = -2;
- char *zMap = 0;
- switch( a[0] ){
- case 2: zType = "index interior node"; break;
- case 5: zType = "table interior node"; break;
- case 10: zType = "index leaf"; break;
- case 13: zType = "table leaf"; break;
- }
- while( zArgs[0] ){
- switch( zArgs[0] ){
- case 'c': showCellContent = 1; break;
- case 'm': showMap = 1; break;
- case 'd': {
- if( !ISDIGIT(zArgs[1]) ){
- cellToDecode = -1;
- }else{
- cellToDecode = 0;
- while( ISDIGIT(zArgs[1]) ){
- zArgs++;
- cellToDecode = cellToDecode*10 + zArgs[0] - '0';
- }
- }
- break;
- }
- }
- zArgs++;
- }
- nCell = a[3]*256 + a[4];
- iCellPtr = (a[0]==2 || a[0]==5) ? 12 : 8;
- if( cellToDecode>=nCell ){
- printf("Page %d has only %d cells\n", pgno, nCell);
- return;
- }
- printf("Header on btree page %d:\n", pgno);
- print_decode_line(a, 0, 1, zType);
- print_decode_line(a, 1, 2, "Offset to first freeblock");
- print_decode_line(a, 3, 2, "Number of cells on this page");
- print_decode_line(a, 5, 2, "Offset to cell content area");
- print_decode_line(a, 7, 1, "Fragmented byte count");
- if( a[0]==2 || a[0]==5 ){
- print_decode_line(a, 8, 4, "Right child");
- }
- if( cellToDecode==(-2) && nCell>0 ){
- printf(" key: lx=left-child n=payload-size r=rowid\n");
- }
- if( showMap ){
- zMap = sqlite3_malloc(g.pagesize);
- memset(zMap, '.', g.pagesize);
- memset(zMap, '1', hdrSize);
- memset(&zMap[hdrSize], 'H', iCellPtr);
- memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
- }
- for(i=0; i<nCell; i++){
- int cofst = iCellPtr + i*2;
- char *zDesc;
- i64 n;
-
- cofst = a[cofst]*256 + a[cofst+1];
- n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
- if( showMap ){
- char zBuf[30];
- memset(&zMap[cofst], '*', (size_t)n);
- zMap[cofst] = '[';
- zMap[cofst+n-1] = ']';
- sprintf(zBuf, "%d", i);
- j = (int)strlen(zBuf);
- if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
- }
- if( cellToDecode==(-2) ){
- printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
- }else if( cellToDecode==(-1) || cellToDecode==i ){
- decodeCell(a, pgno, i, hdrSize, cofst-hdrSize);
- }
- }
- if( showMap ){
- printf("Page map: (H=header P=cell-index 1=page-1-header .=free-space)\n");
- for(i=0; i<g.pagesize; i+=64){
- printf(" %03x: %.64s\n", i, &zMap[i]);
- }
- sqlite3_free(zMap);
- }
-}
-
-/*
-** Decode a freelist trunk page.
-*/
-static void decode_trunk_page(
- int pgno, /* The page number */
- int detail, /* Show leaf pages if true */
- int recursive /* Follow the trunk change if true */
-){
- int n, i;
- unsigned char *a;
- while( pgno>0 ){
- a = fileRead((pgno-1)*g.pagesize, g.pagesize);
- printf("Decode of freelist trunk page %d:\n", pgno);
- print_decode_line(a, 0, 4, "Next freelist trunk page");
- print_decode_line(a, 4, 4, "Number of entries on this page");
- if( detail ){
- n = (int)decodeInt32(&a[4]);
- for(i=0; i<n; i++){
- unsigned int x = decodeInt32(&a[8+4*i]);
- char zIdx[10];
- sprintf(zIdx, "[%d]", i);
- printf(" %5s %7u", zIdx, x);
- if( i%5==4 ) printf("\n");
- }
- if( i%5!=0 ) printf("\n");
- }
- if( !recursive ){
- pgno = 0;
- }else{
- pgno = (int)decodeInt32(&a[0]);
- }
- sqlite3_free(a);
- }
-}
-
-/*
-** A short text comment on the use of each page.
-*/
-static char **zPageUse;
-
-/*
-** Add a comment on the use of a page.
-*/
-static void page_usage_msg(int pgno, const char *zFormat, ...){
- va_list ap;
- char *zMsg;
-
- va_start(ap, zFormat);
- zMsg = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- if( pgno<=0 || pgno>g.mxPage ){
- printf("ERROR: page %d out of range 1..%d: %s\n",
- pgno, g.mxPage, zMsg);
- sqlite3_free(zMsg);
- return;
- }
- if( zPageUse[pgno]!=0 ){
- printf("ERROR: page %d used multiple times:\n", pgno);
- printf("ERROR: previous: %s\n", zPageUse[pgno]);
- printf("ERROR: current: %s\n", zMsg);
- sqlite3_free(zPageUse[pgno]);
- }
- zPageUse[pgno] = zMsg;
-}
-
-/*
-** Find overflow pages of a cell and describe their usage.
-*/
-static void page_usage_cell(
- unsigned char cType, /* Page type */
- unsigned char *a, /* Cell content */
- int pgno, /* page containing the cell */
- int cellno /* Index of the cell on the page */
-){
- int i;
- int n = 0;
- i64 nPayload;
- i64 rowid;
- i64 nLocal;
- i = 0;
- if( cType<=5 ){
- a += 4;
- n += 4;
- }
- if( cType!=5 ){
- i = decodeVarint(a, &nPayload);
- a += i;
- n += i;
- nLocal = localPayload(nPayload, cType);
- }else{
- nPayload = nLocal = 0;
- }
- if( cType==5 || cType==13 ){
- i = decodeVarint(a, &rowid);
- a += i;
- n += i;
- }
- if( nLocal<nPayload ){
- int ovfl = decodeInt32(a+nLocal);
- int cnt = 0;
- while( ovfl && (cnt++)<g.mxPage ){
- page_usage_msg(ovfl, "overflow %d from cell %d of page %d",
- cnt, cellno, pgno);
- a = fileRead((ovfl-1)*g.pagesize, 4);
- ovfl = decodeInt32(a);
- sqlite3_free(a);
- }
- }
-}
-
-
-/*
-** Describe the usages of a b-tree page
-*/
-static void page_usage_btree(
- int pgno, /* Page to describe */
- int parent, /* Parent of this page. 0 for root pages */
- int idx, /* Which child of the parent */
- const char *zName /* Name of the table */
-){
- unsigned char *a;
- const char *zType = "corrupt node";
- int nCell;
- int i;
- int hdr = pgno==1 ? 100 : 0;
-
- if( pgno<=0 || pgno>g.mxPage ) return;
- a = fileRead((pgno-1)*g.pagesize, g.pagesize);
- switch( a[hdr] ){
- case 2: zType = "interior node of index"; break;
- case 5: zType = "interior node of table"; break;
- case 10: zType = "leaf of index"; break;
- case 13: zType = "leaf of table"; break;
- }
- if( parent ){
- page_usage_msg(pgno, "%s [%s], child %d of page %d",
- zType, zName, idx, parent);
- }else{
- page_usage_msg(pgno, "root %s [%s]", zType, zName);
- }
- nCell = a[hdr+3]*256 + a[hdr+4];
- if( a[hdr]==2 || a[hdr]==5 ){
- int cellstart = hdr+12;
- unsigned int child;
- for(i=0; i<nCell; i++){
- int ofst;
-
- ofst = cellstart + i*2;
- ofst = a[ofst]*256 + a[ofst+1];
- child = decodeInt32(a+ofst);
- page_usage_btree(child, pgno, i, zName);
- }
- child = decodeInt32(a+cellstart-4);
- page_usage_btree(child, pgno, i, zName);
- }
- if( a[hdr]==2 || a[hdr]==10 || a[hdr]==13 ){
- int cellstart = hdr + 8 + 4*(a[hdr]<=5);
- for(i=0; i<nCell; i++){
- int ofst;
- ofst = cellstart + i*2;
- ofst = a[ofst]*256 + a[ofst+1];
- page_usage_cell(a[hdr], a+ofst, pgno, i);
- }
- }
- sqlite3_free(a);
-}
-
-/*
-** Determine page usage by the freelist
-*/
-static void page_usage_freelist(int pgno){
- unsigned char *a;
- int cnt = 0;
- int i;
- int n;
- int iNext;
- int parent = 1;
-
- while( pgno>0 && pgno<=g.mxPage && (cnt++)<g.mxPage ){
- page_usage_msg(pgno, "freelist trunk #%d child of %d", cnt, parent);
- a = fileRead((pgno-1)*g.pagesize, g.pagesize);
- iNext = decodeInt32(a);
- n = decodeInt32(a+4);
- for(i=0; i<n; i++){
- int child = decodeInt32(a + (i*4+8));
- page_usage_msg(child, "freelist leaf, child %d of trunk page %d",
- i, pgno);
- }
- sqlite3_free(a);
- parent = pgno;
- pgno = iNext;
- }
-}
-
-/*
-** Determine pages used as PTRMAP pages
-*/
-static void page_usage_ptrmap(unsigned char *a){
- if( a[55] ){
- int usable = g.pagesize - a[20];
- int pgno = 2;
- int perPage = usable/5;
- while( pgno<=g.mxPage ){
- page_usage_msg(pgno, "PTRMAP page covering %d..%d",
- pgno+1, pgno+perPage);
- pgno += perPage + 1;
- }
- }
-}
-
-/*
-** Try to figure out how every page in the database file is being used.
-*/
-static void page_usage_report(const char *zPrg, const char *zDbName){
- int i, j;
- int rc;
- sqlite3 *db;
- sqlite3_stmt *pStmt;
- unsigned char *a;
- char zQuery[200];
-
- /* Avoid the pathological case */
- if( g.mxPage<1 ){
- printf("empty database\n");
- return;
- }
-
- /* Open the database file */
- db = openDatabase(zPrg, zDbName);
-
- /* Set up global variables zPageUse[] and g.mxPage to record page
- ** usages */
- zPageUse = sqlite3_malloc( sizeof(zPageUse[0])*(g.mxPage+1) );
- if( zPageUse==0 ) out_of_memory();
- memset(zPageUse, 0, sizeof(zPageUse[0])*(g.mxPage+1));
-
- /* Discover the usage of each page */
- a = fileRead(0, 100);
- page_usage_freelist(decodeInt32(a+32));
- page_usage_ptrmap(a);
- sqlite3_free(a);
- page_usage_btree(1, 0, 0, "sqlite_master");
- sqlite3_exec(db, "PRAGMA writable_schema=ON", 0, 0, 0);
- for(j=0; j<2; j++){
- sqlite3_snprintf(sizeof(zQuery), zQuery,
- "SELECT type, name, rootpage FROM SQLITE_MASTER WHERE rootpage"
- " ORDER BY rowid %s", j?"DESC":"");
- rc = sqlite3_prepare_v2(db, zQuery, -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- int pgno = sqlite3_column_int(pStmt, 2);
- page_usage_btree(pgno, 0, 0, (const char*)sqlite3_column_text(pStmt,1));
- }
- }else{
- printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db));
- }
- rc = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) break;
- }
- sqlite3_close(db);
-
- /* Print the report and free memory used */
- for(i=1; i<=g.mxPage; i++){
- printf("%5d: %s\n", i, zPageUse[i] ? zPageUse[i] : "???");
- sqlite3_free(zPageUse[i]);
- }
- sqlite3_free(zPageUse);
- zPageUse = 0;
-}
-
-/*
-** Try to figure out how every page in the database file is being used.
-*/
-static void ptrmap_coverage_report(const char *zDbName){
- int pgno;
- unsigned char *aHdr;
- unsigned char *a;
- int usable;
- int perPage;
- int i;
-
- /* Avoid the pathological case */
- if( g.mxPage<1 ){
- printf("empty database\n");
- return;
- }
-
- /* Make sure PTRMAPs are used in this database */
- aHdr = fileRead(0, 100);
- if( aHdr[55]==0 ){
- printf("database does not use PTRMAP pages\n");
- return;
- }
- usable = g.pagesize - aHdr[20];
- perPage = usable/5;
- sqlite3_free(aHdr);
- printf("%5d: root of sqlite_master\n", 1);
- for(pgno=2; pgno<=g.mxPage; pgno += perPage+1){
- printf("%5d: PTRMAP page covering %d..%d\n", pgno,
- pgno+1, pgno+perPage);
- a = fileRead((pgno-1)*g.pagesize, usable);
- for(i=0; i+5<=usable && pgno+1+i/5<=g.mxPage; i+=5){
- const char *zType = "???";
- unsigned int iFrom = decodeInt32(&a[i+1]);
- switch( a[i] ){
- case 1: zType = "b-tree root page"; break;
- case 2: zType = "freelist page"; break;
- case 3: zType = "first page of overflow"; break;
- case 4: zType = "later page of overflow"; break;
- case 5: zType = "b-tree non-root page"; break;
- }
- printf("%5d: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
- }
- sqlite3_free(a);
- }
-}
-
-/*
-** Print a usage comment
-*/
-static void usage(const char *argv0){
- fprintf(stderr, "Usage %s ?--uri? FILENAME ?args...?\n\n", argv0);
- fprintf(stderr,
- "switches:\n"
- " --raw Read db file directly, bypassing SQLite VFS\n"
- "args:\n"
- " dbheader Show database header\n"
- " pgidx Index of how each page is used\n"
- " ptrmap Show all PTRMAP page content\n"
- " NNN..MMM Show hex of pages NNN through MMM\n"
- " NNN..end Show hex of pages NNN through end of file\n"
- " NNNb Decode btree page NNN\n"
- " NNNbc Decode btree page NNN and show content\n"
- " NNNbm Decode btree page NNN and show a layout map\n"
- " NNNbdCCC Decode cell CCC on btree page NNN\n"
- " NNNt Decode freelist trunk page NNN\n"
- " NNNtd Show leaf freelist pages on the decode\n"
- " NNNtr Recursively decode freelist starting at NNN\n"
- );
-}
-
-int main(int argc, char **argv){
- sqlite3_int64 szFile;
- unsigned char *zPgSz;
- const char *zPrg = argv[0]; /* Name of this executable */
- char **azArg = argv;
- int nArg = argc;
-
- /* Check for the "--uri" or "-uri" switch. */
- if( nArg>1 ){
- if( sqlite3_stricmp("-raw", azArg[1])==0
- || sqlite3_stricmp("--raw", azArg[1])==0
- ){
- g.bRaw = 1;
- azArg++;
- nArg--;
- }
- }
-
- if( nArg<2 ){
- usage(zPrg);
- exit(1);
- }
-
- fileOpen(zPrg, azArg[1]);
- szFile = fileGetsize();
-
- zPgSz = fileRead(16, 2);
- g.pagesize = zPgSz[0]*256 + zPgSz[1]*65536;
- if( g.pagesize==0 ) g.pagesize = 1024;
- sqlite3_free(zPgSz);
-
- printf("Pagesize: %d\n", g.pagesize);
- g.mxPage = (int)((szFile+g.pagesize-1)/g.pagesize);
-
- printf("Available pages: 1..%d\n", g.mxPage);
- if( nArg==2 ){
- int i;
- for(i=1; i<=g.mxPage; i++) print_page(i);
- }else{
- int i;
- for(i=2; i<nArg; i++){
- int iStart, iEnd;
- char *zLeft;
- if( strcmp(azArg[i], "dbheader")==0 ){
- print_db_header();
- continue;
- }
- if( strcmp(azArg[i], "pgidx")==0 ){
- page_usage_report(zPrg, azArg[1]);
- continue;
- }
- if( strcmp(azArg[i], "ptrmap")==0 ){
- ptrmap_coverage_report(azArg[1]);
- continue;
- }
- if( strcmp(azArg[i], "help")==0 ){
- usage(zPrg);
- continue;
- }
- if( !ISDIGIT(azArg[i][0]) ){
- fprintf(stderr, "%s: unknown option: [%s]\n", zPrg, azArg[i]);
- continue;
- }
- iStart = strtol(azArg[i], &zLeft, 0);
- if( zLeft && strcmp(zLeft,"..end")==0 ){
- iEnd = g.mxPage;
- }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
- iEnd = strtol(&zLeft[2], 0, 0);
- }else if( zLeft && zLeft[0]=='b' ){
- int ofst, nByte, hdrSize;
- unsigned char *a;
- if( iStart==1 ){
- ofst = hdrSize = 100;
- nByte = g.pagesize-100;
- }else{
- hdrSize = 0;
- ofst = (iStart-1)*g.pagesize;
- nByte = g.pagesize;
- }
- a = fileRead(ofst, nByte);
- decode_btree_page(a, iStart, hdrSize, &zLeft[1]);
- sqlite3_free(a);
- continue;
- }else if( zLeft && zLeft[0]=='t' ){
- int detail = 0;
- int recursive = 0;
- int j;
- for(j=1; zLeft[j]; j++){
- if( zLeft[j]=='r' ) recursive = 1;
- if( zLeft[j]=='d' ) detail = 1;
- }
- decode_trunk_page(iStart, detail, recursive);
- continue;
- }else{
- iEnd = iStart;
- }
- if( iStart<1 || iEnd<iStart || iEnd>g.mxPage ){
- fprintf(stderr,
- "Page argument should be LOWER?..UPPER?. Range 1 to %d\n",
- g.mxPage);
- exit(1);
- }
- while( iStart<=iEnd ){
- print_page(iStart);
- iStart++;
- }
- }
- }
- fileClose();
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showjournal.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/showjournal.c
deleted file mode 100644
index 51c89da499b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showjournal.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-** A utility for printing an SQLite database journal.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
-** state information
-*/
-static int pageSize = 1024;
-static int sectorSize = 512;
-static FILE *db = 0;
-static int fileSize = 0;
-static unsigned cksumNonce = 0;
-
-/* Report a memory allocation error */
-static void out_of_memory(void){
- fprintf(stderr,"Out of memory...\n");
- exit(1);
-}
-
-/*
-** Read N bytes of memory starting at iOfst into space obtained
-** from malloc().
-*/
-static unsigned char *read_content(int N, int iOfst){
- int got;
- unsigned char *pBuf = malloc(N);
- if( pBuf==0 ) out_of_memory();
- fseek(db, iOfst, SEEK_SET);
- got = (int)fread(pBuf, 1, N, db);
- if( got<0 ){
- fprintf(stderr, "I/O error reading %d bytes from %d\n", N, iOfst);
- memset(pBuf, 0, N);
- }else if( got<N ){
- fprintf(stderr, "Short read: got only %d of %d bytes from %d\n",
- got, N, iOfst);
- memset(&pBuf[got], 0, N-got);
- }
- return pBuf;
-}
-
-/* Print a line of decode output showing a 4-byte integer.
-*/
-static unsigned print_decode_line(
- const unsigned char *aData, /* Content being decoded */
- int ofst, int nByte, /* Start and size of decode */
- const char *zMsg /* Message to append */
-){
- int i, j;
- unsigned val = aData[ofst];
- char zBuf[100];
- sprintf(zBuf, " %05x: %02x", ofst, aData[ofst]);
- i = (int)strlen(zBuf);
- for(j=1; j<4; j++){
- if( j>=nByte ){
- sprintf(&zBuf[i], " ");
- }else{
- sprintf(&zBuf[i], " %02x", aData[ofst+j]);
- val = val*256 + aData[ofst+j];
- }
- i += (int)strlen(&zBuf[i]);
- }
- sprintf(&zBuf[i], " %10u", val);
- printf("%s %s\n", zBuf, zMsg);
- return val;
-}
-
-/*
-** Read and print a journal header. Store key information (page size, etc)
-** in global variables.
-*/
-static unsigned decode_journal_header(int iOfst){
- unsigned char *pHdr = read_content(64, iOfst);
- unsigned nPage;
- printf("Header at offset %d:\n", iOfst);
- print_decode_line(pHdr, 0, 4, "Header part 1 (3654616569)");
- print_decode_line(pHdr, 4, 4, "Header part 2 (547447767)");
- nPage =
- print_decode_line(pHdr, 8, 4, "page count");
- cksumNonce =
- print_decode_line(pHdr, 12, 4, "chksum nonce");
- print_decode_line(pHdr, 16, 4, "initial database size in pages");
- sectorSize =
- print_decode_line(pHdr, 20, 4, "sector size");
- pageSize =
- print_decode_line(pHdr, 24, 4, "page size");
- print_decode_line(pHdr, 28, 4, "zero");
- print_decode_line(pHdr, 32, 4, "zero");
- print_decode_line(pHdr, 36, 4, "zero");
- print_decode_line(pHdr, 40, 4, "zero");
- free(pHdr);
- return nPage;
-}
-
-static void print_page(int iOfst){
- unsigned char *aData;
- char zTitle[50];
- aData = read_content(pageSize+8, iOfst);
- sprintf(zTitle, "page number for page at offset %d", iOfst);
- print_decode_line(aData-iOfst, iOfst, 4, zTitle);
- free(aData);
-}
-
-int main(int argc, char **argv){
- int nPage, cnt;
- int iOfst;
- if( argc!=2 ){
- fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
- exit(1);
- }
- db = fopen(argv[1], "rb");
- if( db==0 ){
- fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
- exit(1);
- }
- fseek(db, 0, SEEK_END);
- fileSize = ftell(db);
- printf("journal file size: %d bytes\n", fileSize);
- fseek(db, 0, SEEK_SET);
- iOfst = 0;
- while( iOfst<fileSize ){
- cnt = nPage = (int)decode_journal_header(iOfst);
- if( cnt==0 ){
- cnt = (fileSize - sectorSize)/(pageSize+8);
- }
- iOfst += sectorSize;
- while( cnt && iOfst<fileSize ){
- print_page(iOfst);
- iOfst += pageSize+8;
- }
- iOfst = (iOfst/sectorSize + 1)*sectorSize;
- }
- fclose(db);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showlocks.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/showlocks.c
deleted file mode 100644
index 752c535cc37..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showlocks.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-** This file implements a simple command-line utility that shows all of the
-** Posix Advisory Locks on a file.
-**
-** Usage:
-**
-** showlocks FILENAME
-**
-** To compile: gcc -o showlocks showlocks.c
-*/
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* This utility only looks for locks in the first 2 billion bytes */
-#define MX_LCK 2147483647
-
-/*
-** Print all locks on the inode of "fd" that occur in between
-** lwr and upr, inclusive.
-*/
-static int showLocksInRange(int fd, off_t lwr, off_t upr){
- int cnt = 0;
- struct flock x;
-
- x.l_type = F_WRLCK;
- x.l_whence = SEEK_SET;
- x.l_start = lwr;
- x.l_len = upr-lwr;
- fcntl(fd, F_GETLK, &x);
- if( x.l_type==F_UNLCK ) return 0;
- printf("start: %-12d len: %-5d pid: %-5d type: %s\n",
- (int)x.l_start, (int)x.l_len,
- x.l_pid, x.l_type==F_WRLCK ? "WRLCK" : "RDLCK");
- cnt++;
- if( x.l_start>lwr ){
- cnt += showLocksInRange(fd, lwr, x.l_start-1);
- }
- if( x.l_start+x.l_len<upr ){
- cnt += showLocksInRange(fd, x.l_start+x.l_len+1, upr);
- }
- return cnt;
-}
-
-int main(int argc, char **argv){
- int fd;
- int cnt;
-
- if( argc!=2 ){
- fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
- return 1;
- }
- fd = open(argv[1], O_RDWR, 0);
- if( fd<0 ){
- fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]);
- return 1;
- }
- cnt = showLocksInRange(fd, 0, MX_LCK);
- if( cnt==0 ) printf("no locks\n");
- close(fd);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showshm.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/showshm.c
deleted file mode 100644
index 03e0fc460c5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showshm.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
-** A utility for printing content from the wal-index or "shm" file.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#define ISDIGIT(X) isdigit((unsigned char)(X))
-#define ISPRINT(X) isprint((unsigned char)(X))
-
-#if !defined(_MSC_VER)
-#include <unistd.h>
-#include <sys/types.h>
-#else
-#include <io.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-static int fd = -1; /* The open SHM file */
-
-/* Report an out-of-memory error and die.
-*/
-static void out_of_memory(void){
- fprintf(stderr,"Out of memory...\n");
- exit(1);
-}
-
-/*
-** Read content from the file.
-**
-** Space to hold the content is obtained from malloc() and needs to be
-** freed by the caller.
-*/
-static unsigned char *getContent(int ofst, int nByte){
- unsigned char *aData;
- aData = malloc(nByte);
- if( aData==0 ) out_of_memory();
- lseek(fd, ofst, SEEK_SET);
- read(fd, aData, nByte);
- return aData;
-}
-
-/*
-** Flags values
-*/
-#define FG_HEX 1 /* Show as hex */
-#define FG_NBO 2 /* Native byte order */
-#define FG_PGSZ 4 /* Show as page-size */
-
-/* Print a line of decode output showing a 4-byte integer.
-*/
-static void print_decode_line(
- unsigned char *aData, /* Content being decoded */
- int ofst, int nByte, /* Start and size of decode */
- unsigned flg, /* Display flags */
- const char *zMsg /* Message to append */
-){
- int i, j;
- int val = aData[ofst];
- char zBuf[100];
- sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
- i = (int)strlen(zBuf);
- for(j=1; j<4; j++){
- if( j>=nByte ){
- sprintf(&zBuf[i], " ");
- }else{
- sprintf(&zBuf[i], " %02x", aData[ofst+j]);
- val = val*256 + aData[ofst+j];
- }
- i += (int)strlen(&zBuf[i]);
- }
- if( nByte==8 ){
- for(j=4; j<8; j++){
- sprintf(&zBuf[i], " %02x", aData[ofst+j]);
- i += (int)strlen(&zBuf[i]);
- }
- }
- if( flg & FG_NBO ){
- assert( nByte==4 );
- memcpy(&val, aData+ofst, 4);
- }
- sprintf(&zBuf[i], " ");
- i += 12;
- if( flg & FG_PGSZ ){
- unsigned short sz;
- memcpy(&sz, aData+ofst, 2);
- sprintf(&zBuf[i], " %9d", sz==1 ? 65536 : sz);
- }else if( flg & FG_HEX ){
- sprintf(&zBuf[i], " 0x%08x", val);
- }else if( nByte<8 ){
- sprintf(&zBuf[i], " %9d", val);
- }
- printf("%s %s\n", zBuf, zMsg);
-}
-
-/*
-** Print an instance of the WalIndexHdr object. ix is either 0 or 1
-** to select which header to print.
-*/
-static void print_index_hdr(unsigned char *aData, int ix){
- int i;
- assert( ix==0 || ix==1 );
- i = ix ? 48 : 0;
- print_decode_line(aData, 0+i, 4, FG_NBO, "Wal-index version");
- print_decode_line(aData, 4+i, 4, 0, "unused padding");
- print_decode_line(aData, 8+i, 4, FG_NBO, "transaction counter");
- print_decode_line(aData,12+i, 1, 0, "1 when initialized");
- print_decode_line(aData,13+i, 1, 0, "true if WAL cksums are bigendian");
- print_decode_line(aData,14+i, 2, FG_PGSZ, "database page size");
- print_decode_line(aData,16+i, 4, FG_NBO, "mxFrame");
- print_decode_line(aData,20+i, 4, FG_NBO, "Size of database in pages");
- print_decode_line(aData,24+i, 8, 0, "Cksum of last frame in -wal");
- print_decode_line(aData,32+i, 8, 0, "Salt values from the -wal");
- print_decode_line(aData,40+i, 8, 0, "Cksum over all prior fields");
-}
-
-/*
-** Print the WalCkptInfo object
-*/
-static void print_ckpt_info(unsigned char *aData){
- const int i = 96;
- int j;
- print_decode_line(aData, 0+i, 4, FG_NBO, "nBackfill");
- for(j=0; j<5; j++){
- char zLabel[100];
- sprintf(zLabel, "aReadMark[%d]", j);
- print_decode_line(aData, 4*j+4+i, 4, FG_NBO, zLabel);
- }
- print_decode_line(aData,24+i, 8, 0, "aLock");
- print_decode_line(aData,32+i, 4, FG_NBO, "nBackfillAttempted");
- print_decode_line(aData,36+i, 4, FG_NBO, "notUsed0");
-}
-
-
-int main(int argc, char **argv){
- unsigned char *aData;
- if( argc<2 ){
- fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
- exit(1);
- }
- fd = open(argv[1], O_RDONLY);
- if( fd<0 ){
- fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
- exit(1);
- }
- aData = getContent(0, 136);
- print_index_hdr(aData, 0);
- print_index_hdr(aData, 1);
- print_ckpt_info(aData);
- free(aData);
- close(fd);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showstat4.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/showstat4.c
deleted file mode 100644
index b8a12ad63c6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showstat4.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-** This utility program decodes and displays the content of the
-** sqlite_stat4 table in the database file named on the command
-** line.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "sqlite3.h"
-
-#define ISPRINT(X) isprint((unsigned char)(X))
-
-typedef sqlite3_int64 i64; /* 64-bit signed integer type */
-
-
-/*
-** Convert the var-int format into i64. Return the number of bytes
-** in the var-int. Write the var-int value into *pVal.
-*/
-static int decodeVarint(const unsigned char *z, i64 *pVal){
- i64 v = 0;
- int i;
- for(i=0; i<8; i++){
- v = (v<<7) + (z[i]&0x7f);
- if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
- }
- v = (v<<8) + (z[i]&0xff);
- *pVal = v;
- return 9;
-}
-
-
-
-int main(int argc, char **argv){
- sqlite3 *db;
- sqlite3_stmt *pStmt;
- char *zIdx = 0;
- int rc, j, x, y, mxHdr;
- const unsigned char *aSample;
- int nSample;
- i64 iVal;
- const char *zSep;
- int iRow = 0;
-
- if( argc!=2 ){
- fprintf(stderr, "Usage: %s DATABASE-FILE\n", argv[0]);
- exit(1);
- }
- rc = sqlite3_open(argv[1], &db);
- if( rc!=SQLITE_OK || db==0 ){
- fprintf(stderr, "Cannot open database file [%s]\n", argv[1]);
- exit(1);
- }
- rc = sqlite3_prepare_v2(db,
- "SELECT tbl||'.'||idx, nEq, nLT, nDLt, sample "
- "FROM sqlite_stat4 ORDER BY 1", -1,
- &pStmt, 0);
- if( rc!=SQLITE_OK || pStmt==0 ){
- fprintf(stderr, "%s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( zIdx==0 || strcmp(zIdx, (const char*)sqlite3_column_text(pStmt,0))!=0 ){
- if( zIdx ) printf("\n**************************************"
- "**************\n\n");
- sqlite3_free(zIdx);
- zIdx = sqlite3_mprintf("%s", sqlite3_column_text(pStmt,0));
- iRow = 0;
- }
- printf("%s sample %d ------------------------------------\n", zIdx, ++iRow);
- printf(" nEq = %s\n", sqlite3_column_text(pStmt,1));
- printf(" nLt = %s\n", sqlite3_column_text(pStmt,2));
- printf(" nDLt = %s\n", sqlite3_column_text(pStmt,3));
- printf(" sample = x'");
- aSample = sqlite3_column_blob(pStmt,4);
- nSample = sqlite3_column_bytes(pStmt,4);
- for(j=0; j<nSample; j++) printf("%02x", aSample[j]);
- printf("'\n ");
- zSep = " ";
- x = decodeVarint(aSample, &iVal);
- if( iVal<x || iVal>nSample ){
- printf(" <error>\n");
- continue;
- }
- y = mxHdr = (int)iVal;
- while( x<mxHdr ){
- int sz;
- i64 v;
- x += decodeVarint(aSample+x, &iVal);
- if( x>mxHdr ) break;
- if( iVal<0 ) break;
- switch( iVal ){
- case 0: sz = 0; break;
- case 1: sz = 1; break;
- case 2: sz = 2; break;
- case 3: sz = 3; break;
- case 4: sz = 4; break;
- case 5: sz = 6; break;
- case 6: sz = 8; break;
- case 7: sz = 8; break;
- case 8: sz = 0; break;
- case 9: sz = 0; break;
- case 10:
- case 11: sz = 0; break;
- default: sz = (int)(iVal-12)/2; break;
- }
- if( y+sz>nSample ) break;
- if( iVal==0 ){
- printf("%sNULL", zSep);
- }else if( iVal==8 || iVal==9 ){
- printf("%s%d", zSep, ((int)iVal)-8);
- }else if( iVal<=7 ){
- v = (signed char)aSample[y];
- for(j=1; j<sz; j++){
- v = (v<<8) + aSample[y+j];
- }
- if( iVal==7 ){
- double r;
- char *z;
- memcpy(&r, &v, sizeof(r));
- z = sqlite3_mprintf("%s%!.15g", zSep, r);
- printf("%s", z);
- sqlite3_free(z);
- }else{
- printf("%s%lld", zSep, v);
- }
- }else if( (iVal&1)==0 ){
- printf("%sx'", zSep);
- for(j=0; j<sz; j++){
- printf("%02x", aSample[y+j]);
- }
- printf("'");
- }else{
- printf("%s'", zSep);
- for(j=0; j<sz; j++){
- char c = (char)aSample[y+j];
- if( ISPRINT(c) ){
- if( c=='\'' || c=='\\' ) putchar('\\');
- putchar(c);
- }else if( c=='\n' ){
- printf("\\n");
- }else if( c=='\t' ){
- printf("\\t");
- }else if( c=='\r' ){
- printf("\\r");
- }else{
- printf("\\%03o", c);
- }
- }
- printf("'");
- }
- zSep = ",";
- y += sz;
- }
- printf("\n");
- }
- sqlite3_free(zIdx);
- sqlite3_finalize(pStmt);
- sqlite3_close(db);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showwal.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/showwal.c
deleted file mode 100644
index b214a288ebc..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/showwal.c
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
-** A utility for printing content from a write-ahead log file.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#define ISDIGIT(X) isdigit((unsigned char)(X))
-#define ISPRINT(X) isprint((unsigned char)(X))
-
-#if !defined(_MSC_VER)
-#include <unistd.h>
-#include <sys/types.h>
-#else
-#include <io.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-
-static int pagesize = 1024; /* Size of a database page */
-static int fd = -1; /* File descriptor for reading the WAL file */
-static int mxFrame = 0; /* Last frame */
-static int perLine = 16; /* HEX elements to print per line */
-
-typedef long long int i64; /* Datatype for 64-bit integers */
-
-/* Information for computing the checksum */
-typedef struct Cksum Cksum;
-struct Cksum {
- int bSwap; /* True to do byte swapping on 32-bit words */
- unsigned s0, s1; /* Current checksum value */
-};
-
-/*
-** extract a 32-bit big-endian integer
-*/
-static unsigned int getInt32(const unsigned char *a){
- unsigned int x = (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
- return x;
-}
-
-/*
-** Swap bytes on a 32-bit unsigned integer
-*/
-static unsigned int swab32(unsigned int x){
- return (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)
- + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24);
-}
-
-/* Extend the checksum. Reinitialize the checksum if bInit is true.
-*/
-static void extendCksum(
- Cksum *pCksum,
- unsigned char *aData,
- unsigned int nByte,
- int bInit
-){
- unsigned int *a32;
- if( bInit ){
- int a = 0;
- *((char*)&a) = 1;
- if( a==1 ){
- /* Host is little-endian */
- pCksum->bSwap = getInt32(aData)!=0x377f0682;
- }else{
- /* Host is big-endian */
- pCksum->bSwap = getInt32(aData)!=0x377f0683;
- }
- pCksum->s0 = 0;
- pCksum->s1 = 0;
- }
- a32 = (unsigned int*)aData;
- while( nByte>0 ){
- unsigned int x0 = a32[0];
- unsigned int x1 = a32[1];
- if( pCksum->bSwap ){
- x0 = swab32(x0);
- x1 = swab32(x1);
- }
- pCksum->s0 += x0 + pCksum->s1;
- pCksum->s1 += x1 + pCksum->s0;
- nByte -= 8;
- a32 += 2;
- }
-}
-
-/*
-** Convert the var-int format into i64. Return the number of bytes
-** in the var-int. Write the var-int value into *pVal.
-*/
-static int decodeVarint(const unsigned char *z, i64 *pVal){
- i64 v = 0;
- int i;
- for(i=0; i<8; i++){
- v = (v<<7) + (z[i]&0x7f);
- if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
- }
- v = (v<<8) + (z[i]&0xff);
- *pVal = v;
- return 9;
-}
-
-/* Report an out-of-memory error and die.
-*/
-static void out_of_memory(void){
- fprintf(stderr,"Out of memory...\n");
- exit(1);
-}
-
-/*
-** Read content from the file.
-**
-** Space to hold the content is obtained from malloc() and needs to be
-** freed by the caller.
-*/
-static unsigned char *getContent(int ofst, int nByte){
- unsigned char *aData;
- aData = malloc(nByte);
- if( aData==0 ) out_of_memory();
- lseek(fd, ofst, SEEK_SET);
- read(fd, aData, nByte);
- return aData;
-}
-
-/*
-** Print a range of bytes as hex and as ascii.
-*/
-static void print_byte_range(
- int ofst, /* First byte in the range of bytes to print */
- int nByte, /* Number of bytes to print */
- unsigned char *aData, /* Content to print */
- int printOfst /* Add this amount to the index on the left column */
-){
- int i, j;
- const char *zOfstFmt;
-
- if( ((printOfst+nByte)&~0xfff)==0 ){
- zOfstFmt = " %03x: ";
- }else if( ((printOfst+nByte)&~0xffff)==0 ){
- zOfstFmt = " %04x: ";
- }else if( ((printOfst+nByte)&~0xfffff)==0 ){
- zOfstFmt = " %05x: ";
- }else if( ((printOfst+nByte)&~0xffffff)==0 ){
- zOfstFmt = " %06x: ";
- }else{
- zOfstFmt = " %08x: ";
- }
-
- for(i=0; i<nByte; i += perLine){
- fprintf(stdout, zOfstFmt, i+printOfst);
- for(j=0; j<perLine; j++){
- if( i+j>nByte ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%02x ", aData[i+j]);
- }
- }
- for(j=0; j<perLine; j++){
- if( i+j>nByte ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%c", ISPRINT(aData[i+j]) ? aData[i+j] : '.');
- }
- }
- fprintf(stdout,"\n");
- }
-}
-
-/* Print a line of decode output showing a 4-byte integer.
-*/
-static void print_decode_line(
- unsigned char *aData, /* Content being decoded */
- int ofst, int nByte, /* Start and size of decode */
- int asHex, /* If true, output value as hex */
- const char *zMsg /* Message to append */
-){
- int i, j;
- int val = aData[ofst];
- char zBuf[100];
- sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
- i = (int)strlen(zBuf);
- for(j=1; j<4; j++){
- if( j>=nByte ){
- sprintf(&zBuf[i], " ");
- }else{
- sprintf(&zBuf[i], " %02x", aData[ofst+j]);
- val = val*256 + aData[ofst+j];
- }
- i += (int)strlen(&zBuf[i]);
- }
- if( asHex ){
- sprintf(&zBuf[i], " 0x%08x", val);
- }else{
- sprintf(&zBuf[i], " %9d", val);
- }
- printf("%s %s\n", zBuf, zMsg);
-}
-
-/*
-** Print an entire page of content as hex
-*/
-static void print_frame(int iFrame){
- int iStart;
- unsigned char *aData;
- iStart = 32 + (iFrame-1)*(pagesize+24);
- fprintf(stdout, "Frame %d: (offsets 0x%x..0x%x)\n",
- iFrame, iStart, iStart+pagesize+24);
- aData = getContent(iStart, pagesize+24);
- print_decode_line(aData, 0, 4, 0, "Page number");
- print_decode_line(aData, 4, 4, 0, "DB size, or 0 for non-commit");
- print_decode_line(aData, 8, 4, 1, "Salt-1");
- print_decode_line(aData,12, 4, 1, "Salt-2");
- print_decode_line(aData,16, 4, 1, "Checksum-1");
- print_decode_line(aData,20, 4, 1, "Checksum-2");
- print_byte_range(iStart+24, pagesize, aData+24, 0);
- free(aData);
-}
-
-/*
-** Summarize a single frame on a single line.
-*/
-static void print_oneline_frame(int iFrame, Cksum *pCksum){
- int iStart;
- unsigned char *aData;
- unsigned int s0, s1;
- iStart = 32 + (iFrame-1)*(pagesize+24);
- aData = getContent(iStart, 24);
- extendCksum(pCksum, aData, 8, 0);
- extendCksum(pCksum, getContent(iStart+24, pagesize), pagesize, 0);
- s0 = getInt32(aData+16);
- s1 = getInt32(aData+20);
- fprintf(stdout, "Frame %4d: %6d %6d 0x%08x,%08x 0x%08x,%08x %s\n",
- iFrame,
- getInt32(aData),
- getInt32(aData+4),
- getInt32(aData+8),
- getInt32(aData+12),
- s0,
- s1,
- (s0==pCksum->s0 && s1==pCksum->s1) ? "" : "cksum-fail"
- );
-
- /* Reset the checksum so that a single frame checksum failure will not
- ** cause all subsequent frames to also show a failure. */
- pCksum->s0 = s0;
- pCksum->s1 = s1;
- free(aData);
-}
-
-/*
-** Decode the WAL header.
-*/
-static void print_wal_header(Cksum *pCksum){
- unsigned char *aData;
- aData = getContent(0, 32);
- if( pCksum ){
- extendCksum(pCksum, aData, 24, 1);
- printf("Checksum byte order: %s\n", pCksum->bSwap ? "swapped" : "native");
- }
- printf("WAL Header:\n");
- print_decode_line(aData, 0, 4,1,"Magic. 0x377f0682 (le) or 0x377f0683 (be)");
- print_decode_line(aData, 4, 4, 0, "File format");
- print_decode_line(aData, 8, 4, 0, "Database page size");
- print_decode_line(aData, 12,4, 0, "Checkpoint sequence number");
- print_decode_line(aData, 16,4, 1, "Salt-1");
- print_decode_line(aData, 20,4, 1, "Salt-2");
- print_decode_line(aData, 24,4, 1, "Checksum-1");
- print_decode_line(aData, 28,4, 1, "Checksum-2");
- if( pCksum ){
- if( pCksum->s0!=getInt32(aData+24) ){
- printf("**** cksum-1 mismatch: 0x%08x\n", pCksum->s0);
- }
- if( pCksum->s1!=getInt32(aData+28) ){
- printf("**** cksum-2 mismatch: 0x%08x\n", pCksum->s1);
- }
- }
- free(aData);
-}
-/*
-** Describe cell content.
-*/
-static i64 describeContent(
- unsigned char *a, /* Cell content */
- i64 nLocal, /* Bytes in a[] */
- char *zDesc /* Write description here */
-){
- int nDesc = 0;
- int n, j;
- i64 i, x, v;
- const unsigned char *pData;
- const unsigned char *pLimit;
- char sep = ' ';
-
- pLimit = &a[nLocal];
- n = decodeVarint(a, &x);
- pData = &a[x];
- a += n;
- i = x - n;
- while( i>0 && pData<=pLimit ){
- n = decodeVarint(a, &x);
- a += n;
- i -= n;
- nLocal -= n;
- zDesc[0] = sep;
- sep = ',';
- nDesc++;
- zDesc++;
- if( x==0 ){
- sprintf(zDesc, "*"); /* NULL is a "*" */
- }else if( x>=1 && x<=6 ){
- v = (signed char)pData[0];
- pData++;
- switch( x ){
- case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 4: v = (v<<8) + pData[0]; pData++;
- case 3: v = (v<<8) + pData[0]; pData++;
- case 2: v = (v<<8) + pData[0]; pData++;
- }
- sprintf(zDesc, "%lld", v);
- }else if( x==7 ){
- sprintf(zDesc, "real");
- pData += 8;
- }else if( x==8 ){
- sprintf(zDesc, "0");
- }else if( x==9 ){
- sprintf(zDesc, "1");
- }else if( x>=12 ){
- i64 size = (x-12)/2;
- if( (x&1)==0 ){
- sprintf(zDesc, "blob(%lld)", size);
- }else{
- sprintf(zDesc, "txt(%lld)", size);
- }
- pData += size;
- }
- j = (int)strlen(zDesc);
- zDesc += j;
- nDesc += j;
- }
- return nDesc;
-}
-
-/*
-** Compute the local payload size given the total payload size and
-** the page size.
-*/
-static i64 localPayload(i64 nPayload, char cType){
- i64 maxLocal;
- i64 minLocal;
- i64 surplus;
- i64 nLocal;
- if( cType==13 ){
- /* Table leaf */
- maxLocal = pagesize-35;
- minLocal = (pagesize-12)*32/255-23;
- }else{
- maxLocal = (pagesize-12)*64/255-23;
- minLocal = (pagesize-12)*32/255-23;
- }
- if( nPayload>maxLocal ){
- surplus = minLocal + (nPayload-minLocal)%(pagesize-4);
- if( surplus<=maxLocal ){
- nLocal = surplus;
- }else{
- nLocal = minLocal;
- }
- }else{
- nLocal = nPayload;
- }
- return nLocal;
-}
-
-/*
-** Create a description for a single cell.
-**
-** The return value is the local cell size.
-*/
-static i64 describeCell(
- unsigned char cType, /* Page type */
- unsigned char *a, /* Cell content */
- int showCellContent, /* Show cell content if true */
- char **pzDesc /* Store description here */
-){
- int i;
- i64 nDesc = 0;
- int n = 0;
- int leftChild;
- i64 nPayload;
- i64 rowid;
- i64 nLocal;
- static char zDesc[1000];
- i = 0;
- if( cType<=5 ){
- leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3];
- a += 4;
- n += 4;
- sprintf(zDesc, "lx: %d ", leftChild);
- nDesc = strlen(zDesc);
- }
- if( cType!=5 ){
- i = decodeVarint(a, &nPayload);
- a += i;
- n += i;
- sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
- nDesc += strlen(&zDesc[nDesc]);
- nLocal = localPayload(nPayload, cType);
- }else{
- nPayload = nLocal = 0;
- }
- if( cType==5 || cType==13 ){
- i = decodeVarint(a, &rowid);
- a += i;
- n += i;
- sprintf(&zDesc[nDesc], "r: %lld ", rowid);
- nDesc += strlen(&zDesc[nDesc]);
- }
- if( nLocal<nPayload ){
- int ovfl;
- unsigned char *b = &a[nLocal];
- ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3];
- sprintf(&zDesc[nDesc], "ov: %d ", ovfl);
- nDesc += strlen(&zDesc[nDesc]);
- n += 4;
- }
- if( showCellContent && cType!=5 ){
- nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
- }
- *pzDesc = zDesc;
- return nLocal+n;
-}
-
-/*
-** Decode a btree page
-*/
-static void decode_btree_page(
- unsigned char *a, /* Content of the btree page to be decoded */
- int pgno, /* Page number */
- int hdrSize, /* Size of the page1-header in bytes */
- const char *zArgs /* Flags to control formatting */
-){
- const char *zType = "unknown";
- int nCell;
- int i, j;
- int iCellPtr;
- int showCellContent = 0;
- int showMap = 0;
- char *zMap = 0;
- switch( a[0] ){
- case 2: zType = "index interior node"; break;
- case 5: zType = "table interior node"; break;
- case 10: zType = "index leaf"; break;
- case 13: zType = "table leaf"; break;
- }
- while( zArgs[0] ){
- switch( zArgs[0] ){
- case 'c': showCellContent = 1; break;
- case 'm': showMap = 1; break;
- }
- zArgs++;
- }
- printf("Decode of btree page %d:\n", pgno);
- print_decode_line(a, 0, 1, 0, zType);
- print_decode_line(a, 1, 2, 0, "Offset to first freeblock");
- print_decode_line(a, 3, 2, 0, "Number of cells on this page");
- nCell = a[3]*256 + a[4];
- print_decode_line(a, 5, 2, 0, "Offset to cell content area");
- print_decode_line(a, 7, 1, 0, "Fragmented byte count");
- if( a[0]==2 || a[0]==5 ){
- print_decode_line(a, 8, 4, 0, "Right child");
- iCellPtr = 12;
- }else{
- iCellPtr = 8;
- }
- if( nCell>0 ){
- printf(" key: lx=left-child n=payload-size r=rowid\n");
- }
- if( showMap ){
- zMap = malloc(pagesize);
- memset(zMap, '.', pagesize);
- memset(zMap, '1', hdrSize);
- memset(&zMap[hdrSize], 'H', iCellPtr);
- memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
- }
- for(i=0; i<nCell; i++){
- int cofst = iCellPtr + i*2;
- char *zDesc;
- i64 n;
-
- cofst = a[cofst]*256 + a[cofst+1];
- n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
- if( showMap ){
- char zBuf[30];
- memset(&zMap[cofst], '*', (size_t)n);
- zMap[cofst] = '[';
- zMap[cofst+n-1] = ']';
- sprintf(zBuf, "%d", i);
- j = (int)strlen(zBuf);
- if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
- }
- printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
- }
- if( showMap ){
- for(i=0; i<pagesize; i+=64){
- printf(" %03x: %.64s\n", i, &zMap[i]);
- }
- free(zMap);
- }
-}
-
-int main(int argc, char **argv){
- struct stat sbuf;
- unsigned char zPgSz[4];
- if( argc<2 ){
- fprintf(stderr,"Usage: %s FILENAME ?PAGE? ...\n", argv[0]);
- exit(1);
- }
- fd = open(argv[1], O_RDONLY);
- if( fd<0 ){
- fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
- exit(1);
- }
- zPgSz[0] = 0;
- zPgSz[1] = 0;
- lseek(fd, 8, SEEK_SET);
- read(fd, zPgSz, 4);
- pagesize = zPgSz[1]*65536 + zPgSz[2]*256 + zPgSz[3];
- if( pagesize==0 ) pagesize = 1024;
- printf("Pagesize: %d\n", pagesize);
- fstat(fd, &sbuf);
- if( sbuf.st_size<32 ){
- printf("file too small to be a WAL\n");
- return 0;
- }
- mxFrame = (sbuf.st_size - 32)/(pagesize + 24);
- printf("Available pages: 1..%d\n", mxFrame);
- if( argc==2 ){
- int i;
- Cksum x;
- print_wal_header(&x);
- for(i=1; i<=mxFrame; i++){
- print_oneline_frame(i, &x);
- }
- }else{
- int i;
- for(i=2; i<argc; i++){
- int iStart, iEnd;
- char *zLeft;
- if( strcmp(argv[i], "header")==0 ){
- print_wal_header(0);
- continue;
- }
- if( !ISDIGIT(argv[i][0]) ){
- fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]);
- continue;
- }
- iStart = strtol(argv[i], &zLeft, 0);
- if( zLeft && strcmp(zLeft,"..end")==0 ){
- iEnd = mxFrame;
- }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
- iEnd = strtol(&zLeft[2], 0, 0);
- }else if( zLeft && zLeft[0]=='b' ){
- int ofst, nByte, hdrSize;
- unsigned char *a;
- if( iStart==1 ){
- hdrSize = 100;
- ofst = hdrSize = 100;
- nByte = pagesize-100;
- }else{
- hdrSize = 0;
- ofst = (iStart-1)*pagesize;
- nByte = pagesize;
- }
- ofst = 32 + hdrSize + (iStart-1)*(pagesize+24) + 24;
- a = getContent(ofst, nByte);
- decode_btree_page(a, iStart, hdrSize, zLeft+1);
- free(a);
- continue;
-#if !defined(_MSC_VER)
- }else if( zLeft && strcmp(zLeft,"truncate")==0 ){
- /* Frame number followed by "truncate" truncates the WAL file
- ** after that frame */
- off_t newSize = 32 + iStart*(pagesize+24);
- truncate(argv[1], newSize);
- continue;
-#endif
- }else{
- iEnd = iStart;
- }
- if( iStart<1 || iEnd<iStart || iEnd>mxFrame ){
- fprintf(stderr,
- "Page argument should be LOWER?..UPPER?. Range 1 to %d\n",
- mxFrame);
- exit(1);
- }
- while( iStart<=iEnd ){
- print_frame(iStart);
- iStart++;
- }
- }
- }
- close(fd);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/soak1.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/soak1.tcl
deleted file mode 100644
index 846f905935c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/soak1.tcl
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Usage:
-#
-# tclsh soak1.tcl local-makefile.mk ?target? ?scenario?
-#
-# This generates many variations on local-makefile.mk (by modifing
-# the OPT = lines) and runs them will fulltest, one by one. The
-# constructed makefiles are named "soak1.mk".
-#
-# If ?target? is provided, that is the makefile target that is run.
-# The default is "fulltest"
-#
-# If ?scenario? is provided, it is the name of a single scenario to
-# be run. All other scenarios are skipped.
-#
-set localmake [lindex $argv 0]
-set target [lindex $argv 1]
-set scene [lindex $argv 2]
-if {$target==""} {set target fulltest}
-if {$scene==""} {set scene all}
-
-set in [open $localmake]
-set maketxt [read $in]
-close $in
-regsub -all {\\\n} $maketxt {} maketxt
-#set makefilename "soak1-[expr {int(rand()*1000000000)}].mk"
-set makefilename "soak1.mk"
-
-# Generate a makefile
-#
-proc generate_makefile {pattern} {
- global makefilename maketxt
- set out [open $makefilename w]
- set seen_opt 0
- foreach line [split $maketxt \n] {
- if {[regexp {^ *#? *OPTS[ =+]} $line]} {
- if {!$seen_opt} {
- puts $out "OPTS += -DSQLITE_NO_SYNC=1"
- foreach x $pattern {
- puts $out "OPTS += -D$x"
- }
- set seen_opt 1
- }
- } else {
- puts $out $line
- }
- }
- close $out
-}
-
-# Run a test
-#
-proc scenario {id title pattern} {
- global makefilename target scene
- if {$scene!="all" && $scene!=$id && $scene!=$title} return
- puts "**************** $title ***************"
- generate_makefile $pattern
- exec make -f $makefilename clean >@stdout 2>@stdout
- exec make -f $makefilename $target >@stdout 2>@stdout
-}
-
-###############################################################################
-# Add new scenarios here
-#
-scenario 0 {Default} {}
-scenario 1 {Debug} {
- SQLITE_DEBUG=1
- SQLITE_MEMDEBUG=1
-}
-scenario 2 {Everything} {
- SQLITE_DEBUG=1
- SQLITE_MEMDEBUG=1
- SQLITE_ENABLE_MEMORY_MANAGEMENT=1
- SQLITE_ENABLE_COLUMN_METADATA=1
- SQLITE_ENABLE_LOAD_EXTENSION=1 HAVE_DLOPEN=1
- SQLITE_ENABLE_MEMORY_MANAGEMENT=1
-}
-scenario 3 {Customer-1} {
- SQLITE_DEBUG=1 SQLITE_MEMDEBUG=1
- SQLITE_THREADSAFE=1 SQLITE_OS_UNIX=1
- SQLITE_DISABLE_LFS=1
- SQLITE_DEFAULT_AUTOVACUUM=1
- SQLITE_DEFAULT_PAGE_SIZE=1024
- SQLITE_MAX_PAGE_SIZE=4096
- SQLITE_DEFAULT_CACHE_SIZE=64
- SQLITE_DEFAULT_TEMP_CACHE_SIZE=32
- SQLITE_TEMP_STORE=3
- SQLITE_OMIT_PROGRESS_CALLBACK=1
- SQLITE_OMIT_LOAD_EXTENSION=1
- SQLITE_OMIT_VIRTUALTABLE=1
- SQLITE_ENABLE_IOTRACE=1
-}
-scenario 4 {Small-Cache} {
- SQLITE_DEBUG=1 SQLITE_MEMDEBUG=1
- SQLITE_THREADSAFE=1 SQLITE_OS_UNIX=1
- SQLITE_DEFAULT_AUTOVACUUM=1
- SQLITE_DEFAULT_PAGE_SIZE=1024
- SQLITE_MAX_PAGE_SIZE=2048
- SQLITE_DEFAULT_CACHE_SIZE=13
- SQLITE_DEFAULT_TEMP_CACHE_SIZE=11
- SQLITE_TEMP_STORE=1
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/spaceanal.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/spaceanal.tcl
deleted file mode 100644
index 3e08d3ffa74..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/spaceanal.tcl
+++ /dev/null
@@ -1,891 +0,0 @@
-# Run this TCL script using an SQLite-enabled TCL interpreter to get a report
-# on how much disk space is used by a particular data to actually store data
-# versus how much space is unused.
-#
-# The dbstat virtual table is required.
-#
-
-if {[catch {
-
-# Argument $tname is the name of a table within the database opened by
-# database handle [db]. Return true if it is a WITHOUT ROWID table, or
-# false otherwise.
-#
-proc is_without_rowid {tname} {
- set t [string map {' ''} $tname]
- db eval "PRAGMA index_list = '$t'" o {
- if {$o(origin) == "pk"} {
- set n $o(name)
- if {0==[db one { SELECT count(*) FROM sqlite_master WHERE name=$n }]} {
- return 1
- }
- }
- }
- return 0
-}
-
-# Read and run TCL commands from standard input. Used to implement
-# the --tclsh option.
-#
-proc tclsh {} {
- set line {}
- while {![eof stdin]} {
- if {$line!=""} {
- puts -nonewline "> "
- } else {
- puts -nonewline "% "
- }
- flush stdout
- append line [gets stdin]
- if {[info complete $line]} {
- if {[catch {uplevel #0 $line} result]} {
- puts stderr "Error: $result"
- } elseif {$result!=""} {
- puts $result
- }
- set line {}
- } else {
- append line \n
- }
- }
-}
-
-
-# Get the name of the database to analyze
-#
-proc usage {} {
- set argv0 [file rootname [file tail [info nameofexecutable]]]
- puts stderr "Usage: $argv0 ?--pageinfo? ?--stats? database-filename"
- puts stderr {
-Analyze the SQLite3 database file specified by the "database-filename"
-argument and output a report detailing size and storage efficiency
-information for the database and its constituent tables and indexes.
-
-Options:
-
- --pageinfo Show how each page of the database-file is used
-
- --stats Output SQL text that creates a new database containing
- statistics about the database that was analyzed
-
- --tclsh Run the built-in TCL interpreter interactively (for debugging)
-
- --version Show the version number of SQLite
-}
- exit 1
-}
-set file_to_analyze {}
-set flags(-pageinfo) 0
-set flags(-stats) 0
-set flags(-debug) 0
-append argv {}
-foreach arg $argv {
- if {[regexp {^-+pageinfo$} $arg]} {
- set flags(-pageinfo) 1
- } elseif {[regexp {^-+stats$} $arg]} {
- set flags(-stats) 1
- } elseif {[regexp {^-+debug$} $arg]} {
- set flags(-debug) 1
- } elseif {[regexp {^-+tclsh$} $arg]} {
- tclsh
- exit 0
- } elseif {[regexp {^-+version$} $arg]} {
- sqlite3 mem :memory:
- puts [mem one {SELECT sqlite_version()||' '||sqlite_source_id()}]
- mem close
- exit 0
- } elseif {[regexp {^-} $arg]} {
- puts stderr "Unknown option: $arg"
- usage
- } elseif {$file_to_analyze!=""} {
- usage
- } else {
- set file_to_analyze $arg
- }
-}
-if {$file_to_analyze==""} usage
-set root_filename $file_to_analyze
-regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename
-if {![file exists $root_filename]} {
- puts stderr "No such file: $root_filename"
- exit 1
-}
-if {![file readable $root_filename]} {
- puts stderr "File is not readable: $root_filename"
- exit 1
-}
-set true_file_size [file size $root_filename]
-if {$true_file_size<512} {
- puts stderr "Empty or malformed database: $root_filename"
- exit 1
-}
-
-# Compute the total file size assuming test_multiplexor is being used.
-# Assume that SQLITE_ENABLE_8_3_NAMES might be enabled
-#
-set extension [file extension $root_filename]
-set pattern $root_filename
-append pattern {[0-3][0-9][0-9]}
-foreach f [glob -nocomplain $pattern] {
- incr true_file_size [file size $f]
- set extension {}
-}
-if {[string length $extension]>=2 && [string length $extension]<=4} {
- set pattern [file rootname $root_filename]
- append pattern {.[0-3][0-9][0-9]}
- foreach f [glob -nocomplain $pattern] {
- incr true_file_size [file size $f]
- }
-}
-
-# Open the database
-#
-if {[catch {sqlite3 db $file_to_analyze -uri 1} msg]} {
- puts stderr "error trying to open $file_to_analyze: $msg"
- exit 1
-}
-if {$flags(-debug)} {
- proc dbtrace {txt} {puts $txt; flush stdout;}
- db trace ::dbtrace
-}
-
-# Make sure all required compile-time options are available
-#
-if {![db exists {SELECT 1 FROM pragma_compile_options
- WHERE compile_options='ENABLE_DBSTAT_VTAB'}]} {
- puts "The SQLite database engine linked with this application\
- lacks required capabilities. Recompile using the\
- -DSQLITE_ENABLE_DBSTAT_VTAB compile-time option to fix\
- this problem."
- exit 1
-}
-
-db eval {SELECT count(*) FROM sqlite_master}
-set pageSize [expr {wide([db one {PRAGMA page_size}])}]
-
-if {$flags(-pageinfo)} {
- db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
- db eval {SELECT name, path, pageno FROM temp.stat ORDER BY pageno} {
- puts "$pageno $name $path"
- }
- exit 0
-}
-if {$flags(-stats)} {
- db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
- puts "BEGIN;"
- puts "CREATE TABLE stats("
- puts " name STRING, /* Name of table or index */"
- puts " path INTEGER, /* Path to page from root */"
- puts " pageno INTEGER, /* Page number */"
- puts " pagetype STRING, /* 'internal', 'leaf' or 'overflow' */"
- puts " ncell INTEGER, /* Cells on page (0 for overflow) */"
- puts " payload INTEGER, /* Bytes of payload on this page */"
- puts " unused INTEGER, /* Bytes of unused space on this page */"
- puts " mx_payload INTEGER, /* Largest payload size of all cells */"
- puts " pgoffset INTEGER, /* Offset of page in file */"
- puts " pgsize INTEGER /* Size of the page */"
- puts ");"
- db eval {SELECT quote(name) || ',' ||
- quote(path) || ',' ||
- quote(pageno) || ',' ||
- quote(pagetype) || ',' ||
- quote(ncell) || ',' ||
- quote(payload) || ',' ||
- quote(unused) || ',' ||
- quote(mx_payload) || ',' ||
- quote(pgoffset) || ',' ||
- quote(pgsize) AS x FROM stat} {
- puts "INSERT INTO stats VALUES($x);"
- }
- puts "COMMIT;"
- exit 0
-}
-
-
-# In-memory database for collecting statistics. This script loops through
-# the tables and indices in the database being analyzed, adding a row for each
-# to an in-memory database (for which the schema is shown below). It then
-# queries the in-memory db to produce the space-analysis report.
-#
-sqlite3 mem :memory:
-if {$flags(-debug)} {
- proc dbtrace {txt} {puts $txt; flush stdout;}
- mem trace ::dbtrace
-}
-set tabledef {CREATE TABLE space_used(
- name clob, -- Name of a table or index in the database file
- tblname clob, -- Name of associated table
- is_index boolean, -- TRUE if it is an index, false for a table
- is_without_rowid boolean, -- TRUE if WITHOUT ROWID table
- nentry int, -- Number of entries in the BTree
- leaf_entries int, -- Number of leaf entries
- depth int, -- Depth of the b-tree
- payload int, -- Total amount of data stored in this table or index
- ovfl_payload int, -- Total amount of data stored on overflow pages
- ovfl_cnt int, -- Number of entries that use overflow
- mx_payload int, -- Maximum payload size
- int_pages int, -- Number of interior pages used
- leaf_pages int, -- Number of leaf pages used
- ovfl_pages int, -- Number of overflow pages used
- int_unused int, -- Number of unused bytes on interior pages
- leaf_unused int, -- Number of unused bytes on primary pages
- ovfl_unused int, -- Number of unused bytes on overflow pages
- gap_cnt int, -- Number of gaps in the page layout
- compressed_size int -- Total bytes stored on disk
-);}
-mem eval $tabledef
-
-# Create a temporary "dbstat" virtual table.
-#
-db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
-db eval {CREATE TEMP TABLE dbstat AS SELECT * FROM temp.stat
- ORDER BY name, path}
-db eval {DROP TABLE temp.stat}
-
-set isCompressed 0
-set compressOverhead 0
-set depth 0
-set sql { SELECT name, tbl_name FROM sqlite_master WHERE rootpage>0 }
-foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] {
-
- set is_index [expr {$name!=$tblname}]
- set is_without_rowid [is_without_rowid $name]
- db eval {
- SELECT
- sum(ncell) AS nentry,
- sum((pagetype=='leaf')*ncell) AS leaf_entries,
- sum(payload) AS payload,
- sum((pagetype=='overflow') * payload) AS ovfl_payload,
- sum(path LIKE '%+000000') AS ovfl_cnt,
- max(mx_payload) AS mx_payload,
- sum(pagetype=='internal') AS int_pages,
- sum(pagetype=='leaf') AS leaf_pages,
- sum(pagetype=='overflow') AS ovfl_pages,
- sum((pagetype=='internal') * unused) AS int_unused,
- sum((pagetype=='leaf') * unused) AS leaf_unused,
- sum((pagetype=='overflow') * unused) AS ovfl_unused,
- sum(pgsize) AS compressed_size,
- max((length(CASE WHEN path LIKE '%+%' THEN '' ELSE path END)+3)/4)
- AS depth
- FROM temp.dbstat WHERE name = $name
- } break
-
- set total_pages [expr {$leaf_pages+$int_pages+$ovfl_pages}]
- set storage [expr {$total_pages*$pageSize}]
- if {!$isCompressed && $storage>$compressed_size} {
- set isCompressed 1
- set compressOverhead 14
- }
-
- # Column 'gap_cnt' is set to the number of non-contiguous entries in the
- # list of pages visited if the b-tree structure is traversed in a top-down
- # fashion (each node visited before its child-tree is passed). Any overflow
- # chains present are traversed from start to finish before any child-tree
- # is.
- #
- set gap_cnt 0
- set prev 0
- db eval {
- SELECT pageno, pagetype FROM temp.dbstat
- WHERE name=$name
- ORDER BY pageno
- } {
- if {$prev>0 && $pagetype=="leaf" && $pageno!=$prev+1} {
- incr gap_cnt
- }
- set prev $pageno
- }
- mem eval {
- INSERT INTO space_used VALUES(
- $name,
- $tblname,
- $is_index,
- $is_without_rowid,
- $nentry,
- $leaf_entries,
- $depth,
- $payload,
- $ovfl_payload,
- $ovfl_cnt,
- $mx_payload,
- $int_pages,
- $leaf_pages,
- $ovfl_pages,
- $int_unused,
- $leaf_unused,
- $ovfl_unused,
- $gap_cnt,
- $compressed_size
- );
- }
-}
-
-proc integerify {real} {
- if {[string is double -strict $real]} {
- return [expr {wide($real)}]
- } else {
- return 0
- }
-}
-mem function int integerify
-
-# Quote a string for use in an SQL query. Examples:
-#
-# [quote {hello world}] == {'hello world'}
-# [quote {hello world's}] == {'hello world''s'}
-#
-proc quote {txt} {
- return [string map {' ''} $txt]
-}
-
-# Output a title line
-#
-proc titleline {title} {
- if {$title==""} {
- puts [string repeat * 79]
- } else {
- set len [string length $title]
- set stars [string repeat * [expr 79-$len-5]]
- puts "*** $title $stars"
- }
-}
-
-# Generate a single line of output in the statistics section of the
-# report.
-#
-proc statline {title value {extra {}}} {
- set len [string length $title]
- set dots [string repeat . [expr 50-$len]]
- set len [string length $value]
- set sp2 [string range { } $len end]
- if {$extra ne ""} {
- set extra " $extra"
- }
- puts "$title$dots $value$sp2$extra"
-}
-
-# Generate a formatted percentage value for $num/$denom
-#
-proc percent {num denom {of {}}} {
- if {$denom==0.0} {return ""}
- set v [expr {$num*100.0/$denom}]
- set of {}
- if {$v==100.0 || $v<0.001 || ($v>1.0 && $v<99.0)} {
- return [format {%5.1f%% %s} $v $of]
- } elseif {$v<0.1 || $v>99.9} {
- return [format {%7.3f%% %s} $v $of]
- } else {
- return [format {%6.2f%% %s} $v $of]
- }
-}
-
-proc divide {num denom} {
- if {$denom==0} {return 0.0}
- return [format %.2f [expr double($num)/double($denom)]]
-}
-
-# Generate a subreport that covers some subset of the database.
-# the $where clause determines which subset to analyze.
-#
-proc subreport {title where showFrag} {
- global pageSize file_pgcnt compressOverhead
-
- # Query the in-memory database for the sum of various statistics
- # for the subset of tables/indices identified by the WHERE clause in
- # $where. Note that even if the WHERE clause matches no rows, the
- # following query returns exactly one row (because it is an aggregate).
- #
- # The results of the query are stored directly by SQLite into local
- # variables (i.e. $nentry, $payload etc.).
- #
- mem eval "
- SELECT
- int(sum(
- CASE WHEN (is_without_rowid OR is_index) THEN nentry
- ELSE leaf_entries
- END
- )) AS nentry,
- int(sum(payload)) AS payload,
- int(sum(ovfl_payload)) AS ovfl_payload,
- max(mx_payload) AS mx_payload,
- int(sum(ovfl_cnt)) as ovfl_cnt,
- int(sum(leaf_pages)) AS leaf_pages,
- int(sum(int_pages)) AS int_pages,
- int(sum(ovfl_pages)) AS ovfl_pages,
- int(sum(leaf_unused)) AS leaf_unused,
- int(sum(int_unused)) AS int_unused,
- int(sum(ovfl_unused)) AS ovfl_unused,
- int(sum(gap_cnt)) AS gap_cnt,
- int(sum(compressed_size)) AS compressed_size,
- int(max(depth)) AS depth,
- count(*) AS cnt
- FROM space_used WHERE $where" {} {}
-
- # Output the sub-report title, nicely decorated with * characters.
- #
- puts ""
- titleline $title
- puts ""
-
- # Calculate statistics and store the results in TCL variables, as follows:
- #
- # total_pages: Database pages consumed.
- # total_pages_percent: Pages consumed as a percentage of the file.
- # storage: Bytes consumed.
- # payload_percent: Payload bytes used as a percentage of $storage.
- # total_unused: Unused bytes on pages.
- # avg_payload: Average payload per btree entry.
- # avg_fanout: Average fanout for internal pages.
- # avg_unused: Average unused bytes per btree entry.
- # avg_meta: Average metadata overhead per entry.
- # ovfl_cnt_percent: Percentage of btree entries that use overflow pages.
- #
- set total_pages [expr {$leaf_pages+$int_pages+$ovfl_pages}]
- set total_pages_percent [percent $total_pages $file_pgcnt]
- set storage [expr {$total_pages*$pageSize}]
- set payload_percent [percent $payload $storage {of storage consumed}]
- set total_unused [expr {$ovfl_unused+$int_unused+$leaf_unused}]
- set avg_payload [divide $payload $nentry]
- set avg_unused [divide $total_unused $nentry]
- set total_meta [expr {$storage - $payload - $total_unused}]
- set total_meta [expr {$total_meta + 4*($ovfl_pages - $ovfl_cnt)}]
- set meta_percent [percent $total_meta $storage {of metadata}]
- set avg_meta [divide $total_meta $nentry]
- if {$int_pages>0} {
- # TODO: Is this formula correct?
- set nTab [mem eval "
- SELECT count(*) FROM (
- SELECT DISTINCT tblname FROM space_used WHERE $where AND is_index=0
- )
- "]
- set avg_fanout [mem eval "
- SELECT (sum(leaf_pages+int_pages)-$nTab)/sum(int_pages) FROM space_used
- WHERE $where
- "]
- set avg_fanout [format %.2f $avg_fanout]
- }
- set ovfl_cnt_percent [percent $ovfl_cnt $nentry {of all entries}]
-
- # Print out the sub-report statistics.
- #
- statline {Percentage of total database} $total_pages_percent
- statline {Number of entries} $nentry
- statline {Bytes of storage consumed} $storage
- if {$compressed_size!=$storage} {
- set compressed_size [expr {$compressed_size+$compressOverhead*$total_pages}]
- set pct [expr {$compressed_size*100.0/$storage}]
- set pct [format {%5.1f%%} $pct]
- statline {Bytes used after compression} $compressed_size $pct
- }
- statline {Bytes of payload} $payload $payload_percent
- statline {Bytes of metadata} $total_meta $meta_percent
- if {$cnt==1} {statline {B-tree depth} $depth}
- statline {Average payload per entry} $avg_payload
- statline {Average unused bytes per entry} $avg_unused
- statline {Average metadata per entry} $avg_meta
- if {[info exists avg_fanout]} {
- statline {Average fanout} $avg_fanout
- }
- if {$showFrag && $total_pages>1} {
- set fragmentation [percent $gap_cnt [expr {$total_pages-1}]]
- statline {Non-sequential pages} $gap_cnt $fragmentation
- }
- statline {Maximum payload per entry} $mx_payload
- statline {Entries that use overflow} $ovfl_cnt $ovfl_cnt_percent
- if {$int_pages>0} {
- statline {Index pages used} $int_pages
- }
- statline {Primary pages used} $leaf_pages
- statline {Overflow pages used} $ovfl_pages
- statline {Total pages used} $total_pages
- if {$int_unused>0} {
- set int_unused_percent [
- percent $int_unused [expr {$int_pages*$pageSize}] {of index space}]
- statline "Unused bytes on index pages" $int_unused $int_unused_percent
- }
- statline "Unused bytes on primary pages" $leaf_unused [
- percent $leaf_unused [expr {$leaf_pages*$pageSize}] {of primary space}]
- statline "Unused bytes on overflow pages" $ovfl_unused [
- percent $ovfl_unused [expr {$ovfl_pages*$pageSize}] {of overflow space}]
- statline "Unused bytes on all pages" $total_unused [
- percent $total_unused $storage {of all space}]
- return 1
-}
-
-# Calculate the overhead in pages caused by auto-vacuum.
-#
-# This procedure calculates and returns the number of pages used by the
-# auto-vacuum 'pointer-map'. If the database does not support auto-vacuum,
-# then 0 is returned. The two arguments are the size of the database file in
-# pages and the page size used by the database (in bytes).
-proc autovacuum_overhead {filePages pageSize} {
-
- # Set $autovacuum to non-zero for databases that support auto-vacuum.
- set autovacuum [db one {PRAGMA auto_vacuum}]
-
- # If the database is not an auto-vacuum database or the file consists
- # of one page only then there is no overhead for auto-vacuum. Return zero.
- if {0==$autovacuum || $filePages==1} {
- return 0
- }
-
- # The number of entries on each pointer map page. The layout of the
- # database file is one pointer-map page, followed by $ptrsPerPage other
- # pages, followed by a pointer-map page etc. The first pointer-map page
- # is the second page of the file overall.
- set ptrsPerPage [expr double($pageSize/5)]
-
- # Return the number of pointer map pages in the database.
- return [expr wide(ceil( ($filePages-1.0)/($ptrsPerPage+1.0) ))]
-}
-
-
-# Calculate the summary statistics for the database and store the results
-# in TCL variables. They are output below. Variables are as follows:
-#
-# pageSize: Size of each page in bytes.
-# file_bytes: File size in bytes.
-# file_pgcnt: Number of pages in the file.
-# file_pgcnt2: Number of pages in the file (calculated).
-# av_pgcnt: Pages consumed by the auto-vacuum pointer-map.
-# av_percent: Percentage of the file consumed by auto-vacuum pointer-map.
-# inuse_pgcnt: Data pages in the file.
-# inuse_percent: Percentage of pages used to store data.
-# free_pgcnt: Free pages calculated as (<total pages> - <in-use pages>)
-# free_pgcnt2: Free pages in the file according to the file header.
-# free_percent: Percentage of file consumed by free pages (calculated).
-# free_percent2: Percentage of file consumed by free pages (header).
-# ntable: Number of tables in the db.
-# nindex: Number of indices in the db.
-# nautoindex: Number of indices created automatically.
-# nmanindex: Number of indices created manually.
-# user_payload: Number of bytes of payload in table btrees
-# (not including sqlite_master)
-# user_percent: $user_payload as a percentage of total file size.
-
-### The following, setting $file_bytes based on the actual size of the file
-### on disk, causes this tool to choke on zipvfs databases. So set it based
-### on the return of [PRAGMA page_count] instead.
-if 0 {
- set file_bytes [file size $file_to_analyze]
- set file_pgcnt [expr {$file_bytes/$pageSize}]
-}
-set file_pgcnt [db one {PRAGMA page_count}]
-set file_bytes [expr {$file_pgcnt * $pageSize}]
-
-set av_pgcnt [autovacuum_overhead $file_pgcnt $pageSize]
-set av_percent [percent $av_pgcnt $file_pgcnt]
-
-set sql {SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM space_used}
-set inuse_pgcnt [expr wide([mem eval $sql])]
-set inuse_percent [percent $inuse_pgcnt $file_pgcnt]
-
-set free_pgcnt [expr {$file_pgcnt-$inuse_pgcnt-$av_pgcnt}]
-set free_percent [percent $free_pgcnt $file_pgcnt]
-set free_pgcnt2 [db one {PRAGMA freelist_count}]
-set free_percent2 [percent $free_pgcnt2 $file_pgcnt]
-
-set file_pgcnt2 [expr {$inuse_pgcnt+$free_pgcnt2+$av_pgcnt}]
-
-set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}]
-set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}]
-set sql {SELECT count(*) FROM sqlite_master WHERE name LIKE 'sqlite_autoindex%'}
-set nautoindex [db eval $sql]
-set nmanindex [expr {$nindex-$nautoindex}]
-
-# set total_payload [mem eval "SELECT sum(payload) FROM space_used"]
-set user_payload [mem one {SELECT int(sum(payload)) FROM space_used
- WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}]
-set user_percent [percent $user_payload $file_bytes]
-
-# Output the summary statistics calculated above.
-#
-puts "/** Disk-Space Utilization Report For $root_filename"
-puts ""
-statline {Page size in bytes} $pageSize
-statline {Pages in the whole file (measured)} $file_pgcnt
-statline {Pages in the whole file (calculated)} $file_pgcnt2
-statline {Pages that store data} $inuse_pgcnt $inuse_percent
-statline {Pages on the freelist (per header)} $free_pgcnt2 $free_percent2
-statline {Pages on the freelist (calculated)} $free_pgcnt $free_percent
-statline {Pages of auto-vacuum overhead} $av_pgcnt $av_percent
-statline {Number of tables in the database} $ntable
-statline {Number of indices} $nindex
-statline {Number of defined indices} $nmanindex
-statline {Number of implied indices} $nautoindex
-if {$isCompressed} {
- statline {Size of uncompressed content in bytes} $file_bytes
- set efficiency [percent $true_file_size $file_bytes]
- statline {Size of compressed file on disk} $true_file_size $efficiency
-} else {
- statline {Size of the file in bytes} $file_bytes
-}
-statline {Bytes of user payload stored} $user_payload $user_percent
-
-# Output table rankings
-#
-puts ""
-titleline "Page counts for all tables with their indices"
-puts ""
-mem eval {SELECT tblname, count(*) AS cnt,
- int(sum(int_pages+leaf_pages+ovfl_pages)) AS size
- FROM space_used GROUP BY tblname ORDER BY size+0 DESC, tblname} {} {
- statline [string toupper $tblname] $size [percent $size $file_pgcnt]
-}
-puts ""
-titleline "Page counts for all tables and indices separately"
-puts ""
-mem eval {
- SELECT
- upper(name) AS nm,
- int(int_pages+leaf_pages+ovfl_pages) AS size
- FROM space_used
- ORDER BY size+0 DESC, name} {} {
- statline $nm $size [percent $size $file_pgcnt]
-}
-if {$isCompressed} {
- puts ""
- titleline "Bytes of disk space used after compression"
- puts ""
- set csum 0
- mem eval {SELECT tblname,
- int(sum(compressed_size)) +
- $compressOverhead*sum(int_pages+leaf_pages+ovfl_pages)
- AS csize
- FROM space_used GROUP BY tblname ORDER BY csize+0 DESC, tblname} {} {
- incr csum $csize
- statline [string toupper $tblname] $csize [percent $csize $true_file_size]
- }
- set overhead [expr {$true_file_size - $csum}]
- if {$overhead>0} {
- statline {Header and free space} $overhead [percent $overhead $true_file_size]
- }
-}
-
-# Output subreports
-#
-if {$nindex>0} {
- subreport {All tables and indices} 1 0
-}
-subreport {All tables} {NOT is_index} 0
-if {$nindex>0} {
- subreport {All indices} {is_index} 0
-}
-foreach tbl [mem eval {SELECT DISTINCT tblname name FROM space_used
- ORDER BY name}] {
- set qn [quote $tbl]
- set name [string toupper $tbl]
- set n [mem eval {SELECT count(*) FROM space_used WHERE tblname=$tbl}]
- if {$n>1} {
- set idxlist [mem eval "SELECT name FROM space_used
- WHERE tblname='$qn' AND is_index
- ORDER BY 1"]
- subreport "Table $name and all its indices" "tblname='$qn'" 0
- subreport "Table $name w/o any indices" "name='$qn'" 1
- if {[llength $idxlist]>1} {
- subreport "Indices of table $name" "tblname='$qn' AND is_index" 0
- }
- foreach idx $idxlist {
- set qidx [quote $idx]
- subreport "Index [string toupper $idx] of table $name" "name='$qidx'" 1
- }
- } else {
- subreport "Table $name" "name='$qn'" 1
- }
-}
-
-# Output instructions on what the numbers above mean.
-#
-puts ""
-titleline Definitions
-puts {
-Page size in bytes
-
- The number of bytes in a single page of the database file.
- Usually 1024.
-
-Number of pages in the whole file
-}
-puts " The number of $pageSize-byte pages that go into forming the complete
- database"
-puts {
-Pages that store data
-
- The number of pages that store data, either as primary B*Tree pages or
- as overflow pages. The number at the right is the data pages divided by
- the total number of pages in the file.
-
-Pages on the freelist
-
- The number of pages that are not currently in use but are reserved for
- future use. The percentage at the right is the number of freelist pages
- divided by the total number of pages in the file.
-
-Pages of auto-vacuum overhead
-
- The number of pages that store data used by the database to facilitate
- auto-vacuum. This is zero for databases that do not support auto-vacuum.
-
-Number of tables in the database
-
- The number of tables in the database, including the SQLITE_MASTER table
- used to store schema information.
-
-Number of indices
-
- The total number of indices in the database.
-
-Number of defined indices
-
- The number of indices created using an explicit CREATE INDEX statement.
-
-Number of implied indices
-
- The number of indices used to implement PRIMARY KEY or UNIQUE constraints
- on tables.
-
-Size of the file in bytes
-
- The total amount of disk space used by the entire database files.
-
-Bytes of user payload stored
-
- The total number of bytes of user payload stored in the database. The
- schema information in the SQLITE_MASTER table is not counted when
- computing this number. The percentage at the right shows the payload
- divided by the total file size.
-
-Percentage of total database
-
- The amount of the complete database file that is devoted to storing
- information described by this category.
-
-Number of entries
-
- The total number of B-Tree key/value pairs stored under this category.
-
-Bytes of storage consumed
-
- The total amount of disk space required to store all B-Tree entries
- under this category. The is the total number of pages used times
- the pages size.
-
-Bytes of payload
-
- The amount of payload stored under this category. Payload is the data
- part of table entries and the key part of index entries. The percentage
- at the right is the bytes of payload divided by the bytes of storage
- consumed.
-
-Bytes of metadata
-
- The amount of formatting and structural information stored in the
- table or index. Metadata includes the btree page header, the cell pointer
- array, the size field for each cell, the left child pointer or non-leaf
- cells, the overflow pointers for overflow cells, and the rowid value for
- rowid table cells. In other words, metadata is everything that is neither
- unused space nor content. The record header in the payload is counted as
- content, not metadata.
-
-Average payload per entry
-
- The average amount of payload on each entry. This is just the bytes of
- payload divided by the number of entries.
-
-Average unused bytes per entry
-
- The average amount of free space remaining on all pages under this
- category on a per-entry basis. This is the number of unused bytes on
- all pages divided by the number of entries.
-
-Non-sequential pages
-
- The number of pages in the table or index that are out of sequence.
- Many filesystems are optimized for sequential file access so a small
- number of non-sequential pages might result in faster queries,
- especially for larger database files that do not fit in the disk cache.
- Note that after running VACUUM, the root page of each table or index is
- at the beginning of the database file and all other pages are in a
- separate part of the database file, resulting in a single non-
- sequential page.
-
-Maximum payload per entry
-
- The largest payload size of any entry.
-
-Entries that use overflow
-
- The number of entries that user one or more overflow pages.
-
-Total pages used
-
- This is the number of pages used to hold all information in the current
- category. This is the sum of index, primary, and overflow pages.
-
-Index pages used
-
- This is the number of pages in a table B-tree that hold only key (rowid)
- information and no data.
-
-Primary pages used
-
- This is the number of B-tree pages that hold both key and data.
-
-Overflow pages used
-
- The total number of overflow pages used for this category.
-
-Unused bytes on index pages
-
- The total number of bytes of unused space on all index pages. The
- percentage at the right is the number of unused bytes divided by the
- total number of bytes on index pages.
-
-Unused bytes on primary pages
-
- The total number of bytes of unused space on all primary pages. The
- percentage at the right is the number of unused bytes divided by the
- total number of bytes on primary pages.
-
-Unused bytes on overflow pages
-
- The total number of bytes of unused space on all overflow pages. The
- percentage at the right is the number of unused bytes divided by the
- total number of bytes on overflow pages.
-
-Unused bytes on all pages
-
- The total number of bytes of unused space on all primary and overflow
- pages. The percentage at the right is the number of unused bytes
- divided by the total number of bytes.
-}
-
-# Output a dump of the in-memory database. This can be used for more
-# complex offline analysis.
-#
-titleline {}
-puts "The entire text of this report can be sourced into any SQL database"
-puts "engine for further analysis. All of the text above is an SQL comment."
-puts "The data used to generate this report follows:"
-puts "*/"
-puts "BEGIN;"
-puts $tabledef
-unset -nocomplain x
-mem eval {SELECT * FROM space_used} x {
- puts -nonewline "INSERT INTO space_used VALUES"
- set sep (
- foreach col $x(*) {
- set v $x($col)
- if {$v=="" || ![string is double $v]} {set v '[quote $v]'}
- puts -nonewline $sep$v
- set sep ,
- }
- puts ");"
-}
-puts "COMMIT;"
-
-} err]} {
- puts "ERROR: $err"
- puts $errorInfo
- exit 1
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speed-check.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/speed-check.sh
deleted file mode 100644
index 96025920d31..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speed-check.sh
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/bin/bash
-#
-# This is a template for a script used for day-to-day size and
-# performance monitoring of SQLite. Typical usage:
-#
-# sh run-speed-test.sh trunk # Baseline measurement of trunk
-# sh run-speed-test.sh x1 # Measure some experimental change
-# fossil test-diff --tk cout-trunk.txt cout-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
-# cout-$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
-SPEEDTEST_OPTS="--shrink-memory --reprepare --stats --heap 10000000 64"
-SIZE=5
-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
- ;;
- --reprepare)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --autovacuum)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --utf16be)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --stats)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --without-rowid)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --nomemstat)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
- ;;
- --temp)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --temp 6"
- ;;
- --legacy)
- doWal=0
- ;;
- --wal)
- doWal=1
- ;;
- --size)
- shift; SIZE=$1
- ;;
- --cachesize)
- shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --cachesize $1"
- ;;
- --explain)
- doExplain=1
- ;;
- --vdbeprofile)
- rm -f vdbe_profile.out
- CC_OPTS="$CC_OPTS -DVDBE_PROFILE"
- doCachegrind=0
- doVdbeProfile=1
- ;;
- --lean)
- CC_OPTS="$CC_OPTS $LEAN_OPTS"
- ;;
- --clang)
- CC=clang
- ;;
- --icc)
- CC=/home/drh/intel/bin/icc
- ;;
- --gcc7)
- CC=gcc-7
- ;;
- --heap)
- CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_MEMSYS5"
- shift;
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --heap $1 64"
- ;;
- --lookaside)
- shift;
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --lookaside $1 $2"
- shift;
- ;;
- --repeat)
- CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_RCACHE"
- shift;
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --repeat $1"
- ;;
- --mmap)
- shift;
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --mmap $1"
- ;;
- --rtree)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset rtree"
- CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_RTREE"
- ;;
- --orm)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset orm"
- ;;
- --cte)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset cte"
- ;;
- --fp)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset fp"
- ;;
- -*)
- CC_OPTS="$CC_OPTS $1"
- ;;
- *)
- BASELINE=$1
- ;;
- esac
- shift
-done
-if test $doWal -eq 1; then
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --journal wal"
-fi
-SPEEDTEST_OPTS="$SPEEDTEST_OPTS --size $SIZE"
-echo "NAME = $NAME" | tee summary-$NAME.txt
-echo "SPEEDTEST_OPTS = $SPEEDTEST_OPTS" | tee -a summary-$NAME.txt
-echo "CC_OPTS = $CC_OPTS" | tee -a summary-$NAME.txt
-rm -f cachegrind.out.* speedtest1 speedtest1.db sqlite3.o
-if test $doVdbeProfile -eq 1; then
- rm -f vdbe_profile.out
-fi
-$CC -g -Os -Wall -I. $CC_OPTS -c sqlite3.c
-size sqlite3.o | tee -a summary-$NAME.txt
-if test $doExplain -eq 1; then
- $CC -g -Os -Wall -I. $CC_OPTS \
- -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
- ./shell.c ./sqlite3.c -o sqlite3 -ldl -lpthread
-fi
-SRC=./speedtest1.c
-$CC -g -Os -Wall -I. $CC_OPTS $SRC ./sqlite3.o -o speedtest1 -ldl -lpthread
-ls -l speedtest1 | tee -a summary-$NAME.txt
-if test $doCachegrind -eq 1; then
- valgrind --tool=cachegrind ./speedtest1 speedtest1.db \
- $SPEEDTEST_OPTS 2>&1 | tee -a summary-$NAME.txt
-else
- ./speedtest1 speedtest1.db $SPEEDTEST_OPTS 2>&1 | tee -a summary-$NAME.txt
-fi
-size sqlite3.o | tee -a summary-$NAME.txt
-wc sqlite3.c
-if test $doCachegrind -eq 1; then
- cg_anno.tcl cachegrind.out.* >cout-$NAME.txt
- echo '*****************************************************' >>cout-$NAME.txt
- sed 's/^[0-9=-]\{9\}/==00000==/' summary-$NAME.txt >>cout-$NAME.txt
-fi
-if test $doExplain -eq 1; then
- ./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt
-fi
-if test $doVdbeProfile -eq 1; then
- tclsh ../sqlite/tool/vdbe_profile.tcl >vdbeprofile-$NAME.txt
- open vdbeprofile-$NAME.txt
-fi
-if test "$NAME" != "$BASELINE" -a $doVdbeProfile -ne 1 -a $doDiff -ne 0; then
- fossil test-diff --tk -c 20 cout-$BASELINE.txt cout-$NAME.txt
-fi
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest.tcl
deleted file mode 100644
index ef39dc5461d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest.tcl
+++ /dev/null
@@ -1,275 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Run this script using TCLSH to do a speed comparison between
-# various versions of SQLite and PostgreSQL and MySQL
-#
-
-# Run a test
-#
-set cnt 1
-proc runtest {title} {
- global cnt
- set sqlfile test$cnt.sql
- puts "<h2>Test $cnt: $title</h2>"
- incr cnt
- set fd [open $sqlfile r]
- set sql [string trim [read $fd [file size $sqlfile]]]
- close $fd
- set sx [split $sql \n]
- set n [llength $sx]
- if {$n>8} {
- set sql {}
- for {set i 0} {$i<3} {incr i} {append sql [lindex $sx $i]<br>\n}
- append sql "<i>... [expr {$n-6}] lines omitted</i><br>\n"
- for {set i [expr {$n-3}]} {$i<$n} {incr i} {
- append sql [lindex $sx $i]<br>\n
- }
- } else {
- regsub -all \n [string trim $sql] <br> sql
- }
- puts "<blockquote>"
- puts "$sql"
- puts "</blockquote><table border=0 cellpadding=0 cellspacing=0>"
- set format {<tr><td>%s</td><td align="right">&nbsp;&nbsp;&nbsp;%.3f</td></tr>}
- set delay 1000
-# exec sync; after $delay;
-# set t [time "exec psql drh <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format PostgreSQL: $t]
- exec sync; after $delay;
- set t [time "exec mysql -f drh <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format MySQL: $t]
-# set t [time "exec ./sqlite232 s232.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.3.2:} $t]
-# set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.4 (cache=100):} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite248 s2k.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4.8:} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite248 sns.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4.8 (nosync):} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite2412 s2kb.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4.12:} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite2412 snsb.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4.12 (nosync):} $t]
-# set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.4 (test):} $t]
- puts "</table>"
-}
-
-# Initialize the environment
-#
-expr srand(1)
-catch {exec /bin/sh -c {rm -f s*.db}}
-set fd [open clear.sql w]
-puts $fd {
- drop table t1;
- drop table t2;
-}
-close $fd
-catch {exec psql drh <clear.sql}
-catch {exec mysql drh <clear.sql}
-set fd [open 2kinit.sql w]
-puts $fd {
- PRAGMA default_cache_size=2000;
- PRAGMA default_synchronous=on;
-}
-close $fd
-exec ./sqlite248 s2k.db <2kinit.sql
-exec ./sqlite2412 s2kb.db <2kinit.sql
-set fd [open nosync-init.sql w]
-puts $fd {
- PRAGMA default_cache_size=2000;
- PRAGMA default_synchronous=off;
-}
-close $fd
-exec ./sqlite248 sns.db <nosync-init.sql
-exec ./sqlite2412 snsb.db <nosync-init.sql
-set ones {zero one two three four five six seven eight nine
- ten eleven twelve thirteen fourteen fifteen sixteen seventeen
- eighteen nineteen}
-set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
-proc number_name {n} {
- if {$n>=1000} {
- set txt "[number_name [expr {$n/1000}]] thousand"
- set n [expr {$n%1000}]
- } else {
- set txt {}
- }
- if {$n>=100} {
- append txt " [lindex $::ones [expr {$n/100}]] hundred"
- set n [expr {$n%100}]
- }
- if {$n>=20} {
- append txt " [lindex $::tens [expr {$n/10}]]"
- set n [expr {$n%10}]
- }
- if {$n>0} {
- append txt " [lindex $::ones $n]"
- }
- set txt [string trim $txt]
- if {$txt==""} {set txt zero}
- return $txt
-}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));"
-for {set i 1} {$i<=1000} {incr i} {
- set r [expr {int(rand()*100000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-close $fd
-runtest {1000 INSERTs}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-puts $fd "CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t2 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-
-set fd [open test$cnt.sql w]
-for {set i 0} {$i<100} {incr i} {
- set lwr [expr {$i*100}]
- set upr [expr {($i+10)*100}]
- puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;"
-}
-close $fd
-runtest {100 SELECTs without an index}
-
-
-
-set fd [open test$cnt.sql w]
-for {set i 1} {$i<=100} {incr i} {
- puts $fd "SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%[number_name $i]%';"
-}
-close $fd
-runtest {100 SELECTs on a string comparison}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {CREATE INDEX i2a ON t2(a);}
-puts $fd {CREATE INDEX i2b ON t2(b);}
-close $fd
-runtest {Creating an index}
-
-
-
-set fd [open test$cnt.sql w]
-for {set i 0} {$i<5000} {incr i} {
- set lwr [expr {$i*100}]
- set upr [expr {($i+1)*100}]
- puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;"
-}
-close $fd
-runtest {5000 SELECTs with an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 0} {$i<1000} {incr i} {
- set lwr [expr {$i*10}]
- set upr [expr {($i+1)*10}]
- puts $fd "UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr;"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {1000 UPDATEs without an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "UPDATE t2 SET b=$r WHERE a=$i;"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 UPDATEs with an index}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "UPDATE t2 SET c='[number_name $r]' WHERE a=$i;"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 text UPDATEs with an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-puts $fd "INSERT INTO t1 SELECT * FROM t2;"
-puts $fd "INSERT INTO t2 SELECT * FROM t1;"
-puts $fd "COMMIT;"
-close $fd
-runtest {INSERTs from a SELECT}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {DELETE FROM t2 WHERE c LIKE '%fifty%';}
-close $fd
-runtest {DELETE without an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {DELETE FROM t2 WHERE a>10 AND a<20000;}
-close $fd
-runtest {DELETE with an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {INSERT INTO t2 SELECT * FROM t1;}
-close $fd
-runtest {A big INSERT after a big DELETE}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {BEGIN;}
-puts $fd {DELETE FROM t1;}
-for {set i 1} {$i<=3000} {incr i} {
- set r [expr {int(rand()*100000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd {COMMIT;}
-close $fd
-runtest {A big DELETE followed by many small INSERTs}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {DROP TABLE t1;}
-puts $fd {DROP TABLE t2;}
-close $fd
-runtest {DROP TABLE}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest16.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest16.c
deleted file mode 100644
index 993cc192684..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest16.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-** Performance test for SQLite.
-**
-** This program reads ASCII text from a file named on the command-line.
-** It converts each SQL statement into UTF16 and submits it to SQLite
-** for evaluation. A new UTF16 database is created at the beginning of
-** the program. All statements are timed using the high-resolution timer
-** built into Intel-class processors.
-**
-** To compile this program, first compile the SQLite library separately
-** will full optimizations. For example:
-**
-** gcc -c -O6 -DSQLITE_THREADSAFE=0 sqlite3.c
-**
-** Then link against this program. But to do optimize this program
-** because that defeats the hi-res timer.
-**
-** gcc speedtest16.c sqlite3.o -ldl -I../src
-**
-** Then run this program with a single argument which is the name of
-** a file containing SQL script that you want to test:
-**
-** ./a.out database.db test.sql
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <unistd.h>
-#include "sqlite3.h"
-
-#define ISSPACE(X) isspace((unsigned char)(X))
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-#include "hwtime.h"
-
-/*
-** Convert a zero-terminated ASCII string into a zero-terminated
-** UTF-16le string. Memory to hold the returned string comes
-** from malloc() and should be freed by the caller.
-*/
-static void *asciiToUtf16le(const char *z){
- int n = strlen(z);
- char *z16;
- int i, j;
-
- z16 = malloc( n*2 + 2 );
- for(i=j=0; i<=n; i++){
- z16[j++] = z[i];
- z16[j++] = 0;
- }
- return (void*)z16;
-}
-
-/*
-** Timers
-*/
-static sqlite_uint64 prepTime = 0;
-static sqlite_uint64 runTime = 0;
-static sqlite_uint64 finalizeTime = 0;
-
-/*
-** Prepare and run a single statement of SQL.
-*/
-static void prepareAndRun(sqlite3 *db, const char *zSql){
- void *utf16;
- sqlite3_stmt *pStmt;
- const void *stmtTail;
- sqlite_uint64 iStart, iElapse;
- int rc;
-
- printf("****************************************************************\n");
- printf("SQL statement: [%s]\n", zSql);
- utf16 = asciiToUtf16le(zSql);
- iStart = sqlite3Hwtime();
- rc = sqlite3_prepare16_v2(db, utf16, -1, &pStmt, &stmtTail);
- iElapse = sqlite3Hwtime() - iStart;
- prepTime += iElapse;
- printf("sqlite3_prepare16_v2() returns %d in %llu cycles\n", rc, iElapse);
- if( rc==SQLITE_OK ){
- int nRow = 0;
- iStart = sqlite3Hwtime();
- while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; }
- iElapse = sqlite3Hwtime() - iStart;
- runTime += iElapse;
- printf("sqlite3_step() returns %d after %d rows in %llu cycles\n",
- rc, nRow, iElapse);
- iStart = sqlite3Hwtime();
- rc = sqlite3_finalize(pStmt);
- iElapse = sqlite3Hwtime() - iStart;
- finalizeTime += iElapse;
- printf("sqlite3_finalize() returns %d in %llu cycles\n", rc, iElapse);
- }
- free(utf16);
-}
-
-int main(int argc, char **argv){
- void *utf16;
- sqlite3 *db;
- int rc;
- int nSql;
- char *zSql;
- int i, j;
- FILE *in;
- sqlite_uint64 iStart, iElapse;
- sqlite_uint64 iSetup = 0;
- int nStmt = 0;
- int nByte = 0;
-
- if( argc!=3 ){
- fprintf(stderr, "Usage: %s FILENAME SQL-SCRIPT\n"
- "Runs SQL-SCRIPT as UTF16 against a UTF16 database\n",
- argv[0]);
- exit(1);
- }
- in = fopen(argv[2], "r");
- fseek(in, 0L, SEEK_END);
- nSql = ftell(in);
- zSql = malloc( nSql+1 );
- fseek(in, 0L, SEEK_SET);
- nSql = fread(zSql, 1, nSql, in);
- zSql[nSql] = 0;
-
- printf("SQLite version: %d\n", sqlite3_libversion_number());
- unlink(argv[1]);
- utf16 = asciiToUtf16le(argv[1]);
- iStart = sqlite3Hwtime();
- rc = sqlite3_open16(utf16, &db);
- iElapse = sqlite3Hwtime() - iStart;
- iSetup = iElapse;
- printf("sqlite3_open16() returns %d in %llu cycles\n", rc, iElapse);
- free(utf16);
- for(i=j=0; j<nSql; j++){
- if( zSql[j]==';' ){
- int isComplete;
- char c = zSql[j+1];
- zSql[j+1] = 0;
- isComplete = sqlite3_complete(&zSql[i]);
- zSql[j+1] = c;
- if( isComplete ){
- zSql[j] = 0;
- while( i<j && ISSPACE(zSql[i]) ){ i++; }
- if( i<j ){
- nStmt++;
- nByte += j-i;
- prepareAndRun(db, &zSql[i]);
- }
- zSql[j] = ';';
- i = j+1;
- }
- }
- }
- iStart = sqlite3Hwtime();
- sqlite3_close(db);
- iElapse = sqlite3Hwtime() - iStart;
- iSetup += iElapse;
- printf("sqlite3_close() returns in %llu cycles\n", iElapse);
- printf("\n");
- printf("Statements run: %15d\n", nStmt);
- printf("Bytes of SQL text: %15d\n", nByte);
- printf("Total prepare time: %15llu cycles\n", prepTime);
- printf("Total run time: %15llu cycles\n", runTime);
- printf("Total finalize time: %15llu cycles\n", finalizeTime);
- printf("Open/Close time: %15llu cycles\n", iSetup);
- printf("Total Time: %15llu cycles\n",
- prepTime + runTime + finalizeTime + iSetup);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest2.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest2.tcl
deleted file mode 100644
index 4fd632d4c7c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest2.tcl
+++ /dev/null
@@ -1,207 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Run this script using TCLSH to do a speed comparison between
-# various versions of SQLite and PostgreSQL and MySQL
-#
-
-# Run a test
-#
-set cnt 1
-proc runtest {title} {
- global cnt
- set sqlfile test$cnt.sql
- puts "<h2>Test $cnt: $title</h2>"
- incr cnt
- set fd [open $sqlfile r]
- set sql [string trim [read $fd [file size $sqlfile]]]
- close $fd
- set sx [split $sql \n]
- set n [llength $sx]
- if {$n>8} {
- set sql {}
- for {set i 0} {$i<3} {incr i} {append sql [lindex $sx $i]<br>\n}
- append sql "<i>... [expr {$n-6}] lines omitted</i><br>\n"
- for {set i [expr {$n-3}]} {$i<$n} {incr i} {
- append sql [lindex $sx $i]<br>\n
- }
- } else {
- regsub -all \n [string trim $sql] <br> sql
- }
- puts "<blockquote>"
- puts "$sql"
- puts "</blockquote><table border=0 cellpadding=0 cellspacing=0>"
- set format {<tr><td>%s</td><td align="right">&nbsp;&nbsp;&nbsp;%.3f</td></tr>}
- set delay 1000
- exec sync; after $delay;
- set t [time "exec psql drh <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format PostgreSQL: $t]
- exec sync; after $delay;
- set t [time "exec mysql -f drh <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format MySQL: $t]
-# set t [time "exec ./sqlite232 s232.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.3.2:} $t]
-# set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.4 (cache=100):} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite240 s2k.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4:} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite240 sns.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4 (nosync):} $t]
-# set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.4 (test):} $t]
- puts "</table>"
-}
-
-# Initialize the environment
-#
-expr srand(1)
-catch {exec /bin/sh -c {rm -f s*.db}}
-set fd [open clear.sql w]
-puts $fd {
- drop table t1;
- drop table t2;
-}
-close $fd
-catch {exec psql drh <clear.sql}
-catch {exec mysql drh <clear.sql}
-set fd [open 2kinit.sql w]
-puts $fd {
- PRAGMA default_cache_size=2000;
- PRAGMA default_synchronous=on;
-}
-close $fd
-exec ./sqlite240 s2k.db <2kinit.sql
-exec ./sqlite-t1 st1.db <2kinit.sql
-set fd [open nosync-init.sql w]
-puts $fd {
- PRAGMA default_cache_size=2000;
- PRAGMA default_synchronous=off;
-}
-close $fd
-exec ./sqlite240 sns.db <nosync-init.sql
-set ones {zero one two three four five six seven eight nine
- ten eleven twelve thirteen fourteen fifteen sixteen seventeen
- eighteen nineteen}
-set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
-proc number_name {n} {
- if {$n>=1000} {
- set txt "[number_name [expr {$n/1000}]] thousand"
- set n [expr {$n%1000}]
- } else {
- set txt {}
- }
- if {$n>=100} {
- append txt " [lindex $::ones [expr {$n/100}]] hundred"
- set n [expr {$n%100}]
- }
- if {$n>=20} {
- append txt " [lindex $::tens [expr {$n/10}]]"
- set n [expr {$n%10}]
- }
- if {$n>0} {
- append txt " [lindex $::ones $n]"
- }
- set txt [string trim $txt]
- if {$txt==""} {set txt zero}
- return $txt
-}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd {DROP TABLE t1;}
-close $fd
-runtest {DROP TABLE}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest8.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest8.c
deleted file mode 100644
index 051fc898196..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest8.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
-** Performance test for SQLite.
-**
-** This program reads ASCII text from a file named on the command-line
-** and submits that text to SQLite for evaluation. A new database
-** is created at the beginning of the program. All statements are
-** timed using the high-resolution timer built into Intel-class processors.
-**
-** To compile this program, first compile the SQLite library separately
-** will full optimizations. For example:
-**
-** gcc -c -O6 -DSQLITE_THREADSAFE=0 sqlite3.c
-**
-** Then link against this program. But to do optimize this program
-** because that defeats the hi-res timer.
-**
-** gcc speedtest8.c sqlite3.o -ldl -I../src
-**
-** Then run this program with a single argument which is the name of
-** a file containing SQL script that you want to test:
-**
-** ./a.out test.db test.sql
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <time.h>
-
-#if defined(_MSC_VER)
-#include <windows.h>
-#else
-#include <unistd.h>
-#include <sys/times.h>
-#include <sched.h>
-#endif
-
-#include "sqlite3.h"
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-#include "hwtime.h"
-
-/*
-** Timers
-*/
-static sqlite_uint64 prepTime = 0;
-static sqlite_uint64 runTime = 0;
-static sqlite_uint64 finalizeTime = 0;
-
-/*
-** Prepare and run a single statement of SQL.
-*/
-static void prepareAndRun(sqlite3 *db, const char *zSql, int bQuiet){
- sqlite3_stmt *pStmt;
- const char *stmtTail;
- sqlite_uint64 iStart, iElapse;
- int rc;
-
- if (!bQuiet){
- printf("***************************************************************\n");
- }
- if (!bQuiet) printf("SQL statement: [%s]\n", zSql);
- iStart = sqlite3Hwtime();
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail);
- iElapse = sqlite3Hwtime() - iStart;
- prepTime += iElapse;
- if (!bQuiet){
- printf("sqlite3_prepare_v2() returns %d in %llu cycles\n", rc, iElapse);
- }
- if( rc==SQLITE_OK ){
- int nRow = 0;
- iStart = sqlite3Hwtime();
- while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; }
- iElapse = sqlite3Hwtime() - iStart;
- runTime += iElapse;
- if (!bQuiet){
- printf("sqlite3_step() returns %d after %d rows in %llu cycles\n",
- rc, nRow, iElapse);
- }
- iStart = sqlite3Hwtime();
- rc = sqlite3_finalize(pStmt);
- iElapse = sqlite3Hwtime() - iStart;
- finalizeTime += iElapse;
- if (!bQuiet){
- printf("sqlite3_finalize() returns %d in %llu cycles\n", rc, iElapse);
- }
- }
-}
-
-int main(int argc, char **argv){
- sqlite3 *db;
- int rc;
- int nSql;
- char *zSql;
- int i, j;
- FILE *in;
- sqlite_uint64 iStart, iElapse;
- sqlite_uint64 iSetup = 0;
- int nStmt = 0;
- int nByte = 0;
- const char *zArgv0 = argv[0];
- int bQuiet = 0;
-#if !defined(_MSC_VER)
- struct tms tmsStart, tmsEnd;
- clock_t clkStart, clkEnd;
-#endif
-
-#ifdef HAVE_OSINST
- extern sqlite3_vfs *sqlite3_instvfs_binarylog(char *, char *, char *);
- extern void sqlite3_instvfs_destroy(sqlite3_vfs *);
- sqlite3_vfs *pVfs = 0;
-#endif
-
- while (argc>3)
- {
-#ifdef HAVE_OSINST
- if( argc>4 && (strcmp(argv[1], "-log")==0) ){
- pVfs = sqlite3_instvfs_binarylog("oslog", 0, argv[2]);
- sqlite3_vfs_register(pVfs, 1);
- argv += 2;
- argc -= 2;
- continue;
- }
-#endif
-
- /*
- ** Increasing the priority slightly above normal can help with
- ** repeatability of testing. Note that with Cygwin, -5 equates
- ** to "High", +5 equates to "Low", and anything in between
- ** equates to "Normal".
- */
- if( argc>4 && (strcmp(argv[1], "-priority")==0) ){
-#if defined(_MSC_VER)
- int new_priority = atoi(argv[2]);
- if(!SetPriorityClass(GetCurrentProcess(),
- (new_priority<=-5) ? HIGH_PRIORITY_CLASS :
- (new_priority<=0) ? ABOVE_NORMAL_PRIORITY_CLASS :
- (new_priority==0) ? NORMAL_PRIORITY_CLASS :
- (new_priority<5) ? BELOW_NORMAL_PRIORITY_CLASS :
- IDLE_PRIORITY_CLASS)){
- printf ("error setting priority\n");
- exit(2);
- }
-#else
- struct sched_param myParam;
- sched_getparam(0, &myParam);
- printf ("Current process priority is %d.\n", (int)myParam.sched_priority);
- myParam.sched_priority = atoi(argv[2]);
- printf ("Setting process priority to %d.\n", (int)myParam.sched_priority);
- if (sched_setparam (0, &myParam) != 0){
- printf ("error setting priority\n");
- exit(2);
- }
-#endif
- argv += 2;
- argc -= 2;
- continue;
- }
-
- if( argc>3 && strcmp(argv[1], "-quiet")==0 ){
- bQuiet = -1;
- argv++;
- argc--;
- continue;
- }
-
- break;
- }
-
- if( argc!=3 ){
- fprintf(stderr, "Usage: %s [options] FILENAME SQL-SCRIPT\n"
- "Runs SQL-SCRIPT against a UTF8 database\n"
- "\toptions:\n"
-#ifdef HAVE_OSINST
- "\t-log <log>\n"
-#endif
- "\t-priority <value> : set priority of task\n"
- "\t-quiet : only display summary results\n",
- zArgv0);
- exit(1);
- }
-
- in = fopen(argv[2], "r");
- fseek(in, 0L, SEEK_END);
- nSql = ftell(in);
- zSql = malloc( nSql+1 );
- fseek(in, 0L, SEEK_SET);
- nSql = fread(zSql, 1, nSql, in);
- zSql[nSql] = 0;
-
- printf("SQLite version: %d\n", sqlite3_libversion_number());
- unlink(argv[1]);
-#if !defined(_MSC_VER)
- clkStart = times(&tmsStart);
-#endif
- iStart = sqlite3Hwtime();
- rc = sqlite3_open(argv[1], &db);
- iElapse = sqlite3Hwtime() - iStart;
- iSetup = iElapse;
- if (!bQuiet) printf("sqlite3_open() returns %d in %llu cycles\n", rc, iElapse);
- for(i=j=0; j<nSql; j++){
- if( zSql[j]==';' ){
- int isComplete;
- char c = zSql[j+1];
- zSql[j+1] = 0;
- isComplete = sqlite3_complete(&zSql[i]);
- zSql[j+1] = c;
- if( isComplete ){
- zSql[j] = 0;
- while( i<j && isspace(zSql[i]) ){ i++; }
- if( i<j ){
- int n = j - i;
- if( n>=6 && memcmp(&zSql[i], ".crash",6)==0 ) exit(1);
- nStmt++;
- nByte += n;
- prepareAndRun(db, &zSql[i], bQuiet);
- }
- zSql[j] = ';';
- i = j+1;
- }
- }
- }
- iStart = sqlite3Hwtime();
- sqlite3_close(db);
- iElapse = sqlite3Hwtime() - iStart;
-#if !defined(_MSC_VER)
- clkEnd = times(&tmsEnd);
-#endif
- iSetup += iElapse;
- if (!bQuiet) printf("sqlite3_close() returns in %llu cycles\n", iElapse);
-
- printf("\n");
- printf("Statements run: %15d stmts\n", nStmt);
- printf("Bytes of SQL text: %15d bytes\n", nByte);
- printf("Total prepare time: %15llu cycles\n", prepTime);
- printf("Total run time: %15llu cycles\n", runTime);
- printf("Total finalize time: %15llu cycles\n", finalizeTime);
- printf("Open/Close time: %15llu cycles\n", iSetup);
- printf("Total time: %15llu cycles\n",
- prepTime + runTime + finalizeTime + iSetup);
-
-#if !defined(_MSC_VER)
- printf("\n");
- printf("Total user CPU time: %15.3g secs\n", (tmsEnd.tms_utime - tmsStart.tms_utime)/(double)CLOCKS_PER_SEC );
- printf("Total system CPU time: %15.3g secs\n", (tmsEnd.tms_stime - tmsStart.tms_stime)/(double)CLOCKS_PER_SEC );
- printf("Total real time: %15.3g secs\n", (clkEnd -clkStart)/(double)CLOCKS_PER_SEC );
-#endif
-
-#ifdef HAVE_OSINST
- if( pVfs ){
- sqlite3_instvfs_destroy(pVfs);
- printf("vfs log written to %s\n", argv[0]);
- }
-#endif
-
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest8inst1.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest8inst1.c
deleted file mode 100644
index ceaeca0f167..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/speedtest8inst1.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
-** Performance test for SQLite.
-**
-** This program reads ASCII text from a file named on the command-line
-** and submits that text to SQLite for evaluation. A new database
-** is created at the beginning of the program. All statements are
-** timed using the high-resolution timer built into Intel-class processors.
-**
-** To compile this program, first compile the SQLite library separately
-** will full optimizations. For example:
-**
-** gcc -c -O6 -DSQLITE_THREADSAFE=0 sqlite3.c
-**
-** Then link against this program. But to do optimize this program
-** because that defeats the hi-res timer.
-**
-** gcc speedtest8.c sqlite3.o -ldl -I../src
-**
-** Then run this program with a single argument which is the name of
-** a file containing SQL script that you want to test:
-**
-** ./a.out test.db test.sql
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include "sqlite3.h"
-
-#define ISSPACE(X) isspace((unsigned char)(X))
-
-#include "test_osinst.c"
-
-/*
-** Prepare and run a single statement of SQL.
-*/
-static void prepareAndRun(sqlite3_vfs *pInstVfs, sqlite3 *db, const char *zSql){
- sqlite3_stmt *pStmt;
- const char *stmtTail;
- int rc;
- char zMessage[1024];
- zMessage[1023] = '\0';
-
- sqlite3_uint64 iTime;
-
- sqlite3_snprintf(1023, zMessage, "sqlite3_prepare_v2: %s", zSql);
- sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
-
- iTime = sqlite3Hwtime();
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail);
- iTime = sqlite3Hwtime() - iTime;
- sqlite3_instvfs_binarylog_call(pInstVfs,BINARYLOG_PREPARE_V2,iTime,rc,zSql);
-
- if( rc==SQLITE_OK ){
- int nRow = 0;
-
- sqlite3_snprintf(1023, zMessage, "sqlite3_step loop: %s", zSql);
- sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
- iTime = sqlite3Hwtime();
- while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; }
- iTime = sqlite3Hwtime() - iTime;
- sqlite3_instvfs_binarylog_call(pInstVfs, BINARYLOG_STEP, iTime, rc, zSql);
-
- sqlite3_snprintf(1023, zMessage, "sqlite3_finalize: %s", zSql);
- sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
- iTime = sqlite3Hwtime();
- rc = sqlite3_finalize(pStmt);
- iTime = sqlite3Hwtime() - iTime;
- sqlite3_instvfs_binarylog_call(pInstVfs, BINARYLOG_FINALIZE, iTime, rc, zSql);
- }
-}
-
-static int stringcompare(const char *zLeft, const char *zRight){
- int ii;
- for(ii=0; zLeft[ii] && zRight[ii]; ii++){
- if( zLeft[ii]!=zRight[ii] ) return 0;
- }
- return( zLeft[ii]==zRight[ii] );
-}
-
-static char *readScriptFile(const char *zFile, int *pnScript){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
- sqlite3_file *p;
- int rc;
- sqlite3_int64 nByte;
- char *zData = 0;
- int flags = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_DB;
-
- p = (sqlite3_file *)malloc(pVfs->szOsFile);
- rc = pVfs->xOpen(pVfs, zFile, p, flags, &flags);
- if( rc!=SQLITE_OK ){
- goto error_out;
- }
-
- rc = p->pMethods->xFileSize(p, &nByte);
- if( rc!=SQLITE_OK ){
- goto close_out;
- }
-
- zData = (char *)malloc(nByte+1);
- rc = p->pMethods->xRead(p, zData, nByte, 0);
- if( rc!=SQLITE_OK ){
- goto close_out;
- }
- zData[nByte] = '\0';
-
- p->pMethods->xClose(p);
- free(p);
- *pnScript = nByte;
- return zData;
-
-close_out:
- p->pMethods->xClose(p);
-
-error_out:
- free(p);
- free(zData);
- return 0;
-}
-
-int main(int argc, char **argv){
-
- const char zUsageMsg[] =
- "Usage: %s options...\n"
- " where available options are:\n"
- "\n"
- " -db DATABASE-FILE (database file to operate on)\n"
- " -script SCRIPT-FILE (script file to read sql from)\n"
- " -log LOG-FILE (log file to create)\n"
- " -logdata (log all data to log file)\n"
- "\n"
- " Options -db, -script and -log are compulsory\n"
- "\n"
- ;
-
- const char *zDb = 0;
- const char *zScript = 0;
- const char *zLog = 0;
- int logdata = 0;
-
- int ii;
- int i, j;
- int rc;
-
- sqlite3_vfs *pInstVfs; /* Instrumentation VFS */
-
- char *zSql = 0;
- int nSql;
-
- sqlite3 *db;
-
- for(ii=1; ii<argc; ii++){
- if( stringcompare("-db", argv[ii]) && (ii+1)<argc ){
- zDb = argv[++ii];
- }
-
- else if( stringcompare("-script", argv[ii]) && (ii+1)<argc ){
- zScript = argv[++ii];
- }
-
- else if( stringcompare("-log", argv[ii]) && (ii+1)<argc ){
- zLog = argv[++ii];
- }
-
- else if( stringcompare("-logdata", argv[ii]) ){
- logdata = 1;
- }
-
- else {
- goto usage;
- }
- }
- if( !zDb || !zScript || !zLog ) goto usage;
-
- zSql = readScriptFile(zScript, &nSql);
- if( !zSql ){
- fprintf(stderr, "Failed to read script file\n");
- return -1;
- }
-
- pInstVfs = sqlite3_instvfs_binarylog("logging", 0, zLog, logdata);
-
- rc = sqlite3_open_v2(
- zDb, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "logging"
- );
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "Failed to open db: %s\n", sqlite3_errmsg(db));
- return -2;
- }
-
- for(i=j=0; j<nSql; j++){
- if( zSql[j]==';' ){
- int isComplete;
- char c = zSql[j+1];
- zSql[j+1] = 0;
- isComplete = sqlite3_complete(&zSql[i]);
- zSql[j+1] = c;
- if( isComplete ){
- zSql[j] = 0;
- while( i<j && ISSPACE(zSql[i]) ){ i++; }
- if( i<j ){
- prepareAndRun(pInstVfs, db, &zSql[i]);
- }
- zSql[j] = ';';
- i = j+1;
- }
- }
- }
-
- sqlite3_instvfs_destroy(pInstVfs);
- return 0;
-
-usage:
- fprintf(stderr, zUsageMsg, argv[0]);
- return -3;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/split-sqlite3c.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/split-sqlite3c.tcl
deleted file mode 100644
index 230e3f2549c..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/split-sqlite3c.tcl
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script splits the sqlite3.c amalgamated source code files into
-# several smaller files such that no single files is more than a fixed
-# number of lines in length (32k or 64k). Each of the split out files
-# is #include-ed by the master file.
-#
-# Splitting files up this way allows them to be used with older compilers
-# that cannot handle really long source files.
-#
-set MAX 32768 ;# Maximum number of lines per file.
-
-set BEGIN {^/\*+ Begin file ([a-zA-Z0-9_.]+) \*+/}
-set END {^/\*+ End of %s \*+/}
-
-set in [open sqlite3.c]
-set out1 [open sqlite3-all.c w]
-fconfigure $out1 -translation lf
-
-# Copy the header from sqlite3.c into sqlite3-all.c
-#
-while {[gets $in line]} {
- if {[regexp $BEGIN $line]} break
- puts $out1 $line
-}
-
-# Gather the complete content of a file into memory. Store the
-# content in $bufout. Store the number of lines is $nout
-#
-proc gather_one_file {firstline bufout nout} {
- regexp $::BEGIN $firstline all filename
- set end [format $::END $filename]
- upvar $bufout buf $nout n
- set buf $firstline\n
- global in
- set n 0
- while {[gets $in line]>=0} {
- incr n
- append buf $line\n
- if {[regexp $end $line]} break
- }
-}
-
-# Write a big chunk of text in to an auxiliary file "sqlite3-NNN.c".
-# Also add an appropriate #include to sqlite3-all.c
-#
-set filecnt 0
-proc write_one_file {content} {
- global filecnt
- incr filecnt
- set out [open sqlite3-$filecnt.c w]
- fconfigure $out -translation lf
- puts -nonewline $out $content
- close $out
- puts $::out1 "#include \"sqlite3-$filecnt.c\""
-}
-
-# Continue reading input. Store chunks in separate files and add
-# the #includes to the main sqlite3-all.c file as necessary to reference
-# the extra chunks.
-#
-set all {}
-set N 0
-while {[regexp $BEGIN $line]} {
- set buf {}
- set n 0
- gather_one_file $line buf n
- if {$n+$N>=$MAX} {
- write_one_file $all
- set all {}
- set N 0
- }
- append all $buf
- incr N $n
- while {[gets $in line]>=0} {
- if {[regexp $BEGIN $line]} break
- puts $out1 $line
- }
-}
-if {$N>0} {
- write_one_file $all
-}
-close $out1
-close $in
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqldiff.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqldiff.c
deleted file mode 100644
index 509470a1561..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqldiff.c
+++ /dev/null
@@ -1,2006 +0,0 @@
-/*
-** 2015-04-06
-**
-** 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 is a utility program that computes the differences in content
-** between two SQLite databases.
-**
-** To compile, simply link against SQLite.
-**
-** See the showHelp() routine below for a brief description of how to
-** run the utility.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
-#include <assert.h>
-#include "sqlite3.h"
-
-/*
-** All global variables are gathered into the "g" singleton.
-*/
-struct GlobalVars {
- const char *zArgv0; /* Name of program */
- int bSchemaOnly; /* Only show schema differences */
- int bSchemaPK; /* Use the schema-defined PK, not the true PK */
- int bHandleVtab; /* Handle fts3, fts4, fts5 and rtree vtabs */
- unsigned fDebug; /* Debug flags */
- sqlite3 *db; /* The database connection */
-} g;
-
-/*
-** Allowed values for g.fDebug
-*/
-#define DEBUG_COLUMN_NAMES 0x000001
-#define DEBUG_DIFF_SQL 0x000002
-
-/*
-** Dynamic string object
-*/
-typedef struct Str Str;
-struct Str {
- char *z; /* Text of the string */
- int nAlloc; /* Bytes allocated in z[] */
- int nUsed; /* Bytes actually used in z[] */
-};
-
-/*
-** Initialize a Str object
-*/
-static void strInit(Str *p){
- p->z = 0;
- p->nAlloc = 0;
- p->nUsed = 0;
-}
-
-/*
-** Print an error resulting from faulting command-line arguments and
-** abort the program.
-*/
-static void cmdlineError(const char *zFormat, ...){
- va_list ap;
- fprintf(stderr, "%s: ", g.zArgv0);
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n\"%s --help\" for more help\n", g.zArgv0);
- exit(1);
-}
-
-/*
-** Print an error message for an error that occurs at runtime, then
-** abort the program.
-*/
-static void runtimeError(const char *zFormat, ...){
- va_list ap;
- fprintf(stderr, "%s: ", g.zArgv0);
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-/*
-** Free all memory held by a Str object
-*/
-static void strFree(Str *p){
- sqlite3_free(p->z);
- strInit(p);
-}
-
-/*
-** Add formatted text to the end of a Str object
-*/
-static void strPrintf(Str *p, const char *zFormat, ...){
- int nNew;
- for(;;){
- if( p->z ){
- va_list ap;
- va_start(ap, zFormat);
- sqlite3_vsnprintf(p->nAlloc-p->nUsed, p->z+p->nUsed, zFormat, ap);
- va_end(ap);
- nNew = (int)strlen(p->z + p->nUsed);
- }else{
- nNew = p->nAlloc;
- }
- if( p->nUsed+nNew < p->nAlloc-1 ){
- p->nUsed += nNew;
- break;
- }
- p->nAlloc = p->nAlloc*2 + 1000;
- p->z = sqlite3_realloc(p->z, p->nAlloc);
- if( p->z==0 ) runtimeError("out of memory");
- }
-}
-
-
-
-/* Safely quote an SQL identifier. Use the minimum amount of transformation
-** necessary to allow the string to be used with %s.
-**
-** Space to hold the returned string is obtained from sqlite3_malloc(). The
-** caller is responsible for ensuring this space is freed when no longer
-** needed.
-*/
-static char *safeId(const char *zId){
- int i, x;
- char c;
- if( zId[0]==0 ) return sqlite3_mprintf("\"\"");
- for(i=x=0; (c = zId[i])!=0; i++){
- if( !isalpha(c) && c!='_' ){
- if( i>0 && isdigit(c) ){
- x++;
- }else{
- return sqlite3_mprintf("\"%w\"", zId);
- }
- }
- }
- if( x || !sqlite3_keyword_check(zId,i) ){
- return sqlite3_mprintf("%s", zId);
- }
- return sqlite3_mprintf("\"%w\"", zId);
-}
-
-/*
-** Prepare a new SQL statement. Print an error and abort if anything
-** goes wrong.
-*/
-static sqlite3_stmt *db_vprepare(const char *zFormat, va_list ap){
- char *zSql;
- int rc;
- sqlite3_stmt *pStmt;
-
- zSql = sqlite3_vmprintf(zFormat, ap);
- if( zSql==0 ) runtimeError("out of memory");
- rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0);
- if( rc ){
- runtimeError("SQL statement error: %s\n\"%s\"", sqlite3_errmsg(g.db),
- zSql);
- }
- sqlite3_free(zSql);
- return pStmt;
-}
-static sqlite3_stmt *db_prepare(const char *zFormat, ...){
- va_list ap;
- sqlite3_stmt *pStmt;
- va_start(ap, zFormat);
- pStmt = db_vprepare(zFormat, ap);
- va_end(ap);
- return pStmt;
-}
-
-/*
-** Free a list of strings
-*/
-static void namelistFree(char **az){
- if( az ){
- int i;
- for(i=0; az[i]; i++) sqlite3_free(az[i]);
- sqlite3_free(az);
- }
-}
-
-/*
-** Return a list of column names for the table zDb.zTab. Space to
-** hold the list is obtained from sqlite3_malloc() and should released
-** using namelistFree() when no longer needed.
-**
-** Primary key columns are listed first, followed by data columns.
-** The number of columns in the primary key is returned in *pnPkey.
-**
-** Normally, the "primary key" in the previous sentence is the true
-** primary key - the rowid or INTEGER PRIMARY KEY for ordinary tables
-** or the declared PRIMARY KEY for WITHOUT ROWID tables. However, if
-** the g.bSchemaPK flag is set, then the schema-defined PRIMARY KEY is
-** used in all cases. In that case, entries that have NULL values in
-** any of their primary key fields will be excluded from the analysis.
-**
-** If the primary key for a table is the rowid but rowid is inaccessible,
-** then this routine returns a NULL pointer.
-**
-** Examples:
-** CREATE TABLE t1(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(c));
-** *pnPKey = 1;
-** az = { "rowid", "a", "b", "c", 0 } // Normal case
-** az = { "c", "a", "b", 0 } // g.bSchemaPK==1
-**
-** CREATE TABLE t2(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(b));
-** *pnPKey = 1;
-** az = { "b", "a", "c", 0 }
-**
-** CREATE TABLE t3(x,y,z,PRIMARY KEY(y,z));
-** *pnPKey = 1 // Normal case
-** az = { "rowid", "x", "y", "z", 0 } // Normal case
-** *pnPKey = 2 // g.bSchemaPK==1
-** az = { "y", "x", "z", 0 } // g.bSchemaPK==1
-**
-** CREATE TABLE t4(x,y,z,PRIMARY KEY(y,z)) WITHOUT ROWID;
-** *pnPKey = 2
-** az = { "y", "z", "x", 0 }
-**
-** CREATE TABLE t5(rowid,_rowid_,oid);
-** az = 0 // The rowid is not accessible
-*/
-static char **columnNames(
- const char *zDb, /* Database ("main" or "aux") to query */
- const char *zTab, /* Name of table to return details of */
- int *pnPKey, /* OUT: Number of PK columns */
- int *pbRowid /* OUT: True if PK is an implicit rowid */
-){
- char **az = 0; /* List of column names to be returned */
- int naz = 0; /* Number of entries in az[] */
- sqlite3_stmt *pStmt; /* SQL statement being run */
- char *zPkIdxName = 0; /* Name of the PRIMARY KEY index */
- int truePk = 0; /* PRAGMA table_info indentifies the PK to use */
- int nPK = 0; /* Number of PRIMARY KEY columns */
- int i, j; /* Loop counters */
-
- if( g.bSchemaPK==0 ){
- /* Normal case: Figure out what the true primary key is for the table.
- ** * For WITHOUT ROWID tables, the true primary key is the same as
- ** the schema PRIMARY KEY, which is guaranteed to be present.
- ** * For rowid tables with an INTEGER PRIMARY KEY, the true primary
- ** key is the INTEGER PRIMARY KEY.
- ** * For all other rowid tables, the rowid is the true primary key.
- */
- pStmt = db_prepare("PRAGMA %s.index_list=%Q", zDb, zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,3),"pk")==0 ){
- zPkIdxName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
- break;
- }
- }
- sqlite3_finalize(pStmt);
- if( zPkIdxName ){
- int nKey = 0;
- int nCol = 0;
- truePk = 0;
- pStmt = db_prepare("PRAGMA %s.index_xinfo=%Q", zDb, zPkIdxName);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- nCol++;
- if( sqlite3_column_int(pStmt,5) ){ nKey++; continue; }
- if( sqlite3_column_int(pStmt,1)>=0 ) truePk = 1;
- }
- if( nCol==nKey ) truePk = 1;
- if( truePk ){
- nPK = nKey;
- }else{
- nPK = 1;
- }
- sqlite3_finalize(pStmt);
- sqlite3_free(zPkIdxName);
- }else{
- truePk = 1;
- nPK = 1;
- }
- pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab);
- }else{
- /* The g.bSchemaPK==1 case: Use whatever primary key is declared
- ** in the schema. The "rowid" will still be used as the primary key
- ** if the table definition does not contain a PRIMARY KEY.
- */
- nPK = 0;
- pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_int(pStmt,5)>0 ) nPK++;
- }
- sqlite3_reset(pStmt);
- if( nPK==0 ) nPK = 1;
- truePk = 1;
- }
- *pnPKey = nPK;
- naz = nPK;
- az = sqlite3_malloc( sizeof(char*)*(nPK+1) );
- if( az==0 ) runtimeError("out of memory");
- memset(az, 0, sizeof(char*)*(nPK+1));
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- int iPKey;
- if( truePk && (iPKey = sqlite3_column_int(pStmt,5))>0 ){
- az[iPKey-1] = safeId((char*)sqlite3_column_text(pStmt,1));
- }else{
- az = sqlite3_realloc(az, sizeof(char*)*(naz+2) );
- if( az==0 ) runtimeError("out of memory");
- az[naz++] = safeId((char*)sqlite3_column_text(pStmt,1));
- }
- }
- sqlite3_finalize(pStmt);
- if( az ) az[naz] = 0;
-
- /* If it is non-NULL, set *pbRowid to indicate whether or not the PK of
- ** this table is an implicit rowid (*pbRowid==1) or not (*pbRowid==0). */
- if( pbRowid ) *pbRowid = (az[0]==0);
-
- /* If this table has an implicit rowid for a PK, figure out how to refer
- ** to it. There are three options - "rowid", "_rowid_" and "oid". Any
- ** of these will work, unless the table has an explicit column of the
- ** same name. */
- if( az[0]==0 ){
- const char *azRowid[] = { "rowid", "_rowid_", "oid" };
- for(i=0; i<sizeof(azRowid)/sizeof(azRowid[0]); i++){
- for(j=1; j<naz; j++){
- if( sqlite3_stricmp(az[j], azRowid[i])==0 ) break;
- }
- if( j>=naz ){
- az[0] = sqlite3_mprintf("%s", azRowid[i]);
- break;
- }
- }
- if( az[0]==0 ){
- for(i=1; i<naz; i++) sqlite3_free(az[i]);
- sqlite3_free(az);
- az = 0;
- }
- }
- return az;
-}
-
-/*
-** Print the sqlite3_value X as an SQL literal.
-*/
-static void printQuoted(FILE *out, sqlite3_value *X){
- switch( sqlite3_value_type(X) ){
- case SQLITE_FLOAT: {
- double r1;
- char zBuf[50];
- r1 = sqlite3_value_double(X);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
- fprintf(out, "%s", zBuf);
- break;
- }
- case SQLITE_INTEGER: {
- fprintf(out, "%lld", sqlite3_value_int64(X));
- break;
- }
- case SQLITE_BLOB: {
- const unsigned char *zBlob = sqlite3_value_blob(X);
- int nBlob = sqlite3_value_bytes(X);
- if( zBlob ){
- int i;
- fprintf(out, "x'");
- for(i=0; i<nBlob; i++){
- fprintf(out, "%02x", zBlob[i]);
- }
- fprintf(out, "'");
- }else{
- /* Could be an OOM, could be a zero-byte blob */
- fprintf(out, "X''");
- }
- break;
- }
- case SQLITE_TEXT: {
- const unsigned char *zArg = sqlite3_value_text(X);
- int i, j;
-
- if( zArg==0 ){
- fprintf(out, "NULL");
- }else{
- fprintf(out, "'");
- for(i=j=0; zArg[i]; i++){
- if( zArg[i]=='\'' ){
- fprintf(out, "%.*s'", i-j+1, &zArg[j]);
- j = i+1;
- }
- }
- fprintf(out, "%s'", &zArg[j]);
- }
- break;
- }
- case SQLITE_NULL: {
- fprintf(out, "NULL");
- break;
- }
- }
-}
-
-/*
-** Output SQL that will recreate the aux.zTab table.
-*/
-static void dump_table(const char *zTab, FILE *out){
- char *zId = safeId(zTab); /* Name of the table */
- char **az = 0; /* List of columns */
- int nPk; /* Number of true primary key columns */
- int nCol; /* Number of data columns */
- int i; /* Loop counter */
- sqlite3_stmt *pStmt; /* SQL statement */
- const char *zSep; /* Separator string */
- Str ins; /* Beginning of the INSERT statement */
-
- pStmt = db_prepare("SELECT sql FROM aux.sqlite_master WHERE name=%Q", zTab);
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
- }
- sqlite3_finalize(pStmt);
- if( !g.bSchemaOnly ){
- az = columnNames("aux", zTab, &nPk, 0);
- strInit(&ins);
- if( az==0 ){
- pStmt = db_prepare("SELECT * FROM aux.%s", zId);
- strPrintf(&ins,"INSERT INTO %s VALUES", zId);
- }else{
- Str sql;
- strInit(&sql);
- zSep = "SELECT";
- for(i=0; az[i]; i++){
- strPrintf(&sql, "%s %s", zSep, az[i]);
- zSep = ",";
- }
- strPrintf(&sql," FROM aux.%s", zId);
- zSep = " ORDER BY";
- for(i=1; i<=nPk; i++){
- strPrintf(&sql, "%s %d", zSep, i);
- zSep = ",";
- }
- pStmt = db_prepare("%s", sql.z);
- strFree(&sql);
- strPrintf(&ins, "INSERT INTO %s", zId);
- zSep = "(";
- for(i=0; az[i]; i++){
- strPrintf(&ins, "%s%s", zSep, az[i]);
- zSep = ",";
- }
- strPrintf(&ins,") VALUES");
- namelistFree(az);
- }
- nCol = sqlite3_column_count(pStmt);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- fprintf(out, "%s",ins.z);
- zSep = "(";
- for(i=0; i<nCol; i++){
- fprintf(out, "%s",zSep);
- printQuoted(out, sqlite3_column_value(pStmt,i));
- zSep = ",";
- }
- fprintf(out, ");\n");
- }
- sqlite3_finalize(pStmt);
- strFree(&ins);
- } /* endif !g.bSchemaOnly */
- pStmt = db_prepare("SELECT sql FROM aux.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q AND sql IS NOT NULL",
- zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
- }
- sqlite3_finalize(pStmt);
-}
-
-
-/*
-** Compute all differences for a single table.
-*/
-static void diff_one_table(const char *zTab, FILE *out){
- char *zId = safeId(zTab); /* Name of table (translated for us in SQL) */
- char **az = 0; /* Columns in main */
- char **az2 = 0; /* Columns in aux */
- int nPk; /* Primary key columns in main */
- int nPk2; /* Primary key columns in aux */
- int n = 0; /* Number of columns in main */
- int n2; /* Number of columns in aux */
- int nQ; /* Number of output columns in the diff query */
- int i; /* Loop counter */
- const char *zSep; /* Separator string */
- Str sql; /* Comparison query */
- sqlite3_stmt *pStmt; /* Query statement to do the diff */
-
- strInit(&sql);
- if( g.fDebug==DEBUG_COLUMN_NAMES ){
- /* Simply run columnNames() on all tables of the origin
- ** database and show the results. This is used for testing
- ** and debugging of the columnNames() function.
- */
- az = columnNames("aux",zTab, &nPk, 0);
- if( az==0 ){
- printf("Rowid not accessible for %s\n", zId);
- }else{
- printf("%s:", zId);
- for(i=0; az[i]; i++){
- printf(" %s", az[i]);
- if( i+1==nPk ) printf(" *");
- }
- printf("\n");
- }
- goto end_diff_one_table;
- }
-
-
- if( sqlite3_table_column_metadata(g.db,"aux",zTab,0,0,0,0,0,0) ){
- if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
- /* Table missing from second database. */
- fprintf(out, "DROP TABLE %s;\n", zId);
- }
- goto end_diff_one_table;
- }
-
- if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
- /* Table missing from source */
- dump_table(zTab, out);
- goto end_diff_one_table;
- }
-
- az = columnNames("main", zTab, &nPk, 0);
- az2 = columnNames("aux", zTab, &nPk2, 0);
- if( az && az2 ){
- for(n=0; az[n] && az2[n]; n++){
- if( sqlite3_stricmp(az[n],az2[n])!=0 ) break;
- }
- }
- if( az==0
- || az2==0
- || nPk!=nPk2
- || az[n]
- ){
- /* Schema mismatch */
- fprintf(out, "DROP TABLE %s; -- due to schema mismatch\n", zId);
- dump_table(zTab, out);
- goto end_diff_one_table;
- }
-
- /* Build the comparison query */
- for(n2=n; az2[n2]; n2++){
- fprintf(out, "ALTER TABLE %s ADD COLUMN %s;\n", zId, safeId(az2[n2]));
- }
- nQ = nPk2+1+2*(n2-nPk2);
- if( n2>nPk2 ){
- zSep = "SELECT ";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%sB.%s", zSep, az[i]);
- zSep = ", ";
- }
- strPrintf(&sql, ", 1%s -- changed row\n", nPk==n ? "" : ",");
- while( az[i] ){
- strPrintf(&sql, " A.%s IS NOT B.%s, B.%s%s\n",
- az[i], az2[i], az2[i], az2[i+1]==0 ? "" : ",");
- i++;
- }
- while( az2[i] ){
- strPrintf(&sql, " B.%s IS NOT NULL, B.%s%s\n",
- az2[i], az2[i], az2[i+1]==0 ? "" : ",");
- i++;
- }
- strPrintf(&sql, " FROM main.%s A, aux.%s B\n", zId, zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- zSep = "\n AND (";
- while( az[i] ){
- strPrintf(&sql, "%sA.%s IS NOT B.%s%s\n",
- zSep, az[i], az2[i], az2[i+1]==0 ? ")" : "");
- zSep = " OR ";
- i++;
- }
- while( az2[i] ){
- strPrintf(&sql, "%sB.%s IS NOT NULL%s\n",
- zSep, az2[i], az2[i+1]==0 ? ")" : "");
- zSep = " OR ";
- i++;
- }
- strPrintf(&sql, " UNION ALL\n");
- }
- zSep = "SELECT ";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%sA.%s", zSep, az[i]);
- zSep = ", ";
- }
- strPrintf(&sql, ", 2%s -- deleted row\n", nPk==n ? "" : ",");
- while( az2[i] ){
- strPrintf(&sql, " NULL, NULL%s\n", i==n2-1 ? "" : ",");
- i++;
- }
- strPrintf(&sql, " FROM main.%s A\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n");
- zSep = " UNION ALL\nSELECT ";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%sB.%s", zSep, az[i]);
- zSep = ", ";
- }
- strPrintf(&sql, ", 3%s -- inserted row\n", nPk==n ? "" : ",");
- while( az2[i] ){
- strPrintf(&sql, " 1, B.%s%s\n", az2[i], az2[i+1]==0 ? "" : ",");
- i++;
- }
- strPrintf(&sql, " FROM aux.%s B\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n ORDER BY");
- zSep = " ";
- for(i=1; i<=nPk; i++){
- strPrintf(&sql, "%s%d", zSep, i);
- zSep = ", ";
- }
- strPrintf(&sql, ";\n");
-
- if( g.fDebug & DEBUG_DIFF_SQL ){
- printf("SQL for %s:\n%s\n", zId, sql.z);
- goto end_diff_one_table;
- }
-
- /* Drop indexes that are missing in the destination */
- pStmt = db_prepare(
- "SELECT name FROM main.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q"
- " AND sql IS NOT NULL"
- " AND sql NOT IN (SELECT sql FROM aux.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q"
- " AND sql IS NOT NULL)",
- zTab, zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- char *z = safeId((const char*)sqlite3_column_text(pStmt,0));
- fprintf(out, "DROP INDEX %s;\n", z);
- sqlite3_free(z);
- }
- sqlite3_finalize(pStmt);
-
- /* Run the query and output differences */
- if( !g.bSchemaOnly ){
- pStmt = db_prepare("%s", sql.z);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- int iType = sqlite3_column_int(pStmt, nPk);
- if( iType==1 || iType==2 ){
- if( iType==1 ){ /* Change the content of a row */
- fprintf(out, "UPDATE %s", zId);
- zSep = " SET";
- for(i=nPk+1; i<nQ; i+=2){
- if( sqlite3_column_int(pStmt,i)==0 ) continue;
- fprintf(out, "%s %s=", zSep, az2[(i+nPk-1)/2]);
- zSep = ",";
- printQuoted(out, sqlite3_column_value(pStmt,i+1));
- }
- }else{ /* Delete a row */
- fprintf(out, "DELETE FROM %s", zId);
- }
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- fprintf(out, "%s %s=", zSep, az2[i]);
- printQuoted(out, sqlite3_column_value(pStmt,i));
- zSep = " AND";
- }
- fprintf(out, ";\n");
- }else{ /* Insert a row */
- fprintf(out, "INSERT INTO %s(%s", zId, az2[0]);
- for(i=1; az2[i]; i++) fprintf(out, ",%s", az2[i]);
- fprintf(out, ") VALUES");
- zSep = "(";
- for(i=0; i<nPk2; i++){
- fprintf(out, "%s", zSep);
- zSep = ",";
- printQuoted(out, sqlite3_column_value(pStmt,i));
- }
- for(i=nPk2+2; i<nQ; i+=2){
- fprintf(out, ",");
- printQuoted(out, sqlite3_column_value(pStmt,i));
- }
- fprintf(out, ");\n");
- }
- }
- sqlite3_finalize(pStmt);
- } /* endif !g.bSchemaOnly */
-
- /* Create indexes that are missing in the source */
- pStmt = db_prepare(
- "SELECT sql FROM aux.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q"
- " AND sql IS NOT NULL"
- " AND sql NOT IN (SELECT sql FROM main.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q"
- " AND sql IS NOT NULL)",
- zTab, zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
- }
- sqlite3_finalize(pStmt);
-
-end_diff_one_table:
- strFree(&sql);
- sqlite3_free(zId);
- namelistFree(az);
- namelistFree(az2);
- return;
-}
-
-/*
-** Check that table zTab exists and has the same schema in both the "main"
-** and "aux" databases currently opened by the global db handle. If they
-** do not, output an error message on stderr and exit(1). Otherwise, if
-** the schemas do match, return control to the caller.
-*/
-static void checkSchemasMatch(const char *zTab){
- sqlite3_stmt *pStmt = db_prepare(
- "SELECT A.sql=B.sql FROM main.sqlite_master A, aux.sqlite_master B"
- " WHERE A.name=%Q AND B.name=%Q", zTab, zTab
- );
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_int(pStmt,0)==0 ){
- runtimeError("schema changes for table %s", safeId(zTab));
- }
- }else{
- runtimeError("table %s missing from one or both databases", safeId(zTab));
- }
- sqlite3_finalize(pStmt);
-}
-
-/**************************************************************************
-** The following code is copied from fossil. It is used to generate the
-** fossil delta blobs sometimes used in RBU update records.
-*/
-
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef unsigned char u8;
-
-/*
-** The width of a hash window in bytes. The algorithm only works if this
-** is a power of 2.
-*/
-#define NHASH 16
-
-/*
-** The current state of the rolling hash.
-**
-** z[] holds the values that have been hashed. z[] is a circular buffer.
-** z[i] is the first entry and z[(i+NHASH-1)%NHASH] is the last entry of
-** the window.
-**
-** Hash.a is the sum of all elements of hash.z[]. Hash.b is a weighted
-** sum. Hash.b is z[i]*NHASH + z[i+1]*(NHASH-1) + ... + z[i+NHASH-1]*1.
-** (Each index for z[] should be module NHASH, of course. The %NHASH operator
-** is omitted in the prior expression for brevity.)
-*/
-typedef struct hash hash;
-struct hash {
- u16 a, b; /* Hash values */
- u16 i; /* Start of the hash window */
- char z[NHASH]; /* The values that have been hashed */
-};
-
-/*
-** Initialize the rolling hash using the first NHASH characters of z[]
-*/
-static void hash_init(hash *pHash, const char *z){
- u16 a, b, i;
- a = b = 0;
- for(i=0; i<NHASH; i++){
- a += z[i];
- b += (NHASH-i)*z[i];
- pHash->z[i] = z[i];
- }
- pHash->a = a & 0xffff;
- pHash->b = b & 0xffff;
- pHash->i = 0;
-}
-
-/*
-** Advance the rolling hash by a single character "c"
-*/
-static void hash_next(hash *pHash, int c){
- u16 old = pHash->z[pHash->i];
- pHash->z[pHash->i] = (char)c;
- pHash->i = (pHash->i+1)&(NHASH-1);
- pHash->a = pHash->a - old + (char)c;
- pHash->b = pHash->b - NHASH*old + pHash->a;
-}
-
-/*
-** Return a 32-bit hash value
-*/
-static u32 hash_32bit(hash *pHash){
- return (pHash->a & 0xffff) | (((u32)(pHash->b & 0xffff))<<16);
-}
-
-/*
-** Write an base-64 integer into the given buffer.
-*/
-static void putInt(unsigned int v, char **pz){
- static const char zDigits[] =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~";
- /* 123456789 123456789 123456789 123456789 123456789 123456789 123 */
- int i, j;
- char zBuf[20];
- if( v==0 ){
- *(*pz)++ = '0';
- return;
- }
- for(i=0; v>0; i++, v>>=6){
- zBuf[i] = zDigits[v&0x3f];
- }
- for(j=i-1; j>=0; j--){
- *(*pz)++ = zBuf[j];
- }
-}
-
-/*
-** Return the number digits in the base-64 representation of a positive integer
-*/
-static int digit_count(int v){
- unsigned int i, x;
- for(i=1, x=64; (unsigned int)v>=x; i++, x <<= 6){}
- return i;
-}
-
-/*
-** Compute a 32-bit checksum on the N-byte buffer. Return the result.
-*/
-static unsigned int checksum(const char *zIn, size_t N){
- const unsigned char *z = (const unsigned char *)zIn;
- unsigned sum0 = 0;
- unsigned sum1 = 0;
- unsigned sum2 = 0;
- unsigned sum3 = 0;
- while(N >= 16){
- sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]);
- sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]);
- sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]);
- sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]);
- z += 16;
- N -= 16;
- }
- while(N >= 4){
- sum0 += z[0];
- sum1 += z[1];
- sum2 += z[2];
- sum3 += z[3];
- z += 4;
- N -= 4;
- }
- sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
- switch(N){
- case 3: sum3 += (z[2] << 8);
- case 2: sum3 += (z[1] << 16);
- case 1: sum3 += (z[0] << 24);
- default: ;
- }
- return sum3;
-}
-
-/*
-** Create a new delta.
-**
-** The delta is written into a preallocated buffer, zDelta, which
-** should be at least 60 bytes longer than the target file, zOut.
-** The delta string will be NUL-terminated, but it might also contain
-** embedded NUL characters if either the zSrc or zOut files are
-** binary. This function returns the length of the delta string
-** in bytes, excluding the final NUL terminator character.
-**
-** Output Format:
-**
-** The delta begins with a base64 number followed by a newline. This
-** number is the number of bytes in the TARGET file. Thus, given a
-** delta file z, a program can compute the size of the output file
-** simply by reading the first line and decoding the base-64 number
-** found there. The delta_output_size() routine does exactly this.
-**
-** After the initial size number, the delta consists of a series of
-** literal text segments and commands to copy from the SOURCE file.
-** A copy command looks like this:
-**
-** NNN@MMM,
-**
-** where NNN is the number of bytes to be copied and MMM is the offset
-** into the source file of the first byte (both base-64). If NNN is 0
-** it means copy the rest of the input file. Literal text is like this:
-**
-** NNN:TTTTT
-**
-** where NNN is the number of bytes of text (base-64) and TTTTT is the text.
-**
-** The last term is of the form
-**
-** NNN;
-**
-** In this case, NNN is a 32-bit bigendian checksum of the output file
-** that can be used to verify that the delta applied correctly. All
-** numbers are in base-64.
-**
-** Pure text files generate a pure text delta. Binary files generate a
-** delta that may contain some binary data.
-**
-** Algorithm:
-**
-** The encoder first builds a hash table to help it find matching
-** patterns in the source file. 16-byte chunks of the source file
-** sampled at evenly spaced intervals are used to populate the hash
-** table.
-**
-** Next we begin scanning the target file using a sliding 16-byte
-** window. The hash of the 16-byte window in the target is used to
-** search for a matching section in the source file. When a match
-** is found, a copy command is added to the delta. An effort is
-** made to extend the matching section to regions that come before
-** and after the 16-byte hash window. A copy command is only issued
-** if the result would use less space that just quoting the text
-** literally. Literal text is added to the delta for sections that
-** do not match or which can not be encoded efficiently using copy
-** commands.
-*/
-static int rbuDeltaCreate(
- const char *zSrc, /* The source or pattern file */
- unsigned int lenSrc, /* Length of the source file */
- const char *zOut, /* The target file */
- unsigned int lenOut, /* Length of the target file */
- char *zDelta /* Write the delta into this buffer */
-){
- unsigned int i, base;
- char *zOrigDelta = zDelta;
- hash h;
- int nHash; /* Number of hash table entries */
- int *landmark; /* Primary hash table */
- int *collide; /* Collision chain */
- int lastRead = -1; /* Last byte of zSrc read by a COPY command */
-
- /* Add the target file size to the beginning of the delta
- */
- putInt(lenOut, &zDelta);
- *(zDelta++) = '\n';
-
- /* If the source file is very small, it means that we have no
- ** chance of ever doing a copy command. Just output a single
- ** literal segment for the entire target and exit.
- */
- if( lenSrc<=NHASH ){
- putInt(lenOut, &zDelta);
- *(zDelta++) = ':';
- memcpy(zDelta, zOut, lenOut);
- zDelta += lenOut;
- putInt(checksum(zOut, lenOut), &zDelta);
- *(zDelta++) = ';';
- return (int)(zDelta - zOrigDelta);
- }
-
- /* Compute the hash table used to locate matching sections in the
- ** source file.
- */
- nHash = lenSrc/NHASH;
- collide = sqlite3_malloc( nHash*2*sizeof(int) );
- landmark = &collide[nHash];
- memset(landmark, -1, nHash*sizeof(int));
- memset(collide, -1, nHash*sizeof(int));
- for(i=0; i<lenSrc-NHASH; i+=NHASH){
- int hv;
- hash_init(&h, &zSrc[i]);
- hv = hash_32bit(&h) % nHash;
- collide[i/NHASH] = landmark[hv];
- landmark[hv] = i/NHASH;
- }
-
- /* Begin scanning the target file and generating copy commands and
- ** literal sections of the delta.
- */
- base = 0; /* We have already generated everything before zOut[base] */
- while( base+NHASH<lenOut ){
- int iSrc, iBlock;
- int bestCnt, bestOfst=0, bestLitsz=0;
- hash_init(&h, &zOut[base]);
- i = 0; /* Trying to match a landmark against zOut[base+i] */
- bestCnt = 0;
- while( 1 ){
- int hv;
- int limit = 250;
-
- hv = hash_32bit(&h) % nHash;
- iBlock = landmark[hv];
- while( iBlock>=0 && (limit--)>0 ){
- /*
- ** The hash window has identified a potential match against
- ** landmark block iBlock. But we need to investigate further.
- **
- ** Look for a region in zOut that matches zSrc. Anchor the search
- ** at zSrc[iSrc] and zOut[base+i]. Do not include anything prior to
- ** zOut[base] or after zOut[outLen] nor anything after zSrc[srcLen].
- **
- ** Set cnt equal to the length of the match and set ofst so that
- ** zSrc[ofst] is the first element of the match. litsz is the number
- ** of characters between zOut[base] and the beginning of the match.
- ** sz will be the overhead (in bytes) needed to encode the copy
- ** command. Only generate copy command if the overhead of the
- ** copy command is less than the amount of literal text to be copied.
- */
- int cnt, ofst, litsz;
- int j, k, x, y;
- int sz;
-
- /* Beginning at iSrc, match forwards as far as we can. j counts
- ** the number of characters that match */
- iSrc = iBlock*NHASH;
- for(
- j=0, x=iSrc, y=base+i;
- (unsigned int)x<lenSrc && (unsigned int)y<lenOut;
- j++, x++, y++
- ){
- if( zSrc[x]!=zOut[y] ) break;
- }
- j--;
-
- /* Beginning at iSrc-1, match backwards as far as we can. k counts
- ** the number of characters that match */
- for(k=1; k<iSrc && (unsigned int)k<=i; k++){
- if( zSrc[iSrc-k]!=zOut[base+i-k] ) break;
- }
- k--;
-
- /* Compute the offset and size of the matching region */
- ofst = iSrc-k;
- cnt = j+k+1;
- litsz = i-k; /* Number of bytes of literal text before the copy */
- /* sz will hold the number of bytes needed to encode the "insert"
- ** command and the copy command, not counting the "insert" text */
- sz = digit_count(i-k)+digit_count(cnt)+digit_count(ofst)+3;
- if( cnt>=sz && cnt>bestCnt ){
- /* Remember this match only if it is the best so far and it
- ** does not increase the file size */
- bestCnt = cnt;
- bestOfst = iSrc-k;
- bestLitsz = litsz;
- }
-
- /* Check the next matching block */
- iBlock = collide[iBlock];
- }
-
- /* We have a copy command that does not cause the delta to be larger
- ** than a literal insert. So add the copy command to the delta.
- */
- if( bestCnt>0 ){
- if( bestLitsz>0 ){
- /* Add an insert command before the copy */
- putInt(bestLitsz,&zDelta);
- *(zDelta++) = ':';
- memcpy(zDelta, &zOut[base], bestLitsz);
- zDelta += bestLitsz;
- base += bestLitsz;
- }
- base += bestCnt;
- putInt(bestCnt, &zDelta);
- *(zDelta++) = '@';
- putInt(bestOfst, &zDelta);
- *(zDelta++) = ',';
- if( bestOfst + bestCnt -1 > lastRead ){
- lastRead = bestOfst + bestCnt - 1;
- }
- bestCnt = 0;
- break;
- }
-
- /* If we reach this point, it means no match is found so far */
- if( base+i+NHASH>=lenOut ){
- /* We have reached the end of the file and have not found any
- ** matches. Do an "insert" for everything that does not match */
- putInt(lenOut-base, &zDelta);
- *(zDelta++) = ':';
- memcpy(zDelta, &zOut[base], lenOut-base);
- zDelta += lenOut-base;
- base = lenOut;
- break;
- }
-
- /* Advance the hash by one character. Keep looking for a match */
- hash_next(&h, zOut[base+i+NHASH]);
- i++;
- }
- }
- /* Output a final "insert" record to get all the text at the end of
- ** the file that does not match anything in the source file.
- */
- if( base<lenOut ){
- putInt(lenOut-base, &zDelta);
- *(zDelta++) = ':';
- memcpy(zDelta, &zOut[base], lenOut-base);
- zDelta += lenOut-base;
- }
- /* Output the final checksum record. */
- putInt(checksum(zOut, lenOut), &zDelta);
- *(zDelta++) = ';';
- sqlite3_free(collide);
- return (int)(zDelta - zOrigDelta);
-}
-
-/*
-** End of code copied from fossil.
-**************************************************************************/
-
-static void strPrintfArray(
- Str *pStr, /* String object to append to */
- const char *zSep, /* Separator string */
- const char *zFmt, /* Format for each entry */
- char **az, int n /* Array of strings & its size (or -1) */
-){
- int i;
- for(i=0; az[i] && (i<n || n<0); i++){
- if( i!=0 ) strPrintf(pStr, "%s", zSep);
- strPrintf(pStr, zFmt, az[i], az[i], az[i]);
- }
-}
-
-static void getRbudiffQuery(
- const char *zTab,
- char **azCol,
- int nPK,
- int bOtaRowid,
- Str *pSql
-){
- int i;
-
- /* First the newly inserted rows: **/
- strPrintf(pSql, "SELECT ");
- strPrintfArray(pSql, ", ", "%s", azCol, -1);
- strPrintf(pSql, ", 0, "); /* Set ota_control to 0 for an insert */
- strPrintfArray(pSql, ", ", "NULL", azCol, -1);
- strPrintf(pSql, " FROM aux.%Q AS n WHERE NOT EXISTS (\n", zTab);
- strPrintf(pSql, " SELECT 1 FROM ", zTab);
- strPrintf(pSql, " main.%Q AS o WHERE ", zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
- strPrintf(pSql, "\n) AND ");
- strPrintfArray(pSql, " AND ", "(n.%Q IS NOT NULL)", azCol, nPK);
-
- /* Deleted rows: */
- strPrintf(pSql, "\nUNION ALL\nSELECT ");
- strPrintfArray(pSql, ", ", "%s", azCol, nPK);
- if( azCol[nPK] ){
- strPrintf(pSql, ", ");
- strPrintfArray(pSql, ", ", "NULL", &azCol[nPK], -1);
- }
- strPrintf(pSql, ", 1, "); /* Set ota_control to 1 for a delete */
- strPrintfArray(pSql, ", ", "NULL", azCol, -1);
- strPrintf(pSql, " FROM main.%Q AS n WHERE NOT EXISTS (\n", zTab);
- strPrintf(pSql, " SELECT 1 FROM ", zTab);
- strPrintf(pSql, " aux.%Q AS o WHERE ", zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
- strPrintf(pSql, "\n) AND ");
- strPrintfArray(pSql, " AND ", "(n.%Q IS NOT NULL)", azCol, nPK);
-
- /* Updated rows. If all table columns are part of the primary key, there
- ** can be no updates. In this case this part of the compound SELECT can
- ** be omitted altogether. */
- if( azCol[nPK] ){
- strPrintf(pSql, "\nUNION ALL\nSELECT ");
- strPrintfArray(pSql, ", ", "n.%s", azCol, nPK);
- strPrintf(pSql, ",\n");
- strPrintfArray(pSql, " ,\n",
- " CASE WHEN n.%s IS o.%s THEN NULL ELSE n.%s END", &azCol[nPK], -1
- );
-
- if( bOtaRowid==0 ){
- strPrintf(pSql, ", '");
- strPrintfArray(pSql, "", ".", azCol, nPK);
- strPrintf(pSql, "' ||\n");
- }else{
- strPrintf(pSql, ",\n");
- }
- strPrintfArray(pSql, " ||\n",
- " CASE WHEN n.%s IS o.%s THEN '.' ELSE 'x' END", &azCol[nPK], -1
- );
- strPrintf(pSql, "\nAS ota_control, ");
- strPrintfArray(pSql, ", ", "NULL", azCol, nPK);
- strPrintf(pSql, ",\n");
- strPrintfArray(pSql, " ,\n",
- " CASE WHEN n.%s IS o.%s THEN NULL ELSE o.%s END", &azCol[nPK], -1
- );
-
- strPrintf(pSql, "\nFROM main.%Q AS o, aux.%Q AS n\nWHERE ", zTab, zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
- strPrintf(pSql, " AND ota_control LIKE '%%x%%'");
- }
-
- /* Now add an ORDER BY clause to sort everything by PK. */
- strPrintf(pSql, "\nORDER BY ");
- for(i=1; i<=nPK; i++) strPrintf(pSql, "%s%d", ((i>1)?", ":""), i);
-}
-
-static void rbudiff_one_table(const char *zTab, FILE *out){
- int bOtaRowid; /* True to use an ota_rowid column */
- int nPK; /* Number of primary key columns in table */
- char **azCol; /* NULL terminated array of col names */
- int i;
- int nCol;
- Str ct = {0, 0, 0}; /* The "CREATE TABLE data_xxx" statement */
- Str sql = {0, 0, 0}; /* Query to find differences */
- Str insert = {0, 0, 0}; /* First part of output INSERT statement */
- sqlite3_stmt *pStmt = 0;
- int nRow = 0; /* Total rows in data_xxx table */
-
- /* --rbu mode must use real primary keys. */
- g.bSchemaPK = 1;
-
- /* Check that the schemas of the two tables match. Exit early otherwise. */
- checkSchemasMatch(zTab);
-
- /* Grab the column names and PK details for the table(s). If no usable PK
- ** columns are found, bail out early. */
- azCol = columnNames("main", zTab, &nPK, &bOtaRowid);
- if( azCol==0 ){
- runtimeError("table %s has no usable PK columns", zTab);
- }
- for(nCol=0; azCol[nCol]; nCol++);
-
- /* Build and output the CREATE TABLE statement for the data_xxx table */
- strPrintf(&ct, "CREATE TABLE IF NOT EXISTS 'data_%q'(", zTab);
- if( bOtaRowid ) strPrintf(&ct, "rbu_rowid, ");
- strPrintfArray(&ct, ", ", "%s", &azCol[bOtaRowid], -1);
- strPrintf(&ct, ", rbu_control);");
-
- /* Get the SQL for the query to retrieve data from the two databases */
- getRbudiffQuery(zTab, azCol, nPK, bOtaRowid, &sql);
-
- /* Build the first part of the INSERT statement output for each row
- ** in the data_xxx table. */
- strPrintf(&insert, "INSERT INTO 'data_%q' (", zTab);
- if( bOtaRowid ) strPrintf(&insert, "rbu_rowid, ");
- strPrintfArray(&insert, ", ", "%s", &azCol[bOtaRowid], -1);
- strPrintf(&insert, ", rbu_control) VALUES(");
-
- pStmt = db_prepare("%s", sql.z);
-
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
-
- /* If this is the first row output, print out the CREATE TABLE
- ** statement first. And then set ct.z to NULL so that it is not
- ** printed again. */
- if( ct.z ){
- fprintf(out, "%s\n", ct.z);
- strFree(&ct);
- }
-
- /* Output the first part of the INSERT statement */
- fprintf(out, "%s", insert.z);
- nRow++;
-
- if( sqlite3_column_type(pStmt, nCol)==SQLITE_INTEGER ){
- for(i=0; i<=nCol; i++){
- if( i>0 ) fprintf(out, ", ");
- printQuoted(out, sqlite3_column_value(pStmt, i));
- }
- }else{
- char *zOtaControl;
- int nOtaControl = sqlite3_column_bytes(pStmt, nCol);
-
- zOtaControl = (char*)sqlite3_malloc(nOtaControl+1);
- memcpy(zOtaControl, sqlite3_column_text(pStmt, nCol), nOtaControl+1);
-
- for(i=0; i<nCol; i++){
- int bDone = 0;
- if( i>=nPK
- && sqlite3_column_type(pStmt, i)==SQLITE_BLOB
- && sqlite3_column_type(pStmt, nCol+1+i)==SQLITE_BLOB
- ){
- const char *aSrc = sqlite3_column_blob(pStmt, nCol+1+i);
- int nSrc = sqlite3_column_bytes(pStmt, nCol+1+i);
- const char *aFinal = sqlite3_column_blob(pStmt, i);
- int nFinal = sqlite3_column_bytes(pStmt, i);
- char *aDelta;
- int nDelta;
-
- aDelta = sqlite3_malloc(nFinal + 60);
- nDelta = rbuDeltaCreate(aSrc, nSrc, aFinal, nFinal, aDelta);
- if( nDelta<nFinal ){
- int j;
- fprintf(out, "x'");
- for(j=0; j<nDelta; j++) fprintf(out, "%02x", (u8)aDelta[j]);
- fprintf(out, "'");
- zOtaControl[i-bOtaRowid] = 'f';
- bDone = 1;
- }
- sqlite3_free(aDelta);
- }
-
- if( bDone==0 ){
- printQuoted(out, sqlite3_column_value(pStmt, i));
- }
- fprintf(out, ", ");
- }
- fprintf(out, "'%s'", zOtaControl);
- sqlite3_free(zOtaControl);
- }
-
- /* And the closing bracket of the insert statement */
- fprintf(out, ");\n");
- }
-
- sqlite3_finalize(pStmt);
- if( nRow>0 ){
- Str cnt = {0, 0, 0};
- strPrintf(&cnt, "INSERT INTO rbu_count VALUES('data_%q', %d);", zTab, nRow);
- fprintf(out, "%s\n", cnt.z);
- strFree(&cnt);
- }
-
- strFree(&ct);
- strFree(&sql);
- strFree(&insert);
-}
-
-/*
-** Display a summary of differences between two versions of the same
-** table table.
-**
-** * Number of rows changed
-** * Number of rows added
-** * Number of rows deleted
-** * Number of identical rows
-*/
-static void summarize_one_table(const char *zTab, FILE *out){
- char *zId = safeId(zTab); /* Name of table (translated for us in SQL) */
- char **az = 0; /* Columns in main */
- char **az2 = 0; /* Columns in aux */
- int nPk; /* Primary key columns in main */
- int nPk2; /* Primary key columns in aux */
- int n = 0; /* Number of columns in main */
- int n2; /* Number of columns in aux */
- int i; /* Loop counter */
- const char *zSep; /* Separator string */
- Str sql; /* Comparison query */
- sqlite3_stmt *pStmt; /* Query statement to do the diff */
- sqlite3_int64 nUpdate; /* Number of updated rows */
- sqlite3_int64 nUnchanged; /* Number of unmodified rows */
- sqlite3_int64 nDelete; /* Number of deleted rows */
- sqlite3_int64 nInsert; /* Number of inserted rows */
-
- strInit(&sql);
- if( sqlite3_table_column_metadata(g.db,"aux",zTab,0,0,0,0,0,0) ){
- if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
- /* Table missing from second database. */
- fprintf(out, "%s: missing from second database\n", zTab);
- }
- goto end_summarize_one_table;
- }
-
- if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
- /* Table missing from source */
- fprintf(out, "%s: missing from first database\n", zTab);
- goto end_summarize_one_table;
- }
-
- az = columnNames("main", zTab, &nPk, 0);
- az2 = columnNames("aux", zTab, &nPk2, 0);
- if( az && az2 ){
- for(n=0; az[n]; n++){
- if( sqlite3_stricmp(az[n],az2[n])!=0 ) break;
- }
- }
- if( az==0
- || az2==0
- || nPk!=nPk2
- || az[n]
- ){
- /* Schema mismatch */
- fprintf(out, "%s: incompatible schema\n", zTab);
- goto end_summarize_one_table;
- }
-
- /* Build the comparison query */
- for(n2=n; az[n2]; n2++){}
- strPrintf(&sql, "SELECT 1, count(*)");
- if( n2==nPk2 ){
- strPrintf(&sql, ", 0\n");
- }else{
- zSep = ", sum(";
- for(i=nPk; az[i]; i++){
- strPrintf(&sql, "%sA.%s IS NOT B.%s", zSep, az[i], az[i]);
- zSep = " OR ";
- }
- strPrintf(&sql, ")\n");
- }
- strPrintf(&sql, " FROM main.%s A, aux.%s B\n", zId, zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, " UNION ALL\n");
- strPrintf(&sql, "SELECT 2, count(*), 0\n");
- strPrintf(&sql, " FROM main.%s A\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B ", zId);
- zSep = "WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n");
- strPrintf(&sql, " UNION ALL\n");
- strPrintf(&sql, "SELECT 3, count(*), 0\n");
- strPrintf(&sql, " FROM aux.%s B\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A ", zId);
- zSep = "WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n ORDER BY 1;\n");
-
- if( (g.fDebug & DEBUG_DIFF_SQL)!=0 ){
- printf("SQL for %s:\n%s\n", zId, sql.z);
- goto end_summarize_one_table;
- }
-
- /* Run the query and output difference summary */
- pStmt = db_prepare("%s", sql.z);
- nUpdate = 0;
- nInsert = 0;
- nDelete = 0;
- nUnchanged = 0;
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- switch( sqlite3_column_int(pStmt,0) ){
- case 1:
- nUpdate = sqlite3_column_int64(pStmt,2);
- nUnchanged = sqlite3_column_int64(pStmt,1) - nUpdate;
- break;
- case 2:
- nDelete = sqlite3_column_int64(pStmt,1);
- break;
- case 3:
- nInsert = sqlite3_column_int64(pStmt,1);
- break;
- }
- }
- sqlite3_finalize(pStmt);
- fprintf(out, "%s: %lld changes, %lld inserts, %lld deletes, %lld unchanged\n",
- zTab, nUpdate, nInsert, nDelete, nUnchanged);
-
-end_summarize_one_table:
- strFree(&sql);
- sqlite3_free(zId);
- namelistFree(az);
- namelistFree(az2);
- return;
-}
-
-/*
-** Write a 64-bit signed integer as a varint onto out
-*/
-static void putsVarint(FILE *out, sqlite3_uint64 v){
- int i, n;
- unsigned char p[12];
- if( v & (((sqlite3_uint64)0xff000000)<<32) ){
- p[8] = (unsigned char)v;
- v >>= 8;
- for(i=7; i>=0; i--){
- p[i] = (unsigned char)((v & 0x7f) | 0x80);
- v >>= 7;
- }
- fwrite(p, 8, 1, out);
- }else{
- n = 9;
- do{
- p[n--] = (unsigned char)((v & 0x7f) | 0x80);
- v >>= 7;
- }while( v!=0 );
- p[9] &= 0x7f;
- fwrite(p+n+1, 9-n, 1, out);
- }
-}
-
-/*
-** Write an SQLite value onto out.
-*/
-static void putValue(FILE *out, sqlite3_value *pVal){
- int iDType = sqlite3_value_type(pVal);
- sqlite3_int64 iX;
- double rX;
- sqlite3_uint64 uX;
- int j;
-
- putc(iDType, out);
- switch( iDType ){
- case SQLITE_INTEGER:
- iX = sqlite3_value_int64(pVal);
- memcpy(&uX, &iX, 8);
- for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out);
- break;
- case SQLITE_FLOAT:
- rX = sqlite3_value_double(pVal);
- memcpy(&uX, &rX, 8);
- for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out);
- break;
- case SQLITE_TEXT:
- iX = sqlite3_value_bytes(pVal);
- putsVarint(out, (sqlite3_uint64)iX);
- fwrite(sqlite3_value_text(pVal),1,(size_t)iX,out);
- break;
- case SQLITE_BLOB:
- iX = sqlite3_value_bytes(pVal);
- putsVarint(out, (sqlite3_uint64)iX);
- fwrite(sqlite3_value_blob(pVal),1,(size_t)iX,out);
- break;
- case SQLITE_NULL:
- break;
- }
-}
-
-/*
-** Generate a CHANGESET for all differences from main.zTab to aux.zTab.
-*/
-static void changeset_one_table(const char *zTab, FILE *out){
- sqlite3_stmt *pStmt; /* SQL statment */
- char *zId = safeId(zTab); /* Escaped name of the table */
- char **azCol = 0; /* List of escaped column names */
- int nCol = 0; /* Number of columns */
- int *aiFlg = 0; /* 0 if column is not part of PK */
- int *aiPk = 0; /* Column numbers for each PK column */
- int nPk = 0; /* Number of PRIMARY KEY columns */
- Str sql; /* SQL for the diff query */
- int i, k; /* Loop counters */
- const char *zSep; /* List separator */
-
- /* Check that the schemas of the two tables match. Exit early otherwise. */
- checkSchemasMatch(zTab);
-
- pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- nCol++;
- azCol = sqlite3_realloc(azCol, sizeof(char*)*nCol);
- if( azCol==0 ) runtimeError("out of memory");
- aiFlg = sqlite3_realloc(aiFlg, sizeof(int)*nCol);
- if( aiFlg==0 ) runtimeError("out of memory");
- azCol[nCol-1] = safeId((const char*)sqlite3_column_text(pStmt,1));
- aiFlg[nCol-1] = i = sqlite3_column_int(pStmt,5);
- if( i>0 ){
- if( i>nPk ){
- nPk = i;
- aiPk = sqlite3_realloc(aiPk, sizeof(int)*nPk);
- if( aiPk==0 ) runtimeError("out of memory");
- }
- aiPk[i-1] = nCol-1;
- }
- }
- sqlite3_finalize(pStmt);
- if( nPk==0 ) goto end_changeset_one_table;
- strInit(&sql);
- if( nCol>nPk ){
- strPrintf(&sql, "SELECT %d", SQLITE_UPDATE);
- for(i=0; i<nCol; i++){
- if( aiFlg[i] ){
- strPrintf(&sql, ",\n A.%s", azCol[i]);
- }else{
- strPrintf(&sql, ",\n A.%s IS NOT B.%s, A.%s, B.%s",
- azCol[i], azCol[i], azCol[i], azCol[i]);
- }
- }
- strPrintf(&sql,"\n FROM main.%s A, aux.%s B\n", zId, zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
- zSep = " AND";
- }
- zSep = "\n AND (";
- for(i=0; i<nCol; i++){
- if( aiFlg[i] ) continue;
- strPrintf(&sql, "%sA.%s IS NOT B.%s", zSep, azCol[i], azCol[i]);
- zSep = " OR\n ";
- }
- strPrintf(&sql,")\n UNION ALL\n");
- }
- strPrintf(&sql, "SELECT %d", SQLITE_DELETE);
- for(i=0; i<nCol; i++){
- if( aiFlg[i] ){
- strPrintf(&sql, ",\n A.%s", azCol[i]);
- }else{
- strPrintf(&sql, ",\n 1, A.%s, NULL", azCol[i]);
- }
- }
- strPrintf(&sql, "\n FROM main.%s A\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n UNION ALL\n");
- strPrintf(&sql, "SELECT %d", SQLITE_INSERT);
- for(i=0; i<nCol; i++){
- if( aiFlg[i] ){
- strPrintf(&sql, ",\n B.%s", azCol[i]);
- }else{
- strPrintf(&sql, ",\n 1, NULL, B.%s", azCol[i]);
- }
- }
- strPrintf(&sql, "\n FROM aux.%s B\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n");
- strPrintf(&sql, " ORDER BY");
- zSep = " ";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s %d", zSep, aiPk[i]+2);
- zSep = ",";
- }
- strPrintf(&sql, ";\n");
-
- if( g.fDebug & DEBUG_DIFF_SQL ){
- printf("SQL for %s:\n%s\n", zId, sql.z);
- goto end_changeset_one_table;
- }
-
- putc('T', out);
- putsVarint(out, (sqlite3_uint64)nCol);
- for(i=0; i<nCol; i++) putc(aiFlg[i], out);
- fwrite(zTab, 1, strlen(zTab), out);
- putc(0, out);
-
- pStmt = db_prepare("%s", sql.z);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- int iType = sqlite3_column_int(pStmt,0);
- putc(iType, out);
- putc(0, out);
- switch( sqlite3_column_int(pStmt,0) ){
- case SQLITE_UPDATE: {
- for(k=1, i=0; i<nCol; i++){
- if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
- k++;
- }else if( sqlite3_column_int(pStmt,k) ){
- putValue(out, sqlite3_column_value(pStmt,k+1));
- k += 3;
- }else{
- putc(0, out);
- k += 3;
- }
- }
- for(k=1, i=0; i<nCol; i++){
- if( aiFlg[i] ){
- putc(0, out);
- k++;
- }else if( sqlite3_column_int(pStmt,k) ){
- putValue(out, sqlite3_column_value(pStmt,k+2));
- k += 3;
- }else{
- putc(0, out);
- k += 3;
- }
- }
- break;
- }
- case SQLITE_INSERT: {
- for(k=1, i=0; i<nCol; i++){
- if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
- k++;
- }else{
- putValue(out, sqlite3_column_value(pStmt,k+2));
- k += 3;
- }
- }
- break;
- }
- case SQLITE_DELETE: {
- for(k=1, i=0; i<nCol; i++){
- if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
- k++;
- }else{
- putValue(out, sqlite3_column_value(pStmt,k+1));
- k += 3;
- }
- }
- break;
- }
- }
- }
- sqlite3_finalize(pStmt);
-
-end_changeset_one_table:
- while( nCol>0 ) sqlite3_free(azCol[--nCol]);
- sqlite3_free(azCol);
- sqlite3_free(aiPk);
- sqlite3_free(zId);
-}
-
-/*
-** Extract the next SQL keyword or quoted string from buffer zIn and copy it
-** (or a prefix of it if it will not fit) into buffer zBuf, size nBuf bytes.
-** Return a pointer to the character within zIn immediately following
-** the token or quoted string just extracted.
-*/
-const char *gobble_token(const char *zIn, char *zBuf, int nBuf){
- const char *p = zIn;
- char *pOut = zBuf;
- char *pEnd = &pOut[nBuf-1];
- char q = 0; /* quote character, if any */
-
- if( p==0 ) return 0;
- while( *p==' ' ) p++;
- switch( *p ){
- case '"': q = '"'; break;
- case '\'': q = '\''; break;
- case '`': q = '`'; break;
- case '[': q = ']'; break;
- }
-
- if( q ){
- p++;
- while( *p && pOut<pEnd ){
- if( *p==q ){
- p++;
- if( *p!=q ) break;
- }
- if( pOut<pEnd ) *pOut++ = *p;
- p++;
- }
- }else{
- while( *p && *p!=' ' && *p!='(' ){
- if( pOut<pEnd ) *pOut++ = *p;
- p++;
- }
- }
-
- *pOut = '\0';
- return p;
-}
-
-/*
-** This function is the implementation of SQL scalar function "module_name":
-**
-** module_name(SQL)
-**
-** The only argument should be an SQL statement of the type that may appear
-** in the sqlite_master table. If the statement is a "CREATE VIRTUAL TABLE"
-** statement, then the value returned is the name of the module that it
-** uses. Otherwise, if the statement is not a CVT, NULL is returned.
-*/
-static void module_name_func(
- sqlite3_context *pCtx,
- int nVal, sqlite3_value **apVal
-){
- const char *zSql;
- char zToken[32];
-
- assert( nVal==1 );
- zSql = (const char*)sqlite3_value_text(apVal[0]);
-
- zSql = gobble_token(zSql, zToken, sizeof(zToken));
- if( zSql==0 || sqlite3_stricmp(zToken, "create") ) return;
- zSql = gobble_token(zSql, zToken, sizeof(zToken));
- if( zSql==0 || sqlite3_stricmp(zToken, "virtual") ) return;
- zSql = gobble_token(zSql, zToken, sizeof(zToken));
- if( zSql==0 || sqlite3_stricmp(zToken, "table") ) return;
- zSql = gobble_token(zSql, zToken, sizeof(zToken));
- if( zSql==0 ) return;
- zSql = gobble_token(zSql, zToken, sizeof(zToken));
- if( zSql==0 || sqlite3_stricmp(zToken, "using") ) return;
- zSql = gobble_token(zSql, zToken, sizeof(zToken));
-
- sqlite3_result_text(pCtx, zToken, -1, SQLITE_TRANSIENT);
-}
-
-/*
-** Return the text of an SQL statement that itself returns the list of
-** tables to process within the database.
-*/
-const char *all_tables_sql(){
- if( g.bHandleVtab ){
- int rc;
-
- rc = sqlite3_exec(g.db,
- "CREATE TEMP TABLE tblmap(module COLLATE nocase, postfix);"
- "INSERT INTO temp.tblmap VALUES"
- "('fts3', '_content'), ('fts3', '_segments'), ('fts3', '_segdir'),"
-
- "('fts4', '_content'), ('fts4', '_segments'), ('fts4', '_segdir'),"
- "('fts4', '_docsize'), ('fts4', '_stat'),"
-
- "('fts5', '_data'), ('fts5', '_idx'), ('fts5', '_content'),"
- "('fts5', '_docsize'), ('fts5', '_config'),"
-
- "('rtree', '_node'), ('rtree', '_rowid'), ('rtree', '_parent');"
- , 0, 0, 0
- );
- assert( rc==SQLITE_OK );
-
- rc = sqlite3_create_function(
- g.db, "module_name", 1, SQLITE_UTF8, 0, module_name_func, 0, 0
- );
- assert( rc==SQLITE_OK );
-
- return
- "SELECT name FROM main.sqlite_master\n"
- " WHERE type='table' AND (\n"
- " module_name(sql) IS NULL OR \n"
- " module_name(sql) IN (SELECT module FROM temp.tblmap)\n"
- " ) AND name NOT IN (\n"
- " SELECT a.name || b.postfix \n"
- "FROM main.sqlite_master AS a, temp.tblmap AS b \n"
- "WHERE module_name(a.sql) = b.module\n"
- " )\n"
- "UNION \n"
- "SELECT name FROM aux.sqlite_master\n"
- " WHERE type='table' AND (\n"
- " module_name(sql) IS NULL OR \n"
- " module_name(sql) IN (SELECT module FROM temp.tblmap)\n"
- " ) AND name NOT IN (\n"
- " SELECT a.name || b.postfix \n"
- "FROM aux.sqlite_master AS a, temp.tblmap AS b \n"
- "WHERE module_name(a.sql) = b.module\n"
- " )\n"
- " ORDER BY name";
- }else{
- return
- "SELECT name FROM main.sqlite_master\n"
- " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
- " UNION\n"
- "SELECT name FROM aux.sqlite_master\n"
- " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
- " ORDER BY name";
- }
-}
-
-/*
-** Print sketchy documentation for this utility program
-*/
-static void showHelp(void){
- printf("Usage: %s [options] DB1 DB2\n", g.zArgv0);
- printf(
-"Output SQL text that would transform DB1 into DB2.\n"
-"Options:\n"
-" --changeset FILE Write a CHANGESET into FILE\n"
-" -L|--lib LIBRARY Load an SQLite extension library\n"
-" --primarykey Use schema-defined PRIMARY KEYs\n"
-" --rbu Output SQL to create/populate RBU table(s)\n"
-" --schema Show only differences in the schema\n"
-" --summary Show only a summary of the differences\n"
-" --table TAB Show only differences in table TAB\n"
-" --transaction Show SQL output inside a transaction\n"
-" --vtab Handle fts3, fts4, fts5 and rtree tables\n"
- );
-}
-
-int main(int argc, char **argv){
- const char *zDb1 = 0;
- const char *zDb2 = 0;
- int i;
- int rc;
- char *zErrMsg = 0;
- char *zSql;
- sqlite3_stmt *pStmt;
- char *zTab = 0;
- FILE *out = stdout;
- void (*xDiff)(const char*,FILE*) = diff_one_table;
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- int nExt = 0;
- char **azExt = 0;
-#endif
- int useTransaction = 0;
- int neverUseTransaction = 0;
-
- g.zArgv0 = argv[0];
- sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]=='-' ){
- z++;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"changeset")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- out = fopen(argv[++i], "wb");
- if( out==0 ) cmdlineError("cannot open: %s", argv[i]);
- xDiff = changeset_one_table;
- neverUseTransaction = 1;
- }else
- if( strcmp(z,"debug")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- g.fDebug = strtol(argv[++i], 0, 0);
- }else
- if( strcmp(z,"help")==0 ){
- showHelp();
- return 0;
- }else
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- if( strcmp(z,"lib")==0 || strcmp(z,"L")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- azExt = realloc(azExt, sizeof(azExt[0])*(nExt+1));
- if( azExt==0 ) cmdlineError("out of memory");
- azExt[nExt++] = argv[++i];
- }else
-#endif
- if( strcmp(z,"primarykey")==0 ){
- g.bSchemaPK = 1;
- }else
- if( strcmp(z,"rbu")==0 ){
- xDiff = rbudiff_one_table;
- }else
- if( strcmp(z,"schema")==0 ){
- g.bSchemaOnly = 1;
- }else
- if( strcmp(z,"summary")==0 ){
- xDiff = summarize_one_table;
- }else
- if( strcmp(z,"table")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- zTab = argv[++i];
- }else
- if( strcmp(z,"transaction")==0 ){
- useTransaction = 1;
- }else
- if( strcmp(z,"vtab")==0 ){
- g.bHandleVtab = 1;
- }else
- {
- cmdlineError("unknown option: %s", argv[i]);
- }
- }else if( zDb1==0 ){
- zDb1 = argv[i];
- }else if( zDb2==0 ){
- zDb2 = argv[i];
- }else{
- cmdlineError("unknown argument: %s", argv[i]);
- }
- }
- if( zDb2==0 ){
- cmdlineError("two database arguments required");
- }
- rc = sqlite3_open(zDb1, &g.db);
- if( rc ){
- cmdlineError("cannot open database file \"%s\"", zDb1);
- }
- rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_master", 0, 0, &zErrMsg);
- if( rc || zErrMsg ){
- cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb1);
- }
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- sqlite3_enable_load_extension(g.db, 1);
- for(i=0; i<nExt; i++){
- rc = sqlite3_load_extension(g.db, azExt[i], 0, &zErrMsg);
- if( rc || zErrMsg ){
- cmdlineError("error loading %s: %s", azExt[i], zErrMsg);
- }
- }
- free(azExt);
-#endif
- zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2);
- rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
- if( rc || zErrMsg ){
- cmdlineError("cannot attach database \"%s\"", zDb2);
- }
- rc = sqlite3_exec(g.db, "SELECT * FROM aux.sqlite_master", 0, 0, &zErrMsg);
- if( rc || zErrMsg ){
- cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb2);
- }
-
- if( neverUseTransaction ) useTransaction = 0;
- if( useTransaction ) fprintf(out, "BEGIN TRANSACTION;\n");
- if( xDiff==rbudiff_one_table ){
- fprintf(out, "CREATE TABLE IF NOT EXISTS rbu_count"
- "(tbl TEXT PRIMARY KEY COLLATE NOCASE, cnt INTEGER) "
- "WITHOUT ROWID;\n"
- );
- }
- if( zTab ){
- xDiff(zTab, out);
- }else{
- /* Handle tables one by one */
- pStmt = db_prepare("%s", all_tables_sql() );
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- xDiff((const char*)sqlite3_column_text(pStmt,0), out);
- }
- sqlite3_finalize(pStmt);
- }
- if( useTransaction ) printf("COMMIT;\n");
-
- /* TBD: Handle trigger differences */
- /* TBD: Handle view differences */
- sqlite3_close(g.db);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqlite3_analyzer.c.in b/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqlite3_analyzer.c.in
deleted file mode 100644
index e830521e08a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqlite3_analyzer.c.in
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-** Read an SQLite database file and analyze its space utilization. Generate
-** text on standard output.
-*/
-#define TCLSH_INIT_PROC sqlite3_analyzer_init_proc
-#define SQLITE_ENABLE_DBSTAT_VTAB 1
-#undef SQLITE_THREADSAFE
-#define SQLITE_THREADSAFE 0
-#undef SQLITE_ENABLE_COLUMN_METADATA
-#define SQLITE_OMIT_DECLTYPE 1
-#define SQLITE_OMIT_DEPRECATED 1
-#define SQLITE_OMIT_PROGRESS_CALLBACK 1
-#define SQLITE_OMIT_SHARED_CACHE 1
-#define SQLITE_DEFAULT_MEMSTATUS 0
-#define SQLITE_MAX_EXPR_DEPTH 0
-#define SQLITE_OMIT_LOAD_EXTENSION 1
-#ifndef USE_EXTERNAL_SQLITE
-INCLUDE sqlite3.c
-#endif
-INCLUDE $ROOT/src/tclsqlite.c
-
-const char *sqlite3_analyzer_init_proc(Tcl_Interp *interp){
- (void)interp;
- return
-BEGIN_STRING
-INCLUDE $ROOT/tool/spaceanal.tcl
-END_STRING
-;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqltclsh.c.in b/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqltclsh.c.in
deleted file mode 100644
index da354ee9357..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqltclsh.c.in
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-** This is the source code to a "tclsh" that has SQLite built-in.
-**
-** The startup script is located as follows:
-**
-** (1) Open the executable as an appended SQLite database and try to
-** read the startup script out of that database.
-**
-** (2) If the first argument is a readable file, try to open that file
-** as an SQLite database and read the startup script out of that
-** database.
-**
-** (3) If the first argument is a readable file with a ".tcl" extension,
-** then try to run that script directly.
-**
-** If none of the above steps work, then the program runs as an interactive
-** tclsh.
-*/
-#define TCLSH_INIT_PROC sqlite3_tclapp_init_proc
-#define SQLITE_ENABLE_DBSTAT_VTAB 1
-#undef SQLITE_THREADSAFE
-#define SQLITE_THREADSAFE 0
-#undef SQLITE_ENABLE_COLUMN_METADATA
-#define SQLITE_OMIT_DECLTYPE 1
-#define SQLITE_OMIT_DEPRECATED 1
-#define SQLITE_OMIT_PROGRESS_CALLBACK 1
-#define SQLITE_OMIT_SHARED_CACHE 1
-#define SQLITE_DEFAULT_MEMSTATUS 0
-#define SQLITE_MAX_EXPR_DEPTH 0
-INCLUDE sqlite3.c
-INCLUDE $ROOT/ext/misc/appendvfs.c
-#ifdef SQLITE_HAVE_ZLIB
-INCLUDE $ROOT/ext/misc/zipfile.c
-INCLUDE $ROOT/ext/misc/sqlar.c
-#endif
-INCLUDE $ROOT/src/tclsqlite.c
-
-const char *sqlite3_tclapp_init_proc(Tcl_Interp *interp){
- (void)interp;
- sqlite3_appendvfs_init(0,0,0);
-#ifdef SQLITE_HAVE_ZLIB
- sqlite3_auto_extension((void(*)(void))sqlite3_sqlar_init);
- sqlite3_auto_extension((void(*)(void))sqlite3_zipfile_init);
-#endif
-
- return
-BEGIN_STRING
-INCLUDE $ROOT/tool/sqltclsh.tcl
-END_STRING
-;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqltclsh.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqltclsh.tcl
deleted file mode 100644
index 6a4b1fe1f01..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/sqltclsh.tcl
+++ /dev/null
@@ -1,71 +0,0 @@
-# Try to open the executable as a database and read the "scripts.data"
-# field where "scripts.name" is 'main.tcl'
-#
-catch {
- if {![file exists $argv0] && [file exists $argv0.exe]} {
- append argv0 .exe
- }
- sqlite3 db $argv0 -vfs apndvfs -create 0
- set mainscript [db one {
- SELECT sqlar_uncompress(data,sz) FROM sqlar WHERE name='main.tcl'
- }]
-}
-if {[info exists mainscript]} {
- eval $mainscript
- return
-} else {
- catch {db close}
-}
-
-# Try to open file named in the first argument as a database and
-# read the "scripts.data" field where "scripts.name" is 'main.tcl'
-#
-if {[llength $argv]>0 && [file readable [lindex $argv 0]]} {
- catch {
- sqlite3 db [lindex $argv 0] -vfs apndvfs -create 0
- set mainscript [db one {SELECT data FROM scripts WHERE name='main.tcl'}]
- set argv0 [lindex $argv 0]
- set argv [lrange $argv 1 end]
- }
- if {[info exists mainscript]} {
- eval $mainscript
- return
- } else {
- catch {db close}
- }
- if {[string match *.tcl [lindex $argv 0]]} {
- set fd [open [lindex $argv 0] rb]
- set mainscript [read $fd]
- close $fd
- unset fd
- set argv0 [lindex $argv 0]
- set argv [lrange $argv 1 end]
- }
- if {[info exists mainscript]} {
- eval $mainscript
- return
- }
-}
-
-# If all else fails, do an interactive loop
-#
-set line {}
-while {![eof stdin]} {
- if {$line!=""} {
- puts -nonewline "> "
- } else {
- puts -nonewline "% "
- }
- flush stdout
- append line [gets stdin]
- if {[info complete $line]} {
- if {[catch {uplevel #0 $line} result]} {
- puts stderr "Error: $result"
- } elseif {$result!=""} {
- puts $result
- }
- set line {}
- } else {
- append line \\n"
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/srcck1.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/srcck1.c
deleted file mode 100644
index 20084ac47f1..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/srcck1.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
-** The program does some simple static analysis of the sqlite3.c source
-** file looking for mistakes.
-**
-** Usage:
-**
-** ./srcck1 sqlite3.c
-**
-** This program looks for instances of assert(), ALWAYS(), NEVER() or
-** testcase() that contain side-effects and reports errors if any such
-** instances are found.
-**
-** The aim of this utility is to prevent recurrences of errors such
-** as the one fixed at:
-**
-** https://www.sqlite.org/src/info/a2952231ac7abe16
-**
-** Note that another similar error was found by this utility when it was
-** first written. That other error was fixed by the same check-in that
-** committed the first version of this utility program.
-*/
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-
-/* Read the complete text of a file into memory. Return a pointer to
-** the result. Panic if unable to read the file or allocate memory.
-*/
-static char *readFile(const char *zFilename){
- FILE *in;
- char *z;
- long n;
- size_t got;
-
- in = fopen(zFilename, "rb");
- if( in==0 ){
- fprintf(stderr, "unable to open '%s' for reading\n", zFilename);
- exit(1);
- }
- fseek(in, 0, SEEK_END);
- n = ftell(in);
- rewind(in);
- z = malloc( n+1 );
- if( z==0 ){
- fprintf(stderr, "cannot allocate %d bytes to store '%s'\n",
- (int)(n+1), zFilename);
- exit(1);
- }
- got = fread(z, 1, n, in);
- fclose(in);
- if( got!=(size_t)n ){
- fprintf(stderr, "only read %d of %d bytes from '%s'\n",
- (int)got, (int)n, zFilename);
- exit(1);
- }
- z[n] = 0;
- return z;
-}
-
-/* Check the C code in the argument to see if it might have
-** side effects. The only accurate way to know this is to do a full
-** parse of the C code, which this routine does not do. This routine
-** uses a simple heuristic of looking for:
-**
-** * '=' not immediately after '>', '<', '!', or '='.
-** * '++'
-** * '--'
-**
-** If the code contains the phrase "side-effects-ok" is inside a
-** comment, then always return false. This is used to disable checking
-** for assert()s with deliberate side-effects, such as used by
-** SQLITE_TESTCTRL_ASSERT - a facility that allows applications to
-** determine at runtime whether or not assert()s are enabled.
-** Obviously, that determination cannot be made unless the assert()
-** has some side-effect.
-**
-** Return true if a side effect is seen. Return false if not.
-*/
-static int hasSideEffect(const char *z, unsigned int n){
- unsigned int i;
- for(i=0; i<n; i++){
- if( z[i]=='/' && strncmp(&z[i], "/*side-effects-ok*/", 19)==0 ) return 0;
- if( z[i]=='=' && i>0 && z[i-1]!='=' && z[i-1]!='>'
- && z[i-1]!='<' && z[i-1]!='!' && z[i+1]!='=' ) return 1;
- if( z[i]=='+' && z[i+1]=='+' ) return 1;
- if( z[i]=='-' && z[i+1]=='-' ) return 1;
- }
- return 0;
-}
-
-/* Return the number of bytes in string z[] prior to the first unmatched ')'
-** character.
-*/
-static unsigned int findCloseParen(const char *z){
- unsigned int nOpen = 0;
- unsigned i;
- for(i=0; z[i]; i++){
- if( z[i]=='(' ) nOpen++;
- if( z[i]==')' ){
- if( nOpen==0 ) break;
- nOpen--;
- }
- }
- return i;
-}
-
-/* Search for instances of assert(...), ALWAYS(...), NEVER(...), and/or
-** testcase(...) where the argument contains side effects.
-**
-** Print error messages whenever a side effect is found. Return the number
-** of problems seen.
-*/
-static unsigned int findAllSideEffects(const char *z){
- unsigned int lineno = 1; /* Line number */
- unsigned int i;
- unsigned int nErr = 0;
- char c, prevC = 0;
- for(i=0; (c = z[i])!=0; prevC=c, i++){
- if( c=='\n' ){ lineno++; continue; }
- if( isalpha(c) && !isalpha(prevC) ){
- if( strncmp(&z[i],"assert(",7)==0
- || strncmp(&z[i],"ALWAYS(",7)==0
- || strncmp(&z[i],"NEVER(",6)==0
- || strncmp(&z[i],"testcase(",9)==0
- ){
- unsigned int n;
- const char *z2 = &z[i+5];
- while( z2[0]!='(' ){ z2++; }
- z2++;
- n = findCloseParen(z2);
- if( hasSideEffect(z2, n) ){
- nErr++;
- fprintf(stderr, "side-effect line %u: %.*s\n", lineno,
- (int)(&z2[n+1] - &z[i]), &z[i]);
- }
- }
- }
- }
- return nErr;
-}
-
-int main(int argc, char **argv){
- char *z;
- unsigned int nErr = 0;
- if( argc!=2 ){
- fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
- return 1;
- }
- z = readFile(argv[1]);
- nErr = findAllSideEffects(z);
- free(z);
- if( nErr ){
- fprintf(stderr, "Found %u undesirable side-effects\n", nErr);
- return 1;
- }
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/stack_usage.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/stack_usage.tcl
deleted file mode 100644
index b3574f026e0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/stack_usage.tcl
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Parse the output of
-#
-# objdump -d sqlite3.o
-#
-# for x64 and generate a report showing:
-#
-# (1) Stack used by each function
-# (2) Recursion paths and their aggregate stack depth
-#
-set getStack 0
-while {![eof stdin]} {
- set line [gets stdin]
- if {[regexp {^[0-9a-f]+ <([^>]+)>:\s*$} $line all procname]} {
- set curfunc $procname
- set root($curfunc) 1
- set calls($curfunc) {}
- set calledby($curfunc) {}
- set recursive($curfunc) {}
- set stkdepth($curfunc) 0
- set getStack 1
- continue
- }
- if {[regexp {callq? +[0-9a-z]+ <([^>]+)>} $line all other]} {
- set key [list $curfunc $other]
- set callpair($key) 1
- unset -nocomplain root($curfunc)
- continue
- }
- if {[regexp {sub +\$(0x[0-9a-z]+),%[er]sp} $line all xdepth]} {
- if {$getStack} {
- scan $xdepth %x depth
- set stkdepth($curfunc) $depth
- set getStack 0
- }
- continue
- }
-}
-
-puts "****************** Stack Usage By Function ********************"
-set sdlist {}
-foreach f [array names stkdepth] {
- lappend sdlist [list $stkdepth($f) $f]
-}
-foreach sd [lsort -integer -decr -index 0 $sdlist] {
- foreach {depth fname} $sd break
- puts [format {%6d %s} $depth $fname]
-}
-
-puts "****************** Stack Usage By Recursion *******************"
-foreach key [array names callpair] {
- foreach {from to} $key break
- lappend calls($from) $to
- # lappend calledby($to) $from
-}
-proc all_descendents {root} {
- global calls recursive
- set todo($root) $root
- set go 1
- while {$go} {
- set go 0
- foreach f [array names todo] {
- set path $todo($f)
- unset todo($f)
- if {![info exists calls($f)]} continue
- foreach x $calls($f) {
- if {$x==$root} {
- lappend recursive($root) [concat $path $root]
- } elseif {![info exists d($x)]} {
- set go 1
- set todo($x) [concat $path $x]
- set d($x) 1
- }
- }
- }
- }
- return [array names d]
-}
-set pathlist {}
-foreach f [array names recursive] {
- all_descendents $f
- foreach m $recursive($f) {
- set depth 0
- foreach b [lrange $m 0 end-1] {
- set depth [expr {$depth+$stkdepth($b)}]
- }
- lappend pathlist [list $depth $m]
- }
-}
-foreach path [lsort -integer -decr -index 0 $pathlist] {
- foreach {depth m} $path break
- set first [lindex $m 0]
- puts [format {%6d %s %d} $depth $first $stkdepth($first)]
- foreach b [lrange $m 1 end] {
- puts " $b $stkdepth($b)"
- }
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/symbols-mingw.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/symbols-mingw.sh
deleted file mode 100644
index bf93eec7c6b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/symbols-mingw.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-#
-# Run this script in a directory that contains a valid SQLite makefile in
-# order to verify that unintentionally exported symbols.
-#
-make sqlite3.c
-
-echo '****** Exported symbols from a build including RTREE && FTS4 ******'
-gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- sqlite3.c
-nm sqlite3.o | grep " [TD] "
-
-echo '****** Surplus symbols from a build including RTREE & FTS4 ******'
-nm sqlite3.o | grep " [TD] " | grep -v " .*sqlite3_"
-
-echo '****** Dependencies of the core. No extensions. No OS interface *******'
-gcc -c -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- -DSQLITE_OS_OTHER -DSQLITE_THREADSAFE=0 \
- sqlite3.c
-nm sqlite3.o | grep " U "
-
-echo '****** Dependencies including RTREE & FTS4 *******'
-gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- sqlite3.c
-nm sqlite3.o | grep " U "
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/symbols.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/symbols.sh
deleted file mode 100644
index 5e80078fa33..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/symbols.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-#
-# Run this script in a directory that contains a valid SQLite makefile in
-# order to verify that unintentionally exported symbols.
-#
-make sqlite3.c
-
-echo '****** Exported symbols from a build including RTREE, FTS4 & ICU ******'
-gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- -DSQLITE_ENABLE_ICU -DSQLITE_ENABLE_PREUPDATE_HOOK -DSQLITE_ENABLE_SESSION \
- sqlite3.c
-nm sqlite3.o | grep ' [TD] ' | sort -k 3
-
-echo '****** Surplus symbols from a build including RTREE, FTS4 & ICU ******'
-nm sqlite3.o | grep ' [TD] ' | grep -v ' .*sqlite3_'
-
-echo '****** Dependencies of the core. No extensions. No OS interface *******'
-gcc -c -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- -DSQLITE_OS_OTHER -DSQLITE_THREADSAFE=0 \
- sqlite3.c
-nm sqlite3.o | grep ' U ' | sort -k 3
-
-echo '****** Dependencies including RTREE & FTS4 *******'
-gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- sqlite3.c
-nm sqlite3.o | grep ' U ' | sort -k 3
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/varint.c b/chromium/third_party/sqlite/sqlite-src-3240000/tool/varint.c
deleted file mode 100644
index f4a51118b4d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/varint.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-** A utility program to translate SQLite varints into decimal and decimal
-** integers into varints.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef __int64 i64;
- typedef unsigned __int64 u64;
-#else
- typedef long long int i64;
- typedef unsigned long long int u64;
-#endif
-
-static int hexValue(char c){
- if( c>='0' && c<='9' ) return c - '0';
- if( c>='a' && c<='f' ) return c - 'a' + 10;
- if( c>='A' && c<='F' ) return c - 'A' + 10;
- return -1;
-}
-
-static char toHex(unsigned char c){
- return "0123456789abcdef"[c&0xf];
-}
-
-static int putVarint(unsigned char *p, u64 v){
- int i, j, n;
- unsigned char buf[10];
- if( v & (((u64)0xff000000)<<32) ){
- p[8] = (unsigned char)v;
- v >>= 8;
- for(i=7; i>=0; i--){
- p[i] = (unsigned char)((v & 0x7f) | 0x80);
- v >>= 7;
- }
- return 9;
- }
- n = 0;
- do{
- buf[n++] = (unsigned char)((v & 0x7f) | 0x80);
- v >>= 7;
- }while( v!=0 );
- buf[0] &= 0x7f;
- for(i=0, j=n-1; j>=0; j--, i++){
- p[i] = buf[j];
- }
- return n;
-}
-
-
-int main(int argc, char **argv){
- int i;
- u64 x;
- u64 uX = 0;
- i64 iX;
- int n;
- unsigned char zHex[20];
-
- if( argc==1 ){
- fprintf(stderr,
- "Usage:\n"
- " %s HH HH HH ... Convert varint to decimal\n"
- " %s DDDDD Convert decimal to varint\n"
- " Add '+' or '-' before DDDDD to disambiguate.\n",
- argv[0], argv[0]);
- exit(1);
- }
- if( argc>2
- || (strlen(argv[1])==2 && hexValue(argv[1][0])>=0 && hexValue(argv[1][1])>=0)
- ){
- /* Hex to decimal */
- for(i=1; i<argc && i<9; i++){
- if( strlen(argv[i])!=2 ){
- fprintf(stderr, "Not a hex byte: %s\n", argv[i]);
- exit(1);
- }
- x = (hexValue(argv[i][0])<<4) + hexValue(argv[i][1]);
- uX = (uX<<7) + (x&0x7f);
- if( (x&0x80)==0 ) break;
- }
- if( i==9 && i<argc ){
- if( strlen(argv[i])!=2 ){
- fprintf(stderr, "Not a hex byte: %s\n", argv[i]);
- exit(1);
- }
- x = (hexValue(argv[i][0])<<4) + hexValue(argv[i][1]);
- uX = (uX<<8) + x;
- }
- i++;
- if( i<argc ){
- fprintf(stderr, "Extra arguments: %s...\n", argv[i]);
- exit(1);
- }
- }else{
- char *z = argv[1];
- int sign = 1;
- if( z[0]=='+' ) z++;
- else if( z[0]=='-' ){ z++; sign = -1; }
- uX = 0;
- while( z[0] ){
- if( z[0]<'0' || z[0]>'9' ){
- fprintf(stderr, "Not a decimal number: %s", argv[1]);
- exit(1);
- }
- uX = uX*10 + z[0] - '0';
- z++;
- }
- if( sign<0 ){
- memcpy(&iX, &uX, 8);
- iX = -iX;
- memcpy(&uX, &iX, 8);
- }
- }
- n = putVarint(zHex, uX);
- printf("%lld =", (i64)uX);
- for(i=0; i<n; i++){
- printf(" %c%c", toHex(zHex[i]>>4), toHex(zHex[i]&0x0f));
- }
- printf("\n");
- return 0;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/vdbe-compress.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/vdbe-compress.tcl
deleted file mode 100644
index 9477f4afe62..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/vdbe-compress.tcl
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/tcl
-#
-# This script makes modifications to the vdbe.c source file which reduce
-# the amount of stack space required by the sqlite3VdbeExec() routine.
-#
-# The modifications performed by this script are optional. The vdbe.c
-# source file will compile correctly with and without the modifications
-# performed by this script. And all routines within vdbe.c will compute
-# the same result. The modifications made by this script merely help
-# the C compiler to generate code for sqlite3VdbeExec() that uses less
-# stack space.
-#
-# Script usage:
-#
-# mv vdbe.c vdbe.c.template
-# tclsh vdbe-compress.tcl $CFLAGS <vdbe.c.template >vdbe.c
-#
-# Modifications made:
-#
-# All modifications are within the sqlite3VdbeExec() function. The
-# modifications seek to reduce the amount of stack space allocated by
-# this routine by moving local variable declarations out of individual
-# opcode implementations and into a single large union. The union contains
-# a separate structure for each opcode and that structure contains the
-# local variables used by that opcode. In this way, the total amount
-# of stack space required by sqlite3VdbeExec() is reduced from the
-# sum of all local variables to the maximum of the local variable space
-# required for any single opcode.
-#
-# In order to be recognized by this script, local variables must appear
-# on the first line after the open curly-brace that begins a new opcode
-# implementation. Local variables must not have initializers, though they
-# may be commented.
-#
-# The union definition is inserted in place of a special marker comment
-# in the preamble to the sqlite3VdbeExec() implementation.
-#
-#############################################################################
-#
-set beforeUnion {} ;# C code before union
-set unionDef {} ;# C code of the union
-set afterUnion {} ;# C code after the union
-set sCtr 0 ;# Context counter
-
-# If the SQLITE_SMALL_STACK compile-time option is missing, then
-# this transformation becomes a no-op.
-#
-if {![regexp {SQLITE_SMALL_STACK} $argv]} {
- while {![eof stdin]} {
- puts [gets stdin]
- }
- exit
-}
-
-# Read program text up to the spot where the union should be
-# inserted.
-#
-while {![eof stdin]} {
- set line [gets stdin]
- if {[regexp {INSERT STACK UNION HERE} $line]} break
- append beforeUnion $line\n
-}
-
-# Process the remaining text. Build up the union definition as we go.
-#
-set vlist {}
-set seenDecl 0
-set namechars {abcdefghijklmnopqrstuvwxyz}
-set nnc [string length $namechars]
-while {![eof stdin]} {
- set line [gets stdin]
- if {[regexp "^case (OP_\\w+): \173" $line all operator]} {
- append afterUnion $line\n
- set vlist {}
- while {![eof stdin]} {
- set line [gets stdin]
- if {[regexp {^ +(const )?\w+ \**(\w+)(\[.*\])?;} $line \
- all constKeyword vname notused1]} {
- if {!$seenDecl} {
- set sname {}
- append sname [string index $namechars [expr {$sCtr/$nnc}]]
- append sname [string index $namechars [expr {$sCtr%$nnc}]]
- incr sCtr
- append unionDef " struct ${operator}_stack_vars \173\n"
- append afterUnion \
- "#if 0 /* local variables moved into u.$sname */\n"
- set seenDecl 1
- }
- append unionDef " $line\n"
- append afterUnion $line\n
- lappend vlist $vname
- } elseif {[regexp {^#(if|endif)} $line] && [llength $vlist]>0} {
- append unionDef "$line\n"
- append afterUnion $line\n
- } else {
- break
- }
- }
- if {$seenDecl} {
- append unionDef " \175 $sname;\n"
- append afterUnion "#endif /* local variables moved into u.$sname */\n"
- }
- set seenDecl 0
- }
- if {[regexp "^\175" $line]} {
- append afterUnion $line\n
- set vlist {}
- } elseif {[llength $vlist]>0} {
- append line " "
- foreach v $vlist {
- regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
- regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
-
- # The expressions above fail to catch instance of variable "abc" in
- # expressions like (32>abc). The following expression makes those
- # substitutions.
- regsub -all "(\[^-\])>${v}(\\W)" $line "\\1>u.$sname.$v\\2" line
- }
- append afterUnion [string trimright $line]\n
- } elseif {$line=="" && [eof stdin]} {
- # no-op
- } else {
- append afterUnion $line\n
- }
-}
-
-# Output the resulting text.
-#
-puts -nonewline $beforeUnion
-puts " /********************************************************************"
-puts " ** Automatically generated code"
-puts " **"
-puts " ** The following union is automatically generated by the"
-puts " ** vdbe-compress.tcl script. The purpose of this union is to"
-puts " ** reduce the amount of stack space required by this function."
-puts " ** See comments in the vdbe-compress.tcl script for details."
-puts " */"
-puts " union vdbeExecUnion \173"
-puts -nonewline $unionDef
-puts " \175 u;"
-puts " /* End automatically generated code"
-puts " ********************************************************************/"
-puts -nonewline $afterUnion
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/vdbe_profile.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/tool/vdbe_profile.tcl
deleted file mode 100644
index a0dc99ec33a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/vdbe_profile.tcl
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/tclsh
-#
-# SUMMARY:
-# Run this script in the same directory as the "vdbe_profile.out" file.
-# This script summarizes the results contained in that file.
-#
-# DETAILS:
-# Compile SQLite using the -DVDBE_PROFILE option on Linux. This causes
-# performance information about individual VDBE operations to be appended
-# to the "vdbe_profile.out" file. After content has been accumulated in
-# vdbe_profile.out, run this script to analyze the output and generate a
-# report.
-#
-if {![file readable vdbe_profile.out]} {
- error "run this script in the same directory as the vdbe_profile.out file"
-}
-set in [open vdbe_profile.out r]
-set stmt {}
-set allstmt {}
-while {![eof $in]} {
- set line [gets $in]
- if {$line==""} continue
- if {[regexp {^---- } $line]} {
- set stmt [lindex $line 1]
- if {[info exists cnt($stmt)]} {
- incr cnt($stmt)
- set firsttime 0
- } else {
- set cnt($stmt) 1
- set sql($stmt) {}
- set firsttime 1
- lappend allstmt $stmt
- }
- continue;
- }
- if {[regexp {^-- } $line]} {
- if {$firsttime} {
- append sql($stmt) [string range $line 3 end]\n
- }
- continue
- }
- if {![regexp {^ *\d+ *\d+ *\d+ *\d+ ([A-Z].*)} $line all detail]} continue
- set c [lindex $line 0]
- set t [lindex $line 1]
- set addr [lindex $line 3]
- set op [lindex $line 4]
- if {[info exists opcnt($op)]} {
- incr opcnt($op) $c
- incr opcycle($op) $t
- } else {
- set opcnt($op) $c
- set opcycle($op) $t
- }
- if {[info exists stat($stmt,$addr)]} {
- foreach {cx tx detail} $stat($stmt,$addr) break
- incr cx $c
- incr tx $t
- set stat($stmt,$addr) [list $cx $tx $detail]
- } else {
- set stat($stmt,$addr) [list $c $t $detail]
- }
-}
-close $in
-
-foreach stmt $allstmt {
- puts "********************************************************************"
- puts [string trim $sql($stmt)]
- puts "Execution count: $cnt($stmt)"
- for {set i 0} {[info exists stat($stmt,$i)]} {incr i} {
- foreach {cx tx detail} $stat($stmt,$i) break
- if {$cx==0} {
- set ax 0
- } else {
- set ax [expr {$tx/$cx}]
- }
- puts [format {%8d %12d %12d %4d %s} $cx $tx $ax $i $detail]
- }
-}
-puts "********************************************************************"
-puts "OPCODES:"
-foreach op [lsort [array names opcnt]] {
- set cx $opcnt($op)
- set tx $opcycle($op)
- if {$cx==0} {
- set ax 0
- } else {
- set ax [expr {$tx/$cx}]
- }
- puts [format {%8d %12d %12d %s} $cx $tx $ax $op]
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/warnings-clang.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/warnings-clang.sh
deleted file mode 100644
index 6dcc086d2f6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/warnings-clang.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#/bin/sh
-#
-# Run this script in a directory with a working makefile to check for
-# compiler warnings in SQLite.
-#
-rm -f sqlite3.c shell.c
-make sqlite3.c shell.c
-echo '************* FTS4 and RTREE ****************'
-scan-build gcc -c -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_DEBUG -DSQLITE_ENABLE_STAT3 sqlite3.c 2>&1 | grep -v 'ANALYZE:'
-echo '********** ENABLE_STAT3. THREADSAFE=0 *******'
-scan-build gcc -c -I. -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \
- -DSQLITE_DEBUG \
- sqlite3.c shell.c -ldl 2>&1 | grep -v 'ANALYZE:'
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/warnings.sh b/chromium/third_party/sqlite/sqlite-src-3240000/tool/warnings.sh
deleted file mode 100644
index e9ffad44e07..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/warnings.sh
+++ /dev/null
@@ -1,60 +0,0 @@
-#/bin/sh
-#
-# Run this script in a directory with a working makefile to check for
-# compiler warnings in SQLite.
-#
-
-if uname | grep -i openbsd ; then
- # Use these for testing on OpenBSD:
- WARNING_OPTS=-Wall
- WARNING_ANDROID_OPTS=-Wall
-else
- # Use these for testing on Linux and Mac OSX:
- WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long"
- WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra"
-fi
-
-rm -f sqlite3.c
-make sqlite3.c
-echo '********** No optimizations. Includes FTS4/5, RTREE, JSON1 ***'
-echo '********** ' Options: $WARNING_OPTS
-gcc -c $WARNING_OPTS -std=c89 \
- -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
- sqlite3.c
-if test x`uname` = 'xLinux'; then
-echo '********** Android configuration ******************************'
-echo '********** ' Options: $WARNING_ANDROID_OPTS
-gcc -c \
- -DHAVE_USLEEP=1 \
- -DSQLITE_HAVE_ISNAN \
- -DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \
- -DSQLITE_THREADSAFE=2 \
- -DSQLITE_TEMP_STORE=3 \
- -DSQLITE_POWERSAFE_OVERWRITE=1 \
- -DSQLITE_DEFAULT_FILE_FORMAT=4 \
- -DSQLITE_DEFAULT_AUTOVACUUM=1 \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 \
- -DSQLITE_ENABLE_FTS3 \
- -DSQLITE_ENABLE_FTS3_BACKWARDS \
- -DSQLITE_ENABLE_FTS4 \
- -DSQLITE_OMIT_BUILTIN_TEST \
- -DSQLITE_OMIT_COMPILEOPTION_DIAGS \
- -DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 \
- -DSQLITE_ENABLE_ICU \
- -DUSE_PREAD64 \
- $WARNING_ANDROID_OPTS \
- -Os sqlite3.c shell.c
-fi
-echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
-echo '********** ' Options: $WARNING_OPTS
-gcc -c $WARNING_OPTS -std=c89 \
- -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
- sqlite3.c
-echo '********** Optimized -O3. Includes FTS4/5, RTREE, JSON1 ******'
-echo '********** ' Options: $WARNING_OPTS
-gcc -O3 -c $WARNING_OPTS -std=c89 \
- -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
- sqlite3.c
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/tool/win/sqlite.vsix b/chromium/third_party/sqlite/sqlite-src-3240000/tool/win/sqlite.vsix
deleted file mode 100644
index 1450011266b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/tool/win/sqlite.vsix
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml
deleted file mode 100644
index 80889024ca6..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml
+++ /dev/null
@@ -1,8 +0,0 @@
-<Application
- x:Class="vsixtest.App"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="using:vsixtest"
- RequestedTheme="Light">
-
-</Application>
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml.cpp b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml.cpp
deleted file mode 100644
index da8f327fa02..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-//
-// App.xaml.cpp
-// Implementation of the App class.
-//
-
-#include "pch.h"
-#include "MainPage.xaml.h"
-
-using namespace vsixtest;
-
-using namespace Platform;
-using namespace Windows::ApplicationModel;
-using namespace Windows::ApplicationModel::Activation;
-using namespace Windows::Foundation;
-using namespace Windows::Foundation::Collections;
-using namespace Windows::UI::Xaml;
-using namespace Windows::UI::Xaml::Controls;
-using namespace Windows::UI::Xaml::Controls::Primitives;
-using namespace Windows::UI::Xaml::Data;
-using namespace Windows::UI::Xaml::Input;
-using namespace Windows::UI::Xaml::Interop;
-using namespace Windows::UI::Xaml::Media;
-using namespace Windows::UI::Xaml::Navigation;
-
-/// <summary>
-/// Initializes the singleton application object. This is the first line of authored code
-/// executed, and as such is the logical equivalent of main() or WinMain().
-/// </summary>
-App::App()
-{
- InitializeComponent();
- Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
-}
-
-/// <summary>
-/// Invoked when the application is launched normally by the end user. Other entry points
-/// will be used such as when the application is launched to open a specific file.
-/// </summary>
-/// <param name="e">Details about the launch request and process.</param>
-void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e)
-{
-
-#if _DEBUG
- // Show graphics profiling information while debugging.
- if (IsDebuggerPresent())
- {
- // Display the current frame rate counters
- DebugSettings->EnableFrameRateCounter = true;
- }
-#endif
-
- auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content);
-
- // Do not repeat app initialization when the Window already has content,
- // just ensure that the window is active
- if (rootFrame == nullptr)
- {
- // Create a Frame to act as the navigation context and associate it with
- // a SuspensionManager key
- rootFrame = ref new Frame();
-
- rootFrame->NavigationFailed += ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(this, &App::OnNavigationFailed);
-
- if (e->PreviousExecutionState == ApplicationExecutionState::Terminated)
- {
- // TODO: Restore the saved session state only when appropriate, scheduling the
- // final launch steps after the restore is complete
-
- }
-
- if (rootFrame->Content == nullptr)
- {
- // When the navigation stack isn't restored navigate to the first page,
- // configuring the new page by passing required information as a navigation
- // parameter
- rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments);
- }
- // Place the frame in the current Window
- Window::Current->Content = rootFrame;
- // Ensure the current window is active
- Window::Current->Activate();
- }
- else
- {
- if (rootFrame->Content == nullptr)
- {
- // When the navigation stack isn't restored navigate to the first page,
- // configuring the new page by passing required information as a navigation
- // parameter
- rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments);
- }
- // Ensure the current window is active
- Window::Current->Activate();
- }
-}
-
-/// <summary>
-/// Invoked when application execution is being suspended. Application state is saved
-/// without knowing whether the application will be terminated or resumed with the contents
-/// of memory still intact.
-/// </summary>
-/// <param name="sender">The source of the suspend request.</param>
-/// <param name="e">Details about the suspend request.</param>
-void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)
-{
- (void) sender; // Unused parameter
- (void) e; // Unused parameter
-
- //TODO: Save application state and stop any background activity
-}
-
-/// <summary>
-/// Invoked when Navigation to a certain page fails
-/// </summary>
-/// <param name="sender">The Frame which failed navigation</param>
-/// <param name="e">Details about the navigation failure</param>
-void App::OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e)
-{
- throw ref new FailureException("Failed to load Page " + e->SourcePageType.Name);
-} \ No newline at end of file
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml.h b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml.h
deleted file mode 100644
index 5fa8837d38e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/App.xaml.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// App.xaml.h
-// Declaration of the App class.
-//
-
-#pragma once
-
-#include "App.g.h"
-
-namespace vsixtest
-{
- /// <summary>
- /// Provides application-specific behavior to supplement the default Application class.
- /// </summary>
- ref class App sealed
- {
- protected:
- virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override;
-
- internal:
- App();
-
- private:
- void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e);
- void OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e);
- };
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/LockScreenLogo.scale-200.png b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/LockScreenLogo.scale-200.png
deleted file mode 100644
index 735f57adb5d..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/LockScreenLogo.scale-200.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/SplashScreen.scale-200.png b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/SplashScreen.scale-200.png
deleted file mode 100644
index 023e7f1feda..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/SplashScreen.scale-200.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square150x150Logo.scale-200.png b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square150x150Logo.scale-200.png
deleted file mode 100644
index af49fec1a54..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square150x150Logo.scale-200.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square44x44Logo.scale-200.png b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square44x44Logo.scale-200.png
deleted file mode 100644
index ce342a2ec8a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square44x44Logo.scale-200.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
deleted file mode 100644
index f6c02ce97e0..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/StoreLogo.png b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/StoreLogo.png
deleted file mode 100644
index 7385b56c0e4..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/StoreLogo.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Wide310x150Logo.scale-200.png b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Wide310x150Logo.scale-200.png
deleted file mode 100644
index 288995b397f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Assets/Wide310x150Logo.scale-200.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml
deleted file mode 100644
index 7472ad86267..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml
+++ /dev/null
@@ -1,13 +0,0 @@
-<Page
- x:Class="vsixtest.MainPage"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="using:vsixtest"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d">
-
- <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
-
- </Grid>
-</Page>
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml.cpp b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml.cpp
deleted file mode 100644
index e67dcb83b23..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// MainPage.xaml.cpp
-// Implementation of the MainPage class.
-//
-
-#include "pch.h"
-#include "MainPage.xaml.h"
-#include "sqlite3.h"
-
-using namespace vsixtest;
-
-using namespace Platform;
-using namespace Windows::Foundation;
-using namespace Windows::Foundation::Collections;
-using namespace Windows::UI::Xaml;
-using namespace Windows::UI::Xaml::Controls;
-using namespace Windows::UI::Xaml::Controls::Primitives;
-using namespace Windows::UI::Xaml::Data;
-using namespace Windows::UI::Xaml::Input;
-using namespace Windows::UI::Xaml::Media;
-using namespace Windows::UI::Xaml::Navigation;
-
-// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
-
-MainPage::MainPage()
-{
- InitializeComponent();
- UseSQLite();
-}
-
-void MainPage::UseSQLite(void)
-{
- int rc = SQLITE_OK;
- sqlite3 *pDb = nullptr;
-
- rc = sqlite3_open_v2("test.db", &pDb,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
-
- if (rc != SQLITE_OK)
- throw ref new FailureException("Failed to open database.");
-
- rc = sqlite3_exec(pDb, "VACUUM;", nullptr, nullptr, nullptr);
-
- if (rc != SQLITE_OK)
- throw ref new FailureException("Failed to vacuum database.");
-
- rc = sqlite3_close(pDb);
-
- if (rc != SQLITE_OK)
- throw ref new FailureException("Failed to close database.");
-
- pDb = nullptr;
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml.h b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml.h
deleted file mode 100644
index ea327a3e4c5..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/MainPage.xaml.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// MainPage.xaml.h
-// Declaration of the MainPage class.
-//
-
-#pragma once
-
-#include "MainPage.g.h"
-
-namespace vsixtest
-{
- /// <summary>
- /// An empty page that can be used on its own or navigated to within a Frame.
- /// </summary>
- public ref class MainPage sealed
- {
- public:
- MainPage();
- void UseSQLite(void);
-
- };
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Package.appxmanifest b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Package.appxmanifest
deleted file mode 100644
index 106b3f1e412..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/Package.appxmanifest
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<Package
- xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
- xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
- xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
- IgnorableNamespaces="uap mp">
-
- <Identity
- Name="bb52b3e1-5c8a-4516-a5ff-8b9f9baadef7"
- Publisher="CN=mistachkin"
- Version="1.0.0.0" />
-
- <mp:PhoneIdentity PhoneProductId="bb52b3e1-5c8a-4516-a5ff-8b9f9baadef7" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
-
- <Properties>
- <DisplayName>vsixtest</DisplayName>
- <PublisherDisplayName>mistachkin</PublisherDisplayName>
- <Logo>Assets\StoreLogo.png</Logo>
- </Properties>
-
- <Dependencies>
- <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
- </Dependencies>
-
- <Resources>
- <Resource Language="x-generate"/>
- </Resources>
-
- <Applications>
- <Application Id="App"
- Executable="$targetnametoken$.exe"
- EntryPoint="vsixtest.App">
- <uap:VisualElements
- DisplayName="vsixtest"
- Square150x150Logo="Assets\Square150x150Logo.png"
- Square44x44Logo="Assets\Square44x44Logo.png"
- Description="vsixtest"
- BackgroundColor="transparent">
- <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
- <uap:SplashScreen Image="Assets\SplashScreen.png" />
- </uap:VisualElements>
- </Application>
- </Applications>
-
- <Capabilities>
- <Capability Name="internetClient" />
- </Capabilities>
-</Package> \ No newline at end of file
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/pch.cpp b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/pch.cpp
deleted file mode 100644
index 97b544ec11b..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/pch.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-//
-// pch.cpp
-// Include the standard header and generate the precompiled header.
-//
-
-#include "pch.h"
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/pch.h b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/pch.h
deleted file mode 100644
index b793236d02a..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/pch.h
+++ /dev/null
@@ -1,11 +0,0 @@
-//
-// pch.h
-// Header for standard system include files.
-//
-
-#pragma once
-
-#include <collection.h>
-#include <ppltasks.h>
-
-#include "App.xaml.h"
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.sln b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.sln
deleted file mode 100644
index 1ab6e064f97..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.sln
+++ /dev/null
@@ -1,39 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.24720.0
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vsixtest", "vsixtest.vcxproj", "{60BB14A5-0871-4656-BC38-4F0958230F9A}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|ARM = Debug|ARM
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|ARM = Release|ARM
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.ActiveCfg = Debug|ARM
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.Build.0 = Debug|ARM
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.Deploy.0 = Debug|ARM
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.ActiveCfg = Debug|x64
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.Build.0 = Debug|x64
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.Deploy.0 = Debug|x64
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.ActiveCfg = Debug|Win32
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.Build.0 = Debug|Win32
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.Deploy.0 = Debug|Win32
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.ActiveCfg = Release|ARM
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.Build.0 = Release|ARM
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.Deploy.0 = Release|ARM
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.ActiveCfg = Release|x64
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.Build.0 = Release|x64
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.Deploy.0 = Release|x64
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.ActiveCfg = Release|Win32
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.Build.0 = Release|Win32
- {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.Deploy.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.tcl b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.tcl
deleted file mode 100644
index 5dce821dc4e..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.tcl
+++ /dev/null
@@ -1,373 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script is used to quickly test a VSIX (Visual Studio Extension) file
-# with Visual Studio 2015 on Windows.
-#
-# PREREQUISITES
-#
-# 1. This tool is Windows only.
-#
-# 2. This tool must be executed with "elevated administrator" privileges.
-#
-# 3. Tcl 8.4 and later are supported, earlier versions have not been tested.
-#
-# 4. The "sqlite-UWP-output.vsix" file is assumed to exist in the parent
-# directory of the directory containing this script. The [optional] first
-# command line argument to this script may be used to specify an alternate
-# file. However, currently, the file must be compatible with both Visual
-# Studio 2015 and the Universal Windows Platform.
-#
-# 5. The "VERSION" file is assumed to exist in the parent directory of the
-# directory containing this script. It must contain a version number that
-# matches the VSIX file being tested.
-#
-# 6. The temporary directory specified in the TEMP or TMP environment variables
-# must refer to an existing directory writable by the current user.
-#
-# 7. The VS140COMNTOOLS environment variable must refer to the Visual Studio
-# 2015 common tools directory.
-#
-# USAGE
-#
-# The first argument to this script is optional. If specified, it must be the
-# name of the VSIX file to test.
-#
-package require Tcl 8.4
-
-proc fail { {error ""} {usage false} } {
- if {[string length $error] > 0} then {
- puts stdout $error
- if {!$usage} then {exit 1}
- }
-
- puts stdout "usage:\
-[file tail [info nameofexecutable]]\
-[file tail [info script]] \[vsixFile\]"
-
- exit 1
-}
-
-proc isWindows {} {
- #
- # NOTE: Returns non-zero only when running on Windows.
- #
- return [expr {[info exists ::tcl_platform(platform)] && \
- $::tcl_platform(platform) eq "windows"}]
-}
-
-proc isAdministrator {} {
- #
- # NOTE: Returns non-zero only when running as "elevated administrator".
- #
- if {[isWindows]} then {
- if {[catch {exec -- whoami /groups} groups] == 0} then {
- set groups [string map [list \r\n \n] $groups]
-
- foreach group [split $groups \n] {
- #
- # NOTE: Match this group line against the "well-known" SID for
- # the "Administrators" group on Windows.
- #
- if {[regexp -- {\sS-1-5-32-544\s} $group]} then {
- #
- # NOTE: Match this group line against the attributes column
- # sub-value that should be present when running with
- # elevated administrator credentials.
- #
- if {[regexp -- {\sEnabled group(?:,|\s)} $group]} then {
- return true
- }
- }
- }
- }
- }
-
- return false
-}
-
-proc getEnvironmentVariable { name } {
- #
- # NOTE: Returns the value of the specified environment variable or an empty
- # string for environment variables that do not exist in the current
- # process environment.
- #
- return [expr {[info exists ::env($name)] ? $::env($name) : ""}]
-}
-
-proc getTemporaryPath {} {
- #
- # NOTE: Returns the normalized path to the first temporary directory found
- # in the typical set of environment variables used for that purpose
- # or an empty string to signal a failure to locate such a directory.
- #
- set names [list]
-
- foreach name [list TEMP TMP] {
- lappend names [string toupper $name] [string tolower $name] \
- [string totitle $name]
- }
-
- foreach name $names {
- set value [getEnvironmentVariable $name]
-
- if {[string length $value] > 0} then {
- return [file normalize $value]
- }
- }
-
- return ""
-}
-
-proc appendArgs { args } {
- #
- # NOTE: Returns all passed arguments joined together as a single string
- # with no intervening spaces between arguments.
- #
- eval append result $args
-}
-
-proc readFile { fileName } {
- #
- # NOTE: Reads and returns the entire contents of the specified file, which
- # may contain binary data.
- #
- set file_id [open $fileName RDONLY]
- fconfigure $file_id -encoding binary -translation binary
- set result [read $file_id]
- close $file_id
- return $result
-}
-
-proc writeFile { fileName data } {
- #
- # NOTE: Writes the entire contents of the specified file, which may contain
- # binary data.
- #
- set file_id [open $fileName {WRONLY CREAT TRUNC}]
- fconfigure $file_id -encoding binary -translation binary
- puts -nonewline $file_id $data
- close $file_id
- return ""
-}
-
-proc putsAndEval { command } {
- #
- # NOTE: Outputs a command to the standard output channel and then evaluates
- # it in the callers context.
- #
- catch {
- puts stdout [appendArgs "Running: " [lrange $command 1 end] ...\n]
- }
-
- return [uplevel 1 $command]
-}
-
-proc isBadDirectory { directory } {
- #
- # NOTE: Returns non-zero if the directory is empty, does not exist, -OR- is
- # not a directory.
- #
- catch {
- puts stdout [appendArgs "Checking directory \"" $directory \"...\n]
- }
-
- return [expr {[string length $directory] == 0 || \
- ![file exists $directory] || ![file isdirectory $directory]}]
-}
-
-proc isBadFile { fileName } {
- #
- # NOTE: Returns non-zero if the file name is empty, does not exist, -OR- is
- # not a regular file.
- #
- catch {
- puts stdout [appendArgs "Checking file \"" $fileName \"...\n]
- }
-
- return [expr {[string length $fileName] == 0 || \
- ![file exists $fileName] || ![file isfile $fileName]}]
-}
-
-#
-# NOTE: This is the entry point for this script.
-#
-set script [file normalize [info script]]
-
-if {[string length $script] == 0} then {
- fail "script file currently being evaluated is unknown" true
-}
-
-if {![isWindows]} then {
- fail "this tool only works properly on Windows"
-}
-
-if {![isAdministrator]} then {
- fail "this tool must run with \"elevated administrator\" privileges"
-}
-
-set path [file normalize [file dirname $script]]
-set argc [llength $argv]; if {$argc > 1} then {fail "" true}
-
-if {$argc == 1} then {
- set vsixFileName [lindex $argv 0]
-} else {
- set vsixFileName [file join \
- [file dirname $path] sqlite-UWP-output.vsix]
-}
-
-###############################################################################
-
-if {[isBadFile $vsixFileName]} then {
- fail [appendArgs \
- "VSIX file \"" $vsixFileName "\" does not exist"]
-}
-
-set versionFileName [file join [file dirname $path] VERSION]
-
-if {[isBadFile $versionFileName]} then {
- fail [appendArgs \
- "Version file \"" $versionFileName "\" does not exist"]
-}
-
-set projectTemplateFileName [file join $path vsixtest.vcxproj.data]
-
-if {[isBadFile $projectTemplateFileName]} then {
- fail [appendArgs \
- "Project template file \"" $projectTemplateFileName \
- "\" does not exist"]
-}
-
-set envVarName VS140COMNTOOLS
-set vsDirectory [getEnvironmentVariable $envVarName]
-
-if {[isBadDirectory $vsDirectory]} then {
- fail [appendArgs \
- "Visual Studio 2015 directory \"" $vsDirectory \
- "\" from environment variable \"" $envVarName \
- "\" does not exist"]
-}
-
-set vsixInstaller [file join \
- [file dirname $vsDirectory] IDE VSIXInstaller.exe]
-
-if {[isBadFile $vsixInstaller]} then {
- fail [appendArgs \
- "Visual Studio 2015 VSIX installer \"" $vsixInstaller \
- "\" does not exist"]
-}
-
-set envVarName ProgramFiles
-set programFiles [getEnvironmentVariable $envVarName]
-
-if {[isBadDirectory $programFiles]} then {
- fail [appendArgs \
- "Program Files directory \"" $programFiles \
- "\" from environment variable \"" $envVarName \
- "\" does not exist"]
-}
-
-set msBuild [file join $programFiles MSBuild 14.0 Bin MSBuild.exe]
-
-if {[isBadFile $msBuild]} then {
- fail [appendArgs \
- "MSBuild v14.0 executable file \"" $msBuild \
- "\" does not exist"]
-}
-
-set temporaryDirectory [getTemporaryPath]
-
-if {[isBadDirectory $temporaryDirectory]} then {
- fail [appendArgs \
- "Temporary directory \"" $temporaryDirectory \
- "\" does not exist"]
-}
-
-###############################################################################
-
-set installLogFileName [appendArgs \
- [file rootname [file tail $vsixFileName]] \
- -install- [pid] .log]
-
-set commands(1) [list exec [file nativename $vsixInstaller]]
-
-lappend commands(1) /quiet /norepair
-lappend commands(1) [appendArgs /logFile: $installLogFileName]
-lappend commands(1) [file nativename $vsixFileName]
-
-###############################################################################
-
-set buildLogFileName [appendArgs \
- [file rootname [file tail $vsixFileName]] \
- -build-%configuration%-%platform%- [pid] .log]
-
-set commands(2) [list exec [file nativename $msBuild]]
-
-lappend commands(2) [file nativename [file join $path vsixtest.sln]]
-lappend commands(2) /target:Rebuild
-lappend commands(2) /property:Configuration=%configuration%
-lappend commands(2) /property:Platform=%platform%
-
-lappend commands(2) [appendArgs \
- /logger:FileLogger,Microsoft.Build.Engine\;Logfile= \
- [file nativename [file join $temporaryDirectory \
- $buildLogFileName]] \;Verbosity=diagnostic]
-
-###############################################################################
-
-set uninstallLogFileName [appendArgs \
- [file rootname [file tail $vsixFileName]] \
- -uninstall- [pid] .log]
-
-set commands(3) [list exec [file nativename $vsixInstaller]]
-
-lappend commands(3) /quiet /norepair
-lappend commands(3) [appendArgs /logFile: $uninstallLogFileName]
-lappend commands(3) [appendArgs /uninstall:SQLite.UWP.2015]
-
-###############################################################################
-
-if {1} then {
- catch {
- puts stdout [appendArgs \
- "Install log: \"" [file nativename [file join \
- $temporaryDirectory $installLogFileName]] \"\n]
- }
-
- catch {
- puts stdout [appendArgs \
- "Build logs: \"" [file nativename [file join \
- $temporaryDirectory $buildLogFileName]] \"\n]
- }
-
- catch {
- puts stdout [appendArgs \
- "Uninstall log: \"" [file nativename [file join \
- $temporaryDirectory $uninstallLogFileName]] \"\n]
- }
-}
-
-###############################################################################
-
-if {1} then {
- putsAndEval $commands(1)
-
- set versionNumber [string trim [readFile $versionFileName]]
- set data [readFile $projectTemplateFileName]
- set data [string map [list %versionNumber% $versionNumber] $data]
-
- set projectFileName [file join $path vsixtest.vcxproj]
- writeFile $projectFileName $data
-
- set platforms [list x86 x64 ARM]
- set configurations [list Debug Release]
-
- foreach platform $platforms {
- foreach configuration $configurations {
- putsAndEval [string map [list \
- %platform% $platform %configuration% $configuration] \
- $commands(2)]
- }
- }
-
- putsAndEval $commands(3)
-}
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.vcxproj.data b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.vcxproj.data
deleted file mode 100644
index a64584c3a2f..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.vcxproj.data
+++ /dev/null
@@ -1,198 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup Label="Globals">
- <ProjectGuid>{60bb14a5-0871-4656-bc38-4f0958230f9a}</ProjectGuid>
- <RootNamespace>vsixtest</RootNamespace>
- <DefaultLanguage>en-US</DefaultLanguage>
- <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
- <AppContainerApplication>true</AppContainerApplication>
- <ApplicationType>Windows Store</ApplicationType>
- <WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
- <WindowsTargetPlatformMinVersion>10.0.10586.0</WindowsTargetPlatformMinVersion>
- <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|ARM">
- <Configuration>Debug</Configuration>
- <Platform>ARM</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|ARM">
- <Configuration>Release</Configuration>
- <Platform>ARM</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v140</PlatformToolset>
- <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v140</PlatformToolset>
- <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v140</PlatformToolset>
- <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props" Condition="exists('$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props')" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props" Condition="exists('$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props')" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props" Condition="exists('$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props')" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props" Condition="exists('$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props')" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props" Condition="exists('$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props')" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props" Condition="exists('$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformExtensionSDKLocation(`SQLite.UWP.2015, Version=%versionNumber%`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), $(SDKReferenceDirectoryRoot), $(SDKExtensionDirectoryRoot), $(SDKReferenceRegistryRoot)))\DesignTime\CommonConfiguration\Neutral\SQLite.UWP.2015.props')" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <PackageCertificateKeyFile>vsixtest_TemporaryKey.pfx</PackageCertificateKeyFile>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
- <ClCompile>
- <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
- <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
- <ClCompile>
- <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
- <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
- <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
- <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
- <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
- <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClInclude Include="pch.h" />
- <ClInclude Include="App.xaml.h">
- <DependentUpon>App.xaml</DependentUpon>
- </ClInclude>
- <ClInclude Include="MainPage.xaml.h">
- <DependentUpon>MainPage.xaml</DependentUpon>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ApplicationDefinition Include="App.xaml">
- <SubType>Designer</SubType>
- </ApplicationDefinition>
- <Page Include="MainPage.xaml">
- <SubType>Designer</SubType>
- </Page>
- </ItemGroup>
- <ItemGroup>
- <AppxManifest Include="Package.appxmanifest">
- <SubType>Designer</SubType>
- </AppxManifest>
- <None Include="vsixtest_TemporaryKey.pfx" />
- </ItemGroup>
- <ItemGroup>
- <Image Include="Assets\LockScreenLogo.scale-200.png" />
- <Image Include="Assets\SplashScreen.scale-200.png" />
- <Image Include="Assets\Square150x150Logo.scale-200.png" />
- <Image Include="Assets\Square44x44Logo.scale-200.png" />
- <Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
- <Image Include="Assets\StoreLogo.png" />
- <Image Include="Assets\Wide310x150Logo.scale-200.png" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="App.xaml.cpp">
- <DependentUpon>App.xaml</DependentUpon>
- </ClCompile>
- <ClCompile Include="MainPage.xaml.cpp">
- <DependentUpon>MainPage.xaml</DependentUpon>
- </ClCompile>
- <ClCompile Include="pch.cpp">
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <SDKReference Include="SQLite.UWP.2015, Version=%versionNumber%" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.vcxproj.filters b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.vcxproj.filters
deleted file mode 100644
index ac1dfca4214..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest.vcxproj.filters
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Common">
- <UniqueIdentifier>60bb14a5-0871-4656-bc38-4f0958230f9a</UniqueIdentifier>
- </Filter>
- <Filter Include="Assets">
- <UniqueIdentifier>e6271362-8f96-476d-907f-4da227b02435</UniqueIdentifier>
- <Extensions>bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ApplicationDefinition Include="App.xaml" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="App.xaml.cpp" />
- <ClCompile Include="MainPage.xaml.cpp" />
- <ClCompile Include="pch.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="pch.h" />
- <ClInclude Include="App.xaml.h" />
- <ClInclude Include="MainPage.xaml.h" />
- </ItemGroup>
- <ItemGroup>
- <Image Include="Assets\LockScreenLogo.scale-200.png">
- <Filter>Assets</Filter>
- </Image>
- <Image Include="Assets\SplashScreen.scale-200.png">
- <Filter>Assets</Filter>
- </Image>
- <Image Include="Assets\Square150x150Logo.scale-200.png">
- <Filter>Assets</Filter>
- </Image>
- <Image Include="Assets\Square44x44Logo.scale-200.png">
- <Filter>Assets</Filter>
- </Image>
- <Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png">
- <Filter>Assets</Filter>
- </Image>
- <Image Include="Assets\StoreLogo.png">
- <Filter>Assets</Filter>
- </Image>
- <Image Include="Assets\Wide310x150Logo.scale-200.png">
- <Filter>Assets</Filter>
- </Image>
- </ItemGroup>
- <ItemGroup>
- <AppxManifest Include="Package.appxmanifest" />
- </ItemGroup>
- <ItemGroup>
- <None Include="vsixtest_TemporaryKey.pfx" />
- </ItemGroup>
- <ItemGroup>
- <Page Include="MainPage.xaml" />
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest_TemporaryKey.pfx b/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest_TemporaryKey.pfx
deleted file mode 100644
index e6787bcad05..00000000000
--- a/chromium/third_party/sqlite/sqlite-src-3240000/vsixtest/vsixtest_TemporaryKey.pfx
+++ /dev/null
Binary files differ